Merge Chromium.org at r11.0.672.0: Initial merge by git.

Change-Id: I8b4aaf611a2a405fe3fe10e8a94ea7658645c192
diff --git a/app/sql/connection.cc b/app/sql/connection.cc
index 32590d3..a9b13b6 100644
--- a/app/sql/connection.cc
+++ b/app/sql/connection.cc
@@ -143,7 +143,11 @@
   if (!dummy || !dummy.Step())
     return;
 
+#if !defined(USE_SYSTEM_SQLITE)
+  // This function is only defined in Chromium's version of sqlite.
+  // Do not call it when using system sqlite.
   sqlite3Preload(db_);
+#endif
 }
 
 bool Connection::BeginTransaction() {
diff --git a/app/sql/meta_table.cc b/app/sql/meta_table.cc
index 9ec0998..2700d67 100644
--- a/app/sql/meta_table.cc
+++ b/app/sql/meta_table.cc
@@ -15,18 +15,18 @@
 static const char kVersionKey[] = "version";
 static const char kCompatibleVersionKey[] = "last_compatible_version";
 
-// static
-bool MetaTable::DoesTableExist(sql::Connection* db) {
-  DCHECK(db);
-  return db->DoesTableExist("meta");
-}
-
 MetaTable::MetaTable() : db_(NULL) {
 }
 
 MetaTable::~MetaTable() {
 }
 
+// static
+bool MetaTable::DoesTableExist(sql::Connection* db) {
+  DCHECK(db);
+  return db->DoesTableExist("meta");
+}
+
 bool MetaTable::Init(Connection* db, int version, int compatible_version) {
   DCHECK(!db_ && db);
   db_ = db;
diff --git a/app/sql/meta_table.h b/app/sql/meta_table.h
index 4b06337..d5c76c8 100644
--- a/app/sql/meta_table.h
+++ b/app/sql/meta_table.h
@@ -17,12 +17,12 @@
 
 class MetaTable {
  public:
-  // Returns true if the 'meta' table exists.
-  static bool DoesTableExist(Connection* db);
-
   MetaTable();
   ~MetaTable();
 
+  // Returns true if the 'meta' table exists.
+  static bool DoesTableExist(Connection* db);
+
   // Initializes the MetaTableHelper, creating the meta table if necessary. For
   // new tables, it will initialize the version number to |version| and the
   // compatible version number to |compatible_version|.
diff --git a/base/allocator/allocator.gyp b/base/allocator/allocator.gyp
index 64b1159..87b4127 100644
--- a/base/allocator/allocator.gyp
+++ b/base/allocator/allocator.gyp
@@ -248,7 +248,7 @@
       ],
       'msvs_settings': {
         # TODO(sgk):  merge this with build/common.gypi settings
-        'VCLibrarianTool=': {
+        'VCLibrarianTool': {
           'AdditionalOptions': ['/ignore:4006,4221'],
           'AdditionalLibraryDirectories':
             ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
diff --git a/base/allocator/allocator_unittests.cc b/base/allocator/allocator_unittests.cc
index b1aa9cb..d935cf9 100644
--- a/base/allocator/allocator_unittests.cc
+++ b/base/allocator/allocator_unittests.cc
@@ -313,9 +313,9 @@
   try {
     void* rv = (*func)(kTooBig);
     EXPECT_EQ(NULL, rv);
-    EXPECT_EQ(false, should_throw) << "allocation should have thrown.";
+    EXPECT_FALSE(should_throw) << "allocation should have thrown.";
   } catch(...) {
-    EXPECT_EQ(true, should_throw) << "allocation threw unexpected exception.";
+    EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
   }
 }
 
@@ -359,7 +359,7 @@
     unsigned char* ptr = reinterpret_cast<unsigned char*>(malloc(size));
     CheckAlignment(ptr, 2);  // Should be 2 byte aligned
     Fill(ptr, size);
-    EXPECT_EQ(true, Valid(ptr, size));
+    EXPECT_TRUE(Valid(ptr, size));
     free(ptr);
   }
 }
@@ -420,9 +420,9 @@
       Fill(src, src_size);
       unsigned char* dst =
           reinterpret_cast<unsigned char*>(realloc(src, dst_size));
-      EXPECT_EQ(true, Valid(dst, min(src_size, dst_size)));
+      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
       Fill(dst, dst_size);
-      EXPECT_EQ(true, Valid(dst, dst_size));
+      EXPECT_TRUE(Valid(dst, dst_size));
       if (dst != NULL) free(dst);
     }
   }
@@ -468,13 +468,13 @@
     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_EQ(true, IsZeroed(src, 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_EQ(true, Valid(dst, min(src_size, dst_size)));
+      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
       Fill(dst, dst_size);
-      EXPECT_EQ(true, Valid(dst, dst_size));
+      EXPECT_TRUE(Valid(dst, dst_size));
       if (dst != NULL)
         free(dst);
     }
diff --git a/base/at_exit.cc b/base/at_exit.cc
index 9fdfd77..e6618a0 100644
--- a/base/at_exit.cc
+++ b/base/at_exit.cc
@@ -18,11 +18,6 @@
   g_top_manager = this;
 }
 
-AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
-  DCHECK(shadow || !g_top_manager);
-  g_top_manager = this;
-}
-
 AtExitManager::~AtExitManager() {
   if (!g_top_manager) {
     NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager";
@@ -64,4 +59,9 @@
   }
 }
 
+AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
+  DCHECK(shadow || !g_top_manager);
+  g_top_manager = this;
+}
+
 }  // namespace base
diff --git a/base/at_exit.h b/base/at_exit.h
index 35c96b9..15dcfc8 100644
--- a/base/at_exit.h
+++ b/base/at_exit.h
@@ -9,7 +9,7 @@
 #include <stack>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 
@@ -60,7 +60,7 @@
     void* param_;
   };
 
-  Lock lock_;
+  base::Lock lock_;
   std::stack<CallbackAndParam> stack_;
   AtExitManager* next_manager_;  // Stack of managers to allow shadowing.
 
diff --git a/base/atomicops_internals_x86_macosx.h b/base/atomicops_internals_x86_macosx.h
index 5de7df3..29e58e3 100644
--- a/base/atomicops_internals_x86_macosx.h
+++ b/base/atomicops_internals_x86_macosx.h
@@ -110,7 +110,7 @@
   Atomic64 prev_value;
   do {
     if (OSAtomicCompareAndSwap64(old_value, new_value,
-                                 const_cast<Atomic64*>(ptr))) {
+                                 reinterpret_cast<volatile int64_t*>(ptr))) {
       return old_value;
     }
     prev_value = *ptr;
@@ -124,18 +124,19 @@
   do {
     old_value = *ptr;
   } while (!OSAtomicCompareAndSwap64(old_value, new_value,
-                                     const_cast<Atomic64*>(ptr)));
+                                     reinterpret_cast<volatile int64_t*>(ptr)));
   return old_value;
 }
 
 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
                                           Atomic64 increment) {
-  return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
+  return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
 }
 
 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
                                         Atomic64 increment) {
-  return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
+  return OSAtomicAdd64Barrier(increment,
+                              reinterpret_cast<volatile int64_t*>(ptr));
 }
 
 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
@@ -143,8 +144,8 @@
                                        Atomic64 new_value) {
   Atomic64 prev_value;
   do {
-    if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
-                                        const_cast<Atomic64*>(ptr))) {
+    if (OSAtomicCompareAndSwap64Barrier(
+        old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
       return old_value;
     }
     prev_value = *ptr;
@@ -193,12 +194,11 @@
 
 // MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different
 // on the Mac, even when they are the same size.  We need to explicitly cast
-// from AtomicWord to Atomic32/64 to implement the AtomicWord interface.
-#ifdef __LP64__
-#define AtomicWordCastType Atomic64
-#else
+// from AtomicWord to Atomic32 to implement the AtomicWord interface.
+// When in 64-bit mode, AtomicWord is the same as Atomic64, so we need not
+// add duplicate definitions.
+#ifndef __LP64__
 #define AtomicWordCastType Atomic32
-#endif
 
 inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
                                            AtomicWord old_value,
@@ -273,6 +273,7 @@
 }
 
 #undef AtomicWordCastType
+#endif
 
 }   // namespace base::subtle
 }   // namespace base
diff --git a/base/base.gyp b/base/base.gyp
index 6dc450c..868569e 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -31,6 +31,8 @@
         'base',
       ],
       'sources': [
+	'i18n/bidi_line_iterator.cc',
+	'i18n/bidi_line_iterator.h',
         'i18n/break_iterator.cc',
         'i18n/break_iterator.h',
         'i18n/char_iterator.cc',
@@ -63,12 +65,14 @@
         'at_exit_unittest.cc',
         'atomicops_unittest.cc',
         'base64_unittest.cc',
+        'bind_unittest.cc',
         'bits_unittest.cc',
         'callback_unittest.cc',
         'command_line_unittest.cc',
         'crypto/encryptor_unittest.cc',
         'crypto/rsa_private_key_unittest.cc',
         'crypto/rsa_private_key_nss_unittest.cc',
+        'crypto/secure_hash_unittest.cc',
         'crypto/signature_creator_unittest.cc',
         'crypto/signature_verifier_unittest.cc',
         'crypto/symmetric_key_unittest.cc',
@@ -139,6 +143,7 @@
         'sys_string_conversions_unittest.cc',
         'task_queue_unittest.cc',
         'task_unittest.cc',
+        'template_util_unittest.cc',
         'threading/non_thread_safe_unittest.cc',
         'threading/platform_thread_unittest.cc',
         'threading/simple_thread_unittest.cc',
diff --git a/base/base.gypi b/base/base.gypi
index f241967..7a5da2e 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -36,9 +36,14 @@
           'base_switches.cc',
           'base_switches.h',
           'basictypes.h',
+          'bind.h',
+          'bind_helpers.h',
+          'bind_internal.h',
           'bits.h',
           'bzip2_error_handler.cc',
           'callback.h',
+          'callback_helpers.h',
+          'callback_old.h',
           'command_line.cc',
           'command_line.h',
           'compiler_specific.h',
@@ -52,6 +57,8 @@
           'debug/debugger_win.cc',
           '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_posix.cc',
@@ -98,11 +105,12 @@
           'lazy_instance.h',
           'linked_list.h',
           'linked_ptr.h',
-          'lock.h',
           'logging.cc',
           'logging.h',
           'logging_win.cc',
           'mac/cocoa_protocols.h',
+	  'mac/foundation_util.h',
+	  'mac/foundation_util.mm',
           'mac/mac_util.h',
           'mac/mac_util.mm',
           'mac/os_crash_dumps.cc',
@@ -287,8 +295,6 @@
           'utf_string_conversions.h',
           'values.cc',
           'values.h',
-          'values_util.cc',
-          'values_util.h',
           'version.cc',
           'version.h',
           'vlog.cc',
@@ -526,6 +532,7 @@
             'sources!': [
               'crypto/encryptor_nss.cc',
               'crypto/rsa_private_key_nss.cc',
+              'crypto/secure_hash_default.cc',
               'crypto/signature_creator_nss.cc',
               'crypto/signature_verifier_nss.cc',
               'crypto/symmetric_key_nss.cc',
@@ -545,6 +552,7 @@
             'sources!': [
               'crypto/encryptor_openssl.cc',
               'crypto/rsa_private_key_openssl.cc',
+              'crypto/secure_hash_openssl.cc',
               'crypto/signature_creator_openssl.cc',
               'crypto/signature_verifier_openssl.cc',
               'crypto/symmetric_key_openssl.cc',
@@ -558,6 +566,7 @@
       'sources': [
         'crypto/capi_util.cc',
         'crypto/capi_util.h',
+        'crypto/crypto_module_blocking_password_delegate.h',
         'crypto/cssm_init.cc',
         'crypto/cssm_init.h',
         'crypto/encryptor.h',
@@ -571,6 +580,9 @@
         'crypto/rsa_private_key_nss.cc',
         'crypto/rsa_private_key_openssl.cc',
         'crypto/rsa_private_key_win.cc',
+        'crypto/secure_hash.h',
+        'crypto/secure_hash_default.cc',
+        'crypto/secure_hash_openssl.cc',
         'crypto/signature_creator.h',
         'crypto/signature_creator_mac.cc',
         'crypto/signature_creator_nss.cc',
diff --git a/base/base_paths_linux.cc b/base/base_paths_linux.cc
index 48db3f8..ca8c757 100644
--- a/base/base_paths_linux.cc
+++ b/base/base_paths_linux.cc
@@ -83,10 +83,10 @@
         }
       }
       // In a case of WebKit-only checkout, executable files are put into
-      // WebKit/out/{Debug|Release}, and we should return WebKit/WebKit/chromium
-      // for DIR_SOURCE_ROOT.
+      // <root of checkout>/out/{Debug|Release}, and we should return
+      // <root of checkout>/Source/WebKit/chromium for DIR_SOURCE_ROOT.
       if (PathService::Get(base::DIR_EXE, &path)) {
-        path = path.DirName().DirName().Append("WebKit/chromium");
+        path = path.DirName().DirName().Append("Source/WebKit/chromium");
         if (file_util::PathExists(path.Append(kThisSourceFile))) {
           *result = path;
           return true;
diff --git a/base/base_switches.cc b/base/base_switches.cc
index a1d688a..78f55a7 100644
--- a/base/base_switches.cc
+++ b/base/base_switches.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -24,8 +24,8 @@
 // Suppresses all error dialogs when present.
 const char kNoErrorDialogs[]                = "noerrdialogs";
 
-// Disable app::win::MessageBox.  This is useful when running as part of
-// scripts that do not have a user interface.
+// Disable ui::MessageBox.  This is useful when running as part of scripts that
+// do not have a user interface.
 const char kNoMessageBox[]                  = "no-message-box";
 
 // When running certain tests that spawn child processes, this switch indicates
diff --git a/base/bind.h b/base/bind.h
new file mode 100644
index 0000000..c23af2e
--- /dev/null
+++ b/base/bind.h
@@ -0,0 +1,99 @@
+// This file was GENERATED by command:
+//     pump.py bind.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BIND_H_
+#define BASE_BIND_H_
+#pragma once
+
+#include "base/bind_internal.h"
+#include "base/callback_helpers.h"
+
+// See base/callback.h for how to use these functions.
+//
+// IMPLEMENTATION NOTE
+// Though Bind()'s result is meant to be stored in a Callback<> type, it
+// cannot actually return the exact type without requiring a large amount
+// of extra template specializations. The problem is that in order to
+// discern the correct specialization of Callback<>, Bind would need to
+// unwrap the function signature to determine the signature's arity, and
+// whether or not it is a method.
+//
+// Each unique combination of (arity, function_type, num_prebound) where
+// function_type is one of {function, method, const_method} would require
+// one specialization.  We eventually have to do a similar number of
+// specializations anyways in the implementation (see the FunctionTraitsN,
+// classes).  However, it is avoidable in Bind if we return the result
+// via an indirection like we do below.
+
+namespace base {
+
+template <typename Sig>
+internal::InvokerStorageHolder<internal::InvokerStorage0<Sig> >
+Bind(Sig f) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage0<Sig>(f));
+}
+
+template <typename Sig, typename P1>
+internal::InvokerStorageHolder<internal::InvokerStorage1<Sig,P1> >
+Bind(Sig f, const P1& p1) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage1<Sig, P1>(
+          f, p1));
+}
+
+template <typename Sig, typename P1, typename P2>
+internal::InvokerStorageHolder<internal::InvokerStorage2<Sig,P1, P2> >
+Bind(Sig f, const P1& p1, const P2& p2) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage2<Sig, P1, P2>(
+          f, p1, p2));
+}
+
+template <typename Sig, typename P1, typename P2, typename P3>
+internal::InvokerStorageHolder<internal::InvokerStorage3<Sig,P1, P2, P3> >
+Bind(Sig f, const P1& p1, const P2& p2, const P3& p3) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage3<Sig, P1, P2, P3>(
+          f, p1, p2, p3));
+}
+
+template <typename Sig, typename P1, typename P2, typename P3, typename P4>
+internal::InvokerStorageHolder<internal::InvokerStorage4<Sig,P1, P2, P3, P4> >
+Bind(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage4<Sig, P1, P2, P3, P4>(
+          f, p1, p2, p3, p4));
+}
+
+template <typename Sig, typename P1, typename P2, typename P3, typename P4,
+    typename P5>
+internal::InvokerStorageHolder<internal::InvokerStorage5<Sig,P1, P2, P3, P4,
+    P5> >
+Bind(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
+    const P5& p5) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage5<Sig, P1, P2, P3, P4, P5>(
+          f, p1, p2, p3, p4, p5));
+}
+
+template <typename Sig, typename P1, typename P2, typename P3, typename P4,
+    typename P5, typename P6>
+internal::InvokerStorageHolder<internal::InvokerStorage6<Sig,P1, P2, P3, P4,
+    P5, P6> >
+Bind(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
+    const P5& p5, const P6& p6) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage6<Sig, P1, P2, P3, P4, P5, P6>(
+          f, p1, p2, p3, p4, p5, p6));
+}
+
+}  // namespace base
+
+#endif  // BASE_BIND_H_
diff --git a/base/bind.h.pump b/base/bind.h.pump
new file mode 100644
index 0000000..fc7f246
--- /dev/null
+++ b/base/bind.h.pump
@@ -0,0 +1,71 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$var MAX_ARITY = 6
+
+// Copyright (c) 2011 The Chromium 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_BIND_H_
+#define BASE_BIND_H_
+#pragma once
+
+#include "base/bind_internal.h"
+#include "base/callback_helpers.h"
+
+// See base/callback.h for how to use these functions.
+//
+// IMPLEMENTATION NOTE
+// Though Bind()'s result is meant to be stored in a Callback<> type, it
+// cannot actually return the exact type without requiring a large amount
+// of extra template specializations. The problem is that in order to
+// discern the correct specialization of Callback<>, Bind would need to
+// unwrap the function signature to determine the signature's arity, and
+// whether or not it is a method.
+//
+// Each unique combination of (arity, function_type, num_prebound) where
+// function_type is one of {function, method, const_method} would require
+// one specialization.  We eventually have to do a similar number of
+// specializations anyways in the implementation (see the FunctionTraitsN,
+// classes).  However, it is avoidable in Bind if we return the result
+// via an indirection like we do below.
+
+namespace base {
+
+$range BOUND 0..MAX_ARITY
+$for BOUND [[
+$range BOUND_ARG 1..BOUND
+
+$if BOUND == 0 [[
+
+template <typename Sig>
+internal::InvokerStorageHolder<internal::InvokerStorage0<Sig> >
+Bind(Sig f) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage0<Sig>(f));
+}
+
+]] $else [[
+
+template <typename Sig, $for BOUND_ARG , [[typename P$(BOUND_ARG)]]>
+internal::InvokerStorageHolder<internal::InvokerStorage$(BOUND)<Sig,
+$for BOUND_ARG , [[P$(BOUND_ARG)]]> >
+Bind(Sig f, $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) {
+  return internal::MakeInvokerStorageHolder(
+      new internal::InvokerStorage$(BOUND)<Sig, [[]]
+$for BOUND_ARG , [[P$(BOUND_ARG)]]>(
+          f, $for BOUND_ARG , [[p$(BOUND_ARG)]]));
+}
+
+]]
+
+]]  $$ for BOUND
+
+}  // namespace base
+
+#endif  // BASE_BIND_H_
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
new file mode 100644
index 0000000..c1ca3d7
--- /dev/null
+++ b/base/bind_helpers.h
@@ -0,0 +1,287 @@
+// Copyright (c) 2011 The Chromium 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 defines a set of argument wrappers and related factory methods that
+// can be used specify the refcounting and reference semantics of arguments
+// that are bound by the Bind() function in base/bind.h.
+//
+// The public functions are base::Unretained() and base::ConstRef().
+// Unretained() allows Bind() to bind a non-refcounted class.
+// ConstRef() allows binding a constant reference to an argument rather
+// than a copy.
+//
+//
+// EXAMPLE OF Unretained():
+//
+//   class Foo {
+//    public:
+//     void func() { cout << "Foo:f" << endl;
+//   };
+//
+//   // In some function somewhere.
+//   Foo foo;
+//   Callback<void(void)> foo_callback =
+//       Bind(&Foo::func, Unretained(&foo));
+//   foo_callback.Run();  // Prints "Foo:f".
+//
+// Without the Unretained() wrapper on |&foo|, the above call would fail
+// to compile because Foo does not support the AddRef() and Release() methods.
+//
+//
+// EXAMPLE OF ConstRef();
+//   void foo(int arg) { cout << arg << endl }
+//
+//   int n = 1;
+//   Callback<void(void)> no_ref = Bind(&foo, n);
+//   Callback<void(void)> has_ref = Bind(&foo, ConstRef(n));
+//
+//   no_ref.Run();  // Prints "1"
+//   has_ref.Run();  // Prints "1"
+//
+//   n = 2;
+//   no_ref.Run();  // Prints "1"
+//   has_ref.Run();  // Prints "2"
+//
+// Note that because ConstRef() takes a reference on |n|, |n| must outlive all
+// its bound callbacks.
+//
+
+#ifndef BASE_BIND_HELPERS_H_
+#define BASE_BIND_HELPERS_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/template_util.h"
+
+namespace base {
+namespace internal {
+
+// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T
+// for the existence of AddRef() and Release() functions of the correct
+// signature.
+//
+// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
+// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence
+// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison
+// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
+//
+// The last link in particular show the method used below.
+//
+// For SFINAE to work with inherited methods, we need to pull some extra tricks
+// with multiple inheritance.  In the more standard formulation, the overloads
+// of Check would be:
+//
+//   template <typename C>
+//   Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*);
+//
+//   template <typename C>
+//   No NotTheCheckWeWant(...);
+//
+//   static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes);
+//
+// The problem here is that template resolution will not match
+// C::TargetFunc if TargetFunc does not exist directly in C.  That is, if
+// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match,
+// |value| will be false.  This formulation only checks for whether or
+// not TargetFunc exist directly in the class being introspected.
+//
+// To get around this, we play a dirty trick with multiple inheritance.
+// First, We create a class BaseMixin that declares each function that we
+// want to probe for.  Then we create a class Base that inherits from both T
+// (the class we wish to probe) and BaseMixin.  Note that the function
+// signature in BaseMixin does not need to match the signature of the function
+// we are probing for; thus it's easiest to just use void(void).
+//
+// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
+// ambiguous resolution between BaseMixin and T.  This lets us write the
+// following:
+//
+//   template <typename C>
+//   No GoodCheck(Helper<&C::TargetFunc>*);
+//
+//   template <typename C>
+//   Yes GoodCheck(...);
+//
+//   static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes);
+//
+// Notice here that the variadic version of GoodCheck() returns Yes here
+// instead of No like the previous one. Also notice that we calculate |value|
+// by specializing GoodCheck() on Base instead of T.
+//
+// We've reversed the roles of the variadic, and Helper overloads.
+// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid
+// substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve
+// to the variadic version if T has TargetFunc.  If T::TargetFunc does not
+// exist, then &C::TargetFunc is not ambiguous, and the overload resolution
+// will prefer GoodCheck(Helper<&C::TargetFunc>*).
+//
+// This method of SFINAE will correctly probe for inherited names, but it cannot
+// typecheck those names.  It's still a good enough sanity check though.
+//
+// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008.
+//
+// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted
+// this works well.
+template <typename T>
+class SupportsAddRefAndRelease {
+  typedef char Yes[1];
+  typedef char No[2];
+
+  struct BaseMixin {
+    void AddRef();
+    void Release();
+  };
+
+  struct Base : public T, public BaseMixin {
+  };
+
+  template <void(BaseMixin::*)(void)>  struct Helper {};
+
+  template <typename C>
+  static No& Check(Helper<&C::AddRef>*, Helper<&C::Release>*);
+
+  template <typename >
+  static Yes& Check(...);
+
+ public:
+  static const bool value = sizeof(Check<Base>(0,0)) == sizeof(Yes);
+};
+
+
+// Helpers to assert that arguments of a recounted type are bound with a
+// scoped_refptr.
+template <bool IsClasstype, typename T>
+struct UnsafeBindtoRefCountedArgHelper : false_type {
+};
+
+template <typename T>
+struct UnsafeBindtoRefCountedArgHelper<true, T>
+    : integral_constant<bool, SupportsAddRefAndRelease<T>::value> {
+};
+
+template <typename T>
+struct UnsafeBindtoRefCountedArg
+    : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
+};
+
+
+template <typename T>
+class UnretainedWrapper {
+ public:
+  explicit UnretainedWrapper(T* o) : obj_(o) {}
+  T* get() { return obj_; }
+ private:
+  T* obj_;
+};
+
+template <typename T>
+class ConstRefWrapper {
+ public:
+  explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
+  const T& get() { return *ptr_; }
+ private:
+  const T* ptr_;
+};
+
+
+// Unwrap the stored parameters for the wrappers above.
+template <typename T>
+T Unwrap(T o) { return o; }
+
+template <typename T>
+T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); }
+
+template <typename T>
+const T& Unwrap(ConstRefWrapper<T> const_ref) {
+  return const_ref.get();
+}
+
+
+// Utility for handling different refcounting semantics in the Bind()
+// function.
+template <typename ref, typename T>
+struct MaybeRefcount;
+
+template <typename T>
+struct MaybeRefcount<base::false_type, T> {
+  static void AddRef(const T&) {}
+  static void Release(const T&) {}
+};
+
+template <typename T, size_t n>
+struct MaybeRefcount<base::false_type, T[n]> {
+  static void AddRef(const T*) {}
+  static void Release(const T*) {}
+};
+
+template <typename T>
+struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > {
+  static void AddRef(const UnretainedWrapper<T>&) {}
+  static void Release(const UnretainedWrapper<T>&) {}
+};
+
+template <typename T>
+struct MaybeRefcount<base::true_type, T*> {
+  static void AddRef(T* o) { o->AddRef(); }
+  static void Release(T* o) { o->Release(); }
+};
+
+template <typename T>
+struct MaybeRefcount<base::true_type, const T*> {
+  static void AddRef(const T* o) { o->AddRef(); }
+  static void Release(const T* o) { o->Release(); }
+};
+
+
+// This is a typetraits object that's used to convert an argument type into a
+// type suitable for storage.  In particular, it strips off references, and
+// converts arrays to pointers.
+//
+// This array type becomes an issue because we are passing bound parameters by
+// const reference. In this case, we end up passing an actual array type in the
+// initializer list which C++ does not allow.  This will break passing of
+// C-string literals.
+template <typename T>
+struct BindType {
+  typedef T StorageType;
+};
+
+// This should almost be impossible to trigger unless someone manually
+// specifies type of the bind parameters.  However, in case they do,
+// this will guard against us accidentally storing a reference parameter.
+template <typename T>
+struct BindType<T&> {
+  typedef T StorageType;
+};
+
+// Note that for array types, we implicitly add a const in the conversion. This
+// means that it is not possible to bind array arguments to functions that take
+// a non-const pointer. Trying to specialize the template based on a "const
+// T[n]" does not seem to match correctly, so we are stuck with this
+// restriction.
+template <typename T, size_t n>
+struct BindType<T[n]> {
+  typedef const T* StorageType;
+};
+
+template <typename T>
+struct BindType<T[]> {
+  typedef const T* StorageType;
+};
+
+}  // namespace internal
+
+template <typename T>
+inline internal::UnretainedWrapper<T> Unretained(T* o) {
+  return internal::UnretainedWrapper<T>(o);
+}
+
+template <typename T>
+inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
+  return internal::ConstRefWrapper<T>(o);
+}
+
+}  // namespace base
+
+#endif  // BASE_BIND_HELPERS_H_
diff --git a/base/bind_internal.h b/base/bind_internal.h
new file mode 100644
index 0000000..62f2050
--- /dev/null
+++ b/base/bind_internal.h
@@ -0,0 +1,1670 @@
+// This file was GENERATED by command:
+//     pump.py bind_internal.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BIND_INTERNAL_H_
+#define BASE_BIND_INTERNAL_H_
+#pragma once
+
+#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
+#include "base/template_util.h"
+
+namespace base {
+namespace internal {
+
+// The method by which a function is invoked is determined by 3 different
+// dimensions:
+//
+//   1) The type of function (normal, method, const-method)
+//   2) The arity of the function
+//   3) The number of bound parameters.
+//
+// The FunctionTraitsN classes unwrap the function signature type to
+// specialize based on the first two dimensions.  The N in FunctionTraitsN
+// specifies the 3rd dimension.  We could have specified the unbound parameters
+// via template parameters, but this method looked cleaner.
+//
+// The FunctionTraitsN contains a static DoInvoke() function that is the key to
+// implementing type erasure in the Callback() classes.  DoInvoke() is a static
+// function with a fixed signature that is independent of StorageType; its
+// first argument is a pointer to the non-templated common baseclass of
+// StorageType. This lets us store pointer to DoInvoke() in a function pointer
+// that has knowledge of the specific StorageType, and thus no knowledge of the
+// bound function and bound parameter types.
+//
+// As long as we ensure that DoInvoke() is only used with pointers there were
+// upcasted from the correct StorageType, we can be sure that execution is
+// safe.
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits0;
+
+// Function: Arity 0 -> 0.
+template <typename StorageType, typename R>
+struct FunctionTraits0<StorageType, R(*)()> {
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_();
+  }
+};
+
+// Function: Arity 1 -> 1.
+template <typename StorageType, typename R,typename X1>
+struct FunctionTraits0<StorageType, R(*)(X1)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(x1);
+  }
+};
+
+// Function: Arity 2 -> 2.
+template <typename StorageType, typename R,typename X1, typename X2>
+struct FunctionTraits0<StorageType, R(*)(X1, X2)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(x1, x2);
+  }
+};
+
+// Function: Arity 3 -> 3.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3>
+struct FunctionTraits0<StorageType, R(*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(x1, x2, x3);
+  }
+};
+
+// Function: Arity 4 -> 4.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4>
+struct FunctionTraits0<StorageType, R(*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(x1, x2, x3, x4);
+  }
+};
+
+// Function: Arity 5 -> 5.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5>
+struct FunctionTraits0<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(x1, x2, x3, x4, x5);
+  }
+};
+
+// Function: Arity 6 -> 6.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4, const X5& x5, const X6& x6) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(x1, x2, x3, x4, x5, x6);
+  }
+};
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits1;
+
+// Function: Arity 1 -> 0.
+template <typename StorageType, typename R,typename X1>
+struct FunctionTraits1<StorageType, R(*)(X1)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_));
+  }
+};
+
+// Method: Arity 0 -> 0.
+template <typename StorageType, typename R, typename T>
+struct FunctionTraits1<StorageType, R(T::*)()> {
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)();
+  }
+};
+
+// Const Method: Arity 0 -> 0.
+template <typename StorageType, typename R, typename T>
+struct FunctionTraits1<StorageType, R(T::*)() const> {
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base ) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)();
+  }
+};
+
+// Function: Arity 2 -> 1.
+template <typename StorageType, typename R,typename X1, typename X2>
+struct FunctionTraits1<StorageType, R(*)(X1, X2)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), x2);
+  }
+};
+
+// Method: Arity 1 -> 1.
+template <typename StorageType, typename R, typename T, typename X1>
+struct FunctionTraits1<StorageType, R(T::*)(X1)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1);
+  }
+};
+
+// Const Method: Arity 1 -> 1.
+template <typename StorageType, typename R, typename T, typename X1>
+struct FunctionTraits1<StorageType, R(T::*)(X1) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X1& x1) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1);
+  }
+};
+
+// Function: Arity 3 -> 2.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3>
+struct FunctionTraits1<StorageType, R(*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), x2, x3);
+  }
+};
+
+// Method: Arity 2 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2);
+  }
+};
+
+// Const Method: Arity 2 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X1& x1, const X2& x2) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2);
+  }
+};
+
+// Function: Arity 4 -> 3.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4>
+struct FunctionTraits1<StorageType, R(*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3,
+      const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4);
+  }
+};
+
+// Method: Arity 3 -> 3.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3);
+  }
+};
+
+// Const Method: Arity 3 -> 3.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2, X3) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X1& x1, const X2& x2,
+      const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3);
+  }
+};
+
+// Function: Arity 5 -> 4.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5>
+struct FunctionTraits1<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3,
+      const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5);
+  }
+};
+
+// Method: Arity 4 -> 4.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4);
+  }
+};
+
+// Const Method: Arity 4 -> 4.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2, X3, X4) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4);
+  }
+};
+
+// Function: Arity 6 -> 5.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3,
+      const X4& x4, const X5& x5, const X6& x6) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5, x6);
+  }
+};
+
+// Method: Arity 5 -> 5.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4, x5);
+  }
+};
+
+// Const Method: Arity 5 -> 5.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits1<StorageType, R(T::*)(X1, X2, X3, X4, X5) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X1& x1, const X2& x2,
+      const X3& x3, const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4, x5);
+  }
+};
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits2;
+
+// Function: Arity 2 -> 0.
+template <typename StorageType, typename R,typename X1, typename X2>
+struct FunctionTraits2<StorageType, R(*)(X1, X2)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_));
+  }
+};
+
+// Method: Arity 1 -> 0.
+template <typename StorageType, typename R, typename T, typename X1>
+struct FunctionTraits2<StorageType, R(T::*)(X1)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_));
+  }
+};
+
+// Const Method: Arity 1 -> 0.
+template <typename StorageType, typename R, typename T, typename X1>
+struct FunctionTraits2<StorageType, R(T::*)(X1) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base ) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_));
+  }
+};
+
+// Function: Arity 3 -> 1.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3>
+struct FunctionTraits2<StorageType, R(*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3);
+  }
+};
+
+// Method: Arity 2 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2);
+  }
+};
+
+// Const Method: Arity 2 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X2& x2) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2);
+  }
+};
+
+// Function: Arity 4 -> 2.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4>
+struct FunctionTraits2<StorageType, R(*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4);
+  }
+};
+
+// Method: Arity 3 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3);
+  }
+};
+
+// Const Method: Arity 3 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2, X3) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X2& x2, const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3);
+  }
+};
+
+// Function: Arity 5 -> 3.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5>
+struct FunctionTraits2<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4,
+      const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5);
+  }
+};
+
+// Method: Arity 4 -> 3.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3,
+      const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3,
+        x4);
+  }
+};
+
+// Const Method: Arity 4 -> 3.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2, X3, X4) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X2& x2, const X3& x3,
+      const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3,
+        x4);
+  }
+};
+
+// Function: Arity 6 -> 4.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4,
+      const X5& x5, const X6& x6) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5,
+        x6);
+  }
+};
+
+// Method: Arity 5 -> 4.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X2& x2, const X3& x3,
+      const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3,
+        x4, x5);
+  }
+};
+
+// Const Method: Arity 5 -> 4.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits2<StorageType, R(T::*)(X1, X2, X3, X4, X5) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X2& x2, const X3& x3,
+      const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3,
+        x4, x5);
+  }
+};
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits3;
+
+// Function: Arity 3 -> 0.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3>
+struct FunctionTraits3<StorageType, R(*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_));
+  }
+};
+
+// Method: Arity 2 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_));
+  }
+};
+
+// Const Method: Arity 2 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base ) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_));
+  }
+};
+
+// Function: Arity 4 -> 1.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4>
+struct FunctionTraits3<StorageType, R(*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x4);
+  }
+};
+
+// Method: Arity 3 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x3);
+  }
+};
+
+// Const Method: Arity 3 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2, X3) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X3& x3) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x3);
+  }
+};
+
+// Function: Arity 5 -> 2.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5>
+struct FunctionTraits3<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x4, x5);
+  }
+};
+
+// Method: Arity 4 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x3, x4);
+  }
+};
+
+// Const Method: Arity 4 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2, X3, X4) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X3& x3, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x3, x4);
+  }
+};
+
+// Function: Arity 6 -> 3.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5,
+      const X6& x6) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x4, x5, x6);
+  }
+};
+
+// Method: Arity 5 -> 3.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X3& x3, const X4& x4,
+      const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x3, x4, x5);
+  }
+};
+
+// Const Method: Arity 5 -> 3.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits3<StorageType, R(T::*)(X1, X2, X3, X4, X5) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X3& x3, const X4& x4,
+      const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), x3, x4, x5);
+  }
+};
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits4;
+
+// Function: Arity 4 -> 0.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4>
+struct FunctionTraits4<StorageType, R(*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_));
+  }
+};
+
+// Method: Arity 3 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits4<StorageType, R(T::*)(X1, X2, X3)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_));
+  }
+};
+
+// Const Method: Arity 3 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3>
+struct FunctionTraits4<StorageType, R(T::*)(X1, X2, X3) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base ) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_));
+  }
+};
+
+// Function: Arity 5 -> 1.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5>
+struct FunctionTraits4<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5);
+  }
+};
+
+// Method: Arity 4 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits4<StorageType, R(T::*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4);
+  }
+};
+
+// Const Method: Arity 4 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits4<StorageType, R(T::*)(X1, X2, X3, X4) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X4& x4) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4);
+  }
+};
+
+// Function: Arity 6 -> 2.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X5& x5, const X6& x6) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5, x6);
+  }
+};
+
+// Method: Arity 5 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4, x5);
+  }
+};
+
+// Const Method: Arity 5 -> 2.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits4<StorageType, R(T::*)(X1, X2, X3, X4, X5) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X4& x4, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4, x5);
+  }
+};
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits5;
+
+// Function: Arity 5 -> 0.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5>
+struct FunctionTraits5<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_));
+  }
+};
+
+// Method: Arity 4 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits5<StorageType, R(T::*)(X1, X2, X3, X4)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_));
+  }
+};
+
+// Const Method: Arity 4 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4>
+struct FunctionTraits5<StorageType, R(T::*)(X1, X2, X3, X4) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base ) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_));
+  }
+};
+
+// Function: Arity 6 -> 1.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X6& x6) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x6);
+  }
+};
+
+// Method: Arity 5 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base, const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5);
+  }
+};
+
+// Const Method: Arity 5 -> 1.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits5<StorageType, R(T::*)(X1, X2, X3, X4, X5) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base,  const X5& x5) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5);
+  }
+};
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits6;
+
+// Function: Arity 6 -> 0.
+template <typename StorageType, typename R,typename X1, typename X2,
+    typename X3, typename X4, typename X5, typename X6>
+struct FunctionTraits6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ||
+          is_non_const_reference<X6>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_),
+        Unwrap(invoker->p6_));
+  }
+};
+
+// Method: Arity 5 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+  COMPILE_ASSERT(
+      !( is_non_const_reference<X1>::value ||
+          is_non_const_reference<X2>::value ||
+          is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_),
+        Unwrap(invoker->p6_));
+  }
+};
+
+// Const Method: Arity 5 -> 0.
+template <typename StorageType, typename R, typename T, typename X1,
+    typename X2, typename X3, typename X4, typename X5>
+struct FunctionTraits6<StorageType, R(T::*)(X1, X2, X3, X4, X5) const> {
+  COMPILE_ASSERT(
+      !(is_non_const_reference<X1>::value || is_non_const_reference<X2>::value
+          || is_non_const_reference<X3>::value ||
+          is_non_const_reference<X4>::value ||
+          is_non_const_reference<X5>::value ),
+      do_not_bind_functions_with_nonconst_ref);
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base ) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
+        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_),
+        Unwrap(invoker->p6_));
+  }
+};
+
+
+// These are the actual storage classes for the invokers.
+//
+// Though these types are "classes", they are being used as structs with
+// all member variable public.  We cannot make it a struct because it inherits
+// from a class which causes a compiler warning.  We cannot add a "Run()" method
+// that forwards the unbound arguments because that would require we unwrap the
+// Sig type like in FunctionTraitsN above to know the return type, and the arity
+// of Run().
+//
+// An alternate solution would be to merge FunctionTraitsN and InvokerStorageN,
+// but the generated code seemed harder to read.
+
+template <typename Sig>
+class InvokerStorage0 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage0 StorageType;
+  typedef FunctionTraits0<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+
+
+  InvokerStorage0(Sig f)
+      : f_(f) {
+  }
+
+  virtual ~InvokerStorage0() {  }
+
+  Sig f_;
+};
+
+template <typename Sig, typename P1>
+class InvokerStorage1 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage1 StorageType;
+  typedef FunctionTraits1<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
+                 p1_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+
+
+  InvokerStorage1(Sig f, const P1& p1)
+      : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)) {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+  }
+
+  virtual ~InvokerStorage1() {
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+  }
+
+  Sig f_;
+  typename BindType<P1>::StorageType p1_;
+};
+
+template <typename Sig, typename P1, typename P2>
+class InvokerStorage2 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage2 StorageType;
+  typedef FunctionTraits2<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
+                 p1_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
+                 p2_is_refcounted_type_and_needs_scoped_refptr);
+
+
+  InvokerStorage2(Sig f, const P1& p1, const P2& p2)
+      : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)),
+          p2_(static_cast<typename BindType<P2>::StorageType>(p2)) {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+  }
+
+  virtual ~InvokerStorage2() {
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+  }
+
+  Sig f_;
+  typename BindType<P1>::StorageType p1_;
+  typename BindType<P2>::StorageType p2_;
+};
+
+template <typename Sig, typename P1, typename P2, typename P3>
+class InvokerStorage3 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage3 StorageType;
+  typedef FunctionTraits3<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
+                 p1_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
+                 p2_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
+                 p3_is_refcounted_type_and_needs_scoped_refptr);
+
+
+  InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3)
+      : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)),
+          p2_(static_cast<typename BindType<P2>::StorageType>(p2)),
+          p3_(static_cast<typename BindType<P3>::StorageType>(p3)) {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+  }
+
+  virtual ~InvokerStorage3() {
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+  }
+
+  Sig f_;
+  typename BindType<P1>::StorageType p1_;
+  typename BindType<P2>::StorageType p2_;
+  typename BindType<P3>::StorageType p3_;
+};
+
+template <typename Sig, typename P1, typename P2, typename P3, typename P4>
+class InvokerStorage4 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage4 StorageType;
+  typedef FunctionTraits4<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
+                 p1_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
+                 p2_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
+                 p3_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
+                 p4_is_refcounted_type_and_needs_scoped_refptr);
+
+
+  InvokerStorage4(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4)
+      : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)),
+          p2_(static_cast<typename BindType<P2>::StorageType>(p2)),
+          p3_(static_cast<typename BindType<P3>::StorageType>(p3)),
+          p4_(static_cast<typename BindType<P4>::StorageType>(p4)) {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+  }
+
+  virtual ~InvokerStorage4() {
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+  }
+
+  Sig f_;
+  typename BindType<P1>::StorageType p1_;
+  typename BindType<P2>::StorageType p2_;
+  typename BindType<P3>::StorageType p3_;
+  typename BindType<P4>::StorageType p4_;
+};
+
+template <typename Sig, typename P1, typename P2, typename P3, typename P4,
+    typename P5>
+class InvokerStorage5 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage5 StorageType;
+  typedef FunctionTraits5<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
+                 p1_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
+                 p2_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
+                 p3_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
+                 p4_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value,
+                 p5_is_refcounted_type_and_needs_scoped_refptr);
+
+
+  InvokerStorage5(Sig f, const P1& p1, const P2& p2, const P3& p3,
+      const P4& p4, const P5& p5)
+      : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)),
+          p2_(static_cast<typename BindType<P2>::StorageType>(p2)),
+          p3_(static_cast<typename BindType<P3>::StorageType>(p3)),
+          p4_(static_cast<typename BindType<P4>::StorageType>(p4)),
+          p5_(static_cast<typename BindType<P5>::StorageType>(p5)) {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+  }
+
+  virtual ~InvokerStorage5() {
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+  }
+
+  Sig f_;
+  typename BindType<P1>::StorageType p1_;
+  typename BindType<P2>::StorageType p2_;
+  typename BindType<P3>::StorageType p3_;
+  typename BindType<P4>::StorageType p4_;
+  typename BindType<P5>::StorageType p5_;
+};
+
+template <typename Sig, typename P1, typename P2, typename P3, typename P4,
+    typename P5, typename P6>
+class InvokerStorage6 : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage6 StorageType;
+  typedef FunctionTraits6<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
+                 p1_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
+                 p2_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
+                 p3_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
+                 p4_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value,
+                 p5_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P6>::value,
+                 p6_is_refcounted_type_and_needs_scoped_refptr);
+
+
+  InvokerStorage6(Sig f, const P1& p1, const P2& p2, const P3& p3,
+      const P4& p4, const P5& p5, const P6& p6)
+      : f_(f), p1_(static_cast<typename BindType<P1>::StorageType>(p1)),
+          p2_(static_cast<typename BindType<P2>::StorageType>(p2)),
+          p3_(static_cast<typename BindType<P3>::StorageType>(p3)),
+          p4_(static_cast<typename BindType<P4>::StorageType>(p4)),
+          p5_(static_cast<typename BindType<P5>::StorageType>(p5)),
+          p6_(static_cast<typename BindType<P6>::StorageType>(p6)) {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+  }
+
+  virtual ~InvokerStorage6() {
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+  }
+
+  Sig f_;
+  typename BindType<P1>::StorageType p1_;
+  typename BindType<P2>::StorageType p2_;
+  typename BindType<P3>::StorageType p3_;
+  typename BindType<P4>::StorageType p4_;
+  typename BindType<P5>::StorageType p5_;
+  typename BindType<P6>::StorageType p6_;
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_BIND_INTERNAL_H_
diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump
new file mode 100644
index 0000000..132b0db
--- /dev/null
+++ b/base/bind_internal.h.pump
@@ -0,0 +1,237 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$var MAX_ARITY = 6
+
+// Copyright (c) 2011 The Chromium 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_BIND_INTERNAL_H_
+#define BASE_BIND_INTERNAL_H_
+#pragma once
+
+#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
+#include "base/template_util.h"
+
+namespace base {
+namespace internal {
+
+// The method by which a function is invoked is determined by 3 different
+// dimensions:
+//
+//   1) The type of function (normal, method, const-method)
+//   2) The arity of the function
+//   3) The number of bound parameters.
+//
+// The FunctionTraitsN classes unwrap the function signature type to
+// specialize based on the first two dimensions.  The N in FunctionTraitsN
+// specifies the 3rd dimension.  We could have specified the unbound parameters
+// via template parameters, but this method looked cleaner.
+//
+// The FunctionTraitsN contains a static DoInvoke() function that is the key to
+// implementing type erasure in the Callback() classes.  DoInvoke() is a static
+// function with a fixed signature that is independent of StorageType; its
+// first argument is a pointer to the non-templated common baseclass of
+// StorageType. This lets us store pointer to DoInvoke() in a function pointer
+// that has knowledge of the specific StorageType, and thus no knowledge of the
+// bound function and bound parameter types.
+//
+// As long as we ensure that DoInvoke() is only used with pointers there were
+// upcasted from the correct StorageType, we can be sure that execution is
+// safe.
+
+$range BOUND 0..MAX_ARITY
+$for BOUND [[
+
+template <typename StorageType, typename Sig>
+struct FunctionTraits$(BOUND);
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+
+$var UNBOUND = ARITY - BOUND
+$if UNBOUND >= 0 [[
+
+$$ Variables for function traits generation.
+$range ARG 1..ARITY
+$range BOUND_ARG 1..BOUND
+$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY
+
+$$ Variables for method traits generation. We are always short one arity since
+$$ the first bound parameter is the object.
+$var M_ARITY = ARITY - 1
+$range M_ARG 1..M_ARITY
+$range M_BOUND_ARG 2..BOUND
+$range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY
+
+// Function: Arity $(ARITY) -> $(UNBOUND).
+template <typename StorageType, typename R[[]]
+$if ARITY > 0 [[,]][[]]
+$for ARG , [[typename X$(ARG)]]>
+struct FunctionTraits$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> {
+$if ARITY > 0 [[
+
+  COMPILE_ASSERT(
+      !($for ARG || [[ is_non_const_reference<X$(ARG)>::value ]]),
+      do_not_bind_functions_with_nonconst_ref);
+
+]]
+
+  typedef base::false_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base[[]]
+$if UNBOUND != 0 [[, ]][[]]
+$for UNBOUND_ARG , [[const X$(UNBOUND_ARG)& x$(UNBOUND_ARG)]]) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]]
+$$ Add comma if there are both boudn and unbound args.
+$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
+$for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]);
+  }
+};
+
+$if BOUND > 0 [[
+
+// Method: Arity $(M_ARITY) -> $(UNBOUND).
+template <typename StorageType, typename R, typename T[[]]
+$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
+struct FunctionTraits$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> {
+$if M_ARITY > 0 [[
+
+  COMPILE_ASSERT(
+      !($for M_ARG || [[ is_non_const_reference<X$(M_ARG)>::value ]]),
+      do_not_bind_functions_with_nonconst_ref);
+
+]]
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base[[]]
+$if UNBOUND > 0 [[, ]][[]]
+$for M_UNBOUND_ARG , [[const X$(M_UNBOUND_ARG)& x$(M_UNBOUND_ARG)]]) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)([[]]
+$for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
+$if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
+$for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
+  }
+};
+
+// Const Method: Arity $(M_ARITY) -> $(UNBOUND).
+template <typename StorageType, typename R, typename T[[]]
+$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
+struct FunctionTraits$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]]) const> {
+$if M_ARITY > 0 [[
+
+  COMPILE_ASSERT(
+      !($for M_ARG || [[is_non_const_reference<X$(M_ARG)>::value ]]),
+      do_not_bind_functions_with_nonconst_ref);
+
+]]
+
+  typedef base::true_type IsMethod;
+
+  static R DoInvoke(InvokerStorageBase* base[[]]
+$if UNBOUND > 0 [[, ]]
+[[]] $for M_UNBOUND_ARG , [[const X$(M_UNBOUND_ARG)& x$(M_UNBOUND_ARG)]]) {
+    StorageType* invoker = static_cast<StorageType*>(base);
+    return (Unwrap(invoker->p1_)->*invoker->f_)([[]]
+$for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
+$if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
+$for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
+  }
+};
+
+]]  $$ if BOUND
+
+]]  $$ if UNBOUND
+]]  $$ for ARITY
+]]  $$ for BOUND
+
+
+// These are the actual storage classes for the invokers.
+//
+// Though these types are "classes", they are being used as structs with
+// all member variable public.  We cannot make it a struct because it inherits
+// from a class which causes a compiler warning.  We cannot add a "Run()" method
+// that forwards the unbound arguments because that would require we unwrap the
+// Sig type like in FunctionTraitsN above to know the return type, and the arity
+// of Run().
+//
+// An alternate solution would be to merge FunctionTraitsN and InvokerStorageN,
+// but the generated code seemed harder to read.
+
+$for BOUND [[
+$range BOUND_ARG 1..BOUND
+
+template <typename Sig[[]]
+$if BOUND > 0 [[, ]]
+$for BOUND_ARG , [[typename P$(BOUND_ARG)]]>
+class InvokerStorage$(BOUND) : public InvokerStorageBase {
+ public:
+  typedef InvokerStorage$(BOUND) StorageType;
+  typedef FunctionTraits$(BOUND)<StorageType, Sig> FunctionTraits;
+  typedef typename FunctionTraits::IsMethod IsMethod;
+
+$for BOUND_ARG [[
+$if BOUND_ARG == 1 [[
+
+  // For methods, we need to be careful for parameter 1.  We skip the
+  // scoped_refptr check because the binder itself takes care of this. We also
+  // disallow binding of an array as the method's target object.
+  COMPILE_ASSERT(IsMethod::value ||
+                 !internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
+                 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
+  COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value,
+                 first_bound_argument_to_method_cannot_be_array);
+]] $else [[
+
+  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
+                 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
+]]  $$ $if BOUND_ARG
+]]  $$ $for BOUND_ARG
+
+
+
+  InvokerStorage$(BOUND)(Sig f
+$if BOUND > 0 [[, ]]
+$for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]])
+      : f_(f)[[]]
+$if BOUND == 0 [[
+ {
+
+]] $else [[
+, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename BindType<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] {
+    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
+
+]]
+  }
+
+  virtual ~InvokerStorage$(BOUND)() {
+$if BOUND > 0 [[
+
+    MaybeRefcount<IsMethod, P1>::Release(p1_);
+
+]]
+  }
+
+  Sig f_;
+
+$for BOUND_ARG [[
+  typename BindType<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_;
+
+]]
+};
+
+]]  $$ for BOUND
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_BIND_INTERNAL_H_
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
new file mode 100644
index 0000000..47d971a
--- /dev/null
+++ b/base/bind_unittest.cc
@@ -0,0 +1,597 @@
+// Copyright (c) 2011 The Chromium 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/bind.h"
+
+#if defined(BASE_CALLBACK_H_)
+// We explicitly do not want to include callback.h so people are not tempted
+// to use bind.h in a headerfile for getting the Callback types.
+#error "base/bind.h should avoid pulling in callback.h by default."
+#endif
+
+#include "base/callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::StrictMock;
+
+namespace base {
+namespace {
+
+class NoRef {
+ public:
+  NoRef() {}
+
+  MOCK_METHOD0(VoidMethod0, void(void));
+  MOCK_CONST_METHOD0(VoidConstMethod0, void(void));
+
+  MOCK_METHOD0(IntMethod0, int(void));
+  MOCK_CONST_METHOD0(IntConstMethod0, int(void));
+
+ private:
+  // Particularly important in this test to ensure no copies are made.
+  DISALLOW_COPY_AND_ASSIGN(NoRef);
+};
+
+class HasRef : public NoRef {
+ public:
+  HasRef() {}
+
+  MOCK_CONST_METHOD0(AddRef, void(void));
+  MOCK_CONST_METHOD0(Release, bool(void));
+
+ private:
+  // Particularly important in this test to ensure no copies are made.
+  DISALLOW_COPY_AND_ASSIGN(HasRef);
+};
+
+static const int kParentValue = 1;
+static const int kChildValue = 2;
+
+class Parent {
+ public:
+  void AddRef(void) const {}
+  void Release(void) const {}
+  virtual void VirtualSet() { value = kParentValue; }
+  void NonVirtualSet() { value = kParentValue; }
+  int value;
+};
+
+class Child : public Parent {
+ public:
+  virtual void VirtualSet() { value = kChildValue; }
+  void NonVirtualSet() { value = kChildValue; }
+};
+
+class NoRefParent {
+ public:
+  virtual void VirtualSet() { value = kParentValue; }
+  void NonVirtualSet() { value = kParentValue; }
+  int value;
+};
+
+class NoRefChild : public NoRefParent {
+  virtual void VirtualSet() { value = kChildValue; }
+  void NonVirtualSet() { value = kChildValue; }
+};
+
+// Used for probing the number of copies that occur if a type must be coerced
+// during argument forwarding in the Run() methods.
+struct DerivedCopyCounter {
+  DerivedCopyCounter(int* copies, int* assigns)
+      : copies_(copies), assigns_(assigns) {
+  }
+  int* copies_;
+  int* assigns_;
+};
+
+// Used for probing the number of copies in an argument.
+class CopyCounter {
+ public:
+  CopyCounter(int* copies, int* assigns)
+      : copies_(copies), assigns_(assigns) {
+  }
+
+  CopyCounter(const CopyCounter& other)
+      : copies_(other.copies_),
+        assigns_(other.assigns_) {
+    (*copies_)++;
+  }
+
+  // Probing for copies from coerscion.
+  CopyCounter(const DerivedCopyCounter& other)
+      : copies_(other.copies_),
+        assigns_(other.assigns_) {
+    (*copies_)++;
+  }
+
+  const CopyCounter& operator=(const CopyCounter& rhs) {
+    copies_ = rhs.copies_;
+    assigns_ = rhs.assigns_;
+
+    if (assigns_) {
+      (*assigns_)++;
+    }
+
+    return *this;
+  }
+
+  int copies() const {
+    return *copies_;
+  }
+
+  int assigns() const {
+    return *assigns_;
+  }
+
+ private:
+  int* copies_;
+  int* assigns_;
+};
+
+// Some test functions that we can Bind to.
+template <typename T>
+T PolymorphicIdentity(T t) {
+  return t;
+}
+
+template <typename T>
+void VoidPolymorphic1(T t) {
+}
+
+int Identity(int n) {
+  return n;
+}
+
+int ArrayGet(const int array[], int n) {
+  return array[n];
+}
+
+int Sum(int a, int b, int c, int d, int e, int f) {
+  return a + b + c + d + e + f;
+}
+
+const char* CStringIdentity(const char* s) {
+  return s;
+}
+
+int GetCopies(const CopyCounter& counter) {
+  return counter.copies();
+}
+
+int UnwrapNoRefParent(NoRefParent p) {
+  return p.value;
+}
+
+int UnwrapNoRefParentPtr(NoRefParent* p) {
+  return p->value;
+}
+
+int UnwrapNoRefParentConstRef(const NoRefParent& p) {
+  return p.value;
+}
+
+// Only useful in no-compile tests.
+int UnwrapNoRefParentRef(Parent& p) {
+  return p.value;
+}
+
+class BindTest : public ::testing::Test {
+ public:
+  BindTest() {
+    const_has_ref_ptr_ = &has_ref_;
+    const_no_ref_ptr_ = &no_ref_;
+    static_func_mock_ptr = &static_func_mock_;
+  }
+
+  virtual ~BindTest() {
+  }
+
+  static void VoidFunc0(void) {
+    static_func_mock_ptr->VoidMethod0();
+  }
+
+  static int IntFunc0(void) { return static_func_mock_ptr->IntMethod0(); }
+
+ protected:
+  StrictMock<NoRef> no_ref_;
+  StrictMock<HasRef> has_ref_;
+  const HasRef* const_has_ref_ptr_;
+  const NoRef* const_no_ref_ptr_;
+  StrictMock<NoRef> static_func_mock_;
+
+  // Used by the static functions to perform expectations.
+  static StrictMock<NoRef>* static_func_mock_ptr;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BindTest);
+};
+
+StrictMock<NoRef>* BindTest::static_func_mock_ptr;
+
+// Ensure we can create unbound callbacks. We need this to be able to store
+// them in class members that can be initialized later.
+TEST_F(BindTest, DefaultConstruction) {
+  Callback<void(void)> c0;
+  Callback<void(int)> c1;
+  Callback<void(int,int)> c2;
+  Callback<void(int,int,int)> c3;
+  Callback<void(int,int,int,int)> c4;
+  Callback<void(int,int,int,int,int)> c5;
+  Callback<void(int,int,int,int,int,int)> c6;
+}
+
+// Sanity check that we can instantiate a callback for each arity.
+TEST_F(BindTest, ArityTest) {
+  Callback<int(void)> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1);
+  EXPECT_EQ(63, c0.Run());
+
+  Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2);
+  EXPECT_EQ(75, c1.Run(13));
+
+  Callback<int(int,int)> c2 = Bind(&Sum, 32, 16, 8, 4);
+  EXPECT_EQ(85, c2.Run(13, 12));
+
+  Callback<int(int,int,int)> c3 = Bind(&Sum, 32, 16, 8);
+  EXPECT_EQ(92, c3.Run(13, 12, 11));
+
+  Callback<int(int,int,int,int)> c4 = Bind(&Sum, 32, 16);
+  EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
+
+  Callback<int(int,int,int,int,int)> c5 = Bind(&Sum, 32);
+  EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
+
+  Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
+  EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
+}
+
+// Function type support.
+//   - Normal function.
+//   - Method bound to non-const object.
+//   - Const method bound to non-const object.
+//   - Const method bound to const object.
+//   - Derived classes can be used with pointers to non-virtual base functions.
+//   - Derived classes can be used with pointers to virtual base functions (and
+//     preserve virtual dispatch).
+TEST_F(BindTest, FunctionTypeSupport) {
+  EXPECT_CALL(static_func_mock_, VoidMethod0());
+  EXPECT_CALL(has_ref_, AddRef()).Times(3);
+  EXPECT_CALL(has_ref_, Release()).Times(3);
+  EXPECT_CALL(has_ref_, VoidMethod0());
+  EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2);
+
+  Closure normal_cb = Bind(&VoidFunc0);
+  Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_);
+  Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0,
+                                              &has_ref_);
+  Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0,
+                                           const_has_ref_ptr_);
+  normal_cb.Run();
+  method_cb.Run();
+  const_method_nonconst_obj_cb.Run();
+  const_method_const_obj_cb.Run();
+
+  Child child;
+  child.value = 0;
+  Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child);
+  virtual_set_cb.Run();
+  EXPECT_EQ(kChildValue, child.value);
+
+  child.value = 0;
+  Closure non_virtual_set_cb = Bind(&Parent::NonVirtualSet, &child);
+  non_virtual_set_cb.Run();
+  EXPECT_EQ(kParentValue, child.value);
+}
+
+// Return value support.
+//   - Function with return value.
+//   - Method with return value.
+//   - Const method with return value.
+TEST_F(BindTest, ReturnValues) {
+  EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
+  EXPECT_CALL(has_ref_, AddRef()).Times(3);
+  EXPECT_CALL(has_ref_, Release()).Times(3);
+  EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(31337));
+  EXPECT_CALL(has_ref_, IntConstMethod0())
+      .WillOnce(Return(41337))
+      .WillOnce(Return(51337));
+
+  Callback<int(void)> normal_cb = Bind(&IntFunc0);
+  Callback<int(void)> method_cb = Bind(&HasRef::IntMethod0, &has_ref_);
+  Callback<int(void)> const_method_nonconst_obj_cb =
+      Bind(&HasRef::IntConstMethod0, &has_ref_);
+  Callback<int(void)> const_method_const_obj_cb =
+      Bind(&HasRef::IntConstMethod0, const_has_ref_ptr_);
+  EXPECT_EQ(1337, normal_cb.Run());
+  EXPECT_EQ(31337, method_cb.Run());
+  EXPECT_EQ(41337, const_method_nonconst_obj_cb.Run());
+  EXPECT_EQ(51337, const_method_const_obj_cb.Run());
+}
+
+// Argument binding tests.
+//   - Argument binding to primitive.
+//   - Argument binding to primitive pointer.
+//   - Argument binding to a literal integer.
+//   - Argument binding to a literal string.
+//   - Argument binding with template function.
+//   - Argument binding to an object.
+//   - Argument gets type converted.
+//   - Pointer argument gets converted.
+//   - Const Reference forces conversion.
+TEST_F(BindTest, ArgumentBinding) {
+  int n = 2;
+
+  Callback<int(void)> bind_primitive_cb = Bind(&Identity, n);
+  EXPECT_EQ(n, bind_primitive_cb.Run());
+
+  Callback<int*(void)> bind_primitive_pointer_cb =
+      Bind(&PolymorphicIdentity<int*>, &n);
+  EXPECT_EQ(&n, bind_primitive_pointer_cb.Run());
+
+  Callback<int(void)> bind_int_literal_cb = Bind(&Identity, 3);
+  EXPECT_EQ(3, bind_int_literal_cb.Run());
+
+  Callback<const char*(void)> bind_string_literal_cb =
+      Bind(&CStringIdentity, "hi");
+  EXPECT_STREQ("hi", bind_string_literal_cb.Run());
+
+  Callback<int(void)> bind_template_function_cb =
+      Bind(&PolymorphicIdentity<int>, 4);
+  EXPECT_EQ(4, bind_template_function_cb.Run());
+
+  NoRefParent p;
+  p.value = 5;
+  Callback<int(void)> bind_object_cb = Bind(&UnwrapNoRefParent, p);
+  EXPECT_EQ(5, bind_object_cb.Run());
+
+  NoRefChild c;
+  c.value = 6;
+  Callback<int(void)> bind_promotes_cb = Bind(&UnwrapNoRefParent, c);
+  EXPECT_EQ(6, bind_promotes_cb.Run());
+
+  c.value = 7;
+  Callback<int(void)> bind_pointer_promotes_cb =
+      Bind(&UnwrapNoRefParentPtr, &c);
+  EXPECT_EQ(7, bind_pointer_promotes_cb.Run());
+
+  c.value = 8;
+  Callback<int(void)> bind_const_reference_promotes_cb =
+      Bind(&UnwrapNoRefParentConstRef, c);
+  EXPECT_EQ(8, bind_const_reference_promotes_cb.Run());
+}
+
+// Functions that take reference parameters.
+//  - Forced reference parameter type still stores a copy.
+//  - Forced const reference parameter type still stores a copy.
+TEST_F(BindTest, ReferenceArgumentBinding) {
+  int n = 1;
+  int& ref_n = n;
+  const int& const_ref_n = n;
+
+  Callback<int(void)> ref_copies_cb = Bind(&Identity, ref_n);
+  EXPECT_EQ(n, ref_copies_cb.Run());
+  n++;
+  EXPECT_EQ(n - 1, ref_copies_cb.Run());
+
+  Callback<int(void)> const_ref_copies_cb = Bind(&Identity, const_ref_n);
+  EXPECT_EQ(n, const_ref_copies_cb.Run());
+  n++;
+  EXPECT_EQ(n - 1, const_ref_copies_cb.Run());
+}
+
+// Check that we can pass in arrays and have them be stored as a pointer.
+//  - Array of values stores a pointer.
+//  - Array of const values stores a pointer.
+TEST_F(BindTest, ArrayArgumentBinding) {
+  int array[4] = {1, 1, 1, 1};
+  const int (*const_array_ptr)[4] = &array;
+
+  Callback<int(void)> array_cb = Bind(&ArrayGet, array, 1);
+  EXPECT_EQ(1, array_cb.Run());
+
+  Callback<int(void)> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1);
+  EXPECT_EQ(1, const_array_cb.Run());
+
+  array[1] = 3;
+  EXPECT_EQ(3, array_cb.Run());
+  EXPECT_EQ(3, const_array_cb.Run());
+}
+
+// Verify SupportsAddRefAndRelease correctly introspects the class type for
+// AddRef() and Release().
+TEST_F(BindTest, SupportsAddRefAndRelease) {
+  EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRef>::value);
+  EXPECT_FALSE(internal::SupportsAddRefAndRelease<NoRef>::value);
+
+  // StrictMock<T> is a derived class of T.  So, we use StrictMock<HasRef> and
+  // StrictMock<NoRef> to test that SupportsAddRefAndRelease works over
+  // inheritance.
+  EXPECT_TRUE(internal::SupportsAddRefAndRelease<StrictMock<HasRef> >::value);
+  EXPECT_FALSE(internal::SupportsAddRefAndRelease<StrictMock<NoRef> >::value);
+}
+
+// Unretained() wrapper support.
+//   - Method bound to Unretained() non-object.
+//   - Const method bound to Unretained() non-const object.
+//   - Const method bound to Unretained() const object.
+TEST_F(BindTest, Unretained) {
+  EXPECT_CALL(no_ref_, VoidMethod0());
+  EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
+
+  Callback<void(void)> method_cb =
+      Bind(&NoRef::VoidMethod0, Unretained(&no_ref_));
+  method_cb.Run();
+
+  Callback<void(void)> const_method_cb =
+      Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref_));
+  const_method_cb.Run();
+
+  Callback<void(void)> const_method_const_ptr_cb =
+      Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr_));
+  const_method_const_ptr_cb.Run();
+}
+
+// ConstRef() wrapper support.
+//   - Binding w/o ConstRef takes a copy.
+//   - Binding a ConstRef takes a reference.
+//   - Binding ConstRef to a function ConstRef does not copy on invoke.
+TEST_F(BindTest, ConstRef) {
+  int n = 1;
+
+  Callback<int(void)> copy_cb = Bind(&Identity, n);
+  Callback<int(void)> const_ref_cb = Bind(&Identity, ConstRef(n));
+  EXPECT_EQ(n, copy_cb.Run());
+  EXPECT_EQ(n, const_ref_cb.Run());
+  n++;
+  EXPECT_EQ(n - 1, copy_cb.Run());
+  EXPECT_EQ(n, const_ref_cb.Run());
+
+  int copies = 0;
+  int assigns = 0;
+  CopyCounter counter(&copies, &assigns);
+  Callback<int(void)> all_const_ref_cb =
+      Bind(&GetCopies, ConstRef(counter));
+  EXPECT_EQ(0, all_const_ref_cb.Run());
+  EXPECT_EQ(0, copies);
+  EXPECT_EQ(0, assigns);
+}
+
+// Argument Copy-constructor usage for non-reference parameters.
+//   - Bound arguments are only copied once.
+//   - Forwarded arguments are only copied once.
+//   - Forwarded arguments with coerscions are only copied twice (once for the
+//     coerscion, and one for the final dispatch).
+TEST_F(BindTest, ArgumentCopies) {
+  int copies = 0;
+  int assigns = 0;
+
+  CopyCounter counter(&copies, &assigns);
+
+  Callback<void(void)> copy_cb =
+      Bind(&VoidPolymorphic1<CopyCounter>, counter);
+  EXPECT_GE(1, copies);
+  EXPECT_EQ(0, assigns);
+
+  copies = 0;
+  assigns = 0;
+  Callback<void(CopyCounter)> forward_cb =
+      Bind(&VoidPolymorphic1<CopyCounter>);
+  forward_cb.Run(counter);
+  EXPECT_GE(1, copies);
+  EXPECT_EQ(0, assigns);
+
+  copies = 0;
+  assigns = 0;
+  DerivedCopyCounter dervied(&copies, &assigns);
+  Callback<void(CopyCounter)> coerce_cb =
+      Bind(&VoidPolymorphic1<CopyCounter>);
+  coerce_cb.Run(dervied);
+  EXPECT_GE(2, copies);
+  EXPECT_EQ(0, assigns);
+}
+
+// Callback construction and assignment tests.
+//   - Construction from an InvokerStorageHolder should not cause ref/deref.
+//   - Assignment from other callback should only cause one ref
+//
+// TODO(ajwong): Is there actually a way to test this?
+
+// No-compile tests. These should not compile. If they do, we are allowing
+// error-prone, or incorrect behavior in the callback system.  Uncomment the
+// tests to check.
+TEST_F(BindTest, NoCompile) {
+  // - Method bound to const-object.
+  //
+  // Only const methods should be allowed to work with const objects.
+  //
+  // Callback<void(void)> method_to_const_cb =
+  //     Bind(&HasRef::VoidMethod0, const_has_ref_ptr_);
+  // method_to_const_cb.Run();
+
+  // - Method bound to non-refcounted object.
+  // - Const Method bound to non-refcounted object.
+  //
+  // We require refcounts unless you have Unretained().
+  //
+  // Callback<void(void)> no_ref_cb =
+  //     Bind(&NoRef::VoidMethod0, &no_ref_);
+  // no_ref_cb.Run();
+  // Callback<void(void)> no_ref_const_cb =
+  //     Bind(&NoRef::VoidConstMethod0, &no_ref_);
+  // no_ref_const_cb.Run();
+
+  // - Unretained() used with a refcounted object.
+  //
+  // If the object supports refcounts, unretaining it in the callback is a
+  // memory management contract break.
+  // Callback<void(void)> unretained_cb =
+  //     Bind(&HasRef::VoidConstMethod0, Unretained(&has_ref_));
+  // unretained_cb.Run();
+
+  // - Const argument used with non-const pointer parameter of same type.
+  // - Const argument used with non-const pointer parameter of super type.
+  //
+  // This is just a const-correctness check.
+  //
+  // const Parent* const_parent_ptr;
+  // const Child* const_child_ptr;
+  // Callback<Parent*(void)> pointer_same_cb =
+  //     Bind(&PolymorphicIdentity<Parent*>, const_parent_ptr);
+  // pointer_same_cb.Run();
+  // Callback<Parent*(void)> pointer_super_cb =
+  //     Bind(&PolymorphicIdentity<Parent*>, const_child_ptr);
+  // pointer_super_cb.Run();
+
+  // - Construction of Callback<A> from Callback<B> if A is supertype of B.
+  //   Specific example: Callback<void(void)> a; Callback<int(void)> b; a = b;
+  //
+  // While this is technically safe, most people aren't used to it when coding
+  // C++ so if this is happening, it is almost certainly an error.
+  //
+  // Callback<int(void)> cb_a0 = Bind(&Identity, 1);
+  // Callback<void(void)> cb_b0 = cb_a0;
+
+  // - Assignment of Callback<A> from Callback<B> if A is supertype of B.
+  // See explanation above.
+  //
+  // Callback<int(void)> cb_a1 = Bind(&Identity, 1);
+  // Callback<void(void)> cb_b1;
+  // cb_a1 = cb_b1;
+
+  // - Functions with reference parameters, unsupported.
+  //
+  // First, non-const reference parameters are disallowed by the Google
+  // style guide. Seconds, since we are doing argument forwarding it becomes
+  // very tricky to avoid copies, maintain const correctness, and not
+  // accidentally have the function be modifying a temporary, or a copy.
+  //
+  // NoRefParent p;
+  // Callback<int(Parent&)> ref_arg_cb = Bind(&UnwrapNoRefParentRef);
+  // ref_arg_cb.Run(p);
+  // Callback<int(void)> ref_cb = Bind(&UnwrapNoRefParentRef, p);
+  // ref_cb.Run();
+
+  // - A method should not be bindable with an array of objects.
+  //
+  // This is likely not wanted behavior. We specifically check for it though
+  // because it is possible, depending on how you implement prebinding, to
+  // implicitly convert an array type to a pointer type.
+  //
+  // HasRef p[10];
+  // Callback<void(void)> method_bound_to_array_cb =
+  //    Bind(&HasRef::VoidConstMethod0, p);
+  // method_bound_to_array_cb.Run();
+
+  // - Refcounted types should not be bound as a raw pointer.
+  // HasRef for_raw_ptr;
+  // Callback<void(void)> ref_count_as_raw_ptr =
+  //     Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr);
+  // ASSERT_EQ(&for_raw_ptr, ref_count_as_raw_ptr.Run());
+
+}
+
+}  // namespace
+}  // namespace base
diff --git a/base/callback.h b/base/callback.h
index e5ea771..05a7182 100644
--- a/base/callback.h
+++ b/base/callback.h
@@ -1,4 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// This file was GENERATED by command:
+//     pump.py callback.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,249 +11,472 @@
 #define BASE_CALLBACK_H_
 #pragma once
 
-#include "base/tuple.h"
-#include "base/raw_scoped_refptr_mismatch_checker.h"
+#include "base/callback_helpers.h"
+#include "base/callback_old.h"
 
-// Callback --------------------------------------------------------------------
+// New, super-duper, unified Callback system.  This will eventually replace
+// NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
+// systems currently in the Chromium code base.
 //
-// A Callback is like a Task but with unbound parameters. It is basically an
-// object-oriented function pointer.
+// WHAT IS THIS:
 //
-// Callbacks are designed to work with Tuples.  A set of helper functions and
-// classes is provided to hide the Tuple details from the consumer.  Client
-// code will generally work with the CallbackRunner base class, which merely
-// provides a Run method and is returned by the New* functions. This allows
-// users to not care which type of class implements the callback, only that it
-// has a certain number and type of arguments.
+// The templated Callback class is a generalized function object. Together
+// with the Bind() function in bind.h, they provide a type-safe method for
+// performing currying of arguments, and creating a "closure."
 //
-// The implementation of this is done by CallbackImpl, which inherits
-// CallbackStorage to store the data. This allows the storage of the data
-// (requiring the class type T) to be hidden from users, who will want to call
-// this regardless of the implementor's type T.
+// In programing languages, a closure is a first-class function where all its
+// parameters have been bound (usually via currying).  Closures are well
+// suited for representing, and passing around a unit of delayed execution.
+// They are used in Chromium code to schedule tasks on different MessageLoops.
 //
-// Note that callbacks currently have no facility for cancelling or abandoning
-// them. We currently handle this at a higher level for cases where this is
-// necessary. The pointer in a callback must remain valid until the callback
-// is made.
 //
-// Like Task, the callback executor is responsible for deleting the callback
-// pointer once the callback has executed.
+// MEMORY MANAGEMENT AND PASSING
 //
-// Example client usage:
-//   void Object::DoStuff(int, string);
-//   Callback2<int, string>::Type* callback =
-//       NewCallback(obj, &Object::DoStuff);
-//   callback->Run(5, string("hello"));
-//   delete callback;
-// or, equivalently, using tuples directly:
-//   CallbackRunner<Tuple2<int, string> >* callback =
-//       NewCallback(obj, &Object::DoStuff);
-//   callback->RunWithParams(MakeTuple(5, string("hello")));
+// The Callback objects themselves should be passed by const-reference, and
+// stored by copy. They internally store their state via a refcounted class
+// and thus do not need to be deleted.
 //
-// There is also a 0-args version that returns a value.  Example:
-//   int Object::GetNextInt();
-//   CallbackWithReturnValue<int>::Type* callback =
-//       NewCallbackWithReturnValue(obj, &Object::GetNextInt);
-//   int next_int = callback->Run();
-//   delete callback;
+// The reason to pass via a const-reference is to avoid unnecessary
+// AddRef/Release pairs to the internal state.
+//
+//
+// EXAMPLE USAGE:
+//
+// /* Binding a normal function. */
+// int Return5() { return 5; }
+// base::Callback<int(int)> func_cb = base::Bind(&Return5);
+// LOG(INFO) << func_cb.Run(5);  // Prints 5.
+//
+// void PrintHi() { LOG(INFO) << "hi."; }
+// base::Closure void_func_cb = base::Bind(&PrintHi);
+// LOG(INFO) << void_func_cb.Run();  // Prints: hi.
+//
+// /* Binding a class method. */
+// class Ref : public RefCountedThreadSafe<Ref> {
+//  public:
+//   int Foo() { return 3; }
+//   void PrintBye() { LOG(INFO) << "bye."; }
+// };
+// scoped_refptr<Ref> ref = new Ref();
+// base::Callback<int(void)> ref_cb = base::Bind(&Ref::Foo, ref.get());
+// LOG(INFO) << ref_cb.Run();  // Prints out 3.
+//
+// base::Closure void_ref_cb = base::Bind(&Ref::PrintBye, ref.get());
+// void_ref_cb.Run();  // Prints: bye.
+//
+// /* Binding a class method in a non-refcounted class.
+//  *
+//  * WARNING: You must be sure the referee outlives the callback!
+//  *          This is particularly important if you post a closure to a
+//  *          MessageLoop because then it becomes hard to know what the
+//  *          lifetime of the referee needs to be.
+//  */
+// class NoRef {
+//  public:
+//   int Foo() { return 4; }
+//   void PrintWhy() { LOG(INFO) << "why???"; }
+// };
+// NoRef no_ref;
+// base::Callback<int(void)> base::no_ref_cb =
+//     base::Bind(&NoRef::Foo, base::Unretained(&no_ref));
+// LOG(INFO) << ref_cb.Run();  // Prints out 4.
+//
+// base::Closure void_no_ref_cb =
+//     base::Bind(&NoRef::PrintWhy, base::Unretained(no_ref));
+// void_no_ref_cb.Run();  // Prints: why???
+//
+// /* Binding a reference. */
+// int Identity(int n) { return n; }
+// int value = 1;
+// base::Callback<int(void)> bound_copy_cb = base::Bind(&Identity, value);
+// base::Callback<int(void)> bound_ref_cb =
+//     base::Bind(&Identity, base::ConstRef(value));
+// LOG(INFO) << bound_copy_cb.Run();  // Prints 1.
+// LOG(INFO) << bound_ref_cb.Run();  // Prints 1.
+// value = 2;
+// LOG(INFO) << bound_copy_cb.Run();  // Prints 1.
+// LOG(INFO) << bound_ref_cb.Run();  // Prints 2.
+//
+//
+// WHERE IS THIS DESIGN FROM:
+//
+// The design Callback and Bind is heavily influenced by C++'s
+// tr1::function/tr1::bind, and by the "Google Callback" system used inside
+// Google.
+//
+//
+// HOW THE IMPLEMENTATION WORKS:
+//
+// There are three main components to the system:
+//   1) The Callback classes.
+//   2) The Bind() functions.
+//   3) The arguments wrappers (eg., Unretained() and ConstRef()).
+//
+// The Callback classes represent a generic function pointer. Internally,
+// it stores a refcounted piece of state that represents the target function
+// and all its bound parameters.  Each Callback specialization has a templated
+// constructor that takes an InvokerStorageHolder<> object.  In the context of
+// the constructor, the static type of this InvokerStorageHolder<> object
+// uniquely identifies the function it is representing, all its bound
+// parameters, and a DoInvoke() that is capable of invoking the target.
+//
+// Callback's constructor is takes the InvokerStorageHolder<> that has the
+// full static type and erases the target function type, and the bound
+// parameters.  It does this by storing a pointer to the specific DoInvoke()
+// function, and upcasting the state of InvokerStorageHolder<> to a
+// InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer
+// is only used with the stored DoInvoke() pointer.
+//
+// To create InvokerStorageHolder<> objects, we use the Bind() functions.
+// These functions, along with a set of internal templates, are reponsible for
+//
+//  - Unwrapping the function signature into return type, and parameters
+//  - Determining the number of parameters that are bound
+//  - Creating the storage for the bound parameters
+//  - Performing compile-time asserts to avoid error-prone behavior
+//  - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity
+//    matching the number of unbound parameters, and knows the correct
+//    refcounting semantics for the target object if we are binding a class
+//    method.
+//
+// The Bind functions do the above using type-inference, and template
+// specializations.
+//
+// By default Bind() will store copies of all bound parameters, and attempt
+// to refcount a target object if the function being bound is a class method.
+//
+// To change this behavior, we introduce a set of argument wrappers
+// (eg. Unretained(), and ConstRef()).  These are simple container templates
+// that are passed by value, and wrap a pointer to argument.  See the
+// file-level comment in base/bind_helpers.h for more info.
+//
+// These types are passed to the Unwrap() functions, and the MaybeRefcount()
+// functions respectively to modify the behavior of Bind().  The Unwrap()
+// and MaybeRefcount() functions change behavior by doing partial
+// specialization based on whether or not a parameter is a wrapper type.
+//
+// ConstRef() is similar to tr1::cref.  Unretained() is specific to Chromium.
+//
+//
+// WHY NOT TR1 FUNCTION/BIND?
+//
+// Direct use of tr1::function and tr1::bind was considered, but ultimately
+// rejected because of the number of copy constructors invocations involved
+// in the binding of arguments during construction, and the forwarding of
+// arguments during invocation.  These copies will no longer be an issue in
+// C++0x because C++0x will support rvalue reference allowing for the compiler
+// to avoid these copies.  However, waiting for C++0x is not an option.
+//
+// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
+// tr1::bind call itself will invoke a non-trivial copy constructor three times
+// for each bound parameter.  Also, each when passing a tr1::function, each
+// bound argument will be copied again.
+//
+// In addition to the copies taken at binding and invocation, copying a
+// tr1::function causes a copy to be made of all the bound parameters and
+// state.
+//
+// Furthermore, in Chromium, it is desirable for the Callback to take a
+// reference on a target object when representing a class method call.  This
+// is not supported by tr1.
+//
+// Lastly, tr1::function and tr1::bind has a more general and flexible API.
+// This includes things like argument reordering by use of
+// tr1::bind::placeholder, support for non-const reference parameters, and some
+// limited amount of subtyping of the tr1::function object (eg.,
+// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
+//
+// These are not features that are required in Chromium. Some of them, such as
+// allowing for reference parameters, and subtyping of functions, may actually
+// because a source of errors. Removing support for these features actually
+// allows for a simpler implementation, and a terser Currying API.
+//
+//
+// WHY NOT GOOGLE CALLBACKS?
+//
+// The Google callback system also does not support refcounting.  Furthermore,
+// its implementation has a number of strange edge cases with respect to type
+// conversion of its arguments.  In particular, the argument's constness must
+// at times match exactly the function signature, or the type-inference might
+// break.  Given the above, writing a custom solution was easier.
+//
+//
+// MISSING FUNCTIONALITY
+//  - Invoking the return of Bind.  Bind(&foo).Run() does not work;
+//  - Binding arrays to functions that take a non-const pointer.
+//    Example:
+//      void Foo(const char* ptr);
+//      void Bar(char* ptr);
+//      Bind(&Foo, "test");
+//      Bind(&Bar, "test");  // This fails because ptr is not const.
 
-// Base for all Callbacks that handles storage of the pointers.
-template <class T, typename Method>
-class CallbackStorage {
+namespace base {
+
+// First, we forward declare the Callback class template. This informs the
+// compiler that the template only has 1 type parameter which is the function
+// signature that the Callback is representing.
+//
+// After this, create template specializations for 0-6 parameters. Note that
+// even though the template typelist grows, the specialization still
+// only has one type: the function signature.
+template <typename Sig>
+class Callback;
+
+template <typename R>
+class Callback<R(void)> {
  public:
-  CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
   }
 
- protected:
-  T* obj_;
-  Method meth_;
-};
-
-// Interface that is exposed to the consumer, that does the actual calling
-// of the method.
-template <typename Params>
-class CallbackRunner {
- public:
-  typedef Params TupleType;
-
-  virtual ~CallbackRunner() {}
-  virtual void RunWithParams(const Params& params) = 0;
-
-  // Convenience functions so callers don't have to deal with Tuples.
-  inline void Run() {
-    RunWithParams(Tuple0());
+  R Run(void) const {
+    return polymorphic_invoke_(invoker_storage_.get());
   }
 
-  template <typename Arg1>
-  inline void Run(const Arg1& a) {
-    RunWithParams(Params(a));
-  }
-
-  template <typename Arg1, typename Arg2>
-  inline void Run(const Arg1& a, const Arg2& b) {
-    RunWithParams(Params(a, b));
-  }
-
-  template <typename Arg1, typename Arg2, typename Arg3>
-  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
-    RunWithParams(Params(a, b, c));
-  }
-
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
-    RunWithParams(Params(a, b, c, d));
-  }
-
-  template <typename Arg1, typename Arg2, typename Arg3,
-            typename Arg4, typename Arg5>
-  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
-                  const Arg4& d, const Arg5& e) {
-    RunWithParams(Params(a, b, c, d, e));
-  }
-};
-
-template <class T, typename Method, typename Params>
-class CallbackImpl : public CallbackStorage<T, Method>,
-                     public CallbackRunner<Params> {
- public:
-  CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
-  }
-  virtual void RunWithParams(const Params& params) {
-    // use "this->" to force C++ to look inside our templatized base class; see
-    // Effective C++, 3rd Ed, item 43, p210 for details.
-    DispatchToMethod(this->obj_, this->meth_, params);
-  }
-};
-
-// 0-arg implementation
-struct Callback0 {
-  typedef CallbackRunner<Tuple0> Type;
-};
-
-template <class T>
-typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
-  return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
-}
-
-// 1-arg implementation
-template <typename Arg1>
-struct Callback1 {
-  typedef CallbackRunner<Tuple1<Arg1> > Type;
-};
-
-template <class T, typename Arg1>
-typename Callback1<Arg1>::Type* NewCallback(T* object,
-                                            void (T::*method)(Arg1)) {
-  return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
-}
-
-// 2-arg implementation
-template <typename Arg1, typename Arg2>
-struct Callback2 {
-  typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
-};
-
-template <class T, typename Arg1, typename Arg2>
-typename Callback2<Arg1, Arg2>::Type* NewCallback(
-    T* object,
-    void (T::*method)(Arg1, Arg2)) {
-  return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
-      Tuple2<Arg1, Arg2> >(object, method);
-}
-
-// 3-arg implementation
-template <typename Arg1, typename Arg2, typename Arg3>
-struct Callback3 {
-  typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
-};
-
-template <class T, typename Arg1, typename Arg2, typename Arg3>
-typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
-    T* object,
-    void (T::*method)(Arg1, Arg2, Arg3)) {
-  return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
-      Tuple3<Arg1, Arg2, Arg3> >(object, method);
-}
-
-// 4-arg implementation
-template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-struct Callback4 {
-  typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
-};
-
-template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
-    T* object,
-    void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
-  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
-      Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
-}
-
-// 5-arg implementation
-template <typename Arg1, typename Arg2, typename Arg3,
-          typename Arg4, typename Arg5>
-struct Callback5 {
-  typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
-};
-
-template <class T, typename Arg1, typename Arg2,
-          typename Arg3, typename Arg4, typename Arg5>
-typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
-    T* object,
-    void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
-  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
-      Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
-}
-
-// An UnboundMethod is a wrapper for a method where the actual object is
-// provided at Run dispatch time.
-template <class T, class Method, class Params>
-class UnboundMethod {
- public:
-  UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
-    COMPILE_ASSERT(
-        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
-        badunboundmethodparams);
-  }
-  void Run(T* obj) const {
-    DispatchToMethod(obj, m_, p_);
-  }
  private:
-  Method m_;
-  Params p_;
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
 };
 
-// Return value implementation with no args.
-template <typename ReturnValue>
-struct CallbackWithReturnValue {
-  class Type {
-   public:
-    virtual ~Type() {}
-    virtual ReturnValue Run() = 0;
-  };
-};
-
-template <class T, typename Method, typename ReturnValue>
-class CallbackWithReturnValueImpl
-    : public CallbackStorage<T, Method>,
-      public CallbackWithReturnValue<ReturnValue>::Type {
+template <typename R, typename A1>
+class Callback<R(A1)> {
  public:
-  CallbackWithReturnValueImpl(T* obj, Method meth)
-      : CallbackStorage<T, Method>(obj, meth) {}
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&);
 
-  virtual ReturnValue Run() {
-    return (this->obj_->*(this->meth_))();
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
   }
 
- protected:
-  virtual ~CallbackWithReturnValueImpl() {}
+  R Run(const A1& a1) const {
+    return polymorphic_invoke_(invoker_storage_.get(), a1);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
 };
 
-template <class T, typename ReturnValue>
-typename CallbackWithReturnValue<ReturnValue>::Type*
-NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) {
-  return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>(
-      object, method);
-}
+template <typename R, typename A1, typename A2>
+class Callback<R(A1, A2)> {
+ public:
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
+                                const A2&);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
+  }
+
+  R Run(const A1& a1,
+        const A2& a2) const {
+    return polymorphic_invoke_(invoker_storage_.get(), a1,
+                               a2);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class Callback<R(A1, A2, A3)> {
+ public:
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
+                                const A2&,
+                                const A3&);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
+  }
+
+  R Run(const A1& a1,
+        const A2& a2,
+        const A3& a3) const {
+    return polymorphic_invoke_(invoker_storage_.get(), a1,
+                               a2,
+                               a3);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class Callback<R(A1, A2, A3, A4)> {
+ public:
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
+                                const A2&,
+                                const A3&,
+                                const A4&);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
+  }
+
+  R Run(const A1& a1,
+        const A2& a2,
+        const A3& a3,
+        const A4& a4) const {
+    return polymorphic_invoke_(invoker_storage_.get(), a1,
+                               a2,
+                               a3,
+                               a4);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class Callback<R(A1, A2, A3, A4, A5)> {
+ public:
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
+                                const A2&,
+                                const A3&,
+                                const A4&,
+                                const A5&);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
+  }
+
+  R Run(const A1& a1,
+        const A2& a2,
+        const A3& a3,
+        const A4& a4,
+        const A5& a5) const {
+    return polymorphic_invoke_(invoker_storage_.get(), a1,
+                               a2,
+                               a3,
+                               a4,
+                               a5);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class Callback<R(A1, A2, A3, A4, A5, A6)> {
+ public:
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
+                                const A2&,
+                                const A3&,
+                                const A4&,
+                                const A5&,
+                                const A6&);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
+  }
+
+  R Run(const A1& a1,
+        const A2& a2,
+        const A3& a3,
+        const A4& a4,
+        const A5& a5,
+        const A6& a6) const {
+    return polymorphic_invoke_(invoker_storage_.get(), a1,
+                               a2,
+                               a3,
+                               a4,
+                               a5,
+                               a6);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
+};
+
+
+// Syntactic sugar to make Callbacks<void(void)> easier to declare since it
+// will be used in a lot of APIs with delayed execution.
+typedef Callback<void(void)> Closure;
+
+}  // namespace base
 
 #endif  // BASE_CALLBACK_H
diff --git a/base/callback.h.pump b/base/callback.h.pump
new file mode 100644
index 0000000..9fc4b0b
--- /dev/null
+++ b/base/callback.h.pump
@@ -0,0 +1,291 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$var MAX_ARITY = 6
+
+// Copyright (c) 2011 The Chromium 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_CALLBACK_H_
+#define BASE_CALLBACK_H_
+#pragma once
+
+#include "base/callback_helpers.h"
+#include "base/callback_old.h"
+
+// New, super-duper, unified Callback system.  This will eventually replace
+// NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
+// systems currently in the Chromium code base.
+//
+// WHAT IS THIS:
+//
+// The templated Callback class is a generalized function object. Together
+// with the Bind() function in bind.h, they provide a type-safe method for
+// performing currying of arguments, and creating a "closure."
+//
+// In programing languages, a closure is a first-class function where all its
+// parameters have been bound (usually via currying).  Closures are well
+// suited for representing, and passing around a unit of delayed execution.
+// They are used in Chromium code to schedule tasks on different MessageLoops.
+//
+//
+// MEMORY MANAGEMENT AND PASSING
+//
+// The Callback objects themselves should be passed by const-reference, and
+// stored by copy. They internally store their state via a refcounted class
+// and thus do not need to be deleted.
+//
+// The reason to pass via a const-reference is to avoid unnecessary
+// AddRef/Release pairs to the internal state.
+//
+//
+// EXAMPLE USAGE:
+//
+// /* Binding a normal function. */
+// int Return5() { return 5; }
+// base::Callback<int(int)> func_cb = base::Bind(&Return5);
+// LOG(INFO) << func_cb.Run(5);  // Prints 5.
+//
+// void PrintHi() { LOG(INFO) << "hi."; }
+// base::Closure void_func_cb = base::Bind(&PrintHi);
+// LOG(INFO) << void_func_cb.Run();  // Prints: hi.
+//
+// /* Binding a class method. */
+// class Ref : public RefCountedThreadSafe<Ref> {
+//  public:
+//   int Foo() { return 3; }
+//   void PrintBye() { LOG(INFO) << "bye."; }
+// };
+// scoped_refptr<Ref> ref = new Ref();
+// base::Callback<int(void)> ref_cb = base::Bind(&Ref::Foo, ref.get());
+// LOG(INFO) << ref_cb.Run();  // Prints out 3.
+//
+// base::Closure void_ref_cb = base::Bind(&Ref::PrintBye, ref.get());
+// void_ref_cb.Run();  // Prints: bye.
+//
+// /* Binding a class method in a non-refcounted class.
+//  *
+//  * WARNING: You must be sure the referee outlives the callback!
+//  *          This is particularly important if you post a closure to a
+//  *          MessageLoop because then it becomes hard to know what the
+//  *          lifetime of the referee needs to be.
+//  */
+// class NoRef {
+//  public:
+//   int Foo() { return 4; }
+//   void PrintWhy() { LOG(INFO) << "why???"; }
+// };
+// NoRef no_ref;
+// base::Callback<int(void)> base::no_ref_cb =
+//     base::Bind(&NoRef::Foo, base::Unretained(&no_ref));
+// LOG(INFO) << ref_cb.Run();  // Prints out 4.
+//
+// base::Closure void_no_ref_cb =
+//     base::Bind(&NoRef::PrintWhy, base::Unretained(no_ref));
+// void_no_ref_cb.Run();  // Prints: why???
+//
+// /* Binding a reference. */
+// int Identity(int n) { return n; }
+// int value = 1;
+// base::Callback<int(void)> bound_copy_cb = base::Bind(&Identity, value);
+// base::Callback<int(void)> bound_ref_cb =
+//     base::Bind(&Identity, base::ConstRef(value));
+// LOG(INFO) << bound_copy_cb.Run();  // Prints 1.
+// LOG(INFO) << bound_ref_cb.Run();  // Prints 1.
+// value = 2;
+// LOG(INFO) << bound_copy_cb.Run();  // Prints 1.
+// LOG(INFO) << bound_ref_cb.Run();  // Prints 2.
+//
+//
+// WHERE IS THIS DESIGN FROM:
+//
+// The design Callback and Bind is heavily influenced by C++'s
+// tr1::function/tr1::bind, and by the "Google Callback" system used inside
+// Google.
+//
+//
+// HOW THE IMPLEMENTATION WORKS:
+//
+// There are three main components to the system:
+//   1) The Callback classes.
+//   2) The Bind() functions.
+//   3) The arguments wrappers (eg., Unretained() and ConstRef()).
+//
+// The Callback classes represent a generic function pointer. Internally,
+// it stores a refcounted piece of state that represents the target function
+// and all its bound parameters.  Each Callback specialization has a templated
+// constructor that takes an InvokerStorageHolder<> object.  In the context of
+// the constructor, the static type of this InvokerStorageHolder<> object
+// uniquely identifies the function it is representing, all its bound
+// parameters, and a DoInvoke() that is capable of invoking the target.
+//
+// Callback's constructor is takes the InvokerStorageHolder<> that has the
+// full static type and erases the target function type, and the bound
+// parameters.  It does this by storing a pointer to the specific DoInvoke()
+// function, and upcasting the state of InvokerStorageHolder<> to a
+// InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer
+// is only used with the stored DoInvoke() pointer.
+//
+// To create InvokerStorageHolder<> objects, we use the Bind() functions.
+// These functions, along with a set of internal templates, are reponsible for
+//
+//  - Unwrapping the function signature into return type, and parameters
+//  - Determining the number of parameters that are bound
+//  - Creating the storage for the bound parameters
+//  - Performing compile-time asserts to avoid error-prone behavior
+//  - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity
+//    matching the number of unbound parameters, and knows the correct
+//    refcounting semantics for the target object if we are binding a class
+//    method.
+//
+// The Bind functions do the above using type-inference, and template
+// specializations.
+//
+// By default Bind() will store copies of all bound parameters, and attempt
+// to refcount a target object if the function being bound is a class method.
+//
+// To change this behavior, we introduce a set of argument wrappers
+// (eg. Unretained(), and ConstRef()).  These are simple container templates
+// that are passed by value, and wrap a pointer to argument.  See the
+// file-level comment in base/bind_helpers.h for more info.
+//
+// These types are passed to the Unwrap() functions, and the MaybeRefcount()
+// functions respectively to modify the behavior of Bind().  The Unwrap()
+// and MaybeRefcount() functions change behavior by doing partial
+// specialization based on whether or not a parameter is a wrapper type.
+//
+// ConstRef() is similar to tr1::cref.  Unretained() is specific to Chromium.
+//
+//
+// WHY NOT TR1 FUNCTION/BIND?
+//
+// Direct use of tr1::function and tr1::bind was considered, but ultimately
+// rejected because of the number of copy constructors invocations involved
+// in the binding of arguments during construction, and the forwarding of
+// arguments during invocation.  These copies will no longer be an issue in
+// C++0x because C++0x will support rvalue reference allowing for the compiler
+// to avoid these copies.  However, waiting for C++0x is not an option.
+//
+// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
+// tr1::bind call itself will invoke a non-trivial copy constructor three times
+// for each bound parameter.  Also, each when passing a tr1::function, each
+// bound argument will be copied again.
+//
+// In addition to the copies taken at binding and invocation, copying a
+// tr1::function causes a copy to be made of all the bound parameters and
+// state.
+//
+// Furthermore, in Chromium, it is desirable for the Callback to take a
+// reference on a target object when representing a class method call.  This
+// is not supported by tr1.
+//
+// Lastly, tr1::function and tr1::bind has a more general and flexible API.
+// This includes things like argument reordering by use of
+// tr1::bind::placeholder, support for non-const reference parameters, and some
+// limited amount of subtyping of the tr1::function object (eg.,
+// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
+//
+// These are not features that are required in Chromium. Some of them, such as
+// allowing for reference parameters, and subtyping of functions, may actually
+// because a source of errors. Removing support for these features actually
+// allows for a simpler implementation, and a terser Currying API.
+//
+//
+// WHY NOT GOOGLE CALLBACKS?
+//
+// The Google callback system also does not support refcounting.  Furthermore,
+// its implementation has a number of strange edge cases with respect to type
+// conversion of its arguments.  In particular, the argument's constness must
+// at times match exactly the function signature, or the type-inference might
+// break.  Given the above, writing a custom solution was easier.
+//
+//
+// MISSING FUNCTIONALITY
+//  - Invoking the return of Bind.  Bind(&foo).Run() does not work;
+//  - Binding arrays to functions that take a non-const pointer.
+//    Example:
+//      void Foo(const char* ptr);
+//      void Bar(char* ptr);
+//      Bind(&Foo, "test");
+//      Bind(&Bar, "test");  // This fails because ptr is not const.
+
+namespace base {
+
+// First, we forward declare the Callback class template. This informs the
+// compiler that the template only has 1 type parameter which is the function
+// signature that the Callback is representing.
+//
+// After this, create template specializations for 0-$(MAX_ARITY) parameters. Note that
+// even though the template typelist grows, the specialization still
+// only has one type: the function signature.
+template <typename Sig>
+class Callback;
+
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$range ARG 1..ARITY
+
+$if ARITY == 0 [[
+template <typename R>
+class Callback<R(void)> {
+]] $else [[
+template <typename R, $for ARG , [[typename A$(ARG)]]>
+class Callback<R($for ARG , [[A$(ARG)]])> {
+]]
+
+ public:
+  typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*[[]]
+$if ARITY != 0 [[, ]]
+$for ARG ,
+                                [[const A$(ARG)&]]);
+
+  Callback() : polymorphic_invoke_(NULL) { }
+
+  // We pass InvokerStorageHolder by const ref to avoid incurring an
+  // unnecessary AddRef/Unref pair even though we will modify the object.
+  // We cannot use a normal reference because the compiler will warn
+  // since this is often used on a return value, which is a temporary.
+  //
+  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
+  // return the exact Callback<> type.  See base/bind.h for details.
+  template <typename T>
+  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
+      : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
+    invoker_storage_.swap(invoker_holder.invoker_storage_);
+  }
+
+
+$if ARITY == 0 [[
+  R Run(void) const {
+]] $else [[
+  R Run($for ARG ,
+        [[const A$(ARG)& a$(ARG)]]) const {
+]]
+
+    return polymorphic_invoke_(invoker_storage_.get()[[]]
+$if ARITY != 0 [[, ]]
+$for ARG ,
+                               [[a$(ARG)]]);
+  }
+
+ private:
+  scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
+  PolymorphicInvoke polymorphic_invoke_;
+};
+
+
+]]  $$ for ARITY
+
+// Syntactic sugar to make Callbacks<void(void)> easier to declare since it
+// will be used in a lot of APIs with delayed execution.
+typedef Callback<void(void)> Closure;
+
+}  // namespace base
+
+#endif  // BASE_CALLBACK_H
diff --git a/base/callback_helpers.h b/base/callback_helpers.h
new file mode 100644
index 0000000..86b0df1
--- /dev/null
+++ b/base/callback_helpers.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains utility functions and classes that help the
+// implementation, and management of the Callback objects.
+
+#ifndef BASE_CALLBACK_HELPERS_H_
+#define BASE_CALLBACK_HELPERS_H_
+#pragma once
+
+#include "base/ref_counted.h"
+
+namespace base {
+namespace internal {
+
+// InvokerStorageBase is used to provide an opaque handle that the Callback
+// class can use to represent a function object with bound arguments.  It
+// behaves as an existential type that is used by a corresponding
+// DoInvoke function to perform the function execution.  This allows
+// us to shield the Callback class from the types of the bound argument via
+// "type erasure."
+class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> {
+ protected:
+  friend class RefCountedThreadSafe<InvokerStorageBase>;
+  virtual ~InvokerStorageBase() {}
+};
+
+// This structure exists purely to pass the returned |invoker_storage_| from
+// Bind() to Callback while avoiding an extra AddRef/Release() pair.
+//
+// To do this, the constructor of Callback<> must take a const-ref.  The
+// reference must be to a const object otherwise the compiler will emit a
+// warning about taking a reference to a temporary.
+//
+// Unfortunately, this means that the internal |invoker_storage_| field must
+// be made mutable.
+template <typename T>
+struct InvokerStorageHolder {
+  explicit InvokerStorageHolder(T* invoker_storage)
+      : invoker_storage_(invoker_storage) {
+  }
+
+  mutable scoped_refptr<InvokerStorageBase> invoker_storage_;
+};
+
+template <typename T>
+InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) {
+  return InvokerStorageHolder<T>(o);
+}
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_CALLBACK_HELPERS_H_
diff --git a/base/callback_old.h b/base/callback_old.h
new file mode 100644
index 0000000..ab3927d
--- /dev/null
+++ b/base/callback_old.h
@@ -0,0 +1,254 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_CALLBACK_OLD_H_
+#define BASE_CALLBACK_OLD_H_
+#pragma once
+
+#include "base/tuple.h"
+#include "base/raw_scoped_refptr_mismatch_checker.h"
+
+// Callback --------------------------------------------------------------------
+//
+// A Callback is like a Task but with unbound parameters. It is basically an
+// object-oriented function pointer.
+//
+// Callbacks are designed to work with Tuples.  A set of helper functions and
+// classes is provided to hide the Tuple details from the consumer.  Client
+// code will generally work with the CallbackRunner base class, which merely
+// provides a Run method and is returned by the New* functions. This allows
+// users to not care which type of class implements the callback, only that it
+// has a certain number and type of arguments.
+//
+// The implementation of this is done by CallbackImpl, which inherits
+// CallbackStorage to store the data. This allows the storage of the data
+// (requiring the class type T) to be hidden from users, who will want to call
+// this regardless of the implementor's type T.
+//
+// Note that callbacks currently have no facility for cancelling or abandoning
+// them. We currently handle this at a higher level for cases where this is
+// necessary. The pointer in a callback must remain valid until the callback
+// is made.
+//
+// Like Task, the callback executor is responsible for deleting the callback
+// pointer once the callback has executed.
+//
+// Example client usage:
+//   void Object::DoStuff(int, string);
+//   Callback2<int, string>::Type* callback =
+//       NewCallback(obj, &Object::DoStuff);
+//   callback->Run(5, string("hello"));
+//   delete callback;
+// or, equivalently, using tuples directly:
+//   CallbackRunner<Tuple2<int, string> >* callback =
+//       NewCallback(obj, &Object::DoStuff);
+//   callback->RunWithParams(MakeTuple(5, string("hello")));
+//
+// There is also a 0-args version that returns a value.  Example:
+//   int Object::GetNextInt();
+//   CallbackWithReturnValue<int>::Type* callback =
+//       NewCallbackWithReturnValue(obj, &Object::GetNextInt);
+//   int next_int = callback->Run();
+//   delete callback;
+
+// Base for all Callbacks that handles storage of the pointers.
+template <class T, typename Method>
+class CallbackStorage {
+ public:
+  CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
+  }
+
+ protected:
+  T* obj_;
+  Method meth_;
+};
+
+// Interface that is exposed to the consumer, that does the actual calling
+// of the method.
+template <typename Params>
+class CallbackRunner {
+ public:
+  typedef Params TupleType;
+
+  virtual ~CallbackRunner() {}
+  virtual void RunWithParams(const Params& params) = 0;
+
+  // Convenience functions so callers don't have to deal with Tuples.
+  inline void Run() {
+    RunWithParams(Tuple0());
+  }
+
+  template <typename Arg1>
+  inline void Run(const Arg1& a) {
+    RunWithParams(Params(a));
+  }
+
+  template <typename Arg1, typename Arg2>
+  inline void Run(const Arg1& a, const Arg2& b) {
+    RunWithParams(Params(a, b));
+  }
+
+  template <typename Arg1, typename Arg2, typename Arg3>
+  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
+    RunWithParams(Params(a, b, c));
+  }
+
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
+    RunWithParams(Params(a, b, c, d));
+  }
+
+  template <typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5>
+  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
+                  const Arg4& d, const Arg5& e) {
+    RunWithParams(Params(a, b, c, d, e));
+  }
+};
+
+template <class T, typename Method, typename Params>
+class CallbackImpl : public CallbackStorage<T, Method>,
+                     public CallbackRunner<Params> {
+ public:
+  CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
+  }
+  virtual void RunWithParams(const Params& params) {
+    // use "this->" to force C++ to look inside our templatized base class; see
+    // Effective C++, 3rd Ed, item 43, p210 for details.
+    DispatchToMethod(this->obj_, this->meth_, params);
+  }
+};
+
+// 0-arg implementation
+struct Callback0 {
+  typedef CallbackRunner<Tuple0> Type;
+};
+
+template <class T>
+typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
+  return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
+}
+
+// 1-arg implementation
+template <typename Arg1>
+struct Callback1 {
+  typedef CallbackRunner<Tuple1<Arg1> > Type;
+};
+
+template <class T, typename Arg1>
+typename Callback1<Arg1>::Type* NewCallback(T* object,
+                                            void (T::*method)(Arg1)) {
+  return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
+}
+
+// 2-arg implementation
+template <typename Arg1, typename Arg2>
+struct Callback2 {
+  typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2>
+typename Callback2<Arg1, Arg2>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2)) {
+  return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
+      Tuple2<Arg1, Arg2> >(object, method);
+}
+
+// 3-arg implementation
+template <typename Arg1, typename Arg2, typename Arg3>
+struct Callback3 {
+  typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2, typename Arg3>
+typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2, Arg3)) {
+  return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
+      Tuple3<Arg1, Arg2, Arg3> >(object, method);
+}
+
+// 4-arg implementation
+template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct Callback4 {
+  typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
+  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
+      Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
+}
+
+// 5-arg implementation
+template <typename Arg1, typename Arg2, typename Arg3,
+          typename Arg4, typename Arg5>
+struct Callback5 {
+  typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2,
+          typename Arg3, typename Arg4, typename Arg5>
+typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
+  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
+      Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
+}
+
+// An UnboundMethod is a wrapper for a method where the actual object is
+// provided at Run dispatch time.
+template <class T, class Method, class Params>
+class UnboundMethod {
+ public:
+  UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
+    COMPILE_ASSERT(
+        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
+        badunboundmethodparams);
+  }
+  void Run(T* obj) const {
+    DispatchToMethod(obj, m_, p_);
+  }
+ private:
+  Method m_;
+  Params p_;
+};
+
+// Return value implementation with no args.
+template <typename ReturnValue>
+struct CallbackWithReturnValue {
+  class Type {
+   public:
+    virtual ~Type() {}
+    virtual ReturnValue Run() = 0;
+  };
+};
+
+template <class T, typename Method, typename ReturnValue>
+class CallbackWithReturnValueImpl
+    : public CallbackStorage<T, Method>,
+      public CallbackWithReturnValue<ReturnValue>::Type {
+ public:
+  CallbackWithReturnValueImpl(T* obj, Method meth)
+      : CallbackStorage<T, Method>(obj, meth) {}
+
+  virtual ReturnValue Run() {
+    return (this->obj_->*(this->meth_))();
+  }
+
+ protected:
+  virtual ~CallbackWithReturnValueImpl() {}
+};
+
+template <class T, typename ReturnValue>
+typename CallbackWithReturnValue<ReturnValue>::Type*
+NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) {
+  return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>(
+      object, method);
+}
+
+#endif  // BASE_CALLBACK_OLD_H_
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 017b869..3060306 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -85,7 +85,7 @@
 #if defined(COMPILER_MSVC)
 #define OVERRIDE override
 #elif defined(__clang__)
-#define OVERRIDE __attribute__((override))
+#define OVERRIDE override
 #else
 #define OVERRIDE
 #endif
diff --git a/base/crypto/capi_util.cc b/base/crypto/capi_util.cc
index cf47a50..ef57a3c 100644
--- a/base/crypto/capi_util.cc
+++ b/base/crypto/capi_util.cc
@@ -5,8 +5,8 @@
 #include "base/crypto/capi_util.h"
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 
 namespace {
 
@@ -18,7 +18,7 @@
 
   // Returns a lock to guard calls to CryptAcquireContext with
   // CRYPT_DELETEKEYSET or CRYPT_NEWKEYSET.
-  Lock& acquire_context_lock() {
+  base::Lock& acquire_context_lock() {
     return acquire_context_lock_;
   }
 
@@ -28,7 +28,7 @@
 
   CAPIUtilSingleton() {}
 
-  Lock acquire_context_lock_;
+  base::Lock acquire_context_lock_;
 
   DISALLOW_COPY_AND_ASSIGN(CAPIUtilSingleton);
 };
@@ -43,7 +43,7 @@
                                DWORD prov_type,
                                DWORD flags)
 {
-  AutoLock lock(CAPIUtilSingleton::GetInstance()->acquire_context_lock());
+  base::AutoLock lock(CAPIUtilSingleton::GetInstance()->acquire_context_lock());
   return CryptAcquireContext(prov, container, provider, prov_type, flags);
 }
 
diff --git a/base/crypto/crypto_module_blocking_password_delegate.h b/base/crypto/crypto_module_blocking_password_delegate.h
new file mode 100644
index 0000000..ae962a8
--- /dev/null
+++ b/base/crypto/crypto_module_blocking_password_delegate.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_
+#define BASE_CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_
+#pragma once
+
+#include <string>
+
+namespace base {
+
+// PK11_SetPasswordFunc is a global setting.  An implementation of
+// CryptoModuleBlockingPasswordDelegate should be passed as the user data
+// argument (|wincx|) to relevant NSS functions, which the global password
+// handler will call to do the actual work.
+class CryptoModuleBlockingPasswordDelegate {
+ public:
+  virtual ~CryptoModuleBlockingPasswordDelegate() {}
+
+  // Requests a password to unlock |slot_name|. The interface is
+  // synchronous because NSS cannot issue an asynchronous
+  // request. |retry| is true if this is a request for the retry
+  // and we previously returned the wrong password.
+  // The implementation should set |*cancelled| to true if the user cancelled
+  // instead of entering a password, otherwise it should return the password the
+  // user entered.
+  virtual std::string RequestPassword(const std::string& slot_name, bool retry,
+                                      bool* cancelled) = 0;
+};
+
+}
+
+#endif  // BASE_CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_
diff --git a/base/crypto/cssm_init.cc b/base/crypto/cssm_init.cc
index f588f30..570dcc3 100644
--- a/base/crypto/cssm_init.cc
+++ b/base/crypto/cssm_init.cc
@@ -7,6 +7,7 @@
 #include <Security/SecBase.h>
 
 #include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
 #include "base/singleton.h"
 #include "base/synchronization/lock.h"
 #include "base/sys_string_conversions.h"
@@ -20,16 +21,38 @@
 
 namespace {
 
+void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) {
+  return malloc(size);
+}
+
+void CSSMFree(void* mem_ptr, void* alloc_ref) {
+  free(mem_ptr);
+}
+
+void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) {
+  return realloc(ptr, size);
+}
+
+void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) {
+  return calloc(num, size);
+}
+
 class CSSMInitSingleton {
  public:
   static CSSMInitSingleton* GetInstance() {
-    return Singleton<CSSMInitSingleton>::get();
+    return Singleton<CSSMInitSingleton,
+                     LeakySingletonTraits<CSSMInitSingleton> >::get();
   }
 
-  CSSM_CSP_HANDLE csp_handle() const  {return csp_handle_;}
+  CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; }
+  CSSM_CL_HANDLE cl_handle() const { return cl_handle_; }
+  CSSM_TP_HANDLE tp_handle() const { return tp_handle_; }
 
  private:
-  CSSMInitSingleton() : inited_(false), loaded_(false), csp_handle_(NULL) {
+  CSSMInitSingleton()
+      : inited_(false), csp_loaded_(false), cl_loaded_(false),
+        tp_loaded_(false), csp_handle_(NULL), cl_handle_(NULL),
+        tp_handle_(NULL) {
     static CSSM_VERSION version = {2, 0};
     // TODO(wtc): what should our caller GUID be?
     static const CSSM_GUID test_guid = {
@@ -50,13 +73,42 @@
       NOTREACHED();
       return;
     }
-    loaded_ = true;
+    csp_loaded_ = true;
+    crtn = CSSM_ModuleLoad(
+        &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
+    if (crtn) {
+      NOTREACHED();
+      return;
+    }
+    cl_loaded_ = true;
+    crtn = CSSM_ModuleLoad(
+        &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
+    if (crtn) {
+      NOTREACHED();
+      return;
+    }
+    tp_loaded_ = true;
 
-    crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version,
-                             &base::kCssmMemoryFunctions, 0,
+    const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = {
+      CSSMMalloc,
+      CSSMFree,
+      CSSMRealloc,
+      CSSMCalloc,
+      NULL
+    };
+
+    crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0,
                              CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE,
                              NULL, 0, NULL, &csp_handle_);
     DCHECK(crtn == CSSM_OK);
+    crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions,
+                             0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE,
+                             NULL, 0, NULL, &cl_handle_);
+    DCHECK(crtn == CSSM_OK);
+    crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions,
+                             0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE,
+                             NULL, 0, NULL, &tp_handle_);
+    DCHECK(crtn == CSSM_OK);
   }
 
   ~CSSMInitSingleton() {
@@ -65,10 +117,26 @@
       CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_);
       DCHECK(crtn == CSSM_OK);
     }
-    if (loaded_) {
+    if (cl_handle_) {
+      CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_);
+      DCHECK(crtn == CSSM_OK);
+    }
+    if (tp_handle_) {
+      CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_);
+      DCHECK(crtn == CSSM_OK);
+    }
+    if (csp_loaded_) {
       crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL);
       DCHECK(crtn == CSSM_OK);
     }
+    if (cl_loaded_) {
+      crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL);
+      DCHECK(crtn == CSSM_OK);
+    }
+    if (tp_loaded_) {
+      crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL);
+      DCHECK(crtn == CSSM_OK);
+    }
     if (inited_) {
       crtn = CSSM_Terminate();
       DCHECK(crtn == CSSM_OK);
@@ -76,8 +144,12 @@
   }
 
   bool inited_;  // True if CSSM_Init has been called successfully.
-  bool loaded_;  // True if CSSM_ModuleLoad has been called successfully.
+  bool csp_loaded_;  // True if gGuidAppleCSP has been loaded
+  bool cl_loaded_;  // True if gGuidAppleX509CL has been loaded.
+  bool tp_loaded_;  // True if gGuidAppleX509TP has been loaded.
   CSSM_CSP_HANDLE csp_handle_;
+  CSSM_CL_HANDLE cl_handle_;
+  CSSM_TP_HANDLE tp_handle_;
 
   friend struct DefaultSingletonTraits<CSSMInitSingleton>;
 };
@@ -87,18 +159,17 @@
 class SecurityServicesSingleton {
  public:
   static SecurityServicesSingleton* GetInstance() {
-    return Singleton<SecurityServicesSingleton>::get();
+    return Singleton<SecurityServicesSingleton,
+                     LeakySingletonTraits<SecurityServicesSingleton> >::get();
   }
 
-  ~SecurityServicesSingleton() {}
-
   base::Lock& lock() { return lock_; }
 
  private:
-  friend class Singleton<SecurityServicesSingleton>;
   friend struct DefaultSingletonTraits<SecurityServicesSingleton>;
 
   SecurityServicesSingleton() {}
+  ~SecurityServicesSingleton() {}
 
   base::Lock lock_;
 
@@ -117,45 +188,44 @@
   return CSSMInitSingleton::GetInstance()->csp_handle();
 }
 
-void* CSSMMalloc(CSSM_SIZE size, void *alloc_ref) {
-  return malloc(size);
+CSSM_CL_HANDLE GetSharedCLHandle() {
+  return CSSMInitSingleton::GetInstance()->cl_handle();
 }
 
-void CSSMFree(void* mem_ptr, void* alloc_ref) {
-  free(mem_ptr);
+CSSM_TP_HANDLE GetSharedTPHandle() {
+  return CSSMInitSingleton::GetInstance()->tp_handle();
 }
 
-void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) {
-  return realloc(ptr, size);
+void* CSSMMalloc(CSSM_SIZE size) {
+  return ::CSSMMalloc(size, NULL);
 }
 
-void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) {
-  return calloc(num, size);
+void CSSMFree(void* ptr) {
+  ::CSSMFree(ptr, NULL);
 }
 
-const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions = {
-  CSSMMalloc,
-  CSSMFree,
-  CSSMRealloc,
-  CSSMCalloc,
-  NULL
-};
-
-void LogCSSMError(const char *fn_name, CSSM_RETURN err) {
+void LogCSSMError(const char* fn_name, CSSM_RETURN err) {
   if (!err)
     return;
-  CFStringRef cfstr = SecCopyErrorMessageString(err, NULL);
-  if (cfstr) {
-    std::string err_name = SysCFStringRefToUTF8(cfstr);
-    CFRelease(cfstr);
-    LOG(ERROR) << fn_name << " returned " << err << " (" << err_name << ")";
-  } else {
-    LOG(ERROR) << fn_name << " returned " << err;
-  }
+  base::mac::ScopedCFTypeRef<CFStringRef> cfstr(
+      SecCopyErrorMessageString(err, NULL));
+  LOG(ERROR) << fn_name << " returned " << err
+             << " (" << SysCFStringRefToUTF8(cfstr) << ")";
 }
 
 base::Lock& GetMacSecurityServicesLock() {
   return SecurityServicesSingleton::GetInstance()->lock();
 }
 
+ScopedCSSMData::ScopedCSSMData() {
+  memset(&data_, 0, sizeof(data_));
+}
+
+ScopedCSSMData::~ScopedCSSMData() {
+  if (data_.Data) {
+    CSSMFree(data_.Data);
+    data_.Data = NULL;
+  }
+}
+
 }  // namespace base
diff --git a/base/crypto/cssm_init.h b/base/crypto/cssm_init.h
index 5644d7e..b51a3b5 100644
--- a/base/crypto/cssm_init.h
+++ b/base/crypto/cssm_init.h
@@ -8,7 +8,7 @@
 
 #include <Security/cssm.h>
 
-#include "base/scoped_ptr.h"
+#include "base/basictypes.h"
 
 namespace base {
 
@@ -22,12 +22,22 @@
 // Returns the shared CSP handle used by CSSM functions.
 CSSM_CSP_HANDLE GetSharedCSPHandle();
 
+// Returns the shared CL handle used by CSSM functions.
+CSSM_CL_HANDLE GetSharedCLHandle();
+
+// Returns the shared TP handle used by CSSM functions.
+CSSM_TP_HANDLE GetSharedTPHandle();
+
 // Set of pointers to memory function wrappers that are required for CSSM
 extern const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions;
 
 // Utility function to log an error message including the error name.
 void LogCSSMError(const char *function_name, CSSM_RETURN err);
 
+// Utility functions to allocate and release CSSM memory.
+void* CSSMMalloc(CSSM_SIZE size);
+void CSSMFree(void* ptr);
+
 // The OS X certificate and key management wrappers over CSSM are not
 // thread-safe. In particular, code that accesses the CSSM database is
 // problematic.
@@ -35,6 +45,25 @@
 // http://developer.apple.com/mac/library/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html
 Lock& GetMacSecurityServicesLock();
 
+// Wrapper class for CSSM_DATA type. This should only be used when using the
+// CL/TP/CSP handles from above, since that's the only time we're guaranteed (or
+// supposed to be guaranteed) that our memory management functions will be used.
+// Apple's Sec* APIs manage their own memory so it shouldn't be used for those.
+// The constructor initializes data_ to zero and the destructor releases the
+// data properly.
+class ScopedCSSMData {
+ public:
+  ScopedCSSMData();
+  ~ScopedCSSMData();
+  operator CSSM_DATA*() { return &data_; }
+  CSSM_DATA* operator ->() { return &data_; }
+
+ private:
+  CSSM_DATA data_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedCSSMData);
+};
+
 }  // namespace base
 
 #endif  // BASE_CRYPTO_CSSM_INIT_H_
diff --git a/base/crypto/rsa_private_key.cc b/base/crypto/rsa_private_key.cc
index 75da7e4..024f741 100644
--- a/base/crypto/rsa_private_key.cc
+++ b/base/crypto/rsa_private_key.cc
@@ -4,6 +4,7 @@
 
 #include "base/crypto/rsa_private_key.h"
 
+#include <algorithm>
 #include <list>
 
 #include "base/logging.h"
@@ -48,6 +49,232 @@
   0x05, 0x00
 };
 
+PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
+    : big_endian_(big_endian) {}
+
+PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
+
+bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) {
+  std::list<uint8> content;
+
+  // Version (always zero)
+  uint8 version = 0;
+
+  PrependInteger(coefficient_, &content);
+  PrependInteger(exponent2_, &content);
+  PrependInteger(exponent1_, &content);
+  PrependInteger(prime2_, &content);
+  PrependInteger(prime1_, &content);
+  PrependInteger(private_exponent_, &content);
+  PrependInteger(public_exponent_, &content);
+  PrependInteger(modulus_, &content);
+  PrependInteger(&version, 1, &content);
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+  PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
+
+  // RSA algorithm OID
+  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
+    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
+
+  PrependInteger(&version, 1, &content);
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+
+  // Copy everying into the output.
+  output->reserve(content.size());
+  for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
+    output->push_back(*i);
+
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) {
+  // Create a sequence with the modulus (n) and public exponent (e).
+  std::vector<uint8> bit_string;
+  if (!ExportPublicKey(&bit_string))
+    return false;
+
+  // Add the sequence as the contents of a bit string.
+  std::list<uint8> content;
+  PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
+                   &content);
+
+  // Add the RSA algorithm OID.
+  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
+    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
+
+  // Finally, wrap everything in a sequence.
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+
+  // Copy everything into the output.
+  output->reserve(content.size());
+  for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
+    output->push_back(*i);
+
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8>* output) {
+  // Create a sequence with the modulus (n) and public exponent (e).
+  std::list<uint8> content;
+  PrependInteger(&public_exponent_[0],
+                 static_cast<int>(public_exponent_.size()),
+                 &content);
+  PrependInteger(&modulus_[0],  static_cast<int>(modulus_.size()), &content);
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+
+  // Copy everything into the output.
+  output->reserve(content.size());
+  for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
+    output->push_back(*i);
+
+  return true;
+}
+
+bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) {
+  if (input.empty()) {
+    return false;
+  }
+
+  // Parse the private key info up to the public key values, ignoring
+  // the subsequent private key values.
+  uint8* src = const_cast<uint8*>(&input.front());
+  uint8* end = src + input.size();
+  if (!ReadSequence(&src, end) ||
+      !ReadVersion(&src, end) ||
+      !ReadAlgorithmIdentifier(&src, end) ||
+      !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
+      !ReadSequence(&src, end) ||
+      !ReadVersion(&src, end) ||
+      !ReadInteger(&src, end, &modulus_))
+    return false;
+
+  int mod_size = modulus_.size();
+  READ_ASSERT(mod_size % 2 == 0);
+  int primes_size = mod_size / 2;
+
+  if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
+      !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
+    return false;
+
+  READ_ASSERT(src == end);
+
+
+  return true;
+}
+
+void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8>& in,
+                                         std::list<uint8>* out) {
+  uint8* ptr = const_cast<uint8*>(&in.front());
+  PrependIntegerImpl(ptr, in.size(), out, big_endian_);
+}
+
+// Helper to prepend an ASN.1 integer.
+void PrivateKeyInfoCodec::PrependInteger(uint8* val,
+                                         int num_bytes,
+                                         std::list<uint8>* data) {
+  PrependIntegerImpl(val, num_bytes, data, big_endian_);
+}
+
+void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val,
+                                             int num_bytes,
+                                             std::list<uint8>* data,
+                                             bool big_endian) {
+ // Reverse input if little-endian.
+ std::vector<uint8> tmp;
+ if (!big_endian) {
+   tmp.assign(val, val + num_bytes);
+   reverse(tmp.begin(), tmp.end());
+   val = &tmp.front();
+ }
+
+  // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
+  // from the most-significant end of the integer.
+  int start = 0;
+  while (start < (num_bytes - 1) && val[start] == 0x00) {
+    start++;
+    num_bytes--;
+  }
+  PrependBytes(val, start, num_bytes, data);
+
+  // ASN.1 integers are signed. To encode a positive integer whose sign bit
+  // (the most significant bit) would otherwise be set and make the number
+  // negative, ASN.1 requires a leading null byte to force the integer to be
+  // positive.
+  uint8 front = data->front();
+  if ((front & 0x80) != 0) {
+    data->push_front(0x00);
+    num_bytes++;
+  }
+
+  PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
+}
+
+bool PrivateKeyInfoCodec::ReadInteger(uint8** pos,
+                                      uint8* end,
+                                      std::vector<uint8>* out) {
+  return ReadIntegerImpl(pos, end, out, big_endian_);
+}
+
+bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos,
+                                                      uint8* end,
+                                                      size_t expected_size,
+                                                      std::vector<uint8>* out) {
+  std::vector<uint8> temp;
+  if (!ReadIntegerImpl(pos, end, &temp, true))  // Big-Endian
+    return false;
+
+  int pad = expected_size - temp.size();
+  int index = 0;
+  if (out->size() == expected_size + 1) {
+    READ_ASSERT(out->front() == 0x00);
+    pad++;
+    index++;
+  } else {
+    READ_ASSERT(out->size() <= expected_size);
+  }
+
+  while (pad) {
+    out->push_back(0x00);
+    pad--;
+  }
+  out->insert(out->end(), temp.begin(), temp.end());
+
+  // Reverse output if little-endian.
+  if (!big_endian_)
+    reverse(out->begin(), out->end());
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos,
+                                          uint8* end,
+                                          std::vector<uint8>* out,
+                                          bool big_endian) {
+  uint32 length = 0;
+  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
+    return false;
+
+  // The first byte can be zero to force positiveness. We can ignore this.
+  if (**pos == 0x00) {
+    ++(*pos);
+    --length;
+  }
+
+  if (length)
+    out->insert(out->end(), *pos, (*pos) + length);
+
+  (*pos) += length;
+
+  // Reverse output if little-endian.
+  if (!big_endian)
+    reverse(out->begin(), out->end());
+  return true;
+}
+
 void PrivateKeyInfoCodec::PrependBytes(uint8* val,
                                        int start,
                                        int num_bytes,
@@ -160,220 +387,4 @@
   return true;
 }
 
-PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
-    : big_endian_(big_endian) {}
-
-PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
-
-bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) {
-  std::list<uint8> content;
-
-  // Version (always zero)
-  uint8 version = 0;
-
-  PrependInteger(coefficient_, &content);
-  PrependInteger(exponent2_, &content);
-  PrependInteger(exponent1_, &content);
-  PrependInteger(prime2_, &content);
-  PrependInteger(prime1_, &content);
-  PrependInteger(private_exponent_, &content);
-  PrependInteger(public_exponent_, &content);
-  PrependInteger(modulus_, &content);
-  PrependInteger(&version, 1, &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-  PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
-
-  // RSA algorithm OID
-  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
-    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
-
-  PrependInteger(&version, 1, &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everying into the output.
-  output->reserve(content.size());
-  for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
-    output->push_back(*i);
-
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) {
-  // Create a sequence with the modulus (n) and public exponent (e).
-  std::list<uint8> content;
-  PrependInteger(&public_exponent_[0],
-                 static_cast<int>(public_exponent_.size()),
-                 &content);
-  PrependInteger(&modulus_[0],  static_cast<int>(modulus_.size()), &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy the sequence with n and e into a buffer.
-  std::vector<uint8> bit_string;
-  for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
-    bit_string.push_back(*i);
-  content.clear();
-  // Add the sequence as the contents of a bit string.
-  PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
-                   &content);
-
-  // Add the RSA algorithm OID.
-  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
-    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
-
-  // Finally, wrap everything in a sequence.
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everything into the output.
-  output->reserve(content.size());
-  for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
-    output->push_back(*i);
-
-  return true;
-}
-
-bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) {
-  if (input.empty()) {
-    return false;
-  }
-
-  // Parse the private key info up to the public key values, ignoring
-  // the subsequent private key values.
-  uint8* src = const_cast<uint8*>(&input.front());
-  uint8* end = src + input.size();
-  if (!ReadSequence(&src, end) ||
-      !ReadVersion(&src, end) ||
-      !ReadAlgorithmIdentifier(&src, end) ||
-      !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
-      !ReadSequence(&src, end) ||
-      !ReadVersion(&src, end) ||
-      !ReadInteger(&src, end, &modulus_))
-    return false;
-
-  int mod_size = modulus_.size();
-  READ_ASSERT(mod_size % 2 == 0);
-  int primes_size = mod_size / 2;
-
-  if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
-      !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
-    return false;
-
-  READ_ASSERT(src == end);
-
-
-  return true;
-}
-
-void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8>& in,
-                                         std::list<uint8>* out) {
-  uint8* ptr = const_cast<uint8*>(&in.front());
-  PrependIntegerImpl(ptr, in.size(), out, big_endian_);
-}
-
-// Helper to prepend an ASN.1 integer.
-void PrivateKeyInfoCodec::PrependInteger(uint8* val,
-                                         int num_bytes,
-                                         std::list<uint8>* data) {
-  PrependIntegerImpl(val, num_bytes, data, big_endian_);
-}
-
-void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val,
-                                             int num_bytes,
-                                             std::list<uint8>* data,
-                                             bool big_endian) {
- // Reverse input if little-endian.
- std::vector<uint8> tmp;
- if (!big_endian) {
-   tmp.assign(val, val + num_bytes);
-   reverse(tmp.begin(), tmp.end());
-   val = &tmp.front();
- }
-
-  // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
-  // from the most-significant end of the integer.
-  int start = 0;
-  while (start < (num_bytes - 1) && val[start] == 0x00) {
-    start++;
-    num_bytes--;
-  }
-  PrependBytes(val, start, num_bytes, data);
-
-  // ASN.1 integers are signed. To encode a positive integer whose sign bit
-  // (the most significant bit) would otherwise be set and make the number
-  // negative, ASN.1 requires a leading null byte to force the integer to be
-  // positive.
-  uint8 front = data->front();
-  if ((front & 0x80) != 0) {
-    data->push_front(0x00);
-    num_bytes++;
-  }
-
-  PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
-}
-
-bool PrivateKeyInfoCodec::ReadInteger(uint8** pos,
-                                      uint8* end,
-                                      std::vector<uint8>* out) {
-  return ReadIntegerImpl(pos, end, out, big_endian_);
-}
-
-bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos,
-                                          uint8* end,
-                                          std::vector<uint8>* out,
-                                          bool big_endian) {
-  uint32 length = 0;
-  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
-    return false;
-
-  // The first byte can be zero to force positiveness. We can ignore this.
-  if (**pos == 0x00) {
-    ++(*pos);
-    --length;
-  }
-
-  if (length)
-    out->insert(out->end(), *pos, (*pos) + length);
-
-  (*pos) += length;
-
-  // Reverse output if little-endian.
-  if (!big_endian)
-    reverse(out->begin(), out->end());
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos,
-                                                      uint8* end,
-                                                      size_t expected_size,
-                                                      std::vector<uint8>* out) {
-  std::vector<uint8> temp;
-  if (!ReadIntegerImpl(pos, end, &temp, true))  // Big-Endian
-    return false;
-
-  int pad = expected_size - temp.size();
-  int index = 0;
-  if (out->size() == expected_size + 1) {
-    READ_ASSERT(out->front() == 0x00);
-    pad++;
-    index++;
-  } else {
-    READ_ASSERT(out->size() <= expected_size);
-  }
-
-  while (pad) {
-    out->push_back(0x00);
-    pad--;
-  }
-  out->insert(out->end(), temp.begin(), temp.end());
-
-  // Reverse output if little-endian.
-  if (!big_endian_)
-    reverse(out->begin(), out->end());
-  return true;
-}
-
 }  // namespace base
diff --git a/base/crypto/rsa_private_key.h b/base/crypto/rsa_private_key.h
index 9b8b4fd..5357adc 100644
--- a/base/crypto/rsa_private_key.h
+++ b/base/crypto/rsa_private_key.h
@@ -64,6 +64,10 @@
   // of the PublicKeyInfo structure to |output|.
   bool ExportPublicKeyInfo(std::vector<uint8>* output);
 
+  // Exports the contents of the integer components to the ASN.1 DER encoding
+  // of the RSAPublicKey structure to |output|.
+  bool ExportPublicKey(std::vector<uint8>* output);
+
   // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input|
   // and populates the integer components with |big_endian_| byte-significance.
   // IMPORTANT NOTE: This is currently *not* security-approved for importing
@@ -215,6 +219,7 @@
   HCRYPTKEY key() { return key_; }
 #elif defined(OS_MACOSX)
   CSSM_KEY_PTR key() { return &key_; }
+  CSSM_KEY_PTR public_key() { return &public_key_; }
 #endif
 
   // Exports the private key to a PKCS #1 PrivateKey block.
@@ -257,6 +262,7 @@
   ScopedHCRYPTKEY key_;
 #elif defined(OS_MACOSX)
   CSSM_KEY key_;
+  CSSM_KEY public_key_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey);
diff --git a/base/crypto/rsa_private_key_mac.cc b/base/crypto/rsa_private_key_mac.cc
index e46e93e..ede8014 100644
--- a/base/crypto/rsa_private_key_mac.cc
+++ b/base/crypto/rsa_private_key_mac.cc
@@ -26,14 +26,12 @@
     return NULL;
   }
 
-  CSSM_KEY public_key;
-  memset(&public_key, 0, sizeof(CSSM_KEY));
   CSSM_DATA label = { 9,
       const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) };
   crtn = CSSM_GenerateKeyPair(cc_handle,
       CSSM_KEYUSE_VERIFY,
       CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label,
-      &public_key, CSSM_KEYUSE_SIGN,
+      result->public_key(), CSSM_KEYUSE_SIGN,
       CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL,
       result->key());
   CSSM_DeleteContext(cc_handle);
@@ -42,9 +40,6 @@
     return NULL;
   }
 
-  // Public key is not needed.
-  CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key, CSSM_FALSE);
-
   return result.release();
 }
 
@@ -106,6 +101,46 @@
     return NULL;
   }
 
+  // Extract a public key from the private key.
+  // Apple doesn't accept CSSM_KEYBLOB_RAW_FORMAT_X509 as a valid key
+  // format when attempting to generate certs, so use PKCS1 instead.
+  PrivateKeyInfoCodec codec(true);
+  std::vector<uint8> private_key_data;
+  private_key_data.assign(key.KeyData.Data,
+                          key.KeyData.Data + key.KeyData.Length);
+  if (!codec.Import(private_key_data)) {
+    return NULL;
+  }
+  std::vector<uint8> public_key_data;
+  if (!codec.ExportPublicKey(&public_key_data)) {
+    return NULL;
+  }
+
+  CSSM_KEY* public_key = result->public_key();
+  size_t size = public_key_data.size();
+  public_key->KeyData.Data = reinterpret_cast<uint8*>(CSSMMalloc(size));
+  if (!public_key->KeyData.Data) {
+    NOTREACHED() << "CSSMMalloc failed";
+    return NULL;
+  }
+  memcpy(public_key->KeyData.Data, &public_key_data.front(), size);
+  public_key->KeyData.Length = size;
+  public_key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
+  public_key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
+  public_key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
+  public_key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
+  public_key->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
+  public_key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
+  public_key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
+
+  crtn = CSSM_QueryKeySizeInBits(
+      base::GetSharedCSPHandle(), NULL, public_key, &key_size);
+  if (crtn) {
+    DLOG(ERROR) << "CSSM_QueryKeySizeInBits failed " << crtn;
+    return NULL;
+  }
+  public_key->KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
+
   return result.release();
 }
 
@@ -125,6 +160,7 @@
 
 RSAPrivateKey::RSAPrivateKey() {
   memset(&key_, 0, sizeof(key_));
+  memset(&public_key_, 0, sizeof(public_key_));
 
   EnsureCSSMInit();
 }
@@ -133,6 +169,9 @@
   if (key_.KeyData.Data) {
     CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE);
   }
+  if (public_key_.KeyData.Data) {
+    CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key_, CSSM_FALSE);
+  }
 }
 
 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) {
diff --git a/base/crypto/rsa_private_key_nss.cc b/base/crypto/rsa_private_key_nss.cc
index 7786521..202aa1d 100644
--- a/base/crypto/rsa_private_key_nss.cc
+++ b/base/crypto/rsa_private_key_nss.cc
@@ -41,28 +41,11 @@
 
 namespace base {
 
-// static
-RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits,
-                                               bool permanent,
-                                               bool sensitive) {
-  base::EnsureNSSInit();
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  PK11SlotInfo *slot = GetDefaultNSSKeySlot();
-  if (!slot)
-    return NULL;
-
-  PK11RSAGenParams param;
-  param.keySizeInBits = num_bits;
-  param.pe = 65537L;
-  result->key_ = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &param,
-      &result->public_key_, permanent, sensitive, NULL);
-  PK11_FreeSlot(slot);
-  if (!result->key_)
-    return NULL;
-
-  return result.release();
+RSAPrivateKey::~RSAPrivateKey() {
+  if (key_)
+    SECKEY_DestroyPrivateKey(key_);
+  if (public_key_)
+    SECKEY_DestroyPublicKey(public_key_);
 }
 
 // static
@@ -80,41 +63,6 @@
 }
 
 // static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
-    const std::vector<uint8>& input, bool permanent, bool sensitive) {
-  // This method currently leaks some memory.
-  // See http://crbug.com/34742.
-  ANNOTATE_SCOPED_MEMORY_LEAK;
-  base::EnsureNSSInit();
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  PK11SlotInfo *slot = GetDefaultNSSKeySlot();
-  if (!slot)
-    return NULL;
-
-  SECItem der_private_key_info;
-  der_private_key_info.data = const_cast<unsigned char*>(&input.front());
-  der_private_key_info.len = input.size();
-  SECStatus rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(slot,
-      &der_private_key_info, NULL, NULL, permanent, sensitive,
-      KU_DIGITAL_SIGNATURE, &result->key_, NULL);
-  PK11_FreeSlot(slot);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  result->public_key_ = SECKEY_ConvertToPublicKey(result->key_);
-  if (!result->public_key_) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return result.release();
-}
-
-// static
 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
     const std::vector<uint8>& input) {
   return CreateFromPrivateKeyInfoWithParams(input,
@@ -193,16 +141,6 @@
   return result.release();
 }
 
-RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
-  EnsureNSSInit();
-}
-
-RSAPrivateKey::~RSAPrivateKey() {
-  if (key_)
-    SECKEY_DestroyPrivateKey(key_);
-  if (public_key_)
-    SECKEY_DestroyPublicKey(public_key_);
-}
 
 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) {
   PrivateKeyInfoCodec private_key_info(true);
@@ -240,4 +178,71 @@
   return true;
 }
 
+RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
+  EnsureNSSInit();
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits,
+                                               bool permanent,
+                                               bool sensitive) {
+  base::EnsureNSSInit();
+
+  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
+
+  PK11SlotInfo *slot = GetDefaultNSSKeySlot();
+  if (!slot)
+    return NULL;
+
+  PK11RSAGenParams param;
+  param.keySizeInBits = num_bits;
+  param.pe = 65537L;
+  result->key_ = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &param,
+      &result->public_key_, permanent, sensitive, NULL);
+  PK11_FreeSlot(slot);
+  if (!result->key_)
+    return NULL;
+
+  return result.release();
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
+    const std::vector<uint8>& input, bool permanent, bool sensitive) {
+  // This method currently leaks some memory.
+  // See http://crbug.com/34742.
+  ANNOTATE_SCOPED_MEMORY_LEAK;
+  base::EnsureNSSInit();
+
+  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
+
+  PK11SlotInfo *slot = GetDefaultNSSKeySlot();
+  if (!slot)
+    return NULL;
+
+  SECItem der_private_key_info;
+  der_private_key_info.data = const_cast<unsigned char*>(&input.front());
+  der_private_key_info.len = input.size();
+  // Allow the private key to be used for key unwrapping, data decryption,
+  // and signature generation.
+  const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
+                                 KU_DIGITAL_SIGNATURE;
+  SECStatus rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
+      slot, &der_private_key_info, NULL, NULL, permanent, sensitive,
+      key_usage, &result->key_, NULL);
+  PK11_FreeSlot(slot);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return NULL;
+  }
+
+  result->public_key_ = SECKEY_ConvertToPublicKey(result->key_);
+  if (!result->public_key_) {
+    NOTREACHED();
+    return NULL;
+  }
+
+  return result.release();
+}
+
 }  // namespace base
diff --git a/base/crypto/secure_hash.h b/base/crypto/secure_hash.h
new file mode 100644
index 0000000..3759218
--- /dev/null
+++ b/base/crypto/secure_hash.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_CRYPTO_SECURE_HASH_H_
+#define BASE_CRYPTO_SECURE_HASH_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+namespace base {
+
+// A wrapper to calculate secure hashes incrementally, allowing to
+// be used when the full input is not known in advance.
+class SecureHash {
+ public:
+  enum Algorithm {
+    SHA256,
+  };
+  virtual ~SecureHash() {}
+
+  static SecureHash* Create(Algorithm type);
+
+  virtual void Update(const void* input, size_t len) = 0;
+  virtual void Finish(void* output, size_t len) = 0;
+
+ protected:
+  SecureHash() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SecureHash);
+};
+
+}  // namespace base
+
+#endif  // BASE_CRYPTO_SECURE_HASH_H_
diff --git a/base/crypto/secure_hash_default.cc b/base/crypto/secure_hash_default.cc
new file mode 100644
index 0000000..436867e
--- /dev/null
+++ b/base/crypto/secure_hash_default.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/crypto/secure_hash.h"
+
+#include "base/logging.h"
+#include "base/third_party/nss/blapi.h"
+#include "base/third_party/nss/sha256.h"
+
+namespace base {
+
+namespace {
+
+class SecureHashSHA256NSS : public SecureHash {
+ public:
+  SecureHashSHA256NSS() {
+    SHA256_Begin(&ctx_);
+  }
+
+  virtual ~SecureHashSHA256NSS() {
+  }
+
+  virtual void Update(const void* input, size_t len) {
+    SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len);
+  }
+
+  virtual void Finish(void* output, size_t len) {
+    SHA256_End(&ctx_, static_cast<unsigned char*>(output), NULL,
+               static_cast<unsigned int>(len));
+  }
+
+ private:
+  SHA256Context ctx_;
+};
+
+}  // namespace
+
+SecureHash* SecureHash::Create(Algorithm algorithm) {
+  switch (algorithm) {
+    case SHA256:
+      return new SecureHashSHA256NSS();
+    default:
+      NOTIMPLEMENTED();
+      return NULL;
+  }
+}
+
+}  // namespace base
diff --git a/base/crypto/secure_hash_openssl.cc b/base/crypto/secure_hash_openssl.cc
new file mode 100644
index 0000000..8087279
--- /dev/null
+++ b/base/crypto/secure_hash_openssl.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/crypto/secure_hash.h"
+
+#include <openssl/ssl.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/openssl_util.h"
+
+namespace base {
+
+namespace {
+
+class SecureHashSHA256OpenSSL : public SecureHash {
+ public:
+  SecureHashSHA256OpenSSL() {
+    SHA256_Init(&ctx_);
+  }
+
+  virtual ~SecureHashSHA256OpenSSL() {
+    OPENSSL_cleanse(&ctx_, sizeof(ctx_));
+  }
+
+  virtual void Update(const void* input, size_t len) {
+    SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len);
+  }
+
+  virtual void Finish(void* output, size_t len) {
+    ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result(
+        static_cast<unsigned char*>(output), len);
+    SHA256_Final(result.safe_buffer(), &ctx_);
+  }
+
+ private:
+  SHA256_CTX ctx_;
+};
+
+}  // namespace
+
+SecureHash* SecureHash::Create(Algorithm algorithm) {
+  switch (algorithm) {
+    case SHA256:
+      return new SecureHashSHA256OpenSSL();
+    default:
+      NOTIMPLEMENTED();
+      return NULL;
+  }
+}
+
+}  // namespace base
diff --git a/base/crypto/secure_hash_unittest.cc b/base/crypto/secure_hash_unittest.cc
new file mode 100644
index 0000000..2dac928
--- /dev/null
+++ b/base/crypto/secure_hash_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/crypto/secure_hash.h"
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/sha2.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(SecureHashTest, TestUpdate) {
+  // Example B.3 from FIPS 180-2: long message.
+  std::string input3(500000, 'a');  // 'a' repeated half a million times
+  int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c,
+                      0x99, 0x14, 0xfb, 0x92,
+                      0x81, 0xa1, 0xc7, 0xe2,
+                      0x84, 0xd7, 0x3e, 0x67,
+                      0xf1, 0x80, 0x9a, 0x48,
+                      0xa4, 0x97, 0x20, 0x0e,
+                      0x04, 0x6d, 0x39, 0xcc,
+                      0xc7, 0x11, 0x2c, 0xd0 };
+
+  uint8 output3[base::SHA256_LENGTH];
+
+  scoped_ptr<base::SecureHash> ctx(base::SecureHash::Create(
+      base::SecureHash::SHA256));
+  ctx->Update(input3.data(), input3.size());
+  ctx->Update(input3.data(), input3.size());
+
+  ctx->Finish(output3, sizeof(output3));
+  for (size_t i = 0; i < base::SHA256_LENGTH; i++)
+    EXPECT_EQ(expected3[i], static_cast<int>(output3[i]));
+}
diff --git a/base/crypto/signature_creator_mac.cc b/base/crypto/signature_creator_mac.cc
index d10d54c..1001c64 100644
--- a/base/crypto/signature_creator_mac.cc
+++ b/base/crypto/signature_creator_mac.cc
@@ -59,19 +59,15 @@
 }
 
 bool SignatureCreator::Final(std::vector<uint8>* signature) {
-  CSSM_DATA sig;
-  memset(&sig, 0, sizeof(CSSM_DATA)); // Allow CSSM allocate memory;
-  CSSM_RETURN crtn = CSSM_SignDataFinal(sig_handle_, &sig);
+  ScopedCSSMData sig;
+  CSSM_RETURN crtn = CSSM_SignDataFinal(sig_handle_, sig);
 
   if (crtn) {
     NOTREACHED();
     return false;
   }
 
-  signature->assign(sig.Data, sig.Data + sig.Length);
-  kCssmMemoryFunctions.free_func(sig.Data, NULL); // Release data alloc'd
-                                                  // by CSSM
-
+  signature->assign(sig->Data, sig->Data + sig->Length);
   return true;
 }
 
diff --git a/base/crypto/signature_creator_nss.cc b/base/crypto/signature_creator_nss.cc
index ff1d271..4cc2c10 100644
--- a/base/crypto/signature_creator_nss.cc
+++ b/base/crypto/signature_creator_nss.cc
@@ -14,6 +14,13 @@
 
 namespace base {
 
+SignatureCreator::~SignatureCreator() {
+  if (sign_context_) {
+    SGN_DestroyContext(sign_context_, PR_TRUE);
+    sign_context_ = NULL;
+  }
+}
+
 // static
 SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
   scoped_ptr<SignatureCreator> result(new SignatureCreator);
@@ -35,17 +42,6 @@
   return result.release();
 }
 
-SignatureCreator::SignatureCreator() : sign_context_(NULL) {
-  EnsureNSSInit();
-}
-
-SignatureCreator::~SignatureCreator() {
-  if (sign_context_) {
-    SGN_DestroyContext(sign_context_, PR_TRUE);
-    sign_context_ = NULL;
-  }
-}
-
 bool SignatureCreator::Update(const uint8* data_part, int data_part_len) {
   // TODO(wtc): Remove this const_cast when we require NSS 3.12.5.
   // See NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=518255
@@ -73,4 +69,8 @@
   return true;
 }
 
+SignatureCreator::SignatureCreator() : sign_context_(NULL) {
+  EnsureNSSInit();
+}
+
 }  // namespace base
diff --git a/base/crypto/symmetric_key_nss.cc b/base/crypto/symmetric_key_nss.cc
index d291e8d..1e3551d 100644
--- a/base/crypto/symmetric_key_nss.cc
+++ b/base/crypto/symmetric_key_nss.cc
@@ -12,10 +12,6 @@
 
 namespace base {
 
-SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) {
-  DCHECK(key);
-}
-
 SymmetricKey::~SymmetricKey() {}
 
 // static
@@ -124,4 +120,8 @@
   return true;
 }
 
+SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) {
+  DCHECK(key);
+}
+
 }  // namespace base
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc
index b865e65..2eacaf9 100644
--- a/base/debug/debugger_posix.cc
+++ b/base/debug/debugger_posix.cc
@@ -174,6 +174,9 @@
 
 void BreakDebugger() {
   DEBUG_BREAK();
+#if defined(NDEBUG)
+  _exit(1);
+#endif
 }
 
 }  // namespace debug
diff --git a/base/debug/debugger_win.cc b/base/debug/debugger_win.cc
index 3323b61..b13dbfd 100644
--- a/base/debug/debugger_win.cc
+++ b/base/debug/debugger_win.cc
@@ -105,6 +105,9 @@
   if (IsDebugUISuppressed())
     _exit(1);
   __debugbreak();
+#if defined(NDEBUG)
+  _exit(1);
+#endif
 }
 
 }  // namespace debug
diff --git a/base/debug/profiler.cc b/base/debug/profiler.cc
new file mode 100644
index 0000000..8597dac
--- /dev/null
+++ b/base/debug/profiler.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/profiler.h"
+
+#include <string>
+
+#include "base/process_util.h"
+#include "base/string_util.h"
+
+#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
+#include "third_party/tcmalloc/chromium/src/google/profiler.h"
+#endif
+
+namespace base {
+namespace debug {
+
+#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
+
+static int profile_count = 0;
+
+void StartProfiling(const std::string& name) {
+  ++profile_count;
+  std::string full_name(name);
+  std::string pid = StringPrintf("%d", GetCurrentProcId());
+  std::string count = StringPrintf("%d", profile_count);
+  ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
+  ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
+  ProfilerStart(full_name.c_str());
+}
+
+void StopProfiling() {
+  ProfilerFlush();
+  ProfilerStop();
+}
+
+void FlushProfiling() {
+  ProfilerFlush();
+}
+
+bool BeingProfiled() {
+  return ProfilingIsEnabledForAllThreads();
+}
+
+#else
+
+void StartProfiling(const std::string& name) {
+}
+
+void StopProfiling() {
+}
+
+void FlushProfiling() {
+}
+
+bool BeingProfiled() {
+  return false;
+}
+
+#endif
+
+}  // namespace debug
+}  // namespace base
+
diff --git a/base/debug/profiler.h b/base/debug/profiler.h
new file mode 100644
index 0000000..e3044d6
--- /dev/null
+++ b/base/debug/profiler.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 The Chromium 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_DEBUG_PROFILER_H
+#define BASE_DEBUG_PROFILER_H
+#pragma once
+
+#include <string>
+
+// The Profiler functions allow usage of the underlying sampling based
+// profiler. If the application has not been built with the necessary
+// flags (-DENABLE_PROFILING and not -DNO_TCMALLOC) then these functions
+// are noops.
+namespace base {
+namespace debug {
+
+// Start profiling with the supplied name.
+// {pid} will be replaced by the process' pid and {count} will be replaced
+// by the count of the profile run (starts at 1 with each process).
+void StartProfiling(const std::string& name);
+
+// Stop profiling and write out data.
+void StopProfiling();
+
+// Force data to be written to file.
+void FlushProfiling();
+
+// Returns true if process is being profiled.
+bool BeingProfiled();
+
+}  // namespace debug
+}  // namespace base
+
+#endif  // BASE_DEBUG_DEBUGGER_H
diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc
index 6f4ad02..510d35b 100644
--- a/base/debug/stack_trace_win.cc
+++ b/base/debug/stack_trace_win.cc
@@ -10,9 +10,9 @@
 #include <iostream>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 namespace debug {
@@ -59,7 +59,7 @@
   void OutputTraceToStream(const void* const* trace,
                            int count,
                            std::ostream* os) {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
 
     for (size_t i = 0; (i < count) && os->good(); ++i) {
       const int kMaxNameLength = 256;
@@ -129,7 +129,7 @@
   }
 
   DWORD init_error_;
-  Lock lock_;
+  base::Lock lock_;
   DISALLOW_COPY_AND_ASSIGN(SymbolContext);
 };
 
diff --git a/base/debug/trace_event.cc b/base/debug/trace_event.cc
index f50422c..36a3944 100644
--- a/base/debug/trace_event.cc
+++ b/base/debug/trace_event.cc
@@ -28,22 +28,6 @@
 static const FilePath::CharType* kLogFileName =
     FILE_PATH_LITERAL("trace_%d.log");
 
-TraceLog::TraceLog() : enabled_(false), log_file_(NULL) {
-  base::ProcessHandle proc = base::GetCurrentProcessHandle();
-#if !defined(OS_MACOSX)
-  process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc));
-#else
-  // The default port provider is sufficient to get data for the current
-  // process.
-  process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc,
-                                                                    NULL));
-#endif
-}
-
-TraceLog::~TraceLog() {
-  Stop();
-}
-
 // static
 TraceLog* TraceLog::GetInstance() {
   return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get();
@@ -59,61 +43,11 @@
   return TraceLog::GetInstance()->Start();
 }
 
-bool TraceLog::Start() {
-  if (enabled_)
-    return true;
-  enabled_ = OpenLogFile();
-  if (enabled_) {
-    Log("var raw_trace_events = [\n");
-    trace_start_time_ = TimeTicks::Now();
-    timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat);
-  }
-  return enabled_;
-}
-
 // static
 void TraceLog::StopTracing() {
   return TraceLog::GetInstance()->Stop();
 }
 
-void TraceLog::Stop() {
-  if (enabled_) {
-    enabled_ = false;
-    Log("];\n");
-    CloseLogFile();
-    timer_.Stop();
-  }
-}
-
-void TraceLog::Heartbeat() {
-  std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage());
-  TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu);
-}
-
-void TraceLog::CloseLogFile() {
-  if (log_file_) {
-    file_util::CloseFile(log_file_);
-  }
-}
-
-bool TraceLog::OpenLogFile() {
-  FilePath::StringType pid_filename =
-      StringPrintf(kLogFileName, base::GetCurrentProcId());
-  FilePath log_file_path;
-  if (!PathService::Get(base::DIR_EXE, &log_file_path))
-    return false;
-  log_file_path = log_file_path.Append(pid_filename);
-  log_file_ = file_util::OpenFile(log_file_path, "a");
-  if (!log_file_) {
-    // try the current directory
-    log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
-    if (!log_file_) {
-      return false;
-    }
-  }
-  return true;
-}
-
 void TraceLog::Trace(const std::string& name,
                      EventType type,
                      const void* id,
@@ -158,6 +92,72 @@
   Log(msg);
 }
 
+TraceLog::TraceLog() : enabled_(false), log_file_(NULL) {
+  base::ProcessHandle proc = base::GetCurrentProcessHandle();
+#if !defined(OS_MACOSX)
+  process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc));
+#else
+  // The default port provider is sufficient to get data for the current
+  // process.
+  process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc,
+                                                                    NULL));
+#endif
+}
+
+TraceLog::~TraceLog() {
+  Stop();
+}
+
+bool TraceLog::OpenLogFile() {
+  FilePath::StringType pid_filename =
+      StringPrintf(kLogFileName, base::GetCurrentProcId());
+  FilePath log_file_path;
+  if (!PathService::Get(base::DIR_EXE, &log_file_path))
+    return false;
+  log_file_path = log_file_path.Append(pid_filename);
+  log_file_ = file_util::OpenFile(log_file_path, "a");
+  if (!log_file_) {
+    // try the current directory
+    log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
+    if (!log_file_) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void TraceLog::CloseLogFile() {
+  if (log_file_) {
+    file_util::CloseFile(log_file_);
+  }
+}
+
+bool TraceLog::Start() {
+  if (enabled_)
+    return true;
+  enabled_ = OpenLogFile();
+  if (enabled_) {
+    Log("var raw_trace_events = [\n");
+    trace_start_time_ = TimeTicks::Now();
+    timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat);
+  }
+  return enabled_;
+}
+
+void TraceLog::Stop() {
+  if (enabled_) {
+    enabled_ = false;
+    Log("];\n");
+    CloseLogFile();
+    timer_.Stop();
+  }
+}
+
+void TraceLog::Heartbeat() {
+  std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage());
+  TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu);
+}
+
 void TraceLog::Log(const std::string& msg) {
   AutoLock lock(file_lock_);
 
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index 476f065..e5c2cbd 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -31,9 +31,9 @@
 
 #include <string>
 
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "base/timer.h"
 
@@ -135,7 +135,7 @@
 
   bool enabled_;
   FILE* log_file_;
-  Lock file_lock_;
+  base::Lock file_lock_;
   TimeTicks trace_start_time_;
 #ifndef ANDROID
   scoped_ptr<base::ProcessMetrics> process_metrics_;
diff --git a/base/event_recorder.h b/base/event_recorder.h
index 04fbaa1..e4d8907 100644
--- a/base/event_recorder.h
+++ b/base/event_recorder.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -80,6 +80,9 @@
 #endif
         playback_first_msg_time_(0),
         playback_start_time_(0) {
+#if defined(OS_WIN)
+    memset(&playback_msg_, 0, sizeof(playback_msg_));
+#endif
   }
   ~EventRecorder();
 
diff --git a/base/file_path.cc b/base/file_path.cc
index cddb17e..5f1375a 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "base/file_path.h"
 
 #if defined(OS_WIN)
@@ -511,10 +513,14 @@
 }
 
 #if defined(OS_POSIX)
-
 // See file_path.h for a discussion of the encoding of paths on POSIX
-// platforms.  These *Hack() functions are not quite correct, but they're
-// only temporary while we fix the remainder of the code.
+// platforms.  These encoding conversion functions are not quite correct.
+
+string16 FilePath::LossyDisplayName() const {
+  return WideToUTF16(base::SysNativeMBToWide(path_));
+}
+
+// The *Hack functions are temporary while we fix the remainder of the code.
 // Remember to remove the #includes at the top when you remove these.
 
 // static
@@ -525,6 +531,10 @@
   return base::SysNativeMBToWide(path_);
 }
 #elif defined(OS_WIN)
+string16 FilePath::LossyDisplayName() const {
+  return path_;
+}
+
 // static
 FilePath FilePath::FromWStringHack(const std::wstring& wstring) {
   return FilePath(wstring);
diff --git a/base/file_path.h b/base/file_path.h
index 01cd4a5..84bb350 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -277,6 +277,12 @@
   // directory (i.e. has a path component that is ".."
   bool ReferencesParent() const;
 
+  // Return a Unicode human-readable version of this path.
+  // Warning: you can *not*, in general, go from a display name back to a real
+  // path.  Only use this when displaying paths to users, not just when you
+  // want to stuff a string16 into some other API.
+  string16 LossyDisplayName() const;
+
   // Older Chromium code assumes that paths are always wstrings.
   // These functions convert wstrings to/from FilePaths, and are
   // useful to smooth porting that old code to the FilePath API.
@@ -290,6 +296,9 @@
   //   OS-native string format.
   // - Am I using well-known file names, like "config.ini"?  Then use the
   //   ASCII functions (we require paths to always be supersets of ASCII).
+  // - Am I displaying a string to the user in some UI?  Then use the
+  //   LossyDisplayName() function, but keep in mind that you can't
+  //   ever use the result of that again as a path.
   static FilePath FromWStringHack(const std::wstring& wstring);
   std::wstring ToWStringHack() const;
 
diff --git a/base/file_util.cc b/base/file_util.cc
index d1a46c9..c9661e7 100644
--- a/base/file_util.cc
+++ b/base/file_util.cc
@@ -315,6 +315,18 @@
   CloseHandles();
 }
 
+bool MemoryMappedFile::Initialize(const FilePath& file_name) {
+  if (IsValid())
+    return false;
+
+  if (!MapFileToMemory(file_name)) {
+    CloseHandles();
+    return false;
+  }
+
+  return true;
+}
+
 bool MemoryMappedFile::Initialize(base::PlatformFile file) {
   if (IsValid())
     return false;
@@ -329,16 +341,8 @@
   return true;
 }
 
-bool MemoryMappedFile::Initialize(const FilePath& file_name) {
-  if (IsValid())
-    return false;
-
-  if (!MapFileToMemory(file_name)) {
-    CloseHandles();
-    return false;
-  }
-
-  return true;
+bool MemoryMappedFile::IsValid() {
+  return data_ != NULL;
 }
 
 bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) {
@@ -354,10 +358,6 @@
   return MapFileToMemoryInternal();
 }
 
-bool MemoryMappedFile::IsValid() {
-  return data_ != NULL;
-}
-
 // Deprecated functions ----------------------------------------------------
 
 #if defined(OS_WIN)
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index 475918e..7dd4127 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -641,26 +641,6 @@
 FileEnumerator::~FileEnumerator() {
 }
 
-void FileEnumerator::GetFindInfo(FindInfo* info) {
-  DCHECK(info);
-
-  if (current_directory_entry_ >= directory_entries_.size())
-    return;
-
-  DirectoryEntryInfo* cur_entry = &directory_entries_[current_directory_entry_];
-  memcpy(&(info->stat), &(cur_entry->stat), sizeof(info->stat));
-  info->filename.assign(cur_entry->filename.value());
-}
-
-bool FileEnumerator::IsDirectory(const FindInfo& info) {
-  return S_ISDIR(info.stat.st_mode);
-}
-
-// static
-FilePath FileEnumerator::GetFilename(const FindInfo& find_info) {
-  return FilePath(find_info.filename);
-}
-
 FilePath FileEnumerator::Next() {
   ++current_directory_entry_;
 
@@ -702,6 +682,26 @@
       ].filename);
 }
 
+void FileEnumerator::GetFindInfo(FindInfo* info) {
+  DCHECK(info);
+
+  if (current_directory_entry_ >= directory_entries_.size())
+    return;
+
+  DirectoryEntryInfo* cur_entry = &directory_entries_[current_directory_entry_];
+  memcpy(&(info->stat), &(cur_entry->stat), sizeof(info->stat));
+  info->filename.assign(cur_entry->filename.value());
+}
+
+bool FileEnumerator::IsDirectory(const FindInfo& info) {
+  return S_ISDIR(info.stat.st_mode);
+}
+
+// static
+FilePath FileEnumerator::GetFilename(const FindInfo& find_info) {
+  return FilePath(find_info.filename);
+}
+
 bool FileEnumerator::ReadDirectory(std::vector<DirectoryEntryInfo>* entries,
                                    const FilePath& source, bool show_links) {
   base::ThreadRestrictions::AssertIOAllowed();
diff --git a/base/file_util_proxy.cc b/base/file_util_proxy.cc
index bd08909..d357e98 100644
--- a/base/file_util_proxy.cc
+++ b/base/file_util_proxy.cc
@@ -525,12 +525,11 @@
  public:
   RelayRead(base::PlatformFile file,
             int64 offset,
-            char* buffer,
             int bytes_to_read,
-            base::FileUtilProxy::ReadWriteCallback* callback)
+            base::FileUtilProxy::ReadCallback* callback)
       : file_(file),
         offset_(offset),
-        buffer_(buffer),
+        buffer_(new char[bytes_to_read]),
         bytes_to_read_(bytes_to_read),
         callback_(callback),
         bytes_read_(0) {
@@ -538,7 +537,7 @@
 
  protected:
   virtual void RunWork() {
-    bytes_read_ = base::ReadPlatformFile(file_, offset_, buffer_,
+    bytes_read_ = base::ReadPlatformFile(file_, offset_, buffer_.get(),
                                          bytes_to_read_);
     if (bytes_read_ < 0)
       set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
@@ -546,7 +545,7 @@
 
   virtual void RunCallback() {
     if (callback_) {
-      callback_->Run(error_code(), bytes_read_);
+      callback_->Run(error_code(), buffer_.get(), bytes_read_);
       delete callback_;
     }
   }
@@ -554,9 +553,9 @@
  private:
   base::PlatformFile file_;
   int64 offset_;
-  char* buffer_;
+  scoped_array<char> buffer_;
   int bytes_to_read_;
-  base::FileUtilProxy::ReadWriteCallback* callback_;
+  base::FileUtilProxy::ReadCallback* callback_;
   int bytes_read_;
 };
 
@@ -566,17 +565,18 @@
              int64 offset,
              const char* buffer,
              int bytes_to_write,
-             base::FileUtilProxy::ReadWriteCallback* callback)
+             base::FileUtilProxy::WriteCallback* callback)
       : file_(file),
         offset_(offset),
-        buffer_(buffer),
+        buffer_(new char[bytes_to_write]),
         bytes_to_write_(bytes_to_write),
         callback_(callback) {
+    memcpy(buffer_.get(), buffer, bytes_to_write);
   }
 
  protected:
   virtual void RunWork() {
-    bytes_written_ = base::WritePlatformFile(file_, offset_, buffer_,
+    bytes_written_ = base::WritePlatformFile(file_, offset_, buffer_.get(),
                                              bytes_to_write_);
     if (bytes_written_ < 0)
       set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
@@ -592,9 +592,9 @@
  private:
   base::PlatformFile file_;
   int64 offset_;
-  const char* buffer_;
+  scoped_array<char> buffer_;
   int bytes_to_write_;
-  base::FileUtilProxy::ReadWriteCallback* callback_;
+  base::FileUtilProxy::WriteCallback* callback_;
   int bytes_written_;
 };
 
@@ -747,17 +747,6 @@
 }
 
 // static
-bool FileUtilProxy::CreateDirectory(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
-    const FilePath& file_path,
-    bool exclusive,
-    bool recursive,
-    StatusCallback* callback) {
-  return Start(FROM_HERE, message_loop_proxy, new RelayCreateDirectory(
-      file_path, exclusive, recursive, callback));
-}
-
-// static
 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
                           base::PlatformFile file_handle,
                           StatusCallback* callback) {
@@ -774,13 +763,43 @@
       message_loop_proxy, file_path, callback));
 }
 
+// Retrieves the information about a file. It is invalid to pass NULL for the
+// callback.
+bool FileUtilProxy::GetFileInfo(
+    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    const FilePath& file_path,
+    GetFileInfoCallback* callback) {
+  return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo(
+               file_path, callback));
+}
+
 // static
-bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
-                           const FilePath& file_path,
-                           bool recursive,
-                           StatusCallback* callback) {
+bool FileUtilProxy::GetFileInfoFromPlatformFile(
+    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    PlatformFile file,
+    GetFileInfoCallback* callback) {
   return Start(FROM_HERE, message_loop_proxy,
-               new RelayDelete(file_path, recursive, callback));
+               new RelayGetFileInfoFromPlatformFile(file, callback));
+}
+
+// static
+bool FileUtilProxy::ReadDirectory(
+    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    const FilePath& file_path,
+    ReadDirectoryCallback* callback) {
+  return Start(FROM_HERE, message_loop_proxy, new RelayReadDirectory(
+               file_path, callback));
+}
+
+// static
+bool FileUtilProxy::CreateDirectory(
+    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    const FilePath& file_path,
+    bool exclusive,
+    bool recursive,
+    StatusCallback* callback) {
+  return Start(FROM_HERE, message_loop_proxy, new RelayCreateDirectory(
+      file_path, exclusive, recursive, callback));
 }
 
 // static
@@ -802,22 +821,12 @@
 }
 
 // static
-bool FileUtilProxy::ReadDirectory(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
-    const FilePath& file_path,
-    ReadDirectoryCallback* callback) {
-  return Start(FROM_HERE, message_loop_proxy, new RelayReadDirectory(
-               file_path, callback));
-}
-
-// Retrieves the information about a file. It is invalid to pass NULL for the
-// callback.
-bool FileUtilProxy::GetFileInfo(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
-    const FilePath& file_path,
-    GetFileInfoCallback* callback) {
-  return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo(
-               file_path, callback));
+bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
+                           const FilePath& file_path,
+                           bool recursive,
+                           StatusCallback* callback) {
+  return Start(FROM_HERE, message_loop_proxy,
+               new RelayDelete(file_path, recursive, callback));
 }
 
 // static
@@ -830,24 +839,14 @@
 }
 
 // static
-bool FileUtilProxy::GetFileInfoFromPlatformFile(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
-    PlatformFile file,
-    GetFileInfoCallback* callback) {
-  return Start(FROM_HERE, message_loop_proxy,
-               new RelayGetFileInfoFromPlatformFile(file, callback));
-}
-
-// static
 bool FileUtilProxy::Read(
     scoped_refptr<MessageLoopProxy> message_loop_proxy,
     PlatformFile file,
     int64 offset,
-    char* buffer,
     int bytes_to_read,
-    ReadWriteCallback* callback) {
+    ReadCallback* callback) {
   return Start(FROM_HERE, message_loop_proxy,
-               new RelayRead(file, offset, buffer, bytes_to_read, callback));
+               new RelayRead(file, offset, bytes_to_read, callback));
 }
 
 // static
@@ -857,7 +856,7 @@
     int64 offset,
     const char* buffer,
     int bytes_to_write,
-    ReadWriteCallback* callback) {
+    WriteCallback* callback) {
   return Start(FROM_HERE, message_loop_proxy,
                new RelayWrite(file, offset, buffer, bytes_to_write, callback));
 }
diff --git a/base/file_util_proxy.h b/base/file_util_proxy.h
index 4181a26..f2368cc 100644
--- a/base/file_util_proxy.h
+++ b/base/file_util_proxy.h
@@ -46,8 +46,11 @@
                     >::Type GetFileInfoCallback;
   typedef Callback2<PlatformFileError /* error code */,
                     const std::vector<Entry>&>::Type ReadDirectoryCallback;
+  typedef Callback3<PlatformFileError /* error code */,
+                    const char* /* data */,
+                    int /* bytes read/written */>::Type ReadCallback;
   typedef Callback2<PlatformFileError /* error code */,
-                    int /* bytes read/written */>::Type ReadWriteCallback;
+                    int /* bytes written */>::Type WriteCallback;
 
   // Creates or opens a file with the given flags.  It is invalid to pass NULL
   // for the callback.
@@ -100,6 +103,15 @@
                             const FilePath& file_path,
                             ReadDirectoryCallback* callback);
 
+  // Creates directory at given path. It's an error to create
+  // if |exclusive| is true and dir already exists.
+  static bool CreateDirectory(
+      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      const FilePath& file_path,
+      bool exclusive,
+      bool recursive,
+      StatusCallback* callback);
+
   // Copies a file or a directory from |src_file_path| to |dest_file_path|
   // Error cases:
   // If destination file doesn't exist or destination's parent
@@ -113,13 +125,12 @@
                    const FilePath& dest_file_path,
                    StatusCallback* callback);
 
-  // Creates directory at given path. It's an error to create
-  // if |exclusive| is true and dir already exists.
-  static bool CreateDirectory(
+  // Moves a file or a directory from src_file_path to dest_file_path.
+  // Error cases are similar to Copy method's error cases.
+  static bool Move(
       scoped_refptr<MessageLoopProxy> message_loop_proxy,
-      const FilePath& file_path,
-      bool exclusive,
-      bool recursive,
+      const FilePath& src_file_path,
+      const FilePath& dest_file_path,
       StatusCallback* callback);
 
   // Deletes a file or a directory.
@@ -129,14 +140,6 @@
                      bool recursive,
                      StatusCallback* callback);
 
-  // Moves a file or a directory from src_file_path to dest_file_path.
-  // Error cases are similar to Copy method's error cases.
-  static bool Move(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
-      const FilePath& src_file_path,
-      const FilePath& dest_file_path,
-      StatusCallback* callback);
-
   // Deletes a directory and all of its contents.
   static bool RecursiveDelete(
       scoped_refptr<MessageLoopProxy> message_loop_proxy,
@@ -149,9 +152,8 @@
       scoped_refptr<MessageLoopProxy> message_loop_proxy,
       PlatformFile file,
       int64 offset,
-      char* buffer,
       int bytes_to_read,
-      ReadWriteCallback* callback);
+      ReadCallback* callback);
 
   // Writes to a file. If |offset| is greater than the length of the file,
   // |false| is returned. On success, the file pointer is moved to position
@@ -162,7 +164,7 @@
       int64 offset,
       const char* buffer,
       int bytes_to_write,
-      ReadWriteCallback* callback);
+      WriteCallback* callback);
 
   // Touches a file. The callback can be NULL.
   static bool Touch(
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 6ea94e4..ea29df5 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -163,7 +163,7 @@
 void CreateTextFile(const FilePath& filename,
                     const std::wstring& contents) {
   std::ofstream file;
-  file.open(WideToUTF8(filename.ToWStringHack()).c_str());
+  file.open(filename.value().c_str());
   ASSERT_TRUE(file.is_open());
   file << contents;
   file.close();
@@ -173,7 +173,7 @@
 std::wstring ReadTextFile(const FilePath& filename) {
   wchar_t contents[64];
   std::wifstream file;
-  file.open(WideToUTF8(filename.ToWStringHack()).c_str());
+  file.open(filename.value().c_str());
   EXPECT_TRUE(file.is_open());
   file.getline(contents, 64);
   file.close();
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
index 7476b53..51bcb4e 100644
--- a/base/file_util_win.cc
+++ b/base/file_util_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -667,9 +667,10 @@
   if (!::CreateDirectory(full_path_str, NULL)) {
     DWORD error_code = ::GetLastError();
     if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path)) {
-      // This error code doesn't indicate whether we were racing with someone
-      // creating the same directory, or a file with the same path, therefore
-      // we check.
+      // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we
+      // were racing with someone creating the same directory, or a file
+      // with the same path.  If DirectoryExists() returns true, we lost the
+      // race to create the same directory.
       return true;
     } else {
       LOG(WARNING) << "Failed to create directory " << full_path_str
diff --git a/base/global_descriptors_posix.cc b/base/global_descriptors_posix.cc
index 2fe953c..65e7955 100644
--- a/base/global_descriptors_posix.cc
+++ b/base/global_descriptors_posix.cc
@@ -11,10 +11,6 @@
 
 namespace base {
 
-GlobalDescriptors::GlobalDescriptors() {}
-
-GlobalDescriptors::~GlobalDescriptors() {}
-
 // static
 GlobalDescriptors* GlobalDescriptors::GetInstance() {
   typedef Singleton<base::GlobalDescriptors,
@@ -23,6 +19,14 @@
   return GlobalDescriptorsSingleton::get();
 }
 
+int GlobalDescriptors::Get(Key key) const {
+  const int ret = MaybeGet(key);
+
+  if (ret == -1)
+    LOG(FATAL) << "Unknown global descriptor: " << key;
+  return ret;
+}
+
 int GlobalDescriptors::MaybeGet(Key key) const {
   for (Mapping::const_iterator
        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
@@ -35,14 +39,6 @@
   return kBaseDescriptor + key;
 }
 
-int GlobalDescriptors::Get(Key key) const {
-  const int ret = MaybeGet(key);
-
-  if (ret == -1)
-    LOG(FATAL) << "Unknown global descriptor: " << key;
-  return ret;
-}
-
 void GlobalDescriptors::Set(Key key, int fd) {
   for (Mapping::iterator
        i = descriptors_.begin(); i != descriptors_.end(); ++i) {
@@ -55,4 +51,12 @@
   descriptors_.push_back(std::make_pair(key, fd));
 }
 
+void GlobalDescriptors::Reset(const Mapping& mapping) {
+  descriptors_ = mapping;
+}
+
+GlobalDescriptors::GlobalDescriptors() {}
+
+GlobalDescriptors::~GlobalDescriptors() {}
+
 }  // namespace base
diff --git a/base/global_descriptors_posix.h b/base/global_descriptors_posix.h
index 0cb5b4f..060bf0a 100644
--- a/base/global_descriptors_posix.h
+++ b/base/global_descriptors_posix.h
@@ -55,9 +55,7 @@
   // Set the descriptor for the given key.
   void Set(Key key, int fd);
 
-  void Reset(const Mapping& mapping) {
-    descriptors_ = mapping;
-  }
+  void Reset(const Mapping& mapping);
 
  private:
   friend struct DefaultSingletonTraits<GlobalDescriptors>;
diff --git a/base/hmac_nss.cc b/base/hmac_nss.cc
index 2ca4f67..af0b3eb 100644
--- a/base/hmac_nss.cc
+++ b/base/hmac_nss.cc
@@ -36,6 +36,9 @@
   }
 }
 
+HMAC::~HMAC() {
+}
+
 bool HMAC::Init(const unsigned char *key, int key_length) {
   base::EnsureNSSInit();
 
@@ -70,9 +73,6 @@
   return true;
 }
 
-HMAC::~HMAC() {
-}
-
 bool HMAC::Sign(const std::string& data,
                 unsigned char* digest,
                 int digest_length) {
diff --git a/base/i18n/bidi_line_iterator.cc b/base/i18n/bidi_line_iterator.cc
new file mode 100644
index 0000000..3222a3a
--- /dev/null
+++ b/base/i18n/bidi_line_iterator.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/i18n/bidi_line_iterator.h"
+
+#include "base/logging.h"
+
+namespace base {
+namespace i18n {
+
+BiDiLineIterator::BiDiLineIterator() : bidi_(NULL) {
+}
+
+BiDiLineIterator::~BiDiLineIterator() {
+  if (bidi_) {
+    ubidi_close(bidi_);
+    bidi_ = NULL;
+  }
+}
+
+bool BiDiLineIterator::Open(const string16& text,
+                            bool right_to_left,
+                            bool url) {
+  DCHECK(bidi_ == NULL);
+  UErrorCode error = U_ZERO_ERROR;
+  bidi_ = ubidi_openSized(static_cast<int>(text.length()), 0, &error);
+  if (U_FAILURE(error))
+    return false;
+  if (right_to_left && url)
+    ubidi_setReorderingMode(bidi_, UBIDI_REORDER_RUNS_ONLY);
+  ubidi_setPara(bidi_, text.data(), static_cast<int>(text.length()),
+                right_to_left ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR,
+                NULL, &error);
+  return U_SUCCESS(error) ? true : false;
+}
+
+int BiDiLineIterator::CountRuns() {
+  DCHECK(bidi_ != NULL);
+  UErrorCode error = U_ZERO_ERROR;
+  const int runs = ubidi_countRuns(bidi_, &error);
+  return U_SUCCESS(error) ? runs : 0;
+}
+
+UBiDiDirection BiDiLineIterator::GetVisualRun(int index,
+                                              int* start,
+                                              int* length) {
+  DCHECK(bidi_ != NULL);
+  return ubidi_getVisualRun(bidi_, index, start, length);
+}
+
+void BiDiLineIterator::GetLogicalRun(int start,
+                                     int* end,
+                                     UBiDiLevel* level) {
+  DCHECK(bidi_ != NULL);
+  ubidi_getLogicalRun(bidi_, start, end, level);
+}
+
+}  // namespace i18n
+}  // namespace base
diff --git a/base/i18n/bidi_line_iterator.h b/base/i18n/bidi_line_iterator.h
new file mode 100644
index 0000000..5fff6a3
--- /dev/null
+++ b/base/i18n/bidi_line_iterator.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_I18N_BIDI_LINE_ITERATOR_H_
+#define BASE_I18N_BIDI_LINE_ITERATOR_H_
+#pragma once
+
+#include "unicode/ubidi.h"
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+namespace base {
+namespace i18n {
+
+// A simple wrapper class for the bidirectional iterator of ICU.
+// This class uses the bidirectional iterator of ICU to split a line of
+// bidirectional texts into visual runs in its display order.
+class BiDiLineIterator {
+ public:
+  BiDiLineIterator();
+  ~BiDiLineIterator();
+
+  // Initializes the bidirectional iterator with the specified text.  Returns
+  // whether initialization succeeded.
+  bool Open(const string16& text, bool right_to_left, bool url);
+
+  // Returns the number of visual runs in the text, or zero on error.
+  int CountRuns();
+
+  // Gets the logical offset, length, and direction of the specified visual run.
+  UBiDiDirection GetVisualRun(int index, int* start, int* length);
+
+  // Given a start position, figure out where the run ends (and the BiDiLevel).
+  void GetLogicalRun(int start, int* end, UBiDiLevel* level);
+
+ private:
+  UBiDi* bidi_;
+
+  DISALLOW_COPY_AND_ASSIGN(BiDiLineIterator);
+};
+
+}  // namespace i18n
+}  // namespace base
+
+#endif  // BASE_I18N_BIDI_LINE_ITERATOR_H_
diff --git a/base/i18n/char_iterator.cc b/base/i18n/char_iterator.cc
index a6cf944..ce4d513 100644
--- a/base/i18n/char_iterator.cc
+++ b/base/i18n/char_iterator.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #include "unicode/utf16.h"
 
 namespace base {
+namespace i18n {
 
 UTF8CharIterator::UTF8CharIterator(const std::string* str)
     : str_(reinterpret_cast<const uint8_t*>(str->data())),
@@ -20,6 +21,9 @@
     U8_NEXT(str_, next_pos_, len_, char_);
 }
 
+UTF8CharIterator::~UTF8CharIterator() {
+}
+
 bool UTF8CharIterator::Advance() {
   if (array_pos_ >= len_)
     return false;
@@ -54,6 +58,9 @@
     ReadChar();
 }
 
+UTF16CharIterator::~UTF16CharIterator() {
+}
+
 bool UTF16CharIterator::Advance() {
   if (array_pos_ >= len_)
     return false;
@@ -71,4 +78,5 @@
   U16_NEXT(str_, next_pos_, len_, char_);
 }
 
+}  // namespace i18n
 }  // namespace base
diff --git a/base/i18n/char_iterator.h b/base/i18n/char_iterator.h
index f45b04b..bd7cc9f 100644
--- a/base/i18n/char_iterator.h
+++ b/base/i18n/char_iterator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -25,12 +25,13 @@
 #endif
 
 namespace base {
+namespace i18n {
 
 class UTF8CharIterator {
  public:
   // Requires |str| to live as long as the UTF8CharIterator does.
   UTF8CharIterator(const std::string* str);
-  ~UTF8CharIterator() {}
+  ~UTF8CharIterator();
 
   // Return the starting array index of the current character within the
   // string.
@@ -77,7 +78,7 @@
   // Requires |str| to live as long as the UTF16CharIterator does.
   UTF16CharIterator(const string16* str);
   UTF16CharIterator(const char16* str, size_t str_len);
-  ~UTF16CharIterator() {}
+  ~UTF16CharIterator();
 
   // Return the starting array index of the current character within the
   // string.
@@ -123,6 +124,7 @@
   DISALLOW_COPY_AND_ASSIGN(UTF16CharIterator);
 };
 
+}  // namespace i18n
 }  // namespace base
 
 #endif  // BASE_I18N_CHAR_ITERATOR_H_
diff --git a/base/i18n/char_iterator_unittest.cc b/base/i18n/char_iterator_unittest.cc
index 4fe7ebb..6d1294e 100644
--- a/base/i18n/char_iterator_unittest.cc
+++ b/base/i18n/char_iterator_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,16 +7,19 @@
 #include "base/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace base {
+namespace i18n {
+
 TEST(CharIteratorsTest, TestUTF8) {
   std::string empty("");
-  base::UTF8CharIterator empty_iter(&empty);
+  UTF8CharIterator empty_iter(&empty);
   ASSERT_TRUE(empty_iter.end());
   ASSERT_EQ(0, empty_iter.array_pos());
   ASSERT_EQ(0, empty_iter.char_pos());
   ASSERT_FALSE(empty_iter.Advance());
 
   std::string str("s\303\273r");  // [u with circumflex]
-  base::UTF8CharIterator iter(&str);
+  UTF8CharIterator iter(&str);
   ASSERT_FALSE(iter.end());
   ASSERT_EQ(0, iter.array_pos());
   ASSERT_EQ(0, iter.char_pos());
@@ -47,7 +50,7 @@
 
 TEST(CharIteratorsTest, TestUTF16) {
   string16 empty = UTF8ToUTF16("");
-  base::UTF16CharIterator empty_iter(&empty);
+  UTF16CharIterator empty_iter(&empty);
   ASSERT_TRUE(empty_iter.end());
   ASSERT_EQ(0, empty_iter.array_pos());
   ASSERT_EQ(0, empty_iter.char_pos());
@@ -59,7 +62,7 @@
   //   math double-struck A - 4 bytes in UTF8, 2 codewords in UTF16
   //   z
   string16 str = UTF8ToUTF16("x\303\273\360\235\224\270z");
-  base::UTF16CharIterator iter(&str);
+  UTF16CharIterator iter(&str);
   ASSERT_FALSE(iter.end());
   ASSERT_EQ(0, iter.array_pos());
   ASSERT_EQ(0, iter.char_pos());
@@ -93,3 +96,6 @@
 
   ASSERT_FALSE(iter.Advance());
 }
+
+}  // namespace i18n
+}  // namespace base
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc
index 34eefac..ba69da0 100644
--- a/base/i18n/file_util_icu.cc
+++ b/base/i18n/file_util_icu.cc
@@ -90,7 +90,7 @@
   int Compare(const string16& a, const string16& b) {
     // We are not sure if Collator::compare is thread-safe.
     // Use an AutoLock just in case.
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
 
     UErrorCode error_code = U_ZERO_ERROR;
     UCollationResult result = collator_->compare(
@@ -120,7 +120,7 @@
   }
 
   scoped_ptr<icu::Collator> collator_;
-  Lock lock_;
+  base::Lock lock_;
   friend struct DefaultSingletonTraits<LocaleAwareComparator>;
 
   DISALLOW_COPY_AND_ASSIGN(LocaleAwareComparator);
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc
index d378a25..eb7a688 100644
--- a/base/i18n/icu_util.cc
+++ b/base/i18n/icu_util.cc
@@ -21,6 +21,10 @@
 #include "unicode/putil.h"
 #include "unicode/udata.h"
 
+#if defined(OS_MACOSX)
+#include "base/mac/foundation_util.h"
+#endif
+
 #define ICU_UTIL_DATA_FILE   0
 #define ICU_UTIL_DATA_SHARED 1
 #define ICU_UTIL_DATA_STATIC 2
@@ -35,10 +39,14 @@
 
 #endif  // ICU_UTIL_DATA_IMPL
 
-#if defined(OS_WIN)
+#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
+#define ICU_UTIL_DATA_FILE_NAME "icudt" U_ICU_VERSION_SHORT "l.dat"
+#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED
 #define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat"
+#if defined(OS_WIN)
 #define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt" U_ICU_VERSION_SHORT ".dll"
 #endif
+#endif
 
 namespace icu_util {
 
@@ -78,6 +86,7 @@
   // Mac/Linux bundle the ICU data in.
   return true;
 #elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
+#if !defined(OS_MACOSX)
   // For now, expect the data file to be alongside the executable.
   // This is sufficient while we work on unit tests, but will eventually
   // likely live in a data directory.
@@ -90,6 +99,32 @@
   UErrorCode err = U_ZERO_ERROR;
   udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
   return err == U_ZERO_ERROR;
+#else
+  // If the ICU data directory is set, ICU won't actually load the data until
+  // it is needed.  This can fail if the process is sandboxed at that time.
+  // Instead, Mac maps the file in and hands off the data so the sandbox won't
+  // cause any problems.
+
+  // Chrome doesn't normally shut down ICU, so the mapped data shouldn't ever
+  // be released.
+  static file_util::MemoryMappedFile mapped_file;
+  if (!mapped_file.IsValid()) {
+    // Assume it is in the MainBundle's Resources directory.
+    FilePath data_path =
+      base::mac::PathForMainAppBundleResource(CFSTR(ICU_UTIL_DATA_FILE_NAME));
+    if (data_path.empty()) {
+      LOG(ERROR) << ICU_UTIL_DATA_FILE_NAME << " not found in bundle";
+      return false;
+    }
+    if (!mapped_file.Initialize(data_path)) {
+      LOG(ERROR) << "Couldn't mmap " << data_path.value();
+      return false;
+    }
+  }
+  UErrorCode err = U_ZERO_ERROR;
+  udata_setCommonData(const_cast<uint8*>(mapped_file.data()), &err);
+  return err == U_ZERO_ERROR;
+#endif  // OS check
 #endif
 }
 
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc
index 391f58b..c8fe78d 100644
--- a/base/json/json_reader.cc
+++ b/base/json/json_reader.cc
@@ -81,6 +81,11 @@
 const char* JSONReader::kUnquotedDictionaryKey =
     "Dictionary keys must be quoted.";
 
+JSONReader::JSONReader()
+    : start_pos_(NULL), json_pos_(NULL), stack_depth_(0),
+      allow_trailing_comma_(false),
+      error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {}
+
 /* static */
 Value* JSONReader::Read(const std::string& json,
                         bool allow_trailing_comma) {
@@ -106,16 +111,6 @@
 }
 
 /* static */
-std::string JSONReader::FormatErrorMessage(int line, int column,
-                                           const std::string& description) {
-  if (line || column) {
-    return StringPrintf("Line: %i, column: %i, %s",
-                        line, column, description.c_str());
-  }
-  return description;
-}
-
-/* static */
 std::string JSONReader::ErrorCodeToString(JsonParseError error_code) {
   switch (error_code) {
     case JSON_NO_ERROR:
@@ -147,11 +142,6 @@
                             ErrorCodeToString(error_code_));
 }
 
-JSONReader::JSONReader()
-    : start_pos_(NULL), json_pos_(NULL), stack_depth_(0),
-      allow_trailing_comma_(false),
-      error_code_(JSON_NO_ERROR), error_line_(0), error_col_(0) {}
-
 Value* JSONReader::JsonToValue(const std::string& json, bool check_root,
                                bool allow_trailing_comma) {
   // The input must be in UTF-8.
@@ -195,6 +185,16 @@
   return NULL;
 }
 
+/* static */
+std::string JSONReader::FormatErrorMessage(int line, int column,
+                                           const std::string& description) {
+  if (line || column) {
+    return StringPrintf("Line: %i, column: %i, %s",
+                        line, column, description.c_str());
+  }
+  return description;
+}
+
 Value* JSONReader::BuildValue(bool is_root) {
   ++stack_depth_;
   if (stack_depth_ > kStackLimit) {
@@ -396,7 +396,7 @@
   double num_double;
   if (StringToDouble(WideToUTF8(num_string), &num_double) &&
       base::IsFinite(num_double))
-    return Value::CreateRealValue(num_double);
+    return Value::CreateDoubleValue(num_double);
 
   return NULL;
 }
@@ -580,16 +580,6 @@
   return token;
 }
 
-bool JSONReader::NextStringMatch(const std::wstring& str) {
-  for (size_t i = 0; i < str.length(); ++i) {
-    if ('\0' == *json_pos_)
-      return false;
-    if (*(json_pos_ + i) != str[i])
-      return false;
-  }
-  return true;
-}
-
 void JSONReader::EatWhitespaceAndComments() {
   while ('\0' != *json_pos_) {
     switch (*json_pos_) {
@@ -645,6 +635,16 @@
   return true;
 }
 
+bool JSONReader::NextStringMatch(const std::wstring& str) {
+  for (size_t i = 0; i < str.length(); ++i) {
+    if ('\0' == *json_pos_)
+      return false;
+    if (*(json_pos_ + i) != str[i])
+      return false;
+  }
+  return true;
+}
+
 void JSONReader::SetErrorCode(JsonParseError error,
                               const wchar_t* error_pos) {
   int line_number = 1;
diff --git a/base/json/json_reader.h b/base/json/json_reader.h
index 77c4e74..a6f0686 100644
--- a/base/json/json_reader.h
+++ b/base/json/json_reader.h
@@ -146,14 +146,12 @@
                      bool allow_trailing_comma);
 
  private:
-  static std::string FormatErrorMessage(int line, int column,
-                                        const std::string& description);
-
-  DISALLOW_COPY_AND_ASSIGN(JSONReader);
-
   FRIEND_TEST(JSONReaderTest, Reading);
   FRIEND_TEST(JSONReaderTest, ErrorMessages);
 
+  static std::string FormatErrorMessage(int line, int column,
+                                        const std::string& description);
+
   // Recursively build Value.  Returns NULL if we don't have a valid JSON
   // string.  If |is_root| is true, we verify that the root element is either
   // an object or an array.
@@ -213,6 +211,8 @@
   JsonParseError error_code_;
   int error_line_;
   int error_col_;
+
+  DISALLOW_COPY_AND_ASSIGN(JSONReader);
 };
 
 }  // namespace base
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc
index c00c976..db0ab63 100644
--- a/base/json/json_reader_unittest.cc
+++ b/base/json/json_reader_unittest.cc
@@ -75,60 +75,60 @@
   // storage as doubles
   root.reset(JSONReader().JsonToValue("2147483648", false, false));
   ASSERT_TRUE(root.get());
-  double real_val;
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(2147483648.0, real_val);
+  double double_val;
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(2147483648.0, double_val);
   root.reset(JSONReader().JsonToValue("-2147483649", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(-2147483649.0, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(-2147483649.0, double_val);
 
   // Parse a double
   root.reset(JSONReader().JsonToValue("43.1", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(43.1, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(43.1, double_val);
 
   root.reset(JSONReader().JsonToValue("4.3e-1", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(.43, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(.43, double_val);
 
   root.reset(JSONReader().JsonToValue("2.1e0", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(2.1, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(2.1, double_val);
 
   root.reset(JSONReader().JsonToValue("2.1e+0001", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(21.0, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(21.0, double_val);
 
   root.reset(JSONReader().JsonToValue("0.01", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(0.01, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(0.01, double_val);
 
   root.reset(JSONReader().JsonToValue("1.00", false, false));
   ASSERT_TRUE(root.get());
-  ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
-  real_val = 0.0;
-  ASSERT_TRUE(root->GetAsReal(&real_val));
-  ASSERT_DOUBLE_EQ(1.0, real_val);
+  ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
+  double_val = 0.0;
+  ASSERT_TRUE(root->GetAsDouble(&double_val));
+  ASSERT_DOUBLE_EQ(1.0, double_val);
 
   // Fractional parts must have a digit before and after the decimal point.
   root.reset(JSONReader().JsonToValue("1.", false, false));
@@ -303,9 +303,9 @@
   ASSERT_TRUE(root.get());
   ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
   DictionaryValue* dict_val = static_cast<DictionaryValue*>(root.get());
-  real_val = 0.0;
-  ASSERT_TRUE(dict_val->GetReal("number", &real_val));
-  ASSERT_DOUBLE_EQ(9.87654321, real_val);
+  double_val = 0.0;
+  ASSERT_TRUE(dict_val->GetDouble("number", &double_val));
+  ASSERT_DOUBLE_EQ(9.87654321, double_val);
   Value* null_val = NULL;
   ASSERT_TRUE(dict_val->Get("null", &null_val));
   ASSERT_TRUE(null_val->IsType(Value::TYPE_NULL));
diff --git a/base/json/json_writer.cc b/base/json/json_writer.cc
index dbf43ec..fa8f239 100644
--- a/base/json/json_writer.cc
+++ b/base/json/json_writer.cc
@@ -75,10 +75,10 @@
         break;
       }
 
-    case Value::TYPE_REAL:
+    case Value::TYPE_DOUBLE:
       {
         double value;
-        bool result = node->GetAsReal(&value);
+        bool result = node->GetAsDouble(&value);
         DCHECK(result);
         std::string real = DoubleToString(value);
         // Ensure that the number has a .0 if there's no decimal or 'e'.  This
diff --git a/base/json/json_writer_unittest.cc b/base/json/json_writer_unittest.cc
index 937d083..6d7714b 100644
--- a/base/json/json_writer_unittest.cc
+++ b/base/json/json_writer_unittest.cc
@@ -29,19 +29,19 @@
   delete root;
 
   // Test Real values should always have a decimal or an 'e'.
-  root = Value::CreateRealValue(1.0);
+  root = Value::CreateDoubleValue(1.0);
   JSONWriter::Write(root, false, &output_js);
   ASSERT_EQ("1.0", output_js);
   delete root;
 
   // Test Real values in the the range (-1, 1) must have leading zeros
-  root = Value::CreateRealValue(0.2);
+  root = Value::CreateDoubleValue(0.2);
   JSONWriter::Write(root, false, &output_js);
   ASSERT_EQ("0.2", output_js);
   delete root;
 
   // Test Real values in the the range (-1, 1) must have leading zeros
-  root = Value::CreateRealValue(-0.8);
+  root = Value::CreateDoubleValue(-0.8);
   JSONWriter::Write(root, false, &output_js);
   ASSERT_EQ("-0.8", output_js);
   delete root;
diff --git a/base/linux_util.cc b/base/linux_util.cc
index e1f7275..4e7cc5c 100644
--- a/base/linux_util.cc
+++ b/base/linux_util.cc
@@ -17,12 +17,12 @@
 
 #include "base/command_line.h"
 #include "base/file_util.h"
-#include "base/lock.h"
 #include "base/path_service.h"
 #include "base/process_util.h"
 #include "base/singleton.h"
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 
 namespace {
 
@@ -51,7 +51,7 @@
   // we automatically move to STATE_CHECK_STARTED so nobody else will
   // do the check.
   LinuxDistroState State() {
-    AutoLock scoped_lock(lock_);
+    base::AutoLock scoped_lock(lock_);
     if (STATE_DID_NOT_CHECK == state_) {
       state_ = STATE_CHECK_STARTED;
       return STATE_DID_NOT_CHECK;
@@ -61,13 +61,13 @@
 
   // Indicate the check finished, move to STATE_CHECK_FINISHED.
   void CheckFinished() {
-    AutoLock scoped_lock(lock_);
+    base::AutoLock scoped_lock(lock_);
     DCHECK(state_ == STATE_CHECK_STARTED);
     state_ = STATE_CHECK_FINISHED;
   }
 
  private:
-  Lock lock_;
+  base::Lock lock_;
   LinuxDistroState state_;
 };
 #endif  // if defined(OS_LINUX)
diff --git a/base/lock.h b/base/lock.h
deleted file mode 100644
index 7c90d86..0000000
--- a/base/lock.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_LOCK_H_
-#define BASE_LOCK_H_
-#pragma once
-
-// This is a temporary forwarding file so not every user of lock needs to
-// be updated at once.
-// TODO(brettw) remove this and fix everybody up to using the new location.
-#include "base/synchronization/lock.h"
-
-using base::AutoLock;
-using base::AutoUnlock;
-using base::Lock;
-
-#endif  // BASE_LOCK_H_
diff --git a/base/logging.cc b/base/logging.cc
index a736590..c38a2e0 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -64,7 +64,7 @@
 
 namespace logging {
 
-bool g_enable_dcheck = false;
+DcheckState g_dcheck_state = DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
 VlogInfo* g_vlog_info = NULL;
 
 const char* const log_severity_names[LOG_NUM_SEVERITIES] = {
@@ -353,15 +353,19 @@
 bool BaseInitLoggingImpl(const PathChar* new_log_file,
                          LoggingDestination logging_dest,
                          LogLockingState lock_log,
+<<<<<<< HEAD
                          OldFileDeletionState delete_old) {
 #ifdef ANDROID
   // ifdef is here because we don't support parsing command line parameters
   g_enable_dcheck = false;
   g_vlog_info = NULL;
 #else
+=======
+                         OldFileDeletionState delete_old,
+                         DcheckState dcheck_state) {
+>>>>>>> chromium.org at r11.0.672.0
   CommandLine* command_line = CommandLine::ForCurrentProcess();
-  g_enable_dcheck =
-      command_line->HasSwitch(switches::kEnableDCHECK);
+  g_dcheck_state = dcheck_state;
   delete g_vlog_info;
   g_vlog_info = NULL;
   // Don't bother initializing g_vlog_info unless we use one of the
@@ -536,19 +540,6 @@
   Init(file, line);
 }
 
-LogMessage::LogMessage(const char* file, int line, const CheckOpString& result)
-    : severity_(LOG_FATAL), file_(file), line_(line) {
-  Init(file, line);
-  stream_ << "Check failed: " << (*result.str_);
-}
-
-LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
-                       const CheckOpString& result)
-    : severity_(severity), file_(file), line_(line) {
-  Init(file, line);
-  stream_ << "Check failed: " << (*result.str_);
-}
-
 LogMessage::LogMessage(const char* file, int line)
     : severity_(LOG_INFO), file_(file), line_(line) {
   Init(file, line);
@@ -559,48 +550,19 @@
   Init(file, line);
 }
 
-// writes the common header info to the stream
-void LogMessage::Init(const char* file, int line) {
-  base::StringPiece filename(file);
-  size_t last_slash_pos = filename.find_last_of("\\/");
-  if (last_slash_pos != base::StringPiece::npos)
-    filename.remove_prefix(last_slash_pos + 1);
+LogMessage::LogMessage(const char* file, int line, std::string* result)
+    : severity_(LOG_FATAL), file_(file), line_(line) {
+  Init(file, line);
+  stream_ << "Check failed: " << *result;
+  delete result;
+}
 
-  // TODO(darin): It might be nice if the columns were fixed width.
-
-  stream_ <<  '[';
-  if (log_process_id)
-    stream_ << CurrentProcessId() << ':';
-  if (log_thread_id)
-    stream_ << CurrentThreadId() << ':';
-  if (log_timestamp) {
-    time_t t = time(NULL);
-    struct tm local_time = {0};
-#if _MSC_VER >= 1400
-    localtime_s(&local_time, &t);
-#else
-    localtime_r(&t, &local_time);
-#endif
-    struct tm* tm_time = &local_time;
-    stream_ << std::setfill('0')
-            << std::setw(2) << 1 + tm_time->tm_mon
-            << std::setw(2) << tm_time->tm_mday
-            << '/'
-            << std::setw(2) << tm_time->tm_hour
-            << std::setw(2) << tm_time->tm_min
-            << std::setw(2) << tm_time->tm_sec
-            << ':';
-  }
-  if (log_tickcount)
-    stream_ << TickCount() << ':';
-  if (severity_ >= 0)
-    stream_ << log_severity_names[severity_];
-  else
-    stream_ << "VERBOSE" << -severity_;
-
-  stream_ << ":" << filename << "(" << line << ")] ";
-
-  message_start_ = stream_.tellp();
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
+                       std::string* result)
+    : severity_(severity), file_(file), line_(line) {
+  Init(file, line);
+  stream_ << "Check failed: " << *result;
+  delete result;
 }
 
 LogMessage::~LogMessage() {
@@ -696,6 +658,50 @@
   }
 }
 
+// writes the common header info to the stream
+void LogMessage::Init(const char* file, int line) {
+  base::StringPiece filename(file);
+  size_t last_slash_pos = filename.find_last_of("\\/");
+  if (last_slash_pos != base::StringPiece::npos)
+    filename.remove_prefix(last_slash_pos + 1);
+
+  // TODO(darin): It might be nice if the columns were fixed width.
+
+  stream_ <<  '[';
+  if (log_process_id)
+    stream_ << CurrentProcessId() << ':';
+  if (log_thread_id)
+    stream_ << CurrentThreadId() << ':';
+  if (log_timestamp) {
+    time_t t = time(NULL);
+    struct tm local_time = {0};
+#if _MSC_VER >= 1400
+    localtime_s(&local_time, &t);
+#else
+    localtime_r(&t, &local_time);
+#endif
+    struct tm* tm_time = &local_time;
+    stream_ << std::setfill('0')
+            << std::setw(2) << 1 + tm_time->tm_mon
+            << std::setw(2) << tm_time->tm_mday
+            << '/'
+            << std::setw(2) << tm_time->tm_hour
+            << std::setw(2) << tm_time->tm_min
+            << std::setw(2) << tm_time->tm_sec
+            << ':';
+  }
+  if (log_tickcount)
+    stream_ << TickCount() << ':';
+  if (severity_ >= 0)
+    stream_ << log_severity_names[severity_];
+  else
+    stream_ << "VERBOSE" << -severity_;
+
+  stream_ << ":" << filename << "(" << line << ")] ";
+
+  message_start_ = stream_.tellp();
+}
+
 #if defined(OS_WIN)
 // This has already been defined in the header, but defining it again as DWORD
 // ensures that the type used in the header is equivalent to DWORD. If not,
diff --git a/base/logging.h b/base/logging.h
index a097568..b1bc0b0 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -165,6 +165,11 @@
 // Defaults to APPEND_TO_OLD_LOG_FILE.
 enum OldFileDeletionState { DELETE_OLD_LOG_FILE, APPEND_TO_OLD_LOG_FILE };
 
+enum DcheckState {
+  DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS,
+  ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS
+};
+
 // TODO(avi): do we want to do a unification of character types here?
 #if defined(OS_WIN)
 typedef wchar_t PathChar;
@@ -188,7 +193,8 @@
 bool BaseInitLoggingImpl(const PathChar* log_file,
                          LoggingDestination logging_dest,
                          LogLockingState lock_log,
-                         OldFileDeletionState delete_old);
+                         OldFileDeletionState delete_old,
+                         DcheckState dcheck_state);
 
 // Sets the log file name and other global logging state. Calling this function
 // is recommended, and is normally done at the beginning of application init.
@@ -203,8 +209,10 @@
 inline bool InitLogging(const PathChar* log_file,
                         LoggingDestination logging_dest,
                         LogLockingState lock_log,
-                        OldFileDeletionState delete_old) {
-  return BaseInitLoggingImpl(log_file, logging_dest, lock_log, delete_old);
+                        OldFileDeletionState delete_old,
+                        DcheckState dcheck_state) {
+  return BaseInitLoggingImpl(log_file, logging_dest, lock_log,
+                             delete_old, dcheck_state);
 }
 
 // Sets the log level. Anything at or above this level will be written to the
@@ -428,19 +436,10 @@
   LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
   << "Check failed: " #condition ". "
 
-// A container for a string pointer which can be evaluated to a bool -
-// true iff the pointer is NULL.
-struct CheckOpString {
-  CheckOpString(std::string* str) : str_(str) { }
-  // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
-  // so there's no point in cleaning up str_.
-  operator bool() const { return str_ != NULL; }
-  std::string* str_;
-};
-
 // Build the error message string.  This is separate from the "Impl"
 // function template because it is not performance critical and so can
-// be out of line, while the "Impl" code should be inline.
+// be out of line, while the "Impl" code should be inline.  Caller
+// takes ownership of the returned string.
 template<class t1, class t2>
 std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
   std::ostringstream ss;
@@ -471,7 +470,7 @@
 // TODO(akalin): Rewrite this so that constructs like if (...)
 // CHECK_EQ(...) else { ... } work properly.
 #define CHECK_OP(name, op, val1, val2)                          \
-  if (logging::CheckOpString _result =                          \
+  if (std::string* _result =                                    \
       logging::Check##name##Impl((val1), (val2),                \
                                  #val1 " " #op " " #val2))      \
     logging::LogMessage(__FILE__, __LINE__, _result).stream()
@@ -600,10 +599,11 @@
   COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName , ##__VA_ARGS__)
 #define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_ERROR_REPORT
 const LogSeverity LOG_DCHECK = LOG_ERROR_REPORT;
-// This is set to true in InitLogging when we want to enable the
-// DCHECKs in release.
-extern bool g_enable_dcheck;
-#define DCHECK_IS_ON() (::logging::g_enable_dcheck && LOG_IS_ON(DCHECK))
+extern DcheckState g_dcheck_state;
+#define DCHECK_IS_ON()                                                  \
+  ((::logging::g_dcheck_state ==                                        \
+    ::logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS) &&        \
+   LOG_IS_ON(DCHECK))
 
 #else  // defined(NDEBUG)
 
@@ -646,7 +646,7 @@
 // Don't use this macro directly in your code, use DCHECK_EQ et al below.
 #define DCHECK_OP(name, op, val1, val2)                         \
   if (DCHECK_IS_ON())                                           \
-    if (logging::CheckOpString _result =                        \
+    if (std::string* _result =                                  \
         logging::Check##name##Impl((val1), (val2),              \
                                    #val1 " " #op " " #val2))    \
       logging::LogMessage(                                      \
@@ -714,14 +714,15 @@
   // saves a couple of bytes per call site.
   LogMessage(const char* file, int line, LogSeverity severity);
 
-  // A special constructor used for check failures.
+  // A special constructor used for check failures.  Takes ownership
+  // of the given string.
   // Implied severity = LOG_FATAL
-  LogMessage(const char* file, int line, const CheckOpString& result);
+  LogMessage(const char* file, int line, std::string* result);
 
   // A special constructor used for check failures, with the option to
-  // specify severity.
+  // specify severity.  Takes ownership of the given string.
   LogMessage(const char* file, int line, LogSeverity severity,
-             const CheckOpString& result);
+             std::string* result);
 
   ~LogMessage();
 
@@ -910,4 +911,13 @@
 } while(0)
 #endif
 
+namespace base {
+
+class StringPiece;
+
+// allow StringPiece to be logged (needed for unit testing).
+extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
+
+}  // namespace base
+
 #endif  // BASE_LOGGING_H_
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 4b7fdbc..bb6e3d1 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -197,7 +197,7 @@
 
 #if !defined(LOGGING_IS_OFFICIAL_BUILD) && defined(NDEBUG)
   // Unofficial release build.
-  logging::g_enable_dcheck = false;
+  g_dcheck_state = DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
   DCHECK(mock_log_source.Log()) << mock_log_source.Log();
   DPCHECK(mock_log_source.Log()) << mock_log_source.Log();
   DCHECK_EQ(0, 0) << mock_log_source.Log();
@@ -213,13 +213,13 @@
   EXPECT_FALSE(DLOG_IS_ON(DCHECK));
 #elif defined(NDEBUG)
   // Unofficial release build.
-  logging::g_enable_dcheck = true;
-  logging::SetLogReportHandler(&LogSink);
+  g_dcheck_state = ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
+  SetLogReportHandler(&LogSink);
   EXPECT_TRUE(DCHECK_IS_ON());
   EXPECT_FALSE(DLOG_IS_ON(DCHECK));
 #else
   // Unofficial debug build.
-  logging::SetLogAssertHandler(&LogSink);
+  SetLogAssertHandler(&LogSink);
   EXPECT_TRUE(DCHECK_IS_ON());
   EXPECT_TRUE(DLOG_IS_ON(DCHECK));
 #endif  // defined(LOGGING_IS_OFFICIAL_BUILD)
diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h
new file mode 100644
index 0000000..a7c525a
--- /dev/null
+++ b/base/mac/foundation_util.h
@@ -0,0 +1,107 @@
+// Copyright (c) 2011 The Chromium 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_MAC_FOUNDATION_UTIL_H_
+#define BASE_MAC_FOUNDATION_UTIL_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+
+#if defined(__OBJC__)
+#import <Foundation/Foundation.h>
+@class NSBundle;
+#else  // __OBJC__
+class NSBundle;
+#endif  // __OBJC__
+
+class FilePath;
+
+// Adapted from NSPathUtilities.h and NSObjCRuntime.h.
+#if __LP64__ || NS_BUILD_32_LIKE_64
+typedef unsigned long NSSearchPathDirectory;
+typedef unsigned long NSSearchPathDomainMask;
+#else
+typedef unsigned int NSSearchPathDirectory;
+typedef unsigned int NSSearchPathDomainMask;
+#endif
+
+namespace base {
+namespace mac {
+
+// Returns true if the application is running from a bundle
+bool AmIBundled();
+void SetOverrideAmIBundled(bool value);
+
+// Returns true if this process is marked as a "Background only process".
+bool IsBackgroundOnlyProcess();
+
+// Returns the main bundle or the override, used for code that needs
+// to fetch resources from bundles, but work within a unittest where we
+// aren't a bundle.
+NSBundle* MainAppBundle();
+FilePath MainAppBundlePath();
+
+// Returns the path to a resource within the MainAppBundle.
+FilePath PathForMainAppBundleResource(CFStringRef resourceName);
+
+// Set the bundle that MainAppBundle will return, overriding the default value
+// (Restore the default by calling SetOverrideAppBundle(nil)).
+void SetOverrideAppBundle(NSBundle* bundle);
+void SetOverrideAppBundlePath(const FilePath& file_path);
+
+// Returns the creator code associated with the CFBundleRef at bundle.
+OSType CreatorCodeForCFBundleRef(CFBundleRef bundle);
+
+// Returns the creator code associated with this application, by calling
+// CreatorCodeForCFBundleRef for the application's main bundle.  If this
+// information cannot be determined, returns kUnknownType ('????').  This
+// does not respect the override app bundle because it's based on CFBundle
+// instead of NSBundle, and because callers probably don't want the override
+// app bundle's creator code anyway.
+OSType CreatorCodeForApplication();
+
+// Searches for directories for the given key in only the given |domain_mask|.
+// If found, fills result (which must always be non-NULL) with the
+// first found directory and returns true.  Otherwise, returns false.
+bool GetSearchPathDirectory(NSSearchPathDirectory directory,
+                            NSSearchPathDomainMask domain_mask,
+                            FilePath* result);
+
+// Searches for directories for the given key in only the local domain.
+// If found, fills result (which must always be non-NULL) with the
+// first found directory and returns true.  Otherwise, returns false.
+bool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result);
+
+// Searches for directories for the given key in only the user domain.
+// If found, fills result (which must always be non-NULL) with the
+// first found directory and returns true.  Otherwise, returns false.
+bool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result);
+
+// Returns the ~/Library directory.
+FilePath GetUserLibraryPath();
+
+// Takes a path to an (executable) binary and tries to provide the path to an
+// application bundle containing it. It takes the outermost bundle that it can
+// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
+//   |exec_name| - path to the binary
+//   returns - path to the application bundle, or empty on error
+FilePath GetAppBundlePath(const FilePath& exec_name);
+
+// Utility function to pull out a value from a dictionary, check its type, and
+// return it.  Returns NULL if the key is not present or of the wrong type.
+CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
+                                 CFStringRef key,
+                                 CFTypeID expected_type);
+
+// Retain/release calls for memory management in C++.
+void NSObjectRetain(void* obj);
+void NSObjectRelease(void* obj);
+
+}  // namespace mac
+}  // namespace base
+
+#endif  // BASE_MAC_FOUNDATION_UTIL_H_
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm
new file mode 100644
index 0000000..151d82f
--- /dev/null
+++ b/base/mac/foundation_util.mm
@@ -0,0 +1,236 @@
+// Copyright (c) 2011 The Chromium 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/mac/foundation_util.h"
+
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/sys_string_conversions.h"
+
+namespace base {
+namespace mac {
+
+static bool g_override_am_i_bundled = false;
+static bool g_override_am_i_bundled_value = false;
+
+// Adapted from http://developer.apple.com/carbon/tipsandtricks.html#AmIBundled
+static bool UncachedAmIBundled() {
+  if (g_override_am_i_bundled)
+    return g_override_am_i_bundled_value;
+
+  ProcessSerialNumber psn = {0, kCurrentProcess};
+
+  FSRef fsref;
+  OSStatus pbErr;
+  if ((pbErr = GetProcessBundleLocation(&psn, &fsref)) != noErr) {
+    LOG(ERROR) << "GetProcessBundleLocation failed: error " << pbErr;
+    return false;
+  }
+
+  FSCatalogInfo info;
+  OSErr fsErr;
+  if ((fsErr = FSGetCatalogInfo(&fsref, kFSCatInfoNodeFlags, &info,
+                                NULL, NULL, NULL)) != noErr) {
+    LOG(ERROR) << "FSGetCatalogInfo failed: error " << fsErr;
+    return false;
+  }
+
+  return info.nodeFlags & kFSNodeIsDirectoryMask;
+}
+
+bool AmIBundled() {
+  // If the return value is not cached, this function will return different
+  // values depending on when it's called. This confuses some client code, see
+  // http://crbug.com/63183 .
+  static bool result = UncachedAmIBundled();
+  DCHECK_EQ(result, UncachedAmIBundled())
+      << "The return value of AmIBundled() changed. This will confuse tests. "
+      << "Call SetAmIBundled() override manually if your test binary "
+      << "delay-loads the framework.";
+  return result;
+}
+
+void SetOverrideAmIBundled(bool value) {
+  g_override_am_i_bundled = true;
+  g_override_am_i_bundled_value = value;
+}
+
+bool IsBackgroundOnlyProcess() {
+  // This function really does want to examine NSBundle's idea of the main
+  // bundle dictionary, and not the overriden MainAppBundle.  It needs to look
+  // at the actual running .app's Info.plist to access its LSUIElement
+  // property.
+  NSDictionary* info_dictionary = [[NSBundle mainBundle] infoDictionary];
+  return [[info_dictionary objectForKey:@"LSUIElement"] boolValue] != NO;
+}
+
+// No threading worries since NSBundle isn't thread safe.
+static NSBundle* g_override_app_bundle = nil;
+
+NSBundle* MainAppBundle() {
+  if (g_override_app_bundle)
+    return g_override_app_bundle;
+  return [NSBundle mainBundle];
+}
+
+FilePath MainAppBundlePath() {
+  NSBundle* bundle = MainAppBundle();
+  return FilePath([[bundle bundlePath] fileSystemRepresentation]);
+}
+
+FilePath PathForMainAppBundleResource(CFStringRef resourceName) {
+  NSBundle* bundle = MainAppBundle();
+  NSString* resourcePath = [bundle pathForResource:(NSString*)resourceName
+                                            ofType:nil];
+  if (!resourcePath)
+    return FilePath();
+  return FilePath([resourcePath fileSystemRepresentation]);
+}
+
+void SetOverrideAppBundle(NSBundle* bundle) {
+  if (bundle != g_override_app_bundle) {
+    [g_override_app_bundle release];
+    g_override_app_bundle = [bundle retain];
+  }
+}
+
+void SetOverrideAppBundlePath(const FilePath& file_path) {
+  NSString* path = base::SysUTF8ToNSString(file_path.value());
+  NSBundle* bundle = [NSBundle bundleWithPath:path];
+  CHECK(bundle) << "Failed to load the bundle at " << file_path.value();
+
+  SetOverrideAppBundle(bundle);
+}
+
+OSType CreatorCodeForCFBundleRef(CFBundleRef bundle) {
+  OSType creator = kUnknownType;
+  CFBundleGetPackageInfo(bundle, NULL, &creator);
+  return creator;
+}
+
+OSType CreatorCodeForApplication() {
+  CFBundleRef bundle = CFBundleGetMainBundle();
+  if (!bundle)
+    return kUnknownType;
+
+  return CreatorCodeForCFBundleRef(bundle);
+}
+
+bool GetSearchPathDirectory(NSSearchPathDirectory directory,
+                            NSSearchPathDomainMask domain_mask,
+                            FilePath* result) {
+  DCHECK(result);
+  NSArray* dirs =
+      NSSearchPathForDirectoriesInDomains(directory, domain_mask, YES);
+  if ([dirs count] < 1) {
+    return false;
+  }
+  NSString* path = [dirs objectAtIndex:0];
+  *result = FilePath([path fileSystemRepresentation]);
+  return true;
+}
+
+bool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result) {
+  return GetSearchPathDirectory(directory, NSLocalDomainMask, result);
+}
+
+bool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result) {
+  return GetSearchPathDirectory(directory, NSUserDomainMask, result);
+}
+
+FilePath GetUserLibraryPath() {
+  FilePath user_library_path;
+  if (!GetUserDirectory(NSLibraryDirectory, &user_library_path)) {
+    LOG(WARNING) << "Could not get user library path";
+  }
+  return user_library_path;
+}
+
+// Takes a path to an (executable) binary and tries to provide the path to an
+// application bundle containing it. It takes the outermost bundle that it can
+// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
+//   |exec_name| - path to the binary
+//   returns - path to the application bundle, or empty on error
+FilePath GetAppBundlePath(const FilePath& exec_name) {
+  const char kExt[] = ".app";
+  const size_t kExtLength = arraysize(kExt) - 1;
+
+  // Split the path into components.
+  std::vector<std::string> components;
+  exec_name.GetComponents(&components);
+
+  // It's an error if we don't get any components.
+  if (!components.size())
+    return FilePath();
+
+  // Don't prepend '/' to the first component.
+  std::vector<std::string>::const_iterator it = components.begin();
+  std::string bundle_name = *it;
+  DCHECK(it->length() > 0);
+  // If the first component ends in ".app", we're already done.
+  if (it->length() > kExtLength &&
+      !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength))
+    return FilePath(bundle_name);
+
+  // The first component may be "/" or "//", etc. Only append '/' if it doesn't
+  // already end in '/'.
+  if (bundle_name[bundle_name.length() - 1] != '/')
+    bundle_name += '/';
+
+  // Go through the remaining components.
+  for (++it; it != components.end(); ++it) {
+    DCHECK(it->length() > 0);
+
+    bundle_name += *it;
+
+    // If the current component ends in ".app", we're done.
+    if (it->length() > kExtLength &&
+        !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength))
+      return FilePath(bundle_name);
+
+    // Separate this component from the next one.
+    bundle_name += '/';
+  }
+
+  return FilePath();
+}
+
+CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
+                                 CFStringRef key,
+                                 CFTypeID expected_type) {
+  CFTypeRef value = CFDictionaryGetValue(dict, key);
+  if (!value)
+    return value;
+
+  if (CFGetTypeID(value) != expected_type) {
+    ScopedCFTypeRef<CFStringRef> expected_type_ref(
+        CFCopyTypeIDDescription(expected_type));
+    ScopedCFTypeRef<CFStringRef> actual_type_ref(
+        CFCopyTypeIDDescription(CFGetTypeID(value)));
+    LOG(WARNING) << "Expected value for key "
+                 << base::SysCFStringRefToUTF8(key)
+                 << " to be "
+                 << base::SysCFStringRefToUTF8(expected_type_ref)
+                 << " but it was "
+                 << base::SysCFStringRefToUTF8(actual_type_ref)
+                 << " instead";
+    return NULL;
+  }
+
+  return value;
+}
+
+void NSObjectRetain(void* obj) {
+  id<NSObject> nsobj = static_cast<id<NSObject> >(obj);
+  [nsobj retain];
+}
+
+void NSObjectRelease(void* obj) {
+  id<NSObject> nsobj = static_cast<id<NSObject> >(obj);
+  [nsobj release];
+}
+
+}  // namespace mac
+}  // namespace base
diff --git a/base/mac/mac_util.h b/base/mac/mac_util.h
index 7e5dddb..d75fb6e 100644
--- a/base/mac/mac_util.h
+++ b/base/mac/mac_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,32 +8,20 @@
 
 #include <Carbon/Carbon.h>
 #include <string>
-#include <vector>
 
 #include "base/logging.h"
 
+// TODO(rohitrao): Clean up sites that include mac_util.h and remove this line.
+#include "base/mac/foundation_util.h"
+
 #if defined(__OBJC__)
 #import <Foundation/Foundation.h>
-
-@class NSBundle;
-@class NSWindow;
 #else  // __OBJC__
-class NSBundle;
 class NSImage;
-class NSWindow;
 #endif  // __OBJC__
 
 class FilePath;
 
-// Adapted from NSPathUtilities.h and NSObjCRuntime.h.
-#if __LP64__ || NS_BUILD_32_LIKE_64
-typedef unsigned long NSSearchPathDirectory;
-typedef unsigned long NSSearchPathDomainMask;
-#else
-typedef unsigned int NSSearchPathDirectory;
-typedef unsigned int NSSearchPathDomainMask;
-#endif
-
 namespace base {
 namespace mac {
 
@@ -53,55 +41,6 @@
 std::string PathFromFSRef(const FSRef& ref);
 bool FSRefFromPath(const std::string& path, FSRef* ref);
 
-// Returns true if the application is running from a bundle
-bool AmIBundled();
-void SetOverrideAmIBundled(bool value);
-
-// Returns true if this process is marked as a "Background only process".
-bool IsBackgroundOnlyProcess();
-
-// Returns the main bundle or the override, used for code that needs
-// to fetch resources from bundles, but work within a unittest where we
-// aren't a bundle.
-NSBundle* MainAppBundle();
-FilePath MainAppBundlePath();
-
-// Set the bundle that MainAppBundle will return, overriding the default value
-// (Restore the default by calling SetOverrideAppBundle(nil)).
-void SetOverrideAppBundle(NSBundle* bundle);
-void SetOverrideAppBundlePath(const FilePath& file_path);
-
-// Returns the creator code associated with the CFBundleRef at bundle.
-OSType CreatorCodeForCFBundleRef(CFBundleRef bundle);
-
-// Returns the creator code associated with this application, by calling
-// CreatorCodeForCFBundleRef for the application's main bundle.  If this
-// information cannot be determined, returns kUnknownType ('????').  This
-// does not respect the override app bundle because it's based on CFBundle
-// instead of NSBundle, and because callers probably don't want the override
-// app bundle's creator code anyway.
-OSType CreatorCodeForApplication();
-
-// Searches for directories for the given key in only the given |domain_mask|.
-// If found, fills result (which must always be non-NULL) with the
-// first found directory and returns true.  Otherwise, returns false.
-bool GetSearchPathDirectory(NSSearchPathDirectory directory,
-                            NSSearchPathDomainMask domain_mask,
-                            FilePath* result);
-
-// Searches for directories for the given key in only the user domain.
-// If found, fills result (which must always be non-NULL) with the
-// first found directory and returns true.  Otherwise, returns false.
-bool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result);
-
-// Searches for directories for the given key in only the local domain.
-// If found, fills result (which must always be non-NULL) with the
-// first found directory and returns true.  Otherwise, returns false.
-bool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result);
-
-// Returns the ~/Library directory.
-FilePath GetUserLibraryPath();
-
 // Returns an sRGB color space.  The return value is a static value; do not
 // release it!
 CGColorSpaceRef GetSRGBColorSpace();
@@ -136,29 +75,11 @@
 bool ShouldWindowsMiniaturizeOnDoubleClick();
 
 // Activates the process with the given PID.
-void ActivateProcess(pid_t);
-
-// Pulls a snapshot of the entire browser into png_representation.
-void GrabWindowSnapshot(NSWindow* window,
-                        std::vector<unsigned char>* png_representation,
-                        int* width, int* height);
-
-// Takes a path to an (executable) binary and tries to provide the path to an
-// application bundle containing it. It takes the outermost bundle that it can
-// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
-//   |exec_name| - path to the binary
-//   returns - path to the application bundle, or empty on error
-FilePath GetAppBundlePath(const FilePath& exec_name);
+void ActivateProcess(pid_t pid);
 
 // Set the Time Machine exclusion property for the given file.
 bool SetFileBackupExclusion(const FilePath& file_path, bool exclude);
 
-// Utility function to pull out a value from a dictionary, check its type, and
-// return it.  Returns NULL if the key is not present or of the wrong type.
-CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
-                                 CFStringRef key,
-                                 CFTypeID expected_type);
-
 // Sets the process name as displayed in Activity Monitor to process_name.
 void SetProcessName(CFStringRef process_name);
 
@@ -189,10 +110,6 @@
 // 'Login Item' with 'hide on startup' flag. Used to suppress opening windows.
 bool WasLaunchedAsHiddenLoginItem();
 
-// Retain/release calls for memory management in C++.
-void NSObjectRetain(void* obj);
-void NSObjectRelease(void* obj);
-
 #if defined(__OBJC__)
 
 // Convert toll-free bridged CFTypes to NSTypes. This does not autorelease
diff --git a/base/mac/mac_util.mm b/base/mac/mac_util.mm
index 21213ba..7f3be18 100644
--- a/base/mac/mac_util.mm
+++ b/base/mac/mac_util.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,6 @@
 #include "base/file_path.h"
 #include "base/logging.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/message_loop.h"
 #include "base/scoped_nsobject.h"
 #include "base/sys_string_conversions.h"
 
@@ -141,133 +140,6 @@
   return status == noErr;
 }
 
-static bool g_override_am_i_bundled = false;
-static bool g_override_am_i_bundled_value = false;
-
-// Adapted from http://developer.apple.com/carbon/tipsandtricks.html#AmIBundled
-static bool UncachedAmIBundled() {
-  if (g_override_am_i_bundled)
-    return g_override_am_i_bundled_value;
-
-  ProcessSerialNumber psn = {0, kCurrentProcess};
-
-  FSRef fsref;
-  OSStatus pbErr;
-  if ((pbErr = GetProcessBundleLocation(&psn, &fsref)) != noErr) {
-    LOG(ERROR) << "GetProcessBundleLocation failed: error " << pbErr;
-    return false;
-  }
-
-  FSCatalogInfo info;
-  OSErr fsErr;
-  if ((fsErr = FSGetCatalogInfo(&fsref, kFSCatInfoNodeFlags, &info,
-                                NULL, NULL, NULL)) != noErr) {
-    LOG(ERROR) << "FSGetCatalogInfo failed: error " << fsErr;
-    return false;
-  }
-
-  return info.nodeFlags & kFSNodeIsDirectoryMask;
-}
-
-bool AmIBundled() {
-  // If the return value is not cached, this function will return different
-  // values depending on when it's called. This confuses some client code, see
-  // http://crbug.com/63183 .
-  static bool result = UncachedAmIBundled();
-  DCHECK_EQ(result, UncachedAmIBundled())
-      << "The return value of AmIBundled() changed. This will confuse tests. "
-      << "Call SetAmIBundled() override manually if your test binary "
-      << "delay-loads the framework.";
-  return result;
-}
-
-void SetOverrideAmIBundled(bool value) {
-  g_override_am_i_bundled = true;
-  g_override_am_i_bundled_value = value;
-}
-
-bool IsBackgroundOnlyProcess() {
-  // This function really does want to examine NSBundle's idea of the main
-  // bundle dictionary, and not the overriden MainAppBundle.  It needs to look
-  // at the actual running .app's Info.plist to access its LSUIElement
-  // property.
-  NSDictionary* info_dictionary = [[NSBundle mainBundle] infoDictionary];
-  return [[info_dictionary objectForKey:@"LSUIElement"] boolValue] != NO;
-}
-
-// No threading worries since NSBundle isn't thread safe.
-static NSBundle* g_override_app_bundle = nil;
-
-NSBundle* MainAppBundle() {
-  if (g_override_app_bundle)
-    return g_override_app_bundle;
-  return [NSBundle mainBundle];
-}
-
-FilePath MainAppBundlePath() {
-  NSBundle* bundle = MainAppBundle();
-  return FilePath([[bundle bundlePath] fileSystemRepresentation]);
-}
-
-void SetOverrideAppBundle(NSBundle* bundle) {
-  if (bundle != g_override_app_bundle) {
-    [g_override_app_bundle release];
-    g_override_app_bundle = [bundle retain];
-  }
-}
-
-void SetOverrideAppBundlePath(const FilePath& file_path) {
-  NSString* path = base::SysUTF8ToNSString(file_path.value());
-  NSBundle* bundle = [NSBundle bundleWithPath:path];
-  CHECK(bundle) << "Failed to load the bundle at " << file_path.value();
-
-  SetOverrideAppBundle(bundle);
-}
-
-OSType CreatorCodeForCFBundleRef(CFBundleRef bundle) {
-  OSType creator = kUnknownType;
-  CFBundleGetPackageInfo(bundle, NULL, &creator);
-  return creator;
-}
-
-OSType CreatorCodeForApplication() {
-  CFBundleRef bundle = CFBundleGetMainBundle();
-  if (!bundle)
-    return kUnknownType;
-
-  return CreatorCodeForCFBundleRef(bundle);
-}
-
-bool GetSearchPathDirectory(NSSearchPathDirectory directory,
-                            NSSearchPathDomainMask domain_mask,
-                            FilePath* result) {
-  DCHECK(result);
-  NSArray* dirs =
-      NSSearchPathForDirectoriesInDomains(directory, domain_mask, YES);
-  if ([dirs count] < 1) {
-    return false;
-  }
-  NSString* path = [dirs objectAtIndex:0];
-  *result = FilePath([path fileSystemRepresentation]);
-  return true;
-}
-
-bool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result) {
-  return GetSearchPathDirectory(directory, NSLocalDomainMask, result);
-}
-
-bool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result) {
-  return GetSearchPathDirectory(directory, NSUserDomainMask, result);
-}
-
-FilePath GetUserLibraryPath() {
-  FilePath user_library_path;
-  if (!GetUserDirectory(NSLibraryDirectory, &user_library_path)) {
-    LOG(WARNING) << "Could not get user library path";
-  }
-  return user_library_path;
-}
-
 CGColorSpaceRef GetSRGBColorSpace() {
   // Leaked.  That's OK, it's scoped to the lifetime of the application.
   static CGColorSpaceRef g_color_space_sRGB =
@@ -356,26 +228,6 @@
       [NSWindow performSelector:@selector(_shouldMiniaturizeOnDoubleClick)];
 }
 
-void GrabWindowSnapshot(NSWindow* window,
-    std::vector<unsigned char>* png_representation,
-    int* width, int* height) {
-  // Make sure to grab the "window frame" view so we get current tab +
-  // tabstrip.
-  NSView* view = [[window contentView] superview];
-  NSBitmapImageRep* rep =
-      [view bitmapImageRepForCachingDisplayInRect:[view bounds]];
-  [view cacheDisplayInRect:[view bounds] toBitmapImageRep:rep];
-  NSData* data = [rep representationUsingType:NSPNGFileType properties:nil];
-  const unsigned char* buf = static_cast<const unsigned char*>([data bytes]);
-  NSUInteger length = [data length];
-  if (buf != NULL && length > 0){
-    *width = static_cast<int>([rep pixelsWide]);
-    *height = static_cast<int>([rep pixelsHigh]);
-    png_representation->assign(buf, buf + length);
-    DCHECK(png_representation->size() > 0);
-  }
-}
-
 void ActivateProcess(pid_t pid) {
   ProcessSerialNumber process;
   OSStatus status = GetProcessForPID(pid, &process);
@@ -386,55 +238,6 @@
   }
 }
 
-// Takes a path to an (executable) binary and tries to provide the path to an
-// application bundle containing it. It takes the outermost bundle that it can
-// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app").
-//   |exec_name| - path to the binary
-//   returns - path to the application bundle, or empty on error
-FilePath GetAppBundlePath(const FilePath& exec_name) {
-  const char kExt[] = ".app";
-  const size_t kExtLength = arraysize(kExt) - 1;
-
-  // Split the path into components.
-  std::vector<std::string> components;
-  exec_name.GetComponents(&components);
-
-  // It's an error if we don't get any components.
-  if (!components.size())
-    return FilePath();
-
-  // Don't prepend '/' to the first component.
-  std::vector<std::string>::const_iterator it = components.begin();
-  std::string bundle_name = *it;
-  DCHECK(it->length() > 0);
-  // If the first component ends in ".app", we're already done.
-  if (it->length() > kExtLength &&
-      !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength))
-    return FilePath(bundle_name);
-
-  // The first component may be "/" or "//", etc. Only append '/' if it doesn't
-  // already end in '/'.
-  if (bundle_name[bundle_name.length() - 1] != '/')
-    bundle_name += '/';
-
-  // Go through the remaining components.
-  for (++it; it != components.end(); ++it) {
-    DCHECK(it->length() > 0);
-
-    bundle_name += *it;
-
-    // If the current component ends in ".app", we're done.
-    if (it->length() > kExtLength &&
-        !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength))
-      return FilePath(bundle_name);
-
-    // Separate this component from the next one.
-    bundle_name += '/';
-  }
-
-  return FilePath();
-}
-
 bool SetFileBackupExclusion(const FilePath& file_path, bool exclude) {
   NSString* filePath =
       [NSString stringWithUTF8String:file_path.value().c_str()];
@@ -478,31 +281,6 @@
   return success;
 }
 
-CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
-                                 CFStringRef key,
-                                 CFTypeID expected_type) {
-  CFTypeRef value = CFDictionaryGetValue(dict, key);
-  if (!value)
-    return value;
-
-  if (CFGetTypeID(value) != expected_type) {
-    ScopedCFTypeRef<CFStringRef> expected_type_ref(
-        CFCopyTypeIDDescription(expected_type));
-    ScopedCFTypeRef<CFStringRef> actual_type_ref(
-        CFCopyTypeIDDescription(CFGetTypeID(value)));
-    LOG(WARNING) << "Expected value for key "
-                 << base::SysCFStringRefToUTF8(key)
-                 << " to be "
-                 << base::SysCFStringRefToUTF8(expected_type_ref)
-                 << " but it was "
-                 << base::SysCFStringRefToUTF8(actual_type_ref)
-                 << " instead";
-    return NULL;
-  }
-
-  return value;
-}
-
 void SetProcessName(CFStringRef process_name) {
   if (!process_name || CFStringGetLength(process_name) == 0) {
     NOTREACHED() << "SetProcessName given bad name.";
@@ -702,15 +480,5 @@
   return IsHiddenLoginItem(item);
 }
 
-void NSObjectRetain(void* obj) {
-  id<NSObject> nsobj = static_cast<id<NSObject> >(obj);
-  [nsobj retain];
-}
-
-void NSObjectRelease(void* obj) {
-  id<NSObject> nsobj = static_cast<id<NSObject> >(obj);
-  [nsobj release];
-}
-
 }  // namespace mac
 }  // namespace base
diff --git a/base/mac/mac_util_unittest.mm b/base/mac/mac_util_unittest.mm
index 47ecebf..bae0019 100644
--- a/base/mac/mac_util_unittest.mm
+++ b/base/mac/mac_util_unittest.mm
@@ -1,18 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import <Cocoa/Cocoa.h>
-#include <vector>
 
 #include "base/mac/mac_util.h"
 
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/test/mock_chrome_application_mac.h"
 #include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -53,37 +50,6 @@
   EXPECT_FALSE(library_dir.value().empty());
 }
 
-TEST_F(MacUtilTest, TestGrabWindowSnapshot) {
-  // Launch a test window so we can take a snapshot.
-  [MockCrApp sharedApplication];
-  NSRect frame = NSMakeRect(0, 0, 400, 400);
-  scoped_nsobject<NSWindow> window(
-      [[NSWindow alloc] initWithContentRect:frame
-                                  styleMask:NSBorderlessWindowMask
-                                    backing:NSBackingStoreBuffered
-                                      defer:NO]);
-  [window setBackgroundColor:[NSColor whiteColor]];
-  [window makeKeyAndOrderFront:NSApp];
-
-  scoped_ptr<std::vector<unsigned char> > png_representation(
-      new std::vector<unsigned char>);
-  int width, height;
-  GrabWindowSnapshot(window, png_representation.get(),
-                     &width, &height);
-
-  // Copy png back into NSData object so we can make sure we grabbed a png.
-  scoped_nsobject<NSData> image_data(
-      [[NSData alloc] initWithBytes:&(*png_representation)[0]
-                             length:png_representation->size()]);
-  NSBitmapImageRep* rep = [NSBitmapImageRep imageRepWithData:image_data.get()];
-  EXPECT_TRUE([rep isKindOfClass:[NSBitmapImageRep class]]);
-  EXPECT_TRUE(CGImageGetWidth([rep CGImage]) == 400);
-  NSColor* color = [rep colorAtX:200 y:200];
-  CGFloat red = 0, green = 0, blue = 0, alpha = 0;
-  [color getRed:&red green:&green blue:&blue alpha:&alpha];
-  EXPECT_GE(red + green + blue, 3.0);
-}
-
 TEST_F(MacUtilTest, TestGetAppBundlePath) {
   FilePath out;
 
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 7e35d9f..2ec872f 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -289,6 +289,12 @@
   task_observers_.RemoveObserver(task_observer);
 }
 
+void MessageLoop::AssertIdle() const {
+  // We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
+  base::AutoLock lock(incoming_queue_lock_);
+  DCHECK(incoming_queue_.empty());
+}
+
 //------------------------------------------------------------------------------
 
 // Runs the loop in two different SEH modes:
@@ -399,7 +405,7 @@
 
   // Acquire all we can from the inter-thread queue with one lock acquisition.
   {
-    AutoLock lock(incoming_queue_lock_);
+    base::AutoLock lock(incoming_queue_lock_);
     if (incoming_queue_.empty())
       return;
     incoming_queue_.Swap(&work_queue_);  // Constant time
@@ -500,7 +506,7 @@
 
   scoped_refptr<base::MessagePump> pump;
   {
-    AutoLock locked(incoming_queue_lock_);
+    base::AutoLock locked(incoming_queue_lock_);
 
     bool was_empty = incoming_queue_.empty();
     incoming_queue_.push(pending_task);
diff --git a/base/message_loop.h b/base/message_loop.h
index d5093a9..d238997 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -10,10 +10,10 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/message_pump.h"
 #include "base/observer_list.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 
 #if defined(OS_WIN)
@@ -315,6 +315,9 @@
   // for at least 1s.
   static const int kHighResolutionTimerModeLeaseTimeMs = 1000;
 
+  // Asserts that the MessageLoop is "idle".
+  void AssertIdle() const;
+
   //----------------------------------------------------------------------------
  protected:
   struct RunState {
@@ -461,12 +464,12 @@
   scoped_refptr<base::Histogram> message_histogram_;
 
   // A null terminated list which creates an incoming_queue of tasks that are
-  // aquired under a mutex for processing on this instance's thread. These tasks
+  // acquired under a mutex for processing on this instance's thread. These tasks
   // have not yet been sorted out into items for our work_queue_ vs items that
   // will be handled by the TimerManager.
   TaskQueue incoming_queue_;
   // Protect access to incoming_queue_.
-  Lock incoming_queue_lock_;
+  mutable base::Lock incoming_queue_lock_;
 
   RunState* state_;
 
diff --git a/base/message_loop_proxy_impl.cc b/base/message_loop_proxy_impl.cc
index 3b01fd6..b47c934 100644
--- a/base/message_loop_proxy_impl.cc
+++ b/base/message_loop_proxy_impl.cc
@@ -7,11 +7,6 @@
 
 namespace base {
 
-MessageLoopProxyImpl::MessageLoopProxyImpl()
-    : target_message_loop_(MessageLoop::current()) {
-  target_message_loop_->AddDestructionObserver(this);
-}
-
 MessageLoopProxyImpl::~MessageLoopProxyImpl() {
   AutoLock lock(message_loop_lock_);
   // If the target message loop still exists, the d'tor WILL execute on the
@@ -56,25 +51,10 @@
           (MessageLoop::current() == target_message_loop_));
 }
 
-bool MessageLoopProxyImpl::PostTaskHelper(
-    const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
-    bool nestable) {
-  bool ret = false;
-  {
-    AutoLock lock(message_loop_lock_);
-    if (target_message_loop_) {
-      if (nestable) {
-        target_message_loop_->PostDelayedTask(from_here, task, delay_ms);
-      } else {
-        target_message_loop_->PostNonNestableDelayedTask(from_here, task,
-                                                         delay_ms);
-      }
-      ret = true;
-    }
-  }
-  if (!ret)
-    delete task;
-  return ret;
+// MessageLoop::DestructionObserver implementation
+void MessageLoopProxyImpl::WillDestroyCurrentMessageLoop() {
+  AutoLock lock(message_loop_lock_);
+  target_message_loop_ = NULL;
 }
 
 void MessageLoopProxyImpl::OnDestruct() const {
@@ -96,10 +76,30 @@
     delete this;
 }
 
-// MessageLoop::DestructionObserver implementation
-void MessageLoopProxyImpl::WillDestroyCurrentMessageLoop() {
-  AutoLock lock(message_loop_lock_);
-  target_message_loop_ = NULL;
+MessageLoopProxyImpl::MessageLoopProxyImpl()
+    : target_message_loop_(MessageLoop::current()) {
+  target_message_loop_->AddDestructionObserver(this);
+}
+
+bool MessageLoopProxyImpl::PostTaskHelper(
+    const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
+    bool nestable) {
+  bool ret = false;
+  {
+    AutoLock lock(message_loop_lock_);
+    if (target_message_loop_) {
+      if (nestable) {
+        target_message_loop_->PostDelayedTask(from_here, task, delay_ms);
+      } else {
+        target_message_loop_->PostNonNestableDelayedTask(from_here, task,
+                                                         delay_ms);
+      }
+      ret = true;
+    }
+  }
+  if (!ret)
+    delete task;
+  return ret;
 }
 
 scoped_refptr<MessageLoopProxy>
diff --git a/base/message_loop_proxy_impl.h b/base/message_loop_proxy_impl.h
index 44ab2ea..03e0271 100644
--- a/base/message_loop_proxy_impl.h
+++ b/base/message_loop_proxy_impl.h
@@ -6,9 +6,9 @@
 #define BASE_MESSAGE_LOOP_PROXY_IMPL_H_
 #pragma once
 
-#include "base/lock.h"
 #include "base/message_loop.h"
 #include "base/message_loop_proxy.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 
@@ -50,7 +50,7 @@
   friend class MessageLoopProxy;
 
   // The lock that protects access to target_message_loop_.
-  mutable Lock message_loop_lock_;
+  mutable base::Lock message_loop_lock_;
   MessageLoop* target_message_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageLoopProxyImpl);
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index c471e38..9576a58 100644
--- a/base/message_loop_unittest.cc
+++ b/base/message_loop_unittest.cc
@@ -1555,18 +1555,18 @@
   const int kFastTimerMs = 5;
   const int kSlowTimerMs = 100;
 
-  EXPECT_EQ(false, loop.high_resolution_timers_enabled());
+  EXPECT_FALSE(loop.high_resolution_timers_enabled());
 
   // Post a fast task to enable the high resolution timers.
   loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kFastTimerMs);
   loop.Run();
-  EXPECT_EQ(true, loop.high_resolution_timers_enabled());
+  EXPECT_TRUE(loop.high_resolution_timers_enabled());
 
   // Post a slow task and verify high resolution timers
   // are still enabled.
   loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs);
   loop.Run();
-  EXPECT_EQ(true, loop.high_resolution_timers_enabled());
+  EXPECT_TRUE(loop.high_resolution_timers_enabled());
 
   // Wait for a while so that high-resolution mode elapses.
   Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs);
@@ -1574,7 +1574,7 @@
   // Post a slow task to disable the high resolution timers.
   loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs);
   loop.Run();
-  EXPECT_EQ(false, loop.high_resolution_timers_enabled());
+  EXPECT_FALSE(loop.high_resolution_timers_enabled());
 }
 
 #endif  // defined(OS_WIN)
diff --git a/base/message_pump_glib.cc b/base/message_pump_glib.cc
index b9dcc46..721fedb 100644
--- a/base/message_pump_glib.cc
+++ b/base/message_pump_glib.cc
@@ -303,16 +303,15 @@
   observers_.RemoveObserver(observer);
 }
 
-MessagePumpForUI::Dispatcher* MessagePumpForUI::GetDispatcher() {
-  return state_ ? state_->dispatcher : NULL;
-}
-
-void MessagePumpForUI::WillProcessEvent(GdkEvent* event) {
-  FOR_EACH_OBSERVER(Observer, observers_, WillProcessEvent(event));
-}
-
-void MessagePumpForUI::DidProcessEvent(GdkEvent* event) {
-  FOR_EACH_OBSERVER(Observer, observers_, DidProcessEvent(event));
+void MessagePumpForUI::DispatchEvents(GdkEvent* event) {
+  WillProcessEvent(event);
+  if (state_ && state_->dispatcher) { // state_ may be null during tests.
+    if (!state_->dispatcher->Dispatch(event))
+      state_->should_quit = true;
+  } else {
+    gtk_main_do_event(event);
+  }
+  DidProcessEvent(event);
 }
 
 void MessagePumpForUI::Run(Delegate* delegate) {
@@ -344,15 +343,16 @@
   ScheduleWork();
 }
 
-void MessagePumpForUI::DispatchEvents(GdkEvent* event) {
-  WillProcessEvent(event);
-  if (state_ && state_->dispatcher) { // state_ may be null during tests.
-    if (!state_->dispatcher->Dispatch(event))
-      state_->should_quit = true;
-  } else {
-    gtk_main_do_event(event);
-  }
-  DidProcessEvent(event);
+MessagePumpForUI::Dispatcher* MessagePumpForUI::GetDispatcher() {
+  return state_ ? state_->dispatcher : NULL;
+}
+
+void MessagePumpForUI::WillProcessEvent(GdkEvent* event) {
+  FOR_EACH_OBSERVER(Observer, observers_, WillProcessEvent(event));
+}
+
+void MessagePumpForUI::DidProcessEvent(GdkEvent* event) {
+  FOR_EACH_OBSERVER(Observer, observers_, DidProcessEvent(event));
 }
 
 // static
diff --git a/base/message_pump_glib_unittest.cc b/base/message_pump_glib_unittest.cc
index 9c9f288..fc604b9 100644
--- a/base/message_pump_glib_unittest.cc
+++ b/base/message_pump_glib_unittest.cc
@@ -45,7 +45,6 @@
   bool HandleCheck() {
     if (events_.empty())
       return false;
-    Event event = events_[0];
     return events_[0].time <= base::Time::NowFromSystemTime();
   }
 
diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc
index 775e940..e27a07a 100644
--- a/base/message_pump_glib_x.cc
+++ b/base/message_pump_glib_x.cc
@@ -82,6 +82,41 @@
 MessagePumpGlibX::~MessagePumpGlibX() {
 }
 
+#if defined(HAVE_XINPUT2)
+void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) {
+  Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+
+  // Setup mask for mouse events.
+  unsigned char mask[(XI_LASTEVENT + 7)/8];
+  memset(mask, 0, sizeof(mask));
+
+  XISetMask(mask, XI_ButtonPress);
+  XISetMask(mask, XI_ButtonRelease);
+  XISetMask(mask, XI_Motion);
+
+  // It is necessary to select only for the master devices. XInput2 provides
+  // enough information to the event callback to decide which slave device
+  // triggered the event, thus decide whether the 'pointer event' is a 'mouse
+  // event' or a 'touch event'. So it is not necessary to select for the slave
+  // devices here.
+  XIEventMask evmasks[masters_.size()];
+  int count = 0;
+  for (std::set<int>::const_iterator iter = masters_.begin();
+       iter != masters_.end();
+       ++iter, ++count) {
+    evmasks[count].deviceid = *iter;
+    evmasks[count].mask_len = sizeof(mask);
+    evmasks[count].mask = mask;
+  }
+
+  XISelectEvents(xdisplay, xwindow, evmasks, masters_.size());
+
+  // TODO(sad): Setup masks for keyboard events.
+
+  XFlush(xdisplay);
+}
+#endif  // HAVE_XINPUT2
+
 bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
   GdkDisplay* gdisp = gdk_display_get_default();
   if (!gdisp)
@@ -110,7 +145,7 @@
 
       MessagePumpGlibXDispatcher::DispatchStatus status =
           static_cast<MessagePumpGlibXDispatcher*>
-          (GetDispatcher())->Dispatch(&xev);
+          (GetDispatcher())->DispatchX(&xev);
 
       if (status == MessagePumpGlibXDispatcher::EVENT_QUIT) {
         should_quit = true;
@@ -166,6 +201,25 @@
   return retvalue;
 }
 
+void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
+  MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data);
+
+  if (!pump_x->gdksource_) {
+    pump_x->gdksource_ = g_main_current_source();
+    pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch;
+  } else if (!pump_x->IsDispatchingEvent()) {
+    if (event->type != GDK_NOTHING &&
+        pump_x->capture_gdk_events_[event->type]) {
+      // TODO(sad): An X event is caught by the GDK handler. Put it back in the
+      // X queue so that we catch it in the next iteration. When done, the
+      // following DLOG statement will be removed.
+      DLOG(WARNING) << "GDK received an event it shouldn't have";
+    }
+  }
+
+  pump_x->DispatchEvents(event);
+}
+
 void MessagePumpGlibX::InitializeEventsToCapture(void) {
   // TODO(sad): Decide which events we want to capture and update the tables
   // accordingly.
@@ -237,59 +291,6 @@
   // put it off for a later time.
   // Note: It is not necessary to listen for XI_DeviceChanged events.
 }
-
-void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) {
-  Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-
-  // Setup mask for mouse events.
-  unsigned char mask[(XI_LASTEVENT + 7)/8];
-  memset(mask, 0, sizeof(mask));
-
-  XISetMask(mask, XI_ButtonPress);
-  XISetMask(mask, XI_ButtonRelease);
-  XISetMask(mask, XI_Motion);
-
-  // It is necessary to select only for the master devices. XInput2 provides
-  // enough information to the event callback to decide which slave device
-  // triggered the event, thus decide whether the 'pointer event' is a 'mouse
-  // event' or a 'touch event'. So it is not necessary to select for the slave
-  // devices here.
-  XIEventMask evmasks[masters_.size()];
-  int count = 0;
-  for (std::set<int>::const_iterator iter = masters_.begin();
-       iter != masters_.end();
-       ++iter, ++count) {
-    evmasks[count].deviceid = *iter;
-    evmasks[count].mask_len = sizeof(mask);
-    evmasks[count].mask = mask;
-  }
-
-  XISelectEvents(xdisplay, xwindow, evmasks, masters_.size());
-
-  // TODO(sad): Setup masks for keyboard events.
-
-  XFlush(xdisplay);
-}
-
 #endif  // HAVE_XINPUT2
 
-void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
-  MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data);
-
-  if (!pump_x->gdksource_) {
-    pump_x->gdksource_ = g_main_current_source();
-    pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch;
-  } else if (!pump_x->IsDispatchingEvent()) {
-    if (event->type != GDK_NOTHING &&
-        pump_x->capture_gdk_events_[event->type]) {
-      // TODO(sad): An X event is caught by the GDK handler. Put it back in the
-      // X queue so that we catch it in the next iteration. When done, the
-      // following DLOG statement will be removed.
-      DLOG(WARNING) << "GDK received an event it shouldn't have";
-    }
-  }
-
-  pump_x->DispatchEvents(event);
-}
-
 }  // namespace base
diff --git a/base/message_pump_glib_x_dispatch.h b/base/message_pump_glib_x_dispatch.h
index 4a97372..4c44cab 100644
--- a/base/message_pump_glib_x_dispatch.h
+++ b/base/message_pump_glib_x_dispatch.h
@@ -28,7 +28,7 @@
   // Dispatches the event. EVENT_IGNORED is returned if the event was ignored
   // (i.e. not processed). EVENT_PROCESSED is returned if the event was
   // processed. The nested loop exits immediately if EVENT_QUIT is returned.
-  virtual DispatchStatus Dispatch(XEvent* xevent) = 0;
+  virtual DispatchStatus DispatchX(XEvent* xevent) = 0;
 };
 
 }  // namespace base
diff --git a/base/message_pump_libevent.cc b/base/message_pump_libevent.cc
index 1410f79..933d795 100644
--- a/base/message_pump_libevent.cc
+++ b/base/message_pump_libevent.cc
@@ -62,6 +62,19 @@
   }
 }
 
+bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
+  event* e = ReleaseEvent();
+  if (e == NULL)
+    return true;
+
+  // event_del() is a no-op if the event isn't active.
+  int rv = event_del(e);
+  delete e;
+  pump_ = NULL;
+  watcher_ = NULL;
+  return (rv == 0);
+}
+
 void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e,
                                                       bool is_persistent) {
   DCHECK(e);
@@ -77,19 +90,6 @@
   return e;
 }
 
-bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
-  event* e = ReleaseEvent();
-  if (e == NULL)
-    return true;
-
-  // event_del() is a no-op if the event isn't active.
-  int rv = event_del(e);
-  delete e;
-  pump_ = NULL;
-  watcher_ = NULL;
-  return (rv == 0);
-}
-
 void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
     int fd, MessagePumpLibevent* pump) {
   pump->WillProcessIOEvent();
@@ -104,20 +104,6 @@
   pump->DidProcessIOEvent();
 }
 
-// Called if a byte is received on the wakeup pipe.
-void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
-  base::MessagePumpLibevent* that =
-              static_cast<base::MessagePumpLibevent*>(context);
-  DCHECK(that->wakeup_pipe_out_ == socket);
-
-  // Remove and discard the wakeup byte.
-  char buf;
-  int nread = HANDLE_EINTR(read(socket, &buf, 1));
-  DCHECK_EQ(nread, 1);
-  // Tell libevent to break out of inner loop.
-  event_base_loopbreak(that->event_base_);
-}
-
 MessagePumpLibevent::MessagePumpLibevent()
     : keep_running_(true),
       in_run_(false),
@@ -128,33 +114,6 @@
      NOTREACHED();
 }
 
-bool MessagePumpLibevent::Init() {
-  int fds[2];
-  if (pipe(fds)) {
-    DLOG(ERROR) << "pipe() failed, errno: " << errno;
-    return false;
-  }
-  if (SetNonBlocking(fds[0])) {
-    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
-    return false;
-  }
-  if (SetNonBlocking(fds[1])) {
-    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
-    return false;
-  }
-  wakeup_pipe_out_ = fds[0];
-  wakeup_pipe_in_ = fds[1];
-
-  wakeup_event_ = new event;
-  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
-            OnWakeup, this);
-  event_base_set(event_base_, wakeup_event_);
-
-  if (event_add(wakeup_event_, 0))
-    return false;
-  return true;
-}
-
 MessagePumpLibevent::~MessagePumpLibevent() {
   DCHECK(wakeup_event_);
   DCHECK(event_base_);
@@ -234,19 +193,12 @@
   return true;
 }
 
-void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
-                                                 void* context) {
-  FileDescriptorWatcher* controller =
-      static_cast<FileDescriptorWatcher*>(context);
+void MessagePumpLibevent::AddIOObserver(IOObserver *obs) {
+  io_observers_.AddObserver(obs);
+}
 
-  MessagePumpLibevent* pump = controller->pump();
-
-  if (flags & EV_WRITE) {
-    controller->OnFileCanWriteWithoutBlocking(fd, pump);
-  }
-  if (flags & EV_READ) {
-    controller->OnFileCanReadWithoutBlocking(fd, pump);
-  }
+void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) {
+  io_observers_.RemoveObserver(obs);
 }
 
 // Tell libevent to break out of inner loop.
@@ -334,14 +286,6 @@
   delayed_work_time_ = delayed_work_time;
 }
 
-void MessagePumpLibevent::AddIOObserver(IOObserver *obs) {
-  io_observers_.AddObserver(obs);
-}
-
-void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) {
-  io_observers_.RemoveObserver(obs);
-}
-
 void MessagePumpLibevent::WillProcessIOEvent() {
   FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
 }
@@ -350,4 +294,62 @@
   FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
 }
 
+bool MessagePumpLibevent::Init() {
+  int fds[2];
+  if (pipe(fds)) {
+    DLOG(ERROR) << "pipe() failed, errno: " << errno;
+    return false;
+  }
+  if (SetNonBlocking(fds[0])) {
+    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
+    return false;
+  }
+  if (SetNonBlocking(fds[1])) {
+    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
+    return false;
+  }
+  wakeup_pipe_out_ = fds[0];
+  wakeup_pipe_in_ = fds[1];
+
+  wakeup_event_ = new event;
+  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
+            OnWakeup, this);
+  event_base_set(event_base_, wakeup_event_);
+
+  if (event_add(wakeup_event_, 0))
+    return false;
+  return true;
+}
+
+// static
+void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
+                                                 void* context) {
+  FileDescriptorWatcher* controller =
+      static_cast<FileDescriptorWatcher*>(context);
+
+  MessagePumpLibevent* pump = controller->pump();
+
+  if (flags & EV_WRITE) {
+    controller->OnFileCanWriteWithoutBlocking(fd, pump);
+  }
+  if (flags & EV_READ) {
+    controller->OnFileCanReadWithoutBlocking(fd, pump);
+  }
+}
+
+// Called if a byte is received on the wakeup pipe.
+// static
+void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
+  base::MessagePumpLibevent* that =
+              static_cast<base::MessagePumpLibevent*>(context);
+  DCHECK(that->wakeup_pipe_out_ == socket);
+
+  // Remove and discard the wakeup byte.
+  char buf;
+  int nread = HANDLE_EINTR(read(socket, &buf, 1));
+  DCHECK_EQ(nread, 1);
+  // Tell libevent to break out of inner loop.
+  event_base_loopbreak(that->event_base_);
+}
+
 }  // namespace base
diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc
index 0df888a..d3f3621 100644
--- a/base/message_pump_win.cc
+++ b/base/message_pump_win.cc
@@ -421,7 +421,7 @@
                                          IOHandler* handler) {
   ULONG_PTR key = reinterpret_cast<ULONG_PTR>(handler);
   HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1);
-  DCHECK(port == port_.Get());
+  DPCHECK(port);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index d29ed2d..fceccde 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -7,14 +7,15 @@
 #include "base/logging.h"
 #include "base/rand_util.h"
 #include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
 
 namespace base {
 
 // static
-const int FieldTrial::kNotParticipating = -1;
+const int FieldTrial::kNotFinalized = -1;
 
 // static
-const int FieldTrial::kAllRemainingProbability = -2;
+const int FieldTrial::kDefaultGroupNumber = 0;
 
 // static
 bool FieldTrial::enable_benchmarking_ = false;
@@ -28,30 +29,53 @@
 // FieldTrial methods and members.
 
 FieldTrial::FieldTrial(const std::string& name,
-                       const Probability total_probability)
+                       const Probability total_probability,
+                       const std::string& default_group_name,
+                       const int year,
+                       const int month,
+                       const int day_of_month)
   : name_(name),
     divisor_(total_probability),
+    default_group_name_(default_group_name),
     random_(static_cast<Probability>(divisor_ * base::RandDouble())),
     accumulated_group_probability_(0),
-    next_group_number_(0),
-    group_(kNotParticipating) {
+    next_group_number_(kDefaultGroupNumber+1),
+    group_(kNotFinalized) {
+  DCHECK(!default_group_name_.empty());
   FieldTrialList::Register(this);
+
+  DCHECK_GT(year, 1970);
+  DCHECK_GT(month, 0);
+  DCHECK_LT(month, 13);
+  DCHECK_GT(day_of_month, 0);
+  DCHECK_LT(day_of_month, 32);
+
+  base::Time::Exploded exploded;
+  exploded.year = year;
+  exploded.month = month;
+  exploded.day_of_week = 0;  // Should be unusued.
+  exploded.day_of_month = day_of_month;
+  exploded.hour = 0;
+  exploded.minute = 0;
+  exploded.second = 0;
+  exploded.millisecond = 0;
+
+  base::Time expiration_time = Time::FromLocalExploded(exploded);
+  disable_field_trial_ = (GetBuildTime() > expiration_time) ? true : false;
 }
 
 int FieldTrial::AppendGroup(const std::string& name,
                             Probability group_probability) {
   DCHECK(group_probability <= divisor_);
-  DCHECK(group_probability >=0 ||
-         group_probability == kAllRemainingProbability);
-  if (group_probability == kAllRemainingProbability) {
-    accumulated_group_probability_ = divisor_;
-  } else {
-    if (enable_benchmarking_)
-      group_probability = 0;
-    accumulated_group_probability_ += group_probability;
-  }
+  DCHECK_GE(group_probability, 0);
+
+  if (enable_benchmarking_ || disable_field_trial_)
+    group_probability = 0;
+
+  accumulated_group_probability_ += group_probability;
+
   DCHECK(accumulated_group_probability_ <= divisor_);
-  if (group_ == kNotParticipating && accumulated_group_probability_ > random_) {
+  if (group_ == kNotFinalized && accumulated_group_probability_ > random_) {
     // This is the group that crossed the random line, so we do the assignment.
     group_ = next_group_number_;
     if (name.empty())
@@ -62,6 +86,20 @@
   return next_group_number_++;
 }
 
+int FieldTrial::group() {
+  if (group_ == kNotFinalized) {
+    accumulated_group_probability_ = divisor_;
+    group_ = kDefaultGroupNumber;
+    group_name_ = default_group_name_;
+  }
+  return group_;
+}
+
+std::string FieldTrial::group_name() {
+  group();  // call group() to make group assignment was done.
+  return group_name_;
+}
+
 // static
 std::string FieldTrial::MakeName(const std::string& name_prefix,
                                  const std::string& trial_name) {
@@ -78,6 +116,16 @@
 
 FieldTrial::~FieldTrial() {}
 
+// static
+Time FieldTrial::GetBuildTime() {
+  Time integral_build_time;
+  const char* kDateTime = __DATE__ " " __TIME__;
+  bool result = Time::FromString(ASCIIToWide(kDateTime).c_str(),
+                                 &integral_build_time);
+  DCHECK(result);
+  return integral_build_time;
+}
+
 //------------------------------------------------------------------------------
 // FieldTrialList methods and members.
 
@@ -117,11 +165,19 @@
 }
 
 // static
+FieldTrial* FieldTrialList::Find(const std::string& name) {
+  if (!global_)
+    return NULL;
+  AutoLock auto_lock(global_->lock_);
+  return global_->PreLockedFind(name);
+}
+
+// static
 int FieldTrialList::FindValue(const std::string& name) {
   FieldTrial* field_trial = Find(name);
   if (field_trial)
     return field_trial->group();
-  return FieldTrial::kNotParticipating;
+  return FieldTrial::kNotFinalized;
 }
 
 // static
@@ -133,21 +189,6 @@
 }
 
 // static
-FieldTrial* FieldTrialList::Find(const std::string& name) {
-  if (!global_)
-    return NULL;
-  AutoLock auto_lock(global_->lock_);
-  return global_->PreLockedFind(name);
-}
-
-FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) {
-  RegistrationList::iterator it = registered_.find(name);
-  if (registered_.end() == it)
-    return NULL;
-  return it->second;
-}
-
-// static
 void FieldTrialList::StatesToString(std::string* output) {
   if (!global_)
     return;
@@ -156,9 +197,11 @@
   for (RegistrationList::iterator it = global_->registered_.begin();
        it != global_->registered_.end(); ++it) {
     const std::string name = it->first;
-    const std::string group_name = it->second->group_name();
+    std::string group_name = it->second->group_name_internal();
     if (group_name.empty())
-      continue;  // No definitive winner in this trial.
+      // No definitive winner in this trial, use default_group_name as the
+      // group_name.
+      group_name = it->second->default_group_name();
     DCHECK_EQ(name.find(kPersistentStringSeparator), std::string::npos);
     DCHECK_EQ(group_name.find(kPersistentStringSeparator), std::string::npos);
     output->append(name);
@@ -169,34 +212,43 @@
 }
 
 // static
-bool FieldTrialList::StringAugmentsState(const std::string& prior_state) {
+bool FieldTrialList::CreateTrialsInChildProcess(
+    const std::string& parent_trials) {
   DCHECK(global_);
-  if (prior_state.empty() || !global_)
+  if (parent_trials.empty() || !global_)
     return true;
 
+  Time::Exploded exploded;
+  Time two_years_from_now =
+      Time::NowFromSystemTime() + TimeDelta::FromDays(730);
+  two_years_from_now.LocalExplode(&exploded);
+  const int kTwoYearsFromNow = exploded.year;
+
   size_t next_item = 0;
-  while (next_item < prior_state.length()) {
-    size_t name_end = prior_state.find(kPersistentStringSeparator, next_item);
-    if (name_end == prior_state.npos || next_item == name_end)
+  while (next_item < parent_trials.length()) {
+    size_t name_end = parent_trials.find(kPersistentStringSeparator, next_item);
+    if (name_end == parent_trials.npos || next_item == name_end)
       return false;
-    size_t group_name_end = prior_state.find(kPersistentStringSeparator,
-                                             name_end + 1);
-    if (group_name_end == prior_state.npos || name_end + 1 == group_name_end)
+    size_t group_name_end = parent_trials.find(kPersistentStringSeparator,
+                                               name_end + 1);
+    if (group_name_end == parent_trials.npos || name_end + 1 == group_name_end)
       return false;
-    std::string name(prior_state, next_item, name_end - next_item);
-    std::string group_name(prior_state, name_end + 1,
+    std::string name(parent_trials, next_item, name_end - next_item);
+    std::string group_name(parent_trials, name_end + 1,
                            group_name_end - name_end - 1);
     next_item = group_name_end + 1;
 
     FieldTrial *field_trial(FieldTrialList::Find(name));
     if (field_trial) {
       // In single process mode, we may have already created the field trial.
-      if (field_trial->group_name() != group_name)
+      if ((field_trial->group_name_internal() != group_name) &&
+          (field_trial->default_group_name() != group_name))
         return false;
       continue;
     }
     const int kTotalProbability = 100;
-    field_trial = new FieldTrial(name, kTotalProbability);
+    field_trial = new FieldTrial(name, kTotalProbability, group_name,
+                                 kTwoYearsFromNow, 1, 1);
     field_trial->AppendGroup(group_name, kTotalProbability);
   }
   return true;
@@ -210,4 +262,11 @@
   return global_->registered_.size();
 }
 
+FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) {
+  RegistrationList::iterator it = registered_.find(name);
+  if (registered_.end() == it)
+    return NULL;
+  return it->second;
+}
+
 }  // namespace base
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index 8902077..ec3a483 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -66,36 +66,40 @@
 #include <map>
 #include <string>
 
-#include "base/lock.h"
+#include "base/gtest_prod_util.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 
 namespace base {
 
+class FieldTrialList;
+
 class FieldTrial : public RefCounted<FieldTrial> {
  public:
   typedef int Probability;  // Probability type for being selected in a trial.
 
   // A return value to indicate that a given instance has not yet had a group
   // assignment (and hence is not yet participating in the trial).
-  static const int kNotParticipating;
+  static const int kNotFinalized;
 
-  // Provide an easy way to assign all remaining probability to a group.  Note
-  // that this will force an instance to participate, and make it illegal to
-  // attempt to probabalistically add any other groups to the trial.  When doing
-  // A/B tests with timings, it is often best to define all groups, so that
-  // histograms will get unique names via the MakeName() methods.
-  static const Probability kAllRemainingProbability;
+  // This is the group number of the 'default' group. This provides an easy way
+  // to assign all the remaining probability to a group ('default').
+  static const int kDefaultGroupNumber;
 
   // The name is used to register the instance with the FieldTrialList class,
   // and can be used to find the trial (only one trial can be present for each
   // name).
   // Group probabilities that are later supplied must sum to less than or equal
-  // to the total_probability.
-  FieldTrial(const std::string& name, Probability total_probability);
+  // to the total_probability. Arguments year, month and day_of_month specify
+  // the expiration time. If the build time is after the expiration time then
+  // the field trial reverts to the 'default' group.
+  FieldTrial(const std::string& name, Probability total_probability,
+             const std::string& default_group_name, const int year,
+             const int month, const int day_of_month);
 
   // Establish the name and probability of the next group in this trial.
-  // Sometimes, based on construction randomization, this call may causes the
+  // Sometimes, based on construction randomization, this call may cause the
   // provided group to be *THE* group selected for use in this instance.
   int AppendGroup(const std::string& name, Probability group_probability);
 
@@ -103,14 +107,18 @@
   std::string name() const { return name_; }
 
   // Return the randomly selected group number that was assigned.
-  // Return kNotParticipating if the instance is not participating in the
-  // experiment.
-  int group() const { return group_; }
+  // Return kDefaultGroupNumber if the instance is in the 'default' group.
+  // Note that this will force an instance to participate, and make it illegal
+  // to attempt to probabalistically add any other groups to the trial.
+  int group();
 
   // If the field trial is not in an experiment, this returns the empty string.
   // if the group's name is empty, a name of "_" concatenated with the group
   // number is used as the group name.
-  std::string group_name() const { return group_name_; }
+  std::string group_name();
+
+  // Return the default group name of the FieldTrial.
+  std::string default_group_name() const { return default_group_name_; }
 
   // Helper function for the most common use: as an argument to specifiy the
   // name of a HISTOGRAM.  Use the original histogram name as the name_prefix.
@@ -121,17 +129,40 @@
   static void EnableBenchmarking();
 
  private:
+  // Allow tests to access our innards for testing purposes.
+  FRIEND_TEST(FieldTrialTest, Registration);
+  FRIEND_TEST(FieldTrialTest, AbsoluteProbabilities);
+  FRIEND_TEST(FieldTrialTest, RemainingProbability);
+  FRIEND_TEST(FieldTrialTest, FiftyFiftyProbability);
+  FRIEND_TEST(FieldTrialTest, MiddleProbabilities);
+  FRIEND_TEST(FieldTrialTest, OneWinner);
+  FRIEND_TEST(FieldTrialTest, DisableProbability);
+  FRIEND_TEST(FieldTrialTest, Save);
+  FRIEND_TEST(FieldTrialTest, DuplicateRestore);
+  FRIEND_TEST(FieldTrialTest, MakeName);
+
+  friend class base::FieldTrialList;
+
   friend class RefCounted<FieldTrial>;
 
   virtual ~FieldTrial();
 
+  // Returns the group_name. A winner need not have been chosen.
+  std::string group_name_internal() const { return group_name_; }
+
+  // Get build time.
+  static Time GetBuildTime();
+
   // The name of the field trial, as can be found via the FieldTrialList.
   // This is empty of the trial is not in the experiment.
   const std::string name_;
 
   // The maximum sum of all probabilities supplied, which corresponds to 100%.
   // This is the scaling factor used to adjust supplied probabilities.
-  Probability divisor_;
+  const Probability divisor_;
+
+  // The name of the default group.
+  const std::string default_group_name_;
 
   // The randomly selected probability that is used to select a group (or have
   // the instance not participate).  It is the product of divisor_ and a random
@@ -144,15 +175,19 @@
   int next_group_number_;
 
   // The pseudo-randomly assigned group number.
-  // This is kNotParticipating if no group has been assigned.
+  // This is kNotFinalized if no group has been assigned.
   int group_;
 
-  // A textual name for the randomly selected group, including the Trial name.
-  // If this Trial is not a member of an group, this string is empty.
+  // A textual name for the randomly selected group. If this Trial is not a
+  // member of an group, this string is empty.
   std::string group_name_;
 
+  // When disable_field_trial_ is true, field trial reverts to the 'default'
+  // group.
+  bool disable_field_trial_;
+
   // When benchmarking is enabled, field trials all revert to the 'default'
-  // bucket.
+  // group.
   static bool enable_benchmarking_;
 
   DISALLOW_COPY_AND_ASSIGN(FieldTrial);
@@ -199,7 +234,7 @@
   // is commonly used in a sub-process, to carry randomly selected state in a
   // parent process into this sub-process.
   //  Currently only the group_name_ and name_ are restored.
-  static bool StringAugmentsState(const std::string& prior_state);
+  static bool CreateTrialsInChildProcess(const std::string& prior_trials);
 
   // The time of construction of the global map is recorded in a static variable
   // and is commonly used by experiments to identify the time since the start
@@ -236,7 +271,7 @@
   TimeTicks application_start_time_;
 
   // Lock for access to registered_.
-  Lock lock_;
+  base::Lock lock_;
   RegistrationList registered_;
 
   DISALLOW_COPY_AND_ASSIGN(FieldTrialList);
diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc
index a8138bb..0af6d60 100644
--- a/base/metrics/field_trial_unittest.cc
+++ b/base/metrics/field_trial_unittest.cc
@@ -13,7 +13,23 @@
 
 class FieldTrialTest : public testing::Test {
  public:
-  FieldTrialTest() : trial_list_() { }
+  FieldTrialTest() : trial_list_() {
+    Time now = Time::NowFromSystemTime();
+    TimeDelta oneYear = TimeDelta::FromDays(365);
+    Time::Exploded exploded;
+
+    Time next_year_time = now + oneYear;
+    next_year_time.LocalExplode(&exploded);
+    next_year_ = exploded.year;
+
+    Time last_year_time = now - oneYear;
+    last_year_time.LocalExplode(&exploded);
+    last_year_ = exploded.year;
+  }
+
+ protected:
+  int next_year_;
+  int last_year_;
 
  private:
   FieldTrialList trial_list_;
@@ -27,20 +43,22 @@
   EXPECT_FALSE(FieldTrialList::Find(name1));
   EXPECT_FALSE(FieldTrialList::Find(name2));
 
-  FieldTrial* trial1 = new FieldTrial(name1, 10);
-  EXPECT_EQ(FieldTrial::kNotParticipating, trial1->group());
+  FieldTrial* trial1 =
+      new FieldTrial(name1, 10, "default name 1 test", next_year_, 12, 31);
+  EXPECT_EQ(FieldTrial::kNotFinalized, trial1->group_);
   EXPECT_EQ(name1, trial1->name());
-  EXPECT_EQ("", trial1->group_name());
+  EXPECT_EQ("", trial1->group_name_internal());
 
   trial1->AppendGroup("", 7);
 
   EXPECT_EQ(trial1, FieldTrialList::Find(name1));
   EXPECT_FALSE(FieldTrialList::Find(name2));
 
-  FieldTrial* trial2 = new FieldTrial(name2, 10);
-  EXPECT_EQ(FieldTrial::kNotParticipating, trial2->group());
+  FieldTrial* trial2 =
+      new FieldTrial(name2, 10, "default name 2 test", next_year_, 12, 31);
+  EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
   EXPECT_EQ(name2, trial2->name());
-  EXPECT_EQ("", trial2->group_name());
+  EXPECT_EQ("", trial2->group_name_internal());
 
   trial2->AppendGroup("a first group", 7);
 
@@ -51,20 +69,28 @@
 
 TEST_F(FieldTrialTest, AbsoluteProbabilities) {
   char always_true[] = " always true";
+  char default_always_true[] = " default always true";
   char always_false[] = " always false";
+  char default_always_false[] = " default always false";
   for (int i = 1; i < 250; ++i) {
     // Try lots of names, by changing the first character of the name.
     always_true[0] = i;
+    default_always_true[0] = i;
     always_false[0] = i;
+    default_always_false[0] = i;
 
-    FieldTrial* trial_true = new FieldTrial(always_true, 10);
+    FieldTrial* trial_true =
+        new FieldTrial(
+            always_true, 10, default_always_true, next_year_, 12, 31);
     const std::string winner = "TheWinner";
     int winner_group = trial_true->AppendGroup(winner, 10);
 
     EXPECT_EQ(winner_group, trial_true->group());
     EXPECT_EQ(winner, trial_true->group_name());
 
-    FieldTrial* trial_false = new FieldTrial(always_false, 10);
+    FieldTrial* trial_false =
+        new FieldTrial(
+            always_false, 10, default_always_false, next_year_, 12, 31);
     int loser_group = trial_false->AppendGroup("ALoser", 0);
 
     EXPECT_NE(loser_group, trial_false->group());
@@ -79,12 +105,13 @@
   int counter = 0;
   do {
     std::string name = StringPrintf("trial%d", ++counter);
-    trial = new FieldTrial(name, 10);
+    trial = new FieldTrial(name, 10, winner, next_year_, 12, 31);
     trial->AppendGroup(loser, 5);  // 50% chance of not being chosen.
-  } while (trial->group() != FieldTrial::kNotParticipating);
+    // If a group is not assigned, group_ will be kNotFinalized.
+  } while (trial->group_ != FieldTrial::kNotFinalized);
 
-  // Now add a winner with all remaining probability.
-  trial->AppendGroup(winner, FieldTrial::kAllRemainingProbability);
+  // And that 'default' group (winner) should always win.
+  EXPECT_EQ(FieldTrial::kDefaultGroupNumber, trial->group());
 
   // And that winner should ALWAYS win.
   EXPECT_EQ(winner, trial->group_name());
@@ -100,14 +127,18 @@
   int counter = 0;
   do {
     std::string name = base::StringPrintf("FiftyFifty%d", ++counter);
-    scoped_refptr<FieldTrial> trial(new FieldTrial(name, 2));
+    std::string default_group_name = base::StringPrintf("Default FiftyFifty%d",
+                                                        ++counter);
+    scoped_refptr<FieldTrial> trial(
+        new FieldTrial(name, 2, default_group_name, next_year_, 12, 31));
     trial->AppendGroup("first", 1);  // 50% chance of being chosen.
-    if (trial->group() != FieldTrial::kNotParticipating) {
+    // If group_ is kNotFinalized, then a group assignement hasn't been done.
+    if (trial->group_ != FieldTrial::kNotFinalized) {
       first_winner = true;
       continue;
     }
     trial->AppendGroup("second", 1);  // Always chosen at this point.
-    EXPECT_NE(FieldTrial::kNotParticipating, trial->group());
+    EXPECT_NE(FieldTrial::kNotFinalized, trial->group());
     second_winner = true;
   } while ((!second_winner || !first_winner) && counter < 100);
   EXPECT_TRUE(second_winner);
@@ -116,11 +147,14 @@
 
 TEST_F(FieldTrialTest, MiddleProbabilities) {
   char name[] = " same name";
+  char default_group_name[] = " default same name";
   bool false_event_seen = false;
   bool true_event_seen = false;
   for (int i = 1; i < 250; ++i) {
     name[0] = i;
-    FieldTrial* trial = new FieldTrial(name, 10);
+    default_group_name[0] = i;
+    FieldTrial* trial =
+        new FieldTrial(name, 10, default_group_name, next_year_, 12, 31);
     int might_win = trial->AppendGroup("MightWin", 5);
 
     if (trial->group() == might_win) {
@@ -139,16 +173,21 @@
 
 TEST_F(FieldTrialTest, OneWinner) {
   char name[] = "Some name";
+  char default_group_name[] = "Default some name";
   int group_count(10);
 
-  FieldTrial* trial = new FieldTrial(name, group_count);
+  FieldTrial* trial =
+      new FieldTrial(
+          name, group_count, default_group_name, next_year_, 12, 31);
   int winner_index(-2);
   std::string winner_name;
 
   for (int i = 1; i <= group_count; ++i) {
     int might_win = trial->AppendGroup("", 1);
 
-    if (trial->group() == might_win) {
+    // Because we keep appending groups, we want to see if the last group that
+    // was added has been assigned or not.
+    if (trial->group_ == might_win) {
       EXPECT_EQ(-2, winner_index);
       winner_index = might_win;
       StringAppendF(&winner_name, "%d", might_win);
@@ -160,14 +199,34 @@
   EXPECT_EQ(trial->group_name(), winner_name);
 }
 
+TEST_F(FieldTrialTest, DisableProbability) {
+  const std::string default_group_name = "Default group";
+  const std::string loser = "Loser";
+  const std::string name = "Trial";
+
+  // Create a field trail that has expired.
+  scoped_refptr<FieldTrial> trial;
+  trial = new FieldTrial(
+      name, 1000000000, default_group_name, last_year_, 1, 1);
+  trial->AppendGroup(loser, 999999999);  // 99.9999999% chance of being chosen.
+
+  // Because trial has expired, we should always be in the default group.
+  EXPECT_EQ(FieldTrial::kDefaultGroupNumber, trial->group());
+
+  // And that default_group_name should ALWAYS win.
+  EXPECT_EQ(default_group_name, trial->group_name());
+}
+
 TEST_F(FieldTrialTest, Save) {
   std::string save_string;
 
-  FieldTrial* trial = new FieldTrial("Some name", 10);
+  FieldTrial* trial =
+      new FieldTrial(
+          "Some name", 10, "Default some name", next_year_, 12, 31);
   // There is no winner yet, so no textual group name is associated with trial.
-  EXPECT_EQ("", trial->group_name());
+  EXPECT_EQ("", trial->group_name_internal());
   FieldTrialList::StatesToString(&save_string);
-  EXPECT_EQ("", save_string);
+  EXPECT_EQ("Some name/Default some name/", save_string);
   save_string.clear();
 
   // Create a winning group.
@@ -177,7 +236,8 @@
   save_string.clear();
 
   // Create a second trial and winning group.
-  FieldTrial* trial2 = new FieldTrial("xxx", 10);
+  FieldTrial* trial2 =
+      new FieldTrial("xxx", 10, "Default xxx", next_year_, 12, 31);
   trial2->AppendGroup("yyyy", 10);
 
   FieldTrialList::StatesToString(&save_string);
@@ -189,7 +249,7 @@
   EXPECT_TRUE(FieldTrialList::Find("Some_name") == NULL);
   EXPECT_TRUE(FieldTrialList::Find("xxx") == NULL);
 
-  FieldTrialList::StringAugmentsState("Some_name/Winner/xxx/yyyy/");
+  FieldTrialList::CreateTrialsInChildProcess("Some_name/Winner/xxx/yyyy/");
 
   FieldTrial* trial = FieldTrialList::Find("Some_name");
   ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
@@ -203,29 +263,34 @@
 }
 
 TEST_F(FieldTrialTest, BogusRestore) {
-  EXPECT_FALSE(FieldTrialList::StringAugmentsState("MissingSlash"));
-  EXPECT_FALSE(FieldTrialList::StringAugmentsState("MissingGroupName/"));
-  EXPECT_FALSE(FieldTrialList::StringAugmentsState("MissingFinalSlash/gname"));
-  EXPECT_FALSE(FieldTrialList::StringAugmentsState("/noname, only group/"));
+  EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess("MissingSlash"));
+  EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess("MissingGroupName/"));
+  EXPECT_FALSE(
+      FieldTrialList::CreateTrialsInChildProcess("MissingFinalSlash/gname"));
+  EXPECT_FALSE(
+      FieldTrialList::CreateTrialsInChildProcess("/noname, only group/"));
 }
 
 TEST_F(FieldTrialTest, DuplicateRestore) {
-  FieldTrial* trial = new FieldTrial("Some name", 10);
+  FieldTrial* trial =
+      new FieldTrial(
+          "Some name", 10, "Default some name", next_year_, 12, 31);
   trial->AppendGroup("Winner", 10);
   std::string save_string;
   FieldTrialList::StatesToString(&save_string);
   EXPECT_EQ("Some name/Winner/", save_string);
 
   // It is OK if we redundantly specify a winner.
-  EXPECT_TRUE(FieldTrialList::StringAugmentsState(save_string));
+  EXPECT_TRUE(FieldTrialList::CreateTrialsInChildProcess(save_string));
 
   // But it is an error to try to change to a different winner.
-  EXPECT_FALSE(FieldTrialList::StringAugmentsState("Some name/Loser/"));
+  EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess("Some name/Loser/"));
 }
 
 TEST_F(FieldTrialTest, MakeName) {
-  FieldTrial* trial = new FieldTrial("Field Trial", 10);
-  trial->AppendGroup("Winner", 10);
+  FieldTrial* trial =
+      new FieldTrial("Field Trial", 10, "Winner", next_year_, 12, 31);
+  trial->group();
   EXPECT_EQ("Histogram_Winner",
             FieldTrial::MakeName("Histogram", "Field Trial"));
 }
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 1526cd8..a308932 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -53,48 +53,6 @@
                     bucket_count, flags);
 }
 
-Histogram::Histogram(const std::string& name, Sample minimum,
-                     Sample maximum, size_t bucket_count)
-  : histogram_name_(name),
-    declared_min_(minimum),
-    declared_max_(maximum),
-    bucket_count_(bucket_count),
-    flags_(kNoFlags),
-    ranges_(bucket_count + 1, 0),
-    range_checksum_(0),
-    sample_() {
-  Initialize();
-}
-
-Histogram::Histogram(const std::string& name, TimeDelta minimum,
-                     TimeDelta maximum, size_t bucket_count)
-  : histogram_name_(name),
-    declared_min_(static_cast<int> (minimum.InMilliseconds())),
-    declared_max_(static_cast<int> (maximum.InMilliseconds())),
-    bucket_count_(bucket_count),
-    flags_(kNoFlags),
-    ranges_(bucket_count + 1, 0),
-    range_checksum_(0),
-    sample_() {
-  Initialize();
-}
-
-Histogram::~Histogram() {
-  if (StatisticsRecorder::dump_on_exit()) {
-    std::string output;
-    WriteAscii(true, "\n", &output);
-    LOG(INFO) << output;
-  }
-
-  // Just to make sure most derived class did this properly...
-  DCHECK(ValidateBucketRanges());
-  DCHECK(HasValidRangeChecksum());
-}
-
-bool Histogram::PrintEmptyBucket(size_t index) const {
-  return true;
-}
-
 void Histogram::Add(int value) {
   if (value > kSampleType_MAX - 1)
     value = kSampleType_MAX - 1;
@@ -190,244 +148,6 @@
   DCHECK_EQ(sample_count, past);
 }
 
-bool Histogram::ValidateBucketRanges() const {
-  // Standard assertions that all bucket ranges should satisfy.
-  DCHECK_EQ(bucket_count_ + 1, ranges_.size());
-  DCHECK_EQ(0, ranges_[0]);
-  DCHECK_EQ(declared_min(), ranges_[1]);
-  DCHECK_EQ(declared_max(), ranges_[bucket_count_ - 1]);
-  DCHECK_EQ(kSampleType_MAX, ranges_[bucket_count_]);
-  return true;
-}
-
-void Histogram::Initialize() {
-  sample_.Resize(*this);
-  if (declared_min_ < 1)
-    declared_min_ = 1;
-  if (declared_max_ > kSampleType_MAX - 1)
-    declared_max_ = kSampleType_MAX - 1;
-  DCHECK_LE(declared_min_, declared_max_);
-  DCHECK_GT(bucket_count_, 1u);
-  size_t maximal_bucket_count = declared_max_ - declared_min_ + 2;
-  DCHECK_LE(bucket_count_, maximal_bucket_count);
-  DCHECK_EQ(0, ranges_[0]);
-  ranges_[bucket_count_] = kSampleType_MAX;
-  InitializeBucketRange();
-  DCHECK(ValidateBucketRanges());
-  StatisticsRecorder::Register(this);
-}
-
-// Calculate what range of values are held in each bucket.
-// We have to be careful that we don't pick a ratio between starting points in
-// consecutive buckets that is sooo small, that the integer bounds are the same
-// (effectively making one bucket get no values).  We need to avoid:
-//   ranges_[i] == ranges_[i + 1]
-// To avoid that, we just do a fine-grained bucket width as far as we need to
-// until we get a ratio that moves us along at least 2 units at a time.  From
-// that bucket onward we do use the exponential growth of buckets.
-void Histogram::InitializeBucketRange() {
-  double log_max = log(static_cast<double>(declared_max()));
-  double log_ratio;
-  double log_next;
-  size_t bucket_index = 1;
-  Sample current = declared_min();
-  SetBucketRange(bucket_index, current);
-  while (bucket_count() > ++bucket_index) {
-    double log_current;
-    log_current = log(static_cast<double>(current));
-    // Calculate the count'th root of the range.
-    log_ratio = (log_max - log_current) / (bucket_count() - bucket_index);
-    // See where the next bucket would start.
-    log_next = log_current + log_ratio;
-    int next;
-    next = static_cast<int>(floor(exp(log_next) + 0.5));
-    if (next > current)
-      current = next;
-    else
-      ++current;  // Just do a narrow bucket, and keep trying.
-    SetBucketRange(bucket_index, current);
-  }
-  ResetRangeChecksum();
-
-  DCHECK_EQ(bucket_count(), bucket_index);
-}
-
-size_t Histogram::BucketIndex(Sample value) const {
-  // Use simple binary search.  This is very general, but there are better
-  // approaches if we knew that the buckets were linearly distributed.
-  DCHECK_LE(ranges(0), value);
-  DCHECK_GT(ranges(bucket_count()), value);
-  size_t under = 0;
-  size_t over = bucket_count();
-  size_t mid;
-
-  do {
-    DCHECK_GE(over, under);
-    mid = (over + under)/2;
-    if (mid == under)
-      break;
-    if (ranges(mid) <= value)
-      under = mid;
-    else
-      over = mid;
-  } while (true);
-
-  DCHECK_LE(ranges(mid), value);
-  DCHECK_GT(ranges(mid+1), value);
-  return mid;
-}
-
-// Use the actual bucket widths (like a linear histogram) until the widths get
-// over some transition value, and then use that transition width.  Exponentials
-// get so big so fast (and we don't expect to see a lot of entries in the large
-// buckets), so we need this to make it possible to see what is going on and
-// not have 0-graphical-height buckets.
-double Histogram::GetBucketSize(Count current, size_t i) const {
-  DCHECK_GT(ranges(i + 1), ranges(i));
-  static const double kTransitionWidth = 5;
-  double denominator = ranges(i + 1) - ranges(i);
-  if (denominator > kTransitionWidth)
-    denominator = kTransitionWidth;  // Stop trying to normalize.
-  return current/denominator;
-}
-
-void Histogram::ResetRangeChecksum() {
-  range_checksum_ = CalculateRangeChecksum();
-}
-
-bool Histogram::HasValidRangeChecksum() const {
-  return CalculateRangeChecksum() == range_checksum_;
-}
-
-Histogram::Sample Histogram::CalculateRangeChecksum() const {
-  DCHECK_EQ(ranges_.size(), bucket_count() + 1);
-  Sample checksum = 0;
-  for (size_t index = 0; index < bucket_count(); ++index) {
-    checksum += ranges(index);
-  }
-  return checksum;
-}
-
-//------------------------------------------------------------------------------
-// The following two methods can be overridden to provide a thread safe
-// version of this class.  The cost of locking is low... but an error in each
-// of these methods has minimal impact.  For now, I'll leave this unlocked,
-// and I don't believe I can loose more than a count or two.
-// The vectors are NOT reallocated, so there is no risk of them moving around.
-
-// Update histogram data with new sample.
-void Histogram::Accumulate(Sample value, Count count, size_t index) {
-  // Note locking not done in this version!!!
-  sample_.Accumulate(value, count, index);
-}
-
-// Do a safe atomic snapshot of sample data.
-// This implementation assumes we are on a safe single thread.
-void Histogram::SnapshotSample(SampleSet* sample) const {
-  // Note locking not done in this version!!!
-  *sample = sample_;
-}
-
-bool Histogram::HasConstructorArguments(Sample minimum,
-                                        Sample maximum,
-                                        size_t bucket_count) {
-  return ((minimum == declared_min_) && (maximum == declared_max_) &&
-          (bucket_count == bucket_count_));
-}
-
-bool Histogram::HasConstructorTimeDeltaArguments(TimeDelta minimum,
-                                                 TimeDelta maximum,
-                                                 size_t bucket_count) {
-  return ((minimum.InMilliseconds() == declared_min_) &&
-          (maximum.InMilliseconds() == declared_max_) &&
-          (bucket_count == bucket_count_));
-}
-
-//------------------------------------------------------------------------------
-// Accessor methods
-
-void Histogram::SetBucketRange(size_t i, Sample value) {
-  DCHECK_GT(bucket_count_, i);
-  ranges_[i] = value;
-}
-
-//------------------------------------------------------------------------------
-// Private methods
-
-double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const {
-  double max = 0;
-  for (size_t i = 0; i < bucket_count() ; ++i) {
-    double current_size = GetBucketSize(snapshot.counts(i), i);
-    if (current_size > max)
-      max = current_size;
-  }
-  return max;
-}
-
-void Histogram::WriteAsciiHeader(const SampleSet& snapshot,
-                                 Count sample_count,
-                                 std::string* output) const {
-  StringAppendF(output,
-                "Histogram: %s recorded %d samples",
-                histogram_name().c_str(),
-                sample_count);
-  if (0 == sample_count) {
-    DCHECK_EQ(snapshot.sum(), 0);
-  } else {
-    double average = static_cast<float>(snapshot.sum()) / sample_count;
-    double variance = static_cast<float>(snapshot.square_sum())/sample_count
-                      - average * average;
-    double standard_deviation = sqrt(variance);
-
-    StringAppendF(output,
-                  ", average = %.1f, standard deviation = %.1f",
-                  average, standard_deviation);
-  }
-  if (flags_ & ~kHexRangePrintingFlag)
-    StringAppendF(output, " (flags = 0x%x)", flags_ & ~kHexRangePrintingFlag);
-}
-
-void Histogram::WriteAsciiBucketContext(const int64 past,
-                                        const Count current,
-                                        const int64 remaining,
-                                        const size_t i,
-                                        std::string* output) const {
-  double scaled_sum = (past + current + remaining) / 100.0;
-  WriteAsciiBucketValue(current, scaled_sum, output);
-  if (0 < i) {
-    double percentage = past / scaled_sum;
-    StringAppendF(output, " {%3.1f%%}", percentage);
-  }
-}
-
-const std::string Histogram::GetAsciiBucketRange(size_t i) const {
-  std::string result;
-  if (kHexRangePrintingFlag & flags_)
-    StringAppendF(&result, "%#x", ranges(i));
-  else
-    StringAppendF(&result, "%d", ranges(i));
-  return result;
-}
-
-void Histogram::WriteAsciiBucketValue(Count current, double scaled_sum,
-                                      std::string* output) const {
-  StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum);
-}
-
-void Histogram::WriteAsciiBucketGraph(double current_size, double max_size,
-                                      std::string* output) const {
-  const int k_line_length = 72;  // Maximal horizontal width of graph.
-  int x_count = static_cast<int>(k_line_length * (current_size / max_size)
-                                 + 0.5);
-  int x_remainder = k_line_length - x_count;
-
-  while (0 < x_count--)
-    output->append("-");
-  output->append("O");
-  while (0 < x_remainder--)
-    output->append(" ");
-}
-
 // static
 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
                                               const SampleSet& snapshot) {
@@ -583,6 +303,276 @@
   return bucket_count_;
 }
 
+// Do a safe atomic snapshot of sample data.
+// This implementation assumes we are on a safe single thread.
+void Histogram::SnapshotSample(SampleSet* sample) const {
+  // Note locking not done in this version!!!
+  *sample = sample_;
+}
+
+bool Histogram::HasConstructorArguments(Sample minimum,
+                                        Sample maximum,
+                                        size_t bucket_count) {
+  return ((minimum == declared_min_) && (maximum == declared_max_) &&
+          (bucket_count == bucket_count_));
+}
+
+bool Histogram::HasConstructorTimeDeltaArguments(TimeDelta minimum,
+                                                 TimeDelta maximum,
+                                                 size_t bucket_count) {
+  return ((minimum.InMilliseconds() == declared_min_) &&
+          (maximum.InMilliseconds() == declared_max_) &&
+          (bucket_count == bucket_count_));
+}
+
+Histogram::Histogram(const std::string& name, Sample minimum,
+                     Sample maximum, size_t bucket_count)
+  : histogram_name_(name),
+    declared_min_(minimum),
+    declared_max_(maximum),
+    bucket_count_(bucket_count),
+    flags_(kNoFlags),
+    ranges_(bucket_count + 1, 0),
+    range_checksum_(0),
+    sample_() {
+  Initialize();
+}
+
+Histogram::Histogram(const std::string& name, TimeDelta minimum,
+                     TimeDelta maximum, size_t bucket_count)
+  : histogram_name_(name),
+    declared_min_(static_cast<int> (minimum.InMilliseconds())),
+    declared_max_(static_cast<int> (maximum.InMilliseconds())),
+    bucket_count_(bucket_count),
+    flags_(kNoFlags),
+    ranges_(bucket_count + 1, 0),
+    range_checksum_(0),
+    sample_() {
+  Initialize();
+}
+
+Histogram::~Histogram() {
+  if (StatisticsRecorder::dump_on_exit()) {
+    std::string output;
+    WriteAscii(true, "\n", &output);
+    LOG(INFO) << output;
+  }
+
+  // Just to make sure most derived class did this properly...
+  DCHECK(ValidateBucketRanges());
+  DCHECK(HasValidRangeChecksum());
+}
+
+bool Histogram::PrintEmptyBucket(size_t index) const {
+  return true;
+}
+
+// Calculate what range of values are held in each bucket.
+// We have to be careful that we don't pick a ratio between starting points in
+// consecutive buckets that is sooo small, that the integer bounds are the same
+// (effectively making one bucket get no values).  We need to avoid:
+//   ranges_[i] == ranges_[i + 1]
+// To avoid that, we just do a fine-grained bucket width as far as we need to
+// until we get a ratio that moves us along at least 2 units at a time.  From
+// that bucket onward we do use the exponential growth of buckets.
+void Histogram::InitializeBucketRange() {
+  double log_max = log(static_cast<double>(declared_max()));
+  double log_ratio;
+  double log_next;
+  size_t bucket_index = 1;
+  Sample current = declared_min();
+  SetBucketRange(bucket_index, current);
+  while (bucket_count() > ++bucket_index) {
+    double log_current;
+    log_current = log(static_cast<double>(current));
+    // Calculate the count'th root of the range.
+    log_ratio = (log_max - log_current) / (bucket_count() - bucket_index);
+    // See where the next bucket would start.
+    log_next = log_current + log_ratio;
+    int next;
+    next = static_cast<int>(floor(exp(log_next) + 0.5));
+    if (next > current)
+      current = next;
+    else
+      ++current;  // Just do a narrow bucket, and keep trying.
+    SetBucketRange(bucket_index, current);
+  }
+  ResetRangeChecksum();
+
+  DCHECK_EQ(bucket_count(), bucket_index);
+}
+
+size_t Histogram::BucketIndex(Sample value) const {
+  // Use simple binary search.  This is very general, but there are better
+  // approaches if we knew that the buckets were linearly distributed.
+  DCHECK_LE(ranges(0), value);
+  DCHECK_GT(ranges(bucket_count()), value);
+  size_t under = 0;
+  size_t over = bucket_count();
+  size_t mid;
+
+  do {
+    DCHECK_GE(over, under);
+    mid = (over + under)/2;
+    if (mid == under)
+      break;
+    if (ranges(mid) <= value)
+      under = mid;
+    else
+      over = mid;
+  } while (true);
+
+  DCHECK_LE(ranges(mid), value);
+  DCHECK_GT(ranges(mid+1), value);
+  return mid;
+}
+
+// Use the actual bucket widths (like a linear histogram) until the widths get
+// over some transition value, and then use that transition width.  Exponentials
+// get so big so fast (and we don't expect to see a lot of entries in the large
+// buckets), so we need this to make it possible to see what is going on and
+// not have 0-graphical-height buckets.
+double Histogram::GetBucketSize(Count current, size_t i) const {
+  DCHECK_GT(ranges(i + 1), ranges(i));
+  static const double kTransitionWidth = 5;
+  double denominator = ranges(i + 1) - ranges(i);
+  if (denominator > kTransitionWidth)
+    denominator = kTransitionWidth;  // Stop trying to normalize.
+  return current/denominator;
+}
+
+void Histogram::ResetRangeChecksum() {
+  range_checksum_ = CalculateRangeChecksum();
+}
+
+const std::string Histogram::GetAsciiBucketRange(size_t i) const {
+  std::string result;
+  if (kHexRangePrintingFlag & flags_)
+    StringAppendF(&result, "%#x", ranges(i));
+  else
+    StringAppendF(&result, "%d", ranges(i));
+  return result;
+}
+
+// Update histogram data with new sample.
+void Histogram::Accumulate(Sample value, Count count, size_t index) {
+  // Note locking not done in this version!!!
+  sample_.Accumulate(value, count, index);
+}
+
+void Histogram::SetBucketRange(size_t i, Sample value) {
+  DCHECK_GT(bucket_count_, i);
+  ranges_[i] = value;
+}
+
+bool Histogram::ValidateBucketRanges() const {
+  // Standard assertions that all bucket ranges should satisfy.
+  DCHECK_EQ(bucket_count_ + 1, ranges_.size());
+  DCHECK_EQ(0, ranges_[0]);
+  DCHECK_EQ(declared_min(), ranges_[1]);
+  DCHECK_EQ(declared_max(), ranges_[bucket_count_ - 1]);
+  DCHECK_EQ(kSampleType_MAX, ranges_[bucket_count_]);
+  return true;
+}
+
+void Histogram::Initialize() {
+  sample_.Resize(*this);
+  if (declared_min_ < 1)
+    declared_min_ = 1;
+  if (declared_max_ > kSampleType_MAX - 1)
+    declared_max_ = kSampleType_MAX - 1;
+  DCHECK_LE(declared_min_, declared_max_);
+  DCHECK_GT(bucket_count_, 1u);
+  size_t maximal_bucket_count = declared_max_ - declared_min_ + 2;
+  DCHECK_LE(bucket_count_, maximal_bucket_count);
+  DCHECK_EQ(0, ranges_[0]);
+  ranges_[bucket_count_] = kSampleType_MAX;
+  InitializeBucketRange();
+  DCHECK(ValidateBucketRanges());
+  StatisticsRecorder::Register(this);
+}
+
+bool Histogram::HasValidRangeChecksum() const {
+  return CalculateRangeChecksum() == range_checksum_;
+}
+
+Histogram::Sample Histogram::CalculateRangeChecksum() const {
+  DCHECK_EQ(ranges_.size(), bucket_count() + 1);
+  Sample checksum = 0;
+  for (size_t index = 0; index < bucket_count(); ++index) {
+    checksum += ranges(index);
+  }
+  return checksum;
+}
+
+//------------------------------------------------------------------------------
+// Private methods
+
+double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const {
+  double max = 0;
+  for (size_t i = 0; i < bucket_count() ; ++i) {
+    double current_size = GetBucketSize(snapshot.counts(i), i);
+    if (current_size > max)
+      max = current_size;
+  }
+  return max;
+}
+
+void Histogram::WriteAsciiHeader(const SampleSet& snapshot,
+                                 Count sample_count,
+                                 std::string* output) const {
+  StringAppendF(output,
+                "Histogram: %s recorded %d samples",
+                histogram_name().c_str(),
+                sample_count);
+  if (0 == sample_count) {
+    DCHECK_EQ(snapshot.sum(), 0);
+  } else {
+    double average = static_cast<float>(snapshot.sum()) / sample_count;
+    double variance = static_cast<float>(snapshot.square_sum())/sample_count
+                      - average * average;
+    double standard_deviation = sqrt(variance);
+
+    StringAppendF(output,
+                  ", average = %.1f, standard deviation = %.1f",
+                  average, standard_deviation);
+  }
+  if (flags_ & ~kHexRangePrintingFlag)
+    StringAppendF(output, " (flags = 0x%x)", flags_ & ~kHexRangePrintingFlag);
+}
+
+void Histogram::WriteAsciiBucketContext(const int64 past,
+                                        const Count current,
+                                        const int64 remaining,
+                                        const size_t i,
+                                        std::string* output) const {
+  double scaled_sum = (past + current + remaining) / 100.0;
+  WriteAsciiBucketValue(current, scaled_sum, output);
+  if (0 < i) {
+    double percentage = past / scaled_sum;
+    StringAppendF(output, " {%3.1f%%}", percentage);
+  }
+}
+
+void Histogram::WriteAsciiBucketValue(Count current, double scaled_sum,
+                                      std::string* output) const {
+  StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum);
+}
+
+void Histogram::WriteAsciiBucketGraph(double current_size, double max_size,
+                                      std::string* output) const {
+  const int k_line_length = 72;  // Maximal horizontal width of graph.
+  int x_count = static_cast<int>(k_line_length * (current_size / max_size)
+                                 + 0.5);
+  int x_remainder = k_line_length - x_count;
+
+  while (0 < x_count--)
+    output->append("-");
+  output->append("O");
+  while (0 < x_remainder--)
+    output->append(" ");
+}
+
 //------------------------------------------------------------------------------
 // Methods for the Histogram::SampleSet class
 //------------------------------------------------------------------------------
@@ -700,6 +690,9 @@
 // buckets.
 //------------------------------------------------------------------------------
 
+LinearHistogram::~LinearHistogram() {
+}
+
 scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name,
                                                      Sample minimum,
                                                      Sample maximum,
@@ -733,7 +726,15 @@
                     bucket_count, flags);
 }
 
-LinearHistogram::~LinearHistogram() {
+Histogram::ClassType LinearHistogram::histogram_type() const {
+  return LINEAR_HISTOGRAM;
+}
+
+void LinearHistogram::SetRangeDescriptions(
+    const DescriptionPair descriptions[]) {
+  for (int i =0; descriptions[i].description; ++i) {
+    bucket_description_[descriptions[i].sample] = descriptions[i].description;
+  }
 }
 
 LinearHistogram::LinearHistogram(const std::string& name,
@@ -757,30 +758,6 @@
   DCHECK(ValidateBucketRanges());
 }
 
-Histogram::ClassType LinearHistogram::histogram_type() const {
-  return LINEAR_HISTOGRAM;
-}
-
-void LinearHistogram::SetRangeDescriptions(
-    const DescriptionPair descriptions[]) {
-  for (int i =0; descriptions[i].description; ++i) {
-    bucket_description_[descriptions[i].sample] = descriptions[i].description;
-  }
-}
-
-const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
-  int range = ranges(i);
-  BucketDescriptionMap::const_iterator it = bucket_description_.find(range);
-  if (it == bucket_description_.end())
-    return Histogram::GetAsciiBucketRange(i);
-  return it->second;
-}
-
-bool LinearHistogram::PrintEmptyBucket(size_t index) const {
-  return bucket_description_.find(ranges(index)) == bucket_description_.end();
-}
-
-
 void LinearHistogram::InitializeBucketRange() {
   DCHECK_GT(declared_min(), 0);  // 0 is the underflow bucket here.
   double min = declared_min();
@@ -802,6 +779,19 @@
   return current/denominator;
 }
 
+const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
+  int range = ranges(i);
+  BucketDescriptionMap::const_iterator it = bucket_description_.find(range);
+  if (it == bucket_description_.end())
+    return Histogram::GetAsciiBucketRange(i);
+  return it->second;
+}
+
+bool LinearHistogram::PrintEmptyBucket(size_t index) const {
+  return bucket_description_.find(ranges(index)) == bucket_description_.end();
+}
+
+
 //------------------------------------------------------------------------------
 // This section provides implementation for BooleanHistogram.
 //------------------------------------------------------------------------------
diff --git a/base/metrics/stats_table.cc b/base/metrics/stats_table.cc
index 757c08e..0e8d016 100644
--- a/base/metrics/stats_table.cc
+++ b/base/metrics/stats_table.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -136,7 +136,14 @@
 
  private:
   // Constructor is private because you should use New() instead.
-  Private() {}
+  Private()
+      : table_header_(NULL),
+        thread_names_table_(NULL),
+        thread_tid_table_(NULL),
+        thread_pid_table_(NULL),
+        counter_names_table_(NULL),
+        data_table_(NULL) {
+  }
 
   // Initializes the table on first access.  Sets header values
   // appropriately and zeroes all counters.
@@ -282,6 +289,13 @@
     global_table_ = NULL;
 }
 
+int StatsTable::GetSlot() const {
+  TLSData* data = GetTLSData();
+  if (!data)
+    return 0;
+  return data->slot;
+}
+
 int StatsTable::RegisterThread(const std::string& name) {
 #ifdef ANDROID
   return 0;
@@ -319,15 +333,121 @@
 #endif
 }
 
-StatsTable::TLSData* StatsTable::GetTLSData() const {
-  TLSData* data =
-    static_cast<TLSData*>(tls_index_.Get());
-  if (!data)
+int StatsTable::CountThreadsRegistered() const {
+  if (!impl_)
+    return 0;
+
+  // Loop through the shared memory and count the threads that are active.
+  // We intentionally do not lock the table during the operation.
+  int count = 0;
+  for (int index = 1; index <= impl_->max_threads(); index++) {
+    char* name = impl_->thread_name(index);
+    if (*name != '\0')
+      count++;
+  }
+  return count;
+}
+
+int StatsTable::FindCounter(const std::string& name) {
+  // Note: the API returns counters numbered from 1..N, although
+  // internally, the array is 0..N-1.  This is so that we can return
+  // zero as "not found".
+  if (!impl_)
+    return 0;
+
+  // Create a scope for our auto-lock.
+  {
+    AutoLock scoped_lock(counters_lock_);
+
+    // Attempt to find the counter.
+    CountersMap::const_iterator iter;
+    iter = counters_.find(name);
+    if (iter != counters_.end())
+      return iter->second;
+  }
+
+  // Counter does not exist, so add it.
+  return AddCounter(name);
+}
+
+int* StatsTable::GetLocation(int counter_id, int slot_id) const {
+  if (!impl_)
+    return NULL;
+  if (slot_id > impl_->max_threads())
     return NULL;
 
-  DCHECK(data->slot);
-  DCHECK_EQ(data->table, this);
-  return data;
+  int* row = impl_->row(counter_id);
+  return &(row[slot_id-1]);
+}
+
+const char* StatsTable::GetRowName(int index) const {
+  if (!impl_)
+    return NULL;
+
+  return impl_->counter_name(index);
+}
+
+int StatsTable::GetRowValue(int index) const {
+  return GetRowValue(index, 0);
+}
+
+int StatsTable::GetRowValue(int index, int pid) const {
+  if (!impl_)
+    return 0;
+
+  int rv = 0;
+  int* row = impl_->row(index);
+  for (int slot_id = 0; slot_id < impl_->max_threads(); slot_id++) {
+    if (pid == 0 || *impl_->thread_pid(slot_id) == pid)
+      rv += row[slot_id];
+  }
+  return rv;
+}
+
+int StatsTable::GetCounterValue(const std::string& name) {
+  return GetCounterValue(name, 0);
+}
+
+int StatsTable::GetCounterValue(const std::string& name, int pid) {
+  if (!impl_)
+    return 0;
+
+  int row = FindCounter(name);
+  if (!row)
+    return 0;
+  return GetRowValue(row, pid);
+}
+
+int StatsTable::GetMaxCounters() const {
+  if (!impl_)
+    return 0;
+  return impl_->max_counters();
+}
+
+int StatsTable::GetMaxThreads() const {
+  if (!impl_)
+    return 0;
+  return impl_->max_threads();
+}
+
+int* StatsTable::FindLocation(const char* name) {
+  // Get the static StatsTable
+  StatsTable *table = StatsTable::current();
+  if (!table)
+    return NULL;
+
+  // Get the slot for this thread.  Try to register
+  // it if none exists.
+  int slot = table->GetSlot();
+  if (!slot && !(slot = table->RegisterThread("")))
+      return NULL;
+
+  // Find the counter id for the counter.
+  std::string str_name(name);
+  int counter = table->FindCounter(str_name);
+
+  // Now we can find the location in the table.
+  return table->GetLocation(counter, slot);
 }
 
 void StatsTable::UnregisterThread() {
@@ -359,28 +479,6 @@
   }
 }
 
-int StatsTable::CountThreadsRegistered() const {
-  if (!impl_)
-    return 0;
-
-  // Loop through the shared memory and count the threads that are active.
-  // We intentionally do not lock the table during the operation.
-  int count = 0;
-  for (int index = 1; index <= impl_->max_threads(); index++) {
-    char* name = impl_->thread_name(index);
-    if (*name != '\0')
-      count++;
-  }
-  return count;
-}
-
-int StatsTable::GetSlot() const {
-  TLSData* data = GetTLSData();
-  if (!data)
-    return 0;
-  return data->slot;
-}
-
 int StatsTable::FindEmptyThread() const {
   // Note: the API returns slots numbered from 1..N, although
   // internally, the array is 0..N-1.  This is so that we can return
@@ -426,28 +524,6 @@
   return free_slot;
 }
 
-int StatsTable::FindCounter(const std::string& name) {
-  // Note: the API returns counters numbered from 1..N, although
-  // internally, the array is 0..N-1.  This is so that we can return
-  // zero as "not found".
-  if (!impl_)
-    return 0;
-
-  // Create a scope for our auto-lock.
-  {
-    AutoLock scoped_lock(counters_lock_);
-
-    // Attempt to find the counter.
-    CountersMap::const_iterator iter;
-    iter = counters_.find(name);
-    if (iter != counters_.end())
-      return iter->second;
-  }
-
-  // Counter does not exist, so add it.
-  return AddCounter(name);
-}
-
 int StatsTable::AddCounter(const std::string& name) {
 #ifdef ANDROID
   return 0;
@@ -483,84 +559,15 @@
 #endif
 }
 
-int* StatsTable::GetLocation(int counter_id, int slot_id) const {
-  if (!impl_)
-    return NULL;
-  if (slot_id > impl_->max_threads())
+StatsTable::TLSData* StatsTable::GetTLSData() const {
+  TLSData* data =
+    static_cast<TLSData*>(tls_index_.Get());
+  if (!data)
     return NULL;
 
-  int* row = impl_->row(counter_id);
-  return &(row[slot_id-1]);
-}
-
-const char* StatsTable::GetRowName(int index) const {
-  if (!impl_)
-    return NULL;
-
-  return impl_->counter_name(index);
-}
-
-int StatsTable::GetRowValue(int index, int pid) const {
-  if (!impl_)
-    return 0;
-
-  int rv = 0;
-  int* row = impl_->row(index);
-  for (int slot_id = 0; slot_id < impl_->max_threads(); slot_id++) {
-    if (pid == 0 || *impl_->thread_pid(slot_id) == pid)
-      rv += row[slot_id];
-  }
-  return rv;
-}
-
-int StatsTable::GetRowValue(int index) const {
-  return GetRowValue(index, 0);
-}
-
-int StatsTable::GetCounterValue(const std::string& name, int pid) {
-  if (!impl_)
-    return 0;
-
-  int row = FindCounter(name);
-  if (!row)
-    return 0;
-  return GetRowValue(row, pid);
-}
-
-int StatsTable::GetCounterValue(const std::string& name) {
-  return GetCounterValue(name, 0);
-}
-
-int StatsTable::GetMaxCounters() const {
-  if (!impl_)
-    return 0;
-  return impl_->max_counters();
-}
-
-int StatsTable::GetMaxThreads() const {
-  if (!impl_)
-    return 0;
-  return impl_->max_threads();
-}
-
-int* StatsTable::FindLocation(const char* name) {
-  // Get the static StatsTable
-  StatsTable *table = StatsTable::current();
-  if (!table)
-    return NULL;
-
-  // Get the slot for this thread.  Try to register
-  // it if none exists.
-  int slot = table->GetSlot();
-  if (!slot && !(slot = table->RegisterThread("")))
-      return NULL;
-
-  // Find the counter id for the counter.
-  std::string str_name(name);
-  int counter = table->FindCounter(str_name);
-
-  // Now we can find the location in the table.
-  return table->GetLocation(counter, slot);
+  DCHECK(data->slot);
+  DCHECK_EQ(data->table, this);
+  return data;
 }
 
 }  // namespace base
diff --git a/base/metrics/stats_table.h b/base/metrics/stats_table.h
index 32b22eb..94f7463 100644
--- a/base/metrics/stats_table.h
+++ b/base/metrics/stats_table.h
@@ -25,7 +25,7 @@
 
 #include "base/basictypes.h"
 #include "base/hash_tables.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread_local_storage.h"
 
 namespace base {
@@ -122,7 +122,7 @@
 
   // The maximum length (in characters) of a Counter's name including
   // null terminator, as stored in the shared memory.
-  static const int kMaxCounterNameLength = 32;
+  static const int kMaxCounterNameLength = 64;
 
   // Convenience function to lookup a counter location for a
   // counter by name for the calling thread.  Will register
@@ -175,7 +175,7 @@
   Private* impl_;
 
   // The counters_lock_ protects the counters_ hash table.
-  Lock counters_lock_;
+  base::Lock counters_lock_;
 
   // The counters_ hash map is an in-memory hash of the counters.
   // It is used for quick lookup of counters, but is cannot be used
diff --git a/base/mime_util_xdg.cc b/base/mime_util_xdg.cc
index 8be1d0d..5215d01 100644
--- a/base/mime_util_xdg.cc
+++ b/base/mime_util_xdg.cc
@@ -21,6 +21,7 @@
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/third_party/xdg_mime/xdgmime.h"
+#include "base/threading/thread_restrictions.h"
 
 namespace {
 
@@ -155,6 +156,7 @@
 IconTheme::IconTheme(const std::string& name)
   : index_theme_loaded_(false),
     info_array_(NULL) {
+  base::ThreadRestrictions::AssertIOAllowed();
   // Iterate on all icon directories to find directories of the specified
   // theme and load the first encountered index.theme.
   std::map<FilePath, int>::iterator iter;
@@ -550,10 +552,12 @@
 namespace mime_util {
 
 std::string GetFileMimeType(const FilePath& filepath) {
+  base::ThreadRestrictions::AssertIOAllowed();
   return xdg_mime_get_mime_type_from_file_name(filepath.value().c_str());
 }
 
 std::string GetDataMimeType(const std::string& data) {
+  base::ThreadRestrictions::AssertIOAllowed();
   return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL);
 }
 
@@ -576,6 +580,7 @@
 }
 
 FilePath GetMimeIcon(const std::string& mime_type, size_t size) {
+  base::ThreadRestrictions::AssertIOAllowed();
   std::vector<std::string> icon_names;
   std::string icon_name;
   FilePath icon_file;
diff --git a/base/nss_util.cc b/base/nss_util.cc
index b411422..fe78fe0 100644
--- a/base/nss_util.cc
+++ b/base/nss_util.cc
@@ -29,9 +29,10 @@
 // use NSS for crypto or certificate verification, and we don't use the NSS
 // certificate and key databases.
 #if defined(USE_NSS)
+#include "base/crypto/crypto_module_blocking_password_delegate.h"
 #include "base/environment.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #endif  // defined(USE_NSS)
 
 namespace base {
@@ -69,6 +70,26 @@
 #endif  // defined(OS_CHROMEOS)
 }
 
+// This callback for NSS forwards all requests to a caller-specified
+// CryptoModuleBlockingPasswordDelegate object.
+char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) {
+  base::CryptoModuleBlockingPasswordDelegate* delegate =
+      reinterpret_cast<base::CryptoModuleBlockingPasswordDelegate*>(arg);
+  if (delegate) {
+    bool cancelled = false;
+    std::string password = delegate->RequestPassword(PK11_GetTokenName(slot),
+                                                     retry != PR_FALSE,
+                                                     &cancelled);
+    if (cancelled)
+      return NULL;
+    char* result = PORT_Strdup(password.c_str());
+    password.replace(0, password.size(), password.size(), 0);
+    return result;
+  }
+  DLOG(ERROR) << "PK11 password requested with NULL arg";
+  return NULL;
+}
+
 // NSS creates a local cache of the sqlite database if it detects that the
 // filesystem the database is on is much slower than the local disk.  The
 // detection doesn't work with the latest versions of sqlite, such as 3.6.22
@@ -78,6 +99,9 @@
 //
 // TODO(wtc): port this function to other USE_NSS platforms.  It is defined
 // only for OS_LINUX simply because the statfs structure is OS-specific.
+//
+// Because this function sets an environment variable it must be run before we
+// go multi-threaded.
 void UseLocalCacheOfNSSDatabaseIfNFS(const FilePath& database_dir) {
 #if defined(OS_LINUX)
   struct statfs buf;
@@ -141,6 +165,9 @@
 #if defined(OS_CHROMEOS)
   void OpenPersistentNSSDB() {
     if (!chromeos_user_logged_in_) {
+      // GetDefaultConfigDirectory causes us to do blocking IO on UI thread.
+      // Temporarily allow it until we fix http://crbug.com.70119
+      ThreadRestrictions::ScopedAllowIO allow_io;
       chromeos_user_logged_in_ = true;
       real_db_slot_ = OpenUserDB(GetDefaultConfigDirectory(),
                                  "Real NSS database");
@@ -219,6 +246,9 @@
 #else
     FilePath database_dir = GetInitialConfigDirectory();
     if (!database_dir.empty()) {
+      // This duplicates the work which should have been done in
+      // EarlySetupForNSSInit. However, this function is idempotent so there's
+      // no harm done.
       UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
 
       // Initialize with a persistent database (likely, ~/.pki/nssdb).
@@ -247,6 +277,8 @@
       }
     }
 
+    PK11_SetPasswordFunc(PKCS11PasswordFunc);
+
     // If we haven't initialized the password for the NSS databases,
     // initialize an empty-string password so that we don't need to
     // log in.
@@ -321,6 +353,14 @@
 
 }  // namespace
 
+#if defined(USE_NSS)
+void EarlySetupForNSSInit() {
+  FilePath database_dir = GetInitialConfigDirectory();
+  if (!database_dir.empty())
+    UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
+}
+#endif
+
 void EnsureNSPRInit() {
   g_nspr_singleton.Get();
 }
diff --git a/base/nss_util.h b/base/nss_util.h
index 2b0139e..10bbdfb 100644
--- a/base/nss_util.h
+++ b/base/nss_util.h
@@ -20,6 +20,13 @@
 class Lock;
 class Time;
 
+#if defined(USE_NSS)
+// EarlySetupForNSSInit performs lightweight setup which must occur before the
+// process goes multithreaded. This does not initialise NSS. For test, see
+// EnsureNSSInit.
+void EarlySetupForNSSInit();
+#endif
+
 // Initialize NRPR if it isn't already initialized.  This function is
 // thread-safe, and NSPR will only ever be initialized once.  NSPR will be
 // properly shut down on program exit.
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index d034e6c..47a662e 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -49,9 +49,32 @@
 //   will notify its regular ObserverList.
 //
 ///////////////////////////////////////////////////////////////////////////////
+
+// Forward declaration for ObserverListThreadSafeTraits.
+template <class ObserverType>
+class ObserverListThreadSafe;
+
+// This class is used to work around VS2005 not accepting:
+//
+// friend class
+//     base::RefCountedThreadSafe<ObserverListThreadSafe<ObserverType> >;
+//
+// Instead of friending the class, we could friend the actual function
+// which calls delete.  However, this ends up being
+// RefCountedThreadSafe::DeleteInternal(), which is private.  So we
+// define our own templated traits class so we can friend it.
+template <class T>
+struct ObserverListThreadSafeTraits {
+  static void Destruct(const ObserverListThreadSafe<T>* x) {
+    delete x;
+  }
+};
+
 template <class ObserverType>
 class ObserverListThreadSafe
-    : public base::RefCountedThreadSafe<ObserverListThreadSafe<ObserverType> > {
+    : public base::RefCountedThreadSafe<
+        ObserverListThreadSafe<ObserverType>,
+        ObserverListThreadSafeTraits<ObserverType> > {
  public:
   typedef typename ObserverList<ObserverType>::NotificationType
       NotificationType;
@@ -60,13 +83,6 @@
       : type_(ObserverListBase<ObserverType>::NOTIFY_ALL) {}
   explicit ObserverListThreadSafe(NotificationType type) : type_(type) {}
 
-  ~ObserverListThreadSafe() {
-    typename ObserversListMap::const_iterator it;
-    for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it)
-      delete (*it).second;
-    observer_lists_.clear();
-  }
-
   // Add an observer to the list.
   void AddObserver(ObserverType* obs) {
     ObserverList<ObserverType>* list = NULL;
@@ -77,7 +93,7 @@
     if (!loop)
       return;  // Some unittests may access this without a message loop.
     {
-      AutoLock lock(list_lock_);
+      base::AutoLock lock(list_lock_);
       if (observer_lists_.find(loop) == observer_lists_.end())
         observer_lists_[loop] = new ObserverList<ObserverType>(type_);
       list = observer_lists_[loop];
@@ -96,7 +112,7 @@
     if (!loop)
       return;  // On shutdown, it is possible that current() is already null.
     {
-      AutoLock lock(list_lock_);
+      base::AutoLock lock(list_lock_);
       list = observer_lists_[loop];
       if (!list) {
         NOTREACHED() << "RemoveObserver called on for unknown thread";
@@ -137,9 +153,19 @@
   // TODO(mbelshe):  Add more wrappers for Notify() with more arguments.
 
  private:
+  // See comment above ObserverListThreadSafeTraits' definition.
+  friend struct ObserverListThreadSafeTraits<ObserverType>;
+
+  ~ObserverListThreadSafe() {
+    typename ObserversListMap::const_iterator it;
+    for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it)
+      delete (*it).second;
+    observer_lists_.clear();
+  }
+
   template <class Method, class Params>
   void Notify(const UnboundMethod<ObserverType, Method, Params>& method) {
-    AutoLock lock(list_lock_);
+    base::AutoLock lock(list_lock_);
     typename ObserversListMap::iterator it;
     for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) {
       MessageLoop* loop = (*it).first;
@@ -161,7 +187,7 @@
 
     // Check that this list still needs notifications.
     {
-      AutoLock lock(list_lock_);
+      base::AutoLock lock(list_lock_);
       typename ObserversListMap::iterator it =
           observer_lists_.find(MessageLoop::current());
 
@@ -183,7 +209,7 @@
     // If there are no more observers on the list, we can now delete it.
     if (list->size() == 0) {
       {
-        AutoLock lock(list_lock_);
+        base::AutoLock lock(list_lock_);
         // Remove |list| if it's not already removed.
         // This can happen if multiple observers got removed in a notification.
         // See http://crbug.com/55725.
@@ -199,7 +225,7 @@
   typedef std::map<MessageLoop*, ObserverList<ObserverType>*> ObserversListMap;
 
   // These are marked mutable to facilitate having NotifyAll be const.
-  Lock list_lock_;  // Protects the observer_lists_.
+  base::Lock list_lock_;  // Protects the observer_lists_.
   ObserversListMap observer_lists_;
   const NotificationType type_;
 
diff --git a/base/openssl_util.cc b/base/openssl_util.cc
index bc174fa..931485a 100644
--- a/base/openssl_util.cc
+++ b/base/openssl_util.cc
@@ -7,11 +7,11 @@
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/scoped_vector.h"
 #include "base/singleton.h"
 #include "base/string_piece.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 
@@ -46,7 +46,7 @@
     int num_locks = CRYPTO_num_locks();
     locks_.reserve(num_locks);
     for (int i = 0; i < num_locks; ++i)
-      locks_.push_back(new Lock());
+      locks_.push_back(new base::Lock());
     CRYPTO_set_locking_callback(LockingCallback);
     CRYPTO_set_id_callback(CurrentThreadId);
   }
@@ -70,7 +70,7 @@
   }
 
   // These locks are used and managed by OpenSSL via LockingCallback().
-  ScopedVector<Lock> locks_;
+  ScopedVector<base::Lock> locks_;
 
   DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton);
 };
diff --git a/base/path_service.cc b/base/path_service.cc
index 56ce5fa..117feb5 100644
--- a/base/path_service.cc
+++ b/base/path_service.cc
@@ -14,8 +14,8 @@
 #include "base/file_util.h"
 #include "base/hash_tables.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/logging.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
   bool PathProvider(int key, FilePath* result);
@@ -92,9 +92,9 @@
 
 
 struct PathData {
-  Lock      lock;
-  PathMap   cache;      // Cache mappings from path key to path value.
-  PathMap   overrides;  // Track path overrides.
+  base::Lock lock;
+  PathMap cache;        // Cache mappings from path key to path value.
+  PathMap overrides;    // Track path overrides.
   Provider* providers;  // Linked list of path service providers.
 
   PathData() {
@@ -130,7 +130,7 @@
 // static
 bool PathService::GetFromCache(int key, FilePath* result) {
   PathData* path_data = GetPathData();
-  AutoLock scoped_lock(path_data->lock);
+  base::AutoLock scoped_lock(path_data->lock);
 
   // check for a cached version
   PathMap::const_iterator it = path_data->cache.find(key);
@@ -144,7 +144,7 @@
 // static
 bool PathService::GetFromOverrides(int key, FilePath* result) {
   PathData* path_data = GetPathData();
-  AutoLock scoped_lock(path_data->lock);
+  base::AutoLock scoped_lock(path_data->lock);
 
   // check for an overriden version.
   PathMap::const_iterator it = path_data->overrides.find(key);
@@ -158,7 +158,7 @@
 // static
 void PathService::AddToCache(int key, const FilePath& path) {
   PathData* path_data = GetPathData();
-  AutoLock scoped_lock(path_data->lock);
+  base::AutoLock scoped_lock(path_data->lock);
   // Save the computed path in our cache.
   path_data->cache[key] = path;
 }
@@ -225,7 +225,7 @@
   if (!file_util::AbsolutePath(&file_path))
     return false;
 
-  AutoLock scoped_lock(path_data->lock);
+  base::AutoLock scoped_lock(path_data->lock);
 
   // Clear the cache now. Some of its entries could have depended
   // on the value we are overriding, and are now out of sync with reality.
@@ -243,7 +243,7 @@
   DCHECK(path_data);
   DCHECK(key_end > key_start);
 
-  AutoLock scoped_lock(path_data->lock);
+  base::AutoLock scoped_lock(path_data->lock);
 
   Provider* p;
 
diff --git a/base/pickle.cc b/base/pickle.cc
index a05df28..e7d5768 100644
--- a/base/pickle.cc
+++ b/base/pickle.cc
@@ -406,6 +406,9 @@
   DCHECK(header_size == AlignInt(header_size, sizeof(uint32)));
   DCHECK(header_size <= static_cast<size_t>(kPayloadUnit));
 
+  if (static_cast<size_t>(end - start) < sizeof(Header))
+    return NULL;
+
   const Header* hdr = reinterpret_cast<const Header*>(start);
   const char* payload_base = start + header_size;
   const char* payload_end = payload_base + hdr->payload_size;
diff --git a/base/pickle.h b/base/pickle.h
index bbe5d34..ad08b7c 100644
--- a/base/pickle.h
+++ b/base/pickle.h
@@ -55,8 +55,7 @@
   Pickle& operator=(const Pickle& other);
 
   // Returns the size of the Pickle's data.
-  int size() const { return static_cast<int>(header_size_ +
-                                             header_->payload_size); }
+  size_t size() const { return header_size_ + header_->payload_size; }
 
   // Returns the data for this Pickle.
   const void* data() const { return header_; }
@@ -236,6 +235,7 @@
 
   FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
+  FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
   FRIEND_TEST_ALL_PREFIXES(PickleTest, IteratorHasRoom);
 };
 
diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc
index fdc0664..39eaa1b 100644
--- a/base/pickle_unittest.cc
+++ b/base/pickle_unittest.cc
@@ -171,6 +171,17 @@
   EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1));
 }
 
+TEST(PickleTest, FindNextWithIncompleteHeader) {
+  size_t header_size = sizeof(Pickle::Header);
+  scoped_array<char> buffer(new char[header_size - 1]);
+  memset(buffer.get(), 0x1, header_size - 1);
+
+  const char* start = buffer.get();
+  const char* end = start + header_size - 1;
+
+  EXPECT_TRUE(NULL == Pickle::FindNext(header_size, start, end));
+}
+
 TEST(PickleTest, IteratorHasRoom) {
   Pickle pickle;
   EXPECT_TRUE(pickle.WriteInt(1));
diff --git a/base/pr_time_unittest.cc b/base/pr_time_unittest.cc
index 6dda299..646eb16 100644
--- a/base/pr_time_unittest.cc
+++ b/base/pr_time_unittest.cc
@@ -136,7 +136,7 @@
 TEST_F(PRTimeTest, ParseTimeTest10) {
   Time parsed_time;
   bool result = Time::FromString(L"15/10/07 12:45", &parsed_time);
-  EXPECT_EQ(true, result);
+  EXPECT_TRUE(result);
 
   time_t computed_time = parsed_time.ToTimeT();
   time_t time_to_compare = comparison_time_local_ /
@@ -149,7 +149,7 @@
   Time parsed_time;
   bool result = Time::FromString(L"Mon, 15 Oct 2007 19:45:00 GMT",
                                  &parsed_time);
-  EXPECT_EQ(true, result);
+  EXPECT_TRUE(result);
 
   time_t computed_time = parsed_time.ToTimeT();
   time_t time_to_compare = comparison_time_pdt / Time::kMicrosecondsPerSecond;
@@ -161,11 +161,11 @@
   Time parsed_time;
 
   // time_t == epoch == 0
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:00 +0100 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 01:00:00 +0100 1970",
+                               &parsed_time));
   EXPECT_EQ(0, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:00:00 GMT 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:00:00 GMT 1970",
+                               &parsed_time));
   EXPECT_EQ(0, parsed_time.ToTimeT());
 }
 
@@ -173,11 +173,11 @@
   Time parsed_time;
 
   // time_t == 1 second after epoch == 1
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:01 +0100 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 01:00:01 +0100 1970",
+                               &parsed_time));
   EXPECT_EQ(1, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:00:01 GMT 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:00:01 GMT 1970",
+                               &parsed_time));
   EXPECT_EQ(1, parsed_time.ToTimeT());
 }
 
@@ -185,11 +185,11 @@
   Time parsed_time;
 
   // time_t == 2 seconds after epoch == 2
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:02 +0100 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 01:00:02 +0100 1970",
+                               &parsed_time));
   EXPECT_EQ(2, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:00:02 GMT 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:00:02 GMT 1970",
+                               &parsed_time));
   EXPECT_EQ(2, parsed_time.ToTimeT());
 }
 
@@ -197,11 +197,11 @@
   Time parsed_time;
 
   // time_t == 1 second before epoch == -1
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:59:59 +0100 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:59:59 +0100 1970",
+                               &parsed_time));
   EXPECT_EQ(-1, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Wed Dec 31 23:59:59 GMT 1969",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Wed Dec 31 23:59:59 GMT 1969",
+                               &parsed_time));
   EXPECT_EQ(-1, parsed_time.ToTimeT());
 }
 
@@ -211,8 +211,8 @@
 TEST_F(PRTimeTest, ParseTimeTestEpochNotNeg1) {
   Time parsed_time;
 
-  EXPECT_EQ(true, Time::FromString(L"Wed Dec 31 23:59:59 GMT 2100",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Wed Dec 31 23:59:59 GMT 2100",
+                               &parsed_time));
   EXPECT_NE(-1, parsed_time.ToTimeT());
 }
 
@@ -220,11 +220,11 @@
   Time parsed_time;
 
   // time_t == 2 seconds before epoch == -2
-  EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:59:58 +0100 1970",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:59:58 +0100 1970",
+                               &parsed_time));
   EXPECT_EQ(-2, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Wed Dec 31 23:59:58 GMT 1969",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Wed Dec 31 23:59:58 GMT 1969",
+                               &parsed_time));
   EXPECT_EQ(-2, parsed_time.ToTimeT());
 }
 
@@ -232,14 +232,14 @@
   Time parsed_time;
 
   // time_t before Epoch, in 1960
-  EXPECT_EQ(true, Time::FromString(L"Wed Jun 29 19:40:01 +0100 1960",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Wed Jun 29 19:40:01 +0100 1960",
+                               &parsed_time));
   EXPECT_EQ(-299999999, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Wed Jun 29 18:40:01 GMT 1960",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Wed Jun 29 18:40:01 GMT 1960",
+                               &parsed_time));
   EXPECT_EQ(-299999999, parsed_time.ToTimeT());
-  EXPECT_EQ(true, Time::FromString(L"Wed Jun 29 17:40:01 GMT 1960",
-                                   &parsed_time));
+  EXPECT_TRUE(Time::FromString(L"Wed Jun 29 17:40:01 GMT 1960",
+                               &parsed_time));
   EXPECT_EQ(-300003599, parsed_time.ToTimeT());
 }
 
diff --git a/base/process_linux.cc b/base/process_linux.cc
index 21ed933..14c2424 100644
--- a/base/process_linux.cc
+++ b/base/process_linux.cc
@@ -11,7 +11,14 @@
 
 namespace base {
 
+#if defined(OS_CHROMEOS)
+// We are more aggressive in our lowering of background process priority
+// for chromeos as we have much more control over other processes running
+// on the machine.
+const int kPriorityAdjustment = 19;
+#else
 const int kPriorityAdjustment = 5;
+#endif
 
 bool Process::IsProcessBackgrounded() const {
   DCHECK(process_);
diff --git a/base/process_posix.cc b/base/process_posix.cc
index ee70e5a..6e65ebf 100644
--- a/base/process_posix.cc
+++ b/base/process_posix.cc
@@ -13,6 +13,22 @@
 
 namespace base {
 
+// static
+Process Process::Current() {
+  return Process(GetCurrentProcessHandle());
+}
+
+ProcessId Process::pid() const {
+  if (process_ == 0)
+    return 0;
+
+  return GetProcId(process_);
+}
+
+bool Process::is_current() const {
+  return process_ == GetCurrentProcessHandle();
+}
+
 void Process::Close() {
   process_ = 0;
   // if the process wasn't terminated (so we waited) or the state
@@ -43,22 +59,6 @@
 }
 #endif
 
-ProcessId Process::pid() const {
-  if (process_ == 0)
-    return 0;
-
-  return GetProcId(process_);
-}
-
-bool Process::is_current() const {
-  return process_ == GetCurrentProcessHandle();
-}
-
-// static
-Process Process::Current() {
-  return Process(GetCurrentProcessHandle());
-}
-
 int Process::GetPriority() const {
   DCHECK(process_);
   return getpriority(PRIO_PROCESS, process_);
diff --git a/base/process_util.cc b/base/process_util.cc
index 7b2935d..462dcbf 100644
--- a/base/process_util.cc
+++ b/base/process_util.cc
@@ -44,10 +44,6 @@
   return NULL;
 }
 
-bool ProcessIterator::IncludeEntry() {
-  return !filter_ || filter_->Includes(entry_);
-}
-
 ProcessIterator::ProcessEntries ProcessIterator::Snapshot() {
   ProcessEntries found;
   while (const ProcessEntry* process_entry = NextProcessEntry()) {
@@ -56,6 +52,10 @@
   return found;
 }
 
+bool ProcessIterator::IncludeEntry() {
+  return !filter_ || filter_->Includes(entry_);
+}
+
 NamedProcessIterator::NamedProcessIterator(
     const FilePath::StringType& executable_name,
     const ProcessFilter* filter) : ProcessIterator(filter),
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
index dcaeeb4..4cd27f6 100644
--- a/base/process_util_linux.cc
+++ b/base/process_util_linux.cc
@@ -68,6 +68,39 @@
   return true;
 }
 
+// Get the total CPU of a single process.  Return value is number of jiffies
+// on success or -1 on error.
+int GetProcessCPU(pid_t pid) {
+  // Synchronously reading files in /proc is safe.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+  // Use /proc/<pid>/task to find all threads and parse their /stat file.
+  FilePath path = FilePath(StringPrintf("/proc/%d/task/", pid));
+
+  DIR* dir = opendir(path.value().c_str());
+  if (!dir) {
+    PLOG(ERROR) << "opendir(" << path.value() << ")";
+    return -1;
+  }
+
+  int total_cpu = 0;
+  while (struct dirent* ent = readdir(dir)) {
+    if (ent->d_name[0] == '.')
+      continue;
+
+    FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat");
+    std::string stat;
+    if (file_util::ReadFileToString(stat_path, &stat)) {
+      int cpu = base::ParseProcStatCPU(stat);
+      if (cpu > 0)
+        total_cpu += cpu;
+    }
+  }
+  closedir(dir);
+
+  return total_cpu;
+}
+
 }  // namespace
 
 namespace base {
@@ -167,18 +200,18 @@
     std::string pid_string(slot->d_name);
     int pid;
     if (StringToInt(pid_string, &pid) && !GetProcCmdline(pid, &cmd_line_args))
-      return false;
+      continue;
 
     // Read the process's status.
     char buf[NAME_MAX + 12];
     sprintf(buf, "/proc/%s/stat", slot->d_name);
     FILE *fp = fopen(buf, "r");
     if (!fp)
-      return false;
+      continue;
     const char* result = fgets(buf, sizeof(buf), fp);
     fclose(fp);
     if (!result)
-      return false;
+      continue;
 
     // Parse the status.  It is formatted like this:
     // %d (%s) %c %d %d ...
@@ -188,7 +221,7 @@
     openparen = strchr(buf, '(');
     closeparen = strrchr(buf, ')');
     if (!openparen || !closeparen)
-      return false;
+      continue;
     char runstate = closeparen[2];
 
     // Is the process in 'Zombie' state, i.e. dead but waiting to be reaped?
@@ -226,14 +259,6 @@
 }
 
 
-ProcessMetrics::ProcessMetrics(ProcessHandle process)
-    : process_(process),
-      last_time_(0),
-      last_system_time_(0),
-      last_cpu_(0) {
-  processor_count_ = base::SysInfo::NumberOfProcessors();
-}
-
 // static
 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
   return new ProcessMetrics(process);
@@ -399,6 +424,49 @@
   return true;
 }
 
+double ProcessMetrics::GetCPUUsage() {
+  // This queries the /proc-specific scaling factor which is
+  // conceptually the system hertz.  To dump this value on another
+  // system, try
+  //   od -t dL /proc/self/auxv
+  // and look for the number after 17 in the output; mine is
+  //   0000040          17         100           3   134512692
+  // which means the answer is 100.
+  // It may be the case that this value is always 100.
+  static const int kHertz = sysconf(_SC_CLK_TCK);
+
+  struct timeval now;
+  int retval = gettimeofday(&now, NULL);
+  if (retval)
+    return 0;
+  int64 time = TimeValToMicroseconds(now);
+
+  if (last_time_ == 0) {
+    // First call, just set the last values.
+    last_time_ = time;
+    last_cpu_ = GetProcessCPU(process_);
+    return 0;
+  }
+
+  int64 time_delta = time - last_time_;
+  DCHECK_NE(time_delta, 0);
+  if (time_delta == 0)
+    return 0;
+
+  int cpu = GetProcessCPU(process_);
+
+  // We have the number of jiffies in the time period.  Convert to percentage.
+  // Note this means we will go *over* 100 in the case where multiple threads
+  // are together adding to more than one CPU's worth.
+  int percentage = 100 * (cpu - last_cpu_) /
+      (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
+
+  last_time_ = time;
+  last_cpu_ = cpu;
+
+  return percentage;
+}
+
 // To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
 // in your kernel configuration.
 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
@@ -446,6 +514,14 @@
   return true;
 }
 
+ProcessMetrics::ProcessMetrics(ProcessHandle process)
+    : process_(process),
+      last_time_(0),
+      last_system_time_(0),
+      last_cpu_(0) {
+  processor_count_ = base::SysInfo::NumberOfProcessors();
+}
+
 
 // Exposed for testing.
 int ParseProcStatCPU(const std::string& input) {
@@ -469,82 +545,6 @@
   return fields11 + fields12;
 }
 
-// Get the total CPU of a single process.  Return value is number of jiffies
-// on success or -1 on error.
-static int GetProcessCPU(pid_t pid) {
-  // Synchronously reading files in /proc is safe.
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
-
-  // Use /proc/<pid>/task to find all threads and parse their /stat file.
-  FilePath path = FilePath(StringPrintf("/proc/%d/task/", pid));
-
-  DIR* dir = opendir(path.value().c_str());
-  if (!dir) {
-    PLOG(ERROR) << "opendir(" << path.value() << ")";
-    return -1;
-  }
-
-  int total_cpu = 0;
-  while (struct dirent* ent = readdir(dir)) {
-    if (ent->d_name[0] == '.')
-      continue;
-
-    FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat");
-    std::string stat;
-    if (file_util::ReadFileToString(stat_path, &stat)) {
-      int cpu = ParseProcStatCPU(stat);
-      if (cpu > 0)
-        total_cpu += cpu;
-    }
-  }
-  closedir(dir);
-
-  return total_cpu;
-}
-
-double ProcessMetrics::GetCPUUsage() {
-  // This queries the /proc-specific scaling factor which is
-  // conceptually the system hertz.  To dump this value on another
-  // system, try
-  //   od -t dL /proc/self/auxv
-  // and look for the number after 17 in the output; mine is
-  //   0000040          17         100           3   134512692
-  // which means the answer is 100.
-  // It may be the case that this value is always 100.
-  static const int kHertz = sysconf(_SC_CLK_TCK);
-
-  struct timeval now;
-  int retval = gettimeofday(&now, NULL);
-  if (retval)
-    return 0;
-  int64 time = TimeValToMicroseconds(now);
-
-  if (last_time_ == 0) {
-    // First call, just set the last values.
-    last_time_ = time;
-    last_cpu_ = GetProcessCPU(process_);
-    return 0;
-  }
-
-  int64 time_delta = time - last_time_;
-  DCHECK_NE(time_delta, 0);
-  if (time_delta == 0)
-    return 0;
-
-  int cpu = GetProcessCPU(process_);
-
-  // We have the number of jiffies in the time period.  Convert to percentage.
-  // Note this means we will go *over* 100 in the case where multiple threads
-  // are together adding to more than one CPU's worth.
-  int percentage = 100 * (cpu - last_cpu_) /
-      (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
-
-  last_time_ = time;
-  last_cpu_ = cpu;
-
-  return percentage;
-}
-
 namespace {
 
 // The format of /proc/meminfo is:
diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc
index 672e396..1b7368a 100644
--- a/base/process_util_unittest.cc
+++ b/base/process_util_unittest.cc
@@ -485,12 +485,15 @@
 
   fds_to_remap.push_back(std::make_pair(fds[1], 1));
   EXPECT_TRUE(base::LaunchApp(args, env_changes, fds_to_remap,
-                        true /* wait for exit */, &handle));
-  PCHECK(close(fds[1]) == 0);
+                              true /* wait for exit */, &handle));
+  PCHECK(HANDLE_EINTR(close(fds[1])) == 0);
 
   char buf[512];
   const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
   PCHECK(n > 0);
+
+  PCHECK(HANDLE_EINTR(close(fds[0])) == 0);
+
   return std::string(buf, n);
 }
 
diff --git a/base/ref_counted.cc b/base/ref_counted.cc
index 2f795ea..54c1071 100644
--- a/base/ref_counted.cc
+++ b/base/ref_counted.cc
@@ -12,7 +12,7 @@
 namespace subtle {
 
 RefCountedBase::RefCountedBase()
-    : ref_count_(0)
+    : counter_holder_(new CounterHolder)
 #ifndef NDEBUG
     , in_dtor_(false)
 #endif
@@ -20,6 +20,7 @@
 }
 
 RefCountedBase::~RefCountedBase() {
+  delete counter_holder_;
 #ifndef NDEBUG
   DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
 #endif
@@ -32,7 +33,7 @@
 #ifndef NDEBUG
   DCHECK(!in_dtor_);
 #endif
-  ++ref_count_;
+  ++(counter_holder_->ref_count);
 }
 
 bool RefCountedBase::Release() const {
@@ -42,41 +43,7 @@
 #ifndef NDEBUG
   DCHECK(!in_dtor_);
 #endif
-  if (--ref_count_ == 0) {
-#ifndef NDEBUG
-    in_dtor_ = true;
-#endif
-    return true;
-  }
-  return false;
-}
-
-RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
-#ifndef NDEBUG
-  in_dtor_ = false;
-#endif
-}
-
-RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
-#ifndef NDEBUG
-  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
-                      "calling Release()";
-#endif
-}
-
-void RefCountedThreadSafeBase::AddRef() const {
-#ifndef NDEBUG
-  DCHECK(!in_dtor_);
-#endif
-  AtomicRefCountInc(&ref_count_);
-}
-
-bool RefCountedThreadSafeBase::Release() const {
-#ifndef NDEBUG
-  DCHECK(!in_dtor_);
-  DCHECK(!AtomicRefCountIsZero(&ref_count_));
-#endif
-  if (!AtomicRefCountDec(&ref_count_)) {
+  if (--(counter_holder_->ref_count) == 0) {
 #ifndef NDEBUG
     in_dtor_ = true;
 #endif
@@ -87,7 +54,44 @@
 
 bool RefCountedThreadSafeBase::HasOneRef() const {
   return AtomicRefCountIsOne(
-      &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_);
+      &const_cast<RefCountedThreadSafeBase*>(this)->
+          counter_holder_->ref_count);
+}
+
+RefCountedThreadSafeBase::RefCountedThreadSafeBase()
+  : counter_holder_(new CounterHolder) {
+#ifndef NDEBUG
+  in_dtor_ = false;
+#endif
+}
+
+RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
+  delete counter_holder_;
+#ifndef NDEBUG
+  DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
+                      "calling Release()";
+#endif
+}
+
+void RefCountedThreadSafeBase::AddRef() const {
+#ifndef NDEBUG
+  DCHECK(!in_dtor_);
+#endif
+  AtomicRefCountInc(&counter_holder_->ref_count);
+}
+
+bool RefCountedThreadSafeBase::Release() const {
+#ifndef NDEBUG
+  DCHECK(!in_dtor_);
+  DCHECK(!AtomicRefCountIsZero(&counter_holder_->ref_count));
+#endif
+  if (!AtomicRefCountDec(&counter_holder_->ref_count)) {
+#ifndef NDEBUG
+    in_dtor_ = true;
+#endif
+    return true;
+  }
+  return false;
 }
 
 }  // namespace subtle
diff --git a/base/ref_counted.h b/base/ref_counted.h
index 4c3aeb8..6a2b996 100644
--- a/base/ref_counted.h
+++ b/base/ref_counted.h
@@ -17,19 +17,25 @@
  public:
   static bool ImplementsThreadSafeReferenceCounting() { return false; }
 
-  bool HasOneRef() const { return ref_count_ == 1; }
+  bool HasOneRef() const { return counter_holder_->ref_count == 1; }
 
  protected:
   RefCountedBase();
   ~RefCountedBase();
 
+  struct CounterHolder {
+    CounterHolder() : ref_count(0), weak_count(0) {}
+    int ref_count;
+    int weak_count;  // Simulates weak pointer.
+  };
+
   void AddRef() const;
 
   // Returns true if the object should self-delete.
   bool Release() const;
 
  private:
-  mutable int ref_count_;
+  mutable CounterHolder* counter_holder_;
 #ifndef NDEBUG
   mutable bool in_dtor_;
 #endif
@@ -55,7 +61,12 @@
   bool Release() const;
 
  private:
-  mutable AtomicRefCount ref_count_;
+  struct CounterHolder {
+    CounterHolder() : ref_count(0), weak_count(0) {}
+    AtomicRefCount ref_count;
+    AtomicRefCount weak_count; // Simulates weak pointer.
+  };
+  mutable CounterHolder* counter_holder_;
 #ifndef NDEBUG
   mutable bool in_dtor_;
 #endif
diff --git a/base/scoped_temp_dir.h b/base/scoped_temp_dir.h
index f44bcca..4286d28 100644
--- a/base/scoped_temp_dir.h
+++ b/base/scoped_temp_dir.h
@@ -28,17 +28,17 @@
 
   // Creates a unique directory in TempPath, and takes ownership of it.
   // See file_util::CreateNewTemporaryDirectory.
-  bool CreateUniqueTempDir();
+  bool CreateUniqueTempDir() WARN_UNUSED_RESULT;
 
   // Creates a unique directory under a given path, and takes ownership of it.
-  bool CreateUniqueTempDirUnderPath(const FilePath& path);
+  bool CreateUniqueTempDirUnderPath(const FilePath& path) WARN_UNUSED_RESULT;
 
   // Takes ownership of directory at |path|, creating it if necessary.
   // Don't call multiple times unless Take() has been called first.
-  bool Set(const FilePath& path);
+  bool Set(const FilePath& path) WARN_UNUSED_RESULT;
 
   // Deletes the temporary directory wrapped by this object.
-  bool Delete();
+  bool Delete() WARN_UNUSED_RESULT;
 
   // Caller takes ownership of the temporary directory so it won't be destroyed
   // when this object goes out of scope.
diff --git a/base/scoped_temp_dir_unittest.cc b/base/scoped_temp_dir_unittest.cc
index 039a1ed..135c2fd 100644
--- a/base/scoped_temp_dir_unittest.cc
+++ b/base/scoped_temp_dir_unittest.cc
@@ -23,7 +23,7 @@
 
   {
     ScopedTempDir dir;
-    dir.Set(test_path);
+    EXPECT_TRUE(dir.Set(test_path));
     // Now the dir doesn't exist, so ensure that it gets created.
     EXPECT_TRUE(file_util::DirectoryExists(test_path));
     // When we call Release(), it shouldn't get destroyed when leaving scope.
@@ -36,7 +36,7 @@
   // Clean up.
   {
     ScopedTempDir dir;
-    dir.Set(test_path);
+    EXPECT_TRUE(dir.Set(test_path));
   }
   EXPECT_FALSE(file_util::DirectoryExists(test_path));
 }
@@ -83,7 +83,7 @@
   EXPECT_TRUE(dir.CreateUniqueTempDir());
   EXPECT_FALSE(dir.CreateUniqueTempDir());
   ScopedTempDir other_dir;
-  other_dir.Set(dir.Take());
+  EXPECT_TRUE(other_dir.Set(dir.Take()));
   EXPECT_TRUE(dir.CreateUniqueTempDir());
   EXPECT_FALSE(dir.CreateUniqueTempDir());
   EXPECT_FALSE(other_dir.CreateUniqueTempDir());
diff --git a/base/sha1_portable.cc b/base/sha1_portable.cc
index d0f3c1c..cc05a5c 100644
--- a/base/sha1_portable.cc
+++ b/base/sha1_portable.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -99,6 +99,11 @@
 const int SecureHashAlgorithm::kDigestSizeBytes = 20;
 
 void SecureHashAlgorithm::Init() {
+  A = 0;
+  B = 0;
+  C = 0;
+  D = 0;
+  E = 0;
   cursor = 0;
   l = 0;
   H[0] = 0x67452301;
diff --git a/base/shared_memory_posix.cc b/base/shared_memory_posix.cc
index e83b982..5ac7597 100644
--- a/base/shared_memory_posix.cc
+++ b/base/shared_memory_posix.cc
@@ -196,24 +196,52 @@
   return PrepareMapFile(fp);
 }
 
-// For the given shmem named |mem_name|, return a filename to mmap()
-// (and possibly create).  Modifies |filename|.  Return false on
-// error, or true of we are happy.
-bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
-                                         FilePath* path) {
-  // mem_name will be used for a filename; make sure it doesn't
-  // contain anything which will confuse us.
-  DCHECK(mem_name.find('/') == std::string::npos);
-  DCHECK(mem_name.find('\0') == std::string::npos);
-
-  FilePath temp_dir;
-  if (!file_util::GetShmemTempDir(&temp_dir))
+bool SharedMemory::Map(uint32 bytes) {
+  if (mapped_file_ == -1)
     return false;
 
-  *path = temp_dir.AppendASCII("com.google.chrome.shmem." + mem_name);
+  memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
+                 MAP_SHARED, mapped_file_, 0);
+
+  if (memory_)
+    mapped_size_ = bytes;
+
+  bool mmap_succeeded = (memory_ != (void*)-1);
+  DCHECK(mmap_succeeded) << "Call to mmap failed, errno=" << errno;
+  return mmap_succeeded;
+}
+
+bool SharedMemory::Unmap() {
+  if (memory_ == NULL)
+    return false;
+
+  munmap(memory_, mapped_size_);
+  memory_ = NULL;
+  mapped_size_ = 0;
   return true;
 }
 
+SharedMemoryHandle SharedMemory::handle() const {
+  return FileDescriptor(mapped_file_, false);
+}
+
+void SharedMemory::Close() {
+  Unmap();
+
+  if (mapped_file_ > 0) {
+    close(mapped_file_);
+    mapped_file_ = -1;
+  }
+}
+
+void SharedMemory::Lock() {
+  LockOrUnlockCommon(F_LOCK);
+}
+
+void SharedMemory::Unlock() {
+  LockOrUnlockCommon(F_ULOCK);
+}
+
 bool SharedMemory::PrepareMapFile(FILE *fp) {
   DCHECK(mapped_file_ == -1);
   if (fp == NULL) return false;
@@ -243,55 +271,24 @@
   return true;
 }
 
-bool SharedMemory::Map(uint32 bytes) {
-  if (mapped_file_ == -1)
+// For the given shmem named |mem_name|, return a filename to mmap()
+// (and possibly create).  Modifies |filename|.  Return false on
+// error, or true of we are happy.
+bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
+                                         FilePath* path) {
+  // mem_name will be used for a filename; make sure it doesn't
+  // contain anything which will confuse us.
+  DCHECK(mem_name.find('/') == std::string::npos);
+  DCHECK(mem_name.find('\0') == std::string::npos);
+
+  FilePath temp_dir;
+  if (!file_util::GetShmemTempDir(&temp_dir))
     return false;
 
-  memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
-                 MAP_SHARED, mapped_file_, 0);
-
-  if (memory_)
-    mapped_size_ = bytes;
-
-  bool mmap_succeeded = (memory_ != (void*)-1);
-  DCHECK(mmap_succeeded) << "Call to mmap failed, errno=" << errno;
-  return mmap_succeeded;
-}
-
-bool SharedMemory::Unmap() {
-  if (memory_ == NULL)
-    return false;
-
-  munmap(memory_, mapped_size_);
-  memory_ = NULL;
-  mapped_size_ = 0;
+  *path = temp_dir.AppendASCII("com.google.chrome.shmem." + mem_name);
   return true;
 }
 
-bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
-                                        SharedMemoryHandle *new_handle,
-                                        bool close_self) {
-  const int new_fd = dup(mapped_file_);
-  DCHECK(new_fd >= 0);
-  new_handle->fd = new_fd;
-  new_handle->auto_close = true;
-
-  if (close_self)
-    Close();
-
-  return true;
-}
-
-
-void SharedMemory::Close() {
-  Unmap();
-
-  if (mapped_file_ > 0) {
-    close(mapped_file_);
-    mapped_file_ = -1;
-  }
-}
-
 void SharedMemory::LockOrUnlockCommon(int function) {
   DCHECK(mapped_file_ >= 0);
 #if !defined(ANDROID)
@@ -313,6 +310,7 @@
 #endif
 }
 
+<<<<<<< HEAD
 void SharedMemory::Lock() {
 #if !defined(ANDROID)
   LockOrUnlockCommon(F_LOCK);
@@ -324,9 +322,20 @@
   LockOrUnlockCommon(F_ULOCK);
 #endif
 }
+=======
+bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
+                                        SharedMemoryHandle *new_handle,
+                                        bool close_self) {
+  const int new_fd = dup(mapped_file_);
+  DCHECK(new_fd >= 0);
+  new_handle->fd = new_fd;
+  new_handle->auto_close = true;
 
-SharedMemoryHandle SharedMemory::handle() const {
-  return FileDescriptor(mapped_file_, false);
+  if (close_self)
+    Close();
+>>>>>>> chromium.org at r11.0.672.0
+
+  return true;
 }
 
 }  // namespace base
diff --git a/base/string_piece.h b/base/string_piece.h
index 80c6cab..64326e1 100644
--- a/base/string_piece.h
+++ b/base/string_piece.h
@@ -19,8 +19,6 @@
 #define BASE_STRING_PIECE_H_
 #pragma once
 
-#include <algorithm>
-#include <iosfwd>
 #include <string>
 
 #include "base/basictypes.h"
@@ -93,7 +91,8 @@
   }
 
   int compare(const StringPiece& x) const {
-    int r = wordmemcmp(ptr_, x.ptr_, std::min(length_, x.length_));
+    int r = wordmemcmp(
+        ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
     if (r == 0) {
       if (length_ < x.length_) r = -1;
       else if (length_ > x.length_) r = +1;
@@ -171,8 +170,8 @@
 }
 
 inline bool operator<(const StringPiece& x, const StringPiece& y) {
-  const int r = StringPiece::wordmemcmp(x.data(), y.data(),
-                                        std::min(x.size(), y.size()));
+  const int r = StringPiece::wordmemcmp(
+      x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
   return ((r < 0) || ((r == 0) && (x.size() < y.size())));
 }
 
@@ -188,9 +187,6 @@
   return !(x < y);
 }
 
-// allow StringPiece to be logged (needed for unit testing).
-extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece);
-
 }  // namespace base
 
 #endif  // BASE_STRING_PIECE_H_
diff --git a/base/synchronization/condition_variable.h b/base/synchronization/condition_variable.h
index 3acd0ac..db75a49 100644
--- a/base/synchronization/condition_variable.h
+++ b/base/synchronization/condition_variable.h
@@ -75,7 +75,7 @@
 #endif
 
 #include "base/basictypes.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 
@@ -156,10 +156,10 @@
   RunState run_state_;
 
   // Private critical section for access to member data.
-  Lock internal_lock_;
+  base::Lock internal_lock_;
 
   // Lock that is acquired before calling Wait().
-  Lock& user_lock_;
+  base::Lock& user_lock_;
 
   // Events that threads are blocked on.
   Event waiting_list_;
@@ -176,7 +176,7 @@
   pthread_cond_t condition_;
   pthread_mutex_t* user_mutex_;
 #if !defined(NDEBUG)
-  Lock* user_lock_;     // Needed to adjust shadow lock state on wait.
+  base::Lock* user_lock_;     // Needed to adjust shadow lock state on wait.
 #endif
 
 #endif
diff --git a/base/synchronization/condition_variable_unittest.cc b/base/synchronization/condition_variable_unittest.cc
index 8cfe4fe..cf18320 100644
--- a/base/synchronization/condition_variable_unittest.cc
+++ b/base/synchronization/condition_variable_unittest.cc
@@ -8,11 +8,11 @@
 #include <algorithm>
 #include <vector>
 
-#include "base/synchronization/condition_variable.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/spin_wait.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_collision_warner.h"
 #include "base/time.h"
@@ -198,7 +198,7 @@
   Time start_time;  // Used to time task processing.
 
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     while (!queue.EveryIdWasAllocated())
       queue.all_threads_have_ids()->Wait();
   }
@@ -209,7 +209,7 @@
 
   {
     // Since we have no tasks yet, all threads should be waiting by now.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -232,7 +232,7 @@
 
   {
     // Wait until all 10 work tasks have at least been assigned.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     while (queue.task_count())
       queue.no_more_tasks()->Wait();
     // The last of the tasks *might* still be running, but... all but one should
@@ -252,7 +252,7 @@
 
   {
     // Check that all work was done by one thread id.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(1, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(1, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -278,7 +278,7 @@
 
   {
     // Wait until all work tasks have at least been assigned.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     while (queue.task_count())
       queue.no_more_tasks()->Wait();
 
@@ -301,7 +301,7 @@
   queue.SpinUntilAllThreadsAreWaiting();
 
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -322,7 +322,7 @@
   queue.SpinUntilAllThreadsAreWaiting();
 
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -343,7 +343,7 @@
   queue.SpinUntilAllThreadsAreWaiting();  // Should take about 60 ms.
 
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -362,7 +362,7 @@
   queue.SpinUntilAllThreadsAreWaiting();  // Should take about 60 ms.
 
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -381,11 +381,11 @@
   WorkQueue queue(kThreadCount);  // Start the threads.
 
   Lock private_lock;  // Used locally for master to wait.
-  AutoLock private_held_lock(private_lock);
+  base::AutoLock private_held_lock(private_lock);
   ConditionVariable private_cv(&private_lock);
 
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     while (!queue.EveryIdWasAllocated())
       queue.all_threads_have_ids()->Wait();
   }
@@ -395,7 +395,7 @@
 
   {
     // Since we have no tasks, all threads should be waiting by now.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -412,7 +412,7 @@
   queue.work_is_available()->Broadcast();  // Start up all threads.
   // Wait until we've handed out all tasks.
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     while (queue.task_count() != 0)
       queue.no_more_tasks()->Wait();
   }
@@ -423,7 +423,7 @@
   {
     // With Broadcast(), every thread should have participated.
     // but with racing.. they may not all have done equal numbers of tasks.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -440,7 +440,7 @@
 
   // Wait until we've handed out all tasks
   {
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     while (queue.task_count() != 0)
       queue.no_more_tasks()->Wait();
   }
@@ -451,7 +451,7 @@
   {
     // With Signal(), every thread should have participated.
     // but with racing.. they may not all have done four tasks.
-    AutoLock auto_lock(*queue.lock());
+    base::AutoLock auto_lock(*queue.lock());
     EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
     EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
     EXPECT_EQ(0, queue.task_count());
@@ -500,7 +500,7 @@
 
 WorkQueue::~WorkQueue() {
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     SetShutdown();
   }
   work_is_available_.Broadcast();  // Tell them all to terminate.
@@ -558,7 +558,7 @@
 // lock already acquired.
 bool WorkQueue::ThreadSafeCheckShutdown(int thread_count) {
   bool all_shutdown;
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   {
     // Declare in scope so DFAKE is guranteed to be destroyed before AutoLock.
     DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
@@ -657,7 +657,7 @@
 void WorkQueue::SpinUntilAllThreadsAreWaiting() {
   while (true) {
     {
-      AutoLock auto_lock(lock_);
+      base::AutoLock auto_lock(lock_);
       if (waiting_thread_count_ == thread_count_)
         break;
     }
@@ -668,7 +668,7 @@
 void WorkQueue::SpinUntilTaskCountLessThan(int task_count) {
   while (true) {
     {
-      AutoLock auto_lock(lock_);
+      base::AutoLock auto_lock(lock_);
       if (task_count_ < task_count)
         break;
     }
@@ -698,7 +698,7 @@
 void WorkQueue::ThreadMain() {
   int thread_id;
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     thread_id = GetThreadId();
     if (EveryIdWasAllocated())
       all_threads_have_ids()->Signal();  // Tell creator we're ready.
@@ -709,7 +709,7 @@
     TimeDelta work_time;
     bool could_use_help;
     {
-      AutoLock auto_lock(lock_);
+      base::AutoLock auto_lock(lock_);
       while (0 == task_count() && !shutdown()) {
         ++waiting_thread_count_;
         work_is_available()->Wait();
@@ -732,13 +732,13 @@
     if (work_time > TimeDelta::FromMilliseconds(0)) {
       // We could just sleep(), but we'll instead further exercise the
       // condition variable class, and do a timed wait.
-      AutoLock auto_lock(private_lock);
+      base::AutoLock auto_lock(private_lock);
       ConditionVariable private_cv(&private_lock);
       private_cv.TimedWait(work_time);  // Unsynchronized waiting.
     }
 
     {
-      AutoLock auto_lock(lock_);
+      base::AutoLock auto_lock(lock_);
       // Send notification that we completed our "work."
       WorkIsCompleted(thread_id);
     }
diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h
index 01b5987..9f357d1 100644
--- a/base/synchronization/waitable_event.h
+++ b/base/synchronization/waitable_event.h
@@ -15,8 +15,8 @@
 #if defined(OS_POSIX)
 #include <list>
 #include <utility>
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #endif
 
 namespace base {
@@ -149,7 +149,7 @@
 
     bool Dequeue(Waiter* waiter, void* tag);
 
-    Lock lock_;
+    base::Lock lock_;
     const bool manual_reset_;
     bool signaled_;
     std::list<Waiter*> waiters_;
diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc
index 9cbc03a..ae03ead 100644
--- a/base/synchronization/waitable_event_posix.cc
+++ b/base/synchronization/waitable_event_posix.cc
@@ -149,6 +149,10 @@
   base::ConditionVariable cv_;
 };
 
+bool WaitableEvent::Wait() {
+  return TimedWait(TimeDelta::FromSeconds(-1));
+}
+
 bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
   const Time end_time(Time::Now() + max_time);
   const bool finite_time = max_time.ToInternalValue() >= 0;
@@ -204,13 +208,6 @@
   }
 }
 
-bool WaitableEvent::Wait() {
-  return TimedWait(TimeDelta::FromSeconds(-1));
-}
-
-// -----------------------------------------------------------------------------
-
-
 // -----------------------------------------------------------------------------
 // Synchronous waiting on multiple objects.
 
diff --git a/base/sys_info_win.cc b/base/sys_info_win.cc
index fa3ab43..83e099c 100644
--- a/base/sys_info_win.cc
+++ b/base/sys_info_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -63,8 +63,8 @@
 }
 
 // TODO: Implement OperatingSystemVersionComplete, which would include
-// patchlevel/service pack number. See chrome/browser/views/bug_report_view.cc,
-// BugReportView::SetOSVersion.
+// patchlevel/service pack number.
+// See chrome/browser/ui/views/bug_report_view.cc, BugReportView::SetOSVersion.
 
 // static
 std::string SysInfo::CPUArchitecture() {
diff --git a/base/template_util.h b/base/template_util.h
index 27bdb73..0408fc6 100644
--- a/base/template_util.h
+++ b/base/template_util.h
@@ -6,6 +6,8 @@
 #define BASE_TEMPLATE_UTIL_H_
 #pragma once
 
+#include <cstddef>  // For size_t.
+
 #include "build/build_config.h"
 
 namespace base {
@@ -27,14 +29,22 @@
 template <class T> struct is_pointer : false_type {};
 template <class T> struct is_pointer<T*> : true_type {};
 
+template<class> struct is_array : public false_type {};
+template<class T, size_t n> struct is_array<T[n]> : public true_type {};
+template<class T> struct is_array<T[]> : public true_type {};
+
+template <class T> struct is_non_const_reference : false_type {};
+template <class T> struct is_non_const_reference<T&> : true_type {};
+template <class T> struct is_non_const_reference<const T&> : false_type {};
+
 namespace internal {
 
-// Types small_ and big_ are guaranteed such that sizeof(small_) <
-// sizeof(big_)
-typedef char small_;
+// Types YesType and NoType are guaranteed such that sizeof(YesType) <
+// sizeof(NoType).
+typedef char YesType;
 
-struct big_ {
-  small_ dummy[2];
+struct NoType {
+  YesType dummy[2];
 };
 
 #if !defined(OS_WIN)
@@ -50,13 +60,23 @@
 
 template <typename From, typename To>
 struct ConvertHelper {
-  static small_ Test(To);
-  static big_ Test(...);
+  static YesType Test(To);
+  static NoType Test(...);
   static From Create();
 };
 
 #endif  // !defined(OS_WIN)
 
+// Used to determine if a type is a struct/union/class. Inspired by Boost's
+// is_class type_trait implementation.
+struct IsClassHelper {
+  template <typename C>
+  static YesType Test(void(C::*)(void));
+
+  template <typename C>
+  static NoType Test(...);
+};
+
 }  // namespace internal
 
 #if !defined(OS_WIN)
@@ -67,11 +87,18 @@
     : integral_constant<bool,
                         sizeof(internal::ConvertHelper<From, To>::Test(
                                   internal::ConvertHelper<From, To>::Create()))
-                        == sizeof(internal::small_)> {
+                        == sizeof(internal::YesType)> {
 };
 
 #endif  // !defined(OS_WIN)
 
+template <typename T>
+struct is_class
+    : integral_constant<bool,
+                        sizeof(internal::IsClassHelper::Test<T>(0)) ==
+                            sizeof(internal::YesType)> {
+};
+
 }  // namespace base
 
 #endif  // BASE_TEMPLATE_UTIL_H_
diff --git a/base/template_util_unittest.cc b/base/template_util_unittest.cc
new file mode 100644
index 0000000..51d4d33
--- /dev/null
+++ b/base/template_util_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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/template_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace {
+
+struct AStruct {};
+class AClass {};
+enum AnEnum {};
+
+class Parent {};
+class Child : public Parent {};
+
+TEST(TemplateUtilTest, IsPointer) {
+  EXPECT_FALSE(is_pointer<int>::value);
+  EXPECT_FALSE(is_pointer<int&>::value);
+  EXPECT_TRUE(is_pointer<int*>::value);
+  EXPECT_TRUE(is_pointer<const int*>::value);
+}
+
+TEST(TemplateUtilTest, IsArray) {
+  EXPECT_FALSE(is_array<int>::value);
+  EXPECT_FALSE(is_array<int*>::value);
+  EXPECT_FALSE(is_array<int(*)[3]>::value);
+  EXPECT_TRUE(is_array<int[]>::value);
+  EXPECT_TRUE(is_array<const int[]>::value);
+  EXPECT_TRUE(is_array<int[3]>::value);
+}
+
+TEST(TemplateUtilTest, IsNonConstReference) {
+  EXPECT_FALSE(is_non_const_reference<int>::value);
+  EXPECT_FALSE(is_non_const_reference<const int&>::value);
+  EXPECT_TRUE(is_non_const_reference<int&>::value);
+}
+
+#if !defined(OS_WIN)
+// TODO(ajwong): Why is is_convertible disabled on windows?
+TEST(TemplateUtilTest, IsConvertible) {
+  // Extra parents needed to make EXPECT_*'s parsing happy. Otherwise,
+  // it sees the equivalent of
+  //
+  //  EXPECT_TRUE( (is_convertible < Child), (Parent > ::value));
+  //
+  // Silly C++.
+  EXPECT_TRUE( (is_convertible<Child, Parent>::value) );
+  EXPECT_FALSE( (is_convertible<Parent, Child>::value) );
+}
+#endif  // !defined(OS_WIN)
+
+TEST(TemplateUtilTest, IsClass) {
+  EXPECT_TRUE(is_class<AStruct>::value);
+  EXPECT_TRUE(is_class<AClass>::value);
+
+  EXPECT_FALSE(is_class<AnEnum>::value);
+  EXPECT_FALSE(is_class<int>::value);
+  EXPECT_FALSE(is_class<char*>::value);
+  EXPECT_FALSE(is_class<int&>::value);
+  EXPECT_FALSE(is_class<char[3]>::value);
+}
+
+}  // namespace
+}  // namespace base
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index aa23f04..447a138 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -24,6 +24,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
 
+#if defined(OS_MACOSX)
+#include "base/test/mock_chrome_application_mac.h"
+#endif
+
 #if defined(TOOLKIT_USES_GTK)
 #include <gtk/gtk.h>
 #endif
@@ -171,14 +175,21 @@
 }
 
 void TestSuite::Initialize() {
+#if defined(OS_MACOSX)
+  // Some of the app unit tests spin runloops.
+  mock_cr_app::RegisterMockCrApp();
+#endif
+
   // Initialize logging.
   FilePath exe;
   PathService::Get(base::FILE_EXE, &exe);
   FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
-  logging::InitLogging(log_filename.value().c_str(),
-                       logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
-                       logging::LOCK_LOG_FILE,
-                       logging::DELETE_OLD_LOG_FILE);
+  logging::InitLogging(
+      log_filename.value().c_str(),
+      logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
+      logging::LOCK_LOG_FILE,
+      logging::DELETE_OLD_LOG_FILE,
+      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
   // We want process and thread IDs because we may have multiple processes.
   // Note: temporarily enabled timestamps in an effort to catch bug 6361.
   logging::SetLogItems(true, true, true, true);
diff --git a/base/test/test_timeouts.cc b/base/test/test_timeouts.cc
index 016456e..20cd8a9 100644
--- a/base/test/test_timeouts.cc
+++ b/base/test/test_timeouts.cc
@@ -44,7 +44,7 @@
 // static
 int TestTimeouts::tiny_timeout_ms_ = 100;
 int TestTimeouts::action_timeout_ms_ = 2000;
-int TestTimeouts::action_max_timeout_ms_ = 15000;
+int TestTimeouts::action_max_timeout_ms_ = 20000;
 int TestTimeouts::large_test_timeout_ms_ = 3 * 60 * 1000;
 int TestTimeouts::huge_test_timeout_ms_ = 10 * 60 * 1000;
 
diff --git a/base/third_party/dmg_fp/dtoa_wrapper.cc b/base/third_party/dmg_fp/dtoa_wrapper.cc
index fbbaf80..e34b8a6 100644
--- a/base/third_party/dmg_fp/dtoa_wrapper.cc
+++ b/base/third_party/dmg_fp/dtoa_wrapper.cc
@@ -4,12 +4,12 @@
 //
 // The purpose of this file is to supply the macro definintions necessary
 // to make third_party/dmg_fp/dtoa.cc threadsafe.
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/logging.h"
 
 // We need two locks because they're sometimes grabbed at the same time.
 // A single lock would lead to an attempted recursive grab.
-static Lock dtoa_locks[2];
+static base::Lock dtoa_locks[2];
 
 /*
  * This define and the code below is to trigger thread-safe behavior
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.c b/base/third_party/dynamic_annotations/dynamic_annotations.c
index 4bfc33b..31e9a2b 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.c
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.c
@@ -50,77 +50,86 @@
 
 #if DYNAMIC_ANNOTATIONS_ENABLED == 1
 
-void AnnotateRWLockCreate(const char *file, int line,
-                          const volatile void *lock){}
-void AnnotateRWLockDestroy(const char *file, int line,
-                           const volatile void *lock){}
-void AnnotateRWLockAcquired(const char *file, int line,
-                            const volatile void *lock, long is_w){}
-void AnnotateRWLockReleased(const char *file, int line,
-                            const volatile void *lock, long is_w){}
-void AnnotateBarrierInit(const char *file, int line,
-                         const volatile void *barrier, long count,
-                         long reinitialization_allowed) {}
-void AnnotateBarrierWaitBefore(const char *file, int line,
-                               const volatile void *barrier) {}
-void AnnotateBarrierWaitAfter(const char *file, int line,
-                              const volatile void *barrier) {}
-void AnnotateBarrierDestroy(const char *file, int line,
-                            const volatile void *barrier) {}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(
+    const char *file, int line, const volatile void *lock){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(
+    const char *file, int line, const volatile void *lock){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(
+    const char *file, int line, const volatile void *lock, long is_w){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(
+    const char *file, int line, const volatile void *lock, long is_w){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(
+    const char *file, int line, const volatile void *barrier, long count,
+    long reinitialization_allowed) {}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(
+    const char *file, int line, const volatile void *barrier) {}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(
+    const char *file, int line, const volatile void *barrier) {}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(
+    const char *file, int line, const volatile void *barrier) {}
 
-void AnnotateCondVarWait(const char *file, int line,
-                         const volatile void *cv,
-                         const volatile void *lock){}
-void AnnotateCondVarSignal(const char *file, int line,
-                           const volatile void *cv){}
-void AnnotateCondVarSignalAll(const char *file, int line,
-                              const volatile void *cv){}
-void AnnotatePublishMemoryRange(const char *file, int line,
-                                const volatile void *address,
-                                long size){}
-void AnnotateUnpublishMemoryRange(const char *file, int line,
-                                  const volatile void *address,
-                                  long size){}
-void AnnotatePCQCreate(const char *file, int line,
-                       const volatile void *pcq){}
-void AnnotatePCQDestroy(const char *file, int line,
-                        const volatile void *pcq){}
-void AnnotatePCQPut(const char *file, int line,
-                    const volatile void *pcq){}
-void AnnotatePCQGet(const char *file, int line,
-                    const volatile void *pcq){}
-void AnnotateNewMemory(const char *file, int line,
-                       const volatile void *mem,
-                       long size){}
-void AnnotateExpectRace(const char *file, int line,
-                        const volatile void *mem,
-                        const char *description){}
-void AnnotateBenignRace(const char *file, int line,
-                        const volatile void *mem,
-                        const char *description){}
-void AnnotateBenignRaceSized(const char *file, int line,
-                             const volatile void *mem,
-                             long size,
-                             const char *description) {}
-void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
-                                  const volatile void *mu){}
-void AnnotateTraceMemory(const char *file, int line,
-                         const volatile void *arg){}
-void AnnotateThreadName(const char *file, int line,
-                        const char *name){}
-void AnnotateIgnoreReadsBegin(const char *file, int line){}
-void AnnotateIgnoreReadsEnd(const char *file, int line){}
-void AnnotateIgnoreWritesBegin(const char *file, int line){}
-void AnnotateIgnoreWritesEnd(const char *file, int line){}
-void AnnotateIgnoreSyncBegin(const char *file, int line){}
-void AnnotateIgnoreSyncEnd(const char *file, int line){}
-void AnnotateEnableRaceDetection(const char *file, int line, int enable){}
-void AnnotateNoOp(const char *file, int line,
-                  const volatile void *arg){}
-void AnnotateFlushState(const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(
+    const char *file, int line, const volatile void *cv,
+    const volatile void *lock){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(
+    const char *file, int line, const volatile void *cv){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(
+    const char *file, int line, const volatile void *cv){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(
+    const char *file, int line, const volatile void *address, long size){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(
+    const char *file, int line, const volatile void *address, long size){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(
+    const char *file, int line, const volatile void *pcq){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(
+    const char *file, int line, const volatile void *pcq){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(
+    const char *file, int line, const volatile void *pcq){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(
+    const char *file, int line, const volatile void *pcq){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(
+    const char *file, int line, const volatile void *mem, long size){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(
+    const char *file, int line, const volatile void *mem, long size,
+    const char *description){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(
+    const char *file, int line, const volatile void *mu){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(
+    const char *file, int line, const volatile void *mu){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(
+    const char *file, int line, const volatile void *arg){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(
+    const char *file, int line, const char *name){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(
+    const char *file, int line){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(
+    const char *file, int line, int enable){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(
+    const char *file, int line, const volatile void *arg){}
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(
+    const char *file, int line){}
 
 #endif  /* DYNAMIC_ANNOTATIONS_ENABLED == 1 */
 
+#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1
 static int GetRunningOnValgrind(void) {
 #ifdef RUNNING_ON_VALGRIND
   if (RUNNING_ON_VALGRIND) return 1;
@@ -157,3 +166,5 @@
     running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
   return local_running_on_valgrind;
 }
+
+#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 */
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.h b/base/third_party/dynamic_annotations/dynamic_annotations.h
index 373f2ac..263b8ef 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.h
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.h
@@ -53,6 +53,33 @@
 #ifndef __DYNAMIC_ANNOTATIONS_H__
 #define __DYNAMIC_ANNOTATIONS_H__
 
+#ifndef DYNAMIC_ANNOTATIONS_PREFIX
+# define DYNAMIC_ANNOTATIONS_PREFIX
+#endif
+
+#ifndef DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND
+# define DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND 1
+#endif
+
+#ifdef DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK
+# ifdef __GNUC__
+#  define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak))
+# else
+/* TODO(glider): for Windows support we may want to change this macro in order
+   to prepend __declspec(selectany) to the annotations' declarations. */
+#  error weak annotations are not supported for your compiler
+# endif
+#else
+# define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK
+#endif
+
+/* The following preprocessor magic prepends the value of
+   DYNAMIC_ANNOTATIONS_PREFIX to annotation function names. */
+#define DYNAMIC_ANNOTATIONS_GLUE0(A, B) A##B
+#define DYNAMIC_ANNOTATIONS_GLUE(A, B) DYNAMIC_ANNOTATIONS_GLUE0(A, B)
+#define DYNAMIC_ANNOTATIONS_NAME(name) \
+  DYNAMIC_ANNOTATIONS_GLUE(DYNAMIC_ANNOTATIONS_PREFIX, name)
+
 #ifndef DYNAMIC_ANNOTATIONS_ENABLED
 # define DYNAMIC_ANNOTATIONS_ENABLED 0
 #endif
@@ -100,40 +127,36 @@
   /* Report that wait on the condition variable at address "cv" has succeeded
      and the lock at address "lock" is held. */
   #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
-    AnnotateCondVarWait(__FILE__, __LINE__, cv, lock)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, lock)
 
   /* Report that wait on the condition variable at "cv" has succeeded.  Variant
      w/o lock. */
   #define ANNOTATE_CONDVAR_WAIT(cv) \
-    AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, NULL)
 
   /* Report that we are about to signal on the condition variable at address
      "cv". */
   #define ANNOTATE_CONDVAR_SIGNAL(cv) \
-    AnnotateCondVarSignal(__FILE__, __LINE__, cv)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(__FILE__, __LINE__, cv)
 
   /* Report that we are about to signal_all on the condition variable at address
      "cv". */
   #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
-    AnnotateCondVarSignalAll(__FILE__, __LINE__, cv)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(__FILE__, __LINE__, cv)
 
   /* Annotations for user-defined synchronization mechanisms. */
   #define ANNOTATE_HAPPENS_BEFORE(obj) ANNOTATE_CONDVAR_SIGNAL(obj)
   #define ANNOTATE_HAPPENS_AFTER(obj)  ANNOTATE_CONDVAR_WAIT(obj)
 
-  /* Report that the bytes in the range [pointer, pointer+size) are about
-     to be published safely. The race checker will create a happens-before
-     arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
-     subsequent accesses to this memory.
-     Note: this annotation may not work properly if the race detector uses
-     sampling, i.e. does not observe all memory accesses.
-     */
+  /* DEPRECATED. Don't use it. */
   #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
-    AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(__FILE__, __LINE__, \
+        pointer, size)
 
   /* DEPRECATED. Don't use it. */
   #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
-    AnnotateUnpublishMemoryRange(__FILE__, __LINE__, pointer, size)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(__FILE__, __LINE__, \
+        pointer, size)
 
   /* DEPRECATED. Don't use it. */
   #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size)   \
@@ -150,11 +173,19 @@
      happens-before detectors this is a no-op. For more details see
      http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
   #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
-    AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \
+        mu)
+
+  /* Opposite to ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX.
+     Instruct the tool to NOT create h-b arcs between Unlock and Lock, even in
+     pure happens-before mode. For a hybrid mode this is a no-op. */
+  #define ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(mu) \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(__FILE__, __LINE__, mu)
 
   /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
   #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
-    AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \
+        mu)
 
   /* -------------------------------------------------------------
      Annotations useful when defining memory allocators, or when memory that
@@ -165,7 +196,8 @@
      is about to be reused, or when a the locking discipline for a variable
      changes. */
   #define ANNOTATE_NEW_MEMORY(address, size) \
-    AnnotateNewMemory(__FILE__, __LINE__, address, size)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(__FILE__, __LINE__, address, \
+        size)
 
   /* -------------------------------------------------------------
      Annotations useful when defining FIFO queues that transfer data between
@@ -176,21 +208,21 @@
      should be used only for FIFO queues.  For non-FIFO queues use
      ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
   #define ANNOTATE_PCQ_CREATE(pcq) \
-    AnnotatePCQCreate(__FILE__, __LINE__, pcq)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(__FILE__, __LINE__, pcq)
 
   /* Report that the queue at address "pcq" is about to be destroyed. */
   #define ANNOTATE_PCQ_DESTROY(pcq) \
-    AnnotatePCQDestroy(__FILE__, __LINE__, pcq)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(__FILE__, __LINE__, pcq)
 
   /* Report that we are about to put an element into a FIFO queue at address
      "pcq". */
   #define ANNOTATE_PCQ_PUT(pcq) \
-    AnnotatePCQPut(__FILE__, __LINE__, pcq)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(__FILE__, __LINE__, pcq)
 
   /* Report that we've just got an element from a FIFO queue at address
      "pcq". */
   #define ANNOTATE_PCQ_GET(pcq) \
-    AnnotatePCQGet(__FILE__, __LINE__, pcq)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(__FILE__, __LINE__, pcq)
 
   /* -------------------------------------------------------------
      Annotations that suppress errors.  It is usually better to express the
@@ -202,13 +234,14 @@
      point where "pointer" has been allocated, preferably close to the point
      where the race happens.  See also ANNOTATE_BENIGN_RACE_STATIC. */
   #define ANNOTATE_BENIGN_RACE(pointer, description) \
-    AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
-                            sizeof(*(pointer)), description)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \
+        pointer, sizeof(*(pointer)), description)
 
   /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
      the memory range [address, address+size). */
   #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
-    AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \
+        address, size, description)
 
   /* Request the analysis tool to ignore all reads in the current thread
      until ANNOTATE_IGNORE_READS_END is called.
@@ -216,19 +249,19 @@
      other reads and all writes.
      See also ANNOTATE_UNPROTECTED_READ. */
   #define ANNOTATE_IGNORE_READS_BEGIN() \
-    AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
 
   /* Stop ignoring reads. */
   #define ANNOTATE_IGNORE_READS_END() \
-    AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
 
   /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
   #define ANNOTATE_IGNORE_WRITES_BEGIN() \
-    AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
 
   /* Stop ignoring writes. */
   #define ANNOTATE_IGNORE_WRITES_END() \
-    AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
 
   /* Start ignoring all memory accesses (reads and writes). */
   #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
@@ -247,29 +280,30 @@
   /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore synchronization events:
      RWLOCK* and CONDVAR*. */
   #define ANNOTATE_IGNORE_SYNC_BEGIN() \
-    AnnotateIgnoreSyncBegin(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(__FILE__, __LINE__)
 
   /* Stop ignoring sync events. */
   #define ANNOTATE_IGNORE_SYNC_END() \
-    AnnotateIgnoreSyncEnd(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(__FILE__, __LINE__)
 
 
   /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
      This annotation could be useful if you want to skip expensive race analysis
      during some period of program execution, e.g. during initialization. */
   #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
-    AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(__FILE__, __LINE__, \
+        enable)
 
   /* -------------------------------------------------------------
      Annotations useful for debugging. */
 
   /* Request to trace every access to "address". */
   #define ANNOTATE_TRACE_MEMORY(address) \
-    AnnotateTraceMemory(__FILE__, __LINE__, address)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(__FILE__, __LINE__, address)
 
   /* Report the current thread name to a race detector. */
   #define ANNOTATE_THREAD_NAME(name) \
-    AnnotateThreadName(__FILE__, __LINE__, name)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(__FILE__, __LINE__, name)
 
   /* -------------------------------------------------------------
      Annotations useful when implementing locks.  They are not
@@ -278,20 +312,22 @@
 
   /* Report that a lock has been created at address "lock". */
   #define ANNOTATE_RWLOCK_CREATE(lock) \
-    AnnotateRWLockCreate(__FILE__, __LINE__, lock)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
 
   /* Report that the lock at address "lock" is about to be destroyed. */
   #define ANNOTATE_RWLOCK_DESTROY(lock) \
-    AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
 
   /* Report that the lock at address "lock" has been acquired.
      is_w=1 for writer lock, is_w=0 for reader lock. */
   #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
-    AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(__FILE__, __LINE__, lock, \
+        is_w)
 
   /* Report that the lock at address "lock" is about to be released. */
   #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
-    AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(__FILE__, __LINE__, lock, \
+        is_w)
 
   /* -------------------------------------------------------------
      Annotations useful when implementing barriers.  They are not
@@ -302,20 +338,23 @@
    If 'reinitialization_allowed' is true, initialization is allowed to happen
    multiple times w/o calling barrier_destroy() */
   #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
-    AnnotateBarrierInit(__FILE__, __LINE__, barrier, count, \
-                        reinitialization_allowed)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(__FILE__, __LINE__, barrier, \
+        count, reinitialization_allowed)
 
   /* Report that we are about to enter barrier_wait("barrier"). */
   #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
-    AnnotateBarrierWaitBefore(__FILE__, __LINE__, barrier)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(__FILE__, __LINE__, \
+        barrier)
 
   /* Report that we just exited barrier_wait("barrier"). */
   #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
-    AnnotateBarrierWaitAfter(__FILE__, __LINE__, barrier)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(__FILE__, __LINE__, \
+        barrier)
 
   /* Report that the "barrier" has been destroyed. */
   #define ANNOTATE_BARRIER_DESTROY(barrier) \
-    AnnotateBarrierDestroy(__FILE__, __LINE__, barrier)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(__FILE__, __LINE__, \
+        barrier)
 
   /* -------------------------------------------------------------
      Annotations useful for testing race detectors. */
@@ -323,16 +362,20 @@
   /* Report that we expect a race on the variable at "address".
      Use only in unit tests for a race detector. */
   #define ANNOTATE_EXPECT_RACE(address, description) \
-    AnnotateExpectRace(__FILE__, __LINE__, address, description)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(__FILE__, __LINE__, address, \
+        description)
+
+  #define ANNOTATE_FLUSH_EXPECTED_RACES() \
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(__FILE__, __LINE__)
 
   /* A no-op. Insert where you like to test the interceptors. */
   #define ANNOTATE_NO_OP(arg) \
-    AnnotateNoOp(__FILE__, __LINE__, arg)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(__FILE__, __LINE__, arg)
 
   /* Force the race detector to flush its state. The actual effect depends on
    * the implementation of the detector. */
   #define ANNOTATE_FLUSH_STATE() \
-    AnnotateFlushState(__FILE__, __LINE__)
+    DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(__FILE__, __LINE__)
 
 
 #else  /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
@@ -360,6 +403,7 @@
   #define ANNOTATE_PCQ_GET(pcq) /* empty */
   #define ANNOTATE_NEW_MEMORY(address, size) /* empty */
   #define ANNOTATE_EXPECT_RACE(address, description) /* empty */
+  #define ANNOTATE_FLUSH_EXPECTED_RACES(address, description) /* empty */
   #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
   #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
   #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
@@ -384,72 +428,106 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
-void AnnotateRWLockCreate(const char *file, int line,
-                          const volatile void *lock);
-void AnnotateRWLockDestroy(const char *file, int line,
-                           const volatile void *lock);
-void AnnotateRWLockAcquired(const char *file, int line,
-                            const volatile void *lock, long is_w);
-void AnnotateRWLockReleased(const char *file, int line,
-                            const volatile void *lock, long is_w);
-void AnnotateBarrierInit(const char *file, int line,
-                         const volatile void *barrier, long count,
-                         long reinitialization_allowed);
-void AnnotateBarrierWaitBefore(const char *file, int line,
-                               const volatile void *barrier);
-void AnnotateBarrierWaitAfter(const char *file, int line,
-                              const volatile void *barrier);
-void AnnotateBarrierDestroy(const char *file, int line,
-                            const volatile void *barrier);
-void AnnotateCondVarWait(const char *file, int line,
-                         const volatile void *cv,
-                         const volatile void *lock);
-void AnnotateCondVarSignal(const char *file, int line,
-                           const volatile void *cv);
-void AnnotateCondVarSignalAll(const char *file, int line,
-                              const volatile void *cv);
-void AnnotatePublishMemoryRange(const char *file, int line,
-                                const volatile void *address,
-                                long size);
-void AnnotateUnpublishMemoryRange(const char *file, int line,
-                                  const volatile void *address,
-                                  long size);
-void AnnotatePCQCreate(const char *file, int line,
-                       const volatile void *pcq);
-void AnnotatePCQDestroy(const char *file, int line,
-                        const volatile void *pcq);
-void AnnotatePCQPut(const char *file, int line,
-                    const volatile void *pcq);
-void AnnotatePCQGet(const char *file, int line,
-                    const volatile void *pcq);
-void AnnotateNewMemory(const char *file, int line,
-                       const volatile void *address,
-                       long size);
-void AnnotateExpectRace(const char *file, int line,
-                        const volatile void *address,
-                        const char *description);
-void AnnotateBenignRace(const char *file, int line,
-                        const volatile void *address,
-                        const char *description);
-void AnnotateBenignRaceSized(const char *file, int line,
-                        const volatile void *address,
-                        long size,
-                        const char *description);
-void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
-                                  const volatile void *mu);
-void AnnotateTraceMemory(const char *file, int line,
-                         const volatile void *arg);
-void AnnotateThreadName(const char *file, int line,
-                        const char *name);
-void AnnotateIgnoreReadsBegin(const char *file, int line);
-void AnnotateIgnoreReadsEnd(const char *file, int line);
-void AnnotateIgnoreWritesBegin(const char *file, int line);
-void AnnotateIgnoreWritesEnd(const char *file, int line);
-void AnnotateEnableRaceDetection(const char *file, int line, int enable);
-void AnnotateNoOp(const char *file, int line,
-                  const volatile void *arg);
-void AnnotateFlushState(const char *file, int line);
 
+
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(
+    const char *file, int line,
+    const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(
+    const char *file, int line,
+    const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(
+    const char *file, int line,
+    const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(
+    const char *file, int line,
+    const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(
+    const char *file, int line, const volatile void *barrier, long count,
+    long reinitialization_allowed) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(
+    const char *file, int line,
+    const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(
+    const char *file, int line,
+    const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(
+    const char *file, int line,
+    const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(
+    const char *file, int line, const volatile void *cv,
+    const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(
+    const char *file, int line,
+    const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(
+    const char *file, int line,
+    const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(
+    const char *file, int line,
+    const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(
+    const char *file, int line,
+    const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(
+    const char *file, int line,
+    const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(
+    const char *file, int line,
+    const volatile void *mem, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)(
+    const char *file, int line, const volatile void *mem,
+    const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(
+    const char *file, int line, const volatile void *mem, long size,
+    const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(
+    const char *file, int line,
+    const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(
+    const char *file, int line,
+    const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(
+    const char *file, int line,
+    const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(
+    const char *file, int line,
+    const char *name) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(
+    const char *file, int line, int enable) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(
+    const char *file, int line,
+    const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(
+    const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+
+#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1
 /* Return non-zero value if running under valgrind.
 
   If "valgrind.h" is included into dynamic_annotations.c,
@@ -466,6 +544,7 @@
       change its return value.
  */
 int RunningOnValgrind(void);
+#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 */
 
 #ifdef __cplusplus
 }
diff --git a/base/threading/simple_thread.cc b/base/threading/simple_thread.cc
index 2b030f6..4441477 100644
--- a/base/threading/simple_thread.cc
+++ b/base/threading/simple_thread.cc
@@ -10,6 +10,22 @@
 
 namespace base {
 
+SimpleThread::SimpleThread(const std::string& name_prefix)
+    : name_prefix_(name_prefix), name_(name_prefix),
+      thread_(), event_(true, false), tid_(0), joined_(false) {
+}
+
+SimpleThread::SimpleThread(const std::string& name_prefix,
+                           const Options& options)
+    : name_prefix_(name_prefix), name_(name_prefix), options_(options),
+      thread_(), event_(true, false), tid_(0), joined_(false) {
+}
+
+SimpleThread::~SimpleThread() {
+  DCHECK(HasBeenStarted()) << "SimpleThread was never started.";
+  DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed.";
+}
+
 void SimpleThread::Start() {
   DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times.";
   bool success = PlatformThread::Create(options_.stack_size(), this, &thread_);
@@ -37,22 +53,6 @@
   Run();
 }
 
-SimpleThread::SimpleThread(const std::string& name_prefix)
-    : name_prefix_(name_prefix), name_(name_prefix),
-      thread_(), event_(true, false), tid_(0), joined_(false) {
-}
-
-SimpleThread::SimpleThread(const std::string& name_prefix,
-                           const Options& options)
-    : name_prefix_(name_prefix), name_(name_prefix), options_(options),
-      thread_(), event_(true, false), tid_(0), joined_(false) {
-}
-
-SimpleThread::~SimpleThread() {
-  DCHECK(HasBeenStarted()) << "SimpleThread was never started.";
-  DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed.";
-}
-
 DelegateSimpleThread::DelegateSimpleThread(Delegate* delegate,
                                            const std::string& name_prefix)
     : SimpleThread(name_prefix),
diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h
index f55bd62..1631336 100644
--- a/base/threading/simple_thread.h
+++ b/base/threading/simple_thread.h
@@ -46,8 +46,8 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/threading/platform_thread.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 
 namespace base {
@@ -173,7 +173,7 @@
   int num_threads_;
   std::vector<DelegateSimpleThread*> threads_;
   std::queue<Delegate*> delegates_;
-  Lock lock_;            // Locks delegates_
+  base::Lock lock_;            // Locks delegates_
   WaitableEvent dry_;    // Not signaled when there is no work to do.
 };
 
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index 09f8847..c0fb537 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -11,6 +11,17 @@
 
 namespace base {
 
+namespace {
+
+// We use this thread-local variable to record whether or not a thread exited
+// because its Stop method was called.  This allows us to catch cases where
+// MessageLoop::Quit() is called directly, which is unexpected when using a
+// Thread to setup and run a MessageLoop.
+base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool(
+    base::LINKER_INITIALIZED);
+
+}  // namespace
+
 // This task is used to trigger the message loop to exit.
 class ThreadQuitTask : public Task {
  public:
@@ -48,29 +59,6 @@
   Stop();
 }
 
-namespace {
-
-// We use this thread-local variable to record whether or not a thread exited
-// because its Stop method was called.  This allows us to catch cases where
-// MessageLoop::Quit() is called directly, which is unexpected when using a
-// Thread to setup and run a MessageLoop.
-base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool(
-    base::LINKER_INITIALIZED);
-
-}  // namespace
-
-void Thread::SetThreadWasQuitProperly(bool flag) {
-  lazy_tls_bool.Pointer()->Set(flag);
-}
-
-bool Thread::GetThreadWasQuitProperly() {
-  bool quit_properly = true;
-#ifndef NDEBUG
-  quit_properly = lazy_tls_bool.Pointer()->Get();
-#endif
-  return quit_properly;
-}
-
 bool Thread::Start() {
   return StartWithOptions(Options());
 }
@@ -140,6 +128,18 @@
   message_loop->Run();
 }
 
+void Thread::SetThreadWasQuitProperly(bool flag) {
+  lazy_tls_bool.Pointer()->Set(flag);
+}
+
+bool Thread::GetThreadWasQuitProperly() {
+  bool quit_properly = true;
+#ifndef NDEBUG
+  quit_properly = lazy_tls_bool.Pointer()->Get();
+#endif
+  return quit_properly;
+}
+
 void Thread::ThreadMain() {
   {
     // The message loop for this thread.
diff --git a/base/threading/thread_checker.h b/base/threading/thread_checker.h
index c0010fb..712b5b5 100644
--- a/base/threading/thread_checker.h
+++ b/base/threading/thread_checker.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #ifndef NDEBUG
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 #endif // NDEBUG
 
@@ -51,7 +51,7 @@
  private:
   void EnsureThreadIdAssigned() const;
 
-  mutable Lock lock_;
+  mutable base::Lock lock_;
   // This is mutable so that CalledOnValidThread can set it.
   // It's guarded by |lock_|.
   mutable PlatformThreadId valid_thread_id_;
diff --git a/base/threading/thread_collision_warner_unittest.cc b/base/threading/thread_collision_warner_unittest.cc
index 68987c3..a3d3b66 100644
--- a/base/threading/thread_collision_warner_unittest.cc
+++ b/base/threading/thread_collision_warner_unittest.cc
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include "base/compiler_specific.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/simple_thread.h"
 #include "base/threading/thread_collision_warner.h"
@@ -266,30 +266,30 @@
   // a lock.
   class QueueUser : public base::DelegateSimpleThread::Delegate {
    public:
-    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
+    QueueUser(NonThreadSafeQueue& queue, base::Lock& lock)
         : queue_(queue),
           lock_(lock) {}
 
     virtual void Run() {
       {
-        AutoLock auto_lock(lock_);
+        base::AutoLock auto_lock(lock_);
         queue_.push(0);
       }
       {
-        AutoLock auto_lock(lock_);
+        base::AutoLock auto_lock(lock_);
         queue_.pop();
       }
     }
    private:
     NonThreadSafeQueue& queue_;
-    Lock& lock_;
+    base::Lock& lock_;
   };
 
   AssertReporter* local_reporter = new AssertReporter();
 
   NonThreadSafeQueue queue(local_reporter);
 
-  Lock lock;
+  base::Lock lock;
 
   QueueUser queue_user_a(queue, lock);
   QueueUser queue_user_b(queue, lock);
@@ -340,34 +340,34 @@
   // a lock.
   class QueueUser : public base::DelegateSimpleThread::Delegate {
    public:
-    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
+    QueueUser(NonThreadSafeQueue& queue, base::Lock& lock)
         : queue_(queue),
           lock_(lock) {}
 
     virtual void Run() {
       {
-        AutoLock auto_lock(lock_);
+        base::AutoLock auto_lock(lock_);
         queue_.push(0);
       }
       {
-        AutoLock auto_lock(lock_);
+        base::AutoLock auto_lock(lock_);
         queue_.bar();
       }
       {
-        AutoLock auto_lock(lock_);
+        base::AutoLock auto_lock(lock_);
         queue_.pop();
       }
     }
    private:
     NonThreadSafeQueue& queue_;
-    Lock& lock_;
+    base::Lock& lock_;
   };
 
   AssertReporter* local_reporter = new AssertReporter();
 
   NonThreadSafeQueue queue(local_reporter);
 
-  Lock lock;
+  base::Lock lock;
 
   QueueUser queue_user_a(queue, lock);
   QueueUser queue_user_b(queue, lock);
diff --git a/base/threading/thread_local_storage_posix.cc b/base/threading/thread_local_storage_posix.cc
index 81b7332..3d0e187 100644
--- a/base/threading/thread_local_storage_posix.cc
+++ b/base/threading/thread_local_storage_posix.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,8 @@
 namespace base {
 
 ThreadLocalStorage::Slot::Slot(TLSDestructorFunc destructor)
-    : initialized_(false) {
+    : initialized_(false),
+      key_(0) {
   Initialize(destructor);
 }
 
diff --git a/base/threading/thread_local_storage_win.cc b/base/threading/thread_local_storage_win.cc
index 2967a27..667d1b9 100644
--- a/base/threading/thread_local_storage_win.cc
+++ b/base/threading/thread_local_storage_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -57,7 +57,8 @@
 }
 
 ThreadLocalStorage::Slot::Slot(TLSDestructorFunc destructor)
-    : initialized_(false) {
+    : initialized_(false),
+      slot_(0) {
   Initialize(destructor);
 }
 
diff --git a/base/threading/worker_pool_posix_unittest.cc b/base/threading/worker_pool_posix_unittest.cc
index 332c55e..c984ee3 100644
--- a/base/threading/worker_pool_posix_unittest.cc
+++ b/base/threading/worker_pool_posix_unittest.cc
@@ -6,8 +6,8 @@
 
 #include <set>
 
-#include "base/lock.h"
 #include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "base/threading/platform_thread.h"
 #include "base/synchronization/waitable_event.h"
@@ -61,12 +61,12 @@
 
   virtual void Run() {
     AddSelfToUniqueThreadSet();
-    AutoLock locked(*counter_lock_);
+    base::AutoLock locked(*counter_lock_);
     (*counter_)++;
   }
 
   void AddSelfToUniqueThreadSet() {
-    AutoLock locked(*unique_threads_lock_);
+    base::AutoLock locked(*unique_threads_lock_);
     unique_threads_->insert(PlatformThread::CurrentId());
   }
 
@@ -100,7 +100,7 @@
 
   virtual void Run() {
     {
-      AutoLock num_waiting_to_start_locked(*num_waiting_to_start_lock_);
+      base::AutoLock num_waiting_to_start_locked(*num_waiting_to_start_lock_);
       (*num_waiting_to_start_)++;
     }
     num_waiting_to_start_cv_->Signal();
@@ -138,14 +138,14 @@
   }
 
   void WaitForTasksToStart(int num_tasks) {
-    AutoLock num_waiting_to_start_locked(num_waiting_to_start_lock_);
+    base::AutoLock num_waiting_to_start_locked(num_waiting_to_start_lock_);
     while (num_waiting_to_start_ < num_tasks) {
       num_waiting_to_start_cv_.Wait();
     }
   }
 
   void WaitForIdleThreads(int num_idle_threads) {
-    AutoLock pool_locked(*peer_.lock());
+    base::AutoLock pool_locked(*peer_.lock());
     while (peer_.num_idle_threads() < num_idle_threads) {
       peer_.num_idle_threads_cv()->Wait();
     }
@@ -249,7 +249,7 @@
 
   // Wake up all idle threads so they can exit.
   {
-    AutoLock locked(*peer_.lock());
+    base::AutoLock locked(*peer_.lock());
     while (peer_.num_idle_threads() > 0) {
       peer_.tasks_available_cv()->Signal();
       peer_.num_idle_threads_cv()->Wait();
diff --git a/base/time.h b/base/time.h
index e1fbf96..ed4e772 100644
--- a/base/time.h
+++ b/base/time.h
@@ -411,10 +411,6 @@
   int64 us_;
 };
 
-inline Time TimeDelta::operator+(Time t) const {
-  return Time(t.us_ + delta_);
-}
-
 // Inline the TimeDelta factory methods, for fast TimeDelta construction.
 
 // static
@@ -447,6 +443,10 @@
   return TimeDelta(us);
 }
 
+inline Time TimeDelta::operator+(Time t) const {
+  return Time(t.us_ + delta_);
+}
+
 // TimeTicks ------------------------------------------------------------------
 
 class TimeTicks {
diff --git a/base/time_posix.cc b/base/time_posix.cc
index 9646c87..62e6e49 100644
--- a/base/time_posix.cc
+++ b/base/time_posix.cc
@@ -14,6 +14,19 @@
 
 namespace base {
 
+struct timespec TimeDelta::ToTimeSpec() const {
+  int64 microseconds = InMicroseconds();
+  time_t seconds = 0;
+  if (microseconds >= Time::kMicrosecondsPerSecond) {
+    seconds = InSeconds();
+    microseconds -= seconds * Time::kMicrosecondsPerSecond;
+  }
+  struct timespec result =
+      {seconds,
+       microseconds * Time::kNanosecondsPerMicrosecond};
+  return result;
+}
+
 #if !defined(OS_MACOSX)
 // The Time routines in this file use standard POSIX routines, or almost-
 // standard routines in the case of timegm.  We need to use a Mach-specific
@@ -60,6 +73,30 @@
   return Now();
 }
 
+void Time::Explode(bool is_local, Exploded* exploded) const {
+  // Time stores times with microsecond resolution, but Exploded only carries
+  // millisecond resolution, so begin by being lossy.  Adjust from Windows
+  // epoch (1601) to Unix epoch (1970);
+  int64 milliseconds = (us_ - kWindowsEpochDeltaMicroseconds) /
+      kMicrosecondsPerMillisecond;
+  time_t seconds = milliseconds / kMillisecondsPerSecond;
+
+  struct tm timestruct;
+  if (is_local)
+    localtime_r(&seconds, &timestruct);
+  else
+    gmtime_r(&seconds, &timestruct);
+
+  exploded->year         = timestruct.tm_year + 1900;
+  exploded->month        = timestruct.tm_mon + 1;
+  exploded->day_of_week  = timestruct.tm_wday;
+  exploded->day_of_month = timestruct.tm_mday;
+  exploded->hour         = timestruct.tm_hour;
+  exploded->minute       = timestruct.tm_min;
+  exploded->second       = timestruct.tm_sec;
+  exploded->millisecond  = milliseconds % kMillisecondsPerSecond;
+}
+
 // static
 Time Time::FromExploded(bool is_local, const Exploded& exploded) {
   struct tm timestruct;
@@ -119,30 +156,6 @@
       kWindowsEpochDeltaMicroseconds);
 }
 
-void Time::Explode(bool is_local, Exploded* exploded) const {
-  // Time stores times with microsecond resolution, but Exploded only carries
-  // millisecond resolution, so begin by being lossy.  Adjust from Windows
-  // epoch (1601) to Unix epoch (1970);
-  int64 milliseconds = (us_ - kWindowsEpochDeltaMicroseconds) /
-      kMicrosecondsPerMillisecond;
-  time_t seconds = milliseconds / kMillisecondsPerSecond;
-
-  struct tm timestruct;
-  if (is_local)
-    localtime_r(&seconds, &timestruct);
-  else
-    gmtime_r(&seconds, &timestruct);
-
-  exploded->year         = timestruct.tm_year + 1900;
-  exploded->month        = timestruct.tm_mon + 1;
-  exploded->day_of_week  = timestruct.tm_wday;
-  exploded->day_of_month = timestruct.tm_mday;
-  exploded->hour         = timestruct.tm_hour;
-  exploded->minute       = timestruct.tm_min;
-  exploded->second       = timestruct.tm_sec;
-  exploded->millisecond  = milliseconds % kMillisecondsPerSecond;
-}
-
 // TimeTicks ------------------------------------------------------------------
 // FreeBSD 6 has CLOCK_MONOLITHIC but defines _POSIX_MONOTONIC_CLOCK to -1.
 #if (defined(OS_POSIX) &&                                               \
@@ -177,19 +190,6 @@
 
 #endif  // !OS_MACOSX
 
-struct timespec TimeDelta::ToTimeSpec() const {
-  int64 microseconds = InMicroseconds();
-  time_t seconds = 0;
-  if (microseconds >= Time::kMicrosecondsPerSecond) {
-    seconds = InSeconds();
-    microseconds -= seconds * Time::kMicrosecondsPerSecond;
-  }
-  struct timespec result =
-      {seconds,
-       microseconds * Time::kNanosecondsPerMicrosecond};
-  return result;
-}
-
 struct timeval Time::ToTimeVal() const {
   struct timeval result;
   int64 us = us_ - kTimeTToMicrosecondsOffset;
diff --git a/base/time_win.cc b/base/time_win.cc
index ca3aef1..601211c 100644
--- a/base/time_win.cc
+++ b/base/time_win.cc
@@ -41,10 +41,10 @@
 #include <mmsystem.h>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/cpu.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -262,7 +262,7 @@
 // easy to use a Singleton without even knowing it, and that may lead to many
 // gotchas). Its impact on startup time should be negligible due to low-level
 // nature of time code.
-Lock rollover_lock;
+base::Lock rollover_lock;
 
 // We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
 // because it returns the number of milliseconds since Windows has started,
@@ -270,7 +270,7 @@
 // rollover ourselves, which works if TimeTicks::Now() is called at least every
 // 49 days.
 TimeDelta RolloverProtectedNow() {
-  AutoLock locked(rollover_lock);
+  base::AutoLock locked(rollover_lock);
   // We should hold the lock while calling tick_function to make sure that
   // we keep last_seen_now stay correctly in sync.
   DWORD now = tick_function();
@@ -409,4 +409,4 @@
 // static
 bool TimeTicks::IsHighResClockWorking() {
   return HighResNowSingleton::GetInstance()->IsUsingHighResClock();
-}
\ No newline at end of file
+}
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc
index 3646000..a9f81b1 100644
--- a/base/tracked_objects.cc
+++ b/base/tracked_objects.cc
@@ -85,7 +85,7 @@
 // static
 ThreadData* ThreadData::first_ = NULL;
 // static
-Lock ThreadData::list_lock_;
+base::Lock ThreadData::list_lock_;
 
 // static
 ThreadData::Status ThreadData::status_ = ThreadData::UNINITIALIZED;
@@ -111,7 +111,7 @@
     bool too_late_to_create = false;
     {
       registry = new ThreadData;
-      AutoLock lock(list_lock_);
+      base::AutoLock lock(list_lock_);
       // Use lock to insure we have most recent status.
       if (!IsActive()) {
         too_late_to_create = true;
@@ -285,7 +285,7 @@
   Births* tracker = new Births(location);
   // Lock since the map may get relocated now, and other threads sometimes
   // snapshot it (but they lock before copying it).
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   birth_map_[location] = tracker;
   return tracker;
 }
@@ -305,13 +305,13 @@
     return;
   }
 
-  AutoLock lock(lock_);  // Lock since the map may get relocated now.
+  base::AutoLock lock(lock_);  // Lock since the map may get relocated now.
   death_map_[&lifetimes].RecordDeath(duration);
 }
 
 // static
 ThreadData* ThreadData::first() {
-  AutoLock lock(list_lock_);
+  base::AutoLock lock(list_lock_);
   return first_;
 }
 
@@ -323,7 +323,7 @@
 
 // This may be called from another thread.
 void ThreadData::SnapshotBirthMap(BirthMap *output) const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   for (BirthMap::const_iterator it = birth_map_.begin();
        it != birth_map_.end(); ++it)
     (*output)[it->first] = it->second;
@@ -331,7 +331,7 @@
 
 // This may be called from another thread.
 void ThreadData::SnapshotDeathMap(DeathMap *output) const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   for (DeathMap::const_iterator it = death_map_.begin();
        it != death_map_.end(); ++it)
     (*output)[it->first] = it->second;
@@ -348,7 +348,7 @@
 }
 
 void ThreadData::Reset() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   for (DeathMap::iterator it = death_map_.begin();
        it != death_map_.end(); ++it)
     it->second.Clear();
@@ -372,7 +372,7 @@
 
  private:
   size_t remaining_count_;
-  Lock lock_;  // protect access to remaining_count_.
+  base::Lock lock_;  // protect access to remaining_count_.
 };
 
 ThreadData::ThreadSafeDownCounter::ThreadSafeDownCounter(size_t count)
@@ -382,7 +382,7 @@
 
 bool ThreadData::ThreadSafeDownCounter::LastCaller() {
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     if (--remaining_count_)
       return false;
   }  // Release lock, so we can delete everything in this instance.
@@ -461,12 +461,12 @@
 #endif
 
   if (!status) {
-    AutoLock lock(list_lock_);
+    base::AutoLock lock(list_lock_);
     DCHECK(status_ == ACTIVE || status_ == SHUTDOWN);
     status_ = SHUTDOWN;
     return true;
   }
-  AutoLock lock(list_lock_);
+  base::AutoLock lock(list_lock_);
   DCHECK(status_ == UNINITIALIZED);
   CHECK(tls_index_.Initialize(NULL));
   status_ = ACTIVE;
@@ -504,7 +504,7 @@
     return;
   ThreadData* thread_data_list;
   {
-    AutoLock lock(list_lock_);
+    base::AutoLock lock(list_lock_);
     thread_data_list = first_;
     first_ = NULL;
   }
@@ -614,7 +614,7 @@
   thread_data.SnapshotDeathMap(&death_map);
 
   // Use our lock to protect our accumulation activity.
-  AutoLock lock(accumulation_lock_);
+  base::AutoLock lock(accumulation_lock_);
 
   DCHECK(count_of_contributing_threads_);
 
@@ -743,11 +743,6 @@
   selector_ = NIL;
 }
 
-void Comparator::Sort(DataCollector::Collection* collection) const {
-  std::sort(collection->begin(), collection->end(), *this);
-}
-
-
 bool Comparator::operator()(const Snapshot& left,
                             const Snapshot& right) const {
   switch (selector_) {
@@ -816,6 +811,10 @@
   return false;
 }
 
+void Comparator::Sort(DataCollector::Collection* collection) const {
+  std::sort(collection->begin(), collection->end(), *this);
+}
+
 bool Comparator::Equivalent(const Snapshot& left,
                             const Snapshot& right) const {
   switch (selector_) {
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 07731ff..ed629c3 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/tracked.h"
 #include "base/threading/thread_local_storage.h"
 
@@ -322,7 +322,7 @@
   // seen a death count.
   BirthCount global_birth_count_;
 
-  Lock accumulation_lock_;  // Protects access during accumulation phase.
+  base::Lock accumulation_lock_;  // Protects access during accumulation phase.
 
   DISALLOW_COPY_AND_ASSIGN(DataCollector);
 };
@@ -577,7 +577,7 @@
   // Link to the most recently created instance (starts a null terminated list).
   static ThreadData* first_;
   // Protection for access to first_.
-  static Lock list_lock_;
+  static base::Lock list_lock_;
 
   // We set status_ to SHUTDOWN when we shut down the tracking service. This
   // setting is redundantly established by all participating threads so that we
@@ -613,7 +613,7 @@
   // thread, or reading from another thread.  For reading from this thread we
   // don't need a lock, as there is no potential for a conflict since the
   // writing is only done from this thread.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   DISALLOW_COPY_AND_ASSIGN(ThreadData);
 };
diff --git a/base/tuple.h b/base/tuple.h
index 6b0d336..13d8722 100644
--- a/base/tuple.h
+++ b/base/tuple.h
@@ -548,13 +548,6 @@
 
 template <class ObjT, class Method, class A>
 inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1<A>& arg) {
-
-#if defined(OS_CHROMEOS)
-  // To troubleshoot crosbug.com/7327.
-  CHECK(obj);
-  CHECK(&arg);
-  CHECK(method);
-#endif
   (obj->*method)(arg.a);
 }
 
diff --git a/base/utf_string_conversions.cc b/base/utf_string_conversions.cc
index 41a70db..7b73696 100644
--- a/base/utf_string_conversions.cc
+++ b/base/utf_string_conversions.cc
@@ -133,7 +133,7 @@
   return ConvertUnicode(src, src_len, output);
 }
 
-string16 UTF8ToUTF16(const std::string& utf8) {
+string16 UTF8ToUTF16(const base::StringPiece& utf8) {
   string16 ret;
   // Ignore the success flag of this call, it will do the best it can for
   // invalid input, which is what we want here.
@@ -161,7 +161,7 @@
   return UTF8ToWide(src, src_len, output);
 }
 
-string16 UTF8ToUTF16(const std::string& utf8) {
+string16 UTF8ToUTF16(const base::StringPiece& utf8) {
   return UTF8ToWide(utf8);
 }
 
@@ -175,22 +175,12 @@
 
 #endif
 
-std::wstring ASCIIToWide(const char* ascii) {
-  DCHECK(IsStringASCII(ascii)) << ascii;
-  return std::wstring(ascii, &ascii[strlen(ascii)]);
-}
-
-std::wstring ASCIIToWide(const std::string& ascii) {
+std::wstring ASCIIToWide(const base::StringPiece& ascii) {
   DCHECK(IsStringASCII(ascii)) << ascii;
   return std::wstring(ascii.begin(), ascii.end());
 }
 
-string16 ASCIIToUTF16(const char* ascii) {
-  DCHECK(IsStringASCII(ascii)) << ascii;
-  return string16(ascii, &ascii[strlen(ascii)]);
-}
-
-string16 ASCIIToUTF16(const std::string& ascii) {
+string16 ASCIIToUTF16(const base::StringPiece& ascii) {
   DCHECK(IsStringASCII(ascii)) << ascii;
   return string16(ascii.begin(), ascii.end());
 }
diff --git a/base/utf_string_conversions.h b/base/utf_string_conversions.h
index 6c49b41..4aa4d41 100644
--- a/base/utf_string_conversions.h
+++ b/base/utf_string_conversions.h
@@ -9,10 +9,7 @@
 #include <string>
 
 #include "base/string16.h"
-
-namespace base {
-class StringPiece;
-}
+#include "base/string_piece.h"
 
 // These convert between UTF-8, -16, and -32 strings. They are potentially slow,
 // so avoid unnecessary conversions. The low-level versions return a boolean
@@ -31,7 +28,7 @@
 std::wstring UTF16ToWide(const string16& utf16);
 
 bool UTF8ToUTF16(const char* src, size_t src_len, string16* output);
-string16 UTF8ToUTF16(const std::string& utf8);
+string16 UTF8ToUTF16(const base::StringPiece& utf8);
 bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output);
 std::string UTF16ToUTF8(const string16& utf16);
 
@@ -50,16 +47,7 @@
 
 // These convert an ASCII string, typically a hardcoded constant, to a
 // UTF16/Wide string.
-//
-// Note that this doesn't use StringPiece because it's very common to need
-// ASCIIToUTF16("foo"), and either we have to include it in this file, or
-// forward declare it and force all callers to include string_piece.h. Given
-// that string_piece brings in complicated stuff like <algorithm>, it's
-// easier to just duplicate these very simple definitions for the two calling
-// cases we actually use.
-std::wstring ASCIIToWide(const char* ascii);
-std::wstring ASCIIToWide(const std::string& ascii);
-string16 ASCIIToUTF16(const char* ascii);
-string16 ASCIIToUTF16(const std::string& ascii);
+std::wstring ASCIIToWide(const base::StringPiece& ascii);
+string16 ASCIIToUTF16(const base::StringPiece& ascii);
 
 #endif  // BASE_UTF_STRING_CONVERSIONS_H_
diff --git a/base/values.cc b/base/values.cc
index 3522569..9c96f26 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -70,27 +70,27 @@
 }
 
 // static
-Value* Value::CreateBooleanValue(bool in_value) {
+FundamentalValue* Value::CreateBooleanValue(bool in_value) {
   return new FundamentalValue(in_value);
 }
 
 // static
-Value* Value::CreateIntegerValue(int in_value) {
+FundamentalValue* Value::CreateIntegerValue(int in_value) {
   return new FundamentalValue(in_value);
 }
 
 // static
-Value* Value::CreateRealValue(double in_value) {
+FundamentalValue* Value::CreateDoubleValue(double in_value) {
   return new FundamentalValue(in_value);
 }
 
 // static
-Value* Value::CreateStringValue(const std::string& in_value) {
+StringValue* Value::CreateStringValue(const std::string& in_value) {
   return new StringValue(in_value);
 }
 
 // static
-Value* Value::CreateStringValue(const string16& in_value) {
+StringValue* Value::CreateStringValue(const string16& in_value) {
   return new StringValue(in_value);
 }
 
@@ -107,7 +107,7 @@
   return false;
 }
 
-bool Value::GetAsReal(double* out_value) const {
+bool Value::GetAsDouble(double* out_value) const {
   return false;
 }
 
@@ -158,7 +158,7 @@
 }
 
 FundamentalValue::FundamentalValue(double in_value)
-    : Value(TYPE_REAL), real_value_(in_value) {
+    : Value(TYPE_DOUBLE), double_value_(in_value) {
 }
 
 FundamentalValue::~FundamentalValue() {
@@ -176,13 +176,13 @@
   return (IsType(TYPE_INTEGER));
 }
 
-bool FundamentalValue::GetAsReal(double* out_value) const {
-  if (out_value && IsType(TYPE_REAL))
-    *out_value = real_value_;
-  return (IsType(TYPE_REAL));
+bool FundamentalValue::GetAsDouble(double* out_value) const {
+  if (out_value && IsType(TYPE_DOUBLE))
+    *out_value = double_value_;
+  return (IsType(TYPE_DOUBLE));
 }
 
-Value* FundamentalValue::DeepCopy() const {
+FundamentalValue* FundamentalValue::DeepCopy() const {
   switch (GetType()) {
     case TYPE_BOOLEAN:
       return CreateBooleanValue(boolean_value_);
@@ -190,8 +190,8 @@
     case TYPE_INTEGER:
       return CreateIntegerValue(integer_value_);
 
-    case TYPE_REAL:
-      return CreateRealValue(real_value_);
+    case TYPE_DOUBLE:
+      return CreateDoubleValue(double_value_);
 
     default:
       NOTREACHED();
@@ -212,9 +212,9 @@
       int lhs, rhs;
       return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs;
     }
-    case TYPE_REAL: {
+    case TYPE_DOUBLE: {
       double lhs, rhs;
-      return GetAsReal(&lhs) && other->GetAsReal(&rhs) && lhs == rhs;
+      return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs;
     }
     default:
       NOTREACHED();
@@ -250,7 +250,7 @@
   return true;
 }
 
-Value* StringValue::DeepCopy() const {
+StringValue* StringValue::DeepCopy() const {
   return CreateStringValue(value_);
 }
 
@@ -288,7 +288,7 @@
   return new BinaryValue(buffer_copy, size);
 }
 
-Value* BinaryValue::DeepCopy() const {
+BinaryValue* BinaryValue::DeepCopy() const {
   return CreateWithCopiedBuffer(buffer_, size_);
 }
 
@@ -367,8 +367,8 @@
   Set(path, CreateIntegerValue(in_value));
 }
 
-void DictionaryValue::SetReal(const std::string& path, double in_value) {
-  Set(path, CreateRealValue(in_value));
+void DictionaryValue::SetDouble(const std::string& path, double in_value) {
+  Set(path, CreateDoubleValue(in_value));
 }
 
 void DictionaryValue::SetString(const std::string& path,
@@ -430,13 +430,13 @@
   return value->GetAsInteger(out_value);
 }
 
-bool DictionaryValue::GetReal(const std::string& path,
-                              double* out_value) const {
+bool DictionaryValue::GetDouble(const std::string& path,
+                                double* out_value) const {
   Value* value;
   if (!Get(path, &value))
     return false;
 
-  return value->GetAsReal(out_value);
+  return value->GetAsDouble(out_value);
 }
 
 bool DictionaryValue::GetString(const std::string& path,
@@ -533,13 +533,13 @@
   return value->GetAsInteger(out_value);
 }
 
-bool DictionaryValue::GetRealWithoutPathExpansion(const std::string& key,
-                                                  double* out_value) const {
+bool DictionaryValue::GetDoubleWithoutPathExpansion(const std::string& key,
+                                                    double* out_value) const {
   Value* value;
   if (!GetWithoutPathExpansion(key, &value))
     return false;
 
-  return value->GetAsReal(out_value);
+  return value->GetAsDouble(out_value);
 }
 
 bool DictionaryValue::GetStringWithoutPathExpansion(
@@ -646,7 +646,7 @@
   }
 }
 
-Value* DictionaryValue::DeepCopy() const {
+DictionaryValue* DictionaryValue::DeepCopy() const {
   DictionaryValue* result = new DictionaryValue;
 
   for (ValueMap::const_iterator current_entry(dictionary_.begin());
@@ -742,12 +742,12 @@
   return value->GetAsInteger(out_value);
 }
 
-bool ListValue::GetReal(size_t index, double* out_value) const {
+bool ListValue::GetDouble(size_t index, double* out_value) const {
   Value* value;
   if (!Get(index, &value))
     return false;
 
-  return value->GetAsReal(out_value);
+  return value->GetAsDouble(out_value);
 }
 
 bool ListValue::GetString(size_t index, std::string* out_value) const {
@@ -862,7 +862,7 @@
   return true;
 }
 
-Value* ListValue::DeepCopy() const {
+ListValue* ListValue::DeepCopy() const {
   ListValue* result = new ListValue;
 
   for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
diff --git a/base/values.h b/base/values.h
index d69a685..408ca8b 100644
--- a/base/values.h
+++ b/base/values.h
@@ -50,7 +50,7 @@
     TYPE_NULL = 0,
     TYPE_BOOLEAN,
     TYPE_INTEGER,
-    TYPE_REAL,
+    TYPE_DOUBLE,
     TYPE_STRING,
     TYPE_BINARY,
     TYPE_DICTIONARY,
@@ -63,11 +63,11 @@
   // kinds of values without thinking about which class implements them.
   // These can always be expected to return a valid Value*.
   static Value* CreateNullValue();
-  static Value* CreateBooleanValue(bool in_value);
-  static Value* CreateIntegerValue(int in_value);
-  static Value* CreateRealValue(double in_value);
-  static Value* CreateStringValue(const std::string& in_value);
-  static Value* CreateStringValue(const string16& in_value);
+  static FundamentalValue* CreateBooleanValue(bool in_value);
+  static FundamentalValue* CreateIntegerValue(int in_value);
+  static FundamentalValue* CreateDoubleValue(double in_value);
+  static StringValue* CreateStringValue(const std::string& in_value);
+  static StringValue* CreateStringValue(const string16& in_value);
 
   // This one can return NULL if the input isn't valid.  If the return value
   // is non-null, the new object has taken ownership of the buffer pointer.
@@ -89,13 +89,16 @@
   // returned;  otherwise, false is returned and |out_value| is unchanged.
   virtual bool GetAsBoolean(bool* out_value) const;
   virtual bool GetAsInteger(int* out_value) const;
-  virtual bool GetAsReal(double* out_value) const;
+  virtual bool GetAsDouble(double* out_value) const;
   virtual bool GetAsString(std::string* out_value) const;
   virtual bool GetAsString(string16* out_value) const;
   virtual bool GetAsList(ListValue** out_value);
 
   // This creates a deep copy of the entire Value tree, and returns a pointer
   // to the copy.  The caller gets ownership of the copy, of course.
+  //
+  // Subclasses return their own type directly in their overrides;
+  // this works because C++ supports covariant return types.
   virtual Value* DeepCopy() const;
 
   // Compares if two Value objects have equal contents.
@@ -129,15 +132,15 @@
   // Subclassed methods
   virtual bool GetAsBoolean(bool* out_value) const;
   virtual bool GetAsInteger(int* out_value) const;
-  virtual bool GetAsReal(double* out_value) const;
-  virtual Value* DeepCopy() const;
+  virtual bool GetAsDouble(double* out_value) const;
+  virtual FundamentalValue* DeepCopy() const;
   virtual bool Equals(const Value* other) const;
 
  private:
   union {
     bool boolean_value_;
     int integer_value_;
-    double real_value_;
+    double double_value_;
   };
 
   DISALLOW_COPY_AND_ASSIGN(FundamentalValue);
@@ -156,7 +159,7 @@
   // Subclassed methods
   virtual bool GetAsString(std::string* out_value) const;
   virtual bool GetAsString(string16* out_value) const;
-  virtual Value* DeepCopy() const;
+  virtual StringValue* DeepCopy() const;
   virtual bool Equals(const Value* other) const;
 
  private:
@@ -185,7 +188,7 @@
   const char* GetBuffer() const { return buffer_; }
 
   // Overridden from Value:
-  virtual Value* DeepCopy() const;
+  virtual BinaryValue* DeepCopy() const;
   virtual bool Equals(const Value* other) const;
 
  private:
@@ -234,7 +237,7 @@
   // value at that path, even if it has a different type.
   void SetBoolean(const std::string& path, bool in_value);
   void SetInteger(const std::string& path, int in_value);
-  void SetReal(const std::string& path, double in_value);
+  void SetDouble(const std::string& path, double in_value);
   void SetString(const std::string& path, const std::string& in_value);
   void SetString(const std::string& path, const string16& in_value);
 
@@ -256,7 +259,7 @@
   // the end of the path can be returned in the form specified.
   bool GetBoolean(const std::string& path, bool* out_value) const;
   bool GetInteger(const std::string& path, int* out_value) const;
-  bool GetReal(const std::string& path, double* out_value) const;
+  bool GetDouble(const std::string& path, double* out_value) const;
   bool GetString(const std::string& path, std::string* out_value) const;
   bool GetString(const std::string& path, string16* out_value) const;
   bool GetStringASCII(const std::string& path, std::string* out_value) const;
@@ -271,7 +274,7 @@
                                Value** out_value) const;
   bool GetIntegerWithoutPathExpansion(const std::string& key,
                                       int* out_value) const;
-  bool GetRealWithoutPathExpansion(const std::string& key,
+  bool GetDoubleWithoutPathExpansion(const std::string& key,
                                    double* out_value) const;
   bool GetStringWithoutPathExpansion(const std::string& key,
                                      std::string* out_value) const;
@@ -330,7 +333,7 @@
   key_iterator end_keys() const { return key_iterator(dictionary_.end()); }
 
   // Overridden from Value:
-  virtual Value* DeepCopy() const;
+  virtual DictionaryValue* DeepCopy() const;
   virtual bool Equals(const Value* other) const;
 
  private:
@@ -374,7 +377,7 @@
   // in the specified form.
   bool GetBoolean(size_t index, bool* out_value) const;
   bool GetInteger(size_t index, int* out_value) const;
-  bool GetReal(size_t index, double* out_value) const;
+  bool GetDouble(size_t index, double* out_value) const;
   bool GetString(size_t index, std::string* out_value) const;
   bool GetString(size_t index, string16* out_value) const;
   bool GetBinary(size_t index, BinaryValue** out_value) const;
@@ -417,7 +420,7 @@
 
   // Overridden from Value:
   virtual bool GetAsList(ListValue** out_value);
-  virtual Value* DeepCopy() const;
+  virtual ListValue* DeepCopy() const;
   virtual bool Equals(const Value* other) const;
 
  private:
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index adcd07e..5f901b5 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -60,7 +60,7 @@
   scoped_ptr<ListValue> mixed_list(new ListValue());
   mixed_list->Set(0, Value::CreateBooleanValue(true));
   mixed_list->Set(1, Value::CreateIntegerValue(42));
-  mixed_list->Set(2, Value::CreateRealValue(88.8));
+  mixed_list->Set(2, Value::CreateDoubleValue(88.8));
   mixed_list->Set(3, Value::CreateStringValue("foo"));
   ASSERT_EQ(4u, mixed_list->GetSize());
 
@@ -74,7 +74,7 @@
 
   ASSERT_FALSE(mixed_list->GetInteger(0, &int_value));
   ASSERT_EQ(0, int_value);
-  ASSERT_FALSE(mixed_list->GetReal(1, &double_value));
+  ASSERT_FALSE(mixed_list->GetDouble(1, &double_value));
   ASSERT_EQ(0.0, double_value);
   ASSERT_FALSE(mixed_list->GetString(2, &string_value));
   ASSERT_EQ("", string_value);
@@ -85,7 +85,7 @@
   ASSERT_TRUE(bool_value);
   ASSERT_TRUE(mixed_list->GetInteger(1, &int_value));
   ASSERT_EQ(42, int_value);
-  ASSERT_TRUE(mixed_list->GetReal(2, &double_value));
+  ASSERT_TRUE(mixed_list->GetDouble(2, &double_value));
   ASSERT_EQ(88.8, double_value);
   ASSERT_TRUE(mixed_list->GetString(3, &string_value));
   ASSERT_EQ("foo", string_value);
@@ -323,15 +323,16 @@
   DictionaryValue original_dict;
   Value* original_null = Value::CreateNullValue();
   original_dict.Set("null", original_null);
-  Value* original_bool = Value::CreateBooleanValue(true);
+  FundamentalValue* original_bool = Value::CreateBooleanValue(true);
   original_dict.Set("bool", original_bool);
-  Value* original_int = Value::CreateIntegerValue(42);
+  FundamentalValue* original_int = Value::CreateIntegerValue(42);
   original_dict.Set("int", original_int);
-  Value* original_real = Value::CreateRealValue(3.14);
-  original_dict.Set("real", original_real);
-  Value* original_string = Value::CreateStringValue("hello");
+  FundamentalValue* original_double = Value::CreateDoubleValue(3.14);
+  original_dict.Set("double", original_double);
+  StringValue* original_string = Value::CreateStringValue("hello");
   original_dict.Set("string", original_string);
-  Value* original_string16 = Value::CreateStringValue(ASCIIToUTF16("hello16"));
+  StringValue* original_string16 =
+      Value::CreateStringValue(ASCIIToUTF16("hello16"));
   original_dict.Set("string16", original_string16);
 
   char* original_buffer = new char[42];
@@ -340,14 +341,13 @@
   original_dict.Set("binary", original_binary);
 
   ListValue* original_list = new ListValue();
-  Value* original_list_element_0 = Value::CreateIntegerValue(0);
+  FundamentalValue* original_list_element_0 = Value::CreateIntegerValue(0);
   original_list->Append(original_list_element_0);
-  Value* original_list_element_1 = Value::CreateIntegerValue(1);
+  FundamentalValue* original_list_element_1 = Value::CreateIntegerValue(1);
   original_list->Append(original_list_element_1);
   original_dict.Set("list", original_list);
 
-  scoped_ptr<DictionaryValue> copy_dict(
-      static_cast<DictionaryValue*>(original_dict.DeepCopy()));
+  scoped_ptr<DictionaryValue> copy_dict(original_dict.DeepCopy());
   ASSERT_TRUE(copy_dict.get());
   ASSERT_NE(copy_dict.get(), &original_dict);
 
@@ -375,14 +375,14 @@
   ASSERT_TRUE(copy_int->GetAsInteger(&copy_int_value));
   ASSERT_EQ(42, copy_int_value);
 
-  Value* copy_real = NULL;
-  ASSERT_TRUE(copy_dict->Get("real", &copy_real));
-  ASSERT_TRUE(copy_real);
-  ASSERT_NE(copy_real, original_real);
-  ASSERT_TRUE(copy_real->IsType(Value::TYPE_REAL));
-  double copy_real_value = 0;
-  ASSERT_TRUE(copy_real->GetAsReal(&copy_real_value));
-  ASSERT_EQ(3.14, copy_real_value);
+  Value* copy_double = NULL;
+  ASSERT_TRUE(copy_dict->Get("double", &copy_double));
+  ASSERT_TRUE(copy_double);
+  ASSERT_NE(copy_double, original_double);
+  ASSERT_TRUE(copy_double->IsType(Value::TYPE_DOUBLE));
+  double copy_double_value = 0;
+  ASSERT_TRUE(copy_double->GetAsDouble(&copy_double_value));
+  ASSERT_EQ(3.14, copy_double_value);
 
   Value* copy_string = NULL;
   ASSERT_TRUE(copy_dict->Get("string", &copy_string));
@@ -459,13 +459,13 @@
   DictionaryValue dv;
   dv.SetBoolean("a", false);
   dv.SetInteger("b", 2);
-  dv.SetReal("c", 2.5);
+  dv.SetDouble("c", 2.5);
   dv.SetString("d1", "string");
   dv.SetString("d2", ASCIIToUTF16("http://google.com"));
   dv.Set("e", Value::CreateNullValue());
 
   scoped_ptr<DictionaryValue> copy;
-  copy.reset(static_cast<DictionaryValue*>(dv.DeepCopy()));
+  copy.reset(dv.DeepCopy());
   EXPECT_TRUE(dv.Equals(copy.get()));
 
   ListValue* list = new ListValue;
@@ -481,7 +481,7 @@
   EXPECT_FALSE(dv.Equals(copy.get()));
 
   // Check if Equals detects differences in only the keys.
-  copy.reset(static_cast<DictionaryValue*>(dv.DeepCopy()));
+  copy.reset(dv.DeepCopy());
   EXPECT_TRUE(dv.Equals(copy.get()));
   copy->Remove("a", NULL);
   copy->SetBoolean("aa", false);
@@ -511,6 +511,62 @@
   EXPECT_FALSE(Value::Equals(NULL, null1.get()));
 }
 
+TEST_F(ValuesTest, DeepCopyCovariantReturnTypes) {
+  DictionaryValue original_dict;
+  Value* original_null = Value::CreateNullValue();
+  original_dict.Set("null", original_null);
+  FundamentalValue* original_bool = Value::CreateBooleanValue(true);
+  original_dict.Set("bool", original_bool);
+  FundamentalValue* original_int = Value::CreateIntegerValue(42);
+  original_dict.Set("int", original_int);
+  FundamentalValue* original_double = Value::CreateDoubleValue(3.14);
+  original_dict.Set("double", original_double);
+  StringValue* original_string = Value::CreateStringValue("hello");
+  original_dict.Set("string", original_string);
+  StringValue* original_string16 =
+      Value::CreateStringValue(ASCIIToUTF16("hello16"));
+  original_dict.Set("string16", original_string16);
+
+  char* original_buffer = new char[42];
+  memset(original_buffer, '!', 42);
+  BinaryValue* original_binary = Value::CreateBinaryValue(original_buffer, 42);
+  original_dict.Set("binary", original_binary);
+
+  ListValue* original_list = new ListValue();
+  FundamentalValue* original_list_element_0 = Value::CreateIntegerValue(0);
+  original_list->Append(original_list_element_0);
+  FundamentalValue* original_list_element_1 = Value::CreateIntegerValue(1);
+  original_list->Append(original_list_element_1);
+  original_dict.Set("list", original_list);
+
+  Value* original_dict_value = &original_dict;
+  Value* original_bool_value = original_bool;
+  Value* original_int_value = original_int;
+  Value* original_double_value = original_double;
+  Value* original_string_value = original_string;
+  Value* original_string16_value = original_string16;
+  Value* original_binary_value = original_binary;
+  Value* original_list_value = original_list;
+
+  scoped_ptr<Value> copy_dict_value(original_dict_value->DeepCopy());
+  scoped_ptr<Value> copy_bool_value(original_bool_value->DeepCopy());
+  scoped_ptr<Value> copy_int_value(original_int_value->DeepCopy());
+  scoped_ptr<Value> copy_double_value(original_double_value->DeepCopy());
+  scoped_ptr<Value> copy_string_value(original_string_value->DeepCopy());
+  scoped_ptr<Value> copy_string16_value(original_string16_value->DeepCopy());
+  scoped_ptr<Value> copy_binary_value(original_binary_value->DeepCopy());
+  scoped_ptr<Value> copy_list_value(original_list_value->DeepCopy());
+
+  EXPECT_TRUE(original_dict_value->Equals(copy_dict_value.get()));
+  EXPECT_TRUE(original_bool_value->Equals(copy_bool_value.get()));
+  EXPECT_TRUE(original_int_value->Equals(copy_int_value.get()));
+  EXPECT_TRUE(original_double_value->Equals(copy_double_value.get()));
+  EXPECT_TRUE(original_string_value->Equals(copy_string_value.get()));
+  EXPECT_TRUE(original_string16_value->Equals(copy_string16_value.get()));
+  EXPECT_TRUE(original_binary_value->Equals(copy_binary_value.get()));
+  EXPECT_TRUE(original_list_value->Equals(copy_list_value.get()));
+}
+
 TEST_F(ValuesTest, RemoveEmptyChildren) {
   scoped_ptr<DictionaryValue> root(new DictionaryValue);
   // Remove empty lists and dictionaries.
diff --git a/base/values_util.cc b/base/values_util.cc
deleted file mode 100644
index fbc616b..0000000
--- a/base/values_util.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/values_util.h"
-
-RefCountedList::RefCountedList(ListValue* list) {
-  list_ = list;
-}
-
-RefCountedList::~RefCountedList() {
-  if (list_)
-    delete list_;
-}
-
-ListValue* RefCountedList::Get() {
-  return list_;
-}
diff --git a/base/values_util.h b/base/values_util.h
deleted file mode 100644
index 1626bb5..0000000
--- a/base/values_util.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_VALUES_UTIL_H_
-#define BASE_VALUES_UTIL_H_
-#pragma once
-
-#include "base/values.h"
-#include "base/ref_counted.h"
-
-class RefCountedList : public base::RefCountedThreadSafe<RefCountedList> {
- public:
-  // Takes ownership of |list|.
-  explicit RefCountedList(ListValue* list);
-  virtual ~RefCountedList();
-
-  virtual ListValue* Get();
-
- private:
-  ListValue* list_;
-
-  DISALLOW_COPY_AND_ASSIGN(RefCountedList);
-};
-
-#endif  // BASE_VALUES_UTIL_H_
diff --git a/base/vlog.cc b/base/vlog.cc
index 8903f39..41bf2a5 100644
--- a/base/vlog.cc
+++ b/base/vlog.cc
@@ -13,6 +13,18 @@
 
 const int VlogInfo::kDefaultVlogLevel = 0;
 
+struct VlogInfo::VmodulePattern {
+  enum MatchTarget { MATCH_MODULE, MATCH_FILE };
+
+  explicit VmodulePattern(const std::string& pattern);
+
+  VmodulePattern();
+
+  std::string pattern;
+  int vlog_level;
+  MatchTarget match_target;
+};
+
 VlogInfo::VmodulePattern::VmodulePattern(const std::string& pattern)
     : pattern(pattern),
       vlog_level(VlogInfo::kDefaultVlogLevel),
@@ -64,15 +76,6 @@
 
 VlogInfo::~VlogInfo() {}
 
-void VlogInfo::SetMaxVlogLevel(int level) {
-  // Log severity is the negative verbosity.
-  *min_log_level_ = -level;
-}
-
-int VlogInfo::GetMaxVlogLevel() const {
-  return -*min_log_level_;
-}
-
 namespace {
 
 // Given a path, returns the basename with the extension chopped off
@@ -109,6 +112,15 @@
   return GetMaxVlogLevel();
 }
 
+void VlogInfo::SetMaxVlogLevel(int level) {
+  // Log severity is the negative verbosity.
+  *min_log_level_ = -level;
+}
+
+int VlogInfo::GetMaxVlogLevel() const {
+  return -*min_log_level_;
+}
+
 bool MatchVlogPattern(const base::StringPiece& string,
                       const base::StringPiece& vlog_pattern) {
   base::StringPiece p(vlog_pattern);
diff --git a/base/vlog.h b/base/vlog.h
index 529afd5..54e777f 100644
--- a/base/vlog.h
+++ b/base/vlog.h
@@ -18,6 +18,8 @@
 // A helper class containing all the settings for vlogging.
 class VlogInfo {
  public:
+  static const int kDefaultVlogLevel;
+
   // |v_switch| gives the default maximal active V-logging level; 0 is
   // the default.  Normally positive values are used for V-logging
   // levels.
@@ -45,26 +47,13 @@
   // __FILE__).
   int GetVlogLevel(const base::StringPiece& file) const;
 
-  static const int kDefaultVlogLevel;
-
  private:
   void SetMaxVlogLevel(int level);
   int GetMaxVlogLevel() const;
 
   // VmodulePattern holds all the information for each pattern parsed
   // from |vmodule_switch|.
-  struct VmodulePattern {
-    enum MatchTarget { MATCH_MODULE, MATCH_FILE };
-
-    explicit VmodulePattern(const std::string& pattern);
-
-    VmodulePattern();
-
-    std::string pattern;
-    int vlog_level;
-    MatchTarget match_target;
-  };
-
+  struct VmodulePattern;
   std::vector<VmodulePattern> vmodule_levels_;
   int* min_log_level_;
 
diff --git a/base/weak_ptr.cc b/base/weak_ptr.cc
index 6473b4a..86c89c1 100644
--- a/base/weak_ptr.cc
+++ b/base/weak_ptr.cc
@@ -61,10 +61,10 @@
 WeakPtrBase::WeakPtrBase() {
 }
 
-WeakPtrBase::WeakPtrBase(const WeakReference& ref) : ref_(ref) {
+WeakPtrBase::~WeakPtrBase() {
 }
 
-WeakPtrBase::~WeakPtrBase() {
+WeakPtrBase::WeakPtrBase(const WeakReference& ref) : ref_(ref) {
 }
 
 }  // namespace internal
diff --git a/base/win/registry.cc b/base/win/registry.cc
index dbb8d7a..d105a4c 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,6 +14,268 @@
 namespace base {
 namespace win {
 
+// RegKey ----------------------------------------------------------------------
+
+RegKey::RegKey()
+    : key_(NULL),
+      watch_event_(0) {
+}
+
+RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
+    : key_(NULL),
+      watch_event_(0) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  if (rootkey) {
+    if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
+      Create(rootkey, subkey, access);
+    else
+      Open(rootkey, subkey, access);
+  } else {
+    DCHECK(!subkey);
+  }
+}
+
+RegKey::~RegKey() {
+  Close();
+}
+
+LONG RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
+  DWORD disposition_value;
+  return CreateWithDisposition(rootkey, subkey, &disposition_value, access);
+}
+
+LONG RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey,
+                                   DWORD* disposition, REGSAM access) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(rootkey && subkey && access && disposition);
+  Close();
+
+  LONG result = RegCreateKeyEx(rootkey, subkey, 0, NULL,
+                               REG_OPTION_NON_VOLATILE, access, NULL, &key_,
+                               disposition);
+  return result;
+}
+
+LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(rootkey && subkey && access);
+  Close();
+
+  LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &key_);
+  return result;
+}
+
+LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(name && access);
+
+  HKEY subkey = NULL;
+  LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE,
+                               access, NULL, &subkey, NULL);
+  Close();
+
+  key_ = subkey;
+  return result;
+}
+
+LONG RegKey::OpenKey(const wchar_t* name, REGSAM access) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(name && access);
+
+  HKEY subkey = NULL;
+  LONG result = RegOpenKeyEx(key_, name, 0, access, &subkey);
+
+  Close();
+
+  key_ = subkey;
+  return result;
+}
+
+void RegKey::Close() {
+  base::ThreadRestrictions::AssertIOAllowed();
+  StopWatching();
+  if (key_) {
+    ::RegCloseKey(key_);
+    key_ = NULL;
+  }
+}
+
+DWORD RegKey::ValueCount() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DWORD count = 0;
+  LONG result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, &count,
+                                NULL, NULL, NULL, NULL);
+  return (result != ERROR_SUCCESS) ? 0 : count;
+}
+
+LONG RegKey::ReadName(int index, std::wstring* name) const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  wchar_t buf[256];
+  DWORD bufsize = arraysize(buf);
+  LONG r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, NULL, NULL);
+  if (r == ERROR_SUCCESS)
+    *name = buf;
+
+  return r;
+}
+
+LONG RegKey::DeleteKey(const wchar_t* name) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(key_);
+  DCHECK(name);
+  LONG result = SHDeleteKey(key_, name);
+  return result;
+}
+
+LONG RegKey::DeleteValue(const wchar_t* value_name) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(key_);
+  DCHECK(value_name);
+  LONG result = RegDeleteValue(key_, value_name);
+  return result;
+}
+
+bool RegKey::ValueExists(const wchar_t* name) const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  LONG result = RegQueryValueEx(key_, name, 0, NULL, NULL, NULL);
+  return result == ERROR_SUCCESS;
+}
+
+LONG RegKey::ReadValue(const wchar_t* name, void* data, DWORD* dsize,
+                       DWORD* dtype) const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  LONG result = RegQueryValueEx(key_, name, 0, dtype,
+                                reinterpret_cast<LPBYTE>(data), dsize);
+  return result;
+}
+
+LONG RegKey::ReadValue(const wchar_t* name, std::wstring* value) const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(value);
+  const size_t kMaxStringLength = 1024;  // This is after expansion.
+  // Use the one of the other forms of ReadValue if 1024 is too small for you.
+  wchar_t raw_value[kMaxStringLength];
+  DWORD type = REG_SZ, size = sizeof(raw_value);
+  LONG result = ReadValue(name, raw_value, &size, &type);
+  if (result == ERROR_SUCCESS) {
+    if (type == REG_SZ) {
+      *value = raw_value;
+    } else if (type == REG_EXPAND_SZ) {
+      wchar_t expanded[kMaxStringLength];
+      size = ExpandEnvironmentStrings(raw_value, expanded, kMaxStringLength);
+      // Success: returns the number of wchar_t's copied
+      // Fail: buffer too small, returns the size required
+      // Fail: other, returns 0
+      if (size == 0 || size > kMaxStringLength) {
+        result = ERROR_MORE_DATA;
+      } else {
+        *value = expanded;
+      }
+    } else {
+      // Not a string. Oops.
+      result = ERROR_CANTREAD;
+    }
+  }
+
+  return result;
+}
+
+LONG RegKey::ReadValueDW(const wchar_t* name, DWORD* value) const {
+  DCHECK(value);
+  DWORD type = REG_DWORD;
+  DWORD size = sizeof(DWORD);
+  DWORD local_value = 0;
+  LONG result = ReadValue(name, &local_value, &size, &type);
+  if (result == ERROR_SUCCESS) {
+    if ((type == REG_DWORD || type == REG_BINARY) && size == sizeof(DWORD)) {
+      *value = local_value;
+    } else {
+      result = ERROR_CANTREAD;
+    }
+  }
+
+  return result;
+}
+
+LONG RegKey::ReadInt64(const wchar_t* name, int64* value) const {
+  DCHECK(value);
+  DWORD type = REG_QWORD;
+  int64 local_value = 0;
+  DWORD size = sizeof(local_value);
+  LONG result = ReadValue(name, &local_value, &size, &type);
+  if (result == ERROR_SUCCESS) {
+    if ((type == REG_QWORD || type == REG_BINARY) &&
+        size == sizeof(local_value)) {
+      *value = local_value;
+    } else {
+      result = ERROR_CANTREAD;
+    }
+  }
+
+  return result;
+}
+
+LONG RegKey::WriteValue(const wchar_t* name, const void * data,
+                        DWORD dsize, DWORD dtype) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(data || !dsize);
+
+  LONG result = RegSetValueEx(key_, name, 0, dtype,
+      reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize);
+  return result;
+}
+
+LONG RegKey::WriteValue(const wchar_t * name, const wchar_t* value) {
+  return WriteValue(name, value,
+      static_cast<DWORD>(sizeof(*value) * (wcslen(value) + 1)), REG_SZ);
+}
+
+LONG RegKey::WriteValue(const wchar_t* name, DWORD value) {
+  return WriteValue(name, &value, static_cast<DWORD>(sizeof(value)), REG_DWORD);
+}
+
+LONG RegKey::StartWatching() {
+  DCHECK(key_);
+  if (!watch_event_)
+    watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+  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_, 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;
+}
+
+// RegistryValueIterator ------------------------------------------------------
+
 RegistryValueIterator::RegistryValueIterator(HKEY root_key,
                                              const wchar_t* folder_key) {
   base::ThreadRestrictions::AssertIOAllowed();
@@ -43,6 +305,17 @@
     ::RegCloseKey(key_);
 }
 
+DWORD RegistryValueIterator::ValueCount() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DWORD count = 0;
+  LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL,
+                                  &count, NULL, NULL, NULL, NULL);
+  if (result != ERROR_SUCCESS)
+    return 0;
+
+  return count;
+}
+
 bool RegistryValueIterator::Valid() const {
   return key_ != NULL && index_ >= 0;
 }
@@ -57,8 +330,8 @@
   if (Valid()) {
     DWORD ncount = arraysize(name_);
     value_size_ = sizeof(value_);
-    LRESULT r = ::RegEnumValue(key_, index_, name_, &ncount, NULL, &type_,
-                               reinterpret_cast<BYTE*>(value_), &value_size_);
+    LONG r = ::RegEnumValue(key_, index_, name_, &ncount, NULL, &type_,
+                            reinterpret_cast<BYTE*>(value_), &value_size_);
     if (ERROR_SUCCESS == r)
       return true;
   }
@@ -69,17 +342,7 @@
   return false;
 }
 
-DWORD RegistryValueIterator::ValueCount() const {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DWORD count = 0;
-  HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL,
-                                     &count, NULL, NULL, NULL, NULL);
-
-  if (result != ERROR_SUCCESS)
-    return 0;
-
-  return count;
-}
+// RegistryKeyIterator --------------------------------------------------------
 
 RegistryKeyIterator::RegistryKeyIterator(HKEY root_key,
                                          const wchar_t* folder_key) {
@@ -89,8 +352,8 @@
     key_ = NULL;
   } else {
     DWORD count = 0;
-    HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL);
+    LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
+                                    NULL, NULL, NULL, NULL, NULL);
 
     if (result != ERROR_SUCCESS) {
       ::RegCloseKey(key_);
@@ -109,6 +372,17 @@
     ::RegCloseKey(key_);
 }
 
+DWORD RegistryKeyIterator::SubkeyCount() const {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DWORD count = 0;
+  LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
+                                  NULL, NULL, NULL, NULL, NULL);
+  if (result != ERROR_SUCCESS)
+    return 0;
+
+  return count;
+}
+
 bool RegistryKeyIterator::Valid() const {
   return key_ != NULL && index_ >= 0;
 }
@@ -123,8 +397,8 @@
   if (Valid()) {
     DWORD ncount = arraysize(name_);
     FILETIME written;
-    LRESULT r = ::RegEnumKeyEx(key_, index_, name_, &ncount, NULL, NULL,
-                               NULL, &written);
+    LONG r = ::RegEnumKeyEx(key_, index_, name_, &ncount, NULL, NULL,
+                            NULL, &written);
     if (ERROR_SUCCESS == r)
       return true;
   }
@@ -133,284 +407,5 @@
   return false;
 }
 
-DWORD RegistryKeyIterator::SubkeyCount() const {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DWORD count = 0;
-  HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
-                                     NULL, NULL, NULL, NULL, NULL);
-
-  if (result != ERROR_SUCCESS)
-    return 0;
-
-  return count;
-}
-
-RegKey::RegKey()
-    : key_(NULL),
-      watch_event_(0) {
-}
-
-RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
-    : key_(NULL),
-      watch_event_(0) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (rootkey) {
-    if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
-      Create(rootkey, subkey, access);
-    else
-      Open(rootkey, subkey, access);
-  } else {
-    DCHECK(!subkey);
-  }
-}
-
-RegKey::~RegKey() {
-  Close();
-}
-
-void RegKey::Close() {
-  base::ThreadRestrictions::AssertIOAllowed();
-  StopWatching();
-  if (key_) {
-    ::RegCloseKey(key_);
-    key_ = NULL;
-  }
-}
-
-bool RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
-  DWORD disposition_value;
-  return CreateWithDisposition(rootkey, subkey, &disposition_value, access);
-}
-
-bool RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey,
-                                   DWORD* disposition, REGSAM access) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(rootkey && subkey && access && disposition);
-  Close();
-
-  LONG result = RegCreateKeyEx(rootkey,
-                               subkey,
-                               0,
-                               NULL,
-                               REG_OPTION_NON_VOLATILE,
-                               access,
-                               NULL,
-                               &key_,
-                               disposition);
-  if (result != ERROR_SUCCESS) {
-    key_ = NULL;
-    return false;
-  }
-
-  return true;
-}
-
-bool RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(rootkey && subkey && access);
-  Close();
-
-  LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &key_);
-  if (result != ERROR_SUCCESS) {
-    key_ = NULL;
-    return false;
-  }
-  return true;
-}
-
-bool RegKey::CreateKey(const wchar_t* name, REGSAM access) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(name && access);
-
-  HKEY subkey = NULL;
-  LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE,
-                               access, NULL, &subkey, NULL);
-  Close();
-
-  key_ = subkey;
-  return (result == ERROR_SUCCESS);
-}
-
-bool RegKey::OpenKey(const wchar_t* name, REGSAM access) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(name && access);
-
-  HKEY subkey = NULL;
-  LONG result = RegOpenKeyEx(key_, name, 0, access, &subkey);
-
-  Close();
-
-  key_ = subkey;
-  return (result == ERROR_SUCCESS);
-}
-
-DWORD RegKey::ValueCount() const {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DWORD count = 0;
-  HRESULT result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL,
-                                   NULL, &count, NULL, NULL, NULL, NULL);
-  return (result != ERROR_SUCCESS) ? 0 : count;
-}
-
-bool RegKey::ReadName(int index, std::wstring* name) const {
-  base::ThreadRestrictions::AssertIOAllowed();
-  wchar_t buf[256];
-  DWORD bufsize = arraysize(buf);
-  LRESULT r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL,
-                             NULL, NULL);
-  if (r != ERROR_SUCCESS)
-    return false;
-  if (name)
-    *name = buf;
-  return true;
-}
-
-bool RegKey::ValueExists(const wchar_t* name) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!key_)
-    return false;
-  HRESULT result = RegQueryValueEx(key_, name, 0, NULL, NULL, NULL);
-  return (result == ERROR_SUCCESS);
-}
-
-bool RegKey::ReadValue(const wchar_t* name, void* data,
-                       DWORD* dsize, DWORD* dtype) const {
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!key_)
-    return false;
-  HRESULT result = RegQueryValueEx(key_, name, 0, dtype,
-                                   reinterpret_cast<LPBYTE>(data), dsize);
-  return (result == ERROR_SUCCESS);
-}
-
-bool RegKey::ReadValue(const wchar_t* name, std::wstring* value) const {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(value);
-  const size_t kMaxStringLength = 1024;  // This is after expansion.
-  // Use the one of the other forms of ReadValue if 1024 is too small for you.
-  wchar_t raw_value[kMaxStringLength];
-  DWORD type = REG_SZ, size = sizeof(raw_value);
-  if (ReadValue(name, raw_value, &size, &type)) {
-    if (type == REG_SZ) {
-      *value = raw_value;
-    } else if (type == REG_EXPAND_SZ) {
-      wchar_t expanded[kMaxStringLength];
-      size = ExpandEnvironmentStrings(raw_value, expanded, kMaxStringLength);
-      // Success: returns the number of wchar_t's copied
-      // Fail: buffer too small, returns the size required
-      // Fail: other, returns 0
-      if (size == 0 || size > kMaxStringLength)
-        return false;
-      *value = expanded;
-    } else {
-      // Not a string. Oops.
-      return false;
-    }
-    return true;
-  }
-
-  return false;
-}
-
-bool RegKey::ReadValueDW(const wchar_t* name, DWORD* value) const {
-  DCHECK(value);
-  DWORD type = REG_DWORD;
-  DWORD size = sizeof(DWORD);
-  DWORD result = 0;
-  if (ReadValue(name, &result, &size, &type) &&
-      (type == REG_DWORD || type == REG_BINARY) &&
-      size == sizeof(DWORD)) {
-    *value = result;
-    return true;
-  }
-
-  return false;
-}
-
-bool RegKey::WriteValue(const wchar_t* name, const void * data,
-                        DWORD dsize, DWORD dtype) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(data);
-
-  if (!key_)
-    return false;
-
-  HRESULT result = RegSetValueEx(
-      key_,
-      name,
-      0,
-      dtype,
-      reinterpret_cast<LPBYTE>(const_cast<void*>(data)),
-      dsize);
-  return (result == ERROR_SUCCESS);
-}
-
-bool RegKey::WriteValue(const wchar_t * name, const wchar_t* value) {
-  return WriteValue(name, value,
-      static_cast<DWORD>(sizeof(*value) * (wcslen(value) + 1)), REG_SZ);
-}
-
-bool RegKey::WriteValue(const wchar_t* name, DWORD value) {
-  return WriteValue(name, &value,
-      static_cast<DWORD>(sizeof(value)), REG_DWORD);
-}
-
-bool RegKey::DeleteKey(const wchar_t* name) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  if (!key_)
-    return false;
-  LSTATUS ret = SHDeleteKey(key_, name);
-  if (ERROR_SUCCESS != ret)
-    SetLastError(ret);
-  return ERROR_SUCCESS == ret;
-}
-
-bool RegKey::DeleteValue(const wchar_t* value_name) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(value_name);
-  HRESULT result = RegDeleteValue(key_, value_name);
-  return (result == ERROR_SUCCESS);
-}
-
-bool RegKey::StartWatching() {
-  if (!watch_event_)
-    watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-  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.
-  HRESULT result = RegNotifyChangeKeyValue(key_, TRUE, filter,
-                                           watch_event_, TRUE);
-  if (SUCCEEDED(result)) {
-    return true;
-  } else {
-    CloseHandle(watch_event_);
-    watch_event_ = 0;
-    return false;
-  }
-}
-
-bool RegKey::StopWatching() {
-  if (watch_event_) {
-    CloseHandle(watch_event_);
-    watch_event_ = 0;
-    return true;
-  }
-  return false;
-}
-
-bool RegKey::HasChanged() {
-  if (watch_event_) {
-    if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) {
-      StartWatching();
-      return true;
-    }
-  }
-  return false;
-}
-
 }  // namespace win
 }  // namespace base
diff --git a/base/win/registry.h b/base/win/registry.h
index 96a2bb3..cd5421d 100644
--- a/base/win/registry.h
+++ b/base/win/registry.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,57 +17,62 @@
 // Utility class to read, write and manipulate the Windows Registry.
 // Registry vocabulary primer: a "key" is like a folder, in which there
 // are "values", which are <name, data> pairs, with an associated data type.
+//
+// Note:
+// ReadValue family of functions guarantee that the return arguments
+// are not touched in case of failure.
 class RegKey {
  public:
   RegKey();
   RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access);
   ~RegKey();
 
-  bool Create(HKEY rootkey, const wchar_t* subkey, REGSAM access);
+  LONG Create(HKEY rootkey, const wchar_t* subkey, REGSAM access);
 
-  bool CreateWithDisposition(HKEY rootkey, const wchar_t* subkey,
+  LONG CreateWithDisposition(HKEY rootkey, const wchar_t* subkey,
                              DWORD* disposition, REGSAM access);
 
-  bool Open(HKEY rootkey, const wchar_t* subkey, REGSAM access);
+  LONG Open(HKEY rootkey, const wchar_t* subkey, REGSAM access);
 
   // Creates a subkey or open it if it already exists.
-  bool CreateKey(const wchar_t* name, REGSAM access);
+  LONG CreateKey(const wchar_t* name, REGSAM access);
 
   // Opens a subkey
-  bool OpenKey(const wchar_t* name, REGSAM access);
+  LONG OpenKey(const wchar_t* name, REGSAM access);
 
   void Close();
 
   DWORD ValueCount() const;
 
   // Determine the nth value's name.
-  bool ReadName(int index, std::wstring* name) const;
+  LONG ReadName(int index, std::wstring* name) const;
 
   // True while the key is valid.
   bool Valid() const { return key_ != NULL; }
 
   // Kill a key and everything that live below it; please be careful when using
   // it.
-  bool DeleteKey(const wchar_t* name);
+  LONG DeleteKey(const wchar_t* name);
 
   // Deletes a single value within the key.
-  bool DeleteValue(const wchar_t* name);
+  LONG DeleteValue(const wchar_t* name);
 
-  bool ValueExists(const wchar_t* name);
+  bool ValueExists(const wchar_t* name) const;
 
-  bool ReadValue(const wchar_t* name, void* data, DWORD* dsize,
+  LONG ReadValue(const wchar_t* name, void* data, DWORD* dsize,
                  DWORD* dtype) const;
-  bool ReadValue(const wchar_t* name, std::wstring* value) const;
-  bool ReadValueDW(const wchar_t* name, DWORD* value) const;
+  LONG ReadValue(const wchar_t* name, std::wstring* value) const;
+  LONG ReadValueDW(const wchar_t* name, DWORD* value) const;
+  LONG ReadInt64(const wchar_t* name, int64* value) const;
 
-  bool WriteValue(const wchar_t* name, const void* data, DWORD dsize,
+  LONG WriteValue(const wchar_t* name, const void* data, DWORD dsize,
                   DWORD dtype);
-  bool WriteValue(const wchar_t* name, const wchar_t* value);
-  bool WriteValue(const wchar_t* name, DWORD value);
+  LONG WriteValue(const wchar_t* name, const wchar_t* value);
+  LONG WriteValue(const wchar_t* name, DWORD value);
 
   // Starts watching the key to see if any of its values have changed.
   // The key must have been opened with the KEY_NOTIFY access privilege.
-  bool StartWatching();
+  LONG StartWatching();
 
   // If StartWatching hasn't been called, always returns false.
   // Otherwise, returns true if anything under the key has changed.
@@ -76,7 +81,7 @@
 
   // Will automatically be called by destructor if not manually called
   // beforehand.  Returns true if it was watching, false otherwise.
-  bool StopWatching();
+  LONG StopWatching();
 
   inline bool IsWatching() const { return watch_event_ != 0; }
   HANDLE watch_event() const { return watch_event_; }
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
index 524612a..a7961e9 100644
--- a/base/win/registry_unittest.cc
+++ b/base/win/registry_unittest.cc
@@ -21,14 +21,14 @@
     // Create a temporary key.
     RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
     key.DeleteKey(kRootKey);
-    ASSERT_FALSE(key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
-    ASSERT_TRUE(key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ));
+    ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
+    ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ));
   }
 
   virtual void TearDown() {
     // Clean up the temporary key.
     RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
-    ASSERT_TRUE(key.DeleteKey(kRootKey));
+    ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
   }
 
  private:
@@ -40,22 +40,59 @@
 
   std::wstring foo_key(kRootKey);
   foo_key += L"\\Foo";
-  ASSERT_TRUE(key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
+  ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
+                                      KEY_READ));
 
   {
-    ASSERT_TRUE(key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
-                         KEY_READ | KEY_SET_VALUE));
+    ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
+                                      KEY_READ | KEY_SET_VALUE));
+    ASSERT_TRUE(key.Valid());
 
-    const wchar_t* kName = L"Bar";
-    const wchar_t* kValue = L"bar";
-    EXPECT_TRUE(key.WriteValue(kName, kValue));
-    EXPECT_TRUE(key.ValueExists(kName));
-    std::wstring out_value;
-    EXPECT_TRUE(key.ReadValue(kName, &out_value));
-    EXPECT_NE(out_value, L"");
-    EXPECT_STREQ(out_value.c_str(), kValue);
-    EXPECT_EQ(1U, key.ValueCount());
-    EXPECT_TRUE(key.DeleteValue(kName));
+    const wchar_t* kStringValueName = L"StringValue";
+    const wchar_t* kDWORDValueName = L"DWORDValue";
+    const wchar_t* kInt64ValueName = L"Int64Value";
+    const wchar_t* kStringData = L"string data";
+    const DWORD kDWORDData = 0xdeadbabe;
+    const int64 kInt64Data = 0xdeadbabedeadbabeLL;
+
+    // Test value creation
+    ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kStringValueName, kStringData));
+    ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kDWORDValueName, kDWORDData));
+    ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kInt64ValueName, &kInt64Data,
+                                            sizeof(kInt64Data), REG_QWORD));
+    EXPECT_EQ(3U, key.ValueCount());
+    EXPECT_TRUE(key.ValueExists(kStringValueName));
+    EXPECT_TRUE(key.ValueExists(kDWORDValueName));
+    EXPECT_TRUE(key.ValueExists(kInt64ValueName));
+
+    // Test Read
+    std::wstring string_value;
+    DWORD dword_value = 0;
+    int64 int64_value = 0;
+    ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(kStringValueName, &string_value));
+    ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(kDWORDValueName, &dword_value));
+    ASSERT_EQ(ERROR_SUCCESS, key.ReadInt64(kInt64ValueName, &int64_value));
+    EXPECT_STREQ(kStringData, string_value.c_str());
+    EXPECT_EQ(kDWORDData, dword_value);
+    EXPECT_EQ(kInt64Data, int64_value);
+
+    // Make sure out args are not touched if ReadValue fails
+    const wchar_t* kNonExistent = L"NonExistent";
+    ASSERT_NE(ERROR_SUCCESS, key.ReadValue(kNonExistent, &string_value));
+    ASSERT_NE(ERROR_SUCCESS, key.ReadValueDW(kNonExistent, &dword_value));
+    ASSERT_NE(ERROR_SUCCESS, key.ReadInt64(kNonExistent, &int64_value));
+    EXPECT_STREQ(kStringData, string_value.c_str());
+    EXPECT_EQ(kDWORDData, dword_value);
+    EXPECT_EQ(kInt64Data, int64_value);
+
+    // Test delete
+    ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kStringValueName));
+    ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kDWORDValueName));
+    ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kInt64ValueName));
+    EXPECT_EQ(0U, key.ValueCount());
+    EXPECT_FALSE(key.ValueExists(kStringValueName));
+    EXPECT_FALSE(key.ValueExists(kDWORDValueName));
+    EXPECT_FALSE(key.ValueExists(kInt64ValueName));
   }
 }
 
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index 87905ea..d3d74a2 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -93,7 +93,7 @@
       L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
       KEY_READ);
   DWORD uac_enabled;
-  if (!key.ReadValueDW(L"EnableLUA", &uac_enabled))
+  if (key.ReadValueDW(L"EnableLUA", &uac_enabled) != ERROR_SUCCESS)
     return true;
   // Users can set the EnableLUA value to something arbitrary, like 2, which
   // Vista will treat as UAC enabled, so we make sure it is not set to 0.
@@ -128,12 +128,13 @@
 bool AddCommandToAutoRun(HKEY root_key, const string16& name,
                          const string16& command) {
   base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
-  return autorun_key.WriteValue(name.c_str(), command.c_str());
+  return (autorun_key.WriteValue(name.c_str(), command.c_str()) ==
+      ERROR_SUCCESS);
 }
 
 bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name) {
   base::win::RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
-  return autorun_key.DeleteValue(name.c_str());
+  return (autorun_key.DeleteValue(name.c_str()) == ERROR_SUCCESS);
 }
 
 }  // namespace win
diff --git a/build/.svn/all-wcprops b/build/.svn/all-wcprops
deleted file mode 100644
index 9f84447..0000000
--- a/build/.svn/all-wcprops
+++ /dev/null
@@ -1,137 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 35
-/svn/!svn/ver/70757/trunk/src/build
-END
-README.chromium
-K 25
-svn:wc:ra_dav:version-url
-V 51
-/svn/!svn/ver/26095/trunk/src/build/README.chromium
-END
-features_override.gypi
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/70340/trunk/src/build/features_override.gypi
-END
-release.gypi
-K 25
-svn:wc:ra_dav:version-url
-V 48
-/svn/!svn/ver/45665/trunk/src/build/release.gypi
-END
-extract_from_cab.py
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/54058/trunk/src/build/extract_from_cab.py
-END
-branding_value.sh
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/16372/trunk/src/build/branding_value.sh
-END
-build-bisect.py
-K 25
-svn:wc:ra_dav:version-url
-V 51
-/svn/!svn/ver/70112/trunk/src/build/build-bisect.py
-END
-common.gypi
-K 25
-svn:wc:ra_dav:version-url
-V 47
-/svn/!svn/ver/70757/trunk/src/build/common.gypi
-END
-gyp_chromium
-K 25
-svn:wc:ra_dav:version-url
-V 48
-/svn/!svn/ver/65408/trunk/src/build/gyp_chromium
-END
-dir_exists.py
-K 25
-svn:wc:ra_dav:version-url
-V 49
-/svn/!svn/ver/53810/trunk/src/build/dir_exists.py
-END
-install-build-deps.sh
-K 25
-svn:wc:ra_dav:version-url
-V 57
-/svn/!svn/ver/65094/trunk/src/build/install-build-deps.sh
-END
-sanitize-win-build-log.sh
-K 25
-svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/69510/trunk/src/build/sanitize-win-build-log.sh
-END
-compiler_version.py
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/30847/trunk/src/build/compiler_version.py
-END
-all.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 43
-/svn/!svn/ver/70743/trunk/src/build/all.gyp
-END
-sanitize-win-build-log.sed
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/69510/trunk/src/build/sanitize-win-build-log.sed
-END
-whitespace_file.txt
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/69665/trunk/src/build/whitespace_file.txt
-END
-sanitize-mac-build-log.sh
-K 25
-svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/69274/trunk/src/build/sanitize-mac-build-log.sh
-END
-build_config.h
-K 25
-svn:wc:ra_dav:version-url
-V 50
-/svn/!svn/ver/66999/trunk/src/build/build_config.h
-END
-sanitize-mac-build-log.sed
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/69510/trunk/src/build/sanitize-mac-build-log.sed
-END
-install-chroot.sh
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/63175/trunk/src/build/install-chroot.sh
-END
-common.croc
-K 25
-svn:wc:ra_dav:version-url
-V 47
-/svn/!svn/ver/47071/trunk/src/build/common.croc
-END
-apply_locales.py
-K 25
-svn:wc:ra_dav:version-url
-V 52
-/svn/!svn/ver/40985/trunk/src/build/apply_locales.py
-END
-output_dll_copy.rules
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/7/trunk/src/build/output_dll_copy.rules
-END
diff --git a/build/.svn/dir-prop-base b/build/.svn/dir-prop-base
deleted file mode 100644
index 7f87c4c..0000000
--- a/build/.svn/dir-prop-base
+++ /dev/null
@@ -1,23 +0,0 @@
-K 10
-svn:ignore
-V 288
-all.xcodeproj
-all.sln
-All.vcproj
-SConstruct
-All.scons
-all_main.scons
-All.mk
-chromium_builder.vcproj
-chromium_builder_dbg_tsan_win.vcproj
-chrome_frame_builder.vcproj
-purify_builder_webkit.vcproj
-purify_builder_ui.vcproj
-purify_builder_unit.vcproj
-Debug
-Release
-all.Makefile
-All.target.mk
-
-
-END
diff --git a/build/.svn/entries b/build/.svn/entries
deleted file mode 100644
index 592df7e..0000000
--- a/build/.svn/entries
+++ /dev/null
@@ -1,794 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build
-http://src.chromium.org/svn
-
-
-
-2011-01-07T19:04:43.430431Z
-70757
-tony@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-README.chromium
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-b1b2b94038acd18317539e008a57d128
-2009-09-14T07:41:01.707457Z
-26095
-mmoss@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-892
-
-features_override.gypi
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-26d3a011c9bdceb65dcecb854d6a59b4
-2010-12-31T15:51:00.487219Z
-70340
-jknotten@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3189
-
-temp_gyp
-dir
-
-release.gypi
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-0526837d358186e0e12f1d9478f3b053
-2010-04-27T02:39:59.936412Z
-45665
-thestig@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-405
-
-extract_from_cab.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-4ef80d98b03c939518bc87f558dc495d
-2010-07-28T23:02:22.712200Z
-54058
-apatrick@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-907
-
-branding_value.sh
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-b112e1931330a24299ba260670ec4d81
-2009-05-19T14:10:09.659125Z
-16372
-thomasvl@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1153
-
-build-bisect.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-7a326f8988096282613f80e11c56f43b
-2010-12-23T23:10:06.000703Z
-70112
-evan@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-324
-
-win
-dir
-
-common.gypi
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-cad584dc1df7b44ed8f4eaec309ee6fb
-2011-01-07T19:04:43.430431Z
-70757
-tony@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-57516
-
-linux
-dir
-
-mac
-dir
-
-gyp_chromium
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-faa7afb6ebca58654fdaa6b64c4f8e1c
-2010-11-08T20:09:23.594639Z
-65408
-thomasvl@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4574
-
-dir_exists.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-ee6646b94087e15ba8228a7105b2be3b
-2010-07-27T18:18:17.292389Z
-53810
-apatrick@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-278
-
-install-build-deps.sh
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-6b61028bf33aa5cb009d1366b771431e
-2010-11-04T19:23:30.249443Z
-65094
-ajwong@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-17320
-
-all.gyp
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-e280224af6ab1ed31db64c900e9e7c09
-2011-01-07T17:33:39.224582Z
-70743
-ben@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-19516
-
-compiler_version.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-1982cea7747ba14187db345788c3db60
-2009-11-03T19:27:51.521029Z
-30847
-evan@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1319
-
-sanitize-win-build-log.sh
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-e411ca475511ea20d53ff380dc6799f3
-2010-12-17T03:46:15.376564Z
-69510
-evan@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-225
-
-sanitize-win-build-log.sed
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-1ceed875276096426dbb8c62fb83ef00
-2010-12-17T03:46:15.376564Z
-69510
-evan@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-436
-
-sanitize-mac-build-log.sh
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-e411ca475511ea20d53ff380dc6799f3
-2010-12-15T17:23:25.256786Z
-69274
-scottbyer@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-225
-
-whitespace_file.txt
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-c8105449e62f4bd21d7cc259100255fa
-2010-12-19T02:31:19.684120Z
-69665
-thakis@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-378
-
-build_config.h
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-a03a886228958a0a53a08b7daba5d89d
-2010-11-22T20:57:18.360081Z
-66999
-nkostylev@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4225
-
-sanitize-mac-build-log.sed
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-83432c11a9684f06e26c83bde3747af4
-2010-12-17T03:46:15.376564Z
-69510
-evan@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-779
-
-install-chroot.sh
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-49577308f291ba3b818b4c368c1c0cb2
-2010-10-20T03:32:17.054408Z
-63175
-mmoss@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-10683
-
-internal
-dir
-
-util
-dir
-
-common.croc
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-e491aebfacd2671fbc9b031977539efb
-2010-05-12T21:10:56.860034Z
-47071
-jhawkins@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3333
-
-apply_locales.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-9cdf546ccf194961bfee8ee689d18561
-2010-03-09T02:00:21.811249Z
-40985
-tony@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1455
-
-output_dll_copy.rules
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-6652d32450a16fbbc0d589355d264267
-2008-07-26T20:52:30.524983Z
-7
-initial.commit
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-375
-
diff --git a/build/.svn/prop-base/README.chromium.svn-base b/build/.svn/prop-base/README.chromium.svn-base
deleted file mode 100644
index 0b9192f..0000000
--- a/build/.svn/prop-base/README.chromium.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 13
-svn:mergeinfo
-V 64
-/branches/chrome_webkit_merge_branch/build/README.google:69-2775
-END
diff --git a/build/.svn/prop-base/all.gyp.svn-base b/build/.svn/prop-base/all.gyp.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/all.gyp.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/apply_locales.py.svn-base b/build/.svn/prop-base/apply_locales.py.svn-base
deleted file mode 100644
index 76c8123..0000000
--- a/build/.svn/prop-base/apply_locales.py.svn-base
+++ /dev/null
@@ -1,13 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-K 13
-svn:mergeinfo
-V 80
-/branches/chrome_webkit_merge_branch/chrome/tools/build/apply_locales.py:69-2775
-END
diff --git a/build/.svn/prop-base/branding_value.sh.svn-base b/build/.svn/prop-base/branding_value.sh.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/branding_value.sh.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/build-bisect.py.svn-base b/build/.svn/prop-base/build-bisect.py.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/build-bisect.py.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/build_config.h.svn-base b/build/.svn/prop-base/build_config.h.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/build_config.h.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/common.gypi.svn-base b/build/.svn/prop-base/common.gypi.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/common.gypi.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/compiler_version.py.svn-base b/build/.svn/prop-base/compiler_version.py.svn-base
deleted file mode 100644
index 869ac71..0000000
--- a/build/.svn/prop-base/compiler_version.py.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/dir_exists.py.svn-base b/build/.svn/prop-base/dir_exists.py.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/dir_exists.py.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/extract_from_cab.py.svn-base b/build/.svn/prop-base/extract_from_cab.py.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/extract_from_cab.py.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/features_override.gypi.svn-base b/build/.svn/prop-base/features_override.gypi.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/features_override.gypi.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/gyp_chromium.svn-base b/build/.svn/prop-base/gyp_chromium.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/gyp_chromium.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/install-build-deps.sh.svn-base b/build/.svn/prop-base/install-build-deps.sh.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/install-build-deps.sh.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/install-chroot.sh.svn-base b/build/.svn/prop-base/install-chroot.sh.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/install-chroot.sh.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/output_dll_copy.rules.svn-base b/build/.svn/prop-base/output_dll_copy.rules.svn-base
deleted file mode 100644
index bdbd305..0000000
--- a/build/.svn/prop-base/output_dll_copy.rules.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 6
-native
-END
diff --git a/build/.svn/prop-base/sanitize-mac-build-log.sed.svn-base b/build/.svn/prop-base/sanitize-mac-build-log.sed.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/sanitize-mac-build-log.sed.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/sanitize-mac-build-log.sh.svn-base b/build/.svn/prop-base/sanitize-mac-build-log.sh.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/sanitize-mac-build-log.sh.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/sanitize-win-build-log.sed.svn-base b/build/.svn/prop-base/sanitize-win-build-log.sed.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/sanitize-win-build-log.sed.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/prop-base/sanitize-win-build-log.sh.svn-base b/build/.svn/prop-base/sanitize-win-build-log.sh.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/.svn/prop-base/sanitize-win-build-log.sh.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/.svn/prop-base/whitespace_file.txt.svn-base b/build/.svn/prop-base/whitespace_file.txt.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/.svn/prop-base/whitespace_file.txt.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/.svn/text-base/README.chromium.svn-base b/build/.svn/text-base/README.chromium.svn-base
deleted file mode 100644
index 012df35..0000000
--- a/build/.svn/text-base/README.chromium.svn-base
+++ /dev/null
@@ -1,15 +0,0 @@
-List of property sheets to be included by projects:
-  common.vsprops
-    Not used anymore. No-op. Kept for compatibility with current projects.
-
-  debug.vsprops
-    Enables debug settings. Must be included directly in Debug configuration. Includes internal\essential.vsprops.
-
-  external_code.vsprops
-    Contains settings made to simplify usage of external (non-Google) code. It relaxes the warning levels. Should be included after debug.vsprops or release.vsprops to override their settings.
-
-  output_dll_copy.rules
-    Run to enable automatic copy of DLL when they are as an input file in a vcproj project.
-
-  release.vsprops
-    Enables release settings. Must be included directly in Release configuration. Includes internal\essential.vsprops. Also includes "internal\release_impl$(CHROME_BUILD_TYPE).vsprops". So the behavior is dependant on the CHROME_BUILD_TYPE environment variable.
diff --git a/build/.svn/text-base/all.gyp.svn-base b/build/.svn/text-base/all.gyp.svn-base
deleted file mode 100644
index ba9bc45..0000000
--- a/build/.svn/text-base/all.gyp.svn-base
+++ /dev/null
@@ -1,476 +0,0 @@
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'All',
-      'type': 'none',
-      'xcode_create_dependents_test_runner': 1,
-      'dependencies': [
-        '../app/app.gyp:*',
-        '../base/base.gyp:*',
-        '../chrome/browser/sync/tools/sync_tools.gyp:*',
-        '../chrome/chrome.gyp:*',
-        '../gfx/gfx.gyp:*',
-        '../gpu/gpu.gyp:*',
-        '../gpu/demos/demos.gyp:*',
-        '../ipc/ipc.gyp:*',
-        '../jingle/jingle.gyp:*',
-        '../media/media.gyp:*',
-        '../net/net.gyp:*',
-        '../ppapi/ppapi.gyp:*',
-        '../printing/printing.gyp:*',
-        '../sdch/sdch.gyp:*',
-        '../skia/skia.gyp:*',
-        '../testing/gmock.gyp:*',
-        '../testing/gtest.gyp:*',
-        '../third_party/bzip2/bzip2.gyp:*',
-        '../third_party/cacheinvalidation/cacheinvalidation.gyp:*',
-        '../third_party/cld/cld.gyp:*',
-        '../third_party/codesighs/codesighs.gyp:*',
-        '../third_party/ffmpeg/ffmpeg.gyp:*',
-        '../third_party/iccjpeg/iccjpeg.gyp:*',
-        '../third_party/icu/icu.gyp:*',
-        '../third_party/libpng/libpng.gyp:*',
-        '../third_party/libwebp/libwebp.gyp:*',
-        '../third_party/libxml/libxml.gyp:*',
-        '../third_party/libxslt/libxslt.gyp:*',
-        '../third_party/lzma_sdk/lzma_sdk.gyp:*',
-        '../third_party/mesa/mesa.gyp:*',
-        '../third_party/modp_b64/modp_b64.gyp:*',
-        '../third_party/npapi/npapi.gyp:*',
-        '../third_party/ots/ots.gyp:*',
-        '../third_party/qcms/qcms.gyp:*',
-        '../third_party/sqlite/sqlite.gyp:*',
-        '../third_party/WebKit/WebKit/chromium/WebKit.gyp:*',
-        '../third_party/zlib/zlib.gyp:*',
-        '../ui/ui.gyp:*',
-        '../webkit/support/webkit_support.gyp:*',
-        '../webkit/webkit.gyp:*',
-        'util/build_util.gyp:*',
-        'temp_gyp/googleurl.gyp:*',
-        '<(libjpeg_gyp_path):*',
-      ],
-      'conditions': [
-        ['javascript_engine=="v8"', {
-          'dependencies': [
-            '../v8/tools/gyp/v8.gyp:*',
-          ],
-        }],
-        ['OS=="mac" or OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-          'dependencies': [
-            '../third_party/yasm/yasm.gyp:*#host',
-           ],
-        }],
-        ['OS=="mac" or OS=="win"', {
-          'dependencies': [
-            '../third_party/nss/nss.gyp:*',
-           ],
-        }],
-        ['OS=="mac"', {
-          'dependencies': [
-            '../third_party/ocmock/ocmock.gyp:*',
-          ],
-        }],
-        ['OS=="linux"', {
-          'dependencies': [
-            '../breakpad/breakpad.gyp:*',
-            '../courgette/courgette.gyp:*',
-            '../sandbox/sandbox.gyp:*',
-          ],
-          'conditions': [
-            ['branding=="Chrome"', {
-              'dependencies': [
-                '../chrome/chrome.gyp:linux_packages_<(channel)',
-              ],
-            }],
-          ],
-        }],
-        ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-          'dependencies': [
-            '../tools/gtk_clipboard_dump/gtk_clipboard_dump.gyp:*',
-            '../tools/xdisplaycheck/xdisplaycheck.gyp:*',
-          ],
-        }],
-        ['OS=="win"', {
-          'conditions': [
-            ['win_use_allocator_shim==1', {
-              'dependencies': [
-                '../base/allocator/allocator.gyp:*',
-              ],
-            }],
-          ],
-          'dependencies': [
-            '../breakpad/breakpad.gyp:*',
-            '../chrome/app/locales/locales.gyp:*',
-            '../ceee/ceee.gyp:*',
-            '../chrome_frame/chrome_frame.gyp:*',
-            '../courgette/courgette.gyp:*',
-            '../gears/gears.gyp:*',
-            '../rlz/rlz.gyp:*',
-            '../sandbox/sandbox.gyp:*',
-            '../third_party/angle/src/build_angle.gyp:*',
-            '../third_party/bsdiff/bsdiff.gyp:*',
-            '../third_party/bspatch/bspatch.gyp:*',
-            '../third_party/gles2_book/gles2_book.gyp:*',
-            '../tools/memory_watcher/memory_watcher.gyp:*',
-          ],
-        }, {
-          'dependencies': [
-            '../third_party/libevent/libevent.gyp:*',
-          ],
-        }],
-        ['toolkit_views==1', {
-          'dependencies': [
-            '../views/views.gyp:*',
-          ],
-        }],
-        ['chromeos==1', {
-          'dependencies': [
-            '../chrome/browser/chromeos/input_method/candidate_window.gyp:*',
-          ],
-        }],
-        ['remoting==1', {
-          'dependencies': [
-            '../remoting/remoting.gyp:*',
-          ],
-        }],
-        ['use_openssl!=1', {
-          'dependencies': [
-            '../net/third_party/nss/ssl.gyp:*',
-          ],
-        }],
-      ],
-    },
-    {
-      'target_name': 'chromium_builder_tests',
-      'type': 'none',
-      'dependencies': [
-        '../app/app.gyp:app_unittests',
-        '../base/base.gyp:base_unittests',
-        '../chrome/chrome.gyp:browser_tests',
-        '../chrome/chrome.gyp:interactive_ui_tests',
-        '../chrome/chrome.gyp:nacl_ui_tests',
-        '../chrome/chrome.gyp:nacl_sandbox_tests',
-        '../chrome/chrome.gyp:safe_browsing_tests',
-        '../chrome/chrome.gyp:sync_integration_tests',
-        '../chrome/chrome.gyp:sync_unit_tests',
-        '../chrome/chrome.gyp:ui_tests',
-        '../chrome/chrome.gyp:unit_tests',
-        '../gfx/gfx.gyp:gfx_unittests',
-        '../gpu/gpu.gyp:gpu_unittests',
-        '../ipc/ipc.gyp:ipc_tests',
-        '../jingle/jingle.gyp:notifier_unit_tests',
-        '../media/media.gyp:media_unittests',
-        '../net/net.gyp:net_unittests',
-        '../printing/printing.gyp:printing_unittests',
-        '../remoting/remoting.gyp:remoting_unittests',
-        '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-        'temp_gyp/googleurl.gyp:googleurl_unittests',
-      ],
-      'conditions': [
-        ['OS=="win"', {
-          'dependencies': [
-            '../chrome/chrome.gyp:installer_util_unittests',
-            '../chrome/chrome.gyp:mini_installer_test',
-            # mini_installer_tests depends on mini_installer. This should be
-            # defined in installer.gyp.
-            '../chrome/installer/mini_installer.gyp:mini_installer',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_net_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_perftests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_reliability_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_unittests',
-            '../chrome_frame/chrome_frame.gyp:npchrome_frame',
-            '../courgette/courgette.gyp:courgette_unittests',
-            '../sandbox/sandbox.gyp:sbox_integration_tests',
-            '../sandbox/sandbox.gyp:sbox_unittests',
-            '../sandbox/sandbox.gyp:sbox_validation_tests',
-            '../views/views.gyp:views_unittests',
-            '../third_party/WebKit/WebKit/chromium/WebKit.gyp:copy_TestNetscapePlugIn',
-            # TODO(nsylvain) ui_tests.exe depends on test_shell_common.
-            # This should:
-            # 1) not be the case. OR.
-            # 2) be expressed in the ui tests dependencies.
-            '../webkit/webkit.gyp:test_shell_common',
-           ],
-        }],
-      ],
-    },
-    {
-      'target_name': 'chromium_gpu_builder',
-      'type': 'none',
-      'dependencies': [
-        '../chrome/chrome.gyp:gpu_tests',
-        '../third_party/WebKit/WebKit/chromium/WebKit.gyp:DumpRenderTree',
-      ],
-    }
-  ],
-  'conditions': [
-    ['OS=="mac"', {
-      'targets': [
-        {
-          # Target to build everything plus the dmg.  We don't put the dmg
-          # in the All target because developers really don't need it.
-          'target_name': 'all_and_dmg',
-          'type': 'none',
-          'dependencies': [
-            'All',
-            '../chrome/chrome.gyp:build_app_dmg',
-          ],
-        },
-        # These targets are here so the build bots can use them to build
-        # subsets of a full tree for faster cycle times.
-        {
-          'target_name': 'chromium_builder_dbg',
-          'type': 'none',
-          'dependencies': [
-            '../app/app.gyp:app_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:nacl_ui_tests',
-            '../chrome/chrome.gyp:nacl_sandbox_tests',
-            '../chrome/chrome.gyp:safe_browsing_tests',
-            '../chrome/chrome.gyp:sync_integration_tests',
-            '../chrome/chrome.gyp:sync_unit_tests',
-            '../chrome/chrome.gyp:ui_tests',
-            '../chrome/chrome.gyp:unit_tests',
-            '../gfx/gfx.gyp:gfx_unittests',
-            '../gpu/gpu.gyp:gpu_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../media/media.gyp:media_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-          ],
-        },
-        {
-          'target_name': 'chromium_builder_rel',
-          'type': 'none',
-          'dependencies': [
-            '../app/app.gyp:app_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:memory_test',
-            '../chrome/chrome.gyp:nacl_ui_tests',
-            '../chrome/chrome.gyp:nacl_sandbox_tests',
-            '../chrome/chrome.gyp:page_cycler_tests',
-            '../chrome/chrome.gyp:plugin_tests',
-            '../chrome/chrome.gyp:safe_browsing_tests',
-            '../chrome/chrome.gyp:startup_tests',
-            '../chrome/chrome.gyp:sync_integration_tests',
-            '../chrome/chrome.gyp:sync_unit_tests',
-            '../chrome/chrome.gyp:tab_switching_test',
-            '../chrome/chrome.gyp:ui_tests',
-            '../chrome/chrome.gyp:unit_tests',
-            '../chrome/chrome.gyp:url_fetch_test',
-            '../gfx/gfx.gyp:gfx_unittests',
-            '../gpu/gpu.gyp:gpu_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../media/media.gyp:media_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-          ],
-        },
-        {
-          'target_name': 'chromium_builder_dbg_tsan_mac',
-          'type': 'none',
-          'dependencies': [
-            '../base/base.gyp:base_unittests',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-            '../net/net.gyp:net_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../media/media.gyp:media_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-          ],
-        },
-        {
-          'target_name': 'chromium_builder_dbg_valgrind_mac',
-          'type': 'none',
-          'dependencies': [
-            '../app/app.gyp:app_unittests',
-            '../base/base.gyp:base_unittests',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../media/media.gyp:media_unittests',
-            '../net/net.gyp:net_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../chrome/chrome.gyp:safe_browsing_tests',
-            '../chrome/chrome.gyp:sync_unit_tests',
-            '../chrome/chrome.gyp:unit_tests',
-            '../chrome/chrome.gyp:ui_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-          ],
-        },
-      ],  # targets
-    }], # OS="mac"
-    ['OS=="win"', {
-      'targets': [
-        # These targets are here so the build bots can use them to build
-        # subsets of a full tree for faster cycle times.
-        {
-          'target_name': 'chromium_builder',
-          'type': 'none',
-          'dependencies': [
-            '../app/app.gyp:app_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:installer_util_unittests',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:memory_test',
-            '../chrome/chrome.gyp:mini_installer_test',
-            '../chrome/chrome.gyp:nacl_ui_tests',
-            '../chrome/chrome.gyp:nacl_sandbox_tests',
-            '../chrome/chrome.gyp:page_cycler_tests',
-            '../chrome/chrome.gyp:plugin_tests',
-            '../chrome/chrome.gyp:safe_browsing_tests',
-            '../chrome/chrome.gyp:selenium_tests',
-            '../chrome/chrome.gyp:startup_tests',
-            '../chrome/chrome.gyp:sync_integration_tests',
-            '../chrome/chrome.gyp:sync_unit_tests',
-            '../chrome/chrome.gyp:tab_switching_test',
-            '../chrome/chrome.gyp:ui_tests',
-            '../chrome/chrome.gyp:unit_tests',
-            '../chrome/chrome.gyp:url_fetch_test',
-            # mini_installer_tests depends on mini_installer. This should be
-            # defined in installer.gyp.
-            '../chrome/installer/mini_installer.gyp:mini_installer',
-            '../courgette/courgette.gyp:courgette_unittests',
-            '../gfx/gfx.gyp:gfx_unittests',
-            '../gpu/gpu.gyp:gpu_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../media/media.gyp:media_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-            '../third_party/WebKit/WebKit/chromium/WebKit.gyp:copy_TestNetscapePlugIn',
-            # TODO(nsylvain) ui_tests.exe depends on test_shell_common.
-            # This should:
-            # 1) not be the case. OR.
-            # 2) be expressed in the ui tests dependencies.
-            '../webkit/webkit.gyp:test_shell_common',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_net_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_perftests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_reliability_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_unittests',
-            '../chrome_frame/chrome_frame.gyp:npchrome_frame',
-          ],
-        },
-        {
-          'target_name': 'chromium_builder_dbg_tsan_win',
-          'type': 'none',
-          'dependencies': [
-            '../app/app.gyp:app_unittests',
-            # TODO(bradnelson): app_unittests should depend on locales.
-            # However, we can't add dependencies on chrome/ to app/
-            # See http://crbug.com/43603
-            '../base/base.gyp:base_unittests',
-            '../chrome/app/locales/locales.gyp:*',
-            '../chrome/chrome.gyp:sync_unit_tests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../media/media.gyp:media_unittests',
-            '../net/net.gyp:net_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-          ],
-        },
-      ],  # targets
-      'conditions': [
-        ['branding=="Chrome"', {
-          'targets': [
-            {
-              'target_name': 'chrome_official_builder',
-              'type': 'none',
-              'dependencies': [
-                '../chrome/app/locales/locales.gyp:*',
-                '../chrome/chrome.gyp:crash_service',
-                '../chrome/chrome.gyp:page_cycler_tests',
-                '../chrome/chrome.gyp:policy_templates',
-                '../chrome/chrome.gyp:pyautolib',
-                '../chrome/chrome.gyp:reliability_tests',
-                '../chrome/chrome.gyp:startup_tests',
-                '../chrome/chrome.gyp:automated_ui_tests',
-                '../chrome/installer/mini_installer.gyp:mini_installer',
-                '../chrome_frame/chrome_frame.gyp:chrome_frame_unittests',
-                '../chrome_frame/chrome_frame.gyp:npchrome_frame',
-                '../courgette/courgette.gyp:courgette',
-                '../third_party/adobe/flash/flash_player.gyp:flash_player',
-                '../webkit/webkit.gyp:test_shell',
-              ],
-              'conditions': [
-                ['internal_pdf', {
-                  'dependencies': [
-                    '../pdf/pdf.gyp:pdf',
-                  ],
-                }], # internal_pdf
-              ]
-            },
-          ], # targets
-        }], # branding=="Chrome"
-       ], # conditions
-    }], # OS="win"
-    ['chromeos==1', {
-      'targets': [
-        {
-          'target_name': 'chromeos_builder',
-          'type': 'none',
-          'sources': [
-            # TODO(bradnelson): This is here to work around gyp issue 137.
-            #     Remove this sources list when that issue has been fixed.
-            'all.gyp',
-          ],
-          'dependencies': [
-            '../app/app.gyp:app_unittests',
-            '../base/base.gyp:base_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:chrome',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:memory_test',
-            '../chrome/chrome.gyp:page_cycler_tests',
-            '../chrome/chrome.gyp:safe_browsing_tests',
-            '../chrome/chrome.gyp:startup_tests',
-            '../chrome/chrome.gyp:sync_unit_tests',
-            '../chrome/chrome.gyp:tab_switching_test',
-            '../chrome/chrome.gyp:ui_tests',
-            '../chrome/chrome.gyp:unit_tests',
-            '../chrome/chrome.gyp:url_fetch_test',
-            '../gfx/gfx.gyp:gfx_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../jingle/jingle.gyp:notifier_unit_tests',
-            '../media/media.gyp:ffmpeg_tests',
-            '../media/media.gyp:media_unittests',
-            '../media/media.gyp:omx_test',
-            '../net/net.gyp:net_unittests',
-            '../printing/printing.gyp:printing_unittests',
-            '../remoting/remoting.gyp:remoting_unittests',
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-            'temp_gyp/googleurl.gyp:googleurl_unittests',
-            '../chrome/browser/chromeos/input_method/candidate_window.gyp:candidate_window',
-          ],
-        },
-      ],  # targets
-    }], # "chromeos==1"
-  ], # conditions
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/.svn/text-base/apply_locales.py.svn-base b/build/.svn/text-base/apply_locales.py.svn-base
deleted file mode 100644
index 6af7280..0000000
--- a/build/.svn/text-base/apply_locales.py.svn-base
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-# TODO: remove this script when GYP has for loops
-
-import sys
-import optparse
-
-def main(argv):
-
-  parser = optparse.OptionParser()
-  usage = 'usage: %s [options ...] format_string locale_list'
-  parser.set_usage(usage.replace('%s', '%prog'))
-  parser.add_option('-d', dest='dash_to_underscore', action="store_true",
-                    default=False,
-                    help='map "en-US" to "en" and "-" to "_" in locales')
-
-  (options, arglist) = parser.parse_args(argv)
-
-  if len(arglist) < 3:
-    print 'ERROR: need string and list of locales'
-    return 1
-
-  str_template = arglist[1]
-  locales = arglist[2:]
-
-  results = []
-  for locale in locales:
-    # For Cocoa to find the locale at runtime, it needs to use '_' instead
-    # of '-' (http://crbug.com/20441).  Also, 'en-US' should be represented
-    # simply as 'en' (http://crbug.com/19165, http://crbug.com/25578).
-    if options.dash_to_underscore:
-      if locale == 'en-US':
-        locale = 'en'
-      locale = locale.replace('-', '_')
-    results.append(str_template.replace('ZZLOCALE', locale))
-
-  # Quote each element so filename spaces don't mess up GYP's attempt to parse
-  # it into a list.
-  print ' '.join(["'%s'" % x for x in results])
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/build/.svn/text-base/branding_value.sh.svn-base b/build/.svn/text-base/branding_value.sh.svn-base
deleted file mode 100644
index 9fcb550..0000000
--- a/build/.svn/text-base/branding_value.sh.svn-base
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2008 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is a wrapper for fetching values from the BRANDING files.  Pass the
-# value of GYP's branding variable followed by the key you want and the right
-# file is checked.
-#
-#  branding_value.sh Chromium COPYRIGHT
-#  branding_value.sh Chromium PRODUCT_FULLNAME
-#
-
-set -e
-
-if [ $# -ne 2 ] ;  then
-  echo "error: expect two arguments, branding and key" >&2
-  exit 1
-fi
-
-BUILD_BRANDING=$1
-THE_KEY=$2
-
-pushd $(dirname "${0}") > /dev/null
-BUILD_DIR=$(pwd)
-popd > /dev/null
-
-TOP="${BUILD_DIR}/.."
-
-case ${BUILD_BRANDING} in
-  Chromium)
-    BRANDING_FILE="${TOP}/chrome/app/theme/chromium/BRANDING"
-    ;;
-  Chrome)
-    BRANDING_FILE="${TOP}/chrome/app/theme/google_chrome/BRANDING"
-    ;;
-  *)
-    echo "error: unknown branding: ${BUILD_BRANDING}" >&2
-    exit 1
-    ;;
-esac
-
-BRANDING_VALUE=$(sed -n -e "s/^${THE_KEY}=\(.*\)\$/\1/p" "${BRANDING_FILE}")
-
-if [ -z "${BRANDING_VALUE}" ] ; then
-  echo "error: failed to find key '${THE_KEY}'" >&2
-  exit 1
-fi
-
-echo "${BRANDING_VALUE}"
diff --git a/build/.svn/text-base/build-bisect.py.svn-base b/build/.svn/text-base/build-bisect.py.svn-base
deleted file mode 100644
index 33fcb89..0000000
--- a/build/.svn/text-base/build-bisect.py.svn-base
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-import sys
-
-print "This script has been moved to tools/bisect-builds.py."
-print "Please update any docs you're working from!"
-
-sys.exit(1)
diff --git a/build/.svn/text-base/build_config.h.svn-base b/build/.svn/text-base/build_config.h.svn-base
deleted file mode 100644
index 0bfccd7..0000000
--- a/build/.svn/text-base/build_config.h.svn-base
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file adds defines about the platform we're currently building on.
-//  Operating System:
-//    OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX)
-//  Compiler:
-//    COMPILER_MSVC / COMPILER_GCC
-//  Processor:
-//    ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64)
-//    ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
-
-#ifndef BUILD_BUILD_CONFIG_H_
-#define BUILD_BUILD_CONFIG_H_
-
-// A set of macros to use for platform detection.
-#if defined(__APPLE__)
-#define OS_MACOSX 1
-#elif defined(__native_client__)
-#define OS_NACL 1
-#elif defined(__linux__)
-#define OS_LINUX 1
-// Use TOOLKIT_GTK on linux if TOOLKIT_VIEWS isn't defined.
-#if !defined(TOOLKIT_VIEWS)
-#define TOOLKIT_GTK
-#endif
-#elif defined(_WIN32)
-#define OS_WIN 1
-#define TOOLKIT_VIEWS 1
-#elif defined(__FreeBSD__)
-#define OS_FREEBSD 1
-#define TOOLKIT_GTK
-#elif defined(__OpenBSD__)
-#define OS_OPENBSD 1
-#define TOOLKIT_GTK
-#elif defined(__sun)
-#define OS_SOLARIS 1
-#define TOOLKIT_GTK
-#else
-#error Please add support for your platform in build/build_config.h
-#endif
-
-// A flag derived from the above flags, used to cover GTK code in
-// both TOOLKIT_GTK and TOOLKIT_VIEWS.
-#if defined(TOOLKIT_GTK) || (defined(TOOLKIT_VIEWS) && !defined(OS_WIN))
-#define TOOLKIT_USES_GTK 1
-#endif
-
-#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || \
-    defined(OS_SOLARIS)
-#if !defined(USE_OPENSSL)
-#define USE_NSS 1  // Default to use NSS for crypto, unless OpenSSL is chosen.
-#endif
-#define USE_X11 1  // Use X for graphics.
-#endif
-
-#if defined(USE_OPENSSL) && defined(USE_NSS)
-#error Cannot use both OpenSSL and NSS
-#endif
-
-// For access to standard POSIXish features, use OS_POSIX instead of a
-// more specific macro.
-#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \
-    defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_NACL)
-#define OS_POSIX 1
-// Use base::DataPack for name/value pairs.
-#define USE_BASE_DATA_PACK 1
-#endif
-
-// Use tcmalloc
-#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(NO_TCMALLOC)
-#define USE_TCMALLOC 1
-#endif
-
-// Use heapchecker.
-#if defined(OS_LINUX) && !defined(NO_HEAPCHECKER)
-#define USE_HEAPCHECKER 1
-#endif
-
-// Compiler detection.
-#if defined(__GNUC__)
-#define COMPILER_GCC 1
-#elif defined(_MSC_VER)
-#define COMPILER_MSVC 1
-#else
-#error Please add support for your compiler in build/build_config.h
-#endif
-
-// Processor architecture detection.  For more info on what's defined, see:
-//   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
-//   http://www.agner.org/optimize/calling_conventions.pdf
-//   or with gcc, run: "echo | gcc -E -dM -"
-#if defined(_M_X64) || defined(__x86_64__)
-#define ARCH_CPU_X86_FAMILY 1
-#define ARCH_CPU_X86_64 1
-#define ARCH_CPU_64_BITS 1
-#elif defined(_M_IX86) || defined(__i386__)
-#define ARCH_CPU_X86_FAMILY 1
-#define ARCH_CPU_X86 1
-#define ARCH_CPU_32_BITS 1
-#elif defined(__ARMEL__)
-#define ARCH_CPU_ARM_FAMILY 1
-#define ARCH_CPU_ARMEL 1
-#define ARCH_CPU_32_BITS 1
-#define WCHAR_T_IS_UNSIGNED 1
-#else
-#error Please add support for your architecture in build/build_config.h
-#endif
-
-// Type detection for wchar_t.
-#if defined(OS_WIN)
-#define WCHAR_T_IS_UTF16
-#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
-    defined(__WCHAR_MAX__) && \
-    (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
-#define WCHAR_T_IS_UTF32
-#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
-    defined(__WCHAR_MAX__) && \
-    (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
-// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to
-// compile in this mode (in particular, Chrome doesn't). This is intended for
-// other projects using base who manage their own dependencies and make sure
-// short wchar works for them.
-#define WCHAR_T_IS_UTF16
-#else
-#error Please add support for your compiler in build/build_config.h
-#endif
-
-#if defined(OS_CHROMEOS)
-// Single define to trigger whether CrOS fonts have BCI on.
-// In that case font sizes/deltas should be adjusted.
-//define CROS_FONTS_USING_BCI
-#endif
-
-#endif  // BUILD_BUILD_CONFIG_H_
diff --git a/build/.svn/text-base/common.croc.svn-base b/build/.svn/text-base/common.croc.svn-base
deleted file mode 100644
index 5588990..0000000
--- a/build/.svn/text-base/common.croc.svn-base
+++ /dev/null
@@ -1,127 +0,0 @@
-# -*- python -*-
-# Crocodile config file for Chromium - settings common to all platforms
-#
-# This should be speicified before the platform-specific config, for example:
-#       croc -c chrome_common.croc -c linux/chrome_linux.croc
-
-{
-  # List of root directories, applied in order
-  'roots' : [
-    # Sub-paths we specifically care about and want to call out
-    {
-      'root' : '_/src',
-      'altname' : 'CHROMIUM',
-    },
-  ],
-
-  # List of rules, applied in order
-  # Note that any 'include':0 rules here will be overridden by the 'include':1
-  # rules in the platform-specific configs.
-  'rules' : [
-    # Don't scan for executable lines in uninstrumented C++ header files
-    {
-      'regexp' : '.*\\.(h|hpp)$',
-      'add_if_missing' : 0,
-    },
-
-    # Groups
-    {
-      'regexp' : '',
-      'group' : 'source',
-    },
-    {
-      'regexp' : '.*_(test|unittest)\\.',
-      'group' : 'test',
-    },
-
-    # Languages
-    {
-      'regexp' : '.*\\.(c|h)$',
-      'language' : 'C',
-    },
-    {
-      'regexp' : '.*\\.(cc|cpp|hpp)$',
-      'language' : 'C++',
-    },
-
-    # Files/paths to include.  Specify these before the excludes, since rules
-    # are in order.
-    {
-      'regexp' : '^CHROMIUM/(base|media|net|printing|chrome|webkit/glue|native_client)/',
-      'include' : 1,
-    },
-    # Don't include subversion or mercurial SCM dirs
-    {
-      'regexp' : '.*/(\\.svn|\\.hg)/',
-      'include' : 0,
-    },
-    # Don't include output dirs
-    {
-      'regexp' : '.*/(Debug|Release|sconsbuild|out|xcodebuild)/',
-      'include' : 0,
-    },
-    # Don't include third-party source
-    {
-      'regexp' : '.*/third_party/',
-      'include' : 0,
-    },
-    # We don't run the V8 test suite, so we don't care about V8 coverage.
-    {
-      'regexp' : '.*/v8/',
-      'include' : 0,
-    },
-  ],
-
-  # Paths to add source from
-  'add_files' : [
-    'CHROMIUM'
-  ],
-
-  # Statistics to print
-  'print_stats' : [
-    {
-      'stat' : 'files_executable',
-      'format' : '*RESULT FilesKnown: files_executable= %d files',
-    },
-    {
-      'stat' : 'files_instrumented',
-      'format' : '*RESULT FilesInstrumented: files_instrumented= %d files',
-    },
-    {
-      'stat' : '100.0 * files_instrumented / files_executable',
-      'format' : '*RESULT FilesInstrumentedPercent: files_instrumented_percent= %g',
-    },
-    {
-      'stat' : 'lines_executable',
-      'format' : '*RESULT LinesKnown: lines_known= %d lines',
-    },
-    {
-      'stat' : 'lines_instrumented',
-      'format' : '*RESULT LinesInstrumented: lines_instrumented= %d lines',
-    },
-    {
-      'stat' : 'lines_covered',
-      'format' : '*RESULT LinesCoveredSource: lines_covered_source= %d lines',
-      'group' : 'source',
-    },
-    {
-      'stat' : 'lines_covered',
-      'format' : '*RESULT LinesCoveredTest: lines_covered_test= %d lines',
-      'group' : 'test',
-    },
-    {
-      'stat' : '100.0 * lines_covered / lines_executable',
-      'format' : '*RESULT PercentCovered: percent_covered= %g',
-    },
-    {
-      'stat' : '100.0 * lines_covered / lines_executable',
-      'format' : '*RESULT PercentCoveredSource: percent_covered_source= %g',
-      'group' : 'source',
-    },
-    {
-      'stat' : '100.0 * lines_covered / lines_executable',
-      'format' : '*RESULT PercentCoveredTest: percent_covered_test= %g',
-      'group' : 'test',
-    },
-  ],
-}
diff --git a/build/.svn/text-base/common.gypi.svn-base b/build/.svn/text-base/common.gypi.svn-base
deleted file mode 100644
index ae5f41a..0000000
--- a/build/.svn/text-base/common.gypi.svn-base
+++ /dev/null
@@ -1,1510 +0,0 @@
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# IMPORTANT:
-# Please don't directly include this file if you are building via gyp_chromium,
-# since gyp_chromium is automatically forcing its inclusion.
-{
-  # Variables expected to be overriden on the GYP command line (-D) or by
-  # ~/.gyp/include.gypi.
-  'variables': {
-    # Putting a variables dict inside another variables dict looks kind of
-    # weird.  This is done so that 'host_arch', 'chromeos', etc are defined as
-    # variables within the outer variables dict here.  This is necessary
-    # to get these variables defined for the conditions within this variables
-    # dict that operate on these variables (e.g., for setting 'toolkit_views',
-    # we need to have 'chromeos' already set).
-    'variables': {
-      'variables': {
-        'variables': {
-          # Whether we're building a ChromeOS build.
-          'chromeos%': 0,
-
-          # Disable touch support by default.
-          'touchui%': 0,
-        },
-        # Copy conditionally-set variables out one scope.
-        'chromeos%': '<(chromeos)',
-        'touchui%': '<(touchui)',
-
-        # To do a shared build on linux we need to be able to choose between
-        # type static_library and shared_library. We default to doing a static
-        # build but you can override this with "gyp -Dlibrary=shared_library"
-        # or you can add the following line (without the #) to
-        # ~/.gyp/include.gypi {'variables': {'library': 'shared_library'}}
-        # to compile as shared by default
-        'library%': 'static_library',
-
-        # Compute the architecture that we're building on.
-        'conditions': [
-          [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-            # This handles the Linux platforms we generally deal with. Anything
-            # else gets passed through, which probably won't work very well; such
-            # hosts should pass an explicit target_arch to gyp.
-            'host_arch%':
-              '<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/")',
-          }, {  # OS!="linux"
-            'host_arch%': 'ia32',
-          }],
-
-          # Set default value of toolkit_views on for Windows, Chrome OS
-          # and the touch UI.
-          ['OS=="win" or chromeos==1 or touchui==1', {
-            'toolkit_views%': 1,
-          }, {
-            'toolkit_views%': 0,
-          }],
-        ],
-      },
-
-      # Copy conditionally-set variables out one scope.
-      'chromeos%': '<(chromeos)',
-      'touchui%': '<(touchui)',
-      'host_arch%': '<(host_arch)',
-      'library%': '<(library)',
-      'toolkit_views%': '<(toolkit_views)',
-
-      # Override branding to select the desired branding flavor.
-      'branding%': 'Chromium',
-
-      # Override buildtype to select the desired build flavor.
-      # Dev - everyday build for development/testing
-      # Official - release build (generally implies additional processing)
-      # TODO(mmoss) Once 'buildtype' is fully supported (e.g. Windows gyp
-      # conversion is done), some of the things which are now controlled by
-      # 'branding', such as symbol generation, will need to be refactored based
-      # on 'buildtype' (i.e. we don't care about saving symbols for non-Official
-      # builds).
-      'buildtype%': 'Dev',
-
-      # Default architecture we're building for is the architecture we're
-      # building on.
-      'target_arch%': '<(host_arch)',
-
-      # This variable tells WebCore.gyp and JavaScriptCore.gyp whether they are
-      # are built under a chromium full build (1) or a webkit.org chromium
-      # build (0).
-      'inside_chromium_build%': 1,
-
-      # Set to 1 to enable fast builds. It disables debug info for fastest
-      # compilation.
-      'fastbuild%': 0,
-
-      # Python version.
-      'python_ver%': '2.5',
-
-      # Set ARM-v7 compilation flags
-      'armv7%': 0,
-
-      # Set Neon compilation flags (only meaningful if armv7==1).
-      'arm_neon%': 1,
-
-      # The system root for cross-compiles. Default: none.
-      'sysroot%': '',
-
-      # On Linux, we build with sse2 for Chromium builds.
-      'disable_sse2%': 0,
-
-      # Use libjpeg-turbo as the JPEG codec used by Chromium.
-      'use_libjpeg_turbo%': 0,
-
-      # Variable 'component' is for cases where we would like to build some
-      # components as dynamic shared libraries but still need variable
-      # 'library' for static libraries.
-      # By default, component is set to whatever library is set to and
-      # it can be overriden by the GYP command line or by ~/.gyp/include.gypi.
-      'component%': '<(library)',
-
-      # Set to select the Title Case versions of strings in GRD files.
-      'use_titlecase_in_grd_files%': 0,
-
-      'conditions': [
-        # A flag to enable or disable our compile-time dependency
-        # on gnome-keyring. If that dependency is disabled, no gnome-keyring
-        # support will be available. This option is useful
-        # for Linux distributions.
-        ['chromeos==1', {
-          'use_gnome_keyring%': 0,
-        }, {
-          'use_gnome_keyring%': 1,
-        }],
-
-        # Set to 1 compile with -fPIC cflag on linux. This is a must for shared
-        # libraries on linux x86-64 and arm.
-        ['host_arch=="ia32"', {
-          'linux_fpic%': 0,
-        }, {
-          'linux_fpic%': 1,
-        }],
-
-        ['toolkit_views==0 or OS=="mac"', {
-          # GTK+ and Mac wants Title Case strings
-          'use_titlecase_in_grd_files%': 1,
-        }],
-
-        # Enable some hacks to support Flapper only on Chrome OS.
-        ['chromeos==1', {
-          'enable_flapper_hacks%': 1,
-        }, {
-          'enable_flapper_hacks%': 0,
-        }],
-      ],
-    },
-
-    # Copy conditionally-set variables out one scope.
-    'branding%': '<(branding)',
-    'buildtype%': '<(buildtype)',
-    'target_arch%': '<(target_arch)',
-    'host_arch%': '<(host_arch)',
-    'toolkit_views%': '<(toolkit_views)',
-    'use_gnome_keyring%': '<(use_gnome_keyring)',
-    'linux_fpic%': '<(linux_fpic)',
-    'enable_flapper_hacks%': '<(enable_flapper_hacks)',
-    'chromeos%': '<(chromeos)',
-    'touchui%': '<(touchui)',
-    'inside_chromium_build%': '<(inside_chromium_build)',
-    'fastbuild%': '<(fastbuild)',
-    'python_ver%': '<(python_ver)',
-    'armv7%': '<(armv7)',
-    'arm_neon%': '<(arm_neon)',
-    'sysroot%': '<(sysroot)',
-    'disable_sse2%': '<(disable_sse2)',
-    'library%': '<(library)',
-    'component%': '<(component)',
-    'use_titlecase_in_grd_files%': '<(use_titlecase_in_grd_files)',
-
-    # The release channel that this build targets. This is used to restrict
-    # channel-specific build options, like which installer packages to create.
-    # The default is 'all', which does no channel-specific filtering.
-    'channel%': 'all',
-
-    # Override chromium_mac_pch and set it to 0 to suppress the use of
-    # precompiled headers on the Mac.  Prefix header injection may still be
-    # used, but prefix headers will not be precompiled.  This is useful when
-    # using distcc to distribute a build to compile slaves that don't
-    # share the same compiler executable as the system driving the compilation,
-    # because precompiled headers rely on pointers into a specific compiler
-    # executable's image.  Setting this to 0 is needed to use an experimental
-    # Linux-Mac cross compiler distcc farm.
-    'chromium_mac_pch%': 1,
-
-    # Mac OS X SDK and deployment target support.
-    # The SDK identifies the version of the system headers that will be used,
-    # and corresponds to the MAC_OS_X_VERSION_MAX_ALLOWED compile-time macro.
-    # "Maximum allowed" refers to the operating system version whose APIs are
-    # available in the headers.
-    # The deployment target identifies the minimum system version that the
-    # built products are expected to function on.  It corresponds to the
-    # MAC_OS_X_VERSION_MIN_REQUIRED compile-time macro.
-    # To ensure these macros are available, #include <AvailabilityMacros.h>.
-    # Additional documentation on these macros is available at
-    # http://developer.apple.com/mac/library/technotes/tn2002/tn2064.html#SECTION3
-    # Chrome normally builds with the Mac OS X 10.5 SDK and sets the
-    # deployment target to 10.5.  Other projects, such as O3D, may override
-    # these defaults.
-    'mac_sdk%': '10.5',
-    'mac_deployment_target%': '10.5',
-
-    # Set to 1 to enable code coverage.  In addition to build changes
-    # (e.g. extra CFLAGS), also creates a new target in the src/chrome
-    # project file called "coverage".
-    # Currently ignored on Windows.
-    'coverage%': 0,
-
-    # Overridable specification for potential use of alternative
-    # JavaScript engines.
-    'javascript_engine%': 'v8',
-
-    # Although base/allocator lets you select a heap library via an
-    # environment variable, the libcmt shim it uses sometimes gets in
-    # the way.  To disable it entirely, and switch to normal msvcrt, do e.g.
-    #  'win_use_allocator_shim': 0,
-    #  'win_release_RuntimeLibrary': 2
-    # to ~/.gyp/include.gypi, gclient runhooks --force, and do a release build.
-    'win_use_allocator_shim%': 1, # 1 = shim allocator via libcmt; 0 = msvcrt
-
-    # Whether usage of OpenMAX is enabled.
-    'enable_openmax%': 0,
-
-    # Whether proprietary audio/video codecs are assumed to be included with
-    # this build (only meaningful if branding!=Chrome).
-    'proprietary_codecs%': 0,
-
-    # TODO(bradnelson): eliminate this when possible.
-    # To allow local gyp files to prevent release.vsprops from being included.
-    # Yes(1) means include release.vsprops.
-    # Once all vsprops settings are migrated into gyp, this can go away.
-    'msvs_use_common_release%': 1,
-
-    # TODO(bradnelson): eliminate this when possible.
-    # To allow local gyp files to override additional linker options for msvs.
-    # Yes(1) means set use the common linker options.
-    'msvs_use_common_linker_extras%': 1,
-
-    # TODO(sgk): eliminate this if possible.
-    # It would be nicer to support this via a setting in 'target_defaults'
-    # in chrome/app/locales/locales.gypi overriding the setting in the
-    # 'Debug' configuration in the 'target_defaults' dict below,
-    # but that doesn't work as we'd like.
-    'msvs_debug_link_incremental%': '2',
-
-    # This is the location of the sandbox binary. Chrome looks for this before
-    # running the zygote process. If found, and SUID, it will be used to
-    # sandbox the zygote process and, thus, all renderer processes.
-    'linux_sandbox_path%': '',
-
-    # Set this to true to enable SELinux support.
-    'selinux%': 0,
-
-    # Set this to true when building with Clang.
-    # See http://code.google.com/p/chromium/wiki/Clang for details.
-    # TODO: eventually clang should behave identically to gcc, and this
-    # won't be necessary.
-    'clang%': 0,
-
-    # Override whether we should use Breakpad on Linux. I.e. for Chrome bot.
-    'linux_breakpad%': 0,
-    # And if we want to dump symbols for Breakpad-enabled builds.
-    'linux_dump_symbols%': 0,
-    # And if we want to strip the binary after dumping symbols.
-    'linux_strip_binary%': 0,
-    # Strip the test binaries needed for Linux reliability tests.
-    'linux_strip_reliability_tests%': 0,
-
-    # Enable TCMalloc.
-    'linux_use_tcmalloc%': 1,
-
-    # Disable TCMalloc's debugallocation.
-    'linux_use_debugallocation%': 0,
-
-    # Disable TCMalloc's heapchecker.
-    'linux_use_heapchecker%': 0,
-
-    # Disable shadow stack keeping used by heapcheck to unwind the stacks
-    # better.
-    'linux_keep_shadow_stacks%': 0,
-
-    # Set to 1 to turn on seccomp sandbox by default.
-    # (Note: this is ignored for official builds.)
-    'linux_use_seccomp_sandbox%': 0,
-
-    # Set to 1 to link against libgnome-keyring instead of using dlopen().
-    'linux_link_gnome_keyring%': 0,
-
-    # Used to disable Native Client at compile time, for platforms where it
-    # isn't supported
-    'disable_nacl%': 0,
-
-    # Set Thumb compilation flags.
-    'arm_thumb%': 0,
-
-    # Set ARM fpu compilation flags (only meaningful if armv7==1 and
-    # arm_neon==0).
-    'arm_fpu%': 'vfpv3',
-
-    # Enable new NPDevice API.
-    'enable_new_npdevice_api%': 0,
-
-    # Enable EGLImage support in OpenMAX
-    'enable_eglimage%': 0,
-
-    # Enable a variable used elsewhere throughout the GYP files to determine
-    # whether to compile in the sources for the GPU plugin / process.
-    'enable_gpu%': 1,
-
-    # Use GConf, the GNOME configuration system.
-    'use_gconf%': 1,
-
-    # Use OpenSSL instead of NSS. Under development: see http://crbug.com/62803
-    'use_openssl%': 0,
-
-    # .gyp files or targets should set chromium_code to 1 if they build
-    # Chromium-specific code, as opposed to external code.  This variable is
-    # used to control such things as the set of warnings to enable, and
-    # whether warnings are treated as errors.
-    'chromium_code%': 0,
-
-    # Set to 1 to compile with the built in pdf viewer.
-    'internal_pdf%': 0,
-
-    # This allows to use libcros from the current system, ie. /usr/lib/
-    # The cros_api will be pulled in as a static library, and all headers
-    # from the system include dirs.
-    'system_libcros%': 0,
-
-    # Remoting compilation is enabled by default. Set to 0 to disable.
-    'remoting%': 1,
-
-    # NOTE: When these end up in the Mac bundle, we need to replace '-' for '_'
-    # so Cocoa is happy (http://crbug.com/20441).
-    'locales': [
-      'am', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB',
-      'en-US', 'es-419', 'es', 'et', 'fa', 'fi', 'fil', 'fr', 'gu', 'he',
-      'hi', 'hr', 'hu', 'id', 'it', 'ja', 'kn', 'ko', 'lt', 'lv',
-      'ml', 'mr', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru',
-      'sk', 'sl', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tr', 'uk',
-      'vi', 'zh-CN', 'zh-TW',
-    ],
-
-    'grit_defines': [],
-
-    # Use Harfbuzz-NG instead of Harfbuzz.
-    # Under development: http://crbug.com/68551
-    'use_harfbuzz_ng%': 0,
-
-    'conditions': [
-      ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-        # This will set gcc_version to XY if you are running gcc X.Y.*.
-        # This is used to tweak build flags for gcc 4.4.
-        'gcc_version%': '<!(python <(DEPTH)/build/compiler_version.py)',
-        # Figure out the python architecture to decide if we build pyauto.
-        'python_arch%': '<!(<(DEPTH)/build/linux/python_arch.sh <(sysroot)/usr/lib/libpython<(python_ver).so.1.0)',
-        'conditions': [
-          ['branding=="Chrome"', {
-            'linux_breakpad%': 1,
-          }],
-          # All Chrome builds have breakpad symbols, but only process the
-          # symbols from official builds.
-          ['(branding=="Chrome" and buildtype=="Official")', {
-            'linux_dump_symbols%': 1,
-          }],
-        ],
-      }],  # OS=="linux" or OS=="freebsd" or OS=="openbsd"
-
-      ['OS=="mac"', {
-        'conditions': [
-          # mac_product_name is set to the name of the .app bundle as it should
-          # appear on disk.  This duplicates data from
-          # chrome/app/theme/chromium/BRANDING and
-          # chrome/app/theme/google_chrome/BRANDING, but is necessary to get
-          # these names into the build system.
-          ['branding=="Chrome"', {
-            'mac_product_name%': 'Google Chrome',
-          }, { # else: branding!="Chrome"
-            'mac_product_name%': 'Chromium',
-          }],
-
-          # Feature variables for enabling Mac Breakpad and Keystone auto-update
-          # support.  Both features are on by default in official builds with
-          # Chrome branding.
-          ['branding=="Chrome" and buildtype=="Official"', {
-            'mac_breakpad%': 1,
-            'mac_keystone%': 1,
-          }, { # else: branding!="Chrome" or buildtype!="Official"
-            'mac_breakpad%': 0,
-            'mac_keystone%': 0,
-          }],
-        ],
-      }],  # OS=="mac"
-
-      # Whether to use multiple cores to compile with visual studio. This is
-      # optional because it sometimes causes corruption on VS 2005.
-      # It is on by default on VS 2008 and off on VS 2005.
-      ['OS=="win"', {
-        'conditions': [
-          ['component=="shared_library"', {
-            'win_use_allocator_shim%': 0,
-          }],
-          ['MSVS_VERSION=="2005"', {
-            'msvs_multi_core_compile%': 0,
-          },{
-            'msvs_multi_core_compile%': 1,
-          }],
-          # Don't do incremental linking for large modules on 32-bit.
-          ['MSVS_OS_BITS==32', {
-            'msvs_large_module_debug_link_mode%': '1',  # No
-          },{
-            'msvs_large_module_debug_link_mode%': '2',  # Yes
-          }],
-        ],
-        'nacl_win64_defines': [
-          # This flag is used to minimize dependencies when building
-          # Native Client loader for 64-bit Windows.
-          'NACL_WIN64',
-        ],
-      }],
-
-      ['OS=="mac" or (OS=="linux" and chromeos==0 and target_arch!="arm")', {
-        'use_cups%': 1,
-      }, {
-        'use_cups%': 0,
-      }],
-
-      # Set the relative path from this file to the GYP file of the JPEG
-      # library used by Chromium.
-      ['use_libjpeg_turbo==1', {
-        'libjpeg_gyp_path': '../third_party/libjpeg_turbo/libjpeg.gyp',
-      }, {
-        'libjpeg_gyp_path': '../third_party/libjpeg/libjpeg.gyp',
-      }],  # use_libjpeg_turbo==1
-
-      # Setup -D flags passed into grit.
-      ['chromeos==1', {
-        'grit_defines': ['-D', 'chromeos'],
-      }],
-      ['toolkit_views==1', {
-        'grit_defines': ['-D', 'toolkit_views'],
-      }],
-      ['touchui==1', {
-        'grit_defines': ['-D', 'touchui'],
-      }],
-      ['use_titlecase_in_grd_files==1', {
-        'grit_defines': ['-D', 'use_titlecase'],
-      }],
-    ],
-  },
-  'target_defaults': {
-    'variables': {
-      # The condition that operates on chromium_code is in a target_conditions
-      # section, and will not have access to the default fallback value of
-      # chromium_code at the top of this file, or to the chromium_code
-      # variable placed at the root variables scope of .gyp files, because
-      # those variables are not set at target scope.  As a workaround,
-      # if chromium_code is not set at target scope, define it in target scope
-      # to contain whatever value it has during early variable expansion.
-      # That's enough to make it available during target conditional
-      # processing.
-      'chromium_code%': '<(chromium_code)',
-
-      # See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Optimize-Options.html
-      'mac_release_optimization%': '3', # Use -O3 unless overridden
-      'mac_debug_optimization%': '0',   # Use -O0 unless overridden
-      # See http://msdn.microsoft.com/en-us/library/aa652360(VS.71).aspx
-      'win_release_Optimization%': '2', # 2 = /Os
-      'win_debug_Optimization%': '0',   # 0 = /Od
-      # See http://msdn.microsoft.com/en-us/library/8wtf2dfz(VS.71).aspx
-      'win_debug_RuntimeChecks%': '3',    # 3 = all checks enabled, 0 = off
-      # See http://msdn.microsoft.com/en-us/library/47238hez(VS.71).aspx
-      'win_debug_InlineFunctionExpansion%': '',    # empty = default, 0 = off,
-      'win_release_InlineFunctionExpansion%': '2', # 1 = only __inline, 2 = max
-      # VS inserts quite a lot of extra checks to algorithms like
-      # std::partial_sort in Debug build which make them O(N^2)
-      # instead of O(N*logN). This is particularly slow under memory
-      # tools like ThreadSanitizer so we want it to be disablable.
-      # See http://msdn.microsoft.com/en-us/library/aa985982(v=VS.80).aspx
-      'win_debug_disable_iterator_debugging%': '0',
-
-      'release_extra_cflags%': '',
-      'debug_extra_cflags%': '',
-      'release_valgrind_build%': 0,
-
-      'conditions': [
-        ['OS=="win" and component=="shared_library"', {
-          # See http://msdn.microsoft.com/en-us/library/aa652367.aspx
-          'win_release_RuntimeLibrary%': '2', # 2 = /MT (nondebug DLL)
-          'win_debug_RuntimeLibrary%': '3',   # 3 = /MTd (debug DLL)
-        }, {
-          # See http://msdn.microsoft.com/en-us/library/aa652367.aspx
-          'win_release_RuntimeLibrary%': '0', # 0 = /MT (nondebug static)
-          'win_debug_RuntimeLibrary%': '1',   # 1 = /MTd (debug static)
-        }],
-      ],
-    },
-    'conditions': [
-      ['branding=="Chrome"', {
-        'defines': ['GOOGLE_CHROME_BUILD'],
-      }, {  # else: branding!="Chrome"
-        'defines': ['CHROMIUM_BUILD'],
-      }],
-      ['toolkit_views==1', {
-        'defines': ['TOOLKIT_VIEWS=1'],
-      }],
-      ['chromeos==1', {
-        'defines': ['OS_CHROMEOS=1'],
-      }],
-      ['touchui==1', {
-        'defines': ['TOUCH_UI=1'],
-      }],
-      ['remoting==1', {
-        'defines': ['ENABLE_REMOTING=1'],
-      }],
-      ['proprietary_codecs==1', {
-        'defines': ['USE_PROPRIETARY_CODECS'],
-      }],
-      ['enable_flapper_hacks==1', {
-        'defines': ['ENABLE_FLAPPER_HACKS=1'],
-      }],
-      ['fastbuild!=0', {
-        'conditions': [
-          # For Windows, we don't genererate debug information.
-          ['OS=="win"', {
-            'msvs_settings': {
-              'VCLinkerTool': {
-                'GenerateDebugInformation': 'false',
-              },
-              'VCCLCompilerTool': {
-                'DebugInformationFormat': '0',
-              }
-            }
-          }, { # else: OS != "win", generate less debug information.
-            'variables': {
-              'debug_extra_cflags': '-g1',
-            },
-          }],
-        ],  # conditions for fastbuild.
-      }],  # fastbuild!=0
-      ['selinux==1', {
-        'defines': ['CHROMIUM_SELINUX=1'],
-      }],
-      ['win_use_allocator_shim==0', {
-        'conditions': [
-          ['OS=="win"', {
-            'defines': ['NO_TCMALLOC'],
-          }],
-        ],
-      }],
-      ['enable_gpu==1', {
-        'defines': [
-          'ENABLE_GPU=1',
-        ],
-      }],
-      ['use_openssl==1', {
-        'defines': [
-          'USE_OPENSSL=1',
-        ],
-      }],
-      ['enable_eglimage==1', {
-        'defines': [
-          'ENABLE_EGLIMAGE=1',
-        ],
-      }],
-      ['coverage!=0', {
-        'conditions': [
-          ['OS=="mac"', {
-            'xcode_settings': {
-              'GCC_INSTRUMENT_PROGRAM_FLOW_ARCS': 'YES',  # -fprofile-arcs
-              'GCC_GENERATE_TEST_COVERAGE_FILES': 'YES',  # -ftest-coverage
-            },
-            # Add -lgcov for types executable, shared_library, and
-            # loadable_module; not for static_library.
-            # This is a delayed conditional.
-            'target_conditions': [
-              ['_type!="static_library"', {
-                'xcode_settings': { 'OTHER_LDFLAGS': [ '-lgcov' ] },
-              }],
-            ],
-          }],
-          ['OS=="linux"', {
-            'cflags': [ '-ftest-coverage',
-                        '-fprofile-arcs' ],
-            'link_settings': { 'libraries': [ '-lgcov' ] },
-          }],
-          # Finally, for Windows, we simply turn on profiling.
-          ['OS=="win"', {
-            'msvs_settings': {
-              'VCLinkerTool': {
-                'Profile': 'true',
-              },
-              'VCCLCompilerTool': {
-                # /Z7, not /Zi, so coverage is happyb
-                'DebugInformationFormat': '1',
-                'AdditionalOptions': ['/Yd'],
-              }
-            }
-         }],  # OS==win
-        ],  # conditions for coverage
-      }],  # coverage!=0
-      ['OS=="win"', {
-        'defines': [
-          '__STD_C',
-          '_CRT_SECURE_NO_DEPRECATE',
-          '_SCL_SECURE_NO_DEPRECATE',
-        ],
-        'include_dirs': [
-          '<(DEPTH)/third_party/wtl/include',
-        ],
-      }],  # OS==win
-    ],  # conditions for 'target_defaults'
-    'target_conditions': [
-      ['chromium_code==0', {
-        'conditions': [
-          [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-            'cflags!': [
-              '-Wall',
-              '-Wextra',
-              '-Werror',
-            ],
-          }],
-          [ 'OS=="win"', {
-            'defines': [
-              '_CRT_SECURE_NO_DEPRECATE',
-              '_CRT_NONSTDC_NO_WARNINGS',
-              '_CRT_NONSTDC_NO_DEPRECATE',
-              '_SCL_SECURE_NO_DEPRECATE',
-            ],
-            'msvs_disabled_warnings': [4800],
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                'WarnAsError': 'false',
-                'Detect64BitPortabilityProblems': 'false',
-              },
-            },
-          }],
-          [ 'OS=="mac"', {
-            'xcode_settings': {
-              'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',
-              'WARNING_CFLAGS!': ['-Wall', '-Wextra'],
-            },
-          }],
-        ],
-      }, {
-        # In Chromium code, we define __STDC_FORMAT_MACROS in order to get the
-        # C99 macros on Mac and Linux.
-        'defines': [
-          '__STDC_FORMAT_MACROS',
-        ],
-        'conditions': [
-          ['OS!="win"', {
-            'sources/': [ ['exclude', '_win(_unittest)?\\.(h|cc)$'],
-                          ['exclude', '(^|/)win/'],
-                          ['exclude', '(^|/)win_[^/]*\\.(h|cc)$'] ],
-          }],
-          ['OS!="mac"', {
-            'sources/': [ ['exclude', '_(cocoa|mac)(_unittest)?\\.(h|cc)$'],
-                          ['exclude', '(^|/)(cocoa|mac)/'],
-                          ['exclude', '\\.mm?$' ] ],
-          }],
-          ['OS!="linux" and OS!="freebsd" and OS!="openbsd"', {
-            'sources/': [
-              ['exclude', '_(chromeos|gtk|x|x11|xdg)(_unittest)?\\.(h|cc)$'],
-              ['exclude', '(^|/)gtk/'],
-              ['exclude', '(^|/)(gtk|x11)_[^/]*\\.(h|cc)$'],
-            ],
-          }],
-          ['OS!="linux"', {
-            'sources/': [
-              ['exclude', '_linux(_unittest)?\\.(h|cc)$'],
-              ['exclude', '(^|/)linux/'],
-            ],
-          }],
-          # We use "POSIX" to refer to all non-Windows operating systems.
-          ['OS=="win"', {
-            'sources/': [ ['exclude', '_posix\\.(h|cc)$'] ],
-            # turn on warnings for signed/unsigned mismatch on chromium code.
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                'AdditionalOptions': ['/we4389'],
-              },
-            },
-          }],
-          ['chromeos!=1', {
-            'sources/': [ ['exclude', '_chromeos\\.(h|cc)$'] ]
-          }],
-          ['toolkit_views==0', {
-            'sources/': [ ['exclude', '_views\\.(h|cc)$'] ]
-          }],
-        ],
-      }],
-    ],  # target_conditions for 'target_defaults'
-    'default_configuration': 'Debug',
-    'configurations': {
-      # VCLinkerTool LinkIncremental values below:
-      #   0 == default
-      #   1 == /INCREMENTAL:NO
-      #   2 == /INCREMENTAL
-      # Debug links incremental, Release does not.
-      #
-      # Abstract base configurations to cover common attributes.
-      #
-      'Common_Base': {
-        'abstract': 1,
-        'msvs_configuration_attributes': {
-          'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
-          'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
-          'CharacterSet': '1',
-        },
-      },
-      'x86_Base': {
-        'abstract': 1,
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'TargetMachine': '1',
-          },
-        },
-        'msvs_configuration_platform': 'Win32',
-      },
-      'x64_Base': {
-        'abstract': 1,
-        'msvs_configuration_platform': 'x64',
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'TargetMachine': '17', # x86 - 64
-            'AdditionalLibraryDirectories!':
-              ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
-            'AdditionalLibraryDirectories':
-              ['<(DEPTH)/third_party/platformsdk_win7/files/Lib/x64'],
-          },
-          'VCLibrarianTool': {
-            'AdditionalLibraryDirectories!':
-              ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
-            'AdditionalLibraryDirectories':
-              ['<(DEPTH)/third_party/platformsdk_win7/files/Lib/x64'],
-          },
-        },
-        'defines': [
-          # Not sure if tcmalloc works on 64-bit Windows.
-          'NO_TCMALLOC',
-        ],
-      },
-      'Debug_Base': {
-        'abstract': 1,
-        'defines': ['DYNAMIC_ANNOTATIONS_ENABLED=1'],
-        'xcode_settings': {
-          'COPY_PHASE_STRIP': 'NO',
-          'GCC_OPTIMIZATION_LEVEL': '<(mac_debug_optimization)',
-          'OTHER_CFLAGS': [ '<@(debug_extra_cflags)', ],
-        },
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '<(win_debug_Optimization)',
-            'PreprocessorDefinitions': ['_DEBUG'],
-            'BasicRuntimeChecks': '<(win_debug_RuntimeChecks)',
-            'RuntimeLibrary': '<(win_debug_RuntimeLibrary)',
-            'conditions': [
-              # According to MSVS, InlineFunctionExpansion=0 means
-              # "default inlining", not "/Ob0".
-              # Thus, we have to handle InlineFunctionExpansion==0 separately.
-              ['win_debug_InlineFunctionExpansion==0', {
-                'AdditionalOptions': ['/Ob0'],
-              }],
-              ['win_debug_InlineFunctionExpansion!=""', {
-                'InlineFunctionExpansion':
-                  '<(win_debug_InlineFunctionExpansion)',
-              }],
-              ['win_debug_disable_iterator_debugging==1', {
-                'PreprocessorDefinitions': ['_HAS_ITERATOR_DEBUGGING=0'],
-              }],
-            ],
-          },
-          'VCLinkerTool': {
-            'LinkIncremental': '<(msvs_debug_link_incremental)',
-          },
-          'VCResourceCompilerTool': {
-            'PreprocessorDefinitions': ['_DEBUG'],
-          },
-        },
-        'conditions': [
-          ['OS=="linux"', {
-            'cflags': [
-              '<@(debug_extra_cflags)',
-            ],
-          }],
-        ],
-      },
-      'Release_Base': {
-        'abstract': 1,
-        'defines': [
-          'NDEBUG',
-        ],
-        'xcode_settings': {
-          'DEAD_CODE_STRIPPING': 'YES',  # -Wl,-dead_strip
-          'GCC_OPTIMIZATION_LEVEL': '<(mac_release_optimization)',
-          'OTHER_CFLAGS': [ '<@(release_extra_cflags)', ],
-        },
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '<(win_release_Optimization)',
-            'RuntimeLibrary': '<(win_release_RuntimeLibrary)',
-            'conditions': [
-              # According to MSVS, InlineFunctionExpansion=0 means
-              # "default inlining", not "/Ob0".
-              # Thus, we have to handle InlineFunctionExpansion==0 separately.
-              ['win_release_InlineFunctionExpansion==0', {
-                'AdditionalOptions': ['/Ob0'],
-              }],
-              ['win_release_InlineFunctionExpansion!=""', {
-                'InlineFunctionExpansion':
-                  '<(win_release_InlineFunctionExpansion)',
-              }],
-            ],
-          },
-          'VCLinkerTool': {
-            'LinkIncremental': '1',
-          },
-        },
-        'conditions': [
-          ['release_valgrind_build==0', {
-            'defines': ['NVALGRIND', 'DYNAMIC_ANNOTATIONS_ENABLED=0'],
-          }, {
-            'defines': ['DYNAMIC_ANNOTATIONS_ENABLED=1'],
-          }],
-          ['win_use_allocator_shim==0', {
-            'defines': ['NO_TCMALLOC'],
-          }],
-          ['OS=="linux"', {
-            'cflags': [
-             '<@(release_extra_cflags)',
-            ],
-          }],
-        ],
-      },
-      'Purify_Base': {
-        'abstract': 1,
-        'defines': [
-          'PURIFY',
-          'NO_TCMALLOC',
-        ],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '0',
-            'RuntimeLibrary': '0',
-            'BufferSecurityCheck': 'false',
-          },
-          'VCLinkerTool': {
-            'EnableCOMDATFolding': '1',
-            'LinkIncremental': '1',
-          },
-        },
-      },
-      #
-      # Concrete configurations
-      #
-      'Debug': {
-        'inherit_from': ['Common_Base', 'x86_Base', 'Debug_Base'],
-      },
-      'Release': {
-        'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base'],
-        'conditions': [
-          ['msvs_use_common_release', {
-            'includes': ['release.gypi'],
-          }],
-        ]
-      },
-      'conditions': [
-        [ 'OS=="win"', {
-          # TODO(bradnelson): add a gyp mechanism to make this more graceful.
-          'Purify': {
-            'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base', 'Purify'],
-          },
-          'Debug_x64': {
-            'inherit_from': ['Common_Base', 'x64_Base', 'Debug_Base'],
-          },
-          'Release_x64': {
-            'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base'],
-          },
-          'Purify_x64': {
-            'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base', 'Purify_Base'],
-          },
-        }],
-      ],
-    },
-  },
-  'conditions': [
-    ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
-      'target_defaults': {
-        # Enable -Werror by default, but put it in a variable so it can
-        # be disabled in ~/.gyp/include.gypi on the valgrind builders.
-        'variables': {
-          # Use -fno-strict-aliasing by default since gcc 4.4 has periodic
-          # issues that slip through the cracks. We could do this just for
-          # gcc 4.4 but it makes more sense to be consistent on all
-          # compilers in use. TODO(Craig): turn this off again when
-          # there is some 4.4 test infrastructure in place and existing
-          # aliasing issues have been fixed.
-          'no_strict_aliasing%': 1,
-          'conditions': [['OS=="linux"', {'werror%': '-Werror',}],
-                         ['OS=="freebsd"', {'werror%': '',}],
-                         ['OS=="openbsd"', {'werror%': '',}],
-          ],
-        },
-        'cflags': [
-          '<(werror)',  # See note above about the werror variable.
-          '-pthread',
-          '-fno-exceptions',
-          '-Wall',
-          # TODO(evan): turn this back on once all the builds work.
-          # '-Wextra',
-          # Don't warn about unused function params.  We use those everywhere.
-          '-Wno-unused-parameter',
-          # Don't warn about the "struct foo f = {0};" initialization pattern.
-          '-Wno-missing-field-initializers',
-          '-D_FILE_OFFSET_BITS=64',
-          # Don't export any symbols (for example, to plugins we dlopen()).
-          # Note: this is *required* to make some plugins work.
-          '-fvisibility=hidden',
-          '-pipe',
-        ],
-        'cflags_cc': [
-          '-fno-rtti',
-          '-fno-threadsafe-statics',
-          # Make inline functions have hidden visiblity by default.
-          # Surprisingly, not covered by -fvisibility=hidden.
-          '-fvisibility-inlines-hidden',
-        ],
-        'ldflags': [
-          '-pthread', '-Wl,-z,noexecstack',
-        ],
-        'configurations': {
-          'Debug_Base': {
-            'variables': {
-              'debug_optimize%': '0',
-            },
-            'defines': [
-              '_DEBUG',
-            ],
-            'cflags': [
-              '-O>(debug_optimize)',
-              '-g',
-            ],
-          },
-          'Release_Base': {
-            'variables': {
-              'release_optimize%': '2',
-              # Binaries become big and gold is unable to perform GC
-              # and remove unused sections for some of test targets
-              # on 32 bit platform.
-              # (This is currently observed only in chromeos valgrind bots)
-              # The following flag is to disable --gc-sections linker
-              # option for these bots.
-              'no_gc_sections%': 0,
-            },
-            'cflags': [
-              '-O>(release_optimize)',
-              # Don't emit the GCC version ident directives, they just end up
-              # in the .comment section taking up binary size.
-              '-fno-ident',
-              # Put data and code in their own sections, so that unused symbols
-              # can be removed at link time with --gc-sections.
-              '-fdata-sections',
-              '-ffunction-sections',
-            ],
-            'ldflags': [
-              # Specifically tell the linker to perform optimizations.
-              # See http://lwn.net/Articles/192624/ .
-              '-Wl,-O1',
-              '-Wl,--as-needed',
-            ],
-            'conditions' : [
-              ['no_gc_sections==0', {
-                'ldflags': [
-                  '-Wl,--gc-sections',
-                ],
-              }],
-              ['clang==1', {
-                'cflags!': [
-                  '-fno-ident',
-                ],
-              }],
-            ]
-          },
-        },
-        'variants': {
-          'coverage': {
-            'cflags': ['-fprofile-arcs', '-ftest-coverage'],
-            'ldflags': ['-fprofile-arcs'],
-          },
-          'profile': {
-            'cflags': ['-pg', '-g'],
-            'ldflags': ['-pg'],
-          },
-          'symbols': {
-            'cflags': ['-g'],
-          },
-        },
-        'conditions': [
-          [ 'target_arch=="ia32"', {
-            'asflags': [
-              # Needed so that libs with .s files (e.g. libicudata.a)
-              # are compatible with the general 32-bit-ness.
-              '-32',
-            ],
-            # All floating-point computations on x87 happens in 80-bit
-            # precision.  Because the C and C++ language standards allow
-            # the compiler to keep the floating-point values in higher
-            # precision than what's specified in the source and doing so
-            # is more efficient than constantly rounding up to 64-bit or
-            # 32-bit precision as specified in the source, the compiler,
-            # especially in the optimized mode, tries very hard to keep
-            # values in x87 floating-point stack (in 80-bit precision)
-            # as long as possible. This has important side effects, that
-            # the real value used in computation may change depending on
-            # how the compiler did the optimization - that is, the value
-            # kept in 80-bit is different than the value rounded down to
-            # 64-bit or 32-bit. There are possible compiler options to make
-            # this behavior consistent (e.g. -ffloat-store would keep all
-            # floating-values in the memory, thus force them to be rounded
-            # to its original precision) but they have significant runtime
-            # performance penalty.
-            #
-            # -mfpmath=sse -msse2 makes the compiler use SSE instructions
-            # which keep floating-point values in SSE registers in its
-            # native precision (32-bit for single precision, and 64-bit for
-            # double precision values). This means the floating-point value
-            # used during computation does not change depending on how the
-            # compiler optimized the code, since the value is always kept
-            # in its specified precision.
-            'conditions': [
-              ['branding=="Chromium" and disable_sse2==0', {
-                'cflags': [
-                  '-march=pentium4',
-                  '-msse2',
-                  '-mfpmath=sse',
-                ],
-              }],
-              # ChromeOS targets Pinetrail, which is sse3, but most of the
-              # benefit comes from sse2 so this setting allows ChromeOS
-              # to build on other CPUs.  In the future -march=atom would help
-              # but requires a newer compiler.
-              ['chromeos==1 and disable_sse2==0', {
-                'cflags': [
-                  '-msse2',
-                ],
-              }],
-              # Install packages have started cropping up with
-              # different headers between the 32-bit and 64-bit
-              # versions, so we have to shadow those differences off
-              # and make sure a 32-bit-on-64-bit build picks up the
-              # right files.
-              ['host_arch!="ia32"', {
-                'include_dirs+': [
-                  '/usr/include32',
-                ],
-              }],
-            ],
-            # -mmmx allows mmintrin.h to be used for mmx intrinsics.
-            # video playback is mmx and sse2 optimized.
-            'cflags': [
-              '-m32',
-              '-mmmx',
-            ],
-            'ldflags': [
-              '-m32',
-            ],
-          }],
-          ['target_arch=="arm"', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags_cc': [
-                  # The codesourcery arm-2009q3 toolchain warns at that the ABI
-                  # has changed whenever it encounters a varargs function. This
-                  # silences those warnings, as they are not helpful and
-                  # clutter legitimate warnings.
-                  '-Wno-abi',
-                ],
-                'conditions': [
-                  ['arm_thumb == 1', {
-                    'cflags': [
-                    '-mthumb',
-                    # TODO(piman): -Wa,-mimplicit-it=thumb is needed for
-                    # inline assembly that uses condition codes but it's
-                    # suboptimal. Better would be to #ifdef __thumb__ at the
-                    # right place and have a separate thumb path.
-                    '-Wa,-mimplicit-it=thumb',
-                    ]
-                  }],
-                  ['armv7==1', {
-                    'cflags': [
-                      '-march=armv7-a',
-                      '-mtune=cortex-a8',
-                      '-mfloat-abi=softfp',
-                    ],
-                    'conditions': [
-                      ['arm_neon==1', {
-                        'cflags': [ '-mfpu=neon', ],
-                      }, {
-                        'cflags': [ '-mfpu=<(arm_fpu)', ],
-                      }]
-                    ],
-                  }],
-                ],
-              }],
-            ],
-          }],
-          ['linux_fpic==1', {
-            'cflags': [
-              '-fPIC',
-            ],
-          }],
-          ['sysroot!=""', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '--sysroot=<(sysroot)',
-                ],
-                'ldflags': [
-                  '--sysroot=<(sysroot)',
-                ],
-              }]]
-          }],
-          ['clang==1', {
-            'cflags': [
-              # Don't warn about unused variables, due to a common pattern:
-              #   scoped_deleter unused_variable(&thing_to_delete);
-              '-Wno-unused-variable',
-              # Clang spots more unused functions.
-              '-Wno-unused-function',
-              # gtest confuses clang.
-              '-Wno-bool-conversions',
-              # Don't die on dtoa code that uses a char as an array index.
-              '-Wno-char-subscripts',
-              # Survive EXPECT_EQ(unnamed_enum, unsigned int) -- see
-              # http://code.google.com/p/googletest/source/detail?r=446 .
-              # TODO(thakis): Use -isystem instead (http://crbug.com/58751 ).
-              '-Wno-unnamed-type-template-args',
-            ],
-            'cflags!': [
-              # Clang doesn't seem to know know this flag.
-              '-mfpmath=sse',
-            ],
-          }],
-          ['no_strict_aliasing==1', {
-            'cflags': [
-              '-fno-strict-aliasing',
-            ],
-          }],
-          ['linux_breakpad==1', {
-            'cflags': [ '-g' ],
-            'defines': ['USE_LINUX_BREAKPAD'],
-          }],
-          ['library=="shared_library"', {
-            # When building with shared libraries, remove the visiblity-hiding
-            # flag.
-            'cflags!': [ '-fvisibility=hidden' ],
-            'conditions': [
-              ['target_arch=="x64" or target_arch=="arm"', {
-                # Shared libraries need -fPIC on x86-64 and arm
-                'cflags': ['-fPIC']
-              }]
-            ],
-            'ldflags!': [
-              # --as-needed confuses library interdependencies.
-              # See http://code.google.com/p/chromium/issues/detail?id=61430
-              '-Wl,--as-needed',
-            ],
-          }],
-          ['linux_use_heapchecker==1', {
-            'variables': {'linux_use_tcmalloc%': 1},
-          }],
-          ['linux_use_tcmalloc==0', {
-            'defines': ['NO_TCMALLOC'],
-          }],
-          ['linux_use_heapchecker==0', {
-            'defines': ['NO_HEAPCHECKER'],
-          }],
-          ['linux_keep_shadow_stacks==1', {
-            'defines': ['KEEP_SHADOW_STACKS'],
-            'cflags': ['-finstrument-functions'],
-          }],
-        ],
-      },
-    }],
-    # FreeBSD-specific options; note that most FreeBSD options are set above,
-    # with Linux.
-    ['OS=="freebsd"', {
-      'target_defaults': {
-        'ldflags': [
-          '-Wl,--no-keep-memory',
-        ],
-      },
-    }],
-    ['OS=="solaris"', {
-      'cflags!': ['-fvisibility=hidden'],
-      'cflags_cc!': ['-fvisibility-inlines-hidden'],
-    }],
-    ['OS=="mac"', {
-      'target_defaults': {
-        'variables': {
-          # These should be 'mac_real_dsym%' and 'mac_strip%', but there
-          # seems to be a bug with % in variables that are intended to be
-          # set to different values in different targets, like these two.
-          'mac_strip': 1,      # Strip debugging symbols from the target.
-          'mac_real_dsym': 0,  # Fake .dSYMs are fine in most cases.
-        },
-        'mac_bundle': 0,
-        'xcode_settings': {
-          'ALWAYS_SEARCH_USER_PATHS': 'NO',
-          'GCC_C_LANGUAGE_STANDARD': 'c99',         # -std=c99
-          'GCC_CW_ASM_SYNTAX': 'NO',                # No -fasm-blocks
-          'GCC_DYNAMIC_NO_PIC': 'NO',               # No -mdynamic-no-pic
-                                                    # (Equivalent to -fPIC)
-          'GCC_ENABLE_CPP_EXCEPTIONS': 'NO',        # -fno-exceptions
-          'GCC_ENABLE_CPP_RTTI': 'NO',              # -fno-rtti
-          'GCC_ENABLE_PASCAL_STRINGS': 'NO',        # No -mpascal-strings
-          # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
-          'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
-          'GCC_OBJC_CALL_CXX_CDTORS': 'YES',        # -fobjc-call-cxx-cdtors
-          'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES',      # -fvisibility=hidden
-          'GCC_THREADSAFE_STATICS': 'NO',           # -fno-threadsafe-statics
-          'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES',    # -Werror
-          'GCC_VERSION': '4.2',
-          'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES',  # -Wnewline-eof
-          # MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min
-          'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)',
-          'PREBINDING': 'NO',                       # No -Wl,-prebind
-          'USE_HEADERMAP': 'NO',
-          'WARNING_CFLAGS': [
-            '-Wall',
-            '-Wendif-labels',
-            '-Wextra',
-            # Don't warn about unused function parameters.
-            '-Wno-unused-parameter',
-            # Don't warn about the "struct foo f = {0};" initialization
-            # pattern.
-            '-Wno-missing-field-initializers',
-          ],
-          'conditions': [
-            ['chromium_mac_pch', {'GCC_PRECOMPILE_PREFIX_HEADER': 'YES'},
-                                 {'GCC_PRECOMPILE_PREFIX_HEADER': 'NO'}
-            ],
-            ['clang==1', {
-              'WARNING_CFLAGS': [
-                # Don't die on dtoa code that uses a char as an array index.
-                # This is required solely for base/third_party/dmg_fp/dtoa.cc.
-                '-Wno-char-subscripts',
-                # Clang spots more unused functions.
-                '-Wno-unused-function',
-                # Survive EXPECT_EQ(unnamed_enum, unsigned int) -- see
-                # http://code.google.com/p/googletest/source/detail?r=446 .
-                # TODO(thakis): Use -isystem instead (http://crbug.com/58751 ).
-                '-Wno-unnamed-type-template-args',
-              ],
-            }],
-          ],
-        },
-        'target_conditions': [
-          ['_type!="static_library"', {
-            'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
-          }],
-          ['_mac_bundle', {
-            'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']},
-          }],
-          ['(_type=="executable" or _type=="shared_library" or \
-             _type=="loadable_module") and mac_strip!=0', {
-            'target_conditions': [
-              ['mac_real_dsym == 1', {
-                # To get a real .dSYM bundle produced by dsymutil, set the
-                # debug information format to dwarf-with-dsym.  Since
-                # strip_from_xcode will not be used, set Xcode to do the
-                # stripping as well.
-                'configurations': {
-                  'Release_Base': {
-                    'xcode_settings': {
-                      'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
-                      'DEPLOYMENT_POSTPROCESSING': 'YES',
-                      'STRIP_INSTALLED_PRODUCT': 'YES',
-                      'target_conditions': [
-                        ['_type=="shared_library" or _type=="loadable_module"', {
-                          # The Xcode default is to strip debugging symbols
-                          # only (-S).  Local symbols should be stripped as
-                          # well, which will be handled by -x.  Xcode will
-                          # continue to insert -S when stripping even when
-                          # additional flags are added with STRIPFLAGS.
-                          'STRIPFLAGS': '-x',
-                        }],  # _type=="shared_library" or _type=="loadable_module"'
-                      ],  # target_conditions
-                    },  # xcode_settings
-                  },  # configuration "Release"
-                },  # configurations
-              }, {  # mac_real_dsym != 1
-                # To get a fast fake .dSYM bundle, use a post-build step to
-                # produce the .dSYM and strip the executable.  strip_from_xcode
-                # only operates in the Release configuration.
-                'postbuilds': [
-                  {
-                    'variables': {
-                      # Define strip_from_xcode in a variable ending in _path
-                      # so that gyp understands it's a path and performs proper
-                      # relativization during dict merging.
-                      'strip_from_xcode_path': 'mac/strip_from_xcode',
-                    },
-                    'postbuild_name': 'Strip If Needed',
-                    'action': ['<(strip_from_xcode_path)'],
-                  },
-                ],  # postbuilds
-              }],  # mac_real_dsym
-            ],  # target_conditions
-          }],  # (_type=="executable" or _type=="shared_library" or
-               #  _type=="loadable_module") and mac_strip!=0
-        ],  # target_conditions
-      },  # target_defaults
-    }],  # OS=="mac"
-    ['OS=="win"', {
-      'target_defaults': {
-        'defines': [
-          '_WIN32_WINNT=0x0600',
-          'WINVER=0x0600',
-          'WIN32',
-          '_WINDOWS',
-          'NOMINMAX',
-          '_CRT_RAND_S',
-          'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
-          'WIN32_LEAN_AND_MEAN',
-          '_SECURE_ATL',
-          '_ATL_NO_OPENGL',
-          '_HAS_TR1=0',
-        ],
-        'conditions': [
-          ['component=="static_library"', {
-            'defines': [
-              '_HAS_EXCEPTIONS=0',
-            ],
-          }],
-        ],
-        'msvs_system_include_dirs': [
-          '<(DEPTH)/third_party/platformsdk_win7/files/Include',
-          '<(DEPTH)/third_party/directxsdk/files/Include',
-          '$(VSInstallDir)/VC/atlmfc/include',
-        ],
-        'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'],
-        'msvs_disabled_warnings': [4351, 4396, 4503, 4819],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'MinimalRebuild': 'false',
-            'BufferSecurityCheck': 'true',
-            'EnableFunctionLevelLinking': 'true',
-            'RuntimeTypeInfo': 'false',
-            'WarningLevel': '3',
-            'WarnAsError': 'true',
-            'DebugInformationFormat': '3',
-            'conditions': [
-              [ 'msvs_multi_core_compile', {
-                'AdditionalOptions': ['/MP'],
-              }],
-              ['component=="shared_library"', {
-                'ExceptionHandling': '1',  # /EHsc
-              }, {
-                'ExceptionHandling': '0',
-              }],
-            ],
-          },
-          'VCLibrarianTool': {
-            'AdditionalOptions': ['/ignore:4221'],
-            'AdditionalLibraryDirectories': [
-              '<(DEPTH)/third_party/platformsdk_win7/files/Lib',
-              '<(DEPTH)/third_party/directxsdk/files/Lib/x86',
-            ],
-          },
-          'VCLinkerTool': {
-            'AdditionalDependencies': [
-              'wininet.lib',
-              'version.lib',
-              'msimg32.lib',
-              'ws2_32.lib',
-              'usp10.lib',
-              'psapi.lib',
-              'dbghelp.lib',
-            ],
-            'AdditionalLibraryDirectories': [
-              '<(DEPTH)/third_party/platformsdk_win7/files/Lib',
-              '<(DEPTH)/third_party/directxsdk/files/Lib/x86',
-            ],
-            'GenerateDebugInformation': 'true',
-            'MapFileName': '$(OutDir)\\$(TargetName).map',
-            'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib',
-            'FixedBaseAddress': '1',
-            # SubSystem values:
-            #   0 == not set
-            #   1 == /SUBSYSTEM:CONSOLE
-            #   2 == /SUBSYSTEM:WINDOWS
-            # Most of the executables we'll ever create are tests
-            # and utilities with console output.
-            'SubSystem': '1',
-          },
-          'VCMIDLTool': {
-            'GenerateStublessProxies': 'true',
-            'TypeLibraryName': '$(InputName).tlb',
-            'OutputDirectory': '$(IntDir)',
-            'HeaderFileName': '$(InputName).h',
-            'DLLDataFileName': 'dlldata.c',
-            'InterfaceIdentifierFileName': '$(InputName)_i.c',
-            'ProxyFileName': '$(InputName)_p.c',
-          },
-          'VCResourceCompilerTool': {
-            'Culture' : '1033',
-            'AdditionalIncludeDirectories': [
-              '<(DEPTH)',
-              '<(SHARED_INTERMEDIATE_DIR)',
-            ],
-          },
-        },
-      },
-    }],
-    ['disable_nacl==1 or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
-      'target_defaults': {
-        'defines': [
-          'DISABLE_NACL',
-        ],
-      },
-    }],
-    ['OS=="win" and msvs_use_common_linker_extras', {
-      'target_defaults': {
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'DelayLoadDLLs': [
-              'dbghelp.dll',
-              'dwmapi.dll',
-              'uxtheme.dll',
-            ],
-          },
-        },
-        'configurations': {
-          'x86_Base': {
-            'msvs_settings': {
-              'VCLinkerTool': {
-                'AdditionalOptions': [
-                  '/safeseh',
-                  '/dynamicbase',
-                  '/ignore:4199',
-                  '/ignore:4221',
-                  '/nxcompat',
-                ],
-              },
-            },
-          },
-          'x64_Base': {
-            'msvs_settings': {
-              'VCLinkerTool': {
-                'AdditionalOptions': [
-                  # safeseh is not compatible with x64
-                  '/dynamicbase',
-                  '/ignore:4199',
-                  '/ignore:4221',
-                  '/nxcompat',
-                ],
-              },
-            },
-          },
-        },
-      },
-    }],
-    ['enable_new_npdevice_api==1', {
-      'target_defaults': {
-        'defines': [
-          'ENABLE_NEW_NPDEVICE_API',
-        ],
-      },
-    }],
-  ],
-  'xcode_settings': {
-    # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
-    # This block adds *project-wide* configuration settings to each project
-    # file.  It's almost always wrong to put things here.  Specify your
-    # custom xcode_settings in target_defaults to add them to targets instead.
-
-    # In an Xcode Project Info window, the "Base SDK for All Configurations"
-    # setting sets the SDK on a project-wide basis.  In order to get the
-    # configured SDK to show properly in the Xcode UI, SDKROOT must be set
-    # here at the project level.
-    'SDKROOT': 'macosx<(mac_sdk)',  # -isysroot
-
-    # The Xcode generator will look for an xcode_settings section at the root
-    # of each dict and use it to apply settings on a file-wide basis.  Most
-    # settings should not be here, they should be in target-specific
-    # xcode_settings sections, or better yet, should use non-Xcode-specific
-    # settings in target dicts.  SYMROOT is a special case, because many other
-    # Xcode variables depend on it, including variables such as
-    # PROJECT_DERIVED_FILE_DIR.  When a source group corresponding to something
-    # like PROJECT_DERIVED_FILE_DIR is added to a project, in order for the
-    # files to appear (when present) in the UI as actual files and not red
-    # red "missing file" proxies, the correct path to PROJECT_DERIVED_FILE_DIR,
-    # and therefore SYMROOT, needs to be set at the project level.
-    'SYMROOT': '<(DEPTH)/xcodebuild',
-  },
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/.svn/text-base/compiler_version.py.svn-base b/build/.svn/text-base/compiler_version.py.svn-base
deleted file mode 100644
index 69f0a50..0000000
--- a/build/.svn/text-base/compiler_version.py.svn-base
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/python
-
-# 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.
-
-"""Compiler version checking tool for gcc
-
-Print gcc version as XY if you are running gcc X.Y.*.
-This is used to tweak build flags for gcc 4.4.
-"""
-
-import os
-import re
-import subprocess
-import sys
-
-def GetVersion(compiler):
-  try:
-    # Note that compiler could be something tricky like "distcc g++".
-    compiler = compiler + " -dumpversion"
-    pipe = subprocess.Popen(compiler, stdout=subprocess.PIPE, shell=True)
-    gcc_output = pipe.communicate()[0]
-    result = re.match(r"(\d+)\.(\d+)", gcc_output)
-    return result.group(1) + result.group(2)
-  except Exception, e:
-    print >> sys.stderr, "compiler_version.py failed to execute:", compiler
-    print >> sys.stderr, e
-    return ""
-
-def main():
-  # Check if CXX environment variable exists and
-  # if it does use that compiler.
-  cxx = os.getenv("CXX", None)
-  if cxx:
-    cxxversion = GetVersion(cxx)
-    if cxxversion != "":
-      print cxxversion
-      return 0
-  else:
-    # Otherwise we check the g++ version.
-    gccversion = GetVersion("g++")
-    if gccversion != "":
-      print gccversion
-      return 0
-
-  return 1
-
-if __name__ == "__main__":
-  sys.exit(main())
diff --git a/build/.svn/text-base/dir_exists.py.svn-base b/build/.svn/text-base/dir_exists.py.svn-base
deleted file mode 100644
index d1c194f..0000000
--- a/build/.svn/text-base/dir_exists.py.svn-base
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os.path
-import sys
-
-sys.stdout.write(str(os.path.isdir(sys.argv[1])))
-sys.exit(0)
diff --git a/build/.svn/text-base/extract_from_cab.py.svn-base b/build/.svn/text-base/extract_from_cab.py.svn-base
deleted file mode 100644
index fd99184..0000000
--- a/build/.svn/text-base/extract_from_cab.py.svn-base
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-# Extracts a single file from a CAB archive.
-
-import os
-import subprocess
-import sys
-
-if len(sys.argv) != 4:
-  print 'Usage: extract_from_cab.py cab_path archived_file output_dir'
-  sys.exit(1)
-
-[cab_path, archived_file, output_dir] = sys.argv[1:]
-
-# Invoke the Windows expand utility to extract the file.
-level = subprocess.call(['expand', cab_path, '-F:' + archived_file, output_dir])
-if level != 0:
-  sys.exit(level)
-
-# The expand utility preserves the modification date and time of the archived
-# file. Touch the extracted file. This helps build systems that compare the
-# modification times of input and output files to determine whether to do an
-# action.
-os.utime(os.path.join(output_dir, archived_file), None)
diff --git a/build/.svn/text-base/features_override.gypi.svn-base b/build/.svn/text-base/features_override.gypi.svn-base
deleted file mode 100644
index 770778d..0000000
--- a/build/.svn/text-base/features_override.gypi.svn-base
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file is only included in full-chromium builds, and overrides the
-# feature_defines variable in third_party/WebKit/WebKit/chromium/features.gypi.
-{
-  'variables': {
-    # WARNING: This list of strings completely replaces the list in
-    # features.gypi. Therefore, if an enable is listed in features.gypi
-    # but not listed below, it will revert to its hardcoded webkit value.
-    'feature_defines': [
-      'ENABLE_3D_CANVAS=1',
-      'ENABLE_3D_PLUGIN=1',
-      'ENABLE_BLOB=1',
-      'ENABLE_BLOB_SLICE=1',
-      'ENABLE_CHANNEL_MESSAGING=1',
-      'ENABLE_CLIENT_BASED_GEOLOCATION=1',
-      'ENABLE_DASHBOARD_SUPPORT=0',
-      'ENABLE_DATABASE=1',
-      'ENABLE_DATAGRID=0',
-      'ENABLE_DEVICE_ORIENTATION=1',
-      'ENABLE_DIRECTORY_UPLOAD=1',
-      'ENABLE_DOM_STORAGE=1',
-      'ENABLE_EVENTSOURCE=1',
-      'ENABLE_FILE_SYSTEM=1',
-      'ENABLE_FILTERS=1',
-      'ENABLE_GEOLOCATION=1',
-      'ENABLE_ICONDATABASE=0',
-      'ENABLE_INDEXED_DATABASE=1',
-      'ENABLE_INPUT_SPEECH=1',
-      'ENABLE_JAVASCRIPT_DEBUGGER=1',
-      'ENABLE_JSC_MULTIPLE_THREADS=0',
-      'ENABLE_LINK_PREFETCH=1',
-      'ENABLE_METER_TAG=1',
-      'ENABLE_NOTIFICATIONS=1',
-      'ENABLE_OFFLINE_WEB_APPLICATIONS=1',
-      'ENABLE_OPENTYPE_SANITIZER=1',
-      'ENABLE_ORIENTATION_EVENTS=0',
-      'ENABLE_PROGRESS_TAG=1',
-      'ENABLE_RUBY=1',
-      'ENABLE_SANDBOX=1',
-      'ENABLE_SHARED_WORKERS=1',
-      'ENABLE_SVG=<(enable_svg)',
-      'ENABLE_SVG_ANIMATION=<(enable_svg)',
-      'ENABLE_SVG_AS_IMAGE=<(enable_svg)',
-      'ENABLE_SVG_FONTS=<(enable_svg)',
-      'ENABLE_SVG_FOREIGN_OBJECT=<(enable_svg)',
-      'ENABLE_SVG_USE=<(enable_svg)',
-      'ENABLE_TOUCH_EVENTS=<(enable_touch_events)',
-      'ENABLE_V8_SCRIPT_DEBUG_SERVER=1',
-      'ENABLE_VIDEO=1',
-      'ENABLE_WEB_SOCKETS=1',
-      'ENABLE_WEB_TIMING=1',
-      'ENABLE_WORKERS=1',
-      'ENABLE_XHR_RESPONSE_BLOB=1',
-      'ENABLE_XPATH=1',
-      'ENABLE_XSLT=1',
-      'WTF_USE_WEBP=1',
-      'WTF_USE_WEBKIT_IMAGE_DECODERS=1',
-    ],
-    # We have to nest variables inside variables so that they can be overridden
-    # through GYP_DEFINES.
-    'variables': {
-      'use_accelerated_compositing%': 1,
-      'enable_svg%': 1,
-      'enable_touch_events%': 1,
-    },
-    'use_accelerated_compositing%': '<(use_accelerated_compositing)',
-    'enable_svg%': '<(enable_svg)',
-    'enable_touch_events%': '<(enable_touch_events)',
-    'conditions': [
-      ['(OS=="win" or OS=="linux" or OS=="mac") and use_accelerated_compositing==1', {
-        'feature_defines': [
-          'WTF_USE_ACCELERATED_COMPOSITING=1',
-          'ENABLE_3D_RENDERING=1',
-          'ENABLE_ACCELERATED_2D_CANVAS=1',
-        ],
-        'use_accelerated_compositing': 1,
-      }],
-    ],
-    # TODO: If the need arises, create a mechanism that will intelligently
-    # merge the lists rather than replace one with the other. This may
-    # require changes in gyp.
-  },
-
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/.svn/text-base/gyp_chromium.svn-base b/build/.svn/text-base/gyp_chromium.svn-base
deleted file mode 100644
index 2171770..0000000
--- a/build/.svn/text-base/gyp_chromium.svn-base
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/python
-
-# 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 script is wrapper for Chromium that adds some support for how GYP
-# is invoked by Chromium beyond what can be done in the gclient hooks.
-
-import glob
-import os
-import shlex
-import sys
-
-script_dir = os.path.dirname(__file__)
-chrome_src = os.path.normpath(os.path.join(script_dir, os.pardir))
-
-sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
-import gyp
-
-def apply_gyp_environment(file_path=None):
-  """
-  Reads in a *.gyp_env file and applies the valid keys to os.environ.
-  """
-  if not file_path or not os.path.exists(file_path):
-    return
-  file_contents = open(file_path).read()
-  try:
-    file_data = eval(file_contents, {'__builtins__': None}, None)
-  except SyntaxError, e:
-    e.filename = os.path.abspath(file_path)
-    raise
-  supported_vars = ( 'CHROMIUM_GYP_FILE',
-                     'CHROMIUM_GYP_SYNTAX_CHECK',
-                     'GYP_DEFINES',
-                     'GYP_GENERATOR_FLAGS',
-                     'GYP_GENERATOR_OUTPUT', )
-  for var in supported_vars:
-    val = file_data.get(var)
-    if val:
-      if var in os.environ:
-        print 'INFO: Environment value for "%s" overrides value in %s.' % (
-            var, os.path.abspath(file_path)
-        )
-      else:
-        os.environ[var] = val
-
-def additional_include_files(args=[]):
-  """
-  Returns a list of additional (.gypi) files to include, without
-  duplicating ones that are already specified on the command line.
-  """
-  # Determine the include files specified on the command line.
-  # This doesn't cover all the different option formats you can use,
-  # but it's mainly intended to avoid duplicating flags on the automatic
-  # makefile regeneration which only uses this format.
-  specified_includes = set()
-  for arg in args:
-    if arg.startswith('-I') and len(arg) > 2:
-      specified_includes.add(os.path.realpath(arg[2:]))
-
-  result = []
-  def AddInclude(path):
-    if os.path.realpath(path) not in specified_includes:
-      result.append(path)
-
-  # Always include common.gypi & features_override.gypi
-  AddInclude(os.path.join(script_dir, 'common.gypi'))
-  AddInclude(os.path.join(script_dir, 'features_override.gypi'))
-
-  # Optionally add supplemental .gypi files if present.
-  supplements = glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi'))
-  for supplement in supplements:
-    AddInclude(supplement)
-
-  return result
-
-if __name__ == '__main__':
-  args = sys.argv[1:]
-
-  if 'SKIP_CHROMIUM_GYP_ENV' not in os.environ:
-    # Update the environment based on chromium.gyp_env
-    gyp_env_path = os.path.join(os.path.dirname(chrome_src), 'chromium.gyp_env')
-    apply_gyp_environment(gyp_env_path)
-
-  # This could give false positives since it doesn't actually do real option
-  # parsing.  Oh well.
-  gyp_file_specified = False
-  for arg in args:
-    if arg.endswith('.gyp'):
-      gyp_file_specified = True
-      break
-
-  # If we didn't get a file, check an env var, and then fall back to
-  # assuming 'all.gyp' from the same directory as the script.
-  if not gyp_file_specified:
-    gyp_file = os.environ.get('CHROMIUM_GYP_FILE')
-    if gyp_file:
-      # Note that CHROMIUM_GYP_FILE values can't have backslashes as
-      # path separators even on Windows due to the use of shlex.split().
-      args.extend(shlex.split(gyp_file))
-    else:
-      args.append(os.path.join(script_dir, 'all.gyp'))
-
-  args.extend(['-I' + i for i in additional_include_files(args)])
-
-  # There shouldn't be a circular dependency relationship between .gyp files,
-  # but in Chromium's .gyp files, on non-Mac platforms, circular relationships
-  # currently exist.  The check for circular dependencies is currently
-  # bypassed on other platforms, but is left enabled on the Mac, where a
-  # violation of the rule causes Xcode to misbehave badly.
-  # TODO(mark): Find and kill remaining circular dependencies, and remove this
-  # option.  http://crbug.com/35878.
-  # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the
-  # list.
-  if sys.platform not in ('darwin',):
-    args.append('--no-circular-check')
-
-  # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
-  # to enfore syntax checking.
-  syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK')
-  if syntax_check and int(syntax_check):
-    args.append('--check')
-
-  print 'Updating projects from gyp files...'
-  sys.stdout.flush()
-
-  # Off we go...
-  sys.exit(gyp.main(args))
diff --git a/build/.svn/text-base/install-build-deps.sh.svn-base b/build/.svn/text-base/install-build-deps.sh.svn-base
deleted file mode 100644
index 3ed5513..0000000
--- a/build/.svn/text-base/install-build-deps.sh.svn-base
+++ /dev/null
@@ -1,458 +0,0 @@
-#!/bin/bash -e
-
-# 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.
-
-# Script to install everything needed to build chromium (well, ideally, anyway)
-# See http://code.google.com/p/chromium/wiki/LinuxBuildInstructions
-# and http://code.google.com/p/chromium/wiki/LinuxBuild64Bit
-
-usage() {
-  echo "Usage: $0 [--options]"
-  echo "Options:"
-  echo "--[no-]syms: enable or disable installation of debugging symbols"
-  echo "--[no-]gold: enable or disable installation of gold linker"
-  echo "--[no-]lib32: enable or disable installation of 32 bit libraries"
-  echo "Script will prompt interactively if options not given."
-  exit 1
-}
-
-while test "$1" != ""
-do
-  case "$1" in
-  --syms)     do_inst_syms=1;;
-  --no-syms)  do_inst_syms=0;;
-  --gold)     do_inst_gold=1;;
-  --no-gold)  do_inst_gold=0;;
-  --lib32)    do_inst_lib32=1;;
-  --no-lib32) do_inst_lib32=0;;
-  *) usage;;
-  esac
-  shift
-done
-
-install_gold() {
-  # Gold is optional; it's a faster replacement for ld,
-  # and makes life on 2GB machines much more pleasant.
-
-  # First make sure root can access this directory, as that's tripped
-  # up some folks.
-  if sudo touch xyz.$$
-  then
-    sudo rm xyz.$$
-  else
-    echo root cannot write to the current directory, not installing gold
-    return
-  fi
-
-  BINUTILS=binutils-2.20.1
-  BINUTILS_URL=http://ftp.gnu.org/gnu/binutils/$BINUTILS.tar.bz2
-  BINUTILS_SHA1=fd2ba806e6f3a55cee453cb25c86991b26a75dee
-
-  test -f $BINUTILS.tar.bz2 || wget $BINUTILS_URL
-  if test "`sha1sum $BINUTILS.tar.bz2|cut -d' ' -f1`" != "$BINUTILS_SHA1"
-  then
-    echo Bad sha1sum for $BINUTILS.tar.bz2
-    exit 1
-  fi
-
-  tar -xjvf $BINUTILS.tar.bz2
-  cd $BINUTILS
-  ./configure --prefix=/usr/local/gold --enable-gold
-  make -j3
-  if sudo make install
-  then
-    # Still need to figure out graceful way of pointing gyp to use
-    # /usr/local/gold/bin/ld without requiring him to set environment
-    # variables.  That will go into bootstrap-linux.sh when it's ready.
-    echo "Installing gold as /usr/bin/ld."
-    echo "To uninstall, do 'cd /usr/bin; sudo rm ld; sudo mv ld.orig ld'"
-    test -f /usr/bin/ld && test ! -f /usr/bin/ld.orig && \
-        sudo mv /usr/bin/ld /usr/bin/ld.orig
-    sudo strip /usr/local/gold/bin/ld
-    sudo ln -fs /usr/local/gold/bin/ld /usr/bin/ld.gold
-    sudo ln -fs /usr/bin/ld.gold /usr/bin/ld
-  else
-    echo "make install failed, not installing gold"
-  fi
-}
-
-if ! egrep -q \
-    'Ubuntu (8\.04|8\.10|9\.04|9\.10|10\.04|10\.10|karmic|lucid|maverick)' \
-    /etc/issue; then
-  echo "Only Ubuntu 8.04 (hardy) through 10.10 (maverick) are currently" \
-      "supported" >&2
-  exit 1
-fi
-
-if ! uname -m | egrep -q "i686|x86_64"; then
-  echo "Only x86 architectures are currently supported" >&2
-  exit
-fi
-
-if [ "x$(id -u)" != x0 ]; then
-  echo "Running as non-root user."
-  echo "You might have to enter your password one or more times for 'sudo'."
-  echo
-fi
-
-# Packages needed for chromeos only
-chromeos_dev_list="libpulse-dev"
-
-# Packages need for development
-dev_list="apache2 bison fakeroot flex g++ gperf libapache2-mod-php5
-          libasound2-dev libbz2-dev libcairo2-dev libdbus-glib-1-dev
-          libgconf2-dev libgl1-mesa-dev libglu1-mesa-dev libglib2.0-dev
-          libgnome-keyring-dev libgtk2.0-dev libjpeg62-dev libnspr4-dev
-          libnss3-dev libpam0g-dev libsqlite3-dev libxslt1-dev libxss-dev
-          libxtst-dev lighttpd mesa-common-dev msttcorefonts patch perl
-          php5-cgi pkg-config python python-dev rpm subversion ttf-dejavu-core
-          ttf-kochi-gothic ttf-kochi-mincho wdiff libcurl4-gnutls-dev
-          $chromeos_dev_list"
-
-# Run-time libraries required by chromeos only
-chromeos_lib_list="libpulse0 libbz2-1.0 libcurl4-gnutls-dev"
-
-# Full list of required run-time libraries
-lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libdbus-glib-1-2 libexpat1
-          libfontconfig1 libfreetype6 libglib2.0-0 libgnome-keyring0 libgtk2.0-0
-          libnspr4-0d libnss3-1d libpango1.0-0 libpcre3 libpixman-1-0 libpng12-0
-          libstdc++6 libsqlite3-0 libx11-6 libxau6 libxcb1 libxcomposite1
-          libxcursor1 libxdamage1 libxdmcp6 libxext6 libxfixes3 libxi6
-          libxinerama1 libxrandr2 libxrender1 libxtst6 zlib1g
-          $chromeos_lib_list"
-
-# Debugging symbols for all of the run-time libraries
-dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg
-          libfontconfig1-dbg libglib2.0-0-dbg libgtk2.0-0-dbg libnspr4-0d-dbg
-          libnss3-1d-dbg libpango1.0-0-dbg libpcre3-dbg libpixman-1-0-dbg
-          libx11-6-dbg libxau6-dbg libxcb1-dbg libxcomposite1-dbg
-          libxcursor1-dbg libxdamage1-dbg libxdmcp6-dbg libxext6-dbg
-          libxfixes3-dbg libxi6-dbg libxinerama1-dbg libxrandr2-dbg
-          libxrender1-dbg libxtst6-dbg zlib1g-dbg"
-
-# CUPS package changed its name from hardy to the next version. Include
-# proper package here depending on the system.
-if egrep -q 'Ubuntu (8\.04|8\.10)' /etc/issue; then
-  dev_list="${dev_list} libcupsys2-dev"
-else
-  dev_list="${dev_list} libcups2-dev"
-fi
-
-# Waits for the user to press 'Y' or 'N'. Either uppercase of lowercase is
-# accepted. Returns 0 for 'Y' and 1 for 'N'. If an optional parameter has
-# been provided to yes_no(), the function also accepts RETURN as a user input.
-# The parameter specifies the exit code that should be returned in that case.
-# The function will echo the user's selection followed by a newline character.
-# Users can abort the function by pressing CTRL-C. This will call "exit 1".
-yes_no() {
-  local c
-  while :; do
-    c="$(trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT
-         stty -echo iuclc -icanon 2>/dev/null
-         dd count=1 bs=1 2>/dev/null | od -An -tx1)"
-    case "$c" in
-      " 0a") if [ -n "$1" ]; then
-               [ $1 -eq 0 ] && echo "Y" || echo "N"
-               return $1
-             fi
-             ;;
-      " 79") echo "Y"
-             return 0
-             ;;
-      " 6e") echo "N"
-             return 1
-             ;;
-      "")    echo "Aborted" >&2
-             exit 1
-             ;;
-      *)     # The user pressed an unrecognized key. As we are not echoing
-             # any incorrect user input, alert the user by ringing the bell.
-             (tput bel) 2>/dev/null
-             ;;
-    esac
-  done
-}
-
-if test "$do_inst_syms" = ""
-then
-  echo "This script installs all tools and libraries needed to build Chromium."
-  echo ""
-  echo "For most of the libraries, it can also install debugging symbols, which"
-  echo "will allow you to debug code in the system libraries. Most developers"
-  echo "won't need these symbols."
-  echo -n "Do you want me to install them for you (y/N) "
-  if yes_no 1; then
-    do_inst_syms=1
-  fi
-fi
-if test "$do_inst_syms" = "1"; then
-  echo "Installing debugging symbols."
-else
-  echo "Skipping installation of debugging symbols."
-  dbg_list=
-fi
-
-sudo apt-get update
-
-# We initially run "apt-get" with the --reinstall option and parse its output.
-# This way, we can find all the packages that need to be newly installed
-# without accidentally promoting any packages from "auto" to "manual".
-# We then re-run "apt-get" with just the list of missing packages.
-echo "Finding missing packages..."
-packages="${dev_list} ${lib_list} ${dbg_list}"
-# Intentially leaving $packages unquoted so it's more readable.
-echo "Packages required: " $packages
-echo
-new_list_cmd="sudo apt-get install --reinstall $(echo $packages)"
-if new_list="$(yes n | LANG=C $new_list_cmd)"; then
-  # We probably never hit this following line.
-  echo "No missing packages, and the packages are up-to-date."
-elif [ $? -eq 1 ]; then
-  # We expect apt-get to have exit status of 1.
-  # This indicates that we canceled the install with "yes n|".
-  new_list=$(echo "$new_list" |
-    sed -e '1,/The following NEW packages will be installed:/d;s/^  //;t;d')
-  new_list=$(echo "$new_list" | sed 's/ *$//')
-  if [ -z "$new_list" ] ; then
-    echo "No missing packages, and the packages are up-to-date."
-  else
-    echo "Installing missing packages: $new_list."
-    sudo apt-get install ${new_list}
-  fi
-  echo
-else
-  # An apt-get exit status of 100 indicates that a real error has occurred.
-
-  # I am intentionally leaving out the '"'s around new_list_cmd,
-  # as this makes it easier to cut and paste the output
-  echo "The following command failed: " ${new_list_cmd}
-  echo
-  echo "It produces the following output:"
-  yes n | $new_list_cmd || true
-  echo
-  echo "You will have to install the above packages yourself."
-  echo
-  exit 100
-fi
-
-# Some operating systems already ship gold (on recent Debian and
-# Ubuntu you can do "apt-get install binutils-gold" to get it), but
-# older releases didn't.  Additionally, gold 2.20 (included in Ubuntu
-# Lucid) makes binaries that just segfault.
-# So install from source if we don't have a good version.
-
-case `ld --version` in
-*gold*2.20.1*) ;;
-*gold*2.2[1-9]*) ;;
-* )
-  if test "$do_inst_gold" = ""
-  then
-    echo "Gold is a new linker that links Chrome 5x faster than ld."
-    echo "Don't use it if you need to link other apps (e.g. valgrind, wine)"
-    echo -n "REPLACE SYSTEM LINKER ld with gold and back up ld? (y/N) "
-    if yes_no 1; then
-      do_inst_gold=1
-    fi
-  fi
-  if test "$do_inst_gold" = "1"
-  then
-    # If the system provides a good version of gold, just install it.
-    if apt-cache show binutils-gold | grep -Eq 'Version: 2.2(0.1|[1-9]*)'; then
-      echo "Installing binutils-gold. Backing up ld as ld.single."
-      sudo apt-get install binutils-gold
-    else
-      # FIXME: avoid installing as /usr/bin/ld
-      echo "Building binutils. Backing up ld as ld.orig."
-      install_gold || exit 99
-    fi
-  else
-    echo "Not installing gold."
-  fi
-esac
-
-# Install 32bit backwards compatibility support for 64bit systems
-if [ "$(uname -m)" = "x86_64" ]; then
-  if test "$do_inst_lib32" = ""
-  then
-    echo "Installing 32bit libraries not already provided by the system"
-    echo
-    echo "This is only needed to build a 32-bit Chrome on your 64-bit system."
-    echo
-    echo "While we only need to install a relatively small number of library"
-    echo "files, we temporarily need to download a lot of large *.deb packages"
-    echo "that contain these files. We will create new *.deb packages that"
-    echo "include just the 32bit libraries. These files will then be found on"
-    echo "your system in places like /lib32, /usr/lib32, /usr/lib/debug/lib32,"
-    echo "/usr/lib/debug/usr/lib32. If you ever need to uninstall these files,"
-    echo "look for packages named *-ia32.deb."
-    echo "Do you want me to download all packages needed to build new 32bit"
-    echo -n "package files (Y/n) "
-    if yes_no 0; then
-      do_inst_lib32=1
-    fi
-  fi
-  if test "$do_inst_lib32" != "1"
-  then
-    echo "Exiting without installing any 32bit libraries."
-    exit 0
-  fi
-
-  # Standard 32bit compatibility libraries
-  echo "First, installing the limited existing 32-bit support..."
-  cmp_list="ia32-libs lib32asound2-dev lib32readline5-dev lib32stdc++6 lib32z1
-            lib32z1-dev libc6-dev-i386 libc6-i386 g++-multilib"
-  sudo apt-get install $cmp_list
-
-  tmp=/tmp/install-32bit.$$
-  trap 'rm -rf "${tmp}"' EXIT INT TERM QUIT
-  mkdir -p "${tmp}/apt/lists/partial" "${tmp}/cache" "${tmp}/partial"
-  touch "${tmp}/status"
-
-  [ -r /etc/apt/apt.conf ] && cp /etc/apt/apt.conf "${tmp}/apt/"
-  cat >>"${tmp}/apt/apt.conf" <<EOF
-        Apt::Architecture "i386";
-        Dir::Cache "${tmp}/cache";
-        Dir::Cache::Archives "${tmp}/";
-        Dir::State::Lists "${tmp}/apt/lists/";
-        Dir::State::status "${tmp}/status";
-EOF
-
-  # Download 32bit packages
-  echo "Computing list of available 32bit packages..."
-  sudo apt-get -c="${tmp}/apt/apt.conf" update
-
-  echo "Downloading available 32bit packages..."
-  sudo apt-get -c="${tmp}/apt/apt.conf" \
-          --yes --download-only --force-yes --reinstall install \
-          ${lib_list} ${dbg_list}
-
-  # Open packages, remove everything that is not a library, move the
-  # library to a lib32 directory and package everything as a *.deb file.
-  echo "Repackaging and installing 32bit packages for use on 64bit systems..."
-  for i in ${lib_list} ${dbg_list}; do
-    orig="$(echo "${tmp}/${i}"_*_i386.deb)"
-    compat="$(echo "${orig}" |
-              sed -e 's,\(_[^_/]*_\)i386\(.deb\),-ia32\1amd64\2,')"
-    rm -rf "${tmp}/staging"
-    msg="$(fakeroot -u sh -exc '
-      # Unpack 32bit Debian archive
-      umask 022
-      mkdir -p "'"${tmp}"'/staging/dpkg/DEBIAN"
-      cd "'"${tmp}"'/staging"
-      ar x "'${orig}'"
-      tar zCfx dpkg data.tar.gz
-      tar zCfx dpkg/DEBIAN control.tar.gz
-
-      # Create a posix extended regular expression fragment that will
-      # recognize the includes which have changed. Should be rare,
-      # will almost always be empty.
-      includes=`sed -n -e "s/^[0-9a-z]*  //g" \
-                       -e "\,usr/include/,p" dpkg/DEBIAN/md5sums |
-                  xargs -n 1 -I FILE /bin/sh -c \
-                    "cmp -s dpkg/FILE /FILE || echo FILE" |
-                  tr "\n" "|" |
-                  sed -e "s,|$,,"`
-
-      # If empty, set it to not match anything.
-      test -z "$includes" && includes="^//"
-
-      # Turn the conflicts into an extended RE for removal from the
-      # Provides line.
-      conflicts=`sed -n -e "/Conflicts/s/Conflicts: *//;T;s/, */|/g;p" \
-                   dpkg/DEBIAN/control`
-
-      # Rename package, change architecture, remove conflicts and dependencies
-      sed -r -i                              \
-          -e "/Package/s/$/-ia32/"           \
-          -e "/Architecture/s/:.*$/: amd64/" \
-          -e "/Depends/s/:.*/: ia32-libs/"   \
-          -e "/Provides/s/($conflicts)(, *)?//g;T1;s/, *$//;:1"   \
-          -e "/Recommends/d"                 \
-          -e "/Conflicts/d"                  \
-        dpkg/DEBIAN/control
-
-      # Only keep files that live in "lib" directories or the includes
-      # that have changed.
-      sed -r -i                                                               \
-          -e "/\/lib64\//d" -e "/\/.?bin\//d"                                 \
-          -e "\,$includes,s,[ /]include/,&32/,g;s,include/32/,include32/,g"   \
-          -e "s, lib/, lib32/,g"                                              \
-          -e "s,/lib/,/lib32/,g"                                              \
-          -e "t;d"                                                            \
-          -e "\,^/usr/lib32/debug\(.*/lib32\),s,^/usr/lib32/debug,/usr/lib/debug," \
-        dpkg/DEBIAN/md5sums
-
-      # Re-run ldconfig after installation/removal
-      { echo "#!/bin/sh"; echo "[ \"x\$1\" = xconfigure ]&&ldconfig||:"; } \
-        >dpkg/DEBIAN/postinst
-      { echo "#!/bin/sh"; echo "[ \"x\$1\" = xremove ]&&ldconfig||:"; } \
-        >dpkg/DEBIAN/postrm
-      chmod 755 dpkg/DEBIAN/postinst dpkg/DEBIAN/postrm
-
-      # Remove any other control files
-      find dpkg/DEBIAN -mindepth 1 "(" -name control -o -name md5sums -o \
-                       -name postinst -o -name postrm ")" -o -print |
-        xargs -r rm -rf
-
-      # Remove any files/dirs that live outside of "lib" directories,
-      # or are not in our list of changed includes.
-      find dpkg -mindepth 1 -regextype posix-extended \
-          "(" -name DEBIAN -o -name lib -o -regex "dpkg/($includes)" ")" \
-          -prune -o -print | tac |
-        xargs -r -n 1 sh -c "rm \$0 2>/dev/null || rmdir \$0 2>/dev/null || : "
-      find dpkg -name lib64 -o -name bin -o -name "?bin" |
-        tac | xargs -r rm -rf
-
-      # Remove any symbolic links that were broken by the above steps.
-      find -L dpkg -type l -print | tac | xargs -r rm -rf
-
-      # Rename lib to lib32, but keep debug symbols in /usr/lib/debug/usr/lib32
-      # That is where gdb looks for them.
-      find dpkg -type d -o -path "*/lib/*" -print |
-        xargs -r -n 1 sh -c "
-          i=\$(echo \"\${0}\" |
-               sed -e s,/lib/,/lib32/,g \
-               -e s,/usr/lib32/debug\\\\\(.*/lib32\\\\\),/usr/lib/debug\\\\1,);
-          mkdir -p \"\${i%/*}\";
-          mv \"\${0}\" \"\${i}\""
-
-      # Rename include to include32.
-      [ -d "dpkg/usr/include" ] && mv "dpkg/usr/include" "dpkg/usr/include32"
-
-      # Prune any empty directories
-      find dpkg -type d | tac | xargs -r -n 1 rmdir 2>/dev/null || :
-
-      # Create our own Debian package
-      cd ..
-      dpkg --build staging/dpkg .' 2>&1)"
-    compat="$(eval echo $(echo "${compat}" |
-                          sed -e 's,_[^_/]*_amd64.deb,_*_amd64.deb,'))"
-    [ -r "${compat}" ] || {
-      echo "${msg}" >&2
-      echo "Failed to build new Debian archive!" >&2
-      exit 1
-    }
-
-    msg="$(sudo dpkg -i "${compat}" 2>&1)" && {
-        echo "Installed ${compat##*/}"
-      } || {
-        # echo "${msg}" >&2
-        echo "Skipped ${compat##*/}"
-      }
-  done
-
-  # Add symbolic links for developing 32bit code
-  echo "Adding missing symbolic links, enabling 32bit code development..."
-  for i in $(find /lib32 /usr/lib32 -maxdepth 1 -name \*.so.\* |
-             sed -e 's/[.]so[.][0-9].*/.so/' |
-             sort -u); do
-    [ "x${i##*/}" = "xld-linux.so" ] && continue
-    [ -r "$i" ] && continue
-    j="$(ls "$i."* | sed -e 's/.*[.]so[.]\([^.]*\)$/\1/;t;d' |
-         sort -n | tail -n 1)"
-    [ -r "$i.$j" ] || continue
-    sudo ln -s "${i##*/}.$j" "$i"
-  done
-fi
diff --git a/build/.svn/text-base/install-chroot.sh.svn-base b/build/.svn/text-base/install-chroot.sh.svn-base
deleted file mode 100644
index b80aea0..0000000
--- a/build/.svn/text-base/install-chroot.sh.svn-base
+++ /dev/null
@@ -1,325 +0,0 @@
-#!/bin/bash -e
-
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script installs Debian-derived distributions in a chroot environment.
-# It can for example be used to have an accurate 32bit build and test
-# environment when otherwise working on a 64bit machine.
-# N. B. it is unlikely that this script will ever work on anything other than a
-# Debian-derived system.
-
-usage() {
-  echo "usage: ${0##*/} [-m mirror] [-g group,...] [-s] [-c]"
-  echo "-g group,... groups that can use the chroot unauthenticated"
-  echo "             Default: 'admin' and current user's group ('$(id -gn)')"
-  echo "-m mirror    an alternate repository mirror for package downloads"
-  echo "-s           configure default deb-srcs"
-  echo "-c           always copy 64bit helper binaries to 32bit chroot"
-  echo "-h           this help message"
-}
-
-process_opts() {
-  local OPTNAME OPTIND OPTERR OPTARG
-  while getopts ":g:m:sch" OPTNAME; do
-    case "$OPTNAME" in
-      g)
-        [ -n "${OPTARG}" ] &&
-          chroot_groups="${chroot_groups}${chroot_groups:+,}${OPTARG}"
-        ;;
-      m)
-        if [ -n "${mirror}" ]; then
-          echo "You can only specify exactly one mirror location"
-          usage
-          exit 1
-        fi
-        mirror="$OPTARG"
-        ;;
-      s)
-        add_srcs="y"
-        ;;
-      c)
-        copy_64="y"
-        ;;
-      h)
-        usage
-        exit 0
-        ;;
-      \:)
-        echo "'-$OPTARG' needs an argument."
-        usage
-        exit 1
-        ;;
-      *)
-        echo "invalid command-line option: $OPTARG"
-        usage
-        exit 1
-        ;;
-    esac
-  done
-
-  if [ $# -ge ${OPTIND} ]; then
-    eval echo "Unexpected command line argument: \${${OPTIND}}"
-    usage
-    exit 1
-  fi
-}
-
-
-# Check that we are running as a regular user
-[ "$(id -nu)" = root ] && {
-  echo "Run this script as a regular user and provide your \"sudo\""           \
-       "password if requested" >&2
-  exit 1
-}
-mkdir -p "$HOME/chroot/"
-
-process_opts "$@"
-
-# Error handler
-trap 'exit 1' INT TERM QUIT
-trap 'sudo apt-get clean; tput bel; echo; echo Failed' EXIT
-
-# Install any missing applications that this script relies on. If these packages
-# are already installed, don't force another "apt-get install". That would
-# prevent them from being auto-removed, if they ever become eligible for that.
-# And as this script only needs the packages once, there is no good reason to
-# introduce a hard dependency on things such as dchroot and debootstrap.
-dep=
-for i in dchroot debootstrap; do
-  [ -d /usr/share/doc/"$i" ] || dep="$dep $i"
-done
-[ -n "$dep" ] && sudo apt-get -y install $dep
-sudo apt-get -y install schroot
-
-# Create directory for chroot
-sudo mkdir -p /var/lib/chroot
-
-# Find chroot environments that can be installed with debootstrap
-targets="$(cd /usr/share/debootstrap/scripts
-           ls | grep '^[a-z]*$')"
-
-# Ask user to pick one of the available targets
-echo "The following targets are available to be installed in a chroot:"
-j=1; for i in $targets; do
-  printf '%4d: %s\n' "$j" "$i"
-  j=$(($j+1))
-done
-while :; do
-  printf "Which target would you like to install: "
-  read n
-  [ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev/null && break
-done
-j=1; for i in $targets; do
-  [ "$j" -eq "$n" ] && { distname="$i"; break; }
-  j=$(($j+1))
-done
-
-# On x86-64, ask whether the user wants to install x86-32 or x86-64
-archflag=
-arch=
-if [ "$(uname -m)" = x86_64 ]; then
-  while :; do
-    echo "You are running a 64bit kernel. This allows you to install either a"
-    printf "32bit or a 64bit chroot environment. %s"                           \
-           "Which one do you want (32, 64) "
-    read arch
-    [ "${arch}" == 32 -o "${arch}" == 64 ] && break
-  done
-  [ "${arch}" == 32 ] && archflag="--arch i386" || archflag="--arch amd64"
-  arch="${arch}bit"
-fi
-target="${distname}${arch}"
-
-# Don't overwrite an existing installation
-[ -d /var/lib/chroot/"${target}" ] && {
-  echo "This chroot already exists on your machine." >&2
-  echo "Delete /var/lib/chroot/${target} if you want to start over." >&2
-  exit 1
-}
-sudo mkdir -p /var/lib/chroot/"${target}"
-
-# Offer to include additional standard repositories for Ubuntu-based chroots.
-alt_repos=
-grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null && {
-  while :; do
-    echo "Would you like to add ${distname}-updates and ${distname}-security "
-    echo -n "to the chroot's sources.list (y/n)? "
-    read alt_repos
-    case "${alt_repos}" in
-      y|Y)
-        alt_repos="y"
-        break
-      ;;
-      n|N)
-        break
-      ;;
-    esac
-  done
-}
-
-# Remove stale entry from /etc/schroot/schroot.conf. Entries start
-# with the target name in square brackets, followed by an arbitrary
-# number of lines. The entry stops when either the end of file has
-# been reached, or when the beginning of a new target is encountered.
-# This means, we cannot easily match for a range of lines in
-# "sed". Instead, we actually have to iterate over each line and check
-# whether it is the beginning of a new entry.
-sudo sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p'       \
-         /etc/schroot/schroot.conf
-
-# Download base system. This takes some time
-if [ -z "${mirror}" ]; then
- grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null &&
-   mirror="http://archive.ubuntu.com/ubuntu" ||
-   mirror="http://ftp.us.debian.org/debian"
-fi
- sudo debootstrap ${archflag} "${distname}" /var/lib/chroot/"${target}"        \
-                  "$mirror"
-
-# Add new entry to /etc/schroot/schroot.conf
-grep ubuntu.com /usr/share/debootstrap/scripts/"${distname}" >&/dev/null &&
-  brand="Ubuntu" || brand="Debian"
-if [ -z "${chroot_groups}" ]; then
-  chroot_groups="admin,$(id -gn)"
-fi
-sudo sh -c 'cat >>/etc/schroot/schroot.conf' <<EOF
-[${target%bit}]
-description=${brand} ${distname} ${arch}
-type=directory
-directory=/var/lib/chroot/${target}
-priority=3
-users=root
-groups=${chroot_groups}
-root-groups=${chroot_groups}
-personality=linux$([ "${arch}" != 64bit ] && echo 32)
-script-config=script-${target}
-
-EOF
-
-# Set up a special directory that changes contents depending on the target
-# that is executing.
-sed '/^FSTAB=/s,/mount-defaults",/mount-'"${target}"'",'                       \
-         /etc/schroot/script-defaults |
-  sudo sh -c 'cat >/etc/schroot/script-'"${target}"
-sudo cp /etc/schroot/mount-defaults /etc/schroot/mount-"${target}"
-echo "$HOME/chroot/.${target} $HOME/chroot none rw,bind 0 0" |
-  sudo sh -c 'cat >>/etc/schroot/mount-'"${target}"
-mkdir -p "$HOME/chroot/.${target}"
-
-# Install a helper script to launch commands in the chroot
-sudo sh -c 'cat >/usr/local/bin/'"${target%bit}" <<EOF
-#!/bin/bash
-if [ \$# -eq 0 ]; then
-  exec schroot -c ${target%bit} -p
-else
-  p="\$1"; shift
-  exec schroot -c ${target%bit} -p "\$p" -- "\$@"
-fi
-exit 1
-EOF
-sudo chown root:root /usr/local/bin/"${target%bit}"
-sudo chmod 755 /usr/local/bin/"${target%bit}"
-
-# Add the standard Ubuntu update repositories if requested.
-[ "${alt_repos}" = "y" -a \
-  -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
-sudo sed -i '/^deb .* [^ -]\+ main$/p
-             s/^\(deb .* [^ -]\+\) main/\1-security main/
-             p
-             t1
-             d
-             :1;s/-security main/-updates main/
-             t
-             d' "/var/lib/chroot/${target}/etc/apt/sources.list"
-
-# Add a few more repositories to the chroot
-[ "${add_srcs}" = "y" -a \
-  -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
-sudo sed -i 's/ main$/ main restricted universe multiverse/
-             p
-             t1
-             d
-          :1;s/^deb/deb-src/
-             t
-             d' "/var/lib/chroot/${target}/etc/apt/sources.list"
-
-# Update packages
-sudo schroot -c "${target%bit}" -p -- /bin/sh -c '
-  apt-get update; apt-get -y dist-upgrade' || :
-
-# Install a couple of missing packages
-for i in debian-keyring ubuntu-keyring locales sudo; do
-  [ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] ||
-    sudo schroot -c "${target%bit}" -p -- apt-get -y install "$i" || :
-done
-
-# Configure locales
-sudo schroot -c "${target%bit}" -p -- /bin/sh -c '
-  l='"${LANG:-en_US}"'; l="${l%%.*}"
-  [ -r /etc/locale.gen ] &&
-    sed -i "s/^# \($l\)/\1/" /etc/locale.gen
-  locale-gen $LANG en_US en_US.UTF-8' || :
-
-# Configure "sudo" package
-sudo schroot -c "${target%bit}" -p -- /bin/sh -c '
-  egrep '"'^$(id -nu) '"' /etc/sudoers >/dev/null 2>&1 ||
-  echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers'
-
-# Install a few more commonly used packages
-sudo schroot -c "${target%bit}" -p -- apt-get -y install                       \
-  autoconf automake1.9 dpkg-dev g++-multilib gcc-multilib gdb less libtool     \
-  strace
-
-# If running a 32bit environment on a 64bit machine, install a few binaries
-# as 64bit. This is only done automatically if the chroot distro is the same as
-# the host, otherwise there might be incompatibilities in build settings or
-# runtime dependencies. The user can force it with the '-c' flag.
-host_distro=$(grep DISTRIB_CODENAME /etc/lsb-release 2>/dev/null | \
-  cut -d "=" -f 2)
-if [ "${copy_64}" = "y" -o \
-    "${host_distro}" = "${distname}" -a "${arch}" = 32bit ] && \
-    file /bin/bash 2>/dev/null | grep -q x86-64; then
-  readlinepkg=$(sudo schroot -c "${target%bit}" -p -- sh -c \
-    'apt-cache search "lib64readline.\$" | sort | tail -n 1 | cut -d " " -f 1')
-  sudo schroot -c "${target%bit}" -p -- apt-get -y install                     \
-    lib64expat1 lib64ncurses5 ${readlinepkg} lib64z1
-  dep=
-  for i in binutils gdb strace; do
-    [ -d /usr/share/doc/"$i" ] || dep="$dep $i"
-  done
-  [ -n "$dep" ] && sudo apt-get -y install $dep
-  sudo cp /usr/bin/gdb "/var/lib/chroot/${target}/usr/local/bin/"
-  sudo cp /usr/bin/ld "/var/lib/chroot/${target}/usr/local/bin/"
-  for i in libbfd libpython; do
-    lib="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } |
-           grep "$i" | awk '{ print $3 }')"
-    if [ -n "$lib" -a -r "$lib" ]; then
-      sudo cp "$lib" "/var/lib/chroot/${target}/usr/lib64/"
-    fi
-  done
-  for lib in libssl libcrypt; do
-    sudo cp /usr/lib/$lib* "/var/lib/chroot/${target}/usr/lib64/" || :
-  done
-fi
-
-# Clean up package files
-sudo schroot -c "${target%bit}" -p -- apt-get clean
-sudo apt-get clean
-
-# Let the user know what we did
-trap '' INT TERM QUIT
-trap '' EXIT
-cat <<EOF
-
-
-Successfully installed ${distname} ${arch}
-
-You can run programs inside of the chroot by invoking the "${target%bit}"
-command.
-
-Your home directory is shared between the host and the chroot. But I configured
-$HOME/chroot to be private to the chroot environment. You can use it
-for files that need to differ between environments.
-EOF
diff --git a/build/.svn/text-base/output_dll_copy.rules.svn-base b/build/.svn/text-base/output_dll_copy.rules.svn-base
deleted file mode 100644
index c6e9051..0000000
--- a/build/.svn/text-base/output_dll_copy.rules.svn-base
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<VisualStudioToolFile
-	Name="Output DLL copy"
-	Version="8.00"
-	>
-	<Rules>
-		<CustomBuildRule
-			Name="Output DLL copy"
-			CommandLine="xcopy /R /C /Y $(InputPath) $(OutDir)"
-			Outputs="$(OutDir)\$(InputFileName)"
-			FileExtensions="*.dll"
-			>
-			<Properties>
-			</Properties>
-		</CustomBuildRule>
-	</Rules>
-</VisualStudioToolFile>
diff --git a/build/.svn/text-base/release.gypi.svn-base b/build/.svn/text-base/release.gypi.svn-base
deleted file mode 100644
index c12526b..0000000
--- a/build/.svn/text-base/release.gypi.svn-base
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  'conditions': [
-    # Handle build types.
-    ['buildtype=="Dev"', {
-      'includes': ['internal/release_impl.gypi'],
-    }],
-    ['buildtype=="Official"', {
-      'includes': ['internal/release_impl_official.gypi'],
-    }],
-    # TODO(bradnelson): may also need:
-    #     checksenabled
-    #     coverage
-    #     dom_stats
-    #     pgo_instrument
-    #     pgo_optimize
-    #     purify
-  ],
-}
-
diff --git a/build/.svn/text-base/sanitize-mac-build-log.sed.svn-base b/build/.svn/text-base/sanitize-mac-build-log.sed.svn-base
deleted file mode 100644
index d6cef78..0000000
--- a/build/.svn/text-base/sanitize-mac-build-log.sed.svn-base
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/echo Use sanitize-mac-build-log.sh or sed -f
-
-# 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.
-
-# Use this sed script to reduce a Mac build log into something readable.
-
-# Drop uninformative lines.
-/^distcc/d
-/^Check dependencies/d
-/^    setenv /d
-/^    cd /d
-/^make: Nothing to be done/d
-
-# Xcode prints a short "compiling foobar.o" line followed by the lengthy
-# full command line.  These deletions drop the command line.
-\|^    /Developer/usr/bin/|d
-
-# Shorten the "compiling foobar.o" line.
-s|^Distributed-CompileC \(.*\) normal i386 c++ com.apple.compilers.gcc.4_2|    CC \1|
-s|^CompileC \(.*\) normal i386 c++ com.apple.compilers.gcc.4_2|    CC \1|
diff --git a/build/.svn/text-base/sanitize-mac-build-log.sh.svn-base b/build/.svn/text-base/sanitize-mac-build-log.sh.svn-base
deleted file mode 100644
index dc743fa..0000000
--- a/build/.svn/text-base/sanitize-mac-build-log.sh.svn-base
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-# 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.
-sed -f `dirname "${0}"`/`basename "${0}" sh`sed
-
diff --git a/build/.svn/text-base/sanitize-win-build-log.sed.svn-base b/build/.svn/text-base/sanitize-win-build-log.sed.svn-base
deleted file mode 100644
index d6d049c..0000000
--- a/build/.svn/text-base/sanitize-win-build-log.sed.svn-base
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/echo Use sanitize-win-build-log.sh or sed -f
-
-# 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.
-
-# Use this sed script to reduce a Windows build log into something
-# machine-parsable.
-
-# Drop uninformative lines.
-/The operation completed successfully./d
-
-# Drop parallelization indicators on lines.
-s/^[0-9]\+>//
diff --git a/build/.svn/text-base/sanitize-win-build-log.sh.svn-base b/build/.svn/text-base/sanitize-win-build-log.sh.svn-base
deleted file mode 100644
index dc743fa..0000000
--- a/build/.svn/text-base/sanitize-win-build-log.sh.svn-base
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-# 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.
-sed -f `dirname "${0}"`/`basename "${0}" sh`sed
-
diff --git a/build/.svn/text-base/whitespace_file.txt.svn-base b/build/.svn/text-base/whitespace_file.txt.svn-base
deleted file mode 100644
index ccedfae..0000000
--- a/build/.svn/text-base/whitespace_file.txt.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-Copyright (c) 2010 The Chromium Authors. All rights reserved.
-Use of this useless file is governed by a BSD-style license that can be
-found in the LICENSE file.
-
-This file is used for making non-code changes to trigger buildbot cycles. Make
-any modification below this line.
-================================================================================
-
-i am somewhat YELLY!
diff --git a/build/all.gyp b/build/all.gyp
index ba9bc45..52d1238 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -13,7 +13,7 @@
         '../base/base.gyp:*',
         '../chrome/browser/sync/tools/sync_tools.gyp:*',
         '../chrome/chrome.gyp:*',
-        '../gfx/gfx.gyp:*',
+        '../ui/gfx/gfx.gyp:*',
         '../gpu/gpu.gyp:*',
         '../gpu/demos/demos.gyp:*',
         '../ipc/ipc.gyp:*',
@@ -44,9 +44,8 @@
         '../third_party/ots/ots.gyp:*',
         '../third_party/qcms/qcms.gyp:*',
         '../third_party/sqlite/sqlite.gyp:*',
-        '../third_party/WebKit/WebKit/chromium/WebKit.gyp:*',
+        '../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:*',
         '../third_party/zlib/zlib.gyp:*',
-        '../ui/ui.gyp:*',
         '../webkit/support/webkit_support.gyp:*',
         '../webkit/webkit.gyp:*',
         'util/build_util.gyp:*',
@@ -105,7 +104,6 @@
           'dependencies': [
             '../breakpad/breakpad.gyp:*',
             '../chrome/app/locales/locales.gyp:*',
-            '../ceee/ceee.gyp:*',
             '../chrome_frame/chrome_frame.gyp:*',
             '../courgette/courgette.gyp:*',
             '../gears/gears.gyp:*',
@@ -143,7 +141,7 @@
           ],
         }],
       ],
-    },
+    }, # target_name: All
     {
       'target_name': 'chromium_builder_tests',
       'type': 'none',
@@ -159,7 +157,7 @@
         '../chrome/chrome.gyp:sync_unit_tests',
         '../chrome/chrome.gyp:ui_tests',
         '../chrome/chrome.gyp:unit_tests',
-        '../gfx/gfx.gyp:gfx_unittests',
+        '../ui/gfx/gfx.gyp:gfx_unittests',
         '../gpu/gpu.gyp:gpu_unittests',
         '../ipc/ipc.gyp:ipc_tests',
         '../jingle/jingle.gyp:notifier_unit_tests',
@@ -189,7 +187,7 @@
             '../sandbox/sandbox.gyp:sbox_unittests',
             '../sandbox/sandbox.gyp:sbox_validation_tests',
             '../views/views.gyp:views_unittests',
-            '../third_party/WebKit/WebKit/chromium/WebKit.gyp:copy_TestNetscapePlugIn',
+            '../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:copy_TestNetscapePlugIn',
             # TODO(nsylvain) ui_tests.exe depends on test_shell_common.
             # This should:
             # 1) not be the case. OR.
@@ -198,15 +196,42 @@
            ],
         }],
       ],
-    },
+    }, # target_name: chromium_builder_tests
+    {
+      'target_name': 'chromium_builder_perf',
+      'type': 'none',
+      'dependencies': [
+        '../chrome/chrome.gyp:memory_test',
+        '../chrome/chrome.gyp:page_cycler_tests',
+        '../chrome/chrome.gyp:plugin_tests',
+        '../chrome/chrome.gyp:startup_tests',
+        '../chrome/chrome.gyp:tab_switching_test',
+        '../chrome/chrome.gyp:ui_tests', # needed for dromaeo, sunspider, v8
+        '../chrome/chrome.gyp:url_fetch_test',
+      ],
+    }, # target_name: chromium_builder_perf
     {
       'target_name': 'chromium_gpu_builder',
       'type': 'none',
       'dependencies': [
         '../chrome/chrome.gyp:gpu_tests',
-        '../third_party/WebKit/WebKit/chromium/WebKit.gyp:DumpRenderTree',
+        '../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:DumpRenderTree',
       ],
-    }
+    }, # target_name: chromium_gpu_builder
+    {
+      'target_name': 'chromium_builder_qa',
+      'type': 'none',
+      'dependencies': [
+        '../chrome/chrome.gyp:chromedriver',
+      ],
+      'conditions': [
+        ['OS=="mac" or OS=="win" or (OS=="linux" and target_arch==python_arch)', {
+          'dependencies': [
+            '../chrome/chrome.gyp:pyautolib',
+          ],
+        }], # 'OS=="mac" or OS=="win" or (OS=="linux" and target_arch==python_arch)'
+      ],
+    }, # target_name: chromium_builder_qa
   ],
   'conditions': [
     ['OS=="mac"', {
@@ -237,7 +262,7 @@
             '../chrome/chrome.gyp:sync_unit_tests',
             '../chrome/chrome.gyp:ui_tests',
             '../chrome/chrome.gyp:unit_tests',
-            '../gfx/gfx.gyp:gfx_unittests',
+            '../ui/gfx/gfx.gyp:gfx_unittests',
             '../gpu/gpu.gyp:gpu_unittests',
             '../ipc/ipc.gyp:ipc_tests',
             '../jingle/jingle.gyp:notifier_unit_tests',
@@ -267,7 +292,7 @@
             '../chrome/chrome.gyp:ui_tests',
             '../chrome/chrome.gyp:unit_tests',
             '../chrome/chrome.gyp:url_fetch_test',
-            '../gfx/gfx.gyp:gfx_unittests',
+            '../ui/gfx/gfx.gyp:gfx_unittests',
             '../gpu/gpu.gyp:gpu_unittests',
             '../ipc/ipc.gyp:ipc_tests',
             '../jingle/jingle.gyp:notifier_unit_tests',
@@ -345,8 +370,14 @@
             # mini_installer_tests depends on mini_installer. This should be
             # defined in installer.gyp.
             '../chrome/installer/mini_installer.gyp:mini_installer',
+            '../chrome_frame/chrome_frame.gyp:chrome_frame_net_tests',
+            '../chrome_frame/chrome_frame.gyp:chrome_frame_perftests',
+            '../chrome_frame/chrome_frame.gyp:chrome_frame_reliability_tests',
+            '../chrome_frame/chrome_frame.gyp:chrome_frame_tests',
+            '../chrome_frame/chrome_frame.gyp:chrome_frame_unittests',
+            '../chrome_frame/chrome_frame.gyp:npchrome_frame',
             '../courgette/courgette.gyp:courgette_unittests',
-            '../gfx/gfx.gyp:gfx_unittests',
+            '../ui/gfx/gfx.gyp:gfx_unittests',
             '../gpu/gpu.gyp:gpu_unittests',
             '../ipc/ipc.gyp:ipc_tests',
             '../jingle/jingle.gyp:notifier_unit_tests',
@@ -354,19 +385,14 @@
             '../printing/printing.gyp:printing_unittests',
             '../remoting/remoting.gyp:remoting_unittests',
             '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-            '../third_party/WebKit/WebKit/chromium/WebKit.gyp:copy_TestNetscapePlugIn',
+            '../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:copy_TestNetscapePlugIn',
+            '../views/views.gyp:views_unittests',
             # TODO(nsylvain) ui_tests.exe depends on test_shell_common.
             # This should:
             # 1) not be the case. OR.
             # 2) be expressed in the ui tests dependencies.
             '../webkit/webkit.gyp:test_shell_common',
             'temp_gyp/googleurl.gyp:googleurl_unittests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_net_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_perftests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_reliability_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_tests',
-            '../chrome_frame/chrome_frame.gyp:chrome_frame_unittests',
-            '../chrome_frame/chrome_frame.gyp:npchrome_frame',
           ],
         },
         {
@@ -438,6 +464,7 @@
           'dependencies': [
             '../app/app.gyp:app_unittests',
             '../base/base.gyp:base_unittests',
+            '../chrome/browser/chromeos/input_method/candidate_window.gyp:candidate_window',
             '../chrome/chrome.gyp:browser_tests',
             '../chrome/chrome.gyp:chrome',
             '../chrome/chrome.gyp:interactive_ui_tests',
@@ -450,7 +477,7 @@
             '../chrome/chrome.gyp:ui_tests',
             '../chrome/chrome.gyp:unit_tests',
             '../chrome/chrome.gyp:url_fetch_test',
-            '../gfx/gfx.gyp:gfx_unittests',
+            '../ui/gfx/gfx.gyp:gfx_unittests',
             '../ipc/ipc.gyp:ipc_tests',
             '../jingle/jingle.gyp:notifier_unit_tests',
             '../media/media.gyp:ffmpeg_tests',
@@ -460,8 +487,8 @@
             '../printing/printing.gyp:printing_unittests',
             '../remoting/remoting.gyp:remoting_unittests',
             '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../views/views.gyp:views_unittests',
             'temp_gyp/googleurl.gyp:googleurl_unittests',
-            '../chrome/browser/chromeos/input_method/candidate_window.gyp:candidate_window',
           ],
         },
       ],  # targets
diff --git a/build/common.croc b/build/common.croc
index 5588990..90b9cb9 100644
--- a/build/common.croc
+++ b/build/common.croc
@@ -47,7 +47,7 @@
     # Files/paths to include.  Specify these before the excludes, since rules
     # are in order.
     {
-      'regexp' : '^CHROMIUM/(base|media|net|printing|chrome|webkit/glue|native_client)/',
+      'regexp' : '^CHROMIUM/(base|media|net|printing|remoting|chrome|webkit/glue|native_client)/',
       'include' : 1,
     },
     # Don't include subversion or mercurial SCM dirs
diff --git a/build/common.gypi b/build/common.gypi
index ae5f41a..5b110d5 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -119,6 +119,19 @@
       # Set to select the Title Case versions of strings in GRD files.
       'use_titlecase_in_grd_files%': 0,
 
+      # Use translations provided by volunteers at launchpad.net.  This
+      # currently only works on Linux.
+      'use_third_party_translations%': 0,
+
+      # Remoting compilation is enabled by default. Set to 0 to disable.
+      'remoting%': 1,
+
+      # If this is set, the clang plugins used on the buildbot will be used.
+      # Run tools/clang/scripts/update.sh to make sure they are compiled.
+      # This causes 'clang_chrome_plugins_flags' to be set.
+      # Has no effect if 'clang' is not set as well.
+      'clang_use_chrome_plugins%': 0,
+
       'conditions': [
         # A flag to enable or disable our compile-time dependency
         # on gnome-keyring. If that dependency is disabled, no gnome-keyring
@@ -173,6 +186,9 @@
     'library%': '<(library)',
     'component%': '<(component)',
     'use_titlecase_in_grd_files%': '<(use_titlecase_in_grd_files)',
+    'use_third_party_translations%': '<(use_third_party_translations)',
+    'remoting%': '<(remoting)',
+    'clang_use_chrome_plugins%': '<(clang_use_chrome_plugins)',
 
     # The release channel that this build targets. This is used to restrict
     # channel-specific build options, like which installer packages to create.
@@ -249,6 +265,9 @@
     # but that doesn't work as we'd like.
     'msvs_debug_link_incremental%': '2',
 
+    # Needed for some of the largest modules.
+    'msvs_debug_link_nonincremental%': '1',
+
     # This is the location of the sandbox binary. Chrome looks for this before
     # running the zygote process. If found, and SUID, it will be used to
     # sandbox the zygote process and, thus, all renderer processes.
@@ -263,6 +282,19 @@
     # won't be necessary.
     'clang%': 0,
 
+    # These two variables can be set in GYP_DEFINES while running
+    # |gclient runhooks| to let clang run a plugin in every compilation.
+    # Only has an effect if 'clang=1' is in GYP_DEFINES as well.
+    # Example:
+    #     GYP_DEFINES='clang=1 clang_load=/abs/path/to/libPrintFunctionNames.dylib clang_add_plugin=print-fns' gclient runhooks
+
+    'clang_load%': '',
+    'clang_add_plugin%': '',
+
+    # Enable sampling based profiler.
+    # See http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html
+    'profiling%': '0',
+
     # Override whether we should use Breakpad on Linux. I.e. for Chrome bot.
     'linux_breakpad%': 0,
     # And if we want to dump symbols for Breakpad-enabled builds.
@@ -307,15 +339,12 @@
     'enable_new_npdevice_api%': 0,
 
     # Enable EGLImage support in OpenMAX
-    'enable_eglimage%': 0,
+    'enable_eglimage%': 1,
 
     # Enable a variable used elsewhere throughout the GYP files to determine
     # whether to compile in the sources for the GPU plugin / process.
     'enable_gpu%': 1,
 
-    # Use GConf, the GNOME configuration system.
-    'use_gconf%': 1,
-
     # Use OpenSSL instead of NSS. Under development: see http://crbug.com/62803
     'use_openssl%': 0,
 
@@ -333,9 +362,6 @@
     # from the system include dirs.
     'system_libcros%': 0,
 
-    # Remoting compilation is enabled by default. Set to 0 to disable.
-    'remoting%': 1,
-
     # NOTE: When these end up in the Mac bundle, we need to replace '-' for '_'
     # so Cocoa is happy (http://crbug.com/20441).
     'locales': [
@@ -353,6 +379,9 @@
     # Under development: http://crbug.com/68551
     'use_harfbuzz_ng%': 0,
 
+    # Point to ICU directory.
+    'icu_src_dir': '../third_party/icu',
+
     'conditions': [
       ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
         # This will set gcc_version to XY if you are running gcc X.Y.*.
@@ -439,6 +468,13 @@
         'libjpeg_gyp_path': '../third_party/libjpeg/libjpeg.gyp',
       }],  # use_libjpeg_turbo==1
 
+      # Use GConf, the GNOME configuration system.
+      ['chromeos==1', {
+        'use_gconf%': 0,
+      }, {
+        'use_gconf%': 1,
+      }],
+
       # Setup -D flags passed into grit.
       ['chromeos==1', {
         'grit_defines': ['-D', 'chromeos'],
@@ -449,9 +485,21 @@
       ['touchui==1', {
         'grit_defines': ['-D', 'touchui'],
       }],
+      ['remoting==1', {
+        'grit_defines': ['-D', 'remoting'],
+      }],
       ['use_titlecase_in_grd_files==1', {
         'grit_defines': ['-D', 'use_titlecase'],
       }],
+      ['use_third_party_translations==1', {
+        'grit_defines': ['-D', 'use_third_party_translations'],
+        'locales': ['ast', 'eu', 'gl', 'ka', 'ku', 'ug'],
+      }],
+
+      ['clang_use_chrome_plugins==1', {
+        'clang_chrome_plugins_flags':
+            '<!(<(DEPTH)/tools/clang/scripts/plugin_flags.sh)',
+      }],
     ],
   },
   'target_defaults': {
@@ -516,6 +564,9 @@
       ['touchui==1', {
         'defines': ['TOUCH_UI=1'],
       }],
+      ['profiling==1', {
+        'defines': ['ENABLE_PROFILING=1'],
+      }],
       ['remoting==1', {
         'defines': ['ENABLE_REMOTING=1'],
       }],
@@ -542,6 +593,14 @@
               'debug_extra_cflags': '-g1',
             },
           }],
+          # Clang creates chubby debug information, which makes linking very
+          # slow. For now, don't create debug information with clang.  See
+          # http://crbug.com/70000
+          ['OS=="linux" and clang==1', {
+            'variables': {
+              'debug_extra_cflags': '-g0',
+            },
+          }],
         ],  # conditions for fastbuild.
       }],  # fastbuild!=0
       ['selinux==1', {
@@ -620,11 +679,20 @@
       ['chromium_code==0', {
         'conditions': [
           [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+            # We don't want to get warnings from third-party code,
+            # so remove any existing warning-enabling flags like -Wall.
             'cflags!': [
               '-Wall',
               '-Wextra',
               '-Werror',
             ],
+            'cflags': [
+              # Don't warn about hash_map in third-party code.
+              '-Wno-deprecated',
+              # Don't warn about printf format problems.
+              # This is off by default in gcc but on in Ubuntu's gcc(!).
+              '-Wno-format',
+            ],
           }],
           [ 'OS=="win"', {
             'defines': [
@@ -986,6 +1054,12 @@
                   '-fno-ident',
                 ],
               }],
+              ['profiling==1', {
+                'cflags': [
+                  '-fno-omit-frame-pointer',
+                  '-g',
+                ],
+              }],
             ]
           },
         },
@@ -1128,25 +1202,42 @@
               }]]
           }],
           ['clang==1', {
-            'cflags': [
-              # Don't warn about unused variables, due to a common pattern:
-              #   scoped_deleter unused_variable(&thing_to_delete);
-              '-Wno-unused-variable',
-              # Clang spots more unused functions.
-              '-Wno-unused-function',
-              # gtest confuses clang.
-              '-Wno-bool-conversions',
-              # Don't die on dtoa code that uses a char as an array index.
-              '-Wno-char-subscripts',
-              # Survive EXPECT_EQ(unnamed_enum, unsigned int) -- see
-              # http://code.google.com/p/googletest/source/detail?r=446 .
-              # TODO(thakis): Use -isystem instead (http://crbug.com/58751 ).
-              '-Wno-unnamed-type-template-args',
-            ],
-            'cflags!': [
-              # Clang doesn't seem to know know this flag.
-              '-mfpmath=sse',
-            ],
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  # Clang spots more unused functions.
+                  '-Wno-unused-function',
+                  # Don't die on dtoa code that uses a char as an array index.
+                  '-Wno-char-subscripts',
+                  # Survive EXPECT_EQ(unnamed_enum, unsigned int) -- see
+                  # http://code.google.com/p/googletest/source/detail?r=446 .
+                  # TODO(thakis): Use -isystem instead (http://crbug.com/58751 )
+                  '-Wno-unnamed-type-template-args',
+                  # TODO(thakis): Turn on -- http://crbug.com/72205
+                  '-Wno-overloaded-virtual',
+                ],
+                'cflags!': [
+                  # Clang doesn't seem to know know this flag.
+                  '-mfpmath=sse',
+                ],
+              }]],
+          }],
+          ['clang==1 and clang_use_chrome_plugins==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '<(clang_chrome_plugins_flags)',
+                ],
+              }]],
+          }],
+          ['clang==1 and clang_load!="" and clang_add_plugin!=""', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-Xclang', '-load', '-Xclang', '<(clang_load)',
+                  '-Xclang', '-add-plugin', '-Xclang', '<(clang_add_plugin)',
+                ],
+              }]],
           }],
           ['no_strict_aliasing==1', {
             'cflags': [
@@ -1258,6 +1349,19 @@
                 # http://code.google.com/p/googletest/source/detail?r=446 .
                 # TODO(thakis): Use -isystem instead (http://crbug.com/58751 ).
                 '-Wno-unnamed-type-template-args',
+                # TODO(thakis): Turn on -- http://crbug.com/72205
+                '-Wno-overloaded-virtual',
+              ],
+            }],
+            ['clang==1 and clang_use_chrome_plugins==1', {
+              'OTHER_CFLAGS': [
+                '<(clang_chrome_plugins_flags)',
+              ],
+            }],
+            ['clang==1 and clang_load!="" and clang_add_plugin!=""', {
+              'OTHER_CFLAGS': [
+                '-Xclang', '-load', '-Xclang', '<(clang_load)',
+                '-Xclang', '-add-plugin', '-Xclang', '<(clang_add_plugin)',
               ],
             }],
           ],
@@ -1378,6 +1482,7 @@
           'VCLinkerTool': {
             'AdditionalDependencies': [
               'wininet.lib',
+              'dnsapi.lib',
               'version.lib',
               'msimg32.lib',
               'ws2_32.lib',
diff --git a/build/features_override.gypi b/build/features_override.gypi
index 770778d..de287c3 100644
--- a/build/features_override.gypi
+++ b/build/features_override.gypi
@@ -3,13 +3,15 @@
 # found in the LICENSE file.
 
 # This file is only included in full-chromium builds, and overrides the
-# feature_defines variable in third_party/WebKit/WebKit/chromium/features.gypi.
+# feature_defines variable in
+# third_party/WebKit/Source/WebKit/chromium/features.gypi.
 {
   'variables': {
     # WARNING: This list of strings completely replaces the list in
     # features.gypi. Therefore, if an enable is listed in features.gypi
     # but not listed below, it will revert to its hardcoded webkit value.
     'feature_defines': [
+      # TODO(kbr): remove ENABLE_3D_CANVAS after renaming to ENABLE_WEBGL lands.
       'ENABLE_3D_CANVAS=1',
       'ENABLE_3D_PLUGIN=1',
       'ENABLE_BLOB=1',
@@ -23,6 +25,7 @@
       'ENABLE_DIRECTORY_UPLOAD=1',
       'ENABLE_DOM_STORAGE=1',
       'ENABLE_EVENTSOURCE=1',
+      'ENABLE_JAVASCRIPT_I18N_API=1',
       'ENABLE_FILE_SYSTEM=1',
       'ENABLE_FILTERS=1',
       'ENABLE_GEOLOCATION=1',
@@ -38,9 +41,11 @@
       'ENABLE_OPENTYPE_SANITIZER=1',
       'ENABLE_ORIENTATION_EVENTS=0',
       'ENABLE_PROGRESS_TAG=1',
+      'ENABLE_REQUEST_ANIMATION_FRAME=1',
       'ENABLE_RUBY=1',
       'ENABLE_SANDBOX=1',
       'ENABLE_SHARED_WORKERS=1',
+      'ENABLE_SKIA_GPU=<(use_skia_gpu)',
       'ENABLE_SVG=<(enable_svg)',
       'ENABLE_SVG_ANIMATION=<(enable_svg)',
       'ENABLE_SVG_AS_IMAGE=<(enable_svg)',
@@ -52,6 +57,7 @@
       'ENABLE_VIDEO=1',
       'ENABLE_WEB_SOCKETS=1',
       'ENABLE_WEB_TIMING=1',
+      'ENABLE_WEBGL=1',
       'ENABLE_WORKERS=1',
       'ENABLE_XHR_RESPONSE_BLOB=1',
       'ENABLE_XPATH=1',
@@ -65,6 +71,7 @@
       'use_accelerated_compositing%': 1,
       'enable_svg%': 1,
       'enable_touch_events%': 1,
+      'use_skia_gpu%': 0,
     },
     'use_accelerated_compositing%': '<(use_accelerated_compositing)',
     'enable_svg%': '<(enable_svg)',
@@ -78,6 +85,11 @@
         ],
         'use_accelerated_compositing': 1,
       }],
+      ['OS=="mac"', {
+        'feature_defines': [
+          'ENABLE_WEB_AUDIO=1',
+        ],
+      }],
     ],
     # TODO: If the need arises, create a mechanism that will intelligently
     # merge the lists rather than replace one with the other. This may
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index 3ed5513..22b1b67 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -60,8 +60,8 @@
   tar -xjvf $BINUTILS.tar.bz2
   cd $BINUTILS
   ./configure --prefix=/usr/local/gold --enable-gold
-  make -j3
-  if sudo make install
+  make maybe-all-binutils maybe-all-gold -j4
+  if sudo make maybe-install-binutils maybe-install-gold
   then
     # Still need to figure out graceful way of pointing gyp to use
     # /usr/local/gold/bin/ld without requiring him to set environment
diff --git a/build/internal/.svn/all-wcprops b/build/internal/.svn/all-wcprops
deleted file mode 100644
index fa3850c..0000000
--- a/build/internal/.svn/all-wcprops
+++ /dev/null
@@ -1,29 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 44
-/svn/!svn/ver/42890/trunk/src/build/internal
-END
-README.chromium
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/35367/trunk/src/build/internal/README.chromium
-END
-release_impl_official.gypi
-K 25
-svn:wc:ra_dav:version-url
-V 71
-/svn/!svn/ver/42890/trunk/src/build/internal/release_impl_official.gypi
-END
-release_impl.gypi
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/35449/trunk/src/build/internal/release_impl.gypi
-END
-release_defaults.gypi
-K 25
-svn:wc:ra_dav:version-url
-V 66
-/svn/!svn/ver/35449/trunk/src/build/internal/release_defaults.gypi
-END
diff --git a/build/internal/.svn/entries b/build/internal/.svn/entries
deleted file mode 100644
index e54058f..0000000
--- a/build/internal/.svn/entries
+++ /dev/null
@@ -1,164 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build/internal
-http://src.chromium.org/svn
-
-
-
-2010-03-27T02:16:29.574773Z
-42890
-maruel@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-README.chromium
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-29a46a46f286c28702edc38b379270e7
-2009-12-30T04:39:17.822713Z
-35367
-bradnelson@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2189
-
-release_impl_official.gypi
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-2323279bd929cdb8c81e6b8ff1de8421
-2010-03-27T02:16:29.574773Z
-42890
-maruel@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-567
-
-release_impl.gypi
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-3f7460c6ff5f62fe8ac611440a2aeab0
-2010-01-04T06:40:16.325670Z
-35449
-bradnelson@google.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-45
-
-release_defaults.gypi
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-94e7cde3c64a768becc543257895f783
-2010-01-04T06:40:16.325670Z
-35449
-bradnelson@google.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-318
-
diff --git a/build/internal/.svn/prop-base/README.chromium.svn-base b/build/internal/.svn/prop-base/README.chromium.svn-base
deleted file mode 100644
index 92de39c..0000000
--- a/build/internal/.svn/prop-base/README.chromium.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 13
-svn:mergeinfo
-V 73
-/branches/chrome_webkit_merge_branch/build/internal/README.google:69-2775
-END
diff --git a/build/internal/.svn/text-base/README.chromium.svn-base b/build/internal/.svn/text-base/README.chromium.svn-base
deleted file mode 100644
index 4624830..0000000
--- a/build/internal/.svn/text-base/README.chromium.svn-base
+++ /dev/null
@@ -1,24 +0,0 @@
-Internal property sheets:
-  essential.vsprops
-    Contains the common settings used throughout the projects. Is included by either ..\debug.vsprops or ..\release.vsprops, so in general, it is not included directly.
-
-  release_defaults.vsprops
-    Included by ..\release.vsprops. Its settings are overriden by release_impl$(CHROME_BUILD_TYPE).vsprops. Uses the default VS setting which is "Maximize Speed". Results in relatively fast build with reasonable optimization level but without whole program optimization to reduce build time.
-
-  release_impl.vsprops
-    Included by ..\release.vsprops by default when CHROME_BUILD_TYPE is undefined. Includes release_defaults.vsprops.
-
-  release_impl_checksenabled.vsprops
-    Included by ..\release.vsprops when CHROME_BUILD_TYPE=_checksenabled. Matches what release_defaults.vsprops does, but doesn't actually inherit from it as we couldn't quite get that working. The only difference is that _DEBUG is set instead of NDEBUG. Used for keeping debug checks enabled with a build that is fast enough to dogfood with.
-
-  release_impl_official.vsprops
-    Included by ..\release.vsprops when CHROME_BUILD_TYPE=_official. Includes release_defaults.vsprops. Enables Whole Program Optimizations (WPO), which doubles the build time. Results in much more optimized build. Uses "Full Optimization" and "Flavor small code".
-
-  release_impl_pgo_instrument.vsprops
-    Included by ..\release.vsprops when CHROME_BUILD_TYPE=_pgo_instrument. Includes release_defaults.vsprops. Enables Profile Guided Optimization (PGO) instrumentation (first pass). Uses "Full Optimization" and "Flavor small code".
-
-  release_impl_pgo_optimize.vsprops
-    Included by ..\release.vsprops when CHROME_BUILD_TYPE=_pgo_optimize. Includes release_defaults.vsprops. Enables Profile Guided Optimization (PGO) optimization (second pass). Uses "Full Optimization" and "Flavor small code".
-
-  release_impl_purify.vsprops
-    Included by ..\release.vsprops when CHROME_BUILD_TYPE=_purify. Includes release_defaults.vsprops. Disables optimizations. Used with Purify to test without debug tools and without optimization; i.e. NDEBUG is defined but the compiler doesn't optimize the binary.
diff --git a/build/internal/.svn/text-base/release_defaults.gypi.svn-base b/build/internal/.svn/text-base/release_defaults.gypi.svn-base
deleted file mode 100644
index 5aa2b75..0000000
--- a/build/internal/.svn/text-base/release_defaults.gypi.svn-base
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  'msvs_settings': {
-    'VCCLCompilerTool': {
-      'Optimizations': '2',
-      'StringPooling': 'true',
-      'OmitFramePointers': 'true',
-    },
-    'VCLinkerTool': {
-      'LinkIncremental': '1',
-      'OptimizeReferences': '2',
-      'EnableCOMDATFolding': '2',
-      'OptimizeForWindows98': '1',
-    },
-  },
-}
diff --git a/build/internal/.svn/text-base/release_impl.gypi.svn-base b/build/internal/.svn/text-base/release_impl.gypi.svn-base
deleted file mode 100644
index aff06dc..0000000
--- a/build/internal/.svn/text-base/release_impl.gypi.svn-base
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  'includes': ['release_defaults.gypi'],
-}
diff --git a/build/internal/.svn/text-base/release_impl_official.gypi.svn-base b/build/internal/.svn/text-base/release_impl_official.gypi.svn-base
deleted file mode 100644
index 18f7928..0000000
--- a/build/internal/.svn/text-base/release_impl_official.gypi.svn-base
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  'includes': ['release_defaults.gypi'],
-  'defines': ['OFFICIAL_BUILD'],
-  'msvs_settings': {
-    'VCCLCompilerTool': {
-      'Optimization': '3',
-      'InlineFunctionExpansion': '2',
-      'EnableIntrinsicFunctions': 'true',
-      'FavorSizeOrSpeed': '2',
-      'OmitFramePointers': 'true',
-      'EnableFiberSafeOptimizations': 'true',
-      'WholeProgramOptimization': 'true',
-    },
-    'VCLibrarianTool': {
-      'AdditionalOptions': ['/ltcg', '/expectedoutputsize:120000000'],
-    },
-    'VCLinkerTool': {
-      'LinkTimeCodeGeneration': '1',
-    },
-  },
-}
diff --git a/build/internal/release_defaults.gypi b/build/internal/release_defaults.gypi
index 5aa2b75..1bf6bbe 100644
--- a/build/internal/release_defaults.gypi
+++ b/build/internal/release_defaults.gypi
@@ -1,7 +1,7 @@
 {
   'msvs_settings': {
     'VCCLCompilerTool': {
-      'Optimizations': '2',
+      'Optimization': '2',
       'StringPooling': 'true',
       'OmitFramePointers': 'true',
     },
diff --git a/build/linux/.svn/all-wcprops b/build/linux/.svn/all-wcprops
deleted file mode 100644
index 57d6efe..0000000
--- a/build/linux/.svn/all-wcprops
+++ /dev/null
@@ -1,41 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 41
-/svn/!svn/ver/69058/trunk/src/build/linux
-END
-dump_app_syms
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/43724/trunk/src/build/linux/dump_app_syms
-END
-chrome_linux.croc
-K 25
-svn:wc:ra_dav:version-url
-V 59
-/svn/!svn/ver/61430/trunk/src/build/linux/chrome_linux.croc
-END
-pkg-config-wrapper
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/66712/trunk/src/build/linux/pkg-config-wrapper
-END
-system.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 52
-/svn/!svn/ver/68749/trunk/src/build/linux/system.gyp
-END
-python_arch.sh
-K 25
-svn:wc:ra_dav:version-url
-V 56
-/svn/!svn/ver/40635/trunk/src/build/linux/python_arch.sh
-END
-rewrite_dirs.py
-K 25
-svn:wc:ra_dav:version-url
-V 57
-/svn/!svn/ver/66712/trunk/src/build/linux/rewrite_dirs.py
-END
diff --git a/build/linux/.svn/dir-prop-base b/build/linux/.svn/dir-prop-base
deleted file mode 100644
index f2a987b..0000000
--- a/build/linux/.svn/dir-prop-base
+++ /dev/null
@@ -1,32 +0,0 @@
-K 10
-svn:ignore
-V 390
-SConstruct
-dbus-glib.target.mk
-fontconfig.mk
-fontconfig.target.mk
-freetype2.mk
-freetype2.target.mk
-gconf.mk
-gconf.target.mk
-gdk.mk
-gdk.target.mk
-gnome-keyring.target.mk
-gthread.mk
-gtk.mk
-gtk.target.mk
-gtkprint.mk
-gtkprint.target.mk
-libresolv.target.mk
-nss.mk
-nss.target.mk
-openssl.target.mk
-selinux.mk
-selinux.target.mk
-system.Makefile
-system_main.scons
-x11.mk
-x11.target.mk
-xext.target.mk
-
-END
diff --git a/build/linux/.svn/entries b/build/linux/.svn/entries
deleted file mode 100644
index f796eb7..0000000
--- a/build/linux/.svn/entries
+++ /dev/null
@@ -1,232 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build/linux
-http://src.chromium.org/svn
-
-
-
-2010-12-13T22:33:15.612310Z
-69058
-thestig@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-dump_app_syms
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-6639f13788fedc69c6ce87b9423d7c7e
-2010-04-06T16:54:40.053082Z
-43724
-thestig@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-737
-
-chrome_linux.croc
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-66c3f67e50e44e48bb50b5c6a88b3c05
-2010-10-04T22:56:50.780169Z
-61430
-jrg@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-653
-
-pkg-config-wrapper
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-64e25fc6c3fce9c4b21b35b060e752f8
-2010-11-19T00:43:49.567135Z
-66712
-piman@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1616
-
-system.gyp
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-7546e8d115920cc410d237f62d9abfac
-2010-12-09T18:36:24.185738Z
-68749
-joth@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-9997
-
-python_arch.sh
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-03c809c6fb307b25f0cfd260d43d0a7c
-2010-03-04T17:32:58.651525Z
-40635
-thestig@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-806
-
-rewrite_dirs.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-1cbd0090a5ad2231dae1e0b8c3683d04
-2010-11-19T00:43:49.567135Z
-66712
-piman@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2006
-
diff --git a/build/linux/.svn/prop-base/chrome_linux.croc.svn-base b/build/linux/.svn/prop-base/chrome_linux.croc.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/linux/.svn/prop-base/chrome_linux.croc.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/linux/.svn/prop-base/dump_app_syms.svn-base b/build/linux/.svn/prop-base/dump_app_syms.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/linux/.svn/prop-base/dump_app_syms.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/linux/.svn/prop-base/pkg-config-wrapper.svn-base b/build/linux/.svn/prop-base/pkg-config-wrapper.svn-base
deleted file mode 100644
index 869ac71..0000000
--- a/build/linux/.svn/prop-base/pkg-config-wrapper.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/linux/.svn/prop-base/python_arch.sh.svn-base b/build/linux/.svn/prop-base/python_arch.sh.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/linux/.svn/prop-base/python_arch.sh.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/linux/.svn/prop-base/rewrite_dirs.py.svn-base b/build/linux/.svn/prop-base/rewrite_dirs.py.svn-base
deleted file mode 100644
index 869ac71..0000000
--- a/build/linux/.svn/prop-base/rewrite_dirs.py.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/linux/.svn/prop-base/system.gyp.svn-base b/build/linux/.svn/prop-base/system.gyp.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/linux/.svn/prop-base/system.gyp.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/linux/.svn/text-base/chrome_linux.croc.svn-base b/build/linux/.svn/text-base/chrome_linux.croc.svn-base
deleted file mode 100644
index f400306..0000000
--- a/build/linux/.svn/text-base/chrome_linux.croc.svn-base
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- python -*-
-# Crocodile config file for Chromium linux
-
-# TODO(jhawkins): We'll need to add a chromeos.croc once we get a coverage bot
-# for that platform.
-
-{
-  # List of rules, applied in order
-  'rules' : [
-    # Specify inclusions before exclusions, since rules are in order.
-
-    # Don't include non-Linux platform dirs
-    {
-      'regexp' : '.*/(chromeos|views)/',
-      'include' : 0,
-    },
-    # Don't include chromeos, windows, or mac specific files
-    {
-      'regexp' : '.*(_|/)(chromeos|mac|win|views)(\\.|_)',
-      'include' : 0,
-    },
-
-    # Groups
-    {
-      'regexp' : '.*_test_linux\\.',
-      'group' : 'test',
-    },
-  ],
-}
diff --git a/build/linux/.svn/text-base/dump_app_syms.svn-base b/build/linux/.svn/text-base/dump_app_syms.svn-base
deleted file mode 100644
index 632bcc7..0000000
--- a/build/linux/.svn/text-base/dump_app_syms.svn-base
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-
-# 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.
-#
-# Helper script to run dump_syms on Chrome Linux executables and strip
-# them if needed.
-
-set -e
-
-usage() {
-  echo -n "$0 <dump_syms_exe> <strip_binary> " >&2
-  echo "<binary_with_symbols> <symbols_output>" >&2
-}
-
-
-if [ $# -ne 4 ]; then
-  usage
-  exit 1
-fi
-
-SCRIPTDIR="$(readlink -f "$(dirname "$0")")"
-DUMPSYMS="$1"
-STRIP_BINARY="$2"
-INFILE="$3"
-OUTFILE="$4"
-
-# Dump the symbols from the given binary.
-if [ ! -e "$OUTFILE" -o "$INFILE" -nt "$OUTFILE" ]; then
-  "$DUMPSYMS" "$INFILE" > "$OUTFILE"
-fi
-
-if [ "$STRIP_BINARY" != "0" ]; then
-  strip "$INFILE"
-fi
diff --git a/build/linux/.svn/text-base/pkg-config-wrapper.svn-base b/build/linux/.svn/text-base/pkg-config-wrapper.svn-base
deleted file mode 100644
index 4b5455b..0000000
--- a/build/linux/.svn/text-base/pkg-config-wrapper.svn-base
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This program wraps around pkg-config to generate the correct include and
-# library paths when cross-compiling using a sysroot.
-# The assumption is that the sysroot contains the .pc files in usr/lib/pkgconfig
-# and usr/share/pkgconfig (relative to the sysroot) and that they output paths
-# relative to some parent path of the sysroot.
-# This assumption is valid for a range of sysroots, in particular: a
-# LSB-compliant root filesystem mounted at the sysroot, and a board build
-# directory of a Chromium OS chroot.
-
-root="$1"
-if [ -z "$root" ]
-then
-  echo "usage: $0 /path/to/sysroot [pkg-config-arguments] package" >&2
-  exit 1
-fi
-
-rewrite=`dirname $0`/rewrite_dirs.py
-package=${!#}
-
-shift
-config_path=$root/usr/lib/pkgconfig:$root/usr/share/pkgconfig
-set -e
-# Some sysroots, like the Chromium OS ones, may generate paths that are not
-# relative to the sysroot. For example,
-# /path/to/chroot/build/x86-generic/usr/lib/pkgconfig/pkg.pc may have all paths
-# relative to /path/to/chroot (i.e. prefix=/build/x86-generic/usr) instead of
-# relative to /path/to/chroot/build/x86-generic (i.e prefix=/usr).
-# To support this correctly, it's necessary to extract the prefix to strip from
-# pkg-config's |prefix| variable.
-prefix=`PKG_CONFIG_PATH=$config_path pkg-config --variable=prefix "$package" | sed -e 's|/usr$||'`
-result=`PKG_CONFIG_PATH=$config_path pkg-config "$@"`
-echo "$result"| $rewrite --sysroot "$root" --strip-prefix "$prefix"
diff --git a/build/linux/.svn/text-base/python_arch.sh.svn-base b/build/linux/.svn/text-base/python_arch.sh.svn-base
deleted file mode 100644
index f364469..0000000
--- a/build/linux/.svn/text-base/python_arch.sh.svn-base
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This figures out the architecture of the version of Python we are building
-# pyautolib against.
-#
-#  python_arch.sh /usr/lib/libpython2.5.so.1.0
-#  python_arch.sh /path/to/sysroot/usr/lib/libpython2.4.so.1.0
-#
-
-python=$(readlink -f "$1")
-if [ ! -r "$python" ]; then
-  echo unknown
-  exit 0;
-fi
-file_out=$(file "$python")
-if [ $? -ne 0 ]; then
-  echo unknown
-  exit 0;
-fi
-
-echo $file_out | grep -qs "ARM"
-if [ $? -eq 0 ]; then
-  echo arm
-  exit 0
-fi
-
-echo $file_out | grep -qs "x86-64"
-if [ $? -eq 0 ]; then
-  echo x64
-  exit 0
-fi
-
-echo $file_out | grep -qs "Intel 80386"
-if [ $? -eq 0 ]; then
-  echo ia32
-  exit 0
-fi
-
-exit 1
diff --git a/build/linux/.svn/text-base/rewrite_dirs.py.svn-base b/build/linux/.svn/text-base/rewrite_dirs.py.svn-base
deleted file mode 100644
index 9e166d0..0000000
--- a/build/linux/.svn/text-base/rewrite_dirs.py.svn-base
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-"""Rewrites paths in -I, -L and other option to be relative to a sysroot."""
-
-import sys
-import os
-import optparse
-
-REWRITE_PREFIX = ['-I',
-                  '-idirafter',
-                  '-imacros',
-                  '-imultilib',
-                  '-include',
-                  '-iprefix',
-                  '-iquote',
-                  '-isystem',
-                  '-L']
-
-def RewritePath(path, opts):
-  """Rewrites a path by stripping the prefix and prepending the sysroot."""
-  sysroot = opts.sysroot
-  prefix = opts.strip_prefix
-  if os.path.isabs(path) and not path.startswith(sysroot):
-    if path.startswith(prefix):
-      path = path[len(prefix):]
-    path = path.lstrip('/')
-    return os.path.join(sysroot, path)
-  else:
-    return path
-
-def RewriteLine(line, opts):
-  """Rewrites all the paths in recognized options."""
-  args = line.split()
-  count = len(args)
-  i = 0
-  while i < count:
-    for prefix in REWRITE_PREFIX:
-      # The option can be either in the form "-I /path/to/dir" or
-      # "-I/path/to/dir" so handle both.
-      if args[i] == prefix:
-        i += 1
-        try:
-          args[i] = RewritePath(args[i], opts)
-        except IndexError:
-          sys.stderr.write('Missing argument following %s\n' % prefix)
-          break
-      elif args[i].startswith(prefix):
-        args[i] = prefix + RewritePath(args[i][len(prefix):], opts)
-    i += 1
-
-  return ' '.join(args)
-
-def main(argv):
-  parser = optparse.OptionParser()
-  parser.add_option('-s', '--sysroot', default='/', help='sysroot to prepend')
-  parser.add_option('-p', '--strip-prefix', default='', help='prefix to strip')
-  opts, args = parser.parse_args(argv[1:])
-
-  for line in sys.stdin.readlines():
-    line = RewriteLine(line.strip(), opts)
-    print line
-  return 0
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/build/linux/.svn/text-base/system.gyp.svn-base b/build/linux/.svn/text-base/system.gyp.svn-base
deleted file mode 100644
index 39b3a11..0000000
--- a/build/linux/.svn/text-base/system.gyp.svn-base
+++ /dev/null
@@ -1,356 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'conditions': [
-    ['sysroot!=""', {
-      'variables': {
-        'pkg-config': './pkg-config-wrapper "<(sysroot)"',
-      },
-    }, {
-      'variables': {
-        'pkg-config': 'pkg-config'
-      },
-    }],
-    [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-      'variables': {
-        # We use our own copy of libssl3, although we still need to link against
-        # the rest of NSS.
-        'use_system_ssl%': 0,
-      },
-    }, {  # OS!="linux"
-      'variables': {
-        'use_system_ssl%': 1,
-      },
-    }],
-  ],
-
-
-  'targets': [
-    {
-      'target_name': 'gtk',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags gtk+-2.0 gthread-2.0)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other gtk+-2.0 gthread-2.0)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l gtk+-2.0 gthread-2.0)',
-            ],
-          },
-      }],
-      [ 'chromeos==1', {
-        'link_settings': {
-          'libraries': [ '-lXtst' ]
-        }
-      }]]
-    },
-    {
-      'target_name': 'gtkprint',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags gtk+-unix-print-2.0)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other gtk+-unix-print-2.0)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l gtk+-unix-print-2.0)',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'nss',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'conditions': [
-            ['use_system_ssl==0', {
-              'dependencies': [
-                '../../net/third_party/nss/ssl.gyp:ssl',
-                '../../third_party/zlib/zlib.gyp:zlib',
-              ],
-              'direct_dependent_settings': {
-                'cflags': [
-                  # We need for our local copies of the libssl3 headers to come
-                  # first, otherwise the code will build, but will fallback to
-                  # the set of features advertised in the system headers.
-                  # Unfortunately, there's no include path that we can filter
-                  # out of $(pkg-config --cflags nss) and GYP include paths
-                  # come after cflags on the command line. So we have these
-                  # bodges:
-                  '-Inet/third_party/nss/ssl',                  # for make
-                  '-IWebKit/chromium/net/third_party/nss/ssl',  # for make in webkit
-                  '<!@(<(pkg-config) --cflags nss)',
-                ],
-              },
-              'link_settings': {
-                'ldflags': [
-                  '<!@(<(pkg-config) --libs-only-L --libs-only-other nss)',
-                ],
-                'libraries': [
-                  '<!@(<(pkg-config) --libs-only-l nss | sed -e "s/-lssl3//")',
-                ],
-              },
-            }, {
-              'direct_dependent_settings': {
-                'cflags': [
-                  '<!@(<(pkg-config) --cflags nss)',
-                ],
-                'defines': [
-                  'USE_SYSTEM_SSL',
-                ],
-              },
-              'link_settings': {
-                'ldflags': [
-                  '<!@(<(pkg-config) --libs-only-L --libs-only-other nss)',
-                ],
-                'libraries': [
-                  '<!@(<(pkg-config) --libs-only-l nss)',
-                ],
-              },
-            }
-          ]]
-        }],
-      ],
-    },
-    {
-      'target_name': 'freetype2',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags freetype2)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other freetype2)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l freetype2)',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'fontconfig',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags fontconfig)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other fontconfig)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l fontconfig)',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'gdk',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags gdk-2.0)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other gdk-2.0)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l gdk-2.0)',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'gconf',
-      'type': 'settings',
-      'conditions': [
-        ['use_gconf==1 and _toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags gconf-2.0)',
-            ],
-            'defines': [
-              'USE_GCONF',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other gconf-2.0)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l gconf-2.0)',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'x11',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags x11)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other x11)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l x11)',
-            ],
-          },
-      }],
-      # When XInput2 is available (i.e. inputproto version is 2.0), the
-      # pkg-config command will succeed, so the output will be empty.
-      ['"<!@(<(pkg-config) --atleast-version=2.0 inputproto || echo $?)"==""', {
-        'direct_dependent_settings': {
-          'defines': [
-            'HAVE_XINPUT2',
-          ],
-        },
-        'link_settings': {
-          'ldflags': [
-            '<!@(<(pkg-config) --libs-only-L --libs-only-other xi)',
-          ],
-          'libraries': [
-            '<!@(<(pkg-config) --libs-only-l xi)',
-          ],
-        }
-      }],
-      ],
-    },
-    {
-      'target_name': 'xext',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags xext)',
-            ],
-          },
-          'link_settings': {
-            'ldflags': [
-              '<!@(<(pkg-config) --libs-only-L --libs-only-other xext)',
-            ],
-            'libraries': [
-              '<!@(<(pkg-config) --libs-only-l xext)',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'selinux',
-      'type': 'settings',
-      'conditions': [
-        ['_toolset=="target"', {
-          'link_settings': {
-            'libraries': [
-              '-lselinux',
-            ],
-          },
-      }]]
-    },
-    {
-      'target_name': 'gnome-keyring',
-      'type': 'settings',
-      'conditions': [
-        ['use_gnome_keyring==1', {
-          'direct_dependent_settings': {
-            'cflags': [
-              '<!@(<(pkg-config) --cflags gnome-keyring-1)',
-            ],
-            'defines': [
-              'USE_GNOME_KEYRING',
-            ],
-            'conditions': [
-              ['linux_link_gnome_keyring==0', {
-                'defines': ['DLOPEN_GNOME_KEYRING'],
-              }],
-            ],
-          },
-          'conditions': [
-            ['linux_link_gnome_keyring!=0', {
-              'link_settings': {
-                'ldflags': [
-                  '<!@(<(pkg-config) --libs-only-L --libs-only-other gnome-keyring-1)',
-                ],
-                'libraries': [
-                  '<!@(<(pkg-config) --libs-only-l gnome-keyring-1)',
-                ],
-              },
-            }, {
-              'link_settings': {
-                'libraries': [
-                  '-ldl',
-                ],
-              },
-            }],
-          ],
-        }],
-      ],
-    },
-    {
-      'target_name': 'dbus-glib',
-      'type': 'settings',
-      'direct_dependent_settings': {
-        'cflags': [
-          '<!@(<(pkg-config) --cflags dbus-glib-1)',
-        ],
-      },
-      'link_settings': {
-        'ldflags': [
-          '<!@(<(pkg-config) --libs-only-L --libs-only-other dbus-glib-1)',
-        ],
-        'libraries': [
-          '<!@(<(pkg-config) --libs-only-l dbus-glib-1)',
-        ],
-      },
-    },
-    {
-      'target_name': 'libresolv',
-      'type': 'settings',
-      'link_settings': {
-        'libraries': [
-          '-lresolv',
-        ],
-      },
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 39b3a11..a52083b 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -93,8 +93,8 @@
                   # out of $(pkg-config --cflags nss) and GYP include paths
                   # come after cflags on the command line. So we have these
                   # bodges:
-                  '-Inet/third_party/nss/ssl',                  # for make
-                  '-IWebKit/chromium/net/third_party/nss/ssl',  # for make in webkit
+                  '-Inet/third_party/nss/ssl',                         # for make
+                  '-ISource/WebKit/chromium/net/third_party/nss/ssl',  # for make in webkit
                   '<!@(<(pkg-config) --cflags nss)',
                 ],
               },
@@ -346,6 +346,30 @@
         ],
       },
     },
+    {
+      'target_name': 'ibus',
+      'type': 'settings',
+      'conditions': [
+        ['"<!@(<(pkg-config) --atleast-version=1.3.99 ibus-1.0 || echo $?)"==""', {
+          'variables': {
+            'ibus': 1
+          },
+          'direct_dependent_settings': {
+            'cflags': [
+              '<!@(<(pkg-config) --cflags ibus-1.0)',
+            ],
+          },
+          'link_settings': {
+            'ldflags': [
+              '<!@(<(pkg-config) --libs-only-L --libs-only-other ibus-1.0)',
+            ],
+            'libraries': [
+              '<!@(<(pkg-config) --libs-only-l ibus-1.0)',
+            ],
+          },
+        }],
+      ],
+    },
   ],
 }
 
diff --git a/build/mac/.svn/all-wcprops b/build/mac/.svn/all-wcprops
deleted file mode 100644
index 2dacaaa..0000000
--- a/build/mac/.svn/all-wcprops
+++ /dev/null
@@ -1,23 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 39
-/svn/!svn/ver/61430/trunk/src/build/mac
-END
-chrome_mac.croc
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/61430/trunk/src/build/mac/chrome_mac.croc
-END
-strip_from_xcode
-K 25
-svn:wc:ra_dav:version-url
-V 56
-/svn/!svn/ver/48655/trunk/src/build/mac/strip_from_xcode
-END
-strip_save_dsym
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/41200/trunk/src/build/mac/strip_save_dsym
-END
diff --git a/build/mac/.svn/entries b/build/mac/.svn/entries
deleted file mode 100644
index 6c233c0..0000000
--- a/build/mac/.svn/entries
+++ /dev/null
@@ -1,130 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build/mac
-http://src.chromium.org/svn
-
-
-
-2010-10-04T22:56:50.780169Z
-61430
-jrg@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-chrome_mac.croc
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-eb4bd7c438ca7678b4d1b094877c7f6e
-2010-10-04T22:56:50.780169Z
-61430
-jrg@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-690
-
-strip_from_xcode
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-7e80feb7fbdfabc2d776c47d212be09d
-2010-06-01T20:49:50.582521Z
-48655
-mark@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2116
-
-strip_save_dsym
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-852cf0bc96ddd4cf945cdf7f8e905a31
-2010-03-10T20:29:33.433875Z
-41200
-mark@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-12051
-
diff --git a/build/mac/.svn/prop-base/strip_from_xcode.svn-base b/build/mac/.svn/prop-base/strip_from_xcode.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/mac/.svn/prop-base/strip_from_xcode.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/mac/.svn/prop-base/strip_save_dsym.svn-base b/build/mac/.svn/prop-base/strip_save_dsym.svn-base
deleted file mode 100644
index 2e70e8f..0000000
--- a/build/mac/.svn/prop-base/strip_save_dsym.svn-base
+++ /dev/null
@@ -1,9 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-K 14
-svn:executable
-V 1
-*
-END
diff --git a/build/mac/.svn/text-base/chrome_mac.croc.svn-base b/build/mac/.svn/text-base/chrome_mac.croc.svn-base
deleted file mode 100644
index 8cde00c..0000000
--- a/build/mac/.svn/text-base/chrome_mac.croc.svn-base
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- python -*-
-# Crocodile config file for Chromium mac
-
-{
-  # List of rules, applied in order
-  'rules' : [
-    # Specify inclusions before exclusions, since rules are in order.
-
-    # Don't include chromeos, linux, or windows specific files
-    {
-      'regexp' : '.*(_|/)(chromeos|linux|win|views)(\\.|_)',
-      'include' : 0,
-    },
-    # Don't include ChromeOS dirs
-    {
-      'regexp' : '.*/chromeos/',
-      'include' : 0,
-    },
-
-    # Groups
-    {
-      'regexp' : '.*_test_mac\\.',
-      'group' : 'test',
-    },
-
-    # Languages
-    {
-      'regexp' : '.*\\.m$',
-      'language' : 'ObjC',
-    },
-    {
-      'regexp' : '.*\\.mm$',
-      'language' : 'ObjC++',
-    },
-  ],
-}
diff --git a/build/mac/.svn/text-base/strip_from_xcode.svn-base b/build/mac/.svn/text-base/strip_from_xcode.svn-base
deleted file mode 100644
index c26b9fb..0000000
--- a/build/mac/.svn/text-base/strip_from_xcode.svn-base
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2008 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is a handy wrapper script that figures out how to call the strip
-# utility (strip_save_dsym in this case), if it even needs to be called at all,
-# and then does it.  This script should be called by a post-link phase in
-# targets that might generate Mach-O executables, dynamic libraries, or
-# loadable bundles.
-#
-# An example "Strip If Needed" build phase placed after "Link Binary With
-# Libraries" would do:
-# exec "${XCODEPROJ_DEPTH}/build/mac/strip_from_xcode"
-
-if [ "${CONFIGURATION}" != "Release" ] ; then
-  # Only strip in release mode.
-  exit 0
-fi
-
-declare -a FLAGS
-
-# MACH_O_TYPE is not set for a command-line tool, so check PRODUCT_TYPE too.
-# Weird.
-if [ "${MACH_O_TYPE}" = "mh_execute" ] || \
-   [ "${PRODUCT_TYPE}" = "com.apple.product-type.tool" ] ; then
-  # Strip everything (no special flags).  No-op.
-  true
-elif [ "${MACH_O_TYPE}" = "mh_dylib" ] || \
-     [ "${MACH_O_TYPE}" = "mh_bundle" ]; then
-  # Strip debugging symbols and local symbols
-  FLAGS[${#FLAGS[@]}]=-S
-  FLAGS[${#FLAGS[@]}]=-x
-elif [ "${MACH_O_TYPE}" = "staticlib" ] ; then
-  # Don't strip static libraries.
-  exit 0
-else
-  # Warn, but don't treat this as an error.
-  echo $0: warning: unrecognized MACH_O_TYPE ${MACH_O_TYPE}
-  exit 0
-fi
-
-if [ -n "${STRIPFLAGS}" ] ; then
-  # Pick up the standard STRIPFLAGS Xcode setting, used for "Additional Strip
-  # Flags".
-  for stripflag in "${STRIPFLAGS}" ; do
-    FLAGS[${#FLAGS[@]}]="${stripflag}"
-  done
-fi
-
-if [ -n "${CHROMIUM_STRIP_SAVE_FILE}" ] ; then
-  # An Xcode project can communicate a file listing symbols to saved in this
-  # environment variable by setting it as a build setting.  This isn't a
-  # standard Xcode setting.  It's used in preference to STRIPFLAGS to
-  # eliminate quoting ambiguity concerns.
-  FLAGS[${#FLAGS[@]}]=-s
-  FLAGS[${#FLAGS[@]}]="${CHROMIUM_STRIP_SAVE_FILE}"
-fi
-
-exec "$(dirname ${0})/strip_save_dsym" "${FLAGS[@]}" \
-     "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"
diff --git a/build/mac/.svn/text-base/strip_save_dsym.svn-base b/build/mac/.svn/text-base/strip_save_dsym.svn-base
deleted file mode 100644
index 3904c17..0000000
--- a/build/mac/.svn/text-base/strip_save_dsym.svn-base
+++ /dev/null
@@ -1,341 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2008 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Usage: strip_save_dsym <whatever-arguments-you-would-pass-to-strip>
-#
-# strip_save_dsym is a wrapper around the standard strip utility.  Given an
-# input Mach-O file, strip_save_dsym will save a copy of the file in a "fake"
-# .dSYM bundle for debugging, and then call strip to strip the Mach-O file.
-# Note that the .dSYM file is a "fake" in that it's not a self-contained
-# .dSYM bundle, it just contains a copy of the original (unstripped) Mach-O
-# file, and therefore contains references to object files on the filesystem.
-# The generated .dSYM bundle is therefore unsuitable for debugging in the
-# absence of these .o files.
-#
-# If a .dSYM already exists and has a newer timestamp than the Mach-O file,
-# this utility does nothing.  That allows strip_save_dsym to be run on a file
-# that has already been stripped without trashing the .dSYM.
-#
-# Rationale: the "right" way to generate dSYM bundles, dsymutil, is incredibly
-# slow.  On the other hand, doing a file copy (which is really all that
-# dsymutil does) is comparatively fast.  Since we usually just want to strip
-# a release-mode executable but still be able to debug it, and we don't care
-# so much about generating a hermetic dSYM bundle, we'll prefer the file copy.
-# If a real dSYM is ever needed, it's still possible to create one by running
-# dsymutil and pointing it at the original Mach-O file inside the "fake"
-# bundle, provided that the object files are available.
-
-import errno
-import os
-import re
-import shutil
-import subprocess
-import sys
-import time
-
-# Returns a list of architectures contained in a Mach-O file.  The file can be
-# a universal (fat) file, in which case there will be one list element for
-# each contained architecture, or it can be a thin single-architecture Mach-O
-# file, in which case the list will contain a single element identifying the
-# architecture.  On error, returns an empty list.  Determines the architecture
-# list by calling file.
-def macho_archs(macho):
-  macho_types = ["executable",
-                 "dynamically linked shared library",
-                 "bundle"]
-  macho_types_re = "Mach-O (?:64-bit )?(?:" + "|".join(macho_types) + ")"
-
-  file_cmd = subprocess.Popen(["/usr/bin/file", "-b", "--", macho],
-                              stdout=subprocess.PIPE)
-
-  archs = []
-
-  type_line = file_cmd.stdout.readline()
-  type_match = re.match("^%s (.*)$" % macho_types_re, type_line)
-  if type_match:
-    archs.append(type_match.group(1))
-    return [type_match.group(1)]
-  else:
-    type_match = re.match("^Mach-O universal binary with (.*) architectures$",
-                          type_line)
-    if type_match:
-      for i in range(0, int(type_match.group(1))):
-        arch_line = file_cmd.stdout.readline()
-        arch_match = re.match(
-                     "^.* \(for architecture (.*)\):\t%s .*$" % macho_types_re,
-                     arch_line)
-        if arch_match:
-          archs.append(arch_match.group(1))
-
-  if file_cmd.wait() != 0:
-    archs = []
-
-  if len(archs) == 0:
-    print >> sys.stderr, "No architectures in %s" % macho
-
-  return archs
-
-# Returns a dictionary mapping architectures contained in the file as returned
-# by macho_archs to the LC_UUID load command for that architecture.
-# Architectures with no LC_UUID load command are omitted from the dictionary.
-# Determines the UUID value by calling otool.
-def macho_uuids(macho):
-  uuids = {}
-
-  archs = macho_archs(macho)
-  if len(archs) == 0:
-    return uuids
-
-  for arch in archs:
-    if arch == "":
-      continue
-
-    otool_cmd = subprocess.Popen(["/usr/bin/otool", "-arch", arch, "-l", "-",
-                                  macho],
-                                 stdout=subprocess.PIPE)
-    # state 0 is when nothing UUID-related has been seen yet.  State 1 is
-    # entered after a load command begins, but it may not be an LC_UUID load
-    # command.  States 2, 3, and 4 are intermediate states while reading an
-    # LC_UUID command.  State 5 is the terminal state for a successful LC_UUID
-    # read.  State 6 is the error state.
-    state = 0
-    uuid = ""
-    for otool_line in otool_cmd.stdout:
-      if state == 0:
-        if re.match("^Load command .*$", otool_line):
-          state = 1
-      elif state == 1:
-        if re.match("^     cmd LC_UUID$", otool_line):
-          state = 2
-        else:
-          state = 0
-      elif state == 2:
-        if re.match("^ cmdsize 24$", otool_line):
-          state = 3
-        else:
-          state = 6
-      elif state == 3:
-        # The UUID display format changed in the version of otool shipping
-        # with the Xcode 3.2.2 prerelease.  The new format is traditional:
-        #    uuid 4D7135B2-9C56-C5F5-5F49-A994258E0955
-        # The old format, from cctools-750 and older's otool, breaks the UUID
-        # up into a sequence of bytes:
-        #    uuid 0x4d 0x71 0x35 0xb2 0x9c 0x56 0xc5 0xf5
-        #         0x5f 0x49 0xa9 0x94 0x25 0x8e 0x09 0x55
-        new_uuid_match = re.match("^   uuid (.{8}-.{4}-.{4}-.{4}-.{12})$",
-                                  otool_line)
-        if new_uuid_match:
-          uuid = new_uuid_match.group(1)
-
-          # Skip state 4, there is no second line to read.
-          state = 5
-        else:
-          old_uuid_match = re.match("^   uuid 0x(..) 0x(..) 0x(..) 0x(..) "
-                                    "0x(..) 0x(..) 0x(..) 0x(..)$",
-                                    otool_line)
-          if old_uuid_match:
-            state = 4
-            uuid = old_uuid_match.group(1) + old_uuid_match.group(2) + \
-                   old_uuid_match.group(3) + old_uuid_match.group(4) + "-" + \
-                   old_uuid_match.group(5) + old_uuid_match.group(6) + "-" + \
-                   old_uuid_match.group(7) + old_uuid_match.group(8) + "-"
-          else:
-            state = 6
-      elif state == 4:
-        old_uuid_match = re.match("^        0x(..) 0x(..) 0x(..) 0x(..) "
-                                  "0x(..) 0x(..) 0x(..) 0x(..)$",
-                                  otool_line)
-        if old_uuid_match:
-          state = 5
-          uuid += old_uuid_match.group(1) + old_uuid_match.group(2) + "-" + \
-                  old_uuid_match.group(3) + old_uuid_match.group(4) + \
-                  old_uuid_match.group(5) + old_uuid_match.group(6) + \
-                  old_uuid_match.group(7) + old_uuid_match.group(8)
-        else:
-          state = 6
-
-    if otool_cmd.wait() != 0:
-      state = 6
-
-    if state == 5:
-      uuids[arch] = uuid.upper()
-
-  if len(uuids) == 0:
-    print >> sys.stderr, "No UUIDs in %s" % macho
-
-  return uuids
-
-# Given a path to a Mach-O file and possible information from the environment,
-# determines the desired path to the .dSYM.
-def dsym_path(macho):
-  # If building a bundle, the .dSYM should be placed next to the bundle.  Use
-  # WRAPPER_NAME to make this determination.  If called from xcodebuild,
-  # WRAPPER_NAME will be set to the name of the bundle.
-  dsym = ""
-  if "WRAPPER_NAME" in os.environ:
-    if "BUILT_PRODUCTS_DIR" in os.environ:
-      dsym = os.path.join(os.environ["BUILT_PRODUCTS_DIR"],
-                          os.environ["WRAPPER_NAME"])
-    else:
-      dsym = os.environ["WRAPPER_NAME"]
-  else:
-    dsym = macho
-
-  dsym += ".dSYM"
-
-  return dsym
-
-# Creates a fake .dSYM bundle at dsym for macho, a Mach-O image with the
-# architectures and UUIDs specified by the uuids map.
-def make_fake_dsym(macho, dsym):
-  uuids = macho_uuids(macho)
-  if len(uuids) == 0:
-    return False
-
-  dwarf_dir = os.path.join(dsym, "Contents", "Resources", "DWARF")
-  dwarf_file = os.path.join(dwarf_dir, os.path.basename(macho))
-  try:
-    os.makedirs(dwarf_dir)
-  except OSError, (err, error_string):
-    if err != errno.EEXIST:
-      raise
-  shutil.copyfile(macho, dwarf_file)
-
-  # info_template is the same as what dsymutil would have written, with the
-  # addition of the fake_dsym key.
-  info_template = \
-'''<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-	<dict>
-		<key>CFBundleDevelopmentRegion</key>
-		<string>English</string>
-		<key>CFBundleIdentifier</key>
-		<string>com.apple.xcode.dsym.%(root_name)s</string>
-		<key>CFBundleInfoDictionaryVersion</key>
-		<string>6.0</string>
-		<key>CFBundlePackageType</key>
-		<string>dSYM</string>
-		<key>CFBundleSignature</key>
-		<string>????</string>
-		<key>CFBundleShortVersionString</key>
-		<string>1.0</string>
-		<key>CFBundleVersion</key>
-		<string>1</string>
-		<key>dSYM_UUID</key>
-		<dict>
-%(uuid_dict)s		</dict>
-		<key>fake_dsym</key>
-		<true/>
-	</dict>
-</plist>
-'''
-
-  root_name = os.path.basename(dsym)[:-5]  # whatever.dSYM without .dSYM
-  uuid_dict = ""
-  for arch in sorted(uuids):
-    uuid_dict += "\t\t\t<key>" + arch + "</key>\n"\
-                 "\t\t\t<string>" + uuids[arch] + "</string>\n"
-  info_dict = {
-    "root_name": root_name,
-    "uuid_dict": uuid_dict,
-  }
-  info_contents = info_template % info_dict
-  info_file = os.path.join(dsym, "Contents", "Info.plist")
-  info_fd = open(info_file, "w")
-  info_fd.write(info_contents)
-  info_fd.close()
-
-  return True
-
-# For a Mach-O file, determines where the .dSYM bundle should be located.  If
-# the bundle does not exist or has a modification time older than the Mach-O
-# file, calls make_fake_dsym to create a fake .dSYM bundle there, then strips
-# the Mach-O file and sets the modification time on the .dSYM bundle and Mach-O
-# file to be identical.
-def strip_and_make_fake_dsym(macho):
-  dsym = dsym_path(macho)
-  macho_stat = os.stat(macho)
-  dsym_stat = None
-  try:
-    dsym_stat = os.stat(dsym)
-  except OSError, (err, error_string):
-    if err != errno.ENOENT:
-      raise
-
-  if dsym_stat is None or dsym_stat.st_mtime < macho_stat.st_mtime:
-    # Make a .dSYM bundle
-    if not make_fake_dsym(macho, dsym):
-      return False
-
-    # Strip the Mach-O file
-    remove_dsym = True
-    try:
-      strip_path = ""
-      if "SYSTEM_DEVELOPER_BIN_DIR" in os.environ:
-        strip_path = os.environ["SYSTEM_DEVELOPER_BIN_DIR"]
-      else:
-        strip_path = "/usr/bin"
-      strip_path = os.path.join(strip_path, "strip")
-      strip_cmdline = [strip_path] + sys.argv[1:]
-      # Print the strip invocation so that it's obvious something is happening
-      print " ".join(strip_cmdline)
-      strip_cmd = subprocess.Popen(strip_cmdline)
-      if strip_cmd.wait() == 0:
-        remove_dsym = False
-    finally:
-      if remove_dsym:
-        shutil.rmtree(dsym)
-
-    # Update modification time on the Mach-O file and .dSYM bundle
-    now = time.time()
-    os.utime(macho, (now, now))
-    os.utime(dsym, (now, now))
-
-  return True
-
-def main(argv=None):
-  if argv is None:
-    argv = sys.argv
-
-  # This only supports operating on one file at a time.  Look at the arguments
-  # to strip to figure out what the source to be stripped is.  Arguments are
-  # processed in the same way that strip does, although to reduce complexity,
-  # this doesn't do all of the same checking as strip.  For example, strip
-  # has no -Z switch and would treat -Z on the command line as an error.  For
-  # the purposes this is needed for, that's fine.
-  macho = None
-  process_switches = True
-  ignore_argument = False
-  for arg in argv[1:]:
-    if ignore_argument:
-      ignore_argument = False
-      continue
-    if process_switches:
-      if arg == "-":
-        process_switches = False
-      # strip has these switches accept an argument:
-      if arg in ["-s", "-R", "-d", "-o", "-arch"]:
-        ignore_argument = True
-      if arg[0] == "-":
-        continue
-    if macho is None:
-      macho = arg
-    else:
-      print >> sys.stderr, "Too many things to strip"
-      return 1
-
-  if macho is None:
-    print >> sys.stderr, "Nothing to strip"
-    return 1
-
-  if not strip_and_make_fake_dsym(macho):
-    return 1
-
-  return 0
-
-if __name__ == "__main__":
-  sys.exit(main(sys.argv))
diff --git a/build/temp_gyp/.svn/all-wcprops b/build/temp_gyp/.svn/all-wcprops
deleted file mode 100644
index 08e4f77..0000000
--- a/build/temp_gyp/.svn/all-wcprops
+++ /dev/null
@@ -1,23 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 44
-/svn/!svn/ver/52614/trunk/src/build/temp_gyp
-END
-README.chromium
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/10380/trunk/src/build/temp_gyp/README.chromium
-END
-pdfsqueeze.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 59
-/svn/!svn/ver/28089/trunk/src/build/temp_gyp/pdfsqueeze.gyp
-END
-googleurl.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/52614/trunk/src/build/temp_gyp/googleurl.gyp
-END
diff --git a/build/temp_gyp/.svn/dir-prop-base b/build/temp_gyp/.svn/dir-prop-base
deleted file mode 100644
index f69b131..0000000
--- a/build/temp_gyp/.svn/dir-prop-base
+++ /dev/null
@@ -1,20 +0,0 @@
-K 10
-svn:ignore
-V 279
-SConstruct
-googleurl.scons
-googleurl.sln
-googleurl.vcproj
-googleurl.xcodeproj
-googleurl_main.scons
-googleurl_unittests.scons
-googleurl_unittests.vcproj
-pdfsqueeze.xcodeproj
-googleurl.mk
-googleurl_unittests.mk
-googleurl.target.mk
-googleurl.Makefile
-googleurl_unittests.target.mk
-
-
-END
diff --git a/build/temp_gyp/.svn/entries b/build/temp_gyp/.svn/entries
deleted file mode 100644
index d3a57b6..0000000
--- a/build/temp_gyp/.svn/entries
+++ /dev/null
@@ -1,130 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build/temp_gyp
-http://src.chromium.org/svn
-
-
-
-2010-07-16T05:44:08.289599Z
-52614
-victorw@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-README.chromium
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-3ff4aeeb56d937badeae5bc68e916561
-2009-02-25T21:26:55.507860Z
-10380
-mark@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-162
-
-pdfsqueeze.gyp
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-2d5427d2c6745523d4f4e513cfff54b8
-2009-10-06T03:02:38.090039Z
-28089
-sgk@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1397
-
-googleurl.gyp
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-55222cd4f4cee2d13c3826f75168c57f
-2010-07-16T05:44:08.289599Z
-52614
-victorw@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3757
-
diff --git a/build/temp_gyp/.svn/prop-base/README.chromium.svn-base b/build/temp_gyp/.svn/prop-base/README.chromium.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/temp_gyp/.svn/prop-base/README.chromium.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/temp_gyp/.svn/prop-base/googleurl.gyp.svn-base b/build/temp_gyp/.svn/prop-base/googleurl.gyp.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/temp_gyp/.svn/prop-base/googleurl.gyp.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/temp_gyp/.svn/prop-base/pdfsqueeze.gyp.svn-base b/build/temp_gyp/.svn/prop-base/pdfsqueeze.gyp.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/temp_gyp/.svn/prop-base/pdfsqueeze.gyp.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/temp_gyp/.svn/text-base/README.chromium.svn-base b/build/temp_gyp/.svn/text-base/README.chromium.svn-base
deleted file mode 100644
index 8045d61..0000000
--- a/build/temp_gyp/.svn/text-base/README.chromium.svn-base
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory will be removed once the files in it are committed upstream and
-Chromium imports an upstream revision with these files.  Contact mark for
-details.
diff --git a/build/temp_gyp/.svn/text-base/googleurl.gyp.svn-base b/build/temp_gyp/.svn/text-base/googleurl.gyp.svn-base
deleted file mode 100644
index 9a2eda3..0000000
--- a/build/temp_gyp/.svn/text-base/googleurl.gyp.svn-base
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# TODO(mark): Upstream this file to googleurl.
-{
-  'variables': {
-    'chromium_code': 1,
-  },
-  'targets': [
-    {
-      'target_name': 'googleurl',
-      'type': '<(component)',
-      'msvs_guid': 'EF5E94AB-B646-4E5B-A058-52EF07B8351C',
-      'dependencies': [
-        '../../base/base.gyp:base',
-        '../../third_party/icu/icu.gyp:icudata',
-        '../../third_party/icu/icu.gyp:icui18n',
-        '../../third_party/icu/icu.gyp:icuuc',
-      ],
-      'sources': [
-        '../../googleurl/src/gurl.cc',
-        '../../googleurl/src/gurl.h',
-        '../../googleurl/src/url_canon.h',
-        '../../googleurl/src/url_canon_etc.cc',
-        '../../googleurl/src/url_canon_fileurl.cc',
-        '../../googleurl/src/url_canon_host.cc',
-        '../../googleurl/src/url_canon_icu.cc',
-        '../../googleurl/src/url_canon_icu.h',
-        '../../googleurl/src/url_canon_internal.cc',
-        '../../googleurl/src/url_canon_internal.h',
-        '../../googleurl/src/url_canon_internal_file.h',
-        '../../googleurl/src/url_canon_ip.cc',
-        '../../googleurl/src/url_canon_ip.h',
-        '../../googleurl/src/url_canon_mailtourl.cc',
-        '../../googleurl/src/url_canon_path.cc',
-        '../../googleurl/src/url_canon_pathurl.cc',
-        '../../googleurl/src/url_canon_query.cc',
-        '../../googleurl/src/url_canon_relative.cc',
-        '../../googleurl/src/url_canon_stdstring.h',
-        '../../googleurl/src/url_canon_stdurl.cc',
-        '../../googleurl/src/url_file.h',
-        '../../googleurl/src/url_parse.cc',
-        '../../googleurl/src/url_parse.h',
-        '../../googleurl/src/url_parse_file.cc',
-        '../../googleurl/src/url_parse_internal.h',
-        '../../googleurl/src/url_util.cc',
-        '../../googleurl/src/url_util.h',
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '../..',
-        ],
-      },
-      'conditions': [
-        ['OS=="win" and component=="shared_library"', {
-          'defines': [
-            'GURL_DLL',
-            'GURL_IMPLEMENTATION=1',
-          ],
-          'direct_dependent_settings': {
-            'defines': [
-              'GURL_DLL',
-            ],
-          },
-        }],
-      ],
-    },
-    {
-      'target_name': 'googleurl_unittests',
-      'dependencies': [
-        'googleurl',
-        '../../testing/gtest.gyp:gtest',
-        '../../third_party/icu/icu.gyp:icuuc',
-      ],
-      'sources': [
-        '../../googleurl/src/gurl_unittest.cc',
-        '../../googleurl/src/url_canon_unittest.cc',
-        '../../googleurl/src/url_parse_unittest.cc',
-        '../../googleurl/src/url_test_utils.h',
-        '../../googleurl/src/url_util_unittest.cc',
-        '../../googleurl/src/gurl_test_main.cc',
-      ],
-      'conditions': [
-        ['OS=="linux" or OS=="freebsd"', {
-          'conditions': [
-            ['linux_use_tcmalloc==1', {
-              'dependencies': [
-                '../../base/allocator/allocator.gyp:allocator',
-              ],
-            }],
-          ],
-        }],
-        # TODO(victorw): The unittest code uses inline functions that access
-        # global variables, it also uses internal functions that we may not want
-        # to export, so skip building unittests for windows multi dll build.
-        # The googleurl functions are tested by the static library build.
-        ['OS=="win" and component=="shared_library"', {
-          'type': 'none',
-        }, {
-          'type': 'executable',
-        }],
-      ],
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/temp_gyp/.svn/text-base/pdfsqueeze.gyp.svn-base b/build/temp_gyp/.svn/text-base/pdfsqueeze.gyp.svn-base
deleted file mode 100644
index d7a742c..0000000
--- a/build/temp_gyp/.svn/text-base/pdfsqueeze.gyp.svn-base
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'pdfsqueeze',
-      'type': 'executable',
-      'sources': [
-        '../../third_party/pdfsqueeze/pdfsqueeze.m',
-      ],
-      'defines': [
-        # Use defines to map the full path names that will be used for
-        # the vars into the short forms expected by pdfsqueeze.m.
-        '______third_party_pdfsqueeze_ApplyGenericRGB_qfilter=ApplyGenericRGB_qfilter',
-        '______third_party_pdfsqueeze_ApplyGenericRGB_qfilter_len=ApplyGenericRGB_qfilter_len',
-      ],
-      'include_dirs': [
-        '<(INTERMEDIATE_DIR)',
-      ],
-      'libraries': [
-        '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
-        '$(SDKROOT)/System/Library/Frameworks/Quartz.framework',
-      ],
-      'actions': [
-        {
-          'action_name': 'Generate inline filter data',
-          'inputs': [
-            '../../third_party/pdfsqueeze/ApplyGenericRGB.qfilter',
-          ],
-          'outputs': [
-            '<(INTERMEDIATE_DIR)/ApplyGenericRGB.h',
-          ],
-          'action': ['xxd', '-i', '<@(_inputs)', '<@(_outputs)'],
-        },
-      ],
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/util/.svn/all-wcprops b/build/util/.svn/all-wcprops
deleted file mode 100644
index 12ba8a0..0000000
--- a/build/util/.svn/all-wcprops
+++ /dev/null
@@ -1,17 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 40
-/svn/!svn/ver/61526/trunk/src/build/util
-END
-lastchange.py
-K 25
-svn:wc:ra_dav:version-url
-V 54
-/svn/!svn/ver/61526/trunk/src/build/util/lastchange.py
-END
-build_util.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/39223/trunk/src/build/util/build_util.gyp
-END
diff --git a/build/util/.svn/dir-prop-base b/build/util/.svn/dir-prop-base
deleted file mode 100644
index b3ca30d..0000000
--- a/build/util/.svn/dir-prop-base
+++ /dev/null
@@ -1,16 +0,0 @@
-K 10
-svn:ignore
-V 168
-build_util.xcodeproj
-build_util.sln
-lastchange.vcproj
-SConstruct
-build_util_main.scons
-lastchange.scons
-support
-lastchange.mk
-lastchange.target.mk
-build_util.Makefile
-
-
-END
diff --git a/build/util/.svn/entries b/build/util/.svn/entries
deleted file mode 100644
index 5949de0..0000000
--- a/build/util/.svn/entries
+++ /dev/null
@@ -1,96 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build/util
-http://src.chromium.org/svn
-
-
-
-2010-10-05T17:36:30.884599Z
-61526
-dilmah@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-lastchange.py
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-f40e1d7b2d611ca8962c82d86221874b
-2010-10-05T17:36:30.884599Z
-61526
-dilmah@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3291
-
-build_util.gyp
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-a94ae655e906add9d2b69ed4c92013d7
-2010-02-17T16:49:27.514326Z
-39223
-mmoss@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1195
-
diff --git a/build/util/.svn/prop-base/build_util.gyp.svn-base b/build/util/.svn/prop-base/build_util.gyp.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/util/.svn/prop-base/build_util.gyp.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/util/.svn/prop-base/lastchange.py.svn-base b/build/util/.svn/prop-base/lastchange.py.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/util/.svn/prop-base/lastchange.py.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/util/.svn/text-base/build_util.gyp.svn-base b/build/util/.svn/text-base/build_util.gyp.svn-base
deleted file mode 100644
index a909177..0000000
--- a/build/util/.svn/text-base/build_util.gyp.svn-base
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'lastchange',
-      'type': 'none',
-      'variables': {
-        'lastchange_out_path': '<(SHARED_INTERMEDIATE_DIR)/build/LASTCHANGE',
-        'default_lastchange_path': '../LASTCHANGE.in',
-      },
-      'actions': [
-        {
-          'action_name': 'lastchange',
-          'inputs': [
-            # Note:  <(default_lastchange_path) is optional,
-            # so it doesn't show up in inputs.
-            './lastchange.py',
-          ],
-          'outputs': [
-            '<(lastchange_out_path).always',
-            '<(lastchange_out_path)',
-          ],
-          'action': [
-            'python', '<@(_inputs)',
-            '-o', '<(lastchange_out_path)',
-            '-d', '<(default_lastchange_path)',
-          ],
-          'message': 'Extracting last change to <(lastchange_out_path)',
-          'process_outputs_as_sources': '1',
-        },
-      ],
-    },
-  ]
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/build/util/.svn/text-base/lastchange.py.svn-base b/build/util/.svn/text-base/lastchange.py.svn-base
deleted file mode 100644
index 00b275f..0000000
--- a/build/util/.svn/text-base/lastchange.py.svn-base
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""
-lastchange.py -- Chromium revision fetching utility.
-"""
-
-import optparse
-import os
-import re
-import subprocess
-import sys
-
-
-def svn_fetch_revision():
-  """
-  Fetch the Subversion revision for the local tree.
-
-  Errors are swallowed.
-  """
-  try:
-    p = subprocess.Popen(['svn', 'info'],
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE,
-                         shell=(sys.platform=='win32'))
-  except OSError, e:
-    # 'svn' is apparently either not installed or not executable.
-    return None
-  revision = None
-  if p:
-    svn_re = re.compile('^Revision:\s+(\d+)', re.M)
-    m = svn_re.search(p.stdout.read())
-    if m:
-      revision = m.group(1)
-  return revision
-
-
-def git_fetch_id():
-  """
-  Fetch the GIT identifier for the local tree.
-
-  Errors are swallowed.
-  """
-  git_re = re.compile('^\s*git-svn-id:\s+(\S+)@(\d+)', re.M)
-  try:
-    proc = subprocess.Popen(['git', 'log', '-999'],
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.PIPE,
-                            shell=(sys.platform=='win32'))
-    for line in proc.stdout:
-      match = git_re.search(line)
-      if match:
-        id = match.group(2)
-        if id:
-          proc.stdout.close()  # Cut pipe.
-          return id
-  except OSError:
-    # 'git' is apparently either not installed or not executable.
-    pass
-  return None
-
-
-def fetch_change(default_lastchange):
-  """
-  Returns the last change, from some appropriate revision control system.
-  """
-  change = svn_fetch_revision()
-  if not change and sys.platform in ('linux2',):
-    change = git_fetch_id()
-  if not change:
-    if default_lastchange and os.path.exists(default_lastchange):
-      change = open(default_lastchange, 'r').read().strip()
-    else:
-      change = '0'
-  return change
-
-
-def write_if_changed(file_name, contents):
-  """
-  Writes the specified contents to the specified file_name
-  iff the contents are different than the current contents.
-  """
-  try:
-    old_contents = open(file_name, 'r').read()
-  except EnvironmentError:
-    pass
-  else:
-    if contents == old_contents:
-      return
-    os.unlink(file_name)
-  open(file_name, 'w').write(contents)
-
-
-def main(argv=None):
-  if argv is None:
-    argv = sys.argv
-
-  parser = optparse.OptionParser(usage="lastchange.py [-h] [[-o] FILE]")
-  parser.add_option("-d", "--default-lastchange", metavar="FILE",
-                    help="default last change input FILE")
-  parser.add_option("-o", "--output", metavar="FILE",
-                    help="write last change to FILE")
-  opts, args = parser.parse_args(argv[1:])
-
-  out_file = opts.output
-
-  while len(args) and out_file is None:
-    if out_file is None:
-      out_file = args.pop(0)
-  if args:
-    sys.stderr.write('Unexpected arguments: %r\n\n' % args)
-    parser.print_help()
-    sys.exit(2)
-
-  change = fetch_change(opts.default_lastchange)
-
-  contents = "LASTCHANGE=%s\n" % change
-
-  if out_file:
-    write_if_changed(out_file, contents)
-  else:
-    sys.stdout.write(contents)
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
old mode 100644
new mode 100755
index 00b275f..c7200f1
--- a/build/util/lastchange.py
+++ b/build/util/lastchange.py
@@ -9,75 +9,99 @@
 
 import optparse
 import os
-import re
 import subprocess
 import sys
 
+class VersionInfo(object):
+  def __init__(self, url, root, revision):
+    self.url = url
+    self.root = root
+    self.revision = revision
 
-def svn_fetch_revision():
+def FetchGitRevision(directory):
   """
-  Fetch the Subversion revision for the local tree.
+  Fetch the Git hash for the a given directory.
 
   Errors are swallowed.
+
+  Returns:
+    a VersionInfo object or None on error.
   """
+  # Force shell usage under cygwin & win32. This is a workaround for
+  # mysterious loss of cwd while invoking cygwin's git.
+  # We can't just pass shell=True to Popen, as under win32 this will
+  # cause CMD to be used, while we explicitly want a cygwin shell.
+  command = ['git', 'rev-parse', 'HEAD']
+  if sys.platform in ('cygwin', 'win32'):
+    command = ['sh', '-c', ' '.join(command)]
   try:
-    p = subprocess.Popen(['svn', 'info'],
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE,
-                         shell=(sys.platform=='win32'))
-  except OSError, e:
-    # 'svn' is apparently either not installed or not executable.
-    return None
-  revision = None
-  if p:
-    svn_re = re.compile('^Revision:\s+(\d+)', re.M)
-    m = svn_re.search(p.stdout.read())
-    if m:
-      revision = m.group(1)
-  return revision
-
-
-def git_fetch_id():
-  """
-  Fetch the GIT identifier for the local tree.
-
-  Errors are swallowed.
-  """
-  git_re = re.compile('^\s*git-svn-id:\s+(\S+)@(\d+)', re.M)
-  try:
-    proc = subprocess.Popen(['git', 'log', '-999'],
+    proc = subprocess.Popen(command,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
-                            shell=(sys.platform=='win32'))
-    for line in proc.stdout:
-      match = git_re.search(line)
-      if match:
-        id = match.group(2)
-        if id:
-          proc.stdout.close()  # Cut pipe.
-          return id
+                            cwd=directory)
   except OSError:
-    # 'git' is apparently either not installed or not executable.
-    pass
+    return None
+  output = proc.communicate()[0].strip()
+  if proc.returncode == 0 and output:
+    return VersionInfo('git', 'git', output[:7])
   return None
 
 
-def fetch_change(default_lastchange):
+def FetchSVNRevision(directory):
   """
-  Returns the last change, from some appropriate revision control system.
+  Fetch the Subversion branch and revision for the a given directory.
+
+  Errors are swallowed.
+
+  Returns:
+    a VersionInfo object or None on error.
   """
-  change = svn_fetch_revision()
-  if not change and sys.platform in ('linux2',):
-    change = git_fetch_id()
-  if not change:
+  try:
+    proc = subprocess.Popen(['svn', 'info'],
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE,
+                            cwd=directory,
+                            shell=(sys.platform=='win32'))
+  except OSError:
+    # command is apparently either not installed or not executable.
+    return None
+  if not proc:
+    return None
+
+  attrs = {}
+  for line in proc.stdout:
+    line = line.strip()
+    if not line:
+      continue
+    key, val = line.split(': ', 1)
+    attrs[key] = val
+
+  try:
+    url = attrs['URL']
+    root = attrs['Repository Root']
+    revision = attrs['Revision']
+  except KeyError:
+    return None
+
+  return VersionInfo(url, root, revision)
+
+
+def FetchVersionInfo(default_lastchange, directory=None):
+  """
+  Returns the last change (in the form of a branch, revision tuple),
+  from some appropriate revision control system.
+  """
+  version_info = FetchSVNRevision(directory) or FetchGitRevision(directory)
+  if not version_info:
     if default_lastchange and os.path.exists(default_lastchange):
-      change = open(default_lastchange, 'r').read().strip()
+      revision = open(default_lastchange, 'r').read().strip()
+      version_info = VersionInfo(None, None, revision)
     else:
-      change = '0'
-  return change
+      version_info = VersionInfo('unknown', '', '0')
+  return version_info
 
 
-def write_if_changed(file_name, contents):
+def WriteIfChanged(file_name, contents):
   """
   Writes the specified contents to the specified file_name
   iff the contents are different than the current contents.
@@ -97,11 +121,13 @@
   if argv is None:
     argv = sys.argv
 
-  parser = optparse.OptionParser(usage="lastchange.py [-h] [[-o] FILE]")
+  parser = optparse.OptionParser(usage="lastchange.py [options]")
   parser.add_option("-d", "--default-lastchange", metavar="FILE",
                     help="default last change input FILE")
   parser.add_option("-o", "--output", metavar="FILE",
                     help="write last change to FILE")
+  parser.add_option("--revision-only", action='store_true',
+                    help="just print the SVN revision number")
   opts, args = parser.parse_args(argv[1:])
 
   out_file = opts.output
@@ -114,14 +140,16 @@
     parser.print_help()
     sys.exit(2)
 
-  change = fetch_change(opts.default_lastchange)
+  version_info = FetchVersionInfo(opts.default_lastchange)
 
-  contents = "LASTCHANGE=%s\n" % change
-
-  if out_file:
-    write_if_changed(out_file, contents)
+  if opts.revision_only:
+    print version_info.revision
   else:
-    sys.stdout.write(contents)
+    contents = "LASTCHANGE=%s\n" % version_info.revision
+    if out_file:
+      WriteIfChanged(out_file, contents)
+    else:
+      sys.stdout.write(contents)
 
   return 0
 
diff --git a/build/util/support/.svn/all-wcprops b/build/util/support/.svn/all-wcprops
deleted file mode 100644
index 0c76434..0000000
--- a/build/util/support/.svn/all-wcprops
+++ /dev/null
@@ -1,11 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 38
-/svn/!svn/ver/20411/trunk/deps/support
-END
-support.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 50
-/svn/!svn/ver/18977/trunk/deps/support/support.gyp
-END
diff --git a/build/util/support/.svn/dir-prop-base b/build/util/support/.svn/dir-prop-base
deleted file mode 100644
index 7d19edf..0000000
--- a/build/util/support/.svn/dir-prop-base
+++ /dev/null
@@ -1,11 +0,0 @@
-K 10
-svn:ignore
-V 89
-support.xcodeproj
-support.sln
-support.vcproj
-support.scons
-support_main.scons
-SConstruct
-
-END
diff --git a/build/util/support/.svn/entries b/build/util/support/.svn/entries
deleted file mode 100644
index 202a5d1..0000000
--- a/build/util/support/.svn/entries
+++ /dev/null
@@ -1,62 +0,0 @@
-10
-
-dir
-70887
-http://src.chromium.org/svn/trunk/deps/support
-http://src.chromium.org/svn
-
-
-
-2009-07-10T20:45:27.710843Z
-20411
-maruel@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-support.gyp
-file
-
-
-
-
-2011-05-16T13:47:41.000000Z
-9e82dfc26643f6910d7e89c93f3482ef
-2009-06-22T23:11:42.165255Z
-18977
-slightlyoff@chromium.org
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-411
-
diff --git a/build/util/support/.svn/text-base/support.gyp.svn-base b/build/util/support/.svn/text-base/support.gyp.svn-base
deleted file mode 100644
index 5840f80..0000000
--- a/build/util/support/.svn/text-base/support.gyp.svn-base
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'variables': {
-    'chromium_code': 1,
-  },
-  'includes': [
-    '../../common.gypi',
-  ],
-  'targets': [
-    {
-      'target_name': 'support',
-      'type': 'none',
-    },
-    # TODO(slightlyoff)
-  ],
-}
-
-# vim: shiftwidth=2:et:ai:tabstop=2
diff --git a/build/win/.svn/all-wcprops b/build/win/.svn/all-wcprops
deleted file mode 100644
index 1302eea..0000000
--- a/build/win/.svn/all-wcprops
+++ /dev/null
@@ -1,17 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 39
-/svn/!svn/ver/61430/trunk/src/build/win
-END
-chrome_win.croc
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/61430/trunk/src/build/win/chrome_win.croc
-END
-system.gyp
-K 25
-svn:wc:ra_dav:version-url
-V 50
-/svn/!svn/ver/28089/trunk/src/build/win/system.gyp
-END
diff --git a/build/win/.svn/dir-prop-base b/build/win/.svn/dir-prop-base
deleted file mode 100644
index d9a97b6..0000000
--- a/build/win/.svn/dir-prop-base
+++ /dev/null
@@ -1,7 +0,0 @@
-K 10
-svn:ignore
-V 25
-cygwin.vcproj
-system.sln
-
-END
diff --git a/build/win/.svn/entries b/build/win/.svn/entries
deleted file mode 100644
index ff20a7b..0000000
--- a/build/win/.svn/entries
+++ /dev/null
@@ -1,96 +0,0 @@
-10
-
-dir
-70875
-http://src.chromium.org/svn/trunk/src/build/win
-http://src.chromium.org/svn
-
-
-
-2010-10-04T22:56:50.780169Z
-61430
-jrg@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-4ff67af0-8c30-449e-8e8b-ad334ec8d88c
-
-chrome_win.croc
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-543f11b337d8bfe217b8607213a6cfe0
-2010-10-04T22:56:50.780169Z
-61430
-jrg@chromium.org
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-532
-
-system.gyp
-file
-
-
-
-
-2011-05-16T13:12:11.000000Z
-3e1258608d17c81c63fb44b43bf93769
-2009-10-06T03:02:38.090039Z
-28089
-sgk@google.com
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-832
-
diff --git a/build/win/.svn/prop-base/chrome_win.croc.svn-base b/build/win/.svn/prop-base/chrome_win.croc.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/win/.svn/prop-base/chrome_win.croc.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/win/.svn/prop-base/system.gyp.svn-base b/build/win/.svn/prop-base/system.gyp.svn-base
deleted file mode 100644
index abd5821..0000000
--- a/build/win/.svn/prop-base/system.gyp.svn-base
+++ /dev/null
@@ -1,5 +0,0 @@
-K 13
-svn:eol-style
-V 2
-LF
-END
diff --git a/build/win/.svn/text-base/chrome_win.croc.svn-base b/build/win/.svn/text-base/chrome_win.croc.svn-base
deleted file mode 100644
index e1e3bb7..0000000
--- a/build/win/.svn/text-base/chrome_win.croc.svn-base
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- python -*-
-# Crocodile config file for Chromium windows
-
-{
-  # List of rules, applied in order
-  'rules' : [
-    # Specify inclusions before exclusions, since rules are in order.
-
-    # Don't include chromeos, posix, or linux specific files
-    {
-      'regexp' : '.*(_|/)(chromeos|linux|posix)(\\.|_)',
-      'include' : 0,
-    },
-    # Don't include ChromeOS dirs
-    {
-      'regexp' : '.*/chromeos/',
-      'include' : 0,
-    },
-
-    # Groups
-    {
-      'regexp' : '.*_test_win\\.',
-      'group' : 'test',
-    },
-  ],
-}
diff --git a/build/win/.svn/text-base/system.gyp.svn-base b/build/win/.svn/text-base/system.gyp.svn-base
deleted file mode 100644
index 0c06849..0000000
--- a/build/win/.svn/text-base/system.gyp.svn-base
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'cygwin',
-      'type': 'none',
-      'actions': [
-        {
-          'action_name': 'setup_mount',
-          'msvs_cygwin_shell': 0,
-          'inputs': [
-            '../../third_party/cygwin/setup_mount.bat',
-          ],
-          # Visual Studio requires an output file, or else the
-          # custom build step won't run.
-          'outputs': [
-            '../../third_party/cygwin/_always_run_setup_mount.marker',
-          ],
-          'action': ['', '<@(_inputs)'],
-        },
-      ],
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 1d4653b..757e0b4 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -8,6 +8,7 @@
   "+chrome/tools/profiles",  # For history unit tests.
   "+chrome/views",
   "+grit",  # For generated headers
+  "+policy",  # For generated headers and source
   "+ppapi/c",  # For various types.
   "+ppapi/proxy",
   "+rlz",
@@ -37,7 +38,8 @@
   "+third_party/undoview",
   "+v8/include",  # Browser uses V8 to get the version and run the debugger.
 
-  # FIXME: this should probably not be here, we need to find a better
+  # FIXME: these should probably not be here, we need to find a better
   # structure for these includes.
   "+chrome/renderer",
+  "+chrome/gpu",
 ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 69b7a4e..f2374ed 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -9,7 +9,6 @@
 #include <map>
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/singleton.h"
 #include "base/string_number_conversions.h"
@@ -19,14 +18,17 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace about_flags {
 
 // Macros to simplify specifying the type.
-#define SINGLE_VALUE_TYPE(command_line) Experiment::SINGLE_VALUE, \
-    command_line, NULL, 0
-#define MULTI_VALUE_TYPE(choices) Experiment::MULTI_VALUE, "", choices, \
-    arraysize(choices)
+#define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \
+    Experiment::SINGLE_VALUE, command_line_switch, switch_value, NULL, 0
+#define SINGLE_VALUE_TYPE(command_line_switch) \
+    SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "")
+#define MULTI_VALUE_TYPE(choices) \
+    Experiment::MULTI_VALUE, "", "", choices, arraysize(choices)
 
 namespace {
 
@@ -38,13 +40,12 @@
 const char kAdvancedFileSystemExperimentName[] = "advanced-file-system";
 const char kVerticalTabsExperimentName[] = "vertical-tabs";
 
-// If adding a new choice, add it to the end of the list.
-const Experiment::Choice kInstantChoices[] = {
-  { IDS_FLAGS_INSTANT_TYPE_VERBATIM, switches::kEnableVerbatimInstant },
-  { IDS_FLAGS_INSTANT_TYPE_PREDICTIVE, switches::kEnablePredictiveInstant },
-  { IDS_FLAGS_INSTANT_TYPE_PREDICTIVE_NO_AUTO_COMPLETE,
-    switches::kEnablePredictiveNoAutoCompleteInstant
-  },
+const Experiment::Choice kPagePrerenderChoices[] = {
+  { IDS_FLAGS_PAGE_PRERENDER_AUTOMATIC, "", "" },
+  { IDS_FLAGS_PAGE_PRERENDER_ENABLED,
+    switches::kPrerender, switches::kPrerenderSwitchValueEnabled },
+  { IDS_FLAGS_PAGE_PRERENDER_DISABLED,
+    switches::kPrerender, switches::kPrerenderSwitchValueDisabled },
 };
 
 // RECORDING USER METRICS FOR FLAGS:
@@ -71,26 +72,15 @@
 // distinct types of experiments:
 // . SINGLE_VALUE: experiment is either on or off. Use the SINGLE_VALUE_TYPE
 //   macro for this type supplying the command line to the macro.
-// . MULTI_VALUE: if enabled the command line of the selected choice is enabled.
-//   To specify this type of experiment use the macro MULTI_VALUE_TYPE supplying
-//   it the array of choices.
+// . MULTI_VALUE: a list of choices, the first of which should correspond to a
+//   deactivated state for this lab (i.e. no command line option).  To specify
+//   this type of experiment use the macro MULTI_VALUE_TYPE supplying it the
+//   array of choices.
 // See the documentation of Experiment for details on the fields.
 //
 // When adding a new choice, add it to the end of the list.
 const Experiment kExperiments[] = {
   {
-    "expose-for-tabs",  // FLAGS:RECORD_UMA
-    IDS_FLAGS_TABPOSE_NAME,
-    IDS_FLAGS_TABPOSE_DESCRIPTION,
-    kOsMac,
-#if defined(OS_MACOSX)
-    // The switch exists only on OS X.
-    SINGLE_VALUE_TYPE(switches::kEnableExposeForTabs)
-#else
-    SINGLE_VALUE_TYPE("")
-#endif
-  },
-  {
     kMediaPlayerExperimentName,
     IDS_FLAGS_MEDIA_PLAYER_NAME,
     IDS_FLAGS_MEDIA_PLAYER_DESCRIPTION,
@@ -124,25 +114,9 @@
   {
     "remoting",  // FLAGS:RECORD_UMA
     IDS_FLAGS_REMOTING_NAME,
-#if defined(OS_WIN)
-    // Windows only supports host functionality at the moment.
-    IDS_FLAGS_REMOTING_HOST_DESCRIPTION,
-#elif defined(OS_LINUX)  // Also true for CrOS.
-    // Linux only supports client functionality at the moment.
-    IDS_FLAGS_REMOTING_CLIENT_DESCRIPTION,
-#else
-    // On other platforms, this lab isn't available at all.
-    0,
-#endif
-    kOsWin | kOsLinux | kOsCrOS,
-    SINGLE_VALUE_TYPE(switches::kEnableRemoting)
-  },
-  {
-    "xss-auditor",  // FLAGS:RECORD_UMA
-    IDS_FLAGS_XSS_AUDITOR_NAME,
-    IDS_FLAGS_XSS_AUDITOR_DESCRIPTION,
+    IDS_FLAGS_REMOTING_DESCRIPTION,
     kOsAll,
-    SINGLE_VALUE_TYPE(switches::kEnableXSSAuditor)
+    SINGLE_VALUE_TYPE(switches::kEnableRemoting)
   },
   {
     "conflicting-modules-check",  // FLAGS:RECORD_UMA
@@ -175,10 +149,17 @@
   },
   {
     "gpu-compositing",
-     IDS_FLAGS_ACCELERATED_COMPOSITING_NAME,
-     IDS_FLAGS_ACCELERATED_COMPOSITING_DESCRIPTION,
-     kOsAll,
-     SINGLE_VALUE_TYPE(switches::kEnableAcceleratedLayers)
+    IDS_FLAGS_ACCELERATED_COMPOSITING_NAME,
+    IDS_FLAGS_ACCELERATED_COMPOSITING_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kEnableAcceleratedLayers)
+  },
+  {
+    "composited-layer-borders",
+    IDS_FLAGS_COMPOSITED_LAYER_BORDERS,
+    IDS_FLAGS_COMPOSITED_LAYER_BORDERS_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kShowCompositedLayerBorders)
   },
   {
     "gpu-canvas-2d",  // FLAGS:RECORD_UMA
@@ -222,7 +203,7 @@
     IDS_FLAGS_PAGE_PRERENDER_NAME,
     IDS_FLAGS_PAGE_PRERENDER_DESCRIPTION,
     kOsAll,
-    SINGLE_VALUE_TYPE(switches::kEnablePagePrerender)
+    MULTI_VALUE_TYPE(kPagePrerenderChoices)
   },
   {
     "confirm-to-quit",  // FLAGS:RECORD_UMA
@@ -260,11 +241,25 @@
     SINGLE_VALUE_TYPE(switches::kExperimentalLocationFeatures)
   },
   {
-    "instant-type",  // FLAGS:RECORD_UMA
-    IDS_FLAGS_INSTANT_TYPE_NAME,
-    IDS_FLAGS_INSTANT_TYPE_DESCRIPTION,
-    kOsWin,
-    MULTI_VALUE_TYPE(kInstantChoices)
+    "block-reading-third-party-cookies",
+    IDS_FLAGS_BLOCK_ALL_THIRD_PARTY_COOKIES_NAME,
+    IDS_FLAGS_BLOCK_ALL_THIRD_PARTY_COOKIES_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kBlockReadingThirdPartyCookies)
+  },
+  {
+    "disable-interactive-form-validation",
+    IDS_FLAGS_DISABLE_INTERACTIVE_FORM_VALIDATION_NAME,
+    IDS_FLAGS_DISABLE_INTERACTIVE_FORM_VALIDATION_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kDisableInteractiveFormValidation)
+  },
+  {
+    "webaudio",
+    IDS_FLAGS_WEBAUDIO_NAME,
+    IDS_FLAGS_WEBAUDIO_DESCRIPTION,
+    kOsMac,  // TODO(crogers): add windows and linux when FFT is ready.
+    SINGLE_VALUE_TYPE(switches::kEnableWebAudio)
   },
 };
 
@@ -290,30 +285,11 @@
 
  private:
   bool needs_restart_;
-  std::set<std::string> flags_switches_;
+  std::map<std::string, std::string> flags_switches_;
 
   DISALLOW_COPY_AND_ASSIGN(FlagsState);
 };
 
-#if defined(OS_CHROMEOS)
-// Migrates Chrome OS Labs settings to experiments adding flags to enabled
-// experiment list if the corresponding pref is on.
-void MigrateChromeOSLabsPrefs(PrefService* prefs,
-                              std::set<std::string>* result) {
-  DCHECK(prefs);
-  DCHECK(result);
-  if (prefs->GetBoolean(prefs::kLabsMediaplayerEnabled))
-    result->insert(kMediaPlayerExperimentName);
-  if (prefs->GetBoolean(prefs::kLabsAdvancedFilesystemEnabled))
-    result->insert(kAdvancedFileSystemExperimentName);
-  if (prefs->GetBoolean(prefs::kUseVerticalTabs))
-    result->insert(kVerticalTabsExperimentName);
-  prefs->SetBoolean(prefs::kLabsMediaplayerEnabled, false);
-  prefs->SetBoolean(prefs::kLabsAdvancedFilesystemEnabled, false);
-  prefs->SetBoolean(prefs::kUseVerticalTabs, false);
-}
-#endif
-
 // Extracts the list of enabled lab experiments from preferences and stores them
 // in a set.
 void GetEnabledFlags(const PrefService* prefs, std::set<std::string>* result) {
@@ -369,13 +345,35 @@
   }
 }
 
+// Confirms that an experiment is valid, used in a DCHECK in
+// SanitizeList below.
+bool ValidateExperiment(const Experiment& e) {
+  switch (e.type) {
+    case Experiment::SINGLE_VALUE:
+      DCHECK_EQ(0, e.num_choices);
+      DCHECK(!e.choices);
+      break;
+    case Experiment::MULTI_VALUE:
+      DCHECK_GT(e.num_choices, 0);
+      DCHECK(e.choices);
+      DCHECK(e.choices[0].command_line_switch);
+      DCHECK_EQ('\0', e.choices[0].command_line_switch[0]);
+      break;
+    default:
+      NOTREACHED();
+  }
+  return true;
+}
+
 // Removes all experiments from prefs::kEnabledLabsExperiments that are
 // unknown, to prevent this list to become very long as experiments are added
 // and removed.
 void SanitizeList(PrefService* prefs) {
   std::set<std::string> known_experiments;
-  for (size_t i = 0; i < num_experiments; ++i)
+  for (size_t i = 0; i < num_experiments; ++i) {
+    DCHECK(ValidateExperiment(experiments[i]));
     AddInternalName(experiments[i], &known_experiments);
+  }
 
   std::set<std::string> enabled_experiments;
   GetEnabledFlags(prefs, &enabled_experiments);
@@ -421,10 +419,8 @@
 }
 
 // Returns the Value representing the choice data in the specified experiment.
-// If one of the choices is enabled |is_one_selected| is set to true.
 Value* CreateChoiceData(const Experiment& experiment,
-                        const std::set<std::string>& enabled_experiments,
-                        bool* is_one_selected) {
+                        const std::set<std::string>& enabled_experiments) {
   DCHECK(experiment.type == Experiment::MULTI_VALUE);
   ListValue* result = new ListValue;
   for (int i = 0; i < experiment.num_choices; ++i) {
@@ -434,10 +430,7 @@
     value->SetString("description",
                      l10n_util::GetStringUTF16(choice.description_id));
     value->SetString("internal_name", name);
-    bool is_selected = enabled_experiments.count(name) > 0;
-    if (is_selected)
-      *is_one_selected = true;
-    value->SetBoolean("selected", is_selected);
+    value->SetBoolean("selected", enabled_experiments.count(name) > 0);
     result->Append(value);
   }
   return result;
@@ -469,14 +462,19 @@
                     l10n_util::GetStringUTF16(
                         experiment.visible_description_id));
 
-    bool enabled = enabled_experiments.count(experiment.internal_name) > 0;
-
-    if (experiment.type == Experiment::MULTI_VALUE) {
-      data->Set("choices", CreateChoiceData(experiment, enabled_experiments,
-                                            &enabled));
+    switch (experiment.type) {
+      case Experiment::SINGLE_VALUE:
+        data->SetBoolean(
+            "enabled",
+            enabled_experiments.count(experiment.internal_name) > 0);
+        break;
+      case Experiment::MULTI_VALUE:
+        data->Set("choices", CreateChoiceData(experiment, enabled_experiments));
+        break;
+      default:
+        NOTREACHED();
     }
 
-    data->SetBoolean("enabled", enabled);
     experiments_data->Append(data);
   }
   return experiments_data;
@@ -523,6 +521,7 @@
   // stats can be made meaningful.
   if (flags.size())
     UserMetrics::RecordAction(UserMetricsAction("AboutFlags_StartupTick"));
+  UserMetrics::RecordAction(UserMetricsAction("StartupTick"));
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -537,44 +536,52 @@
 
   std::set<std::string> enabled_experiments;
 
-#if defined(OS_CHROMEOS)
-  // Some experiments were implemented via prefs on Chrome OS and we want to
-  // seamlessly migrate these prefs to about:flags for updated users.
-  MigrateChromeOSLabsPrefs(prefs, &enabled_experiments);
-#endif
-
   GetSanitizedEnabledFlagsForCurrentPlatform(prefs, &enabled_experiments);
 
-  typedef std::map<std::string, std::string> NameToSwitchMap;
-  NameToSwitchMap name_to_switch_map;
+  typedef std::map<std::string, std::pair<std::string, std::string> >
+      NameToSwitchAndValueMap;
+  NameToSwitchAndValueMap name_to_switch_map;
   for (size_t i = 0; i < num_experiments; ++i) {
     const Experiment& e = experiments[i];
     if (e.type == Experiment::SINGLE_VALUE) {
-      name_to_switch_map[e.internal_name] = e.command_line;
+      name_to_switch_map[e.internal_name] =
+          std::pair<std::string, std::string>(e.command_line_switch,
+                                              e.command_line_value);
     } else {
       for (int j = 0; j < e.num_choices; ++j)
-        name_to_switch_map[NameForChoice(e, j)] = e.choices[j].command_line;
+        name_to_switch_map[NameForChoice(e, j)] =
+            std::pair<std::string, std::string>(
+                e.choices[j].command_line_switch,
+                e.choices[j].command_line_value);
     }
   }
 
   command_line->AppendSwitch(switches::kFlagSwitchesBegin);
-  flags_switches_.insert(switches::kFlagSwitchesBegin);
+  flags_switches_.insert(
+      std::pair<std::string, std::string>(switches::kFlagSwitchesBegin,
+                                          std::string()));
   for (std::set<std::string>::iterator it = enabled_experiments.begin();
        it != enabled_experiments.end();
        ++it) {
     const std::string& experiment_name = *it;
-    NameToSwitchMap::const_iterator name_to_switch_it =
+    NameToSwitchAndValueMap::const_iterator name_to_switch_it =
         name_to_switch_map.find(experiment_name);
     if (name_to_switch_it == name_to_switch_map.end()) {
       NOTREACHED();
       continue;
     }
 
-    command_line->AppendSwitch(name_to_switch_it->second);
-    flags_switches_.insert(name_to_switch_it->second);
+    const std::pair<std::string, std::string>&
+        switch_and_value_pair = name_to_switch_it->second;
+
+    command_line->AppendSwitchASCII(switch_and_value_pair.first,
+                                    switch_and_value_pair.second);
+    flags_switches_[switch_and_value_pair.first] = switch_and_value_pair.second;
   }
   command_line->AppendSwitch(switches::kFlagSwitchesEnd);
-  flags_switches_.insert(switches::kFlagSwitchesEnd);
+  flags_switches_.insert(
+      std::pair<std::string, std::string>(switches::kFlagSwitchesEnd,
+                                          std::string()));
 }
 
 bool FlagsState::IsRestartNeededToCommitChanges() {
@@ -591,13 +598,16 @@
     // We're being asked to enable a multi-choice experiment. Disable the
     // currently selected choice.
     DCHECK_NE(at_index, 0u);
-    SetExperimentEnabled(prefs, internal_name.substr(0, at_index), false);
+    const std::string experiment_name = internal_name.substr(0, at_index);
+    SetExperimentEnabled(prefs, experiment_name, false);
 
-    // And enable the new choice.
-    std::set<std::string> enabled_experiments;
-    GetSanitizedEnabledFlags(prefs, &enabled_experiments);
-    enabled_experiments.insert(internal_name);
-    SetEnabledFlags(prefs, enabled_experiments);
+    // And enable the new choice, if it is not the default first choice.
+    if (internal_name != experiment_name + "@0") {
+      std::set<std::string> enabled_experiments;
+      GetSanitizedEnabledFlags(prefs, &enabled_experiments);
+      enabled_experiments.insert(internal_name);
+      SetEnabledFlags(prefs, enabled_experiments);
+    }
     return;
   }
 
@@ -641,10 +651,9 @@
 
 void FlagsState::RemoveFlagsSwitches(
     std::map<std::string, CommandLine::StringType>* switch_list) {
-  for (std::set<std::string>::const_iterator it = flags_switches_.begin();
-       it != flags_switches_.end();
-       ++it) {
-    switch_list->erase(*it);
+  for (std::map<std::string, std::string>::const_iterator
+           it = flags_switches_.begin(); it != flags_switches_.end(); ++it) {
+    switch_list->erase(it->first);
   }
 }
 
diff --git a/chrome/browser/about_flags.h b/chrome/browser/about_flags.h
index daa76df..780e9fb 100644
--- a/chrome/browser/about_flags.h
+++ b/chrome/browser/about_flags.h
@@ -29,9 +29,10 @@
     SINGLE_VALUE,
 
     // The experiment has multiple values only one of which is ever enabled.
-    // For MULTI_VALUE experiments the command_line of the Experiment is not
-    // used. If the experiment is enabled the command line of the selected
-    // Choice is enabled.
+    // The first of the values should correspond to a deactivated state for this
+    // lab (i.e. no command line option). For MULTI_VALUE experiments the
+    // command_line of the Experiment is not used. If the experiment is enabled
+    // the command line of the selected Choice is enabled.
     MULTI_VALUE,
   };
 
@@ -41,8 +42,10 @@
     // ID of the message containing the choice name.
     int description_id;
 
-    // Command line to enabled for this choice.
-    const char* command_line;
+    // Command line switch and value to enabled for this choice.
+    const char* command_line_switch;
+    // Simple switches that have no value should use "" for command_line_value.
+    const char* command_line_value;
   };
 
   // The internal name of the experiment. This is never shown to the user.
@@ -63,11 +66,13 @@
   // Type of experiment.
   Type type;
 
-  // The commandline parameter that's added when this lab is active. This is
-  // different from |internal_name| so that the commandline flag can be
+  // The commandline switch and value that are added when this lab is active.
+  // This is different from |internal_name| so that the commandline flag can be
   // renamed without breaking the prefs file.
   // This is used if type is SINGLE_VALUE.
-  const char* command_line;
+  const char* command_line_switch;
+  // Simple switches that have no value should use "" for command_line_value.
+  const char* command_line_value;
 
   // This is used if type is MULTI_VALUE.
   const Choice* choices;
diff --git a/chrome/browser/about_flags_unittest.cc b/chrome/browser/about_flags_unittest.cc
index c3bbe95..fce30d4 100644
--- a/chrome/browser/about_flags_unittest.cc
+++ b/chrome/browser/about_flags_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/common/chrome_switches.h"
@@ -19,15 +20,18 @@
 const char kSwitch1[] = "switch";
 const char kSwitch2[] = "switch2";
 const char kSwitch3[] = "switch3";
+const char kValueForSwitch2[] = "value_for_switch2";
 
 const char kMultiSwitch1[] = "multi_switch1";
 const char kMultiSwitch2[] = "multi_switch2";
+const char kValueForMultiSwitch2[] = "value_for_multi_switch2";
 
 namespace about_flags {
 
 const Experiment::Choice kMultiChoices[] = {
-  { IDS_PRODUCT_NAME, kMultiSwitch1 },
-  { IDS_PRODUCT_NAME, kMultiSwitch2 },
+  { IDS_PRODUCT_NAME, "", "" },
+  { IDS_PRODUCT_NAME, kMultiSwitch1, "" },
+  { IDS_PRODUCT_NAME, kMultiSwitch2, kValueForMultiSwitch2 },
 };
 
 // The experiments that are set for these tests. The 3rd experiment is not
@@ -40,6 +44,7 @@
     0,  // Ends up being mapped to the current platform.
     Experiment::SINGLE_VALUE,
     kSwitch1,
+    "",
     NULL,
     0
   },
@@ -50,6 +55,7 @@
     0,  // Ends up being mapped to the current platform.
     Experiment::SINGLE_VALUE,
     kSwitch2,
+    kValueForSwitch2,
     NULL,
     0
   },
@@ -60,6 +66,7 @@
     0,  // This ends up enabling for an OS other than the current.
     Experiment::SINGLE_VALUE,
     kSwitch3,
+    "",
     NULL,
     0
   },
@@ -70,6 +77,7 @@
     0,  // Ends up being mapped to the current platform.
     Experiment::MULTI_VALUE,
     "",
+    "",
     kMultiChoices,
     arraysize(kMultiChoices)
   },
@@ -222,31 +230,85 @@
   EXPECT_EQ(arraysize(kExperiments) - 1, switch_prefs->GetSize());
 }
 
-// Tests enabling multi-value type experiments.
+// Tests that switches which should have values get them in the command
+// line.
+TEST_F(AboutFlagsTest, CheckValues) {
+  // Enable experiments 1 and 2.
+  SetExperimentEnabled(&prefs_, kFlags1, true);
+  SetExperimentEnabled(&prefs_, kFlags2, true);
+  CommandLine command_line(CommandLine::NO_PROGRAM);
+  EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
+  EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
+
+  // Convert the flags to switches.
+  ConvertFlagsToSwitches(&prefs_, &command_line);
+  EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
+  EXPECT_EQ(std::string(""),
+            command_line.GetSwitchValueASCII(kSwitch1));
+  EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
+  EXPECT_EQ(std::string(kValueForSwitch2),
+            command_line.GetSwitchValueASCII(kSwitch2));
+
+  // Confirm that there is no '=' in the command line for simple switches.
+  std::string switch1_with_equals = std::string("--") +
+                                    std::string(kSwitch1) +
+                                    std::string("=");
+#if defined(OS_WIN)
+  EXPECT_EQ(std::wstring::npos,
+            command_line.command_line_string().find(
+                ASCIIToWide(switch1_with_equals)));
+#else
+  EXPECT_EQ(std::string::npos,
+            command_line.command_line_string().find(switch1_with_equals));
+#endif
+
+  // And confirm there is a '=' for switches with values.
+  std::string switch2_with_equals = std::string("--") +
+                                    std::string(kSwitch2) +
+                                    std::string("=");
+#if defined(OS_WIN)            
+  EXPECT_NE(std::wstring::npos,
+            command_line.command_line_string().find(
+                ASCIIToWide(switch2_with_equals)));
+#else
+  EXPECT_NE(std::string::npos,
+            command_line.command_line_string().find(switch2_with_equals));
+#endif
+
+  // And it should persist
+  scoped_ptr<ListValue> switch_prefs(GetFlagsExperimentsData(&prefs_));
+  ASSERT_TRUE(switch_prefs.get());
+  EXPECT_EQ(arraysize(kExperiments) - 1, switch_prefs->GetSize());
+}
+
+// Tests multi-value type experiments.
 TEST_F(AboutFlagsTest, MultiValues) {
-  // Enable the multi value experiment, which should enable the first choice.
-  SetExperimentEnabled(&prefs_, kFlags4, true);
+  // Initially, the first "deactivated" option of the multi experiment should
+  // be set.
   {
     CommandLine command_line(CommandLine::NO_PROGRAM);
     ConvertFlagsToSwitches(&prefs_, &command_line);
-    EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch1));
+    EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
     EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
   }
 
-  // Enable the 2nd choice of the multi-value, which should disable the first
-  // choice.
+  // Enable the 2nd choice of the multi-value.
   SetExperimentEnabled(&prefs_, std::string(kFlags4) +
                        std::string(testing::kMultiSeparator) +
-                       base::IntToString(1), true);
+                       base::IntToString(2), true);
   {
     CommandLine command_line(CommandLine::NO_PROGRAM);
     ConvertFlagsToSwitches(&prefs_, &command_line);
     EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
     EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch2));
+    EXPECT_EQ(std::string(kValueForMultiSwitch2),
+              command_line.GetSwitchValueASCII(kMultiSwitch2));
   }
 
   // Disable the multi-value experiment.
-  SetExperimentEnabled(&prefs_, kFlags4, false);
+  SetExperimentEnabled(&prefs_, std::string(kFlags4) +
+                       std::string(testing::kMultiSeparator) +
+                       base::IntToString(0), true);
   {
     CommandLine command_line(CommandLine::NO_PROGRAM);
     ConvertFlagsToSwitches(&prefs_, &command_line);
diff --git a/chrome/browser/accessibility/OWNERS b/chrome/browser/accessibility/OWNERS
new file mode 100644
index 0000000..ab8afa4
--- /dev/null
+++ b/chrome/browser/accessibility/OWNERS
@@ -0,0 +1,3 @@
+ctguil@chromium.org
+dmazzoni@chromium.org
+dtseng@chromium.org
diff --git a/chrome/browser/accessibility/accessibility_mac_uitest.mm b/chrome/browser/accessibility/accessibility_mac_uitest.mm
index 5a79057..f88dd2b 100644
--- a/chrome/browser/accessibility/accessibility_mac_uitest.mm
+++ b/chrome/browser/accessibility/accessibility_mac_uitest.mm
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import <Cocoa/Cocoa.h>
 
 #include "base/scoped_nsobject.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/ui/ui_test.h"
 
@@ -40,7 +41,8 @@
   void WaitAndAssertAllEventsObserved() {
     ASSERT_GE([expectedEvents count], 1U);
     CFRunLoopRunInMode(
-        kCFRunLoopDefaultMode, action_max_timeout_ms()/1000, false);
+        kCFRunLoopDefaultMode,
+        TestTimeouts::action_max_timeout_ms() / 1000, false);
     ASSERT_EQ(0U, [AccessibilityMacUITest::expectedEvents count]);
   }
 
diff --git a/chrome/browser/accessibility/accessibility_win_browsertest.cc b/chrome/browser/accessibility/accessibility_win_browsertest.cc
index 7dd669c..ab12925 100644
--- a/chrome/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chrome/browser/accessibility/accessibility_win_browsertest.cc
@@ -12,11 +12,11 @@
 #include "chrome/browser/renderer_host/render_widget_host_view_win.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
-#include "ia2_api_all.h"  // Generated
+#include "ia2_api_all.h"  // Generated    NOLINT
+#include "ISimpleDOMNode.h"  // Generated   NOLINT
 
 using std::auto_ptr;
 using std::vector;
@@ -136,7 +136,7 @@
 
 // Sets result to true if the child is located in the parent's tree. An
 // exhustive search is perform here because we determine equality using
-// IAccessible2::get_uniqueID which is only supported by the child node.
+// IAccessible2::get_unique_id which is only supported by the child node.
 void AccessibleContainsAccessible(
     IAccessible* parent, IAccessible2* child, bool* result) {
   vector<ScopedComPtr<IAccessible>> accessible_list;
@@ -144,7 +144,7 @@
 
   LONG unique_id;
   HRESULT hr = child->get_uniqueID(&unique_id);
-  ASSERT_EQ(hr, S_OK);
+  ASSERT_EQ(S_OK, hr);
   *result = false;
 
   while (accessible_list.size()) {
@@ -164,7 +164,7 @@
 
     LONG child_count;
     hr = accessible->get_accChildCount(&child_count);
-    ASSERT_EQ(hr, S_OK);
+    ASSERT_EQ(S_OK, hr);
     if (child_count == 0)
       continue;
 
@@ -172,7 +172,7 @@
     LONG obtained_count = 0;
     hr = AccessibleChildren(
         accessible, 0, child_count, child_array.get(), &obtained_count);
-    ASSERT_EQ(hr, S_OK);
+    ASSERT_EQ(S_OK, hr);
     ASSERT_EQ(child_count, obtained_count);
 
     for (int index = 0; index < obtained_count; index++) {
@@ -260,7 +260,7 @@
     EXPECT_EQ(hr, S_FALSE);
   } else {
     // Test that the correct string was returned.
-    EXPECT_EQ(hr, S_OK);
+    EXPECT_EQ(S_OK, hr);
     EXPECT_STREQ(name_.c_str(),
                  wstring(name.m_str, SysStringLen(name)).c_str());
   }
@@ -270,7 +270,7 @@
   VARIANT var_role = {0};
   HRESULT hr =
       accessible->get_accRole(CreateI4Variant(CHILDID_SELF), &var_role);
-  ASSERT_EQ(hr, S_OK);
+  ASSERT_EQ(S_OK, hr);
   EXPECT_TRUE(role_ == var_role);
 }
 
@@ -292,7 +292,7 @@
   VARIANT var_state = {0};
   HRESULT hr =
       accessible->get_accState(CreateI4Variant(CHILDID_SELF), &var_state);
-  EXPECT_EQ(hr, S_OK);
+  EXPECT_EQ(S_OK, hr);
   ASSERT_EQ(VT_I4, V_VT(&var_state));
   EXPECT_EQ(state_, V_I4(&var_state));
 }
@@ -300,14 +300,14 @@
 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) {
   LONG child_count = 0;
   HRESULT hr = parent->get_accChildCount(&child_count);
-  EXPECT_EQ(hr, S_OK);
+  EXPECT_EQ(S_OK, hr);
   ASSERT_EQ(child_count, children_.size());
 
   auto_ptr<VARIANT> child_array(new VARIANT[child_count]);
   LONG obtained_count = 0;
   hr = AccessibleChildren(parent, 0, child_count,
                           child_array.get(), &obtained_count);
-  ASSERT_EQ(hr, S_OK);
+  ASSERT_EQ(S_OK, hr);
   ASSERT_EQ(child_count, obtained_count);
 
   VARIANT* child = child_array.get();
@@ -362,7 +362,7 @@
   ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
   ScopedComPtr<IDispatch> parent_dispatch;
   HRESULT hr = document_accessible->get_accParent(parent_dispatch.Receive());
-  EXPECT_EQ(hr, S_OK);
+  EXPECT_EQ(S_OK, hr);
   EXPECT_NE(parent_dispatch, reinterpret_cast<IDispatch*>(NULL));
 
   // Navigate to another page.
@@ -388,7 +388,7 @@
 
   // Check the browser's copy of the renderer accessibility tree.
   AccessibleChecker list_marker_checker(L"", ROLE_SYSTEM_LISTITEM, L"\x2022");
-  AccessibleChecker static_text_checker(L"", ROLE_SYSTEM_TEXT, L"li");
+  AccessibleChecker static_text_checker(L"li", ROLE_SYSTEM_TEXT, L"");
   AccessibleChecker list_item_checker(L"", ROLE_SYSTEM_LISTITEM, L"");
   list_item_checker.SetExpectedState(
       STATE_SYSTEM_READONLY);
@@ -477,7 +477,7 @@
       NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED);
 
   // Check that the accessibility tree of the browser has been updated.
-  AccessibleChecker text_checker(L"", ROLE_SYSTEM_TEXT, L"new text");
+  AccessibleChecker text_checker(L"new text", ROLE_SYSTEM_TEXT, L"");
   body_checker.AppendExpectedChild(&text_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
 }
@@ -503,7 +503,7 @@
       NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED);
 
   // Check that the accessibility tree of the browser has been updated.
-  AccessibleChecker static_text_checker(L"", ROLE_SYSTEM_TEXT, L"text");
+  AccessibleChecker static_text_checker(L"text", ROLE_SYSTEM_TEXT, L"");
   AccessibleChecker div_checker(L"", L"div", L"");
   document_checker.AppendExpectedChild(&div_checker);
   div_checker.AppendExpectedChild(&static_text_checker);
@@ -543,7 +543,7 @@
   ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
   HRESULT hr = document_accessible->accSelect(
     SELFLAG_TAKEFOCUS, CreateI4Variant(CHILDID_SELF));
-  ASSERT_EQ(hr, S_OK);
+  ASSERT_EQ(S_OK, hr);
   ui_test_utils::WaitForNotification(
       NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED);
 
@@ -638,7 +638,7 @@
   }
 
   // If pointer comparison fails resort to the exhuasive search that can use
-  // IAccessible2::get_uniqueID for equality comparison.
+  // IAccessible2::get_unique_id for equality comparison.
   if (!found) {
     AccessibleContainsAccessible(
         browser_accessible, document_accessible2, &found);
@@ -646,4 +646,67 @@
 
   ASSERT_EQ(found, true);
 }
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+                       SupportsISimpleDOM) {
+  GURL tree_url("data:text/html,<body><input type='checkbox' /></body>");
+  browser()->OpenURL(tree_url, GURL(), CURRENT_TAB, PageTransition::TYPED);
+  GetRendererAccessible();
+  ui_test_utils::WaitForNotification(
+      NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED);
+
+  // Get the IAccessible object for the document.
+  ScopedComPtr<IAccessible> document_accessible(GetRendererAccessible());
+  ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
+
+  // Get the ISimpleDOM object for the document.
+  ScopedComPtr<IServiceProvider> service_provider;
+  HRESULT hr = static_cast<IAccessible*>(document_accessible)->QueryInterface(
+      service_provider.Receive());
+  ASSERT_EQ(S_OK, hr);
+  const GUID refguid = {0x0c539790, 0x12e4, 0x11cf,
+                        0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8};
+  ScopedComPtr<ISimpleDOMNode> document_isimpledomnode;
+  hr = static_cast<IServiceProvider *>(service_provider)->QueryService(
+      refguid, IID_ISimpleDOMNode,
+      reinterpret_cast<void**>(document_isimpledomnode.Receive()));
+  ASSERT_EQ(S_OK, hr);
+
+  BSTR node_name;
+  short name_space_id;  // NOLINT
+  BSTR node_value;
+  unsigned int num_children;
+  unsigned int unique_id;
+  unsigned short node_type;  // NOLINT
+  hr = document_isimpledomnode->get_nodeInfo(
+      &node_name, &name_space_id, &node_value, &num_children, &unique_id,
+      &node_type);
+  ASSERT_EQ(S_OK, hr);
+  EXPECT_EQ(NODETYPE_DOCUMENT, node_type);
+  EXPECT_EQ(1, num_children);
+
+  ScopedComPtr<ISimpleDOMNode> body_isimpledomnode;
+  hr = document_isimpledomnode->get_firstChild(
+      body_isimpledomnode.Receive());
+  ASSERT_EQ(S_OK, hr);
+  hr = body_isimpledomnode->get_nodeInfo(
+      &node_name, &name_space_id, &node_value, &num_children, &unique_id,
+      &node_type);
+  ASSERT_EQ(S_OK, hr);
+  EXPECT_STREQ(L"body", wstring(node_name, SysStringLen(node_name)).c_str());
+  EXPECT_EQ(NODETYPE_ELEMENT, node_type);
+  EXPECT_EQ(1, num_children);
+
+  ScopedComPtr<ISimpleDOMNode> checkbox_isimpledomnode;
+  hr = body_isimpledomnode->get_firstChild(
+      checkbox_isimpledomnode.Receive());
+  ASSERT_EQ(S_OK, hr);
+  hr = checkbox_isimpledomnode->get_nodeInfo(
+      &node_name, &name_space_id, &node_value, &num_children, &unique_id,
+      &node_type);
+  ASSERT_EQ(S_OK, hr);
+  EXPECT_STREQ(L"input", wstring(node_name, SysStringLen(node_name)).c_str());
+  EXPECT_EQ(NODETYPE_ELEMENT, node_type);
+  EXPECT_EQ(0, num_children);
+}
 }  // namespace.
diff --git a/chrome/browser/accessibility/browser_accessibility_cocoa.mm b/chrome/browser/accessibility/browser_accessibility_cocoa.mm
index a86a0bb..3d451cf 100644
--- a/chrome/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chrome/browser/accessibility/browser_accessibility_cocoa.mm
@@ -6,12 +6,12 @@
 
 #import "chrome/browser/accessibility/browser_accessibility_cocoa.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/string16.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
 #include "grit/webkit_strings.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
@@ -133,9 +133,16 @@
 
 // Returns a string indicating the role of this object.
 - (NSString*)role {
-  NSString* role = NSAccessibilityUnknownRole;
   WebAccessibility::Role value =
       static_cast<WebAccessibility::Role>( browserAccessibility_->role());
+
+  // Roles that we only determine at runtime.
+  if (value == WebAccessibility::ROLE_TEXT_FIELD &&
+      GetState(browserAccessibility_, WebAccessibility::STATE_PROTECTED)) {
+    return @"AXSecureTextField";
+  }
+
+  NSString* role = NSAccessibilityUnknownRole;
   const size_t numRoles = sizeof(roles) / sizeof(roles[0]);
   for (size_t i = 0; i < numRoles; ++i) {
     if (roles[i].value == value) {
@@ -143,6 +150,7 @@
       break;
     }
   }
+
   return role;
 }
 
diff --git a/chrome/browser/accessibility/browser_accessibility_manager.cc b/chrome/browser/accessibility/browser_accessibility_manager.cc
index 0bb8524..0f80e4f 100644
--- a/chrome/browser/accessibility/browser_accessibility_manager.cc
+++ b/chrome/browser/accessibility/browser_accessibility_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "chrome/browser/accessibility/browser_accessibility.h"
+#include "chrome/common/render_messages_params.h"
 
 using webkit_glue::WebAccessibility;
 
@@ -307,6 +308,9 @@
     DCHECK_EQ(old_browser_acc, root_);
     root_ = new_browser_acc;
   }
+  if (focus_ && focus_->IsDescendantOf(old_browser_acc))
+    focus_ = root_;
+
   old_browser_acc->ReleaseTree();
   old_browser_acc->ReleaseReference();
   child_id_map_[child_id] = new_browser_acc;
diff --git a/chrome/browser/accessibility/browser_accessibility_manager.h b/chrome/browser/accessibility/browser_accessibility_manager.h
index 0abcd1c..f9ce989 100644
--- a/chrome/browser/accessibility/browser_accessibility_manager.h
+++ b/chrome/browser/accessibility/browser_accessibility_manager.h
@@ -11,8 +11,7 @@
 #include "base/hash_tables.h"
 #include "base/scoped_ptr.h"
 #include "build/build_config.h"
-#include "chrome/common/render_messages_params.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/webaccessibility.h"
 
 class BrowserAccessibility;
@@ -20,6 +19,8 @@
 class BrowserAccessibilityManagerWin;
 #endif
 
+struct ViewHostMsg_AccessibilityNotification_Params;
+
 using webkit_glue::WebAccessibility;
 
 // Class that can perform actions on behalf of the BrowserAccessibilityManager.
@@ -54,8 +55,11 @@
 
   virtual ~BrowserAccessibilityManager();
 
+  // Type is a ViewHostMsg_AccessibilityNotification_Params::NotificationType.
+  // We pass it as int so that we don't include the render message declaration
+  // header here.
   virtual void NotifyAccessibilityEvent(
-      ViewHostMsg_AccessibilityNotification_Params::NotificationType n,
+      int type,
       BrowserAccessibility* node) = 0;
 
   // Returns the next unique child id.
diff --git a/chrome/browser/accessibility/browser_accessibility_manager_mac.h b/chrome/browser/accessibility/browser_accessibility_manager_mac.h
index 892de15..dc35d6f 100644
--- a/chrome/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chrome/browser/accessibility/browser_accessibility_manager_mac.h
@@ -13,9 +13,7 @@
 class BrowserAccessibilityManagerMac : public BrowserAccessibilityManager {
  public:
   // Implementation of BrowserAccessibilityManager.
-  virtual void NotifyAccessibilityEvent(
-      ViewHostMsg_AccessibilityNotification_Params::NotificationType n,
-      BrowserAccessibility* node);
+  virtual void NotifyAccessibilityEvent(int type, BrowserAccessibility* node);
 
  private:
   // This gives BrowserAccessibilityManager::Create access to the class
diff --git a/chrome/browser/accessibility/browser_accessibility_manager_mac.mm b/chrome/browser/accessibility/browser_accessibility_manager_mac.mm
index 6e39cd1..47230aa 100644
--- a/chrome/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chrome/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -5,6 +5,7 @@
 #include "chrome/browser/accessibility/browser_accessibility_manager_mac.h"
 
 #import "chrome/browser/accessibility/browser_accessibility_cocoa.h"
+#include "chrome/common/render_messages_params.h"
 
 // static
 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
@@ -29,11 +30,11 @@
 }
 
 void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
-    ViewHostMsg_AccessibilityNotification_Params::NotificationType n,
+    int type,
     BrowserAccessibility* node) {
   // Refer to AXObjectCache.mm (webkit).
   NSString* event_id = @"";
-  switch (n) {
+  switch (type) {
     case ViewHostMsg_AccessibilityNotification_Params::
         NOTIFICATION_TYPE_CHECK_STATE_CHANGED:
       // Does not exist on Mac.
diff --git a/chrome/browser/accessibility/browser_accessibility_manager_win.cc b/chrome/browser/accessibility/browser_accessibility_manager_win.cc
index 3f2c253..5720dd3 100644
--- a/chrome/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chrome/browser/accessibility/browser_accessibility_manager_win.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/accessibility/browser_accessibility_manager_win.h"
 
 #include "chrome/browser/accessibility/browser_accessibility_win.h"
+#include "chrome/common/render_messages_params.h"
 
 using webkit_glue::WebAccessibility;
 
@@ -52,10 +53,10 @@
 }
 
 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
-    ViewHostMsg_AccessibilityNotification_Params::NotificationType n,
+    int type,
     BrowserAccessibility* node) {
   LONG event_id;
-  switch (n) {
+  switch (type) {
     case ViewHostMsg_AccessibilityNotification_Params::
           NOTIFICATION_TYPE_CHECK_STATE_CHANGED:
       event_id = EVENT_OBJECT_STATECHANGE;
diff --git a/chrome/browser/accessibility/browser_accessibility_manager_win.h b/chrome/browser/accessibility/browser_accessibility_manager_win.h
index 9ee396f..8226e5e 100644
--- a/chrome/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chrome/browser/accessibility/browser_accessibility_manager_win.h
@@ -10,7 +10,6 @@
 
 #include "base/scoped_comptr_win.h"
 #include "chrome/browser/accessibility/browser_accessibility_manager.h"
-#include "chrome/common/render_messages_params.h"
 #include "webkit/glue/webaccessibility.h"
 
 class BrowserAccessibilityWin;
@@ -28,9 +27,7 @@
   IAccessible* GetParentWindowIAccessible();
 
   // BrowserAccessibilityManager methods
-  virtual void NotifyAccessibilityEvent(
-      ViewHostMsg_AccessibilityNotification_Params::NotificationType n,
-      BrowserAccessibility* node);
+  virtual void NotifyAccessibilityEvent(int type, BrowserAccessibility* node);
 
  private:
   BrowserAccessibilityManagerWin(
diff --git a/chrome/browser/accessibility/browser_accessibility_win.cc b/chrome/browser/accessibility/browser_accessibility_win.cc
index 011ed86..fcd01a5 100644
--- a/chrome/browser/accessibility/browser_accessibility_win.cc
+++ b/chrome/browser/accessibility/browser_accessibility_win.cc
@@ -12,6 +12,15 @@
 
 using webkit_glue::WebAccessibility;
 
+// The GUID for the ISimpleDOM service is not defined in the IDL files.
+// This is taken directly from the Mozilla sources
+// (accessible/src/msaa/nsAccessNodeWrap.cpp) and it's also documented at:
+// http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/MSAA
+
+const GUID GUID_ISimpleDOM = {
+    0x0c539790, 0x12e4, 0x11cf,
+    0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8};
+
 // static
 BrowserAccessibility* BrowserAccessibility::Create() {
   CComObject<BrowserAccessibilityWin>* instance;
@@ -1070,7 +1079,8 @@
       guidService == IID_IAccessibleText ||
       guidService == IID_ISimpleDOMDocument ||
       guidService == IID_ISimpleDOMNode ||
-      guidService == IID_ISimpleDOMText) {
+      guidService == IID_ISimpleDOMText ||
+      guidService == GUID_ISimpleDOM) {
     return QueryInterface(riid, object);
   }
 
@@ -1127,12 +1137,15 @@
   if (GetAttribute(WebAccessibility::ATTR_DISPLAY, &display))
     html_attributes_.push_back(std::make_pair(L"display", display));
 
+  // If this is static text, put the text in the name rather than the value.
+  if (role_ == WebAccessibility::ROLE_STATIC_TEXT && name_.empty())
+    name_.swap(value_);
+
   // If this object doesn't have a name but it does have a description,
   // use the description as its name - because some screen readers only
   // announce the name.
-  if (name_.empty() && HasAttribute(WebAccessibility::ATTR_DESCRIPTION)) {
+  if (name_.empty() && HasAttribute(WebAccessibility::ATTR_DESCRIPTION))
     GetAttribute(WebAccessibility::ATTR_DESCRIPTION, &name_);
-  }
 
   instance_active_ = true;
 }
@@ -1310,6 +1323,8 @@
   if ((state_ >> WebAccessibility::STATE_UNAVAILABLE) & 1)
     ia_state_|= STATE_SYSTEM_UNAVAILABLE;
 
+  string16 html_tag;
+  GetAttribute(WebAccessibility::ATTR_HTML_TAG, &html_tag);
   ia_role_ = 0;
   ia2_role_ = 0;
   switch (role_) {
@@ -1324,6 +1339,9 @@
       ia_role_ = ROLE_SYSTEM_GROUPING;
       ia2_role_ = IA2_ROLE_SECTION;
       break;
+    case WebAccessibility::ROLE_BUSY_INDICATOR:
+      ia_role_ = ROLE_SYSTEM_ANIMATION;
+      break;
     case WebAccessibility::ROLE_BUTTON:
       ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
       break;
@@ -1347,7 +1365,7 @@
       ia_role_ = ROLE_SYSTEM_COMBOBOX;
       break;
     case WebAccessibility::ROLE_DEFINITION_LIST_DEFINITION:
-      GetAttribute(WebAccessibility::ATTR_HTML_TAG, &role_name_);
+      role_name_ = html_tag;
       ia2_role_ = IA2_ROLE_PARAGRAPH;
       break;
     case WebAccessibility::ROLE_DEFINITION_LIST_TERM:
@@ -1356,6 +1374,9 @@
     case WebAccessibility::ROLE_DIALOG:
       ia_role_ = ROLE_SYSTEM_DIALOG;
       break;
+    case WebAccessibility::ROLE_DISCLOSURE_TRIANGLE:
+      ia_role_ = ROLE_SYSTEM_OUTLINEBUTTON;
+      break;
     case WebAccessibility::ROLE_DOCUMENT:
     case WebAccessibility::ROLE_WEB_AREA:
       ia_role_ = ROLE_SYSTEM_DOCUMENT;
@@ -1371,20 +1392,28 @@
       ia_role_ = ROLE_SYSTEM_TABLE;
       break;
     case WebAccessibility::ROLE_GROUP:
-      GetAttribute(WebAccessibility::ATTR_HTML_TAG, &role_name_);
-      if (role_name_.empty())
-        role_name_ = L"div";
-      ia2_role_ = IA2_ROLE_SECTION;
+      if (html_tag == L"li") {
+        ia_role_ = ROLE_SYSTEM_LISTITEM;
+      } else {
+        if (html_tag.empty())
+          role_name_ = L"div";
+        else
+          role_name_ = html_tag;
+        ia2_role_ = IA2_ROLE_SECTION;
+      }
+      break;
+    case WebAccessibility::ROLE_GROW_AREA:
+      ia_role_ = ROLE_SYSTEM_GRIP;
       break;
     case WebAccessibility::ROLE_HEADING:
-      GetAttribute(WebAccessibility::ATTR_HTML_TAG, &role_name_);
+      role_name_ = html_tag;
       ia2_role_ = IA2_ROLE_HEADING;
       break;
     case WebAccessibility::ROLE_IMAGE:
       ia_role_ = ROLE_SYSTEM_GRAPHIC;
       break;
     case WebAccessibility::ROLE_IMAGE_MAP:
-      GetAttribute(WebAccessibility::ATTR_HTML_TAG, &role_name_);
+      role_name_ = html_tag;
       ia2_role_ = IA2_ROLE_IMAGE_MAP;
       break;
     case WebAccessibility::ROLE_IMAGE_MAP_LINK:
@@ -1417,6 +1446,9 @@
     case WebAccessibility::ROLE_LIST_MARKER:
       ia_role_ = ROLE_SYSTEM_LISTITEM;
       break;
+    case WebAccessibility::ROLE_MATH:
+      ia_role_ = ROLE_SYSTEM_EQUATION;
+      break;
     case WebAccessibility::ROLE_MENU:
     case WebAccessibility::ROLE_MENU_BUTTON:
       ia_role_ = ROLE_SYSTEM_MENUPOPUP;
@@ -1486,6 +1518,9 @@
     case WebAccessibility::ROLE_STATUS:
       ia_role_ = ROLE_SYSTEM_STATUSBAR;
       break;
+    case WebAccessibility::ROLE_SPLITTER:
+      ia_role_ = ROLE_SYSTEM_SEPARATOR;
+      break;
     case WebAccessibility::ROLE_TAB:
       ia_role_ = ROLE_SYSTEM_PAGETAB;
       break;
@@ -1511,6 +1546,9 @@
       ia2_state_ |= IA2_STATE_SINGLE_LINE;
       ia2_state_ |= IA2_STATE_EDITABLE;
       break;
+    case WebAccessibility::ROLE_TIMER:
+      ia_role_ = ROLE_SYSTEM_CLOCK;
+      break;
     case WebAccessibility::ROLE_TOOLBAR:
       ia_role_ = ROLE_SYSTEM_TOOLBAR;
       break;
@@ -1532,24 +1570,18 @@
 
     // TODO(dmazzoni): figure out the proper MSAA role for all of these.
     case WebAccessibility::ROLE_BROWSER:
-    case WebAccessibility::ROLE_BUSY_INDICATOR:
     case WebAccessibility::ROLE_DIRECTORY:
-    case WebAccessibility::ROLE_DISCLOSURE_TRIANGLE:
     case WebAccessibility::ROLE_DRAWER:
-    case WebAccessibility::ROLE_GROW_AREA:
     case WebAccessibility::ROLE_HELP_TAG:
     case WebAccessibility::ROLE_IGNORED:
     case WebAccessibility::ROLE_INCREMENTOR:
     case WebAccessibility::ROLE_LOG:
     case WebAccessibility::ROLE_MARQUEE:
-    case WebAccessibility::ROLE_MATH:
     case WebAccessibility::ROLE_MATTE:
     case WebAccessibility::ROLE_RULER_MARKER:
     case WebAccessibility::ROLE_SHEET:
     case WebAccessibility::ROLE_SLIDER_THUMB:
-    case WebAccessibility::ROLE_SPLITTER:
     case WebAccessibility::ROLE_SYSTEM_WIDE:
-    case WebAccessibility::ROLE_TIMER:
     case WebAccessibility::ROLE_VALUE_INDICATOR:
     default:
       ia_role_ = ROLE_SYSTEM_CLIENT;
diff --git a/chrome/browser/accessibility/browser_accessibility_win_unittest.cc b/chrome/browser/accessibility/browser_accessibility_win_unittest.cc
index dd264a1..fe5fa04 100644
--- a/chrome/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chrome/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -146,7 +146,7 @@
   WebAccessibility text;
   text.id = 2;
   text.role = WebAccessibility::ROLE_STATIC_TEXT;
-  text.value = L"old text";
+  text.name = L"old text";
   text.state = 0;
 
   WebAccessibility root;
@@ -177,16 +177,16 @@
   hr = text_dispatch.QueryInterface(text_accessible.Receive());
   ASSERT_EQ(S_OK, hr);
 
-  CComBSTR value;
-  hr = text_accessible->get_accValue(CreateI4Variant(CHILDID_SELF), &value);
+  CComBSTR name;
+  hr = text_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name);
   ASSERT_EQ(S_OK, hr);
-  EXPECT_STREQ(L"old text", value.m_str);
+  EXPECT_STREQ(L"old text", name.m_str);
 
   text_dispatch.Release();
   text_accessible.Release();
 
   // Notify the BrowserAccessibilityManager that the text child has changed.
-  text.value = L"new text";
+  text.name = L"new text";
   ViewHostMsg_AccessibilityNotification_Params param;
   param.notification_type =
       ViewHostMsg_AccessibilityNotification_Params::
@@ -206,9 +206,9 @@
   hr = text_dispatch.QueryInterface(text_accessible.Receive());
   ASSERT_EQ(S_OK, hr);
 
-  hr = text_accessible->get_accValue(CreateI4Variant(CHILDID_SELF), &value);
+  hr = text_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name);
   ASSERT_EQ(S_OK, hr);
-  EXPECT_STREQ(L"new text", value.m_str);
+  EXPECT_STREQ(L"new text", name.m_str);
 
   text_dispatch.Release();
   text_accessible.Release();
@@ -311,14 +311,14 @@
   SysFreeString(text);
 
   ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, &text));
-  ASSERT_EQ(text, std::wstring(L"One "));
+  ASSERT_EQ(text, string16(L"One "));
   SysFreeString(text);
 
   ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
       1, IA2_TEXT_BOUNDARY_CHAR, &start, &end, &text));
   ASSERT_EQ(start, 1);
   ASSERT_EQ(end, 2);
-  ASSERT_EQ(text, std::wstring(L"n"));
+  ASSERT_EQ(text, string16(L"n"));
   SysFreeString(text);
 
   ASSERT_EQ(S_FALSE, text1_obj->get_textAtOffset(
@@ -330,28 +330,28 @@
       1, IA2_TEXT_BOUNDARY_WORD, &start, &end, &text));
   ASSERT_EQ(start, 0);
   ASSERT_EQ(end, 3);
-  ASSERT_EQ(text, std::wstring(L"One"));
+  ASSERT_EQ(text, string16(L"One"));
   SysFreeString(text);
 
   ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
       6, IA2_TEXT_BOUNDARY_WORD, &start, &end, &text));
   ASSERT_EQ(start, 4);
   ASSERT_EQ(end, 7);
-  ASSERT_EQ(text, std::wstring(L"two"));
+  ASSERT_EQ(text, string16(L"two"));
   SysFreeString(text);
 
   ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
       text1_len, IA2_TEXT_BOUNDARY_WORD, &start, &end, &text));
   ASSERT_EQ(start, 25);
   ASSERT_EQ(end, 29);
-  ASSERT_EQ(text, std::wstring(L"six."));
+  ASSERT_EQ(text, string16(L"six."));
   SysFreeString(text);
 
   ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
       1, IA2_TEXT_BOUNDARY_LINE, &start, &end, &text));
   ASSERT_EQ(start, 0);
   ASSERT_EQ(end, 13);
-  ASSERT_EQ(text, std::wstring(L"One two three"));
+  ASSERT_EQ(text, string16(L"One two three"));
   SysFreeString(text);
 
   // Delete the manager and test that all BrowserAccessibility instances are
diff --git a/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc b/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc
index 9fbd160..85f59a3 100644
--- a/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc
+++ b/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc
@@ -4,7 +4,6 @@
 
 #include <oleacc.h>
 
-#include "app/l10n_util.h"
 #include "base/scoped_comptr_win.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
@@ -18,6 +17,7 @@
 #include "chrome/test/ui_test_utils.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/accessibility/view_accessibility.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_win.h"
diff --git a/chrome/browser/aeropeek_manager.cc b/chrome/browser/aeropeek_manager.cc
index 92ce3b8..b42a359 100644
--- a/chrome/browser/aeropeek_manager.cc
+++ b/chrome/browser/aeropeek_manager.cc
@@ -7,8 +7,6 @@
 #include <dwmapi.h>
 #include <shobjidl.h>
 
-#include "app/win/hwnd_util.h"
-#include "app/win/window_impl.h"
 #include "app/win/shell.h"
 #include "base/command_line.h"
 #include "base/scoped_comptr_win.h"
@@ -32,11 +30,13 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/installer/util/browser_distribution.h"
-#include "gfx/gdi_util.h"
-#include "gfx/icon_util.h"
 #include "skia/ext/image_operations.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/win/window_impl.h"
+#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/icon_util.h"
+#include "views/widget/widget_win.h"
 
 namespace {
 
@@ -548,7 +548,7 @@
 // * Translating received messages for TabStrip.
 // This class is used by the AeroPeekManager class, which is a proxy
 // between TabStrip and Windows 7.
-class AeroPeekWindow : public app::win::WindowImpl {
+class AeroPeekWindow : public ui::WindowImpl {
  public:
   AeroPeekWindow(HWND frame_window,
                  AeroPeekWindowDelegate* delegate,
@@ -1016,7 +1016,7 @@
   // flooding users with tab thumbnails.
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
   return base::win::GetVersion() >= base::win::VERSION_WIN7 &&
-      app::win::ShouldUseVistaFrame() &&
+      views::WidgetWin::IsAeroGlassEnabled() &&
       !command_line->HasSwitch(switches::kApp) &&
       command_line->HasSwitch(switches::kEnableAeroPeekTabs);
 }
diff --git a/chrome/browser/aeropeek_manager.h b/chrome/browser/aeropeek_manager.h
index 1e26af6..58eaf07 100644
--- a/chrome/browser/aeropeek_manager.h
+++ b/chrome/browser/aeropeek_manager.h
@@ -11,7 +11,7 @@
 #include <list>
 
 #include "chrome/browser/tabs/tab_strip_model_observer.h"
-#include "gfx/insets.h"
+#include "ui/gfx/insets.h"
 
 namespace gfx {
 class Size;
diff --git a/chrome/browser/alternate_nav_url_fetcher.cc b/chrome/browser/alternate_nav_url_fetcher.cc
index 199afbc..b143c6a 100644
--- a/chrome/browser/alternate_nav_url_fetcher.cc
+++ b/chrome/browser/alternate_nav_url_fetcher.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/alternate_nav_url_fetcher.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/intranet_redirect_detector.h"
 #include "chrome/browser/profiles/profile.h"
@@ -17,6 +15,8 @@
 #include "grit/theme_resources.h"
 #include "net/base/registry_controlled_domain.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 AlternateNavURLFetcher::AlternateNavURLFetcher(
     const GURL& alternate_nav_url)
@@ -86,17 +86,27 @@
   }
 }
 
-void AlternateNavURLFetcher::OnURLFetchComplete(const URLFetcher* source,
-                                                const GURL& url,
-                                                const URLRequestStatus& status,
-                                                int response_code,
-                                                const ResponseCookies& cookies,
-                                                const std::string& data) {
+void AlternateNavURLFetcher::OnURLFetchComplete(
+    const URLFetcher* source,
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
+    const std::string& data) {
   DCHECK(fetcher_.get() == source);
   SetStatusFromURLFetch(url, status, response_code);
   ShowInfobarIfPossible();
 }
 
+SkBitmap* AlternateNavURLFetcher::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_ALT_NAV_URL);
+}
+
+InfoBarDelegate::Type AlternateNavURLFetcher::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
 string16 AlternateNavURLFetcher::GetMessageTextWithOffset(
     size_t* link_offset) const {
   const string16 label = l10n_util::GetStringFUTF16(
@@ -109,11 +119,6 @@
   return UTF8ToUTF16(alternate_nav_url_.spec());
 }
 
-SkBitmap* AlternateNavURLFetcher::GetIcon() const {
-  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-      IDR_INFOBAR_ALT_NAV_URL);
-}
-
 bool AlternateNavURLFetcher::LinkClicked(WindowOpenDisposition disposition) {
   infobar_contents_->OpenURL(
       alternate_nav_url_, GURL(), disposition,
@@ -133,7 +138,7 @@
 
 void AlternateNavURLFetcher::SetStatusFromURLFetch(
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code) {
   if (!status.is_success() ||
       // HTTP 2xx, 401, and 407 all indicate that the target address exists.
@@ -165,6 +170,5 @@
 
   infobar_contents_ = controller_->tab_contents();
   StoreActiveEntryUniqueID(infobar_contents_);
-  // We will be deleted when the InfoBar is destroyed. (See InfoBarClosed).
   infobar_contents_->AddInfoBar(this);
 }
diff --git a/chrome/browser/alternate_nav_url_fetcher.h b/chrome/browser/alternate_nav_url_fetcher.h
index 7f573dd..0dbcfb8 100644
--- a/chrome/browser/alternate_nav_url_fetcher.h
+++ b/chrome/browser/alternate_nav_url_fetcher.h
@@ -43,6 +43,7 @@
 
   State state() const { return state_; }
 
+ private:
   // NotificationObserver
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -57,13 +58,13 @@
                                   const std::string& data);
 
   // LinkInfoBarDelegate
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
   virtual string16 GetMessageTextWithOffset(size_t* link_offset) const;
   virtual string16 GetLinkText() const;
-  virtual SkBitmap* GetIcon() const;
   virtual bool LinkClicked(WindowOpenDisposition disposition);
   virtual void InfoBarClosed();
 
- private:
   // Sets |state_| to either SUCCEEDED or FAILED depending on the result of the
   // fetch.
   void SetStatusFromURLFetch(const GURL& url,
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 79579fe..cf49d4a 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/app_controller_mac.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/file_path.h"
@@ -21,7 +19,6 @@
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/printing/print_job_manager.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sessions/tab_restore_service.h"
@@ -42,21 +39,22 @@
 #import "chrome/browser/ui/cocoa/confirm_quit_panel_controller.h"
 #import "chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.h"
 #import "chrome/browser/ui/cocoa/history_menu_bridge.h"
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
-#import "chrome/browser/ui/cocoa/preferences_window_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_window_controller.h"
+#import "chrome/browser/ui/cocoa/importer/import_settings_dialog.h"
+#import "chrome/browser/ui/cocoa/options/preferences_window_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
 #include "chrome/browser/ui/cocoa/task_manager_mac.h"
 #include "chrome/browser/ui/options/options_window.h"
 #include "chrome/common/app_mode_common_mac.h"
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 // 10.6 adds a public API for the Spotlight-backed search menu item in the Help
 // menu.  Provide the declaration so it can be called below when building with
@@ -611,11 +609,6 @@
     [self openUrls:startupUrls_];
     [self clearStartupUrls];
   }
-
-  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
-  if (!parsed_command_line.HasSwitch(switches::kEnableExposeForTabs)) {
-    [tabposeMenuItem_ setHidden:YES];
-  }
 }
 
 // This is called after profiles have been loaded and preferences registered.
@@ -850,15 +843,33 @@
       break;
     case IDC_CLEAR_BROWSING_DATA: {
       // There may not be a browser open, so use the default profile.
-      [ClearBrowsingDataController
-          showClearBrowsingDialogForProfile:defaultProfile];
+      if (CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kDisableTabbedOptions)) {
+        [ClearBrowsingDataController
+            showClearBrowsingDialogForProfile:defaultProfile];
+      } else {
+        if (Browser* browser = ActivateBrowser(defaultProfile)) {
+          browser->OpenClearBrowsingDataDialog();
+        } else {
+          Browser::OpenClearBrowingDataDialogWindow(defaultProfile);
+        }
+      }
       break;
     }
     case IDC_IMPORT_SETTINGS: {
-      UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"),
-                                defaultProfile);
-      [ImportSettingsDialogController
-          showImportSettingsDialogForProfile:defaultProfile];
+      if (CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kDisableTabbedOptions)) {
+        UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"),
+                                  defaultProfile);
+        [ImportSettingsDialogController
+            showImportSettingsDialogForProfile:defaultProfile];
+      } else {
+        if (Browser* browser = ActivateBrowser(defaultProfile)) {
+          browser->OpenImportSettingsDialog();
+        } else {
+          Browser::OpenImportSettingsDialogWindow(defaultProfile);
+        }
+      }
       break;
     }
     case IDC_SHOW_BOOKMARK_MANAGER:
@@ -920,12 +931,13 @@
       // TODO(akalin): Add a constant to denote starting sync from the
       // main menu and use that instead of START_FROM_WRENCH.
       sync_ui_util::OpenSyncMyBookmarksDialog(
-          defaultProfile, ProfileSyncService::START_FROM_WRENCH);
+          defaultProfile, ActivateBrowser(defaultProfile),
+          ProfileSyncService::START_FROM_WRENCH);
       break;
     case IDC_TASK_MANAGER:
       UserMetrics::RecordAction(UserMetricsAction("TaskManager"),
                                 defaultProfile);
-      TaskManagerMac::Show();
+      TaskManagerMac::Show(false);
       break;
     case IDC_OPTIONS:
       [self showPreferences:sender];
@@ -1196,48 +1208,59 @@
   NSMenu* dockMenu = [[[NSMenu alloc] initWithTitle: @""] autorelease];
   Profile* profile = [self defaultProfile];
 
-  // TODO(rickcam): Mock out BackgroundApplicationListModel, then add unit
-  // tests which use the mock in place of the profile-initialized model.
-
-  // Avoid breaking unit tests which have no profile.
-  if (profile) {
-    int position = 0;
-    BackgroundApplicationListModel applications(profile);
-    for (ExtensionList::const_iterator cursor = applications.begin();
-         cursor != applications.end();
-         ++cursor, ++position) {
-      DCHECK(position == applications.GetPosition(*cursor));
-      scoped_nsobject<NSMenuItem> appItem([[NSMenuItem alloc]
-          initWithTitle:base::SysUTF16ToNSString(UTF8ToUTF16((*cursor)->name()))
-          action:@selector(commandFromDock:)
-          keyEquivalent:@""]);
-      [appItem setTarget:self];
-      [appItem setTag:position];
-      [dockMenu addItem:appItem];
-    }
-    if (applications.begin() != applications.end()) {
-      NSMenuItem* sepItem = [[NSMenuItem separatorItem] init];
-      [dockMenu addItem:sepItem];
-    }
-  }
-
   NSString* titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_WINDOW_MAC);
-  scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc]
-                                    initWithTitle:titleStr
-                                    action:@selector(commandFromDock:)
-                                    keyEquivalent:@""]);
+  scoped_nsobject<NSMenuItem> item(
+      [[NSMenuItem alloc] initWithTitle:titleStr
+                                 action:@selector(commandFromDock:)
+                          keyEquivalent:@""]);
   [item setTarget:self];
   [item setTag:IDC_NEW_WINDOW];
   [dockMenu addItem:item];
 
   titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_INCOGNITO_WINDOW_MAC);
   item.reset([[NSMenuItem alloc] initWithTitle:titleStr
-                                 action:@selector(commandFromDock:)
+                                        action:@selector(commandFromDock:)
                                  keyEquivalent:@""]);
   [item setTarget:self];
   [item setTag:IDC_NEW_INCOGNITO_WINDOW];
   [dockMenu addItem:item];
 
+  // TODO(rickcam): Mock out BackgroundApplicationListModel, then add unit
+  // tests which use the mock in place of the profile-initialized model.
+
+  // Avoid breaking unit tests which have no profile.
+  if (profile) {
+    BackgroundApplicationListModel applications(profile);
+    if (applications.size()) {
+      int position = 0;
+      NSString* menuStr =
+          l10n_util::GetNSStringWithFixup(IDS_BACKGROUND_APPS_MAC);
+      scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:menuStr]);
+      for (ExtensionList::const_iterator cursor = applications.begin();
+           cursor != applications.end();
+           ++cursor, ++position) {
+        DCHECK(position == applications.GetPosition(*cursor));
+        NSString* itemStr =
+            base::SysUTF16ToNSString(UTF8ToUTF16((*cursor)->name()));
+        scoped_nsobject<NSMenuItem> appItem([[NSMenuItem alloc]
+            initWithTitle:itemStr
+                   action:@selector(commandFromDock:)
+            keyEquivalent:@""]);
+        [appItem setTarget:self];
+        [appItem setTag:position];
+        [appMenu addItem:appItem];
+      }
+      scoped_nsobject<NSMenuItem> appMenuItem([[NSMenuItem alloc]
+          initWithTitle:menuStr
+                 action:@selector(commandFromDock:)
+          keyEquivalent:@""]);
+      [appMenuItem setTarget:self];
+      [appMenuItem setTag:position];
+      [appMenuItem setSubmenu:appMenu];
+      [dockMenu addItem:appMenuItem];
+    }
+  }
+
   return dockMenu;
 }
 
diff --git a/chrome/browser/app_launched_animation.h b/chrome/browser/app_launched_animation.h
deleted file mode 100644
index 91c029f..0000000
--- a/chrome/browser/app_launched_animation.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_APP_LAUNCHED_ANIMATION_H_
-#define CHROME_BROWSER_APP_LAUNCHED_ANIMATION_H_
-#pragma once
-
-#include "base/basictypes.h"
-
-class Extension;
-
-namespace gfx {
-  class Rect;
-}
-
-class AppLaunchedAnimation {
- public:
-  // Starts an animation of the |extension| being launched. The |rect| is the
-  // rect of the app icon.
-  static void Show(const Extension* extension, const gfx::Rect& rect);
-
- private:
-  AppLaunchedAnimation() { }
-
-  DISALLOW_COPY_AND_ASSIGN(AppLaunchedAnimation);
-};
-
-#endif  // CHROME_BROWSER_APP_LAUNCHED_ANIMATION_H_
diff --git a/chrome/browser/appcache/appcache_dispatcher_host.cc b/chrome/browser/appcache/appcache_dispatcher_host.cc
index 8bcf53e..15798ea 100644
--- a/chrome/browser/appcache/appcache_dispatcher_host.cc
+++ b/chrome/browser/appcache/appcache_dispatcher_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,7 +12,7 @@
 #include "chrome/common/render_messages.h"
 
 AppCacheDispatcherHost::AppCacheDispatcherHost(
-    URLRequestContext* request_context,
+    net::URLRequestContext* request_context,
     int process_id)
     : ALLOW_THIS_IN_INITIALIZER_LIST(frontend_proxy_(this)),
       request_context_(request_context),
@@ -37,7 +37,7 @@
   DCHECK(request_context_.get() || request_context_getter_.get());
 
   // Get the AppCacheService (it can only be accessed from IO thread).
-  URLRequestContext* context = request_context_.get();
+  net::URLRequestContext* context = request_context_.get();
   if (!context)
     context = request_context_getter_->GetURLRequestContext();
   appcache_service_ =
diff --git a/chrome/browser/appcache/appcache_dispatcher_host.h b/chrome/browser/appcache/appcache_dispatcher_host.h
index 1feca77..527a306 100644
--- a/chrome/browser/appcache/appcache_dispatcher_host.h
+++ b/chrome/browser/appcache/appcache_dispatcher_host.h
@@ -79,7 +79,7 @@
   appcache::AppCacheBackendImpl backend_impl_;
 
   // Temporary until OnChannelConnected() can be called from the IO thread,
-  // which will extract the AppCacheService from the URLRequestContext.
+  // which will extract the AppCacheService from the net::URLRequestContext.
   scoped_refptr<net::URLRequestContext> request_context_;
   scoped_refptr<URLRequestContextGetter> request_context_getter_;
 
diff --git a/chrome/browser/appcache/appcache_ui_test.cc b/chrome/browser/appcache/appcache_ui_test.cc
index 521cfd6..58ca32b 100644
--- a/chrome/browser/appcache/appcache_ui_test.cc
+++ b/chrome/browser/appcache/appcache_ui_test.cc
@@ -80,16 +80,18 @@
       "non-html.xhtml",
       "offline-access.html",
       "online-whitelist.html",
+      "remove-cache.html",
       "resource-redirect.html",
       "resource-redirect-2.html",
       "update-cache.html",
   };
 
-  // These tests are racey due to status polling on timers.
-  // https://bugs.webkit.org/show_bug.cgi?id=49104
+  // This tests loads a data url which calls notifyDone, this just
+  // doesn't work with the layoutTestController in this test harness.
   // "fail-on-update.html",
+
+  // Flaky for reasons i don't yet see?
   // "fail-on-update2.html",
-  // "remove-cache.html",
 
   // TODO(michaeln): investigate these more closely
   // "crash-when-navigating-away-then-back.html",
diff --git a/chrome/browser/appcache/chrome_appcache_service.cc b/chrome/browser/appcache/chrome_appcache_service.cc
index c01b1d7..57b4e31 100644
--- a/chrome/browser/appcache/chrome_appcache_service.cc
+++ b/chrome/browser/appcache/chrome_appcache_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,14 +15,30 @@
 
 static bool has_initialized_thread_ids;
 
+namespace {
+
+// Used to defer deleting of local storage until the destructor has finished.
+void DeleteLocalStateOnIOThread(FilePath cache_path) {
+  // Post the actual deletion to the DB thread to ensure it happens after the
+  // database file has been closed.
+  BrowserThread::PostTask(
+      BrowserThread::DB, FROM_HERE,
+      NewRunnableFunction<bool(*)(const FilePath&, bool), FilePath, bool>(
+          &file_util::Delete, cache_path, true));
+}
+
+}  // namespace
+
 // ----------------------------------------------------------------------------
 
-ChromeAppCacheService::ChromeAppCacheService() {
+ChromeAppCacheService::ChromeAppCacheService()
+    : clear_local_state_on_exit_(false) {
 }
 
 void ChromeAppCacheService::InitializeOnIOThread(
     const FilePath& profile_path, bool is_incognito,
-    scoped_refptr<HostContentSettingsMap> content_settings_map) {
+    scoped_refptr<HostContentSettingsMap> content_settings_map,
+    bool clear_local_state_on_exit) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   if (!has_initialized_thread_ids) {
@@ -33,16 +49,24 @@
   host_contents_settings_map_ = content_settings_map;
   registrar_.Add(
       this, NotificationType::PURGE_MEMORY, NotificationService::AllSources());
+  SetClearLocalStateOnExit(clear_local_state_on_exit);
+  if (!is_incognito)
+    cache_path_ = profile_path.Append(chrome::kAppCacheDirname);
 
   // Init our base class.
-  Initialize(
-      is_incognito ? FilePath() : profile_path.Append(chrome::kAppCacheDirname),
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
+  Initialize(cache_path_,
+             BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
   set_appcache_policy(this);
 }
 
 ChromeAppCacheService::~ChromeAppCacheService() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  if (clear_local_state_on_exit_ && !cache_path_.empty()) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        NewRunnableFunction(DeleteLocalStateOnIOThread, cache_path_));
+  }
 }
 
 void ChromeAppCacheService::SetOriginQuotaInMemory(
@@ -58,9 +82,16 @@
     storage()->ResetOriginQuotaInMemory(origin);
 }
 
-// static
-void ChromeAppCacheService::ClearLocalState(const FilePath& profile_path) {
-  file_util::Delete(profile_path.Append(chrome::kAppCacheDirname), true);
+void ChromeAppCacheService::SetClearLocalStateOnExit(bool clear_local_state) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        NewRunnableMethod(this,
+                          &ChromeAppCacheService::SetClearLocalStateOnExit,
+                          clear_local_state));
+    return;
+  }
+  clear_local_state_on_exit_ = clear_local_state;
 }
 
 bool ChromeAppCacheService::CanLoadAppCache(const GURL& manifest_url) {
diff --git a/chrome/browser/appcache/chrome_appcache_service.h b/chrome/browser/appcache/chrome_appcache_service.h
index dbc0616..0b43759 100644
--- a/chrome/browser/appcache/chrome_appcache_service.h
+++ b/chrome/browser/appcache/chrome_appcache_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -35,14 +35,15 @@
 
   void InitializeOnIOThread(
       const FilePath& profile_path, bool is_incognito,
-      scoped_refptr<HostContentSettingsMap> content_settings_map);
+      scoped_refptr<HostContentSettingsMap> content_settings_map,
+      bool clear_local_state_on_exit);
 
   // Helpers used by the extension service to grant and revoke
   // unlimited storage to app extensions.
   void SetOriginQuotaInMemory(const GURL& origin, int64 quota);
   void ResetOriginQuotaInMemory(const GURL& origin);
 
-  static void ClearLocalState(const FilePath& profile_path);
+  void SetClearLocalStateOnExit(bool clear_local_state);
 
  private:
   friend class BrowserThread;
@@ -62,6 +63,10 @@
 
   scoped_refptr<HostContentSettingsMap> host_contents_settings_map_;
   NotificationRegistrar registrar_;
+  bool clear_local_state_on_exit_;
+  FilePath cache_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeAppCacheService);
 };
 
 #endif  // CHROME_BROWSER_APPCACHE_CHROME_APPCACHE_SERVICE_H_
diff --git a/chrome/browser/appcache/chrome_appcache_service_unittest.cc b/chrome/browser/appcache/chrome_appcache_service_unittest.cc
new file mode 100644
index 0000000..0cb5090
--- /dev/null
+++ b/chrome/browser/appcache/chrome_appcache_service_unittest.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/scoped_temp_dir.h"
+#include "chrome/browser/appcache/chrome_appcache_service.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/test/thread_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/appcache/appcache_storage_impl.h"
+
+namespace appcache {
+
+class ChromeAppCacheServiceTest : public testing::Test {
+ public:
+  ChromeAppCacheServiceTest()
+      : message_loop_(MessageLoop::TYPE_IO),
+        db_thread_(BrowserThread::DB, &message_loop_),
+        file_thread_(BrowserThread::FILE, &message_loop_),
+        cache_thread_(BrowserThread::CACHE, &message_loop_),
+        io_thread_(BrowserThread::IO, &message_loop_) {
+  }
+
+ protected:
+  MessageLoop message_loop_;
+  ScopedTempDir temp_dir_;
+
+ private:
+  BrowserThread db_thread_;
+  BrowserThread file_thread_;
+  BrowserThread cache_thread_;
+  BrowserThread io_thread_;
+};
+
+TEST_F(ChromeAppCacheServiceTest, KeepOnDestruction) {
+  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+  FilePath appcache_path = temp_dir_.path().Append(chrome::kAppCacheDirname);
+  scoped_refptr<ChromeAppCacheService> appcache_service =
+      new ChromeAppCacheService;
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      NewRunnableMethod(appcache_service.get(),
+                        &ChromeAppCacheService::InitializeOnIOThread,
+                        temp_dir_.path(), false,
+                        scoped_refptr<HostContentSettingsMap>(NULL),
+                        false));
+  // Make the steps needed to initialize the storage of AppCache data.
+  message_loop_.RunAllPending();
+  appcache::AppCacheStorageImpl* storage =
+      static_cast<appcache::AppCacheStorageImpl*>(appcache_service->storage());
+  ASSERT_TRUE(storage->database_->db_connection());
+  ASSERT_EQ(1, storage->NewCacheId());
+  storage->disk_cache();
+  message_loop_.RunAllPending();
+
+  ASSERT_TRUE(file_util::PathExists(appcache_path));
+  ASSERT_TRUE(file_util::PathExists(appcache_path.AppendASCII("Index")));
+
+  appcache_service = NULL;
+  message_loop_.RunAllPending();
+
+  ASSERT_TRUE(file_util::PathExists(appcache_path));
+}
+
+TEST_F(ChromeAppCacheServiceTest, RemoveOnDestruction) {
+  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+  FilePath appcache_path = temp_dir_.path().Append(chrome::kAppCacheDirname);
+  scoped_refptr<ChromeAppCacheService> appcache_service =
+      new ChromeAppCacheService;
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      NewRunnableMethod(appcache_service.get(),
+                        &ChromeAppCacheService::InitializeOnIOThread,
+                        temp_dir_.path(), false,
+                        scoped_refptr<HostContentSettingsMap>(NULL),
+                        true));
+  // Make the steps needed to initialize the storage of AppCache data.
+  message_loop_.RunAllPending();
+  appcache::AppCacheStorageImpl* storage =
+      static_cast<appcache::AppCacheStorageImpl*>(appcache_service->storage());
+  ASSERT_TRUE(storage->database_->db_connection());
+  ASSERT_EQ(1, storage->NewCacheId());
+  storage->disk_cache();
+  message_loop_.RunAllPending();
+
+  ASSERT_TRUE(file_util::PathExists(appcache_path));
+  ASSERT_TRUE(file_util::PathExists(appcache_path.AppendASCII("Index")));
+
+  appcache_service = NULL;
+  message_loop_.RunAllPending();
+
+  ASSERT_FALSE(file_util::PathExists(appcache_path));
+}
+
+}  // namespace appcache
diff --git a/chrome/browser/appcache/view_appcache_internals_job_factory.cc b/chrome/browser/appcache/view_appcache_internals_job_factory.cc
index 99ef75f..6de6a6a 100644
--- a/chrome/browser/appcache/view_appcache_internals_job_factory.cc
+++ b/chrome/browser/appcache/view_appcache_internals_job_factory.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -20,7 +20,7 @@
 // static.
 net::URLRequestJob* ViewAppCacheInternalsJobFactory::CreateJobForRequest(
     net::URLRequest* request) {
-  URLRequestContext* context = request->context();
+  net::URLRequestContext* context = request->context();
   ChromeURLRequestContext* chrome_request_context =
       reinterpret_cast<ChromeURLRequestContext*>(context);
   return new appcache::ViewAppCacheInternalsJob(
diff --git a/chrome/browser/autocomplete/OWNERS b/chrome/browser/autocomplete/OWNERS
new file mode 100644
index 0000000..3363c14
--- /dev/null
+++ b/chrome/browser/autocomplete/OWNERS
@@ -0,0 +1,2 @@
+pkasting@chromium.org
+sky@chromium.org
diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc
index dfbc3a6..5f8f681 100644
--- a/chrome/browser/autocomplete/autocomplete.cc
+++ b/chrome/browser/autocomplete/autocomplete.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/command_line.h"
 #include "base/i18n/number_formatting.h"
@@ -37,6 +36,7 @@
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domain.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::TimeDelta;
 
@@ -51,13 +51,14 @@
     synchronous_only_(false) {
 }
 
-AutocompleteInput::AutocompleteInput(const std::wstring& text,
-                                     const std::wstring& desired_tld,
+AutocompleteInput::AutocompleteInput(const string16& text,
+                                     const string16& desired_tld,
                                      bool prevent_inline_autocomplete,
                                      bool prefer_keyword,
                                      bool allow_exact_keyword_match,
                                      bool synchronous_only)
-    : desired_tld_(desired_tld),
+    : original_text_(text),
+      desired_tld_(desired_tld),
       initial_prevent_inline_autocomplete_(prevent_inline_autocomplete),
       prevent_inline_autocomplete_(prevent_inline_autocomplete),
       prefer_keyword_(prefer_keyword),
@@ -88,7 +89,7 @@
 
 // static
 void AutocompleteInput::RemoveForcedQueryStringIfNecessary(Type type,
-                                                           std::wstring* text) {
+                                                           string16* text) {
   if (type == FORCED_QUERY && !text->empty() && (*text)[0] == L'?')
     text->erase(0, 1);
 }
@@ -111,13 +112,13 @@
 
 // static
 AutocompleteInput::Type AutocompleteInput::Parse(
-    const std::wstring& text,
-    const std::wstring& desired_tld,
+    const string16& text,
+    const string16& desired_tld,
     url_parse::Parsed* parts,
-    std::wstring* scheme,
+    string16* scheme,
     GURL* canonicalized_url) {
-  const size_t first_non_white = text.find_first_not_of(kWhitespaceWide, 0);
-  if (first_non_white == std::wstring::npos)
+  const size_t first_non_white = text.find_first_not_of(kWhitespaceUTF16, 0);
+  if (first_non_white == string16::npos)
     return INVALID;  // All whitespace.
 
   if (text.at(first_non_white) == L'?') {
@@ -133,15 +134,15 @@
   url_parse::Parsed local_parts;
   if (!parts)
     parts = &local_parts;
-  const std::wstring parsed_scheme(URLFixerUpper::SegmentURL(text, parts));
+  const string16 parsed_scheme(URLFixerUpper::SegmentURL(text, parts));
   if (scheme)
     *scheme = parsed_scheme;
   if (canonicalized_url) {
-    *canonicalized_url = URLFixerUpper::FixupURL(WideToUTF8(text),
-                                                 WideToUTF8(desired_tld));
+    *canonicalized_url = URLFixerUpper::FixupURL(UTF16ToUTF8(text),
+                                                 UTF16ToUTF8(desired_tld));
   }
 
-  if (parsed_scheme == L"file") {
+  if (LowerCaseEqualsASCII(parsed_scheme, chrome::kFileScheme)) {
     // A user might or might not type a scheme when entering a file URL.  In
     // either case, |parsed_scheme| will tell us that this is a file URL, but
     // |parts->scheme| might be empty, e.g. if the user typed "C:\foo".
@@ -155,9 +156,10 @@
   // (e.g. "ftp" or "view-source") but I'll wait to spend the effort on that
   // until I run into some cases that really need it.
   if (parts->scheme.is_nonempty() &&
-      (parsed_scheme != L"http") && (parsed_scheme != L"https")) {
+      !LowerCaseEqualsASCII(parsed_scheme, chrome::kHttpScheme) &&
+      !LowerCaseEqualsASCII(parsed_scheme, chrome::kHttpsScheme)) {
     // See if we know how to handle the URL internally.
-    if (net::URLRequest::IsHandledProtocol(WideToASCII(parsed_scheme)))
+    if (net::URLRequest::IsHandledProtocol(UTF16ToASCII(parsed_scheme)))
       return URL;
 
     // There are also some schemes that we convert to other things before they
@@ -175,7 +177,9 @@
     // "blocked" by the external protocol handler because we don't want pages to
     // open them, but users still can.
     // TODO(viettrungluu): get rid of conversion.
-    switch (ExternalProtocolHandler::GetBlockState(WideToUTF8(parsed_scheme))) {
+    ExternalProtocolHandler::BlockState block_state =
+        ExternalProtocolHandler::GetBlockState(UTF16ToUTF8(parsed_scheme));
+    switch (block_state) {
       case ExternalProtocolHandler::DONT_BLOCK:
         return URL;
 
@@ -187,14 +191,16 @@
       default: {
         // We don't know about this scheme.  It might be that the user typed a
         // URL of the form "username:password@foo.com".
-        const std::wstring http_scheme_prefix = L"http://";
+        const string16 http_scheme_prefix =
+            ASCIIToUTF16(std::string(chrome::kHttpScheme) +
+                         chrome::kStandardSchemeSeparator);
         url_parse::Parsed http_parts;
-        std::wstring http_scheme;
+        string16 http_scheme;
         GURL http_canonicalized_url;
         Type http_type = Parse(http_scheme_prefix + text, desired_tld,
                                &http_parts, &http_scheme,
                                &http_canonicalized_url);
-        DCHECK_EQ("http", WideToUTF8(http_scheme));
+        DCHECK_EQ(std::string(chrome::kHttpScheme), UTF16ToUTF8(http_scheme));
 
         if ((http_type == URL || http_type == REQUESTED_URL) &&
             http_parts.username.is_nonempty() &&
@@ -246,18 +252,19 @@
 
   // Likewise, the RCDS can reject certain obviously-invalid hosts.  (We also
   // use the registry length later below.)
-  const std::wstring host(text.substr(parts->host.begin, parts->host.len));
+  const string16 host(text.substr(parts->host.begin, parts->host.len));
   const size_t registry_length =
-      net::RegistryControlledDomainService::GetRegistryLength(host, false);
-  if (registry_length == std::wstring::npos) {
+      net::RegistryControlledDomainService::GetRegistryLength(UTF16ToUTF8(host),
+                                                              false);
+  if (registry_length == std::string::npos) {
     // Try to append the desired_tld.
     if (!desired_tld.empty()) {
-      std::wstring host_with_tld(host);
+      string16 host_with_tld(host);
       if (host[host.length() - 1] != '.')
         host_with_tld += '.';
       host_with_tld += desired_tld;
       if (net::RegistryControlledDomainService::GetRegistryLength(
-          host_with_tld, false) != std::wstring::npos)
+          UTF16ToUTF8(host_with_tld), false) != std::string::npos)
         return REQUESTED_URL;  // Something like "99999999999" that looks like a
                                // bad IP address, but becomes valid on attaching
                                // a TLD.
@@ -271,10 +278,11 @@
   // unlikely that a user would be trying to type those in for anything other
   // than a search query.
   url_canon::CanonHostInfo host_info;
-  const std::string canonicalized_host(net::CanonicalizeHost(host, &host_info));
+  const std::string canonicalized_host(net::CanonicalizeHost(UTF16ToUTF8(host),
+                                                             &host_info));
   if ((host_info.family == url_canon::CanonHostInfo::NEUTRAL) &&
       !net::IsCanonicalizedHostCompliant(canonicalized_host,
-                                         WideToUTF8(desired_tld))) {
+                                         UTF16ToUTF8(desired_tld))) {
     // Invalid hostname.  There are several possible cases:
     // * Our checker is too strict and the user pasted in a real-world URL
     //   that's "invalid" but resolves.  To catch these, we return UNKNOWN when
@@ -294,7 +302,7 @@
     //   TLD
     // These are rare, though probably possible in intranets.
     return (parts->scheme.is_nonempty() ||
-           ((registry_length != 0) && (host.find(' ') == std::wstring::npos))) ?
+           ((registry_length != 0) && (host.find(' ') == string16::npos))) ?
         UNKNOWN : QUERY;
   }
 
@@ -306,8 +314,8 @@
   // below.
   if (parts->port.is_nonempty()) {
     int port;
-    if (!base::StringToInt(WideToUTF8(
-            text.substr(parts->port.begin, parts->port.len)), &port) ||
+    if (!base::StringToInt(text.substr(parts->port.begin, parts->port.len),
+                           &port) ||
         (port < 0) || (port > 65535))
       return QUERY;
   }
@@ -356,7 +364,7 @@
     // since that's the common case.
     return ((registry_length == 0) &&
             (text.substr(parts->path.begin, parts->path.len).find(' ') !=
-                std::wstring::npos)) ? UNKNOWN : URL;
+                string16::npos)) ? UNKNOWN : URL;
   }
 
   // If we reach here with a username, our input looks like "user@host".
@@ -392,12 +400,12 @@
 
 // static
 void AutocompleteInput::ParseForEmphasizeComponents(
-    const std::wstring& text,
-    const std::wstring& desired_tld,
+    const string16& text,
+    const string16& desired_tld,
     url_parse::Component* scheme,
     url_parse::Component* host) {
   url_parse::Parsed parts;
-  std::wstring scheme_str;
+  string16 scheme_str;
   Parse(text, desired_tld, &parts, &scheme_str, NULL);
 
   *scheme = parts.scheme;
@@ -409,7 +417,7 @@
   if (LowerCaseEqualsASCII(scheme_str, chrome::kViewSourceScheme) &&
       (static_cast<int>(text.length()) > after_scheme_and_colon)) {
     // Obtain the URL prefixed by view-source and parse it.
-    std::wstring real_url(text.substr(after_scheme_and_colon));
+    string16 real_url(text.substr(after_scheme_and_colon));
     url_parse::Parsed real_parts;
     AutocompleteInput::Parse(real_url, desired_tld, &real_parts, NULL, NULL);
     if (real_parts.scheme.is_nonempty() || real_parts.host.is_nonempty()) {
@@ -432,15 +440,15 @@
 }
 
 // static
-std::wstring AutocompleteInput::FormattedStringWithEquivalentMeaning(
+string16 AutocompleteInput::FormattedStringWithEquivalentMeaning(
     const GURL& url,
-    const std::wstring& formatted_url) {
+    const string16& formatted_url) {
   if (!net::CanStripTrailingSlash(url))
     return formatted_url;
-  const std::wstring url_with_path(formatted_url + L"/");
-  return (AutocompleteInput::Parse(formatted_url, std::wstring(), NULL, NULL,
+  const string16 url_with_path(formatted_url + char16('/'));
+  return (AutocompleteInput::Parse(formatted_url, string16(), NULL, NULL,
                                    NULL) ==
-          AutocompleteInput::Parse(url_with_path, std::wstring(), NULL, NULL,
+          AutocompleteInput::Parse(url_with_path, string16(), NULL, NULL,
                                    NULL)) ?
       formatted_url : url_with_path;
 }
@@ -501,8 +509,8 @@
 }
 
 // static
-bool AutocompleteProvider::HasHTTPScheme(const std::wstring& input) {
-  std::string utf8_input(WideToUTF8(input));
+bool AutocompleteProvider::HasHTTPScheme(const string16& input) {
+  std::string utf8_input(UTF16ToUTF8(input));
   url_parse::Component scheme;
   if (url_util::FindAndCompareScheme(utf8_input, chrome::kViewSourceScheme,
                                      &scheme))
@@ -524,16 +532,16 @@
     i->starred = bookmark_model->IsBookmarked(GURL(i->destination_url));
 }
 
-std::wstring AutocompleteProvider::StringForURLDisplay(const GURL& url,
-                                                       bool check_accept_lang,
-                                                       bool trim_http) const {
+string16 AutocompleteProvider::StringForURLDisplay(const GURL& url,
+                                                   bool check_accept_lang,
+                                                   bool trim_http) const {
   std::string languages = (check_accept_lang && profile_) ?
       profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::string();
-  return UTF16ToWideHack(net::FormatUrl(
+  return net::FormatUrl(
       url,
       languages,
       net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP),
-      UnescapeRule::SPACES, NULL, NULL, NULL));
+      UnescapeRule::SPACES, NULL, NULL, NULL);
 }
 
 // AutocompleteResult ---------------------------------------------------------
@@ -548,9 +556,8 @@
 }
 
 AutocompleteResult::AutocompleteResult() {
-  // Reserve space for the max number of matches we'll show. The +1 accounts
-  // for the history shortcut match as it isn't included in max_matches.
-  matches_.reserve(kMaxMatches + 1);
+  // Reserve space for the max number of matches we'll show.
+  matches_.reserve(kMaxMatches);
 
   // It's probably safe to do this in the initializer list, but there's little
   // penalty to doing it here and it ensures our object is fully constructed
@@ -573,6 +580,33 @@
   alternate_nav_url_ = rhs.alternate_nav_url_;
 }
 
+void AutocompleteResult::CopyOldMatches(const AutocompleteResult& old_matches) {
+  if (size() >= old_matches.size())
+    return;  // We've got enough matches.
+
+  if (empty()) {
+    // If we've got no matches we can copy everything from the last result.
+    CopyFrom(old_matches);
+    for (ACMatches::iterator i = begin(); i != end(); ++i)
+      i->from_previous = true;
+    return;
+  }
+
+  // In hopes of providing a stable popup we try to keep the number of matches
+  // per provider consistent. Other schemes (such as blindly copying the most
+  // relevant matches) typically result in many successive 'What You Typed'
+  // results filling all the matches, which looks awful.
+  ProviderToMatchPtrs matches_per_provider, old_matches_per_provider;
+  BuildProviderToMatchPtrs(&matches_per_provider);
+  old_matches.BuildProviderToMatchPtrs(&old_matches_per_provider);
+  size_t delta = old_matches.size() - size();
+  for (ProviderToMatchPtrs::const_iterator i =
+           old_matches_per_provider.begin();
+       i != old_matches_per_provider.end() && delta > 0; ++i) {
+    MergeMatchesByProvider(i->second, matches_per_provider[i->first], &delta);
+  }
+}
+
 void AutocompleteResult::AppendMatches(const ACMatches& matches) {
   std::copy(matches.begin(), matches.end(), std::back_inserter(matches_));
   default_match_ = end();
@@ -599,25 +633,12 @@
                              &AutocompleteMatch::DestinationsEqual),
                  matches_.end());
 
-  // Find the top |kMaxMatches| matches.
-  if (matches_.size() > kMaxMatches) {
-    std::partial_sort(matches_.begin(), matches_.begin() + kMaxMatches,
-                      matches_.end(), &AutocompleteMatch::MoreRelevant);
-    matches_.erase(matches_.begin() + kMaxMatches, matches_.end());
-  }
+  // Sort and trim to the most relevant kMaxMatches matches.
+  const size_t num_matches = std::min(kMaxMatches, matches_.size());
+  std::partial_sort(matches_.begin(), matches_.begin() + num_matches,
+                    matches_.end(), &AutocompleteMatch::MoreRelevant);
+  matches_.resize(num_matches);
 
-  // HistoryContentsProvider uses a negative relevance as a way to avoid
-  // starving out other provider matches, yet we may end up using this match. To
-  // make sure such matches are sorted correctly we search for all
-  // relevances < 0 and negate them. If we change our relevance algorithm to
-  // properly mix different providers' matches, this can go away.
-  for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) {
-    if (i->relevance < 0)
-      i->relevance = -i->relevance;
-  }
-
-  // Put the final result set in order.
-  std::sort(matches_.begin(), matches_.end(), &AutocompleteMatch::MoreRelevant);
   default_match_ = begin();
 
   // Set the alternate nav URL.
@@ -631,6 +652,27 @@
     alternate_nav_url_ = input.canonicalized_url();
 }
 
+bool AutocompleteResult::HasCopiedMatches() const {
+  for (ACMatches::const_iterator i = begin(); i != end(); ++i) {
+    if (i->from_previous)
+      return true;
+  }
+  return false;
+}
+
+bool AutocompleteResult::RemoveCopiedMatches() {
+  bool removed = false;
+  for (ACMatches::iterator i = begin(); i != end(); ) {
+    if (i->from_previous) {
+      i = matches_.erase(i);
+      removed = true;
+    } else {
+      ++i;
+    }
+  }
+  return removed;
+}
+
 size_t AutocompleteResult::size() const {
   return matches_.size();
 }
@@ -666,6 +708,16 @@
   default_match_ = end();
 }
 
+void AutocompleteResult::Swap(AutocompleteResult* other) {
+  const size_t default_match_offset = default_match_ - begin();
+  const size_t other_default_match_offset =
+      other->default_match_ - other->begin();
+  matches_.swap(other->matches_);
+  default_match_ = begin() + other_default_match_offset;
+  other->default_match_ = other->begin() + default_match_offset;
+  alternate_nav_url_.Swap(&(other->alternate_nav_url_));
+}
+
 #ifndef NDEBUG
 void AutocompleteResult::Validate() const {
   for (const_iterator i(begin()); i != end(); ++i)
@@ -673,21 +725,64 @@
 }
 #endif
 
+void AutocompleteResult::BuildProviderToMatchPtrs(
+    ProviderToMatchPtrs* provider_to_matches) const {
+  for (ACMatches::const_iterator i = begin(); i != end(); ++i)
+    (*provider_to_matches)[i->provider].push_back(&(*i));
+}
+
+// static
+bool AutocompleteResult::HasMatchByDestination(const AutocompleteMatch& match,
+                                               const ACMatchPtrs& matches) {
+  for (ACMatchPtrs::const_iterator i = matches.begin(); i != matches.end();
+       ++i) {
+    if ((*i)->destination_url == match.destination_url)
+      return true;
+  }
+  return false;
+}
+
+void AutocompleteResult::MergeMatchesByProvider(const ACMatchPtrs& old_matches,
+                                                const ACMatchPtrs& new_matches,
+                                                size_t* max_to_add) {
+  if (new_matches.size() >= old_matches.size())
+    return;
+
+  size_t delta = old_matches.size() - new_matches.size();
+  const int max_relevance = (new_matches.empty() ?
+      matches_.front().relevance : new_matches[0]->relevance) - 1;
+  // Because the goal is a visibly-stable popup, rather than one that preserves
+  // the highest-relevance matches, we copy in the lowest-relevance matches
+  // first. This means that within each provider's "group" of matches, any
+  // synchronous matches (which tend to have the highest scores) will
+  // "overwrite" the initial matches from that provider's previous results,
+  // minimally disturbing the rest of the matches.
+  for (ACMatchPtrs::const_reverse_iterator i = old_matches.rbegin();
+       i != old_matches.rend() && *max_to_add > 0 && delta > 0; ++i) {
+    if (!HasMatchByDestination(**i, new_matches)) {
+      AutocompleteMatch match = **i;
+      match.relevance = std::min(max_relevance, match.relevance);
+      match.from_previous = true;
+      AddMatch(match);
+      (*max_to_add)--;
+      delta--;
+    }
+  }
+}
+
 // AutocompleteController -----------------------------------------------------
 
 const int AutocompleteController::kNoItemSelected = -1;
 
-namespace {
-// The time we'll wait between sending updates to our observers (balances
-// flicker against lag).
-const int kUpdateDelayMs = 350;
-};
+// Amount of time (in ms) between when the user stops typing and when we remove
+// any copied entries. We do this from the time the user stopped typing as some
+// providers (such as SearchProvider) wait for the user to stop typing before
+// they initiate a query.
+static const int kExpireTimeMS = 500;
 
 AutocompleteController::AutocompleteController(Profile* profile)
-    : updated_latest_result_(false),
-      delay_interval_has_passed_(false),
-      have_committed_during_this_query_(false),
-      done_(true) {
+    : done_(true),
+      in_start_(false) {
   search_provider_ = new SearchProvider(this, profile);
   providers_.push_back(search_provider_);
   if (!CommandLine::ForCurrentProcess()->HasSwitch(
@@ -697,8 +792,7 @@
       switches::kDisableHistoryURLProvider))
     providers_.push_back(new HistoryURLProvider(this, profile));
   providers_.push_back(new KeywordProvider(this, profile));
-  history_contents_provider_ = new HistoryContentsProvider(this, profile);
-  providers_.push_back(history_contents_provider_);
+  providers_.push_back(new HistoryContentsProvider(this, profile));
   for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i)
     (*i)->AddRef();
 }
@@ -727,13 +821,13 @@
                    // different profile.
 }
 
-void AutocompleteController::Start(const std::wstring& text,
-                                   const std::wstring& desired_tld,
+void AutocompleteController::Start(const string16& text,
+                                   const string16& desired_tld,
                                    bool prevent_inline_autocomplete,
                                    bool prefer_keyword,
                                    bool allow_exact_keyword_match,
                                    bool synchronous_only) {
-  const std::wstring old_input_text(input_.text());
+  const string16 old_input_text(input_.text());
   const bool old_synchronous_only = input_.synchronous_only();
   input_ = AutocompleteInput(text, desired_tld, prevent_inline_autocomplete,
       prefer_keyword, allow_exact_keyword_match, synchronous_only);
@@ -750,36 +844,22 @@
   const bool minimal_changes = (input_.text() == old_input_text) &&
       (input_.synchronous_only() == old_synchronous_only);
 
-  // If we're interrupting an old query, and committing its result won't shrink
-  // the visible set (which would probably re-expand soon, thus looking very
-  // flickery), then go ahead and commit what we've got, in order to feel more
-  // responsive when the user is typing rapidly.  In this case it's important
-  // that we don't update the edit, as the user has already changed its contents
-  // and anything we might do with it (e.g. inline autocomplete) likely no
-  // longer applies.
-  if (!minimal_changes && !done_ && (latest_result_.size() >= result_.size()))
-    CommitResult(false);
-
-  // If the timer is already running, it could fire shortly after starting this
-  // query, when we're likely to only have the synchronous results back, thus
-  // almost certainly causing flicker.  Reset it, except when we haven't
-  // committed anything for the past query, in which case the user is typing
-  // quickly and we need to keep running the timer lest we lag too far behind.
-  if (have_committed_during_this_query_) {
-    update_delay_timer_.Stop();
-    delay_interval_has_passed_ = false;
-  }
+  expire_timer_.Stop();
 
   // Start the new query.
-  have_committed_during_this_query_ = false;
+  in_start_ = true;
   for (ACProviders::iterator i(providers_.begin()); i != providers_.end();
        ++i) {
     (*i)->Start(input_, minimal_changes);
     if (synchronous_only)
       DCHECK((*i)->done());
   }
+  in_start_ = false;
   CheckIfDone();
-  UpdateLatestResult(true);
+  UpdateResult(true);
+
+  if (!done_)
+    StartExpireTimer();
 }
 
 void AutocompleteController::Stop(bool clear_result) {
@@ -788,217 +868,86 @@
     (*i)->Stop();
   }
 
-  update_delay_timer_.Stop();
-  updated_latest_result_ = false;
-  delay_interval_has_passed_ = false;
+  expire_timer_.Stop();
   done_ = true;
   if (clear_result && !result_.empty()) {
     result_.Reset();
-    NotificationService::current()->Notify(
-        NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
-        Source<AutocompleteController>(this),
-        Details<const AutocompleteResult>(&result_));
-    // NOTE: We don't notify AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED since
-    // we're trying to only clear the popup, not touch the edit... this is all
-    // a mess and should be cleaned up :(
+    // NOTE: We pass in false since we're trying to only clear the popup, not
+    // touch the edit... this is all a mess and should be cleaned up :(
+    NotifyChanged(false);
   }
-  latest_result_.CopyFrom(result_);
 }
 
 void AutocompleteController::DeleteMatch(const AutocompleteMatch& match) {
   DCHECK(match.deletable);
   match.provider->DeleteMatch(match);  // This may synchronously call back to
                                        // OnProviderUpdate().
-  CommitResult(true);  // Ensure any new result gets committed immediately.  If
-                       // it was committed already or hasn't been modified, this
-                       // is harmless.
+  // If DeleteMatch resulted in a callback to OnProviderUpdate and we're
+  // not done, we might attempt to redisplay the deleted match. Make sure
+  // we aren't displaying it by removing any old entries.
+  ExpireCopiedEntries();
 }
 
-void AutocompleteController::CommitIfQueryHasNeverBeenCommitted() {
-  if (!have_committed_during_this_query_)
-    CommitResult(true);
+void AutocompleteController::ExpireCopiedEntries() {
+  if (result_.RemoveCopiedMatches())
+    NotifyChanged(false);
 }
 
 void AutocompleteController::OnProviderUpdate(bool updated_matches) {
   CheckIfDone();
-  if (updated_matches || done_)
-    UpdateLatestResult(false);
+  // Multiple providers may provide synchronous results, so we only update the
+  // results if we're not in Start().
+  if (!in_start_ && (updated_matches || done_))
+    UpdateResult(false);
 }
 
-void AutocompleteController::UpdateLatestResult(bool is_synchronous_pass) {
-  // Add all providers' matches.
-  latest_result_.Reset();
+void AutocompleteController::UpdateResult(bool is_synchronous_pass) {
+  AutocompleteResult last_result;
+  last_result.Swap(&result_);
+
   for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end();
        ++i)
-    latest_result_.AppendMatches((*i)->matches());
-  updated_latest_result_ = true;
+    result_.AppendMatches((*i)->matches());
 
   // Sort the matches and trim to a small number of "best" matches.
-  latest_result_.SortAndCull(input_);
+  result_.SortAndCull(input_);
 
-  if (history_contents_provider_)
-    AddHistoryContentsShortcut();
-
+  // Need to validate before invoking CopyOldMatches as the old matches are not
+  // valid against the current input.
 #ifndef NDEBUG
-  latest_result_.Validate();
+  result_.Validate();
 #endif
 
-  if (is_synchronous_pass) {
-    if (!update_delay_timer_.IsRunning()) {
-      update_delay_timer_.Start(
-          TimeDelta::FromMilliseconds(kUpdateDelayMs),
-          this, &AutocompleteController::DelayTimerFired);
-    }
-
-    NotificationService::current()->Notify(
-        NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED,
-        Source<AutocompleteController>(this),
-        Details<const AutocompleteResult>(&latest_result_));
+  if (!done_) {
+    // This conditional needs to match the conditional in Start that invokes
+    // StartExpireTimer.
+    result_.CopyOldMatches(last_result);
   }
 
-  // If nothing is visible, commit immediately so that the first character the
-  // user types produces an instant response.  If the query has finished and we
-  // haven't ever committed a result set, commit immediately to minimize lag.
-  // Otherwise, only commit when it's been at least one delay interval since the
-  // last commit, to minimize flicker.
-  if (result_.empty() || (done_ && !have_committed_during_this_query_) ||
-      delay_interval_has_passed_)
-    CommitResult(true);
-}
-
-void AutocompleteController::DelayTimerFired() {
-  delay_interval_has_passed_ = true;
-  CommitResult(true);
-}
-
-void AutocompleteController::CommitResult(bool notify_default_match) {
-  if (done_) {
-    update_delay_timer_.Stop();
-    delay_interval_has_passed_ = false;
+  bool notify_default_match = is_synchronous_pass;
+  if (!is_synchronous_pass) {
+    const bool last_default_was_valid =
+        last_result.default_match() != last_result.end();
+    const bool default_is_valid = result_.default_match() != result_.end();
+    // We've gotten async results. Send notification that the default match
+    // updated if fill_into_edit differs. We don't check the URL as that may
+    // change for the default match even though the fill into edit hasn't
+    // changed (see SearchProvider for one case of this).
+    notify_default_match =
+        (last_default_was_valid != default_is_valid) ||
+        (default_is_valid &&
+         (result_.default_match()->fill_into_edit !=
+          last_result.default_match()->fill_into_edit));
   }
 
-  // Don't send update notifications when nothing's actually changed.
-  if (!updated_latest_result_)
-    return;
+  NotifyChanged(notify_default_match);
+}
 
-  updated_latest_result_ = false;
-  delay_interval_has_passed_ = false;
-  have_committed_during_this_query_ = true;
-  result_.CopyFrom(latest_result_);
+void AutocompleteController::NotifyChanged(bool notify_default_match) {
   NotificationService::current()->Notify(
       NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
       Source<AutocompleteController>(this),
-      Details<const AutocompleteResult>(&result_));
-  if (notify_default_match) {
-    // This notification must be sent after the other so the popup has time to
-    // update its state before the edit calls into it.
-    // TODO(pkasting): Eliminate this ordering requirement.
-    NotificationService::current()->Notify(
-        NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED,
-        Source<AutocompleteController>(this),
-        Details<const AutocompleteResult>(&result_));
-  }
-  if (!done_)
-    update_delay_timer_.Reset();
-}
-
-ACMatches AutocompleteController::GetMatchesNotInLatestResult(
-    const AutocompleteProvider* provider) const {
-  DCHECK(provider);
-
-  // Determine the set of destination URLs.
-  std::set<GURL> destination_urls;
-  for (AutocompleteResult::const_iterator i(latest_result_.begin());
-       i != latest_result_.end(); ++i)
-    destination_urls.insert(i->destination_url);
-
-  ACMatches matches;
-  const ACMatches& provider_matches = provider->matches();
-  for (ACMatches::const_iterator i = provider_matches.begin();
-       i != provider_matches.end(); ++i) {
-    if (destination_urls.find(i->destination_url) == destination_urls.end())
-      matches.push_back(*i);
-  }
-
-  return matches;
-}
-
-void AutocompleteController::AddHistoryContentsShortcut() {
-  DCHECK(history_contents_provider_);
-  // Only check the history contents provider if the history contents provider
-  // is done and has matches.
-  if (!history_contents_provider_->done() ||
-      !history_contents_provider_->db_match_count()) {
-    return;
-  }
-
-  if ((history_contents_provider_->db_match_count() <=
-          (latest_result_.size() + 1)) ||
-      (history_contents_provider_->db_match_count() == 1)) {
-    // We only want to add a shortcut if we're not already showing the matches.
-    ACMatches matches(GetMatchesNotInLatestResult(history_contents_provider_));
-    if (matches.empty())
-      return;
-    if (matches.size() == 1) {
-      // Only one match not shown, add it. The relevance may be negative,
-      // which means we need to negate it to get the true relevance.
-      AutocompleteMatch& match = matches.front();
-      if (match.relevance < 0)
-        match.relevance = -match.relevance;
-      latest_result_.AddMatch(match);
-      return;
-    } // else, fall through and add item.
-  }
-
-  AutocompleteMatch match(NULL, 0, false, AutocompleteMatch::OPEN_HISTORY_PAGE);
-  match.fill_into_edit = input_.text();
-
-  // Mark up the text such that the user input text is bold.
-  size_t keyword_offset = std::wstring::npos;  // Offset into match.contents.
-  if (history_contents_provider_->db_match_count() ==
-      history_contents_provider_->kMaxMatchCount) {
-    // History contents searcher has maxed out.
-    match.contents = UTF16ToWideHack(
-        l10n_util::GetStringFUTF16(IDS_OMNIBOX_RECENT_HISTORY_MANY,
-                                   WideToUTF16Hack(input_.text()),
-                                   &keyword_offset));
-  } else {
-    // We can report exact matches when there aren't too many.
-    std::vector<size_t> content_param_offsets;
-    match.contents = UTF16ToWideHack(l10n_util::GetStringFUTF16(
-        IDS_OMNIBOX_RECENT_HISTORY,
-        base::FormatNumber(history_contents_provider_->
-                               db_match_count()),
-        WideToUTF16Hack(input_.text()),
-        &content_param_offsets));
-
-    // content_param_offsets is ordered based on supplied params, we expect
-    // that the second one contains the query (first is the number).
-    if (content_param_offsets.size() == 2) {
-      keyword_offset = content_param_offsets[1];
-    } else {
-      // See comments on an identical NOTREACHED() in search_provider.cc.
-      NOTREACHED();
-    }
-  }
-
-  // NOTE: This comparison succeeds when keyword_offset == std::wstring::npos.
-  if (keyword_offset > 0) {
-    match.contents_class.push_back(
-        ACMatchClassification(0, ACMatchClassification::NONE));
-  }
-  match.contents_class.push_back(
-      ACMatchClassification(keyword_offset, ACMatchClassification::MATCH));
-  if (keyword_offset + input_.text().size() < match.contents.size()) {
-    match.contents_class.push_back(
-        ACMatchClassification(keyword_offset + input_.text().size(),
-                              ACMatchClassification::NONE));
-  }
-  match.destination_url =
-      HistoryUI::GetHistoryURLWithSearchText(WideToUTF16(input_.text()));
-  match.transition = PageTransition::AUTO_BOOKMARK;
-  match.provider = history_contents_provider_;
-  latest_result_.AddMatch(match);
+      Details<bool>(&notify_default_match));
 }
 
 void AutocompleteController::CheckIfDone() {
@@ -1011,3 +960,9 @@
   }
   done_ = true;
 }
+
+void AutocompleteController::StartExpireTimer() {
+  if (result_.HasCopiedMatches())
+    expire_timer_.Start(base::TimeDelta::FromMilliseconds(kExpireTimeMS),
+                        this, &AutocompleteController::ExpireCopiedEntries);
+}
diff --git a/chrome/browser/autocomplete/autocomplete.h b/chrome/browser/autocomplete/autocomplete.h
index f91dbab..148209f 100644
--- a/chrome/browser/autocomplete/autocomplete.h
+++ b/chrome/browser/autocomplete/autocomplete.h
@@ -6,11 +6,13 @@
 #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_
 #pragma once
 
+#include <map>
 #include <string>
 #include <vector>
 
 #include "base/logging.h"
 #include "base/ref_counted.h"
+#include "base/string16.h"
 #include "base/timer.h"
 #include "googleurl/src/gurl.h"
 #include "googleurl/src/url_parse.h"
@@ -180,8 +182,8 @@
   };
 
   AutocompleteInput();
-  AutocompleteInput(const std::wstring& text,
-                    const std::wstring& desired_tld,
+  AutocompleteInput(const string16& text,
+                    const string16& desired_tld,
                     bool prevent_inline_autocomplete,
                     bool prefer_keyword,
                     bool allow_exact_keyword_match,
@@ -189,7 +191,7 @@
   ~AutocompleteInput();
 
   // If type is |FORCED_QUERY| and |text| starts with '?', it is removed.
-  static void RemoveForcedQueryStringIfNecessary(Type type, std::wstring* text);
+  static void RemoveForcedQueryStringIfNecessary(Type type, string16* text);
 
   // Converts |type| to a string representation.  Used in logging.
   static std::string TypeToString(Type type);
@@ -199,18 +201,18 @@
   // it is non-NULL. The scheme is stored in |scheme| if it is non-NULL. The
   // canonicalized URL is stored in |canonicalized_url|; however, this URL is
   // not guaranteed to be valid, especially if the parsed type is, e.g., QUERY.
-  static Type Parse(const std::wstring& text,
-                    const std::wstring& desired_tld,
+  static Type Parse(const string16& text,
+                    const string16& desired_tld,
                     url_parse::Parsed* parts,
-                    std::wstring* scheme,
+                    string16* scheme,
                     GURL* canonicalized_url);
 
   // Parses |text| and fill |scheme| and |host| by the positions of them.
   // The results are almost as same as the result of Parse(), but if the scheme
   // is view-source, this function returns the positions of scheme and host
   // in the URL qualified by "view-source:" prefix.
-  static void ParseForEmphasizeComponents(const std::wstring& text,
-                                          const std::wstring& desired_tld,
+  static void ParseForEmphasizeComponents(const string16& text,
+                                          const string16& desired_tld,
                                           url_parse::Component* scheme,
                                           url_parse::Component* host);
 
@@ -220,23 +222,27 @@
   // function with the URL and its formatted string, and it will return a
   // formatted string with the same meaning as the original URL (i.e. it will
   // re-append a slash if necessary).
-  static std::wstring FormattedStringWithEquivalentMeaning(
+  static string16 FormattedStringWithEquivalentMeaning(
       const GURL& url,
-      const std::wstring& formatted_url);
+      const string16& formatted_url);
 
   // User-provided text to be completed.
-  const std::wstring& text() const { return text_; }
+  const string16& text() const { return text_; }
 
   // Use of this setter is risky, since no other internal state is updated
   // besides |text_|.  Only callers who know that they're not changing the
   // type/scheme/etc. should use this.
-  void set_text(const std::wstring& text) { text_ = text; }
+  void set_text(const string16& text) { text_ = text; }
+
+  // The text supplied to the constructor. This differs from |text| if the text
+  // supplied to the constructor had leading or trailing white space.
+  const string16& original_text() const { return original_text_; }
 
   // User's desired TLD, if one is not already present in the text to
   // autocomplete.  When this is non-empty, it also implies that "www." should
   // be prepended to the domain where possible.  This should not have a leading
   // '.' (use "com" instead of ".com").
-  const std::wstring& desired_tld() const { return desired_tld_; }
+  const string16& desired_tld() const { return desired_tld_; }
 
   // The type of input supplied.
   Type type() const { return type_; }
@@ -246,7 +252,7 @@
 
   // The scheme parsed from the provided text; only meaningful when type_ is
   // URL.
-  const std::wstring& scheme() const { return scheme_; }
+  const string16& scheme() const { return scheme_; }
 
   // The input as an URL to navigate to, if possible.
   const GURL& canonicalized_url() const { return canonicalized_url_; }
@@ -285,11 +291,12 @@
   void Clear();
 
  private:
-  std::wstring text_;
-  std::wstring desired_tld_;
+  string16 text_;
+  string16 original_text_;
+  string16 desired_tld_;
   Type type_;
   url_parse::Parsed parts_;
-  std::wstring scheme_;
+  string16 scheme_;
   GURL canonicalized_url_;
   bool initial_prevent_inline_autocomplete_;
   bool prevent_inline_autocomplete_;
@@ -389,7 +396,7 @@
   virtual ~AutocompleteProvider();
 
   // Returns whether |input| begins "http:" or "view-source:http:".
-  static bool HasHTTPScheme(const std::wstring& input);
+  static bool HasHTTPScheme(const string16& input);
 
   // Updates the starred state of each of the matches in matches_ from the
   // profile's bookmark bar model.
@@ -398,9 +405,9 @@
   // A convenience function to call net::FormatUrl() with the current set of
   // "Accept Languages" when check_accept_lang is true.  Otherwise, it's called
   // with an empty list.
-  std::wstring StringForURLDisplay(const GURL& url,
-                                   bool check_accept_lang,
-                                   bool trim_http) const;
+  string16 StringForURLDisplay(const GURL& url,
+                               bool check_accept_lang,
+                               bool trim_http) const;
 
   // The profile associated with the AutocompleteProvider.  Reference is not
   // owned by us.
@@ -466,6 +473,10 @@
   // operator=() by another name.
   void CopyFrom(const AutocompleteResult& rhs);
 
+  // If there are fewer matches in this result set than in |old_matches|, copies
+  // enough matches from |old_matches| to make the counts equal.
+  void CopyOldMatches(const AutocompleteResult& old_matches);
+
   // Adds a single match. The match is inserted at the appropriate position
   // based on relevancy and display order. This is ONLY for use after
   // SortAndCull() has been invoked, and preserves default_match_.
@@ -479,6 +490,13 @@
   // and updates the alternate nav URL.
   void SortAndCull(const AutocompleteInput& input);
 
+  // Returns true if at least one match was copied from the last result.
+  bool HasCopiedMatches() const;
+
+  // Removes any matches that were copied from the previous result. Returns true
+  // if at least one entry was removed.
+  bool RemoveCopiedMatches();
+
   // Vector-style accessors/operators.
   size_t size() const;
   bool empty() const;
@@ -499,17 +517,35 @@
   // Clears the matches for this result set.
   void Reset();
 
+  void Swap(AutocompleteResult* other);
+
 #ifndef NDEBUG
   // Does a data integrity check on this result.
   void Validate() const;
 #endif
 
-  // Max number of matches we'll show from the various providers. We may end
-  // up showing an additional shortcut for Destinations->History, see
-  // AddHistoryContentsShortcut.
+  // Max number of matches we'll show from the various providers.
   static const size_t kMaxMatches;
 
  private:
+  typedef std::vector<const AutocompleteMatch*> ACMatchPtrs;
+  typedef std::map<AutocompleteProvider*, ACMatchPtrs> ProviderToMatchPtrs;
+
+  // Populates |provider_to_matches| from |matches_|.
+  void BuildProviderToMatchPtrs(ProviderToMatchPtrs* provider_to_matches) const;
+
+  // Returns true if |matches| contains a match with the same destination as
+  // |match|.
+  static bool HasMatchByDestination(const AutocompleteMatch& match,
+                                    const ACMatchPtrs& matches);
+
+  // Copies matches into this result. |old_matches| gives the matches from the
+  // last result, and |new_matches| the results from this result. |max_to_add|
+  // is decremented for each match copied.
+  void MergeMatchesByProvider(const ACMatchPtrs& old_matches,
+                              const ACMatchPtrs& new_matches,
+                              size_t* max_to_add);
+
   ACMatches matches_;
 
   const_iterator default_match_;
@@ -543,12 +579,9 @@
 #ifdef UNIT_TEST
   explicit AutocompleteController(const ACProviders& providers)
       : providers_(providers),
-        history_contents_provider_(NULL),
         search_provider_(NULL),
-        updated_latest_result_(false),
-        delay_interval_has_passed_(false),
-        have_committed_during_this_query_(false),
-        done_(true) {
+        done_(true),
+        in_start_(false) {
   }
 #endif
   ~AutocompleteController();
@@ -575,21 +608,19 @@
   //
   // |allow_exact_keyword_match| should be false when triggering keyword mode on
   // the input string would be surprising or wrong, e.g. when highlighting text
-  // in a page and telling the browser to search for it or navigate to it.
+  // in a page and telling the browser to search for it or navigate to it. This
+  // parameter only applies to substituting keywords.
 
   // If |synchronous_only| is true, the controller asks the providers to only
   // return matches which are synchronously available, which should mean that
   // all providers will be done immediately.
   //
-  // The controller will fire
-  // AUTOCOMPLETE_CONTROLLER_SYNCHRONOUS_MATCHES_AVAILABLE from inside this
-  // call, and unless the query is stopped, will fire at least one (and perhaps
-  // more) AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED later as more matches come in
-  // (even if the query completes synchronously).  Listeners should use the
-  // result set provided in the accompanying Details object to update
-  // themselves.
-  void Start(const std::wstring& text,
-             const std::wstring& desired_tld,
+  // The controller will fire AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED from
+  // inside this call at least once. If matches are available later on that
+  // result in changing the result set AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED
+  // is sent again.
+  void Start(const string16& text,
+             const string16& desired_tld,
              bool prevent_inline_autocomplete,
              bool prefer_keyword,
              bool allow_exact_keyword_match,
@@ -607,59 +638,43 @@
   // no query is running.
   void DeleteMatch(const AutocompleteMatch& match);
 
-  // Commits the results for the current query if they've never been committed.
-  // This is used by the popup to ensure it's not showing an out-of-date query.
-  void CommitIfQueryHasNeverBeenCommitted();
+  // Removes any entries that were copied from the last result. This is used by
+  // the popup to ensure it's not showing an out-of-date query.
+  void ExpireCopiedEntries();
 
   SearchProvider* search_provider() const { return search_provider_; }
 
   // Getters
   const AutocompleteInput& input() const { return input_; }
   const AutocompleteResult& result() const { return result_; }
-  // This next is temporary and should go away when
-  // AutocompletePopup::InfoForCurrentSelection() moves to the controller.
-  const AutocompleteResult& latest_result() const { return latest_result_; }
-  bool done() const { return done_ && !update_delay_timer_.IsRunning(); }
+  bool done() const { return done_; }
 
   // From AutocompleteProvider::Listener
   virtual void OnProviderUpdate(bool updated_matches);
 
  private:
-  // Updates |latest_result_| and |done_| to reflect the current provider state.
-  // Resets timers and fires notifications as necessary.  |is_synchronous_pass|
-  // is true only when Start() is calling this to get the synchronous result.
-  void UpdateLatestResult(bool is_synchronous_pass);
+  // Updates |result_| to reflect the current provider state.  Resets timers and
+  // fires notifications as necessary.  |is_synchronous_pass| is true only when
+  // Start() is calling this to get the synchronous result.
+  void UpdateResult(bool is_synchronous_pass);
 
-  // Callback for when |max_delay_timer_| fires; this notes that the delay
-  // interval has passed and commits the result, if it's changed.
-  void DelayTimerFired();
-
-  // Copies |latest_result_| to |result_| and notifies observers of updates.
-  // |notify_default_match| should normally be true; if it's false, we don't
-  // send an AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED notification.  This
-  // is a hack to avoid updating the edit with out-of-date data.
+  // Sends notifications that the results were updated. If
+  // |notify_default_match| is true,
+  // AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED is sent in addition to
+  // AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED.
   // TODO(pkasting): Don't hardcode assumptions about who listens to these
   // notificiations.
-  void CommitResult(bool notify_default_match);
-
-  // Returns the matches from |provider| whose destination urls are not in
-  // |latest_result_|.
-  ACMatches GetMatchesNotInLatestResult(
-      const AutocompleteProvider* provider) const;
-
-  // If the HistoryContentsAutocomplete provider is done and there are more
-  // matches in the database than currently shown, an entry is added to
-  // |latest_result_| to show all history matches.
-  void AddHistoryContentsShortcut();
+  void NotifyChanged(bool notify_default_match);
 
   // Updates |done_| to be accurate with respect to current providers' statuses.
   void CheckIfDone();
 
+  // Starts the expire timer.
+  void StartExpireTimer();
+
   // A list of all providers.
   ACProviders providers_;
 
-  HistoryContentsProvider* history_contents_provider_;
-
   SearchProvider* search_provider_;
 
   // Input passed to Start.
@@ -668,43 +683,16 @@
   // Data from the autocomplete query.
   AutocompleteResult result_;
 
-  // The latest result available from the autocomplete providers.  This may be
-  // different than |result_| if we've gotten matches from our providers that we
-  // haven't yet shown the user.  If there aren't yet as many matches as in
-  // |result|, we'll wait to display these in hopes of minimizing flicker in GUI
-  // observers.
-  AutocompleteResult latest_result_;
-
-  // True if |latest_result_| has been updated since it was last committed to
-  // |result_|.  Used to determine whether we need to commit any changes.
-  bool updated_latest_result_;
-
-  // True when it's been at least one interval of the delay timer since we
-  // committed any updates.  This is used to allow a new update to be committed
-  // immediately.
-  //
-  // NOTE: This can never be true when |have_committed_during_this_query_| is
-  // false (except transiently while processing the timer firing).
-  bool delay_interval_has_passed_;
-
-  // True when we've committed a result set at least once during this query.
-  // When this is false, we commit immediately when |done_| is set, since there
-  // are no more updates to come and thus no possible flicker due to committing
-  // immediately.
-  //
-  // NOTE: This can never be false when |delay_interval_has_passed_| is true
-  // (except transiently while processing the timer firing).
-  bool have_committed_during_this_query_;
+  // Timer used to remove any matches copied from the last result. When run
+  // invokes |ExpireCopiedEntries|.
+  base::OneShotTimer<AutocompleteController> expire_timer_;
 
   // True if a query is not currently running.
   bool done_;
 
-  // Timer that tracks how long it's been since the last time we sent our
-  // observers a new result set.  This is used both to enforce a lower bound on
-  // the delay between most commits (to reduce flicker), and ensure that updates
-  // eventually get committed no matter what delays occur between them or how
-  // fast or continuously the user is typing.
-  base::RepeatingTimer<AutocompleteController> update_delay_timer_;
+  // Are we in Start()? This is used to avoid updating |result_| and sending
+  // notifications until Start() has been invoked on all providers.
+  bool in_start_;
 
   DISALLOW_COPY_AND_ASSIGN(AutocompleteController);
 };
@@ -714,7 +702,7 @@
 // The data to log (via the metrics service) when the user selects an item
 // from the omnibox popup.
 struct AutocompleteLog {
-  AutocompleteLog(std::wstring text,
+  AutocompleteLog(string16 text,
                   AutocompleteInput::Type input_type,
                   size_t selected_index,
                   size_t inline_autocompleted_length,
@@ -726,7 +714,7 @@
         result(result) {
   }
   // The user's input text in the omnibox.
-  std::wstring text;
+  string16 text;
   // The detected type of the user's input.
   AutocompleteInput::Type input_type;
   // Selected index (if selected) or -1 (AutocompletePopupModel::kNoMatch).
diff --git a/chrome/browser/autocomplete/autocomplete_accessibility.cc b/chrome/browser/autocomplete/autocomplete_accessibility.cc
index 747d8fe..05cc6c0 100644
--- a/chrome/browser/autocomplete/autocomplete_accessibility.cc
+++ b/chrome/browser/autocomplete/autocomplete_accessibility.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/autocomplete/autocomplete_accessibility.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/autocomplete/autocomplete_edit.h"
 #include "chrome/browser/autocomplete/autocomplete_edit_view_win.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/accessibility/view_accessibility.h"
 #include "views/view.h"
 
@@ -120,7 +120,7 @@
     return E_INVALIDARG;
   }
 
-  std::wstring temp_value;
+  string16 temp_value;
 
   if (var_id.lVal != CHILDID_SELF)
     return E_INVALIDARG;
diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc
index 1d695d2..fa57800 100644
--- a/chrome/browser/autocomplete/autocomplete_browsertest.cc
+++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/format_macros.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
@@ -32,16 +33,16 @@
 
 namespace {
 
-std::wstring AutocompleteResultAsString(const AutocompleteResult& result) {
-  std::wstring output(StringPrintf(L"{%d} ", result.size()));
+string16 AutocompleteResultAsString(const AutocompleteResult& result) {
+  std::string output(base::StringPrintf("{%" PRIuS "} ", result.size()));
   for (size_t i = 0; i < result.size(); ++i) {
     AutocompleteMatch match = result.match_at(i);
-    std::wstring provider_name(ASCIIToWide(match.provider->name()));
-    output.append(StringPrintf(L"[\"%ls\" by \"%ls\"] ",
-                               match.contents.c_str(),
-                               provider_name.c_str()));
+    std::string provider_name = match.provider->name();
+    output.append(base::StringPrintf("[\"%s\" by \"%s\"] ",
+                                     UTF16ToUTF8(match.contents).c_str(),
+                                     provider_name.c_str()));
   }
-  return output;
+  return UTF8ToUTF16(output);
 }
 
 }  // namespace
@@ -62,7 +63,7 @@
   LocationBar* location_bar = GetLocationBar();
 
   EXPECT_TRUE(location_bar->GetInputString().empty());
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
   // TODO(phajdan.jr): check state of IsSelectAll when it's consistent across
   // platforms.
@@ -70,28 +71,28 @@
   location_bar->FocusLocation(true);
 
   EXPECT_TRUE(location_bar->GetInputString().empty());
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
   EXPECT_TRUE(location_bar->location_entry()->IsSelectAll());
 
-  location_bar->location_entry()->SetUserText(L"chrome");
+  location_bar->location_entry()->SetUserText(ASCIIToUTF16("chrome"));
 
   EXPECT_TRUE(location_bar->GetInputString().empty());
-  EXPECT_EQ(L"chrome", location_bar->location_entry()->GetText());
+  EXPECT_EQ(ASCIIToUTF16("chrome"), location_bar->location_entry()->GetText());
   EXPECT_FALSE(location_bar->location_entry()->IsSelectAll());
 
   location_bar->location_entry()->RevertAll();
 
   EXPECT_TRUE(location_bar->GetInputString().empty());
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
   EXPECT_FALSE(location_bar->location_entry()->IsSelectAll());
 
-  location_bar->location_entry()->SetUserText(L"chrome");
+  location_bar->location_entry()->SetUserText(ASCIIToUTF16("chrome"));
   location_bar->Revert();
 
   EXPECT_TRUE(location_bar->GetInputString().empty());
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
   EXPECT_FALSE(location_bar->location_entry()->IsSelectAll());
 }
@@ -105,7 +106,7 @@
   AutocompleteController* autocomplete_controller = GetAutocompleteController();
 
   {
-    autocomplete_controller->Start(L"chrome", std::wstring(),
+    autocomplete_controller->Start(ASCIIToUTF16("chrome"), string16(),
                                    true, false, true, true);
 
     EXPECT_TRUE(autocomplete_controller->done());
@@ -123,7 +124,7 @@
     location_bar->Revert();
 
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+    EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
               location_bar->location_entry()->GetText());
     EXPECT_FALSE(location_bar->location_entry()->IsSelectAll());
     const AutocompleteResult& result = autocomplete_controller->result();
@@ -136,17 +137,17 @@
   // Make sure that tabbing away from an empty omnibar causes a revert
   // and select all.
   LocationBar* location_bar = GetLocationBar();
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
-  location_bar->location_entry()->SetUserText(L"");
+  location_bar->location_entry()->SetUserText(string16());
   browser()->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
                                    PageTransition::START_PAGE);
   ui_test_utils::WaitForNavigation(
       &browser()->GetSelectedTabContents()->controller());
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
   browser()->CloseTab();
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
             location_bar->location_entry()->GetText());
   EXPECT_TRUE(location_bar->location_entry()->IsSelectAll());
 }
@@ -157,12 +158,12 @@
   // Focus search when omnibox is blank
   {
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL),
+    EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL),
               location_bar->location_entry()->GetText());
 
     location_bar->FocusSearch();
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"?", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("?"), location_bar->location_entry()->GetText());
 
     size_t selection_start, selection_end;
     location_bar->location_entry()->GetSelectionBounds(&selection_start,
@@ -173,13 +174,13 @@
 
   // Focus search when omnibox is _not_ alread in forced query mode.
   {
-    location_bar->location_entry()->SetUserText(L"foo");
+    location_bar->location_entry()->SetUserText(ASCIIToUTF16("foo"));
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"foo", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("foo"), location_bar->location_entry()->GetText());
 
     location_bar->FocusSearch();
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"?", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("?"), location_bar->location_entry()->GetText());
 
     size_t selection_start, selection_end;
     location_bar->location_entry()->GetSelectionBounds(&selection_start,
@@ -191,13 +192,13 @@
   // Focus search when omnibox _is_ already in forced query mode, but no query
   // has been typed.
   {
-    location_bar->location_entry()->SetUserText(L"?");
+    location_bar->location_entry()->SetUserText(ASCIIToUTF16("?"));
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"?", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("?"), location_bar->location_entry()->GetText());
 
     location_bar->FocusSearch();
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"?", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("?"), location_bar->location_entry()->GetText());
 
     size_t selection_start, selection_end;
     location_bar->location_entry()->GetSelectionBounds(&selection_start,
@@ -209,13 +210,13 @@
   // Focus search when omnibox _is_ already in forced query mode, and some query
   // has been typed.
   {
-    location_bar->location_entry()->SetUserText(L"?foo");
+    location_bar->location_entry()->SetUserText(ASCIIToUTF16("?foo"));
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"?foo", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("?foo"), location_bar->location_entry()->GetText());
 
     location_bar->FocusSearch();
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"?foo", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("?foo"), location_bar->location_entry()->GetText());
 
     size_t selection_start, selection_end;
     location_bar->location_entry()->GetSelectionBounds(&selection_start,
@@ -226,13 +227,15 @@
 
   // Focus search when omnibox is in forced query mode with leading whitespace.
   {
-    location_bar->location_entry()->SetUserText(L"   ?foo");
+    location_bar->location_entry()->SetUserText(ASCIIToUTF16("   ?foo"));
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"   ?foo", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("   ?foo"),
+              location_bar->location_entry()->GetText());
 
     location_bar->FocusSearch();
     EXPECT_TRUE(location_bar->GetInputString().empty());
-    EXPECT_EQ(L"   ?foo", location_bar->location_entry()->GetText());
+    EXPECT_EQ(ASCIIToUTF16("   ?foo"),
+              location_bar->location_entry()->GetText());
 
     size_t selection_start, selection_end;
     location_bar->location_entry()->GetSelectionBounds(&selection_start,
diff --git a/chrome/browser/autocomplete/autocomplete_classifier.cc b/chrome/browser/autocomplete/autocomplete_classifier.cc
index 45635e3..45deb87 100644
--- a/chrome/browser/autocomplete/autocomplete_classifier.cc
+++ b/chrome/browser/autocomplete/autocomplete_classifier.cc
@@ -15,8 +15,8 @@
 AutocompleteClassifier::~AutocompleteClassifier() {
 }
 
-void AutocompleteClassifier::Classify(const std::wstring& text,
-                                      const std::wstring& desired_tld,
+void AutocompleteClassifier::Classify(const string16& text,
+                                      const string16& desired_tld,
                                       bool allow_exact_keyword_match,
                                       AutocompleteMatch* match,
                                       GURL* alternate_nav_url) {
diff --git a/chrome/browser/autocomplete/autocomplete_classifier.h b/chrome/browser/autocomplete/autocomplete_classifier.h
index ed59306..1d8b473 100644
--- a/chrome/browser/autocomplete/autocomplete_classifier.h
+++ b/chrome/browser/autocomplete/autocomplete_classifier.h
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
+#include "base/string16.h"
 
 class AutocompleteController;
 struct AutocompleteMatch;
@@ -33,8 +34,8 @@
   // non-NULL, will be set to the navigational URL (if any) in case of an
   // accidental search; see comments on
   // AutocompleteResult::alternate_nav_url_ in autocomplete.h.
-  void Classify(const std::wstring& text,
-                const std::wstring& desired_tld,
+  void Classify(const string16& text,
+                const string16& desired_tld,
                 bool allow_exact_keyword_match,
                 AutocompleteMatch* match,
                 GURL* alternate_nav_url);
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc
index f08a2e4..5f3aeef 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
+#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
 #include "chrome/browser/autocomplete/keyword_provider.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/command_updater.h"
@@ -43,15 +44,13 @@
 // AutocompleteEditModel::State
 
 AutocompleteEditModel::State::State(bool user_input_in_progress,
-                                    const std::wstring& user_text,
-                                    const std::wstring& keyword,
-                                    bool is_keyword_hint,
-                                    KeywordUIState keyword_ui_state)
+                                    const string16& user_text,
+                                    const string16& keyword,
+                                    bool is_keyword_hint)
     : user_input_in_progress(user_input_in_progress),
       user_text(user_text),
       keyword(keyword),
-      is_keyword_hint(is_keyword_hint),
-      keyword_ui_state(keyword_ui_state) {
+      is_keyword_hint(is_keyword_hint) {
 }
 
 AutocompleteEditModel::State::~State() {
@@ -71,11 +70,9 @@
       user_input_in_progress_(false),
       just_deleted_text_(false),
       has_temporary_text_(false),
-      original_keyword_ui_state_(NORMAL),
       paste_state_(NONE),
       control_key_state_(UP),
       is_keyword_hint_(false),
-      keyword_ui_state_(NORMAL),
       paste_and_go_transition_(PageTransition::TYPED),
       profile_(profile) {
 }
@@ -86,7 +83,7 @@
 void AutocompleteEditModel::SetPopupModel(AutocompletePopupModel* popup_model) {
   popup_ = popup_model;
   registrar_.Add(this,
-      NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED,
+      NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
       Source<AutocompleteController>(popup_->autocomplete_controller()));
 }
 
@@ -105,7 +102,7 @@
     // Weird edge case to match other browsers: if the edit is empty, revert to
     // the permanent text (so the user can get it back easily) but select it (so
     // on switching back, typing will "just work").
-    const std::wstring user_text(UserTextFromDisplayText(view_->GetText()));
+    const string16 user_text(UserTextFromDisplayText(view_->GetText()));
     if (user_text.empty()) {
       view_->RevertAll();
       view_->SelectAll(true);
@@ -114,8 +111,7 @@
     }
   }
 
-  return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_,
-               keyword_ui_state_);
+  return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_);
 }
 
 void AutocompleteEditModel::RestoreState(const State& state) {
@@ -125,7 +121,6 @@
     // DisplayTextFromUserText(), as its result depends upon this state.
     keyword_ = state.keyword;
     is_keyword_hint_ = state.is_keyword_hint;
-    keyword_ui_state_ = state.keyword_ui_state;
     view_->SetUserText(state.user_text,
         DisplayTextFromUserText(state.user_text), false);
   }
@@ -138,7 +133,7 @@
 }
 
 bool AutocompleteEditModel::UpdatePermanentText(
-    const std::wstring& new_permanent_text) {
+    const string16& new_permanent_text) {
   // When there's a new URL, and the user is not editing anything or the edit
   // doesn't have focus, we want to revert the edit to show the new URL.  (The
   // common case where the edit doesn't have focus is when the user has started
@@ -151,7 +146,7 @@
   return visibly_changed_permanent_text;
 }
 
-void AutocompleteEditModel::SetUserText(const std::wstring& text) {
+void AutocompleteEditModel::SetUserText(const string16& text) {
   SetInputInProgress(true);
   InternalSetUserText(text);
   paste_state_ = NONE;
@@ -159,18 +154,26 @@
 }
 
 void AutocompleteEditModel::FinalizeInstantQuery(
-    const std::wstring& input_text,
-    const std::wstring& suggest_text) {
-  popup_->FinalizeInstantQuery(input_text, suggest_text);
+    const string16& input_text,
+    const string16& suggest_text,
+    bool skip_inline_autocomplete) {
+  if (skip_inline_autocomplete) {
+    const string16 final_text = input_text + suggest_text;
+    view_->OnBeforePossibleChange();
+    view_->SetWindowTextAndCaretPos(final_text, final_text.length());
+    view_->OnAfterPossibleChange();
+  } else {
+    popup_->FinalizeInstantQuery(input_text, suggest_text);
+  }
 }
 
 void AutocompleteEditModel::GetDataForURLExport(GURL* url,
-                                                std::wstring* title,
+                                                string16* title,
                                                 SkBitmap* favicon) {
   AutocompleteMatch match;
   GetInfoForCurrentText(&match, NULL);
   *url = match.destination_url;
-  if (*url == URLFixerUpper::FixupURL(WideToUTF8(permanent_text_),
+  if (*url == URLFixerUpper::FixupURL(UTF16ToUTF8(permanent_text_),
                                       std::string())) {
     *title = controller_->GetTitle();
     *favicon = controller_->GetFavIcon();
@@ -197,12 +200,12 @@
       just_deleted_text_)
     return true;
 
-  std::wstring::size_type start, end;
+  string16::size_type start, end;
   view_->GetSelectionBounds(&start, &end);
   return (start != end) || (start != view_->GetText().size());
 }
 
-std::wstring AutocompleteEditModel::GetDesiredTLD() const {
+string16 AutocompleteEditModel::GetDesiredTLD() const {
   // Tricky corner case: The user has typed "foo" and currently sees an inline
   // autocomplete suggestion of "foo.net".  He now presses ctrl-a (e.g. to
   // select all, on Windows).  If we treat the ctrl press as potentially for the
@@ -217,7 +220,7 @@
   // * the user is not typing a keyword query.
   return (control_key_state_ == DOWN_WITHOUT_CHANGE &&
           inline_autocomplete_text_.empty() && !KeywordIsSelected())?
-    std::wstring(L"com") : std::wstring();
+    ASCIIToUTF16("com") : string16();
 }
 
 bool AutocompleteEditModel::CurrentTextIsURL() const {
@@ -241,7 +244,7 @@
 
 void AutocompleteEditModel::AdjustTextForCopy(int sel_min,
                                               bool is_all_selected,
-                                              std::wstring* text,
+                                              string16* text,
                                               GURL* url,
                                               bool* write_url) {
   *write_url = false;
@@ -259,7 +262,7 @@
     // The user selected all the text and has not edited it. Use the url as the
     // text so that if the scheme was stripped it's added back, and the url
     // is unescaped (we escape parts of the url for display).
-    *text = UTF8ToWide(url->spec());
+    *text = UTF8ToUTF16(url->spec());
     *write_url = true;
     return;
   }
@@ -275,8 +278,8 @@
       perm_url.host() == url->host()) {
     *write_url = true;
 
-    std::wstring http = ASCIIToWide(chrome::kHttpScheme) +
-        ASCIIToWide(chrome::kStandardSchemeSeparator);
+    string16 http = ASCIIToUTF16(chrome::kHttpScheme) +
+        ASCIIToUTF16(chrome::kStandardSchemeSeparator);
     if (text->compare(0, http.length(), http) != 0)
       *text = http + *text;
   }
@@ -293,10 +296,9 @@
 void AutocompleteEditModel::Revert() {
   SetInputInProgress(false);
   paste_state_ = NONE;
-  InternalSetUserText(std::wstring());
+  InternalSetUserText(string16());
   keyword_.clear();
   is_keyword_hint_ = false;
-  keyword_ui_state_ = NORMAL;
   has_temporary_text_ = false;
   view_->SetWindowTextAndCaretPos(permanent_text_,
                                   has_focus_ ? permanent_text_.length() : 0);
@@ -305,18 +307,19 @@
 void AutocompleteEditModel::StartAutocomplete(
     bool has_selected_text,
     bool prevent_inline_autocomplete) const {
+  bool keyword_is_selected = KeywordIsSelected();
   popup_->StartAutocomplete(user_text_, GetDesiredTLD(),
       prevent_inline_autocomplete || just_deleted_text_ ||
       (has_selected_text && inline_autocomplete_text_.empty()) ||
-      (paste_state_ != NONE), keyword_ui_state_ == KEYWORD);
+      (paste_state_ != NONE), keyword_is_selected, keyword_is_selected);
 }
 
-bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const {
+bool AutocompleteEditModel::CanPasteAndGo(const string16& text) const {
   if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL))
     return false;
 
   AutocompleteMatch match;
-  profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), false,
+  profile_->GetAutocompleteClassifier()->Classify(text, string16(), false,
       &match, &paste_and_go_alternate_nav_url_);
   paste_and_go_url_ = match.destination_url;
   paste_and_go_transition_ = match.transition;
@@ -330,7 +333,7 @@
   view_->RevertAll();
   view_->OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_,
       paste_and_go_alternate_nav_url_, AutocompletePopupModel::kNoMatch,
-      std::wstring());
+      string16());
 }
 
 void AutocompleteEditModel::AcceptInput(WindowOpenDisposition disposition,
@@ -344,7 +347,7 @@
     return;
 
   if ((match.transition == PageTransition::TYPED) && (match.destination_url ==
-      URLFixerUpper::FixupURL(WideToUTF8(permanent_text_), std::string()))) {
+      URLFixerUpper::FixupURL(UTF16ToUTF8(permanent_text_), std::string()))) {
     // When the user hit enter on the existing permanent URL, treat it like a
     // reload for scoring purposes.  We could detect this by just checking
     // user_input_in_progress_, but it seems better to treat "edits" that end
@@ -369,12 +372,18 @@
     const TemplateURL* default_provider =
         profile_->GetTemplateURLModel()->GetDefaultSearchProvider();
     if (default_provider && default_provider->url() &&
-        default_provider->url()->HasGoogleBaseURLs())
+        default_provider->url()->HasGoogleBaseURLs()) {
       GoogleURLTracker::GoogleURLSearchCommitted();
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+      // TODO(pastarmovj): Remove these metrics once we have proven that (close
+      // to) none searches that should have RLZ are sent out without one.
+      default_provider->url()->CollectRLZMetrics();
+#endif
+    }
   }
   view_->OpenURL(match.destination_url, disposition, match.transition,
                  alternate_nav_url, AutocompletePopupModel::kNoMatch,
-                 is_keyword_hint_ ? std::wstring() : keyword_);
+                 is_keyword_hint_ ? string16() : keyword_);
 }
 
 void AutocompleteEditModel::OpenURL(const GURL& url,
@@ -382,7 +391,7 @@
                                     PageTransition::Type transition,
                                     const GURL& alternate_nav_url,
                                     size_t index,
-                                    const std::wstring& keyword) {
+                                    const string16& keyword) {
   // We only care about cases where there is a selection (i.e. the popup is
   // open).
   if (popup_->IsOpen()) {
@@ -415,7 +424,7 @@
       size_t prefix_length = match.template_url->keyword().size() + 1;
       ExtensionOmniboxEventRouter::OnInputEntered(
           profile_, match.template_url->GetExtensionId(),
-          WideToUTF8(match.fill_into_edit.substr(prefix_length)));
+          UTF16ToUTF8(match.fill_into_edit.substr(prefix_length)));
       view_->RevertAll();
       return;
     }
@@ -437,25 +446,27 @@
                                     alternate_nav_url);
 }
 
-void AutocompleteEditModel::AcceptKeyword() {
+bool AutocompleteEditModel::AcceptKeyword() {
+  DCHECK(is_keyword_hint_ && !keyword_.empty());
+
   view_->OnBeforePossibleChange();
-  view_->SetWindowTextAndCaretPos(std::wstring(), 0);
+  view_->SetWindowTextAndCaretPos(string16(), 0);
   is_keyword_hint_ = false;
-  keyword_ui_state_ = KEYWORD;
   view_->OnAfterPossibleChange();
   just_deleted_text_ = false;  // OnAfterPossibleChange() erroneously sets this
                                // since the edit contents have disappeared.  It
                                // doesn't really matter, but we clear it to be
                                // consistent.
   UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_);
+  return true;
 }
 
-void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) {
+void AutocompleteEditModel::ClearKeyword(const string16& visible_text) {
   view_->OnBeforePossibleChange();
-  const std::wstring window_text(keyword_ + visible_text);
+  const string16 window_text(keyword_ + visible_text);
   view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length());
   keyword_.clear();
-  keyword_ui_state_ = NORMAL;
+  is_keyword_hint_ = false;
   view_->OnAfterPossibleChange();
   just_deleted_text_ = true;  // OnAfterPossibleChange() fails to clear this
                               // since the edit contents have actually grown
@@ -483,12 +494,6 @@
   has_focus_ = false;
   control_key_state_ = UP;
   paste_state_ = NONE;
-
-  // Like typing, killing focus "accepts" the temporary text as the user
-  // text, because it makes little sense to have temporary text when the
-  // popup is closed.
-  InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
-  has_temporary_text_ = false;
 }
 
 bool AutocompleteEditModel::OnEscapeKeyPressed() {
@@ -496,14 +501,7 @@
     AutocompleteMatch match;
     popup_->InfoForCurrentSelection(&match, NULL);
     if (match.destination_url != original_url_) {
-      // The user typed something, then selected a different item.  Restore the
-      // text they typed and change back to the default item.
-      // NOTE: This purposefully does not reset paste_state_.
-      just_deleted_text_ = false;
-      has_temporary_text_ = false;
-      keyword_ui_state_ = original_keyword_ui_state_;
-      popup_->ResetToDefaultMatch();
-      view_->OnRevertTemporaryText();
+      RevertTemporaryText(true);
       return true;
     }
   }
@@ -568,17 +566,12 @@
     // normally.
     popup_->Move(count);
   }
-
-  // NOTE: We need to reset the keyword_ui_state_ after the popup updates, since
-  // Move() will eventually call back to OnPopupDataChanged(), which needs to
-  // save off the current keyword_ui_state_.
-  keyword_ui_state_ = NORMAL;
 }
 
 void AutocompleteEditModel::OnPopupDataChanged(
-    const std::wstring& text,
+    const string16& text,
     GURL* destination_for_temporary_text_change,
-    const std::wstring& keyword,
+    const string16& keyword,
     bool is_keyword_hint) {
   // Update keyword/hint-related local state.
   bool keyword_state_changed = (keyword_ != keyword) ||
@@ -586,6 +579,9 @@
   if (keyword_state_changed) {
     keyword_ = keyword;
     is_keyword_hint_ = is_keyword_hint;
+
+    // |is_keyword_hint_| should always be false if |keyword_| is empty.
+    DCHECK(!keyword_.empty() || !is_keyword_hint_);
   }
 
   // Handle changes to temporary text.
@@ -595,7 +591,7 @@
       // Save the original selection and URL so it can be reverted later.
       has_temporary_text_ = true;
       original_url_ = *destination_for_temporary_text_change;
-      original_keyword_ui_state_ = keyword_ui_state_;
+      inline_autocomplete_text_.clear();
     }
     if (control_key_state_ == DOWN_WITHOUT_CHANGE) {
       // Arrowing around the popup cancels control-enter.
@@ -612,40 +608,40 @@
     return;
   }
 
-  // TODO(suzhe): Instead of messing with |inline_autocomplete_text_| here,
-  // we should probably do it inside Observe(), and save/restore it around
-  // changes to the temporary text.  This will let us remove knowledge of
-  // inline autocompletions from the popup code.
-  //
-  // Handle changes to inline autocomplete text.  Don't make changes if the user
-  // is showing temporary text.  Making display changes would be obviously
-  // wrong; making changes to the inline_autocomplete_text_ itself turns out to
-  // be more subtlely wrong, because it means hitting esc will no longer revert
-  // to the original state before arrowing.
-  if (!has_temporary_text_) {
-    inline_autocomplete_text_ = text;
-    if (view_->OnInlineAutocompleteTextMaybeChanged(
-        DisplayTextFromUserText(user_text_ + inline_autocomplete_text_),
-        DisplayTextFromUserText(user_text_).length()))
-      return;
+  bool call_controller_onchanged = true;
+  inline_autocomplete_text_ = text;
+  if (view_->OnInlineAutocompleteTextMaybeChanged(
+      DisplayTextFromUserText(user_text_ + inline_autocomplete_text_),
+      DisplayTextFromUserText(user_text_).length()))
+    call_controller_onchanged = false;
+
+  // If |has_temporary_text_| is true, then we previously had a manual selection
+  // but now don't (or |destination_for_temporary_text_change| would have been
+  // non-NULL). This can happen when deleting the selected item in the popup.
+  // In this case, we've already reverted the popup to the default match, so we
+  // need to revert ourselves as well.
+  if (has_temporary_text_) {
+    RevertTemporaryText(false);
+    call_controller_onchanged = false;
   }
 
-  // All other code paths that return invoke OnChanged. We need to invoke
-  // OnChanged in case the destination url changed (as could happen when control
-  // is toggled).
-  controller_->OnChanged();
+  // We need to invoke OnChanged in case the destination url changed (as could
+  // happen when control is toggled).
+  if (call_controller_onchanged)
+    controller_->OnChanged();
 }
 
-bool AutocompleteEditModel::OnAfterPossibleChange(const std::wstring& new_text,
-                                                  bool selection_differs,
-                                                  bool text_differs,
-                                                  bool just_deleted_text,
-                                                  bool at_end_of_edit) {
+bool AutocompleteEditModel::OnAfterPossibleChange(
+    const string16& new_text,
+    bool selection_differs,
+    bool text_differs,
+    bool just_deleted_text,
+    bool allow_keyword_ui_change) {
   // Update the paste state as appropriate: if we're just finishing a paste
   // that replaced all the text, preserve that information; otherwise, if we've
   // made some other edit, clear paste tracking.
-  if (paste_state_ == REPLACING_ALL)
-    paste_state_ = REPLACED_ALL;
+  if (paste_state_ == PASTING)
+    paste_state_ = PASTED;
   else if (text_differs)
     paste_state_ = NONE;
 
@@ -665,8 +661,7 @@
     return false;
   }
 
-  const bool had_keyword = KeywordIsSelected();
-
+  const string16 old_user_text = user_text_;
   // If the user text has not changed, we do not want to change the model's
   // state associated with the text.  Otherwise, we can get surprising behavior
   // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983
@@ -679,36 +674,19 @@
     just_deleted_text_ = just_deleted_text;
   }
 
-  // Disable the fancy keyword UI if the user didn't already have a visible
-  // keyword and is not at the end of the edit.  This prevents us from showing
-  // the fancy UI (and interrupting the user's editing) if the user happens to
-  // have a keyword for 'a', types 'ab' then puts a space between the 'a' and
-  // the 'b'.
-  if (!had_keyword)
-    keyword_ui_state_ = at_end_of_edit ? NORMAL : NO_KEYWORD;
-
   view_->UpdatePopup();
 
-  if (had_keyword) {
-    if (is_keyword_hint_ || keyword_.empty())
-      keyword_ui_state_ = NORMAL;
-  } else if ((keyword_ui_state_ != NO_KEYWORD) && !is_keyword_hint_ &&
-             !keyword_.empty()) {
-    // Went from no selected keyword to a selected keyword.
-    keyword_ui_state_ = KEYWORD;
-  }
-
-  return true;
+  // Change to keyword mode if the user has typed a keyword name and is now
+  // pressing space after the name. Accepting the keyword will update our
+  // state, so in that case there's no need to also return true here.
+  return !(text_differs && allow_keyword_ui_change && !just_deleted_text &&
+           MaybeAcceptKeywordBySpace(old_user_text, user_text_));
 }
 
 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) {
   controller_->OnPopupBoundsChanged(bounds);
 }
 
-void AutocompleteEditModel::ResultsUpdated() {
-  UpdateSuggestedSearchText();
-}
-
 // Return true if the suggestion type warrants a TCP/IP preconnection.
 // i.e., it is now highly likely that the user will select the related domain.
 static bool IsPreconnectable(AutocompleteMatch::Type type) {
@@ -731,58 +709,74 @@
 void AutocompleteEditModel::Observe(NotificationType type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
-  DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED,
+  DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
             type.value);
 
-  std::wstring inline_autocomplete_text;
-  std::wstring keyword;
-  bool is_keyword_hint = false;
-  const AutocompleteResult* result =
-      Details<const AutocompleteResult>(details).ptr();
-  const AutocompleteResult::const_iterator match(result->default_match());
-  if (match != result->end()) {
-    if ((match->inline_autocomplete_offset != std::wstring::npos) &&
-        (match->inline_autocomplete_offset < match->fill_into_edit.length())) {
-      inline_autocomplete_text =
-          match->fill_into_edit.substr(match->inline_autocomplete_offset);
+  const bool was_open = popup_->view()->IsOpen();
+  if (*(Details<bool>(details).ptr())) {
+    string16 inline_autocomplete_text;
+    string16 keyword;
+    bool is_keyword_hint = false;
+    const AutocompleteResult& result =
+        popup_->autocomplete_controller()->result();
+    const AutocompleteResult::const_iterator match(result.default_match());
+    if (match != result.end()) {
+      if ((match->inline_autocomplete_offset != string16::npos) &&
+          (match->inline_autocomplete_offset <
+           match->fill_into_edit.length())) {
+        inline_autocomplete_text =
+            match->fill_into_edit.substr(match->inline_autocomplete_offset);
+      }
+
+      if (!match->destination_url.SchemeIs(chrome::kExtensionScheme)) {
+        // Warm up DNS Prefetch cache, or preconnect to a search service.
+        chrome_browser_net::AnticipateOmniboxUrl(match->destination_url,
+                                                 IsPreconnectable(match->type));
+      }
+
+      // We could prefetch the alternate nav URL, if any, but because there
+      // can be many of these as a user types an initial series of characters,
+      // the OS DNS cache could suffer eviction problems for minimal gain.
+
+      is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword);
     }
-
-    if (!match->destination_url.SchemeIs(chrome::kExtensionScheme)) {
-      // Warm up DNS Prefetch cache, or preconnect to a search service.
-      chrome_browser_net::AnticipateOmniboxUrl(match->destination_url,
-                                               IsPreconnectable(match->type));
-    }
-
-    // We could prefetch the alternate nav URL, if any, but because there
-    // can be many of these as a user types an initial series of characters,
-    // the OS DNS cache could suffer eviction problems for minimal gain.
-
-    is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword);
+    popup_->OnResultChanged();
+    OnPopupDataChanged(inline_autocomplete_text, NULL, keyword,
+                       is_keyword_hint);
+  } else {
+    popup_->OnResultChanged();
   }
 
-  OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint);
+  if (popup_->view()->IsOpen()) {
+    PopupBoundsChangedTo(popup_->view()->GetTargetBounds());
+  } else if (was_open) {
+    // Accepts the temporary text as the user text, because it makes little
+    // sense to have temporary text when the popup is closed.
+    InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
+    has_temporary_text_ = false;
+    PopupBoundsChangedTo(gfx::Rect());
+  }
 }
 
-void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) {
+void AutocompleteEditModel::InternalSetUserText(const string16& text) {
   user_text_ = text;
   just_deleted_text_ = false;
   inline_autocomplete_text_.clear();
 }
 
 bool AutocompleteEditModel::KeywordIsSelected() const {
-  return ((keyword_ui_state_ != NO_KEYWORD) && !is_keyword_hint_ &&
-          !keyword_.empty());
+  return !is_keyword_hint_ && !keyword_.empty();
 }
 
-std::wstring AutocompleteEditModel::DisplayTextFromUserText(
-    const std::wstring& text) const {
+string16 AutocompleteEditModel::DisplayTextFromUserText(
+    const string16& text) const {
   return KeywordIsSelected() ?
-      KeywordProvider::SplitReplacementStringFromInput(text) : text;
+      KeywordProvider::SplitReplacementStringFromInput(text, false) : text;
 }
 
-std::wstring AutocompleteEditModel::UserTextFromDisplayText(
-    const std::wstring& text) const {
-  return KeywordIsSelected() ? (keyword_ + L" " + text) : text;
+string16 AutocompleteEditModel::UserTextFromDisplayText(
+    const string16& text) const {
+  return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text;
 }
 
 void AutocompleteEditModel::GetInfoForCurrentText(
@@ -797,11 +791,11 @@
   }
 }
 
-bool AutocompleteEditModel::GetURLForText(const std::wstring& text,
+bool AutocompleteEditModel::GetURLForText(const string16& text,
                                           GURL* url) const {
   GURL parsed_url;
   const AutocompleteInput::Type type = AutocompleteInput::Parse(
-      UserTextFromDisplayText(text), std::wstring(), NULL, NULL, &parsed_url);
+      UserTextFromDisplayText(text), string16(), NULL, NULL, &parsed_url);
   if (type != AutocompleteInput::URL)
     return false;
 
@@ -809,37 +803,37 @@
   return true;
 }
 
-// Returns true if suggested search text should be shown for the specified match
-// type.
-static bool ShouldShowSuggestSearchTextFor(AutocompleteMatch::Type type) {
-  // TODO: add support for other engines when in keyword mode.
-  return ((type == AutocompleteMatch::SEARCH_HISTORY) ||
-          (type == AutocompleteMatch::SEARCH_SUGGEST));
+void AutocompleteEditModel::RevertTemporaryText(bool revert_popup) {
+  // The user typed something, then selected a different item.  Restore the
+  // text they typed and change back to the default item.
+  // NOTE: This purposefully does not reset paste_state_.
+  just_deleted_text_ = false;
+  has_temporary_text_ = false;
+  if (revert_popup)
+    popup_->ResetToDefaultMatch();
+  view_->OnRevertTemporaryText();
 }
 
-void AutocompleteEditModel::UpdateSuggestedSearchText() {
-  if (!InstantController::IsEnabled(profile_, InstantController::VERBATIM_TYPE))
-    return;
+bool AutocompleteEditModel::MaybeAcceptKeywordBySpace(
+    const string16& old_user_text,
+    const string16& new_user_text) {
+  return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() &&
+      inline_autocomplete_text_.empty() && new_user_text.length() >= 2 &&
+      IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) &&
+      !IsWhitespace(*(new_user_text.rbegin() + 1)) &&
+      (old_user_text.length() + 1 >= new_user_text.length()) &&
+      !new_user_text.compare(0, new_user_text.length() - 1, old_user_text,
+                             0, new_user_text.length() - 1) &&
+      AcceptKeyword();
+}
 
-  string16 suggested_text;
-  // The suggested text comes from the first search result.
-  if (popup_->IsOpen()) {
-    const AutocompleteResult& result = popup_->result();
-    if ((result.size() > 1) && (popup_->selected_line() == 0) &&
-        ((result.begin()->inline_autocomplete_offset == std::wstring::npos) ||
-         (result.begin()->inline_autocomplete_offset ==
-          result.begin()->fill_into_edit.size()))) {
-      for (AutocompleteResult::const_iterator i = result.begin() + 1;
-           i != result.end(); ++i) {
-        // TODO: add support for other engines when in keyword mode.
-        if (ShouldShowSuggestSearchTextFor(i->type) &&
-            i->inline_autocomplete_offset != std::wstring::npos) {
-          suggested_text = WideToUTF16(i->fill_into_edit.substr(
-                                           i->inline_autocomplete_offset));
-          break;
-        }
-      }
-    }
+//  static
+bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) {
+  switch (c) {
+    case 0x0020:  // Space
+    case 0x3000:  // Ideographic Space
+      return true;
+    default:
+      return false;
   }
-  controller_->OnSetSuggestedSearchText(suggested_text);
 }
diff --git a/chrome/browser/autocomplete/autocomplete_edit.h b/chrome/browser/autocomplete/autocomplete_edit.h
index 1a8da22..8a94be4 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.h
+++ b/chrome/browser/autocomplete/autocomplete_edit.h
@@ -11,8 +11,8 @@
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class AutocompletePopupModel;
@@ -48,17 +48,16 @@
   // OnAutoCompleteAccept.
   virtual void OnAutocompleteWillAccept() = 0;
 
-  // Commits the suggested text. |typed_text| is the current text showing in the
-  // autocomplete. Returns true if the text was committed.
-  virtual bool OnCommitSuggestedText(const std::wstring& typed_text) = 0;
+  // Commits the suggested text. If |skip_inline_autocomplete| is true then the
+  // suggested text will be committed as final text as if it's inputted by the
+  // user, rather than as inline autocomplete suggest.
+  // Returns true if the text was committed.
+  virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete) = 0;
 
   // Accepts the currently showing instant preview, if any, and returns true.
   // Returns false if there is no instant preview showing.
   virtual bool AcceptCurrentInstantPreview() = 0;
 
-  // Sets the suggested search text to |suggested_text|.
-  virtual void OnSetSuggestedSearchText(const string16& suggested_text) = 0;
-
   // Invoked when the popup is going to change its bounds to |bounds|.
   virtual void OnPopupBoundsChanged(const gfx::Rect& bounds) = 0;
 
@@ -97,7 +96,7 @@
   virtual SkBitmap GetFavIcon() const = 0;
 
   // Returns the title of the current page.
-  virtual std::wstring GetTitle() const = 0;
+  virtual string16 GetTitle() const = 0;
 
  protected:
   virtual ~AutocompleteEditController();
@@ -105,32 +104,17 @@
 
 class AutocompleteEditModel : public NotificationObserver {
  public:
-  enum KeywordUIState {
-    // The user is typing normally.
-    NORMAL,
-    // The user is editing in the middle of the input string.  Even if the
-    // input looks like a keyword, don't display the keyword UI, as to not
-    // interfere with the user's editing.
-    NO_KEYWORD,
-    // The user has triggered the keyword UI.  Until it disappears, bias
-    // autocomplete results so that input strings of the keyword alone default
-    // to the keyword provider, not a normal navigation or search.
-    KEYWORD,
-  };
-
   struct State {
     State(bool user_input_in_progress,
-          const std::wstring& user_text,
-          const std::wstring& keyword,
-          bool is_keyword_hint,
-          KeywordUIState keyword_ui_state);
+          const string16& user_text,
+          const string16& keyword,
+          bool is_keyword_hint);
     ~State();
 
     bool user_input_in_progress;
-    const std::wstring user_text;
-    const std::wstring keyword;
+    const string16 user_text;
+    const string16 keyword;
     const bool is_keyword_hint;
-    const KeywordUIState keyword_ui_state;
   };
 
   AutocompleteEditModel(AutocompleteEditView* view,
@@ -162,7 +146,7 @@
 
   // Called when the user wants to export the entire current text as a URL.
   // Sets the url, and if known, the title and favicon.
-  void GetDataForURLExport(GURL* url, std::wstring* title, SkBitmap* favicon);
+  void GetDataForURLExport(GURL* url, string16* title, SkBitmap* favicon);
 
   // Returns true if a verbatim query should be used for instant. A verbatim
   // query is forced in certain situations, such as pressing delete at the end
@@ -173,7 +157,7 @@
   // desired TLD is the TLD the user desires to add to the end of the current
   // input, if any, based on their control key state and any other actions
   // they've taken.
-  std::wstring GetDesiredTLD() const;
+  string16 GetDesiredTLD() const;
 
   // Returns true if the current edit contents will be treated as a
   // URL/navigation, as opposed to a search.
@@ -190,7 +174,7 @@
   // is set to true and |url| set to the url to write.
   void AdjustTextForCopy(int sel_min,
                          bool is_all_selected,
-                         std::wstring* text,
+                         string16* text,
                          GURL* url,
                          bool* write_url);
 
@@ -203,14 +187,17 @@
   // Updates permanent_text_ to |new_permanent_text|.  Returns true if this
   // change should be immediately user-visible, because either the user is not
   // editing or the edit does not have focus.
-  bool UpdatePermanentText(const std::wstring& new_permanent_text);
+  bool UpdatePermanentText(const string16& new_permanent_text);
 
   // Sets the user_text_ to |text|.  Only the View should call this.
-  void SetUserText(const std::wstring& text);
+  void SetUserText(const string16& text);
 
   // Calls through to SearchProvider::FinalizeInstantQuery.
-  void FinalizeInstantQuery(const std::wstring& input_text,
-                            const std::wstring& suggest_text);
+  // If |skip_inline_autocomplete| is true then the |suggest_text| will be
+  // turned into final text instead of inline autocomplete suggest.
+  void FinalizeInstantQuery(const string16& input_text,
+                            const string16& suggest_text,
+                            bool skip_inline_autocomplete);
 
   // Reverts the edit model back to its unedited state (permanent text showing,
   // no user input in progress).
@@ -224,7 +211,7 @@
   // This also updates the internal paste-and-go-related state variables as
   // appropriate so that the controller doesn't need to be repeatedly queried
   // for the same text in every clipboard-related function.
-  bool CanPasteAndGo(const std::wstring& text) const;
+  bool CanPasteAndGo(const string16& text) const;
 
   // Navigates to the destination last supplied to CanPasteAndGo.
   void PasteAndGo();
@@ -252,24 +239,22 @@
                PageTransition::Type transition,
                const GURL& alternate_nav_url,
                size_t index,
-               const std::wstring& keyword);
+               const string16& keyword);
 
   bool has_focus() const { return has_focus_; }
 
   // Accessors for keyword-related state (see comments on keyword_ and
   // is_keyword_hint_).
-  std::wstring keyword() const {
-    return (is_keyword_hint_ || (keyword_ui_state_ != NO_KEYWORD)) ?
-        keyword_ : std::wstring();
-  }
+  const string16& keyword() const { return keyword_; }
   bool is_keyword_hint() const { return is_keyword_hint_; }
 
-  // Accepts the current keyword hint as a keyword.
-  void AcceptKeyword();
+  // Accepts the current keyword hint as a keyword. It always returns true for
+  // caller convenience.
+  bool AcceptKeyword();
 
   // Clears the current keyword.  |visible_text| is the (non-keyword) text
   // currently visible in the edit.
-  void ClearKeyword(const std::wstring& visible_text);
+  void ClearKeyword(const string16& visible_text);
 
   // Returns true if a query to an autocomplete provider is currently
   // in progress.  This logic should in the future live in
@@ -297,8 +282,8 @@
   // necessary.
   void OnControlKeyChanged(bool pressed);
 
-  // Called when the user pastes in text that replaces the entire edit contents.
-  void on_paste_replacing_all() { paste_state_ = REPLACING_ALL; }
+  // Called when the user pastes in text.
+  void on_paste() { paste_state_ = PASTING; }
 
   // Called when the user presses up or down.  |count| is a repeat count,
   // negative for moving up, positive for moving down.
@@ -317,37 +302,38 @@
   //     or the currently selected keyword if |is_keyword_hint| is false (see
   //     comments on keyword_ and is_keyword_hint_).
   void OnPopupDataChanged(
-      const std::wstring& text,
+      const string16& text,
       GURL* destination_for_temporary_text_change,
-      const std::wstring& keyword,
+      const string16& keyword,
       bool is_keyword_hint);
 
   // Called by the AutocompleteEditView after something changes, with details
   // about what state changes occured.  Updates internal state, updates the
   // popup if necessary, and returns true if any significant changes occurred.
-  bool OnAfterPossibleChange(const std::wstring& new_text,
+  // If |allow_keyword_ui_change| is false then the change should not affect
+  // keyword ui state, even if the text matches a keyword exactly. This value
+  // may be false when:
+  // 1) The insert caret is not at the end of the edit box
+  // 2) The user is composing a text with an IME
+  bool OnAfterPossibleChange(const string16& new_text,
                              bool selection_differs,
                              bool text_differs,
                              bool just_deleted_text,
-                             bool at_end_of_edit);
+                             bool allow_keyword_ui_change);
 
   // Invoked when the popup is going to change its bounds to |bounds|.
   void PopupBoundsChangedTo(const gfx::Rect& bounds);
 
-  // Invoked when the autocomplete results may have changed in some way.
-  void ResultsUpdated();
-
  private:
   enum PasteState {
-    NONE,           // Most recent edit was not a paste that replaced all text.
-    REPLACED_ALL,   // Most recent edit was a paste that replaced all text.
-    REPLACING_ALL,  // In the middle of doing a paste that replaces all
-                    // text.  We need this intermediate state because OnPaste()
-                    // does the actual detection of such pastes, but
-                    // OnAfterPossibleChange() has to update the paste state
-                    // for every edit.  If OnPaste() set the state directly to
-                    // REPLACED_ALL, OnAfterPossibleChange() wouldn't know
+    NONE,           // Most recent edit was not a paste.
+    PASTING,        // In the middle of doing a paste. We need this intermediate
+                    // state because OnPaste() does the actual detection of
+                    // paste, but OnAfterPossibleChange() has to update the
+                    // paste state for every edit. If OnPaste() set the state
+                    // directly to PASTED, OnAfterPossibleChange() wouldn't know
                     // whether that represented the current edit or a past one.
+    PASTED,         // Most recent edit was a paste.
   };
 
   enum ControlKeyState {
@@ -370,7 +356,7 @@
                        const NotificationDetails& details);
 
   // Called whenever user_text_ should change.
-  void InternalSetUserText(const std::wstring& text);
+  void InternalSetUserText(const string16& text);
 
   // Returns true if a keyword is selected.
   bool KeywordIsSelected() const;
@@ -378,8 +364,8 @@
   // Conversion between user text and display text. User text is the text the
   // user has input. Display text is the text being shown in the edit. The
   // two are different if a keyword is selected.
-  std::wstring DisplayTextFromUserText(const std::wstring& text) const;
-  std::wstring UserTextFromDisplayText(const std::wstring& text) const;
+  string16 DisplayTextFromUserText(const string16& text) const;
+  string16 UserTextFromDisplayText(const string16& text) const;
 
   // Returns the default match for the current text, as well as the alternate
   // nav URL, if |alternate_nav_url| is non-NULL and there is such a URL.
@@ -392,11 +378,21 @@
   // and CurrentTextIsURL()).  The view needs this because it calls this
   // function during copy handling, when the control key is down to trigger the
   // copy.
-  bool GetURLForText(const std::wstring& text, GURL* url) const;
+  bool GetURLForText(const string16& text, GURL* url) const;
 
-  // Determines the suggested search text and invokes OnSetSuggestedSearchText
-  // on the controller.
-  void UpdateSuggestedSearchText();
+  // Reverts the edit box from a temporary text back to the original user text.
+  // If |revert_popup| is true then the popup will be reverted as well.
+  void RevertTemporaryText(bool revert_popup);
+
+  // Accepts current keyword if the user only typed a space at the end of
+  // |new_user_text| comparing to the |old_user_text|.
+  // Returns true if the current keyword is accepted.
+  bool MaybeAcceptKeywordBySpace(const string16& old_user_text,
+                                 const string16& new_user_text);
+
+  // Checks if a given character is a valid space character for accepting
+  // keyword.
+  static bool IsSpaceCharForAcceptingKeyword(wchar_t c);
 
   AutocompleteEditView* view_;
 
@@ -410,7 +406,7 @@
   bool has_focus_;
 
   // The URL of the currently displayed page.
-  std::wstring permanent_text_;
+  string16 permanent_text_;
 
   // This flag is true when the user has modified the contents of the edit, but
   // not yet accepted them.  We use this to determine when we need to save
@@ -421,7 +417,7 @@
 
   // The text that the user has entered.  This does not include inline
   // autocomplete text that has not yet been accepted.
-  std::wstring user_text_;
+  string16 user_text_;
 
   // When the user closes the popup, we need to remember the URL for their
   // desired choice, so that if they hit enter without reopening the popup we
@@ -438,7 +434,7 @@
   // simply ask the popup for the desired URL directly.  As a result, the
   // contents of this variable only need to be updated when the popup is closed
   // but user_input_in_progress_ is not being cleared.
-  std::wstring url_for_remembered_user_selection_;
+  string16 url_for_remembered_user_selection_;
 
   // Inline autocomplete is allowed if the user has not just deleted text, and
   // no temporary text is showing.  In this case, inline_autocomplete_text_ is
@@ -448,7 +444,7 @@
   // text (actions that close the popup should either accept the text, convert
   // it to a normal selection, or change the edit entirely).
   bool just_deleted_text_;
-  std::wstring inline_autocomplete_text_;
+  string16 inline_autocomplete_text_;
 
   // Used by OnPopupDataChanged to keep track of whether there is currently a
   // temporary text.
@@ -466,12 +462,10 @@
   // them and not revert all the way to the permanent_text_.
   bool has_temporary_text_;
   GURL original_url_;
-  KeywordUIState original_keyword_ui_state_;
 
-  // When the user's last action was to paste and replace all the text, we
-  // disallow inline autocomplete (on the theory that the user is trying to
-  // paste in a new URL or part of one, and in either case inline autocomplete
-  // would get in the way).
+  // When the user's last action was to paste, we disallow inline autocomplete
+  // (on the theory that the user is trying to paste in a new URL or part of
+  // one, and in either case inline autocomplete would get in the way).
   PasteState paste_state_;
 
   // Whether the control key is depressed.  We track this to avoid calling
@@ -483,16 +477,13 @@
   // selected keyword, or just some input text that looks like a keyword (so we
   // can show a hint to press <tab>).  This is the keyword in either case;
   // is_keyword_hint_ (below) distinguishes the two cases.
-  std::wstring keyword_;
+  string16 keyword_;
 
   // True if the keyword associated with this match is merely a hint, i.e. the
   // user hasn't actually selected a keyword yet.  When this is true, we can use
   // keyword_ to show a "Press <tab> to search" sort of hint.
   bool is_keyword_hint_;
 
-  // See KeywordUIState enum.
-  KeywordUIState keyword_ui_state_;
-
   // Paste And Go-related state.  See CanPasteAndGo().
   mutable GURL paste_and_go_url_;
   mutable PageTransition::Type paste_and_go_transition_;
diff --git a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
index 73c8ae9..9d54555 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_edit.h"
 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
 #include "chrome/test/testing_profile.h"
@@ -23,30 +24,30 @@
                        PageTransition::Type transition,
                        const GURL& alternate_nav_url,
                        size_t selected_line,
-                       const std::wstring& keyword) {}
-  virtual std::wstring GetText() const { return std::wstring(); }
+                       const string16& keyword) {}
+  virtual string16 GetText() const { return string16(); }
   virtual bool IsEditingOrEmpty() const { return true; }
   virtual int GetIcon() const { return 0; }
-  virtual void SetUserText(const std::wstring& text) {}
-  virtual void SetUserText(const std::wstring& text,
-                           const std::wstring& display_text,
+  virtual void SetUserText(const string16& text) {}
+  virtual void SetUserText(const string16& text,
+                           const string16& display_text,
                            bool update_popup) {}
-  virtual void SetWindowTextAndCaretPos(const std::wstring& text,
+  virtual void SetWindowTextAndCaretPos(const string16& text,
                                         size_t caret_pos) {}
   virtual void SetForcedQuery() {}
   virtual bool IsSelectAll() { return false; }
   virtual bool DeleteAtEndPressed() { return false; }
-  virtual void GetSelectionBounds(std::wstring::size_type* start,
-                                  std::wstring::size_type* end) {}
+  virtual void GetSelectionBounds(string16::size_type* start,
+                                  string16::size_type* end) {}
   virtual void SelectAll(bool reversed) {}
   virtual void RevertAll() {}
   virtual void UpdatePopup() {}
   virtual void ClosePopup() {}
   virtual void SetFocus() {}
-  virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text,
+  virtual void OnTemporaryTextMaybeChanged(const string16& display_text,
                                            bool save_original_selection) {}
   virtual bool OnInlineAutocompleteTextMaybeChanged(
-      const std::wstring& display_text, size_t user_text_length) {
+      const string16& display_text, size_t user_text_length) {
     return false;
   }
   virtual void OnRevertTemporaryText() {}
@@ -54,14 +55,13 @@
   virtual bool OnAfterPossibleChange() { return false; }
   virtual gfx::NativeView GetNativeView() const { return 0; }
   virtual CommandUpdater* GetCommandUpdater() { return NULL; }
+  virtual void SetInstantSuggestion(const string16& input) {}
+  virtual string16 GetInstantSuggestion() const { return string16(); }
+  virtual int TextWidth() const { return 0; }
+  virtual bool IsImeComposing() const { return false; }
 
 #if defined(TOOLKIT_VIEWS)
   virtual views::View* AddToView(views::View* parent) { return NULL; }
-  virtual int TextWidth() const { return 0; }
-  virtual bool CommitInstantSuggestion(
-      const std::wstring& typed_text,
-      const std::wstring& suggested_text) { return false;}
-  virtual void SetInstantSuggestion(const string16& input) {}
 #endif
 
  private:
@@ -74,13 +74,12 @@
   virtual void OnAutocompleteWillClosePopup() {}
   virtual void OnAutocompleteLosingFocus(gfx::NativeView view_gaining_focus) {}
   virtual void OnAutocompleteWillAccept() {}
-  virtual bool OnCommitSuggestedText(const std::wstring& typed_text) {
+  virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete) {
     return false;
   }
   virtual bool AcceptCurrentInstantPreview() {
     return false;
   }
-  virtual void OnSetSuggestedSearchText(const string16& suggested_text) {}
   virtual void OnPopupBoundsChanged(const gfx::Rect& bounds) {}
   virtual void OnAutocompleteAccept(const GURL& url,
                                     WindowOpenDisposition disposition,
@@ -92,7 +91,7 @@
   virtual void OnKillFocus() {}
   virtual void OnSetFocus() {}
   virtual SkBitmap GetFavIcon() const { return SkBitmap(); }
-  virtual std::wstring GetTitle() const { return std::wstring(); }
+  virtual string16 GetTitle() const { return string16(); }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TestingAutocompleteEditController);
@@ -105,41 +104,41 @@
 // Tests various permutations of AutocompleteModel::AdjustTextForCopy.
 TEST(AutocompleteEditTest, AdjustTextForCopy) {
   struct Data {
-    const wchar_t* perm_text;
+    const char* perm_text;
     const int sel_start;
     const bool is_all_selected;
-    const wchar_t* input;
-    const wchar_t* expected_output;
+    const char* input;
+    const char* expected_output;
     const bool write_url;
     const char* expected_url;
   } input[] = {
     // Test that http:// is inserted if all text is selected.
-    { L"a.b/c", 0, true, L"a.b/c", L"http://a.b/c", true, "http://a.b/c" },
+    { "a.b/c", 0, true, "a.b/c", "http://a.b/c", true, "http://a.b/c" },
 
     // Test that http:// is inserted if the host is selected.
-    { L"a.b/c", 0, false, L"a.b/", L"http://a.b/", true, "http://a.b/" },
+    { "a.b/c", 0, false, "a.b/", "http://a.b/", true, "http://a.b/" },
 
     // Tests that http:// is inserted if the path is modified.
-    { L"a.b/c", 0, false, L"a.b/d", L"http://a.b/d", true, "http://a.b/d" },
+    { "a.b/c", 0, false, "a.b/d", "http://a.b/d", true, "http://a.b/d" },
 
     // Tests that http:// isn't inserted if the host is modified.
-    { L"a.b/c", 0, false, L"a.c/", L"a.c/", false, "" },
+    { "a.b/c", 0, false, "a.c/", "a.c/", false, "" },
 
     // Tests that http:// isn't inserted if the start of the selection is 1.
-    { L"a.b/c", 1, false, L"a.b/", L"a.b/", false, "" },
+    { "a.b/c", 1, false, "a.b/", "a.b/", false, "" },
 
     // Tests that http:// isn't inserted if a portion of the host is selected.
-    { L"a.com/", 0, false, L"a.co", L"a.co", false, "" },
+    { "a.com/", 0, false, "a.co", "a.co", false, "" },
 
     // Tests that http:// isn't inserted for an https url after the user nukes
     // https.
-    { L"https://a.com/", 0, false, L"a.com/", L"a.com/", false, "" },
+    { "https://a.com/", 0, false, "a.com/", "a.com/", false, "" },
 
     // Tests that http:// isn't inserted if the user adds to the host.
-    { L"a.b/", 0, false, L"a.bc/", L"a.bc/", false, "" },
+    { "a.b/", 0, false, "a.bc/", "a.bc/", false, "" },
 
     // Tests that we don't get double http if the user manually inserts http.
-    { L"a.b/", 0, false, L"http://a.b/", L"http://a.b/", true, "http://a.b/" },
+    { "a.b/", 0, false, "http://a.b/", "http://a.b/", true, "http://a.b/" },
   };
   TestingAutocompleteEditView view;
   TestingAutocompleteEditController controller;
@@ -147,14 +146,14 @@
   AutocompleteEditModel model(&view, &controller, &profile);
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input); ++i) {
-    model.UpdatePermanentText(input[i].perm_text);
+    model.UpdatePermanentText(ASCIIToUTF16(input[i].perm_text));
 
-    std::wstring result(input[i].input);
+    string16 result = ASCIIToUTF16(input[i].input);
     GURL url;
     bool write_url;
     model.AdjustTextForCopy(input[i].sel_start, input[i].is_all_selected,
                             &result, &url, &write_url);
-    EXPECT_EQ(input[i].expected_output, result) << "@: " << i;
+    EXPECT_EQ(ASCIIToUTF16(input[i].expected_output), result) << "@: " << i;
     EXPECT_EQ(input[i].write_url, write_url) << " @" << i;
     if (write_url)
       EXPECT_EQ(input[i].expected_url, url.spec()) << " @" << i;
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h
index 12c42a2..a7af148 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view.h
@@ -16,7 +16,7 @@
 
 #include "base/string16.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class AutocompleteEditModel;
@@ -60,12 +60,12 @@
                        PageTransition::Type transition,
                        const GURL& alternate_nav_url,
                        size_t selected_line,
-                       const std::wstring& keyword) = 0;
+                       const string16& keyword) = 0;
 
   // Returns the current text of the edit control, which could be the
   // "temporary" text set by the popup, the "permanent" text set by the
   // browser, or just whatever the user has currently typed.
-  virtual std::wstring GetText() const = 0;
+  virtual string16 GetText() const = 0;
 
   // |true| if the user is in the process of editing the field, or if
   // the field is empty.
@@ -77,13 +77,13 @@
   // The user text is the text the user has manually keyed in.  When present,
   // this is shown in preference to the permanent text; hitting escape will
   // revert to the permanent text.
-  virtual void SetUserText(const std::wstring& text) = 0;
-  virtual void SetUserText(const std::wstring& text,
-                           const std::wstring& display_text,
+  virtual void SetUserText(const string16& text) = 0;
+  virtual void SetUserText(const string16& text,
+                           const string16& display_text,
                            bool update_popup) = 0;
 
   // Sets the window text and the caret position.
-  virtual void SetWindowTextAndCaretPos(const std::wstring& text,
+  virtual void SetWindowTextAndCaretPos(const string16& text,
                                         size_t caret_pos) = 0;
 
   // Sets the edit to forced query mode.  Practically speaking, this means that
@@ -105,8 +105,8 @@
   // It is not guaranteed that |*start < *end|, as the selection can be
   // directed.  If there is no selection, |start| and |end| will both be equal
   // to the current cursor position.
-  virtual void GetSelectionBounds(std::wstring::size_type* start,
-                                  std::wstring::size_type* end) = 0;
+  virtual void GetSelectionBounds(string16::size_type* start,
+                                  string16::size_type* end) = 0;
 
   // Selects all the text in the edit.  Use this in place of SetSelAll() to
   // avoid selecting the "phantom newline" at the end of the edit.
@@ -130,7 +130,7 @@
   // |display_text| is the new text to show; |save_original_selection| is true
   // when there wasn't previously a temporary text and thus we need to save off
   // the user's existing selection.
-  virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text,
+  virtual void OnTemporaryTextMaybeChanged(const string16& display_text,
                                            bool save_original_selection) = 0;
 
   // Called when the inline autocomplete text in the model may have changed.
@@ -138,7 +138,7 @@
   // the user input portion of that (so, up to but not including the inline
   // autocompletion).  Returns whether the display text actually changed.
   virtual bool OnInlineAutocompleteTextMaybeChanged(
-      const std::wstring& display_text, size_t user_text_length) = 0;
+      const string16& display_text, size_t user_text_length) = 0;
 
   // Called when the temporary text has been reverted by the user.  This will
   // reset the user's original selection.
@@ -158,21 +158,23 @@
   // Returns the command updater for this view.
   virtual CommandUpdater* GetCommandUpdater() = 0;
 
-#if defined(TOOLKIT_VIEWS)
-  // Adds the autocomplete edit view to view hierarchy and
-  // returns the views::View of the edit view.
-  virtual views::View* AddToView(views::View* parent) = 0;
-
-  // Commits the suggested text.
-  virtual bool CommitInstantSuggestion(const std::wstring& typed_text,
-                                       const std::wstring& suggested_text) = 0;
-
   // Shows the instant suggestion text.
   virtual void SetInstantSuggestion(const string16& input) = 0;
 
+  // Returns the current instant suggestion text.
+  virtual string16 GetInstantSuggestion() const = 0;
+
   // Returns the width in pixels needed to display the current text. The
   // returned value includes margins.
   virtual int TextWidth() const = 0;
+
+  // Returns true if the user is composing something in an IME.
+  virtual bool IsImeComposing() const = 0;
+
+#if defined(TOOLKIT_VIEWS)
+  // Adds the autocomplete edit view to view hierarchy and
+  // returns the views::View of the edit view.
+  virtual views::View* AddToView(views::View* parent) = 0;
 #endif
 
   virtual ~AutocompleteEditView() {}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc b/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc
index adbba71..0cb8fdf 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <stdio.h>
 
-#include "app/keyboard_codes.h"
 #include "base/message_loop.h"
 #include "base/string16.h"
 #include "base/string_util.h"
@@ -31,13 +30,18 @@
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/base/mock_host_resolver.h"
-#include "views/event.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "views/events/event.h"
 
 #if defined(OS_LINUX)
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 #endif
 
+#if defined(TOOLKIT_VIEWS)
+#include "views/controls/textfield/native_textfield_views.h"
+#endif
+
 using base::Time;
 using base::TimeDelta;
 
@@ -45,24 +49,29 @@
 
 const char kSearchKeyword[] = "foo";
 const wchar_t kSearchKeywordKeys[] = {
-  app::VKEY_F, app::VKEY_O, app::VKEY_O, 0
+  ui::VKEY_F, ui::VKEY_O, ui::VKEY_O, 0
 };
 const char kSearchURL[] = "http://www.foo.com/search?q={searchTerms}";
 const char kSearchShortName[] = "foo";
 const char kSearchText[] = "abc";
 const wchar_t kSearchTextKeys[] = {
-  app::VKEY_A, app::VKEY_B, app::VKEY_C, 0
+  ui::VKEY_A, ui::VKEY_B, ui::VKEY_C, 0
 };
 const char kSearchTextURL[] = "http://www.foo.com/search?q=abc";
 const char kSearchSingleChar[] = "z";
-const wchar_t kSearchSingleCharKeys[] = { app::VKEY_Z, 0 };
+const wchar_t kSearchSingleCharKeys[] = { ui::VKEY_Z, 0 };
 const char kSearchSingleCharURL[] = "http://www.foo.com/search?q=z";
 
 const char kHistoryPageURL[] = "chrome://history/#q=abc";
 
 const char kDesiredTLDHostname[] = "www.bar.com";
 const wchar_t kDesiredTLDKeys[] = {
-  app::VKEY_B, app::VKEY_A, app::VKEY_R, 0
+  ui::VKEY_B, ui::VKEY_A, ui::VKEY_R, 0
+};
+
+const char kInlineAutocompleteText[] = "def";
+const wchar_t kInlineAutocompleteTextKeys[] = {
+  ui::VKEY_D, ui::VKEY_E, ui::VKEY_F, 0
 };
 
 // Hostnames that shall be blocked by host resolver.
@@ -73,6 +82,8 @@
   "*.bar.com",
   "abc",
   "*.abc.com",
+  "def",
+  "*.def.com",
   "history",
   "z"
 };
@@ -85,18 +96,18 @@
   int typed_count;
   bool starred;
 } kHistoryEntries[] = {
-  {"http://www.bar.com/1", "Page 1", kSearchText, 1, 1, false },
-  {"http://www.bar.com/2", "Page 2", kSearchText, 1, 1, false },
-  {"http://www.bar.com/3", "Page 3", kSearchText, 1, 1, false },
-  {"http://www.bar.com/4", "Page 4", kSearchText, 1, 1, false },
-  {"http://www.bar.com/5", "Page 5", kSearchText, 1, 1, false },
-  {"http://www.bar.com/6", "Page 6", kSearchText, 1, 1, false },
-  {"http://www.bar.com/7", "Page 7", kSearchText, 1, 1, false },
-  {"http://www.bar.com/8", "Page 8", kSearchText, 1, 1, false },
-  {"http://www.bar.com/9", "Page 9", kSearchText, 1, 1, false },
+  {"http://www.bar.com/1", "Page 1", kSearchText, 10, 10, false },
+  {"http://www.bar.com/2", "Page 2", kSearchText, 9, 9, false },
+  {"http://www.bar.com/3", "Page 3", kSearchText, 8, 8, false },
+  {"http://www.bar.com/4", "Page 4", kSearchText, 7, 7, false },
+  {"http://www.bar.com/5", "Page 5", kSearchText, 6, 6, false },
+  {"http://www.bar.com/6", "Page 6", kSearchText, 5, 5, false },
+  {"http://www.bar.com/7", "Page 7", kSearchText, 4, 4, false },
+  {"http://www.bar.com/8", "Page 8", kSearchText, 3, 3, false },
+  {"http://www.bar.com/9", "Page 9", kSearchText, 2, 2, false },
 
   // To trigger inline autocomplete.
-  {"http://www.abc.com", "Page abc", kSearchText, 10000, 10000, true },
+  {"http://www.def.com", "Page def", kSearchText, 10000, 10000, true },
 };
 
 #if defined(OS_LINUX)
@@ -129,6 +140,18 @@
     set_show_window(true);
   }
 
+  virtual void SetUpOnMainThread() {
+    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+    ASSERT_NO_FATAL_FAILURE(SetupComponents());
+    browser()->FocusLocationBar();
+#if defined(TOOLKIT_VIEWS)
+    if (views::NativeTextfieldViews::IsTextfieldViewsEnabled())
+      return;
+#endif
+    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(),
+                                             VIEW_ID_LOCATION_BAR));
+  }
+
   static void GetAutocompleteEditViewForBrowser(
       const Browser* browser,
       AutocompleteEditView** edit_view) {
@@ -145,7 +168,7 @@
   }
 
   static void SendKeyForBrowser(const Browser* browser,
-                                app::KeyboardCode key,
+                                ui::KeyboardCode key,
                                 bool control,
                                 bool shift,
                                 bool alt) {
@@ -153,13 +176,13 @@
         browser, key, control, shift, alt, false /* command */));
   }
 
-  void SendKey(app::KeyboardCode key, bool control, bool shift, bool alt) {
+  void SendKey(ui::KeyboardCode key, bool control, bool shift, bool alt) {
     SendKeyForBrowser(browser(), key, control, shift, alt);
   }
 
   void SendKeySequence(const wchar_t* keys) {
     for (; *keys; ++keys)
-      ASSERT_NO_FATAL_FAILURE(SendKey(static_cast<app::KeyboardCode>(*keys),
+      ASSERT_NO_FATAL_FAILURE(SendKey(static_cast<ui::KeyboardCode>(*keys),
                                       false, false, false));
   }
 
@@ -221,17 +244,24 @@
     }
 
     ASSERT_TRUE(model->loaded());
+    // Remove built-in template urls, like google.com, bing.com etc., as they
+    // may appear as autocomplete suggests and interfere with our tests.
+    model->SetDefaultSearchProvider(NULL);
+    TemplateURLModel::TemplateURLVector builtins = model->GetTemplateURLs();
+    for (TemplateURLModel::TemplateURLVector::const_iterator
+         i = builtins.begin(); i != builtins.end(); ++i)
+      model->Remove(*i);
 
     TemplateURL* template_url = new TemplateURL();
     template_url->SetURL(kSearchURL, 0, 0);
-    template_url->set_keyword(UTF8ToWide(kSearchKeyword));
-    template_url->set_short_name(UTF8ToWide(kSearchShortName));
+    template_url->set_keyword(UTF8ToUTF16(kSearchKeyword));
+    template_url->set_short_name(UTF8ToUTF16(kSearchShortName));
 
     model->Add(template_url);
     model->SetDefaultSearchProvider(template_url);
   }
 
-  void SetupHistory() {
+  void AddHistoryEntry(const TestHistoryEntry& entry, const Time& time) {
     Profile* profile = browser()->profile();
     HistoryService* history_service =
         profile->GetHistoryService(Profile::EXPLICIT_ACCESS);
@@ -254,22 +284,26 @@
       ui_test_utils::RunMessageLoop();
     }
 
-    // Add enough history pages containing |kSearchText| to trigger open history
-    // page url in autocomplete result.
+    GURL url(entry.url);
+    // Add everything in order of time. We don't want to have a time that
+    // is "right now" or it will nondeterministically appear in the results.
+    history_service->AddPageWithDetails(url, UTF8ToUTF16(entry.title),
+                                        entry.visit_count,
+                                        entry.typed_count, time, false,
+                                        history::SOURCE_BROWSED);
+    history_service->SetPageContents(url, UTF8ToUTF16(entry.body));
+    if (entry.starred)
+      bookmark_model->SetURLStarred(url, string16(), true);
+  }
+
+  void SetupHistory() {
+    // Add enough history pages containing |kSearchText| to trigger
+    // open history page url in autocomplete result.
     for (size_t i = 0; i < arraysize(kHistoryEntries); i++) {
-      const TestHistoryEntry& cur = kHistoryEntries[i];
-      GURL url(cur.url);
       // Add everything in order of time. We don't want to have a time that
       // is "right now" or it will nondeterministically appear in the results.
       Time t = Time::Now() - TimeDelta::FromHours(i + 1);
-      history_service->AddPageWithDetails(url, UTF8ToUTF16(cur.title),
-                                          cur.visit_count,
-                                          cur.typed_count, t, false,
-                                          history::SOURCE_BROWSED);
-      history_service->SetPageContents(url, UTF8ToUTF16(cur.body));
-      if (cur.starred) {
-        bookmark_model->SetURLStarred(url, string16(), true);
-      }
+      ASSERT_NO_FATAL_FAILURE(AddHistoryEntry(kHistoryEntries[i], t));
     }
   }
 
@@ -300,506 +334,849 @@
     }
     MessageLoopForUI::current()->Quit();
   }
+
+  void BrowserAcceleratorsTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    int tab_count = browser()->tab_count();
+
+    // Create a new Tab.
+    browser()->NewTab();
+    ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
+
+    // Select the first Tab.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_1, true, false, false));
+    ASSERT_EQ(0, browser()->selected_index());
+
+    browser()->FocusLocationBar();
+
+    // Select the second Tab.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_2, true, false, false));
+    ASSERT_EQ(1, browser()->selected_index());
+
+    browser()->FocusLocationBar();
+
+    // Try ctrl-w to close a Tab.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_W, true, false, false));
+    ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count));
+
+    // Try ctrl-l to focus location bar.
+    edit_view->SetUserText(ASCIIToUTF16("Hello world"));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_L, true, false, false));
+    EXPECT_TRUE(edit_view->IsSelectAll());
+
+    // Try editing the location bar text.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RIGHT, false, false, false));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_S, false, false, false));
+    EXPECT_EQ(ASCIIToUTF16("Hello worlds"), edit_view->GetText());
+
+    // Try ctrl-x to cut text.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, true, true, false));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_X, true, false, false));
+    EXPECT_EQ(ASCIIToUTF16("Hello "), edit_view->GetText());
+
+#if !defined(OS_CHROMEOS)
+    // Try alt-f4 to close the browser.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+        browser(), ui::VKEY_F4, false, false, true, false,
+        NotificationType::BROWSER_CLOSED, Source<Browser>(browser())));
+#endif
+  }
+
+  void PopupAcceleratorsTest() {
+    // Create a popup.
+    Browser* popup = CreateBrowserForPopup(browser()->profile());
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(
+        GetAutocompleteEditViewForBrowser(popup, &edit_view));
+    popup->FocusLocationBar();
+    EXPECT_TRUE(edit_view->IsSelectAll());
+
+    // Try ctrl-w to close the popup.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+        popup, ui::VKEY_W, true, false, false, false,
+        NotificationType::BROWSER_CLOSED, Source<Browser>(popup)));
+
+    // Create another popup.
+    popup = CreateBrowserForPopup(browser()->profile());
+    ASSERT_NO_FATAL_FAILURE(
+        GetAutocompleteEditViewForBrowser(popup, &edit_view));
+
+    // Set the edit text to "Hello world".
+    edit_view->SetUserText(ASCIIToUTF16("Hello world"));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    popup->FocusLocationBar();
+    EXPECT_TRUE(edit_view->IsSelectAll());
+
+    // Try editing the location bar text -- should be disallowed.
+    ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, ui::VKEY_RIGHT, false,
+                                              false, false));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, ui::VKEY_S, false, false,
+                                              false));
+    EXPECT_EQ(ASCIIToUTF16("Hello world"), edit_view->GetText());
+
+    // Try ctrl-x to cut text -- should be disallowed.
+    ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, ui::VKEY_LEFT, true, true,
+                                              false));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, ui::VKEY_X, true, false,
+                                              false));
+    EXPECT_EQ(ASCIIToUTF16("Hello world"), edit_view->GetText());
+
+#if !defined(OS_CHROMEOS)
+    // Try alt-f4 to close the popup.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+        popup, ui::VKEY_F4, false, false, true, false,
+        NotificationType::BROWSER_CLOSED, Source<Browser>(popup)));
+#endif
+  }
+
+  void BackspaceInKeywordModeTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    // Trigger keyword hint mode.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+
+    // Trigger keyword mode.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+
+    // Backspace without search text should bring back keyword hint mode.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+
+    // Trigger keyword mode again.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+
+    // Input something as search text.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
+
+    // Should stay in keyword mode while deleting search text by pressing
+    // backspace.
+    for (size_t i = 0; i < arraysize(kSearchText) - 1; ++i) {
+      ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+      ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+      ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+    }
+
+    // Input something as search text.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
+
+    // Move cursor to the beginning of the search text.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_HOME, false, false, false));
+    // Backspace at the beginning of the search text shall turn off
+    // the keyword mode.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(string16(), edit_view->model()->keyword());
+    ASSERT_EQ(std::string(kSearchKeyword) + kSearchText,
+              UTF16ToUTF8(edit_view->GetText()));
+  }
+
+  void EscapeTest() {
+    ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIHistoryURL));
+    browser()->FocusLocationBar();
+
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    string16 old_text = edit_view->GetText();
+    EXPECT_FALSE(old_text.empty());
+    EXPECT_TRUE(edit_view->IsSelectAll());
+
+    // Delete all text in omnibox.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+    EXPECT_TRUE(edit_view->GetText().empty());
+
+    // Escape shall revert the text in omnibox.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_ESCAPE, false, false, false));
+    EXPECT_EQ(old_text, edit_view->GetText());
+    EXPECT_TRUE(edit_view->IsSelectAll());
+  }
+
+  void DesiredTLDTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+    AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
+    ASSERT_TRUE(popup_model);
+
+    // Test ctrl-Enter.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kDesiredTLDKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+    // ctrl-Enter triggers desired_tld feature, thus www.bar.com shall be
+    // opened.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN, true, false, false));
+
+    GURL url = browser()->GetSelectedTabContents()->GetURL();
+    EXPECT_STREQ(kDesiredTLDHostname, url.host().c_str());
+  }
+
+  void AltEnterTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    edit_view->SetUserText(ASCIIToUTF16(chrome::kChromeUIHistoryURL));
+    int tab_count = browser()->tab_count();
+    // alt-Enter opens a new tab.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN, false, false, true));
+    ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
+  }
+
+  void EnterToSearchTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+    AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
+    ASSERT_TRUE(popup_model);
+
+    // Test Enter to search.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+
+    // Check if the default match result is Search Primary Provider.
+    ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
+              popup_model->result().default_match()->type);
+
+    // Open the default match.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN, false, false, false));
+    GURL url = browser()->GetSelectedTabContents()->GetURL();
+    EXPECT_STREQ(kSearchTextURL, url.spec().c_str());
+
+    // Test that entering a single character then Enter performs a search.
+    browser()->FocusLocationBar();
+    EXPECT_TRUE(edit_view->IsSelectAll());
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchSingleCharKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+    EXPECT_EQ(kSearchSingleChar, UTF16ToUTF8(edit_view->GetText()));
+
+    // Check if the default match result is Search Primary Provider.
+    ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
+              popup_model->result().default_match()->type);
+
+    // Open the default match.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN, false, false, false));
+    url = browser()->GetSelectedTabContents()->GetURL();
+    EXPECT_STREQ(kSearchSingleCharURL, url.spec().c_str());
+  }
+
+  void EscapeToDefaultMatchTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+    AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
+    ASSERT_TRUE(popup_model);
+
+    // Input something to trigger inline autocomplete.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kInlineAutocompleteTextKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+
+    string16 old_text = edit_view->GetText();
+
+    // Make sure inline autocomplete is triggerred.
+    EXPECT_GT(old_text.length(), arraysize(kInlineAutocompleteText) - 1);
+
+    size_t old_selected_line = popup_model->selected_line();
+    EXPECT_EQ(0U, old_selected_line);
+
+    // Move to another line with different text.
+    size_t size = popup_model->result().size();
+    while (popup_model->selected_line() < size - 1) {
+      ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DOWN, false, false, false));
+      ASSERT_NE(old_selected_line, popup_model->selected_line());
+      if (old_text != edit_view->GetText())
+        break;
+    }
+
+    EXPECT_NE(old_text, edit_view->GetText());
+
+    // Escape shall revert back to the default match item.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_ESCAPE, false, false, false));
+    EXPECT_EQ(old_text, edit_view->GetText());
+    EXPECT_EQ(old_selected_line, popup_model->selected_line());
+  }
+
+  void BasicTextOperationsTest() {
+    ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL));
+    browser()->FocusLocationBar();
+
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    string16 old_text = edit_view->GetText();
+    EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL), old_text);
+    EXPECT_TRUE(edit_view->IsSelectAll());
+
+    string16::size_type start, end;
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(0U, start);
+    EXPECT_EQ(old_text.size(), end);
+
+    // Move the cursor to the end.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_END, false, false, false));
+    EXPECT_FALSE(edit_view->IsSelectAll());
+
+    // Make sure the cursor is placed correctly.
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(old_text.size(), start);
+    EXPECT_EQ(old_text.size(), end);
+
+    // Insert one character at the end. Make sure we won't insert
+    // anything after the special ZWS mark used in gtk implementation.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_A, false, false, false));
+    EXPECT_EQ(old_text + char16('a'), edit_view->GetText());
+
+    // Delete one character from the end. Make sure we won't delete the special
+    // ZWS mark used in gtk implementation.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+    EXPECT_EQ(old_text, edit_view->GetText());
+
+    edit_view->SelectAll(true);
+    EXPECT_TRUE(edit_view->IsSelectAll());
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(0U, start);
+    EXPECT_EQ(old_text.size(), end);
+
+    // Delete the content
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DELETE, false, false, false));
+    EXPECT_TRUE(edit_view->IsSelectAll());
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(0U, start);
+    EXPECT_EQ(0U, end);
+    EXPECT_TRUE(edit_view->GetText().empty());
+
+    // Check if RevertAll() can set text and cursor correctly.
+    edit_view->RevertAll();
+    EXPECT_FALSE(edit_view->IsSelectAll());
+    EXPECT_EQ(old_text, edit_view->GetText());
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(old_text.size(), start);
+    EXPECT_EQ(old_text.size(), end);
+  }
+
+  void AcceptKeywordBySpaceTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    string16 text = UTF8ToUTF16(kSearchKeyword);
+
+    // Trigger keyword hint mode.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text, edit_view->GetText());
+
+    // Trigger keyword mode by space.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_TRUE(edit_view->GetText().empty());
+
+    // Revert to keyword hint mode.
+    edit_view->model()->ClearKeyword(string16());
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text, edit_view->GetText());
+
+    // Keyword should also be accepted by typing an ideographic space.
+    edit_view->OnBeforePossibleChange();
+    edit_view->SetWindowTextAndCaretPos(text + WideToUTF16(L"\x3000"),
+                                        text.length() + 1);
+    edit_view->OnAfterPossibleChange();
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_TRUE(edit_view->GetText().empty());
+
+    // Revert to keyword hint mode.
+    edit_view->model()->ClearKeyword(string16());
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text, edit_view->GetText());
+
+    // Keyword shouldn't be accepted by pasting.
+    // Simulate pasting a whitespace to the end of content.
+    edit_view->OnBeforePossibleChange();
+    edit_view->model()->on_paste();
+    edit_view->SetWindowTextAndCaretPos(text + char16(' '), text.length() + 1);
+    edit_view->OnAfterPossibleChange();
+    // Should be still in keyword hint mode.
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text + char16(' '), edit_view->GetText());
+
+    // Keyword shouldn't be accepted by pressing space with a trailing
+    // whitespace.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text + ASCIIToUTF16("  "), edit_view->GetText());
+
+    // Keyword shouldn't be accepted by deleting the trailing space.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text + char16(' '), edit_view->GetText());
+
+    // Keyword shouldn't be accepted by pressing space in the middle
+    // of content.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, false, false, false));
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text + ASCIIToUTF16("  "), edit_view->GetText());
+
+    // Keyword shouldn't be accepted by pasting "foo bar".
+    edit_view->SetUserText(string16());
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_TRUE(edit_view->model()->keyword().empty());
+
+    edit_view->OnBeforePossibleChange();
+    edit_view->model()->on_paste();
+    edit_view->SetWindowTextAndCaretPos(text + ASCIIToUTF16(" bar"),
+                                        text.length() + 4);
+    edit_view->OnAfterPossibleChange();
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_TRUE(edit_view->model()->keyword().empty());
+    ASSERT_EQ(text + ASCIIToUTF16(" bar"), edit_view->GetText());
+
+    // Keyword could be accepted by pressing space with a selected range at the
+    // end of text.
+    edit_view->OnBeforePossibleChange();
+    edit_view->OnInlineAutocompleteTextMaybeChanged(
+        text + ASCIIToUTF16("  "), text.length());
+    edit_view->OnAfterPossibleChange();
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(text + ASCIIToUTF16("  "), edit_view->GetText());
+
+    string16::size_type start, end;
+    edit_view->GetSelectionBounds(&start, &end);
+    ASSERT_NE(start, end);
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_EQ(string16(), edit_view->GetText());
+
+    edit_view->SetUserText(string16());
+
+    // Space should accept keyword even when inline autocomplete is available.
+    const TestHistoryEntry kHistoryFoobar = {
+      "http://www.foobar.com", "Page foobar", kSearchText, 10000, 10000, true
+    };
+
+    // Add a history entry to trigger inline autocomplete when typing "foo".
+    ASSERT_NO_FATAL_FAILURE(
+        AddHistoryEntry(kHistoryFoobar, Time::Now() - TimeDelta::FromHours(1)));
+
+    // Type "foo" to trigger inline autocomplete.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(edit_view->model()->popup_model()->IsOpen());
+    ASSERT_NE(text, edit_view->GetText());
+
+    // Keyword hint shouldn't be visible.
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_TRUE(edit_view->model()->keyword().empty());
+
+    // Trigger keyword mode by space.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(text, edit_view->model()->keyword());
+    ASSERT_TRUE(edit_view->GetText().empty());
+  }
+
+  void NonSubstitutingKeywordTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+    AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
+    ASSERT_TRUE(popup_model);
+
+    TemplateURLModel* template_url_model =
+        browser()->profile()->GetTemplateURLModel();
+
+    // Add a non-default substituting keyword.
+    TemplateURL* template_url = new TemplateURL();
+    template_url->SetURL("http://abc.com/{searchTerms}", 0, 0);
+    template_url->set_keyword(UTF8ToUTF16(kSearchText));
+    template_url->set_short_name(UTF8ToUTF16("Search abc"));
+    template_url_model->Add(template_url);
+
+    edit_view->SetUserText(string16());
+
+    // Non-default substituting keyword shouldn't be matched by default.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+
+    // Check if the default match result is Search Primary Provider.
+    ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
+              popup_model->result().default_match()->type);
+    ASSERT_EQ(kSearchTextURL,
+              popup_model->result().default_match()->destination_url.spec());
+
+    edit_view->SetUserText(string16());
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_FALSE(popup_model->IsOpen());
+
+    // Try a non-substituting keyword.
+    template_url_model->Remove(template_url);
+    template_url = new TemplateURL();
+    template_url->SetURL("http://abc.com/", 0, 0);
+    template_url->set_keyword(UTF8ToUTF16(kSearchText));
+    template_url->set_short_name(UTF8ToUTF16("abc"));
+    template_url_model->Add(template_url);
+
+    // We always allow exact matches for non-substituting keywords.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+    ASSERT_EQ(AutocompleteMatch::HISTORY_KEYWORD,
+              popup_model->result().default_match()->type);
+    ASSERT_EQ("http://abc.com/",
+              popup_model->result().default_match()->destination_url.spec());
+  }
+
+  void DeleteItemTest() {
+    // Disable the search provider, to make sure the popup contains only history
+    // items.
+    TemplateURLModel* model = browser()->profile()->GetTemplateURLModel();
+    model->SetDefaultSearchProvider(NULL);
+
+    ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL));
+    browser()->FocusLocationBar();
+
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
+    ASSERT_TRUE(popup_model);
+
+    string16 old_text = edit_view->GetText();
+
+    // Input something that can match history items.
+    edit_view->SetUserText(ASCIIToUTF16("bar"));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+
+    // Delete the inline autocomplete part.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DELETE, false, false, false));
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    ASSERT_TRUE(popup_model->IsOpen());
+    ASSERT_GE(popup_model->result().size(), 3U);
+
+    string16 user_text = edit_view->GetText();
+    ASSERT_EQ(ASCIIToUTF16("bar"), user_text);
+    edit_view->SelectAll(true);
+    ASSERT_TRUE(edit_view->IsSelectAll());
+
+    // The first item should be the default match.
+    size_t default_line = popup_model->selected_line();
+    std::string default_url =
+        popup_model->result().match_at(default_line).destination_url.spec();
+
+    // Move down.
+    edit_view->model()->OnUpOrDownKeyPressed(1);
+    ASSERT_EQ(default_line + 1, popup_model->selected_line());
+    string16 selected_text =
+        popup_model->result().match_at(default_line + 1).fill_into_edit;
+    // Temporary text is shown.
+    ASSERT_EQ(selected_text, edit_view->GetText());
+    ASSERT_FALSE(edit_view->IsSelectAll());
+
+    // Delete the item.
+    popup_model->TryDeletingCurrentItem();
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    // The selected line shouldn't be changed, because we have more than two
+    // items.
+    ASSERT_EQ(default_line + 1, popup_model->selected_line());
+    // Make sure the item is really deleted.
+    ASSERT_NE(selected_text,
+              popup_model->result().match_at(default_line + 1).fill_into_edit);
+    selected_text =
+        popup_model->result().match_at(default_line + 1).fill_into_edit;
+    // New temporary text is shown.
+    ASSERT_EQ(selected_text, edit_view->GetText());
+
+    // Revert to the default match.
+    ASSERT_TRUE(edit_view->model()->OnEscapeKeyPressed());
+    ASSERT_EQ(default_line, popup_model->selected_line());
+    ASSERT_EQ(user_text, edit_view->GetText());
+    ASSERT_TRUE(edit_view->IsSelectAll());
+
+    // Move down and up to select the default match as temporary text.
+    edit_view->model()->OnUpOrDownKeyPressed(1);
+    ASSERT_EQ(default_line + 1, popup_model->selected_line());
+    edit_view->model()->OnUpOrDownKeyPressed(-1);
+    ASSERT_EQ(default_line, popup_model->selected_line());
+
+    selected_text = popup_model->result().match_at(default_line).fill_into_edit;
+    // New temporary text is shown.
+    ASSERT_EQ(selected_text, edit_view->GetText());
+    ASSERT_FALSE(edit_view->IsSelectAll());
+
+    // Delete the default item.
+    popup_model->TryDeletingCurrentItem();
+    ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
+    // The selected line shouldn't be changed, but the default item should have
+    // been changed.
+    ASSERT_EQ(default_line, popup_model->selected_line());
+    // Make sure the item is really deleted.
+    ASSERT_NE(selected_text,
+              popup_model->result().match_at(default_line).fill_into_edit);
+    selected_text =
+        popup_model->result().match_at(default_line).fill_into_edit;
+    // New temporary text is shown.
+    ASSERT_EQ(selected_text, edit_view->GetText());
+
+    // As the current selected item is the new default item, pressing Escape key
+    // should revert all directly.
+    ASSERT_TRUE(edit_view->model()->OnEscapeKeyPressed());
+    ASSERT_EQ(old_text, edit_view->GetText());
+    ASSERT_TRUE(edit_view->IsSelectAll());
+  }
+
+  void TabMoveCursorToEndTest() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    edit_view->SetUserText(ASCIIToUTF16("Hello world"));
+
+    // Move cursor to the beginning.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_HOME, false, false, false));
+
+    string16::size_type start, end;
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(0U, start);
+    EXPECT_EQ(0U, end);
+
+    // Pressing tab should move cursor to the end.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false));
+
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(edit_view->GetText().size(), start);
+    EXPECT_EQ(edit_view->GetText().size(), end);
+
+    // The location bar should still have focus.
+    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_LOCATION_BAR));
+
+    // Select all text.
+    edit_view->SelectAll(true);
+    EXPECT_TRUE(edit_view->IsSelectAll());
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(0U, start);
+    EXPECT_EQ(edit_view->GetText().size(), end);
+
+    // Pressing tab should move cursor to the end.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false));
+
+    edit_view->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(edit_view->GetText().size(), start);
+    EXPECT_EQ(edit_view->GetText().size(), end);
+
+    // The location bar should still have focus.
+    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_LOCATION_BAR));
+
+    // Pressing tab when cursor is at the end should change focus.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false));
+
+    ASSERT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_LOCATION_BAR));
+  }
+
+  void PersistKeywordModeOnTabSwitch() {
+    AutocompleteEditView* edit_view = NULL;
+    ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+
+    // Trigger keyword hint mode.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
+    ASSERT_TRUE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+
+    // Trigger keyword mode.
+    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false));
+    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+
+    // Input something as search text.
+    ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
+
+    // Create a new tab.
+    browser()->NewTab();
+
+    // Switch back to the first tab.
+    browser()->SelectTabContentsAt(0, true);
+
+    // Make sure we're still in keyword mode.
+    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(edit_view->model()->keyword()));
+  }
 };
 
 // Test if ctrl-* accelerators are workable in omnibox.
 // See http://crbug.com/19193: omnibox blocks ctrl-* commands
-IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, BrowserAccelerators) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  browser()->FocusLocationBar();
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-
-  int tab_count = browser()->tab_count();
-
-  // Create a new Tab.
-  browser()->NewTab();
-  ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
-
-  // Select the first Tab.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_1, true, false, false));
-  ASSERT_EQ(0, browser()->selected_index());
-
-  browser()->FocusLocationBar();
-
-  // Select the second Tab.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_2, true, false, false));
-  ASSERT_EQ(1, browser()->selected_index());
-
-  browser()->FocusLocationBar();
-
-  // Try ctrl-w to close a Tab.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_W, true, false, false));
-  ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count));
-
-  // Try ctrl-l to focus location bar.
-  edit_view->SetUserText(L"Hello world");
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_L, true, false, false));
-  EXPECT_TRUE(edit_view->IsSelectAll());
-
-  // Try editing the location bar text.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RIGHT, false, false, false));
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_S, false, false, false));
-  EXPECT_EQ(L"Hello worlds", edit_view->GetText());
-
-  // Try ctrl-x to cut text.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_LEFT, true, true, false));
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_X, true, false, false));
-  EXPECT_EQ(L"Hello ", edit_view->GetText());
-
-#if !defined(OS_CHROMEOS)
-  // Try alt-f4 to close the browser.
-  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-      browser(), app::VKEY_F4, false, false, true, false,
-      NotificationType::BROWSER_CLOSED, Source<Browser>(browser())));
-#endif
+//
+// Flaky on interactive tests (dbg), http://crbug.com/69433
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, FLAKY_BrowserAccelerators) {
+  BrowserAcceleratorsTest();
 }
 
-IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, PopupAccelerators) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  // Create a popup.
-  Browser* popup = CreateBrowserForPopup(browser()->profile());
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditViewForBrowser(popup, &edit_view));
-  popup->FocusLocationBar();
-  EXPECT_TRUE(edit_view->IsSelectAll());
-
-  // Try ctrl-w to close the popup.
-  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-      popup, app::VKEY_W, true, false, false, false,
-      NotificationType::BROWSER_CLOSED, Source<Browser>(popup)));
-
-  // Create another popup.
-  popup = CreateBrowserForPopup(browser()->profile());
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditViewForBrowser(popup, &edit_view));
-
-  // Set the edit text to "Hello world".
-  edit_view->SetUserText(L"Hello world");
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  popup->FocusLocationBar();
-  EXPECT_TRUE(edit_view->IsSelectAll());
-
-  // Try editing the location bar text -- should be disallowed.
-  ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, app::VKEY_RIGHT, false,
-                                            false, false));
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, app::VKEY_S, false, false,
-                                            false));
-  EXPECT_EQ(L"Hello world", edit_view->GetText());
-
-  // Try ctrl-x to cut text -- should be disallowed.
-  ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, app::VKEY_LEFT, true, true,
-                                            false));
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, app::VKEY_X, true, false,
-                                            false));
-  EXPECT_EQ(L"Hello world", edit_view->GetText());
-
-#if !defined(OS_CHROMEOS)
-  // Try alt-f4 to close the popup.
-  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-      popup, app::VKEY_F4, false, false, true, false,
-      NotificationType::BROWSER_CLOSED, Source<Browser>(popup)));
+// Flakily fails and times out on Win only.  http://crbug.com/69941
+#if defined(OS_WIN)
+#define MAYBE_PopupAccelerators DISABLED_PopupAccelerators
+#else
+#define MAYBE_PopupAccelerators PopupAccelerators
 #endif
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_PopupAccelerators) {
+  PopupAcceleratorsTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, BackspaceInKeywordMode) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-
-  // Trigger keyword hint mode.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
-  ASSERT_TRUE(edit_view->model()->is_keyword_hint());
-  ASSERT_EQ(kSearchKeyword, WideToUTF8(edit_view->model()->keyword()));
-
-  // Trigger keyword mode.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_TAB, false, false, false));
-  ASSERT_FALSE(edit_view->model()->is_keyword_hint());
-  ASSERT_EQ(kSearchKeyword, WideToUTF8(edit_view->model()->keyword()));
-
-  // Backspace without search text should bring back keyword hint mode.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-  ASSERT_TRUE(edit_view->model()->is_keyword_hint());
-  ASSERT_EQ(kSearchKeyword, WideToUTF8(edit_view->model()->keyword()));
-
-  // Trigger keyword mode again.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_TAB, false, false, false));
-  ASSERT_FALSE(edit_view->model()->is_keyword_hint());
-  ASSERT_EQ(kSearchKeyword, WideToUTF8(edit_view->model()->keyword()));
-
-  // Input something as search text.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
-
-  // Should stay in keyword mode while deleting search text by pressing
-  // backspace.
-  for (size_t i = 0; i < arraysize(kSearchText) - 1; ++i) {
-    ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-    ASSERT_FALSE(edit_view->model()->is_keyword_hint());
-    ASSERT_EQ(kSearchKeyword, WideToUTF8(edit_view->model()->keyword()));
-  }
-
-  // Input something as search text.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
-
-  // Move cursor to the beginning of the search text.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_HOME, false, false, false));
-  // Backspace at the beginning of the search text shall turn off
-  // the keyword mode.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-  ASSERT_FALSE(edit_view->model()->is_keyword_hint());
-  ASSERT_EQ(std::string(), WideToUTF8(edit_view->model()->keyword()));
-  ASSERT_EQ(std::string(kSearchKeyword) + kSearchText,
-            WideToUTF8(edit_view->GetText()));
+  BackspaceInKeywordModeTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, Escape) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIHistoryURL));
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-
-  std::wstring old_text = edit_view->GetText();
-  EXPECT_FALSE(old_text.empty());
-  EXPECT_TRUE(edit_view->IsSelectAll());
-
-  // Delete all text in omnibox.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-  EXPECT_TRUE(edit_view->GetText().empty());
-
-  // Escape shall revert the text in omnibox.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_ESCAPE, false, false, false));
-  EXPECT_EQ(old_text, edit_view->GetText());
-  EXPECT_TRUE(edit_view->IsSelectAll());
+  EscapeTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, DesiredTLD) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-  AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
-  ASSERT_TRUE(popup_model);
-
-  // Test ctrl-Enter.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kDesiredTLDKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(popup_model->IsOpen());
-  // ctrl-Enter triggers desired_tld feature, thus www.bar.com shall be opened.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RETURN, true, false, false));
-
-  GURL url = browser()->GetSelectedTabContents()->GetURL();
-  EXPECT_STREQ(kDesiredTLDHostname, url.host().c_str());
+  DesiredTLDTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, AltEnter) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-
-  edit_view->SetUserText(ASCIIToWide(chrome::kChromeUIHistoryURL));
-  int tab_count = browser()->tab_count();
-  // alt-Enter opens a new tab.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RETURN, false, false, true));
-  ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
+  AltEnterTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, EnterToSearch) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
-  ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-  AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
-  ASSERT_TRUE(popup_model);
-
-  // Test Enter to search.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(popup_model->IsOpen());
-
-  // Check if the default match result is Search Primary Provider.
-  ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
-            popup_model->result().default_match()->type);
-
-  // Open the default match.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RETURN, false, false, false));
-  GURL url = browser()->GetSelectedTabContents()->GetURL();
-  EXPECT_STREQ(kSearchTextURL, url.spec().c_str());
-
-  // Test that entering a single character then Enter performs a search.
-  browser()->FocusLocationBar();
-  EXPECT_TRUE(edit_view->IsSelectAll());
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchSingleCharKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(popup_model->IsOpen());
-  EXPECT_EQ(kSearchSingleChar, WideToUTF8(edit_view->GetText()));
-
-  // Check if the default match result is Search Primary Provider.
-  ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
-            popup_model->result().default_match()->type);
-
-  // Open the default match.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RETURN, false, false, false));
-  url = browser()->GetSelectedTabContents()->GetURL();
-  EXPECT_STREQ(kSearchSingleCharURL, url.spec().c_str());
-}
-
-// See http://crbug.com/20934: Omnibox keyboard behavior wrong for
-// "See recent pages in history"
-IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, EnterToOpenHistoryPage) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-  AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
-  ASSERT_TRUE(popup_model);
-
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(popup_model->IsOpen());
-  EXPECT_EQ(0U, popup_model->selected_line());
-
-  // Move to the history page item.
-  size_t size = popup_model->result().size();
-  while (true) {
-    if (popup_model->result().match_at(popup_model->selected_line()).type ==
-        AutocompleteMatch::OPEN_HISTORY_PAGE)
-      break;
-    size_t old_selected_line = popup_model->selected_line();
-    ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_DOWN, false, false, false));
-    ASSERT_EQ(old_selected_line + 1, popup_model->selected_line());
-    if (popup_model->selected_line() == size - 1)
-      break;
-  }
-
-  // Make sure the history page item is selected.
-  ASSERT_EQ(AutocompleteMatch::OPEN_HISTORY_PAGE,
-            popup_model->result().match_at(popup_model->selected_line()).type);
-
-  // Open the history page item.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RETURN, false, false, false));
-  GURL url = browser()->GetSelectedTabContents()->GetURL();
-  EXPECT_STREQ(kHistoryPageURL, url.spec().c_str());
+  EnterToSearchTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, EscapeToDefaultMatch) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  browser()->FocusLocationBar();
-
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-  AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
-  ASSERT_TRUE(popup_model);
-
-  // Input something to trigger inline autocomplete.
-  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
-  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
-  ASSERT_TRUE(popup_model->IsOpen());
-
-  std::wstring old_text = edit_view->GetText();
-
-  // Make sure inline autocomplete is triggerred.
-  EXPECT_GT(old_text.length(), arraysize(kSearchText) - 1);
-
-  size_t old_selected_line = popup_model->selected_line();
-  EXPECT_EQ(0U, old_selected_line);
-
-  // Move to another line with different text.
-  size_t size = popup_model->result().size();
-  while (popup_model->selected_line() < size - 1) {
-    ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_DOWN, false, false, false));
-    ASSERT_NE(old_selected_line, popup_model->selected_line());
-    if (old_text != edit_view->GetText())
-      break;
-  }
-
-  EXPECT_NE(old_text, edit_view->GetText());
-
-  // Escape shall revert back to the default match item.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_ESCAPE, false, false, false));
-  EXPECT_EQ(old_text, edit_view->GetText());
-  EXPECT_EQ(old_selected_line, popup_model->selected_line());
+  EscapeToDefaultMatchTest();
 }
 
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, BasicTextOperations) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  BasicTextOperationsTest();
+}
 
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL));
-  browser()->FocusLocationBar();
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, AcceptKeywordBySpace) {
+  AcceptKeywordBySpaceTest();
+}
 
-  AutocompleteEditView* edit_view = NULL;
-  ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, NonSubstitutingKeywordTest) {
+  NonSubstitutingKeywordTest();
+}
 
-  std::wstring old_text = edit_view->GetText();
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL), old_text);
-  EXPECT_TRUE(edit_view->IsSelectAll());
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, DeleteItem) {
+  DeleteItemTest();
+}
 
-  std::wstring::size_type start, end;
-  edit_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(0U, start);
-  EXPECT_EQ(old_text.size(), end);
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, TabMoveCursorToEnd) {
+  TabMoveCursorToEndTest();
+}
 
-  // Move the cursor to the end.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_END, false, false, false));
-  EXPECT_FALSE(edit_view->IsSelectAll());
-
-  // Make sure the cursor is placed correctly.
-  edit_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(old_text.size(), start);
-  EXPECT_EQ(old_text.size(), end);
-
-  // Insert one character at the end. Make sure we won't insert anything after
-  // the special ZWS mark used in gtk implementation.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_A, false, false, false));
-  EXPECT_EQ(old_text + L"a", edit_view->GetText());
-
-  // Delete one character from the end. Make sure we won't delete the special
-  // ZWS mark used in gtk implementation.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-  EXPECT_EQ(old_text, edit_view->GetText());
-
-  edit_view->SelectAll(true);
-  EXPECT_TRUE(edit_view->IsSelectAll());
-  edit_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(0U, start);
-  EXPECT_EQ(old_text.size(), end);
-
-  // Delete the content
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_DELETE, false, false, false));
-  EXPECT_TRUE(edit_view->IsSelectAll());
-  edit_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(0U, start);
-  EXPECT_EQ(0U, end);
-  EXPECT_TRUE(edit_view->GetText().empty());
-
-  // Check if RevertAll() can set text and cursor correctly.
-  edit_view->RevertAll();
-  EXPECT_FALSE(edit_view->IsSelectAll());
-  EXPECT_EQ(old_text, edit_view->GetText());
-  edit_view->GetSelectionBounds(&start, &end);
-  EXPECT_EQ(old_text.size(), start);
-  EXPECT_EQ(old_text.size(), end);
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest,
+                       PersistKeywordModeOnTabSwitch) {
+  PersistKeywordModeOnTabSwitch();
 }
 
 #if defined(OS_LINUX)
-IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, UndoRedoLinux) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+// TODO(oshima): enable these tests for views-implmentation when
+// these featuers are supported.
 
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, UndoRedoLinux) {
   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL));
   browser()->FocusLocationBar();
 
   AutocompleteEditView* edit_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
 
-  std::wstring old_text = edit_view->GetText();
-  EXPECT_EQ(UTF8ToWide(chrome::kAboutBlankURL), old_text);
+  string16 old_text = edit_view->GetText();
+  EXPECT_EQ(UTF8ToUTF16(chrome::kAboutBlankURL), old_text);
   EXPECT_TRUE(edit_view->IsSelectAll());
 
   // Undo should clear the omnibox.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, false, false));
   EXPECT_TRUE(edit_view->GetText().empty());
 
   // Nothing should happen if undo again.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, false, false));
   EXPECT_TRUE(edit_view->GetText().empty());
 
   // Redo should restore the original text.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, true, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, true, false));
   EXPECT_EQ(old_text, edit_view->GetText());
 
   // Looks like the undo manager doesn't support restoring selection.
   EXPECT_FALSE(edit_view->IsSelectAll());
 
   // The cursor should be at the end.
-  std::wstring::size_type start, end;
+  string16::size_type start, end;
   edit_view->GetSelectionBounds(&start, &end);
   EXPECT_EQ(old_text.size(), start);
   EXPECT_EQ(old_text.size(), end);
 
   // Delete two characters.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
   EXPECT_EQ(old_text.substr(0, old_text.size() - 2), edit_view->GetText());
 
   // Undo delete.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, false, false));
   EXPECT_EQ(old_text, edit_view->GetText());
 
   // Redo delete.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, true, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, true, false));
   EXPECT_EQ(old_text.substr(0, old_text.size() - 2), edit_view->GetText());
 
   // Delete everything.
   edit_view->SelectAll(true);
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
   EXPECT_TRUE(edit_view->GetText().empty());
 
   // Undo delete everything.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, false, false));
   EXPECT_EQ(old_text.substr(0, old_text.size() - 2), edit_view->GetText());
 
   // Undo delete two characters.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, false, false));
   EXPECT_EQ(old_text, edit_view->GetText());
 
   // Undo again.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_Z, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, true, false, false));
   EXPECT_TRUE(edit_view->GetText().empty());
 }
 
 // See http://crbug.com/63860
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, PrimarySelection) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  browser()->FocusLocationBar();
   AutocompleteEditView* edit_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
-  edit_view->SetUserText(L"Hello world");
+  edit_view->SetUserText(ASCIIToUTF16("Hello world"));
   EXPECT_FALSE(edit_view->IsSelectAll());
 
   // Move the cursor to the end.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_END, false, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_END, false, false, false));
 
   // Select all text by pressing Shift+Home
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_HOME, false, true, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_HOME, false, true, false));
   EXPECT_TRUE(edit_view->IsSelectAll());
 
   // The selected content should be saved to the PRIMARY clipboard.
   EXPECT_EQ("Hello world", GetPrimarySelectionText());
 
   // Move the cursor to the end.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_END, false, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_END, false, false, false));
   EXPECT_FALSE(edit_view->IsSelectAll());
 
   // The content in the PRIMARY clipboard should not be cleared.
@@ -809,29 +1186,21 @@
 // See http://crosbug.com/10306
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest,
                        BackspaceDeleteHalfWidthKatakana) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  browser()->FocusLocationBar();
   AutocompleteEditView* edit_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
   // Insert text: ダ
-  edit_view->SetUserText(UTF8ToWide("\357\276\200\357\276\236"));
+  edit_view->SetUserText(UTF8ToUTF16("\357\276\200\357\276\236"));
 
   // Move the cursor to the end.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_END, false, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_END, false, false, false));
 
   // Backspace should delete one character.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_BACK, false, false, false));
-  EXPECT_EQ(UTF8ToWide("\357\276\200"), edit_view->GetText());
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, false, false, false));
+  EXPECT_EQ(UTF8ToUTF16("\357\276\200"), edit_view->GetText());
 }
 
 // http://crbug.com/12316
 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, PasteReplacingAll) {
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-
-  ASSERT_NO_FATAL_FAILURE(SetupComponents());
-  browser()->FocusLocationBar();
-
   AutocompleteEditView* edit_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
   AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
@@ -840,11 +1209,83 @@
   SetClipboardText(kSearchText);
 
   // Paste text.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_V, true, false, false));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_V, true, false, false));
   ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
   ASSERT_TRUE(popup_model->IsOpen());
 
   // Inline autocomplete shouldn't be triggered.
-  ASSERT_EQ(L"abc", edit_view->GetText());
+  ASSERT_EQ(ASCIIToUTF16("abc"), edit_view->GetText());
 }
 #endif
+
+#if defined(TOOLKIT_VIEWS)
+class AutocompleteEditViewViewsTest : public AutocompleteEditViewTest {
+ public:
+  AutocompleteEditViewViewsTest() {
+    views::NativeTextfieldViews::SetEnableTextfieldViews(true);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest,
+                       FLAKY_BrowserAccelerators) {
+  BrowserAcceleratorsTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, MAYBE_PopupAccelerators) {
+  PopupAcceleratorsTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, BackspaceInKeywordMode) {
+  BackspaceInKeywordModeTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, Escape) {
+  EscapeTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, DesiredTLD) {
+  DesiredTLDTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, AltEnter) {
+  AltEnterTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, EnterToSearch) {
+  EnterToSearchTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, EscapeToDefaultMatch) {
+  EscapeToDefaultMatchTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, BasicTextOperations) {
+  BasicTextOperationsTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, AcceptKeywordBySpace) {
+  AcceptKeywordBySpaceTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest,
+                       NonSubstitutingKeywordTest) {
+  NonSubstitutingKeywordTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, DeleteItem) {
+  DeleteItemTest();
+}
+
+// TODO(suzhe): This test is broken because of broken ViewID support when
+// enabling AutocompleteEditViewViews.
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest,
+                       DISABLED_TabMoveCursorToEnd) {
+  TabMoveCursorToEndTest();
+}
+
+IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest,
+                       PersistKeywordModeOnTabSwitch) {
+  PersistKeywordModeOnTabSwitch();
+}
+
+#endif
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
index 4de3d2c..33eb4ff 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
@@ -1,15 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
 
-#include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -20,32 +19,35 @@
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/defaults.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/view_id_util.h"
 #include "chrome/browser/instant/instant_controller.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
 #include "chrome/browser/ui/toolbar/toolbar_model.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/color_utils.h"
-#include "gfx/font.h"
-#include "gfx/gtk_util.h"
-#include "gfx/skia_utils_gtk.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "third_party/undoview/undo_view.h"
 #include "ui/base/animation/multi_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/skia_utils_gtk.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view_views.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "views/controls/textfield/native_textfield_views.h"
 #else
 #include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-#include "views/controls/native/native_view_host.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
 #endif
 
 namespace {
@@ -59,8 +61,8 @@
 const double kStrikethroughStrokeRed = 162.0 / 256.0;
 const double kStrikethroughStrokeWidth = 2.0;
 
-size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) {
-  return WideToUTF8(wide_text.substr(0, wide_text_offset)).size();
+size_t GetUTF8Offset(const string16& text, size_t text_offset) {
+  return UTF16ToUTF8(text.substr(0, text_offset)).size();
 }
 
 // Stores GTK+-specific state so it can be restored after switching tabs.
@@ -159,13 +161,6 @@
       instant_view_(NULL),
       instant_mark_(NULL),
       model_(new AutocompleteEditModel(this, controller, profile)),
-#if defined(TOOLKIT_VIEWS)
-      popup_view_(new AutocompletePopupContentsView(
-          gfx::Font(), this, model_.get(), profile, location_bar)),
-#else
-      popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile,
-                                               location_bar)),
-#endif
       controller_(controller),
       toolbar_model_(toolbar_model),
       command_updater_(command_updater),
@@ -184,16 +179,24 @@
       tab_was_pressed_(false),
       paste_clipboard_requested_(false),
       enter_was_inserted_(false),
-      enable_tab_to_search_(true),
       selection_suggested_(false),
       delete_was_pressed_(false),
       delete_at_end_pressed_(false),
       handling_key_press_(false),
       content_maybe_changed_by_key_press_(false),
+      update_popup_without_focus_(false),
 #if GTK_CHECK_VERSION(2, 20, 0)
       preedit_size_before_change_(0),
 #endif
       going_to_focus_(NULL) {
+  popup_view_.reset(
+#if defined(TOOLKIT_VIEWS)
+      new AutocompletePopupContentsView
+#else
+      new AutocompletePopupViewGtk
+#endif
+          (GetFont(), this, model_.get(), profile, location_bar));
+
   model_->SetPopupModel(popup_view_->GetModel());
 }
 
@@ -341,6 +344,8 @@
                          G_CALLBACK(&HandleUndoRedoAfterThunk), this);
   g_signal_connect_after(text_view_, "redo",
                          G_CALLBACK(&HandleUndoRedoAfterThunk), this);
+  g_signal_connect(text_view_, "destroy",
+                   G_CALLBACK(&gtk_widget_destroyed), &text_view_);
 
   // Setup for the Instant suggestion text view.
   // GtkLabel is used instead of GtkTextView to get transparent background.
@@ -417,6 +422,7 @@
 }
 
 void AutocompleteEditViewGtk::SetFocus() {
+  DCHECK(text_view_);
   gtk_widget_grab_focus(text_view_);
 }
 
@@ -425,12 +431,6 @@
   return -1;
 }
 
-gfx::Font AutocompleteEditViewGtk::GetFont() {
-  GtkRcStyle* rc_style = gtk_widget_get_modifier_style(text_view_);
-  return gfx::Font((rc_style && rc_style->font_desc) ?
-                   rc_style->font_desc : text_view_->style->font_desc);
-}
-
 AutocompleteEditModel* AutocompleteEditViewGtk::model() {
   return model_.get();
 }
@@ -455,7 +455,7 @@
 void AutocompleteEditViewGtk::Update(const TabContents* contents) {
   // NOTE: We're getting the URL text here from the ToolbarModel.
   bool visibly_changed_permanent_text =
-      model_->UpdatePermanentText(toolbar_model_->GetText());
+      model_->UpdatePermanentText(WideToUTF16Hack(toolbar_model_->GetText()));
 
   ToolbarModel::SecurityLevel security_level =
         toolbar_model_->GetSecurityLevel();
@@ -489,7 +489,7 @@
                                       PageTransition::Type transition,
                                       const GURL& alternate_nav_url,
                                       size_t selected_line,
-                                      const std::wstring& keyword) {
+                                      const string16& keyword) {
   if (!url.is_valid())
     return;
 
@@ -497,11 +497,11 @@
                   selected_line, keyword);
 }
 
-std::wstring AutocompleteEditViewGtk::GetText() const {
+string16 AutocompleteEditViewGtk::GetText() const {
   GtkTextIter start, end;
   GetTextBufferBounds(&start, &end);
   gchar* utf8 = gtk_text_buffer_get_text(text_buffer_, &start, &end, false);
-  std::wstring out(UTF8ToWide(utf8));
+  string16 out(UTF8ToUTF16(utf8));
   g_free(utf8);
 
 #if GTK_CHECK_VERSION(2, 20, 0)
@@ -527,12 +527,12 @@
       toolbar_model_->GetIcon();
 }
 
-void AutocompleteEditViewGtk::SetUserText(const std::wstring& text) {
+void AutocompleteEditViewGtk::SetUserText(const string16& text) {
   SetUserText(text, text, true);
 }
 
-void AutocompleteEditViewGtk::SetUserText(const std::wstring& text,
-                                          const std::wstring& display_text,
+void AutocompleteEditViewGtk::SetUserText(const string16& text,
+                                          const string16& display_text,
                                           bool update_popup) {
   model_->SetUserText(text);
   // TODO(deanm): something about selection / focus change here.
@@ -542,17 +542,17 @@
   TextChanged();
 }
 
-void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const std::wstring& text,
+void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const string16& text,
                                                        size_t caret_pos) {
   CharRange range(static_cast<int>(caret_pos), static_cast<int>(caret_pos));
   SetTextAndSelectedRange(text, range);
 }
 
 void AutocompleteEditViewGtk::SetForcedQuery() {
-  const std::wstring current_text(GetText());
-  const size_t start = current_text.find_first_not_of(kWhitespaceWide);
-  if (start == std::wstring::npos || (current_text[start] != '?')) {
-    SetUserText(L"?");
+  const string16 current_text(GetText());
+  const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
+  if (start == string16::npos || (current_text[start] != '?')) {
+    SetUserText(ASCIIToUTF16("?"));
   } else {
     StartUpdatingHighlightedText();
     SetSelectedRange(CharRange(current_text.size(), start + 1));
@@ -576,8 +576,8 @@
   return delete_at_end_pressed_;
 }
 
-void AutocompleteEditViewGtk::GetSelectionBounds(std::wstring::size_type* start,
-                                                 std::wstring::size_type* end) {
+void AutocompleteEditViewGtk::GetSelectionBounds(string16::size_type* start,
+                                                 string16::size_type* end) {
   CharRange selection = GetSelection();
   *start = static_cast<size_t>(selection.cp_min);
   *end = static_cast<size_t>(selection.cp_max);
@@ -598,17 +598,14 @@
 
 void AutocompleteEditViewGtk::UpdatePopup() {
   model_->SetInputInProgress(true);
-  if (!model_->has_focus())
+  if (!update_popup_without_focus_ && !model_->has_focus())
     return;
 
   // Don't inline autocomplete when the caret/selection isn't at the end of
   // the text, or in the middle of composition.
   CharRange sel = GetSelection();
   bool no_inline_autocomplete =
-      std::max(sel.cp_max, sel.cp_min) < GetTextLength();
-#if GTK_CHECK_VERSION(2, 20, 0)
-  no_inline_autocomplete = no_inline_autocomplete || preedit_.size();
-#endif
+      std::max(sel.cp_max, sel.cp_min) < GetTextLength() || IsImeComposing();
   model_->StartAutocomplete(sel.cp_min != sel.cp_max, no_inline_autocomplete);
 }
 
@@ -620,7 +617,7 @@
 }
 
 void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged(
-    const std::wstring& display_text,
+    const string16& display_text,
     bool save_original_selection) {
   if (save_original_selection)
     saved_temporary_selection_ = GetSelection();
@@ -632,7 +629,7 @@
 }
 
 bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged(
-    const std::wstring& display_text,
+    const string16& display_text,
     size_t user_text_length) {
   if (display_text == GetText())
     return false;
@@ -653,13 +650,10 @@
 }
 
 void AutocompleteEditViewGtk::OnBeforePossibleChange() {
-  // If this change is caused by a paste clipboard action and all text is
-  // selected, then call model_->on_paste_replacing_all() to prevent inline
-  // autocomplete.
+  // Record this paste, so we can do different behavior.
   if (paste_clipboard_requested_) {
     paste_clipboard_requested_ = false;
-    if (IsSelectAll())
-      model_->on_paste_replacing_all();
+    model_->on_paste();
   }
 
   // This method will be called in HandleKeyPress() method just before
@@ -699,12 +693,15 @@
 
   CharRange new_sel = GetSelection();
   int length = GetTextLength();
-  bool selection_differs = (new_sel.cp_min != sel_before_change_.cp_min) ||
-                           (new_sel.cp_max != sel_before_change_.cp_max);
+  bool selection_differs =
+      ((new_sel.cp_min != new_sel.cp_max) ||
+       (sel_before_change_.cp_min != sel_before_change_.cp_max)) &&
+      ((new_sel.cp_min != sel_before_change_.cp_min) ||
+       (new_sel.cp_max != sel_before_change_.cp_max));
   bool at_end_of_edit = (new_sel.cp_min == length && new_sel.cp_max == length);
 
   // See if the text or selection have changed since OnBeforePossibleChange().
-  std::wstring new_text(GetText());
+  string16 new_text(GetText());
   text_changed_ = (new_text != text_before_change_);
 #if GTK_CHECK_VERSION(2, 20, 0)
   text_changed_ =
@@ -726,8 +723,10 @@
 
   delete_at_end_pressed_ = false;
 
+  bool allow_keyword_ui_change = at_end_of_edit && !IsImeComposing();
   bool something_changed = model_->OnAfterPossibleChange(new_text,
-      selection_differs, text_changed_, just_deleted_text, at_end_of_edit);
+      selection_differs, text_changed_, just_deleted_text,
+      allow_keyword_ui_change);
 
   // If only selection was changed, we don't need to call |controller_|'s
   // OnChanged() method, which is called in TextChanged().
@@ -754,34 +753,44 @@
   return command_updater_;
 }
 
-#if defined(TOOLKIT_VIEWS)
-views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) {
-  views::NativeViewHost* host = new views::NativeViewHost;
-  parent->AddChildView(host);
-  host->set_focus_view(parent);
-  host->Attach(GetNativeView());
-  return host;
-}
-
-bool AutocompleteEditViewGtk::CommitInstantSuggestion(
-    const std::wstring& typed_text,
-    const std::wstring& suggestion) {
-  return CommitInstantSuggestion();
-}
-
-void AutocompleteEditViewGtk::EnableAccessibility() {
-  accessible_widget_helper_.reset(
-      new AccessibleWidgetHelper(text_view(), model_->profile()));
-  accessible_widget_helper_->SetWidgetName(
-      text_view(), l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION));
-}
-
 void AutocompleteEditViewGtk::SetInstantSuggestion(const string16& suggestion) {
-  SetInstantSuggestion(UTF16ToUTF8(suggestion));
-}
+  std::string suggestion_utf8 = UTF16ToUTF8(suggestion);
+
+  gtk_label_set_text(GTK_LABEL(instant_view_), suggestion_utf8.c_str());
+
+  StopAnimation();
+
+  if (suggestion.empty()) {
+    gtk_widget_hide(instant_view_);
+    return;
+  }
+  if (InstantController::IsEnabled(model_->profile())
+#if GTK_CHECK_VERSION(2, 20, 0)
+      && preedit_.empty()
 #endif
+      ) {
+    instant_animation_->set_delegate(this);
+    instant_animation_->Start();
+  }
+
+  gtk_widget_show(instant_view_);
+  AdjustVerticalAlignmentOfInstantView();
+  UpdateInstantViewColors();
+}
+
+string16 AutocompleteEditViewGtk::GetInstantSuggestion() const {
+  const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_));
+  return suggestion ? UTF8ToUTF16(suggestion) : string16();
+}
 
 int AutocompleteEditViewGtk::TextWidth() const {
+  // TextWidth may be called after gtk widget tree is destroyed but
+  // before AutocompleteEditViewGtk gets deleted.  This is a safe guard
+  // to avoid accessing |text_view_| that has already been destroyed.
+  // See crbug.com/70192.
+  if (!text_view_)
+    return 0;
+
   int horizontal_border_size =
       gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_),
                                            GTK_TEXT_WINDOW_LEFT) +
@@ -819,7 +828,30 @@
   return text_width + horizontal_border_size;
 }
 
+bool AutocompleteEditViewGtk::IsImeComposing() const {
+#if GTK_CHECK_VERSION(2, 20, 0)
+  return !preedit_.empty();
+#else
+  return false;
+#endif
+}
+
 #if defined(TOOLKIT_VIEWS)
+views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) {
+  views::NativeViewHost* host = new views::NativeViewHost;
+  parent->AddChildView(host);
+  host->set_focus_view(parent);
+  host->Attach(GetNativeView());
+  return host;
+}
+
+void AutocompleteEditViewGtk::EnableAccessibility() {
+  accessible_widget_helper_.reset(
+      new AccessibleWidgetHelper(text_view(), model_->profile()));
+  accessible_widget_helper_->SetWidgetName(
+      text_view(), l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION));
+}
+
 // static
 AutocompleteEditView* AutocompleteEditViewGtk::Create(
     AutocompleteEditController* controller,
@@ -828,6 +860,18 @@
     CommandUpdater* command_updater,
     bool popup_window_mode,
     const views::View* location_bar) {
+  if (views::NativeTextfieldViews::IsTextfieldViewsEnabled()) {
+    AutocompleteEditViewViews* autocomplete =
+        new AutocompleteEditViewViews(controller,
+                                      toolbar_model,
+                                      profile,
+                                      command_updater,
+                                      popup_window_mode,
+                                      location_bar);
+    autocomplete->Init();
+    return autocomplete;
+  }
+
   AutocompleteEditViewGtk* autocomplete =
       new AutocompleteEditViewGtk(controller,
                                   toolbar_model,
@@ -859,7 +903,7 @@
 }
 
 void AutocompleteEditViewGtk::AnimationEnded(const ui::Animation* animation) {
-  controller_->OnCommitSuggestedText(GetText());
+  controller_->OnCommitSuggestedText(false);
 }
 
 void AutocompleteEditViewGtk::AnimationProgressed(
@@ -873,12 +917,13 @@
 }
 
 void AutocompleteEditViewGtk::SetBaseColor() {
+  DCHECK(text_view_);
+
 #if defined(TOOLKIT_VIEWS)
   bool use_gtk = false;
 #else
   bool use_gtk = theme_provider_->UseGtkTheme();
 #endif
-
   if (use_gtk) {
     gtk_widget_modify_cursor(text_view_, NULL, NULL);
     gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, NULL);
@@ -937,15 +982,8 @@
 #endif
 
     // Until we switch to vector graphics, force the font size.
-    gtk_util::ForceFontSizePixels(text_view_,
-        popup_window_mode_ ?
-        browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
-        browser_defaults::kAutocompleteEditFontPixelSize);
-
-    gtk_util::ForceFontSizePixels(instant_view_,
-        popup_window_mode_ ?
-        browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
-        browser_defaults::kAutocompleteEditFontPixelSize);
+    gtk_util::ForceFontSizePixels(text_view_, GetFont().GetFontSize());
+    gtk_util::ForceFontSizePixels(instant_view_, GetFont().GetFontSize());
 
     g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL);
     g_object_set(normal_text_tag_, "foreground", "#000000", NULL);
@@ -1194,6 +1232,8 @@
   if (event->type != GDK_BUTTON_PRESS)
     return FALSE;
 
+  DCHECK(text_view_);
+
   if (event->button == 1) {
 #if defined(OS_CHROMEOS)
     // When the first button is pressed, track some stuff that will help us
@@ -1221,6 +1261,8 @@
   if (event->button != 1)
     return FALSE;
 
+  DCHECK(text_view_);
+
 #if defined(OS_CHROMEOS)
   button_1_pressed_ = false;
 #endif
@@ -1254,6 +1296,9 @@
 
 gboolean AutocompleteEditViewGtk::HandleViewFocusIn(GtkWidget* sender,
                                                     GdkEventFocus* event) {
+  DCHECK(text_view_);
+  update_popup_without_focus_ = false;
+
   GdkModifierType modifiers;
   gdk_window_get_pointer(text_view_->window, NULL, NULL, &modifiers);
   model_->OnSetFocus((modifiers & GDK_CONTROL_MASK) != 0);
@@ -1272,6 +1317,7 @@
 
 gboolean AutocompleteEditViewGtk::HandleViewFocusOut(GtkWidget* sender,
                                                      GdkEventFocus* event) {
+  DCHECK(text_view_);
   GtkWidget* view_getting_focus = NULL;
   GtkWindow* toplevel = platform_util::GetTopLevel(sender);
   if (gtk_window_is_active(toplevel))
@@ -1298,6 +1344,7 @@
     GtkMovementStep step,
     gint count,
     gboolean extend_selection) {
+  DCHECK(text_view_);
   GtkTextIter sel_start, sel_end;
   gboolean has_selection =
       gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end);
@@ -1305,9 +1352,6 @@
 
   if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection &&
       (count == 1 || count == -1)) {
-    gint cursor_pos;
-    g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, NULL);
-
     // We need to take the content direction into account when handling cursor
     // movement, because the behavior of Left and Right key will be inverted if
     // the direction is RTL. Although we should check the direction around the
@@ -1330,8 +1374,8 @@
           text_buffer_, count == count_towards_end ? &sel_end : &sel_start);
       OnAfterPossibleChange();
       handled = true;
-    } else if (count == count_towards_end && cursor_pos == GetTextLength()) {
-      handled = controller_->OnCommitSuggestedText(GetText());
+    } else if (count == count_towards_end && !IsCaretAtEnd()) {
+      handled = controller_->OnCommitSuggestedText(true);
     }
   } else if (step == GTK_MOVEMENT_PAGES) {  // Page up and down.
     // Multiply by count for the direction (if we move too much that's ok).
@@ -1370,6 +1414,15 @@
   req->width = 1;
 }
 
+void AutocompleteEditViewGtk::HandlePopupMenuDeactivate(GtkWidget* sender) {
+  // When the context menu appears, |text_view_|'s focus is lost. After an item
+  // is activated, the focus comes back to |text_view_|, but only after the
+  // check in UpdatePopup(). We set this flag to make UpdatePopup() aware that
+  // it will be receiving focus again.
+  if (!model_->has_focus())
+    update_popup_without_focus_ = true;
+}
+
 void AutocompleteEditViewGtk::HandlePopulatePopup(GtkWidget* sender,
                                                   GtkMenu* menu) {
   GtkWidget* separator = gtk_separator_menu_item_new();
@@ -1393,7 +1446,7 @@
   // back after shutdown, and similar issues.
   GtkClipboard* x_clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
   gchar* text = gtk_clipboard_wait_for_text(x_clipboard);
-  std::wstring text_wstr = UTF8ToWide(text);
+  string16 text_wstr = UTF8ToUTF16(text ? text : "");
   g_free(text);
 
   // Paste and Go menu item.
@@ -1407,6 +1460,9 @@
   gtk_widget_set_sensitive(paste_go_menuitem,
                            model_->CanPasteAndGo(text_wstr));
   gtk_widget_show(paste_go_menuitem);
+
+  g_signal_connect(menu, "deactivate",
+                   G_CALLBACK(HandlePopupMenuDeactivateThunk), this);
 }
 
 void AutocompleteEditViewGtk::HandleEditSearchEngines(GtkWidget* sender) {
@@ -1475,6 +1531,8 @@
 void AutocompleteEditViewGtk::HandleDragDataReceived(
     GtkWidget* sender, GdkDragContext* context, gint x, gint y,
     GtkSelectionData* selection_data, guint target_type, guint time) {
+  DCHECK(text_view_);
+
   // Reset |paste_clipboard_requested_| to make sure we won't misinterpret this
   // drop action as a paste action.
   paste_clipboard_requested_ = false;
@@ -1488,7 +1546,7 @@
   if (!text)
     return;
 
-  std::wstring possible_url = UTF8ToWide(reinterpret_cast<char*>(text));
+  string16 possible_url = UTF8ToUTF16(reinterpret_cast<char*>(text));
   g_free(text);
   if (model_->CanPasteAndGo(CollapseWhitespace(possible_url, true))) {
     model_->PasteAndGo();
@@ -1506,6 +1564,7 @@
     GtkSelectionData* selection_data,
     guint target_type,
     guint time) {
+  DCHECK(text_view_);
   // If GTK put the normal textual version of the selection in our drag data,
   // put our doctored selection that might have the 'http://' prefix. Also, GTK
   // is confused about signedness of its datatypes, leading to the weird switch
@@ -1569,6 +1628,8 @@
   if (model_->is_keyword_hint() || model_->keyword().empty())
     return;  // Propgate into GtkTextView.
 
+  DCHECK(text_view_);
+
   GtkTextIter sel_start, sel_end;
   // Checks if there is some text selected.
   if (gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end))
@@ -1599,20 +1660,29 @@
   bool handled = false;
 
   // Trigger Tab to search behavior only when Tab key is pressed.
-  if (model_->is_keyword_hint() && !model_->keyword().empty()) {
-    if (enable_tab_to_search_) {
-      model_->AcceptKeyword();
+  if (model_->is_keyword_hint())
+    handled = model_->AcceptKeyword();
+
+#if GTK_CHECK_VERSION(2, 20, 0)
+  if (!handled && !preedit_.empty())
+    handled = true;
+#endif
+
+  if (!handled && GTK_WIDGET_VISIBLE(instant_view_))
+    handled = controller_->OnCommitSuggestedText(true);
+
+  if (!handled) {
+    if (!IsCaretAtEnd()) {
+      OnBeforePossibleChange();
+      PlaceCaretAt(GetTextLength());
+      OnAfterPossibleChange();
       handled = true;
     }
-  } else {
-    if (GTK_WIDGET_VISIBLE(instant_view_)) {
-      controller_->OnCommitSuggestedText(GetText());
-      handled = true;
-    } else {
-      handled = controller_->AcceptCurrentInstantPreview();
-    }
   }
 
+  if (!handled)
+    handled = controller_->AcceptCurrentInstantPreview();
+
   if (handled) {
     static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET);
     g_signal_stop_emission(widget, signal_id, 0);
@@ -1628,6 +1698,8 @@
 }
 
 void AutocompleteEditViewGtk::HandleCopyOrCutClipboard(bool copy) {
+  DCHECK(text_view_);
+
   // On copy or cut, we manually update the PRIMARY selection to contain the
   // highlighted text.  This matches Firefox -- we highlight the URL but don't
   // update PRIMARY on Ctrl-L, so Ctrl-L, Ctrl-C and then middle-click is a
@@ -1642,15 +1714,14 @@
 
   CharRange selection = GetSelection();
   GURL url;
-  std::wstring text(UTF8ToWide(GetSelectedText()));
+  string16 text(UTF8ToUTF16(GetSelectedText()));
   bool write_url;
   model_->AdjustTextForCopy(selection.selection_min(), IsSelectAll(), &text,
                             &url, &write_url);
 
   if (write_url) {
-    string16 text16(WideToUTF16(text));
     BookmarkNodeData data;
-    data.ReadFromTuple(url, text16);
+    data.ReadFromTuple(url, text);
     data.WriteToClipboard(NULL);
 
     // Stop propagating the signal.
@@ -1666,7 +1737,38 @@
       gtk_text_buffer_delete_selection(text_buffer_, true, true);
   }
 
-  OwnPrimarySelection(WideToUTF8(text));
+  OwnPrimarySelection(UTF16ToUTF8(text));
+}
+
+gfx::Font AutocompleteEditViewGtk::GetFont() {
+#if defined(TOOLKIT_VIEWS)
+  bool use_gtk = false;
+#else
+  bool use_gtk = theme_provider_->UseGtkTheme();
+#endif
+
+  if (use_gtk) {
+    // If we haven't initialized the text view yet, just create a temporary one
+    // whose style we can grab.
+    GtkWidget* widget = text_view_ ? text_view_ : gtk_text_view_new();
+    GtkRcStyle* rc_style = gtk_widget_get_modifier_style(widget);
+    gfx::Font font((rc_style && rc_style->font_desc) ?
+                   rc_style->font_desc :
+                   widget->style->font_desc);
+    if (!text_view_)
+      g_object_unref(g_object_ref_sink(widget));
+
+    // Scaling the font down for popup windows doesn't help here, since we just
+    // use the normal unforced font size when using the GTK theme.
+    return font;
+  } else {
+    return gfx::Font(
+        ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont).
+            GetFontName(),
+        popup_window_mode_ ?
+            browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
+            browser_defaults::kAutocompleteEditFontPixelSize);
+  }
 }
 
 void AutocompleteEditViewGtk::OwnPrimarySelection(const std::string& text) {
@@ -1718,6 +1820,7 @@
                                                     GdkEventExpose* expose) {
   if (strikethrough_.cp_min >= strikethrough_.cp_max)
     return FALSE;
+  DCHECK(text_view_);
 
   gfx::Rect expose_rect(expose->area);
 
@@ -1789,7 +1892,8 @@
   g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_);
 }
 
-AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() {
+AutocompleteEditViewGtk::CharRange
+  AutocompleteEditViewGtk::GetSelection() const {
   // You can not just use get_selection_bounds here, since the order will be
   // ascending, and you don't know where the user's start and end of the
   // selection was (if the selection was forwards or backwards).  Get the
@@ -1821,9 +1925,7 @@
 void AutocompleteEditViewGtk::ItersFromCharRange(const CharRange& range,
                                                  GtkTextIter* iter_min,
                                                  GtkTextIter* iter_max) {
-#if GTK_CHECK_VERSION(2, 20, 0)
-  DCHECK(preedit_.empty());
-#endif
+  DCHECK(!IsImeComposing());
   gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min);
   gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max);
 }
@@ -1840,6 +1942,18 @@
 #endif
 }
 
+void AutocompleteEditViewGtk::PlaceCaretAt(int pos) {
+  GtkTextIter cursor;
+  gtk_text_buffer_get_iter_at_offset(text_buffer_, &cursor, pos);
+  gtk_text_buffer_place_cursor(text_buffer_, &cursor);
+}
+
+bool AutocompleteEditViewGtk::IsCaretAtEnd() const {
+  const CharRange selection = GetSelection();
+  return selection.cp_min == selection.cp_max &&
+      selection.cp_min == GetTextLength();
+}
+
 void AutocompleteEditViewGtk::EmphasizeURLComponents() {
 #if GTK_CHECK_VERSION(2, 20, 0)
   // We can't change the text style easily, if the preedit string (the text
@@ -1859,7 +1973,7 @@
   // be treated as a search or a navigation, and is the same method the Paste
   // And Go system uses.
   url_parse::Component scheme, host;
-  std::wstring text(GetText());
+  string16 text(GetText());
   AutocompleteInput::ParseForEmphasizeComponents(
       text, model_->GetDesiredTLD(), &scheme, &host);
   const bool emphasize = model_->CurrentTextIsURL() && (host.len > 0);
@@ -1908,31 +2022,6 @@
   }
 }
 
-void AutocompleteEditViewGtk::SetInstantSuggestion(
-    const std::string& suggestion) {
-  gtk_label_set_text(GTK_LABEL(instant_view_), suggestion.c_str());
-
-  StopAnimation();
-
-  if (suggestion.empty()) {
-    gtk_widget_hide(instant_view_);
-  } else {
-    if (InstantController::IsEnabled(model_->profile(),
-                                     InstantController::PREDICTIVE_TYPE)
-#if GTK_CHECK_VERSION(2, 20, 0)
-        && preedit_.empty()
-#endif
-        ) {
-      instant_animation_->set_delegate(this);
-      instant_animation_->Start();
-    }
-
-    gtk_widget_show(instant_view_);
-    AdjustVerticalAlignmentOfInstantView();
-    UpdateInstantViewColors();
-  }
-}
-
 void AutocompleteEditViewGtk::StopAnimation() {
   // Clear the animation delegate so we don't get an AnimationEnded() callback.
   instant_animation_->set_delegate(NULL);
@@ -1940,16 +2029,6 @@
   UpdateInstantViewColors();
 }
 
-bool AutocompleteEditViewGtk::CommitInstantSuggestion() {
-  const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_));
-  if (!suggestion || !*suggestion)
-    return false;
-
-  model()->FinalizeInstantQuery(GetText(),
-                                UTF8ToWide(suggestion));
-  return true;
-}
-
 void AutocompleteEditViewGtk::TextChanged() {
   EmphasizeURLComponents();
   controller_->OnChanged();
@@ -1957,6 +2036,8 @@
 
 void AutocompleteEditViewGtk::SavePrimarySelection(
     const std::string& selected_text) {
+  DCHECK(text_view_);
+
   GtkClipboard* clipboard =
       gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
   DCHECK(clipboard);
@@ -1967,10 +2048,10 @@
       clipboard, selected_text.data(), selected_text.size());
 }
 
-void AutocompleteEditViewGtk::SetTextAndSelectedRange(const std::wstring& text,
+void AutocompleteEditViewGtk::SetTextAndSelectedRange(const string16& text,
                                                       const CharRange& range) {
   if (text != GetText()) {
-    std::string utf8 = WideToUTF8(text);
+    std::string utf8 = UTF16ToUTF8(text);
     gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length());
   }
   SetSelectedRange(range);
@@ -1989,6 +2070,8 @@
 }
 
 void AutocompleteEditViewGtk::AdjustTextJustification() {
+  DCHECK(text_view_);
+
   PangoDirection content_dir = GetContentDirection();
 
   // Use keymap direction if content does not have strong direction.
@@ -2136,7 +2219,7 @@
 }
 
 void AutocompleteEditViewGtk::UpdatePrimarySelectionIfValidURL() {
-  std::wstring text = UTF8ToWide(GetSelectedText());
+  string16 text = UTF8ToUTF16(GetSelectedText());
 
   if (text.empty())
     return;
@@ -2148,7 +2231,7 @@
   model_->AdjustTextForCopy(selection.selection_min(), IsSelectAll(), &text,
                             &url, &write_url);
   if (write_url) {
-    selected_text_ = WideToUTF8(text);
+    selected_text_ = UTF16ToUTF8(text);
     OwnPrimarySelection(selected_text_);
   }
 }
@@ -2166,7 +2249,7 @@
     // delete the selection range here explicitly. See http://crbug.com/18808.
     if (preedit_.empty())
       gtk_text_buffer_delete_selection(text_buffer_, false, true);
-    preedit_ = UTF8ToWide(preedit);
+    preedit_ = UTF8ToUTF16(preedit);
   } else {
     preedit_.clear();
   }
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
index 2397d26..615b137 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,19 +11,19 @@
 #include <algorithm>
 #include <string>
 
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
 #include "chrome/browser/ui/toolbar/toolbar_model.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/rect.h"
 #include "ui/base/animation/animation_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class AccessibleWidgetHelper;
@@ -89,9 +89,6 @@
   // LocationBarView::Layout as to why this uses -1.
   int WidthOfTextAfterCursor();
 
-  // Returns the font.
-  gfx::Font GetFont();
-
   // Implement the AutocompleteEditView interface.
   virtual AutocompleteEditModel* model();
   virtual const AutocompleteEditModel* model() const;
@@ -105,27 +102,27 @@
                        PageTransition::Type transition,
                        const GURL& alternate_nav_url,
                        size_t selected_line,
-                       const std::wstring& keyword);
+                       const string16& keyword);
 
-  virtual std::wstring GetText() const;
+  virtual string16 GetText() const;
 
   virtual bool IsEditingOrEmpty() const;
   virtual int GetIcon() const;
 
-  virtual void SetUserText(const std::wstring& text);
-  virtual void SetUserText(const std::wstring& text,
-                           const std::wstring& display_text,
+  virtual void SetUserText(const string16& text);
+  virtual void SetUserText(const string16& text,
+                           const string16& display_text,
                            bool update_popup);
 
-  virtual void SetWindowTextAndCaretPos(const std::wstring& text,
+  virtual void SetWindowTextAndCaretPos(const string16& text,
                                         size_t caret_pos);
 
   virtual void SetForcedQuery();
 
   virtual bool IsSelectAll();
   virtual bool DeleteAtEndPressed();
-  virtual void GetSelectionBounds(std::wstring::size_type* start,
-                                  std::wstring::size_type* end);
+  virtual void GetSelectionBounds(string16::size_type* start,
+                                  string16::size_type* end);
   virtual void SelectAll(bool reversed);
   virtual void RevertAll();
 
@@ -134,20 +131,22 @@
 
   virtual void SetFocus();
 
-  virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text,
+  virtual void OnTemporaryTextMaybeChanged(const string16& display_text,
                                            bool save_original_selection);
   virtual bool OnInlineAutocompleteTextMaybeChanged(
-      const std::wstring& display_text, size_t user_text_length);
+      const string16& display_text, size_t user_text_length);
   virtual void OnRevertTemporaryText();
   virtual void OnBeforePossibleChange();
   virtual bool OnAfterPossibleChange();
   virtual gfx::NativeView GetNativeView() const;
   virtual CommandUpdater* GetCommandUpdater();
+  virtual void SetInstantSuggestion(const string16& suggestion);
+  virtual string16 GetInstantSuggestion() const;
+  virtual int TextWidth() const;
+  virtual bool IsImeComposing() const;
+
 #if defined(TOOLKIT_VIEWS)
   virtual views::View* AddToView(views::View* parent);
-  virtual bool CommitInstantSuggestion(const std::wstring& typed_text,
-                                       const std::wstring& suggested_text);
-  virtual void SetInstantSuggestion(const string16& suggestion);
 
   // Enables accessibility on AutocompleteEditView.
   void EnableAccessibility();
@@ -163,7 +162,6 @@
                                       bool popup_window_mode,
                                       const views::View* location_bar);
 #endif
-  virtual int TextWidth() const;
 
   // Overridden from NotificationObserver:
   virtual void Observe(NotificationType type,
@@ -181,16 +179,8 @@
   // the animation state.
   void UpdateInstantViewColors();
 
-  void SetInstantSuggestion(const std::string& suggestion);
-  bool CommitInstantSuggestion();
-
-  // Used by LocationBarViewGtk to inform AutocompleteEditViewGtk if the tab to
-  // search should be enabled or not. See the comment of |enable_tab_to_search_|
-  // for details.
-  void set_enable_tab_to_search(bool enable) {
-    enable_tab_to_search_ = enable;
-  }
-
+  // Returns the text view gtk widget. May return NULL if the widget
+  // has already been destroyed.
   GtkWidget* text_view() {
     return text_view_;
   }
@@ -271,6 +261,10 @@
   CHROMEG_CALLBACK_1(AutocompleteEditViewGtk, void, HandleWindowSetFocus,
                      GtkWindow*, GtkWidget*);
 
+  // Callback function called after context menu is closed.
+  CHROMEGTK_CALLBACK_0(AutocompleteEditViewGtk, void,
+                       HandlePopupMenuDeactivate);
+
   // Callback for the PRIMARY selection clipboard.
   static void ClipboardGetSelectionThunk(GtkClipboard* clipboard,
                                          GtkSelectionData* selection_data,
@@ -282,6 +276,9 @@
 
   void HandleCopyOrCutClipboard(bool copy);
 
+  // Returns the font used in |text_view_|.
+  gfx::Font GetFont();
+
   // Take control of the PRIMARY selection clipboard with |text|. Use
   // |text_buffer_| as the owner, so that this doesn't remove the selection on
   // it. This makes use of the above callbacks.
@@ -308,7 +305,7 @@
 
   // Get the character indices of the current selection.  This honors
   // direction, cp_max is the insertion point, and cp_min is the bound.
-  CharRange GetSelection();
+  CharRange GetSelection() const;
 
   // Translate from character positions to iterators for the current buffer.
   void ItersFromCharRange(const CharRange& range,
@@ -318,6 +315,12 @@
   // Return the number of characers in the current buffer.
   int GetTextLength() const;
 
+  // Places the caret at the given position. This clears any selection.
+  void PlaceCaretAt(int pos);
+
+  // Returns true if the caret is at the end of the content.
+  bool IsCaretAtEnd() const;
+
   // Try to parse the current text as a URL and colorize the components.
   void EmphasizeURLComponents();
 
@@ -329,7 +332,7 @@
   void SavePrimarySelection(const std::string& selected_text);
 
   // Update the field with |text| and set the selection.
-  void SetTextAndSelectedRange(const std::wstring& text,
+  void SetTextAndSelectedRange(const string16& text,
                                const CharRange& range);
 
   // Set the selection to |range|.
@@ -369,7 +372,10 @@
   // since the height will change based on the font / font size, etc.
   OwnedWidgetGtk alignment_;
 
-  // The actual text entry which will be owned by the alignment_.
+  // The actual text entry which will be owned by the alignment_.  The
+  // reference will be set to NULL upon destruction to tell if the gtk
+  // widget tree has been destroyed. This is because gtk destroies child
+  // widgets if the parent (alignemtn_)'s refcount does not go down to 0.
   GtkWidget* text_view_;
 
   GtkTextTagTable* tag_table_;
@@ -414,7 +420,7 @@
   CharRange saved_temporary_selection_;
 
   // Tracking state before and after a possible change.
-  std::wstring text_before_change_;
+  string16 text_before_change_;
   CharRange sel_before_change_;
 
   // The most-recently-selected text from the entry that was copied to the
@@ -494,11 +500,6 @@
   // is needed.
   CharRange strikethrough_;
 
-  // Indicate if the tab to search should be enabled or not. It's true by
-  // default and will only be set to false if the location bar view is not able
-  // to show the tab to search hint.
-  bool enable_tab_to_search_;
-
   // Indicates if the selected text is suggested text or not. If the selection
   // is not suggested text, that means the user manually made the selection.
   bool selection_suggested_;
@@ -520,9 +521,14 @@
   // flag.
   bool content_maybe_changed_by_key_press_;
 
+  // Set this flag to call UpdatePopup() in lost focus and need to update.
+  // Because context menu might take the focus, before setting the flag, check
+  // the focus with model_->has_focus().
+  bool update_popup_without_focus_;
+
 #if GTK_CHECK_VERSION(2, 20, 0)
   // Stores the text being composed by the input method.
-  std::wstring preedit_;
+  string16 preedit_;
 
   // Tracking preedit state before and after a possible change. We don't need to
   // track preedit_'s content, as it'll be treated as part of text content.
@@ -533,7 +539,7 @@
   // "focus-out" events.
   GtkWidget* going_to_focus_;
 
-  GtkSignalRegistrar signals_;
+  ui::GtkSignalRegistrar signals_;
 
 #if defined(TOOLKIT_VIEWS)
   scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
index d486cc5..3ba5963 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
@@ -15,10 +15,13 @@
 
 class AutocompleteEditController;
 class AutocompletePopupViewMac;
-class Clipboard;
 class Profile;
 class ToolbarModel;
 
+namespace ui {
+class Clipboard;
+}
+
 // Implements AutocompleteEditView on an AutocompleteTextField.
 
 class AutocompleteEditViewMac : public AutocompleteEditView,
@@ -43,43 +46,47 @@
                        PageTransition::Type transition,
                        const GURL& alternate_nav_url,
                        size_t selected_line,
-                       const std::wstring& keyword);
+                       const string16& keyword);
 
-  virtual std::wstring GetText() const;
+  virtual string16 GetText() const;
 
   virtual bool IsEditingOrEmpty() const;
   virtual int GetIcon() const;
 
-  virtual void SetUserText(const std::wstring& text);
-  virtual void SetUserText(const std::wstring& text,
-                           const std::wstring& display_text,
+  virtual void SetUserText(const string16& text);
+  virtual void SetUserText(const string16& text,
+                           const string16& display_text,
                            bool update_popup);
 
-  virtual void SetWindowTextAndCaretPos(const std::wstring& text,
+  virtual void SetWindowTextAndCaretPos(const string16& text,
                                         size_t caret_pos);
 
   virtual void SetForcedQuery();
 
   virtual bool IsSelectAll();
   virtual bool DeleteAtEndPressed();
-  virtual void GetSelectionBounds(std::wstring::size_type* start,
-                                  std::wstring::size_type* end);
+  virtual void GetSelectionBounds(string16::size_type* start,
+                                  string16::size_type* end);
 
   virtual void SelectAll(bool reversed);
   virtual void RevertAll();
   virtual void UpdatePopup();
   virtual void ClosePopup();
   virtual void SetFocus();
-  virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text,
+  virtual void OnTemporaryTextMaybeChanged(const string16& display_text,
                                            bool save_original_selection);
   virtual bool OnInlineAutocompleteTextMaybeChanged(
-      const std::wstring& display_text, size_t user_text_length);
+      const string16& display_text, size_t user_text_length);
   virtual void OnStartingIME();
   virtual void OnRevertTemporaryText();
   virtual void OnBeforePossibleChange();
   virtual bool OnAfterPossibleChange();
   virtual gfx::NativeView GetNativeView() const;
   virtual CommandUpdater* GetCommandUpdater();
+  virtual void SetInstantSuggestion(const string16& input);
+  virtual string16 GetInstantSuggestion() const;
+  virtual int TextWidth() const;
+  virtual bool IsImeComposing() const;
 
   // Implement the AutocompleteTextFieldObserver interface.
   virtual NSRange SelectionRangeForProposedRange(NSRange proposed_range);
@@ -98,16 +105,12 @@
   virtual void OnSetFocus(bool control_down);
   virtual void OnKillFocus();
 
-  // Suggest text should be in the model, but for now, it's here.
-  void SetSuggestText(const string16& suggest_text);
-  bool CommitSuggestText();
-
   // Helper for LocationBarViewMac.  Optionally selects all in |field_|.
   void FocusLocation(bool select_all);
 
   // Helper to get appropriate contents from |clipboard|.  Returns
   // empty string if no appropriate data is found on |clipboard|.
-  static std::wstring GetClipboardText(Clipboard* clipboard);
+  static string16 GetClipboardText(ui::Clipboard* clipboard);
 
   // Helper to get the font to use in the field, exposed for the
   // popup.
@@ -128,6 +131,10 @@
   // field has focus.
   NSRange GetSelectedRange() const;
 
+  // Returns the field's currently marked range. Only valid if the field has
+  // focus.
+  NSRange GetMarkedRange() const;
+
   // Returns true if |field_| is first-responder in the window.  Used
   // in various DCHECKS to make sure code is running in appropriate
   // situations.
@@ -139,19 +146,22 @@
 
   // Update the field with |display_text| and highlight the host and scheme (if
   // it's an URL or URL-fragment).  Resets any suggest text that may be present.
-  void SetText(const std::wstring& display_text);
+  void SetText(const string16& display_text);
 
   // Internal implementation of SetText.  Does not reset the suggest text before
   // setting the display text.  Most callers should use |SetText()| instead.
-  void SetTextInternal(const std::wstring& display_text);
+  void SetTextInternal(const string16& display_text);
 
   // Update the field with |display_text| and set the selection.
-  void SetTextAndSelectedRange(const std::wstring& display_text,
+  void SetTextAndSelectedRange(const string16& display_text,
                                const NSRange range);
 
   // Returns the non-suggest portion of |field_|'s string value.
   NSString* GetNonSuggestTextSubstring() const;
 
+  // Returns the suggest portion of |field_|'s string value.
+  NSString* GetSuggestTextSubstring() const;
+
   // Pass the current content of |field_| to SetText(), maintaining
   // any selection.  Named to be consistent with GTK and Windows,
   // though here we cannot really do the in-place operation they do.
@@ -159,9 +169,19 @@
 
   // Calculates text attributes according to |display_text| and applies them
   // to the given |as| object.
-  void ApplyTextAttributes(const std::wstring& display_text,
+  void ApplyTextAttributes(const string16& display_text,
                            NSMutableAttributedString* as);
 
+  // Return the number of UTF-16 units in the current buffer, excluding the
+  // suggested text.
+  NSUInteger GetTextLength() const;
+
+  // Places the caret at the given position. This clears any selection.
+  void PlaceCaretAt(NSUInteger pos);
+
+  // Returns true if the caret is at the end of the content.
+  bool IsCaretAtEnd() const;
+
   scoped_ptr<AutocompleteEditModel> model_;
   scoped_ptr<AutocompletePopupViewMac> popup_view_;
 
@@ -181,7 +201,8 @@
   // Tracking state before and after a possible change for reporting
   // to model_.
   NSRange selection_before_change_;
-  std::wstring text_before_change_;
+  string16 text_before_change_;
+  NSRange marked_range_before_change_;
 
   // Length of the suggest text.  The suggest text always appears at the end of
   // the field.
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
index ce2c0f1..759de98 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
@@ -6,10 +6,7 @@
 
 #include <Carbon/Carbon.h>  // kVK_Return
 
-#include "app/clipboard/clipboard.h"
-#include "app/clipboard/scoped_clipboard_writer.h"
 #include "app/mac/nsimage_cache.h"
-#include "app/resource_bundle.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -25,6 +22,9 @@
 #include "grit/theme_resources.h"
 #include "net/base/escape.h"
 #import "third_party/mozilla/NSPasteboard+Utils.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/rect.h"
 
 // Focus-handling between |field_| and |model_| is a bit subtle.
 // Other platforms detect change of focus, which is inconvenient
@@ -137,7 +137,6 @@
     case IDR_OMNIBOX_SEARCH: image_name = @"omnibox_search.pdf"; break;
     case IDR_OMNIBOX_HTTP: image_name = @"omnibox_http.pdf"; break;
     case IDR_OMNIBOX_HISTORY: image_name = @"omnibox_history.pdf"; break;
-    case IDR_OMNIBOX_MORE: image_name = @"omnibox_more.pdf"; break;
 
     // Values from |ToolbarModel::GetIcon()|.
     case IDR_OMNIBOX_HTTPS_VALID:
@@ -218,7 +217,7 @@
   } else {
     // If we are not focussed, there is no selection.  Manufacture
     // something reasonable in case it starts to matter in the future.
-    range = NSMakeRange(0, [[field_ stringValue] length]);
+    range = NSMakeRange(0, GetTextLength());
   }
 
   AutocompleteEditViewMacState state(model_->GetStateForTabSwitch(),
@@ -234,7 +233,7 @@
   // this is.  Maybe this method should be refactored into more
   // specific cases.
   const bool user_visible =
-      model_->UpdatePermanentText(toolbar_model_->GetText());
+      model_->UpdatePermanentText(WideToUTF16Hack(toolbar_model_->GetText()));
 
   if (tab_for_state_restoring) {
     RevertAll();
@@ -281,7 +280,7 @@
                                       PageTransition::Type transition,
                                       const GURL& alternate_nav_url,
                                       size_t selected_line,
-                                      const std::wstring& keyword) {
+                                      const string16& keyword) {
   // TODO(shess): Why is the caller passing an invalid url in the
   // first place?  Make sure that case isn't being dropped on the
   // floor.
@@ -293,13 +292,12 @@
                   selected_line, keyword);
 }
 
-std::wstring AutocompleteEditViewMac::GetText() const {
-  return base::SysNSStringToWide(GetNonSuggestTextSubstring());
+string16 AutocompleteEditViewMac::GetText() const {
+  return base::SysNSStringToUTF16(GetNonSuggestTextSubstring());
 }
 
 bool AutocompleteEditViewMac::IsEditingOrEmpty() const {
-  return model_->user_input_in_progress() ||
-      ([[field_ stringValue] length] == 0);
+  return model_->user_input_in_progress() || !GetTextLength();
 }
 
 int AutocompleteEditViewMac::GetIcon() const {
@@ -308,12 +306,12 @@
       toolbar_model_->GetIcon();
 }
 
-void AutocompleteEditViewMac::SetUserText(const std::wstring& text) {
+void AutocompleteEditViewMac::SetUserText(const string16& text) {
   SetUserText(text, text, true);
 }
 
-void AutocompleteEditViewMac::SetUserText(const std::wstring& text,
-                                          const std::wstring& display_text,
+void AutocompleteEditViewMac::SetUserText(const string16& text,
+                                          const string16& display_text,
                                           bool update_popup) {
   model_->SetUserText(text);
   // TODO(shess): TODO below from gtk.
@@ -326,10 +324,14 @@
 }
 
 NSRange AutocompleteEditViewMac::GetSelectedRange() const {
-  DCHECK([field_ currentEditor]);
   return [[field_ currentEditor] selectedRange];
 }
 
+NSRange AutocompleteEditViewMac::GetMarkedRange() const {
+  DCHECK([field_ currentEditor]);
+  return [(NSTextView*)[field_ currentEditor] markedRange];
+}
+
 void AutocompleteEditViewMac::SetSelectedRange(const NSRange range) {
   // This can be called when we don't have focus.  For instance, when
   // the user clicks the "Go" button.
@@ -348,7 +350,7 @@
   }
 }
 
-void AutocompleteEditViewMac::SetWindowTextAndCaretPos(const std::wstring& text,
+void AutocompleteEditViewMac::SetWindowTextAndCaretPos(const string16& text,
                                                        size_t caret_pos) {
   DCHECK_LE(caret_pos, text.size());
   SetTextAndSelectedRange(text, NSMakeRange(caret_pos, caret_pos));
@@ -358,10 +360,10 @@
   // We need to do this first, else |SetSelectedRange()| won't work.
   FocusLocation(true);
 
-  const std::wstring current_text(GetText());
-  const size_t start = current_text.find_first_not_of(kWhitespaceWide);
-  if (start == std::wstring::npos || (current_text[start] != '?')) {
-    SetUserText(L"?");
+  const string16 current_text(GetText());
+  const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
+  if (start == string16::npos || (current_text[start] != '?')) {
+    SetUserText(ASCIIToUTF16("?"));
   } else {
     NSRange range = NSMakeRange(start + 1, current_text.size() - start - 1);
     [[field_ currentEditor] setSelectedRange:range];
@@ -371,7 +373,7 @@
 bool AutocompleteEditViewMac::IsSelectAll() {
   if (![field_ currentEditor])
     return true;
-  const NSRange all_range = NSMakeRange(0, GetText().length());
+  const NSRange all_range = NSMakeRange(0, GetTextLength());
   return NSEqualRanges(all_range, GetSelectedRange());
 }
 
@@ -379,8 +381,8 @@
   return delete_at_end_pressed_;
 }
 
-void AutocompleteEditViewMac::GetSelectionBounds(std::wstring::size_type* start,
-                                                 std::wstring::size_type* end) {
+void AutocompleteEditViewMac::GetSelectionBounds(string16::size_type* start,
+                                                 string16::size_type* end) {
   if (![field_ currentEditor]) {
     *start = *end = 0;
     return;
@@ -398,18 +400,12 @@
 
   // TODO(shess): Verify that we should be stealing focus at this
   // point.
-  SetSelectedRange(NSMakeRange(0, GetText().length()));
+  SetSelectedRange(NSMakeRange(0, GetTextLength()));
 }
 
 void AutocompleteEditViewMac::RevertAll() {
   ClosePopup();
   model_->Revert();
-
-  // TODO(shess): This should be a no-op, the results from GetText()
-  // could only get there via UpdateAndStyleText() in the first place.
-  // Dig into where this code can be called from and see if this line
-  // can be removed.
-  EmphasizeURLComponents();
   controller_->OnChanged();
   [field_ clearUndoChain];
 }
@@ -425,20 +421,8 @@
   //   * The caret/selection isn't at the end of the text
   //   * The user has just pasted in something that replaced all the text
   //   * The user is trying to compose something in an IME
-  bool prevent_inline_autocomplete = false;
-  NSTextView* editor = (NSTextView*)[field_ currentEditor];
-  if (editor) {
-    if ([editor hasMarkedText])
-      prevent_inline_autocomplete = true;
-
-    if (NSMaxRange([editor selectedRange]) <
-        [[editor textStorage] length] - suggest_text_length_) {
-      prevent_inline_autocomplete = true;
-    }
-  }
-
-  model_->StartAutocomplete([editor selectedRange].length != 0,
-                            prevent_inline_autocomplete);
+  model_->StartAutocomplete(GetSelectedRange().length != 0,
+                            IsImeComposing() || !IsCaretAtEnd());
 }
 
 void AutocompleteEditViewMac::ClosePopup() {
@@ -451,50 +435,15 @@
 void AutocompleteEditViewMac::SetFocus() {
 }
 
-void AutocompleteEditViewMac::SetSuggestText(const string16& suggest_text) {
-  NSString* text = GetNonSuggestTextSubstring();
-  bool needs_update = (suggest_text_length_ > 0);
-
-  // Append the new suggest text.
-  suggest_text_length_ = suggest_text.length();
-  if (suggest_text_length_ > 0) {
-    text = [text stringByAppendingString:base::SysUTF16ToNSString(
-               suggest_text)];
-    needs_update = true;
-  }
-
-  if (needs_update) {
-    NSRange current_range = GetSelectedRange();
-    SetTextInternal(base::SysNSStringToWide(text));
-    if (NSMaxRange(current_range) <= [text length] - suggest_text_length_)
-      SetSelectedRange(current_range);
-    else
-      SetSelectedRange(NSMakeRange([text length] - suggest_text_length_, 0));
-  }
-}
-
-bool AutocompleteEditViewMac::CommitSuggestText() {
-  if (suggest_text_length_ == 0)
-    return false;
-
-  std::wstring input_text(GetText());
-  suggest_text_length_ = 0;
-  std::wstring text(GetText());
-  // Call SetText() to force a redraw and move the cursor to the end.
-  SetText(text);
-  model()->FinalizeInstantQuery(input_text, text.substr(input_text.size()));
-  return true;
-}
-
-void AutocompleteEditViewMac::SetText(const std::wstring& display_text) {
+void AutocompleteEditViewMac::SetText(const string16& display_text) {
   // If we are setting the text directly, there cannot be any suggest text.
   suggest_text_length_ = 0;
   SetTextInternal(display_text);
 }
 
 void AutocompleteEditViewMac::SetTextInternal(
-    const std::wstring& display_text) {
-  NSString* ss = base::SysWideToNSString(display_text);
+    const string16& display_text) {
+  NSString* ss = base::SysUTF16ToNSString(display_text);
   NSMutableAttributedString* as =
       [[[NSMutableAttributedString alloc] initWithString:ss] autorelease];
 
@@ -520,7 +469,7 @@
 }
 
 void AutocompleteEditViewMac::SetTextAndSelectedRange(
-    const std::wstring& display_text, const NSRange range) {
+    const string16& display_text, const NSRange range) {
   SetText(display_text);
   SetSelectedRange(range);
 }
@@ -536,6 +485,16 @@
   return text;
 }
 
+NSString* AutocompleteEditViewMac::GetSuggestTextSubstring() const {
+  if (suggest_text_length_ == 0)
+    return nil;
+
+  NSString* text = [field_ stringValue];
+  NSUInteger length = [text length];
+  DCHECK_LE(suggest_text_length_, length);
+  return [text substringFromIndex:(length - suggest_text_length_)];
+}
+
 void AutocompleteEditViewMac::EmphasizeURLComponents() {
   NSTextView* editor = (NSTextView*)[field_ currentEditor];
   // If the autocomplete text field is in editing mode, then we can just change
@@ -557,7 +516,7 @@
 }
 
 void AutocompleteEditViewMac::ApplyTextAttributes(
-    const std::wstring& display_text, NSMutableAttributedString* as) {
+    const string16& display_text, NSMutableAttributedString* as) {
   [as addAttribute:NSFontAttributeName value:GetFieldFont()
              range:NSMakeRange(0, [as length])];
 
@@ -617,7 +576,7 @@
 }
 
 void AutocompleteEditViewMac::OnTemporaryTextMaybeChanged(
-    const std::wstring& display_text, bool save_original_selection) {
+    const string16& display_text, bool save_original_selection) {
   if (save_original_selection)
     saved_temporary_selection_ = GetSelectedRange();
 
@@ -628,18 +587,19 @@
 }
 
 void AutocompleteEditViewMac::OnStartingIME() {
-  if (model_->is_keyword_hint() && !model_->keyword().empty())
-    model_->AcceptKeyword();
+  // Reset the suggest text just before starting an IME composition session,
+  // otherwise the IME composition may be interrupted when the suggest text
+  // gets reset by the IME composition change.
+  SetInstantSuggestion(string16());
 }
 
 bool AutocompleteEditViewMac::OnInlineAutocompleteTextMaybeChanged(
-    const std::wstring& display_text, size_t user_text_length) {
+    const string16& display_text, size_t user_text_length) {
   // TODO(shess): Make sure that this actually works.  The round trip
   // to native form and back may mean that it's the same but not the
   // same.
-  if (display_text == GetText()) {
+  if (display_text == GetText())
     return false;
-  }
 
   DCHECK_LE(user_text_length, display_text.size());
   const NSRange range =
@@ -665,6 +625,7 @@
 
   selection_before_change_ = GetSelectedRange();
   text_before_change_ = GetText();
+  marked_range_before_change_ = GetMarkedRange();
 }
 
 bool AutocompleteEditViewMac::OnAfterPossibleChange() {
@@ -672,13 +633,15 @@
   DCHECK(IsFirstResponder());
 
   const NSRange new_selection(GetSelectedRange());
-  const std::wstring new_text(GetText());
+  const string16 new_text(GetText());
   const size_t length = new_text.length();
 
-  const bool selection_differs = !NSEqualRanges(new_selection,
-                                                selection_before_change_);
+  const bool selection_differs =
+      (new_selection.length || selection_before_change_.length) &&
+      !NSEqualRanges(new_selection, selection_before_change_);
   const bool at_end_of_edit = (length == new_selection.location);
-  const bool text_differs = (new_text != text_before_change_);
+  const bool text_differs = (new_text != text_before_change_) ||
+      !NSEqualRanges(marked_range_before_change_, GetMarkedRange());
 
   // When the user has deleted text, we don't allow inline
   // autocomplete.  This is assumed if the text has gotten shorter AND
@@ -696,8 +659,10 @@
 
   delete_at_end_pressed_ = false;
 
+  const bool allow_keyword_ui_change = at_end_of_edit && !IsImeComposing();
   const bool something_changed = model_->OnAfterPossibleChange(new_text,
-      selection_differs, text_differs, just_deleted_text, at_end_of_edit);
+      selection_differs, text_differs, just_deleted_text,
+      allow_keyword_ui_change);
 
   if (delete_was_pressed_ && at_end_of_edit)
     delete_at_end_pressed_ = true;
@@ -723,6 +688,44 @@
   return command_updater_;
 }
 
+void AutocompleteEditViewMac::SetInstantSuggestion(
+    const string16& suggest_text) {
+  NSString* text = GetNonSuggestTextSubstring();
+  bool needs_update = (suggest_text_length_ > 0);
+
+  // Append the new suggest text.
+  suggest_text_length_ = suggest_text.length();
+  if (suggest_text_length_ > 0) {
+    text = [text stringByAppendingString:base::SysUTF16ToNSString(
+               suggest_text)];
+    needs_update = true;
+  }
+
+  if (needs_update) {
+    NSRange current_range = GetSelectedRange();
+    SetTextInternal(base::SysNSStringToUTF16(text));
+    if (NSMaxRange(current_range) <= [text length] - suggest_text_length_)
+      SetSelectedRange(current_range);
+    else
+      SetSelectedRange(NSMakeRange([text length] - suggest_text_length_, 0));
+  }
+}
+
+string16 AutocompleteEditViewMac::GetInstantSuggestion() const {
+  return suggest_text_length_ ?
+      base::SysNSStringToUTF16(GetSuggestTextSubstring()) : string16();
+}
+
+int AutocompleteEditViewMac::TextWidth() const {
+  // Not used on mac.
+  NOTREACHED();
+  return 0;
+}
+
+bool AutocompleteEditViewMac::IsImeComposing() const {
+  return [(NSTextView*)[field_ currentEditor] hasMarkedText];
+}
+
 void AutocompleteEditViewMac::OnDidBeginEditing() {
   // We should only arrive here when the field is focussed.
   DCHECK([field_ currentEditor]);
@@ -753,7 +756,7 @@
     // Reset the suggest text for any change other than key right or tab.
     // TODO(rohitrao): This is here to prevent complications when editing text.
     // See if this can be removed.
-    SetSuggestText(string16());
+    SetInstantSuggestion(string16());
   }
 
   if (cmd == @selector(deleteForward:))
@@ -775,12 +778,8 @@
   if (cmd == @selector(moveRight:)) {
     // Only commit suggested text if the cursor is all the way to the right and
     // there is no selection.
-    NSRange range = GetSelectedRange();
-    if (range.length == 0 &&
-        suggest_text_length_ > 0 &&
-        (range.location + suggest_text_length_ ==
-         [[field_ stringValue] length])) {
-      controller_->OnCommitSuggestedText(GetText());
+    if (suggest_text_length_ > 0 && IsCaretAtEnd()) {
+      controller_->OnCommitSuggestedText(true);
       return true;
     }
   }
@@ -801,13 +800,19 @@
 
   if (cmd == @selector(insertTab:) ||
       cmd == @selector(insertTabIgnoringFieldEditor:)) {
-    if (model_->is_keyword_hint() && !model_->keyword().empty()) {
-      model_->AcceptKeyword();
+    if (model_->is_keyword_hint())
+      return model_->AcceptKeyword();
+
+    if (suggest_text_length_ > 0) {
+      controller_->OnCommitSuggestedText(true);
       return true;
     }
 
-    if (suggest_text_length_ > 0) {
-      controller_->OnCommitSuggestedText(GetText());
+    if (!IsCaretAtEnd()) {
+      PlaceCaretAt(GetTextLength());
+      // OnDidChange() will not be triggered when setting selected range in this
+      // method, so we need to call it explicitly.
+      OnDidChange();
       return true;
     }
 
@@ -893,7 +898,7 @@
   DCHECK(CanCopy());
 
   const NSRange selection = GetSelectedRange();
-  std::wstring text = base::SysNSStringToWide(
+  string16 text = base::SysNSStringToUTF16(
       [[field_ stringValue] substringWithRange:selection]);
 
   GURL url;
@@ -901,7 +906,7 @@
   model_->AdjustTextForCopy(selection.location, IsSelectAll(), &text, &url,
                             &write_url);
 
-  NSString* nstext = base::SysWideToNSString(text);
+  NSString* nstext = base::SysUTF16ToNSString(text);
   [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
   [pb setString:nstext forType:NSStringPboardType];
 
@@ -915,11 +920,11 @@
   // This code currently expects |field_| to be focussed.
   DCHECK([field_ currentEditor]);
 
-  std::wstring text = GetClipboardText(g_browser_process->clipboard());
+  string16 text = GetClipboardText(g_browser_process->clipboard());
   if (text.empty()) {
     return;
   }
-  NSString* s = base::SysWideToNSString(text);
+  NSString* s = base::SysUTF16ToNSString(text);
 
   // -shouldChangeTextInRange:* and -didChangeText are documented in
   // NSTextView as things you need to do if you write additional
@@ -930,10 +935,8 @@
   NSTextView* editor = static_cast<NSTextView*>([field_ currentEditor]);
   const NSRange selectedRange = GetSelectedRange();
   if ([editor shouldChangeTextInRange:selectedRange replacementString:s]) {
-    // If this paste will be replacing all the text, record that, so
-    // we can do different behaviors in such a case.
-    if (IsSelectAll())
-      model_->on_paste_replacing_all();
+    // Record this paste, so we can do different behavior.
+    model_->on_paste();
 
     // Force a Paste operation to trigger the text_changed code in
     // OnAfterPossibleChange(), even if identical contents are pasted
@@ -1042,15 +1045,16 @@
 
 // TODO(shess): Copied from autocomplete_edit_view_win.cc.  Could this
 // be pushed into the model?
-std::wstring AutocompleteEditViewMac::GetClipboardText(Clipboard* clipboard) {
+string16 AutocompleteEditViewMac::GetClipboardText(
+    ui::Clipboard* clipboard) {
   // autocomplete_edit_view_win.cc assumes this can never happen, we
   // will too.
   DCHECK(clipboard);
 
-  if (clipboard->IsFormatAvailable(Clipboard::GetPlainTextWFormatType(),
-                                   Clipboard::BUFFER_STANDARD)) {
+  if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
+                                   ui::Clipboard::BUFFER_STANDARD)) {
     string16 text16;
-    clipboard->ReadText(Clipboard::BUFFER_STANDARD, &text16);
+    clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &text16);
 
     // Note: Unlike in the find popup and textfield view, here we completely
     // remove whitespace strings containing newlines.  We assume users are
@@ -1058,7 +1062,7 @@
     // lines in terminals, email programs, etc., and so linebreaks indicate
     // completely bogus whitespace that would just cause the input to be
     // invalid.
-    return CollapseWhitespace(UTF16ToWide(text16), true);
+    return CollapseWhitespace(text16, true);
   }
 
   // Try bookmark format.
@@ -1068,18 +1072,18 @@
   // and pastes from the URL bar to itself, the text will get fixed up and
   // cannonicalized, which is not what the user expects.  By pasting in this
   // order, we are sure to paste what the user copied.
-  if (clipboard->IsFormatAvailable(Clipboard::GetUrlWFormatType(),
-                                   Clipboard::BUFFER_STANDARD)) {
+  if (clipboard->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
+                                   ui::Clipboard::BUFFER_STANDARD)) {
     std::string url_str;
     clipboard->ReadBookmark(NULL, &url_str);
     // pass resulting url string through GURL to normalize
     GURL url(url_str);
     if (url.is_valid()) {
-      return UTF8ToWide(url.spec());
+      return UTF8ToUTF16(url.spec());
     }
   }
 
-  return std::wstring();
+  return string16();
 }
 
 // static
@@ -1087,3 +1091,19 @@
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
   return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont();
 }
+
+NSUInteger AutocompleteEditViewMac::GetTextLength() const {
+  return ([field_ currentEditor] ?
+          [[[field_ currentEditor] string] length] :
+          [[field_ stringValue] length]) - suggest_text_length_;
+}
+
+void AutocompleteEditViewMac::PlaceCaretAt(NSUInteger pos) {
+  DCHECK(pos <= GetTextLength());
+  SetSelectedRange(NSMakeRange(pos, pos));
+}
+
+bool AutocompleteEditViewMac::IsCaretAtEnd() const {
+  const NSRange selection = GetSelectedRange();
+  return selection.length == 0 && selection.location == GetTextLength();
+}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac_unittest.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac_unittest.mm
index bf61499..bbf899b 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_mac_unittest.mm
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac_unittest.mm
@@ -4,25 +4,25 @@
 
 #import "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
 
-#include "app/clipboard/clipboard.h"
-#include "app/clipboard/scoped_clipboard_writer.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
-#include "gfx/size.h"
 #include "testing/platform_test.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/gfx/size.h"
 
 namespace {
 
 TEST(AutocompleteEditViewMacTest, GetClipboardText) {
-  Clipboard clipboard;
-  std::wstring text;
+  ui::Clipboard clipboard;
+  string16 text;
 
   // Does an empty clipboard get empty text?
-  clipboard.WriteObjects(Clipboard::ObjectMap());
+  clipboard.WriteObjects(ui::Clipboard::ObjectMap());
   text = AutocompleteEditViewMac::GetClipboardText(&clipboard);
-  EXPECT_EQ(std::wstring(), text);
+  EXPECT_EQ(string16(), text);
 
   const string16 plainText(ASCIIToUTF16("test text"));
   const std::string url("http://www.example.com/");
@@ -30,36 +30,36 @@
 
   // Can we pull straight text off the clipboard?
   {
-    ScopedClipboardWriter clipboard_writer(&clipboard);
+    ui::ScopedClipboardWriter clipboard_writer(&clipboard);
     clipboard_writer.WriteText(plainText);
   }
 
   text = AutocompleteEditViewMac::GetClipboardText(&clipboard);
-  EXPECT_EQ(UTF16ToWide(plainText), text);
+  EXPECT_EQ(plainText, text);
 
   // Can we pull a bookmark off the clipboard?
   {
-    ScopedClipboardWriter clipboard_writer(&clipboard);
+    ui::ScopedClipboardWriter clipboard_writer(&clipboard);
     clipboard_writer.WriteBookmark(title, url);
   }
 
   text = AutocompleteEditViewMac::GetClipboardText(&clipboard);
-  EXPECT_EQ(ASCIIToWide(url), text);
+  EXPECT_EQ(ASCIIToUTF16(url), text);
 
   // Do we pull text in preference to a bookmark?
   {
-    ScopedClipboardWriter clipboard_writer(&clipboard);
+    ui::ScopedClipboardWriter clipboard_writer(&clipboard);
     clipboard_writer.WriteText(plainText);
     clipboard_writer.WriteBookmark(title, url);
   }
 
   text = AutocompleteEditViewMac::GetClipboardText(&clipboard);
-  EXPECT_EQ(UTF16ToWide(plainText), text);
+  EXPECT_EQ(plainText, text);
 
   // Do we get nothing if there is neither text nor a bookmark?
   {
     const string16 markup(ASCIIToUTF16("<strong>Hi!</string>"));
-    ScopedClipboardWriter clipboard_writer(&clipboard);
+    ui::ScopedClipboardWriter clipboard_writer(&clipboard);
     clipboard_writer.WriteHTML(markup, url);
   }
 
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_views.cc b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc
new file mode 100644
index 0000000..80baa0d
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc
@@ -0,0 +1,645 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/autocomplete/autocomplete_edit_view_views.h"
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/common/notification_service.h"
+#include "googleurl/src/gurl.h"
+#include "grit/generated_resources.h"
+#include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/font.h"
+#include "views/border.h"
+#include "views/layout/fill_layout.h"
+
+namespace {
+
+// Textfield for autocomplete that intercepts events that are necessary
+// for AutocompleteEditViewViews.
+class AutocompleteTextfield : public views::Textfield {
+ public:
+  explicit AutocompleteTextfield(
+      AutocompleteEditViewViews* autocomplete_edit_view)
+      : views::Textfield(views::Textfield::STYLE_DEFAULT),
+        autocomplete_edit_view_(autocomplete_edit_view) {
+    DCHECK(autocomplete_edit_view_);
+    RemoveBorder();
+  }
+
+  // views::View implementation
+  virtual void DidGainFocus() {
+    views::Textfield::DidGainFocus();
+    autocomplete_edit_view_->HandleFocusIn();
+  }
+
+  virtual void WillLoseFocus() {
+    views::Textfield::WillLoseFocus();
+    autocomplete_edit_view_->HandleFocusOut();
+  }
+
+  virtual bool OnKeyPressed(const views::KeyEvent& e) {
+    bool handled = views::Textfield::OnKeyPressed(e);
+    return autocomplete_edit_view_->HandleAfterKeyEvent(e, handled) || handled;
+  }
+
+  virtual bool OnKeyReleased(const views::KeyEvent& e) {
+    return autocomplete_edit_view_->HandleKeyReleaseEvent(e);
+  }
+
+  virtual bool IsFocusable() const {
+    // Bypass Textfield::IsFocusable. The omnibox in popup window requires
+    // focus in order for text selection to work.
+    return views::View::IsFocusable();
+  }
+
+ private:
+  AutocompleteEditViewViews* autocomplete_edit_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutocompleteTextfield);
+};
+
+// Stores omnibox state for each tab.
+struct ViewState {
+  explicit ViewState(const views::TextRange& selection_range)
+      : selection_range(selection_range) {
+  }
+
+  // Range of selected text.
+  views::TextRange selection_range;
+};
+
+struct AutocompleteEditState {
+  AutocompleteEditState(const AutocompleteEditModel::State& model_state,
+                        const ViewState& view_state)
+      : model_state(model_state),
+        view_state(view_state) {
+  }
+
+  const AutocompleteEditModel::State model_state;
+  const ViewState view_state;
+};
+
+// Returns a lazily initialized property bag accessor for saving our state in a
+// TabContents.
+PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
+  static PropertyAccessor<AutocompleteEditState> state;
+  return &state;
+}
+
+const int kAutocompleteVerticalMargin = 4;
+
+}  // namespace
+
+AutocompleteEditViewViews::AutocompleteEditViewViews(
+    AutocompleteEditController* controller,
+    ToolbarModel* toolbar_model,
+    Profile* profile,
+    CommandUpdater* command_updater,
+    bool popup_window_mode,
+    const views::View* location_bar)
+    : model_(new AutocompleteEditModel(this, controller, profile)),
+      popup_view_(new AutocompletePopupContentsView(
+          gfx::Font(), this, model_.get(), profile, location_bar)),
+      controller_(controller),
+      toolbar_model_(toolbar_model),
+      command_updater_(command_updater),
+      popup_window_mode_(popup_window_mode),
+      security_level_(ToolbarModel::NONE),
+      delete_was_pressed_(false),
+      delete_at_end_pressed_(false) {
+  model_->SetPopupModel(popup_view_->GetModel());
+  set_border(views::Border::CreateEmptyBorder(kAutocompleteVerticalMargin, 0,
+                                              kAutocompleteVerticalMargin, 0));
+}
+
+AutocompleteEditViewViews::~AutocompleteEditViewViews() {
+  NotificationService::current()->Notify(
+      NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
+      Source<AutocompleteEditViewViews>(this),
+      NotificationService::NoDetails());
+  // Explicitly teardown members which have a reference to us.  Just to be safe
+  // we want them to be destroyed before destroying any other internal state.
+  popup_view_.reset();
+  model_.reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditViewViews public:
+
+void AutocompleteEditViewViews::Init() {
+  // The height of the text view is going to change based on the font used.  We
+  // don't want to stretch the height, and we want it vertically centered.
+  // TODO(oshima): make sure the above happens with views.
+  textfield_ = new AutocompleteTextfield(this);
+  textfield_->SetController(this);
+
+  if (popup_window_mode_)
+    textfield_->SetReadOnly(true);
+
+  // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe
+  // themes.
+  SetBaseColor();
+}
+
+void AutocompleteEditViewViews::SetBaseColor() {
+  // TODO(oshima): Implment style change.
+  NOTIMPLEMENTED();
+}
+
+bool AutocompleteEditViewViews::HandleAfterKeyEvent(
+    const views::KeyEvent& event,
+    bool handled) {
+  handling_key_press_ = false;
+  if (content_maybe_changed_by_key_press_)
+    OnAfterPossibleChange();
+
+  if (event.key_code() == ui::VKEY_RETURN) {
+    bool alt_held = event.IsAltDown();
+    model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false);
+    handled = true;
+  } else if (!handled && event.key_code() == ui::VKEY_ESCAPE) {
+    // We can handle the Escape key if textfield did not handle it.
+    // If it's not handled by us, then we need to propagate it up to the parent
+    // widgets, so that Escape accelerator can still work.
+    handled = model_->OnEscapeKeyPressed();
+  } else if (event.key_code() == ui::VKEY_CONTROL) {
+    // Omnibox2 can switch its contents while pressing a control key. To switch
+    // the contents of omnibox2, we notify the AutocompleteEditModel class when
+    // the control-key state is changed.
+    model_->OnControlKeyChanged(true);
+  } else if (!text_changed_ && event.key_code() == ui::VKEY_DELETE &&
+             event.IsShiftDown()) {
+    // If shift+del didn't change the text, we let this delete an entry from
+    // the popup.  We can't check to see if the IME handled it because even if
+    // nothing is selected, the IME or the TextView still report handling it.
+    AutocompletePopupModel* popup_model = popup_view_->GetModel();
+    if (popup_model->IsOpen())
+      popup_model->TryDeletingCurrentItem();
+  } else if (!handled && event.key_code() == ui::VKEY_UP) {
+    model_->OnUpOrDownKeyPressed(-1);
+    handled = true;
+  } else if (!handled && event.key_code() == ui::VKEY_DOWN) {
+    model_->OnUpOrDownKeyPressed(1);
+    handled = true;
+  } else if (!handled &&
+             event.key_code() == ui::VKEY_TAB &&
+             !event.IsShiftDown() &&
+             !event.IsControlDown()) {
+    if (model_->is_keyword_hint()) {
+      handled = model_->AcceptKeyword();
+    } else {
+      string16::size_type start = 0;
+      string16::size_type end = 0;
+      size_t length = GetTextLength();
+      GetSelectionBounds(&start, &end);
+      if (start != end || start < length) {
+        OnBeforePossibleChange();
+        SelectRange(length, length);
+        OnAfterPossibleChange();
+        handled = true;
+      }
+
+      // TODO(Oshima): handle instant
+    }
+  }
+  // TODO(oshima): page up & down
+
+  return handled;
+}
+
+bool AutocompleteEditViewViews::HandleKeyReleaseEvent(
+    const views::KeyEvent& event) {
+  // Omnibox2 can switch its contents while pressing a control key. To switch
+  // the contents of omnibox2, we notify the AutocompleteEditModel class when
+  // the control-key state is changed.
+  if (event.key_code() == ui::VKEY_CONTROL) {
+    // TODO(oshima): investigate if we need to support keyboard with two
+    // controls. See autocomplete_edit_view_gtk.cc.
+    model_->OnControlKeyChanged(false);
+    return true;
+  }
+  return false;
+}
+
+void AutocompleteEditViewViews::HandleFocusIn() {
+  // TODO(oshima): Get control key state.
+  model_->OnSetFocus(false);
+  // Don't call controller_->OnSetFocus as this view has already
+  // acquired the focus.
+}
+
+void AutocompleteEditViewViews::HandleFocusOut() {
+  // TODO(oshima): we don't have native view. This requires
+  // further refactoring.
+  controller_->OnAutocompleteLosingFocus(NULL);
+  // Close the popup.
+  ClosePopup();
+  // Tell the model to reset itself.
+  model_->OnKillFocus();
+  controller_->OnKillFocus();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditViewViews, views::View implementation:
+
+bool AutocompleteEditViewViews::OnMousePressed(
+    const views::MouseEvent& event) {
+  if (event.IsLeftMouseButton()) {
+    // Button press event may change the selection, we need to record the change
+    // and report it to |model_| later when button is released.
+    OnBeforePossibleChange();
+  }
+  // Pass the event through to TextfieldViews.
+  return false;
+}
+
+void AutocompleteEditViewViews::Layout() {
+  gfx::Insets insets = GetInsets();
+  textfield_->SetBounds(insets.left(), insets.top(),
+                        width() - insets.width(),
+                        height() - insets.height());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditViewViews, AutocopmleteEditView implementation:
+
+AutocompleteEditModel* AutocompleteEditViewViews::model() {
+  return model_.get();
+}
+
+const AutocompleteEditModel* AutocompleteEditViewViews::model() const {
+  return model_.get();
+}
+
+void AutocompleteEditViewViews::SaveStateToTab(TabContents* tab) {
+  DCHECK(tab);
+
+  // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important.
+  AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch();
+  views::TextRange selection;
+  textfield_->GetSelectedRange(&selection);
+  GetStateAccessor()->SetProperty(
+      tab->property_bag(),
+      AutocompleteEditState(model_state, ViewState(selection)));
+}
+
+void AutocompleteEditViewViews::Update(const TabContents* contents) {
+  // NOTE: We're getting the URL text here from the ToolbarModel.
+  bool visibly_changed_permanent_text =
+      model_->UpdatePermanentText(WideToUTF16Hack(toolbar_model_->GetText()));
+
+  ToolbarModel::SecurityLevel security_level =
+        toolbar_model_->GetSecurityLevel();
+  bool changed_security_level = (security_level != security_level_);
+  security_level_ = security_level;
+
+  // TODO(oshima): Copied from gtk implementation which is
+  // slightly different from WIN impl. Find out the correct implementation
+  // for views-implementation.
+  if (contents) {
+    RevertAll();
+    const AutocompleteEditState* state =
+        GetStateAccessor()->GetProperty(contents->property_bag());
+    if (state) {
+      model_->RestoreState(state->model_state);
+
+      // Move the marks for the cursor and the other end of the selection to
+      // the previously-saved offsets (but preserve PRIMARY).
+      textfield_->SelectRange(state->view_state.selection_range);
+    }
+  } else if (visibly_changed_permanent_text) {
+    RevertAll();
+  } else if (changed_security_level) {
+    EmphasizeURLComponents();
+  }
+}
+
+void AutocompleteEditViewViews::OpenURL(const GURL& url,
+                                        WindowOpenDisposition disposition,
+                                        PageTransition::Type transition,
+                                        const GURL& alternate_nav_url,
+                                        size_t selected_line,
+                                        const string16& keyword) {
+  if (!url.is_valid())
+    return;
+
+  model_->OpenURL(url, disposition, transition, alternate_nav_url,
+                  selected_line, keyword);
+}
+
+string16 AutocompleteEditViewViews::GetText() const {
+  // TODO(oshima): IME support
+  return textfield_->text();
+}
+
+bool AutocompleteEditViewViews::IsEditingOrEmpty() const {
+  return model_->user_input_in_progress() || (GetTextLength() == 0);
+}
+
+int AutocompleteEditViewViews::GetIcon() const {
+  return IsEditingOrEmpty() ?
+      AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
+      toolbar_model_->GetIcon();
+}
+
+void AutocompleteEditViewViews::SetUserText(const string16& text) {
+  SetUserText(text, text, true);
+}
+
+void AutocompleteEditViewViews::SetUserText(const string16& text,
+                                            const string16& display_text,
+                                            bool update_popup) {
+  model_->SetUserText(text);
+  SetWindowTextAndCaretPos(display_text, display_text.length());
+  if (update_popup)
+    UpdatePopup();
+  TextChanged();
+}
+
+void AutocompleteEditViewViews::SetWindowTextAndCaretPos(
+    const string16& text,
+    size_t caret_pos) {
+  const views::TextRange range(caret_pos, caret_pos);
+  SetTextAndSelectedRange(text, range);
+}
+
+void AutocompleteEditViewViews::SetForcedQuery() {
+  const string16 current_text(GetText());
+  const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
+  if (start == string16::npos || (current_text[start] != '?')) {
+    SetUserText(ASCIIToUTF16("?"));
+  } else {
+    SelectRange(current_text.size(), start + 1);
+  }
+}
+
+bool AutocompleteEditViewViews::IsSelectAll() {
+  // TODO(oshima): IME support.
+  return textfield_->text() == textfield_->GetSelectedText();
+}
+
+bool AutocompleteEditViewViews::DeleteAtEndPressed() {
+  return delete_at_end_pressed_;
+}
+
+void AutocompleteEditViewViews::GetSelectionBounds(
+    string16::size_type* start,
+    string16::size_type* end) {
+  views::TextRange range;
+  textfield_->GetSelectedRange(&range);
+  *start = static_cast<size_t>(range.end());
+  *end = static_cast<size_t>(range.start());
+}
+
+void AutocompleteEditViewViews::SelectAll(bool reversed) {
+  if (reversed)
+    SelectRange(GetTextLength(), 0);
+  else
+    SelectRange(0, GetTextLength());
+}
+
+void AutocompleteEditViewViews::RevertAll() {
+  ClosePopup();
+  model_->Revert();
+  TextChanged();
+}
+
+void AutocompleteEditViewViews::UpdatePopup() {
+  model_->SetInputInProgress(true);
+  if (!model_->has_focus())
+    return;
+
+  // Don't inline autocomplete when the caret/selection isn't at the end of
+  // the text, or in the middle of composition.
+  views::TextRange sel;
+  textfield_->GetSelectedRange(&sel);
+  bool no_inline_autocomplete = sel.GetMax() < GetTextLength();
+
+  // TODO(oshima): Support IME. Don't show autocomplete if IME has some text.
+  model_->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete);
+}
+
+void AutocompleteEditViewViews::ClosePopup() {
+  if (popup_view_->GetModel()->IsOpen())
+    controller_->OnAutocompleteWillClosePopup();
+
+  popup_view_->GetModel()->StopAutocomplete();
+}
+
+void AutocompleteEditViewViews::SetFocus() {
+  // In views-implementation, the focus is on textfield rather than
+  // AutocompleteEditView.
+  textfield_->RequestFocus();
+}
+
+void AutocompleteEditViewViews::OnTemporaryTextMaybeChanged(
+    const string16& display_text,
+    bool save_original_selection) {
+  if (save_original_selection)
+    textfield_->GetSelectedRange(&saved_temporary_selection_);
+
+  SetWindowTextAndCaretPos(display_text, display_text.length());
+  TextChanged();
+}
+
+bool AutocompleteEditViewViews::OnInlineAutocompleteTextMaybeChanged(
+    const string16& display_text,
+    size_t user_text_length) {
+  if (display_text == GetText())
+    return false;
+  views::TextRange range(display_text.size(), user_text_length);
+  SetTextAndSelectedRange(display_text, range);
+  TextChanged();
+  return true;
+}
+
+void AutocompleteEditViewViews::OnRevertTemporaryText() {
+  textfield_->SelectRange(saved_temporary_selection_);
+  TextChanged();
+}
+
+void AutocompleteEditViewViews::OnBeforePossibleChange() {
+  // Record our state.
+  text_before_change_ = GetText();
+  textfield_->GetSelectedRange(&sel_before_change_);
+}
+
+bool AutocompleteEditViewViews::OnAfterPossibleChange() {
+  // OnAfterPossibleChange should be called once per modification,
+  // and we should ignore if this is called while a key event is being handled
+  // because OnAfterPossibleChagne will be called after the key event is
+  // actually handled.
+  if (handling_key_press_) {
+    content_maybe_changed_by_key_press_ = true;
+    return false;
+  }
+  views::TextRange new_sel;
+  textfield_->GetSelectedRange(&new_sel);
+
+  size_t length = GetTextLength();
+  bool at_end_of_edit = (new_sel.start() == length && new_sel.end() == length);
+
+  // See if the text or selection have changed since OnBeforePossibleChange().
+  string16 new_text = GetText();
+  text_changed_ = (new_text != text_before_change_);
+  bool selection_differs =
+      !((sel_before_change_.is_empty() && new_sel.is_empty()) ||
+        sel_before_change_.EqualsIgnoringDirection(new_sel));
+
+  // When the user has deleted text, we don't allow inline autocomplete.  Make
+  // sure to not flag cases like selecting part of the text and then pasting
+  // (or typing) the prefix of that selection.  (We detect these by making
+  // sure the caret, which should be after any insertion, hasn't moved
+  // forward of the old selection start.)
+  bool just_deleted_text =
+      (text_before_change_.length() > new_text.length()) &&
+      (new_sel.start() <= sel_before_change_.GetMin());
+
+  delete_at_end_pressed_ = false;
+
+  bool something_changed = model_->OnAfterPossibleChange(new_text,
+      selection_differs, text_changed_, just_deleted_text, at_end_of_edit);
+
+  // If only selection was changed, we don't need to call |controller_|'s
+  // OnChanged() method, which is called in TextChanged().
+  // But we still need to call EmphasizeURLComponents() to make sure the text
+  // attributes are updated correctly.
+  if (something_changed && text_changed_) {
+    TextChanged();
+  } else if (selection_differs) {
+    EmphasizeURLComponents();
+  } else if (delete_was_pressed_ && at_end_of_edit) {
+    delete_at_end_pressed_ = true;
+    controller_->OnChanged();
+  }
+  delete_was_pressed_ = false;
+
+  return something_changed;
+}
+
+gfx::NativeView AutocompleteEditViewViews::GetNativeView() const {
+  return GetWidget()->GetNativeView();
+}
+
+CommandUpdater* AutocompleteEditViewViews::GetCommandUpdater() {
+  return command_updater_;
+}
+
+void AutocompleteEditViewViews::SetInstantSuggestion(const string16& input) {
+  NOTIMPLEMENTED();
+}
+
+string16 AutocompleteEditViewViews::GetInstantSuggestion() const {
+  NOTIMPLEMENTED();
+  return string16();
+}
+
+int AutocompleteEditViewViews::TextWidth() const {
+  // TODO(oshima): add horizontal margin.
+  return textfield_->font().GetStringWidth(textfield_->text());
+}
+
+bool AutocompleteEditViewViews::IsImeComposing() const {
+  return false;
+}
+
+views::View* AutocompleteEditViewViews::AddToView(views::View* parent) {
+  parent->AddChildView(this);
+  AddChildView(textfield_);
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditViewViews, NotificationObserver implementation:
+
+void AutocompleteEditViewViews::Observe(NotificationType type,
+                                      const NotificationSource& source,
+                                      const NotificationDetails& details) {
+  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+  SetBaseColor();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditViewViews, Textfield::Controller implementation:
+
+void AutocompleteEditViewViews::ContentsChanged(views::Textfield* sender,
+                                                const string16& new_contents) {
+  if (handling_key_press_)
+    content_maybe_changed_by_key_press_ = true;
+}
+
+bool AutocompleteEditViewViews::HandleKeyEvent(
+    views::Textfield* textfield,
+    const views::KeyEvent& event) {
+  delete_was_pressed_ = event.key_code() == ui::VKEY_DELETE;
+
+  // Reset |text_changed_| before passing the key event on to the text view.
+  text_changed_ = false;
+  OnBeforePossibleChange();
+  handling_key_press_ = true;
+  content_maybe_changed_by_key_press_ = false;
+
+  if (event.key_code() == ui::VKEY_BACK) {
+    // Checks if it's currently in keyword search mode.
+    if (model_->is_keyword_hint() || model_->keyword().empty())
+      return false;
+    // If there is selection, let textfield handle the backspace.
+    if (!textfield_->GetSelectedText().empty())
+      return false;
+    // If not at the begining of the text, let textfield handle the backspace.
+    if (textfield_->GetCursorPosition())
+      return false;
+    model_->ClearKeyword(GetText());
+    return true;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditViewViews, private:
+
+size_t AutocompleteEditViewViews::GetTextLength() const {
+  // TODO(oshima): Support instant, IME.
+  return textfield_->text().length();
+}
+
+void AutocompleteEditViewViews::EmphasizeURLComponents() {
+  // TODO(oshima): Update URL visual style
+  NOTIMPLEMENTED();
+}
+
+void AutocompleteEditViewViews::TextChanged() {
+  EmphasizeURLComponents();
+  controller_->OnChanged();
+}
+
+void AutocompleteEditViewViews::SetTextAndSelectedRange(
+    const string16& text,
+    const views::TextRange& range) {
+  if (text != GetText())
+    textfield_->SetText(text);
+  textfield_->SelectRange(range);
+}
+
+string16 AutocompleteEditViewViews::GetSelectedText() const {
+  // TODO(oshima): Support instant, IME.
+  return textfield_->GetSelectedText();
+}
+
+void AutocompleteEditViewViews::SelectRange(size_t caret, size_t end) {
+  const views::TextRange range(caret, end);
+  textfield_->SelectRange(range);
+}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_views.h b/chrome/browser/autocomplete/autocomplete_edit_view_views.h
new file mode 100644
index 0000000..e347aa2
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_views.h
@@ -0,0 +1,205 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_VIEWS_H_
+#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_VIEWS_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
+#include "chrome/browser/ui/toolbar/toolbar_model.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/page_transition_types.h"
+#include "views/controls/textfield/textfield.h"
+#include "views/view.h"
+#include "webkit/glue/window_open_disposition.h"
+
+class AutocompleteEditController;
+class AutocompleteEditModel;
+class AutocompletePopupView;
+class Profile;
+class TabContents;
+
+// Views-implementation of AutocompleteEditView. This is based on
+// gtk implementation. The following features are not yet supported.
+//
+// IME supoprt.
+// LTR support.
+// Selection behavior.
+// Cut,copy and paste behavior.
+// URL styles (strikestrough insecure scheme, emphasize host).
+// Custom context menu for omnibox.
+// Instant.
+class AutocompleteEditViewViews : public views::View,
+                                  public AutocompleteEditView,
+                                  public NotificationObserver,
+                                  public views::Textfield::Controller {
+ public:
+  AutocompleteEditViewViews(AutocompleteEditController* controller,
+                            ToolbarModel* toolbar_model,
+                            Profile* profile,
+                            CommandUpdater* command_updater,
+                            bool popup_window_mode,
+                            const views::View* location_bar);
+  virtual ~AutocompleteEditViewViews();
+
+  // Initialize, create the underlying views, etc;
+  void Init();
+
+  // Sets the colors of the text view according to the theme.
+  void SetBaseColor();
+
+  // Called after key even is handled either by HandleKeyEvent or by Textfield.
+  bool HandleAfterKeyEvent(const views::KeyEvent& event, bool handled);
+
+  // Called when KeyRelease event is generated on textfield.
+  bool HandleKeyReleaseEvent(const views::KeyEvent& event);
+
+  // Called when Focus is set/unset on textfield.
+  void HandleFocusIn();
+  void HandleFocusOut();
+
+  // Implements views::View
+  virtual bool OnMousePressed(const views::MouseEvent& event);
+  virtual void Layout();
+
+  // Implement the AutocompleteEditView interface.
+  virtual AutocompleteEditModel* model();
+  virtual const AutocompleteEditModel* model() const;
+
+  virtual void SaveStateToTab(TabContents* tab);
+
+  virtual void Update(const TabContents* tab_for_state_restoring);
+
+  virtual void OpenURL(const GURL& url,
+                       WindowOpenDisposition disposition,
+                       PageTransition::Type transition,
+                       const GURL& alternate_nav_url,
+                       size_t selected_line,
+                       const string16& keyword);
+
+  virtual string16 GetText() const;
+
+  virtual bool IsEditingOrEmpty() const;
+  virtual int GetIcon() const;
+  virtual void SetUserText(const string16& text);
+  virtual void SetUserText(const string16& text,
+                           const string16& display_text,
+                           bool update_popup);
+  virtual void SetWindowTextAndCaretPos(const string16& text,
+                                        size_t caret_pos);
+  virtual void SetForcedQuery();
+  virtual bool IsSelectAll();
+  virtual bool DeleteAtEndPressed();
+  virtual void GetSelectionBounds(string16::size_type* start,
+                                  string16::size_type* end);
+  virtual void SelectAll(bool reversed);
+  virtual void RevertAll();
+  virtual void UpdatePopup();
+  virtual void ClosePopup();
+  virtual void SetFocus();
+  virtual void OnTemporaryTextMaybeChanged(const string16& display_text,
+                                           bool save_original_selection);
+  virtual bool OnInlineAutocompleteTextMaybeChanged(
+      const string16& display_text, size_t user_text_length);
+  virtual void OnRevertTemporaryText();
+  virtual void OnBeforePossibleChange();
+  virtual bool OnAfterPossibleChange();
+  virtual gfx::NativeView GetNativeView() const;
+  virtual CommandUpdater* GetCommandUpdater();
+  virtual void SetInstantSuggestion(const string16& input);
+  virtual string16 GetInstantSuggestion() const;
+  virtual int TextWidth() const;
+  virtual bool IsImeComposing() const;
+  virtual views::View* AddToView(views::View* parent);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Overridden from Textfield::Controller
+  virtual void ContentsChanged(views::Textfield* sender,
+                               const string16& new_contents);
+  virtual bool HandleKeyEvent(views::Textfield* sender,
+                              const views::KeyEvent& key_event);
+
+ private:
+  // Return the number of characers in the current buffer.
+  size_t GetTextLength() const;
+
+  // Try to parse the current text as a URL and colorize the components.
+  void EmphasizeURLComponents();
+
+  // Internally invoked whenever the text changes in some way.
+  void TextChanged();
+
+  // Update the field with |text| and set the selection.
+  void SetTextAndSelectedRange(const string16& text,
+                               const views::TextRange& range);
+
+  // Returns the selected text.
+  string16 GetSelectedText() const;
+
+  // Selects the text given by |caret| and |end|.
+  void SelectRange(size_t caret, size_t end);
+
+  views::Textfield* textfield_;
+
+  scoped_ptr<AutocompleteEditModel> model_;
+  scoped_ptr<AutocompletePopupView> popup_view_;
+  AutocompleteEditController* controller_;
+  ToolbarModel* toolbar_model_;
+
+  // The object that handles additional command functionality exposed on the
+  // edit, such as invoking the keyword editor.
+  CommandUpdater* command_updater_;
+
+  // When true, the location bar view is read only and also is has a slightly
+  // different presentation (smaller font size). This is used for popups.
+  bool popup_window_mode_;
+
+  ToolbarModel::SecurityLevel security_level_;
+
+  // Selection at the point where the user started using the
+  // arrows to move around in the popup.
+  views::TextRange saved_temporary_selection_;
+
+  // Tracking state before and after a possible change.
+  string16 text_before_change_;
+  views::TextRange sel_before_change_;
+
+  // TODO(oshima): following flags are copied from gtk implementation.
+  // It should be possible to refactor this class to simplify flags and
+  // logic. I'll work on this refactoring once all features are completed.
+
+  // Indicates whether the IME changed the text.  It's possible for the IME to
+  // handle a key event but not change the text contents (e.g., when pressing
+  // shift+del with no selection).
+  bool text_changed_;
+
+  // Was delete pressed?
+  bool delete_was_pressed_;
+
+  // Was the delete key pressed with an empty selection at the end of the edit?
+  bool delete_at_end_pressed_;
+
+  // Indicates if we are handling a key press event.
+  bool handling_key_press_;
+
+  // Indicates if omnibox's content maybe changed by a key press event, so that
+  // we need to call OnAfterPossibleChange() after handling the event.
+  // This flag should be set for changes directly caused by a key press event,
+  // including changes to content text, selection range and preedit string.
+  // Changes caused by function calls like SetUserText() should not affect this
+  // flag.
+  bool content_maybe_changed_by_key_press_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutocompleteEditViewViews);
+};
+
+#endif  // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_EDIT_VIEW_VIEWS_H_
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
index df2a8ba..fb04276 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,17 +11,7 @@
 #include <richedit.h>
 #include <textserv.h>
 
-#include "app/clipboard/clipboard.h"
-#include "app/clipboard/scoped_clipboard_writer.h"
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/l10n_util_win.h"
-#include "app/os_exchange_data.h"
-#include "app/os_exchange_data_provider_win.h"
-#include "app/win/drag_source.h"
-#include "app/win/drop_target.h"
 #include "app/win/iat_patch_function.h"
-#include "app/win/win_util.h"
 #include "base/auto_reset.h"
 #include "base/basictypes.h"
 #include "base/i18n/rtl.h"
@@ -42,15 +32,26 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/common/notification_service.h"
 #include "googleurl/src/url_util.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "skia/ext/skia_utils_win.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/dragdrop/drag_source.h"
+#include "ui/base/dragdrop/drop_target.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_win.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "views/controls/textfield/native_textfield_win.h"
 #include "views/drag_utils.h"
+#include "views/events/event_utils_win.h"
 #include "views/focus/focus_util_win.h"
 #include "views/widget/widget.h"
 
@@ -68,7 +69,7 @@
 // URL. A drop of plain text from the same edit either copies or moves the
 // selected text, and a drop of plain text from a source other than the edit
 // does a paste and go.
-class EditDropTarget : public app::win::DropTarget {
+class EditDropTarget : public ui::DropTarget {
  public:
   explicit EditDropTarget(AutocompleteEditViewWin* edit);
 
@@ -119,7 +120,7 @@
 }
 
 EditDropTarget::EditDropTarget(AutocompleteEditViewWin* edit)
-    : app::win::DropTarget(edit->m_hWnd),
+    : ui::DropTarget(edit->m_hWnd),
       edit_(edit),
       drag_has_url_(false),
       drag_has_string_(false) {
@@ -129,7 +130,7 @@
                                   DWORD key_state,
                                   POINT cursor_position,
                                   DWORD effect) {
-  OSExchangeData os_data(new OSExchangeDataProviderWin(data_object));
+  ui::OSExchangeData os_data(new ui::OSExchangeDataProviderWin(data_object));
   drag_has_url_ = os_data.HasURL();
   drag_has_string_ = !drag_has_url_ && os_data.HasString();
   if (drag_has_url_) {
@@ -179,11 +180,11 @@
                              DWORD key_state,
                              POINT cursor_position,
                              DWORD effect) {
-  OSExchangeData os_data(new OSExchangeDataProviderWin(data_object));
+  ui::OSExchangeData os_data(new ui::OSExchangeDataProviderWin(data_object));
 
   if (drag_has_url_) {
     GURL url;
-    std::wstring title;
+    string16 title;
     if (os_data.GetURLAndTitle(&url, &title)) {
       edit_->SetUserText(UTF8ToWide(url.spec()));
       edit_->model()->AcceptInput(CURRENT_TAB, true);
@@ -191,7 +192,7 @@
     }
   } else if (drag_has_string_) {
     int string_drop_position = edit_->drop_highlight_position();
-    std::wstring text;
+    string16 text;
     if ((string_drop_position != -1 || !edit_->in_drag()) &&
         os_data.GetString(&text)) {
       DCHECK(string_drop_position == -1 ||
@@ -261,6 +262,16 @@
   const AutocompleteEditViewWin::State view_state;
 };
 
+// Returns true if the current point is far enough from the origin that it
+// would be considered a drag.
+bool IsDrag(const POINT& origin, const POINT& current) {
+  // The CXDRAG and CYDRAG system metrics describe the width and height of a
+  // rectangle around the origin position, inside of which motion is not
+  // considered a drag.
+  return (abs(current.x - origin.x) > (GetSystemMetrics(SM_CXDRAG) / 2)) ||
+         (abs(current.y - origin.y) > (GetSystemMetrics(SM_CYDRAG) / 2));
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -597,7 +608,7 @@
                                       PageTransition::Type transition,
                                       const GURL& alternate_nav_url,
                                       size_t selected_line,
-                                      const std::wstring& keyword) {
+                                      const string16& keyword) {
   if (!url.is_valid())
     return;
 
@@ -610,9 +621,9 @@
                   selected_line, keyword);
 }
 
-std::wstring AutocompleteEditViewWin::GetText() const {
+string16 AutocompleteEditViewWin::GetText() const {
   const int len = GetTextLength() + 1;
-  std::wstring str;
+  string16 str;
   GetWindowText(WriteInto(&str, len), len);
   return str;
 }
@@ -627,12 +638,12 @@
       toolbar_model_->GetIcon();
 }
 
-void AutocompleteEditViewWin::SetUserText(const std::wstring& text) {
+void AutocompleteEditViewWin::SetUserText(const string16& text) {
   SetUserText(text, text, true);
 }
 
-void AutocompleteEditViewWin::SetUserText(const std::wstring& text,
-                                          const std::wstring& display_text,
+void AutocompleteEditViewWin::SetUserText(const string16& text,
+                                          const string16& display_text,
                                           bool update_popup) {
   ScopedFreeze freeze(this, GetTextObjectModel());
   model_->SetUserText(text);
@@ -643,16 +654,16 @@
   TextChanged();
 }
 
-void AutocompleteEditViewWin::SetWindowTextAndCaretPos(const std::wstring& text,
+void AutocompleteEditViewWin::SetWindowTextAndCaretPos(const string16& text,
                                                        size_t caret_pos) {
   SetWindowText(text.c_str());
   PlaceCaretAt(caret_pos);
 }
 
 void AutocompleteEditViewWin::SetForcedQuery() {
-  const std::wstring current_text(GetText());
+  const string16 current_text(GetText());
   const size_t start = current_text.find_first_not_of(kWhitespaceWide);
-  if (start == std::wstring::npos || (current_text[start] != '?'))
+  if (start == string16::npos || (current_text[start] != '?'))
     SetUserText(L"?");
   else
     SetSelection(current_text.length(), start + 1);
@@ -668,8 +679,8 @@
   return delete_at_end_pressed_;
 }
 
-void AutocompleteEditViewWin::GetSelectionBounds(std::wstring::size_type* start,
-                                                 std::wstring::size_type* end) {
+void AutocompleteEditViewWin::GetSelectionBounds(string16::size_type* start,
+                                                 string16::size_type* end) {
   CHARRANGE selection;
   GetSel(selection);
   *start = static_cast<size_t>(selection.cpMin);
@@ -761,7 +772,7 @@
 }
 
 void AutocompleteEditViewWin::MoveSelectedText(int new_position) {
-  const std::wstring selected_text(GetSelectedText());
+  const string16 selected_text(GetSelectedText());
   CHARRANGE sel;
   GetSel(sel);
   DCHECK((sel.cpMax != sel.cpMin) && (new_position >= 0) &&
@@ -783,7 +794,7 @@
 }
 
 void AutocompleteEditViewWin::InsertText(int position,
-                                         const std::wstring& text) {
+                                         const string16& text) {
   DCHECK((position >= 0) && (position <= GetTextLength()));
   ScopedFreeze freeze(this, GetTextObjectModel());
   OnBeforePossibleChange();
@@ -793,7 +804,7 @@
 }
 
 void AutocompleteEditViewWin::OnTemporaryTextMaybeChanged(
-    const std::wstring& display_text,
+    const string16& display_text,
     bool save_original_selection) {
   if (save_original_selection)
     GetSelection(original_selection_);
@@ -811,7 +822,7 @@
 }
 
 bool AutocompleteEditViewWin::OnInlineAutocompleteTextMaybeChanged(
-    const std::wstring& display_text,
+    const string16& display_text,
     size_t user_text_length) {
   // Update the text and selection.  Because this can be called repeatedly while
   // typing, we've careful not to freeze the edit unless we really need to.
@@ -843,6 +854,11 @@
 }
 
 bool AutocompleteEditViewWin::OnAfterPossibleChange() {
+  return OnAfterPossibleChangeInternal(false);
+}
+
+bool AutocompleteEditViewWin::OnAfterPossibleChangeInternal(
+    bool force_text_changed) {
   // Prevent the user from selecting the "phantom newline" at the end of the
   // edit.  If they try, we just silently move the end of the selection back to
   // the end of the real text.
@@ -856,14 +872,18 @@
       new_sel.cpMax = length;
     SetSelectionRange(new_sel);
   }
-  const bool selection_differs = (new_sel.cpMin != sel_before_change_.cpMin) ||
-      (new_sel.cpMax != sel_before_change_.cpMax);
+  const bool selection_differs =
+      ((new_sel.cpMin != new_sel.cpMax) ||
+       (sel_before_change_.cpMin != sel_before_change_.cpMax)) &&
+      ((new_sel.cpMin != sel_before_change_.cpMin) ||
+       (new_sel.cpMax != sel_before_change_.cpMax));
   const bool at_end_of_edit =
       (new_sel.cpMin == length) && (new_sel.cpMax == length);
 
   // See if the text or selection have changed since OnBeforePossibleChange().
-  const std::wstring new_text(GetText());
-  const bool text_differs = (new_text != text_before_change_);
+  const string16 new_text(GetText());
+  const bool text_differs = (new_text != text_before_change_) ||
+      force_text_changed;
 
   // When the user has deleted text, we don't allow inline autocomplete.  Make
   // sure to not flag cases like selecting part of the text and then pasting
@@ -875,9 +895,10 @@
       (new_sel.cpMin <= std::min(sel_before_change_.cpMin,
                                  sel_before_change_.cpMax));
 
-
+  const bool allow_keyword_ui_change = at_end_of_edit && !IsImeComposing();
   const bool something_changed = model_->OnAfterPossibleChange(new_text,
-      selection_differs, text_differs, just_deleted_text, at_end_of_edit);
+      selection_differs, text_differs, just_deleted_text,
+      allow_keyword_ui_change);
 
   if (selection_differs)
     controller_->OnSelectionBoundsChanged();
@@ -909,6 +930,31 @@
   return command_updater_;
 }
 
+void AutocompleteEditViewWin::SetInstantSuggestion(const string16& suggestion) {
+  // On Windows, we shows the suggestion in LocationBarView.
+  NOTREACHED();
+}
+
+string16 AutocompleteEditViewWin::GetInstantSuggestion() const {
+  // On Windows, we shows the suggestion in LocationBarView.
+  NOTREACHED();
+  return string16();
+}
+
+int AutocompleteEditViewWin::TextWidth() const {
+  return WidthNeededToDisplay(GetText());
+}
+
+bool AutocompleteEditViewWin::IsImeComposing() const {
+  bool ime_composing = false;
+  HIMC context = ImmGetContext(m_hWnd);
+  if (context) {
+    ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
+    ImmReleaseContext(m_hWnd, context);
+  }
+  return ime_composing;
+}
+
 views::View* AutocompleteEditViewWin::AddToView(views::View* parent) {
   views::NativeViewHost* host = new views::NativeViewHost;
   parent->AddChildView(host);
@@ -917,34 +963,18 @@
   return host;
 }
 
-bool AutocompleteEditViewWin::CommitInstantSuggestion(
-    const std::wstring& typed_text,
-    const std::wstring& suggested_text) {
-  model_->FinalizeInstantQuery(typed_text, suggested_text);
-  return true;
-}
-
-void AutocompleteEditViewWin::SetInstantSuggestion(const string16& suggestion) {
-  // Win shows the suggestion in LocationBarView.
-  NOTREACHED();
-}
-
-int AutocompleteEditViewWin::TextWidth() const {
-  return WidthNeededToDisplay(GetText());
-}
-
-void AutocompleteEditViewWin::PasteAndGo(const std::wstring& text) {
+void AutocompleteEditViewWin::PasteAndGo(const string16& text) {
   if (CanPasteAndGo(text))
     model_->PasteAndGo();
 }
 
 bool AutocompleteEditViewWin::SkipDefaultKeyEventProcessing(
     const views::KeyEvent& e) {
-  app::KeyboardCode key = e.GetKeyCode();
+  ui::KeyboardCode key = e.key_code();
   // We don't process ALT + numpad digit as accelerators, they are used for
   // entering special characters.  We do translate alt-home.
-  if (e.IsAltDown() && (key != app::VKEY_HOME) &&
-      app::win::IsNumPadDigit(key, e.IsExtendedKey()))
+  if (e.IsAltDown() && (key != ui::VKEY_HOME) &&
+      views::NativeTextfieldWin::IsNumPadDigit(key, views::IsExtendedKey(e)))
     return true;
 
   // Skip accelerators for key combinations omnibox wants to crack. This list
@@ -955,28 +985,28 @@
   // accelerators (e.g., F5 for reload the page should work even when the
   // Omnibox gets focused).
   switch (key) {
-    case app::VKEY_ESCAPE: {
+    case ui::VKEY_ESCAPE: {
       ScopedFreeze freeze(this, GetTextObjectModel());
       return model_->OnEscapeKeyPressed();
     }
 
-    case app::VKEY_RETURN:
+    case ui::VKEY_RETURN:
       return true;
 
-    case app::VKEY_UP:
-    case app::VKEY_DOWN:
+    case ui::VKEY_UP:
+    case ui::VKEY_DOWN:
       return !e.IsAltDown();
 
-    case app::VKEY_DELETE:
-    case app::VKEY_INSERT:
+    case ui::VKEY_DELETE:
+    case ui::VKEY_INSERT:
       return !e.IsAltDown() && e.IsShiftDown() && !e.IsControlDown();
 
-    case app::VKEY_X:
-    case app::VKEY_V:
+    case ui::VKEY_X:
+    case ui::VKEY_V:
       return !e.IsAltDown() && e.IsControlDown();
 
-    case app::VKEY_BACK:
-    case app::VKEY_OEM_PLUS:
+    case ui::VKEY_BACK:
+    case ui::VKEY_OEM_PLUS:
       return true;
 
     default:
@@ -1019,7 +1049,7 @@
 
 bool AutocompleteEditViewWin::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   return parent_view_->GetWidget()->GetAccelerator(command_id, accelerator);
 }
 
@@ -1029,7 +1059,7 @@
   return command_id == IDS_PASTE_AND_GO;
 }
 
-std::wstring AutocompleteEditViewWin::GetLabelForCommandId(
+string16 AutocompleteEditViewWin::GetLabelForCommandId(
     int command_id) const {
   DCHECK(command_id == IDS_PASTE_AND_GO);
   return l10n_util::GetStringUTF16(model_->is_paste_and_search() ?
@@ -1241,7 +1271,7 @@
 }
 
 void AutocompleteEditViewWin::OnCopy() {
-  std::wstring text(GetSelectedText());
+  string16 text(GetSelectedText());
   if (text.empty())
     return;
 
@@ -1252,7 +1282,7 @@
   // GetSel() doesn't preserve selection direction, so sel.cpMin will always be
   // the smaller value.
   model_->AdjustTextForCopy(sel.cpMin, IsSelectAll(), &text, &url, &write_url);
-  ScopedClipboardWriter scw(g_browser_process->clipboard());
+  ui::ScopedClipboardWriter scw(g_browser_process->clipboard());
   scw.WriteText(text);
   if (write_url) {
     scw.WriteBookmark(text, url.spec());
@@ -1301,70 +1331,13 @@
   ScopedFreeze freeze(this, GetTextObjectModel());
   OnBeforePossibleChange();
   LRESULT result = DefWindowProc(message, wparam, lparam);
-
-  // Some IMEs insert whitespace characters instead of input characters while
-  // they are composing text, and trimming these whitespace characters at the
-  // beginning of this control (in OnAfterPossibleChange()) prevents users from
-  // inputting text on these IMEs.
-  // To prevent this problem, we should not start auto-complete if the
-  // composition string starts with whitespace characters.
-  // (When we type a space key to insert a whitespace character, IMEs don't
-  // insert the whitespace character to their composition string but their
-  // result string. So, this code doesn't prevent us from updating autocomplete
-  // when we insert a whitespace character.)
-  if (lparam & GCS_COMPSTR) {
-    std::wstring text;
-    HIMC context = ImmGetContext(m_hWnd);
-    if (context) {
-      int size = ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
-      if (size > 0) {
-        wchar_t* text_data = WriteInto(&text, size / sizeof(wchar_t) + 1);
-        if (text_data)
-          ImmGetCompositionString(context, GCS_COMPSTR, text_data, size);
-      }
-      ImmReleaseContext(m_hWnd, context);
-    }
-    if (!text.empty() && IsWhitespace(text[0]))
-      return result;
-  }
-
-  if (!OnAfterPossibleChange() && (lparam & GCS_RESULTSTR)) {
-    // The result string changed, but the text in the popup didn't actually
-    // change.  This means the user finalized the composition.  Rerun
-    // autocomplete so that we can now trigger inline autocomplete if
-    // applicable.
-    //
-    // Note that if we're in the midst of losing focus, UpdatePopup() won't
-    // actually rerun autocomplete, but will just set local state correctly.
-    UpdatePopup();
-  }
+  // Force an IME composition confirmation operation to trigger the text_changed
+  // code in OnAfterPossibleChange(), even if identical contents are confirmed,
+  // to make sure the model can update its internal states correctly.
+  OnAfterPossibleChangeInternal((lparam & GCS_RESULTSTR) != 0);
   return result;
 }
 
-LRESULT AutocompleteEditViewWin::OnImeNotify(UINT message,
-                                             WPARAM wparam,
-                                             LPARAM lparam) {
-  // NOTE: I'm not sure this is ever reached with |ignore_ime_messages_| set,
-  // but if it is, the safe thing to do is to only call DefWindowProc().
-  if (!ignore_ime_messages_ && (wparam == IMN_SETOPENSTATUS)) {
-    // A user has activated (or deactivated) IMEs (but not started a
-    // composition).
-    // Some IMEs get confused when we accept keywords while they are composing
-    // text. To prevent this situation, we accept keywords when an IME is
-    // activated.
-    HIMC imm_context = ImmGetContext(m_hWnd);
-    if (imm_context) {
-      if (ImmGetOpenStatus(imm_context) &&
-          model_->is_keyword_hint() && !model_->keyword().empty()) {
-        ScopedFreeze freeze(this, GetTextObjectModel());
-        model_->AcceptKeyword();
-      }
-      ImmReleaseContext(m_hWnd, imm_context);
-    }
-  }
-  return DefWindowProc(message, wparam, lparam);
-}
-
 void AutocompleteEditViewWin::OnKeyDown(TCHAR key,
                                         UINT repeat_count,
                                         UINT flags) {
@@ -1406,7 +1379,7 @@
        ((key == VK_SHIFT) && (GetKeyState(VK_CONTROL) < 0)))) {
     ScopedFreeze freeze(this, GetTextObjectModel());
 
-    std::wstring saved_text(GetText());
+    string16 saved_text(GetText());
     CHARRANGE saved_sel;
     GetSelection(saved_sel);
 
@@ -1497,8 +1470,8 @@
   // double_click_time_ from the current message's time even if the timer has
   // wrapped in between.
   const bool is_triple_click = tracking_double_click_ &&
-      app::win::IsDoubleClick(double_click_point_, point,
-                              GetCurrentMessage()->time - double_click_time_);
+      views::NativeTextfieldWin::IsDoubleClick(double_click_point_, point,
+          GetCurrentMessage()->time - double_click_time_);
   tracking_double_click_ = false;
 
   if (!gaining_focus_.get() && !is_triple_click)
@@ -1597,7 +1570,7 @@
     return;
   }
 
-  if (tracking_click_[kLeft] && !app::win::IsDrag(click_point_[kLeft], point))
+  if (tracking_click_[kLeft] && !IsDrag(click_point_[kLeft], point))
     return;
 
   tracking_click_[kLeft] = false;
@@ -1728,12 +1701,10 @@
 
 void AutocompleteEditViewWin::OnPaste() {
   // Replace the selection if we have something to paste.
-  const std::wstring text(GetClipboardText());
+  const string16 text(GetClipboardText());
   if (!text.empty()) {
-    // If this paste will be replacing all the text, record that, so we can do
-    // different behaviors in such a case.
-    if (IsSelectAll())
-      model_->on_paste_replacing_all();
+    // Record this paste, so we can do different behavior.
+    model_->on_paste();
     // Force a Paste operation to trigger the text_changed code in
     // OnAfterPossibleChange(), even if identical contents are pasted into the
     // text box.
@@ -1835,7 +1806,7 @@
   ScopedFreeze freeze(this, GetTextObjectModel());
   OnBeforePossibleChange();
 
-  if (key == app::VKEY_HOME || key == app::VKEY_END) {
+  if (key == ui::VKEY_HOME || key == ui::VKEY_END) {
     // DefWindowProc() might reset the keyboard layout when it receives a
     // keydown event for VKEY_HOME or VKEY_END. When the window was created
     // with WS_EX_LAYOUTRTL and the current keyboard layout is not a RTL one,
@@ -1887,7 +1858,7 @@
         GetSel(selection);
         return (selection.cpMin == selection.cpMax) &&
             (selection.cpMin == GetTextLength()) &&
-            controller_->OnCommitSuggestedText(GetText());
+            controller_->OnCommitSuggestedText(true);
       }
 
     case VK_RETURN:
@@ -2012,12 +1983,17 @@
     }
 
     case VK_TAB: {
-      if (model_->is_keyword_hint() && !model_->keyword().empty()) {
+      if (model_->is_keyword_hint()) {
         // Accept the keyword.
         ScopedFreeze freeze(this, GetTextObjectModel());
         model_->AcceptKeyword();
+      } else if (!IsCaretAtEnd()) {
+        ScopedFreeze freeze(this, GetTextObjectModel());
+        OnBeforePossibleChange();
+        PlaceCaretAt(GetTextLength());
+        OnAfterPossibleChange();
       } else {
-        controller_->OnCommitSuggestedText(GetText());
+        controller_->OnCommitSuggestedText(true);
       }
       return true;
     }
@@ -2072,13 +2048,13 @@
     std::swap(sel.cpMin, sel.cpMax);
 }
 
-std::wstring AutocompleteEditViewWin::GetSelectedText() const {
+string16 AutocompleteEditViewWin::GetSelectedText() const {
   // Figure out the length of the selection.
   CHARRANGE sel;
   GetSel(sel);
 
   // Grab the selected text.
-  std::wstring str;
+  string16 str;
   GetSelText(WriteInto(&str, sel.cpMax - sel.cpMin + 1));
   return str;
 }
@@ -2099,7 +2075,7 @@
   selection->SetFlags(tomSelStartActive);
 }
 
-void AutocompleteEditViewWin::PlaceCaretAt(std::wstring::size_type pos) {
+void AutocompleteEditViewWin::PlaceCaretAt(string16::size_type pos) {
   SetSelection(static_cast<LONG>(pos), static_cast<LONG>(pos));
 }
 
@@ -2358,13 +2334,13 @@
   controller_->OnChanged();
 }
 
-std::wstring AutocompleteEditViewWin::GetClipboardText() const {
+string16 AutocompleteEditViewWin::GetClipboardText() const {
   // Try text format.
-  Clipboard* clipboard = g_browser_process->clipboard();
-  if (clipboard->IsFormatAvailable(Clipboard::GetPlainTextWFormatType(),
-                                   Clipboard::BUFFER_STANDARD)) {
-    std::wstring text;
-    clipboard->ReadText(Clipboard::BUFFER_STANDARD, &text);
+  ui::Clipboard* clipboard = g_browser_process->clipboard();
+  if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
+                                   ui::Clipboard::BUFFER_STANDARD)) {
+    string16 text;
+    clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &text);
 
     // Note: Unlike in the find popup and textfield view, here we completely
     // remove whitespace strings containing newlines.  We assume users are
@@ -2382,8 +2358,8 @@
   // and pastes from the URL bar to itself, the text will get fixed up and
   // cannonicalized, which is not what the user expects.  By pasting in this
   // order, we are sure to paste what the user copied.
-  if (clipboard->IsFormatAvailable(Clipboard::GetUrlWFormatType(),
-                                   Clipboard::BUFFER_STANDARD)) {
+  if (clipboard->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
+                                   ui::Clipboard::BUFFER_STANDARD)) {
     std::string url_str;
     clipboard->ReadBookmark(NULL, &url_str);
     // pass resulting url string through GURL to normalize
@@ -2392,10 +2368,10 @@
       return UTF8ToWide(url.spec());
   }
 
-  return std::wstring();
+  return string16();
 }
 
-bool AutocompleteEditViewWin::CanPasteAndGo(const std::wstring& text) const {
+bool AutocompleteEditViewWin::CanPasteAndGo(const string16& text) const {
   return !popup_window_mode_ && model_->CanPasteAndGo(text);
 }
 
@@ -2415,10 +2391,10 @@
 }
 
 void AutocompleteEditViewWin::StartDragIfNecessary(const CPoint& point) {
-  if (initiated_drag_ || !app::win::IsDrag(click_point_[kLeft], point))
+  if (initiated_drag_ || !IsDrag(click_point_[kLeft], point))
     return;
 
-  OSExchangeData data;
+  ui::OSExchangeData data;
 
   DWORD supported_modes = DROPEFFECT_COPY;
 
@@ -2439,8 +2415,8 @@
     SetSelectionRange(sel);
   }
 
-  const std::wstring start_text(GetText());
-  std::wstring text_to_write(GetSelectedText());
+  const string16 start_text(GetText());
+  string16 text_to_write(GetSelectedText());
   GURL url;
   bool write_url;
   const bool is_all_selected = IsSelectAllForRange(sel);
@@ -2451,7 +2427,7 @@
                              &text_to_write, &url, &write_url);
 
   if (write_url) {
-    std::wstring title;
+    string16 title;
     SkBitmap favicon;
     if (is_all_selected)
       model_->GetDataForURLExport(&url, &title, &favicon);
@@ -2467,11 +2443,12 @@
 
   data.SetString(text_to_write);
 
-  scoped_refptr<app::win::DragSource> drag_source(new app::win::DragSource);
+  scoped_refptr<ui::DragSource> drag_source(new ui::DragSource);
   DWORD dropped_mode;
   AutoReset<bool> auto_reset_in_drag(&in_drag_, true);
-  if (DoDragDrop(OSExchangeDataProviderWin::GetIDataObject(data), drag_source,
-                 supported_modes, &dropped_mode) == DRAGDROP_S_DROP) {
+  if (DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data),
+                 drag_source, supported_modes, &dropped_mode) ==
+          DRAGDROP_S_DROP) {
     if ((dropped_mode == DROPEFFECT_MOVE) && (start_text == GetText())) {
       ScopedFreeze freeze(this, GetTextObjectModel());
       OnBeforePossibleChange();
@@ -2544,7 +2521,7 @@
   if (context_menu_contents_.get())
     return;
 
-  context_menu_contents_.reset(new menus::SimpleMenuModel(this));
+  context_menu_contents_.reset(new ui::SimpleMenuModel(this));
   // Set up context menu.
   if (popup_window_mode_) {
     context_menu_contents_->AddItemWithStringId(IDC_COPY, IDS_COPY);
@@ -2571,7 +2548,7 @@
                                                    const CPoint& point) {
   // When the user has clicked and released to give us focus, select all.
   if (tracking_click_[button] &&
-      !app::win::IsDrag(click_point_[button], point)) {
+      !IsDrag(click_point_[button], point)) {
     // Select all in the reverse direction so as not to scroll the caret
     // into view and shift the contents jarringly.
     SelectAll(true);
@@ -2599,7 +2576,7 @@
 }
 
 int AutocompleteEditViewWin::WidthNeededToDisplay(
-    const std::wstring& text) const {
+    const string16& text) const {
   // Use font_.GetStringWidth() instead of
   // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is
   // apparently buggy. In both LTR UI and RTL UI with left-to-right layout,
@@ -2607,12 +2584,9 @@
   return font_.GetStringWidth(text) + GetHorizontalMargin();
 }
 
-bool AutocompleteEditViewWin::IsImeComposing() const {
-  bool ime_composing = false;
-  HIMC context = ImmGetContext(m_hWnd);
-  if (context) {
-    ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
-    ImmReleaseContext(m_hWnd, context);
-  }
-  return ime_composing;
+bool AutocompleteEditViewWin::IsCaretAtEnd() const {
+  long length = GetTextLength();
+  CHARRANGE sel;
+  GetSelection(sel);
+  return sel.cpMin == sel.cpMax && sel.cpMin == length;
 }
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
index 7fc56a9..aaa4b73 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,15 +13,15 @@
 #include <atlmisc.h>
 #include <tom.h>  // For ITextDocument, a COM interface to CRichEditCtrl.
 
-#include "app/menus/simple_menu_model.h"
 #include "base/scoped_comptr_win.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
 #include "chrome/browser/ui/toolbar/toolbar_model.h"
-#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/font.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/font.h"
 #include "views/controls/menu/menu_2.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -45,7 +45,7 @@
                          CWinTraits<WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |
                                     ES_NOHIDESEL> >,
       public CRichEditCommands<AutocompleteEditViewWin>,
-      public menus::SimpleMenuModel::Delegate,
+      public ui::SimpleMenuModel::Delegate,
       public AutocompleteEditView {
  public:
   struct State {
@@ -95,27 +95,27 @@
                        PageTransition::Type transition,
                        const GURL& alternate_nav_url,
                        size_t selected_line,
-                       const std::wstring& keyword);
+                       const string16& keyword);
 
-  virtual std::wstring GetText() const;
+  virtual string16 GetText() const;
 
   virtual bool IsEditingOrEmpty() const;
   virtual int GetIcon() const;
 
-  virtual void SetUserText(const std::wstring& text);
-  virtual void SetUserText(const std::wstring& text,
-                           const std::wstring& display_text,
+  virtual void SetUserText(const string16& text);
+  virtual void SetUserText(const string16& text,
+                           const string16& display_text,
                            bool update_popup);
 
-  virtual void SetWindowTextAndCaretPos(const std::wstring& text,
+  virtual void SetWindowTextAndCaretPos(const string16& text,
                                         size_t caret_pos);
 
   virtual void SetForcedQuery();
 
   virtual bool IsSelectAll();
   virtual bool DeleteAtEndPressed();
-  virtual void GetSelectionBounds(std::wstring::size_type* start,
-                                  std::wstring::size_type* end);
+  virtual void GetSelectionBounds(string16::size_type* start,
+                                  string16::size_type* end);
   virtual void SelectAll(bool reversed);
   virtual void RevertAll();
 
@@ -124,20 +124,21 @@
 
   virtual void SetFocus();
 
-  virtual void OnTemporaryTextMaybeChanged(const std::wstring& display_text,
+  virtual void OnTemporaryTextMaybeChanged(const string16& display_text,
                                            bool save_original_selection);
   virtual bool OnInlineAutocompleteTextMaybeChanged(
-      const std::wstring& display_text, size_t user_text_length);
+      const string16& display_text, size_t user_text_length);
   virtual void OnRevertTemporaryText();
   virtual void OnBeforePossibleChange();
   virtual bool OnAfterPossibleChange();
   virtual gfx::NativeView GetNativeView() const;
   virtual CommandUpdater* GetCommandUpdater();
-  virtual views::View* AddToView(views::View* parent);
-  virtual bool CommitInstantSuggestion(const std::wstring& typed_text,
-                                       const std::wstring& suggested_text);
   virtual void SetInstantSuggestion(const string16& suggestion);
+  virtual string16 GetInstantSuggestion() const;
   virtual int TextWidth() const;
+  virtual bool IsImeComposing() const;
+
+  virtual views::View* AddToView(views::View* parent);
 
   int GetPopupMaxYCoordinate();
 
@@ -154,12 +155,12 @@
   void MoveSelectedText(int new_position);
 
   // Inserts the text at the specified position.
-  void InsertText(int position, const std::wstring& text);
+  void InsertText(int position, const string16& text);
 
   // Invokes CanPasteAndGo with the specified text, and if successful navigates
   // to the appropriate URL. The behavior of this is the same as if the user
   // typed in the specified text and pressed enter.
-  void PasteAndGo(const std::wstring& text);
+  void PasteAndGo(const string16& text);
 
   void set_force_hidden(bool force_hidden) { force_hidden_ = force_hidden; }
 
@@ -179,7 +180,6 @@
     MSG_WM_CUT(OnCut)
     MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
     MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition)
-    MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeNotify)
     MSG_WM_KEYDOWN(OnKeyDown)
     MSG_WM_KEYUP(OnKeyUp)
     MSG_WM_KILLFOCUS(OnKillFocus)
@@ -206,17 +206,17 @@
     DEFAULT_REFLECTION_HANDLER()  // avoids black margin area
   END_MSG_MAP()
 
-  // menus::SimpleMenuModel::Delegate
+  // ui::SimpleMenuModel::Delegate
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual bool IsItemForCommandIdDynamic(int command_id) const;
-  virtual std::wstring GetLabelForCommandId(int command_id) const;
+  virtual string16 GetLabelForCommandId(int command_id) const;
   virtual void ExecuteCommand(int command_id);
 
-  // Returns true if the user is composing something in an IME.
-  bool IsImeComposing() const;
+  // Returns true if the caret is at the end of the content.
+  bool IsCaretAtEnd() const;
 
  private:
   enum MouseButton {
@@ -275,7 +275,6 @@
   void OnCut();
   LRESULT OnGetObject(UINT uMsg, WPARAM wparam, LPARAM lparam);
   LRESULT OnImeComposition(UINT message, WPARAM wparam, LPARAM lparam);
-  LRESULT OnImeNotify(UINT message, WPARAM wparam, LPARAM lparam);
   void OnKeyDown(TCHAR key, UINT repeat_count, UINT flags);
   void OnKeyUp(TCHAR key, UINT repeat_count, UINT flags);
   void OnKillFocus(HWND focus_wnd);
@@ -315,7 +314,7 @@
   void GetSelection(CHARRANGE& sel) const;
 
   // Returns the currently selected text of the edit control.
-  std::wstring GetSelectedText() const;
+  string16 GetSelectedText() const;
 
   // Like SetSel(), but respects the selection direction implied by |start| and
   // |end|: if |end| < |start|, the effective cursor will be placed at the
@@ -373,10 +372,10 @@
   // Returns the current clipboard contents as a string that can be pasted in.
   // In addition to just getting CF_UNICODETEXT out, this can also extract URLs
   // from bookmarks on the clipboard.
-  std::wstring GetClipboardText() const;
+  string16 GetClipboardText() const;
 
   // Determines whether the user can "paste and go", given the specified text.
-  bool CanPasteAndGo(const std::wstring& text) const;
+  bool CanPasteAndGo(const string16& text) const;
 
   // Getter for the text_object_model_.  Note that the pointer returned here is
   // only valid as long as the AutocompleteEdit is still alive.  Also, if the
@@ -406,7 +405,12 @@
   int GetHorizontalMargin() const;
 
   // Returns the width in pixels needed to display |text|.
-  int WidthNeededToDisplay(const std::wstring& text) const;
+  int WidthNeededToDisplay(const string16& text) const;
+
+  // Real implementation of OnAfterPossibleChange() method.
+  // If |force_text_changed| is true, then the text_changed code will always be
+  // triggerred no matter if the text is actually changed or not.
+  bool OnAfterPossibleChangeInternal(bool force_text_changed);
 
   scoped_ptr<AutocompleteEditModel> model_;
 
@@ -470,7 +474,7 @@
   bool ignore_ime_messages_;
 
   // Variables for tracking state before and after a possible change.
-  std::wstring text_before_change_;
+  string16 text_before_change_;
   CHARRANGE sel_before_change_;
 
   // Set at the same time the model's original_* members are set, and valid in
@@ -485,7 +489,7 @@
   bool delete_at_end_pressed_;
 
   // The context menu for the edit.
-  scoped_ptr<menus::SimpleMenuModel> context_menu_contents_;
+  scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
   scoped_ptr<views::Menu2> context_menu_;
 
   // Font we're using.  We keep a reference to make sure the font supplied to
diff --git a/chrome/browser/autocomplete/autocomplete_match.cc b/chrome/browser/autocomplete/autocomplete_match.cc
index 57d57cd..f05892e 100644
--- a/chrome/browser/autocomplete/autocomplete_match.cc
+++ b/chrome/browser/autocomplete/autocomplete_match.cc
@@ -12,12 +12,13 @@
     : provider(NULL),
       relevance(0),
       deletable(false),
-      inline_autocomplete_offset(std::wstring::npos),
+      inline_autocomplete_offset(string16::npos),
       transition(PageTransition::GENERATED),
       is_history_what_you_typed_match(false),
       type(SEARCH_WHAT_YOU_TYPED),
       template_url(NULL),
-      starred(false) {
+      starred(false),
+      from_previous(false) {
 }
 
 AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
@@ -27,12 +28,13 @@
     : provider(provider),
       relevance(relevance),
       deletable(deletable),
-      inline_autocomplete_offset(std::wstring::npos),
+      inline_autocomplete_offset(string16::npos),
       transition(PageTransition::TYPED),
       is_history_what_you_typed_match(false),
       type(type),
       template_url(NULL),
-      starred(false) {
+      starred(false),
+      from_previous(false) {
 }
 
 AutocompleteMatch::~AutocompleteMatch() {
@@ -51,7 +53,6 @@
     "search-history",
     "search-suggest",
     "search-other-engine",
-    "open-history-page",
   };
   DCHECK(arraysize(strings) == NUM_TYPES);
   return strings[type];
@@ -70,7 +71,6 @@
     IDR_OMNIBOX_SEARCH,
     IDR_OMNIBOX_SEARCH,
     IDR_OMNIBOX_SEARCH,
-    IDR_OMNIBOX_MORE,
   };
   DCHECK(arraysize(icons) == NUM_TYPES);
   return icons[type];
@@ -85,12 +85,7 @@
   if (elem1.relevance == elem2.relevance)
     return elem1.contents > elem2.contents;
 
-  // A negative relevance indicates the real relevance can be determined by
-  // negating the value. If both relevances are negative, negate the result
-  // so that we end up with positive relevances, then negative relevances with
-  // the negative relevances sorted by absolute values.
-  const bool result = elem1.relevance > elem2.relevance;
-  return (elem1.relevance < 0 && elem2.relevance < 0) ? !result : result;
+  return elem1.relevance > elem2.relevance;
 }
 
 // static
@@ -112,8 +107,8 @@
 
 // static
 void AutocompleteMatch::ClassifyMatchInString(
-    const std::wstring& find_text,
-    const std::wstring& text,
+    const string16& find_text,
+    const string16& text,
     int style,
     ACMatchClassifications* classification) {
   ClassifyLocationInString(text.find(find_text), find_text.length(),
@@ -139,7 +134,7 @@
   }
 
   // Mark matching portion of string.
-  if (match_location == std::wstring::npos) {
+  if (match_location == string16::npos) {
     // No match, above classification will suffice for whole string.
     return;
   }
@@ -163,7 +158,7 @@
 }
 
 void AutocompleteMatch::ValidateClassifications(
-    const std::wstring& text,
+    const string16& text,
     const ACMatchClassifications& classifications) const {
   if (text.empty()) {
     DCHECK(classifications.size() == 0);
diff --git a/chrome/browser/autocomplete/autocomplete_match.h b/chrome/browser/autocomplete/autocomplete_match.h
index d65ff5f..49d9fbb 100644
--- a/chrome/browser/autocomplete/autocomplete_match.h
+++ b/chrome/browser/autocomplete/autocomplete_match.h
@@ -77,8 +77,6 @@
                              // containing the input.
     SEARCH_SUGGEST,          // A suggested search (with the default engine).
     SEARCH_OTHER_ENGINE,     // A search with a non-default engine.
-    OPEN_HISTORY_PAGE,       // A synthetic result that opens the history page
-                             // to search for the input.
     NUM_TYPES,
   };
 
@@ -110,8 +108,8 @@
   // Fills in the classifications for |text|, using |style| as the base style
   // and marking the first instance of |find_text| as a match.  (This match
   // will also not be dimmed, if |style| has DIM set.)
-  static void ClassifyMatchInString(const std::wstring& find_text,
-                                    const std::wstring& text,
+  static void ClassifyMatchInString(const string16& find_text,
+                                    const string16& text,
                                     int style,
                                     ACMatchClassifications* classifications);
 
@@ -135,13 +133,6 @@
   // providers, so different providers must be carefully tuned to supply
   // matches with appropriate relevance.
   //
-  // If the relevance is negative, it will only be displayed if there are not
-  // enough non-negative items in all the providers to max out the popup. In
-  // this case, the relevance of the additional items will be inverted so they
-  // can be mixed in with the rest of the relevances. This allows a provider
-  // to group its matches, having the added items appear intermixed with its
-  // other matches.
-  //
   // TODO(pkasting): http://b/1111299 This should be calculated algorithmically,
   // rather than being a fairly fixed value defined by the table above.
   int relevance;
@@ -152,10 +143,10 @@
   // This string is loaded into the location bar when the item is selected
   // by pressing the arrow keys. This may be different than a URL, for example,
   // for search suggestions, this would just be the search terms.
-  std::wstring fill_into_edit;
+  string16 fill_into_edit;
 
   // The position within fill_into_edit from which we'll display the inline
-  // autocomplete string.  This will be std::wstring::npos if this match should
+  // autocomplete string.  This will be string16::npos if this match should
   // not be inline autocompleted.
   size_t inline_autocomplete_offset;
 
@@ -165,11 +156,11 @@
   GURL destination_url;
 
   // The main text displayed in the address bar dropdown.
-  std::wstring contents;
+  string16 contents;
   ACMatchClassifications contents_class;
 
   // Additional helper text for each entry, such as a title or description.
-  std::wstring description;
+  string16 description;
   ACMatchClassifications description_class;
 
   // The transition type to use when the user opens this match.  By default
@@ -191,13 +182,16 @@
   // True if the user has starred the destination URL.
   bool starred;
 
+  // True if this match is from a previous result.
+  bool from_previous;
+
 #ifndef NDEBUG
   // Does a data integrity check on this match.
   void Validate() const;
 
   // Checks one text/classifications pair for valid values.
   void ValidateClassifications(
-      const std::wstring& text,
+      const string16& text,
       const ACMatchClassifications& classifications) const;
 #endif
 };
diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.cc b/chrome/browser/autocomplete/autocomplete_popup_model.cc
index 2ea4068..6809d0c 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_model.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_model.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include "unicode/ubidi.h"
 
 #include "base/string_util.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_edit.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_view.h"
@@ -17,9 +18,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // AutocompletePopupModel
@@ -34,8 +33,6 @@
       profile_(profile),
       hovered_line_(kNoMatch),
       selected_line_(kNoMatch) {
-  registrar_.Add(this, NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
-                 Source<AutocompleteController>(controller_.get()));
 }
 
 AutocompletePopupModel::~AutocompletePopupModel() {
@@ -48,17 +45,18 @@
 }
 
 void AutocompletePopupModel::StartAutocomplete(
-    const std::wstring& text,
-    const std::wstring& desired_tld,
+    const string16& text,
+    const string16& desired_tld,
     bool prevent_inline_autocomplete,
-    bool prefer_keyword) {
+    bool prefer_keyword,
+    bool allow_exact_keyword_match) {
   // The user is interacting with the edit, so stop tracking hover.
   SetHoveredLine(kNoMatch);
 
   manually_selected_match_.Clear();
 
   controller_->Start(text, desired_tld, prevent_inline_autocomplete,
-                     prefer_keyword, true, false);
+                     prefer_keyword, allow_exact_keyword_match, false);
 }
 
 void AutocompletePopupModel::StopAutocomplete() {
@@ -88,12 +86,8 @@
 }
 
 void AutocompletePopupModel::SetSelectedLine(size_t line,
-                                             bool reset_to_default) {
-  // We should at least be dealing with the results of the current query.  Note
-  // that even if |line| was valid on entry, this may make it invalid.  We clamp
-  // it below.
-  controller_->CommitIfQueryHasNeverBeenCommitted();
-
+                                             bool reset_to_default,
+                                             bool force) {
   const AutocompleteResult& result = controller_->result();
   if (result.empty())
     return;
@@ -113,7 +107,7 @@
         match.is_history_what_you_typed_match;
   }
 
-  if (line == selected_line_)
+  if (line == selected_line_ && !force)
     return;  // Nothing else to do.
 
   // We need to update |selected_line_| before calling OnPopupDataChanged(), so
@@ -132,11 +126,11 @@
   // Update the edit with the new data for this match.
   // TODO(pkasting): If |selected_line_| moves to the controller, this can be
   // eliminated and just become a call to the observer on the edit.
-  std::wstring keyword;
+  string16 keyword;
   const bool is_keyword_hint = GetKeywordForMatch(match, &keyword);
   if (reset_to_default) {
-    std::wstring inline_autocomplete_text;
-    if ((match.inline_autocomplete_offset != std::wstring::npos) &&
+    string16 inline_autocomplete_text;
+    if ((match.inline_autocomplete_offset != string16::npos) &&
         (match.inline_autocomplete_offset < match.fill_into_edit.length())) {
       inline_autocomplete_text =
           match.fill_into_edit.substr(match.inline_autocomplete_offset);
@@ -156,7 +150,7 @@
 void AutocompletePopupModel::ResetToDefaultMatch() {
   const AutocompleteResult& result = controller_->result();
   CHECK(!result.empty());
-  SetSelectedLine(result.default_match() - result.begin(), true);
+  SetSelectedLine(result.default_match() - result.begin(), true, false);
   view_->OnDragCanceled();
 }
 
@@ -164,43 +158,31 @@
     AutocompleteMatch* match,
     GURL* alternate_nav_url) const {
   DCHECK(match != NULL);
-  const AutocompleteResult* result;
+  const AutocompleteResult& result = controller_->result();
   if (!controller_->done()) {
-    // NOTE: Using latest_result() is important here since not only could it
-    // contain newer results than result() for the current query, it could even
-    // refer to an entirely different query (e.g. if the user is typing rapidly
-    // and the controller is purposefully delaying updates to avoid flicker).
-    result = &controller_->latest_result();
     // It's technically possible for |result| to be empty if no provider returns
     // a synchronous result but the query has not completed synchronously;
     // pratically, however, that should never actually happen.
-    if (result->empty())
+    if (result.empty())
       return;
     // The user cannot have manually selected a match, or the query would have
     // stopped.  So the default match must be the desired selection.
-    *match = *result->default_match();
+    *match = *result.default_match();
   } else {
     CHECK(IsOpen());
-    // The query isn't running, so the standard result set can't possibly be out
-    // of date.
-    //
-    // NOTE: In practice, it should actually be safe to use
-    // controller_->latest_result() here too, since the controller keeps that
-    // up-to-date.  However we generally try to avoid referring to that.
-    result = &controller_->result();
     // If there are no results, the popup should be closed (so we should have
     // failed the CHECK above), and URLsForDefaultMatch() should have been
     // called instead.
-    CHECK(!result->empty());
-    CHECK(selected_line_ < result->size());
-    *match = result->match_at(selected_line_);
+    CHECK(!result.empty());
+    CHECK(selected_line_ < result.size());
+    *match = result.match_at(selected_line_);
   }
   if (alternate_nav_url && manually_selected_match_.empty())
-    *alternate_nav_url = result->alternate_nav_url();
+    *alternate_nav_url = result.alternate_nav_url();
 }
 
 bool AutocompletePopupModel::GetKeywordForMatch(const AutocompleteMatch& match,
-                                                std::wstring* keyword) const {
+                                                string16* keyword) const {
   // Assume we have no keyword until we find otherwise.
   keyword->clear();
 
@@ -214,8 +196,8 @@
   if (!profile_->GetTemplateURLModel())
     return false;
   profile_->GetTemplateURLModel()->Load();
-  const std::wstring keyword_hint(
-      TemplateURLModel::CleanUserInputKeyword(match.fill_into_edit));
+  const string16 keyword_hint(TemplateURLModel::CleanUserInputKeyword(
+      match.fill_into_edit));
   if (keyword_hint.empty())
     return false;
 
@@ -240,8 +222,8 @@
 }
 
 void AutocompletePopupModel::FinalizeInstantQuery(
-    const std::wstring& input_text,
-    const std::wstring& suggest_text) {
+    const string16& input_text,
+    const string16& suggest_text) {
   if (IsOpen()) {
     SearchProvider* search_provider = controller_->search_provider();
     search_provider->FinalizeInstantQuery(input_text, suggest_text);
@@ -265,7 +247,7 @@
   // Clamp the new line to [0, result_.count() - 1].
   const size_t new_line = selected_line_ + count;
   SetSelectedLine(((count < 0) && (new_line >= selected_line_)) ? 0 : new_line,
-                  false);
+                  false, false);
 }
 
 void AutocompletePopupModel::TryDeletingCurrentItem() {
@@ -282,44 +264,25 @@
       controller_->result().match_at(selected_line_);
   if (match.deletable) {
     const size_t selected_line = selected_line_;
-    controller_->DeleteMatch(match);  // This may synchronously notify us that
-                                      // the results have changed.
+    const bool was_temporary_text = !manually_selected_match_.empty();
+
+    // This will synchronously notify both the edit and us that the results
+    // have changed, causing both to revert to the default match.
+    controller_->DeleteMatch(match);
     const AutocompleteResult& result = controller_->result();
-    if (!result.empty()) {
+    if (!result.empty() &&
+        (was_temporary_text || selected_line != selected_line_)) {
       // Move the selection to the next choice after the deleted one.
       // SetSelectedLine() will clamp to take care of the case where we deleted
       // the last item.
       // TODO(pkasting): Eventually the controller should take care of this
       // before notifying us, reducing flicker.  At that point the check for
       // deletability can move there too.
-      SetSelectedLine(selected_line, false);
+      SetSelectedLine(selected_line, false, true);
     }
   }
 }
 
-void AutocompletePopupModel::Observe(NotificationType type,
-                                     const NotificationSource& source,
-                                     const NotificationDetails& details) {
-  DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
-            type.value);
-
-  const AutocompleteResult* result =
-      Details<const AutocompleteResult>(details).ptr();
-  selected_line_ = result->default_match() == result->end() ?
-      kNoMatch : static_cast<size_t>(result->default_match() - result->begin());
-  // There had better not be a nonempty result set with no default match.
-  CHECK((selected_line_ != kNoMatch) || result->empty());
-  // If we're going to trim the window size to no longer include the hovered
-  // line, turn hover off.  Practically, this shouldn't happen, but it
-  // doesn't hurt to be defensive.
-  if ((hovered_line_ != kNoMatch) && (result->size() <= hovered_line_))
-    SetHoveredLine(kNoMatch);
-
-  view_->UpdatePopupAppearance();
-  edit_model_->ResultsUpdated();
-  edit_model_->PopupBoundsChangedTo(view_->GetTargetBounds());
-}
-
 const SkBitmap* AutocompletePopupModel::GetSpecialIconForMatch(
     const AutocompleteMatch& match) const {
   if (!match.template_url || !match.template_url->IsExtensionKeyword())
@@ -328,3 +291,19 @@
   return &profile_->GetExtensionService()->GetOmniboxPopupIcon(
       match.template_url->GetExtensionId());
 }
+
+void AutocompletePopupModel::OnResultChanged() {
+  const AutocompleteResult& result = controller_->result();
+  selected_line_ = result.default_match() == result.end() ?
+      kNoMatch : static_cast<size_t>(result.default_match() - result.begin());
+  // There had better not be a nonempty result set with no default match.
+  CHECK((selected_line_ != kNoMatch) || result.empty());
+  manually_selected_match_.Clear();
+  // If we're going to trim the window size to no longer include the hovered
+  // line, turn hover off.  Practically, this shouldn't happen, but it
+  // doesn't hurt to be defensive.
+  if ((hovered_line_ != kNoMatch) && (result.size() <= hovered_line_))
+    SetHoveredLine(kNoMatch);
+
+  view_->UpdatePopupAppearance();
+}
diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.h b/chrome/browser/autocomplete/autocomplete_popup_model.h
index 9c5384f..6402ff2 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_model.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_model.h
@@ -8,8 +8,6 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
 
 class AutocompleteEditModel;
 class AutocompleteEditView;
@@ -18,7 +16,7 @@
 
 class AutocompletePopupView;
 
-class AutocompletePopupModel : public NotificationObserver {
+class AutocompletePopupModel {
  public:
   AutocompletePopupModel(AutocompletePopupView* popup_view,
                          AutocompleteEditModel* edit_model,
@@ -30,10 +28,11 @@
 
   // Starts a new query running.  These parameters are passed through to the
   // autocomplete controller; see comments there.
-  void StartAutocomplete(const std::wstring& text,
-                         const std::wstring& desired_tld,
+  void StartAutocomplete(const string16& text,
+                         const string16& desired_tld,
                          bool prevent_inline_autocomplete,
-                         bool prefer_keyword);
+                         bool prefer_keyword,
+                         bool allow_exact_keyword_match);
 
   // Closes the window and cancels any pending asynchronous queries.
   void StopAutocomplete();
@@ -69,10 +68,12 @@
   // new temporary text.  |line| will be clamped to the range of valid lines.
   // |reset_to_default| is true when the selection is being reset back to the
   // default match, and thus there is no temporary text (and no
-  // |manually_selected_match_|).
+  // |manually_selected_match_|). If |force| is true then the selected line will
+  // be updated forcibly even if the |line| is same as the current selected
+  // line.
   // NOTE: This assumes the popup is open, and thus both old and new values for
   // the selected line should not be kNoMatch.
-  void SetSelectedLine(size_t line, bool reset_to_default);
+  void SetSelectedLine(size_t line, bool reset_to_default, bool force);
 
   // Called when the user hits escape after arrowing around the popup.  This
   // will change the selected line back to the default match and redraw.
@@ -97,11 +98,11 @@
   // possibly to the empty string], and you cannot have both a selected keyword
   // and a keyword hint simultaneously.)
   bool GetKeywordForMatch(const AutocompleteMatch& match,
-                          std::wstring* keyword) const;
+                          string16* keyword) const;
 
   // Calls through to SearchProvider::FinalizeInstantQuery.
-  void FinalizeInstantQuery(const std::wstring& input_text,
-                            const std::wstring& suggest_text);
+  void FinalizeInstantQuery(const string16& input_text,
+                            const string16& suggest_text);
 
   // Returns a pointer to a heap-allocated AutocompleteLog containing the
   // current input text, selected match, and result set.  The caller is
@@ -125,23 +126,20 @@
 
   Profile* profile() const { return profile_; }
 
+  // Invoked from the edit model any time the result set of the controller
+  // changes.
+  void OnResultChanged();
+
   // The token value for selected_line_, hover_line_ and functions dealing with
   // a "line number" that indicates "no line".
   static const size_t kNoMatch = -1;
 
  private:
-  // NotificationObserver
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
   AutocompletePopupView* view_;
 
   AutocompleteEditModel* edit_model_;
   scoped_ptr<AutocompleteController> controller_;
 
-  NotificationRegistrar registrar_;
-
   // Profile for current tab.
   Profile* profile_;
 
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
index e7da263..6834156 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -20,18 +20,18 @@
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
 #include "chrome/browser/defaults.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/color_utils.h"
-#include "gfx/font.h"
-#include "gfx/gtk_util.h"
-#include "gfx/rect.h"
-#include "gfx/skia_utils_gtk.h"
 #include "grit/theme_resources.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/skia_utils_gtk.h"
 
 namespace {
 
@@ -76,6 +76,10 @@
 // How much to offset the popup from the bottom of the location bar.
 const int kVerticalOffset = 3;
 
+// The size delta between the font used for the edit and the result rows. Passed
+// to gfx::Font::DeriveFont.
+const int kEditFontAdjust = -1;
+
 // UTF-8 Left-to-right embedding.
 const char* kLRE = "\xe2\x80\xaa";
 
@@ -106,8 +110,8 @@
 }
 
 // TODO(deanm): Find some better home for this, and make it more efficient.
-size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) {
-  return WideToUTF8(wide_text.substr(0, wide_text_offset)).size();
+size_t GetUTF8Offset(const string16& text, size_t text_offset) {
+  return UTF16ToUTF8(text.substr(0, text_offset)).size();
 }
 
 // Generates the normal URL color, a green color used in unhighlighted URL
@@ -170,7 +174,7 @@
 
 void AutocompletePopupViewGtk::SetupLayoutForMatch(
     PangoLayout* layout,
-    const std::wstring& text,
+    const string16& text,
     const AutocompleteMatch::ACMatchClassifications& classifications,
     const GdkColor* base_color,
     const GdkColor* dim_color,
@@ -180,21 +184,21 @@
   // RTL characters inside it, so the ending punctuation displays correctly
   // and the eliding ellipsis displays correctly. We only mark the text with
   // LRE. Wrapping it with LRE and PDF by calling AdjustStringForLocaleDirection
-  // will render the elllipsis at the left of the elided pure LTR text.
+  // or WrapStringWithLTRFormatting will render the elllipsis at the left of the
+  // elided pure LTR text.
   bool marked_with_lre = false;
-  std::wstring localized_text = text;
+  string16 localized_text = text;
   bool is_rtl = base::i18n::IsRTL();
   if (is_rtl && !base::i18n::StringContainsStrongRTLChars(localized_text)) {
-    localized_text.insert(0, 1,
-        static_cast<wchar_t>(base::i18n::kLeftToRightEmbeddingMark));
+    localized_text.insert(0, 1, base::i18n::kLeftToRightEmbeddingMark);
     marked_with_lre = true;
   }
 
   // We can have a prefix, or insert additional characters while processing the
   // classifications.  We need to take this in to account when we translate the
-  // wide offsets in the classification into text_utf8 byte offsets.
+  // UTF-16 offsets in the classification into text_utf8 byte offsets.
   size_t additional_offset = prefix_text.size();  // Length in utf-8 bytes.
-  std::string text_utf8 = prefix_text + WideToUTF8(localized_text);
+  std::string text_utf8 = prefix_text + UTF16ToUTF8(localized_text);
 
   PangoAttrList* attrs = pango_attr_list_new();
 
@@ -256,6 +260,7 @@
 }
 
 AutocompletePopupViewGtk::AutocompletePopupViewGtk(
+    const gfx::Font& font,
     AutocompleteEditView* edit_view,
     AutocompleteEditModel* edit_model,
     Profile* profile,
@@ -266,6 +271,7 @@
       window_(gtk_window_new(GTK_WINDOW_POPUP)),
       layout_(NULL),
       theme_provider_(GtkThemeProvider::GetFrom(profile)),
+      font_(font.DeriveFont(kEditFontAdjust)),
       ignore_mouse_drag_(false),
       opened_(false) {
   GTK_WIDGET_UNSET_FLAGS(window_, GTK_CAN_FOCUS);
@@ -284,15 +290,6 @@
   pango_layout_set_auto_dir(layout_, FALSE);
   // We always ellipsize when drawing our text runs.
   pango_layout_set_ellipsize(layout_, PANGO_ELLIPSIZE_END);
-  // TODO(deanm): We might want to eventually follow what Windows does and
-  // plumb a gfx::Font through.  This is because popup windows have a
-  // different font size, although we could just derive that font here.
-  // For now, force the font size.
-  gfx::Font font(gfx::Font().GetFontName(),
-                 browser_defaults::kAutocompletePopupFontSize);
-  PangoFontDescription* pfd = font.GetNativeFont();
-  pango_layout_set_font_description(layout_, pfd);
-  pango_font_description_free(pfd);
 
   gtk_widget_add_events(window_, GDK_BUTTON_MOTION_MASK |
                                  GDK_POINTER_MOTION_MASK |
@@ -395,6 +392,8 @@
   DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
 
   if (theme_provider_->UseGtkTheme()) {
+    gtk_util::UndoForceFontSize(window_);
+
     border_color_ = theme_provider_->GetBorderColor();
 
     gtk_util::GetTextColors(
@@ -407,6 +406,8 @@
     url_selected_text_color_ = SelectedURLColor(selected_content_text_color_,
                                                 selected_background_color_);
   } else {
+    gtk_util::ForceFontSizePixels(window_, font_.GetFontSize());
+
     border_color_ = kBorderColor;
     background_color_ = kBackgroundColor;
     selected_background_color_ = kSelectedBackgroundColor;
@@ -473,10 +474,10 @@
   // extension, |match| and its contents.  So copy the relevant strings out to
   // make sure they stay alive until the call completes.
   const GURL url(match.destination_url);
-  std::wstring keyword;
+  string16 keyword;
   const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword);
   edit_view_->OpenURL(url, disposition, match.transition, GURL(), line,
-                      is_keyword_hint ? std::wstring() : keyword);
+                      is_keyword_hint ? string16() : keyword);
 }
 
 GdkPixbuf* AutocompletePopupViewGtk::IconForMatch(
@@ -495,7 +496,6 @@
       case IDR_OMNIBOX_HTTP:    icon = IDR_OMNIBOX_HTTP_DARK; break;
       case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break;
       case IDR_OMNIBOX_SEARCH:  icon = IDR_OMNIBOX_SEARCH_DARK; break;
-      case IDR_OMNIBOX_MORE:    icon = IDR_OMNIBOX_MORE_DARK; break;
       case IDR_OMNIBOX_STAR:    icon = IDR_OMNIBOX_STAR_DARK; break;
       default:                  NOTREACHED(); break;
     }
@@ -514,7 +514,7 @@
   model_->SetHoveredLine(line);
   // Select the line if the user has the left mouse button down.
   if (!ignore_mouse_drag_ && (event->state & GDK_BUTTON1_MASK))
-    model_->SetSelectedLine(line, false);
+    model_->SetSelectedLine(line, false, false);
   return TRUE;
 }
 
@@ -525,7 +525,7 @@
   size_t line = LineFromY(static_cast<int>(event->y));
   model_->SetHoveredLine(line);
   if (event->button == 1)
-    model_->SetSelectedLine(line, false);
+    model_->SetSelectedLine(line, false, false);
   return TRUE;
 }
 
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
index 0632635..4350ae9 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/autocomplete/autocomplete_popup_view.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "ui/gfx/font.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class AutocompleteEditModel;
@@ -28,7 +29,8 @@
 class AutocompletePopupViewGtk : public AutocompletePopupView,
                                  public NotificationObserver {
  public:
-  AutocompletePopupViewGtk(AutocompleteEditView* edit_view,
+  AutocompletePopupViewGtk(const gfx::Font& font,
+                           AutocompleteEditView* edit_view,
                            AutocompleteEditModel* edit_model,
                            Profile* profile,
                            GtkWidget* location_bar);
@@ -53,7 +55,7 @@
   friend class AutocompletePopupViewGtkTest;
   static void SetupLayoutForMatch(
       PangoLayout* layout,
-      const std::wstring& text,
+      const string16& text,
       const AutocompleteMatch::ACMatchClassifications& classifications,
       const GdkColor* base_color,
       const GdkColor* dim_color,
@@ -117,6 +119,10 @@
   GtkThemeProvider* theme_provider_;
   NotificationRegistrar registrar_;
 
+  // Font used for suggestions after being derived from the constructor's
+  // |font|.
+  gfx::Font font_;
+
   // Used to cache GdkPixbufs and map them from the SkBitmaps they were created
   // from.
   typedef std::map<const SkBitmap*, GdkPixbuf*> PixbufMap;
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk_unittest.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk_unittest.cc
index dd84f26..3be69e5 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,10 @@
 
 #include <gtk/gtk.h>
 
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "testing/platform_test.h"
 
 namespace {
@@ -44,7 +45,7 @@
   // friend of the class being tested.  This method just proxies the
   // call through after adding the fixture's layout_.
   void SetupLayoutForMatch(
-      const std::wstring& text,
+      const string16& text,
       const AutocompleteMatch::ACMatchClassifications& classifications,
       const GdkColor* base_color,
       const GdkColor* dim_color,
@@ -188,7 +189,7 @@
 // text matches the input string, with the passed-in color, and
 // nothing bolded.
 TEST_F(AutocompletePopupViewGtkTest, DecorateMatchedStringNoMatch) {
-  const std::wstring kContents = L"This is a test";
+  const string16 kContents = ASCIIToUTF16("This is a test");
 
   AutocompleteMatch::ACMatchClassifications classifications;
 
@@ -224,7 +225,7 @@
 // Identical to DecorateMatchedStringNoMatch, except test that URL
 // style gets a different color than we passed in.
 TEST_F(AutocompletePopupViewGtkTest, DecorateMatchedStringURLNoMatch) {
-  const std::wstring kContents = L"This is a test";
+  const string16 kContents = ASCIIToUTF16("This is a test");
   AutocompleteMatch::ACMatchClassifications classifications;
 
   classifications.push_back(
@@ -260,7 +261,7 @@
 
 // Test that DIM works as expected.
 TEST_F(AutocompletePopupViewGtkTest, DecorateMatchedStringDimNoMatch) {
-  const std::wstring kContents = L"This is a test";
+  const string16 kContents = ASCIIToUTF16("This is a test");
   // Dim "is".
   const guint runLength1 = 5, runLength2 = 2, runLength3 = 7;
   // Make sure nobody messed up the inputs.
@@ -322,7 +323,7 @@
 // Test that the matched run gets bold-faced, but keeps the same
 // color.
 TEST_F(AutocompletePopupViewGtkTest, DecorateMatchedStringMatch) {
-  const std::wstring kContents = L"This is a test";
+  const string16 kContents = ASCIIToUTF16("This is a test");
   // Match "is".
   const guint runLength1 = 5, runLength2 = 2, runLength3 = 7;
   // Make sure nobody messed up the inputs.
@@ -380,7 +381,7 @@
 
 // Just like DecorateMatchedStringURLMatch, this time with URL style.
 TEST_F(AutocompletePopupViewGtkTest, DecorateMatchedStringURLMatch) {
-  const std::wstring kContents = L"http://hello.world/";
+  const string16 kContents = ASCIIToUTF16("http://hello.world/");
   // Match "hello".
   const guint runLength1 = 7, runLength2 = 5, runLength3 = 7;
   // Make sure nobody messed up the inputs.
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
index 2fdfaa9..f05dc7a 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
@@ -17,7 +17,7 @@
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_view.h"
 #import "chrome/browser/ui/cocoa/location_bar/instant_opt_in_controller.h"
-#include "gfx/font.h"
+#include "ui/gfx/font.h"
 #include "webkit/glue/window_open_disposition.h"
 
 
@@ -102,7 +102,7 @@
   // and description cases.  Returns NSMutableAttributedString as a
   // convenience for MatchText().
   static NSMutableAttributedString* DecorateMatchedString(
-      const std::wstring &matchString,
+      const string16 &matchString,
       const AutocompleteMatch::ACMatchClassifications &classifications,
       NSColor* textColor, NSColor* dimTextColor, gfx::Font& font);
 
@@ -114,7 +114,7 @@
   // cleaner.
   static NSMutableAttributedString* ElideString(
       NSMutableAttributedString* aString,
-      const std::wstring originalString,
+      const string16 originalString,
       const gfx::Font& font,
       const float cellWidth);
 
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
index d0b84e7..00c31c3 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
@@ -6,8 +6,6 @@
 
 #include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h"
 
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
 #include "base/stl_util-inl.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -23,11 +21,13 @@
 #import "chrome/browser/ui/cocoa/location_bar/instant_opt_in_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/instant_opt_in_view.h"
 #import "chrome/browser/ui/cocoa/location_bar/omnibox_popup_view.h"
-#include "gfx/rect.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/rect.h"
 
 namespace {
 
@@ -102,14 +102,14 @@
 // and description cases.  Returns NSMutableAttributedString as a
 // convenience for MatchText().
 NSMutableAttributedString* AutocompletePopupViewMac::DecorateMatchedString(
-    const std::wstring &matchString,
+    const string16 &matchString,
     const AutocompleteMatch::ACMatchClassifications &classifications,
     NSColor* textColor, NSColor* dimTextColor, gfx::Font& font) {
   // Cache for on-demand computation of the bold version of |font|.
   NSFont* boldFont = nil;
 
   // Start out with a string using the default style info.
-  NSString* s = base::SysWideToNSString(matchString);
+  NSString* s = base::SysUTF16ToNSString(matchString);
   NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                   font.GetNativeFont(), NSFontAttributeName,
                                   textColor, NSForegroundColorAttributeName,
@@ -154,7 +154,7 @@
 
 NSMutableAttributedString* AutocompletePopupViewMac::ElideString(
     NSMutableAttributedString* aString,
-    const std::wstring originalString,
+    const string16 originalString,
     const gfx::Font& font,
     const float width) {
   // If it already fits, nothing to be done.
@@ -163,8 +163,7 @@
   }
 
   // If ElideText() decides to do nothing, nothing to be done.
-  const std::wstring elided(UTF16ToWideHack(ElideText(
-      WideToUTF16Hack(originalString), font, width, false)));
+  const string16 elided = ui::ElideText(originalString, font, width, false);
   if (0 == elided.compare(originalString)) {
     return aString;
   }
@@ -181,7 +180,7 @@
   DCHECK(0 != elided.compare(0, i, originalString));
 
   // Replace the end of |aString| with the ellipses from |elided|.
-  NSString* s = base::SysWideToNSString(elided.substr(i));
+  NSString* s = base::SysUTF16ToNSString(elided.substr(i));
   [aString replaceCharactersInRange:NSMakeRange(i, [aString length] - i)
                          withString:s];
 
@@ -449,7 +448,7 @@
   // The popup's font is a slightly smaller version of the field's.
   NSFont* fieldFont = AutocompleteEditViewMac::GetFieldFont();
   const CGFloat resultFontSize = [fieldFont pointSize] + kEditFontAdjust;
-  gfx::Font resultFont(base::SysNSStringToWide([fieldFont fontName]),
+  gfx::Font resultFont(base::SysNSStringToUTF16([fieldFont fontName]),
                        static_cast<int>(resultFontSize));
 
   AutocompleteMatrix* matrix = GetAutocompleteMatrix();
@@ -519,7 +518,7 @@
 }
 
 void AutocompletePopupViewMac::SetSelectedLine(size_t line) {
-  model_->SetSelectedLine(line, false);
+  model_->SetSelectedLine(line, false, false);
 }
 
 // This is only called by model in SetSelectedLine() after updating
@@ -548,10 +547,10 @@
   // completes.
   const AutocompleteMatch& match = model_->result().match_at(row);
   const GURL url(match.destination_url);
-  std::wstring keyword;
+  string16 keyword;
   const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword);
   edit_view_->OpenURL(url, disposition, match.transition, GURL(), row,
-                      is_keyword_hint ? std::wstring() : keyword);
+                      is_keyword_hint ? string16() : keyword);
 }
 
 void AutocompletePopupViewMac::UserPressedOptIn(bool opt_in) {
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm
index 82d30e8..344694d 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm
@@ -4,12 +4,12 @@
 
 #import "chrome/browser/autocomplete/autocomplete_popup_view_mac.h"
 
-#include "app/text_elider.h"
 #include "base/scoped_ptr.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
 #include "testing/platform_test.h"
+#include "ui/base/text/text_elider.h"
 
 namespace {
 
@@ -27,7 +27,7 @@
     color_ = [NSColor blackColor];
     dimColor_ = [NSColor darkGrayColor];
     font_ = gfx::Font(
-        base::SysNSStringToWide([[NSFont userFontOfSize:12] fontName]), 12);
+        base::SysNSStringToUTF16([[NSFont userFontOfSize:12] fontName]), 12);
   }
 
   // Returns the length of the run starting at |location| for which
@@ -86,8 +86,8 @@
 
   // AutocompleteMatch doesn't really have the right constructor for our
   // needs.  Fake one for us to use.
-  static AutocompleteMatch MakeMatch(const std::wstring &contents,
-                                     const std::wstring &description) {
+  static AutocompleteMatch MakeMatch(const string16 &contents,
+                                     const string16 &description) {
     AutocompleteMatch m(NULL, 1, true, AutocompleteMatch::URL_WHAT_YOU_TYPED);
     m.contents = contents;
     m.description = description;
@@ -108,7 +108,7 @@
 
   NSAttributedString* decorated =
       AutocompletePopupViewMac::DecorateMatchedString(
-          base::SysNSStringToWide(string), classifications,
+          base::SysNSStringToUTF16(string), classifications,
           color_, dimColor_, font_);
 
   // Result has same characters as the input.
@@ -138,7 +138,7 @@
 
   NSAttributedString* decorated =
       AutocompletePopupViewMac::DecorateMatchedString(
-          base::SysNSStringToWide(string), classifications,
+          base::SysNSStringToUTF16(string), classifications,
           color_, dimColor_, font_);
 
   // Result has same characters as the input.
@@ -177,7 +177,7 @@
 
   NSAttributedString* decorated =
       AutocompletePopupViewMac::DecorateMatchedString(
-          base::SysNSStringToWide(string), classifications,
+          base::SysNSStringToUTF16(string), classifications,
           color_, dimColor_, font_);
 
   // Result has same characters as the input.
@@ -227,7 +227,7 @@
 
   NSAttributedString* decorated =
       AutocompletePopupViewMac::DecorateMatchedString(
-          base::SysNSStringToWide(string), classifications,
+          base::SysNSStringToUTF16(string), classifications,
           color_, dimColor_, font_);
 
   // Result has same characters as the input.
@@ -275,7 +275,7 @@
 
   NSAttributedString* decorated =
       AutocompletePopupViewMac::DecorateMatchedString(
-          base::SysNSStringToWide(string), classifications,
+          base::SysNSStringToUTF16(string), classifications,
           color_, dimColor_, font_);
 
   // Result has same characters as the input.
@@ -310,8 +310,8 @@
 TEST_F(AutocompletePopupViewMacTest, MatchText) {
   NSString* const contents = @"contents";
   NSString* const description = @"description";
-  AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
-                                  base::SysNSStringToWide(description));
+  AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
+                                  base::SysNSStringToUTF16(description));
 
   NSAttributedString* decorated =
       AutocompletePopupViewMac::MatchText(m, font_, kLargeWidth);
@@ -346,8 +346,8 @@
   // Make sure nobody messed up the inputs.
   EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]);
 
-  AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
-                                  std::wstring());
+  AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
+                                  string16());
 
   // Push each run onto contents classifications.
   m.contents_class.push_back(
@@ -394,8 +394,8 @@
   // Make sure nobody messed up the inputs.
   EXPECT_EQ(runLength1 + runLength2, [description length]);
 
-  AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
-                                  base::SysNSStringToWide(description));
+  AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
+                                  base::SysNSStringToUTF16(description));
 
   // Push each run onto contents classifications.
   m.description_class.push_back(
@@ -441,7 +441,7 @@
 
 TEST_F(AutocompletePopupViewMacTest, ElideString) {
   NSString* const contents = @"This is a test with long contents";
-  const std::wstring wideContents(base::SysNSStringToWide(contents));
+  const string16 contents16(base::SysNSStringToUTF16(contents));
 
   const float kWide = 1000.0;
   const float kNarrow = 20.0;
@@ -455,25 +455,23 @@
 
   // Nothing happens if the space is really wide.
   NSMutableAttributedString* ret =
-      AutocompletePopupViewMac::ElideString(as, wideContents, font_, kWide);
+      AutocompletePopupViewMac::ElideString(as, contents16, font_, kWide);
   EXPECT_TRUE(ret == as);
   EXPECT_TRUE([[as string] isEqualToString:contents]);
 
   // When elided, result is the same as ElideText().
-  ret = AutocompletePopupViewMac::ElideString(as, wideContents, font_, kNarrow);
-  std::wstring elided(UTF16ToWideHack(ElideText(WideToUTF16Hack(
-      wideContents), font_, kNarrow, false)));
+  ret = AutocompletePopupViewMac::ElideString(as, contents16, font_, kNarrow);
+  string16 elided = ui::ElideText(contents16, font_, kNarrow, false);
   EXPECT_TRUE(ret == as);
   EXPECT_FALSE([[as string] isEqualToString:contents]);
-  EXPECT_TRUE([[as string] isEqualToString:base::SysWideToNSString(elided)]);
+  EXPECT_TRUE([[as string] isEqualToString:base::SysUTF16ToNSString(elided)]);
 
   // When elided, result is the same as ElideText().
-  ret = AutocompletePopupViewMac::ElideString(as, wideContents, font_, 0.0);
-  elided = UTF16ToWideHack(ElideText(WideToUTF16Hack(wideContents), font_,
-                                     0.0, false));
+  ret = AutocompletePopupViewMac::ElideString(as, contents16, font_, 0.0);
+  elided = ui::ElideText(contents16, font_, 0.0, false);
   EXPECT_TRUE(ret == as);
   EXPECT_FALSE([[as string] isEqualToString:contents]);
-  EXPECT_TRUE([[as string] isEqualToString:base::SysWideToNSString(elided)]);
+  EXPECT_TRUE([[as string] isEqualToString:base::SysUTF16ToNSString(elided)]);
 }
 
 TEST_F(AutocompletePopupViewMacTest, MatchTextElide) {
@@ -484,8 +482,8 @@
   // Make sure nobody messed up the inputs.
   EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]);
 
-  AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
-                                  base::SysNSStringToWide(description));
+  AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents),
+                                  base::SysNSStringToUTF16(description));
 
   // Push each run onto contents classifications.
   m.contents_class.push_back(
diff --git a/chrome/browser/autocomplete/autocomplete_result_unittest.cc b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
new file mode 100644
index 0000000..37ffa40
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
@@ -0,0 +1,187 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class AutocompleteResultTest : public testing::Test  {
+ public:
+  struct TestData {
+    // Used to build a url for the AutocompleteMatch. The URL becomes
+    // 'http://' + |url_id|.
+    int url_id;
+
+    // ID of the provider.
+    int provider_id;
+
+    // Relevance score.
+    int relevance;
+  };
+
+  AutocompleteResultTest() {}
+
+  // Configures |match| from |data|.
+  static void PopulateAutocompleteMatch(const TestData& data,
+                                        AutocompleteMatch* match);
+
+  // Adds |count| AutocompleteMatches to |matches|.
+  static void PopulateAutocompleteMatches(const TestData* data,
+                                          size_t count,
+                                          ACMatches* matches);
+
+  // Asserts that |result| has |expected_count| matches matching |expected|.
+  void AssertResultMatches(const AutocompleteResult& result,
+                           const TestData* expected,
+                           size_t expected_count);
+
+  // Creates an AutocompleteResult from |last| and |current|. The two are
+  // merged by |CopyOldMatches| and compared by |AssertResultMatches|.
+  void RunCopyOldMatchesTest(const TestData* last, size_t last_size,
+                             const TestData* current, size_t current_size,
+                             const TestData* expected, size_t expected_size);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest);
+};
+
+// static
+void AutocompleteResultTest::PopulateAutocompleteMatch(
+    const TestData& data,
+    AutocompleteMatch* match) {
+  match->provider = reinterpret_cast<AutocompleteProvider*>(data.provider_id);
+  match->fill_into_edit = base::IntToString16(data.url_id);
+  std::string url_id(1, data.url_id + 'a');
+  match->destination_url = GURL("http://" + url_id);
+  match->relevance = data.relevance;
+}
+
+// static
+void AutocompleteResultTest::PopulateAutocompleteMatches(
+    const TestData* data,
+    size_t count,
+    ACMatches* matches) {
+  for (size_t i = 0; i < count; ++i) {
+    AutocompleteMatch match;
+    PopulateAutocompleteMatch(data[i], &match);
+    matches->push_back(match);
+  }
+}
+
+void AutocompleteResultTest::AssertResultMatches(
+    const AutocompleteResult& result,
+    const TestData* expected,
+    size_t expected_count) {
+  ASSERT_EQ(expected_count, result.size());
+  for (size_t i = 0; i < expected_count; ++i) {
+    AutocompleteMatch expected_match;
+    PopulateAutocompleteMatch(expected[i], &expected_match);
+    const AutocompleteMatch& match = *(result.begin() + i);
+    EXPECT_EQ(expected_match.provider, match.provider) << i;
+    EXPECT_EQ(expected_match.relevance, match.relevance) << i;
+    EXPECT_EQ(expected_match.destination_url.spec(),
+              match.destination_url.spec()) << i;
+  }
+}
+
+void AutocompleteResultTest::RunCopyOldMatchesTest(
+    const TestData* last, size_t last_size,
+    const TestData* current, size_t current_size,
+    const TestData* expected, size_t expected_size) {
+  AutocompleteInput input(ASCIIToUTF16("a"), string16(), false, false, false,
+                          false);
+
+  ACMatches last_matches;
+  PopulateAutocompleteMatches(last, last_size, &last_matches);
+  AutocompleteResult last_result;
+  last_result.AppendMatches(last_matches);
+  last_result.SortAndCull(input);
+
+  ACMatches current_matches;
+  PopulateAutocompleteMatches(current, current_size, &current_matches);
+  AutocompleteResult current_result;
+  current_result.AppendMatches(current_matches);
+  current_result.SortAndCull(input);
+  current_result.CopyOldMatches(last_result);
+
+  AssertResultMatches(current_result, expected, expected_size);
+}
+
+// Assertion testing for AutocompleteResult::Swap.
+TEST_F(AutocompleteResultTest, Swap) {
+  AutocompleteResult r1;
+  AutocompleteResult r2;
+
+  // Swap with empty shouldn't do anything interesting.
+  r1.Swap(&r2);
+  EXPECT_EQ(r1.end(), r1.default_match());
+  EXPECT_EQ(r2.end(), r2.default_match());
+
+  // Swap with a single match.
+  ACMatches matches;
+  AutocompleteMatch match;
+  AutocompleteInput input(ASCIIToUTF16("a"), string16(), false, false, false,
+                          false);
+  matches.push_back(match);
+  r1.AppendMatches(matches);
+  r1.SortAndCull(input);
+  EXPECT_EQ(r1.begin(), r1.default_match());
+  EXPECT_EQ("http://a/", r1.alternate_nav_url().spec());
+  r1.Swap(&r2);
+  EXPECT_TRUE(r1.empty());
+  EXPECT_EQ(r1.end(), r1.default_match());
+  EXPECT_TRUE(r1.alternate_nav_url().is_empty());
+  ASSERT_FALSE(r2.empty());
+  EXPECT_EQ(r2.begin(), r2.default_match());
+  EXPECT_EQ("http://a/", r2.alternate_nav_url().spec());
+}
+
+// Tests that if the new results have a lower max relevance score than last,
+// any copied results have their relevance shifted down.
+TEST_F(AutocompleteResultTest, CopyOldMatches) {
+  TestData last[] = {
+    { 0, 0, 1000 },
+    { 1, 0, 500 },
+  };
+  TestData current[] = {
+    { 2, 0, 400 },
+  };
+  TestData result[] = {
+    { 2, 0, 400 },
+    { 1, 0, 399 },
+  };
+
+  ASSERT_NO_FATAL_FAILURE(
+      RunCopyOldMatchesTest(last, ARRAYSIZE_UNSAFE(last),
+                            current, ARRAYSIZE_UNSAFE(current),
+                            result, ARRAYSIZE_UNSAFE(result)));
+}
+
+// Tests that matches are copied correctly from two distinct providers.
+TEST_F(AutocompleteResultTest, CopyOldMatches2) {
+  TestData last[] = {
+    { 0, 0, 1000 },
+    { 1, 1, 500 },
+    { 2, 0, 400 },
+    { 3, 1, 300 },
+  };
+  TestData current[] = {
+    { 4, 0, 1100 },
+    { 5, 1, 550 },
+  };
+  TestData result[] = {
+    { 4, 0, 1100 },
+    { 5, 1, 550 },
+    { 2, 0, 400 },
+    { 3, 1, 300 },
+  };
+
+  ASSERT_NO_FATAL_FAILURE(
+      RunCopyOldMatchesTest(last, ARRAYSIZE_UNSAFE(last),
+                            current, ARRAYSIZE_UNSAFE(current),
+                            result, ARRAYSIZE_UNSAFE(result)));
+}
diff --git a/chrome/browser/autocomplete/autocomplete_unittest.cc b/chrome/browser/autocomplete/autocomplete_unittest.cc
index fc6c402..93ce9da 100644
--- a/chrome/browser/autocomplete/autocomplete_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,10 +19,6 @@
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// identifiers for known autocomplete providers
-#define HISTORY_IDENTIFIER L"Chrome:History"
-#define SEARCH_IDENTIFIER L"google.com/websearch/en"
-
 static std::ostream& operator<<(std::ostream& os,
                                 const AutocompleteResult::const_iterator& it) {
   return os << static_cast<const AutocompleteMatch*>(&(*it));
@@ -36,7 +32,7 @@
 // refcounted so that it can also be a task on the message loop.
 class TestProvider : public AutocompleteProvider {
  public:
-  TestProvider(int relevance, const std::wstring& prefix)
+  TestProvider(int relevance, const string16& prefix)
       : AutocompleteProvider(NULL, NULL, ""),
         relevance_(relevance),
         prefix_(prefix) {
@@ -57,7 +53,7 @@
   void AddResults(int start_at, int num);
 
   int relevance_;
-  const std::wstring prefix_;
+  const string16 prefix_;
 };
 
 void TestProvider::Start(const AutocompleteInput& input,
@@ -90,8 +86,8 @@
     AutocompleteMatch match(this, relevance_ - i, false,
                             AutocompleteMatch::URL_WHAT_YOU_TYPED);
 
-    match.fill_into_edit = prefix_ + UTF8ToWide(base::IntToString(i));
-    match.destination_url = GURL(WideToUTF8(match.fill_into_edit));
+    match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i));
+    match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit));
 
     match.contents = match.fill_into_edit;
     match.contents_class.push_back(
@@ -141,12 +137,12 @@
 
   // Construct two new providers, with either the same or different prefixes.
   TestProvider* providerA = new TestProvider(num_results_per_provider,
-                                             L"http://a");
+                                             ASCIIToUTF16("http://a"));
   providerA->AddRef();
   providers_.push_back(providerA);
 
   TestProvider* providerB = new TestProvider(num_results_per_provider * 2,
-      same_destinations ? L"http://a" : L"http://b");
+      same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b"));
   providerB->AddRef();
   providers_.push_back(providerB);
 
@@ -177,8 +173,8 @@
 
   // Create another TemplateURL for KeywordProvider.
   TemplateURL* keyword_t_url = new TemplateURL();
-  keyword_t_url->set_short_name(L"k");
-  keyword_t_url->set_keyword(L"k");
+  keyword_t_url->set_short_name(ASCIIToUTF16("k"));
+  keyword_t_url->set_keyword(ASCIIToUTF16("k"));
   keyword_t_url->SetURL("http://keyword/{searchTerms}", 0, 0);
   profile_.GetTemplateURLModel()->Add(keyword_t_url);
   ASSERT_NE(0, keyword_t_url->id());
@@ -203,7 +199,7 @@
 
 void AutocompleteProviderTest::RunTest() {
   result_.Reset();
-  controller_->Start(L"a", std::wstring(), true, false, true, false);
+  controller_->Start(ASCIIToUTF16("a"), string16(), true, false, true, false);
 
   // The message loop will terminate when all autocomplete input has been
   // collected.
@@ -216,7 +212,7 @@
   // created in ResetControllerWithKeywordAndSearchProviders().  The default
   // match should thus be a keyword match iff |allow_exact_keyword_match| is
   // true.
-  controller_->Start(L"k test", std::wstring(), true, false,
+  controller_->Start(ASCIIToUTF16("k test"), string16(), true, false,
                      allow_exact_keyword_match, true);
   EXPECT_TRUE(controller_->done());
   // ResetControllerWithKeywordAndSearchProviders() adds the keyword provider
@@ -230,7 +226,7 @@
                                        const NotificationSource& source,
                                        const NotificationDetails& details) {
   if (controller_->done()) {
-    result_.CopyFrom(*(Details<const AutocompleteResult>(details).ptr()));
+    result_.CopyFrom(controller_->result());
     MessageLoop::current()->Quit();
   }
 }
@@ -267,92 +263,96 @@
 
 TEST(AutocompleteTest, InputType) {
   struct test_data {
-    const wchar_t* input;
+    const string16 input;
     const AutocompleteInput::Type type;
   } input_cases[] = {
-    { L"", AutocompleteInput::INVALID },
-    { L"?", AutocompleteInput::FORCED_QUERY },
-    { L"?foo", AutocompleteInput::FORCED_QUERY },
-    { L"?foo bar", AutocompleteInput::FORCED_QUERY },
-    { L"?http://foo.com/bar", AutocompleteInput::FORCED_QUERY },
-    { L"foo", AutocompleteInput::UNKNOWN },
-    { L"foo.c", AutocompleteInput::UNKNOWN },
-    { L"foo.com", AutocompleteInput::URL },
-    { L"-.com", AutocompleteInput::UNKNOWN },
-    { L"foo/bar", AutocompleteInput::URL },
-    { L"foo;bar", AutocompleteInput::QUERY },
-    { L"foo/bar baz", AutocompleteInput::UNKNOWN },
-    { L"foo bar.com", AutocompleteInput::QUERY },
-    { L"foo bar", AutocompleteInput::QUERY },
-    { L"foo+bar", AutocompleteInput::QUERY },
-    { L"foo+bar.com", AutocompleteInput::UNKNOWN },
-    { L"\"foo:bar\"", AutocompleteInput::QUERY },
-    { L"link:foo.com", AutocompleteInput::UNKNOWN },
-    { L"foo:81", AutocompleteInput::URL },
-    { L"www.foo.com:81", AutocompleteInput::URL },
-    { L"localhost:8080", AutocompleteInput::URL },
-    { L"foo.com:123456", AutocompleteInput::QUERY },
-    { L"foo.com:abc", AutocompleteInput::QUERY },
-    { L"1.2.3.4:abc", AutocompleteInput::QUERY },
-    { L"user@foo.com", AutocompleteInput::UNKNOWN },
-    { L"user:pass@", AutocompleteInput::UNKNOWN },
-    { L"user:pass@!foo.com", AutocompleteInput::UNKNOWN },
-    { L"user:pass@foo", AutocompleteInput::URL },
-    { L"user:pass@foo.c", AutocompleteInput::URL },
-    { L"user:pass@foo.com", AutocompleteInput::URL },
-    { L"user:pass@foo.com:81", AutocompleteInput::URL },
-    { L"user:pass@foo:81", AutocompleteInput::URL },
-    { L"1.2", AutocompleteInput::UNKNOWN },
-    { L"1.2/45", AutocompleteInput::UNKNOWN },
-    { L"1.2:45", AutocompleteInput::UNKNOWN },
-    { L"user@1.2:45", AutocompleteInput::UNKNOWN },
-    { L"user:pass@1.2:45", AutocompleteInput::URL },
-    { L"ps/2 games", AutocompleteInput::UNKNOWN },
-    { L"en.wikipedia.org/wiki/James Bond", AutocompleteInput::URL },
+    { ASCIIToUTF16(""), AutocompleteInput::INVALID },
+    { ASCIIToUTF16("?"), AutocompleteInput::FORCED_QUERY },
+    { ASCIIToUTF16("?foo"), AutocompleteInput::FORCED_QUERY },
+    { ASCIIToUTF16("?foo bar"), AutocompleteInput::FORCED_QUERY },
+    { ASCIIToUTF16("?http://foo.com/bar"), AutocompleteInput::FORCED_QUERY },
+    { ASCIIToUTF16("foo"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("foo.c"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("-.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("foo/bar"), AutocompleteInput::URL },
+    { ASCIIToUTF16("foo;bar"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("foo/bar baz"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("foo bar.com"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("foo bar"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("foo+bar"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("foo+bar.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("\"foo:bar\""), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("link:foo.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("foo:81"), AutocompleteInput::URL },
+    { ASCIIToUTF16("www.foo.com:81"), AutocompleteInput::URL },
+    { ASCIIToUTF16("localhost:8080"), AutocompleteInput::URL },
+    { ASCIIToUTF16("foo.com:123456"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("foo.com:abc"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("1.2.3.4:abc"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("user@foo.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("user:pass@"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("user:pass@!foo.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("user:pass@foo"), AutocompleteInput::URL },
+    { ASCIIToUTF16("user:pass@foo.c"), AutocompleteInput::URL },
+    { ASCIIToUTF16("user:pass@foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("user:pass@foo.com:81"), AutocompleteInput::URL },
+    { ASCIIToUTF16("user:pass@foo:81"), AutocompleteInput::URL },
+    { ASCIIToUTF16("1.2"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("1.2/45"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("1.2:45"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("user@1.2:45"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("user:pass@1.2:45"), AutocompleteInput::URL },
+    { ASCIIToUTF16("ps/2 games"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("en.wikipedia.org/wiki/James Bond"),
+        AutocompleteInput::URL },
     // In Chrome itself, mailto: will get handled by ShellExecute, but in
     // unittest mode, we don't have the data loaded in the external protocol
     // handler to know this.
-    // { L"mailto:abuse@foo.com", AutocompleteInput::URL },
-    { L"view-source:http://www.foo.com/", AutocompleteInput::URL },
-    { L"javascript:alert(\"Hey there!\");", AutocompleteInput::URL },
+    // { ASCIIToUTF16("mailto:abuse@foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("view-source:http://www.foo.com/"), AutocompleteInput::URL },
+    { ASCIIToUTF16("javascript:alert(\"Hey there!\");"),
+        AutocompleteInput::URL },
 #if defined(OS_WIN)
-    { L"C:\\Program Files", AutocompleteInput::URL },
-    { L"\\\\Server\\Folder\\File", AutocompleteInput::URL },
+    { ASCIIToUTF16("C:\\Program Files"), AutocompleteInput::URL },
+    { ASCIIToUTF16("\\\\Server\\Folder\\File"), AutocompleteInput::URL },
 #endif  // defined(OS_WIN)
-    { L"http:foo", AutocompleteInput::URL },
-    { L"http://foo", AutocompleteInput::URL },
-    { L"http://foo.c", AutocompleteInput::URL },
-    { L"http://foo.com", AutocompleteInput::URL },
-    { L"http://foo_bar.com", AutocompleteInput::URL },
-    { L"http://foo/bar baz", AutocompleteInput::URL },
-    { L"http://-.com", AutocompleteInput::UNKNOWN },
-    { L"http://_foo_.com", AutocompleteInput::UNKNOWN },
-    { L"http://foo.com:abc", AutocompleteInput::QUERY },
-    { L"http://foo.com:123456", AutocompleteInput::QUERY },
-    { L"http://1.2.3.4:abc", AutocompleteInput::QUERY },
-    { L"http:user@foo.com", AutocompleteInput::URL },
-    { L"http://user@foo.com", AutocompleteInput::URL },
-    { L"http:user:pass@foo.com", AutocompleteInput::URL },
-    { L"http://user:pass@foo.com", AutocompleteInput::URL },
-    { L"http://1.2", AutocompleteInput::URL },
-    { L"http://1.2/45", AutocompleteInput::URL },
-    { L"http:ps/2 games", AutocompleteInput::URL },
-    { L"http://ps/2 games", AutocompleteInput::URL },
-    { L"https://foo.com", AutocompleteInput::URL },
-    { L"127.0.0.1", AutocompleteInput::URL },
-    { L"127.0.1", AutocompleteInput::UNKNOWN },
-    { L"127.0.1/", AutocompleteInput::UNKNOWN },
-    { L"browser.tabs.closeButtons", AutocompleteInput::UNKNOWN },
-    { L"\u6d4b\u8bd5", AutocompleteInput::UNKNOWN },
-    { L"[2001:]", AutocompleteInput::QUERY },  // Not a valid IP
-    { L"[2001:dB8::1]", AutocompleteInput::URL },
-    { L"192.168.0.256", AutocompleteInput::QUERY },  // Invalid IPv4 literal.
-    { L"[foo.com]", AutocompleteInput::QUERY },  // Invalid IPv6 literal.
+    { ASCIIToUTF16("http:foo"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://foo"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://foo.c"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://foo_bar.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://foo/bar baz"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://-.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("http://_foo_.com"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("http://foo.com:abc"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("http://foo.com:123456"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("http://1.2.3.4:abc"), AutocompleteInput::QUERY },
+    { ASCIIToUTF16("http:user@foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://user@foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http:user:pass@foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://user:pass@foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://1.2"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://1.2/45"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http:ps/2 games"), AutocompleteInput::URL },
+    { ASCIIToUTF16("http://ps/2 games"), AutocompleteInput::URL },
+    { ASCIIToUTF16("https://foo.com"), AutocompleteInput::URL },
+    { ASCIIToUTF16("127.0.0.1"), AutocompleteInput::URL },
+    { ASCIIToUTF16("127.0.1"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("127.0.1/"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("browser.tabs.closeButtons"), AutocompleteInput::UNKNOWN },
+    { WideToUTF16(L"\u6d4b\u8bd5"), AutocompleteInput::UNKNOWN },
+    { ASCIIToUTF16("[2001:]"), AutocompleteInput::QUERY },  // Not a valid IP
+    { ASCIIToUTF16("[2001:dB8::1]"), AutocompleteInput::URL },
+    { ASCIIToUTF16("192.168.0.256"),
+        AutocompleteInput::QUERY },  // Invalid IPv4 literal.
+    { ASCIIToUTF16("[foo.com]"),
+        AutocompleteInput::QUERY },  // Invalid IPv6 literal.
   };
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
     SCOPED_TRACE(input_cases[i].input);
-    AutocompleteInput input(input_cases[i].input, std::wstring(), true, false,
+    AutocompleteInput input(input_cases[i].input, string16(), true, false,
                             true, false);
     EXPECT_EQ(input_cases[i].type, input.type());
   }
@@ -360,16 +360,16 @@
 
 TEST(AutocompleteTest, InputTypeWithDesiredTLD) {
   struct test_data {
-    const wchar_t* input;
+    const string16 input;
     const AutocompleteInput::Type type;
   } input_cases[] = {
-    { L"401k", AutocompleteInput::REQUESTED_URL },
-    { L"999999999999999", AutocompleteInput::REQUESTED_URL },
+    { ASCIIToUTF16("401k"), AutocompleteInput::REQUESTED_URL },
+    { ASCIIToUTF16("999999999999999"), AutocompleteInput::REQUESTED_URL },
   };
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
-    AutocompleteInput input(input_cases[i].input, L"com", true, false, true,
-                            false);
+    AutocompleteInput input(input_cases[i].input, ASCIIToUTF16("com"), true,
+                            false, true, false);
     EXPECT_EQ(input_cases[i].type, input.type()) << "Input: " <<
         input_cases[i].input;
   }
@@ -378,12 +378,11 @@
 // This tests for a regression where certain input in the omnibox caused us to
 // crash. As long as the test completes without crashing, we're fine.
 TEST(AutocompleteTest, InputCrash) {
-  AutocompleteInput input(L"\uff65@s", std::wstring(), true, false, true,
-                          false);
+  AutocompleteInput input(WideToUTF16(L"\uff65@s"), string16(), true, false,
+                          true, false);
 }
 
-// Test that we can properly compare matches' relevance when at least one is
-// negative.
+// Test comparing matches relevance.
 TEST(AutocompleteMatch, MoreRelevant) {
   struct RelevantCases {
     int r1;
@@ -394,8 +393,8 @@
     {  10,  -5, true  },
     {  -5,  10, false },
     {   0,  10, false },
-    { -10,  -5, true  },
-    {  -5, -10, false },
+    { -10,  -5, false  },
+    {  -5, -10, true },
   };
 
   AutocompleteMatch m1(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED);
@@ -413,36 +412,41 @@
   using url_parse::Component;
   Component kInvalidComponent(0, -1);
   struct test_data {
-    const wchar_t* input;
+    const string16 input;
     const Component scheme;
     const Component host;
   } input_cases[] = {
-    { L"", kInvalidComponent, kInvalidComponent },
-    { L"?", kInvalidComponent, kInvalidComponent },
-    { L"?http://foo.com/bar", kInvalidComponent, kInvalidComponent },
-    { L"foo/bar baz", kInvalidComponent, Component(0, 3) },
-    { L"http://foo/bar baz", Component(0, 4), Component(7, 3) },
-    { L"link:foo.com", Component(0, 4), kInvalidComponent },
-    { L"www.foo.com:81", kInvalidComponent, Component(0, 11) },
-    { L"\u6d4b\u8bd5", kInvalidComponent, Component(0, 2) },
-    { L"view-source:http://www.foo.com/", Component(12, 4), Component(19, 11) },
-    { L"view-source:https://example.com/",
+    { ASCIIToUTF16(""), kInvalidComponent, kInvalidComponent },
+    { ASCIIToUTF16("?"), kInvalidComponent, kInvalidComponent },
+    { ASCIIToUTF16("?http://foo.com/bar"), kInvalidComponent,
+        kInvalidComponent },
+    { ASCIIToUTF16("foo/bar baz"), kInvalidComponent, Component(0, 3) },
+    { ASCIIToUTF16("http://foo/bar baz"), Component(0, 4), Component(7, 3) },
+    { ASCIIToUTF16("link:foo.com"), Component(0, 4), kInvalidComponent },
+    { ASCIIToUTF16("www.foo.com:81"), kInvalidComponent, Component(0, 11) },
+    { WideToUTF16(L"\u6d4b\u8bd5"), kInvalidComponent, Component(0, 2) },
+    { ASCIIToUTF16("view-source:http://www.foo.com/"), Component(12, 4),
+        Component(19, 11) },
+    { ASCIIToUTF16("view-source:https://example.com/"),
       Component(12, 5), Component(20, 11) },
-    { L"view-source:www.foo.com", kInvalidComponent, Component(12, 11) },
-    { L"view-source:", Component(0, 11), kInvalidComponent },
-    { L"view-source:garbage", kInvalidComponent, Component(12, 7) },
-    { L"view-source:http://http://foo", Component(12, 4), Component(19, 4) },
-    { L"view-source:view-source:http://example.com/",
-      Component(12, 11), kInvalidComponent }
+    { ASCIIToUTF16("view-source:www.foo.com"), kInvalidComponent,
+        Component(12, 11) },
+    { ASCIIToUTF16("view-source:"), Component(0, 11), kInvalidComponent },
+    { ASCIIToUTF16("view-source:garbage"), kInvalidComponent,
+        Component(12, 7) },
+    { ASCIIToUTF16("view-source:http://http://foo"), Component(12, 4),
+        Component(19, 4) },
+    { ASCIIToUTF16("view-source:view-source:http://example.com/"),
+        Component(12, 11), kInvalidComponent }
   };
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
     Component scheme, host;
     AutocompleteInput::ParseForEmphasizeComponents(input_cases[i].input,
-                                                   std::wstring(),
+                                                   string16(),
                                                    &scheme,
                                                    &host);
-    AutocompleteInput input(input_cases[i].input, std::wstring(), true, false,
+    AutocompleteInput input(input_cases[i].input, string16(), true, false,
                             true, false);
     EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin) << "Input: " <<
         input_cases[i].input;
diff --git a/chrome/browser/autocomplete/history_contents_provider.cc b/chrome/browser/autocomplete/history_contents_provider.cc
index 37f3144..44d24e8 100644
--- a/chrome/browser/autocomplete/history_contents_provider.cc
+++ b/chrome/browser/autocomplete/history_contents_provider.cc
@@ -82,7 +82,7 @@
   if ((input.type() == AutocompleteInput::URL) ||
       (((input.type() == AutocompleteInput::REQUESTED_URL) ||
         (input.type() == AutocompleteInput::UNKNOWN)) &&
-       (input.text().find('.') != std::wstring::npos))) {
+       (input.text().find('.') != string16::npos))) {
     Stop();
     return;
   }
@@ -133,8 +133,8 @@
 
       history::QueryOptions options;
       options.SetRecentDayRange(kDaysToSearch);
-      options.max_count = kMaxMatchCount;
-      history->QueryHistory(WideToUTF16(input.text()), options,
+      options.max_count = kMaxMatches;
+      history->QueryHistory(input.text(), options,
           &request_consumer_,
           NewCallback(this, &HistoryContentsProvider::QueryComplete));
     }
@@ -183,34 +183,15 @@
     result_refs.push_back(ref);
   }
 
-  // Get the top matches and add them. Always do max number of matches the popup
-  // will show plus one. This ensures that if the other providers provide the
-  // exact same set of results, and the db only has max_matches + 1 results
-  // available for this query, we know the last one.
-  //
-  // This is done to avoid having the history search shortcut show
-  // 'See 1 previously viewed ...'.
-  //
-  // Note that AutocompleteResult::kMaxMatches (maximum size of the popup)
-  // is different than both kMaxMatches (the provider's maximum) and
-  // kMaxMatchCount (the number of items we want from the history).
-  size_t max_for_popup = std::min(AutocompleteResult::kMaxMatches + 1,
-                                  result_refs.size());
+  // Get the top matches and add them.
   size_t max_for_provider = std::min(kMaxMatches, result_refs.size());
-  std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_popup,
+  std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_provider,
                     result_refs.end(), &CompareMatchRelevance);
   matches_.clear();
-  for (size_t i = 0; i < max_for_popup; i++) {
+  for (size_t i = 0; i < max_for_provider; i++) {
     matches_.push_back(ResultToMatch(*result_refs[i].result,
                                      result_refs[i].relevance));
   }
-
-  // We made more matches than the autocomplete service requested for this
-  // provider (see previous comment). We invert the weights for the items
-  // we want to get removed, but preserve their magnitude which will be used
-  // to fill them in with our other results.
-  for (size_t i = max_for_provider; i < max_for_popup; i++)
-      matches_[i].relevance = -matches_[i].relevance;
 }
 
 static bool MatchInTitle(const history::URLResult& result) {
@@ -231,7 +212,7 @@
   match.destination_url = result.url();
   match.contents_class.push_back(
       ACMatchClassification(0, ACMatchClassification::URL));
-  match.description = UTF16ToWide(result.title());
+  match.description = result.title();
   match.starred =
       (profile_->GetBookmarkModel() &&
        profile_->GetBookmarkModel()->IsBookmarked(result.url()));
@@ -284,7 +265,7 @@
 
   TimeTicks start_time = TimeTicks::Now();
   std::vector<bookmark_utils::TitleMatch> matches;
-  bookmark_model->GetBookmarksWithTitlesMatching(WideToUTF16Hack(input.text()),
+  bookmark_model->GetBookmarksWithTitlesMatching(input.text(),
                                                  kMaxMatches, &matches);
   for (size_t i = 0; i < matches.size(); ++i)
     AddBookmarkTitleMatchToResults(matches[i]);
diff --git a/chrome/browser/autocomplete/history_contents_provider.h b/chrome/browser/autocomplete/history_contents_provider.h
index 657403f..5bee112 100644
--- a/chrome/browser/autocomplete/history_contents_provider.h
+++ b/chrome/browser/autocomplete/history_contents_provider.h
@@ -30,15 +30,6 @@
                      bool minimal_changes) OVERRIDE;
   virtual void Stop() OVERRIDE;
 
-  // Returns the total number of matches available in the database, up to
-  // kMaxMatchCount, whichever is smaller.
-  // Return value is incomplete if done() returns false.
-  size_t db_match_count() const { return results_.size(); }
-
-  // The maximum match count we'll report. If the db_match_count is greater
-  // than this, it will be clamped to this result.
-  static const size_t kMaxMatchCount = 50;
-
  private:
   ~HistoryContentsProvider();
 
@@ -93,7 +84,7 @@
   bool have_results_;
 
   // Current query string.
-  std::wstring query_;
+  string16 query_;
 
   DISALLOW_COPY_AND_ASSIGN(HistoryContentsProvider);
 };
diff --git a/chrome/browser/autocomplete/history_contents_provider_unittest.cc b/chrome/browser/autocomplete/history_contents_provider_unittest.cc
index 6404ede..c9067ea 100644
--- a/chrome/browser/autocomplete/history_contents_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_contents_provider_unittest.cc
@@ -100,51 +100,51 @@
   BrowserThread ui_thread_;
   BrowserThread file_thread_;
 
-  std::wstring history_dir_;
-
   scoped_ptr<TestingProfile> profile_;
   scoped_refptr<HistoryContentsProvider> provider_;
 };
 
 TEST_F(HistoryContentsProviderTest, Body) {
-  AutocompleteInput input(L"FOO", std::wstring(), true, false, true, false);
+  AutocompleteInput input(ASCIIToUTF16("FOO"), string16(), true, false, true,
+                          false);
   RunQuery(input, false);
 
   // The results should be the first two pages, in decreasing order.
   const ACMatches& m = matches();
   ASSERT_EQ(2U, m.size());
   EXPECT_EQ(test_entries[0].url, m[0].destination_url.spec());
-  EXPECT_STREQ(test_entries[0].title, WideToUTF8(m[0].description).c_str());
+  EXPECT_STREQ(test_entries[0].title, UTF16ToUTF8(m[0].description).c_str());
   EXPECT_EQ(test_entries[1].url, m[1].destination_url.spec());
-  EXPECT_STREQ(test_entries[1].title, WideToUTF8(m[1].description).c_str());
+  EXPECT_STREQ(test_entries[1].title, UTF16ToUTF8(m[1].description).c_str());
 }
 
 TEST_F(HistoryContentsProviderTest, Title) {
-  AutocompleteInput input(L"PAGEONE", std::wstring(), true, false, true, false);
+  AutocompleteInput input(ASCIIToUTF16("PAGEONE"), string16(), true, false,
+                          true, false);
   RunQuery(input, false);
 
   // The results should be the first two pages.
   const ACMatches& m = matches();
   ASSERT_EQ(2U, m.size());
   EXPECT_EQ(test_entries[0].url, m[0].destination_url.spec());
-  EXPECT_STREQ(test_entries[0].title, WideToUTF8(m[0].description).c_str());
+  EXPECT_STREQ(test_entries[0].title, UTF16ToUTF8(m[0].description).c_str());
   EXPECT_EQ(test_entries[1].url, m[1].destination_url.spec());
-  EXPECT_STREQ(test_entries[1].title, WideToUTF8(m[1].description).c_str());
+  EXPECT_STREQ(test_entries[1].title, UTF16ToUTF8(m[1].description).c_str());
 }
 
 // The "minimal changes" flag should mean that we don't re-query the DB.
 TEST_F(HistoryContentsProviderTest, MinimalChanges) {
   // A minimal changes request when there have been no real queries should
   // give us no results.
-  AutocompleteInput sync_input(L"PAGEONE", std::wstring(), true, false, true,
-                               true);
+  AutocompleteInput sync_input(ASCIIToUTF16("PAGEONE"), string16(), true, false,
+                               true, true);
   RunQuery(sync_input, true);
   const ACMatches& m1 = matches();
   EXPECT_EQ(0U, m1.size());
 
   // Now do a "regular" query to get the results.
-  AutocompleteInput async_input(L"PAGEONE", std::wstring(), true, false, true,
-                                false);
+  AutocompleteInput async_input(ASCIIToUTF16("PAGEONE"), string16(), true,
+                                false, true, false);
   RunQuery(async_input, false);
   const ACMatches& m2 = matches();
   EXPECT_EQ(2U, m2.size());
@@ -167,17 +167,18 @@
                                                ASCIIToUTF16("bar"), true);
 
   // Ask for synchronous. This should only get the bookmark.
-  AutocompleteInput sync_input(L"bar", std::wstring(), true, false, true, true);
+  AutocompleteInput sync_input(ASCIIToUTF16("bar"), string16(), true, false,
+                               true, true);
   RunQuery(sync_input, false);
   const ACMatches& m1 = matches();
   ASSERT_EQ(1U, m1.size());
   EXPECT_EQ(bookmark_url, m1[0].destination_url);
-  EXPECT_EQ(L"bar", m1[0].description);
+  EXPECT_EQ(ASCIIToUTF16("bar"), m1[0].description);
   EXPECT_TRUE(m1[0].starred);
 
   // Ask for async. We should get the bookmark immediately.
-  AutocompleteInput async_input(L"bar", std::wstring(), true, false, true,
-                                false);
+  AutocompleteInput async_input(ASCIIToUTF16("bar"), string16(), true, false,
+                                true, false);
   provider()->Start(async_input, false);
   const ACMatches& m2 = matches();
   ASSERT_EQ(1U, m2.size());
@@ -199,7 +200,8 @@
 
 // Tests that history is deleted properly.
 TEST_F(HistoryContentsProviderTest, DeleteMatch) {
-  AutocompleteInput input(L"bar", std::wstring(), true, false, true, false);
+  AutocompleteInput input(ASCIIToUTF16("bar"), string16(), true, false, true,
+                          false);
   RunQuery(input, false);
 
   // Query; the result should be the third page.
@@ -223,7 +225,8 @@
                                                ASCIIToUTF16("bar"), true);
 
   // Get the match to delete its history
-  AutocompleteInput input(L"bar", std::wstring(), true, false, true, false);
+  AutocompleteInput input(ASCIIToUTF16("bar"), string16(), true, false, true,
+                          false);
   RunQuery(input, false);
   const ACMatches& m = matches();
   ASSERT_EQ(1U, m.size());
@@ -233,7 +236,8 @@
   EXPECT_EQ(1U, matches().size());
 
   // Run a query that would only match history (but the history is deleted)
-  AutocompleteInput you_input(L"you", std::wstring(), true, false, true, false);
+  AutocompleteInput you_input(ASCIIToUTF16("you"), string16(), true, false,
+                              true, false);
   RunQuery(you_input, false);
   EXPECT_EQ(0U, matches().size());
 
diff --git a/chrome/browser/autocomplete/history_provider.cc b/chrome/browser/autocomplete/history_provider.cc
index cbcf691..4b1d9a3 100644
--- a/chrome/browser/autocomplete/history_provider.cc
+++ b/chrome/browser/autocomplete/history_provider.cc
@@ -60,10 +60,10 @@
 }
 
 // static
-std::wstring HistoryProvider::FixupUserInput(const AutocompleteInput& input) {
-  const std::wstring& input_text = input.text();
+string16 HistoryProvider::FixupUserInput(const AutocompleteInput& input) {
+  const string16& input_text = input.text();
   // Fixup and canonicalize user input.
-  const GURL canonical_gurl(URLFixerUpper::FixupURL(WideToUTF8(input_text),
+  const GURL canonical_gurl(URLFixerUpper::FixupURL(UTF16ToUTF8(input_text),
                                                     std::string()));
   std::string canonical_gurl_str(canonical_gurl.possibly_invalid_spec());
   if (canonical_gurl_str.empty()) {
@@ -80,8 +80,8 @@
   if ((input.type() != AutocompleteInput::URL) &&
       canonical_gurl.HostIsIPAddress()) {
     std::string original_hostname =
-        WideToUTF8(input_text.substr(input.parts().host.begin,
-                                     input.parts().host.len));
+        UTF16ToUTF8(input_text.substr(input.parts().host.begin,
+                                      input.parts().host.len));
     const url_parse::Parsed& parts =
         canonical_gurl.parsed_for_possibly_invalid_spec();
     // parts.host must not be empty when HostIsIPAddress() is true.
@@ -89,11 +89,11 @@
     canonical_gurl_str.replace(parts.host.begin, parts.host.len,
                                original_hostname);
   }
-  std::wstring output = UTF8ToWide(canonical_gurl_str);
+  string16 output = UTF8ToUTF16(canonical_gurl_str);
   // Don't prepend a scheme when the user didn't have one.  Since the fixer
   // upper only prepends the "http" scheme, that's all we need to check for.
   if (canonical_gurl.SchemeIs(chrome::kHttpScheme) &&
-      !url_util::FindAndCompareScheme(WideToUTF8(input_text),
+      !url_util::FindAndCompareScheme(UTF16ToUTF8(input_text),
                                       chrome::kHttpScheme, NULL))
     TrimHttpPrefix(&output);
 
@@ -111,12 +111,14 @@
   // trailing slashes (if the scheme is the only thing in the input).  It's not
   // clear that the result of fixup really matters in this case, but there's no
   // harm in making sure.
-  const size_t last_input_nonslash = input_text.find_last_not_of(L"/\\");
-  const size_t num_input_slashes = (last_input_nonslash == std::wstring::npos) ?
+  const size_t last_input_nonslash =
+      input_text.find_last_not_of(ASCIIToUTF16("/\\"));
+  const size_t num_input_slashes = (last_input_nonslash == string16::npos) ?
       input_text.length() : (input_text.length() - 1 - last_input_nonslash);
-  const size_t last_output_nonslash = output.find_last_not_of(L"/\\");
+  const size_t last_output_nonslash =
+      output.find_last_not_of(ASCIIToUTF16("/\\"));
   const size_t num_output_slashes =
-      (last_output_nonslash == std::wstring::npos) ?
+      (last_output_nonslash == string16::npos) ?
       output.length() : (output.length() - 1 - last_output_nonslash);
   if (num_output_slashes < num_input_slashes)
     output.append(num_input_slashes - num_output_slashes, '/');
@@ -127,17 +129,18 @@
 }
 
 // static
-size_t HistoryProvider::TrimHttpPrefix(std::wstring* url) {
+size_t HistoryProvider::TrimHttpPrefix(string16* url) {
   // Find any "http:".
   if (!HasHTTPScheme(*url))
     return 0;
-  size_t scheme_pos = url->find(ASCIIToWide(chrome::kHttpScheme) + L":");
-  DCHECK(scheme_pos != std::wstring::npos);
+  size_t scheme_pos =
+      url->find(ASCIIToUTF16(chrome::kHttpScheme) + char16(':'));
+  DCHECK(scheme_pos != string16::npos);
 
   // Erase scheme plus up to two slashes.
   size_t prefix_end = scheme_pos + strlen(chrome::kHttpScheme) + 1;
   const size_t after_slashes = std::min(url->length(), prefix_end + 2);
-  while ((prefix_end < after_slashes) && ((*url)[prefix_end] == L'/'))
+  while ((prefix_end < after_slashes) && ((*url)[prefix_end] == '/'))
     ++prefix_end;
   url->erase(scheme_pos, prefix_end - scheme_pos);
   return (scheme_pos == 0) ? prefix_end : 0;
diff --git a/chrome/browser/autocomplete/history_provider.h b/chrome/browser/autocomplete/history_provider.h
index 3cec58e..a304742 100644
--- a/chrome/browser/autocomplete/history_provider.h
+++ b/chrome/browser/autocomplete/history_provider.h
@@ -44,13 +44,13 @@
   // Note that we don't do this in AutocompleteInput's constructor, because if
   // e.g. we convert a Unicode hostname to punycode, other providers will show
   // output that surprises the user ("Search Google for xn--6ca.com").
-  static std::wstring FixupUserInput(const AutocompleteInput& input);
+  static string16 FixupUserInput(const AutocompleteInput& input);
 
   // Trims "http:" and up to two subsequent slashes from |url|.  Returns the
   // number of characters that were trimmed.
   // NOTE: For a view-source: URL, this will trim from after "view-source:" and
   // return 0.
-  static size_t TrimHttpPrefix(std::wstring* url);
+  static size_t TrimHttpPrefix(string16* url);
 };
 
 #endif  // CHROME_BROWSER_AUTOCOMPLETE_HISTORY_PROVIDER_H_
diff --git a/chrome/browser/autocomplete/history_provider_util.cc b/chrome/browser/autocomplete/history_provider_util.cc
index 39c26ec..4325b6b 100644
--- a/chrome/browser/autocomplete/history_provider_util.cc
+++ b/chrome/browser/autocomplete/history_provider_util.cc
@@ -12,7 +12,7 @@
 
 HistoryMatch::HistoryMatch()
     : url_info(),
-      input_location(std::wstring::npos),
+      input_location(string16::npos),
       match_in_scheme(false),
       innermost_match(true) {
 }
diff --git a/chrome/browser/autocomplete/history_provider_util.h b/chrome/browser/autocomplete/history_provider_util.h
index 5f72983..aa4b444 100644
--- a/chrome/browser/autocomplete/history_provider_util.h
+++ b/chrome/browser/autocomplete/history_provider_util.h
@@ -57,11 +57,11 @@
 typedef std::deque<HistoryMatch> HistoryMatches;
 
 struct Prefix {
-  Prefix(const std::wstring& prefix, int num_components)
+  Prefix(const string16& prefix, int num_components)
       : prefix(prefix),
         num_components(num_components) {}
 
-  std::wstring prefix;
+  string16 prefix;
 
   // The number of "components" in the prefix.  The scheme is a component,
   // and the initial "www." or "ftp." is a component.  So "http://foo.com"
diff --git a/chrome/browser/autocomplete/history_quick_provider.cc b/chrome/browser/autocomplete/history_quick_provider.cc
index 0392f1e..9f8fbaa 100644
--- a/chrome/browser/autocomplete/history_quick_provider.cc
+++ b/chrome/browser/autocomplete/history_quick_provider.cc
@@ -52,7 +52,7 @@
   // NOTE: This purposefully doesn't take input.desired_tld() into account; if
   // it did, then holding "ctrl" would change all the results from the
   // HistoryQuickProvider provider, not just the What You Typed Result.
-  const std::wstring fixed_text(FixupUserInput(input));
+  const string16 fixed_text(FixupUserInput(input));
   if (fixed_text.empty()) {
     // Conceivably fixup could result in an empty string (although I don't
     // have cases where this happens offhand).  We can't do anything with
@@ -76,7 +76,7 @@
 
 void HistoryQuickProvider::DoAutocomplete() {
   // Get the matching URLs from the DB.
-  string16 term_string(WideToUTF16(autocomplete_input_.text()));
+  string16 term_string = autocomplete_input_.text();
   term_string = UnescapeURLComponent(term_string,
       UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
   history::InMemoryURLIndex::String16Vector terms(
@@ -114,34 +114,33 @@
       match_type == WHAT_YOU_TYPED ? std::string() : languages_;
   match.fill_into_edit =
       AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(),
-          UTF16ToWide(net::FormatUrl(info.url(), languages, format_types,
-                                     UnescapeRule::SPACES, NULL, NULL,
-                                     &inline_autocomplete_offset)));
+          net::FormatUrl(info.url(), languages, format_types,
+                         UnescapeRule::SPACES, NULL, NULL,
+                         &inline_autocomplete_offset));
   if (!autocomplete_input_.prevent_inline_autocomplete())
     match.inline_autocomplete_offset = inline_autocomplete_offset;
-  DCHECK((match.inline_autocomplete_offset == std::wstring::npos) ||
+  DCHECK((match.inline_autocomplete_offset == string16::npos) ||
          (match.inline_autocomplete_offset <= match.fill_into_edit.length()));
 
   size_t match_start = history_match.input_location;
-  match.contents =
-      UTF16ToWide(net::FormatUrl(info.url(), languages, format_types,
-                                 UnescapeRule::SPACES, NULL, NULL,
-                                 &match_start));
-  if ((match_start != std::wstring::npos) &&
-      (inline_autocomplete_offset != std::wstring::npos) &&
+  match.contents = net::FormatUrl(info.url(), languages, format_types,
+                                  UnescapeRule::SPACES, NULL, NULL,
+                                  &match_start);
+  if ((match_start != string16::npos) &&
+      (inline_autocomplete_offset != string16::npos) &&
       (inline_autocomplete_offset != match_start)) {
     DCHECK(inline_autocomplete_offset > match_start);
     AutocompleteMatch::ClassifyLocationInString(match_start,
         inline_autocomplete_offset - match_start, match.contents.length(),
         ACMatchClassification::URL, &match.contents_class);
   } else {
-    AutocompleteMatch::ClassifyLocationInString(std::wstring::npos, 0,
+    AutocompleteMatch::ClassifyLocationInString(string16::npos, 0,
         match.contents.length(), ACMatchClassification::URL,
         &match.contents_class);
   }
-  match.description = UTF16ToWide(info.title());
+  match.description = info.title();
   AutocompleteMatch::ClassifyMatchInString(autocomplete_input_.text(),
-                                           UTF16ToWide(info.title()),
+                                           info.title(),
                                            ACMatchClassification::NONE,
                                            &match.description_class);
 
diff --git a/chrome/browser/autocomplete/history_quick_provider_unittest.cc b/chrome/browser/autocomplete/history_quick_provider_unittest.cc
index 7dab5dc..e9f0581 100644
--- a/chrome/browser/autocomplete/history_quick_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_quick_provider_unittest.cc
@@ -96,7 +96,7 @@
   // Runs an autocomplete query on |text| and checks to see that the returned
   // results' destination URLs match those provided. |expected_urls| does not
   // need to be in sorted order.
-  void RunTest(const std::wstring text,
+  void RunTest(const string16 text,
                std::vector<std::string> expected_urls,
                std::string expected_top_result);
 
@@ -163,13 +163,13 @@
   std::set<std::string> matches_;
 };
 
-void HistoryQuickProviderTest::RunTest(const std::wstring text,
+void HistoryQuickProviderTest::RunTest(const string16 text,
                                        std::vector<std::string> expected_urls,
                                        std::string expected_top_result) {
   std::sort(expected_urls.begin(), expected_urls.end());
 
   MessageLoop::current()->RunAllPending();
-  AutocompleteInput input(text, std::wstring(), false, false, true, false);
+  AutocompleteInput input(text, string16(), false, false, true, false);
   provider_->Start(input, false);
   EXPECT_TRUE(provider_->done());
 
@@ -194,7 +194,7 @@
 }
 
 TEST_F(HistoryQuickProviderTest, SimpleSingleMatch) {
-  std::wstring text(L"slashdot");
+  string16 text(ASCIIToUTF16("slashdot"));
   std::string expected_url("http://slashdot.org/favorite_page.html");
   std::vector<std::string> expected_urls;
   expected_urls.push_back(expected_url);
@@ -202,7 +202,7 @@
 }
 
 TEST_F(HistoryQuickProviderTest, MultiMatch) {
-  std::wstring text(L"foo");
+  string16 text(ASCIIToUTF16("foo"));
   std::vector<std::string> expected_urls;
   expected_urls.push_back("http://foo.com/");
   expected_urls.push_back("http://foo.com/dir/");
@@ -214,7 +214,7 @@
 }
 
 TEST_F(HistoryQuickProviderTest, StartRelativeMatch) {
-  std::wstring text(L"xyz");
+  string16 text(ASCIIToUTF16("xyz"));
   std::vector<std::string> expected_urls;
   expected_urls.push_back("http://xyzabcdefghijklmnopqrstuvw.com/a");
   expected_urls.push_back("http://abcxyzdefghijklmnopqrstuvw.com/a");
@@ -225,7 +225,7 @@
 }
 
 TEST_F(HistoryQuickProviderTest, RecencyMatch) {
-  std::wstring text(L"startest");
+  string16 text(ASCIIToUTF16("startest"));
   std::vector<std::string> expected_urls;
   expected_urls.push_back("http://startest.com/y/a");
   expected_urls.push_back("http://startest.com/y/b");
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc
index 41fb155..1db38f0 100644
--- a/chrome/browser/autocomplete/history_url_provider.cc
+++ b/chrome/browser/autocomplete/history_url_provider.cc
@@ -78,7 +78,7 @@
 // Given the user's |input| and a |match| created from it, reduce the
 // match's URL to just a host.  If this host still matches the user input,
 // return it.  Returns the empty string on failure.
-GURL ConvertToHostOnly(const HistoryMatch& match, const std::wstring& input) {
+GURL ConvertToHostOnly(const HistoryMatch& match, const string16& input) {
   // See if we should try to do host-only suggestions for this URL. Nonstandard
   // schemes means there's no authority section, so suggesting the host name
   // is useless. File URLs are standard, but host suggestion is not useful for
@@ -93,7 +93,7 @@
   if ((host.spec().length() < (match.input_location + input.length())))
     return GURL();  // User typing is longer than this host suggestion.
 
-  const std::wstring spec = UTF8ToWide(host.spec());
+  const string16 spec = UTF8ToUTF16(host.spec());
   if (spec.compare(match.input_location, input.length(), input))
     return GURL();  // User typing is no longer a prefix.
 
@@ -188,7 +188,7 @@
       (params->input.type() != AutocompleteInput::QUERY) &&
       ((params->input.type() != AutocompleteInput::UNKNOWN) ||
           !params->trim_http ||
-          url_util::FindAndCompareScheme(WideToUTF8(params->input.text()),
+          url_util::FindAndCompareScheme(UTF16ToUTF8(params->input.text()),
                                          chrome::kHttpsScheme, NULL));
   AutocompleteMatch what_you_typed_match(SuggestExactInput(params->input,
                                                            params->trim_http));
@@ -208,11 +208,11 @@
     // for more results than we need, of every prefix type, in hopes this will
     // give us far more than enough to work with.  CullRedirects() will then
     // reduce the list to the best kMaxMatches results.
-    db->AutocompleteForPrefix(WideToUTF16(i->prefix + params->input.text()),
+    db->AutocompleteForPrefix(i->prefix + params->input.text(),
                               kMaxMatches * 2, (backend == NULL), &url_matches);
     for (URLRowVector::const_iterator j(url_matches.begin());
          j != url_matches.end(); ++j) {
-      const Prefix* best_prefix = BestPrefix(j->url(), std::wstring());
+      const Prefix* best_prefix = BestPrefix(j->url(), string16());
       DCHECK(best_prefix != NULL);
       history_matches.push_back(HistoryMatch(*j, i->prefix.length(),
           !i->num_components,
@@ -313,7 +313,7 @@
     // |match_location| below.  StringForURLDisplay() and TrimHttpPrefix() have
     // slightly different behavior as well (the latter will strip even without
     // two slashes after the scheme).
-    std::wstring display_string(StringForURLDisplay(url, false, false));
+    string16 display_string(StringForURLDisplay(url, false, false));
     const size_t offset = trim_http ? TrimHttpPrefix(&display_string) : 0;
     match.fill_into_edit =
         AutocompleteInput::FormattedStringWithEquivalentMeaning(url,
@@ -331,7 +331,7 @@
     // to not contain the user's input at all.  In this case don't mark anything
     // as a match.
     const size_t match_location = (best_prefix == NULL) ?
-        std::wstring::npos : best_prefix->prefix.length() - offset;
+        string16::npos : best_prefix->prefix.length() - offset;
     AutocompleteMatch::ClassifyLocationInString(match_location,
                                                 input.text().length(),
                                                 match.contents.length(),
@@ -371,7 +371,7 @@
   if (!db->GetRowForURL(match->destination_url, &info)) {
     if (input.desired_tld().empty())
       return false;
-    GURL destination_url(URLFixerUpper::FixupURL(WideToUTF8(input.text()),
+    GURL destination_url(URLFixerUpper::FixupURL(UTF16ToUTF8(input.text()),
                                                  std::string()));
     if (!db->GetRowForURL(destination_url, NULL))
       return false;
@@ -382,9 +382,9 @@
   } else {
     // We have data for this match, use it.
     match->deletable = true;
-    match->description = UTF16ToWide(info.title());
+    match->description = info.title();
     AutocompleteMatch::ClassifyMatchInString(input.text(),
-        UTF16ToWide(info.title()),
+        info.title(),
         ACMatchClassification::NONE, &match->description_class);
     if (!info.typed_count()) {
       // If we reach here, we must be in the second pass, and we must not have
@@ -402,7 +402,7 @@
   match->relevance = CalculateRelevance(input.type(), type, 0);
 
   // Put it on the front of the HistoryMatches for redirect culling.
-  EnsureMatchPresent(info, std::wstring::npos, false, matches, true);
+  EnsureMatchPresent(info, string16::npos, false, matches, true);
   return true;
 }
 
@@ -425,19 +425,22 @@
   return true;
 }
 
+HistoryURLProvider::~HistoryURLProvider() {}
+
 // static
 history::Prefixes HistoryURLProvider::GetPrefixes() {
   // We'll complete text following these prefixes.
   // NOTE: There's no requirement that these be in any particular order.
   Prefixes prefixes;
-  prefixes.push_back(Prefix(L"https://www.", 2));
-  prefixes.push_back(Prefix(L"http://www.", 2));
-  prefixes.push_back(Prefix(L"ftp://ftp.", 2));
-  prefixes.push_back(Prefix(L"ftp://www.", 2));
-  prefixes.push_back(Prefix(L"https://", 1));
-  prefixes.push_back(Prefix(L"http://", 1));
-  prefixes.push_back(Prefix(L"ftp://", 1));
-  prefixes.push_back(Prefix(L"", 0));  // Catches within-scheme matches as well
+  prefixes.push_back(Prefix(ASCIIToUTF16("https://www."), 2));
+  prefixes.push_back(Prefix(ASCIIToUTF16("http://www."), 2));
+  prefixes.push_back(Prefix(ASCIIToUTF16("ftp://ftp."), 2));
+  prefixes.push_back(Prefix(ASCIIToUTF16("ftp://www."), 2));
+  prefixes.push_back(Prefix(ASCIIToUTF16("https://"), 1));
+  prefixes.push_back(Prefix(ASCIIToUTF16("http://"), 1));
+  prefixes.push_back(Prefix(ASCIIToUTF16("ftp://"), 1));
+  // Empty string catches within-scheme matches as well.
+  prefixes.push_back(Prefix(string16(), 0));
   return prefixes;
 }
 
@@ -529,7 +532,7 @@
 // static
 void HistoryURLProvider::EnsureMatchPresent(
     const history::URLRow& info,
-    std::wstring::size_type input_location,
+    string16::size_type input_location,
     bool match_in_scheme,
     HistoryMatches* matches,
     bool promote) {
@@ -594,7 +597,7 @@
     // NOTE: This purposefully doesn't take input.desired_tld() into account; if
     // it did, then holding "ctrl" would change all the results from the
     // HistoryURLProvider provider, not just the What You Typed Result.
-    const std::wstring fixed_text(FixupUserInput(input));
+    const string16 fixed_text(FixupUserInput(input));
     if (fixed_text.empty()) {
       // Conceivably fixup could result in an empty string (although I don't
       // have cases where this happens offhand).  We can't do anything with
@@ -635,14 +638,14 @@
 
 const history::Prefix* HistoryURLProvider::BestPrefix(
     const GURL& url,
-    const std::wstring& prefix_suffix) const {
+    const string16& prefix_suffix) const {
   const Prefix* best_prefix = NULL;
-  const std::wstring text(UTF8ToWide(url.spec()));
+  const string16 text(UTF8ToUTF16(url.spec()));
   for (Prefixes::const_iterator i(prefixes_.begin()); i != prefixes_.end();
        ++i) {
     if ((best_prefix == NULL) ||
         (i->num_components > best_prefix->num_components)) {
-      std::wstring prefix_with_suffix(i->prefix + prefix_suffix);
+      string16 prefix_with_suffix(i->prefix + prefix_suffix);
       if ((text.length() >= prefix_with_suffix.length()) &&
           !text.compare(0, prefix_with_suffix.length(), prefix_with_suffix))
         best_prefix = &(*i);
@@ -778,32 +781,32 @@
           0 : net::kFormatUrlOmitHTTP);
   match.fill_into_edit =
       AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(),
-          UTF16ToWideHack(net::FormatUrl(info.url(), languages, format_types,
-                                         UnescapeRule::SPACES, NULL, NULL,
-                                         &inline_autocomplete_offset)));
+          net::FormatUrl(info.url(), languages, format_types,
+                         UnescapeRule::SPACES, NULL, NULL,
+                         &inline_autocomplete_offset));
   if (!params->input.prevent_inline_autocomplete())
     match.inline_autocomplete_offset = inline_autocomplete_offset;
-  DCHECK((match.inline_autocomplete_offset == std::wstring::npos) ||
+  DCHECK((match.inline_autocomplete_offset == string16::npos) ||
          (match.inline_autocomplete_offset <= match.fill_into_edit.length()));
 
   size_t match_start = history_match.input_location;
-  match.contents = UTF16ToWideHack(net::FormatUrl(info.url(), languages,
-      format_types, UnescapeRule::SPACES, NULL, NULL, &match_start));
-  if ((match_start != std::wstring::npos) &&
-      (inline_autocomplete_offset != std::wstring::npos) &&
+  match.contents = net::FormatUrl(info.url(), languages,
+      format_types, UnescapeRule::SPACES, NULL, NULL, &match_start);
+  if ((match_start != string16::npos) &&
+      (inline_autocomplete_offset != string16::npos) &&
       (inline_autocomplete_offset != match_start)) {
     DCHECK(inline_autocomplete_offset > match_start);
     AutocompleteMatch::ClassifyLocationInString(match_start,
         inline_autocomplete_offset - match_start, match.contents.length(),
         ACMatchClassification::URL, &match.contents_class);
   } else {
-    AutocompleteMatch::ClassifyLocationInString(std::wstring::npos, 0,
+    AutocompleteMatch::ClassifyLocationInString(string16::npos, 0,
         match.contents.length(), ACMatchClassification::URL,
         &match.contents_class);
   }
-  match.description = UTF16ToWide(info.title());
+  match.description = info.title();
   AutocompleteMatch::ClassifyMatchInString(params->input.text(),
-                                           UTF16ToWide(info.title()),
+                                           info.title(),
                                            ACMatchClassification::NONE,
                                            &match.description_class);
 
diff --git a/chrome/browser/autocomplete/history_url_provider.h b/chrome/browser/autocomplete/history_url_provider.h
index 0e4e5ff..ac93c57 100644
--- a/chrome/browser/autocomplete/history_url_provider.h
+++ b/chrome/browser/autocomplete/history_url_provider.h
@@ -175,7 +175,7 @@
   void QueryComplete(HistoryURLProviderParams* params_gets_deleted);
 
  private:
-  ~HistoryURLProvider() {}
+  ~HistoryURLProvider();
 
   // Returns the set of prefixes to use for prefixes_.
   static history::Prefixes GetPrefixes();
@@ -192,7 +192,7 @@
   // match's URL to just a host.  If this host still matches the user input,
   // return it.  Returns the empty string on failure.
   static GURL ConvertToHostOnly(const history::HistoryMatch& match,
-                                const std::wstring& input);
+                                const string16& input);
 
   // See if a shorter version of the best match should be created, and if so
   // place it at the front of |matches|.  This can suggest history URLs that
@@ -216,7 +216,7 @@
   // |promote| is false, existing matches are left in place, and newly added
   // matches are placed at the back.
   static void EnsureMatchPresent(const history::URLRow& info,
-                                 std::wstring::size_type input_location,
+                                 string16::size_type input_location,
                                  bool match_in_scheme,
                                  history::HistoryMatches* matches,
                                  bool promote);
@@ -232,7 +232,7 @@
   // prefix.  This is useful when you need to figure out the innermost match
   // for some user input in a URL.
   const history::Prefix* BestPrefix(const GURL& text,
-                                    const std::wstring& prefix_suffix) const;
+                                    const string16& prefix_suffix) const;
 
   // Returns a match corresponding to exactly what the user has typed.
   AutocompleteMatch SuggestExactInput(const AutocompleteInput& input,
diff --git a/chrome/browser/autocomplete/history_url_provider_unittest.cc b/chrome/browser/autocomplete/history_url_provider_unittest.cc
index b0f3cbd..116cab6 100644
--- a/chrome/browser/autocomplete/history_url_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_url_provider_unittest.cc
@@ -115,13 +115,13 @@
 
   // Runs an autocomplete query on |text| and checks to see that the returned
   // results' destination URLs match those provided.
-  void RunTest(const std::wstring text,
-               const std::wstring& desired_tld,
+  void RunTest(const string16 text,
+               const string16& desired_tld,
                bool prevent_inline_autocomplete,
                const std::string* expected_urls,
                size_t num_results);
 
-  void RunAdjustOffsetTest(const std::wstring text, size_t expected_offset);
+  void RunAdjustOffsetTest(const string16 text, size_t expected_offset);
 
   MessageLoopForUI message_loop_;
   BrowserThread ui_thread_;
@@ -180,8 +180,8 @@
   }
 }
 
-void HistoryURLProviderTest::RunTest(const std::wstring text,
-                                     const std::wstring& desired_tld,
+void HistoryURLProviderTest::RunTest(const string16 text,
+                                     const string16& desired_tld,
                                      bool prevent_inline_autocomplete,
                                      const std::string* expected_urls,
                                      size_t num_results) {
@@ -198,9 +198,9 @@
     EXPECT_EQ(expected_urls[i], matches_[i].destination_url.spec());
 }
 
-void HistoryURLProviderTest::RunAdjustOffsetTest(const std::wstring text,
+void HistoryURLProviderTest::RunAdjustOffsetTest(const string16 text,
                                                  size_t expected_offset) {
-  AutocompleteInput input(text, std::wstring(), false, false, true, false);
+  AutocompleteInput input(text, string16(), false, false, true, false);
   autocomplete_->Start(input, false);
   if (!autocomplete_->done())
     MessageLoop::current()->Run();
@@ -216,7 +216,7 @@
     "http://slashdot.org/favorite_page.html",
     "http://slashdot.org/",
   };
-  RunTest(L"slash", std::wstring(), true, expected_nonsynth,
+  RunTest(ASCIIToUTF16("slash"), string16(), true, expected_nonsynth,
           arraysize(expected_nonsynth));
 
   // Test that hosts get synthesized above less popular pages.
@@ -224,11 +224,11 @@
     "http://kerneltrap.org/",
     "http://kerneltrap.org/not_very_popular.html",
   };
-  RunTest(L"kernel", std::wstring(), true, expected_synth,
+  RunTest(ASCIIToUTF16("kernel"), string16(), true, expected_synth,
           arraysize(expected_synth));
 
   // Test that unpopular pages are ignored completely.
-  RunTest(L"fresh", std::wstring(), true, NULL, 0);
+  RunTest(ASCIIToUTF16("fresh"), string16(), true, NULL, 0);
 
   // Test that if we have a synthesized host that matches a suggestion, they
   // get combined into one.
@@ -236,11 +236,11 @@
     "http://news.google.com/",
     "http://news.google.com/?ned=us&topic=n",
   };
-  ASSERT_NO_FATAL_FAILURE(RunTest(L"news", std::wstring(), true,
+  ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("news"), string16(), true,
       expected_combine, arraysize(expected_combine)));
   // The title should also have gotten set properly on the host for the
   // synthesized one, since it was also in the results.
-  EXPECT_EQ(std::wstring(L"Google News"), matches_.front().description);
+  EXPECT_EQ(ASCIIToUTF16("Google News"), matches_.front().description);
 
   // Test that short URL matching works correctly as the user types more
   // (several tests):
@@ -250,7 +250,7 @@
     "http://foo.com/dir/another/again/myfile.html",
     "http://foo.com/dir/",
   };
-  RunTest(L"foo", std::wstring(), true, short_1, arraysize(short_1));
+  RunTest(ASCIIToUTF16("foo"), string16(), true, short_1, arraysize(short_1));
 
   // When the user types the whole host, make sure we don't get two results for
   // it.
@@ -260,8 +260,10 @@
     "http://foo.com/dir/",
     "http://foo.com/dir/another/",
   };
-  RunTest(L"foo.com", std::wstring(), true, short_2, arraysize(short_2));
-  RunTest(L"foo.com/", std::wstring(), true, short_2, arraysize(short_2));
+  RunTest(ASCIIToUTF16("foo.com"), string16(), true, short_2,
+          arraysize(short_2));
+  RunTest(ASCIIToUTF16("foo.com/"), string16(), true, short_2,
+          arraysize(short_2));
 
   // The filename is the second best of the foo.com* entries, but there is a
   // shorter URL that's "good enough".  The host doesn't match the user input
@@ -272,7 +274,8 @@
     "http://foo.com/dir/another/again/myfile.html",
     "http://foo.com/dir/",
   };
-  RunTest(L"foo.com/d", std::wstring(), true, short_3, arraysize(short_3));
+  RunTest(ASCIIToUTF16("foo.com/d"), string16(), true, short_3,
+          arraysize(short_3));
 
   // We shouldn't promote shorter URLs than the best if they're not good
   // enough.
@@ -281,7 +284,7 @@
     "http://foo.com/dir/another/again/myfile.html",
     "http://foo.com/dir/another/again/",
   };
-  RunTest(L"foo.com/dir/another/a", std::wstring(), true, short_4,
+  RunTest(ASCIIToUTF16("foo.com/dir/another/a"), string16(), true, short_4,
           arraysize(short_4));
 
   // Exact matches should always be best no matter how much more another match
@@ -295,8 +298,8 @@
     "http://gooey/",
     "http://www.google.com/",
   };
-  RunTest(L"g", std::wstring(), false, short_5a, arraysize(short_5a));
-  RunTest(L"go", std::wstring(), false, short_5b, arraysize(short_5b));
+  RunTest(ASCIIToUTF16("g"), string16(), false, short_5a, arraysize(short_5a));
+  RunTest(ASCIIToUTF16("go"), string16(), false, short_5b, arraysize(short_5b));
 }
 
 TEST_F(HistoryURLProviderTest, CullRedirects) {
@@ -336,31 +339,32 @@
   // Because all the results are part of a redirect chain with other results,
   // all but the first one (A) should be culled. We should get the default
   // "what you typed" result, plus this one.
-  const std::wstring typing(L"http://redirects/");
+  const string16 typing(ASCIIToUTF16("http://redirects/"));
   const std::string expected_results[] = {
-    WideToUTF8(typing),
+    UTF16ToUTF8(typing),
     redirect[0].url};
-  RunTest(typing, std::wstring(), true, expected_results,
+  RunTest(typing, string16(), true, expected_results,
           arraysize(expected_results));
 }
 
 TEST_F(HistoryURLProviderTest, WhatYouTyped) {
   // Make sure we suggest a What You Typed match at the right times.
-  RunTest(L"wytmatch", std::wstring(), false, NULL, 0);
-  RunTest(L"wytmatch foo bar", std::wstring(), false, NULL, 0);
-  RunTest(L"wytmatch+foo+bar", std::wstring(), false, NULL, 0);
-  RunTest(L"wytmatch+foo+bar.com", std::wstring(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("wytmatch"), string16(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("wytmatch foo bar"), string16(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("wytmatch+foo+bar"), string16(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("wytmatch+foo+bar.com"), string16(), false, NULL, 0);
 
   const std::string results_1[] = {"http://www.wytmatch.com/"};
-  RunTest(L"wytmatch", L"com", false, results_1, arraysize(results_1));
+  RunTest(ASCIIToUTF16("wytmatch"), ASCIIToUTF16("com"), false, results_1,
+          arraysize(results_1));
 
   const std::string results_2[] = {"http://wytmatch%20foo%20bar/"};
-  RunTest(L"http://wytmatch foo bar", std::wstring(), false, results_2,
+  RunTest(ASCIIToUTF16("http://wytmatch foo bar"), string16(), false, results_2,
           arraysize(results_2));
 
   const std::string results_3[] = {"https://wytmatch%20foo%20bar/"};
-  RunTest(L"https://wytmatch foo bar", std::wstring(), false, results_3,
-          arraysize(results_3));
+  RunTest(ASCIIToUTF16("https://wytmatch foo bar"), string16(), false,
+          results_3, arraysize(results_3));
 
   // Test the corner case where a user has fully typed a previously visited
   // intranet address and is now hitting ctrl-enter, which completes to a
@@ -370,9 +374,9 @@
     "http://www.binky.com/",
     "http://binky/",
   };
-  RunTest(L"binky", std::wstring(), false, binky_results,
+  RunTest(ASCIIToUTF16("binky"), string16(), false, binky_results,
           arraysize(binky_results));
-  RunTest(L"binky", L"com", false, binky_com_results,
+  RunTest(ASCIIToUTF16("binky"), ASCIIToUTF16("com"), false, binky_com_results,
           arraysize(binky_com_results));
 
   // Test the related case where a user has fully typed a previously visited
@@ -386,71 +390,74 @@
     "http://www.winky.com/",
     "http://winky/",
   };
-  RunTest(L"winky", std::wstring(), false, winky_results,
+  RunTest(ASCIIToUTF16("winky"), string16(), false, winky_results,
           arraysize(winky_results));
-  RunTest(L"winky", L"com", false, winky_com_results,
+  RunTest(ASCIIToUTF16("winky"), ASCIIToUTF16("com"), false, winky_com_results,
           arraysize(winky_com_results));
 }
 
 TEST_F(HistoryURLProviderTest, Fixup) {
   // Test for various past crashes we've had.
-  RunTest(L"\\", std::wstring(), false, NULL, 0);
-  RunTest(L"#", std::wstring(), false, NULL, 0);
-  RunTest(L"%20", std::wstring(), false, NULL, 0);
-  RunTest(L"\uff65@s", std::wstring(), false, NULL, 0);
-  RunTest(L"\u2015\u2015@ \uff7c", std::wstring(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("\\"), string16(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("#"), string16(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("%20"), string16(), false, NULL, 0);
+  RunTest(WideToUTF16(L"\uff65@s"), string16(), false, NULL, 0);
+  RunTest(WideToUTF16(L"\u2015\u2015@ \uff7c"), string16(), false, NULL, 0);
 
   // Fixing up "file:" should result in an inline autocomplete offset of just
   // after "file:", not just after "file://".
-  const std::wstring input_1(L"file:");
+  const string16 input_1(ASCIIToUTF16("file:"));
   const std::string fixup_1[] = {"file:///C:/foo.txt"};
-  ASSERT_NO_FATAL_FAILURE(RunTest(input_1, std::wstring(), false, fixup_1,
+  ASSERT_NO_FATAL_FAILURE(RunTest(input_1, string16(), false, fixup_1,
                                   arraysize(fixup_1)));
   EXPECT_EQ(input_1.length(), matches_.front().inline_autocomplete_offset);
 
   // Fixing up "http:/" should result in an inline autocomplete offset of just
   // after "http:/", not just after "http:".
-  const std::wstring input_2(L"http:/");
+  const string16 input_2(ASCIIToUTF16("http:/"));
   const std::string fixup_2[] = {
     "http://bogussite.com/a",
     "http://bogussite.com/b",
     "http://bogussite.com/c",
   };
-  ASSERT_NO_FATAL_FAILURE(RunTest(input_2, std::wstring(), false, fixup_2,
+  ASSERT_NO_FATAL_FAILURE(RunTest(input_2, string16(), false, fixup_2,
                                   arraysize(fixup_2)));
   EXPECT_EQ(input_2.length(), matches_.front().inline_autocomplete_offset);
 
   // Adding a TLD to a small number like "56" should result in "www.56.com"
   // rather than "0.0.0.56.com".
   const std::string fixup_3[] = {"http://www.56.com/"};
-  RunTest(L"56", L"com", true, fixup_3, arraysize(fixup_3));
+  RunTest(ASCIIToUTF16("56"), ASCIIToUTF16("com"), true, fixup_3,
+          arraysize(fixup_3));
 
   // An input looks like a IP address like "127.0.0.1" should result in
   // "http://127.0.0.1/".
   const std::string fixup_4[] = {"http://127.0.0.1/"};
-  RunTest(L"127.0.0.1", std::wstring(), false, fixup_4, arraysize(fixup_4));
+  RunTest(ASCIIToUTF16("127.0.0.1"), string16(), false, fixup_4,
+          arraysize(fixup_4));
 
   // An number "17173" should result in "http://www.17173.com/" in db.
   const std::string fixup_5[] = {"http://www.17173.com/"};
-  RunTest(L"17173", std::wstring(), false, fixup_5, arraysize(fixup_5));
+  RunTest(ASCIIToUTF16("17173"), string16(), false, fixup_5,
+          arraysize(fixup_5));
 }
 
 TEST_F(HistoryURLProviderTest, AdjustOffset) {
-  RunAdjustOffsetTest(L"http://www.\uAD50\uC721", 13);
-  RunAdjustOffsetTest(L"http://spaces.com/path%20with%20spa", 31);
-  RunAdjustOffsetTest(L"http://ms/c++ s", 15);
+  RunAdjustOffsetTest(WideToUTF16(L"http://www.\uAD50\uC721"), 13);
+  RunAdjustOffsetTest(ASCIIToUTF16("http://spaces.com/path%20with%20spa"), 31);
+  RunAdjustOffsetTest(ASCIIToUTF16("http://ms/c++ s"), 15);
 }
 
 TEST_F(HistoryURLProviderTestNoDB, NavigateWithoutDB) {
   // Ensure that we will still produce matches for navigation when there is no
   // database.
   std::string navigation_1[] = {"http://test.com/"};
-  RunTest(L"test.com", std::wstring(), false, navigation_1,
+  RunTest(ASCIIToUTF16("test.com"), string16(), false, navigation_1,
           arraysize(navigation_1));
 
   std::string navigation_2[] = {"http://slash/"};
-  RunTest(L"slash", std::wstring(), false, navigation_2,
+  RunTest(ASCIIToUTF16("slash"), string16(), false, navigation_2,
           arraysize(navigation_2));
 
-  RunTest(L"this is a query", std::wstring(), false, NULL, 0);
+  RunTest(ASCIIToUTF16("this is a query"), string16(), false, NULL, 0);
 }
diff --git a/chrome/browser/autocomplete/keyword_provider.cc b/chrome/browser/autocomplete/keyword_provider.cc
index 71a8f40..97ccc5c 100644
--- a/chrome/browser/autocomplete/keyword_provider.cc
+++ b/chrome/browser/autocomplete/keyword_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
@@ -21,6 +20,7 @@
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // Helper functor for Start(), for ending keyword mode unless explicitly told
 // otherwise.
@@ -41,15 +41,17 @@
 };
 
 // static
-std::wstring KeywordProvider::SplitReplacementStringFromInput(
-    const std::wstring& input) {
+string16 KeywordProvider::SplitReplacementStringFromInput(
+    const string16& input,
+    bool trim_leading_whitespace) {
   // The input may contain leading whitespace, strip it.
-  std::wstring trimmed_input;
+  string16 trimmed_input;
   TrimWhitespace(input, TRIM_LEADING, &trimmed_input);
 
   // And extract the replacement string.
-  std::wstring remaining_input;
-  SplitKeywordFromInput(trimmed_input, &remaining_input);
+  string16 remaining_input;
+  SplitKeywordFromInput(trimmed_input, trim_leading_whitespace,
+                        &remaining_input);
   return remaining_input;
 }
 
@@ -89,8 +91,8 @@
   // probably better rankings than the fraction of the keyword typed.  We should
   // always put any exact matches first no matter what, since the code in
   // Start() assumes this (and it makes sense).
-  bool operator()(const std::wstring& keyword1,
-                  const std::wstring& keyword2) const {
+  bool operator()(const string16& keyword1,
+                  const string16& keyword2) const {
     return keyword1.length() < keyword2.length();
   }
 };
@@ -105,11 +107,11 @@
 const TemplateURL* KeywordProvider::GetSubstitutingTemplateURLForInput(
     Profile* profile,
     const AutocompleteInput& input,
-    std::wstring* remaining_input) {
+    string16* remaining_input) {
   if (!input.allow_exact_keyword_match())
     return NULL;
 
-  std::wstring keyword;
+  string16 keyword;
   if (!ExtractKeywordFromInput(input, &keyword, remaining_input))
     return NULL;
 
@@ -152,7 +154,7 @@
   // keywords, we might suggest keywords that haven't even been partially typed,
   // if the user uses them enough and isn't obviously typing something else.  In
   // this case we'd consider all input here to be query input.
-  std::wstring keyword, remaining_input;
+  string16 keyword, remaining_input;
   if (!ExtractKeywordFromInput(input, &keyword, &remaining_input))
     return;
 
@@ -172,13 +174,14 @@
   // TODO(pkasting): http://b/893701 We should remember the user's use of a
   // search query both from the autocomplete popup and from web pages
   // themselves.
-  std::vector<std::wstring> keyword_matches;
-  model->FindMatchingKeywords(keyword, !remaining_input.empty(),
+  std::vector<string16> keyword_matches;
+  model->FindMatchingKeywords(keyword,
+                              !remaining_input.empty(),
                               &keyword_matches);
 
   // Prune any extension keywords that are disallowed in incognito mode (if
   // we're incognito), or disabled.
-  for (std::vector<std::wstring>::iterator i(keyword_matches.begin());
+  for (std::vector<string16>::iterator i(keyword_matches.begin());
        i != keyword_matches.end(); ) {
     const TemplateURL* template_url(model->GetTemplateURLForKeyword(*i));
     if (profile_ &&
@@ -220,7 +223,7 @@
       keyword_mode_toggle.StayInKeywordMode();
 
       ApplyDefaultSuggestionForExtensionKeyword(profile_, template_url,
-                                                WideToUTF16(remaining_input),
+                                                remaining_input,
                                                 &matches_[0]);
 
       if (minimal_changes) {
@@ -237,7 +240,7 @@
 
         bool have_listeners = ExtensionOmniboxEventRouter::OnInputChanged(
             profile_, template_url->GetExtensionId(),
-            WideToUTF8(remaining_input), current_input_id_);
+            UTF16ToUTF8(remaining_input), current_input_id_);
 
         // We only have to wait for suggest results if there are actually
         // extensions listening for input changes.
@@ -250,10 +253,10 @@
       keyword_matches.erase(keyword_matches.begin() + kMaxMatches,
                             keyword_matches.end());
     }
-    for (std::vector<std::wstring>::const_iterator i(keyword_matches.begin());
+    for (std::vector<string16>::const_iterator i(keyword_matches.begin());
          i != keyword_matches.end(); ++i) {
-      matches_.push_back(CreateAutocompleteMatch(model, *i, input,
-                                                 keyword.length(),
+      matches_.push_back(CreateAutocompleteMatch(model, *i,
+                                                 input, keyword.length(),
                                                  remaining_input, -1));
     }
   }
@@ -268,34 +271,36 @@
 
 // static
 bool KeywordProvider::ExtractKeywordFromInput(const AutocompleteInput& input,
-                                              std::wstring* keyword,
-                                              std::wstring* remaining_input) {
+                                              string16* keyword,
+                                              string16* remaining_input) {
   if ((input.type() == AutocompleteInput::INVALID) ||
       (input.type() == AutocompleteInput::FORCED_QUERY))
     return false;
 
   *keyword = TemplateURLModel::CleanUserInputKeyword(
-      SplitKeywordFromInput(input.text(), remaining_input));
+      SplitKeywordFromInput(input.text(), true, remaining_input));
   return !keyword->empty();
 }
 
 // static
-std::wstring KeywordProvider::SplitKeywordFromInput(
-    const std::wstring& input,
-    std::wstring* remaining_input) {
+string16 KeywordProvider::SplitKeywordFromInput(
+    const string16& input,
+    bool trim_leading_whitespace,
+    string16* remaining_input) {
   // Find end of first token.  The AutocompleteController has trimmed leading
   // whitespace, so we need not skip over that.
-  const size_t first_white(input.find_first_of(kWhitespaceWide));
+  const size_t first_white(input.find_first_of(kWhitespaceUTF16));
   DCHECK_NE(0U, first_white);
-  if (first_white == std::wstring::npos)
+  if (first_white == string16::npos)
     return input;  // Only one token provided.
 
   // Set |remaining_input| to everything after the first token.
   DCHECK(remaining_input != NULL);
-  const size_t first_nonwhite(input.find_first_not_of(kWhitespaceWide,
-                                                      first_white));
-  if (first_nonwhite != std::wstring::npos)
-    remaining_input->assign(input.begin() + first_nonwhite, input.end());
+  const size_t remaining_start = trim_leading_whitespace ?
+    input.find_first_not_of(kWhitespaceUTF16, first_white) : first_white + 1;
+
+  if (remaining_start < input.length())
+    remaining_input->assign(input.begin() + remaining_start, input.end());
 
   // Return first token as keyword.
   return input.substr(0, first_white);
@@ -303,7 +308,7 @@
 
 // static
 void KeywordProvider::FillInURLAndContents(
-    const std::wstring& remaining_input,
+    const string16& remaining_input,
     const TemplateURL* element,
     AutocompleteMatch* match) {
   DCHECK(!element->short_name().empty());
@@ -318,10 +323,10 @@
     if (element->url()->SupportsReplacement() &&
         !element->IsExtensionKeyword()) {
       // No query input; return a generic, no-destination placeholder.
-      match->contents.assign(UTF16ToWideHack(
+      match->contents.assign(
           l10n_util::GetStringFUTF16(message_id,
-              WideToUTF16Hack(element->AdjustedShortNameForLocaleDirection()),
-              l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE))));
+              element->AdjustedShortNameForLocaleDirection(),
+              l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)));
       match->contents_class.push_back(
           ACMatchClassification(0, ACMatchClassification::DIM));
     } else {
@@ -339,14 +344,13 @@
     // fixup to make the URL valid if necessary.
     DCHECK(element->url()->SupportsReplacement());
     match->destination_url = GURL(element->url()->ReplaceSearchTerms(
-      *element, remaining_input, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
-      std::wstring()));
+        *element, remaining_input,
+        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
     std::vector<size_t> content_param_offsets;
-    match->contents.assign(UTF16ToWideHack(
-        l10n_util::GetStringFUTF16(message_id,
-                                   WideToUTF16Hack(element->short_name()),
-                                   WideToUTF16Hack(remaining_input),
-                                   &content_param_offsets)));
+    match->contents.assign(l10n_util::GetStringFUTF16(message_id,
+                                                      element->short_name(),
+                                                      remaining_input,
+                                                      &content_param_offsets));
     if (content_param_offsets.size() == 2) {
       AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1],
           remaining_input.length(), match->contents.length(),
@@ -361,27 +365,28 @@
 // static
 int KeywordProvider::CalculateRelevance(AutocompleteInput::Type type,
                                         bool complete,
-                                        bool no_query_text_needed,
+                                        bool supports_replacement,
+                                        bool prefer_keyword,
                                         bool allow_exact_keyword_match) {
   if (!complete)
     return (type == AutocompleteInput::URL) ? 700 : 450;
-  if (!allow_exact_keyword_match)
-    return 1100;
-  if (no_query_text_needed)
+  if (!supports_replacement || (allow_exact_keyword_match && prefer_keyword))
     return 1500;
-  return (type == AutocompleteInput::QUERY) ? 1450 : 1100;
+  return (allow_exact_keyword_match && (type == AutocompleteInput::QUERY)) ?
+      1450 : 1100;
 }
 
 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
     TemplateURLModel* model,
-    const std::wstring& keyword,
+    const string16& keyword,
     const AutocompleteInput& input,
     size_t prefix_length,
-    const std::wstring& remaining_input,
+    const string16& remaining_input,
     int relevance) {
   DCHECK(model);
   // Get keyword data from data store.
-  const TemplateURL* element(model->GetTemplateURLForKeyword(keyword));
+  const TemplateURL* element(
+      model->GetTemplateURLForKeyword(keyword));
   DCHECK(element && element->url());
   const bool supports_replacement = element->url()->SupportsReplacement();
 
@@ -395,7 +400,7 @@
                            // When the user wants keyword matches to take
                            // preference, score them highly regardless of
                            // whether the input provides query text.
-                           input.prefer_keyword() || !supports_replacement,
+                           supports_replacement, input.prefer_keyword(),
                            input.allow_exact_keyword_match());
   }
   AutocompleteMatch result(this, relevance, false,
@@ -410,7 +415,7 @@
   // to the user's input.  Because right now inexact keyword matches can't score
   // more highly than a "what you typed" match from one of the other providers,
   // we just don't bother to do this, and leave inline autocompletion off.
-  result.inline_autocomplete_offset = std::wstring::npos;
+  result.inline_autocomplete_offset = string16::npos;
 
   // Create destination URL and popup entry content by substituting user input
   // into keyword templates.
@@ -422,8 +427,8 @@
 
   // Create popup entry description based on the keyword name.
   if (!element->IsExtensionKeyword()) {
-    result.description.assign(UTF16ToWideHack(l10n_util::GetStringFUTF16(
-        IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION, WideToUTF16Hack(keyword))));
+    result.description.assign(l10n_util::GetStringFUTF16(
+        IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION, keyword));
     string16 keyword_desc(
         l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION));
     AutocompleteMatch::ClassifyLocationInString(
@@ -453,14 +458,15 @@
     case NotificationType::EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED: {
       // It's possible to change the default suggestion while not in an editing
       // session.
-      std::wstring keyword, remaining_input;
+      string16 keyword, remaining_input;
       if (matches_.empty() || current_keyword_extension_id_.empty() ||
           !ExtractKeywordFromInput(input, &keyword, &remaining_input))
         return;
 
-      const TemplateURL* template_url(model->GetTemplateURLForKeyword(keyword));
+      const TemplateURL* template_url(
+          model->GetTemplateURLForKeyword(keyword));
       ApplyDefaultSuggestionForExtensionKeyword(profile_, template_url,
-                                                WideToUTF16(remaining_input),
+                                                remaining_input,
                                                 &matches_[0]);
       listener_->OnProviderUpdate(true);
       return;
@@ -472,7 +478,7 @@
       if (suggestions.request_id != current_input_id_)
         return;  // This is an old result. Just ignore.
 
-      std::wstring keyword, remaining_input;
+      string16 keyword, remaining_input;
       if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) {
         NOTREACHED();
         return;
@@ -488,14 +494,14 @@
         // and subtract 1 for each subsequent suggestion from the extension.
         // We know that |complete| is true, because we wouldn't get results from
         // the extension unless the full keyword had been typed.
-        int first_relevance = CalculateRelevance(input.type(), true,
+        int first_relevance = CalculateRelevance(input.type(), true, true,
             input.prefer_keyword(), input.allow_exact_keyword_match());
         extension_suggest_matches_.push_back(CreateAutocompleteMatch(
             model, keyword, input, keyword.length(),
-            UTF16ToWide(suggestion.content), first_relevance - (i + 1)));
+            suggestion.content, first_relevance - (i + 1)));
 
         AutocompleteMatch* match = &extension_suggest_matches_.back();
-        match->contents.assign(UTF16ToWide(suggestion.description));
+        match->contents.assign(suggestion.description);
         match->contents_class = suggestion.description_styles;
         match->description.clear();
         match->description_class.clear();
diff --git a/chrome/browser/autocomplete/keyword_provider.h b/chrome/browser/autocomplete/keyword_provider.h
index 4a6ad90..6406fb9 100644
--- a/chrome/browser/autocomplete/keyword_provider.h
+++ b/chrome/browser/autocomplete/keyword_provider.h
@@ -58,15 +58,18 @@
   // Returns the replacement string from the user input. The replacement
   // string is the portion of the input that does not contain the keyword.
   // For example, the replacement string for "b blah" is blah.
-  static std::wstring SplitReplacementStringFromInput(
-      const std::wstring& input);
+  // If |trim_leading_whitespace| is true then leading whitespace in
+  // replacement string will be trimmed.
+  static string16 SplitReplacementStringFromInput(
+      const string16& input,
+      bool trim_leading_whitespace);
 
   // Returns the matching substituting keyword for |input|, or NULL if there
   // is no keyword for the specified input.
   static const TemplateURL* GetSubstitutingTemplateURLForInput(
       Profile* profile,
       const AutocompleteInput& input,
-      std::wstring* remaining_input);
+      string16* remaining_input);
 
   // AutocompleteProvider
   virtual void Start(const AutocompleteInput& input, bool minimal_changes);
@@ -84,42 +87,46 @@
   // extract the keyword and remaining string, and uses
   // TemplateURLModel::CleanUserInputKeyword to remove unnecessary characters.
   // In general use this instead of SplitKeywordFromInput.
+  // Leading whitespace in |*remaining_input| will be trimmed.
   static bool ExtractKeywordFromInput(const AutocompleteInput& input,
-                                      std::wstring* keyword,
-                                      std::wstring* remaining_input);
+                                      string16* keyword,
+                                      string16* remaining_input);
 
   // Extracts the next whitespace-delimited token from input and returns it.
   // Sets |remaining_input| to everything after the first token (skipping over
-  // intervening whitespace).
-  static std::wstring SplitKeywordFromInput(const std::wstring& input,
-                                            std::wstring* remaining_input);
+  // the first intervening whitespace).
+  // If |trim_leading_whitespace| is true then leading whitespace in
+  // |*remaining_input| will be trimmed.
+  static string16 SplitKeywordFromInput(const string16& input,
+                                        bool trim_leading_whitespace,
+                                        string16* remaining_input);
 
   // Fills in the "destination_url" and "contents" fields of |match| with the
   // provided user input and keyword data.
   static void FillInURLAndContents(
-      const std::wstring& remaining_input,
+      const string16& remaining_input,
       const TemplateURL* element,
       AutocompleteMatch* match);
 
   // Determines the relevance for some input, given its type, whether the user
-  // typed the complete keyword, and whether the keyword needs query text (true
-  // if the keyword supports replacement and the user isn't in "prefer keyword
-  // matches" mode).
+  // typed the complete keyword, and whether the user is in "prefer keyword
+  // matches" mode, and whether the keyword supports replacement.
   // If |allow_exact_keyword_match| is false, the relevance for complete
-  // keywords is degraded.
+  // keywords that support replacements is degraded.
   static int CalculateRelevance(AutocompleteInput::Type type,
                                 bool complete,
-                                bool no_query_text_needed,
+                                bool support_replacement,
+                                bool prefer_keyword,
                                 bool allow_exact_keyword_match);
 
   // Creates a fully marked-up AutocompleteMatch from the user's input.
   // If |relevance| is negative, calculate a relevance based on heuristics.
   AutocompleteMatch CreateAutocompleteMatch(
       TemplateURLModel* model,
-      const std::wstring& keyword,
+      const string16& keyword,
       const AutocompleteInput& input,
       size_t prefix_length,
-      const std::wstring& remaining_input,
+      const string16& remaining_input,
       int relevance);
 
   void EnterExtensionKeywordMode(const std::string& extension_id);
diff --git a/chrome/browser/autocomplete/keyword_provider_unittest.cc b/chrome/browser/autocomplete/keyword_provider_unittest.cc
index 165662e..5874cca 100644
--- a/chrome/browser/autocomplete/keyword_provider_unittest.cc
+++ b/chrome/browser/autocomplete/keyword_provider_unittest.cc
@@ -1,8 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/keyword_provider.h"
 #include "chrome/browser/search_engines/template_url.h"
@@ -14,7 +15,7 @@
  protected:
   template<class ResultType>
   struct test_data {
-    const std::wstring input;
+    const string16 input;
     const size_t num_results;
     const ResultType output[3];
   };
@@ -37,13 +38,13 @@
 
 void KeywordProviderTest::SetUp() {
   static const TemplateURLModel::Initializer kTestKeywordData[] = {
-    { L"aa", "aa.com?foo=%s", L"aa" },
-    { L"aaaa", "http://aaaa/?aaaa=1&b=%s&c", L"aaaa" },
-    { L"aaaaa", "%s", L"aaaaa" },
-    { L"ab", "bogus URL %s", L"ab" },
-    { L"weasel", "weasel%sweasel", L"weasel" },
-    { L"www", " +%2B?=%sfoo ", L"www" },
-    { L"z", "%s=z", L"z" },
+    { "aa", "aa.com?foo=%s", "aa" },
+    { "aaaa", "http://aaaa/?aaaa=1&b=%s&c", "aaaa" },
+    { "aaaaa", "%s", "aaaaa" },
+    { "ab", "bogus URL %s", "ab" },
+    { "weasel", "weasel%sweasel", "weasel" },
+    { "www", " +%2B?=%sfoo ", "www" },
+    { "z", "%s=z", "z" },
   };
 
   model_.reset(new TemplateURLModel(kTestKeywordData,
@@ -63,13 +64,13 @@
     ResultType AutocompleteMatch::* member) {
   ACMatches matches;
   for (int i = 0; i < num_cases; ++i) {
-    AutocompleteInput input(keyword_cases[i].input, std::wstring(), true,
+    AutocompleteInput input(keyword_cases[i].input, string16(), true,
                             false, true, false);
     kw_provider_->Start(input, false);
     EXPECT_TRUE(kw_provider_->done());
     matches = kw_provider_->matches();
     EXPECT_EQ(keyword_cases[i].num_results, matches.size()) <<
-                L"Input was: " + keyword_cases[i].input;
+                ASCIIToUTF16("Input was: ") + keyword_cases[i].input;
     if (matches.size() == keyword_cases[i].num_results) {
       for (size_t j = 0; j < keyword_cases[i].num_results; ++j) {
         EXPECT_EQ(keyword_cases[i].output[j], matches[j].*member);
@@ -79,61 +80,69 @@
 }
 
 TEST_F(KeywordProviderTest, Edit) {
-  test_data<std::wstring> edit_cases[] = {
+  test_data<string16> edit_cases[] = {
     // Searching for a nonexistent prefix should give nothing.
-    {L"Not Found",       0, {}},
-    {L"aaaaaNot Found",  0, {}},
+    {ASCIIToUTF16("Not Found"),       0, {}},
+    {ASCIIToUTF16("aaaaaNot Found"),  0, {}},
 
     // Check that tokenization only collapses whitespace between first tokens,
     // no-query-input cases have a space appended, and action is not escaped.
-    {L"z foo",           1, {L"z foo"}},
-    {L"z",               1, {L"z "}},
-    {L"z    \t",         1, {L"z "}},
-    {L"z   a   b   c++", 1, {L"z a   b   c++"}},
+    {ASCIIToUTF16("z foo"),           1, {ASCIIToUTF16("z foo")}},
+    {ASCIIToUTF16("z"),               1, {ASCIIToUTF16("z ")}},
+    {ASCIIToUTF16("z    \t"),         1, {ASCIIToUTF16("z ")}},
+    {ASCIIToUTF16("z   a   b   c++"), 1, {ASCIIToUTF16("z a   b   c++")}},
 
     // Matches should be limited to three, and sorted in quality order, not
     // alphabetical.
-    {L"aaa",             2, {L"aaaa ", L"aaaaa "}},
-    {L"a 1 2 3",         3, {L"aa 1 2 3", L"ab 1 2 3", L"aaaa 1 2 3"}},
-    {L"www.a",           3, {L"aa ", L"ab ", L"aaaa "}},
+    {ASCIIToUTF16("aaa"),             2, {ASCIIToUTF16("aaaa "),
+                                          ASCIIToUTF16("aaaaa ")}},
+    {ASCIIToUTF16("a 1 2 3"),         3, {ASCIIToUTF16("aa 1 2 3"),
+                                          ASCIIToUTF16("ab 1 2 3"),
+                                          ASCIIToUTF16("aaaa 1 2 3")}},
+    {ASCIIToUTF16("www.a"),           3, {ASCIIToUTF16("aa "),
+                                          ASCIIToUTF16("ab "),
+                                          ASCIIToUTF16("aaaa ")}},
     // Exact matches should prevent returning inexact matches.
-    {L"aaaa foo",        1, {L"aaaa foo"}},
-    {L"www.aaaa foo",    1, {L"aaaa foo"}},
+    {ASCIIToUTF16("aaaa foo"),        1, {ASCIIToUTF16("aaaa foo")}},
+    {ASCIIToUTF16("www.aaaa foo"),    1, {ASCIIToUTF16("aaaa foo")}},
 
     // Clean up keyword input properly.  "http" and "https" are the only
     // allowed schemes.
-    {L"www",             1, {L"www "}},
-    {L"www.",            0, {}},
-    {L"www.w w",         2, {L"www w", L"weasel w"}},
-    {L"http://www",      1, {L"www "}},
-    {L"http://www.",     0, {}},
-    {L"ftp: blah",       0, {}},
-    {L"mailto:z",        0, {}},
-    {L"ftp://z",         0, {}},
-    {L"https://z",       1, {L"z "}},
+    {ASCIIToUTF16("www"),             1, {ASCIIToUTF16("www ")}},
+    {ASCIIToUTF16("www."),            0, {}},
+    {ASCIIToUTF16("www.w w"),         2, {ASCIIToUTF16("www w"),
+                                          ASCIIToUTF16("weasel w")}},
+    {ASCIIToUTF16("http://www"),      1, {ASCIIToUTF16("www ")}},
+    {ASCIIToUTF16("http://www."),     0, {}},
+    {ASCIIToUTF16("ftp: blah"),       0, {}},
+    {ASCIIToUTF16("mailto:z"),        0, {}},
+    {ASCIIToUTF16("ftp://z"),         0, {}},
+    {ASCIIToUTF16("https://z"),       1, {ASCIIToUTF16("z ")}},
   };
 
-  RunTest<std::wstring>(edit_cases, arraysize(edit_cases),
-                        &AutocompleteMatch::fill_into_edit);
+  RunTest<string16>(edit_cases, arraysize(edit_cases),
+                    &AutocompleteMatch::fill_into_edit);
 }
 
 TEST_F(KeywordProviderTest, URL) {
   test_data<GURL> url_cases[] = {
     // No query input -> empty destination URL.
-    {L"z",               1, {GURL()}},
-    {L"z    \t",         1, {GURL()}},
+    {ASCIIToUTF16("z"),               1, {GURL()}},
+    {ASCIIToUTF16("z    \t"),         1, {GURL()}},
 
     // Check that tokenization only collapses whitespace between first tokens
     // and query input, but not rest of URL, is escaped.
-    {L"z   a   b   c++", 1, {GURL("a+++b+++c%2B%2B=z")}},
-    {L"www.www www",     1, {GURL(" +%2B?=wwwfoo ")}},
+    {ASCIIToUTF16("z   a   b   c++"), 1, {GURL("a+++b+++c%2B%2B=z")}},
+    {ASCIIToUTF16("www.www www"),     1, {GURL(" +%2B?=wwwfoo ")}},
 
     // Substitution should work with various locations of the "%s".
-    {L"aaa 1a2b",        2, {GURL("http://aaaa/?aaaa=1&b=1a2b&c"),
-                             GURL("1a2b")}},
-    {L"a 1 2 3",         3, {GURL("aa.com?foo=1+2+3"), GURL("bogus URL 1+2+3"),
-                             GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}},
-    {L"www.w w",         2, {GURL(" +%2B?=wfoo "), GURL("weaselwweasel")}},
+    {ASCIIToUTF16("aaa 1a2b"),        2, {GURL("http://aaaa/?aaaa=1&b=1a2b&c"),
+                                          GURL("1a2b")}},
+    {ASCIIToUTF16("a 1 2 3"),         3, {GURL("aa.com?foo=1+2+3"),
+                                          GURL("bogus URL 1+2+3"),
+                                        GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}},
+    {ASCIIToUTF16("www.w w"),         2, {GURL(" +%2B?=wfoo "),
+                                          GURL("weaselwweasel")}},
   };
 
   RunTest<GURL>(url_cases, arraysize(url_cases),
@@ -141,60 +150,67 @@
 }
 
 TEST_F(KeywordProviderTest, Contents) {
-  test_data<std::wstring> contents_cases[] = {
+  test_data<string16> contents_cases[] = {
     // No query input -> substitute "<enter query>" into contents.
-    {L"z",               1, {L"Search z for <enter query>"}},
-    {L"z    \t",         1, {L"Search z for <enter query>"}},
+    {ASCIIToUTF16("z"),               1,
+        {ASCIIToUTF16("Search z for <enter query>")}},
+    {ASCIIToUTF16("z    \t"),         1,
+        {ASCIIToUTF16("Search z for <enter query>")}},
 
     // Check that tokenization only collapses whitespace between first tokens
     // and contents are not escaped or unescaped.
-    {L"z   a   b   c++", 1, {L"Search z for a   b   c++"}},
-    {L"www.www www",     1, {L"Search www for www"}},
+    {ASCIIToUTF16("z   a   b   c++"), 1,
+        {ASCIIToUTF16("Search z for a   b   c++")}},
+    {ASCIIToUTF16("www.www www"),     1, {ASCIIToUTF16("Search www for www")}},
 
     // Substitution should work with various locations of the "%s".
-    {L"aaa",             2, {L"Search aaaa for <enter query>",
-                             L"Search aaaaa for <enter query>"}},
-    {L"a 1 2 3",         3, {L"Search aa for 1 2 3", L"Search ab for 1 2 3",
-                             L"Search aaaa for 1 2 3"}},
-    {L"www.w w",         2, {L"Search www for w", L"Search weasel for w"}},
+    {ASCIIToUTF16("aaa"),             2,
+        {ASCIIToUTF16("Search aaaa for <enter query>"),
+         ASCIIToUTF16("Search aaaaa for <enter query>")}},
+    {ASCIIToUTF16("a 1 2 3"),         3, {ASCIIToUTF16("Search aa for 1 2 3"),
+                                          ASCIIToUTF16("Search ab for 1 2 3"),
+                                        ASCIIToUTF16("Search aaaa for 1 2 3")}},
+    {ASCIIToUTF16("www.w w"),         2, {ASCIIToUTF16("Search www for w"),
+        ASCIIToUTF16("Search weasel for w")}},
   };
 
-  RunTest<std::wstring>(contents_cases, arraysize(contents_cases),
+  RunTest<string16>(contents_cases, arraysize(contents_cases),
                         &AutocompleteMatch::contents);
 }
 
 TEST_F(KeywordProviderTest, Description) {
-  test_data<std::wstring> description_cases[] = {
+  test_data<string16> description_cases[] = {
     // Whole keyword should be returned for both exact and inexact matches.
-    {L"z foo",           1, {L"(Keyword: z)"}},
-    {L"a foo",           3, {L"(Keyword: aa)", L"(Keyword: ab)",
-                             L"(Keyword: aaaa)"}},
-    {L"ftp://www.www w", 0, {}},
-    {L"http://www.ab w", 1, {L"(Keyword: ab)"}},
+    {ASCIIToUTF16("z foo"),           1, {ASCIIToUTF16("(Keyword: z)")}},
+    {ASCIIToUTF16("a foo"),           3, {ASCIIToUTF16("(Keyword: aa)"),
+                                          ASCIIToUTF16("(Keyword: ab)"),
+                                          ASCIIToUTF16("(Keyword: aaaa)")}},
+    {ASCIIToUTF16("ftp://www.www w"), 0, {}},
+    {ASCIIToUTF16("http://www.ab w"), 1, {ASCIIToUTF16("(Keyword: ab)")}},
 
     // Keyword should be returned regardless of query input.
-    {L"z",               1, {L"(Keyword: z)"}},
-    {L"z    \t",         1, {L"(Keyword: z)"}},
-    {L"z   a   b   c++", 1, {L"(Keyword: z)"}},
+    {ASCIIToUTF16("z"),               1, {ASCIIToUTF16("(Keyword: z)")}},
+    {ASCIIToUTF16("z    \t"),         1, {ASCIIToUTF16("(Keyword: z)")}},
+    {ASCIIToUTF16("z   a   b   c++"), 1, {ASCIIToUTF16("(Keyword: z)")}},
   };
 
-  RunTest<std::wstring>(description_cases, arraysize(description_cases),
+  RunTest<string16>(description_cases, arraysize(description_cases),
                         &AutocompleteMatch::description);
 }
 
 TEST_F(KeywordProviderTest, AddKeyword) {
   TemplateURL* template_url = new TemplateURL();
-  std::wstring keyword(L"foo");
+  string16 keyword(ASCIIToUTF16("foo"));
   std::string url("http://www.google.com/foo?q={searchTerms}");
   template_url->SetURL(url, 0, 0);
   template_url->set_keyword(keyword);
-  template_url->set_short_name(L"Test");
+  template_url->set_short_name(ASCIIToUTF16("Test"));
   model_->Add(template_url);
   ASSERT_TRUE(template_url == model_->GetTemplateURLForKeyword(keyword));
 }
 
 TEST_F(KeywordProviderTest, RemoveKeyword) {
-  std::wstring url(L"http://aaaa/?aaaa=1&b={searchTerms}&c");
-  model_->Remove(model_->GetTemplateURLForKeyword(L"aaaa"));
-  ASSERT_TRUE(model_->GetTemplateURLForKeyword(L"aaaa") == NULL);
+  string16 url(ASCIIToUTF16("http://aaaa/?aaaa=1&b={searchTerms}&c"));
+  model_->Remove(model_->GetTemplateURLForKeyword(ASCIIToUTF16("aaaa")));
+  ASSERT_TRUE(model_->GetTemplateURLForKeyword(ASCIIToUTF16("aaaa")) == NULL);
 }
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index 4c9da21..ed308bb 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <cmath>
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/i18n/icu_string_conversions.h"
 #include "base/message_loop.h"
@@ -31,6 +30,7 @@
 #include "net/base/escape.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request_status.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -63,8 +63,8 @@
       instant_finalized_(false) {
 }
 
-void SearchProvider::FinalizeInstantQuery(const std::wstring& input_text,
-                                          const std::wstring& suggest_text) {
+void SearchProvider::FinalizeInstantQuery(const string16& input_text,
+                                          const string16& suggest_text) {
   if (done_ || instant_finalized_)
     return;
 
@@ -78,11 +78,13 @@
     return;
   }
 
-  std::wstring adjusted_input_text(input_text);
+  default_provider_suggest_text_ = suggest_text;
+
+  string16 adjusted_input_text(input_text);
   AutocompleteInput::RemoveForcedQueryStringIfNecessary(input_.type(),
                                                         &adjusted_input_text);
 
-  const std::wstring text = adjusted_input_text + suggest_text;
+  const string16 text = adjusted_input_text + suggest_text;
   // Remove any matches that are identical to |text|. We don't use the
   // destination_url for comparison as it varies depending upon the index passed
   // to TemplateURL::ReplaceSearchTerms.
@@ -162,9 +164,15 @@
 
   // If we're still running an old query but have since changed the query text
   // or the providers, abort the query.
-  if (!done_ && (!minimal_changes ||
-                 !providers_.equals(default_provider, keyword_provider))) {
-    Stop();
+  if (!minimal_changes ||
+      !providers_.equals(default_provider, keyword_provider)) {
+    if (done_)
+      default_provider_suggest_text_.clear();
+    else
+      Stop();
+  } else if (minimal_changes &&
+             (input_.original_text() != input.original_text())) {
+    default_provider_suggest_text_.clear();
   }
 
   providers_.Set(default_provider, keyword_provider);
@@ -175,8 +183,7 @@
     if (default_provider) {
       AutocompleteMatch match;
       match.provider = this;
-      match.contents.assign(UTF16ToWideHack(
-          l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)));
+      match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE));
       match.contents_class.push_back(
           ACMatchClassification(0, ACMatchClassification::NONE));
       matches_.push_back(match);
@@ -218,11 +225,12 @@
 void SearchProvider::Stop() {
   StopSuggest();
   done_ = true;
+  default_provider_suggest_text_.clear();
 }
 
 void SearchProvider::OnURLFetchComplete(const URLFetcher* source,
                                         const GURL& url,
-                                        const URLRequestStatus& status,
+                                        const net::URLRequestStatus& status,
                                         int response_code,
                                         const ResponseCookies& cookie,
                                         const std::string& data) {
@@ -238,12 +246,12 @@
   if (response_headers) {
     std::string charset;
     if (response_headers->GetCharset(&charset)) {
-      std::wstring wide_data;
+      string16 data_16;
       // TODO(jungshik): Switch to CodePageToUTF8 after it's added.
-      if (base::CodepageToWide(data, charset.c_str(),
-                               base::OnStringConversionError::FAIL,
-                               &wide_data))
-        json_data = WideToUTF8(wide_data);
+      if (base::CodepageToUTF16(data, charset.c_str(),
+                                base::OnStringConversionError::FAIL,
+                                &data_16))
+        json_data = UTF16ToUTF8(data_16);
     }
   }
 
@@ -255,7 +263,7 @@
     JSONStringValueSerializer deserializer(json_data);
     deserializer.set_allow_trailing_comma(true);
     scoped_ptr<Value> root_val(deserializer.Deserialize(NULL, NULL));
-    const std::wstring& input_text =
+    const string16& input_text =
         is_keyword_results ? keyword_input_text_ : input_.text();
     have_suggest_results_ =
         root_val.get() &&
@@ -290,14 +298,14 @@
   if (providers_.valid_keyword_provider()) {
     url_db->GetMostRecentKeywordSearchTerms(
         providers_.keyword_provider().id(),
-        WideToUTF16(keyword_input_text_),
+        keyword_input_text_,
         static_cast<int>(kMaxMatches),
         &keyword_history_results_);
   }
   if (providers_.valid_default_provider()) {
     url_db->GetMostRecentKeywordSearchTerms(
         providers_.default_provider().id(),
-        WideToUTF16(input_.text()),
+        input_.text(),
         static_cast<int>(kMaxMatches),
         &default_history_results_);
   }
@@ -367,8 +375,9 @@
   // probably a URL that's being entered and happens to currently be invalid --
   // in which case we again want to run our checks below.  Other QUERY cases are
   // less likely to be URLs and thus we assume we're OK.
-  if ((input_.scheme() != L"http") && (input_.scheme() != L"https") &&
-      (input_.scheme() != L"ftp"))
+  if (!LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpScheme) &&
+      !LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpsScheme) &&
+      !LowerCaseEqualsASCII(input_.scheme(), chrome::kFtpScheme))
     return (input_.type() == AutocompleteInput::QUERY);
 
   // Don't send URLs with usernames, queries or refs.  Some of these are
@@ -385,7 +394,8 @@
   // Don't send anything for https except the hostname.  Hostnames are OK
   // because they are visible when the TCP connection is established, but the
   // specific path may reveal private information.
-  if ((input_.scheme() == L"https") && parts.path.is_nonempty())
+  if (LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpsScheme) &&
+      parts.path.is_nonempty())
     return false;
 
   return true;
@@ -406,13 +416,13 @@
 
 URLFetcher* SearchProvider::CreateSuggestFetcher(int id,
                                                  const TemplateURL& provider,
-                                                 const std::wstring& text) {
+                                                 const string16& text) {
   const TemplateURLRef* const suggestions_url = provider.suggestions_url();
   DCHECK(suggestions_url->SupportsReplacement());
   URLFetcher* fetcher = URLFetcher::Create(id,
       GURL(suggestions_url->ReplaceSearchTerms(
-           provider, text, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
-           std::wstring())),
+           provider, text,
+           TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())),
       URLFetcher::GET, this);
   fetcher->set_request_context(profile_->GetRequestContext());
   fetcher->Start();
@@ -421,7 +431,7 @@
 
 bool SearchProvider::ParseSuggestResults(Value* root_val,
                                          bool is_keyword,
-                                         const std::wstring& input_text,
+                                         const string16& input_text,
                                          SuggestResults* suggest_results) {
   if (!root_val->IsType(Value::TYPE_LIST))
     return false;
@@ -432,7 +442,7 @@
   Value* result_val;
   if ((root_list->GetSize() < 2) || !root_list->Get(0, &query_val) ||
       !query_val->GetAsString(&query_str) ||
-      (query_str != WideToUTF16Hack(input_text)) ||
+      (query_str != input_text) ||
       !root_list->Get(1, &result_val) || !result_val->IsType(Value::TYPE_LIST))
     return false;
 
@@ -497,15 +507,14 @@
         GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str),
                                                 std::string()));
         if (result_url.is_valid()) {
-          navigation_results.push_back(NavigationResult(result_url,
-              UTF16ToWideHack(site_name)));
+          navigation_results.push_back(NavigationResult(result_url, site_name));
         }
       }
     } else {
       // TODO(kochi): Currently we treat a calculator result as a query, but it
       // is better to have better presentation for caluculator results.
       if (suggest_results->size() < kMaxMatches)
-        suggest_results->push_back(UTF16ToWideHack(suggestion_str));
+        suggest_results->push_back(suggestion_str);
     }
   }
 
@@ -531,6 +540,13 @@
                   AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
                   did_not_accept_default_suggestion, false,
                   input_.initial_prevent_inline_autocomplete(), &map);
+    if (!default_provider_suggest_text_.empty()) {
+      AddMatchToMap(input_.text() + default_provider_suggest_text_,
+                    input_.text(), CalculateRelevanceForWhatYouTyped() + 1,
+                    AutocompleteMatch::SEARCH_SUGGEST,
+                    did_not_accept_default_suggestion, false,
+                    input_.initial_prevent_inline_autocomplete(), &map);
+    }
   }
 
   AddHistoryResultsToMap(keyword_history_results_, true,
@@ -599,7 +615,7 @@
     if (i != results.begin() && relevance >= last_relevance)
       relevance = last_relevance - 1;
     last_relevance = relevance;
-    AddMatchToMap(UTF16ToWide(i->term),
+    AddMatchToMap(i->term,
                   is_keyword ? keyword_input_text_ : input_.text(),
                   relevance,
                   AutocompleteMatch::SEARCH_HISTORY, did_not_accept_suggestion,
@@ -704,8 +720,8 @@
       static_cast<int>(num_results - 1 - result_number);
 }
 
-void SearchProvider::AddMatchToMap(const std::wstring& query_string,
-                                   const std::wstring& input_text,
+void SearchProvider::AddMatchToMap(const string16& query_string,
+                                   const string16& input_text,
                                    int relevance,
                                    AutocompleteMatch::Type type,
                                    int accepted_suggestion,
@@ -722,7 +738,7 @@
   // "youtube", so we'll bold the "tube" section: you*tube*.
   if (input_text != query_string) {
     size_t input_position = match.contents.find(input_text);
-    if (input_position == std::wstring::npos) {
+    if (input_position == string16::npos) {
       // The input text is not a substring of the query string, e.g. input
       // text is "slasdot" and the query string is "slashdot", so we bold the
       // whole thing.
@@ -761,11 +777,12 @@
   // suggestion, non-Search results will suddenly appear.
   size_t search_start = 0;
   if (input_.type() == AutocompleteInput::FORCED_QUERY) {
-    match.fill_into_edit.assign(L"?");
+    match.fill_into_edit.assign(ASCIIToUTF16("?"));
     ++search_start;
   }
   if (is_keyword) {
-    match.fill_into_edit.append(providers_.keyword_provider().keyword() + L" ");
+    match.fill_into_edit.append(
+        providers_.keyword_provider().keyword() + char16(' '));
     match.template_url = &providers_.keyword_provider();
   }
   match.fill_into_edit.append(query_string);
@@ -791,8 +808,8 @@
   // |map|, replace it if |match| is more relevant.
   // NOTE: Keep this ToLower() call in sync with url_database.cc.
   const std::pair<MatchMap::iterator, bool> i = map->insert(
-      std::pair<std::wstring, AutocompleteMatch>(
-      UTF16ToWide(l10n_util::ToLower(WideToUTF16(query_string))), match));
+      std::pair<string16, AutocompleteMatch>(
+          l10n_util::ToLower(query_string), match));
   // NOTE: We purposefully do a direct relevance comparison here instead of
   // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
   // first" rather than "items alphabetically first" when the scores are equal.
@@ -809,7 +826,7 @@
     const NavigationResult& navigation,
     int relevance,
     bool is_keyword) {
-  const std::wstring& input_text =
+  const string16& input_text =
       is_keyword ? keyword_input_text_ : input_.text();
   AutocompleteMatch match(this, relevance, false,
                           AutocompleteMatch::NAVSUGGEST);
@@ -829,7 +846,7 @@
   // values preserve that property.  Otherwise, if the user starts editing a
   // suggestion, non-Search results will suddenly appear.
   if (input_.type() == AutocompleteInput::FORCED_QUERY)
-    match.fill_into_edit.assign(L"?");
+    match.fill_into_edit.assign(ASCIIToUTF16("?"));
   match.fill_into_edit.append(
       AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url,
                                                               match.contents));
@@ -856,11 +873,10 @@
       case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
       case AutocompleteMatch::SEARCH_HISTORY:
       case AutocompleteMatch::SEARCH_SUGGEST:
-        match.description.assign(
-            UTF16ToWideHack(l10n_util::GetStringFUTF16(
-                IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION,
-                WideToUTF16Hack(providers_.default_provider().
-                                AdjustedShortNameForLocaleDirection()))));
+        match.description.assign(l10n_util::GetStringFUTF16(
+            IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION,
+            providers_.default_provider().
+                AdjustedShortNameForLocaleDirection()));
         match.description_class.push_back(
             ACMatchClassification(0, ACMatchClassification::DIM));
         // Only the first search match gets a description.
diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h
index 9b83c3d..f25e9c8 100644
--- a/chrome/browser/autocomplete/search_provider.h
+++ b/chrome/browser/autocomplete/search_provider.h
@@ -59,8 +59,8 @@
   //
   // This method also marks the search provider as no longer needing to wait for
   // the instant result.
-  void FinalizeInstantQuery(const std::wstring& input_text,
-                            const std::wstring& suggest_text);
+  void FinalizeInstantQuery(const string16& input_text,
+                            const string16& suggest_text);
 
   // AutocompleteProvider
   virtual void Start(const AutocompleteInput& input,
@@ -152,7 +152,7 @@
   };
 
   struct NavigationResult {
-    NavigationResult(const GURL& url, const std::wstring& site_name)
+    NavigationResult(const GURL& url, const string16& site_name)
         : url(url),
           site_name(site_name) {
     }
@@ -161,13 +161,13 @@
     GURL url;
 
     // Name for the site.
-    std::wstring site_name;
+    string16 site_name;
   };
 
-  typedef std::vector<std::wstring> SuggestResults;
+  typedef std::vector<string16> SuggestResults;
   typedef std::vector<NavigationResult> NavigationResults;
   typedef std::vector<history::KeywordSearchTermVisit> HistoryResults;
-  typedef std::map<std::wstring, AutocompleteMatch> MatchMap;
+  typedef std::map<string16, AutocompleteMatch> MatchMap;
 
   // Called when timer_ expires.
   void Run();
@@ -194,13 +194,13 @@
   // TemplateURL. Ownership of the returned URLFetchet passes to the caller.
   URLFetcher* CreateSuggestFetcher(int id,
                                    const TemplateURL& provider,
-                                   const std::wstring& text);
+                                   const string16& text);
 
   // Parses the results from the Suggest server and stores up to kMaxMatches of
   // them in server_results_.  Returns whether parsing succeeded.
   bool ParseSuggestResults(Value* root_val,
                            bool is_keyword,
-                           const std::wstring& input_text,
+                           const string16& input_text,
                            SuggestResults* suggest_results);
 
   // Converts the parsed server results in server_results_ to a set of
@@ -251,8 +251,8 @@
   // Creates an AutocompleteMatch for "Search <engine> for |query_string|" with
   // the supplied relevance.  Adds this match to |map|; if such a match already
   // exists, whichever one has lower relevance is eliminated.
-  void AddMatchToMap(const std::wstring& query_string,
-                     const std::wstring& input_text,
+  void AddMatchToMap(const string16& query_string,
+                     const string16& input_text,
                      int relevance,
                      AutocompleteMatch::Type type,
                      int accepted_suggestion,
@@ -282,7 +282,7 @@
   AutocompleteInput input_;
 
   // Input text when searching against the keyword provider.
-  std::wstring keyword_input_text_;
+  string16 keyword_input_text_;
 
   // Searches in the user's history that begin with the input text.
   HistoryResults keyword_history_results_;
@@ -317,6 +317,9 @@
   // Has FinalizeInstantQuery been invoked since the last |Start|?
   bool instant_finalized_;
 
+  // The |suggest_text| parameter passed to FinalizeInstantQuery.
+  string16 default_provider_suggest_text_;
+
   DISALLOW_COPY_AND_ASSIGN(SearchProvider);
 };
 
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index 7120a08..0d25649 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -61,7 +61,8 @@
 
   // Invokes Start on provider_, then runs all pending tasks.
   void QueryForInput(const string16& text,
-                     bool prevent_inline_autocomplete);
+                     bool prevent_inline_autocomplete,
+                     bool minimal_changes);
 
   // Notifies the URLFetcher for the suggest query corresponding to the default
   // search provider that it's done.
@@ -116,7 +117,7 @@
   HistoryService* history =
       profile_.GetHistoryService(Profile::EXPLICIT_ACCESS);
   term1_url_ = GURL(default_t_url_->url()->ReplaceSearchTerms(
-      *default_t_url_, UTF16ToWide(term1_), 0, std::wstring()));
+      *default_t_url_, term1_, 0, string16()));
   history->AddPageWithDetails(term1_url_, string16(), 1, 1,
                               base::Time::Now(), false,
                               history::SOURCE_BROWSED);
@@ -125,7 +126,7 @@
 
   // Create another TemplateURL.
   keyword_t_url_ = new TemplateURL();
-  keyword_t_url_->set_keyword(L"k");
+  keyword_t_url_->set_keyword(ASCIIToUTF16("k"));
   keyword_t_url_->SetURL("http://keyword/{searchTerms}", 0, 0);
   keyword_t_url_->SetSuggestionsURL("http://suggest_keyword/{searchTerms}", 0,
                                     0);
@@ -134,7 +135,7 @@
 
   // Add a page and search term for keyword_t_url_.
   keyword_url_ = GURL(keyword_t_url_->url()->ReplaceSearchTerms(
-      *keyword_t_url_, UTF16ToWide(keyword_term_), 0, std::wstring()));
+      *keyword_t_url_, keyword_term_, 0, string16()));
   history->AddPageWithDetails(keyword_url_, string16(), 1, 1,
                               base::Time::Now(), false,
                               history::SOURCE_BROWSED);
@@ -171,11 +172,12 @@
 }
 
 void SearchProviderTest::QueryForInput(const string16& text,
-                                       bool prevent_inline_autocomplete) {
+                                       bool prevent_inline_autocomplete,
+                                       bool minimal_changes) {
   // Start a query.
-  AutocompleteInput input(UTF16ToWide(text), std::wstring(),
-                          prevent_inline_autocomplete, false, true, false);
-  provider_->Start(input, false);
+  AutocompleteInput input(text, string16(), prevent_inline_autocomplete,
+                          false, true, false);
+  provider_->Start(input, minimal_changes);
 
   // RunAllPending so that the task scheduled by SearchProvider to create the
   // URLFetchers runs.
@@ -208,7 +210,7 @@
 
   // Tell the SearchProvider the default suggest query is done.
   default_fetcher->delegate()->OnURLFetchComplete(
-      default_fetcher, GURL(), URLRequestStatus(), 200, ResponseCookies(),
+      default_fetcher, GURL(), net::URLRequestStatus(), 200, ResponseCookies(),
       std::string());
 }
 
@@ -218,7 +220,7 @@
 // created for the default provider suggest results.
 TEST_F(SearchProviderTest, QueryDefaultProvider) {
   string16 term = term1_.substr(0, term1_.size() - 1);
-  QueryForInput(term, false);
+  QueryForInput(term, false, false);
 
   // Make sure the default providers suggest service was queried.
   TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
@@ -227,13 +229,12 @@
 
   // And the URL matches what we expected.
   GURL expected_url = GURL(default_t_url_->suggestions_url()->
-      ReplaceSearchTerms(*default_t_url_, UTF16ToWide(term),
-      0, std::wstring()));
+      ReplaceSearchTerms(*default_t_url_, term, 0, string16()));
   ASSERT_TRUE(fetcher->original_url() == expected_url);
 
   // Tell the SearchProvider the suggest query is done.
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, GURL(), URLRequestStatus(), 200, ResponseCookies(),
+      fetcher, GURL(), net::URLRequestStatus(), 200, ResponseCookies(),
       std::string());
   fetcher = NULL;
 
@@ -248,7 +249,7 @@
   EXPECT_FALSE(term1_match.description.empty());
 
   GURL what_you_typed_url = GURL(default_t_url_->url()->ReplaceSearchTerms(
-      *default_t_url_, UTF16ToWide(term), 0, std::wstring()));
+      *default_t_url_, term, 0, string16()));
   AutocompleteMatch what_you_typed_match =
       FindMatchWithDestination(what_you_typed_url);
   EXPECT_TRUE(!what_you_typed_match.destination_url.is_empty());
@@ -260,7 +261,7 @@
 
 TEST_F(SearchProviderTest, HonorPreventInlineAutocomplete) {
   string16 term = term1_.substr(0, term1_.size() - 1);
-  QueryForInput(term, true);
+  QueryForInput(term, true, false);
 
   ASSERT_FALSE(provider_->matches().empty());
   ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
@@ -271,8 +272,8 @@
 // is queried as well as URLFetchers getting created.
 TEST_F(SearchProviderTest, QueryKeywordProvider) {
   string16 term = keyword_term_.substr(0, keyword_term_.size() - 1);
-  QueryForInput(WideToUTF16(keyword_t_url_->keyword()) +
-                UTF8ToUTF16(" ") + term, false);
+  QueryForInput(keyword_t_url_->keyword() + UTF8ToUTF16(" ") + term, false,
+                false);
 
   // Make sure the default providers suggest service was queried.
   TestURLFetcher* default_fetcher = test_factory_.GetFetcherByID(
@@ -281,7 +282,7 @@
 
   // Tell the SearchProvider the default suggest query is done.
   default_fetcher->delegate()->OnURLFetchComplete(
-      default_fetcher, GURL(), URLRequestStatus(), 200, ResponseCookies(),
+      default_fetcher, GURL(), net::URLRequestStatus(), 200, ResponseCookies(),
       std::string());
   default_fetcher = NULL;
 
@@ -292,13 +293,12 @@
 
   // And the URL matches what we expected.
   GURL expected_url = GURL(keyword_t_url_->suggestions_url()->
-      ReplaceSearchTerms(*keyword_t_url_, UTF16ToWide(term), 0,
-      std::wstring()));
+      ReplaceSearchTerms(*keyword_t_url_, term, 0, string16()));
   ASSERT_TRUE(keyword_fetcher->original_url() == expected_url);
 
   // Tell the SearchProvider the keyword suggest query is done.
   keyword_fetcher->delegate()->OnURLFetchComplete(
-      keyword_fetcher, GURL(), URLRequestStatus(), 200, ResponseCookies(),
+      keyword_fetcher, GURL(), net::URLRequestStatus(), 200, ResponseCookies(),
       std::string());
   keyword_fetcher = NULL;
 
@@ -314,7 +314,7 @@
   EXPECT_TRUE(match.template_url);
 
   // The fill into edit should contain the keyword.
-  EXPECT_EQ(keyword_t_url_->keyword() + L" " + UTF16ToWide(keyword_term_),
+  EXPECT_EQ(keyword_t_url_->keyword() + char16(' ') + keyword_term_,
             match.fill_into_edit);
 }
 
@@ -336,7 +336,7 @@
   };
 
   for (size_t i = 0; i < arraysize(inputs); ++i) {
-    QueryForInput(ASCIIToUTF16(inputs[i]), false);
+    QueryForInput(ASCIIToUTF16(inputs[i]), false, false);
     // Make sure the default providers suggest service was not queried.
     ASSERT_TRUE(test_factory_.GetFetcherByID(
         SearchProvider::kDefaultProviderURLFetcherID) == NULL);
@@ -350,7 +350,7 @@
   PrefService* service = profile_.GetPrefs();
   service->SetBoolean(prefs::kInstantEnabled, true);
 
-  QueryForInput(ASCIIToUTF16("foo"), false);
+  QueryForInput(ASCIIToUTF16("foo"), false, false);
 
   // Wait until history and the suggest query complete.
   profile_.BlockUntilHistoryProcessesPendingRequests();
@@ -361,7 +361,7 @@
   EXPECT_FALSE(provider_->done());
 
   // Tell the provider instant is done.
-  provider_->FinalizeInstantQuery(L"foo", L"bar");
+  provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
 
   // The provider should now be done.
   EXPECT_TRUE(provider_->done());
@@ -370,7 +370,7 @@
   // 'foobar'.
   EXPECT_EQ(2u, provider_->matches().size());
   GURL instant_url = GURL(default_t_url_->url()->ReplaceSearchTerms(
-      *default_t_url_, L"foobar", 0, std::wstring()));
+      *default_t_url_, ASCIIToUTF16("foobar"), 0, string16()));
   AutocompleteMatch instant_match = FindMatchWithDestination(instant_url);
   EXPECT_TRUE(!instant_match.destination_url.is_empty());
 
@@ -379,7 +379,7 @@
 
   // Make sure the what you typed match has no description.
   GURL what_you_typed_url = GURL(default_t_url_->url()->ReplaceSearchTerms(
-      *default_t_url_, L"foo", 0, std::wstring()));
+      *default_t_url_, ASCIIToUTF16("foo"), 0, string16()));
   AutocompleteMatch what_you_typed_match =
       FindMatchWithDestination(what_you_typed_url);
   EXPECT_TRUE(!what_you_typed_match.destination_url.is_empty());
@@ -388,3 +388,66 @@
   // The instant search should be more relevant.
   EXPECT_GT(instant_match.relevance, what_you_typed_match.relevance);
 }
+
+// Make sure that if FinalizeInstantQuery is invoked before suggest results
+// return, the suggest text from FinalizeInstantQuery is remembered.
+TEST_F(SearchProviderTest, RememberInstantQuery) {
+  PrefService* service = profile_.GetPrefs();
+  service->SetBoolean(prefs::kInstantEnabled, true);
+
+  QueryForInput(ASCIIToUTF16("foo"), false, false);
+
+  // Finalize the instant query immediately.
+  provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
+
+  // There should be two matches, one for what you typed, the other for
+  // 'foobar'.
+  EXPECT_EQ(2u, provider_->matches().size());
+  GURL instant_url = GURL(default_t_url_->url()->ReplaceSearchTerms(
+      *default_t_url_, ASCIIToUTF16("foobar"), 0, string16()));
+  AutocompleteMatch instant_match = FindMatchWithDestination(instant_url);
+  EXPECT_FALSE(instant_match.destination_url.is_empty());
+
+  // Wait until history and the suggest query complete.
+  profile_.BlockUntilHistoryProcessesPendingRequests();
+  ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
+
+  // Provider should be done.
+  EXPECT_TRUE(provider_->done());
+
+  // There should be two matches, one for what you typed, the other for
+  // 'foobar'.
+  EXPECT_EQ(2u, provider_->matches().size());
+  instant_match = FindMatchWithDestination(instant_url);
+  EXPECT_FALSE(instant_match.destination_url.is_empty());
+
+  // And the 'foobar' match should have a description.
+  EXPECT_FALSE(instant_match.description.empty());
+}
+
+// Make sure that if trailing whitespace is added to the text supplied to
+// AutocompleteInput the default suggest text is cleared.
+TEST_F(SearchProviderTest, DifferingText) {
+  PrefService* service = profile_.GetPrefs();
+  service->SetBoolean(prefs::kInstantEnabled, true);
+
+  QueryForInput(ASCIIToUTF16("foo"), false, false);
+
+  // Wait until history and the suggest query complete.
+  profile_.BlockUntilHistoryProcessesPendingRequests();
+  ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
+
+  // Finalize the instant query immediately.
+  provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
+
+  // Query with input that ends up getting trimmed to be the same as was
+  // originally supplied.
+  QueryForInput(ASCIIToUTF16("foo "), false, true);
+
+  // There should only one match, for what you typed.
+  EXPECT_EQ(1u, provider_->matches().size());
+  GURL instant_url = GURL(default_t_url_->url()->ReplaceSearchTerms(
+      *default_t_url_, ASCIIToUTF16("foo"), 0, string16()));
+  AutocompleteMatch instant_match = FindMatchWithDestination(instant_url);
+  EXPECT_FALSE(instant_match.destination_url.is_empty());
+}
diff --git a/chrome/browser/autocomplete_history_manager.cc b/chrome/browser/autocomplete_history_manager.cc
index 4e93aa6..2acdcfc 100644
--- a/chrome/browser/autocomplete_history_manager.cc
+++ b/chrome/browser/autocomplete_history_manager.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/autofill_messages.h"
 #include "chrome/common/pref_names.h"
 #include "webkit/glue/form_data.h"
 
@@ -72,16 +73,13 @@
 }  // namespace
 
 AutocompleteHistoryManager::AutocompleteHistoryManager(
-    TabContents* tab_contents) : tab_contents_(tab_contents),
-                                 pending_query_handle_(0) {
-  DCHECK(tab_contents);
-
+    TabContents* tab_contents)
+    : tab_contents_(tab_contents),
+      pending_query_handle_(0),
+      query_id_(0) {
   profile_ = tab_contents_->profile();
-  DCHECK(profile_);
-
+  // May be NULL in unit tests.
   web_data_service_ = profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
-  DCHECK(web_data_service_);
-
   autofill_enabled_.Init(prefs::kAutoFillEnabled, profile_->GetPrefs(), NULL);
 }
 
@@ -89,61 +87,18 @@
   CancelPendingQuery();
 }
 
-void AutocompleteHistoryManager::FormSubmitted(const FormData& form) {
-  StoreFormEntriesInWebDatabase(form);
+bool AutocompleteHistoryManager::OnMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(AutocompleteHistoryManager, message)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_RemoveAutocompleteEntry,
+                        OnRemoveAutocompleteEntry)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
 }
 
-void AutocompleteHistoryManager::GetAutocompleteSuggestions(
-    const string16& name, const string16& prefix) {
-  if (!*autofill_enabled_) {
-    SendSuggestions(NULL);
-    return;
-  }
-
-  CancelPendingQuery();
-
-  pending_query_handle_ = web_data_service_->GetFormValuesForElementName(
-      name, prefix, kMaxAutocompleteMenuItems, this);
-}
-
-void AutocompleteHistoryManager::RemoveAutocompleteEntry(
-    const string16& name, const string16& value) {
-  web_data_service_->RemoveFormValueForElementName(name, value);
-}
-
-void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
-    WebDataService::Handle h,
-    const WDTypedResult* result) {
-  DCHECK(pending_query_handle_);
-  pending_query_handle_ = 0;
-
-  if (*autofill_enabled_) {
-    DCHECK(result);
-    SendSuggestions(result);
-  } else {
-    SendSuggestions(NULL);
-  }
-}
-
-AutocompleteHistoryManager::AutocompleteHistoryManager(
-    Profile* profile, WebDataService* wds) : tab_contents_(NULL),
-                                             profile_(profile),
-                                             web_data_service_(wds),
-                                             pending_query_handle_(0) {
-  autofill_enabled_.Init(
-      prefs::kAutoFillEnabled, profile_->GetPrefs(), NULL);
-}
-
-void AutocompleteHistoryManager::CancelPendingQuery() {
-  if (pending_query_handle_) {
-    SendSuggestions(NULL);
-    web_data_service_->CancelRequest(pending_query_handle_);
-  }
-  pending_query_handle_ = 0;
-}
-
-void AutocompleteHistoryManager::StoreFormEntriesInWebDatabase(
-    const FormData& form) {
+void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) {
   if (!*autofill_enabled_)
     return;
 
@@ -172,21 +127,124 @@
       values.push_back(*iter);
   }
 
-  if (!values.empty())
+  if (!values.empty() && web_data_service_.get())
     web_data_service_->AddFormFields(values);
 }
 
-void AutocompleteHistoryManager::SendSuggestions(const WDTypedResult* result) {
-  RenderViewHost* host = tab_contents_->render_view_host();
-  if (!host)
-    return;
+void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
+    const string16& name, const string16& value) {
+  if (web_data_service_.get())
+    web_data_service_->RemoveFormValueForElementName(name, value);
+}
 
-  if (result) {
-    DCHECK(result->GetType() == AUTOFILL_VALUE_RESULT);
-    const WDResult<std::vector<string16> >* autofill_result =
-        static_cast<const WDResult<std::vector<string16> >*>(result);
-    host->AutocompleteSuggestionsReturned(autofill_result->GetValue());
-  } else {
-    host->AutocompleteSuggestionsReturned(std::vector<string16>());
+void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
+    int query_id,
+    const string16& name,
+    const string16& prefix,
+    const std::vector<string16>& autofill_values,
+    const std::vector<string16>& autofill_labels,
+    const std::vector<string16>& autofill_icons,
+    const std::vector<int>& autofill_unique_ids) {
+  CancelPendingQuery();
+
+  query_id_ = query_id;
+  autofill_values_ = autofill_values;
+  autofill_labels_ = autofill_labels;
+  autofill_icons_ = autofill_icons;
+  autofill_unique_ids_ = autofill_unique_ids;
+  if (!*autofill_enabled_) {
+    SendSuggestions(NULL);
+    return;
   }
+
+  if (web_data_service_.get()) {
+    pending_query_handle_ = web_data_service_->GetFormValuesForElementName(
+        name, prefix, kMaxAutocompleteMenuItems, this);
+  }
+}
+
+void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
+    WebDataService::Handle h,
+    const WDTypedResult* result) {
+  DCHECK(pending_query_handle_);
+  pending_query_handle_ = 0;
+
+  if (!*autofill_enabled_) {
+    SendSuggestions(NULL);
+    return;
+  }
+
+  DCHECK(result);
+  // Returning early here if |result| is NULL.  We've seen this happen on
+  // Linux due to NFS dismounting and causing sql failures.
+  // See http://crbug.com/68783.
+  if (!result) {
+    SendSuggestions(NULL);
+    return;
+  }
+
+  DCHECK(result->GetType() == AUTOFILL_VALUE_RESULT);
+  const WDResult<std::vector<string16> >* autofill_result =
+      static_cast<const WDResult<std::vector<string16> >*>(result);
+  std::vector<string16> suggestions = autofill_result->GetValue();
+  SendSuggestions(&suggestions);
+}
+
+AutocompleteHistoryManager::AutocompleteHistoryManager(
+    Profile* profile, WebDataService* wds) : tab_contents_(NULL),
+                                             profile_(profile),
+                                             web_data_service_(wds),
+                                             pending_query_handle_(0),
+                                             query_id_(0) {
+  autofill_enabled_.Init(
+      prefs::kAutoFillEnabled, profile_->GetPrefs(), NULL);
+}
+
+void AutocompleteHistoryManager::CancelPendingQuery() {
+  if (pending_query_handle_) {
+    SendSuggestions(NULL);
+    if (web_data_service_.get())
+      web_data_service_->CancelRequest(pending_query_handle_);
+    pending_query_handle_ = 0;
+  }
+}
+
+void AutocompleteHistoryManager::SendSuggestions(
+    const std::vector<string16>* suggestions) {
+  if (suggestions) {
+    // Combine AutoFill and Autocomplete values into values and labels.
+    for (size_t i = 0; i < suggestions->size(); ++i) {
+      bool unique = true;
+      for (size_t j = 0; j < autofill_values_.size(); ++j) {
+        // Don't add duplicate values.
+        if (autofill_values_[j] == (*suggestions)[i]) {
+          unique = false;
+          break;
+        }
+      }
+
+      if (unique) {
+        autofill_values_.push_back((*suggestions)[i]);
+        autofill_labels_.push_back(string16());
+        autofill_icons_.push_back(string16());
+        autofill_unique_ids_.push_back(0);  // 0 means no profile.
+      }
+    }
+  }
+
+  RenderViewHost* host = tab_contents_->render_view_host();
+  if (host) {
+    host->Send(new AutoFillMsg_SuggestionsReturned(host->routing_id(),
+                                                   query_id_,
+                                                   autofill_values_,
+                                                   autofill_labels_,
+                                                   autofill_icons_,
+                                                   autofill_unique_ids_));
+  }
+
+  query_id_ = 0;
+  autofill_values_.clear();
+  autofill_labels_.clear();
+  autofill_icons_.clear();
+  autofill_unique_ids_.clear();
 }
diff --git a/chrome/browser/autocomplete_history_manager.h b/chrome/browser/autocomplete_history_manager.h
index 5752942..fd4387f 100644
--- a/chrome/browser/autocomplete_history_manager.h
+++ b/chrome/browser/autocomplete_history_manager.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_AUTOCOMPLETE_HISTORY_MANAGER_H_
 #pragma once
 
+#include <vector>
+
 #include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
 #include "chrome/browser/webdata/web_data_service.h"
 
 namespace webkit_glue {
@@ -19,34 +21,43 @@
 
 // Per-tab Autocomplete history manager. Handles receiving form data from the
 // renderer and the storing and retrieving of form data through WebDataService.
-class AutocompleteHistoryManager
-    : public RenderViewHostDelegate::Autocomplete,
-      public WebDataServiceConsumer {
+class AutocompleteHistoryManager : public TabContentsObserver,
+                                   public WebDataServiceConsumer {
  public:
   explicit AutocompleteHistoryManager(TabContents* tab_contents);
   virtual ~AutocompleteHistoryManager();
 
-  // RenderViewHostDelegate::Autocomplete implementation.
-  virtual void FormSubmitted(const webkit_glue::FormData& form);
-  virtual void GetAutocompleteSuggestions(const string16& name,
-                                          const string16& prefix);
-  virtual void RemoveAutocompleteEntry(const string16& name,
-                                       const string16& value);
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
 
   // WebDataServiceConsumer implementation.
   virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
                                            const WDTypedResult* result);
 
+  // Pass-through functions that are called by AutoFillManager, after it has
+  // dispatched a message.
+  void OnGetAutocompleteSuggestions(
+      int query_id,
+      const string16& name,
+      const string16& prefix,
+      const std::vector<string16>& autofill_values,
+      const std::vector<string16>& autofill_labels,
+      const std::vector<string16>& autofill_icons,
+      const std::vector<int>& autofill_unique_ids);
+  void OnFormSubmitted(const webkit_glue::FormData& form);
+
  protected:
   friend class AutocompleteHistoryManagerTest;
+  friend class AutoFillManagerTest;
 
   // For tests.
   AutocompleteHistoryManager(Profile* profile, WebDataService* wds);
 
- private:
+  void SendSuggestions(const std::vector<string16>* suggestions);
   void CancelPendingQuery();
-  void StoreFormEntriesInWebDatabase(const webkit_glue::FormData& form);
-  void SendSuggestions(const WDTypedResult* suggestions);
+
+ private:
+  void OnRemoveAutocompleteEntry(const string16& name, const string16& value);
 
   TabContents* tab_contents_;
   Profile* profile_;
@@ -54,10 +65,15 @@
 
   BooleanPrefMember autofill_enabled_;
 
-  // When the manager makes a request from WebDataService, the database
-  // is queried on another thread, we record the query handle until we
-  // get called back.
+  // When the manager makes a request from WebDataService, the database is
+  // queried on another thread, we record the query handle until we get called
+  // back.  We also store the autofill results so we can send them together.
   WebDataService::Handle pending_query_handle_;
+  int query_id_;
+  std::vector<string16> autofill_values_;
+  std::vector<string16> autofill_labels_;
+  std::vector<string16> autofill_icons_;
+  std::vector<int> autofill_unique_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(AutocompleteHistoryManager);
 };
diff --git a/chrome/browser/autocomplete_history_manager_unittest.cc b/chrome/browser/autocomplete_history_manager_unittest.cc
index 409225f..cfc0c83 100644
--- a/chrome/browser/autocomplete_history_manager_unittest.cc
+++ b/chrome/browser/autocomplete_history_manager_unittest.cc
@@ -63,7 +63,7 @@
   form.fields.push_back(valid_cc);
 
   EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
-  autocomplete_manager_->FormSubmitted(form);
+  autocomplete_manager_->OnFormSubmitted(form);
 }
 
 // Contrary test to AutocompleteHistoryManagerTest.CreditCardNumberValue.  The
@@ -87,7 +87,7 @@
   form.fields.push_back(invalid_cc);
 
   EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(1);
-  autocomplete_manager_->FormSubmitted(form);
+  autocomplete_manager_->OnFormSubmitted(form);
 }
 
 // Tests that SSNs are not sent to the WebDatabase to be saved.
@@ -108,5 +108,5 @@
   form.fields.push_back(ssn);
 
   EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0);
-  autocomplete_manager_->FormSubmitted(form);
+  autocomplete_manager_->OnFormSubmitted(form);
 }
diff --git a/chrome/browser/autofill/OWNERS b/chrome/browser/autofill/OWNERS
new file mode 100644
index 0000000..27f4c6e
--- /dev/null
+++ b/chrome/browser/autofill/OWNERS
@@ -0,0 +1,2 @@
+dhollowa@chromium.org
+isherman@chromium.org
diff --git a/chrome/browser/autofill/address_field.cc b/chrome/browser/autofill/address_field.cc
index b2bef04..e379c74 100644
--- a/chrome/browser/autofill/address_field.cc
+++ b/chrome/browser/autofill/address_field.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/autofill/address_field.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
@@ -12,6 +11,7 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/autofill_field.h"
 #include "grit/autofill_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 bool AddressField::GetFieldInfo(FieldTypeMap* field_type_map) const {
   AutoFillFieldType address_company;
diff --git a/chrome/browser/autofill/autofill_address_model_mac.h b/chrome/browser/autofill/autofill_address_model_mac.h
index 230db90..59b4cbf 100644
--- a/chrome/browser/autofill/autofill_address_model_mac.h
+++ b/chrome/browser/autofill/autofill_address_model_mac.h
@@ -34,17 +34,17 @@
   NSString* faxWholeNumber_;
 }
 
-@property (nonatomic, copy) NSString* fullName;
-@property (nonatomic, copy) NSString* email;
-@property (nonatomic, copy) NSString* companyName;
-@property (nonatomic, copy) NSString* addressLine1;
-@property (nonatomic, copy) NSString* addressLine2;
-@property (nonatomic, copy) NSString* addressCity;
-@property (nonatomic, copy) NSString* addressState;
-@property (nonatomic, copy) NSString* addressZip;
-@property (nonatomic, copy) NSString* addressCountry;
-@property (nonatomic, copy) NSString* phoneWholeNumber;
-@property (nonatomic, copy) NSString* faxWholeNumber;
+@property(nonatomic, copy) NSString* fullName;
+@property(nonatomic, copy) NSString* email;
+@property(nonatomic, copy) NSString* companyName;
+@property(nonatomic, copy) NSString* addressLine1;
+@property(nonatomic, copy) NSString* addressLine2;
+@property(nonatomic, copy) NSString* addressCity;
+@property(nonatomic, copy) NSString* addressState;
+@property(nonatomic, copy) NSString* addressZip;
+@property(nonatomic, copy) NSString* addressCountry;
+@property(nonatomic, copy) NSString* phoneWholeNumber;
+@property(nonatomic, copy) NSString* faxWholeNumber;
 
 // The designated initializer. Initializes the property strings to values
 // retrieved from the |profile|.
diff --git a/chrome/browser/autofill/autofill_address_model_mac.mm b/chrome/browser/autofill/autofill_address_model_mac.mm
index d94c06e..3b1623b 100644
--- a/chrome/browser/autofill/autofill_address_model_mac.mm
+++ b/chrome/browser/autofill/autofill_address_model_mac.mm
@@ -3,10 +3,10 @@
 // found in the LICENSE file.
 
 #import "chrome/browser/autofill/autofill_address_model_mac.h"
-#include "app/l10n_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/autofill/autofill_profile.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 @implementation AutoFillAddressModel
 
diff --git a/chrome/browser/autofill/autofill_address_sheet_controller_mac.h b/chrome/browser/autofill/autofill_address_sheet_controller_mac.h
index 0df6016..70a63bf 100644
--- a/chrome/browser/autofill/autofill_address_sheet_controller_mac.h
+++ b/chrome/browser/autofill/autofill_address_sheet_controller_mac.h
@@ -39,7 +39,7 @@
   AutoFillAddressMode mode_;
 }
 
-@property (nonatomic, retain) AutoFillAddressModel* addressModel;
+@property(nonatomic, retain) AutoFillAddressModel* addressModel;
 
 // IBActions for save and cancel buttons.  Both invoke |endSheet:|.
 - (IBAction)save:(id)sender;
diff --git a/chrome/browser/autofill/autofill_address_sheet_controller_mac.mm b/chrome/browser/autofill/autofill_address_sheet_controller_mac.mm
index d2f6938..a2c55cf 100644
--- a/chrome/browser/autofill/autofill_address_sheet_controller_mac.mm
+++ b/chrome/browser/autofill/autofill_address_sheet_controller_mac.mm
@@ -4,13 +4,13 @@
 
 #import "chrome/browser/autofill/autofill_address_sheet_controller_mac.h"
 
-#include "app/l10n_util.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #import "chrome/browser/autofill/autofill_address_model_mac.h"
 #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
 #include "chrome/browser/autofill/autofill_profile.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 @implementation AutoFillAddressSheetController
 
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index 0aad9de..9d36e16 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -1,11 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <string>
 
 #include "base/utf_string_conversions.h"
-#include "app/keyboard_code_conversion.h"
 #include "base/basictypes.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
@@ -22,16 +21,18 @@
 #include "chrome/browser/translate/translate_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/net/test_url_fetcher_factory.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/renderer/translate_helper.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
+static const char* kDataURIPrefix = "data:text/html;charset=utf-8,";
 static const char* kTestFormString =
-    "<form action=\"http://www.google.com/\" method=\"POST\">"
+    "<form action=\"http://www.example.com/\" method=\"POST\">"
     "<label for=\"firstname\">First name:</label>"
     " <input type=\"text\" id=\"firstname\""
     "        onFocus=\"domAutomationController.send(true)\""
@@ -69,7 +70,11 @@
     EnableDOMAutomation();
   }
 
-  void SetUpProfile() {
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    URLFetcher::set_factory(&url_fetcher_factory_);
+  }
+
+  void CreateTestProfile() {
     autofill_test::DisableSystemServices(browser()->profile());
 
     AutoFillProfile profile;
@@ -97,21 +102,16 @@
     EXPECT_EQ(expected_value, value);
   }
 
-  RenderViewHost* rvh() {
+  RenderViewHost* render_view_host() {
     return browser()->GetSelectedTabContents()->render_view_host();
   }
 
-  virtual void SetUp() {
-    URLFetcher::set_factory(&url_fetcher_factory_);
-    InProcessBrowserTest::SetUp();
-  }
-
   void SimulateURLFetch(bool success) {
     TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
     ASSERT_TRUE(fetcher);
-    URLRequestStatus status;
-    status.set_status(success ? URLRequestStatus::SUCCESS :
-        URLRequestStatus::FAILED);
+    net::URLRequestStatus status;
+    status.set_status(success ? net::URLRequestStatus::SUCCESS :
+                                net::URLRequestStatus::FAILED);
 
     std::string script = " var google = {};"
         "google.translate = (function() {"
@@ -145,7 +145,7 @@
         script);
   }
 
-  void TryBasicFormFillWithMKey() {
+  void FocusFirstNameField() {
     ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
                                                        VIEW_ID_TAB_CONTAINER));
     ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(),
@@ -153,21 +153,39 @@
 
     bool result = false;
     ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
-        rvh(), L"", L"document.getElementById('firstname').focus();", &result));
+        render_view_host(), L"",
+        L"document.getElementById('firstname').focus();", &result));
     ASSERT_TRUE(result);
+  }
+
+  void ExpectFilledTestForm() {
+    ExpectFieldValue(L"firstname", "Milton");
+    ExpectFieldValue(L"lastname", "Waddams");
+    ExpectFieldValue(L"address1", "4120 Freidrich Lane");
+    ExpectFieldValue(L"address2", "Basement");
+    ExpectFieldValue(L"city", "Austin");
+    ExpectFieldValue(L"state", "TX");
+    ExpectFieldValue(L"zip", "78744");
+    ExpectFieldValue(L"country", "US");
+    ExpectFieldValue(L"phone", "5125551234");
+  }
+
+  void TryBasicFormFill() {
+    FocusFirstNameField();
+
     // Start filling the first name field with "M" and wait for the popup to be
     // shown.
     ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-        browser(), app::VKEY_M, false, true, false, false,
+        browser(), ui::VKEY_M, false, true, false, false,
         NotificationType::AUTOFILL_DID_SHOW_SUGGESTIONS,
-        Source<RenderViewHost>(rvh())));
+        Source<RenderViewHost>(render_view_host())));
 
     // Press the down arrow to select the suggestion and preview the autofilled
     // form.
     ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-        browser(), app::VKEY_DOWN, false, false, false, false,
+        browser(), ui::VKEY_DOWN, false, false, false, false,
         NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
-        Source<RenderViewHost>(rvh())));
+        Source<RenderViewHost>(render_view_host())));
 
     // The previewed values should not be accessible to JavaScript.
     ExpectFieldValue(L"firstname", "M");
@@ -184,21 +202,12 @@
 
     // Press Enter to accept the autofill suggestions.
     ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-        browser(), app::VKEY_RETURN, false, false, false, false,
+        browser(), ui::VKEY_RETURN, false, false, false, false,
         NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
-        Source<RenderViewHost>(rvh())));
+        Source<RenderViewHost>(render_view_host())));
 
     // The form should be filled.
-    ExpectFieldValue(L"firstname", "Milton");
-    ExpectFieldValue(L"lastname", "Waddams");
-    ExpectFieldValue(L"address1", "4120 Freidrich Lane");
-    ExpectFieldValue(L"address2", "Basement");
-    ExpectFieldValue(L"city", "Austin");
-    ExpectFieldValue(L"state", "TX");
-    ExpectFieldValue(L"zip", "78744");
-    ExpectFieldValue(L"country", "US");
-    ExpectFieldValue(L"phone", "5125551234");
-
+    ExpectFilledTestForm();
   }
 
  private:
@@ -207,66 +216,123 @@
 
 // Test that basic form fill is working.
 IN_PROC_BROWSER_TEST_F(AutoFillTest, BasicFormFill) {
-  SetUpProfile();
+  CreateTestProfile();
 
+  // Load the test page.
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
   ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL("data:text/html;charset=utf-8," + std::string(kTestFormString))));
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
 
-  TryBasicFormFillWithMKey();
+  // Invoke AutoFill.
+  TryBasicFormFill();
 }
 
-// Test that basic form fill is working.
-IN_PROC_BROWSER_TEST_F(AutoFillTest, TranslateAndFormFill) {
-  SetUpProfile();
+// Test that form filling can be initiated by pressing the down arrow.
+IN_PROC_BROWSER_TEST_F(AutoFillTest, AutoFillViaDownArrow) {
+  CreateTestProfile();
 
-  GURL url("data:text/html;charset=utf-8,"
-              "<form action=\"http://www.google.com/\" method=\"POST\">"
-              "<label for=\"firstname\">なまえ</label>"
-              " <input type=\"text\" id=\"firstname\""
-              "        onFocus=\"domAutomationController.send(true)\""
-              " /><br />"
-              "<label for=\"lastname\">みょうじ</label>"
-              " <input type=\"text\" id=\"lastname\" /><br />"
-              "<label for=\"address1\">Address line 1:</label>"
-              " <input type=\"text\" id=\"address1\" /><br />"
-              "<label for=\"address2\">Address line 2:</label>"
-              " <input type=\"text\" id=\"address2\" /><br />"
-              "<label for=\"city\">City:</label>"
-              " <input type=\"text\" id=\"city\" /><br />"
-              "<label for=\"state\">State:</label>"
-              " <select id=\"state\">"
-              " <option value=\"\" selected=\"yes\">--</option>"
-              " <option value=\"CA\">California</option>"
-              " <option value=\"TX\">Texas</option>"
-              " </select><br />"
-              "<label for=\"zip\">ZIP code:</label>"
-              " <input type=\"text\" id=\"zip\" /><br />"
-              "<label for=\"country\">Country:</label>"
-              " <select id=\"country\">"
-              " <option value=\"\" selected=\"yes\">--</option>"
-              " <option value=\"CA\">Canada</option>"
-              " <option value=\"US\">United States</option>"
-              " </select><br />"
-              "<label for=\"phone\">Phone number:</label>"
-              " <input type=\"text\" id=\"phone\" /><br />"
-              "</form>");
+  // Load the test page.
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
-      browser(), url));
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+  // Focus a fillable field.
+  FocusFirstNameField();
+
+  // Press the down arrow to initiate AutoFill and wait for the popup to be
+  // shown.
+  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+      browser(), ui::VKEY_DOWN, false, false, false, false,
+      NotificationType::AUTOFILL_DID_SHOW_SUGGESTIONS,
+      Source<RenderViewHost>(render_view_host())));
+
+  // Press the down arrow to select the suggestion and preview the autofilled
+  // form.
+  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+      browser(), ui::VKEY_DOWN, false, false, false, false,
+      NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
+      Source<RenderViewHost>(render_view_host())));
+
+  // Press Enter to accept the autofill suggestions.
+  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+      browser(), ui::VKEY_RETURN, false, false, false, false,
+      NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
+      Source<RenderViewHost>(render_view_host())));
+
+  // The form should be filled.
+  ExpectFilledTestForm();
+}
+
+// Test that form filling works after reloading the current page.
+// This test brought to you by http://crbug.com/69204
+IN_PROC_BROWSER_TEST_F(AutoFillTest, AutoFillAfterReload) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+  // Reload the page.
+  NavigationController* controller =
+      &browser()->GetSelectedTabContentsWrapper()->tab_contents()->controller();
+  controller->Reload(false);
+  ui_test_utils::WaitForLoadStop(controller);
+
+  // Invoke AutoFill.
+  TryBasicFormFill();
+}
+
+// Test that autofill works after page translation.
+IN_PROC_BROWSER_TEST_F(AutoFillTest, AutoFillAfterTranslate) {
+  CreateTestProfile();
+
+  GURL url(std::string(kDataURIPrefix) +
+               "<form action=\"http://www.example.com/\" method=\"POST\">"
+               "<label for=\"fn\">なまえ</label>"
+               " <input type=\"text\" id=\"fn\""
+               "        onFocus=\"domAutomationController.send(true)\""
+               " /><br />"
+               "<label for=\"ln\">みょうじ</label>"
+               " <input type=\"text\" id=\"ln\" /><br />"
+               "<label for=\"a1\">Address line 1:</label>"
+               " <input type=\"text\" id=\"a1\" /><br />"
+               "<label for=\"a2\">Address line 2:</label>"
+               " <input type=\"text\" id=\"a2\" /><br />"
+               "<label for=\"ci\">City:</label>"
+               " <input type=\"text\" id=\"ci\" /><br />"
+               "<label for=\"st\">State:</label>"
+               " <select id=\"st\">"
+               " <option value=\"\" selected=\"yes\">--</option>"
+               " <option value=\"CA\">California</option>"
+               " <option value=\"TX\">Texas</option>"
+               " </select><br />"
+               "<label for=\"z\">ZIP code:</label>"
+               " <input type=\"text\" id=\"z\" /><br />"
+               "<label for=\"co\">Country:</label>"
+               " <select id=\"co\">"
+               " <option value=\"\" selected=\"yes\">--</option>"
+               " <option value=\"CA\">Canada</option>"
+               " <option value=\"US\">United States</option>"
+               " </select><br />"
+               "<label for=\"ph\">Phone number:</label>"
+               " <input type=\"text\" id=\"ph\" /><br />"
+               "</form>");
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
 
   // Get translation bar.
   int page_id = browser()->GetSelectedTabContents()->controller().
       GetLastCommittedEntry()->page_id();
-  rvh()->OnMessageReceived(ViewHostMsg_PageContents(0, url, page_id,
-      UTF8ToUTF16("test"), "ja", true));
+  render_view_host()->OnMessageReceived(ViewHostMsg_PageContents(
+      0, url, page_id, ASCIIToUTF16("test"), "ja", true));
   TranslateInfoBarDelegate* infobar = browser()->GetSelectedTabContents()->
       GetInfoBarDelegateAt(0)->AsTranslateInfoBarDelegate();
 
   ASSERT_TRUE(infobar != NULL);
   EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type());
 
-  // Simulate press translation button.
+  // Simulate translation button press.
   infobar->Translate();
 
   // Simulate the translate script being retrieved.
@@ -277,10 +343,11 @@
   // But right now, the call stucks here.
   // Once click the text field, it starts again.
   ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
-      rvh(), L"", L"cr.googleTranslate.onTranslateElementLoad();"));
+      render_view_host(), L"",
+      L"cr.googleTranslate.onTranslateElementLoad();"));
 
   // Simulate the render notifying the translation has been done.
   ui_test_utils::WaitForNotification(NotificationType::PAGE_TRANSLATED);
 
-  TryBasicFormFillWithMKey();
+  TryBasicFormFill();
 }
diff --git a/chrome/browser/autofill/autofill_cc_infobar_delegate.cc b/chrome/browser/autofill/autofill_cc_infobar_delegate.cc
index a57c6e3..f230b43 100644
--- a/chrome/browser/autofill/autofill_cc_infobar_delegate.cc
+++ b/chrome/browser/autofill/autofill_cc_infobar_delegate.cc
@@ -1,23 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/autofill/autofill_cc_infobar_delegate.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/metrics/histogram.h"
 #include "chrome/browser/autofill/autofill_cc_infobar.h"
 #include "chrome/browser/autofill/autofill_manager.h"
 #include "chrome/browser/browser_list.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "chrome/common/pref_names.h"
-#include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 AutoFillCCInfoBarDelegate::AutoFillCCInfoBarDelegate(TabContents* tab_contents,
                                                      AutoFillManager* host)
@@ -44,29 +38,22 @@
   delete this;
 }
 
-string16 AutoFillCCInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_INFOBAR_TEXT);
-}
-
 SkBitmap* AutoFillCCInfoBarDelegate::GetIcon() const {
   return ResourceBundle::GetSharedInstance().GetBitmapNamed(
       IDR_INFOBAR_AUTOFILL);
 }
 
-int AutoFillCCInfoBarDelegate::GetButtons() const {
-  return BUTTON_OK | BUTTON_CANCEL;
+InfoBarDelegate::Type AutoFillCCInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
 }
 
-string16 AutoFillCCInfoBarDelegate::GetButtonLabel(
-    ConfirmInfoBarDelegate::InfoBarButton button) const {
-  if (button == BUTTON_OK)
-    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_INFOBAR_ACCEPT);
-  else if (button == BUTTON_CANCEL)
-    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_INFOBAR_DENY);
-  else
-    NOTREACHED();
+string16 AutoFillCCInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_INFOBAR_TEXT);
+}
 
-  return string16();
+string16 AutoFillCCInfoBarDelegate::GetButtonLabel(InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_AUTOFILL_CC_INFOBAR_ACCEPT : IDS_AUTOFILL_CC_INFOBAR_DENY);
 }
 
 bool AutoFillCCInfoBarDelegate::Accept() {
@@ -80,10 +67,6 @@
 
 bool AutoFillCCInfoBarDelegate::Cancel() {
   UMA_HISTOGRAM_COUNTS("AutoFill.CCInfoBarDenied", 1);
-  if (host_) {
-    host_->OnInfoBarClosed(false);
-    host_ = NULL;
-  }
   return true;
 }
 
@@ -103,7 +86,3 @@
   return CreateAutofillCcInfoBar(this);
 }
 #endif  // defined(OS_WIN)
-
-InfoBarDelegate::Type AutoFillCCInfoBarDelegate::GetInfoBarType() {
-  return PAGE_ACTION_TYPE;
-}
diff --git a/chrome/browser/autofill/autofill_cc_infobar_delegate.h b/chrome/browser/autofill/autofill_cc_infobar_delegate.h
index a02b4ca..196be3f 100644
--- a/chrome/browser/autofill/autofill_cc_infobar_delegate.h
+++ b/chrome/browser/autofill/autofill_cc_infobar_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,25 +10,24 @@
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 
 class AutoFillManager;
-class SkBitmap;
-class TabContents;
 
 // An InfoBar delegate that enables the user to allow or deny storing credit
 // card information gathered from a form submission.
 class AutoFillCCInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   AutoFillCCInfoBarDelegate(TabContents* tab_contents, AutoFillManager* host);
+
+ private:
   virtual ~AutoFillCCInfoBarDelegate();
 
-  // ConfirmInfoBarDelegate implementation.
+  // ConfirmInfoBarDelegate:
   virtual bool ShouldExpire(
-     const NavigationController::LoadCommittedDetails& details) const;
+      const NavigationController::LoadCommittedDetails& details) const;
   virtual void InfoBarClosed();
-  virtual string16 GetMessageText() const;
   virtual SkBitmap* GetIcon() const;
-  virtual int GetButtons() const;
-  virtual string16 GetButtonLabel(
-     ConfirmInfoBarDelegate::InfoBarButton button) const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
   virtual bool Accept();
   virtual bool Cancel();
   virtual string16 GetLinkText();
@@ -39,9 +38,6 @@
   virtual InfoBar* CreateInfoBar();
 #endif  // defined(OS_WIN)
 
-  virtual Type GetInfoBarType();
-
- private:
   // The AutoFillManager that initiated this InfoBar.
   AutoFillManager* host_;
 
diff --git a/chrome/browser/autofill/autofill_cc_infobar_win.cc b/chrome/browser/autofill/autofill_cc_infobar_win.cc
index 31a7c6a..d24e4f0 100644
--- a/chrome/browser/autofill/autofill_cc_infobar_win.cc
+++ b/chrome/browser/autofill/autofill_cc_infobar_win.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/autofill/autofill_cc_infobar.h"
 
-#include "app/resource_bundle.h"
-#include "chrome/browser/views/event_utils.h"
-#include "chrome/browser/views/infobars/infobars.h"
-#include "chrome/browser/views/infobars/infobar_text_button.h"
-#include "chrome/common/pref_names.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/ui/views/event_utils.h"
+#include "chrome/browser/ui/views/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/link.h"
 
@@ -85,7 +85,7 @@
 
 void SaveCCInfoConfirmInfoBar::Layout() {
   // Layout the close button.
-  InfoBar::Layout();
+  InfoBarView::Layout();
 
   int available_width = AlertInfoBar::GetAvailableWidth();
 
@@ -130,7 +130,7 @@
 void SaveCCInfoConfirmInfoBar::ViewHierarchyChanged(bool is_add,
                                                     views::View* parent,
                                                     views::View* child) {
-  InfoBar::ViewHierarchyChanged(is_add, parent, child);
+  InfoBarView::ViewHierarchyChanged(is_add, parent, child);
   if (is_add && child == this && !initialized_) {
     Init();
     initialized_ = true;
@@ -139,7 +139,7 @@
 
 void SaveCCInfoConfirmInfoBar::ButtonPressed(views::Button* sender,
                                              const views::Event& event) {
-  InfoBar::ButtonPressed(sender, event);
+  InfoBarView::ButtonPressed(sender, event);
   if (sender == save_button_) {
     if (GetDelegate()->Accept())
       RemoveInfoBar();
diff --git a/chrome/browser/autofill/autofill_common_test.cc b/chrome/browser/autofill/autofill_common_test.cc
index 6817dbb..c926b8e 100644
--- a/chrome/browser/autofill/autofill_common_test.cc
+++ b/chrome/browser/autofill/autofill_common_test.cc
@@ -86,8 +86,10 @@
 
   // Disable auxiliary profiles for unit testing.  These reach out to system
   // services on the Mac.
-  profile->GetPrefs()->SetBoolean(prefs::kAutoFillAuxiliaryProfilesEnabled,
-                                  false);
+  if (profile) {
+    profile->GetPrefs()->SetBoolean(prefs::kAutoFillAuxiliaryProfilesEnabled,
+                                    false);
+  }
 }
 
 }  // namespace autofill_test
diff --git a/chrome/browser/autofill/autofill_credit_card_model_mac.h b/chrome/browser/autofill/autofill_credit_card_model_mac.h
index 093e7cb..53562a2 100644
--- a/chrome/browser/autofill/autofill_credit_card_model_mac.h
+++ b/chrome/browser/autofill/autofill_credit_card_model_mac.h
@@ -27,10 +27,10 @@
   NSString* expirationYear_;
 }
 
-@property (nonatomic, copy) NSString* nameOnCard;
-@property (nonatomic, copy) NSString* creditCardNumber;
-@property (nonatomic, copy) NSString* expirationMonth;
-@property (nonatomic, copy) NSString* expirationYear;
+@property(nonatomic, copy) NSString* nameOnCard;
+@property(nonatomic, copy) NSString* creditCardNumber;
+@property(nonatomic, copy) NSString* expirationMonth;
+@property(nonatomic, copy) NSString* expirationYear;
 
 // Designated initializer.  Initializes the property strings to values retrieved
 // from the |creditCard| object.
diff --git a/chrome/browser/autofill/autofill_credit_card_model_mac.mm b/chrome/browser/autofill/autofill_credit_card_model_mac.mm
index 1eec96f..6c939ca 100644
--- a/chrome/browser/autofill/autofill_credit_card_model_mac.mm
+++ b/chrome/browser/autofill/autofill_credit_card_model_mac.mm
@@ -3,10 +3,10 @@
 // found in the LICENSE file.
 
 #import "chrome/browser/autofill/autofill_credit_card_model_mac.h"
-#include "app/l10n_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/autofill/credit_card.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 
 @implementation AutoFillCreditCardModel
diff --git a/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h b/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h
index 650fb1c..3015c9b 100644
--- a/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h
+++ b/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h
@@ -53,9 +53,9 @@
   AutoFillCreditCardMode mode_;
 }
 
-@property (nonatomic, retain) AutoFillCreditCardModel* creditCardModel;
-@property (nonatomic, retain) NSArray* expirationMonthContents;
-@property (nonatomic, retain) NSArray* expirationYearContents;
+@property(nonatomic, retain) AutoFillCreditCardModel* creditCardModel;
+@property(nonatomic, retain) NSArray* expirationMonthContents;
+@property(nonatomic, retain) NSArray* expirationYearContents;
 
 // Designated initializer.  Takes a copy of the data in |creditCard|,
 // it is not held as a reference.
diff --git a/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.mm b/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.mm
index ae72117..dd00cd5 100644
--- a/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.mm
+++ b/chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.mm
@@ -4,13 +4,13 @@
 
 #import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h"
 
-#include "app/l10n_util.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #import "chrome/browser/autofill/autofill_credit_card_model_mac.h"
 #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
 #include "chrome/browser/autofill/credit_card.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // Interface exposed for unit testing.
 @implementation AutoFillCreditCardSheetController (ExposedForUnitTests)
diff --git a/chrome/browser/autofill/autofill_dialog.h b/chrome/browser/autofill/autofill_dialog.h
index 1c47c86..a3ad48d 100644
--- a/chrome/browser/autofill/autofill_dialog.h
+++ b/chrome/browser/autofill/autofill_dialog.h
@@ -10,6 +10,7 @@
 
 #include "chrome/browser/autofill/autofill_profile.h"
 #include "chrome/browser/autofill/credit_card.h"
+<<<<<<< HEAD
 
 #ifdef ANDROID
 namespace gfx {
@@ -18,6 +19,9 @@
 #else
 #include "gfx/native_widget_types.h"
 #endif
+=======
+#include "ui/gfx/native_widget_types.h"
+>>>>>>> chromium.org at r11.0.672.0
 
 class Profile;
 
diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.h b/chrome/browser/autofill/autofill_dialog_controller_mac.h
index 642e811..5a9967e 100644
--- a/chrome/browser/autofill/autofill_dialog_controller_mac.h
+++ b/chrome/browser/autofill/autofill_dialog_controller_mac.h
@@ -99,28 +99,28 @@
 // Property representing state of the AutoFill enabled preference.  Checkbox is
 // bound to this in nib.  Also, enabled state of other controls are also bound
 // to this property.
-@property (nonatomic) BOOL autoFillEnabled;
+@property(nonatomic) BOOL autoFillEnabled;
 
 // Property indicating whether AutoFill is under control of configuration
 // management. The enabled state of the AutoFill enabled checkbox is bound to
 // this property.
-@property (nonatomic) BOOL autoFillManaged;
+@property(nonatomic) BOOL autoFillManaged;
 
 // Property that is true iff AutoFill is managed and disabled. The save button's
 // enabled state is bound to this property.
-@property (nonatomic) BOOL autoFillManagedAndDisabled;
+@property(nonatomic) BOOL autoFillManagedAndDisabled;
 
 // Property representing state of Address Book "me" card usage.  Checkbox is
 // bound to this in nib.
-@property (nonatomic) BOOL auxiliaryEnabled;
+@property(nonatomic) BOOL auxiliaryEnabled;
 
 // Property representing selection state in |tableView_|.  Enabled state of
 // edit and delete buttons are bound to this property.
-@property (nonatomic) BOOL itemIsSelected;
+@property(nonatomic) BOOL itemIsSelected;
 
 // Property representing multiple selection state in |tableView_|.  Enabled
 // state of edit button is bound to this property.
-@property (nonatomic) BOOL multipleSelected;
+@property(nonatomic) BOOL multipleSelected;
 
 // Main interface for displaying a modeless AutoFill dialog on screen.
 // This class method creates a new |AutoFillDialogController| and runs it as a
diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.mm b/chrome/browser/autofill/autofill_dialog_controller_mac.mm
index 892160f..039d137 100644
--- a/chrome/browser/autofill/autofill_dialog_controller_mac.mm
+++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm
@@ -3,8 +3,6 @@
 // found in the LICENSE file.
 
 #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/lazy_instance.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
@@ -26,6 +24,8 @@
 #include "grit/generated_resources.h"
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm
index bc2bb40..47654a3 100644
--- a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm
+++ b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm
@@ -74,7 +74,7 @@
 class ProfileMock : public TestingProfile {
  public:
   ProfileMock() {
-    test_manager_ =new PersonalDataManagerMock;
+    test_manager_ = new PersonalDataManagerMock;
   }
   virtual ~ProfileMock() {}
 
diff --git a/chrome/browser/autofill/autofill_dialog_gtk.cc b/chrome/browser/autofill/autofill_dialog_gtk.cc
index b35ad90..0195014 100644
--- a/chrome/browser/autofill/autofill_dialog_gtk.cc
+++ b/chrome/browser/autofill/autofill_dialog_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,8 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
@@ -21,23 +19,25 @@
 #include "chrome/browser/autofill/form_group.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/autofill/phone_number.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/gtk_util.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
 
 // Shows the editor for adding/editing an AutoFillProfile. If
 // |auto_fill_profile| is NULL, a new AutoFillProfile should be created.
diff --git a/chrome/browser/autofill/autofill_dialog_mac.mm b/chrome/browser/autofill/autofill_dialog_mac.mm
index ca611c4..43e161e 100644
--- a/chrome/browser/autofill/autofill_dialog_mac.mm
+++ b/chrome/browser/autofill/autofill_dialog_mac.mm
@@ -4,9 +4,7 @@
 
 #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
 #include "chrome/browser/autofill/autofill_dialog.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
 
 // Mac implementation of |ShowAutoFillDialog| interface defined in
 // |chrome/browser/autofill/autofill_dialog.h|.
diff --git a/chrome/browser/autofill/autofill_download.cc b/chrome/browser/autofill/autofill_download.cc
index 091c0ec..c571d7b 100644
--- a/chrome/browser/autofill/autofill_download.cc
+++ b/chrome/browser/autofill/autofill_download.cc
@@ -17,8 +17,13 @@
 #include "chrome/common/pref_names.h"
 #include "net/http/http_response_headers.h"
 
-#define DISABLED_REQUEST_URL "http://disabled"
+#define AUTO_FILL_QUERY_SERVER_REQUEST_URL \
+    "http://toolbarqueries.clients.google.com:80/tbproxy/af/query"
+#define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL \
+    "http://toolbarqueries.clients.google.com:80/tbproxy/af/upload"
+#define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "GFE/"
 
+<<<<<<< HEAD
 #if defined(GOOGLE_CHROME_BUILD) || (defined(ANDROID) && defined(HAVE_AUTOFILL_DOWNLOAD_INTERNAL_H) && HAVE_AUTOFILL_DOWNLOAD_INTERNAL_H)
 #include "chrome/browser/autofill/internal/autofill_download_internal.h"
 #else
@@ -26,6 +31,11 @@
 #define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL DISABLED_REQUEST_URL
 #define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "SOMESERVER/"
 #endif
+=======
+namespace {
+const size_t kMaxFormCacheSize = 16;
+};
+>>>>>>> chromium.org at r11.0.672.0
 
 struct AutoFillDownloadManager::FormRequestData {
   std::vector<std::string> form_signatures;
@@ -41,12 +51,12 @@
 AutoFillDownloadManager::AutoFillDownloadManager(Profile* profile)
     : profile_(profile),
       observer_(NULL),
+      max_form_cache_size_(kMaxFormCacheSize),
       next_query_request_(base::Time::Now()),
       next_upload_request_(base::Time::Now()),
       positive_upload_rate_(0),
       negative_upload_rate_(0),
-      fetcher_id_for_unittest_(0),
-      is_testing_(false) {
+      fetcher_id_for_unittest_(0) {
   // |profile_| could be NULL in some unit-tests.
 #ifdef ANDROID
   positive_upload_rate_ = kAutoFillPositiveUploadRateDefaultValue;
@@ -55,9 +65,9 @@
   if (profile_) {
     PrefService* preferences = profile_->GetPrefs();
     positive_upload_rate_ =
-        preferences->GetReal(prefs::kAutoFillPositiveUploadRate);
+        preferences->GetDouble(prefs::kAutoFillPositiveUploadRate);
     negative_upload_rate_ =
-        preferences->GetReal(prefs::kAutoFillNegativeUploadRate);
+        preferences->GetDouble(prefs::kAutoFillNegativeUploadRate);
   }
 #endif
 }
@@ -87,12 +97,22 @@
   std::string form_xml;
   FormRequestData request_data;
   if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
-                                         &form_xml))
+                                         &form_xml)) {
     return false;
+  }
 
   request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY;
   metric_logger.Log(AutoFillMetrics::QUERY_SENT);
 
+  std::string query_data;
+  if (CheckCacheForQueryRequest(request_data.form_signatures, &query_data)) {
+    VLOG(1) << "AutoFillDownloadManager: query request has been retrieved from"
+            << "the cache";
+    if (observer_)
+      observer_->OnLoadedAutoFillHeuristics(query_data);
+    return true;
+  }
+
   return StartRequest(form_xml, request_data);
 }
 
@@ -157,7 +177,7 @@
   DCHECK_LE(rate, 1.0);
   DCHECK(profile_);
   PrefService* preferences = profile_->GetPrefs();
-  preferences->SetReal(prefs::kAutoFillPositiveUploadRate, rate);
+  preferences->SetDouble(prefs::kAutoFillPositiveUploadRate, rate);
 }
 
 void AutoFillDownloadManager::SetNegativeUploadRate(double rate) {
@@ -168,7 +188,7 @@
   DCHECK_LE(rate, 1.0);
   DCHECK(profile_);
   PrefService* preferences = profile_->GetPrefs();
-  preferences->SetReal(prefs::kAutoFillNegativeUploadRate, rate);
+  preferences->SetDouble(prefs::kAutoFillNegativeUploadRate, rate);
 }
 
 bool AutoFillDownloadManager::StartRequest(
@@ -180,11 +200,6 @@
   else
     request_url = AUTO_FILL_UPLOAD_SERVER_REQUEST_URL;
 
-  if (!request_url.compare(DISABLED_REQUEST_URL) && !is_testing_) {
-    // We have it disabled - return true as if it succeeded, but do nothing.
-    return true;
-  }
-
   // Id is ignored for regular chrome, in unit test id's for fake fetcher
   // factory will be 0, 1, 2, ...
   URLFetcher *fetcher = URLFetcher::Create(fetcher_id_for_unittest_++,
@@ -205,6 +220,60 @@
   return true;
 }
 
+void AutoFillDownloadManager::CacheQueryRequest(
+    const std::vector<std::string>& forms_in_query,
+    const std::string& query_data) {
+  std::string signature = GetCombinedSignature(forms_in_query);
+  for (QueryRequestCache::iterator it = cached_forms_.begin();
+       it != cached_forms_.end(); ++it) {
+    if (it->first == signature) {
+      // We hit the cache, move to the first position and return.
+      std::pair<std::string, std::string> data = *it;
+      cached_forms_.erase(it);
+      cached_forms_.push_front(data);
+      return;
+    }
+  }
+  std::pair<std::string, std::string> data;
+  data.first = signature;
+  data.second = query_data;
+  cached_forms_.push_front(data);
+  while (cached_forms_.size() > max_form_cache_size_)
+    cached_forms_.pop_back();
+}
+
+bool AutoFillDownloadManager::CheckCacheForQueryRequest(
+    const std::vector<std::string>& forms_in_query,
+    std::string* query_data) const {
+  std::string signature = GetCombinedSignature(forms_in_query);
+  for (QueryRequestCache::const_iterator it = cached_forms_.begin();
+       it != cached_forms_.end(); ++it) {
+    if (it->first == signature) {
+      // We hit the cache, fill the data and return.
+      *query_data = it->second;
+      return true;
+    }
+  }
+  return false;
+}
+
+std::string AutoFillDownloadManager::GetCombinedSignature(
+    const std::vector<std::string>& forms_in_query) const {
+  size_t total_size = forms_in_query.size();
+  for (size_t i = 0; i < forms_in_query.size(); ++i)
+    total_size += forms_in_query[i].length();
+  std::string signature;
+
+  signature.reserve(total_size);
+
+  for (size_t i = 0; i < forms_in_query.size(); ++i) {
+    if (i)
+      signature.append(",");
+    signature.append(forms_in_query[i]);
+  }
+  return signature;
+}
+
 void AutoFillDownloadManager::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
@@ -267,6 +336,7 @@
     VLOG(1) << "AutoFillDownloadManager: " << type_of_request
             << " request has succeeded";
     if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) {
+      CacheQueryRequest(it->second.form_signatures, data);
       if (observer_)
         observer_->OnLoadedAutoFillHeuristics(data);
     } else {
diff --git a/chrome/browser/autofill/autofill_download.h b/chrome/browser/autofill/autofill_download.h
index 01fda7f..3c8d4dd 100644
--- a/chrome/browser/autofill/autofill_download.h
+++ b/chrome/browser/autofill/autofill_download.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_AUTOFILL_AUTOFILL_DOWNLOAD_H_
 #pragma once
 
+#include <list>
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/scoped_vector.h"
 #include "base/time.h"
@@ -89,7 +91,7 @@
   // GetNegativeUploadRate() for non matched.
   double GetPositiveUploadRate() const;
   double GetNegativeUploadRate() const;
-  // These functions called very rarely outside of theunit-tests. With current
+  // These functions called very rarely outside of the unit-tests. With current
   // percentages, they would be called once per 100 auto-fillable forms filled
   // and submitted by user. The order of magnitude would remain similar in the
   // future.
@@ -100,6 +102,7 @@
   friend class AutoFillDownloadTestHelper;  // unit-test.
 
   struct FormRequestData;
+  typedef std::list<std::pair<std::string, std::string> > QueryRequestCache;
 
   // Initiates request to AutoFill servers to download/upload heuristics.
   // |form_xml| - form structure XML to upload/download.
@@ -110,6 +113,25 @@
   bool StartRequest(const std::string& form_xml,
                     const FormRequestData& request_data);
 
+  // Each request is page visited. We store last |max_form_cache_size|
+  // request, to avoid going over the wire. Set to 16 in constructor. Warning:
+  // the search is linear (newest first), so do not make the constant very big.
+  void set_max_form_cache_size(size_t max_form_cache_size) {
+    max_form_cache_size_ = max_form_cache_size;
+  }
+
+  // Caches query request. |forms_in_query| is a vector of form signatures in
+  // the query. |query_data| is the successful data returned over the wire.
+  void CacheQueryRequest(const std::vector<std::string>& forms_in_query,
+                         const std::string& query_data);
+  // Returns true if query is in the cache, while filling |query_data|, false
+  // otherwise. |forms_in_query| is a vector of form signatures in the query.
+  bool CheckCacheForQueryRequest(const std::vector<std::string>& forms_in_query,
+                                 std::string* query_data) const;
+  // Concatenates |forms_in_query| into one signature.
+  std::string GetCombinedSignature(
+      const std::vector<std::string>& forms_in_query) const;
+
   // URLFetcher::Delegate implementation:
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
@@ -127,6 +149,10 @@
   std::map<URLFetcher*, FormRequestData> url_fetchers_;
   AutoFillDownloadManager::Observer *observer_;
 
+  // Cached QUERY requests.
+  QueryRequestCache cached_forms_;
+  size_t max_form_cache_size_;
+
   // Time when next query/upload requests are allowed. If 50x HTTP received,
   // exponential back off is initiated, so this times will be in the future
   // for awhile.
@@ -140,7 +166,6 @@
 
   // Needed for unit-test.
   int fetcher_id_for_unittest_;
-  bool is_testing_;
 };
 
 #endif  // CHROME_BROWSER_AUTOFILL_AUTOFILL_DOWNLOAD_H_
diff --git a/chrome/browser/autofill/autofill_download_unittest.cc b/chrome/browser/autofill/autofill_download_unittest.cc
index a2f9d78..099df01 100644
--- a/chrome/browser/autofill/autofill_download_unittest.cc
+++ b/chrome/browser/autofill/autofill_download_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
 #include "net/url_request/url_request_status.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
 #include "webkit/glue/form_data.h"
 
 using webkit_glue::FormData;
@@ -46,13 +46,15 @@
   AutoFillDownloadTestHelper()
       : download_manager(&profile) {
     download_manager.SetObserver(this);
-    // For chromium builds forces Start*Request to actually execute.
-    download_manager.is_testing_ = true;
   }
   ~AutoFillDownloadTestHelper() {
     download_manager.SetObserver(NULL);
   }
 
+  void LimitCache(size_t cache_size) {
+    download_manager.set_max_form_cache_size(cache_size);
+  }
+
   // AutoFillDownloadManager::Observer overridables:
   virtual void OnLoadedAutoFillHeuristics(
       const std::string& heuristic_xml) {
@@ -61,7 +63,6 @@
     response.type_of_response = QUERY_SUCCESSFULL;
     responses_.push_back(response);
   };
-
   virtual void OnUploadedAutoFillHeuristics(const std::string& form_signature) {
     ResponseData response;
     response.type_of_response = UPLOAD_SUCCESSFULL;
@@ -219,7 +220,8 @@
   // Return them out of sequence.
   TestURLFetcher* fetcher = factory.GetFetcherByID(1);
   ASSERT_TRUE(fetcher);
-  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(),
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
                                           200, ResponseCookies(),
                                           std::string(responses[1]));
   // After that upload rates would be adjusted to 0.5/0.3
@@ -228,12 +230,14 @@
 
   fetcher = factory.GetFetcherByID(2);
   ASSERT_TRUE(fetcher);
-  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(),
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
                                           404, ResponseCookies(),
                                           std::string(responses[2]));
   fetcher = factory.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
-  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(),
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
                                           200, ResponseCookies(),
                                           std::string(responses[0]));
   EXPECT_EQ(static_cast<size_t>(3), helper.responses_.size());
@@ -273,6 +277,16 @@
   fetcher = factory.GetFetcherByID(3);
   EXPECT_EQ(NULL, fetcher);
 
+  // Modify form structures to miss the cache.
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address line 2"),
+                                               ASCIIToUTF16("address2"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false));
+  form_structure = new FormStructure(form);
+  form_structures.push_back(form_structure);
+
   // Request with id 3.
   EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures,
@@ -281,7 +295,8 @@
   ASSERT_TRUE(fetcher);
   fetcher->set_backoff_delay(
       base::TimeDelta::FromMilliseconds(TestTimeouts::action_max_timeout_ms()));
-  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(),
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
                                           500, ResponseCookies(),
                                           std::string(responses[0]));
   EXPECT_EQ(AutoFillDownloadTestHelper::REQUEST_QUERY_FAILED,
@@ -307,7 +322,8 @@
   ASSERT_TRUE(fetcher);
   fetcher->set_backoff_delay(
       base::TimeDelta::FromMilliseconds(TestTimeouts::action_max_timeout_ms()));
-  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(), URLRequestStatus(),
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
                                           503, ResponseCookies(),
                                           std::string(responses[2]));
   EXPECT_EQ(AutoFillDownloadTestHelper::REQUEST_UPLOAD_FAILED,
@@ -324,3 +340,178 @@
   // Make sure consumer of URLFetcher does the right thing.
   URLFetcher::set_factory(NULL);
 }
+
+TEST(AutoFillDownloadTest, CacheQueryTest) {
+  MessageLoopForUI message_loop;
+  AutoFillDownloadTestHelper helper;
+  // Create and register factory.
+  TestURLFetcherFactory factory;
+  URLFetcher::set_factory(&factory);
+
+  FormData form;
+  form.method = ASCIIToUTF16("post");
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("username"),
+                                               ASCIIToUTF16("username"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false));
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
+                                               ASCIIToUTF16("firstname"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false));
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
+                                               ASCIIToUTF16("lastname"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false));
+  FormStructure *form_structure = new FormStructure(form);
+  ScopedVector<FormStructure> form_structures0;
+  form_structures0.push_back(form_structure);
+
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"),
+                                               ASCIIToUTF16("email"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false));
+  // Slightly different form - so different request.
+  form_structure = new FormStructure(form);
+  ScopedVector<FormStructure> form_structures1;
+  form_structures1.push_back(form_structure);
+
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email2"),
+                                               ASCIIToUTF16("email2"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false));
+  // Slightly different form - so different request.
+  form_structure = new FormStructure(form);
+  ScopedVector<FormStructure> form_structures2;
+  form_structures2.push_back(form_structure);
+
+  // Limit cache to two forms.
+  helper.LimitCache(2);
+
+  const char *responses[] = {
+    "<autofillqueryresponse>"
+      "<field autofilltype=\"0\" />"
+      "<field autofilltype=\"3\" />"
+      "<field autofilltype=\"5\" />"
+    "</autofillqueryresponse>",
+    "<autofillqueryresponse>"
+      "<field autofilltype=\"0\" />"
+      "<field autofilltype=\"3\" />"
+      "<field autofilltype=\"5\" />"
+      "<field autofilltype=\"9\" />"
+    "</autofillqueryresponse>",
+    "<autofillqueryresponse>"
+      "<field autofilltype=\"0\" />"
+      "<field autofilltype=\"3\" />"
+      "<field autofilltype=\"5\" />"
+      "<field autofilltype=\"9\" />"
+      "<field autofilltype=\"0\" />"
+    "</autofillqueryresponse>",
+  };
+
+  // Request with id 0.
+  MockAutoFillMetrics mock_metric_logger;
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures0,
+                                                        mock_metric_logger));
+  // No responses yet
+  EXPECT_EQ(static_cast<size_t>(0), helper.responses_.size());
+
+  TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+  ASSERT_TRUE(fetcher);
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
+                                          200, ResponseCookies(),
+                                          std::string(responses[0]));
+  ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
+  EXPECT_EQ(responses[0], helper.responses_.front().response);
+
+  helper.responses_.clear();
+
+  // No actual request - should be a cache hit.
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures0,
+                                                        mock_metric_logger));
+  // Data is available immediately from cache - no over-the-wire trip.
+  ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
+  EXPECT_EQ(responses[0], helper.responses_.front().response);
+  helper.responses_.clear();
+
+  // Request with id 1.
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures1,
+                                                        mock_metric_logger));
+  // No responses yet
+  EXPECT_EQ(static_cast<size_t>(0), helper.responses_.size());
+
+  fetcher = factory.GetFetcherByID(1);
+  ASSERT_TRUE(fetcher);
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
+                                          200, ResponseCookies(),
+                                          std::string(responses[1]));
+  ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
+  EXPECT_EQ(responses[1], helper.responses_.front().response);
+
+  helper.responses_.clear();
+
+  // Request with id 2.
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures2,
+                                                        mock_metric_logger));
+
+  fetcher = factory.GetFetcherByID(2);
+  ASSERT_TRUE(fetcher);
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
+                                          200, ResponseCookies(),
+                                          std::string(responses[2]));
+  ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
+  EXPECT_EQ(responses[2], helper.responses_.front().response);
+
+  helper.responses_.clear();
+
+  // No actual requests - should be a cache hit.
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures1,
+                                                        mock_metric_logger));
+
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures2,
+                                                        mock_metric_logger));
+
+  ASSERT_EQ(static_cast<size_t>(2), helper.responses_.size());
+  EXPECT_EQ(responses[1], helper.responses_.front().response);
+  EXPECT_EQ(responses[2], helper.responses_.back().response);
+  helper.responses_.clear();
+
+  // The first structure should've expired.
+  // Request with id 3.
+  EXPECT_CALL(mock_metric_logger, Log(AutoFillMetrics::QUERY_SENT)).Times(1);
+  EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures0,
+                                                        mock_metric_logger));
+  // No responses yet
+  EXPECT_EQ(static_cast<size_t>(0), helper.responses_.size());
+
+  fetcher = factory.GetFetcherByID(3);
+  ASSERT_TRUE(fetcher);
+  fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
+                                          net::URLRequestStatus(),
+                                          200, ResponseCookies(),
+                                          std::string(responses[0]));
+  ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
+  EXPECT_EQ(responses[0], helper.responses_.front().response);
+
+  // Make sure consumer of URLFetcher does the right thing.
+  URLFetcher::set_factory(NULL);
+}
+
diff --git a/chrome/browser/autofill/autofill_editor_gtk.cc b/chrome/browser/autofill/autofill_editor_gtk.cc
index 3cdec02..3c05cf5 100644
--- a/chrome/browser/autofill/autofill_editor_gtk.cc
+++ b/chrome/browser/autofill/autofill_editor_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,6 @@
 
 #include <gtk/gtk.h>
 
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/task.h"
@@ -17,12 +14,15 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/autofill/phone_number.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -723,9 +723,11 @@
   }
 
   int year;
-  base::StringToInt(
-      card->GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)),
-      &year);
+  if (!base::StringToInt(
+          card->GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)),
+          &year)) {
+    NOTREACHED();
+  }
   if (year >= base_year_ && year < base_year_ + kNumYears)
     gtk_combo_box_set_active(GTK_COMBO_BOX(year_), year - base_year_);
   else
diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
index 05b7ade..3519de1 100644
--- a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
+++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
@@ -57,12 +57,13 @@
 string16 ReadAndDecryptValue(RegKey* key, const wchar_t* value_name) {
   DWORD data_type = REG_BINARY;
   DWORD data_size = 0;
-  if (!key->ReadValue(value_name, NULL, &data_size, &data_type) ||
-      !data_size || data_type != REG_BINARY)
+  LONG result = key->ReadValue(value_name, NULL, &data_size, &data_type);
+  if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY)
     return string16();
   std::vector<uint8> data;
   data.resize(data_size);
-  if (key->ReadValue(value_name, &(data[0]), &data_size, &data_type)) {
+  result = key->ReadValue(value_name, &(data[0]), &data_size, &data_type);
+  if (result == ERROR_SUCCESS) {
     std::string out_data;
     if (DecryptData(data, &out_data)) {
       // The actual data is in UTF16 already.
@@ -125,7 +126,7 @@
 
   for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) {
     std::wstring value_name;
-    if (!key->ReadName(value_index, &value_name))
+    if (key->ReadName(value_index, &value_name) != ERROR_SUCCESS)
       continue;
     RegToFieldMap::const_iterator it = reg_to_field.find(value_name);
     if (it == reg_to_field.end())
diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc
index 17e85db..972badb 100644
--- a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc
+++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc
@@ -92,8 +92,8 @@
   memcpy(&data[0], value->value, data_size);
 
   std::vector<uint8> encrypted_data = EncryptData(data);
-  EXPECT_TRUE(key->WriteValue(value->value_name, &encrypted_data[0],
-                              encrypted_data.size(), REG_BINARY));
+  EXPECT_EQ(ERROR_SUCCESS, key->WriteValue(value->value_name,
+      &encrypted_data[0], encrypted_data.size(), REG_BINARY));
 }
 
 void CreateSubkey(RegKey* key, wchar_t const* subkey_name,
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index faba5a2..93215eb 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -1,17 +1,23 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/autofill/autofill_manager.h"
 
 #include <limits>
+#include <map>
 #include <set>
+#include <utility>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
+#include "base/command_line.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
+<<<<<<< HEAD
 #ifndef ANDROID
+=======
+#include "chrome/browser/autocomplete_history_manager.h"
+>>>>>>> chromium.org at r11.0.672.0
 #include "chrome/browser/autofill/autofill_cc_infobar_delegate.h"
 #endif
 #include "chrome/browser/autofill/autofill_dialog.h"
@@ -25,11 +31,17 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #endif
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/autofill_messages.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/guid.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/glue/form_data.h"
 #ifdef ANDROID
 #include <WebCoreSupport/autofill/FormFieldAndroid.h>
@@ -47,8 +59,8 @@
 const double kAutoFillPositiveUploadRateDefaultValue = 0.01;
 const double kAutoFillNegativeUploadRateDefaultValue = 0.01;
 
-const string16::value_type kCreditCardPrefix[] = {'*',0};
-const string16::value_type kLabelSeparator[] = {';',' ','*',0};
+const string16::value_type kCreditCardPrefix[] = {'*', 0};
+const string16::value_type kLabelSeparator[] = {';', ' ', '*', 0};
 
 // Removes duplicate suggestions whilst preserving their original order.
 void RemoveDuplicateSuggestions(std::vector<string16>* values,
@@ -81,13 +93,93 @@
   unique_ids->swap(unique_ids_copy);
 }
 
+// Precondition: |form| should be the cached version of the form that is to be
+// autofilled, and |field| should be the field in the |form| that corresponds to
+// the initiating field. |is_filling_credit_card| should be true if filling
+// credit card data, false otherwise.
+// Fills |section_start| and |section_end| so that [section_start, section_end)
+// gives the bounds of logical section within |form| that includes |field|.
+// Logical sections are identified by two heuristics:
+//  1. The fields in the section must all be profile or credit card fields,
+//     depending on whether |is_filling_credit_card| is true.
+//  2. A logical section should not include multiple fields of the same autofill
+//     type (except for phone/fax numbers, as described below).
+void FindSectionBounds(const FormStructure& form,
+                       const AutoFillField& field,
+                       bool is_filling_credit_card,
+                       size_t* section_start,
+                       size_t* section_end) {
+  DCHECK(section_start);
+  DCHECK(section_end);
+
+  // By default, the relevant section is the entire form.
+  *section_start = 0;
+  *section_end = form.field_count();
+
+  std::set<AutoFillFieldType> seen_types;
+  bool initiating_field_is_in_current_section = false;
+  for (size_t i = 0; i < form.field_count(); ++i) {
+    const AutoFillField* current_field = form.field(i);
+    const AutoFillFieldType current_type =
+        AutoFillType::GetEquivalentFieldType(current_field->type());
+
+    // Fields of unknown type don't help us to distinguish sections.
+    if (current_type == UNKNOWN_TYPE)
+      continue;
+
+    bool already_saw_current_type = seen_types.count(current_type) > 0;
+    // Forms often ask for multiple phone numbers -- e.g. both a daytime and
+    // evening phone number.  Our phone and fax number detection is also
+    // generally a little off.  Hence, ignore both field types as a signal here.
+    AutoFillType::FieldTypeGroup current_type_group =
+        AutoFillType(current_type).group();
+    if (current_type_group == AutoFillType::PHONE_HOME ||
+        current_type_group == AutoFillType::PHONE_FAX)
+      already_saw_current_type = false;
+
+    // If we are filling credit card data, the relevant section should include
+    // only credit card fields; and similarly for profile data.
+    bool is_credit_card_field = current_type_group == AutoFillType::CREDIT_CARD;
+    bool is_appropriate_type = is_credit_card_field == is_filling_credit_card;
+
+    if (already_saw_current_type || !is_appropriate_type) {
+      if (initiating_field_is_in_current_section) {
+        // We reached the end of the section containing the initiating field.
+        *section_end = i;
+        break;
+      }
+
+      // We reached the end of a section, so start a new section.
+      seen_types.clear();
+
+      // Only include the current field in the new section if it matches the
+      // type of data we are filling.
+      if (is_appropriate_type) {
+        *section_start = i;
+      } else {
+        *section_start = i + 1;
+        continue;
+      }
+    }
+
+    seen_types.insert(current_type);
+
+    if (current_field == &field)
+      initiating_field_is_in_current_section = true;
+  }
+
+  // We should have found the initiating field.
+  DCHECK(initiating_field_is_in_current_section);
+}
+
 // Precondition: |form_structure| and |form| should correspond to the same
 // logical form. Returns true if the relevant portion of |form| is auto-filled.
-// If |is_filling_credit_card|, the relevant portion is the credit card portion;
-// otherwise it is the address and contact info portion.
-bool FormIsAutoFilled(const FormStructure* form_structure,
-                      const webkit_glue::FormData& form,
-                      bool is_filling_credit_card) {
+// The "relevant" fields in |form| are ones corresponding to fields in
+// |form_structure| with indices in the range [section_start, section_end).
+bool SectionIsAutoFilled(const FormStructure* form_structure,
+                         const webkit_glue::FormData& form,
+                         size_t section_start,
+                         size_t section_end) {
   // TODO(isherman): It would be nice to share most of this code with the loop
   // in |FillAutoFillFormData()|, but I don't see a particularly clean way to do
   // that.
@@ -96,8 +188,8 @@
   // directly and we can fill these corresponding fields; however, when the
   // |form_structure| and |form.fields| do not match directly we search
   // ahead in the |form_structure| for the matching field.
-  for (size_t i = 0, j = 0;
-       i < form_structure->field_count() && j < form.fields.size();
+  for (size_t i = section_start, j = 0;
+       i < section_end && j < form.fields.size();
        j++) {
     size_t k = i;
 
@@ -112,10 +204,7 @@
       continue;
 
     AutoFillType autofill_type(form_structure->field(k)->type());
-    bool is_credit_card_field =
-        autofill_type.group() == AutoFillType::CREDIT_CARD;
-    if (is_filling_credit_card == is_credit_card_field &&
-        form.fields[j].is_autofilled())
+    if (form.fields[j].is_autofilled())
       return true;
 
     // We found a matching field in the |form_structure| so we
@@ -164,13 +253,43 @@
 #else
   prefs->RegisterBooleanPref(prefs::kAutoFillAuxiliaryProfilesEnabled, false);
 #endif
-  prefs->RegisterRealPref(prefs::kAutoFillPositiveUploadRate,
-                          kAutoFillPositiveUploadRateDefaultValue);
-  prefs->RegisterRealPref(prefs::kAutoFillNegativeUploadRate,
-                          kAutoFillNegativeUploadRateDefaultValue);
+  prefs->RegisterDoublePref(prefs::kAutoFillPositiveUploadRate,
+                            kAutoFillPositiveUploadRateDefaultValue);
+  prefs->RegisterDoublePref(prefs::kAutoFillNegativeUploadRate,
+                            kAutoFillNegativeUploadRateDefaultValue);
 }
 
-void AutoFillManager::FormSubmitted(const FormData& form) {
+void AutoFillManager::DidNavigateMainFramePostCommit(
+    const NavigationController::LoadCommittedDetails& details,
+    const ViewHostMsg_FrameNavigate_Params& params) {
+  Reset();
+}
+
+bool AutoFillManager::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(AutoFillManager, message)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_FormsSeen, OnFormsSeen)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_FormSubmitted, OnFormSubmitted)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_QueryFormFieldAutoFill,
+                        OnQueryFormFieldAutoFill)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_ShowAutoFillDialog,
+                        OnShowAutoFillDialog)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_FillAutoFillFormData,
+                        OnFillAutoFillFormData)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_DidFillAutoFillFormData,
+                        OnDidFillAutoFillFormData)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_DidShowAutoFillSuggestions,
+                        OnDidShowAutoFillSuggestions)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+
+  return handled;
+}
+
+void AutoFillManager::OnFormSubmitted(const FormData& form) {
+  // Let AutoComplete know as well.
+  tab_contents_->autocomplete_history_manager()->OnFormSubmitted(form);
+
   if (!IsAutoFillEnabled())
     return;
 
@@ -182,29 +301,31 @@
     return;
 
   // Grab a copy of the form data.
-  upload_form_structure_.reset(new FormStructure(form));
+  FormStructure submitted_form(form);
 
   // Disregard forms that we wouldn't ever autofill in the first place.
-  if (!upload_form_structure_->ShouldBeParsed(true))
+  if (!submitted_form.ShouldBeParsed(true))
     return;
 
-  DeterminePossibleFieldTypesForUpload();
-  // TODO(isherman): Consider uploading to server here rather than in
-  // HandleSubmit().
+  DeterminePossibleFieldTypesForUpload(&submitted_form);
+  LogMetricsAboutSubmittedForm(form, &submitted_form);
 
-  if (!upload_form_structure_->IsAutoFillable(true))
+  UploadFormData(submitted_form);
+
+  if (!submitted_form.IsAutoFillable(true))
     return;
 
-  HandleSubmit();
+  ImportFormData(submitted_form);
 }
 
-void AutoFillManager::FormsSeen(const std::vector<FormData>& forms) {
+void AutoFillManager::OnFormsSeen(const std::vector<FormData>& forms) {
   if (!IsAutoFillEnabled())
     return;
 
   ParseForms(forms);
 }
 
+<<<<<<< HEAD
 bool AutoFillManager::GetAutoFillSuggestions(const FormData& form,
                                              const FormField& field) {
 #ifdef ANDROID
@@ -228,29 +349,36 @@
   if (!form_structure->IsAutoFillable(false))
     return false;
 
+=======
+void AutoFillManager::OnQueryFormFieldAutoFill(
+    int query_id,
+    const webkit_glue::FormData& form,
+    const webkit_glue::FormField& field) {
+>>>>>>> chromium.org at r11.0.672.0
   std::vector<string16> values;
   std::vector<string16> labels;
   std::vector<string16> icons;
   std::vector<int> unique_ids;
 
-  AutoFillType type(autofill_field->type());
-  bool is_filling_credit_card = (type.group() == AutoFillType::CREDIT_CARD);
-  if (is_filling_credit_card) {
-    GetCreditCardSuggestions(
-        form_structure, field, type, &values, &labels, &icons, &unique_ids);
-  } else {
-    GetProfileSuggestions(
-        form_structure, field, type, &values, &labels, &icons, &unique_ids);
-  }
+  RenderViewHost* host = NULL;
+  FormStructure* form_structure = NULL;
+  AutoFillField* autofill_field = NULL;
+  if (GetHost(
+          personal_data_->profiles(), personal_data_->credit_cards(), &host) &&
+      FindCachedFormAndField(form, field, &form_structure, &autofill_field) &&
+      // Don't send suggestions for forms that aren't auto-fillable.
+      form_structure->IsAutoFillable(false)) {
+    AutoFillType type(autofill_field->type());
+    bool is_filling_credit_card = (type.group() == AutoFillType::CREDIT_CARD);
+    if (is_filling_credit_card) {
+      GetCreditCardSuggestions(
+          form_structure, field, type, &values, &labels, &icons, &unique_ids);
+    } else {
+      GetProfileSuggestions(
+          form_structure, field, type, &values, &labels, &icons, &unique_ids);
+    }
 
-  DCHECK_EQ(values.size(), labels.size());
-  DCHECK_EQ(values.size(), icons.size());
-  DCHECK_EQ(values.size(), unique_ids.size());
-
-  // No suggestions.
-  if (values.empty())
-    return false;
-
+<<<<<<< HEAD
 #ifndef ANDROID
   // Don't provide AutoFill suggestions when AutoFill is disabled, and don't
   // provide credit card suggestions for non-HTTPS pages. However, provide a
@@ -269,25 +397,56 @@
     return true;
   }
 #endif
+=======
+    DCHECK_EQ(values.size(), labels.size());
+    DCHECK_EQ(values.size(), icons.size());
+    DCHECK_EQ(values.size(), unique_ids.size());
 
-  // If the form is auto-filled and the renderer is querying for suggestions,
-  // then the user is editing the value of a field. In this case, mimic
-  // autocomplete: don't display labels or icons, as that information is
-  // redundant.
-  if (FormIsAutoFilled(form_structure, form, is_filling_credit_card)) {
-    labels.assign(labels.size(), string16());
-    icons.assign(icons.size(), string16());
+    if (!values.empty()) {
+      // Don't provide AutoFill suggestions when AutoFill is disabled, and don't
+      // provide credit card suggestions for non-HTTPS pages. However, provide a
+      // warning to the user in these cases.
+      int warning = 0;
+      if (!form_structure->IsAutoFillable(true))
+        warning = IDS_AUTOFILL_WARNING_FORM_DISABLED;
+      else if (is_filling_credit_card && !FormIsHTTPS(form_structure))
+        warning = IDS_AUTOFILL_WARNING_INSECURE_CONNECTION;
+      if (warning) {
+        values.assign(1, l10n_util::GetStringUTF16(warning));
+        labels.assign(1, string16());
+        icons.assign(1, string16());
+        unique_ids.assign(1, -1);
+      } else {
+        size_t section_start, section_end;
+        FindSectionBounds(*form_structure, *autofill_field,
+                          is_filling_credit_card, &section_start, &section_end);
+        if (SectionIsAutoFilled(form_structure, form, section_start,
+                                section_end)) {
+          // If the relevant section is auto-filled and the renderer is querying
+          // for suggestions, then the user is editing the value of a field.
+          // In this case, mimic autocomplete: don't display labels or icons,
+          // as that information is redundant.
+          labels.assign(labels.size(), string16());
+          icons.assign(icons.size(), string16());
+        }
+>>>>>>> chromium.org at r11.0.672.0
+
+        RemoveDuplicateSuggestions(&values, &labels, &icons, &unique_ids);
+      }
+    }
   }
 
-  RemoveDuplicateSuggestions(&values, &labels, &icons, &unique_ids);
-  host->AutoFillSuggestionsReturned(values, labels, icons, unique_ids);
-  return true;
+  // Add the results from AutoComplete.  They come back asynchronously, so we
+  // hand off what we generated and they will send the results back to the
+  // renderer.
+  tab_contents_->autocomplete_history_manager()->OnGetAutocompleteSuggestions(
+      query_id, field.name(), field.value(), values, labels, icons, unique_ids);
 }
 
-bool AutoFillManager::FillAutoFillFormData(int query_id,
-                                           const FormData& form,
-                                           const FormField& field,
-                                           int unique_id) {
+void AutoFillManager::OnFillAutoFillFormData(int query_id,
+                                             const FormData& form,
+                                             const FormField& field,
+                                             int unique_id) {
   const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles();
   const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
 #ifdef ANDROID
@@ -299,7 +458,7 @@
   AutoFillField* autofill_field = NULL;
   if (!GetHost(profiles, credit_cards, &host) ||
       !FindCachedFormAndField(form, field, &form_structure, &autofill_field))
-    return false;
+    return;
 
   DCHECK(host);
   DCHECK(form_structure);
@@ -338,30 +497,36 @@
   }
 
   if (!profile && !credit_card)
-    return false;
+    return;
+
+  // Find the section of the form that we are autofilling.
+  size_t section_start, section_end;
+  FindSectionBounds(*form_structure, *autofill_field, (credit_card != NULL),
+                    &section_start, &section_end);
 
   FormData result = form;
 
-  // If the form is auto-filled, we should fill |field| but not the rest of the
-  // form.
-  if (FormIsAutoFilled(form_structure, form, (credit_card != NULL))) {
+  // If the relevant section is auto-filled, we should fill |field| but not the
+  // rest of the form.
+  if (SectionIsAutoFilled(form_structure, form, section_start, section_end)) {
     for (std::vector<FormField>::iterator iter = result.fields.begin();
          iter != result.fields.end(); ++iter) {
       if ((*iter) == field) {
         AutoFillType autofill_type(autofill_field->type());
-        if (credit_card &&
-            autofill_type.group() == AutoFillType::CREDIT_CARD) {
-          FillCreditCardFormField(credit_card, autofill_type, &(*iter));
-        } else if (profile &&
-                   autofill_type.group() != AutoFillType::CREDIT_CARD) {
+        if (profile) {
+          DCHECK(autofill_type.group() != AutoFillType::CREDIT_CARD);
           FillFormField(profile, autofill_type, &(*iter));
+        } else {
+          DCHECK(autofill_type.group() == AutoFillType::CREDIT_CARD);
+          FillCreditCardFormField(credit_card, autofill_type, &(*iter));
         }
         break;
       }
     }
 
-    host->AutoFillFormDataFilled(query_id, result);
-    return true;
+    host->Send(new AutoFillMsg_FormDataFilled(host->routing_id(), query_id,
+                                              result));
+    return;
   }
 
   // The list of fields in |form_structure| and |result.fields| often match
@@ -370,30 +535,30 @@
   // ahead in the |form_structure| for the matching field.
   // See unit tests: AutoFillManagerTest.FormChangesRemoveField and
   // AutoFillManagerTest.FormChangesAddField for usage.
-  for (size_t i = 0, j = 0;
-       i < form_structure->field_count() && j < result.fields.size();
+  for (size_t i = section_start, j = 0;
+       i < section_end && j < result.fields.size();
        j++) {
     size_t k = i;
 
     // Search forward in the |form_structure| for a corresponding field.
-    while (k < form_structure->field_count() &&
-           *form_structure->field(k) != result.fields[j]) {
+    while (k < section_end && *form_structure->field(k) != result.fields[j]) {
       k++;
     }
 
     // If we've found a match then fill the |result| field with the found
     // field in the |form_structure|.
-    if (k >= form_structure->field_count())
+    if (k >= section_end)
       continue;
 
-    const AutoFillField* field = form_structure->field(k);
-    AutoFillType autofill_type(field->type());
-    if (credit_card &&
-        autofill_type.group() == AutoFillType::CREDIT_CARD) {
-      FillCreditCardFormField(credit_card, autofill_type, &result.fields[j]);
-    } else if (profile &&
-               autofill_type.group() != AutoFillType::CREDIT_CARD) {
-      FillFormField(profile, autofill_type, &result.fields[j]);
+    AutoFillType autofill_type(form_structure->field(k)->type());
+    if (autofill_type.group() != AutoFillType::NO_GROUP) {
+      if (profile) {
+        DCHECK(autofill_type.group() != AutoFillType::CREDIT_CARD);
+        FillFormField(profile, autofill_type, &result.fields[j]);
+      } else {
+        DCHECK(autofill_type.group() == AutoFillType::CREDIT_CARD);
+        FillCreditCardFormField(credit_card, autofill_type, &result.fields[j]);
+      }
     }
 
     // We found a matching field in the |form_structure| so we
@@ -402,21 +567,45 @@
   }
   autofilled_forms_signatures_.push_front(form_structure->FormSignature());
 
-  host->AutoFillFormDataFilled(query_id, result);
-  return true;
+  host->Send(new AutoFillMsg_FormDataFilled(
+      host->routing_id(), query_id, result));
 }
 
+void AutoFillManager::OnShowAutoFillDialog() {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableTabbedOptions)) {
+    Browser* browser = BrowserList::GetLastActive();
+    if (browser)
+      browser->ShowOptionsTab(chrome::kAutoFillSubPage);
+    return;
+  }
+
+  ShowAutoFillDialog(tab_contents_->GetContentNativeView(),
+                     personal_data_,
+                     tab_contents_->profile()->GetOriginalProfile());
+}
+
+<<<<<<< HEAD
 void AutoFillManager::ShowAutoFillDialog() {
 #ifndef ANDROID
   ::ShowAutoFillDialog(tab_contents_->GetContentNativeView(),
                        personal_data_,
                        tab_contents_->profile()->GetOriginalProfile());
 #endif
+=======
+void AutoFillManager::OnDidFillAutoFillFormData() {
+  NotificationService::current()->Notify(
+      NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
+      Source<RenderViewHost>(tab_contents_->render_view_host()),
+      NotificationService::NoDetails());
+>>>>>>> chromium.org at r11.0.672.0
 }
 
-void AutoFillManager::Reset() {
-  upload_form_structure_.reset();
-  form_structures_.reset();
+void AutoFillManager::OnDidShowAutoFillSuggestions() {
+  NotificationService::current()->Notify(
+      NotificationType::AUTOFILL_DID_SHOW_SUGGESTIONS,
+      Source<RenderViewHost>(tab_contents_->render_view_host()),
+      NotificationService::NoDetails());
 }
 
 void AutoFillManager::OnLoadedAutoFillHeuristics(
@@ -457,13 +646,40 @@
   return prefs->GetBoolean(prefs::kAutoFillEnabled);
 }
 
-void AutoFillManager::DeterminePossibleFieldTypesForUpload() {
-  for (size_t i = 0; i < upload_form_structure_->field_count(); i++) {
-    const AutoFillField* field = upload_form_structure_->field(i);
+void AutoFillManager::DeterminePossibleFieldTypesForUpload(
+    FormStructure* submitted_form) {
+  for (size_t i = 0; i < submitted_form->field_count(); i++) {
+    const AutoFillField* field = submitted_form->field(i);
+    FieldTypeSet field_types;
+    personal_data_->GetPossibleFieldTypes(field->value(), &field_types);
+
+    DCHECK(!field_types.empty());
+    submitted_form->set_possible_types(i, field_types);
+  }
+}
+
+void AutoFillManager::LogMetricsAboutSubmittedForm(
+    const FormData& form,
+    const FormStructure* submitted_form) {
+  FormStructure* cached_submitted_form;
+  if (!FindCachedForm(form, &cached_submitted_form)) {
+    NOTREACHED();
+    return;
+  }
+
+  // Map from field signatures to cached fields.
+  std::map<std::string, const AutoFillField*> cached_fields;
+  for (size_t i = 0; i < cached_submitted_form->field_count(); ++i) {
+    const AutoFillField* field = cached_submitted_form->field(i);
+    cached_fields[field->FieldSignature()] = field;
+  }
+
+  std::string experiment_id = cached_submitted_form->server_experiment_id();
+  for (size_t i = 0; i < submitted_form->field_count(); ++i) {
+    const AutoFillField* field = submitted_form->field(i);
     FieldTypeSet field_types;
     personal_data_->GetPossibleFieldTypes(field->value(), &field_types);
     DCHECK(!field_types.empty());
-    upload_form_structure_->set_possible_types(i, field_types);
 
     if (field->form_control_type() == ASCIIToUTF16("select-one")) {
       // TODO(isherman): <select> fields don't support |is_autofilled()|. Since
@@ -473,16 +689,48 @@
     }
 
     // Log various quality metrics.
-    metric_logger_->Log(AutoFillMetrics::FIELD_SUBMITTED);
+    metric_logger_->Log(AutoFillMetrics::FIELD_SUBMITTED, experiment_id);
     if (field_types.find(EMPTY_TYPE) == field_types.end() &&
         field_types.find(UNKNOWN_TYPE) == field_types.end()) {
-      if (field->is_autofilled())
-         metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILLED);
-      else
-         metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED);
+      if (field->is_autofilled()) {
+        metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILLED, experiment_id);
+      } else {
+        metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED,
+                            experiment_id);
+
+        AutoFillFieldType heuristic_type = UNKNOWN_TYPE;
+        AutoFillFieldType server_type = NO_SERVER_DATA;
+        std::map<std::string, const AutoFillField*>::const_iterator
+            cached_field = cached_fields.find(field->FieldSignature());
+        if (cached_field != cached_fields.end()) {
+          heuristic_type = cached_field->second->heuristic_type();
+          server_type = cached_field->second->server_type();
+        }
+
+        if (heuristic_type == UNKNOWN_TYPE) {
+          metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+                              experiment_id);
+        } else if (field_types.count(heuristic_type)) {
+          metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH,
+                              experiment_id);
+        } else {
+          metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH,
+                              experiment_id);
+        }
+
+        if (server_type == NO_SERVER_DATA) {
+          metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN,
+                              experiment_id);
+        } else if (field_types.count(server_type)) {
+          metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_MATCH,
+                              experiment_id);
+        } else {
+          metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH,
+                              experiment_id);
+        }
+      }
 
       // TODO(isherman): Other things we might want to log here:
-      // * Did the field's heuristic type match the PDM type?
       // * Per Vadim's email, a combination of (1) whether heuristics fired,
       //   (2) whether the server returned something interesting, (3) whether
       //   the user filled the field
@@ -492,37 +740,32 @@
   }
 }
 
-void AutoFillManager::HandleSubmit() {
-  // If there wasn't enough data to import then we don't want to send an upload
-  // to the server.
-  // TODO(jhawkins): Import form data from |form_structures_|.  That will
-  // require querying the FormManager for updated field values.
-  std::vector<FormStructure*> import;
-  import.push_back(upload_form_structure_.get());
-  if (!personal_data_->ImportFormData(import))
+void AutoFillManager::ImportFormData(const FormStructure& submitted_form) {
+  std::vector<const FormStructure*> import;
+  import.push_back(&submitted_form);
+
+  const CreditCard* imported_credit_card;
+  if (!personal_data_->ImportFormData(import, &imported_credit_card))
     return;
 
-  // Did we get credit card info?
-  AutoFillProfile* profile;
-  CreditCard* credit_card;
-  personal_data_->GetImportedFormData(&profile, &credit_card);
-
-  if (!credit_card) {
-    UploadFormData();
-    return;
-  }
-
+<<<<<<< HEAD
 #ifndef ANDROID
   // Show an infobar to offer to save the credit card info.
   if (tab_contents_) {
+=======
+  // If credit card information was submitted, show an infobar to offer to save
+  // it.
+  if (imported_credit_card && tab_contents_) {
+    imported_credit_card_.reset(imported_credit_card);
+>>>>>>> chromium.org at r11.0.672.0
     tab_contents_->AddInfoBar(new AutoFillCCInfoBarDelegate(tab_contents_,
                                                             this));
   }
 #endif
 }
 
-void AutoFillManager::UploadFormData() {
-  if (!disable_download_manager_requests_ && upload_form_structure_.get()) {
+void AutoFillManager::UploadFormData(const FormStructure& submitted_form) {
+  if (!disable_download_manager_requests_) {
     bool was_autofilled = false;
     // Check if the form among last 3 forms that were auto-filled.
     // Clear older signatures.
@@ -531,7 +774,7 @@
     for (it = autofilled_forms_signatures_.begin();
          it != autofilled_forms_signatures_.end() && total_form_checked < 3;
          ++it, ++total_form_checked) {
-      if (*it == upload_form_structure_->FormSignature())
+      if (*it == submitted_form.FormSignature())
         was_autofilled = true;
     }
     // Remove outdated form signatures.
@@ -539,15 +782,17 @@
       autofilled_forms_signatures_.erase(it,
                                          autofilled_forms_signatures_.end());
     }
-    download_manager_.StartUploadRequest(*(upload_form_structure_.get()),
-                                         was_autofilled);
+    download_manager_.StartUploadRequest(submitted_form, was_autofilled);
   }
 }
 
+void AutoFillManager::Reset() {
+  form_structures_.reset();
+}
+
 void AutoFillManager::OnInfoBarClosed(bool should_save) {
   if (should_save)
-    personal_data_->SaveImportedCreditCard();
-  UploadFormData();
+    personal_data_->SaveImportedCreditCard(*imported_credit_card_);
 }
 
 AutoFillManager::AutoFillManager()
@@ -593,17 +838,19 @@
   *host = tab_contents_->autofill_host();
 #else
   *host = tab_contents_->render_view_host();
+<<<<<<< HEAD
 #endif
   if (!(*host))
+=======
+  if (!*host)
+>>>>>>> chromium.org at r11.0.672.0
     return false;
 
   return true;
 }
 
-bool AutoFillManager::FindCachedFormAndField(const FormData& form,
-                                             const FormField& field,
-                                             FormStructure** form_structure,
-                                             AutoFillField** autofill_field) {
+bool AutoFillManager::FindCachedForm(const FormData& form,
+                                     FormStructure** form_structure) {
   // Find the FormStructure that corresponds to |form|.
   *form_structure = NULL;
   for (std::vector<FormStructure*>::const_iterator iter =
@@ -618,6 +865,17 @@
   if (!(*form_structure))
     return false;
 
+  return true;
+}
+
+bool AutoFillManager::FindCachedFormAndField(const FormData& form,
+                                             const FormField& field,
+                                             FormStructure** form_structure,
+                                             AutoFillField** autofill_field) {
+  // Find the FormStructure that corresponds to |form|.
+  if (!FindCachedForm(form, form_structure))
+    return false;
+
   // No data to return if there are no auto-fillable fields.
   if (!(*form_structure)->autofill_count())
     return false;
@@ -720,10 +978,22 @@
   DCHECK(type.group() == AutoFillType::CREDIT_CARD);
   DCHECK(field);
 
-  if (field->form_control_type() == ASCIIToUTF16("select-one"))
-    autofill::FillSelectControl(credit_card, type, field);
-  else
+  if (field->form_control_type() == ASCIIToUTF16("select-one")) {
+    autofill::FillSelectControl(*credit_card, type, field);
+  } else if (field->form_control_type() == ASCIIToUTF16("month")) {
+    // HTML5 input="month" consists of year-month.
+    string16 year = credit_card->GetFieldText(
+        AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+    string16 month = credit_card->GetFieldText(
+        AutoFillType(CREDIT_CARD_EXP_MONTH));
+    if (!year.empty() && !month.empty()) {
+      // Fill the value only if |credit_card| includes both year and month
+      // information.
+      field->set_value(year + ASCIIToUTF16("-") + month);
+    }
+  } else {
     field->set_value(credit_card->GetFieldText(type));
+  }
 }
 
 void AutoFillManager::FillFormField(const AutoFillProfile* profile,
@@ -734,20 +1004,21 @@
   DCHECK(field);
 
   if (type.subgroup() == AutoFillType::PHONE_NUMBER) {
-    FillPhoneNumberField(profile, field);
+    FillPhoneNumberField(profile, type, field);
   } else {
     if (field->form_control_type() == ASCIIToUTF16("select-one"))
-      autofill::FillSelectControl(profile, type, field);
+      autofill::FillSelectControl(*profile, type, field);
     else
       field->set_value(profile->GetFieldText(type));
   }
 }
 
 void AutoFillManager::FillPhoneNumberField(const AutoFillProfile* profile,
+                                           AutoFillType type,
                                            webkit_glue::FormField* field) {
   // If we are filling a phone number, check to see if the size field
   // matches the "prefix" or "suffix" sizes and fill accordingly.
-  string16 number = profile->GetFieldText(AutoFillType(PHONE_HOME_NUMBER));
+  string16 number = profile->GetFieldText(AutoFillType(type));
   bool has_valid_suffix_and_prefix = (number.length() ==
       static_cast<size_t>(PhoneNumber::kPrefixLength +
                           PhoneNumber::kSuffixLength));
@@ -767,7 +1038,7 @@
 }
 
 void AutoFillManager::ParseForms(const std::vector<FormData>& forms) {
-  std::vector<FormStructure *> non_queryable_forms;
+  std::vector<FormStructure*> non_queryable_forms;
   for (std::vector<FormData>::const_iterator iter = forms.begin();
        iter != forms.end(); ++iter) {
     scoped_ptr<FormStructure> form_structure(new FormStructure(*iter));
@@ -783,12 +1054,10 @@
   }
 
   // If none of the forms were parsed, no use querying the server.
-  if (!form_structures_.empty() && !disable_download_manager_requests_) {
-    download_manager_.StartQueryRequest(form_structures_,
-                                        *metric_logger_);
-  }
+  if (!form_structures_.empty() && !disable_download_manager_requests_)
+    download_manager_.StartQueryRequest(form_structures_, *metric_logger_);
 
-  for (std::vector<FormStructure *>::const_iterator iter =
+  for (std::vector<FormStructure*>::const_iterator iter =
            non_queryable_forms.begin();
        iter != non_queryable_forms.end(); ++iter) {
     form_structures_.push_back(*iter);
diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h
index bb0d67e..933927b 100644
--- a/chrome/browser/autofill/autofill_manager.h
+++ b/chrome/browser/autofill/autofill_manager.h
@@ -16,9 +16,13 @@
 #include "chrome/browser/autofill/autofill_dialog.h"
 #include "chrome/browser/autofill/autofill_download.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
+<<<<<<< HEAD
 #ifndef ANDROID
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #endif
+=======
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+>>>>>>> chromium.org at r11.0.672.0
 
 #ifndef ANDROID
 class AutoFillCCInfoBarDelegate;
@@ -28,7 +32,7 @@
 class CreditCard;
 class FormStructure;
 class PrefService;
-class TabContents;
+class RenderViewHost;
 
 #ifdef ANDROID
 class AutoFillHost;
@@ -41,11 +45,16 @@
 
 // Manages saving and restoring the user's personal information entered into web
 // forms.
+<<<<<<< HEAD
 class AutoFillManager :
 #ifndef ANDROID
   public RenderViewHostDelegate::AutoFill,
 #endif
   public AutoFillDownloadManager::Observer {
+=======
+class AutoFillManager : public TabContentsObserver,
+                        public AutoFillDownloadManager::Observer {
+>>>>>>> chromium.org at r11.0.672.0
  public:
   explicit AutoFillManager(TabContents* tab_contents);
   virtual ~AutoFillManager();
@@ -59,17 +68,11 @@
   // Returns the TabContents hosting this AutoFillManager.
   TabContents* tab_contents() const { return tab_contents_; }
 
-  // RenderViewHostDelegate::AutoFill implementation:
-  virtual void FormSubmitted(const webkit_glue::FormData& form);
-  virtual void FormsSeen(const std::vector<webkit_glue::FormData>& forms);
-  virtual bool GetAutoFillSuggestions(const webkit_glue::FormData& form,
-                                      const webkit_glue::FormField& field);
-  virtual bool FillAutoFillFormData(int query_id,
-                                    const webkit_glue::FormData& form,
-                                    const webkit_glue::FormField& field,
-                                    int unique_id);
-  virtual void ShowAutoFillDialog();
-  virtual void Reset();
+  // TabContentsObserver implementation.
+  virtual void DidNavigateMainFramePostCommit(
+      const NavigationController::LoadCommittedDetails& details,
+      const ViewHostMsg_FrameNavigate_Params& params);
+  virtual bool OnMessageReceived(const IPC::Message& message);
 
   // Called by the AutoFillCCInfoBarDelegate when the user interacts with the
   // infobar.
@@ -86,11 +89,14 @@
   // Returns the value of the AutoFillEnabled pref.
   virtual bool IsAutoFillEnabled() const;
 
-  // Handles the form data submitted by the user.
-  void HandleSubmit();
+  // Imports the form data, submitted by the user, into |personal_data_|.
+  void ImportFormData(const FormStructure& submitted_form);
 
   // Uploads the form data to the AutoFill server.
-  void UploadFormData();
+  void UploadFormData(const FormStructure& submitted_form);
+
+  // Reset cache.
+  void Reset();
 
  protected:
   // For tests.
@@ -107,6 +113,8 @@
   }
   void set_metric_logger(const AutoFillMetrics* metric_logger);
 
+  ScopedVector<FormStructure>* form_structures() { return &form_structures_; }
+
   // Maps GUIDs to and from IDs that are used to identify profiles and credit
   // cards sent to and from the renderer process.
   virtual int GUIDToID(const std::string& guid);
@@ -118,6 +126,19 @@
   void UnpackGUIDs(int id, std::string* cc_guid, std::string* profile_guid);
 
  private:
+  void OnFormSubmitted(const webkit_glue::FormData& form);
+  void OnFormsSeen(const std::vector<webkit_glue::FormData>& forms);
+  void OnQueryFormFieldAutoFill(int query_id,
+                                const webkit_glue::FormData& form,
+                                const webkit_glue::FormField& field);
+  void OnFillAutoFillFormData(int query_id,
+                              const webkit_glue::FormData& form,
+                              const webkit_glue::FormField& field,
+                              int unique_id);
+  void OnShowAutoFillDialog();
+  void OnDidFillAutoFillFormData();
+  void OnDidShowAutoFillSuggestions();
+
   // Fills |host| with the RenderViewHost for this tab.
   // Returns false if AutoFill is disabled or if the host is unavailable.
   bool GetHost(const std::vector<AutoFillProfile*>& profiles,
@@ -128,6 +149,11 @@
                RenderViewHost** host) WARN_UNUSED_RESULT;
 #endif
 
+  // Fills |form_structure| cached element corresponding to |form|.
+  // Returns false if the cached element was not found.
+  bool FindCachedForm(const webkit_glue::FormData& form,
+                      FormStructure** form_structure) WARN_UNUSED_RESULT;
+
   // Fills |form_structure| and |autofill_field| with the cached elements
   // corresponding to |form| and |field|. Returns false if the cached elements
   // were not found.
@@ -169,17 +195,21 @@
                      AutoFillType type,
                      webkit_glue::FormField* field);
 
-  // Set |field| argument's value for phone number based on contents of the
-  // |profile|.
+  // Set |field| argument's value for phone/fax number based on contents of the
+  // |profile|. |type| is the type of the phone.
   void FillPhoneNumberField(const AutoFillProfile* profile,
+                            AutoFillType type,
                             webkit_glue::FormField* field);
 
   // Parses the forms using heuristic matching and querying the AutoFill server.
   void ParseForms(const std::vector<webkit_glue::FormData>& forms);
 
   // Uses existing personal data to determine possible field types for the
-  // |upload_form_structure_|.
-  void DeterminePossibleFieldTypesForUpload();
+  // |submitted_form|.
+  void DeterminePossibleFieldTypesForUpload(FormStructure* submitted_form);
+
+  void LogMetricsAboutSubmittedForm(const webkit_glue::FormData& form,
+                                    const FormStructure* submitted_form);
 
   // The TabContents hosting this AutoFillManager.
   // Weak reference.
@@ -208,6 +238,7 @@
   // Our copy of the form data.
   ScopedVector<FormStructure> form_structures_;
 
+<<<<<<< HEAD
   // The form data the user has submitted.
   scoped_ptr<FormStructure> upload_form_structure_;
 
@@ -215,23 +246,42 @@
   // To minimize merge conflicts, we keep this pointer around, but never use it.
   void* cc_infobar_;
 #else
+=======
+>>>>>>> chromium.org at r11.0.672.0
   // The InfoBar that asks for permission to store credit card information.
   // Deletes itself when closed.
   AutoFillCCInfoBarDelegate* cc_infobar_;
 #endif
 
+  // The imported credit card that should be saved if the user accepts the
+  // infobar.
+  scoped_ptr<const CreditCard> imported_credit_card_;
+
   // GUID to ID mapping.  We keep two maps to convert back and forth.
   std::map<std::string, int> guid_id_map_;
   std::map<int, std::string> id_guid_map_;
 
+  friend class AutoFillManagerTest;
   friend class FormStructureBrowserTest;
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillCreditCardForm);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest,
+                           FillCreditCardFormNoYearNoMonth);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillCreditCardFormYearNoMonth);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillCreditCardFormNoYearMonth);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillCreditCardFormYearMonth);
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillAddressForm);
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillAddressAndCreditCardForm);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillFormWithMultipleSections);
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillAutoFilledForm);
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillPhoneNumber);
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FormChangesRemoveField);
   FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FormChangesAddField);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillMetricsTest, QualityMetrics);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillMetricsTest,
+                           NoQualityMetricsForNonAutoFillableForms);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillMetricsTest, SaneMetricsWithCacheMismatch);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillMetricsTest, QualityMetricsForFailure);
+  FRIEND_TEST_ALL_PREFIXES(AutoFillMetricsTest, QualityMetricsWithExperimentId);
 
   DISALLOW_COPY_AND_ASSIGN(AutoFillManager);
 };
diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc
index b454143..d22f0fd 100644
--- a/chrome/browser/autofill/autofill_manager_unittest.cc
+++ b/chrome/browser/autofill/autofill_manager_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/scoped_vector.h"
@@ -13,6 +12,7 @@
 #include "base/stringprintf.h"
 #include "base/tuple.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/autocomplete_history_manager.h"
 #include "chrome/browser/autofill/autofill_common_test.h"
 #include "chrome/browser/autofill/autofill_manager.h"
 #include "chrome/browser/autofill/autofill_profile.h"
@@ -22,12 +22,15 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
 #include "chrome/browser/tab_contents/test_tab_contents.h"
-#include "chrome/common/ipc_test_sink.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/autofill_messages.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/test/testing_profile.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ipc/ipc_test_sink.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/glue/form_data.h"
 #include "webkit/glue/form_field.h"
 
@@ -87,6 +90,16 @@
     credit_cards_.reset();
   }
 
+  void CreateTestCreditCardsYearAndMonth(const char* year, const char* month) {
+    ClearCreditCards();
+    CreditCard* credit_card = new CreditCard;
+    autofill_test::SetCreditCardInfo(credit_card, "Miku", "Miku Hatsune",
+                                     "4234567890654321", // Visa
+                                     month, year);
+    credit_card->set_guid("00000000-0000-0000-0000-000000000007");
+    credit_cards_->push_back(credit_card);
+ }
+
  private:
   void CreateTestAutoFillProfiles(ScopedVector<AutoFillProfile>* profiles) {
     AutoFillProfile* profile = new AutoFillProfile;
@@ -115,13 +128,13 @@
   void CreateTestCreditCards(ScopedVector<CreditCard>* credit_cards) {
     CreditCard* credit_card = new CreditCard;
     autofill_test::SetCreditCardInfo(credit_card, "First", "Elvis Presley",
-                                     "4234567890123456", // Visa
+                                     "4234567890123456",  // Visa
                                      "04", "2012");
     credit_card->set_guid("00000000-0000-0000-0000-000000000004");
     credit_cards->push_back(credit_card);
     credit_card = new CreditCard;
     autofill_test::SetCreditCardInfo(credit_card, "Second", "Buddy Holly",
-                                     "5187654321098765", // Mastercard
+                                     "5187654321098765",  // Mastercard
                                      "10", "2014");
     credit_card->set_guid("00000000-0000-0000-0000-000000000005");
     credit_cards->push_back(credit_card);
@@ -173,20 +186,22 @@
       "Country", "country", "", "text", &field);
   form->fields.push_back(field);
   autofill_test::CreateTestFormField(
-      "Phone Number", "phonenumber", "", "text", &field);
+      "Phone Number", "phonenumber", "", "tel", &field);
   form->fields.push_back(field);
   autofill_test::CreateTestFormField(
       "Fax", "fax", "", "text", &field);
   form->fields.push_back(field);
   autofill_test::CreateTestFormField(
-      "Email", "email", "", "text", &field);
+      "Email", "email", "", "email", &field);
   form->fields.push_back(field);
 }
 
 // Populates |form| with data corresponding to a simple credit card form.
 // Note that this actually appends fields to the form data, which can be useful
 // for building up more complex test forms.
-void CreateTestCreditCardFormData(FormData* form, bool is_https) {
+void CreateTestCreditCardFormData(FormData* form,
+                                  bool is_https,
+                                  bool use_month_type) {
   form->name = ASCIIToUTF16("MyForm");
   form->method = ASCIIToUTF16("POST");
   if (is_https) {
@@ -205,12 +220,18 @@
   autofill_test::CreateTestFormField(
       "Card Number", "cardnumber", "", "text", &field);
   form->fields.push_back(field);
-  autofill_test::CreateTestFormField(
-      "Expiration Date", "ccmonth", "", "text", &field);
-  form->fields.push_back(field);
-  autofill_test::CreateTestFormField(
-      "", "ccyear", "", "text", &field);
-  form->fields.push_back(field);
+  if (use_month_type) {
+    autofill_test::CreateTestFormField(
+        "Expiration Date", "ccmonth", "", "month", &field);
+    form->fields.push_back(field);
+  } else {
+    autofill_test::CreateTestFormField(
+        "Expiration Date", "ccmonth", "", "text", &field);
+    form->fields.push_back(field);
+    autofill_test::CreateTestFormField(
+        "", "ccyear", "", "text", &field);
+    form->fields.push_back(field);
+  }
 }
 
 void ExpectSuggestions(int page_id,
@@ -241,7 +262,7 @@
 // Verifies that the |filled_form| has been filled with the given data.
 // Verifies address fields if |has_address_fields| is true, and verifies
 // credit card fields if |has_credit_card_fields| is true. Verifies both if both
-// are true.
+// are true. |use_month_type| is used for credit card input month type.
 void ExpectFilledForm(int page_id,
                       const FormData& filled_form,
                       int expected_page_id,
@@ -262,10 +283,11 @@
                       const char* expiration_month,
                       const char* expiration_year,
                       bool has_address_fields,
-                      bool has_credit_card_fields) {
+                      bool has_credit_card_fields,
+                      bool use_month_type) {
   // The number of fields in the address and credit card forms created above.
   const size_t kAddressFormSize = 12;
-  const size_t kCreditCardFormSize = 4;
+  const size_t kCreditCardFormSize = use_month_type ? 3 : 4;
 
   EXPECT_EQ(expected_page_id, page_id);
   EXPECT_EQ(ASCIIToUTF16("MyForm"), filled_form.name);
@@ -295,34 +317,34 @@
         "Middle Name", "middlename", middle, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[1]));
     autofill_test::CreateTestFormField(
-         "Last Name", "lastname", last, "text", &field);
+        "Last Name", "lastname", last, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[2]));
     autofill_test::CreateTestFormField(
-         "Address Line 1", "addr1", address1, "text", &field);
+        "Address Line 1", "addr1", address1, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[3]));
     autofill_test::CreateTestFormField(
-         "Address Line 2", "addr2", address2, "text", &field);
+        "Address Line 2", "addr2", address2, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[4]));
     autofill_test::CreateTestFormField(
-         "City", "city", city, "text", &field);
+        "City", "city", city, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[5]));
     autofill_test::CreateTestFormField(
-         "State", "state", state, "text", &field);
+        "State", "state", state, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[6]));
     autofill_test::CreateTestFormField(
-         "Postal Code", "zipcode", postal_code, "text", &field);
+        "Postal Code", "zipcode", postal_code, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[7]));
     autofill_test::CreateTestFormField(
-         "Country", "country", country, "text", &field);
+        "Country", "country", country, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[8]));
     autofill_test::CreateTestFormField(
-        "Phone Number", "phonenumber", phone, "text", &field);
+        "Phone Number", "phonenumber", phone, "tel", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[9]));
     autofill_test::CreateTestFormField(
         "Fax", "fax", fax, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[10]));
     autofill_test::CreateTestFormField(
-         "Email", "email", email, "text", &field);
+        "Email", "email", email, "email", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[11]));
   }
 
@@ -334,12 +356,23 @@
     autofill_test::CreateTestFormField(
         "Card Number", "cardnumber", card_number, "text", &field);
     EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 1]));
-    autofill_test::CreateTestFormField(
-        "Expiration Date", "ccmonth", expiration_month, "text", &field);
-    EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 2]));
-    autofill_test::CreateTestFormField(
-        "", "ccyear", expiration_year, "text", &field);
-    EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 3]));
+    if (use_month_type) {
+      std::string exp_year = expiration_year;
+      std::string exp_month = expiration_month;
+      std::string date;
+      if (!exp_year.empty() && !exp_month.empty())
+        date = exp_year + "-" + exp_month;
+      autofill_test::CreateTestFormField(
+          "Expiration Date", "ccmonth", date.c_str(), "month", &field);
+      EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 2]));
+    } else {
+      autofill_test::CreateTestFormField(
+          "Expiration Date", "ccmonth", expiration_month, "text", &field);
+      EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 2]));
+      autofill_test::CreateTestFormField(
+          "", "ccyear", expiration_year, "text", &field);
+      EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 3]));
+    }
   }
 }
 
@@ -351,7 +384,7 @@
                    "Presley", "3734 Elvis Presley Blvd.", "Apt. 10", "Memphis",
                    "Tennessee", "38116", "USA", "12345678901", "",
                    "theking@gmail.com", "", "", "", "", true,
-                   has_credit_card_fields);
+                   has_credit_card_fields, false);
 }
 
 void ExpectFilledCreditCardFormElvis(int page_id,
@@ -361,7 +394,19 @@
   ExpectFilledForm(page_id, filled_form, expected_page_id,
                    "", "", "", "", "", "", "", "", "", "", "", "",
                    "Elvis Presley", "4234567890123456", "04", "2012",
-                   has_address_fields, true);
+                   has_address_fields, true, false);
+}
+
+void ExpectFilledCreditCardYearMonthWithYearMonth(int page_id,
+                                              const FormData& filled_form,
+                                              int expected_page_id,
+                                              bool has_address_fields,
+                                              const char* year,
+                                              const char* month) {
+  ExpectFilledForm(page_id, filled_form, expected_page_id,
+                   "", "", "", "", "", "", "", "", "", "", "", "",
+                   "Miku Hatsune", "4234567890654321", month, year,
+                   has_address_fields, true, true);
 }
 
 class TestAutoFillManager : public AutoFillManager {
@@ -440,19 +485,46 @@
 
   Profile* profile() { return contents()->profile(); }
 
+  void GetAutoFillSuggestions(int query_id,
+                              const webkit_glue::FormData& form,
+                              const webkit_glue::FormField& field) {
+    autofill_manager_->OnQueryFormFieldAutoFill(query_id, form, field);
+  }
+
+  void GetAutoFillSuggestions(const webkit_glue::FormData& form,
+                              const webkit_glue::FormField& field) {
+    GetAutoFillSuggestions(kDefaultPageID, form, field);
+  }
+
+  void AutocompleteSuggestionsReturned(const std::vector<string16>& result) {
+    autofill_manager_->tab_contents()->autocomplete_history_manager()->
+        SendSuggestions(&result);
+  }
+
+  void FormsSeen(const std::vector<webkit_glue::FormData>& forms) {
+    autofill_manager_->OnFormsSeen(forms);
+  }
+
+  void FillAutoFillFormData(int query_id,
+                            const webkit_glue::FormData& form,
+                            const webkit_glue::FormField& field,
+                            int unique_id) {
+    autofill_manager_->OnFillAutoFillFormData(query_id, form, field, unique_id);
+  }
+
   bool GetAutoFillSuggestionsMessage(int* page_id,
                                      std::vector<string16>* values,
                                      std::vector<string16>* labels,
                                      std::vector<string16>* icons,
                                      std::vector<int>* unique_ids) {
-    const uint32 kMsgID = ViewMsg_AutoFillSuggestionsReturned::ID;
+    const uint32 kMsgID = AutoFillMsg_SuggestionsReturned::ID;
     const IPC::Message* message =
         process()->sink().GetFirstMessageMatching(kMsgID);
     if (!message)
       return false;
 
     AutoFillParam autofill_param;
-    ViewMsg_AutoFillSuggestionsReturned::Read(message, &autofill_param);
+    AutoFillMsg_SuggestionsReturned::Read(message, &autofill_param);
     if (page_id)
       *page_id = autofill_param.a;
     if (values)
@@ -463,21 +535,27 @@
       *icons = autofill_param.d;
     if (unique_ids)
       *unique_ids = autofill_param.e;
+
+    autofill_manager_->tab_contents()->autocomplete_history_manager()->
+        CancelPendingQuery();
+    process()->sink().ClearMessages();
     return true;
   }
 
   bool GetAutoFillFormDataFilledMessage(int *page_id, FormData* results) {
-    const uint32 kMsgID = ViewMsg_AutoFillFormDataFilled::ID;
+    const uint32 kMsgID = AutoFillMsg_FormDataFilled::ID;
     const IPC::Message* message =
         process()->sink().GetFirstMessageMatching(kMsgID);
     if (!message)
       return false;
     Tuple2<int, FormData> autofill_param;
-    ViewMsg_AutoFillFormDataFilled::Read(message, &autofill_param);
+    AutoFillMsg_FormDataFilled::Read(message, &autofill_param);
     if (page_id)
       *page_id = autofill_param.a;
     if (results)
       *results = autofill_param.b;
+
+    process()->sink().ClearMessages();
     return true;
   }
 
@@ -496,15 +574,14 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -512,8 +589,8 @@
   std::vector<string16> labels;
   std::vector<string16> icons;
   std::vector<int> unique_ids;
-  EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons,
-                                            &unique_ids));
+  GetAutoFillSuggestionsMessage(
+      &page_id, &values, &labels, &icons, &unique_ids);
 
   string16 expected_values[] = {
     ASCIIToUTF16("Elvis"),
@@ -539,17 +616,16 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   FormField field;
   autofill_test::CreateTestFormField("First Name", "firstname", "E", "text",
                                      &field);
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -592,10 +668,10 @@
   form.fields.push_back(field);
 
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
+  EXPECT_FALSE(GetAutoFillSuggestionsMessage(NULL, NULL, NULL, NULL, NULL));
 }
 
 // Test that we cull duplicate profile suggestions.
@@ -604,7 +680,7 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // Add a duplicate profile.
   AutoFillProfile* duplicate_profile = static_cast<AutoFillProfile*>(
@@ -612,12 +688,11 @@
   autofill_manager_->AddProfile(duplicate_profile);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -649,14 +724,14 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // Disable AutoFill.
   autofill_manager_->set_autofill_enabled(false);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
+  EXPECT_FALSE(GetAutoFillSuggestionsMessage(NULL, NULL, NULL, NULL, NULL));
 }
 
 // Test that we return a warning explaining that autofill suggestions are
@@ -667,15 +742,14 @@
   CreateTestAddressFormData(&form);
   form.method = ASCIIToUTF16("GET");
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -698,15 +772,13 @@
 
   // Now add some Autocomplete suggestions. We should return the autocomplete
   // suggestions and the warning; these will be culled by the renderer.
-  process()->sink().ClearMessages();
   const int kPageID2 = 2;
-  rvh()->ResetAutoFillState(kPageID2);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(kPageID2, form, field);
 
   std::vector<string16> suggestions;
   suggestions.push_back(ASCIIToUTF16("Jay"));
   suggestions.push_back(ASCIIToUTF16("Jason"));
-  rvh()->AutocompleteSuggestionsReturned(suggestions);
+  AutocompleteSuggestionsReturned(suggestions);
 
   EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons,
                                             &unique_ids));
@@ -725,7 +797,8 @@
 
   // Now clear the test profiles and try again -- we shouldn't return a warning.
   test_personal_data_->ClearAutoFillProfiles();
-  EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
+  EXPECT_FALSE(GetAutoFillSuggestionsMessage(NULL, NULL, NULL, NULL, NULL));
 }
 
 // Test that we return all credit card profile suggestions when all form fields
@@ -733,17 +806,16 @@
 TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsEmptyValue) {
   // Set up our form data.
   FormData form;
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   FormField field = form.fields[1];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -777,19 +849,18 @@
 TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsMatchCharacter) {
   // Set up our form data.
   FormData form;
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   FormField field;
   autofill_test::CreateTestFormField(
       "Card Number", "cardnumber", "4", "text", &field);
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -814,17 +885,16 @@
 TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonCCNumber) {
   // Set up our form data.
   FormData form;
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -858,17 +928,16 @@
 TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonHTTPS) {
   // Set up our form data.
   FormData form;
-  CreateTestCreditCardFormData(&form, false);
+  CreateTestCreditCardFormData(&form, false, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -891,15 +960,13 @@
 
   // Now add some Autocomplete suggestions. We should show the autocomplete
   // suggestions and the warning.
-  process()->sink().ClearMessages();
   const int kPageID2 = 2;
-  rvh()->ResetAutoFillState(kPageID2);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(kPageID2, form, field);
 
   std::vector<string16> suggestions;
   suggestions.push_back(ASCIIToUTF16("Jay"));
   suggestions.push_back(ASCIIToUTF16("Jason"));
-  rvh()->AutocompleteSuggestionsReturned(suggestions);
+  AutocompleteSuggestionsReturned(suggestions);
 
   EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons,
                                             &unique_ids));
@@ -917,7 +984,8 @@
 
   // Clear the test credit cards and try again -- we shouldn't return a warning.
   test_personal_data_->ClearCreditCards();
-  EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
+  EXPECT_FALSE(GetAutoFillSuggestionsMessage(NULL, NULL, NULL, NULL, NULL));
 }
 
 // Test that we return profile and credit card suggestions for combined forms.
@@ -925,17 +993,16 @@
   // Set up our form data.
   FormData form;
   CreateTestAddressFormData(&form);
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   FormField field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right address suggestions to the renderer.
   int page_id = 0;
@@ -960,16 +1027,14 @@
                     kDefaultPageID, arraysize(expected_values), expected_values,
                     expected_labels, expected_icons, expected_unique_ids);
 
-  process()->sink().ClearMessages();
   const int kPageID2 = 2;
   autofill_test::CreateTestFormField(
       "Card Number", "cardnumber", "", "text", &field);
-  rvh()->ResetAutoFillState(kPageID2);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(kPageID2, form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the credit card suggestions to the renderer.
   page_id = 0;
@@ -1002,17 +1067,16 @@
   // Set up our form data.
   FormData form;
   CreateTestAddressFormData(&form);
-  CreateTestCreditCardFormData(&form, false);
+  CreateTestCreditCardFormData(&form, false, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   FormField field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right address suggestions to the renderer.
   int page_id = 0;
@@ -1037,16 +1101,14 @@
                     kDefaultPageID, arraysize(expected_values), expected_values,
                     expected_labels, expected_icons, expected_unique_ids);
 
-  process()->sink().ClearMessages();
   autofill_test::CreateTestFormField(
       "Card Number", "cardnumber", "", "text", &field);
   const int kPageID2 = 2;
-  rvh()->ResetAutoFillState(kPageID2);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(kPageID2, form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons,
@@ -1064,7 +1126,8 @@
 
   // Clear the test credit cards and try again -- we shouldn't return a warning.
   test_personal_data_->ClearCreditCards();
-  EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
+  EXPECT_FALSE(GetAutoFillSuggestionsMessage(NULL, NULL, NULL, NULL, NULL));
 }
 
 // Test that we correctly combine autofill and autocomplete suggestions.
@@ -1073,11 +1136,10 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // Add some Autocomplete suggestions.
   // This triggers the combined message send.
@@ -1086,7 +1148,7 @@
   // This suggestion is a duplicate, and should be trimmed.
   suggestions.push_back(ASCIIToUTF16("Elvis"));
   suggestions.push_back(ASCIIToUTF16("Jason"));
-  rvh()->AutocompleteSuggestionsReturned(suggestions);
+  AutocompleteSuggestionsReturned(suggestions);
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -1123,17 +1185,16 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // Mark one of the fields as filled.
   form.fields[2].set_autofilled(true);
   const FormField& field = form.fields[0];
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -1166,17 +1227,16 @@
       "Some Field", "somefield", "", "text", &field);
   form.fields.push_back(field);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // Add some Autocomplete suggestions.
   // This triggers the combined message send.
   std::vector<string16> suggestions;
   suggestions.push_back(ASCIIToUTF16("one"));
   suggestions.push_back(ASCIIToUTF16("two"));
-  rvh()->AutocompleteSuggestionsReturned(suggestions);
+  AutocompleteSuggestionsReturned(suggestions);
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -1206,7 +1266,7 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // |profile| will be owned by the mock PersonalDataManager.
   AutoFillProfile* profile = new AutoFillProfile;
@@ -1217,12 +1277,11 @@
 
   FormField& field = form.fields[0];
   field.set_autofilled(true);
-  rvh()->ResetAutoFillState(kDefaultPageID);
-  EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field));
+  GetAutoFillSuggestions(form, field);
 
   // No suggestions provided, so send an empty vector as the results.
   // This triggers the combined message send.
-  rvh()->AutocompleteSuggestionsReturned(std::vector<string16>());
+  AutocompleteSuggestionsReturned(std::vector<string16>());
 
   // Test that we sent the right message to the renderer.
   int page_id = 0;
@@ -1251,12 +1310,12 @@
   FormData form;
   CreateTestAddressFormData(&form);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kDefaultPageID, form, form.fields[0],
-      autofill_manager_->PackGUIDs(std::string(), guid)));
+      autofill_manager_->PackGUIDs(std::string(), guid));
 
   int page_id = 0;
   FormData results;
@@ -1268,14 +1327,14 @@
 TEST_F(AutoFillManagerTest, FillCreditCardForm) {
   // Set up our form data.
   FormData form;
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   std::string guid = autofill_manager_->GetLabeledCreditCard("First")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kDefaultPageID, form, *form.fields.begin(),
-      autofill_manager_->PackGUIDs(guid, std::string())));
+      autofill_manager_->PackGUIDs(guid, std::string()));
 
   int page_id = 0;
   FormData results;
@@ -1283,20 +1342,117 @@
   ExpectFilledCreditCardFormElvis(page_id, results, kDefaultPageID, false);
 }
 
+// Test that we correctly fill a credit card form with month input type.
+// 1. year empty, month empty
+TEST_F(AutoFillManagerTest, FillCreditCardFormNoYearNoMonth) {
+  // Same as the SetUp(), but generate 4 credit cards with year month
+  // combination.
+  test_personal_data_->CreateTestCreditCardsYearAndMonth("", "");
+  // Set up our form data.
+  FormData form;
+  CreateTestCreditCardFormData(&form, true, true);
+  std::vector<FormData> forms(1, form);
+  FormsSeen(forms);
+
+  std::string guid = autofill_manager_->GetLabeledCreditCard("Miku")->guid();
+  FillAutoFillFormData(
+      kDefaultPageID, form, *form.fields.begin(),
+      autofill_manager_->PackGUIDs(guid, std::string()));
+
+  int page_id = 0;
+  FormData results;
+  EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
+  ExpectFilledCreditCardYearMonthWithYearMonth(page_id, results,
+      kDefaultPageID, false, "", "");
+}
+
+
+// Test that we correctly fill a credit card form with month input type.
+// 2. year empty, month non-empty
+TEST_F(AutoFillManagerTest, FillCreditCardFormNoYearMonth) {
+  // Same as the SetUp(), but generate 4 credit cards with year month
+  // combination.
+  test_personal_data_->CreateTestCreditCardsYearAndMonth("", "04");
+  // Set up our form data.
+  FormData form;
+  CreateTestCreditCardFormData(&form, true, true);
+  std::vector<FormData> forms(1, form);
+  FormsSeen(forms);
+
+  std::string guid = autofill_manager_->GetLabeledCreditCard("Miku")->guid();
+  FillAutoFillFormData(
+      kDefaultPageID, form, *form.fields.begin(),
+      autofill_manager_->PackGUIDs(guid, std::string()));
+
+  int page_id = 0;
+  FormData results;
+  EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
+  ExpectFilledCreditCardYearMonthWithYearMonth(page_id, results,
+      kDefaultPageID, false, "", "04");
+}
+
+// Test that we correctly fill a credit card form with month input type.
+// 3. year non-empty, month empty
+TEST_F(AutoFillManagerTest, FillCreditCardFormYearNoMonth) {
+  // Same as the SetUp(), but generate 4 credit cards with year month
+  // combination.
+  test_personal_data_->CreateTestCreditCardsYearAndMonth("2012", "");
+  // Set up our form data.
+  FormData form;
+  CreateTestCreditCardFormData(&form, true, true);
+  std::vector<FormData> forms(1, form);
+  FormsSeen(forms);
+
+  std::string guid = autofill_manager_->GetLabeledCreditCard("Miku")->guid();
+  FillAutoFillFormData(
+      kDefaultPageID, form, *form.fields.begin(),
+      autofill_manager_->PackGUIDs(guid, std::string()));
+
+  int page_id = 0;
+  FormData results;
+  EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
+  ExpectFilledCreditCardYearMonthWithYearMonth(page_id, results,
+      kDefaultPageID, false, "2012", "");
+}
+
+// Test that we correctly fill a credit card form with month input type.
+// 4. year non-empty, month empty
+TEST_F(AutoFillManagerTest, FillCreditCardFormYearMonth) {
+  // Same as the SetUp(), but generate 4 credit cards with year month
+  // combination.
+  test_personal_data_->ClearCreditCards();
+  test_personal_data_->CreateTestCreditCardsYearAndMonth("2012", "04");
+  // Set up our form data.
+  FormData form;
+  CreateTestCreditCardFormData(&form, true, true);
+  std::vector<FormData> forms(1, form);
+  FormsSeen(forms);
+
+  std::string guid = autofill_manager_->GetLabeledCreditCard("Miku")->guid();
+  FillAutoFillFormData(
+      kDefaultPageID, form, *form.fields.begin(),
+      autofill_manager_->PackGUIDs(guid, std::string()));
+
+  int page_id = 0;
+  FormData results;
+  EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
+  ExpectFilledCreditCardYearMonthWithYearMonth(page_id, results,
+      kDefaultPageID, false, "2012", "04");
+}
+
 // Test that we correctly fill a combined address and credit card form.
 TEST_F(AutoFillManagerTest, FillAddressAndCreditCardForm) {
   // Set up our form data.
   FormData form;
   CreateTestAddressFormData(&form);
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // First fill the address data.
   std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
-      kDefaultPageID, form, form.fields[0],
-      autofill_manager_->PackGUIDs(std::string(), guid)));
+  FillAutoFillFormData(kDefaultPageID, form, form.fields[0],
+                       autofill_manager_->PackGUIDs(std::string(), guid));
 
   int page_id = 0;
   FormData results;
@@ -1307,12 +1463,11 @@
   }
 
   // Now fill the credit card data.
-  process()->sink().ClearMessages();
   const int kPageID2 = 2;
   guid = autofill_manager_->GetLabeledCreditCard("First")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kPageID2, form, form.fields.back(),
-      autofill_manager_->PackGUIDs(guid, std::string())));
+      autofill_manager_->PackGUIDs(guid, std::string()));
 
   page_id = 0;
   EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
@@ -1322,6 +1477,77 @@
   }
 }
 
+// Test that we correctly fill a form that has multiple logical sections, e.g.
+// both a billing and a shipping address.
+TEST_F(AutoFillManagerTest, FillFormWithMultipleSections) {
+  // Set up our form data.
+  FormData form;
+  CreateTestAddressFormData(&form);
+  const size_t kAddressFormSize = form.fields.size();
+  CreateTestAddressFormData(&form);
+  for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) {
+    // Make sure the fields have distinct names.
+    form.fields[i].set_name(form.fields[i].name() + ASCIIToUTF16("_"));
+  }
+  std::vector<FormData> forms(1, form);
+  FormsSeen(forms);
+
+  // Fill the first section.
+  std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid();
+  FillAutoFillFormData(kDefaultPageID, form, form.fields[0],
+                       autofill_manager_->PackGUIDs(std::string(), guid));
+
+  int page_id = 0;
+  FormData results;
+  EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
+  {
+    SCOPED_TRACE("Address 1");
+
+    // The second address section should be empty.
+    ASSERT_EQ(results.fields.size(), 2*kAddressFormSize);
+    for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) {
+      EXPECT_EQ(string16(), results.fields[i].value());
+    }
+
+    // The first address section should be filled with Elvis's data.
+    results.fields.resize(kAddressFormSize);
+    ExpectFilledAddressFormElvis(page_id, results, kDefaultPageID, false);
+  }
+
+  // Fill the second section, with the initiating field somewhere in the middle
+  // of the section.
+  const int kPageID2 = 2;
+  guid = autofill_manager_->GetLabeledProfile("Home")->guid();
+  ASSERT_LT(9U, kAddressFormSize);
+  FillAutoFillFormData(kPageID2, form, form.fields[kAddressFormSize + 9],
+                       autofill_manager_->PackGUIDs(std::string(), guid));
+
+  page_id = 0;
+  EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
+  {
+    SCOPED_TRACE("Address 2");
+    ASSERT_EQ(results.fields.size(), form.fields.size());
+
+    // The first address section should be empty.
+    ASSERT_EQ(results.fields.size(), 2*kAddressFormSize);
+    for (size_t i = 0; i < kAddressFormSize; ++i) {
+      EXPECT_EQ(string16(), results.fields[i].value());
+    }
+
+    // The second address section should be filled with Elvis's data.
+    FormData secondSection = results;
+    secondSection.fields.erase(secondSection.fields.begin(),
+                               secondSection.fields.begin() + kAddressFormSize);
+    for (size_t i = 0; i < kAddressFormSize; ++i) {
+      // Restore the expected field names.
+      string16 name = secondSection.fields[i].name();
+      string16 original_name = name.substr(0, name.size() - 1);
+      secondSection.fields[i].set_name(original_name);
+    }
+    ExpectFilledAddressFormElvis(page_id, secondSection, kPageID2, false);
+  }
+}
+
 // Test that we correctly fill a previously auto-filled form.
 TEST_F(AutoFillManagerTest, FillAutoFilledForm) {
   // Set up our form data.
@@ -1329,15 +1555,15 @@
   CreateTestAddressFormData(&form);
   // Mark one of the address fields as autofilled.
   form.fields[4].set_autofilled(true);
-  CreateTestCreditCardFormData(&form, true);
+  CreateTestCreditCardFormData(&form, true, false);
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // First fill the address data.
   std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kDefaultPageID, form, *form.fields.begin(),
-      autofill_manager_->PackGUIDs(std::string(), guid)));
+      autofill_manager_->PackGUIDs(std::string(), guid));
 
   int page_id = 0;
   FormData results;
@@ -1346,16 +1572,15 @@
     SCOPED_TRACE("Address");
     ExpectFilledForm(page_id, results, kDefaultPageID,
                      "Elvis", "", "", "", "", "", "", "", "", "", "", "",
-                     "", "", "", "", true, true);
+                     "", "", "", "", true, true, false);
   }
 
   // Now fill the credit card data.
-  process()->sink().ClearMessages();
   const int kPageID2 = 2;
   guid = autofill_manager_->GetLabeledCreditCard("First")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kPageID2, form, form.fields.back(),
-      autofill_manager_->PackGUIDs(guid, std::string())));
+      autofill_manager_->PackGUIDs(guid, std::string()));
 
   page_id = 0;
   EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
@@ -1368,15 +1593,14 @@
   // fill the credit card data
   for (std::vector<FormField>::iterator iter = form.fields.begin();
        iter != form.fields.end();
-       ++iter){
+       ++iter) {
     iter->set_autofilled(true);
   }
 
-  process()->sink().ClearMessages();
   const int kPageID3 = 3;
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kPageID3, form, *form.fields.rbegin(),
-      autofill_manager_->PackGUIDs(guid, std::string())));
+      autofill_manager_->PackGUIDs(guid, std::string()));
 
   page_id = 0;
   EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
@@ -1384,7 +1608,7 @@
     SCOPED_TRACE("Credit card 2");
     ExpectFilledForm(page_id, results, kPageID3,
                    "", "", "", "", "", "", "", "", "", "", "", "",
-                   "", "", "", "2012", true, true);
+                   "", "", "", "2012", true, true, false);
   }
 }
 
@@ -1421,7 +1645,7 @@
   form.fields.push_back(field);
 
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   AutoFillProfile *work_profile = autofill_manager_->GetLabeledProfile("Work");
   ASSERT_TRUE(work_profile != NULL);
@@ -1435,10 +1659,9 @@
     // The page ID sent to the AutoFillManager from the RenderView, used to send
     // an IPC message back to the renderer.
     int page_id = 100 - i;
-    process()->sink().ClearMessages();
-    EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+    FillAutoFillFormData(
         page_id, form, *form.fields.begin(),
-        autofill_manager_->PackGUIDs(std::string(), work_profile->guid())));
+        autofill_manager_->PackGUIDs(std::string(), work_profile->guid()));
     page_id = 0;
     FormData results;
     EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results));
@@ -1468,15 +1691,15 @@
   form.fields.insert(form.fields.begin() + 3, field);
 
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // Now, after the call to |FormsSeen|, we remove the field before filling.
   form.fields.erase(form.fields.begin() + 3);
 
   std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kDefaultPageID, form, form.fields[0],
-      autofill_manager_->PackGUIDs(std::string(), guid)));
+      autofill_manager_->PackGUIDs(std::string(), guid));
 
   int page_id = 0;
   FormData results;
@@ -1499,15 +1722,15 @@
   pos = form.fields.erase(pos);
 
   std::vector<FormData> forms(1, form);
-  autofill_manager_->FormsSeen(forms);
+  FormsSeen(forms);
 
   // Now, after the call to |FormsSeen|, we restore the field before filling.
   form.fields.insert(pos, field);
 
   std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid();
-  EXPECT_TRUE(autofill_manager_->FillAutoFillFormData(
+  FillAutoFillFormData(
       kDefaultPageID, form, form.fields[0],
-      autofill_manager_->PackGUIDs(std::string(), guid)));
+      autofill_manager_->PackGUIDs(std::string(), guid));
 
   int page_id = 0;
   FormData results;
@@ -1515,37 +1738,6 @@
   ExpectFilledAddressFormElvis(page_id, results, kDefaultPageID, false);
 }
 
-TEST_F(AutoFillManagerTest, HiddenFields) {
-  FormData form;
-  form.name = ASCIIToUTF16("MyForm");
-  form.method = ASCIIToUTF16("POST");
-  form.origin = GURL("http://myform.com/form.html");
-  form.action = GURL("http://myform.com/submit.html");
-  form.user_submitted = true;
-
-  FormField field;
-  autofill_test::CreateTestFormField(
-      "E-mail", "one", "one", "hidden", &field);
-  form.fields.push_back(field);
-  autofill_test::CreateTestFormField(
-      "E-mail", "two", "two", "hidden", &field);
-  form.fields.push_back(field);
-  autofill_test::CreateTestFormField(
-      "E-mail", "three", "three", "hidden", &field);
-  form.fields.push_back(field);
-
-  // Set up our form data.
-  std::vector<FormData> forms;
-  forms.push_back(form);
-  autofill_manager_->FormsSeen(forms);
-
-  // Submit the form.
-  autofill_manager_->FormSubmitted(form);
-
-  // TODO(jhawkins): We can't use the InfoBar anymore to determine if we saved
-  // fields.  Need to query the PDM.
-}
-
 // Checks that resetting the auxiliary profile enabled preference does the right
 // thing on all platforms.
 TEST_F(AutoFillManagerTest, AuxiliaryProfilesReset) {
@@ -1569,4 +1761,3 @@
       prefs::kAutoFillAuxiliaryProfilesEnabled));
 #endif
 }
-
diff --git a/chrome/browser/autofill/autofill_merge_unittest.cc b/chrome/browser/autofill/autofill_merge_unittest.cc
new file mode 100644
index 0000000..a1548a0
--- /dev/null
+++ b/chrome/browser/autofill/autofill_merge_unittest.cc
@@ -0,0 +1,222 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autofill/autofill_common_test.h"
+#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/data_driven_test.h"
+#include "chrome/browser/autofill/form_structure.h"
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "webkit/glue/form_data.h"
+
+namespace {
+
+const FilePath::CharType kTestName[] = FILE_PATH_LITERAL("merge");
+const FilePath::CharType kFileNamePattern[] = FILE_PATH_LITERAL("*.in");
+
+const char kFieldSeparator[] = ": ";
+const char kProfileSeparator[] = "---";
+const size_t kFieldOffset = arraysize(kFieldSeparator) - 1;
+
+const AutoFillFieldType kProfileFieldTypes[] = {
+  NAME_FIRST,
+  NAME_MIDDLE,
+  NAME_LAST,
+  EMAIL_ADDRESS,
+  COMPANY_NAME,
+  ADDRESS_HOME_LINE1,
+  ADDRESS_HOME_LINE2,
+  ADDRESS_HOME_CITY,
+  ADDRESS_HOME_STATE,
+  ADDRESS_HOME_ZIP,
+  ADDRESS_HOME_COUNTRY,
+  PHONE_HOME_NUMBER,
+  PHONE_FAX_NUMBER,
+};
+
+// Serializes the |profiles| into a string.
+std::string SerializeProfiles(const std::vector<AutoFillProfile*>& profiles) {
+  std::string result;
+  for (size_t i = 0; i < profiles.size(); ++i) {
+    result += kProfileSeparator;
+    result += "\n";
+    for (size_t j = 0; j < arraysize(kProfileFieldTypes); ++j) {
+      AutoFillFieldType type = kProfileFieldTypes[j];
+      result += AutoFillType::FieldTypeToString(type);
+      result += kFieldSeparator;
+      result += UTF16ToUTF8(profiles[i]->GetFieldText(AutoFillType(type)));
+      result += "\n";
+    }
+  }
+
+  return result;
+}
+
+class PersonalDataManagerMock : public PersonalDataManager {
+ public:
+  PersonalDataManagerMock();
+  virtual ~PersonalDataManagerMock();
+
+  // Reset the saved profiles.
+  void Reset();
+
+  // PersonalDataManager:
+  virtual void SaveImportedProfile(const AutoFillProfile& profile) OVERRIDE;
+  virtual const std::vector<AutoFillProfile*>& web_profiles() OVERRIDE;
+
+ private:
+  ScopedVector<AutoFillProfile> profiles_;
+
+  DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerMock);
+};
+
+PersonalDataManagerMock::PersonalDataManagerMock() : PersonalDataManager() {
+}
+
+PersonalDataManagerMock::~PersonalDataManagerMock() {
+}
+
+void PersonalDataManagerMock::Reset() {
+  profiles_.reset();
+}
+
+void PersonalDataManagerMock::SaveImportedProfile(
+    const AutoFillProfile& profile) {
+  std::vector<AutoFillProfile> profiles;
+  if (!MergeProfile(profile, profiles_.get(), &profiles))
+    profiles_.push_back(new AutoFillProfile(profile));
+}
+
+const std::vector<AutoFillProfile*>& PersonalDataManagerMock::web_profiles() {
+  return profiles_.get();
+}
+
+}  // namespace
+
+// A data-driven test for verifying merging of AutoFill profiles. Each input is
+// a structured dump of a set of implicitly detected autofill profiles. The
+// corresponding output file is a dump of the saved profiles that result from
+// importing the input profiles. The output file format is identical to the
+// input format.
+class AutoFillMergeTest : public testing::Test, public DataDrivenTest {
+ protected:
+  AutoFillMergeTest();
+  virtual ~AutoFillMergeTest();
+
+  // testing::Test:
+  virtual void SetUp();
+
+  // DataDrivenTest:
+  virtual void GenerateResults(const std::string& input,
+                               std::string* output) OVERRIDE;
+
+  // Deserializes a set of AutoFill profiles from |profiles|, imports each
+  // sequentially, and fills |merged_profiles| with the serialized result.
+  void MergeProfiles(const std::string& profiles, std::string* merged_profiles);
+
+  scoped_refptr<PersonalDataManagerMock> personal_data_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AutoFillMergeTest);
+};
+
+AutoFillMergeTest::AutoFillMergeTest() : DataDrivenTest() {
+}
+
+AutoFillMergeTest::~AutoFillMergeTest() {
+}
+
+void AutoFillMergeTest::SetUp() {
+  autofill_test::DisableSystemServices(NULL);
+
+  personal_data_ = new PersonalDataManagerMock();
+}
+
+void AutoFillMergeTest::GenerateResults(const std::string& input,
+                                        std::string* output) {
+  MergeProfiles(input, output);
+
+  // Verify that the test is idempotent on the output profiles.
+  std::string merged_output;
+  MergeProfiles(*output, &merged_output);
+  EXPECT_EQ(*output, merged_output);
+}
+
+void AutoFillMergeTest::MergeProfiles(const std::string& profiles,
+                                      std::string* merged_profiles) {
+  // Start with no saved profiles.
+  personal_data_->Reset();
+
+  // Create a test form.
+  webkit_glue::FormData form;
+  form.name = ASCIIToUTF16("MyTestForm");
+  form.method = ASCIIToUTF16("POST");
+  form.origin = GURL("https://www.example.com/origin.html");
+  form.action = GURL("https://www.example.com/action.html");
+  form.user_submitted = true;
+
+  // Parse the input line by line.
+  std::vector<std::string> lines;
+  Tokenize(profiles, "\n", &lines);
+  for (size_t i = 0; i < lines.size(); ++i) {
+    std::string line = lines[i];
+
+    if (line != kProfileSeparator) {
+      // Add a field to the current profile.
+      size_t separator_pos = line.find(kFieldSeparator);
+      ASSERT_NE(std::string::npos, separator_pos);
+      string16 field_type = UTF8ToUTF16(line.substr(0, separator_pos));
+      string16 value = UTF8ToUTF16(line.substr(separator_pos + kFieldOffset));
+
+      webkit_glue::FormField field(field_type,
+                                   field_type,
+                                   value,
+                                   ASCIIToUTF16("text"),
+                                   WebKit::WebInputElement::defaultMaxLength(),
+                                   false);
+      form.fields.push_back(field);
+    }
+
+    // The first line is always a profile separator, and the last profile is not
+    // followed by an explicit separator.
+    if ((i > 0 && line == kProfileSeparator) ||
+        i == lines.size() - 1) {
+      // Reached the end of a profile.  Try to import it.
+      FormStructure form_structure(form);
+      for (size_t i = 0; i < form_structure.field_count(); ++i) {
+        // Set the heuristic type for each field, which is currently serialized
+        // into the field's name.
+        AutoFillField* field =
+            const_cast<AutoFillField*>(form_structure.field(i));
+        AutoFillFieldType type =
+            AutoFillType::StringToFieldType(UTF16ToUTF8(field->name()));
+        field->set_heuristic_type(type);
+      }
+      std::vector<const FormStructure*> form_structures(1, &form_structure);
+
+      // Import the profile.
+      const CreditCard* imported_credit_card;
+      personal_data_->ImportFormData(form_structures, &imported_credit_card);
+      EXPECT_FALSE(imported_credit_card);
+
+      // Clear the |form| to start a new profile.
+      form.fields.clear();
+    }
+  }
+
+  *merged_profiles = SerializeProfiles(personal_data_->web_profiles());
+}
+
+TEST_F(AutoFillMergeTest, DataDrivenMergeProfiles) {
+  RunDataDrivenTest(GetInputDirectory(kTestName), GetOutputDirectory(kTestName),
+                    kFileNamePattern);
+}
diff --git a/chrome/browser/autofill/autofill_metrics.cc b/chrome/browser/autofill/autofill_metrics.cc
index bae11d7..da30064 100644
--- a/chrome/browser/autofill/autofill_metrics.cc
+++ b/chrome/browser/autofill/autofill_metrics.cc
@@ -19,9 +19,13 @@
                             NUM_SERVER_QUERY_METRICS);
 }
 
-void AutoFillMetrics::Log(QualityMetric metric) const {
+void AutoFillMetrics::Log(QualityMetric metric,
+                          const std::string& experiment_id) const {
   DCHECK(metric < NUM_QUALITY_METRICS);
 
-  UMA_HISTOGRAM_ENUMERATION("AutoFill.Quality", metric,
-                            NUM_QUALITY_METRICS);
+  std::string histogram_name = "AutoFill.Quality";
+  if (!experiment_id.empty())
+    histogram_name += "_" + experiment_id;
+
+  UMA_HISTOGRAM_ENUMERATION(histogram_name, metric, NUM_QUALITY_METRICS);
 }
diff --git a/chrome/browser/autofill/autofill_metrics.h b/chrome/browser/autofill/autofill_metrics.h
index 6318274..6afc364 100644
--- a/chrome/browser/autofill/autofill_metrics.h
+++ b/chrome/browser/autofill/autofill_metrics.h
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_AUTOFILL_AUTOFILL_METRICS_H_
 #pragma once
 
+#include <string>
+
 #include "base/basictypes.h"
 
 class AutoFillMetrics {
@@ -45,6 +47,13 @@
     // |is_autofilled()| but as a value that is present in the personal data
     // manager.
     FIELD_AUTOFILL_FAILED,
+    // The below are only logged when |FIELD_AUTOFILL_FAILED| is also logged.
+    FIELD_HEURISTIC_TYPE_UNKNOWN,
+    FIELD_HEURISTIC_TYPE_MATCH,
+    FIELD_HEURISTIC_TYPE_MISMATCH,
+    FIELD_SERVER_TYPE_UNKNOWN,
+    FIELD_SERVER_TYPE_MATCH,
+    FIELD_SERVER_TYPE_MISMATCH,
     NUM_QUALITY_METRICS
   };
 
@@ -52,7 +61,8 @@
   virtual ~AutoFillMetrics();
 
   virtual void Log(ServerQueryMetric metric) const;
-  virtual void Log(QualityMetric metric) const;
+  virtual void Log(QualityMetric metric,
+                   const std::string& experiment_id) const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AutoFillMetrics);
diff --git a/chrome/browser/autofill/autofill_metrics_unittest.cc b/chrome/browser/autofill/autofill_metrics_unittest.cc
index 4521296..007b90c 100644
--- a/chrome/browser/autofill/autofill_metrics_unittest.cc
+++ b/chrome/browser/autofill/autofill_metrics_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
@@ -85,7 +87,8 @@
  public:
   MockAutoFillMetrics() {}
   MOCK_CONST_METHOD1(Log, void(ServerQueryMetric metric));
-  MOCK_CONST_METHOD1(Log, void(QualityMetric metric));
+  MOCK_CONST_METHOD2(Log, void(QualityMetric metric,
+                               const std::string& experiment_id));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockAutoFillMetrics);
@@ -112,12 +115,48 @@
         AutoFillManager::metric_logger());
   }
 
+  void AddSeenForm(FormStructure* form) {
+    form_structures()->push_back(form);
+  }
+
  private:
   bool autofill_enabled_;
 
   DISALLOW_COPY_AND_ASSIGN(TestAutoFillManager);
 };
 
+class TestFormStructure : public FormStructure {
+ public:
+  explicit TestFormStructure(const FormData& form) : FormStructure(form) {}
+  virtual ~TestFormStructure() {}
+
+  void SetFieldTypes(const std::vector<AutoFillFieldType>& heuristic_types,
+                     const std::vector<AutoFillFieldType>& server_types) {
+    ASSERT_EQ(field_count(), heuristic_types.size());
+    ASSERT_EQ(field_count(), server_types.size());
+
+    for (size_t i = 0; i < field_count(); ++i) {
+      AutoFillField* field = (*fields())[i];
+      ASSERT_TRUE(field);
+      field->set_heuristic_type(heuristic_types[i]);
+      field->set_server_type(server_types[i]);
+    }
+
+    UpdateAutoFillCount();
+  }
+
+  virtual std::string server_experiment_id() const OVERRIDE {
+    return server_experiment_id_;
+  }
+  void set_server_experiment_id(const std::string& server_experiment_id) {
+    server_experiment_id_ = server_experiment_id;
+  }
+
+ private:
+  std::string server_experiment_id_;
+  DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
+};
+
 }  // namespace
 
 class AutoFillMetricsTest : public RenderViewHostTestHarness {
@@ -173,23 +212,235 @@
       "Select", "select", "USA", "select-one", &field);
   form.fields.push_back(field);
 
+  // Simulate having seen this form on page load.
+  // |form_structure| will be owned by |autofill_manager_|.
+  TestFormStructure* form_structure = new TestFormStructure(form);
+  autofill_manager_->AddSeenForm(form_structure);
+
   // Establish our expectations.
   ::testing::InSequence dummy;
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_SUBMITTED));
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_AUTOFILLED));
+              Log(AutoFillMetrics::FIELD_AUTOFILLED, std::string()));
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_SUBMITTED));
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED ));
+              Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED, std::string()));
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_SUBMITTED));
+              Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+                  std::string()));
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_SUBMITTED));
+              Log(AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
 
   // Simulate form submission.
-  EXPECT_NO_FATAL_FAILURE(autofill_manager_->FormSubmitted(form));
+  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
+}
+
+// Test that we log the appropriate additional metrics when AutoFill failed.
+TEST_F(AutoFillMetricsTest, QualityMetricsForFailure) {
+  // Set up our form data.
+  FormData form;
+  form.name = ASCIIToUTF16("TestForm");
+  form.method = ASCIIToUTF16("POST");
+  form.origin = GURL("http://example.com/form.html");
+  form.action = GURL("http://example.com/submit.html");
+  form.user_submitted = true;
+
+  struct {
+    const char* label;
+    const char* name;
+    const char* value;
+    AutoFillFieldType heuristic_type;
+    AutoFillFieldType server_type;
+    AutoFillMetrics::QualityMetric heuristic_metric;
+    AutoFillMetrics::QualityMetric server_metric;
+  } failure_cases[] = {
+    {
+      "Heuristics unknown, server unknown", "0,0", "Elvis",
+      UNKNOWN_TYPE, NO_SERVER_DATA,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+      AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN
+    },
+    {
+      "Heuristics match, server unknown", "1,0", "Aaron",
+      NAME_MIDDLE, NO_SERVER_DATA,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH,
+      AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN
+    },
+    {
+      "Heuristics mismatch, server unknown", "2,0", "Presley",
+      PHONE_HOME_NUMBER, NO_SERVER_DATA,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH,
+      AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN
+    },
+    {
+      "Heuristics unknown, server match", "0,1", "theking@gmail.com",
+      UNKNOWN_TYPE, EMAIL_ADDRESS,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+      AutoFillMetrics::FIELD_SERVER_TYPE_MATCH
+    },
+    {
+      "Heuristics match, server match", "1,1", "3734 Elvis Presley Blvd.",
+      ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE1,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH,
+      AutoFillMetrics::FIELD_SERVER_TYPE_MATCH
+    },
+    {
+      "Heuristics mismatch, server match", "2,1", "Apt. 10",
+      PHONE_HOME_NUMBER, ADDRESS_HOME_LINE2,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH,
+      AutoFillMetrics::FIELD_SERVER_TYPE_MATCH
+    },
+    {
+      "Heuristics unknown, server mismatch", "0,2", "Memphis",
+      UNKNOWN_TYPE, PHONE_HOME_NUMBER,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+      AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH
+    },
+    {
+      "Heuristics match, server mismatch", "1,2", "Tennessee",
+      ADDRESS_HOME_STATE, PHONE_HOME_NUMBER,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH,
+      AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH
+    },
+    {
+      "Heuristics mismatch, server mismatch", "2,2", "38116",
+      PHONE_HOME_NUMBER, PHONE_HOME_NUMBER,
+      AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH,
+      AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH
+    }
+  };
+
+  std::vector<AutoFillFieldType> heuristic_types, server_types;
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(failure_cases); ++i) {
+    FormField field;
+    autofill_test::CreateTestFormField(failure_cases[i].label,
+                                       failure_cases[i].name,
+                                       failure_cases[i].value, "text", &field);
+    form.fields.push_back(field);
+    heuristic_types.push_back(failure_cases[i].heuristic_type);
+    server_types.push_back(failure_cases[i].server_type);
+
+  }
+
+  // Simulate having seen this form with the desired heuristic and server types.
+  // |form_structure| will be owned by |autofill_manager_|.
+  TestFormStructure* form_structure = new TestFormStructure(form);
+  form_structure->SetFieldTypes(heuristic_types, server_types);
+  autofill_manager_->AddSeenForm(form_structure);
+
+  // Establish our expectations.
+  ::testing::InSequence dummy;
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(failure_cases); ++i) {
+    EXPECT_CALL(*autofill_manager_->metric_logger(),
+                Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+    EXPECT_CALL(*autofill_manager_->metric_logger(),
+                Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED, std::string()));
+    EXPECT_CALL(*autofill_manager_->metric_logger(),
+                Log(failure_cases[i].heuristic_metric, std::string()));
+    EXPECT_CALL(*autofill_manager_->metric_logger(),
+                Log(failure_cases[i].server_metric, std::string()));
+  }
+
+  // Simulate form submission.
+  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
+}
+
+// Test that we behave sanely when the cached form differs from the submitted
+// one.
+TEST_F(AutoFillMetricsTest, SaneMetricsWithCacheMismatch) {
+  // Set up our form data.
+  FormData form;
+  form.name = ASCIIToUTF16("TestForm");
+  form.method = ASCIIToUTF16("POST");
+  form.origin = GURL("http://example.com/form.html");
+  form.action = GURL("http://example.com/submit.html");
+  form.user_submitted = true;
+
+  std::vector<AutoFillFieldType> heuristic_types, server_types;
+
+  FormField field;
+  autofill_test::CreateTestFormField(
+      "Both match", "match", "Elvis Presley", "text", &field);
+  field.set_autofilled(true);
+  form.fields.push_back(field);
+  heuristic_types.push_back(NAME_FULL);
+  server_types.push_back(NAME_FULL);
+  autofill_test::CreateTestFormField(
+      "Both mismatch", "mismatch", "buddy@gmail.com", "text", &field);
+  form.fields.push_back(field);
+  heuristic_types.push_back(PHONE_HOME_NUMBER);
+  server_types.push_back(PHONE_HOME_NUMBER);
+  autofill_test::CreateTestFormField(
+      "Only heuristics match", "mixed", "Memphis", "text", &field);
+  form.fields.push_back(field);
+  heuristic_types.push_back(ADDRESS_HOME_CITY);
+  server_types.push_back(PHONE_HOME_NUMBER);
+  autofill_test::CreateTestFormField(
+      "Unknown", "unknown", "garbage", "text", &field);
+  form.fields.push_back(field);
+  heuristic_types.push_back(UNKNOWN_TYPE);
+  server_types.push_back(UNKNOWN_TYPE);
+
+  // Simulate having seen this form with the desired heuristic and server types.
+  // |form_structure| will be owned by |autofill_manager_|.
+  TestFormStructure* form_structure = new TestFormStructure(form);
+  form_structure->SetFieldTypes(heuristic_types, server_types);
+  autofill_manager_->AddSeenForm(form_structure);
+
+  // Add a field and re-arrange the remaining form fields before submitting.
+  std::vector<FormField> cached_fields = form.fields;
+  form.fields.clear();
+  autofill_test::CreateTestFormField(
+      "New field", "new field", "Tennessee", "text", &field);
+  form.fields.push_back(field);
+  form.fields.push_back(cached_fields[2]);
+  form.fields.push_back(cached_fields[1]);
+  form.fields.push_back(cached_fields[3]);
+  form.fields.push_back(cached_fields[0]);
+
+  // Establish our expectations.
+  ::testing::InSequence dummy;
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+                  std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH,
+                  std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string()));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_AUTOFILLED, std::string()));
+
+  // Simulate form submission.
+  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
 }
 
 // Test that we don't log quality metrics for non-autofillable forms.
@@ -213,8 +464,8 @@
 
   // Simulate form submission.
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_SUBMITTED)).Times(0);
-  EXPECT_NO_FATAL_FAILURE(autofill_manager_->FormSubmitted(form));
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string())).Times(0);
+  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
 
   // Search forms are not auto-fillable.
   form.action = GURL("http://example.com/search?q=Elvis%20Presley");
@@ -224,6 +475,66 @@
 
   // Simulate form submission.
   EXPECT_CALL(*autofill_manager_->metric_logger(),
-              Log(AutoFillMetrics::FIELD_SUBMITTED)).Times(0);
-  EXPECT_NO_FATAL_FAILURE(autofill_manager_->FormSubmitted(form));
+              Log(AutoFillMetrics::FIELD_SUBMITTED, std::string())).Times(0);
+  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
+}
+
+// Test that we recored the experiment id appropriately.
+TEST_F(AutoFillMetricsTest, QualityMetricsWithExperimentId) {
+  // Set up our form data.
+  FormData form;
+  form.name = ASCIIToUTF16("TestForm");
+  form.method = ASCIIToUTF16("POST");
+  form.origin = GURL("http://example.com/form.html");
+  form.action = GURL("http://example.com/submit.html");
+  form.user_submitted = true;
+
+  FormField field;
+  autofill_test::CreateTestFormField(
+      "Autofilled", "autofilled", "Elvis Presley", "text", &field);
+  field.set_autofilled(true);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Autofill Failed", "autofillfailed", "buddy@gmail.com", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Empty", "empty", "", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Unknown", "unknown", "garbage", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Select", "select", "USA", "select-one", &field);
+  form.fields.push_back(field);
+
+  const std::string experiment_id = "ThatOughtaDoIt";
+
+  // Simulate having seen this form on page load.
+  // |form_structure| will be owned by |autofill_manager_|.
+  TestFormStructure* form_structure = new TestFormStructure(form);
+  form_structure->set_server_experiment_id(experiment_id);
+  autofill_manager_->AddSeenForm(form_structure);
+
+  // Establish our expectations.
+  ::testing::InSequence dummy;
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_AUTOFILLED, experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED, experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN,
+                  experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN, experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, experiment_id));
+  EXPECT_CALL(*autofill_manager_->metric_logger(),
+              Log(AutoFillMetrics::FIELD_SUBMITTED, experiment_id));
+
+  // Simulate form submission.
+  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
 }
diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc
index b764f44..083971f 100644
--- a/chrome/browser/autofill/autofill_profile.cc
+++ b/chrome/browser/autofill/autofill_profile.cc
@@ -7,17 +7,18 @@
 #include <algorithm>
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/address.h"
 #include "chrome/browser/autofill/autofill_manager.h"
+#include "chrome/browser/autofill/autofill_type.h"
 #include "chrome/browser/autofill/contact_info.h"
 #include "chrome/browser/autofill/fax_number.h"
 #include "chrome/browser/autofill/home_address.h"
 #include "chrome/browser/autofill/home_phone_number.h"
 #include "chrome/common/guid.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -28,48 +29,15 @@
   (*personal_info)[AutoFillType::ADDRESS_HOME] = new HomeAddress();
 }
 
-// Maps |field_type| to a field type that can be directly stored in a profile
-// (in the sense that it makes sense to call |AutoFillProfile::SetInfo()| with
-// the returned field type as the first parameter.
-AutoFillFieldType GetEquivalentFieldType(AutoFillFieldType field_type) {
-  // When billing information is requested from the profile we map to the
-  // home address equivalents.
-  switch (field_type) {
-    case ADDRESS_BILLING_LINE1:
-      return ADDRESS_HOME_LINE1;
-
-    case ADDRESS_BILLING_LINE2:
-      return ADDRESS_HOME_LINE2;
-
-    case ADDRESS_BILLING_APT_NUM:
-      return ADDRESS_HOME_APT_NUM;
-
-    case ADDRESS_BILLING_CITY:
-      return ADDRESS_HOME_CITY;
-
-    case ADDRESS_BILLING_STATE:
-      return ADDRESS_HOME_STATE;
-
-    case ADDRESS_BILLING_ZIP:
-      return ADDRESS_HOME_ZIP;
-
-    case ADDRESS_BILLING_COUNTRY:
-      return ADDRESS_HOME_COUNTRY;
-
-    default:
-      return field_type;
-  }
-}
-
-// Like |GetEquivalentFieldType()| above, but also returns |NAME_FULL| for
-// first, middle, and last name field types.
+// Like |AutoFillType::GetEquivalentFieldType()|, but also returns |NAME_FULL|
+// for first, middle, and last name field types.
 AutoFillFieldType GetEquivalentFieldTypeCollapsingNames(
     AutoFillFieldType field_type) {
   if (field_type == NAME_FIRST || field_type == NAME_MIDDLE ||
       field_type == NAME_LAST)
     return NAME_FULL;
 
-  return GetEquivalentFieldType(field_type);
+  return AutoFillType::GetEquivalentFieldType(field_type);
 }
 
 // Fills |distinguishing_fields| with a list of fields to use when creating
@@ -182,7 +150,9 @@
 }
 
 string16 AutoFillProfile::GetFieldText(const AutoFillType& type) const {
-  AutoFillType return_type(GetEquivalentFieldType(type.field_type()));
+  AutoFillType return_type(
+      AutoFillType::GetEquivalentFieldType(type.field_type()));
+
   FormGroupMap::const_iterator iter = personal_info_.find(return_type.group());
   if (iter == personal_info_.end() || iter->second == NULL)
     return string16();
diff --git a/chrome/browser/autofill/autofill_resources.grd b/chrome/browser/autofill/autofill_resources.grd
index 90c2ec2..475e706 100644
--- a/chrome/browser/autofill/autofill_resources.grd
+++ b/chrome/browser/autofill/autofill_resources.grd
@@ -64,22 +64,22 @@
         e.?mail<!-- ja-JP -->|メールアドレス<!-- ru -->|Электронной.?Почты<!-- zh-CN -->|邮件|邮箱<!-- zh-TW -->|電郵地址
       </message>
       <message name="IDS_AUTOFILL_NAME_ON_CARD_RE">
-        card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|name.?des.?karteninhabers<!-- zh-CN -->|信用卡开户名|开户名
+        card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|karteninhaber<!-- es -->|nombre.*tarjeta<!-- fr-FR -->|nom.*carte<!-- it-IT -->|nome.*cart<!-- ja-JP -->|名前<!-- ru -->|Имя.*карты<!-- zh-CN -->|信用卡开户名|开户名|持卡人姓名<!-- zh-TW -->|持卡人姓名
       </message>
       <message name="IDS_AUTOFILL_NAME_ON_CARD_CONTEXTUAL_RE">
         name
       </message>
       <message name="IDS_AUTOFILL_CARD_NUMBER_RE">
-        number|card.?#|card.?no|ccnum<!-- de-DE -->|kartennummer<!-- es -->|credito<!-- fr-FR -->|n.*de.*carte<!-- zh-CN -->|信用卡号
+        number|card.?#|card.?no|ccnum<!-- de-DE -->|nummer<!-- es -->|credito|numero|número<!-- fr-FR -->|numéro<!-- ja-JP -->|カード番号<!-- ru -->|Номер.*карты<!-- zh-CN -->|信用卡号|信用卡号码<!-- zh-TW -->|信用卡卡號
       </message>
       <message name="IDS_AUTOFILL_CARD_CVC_RE">
         verification|card identification|cvn|security code|cvv code|cvc
       </message>
       <message name="IDS_AUTOFILL_EXPIRATION_MONTH_RE">
-        expir|exp.*month|exp.*date|ccmonth
+        expir|exp.*month|exp.*date|ccmonth<!-- de-DE -->|gueltig|gültig|monat<!-- es -->|fecha<!-- fr-FR -->|date.*exp<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|月
       </message>
       <message name="IDS_AUTOFILL_EXPIRATION_DATE_RE">
-        exp|^/|year<!-- de-DE -->|ablaufdatum<!-- es -->|fecha.*de.*vencimiento
+        exp|^/|year<!-- de-DE -->|ablaufdatum|gueltig|gültig|yahr<!-- es -->|fecha<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|年|有效期
       </message>
       <message name="IDS_AUTOFILL_CARD_IGNORED_RE">
         ^card
diff --git a/chrome/browser/autofill/autofill_type.cc b/chrome/browser/autofill/autofill_type.cc
index 2fd8cf2..69485aa 100644
--- a/chrome/browser/autofill/autofill_type.cc
+++ b/chrome/browser/autofill/autofill_type.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/autofill/autofill_type.h"
 
 #include "base/basictypes.h"
+#include "base/logging.h"
 
 namespace {
 
@@ -167,3 +168,227 @@
 FieldTypeSubGroup AutoFillType::subgroup() const {
   return kAutoFillTypeDefinitions[field_type_].subgroup;
 }
+
+// static
+AutoFillFieldType AutoFillType::GetEquivalentFieldType(
+    AutoFillFieldType field_type) {
+  // When billing information is requested from the profile we map to the
+  // home address equivalents.
+  switch (field_type) {
+    case ADDRESS_BILLING_LINE1:
+      return ADDRESS_HOME_LINE1;
+
+    case ADDRESS_BILLING_LINE2:
+      return ADDRESS_HOME_LINE2;
+
+    case ADDRESS_BILLING_APT_NUM:
+      return ADDRESS_HOME_APT_NUM;
+
+    case ADDRESS_BILLING_CITY:
+      return ADDRESS_HOME_CITY;
+
+    case ADDRESS_BILLING_STATE:
+      return ADDRESS_HOME_STATE;
+
+    case ADDRESS_BILLING_ZIP:
+      return ADDRESS_HOME_ZIP;
+
+    case ADDRESS_BILLING_COUNTRY:
+      return ADDRESS_HOME_COUNTRY;
+
+    default:
+      return field_type;
+  }
+}
+
+// static
+std::string AutoFillType::FieldTypeToString(AutoFillFieldType type) {
+  switch (type) {
+    case NO_SERVER_DATA:
+      return "NO_SERVER_DATA";
+    case UNKNOWN_TYPE:
+      return "UNKNOWN_TYPE";
+    case EMPTY_TYPE:
+      return "EMPTY_TYPE";
+    case NAME_FIRST:
+      return "NAME_FIRST";
+    case NAME_MIDDLE:
+      return "NAME_MIDDLE";
+    case NAME_LAST:
+      return "NAME_LAST";
+    case NAME_MIDDLE_INITIAL:
+      return "NAME_MIDDLE_INITIAL";
+    case NAME_FULL:
+      return "NAME_FULL";
+    case NAME_SUFFIX:
+      return "NAME_SUFFIX";
+    case EMAIL_ADDRESS:
+      return "EMAIL_ADDRESS";
+    case PHONE_HOME_NUMBER:
+      return "PHONE_HOME_NUMBER";
+    case PHONE_HOME_CITY_CODE:
+      return "PHONE_HOME_CITY_CODE";
+    case PHONE_HOME_COUNTRY_CODE:
+      return "PHONE_HOME_COUNTRY_CODE";
+    case PHONE_HOME_CITY_AND_NUMBER:
+      return "PHONE_HOME_CITY_AND_NUMBER";
+    case PHONE_HOME_WHOLE_NUMBER:
+      return "PHONE_HOME_WHOLE_NUMBER";
+    case PHONE_FAX_NUMBER:
+      return "PHONE_FAX_NUMBER";
+    case PHONE_FAX_CITY_CODE:
+      return "PHONE_FAX_CITY_CODE";
+    case PHONE_FAX_COUNTRY_CODE:
+      return "PHONE_FAX_COUNTRY_CODE";
+    case PHONE_FAX_CITY_AND_NUMBER:
+      return "PHONE_FAX_CITY_AND_NUMBER";
+    case PHONE_FAX_WHOLE_NUMBER:
+      return "PHONE_FAX_WHOLE_NUMBER";
+    case ADDRESS_HOME_LINE1:
+      return "ADDRESS_HOME_LINE1";
+    case ADDRESS_HOME_LINE2:
+      return "ADDRESS_HOME_LINE2";
+    case ADDRESS_HOME_APT_NUM:
+      return "ADDRESS_HOME_APT_NUM";
+    case ADDRESS_HOME_CITY:
+      return "ADDRESS_HOME_CITY";
+    case ADDRESS_HOME_STATE:
+      return "ADDRESS_HOME_STATE";
+    case ADDRESS_HOME_ZIP:
+      return "ADDRESS_HOME_ZIP";
+    case ADDRESS_HOME_COUNTRY:
+      return "ADDRESS_HOME_COUNTRY";
+    case ADDRESS_BILLING_LINE1:
+      return "ADDRESS_BILLING_LINE1";
+    case ADDRESS_BILLING_LINE2:
+      return "ADDRESS_BILLING_LINE2";
+    case ADDRESS_BILLING_APT_NUM:
+      return "ADDRESS_BILLING_APT_NUM";
+    case ADDRESS_BILLING_CITY:
+      return "ADDRESS_BILLING_CITY";
+    case ADDRESS_BILLING_STATE:
+      return "ADDRESS_BILLING_STATE";
+    case ADDRESS_BILLING_ZIP:
+      return "ADDRESS_BILLING_ZIP";
+    case ADDRESS_BILLING_COUNTRY:
+      return "ADDRESS_BILLING_COUNTRY";
+    case CREDIT_CARD_NAME:
+      return "CREDIT_CARD_NAME";
+    case CREDIT_CARD_NUMBER:
+      return "CREDIT_CARD_NUMBER";
+    case CREDIT_CARD_EXP_MONTH:
+      return "CREDIT_CARD_EXP_MONTH";
+    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
+      return "CREDIT_CARD_EXP_2_DIGIT_YEAR";
+    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
+      return "CREDIT_CARD_EXP_4_DIGIT_YEAR";
+    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
+      return "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR";
+    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
+      return "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR";
+    case CREDIT_CARD_TYPE:
+      return "CREDIT_CARD_TYPE";
+    case CREDIT_CARD_VERIFICATION_CODE:
+      return "CREDIT_CARD_VERIFICATION_CODE";
+    case COMPANY_NAME:
+      return "COMPANY_NAME";
+    default:
+      NOTREACHED() << "Invalid AutoFillFieldType value.";
+  }
+  return std::string();
+}
+
+// static
+AutoFillFieldType AutoFillType::StringToFieldType(const std::string& str) {
+  if (str == "NO_SERVER_DATA")
+    return NO_SERVER_DATA;
+  if (str == "UNKNOWN_TYPE")
+    return UNKNOWN_TYPE;
+  if (str == "EMPTY_TYPE")
+    return EMPTY_TYPE;
+  if (str == "NAME_FIRST")
+    return NAME_FIRST;
+  if (str == "NAME_MIDDLE")
+    return NAME_MIDDLE;
+  if (str == "NAME_LAST")
+    return NAME_LAST;
+  if (str == "NAME_MIDDLE_INITIAL")
+    return NAME_MIDDLE_INITIAL;
+  if (str == "NAME_FULL")
+    return NAME_FULL;
+  if (str == "NAME_SUFFIX")
+    return NAME_SUFFIX;
+  if (str == "EMAIL_ADDRESS")
+    return EMAIL_ADDRESS;
+  if (str == "PHONE_HOME_NUMBER")
+    return PHONE_HOME_NUMBER;
+  if (str == "PHONE_HOME_CITY_CODE")
+    return PHONE_HOME_CITY_CODE;
+  if (str == "PHONE_HOME_COUNTRY_CODE")
+    return PHONE_HOME_COUNTRY_CODE;
+  if (str == "PHONE_HOME_CITY_AND_NUMBER")
+    return PHONE_HOME_CITY_AND_NUMBER;
+  if (str == "PHONE_HOME_WHOLE_NUMBER")
+    return PHONE_HOME_WHOLE_NUMBER;
+  if (str == "PHONE_FAX_NUMBER")
+    return PHONE_FAX_NUMBER;
+  if (str == "PHONE_FAX_CITY_CODE")
+    return PHONE_FAX_CITY_CODE;
+  if (str == "PHONE_FAX_COUNTRY_CODE")
+    return PHONE_FAX_COUNTRY_CODE;
+  if (str == "PHONE_FAX_CITY_AND_NUMBER")
+    return PHONE_FAX_CITY_AND_NUMBER;
+  if (str == "PHONE_FAX_WHOLE_NUMBER")
+    return PHONE_FAX_WHOLE_NUMBER;
+  if (str == "ADDRESS_HOME_LINE1")
+    return ADDRESS_HOME_LINE1;
+  if (str == "ADDRESS_HOME_LINE2")
+    return ADDRESS_HOME_LINE2;
+  if (str == "ADDRESS_HOME_APT_NUM")
+    return ADDRESS_HOME_APT_NUM;
+  if (str == "ADDRESS_HOME_CITY")
+    return ADDRESS_HOME_CITY;
+  if (str == "ADDRESS_HOME_STATE")
+    return ADDRESS_HOME_STATE;
+  if (str == "ADDRESS_HOME_ZIP")
+    return ADDRESS_HOME_ZIP;
+  if (str == "ADDRESS_HOME_COUNTRY")
+    return ADDRESS_HOME_COUNTRY;
+  if (str == "ADDRESS_BILLING_LINE1")
+    return ADDRESS_BILLING_LINE1;
+  if (str == "ADDRESS_BILLING_LINE2")
+    return ADDRESS_BILLING_LINE2;
+  if (str == "ADDRESS_BILLING_APT_NUM")
+    return ADDRESS_BILLING_APT_NUM;
+  if (str == "ADDRESS_BILLING_CITY")
+    return ADDRESS_BILLING_CITY;
+  if (str == "ADDRESS_BILLING_STATE")
+    return ADDRESS_BILLING_STATE;
+  if (str == "ADDRESS_BILLING_ZIP")
+    return ADDRESS_BILLING_ZIP;
+  if (str == "ADDRESS_BILLING_COUNTRY")
+    return ADDRESS_BILLING_COUNTRY;
+  if (str == "CREDIT_CARD_NAME")
+    return CREDIT_CARD_NAME;
+  if (str == "CREDIT_CARD_NUMBER")
+    return CREDIT_CARD_NUMBER;
+  if (str == "CREDIT_CARD_EXP_MONTH")
+    return CREDIT_CARD_EXP_MONTH;
+  if (str == "CREDIT_CARD_EXP_2_DIGIT_YEAR")
+    return CREDIT_CARD_EXP_2_DIGIT_YEAR;
+  if (str == "CREDIT_CARD_EXP_4_DIGIT_YEAR")
+    return CREDIT_CARD_EXP_4_DIGIT_YEAR;
+  if (str == "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR")
+    return CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
+  if (str == "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR")
+    return CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
+  if (str == "CREDIT_CARD_TYPE")
+    return CREDIT_CARD_TYPE;
+  if (str == "CREDIT_CARD_VERIFICATION_CODE")
+    return CREDIT_CARD_VERIFICATION_CODE;
+  if (str == "COMPANY_NAME")
+    return COMPANY_NAME;
+
+  NOTREACHED() << "Unknown AutoFillFieldType " << str;
+  return UNKNOWN_TYPE;
+}
diff --git a/chrome/browser/autofill/autofill_type.h b/chrome/browser/autofill/autofill_type.h
index 2091153..a7861af 100644
--- a/chrome/browser/autofill/autofill_type.h
+++ b/chrome/browser/autofill/autofill_type.h
@@ -8,6 +8,7 @@
 
 #include <map>
 #include <set>
+#include <string>
 
 #include "base/string16.h"
 #include "chrome/browser/autofill/field_types.h"
@@ -58,6 +59,15 @@
   FieldTypeGroup group() const;
   FieldTypeSubGroup subgroup() const;
 
+  // Maps |field_type| to a field type that can be directly stored in a profile
+  // (in the sense that it makes sense to call |AutoFillProfile::SetInfo()| with
+  // the returned field type as the first parameter).
+  static AutoFillFieldType GetEquivalentFieldType(AutoFillFieldType field_type);
+
+  // Utilities for serializing and deserializing an |AutoFillFieldType|.
+  static std::string FieldTypeToString(AutoFillFieldType field_type);
+  static AutoFillFieldType StringToFieldType(const std::string& str);
+
  private:
   AutoFillFieldType field_type_;
 };
diff --git a/chrome/browser/autofill/autofill_xml_parser.cc b/chrome/browser/autofill/autofill_xml_parser.cc
index 4577c38..decbee4 100644
--- a/chrome/browser/autofill/autofill_xml_parser.cc
+++ b/chrome/browser/autofill/autofill_xml_parser.cc
@@ -4,9 +4,6 @@
 
 #include "chrome/browser/autofill/autofill_xml_parser.h"
 
-#include <string>
-#include <vector>
-
 #include "chrome/browser/autofill/autofill_type.h"
 #include "third_party/libjingle/overrides/talk/xmllite/qname.h"
 
@@ -29,30 +26,42 @@
 
 AutoFillQueryXmlParser::AutoFillQueryXmlParser(
     std::vector<AutoFillFieldType>* field_types,
-    UploadRequired* upload_required)
+    UploadRequired* upload_required,
+    std::string* experiment_id)
     : field_types_(field_types),
-      upload_required_(upload_required) {
+      upload_required_(upload_required),
+      experiment_id_(experiment_id) {
   DCHECK(upload_required_);
+  DCHECK(experiment_id_);
 }
 
 void AutoFillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
                                           const char* name,
                                           const char** attrs) {
   buzz::QName qname = context->ResolveQName(name, false);
-  const std::string &element = qname.LocalPart();
+  const std::string& element = qname.LocalPart();
   if (element.compare("autofillqueryresponse") == 0) {
-    // Check for the upload required attribute.  If it's not present, we use the
-    // default upload rates.
+    // We check for the upload required attribute below, but if it's not
+    // present, we use the default upload rates. Likewise, by default we assume
+    // an empty experiment id.
     *upload_required_ = USE_UPLOAD_RATES;
-    if (*attrs) {
+    *experiment_id_ = std::string();
+
+    // |attrs| is a NULL-terminated list of (attribute, value) pairs.
+    while (*attrs) {
       buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
-      const std::string &attribute_name = attribute_qname.LocalPart();
+      const std::string& attribute_name = attribute_qname.LocalPart();
       if (attribute_name.compare("uploadrequired") == 0) {
         if (strcmp(attrs[1], "true") == 0)
           *upload_required_ = UPLOAD_REQUIRED;
         else if (strcmp(attrs[1], "false") == 0)
           *upload_required_ = UPLOAD_NOT_REQUIRED;
+      } else if (attribute_name.compare("experimentid") == 0) {
+        *experiment_id_ = attrs[1];
       }
+
+      // Advance to the next (attribute, value) pair.
+      attrs += 2;
     }
   } else if (element.compare("field") == 0) {
     if (!attrs[0]) {
@@ -65,7 +74,7 @@
     // attribute (autofilltype) with an integer value.
     AutoFillFieldType field_type = UNKNOWN_TYPE;
     buzz::QName attribute_qname = context->ResolveQName(attrs[0], true);
-    const std::string &attribute_name = attribute_qname.LocalPart();
+    const std::string& attribute_name = attribute_qname.LocalPart();
 
     if (attribute_name.compare("autofilltype") == 0) {
       int value = GetIntValue(context, attrs[1]);
diff --git a/chrome/browser/autofill/autofill_xml_parser.h b/chrome/browser/autofill/autofill_xml_parser.h
index 9a58011..5afe03a 100644
--- a/chrome/browser/autofill/autofill_xml_parser.h
+++ b/chrome/browser/autofill/autofill_xml_parser.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_AUTOFILL_AUTOFILL_XML_PARSER_H_
 #pragma once
 
+#include <string>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -51,7 +52,7 @@
 // The XML parse handler for parsing AutoFill query responses.  A typical
 // response looks like:
 //
-// <autofillqueryresponse>
+// <autofillqueryresponse experimentid="1">
 //   <field autofilltype="0" />
 //   <field autofilltype="1" />
 //   <field autofilltype="3" />
@@ -64,7 +65,8 @@
 class AutoFillQueryXmlParser : public AutoFillXmlParser {
  public:
   AutoFillQueryXmlParser(std::vector<AutoFillFieldType>* field_types,
-                         UploadRequired* upload_required);
+                         UploadRequired* upload_required,
+                         std::string* experiment_id);
 
  private:
   // A callback for the beginning of a new <element>, called by Expat.
@@ -87,6 +89,10 @@
   // form is submitted.
   UploadRequired* upload_required_;
 
+  // The server experiment to which this query response belongs.
+  // For the default server implementation, this is empty.
+  std::string* experiment_id_;
+
   DISALLOW_COPY_AND_ASSIGN(AutoFillQueryXmlParser);
 };
 
diff --git a/chrome/browser/autofill/autofill_xml_parser_unittest.cc b/chrome/browser/autofill/autofill_xml_parser_unittest.cc
index ec5ebb5..11d1ee6 100644
--- a/chrome/browser/autofill/autofill_xml_parser_unittest.cc
+++ b/chrome/browser/autofill/autofill_xml_parser_unittest.cc
@@ -24,71 +24,140 @@
   // Create a vector of AutoFillFieldTypes, to assign the parsed field types to.
   std::vector<AutoFillFieldType> field_types;
   UploadRequired upload_required = USE_UPLOAD_RATES;
+  std::string experiment_id;
 
   // Create a parser.
-  AutoFillQueryXmlParser parse_handler(&field_types, &upload_required);
+  AutoFillQueryXmlParser parse_handler(&field_types, &upload_required,
+                                       &experiment_id);
   buzz::XmlParser parser(&parse_handler);
   parser.Parse(xml.c_str(), xml.length(), true);
   EXPECT_TRUE(parse_handler.succeeded());
-  EXPECT_EQ(upload_required, USE_UPLOAD_RATES);
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
   ASSERT_EQ(4U, field_types.size());
   EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
   EXPECT_EQ(UNKNOWN_TYPE, field_types[1]);
   EXPECT_EQ(NAME_FIRST, field_types[2]);
   EXPECT_EQ(EMPTY_TYPE, field_types[3]);
+  EXPECT_EQ(std::string(), experiment_id);
 }
 
 // Test parsing the upload required attribute.
 TEST(AutoFillQueryXmlParserTest, TestUploadRequired) {
   std::vector<AutoFillFieldType> field_types;
   UploadRequired upload_required = USE_UPLOAD_RATES;
+  std::string experiment_id;
 
   std::string xml = "<autofillqueryresponse uploadrequired=\"true\">"
                     "<field autofilltype=\"0\" />"
                     "</autofillqueryresponse>";
 
   scoped_ptr<AutoFillQueryXmlParser> parse_handler(
-      new AutoFillQueryXmlParser(&field_types, &upload_required));
+      new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                 &experiment_id));
   scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get()));
   parser->Parse(xml.c_str(), xml.length(), true);
   EXPECT_TRUE(parse_handler->succeeded());
   EXPECT_EQ(UPLOAD_REQUIRED, upload_required);
   ASSERT_EQ(1U, field_types.size());
   EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string(), experiment_id);
 
   field_types.clear();
   xml = "<autofillqueryresponse uploadrequired=\"false\">"
         "<field autofilltype=\"0\" />"
         "</autofillqueryresponse>";
 
-  parse_handler.reset(
-      new AutoFillQueryXmlParser(&field_types, &upload_required));
+  parse_handler.reset(new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                                 &experiment_id));
   parser.reset(new buzz::XmlParser(parse_handler.get()));
   parser->Parse(xml.c_str(), xml.length(), true);
   EXPECT_TRUE(parse_handler->succeeded());
-  EXPECT_EQ(upload_required, UPLOAD_NOT_REQUIRED);
+  EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required);
   ASSERT_EQ(1U, field_types.size());
   EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string(), experiment_id);
 
   field_types.clear();
   xml = "<autofillqueryresponse uploadrequired=\"bad_value\">"
         "<field autofilltype=\"0\" />"
         "</autofillqueryresponse>";
 
-  parse_handler.reset(
-      new AutoFillQueryXmlParser(&field_types, &upload_required));
+  parse_handler.reset(new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                                 &experiment_id));
   parser.reset(new buzz::XmlParser(parse_handler.get()));
   parser->Parse(xml.c_str(), xml.length(), true);
   EXPECT_TRUE(parse_handler->succeeded());
-  EXPECT_EQ(upload_required, USE_UPLOAD_RATES);
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
   ASSERT_EQ(1U, field_types.size());
   EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string(), experiment_id);
+}
+
+// Test parsing the experiment id attribute
+TEST(AutoFillQueryXmlParserTest, ParseExperimentId) {
+  std::vector<AutoFillFieldType> field_types;
+  UploadRequired upload_required = USE_UPLOAD_RATES;
+  std::string experiment_id;
+
+  // When the attribute is missing, we should get back the default value -- the
+  // empty string.
+  std::string xml = "<autofillqueryresponse>"
+                    "<field autofilltype=\"0\" />"
+                    "</autofillqueryresponse>";
+
+  scoped_ptr<AutoFillQueryXmlParser> parse_handler(
+      new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                 &experiment_id));
+  scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get()));
+  parser->Parse(xml.c_str(), xml.length(), true);
+  EXPECT_TRUE(parse_handler->succeeded());
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
+  ASSERT_EQ(1U, field_types.size());
+  EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string(), experiment_id);
+
+  field_types.clear();
+
+  // When the attribute is present, make sure we parse it.
+  xml = "<autofillqueryresponse experimentid=\"FancyNewAlgorithm\">"
+        "<field autofilltype=\"0\" />"
+        "</autofillqueryresponse>";
+
+  parse_handler.reset(new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                                 &experiment_id));
+  parser.reset(new buzz::XmlParser(parse_handler.get()));
+  parser->Parse(xml.c_str(), xml.length(), true);
+  EXPECT_TRUE(parse_handler->succeeded());
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
+  ASSERT_EQ(1U, field_types.size());
+  EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string("FancyNewAlgorithm"), experiment_id);
+
+  field_types.clear();
+
+  // Make sure that we can handle parsing both the upload required and the
+  // experiment id attribute together.
+  xml = "<autofillqueryresponse uploadrequired=\"false\""
+        "                       experimentid=\"ServerSmartyPants\">"
+        "<field autofilltype=\"0\" />"
+        "</autofillqueryresponse>";
+
+  parse_handler.reset(new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                                 &experiment_id));
+  parser.reset(new buzz::XmlParser(parse_handler.get()));
+  parser->Parse(xml.c_str(), xml.length(), true);
+  EXPECT_TRUE(parse_handler->succeeded());
+  EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required);
+  ASSERT_EQ(1U, field_types.size());
+  EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string("ServerSmartyPants"), experiment_id);
 }
 
 // Test badly formed XML queries.
 TEST(AutoFillQueryXmlParserTest, ParseErrors) {
   std::vector<AutoFillFieldType> field_types;
   UploadRequired upload_required = USE_UPLOAD_RATES;
+  std::string experiment_id;
 
   // Test no AutoFill type.
   std::string xml = "<autofillqueryresponse>"
@@ -96,27 +165,30 @@
                     "</autofillqueryresponse>";
 
   scoped_ptr<AutoFillQueryXmlParser> parse_handler(
-      new AutoFillQueryXmlParser(&field_types, &upload_required));
+      new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                 &experiment_id));
   scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get()));
   parser->Parse(xml.c_str(), xml.length(), true);
   EXPECT_FALSE(parse_handler->succeeded());
-  EXPECT_EQ(upload_required, USE_UPLOAD_RATES);
-  ASSERT_EQ(0U, field_types.size());
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
+  EXPECT_EQ(0U, field_types.size());
+  EXPECT_EQ(std::string(), experiment_id);
 
   // Test an incorrect AutoFill type.
   xml = "<autofillqueryresponse>"
         "<field autofilltype=\"307\"/>"
         "</autofillqueryresponse>";
 
-  parse_handler.reset(
-      new AutoFillQueryXmlParser(&field_types, &upload_required));
+  parse_handler.reset(new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                                 &experiment_id));
   parser.reset(new buzz::XmlParser(parse_handler.get()));
   parser->Parse(xml.c_str(), xml.length(), true);
   EXPECT_TRUE(parse_handler->succeeded());
-  EXPECT_EQ(upload_required, USE_UPLOAD_RATES);
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
   ASSERT_EQ(1U, field_types.size());
   // AutoFillType was out of range and should be set to NO_SERVER_DATA.
   EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string(), experiment_id);
 
   // Test an incorrect AutoFill type.
   field_types.clear();
@@ -125,14 +197,15 @@
         "</autofillqueryresponse>";
 
   // Parse fails but an entry is still added to field_types.
-  parse_handler.reset(
-      new AutoFillQueryXmlParser(&field_types, &upload_required));
+  parse_handler.reset(new AutoFillQueryXmlParser(&field_types, &upload_required,
+                                                 &experiment_id));
   parser.reset(new buzz::XmlParser(parse_handler.get()));
   parser->Parse(xml.c_str(), xml.length(), true);
   EXPECT_FALSE(parse_handler->succeeded());
-  EXPECT_EQ(upload_required, USE_UPLOAD_RATES);
+  EXPECT_EQ(USE_UPLOAD_RATES, upload_required);
   ASSERT_EQ(1U, field_types.size());
   EXPECT_EQ(NO_SERVER_DATA, field_types[0]);
+  EXPECT_EQ(std::string(), experiment_id);
 }
 
 // Test successfull upload response.
diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc
index a24c629..ba6949b 100644
--- a/chrome/browser/autofill/credit_card.cc
+++ b/chrome/browser/autofill/credit_card.cc
@@ -6,8 +6,8 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
+#include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string16.h"
@@ -16,6 +16,9 @@
 #include "chrome/browser/autofill/field_types.h"
 #include "chrome/common/guid.h"
 #include "grit/generated_resources.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -329,6 +332,26 @@
   return label_;
 }
 
+void CreditCard::SetInfoForMonthInputType(const string16& value) {
+  // Check if |text| is "yyyy-mm" format first, and check normal month format.
+  WebKit::WebRegularExpression re(WebKit::WebString("^[0-9]{4}\\-[0-9]{1,2}$"),
+                                  WebKit::WebTextCaseInsensitive);
+  bool match = re.match(WebKit::WebString(StringToLowerASCII(value))) != -1;
+  if (match) {
+    std::vector<string16> year_month;
+    base::SplitString(value, L'-', &year_month);
+    DCHECK_EQ((int)year_month.size(), 2);
+    int num = 0;
+    bool converted = false;
+    converted = base::StringToInt(year_month[0], &num);
+    DCHECK(converted);
+    set_expiration_year(num);
+    converted = base::StringToInt(year_month[1], &num);
+    DCHECK(converted);
+    set_expiration_month(num);
+  }
+}
+
 string16 CreditCard::ObfuscatedNumber() const {
   if (number().empty())
     return string16();  // No CC number, means empty preview.
diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h
index 2b2d089..951b605 100644
--- a/chrome/browser/autofill/credit_card.h
+++ b/chrome/browser/autofill/credit_card.h
@@ -34,6 +34,9 @@
   virtual void SetInfo(const AutoFillType& type, const string16& value);
   virtual const string16 Label() const;
 
+  // Special method to set value for HTML5 month input type.
+  void SetInfoForMonthInputType(const string16& value);
+
   // The number altered for display, for example: ******1234
   string16 ObfuscatedNumber() const;
   // Credit card preview summary, for example: ******1234, Exp: 01/2020
diff --git a/chrome/browser/autofill/credit_card_field.cc b/chrome/browser/autofill/credit_card_field.cc
index 3a51b6f..746bdf9 100644
--- a/chrome/browser/autofill/credit_card_field.cc
+++ b/chrome/browser/autofill/credit_card_field.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/browser/autofill/credit_card_field.h"
 
-#include "app/l10n_util.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/autofill_field.h"
 #include "grit/autofill_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const {
   bool ok = Add(field_type_map, number_, AutoFillType(CREDIT_CARD_NUMBER));
@@ -118,35 +118,40 @@
         &credit_card_field->number_))
       continue;
 
-    // "Expiration date" is the most common label here, but some pages have
-    // "Expires", "exp. date" or "exp. month" and "exp. year".  We also look for
-    // the field names ccmonth and ccyear, which appear on at least 4 of our
-    // test pages.
-    //
-    // -> On at least one page (The China Shop2.html) we find only the labels
-    // "month" and "year".  So for now we match these words directly; we'll
-    // see if this turns out to be too general.
-    //
-    // Toolbar Bug 51451: indeed, simply matching "month" is too general for
-    //   https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init.
-    // Instead, we match only words beginning with "month".
-    if (is_ecml)
-      pattern = GetEcmlPattern(kEcmlCardExpireMonth);
-    else
-      pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_MONTH_RE);
-
-    if ((!credit_card_field->expiration_month_ ||
-        credit_card_field->expiration_month_->IsEmpty()) &&
-        ParseText(&q, pattern, &credit_card_field->expiration_month_)) {
+    if ((*q) && LowerCaseEqualsASCII((*q)->form_control_type(), "month")) {
+      credit_card_field->expiration_month_ = *q++;
+    } else {
+      // "Expiration date" is the most common label here, but some pages have
+      // "Expires", "exp. date" or "exp. month" and "exp. year".  We also look
+      // for the field names ccmonth and ccyear, which appear on at least 4 of
+      // our test pages.
+      //
+      // -> On at least one page (The China Shop2.html) we find only the labels
+      // "month" and "year".  So for now we match these words directly; we'll
+      // see if this turns out to be too general.
+      //
+      // Toolbar Bug 51451: indeed, simply matching "month" is too general for
+      //   https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init.
+      // Instead, we match only words beginning with "month".
       if (is_ecml)
-        pattern = GetEcmlPattern(kEcmlCardExpireYear);
+        pattern = GetEcmlPattern(kEcmlCardExpireMonth);
       else
-        pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_DATE_RE);
+        pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_MONTH_RE);
 
-      if (!ParseText(&q, pattern, &credit_card_field->expiration_year_))
-        return NULL;
+      if ((!credit_card_field->expiration_month_ ||
+          credit_card_field->expiration_month_->IsEmpty()) &&
+        ParseText(&q, pattern, &credit_card_field->expiration_month_)) {
 
-      continue;
+        if (is_ecml)
+          pattern = GetEcmlPattern(kEcmlCardExpireYear);
+        else
+          pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_DATE_RE);
+
+        if (!ParseText(&q, pattern, &credit_card_field->expiration_year_)) {
+          return NULL;
+        }
+        continue;
+      }
     }
 
     if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay)))
@@ -180,7 +185,10 @@
   // the cvc and date were found independently they are returned.
   if ((credit_card_field->number_ || credit_card_field->verification_) &&
       credit_card_field->expiration_month_ &&
-      credit_card_field->expiration_year_) {
+      (credit_card_field->expiration_year_ ||
+      (LowerCaseEqualsASCII(
+           credit_card_field->expiration_month_->form_control_type(),
+           "month")))) {
       *iter = q;
       return credit_card_field.release();
   }
diff --git a/chrome/browser/autofill/data_driven_test.cc b/chrome/browser/autofill/data_driven_test.cc
new file mode 100644
index 0000000..8aa04ac
--- /dev/null
+++ b/chrome/browser/autofill/data_driven_test.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/autofill/data_driven_test.h"
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Reads |file| into |content|, and converts Windows line-endings to Unix ones.
+// Returns true on success.
+bool ReadFile(const FilePath& file, std::string* content) {
+  if (!file_util::ReadFileToString(file, content))
+    return false;
+
+  ReplaceSubstringsAfterOffset(content, 0, "\r\n", "\n");
+  return true;
+}
+
+// Write |content| to |file|. Returns true on success.
+bool WriteFile(const FilePath& file, const std::string& content) {
+  int write_size = file_util::WriteFile(file, content.c_str(),
+                                        content.length());
+  return write_size == static_cast<int>(content.length());
+}
+
+}  // namespace
+
+void DataDrivenTest::RunDataDrivenTest(
+    const FilePath& input_directory,
+    const FilePath& output_directory,
+    const FilePath::StringType& file_name_pattern) {
+  file_util::FileEnumerator input_files(input_directory,
+                                        false,
+                                        file_util::FileEnumerator::FILES,
+                                        file_name_pattern);
+
+  for (FilePath input_file = input_files.Next();
+       !input_file.empty();
+       input_file = input_files.Next()) {
+    std::string input;
+    ASSERT_TRUE(ReadFile(input_file, &input));
+
+    std::string output;
+    GenerateResults(input, &output);
+
+    FilePath output_file = output_directory.Append(
+        input_file.BaseName().StripTrailingSeparators().ReplaceExtension(
+            FILE_PATH_LITERAL(".out")));
+
+    std::string output_file_contents;
+    if (ReadFile(output_file, &output_file_contents))
+      EXPECT_EQ(output_file_contents, output);
+    else
+      ASSERT_TRUE(WriteFile(output_file, output));
+  }
+}
+
+FilePath DataDrivenTest::GetInputDirectory(
+    const FilePath::StringType& test_name) {
+  FilePath test_data_dir_;
+  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
+  test_data_dir_ = test_data_dir_.AppendASCII("autofill")
+                                 .Append(test_name)
+                                 .AppendASCII("input");
+  return test_data_dir_;
+}
+
+FilePath DataDrivenTest::GetOutputDirectory(
+    const FilePath::StringType& test_name) {
+  FilePath test_data_dir_;
+  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
+  test_data_dir_ = test_data_dir_.AppendASCII("autofill")
+                                 .Append(test_name)
+                                 .AppendASCII("output");
+  return test_data_dir_;
+}
+
+DataDrivenTest::DataDrivenTest() {
+}
+
+DataDrivenTest::~DataDrivenTest() {
+}
diff --git a/chrome/browser/autofill/data_driven_test.h b/chrome/browser/autofill/data_driven_test.h
new file mode 100644
index 0000000..2bb5c54
--- /dev/null
+++ b/chrome/browser/autofill/data_driven_test.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_AUTOFILL_DATA_DRIVEN_TEST_H_
+#define CHROME_BROWSER_AUTOFILL_DATA_DRIVEN_TEST_H_
+#pragma once
+
+#include <string>
+
+#include "base/file_path.h"
+#include "base/string16.h"
+
+// A convenience class for implementing data-driven tests. Subclassers need only
+// implement the conversion of serialized input data to serialized output data
+// and provide a set of input files. For each input file, on the first run, a
+// gold output file is generated; for subsequent runs, the test ouptut is
+// compared to this gold output.
+class DataDrivenTest {
+ public:
+  // For each file in |input_directory| whose filename matches
+  // |file_name_pattern|, slurps in the file contents and calls into
+  // |GenerateResults()|. If the corresponding output file already exists in
+  // the |output_directory|, verifies that the results match the file contents;
+  // otherwise, writes a gold result file to the |output_directory|.
+  void RunDataDrivenTest(const FilePath& input_directory,
+                         const FilePath& output_directory,
+                         const FilePath::StringType& file_name_pattern);
+
+  // Given the |input| data, generates the |output| results. The output results
+  // must be stable across runs.
+  // Note: The return type is |void| so that googletest |ASSERT_*| macros will
+  // compile.
+  virtual void GenerateResults(const std::string& input,
+                               std::string* output) = 0;
+
+  // Return |FilePath|s to the test input and output subdirectories
+  // ../autofill/|test_name|/input and ../autofill/|test_name|/output.
+  FilePath GetInputDirectory(const FilePath::StringType& test_name);
+  FilePath GetOutputDirectory(const FilePath::StringType& test_name);
+
+ protected:
+  DataDrivenTest();
+  virtual ~DataDrivenTest();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DataDrivenTest);
+};
+
+#endif  // CHROME_BROWSER_AUTOFILL_DATA_DRIVEN_TEST_H_
diff --git a/chrome/browser/autofill/fax_field.cc b/chrome/browser/autofill/fax_field.cc
deleted file mode 100644
index 8475730..0000000
--- a/chrome/browser/autofill/fax_field.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/autofill/fax_field.h"
-
-#include "app/l10n_util.h"
-#include "base/logging.h"
-#include "base/scoped_ptr.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/autofill_field.h"
-#include "grit/autofill_resources.h"
-
-// static
-FaxField* FaxField::Parse(std::vector<AutoFillField*>::const_iterator* iter) {
-  DCHECK(iter);
-
-  scoped_ptr<FaxField> fax_field(new FaxField);
-  if (ParseText(iter,
-                l10n_util::GetStringUTF16(IDS_AUTOFILL_FAX_RE),
-                &fax_field->number_)) {
-    return fax_field.release();
-  }
-
-  return NULL;
-}
-
-bool FaxField::GetFieldInfo(FieldTypeMap* field_type_map) const {
-  return Add(field_type_map, number_, AutoFillType(PHONE_FAX_WHOLE_NUMBER));
-}
-
-FaxField::FaxField() : number_(NULL) {}
diff --git a/chrome/browser/autofill/fax_field.h b/chrome/browser/autofill/fax_field.h
deleted file mode 100644
index e954ee1..0000000
--- a/chrome/browser/autofill/fax_field.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_AUTOFILL_FAX_FIELD_H_
-#define CHROME_BROWSER_AUTOFILL_FAX_FIELD_H_
-#pragma once
-
-#include <vector>
-
-#include "chrome/browser/autofill/autofill_type.h"
-#include "chrome/browser/autofill/form_field.h"
-
-class AutoFillField;
-
-// A class that identifies itself as a fax field using heuristics.
-class FaxField : public FormField {
- public:
-  static FaxField* Parse(std::vector<AutoFillField*>::const_iterator* iter);
-
-  virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const;
-
- private:
-  FaxField();
-
-  // The fax number field.
-  AutoFillField* number_;
-
-  DISALLOW_COPY_AND_ASSIGN(FaxField);
-};
-
-#endif  // CHROME_BROWSER_AUTOFILL_FAX_FIELD_H_
diff --git a/chrome/browser/autofill/fax_field_unittest.cc b/chrome/browser/autofill/fax_field_unittest.cc
deleted file mode 100644
index 724456a..0000000
--- a/chrome/browser/autofill/fax_field_unittest.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_ptr.h"
-#include "base/scoped_vector.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/fax_field.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/glue/form_field.h"
-
-namespace {
-
-class FaxFieldTest : public testing::Test {
- public:
-  FaxFieldTest() {}
-
- protected:
-  ScopedVector<AutoFillField> list_;
-  scoped_ptr<FaxField> field_;
-  FieldTypeMap field_type_map_;
-  std::vector<AutoFillField*>::const_iterator iter_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FaxFieldTest);
-};
-
-TEST_F(FaxFieldTest, Empty) {
-  list_.push_back(NULL);
-  iter_ = list_.begin();
-  field_.reset(FaxField::Parse(&iter_));
-  ASSERT_EQ(static_cast<FaxField*>(NULL), field_.get());
-}
-
-TEST_F(FaxFieldTest, NonParse) {
-  list_.push_back(new AutoFillField);
-  list_.push_back(NULL);
-  iter_ = list_.begin();
-  field_.reset(FaxField::Parse(&iter_));
-  ASSERT_EQ(static_cast<FaxField*>(NULL), field_.get());
-}
-
-TEST_F(FaxFieldTest, ParseOneLineFax) {
-  list_.push_back(
-      new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Fax"),
-                                               ASCIIToUTF16("faxnumber"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false),
-                        ASCIIToUTF16("fax1")));
-  list_.push_back(NULL);
-  iter_ = list_.begin();
-  field_.reset(FaxField::Parse(&iter_));
-  ASSERT_NE(static_cast<FaxField*>(NULL), field_.get());
-  ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
-  ASSERT_TRUE(
-      field_type_map_.find(ASCIIToUTF16("fax1")) != field_type_map_.end());
-  EXPECT_EQ(PHONE_FAX_WHOLE_NUMBER, field_type_map_[ASCIIToUTF16("fax1")]);
-}
-
-}  // namespace
diff --git a/chrome/browser/autofill/form_field.cc b/chrome/browser/autofill/form_field.cc
index 545ce1b..e2d24dd 100644
--- a/chrome/browser/autofill/form_field.cc
+++ b/chrome/browser/autofill/form_field.cc
@@ -4,18 +4,17 @@
 
 #include "chrome/browser/autofill/form_field.h"
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/address_field.h"
 #include "chrome/browser/autofill/autofill_field.h"
 #include "chrome/browser/autofill/credit_card_field.h"
-#include "chrome/browser/autofill/fax_field.h"
 #include "chrome/browser/autofill/name_field.h"
 #include "chrome/browser/autofill/phone_field.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRegularExpression.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "grit/autofill_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // Field names from the ECML specification; see RFC 3106.  We've
 // made these names lowercase since we convert labels and field names to
@@ -64,19 +63,6 @@
 const char kEcmlCardExpireMonth[] = "ecom_payment_card_expdate_month";
 const char kEcmlCardExpireYear[] = "ecom_payment_card_expdate_year";
 
-namespace {
-
-// The name of the hidden form control element.
-const char* const kControlTypeHidden = "hidden";
-
-// The name of the radio form control element.
-const char* const kControlTypeRadio = "radio";
-
-// The name of the checkbox form control element.
-const char* const kControlTypeCheckBox = "checkbox";
-
-}  // namespace
-
 class EmailField : public FormField {
  public:
   virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const {
@@ -161,12 +147,10 @@
   field = EmailField::Parse(iter, is_ecml);
   if (field != NULL)
     return field;
+  // Parses both phone and fax.
   field = PhoneField::Parse(iter, is_ecml);
   if (field != NULL)
     return field;
-  field = FaxField::Parse(iter);
-  if (field != NULL)
-    return field;
   field = AddressField::Parse(iter, is_ecml);
   if (field != NULL)
     return field;
@@ -213,12 +197,6 @@
                           const string16& pattern,
                           AutoFillField** dest,
                           bool match_label_only) {
-  // Some forms have one or more hidden fields before each visible input; skip
-  // past these.
-  while (**iter && LowerCaseEqualsASCII((**iter)->form_control_type(),
-                                        kControlTypeHidden))
-    (*iter)++;
-
   AutoFillField* field = **iter;
   if (!field)
     return false;
@@ -289,17 +267,6 @@
   // Parse fields.
   std::vector<AutoFillField*>::const_iterator field = fields->begin();
   while (field != fields->end() && *field != NULL) {
-    // Don't parse hidden fields or radio or checkbox controls.
-    if (LowerCaseEqualsASCII((*field)->form_control_type(),
-                             kControlTypeHidden) ||
-        LowerCaseEqualsASCII((*field)->form_control_type(),
-                             kControlTypeRadio) ||
-        LowerCaseEqualsASCII((*field)->form_control_type(),
-                             kControlTypeCheckBox)) {
-      field++;
-      continue;
-    }
-
     FormField* form_field = FormField::ParseFormField(&field, is_ecml);
     if (!form_field) {
       field++;
diff --git a/chrome/browser/autofill/form_group.cc b/chrome/browser/autofill/form_group.cc
index 49beb16..f702a3a 100644
--- a/chrome/browser/autofill/form_group.cc
+++ b/chrome/browser/autofill/form_group.cc
@@ -2,8 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "chrome/browser/autofill/form_group.h"
 
+#include <iterator>
+
 string16 FormGroup::GetPreviewText(const AutoFillType& type) const {
   return GetFieldText(type);
 }
diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc
index 7f4dcbf..46ddb94 100644
--- a/chrome/browser/autofill/form_structure.cc
+++ b/chrome/browser/autofill/form_structure.cc
@@ -24,22 +24,23 @@
 
 namespace {
 
-const char* kFormMethodPost = "post";
+const char kFormMethodPost[] = "post";
 
-// XML attribute names.
-const char* const kAttributeClientVersion = "clientversion";
-const char* const kAttributeAutoFillUsed = "autofillused";
-const char* const kAttributeSignature = "signature";
-const char* const kAttributeFormSignature = "formsignature";
-const char* const kAttributeDataPresent = "datapresent";
-
-const char* const kXMLElementForm = "form";
-const char* const kXMLElementField = "field";
-const char* const kAttributeAutoFillType = "autofilltype";
-
-// The list of form control types we handle.
-const char* const kControlTypeSelect = "select-one";
-const char* const kControlTypeText = "text";
+// XML elements and attributes.
+const char kAttributeAcceptedFeatures[] = "accepts";
+const char kAttributeAutoFillUsed[] = "autofillused";
+const char kAttributeAutoFillType[] = "autofilltype";
+const char kAttributeClientVersion[] = "clientversion";
+const char kAttributeDataPresent[] = "datapresent";
+const char kAttributeFormSignature[] = "formsignature";
+const char kAttributeSignature[] = "signature";
+const char kAcceptedFeatures[] = "e"; // e=experiments
+const char kClientVersion[] = "6.1.1715.1442/en (GGLL)";
+const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+const char kXMLElementAutoFillQuery[] = "autofillquery";
+const char kXMLElementAutoFillUpload[] = "autofillupload";
+const char kXMLElementForm[] = "form";
+const char kXMLElementField[] = "field";
 
 // The number of fillable fields necessary for a form to be fillable.
 #ifdef ANDROID
@@ -50,22 +51,6 @@
 const size_t kRequiredFillableFields = 3;
 #endif
 
-static std::string Hash64Bit(const std::string& str) {
-  std::string hash_bin = base::SHA1HashString(str);
-  DCHECK_EQ(20U, hash_bin.length());
-
-  uint64 hash64 = (((static_cast<uint64>(hash_bin[0])) & 0xFF) << 56) |
-                  (((static_cast<uint64>(hash_bin[1])) & 0xFF) << 48) |
-                  (((static_cast<uint64>(hash_bin[2])) & 0xFF) << 40) |
-                  (((static_cast<uint64>(hash_bin[3])) & 0xFF) << 32) |
-                  (((static_cast<uint64>(hash_bin[4])) & 0xFF) << 24) |
-                  (((static_cast<uint64>(hash_bin[5])) & 0xFF) << 16) |
-                  (((static_cast<uint64>(hash_bin[6])) & 0xFF) << 8) |
-                   ((static_cast<uint64>(hash_bin[7])) & 0xFF);
-
-  return base::Uint64ToString(hash64);
-}
-
 }  // namespace
 
 FormStructure::FormStructure(const FormData& form)
@@ -80,17 +65,10 @@
   std::vector<webkit_glue::FormField>::const_iterator field;
   for (field = form.fields.begin();
        field != form.fields.end(); field++) {
-    // We currently only handle text and select fields; however, we need to
-    // store all fields in order to match the fields stored in the FormManager.
-    // We don't append other field types to the form signature though in order
-    // to match the form signature of the AutoFill servers.
-    if (LowerCaseEqualsASCII(field->form_control_type(), kControlTypeText) ||
-        LowerCaseEqualsASCII(field->form_control_type(), kControlTypeSelect)) {
-      // Add all supported form fields (including with empty names) to
-      // signature.  This is a requirement for AutoFill servers.
-      form_signature_field_names_.append("&");
-      form_signature_field_names_.append(UTF16ToUTF8(field->name()));
-    }
+    // Add all supported form fields (including with empty names) to the
+    // signature.  This is a requirement for AutoFill servers.
+    form_signature_field_names_.append("&");
+    form_signature_field_names_.append(UTF16ToUTF8(field->name()));
 
     // Generate a unique name for this field by appending a counter to the name.
     string16 unique_name = field->name() +
@@ -118,36 +96,29 @@
                                         std::string* encoded_xml) const {
   DCHECK(encoded_xml);
   encoded_xml->clear();
-  bool auto_fillable = IsAutoFillable(false);
+  bool auto_fillable = ShouldBeParsed(true);
   DCHECK(auto_fillable);  // Caller should've checked for search pages.
   if (!auto_fillable)
     return false;
 
-  buzz::XmlElement autofil_request_xml(buzz::QName("autofillupload"));
+  // Set up the <autofillupload> element and its attributes.
+  buzz::XmlElement autofill_request_xml(
+      (buzz::QName(kXMLElementAutoFillUpload)));
+  autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
+                               kClientVersion);
+  autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature),
+                               FormSignature());
+  autofill_request_xml.SetAttr(buzz::QName(kAttributeAutoFillUsed),
+                               auto_fill_used ? "true" : "false");
+  autofill_request_xml.SetAttr(buzz::QName(kAttributeDataPresent),
+                               ConvertPresenceBitsToString().c_str());
 
-  // Attributes for the <autofillupload> element.
-  //
-  // TODO(jhawkins): Work with toolbar devs to make a spec for autofill clients.
-  // For now these values are hacked from the toolbar code.
-  autofil_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
-                              "6.1.1715.1442/en (GGLL)");
-
-  autofil_request_xml.SetAttr(buzz::QName(kAttributeFormSignature),
-                              FormSignature());
-
-  autofil_request_xml.SetAttr(buzz::QName(kAttributeAutoFillUsed),
-                              auto_fill_used ? "true" : "false");
-
-  // TODO(jhawkins): Hook this up to the personal data manager.
-  // personaldata_manager_->GetDataPresent();
-  autofil_request_xml.SetAttr(buzz::QName(kAttributeDataPresent), "");
-
-  if (!EncodeFormRequest(FormStructure::UPLOAD, &autofil_request_xml))
+  if (!EncodeFormRequest(FormStructure::UPLOAD, &autofill_request_xml))
     return false;  // Malformed form, skip it.
 
   // Obtain the XML structure as a string.
-  *encoded_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-  *encoded_xml += autofil_request_xml.Str().c_str();
+  *encoded_xml = kXMLDeclaration;
+  *encoded_xml += autofill_request_xml.Str().c_str();
 
   return true;
 }
@@ -161,13 +132,15 @@
   encoded_xml->clear();
   encoded_signatures->clear();
   encoded_signatures->reserve(forms.size());
-  buzz::XmlElement autofil_request_xml(buzz::QName("autofillquery"));
-  // Attributes for the <autofillquery> element.
-  //
-  // TODO(jhawkins): Work with toolbar devs to make a spec for autofill clients.
-  // For now these values are hacked from the toolbar code.
-  autofil_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
-                              "6.1.1715.1442/en (GGLL)");
+
+  // Set up the <autofillquery> element and attributes.
+  buzz::XmlElement autofill_request_xml(
+      (buzz::QName(kXMLElementAutoFillQuery)));
+  autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
+                               kClientVersion);
+  autofill_request_xml.SetAttr(buzz::QName(kAttributeAcceptedFeatures),
+                               kAcceptedFeatures);
+
   // Some badly formatted web sites repeat forms - detect that and encode only
   // one form as returned data would be the same for all the repeated forms.
   std::set<std::string> processed_forms;
@@ -179,7 +152,7 @@
       continue;
     processed_forms.insert(signature);
     scoped_ptr<buzz::XmlElement> encompassing_xml_element(
-        new buzz::XmlElement(buzz::QName("form")));
+        new buzz::XmlElement(buzz::QName(kXMLElementForm)));
     encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature),
                                       signature);
 
@@ -187,7 +160,7 @@
                                   encompassing_xml_element.get()))
       continue;  // Malformed form, skip it.
 
-    autofil_request_xml.AddElement(encompassing_xml_element.release());
+    autofill_request_xml.AddElement(encompassing_xml_element.release());
     encoded_signatures->push_back(signature);
   }
 
@@ -195,8 +168,8 @@
     return false;
 
   // Obtain the XML structure as a string.
-  *encoded_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-  *encoded_xml += autofil_request_xml.Str().c_str();
+  *encoded_xml = kXMLDeclaration;
+  *encoded_xml += autofill_request_xml.Str().c_str();
 
   return true;
 }
@@ -210,7 +183,9 @@
 
   // Parse the field types from the server response to the query.
   std::vector<AutoFillFieldType> field_types;
-  AutoFillQueryXmlParser parse_handler(&field_types, upload_required);
+  std::string experiment_id;
+  AutoFillQueryXmlParser parse_handler(&field_types, upload_required,
+                                       &experiment_id);
   buzz::XmlParser parser(&parse_handler);
   parser.Parse(response_xml.c_str(), response_xml.length(), true);
   if (!parse_handler.succeeded())
@@ -226,6 +201,7 @@
   for (std::vector<FormStructure*>::const_iterator iter = forms.begin();
        iter != forms.end(); ++iter) {
     FormStructure* form = *iter;
+    form->server_experiment_id_ = experiment_id;
 
     if (form->has_autofillable_field_)
       heuristics_detected_fillable_field = true;
@@ -276,10 +252,17 @@
 }
 
 std::string FormStructure::FormSignature() const {
-  std::string form_string = target_url_.scheme() +
-                            "://" +
-                            target_url_.host() +
-                            "&" +
+  std::string scheme(target_url_.scheme());
+  std::string host(target_url_.host());
+
+  // If target host or scheme is empty, set scheme and host of source url.
+  // This is done to match the Toolbar's behavior.
+  if (scheme.empty() || host.empty()) {
+    scheme = source_url_.scheme();
+    host = source_url_.host();
+  }
+
+  std::string form_string = scheme + "://" + host + "&" +
                             UTF16ToUTF8(form_name_) +
                             form_signature_field_names_;
 
@@ -347,6 +330,10 @@
   return (field_size == 0) ? 0 : field_size - 1;
 }
 
+std::string FormStructure::server_experiment_id() const {
+  return server_experiment_id_;
+}
+
 bool FormStructure::operator==(const FormData& form) const {
   // TODO(jhawkins): Is this enough to differentiate a form?
   if (form_name_ == form.name &&
@@ -365,6 +352,22 @@
   return !operator==(form);
 }
 
+std::string FormStructure::Hash64Bit(const std::string& str) {
+  std::string hash_bin = base::SHA1HashString(str);
+  DCHECK_EQ(20U, hash_bin.length());
+
+  uint64 hash64 = (((static_cast<uint64>(hash_bin[0])) & 0xFF) << 56) |
+                  (((static_cast<uint64>(hash_bin[1])) & 0xFF) << 48) |
+                  (((static_cast<uint64>(hash_bin[2])) & 0xFF) << 40) |
+                  (((static_cast<uint64>(hash_bin[3])) & 0xFF) << 32) |
+                  (((static_cast<uint64>(hash_bin[4])) & 0xFF) << 24) |
+                  (((static_cast<uint64>(hash_bin[5])) & 0xFF) << 16) |
+                  (((static_cast<uint64>(hash_bin[6])) & 0xFF) << 8) |
+                   ((static_cast<uint64>(hash_bin[7])) & 0xFF);
+
+  return base::Uint64ToString(hash64);
+}
+
 void FormStructure::GetHeuristicAutoFillTypes() {
   has_credit_card_field_ = false;
   has_autofillable_field_ = false;
@@ -410,28 +413,30 @@
     buzz::XmlElement* encompassing_xml_element) const {
   if (!field_count())  // Nothing to add.
     return false;
+
   // Some badly formatted web sites repeat fields - limit number of fields to
   // 48, which is far larger than any valid form and XML still fits into 2K.
+  // Do not send requests for forms with more than this many fields, as they are
+  // near certainly not valid/auto-fillable.
   const size_t kMaxFieldsOnTheForm = 48;
-  if (field_count() > kMaxFieldsOnTheForm) {
-    // This is not a valid form, most certainly. Do not send request for the
-    // wrongly formatted forms.
+  if (field_count() > kMaxFieldsOnTheForm)
     return false;
-  }
+
   // Add the child nodes for the form fields.
   for (size_t index = 0; index < field_count(); ++index) {
     const AutoFillField* field = fields_[index];
     if (request_type == FormStructure::UPLOAD) {
       FieldTypeSet types = field->possible_types();
-      for (FieldTypeSet::const_iterator type = types.begin();
-           type != types.end(); type++) {
+      // |types| could be empty in unit-tests only.
+      for (FieldTypeSet::iterator field_type = types.begin();
+           field_type != types.end(); ++field_type) {
         buzz::XmlElement *field_element = new buzz::XmlElement(
             buzz::QName(kXMLElementField));
 
         field_element->SetAttr(buzz::QName(kAttributeSignature),
                                field->FieldSignature());
         field_element->SetAttr(buzz::QName(kAttributeAutoFillType),
-                               base::IntToString(*type));
+                               base::IntToString(*field_type));
         encompassing_xml_element->AddElement(field_element);
       }
     } else {
@@ -444,3 +449,42 @@
   }
   return true;
 }
+
+std::string FormStructure::ConvertPresenceBitsToString() const {
+  std::vector<uint8> presence_bitfield;
+  // Determine all of the field types that were autofilled. Pack bits into
+  // |presence_bitfield|. The necessary size for |presence_bitfield| is
+  // ceil((MAX_VALID_FIELD_TYPE + 7) / 8) bytes (uint8).
+  presence_bitfield.resize((MAX_VALID_FIELD_TYPE + 0x7) / 8);
+  for (size_t i = 0; i < presence_bitfield.size(); ++i)
+    presence_bitfield[i] = 0;
+
+  for (size_t i = 0; i < field_count(); ++i) {
+    const AutoFillField* field = fields_[i];
+    FieldTypeSet types = field->possible_types();
+    // |types| could be empty in unit-tests only.
+    for (FieldTypeSet::iterator field_type = types.begin();
+         field_type != types.end(); ++field_type) {
+      DCHECK(presence_bitfield.size() > (static_cast<size_t>(*field_type) / 8));
+      // Set bit in the bitfield: byte |field_type| / 8, bit in byte
+      // |field_type| % 8 from the left.
+      presence_bitfield[*field_type / 8] |= (0x80 >> (*field_type % 8));
+    }
+  }
+
+  std::string data_presence;
+  data_presence.reserve(presence_bitfield.size() * 2 + 1);
+
+  // Skip trailing zeroes. If all mask is 0 - return empty string.
+  size_t data_end = presence_bitfield.size();
+  for (; data_end > 0 && !presence_bitfield[data_end - 1]; --data_end) {
+  }
+
+  // Print all meaningfull bytes into the string.
+  for (size_t i = 0; i < data_end; ++i) {
+    base::StringAppendF(&data_presence, "%02x", presence_bitfield[i]);
+  }
+
+  return data_presence;
+}
+
diff --git a/chrome/browser/autofill/form_structure.h b/chrome/browser/autofill/form_structure.h
index ad0c411..fbc214e 100644
--- a/chrome/browser/autofill/form_structure.h
+++ b/chrome/browser/autofill/form_structure.h
@@ -38,11 +38,10 @@
 class FormStructure {
  public:
   explicit FormStructure(const webkit_glue::FormData& form);
-  ~FormStructure();
+  virtual ~FormStructure();
 
   // Encodes the XML upload request from this FormStructure.
-  bool EncodeUploadRequest(bool auto_fill_used,
-                           std::string* encoded_xml) const;
+  bool EncodeUploadRequest(bool auto_fill_used, std::string* encoded_xml) const;
 
   // Encodes the XML query request for the set of forms.
   // All fields are returned in one XML. For example, there are three forms,
@@ -103,10 +102,20 @@
 
   const GURL& source_url() const { return source_url_; }
 
+  virtual std::string server_experiment_id() const;
+
   bool operator==(const webkit_glue::FormData& form) const;
   bool operator!=(const webkit_glue::FormData& form) const;
 
+ protected:
+  // For tests.
+  ScopedVector<AutoFillField>* fields() { return &fields_; }
+
  private:
+  friend class FormStructureTest;
+  // 64-bit hash of the string - used in FormSignature and unit-tests.
+  static std::string Hash64Bit(const std::string& str);
+
   enum EncodeRequestType {
     QUERY,
     UPLOAD,
@@ -124,6 +133,10 @@
   bool EncodeFormRequest(EncodeRequestType request_type,
                          buzz::XmlElement* encompassing_xml_element) const;
 
+  // Helper for EncodeUploadRequest() that collects presense of all data in the
+  // form structure and converts it to string for uploading.
+  std::string ConvertPresenceBitsToString() const;
+
   // The name of the form.
   string16 form_name_;
 
@@ -149,6 +162,10 @@
   // character. E.g.: "&form_input1_name&form_input2_name&...&form_inputN_name"
   std::string form_signature_field_names_;
 
+  // The server experiment corresponding to the server types returned for this
+  // form.
+  std::string server_experiment_id_;
+
   // GET or POST.
   RequestMethod method_;
 
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc
index f6bda60..7cdcd69 100644
--- a/chrome/browser/autofill/form_structure_browsertest.cc
+++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -1,99 +1,72 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <vector>
 
 #include "base/file_path.h"
-#include "base/path_service.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/autofill_manager.h"
+#include "chrome/browser/autofill/data_driven_test.h"
 #include "chrome/browser/autofill/form_structure.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_paths.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "googleurl/src/gurl.h"
 
 namespace {
 
-FilePath GetInputFileDirectory() {
-  FilePath test_data_dir_;
-  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
-  test_data_dir_ = test_data_dir_.AppendASCII("autofill_heuristics")
-                                 .AppendASCII("input");
-  return test_data_dir_;
-}
+const FilePath::CharType kTestName[] = FILE_PATH_LITERAL("heuristics");
+const FilePath::CharType kFileNamePattern[] = FILE_PATH_LITERAL("*.html");
 
-FilePath GetOutputFileDirectory() {
-  FilePath test_data_dir_;
-  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
-  test_data_dir_ = test_data_dir_.AppendASCII("autofill_heuristics")
-                                 .AppendASCII("output");
-  return test_data_dir_;
-}
-
-// Write |content| to |file|. Returns true on success.
-bool WriteFile(const FilePath& file, const std::string& content) {
-  int write_size = file_util::WriteFile(file, content.c_str(),
-                                        content.length());
-  return write_size == static_cast<int>(content.length());
-}
-
-// Convert |html| to URL format, and return the converted string.
-const std::string ConvertToURLFormat(const std::string& html) {
-  return std::string("data:text/html;charset=utf-8,") + html;
-}
-
-// Convert strings with platform end-of-line characters with spaces.
-const std::string NormalizeText(const std::string& text) {
-  std::string normalized = text;
-  ReplaceSubstringsAfterOffset(&normalized, 0, "\r\n", " ");
-  ReplaceSubstringsAfterOffset(&normalized, 0, "\r", " ");
-  ReplaceSubstringsAfterOffset(&normalized, 0, "\n", " ");
-  return normalized;
+// Convert the |html| snippet to a data URI.
+GURL HTMLToDataURI(const std::string& html) {
+  return GURL(std::string("data:text/html;charset=utf-8,") + html);
 }
 
 }  // namespace
 
-// Test class for verifying proper form structure as determined by AutoFill
-// heuristics. A test inputs each form file(e.g. form_[language_code].html),
-// loads its HTML content with a call to |NavigateToURL|, the |AutoFillManager|
-// associated with the tab contents is queried for the form structures that
-// were loaded and parsed. These form structures are serialized to string form.
-// If this is the first time test is run, a gold test result file is generated
-// in output directory, else the form structures are compared against the
-// existing result file.
-class FormStructureBrowserTest : public InProcessBrowserTest {
- public:
-  FormStructureBrowserTest() {}
-  virtual ~FormStructureBrowserTest() {}
-
+// A data-driven test for verifying AutoFill heuristics. Each input is an HTML
+// file that contains one or more forms. The corresponding output file lists the
+// heuristically detected type for eachfield.
+class FormStructureBrowserTest : public InProcessBrowserTest,
+                                 public DataDrivenTest {
  protected:
-  // Returns a vector of form structure objects associated with the given
-  // |autofill_manager|.
-  const std::vector<FormStructure*>& GetFormStructures(
-      const AutoFillManager& autofill_manager);
+  FormStructureBrowserTest();
+  virtual ~FormStructureBrowserTest();
 
-  // Serializes the given form structures in |forms| to string form.
-  const std::string FormStructuresToString(
-      const std::vector<FormStructure*>& forms);
+  // DataDrivenTest:
+  virtual void GenerateResults(const std::string& input,
+                               std::string* output);
+
+  // Serializes the given |forms| into a string.
+  std::string FormStructuresToString(const std::vector<FormStructure*>& forms);
 
  private:
-  // A helper utility for converting an |AutoFillFieldType| to string form.
-  const std::string AutoFillFieldTypeToString(AutoFillFieldType type);
-
   DISALLOW_COPY_AND_ASSIGN(FormStructureBrowserTest);
 };
 
-const std::vector<FormStructure*>& FormStructureBrowserTest::GetFormStructures(
-  const AutoFillManager& autofill_manager) {
-  return autofill_manager.form_structures_.get();
+FormStructureBrowserTest::FormStructureBrowserTest() {
 }
 
-const std::string FormStructureBrowserTest::FormStructuresToString(
+FormStructureBrowserTest::~FormStructureBrowserTest() {
+}
+
+void FormStructureBrowserTest::GenerateResults(const std::string& input,
+                                               std::string* output) {
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+                                                       HTMLToDataURI(input)));
+
+  AutoFillManager* autofill_manager =
+      browser()->GetSelectedTabContents()->autofill_manager();
+  ASSERT_NE(static_cast<AutoFillManager*>(NULL), autofill_manager);
+  std::vector<FormStructure*> forms = autofill_manager->form_structures_.get();
+  *output = FormStructureBrowserTest::FormStructuresToString(forms);
+}
+
+std::string FormStructureBrowserTest::FormStructuresToString(
     const std::vector<FormStructure*>& forms) {
   std::string forms_string;
   for (std::vector<FormStructure*>::const_iterator iter = forms.begin();
@@ -107,154 +80,15 @@
       // The field list is NULL-terminated.  Exit loop when at the end.
       if (!*field_iter)
         break;
-      forms_string += AutoFillFieldTypeToString((*field_iter)->type());
+      forms_string += AutoFillType::FieldTypeToString((*field_iter)->type());
       forms_string += "\n";
     }
   }
   return forms_string;
 }
 
-const std::string FormStructureBrowserTest::AutoFillFieldTypeToString(
-    AutoFillFieldType type) {
-  switch (type) {
-    case NO_SERVER_DATA:
-      return "NO_SERVER_DATA";
-    case UNKNOWN_TYPE:
-      return "UNKNOWN_TYPE";
-    case EMPTY_TYPE:
-      return "EMPTY_TYPE";
-    case NAME_FIRST:
-      return "NAME_FIRST";
-    case NAME_MIDDLE:
-      return "NAME_MIDDLE";
-    case NAME_LAST:
-      return "NAME_LAST";
-    case NAME_MIDDLE_INITIAL:
-      return "NAME_MIDDLE_INITIAL";
-    case NAME_FULL:
-      return "NAME_FULL";
-    case NAME_SUFFIX:
-      return "NAME_SUFFIX";
-    case EMAIL_ADDRESS:
-      return "EMAIL_ADDRESS";
-    case PHONE_HOME_NUMBER:
-      return "PHONE_HOME_NUMBER";
-    case PHONE_HOME_CITY_CODE:
-      return "PHONE_HOME_CITY_CODE";
-    case PHONE_HOME_COUNTRY_CODE:
-      return "PHONE_HOME_COUNTRY_CODE";
-    case PHONE_HOME_CITY_AND_NUMBER:
-      return "PHONE_HOME_CITY_AND_NUMBER";
-    case PHONE_HOME_WHOLE_NUMBER:
-      return "PHONE_HOME_WHOLE_NUMBER";
-    case PHONE_FAX_NUMBER:
-      return "PHONE_FAX_NUMBER";
-    case PHONE_FAX_CITY_CODE:
-      return "PHONE_FAX_CITY_CODE";
-    case PHONE_FAX_COUNTRY_CODE:
-      return "PHONE_FAX_COUNTRY_CODE";
-    case PHONE_FAX_CITY_AND_NUMBER:
-      return "PHONE_FAX_CITY_AND_NUMBER";
-    case PHONE_FAX_WHOLE_NUMBER:
-      return "PHONE_FAX_WHOLE_NUMBER";
-    case ADDRESS_HOME_LINE1:
-      return "ADDRESS_HOME_LINE1";
-    case ADDRESS_HOME_LINE2:
-      return "ADDRESS_HOME_LINE2";
-    case ADDRESS_HOME_APT_NUM:
-      return "ADDRESS_HOME_APT_NUM";
-    case ADDRESS_HOME_CITY:
-      return "ADDRESS_HOME_CITY";
-    case ADDRESS_HOME_STATE:
-      return "ADDRESS_HOME_STATE";
-    case ADDRESS_HOME_ZIP:
-      return "ADDRESS_HOME_ZIP";
-    case ADDRESS_HOME_COUNTRY:
-      return "ADDRESS_HOME_COUNTRY";
-    case ADDRESS_BILLING_LINE1:
-      return "ADDRESS_BILLING_LINE1";
-    case ADDRESS_BILLING_LINE2:
-      return "ADDRESS_BILLING_LINE2";
-    case ADDRESS_BILLING_APT_NUM:
-      return "ADDRESS_BILLING_APT_NUM";
-    case ADDRESS_BILLING_CITY:
-      return "ADDRESS_BILLING_CITY";
-    case ADDRESS_BILLING_STATE:
-      return "ADDRESS_BILLING_STATE";
-    case ADDRESS_BILLING_ZIP:
-      return "ADDRESS_BILLING_ZIP";
-    case ADDRESS_BILLING_COUNTRY:
-      return "ADDRESS_BILLING_COUNTRY";
-    case CREDIT_CARD_NAME:
-      return "CREDIT_CARD_NAME";
-    case CREDIT_CARD_NUMBER:
-      return "CREDIT_CARD_NUMBER";
-    case CREDIT_CARD_EXP_MONTH:
-      return "CREDIT_CARD_EXP_MONTH";
-    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
-      return "CREDIT_CARD_EXP_2_DIGIT_YEAR";
-    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
-      return "CREDIT_CARD_EXP_4_DIGIT_YEAR";
-    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
-      return "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR";
-    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
-      return "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR";
-    case CREDIT_CARD_TYPE:
-      return "CREDIT_CARD_TYPE";
-    case CREDIT_CARD_VERIFICATION_CODE:
-      return "CREDIT_CARD_VERIFICATION_CODE";
-    case COMPANY_NAME:
-      return "COMPANY_NAME";
-    default:
-      NOTREACHED() << "Invalid AutoFillFieldType value.";
-  }
-  return std::string();
-}
-
-IN_PROC_BROWSER_TEST_F(FormStructureBrowserTest, HTMLFiles) {
-  FilePath input_file_path = GetInputFileDirectory();
-  file_util::FileEnumerator input_file_enumerator(input_file_path,
-      false, file_util::FileEnumerator::FILES, FILE_PATH_LITERAL("*.html"));
-
-  for (input_file_path = input_file_enumerator.Next();
-       !input_file_path.empty();
-       input_file_path = input_file_enumerator.Next()) {
-    std::string input_file_source;
-
-    ASSERT_TRUE(file_util::ReadFileToString(input_file_path,
-                                            &input_file_source));
-    input_file_source = ConvertToURLFormat(input_file_source);
-
-    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-    ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
-        browser(), GURL(input_file_source)));
-
-    ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
-                                                       VIEW_ID_TAB_CONTAINER));
-    ASSERT_TRUE(ui_test_utils::IsViewFocused(
-        browser(),
-        VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
-
-    AutoFillManager* autofill_manager =
-        browser()->GetSelectedTabContents()->GetAutoFillManager();
-    ASSERT_NE(static_cast<AutoFillManager*>(NULL), autofill_manager);
-    std::vector<FormStructure*> forms = GetFormStructures(*autofill_manager);
-
-    FilePath output_file_directory = GetOutputFileDirectory();
-    FilePath output_file_path = output_file_directory.Append(
-        input_file_path.BaseName().StripTrailingSeparators().ReplaceExtension(
-            FILE_PATH_LITERAL(".out")));
-
-    std::string output_file_source;
-    if (file_util::ReadFileToString(output_file_path, &output_file_source)) {
-      ASSERT_EQ(NormalizeText(output_file_source),
-                NormalizeText(
-                    FormStructureBrowserTest::FormStructuresToString(forms)));
-
-    } else {
-      ASSERT_TRUE(WriteFile(
-          output_file_path,
-          FormStructureBrowserTest::FormStructuresToString(forms)));
-    }
-  }
+IN_PROC_BROWSER_TEST_F(FormStructureBrowserTest, DataDrivenHeuristics) {
+  RunDataDrivenTest(GetInputDirectory(kTestName),
+                    GetOutputDirectory(kTestName),
+                    kFileNamePattern);
 }
diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc
index 96d8fff..bd3056a 100644
--- a/chrome/browser/autofill/form_structure_unittest.cc
+++ b/chrome/browser/autofill/form_structure_unittest.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/autofill/form_structure.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
 #include "webkit/glue/form_data.h"
 #include "webkit/glue/form_field.h"
 
@@ -39,6 +39,13 @@
 
 }  // namespace webkit_glue
 
+class FormStructureTest {
+ public:
+  static std::string Hash64Bit(const std::string& str) {
+    return FormStructure::Hash64Bit(str);
+  }
+};
+
 namespace {
 
 TEST(FormStructureTest, FieldCount) {
@@ -352,141 +359,6 @@
   EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(8)->heuristic_type());
 }
 
-TEST(FormStructureTest, HeuristicsHiddenFields) {
-  scoped_ptr<FormStructure> form_structure;
-  FormData form;
-
-  form.method = ASCIIToUTF16("post");
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
-                                               ASCIIToUTF16("firstname"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden1"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
-                                               ASCIIToUTF16("lastname"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden2"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"),
-                                               ASCIIToUTF16("email"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden3"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"),
-                                               ASCIIToUTF16("phone"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden4"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"),
-                                               ASCIIToUTF16("fax"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden5"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
-                                               ASCIIToUTF16("address"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden6"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("City"),
-                                               ASCIIToUTF16("city"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden7"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Zip code"),
-                                               ASCIIToUTF16("zipcode"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("hidden8"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("Submit"),
-                                               string16(),
-                                               ASCIIToUTF16("submit"),
-                                               0,
-                                               false));
-  form_structure.reset(new FormStructure(form));
-  EXPECT_TRUE(form_structure->IsAutoFillable(true));
-
-  // Expect the correct number of fields.
-  ASSERT_EQ(17U, form_structure->field_count());
-  ASSERT_EQ(8U, form_structure->autofill_count());
-
-  // First name.
-  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
-  // Last name.
-  EXPECT_EQ(NAME_LAST, form_structure->field(2)->heuristic_type());
-  // Email.
-  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(4)->heuristic_type());
-  // Phone.
-  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER,
-      form_structure->field(6)->heuristic_type());
-  // Fax.
-  EXPECT_EQ(PHONE_FAX_WHOLE_NUMBER, form_structure->field(8)->heuristic_type());
-  // Address.
-  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(10)->heuristic_type());
-  // City.
-  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(12)->heuristic_type());
-  // Zip.
-  EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(14)->heuristic_type());
-  // Submit.
-  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(16)->heuristic_type());
-}
-
 TEST(FormStructureTest, HeuristicsSample8) {
   scoped_ptr<FormStructure> form_structure;
   FormData form;
@@ -1274,100 +1146,6 @@
   EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(3)->heuristic_type());
 }
 
-TEST(FormStructureTest, MatchSpecificInputTypes) {
-  scoped_ptr<FormStructure> form_structure;
-  FormData form;
-  form.method = ASCIIToUTF16("post");
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
-                                               ASCIIToUTF16("firstname"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
-                                               ASCIIToUTF16("lastname"),
-                                               string16(),
-                                               ASCIIToUTF16("text"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"),
-                                               ASCIIToUTF16("email"),
-                                               string16(),
-                                               ASCIIToUTF16("email"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"),
-                                               ASCIIToUTF16("phone"),
-                                               string16(),
-                                               ASCIIToUTF16("number"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Country"),
-                                               ASCIIToUTF16("country"),
-                                               string16(),
-                                               ASCIIToUTF16("select-one"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"),
-                                               ASCIIToUTF16("fax"),
-                                               string16(),
-                                               ASCIIToUTF16("tel"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
-                                               ASCIIToUTF16("address"),
-                                               string16(),
-                                               ASCIIToUTF16("radio"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("City"),
-                                               ASCIIToUTF16("city"),
-                                               string16(),
-                                               ASCIIToUTF16("checkbox"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("State"),
-                                               ASCIIToUTF16("state"),
-                                               string16(),
-                                               ASCIIToUTF16("hidden"),
-                                               0,
-                                               false));
-  form.fields.push_back(webkit_glue::FormField(string16(),
-                                               ASCIIToUTF16("Submit"),
-                                               string16(),
-                                               ASCIIToUTF16("submit"),
-                                               0,
-                                               false));
-  form_structure.reset(new FormStructure(form));
-  EXPECT_TRUE(form_structure->IsAutoFillable(true));
-
-  // Expect the correct number of fields.
-  ASSERT_EQ(10U, form_structure->field_count());
-  ASSERT_EQ(6U, form_structure->autofill_count());
-
-  // First name.
-  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
-  // Last name.
-  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type());
-  // Email.
-  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(2)->heuristic_type());
-  // Phone.
-  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER,
-            form_structure->field(3)->heuristic_type());
-  // Country.
-  EXPECT_EQ(ADDRESS_HOME_COUNTRY, form_structure->field(4)->heuristic_type());
-  // Fax.
-  EXPECT_EQ(PHONE_FAX_WHOLE_NUMBER, form_structure->field(5)->heuristic_type());
-  // Address.  Invalid input type.
-  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(6)->heuristic_type());
-  // City.  Invalid input type.
-  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(7)->heuristic_type());
-  // State.  Invalid input type.
-  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(8)->heuristic_type());
-  // Submit.  Invalid input type.
-  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(9)->heuristic_type());
-}
-
 TEST(FormStructureTest, HeuristicsInfernoCC) {
   scoped_ptr<FormStructure> form_structure;
   FormData form;
@@ -1524,25 +1302,25 @@
   const char * const kSignature1 = "11337937696949187602";
   const char * const kResponse1 =
       "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillquery "
-      "clientversion=\"6.1.1715.1442/en (GGLL)\"><form signature=\""
-      "11337937696949187602\"><field signature=\"412125936\"/><field "
-      "signature=\"1917667676\"/><field signature=\"2226358947\"/><field "
-      "signature=\"747221617\"/><field signature=\"4108155786\"/></form>"
+      "clientversion=\"6.1.1715.1442/en (GGLL)\" accepts=\"e\"><form "
+      "signature=\"11337937696949187602\"><field signature=\"412125936\"/>"
+      "<field signature=\"1917667676\"/><field signature=\"2226358947\"/>"
+      "<field signature=\"747221617\"/><field signature=\"4108155786\"/></form>"
       "</autofillquery>";
   ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
                                                 &encoded_xml));
-  ASSERT_EQ(encoded_signatures.size(), 1U);
-  EXPECT_EQ(encoded_signatures[0], kSignature1);
-  EXPECT_EQ(encoded_xml, kResponse1);
+  ASSERT_EQ(1U, encoded_signatures.size());
+  EXPECT_EQ(kSignature1, encoded_signatures[0]);
+  EXPECT_EQ(kResponse1, encoded_xml);
 
   // Add the same form, only one will be encoded, so EncodeQueryRequest() should
   // return the same data.
   forms.push_back(new FormStructure(form));
   ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
                                                 &encoded_xml));
-  ASSERT_EQ(encoded_signatures.size(), 1U);
-  EXPECT_EQ(encoded_signatures[0], kSignature1);
-  EXPECT_EQ(encoded_xml, kResponse1);
+  ASSERT_EQ(1U, encoded_signatures.size());
+  EXPECT_EQ(kSignature1, encoded_signatures[0]);
+  EXPECT_EQ(kResponse1, encoded_xml);
   // Add 5 address fields - this should be still a valid form.
   for (size_t i = 0; i < 5; ++i) {
     form.fields.push_back(
@@ -1557,23 +1335,23 @@
   forms.push_back(new FormStructure(form));
   ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
                                                 &encoded_xml));
-  ASSERT_EQ(encoded_signatures.size(), 2U);
-  EXPECT_EQ(encoded_signatures[0], kSignature1);
+  ASSERT_EQ(2U, encoded_signatures.size());
+  EXPECT_EQ(kSignature1, encoded_signatures[0]);
   const char * const kSignature2 = "8308881815906226214";
-  EXPECT_EQ(encoded_signatures[1], kSignature2);
+  EXPECT_EQ(kSignature2, encoded_signatures[1]);
   const char * const kResponse2 =
       "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillquery "
-      "clientversion=\"6.1.1715.1442/en (GGLL)\"><form signature=\""
-      "11337937696949187602\"><field signature=\"412125936\"/><field signature="
-      "\"1917667676\"/><field signature=\"2226358947\"/><field signature=\""
-      "747221617\"/><field signature=\"4108155786\"/></form><form signature=\""
-      "8308881815906226214\"><field signature=\"412125936\"/><field signature="
-      "\"1917667676\"/><field signature=\"2226358947\"/><field signature=\""
-      "747221617\"/><field signature=\"4108155786\"/><field signature=\""
-      "509334676\"/><field signature=\"509334676\"/><field signature=\""
-      "509334676\"/><field signature=\"509334676\"/><field signature=\""
-      "509334676\"/></form></autofillquery>";
-  EXPECT_EQ(encoded_xml, kResponse2);
+      "clientversion=\"6.1.1715.1442/en (GGLL)\" accepts=\"e\"><form "
+      "signature=\"11337937696949187602\"><field signature=\"412125936\"/>"
+      "<field signature=\"1917667676\"/><field signature=\"2226358947\"/>"
+      "<field signature=\"747221617\"/><field signature=\"4108155786\"/></form>"
+      "<form signature=\"8308881815906226214\"><field signature=\"412125936\"/>"
+      "<field signature=\"1917667676\"/><field signature=\"2226358947\"/>"
+      "<field signature=\"747221617\"/><field signature=\"4108155786\"/><field "
+      "signature=\"509334676\"/><field signature=\"509334676\"/><field "
+      "signature=\"509334676\"/><field signature=\"509334676\"/><field "
+      "signature=\"509334676\"/></form></autofillquery>";
+  EXPECT_EQ(kResponse2, encoded_xml);
 
   // Add 50 address fields - the form is not valid anymore, but previous ones
   // are. The result should be the same as in previous test.
@@ -1590,18 +1368,18 @@
   forms.push_back(new FormStructure(form));
   ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
                                                 &encoded_xml));
-  ASSERT_EQ(encoded_signatures.size(), 2U);
-  EXPECT_EQ(encoded_signatures[0], kSignature1);
-  EXPECT_EQ(encoded_signatures[1], kSignature2);
-  EXPECT_EQ(encoded_xml, kResponse2);
+  ASSERT_EQ(2U, encoded_signatures.size());
+  EXPECT_EQ(kSignature1, encoded_signatures[0]);
+  EXPECT_EQ(kSignature2, encoded_signatures[1]);
+  EXPECT_EQ(kResponse2, encoded_xml);
 
   // Check that we fail if there are only bad form(s).
   ScopedVector<FormStructure> bad_forms;
   bad_forms.push_back(new FormStructure(form));
   EXPECT_FALSE(FormStructure::EncodeQueryRequest(bad_forms, &encoded_signatures,
                                                  &encoded_xml));
-  EXPECT_EQ(encoded_signatures.size(), 0U);
-  EXPECT_EQ(encoded_xml, "");
+  EXPECT_EQ(0U, encoded_signatures.size());
+  EXPECT_EQ("", encoded_xml);
 }
 
 TEST(FormStructureTest, EncodeUploadRequest) {
@@ -1658,43 +1436,42 @@
                         false));
   possible_field_types.push_back(FieldTypeSet());
   possible_field_types.back().insert(PHONE_FAX_WHOLE_NUMBER);
-  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
-                        ASCIIToUTF16("address"),
-                        string16(),
-                        ASCIIToUTF16("radio"),
-                        0,
-                        false));
-  possible_field_types.push_back(FieldTypeSet());
-  possible_field_types.back().insert(ADDRESS_HOME_LINE1);
   form_structure.reset(new FormStructure(form));
-  std::string encoded_xml;
+
   ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
   for (size_t i = 0; i < form_structure->field_count(); ++i)
     form_structure->set_possible_types(i, possible_field_types[i]);
+
+  std::string encoded_xml;
   EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
-  EXPECT_EQ(encoded_xml,
-      "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
-      "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
-      "8269229441054798720\" autofillused=\"false\" datapresent=\"\"><field "
-      "signature=\"3763331450\" autofilltype=\"3\"/><field signature=\""
-      "3494530716\" autofilltype=\"5\"/><field signature=\"1029417091\" "
-      "autofilltype=\"9\"/><field signature=\"466116101\" autofilltype="
-      "\"14\"/><field signature=\"2799270304\" autofilltype=\"36\"/><field "
-      "signature=\"1876771436\" autofilltype=\"24\"/><field signature="
-      "\"263446779\" autofilltype=\"30\"/></autofillupload>");
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
+            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\" "
+            "formsignature=\"7641728017676399335\" autofillused=\"false\" "
+            "datapresent=\"1442008008\">"
+            "<field signature=\"3763331450\" autofilltype=\"3\"/>"
+            "<field signature=\"3494530716\" autofilltype=\"5\"/>"
+            "<field signature=\"1029417091\" autofilltype=\"9\"/>"
+            "<field signature=\"466116101\" autofilltype=\"14\"/>"
+            "<field signature=\"2799270304\" autofilltype=\"36\"/>"
+            "<field signature=\"1876771436\" autofilltype=\"24\"/>"
+            "</autofillupload>",
+            encoded_xml);
   EXPECT_TRUE(form_structure->EncodeUploadRequest(true, &encoded_xml));
-  EXPECT_EQ(encoded_xml,
-      "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
-      "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
-      "8269229441054798720\" autofillused=\"true\" datapresent=\"\"><field "
-      "signature=\"3763331450\" autofilltype=\"3\"/><field signature=\""
-      "3494530716\" autofilltype=\"5\"/><field signature=\"1029417091\" "
-      "autofilltype=\"9\"/><field signature=\"466116101\" autofilltype="
-      "\"14\"/><field signature=\"2799270304\" autofilltype=\"36\"/><field "
-      "signature=\"1876771436\" autofilltype=\"24\"/><field signature="
-      "\"263446779\" autofilltype=\"30\"/></autofillupload>");
-  // Add 5 address fields - this should be still a valid form.
-  for (size_t i = 0; i < 5; ++i) {
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
+            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\" "
+            "formsignature=\"7641728017676399335\" autofillused=\"true\" "
+            "datapresent=\"1442008008\">"
+            "<field signature=\"3763331450\" autofilltype=\"3\"/>"
+            "<field signature=\"3494530716\" autofilltype=\"5\"/>"
+            "<field signature=\"1029417091\" autofilltype=\"9\"/>"
+            "<field signature=\"466116101\" autofilltype=\"14\"/>"
+            "<field signature=\"2799270304\" autofilltype=\"36\"/>"
+            "<field signature=\"1876771436\" autofilltype=\"24\"/>"
+            "</autofillupload>",
+            encoded_xml);
+
+  // Add 2 address fields - this should be still a valid form.
+  for (size_t i = 0; i < 2; ++i) {
     form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
                                                  ASCIIToUTF16("address"),
                                                  string16(),
@@ -1712,33 +1489,28 @@
   for (size_t i = 0; i < form_structure->field_count(); ++i)
     form_structure->set_possible_types(i, possible_field_types[i]);
   EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
-  EXPECT_EQ(encoded_xml,
-      "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
-      "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
-      "2027360543766157144\" autofillused=\"false\" datapresent=\"\"><field "
-      "signature=\"3763331450\" autofilltype=\"3\"/><field signature=\""
-      "3494530716\" autofilltype=\"5\"/><field signature=\"1029417091\" "
-      "autofilltype=\"9\"/><field signature=\"466116101\" autofilltype=\"14\"/>"
-      "<field signature=\"2799270304\" autofilltype=\"36\"/><field signature=\""
-      "1876771436\" autofilltype=\"24\"/><field signature=\"263446779\" "
-      "autofilltype=\"30\"/><field signature=\"509334676\" autofilltype="
-      "\"30\"/><field signature=\"509334676\" autofilltype=\"31\"/><field "
-      "signature=\"509334676\" autofilltype=\"37\"/><field signature="
-      "\"509334676\" autofilltype=\"38\"/><field signature=\"509334676\" "
-      "autofilltype=\"30\"/><field signature=\"509334676\" autofilltype="
-      "\"31\"/><field signature=\"509334676\" autofilltype=\"37\"/><field "
-      "signature=\"509334676\" autofilltype=\"38\"/><field signature=\""
-      "509334676\" autofilltype=\"30\"/><field signature=\"509334676\" "
-      "autofilltype=\"31\"/><field signature=\"509334676\" "
-      "autofilltype=\"37\"/><field signature=\"509334676\" autofilltype="
-      "\"38\"/><field signature=\"509334676\" autofilltype=\"30\"/><field "
-      "signature=\"509334676\" autofilltype=\"31\"/><field signature="
-      "\"509334676\" autofilltype=\"37\"/><field signature=\"509334676\" "
-      "autofilltype=\"38\"/><field signature=\"509334676\" autofilltype="
-      "\"30\"/><field signature=\"509334676\" autofilltype=\"31\"/><field "
-      "signature=\"509334676\" autofilltype=\"37\"/><field signature="
-      "\"509334676\" autofilltype=\"38\"/></autofillupload>");
-  // Add 50 address fields - now the form is invalid.
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
+            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\" "
+            "formsignature=\"12226592129574322128\" autofillused=\"false\" "
+            "datapresent=\"144200830e\">"
+            "<field signature=\"3763331450\" autofilltype=\"3\"/>"
+            "<field signature=\"3494530716\" autofilltype=\"5\"/>"
+            "<field signature=\"1029417091\" autofilltype=\"9\"/>"
+            "<field signature=\"466116101\" autofilltype=\"14\"/>"
+            "<field signature=\"2799270304\" autofilltype=\"36\"/>"
+            "<field signature=\"1876771436\" autofilltype=\"24\"/>"
+            "<field signature=\"509334676\" autofilltype=\"30\"/>"
+            "<field signature=\"509334676\" autofilltype=\"31\"/>"
+            "<field signature=\"509334676\" autofilltype=\"37\"/>"
+            "<field signature=\"509334676\" autofilltype=\"38\"/>"
+            "<field signature=\"509334676\" autofilltype=\"30\"/>"
+            "<field signature=\"509334676\" autofilltype=\"31\"/>"
+            "<field signature=\"509334676\" autofilltype=\"37\"/>"
+            "<field signature=\"509334676\" autofilltype=\"38\"/>"
+            "</autofillupload>",
+            encoded_xml);
+
+  // Add 50 address fields - now the form is invalid, as it has too many fields.
   for (size_t i = 0; i < 50; ++i) {
     form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
                                                  ASCIIToUTF16("address"),
@@ -1757,7 +1529,252 @@
   for (size_t i = 0; i < form_structure->field_count(); ++i)
     form_structure->set_possible_types(i, possible_field_types[i]);
   EXPECT_FALSE(form_structure->EncodeUploadRequest(false, &encoded_xml));
-  EXPECT_EQ(encoded_xml, "");
+  EXPECT_EQ("", encoded_xml);
+}
+
+TEST(FormStructureTest, CheckDataPresence) {
+  // Checks bits set in the datapresence field: for each type in the form
+  // relevant bit in datapresence has to be set.
+  scoped_ptr<FormStructure> form_structure;
+  std::vector<FieldTypeSet> possible_field_types;
+  FormData form;
+  form.method = ASCIIToUTF16("post");
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
+                        ASCIIToUTF16("first"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(NAME_FIRST);
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
+                        ASCIIToUTF16("last"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(NAME_LAST);
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"),
+                        ASCIIToUTF16("email"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(EMAIL_ADDRESS);
+  form_structure.reset(new FormStructure(form));
+  for (size_t i = 0; i < form_structure->field_count(); ++i)
+    form_structure->set_possible_types(i, possible_field_types[i]);
+  std::string encoded_xml;
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "6402244543831589061\" autofillused=\"false\" "
+            "datapresent=\"1440\"><field signature=\"1089846351\" ",
+            encoded_xml.substr(0, 200));
+
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
+                        ASCIIToUTF16("address"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(ADDRESS_HOME_LINE1);
+  form_structure.reset(new FormStructure(form));
+  for (size_t i = 0; i < form_structure->field_count(); ++i)
+    form_structure->set_possible_types(i, possible_field_types[i]);
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "11817937699000629499\" autofillused=\"false\" "
+            "datapresent=\"14400002\"><field signature=\"1089846",
+            encoded_xml.substr(0, 200));
+
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("F4"),
+                        ASCIIToUTF16("f4"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(CREDIT_CARD_TYPE);
+  form_structure.reset(new FormStructure(form));
+  for (size_t i = 0; i < form_structure->field_count(); ++i)
+    form_structure->set_possible_types(i, possible_field_types[i]);
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "15126663683491865216\" autofillused=\"false\" "
+            "datapresent=\"1440000200000020\"><field signature=",
+            encoded_xml.substr(0, 200));
+}
+
+TEST(FormStructureTest, CheckMultipleTypes) {
+  // Check that multiple types for the field are processed correctly, both in
+  // datapresence and in actual field data.
+  scoped_ptr<FormStructure> form_structure;
+  std::vector<FieldTypeSet> possible_field_types;
+  FormData form;
+  form.method = ASCIIToUTF16("post");
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"),
+                        ASCIIToUTF16("email"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(EMAIL_ADDRESS);
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
+                        ASCIIToUTF16("first"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(NAME_FIRST);
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
+                        ASCIIToUTF16("last"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(NAME_LAST);
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
+                        ASCIIToUTF16("address"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  possible_field_types.push_back(FieldTypeSet());
+  possible_field_types.back().insert(ADDRESS_HOME_LINE1);
+  form_structure.reset(new FormStructure(form));
+  for (size_t i = 0; i < form_structure->field_count(); ++i)
+    form_structure->set_possible_types(i, possible_field_types[i]);
+  std::string encoded_xml;
+  // Now we matched both fields singularly.
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  // datapresent==14400002==00010100010000000000000000000010b set bits are:
+  // #3 == NAME_FIRST
+  // #5 == NAME_LAST
+  // #9 == EMAIL_ADDRESS
+  // #30 == ADDRESS_HOME_LINE1
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "18062476096658145866\" autofillused=\"false\" datapresent="
+            "\"14400002\"><field signature=\"420638584\" autofilltype="
+            "\"9\"/><field signature=\"1089846351\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"5\"/><field signature="
+            "\"509334676\" autofilltype=\"30\"/></autofillupload>",
+            encoded_xml);
+  // Match third field as both first and last.
+  possible_field_types[2].insert(NAME_FIRST);
+  form_structure->set_possible_types(2, possible_field_types[2]);
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  // datapresent==14400002==00010100010000000000000000000010b set bits are:
+  // #3 == NAME_FIRST
+  // #5 == NAME_LAST
+  // #9 == EMAIL_ADDRESS
+  // #30 == ADDRESS_HOME_LINE1
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "18062476096658145866\" autofillused=\"false\" datapresent="
+            "\"14400002\"><field signature=\"420638584\" autofilltype="
+            "\"9\"/><field signature=\"1089846351\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"5\"/><field signature="
+            "\"509334676\" autofilltype=\"30\"/></autofillupload>",
+            encoded_xml);
+  possible_field_types[3].insert(ADDRESS_BILLING_LINE1);
+  form_structure->set_possible_types(
+      form_structure->field_count() - 1,
+      possible_field_types[form_structure->field_count() - 1]);
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  // datapresent==1440000204==0001010001000000000000000000001000000100b set bits
+  // are:
+  // #3 == NAME_FIRST
+  // #5 == NAME_LAST
+  // #9 == EMAIL_ADDRESS
+  // #30 == ADDRESS_HOME_LINE1
+  // #37 == ADDRESS_BILLING_LINE1
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "18062476096658145866\" autofillused=\"false\" datapresent="
+            "\"1440000204\"><field signature=\"420638584\" autofilltype="
+            "\"9\"/><field signature=\"1089846351\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"5\"/><field signature="
+            "\"509334676\" autofilltype=\"30\"/><field signature=\"509334676\" "
+            "autofilltype=\"37\"/></autofillupload>",
+            encoded_xml);
+  possible_field_types[3].clear();
+  possible_field_types[3].insert(ADDRESS_HOME_LINE1);
+  possible_field_types[3].insert(ADDRESS_BILLING_LINE2);
+  form_structure->set_possible_types(
+      form_structure->field_count() - 1,
+      possible_field_types[form_structure->field_count() - 1]);
+  EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+  // datapresent==1440000202==0001010001000000000000000000001000000010b set bits
+  // are:
+  // #3 == NAME_FIRST
+  // #5 == NAME_LAST
+  // #9 == EMAIL_ADDRESS
+  // #30 == ADDRESS_HOME_LINE1
+  // #38 == ADDRESS_BILLING_LINE2
+  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+            "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+            "18062476096658145866\" autofillused=\"false\" datapresent="
+            "\"1440000202\"><field signature=\"420638584\" autofilltype="
+            "\"9\"/><field signature=\"1089846351\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"3\"/><field "
+            "signature=\"2404144663\" autofilltype=\"5\"/><field signature="
+            "\"509334676\" autofilltype=\"30\"/><field signature=\"509334676\" "
+            "autofilltype=\"38\"/></autofillupload>",
+            encoded_xml);
+}
+
+TEST(FormStructureTest, CheckFormSignature) {
+  // Check that form signature is created correctly.
+  scoped_ptr<FormStructure> form_structure;
+  FormData form;
+  form.method = ASCIIToUTF16("post");
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"),
+                        ASCIIToUTF16("email"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
+                        ASCIIToUTF16("first"),
+                        string16(),
+                        ASCIIToUTF16("text"),
+                        0,
+                        false));
+  form_structure.reset(new FormStructure(form));
+
+  EXPECT_EQ(FormStructureTest::Hash64Bit(
+      std::string("://&&email&first")),
+      form_structure->FormSignature());
+
+  form.origin = GURL(std::string("http://www.facebook.com"));
+  form_structure.reset(new FormStructure(form));
+  EXPECT_EQ(FormStructureTest::Hash64Bit(
+      std::string("http://www.facebook.com&&email&first")),
+      form_structure->FormSignature());
+
+  form.action = GURL(std::string("https://login.facebook.com/path"));
+  form_structure.reset(new FormStructure(form));
+  EXPECT_EQ(FormStructureTest::Hash64Bit(
+      std::string("https://login.facebook.com&&email&first")),
+      form_structure->FormSignature());
+
+  form.name = ASCIIToUTF16("login_form");
+  form_structure.reset(new FormStructure(form));
+  EXPECT_EQ(FormStructureTest::Hash64Bit(
+      std::string("https://login.facebook.com&login_form&email&first")),
+      form_structure->FormSignature());
 }
 
 }  // namespace
diff --git a/chrome/browser/autofill/name_field.cc b/chrome/browser/autofill/name_field.cc
index 8a83ff7..11cd534 100644
--- a/chrome/browser/autofill/name_field.cc
+++ b/chrome/browser/autofill/name_field.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/autofill/name_field.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/autofill_type.h"
 #include "grit/autofill_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 NameField* NameField::Parse(std::vector<AutoFillField*>::const_iterator* iter,
                             bool is_ecml) {
diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc
index cb70267..8409fc7 100644
--- a/chrome/browser/autofill/personal_data_manager.cc
+++ b/chrome/browser/autofill/personal_data_manager.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/pref_names.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 namespace {
 
@@ -69,6 +71,27 @@
   return &v;
 }
 
+bool IsValidEmail(const string16& value) {
+  // This regex is more permissive than the official rfc2822 spec on the
+  // subject, but it does reject obvious non-email addresses.
+  const string16 kEmailPattern =
+      ASCIIToUTF16("^[^@]+@[^@]+\\.[a-z]{2,6}$");
+  WebKit::WebRegularExpression re(WebKit::WebString(kEmailPattern),
+                                  WebKit::WebTextCaseInsensitive);
+  return re.match(WebKit::WebString(StringToLowerASCII(value))) != -1;
+}
+
+// Returns true if minimum requirements for import of a given |profile| have
+// been met.  An address submitted via a form must have at least these fields
+// filled.  No verification of validity of the contents is preformed.  This is
+// and existence check only.
+bool IsMinimumAddress(const AutoFillProfile& profile) {
+  return !profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)).empty() &&
+         !profile.GetFieldText(AutoFillType(ADDRESS_HOME_CITY)).empty() &&
+         !profile.GetFieldText(AutoFillType(ADDRESS_HOME_STATE)).empty() &&
+         !profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)).empty();
+}
+
 }  // namespace
 
 PersonalDataManager::~PersonalDataManager() {
@@ -140,21 +163,26 @@
 }
 
 bool PersonalDataManager::ImportFormData(
+<<<<<<< HEAD
     const std::vector<FormStructure*>& form_structures) {
 #ifdef ANDROID
   // TODO: Is this the funcionality that tries to create a profile for the user
   // based on what they've entered into forms?
   return false;
 #else
+=======
+    const std::vector<const FormStructure*>& form_structures,
+    const CreditCard** imported_credit_card) {
+  scoped_ptr<AutoFillProfile> imported_profile(new AutoFillProfile);
+  scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
+
+>>>>>>> chromium.org at r11.0.672.0
   // Parse the form and construct a profile based on the information that is
   // possible to import.
   int importable_fields = 0;
   int importable_credit_card_fields = 0;
-  imported_profile_.reset(new AutoFillProfile);
-  // TODO(jhawkins): Use a hash of the CC# instead of a list of unique IDs?
-  imported_credit_card_.reset(new CreditCard);
 
-  std::vector<FormStructure*>::const_iterator iter;
+  std::vector<const FormStructure*>::const_iterator iter;
   for (iter = form_structures.begin(); iter != form_structures.end(); ++iter) {
     const FormStructure* form = *iter;
     for (size_t i = 0; i < form->field_count(); ++i) {
@@ -173,8 +201,13 @@
         // If the user has a password set, we have no way of setting credit
         // card numbers.
         if (!HasPassword()) {
-          imported_credit_card_->SetInfo(AutoFillType(field_type.field_type()),
-                                         value);
+          if (LowerCaseEqualsASCII(field->form_control_type(), "month")) {
+            DCHECK_EQ(CREDIT_CARD_EXP_MONTH, field_type.field_type());
+            local_imported_credit_card->SetInfoForMonthInputType(value);
+          } else {
+            local_imported_credit_card->SetInfo(
+                AutoFillType(field_type.field_type()), value);
+          }
           ++importable_credit_card_fields;
         }
       } else {
@@ -192,17 +225,17 @@
             continue;
 
           if (group == AutoFillType::PHONE_HOME) {
-            imported_profile_->SetInfo(AutoFillType(PHONE_HOME_COUNTRY_CODE),
-                                       country_code);
-            imported_profile_->SetInfo(AutoFillType(PHONE_HOME_CITY_CODE),
-                                       city_code);
-            imported_profile_->SetInfo(AutoFillType(PHONE_HOME_NUMBER), number);
+            imported_profile->SetInfo(AutoFillType(PHONE_HOME_COUNTRY_CODE),
+                                      country_code);
+            imported_profile->SetInfo(AutoFillType(PHONE_HOME_CITY_CODE),
+                                      city_code);
+            imported_profile->SetInfo(AutoFillType(PHONE_HOME_NUMBER), number);
           } else if (group == AutoFillType::PHONE_FAX) {
-            imported_profile_->SetInfo(AutoFillType(PHONE_FAX_COUNTRY_CODE),
-                                       country_code);
-            imported_profile_->SetInfo(AutoFillType(PHONE_FAX_CITY_CODE),
-                                       city_code);
-            imported_profile_->SetInfo(AutoFillType(PHONE_FAX_NUMBER), number);
+            imported_profile->SetInfo(AutoFillType(PHONE_FAX_COUNTRY_CODE),
+                                      country_code);
+            imported_profile->SetInfo(AutoFillType(PHONE_FAX_CITY_CODE),
+                                      city_code);
+            imported_profile->SetInfo(AutoFillType(PHONE_FAX_NUMBER), number);
           }
 
           continue;
@@ -217,7 +250,7 @@
           if (group == AutoFillType::PHONE_FAX)
             number_type = AutoFillType(PHONE_FAX_NUMBER);
 
-          string16 stored_number = imported_profile_->GetFieldText(number_type);
+          string16 stored_number = imported_profile->GetFieldText(number_type);
           if (stored_number.size() ==
                   static_cast<size_t>(PhoneNumber::kPrefixLength) &&
               value.size() == static_cast<size_t>(PhoneNumber::kSuffixLength)) {
@@ -225,7 +258,10 @@
           }
         }
 
-        imported_profile_->SetInfo(AutoFillType(field_type.field_type()),
+        if (field_type.field_type() == EMAIL_ADDRESS && !IsValidEmail(value))
+          continue;
+
+        imported_profile->SetInfo(AutoFillType(field_type.field_type()),
                                    value);
         ++importable_fields;
       }
@@ -235,34 +271,38 @@
   // If the user did not enter enough information on the page then don't bother
   // importing the data.
   if (importable_fields < kMinProfileImportSize)
-    imported_profile_.reset();
+    imported_profile.reset();
   if (importable_credit_card_fields < kMinCreditCardImportSize)
-    imported_credit_card_.reset();
+    local_imported_credit_card.reset();
 
-  if (imported_credit_card_.get()) {
-    if (!CreditCard::IsCreditCardNumber(imported_credit_card_->GetFieldText(
+  if (imported_profile.get() && !IsMinimumAddress(*imported_profile.get()))
+    imported_profile.reset();
+
+  if (local_imported_credit_card.get() &&
+      !CreditCard::IsCreditCardNumber(local_imported_credit_card->GetFieldText(
           AutoFillType(CREDIT_CARD_NUMBER)))) {
-      imported_credit_card_.reset();
-    }
+    local_imported_credit_card.reset();
   }
 
   // Don't import if we already have this info.
-  if (imported_credit_card_.get()) {
+  if (local_imported_credit_card.get()) {
     for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
          iter != credit_cards_.end();
          ++iter) {
-      if (imported_credit_card_->IsSubsetOf(**iter)) {
-        imported_credit_card_.reset();
+      if (local_imported_credit_card->IsSubsetOf(**iter)) {
+        local_imported_credit_card.reset();
         break;
       }
     }
   }
 
-  if (imported_profile_.get()) {
+  if (imported_profile.get()) {
     // We always save imported profiles.
-    SaveImportedProfile();
+    SaveImportedProfile(*imported_profile);
   }
+  *imported_credit_card = local_imported_credit_card.release();
 
+<<<<<<< HEAD
   return imported_profile_.get() || imported_credit_card_.get();
 #endif
 }
@@ -274,6 +314,9 @@
 
   *profile = imported_profile_.get();
   *credit_card = imported_credit_card_.get();
+=======
+  return imported_profile.get() || *imported_credit_card;
+>>>>>>> chromium.org at r11.0.672.0
 }
 
 void PersonalDataManager::SetProfiles(std::vector<AutoFillProfile>* profiles) {
@@ -406,53 +449,8 @@
       return;
   }
 
-  // Set to true if |profile| is merged into the profile list.
-  bool merged = false;
-
-  // First preference is to add missing values to an existing profile.
-  // Only merge with the first match.
   std::vector<AutoFillProfile> profiles;
-  for (std::vector<AutoFillProfile*>::const_iterator iter =
-           web_profiles_.begin();
-       iter != web_profiles_.end(); ++iter) {
-    if (!merged) {
-      if (profile.IsSubsetOf(**iter)) {
-        // In this case, the existing profile already contains all of the data
-        // in |profile|, so consider the profiles already merged.
-        merged = true;
-      } else if ((*iter)->IntersectionOfTypesHasEqualValues(profile)) {
-        // |profile| contains all of the data in this profile, plus more.
-        merged = true;
-        (*iter)->MergeWith(profile);
-      }
-    }
-    profiles.push_back(**iter);
-  }
-
-  // The second preference, if not merged above, is to alter non-primary values
-  // where the primary values match.
-  // Again, only merge with the first match.
-  if (!merged) {
-    profiles.clear();
-    for (std::vector<AutoFillProfile*>::const_iterator iter =
-             web_profiles_.begin();
-         iter != web_profiles_.end(); ++iter) {
-      if (!merged) {
-        if (!profile.PrimaryValue().empty() &&
-            (*iter)->PrimaryValue() == profile.PrimaryValue()) {
-          merged = true;
-          (*iter)->OverwriteWith(profile);
-        }
-      }
-      profiles.push_back(**iter);
-    }
-  }
-
-  // Finally, if the new profile was not merged with an existing profile then
-  // add the new profile to the list.
-  if (!merged)
-    profiles.push_back(profile);
-
+  MergeProfile(profile, web_profiles_.get(), &profiles);
   SetProfiles(&profiles);
 }
 
@@ -786,57 +784,118 @@
   }
 }
 
+<<<<<<< HEAD
 void PersonalDataManager::SaveImportedProfile() {
 #ifdef ANDROID
   // TODO: This should update the profile in Java land.
   return;
 #else
+=======
+void PersonalDataManager::SaveImportedProfile(
+    const AutoFillProfile& imported_profile) {
+>>>>>>> chromium.org at r11.0.672.0
   if (profile_->IsOffTheRecord())
     return;
 
-  if (!imported_profile_.get())
-    return;
-
-  AddProfile(*imported_profile_);
-#endif
+  AddProfile(imported_profile);
 }
 
-// TODO(jhawkins): Refactor and merge this with SaveImportedProfile.
-void PersonalDataManager::SaveImportedCreditCard() {
+bool PersonalDataManager::MergeProfile(
+    const AutoFillProfile& profile,
+    const std::vector<AutoFillProfile*>& existing_profiles,
+    std::vector<AutoFillProfile>* merged_profiles) {
+  DCHECK(merged_profiles);
+  merged_profiles->clear();
+
+  // Set to true if |profile| is merged into |existing_profiles|.
+  bool merged = false;
+
+  // First preference is to add missing values to an existing profile.
+  // Only merge with the first match.
+  for (std::vector<AutoFillProfile*>::const_iterator iter =
+           existing_profiles.begin();
+       iter != existing_profiles.end(); ++iter) {
+    if (!merged) {
+      if (profile.IsSubsetOf(**iter)) {
+        // In this case, the existing profile already contains all of the data
+        // in |profile|, so consider the profiles already merged.
+        merged = true;
+      } else if ((*iter)->IntersectionOfTypesHasEqualValues(profile)) {
+        // |profile| contains all of the data in this profile, plus more.
+        merged = true;
+        (*iter)->MergeWith(profile);
+      }
+    }
+    merged_profiles->push_back(**iter);
+  }
+
+<<<<<<< HEAD
+  AddProfile(*imported_profile_);
+#endif
+=======
+  // The second preference, if not merged above, is to alter non-primary values
+  // where the primary values match.
+  // Again, only merge with the first match.
+  if (!merged) {
+    merged_profiles->clear();
+    for (std::vector<AutoFillProfile*>::const_iterator iter =
+             existing_profiles.begin();
+         iter != existing_profiles.end(); ++iter) {
+      if (!merged) {
+        if (!profile.PrimaryValue().empty() &&
+            (*iter)->PrimaryValue() == profile.PrimaryValue()) {
+          merged = true;
+          (*iter)->OverwriteWith(profile);
+        }
+      }
+      merged_profiles->push_back(**iter);
+    }
+  }
+
+  // Finally, if the new profile was not merged with an existing profile then
+  // add the new profile to the list.
+  if (!merged)
+    merged_profiles->push_back(profile);
+
+  return merged;
+>>>>>>> chromium.org at r11.0.672.0
+}
+
+
+void PersonalDataManager::SaveImportedCreditCard(
+    const CreditCard& imported_credit_card) {
   if (profile_->IsOffTheRecord())
     return;
 
-  if (!imported_credit_card_.get())
-    return;
-
-  // Set to true if |imported_credit_card_| is merged into the profile list.
+  // Set to true if |imported_credit_card| is merged into the credit card list.
   bool merged = false;
 
   std::vector<CreditCard> creditcards;
-  for (std::vector<CreditCard*>::const_iterator iter =
-           credit_cards_.begin();
-       iter != credit_cards_.end(); ++iter) {
-    if (imported_credit_card_->IsSubsetOf(**iter)) {
+  for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
+       iter != credit_cards_.end();
+       ++iter) {
+    if (imported_credit_card.IsSubsetOf(**iter)) {
       // In this case, the existing credit card already contains all of the data
-      // in |imported_credit_card_|, so consider the credit cards already
+      // in |imported_credit_card|, so consider the credit cards already
       // merged.
       merged = true;
     } else if ((*iter)->IntersectionOfTypesHasEqualValues(
-        *imported_credit_card_)) {
-      // |imported_profile| contains all of the data in this profile, plus more.
+        imported_credit_card)) {
+      // |imported_credit_card| contains all of the data in this credit card,
+      // plus more.
       merged = true;
-      (*iter)->MergeWith(*imported_credit_card_);
-    } else if (!imported_credit_card_->number().empty() &&
-               (*iter)->number() == imported_credit_card_->number()) {
+      (*iter)->MergeWith(imported_credit_card);
+    } else if (!imported_credit_card.number().empty() &&
+               (*iter)->number() == imported_credit_card.number()) {
       merged = true;
-      (*iter)->OverwriteWith(*imported_credit_card_);
+      (*iter)->OverwriteWith(imported_credit_card);
     }
 
     creditcards.push_back(**iter);
   }
 
   if (!merged)
-    creditcards.push_back(*imported_credit_card_);
+    creditcards.push_back(imported_credit_card);
 
   SetCreditCards(&creditcards);
 }
diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h
index 6d25013..1012d04 100644
--- a/chrome/browser/autofill/personal_data_manager.h
+++ b/chrome/browser/autofill/personal_data_manager.h
@@ -63,22 +63,16 @@
   // Removes |observer| as the observer of this PersonalDataManager.
   virtual void RemoveObserver(PersonalDataManager::Observer* observer);
 
+        // TODO(isherman): Update this comment
   // If AutoFill is able to determine the field types of a significant number of
   // field types that contain information in the FormStructures a profile will
   // be created with all of the information from recognized fields. Returns
   // whether a profile was created.
-  bool ImportFormData(const std::vector<FormStructure*>& form_structures);
-
-  // Gets |imported_profile_| and |imported_credit_card_| and returns their
-  // values in |profile| and |credit_card| parameters respectively.  One or
-  // both may return NULL.  The objects returned are owned by the
-  // PersonalDataManager, so should be considered weak references by caller.
-  // TODO(dhollowa) Now that we aren't immediately saving the imported form
-  // data, we should store the profile and CC in the AFM instead of the PDM.
-  void GetImportedFormData(AutoFillProfile** profile, CreditCard** credit_card);
+  bool ImportFormData(const std::vector<const FormStructure*>& form_structures,
+                      const CreditCard** credit_card);
 
   // Saves a credit card value detected in |ImportedFormData|.
-  void SaveImportedCreditCard();
+  void SaveImportedCreditCard(const CreditCard& imported_credit_card);
 
   // Sets |web_profiles_| to the contents of |profiles| and updates the web
   // database by adding, updating and removing profiles.
@@ -166,6 +160,7 @@
   // Make sure that only Profile and certain tests can create an instance of
   // PersonalDataManager.
   friend class base::RefCountedThreadSafe<PersonalDataManager>;
+  friend class AutoFillMergeTest;
   friend class PersonalDataManagerTest;
   friend class ProfileImpl;
   friend class ProfileSyncServiceAutofillTest;
@@ -174,7 +169,7 @@
 #endif
 
   PersonalDataManager();
-  ~PersonalDataManager();
+  virtual ~PersonalDataManager();
 
   // Returns the profile of the tab contents.
   Profile* profile();
@@ -208,8 +203,15 @@
   // two methods into one.
   void SetUniqueCreditCardLabels(std::vector<CreditCard>* credit_cards);
 
-  // Saves |imported_profile_| to the WebDB if it exists.
-  void SaveImportedProfile();
+  // Saves |imported_profile| to the WebDB if it exists.
+  virtual void SaveImportedProfile(const AutoFillProfile& imported_profile);
+
+  // Merges |profile| into one of the |existing_profiles| if possible; otherwise
+  // appends |profile| to the end of that list. Fills |merged_profiles| with the
+  // result.
+  bool MergeProfile(const AutoFillProfile& profile,
+                    const std::vector<AutoFillProfile*>& existing_profiles,
+                    std::vector<AutoFillProfile>* merged_profiles);
 
   // The profile hosting this PersonalDataManager.
   Profile* profile_;
@@ -230,12 +232,6 @@
   // The loaded credit cards.
   ScopedVector<CreditCard> credit_cards_;
 
-  // The profile that is imported from a web form by ImportFormData.
-  scoped_ptr<AutoFillProfile> imported_profile_;
-
-  // The credit card that is imported from a web form by ImportFormData.
-  scoped_ptr<CreditCard> imported_credit_card_;
-
   // The hash of the password used to store the credit card.  This is empty if
   // no password exists.
   string16 password_hash_;
diff --git a/chrome/browser/autofill/personal_data_manager_mac.mm b/chrome/browser/autofill/personal_data_manager_mac.mm
index d6ddf1b..a081122 100644
--- a/chrome/browser/autofill/personal_data_manager_mac.mm
+++ b/chrome/browser/autofill/personal_data_manager_mac.mm
@@ -6,7 +6,6 @@
 
 #import <AddressBook/AddressBook.h>
 
-#include "app/l10n_util_mac.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/scoped_vector.h"
@@ -15,6 +14,7 @@
 #include "chrome/browser/autofill/phone_number.h"
 #include "chrome/common/guid.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
diff --git a/chrome/browser/autofill/personal_data_manager_unittest.cc b/chrome/browser/autofill/personal_data_manager_unittest.cc
index 79f3d58..8687ed2 100644
--- a/chrome/browser/autofill/personal_data_manager_unittest.cc
+++ b/chrome/browser/autofill/personal_data_manager_unittest.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/autofill/form_structure.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/password_manager/encryptor.h"
 #include "chrome/common/guid.h"
 #include "chrome/common/notification_details.h"
@@ -22,7 +21,6 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/testing_profile.h"
 #include "webkit/glue/form_data.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -61,6 +59,7 @@
   }
 
   virtual void TearDown() {
+    personal_data_ = NULL;
     if (profile_.get())
       profile_.reset(NULL);
 
@@ -268,6 +267,8 @@
   EXPECT_EQ(0, profile0.Compare(*results1.at(0)));
   EXPECT_EQ(0, profile1.Compare(*results1.at(1)));
 
+  MessageLoop::current()->Run();
+
   // Add two test credit cards to the database.
   std::vector<CreditCard> update_cc;
   update_cc.push_back(creditcard0);
@@ -525,10 +526,24 @@
   autofill_test::CreateTestFormField(
       "Email:", "email", "theprez@gmail.com", "text", &field);
   form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address:", "address1", "21 Laussat St", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form.fields.push_back(field);
   FormStructure form_structure(form);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -538,15 +553,60 @@
 
   AutoFillProfile expected;
   autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
-      "Washington", "theprez@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL);
+      "Washington", "theprez@gmail.com", NULL, "21 Laussat St", NULL,
+      "San Francisco", "California", "94102", NULL, NULL, NULL);
   const std::vector<AutoFillProfile*>& results = personal_data_->profiles();
   ASSERT_EQ(1U, results.size());
   EXPECT_EQ(0, expected.Compare(*results[0]));
 }
 
-// Crashy, http://crbug.com/67423.
-TEST_F(PersonalDataManagerTest, DISABLED_ImportFormDataNotEnoughFilledFields) {
+TEST_F(PersonalDataManagerTest, ImportFormDataBadEmail) {
+  FormData form;
+  webkit_glue::FormField field;
+  autofill_test::CreateTestFormField(
+      "First name:", "first_name", "George", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Last name:", "last_name", "Washington", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Email:", "email", "bogus", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address:", "address1", "21 Laussat St", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form.fields.push_back(field);
+  FormStructure form_structure(form);
+  std::vector<const FormStructure*> forms;
+  forms.push_back(&form_structure);
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+
+  // Wait for the refresh.
+  EXPECT_CALL(personal_data_observer_,
+      OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+  MessageLoop::current()->Run();
+
+  AutoFillProfile expected;
+  autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
+      "Washington", NULL, NULL, "21 Laussat St", NULL,
+      "San Francisco", "California", "94102", NULL, NULL, NULL);
+  const std::vector<AutoFillProfile*>& results = personal_data_->profiles();
+  ASSERT_EQ(1U, results.size());
+  EXPECT_EQ(0, expected.Compare(*results[0]));
+}
+
+TEST_F(PersonalDataManagerTest, ImportFormDataNotEnoughFilledFields) {
   FormData form;
   webkit_glue::FormField field;
   autofill_test::CreateTestFormField(
@@ -559,14 +619,18 @@
       "Card number:", "card_number", "4111 1111 1111 1111", "text", &field);
   form.fields.push_back(field);
   FormStructure form_structure(form);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure);
-  EXPECT_FALSE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_FALSE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
       OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
 
+  MessageLoop::current()->Run();
+
   const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles();
   ASSERT_EQ(0U, profiles.size());
   const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
@@ -594,10 +658,24 @@
       "Phone #:", "home_phone_suffix", "0000", "text", &field);
   field.set_max_length(4);
   form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address:", "address1", "21 Laussat St", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form.fields.push_back(field);
   FormStructure form_structure(form);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -606,8 +684,9 @@
   MessageLoop::current()->Run();
 
   AutoFillProfile expected;
-  autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, "Washington",
-      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "6505550000", NULL);
+  autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
+      "Washington", NULL, NULL, "21 Laussat St", NULL,
+      "San Francisco", "California", "94102", NULL, "6505550000", NULL);
   const std::vector<AutoFillProfile*>& results = personal_data_->profiles();
   ASSERT_EQ(1U, results.size());
   EXPECT_EQ(0, expected.Compare(*results[0]));
@@ -686,11 +765,25 @@
   autofill_test::CreateTestFormField(
       "Email:", "email", "theprez@gmail.com", "text", &field);
   form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address:", "address1", "21 Laussat St", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -700,8 +793,8 @@
 
   AutoFillProfile expected;
   autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
-      "Washington", "theprez@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL);
+      "Washington", "theprez@gmail.com", NULL, "21 Laussat St", NULL,
+      "San Francisco", "California", "94102", NULL, NULL, NULL);
   const std::vector<AutoFillProfile*>& results1 = personal_data_->profiles();
   ASSERT_EQ(1U, results1.size());
   EXPECT_EQ(0, expected.Compare(*results1[0]));
@@ -717,11 +810,24 @@
   autofill_test::CreateTestFormField(
       "Email:", "email", "second@gmail.com", "text", &field);
   form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address:", "address1", "21 Laussat St", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form2.fields.push_back(field);
 
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -733,8 +839,8 @@
 
   AutoFillProfile expected2;
   autofill_test::SetProfileInfo(&expected2, NULL, "John", NULL,
-      "Adams", "second@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL);
+      "Adams", "second@gmail.com", NULL, "21 Laussat St", NULL,
+      "San Francisco", "California", "94102", NULL, NULL, NULL);
   ASSERT_EQ(2U, results2.size());
   EXPECT_EQ(0, expected.Compare(*results2[0]));
   EXPECT_EQ(0, expected2.Compare(*results2[1]));
@@ -756,6 +862,15 @@
       "Address Line 2:", "address2", "Suite A", "text", &field);
   form1.fields.push_back(field);
   autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
       "Email:", "email", "theprez@gmail.com", "text", &field);
   form1.fields.push_back(field);
   // Phone gets updated.
@@ -764,9 +879,11 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -777,7 +894,8 @@
   AutoFillProfile expected;
   autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
       "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue",
-      "Suite A", NULL, NULL, NULL, NULL, "4445556666", NULL);
+      "Suite A", "San Francisco", "California", "94102", NULL, "4445556666",
+      NULL);
   const std::vector<AutoFillProfile*>& results1 = personal_data_->profiles();
   ASSERT_EQ(1U, results1.size());
   EXPECT_EQ(0, expected.Compare(*results1[0]));
@@ -797,6 +915,15 @@
       "Address Line 2:", "address2", "Suite A", "text", &field);
   form2.fields.push_back(field);
   autofill_test::CreateTestFormField(
+      "City:", "city", "San Francisco", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "California", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zip", "94102", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
       "Email:", "email", "theprez@gmail.com", "text", &field);
   form2.fields.push_back(field);
   // Country gets added.
@@ -811,7 +938,8 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -824,7 +952,8 @@
   AutoFillProfile expected2;
   autofill_test::SetProfileInfo(&expected2, NULL, "George", NULL,
       "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue",
-      "Suite A", NULL, NULL, NULL, "USA", "1231231234", NULL);
+      "Suite A", "San Francisco", "California", "94102", "USA", "1231231234",
+      NULL);
   ASSERT_EQ(1U, results2.size());
   EXPECT_EQ(0, expected2.Compare(*results2[0]));
 }
@@ -839,13 +968,24 @@
       "Last name:", "last_name", "Washington", "text", &field);
   form1.fields.push_back(field);
   autofill_test::CreateTestFormField(
-      "Email:", "email", "theprez@gmail.com", "text", &field);
+      "Address Line 1:", "address", "190 High Street", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "Philadelphia", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "Pennsylvania", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zipcode", "19106", "text", &field);
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -855,8 +995,8 @@
 
   AutoFillProfile expected;
   autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
-      "Washington", "theprez@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL);
+      "Washington", NULL, NULL, "190 High Street", NULL,
+      "Philadelphia", "Pennsylvania", "19106", NULL, NULL, NULL);
   const std::vector<AutoFillProfile*>& results1 = personal_data_->profiles();
   ASSERT_EQ(1U, results1.size());
   EXPECT_EQ(0, expected.Compare(*results1[0]));
@@ -870,6 +1010,9 @@
       "Last name:", "last_name", "Washington", "text", &field);
   form2.fields.push_back(field);
   autofill_test::CreateTestFormField(
+      "Email:", "email", "theprez@gmail.com", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
       "Address Line 1:", "address", "190 High Street", "text", &field);
   form2.fields.push_back(field);
   autofill_test::CreateTestFormField(
@@ -885,7 +1028,8 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -918,11 +1062,25 @@
   autofill_test::CreateTestFormField(
       "Email:", "email", "theprez@gmail.com", "text", &field);
   form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address Line 1:", "address", "190 High Street", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "Philadelphia", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "Pennsylvania", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zipcode", "19106", "text", &field);
+  form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -932,8 +1090,8 @@
 
   AutoFillProfile expected;
   autofill_test::SetProfileInfo(&expected, NULL, "George", NULL,
-      "Washington", "theprez@gmail.com", "Government", NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL, NULL);
+      "Washington", "theprez@gmail.com", "Government", "190 High Street", NULL,
+      "Philadelphia", "Pennsylvania", "19106", NULL, NULL, NULL);
   const std::vector<AutoFillProfile*>& results1 = personal_data_->profiles();
   ASSERT_EQ(1U, results1.size());
   EXPECT_EQ(0, expected.Compare(*results1[0]));
@@ -950,11 +1108,24 @@
   autofill_test::CreateTestFormField(
       "Email:", "email", "theprez@gmail.com", "text", &field);
   form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address Line 1:", "address", "190 High Street", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "Philadelphia", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "State:", "state", "Pennsylvania", "text", &field);
+  form2.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Zip:", "zipcode", "19106", "text", &field);
+  form2.fields.push_back(field);
 
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -969,6 +1140,48 @@
   EXPECT_EQ(0, expected.Compare(*results2[0]));
 }
 
+TEST_F(PersonalDataManagerTest, AggregateProfileWithInsufficientAddress) {
+  FormData form1;
+  webkit_glue::FormField field;
+  autofill_test::CreateTestFormField(
+      "First name:", "first_name", "George", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Last name:", "last_name", "Washington", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Company:", "company", "Government", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Email:", "email", "theprez@gmail.com", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "Address Line 1:", "address", "190 High Street", "text", &field);
+  form1.fields.push_back(field);
+  autofill_test::CreateTestFormField(
+      "City:", "city", "Philadelphia", "text", &field);
+  form1.fields.push_back(field);
+
+  FormStructure form_structure1(form1);
+  std::vector<const FormStructure*> forms;
+  forms.push_back(&form_structure1);
+  const CreditCard* imported_credit_card;
+  EXPECT_FALSE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+
+  // Wait for the refresh.
+  EXPECT_CALL(personal_data_observer_,
+      OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+  MessageLoop::current()->Run();
+
+  const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles();
+  ASSERT_EQ(0U, profiles.size());
+  const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
+  ASSERT_EQ(0U, credit_cards.size());
+}
+
+
 TEST_F(PersonalDataManagerTest, AggregateTwoDifferentCreditCards) {
   FormData form1;
 
@@ -988,10 +1201,13 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1024,8 +1240,10 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1061,10 +1279,13 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1097,8 +1318,8 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_FALSE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  EXPECT_FALSE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Note: no refresh here.
 
@@ -1126,10 +1347,13 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1163,8 +1387,10 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1201,10 +1427,13 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1234,8 +1463,8 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  personal_data_->ImportFormData(forms);
-  personal_data_->SaveImportedCreditCard();
+  EXPECT_FALSE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Note: no refresh here.
 
@@ -1267,10 +1496,13 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1302,8 +1534,8 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  personal_data_->ImportFormData(forms);
-  personal_data_->SaveImportedCreditCard();
+  EXPECT_FALSE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
 
   // Note: no refresh here.
 
@@ -1333,10 +1565,13 @@
   form1.fields.push_back(field);
 
   FormStructure form_structure1(form1);
-  std::vector<FormStructure*> forms;
+  std::vector<const FormStructure*> forms;
   forms.push_back(&form_structure1);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  const CreditCard* imported_credit_card;
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
@@ -1370,8 +1605,10 @@
   FormStructure form_structure2(form2);
   forms.clear();
   forms.push_back(&form_structure2);
-  EXPECT_TRUE(personal_data_->ImportFormData(forms));
-  personal_data_->SaveImportedCreditCard();
+  EXPECT_TRUE(personal_data_->ImportFormData(forms, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  personal_data_->SaveImportedCreditCard(*imported_credit_card);
+  delete imported_credit_card;
 
   // Wait for the refresh.
   EXPECT_CALL(personal_data_observer_,
diff --git a/chrome/browser/autofill/phone_field.cc b/chrome/browser/autofill/phone_field.cc
index 083a8dc..f6b41a2 100644
--- a/chrome/browser/autofill/phone_field.cc
+++ b/chrome/browser/autofill/phone_field.cc
@@ -4,14 +4,18 @@
 
 #include "chrome/browser/autofill/phone_field.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/autofill_field.h"
+#include "chrome/browser/autofill/fax_number.h"
+#include "chrome/browser/autofill/home_phone_number.h"
 #include "grit/autofill_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+PhoneField::~PhoneField() {}
 
 // static
 PhoneField* PhoneField::Parse(std::vector<AutoFillField*>::const_iterator* iter,
@@ -23,70 +27,18 @@
   if (is_ecml)
     return ParseECML(iter);
 
-  std::vector<AutoFillField*>::const_iterator q = *iter;
-  AutoFillField* phone = NULL;
-  AutoFillField* phone2 = NULL;
-  AutoFillField* phone3 = NULL;
-  bool area_code;  // true if we've parsed an area code field.
-
-  // Some pages, such as BloomingdalesShipping.html, have a field labeled
-  // "Area Code and Phone"; we want to parse this as a phone number field so
-  // we look for "phone" before we look for "area code".
-  if (ParseText(&q, l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_RE), &phone)) {
-    area_code = false;
-  } else {
-    if (!ParseText(&q,
-                   l10n_util::GetStringUTF16(IDS_AUTOFILL_AREA_CODE_RE),
-                   &phone))
-      return NULL;
-    area_code = true;
-    ParseText(&q, l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_RE), &phone2);
-  }
-
-  // Sometimes phone number fields are separated by "-" (e.g. test page
-  // Crate and Barrel Check Out.html).  Also, area codes are sometimes
-  // surrounded by parentheses, so a ")" may appear after the area code field.
-  //
-  // We used to match "tel" here, which we've seen in field names (e.g. on
-  // Newegg2.html), but that's too general: some pages (e.g.
-  // uk/Furniture123-1.html) have several phone numbers in succession and we
-  // don't want those to be parsed as components of a single phone number.
-  if (phone2 == NULL)
-    ParseText(&q,
-              l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_PREFIX_RE),
-              &phone2);
-
-  // Look for a third text box.
-  if (phone2)
-    ParseText(&q,
-              l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_SUFFIX_RE),
-              &phone3);
-
-  // Now we have one, two, or three phone number text fields.  Package them
-  // up into a PhoneField object.
-
   scoped_ptr<PhoneField> phone_field(new PhoneField);
-  if (phone2 == NULL) {  // only one field
-    if (area_code)  // it's an area code
-      return NULL;  // doesn't make sense
-    phone_field->phone_ = phone;
-  } else {
-    phone_field->area_code_ = phone;
-    if (phone3 == NULL) {  // two fields
-      phone_field->phone_ = phone2;
-    } else {  // three boxes: area code, prefix and suffix
-      phone_field->prefix_ = phone2;
-      phone_field->phone_ = phone3;
-    }
+
+  // Go through the phones in order HOME, FAX, attempting to match. HOME should
+  // be the last as it is a catch all case ("fax" and "faxarea" parsed as FAX,
+  // but "area" and "someotherarea" parsed as HOME, for example).
+  for (int i = PHONE_TYPE_MAX - 1; i >= PHONE_TYPE_FIRST; --i) {
+    phone_field->SetPhoneType(static_cast<PhoneField::PHONE_TYPE>(i));
+    if (ParseInternal(phone_field.get(), iter, i == HOME_PHONE))
+      return phone_field.release();
   }
 
-  // Now look for an extension.
-  ParseText(&q,
-            l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_EXTENSION_RE),
-            &phone_field->extension_);
-
-  *iter = q;
-  return phone_field.release();
+  return NULL;
 }
 
 // static
@@ -108,7 +60,8 @@
   bool ok;
 
   if (area_code_ != NULL) {
-    ok = Add(field_type_map, area_code_, AutoFillType(PHONE_HOME_CITY_CODE));
+    ok = Add(field_type_map, area_code_,
+             AutoFillType(number_->GetCityCodeType()));
     DCHECK(ok);
 
     if (prefix_ != NULL) {
@@ -116,20 +69,24 @@
       // we fill only the prefix depending on the size of the input field.
       ok = ok && Add(field_type_map,
                      prefix_,
-                     AutoFillType(PHONE_HOME_NUMBER));
+                     AutoFillType(number_->GetNumberType()));
       DCHECK(ok);
       // We tag the suffix as PHONE_HOME_NUMBER, then when filling the form
       // we fill only the suffix depending on the size of the input field.
       ok = ok && Add(field_type_map,
                      phone_,
-                     AutoFillType(PHONE_HOME_NUMBER));
+                     AutoFillType(number_->GetNumberType()));
       DCHECK(ok);
     } else {
-      ok = ok && Add(field_type_map, phone_, AutoFillType(PHONE_HOME_NUMBER));
+      ok = ok && Add(field_type_map,
+                     phone_,
+                     AutoFillType(number_->GetNumberType()));
       DCHECK(ok);
     }
   } else {
-    ok = Add(field_type_map, phone_, AutoFillType(PHONE_HOME_WHOLE_NUMBER));
+    ok = Add(field_type_map,
+             phone_,
+             AutoFillType(number_->GetWholeNumberType()));
     DCHECK(ok);
   }
 
@@ -141,4 +98,136 @@
       area_code_(NULL),
       prefix_(NULL),
       extension_(NULL) {
+  SetPhoneType(HOME_PHONE);
 }
+
+string16 PhoneField::GetAreaRegex() const {
+  // This one is the same for Home and Fax numbers.
+  return l10n_util::GetStringUTF16(IDS_AUTOFILL_AREA_CODE_RE);
+}
+
+string16 PhoneField::GetPhoneRegex() const {
+  if (phone_type_ == HOME_PHONE)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_RE);
+  else if (phone_type_ == FAX_PHONE)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_FAX_RE);
+  else
+    NOTREACHED();
+  return string16();
+}
+
+string16 PhoneField::GetPrefixRegex() const {
+  // This one is the same for Home and Fax numbers.
+  return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_PREFIX_RE);
+}
+
+string16 PhoneField::GetSuffixRegex() const {
+  // This one is the same for Home and Fax numbers.
+  return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_SUFFIX_RE);
+}
+
+string16 PhoneField::GetExtensionRegex() const {
+  // This one is the same for Home and Fax numbers.
+  return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_EXTENSION_RE);
+}
+
+// static
+bool PhoneField::ParseInternal(
+    PhoneField *phone_field,
+    std::vector<AutoFillField*>::const_iterator* iter,
+    bool regular_phone) {
+  DCHECK(iter);
+
+  DCHECK(phone_field);
+  if (!phone_field)
+    return false;
+
+  std::vector<AutoFillField*>::const_iterator q = *iter;
+  // The form owns the following variables, so they should not be deleted.
+  AutoFillField* phone = NULL;
+  AutoFillField* phone2 = NULL;
+  AutoFillField* phone3 = NULL;
+  bool area_code = false;  // true if we've parsed an area code field.
+
+  // Some pages, such as BloomingdalesShipping.html, have a field labeled
+  // "Area Code and Phone"; we want to parse this as a phone number field so
+  // we look for "phone" before we look for "area code".
+  if (ParseText(&q, phone_field->GetPhoneRegex(), &phone)) {
+    area_code = false;
+    // Check the case when the match is for non-home phone and area code, e.g.
+    // first field is a "Fax area code" and the subsequent is "Fax phone".
+    if (!regular_phone) {
+      // Attempt parsing of the same field as an area code and then phone:
+      std::vector<AutoFillField*>::const_iterator temp_it = *iter;
+      AutoFillField* tmp_phone1 = NULL;
+      AutoFillField* tmp_phone2 = NULL;
+      if (ParseText(&temp_it, phone_field->GetAreaRegex(), &tmp_phone1) &&
+          ParseText(&temp_it, phone_field->GetPhoneRegex(), &tmp_phone2)) {
+        phone = tmp_phone1;
+        phone2 = tmp_phone2;
+        q = temp_it;
+        area_code = true;
+      }
+    }
+  } else {
+    if (!ParseText(&q, phone_field->GetAreaRegex(), &phone))
+      return false;
+    area_code = true;
+    // If this is not a home phone and there was no specification before
+    // the phone number actually starts (e.g. field 1 "Area code:", field 2
+    // "Fax:"), we skip searching for preffix and suffix and bail out.
+    if (!ParseText(&q, phone_field->GetPhoneRegex(), &phone2) && !regular_phone)
+      return false;
+  }
+
+  // Sometimes phone number fields are separated by "-" (e.g. test page
+  // Crate and Barrel Check Out.html).  Also, area codes are sometimes
+  // surrounded by parentheses, so a ")" may appear after the area code field.
+  //
+  // We used to match "tel" here, which we've seen in field names (e.g. on
+  // Newegg2.html), but that's too general: some pages (e.g.
+  // uk/Furniture123-1.html) have several phone numbers in succession and we
+  // don't want those to be parsed as components of a single phone number.
+  if (phone2 == NULL)
+    ParseText(&q, phone_field->GetPrefixRegex(), &phone2);
+
+  // Look for a third text box.
+  if (phone2)
+    ParseText(&q, phone_field->GetSuffixRegex(), &phone3);
+
+  // Now we have one, two, or three phone number text fields.  Package them
+  // up into a PhoneField object.
+
+  if (phone2 == NULL) {  // only one field
+    if (area_code) {
+      // It's an area code - it doesn't make sense.
+      return false;
+    }
+    phone_field->phone_ = phone;
+  } else {
+    phone_field->area_code_ = phone;
+    if (phone3 == NULL) {  // two fields
+      phone_field->phone_ = phone2;
+    } else {  // three boxes: area code, prefix and suffix
+      phone_field->prefix_ = phone2;
+      phone_field->phone_ = phone3;
+    }
+  }
+
+  // Now look for an extension.
+  ParseText(&q, phone_field->GetExtensionRegex(), &phone_field->extension_);
+
+  *iter = q;
+  return true;
+}
+
+void PhoneField::SetPhoneType(PHONE_TYPE phone_type) {
+  // Field types are different as well, so we create a temporary phone number,
+  // to get relevant field types.
+  if (phone_type == HOME_PHONE)
+    number_.reset(new HomePhoneNumber);
+  else
+    number_.reset(new FaxNumber);
+  phone_type_ = phone_type;
+}
+
diff --git a/chrome/browser/autofill/phone_field.h b/chrome/browser/autofill/phone_field.h
index 2642a5c..2563a81 100644
--- a/chrome/browser/autofill/phone_field.h
+++ b/chrome/browser/autofill/phone_field.h
@@ -8,8 +8,10 @@
 
 #include <vector>
 
+#include "base/scoped_ptr.h"
 #include "chrome/browser/autofill/autofill_type.h"
 #include "chrome/browser/autofill/form_field.h"
+#include "chrome/browser/autofill/phone_number.h"
 
 class AutoFillField;
 
@@ -19,6 +21,8 @@
 // - number
 class PhoneField : public FormField {
  public:
+  virtual ~PhoneField();
+
   static PhoneField* Parse(std::vector<AutoFillField*>::const_iterator* iter,
                            bool is_ecml);
   static PhoneField* ParseECML(
@@ -29,6 +33,39 @@
  private:
   PhoneField();
 
+  enum PHONE_TYPE {
+    PHONE_TYPE_FIRST = 0,
+    HOME_PHONE = PHONE_TYPE_FIRST,
+    FAX_PHONE,
+
+    // Must be last.
+    PHONE_TYPE_MAX,
+  };
+
+  // Some field names are different for phone and fax.
+  string16 GetAreaRegex() const;
+  string16 GetPhoneRegex() const;
+  string16 GetPrefixRegex() const;
+  string16 GetSuffixRegex() const;
+  string16 GetExtensionRegex() const;
+
+  // |field| - field to fill up on successful parsing.
+  // |iter| - in/out. Form field iterator, points to the first field that is
+  //   attempted to be parsed. If parsing successful, points to the first field
+  //   after parsed fields.
+  // |regular_phone| - true if the parsed phone is a HOME phone, false
+  //   otherwise.
+  static bool ParseInternal(PhoneField* field,
+                            std::vector<AutoFillField*>::const_iterator* iter,
+                            bool regular_phone);
+
+  void SetPhoneType(PHONE_TYPE phone_type);
+
+  // Field types are different as well, so we create a temporary phone number,
+  // to get relevant field types.
+  scoped_ptr<PhoneNumber> number_;
+  PHONE_TYPE phone_type_;
+
   // Always present; holds suffix if prefix is present.
   AutoFillField* phone_;
 
diff --git a/chrome/browser/autofill/phone_field_unittest.cc b/chrome/browser/autofill/phone_field_unittest.cc
index e79d64a..96b02f3 100644
--- a/chrome/browser/autofill/phone_field_unittest.cc
+++ b/chrome/browser/autofill/phone_field_unittest.cc
@@ -263,4 +263,95 @@
   EXPECT_EQ(PHONE_HOME_NUMBER, field_type_map_[ASCIIToUTF16("suffix1")]);
 }
 
+TEST_F(PhoneFieldTest, ParseOneLineFax) {
+  list_.push_back(
+      new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Fax"),
+                                               ASCIIToUTF16("fax"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false),
+                        ASCIIToUTF16("fax1")));
+  list_.push_back(NULL);
+  iter_ = list_.begin();
+  field_.reset(PhoneField::Parse(&iter_, false));
+  ASSERT_NE(static_cast<PhoneField*>(NULL), field_.get());
+  ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+  ASSERT_TRUE(
+      field_type_map_.find(ASCIIToUTF16("fax1")) != field_type_map_.end());
+  EXPECT_EQ(PHONE_FAX_WHOLE_NUMBER, field_type_map_[ASCIIToUTF16("fax1")]);
+}
+
+TEST_F(PhoneFieldTest, ParseTwoLineFax) {
+  list_.push_back(
+      new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Area Code"),
+                                               ASCIIToUTF16("area code"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false),
+                        ASCIIToUTF16("areacode1")));
+  list_.push_back(
+      new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Fax"),
+                                               ASCIIToUTF16("fax"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false),
+                        ASCIIToUTF16("fax1")));
+  list_.push_back(NULL);
+  iter_ = list_.begin();
+  field_.reset(PhoneField::Parse(&iter_, false));
+  ASSERT_NE(static_cast<PhoneField*>(NULL), field_.get());
+  ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+  ASSERT_TRUE(
+      field_type_map_.find(ASCIIToUTF16("areacode1")) != field_type_map_.end());
+  // It should be FAX, based on the other phone in the group.
+  EXPECT_EQ(PHONE_FAX_CITY_CODE, field_type_map_[ASCIIToUTF16("areacode1")]);
+  ASSERT_TRUE(
+      field_type_map_.find(ASCIIToUTF16("fax1")) != field_type_map_.end());
+  EXPECT_EQ(PHONE_FAX_NUMBER, field_type_map_[ASCIIToUTF16("fax1")]);
+}
+
+TEST_F(PhoneFieldTest, ThreePartFaxNumberPrefixSuffix) {
+  list_.push_back(
+      new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Fax:"),
+                                               ASCIIToUTF16("area"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false),
+                        ASCIIToUTF16("areacode1")));
+  list_.push_back(
+      new AutoFillField(webkit_glue::FormField(string16(),
+                                               ASCIIToUTF16("prefix"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false),
+                        ASCIIToUTF16("prefix1")));
+  list_.push_back(
+      new AutoFillField(webkit_glue::FormField(string16(),
+                                               ASCIIToUTF16("suffix"),
+                                               string16(),
+                                               ASCIIToUTF16("text"),
+                                               0,
+                                               false),
+                        ASCIIToUTF16("suffix1")));
+  list_.push_back(NULL);
+  iter_ = list_.begin();
+  field_.reset(PhoneField::Parse(&iter_, false));
+  ASSERT_NE(static_cast<PhoneField*>(NULL), field_.get());
+  ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+  ASSERT_TRUE(
+      field_type_map_.find(ASCIIToUTF16("areacode1")) != field_type_map_.end());
+  EXPECT_EQ(PHONE_FAX_CITY_CODE, field_type_map_[ASCIIToUTF16("areacode1")]);
+  ASSERT_TRUE(
+      field_type_map_.find(ASCIIToUTF16("prefix1")) != field_type_map_.end());
+  EXPECT_EQ(PHONE_FAX_NUMBER, field_type_map_[ASCIIToUTF16("prefix1")]);
+  ASSERT_TRUE(
+      field_type_map_.find(ASCIIToUTF16("suffix1")) != field_type_map_.end());
+  EXPECT_EQ(PHONE_FAX_NUMBER, field_type_map_[ASCIIToUTF16("suffix1")]);
+}
+
 }  // namespace
diff --git a/chrome/browser/autofill/phone_number.h b/chrome/browser/autofill/phone_number.h
index 25648bc..3bb94ca 100644
--- a/chrome/browser/autofill/phone_number.h
+++ b/chrome/browser/autofill/phone_number.h
@@ -45,6 +45,14 @@
   static const int kSuffixOffset = 3;
   static const int kSuffixLength = 4;
 
+  // The following functions should return the field type for each part of the
+  // phone number.  Currently, these are either fax or home phone number types.
+  virtual AutoFillFieldType GetNumberType() const = 0;
+  virtual AutoFillFieldType GetCityCodeType() const = 0;
+  virtual AutoFillFieldType GetCountryCodeType() const = 0;
+  virtual AutoFillFieldType GetCityAndNumberType() const = 0;
+  virtual AutoFillFieldType GetWholeNumberType() const = 0;
+
  protected:
   explicit PhoneNumber(const PhoneNumber& phone_number);
 
@@ -84,14 +92,6 @@
   bool IsCityAndNumber(const string16& text) const;
   bool IsWholeNumber(const string16& text) const;
 
-  // The following functions should return the field type for each part of the
-  // phone number.  Currently, these are either fax or home phone number types.
-  virtual AutoFillFieldType GetNumberType() const = 0;
-  virtual AutoFillFieldType GetCityCodeType() const = 0;
-  virtual AutoFillFieldType GetCountryCodeType() const = 0;
-  virtual AutoFillFieldType GetCityAndNumberType() const = 0;
-  virtual AutoFillFieldType GetWholeNumberType() const = 0;
-
   // Verifies that |number| is a valid phone number.
   bool Validate(const string16& number) const;
 
diff --git a/chrome/browser/autofill/select_control_handler.cc b/chrome/browser/autofill/select_control_handler.cc
index f7f2282..1d0526e 100644
--- a/chrome/browser/autofill/select_control_handler.cc
+++ b/chrome/browser/autofill/select_control_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -385,6 +385,11 @@
   "July", "August", "September", "October", "November", "December",
 };
 
+const char* const kMonthsNumeric[] = {
+  NULL,  // Padding so index 1 = month 1 = January.
+  "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
+};
+
 // Returns true if the value was successfully set, meaning |value| was found in
 // the list of select options in |field|.
 bool SetSelectControlValue(const string16& value,
@@ -467,7 +472,8 @@
 
   bool filled =
       SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) ||
-      SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field);
+      SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) ||
+      SetSelectControlValue(ASCIIToUTF16(kMonthsNumeric[index]), field);
   return filled;
 }
 
@@ -475,15 +481,14 @@
 
 namespace autofill {
 
-void FillSelectControl(const FormGroup* form_group,
+void FillSelectControl(const FormGroup& form_group,
                        AutoFillType type,
                        webkit_glue::FormField* field) {
-  DCHECK(form_group);
   DCHECK(field);
   DCHECK(field->form_control_type() == ASCIIToUTF16("select-one"));
 
   string16 value;
-  string16 field_text = form_group->GetFieldText(type);
+  string16 field_text = form_group.GetFieldText(type);
   for (size_t i = 0; i < field->option_strings().size(); ++i) {
     if (field_text == field->option_strings()[i]) {
       // An exact match, use it.
diff --git a/chrome/browser/autofill/select_control_handler.h b/chrome/browser/autofill/select_control_handler.h
index 723600a..c883e73 100644
--- a/chrome/browser/autofill/select_control_handler.h
+++ b/chrome/browser/autofill/select_control_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,13 +16,11 @@
 
 namespace autofill {
 
-// TODO(jhawkins): This definitely needs tests.
-
 // Fills a select-one control with the appropriate value from |form_group|.
 // Finds the matching value for field types that we know contain different
 // variations of a value, e.g., (tx, TX, Texas) or credit card expiration
 // months, e.g., (04, April).
-void FillSelectControl(const FormGroup* form_group,
+void FillSelectControl(const FormGroup& form_group,
                        AutoFillType type,
                        webkit_glue::FormField* field);
 
diff --git a/chrome/browser/autofill/select_control_handler_unittest.cc b/chrome/browser/autofill/select_control_handler_unittest.cc
new file mode 100644
index 0000000..1b40355
--- /dev/null
+++ b/chrome/browser/autofill/select_control_handler_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autofill/autofill_profile.h"
+#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/credit_card.h"
+#include "chrome/browser/autofill/select_control_handler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/form_field.h"
+
+TEST(SelectControlHandlerTest, CreditCardMonthExact) {
+  const char* const kMonthsNumeric[] = {
+    "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
+  };
+  std::vector<string16> options(arraysize(kMonthsNumeric));
+  for (size_t i = 0; i < arraysize(kMonthsNumeric); ++i)
+    options[i] = ASCIIToUTF16(kMonthsNumeric[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  CreditCard credit_card;
+  credit_card.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("01"));
+  autofill::FillSelectControl(credit_card,
+                              AutoFillType(CREDIT_CARD_EXP_MONTH),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("01"), field.value());
+}
+
+TEST(SelectControlHandlerTest, CreditCardMonthAbbreviated) {
+  const char* const kMonthsAbbreviated[] = {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+  };
+  std::vector<string16> options(arraysize(kMonthsAbbreviated));
+  for (size_t i = 0; i < arraysize(kMonthsAbbreviated); ++i)
+    options[i] = ASCIIToUTF16(kMonthsAbbreviated[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  CreditCard credit_card;
+  credit_card.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("01"));
+  autofill::FillSelectControl(credit_card,
+                              AutoFillType(CREDIT_CARD_EXP_MONTH),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("Jan"), field.value());
+}
+
+TEST(SelectControlHandlerTest, CreditCardMonthFull) {
+  const char* const kMonthsFull[] = {
+    "January", "February", "March", "April", "May", "June",
+    "July", "August", "September", "October", "November", "December",
+  };
+  std::vector<string16> options(arraysize(kMonthsFull));
+  for (size_t i = 0; i < arraysize(kMonthsFull); ++i)
+    options[i] = ASCIIToUTF16(kMonthsFull[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  CreditCard credit_card;
+  credit_card.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("01"));
+  autofill::FillSelectControl(credit_card,
+                              AutoFillType(CREDIT_CARD_EXP_MONTH),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("January"), field.value());
+}
+
+TEST(SelectControlHandlerTest, CreditCardMonthNumeric) {
+  const char* const kMonthsNumeric[] = {
+    "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
+  };
+  std::vector<string16> options(arraysize(kMonthsNumeric));
+  for (size_t i = 0; i < arraysize(kMonthsNumeric); ++i)
+    options[i] = ASCIIToUTF16(kMonthsNumeric[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  CreditCard credit_card;
+  credit_card.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("01"));
+  autofill::FillSelectControl(credit_card,
+                              AutoFillType(CREDIT_CARD_EXP_MONTH),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("1"), field.value());
+}
+
+TEST(SelectControlHandlerTest, AddressCountryFull) {
+  const char* const kCountries[] = {
+    "Albania", "Canada"
+  };
+  std::vector<string16> options(arraysize(kCountries));
+  for (size_t i = 0; i < arraysize(kCountries); ++i)
+    options[i] = ASCIIToUTF16(kCountries[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  AutoFillProfile profile;
+  profile.SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), ASCIIToUTF16("CA"));
+  autofill::FillSelectControl(profile,
+                              AutoFillType(ADDRESS_HOME_COUNTRY),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("Canada"), field.value());
+}
+
+TEST(SelectControlHandlerTest, AddressCountryAbbrev) {
+  const char* const kCountries[] = {
+    "AL", "CA"
+  };
+  std::vector<string16> options(arraysize(kCountries));
+  for (size_t i = 0; i < arraysize(kCountries); ++i)
+    options[i] = ASCIIToUTF16(kCountries[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  AutoFillProfile profile;
+  profile.SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), ASCIIToUTF16("Canada"));
+  autofill::FillSelectControl(profile,
+                              AutoFillType(ADDRESS_HOME_COUNTRY),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("CA"), field.value());
+}
+
+TEST(SelectControlHandlerTest, AddressStateFull) {
+  const char* const kStates[] = {
+    "Alabama", "California"
+  };
+  std::vector<string16> options(arraysize(kStates));
+  for (size_t i = 0; i < arraysize(kStates); ++i)
+    options[i] = ASCIIToUTF16(kStates[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  AutoFillProfile profile;
+  profile.SetInfo(AutoFillType(ADDRESS_HOME_STATE), ASCIIToUTF16("CA"));
+  autofill::FillSelectControl(profile,
+                              AutoFillType(ADDRESS_HOME_STATE),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("California"), field.value());
+}
+
+TEST(SelectControlHandlerTest, AddressStateAbbrev) {
+  const char* const kStates[] = {
+    "AL", "CA"
+  };
+  std::vector<string16> options(arraysize(kStates));
+  for (size_t i = 0; i < arraysize(kStates); ++i)
+    options[i] = ASCIIToUTF16(kStates[i]);
+
+  webkit_glue::FormField field;
+  field.set_form_control_type(ASCIIToUTF16("select-one"));
+  field.set_option_strings(options);
+
+  AutoFillProfile profile;
+  profile.SetInfo(AutoFillType(ADDRESS_HOME_STATE), ASCIIToUTF16("California"));
+  autofill::FillSelectControl(profile,
+                              AutoFillType(ADDRESS_HOME_STATE),
+                              &field);
+  EXPECT_EQ(ASCIIToUTF16("CA"), field.value());
+}
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 0c15995..255781b 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <set>
 
-#include "app/message_box_flags.h"
 #include "base/callback.h"
 #include "base/debug/trace_event.h"
 #include "base/file_path.h"
@@ -72,18 +71,18 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/ssl/ssl_manager.h"
 #include "chrome/browser/ssl/ssl_blocking_page.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/browser/ui/login/login_prompt.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/automation_constants.h"
 #include "chrome/common/automation_messages.h"
 #include "chrome/common/chrome_constants.h"
@@ -100,7 +99,6 @@
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/url_request/url_request_context.h"
 #include "chrome/browser/automation/ui_controls.h"
-#include "views/event.h"
 #include "webkit/glue/password_form.h"
 
 #if defined(OS_WIN)
@@ -116,6 +114,8 @@
       initial_loads_complete_(false) {
   TRACE_EVENT_BEGIN("AutomationProvider::AutomationProvider", 0, "");
 
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
   browser_tracker_.reset(new AutomationBrowserTracker(this));
   extension_tracker_.reset(new AutomationExtensionTracker(this));
   tab_tracker_.reset(new AutomationTabTracker(this));
@@ -137,15 +137,9 @@
                                        port_containers_.end());
   port_containers_.clear();
 
-  // Make sure that any outstanding NotificationObservers also get destroyed.
-  ObserverList<NotificationObserver>::Iterator it(notification_observer_list_);
-  NotificationObserver* observer;
-  while ((observer = it.GetNext()) != NULL)
-    delete observer;
-
-  if (channel_.get()) {
+  if (channel_.get())
     channel_->Close();
-  }
+
   g_browser_process->ReleaseModule();
 }
 
@@ -201,37 +195,6 @@
     Send(new AutomationMsg_InitialLoadsComplete());
 }
 
-NotificationObserver* AutomationProvider::AddNavigationStatusListener(
-    NavigationController* tab, IPC::Message* reply_message,
-    int number_of_navigations, bool include_current_navigation) {
-  NotificationObserver* observer =
-      new NavigationNotificationObserver(tab, this, reply_message,
-                                         number_of_navigations,
-                                         include_current_navigation);
-
-  notification_observer_list_.AddObserver(observer);
-  return observer;
-}
-
-void AutomationProvider::RemoveNavigationStatusListener(
-    NotificationObserver* obs) {
-  notification_observer_list_.RemoveObserver(obs);
-}
-
-NotificationObserver* AutomationProvider::AddTabStripObserver(
-    Browser* parent,
-    IPC::Message* reply_message) {
-  NotificationObserver* observer =
-      new TabAppendedNotificationObserver(parent, this, reply_message);
-  notification_observer_list_.AddObserver(observer);
-
-  return observer;
-}
-
-void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) {
-  notification_observer_list_.RemoveObserver(obs);
-}
-
 void AutomationProvider::AddLoginHandler(NavigationController* tab,
                                          LoginHandler* handler) {
   login_handler_map_[tab] = handler;
@@ -352,8 +315,7 @@
   LOG(INFO) << "Testing channel connected, sending hello message";
 
   // Send a hello message with our current automation protocol version.
-  chrome::VersionInfo version_info;
-  channel_->Send(new AutomationMsg_Hello(version_info.Version()));
+  channel_->Send(new AutomationMsg_Hello(GetProtocolVersion()));
   if (initial_loads_complete_)
     Send(new AutomationMsg_InitialLoadsComplete());
 }
@@ -403,6 +365,8 @@
                         GetExtensionProperty)
     IPC_MESSAGE_HANDLER(AutomationMsg_SaveAsAsync, SaveAsAsync)
     IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBrowsingData, RemoveBrowsingData)
+    IPC_MESSAGE_HANDLER(AutomationMsg_JavaScriptStressTestControl,
+                        JavaScriptStressTestControl)
 #if defined(OS_WIN)
     // These are for use with external tabs.
     IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab)
@@ -426,10 +390,6 @@
                                     OnRunUnloadHandlers)
     IPC_MESSAGE_HANDLER(AutomationMsg_SetZoomLevel, OnSetZoomLevel)
 #endif  // defined(OS_WIN)
-#if defined(OS_CHROMEOS)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoginWithUserAndPass,
-                                    LoginWithUserAndPass)
-#endif  // defined(OS_CHROMEOS)
     IPC_MESSAGE_UNHANDLED(handled = false;OnUnhandledMessage())
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -531,7 +491,11 @@
   if (!with_json) {
     find_in_page_observer_.reset(observer);
   }
-  tab_contents->set_current_find_request_id(request_id);
+  TabContentsWrapper* wrapper =
+      TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
+  if (wrapper)
+    wrapper->GetFindManager()->set_current_find_request_id(request_id);
+
   tab_contents->render_view_host()->StartFinding(
       FindInPageNotificationObserver::kFindInPageRequestId,
       search_string,
@@ -764,6 +728,18 @@
   // BrowsingDataRemover deletes itself.
 }
 
+void AutomationProvider::JavaScriptStressTestControl(int tab_handle,
+                                                     int cmd,
+                                                     int param) {
+  RenderViewHost* view = GetViewForTab(tab_handle);
+  if (!view) {
+    NOTREACHED();
+    return;
+  }
+
+  view->JavaScriptStressTestControl(cmd, param);
+}
+
 RenderViewHost* AutomationProvider::GetViewForTab(int tab_handle) {
   if (tab_tracker_->ContainsHandle(tab_handle)) {
     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
@@ -934,11 +910,11 @@
   if (extension && service && message_service && browser) {
     int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents());
     if (extension->page_action()) {
-      ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+      service->browser_event_router()->PageActionExecuted(
           browser->profile(), extension->id(), "action", tab_id, "", 1);
       success = true;
     } else if (extension->browser_action()) {
-      ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
+      service->browser_event_router()->BrowserActionExecuted(
           browser->profile(), extension->id(), browser);
       success = true;
     }
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index 4eb6f96..a9dbc9d 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -21,7 +21,9 @@
 #include "base/observer_list.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
+#include "base/weak_ptr.h"
 #include "chrome/browser/autofill/field_types.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/common/automation_constants.h"
@@ -29,9 +31,10 @@
 #include "chrome/common/notification_observer.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_channel.h"
+
 #if defined(OS_WIN)
-#include "gfx/native_widget_types.h"
-#include "views/event.h"
+#include "ui/gfx/native_widget_types.h"
+#include "views/events/event.h"
 #endif  // defined(OS_WIN)
 
 class PopupMenuWaiter;
@@ -75,9 +78,12 @@
 class Point;
 }
 
-class AutomationProvider : public base::RefCounted<AutomationProvider>,
-                           public IPC::Channel::Listener,
-                           public IPC::Message::Sender {
+class AutomationProvider
+    : public IPC::Channel::Listener,
+      public IPC::Message::Sender,
+      public base::SupportsWeakPtr<AutomationProvider>,
+      public base::RefCountedThreadSafe<AutomationProvider,
+                                        BrowserThread::DeleteOnUIThread> {
  public:
   explicit AutomationProvider(Profile* profile);
 
@@ -100,28 +106,6 @@
   // Call SetExpectedTabCount(0) to set this to true immediately.
   void OnInitialLoadsComplete();
 
-  // Add a listener for navigation status notification. Currently only
-  // navigation completion is observed; when the |number_of_navigations|
-  // complete, the completed_response object is sent; if the server requires
-  // authentication, we instead send the auth_needed_response object.  A pointer
-  // to the added navigation observer is returned. This object should NOT be
-  // deleted and should be released by calling the corresponding
-  // RemoveNavigationStatusListener method.
-  NotificationObserver* AddNavigationStatusListener(
-      NavigationController* tab, IPC::Message* reply_message,
-      int number_of_navigations, bool include_current_navigation);
-
-  void RemoveNavigationStatusListener(NotificationObserver* obs);
-
-  // Add an observer for the TabStrip. Currently only Tab append is observed. A
-  // navigation listener is created on successful notification of tab append. A
-  // pointer to the added navigation observer is returned. This object should
-  // NOT be deleted and should be released by calling the corresponding
-  // RemoveTabStripObserver method.
-  NotificationObserver* AddTabStripObserver(Browser* parent,
-                                            IPC::Message* reply_message);
-  void RemoveTabStripObserver(NotificationObserver* obs);
-
   // Get the index of a particular NavigationController object
   // in the given parent window.  This method uses
   // TabStrip::GetIndexForNavigationController to get the index.
@@ -172,7 +156,8 @@
   DictionaryValue* GetDictionaryFromDownloadItem(const DownloadItem* download);
 
  protected:
-  friend class base::RefCounted<AutomationProvider>;
+  friend class BrowserThread;
+  friend class DeleteTask<AutomationProvider>;
   virtual ~AutomationProvider();
 
   // Helper function to find the browser window that contains a given
@@ -200,9 +185,6 @@
   scoped_ptr<AutomationTabTracker> tab_tracker_;
   scoped_ptr<AutomationWindowTracker> window_tracker_;
 
-  typedef ObserverList<NotificationObserver> NotificationObserverList;
-  NotificationObserverList notification_observer_list_;
-
   typedef std::map<NavigationController*, LoginHandler*> LoginHandlerMap;
   LoginHandlerMap login_handler_map_;
 
@@ -254,6 +236,12 @@
   // See browsing_data_remover.h for explanation of bitmap fields.
   void RemoveBrowsingData(int remove_mask);
 
+  // Notify the JavaScript engine in the render to change its parameters
+  // while performing stress testing. See
+  // |ViewHostMsg_JavaScriptStressTestControl_Commands| in render_messages.h
+  // for information on the arguments.
+  void JavaScriptStressTestControl(int handle, int cmd, int param);
+
   void InstallExtension(const FilePath& crx_path,
                         IPC::Message* reply_message);
 
@@ -318,14 +306,6 @@
   void StopAsync(int tab_handle);
   void SaveAsAsync(int tab_handle);
 
-#if defined(OS_CHROMEOS)
-  // Logs in through the Chrome OS Login Wizard with given |username| and
-  // password.  Returns true via |reply_message| on success.
-  void LoginWithUserAndPass(const std::string& username,
-                            const std::string& password,
-                            IPC::Message* reply_message);
-#endif
-
   // Returns the extension for the given handle. Returns NULL if there is
   // no extension for the handle.
   const Extension* GetExtension(int extension_handle);
@@ -405,7 +385,6 @@
   scoped_ptr<NotificationObserver> new_tab_ui_load_observer_;
   scoped_ptr<NotificationObserver> find_in_page_observer_;
   scoped_ptr<NotificationObserver> dom_operation_observer_;
-  scoped_ptr<NotificationObserver> dom_inspector_observer_;
   scoped_ptr<ExtensionTestResultNotificationObserver>
       extension_test_result_observer_;
   scoped_ptr<AutomationExtensionTracker> extension_tracker_;
diff --git a/chrome/browser/automation/automation_provider_chromeos.cc b/chrome/browser/automation/automation_provider_chromeos.cc
deleted file mode 100644
index 6e1cc2b..0000000
--- a/chrome/browser/automation/automation_provider_chromeos.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/automation/automation_provider.h"
-
-#include "chrome/browser/automation/automation_provider_observers.h"
-#include "chrome/browser/chromeos/login/login_screen.h"
-#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "views/window/window_gtk.h"
-
-void AutomationProvider::LoginWithUserAndPass(const std::string& username,
-                                              const std::string& password,
-                                              IPC::Message* reply_message) {
-  WizardController* controller = WizardController::default_controller();
-  chromeos::NewUserView* new_user_view =
-        controller->GetLoginScreen()->view();
-
-  new_user_view->SetUsername(username);
-  new_user_view->SetPassword(password);
-
-  // Set up an observer (it will delete itself).
-  new LoginManagerObserver(this, reply_message);
-
-  new_user_view->Login();
-}
diff --git a/chrome/browser/automation/automation_provider_gtk.cc b/chrome/browser/automation/automation_provider_gtk.cc
index ca021cd..fcc8733 100644
--- a/chrome/browser/automation/automation_provider_gtk.cc
+++ b/chrome/browser/automation/automation_provider_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,16 +7,16 @@
 #include <gtk/gtk.h>
 
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/automation/ui_controls.h"
 #include "chrome/browser/automation/automation_browser_tracker.h"
 #include "chrome/browser/automation/automation_window_tracker.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/view_id_util.h"
+#include "chrome/browser/automation/ui_controls.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
 #include "chrome/common/automation_messages.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 
 void AutomationProvider::PrintAsync(int tab_handle) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/automation/automation_provider_mac.mm b/chrome/browser/automation/automation_provider_mac.mm
index f19bec2..d08b85e 100644
--- a/chrome/browser/automation/automation_provider_mac.mm
+++ b/chrome/browser/automation/automation_provider_mac.mm
@@ -6,18 +6,18 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/automation/automation_browser_tracker.h"
 #include "chrome/browser/automation/automation_window_tracker.h"
-#include "chrome/browser/ui/cocoa/tab_window_controller.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#include "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/common/automation_messages.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 
 void AutomationProvider::PrintAsync(int tab_handle) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 7703765..366530d 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,6 +16,7 @@
 #include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/automation/automation_provider.h"
@@ -50,14 +51,15 @@
 #include "chrome/browser/translate/page_translated_details.h"
 #include "chrome/browser/translate/translate_infobar_delegate.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/browser/ui/login/login_prompt.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/automation_constants.h"
+#include "chrome/common/automation_messages.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/rect.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/authentication_notification_details.h"
@@ -85,7 +87,7 @@
 
 InitialLoadObserver::InitialLoadObserver(size_t tab_count,
                                          AutomationProvider* automation)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       outstanding_tab_count_(tab_count),
       init_time_(base::TimeTicks::Now()) {
   if (outstanding_tab_count_ > 0) {
@@ -130,12 +132,12 @@
     DictionaryValue* item = new DictionaryValue;
     base::TimeDelta delta_start = it->second.start_time() - init_time_;
 
-    item->SetReal("load_start_ms", delta_start.InMillisecondsF());
+    item->SetDouble("load_start_ms", delta_start.InMillisecondsF());
     if (it->second.stop_time().is_null()) {
       item->Set("load_stop_ms", Value::CreateNullValue());
     } else {
       base::TimeDelta delta_stop = it->second.stop_time() - init_time_;
-      item->SetReal("load_stop_ms", delta_stop.InMillisecondsF());
+      item->SetDouble("load_stop_ms", delta_stop.InMillisecondsF());
     }
     items->Append(item);
   }
@@ -146,11 +148,12 @@
 
 void InitialLoadObserver::ConditionMet() {
   registrar_.RemoveAll();
-  automation_->OnInitialLoadsComplete();
+  if (automation_)
+    automation_->OnInitialLoadsComplete();
 }
 
 NewTabUILoadObserver::NewTabUILoadObserver(AutomationProvider* automation)
-    : automation_(automation) {
+    : automation_(automation->AsWeakPtr()) {
   registrar_.Add(this, NotificationType::INITIAL_NEW_TAB_UI_LOAD,
                  NotificationService::AllSources());
 }
@@ -163,8 +166,10 @@
                                    const NotificationDetails& details) {
   if (type == NotificationType::INITIAL_NEW_TAB_UI_LOAD) {
     Details<int> load_time(details);
-    automation_->Send(
-        new AutomationMsg_InitialNewTabUILoadComplete(*load_time.ptr()));
+    if (automation_) {
+      automation_->Send(
+          new AutomationMsg_InitialNewTabUILoadComplete(*load_time.ptr()));
+    }
   } else {
     NOTREACHED();
   }
@@ -174,7 +179,7 @@
     AutomationProvider* automation,
     NavigationController* controller,
     IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       controller_(controller),
       reply_message_(reply_message) {
   if (FinishedRestoring()) {
@@ -203,8 +208,12 @@
 }
 
 void NavigationControllerRestoredObserver::SendDone() {
-  DCHECK(reply_message_ != NULL);
-  automation_->Send(reply_message_);
+  if (!automation_)
+    return;
+
+  AutomationMsg_WaitForTabToBeRestored::WriteReplyParams(reply_message_.get(),
+                                                         true);
+  automation_->Send(reply_message_.release());
 }
 
 NavigationNotificationObserver::NavigationNotificationObserver(
@@ -213,11 +222,11 @@
     IPC::Message* reply_message,
     int number_of_navigations,
     bool include_current_navigation)
-  : automation_(automation),
-    reply_message_(reply_message),
-    controller_(controller),
-    navigations_remaining_(number_of_navigations),
-    navigation_started_(false) {
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message),
+      controller_(controller),
+      navigations_remaining_(number_of_navigations),
+      navigation_started_(false) {
   DCHECK_LT(0, navigations_remaining_);
   Source<NavigationController> source(controller_);
   registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, source);
@@ -232,22 +241,16 @@
 }
 
 NavigationNotificationObserver::~NavigationNotificationObserver() {
-  if (reply_message_) {
-    // This means we did not receive a notification for this navigation.
-    // Send over a failed navigation status back to the caller to ensure that
-    // the caller does not hang waiting for the response.
-    IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write(
-        reply_message_, AUTOMATION_MSG_NAVIGATION_ERROR);
-    automation_->Send(reply_message_);
-    reply_message_ = NULL;
-  }
-
-  automation_->RemoveNavigationStatusListener(this);
 }
 
 void NavigationNotificationObserver::Observe(
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   // We listen for 2 events to determine when the navigation started because:
   // - when this is used by the WaitForNavigation method, we might be invoked
   // afer the load has started (but not after the entry was committed, as
@@ -290,19 +293,18 @@
 
 void NavigationNotificationObserver::ConditionMet(
     AutomationMsg_NavigationResponseValues navigation_result) {
-  DCHECK(reply_message_ != NULL);
-
-  IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write(
-      reply_message_, navigation_result);
-  automation_->Send(reply_message_);
-  reply_message_ = NULL;
+  if (automation_) {
+    IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write(
+        reply_message_.get(), navigation_result);
+    automation_->Send(reply_message_.release());
+  }
 
   delete this;
 }
 
 TabStripNotificationObserver::TabStripNotificationObserver(
     NotificationType notification, AutomationProvider* automation)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       notification_(notification) {
   registrar_.Add(this, notification_, NotificationService::AllSources());
 }
@@ -315,9 +317,6 @@
                                            const NotificationDetails& details) {
   if (type == notification_) {
     ObserveTab(Source<NavigationController>(source).ptr());
-
-    // If verified, no need to observe anymore
-    automation_->RemoveTabStripObserver(this);
     delete this;
   } else {
     NOTREACHED();
@@ -332,16 +331,22 @@
       reply_message_(reply_message) {
 }
 
+TabAppendedNotificationObserver::~TabAppendedNotificationObserver() {}
+
 void TabAppendedNotificationObserver::ObserveTab(
     NavigationController* controller) {
+  if (!automation_)
+    return;
+
   if (automation_->GetIndexForNavigationController(controller, parent_) ==
       TabStripModel::kNoTab) {
     // This tab notification doesn't belong to the parent_.
     return;
   }
 
-  automation_->AddNavigationStatusListener(controller, reply_message_, 1,
-                                           false);
+  new NavigationNotificationObserver(controller, automation_,
+                                     reply_message_.release(),
+                                     1, false);
 }
 
 TabClosedNotificationObserver::TabClosedNotificationObserver(
@@ -354,15 +359,20 @@
       for_browser_command_(false) {
 }
 
+TabClosedNotificationObserver::~TabClosedNotificationObserver() {}
+
 void TabClosedNotificationObserver::ObserveTab(
     NavigationController* controller) {
+  if (!automation_)
+    return;
+
   if (for_browser_command_) {
-    AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
+    AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_.get(),
                                                          true);
   } else {
-    AutomationMsg_CloseTab::WriteReplyParams(reply_message_, true);
+    AutomationMsg_CloseTab::WriteReplyParams(reply_message_.get(), true);
   }
-  automation_->Send(reply_message_);
+  automation_->Send(reply_message_.release());
 }
 
 void TabClosedNotificationObserver::set_for_browser_command(
@@ -374,7 +384,7 @@
                                                Browser* browser,
                                                IPC::Message* reply_message,
                                                int target_tab_count)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message),
       tab_strip_model_(browser->tabstrip_model()),
       target_tab_count_(target_tab_count) {
@@ -398,9 +408,12 @@
 }
 
 void TabCountChangeObserver::TabStripModelDeleted() {
-  AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message_,
-                                                          false);
-  automation_->Send(reply_message_);
+  if (automation_) {
+    AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(
+        reply_message_.get(), false);
+    automation_->Send(reply_message_.release());
+  }
+
   delete this;
 }
 
@@ -408,9 +421,12 @@
   if (tab_strip_model_->count() != target_tab_count_)
     return;
 
-  AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message_,
-                                                          true);
-  automation_->Send(reply_message_);
+  if (automation_) {
+    AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(
+        reply_message_.get(), true);
+    automation_->Send(reply_message_.release());
+  }
+
   delete this;
 }
 
@@ -425,7 +441,7 @@
 
 ExtensionInstallNotificationObserver::ExtensionInstallNotificationObserver(
     AutomationProvider* automation, int id, IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       id_(id),
       reply_message_(reply_message) {
   registrar_.Add(this, NotificationType::EXTENSION_LOADED,
@@ -460,31 +476,33 @@
 
 void ExtensionInstallNotificationObserver::SendResponse(
     AutomationMsg_ExtensionResponseValues response) {
-  if (reply_message_ != NULL) {
-    switch (id_) {
-      case AutomationMsg_InstallExtension::ID:
-        AutomationMsg_InstallExtension::WriteReplyParams(reply_message_,
-                                                         response);
-        break;
-      case AutomationMsg_LoadExpandedExtension::ID:
-        AutomationMsg_LoadExpandedExtension::WriteReplyParams(reply_message_,
-                                                              response);
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
-
-    automation_->Send(reply_message_);
-    reply_message_ = NULL;
+  if (!automation_ || !reply_message_.get()) {
+    delete this;
+    return;
   }
+
+  switch (id_) {
+    case AutomationMsg_InstallExtension::ID:
+      AutomationMsg_InstallExtension::WriteReplyParams(reply_message_.get(),
+                                                       response);
+      break;
+    case AutomationMsg_LoadExpandedExtension::ID:
+      AutomationMsg_LoadExpandedExtension::WriteReplyParams(
+          reply_message_.get(), response);
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+
+  automation_->Send(reply_message_.release());
 }
 
 ExtensionReadyNotificationObserver::ExtensionReadyNotificationObserver(
     ExtensionProcessManager* manager, AutomationProvider* automation, int id,
     IPC::Message* reply_message)
     : manager_(manager),
-      automation_(automation),
+      automation_(automation->AsWeakPtr()),
       id_(id),
       reply_message_(reply_message),
       extension_(NULL) {
@@ -504,6 +522,11 @@
 void ExtensionReadyNotificationObserver::Observe(
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   bool success = false;
   switch (type.value) {
     case NotificationType::EXTENSION_HOST_DID_STOP_LOADING:
@@ -534,15 +557,15 @@
     if (extension_)
       extension_handle = automation_->AddExtension(extension_);
     AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams(
-        reply_message_, extension_handle);
+        reply_message_.get(), extension_handle);
   } else if (id_ == AutomationMsg_EnableExtension::ID) {
-    AutomationMsg_EnableExtension::WriteReplyParams(reply_message_, true);
+    AutomationMsg_EnableExtension::WriteReplyParams(reply_message_.get(), true);
   } else {
     NOTREACHED();
     LOG(ERROR) << "Cannot write reply params for unknown message id.";
   }
 
-  automation_->Send(reply_message_);
+  automation_->Send(reply_message_.release());
   delete this;
 }
 
@@ -567,7 +590,7 @@
 
 ExtensionTestResultNotificationObserver::
     ExtensionTestResultNotificationObserver(AutomationProvider* automation)
-    : automation_(automation) {
+        : automation_(automation->AsWeakPtr()) {
   registrar_.Add(this, NotificationType::EXTENSION_TEST_PASSED,
                  NotificationService::AllSources());
   registrar_.Add(this, NotificationType::EXTENSION_TEST_FAILED,
@@ -600,6 +623,9 @@
 }
 
 void ExtensionTestResultNotificationObserver::MaybeSendResult() {
+  if (!automation_)
+    return;
+
   if (results_.size() > 0) {
     // This release method should return the automation's current
     // reply message, or NULL if there is no current one. If it is not
@@ -618,7 +644,7 @@
 
 BrowserOpenedNotificationObserver::BrowserOpenedNotificationObserver(
     AutomationProvider* automation, IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message),
       for_browser_command_(false) {
   registrar_.Add(this, NotificationType::BROWSER_OPENED,
@@ -631,12 +657,17 @@
 void BrowserOpenedNotificationObserver::Observe(
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   if (type == NotificationType::BROWSER_OPENED) {
     if (for_browser_command_) {
-      AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
+      AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_.get(),
                                                            true);
     }
-    automation_->Send(reply_message_);
+    automation_->Send(reply_message_.release());
     delete this;
   } else {
     NOTREACHED();
@@ -652,28 +683,35 @@
     Browser* browser,
     AutomationProvider* automation,
     IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message),
       for_browser_command_(false) {
   registrar_.Add(this, NotificationType::BROWSER_CLOSED,
                  Source<Browser>(browser));
 }
 
+BrowserClosedNotificationObserver::~BrowserClosedNotificationObserver() {}
+
 void BrowserClosedNotificationObserver::Observe(
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
   DCHECK(type == NotificationType::BROWSER_CLOSED);
+
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   Details<bool> close_app(details);
-  DCHECK(reply_message_ != NULL);
+
   if (for_browser_command_) {
-    AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
+    AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_.get(),
                                                          true);
   } else {
-    AutomationMsg_CloseBrowser::WriteReplyParams(reply_message_, true,
+    AutomationMsg_CloseBrowser::WriteReplyParams(reply_message_.get(), true,
                                                  *(close_app.ptr()));
   }
-  automation_->Send(reply_message_);
-  reply_message_ = NULL;
+  automation_->Send(reply_message_.release());
   delete this;
 }
 
@@ -687,7 +725,7 @@
     AutomationProvider* automation,
     IPC::Message* reply_message)
     : target_count_(target_count),
-      automation_(automation),
+      automation_(automation->AsWeakPtr()),
       reply_message_(reply_message) {
   registrar_.Add(this, NotificationType::BROWSER_OPENED,
                  NotificationService::AllSources());
@@ -695,8 +733,12 @@
                  NotificationService::AllSources());
 }
 
+BrowserCountChangeNotificationObserver::
+~BrowserCountChangeNotificationObserver() {}
+
 void BrowserCountChangeNotificationObserver::Observe(
-    NotificationType type, const NotificationSource& source,
+    NotificationType type,
+    const NotificationSource& source,
     const NotificationDetails& details) {
   DCHECK(type == NotificationType::BROWSER_OPENED ||
          type == NotificationType::BROWSER_CLOSED);
@@ -707,18 +749,23 @@
     DCHECK_LT(0, current_count);
     current_count--;
   }
+
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   if (current_count == target_count_) {
     AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
-        reply_message_, true);
-    automation_->Send(reply_message_);
-    reply_message_ = NULL;
+        reply_message_.get(), true);
+    automation_->Send(reply_message_.release());
     delete this;
   }
 }
 
 AppModalDialogShownObserver::AppModalDialogShownObserver(
     AutomationProvider* automation, IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message) {
   registrar_.Add(this, NotificationType::APP_MODAL_DIALOG_SHOWN,
                  NotificationService::AllSources());
@@ -732,10 +779,11 @@
     const NotificationDetails& details) {
   DCHECK(type == NotificationType::APP_MODAL_DIALOG_SHOWN);
 
-  AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams(
-      reply_message_, true);
-  automation_->Send(reply_message_);
-  reply_message_ = NULL;
+  if (automation_) {
+    AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams(
+        reply_message_.get(), true);
+    automation_->Send(reply_message_.release());
+  }
   delete this;
 }
 
@@ -749,7 +797,6 @@
 
 const struct CommandNotification command_notifications[] = {
   {IDC_DUPLICATE_TAB, NotificationType::TAB_PARENTED},
-  {IDC_NEW_TAB, NotificationType::INITIAL_NEW_TAB_UI_LOAD},
 
   // Returns as soon as the restored tab is created. To further wait until
   // the content page is loaded, use WaitForTabToBeRestored.
@@ -775,6 +822,10 @@
     IPC::Message* reply_message) {
   bool result = true;
   switch (command) {
+    case IDC_NEW_TAB: {
+      new NewTabObserver(automation, reply_message);
+      break;
+    }
     case IDC_NEW_WINDOW:
     case IDC_NEW_INCOGNITO_WINDOW: {
       BrowserOpenedNotificationObserver* observer =
@@ -798,9 +849,9 @@
     case IDC_BACK:
     case IDC_FORWARD:
     case IDC_RELOAD: {
-      automation->AddNavigationStatusListener(
+      new NavigationNotificationObserver(
           &browser->GetSelectedTabContents()->controller(),
-          reply_message, 1, false);
+          automation, reply_message, 1, false);
       break;
     }
     default: {
@@ -820,9 +871,11 @@
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
   if (type == notification_type_) {
-    AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
-                                                         true);
-    automation_->Send(reply_message_);
+    if (automation_) {
+      AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_.get(),
+                                                           true);
+      automation_->Send(reply_message_.release());
+    }
     delete this;
   } else {
     NOTREACHED();
@@ -831,7 +884,7 @@
 
 ExecuteBrowserCommandObserver::ExecuteBrowserCommandObserver(
     AutomationProvider* automation, IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       notification_type_(NotificationType::ALL),
       reply_message_(reply_message) {
 }
@@ -861,7 +914,7 @@
 FindInPageNotificationObserver::FindInPageNotificationObserver(
     AutomationProvider* automation, TabContents* parent_tab,
     bool reply_with_json, IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       active_match_ordinal_(-1),
       reply_with_json_(reply_with_json),
       reply_message_(reply_message) {
@@ -880,6 +933,12 @@
     DVLOG(1) << "Ignoring, since we only care about the final message";
     return;
   }
+
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   // We get multiple responses and one of those will contain the ordinal.
   // This message comes to us before the final update is sent.
   if (find_details->request_id() == kFindInPageRequestId) {
@@ -897,16 +956,15 @@
         return_value->SetInteger("match_right", rect.right());
         return_value->SetInteger("match_bottom", rect.bottom());
       }
-      AutomationJSONReply(automation_, reply_message_)
+      AutomationJSONReply(automation_, reply_message_.release())
           .SendSuccess(return_value.get());
       delete this;
     } else {
       if (find_details->active_match_ordinal() > -1) {
         active_match_ordinal_ = find_details->active_match_ordinal();
-        AutomationMsg_Find::WriteReplyParams(reply_message_,
+        AutomationMsg_Find::WriteReplyParams(reply_message_.get(),
             active_match_ordinal_, find_details->number_of_matches());
-        automation_->Send(reply_message_);
-        reply_message_ = NULL;
+        automation_->Send(reply_message_.release());
       }
     }
   }
@@ -920,6 +978,8 @@
                  NotificationService::AllSources());
 }
 
+DomOperationObserver::~DomOperationObserver() {}
+
 void DomOperationObserver::Observe(
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
@@ -929,8 +989,18 @@
   }
 }
 
+DomOperationMessageSender::DomOperationMessageSender(
+    AutomationProvider* automation)
+    : automation_(automation->AsWeakPtr()) {
+}
+
+DomOperationMessageSender::~DomOperationMessageSender() {}
+
 void DomOperationMessageSender::OnDomOperationCompleted(
     const std::string& json) {
+  if (!automation_)
+    return;
+
   IPC::Message* reply_message = automation_->reply_message_release();
   if (reply_message) {
     AutomationMsg_DomOperation::WriteReplyParams(reply_message, json);
@@ -942,7 +1012,7 @@
 
 DocumentPrintedNotificationObserver::DocumentPrintedNotificationObserver(
     AutomationProvider* automation, IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       success_(false),
       reply_message_(reply_message) {
   registrar_.Add(this, NotificationType::PRINT_JOB_EVENT,
@@ -950,10 +1020,10 @@
 }
 
 DocumentPrintedNotificationObserver::~DocumentPrintedNotificationObserver() {
-  DCHECK(reply_message_ != NULL);
-  AutomationMsg_PrintNow::WriteReplyParams(reply_message_, success_);
-  automation_->Send(reply_message_);
-  automation_->RemoveNavigationStatusListener(this);
+  if (automation_) {
+    AutomationMsg_PrintNow::WriteReplyParams(reply_message_.get(), success_);
+    automation_->Send(reply_message_.release());
+  }
 }
 
 void DocumentPrintedNotificationObserver::Observe(
@@ -1021,7 +1091,7 @@
 PageTranslatedObserver::PageTranslatedObserver(AutomationProvider* automation,
                                                IPC::Message* reply_message,
                                                TabContents* tab_contents)
-  : automation_(automation),
+  : automation_(automation->AsWeakPtr()),
     reply_message_(reply_message) {
   registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
                  Source<TabContents>(tab_contents));
@@ -1032,8 +1102,13 @@
 void PageTranslatedObserver::Observe(NotificationType type,
                                      const NotificationSource& source,
                                      const NotificationDetails& details) {
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   DCHECK(type == NotificationType::PAGE_TRANSLATED);
-  AutomationJSONReply reply(automation_, reply_message_);
+  AutomationJSONReply reply(automation_, reply_message_.release());
 
   PageTranslatedDetails* translated_details =
       Details<PageTranslatedDetails>(details).ptr();
@@ -1048,19 +1123,26 @@
 TabLanguageDeterminedObserver::TabLanguageDeterminedObserver(
     AutomationProvider* automation, IPC::Message* reply_message,
     TabContents* tab_contents, TranslateInfoBarDelegate* translate_bar)
-  : automation_(automation),
-    reply_message_(reply_message),
-    tab_contents_(tab_contents),
-    translate_bar_(translate_bar) {
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message),
+      tab_contents_(tab_contents),
+      translate_bar_(translate_bar) {
   registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED,
                  Source<TabContents>(tab_contents));
 }
 
+TabLanguageDeterminedObserver::~TabLanguageDeterminedObserver() {}
+
 void TabLanguageDeterminedObserver::Observe(
     NotificationType type, const NotificationSource& source,
     const NotificationDetails& details) {
   DCHECK(type == NotificationType::TAB_LANGUAGE_DETERMINED);
 
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
   return_value->SetBoolean("page_translated",
                            tab_contents_->language_state().IsPageTranslated());
@@ -1095,7 +1177,7 @@
                         translate_bar_->GetOriginalLanguageCode());
     return_value->Set("translate_bar", bar_info);
   }
-  AutomationJSONReply(automation_, reply_message_)
+  AutomationJSONReply(automation_, reply_message_.release())
       .SendSuccess(return_value.get());
   delete this;
 }
@@ -1103,8 +1185,8 @@
 InfoBarCountObserver::InfoBarCountObserver(AutomationProvider* automation,
                                            IPC::Message* reply_message,
                                            TabContents* tab_contents,
-                                           int target_count)
-    : automation_(automation),
+                                           size_t target_count)
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message),
       tab_contents_(tab_contents),
       target_count_(target_count) {
@@ -1114,6 +1196,8 @@
   CheckCount();
 }
 
+InfoBarCountObserver::~InfoBarCountObserver() {}
+
 void InfoBarCountObserver::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
@@ -1123,11 +1207,14 @@
 }
 
 void InfoBarCountObserver::CheckCount() {
-  if (tab_contents_->infobar_delegate_count() != target_count_)
+  if (tab_contents_->infobar_count() != target_count_)
     return;
 
-  AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, true);
-  automation_->Send(reply_message_);
+  if (automation_) {
+    AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_.get(),
+                                                        true);
+    automation_->Send(reply_message_.release());
+  }
   delete this;
 }
 
@@ -1135,21 +1222,54 @@
 LoginManagerObserver::LoginManagerObserver(
     AutomationProvider* automation,
     IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message) {
 
-  registrar_.Add(this, NotificationType::LOGIN_AUTHENTICATION,
+  registrar_.Add(this, NotificationType::LOGIN_USER_CHANGED,
                  NotificationService::AllSources());
 }
 
 void LoginManagerObserver::Observe(NotificationType type,
                                    const NotificationSource& source,
                                    const NotificationDetails& details) {
-  DCHECK(type == NotificationType::LOGIN_AUTHENTICATION);
+  DCHECK(type == NotificationType::LOGIN_USER_CHANGED);
+
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
+  AutomationJSONReply reply(automation_, reply_message_.release());
   Details<AuthenticationNotificationDetails> auth_details(details);
-  AutomationMsg_LoginWithUserAndPass::WriteReplyParams(reply_message_,
-      auth_details->success());
-  automation_->Send(reply_message_);
+  if (auth_details->success())
+    reply.SendSuccess(NULL);
+  else
+    reply.SendError("Login failure.");
+  delete this;
+}
+
+ScreenLockUnlockObserver::ScreenLockUnlockObserver(
+    AutomationProvider* automation,
+    IPC::Message* reply_message,
+    bool lock_screen)
+    : automation_(automation),
+      reply_message_(reply_message),
+      lock_screen_(lock_screen) {
+
+  registrar_.Add(this, NotificationType::SCREEN_LOCK_STATE_CHANGED,
+                 NotificationService::AllSources());
+}
+
+void ScreenLockUnlockObserver::Observe(NotificationType type,
+                                       const NotificationSource& source,
+                                       const NotificationDetails& details) {
+  DCHECK(type == NotificationType::SCREEN_LOCK_STATE_CHANGED);
+  AutomationJSONReply reply(automation_, reply_message_);
+  bool is_screen_locked = *Details<bool>(details).ptr();
+  if (lock_screen_ == is_screen_locked)
+    reply.SendSuccess(NULL);
+  else
+    reply.SendError("Screen lock failure.");
   delete this;
 }
 #endif
@@ -1158,10 +1278,10 @@
 AutomationProviderBookmarkModelObserver(
     AutomationProvider* provider,
     IPC::Message* reply_message,
-    BookmarkModel* model) {
-  automation_provider_ = provider;
-  reply_message_ = reply_message;
-  model_ = model;
+    BookmarkModel* model)
+    : automation_provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message),
+      model_(model) {
   model_->AddObserver(this);
 }
 
@@ -1180,21 +1300,59 @@
 }
 
 void AutomationProviderBookmarkModelObserver::ReplyAndDelete(bool success) {
-  AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
-      reply_message_, success);
-  automation_provider_->Send(reply_message_);
+  if (automation_provider_) {
+    AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
+        reply_message_.get(), success);
+    automation_provider_->Send(reply_message_.release());
+  }
   delete this;
 }
 
+AutomationProviderDownloadItemObserver::AutomationProviderDownloadItemObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message,
+    int downloads)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message),
+      downloads_(downloads) {
+}
+
+AutomationProviderDownloadItemObserver::
+~AutomationProviderDownloadItemObserver() {}
+
+void AutomationProviderDownloadItemObserver::OnDownloadUpdated(
+    DownloadItem* download) {
+}
+
 void AutomationProviderDownloadItemObserver::OnDownloadFileCompleted(
     DownloadItem* download) {
   download->RemoveObserver(this);
   if (--downloads_ == 0) {
-    AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
+    if (provider_) {
+      AutomationJSONReply(provider_,
+                          reply_message_.release()).SendSuccess(NULL);
+    }
     delete this;
   }
 }
 
+void AutomationProviderDownloadItemObserver::OnDownloadOpened(
+    DownloadItem* download) {
+}
+
+AutomationProviderDownloadUpdatedObserver::
+AutomationProviderDownloadUpdatedObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message,
+    bool wait_for_open)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message),
+      wait_for_open_(wait_for_open) {
+}
+
+AutomationProviderDownloadUpdatedObserver::
+~AutomationProviderDownloadUpdatedObserver() {}
+
 void AutomationProviderDownloadUpdatedObserver::OnDownloadUpdated(
     DownloadItem* download) {
   // If this observer is watching for open, only send the reply if the download
@@ -1205,8 +1363,11 @@
   download->RemoveObserver(this);
   scoped_ptr<DictionaryValue> return_value(
       provider_->GetDictionaryFromDownloadItem(download));
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(
-      return_value.get());
+
+  if (provider_) {
+    AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(
+        return_value.get());
+  }
   delete this;
 }
 
@@ -1215,27 +1376,75 @@
   download->RemoveObserver(this);
   scoped_ptr<DictionaryValue> return_value(
       provider_->GetDictionaryFromDownloadItem(download));
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(
-      return_value.get());
+
+  if (provider_) {
+    AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(
+        return_value.get());
+  }
   delete this;
 }
 
+void AutomationProviderDownloadUpdatedObserver::OnDownloadFileCompleted(
+    DownloadItem* download) {
+}
+
+AutomationProviderDownloadModelChangedObserver::
+AutomationProviderDownloadModelChangedObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message,
+    DownloadManager* download_manager)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message),
+      download_manager_(download_manager) {
+}
+
+AutomationProviderDownloadModelChangedObserver::
+~AutomationProviderDownloadModelChangedObserver() {}
+
 void AutomationProviderDownloadModelChangedObserver::ModelChanged() {
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
   download_manager_->RemoveObserver(this);
+
+  if (provider_)
+    AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(NULL);
   delete this;
 }
 
+AutomationProviderSearchEngineObserver::AutomationProviderSearchEngineObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message) {
+}
+
+AutomationProviderSearchEngineObserver::
+~AutomationProviderSearchEngineObserver() {}
+
 void AutomationProviderSearchEngineObserver::OnTemplateURLModelChanged() {
   TemplateURLModel* url_model = provider_->profile()->GetTemplateURLModel();
   url_model->RemoveObserver(this);
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
+
+  if (provider_)
+    AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(NULL);
   delete this;
 }
 
+AutomationProviderHistoryObserver::AutomationProviderHistoryObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message) {
+}
+
+AutomationProviderHistoryObserver::~AutomationProviderHistoryObserver() {}
+
 void AutomationProviderHistoryObserver::HistoryQueryComplete(
     HistoryService::Handle request_handle,
     history::QueryResults* results) {
+  if (!provider_) {
+    delete this;
+    return;
+  }
+
   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
 
   ListValue* history_list = new ListValue;
@@ -1244,8 +1453,8 @@
     history::URLResult const &page = (*results)[i];
     page_value->SetString("title", page.title());
     page_value->SetString("url", page.url().spec());
-    page_value->SetReal("time",
-                        static_cast<double>(page.visit_time().ToDoubleT()));
+    page_value->SetDouble("time",
+                          static_cast<double>(page.visit_time().ToDoubleT()));
     page_value->SetString("snippet", page.snippet().text());
     page_value->SetBoolean(
         "starred",
@@ -1255,19 +1464,56 @@
 
   return_value->Set("history", history_list);
   // Return history info.
-  AutomationJSONReply reply(provider_, reply_message_);
+  AutomationJSONReply reply(provider_, reply_message_.release());
   reply.SendSuccess(return_value.get());
   delete this;
 }
 
+AutomationProviderImportSettingsObserver::
+AutomationProviderImportSettingsObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message) {
+}
+
+AutomationProviderImportSettingsObserver::
+~AutomationProviderImportSettingsObserver() {}
+
+void AutomationProviderImportSettingsObserver::ImportStarted() {
+}
+
+void AutomationProviderImportSettingsObserver::ImportItemStarted(
+    importer::ImportItem item) {
+}
+
+void AutomationProviderImportSettingsObserver::ImportItemEnded(
+    importer::ImportItem item) {
+}
+
 void AutomationProviderImportSettingsObserver::ImportEnded() {
-  // Send back an empty success message.
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
+  if (provider_)
+    AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(NULL);
   delete this;
 }
 
+AutomationProviderGetPasswordsObserver::AutomationProviderGetPasswordsObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message) {
+}
+
+AutomationProviderGetPasswordsObserver::
+~AutomationProviderGetPasswordsObserver() {}
+
 void AutomationProviderGetPasswordsObserver::OnPasswordStoreRequestDone(
     int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
+  if (!provider_) {
+    delete this;
+    return;
+  }
+
   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
 
   ListValue* passwords = new ListValue;
@@ -1278,7 +1524,7 @@
     password_val->SetString("username_value", password_form->username_value);
     password_val->SetString("password_value", password_form->password_value);
     password_val->SetString("signon_realm", password_form->signon_realm);
-    password_val->SetReal(
+    password_val->SetDouble(
         "time", static_cast<double>(password_form->date_created.ToDoubleT()));
     password_val->SetString("origin_url", password_form->origin.spec());
     password_val->SetString("username_element",
@@ -1293,14 +1539,24 @@
   }
 
   return_value->Set("passwords", passwords);
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(
+  AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(
       return_value.get());
   delete this;
 }
 
+AutomationProviderBrowsingDataObserver::AutomationProviderBrowsingDataObserver(
+    AutomationProvider* provider,
+    IPC::Message* reply_message)
+    : provider_(provider->AsWeakPtr()),
+      reply_message_(reply_message) {
+}
+
+AutomationProviderBrowsingDataObserver::
+~AutomationProviderBrowsingDataObserver() {}
+
 void AutomationProviderBrowsingDataObserver::OnBrowsingDataRemoverDone() {
-  // Send back an empty success message
-  AutomationJSONReply(provider_, reply_message_).SendSuccess(NULL);
+  if (provider_)
+    AutomationJSONReply(provider_, reply_message_.release()).SendSuccess(NULL);
   delete this;
 }
 
@@ -1308,9 +1564,9 @@
     NavigationController* controller,
     AutomationProvider* automation,
     IPC::Message* reply_message)
-  : automation_(automation),
-    reply_message_(reply_message),
-    controller_(controller) {
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message),
+      controller_(controller) {
   Source<NavigationController> source(controller_);
   registrar_.Add(this, NotificationType::LOAD_STOP, source);
   // Pages requiring auth don't send LOAD_STOP.
@@ -1318,7 +1574,6 @@
 }
 
 OmniboxAcceptNotificationObserver::~OmniboxAcceptNotificationObserver() {
-  automation_->RemoveNavigationStatusListener(this);
 }
 
 void OmniboxAcceptNotificationObserver::Observe(
@@ -1327,7 +1582,10 @@
     const NotificationDetails& details) {
   if (type == NotificationType::LOAD_STOP ||
       type == NotificationType::AUTH_NEEDED) {
-    AutomationJSONReply(automation_, reply_message_).SendSuccess(NULL);
+    if (automation_) {
+      AutomationJSONReply(automation_,
+                          reply_message_.release()).SendSuccess(NULL);
+    }
     delete this;
   } else {
     NOTREACHED();
@@ -1337,19 +1595,25 @@
 SavePackageNotificationObserver::SavePackageNotificationObserver(
     SavePackage* save_package,
     AutomationProvider* automation,
-    IPC::Message* reply_message) : automation_(automation),
-                                   reply_message_(reply_message) {
+    IPC::Message* reply_message)
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message) {
   Source<SavePackage> source(save_package);
   registrar_.Add(this, NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
                  source);
 }
 
+SavePackageNotificationObserver::~SavePackageNotificationObserver() {}
+
 void SavePackageNotificationObserver::Observe(
     NotificationType type,
     const NotificationSource& source,
     const NotificationDetails& details) {
   if (type == NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED) {
-    AutomationJSONReply(automation_, reply_message_).SendSuccess(NULL);
+    if (automation_) {
+      AutomationJSONReply(automation_,
+                          reply_message_.release()).SendSuccess(NULL);
+    }
     delete this;
   } else {
     NOTREACHED();
@@ -1360,12 +1624,14 @@
                                      IPC::Message* reply_message,
                                      RenderViewHost* render_view,
                                      const FilePath& path)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message),
       render_view_(render_view),
       image_path_(path),
       received_width_(false) {}
 
+PageSnapshotTaker::~PageSnapshotTaker() {}
+
 void PageSnapshotTaker::Start() {
   ExecuteScript(L"window.domAutomationController.send(document.width);");
 }
@@ -1390,7 +1656,8 @@
     // Don't actually start the thumbnail generator, this leads to crashes on
     // Mac, crbug.com/62986. Instead, just hook the generator to the
     // RenderViewHost manually.
-    render_view_->set_painting_observer(generator);
+
+    generator->MonitorRenderer(render_view_, true);
     generator->AskForSnapshot(render_view_, false, callback,
                               entire_page_size_, entire_page_size_);
   }
@@ -1412,14 +1679,18 @@
       L"window.domAutomationController.setAutomationId(%d);",
       reply_message_->routing_id());
 
-  render_view_->ExecuteJavascriptInWebFrame(L"", set_automation_id);
-  render_view_->ExecuteJavascriptInWebFrame(L"", javascript);
+  render_view_->ExecuteJavascriptInWebFrame(string16(),
+                                            WideToUTF16Hack(set_automation_id));
+  render_view_->ExecuteJavascriptInWebFrame(string16(),
+                                            WideToUTF16Hack(javascript));
 }
 
 void PageSnapshotTaker::SendMessage(bool success) {
-  AutomationMsg_CaptureEntirePageAsPNG::WriteReplyParams(reply_message_,
-                                                         success);
-  automation_->Send(reply_message_);
+  if (automation_) {
+    AutomationMsg_CaptureEntirePageAsPNG::WriteReplyParams(reply_message_.get(),
+                                                           success);
+    automation_->Send(reply_message_.release());
+  }
   delete this;
 }
 
@@ -1427,20 +1698,20 @@
     AutomationProvider* automation,
     IPC::Message* reply_message,
     CancelableRequestConsumer* consumer)
-        : automation_(automation),
-          reply_message_(reply_message),
-          consumer_(consumer),
-          request_(NULL),
-          ntp_info_(new DictionaryValue) {
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message),
+      consumer_(consumer),
+      request_(0),
+      ntp_info_(new DictionaryValue) {
   top_sites_ = automation_->profile()->GetTopSites();
   if (!top_sites_) {
-    AutomationJSONReply(automation_, reply_message_)
+    AutomationJSONReply(automation_, reply_message_.release())
         .SendError("Profile does not have service for querying the top sites.");
     return;
   }
   TabRestoreService* service = automation_->profile()->GetTabRestoreService();
   if (!service) {
-    AutomationJSONReply(automation_, reply_message_)
+    AutomationJSONReply(automation_, reply_message_.release())
         .SendError("No TabRestoreService.");
     return;
   }
@@ -1493,6 +1764,11 @@
 
 void NTPInfoObserver::OnTopSitesReceived(
     const history::MostVisitedURLList& visited_list) {
+  if (!automation_) {
+    delete this;
+    return;
+  }
+
   ListValue* list_value = new ListValue;
   for (size_t i = 0; i < visited_list.size(); ++i) {
     const history::MostVisitedURL& visited = visited_list[i];
@@ -1505,7 +1781,8 @@
     list_value->Append(dict);
   }
   ntp_info_->Set("most_visited", list_value);
-  AutomationJSONReply(automation_, reply_message_).SendSuccess(ntp_info_.get());
+  AutomationJSONReply(automation_,
+                      reply_message_.release()).SendSuccess(ntp_info_.get());
   delete this;
 }
 
@@ -1513,21 +1790,25 @@
     AutomationProvider* automation,
     AutocompleteEditModel* autocomplete_edit,
     IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message),
       autocomplete_edit_model_(autocomplete_edit) {
   Source<AutocompleteEditModel> source(autocomplete_edit);
   registrar_.Add(this, NotificationType::AUTOCOMPLETE_EDIT_FOCUSED, source);
 }
 
+AutocompleteEditFocusedObserver::~AutocompleteEditFocusedObserver() {}
+
 void AutocompleteEditFocusedObserver::Observe(
     NotificationType type,
     const NotificationSource& source,
     const NotificationDetails& details) {
   DCHECK(type == NotificationType::AUTOCOMPLETE_EDIT_FOCUSED);
-  AutomationMsg_WaitForAutocompleteEditFocus::WriteReplyParams(
-      reply_message_, true);
-  automation_->Send(reply_message_);
+  if (automation_) {
+    AutomationMsg_WaitForAutocompleteEditFocus::WriteReplyParams(
+        reply_message_.get(), true);
+    automation_->Send(reply_message_.release());
+  }
   delete this;
 }
 
@@ -1568,6 +1849,8 @@
   }
 }
 
+GetActiveNotificationsObserver::~GetActiveNotificationsObserver() {}
+
 void GetActiveNotificationsObserver::Observe(
     NotificationType type,
     const NotificationSource& source,
@@ -1623,16 +1906,117 @@
 RendererProcessClosedObserver::RendererProcessClosedObserver(
     AutomationProvider* automation,
     IPC::Message* reply_message)
-    : automation_(automation),
+    : automation_(automation->AsWeakPtr()),
       reply_message_(reply_message) {
   registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSED,
                  NotificationService::AllSources());
 }
 
+RendererProcessClosedObserver::~RendererProcessClosedObserver() {}
+
 void RendererProcessClosedObserver::Observe(
     NotificationType type,
     const NotificationSource& source,
     const NotificationDetails& details) {
-  AutomationJSONReply(automation_, reply_message_).SendSuccess(NULL);
+  if (automation_) {
+    AutomationJSONReply(automation_,
+                        reply_message_.release()).SendSuccess(NULL);
+  }
   delete this;
 }
+
+InputEventAckNotificationObserver::InputEventAckNotificationObserver(
+    AutomationProvider* automation,
+    IPC::Message* reply_message,
+    int event_type)
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message),
+      event_type_(event_type) {
+  registrar_.Add(
+      this, NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
+      NotificationService::AllSources());
+}
+
+InputEventAckNotificationObserver::~InputEventAckNotificationObserver() {}
+
+void InputEventAckNotificationObserver::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  Details<int> request_details(details);
+  if (event_type_ == *request_details.ptr()) {
+    if (automation_) {
+      AutomationJSONReply(automation_,
+                          reply_message_.release()).SendSuccess(NULL);
+    }
+    delete this;
+  } else {
+    LOG(WARNING) << "Ignoring unexpected event types.";
+  }
+}
+
+NewTabObserver::NewTabObserver(AutomationProvider* automation,
+                               IPC::Message* reply_message)
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message) {
+  // Use TAB_PARENTED to detect the new tab.
+  registrar_.Add(this,
+                 NotificationType::TAB_PARENTED,
+                 NotificationService::AllSources());
+}
+
+void NewTabObserver::Observe(NotificationType type,
+                             const NotificationSource& source,
+                             const NotificationDetails& details) {
+  DCHECK_EQ(NotificationType::TAB_PARENTED, type.value);
+  NavigationController* controller = Source<NavigationController>(source).ptr();
+  if (automation_) {
+    // TODO(phajdan.jr): Clean up this hack. We write the correct return type
+    // here, but don't send the message. NavigationNotificationObserver
+    // will wait properly for the load to finish, and send the message,
+    // but it will also append its own return value at the end of the reply.
+    AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_.get(),
+                                                         true);
+    new NavigationNotificationObserver(controller, automation_,
+                                       reply_message_.release(),
+                                       1, false);
+  }
+  delete this;
+}
+
+NewTabObserver::~NewTabObserver() {
+}
+
+WaitForProcessLauncherThreadToGoIdleObserver::
+WaitForProcessLauncherThreadToGoIdleObserver(
+    AutomationProvider* automation, IPC::Message* reply_message)
+    : automation_(automation->AsWeakPtr()),
+      reply_message_(reply_message) {
+  // Balanced in RunOnUIThread.
+  AddRef();
+  BrowserThread::PostTask(
+      BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &WaitForProcessLauncherThreadToGoIdleObserver::
+              RunOnProcessLauncherThread));
+}
+
+WaitForProcessLauncherThreadToGoIdleObserver::
+~WaitForProcessLauncherThreadToGoIdleObserver() {
+}
+
+void WaitForProcessLauncherThreadToGoIdleObserver::
+RunOnProcessLauncherThread() {
+  BrowserThread::PostTask(
+      BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &WaitForProcessLauncherThreadToGoIdleObserver::RunOnUIThread));
+}
+
+void WaitForProcessLauncherThreadToGoIdleObserver::RunOnUIThread() {
+  if (automation_)
+    automation_->Send(reply_message_.release());
+  Release();
+}
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index 8868863..0ffc85f 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 #include <set>
 
 #include "base/scoped_ptr.h"
+#include "base/weak_ptr.h"
 #include "chrome/browser/automation/automation_provider_json.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
 #include "chrome/browser/browsing_data_remover.h"
@@ -24,10 +25,11 @@
 #include "chrome/browser/password_manager/password_store.h"
 #include "chrome/browser/search_engines/template_url_model_observer.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/common/automation_messages.h"
+#include "chrome/common/automation_constants.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_type.h"
+#include "ui/gfx/size.h"
 
 class AutocompleteEditModel;
 class AutomationProvider;
@@ -52,7 +54,7 @@
 class InitialLoadObserver : public NotificationObserver {
  public:
   InitialLoadObserver(size_t tab_count, AutomationProvider* automation);
-  ~InitialLoadObserver();
+  virtual ~InitialLoadObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -76,7 +78,7 @@
 
   NotificationRegistrar registrar_;
 
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   size_t outstanding_tab_count_;
   base::TimeTicks init_time_;
   TabTimeMap loading_tabs_;
@@ -89,7 +91,7 @@
 class NewTabUILoadObserver : public NotificationObserver {
  public:
   explicit NewTabUILoadObserver(AutomationProvider* automation);
-  ~NewTabUILoadObserver();
+  virtual ~NewTabUILoadObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -97,7 +99,7 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
 
   DISALLOW_COPY_AND_ASSIGN(NewTabUILoadObserver);
 };
@@ -107,7 +109,7 @@
   NavigationControllerRestoredObserver(AutomationProvider* automation,
                                        NavigationController* controller,
                                        IPC::Message* reply_message);
-  ~NavigationControllerRestoredObserver();
+  virtual ~NavigationControllerRestoredObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -118,9 +120,9 @@
   void SendDone();
 
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   NavigationController* controller_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(NavigationControllerRestoredObserver);
 };
@@ -132,7 +134,7 @@
                                  IPC::Message* reply_message,
                                  int number_of_navigations,
                                  bool include_current_navigation);
-  ~NavigationNotificationObserver();
+  virtual ~NavigationNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -142,8 +144,8 @@
   void ConditionMet(AutomationMsg_NavigationResponseValues navigation_result);
 
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   NavigationController* controller_;
   int navigations_remaining_;
   bool navigation_started_;
@@ -165,7 +167,7 @@
 
  protected:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   NotificationType notification_;
 };
 
@@ -174,12 +176,13 @@
   TabAppendedNotificationObserver(Browser* parent,
                                   AutomationProvider* automation,
                                   IPC::Message* reply_message);
+  virtual ~TabAppendedNotificationObserver();
 
   virtual void ObserveTab(NavigationController* controller);
 
  protected:
   Browser* parent_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TabAppendedNotificationObserver);
@@ -190,13 +193,14 @@
   TabClosedNotificationObserver(AutomationProvider* automation,
                                 bool wait_until_closed,
                                 IPC::Message* reply_message);
+  virtual ~TabClosedNotificationObserver();
 
   virtual void ObserveTab(NavigationController* controller);
 
   void set_for_browser_command(bool for_browser_command);
 
  protected:
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
   bool for_browser_command_;
 
  private:
@@ -218,14 +222,14 @@
   virtual void TabStripModelDeleted();
 
  private:
-  ~TabCountChangeObserver();
+  virtual ~TabCountChangeObserver();
 
   // Checks if the current tab count matches our target, and if so,
   // sends the reply message and deletes self.
   void CheckTabCount();
 
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   TabStripModel* tab_strip_model_;
 
@@ -241,7 +245,7 @@
   ExtensionInstallNotificationObserver(AutomationProvider* automation,
                                        int id,
                                        IPC::Message* reply_message);
-  ~ExtensionInstallNotificationObserver();
+  virtual ~ExtensionInstallNotificationObserver();
 
   // Implementation of NotificationObserver.
   virtual void Observe(NotificationType type,
@@ -253,9 +257,9 @@
   void SendResponse(AutomationMsg_ExtensionResponseValues response);
 
   NotificationRegistrar registrar_;
-  scoped_refptr<AutomationProvider> automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   int id_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionInstallNotificationObserver);
 };
@@ -268,7 +272,7 @@
                                      AutomationProvider* automation,
                                      int id,
                                      IPC::Message* reply_message);
-  ~ExtensionReadyNotificationObserver();
+  virtual ~ExtensionReadyNotificationObserver();
 
   // Implementation of NotificationObserver.
   virtual void Observe(NotificationType type,
@@ -278,9 +282,9 @@
  private:
   NotificationRegistrar registrar_;
   ExtensionProcessManager* manager_;
-  scoped_refptr<AutomationProvider> automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   int id_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
   const Extension* extension_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionReadyNotificationObserver);
@@ -289,7 +293,7 @@
 class ExtensionUnloadNotificationObserver : public NotificationObserver {
  public:
   ExtensionUnloadNotificationObserver();
-  ~ExtensionUnloadNotificationObserver();
+  virtual ~ExtensionUnloadNotificationObserver();
 
   // Implementation of NotificationObserver.
   virtual void Observe(NotificationType type,
@@ -311,7 +315,7 @@
  public:
   explicit ExtensionTestResultNotificationObserver(
       AutomationProvider* automation);
-  ~ExtensionTestResultNotificationObserver();
+  virtual ~ExtensionTestResultNotificationObserver();
 
   // Implementation of NotificationObserver.
   virtual void Observe(NotificationType type,
@@ -324,7 +328,7 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   // Two queues containing the test results. Although typically only
   // one result will be in each queue, there are cases where a queue is
   // needed.
@@ -342,7 +346,7 @@
  public:
   BrowserOpenedNotificationObserver(AutomationProvider* automation,
                                     IPC::Message* reply_message);
-  ~BrowserOpenedNotificationObserver();
+  virtual ~BrowserOpenedNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -352,8 +356,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   bool for_browser_command_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserOpenedNotificationObserver);
@@ -364,6 +368,7 @@
   BrowserClosedNotificationObserver(Browser* browser,
                                     AutomationProvider* automation,
                                     IPC::Message* reply_message);
+  virtual ~BrowserClosedNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -373,8 +378,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   bool for_browser_command_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserClosedNotificationObserver);
@@ -385,6 +390,7 @@
   BrowserCountChangeNotificationObserver(int target_count,
                                          AutomationProvider* automation,
                                          IPC::Message* reply_message);
+  virtual ~BrowserCountChangeNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -393,8 +399,8 @@
  private:
   int target_count_;
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserCountChangeNotificationObserver);
 };
@@ -403,7 +409,7 @@
  public:
   AppModalDialogShownObserver(AutomationProvider* automation,
                               IPC::Message* reply_message);
-  ~AppModalDialogShownObserver();
+  virtual ~AppModalDialogShownObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -411,15 +417,15 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(AppModalDialogShownObserver);
 };
 
 class ExecuteBrowserCommandObserver : public NotificationObserver {
  public:
-  ~ExecuteBrowserCommandObserver();
+  virtual ~ExecuteBrowserCommandObserver();
 
   static bool CreateAndRegisterObserver(AutomationProvider* automation,
                                         Browser* browser,
@@ -439,9 +445,9 @@
   bool GetNotificationType(int command, NotificationType::Type* type);
 
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   NotificationType::Type notification_type_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(ExecuteBrowserCommandObserver);
 };
@@ -452,7 +458,7 @@
                                  TabContents* parent_tab,
                                  bool reply_with_json,
                                  IPC::Message* reply_message);
-  ~FindInPageNotificationObserver();
+  virtual ~FindInPageNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -469,13 +475,13 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   // We will at some point (before final update) be notified of the ordinal and
   // we need to preserve it so we can send it later.
   int active_match_ordinal_;
   // Send reply using json automation interface.
   bool reply_with_json_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(FindInPageNotificationObserver);
 };
@@ -483,7 +489,7 @@
 class DomOperationObserver : public NotificationObserver {
  public:
   DomOperationObserver();
-  virtual ~DomOperationObserver() {}
+  virtual ~DomOperationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -499,13 +505,13 @@
 
 class DomOperationMessageSender : public DomOperationObserver {
  public:
-  explicit DomOperationMessageSender(AutomationProvider* automation)
-      : automation_(automation) {}
+  explicit DomOperationMessageSender(AutomationProvider* automation);
+  virtual ~DomOperationMessageSender();
 
   virtual void OnDomOperationCompleted(const std::string& json);
 
  private:
-  AutomationProvider* automation_;
+  base::WeakPtr<AutomationProvider> automation_;
 
   DISALLOW_COPY_AND_ASSIGN(DomOperationMessageSender);
 };
@@ -514,16 +520,16 @@
  public:
   DocumentPrintedNotificationObserver(AutomationProvider* automation,
                                       IPC::Message* reply_message);
-  ~DocumentPrintedNotificationObserver();
+  virtual ~DocumentPrintedNotificationObserver();
 
   virtual void Observe(NotificationType type, const NotificationSource& source,
                        const NotificationDetails& details);
 
  private:
   NotificationRegistrar registrar_;
-  scoped_refptr<AutomationProvider> automation_;
+  base::WeakPtr<AutomationProvider> automation_;
   bool success_;
-  IPC::Message* reply_message_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(DocumentPrintedNotificationObserver);
 };
@@ -564,8 +570,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  scoped_refptr<AutomationProvider> automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(PageTranslatedObserver);
 };
@@ -576,6 +582,7 @@
                                 IPC::Message* reply_message,
                                 TabContents* tab_contents,
                                 TranslateInfoBarDelegate* translate_bar);
+  virtual ~TabLanguageDeterminedObserver();
 
   // NotificationObserver interface.
   virtual void Observe(NotificationType type,
@@ -584,8 +591,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   TabContents* tab_contents_;
   TranslateInfoBarDelegate* translate_bar_;
 
@@ -597,7 +604,8 @@
   InfoBarCountObserver(AutomationProvider* automation,
                        IPC::Message* reply_message,
                        TabContents* tab_contents,
-                       int target_count);
+                       size_t target_count);
+  virtual ~InfoBarCountObserver();
 
   // NotificationObserver interface.
   virtual void Observe(NotificationType type,
@@ -610,17 +618,17 @@
   void CheckCount();
 
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   TabContents* tab_contents_;
 
-  const int target_count_;
+  const size_t target_count_;
 
   DISALLOW_COPY_AND_ASSIGN(InfoBarCountObserver);
 };
 
 #if defined(OS_CHROMEOS)
-// Collects LOGIN_AUTHENTICATION notifications and returns
+// Collects LOGIN_USER_CHANGED notifications and returns
 // whether authentication succeeded to the automation provider.
 class LoginManagerObserver : public NotificationObserver {
  public:
@@ -633,11 +641,34 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(LoginManagerObserver);
 };
+
+// Collects SCREEN_LOCK_STATE_CHANGED notifications and returns
+// whether authentication succeeded to the automation provider.
+class ScreenLockUnlockObserver : public NotificationObserver {
+ public:
+  // Set lock_screen to true to observe lock screen events,
+  // false for unlock screen events.
+  ScreenLockUnlockObserver(AutomationProvider* automation,
+                           IPC::Message* reply_message,
+                           bool lock_screen);
+
+  // NotificationObserver interface.
+  virtual void Observe(NotificationType type, const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  NotificationRegistrar registrar_;
+  AutomationProvider* automation_;
+  IPC::Message* reply_message_;
+  bool lock_screen_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScreenLockUnlockObserver);
+};
 #endif
 
 // Waits for the bookmark model to load.
@@ -675,8 +706,8 @@
   // observer list).
   void ReplyAndDelete(bool success);
 
-  scoped_refptr<AutomationProvider> automation_provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_provider_;
+  scoped_ptr<IPC::Message> reply_message_;
   BookmarkModel* model_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationProviderBookmarkModelObserver);
@@ -688,20 +719,16 @@
   AutomationProviderDownloadItemObserver(
       AutomationProvider* provider,
       IPC::Message* reply_message,
-      int downloads) {
-    provider_ = provider;
-    reply_message_ = reply_message;
-    downloads_ = downloads;
-  }
-  virtual ~AutomationProviderDownloadItemObserver() {}
+      int downloads);
+  virtual ~AutomationProviderDownloadItemObserver();
 
-  virtual void OnDownloadUpdated(DownloadItem* download) { }
+  virtual void OnDownloadUpdated(DownloadItem* download);
   virtual void OnDownloadFileCompleted(DownloadItem* download);
-  virtual void OnDownloadOpened(DownloadItem* download) { }
+  virtual void OnDownloadOpened(DownloadItem* download);
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
   int downloads_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationProviderDownloadItemObserver);
@@ -715,18 +742,16 @@
   AutomationProviderDownloadUpdatedObserver(
       AutomationProvider* provider,
       IPC::Message* reply_message,
-      bool wait_for_open)
-    : provider_(provider),
-      reply_message_(reply_message),
-      wait_for_open_(wait_for_open) {}
+      bool wait_for_open);
+  virtual ~AutomationProviderDownloadUpdatedObserver();
 
   virtual void OnDownloadUpdated(DownloadItem* download);
   virtual void OnDownloadOpened(DownloadItem* download);
-  virtual void OnDownloadFileCompleted(DownloadItem* download) { }
+  virtual void OnDownloadFileCompleted(DownloadItem* download);
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
   bool wait_for_open_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationProviderDownloadUpdatedObserver);
@@ -740,16 +765,14 @@
   AutomationProviderDownloadModelChangedObserver(
       AutomationProvider* provider,
       IPC::Message* reply_message,
-      DownloadManager* download_manager)
-    : provider_(provider),
-      reply_message_(reply_message),
-      download_manager_(download_manager) {}
+      DownloadManager* download_manager);
+  virtual ~AutomationProviderDownloadModelChangedObserver();
 
   virtual void ModelChanged();
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
   DownloadManager* download_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationProviderDownloadModelChangedObserver);
@@ -762,15 +785,14 @@
  public:
   AutomationProviderSearchEngineObserver(
       AutomationProvider* provider,
-      IPC::Message* reply_message)
-    : provider_(provider),
-      reply_message_(reply_message) {}
+      IPC::Message* reply_message);
+  virtual ~AutomationProviderSearchEngineObserver();
 
   virtual void OnTemplateURLModelChanged();
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationProviderSearchEngineObserver);
 };
@@ -780,17 +802,15 @@
  public:
   AutomationProviderHistoryObserver(
       AutomationProvider* provider,
-      IPC::Message* reply_message) {
-    provider_ = provider;
-    reply_message_ = reply_message;
-  }
-  ~AutomationProviderHistoryObserver() {}
+      IPC::Message* reply_message);
+  virtual ~AutomationProviderHistoryObserver();
+
   void HistoryQueryComplete(HistoryService::Handle request_handle,
                             history::QueryResults* results);
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
 };
 
 // Allows the automation provider to wait for import queries to finish.
@@ -799,16 +819,16 @@
  public:
   AutomationProviderImportSettingsObserver(
       AutomationProvider* provider,
-      IPC::Message* reply_message)
-    : provider_(provider),
-      reply_message_(reply_message) {}
-  virtual void ImportStarted() {}
-  virtual void ImportItemStarted(importer::ImportItem item) {}
-  virtual void ImportItemEnded(importer::ImportItem item) {}
+      IPC::Message* reply_message);
+  virtual ~AutomationProviderImportSettingsObserver();
+
+  virtual void ImportStarted();
+  virtual void ImportItemStarted(importer::ImportItem item);
+  virtual void ImportItemEnded(importer::ImportItem item);
   virtual void ImportEnded();
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
 };
 
 // Allows automation provider to wait for getting passwords to finish.
@@ -817,16 +837,15 @@
  public:
   AutomationProviderGetPasswordsObserver(
       AutomationProvider* provider,
-      IPC::Message* reply_message)
-    : provider_(provider),
-      reply_message_(reply_message) {}
+      IPC::Message* reply_message);
+  virtual ~AutomationProviderGetPasswordsObserver();
 
   virtual void OnPasswordStoreRequestDone(
       int handle, const std::vector<webkit_glue::PasswordForm*>& result);
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
 };
 
 // Allows the automation provider to wait for clearing browser data to finish.
@@ -835,14 +854,14 @@
  public:
   AutomationProviderBrowsingDataObserver(
       AutomationProvider* provider,
-      IPC::Message* reply_message)
-    : provider_(provider),
-      reply_message_(reply_message) {}
+      IPC::Message* reply_message);
+  virtual ~AutomationProviderBrowsingDataObserver();
+
   virtual void OnBrowsingDataRemoverDone();
 
  private:
-  AutomationProvider* provider_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> provider_;
+  scoped_ptr<IPC::Message> reply_message_;
 };
 
 // Allows automation provider to wait until page load after selecting an item
@@ -852,7 +871,7 @@
   OmniboxAcceptNotificationObserver(NavigationController* controller,
                                  AutomationProvider* automation,
                                  IPC::Message* reply_message);
-  ~OmniboxAcceptNotificationObserver();
+  virtual ~OmniboxAcceptNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -860,8 +879,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   NavigationController* controller_;
 
   DISALLOW_COPY_AND_ASSIGN(OmniboxAcceptNotificationObserver);
@@ -873,7 +892,7 @@
   SavePackageNotificationObserver(SavePackage* save_package,
                                   AutomationProvider* automation,
                                   IPC::Message* reply_message);
-  virtual ~SavePackageNotificationObserver() {}
+  virtual ~SavePackageNotificationObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -881,8 +900,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(SavePackageNotificationObserver);
 };
@@ -895,6 +914,7 @@
                     IPC::Message* reply_message,
                     RenderViewHost* render_view,
                     const FilePath& path);
+  virtual ~PageSnapshotTaker();
 
   // Start the process of taking a snapshot of the entire page.
   void Start();
@@ -913,8 +933,8 @@
   // Helper method to send a response back to the client. Deletes this.
   void SendMessage(bool success);
 
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   RenderViewHost* render_view_;
   FilePath image_path_;
   bool received_width_;
@@ -938,8 +958,8 @@
   void OnTopSitesLoaded();
   void OnTopSitesReceived(const history::MostVisitedURLList& visited_list);
 
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   CancelableRequestConsumer* consumer_;
   CancelableRequestProvider::Handle request_;
   scoped_ptr<DictionaryValue> ntp_info_;
@@ -956,6 +976,7 @@
   AutocompleteEditFocusedObserver(AutomationProvider* automation,
                                   AutocompleteEditModel* autocomplete_edit,
                                   IPC::Message* reply_message);
+  virtual ~AutocompleteEditFocusedObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -963,8 +984,8 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
   AutocompleteEditModel* autocomplete_edit_model_;
 
   DISALLOW_COPY_AND_ASSIGN(AutocompleteEditFocusedObserver);
@@ -976,6 +997,7 @@
  public:
   GetActiveNotificationsObserver(AutomationProvider* automation,
                                  IPC::Message* reply_message);
+  virtual ~GetActiveNotificationsObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -1015,6 +1037,7 @@
  public:
   RendererProcessClosedObserver(AutomationProvider* automation,
                                 IPC::Message* reply_message);
+  virtual ~RendererProcessClosedObserver();
 
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -1022,11 +1045,76 @@
 
  private:
   NotificationRegistrar registrar_;
-  AutomationProvider* automation_;
-  IPC::Message* reply_message_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
 
   DISALLOW_COPY_AND_ASSIGN(RendererProcessClosedObserver);
 };
 
+// Allows the automation provider to wait for acknowledgement that a input
+// event has been handled.
+class InputEventAckNotificationObserver : public NotificationObserver {
+ public:
+  InputEventAckNotificationObserver(AutomationProvider* automation,
+                                    IPC::Message* reply_message,
+                                    int event_type);
+  virtual ~InputEventAckNotificationObserver();
+
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  NotificationRegistrar registrar_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
+  int event_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputEventAckNotificationObserver);
+};
+
+// Observer used to listen for new tab creation to complete.
+class NewTabObserver : public NotificationObserver {
+ public:
+  NewTabObserver(AutomationProvider* automation, IPC::Message* reply_message);
+
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) OVERRIDE;
+
+ private:
+  virtual ~NewTabObserver();
+
+  NotificationRegistrar registrar_;
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(NewTabObserver);
+};
+
+// Posts a task to the PROCESS_LAUNCHER thread, once processed posts a task
+// back to the UI thread that notifies the provider we're done.
+class WaitForProcessLauncherThreadToGoIdleObserver
+    : public base::RefCountedThreadSafe<
+          WaitForProcessLauncherThreadToGoIdleObserver,
+          BrowserThread::DeleteOnUIThread> {
+ public:
+  WaitForProcessLauncherThreadToGoIdleObserver(
+      AutomationProvider* automation, IPC::Message* reply_message);
+
+ private:
+  friend class BrowserThread;
+  friend class DeleteTask<WaitForProcessLauncherThreadToGoIdleObserver>;
+
+  virtual ~WaitForProcessLauncherThreadToGoIdleObserver();
+
+  void RunOnProcessLauncherThread();
+  void RunOnUIThread();
+
+  base::WeakPtr<AutomationProvider> automation_;
+  scoped_ptr<IPC::Message> reply_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaitForProcessLauncherThreadToGoIdleObserver);
+};
 
 #endif  // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_
diff --git a/chrome/browser/automation/automation_provider_unittest.cc b/chrome/browser/automation/automation_provider_unittest.cc
index 356d0f4..c931701 100644
--- a/chrome/browser/automation/automation_provider_unittest.cc
+++ b/chrome/browser/automation/automation_provider_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/automation/chrome_frame_automation_provider.h"
 #include "ipc/ipc_message.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -20,6 +21,9 @@
 };
 
 TEST(AutomationProviderTest, TestInvalidChromeFrameMessage) {
+  MessageLoop message_loop;
+  BrowserThread ui_thread(BrowserThread::UI, &message_loop);
+
   IPC::Message bad_msg(1, -1, IPC::Message::PRIORITY_NORMAL);
 
   scoped_refptr<MockChromeFrameAutomationProvider>
diff --git a/chrome/browser/automation/automation_provider_win.cc b/chrome/browser/automation/automation_provider_win.cc
index 0ad5400..e0f76c9 100644
--- a/chrome/browser/automation/automation_provider_win.cc
+++ b/chrome/browser/automation/automation_provider_win.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/automation/automation_provider.h"
 
-#include "app/keyboard_codes.h"
 #include "base/debug/trace_event.h"
 #include "base/json/json_reader.h"
 #include "base/utf_string_conversions.h"
@@ -21,9 +20,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 #include "chrome/common/automation_messages.h"
 #include "chrome/common/page_zoom.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "views/focus/accelerator_handler.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_win.h"
@@ -79,7 +79,7 @@
 class MouseEventTask : public Task {
  public:
   MouseEventTask(views::View* view,
-                 views::Event::EventType type,
+                 ui::EventType type,
                  const gfx::Point& point,
                  int flags)
       : view_(view), type_(type), point_(point), flags_(flags) {}
@@ -97,15 +97,15 @@
     view_->ConvertPointToScreen(view_, &screen_location);
     MoveMouse(screen_location.ToPOINT());
     switch (type_) {
-      case views::Event::ET_MOUSE_PRESSED:
+      case ui::ET_MOUSE_PRESSED:
         view_->OnMousePressed(event);
         break;
 
-      case views::Event::ET_MOUSE_DRAGGED:
+      case ui::ET_MOUSE_DRAGGED:
         view_->OnMouseDragged(event);
         break;
 
-      case views::Event::ET_MOUSE_RELEASED:
+      case ui::ET_MOUSE_RELEASED:
         view_->OnMouseReleased(event, false);
         break;
 
@@ -116,7 +116,7 @@
 
  private:
   views::View* view_;
-  views::Event::EventType type_;
+  ui::EventType type_;
   gfx::Point point_;
   int flags_;
 
@@ -159,21 +159,21 @@
     UINT down_message = 0;
     UINT up_message = 0;
     WPARAM wparam_flags = 0;
-    if (flags & views::Event::EF_SHIFT_DOWN)
+    if (flags & ui::EF_SHIFT_DOWN)
       wparam_flags |= MK_SHIFT;
-    if (flags & views::Event::EF_CONTROL_DOWN)
+    if (flags & ui::EF_CONTROL_DOWN)
       wparam_flags |= MK_CONTROL;
-    if (flags & views::Event::EF_LEFT_BUTTON_DOWN) {
+    if (flags & ui::EF_LEFT_BUTTON_DOWN) {
       wparam_flags |= MK_LBUTTON;
       down_message = WM_LBUTTONDOWN;
       up_message = WM_LBUTTONUP;
     }
-    if (flags & views::Event::EF_MIDDLE_BUTTON_DOWN) {
+    if (flags & ui::EF_MIDDLE_BUTTON_DOWN) {
       wparam_flags |= MK_MBUTTON;
       down_message = WM_MBUTTONDOWN;
       up_message = WM_MBUTTONUP;
     }
-    if (flags & views::Event::EF_RIGHT_BUTTON_DOWN) {
+    if (flags & ui::EF_RIGHT_BUTTON_DOWN) {
       wparam_flags |= MK_RBUTTON;
       down_message = WM_LBUTTONDOWN;
       up_message = WM_LBUTTONUP;
@@ -203,12 +203,12 @@
       // Press Escape, making sure we wait until chrome processes the escape.
       // TODO(phajdan.jr): make this use ui_test_utils::SendKeyPressSync.
       ui_controls::SendKeyPressNotifyWhenDone(
-          window, app::VKEY_ESCAPE,
-          ((flags & views::Event::EF_CONTROL_DOWN) ==
-           views::Event::EF_CONTROL_DOWN),
-          ((flags & views::Event::EF_SHIFT_DOWN) ==
-           views::Event::EF_SHIFT_DOWN),
-          ((flags & views::Event::EF_ALT_DOWN) == views::Event::EF_ALT_DOWN),
+          window, ui::VKEY_ESCAPE,
+          ((flags & ui::EF_CONTROL_DOWN) ==
+           ui::EF_CONTROL_DOWN),
+          ((flags & ui::EF_SHIFT_DOWN) ==
+           ui::EF_SHIFT_DOWN),
+          ((flags & ui::EF_ALT_DOWN) == ui::EF_ALT_DOWN),
           false,
           new MessageLoop::QuitTask());
       MessageLoopForUI* loop = MessageLoopForUI::current();
diff --git a/chrome/browser/automation/automation_resource_message_filter.cc b/chrome/browser/automation/automation_resource_message_filter.cc
index 5fce672..8fc76a6 100644
--- a/chrome/browser/automation/automation_resource_message_filter.cc
+++ b/chrome/browser/automation/automation_resource_message_filter.cc
@@ -403,7 +403,7 @@
   int automation_request_id = 0;
   bool valid_id = GetAutomationRequestId(request_id, &automation_request_id);
   if (!valid_id) {
-    NOTREACHED() << "Invalid request id: " << request_id;
+    LOG(ERROR) << "Invalid request id: " << request_id;
     return false;
   }
 
diff --git a/chrome/browser/automation/automation_resource_message_filter.h b/chrome/browser/automation/automation_resource_message_filter.h
index 89357e6..d1a192d 100644
--- a/chrome/browser/automation/automation_resource_message_filter.h
+++ b/chrome/browser/automation/automation_resource_message_filter.h
@@ -10,7 +10,6 @@
 
 #include "base/atomicops.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "ipc/ipc_channel_proxy.h"
 #include "net/base/completion_callback.h"
 #include "net/base/cookie_store.h"
diff --git a/chrome/browser/automation/automation_window_tracker.h b/chrome/browser/automation/automation_window_tracker.h
index 7483f1d..f8dfea1 100644
--- a/chrome/browser/automation/automation_window_tracker.h
+++ b/chrome/browser/automation/automation_window_tracker.h
@@ -8,7 +8,7 @@
 
 #include "build/build_config.h"
 #include "chrome/browser/automation/automation_resource_tracker.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class AutomationWindowTracker
     : public AutomationResourceTracker<gfx::NativeWindow> {
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index d25c07c..6e718cb 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -1,10 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/automation/testing_automation_provider.h"
 
-#include "app/message_box_flags.h"
+#include <map>
+#include <string>
+#include <vector>
+
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -75,7 +78,9 @@
 #include "chrome/common/automation_messages.h"
 #include "net/base/cookie_store.h"
 #include "net/url_request/url_request_context.h"
-#include "views/event.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "ui/base/events.h"
+#include "ui/base/message_box_flags.h"
 #include "webkit/plugins/npapi/plugin_list.h"
 
 namespace {
@@ -110,14 +115,14 @@
 
 void SendMouseClick(int flags) {
   ui_controls::MouseButton button = ui_controls::LEFT;
-  if ((flags & views::Event::EF_LEFT_BUTTON_DOWN) ==
-      views::Event::EF_LEFT_BUTTON_DOWN) {
+  if ((flags & ui::EF_LEFT_BUTTON_DOWN) ==
+      ui::EF_LEFT_BUTTON_DOWN) {
     button = ui_controls::LEFT;
-  } else if ((flags & views::Event::EF_RIGHT_BUTTON_DOWN) ==
-             views::Event::EF_RIGHT_BUTTON_DOWN) {
+  } else if ((flags & ui::EF_RIGHT_BUTTON_DOWN) ==
+             ui::EF_RIGHT_BUTTON_DOWN) {
     button = ui_controls::RIGHT;
-  } else if ((flags & views::Event::EF_MIDDLE_BUTTON_DOWN) ==
-             views::Event::EF_MIDDLE_BUTTON_DOWN) {
+  } else if ((flags & ui::EF_MIDDLE_BUTTON_DOWN) ==
+             ui::EF_MIDDLE_BUTTON_DOWN) {
     button = ui_controls::MIDDLE;
   } else {
     NOTREACHED();
@@ -161,16 +166,16 @@
 }
 
 void TestingAutomationProvider::SourceProfilesLoaded() {
-  DCHECK_NE(static_cast<ImporterHost*>(NULL), importer_host_.get());
+  DCHECK_NE(static_cast<ImporterList*>(NULL), importer_list_.get());
 
   // Get the correct ProfileInfo based on the browser the user provided.
   importer::ProfileInfo profile_info;
-  int num_browsers = importer_host_->GetAvailableProfileCount();
+  int num_browsers = importer_list_->GetAvailableProfileCount();
   int i = 0;
   for ( ; i < num_browsers; i++) {
-    string16 name = WideToUTF16Hack(importer_host_->GetSourceProfileNameAt(i));
+    string16 name = WideToUTF16Hack(importer_list_->GetSourceProfileNameAt(i));
     if (name == import_settings_data_.browser_name) {
-      profile_info = importer_host_->GetSourceProfileInfoAt(i);
+      profile_info = importer_list_->GetSourceProfileInfoAt(i);
       break;
     }
   }
@@ -181,16 +186,17 @@
     return;
   }
 
-  importer_host_->SetObserver(
+  scoped_refptr<ImporterHost> importer_host(new ImporterHost);
+  importer_host->SetObserver(
       new AutomationProviderImportSettingsObserver(
           this, import_settings_data_.reply_message));
 
   Profile* profile = import_settings_data_.browser->profile();
-  importer_host_->StartImportSettings(profile_info,
-                                      profile,
-                                      import_settings_data_.import_items,
-                                      new ProfileWriter(profile),
-                                      import_settings_data_.first_run);
+  importer_host->StartImportSettings(profile_info,
+                                     profile,
+                                     import_settings_data_.import_items,
+                                     new ProfileWriter(profile),
+                                     import_settings_data_.first_run);
 }
 
 void TestingAutomationProvider::Observe(NotificationType type,
@@ -389,6 +395,9 @@
     IPC_MESSAGE_HANDLER(AutomationMsg_SetContentSetting, SetContentSetting)
     IPC_MESSAGE_HANDLER(AutomationMsg_LoadBlockedPlugins, LoadBlockedPlugins)
     IPC_MESSAGE_HANDLER(AutomationMsg_ResetToDefaultTheme, ResetToDefaultTheme)
+    IPC_MESSAGE_HANDLER_DELAY_REPLY(
+        AutomationMsg_WaitForProcessLauncherThreadToGoIdle,
+        WaitForProcessLauncherThreadToGoIdle)
 
     IPC_MESSAGE_UNHANDLED(
         handled = AutomationProvider::OnMessageReceived(message))
@@ -441,7 +450,8 @@
 
   if (browser_tracker_->ContainsHandle(handle)) {
     Browser* browser = browser_tracker_->GetResource(handle);
-    observer = AddTabStripObserver(browser, reply_message);
+    observer = new TabAppendedNotificationObserver(browser, this,
+                                                   reply_message);
     TabContentsWrapper* contents =
         browser->AddSelectedTabWithURL(url, PageTransition::TYPED);
     if (contents) {
@@ -451,11 +461,10 @@
   }
 
   if (append_tab_response < 0) {
-    // The append tab failed. Remove the TabStripObserver
-    if (observer) {
-      RemoveTabStripObserver(observer);
+    // Appending tab failed. Clean up and send failure response.
+
+    if (observer)
       delete observer;
-    }
 
     AutomationMsg_AppendTab::WriteReplyParams(reply_message,
                                               append_tab_response);
@@ -577,8 +586,8 @@
     Browser* browser = FindAndActivateTab(tab);
 
     if (browser) {
-      AddNavigationStatusListener(tab, reply_message, number_of_navigations,
-                                  false);
+      new NavigationNotificationObserver(tab, this, reply_message,
+                                         number_of_navigations, false);
 
       // TODO(darin): avoid conversion to GURL.
       browser->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
@@ -626,7 +635,7 @@
     NavigationController* tab = tab_tracker_->GetResource(handle);
     Browser* browser = FindAndActivateTab(tab);
     if (browser && browser->command_updater()->IsCommandEnabled(IDC_RELOAD)) {
-      AddNavigationStatusListener(tab, reply_message, 1, false);
+      new NavigationNotificationObserver(tab, this, reply_message, 1, false);
       browser->Reload(CURRENT_TAB);
       return;
     }
@@ -650,8 +659,8 @@
       // not strictly correct, because a navigation can require both proxy and
       // server auth, but it should be OK for now.
       LoginHandler* handler = iter->second;
-      AddNavigationStatusListener(tab, reply_message, 1, false);
-      handler->SetAuth(username, password);
+      new NavigationNotificationObserver(tab, this, reply_message, 1, false);
+      handler->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password));
       return;
     }
   }
@@ -670,7 +679,7 @@
     if (iter != login_handler_map_.end()) {
       // If auth is needed again after this, something is screwy.
       LoginHandler* handler = iter->second;
-      AddNavigationStatusListener(tab, reply_message, 1, false);
+      new NavigationNotificationObserver(tab, this, reply_message, 1, false);
       handler->CancelAuth();
       return;
     }
@@ -869,15 +878,15 @@
 
   gfx::NativeWindow window = window_tracker_->GetResource(handle);
   // The key event is sent to whatever window is active.
-  ui_controls::SendKeyPress(window, static_cast<app::KeyboardCode>(key),
-                            ((flags & views::Event::EF_CONTROL_DOWN) ==
-                             views::Event::EF_CONTROL_DOWN),
-                            ((flags & views::Event::EF_SHIFT_DOWN) ==
-                             views::Event::EF_SHIFT_DOWN),
-                            ((flags & views::Event::EF_ALT_DOWN) ==
-                             views::Event::EF_ALT_DOWN),
-                            ((flags & views::Event::EF_COMMAND_DOWN) ==
-                             views::Event::EF_COMMAND_DOWN));
+  ui_controls::SendKeyPress(window, static_cast<ui::KeyboardCode>(key),
+                            ((flags & ui::EF_CONTROL_DOWN) ==
+                             ui::EF_CONTROL_DOWN),
+                            ((flags & ui::EF_SHIFT_DOWN) ==
+                             ui::EF_SHIFT_DOWN),
+                            ((flags & ui::EF_ALT_DOWN) ==
+                             ui::EF_ALT_DOWN),
+                            ((flags & ui::EF_COMMAND_DOWN) ==
+                             ui::EF_COMMAND_DOWN));
 }
 
 void TestingAutomationProvider::GetTabCount(int handle, int* tab_count) {
@@ -1015,7 +1024,7 @@
 void TestingAutomationProvider::GetAutocompleteEditText(
     int autocomplete_edit_handle,
     bool* success,
-    std::wstring* text) {
+    string16* text) {
   *success = false;
   if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
     *text = autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
@@ -1026,7 +1035,7 @@
 
 void TestingAutomationProvider::SetAutocompleteEditText(
     int autocomplete_edit_handle,
-    const std::wstring& text,
+    const string16& text,
     bool* success) {
   *success = false;
   if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
@@ -1121,18 +1130,18 @@
   // This routing id needs to be remembered for the reverse
   // communication while sending back the response of
   // this javascript execution.
-  std::wstring set_automation_id;
+  std::string set_automation_id;
   base::SStringPrintf(&set_automation_id,
-                      L"window.domAutomationController.setAutomationId(%d);",
+                      "window.domAutomationController.setAutomationId(%d);",
                       reply_message->routing_id());
 
   DCHECK(reply_message_ == NULL);
   reply_message_ = reply_message;
 
   tab_contents->render_view_host()->ExecuteJavascriptInWebFrame(
-      frame_xpath, set_automation_id);
+      WideToUTF16Hack(frame_xpath), UTF8ToUTF16(set_automation_id));
   tab_contents->render_view_host()->ExecuteJavascriptInWebFrame(
-      frame_xpath, script);
+      WideToUTF16Hack(frame_xpath), WideToUTF16Hack(script));
 }
 
 void TestingAutomationProvider::GetConstrainedWindowCount(int handle,
@@ -1227,7 +1236,9 @@
     NavigationController* controller = tab_tracker_->GetResource(tab_handle);
     TabContents* tab_contents = controller->tab_contents();
 
-    AddNavigationStatusListener(controller, reply_message, 1, false);
+    new NavigationNotificationObserver(controller, this, reply_message, 1,
+                                       false);
+
     AutomationInterstitialPage* interstitial =
         new AutomationInterstitialPage(tab_contents,
                                        GURL("about:interstitial"),
@@ -1258,6 +1269,10 @@
     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
     restore_tracker_.reset(
         new NavigationControllerRestoredObserver(this, tab, reply_message));
+  } else {
+    AutomationMsg_WaitForTabToBeRestored::WriteReplyParams(
+        reply_message, false);
+    Send(reply_message);
   }
 }
 
@@ -1321,7 +1336,8 @@
           InterstitialPage::GetInterstitialPage(tab_contents);
       if (ssl_blocking_page) {
         if (proceed) {
-          AddNavigationStatusListener(tab, reply_message, 1, false);
+          new NavigationNotificationObserver(tab, this, reply_message, 1,
+                                             false);
           ssl_blocking_page->Proceed();
           return;
         }
@@ -1362,15 +1378,24 @@
 
 void TestingAutomationProvider::PrintNow(int tab_handle,
                                          IPC::Message* reply_message) {
+
   NavigationController* tab = NULL;
   TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab);
   if (tab_contents) {
     FindAndActivateTab(tab);
-    notification_observer_list_.AddObserver(
-        new DocumentPrintedNotificationObserver(this, reply_message));
-    if (tab_contents->PrintNow())
-      return;
+
+    NotificationObserver* observer =
+        new DocumentPrintedNotificationObserver(this, reply_message);
+
+    if (!tab_contents->PrintNow()) {
+      // Clean up the observer. It will send the reply message.
+      delete observer;
+    }
+
+    // Return now to avoid sending reply message twice.
+    return;
   }
+
   AutomationMsg_PrintNow::WriteReplyParams(reply_message, false);
   Send(reply_message);
 }
@@ -1658,28 +1683,28 @@
   *success = false;
 }
 
-void TestingAutomationProvider::GetInfoBarCount(int handle, int* count) {
-  *count = -1;  // -1 means error.
+void TestingAutomationProvider::GetInfoBarCount(int handle, size_t* count) {
+  *count = static_cast<size_t>(-1);  // -1 means error.
   if (tab_tracker_->ContainsHandle(handle)) {
     NavigationController* nav_controller = tab_tracker_->GetResource(handle);
     if (nav_controller)
-      *count = nav_controller->tab_contents()->infobar_delegate_count();
+      *count = nav_controller->tab_contents()->infobar_count();
   }
 }
 
 void TestingAutomationProvider::ClickInfoBarAccept(
     int handle,
-    int info_bar_index,
+    size_t info_bar_index,
     bool wait_for_navigation,
     IPC::Message* reply_message) {
   bool success = false;
   if (tab_tracker_->ContainsHandle(handle)) {
     NavigationController* nav_controller = tab_tracker_->GetResource(handle);
     if (nav_controller) {
-      int count = nav_controller->tab_contents()->infobar_delegate_count();
-      if (info_bar_index >= 0 && info_bar_index < count) {
+      if (info_bar_index < nav_controller->tab_contents()->infobar_count()) {
         if (wait_for_navigation) {
-          AddNavigationStatusListener(nav_controller, reply_message, 1, false);
+          new NavigationNotificationObserver(nav_controller, this,
+                                             reply_message, 1, false);
         }
         InfoBarDelegate* delegate =
             nav_controller->tab_contents()->GetInfoBarDelegateAt(
@@ -1722,7 +1747,7 @@
     return;
   }
 
-  AddNavigationStatusListener(controller, reply_message, 1, true);
+  new NavigationNotificationObserver(controller, this, reply_message, 1, true);
 }
 
 void TestingAutomationProvider::SetIntPreference(int handle,
@@ -1780,7 +1805,7 @@
       AppModalDialogQueue::GetInstance()->active_dialog();
   if (!active_dialog) {
     *showing_dialog = false;
-    *dialog_button = MessageBoxFlags::DIALOGBUTTON_NONE;
+    *dialog_button = ui::MessageBoxFlags::DIALOGBUTTON_NONE;
     return;
   }
   NativeAppModalDialog* native_dialog = active_dialog->native_dialog();
@@ -1788,7 +1813,7 @@
   if (*showing_dialog)
     *dialog_button = native_dialog->GetAppModalDialogButtons();
   else
-    *dialog_button = MessageBoxFlags::DIALOGBUTTON_NONE;
+    *dialog_button = ui::MessageBoxFlags::DIALOGBUTTON_NONE;
 }
 
 void TestingAutomationProvider::ClickAppModalDialogButton(int button,
@@ -1799,13 +1824,13 @@
       AppModalDialogQueue::GetInstance()->active_dialog()->native_dialog();
   if (native_dialog &&
       (native_dialog->GetAppModalDialogButtons() & button) == button) {
-    if ((button & MessageBoxFlags::DIALOGBUTTON_OK) ==
-        MessageBoxFlags::DIALOGBUTTON_OK) {
+    if ((button & ui::MessageBoxFlags::DIALOGBUTTON_OK) ==
+        ui::MessageBoxFlags::DIALOGBUTTON_OK) {
       native_dialog->AcceptAppModalDialog();
       *success =  true;
     }
-    if ((button & MessageBoxFlags::DIALOGBUTTON_CANCEL) ==
-        MessageBoxFlags::DIALOGBUTTON_CANCEL) {
+    if ((button & ui::MessageBoxFlags::DIALOGBUTTON_CANCEL) ==
+        ui::MessageBoxFlags::DIALOGBUTTON_CANCEL) {
       DCHECK(!*success) << "invalid param, OK and CANCEL specified";
       native_dialog->CancelAppModalDialog();
       *success =  true;
@@ -1814,7 +1839,8 @@
 }
 
 void TestingAutomationProvider::WaitForBrowserWindowCountToBecome(
-    int target_count, IPC::Message* reply_message) {
+    int target_count,
+    IPC::Message* reply_message) {
   if (static_cast<int>(BrowserList::size()) == target_count) {
     AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
         reply_message, true);
@@ -1845,8 +1871,8 @@
     NavigationController* tab = tab_tracker_->GetResource(handle);
     Browser* browser = FindAndActivateTab(tab);
     if (browser && browser->command_updater()->IsCommandEnabled(IDC_BACK)) {
-      AddNavigationStatusListener(tab, reply_message, number_of_navigations,
-                                  false);
+      new NavigationNotificationObserver(tab, this, reply_message,
+                                         number_of_navigations, false);
       browser->GoBack(CURRENT_TAB);
       return;
     }
@@ -1863,8 +1889,8 @@
     NavigationController* tab = tab_tracker_->GetResource(handle);
     Browser* browser = FindAndActivateTab(tab);
     if (browser && browser->command_updater()->IsCommandEnabled(IDC_FORWARD)) {
-      AddNavigationStatusListener(tab, reply_message, number_of_navigations,
-                                  false);
+      new NavigationNotificationObserver(tab, this, reply_message,
+                                         number_of_navigations, false);
       browser->GoForward(CURRENT_TAB);
       return;
     }
@@ -1930,17 +1956,7 @@
 void TestingAutomationProvider::SendJSONRequest(int handle,
                                                 std::string json_request,
                                                 IPC::Message* reply_message) {
-  Browser* browser = NULL;
   scoped_ptr<Value> values;
-
-  // Basic error checking.
-  if (browser_tracker_->ContainsHandle(handle)) {
-    browser = browser_tracker_->GetResource(handle);
-  }
-  if (!browser) {
-    AutomationJSONReply(this, reply_message).SendError("no browser object");
-    return;
-  }
   base::JSONReader reader;
   std::string error;
   values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error));
@@ -1966,133 +1982,172 @@
 
   // Map json commands to their handlers.
   std::map<std::string, JsonHandler> handler_map;
-  handler_map["DisablePlugin"] = &TestingAutomationProvider::DisablePlugin;
-  handler_map["EnablePlugin"] = &TestingAutomationProvider::EnablePlugin;
-  handler_map["GetPluginsInfo"] = &TestingAutomationProvider::GetPluginsInfo;
+#if defined(OS_CHROMEOS)
+  handler_map["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest;
+  handler_map["Login"] = &TestingAutomationProvider::Login;
+  handler_map["Logout"] = &TestingAutomationProvider::Logout;
+  handler_map["ScreenLock"] = &TestingAutomationProvider::ScreenLock;
+  handler_map["ScreenUnlock"] = &TestingAutomationProvider::ScreenUnlock;
+#endif  // defined(OS_CHROMEOS)
 
-  handler_map["GetBrowserInfo"] = &TestingAutomationProvider::GetBrowserInfo;
+  std::map<std::string, BrowserJsonHandler> browser_handler_map;
+  browser_handler_map["DisablePlugin"] =
+      &TestingAutomationProvider::DisablePlugin;
+  browser_handler_map["EnablePlugin"] =
+      &TestingAutomationProvider::EnablePlugin;
+  browser_handler_map["GetPluginsInfo"] =
+      &TestingAutomationProvider::GetPluginsInfo;
 
-  handler_map["GetNavigationInfo"] =
+  browser_handler_map["GetBrowserInfo"] =
+      &TestingAutomationProvider::GetBrowserInfo;
+
+  browser_handler_map["GetNavigationInfo"] =
       &TestingAutomationProvider::GetNavigationInfo;
 
-  handler_map["PerformActionOnInfobar"] =
+  browser_handler_map["PerformActionOnInfobar"] =
       &TestingAutomationProvider::PerformActionOnInfobar;
 
-  handler_map["GetHistoryInfo"] = &TestingAutomationProvider::GetHistoryInfo;
-  handler_map["AddHistoryItem"] = &TestingAutomationProvider::AddHistoryItem;
+  browser_handler_map["GetHistoryInfo"] =
+      &TestingAutomationProvider::GetHistoryInfo;
+  browser_handler_map["AddHistoryItem"] =
+      &TestingAutomationProvider::AddHistoryItem;
 
-  handler_map["GetOmniboxInfo"] = &TestingAutomationProvider::GetOmniboxInfo;
-  handler_map["SetOmniboxText"] = &TestingAutomationProvider::SetOmniboxText;
-  handler_map["OmniboxAcceptInput"] =
+  browser_handler_map["GetOmniboxInfo"] =
+      &TestingAutomationProvider::GetOmniboxInfo;
+  browser_handler_map["SetOmniboxText"] =
+      &TestingAutomationProvider::SetOmniboxText;
+  browser_handler_map["OmniboxAcceptInput"] =
       &TestingAutomationProvider::OmniboxAcceptInput;
-  handler_map["OmniboxMovePopupSelection"] =
+  browser_handler_map["OmniboxMovePopupSelection"] =
       &TestingAutomationProvider::OmniboxMovePopupSelection;
 
-  handler_map["GetInstantInfo"] = &TestingAutomationProvider::GetInstantInfo;
+  browser_handler_map["GetInstantInfo"] =
+      &TestingAutomationProvider::GetInstantInfo;
 
-  handler_map["LoadSearchEngineInfo"] =
+  browser_handler_map["LoadSearchEngineInfo"] =
       &TestingAutomationProvider::LoadSearchEngineInfo;
-  handler_map["GetSearchEngineInfo"] =
+  browser_handler_map["GetSearchEngineInfo"] =
       &TestingAutomationProvider::GetSearchEngineInfo;
-  handler_map["AddOrEditSearchEngine"] =
+  browser_handler_map["AddOrEditSearchEngine"] =
       &TestingAutomationProvider::AddOrEditSearchEngine;
-  handler_map["PerformActionOnSearchEngine"] =
+  browser_handler_map["PerformActionOnSearchEngine"] =
       &TestingAutomationProvider::PerformActionOnSearchEngine;
 
-  handler_map["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo;
-  handler_map["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
+  browser_handler_map["GetPrefsInfo"] =
+      &TestingAutomationProvider::GetPrefsInfo;
+  browser_handler_map["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
 
-  handler_map["SetWindowDimensions"] =
+  browser_handler_map["SetWindowDimensions"] =
       &TestingAutomationProvider::SetWindowDimensions;
 
-  handler_map["GetDownloadsInfo"] =
+  browser_handler_map["GetDownloadsInfo"] =
       &TestingAutomationProvider::GetDownloadsInfo;
-  handler_map["WaitForAllDownloadsToComplete"] =
+  browser_handler_map["WaitForAllDownloadsToComplete"] =
       &TestingAutomationProvider::WaitForDownloadsToComplete;
-  handler_map["PerformActionOnDownload"] =
+  browser_handler_map["PerformActionOnDownload"] =
       &TestingAutomationProvider::PerformActionOnDownload;
 
-  handler_map["GetInitialLoadTimes"] =
+  browser_handler_map["GetInitialLoadTimes"] =
       &TestingAutomationProvider::GetInitialLoadTimes;
 
-  handler_map["SaveTabContents"] = &TestingAutomationProvider::SaveTabContents;
+  browser_handler_map["SaveTabContents"] =
+      &TestingAutomationProvider::SaveTabContents;
 
-  handler_map["ImportSettings"] = &TestingAutomationProvider::ImportSettings;
+  browser_handler_map["ImportSettings"] =
+      &TestingAutomationProvider::ImportSettings;
 
-  handler_map["AddSavedPassword"] =
+  browser_handler_map["AddSavedPassword"] =
       &TestingAutomationProvider::AddSavedPassword;
-  handler_map["RemoveSavedPassword"] =
+  browser_handler_map["RemoveSavedPassword"] =
       &TestingAutomationProvider::RemoveSavedPassword;
-  handler_map["GetSavedPasswords"] =
+  browser_handler_map["GetSavedPasswords"] =
       &TestingAutomationProvider::GetSavedPasswords;
 
-  handler_map["ClearBrowsingData"] =
+  browser_handler_map["ClearBrowsingData"] =
       &TestingAutomationProvider::ClearBrowsingData;
 
-  handler_map["GetBlockedPopupsInfo"] =
+  browser_handler_map["GetBlockedPopupsInfo"] =
       &TestingAutomationProvider::GetBlockedPopupsInfo;
-  handler_map["UnblockAndLaunchBlockedPopup"] =
+  browser_handler_map["UnblockAndLaunchBlockedPopup"] =
       &TestingAutomationProvider::UnblockAndLaunchBlockedPopup;
 
   // SetTheme() implemented using InstallExtension().
-  handler_map["GetThemeInfo"] = &TestingAutomationProvider::GetThemeInfo;
+  browser_handler_map["GetThemeInfo"] =
+      &TestingAutomationProvider::GetThemeInfo;
 
   // InstallExtension() present in pyauto.py.
-  handler_map["GetExtensionsInfo"] =
+  browser_handler_map["GetExtensionsInfo"] =
       &TestingAutomationProvider::GetExtensionsInfo;
-  handler_map["UninstallExtensionById"] =
+  browser_handler_map["UninstallExtensionById"] =
       &TestingAutomationProvider::UninstallExtensionById;
 
-  handler_map["FindInPage"] = &TestingAutomationProvider::FindInPage;
+  browser_handler_map["FindInPage"] = &TestingAutomationProvider::FindInPage;
 
-  handler_map["SelectTranslateOption"] =
+  browser_handler_map["SelectTranslateOption"] =
       &TestingAutomationProvider::SelectTranslateOption;
-  handler_map["GetTranslateInfo"] =
+  browser_handler_map["GetTranslateInfo"] =
       &TestingAutomationProvider::GetTranslateInfo;
 
-  handler_map["GetAutoFillProfile"] =
+  browser_handler_map["GetAutoFillProfile"] =
       &TestingAutomationProvider::GetAutoFillProfile;
-  handler_map["FillAutoFillProfile"] =
+  browser_handler_map["FillAutoFillProfile"] =
       &TestingAutomationProvider::FillAutoFillProfile;
 
-  handler_map["GetActiveNotifications"] =
+  browser_handler_map["GetActiveNotifications"] =
       &TestingAutomationProvider::GetActiveNotifications;
-  handler_map["CloseNotification"] =
+  browser_handler_map["CloseNotification"] =
       &TestingAutomationProvider::CloseNotification;
-  handler_map["WaitForNotificationCount"] =
+  browser_handler_map["WaitForNotificationCount"] =
       &TestingAutomationProvider::WaitForNotificationCount;
 
-  handler_map["SignInToSync"] = &TestingAutomationProvider::SignInToSync;
-  handler_map["GetSyncInfo"] = &TestingAutomationProvider::GetSyncInfo;
-  handler_map["AwaitSyncCycleCompletion"] =
+  browser_handler_map["SignInToSync"] =
+      &TestingAutomationProvider::SignInToSync;
+  browser_handler_map["GetSyncInfo"] = &TestingAutomationProvider::GetSyncInfo;
+  browser_handler_map["AwaitSyncCycleCompletion"] =
       &TestingAutomationProvider::AwaitSyncCycleCompletion;
-  handler_map["EnableSyncForDatatypes"] =
+  browser_handler_map["EnableSyncForDatatypes"] =
       &TestingAutomationProvider::EnableSyncForDatatypes;
-  handler_map["DisableSyncForDatatypes"] =
+  browser_handler_map["DisableSyncForDatatypes"] =
       &TestingAutomationProvider::DisableSyncForDatatypes;
 
-  handler_map["GetNTPInfo"] =
+  browser_handler_map["GetNTPInfo"] =
       &TestingAutomationProvider::GetNTPInfo;
-  handler_map["MoveNTPMostVisitedThumbnail"] =
+  browser_handler_map["MoveNTPMostVisitedThumbnail"] =
       &TestingAutomationProvider::MoveNTPMostVisitedThumbnail;
-  handler_map["RemoveNTPMostVisitedThumbnail"] =
+  browser_handler_map["RemoveNTPMostVisitedThumbnail"] =
       &TestingAutomationProvider::RemoveNTPMostVisitedThumbnail;
-  handler_map["UnpinNTPMostVisitedThumbnail"] =
+  browser_handler_map["UnpinNTPMostVisitedThumbnail"] =
       &TestingAutomationProvider::UnpinNTPMostVisitedThumbnail;
-  handler_map["RestoreAllNTPMostVisitedThumbnails"] =
+  browser_handler_map["RestoreAllNTPMostVisitedThumbnails"] =
       &TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails;
 
-  handler_map["KillRendererProcess"] =
+  browser_handler_map["KillRendererProcess"] =
       &TestingAutomationProvider::KillRendererProcess;
 
+  browser_handler_map["SendKeyEventToActiveTab"] =
+      &TestingAutomationProvider::SendKeyEventToActiveTab;
+
   if (handler_map.find(std::string(command)) != handler_map.end()) {
-    (this->*handler_map[command])(browser, dict_value, reply_message);
+    (this->*handler_map[command])(dict_value, reply_message);
+  } else if (browser_handler_map.find(std::string(command)) !=
+             browser_handler_map.end()) {
+    Browser* browser = NULL;
+    if (!browser_tracker_->ContainsHandle(handle) ||
+        !(browser = browser_tracker_->GetResource(handle))) {
+      AutomationJSONReply(this, reply_message).SendError("No browser object.");
+      return;
+    }
+    (this->*browser_handler_map[command])(browser, dict_value, reply_message);
   } else {
     std::string error_string = "Unknown command. Options: ";
     for (std::map<std::string, JsonHandler>::const_iterator it =
          handler_map.begin(); it != handler_map.end(); ++it) {
       error_string += it->first + ", ";
     }
+    for (std::map<std::string, BrowserJsonHandler>::const_iterator it =
+         browser_handler_map.begin(); it != browser_handler_map.end(); ++it) {
+      error_string += it->first + ", ";
+    }
     AutomationJSONReply(this, reply_message).SendError(error_string);
   }
 }
@@ -2123,11 +2178,9 @@
 ListValue* TestingAutomationProvider::GetInfobarsInfo(TabContents* tc) {
   // Each infobar may have different properties depending on the type.
   ListValue* infobars = new ListValue;
-  for (int infobar_index = 0;
-       infobar_index < tc->infobar_delegate_count();
-       ++infobar_index) {
+  for (size_t i = 0; i < tc->infobar_count(); ++i) {
     DictionaryValue* infobar_item = new DictionaryValue;
-    InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(infobar_index);
+    InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(i);
     if (infobar->AsConfirmInfoBarDelegate()) {
       // Also covers ThemeInstalledInfoBarDelegate and
       // CrashedExtensionInfoBarDelegate.
@@ -2138,24 +2191,19 @@
       infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
       ListValue* buttons_list = new ListValue;
       int buttons = confirm_infobar->GetButtons();
-      if (ConfirmInfoBarDelegate::BUTTON_OK & buttons) {
+      if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) {
         StringValue* button_label = new StringValue(
             confirm_infobar->GetButtonLabel(
               ConfirmInfoBarDelegate::BUTTON_OK));
         buttons_list->Append(button_label);
       }
-      if (ConfirmInfoBarDelegate::BUTTON_CANCEL & buttons) {
+      if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
         StringValue* button_label = new StringValue(
             confirm_infobar->GetButtonLabel(
               ConfirmInfoBarDelegate::BUTTON_CANCEL));
         buttons_list->Append(button_label);
       }
       infobar_item->Set("buttons", buttons_list);
-    } else if (infobar->AsAlertInfoBarDelegate()) {
-      infobar_item->SetString("type", "alert_infobar");
-      AlertInfoBarDelegate* alert_infobar =
-        infobar->AsAlertInfoBarDelegate();
-      infobar_item->SetString("text", alert_infobar->GetMessageText());
     } else if (infobar->AsLinkInfoBarDelegate()) {
       infobar_item->SetString("type", "link_infobar");
       LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate();
@@ -2189,10 +2237,10 @@
     IPC::Message* reply_message) {
   AutomationJSONReply reply(this, reply_message);
   int tab_index;
-  int infobar_index;
+  int infobar_index_int;
   std::string action;
   if (!args->GetInteger("tab_index", &tab_index) ||
-      !args->GetInteger("infobar_index", &infobar_index) ||
+      !args->GetInteger("infobar_index", &infobar_index_int) ||
       !args->GetString("action", &action)) {
     reply.SendError("Invalid or missing args");
     return;
@@ -2203,10 +2251,11 @@
     return;
   }
   InfoBarDelegate* infobar = NULL;
-  if (infobar_index < 0 ||
-      infobar_index >= tab_contents->infobar_delegate_count() ||
+  size_t infobar_index = static_cast<size_t>(infobar_index_int);
+  if (infobar_index >= tab_contents->infobar_count() ||
       !(infobar = tab_contents->GetInfoBarDelegateAt(infobar_index))) {
-    reply.SendError(StringPrintf("No such infobar at index %d", infobar_index));
+    reply.SendError(StringPrintf("No such infobar at index %" PRIuS,
+                                 infobar_index));
     return;
   }
   if ("dismiss" == action) {
@@ -2494,7 +2543,7 @@
   double dt;
   if (item->GetInteger("time", &it))
     time = base::Time::FromTimeT(it);
-  else if (item->GetReal("time", &dt))
+  else if (item->GetDouble("time", &dt))
     time = base::Time::FromDoubleT(dt);
 
   // Ideas for "dummy" values (e.g. id_scope) came from
@@ -2521,14 +2570,15 @@
                                                  IPC::Message* reply_message) {
   AutomationJSONReply reply(this, reply_message);
 
-  if (!profile_->HasCreatedDownloadManager()) {
+  if (!browser->profile()->HasCreatedDownloadManager()) {
       reply.SendError("no download manager");
       return;
   }
 
   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
   std::vector<DownloadItem*> downloads;
-  profile_->GetDownloadManager()->GetAllDownloads(FilePath(), &downloads);
+  browser->profile()->GetDownloadManager()->
+      GetAllDownloads(FilePath(), &downloads);
 
   ListValue* list_of_downloads = new ListValue;
   for (std::vector<DownloadItem*>::iterator it = downloads.begin();
@@ -2548,18 +2598,18 @@
     IPC::Message* reply_message) {
 
   // Look for a quick return.
-  if (!profile_->HasCreatedDownloadManager()) {
+  if (!browser->profile()->HasCreatedDownloadManager()) {
     // No download manager.
     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
     return;
   }
   std::vector<DownloadItem*> downloads;
-  profile_->GetDownloadManager()->GetCurrentDownloads(FilePath(), &downloads);
+  browser->profile()->GetDownloadManager()->
+      GetCurrentDownloads(FilePath(), &downloads);
   if (downloads.empty()) {
     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
     return;
   }
-
   // The observer owns itself.  When the last observed item pings, it
   // deletes itself.
   AutomationProviderDownloadItemObserver* item_observer =
@@ -2591,7 +2641,7 @@
   return selected_item;
 }
 
-} // namespace
+}  // namespace
 
 // See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
 // json input and output.
@@ -2602,7 +2652,7 @@
   int id;
   std::string action;
 
-  if (!profile_->HasCreatedDownloadManager()) {
+  if (!browser->profile()->HasCreatedDownloadManager()) {
     AutomationJSONReply(this, reply_message).SendError("No download manager.");
     return;
   }
@@ -2612,7 +2662,7 @@
     return;
   }
 
-  DownloadManager* download_manager = profile_->GetDownloadManager();
+  DownloadManager* download_manager = browser->profile()->GetDownloadManager();
   DownloadItem* selected_item = GetDownloadItemFromId(id, download_manager);
   if (!selected_item) {
     AutomationJSONReply(this, reply_message).SendError(
@@ -2687,9 +2737,9 @@
   for (std::vector<const TemplateURL*>::const_iterator it =
        template_urls.begin(); it != template_urls.end(); ++it) {
     DictionaryValue* search_engine = new DictionaryValue;
-    search_engine->SetString("short_name", WideToUTF8((*it)->short_name()));
-    search_engine->SetString("description", WideToUTF8((*it)->description()));
-    search_engine->SetString("keyword", WideToUTF8((*it)->keyword()));
+    search_engine->SetString("short_name", UTF16ToUTF8((*it)->short_name()));
+    search_engine->SetString("description", UTF16ToUTF8((*it)->description()));
+    search_engine->SetString("keyword", UTF16ToUTF8((*it)->keyword()));
     search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
     search_engine->SetBoolean("is_default",
         (*it) == url_model->GetDefaultSearchProvider());
@@ -2700,7 +2750,7 @@
     search_engine->SetString("host", (*it)->url()->GetHost());
     search_engine->SetString("path", (*it)->url()->GetPath());
     search_engine->SetString("display_url",
-                             WideToUTF8((*it)->url()->DisplayURL()));
+                             UTF16ToUTF8((*it)->url()->DisplayURL()));
     search_engines->Append(search_engine);
   }
   return_value->Set("search_engines", search_engines);
@@ -2726,11 +2776,11 @@
     return;
   }
   std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef(
-      UTF8ToWide(new_url));
+      UTF8ToUTF16(new_url));
   scoped_ptr<KeywordEditorController> controller(
       new KeywordEditorController(profile_));
   if (args->GetString("keyword", &keyword)) {
-    template_url = url_model->GetTemplateURLForKeyword(UTF8ToWide(keyword));
+    template_url = url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword));
     if (template_url == NULL) {
       AutomationJSONReply(this, reply_message).SendError(
           StringPrintf("No match for keyword: %s", keyword.c_str()));
@@ -2763,7 +2813,7 @@
     return;
   }
   const TemplateURL* template_url(
-      url_model->GetTemplateURLForKeyword(UTF8ToWide(keyword)));
+      url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword)));
   if (template_url == NULL) {
     AutomationJSONReply(this, reply_message).SendError(
         StringPrintf("No match for keyword: %s", keyword.c_str()));
@@ -2788,13 +2838,8 @@
 void TestingAutomationProvider::GetPrefsInfo(Browser* browser,
                                              DictionaryValue* args,
                                              IPC::Message* reply_message) {
-  const PrefService::PreferenceSet& prefs =
-      profile_->GetPrefs()->preference_set();
-  DictionaryValue* items = new DictionaryValue;
-  for (PrefService::PreferenceSet::const_iterator it = prefs.begin();
-       it != prefs.end(); ++it) {
-    items->Set((*it)->name(), (*it)->GetValue()->DeepCopy());
-  }
+  DictionaryValue* items = profile_->GetPrefs()->GetPreferenceValues();
+
   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
   return_value->Set("prefs", items);  // return_value owns items.
   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
@@ -2849,8 +2894,8 @@
     item->SetString("type", AutocompleteMatch::TypeToString(match.type));
     item->SetBoolean("starred", match.starred);
     item->SetString("destination_url", match.destination_url.spec());
-    item->SetString("contents", WideToUTF16Hack(match.contents));
-    item->SetString("description", WideToUTF16Hack(match.description));
+    item->SetString("contents", match.contents);
+    item->SetString("description", match.description);
     matches->Append(item);
   }
   return_value->Set("matches", matches);
@@ -2859,8 +2904,8 @@
   DictionaryValue* properties = new DictionaryValue;  // owned by return_value
   properties->SetBoolean("has_focus", model->has_focus());
   properties->SetBoolean("query_in_progress", model->query_in_progress());
-  properties->SetString("keyword", WideToUTF16Hack(model->keyword()));
-  properties->SetString("text", WideToUTF16Hack(edit_view->GetText()));
+  properties->SetString("keyword", model->keyword());
+  properties->SetString("text", edit_view->GetText());
   return_value->Set("properties", properties);
 
   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
@@ -2881,7 +2926,7 @@
   LocationBar* loc_bar = browser->window()->GetLocationBar();
   AutocompleteEditView* edit_view = loc_bar->location_entry();
   edit_view->model()->OnSetFocus(false);
-  edit_view->SetUserText(UTF16ToWideHack(text));
+  edit_view->SetUserText(text);
   reply.SendSuccess(NULL);
 }
 
@@ -2912,11 +2957,7 @@
     IPC::Message* reply_message) {
   NavigationController& controller =
       browser->GetSelectedTabContents()->controller();
-  // Setup observer to wait until the selected item loads.
-  NotificationObserver* observer =
-      new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
-  notification_observer_list_.AddObserver(observer);
-
+  new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
   browser->window()->GetLocationBar()->AcceptInput();
 }
 
@@ -2980,7 +3021,7 @@
     item->SetString("path", it->path.value());
     item->SetString("version", it->version);
     item->SetString("desc", it->desc);
-    item->SetBoolean("enabled", it->enabled);
+    item->SetBoolean("enabled", webkit::npapi::IsPluginEnabled(*it));
     // Add info about mime types.
     ListValue* mime_types = new ListValue();
     for (std::vector<webkit::npapi::WebPluginMimeType>::const_iterator type_it =
@@ -3136,9 +3177,10 @@
   import_settings_data_.reply_message = reply_message;
 
   // The remaining functionality of importing settings is in
-  // SourceProfilesLoaded(), which is called by |importer_host_| once the source
+  // SourceProfilesLoaded(), which is called by |importer_list_| once the source
   // profiles are loaded.
-  importer_host_ = new ImporterHost(this);
+  importer_list_ = new ImporterList;
+  importer_list_->DetectSourceProfiles(this);
 }
 
 namespace {
@@ -3153,7 +3195,7 @@
   double dt;
   if (password_dict.GetInteger("time", &it))
     time = base::Time::FromTimeT(it);
-  else if (password_dict.GetReal("time", &dt))
+  else if (password_dict.GetDouble("time", &dt))
     time = base::Time::FromDoubleT(dt);
 
   std::string signon_realm;
@@ -3198,7 +3240,7 @@
   return password_form;
 }
 
-} // namespace
+}  // namespace
 
 // See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
 // input.
@@ -3376,7 +3418,7 @@
   // Get the TranslateInfoBarDelegate from TabContents.
   TranslateInfoBarDelegate* GetTranslateInfoBarDelegate(
       TabContents* tab_contents) {
-    for (int i = 0; i < tab_contents->infobar_delegate_count(); i++) {
+    for (size_t i = 0; i < tab_contents->infobar_count(); i++) {
       InfoBarDelegate* infobar = tab_contents->GetInfoBarDelegateAt(i);
       if (infobar->AsTranslateInfoBarDelegate())
         return infobar->AsTranslateInfoBarDelegate();
@@ -3503,14 +3545,14 @@
       return;
     }
     // Get the target language index based off of the language name.
-    int target_language_index = -1;
-    for (int i = 0; i < translate_bar->GetLanguageCount(); i++) {
+    size_t target_language_index = TranslateInfoBarDelegate::kNoIndex;
+    for (size_t i = 0; i < translate_bar->GetLanguageCount(); i++) {
       if (translate_bar->GetLanguageDisplayableNameAt(i) == target_language) {
         target_language_index = i;
         break;
       }
     }
-    if (target_language_index == -1) {
+    if (target_language_index == TranslateInfoBarDelegate::kNoIndex) {
        AutomationJSONReply(this, reply_message)
            .SendError("Invalid target language string.");
        return;
@@ -3729,12 +3771,15 @@
     Browser* browser,
     DictionaryValue* args,
     IPC::Message* reply_message) {
+  AutomationJSONReply reply(this, reply_message);
   // Get the AutoFillProfiles currently in the database.
   int tab_index = 0;
-  args->GetInteger("tab_index", &tab_index);
-  TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
-  AutomationJSONReply reply(this, reply_message);
+  if (!args->GetInteger("tab_index", &tab_index)) {
+    reply.SendError("Invalid or missing tab_index integer value.");
+    return;
+  }
 
+  TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
   if (tab_contents) {
     PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile()
         ->GetPersonalDataManager();
@@ -3770,8 +3815,11 @@
   AutomationJSONReply reply(this, reply_message);
   ListValue* profiles = NULL;
   ListValue* cards = NULL;
+
+  // It's ok for profiles/credit_cards elements to be missing.
   args->GetList("profiles", &profiles);
   args->GetList("credit_cards", &cards);
+
   std::string error_mesg;
 
   std::vector<AutoFillProfile> autofill_profiles;
@@ -3791,7 +3839,11 @@
 
   // Save the AutoFillProfiles.
   int tab_index = 0;
-  args->GetInteger("tab_index", &tab_index);
+  if (!args->GetInteger("tab_index", &tab_index)) {
+    reply.SendError("Invalid or missing tab_index integer");
+    return;
+  }
+
   TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
 
   if (tab_contents) {
@@ -3984,7 +4036,10 @@
     return;
   }
   std::string first_datatype;
-  datatypes->GetString(0, &first_datatype);
+  if (!datatypes->GetString(0, &first_datatype)) {
+    reply.SendError("Invalid or missing string");
+    return;
+  }
   if (first_datatype == "All") {
     sync_waiter_->DisableSyncForAllDatatypes();
     ProfileSyncService::Status status = sync_waiter_->GetStatus();
@@ -4029,7 +4084,7 @@
     const std::vector<AutoFillProfile*>& autofill_profiles) {
   ListValue* profiles = new ListValue;
 
-  std::map<AutoFillFieldType, std::wstring> autofill_type_to_string
+  std::map<AutoFillFieldType, std::string> autofill_type_to_string
       = GetAutoFillFieldToStringMap();
 
   // For each AutoFillProfile, transform it to a dictionary object to return.
@@ -4039,12 +4094,12 @@
     AutoFillProfile* profile = *it;
     DictionaryValue* profile_info = new DictionaryValue;
     // For each of the types, if it has a value, add it to the dictionary.
-    for (std::map<AutoFillFieldType, std::wstring>::iterator
+    for (std::map<AutoFillFieldType, std::string>::iterator
          type_it = autofill_type_to_string.begin();
          type_it != autofill_type_to_string.end(); ++type_it) {
       string16 value = profile->GetFieldText(AutoFillType(type_it->first));
       if (value.length()) {  // If there was something stored for that value.
-        profile_info->SetString(WideToUTF8(type_it->second), value);
+        profile_info->SetString(type_it->second, value);
       }
     }
     profiles->Append(profile_info);
@@ -4057,7 +4112,7 @@
     const std::vector<CreditCard*>& credit_cards) {
   ListValue* cards = new ListValue;
 
-  std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
+  std::map<AutoFillFieldType, std::string> credit_card_type_to_string =
       GetCreditCardFieldToStringMap();
 
   // For each AutoFillProfile, transform it to a dictionary object to return.
@@ -4067,13 +4122,13 @@
     CreditCard* card = *it;
     DictionaryValue* card_info = new DictionaryValue;
     // For each of the types, if it has a value, add it to the dictionary.
-    for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
+    for (std::map<AutoFillFieldType, std::string>::iterator type_it =
         credit_card_type_to_string.begin();
         type_it != credit_card_type_to_string.end(); ++type_it) {
       string16 value = card->GetFieldText(AutoFillType(type_it->first));
       // If there was something stored for that value.
       if (value.length()) {
-        card_info->SetString(WideToUTF8(type_it->second), value);
+        card_info->SetString(type_it->second, value);
       }
     }
     cards->Append(card_info);
@@ -4089,7 +4144,7 @@
   DictionaryValue* profile_info = NULL;
   string16 current_value;
 
-  std::map<AutoFillFieldType, std::wstring> autofill_type_to_string =
+  std::map<AutoFillFieldType, std::string> autofill_type_to_string =
       GetAutoFillFieldToStringMap();
 
   int num_profiles = profiles.GetSize();
@@ -4097,11 +4152,11 @@
     profiles.GetDictionary(i, &profile_info);
     AutoFillProfile profile;
     // Loop through the possible profile types and add those provided.
-    for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
+    for (std::map<AutoFillFieldType, std::string>::iterator type_it =
          autofill_type_to_string.begin();
          type_it != autofill_type_to_string.end(); ++type_it) {
-      if (profile_info->HasKey(WideToUTF8(type_it->second))) {
-        if (profile_info->GetString(WideToUTF8(type_it->second),
+      if (profile_info->HasKey(type_it->second)) {
+        if (profile_info->GetString(type_it->second,
                                     &current_value)) {
           profile.SetInfo(AutoFillType(type_it->first), current_value);
         } else {
@@ -4122,7 +4177,7 @@
   DictionaryValue* card_info = NULL;
   string16 current_value;
 
-  std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
+  std::map<AutoFillFieldType, std::string> credit_card_type_to_string =
       GetCreditCardFieldToStringMap();
 
   int num_credit_cards = cards.GetSize();
@@ -4130,11 +4185,11 @@
     cards.GetDictionary(i, &card_info);
     CreditCard card;
     // Loop through the possible credit card fields and add those provided.
-    for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
+    for (std::map<AutoFillFieldType, std::string>::iterator type_it =
         credit_card_type_to_string.begin();
         type_it != credit_card_type_to_string.end(); ++type_it) {
-      if (card_info->HasKey(WideToUTF8(type_it->second))) {
-        if (card_info->GetString(WideToUTF8(type_it->second), &current_value)) {
+      if (card_info->HasKey(type_it->second)) {
+        if (card_info->GetString(type_it->second, &current_value)) {
           card.SetInfo(AutoFillType(type_it->first), current_value);
         } else {
           *error_message= "All values must be strings";
@@ -4148,36 +4203,36 @@
 }
 
 /* static */
-std::map<AutoFillFieldType, std::wstring>
+std::map<AutoFillFieldType, std::string>
     TestingAutomationProvider::GetAutoFillFieldToStringMap() {
-  std::map<AutoFillFieldType, std::wstring> autofill_type_to_string;
-  autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
-  autofill_type_to_string[NAME_MIDDLE] = L"NAME_MIDDLE";
-  autofill_type_to_string[NAME_LAST] = L"NAME_LAST";
-  autofill_type_to_string[COMPANY_NAME] = L"COMPANY_NAME";
-  autofill_type_to_string[EMAIL_ADDRESS] = L"EMAIL_ADDRESS";
-  autofill_type_to_string[ADDRESS_HOME_LINE1] = L"ADDRESS_HOME_LINE1";
-  autofill_type_to_string[ADDRESS_HOME_LINE2] = L"ADDRESS_HOME_LINE2";
-  autofill_type_to_string[ADDRESS_HOME_CITY] = L"ADDRESS_HOME_CITY";
-  autofill_type_to_string[ADDRESS_HOME_STATE] = L"ADDRESS_HOME_STATE";
-  autofill_type_to_string[ADDRESS_HOME_ZIP] = L"ADDRESS_HOME_ZIP";
-  autofill_type_to_string[ADDRESS_HOME_COUNTRY] = L"ADDRESS_HOME_COUNTRY";
+  std::map<AutoFillFieldType, std::string> autofill_type_to_string;
+  autofill_type_to_string[NAME_FIRST] = "NAME_FIRST";
+  autofill_type_to_string[NAME_MIDDLE] = "NAME_MIDDLE";
+  autofill_type_to_string[NAME_LAST] = "NAME_LAST";
+  autofill_type_to_string[COMPANY_NAME] = "COMPANY_NAME";
+  autofill_type_to_string[EMAIL_ADDRESS] = "EMAIL_ADDRESS";
+  autofill_type_to_string[ADDRESS_HOME_LINE1] = "ADDRESS_HOME_LINE1";
+  autofill_type_to_string[ADDRESS_HOME_LINE2] = "ADDRESS_HOME_LINE2";
+  autofill_type_to_string[ADDRESS_HOME_CITY] = "ADDRESS_HOME_CITY";
+  autofill_type_to_string[ADDRESS_HOME_STATE] = "ADDRESS_HOME_STATE";
+  autofill_type_to_string[ADDRESS_HOME_ZIP] = "ADDRESS_HOME_ZIP";
+  autofill_type_to_string[ADDRESS_HOME_COUNTRY] = "ADDRESS_HOME_COUNTRY";
   autofill_type_to_string[PHONE_HOME_WHOLE_NUMBER] =
-      L"PHONE_HOME_WHOLE_NUMBER";
-  autofill_type_to_string[PHONE_FAX_WHOLE_NUMBER] = L"PHONE_FAX_WHOLE_NUMBER";
-  autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
+      "PHONE_HOME_WHOLE_NUMBER";
+  autofill_type_to_string[PHONE_FAX_WHOLE_NUMBER] = "PHONE_FAX_WHOLE_NUMBER";
+  autofill_type_to_string[NAME_FIRST] = "NAME_FIRST";
   return autofill_type_to_string;
 }
 
 /* static */
-std::map<AutoFillFieldType, std::wstring>
+std::map<AutoFillFieldType, std::string>
     TestingAutomationProvider::GetCreditCardFieldToStringMap() {
-  std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string;
-  credit_card_type_to_string[CREDIT_CARD_NAME] = L"CREDIT_CARD_NAME";
-  credit_card_type_to_string[CREDIT_CARD_NUMBER] = L"CREDIT_CARD_NUMBER";
-  credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = L"CREDIT_CARD_EXP_MONTH";
+  std::map<AutoFillFieldType, std::string> credit_card_type_to_string;
+  credit_card_type_to_string[CREDIT_CARD_NAME] = "CREDIT_CARD_NAME";
+  credit_card_type_to_string[CREDIT_CARD_NUMBER] = "CREDIT_CARD_NUMBER";
+  credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = "CREDIT_CARD_EXP_MONTH";
   credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] =
-      L"CREDIT_CARD_EXP_4_DIGIT_YEAR";
+      "CREDIT_CARD_EXP_4_DIGIT_YEAR";
   return credit_card_type_to_string;
 }
 
@@ -4360,6 +4415,99 @@
   base::CloseProcessHandle(process);
 }
 
+void TestingAutomationProvider::SendKeyEventToActiveTab(
+    Browser* browser,
+    DictionaryValue* args,
+    IPC::Message* reply_message) {
+  int type, modifiers;
+  bool is_system_key;
+  string16 unmodified_text, text;
+  std::string key_identifier;
+  NativeWebKeyboardEvent event;
+  if (!args->GetInteger("type", &type)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'type' missing or invalid.");
+    return;
+  }
+  if (!args->GetBoolean("isSystemKey", &is_system_key)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'isSystemKey' missing or invalid.");
+    return;
+  }
+  if (!args->GetString("unmodifiedText", &unmodified_text)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'unmodifiedText' missing or invalid.");
+    return;
+  }
+  if (!args->GetString("text", &text)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'text' missing or invalid.");
+    return;
+  }
+  if (!args->GetInteger("nativeKeyCode", &event.nativeKeyCode)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'nativeKeyCode' missing or invalid.");
+    return;
+  }
+  if (!args->GetInteger("windowsKeyCode", &event.windowsKeyCode)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'windowsKeyCode' missing or invalid.");
+    return;
+  }
+  if (!args->GetInteger("modifiers", &modifiers)) {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'modifiers' missing or invalid.");
+    return;
+  }
+  if (args->GetString("keyIdentifier", &key_identifier)) {
+    base::strlcpy(event.keyIdentifier,
+                  key_identifier.c_str(),
+                  WebKit::WebKeyboardEvent::keyIdentifierLengthCap);
+  } else {
+    event.setKeyIdentifierFromWindowsKeyCode();
+  }
+
+  if (type == automation::kRawKeyDownType) {
+    event.type = WebKit::WebInputEvent::RawKeyDown;
+  } else if (type == automation::kKeyDownType) {
+    event.type = WebKit::WebInputEvent::KeyDown;
+  } else if (type == automation::kKeyUpType) {
+    event.type = WebKit::WebInputEvent::KeyUp;
+  } else if (type == automation::kCharType) {
+    event.type = WebKit::WebInputEvent::Char;
+  } else {
+    AutomationJSONReply reply(this, reply_message);
+    reply.SendError("'type' refers to an unrecognized keyboard event type");
+    return;
+  }
+
+  string16 unmodified_text_truncated = unmodified_text.substr(
+      0, WebKit::WebKeyboardEvent::textLengthCap - 1);
+  memcpy(event.unmodifiedText,
+         unmodified_text_truncated.c_str(),
+         unmodified_text_truncated.length() + 1);
+  string16 text_truncated = text.substr(
+      0, WebKit::WebKeyboardEvent::textLengthCap - 1);
+  memcpy(event.text, text_truncated.c_str(), text_truncated.length() + 1);
+
+  event.modifiers = 0;
+  if (modifiers & automation::kShiftKeyMask)
+    event.modifiers |= WebKit::WebInputEvent::ShiftKey;
+  if (modifiers & automation::kControlKeyMask)
+    event.modifiers |= WebKit::WebInputEvent::ControlKey;
+  if (modifiers & automation::kAltKeyMask)
+    event.modifiers |= WebKit::WebInputEvent::AltKey;
+  if (modifiers & automation::kMetaKeyMask)
+    event.modifiers |= WebKit::WebInputEvent::MetaKey;
+
+  event.isSystemKey = is_system_key;
+  event.timeStampSeconds = base::Time::Now().ToDoubleT();
+  event.skip_in_browser = true;
+  new InputEventAckNotificationObserver(this, reply_message, event.type);
+  browser->GetSelectedTabContents()->render_view_host()->
+    ForwardKeyboardEvent(event);
+}
+
 void TestingAutomationProvider::WaitForTabCountToBecome(
     int browser_handle,
     int target_tab_count,
@@ -4379,7 +4527,7 @@
 
 void TestingAutomationProvider::WaitForInfoBarCount(
     int tab_handle,
-    int target_count,
+    size_t target_count,
     IPC::Message* reply_message) {
   if (!tab_tracker_->ContainsHandle(tab_handle)) {
     AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
@@ -4463,6 +4611,11 @@
   profile_->ClearTheme();
 }
 
+void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle(
+    IPC::Message* reply_message) {
+  new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message);
+}
+
 // TODO(brettw) change this to accept GURLs when history supports it
 void TestingAutomationProvider::OnRedirectQueryComplete(
     HistoryService::Handle request_handle,
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index 6bda672..bd42171 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,7 +17,6 @@
 #include "chrome/common/page_type.h"
 
 class DictionaryValue;
-class ImporterHost;
 class TemplateURLModel;
 
 // This is an automation provider containing testing calls.
@@ -138,11 +137,11 @@
 
   // Retrieves the visible text from the autocomplete edit.
   void GetAutocompleteEditText(int autocomplete_edit_handle,
-                               bool* success, std::wstring* text);
+                               bool* success, string16* text);
 
   // Sets the visible text from the autocomplete edit.
   void SetAutocompleteEditText(int autocomplete_edit_handle,
-                               const std::wstring& text,
+                               const string16& text,
                                bool* success);
 
   // Retrieves if a query to an autocomplete provider is in progress.
@@ -291,12 +290,13 @@
                       bool* success);
 
   // Retrieves the number of info-bars currently showing in |count|.
-  void GetInfoBarCount(int handle, int* count);
+  void GetInfoBarCount(int handle, size_t* count);
 
   // Causes a click on the "accept" button of the info-bar at |info_bar_index|.
   // If |wait_for_navigation| is true, it sends the reply after a navigation has
   // occurred.
-  void ClickInfoBarAccept(int handle, int info_bar_index,
+  void ClickInfoBarAccept(int handle,
+                          size_t info_bar_index,
                           bool wait_for_navigation,
                           IPC::Message* reply_message);
 
@@ -371,7 +371,12 @@
 
   // Method ptr for json handlers.
   // Uses the JSON interface for input/output.
-  typedef void (TestingAutomationProvider::*JsonHandler)(
+  typedef void (TestingAutomationProvider::*JsonHandler)(DictionaryValue*,
+                                                         IPC::Message*);
+
+  // Method ptr for json handlers that take a browser argument.
+  // Uses the JSON interface for input/output.
+  typedef void (TestingAutomationProvider::*BrowserJsonHandler)(
       Browser* browser,
       DictionaryValue*,
       IPC::Message*);
@@ -688,9 +693,9 @@
 
   // Return the map from the internal data representation to the string value
   // of auto fill fields and credit card fields.
-  static std::map<AutoFillFieldType, std::wstring>
+  static std::map<AutoFillFieldType, std::string>
       GetAutoFillFieldToStringMap();
-  static std::map<AutoFillFieldType, std::wstring>
+  static std::map<AutoFillFieldType, std::string>
       GetCreditCardFieldToStringMap();
 
   // Get a list of active HTML5 notifications.
@@ -749,12 +754,31 @@
                            DictionaryValue* args,
                            IPC::Message* reply_message);
 
+  // Sends a web keyboard event to the active tab. This should not trigger any
+  // browser hotkeys.
+  // Uses the JSON interface for input/output.
+  void SendKeyEventToActiveTab(Browser* browser,
+                               DictionaryValue* args,
+                               IPC::Message* reply_message);
+
+#if defined(OS_CHROMEOS)
+  void LoginAsGuest(DictionaryValue* args, IPC::Message* reply_message);
+
+  void Login(DictionaryValue* args, IPC::Message* reply_message);
+
+  void Logout(DictionaryValue* args, IPC::Message* reply_message);
+
+  void ScreenLock(DictionaryValue* args, IPC::Message* reply_message);
+
+  void ScreenUnlock(DictionaryValue* args, IPC::Message* reply_message);
+#endif  // defined(OS_CHROMEOS)
+
   void WaitForTabCountToBecome(int browser_handle,
                                int target_tab_count,
                                IPC::Message* reply_message);
 
   void WaitForInfoBarCount(int tab_handle,
-                           int target_count,
+                           size_t target_count,
                            IPC::Message* reply_message);
 
   // Gets the current used encoding name of the page in the specified tab.
@@ -774,6 +798,8 @@
   // Resets to the default theme.
   void ResetToDefaultTheme();
 
+  void WaitForProcessLauncherThreadToGoIdle(IPC::Message* reply_message);
+
   // Callback for history redirect queries.
   virtual void OnRedirectQueryComplete(
       HistoryService::Handle request_handle,
@@ -803,8 +829,8 @@
 
   NotificationRegistrar registrar_;
 
-  // Used to import settings from browser profiles.
-  scoped_refptr<ImporterHost> importer_host_;
+  // Used to enumerate browser profiles.
+  scoped_refptr<ImporterList> importer_list_;
 
   // The stored data for the ImportSettings operation.
   ImportSettingsData import_settings_data_;
diff --git a/chrome/browser/automation/testing_automation_provider_chromeos.cc b/chrome/browser/automation/testing_automation_provider_chromeos.cc
new file mode 100644
index 0000000..c34f02a
--- /dev/null
+++ b/chrome/browser/automation/testing_automation_provider_chromeos.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/automation/testing_automation_provider.h"
+
+#include "base/values.h"
+#include "chrome/browser/automation/automation_provider_json.h"
+#include "chrome/browser/automation/automation_provider_observers.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/screen_lock_library.h"
+#include "chrome/browser/chromeos/login/existing_user_controller.h"
+
+void TestingAutomationProvider::LoginAsGuest(DictionaryValue* args,
+                                             IPC::Message* reply_message) {
+  chromeos::ExistingUserController* controller =
+      chromeos::ExistingUserController::current_controller();
+  // Set up an observer (it will delete itself).
+  new LoginManagerObserver(this, reply_message);
+  controller->LoginAsGuest();
+}
+
+void TestingAutomationProvider::Login(DictionaryValue* args,
+                                      IPC::Message* reply_message) {
+  std::string username, password;
+  if (!args->GetString("username", &username) ||
+      !args->GetString("password", &password)) {
+    AutomationJSONReply(this, reply_message).SendError(
+        "Invalid or missing args");
+    return;
+  }
+
+  chromeos::ExistingUserController* controller =
+      chromeos::ExistingUserController::current_controller();
+  // Set up an observer (it will delete itself).
+  new LoginManagerObserver(this, reply_message);
+  controller->Login(username, password);
+}
+
+// Logging out could have other undesirable side effects: session_manager is
+// killed, so its children, including chrome and the window manager will also
+// be killed. SSH connections might be closed, the test binary might be killed.
+void TestingAutomationProvider::Logout(DictionaryValue* args,
+                                       IPC::Message* reply_message) {
+  // Send success before stopping session because if we're a child of
+  // session manager then we'll die when the session is stopped.
+  AutomationJSONReply(this, reply_message).SendSuccess(NULL);
+  if (chromeos::CrosLibrary::Get()->EnsureLoaded())
+    chromeos::CrosLibrary::Get()->GetLoginLibrary()->StopSession("");
+}
+
+void TestingAutomationProvider::ScreenLock(DictionaryValue* args,
+                                           IPC::Message* reply_message) {
+  new ScreenLockUnlockObserver(this, reply_message, true);
+  chromeos::CrosLibrary::Get()->GetScreenLockLibrary()->
+      NotifyScreenLockRequested();
+}
+
+void TestingAutomationProvider::ScreenUnlock(DictionaryValue* args,
+                                             IPC::Message* reply_message) {
+  new ScreenLockUnlockObserver(this, reply_message, false);
+  chromeos::CrosLibrary::Get()->GetScreenLockLibrary()->
+      NotifyScreenUnlockRequested();
+}
diff --git a/chrome/browser/automation/testing_automation_provider_gtk.cc b/chrome/browser/automation/testing_automation_provider_gtk.cc
index b57d1b9..f00025f 100644
--- a/chrome/browser/automation/testing_automation_provider_gtk.cc
+++ b/chrome/browser/automation/testing_automation_provider_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,8 @@
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/automation/automation_window_tracker.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/view_id_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
 
 void TestingAutomationProvider::ActivateWindow(int handle) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/automation/testing_automation_provider_mac.mm b/chrome/browser/automation/testing_automation_provider_mac.mm
index 094dfff..d8cbe79 100644
--- a/chrome/browser/automation/testing_automation_provider_mac.mm
+++ b/chrome/browser/automation/testing_automation_provider_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,16 +6,16 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "base/logging.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/automation/automation_browser_tracker.h"
 #include "chrome/browser/automation/automation_window_tracker.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/tab_window_controller.h"
+#include "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 void TestingAutomationProvider::ActivateWindow(int handle) {
   NOTIMPLEMENTED();
@@ -25,7 +25,11 @@
                                                   bool* is_maximized,
                                                   bool* success) {
   *success = false;
-  NOTIMPLEMENTED();
+  NSWindow* window = window_tracker_->GetResource(handle);
+  if (!window)
+    return;
+  *is_maximized = [window isZoomed];
+  *success = true;
 }
 
 void TestingAutomationProvider::TerminateSession(int handle, bool* success) {
@@ -66,9 +70,10 @@
   // not bottom left, to match other platforms.
   rect.origin.y += rect.size.height;
   CGFloat coord_sys_height;
-  if (screen_coordinates) {
+  if (screen_coordinates && [[NSScreen screens] count] > 0) {
     rect.origin = [window convertBaseToScreen:rect.origin];
-    coord_sys_height = [[window screen] frame].size.height;
+    coord_sys_height =
+        [[[NSScreen screens] objectAtIndex:0] frame].size.height;
   } else {
     coord_sys_height = [window frame].size.height;
   }
@@ -80,9 +85,20 @@
 
 void TestingAutomationProvider::GetWindowBounds(int handle,
                                                 gfx::Rect* bounds,
-                                                bool* result) {
-  *result = false;
-  NOTIMPLEMENTED();
+                                                bool* success) {
+  *success = false;
+  NSWindow* window = window_tracker_->GetResource(handle);
+  if (window) {
+    // Move rect to reflect flipped coordinate system.
+    if ([[NSScreen screens] count] > 0) {
+      NSRect rect = [window frame];
+      rect.origin.y =
+          [[[NSScreen screens] objectAtIndex:0] frame].size.height -
+              rect.origin.y - rect.size.height;
+      *bounds = gfx::Rect(NSRectToCGRect(rect));
+      *success = true;
+    }
+  }
 }
 
 void TestingAutomationProvider::SetWindowBounds(int handle,
diff --git a/chrome/browser/automation/testing_automation_provider_views.cc b/chrome/browser/automation/testing_automation_provider_views.cc
index f8631cf..99b4065 100644
--- a/chrome/browser/automation/testing_automation_provider_views.cc
+++ b/chrome/browser/automation/testing_automation_provider_views.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,10 +7,10 @@
 #include "chrome/browser/automation/automation_browser_tracker.h"
 #include "chrome/browser/automation/automation_window_tracker.h"
 #include "chrome/browser/browser_window.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 #include "chrome/common/automation_messages.h"
-#include "gfx/point.h"
+#include "ui/gfx/point.h"
 #include "views/controls/menu/menu_wrapper.h"
 #include "views/view.h"
 #include "views/widget/root_view.h"
@@ -131,7 +131,7 @@
           views::View::ConvertPointToScreen(view, &point);
         else
           views::View::ConvertPointToView(view, root_view, &point);
-        *bounds = view->GetLocalBounds(false);
+        *bounds = view->GetContentsBounds();
         bounds->set_origin(point);
       }
     }
diff --git a/chrome/browser/automation/ui_controls.h b/chrome/browser/automation/ui_controls.h
index 3664567..7d7b0bf 100644
--- a/chrome/browser/automation/ui_controls.h
+++ b/chrome/browser/automation/ui_controls.h
@@ -12,9 +12,9 @@
 #include <wtypes.h>
 #endif
 
-#include "app/keyboard_codes.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/point.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
 
 #if defined(TOOLKIT_VIEWS)
 namespace views {
@@ -46,13 +46,13 @@
 // If you're writing a test chances are you want the variant in ui_test_utils.
 // See it for details.
 bool SendKeyPress(gfx::NativeWindow window,
-                  app::KeyboardCode key,
+                  ui::KeyboardCode key,
                   bool control,
                   bool shift,
                   bool alt,
                   bool command);
 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
-                                app::KeyboardCode key,
+                                ui::KeyboardCode key,
                                 bool control,
                                 bool shift,
                                 bool alt,
diff --git a/chrome/browser/automation/ui_controls_internal.h b/chrome/browser/automation/ui_controls_internal.h
index 7299b9b..5ec9a81 100644
--- a/chrome/browser/automation/ui_controls_internal.h
+++ b/chrome/browser/automation/ui_controls_internal.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_AUTOMATION_UI_CONTROLS_INTERNAL_H_
 #define CHROME_BROWSER_AUTOMATION_UI_CONTROLS_INTERNAL_H_
 
-#include "base/message_loop.h"
+#include "base/task.h"
 #include "chrome/browser/automation/ui_controls.h"
 
 namespace ui_controls {
@@ -26,6 +26,6 @@
   Task* followup_;
 };
 
-}  // ui_controls
+}  // namespace ui_controls
 
 #endif  // CHROME_BROWSER_AUTOMATION_UI_CONTROLS_INTERNAL_H_
diff --git a/chrome/browser/automation/ui_controls_linux.cc b/chrome/browser/automation/ui_controls_linux.cc
index 21cd0dd..97649ee 100644
--- a/chrome/browser/automation/ui_controls_linux.cc
+++ b/chrome/browser/automation/ui_controls_linux.cc
@@ -1,19 +1,19 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/automation/ui_controls.h"
 
-#include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
 
-#include "app/event_synthesis_gtk.h"
-#include "gfx/rect.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "chrome/browser/automation/ui_controls_internal.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/automation_constants.h"
+#include "ui/base/gtk/event_synthesis_gtk.h"
+#include "ui/gfx/rect.h"
 
 #if defined(TOOLKIT_VIEWS)
 #include "views/view.h"
@@ -96,7 +96,7 @@
 namespace ui_controls {
 
 bool SendKeyPress(gfx::NativeWindow window,
-                  app::KeyboardCode key,
+                  ui::KeyboardCode key,
                   bool control, bool shift, bool alt, bool command) {
   DCHECK(command == false);  // No command key on Linux
   GdkWindow* event_window = NULL;
@@ -124,8 +124,7 @@
   }
 
   std::vector<GdkEvent*> events;
-  app::SynthesizeKeyPressEvents(event_window, key, control, shift, alt,
-                                 &events);
+  ui::SynthesizeKeyPressEvents(event_window, key, control, shift, alt, &events);
   for (std::vector<GdkEvent*>::iterator iter = events.begin();
        iter != events.end(); ++iter) {
     gdk_event_put(*iter);
@@ -137,7 +136,7 @@
 }
 
 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
-                                app::KeyboardCode key,
+                                ui::KeyboardCode key,
                                 bool control, bool shift,
                                 bool alt, bool command,
                                 Task* task) {
diff --git a/chrome/browser/automation/ui_controls_mac.mm b/chrome/browser/automation/ui_controls_mac.mm
index 03f7e2c..6e8bcc9 100644
--- a/chrome/browser/automation/ui_controls_mac.mm
+++ b/chrome/browser/automation/ui_controls_mac.mm
@@ -8,10 +8,10 @@
 #include <mach/mach_time.h>
 #include <vector>
 
-#include "app/keyboard_code_conversion_mac.h"
 #include "base/message_loop.h"
 #include "chrome/browser/automation/ui_controls_internal.h"
 #include "chrome/browser/browser_thread.h"
+#include "ui/base/keycodes/keyboard_code_conversion_mac.h"
 
 // Implementation details: We use [NSApplication sendEvent:] instead
 // of [NSApplication postEvent:atStart:] so that the event gets sent
@@ -76,11 +76,11 @@
 // Creates and returns an autoreleased key event.
 NSEvent* SynthesizeKeyEvent(NSWindow* window,
                             bool keyDown,
-                            app::KeyboardCode keycode,
+                            ui::KeyboardCode keycode,
                             NSUInteger flags) {
   unichar character;
   unichar characterIgnoringModifiers;
-  int macKeycode = app::MacKeyCodeForWindowsKeyCode(
+  int macKeycode = ui::MacKeyCodeForWindowsKeyCode(
       keycode, flags, &character, &characterIgnoringModifiers);
 
   if (macKeycode < 0)
@@ -97,8 +97,8 @@
 
   // Modifier keys generate NSFlagsChanged event rather than
   // NSKeyDown/NSKeyUp events.
-  if (keycode == app::VKEY_CONTROL || keycode == app::VKEY_SHIFT ||
-      keycode == app::VKEY_MENU || keycode == app::VKEY_COMMAND)
+  if (keycode == ui::VKEY_CONTROL || keycode == ui::VKEY_SHIFT ||
+      keycode == ui::VKEY_MENU || keycode == ui::VKEY_COMMAND)
     type = NSFlagsChanged;
 
   // For events other than mouse moved, [event locationInWindow] is
@@ -121,7 +121,7 @@
 
 // Creates the proper sequence of autoreleased key events for a key down + up.
 void SynthesizeKeyEventsSequence(NSWindow* window,
-                                 app::KeyboardCode keycode,
+                                 ui::KeyboardCode keycode,
                                  bool control,
                                  bool shift,
                                  bool alt,
@@ -131,25 +131,25 @@
   NSUInteger flags = 0;
   if (control) {
     flags |= NSControlKeyMask;
-    event = SynthesizeKeyEvent(window, true, app::VKEY_CONTROL, flags);
+    event = SynthesizeKeyEvent(window, true, ui::VKEY_CONTROL, flags);
     DCHECK(event);
     events->push_back(event);
   }
   if (shift) {
     flags |= NSShiftKeyMask;
-    event = SynthesizeKeyEvent(window, true, app::VKEY_SHIFT, flags);
+    event = SynthesizeKeyEvent(window, true, ui::VKEY_SHIFT, flags);
     DCHECK(event);
     events->push_back(event);
   }
   if (alt) {
     flags |= NSAlternateKeyMask;
-    event = SynthesizeKeyEvent(window, true, app::VKEY_MENU, flags);
+    event = SynthesizeKeyEvent(window, true, ui::VKEY_MENU, flags);
     DCHECK(event);
     events->push_back(event);
   }
   if (command) {
     flags |= NSCommandKeyMask;
-    event = SynthesizeKeyEvent(window, true, app::VKEY_COMMAND, flags);
+    event = SynthesizeKeyEvent(window, true, ui::VKEY_COMMAND, flags);
     DCHECK(event);
     events->push_back(event);
   }
@@ -163,25 +163,25 @@
 
   if (command) {
     flags &= ~NSCommandKeyMask;
-    event = SynthesizeKeyEvent(window, false, app::VKEY_COMMAND, flags);
+    event = SynthesizeKeyEvent(window, false, ui::VKEY_COMMAND, flags);
     DCHECK(event);
     events->push_back(event);
   }
   if (alt) {
     flags &= ~NSAlternateKeyMask;
-    event = SynthesizeKeyEvent(window, false, app::VKEY_MENU, flags);
+    event = SynthesizeKeyEvent(window, false, ui::VKEY_MENU, flags);
     DCHECK(event);
     events->push_back(event);
   }
   if (shift) {
     flags &= ~NSShiftKeyMask;
-    event = SynthesizeKeyEvent(window, false, app::VKEY_SHIFT, flags);
+    event = SynthesizeKeyEvent(window, false, ui::VKEY_SHIFT, flags);
     DCHECK(event);
     events->push_back(event);
   }
   if (control) {
     flags &= ~NSControlKeyMask;
-    event = SynthesizeKeyEvent(window, false, app::VKEY_CONTROL, flags);
+    event = SynthesizeKeyEvent(window, false, ui::VKEY_CONTROL, flags);
     DCHECK(event);
     events->push_back(event);
   }
@@ -221,7 +221,7 @@
 namespace ui_controls {
 
 bool SendKeyPress(gfx::NativeWindow window,
-                  app::KeyboardCode key,
+                  ui::KeyboardCode key,
                   bool control,
                   bool shift,
                   bool alt,
@@ -234,7 +234,7 @@
 // Win and Linux implement a SendKeyPress() this as a
 // SendKeyPressAndRelease(), so we should as well (despite the name).
 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
-                                app::KeyboardCode key,
+                                ui::KeyboardCode key,
                                 bool control,
                                 bool shift,
                                 bool alt,
diff --git a/chrome/browser/automation/ui_controls_win.cc b/chrome/browser/automation/ui_controls_win.cc
index b03c97b..127ea6d 100644
--- a/chrome/browser/automation/ui_controls_win.cc
+++ b/chrome/browser/automation/ui_controls_win.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/browser/automation/ui_controls.h"
 
-#include "app/keyboard_code_conversion_win.h"
-#include "app/keyboard_codes.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/task.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/keycodes/keyboard_code_conversion_win.h"
 #include "views/view.h"
 
 namespace ui_controls {
@@ -139,10 +139,10 @@
 
 // Populate the INPUT structure with the appropriate keyboard event
 // parameters required by SendInput
-bool FillKeyboardInput(app::KeyboardCode key, INPUT* input, bool key_up) {
+bool FillKeyboardInput(ui::KeyboardCode key, INPUT* input, bool key_up) {
   memset(input, 0, sizeof(INPUT));
   input->type = INPUT_KEYBOARD;
-  input->ki.wVk = app::WindowsKeyCodeForKeyboardCode(key);
+  input->ki.wVk = ui::WindowsKeyCodeForKeyboardCode(key);
   input->ki.dwFlags = key_up ? KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP :
                                KEYEVENTF_EXTENDEDKEY;
 
@@ -150,7 +150,7 @@
 }
 
 // Send a key event (up/down)
-bool SendKeyEvent(app::KeyboardCode key, bool up) {
+bool SendKeyEvent(ui::KeyboardCode key, bool up) {
   INPUT input = { 0 };
 
   if (!FillKeyboardInput(key, &input, up))
@@ -162,7 +162,7 @@
   return true;
 }
 
-bool SendKeyPressImpl(app::KeyboardCode key,
+bool SendKeyPressImpl(ui::KeyboardCode key,
                       bool control, bool shift, bool alt,
                       Task* task) {
   scoped_refptr<InputDispatcher> dispatcher(
@@ -173,7 +173,7 @@
   // exists, send the key event directly there.
   HWND popup_menu = ::FindWindow(L"#32768", 0);
   if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) {
-    WPARAM w_param = app::WindowsKeyCodeForKeyboardCode(key);
+    WPARAM w_param = ui::WindowsKeyCodeForKeyboardCode(key);
     LPARAM l_param = 0;
     ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param);
     ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param);
@@ -187,19 +187,19 @@
 
   UINT i = 0;
   if (control) {
-    if (!FillKeyboardInput(app::VKEY_CONTROL, &input[i], false))
+    if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], false))
       return false;
     i++;
   }
 
   if (shift) {
-    if (!FillKeyboardInput(app::VKEY_SHIFT, &input[i], false))
+    if (!FillKeyboardInput(ui::VKEY_SHIFT, &input[i], false))
       return false;
     i++;
   }
 
   if (alt) {
-    if (!FillKeyboardInput(app::VKEY_MENU, &input[i], false))
+    if (!FillKeyboardInput(ui::VKEY_MENU, &input[i], false))
       return false;
     i++;
   }
@@ -213,19 +213,19 @@
   i++;
 
   if (alt) {
-    if (!FillKeyboardInput(app::VKEY_MENU, &input[i], true))
+    if (!FillKeyboardInput(ui::VKEY_MENU, &input[i], true))
       return false;
     i++;
   }
 
   if (shift) {
-    if (!FillKeyboardInput(app::VKEY_SHIFT, &input[i], true))
+    if (!FillKeyboardInput(ui::VKEY_SHIFT, &input[i], true))
       return false;
     i++;
   }
 
   if (control) {
-    if (!FillKeyboardInput(app::VKEY_CONTROL, &input[i], true))
+    if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], true))
       return false;
     i++;
   }
@@ -325,14 +325,14 @@
 
 // public functions -----------------------------------------------------------
 
-bool SendKeyPress(gfx::NativeWindow window, app::KeyboardCode key,
+bool SendKeyPress(gfx::NativeWindow window, ui::KeyboardCode key,
                   bool control, bool shift, bool alt, bool command) {
   DCHECK(command == false);  // No command key on Windows
   return SendKeyPressImpl(key, control, shift, alt, NULL);
 }
 
 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
-                                app::KeyboardCode key,
+                                ui::KeyboardCode key,
                                 bool control, bool shift, bool alt,
                                 bool command,
                                 Task* task) {
diff --git a/chrome/browser/automation/url_request_automation_job.cc b/chrome/browser/automation/url_request_automation_job.cc
index 7e2bc57..cd5db32 100644
--- a/chrome/browser/automation/url_request_automation_job.cc
+++ b/chrome/browser/automation/url_request_automation_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -149,7 +149,8 @@
   if (message_filter_.get()) {
     if (!is_pending()) {
       message_filter_->Send(new AutomationMsg_RequestEnd(tab_, id_,
-          URLRequestStatus(URLRequestStatus::CANCELED, net::ERR_ABORTED)));
+          net::URLRequestStatus(net::URLRequestStatus::CANCELED,
+                                net::ERR_ABORTED)));
     }
   }
   DisconnectFromMessageFilter();
@@ -169,7 +170,7 @@
 
   if (message_filter_) {
     message_filter_->Send(new AutomationMsg_RequestRead(tab_, id_, buf_size));
-    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
   } else {
     MessageLoop::current()->PostTask(
         FROM_HERE,
@@ -233,6 +234,20 @@
   return true;
 }
 
+uint64 URLRequestAutomationJob::GetUploadProgress() const {
+  if (request_ && request_->status().is_success()) {
+    // We don't support incremental progress notifications in ChromeFrame. When
+    // we receive a response for the POST request from Chromeframe, it means
+    // that the upload is fully complete.
+    ResourceDispatcherHostRequestInfo* request_info =
+        ResourceDispatcherHost::InfoForRequest(request_);
+    if (request_info) {
+      return request_info->upload_size();
+    }
+  }
+  return 0;
+}
+
 bool URLRequestAutomationJob::MayFilterMessage(const IPC::Message& message,
                                                int* request_id) {
   switch (message.type()) {
@@ -292,7 +307,7 @@
 
   // The request completed, and we have all the data.
   // Clear any IO pending status.
-  SetStatus(URLRequestStatus());
+  SetStatus(net::URLRequestStatus());
 
   if (pending_buf_ && pending_buf_->data()) {
     DCHECK_GE(pending_buf_size_, bytes.size());
@@ -309,7 +324,7 @@
 }
 
 void URLRequestAutomationJob::OnRequestEnd(
-    int id, const URLRequestStatus& status) {
+    int id, const net::URLRequestStatus& status) {
 #ifndef NDEBUG
   std::string url;
   if (request_)
@@ -322,7 +337,7 @@
   // OnSSLCertificateError().  Right now we don't have the certificate
   // so we don't.  We could possibly call OnSSLCertificateError with a NULL
   // certificate, but I'm not sure if all implementations expect it.
-  // if (status.status() == URLRequestStatus::FAILED &&
+  // if (status.status() == net::URLRequestStatus::FAILED &&
   //    net::IsCertificateError(status.os_error()) && request_->delegate()) {
   //  request_->delegate()->OnSSLCertificateError(request_, status.os_error());
   // }
@@ -381,8 +396,8 @@
   DCHECK(!is_pending());
 
   if (!request_) {
-    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
-        net::ERR_FAILED));
+    NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                           net::ERR_FAILED));
     return;
   }
 
diff --git a/chrome/browser/automation/url_request_automation_job.h b/chrome/browser/automation/url_request_automation_job.h
index f1e1aa1..9dab13a 100644
--- a/chrome/browser/automation/url_request_automation_job.h
+++ b/chrome/browser/automation/url_request_automation_job.h
@@ -45,6 +45,7 @@
   virtual void GetResponseInfo(net::HttpResponseInfo* info);
   virtual int GetResponseCode() const;
   virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
+  virtual uint64 GetUploadProgress() const;
 
   // Peek and process automation messages for URL requests.
   static bool MayFilterMessage(const IPC::Message& message, int* request_id);
@@ -120,7 +121,7 @@
 
   // Contains the request status code, which is eventually passed  to the http
   // stack when we receive a Read request for a completed job.
-  URLRequestStatus request_status_;
+  net::URLRequestStatus request_status_;
 
   ScopedRunnableMethodFactory<URLRequestAutomationJob> method_factory_;
 
diff --git a/chrome/browser/background_application_list_model.cc b/chrome/browser/background_application_list_model.cc
index 0392d09..83d1e27 100644
--- a/chrome/browser/background_application_list_model.cc
+++ b/chrome/browser/background_application_list_model.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <set>
 
-#include "app/l10n_util_collator.h"
 #include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -16,13 +15,12 @@
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "chrome/common/pref_names.h"
+#include "ui/base/l10n/l10n_util_collator.h"
 
 class ExtensionNameComparator {
  public:
diff --git a/chrome/browser/background_contents_service.cc b/chrome/browser/background_contents_service.cc
index df6db03..84fca87 100644
--- a/chrome/browser/background_contents_service.cc
+++ b/chrome/browser/background_contents_service.cc
@@ -113,10 +113,24 @@
       DCHECK(IsTracked(Details<BackgroundContents>(details).ptr()));
       RegisterBackgroundContents(Details<BackgroundContents>(details).ptr());
       break;
-    case NotificationType::EXTENSION_UNLOADED:
-      ShutdownAssociatedBackgroundContents(
-          ASCIIToUTF16(
-              Details<UnloadedExtensionInfo>(details)->extension->id()));
+   case NotificationType::EXTENSION_UNLOADED:
+      switch (Details<UnloadedExtensionInfo>(details)->reason) {
+        case UnloadedExtensionInfo::DISABLE:  // Intentionally fall through.
+        case UnloadedExtensionInfo::UNINSTALL:
+          ShutdownAssociatedBackgroundContents(
+              ASCIIToUTF16(
+                  Details<UnloadedExtensionInfo>(details)->extension->id()));
+          break;
+        case UnloadedExtensionInfo::UPDATE:
+          // Leave BackgroundContents in place
+          break;
+        default:
+          NOTREACHED();
+          ShutdownAssociatedBackgroundContents(
+              ASCIIToUTF16(
+                  Details<UnloadedExtensionInfo>(details)->extension->id()));
+          break;
+      }
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/background_contents_service.h b/chrome/browser/background_contents_service.h
index 7fe16ac..3a167c6 100644
--- a/chrome/browser/background_contents_service.h
+++ b/chrome/browser/background_contents_service.h
@@ -84,6 +84,8 @@
                            TestApplicationIDLinkage);
   FRIEND_TEST_ALL_PREFIXES(TaskManagerBrowserTest,
                            NoticeBGContentsChanges);
+  FRIEND_TEST_ALL_PREFIXES(TaskManagerBrowserTest,
+                           KillBGContents);
 
   // Registers for various notifications.
   void StartObserving(Profile* profile);
diff --git a/chrome/browser/background_contents_service_unittest.cc b/chrome/browser/background_contents_service_unittest.cc
index 566b74b..0e55dd3 100644
--- a/chrome/browser/background_contents_service_unittest.cc
+++ b/chrome/browser/background_contents_service_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
 
 #include "base/basictypes.h"
 #include "base/command_line.h"
@@ -11,7 +12,6 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/tab_contents/background_contents.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/testing_browser_process.h"
 #include "chrome/test/testing_profile.h"
@@ -138,7 +138,6 @@
     contents->Navigate(url2);
     EXPECT_EQ(1U, GetPrefs(&profile)->size());
     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
-
   }
   // Contents are deleted, url should persist.
   EXPECT_EQ(1U, GetPrefs(&profile)->size());
diff --git a/chrome/browser/background_mode_manager.cc b/chrome/browser/background_mode_manager.cc
index 3af5779..fc0e07f 100644
--- a/chrome/browser/background_mode_manager.cc
+++ b/chrome/browser/background_mode_manager.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include <string>
+
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/logging.h"
@@ -14,7 +14,6 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/status_icons/status_icon.h"
 #include "chrome/browser/status_icons/status_tray.h"
@@ -26,6 +25,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 void BackgroundModeManager::OnApplicationDataChanged(
     const Extension* extension) {
@@ -67,15 +68,9 @@
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest))
     OnBackgroundAppLoaded();
 
-  // When an extension is installed, make sure launch on startup is properly
-  // set if appropriate. Likewise, turn off launch on startup when the last
-  // background app is uninstalled.
-  registrar_.Add(this, NotificationType::EXTENSION_INSTALLED,
-                 Source<Profile>(profile));
-  registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED,
-                 Source<Profile>(profile));
   // Listen for when extensions are loaded/unloaded so we can track the
-  // number of background apps.
+  // number of background apps and modify our keep-alive and launch-on-startup
+  // state appropriately.
   registrar_.Add(this, NotificationType::EXTENSION_LOADED,
                  Source<Profile>(profile));
   registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
@@ -116,7 +111,10 @@
 
       // On a Mac, we use 'login items' mechanism which has user-facing UI so we
       // don't want to stomp on user choice every time we start and load
-      // registered extensions.
+      // registered extensions. This means that if a background app is removed
+      // or added while Chrome is not running, we could leave Chrome in the
+      // wrong state, but this is better than constantly forcing Chrome to
+      // launch on startup even after the user removes the LoginItem manually.
 #if !defined(OS_MACOSX)
       EnableLaunchOnStartup(background_app_count_ > 0);
 #endif
@@ -124,26 +122,25 @@
     case NotificationType::EXTENSION_LOADED:
       if (BackgroundApplicationListModel::IsBackgroundApp(
               *Details<Extension>(details).ptr())) {
+        // Extensions loaded after the ExtensionsService is ready should be
+        // treated as new installs.
+        if (profile_->GetExtensionService()->is_ready())
+          OnBackgroundAppInstalled();
         OnBackgroundAppLoaded();
       }
       break;
     case NotificationType::EXTENSION_UNLOADED:
       if (BackgroundApplicationListModel::IsBackgroundApp(
               *Details<UnloadedExtensionInfo>(details)->extension)) {
+        Details<UnloadedExtensionInfo> info =
+            Details<UnloadedExtensionInfo>(details);
+        // If we already got an unload notification when it was disabled, ignore
+        // this one.
+        // TODO(atwilson): Change BackgroundModeManager to use
+        // BackgroundApplicationListModel instead of tracking the count here.
+        if (info->already_disabled)
+          return;
         OnBackgroundAppUnloaded();
-      }
-      break;
-    case NotificationType::EXTENSION_INSTALLED:
-      if (BackgroundApplicationListModel::IsBackgroundApp(
-              *Details<Extension>(details).ptr())) {
-        OnBackgroundAppInstalled();
-      }
-      break;
-    case NotificationType::EXTENSION_UNINSTALLED:
-      if (Extension::HasApiPermission(
-            Details<UninstalledExtensionInfo>(details).ptr()->
-                extension_api_permissions,
-            Extension::kBackgroundPermission)) {
         OnBackgroundAppUninstalled();
       }
       break;
@@ -270,7 +267,7 @@
     return;
 
   // Create a context menu item for Chrome.
-  menus::SimpleMenuModel* menu = new menus::SimpleMenuModel(this);
+  ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(this);
   // Add About item
   menu->AddItem(IDC_ABOUT, l10n_util::GetStringFUTF16(IDS_ABOUT,
       l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
@@ -307,7 +304,7 @@
 
 bool BackgroundModeManager::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   // No accelerators for status icon context menus.
   return false;
 }
@@ -316,6 +313,7 @@
   if (status_icon_)
     status_tray_->RemoveStatusIcon(status_icon_);
   status_icon_ = NULL;
+  context_menu_ = NULL;  // Do not delete, points within status_icon_
 }
 
 void BackgroundModeManager::ExecuteApplication(int item) {
@@ -342,7 +340,7 @@
       GetBrowserWindow()->OpenOptionsDialog();
       break;
     case IDC_TASK_MANAGER:
-      GetBrowserWindow()->OpenTaskManager();
+      GetBrowserWindow()->OpenTaskManager(true);
       break;
     default:
       ExecuteApplication(item);
diff --git a/chrome/browser/background_mode_manager.h b/chrome/browser/background_mode_manager.h
index 9407d4a..b874fd6 100644
--- a/chrome/browser/background_mode_manager.h
+++ b/chrome/browser/background_mode_manager.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_BACKGROUND_MODE_MANAGER_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
 #include "base/gtest_prod_util.h"
 #include "chrome/browser/background_application_list_model.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/browser/status_icons/status_icon.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class Browser;
 class CommandLine;
@@ -38,7 +38,7 @@
 // background.
 class BackgroundModeManager
     : public NotificationObserver,
-      public menus::SimpleMenuModel::Delegate,
+      public ui::SimpleMenuModel::Delegate,
       public BackgroundApplicationListModel::Observer {
  public:
   BackgroundModeManager(Profile* profile, CommandLine* command_line);
@@ -69,7 +69,7 @@
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
   // Open an application in a new tab, opening a new window if needed.
@@ -151,7 +151,7 @@
 
   // Reference to our status icon's context menu (if any) - owned by the
   // status_icon_
-  menus::SimpleMenuModel* context_menu_;
+  ui::SimpleMenuModel* context_menu_;
 
   // Set to the position of the first application entry in the status icon's
   // context menu.
diff --git a/chrome/browser/background_mode_manager_chromeos.cc b/chrome/browser/background_mode_manager_chromeos.cc
index 8439f18..d01c70d 100644
--- a/chrome/browser/background_mode_manager_chromeos.cc
+++ b/chrome/browser/background_mode_manager_chromeos.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/background_mode_manager.h"
 
-#include "app/l10n_util.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
   NOTREACHED();
diff --git a/chrome/browser/background_mode_manager_linux.cc b/chrome/browser/background_mode_manager_linux.cc
index 3d998a6..4f4b570 100644
--- a/chrome/browser/background_mode_manager_linux.cc
+++ b/chrome/browser/background_mode_manager_linux.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <unistd.h>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/file_path.h"
@@ -14,13 +13,12 @@
 #include "base/task.h"
 #include "chrome/browser/background_mode_manager.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/shell_integration.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
-#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/background_mode_manager_mac.mm b/chrome/browser/background_mode_manager_mac.mm
index 40b958d..02e93f4 100644
--- a/chrome/browser/background_mode_manager_mac.mm
+++ b/chrome/browser/background_mode_manager_mac.mm
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/mac/mac_util.h"
 #include "chrome/browser/background_mode_manager.h"
@@ -10,6 +9,7 @@
 #include "chrome/common/app_mode_common_mac.h"
 #include "chrome/common/chrome_switches.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/background_mode_manager_unittest.cc b/chrome/browser/background_mode_manager_unittest.cc
index d47d8e0..13cf9f0 100644
--- a/chrome/browser/background_mode_manager_unittest.cc
+++ b/chrome/browser/background_mode_manager_unittest.cc
@@ -6,9 +6,7 @@
 #include "base/scoped_ptr.h"
 #include "chrome/browser/background_mode_manager.h"
 #include "chrome/browser/browser_list.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/background_mode_manager_win.cc b/chrome/browser/background_mode_manager_win.cc
index 2f10843..a957493 100644
--- a/chrome/browser/background_mode_manager_win.cc
+++ b/chrome/browser/background_mode_manager_win.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/file_path.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/common/chrome_switches.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -38,8 +38,11 @@
                              kBackgroundModeRegistrySubkey, KEY_READ);
   base::win::RegKey write_key(kBackgroundModeRegistryRootKey,
                               kBackgroundModeRegistrySubkey, KEY_WRITE);
-  if (read_key.ValueExists(key_name) && !write_key.DeleteValue(key_name))
-    NOTREACHED() << "Failed to deregister launch on login.";
+  if (read_key.ValueExists(key_name)) {
+    LONG result = write_key.DeleteValue(key_name);
+    DCHECK_EQ(ERROR_SUCCESS, result) <<
+        "Failed to deregister launch on login. error: " << result;
+  }
 }
 
 void EnableLaunchOnStartupTask::Run() {
@@ -56,13 +59,14 @@
   std::wstring new_value = executable.value() + L" --no-startup-window";
   if (read_key.ValueExists(key_name)) {
     std::wstring current_value;
-    if (read_key.ReadValue(key_name, &current_value) &&
+    if ((read_key.ReadValue(key_name, &current_value) == ERROR_SUCCESS) &&
         (current_value == new_value)) {
       return;
     }
   }
-  if (!write_key.WriteValue(key_name, new_value.c_str()))
-    NOTREACHED() << "Failed to register launch on login.";
+  LONG result = write_key.WriteValue(key_name, new_value.c_str());
+  DCHECK_EQ(ERROR_SUCCESS, result) <<
+      "Failed to register launch on login. error: " << result;
 }
 
 }  // namespace
diff --git a/chrome/browser/background_page_tracker.cc b/chrome/browser/background_page_tracker.cc
index 7bc4c4f..1337d90 100644
--- a/chrome/browser/background_page_tracker.cc
+++ b/chrome/browser/background_page_tracker.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/background_page_tracker.h"
 
+#include <set>
 #include <string>
+#include <vector>
 
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
@@ -17,7 +19,6 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
@@ -189,6 +190,10 @@
   PrefService* prefs = GetPrefService();
   std::set<std::string> keys_to_delete;
   bool pref_modified = false;
+  // If we've never set any prefs, then this is the first launch ever, so we
+  // want to automatically mark all existing extensions as acknowledged.
+  bool first_launch =
+      prefs->GetDictionary(prefs::kKnownBackgroundPages) == NULL;
   DictionaryValue* contents =
       prefs->GetMutableDictionary(prefs::kKnownBackgroundPages);
   for (DictionaryValue::key_iterator it = contents->begin_keys();
@@ -220,7 +225,7 @@
       // If we have not seen this extension ID before, add it to our list.
       if (!contents->HasKey((*iter)->id())) {
         contents->SetWithoutPathExpansion(
-            (*iter)->id(), Value::CreateBooleanValue(false));
+            (*iter)->id(), Value::CreateBooleanValue(first_launch));
         pref_modified = true;
       }
     }
@@ -239,7 +244,7 @@
          background_contents_service->GetParentApplicationId(*iter));
      if (!contents->HasKey(application_id)) {
         contents->SetWithoutPathExpansion(
-            application_id, Value::CreateBooleanValue(false));
+            application_id, Value::CreateBooleanValue(first_launch));
         pref_modified = true;
      }
   }
diff --git a/chrome/browser/background_page_tracker_unittest.cc b/chrome/browser/background_page_tracker_unittest.cc
index b7039bd..74fd7ea 100644
--- a/chrome/browser/background_page_tracker_unittest.cc
+++ b/chrome/browser/background_page_tracker_unittest.cc
@@ -6,7 +6,6 @@
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/background_page_tracker.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/test/testing_pref_service.h"
diff --git a/chrome/browser/blocked_content_container.cc b/chrome/browser/blocked_content_container.cc
index bbe712a..e39cfc6 100644
--- a/chrome/browser/blocked_content_container.cc
+++ b/chrome/browser/blocked_content_container.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/blocked_content_container.h"
 
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 // static
 const size_t BlockedContentContainer::kImpossibleNumberOfPopups = 30;
diff --git a/chrome/browser/blocked_content_container.h b/chrome/browser/blocked_content_container.h
index 714af7c..bf13334 100644
--- a/chrome/browser/blocked_content_container.h
+++ b/chrome/browser/blocked_content_container.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -84,9 +84,6 @@
   // Ignored; BlockedContentContainer doesn't display a toolbar.
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
 
-  // Ignored; BlockedContentContainer doesn't display a bookmarking star.
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
-
   // Ignored; BlockedContentContainer doesn't display a URL bar.
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
 
diff --git a/chrome/browser/bookmarks/OWNERS b/chrome/browser/bookmarks/OWNERS
new file mode 100644
index 0000000..90b3e80
--- /dev/null
+++ b/chrome/browser/bookmarks/OWNERS
@@ -0,0 +1 @@
+sky@chromium.org
diff --git a/chrome/browser/bookmarks/bookmark_codec.cc b/chrome/browser/bookmarks/bookmark_codec.cc
index 9b5be0f..d662c28 100644
--- a/chrome/browser/bookmarks/bookmark_codec.cc
+++ b/chrome/browser/bookmarks/bookmark_codec.cc
@@ -6,13 +6,13 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::Time;
 
diff --git a/chrome/browser/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/bookmarks/bookmark_context_menu_controller.cc
index 32b9d07..85a2559 100644
--- a/chrome/browser/bookmarks/bookmark_context_menu_controller.cc
+++ b/chrome/browser/bookmarks/bookmark_context_menu_controller.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/compiler_specific.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/bookmarks/bookmark_editor.h"
@@ -19,6 +18,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 BookmarkContextMenuController::BookmarkContextMenuController(
     gfx::NativeWindow parent_window,
@@ -36,7 +36,7 @@
       model_(profile->GetBookmarkModel()) {
   DCHECK(profile_);
   DCHECK(model_->IsLoaded());
-  menu_model_.reset(new menus::SimpleMenuModel(this));
+  menu_model_.reset(new ui::SimpleMenuModel(this));
   model_->AddObserver(this);
 
   BuildMenu();
@@ -244,10 +244,12 @@
        selection_[0]->GetParent() == model_->root_node());
   switch (command_id) {
     case IDC_BOOKMARK_BAR_OPEN_INCOGNITO:
-      return !profile_->IsOffTheRecord();
+      return !profile_->IsOffTheRecord() &&
+             profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
 
     case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO:
-      return HasURLs() && !profile_->IsOffTheRecord();
+      return HasURLs() && !profile_->IsOffTheRecord() &&
+             profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
 
     case IDC_BOOKMARK_BAR_OPEN_ALL:
     case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW:
@@ -280,7 +282,7 @@
 
 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   return false;
 }
 
diff --git a/chrome/browser/bookmarks/bookmark_context_menu_controller.h b/chrome/browser/bookmarks/bookmark_context_menu_controller.h
index f5f04af..5686c0d 100644
--- a/chrome/browser/bookmarks/bookmark_context_menu_controller.h
+++ b/chrome/browser/bookmarks/bookmark_context_menu_controller.h
@@ -8,10 +8,10 @@
 
 #include <vector>
 
-#include "app/menus/simple_menu_model.h"
 #include "base/basictypes.h"
 #include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
-#include "gfx/native_widget_types.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/native_widget_types.h"
 
 class PageNavigator;
 class Profile;
@@ -35,7 +35,7 @@
 // BookmarkContextMenuController creates and manages state for the context menu
 // shown for any bookmark item.
 class BookmarkContextMenuController : public BaseBookmarkModelObserver,
-                                      public menus::SimpleMenuModel::Delegate {
+                                      public ui::SimpleMenuModel::Delegate {
  public:
   // Creates the bookmark context menu.
   // |profile| is used for opening urls as well as enabling 'open incognito'.
@@ -54,13 +54,13 @@
 
   void BuildMenu();
 
-  menus::SimpleMenuModel* menu_model() const { return menu_model_.get(); }
+  ui::SimpleMenuModel* menu_model() const { return menu_model_.get(); }
 
-  // menus::SimpleMenuModel::Delegate implementation:
+  // ui::SimpleMenuModel::Delegate implementation:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
   // Accessors:
@@ -89,7 +89,7 @@
   const BookmarkNode* parent_;
   std::vector<const BookmarkNode*> selection_;
   BookmarkModel* model_;
-  scoped_ptr<menus::SimpleMenuModel> menu_model_;
+  scoped_ptr<ui::SimpleMenuModel> menu_model_;
 
   DISALLOW_COPY_AND_ASSIGN(BookmarkContextMenuController);
 };
diff --git a/chrome/browser/bookmarks/bookmark_context_menu_controller_unittest.cc b/chrome/browser/bookmarks/bookmark_context_menu_controller_unittest.cc
index 311237f..f973635 100644
--- a/chrome/browser/bookmarks/bookmark_context_menu_controller_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_context_menu_controller_unittest.cc
@@ -1,7 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+
 #include "base/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -9,16 +11,14 @@
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/page_navigator.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/testing_profile.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 #endif
 
 // PageNavigator implementation that records the URL.
diff --git a/chrome/browser/bookmarks/bookmark_drop_info.cc b/chrome/browser/bookmarks/bookmark_drop_info.cc
index 9a6106d..30d1f03 100644
--- a/chrome/browser/bookmarks/bookmark_drop_info.cc
+++ b/chrome/browser/bookmarks/bookmark_drop_info.cc
@@ -9,7 +9,7 @@
 #endif
 
 #include "base/basictypes.h"
-#include "views/event.h"
+#include "views/events/event.h"
 #include "views/view_constants.h"
 
 BookmarkDropInfo::BookmarkDropInfo(gfx::NativeWindow wnd, int top_margin)
@@ -26,7 +26,7 @@
 }
 
 void BookmarkDropInfo::Update(const views::DropTargetEvent& event) {
-  source_operations_ = event.GetSourceOperations();
+  source_operations_ = event.source_operations();
   is_control_down_ = event.IsControlDown();
   last_y_ = event.y();
 
diff --git a/chrome/browser/bookmarks/bookmark_drop_info.h b/chrome/browser/bookmarks/bookmark_drop_info.h
index 1faea29..6625f39 100644
--- a/chrome/browser/bookmarks/bookmark_drop_info.h
+++ b/chrome/browser/bookmarks/bookmark_drop_info.h
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "base/timer.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace views {
 class DropTargetEvent;
diff --git a/chrome/browser/bookmarks/bookmark_editor.h b/chrome/browser/bookmarks/bookmark_editor.h
index 63d3ccf..1816420 100644
--- a/chrome/browser/bookmarks/bookmark_editor.h
+++ b/chrome/browser/bookmarks/bookmark_editor.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "base/string16.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class BookmarkNode;
 class GURL;
diff --git a/chrome/browser/bookmarks/bookmark_folder_editor_controller.cc b/chrome/browser/bookmarks/bookmark_folder_editor_controller.cc
index a995c63..d5ae421 100644
--- a/chrome/browser/bookmarks/bookmark_folder_editor_controller.cc
+++ b/chrome/browser/bookmarks/bookmark_folder_editor_controller.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/browser/bookmarks/bookmark_folder_editor_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 BookmarkFolderEditorController::~BookmarkFolderEditorController() {
   if (model_)
diff --git a/chrome/browser/bookmarks/bookmark_folder_editor_controller.h b/chrome/browser/bookmarks/bookmark_folder_editor_controller.h
index fde7c68..ac24897 100644
--- a/chrome/browser/bookmarks/bookmark_folder_editor_controller.h
+++ b/chrome/browser/bookmarks/bookmark_folder_editor_controller.h
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
 #include "chrome/browser/ui/input_window_dialog.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Profile;
 
diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc
index 5095158..376fb69 100644
--- a/chrome/browser/bookmarks/bookmark_html_writer.cc
+++ b/chrome/browser/bookmarks/bookmark_html_writer.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/bookmarks/bookmark_html_writer.h"
 
-#include "app/l10n_util.h"
 #include "base/base64.h"
 #include "base/callback.h"
 #include "base/file_path.h"
@@ -24,6 +23,7 @@
 #include "net/base/escape.h"
 #include "net/base/file_stream.h"
 #include "net/base/net_errors.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc b/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc
index 3a0bcbf..66368ac 100644
--- a/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_html_writer_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
@@ -18,9 +17,10 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/importer/firefox2_importer.h"
 #include "chrome/test/testing_profile.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace {
 
diff --git a/chrome/browser/bookmarks/bookmark_index.cc b/chrome/browser/bookmarks/bookmark_index.cc
index c75c5fe..c247cb5 100644
--- a/chrome/browser/bookmarks/bookmark_index.cc
+++ b/chrome/browser/bookmarks/bookmark_index.cc
@@ -8,13 +8,13 @@
 #include <iterator>
 #include <list>
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/history/history_database.h"
 #include "chrome/browser/history/query_parser.h"
 #include "chrome/browser/profiles/profile.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // Used when finding the set of bookmarks that match a query. Each match
 // represents a set of terms (as an interator into the Index) matching the
diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc
index 9a58709..a2cb269 100644
--- a/chrome/browser/bookmarks/bookmark_model.cc
+++ b/chrome/browser/bookmarks/bookmark_model.cc
@@ -4,8 +4,9 @@
 
 #include "chrome/browser/bookmarks/bookmark_model.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_collator.h"
+#include <algorithm>
+#include <functional>
+
 #include "base/callback.h"
 #include "base/scoped_vector.h"
 #include "build/build_config.h"
@@ -14,11 +15,12 @@
 #include "chrome/browser/bookmarks/bookmark_storage.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/history/history_notifications.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
+#include "ui/gfx/codec/png_codec.h"
 
 using base::Time;
 
@@ -294,7 +296,7 @@
   CancelPendingFavIconLoadRequests(AsMutable(node));
 
   {
-    AutoLock url_lock(url_lock_);
+    base::AutoLock url_lock(url_lock_);
     NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(
         AsMutable(node));
     DCHECK(i != nodes_ordered_by_url_set_.end());
@@ -321,7 +323,7 @@
 
 void BookmarkModel::GetNodesByURL(const GURL& url,
                                   std::vector<const BookmarkNode*>* nodes) {
-  AutoLock url_lock(url_lock_);
+  base::AutoLock url_lock(url_lock_);
   BookmarkNode tmp_node(url);
   NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(&tmp_node);
   while (i != nodes_ordered_by_url_set_.end() && (*i)->GetURL() == url) {
@@ -342,7 +344,7 @@
 }
 
 void BookmarkModel::GetBookmarks(std::vector<GURL>* urls) {
-  AutoLock url_lock(url_lock_);
+  base::AutoLock url_lock(url_lock_);
   const GURL* last_url = NULL;
   for (NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.begin();
        i != nodes_ordered_by_url_set_.end(); ++i) {
@@ -355,12 +357,12 @@
 }
 
 bool BookmarkModel::HasBookmarks() {
-  AutoLock url_lock(url_lock_);
+  base::AutoLock url_lock(url_lock_);
   return !nodes_ordered_by_url_set_.empty();
 }
 
 bool BookmarkModel::IsBookmarked(const GURL& url) {
-  AutoLock url_lock(url_lock_);
+  base::AutoLock url_lock(url_lock_);
   return IsBookmarkedNoLock(url);
 }
 
@@ -417,7 +419,7 @@
 
   {
     // Only hold the lock for the duration of the insert.
-    AutoLock url_lock(url_lock_);
+    base::AutoLock url_lock(url_lock_);
     nodes_ordered_by_url_set_.insert(new_node);
   }
 
@@ -572,7 +574,7 @@
   root_.Add(1, other_node_);
 
   {
-    AutoLock url_lock(url_lock_);
+    base::AutoLock url_lock(url_lock_);
     // Update nodes_ordered_by_url_set_ from the nodes.
     PopulateNodesByURL(&root_);
   }
@@ -600,7 +602,7 @@
   parent->Remove(index);
   history::URLsStarredDetails details(false);
   {
-    AutoLock url_lock(url_lock_);
+    base::AutoLock url_lock(url_lock_);
     RemoveNode(node.get(), &details.changed_urls);
 
     // RemoveNode adds an entry to changed_urls for each node of type URL. As we
diff --git a/chrome/browser/bookmarks/bookmark_model.h b/chrome/browser/bookmarks/bookmark_model.h
index 3155103..51e8a17 100644
--- a/chrome/browser/bookmarks/bookmark_model.h
+++ b/chrome/browser/bookmarks/bookmark_model.h
@@ -11,10 +11,9 @@
 #include <set>
 #include <vector>
 
-#include "app/tree_node_model.h"
-#include "base/lock.h"
 #include "base/observer_list.h"
 #include "base/string16.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
 #include "chrome/browser/bookmarks/bookmark_service.h"
@@ -26,6 +25,7 @@
 #include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
+#include "ui/base/models/tree_node_model.h"
 
 class BookmarkIndex;
 class BookmarkLoadDetails;
@@ -42,7 +42,7 @@
 // BookmarkNode contains information about a starred entry: title, URL, favicon,
 // star id and type. BookmarkNodes are returned from a BookmarkModel.
 //
-class BookmarkNode : public TreeNode<BookmarkNode> {
+class BookmarkNode : public ui::TreeNode<BookmarkNode> {
   friend class BookmarkModel;
 
  public:
@@ -455,7 +455,7 @@
   // such, be sure and wrap all usage of it around url_lock_.
   typedef std::multiset<BookmarkNode*, NodeURLComparator> NodesOrderedByURLSet;
   NodesOrderedByURLSet nodes_ordered_by_url_set_;
-  Lock url_lock_;
+  base::Lock url_lock_;
 
   // Used for loading favicons and the empty history request.
   CancelableRequestConsumerTSimple<BookmarkNode*> load_consumer_;
diff --git a/chrome/browser/bookmarks/bookmark_model_unittest.cc b/chrome/browser/bookmarks/bookmark_model_unittest.cc
index ef486fb..ec769ba 100644
--- a/chrome/browser/bookmarks/bookmark_model_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_model_unittest.cc
@@ -5,8 +5,6 @@
 #include <string>
 #include <set>
 
-#include "app/tree_node_iterator.h"
-#include "app/tree_node_model.h"
 #include "base/base_paths.h"
 #include "base/file_util.h"
 #include "base/hash_tables.h"
@@ -29,6 +27,8 @@
 #include "chrome/test/model_test_utils.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/models/tree_node_model.h"
+#include "ui/base/models/tree_node_iterator.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -566,7 +566,7 @@
 namespace {
 
 // See comment in PopulateNodeFromString.
-typedef TreeNodeWithValue<BookmarkNode::Type> TestNode;
+typedef ui::TreeNodeWithValue<BookmarkNode::Type> TestNode;
 
 // Does the work of PopulateNodeFromString. index gives the index of the current
 // element in description to process.
@@ -688,7 +688,7 @@
   }
 
   void VerifyNoDuplicateIDs(BookmarkModel* model) {
-    TreeNodeIterator<const BookmarkNode> it(model->root_node());
+    ui::TreeNodeIterator<const BookmarkNode> it(model->root_node());
     base::hash_set<int64> ids;
     while (it.has_next())
       ASSERT_TRUE(ids.insert(it.Next()->id()).second);
diff --git a/chrome/browser/bookmarks/bookmark_node_data.cc b/chrome/browser/bookmarks/bookmark_node_data.cc
index 27e8683..c94d207 100644
--- a/chrome/browser/bookmarks/bookmark_node_data.cc
+++ b/chrome/browser/bookmarks/bookmark_node_data.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/clipboard/scoped_clipboard_writer.h"
 #include "base/basictypes.h"
 #include "base/pickle.h"
 #include "base/string_util.h"
@@ -15,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "net/base/escape.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
 
 #if defined(OS_MACOSX)
 #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
@@ -81,13 +81,13 @@
 
 #if defined(TOOLKIT_VIEWS)
 // static
-OSExchangeData::CustomFormat BookmarkNodeData::GetBookmarkCustomFormat() {
-  static OSExchangeData::CustomFormat format;
+ui::OSExchangeData::CustomFormat BookmarkNodeData::GetBookmarkCustomFormat() {
+  static ui::OSExchangeData::CustomFormat format;
   static bool format_valid = false;
 
   if (!format_valid) {
     format_valid = true;
-    format = OSExchangeData::RegisterCustomFormat(
+    format = ui::OSExchangeData::RegisterCustomFormat(
         BookmarkNodeData::kClipboardFormatString);
   }
   return format;
@@ -140,7 +140,7 @@
 
 #if !defined(OS_MACOSX)
 void BookmarkNodeData::WriteToClipboard(Profile* profile) const {
-  ScopedClipboardWriter scw(g_browser_process->clipboard());
+  ui::ScopedClipboardWriter scw(g_browser_process->clipboard());
 
   // If there is only one element and it is a URL, write the URL to the
   // clipboard.
@@ -166,7 +166,7 @@
 
 bool BookmarkNodeData::ReadFromClipboard() {
   std::string data;
-  Clipboard* clipboard = g_browser_process->clipboard();
+  ui::Clipboard* clipboard = g_browser_process->clipboard();
   clipboard->ReadData(kClipboardFormatString, &data);
 
   if (!data.empty()) {
@@ -194,7 +194,7 @@
 
 bool BookmarkNodeData::ClipboardContainsBookmarks() {
   return g_browser_process->clipboard()->IsFormatAvailableByString(
-      BookmarkNodeData::kClipboardFormatString, Clipboard::BUFFER_STANDARD);
+      BookmarkNodeData::kClipboardFormatString, ui::Clipboard::BUFFER_STANDARD);
 }
 #else
 void BookmarkNodeData::WriteToClipboard(Profile* profile) const {
@@ -217,7 +217,7 @@
 #endif  // !defined(OS_MACOSX)
 
 #if defined(TOOLKIT_VIEWS)
-void BookmarkNodeData::Write(Profile* profile, OSExchangeData* data) const {
+void BookmarkNodeData::Write(Profile* profile, ui::OSExchangeData* data) const {
   DCHECK(data);
 
   // If there is only one element and it is a URL, write the URL to the
@@ -236,7 +236,7 @@
   data->SetPickledData(GetBookmarkCustomFormat(), data_pickle);
 }
 
-bool BookmarkNodeData::Read(const OSExchangeData& data) {
+bool BookmarkNodeData::Read(const ui::OSExchangeData& data) {
   elements.clear();
 
   profile_path_.clear();
diff --git a/chrome/browser/bookmarks/bookmark_node_data.h b/chrome/browser/bookmarks/bookmark_node_data.h
index 8b8310d..d45054d 100644
--- a/chrome/browser/bookmarks/bookmark_node_data.h
+++ b/chrome/browser/bookmarks/bookmark_node_data.h
@@ -13,7 +13,7 @@
 #include "googleurl/src/gurl.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "app/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
 #endif
 
 class BookmarkNode;
@@ -74,7 +74,7 @@
   BookmarkNodeData();
 
 #if defined(TOOLKIT_VIEWS)
-  static OSExchangeData::CustomFormat GetBookmarkCustomFormat();
+  static ui::OSExchangeData::CustomFormat GetBookmarkCustomFormat();
 #endif
 
   // Created a BookmarkNodeData populated from the arguments.
@@ -108,10 +108,10 @@
   // use.
   // |profile| is used to identify which profile the data came from. Use a
   // value of null to indicate the data is not associated with any profile.
-  void Write(Profile* profile, OSExchangeData* data) const;
+  void Write(Profile* profile, ui::OSExchangeData* data) const;
 
   // Restores this data from the clipboard, returning true on success.
-  bool Read(const OSExchangeData& data);
+  bool Read(const ui::OSExchangeData& data);
 #endif
 
   // Writes the data for a drag to |pickle|.
diff --git a/chrome/browser/bookmarks/bookmark_node_data_unittest.cc b/chrome/browser/bookmarks/bookmark_node_data_unittest.cc
index a81d0a0..88f6936 100644
--- a/chrome/browser/bookmarks/bookmark_node_data_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_node_data_unittest.cc
@@ -1,9 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/os_exchange_data.h"
-#include "app/os_exchange_data_provider_win.h"
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
@@ -14,6 +12,8 @@
 #include "chrome/test/testing_profile.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
 
 class BookmarkNodeDataTest : public testing::Test {
  public:
@@ -29,9 +29,9 @@
 
 namespace {
 
-OSExchangeData::Provider* CloneProvider(const OSExchangeData& data) {
-  return new OSExchangeDataProviderWin(
-      OSExchangeDataProviderWin::GetIDataObject(data));
+ui::OSExchangeData::Provider* CloneProvider(const ui::OSExchangeData& data) {
+  return new ui::OSExchangeDataProviderWin(
+      ui::OSExchangeDataProviderWin::GetIDataObject(data));
 }
 
 }  // namespace
@@ -44,9 +44,9 @@
 
 // Makes sure reading bogus data leaves the BookmarkNodeData invalid.
 TEST_F(BookmarkNodeDataTest, BogusRead) {
-  OSExchangeData data;
+  ui::OSExchangeData data;
   BookmarkNodeData drag_data;
-  EXPECT_FALSE(drag_data.Read(OSExchangeData(CloneProvider(data))));
+  EXPECT_FALSE(drag_data.Read(ui::OSExchangeData(CloneProvider(data))));
   EXPECT_FALSE(drag_data.is_valid());
 }
 
@@ -56,11 +56,11 @@
   const GURL url("http://google.com");
   const std::wstring title(L"title");
 
-  OSExchangeData data;
+  ui::OSExchangeData data;
   data.SetURL(url, title);
 
   BookmarkNodeData drag_data;
-  EXPECT_TRUE(drag_data.Read(OSExchangeData(CloneProvider(data))));
+  EXPECT_TRUE(drag_data.Read(ui::OSExchangeData(CloneProvider(data))));
   EXPECT_TRUE(drag_data.is_valid());
   ASSERT_EQ(1, drag_data.elements.size());
   EXPECT_TRUE(drag_data.elements[0].is_url);
@@ -86,11 +86,11 @@
   EXPECT_TRUE(drag_data.elements[0].is_url);
   EXPECT_EQ(url, drag_data.elements[0].url);
   EXPECT_EQ(title, WideToUTF16Hack(drag_data.elements[0].title));
-  OSExchangeData data;
+  ui::OSExchangeData data;
   drag_data.Write(&profile, &data);
 
   // Now read the data back in.
-  OSExchangeData data2(CloneProvider(data));
+  ui::OSExchangeData data2(CloneProvider(data));
   BookmarkNodeData read_data;
   EXPECT_TRUE(read_data.Read(data2));
   EXPECT_TRUE(read_data.is_valid());
@@ -130,11 +130,11 @@
   EXPECT_EQ(g12->GetTitle(), WideToUTF16Hack(drag_data.elements[0].title));
   EXPECT_FALSE(drag_data.elements[0].is_url);
 
-  OSExchangeData data;
+  ui::OSExchangeData data;
   drag_data.Write(&profile, &data);
 
   // Now read the data back in.
-  OSExchangeData data2(CloneProvider(data));
+  ui::OSExchangeData data2(CloneProvider(data));
   BookmarkNodeData read_data;
   EXPECT_TRUE(read_data.Read(data2));
   EXPECT_TRUE(read_data.is_valid());
@@ -168,11 +168,11 @@
 
   BookmarkNodeData drag_data(group);
 
-  OSExchangeData data;
+  ui::OSExchangeData data;
   drag_data.Write(&profile, &data);
 
   // Now read the data back in.
-  OSExchangeData data2(CloneProvider(data));
+  ui::OSExchangeData data2(CloneProvider(data));
   BookmarkNodeData read_data;
   EXPECT_TRUE(read_data.Read(data2));
   ASSERT_EQ(1, read_data.elements.size());
@@ -210,11 +210,11 @@
   nodes.push_back(group);
   nodes.push_back(url_node);
   BookmarkNodeData drag_data(nodes);
-  OSExchangeData data;
+  ui::OSExchangeData data;
   drag_data.Write(&profile, &data);
 
   // Read the data back in.
-  OSExchangeData data2(CloneProvider(data));
+  ui::OSExchangeData data2(CloneProvider(data));
   BookmarkNodeData read_data;
   EXPECT_TRUE(read_data.Read(data2));
   EXPECT_TRUE(read_data.is_valid());
diff --git a/chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h b/chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h
index 4ffc008..18f4360 100644
--- a/chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h
+++ b/chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h
@@ -8,7 +8,7 @@
 
 #include "base/file_path.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 // This set of functions lets C++ code interact with the cocoa pasteboard
 // and dragging methods.
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index 55acbbe..f47090f 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,17 +6,14 @@
 
 #include <utility>
 
-#include "app/drag_drop_types.h"
-#include "app/l10n_util.h"
-#include "app/tree_node_iterator.h"
 #include "base/basictypes.h"
 #include "base/file_path.h"
-#include "base/string_number_conversions.h"
 #include "base/string16.h"
+#include "base/string_number_conversions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_node_data.h"
 #if defined(OS_MACOSX)
 #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
 #endif
@@ -35,15 +32,18 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
-#include "views/event.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/tree_node_iterator.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "app/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
 #include "views/drag_utils.h"
+#include "views/events/event.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget.h"
 #elif defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/custom_drag.h"
+#include "chrome/browser/ui/gtk/custom_drag.h"
 #endif
 
 using base::Time;
@@ -210,23 +210,24 @@
   int common_ops = (source_operations & operations);
   if (!common_ops)
     return 0;
-  if (DragDropTypes::DRAG_COPY & common_ops)
-    return DragDropTypes::DRAG_COPY;
-  if (DragDropTypes::DRAG_LINK & common_ops)
-    return DragDropTypes::DRAG_LINK;
-  if (DragDropTypes::DRAG_MOVE & common_ops)
-    return DragDropTypes::DRAG_MOVE;
-  return DragDropTypes::DRAG_NONE;
+  if (ui::DragDropTypes::DRAG_COPY & common_ops)
+    return ui::DragDropTypes::DRAG_COPY;
+  if (ui::DragDropTypes::DRAG_LINK & common_ops)
+    return ui::DragDropTypes::DRAG_LINK;
+  if (ui::DragDropTypes::DRAG_MOVE & common_ops)
+    return ui::DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_NONE;
 }
 
 int BookmarkDragOperation(const BookmarkNode* node) {
   if (node->is_url()) {
-    return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE |
-           DragDropTypes::DRAG_LINK;
+    return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE |
+           ui::DragDropTypes::DRAG_LINK;
   }
-  return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
 }
 
+#if defined(TOOLKIT_VIEWS)
 int BookmarkDropOperation(Profile* profile,
                           const views::DropTargetEvent& event,
                           const BookmarkNodeData& data,
@@ -234,19 +235,20 @@
                           int index) {
   if (data.IsFromProfile(profile) && data.size() > 1)
     // Currently only accept one dragged node at a time.
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
 
   if (!bookmark_utils::IsValidDropLocation(profile, data, parent, index))
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
 
   if (data.GetFirstNode(profile)) {
     // User is dragging from this profile: move.
-    return DragDropTypes::DRAG_MOVE;
+    return ui::DragDropTypes::DRAG_MOVE;
   }
   // User is dragging from another app, copy.
-  return PreferredDropOperation(event.GetSourceOperations(),
-      DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK);
+  return PreferredDropOperation(event.source_operations(),
+      ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK);
 }
+#endif  // defined(TOOLKIT_VIEWS)
 
 int PerformBookmarkDrop(Profile* profile,
                         const BookmarkNodeData& data,
@@ -262,13 +264,13 @@
         model->Move(dragged_nodes[i], parent_node, index);
         index = parent_node->IndexOfChild(dragged_nodes[i]) + 1;
       }
-      return DragDropTypes::DRAG_MOVE;
+      return ui::DragDropTypes::DRAG_MOVE;
     }
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
   }
   // Dropping a group from different profile. Always accept.
   bookmark_utils::CloneBookmarkNode(model, data.elements, parent_node, index);
-  return DragDropTypes::DRAG_COPY;
+  return ui::DragDropTypes::DRAG_COPY;
 }
 
 bool IsValidDropLocation(Profile* profile,
@@ -325,7 +327,7 @@
 
 #if defined(TOOLKIT_VIEWS)
   // Set up our OLE machinery
-  OSExchangeData data;
+  ui::OSExchangeData data;
   BookmarkNodeData drag_data(nodes);
   drag_data.Write(profile, &data);
 
@@ -337,8 +339,8 @@
   MessageLoop::current()->SetNestableTasksAllowed(true);
 
   root_view->StartDragForViewFromMouseEvent(NULL, data,
-      DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE |
-      DragDropTypes::DRAG_LINK);
+      ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE |
+      ui::DragDropTypes::DRAG_LINK);
 
   MessageLoop::current()->SetNestableTasksAllowed(was_nested);
 #elif defined(OS_MACOSX)
@@ -428,12 +430,11 @@
   return BookmarkNodeData::ClipboardContainsBookmarks();
 }
 
-std::string GetNameForURL(const GURL& url) {
+string16 GetNameForURL(const GURL& url) {
   if (url.is_valid()) {
-    return WideToUTF8(net::GetSuggestedFilename(
-        url, std::string(), std::string(), FilePath()).ToWStringHack());
+    return net::GetSuggestedFilename(url, "", "", string16());
   } else {
-    return l10n_util::GetStringUTF8(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
+    return l10n_util::GetStringUTF16(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
   }
 }
 
@@ -441,7 +442,7 @@
     BookmarkModel* model,
     size_t max_count) {
   std::vector<const BookmarkNode*> nodes;
-  TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
+  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
   while (iterator.has_next()) {
     const BookmarkNode* parent = iterator.Next();
     if (parent->is_folder() && parent->date_group_modified() > base::Time()) {
@@ -479,7 +480,7 @@
 void GetMostRecentlyAddedEntries(BookmarkModel* model,
                                  size_t count,
                                  std::vector<const BookmarkNode*>* nodes) {
-  TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
+  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
   while (iterator.has_next()) {
     const BookmarkNode* node = iterator.Next();
     if (node->is_url()) {
@@ -495,6 +496,12 @@
   }
 }
 
+TitleMatch::TitleMatch()
+    : node(NULL) {
+}
+
+TitleMatch::~TitleMatch() {}
+
 bool MoreRecentlyAdded(const BookmarkNode* n1, const BookmarkNode* n2) {
   return n1->date_added() > n2->date_added();
 }
@@ -510,7 +517,7 @@
   if (words.empty())
     return;
 
-  TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
+  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
   while (iterator.has_next()) {
     const BookmarkNode* node = iterator.Next();
     if (node->is_url() && DoesBookmarkContainWords(node, words, languages)) {
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index 0fc7615..cd02045 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,7 @@
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/history/snippet.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class BookmarkModel;
@@ -115,7 +115,7 @@
 
 // Returns a name for the given URL. Used for drags into bookmark areas when
 // the source doesn't specify a title.
-std::string GetNameForURL(const GURL& url);
+string16 GetNameForURL(const GURL& url);
 
 // Returns a vector containing up to |max_count| of the most recently modified
 // groups. This never returns an empty vector.
@@ -131,6 +131,9 @@
 // Used by GetBookmarksMatchingText to return a matching node and the location
 // of the match in the title.
 struct TitleMatch {
+  TitleMatch();
+  ~TitleMatch();
+
   const BookmarkNode* node;
 
   // Location of the matching words in the title of the node.
diff --git a/chrome/browser/bookmarks/bookmark_utils_unittest.cc b/chrome/browser/bookmarks/bookmark_utils_unittest.cc
index 9de3b66..b1e3577 100644
--- a/chrome/browser/bookmarks/bookmark_utils_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_utils_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-#include "app/clipboard/scoped_clipboard_writer.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
 
 #if !defined(OS_MACOSX)
 #include "chrome/browser/browser_process.h"
@@ -121,7 +121,7 @@
 
   // Write some text to the clipboard.
   {
-    ScopedClipboardWriter clipboard_writer(g_browser_process->clipboard());
+    ui::ScopedClipboardWriter clipboard_writer(g_browser_process->clipboard());
     clipboard_writer.WriteText(ASCIIToUTF16("foo"));
   }
 
diff --git a/chrome/browser/bookmarks/recently_used_folders_combo_model.cc b/chrome/browser/bookmarks/recently_used_folders_combo_model.cc
index 7990de6..172e779 100644
--- a/chrome/browser/bookmarks/recently_used_folders_combo_model.cc
+++ b/chrome/browser/bookmarks/recently_used_folders_combo_model.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/bookmarks/recently_used_folders_combo_model.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/bookmarks/recently_used_folders_combo_model.h b/chrome/browser/bookmarks/recently_used_folders_combo_model.h
index e8fcc75..b405899 100644
--- a/chrome/browser/bookmarks/recently_used_folders_combo_model.h
+++ b/chrome/browser/bookmarks/recently_used_folders_combo_model.h
@@ -8,19 +8,19 @@
 
 #include <vector>
 
-#include "app/combobox_model.h"
 #include "base/string16.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
+#include "ui/base/models/combobox_model.h"
 
 // Model for the combobox showing the list of folders to choose from. The
 // list always contains the bookmark bar, other node and parent. The list
 // also contains an extra item that shows the text 'Choose another folder...'.
-class RecentlyUsedFoldersComboModel : public ComboboxModel {
+class RecentlyUsedFoldersComboModel : public ui::ComboboxModel {
  public:
   RecentlyUsedFoldersComboModel(BookmarkModel* model, const BookmarkNode* node);
   virtual ~RecentlyUsedFoldersComboModel();
 
-  // Overridden from ComboboxModel:
+  // Overridden from ui::ComboboxModel:
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc
index 3de80ac..535937f 100644
--- a/chrome/browser/browser_about_handler.cc
+++ b/chrome/browser/browser_about_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,11 +8,10 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/i18n/number_formatting.h"
+#include "base/json/json_writer.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/stats_table.h"
 #include "base/path_service.h"
@@ -24,6 +23,7 @@
 #include "base/threading/thread.h"
 #include "base/tracked_objects.h"
 #include "base/utf_string_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
@@ -35,21 +35,17 @@
 #include "chrome/browser/metrics/histogram_synchronizer.h"
 #include "chrome/browser/net/predictor_api.h"
 #include "chrome/browser/platform_util.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/common/about_handler.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/gpu_info.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
@@ -59,21 +55,20 @@
 #include "grit/locale_settings.h"
 #include "webkit/glue/webkit_glue.h"
 #include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #ifdef CHROME_V8
 #include "v8/include/v8.h"
 #endif
 
 #if defined(OS_WIN)
 #include "chrome/browser/enumerate_modules_model_win.h"
-#include "chrome/browser/views/about_ipc_dialog.h"
 #elif defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/cros/syslogs_library.h"
 #include "chrome/browser/chromeos/version_loader.h"
 #include "chrome/browser/zygote_host_linux.h"
-#elif defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/about_ipc_dialog.h"
 #elif defined(OS_LINUX)
 #include "chrome/browser/zygote_host_linux.h"
 #endif
@@ -82,8 +77,6 @@
 #include "third_party/tcmalloc/chromium/src/google/malloc_extension.h"
 #endif
 
-using sync_api::SyncManager;
-
 using base::Time;
 using base::TimeDelta;
 
@@ -117,7 +110,6 @@
 const char kMemoryRedirectPath[] = "memory-redirect";
 const char kMemoryPath[] = "memory";
 const char kStatsPath[] = "stats";
-const char kSyncPath[] = "sync";
 const char kTasksPath[] = "tasks";
 const char kTcmallocPath[] = "tcmalloc";
 const char kTermsPath[] = "terms";
@@ -126,6 +118,7 @@
 // Not about:* pages, but included to make about:about look nicer
 const char kNetInternalsPath[] = "net-internals";
 const char kPluginsPath[] = "plugins";
+const char kSyncInternalsPath[] = "sync-internals";
 
 #if defined(OS_LINUX)
 const char kLinuxProxyConfigPath[] = "linux-proxy-config";
@@ -154,7 +147,7 @@
   kNetInternalsPath,
   kPluginsPath,
   kStatsPath,
-  kSyncPath,
+  kSyncInternalsPath,
   kTasksPath,
   kTcmallocPath,
   kTermsPath,
@@ -168,9 +161,6 @@
 #endif
   };
 
-// Points to the singleton AboutSource object, if any.
-ChromeURLDataManager::DataSource* about_source = NULL;
-
 // When you type about:memory, it actually loads an intermediate URL that
 // redirects you to the final page. This avoids the problem where typing
 // "about:memory" on the new tab page or any other page where a process
@@ -290,7 +280,8 @@
     html.append(kAllAboutPaths[i]);
     html.append("</a>\n");
   }
-  const char *debug[] = { "crash", "hang", "shorthang", "gpucrash", "gpuhang" };
+  const char *debug[] = { "crash", "kill", "hang", "shorthang",
+                          "gpucrash", "gpuhang" };
   html.append("</ul><h2>For Debug</h2>");
   html.append("</ul><p>The following pages are for debugging purposes only. "
               "Because they crash or hang the renderer, they're not linked "
@@ -437,10 +428,23 @@
 }
 #endif  // TRACK_ALL_TASK_OBJECTS
 
-std::string AboutStats() {
+// Handler for filling in the "about:stats" page, as called by the browser's
+// About handler processing.
+// |query| is roughly the query string of the about:stats URL.
+// Returns a string containing the HTML to render for the about:stats page.
+// Conditional Output:
+//      if |query| is "json", returns a JSON format of all counters.
+//      if |query| is "raw", returns plain text of counter deltas.
+//      otherwise, returns HTML with pretty JS/HTML to display the data.
+std::string AboutStats(const std::string& query) {
   // We keep the DictionaryValue tree live so that we can do delta
   // stats computations across runs.
   static DictionaryValue root;
+  static base::TimeTicks last_sample_time = base::TimeTicks::Now();
+
+  base::TimeTicks now = base::TimeTicks::Now();
+  base::TimeDelta time_since_last_sample = now - last_sample_time;
+  last_sample_time = now;
 
   base::StatsTable* table = base::StatsTable::current();
   if (!table)
@@ -528,22 +532,58 @@
     }
   }
 
-  // Get about_stats.html
-  static const base::StringPiece stats_html(
-      ResourceBundle::GetSharedInstance().GetRawDataResource(
-          IDR_ABOUT_STATS_HTML));
+  std::string data;
+  if (query == "json") {
+    base::JSONWriter::WriteWithOptionalEscape(&root, true, false, &data);
+  } else if (query == "raw") {
+    // Dump the raw counters which have changed in text format.
+    data = "<pre>";
+    data.append(StringPrintf("Counter changes in the last %ldms\n",
+        static_cast<long int>(time_since_last_sample.InMilliseconds())));
+    for (size_t i = 0; i < counters->GetSize(); ++i) {
+      Value* entry = NULL;
+      bool rv = counters->Get(i, &entry);
+      if (!rv)
+        continue;  // None of these should fail.
+      DictionaryValue* counter = static_cast<DictionaryValue*>(entry);
+      int delta;
+      rv = counter->GetInteger("delta", &delta);
+      if (!rv)
+        continue;
+      if (delta > 0) {
+        std::string name;
+        rv = counter->GetString("name", &name);
+        if (!rv)
+          continue;
+        int value;
+        rv = counter->GetInteger("value", &value);
+        if (!rv)
+          continue;
+        data.append(name);
+        data.append(":");
+        data.append(base::IntToString(delta));
+        data.append("\n");
+      }
+    }
+    data.append("</pre>");
+  } else {
+    // Get about_stats.html and process a pretty page.
+    static const base::StringPiece stats_html(
+        ResourceBundle::GetSharedInstance().GetRawDataResource(
+            IDR_ABOUT_STATS_HTML));
 
-  // Create jstemplate and return.
-  std::string data = jstemplate_builder::GetTemplateHtml(
-      stats_html, &root, "t" /* template root node id */);
+    // Create jstemplate and return.
+    data = jstemplate_builder::GetTemplateHtml(
+        stats_html, &root, "t" /* template root node id */);
 
-  // Clear the timer list since we stored the data in the timers list as well.
-  for (int index = static_cast<int>(timers->GetSize())-1; index >= 0;
-       index--) {
-    Value* value;
-    timers->Remove(index, &value);
-    // We don't care about the value pointer; it's still tracked
-    // on the counters list.
+    // Clear the timer list since we stored the data in the timers list as well.
+    for (int index = static_cast<int>(timers->GetSize())-1; index >= 0;
+         index--) {
+      Value* value;
+      timers->Remove(index, &value);
+      // We don't care about the value pointer; it's still tracked
+      // on the counters list.
+    }
   }
 
   return data;
@@ -689,31 +729,6 @@
       version_html, localized_strings, "t" /* template root node id */);
 }
 
-
-
-std::string AboutSync() {
-  FilePath user_data_dir;
-  if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
-    return std::string();
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
-  ProfileSyncService* service = profile->GetProfileSyncService();
-
-  DictionaryValue strings;
-  if (!service) {
-    strings.SetString("summary", "SYNC DISABLED");
-  } else {
-    sync_ui_util::ConstructAboutInformation(service, &strings);
-  }
-
-  static const base::StringPiece sync_html(
-      ResourceBundle::GetSharedInstance().GetRawDataResource(
-      IDR_ABOUT_SYNC_HTML));
-
-  return jstemplate_builder::GetTemplatesHtml(
-      sync_html, &strings , "t" /* template root node id */);
-}
-
 std::string VersionNumberToString(uint32 value) {
   int hi = (value >> 8) & 0xff;
   int low = value & 0xff;
@@ -724,21 +739,9 @@
 
 AboutSource::AboutSource()
     : DataSource(chrome::kAboutScheme, MessageLoop::current()) {
-  // This should be a singleton.
-  DCHECK(!about_source);
-  about_source = this;
-
-  // Add us to the global URL handler on the IO thread.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(this)));
 }
 
 AboutSource::~AboutSource() {
-  about_source = NULL;
 }
 
 void AboutSource::StartDataRequest(const std::string& path_raw,
@@ -768,7 +771,7 @@
     response = AboutObjects(info);
 #endif
   } else if (path == kStatsPath) {
-    response = AboutStats();
+    response = AboutStats(info);
 #if defined(USE_TCMALLOC)
   } else if (path == kTcmallocPath) {
     response = AboutTcmalloc(info);
@@ -802,8 +805,6 @@
   } else if (path == kSandboxPath) {
     response = AboutSandbox();
 #endif
-  } else if (path == kSyncPath) {
-    response = AboutSync();
   }
 
   FinishDataRequest(response, request_id);
@@ -1050,6 +1051,14 @@
     return true;
   }
 
+  // Rewrite about:sync-internals/* URLs (and about:sync, too, for
+  // legacy reasons) to chrome://sync-internals/*
+  if (StartsWithAboutSpecifier(*url, chrome::kAboutSyncInternalsURL) ||
+      StartsWithAboutSpecifier(*url, chrome::kAboutSyncURL)) {
+    *url = RemapAboutURL(chrome::kSyncViewInternalsURL, *url);
+    return true;
+  }
+
   // Rewrite about:plugins to chrome://plugins/.
   if (LowerCaseEqualsASCII(url->spec(), chrome::kAboutPluginsURL)) {
     *url = GURL(chrome::kChromeUIPluginsURL);
@@ -1080,7 +1089,7 @@
     return false;
 
   // Anything else requires our special handler; make sure it's initialized.
-  InitializeAboutDataSource();
+  InitializeAboutDataSource(profile);
 
   // Special case about:memory to go through a redirect before ending up on
   // the final page. See GetAboutMemoryRedirectResponse above for why.
@@ -1098,14 +1107,8 @@
   return true;
 }
 
-void InitializeAboutDataSource() {
-  // We only need to register the AboutSource once and it is kept globally.
-  // There is currently no way to remove a data source.
-  static bool initialized = false;
-  if (!initialized) {
-    about_source = new AboutSource();
-    initialized = true;
-  }
+void InitializeAboutDataSource(Profile* profile) {
+  profile->GetChromeURLDataManager()->AddDataSource(new AboutSource());
 }
 
 // This function gets called with the fixed-up chrome: URLs, so we have to
@@ -1117,7 +1120,7 @@
 #if (defined(OS_MACOSX) || defined(OS_WIN)) && defined(IPC_MESSAGE_LOG_ENABLED)
   if (LowerCaseEqualsASCII(url.spec(), chrome::kChromeUIIPCURL)) {
     // Run the dialog. This will re-use the existing one if it's already up.
-    AboutIPCDialog::RunDialog();
+    browser::ShowAboutIPCDialog();
     return true;
   }
 #endif
diff --git a/chrome/browser/browser_about_handler.h b/chrome/browser/browser_about_handler.h
index 46ae100..e5e31c9 100644
--- a/chrome/browser/browser_about_handler.h
+++ b/chrome/browser/browser_about_handler.h
@@ -28,7 +28,7 @@
 
 // Register the data source for chrome://about URLs.
 // Safe to call multiple times.
-void InitializeAboutDataSource();
+void InitializeAboutDataSource(Profile* profile);
 
 // We have a few magic commands that don't cause navigations, but rather pop up
 // dialogs. This function handles those cases, and returns true if so. In this
diff --git a/chrome/browser/browser_about_handler_unittest.cc b/chrome/browser/browser_about_handler_unittest.cc
index 9b234a2..16fface 100644
--- a/chrome/browser/browser_about_handler_unittest.cc
+++ b/chrome/browser/browser_about_handler_unittest.cc
@@ -5,8 +5,10 @@
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/browser_about_handler.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/common/about_handler.h"
 #include "chrome/common/url_constants.h"
+#include "chrome/test/testing_profile.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -66,6 +68,12 @@
         false
       },
       {
+        GURL(chrome::kAboutKillURL),
+        GURL(chrome::kAboutKillURL),
+        true,
+        false
+      },
+      {
         GURL(chrome::kAboutHangURL),
         GURL(chrome::kAboutHangURL),
         true,
@@ -90,13 +98,16 @@
         true
       },
   };
+  MessageLoopForUI message_loop;
+  BrowserThread ui_thread(BrowserThread::UI, &message_loop);
+  TestingProfile profile;
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
     GURL url(test_data[i].test_url);
     EXPECT_EQ(test_data[i].about_handled,
               chrome_about_handler::WillHandle(url));
     EXPECT_EQ(test_data[i].browser_handled,
-              WillHandleBrowserAboutURL(&url, NULL));
+              WillHandleBrowserAboutURL(&url, &profile));
     EXPECT_EQ(test_data[i].result_url, url);
   }
 
diff --git a/chrome/browser/browser_browsertest.cc b/chrome/browser/browser_browsertest.cc
index b286711..35e933f 100644
--- a/chrome/browser/browser_browsertest.cc
+++ b/chrome/browser/browser_browsertest.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/compiler_specific.h"
 #include "base/file_path.h"
 #include "base/sys_info.h"
@@ -39,6 +38,7 @@
 #include "grit/generated_resources.h"
 #include "net/base/mock_host_resolver.h"
 #include "net/test/test_server.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_WIN)
 #include "base/i18n/rtl.h"
@@ -47,13 +47,13 @@
 
 namespace {
 
-const std::string BEFORE_UNLOAD_HTML =
+const char* kBeforeUnloadHTML =
     "<html><head><title>beforeunload</title></head><body>"
     "<script>window.onbeforeunload=function(e){return 'foo'}</script>"
     "</body></html>";
 
-const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE =
-    L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};";
+const char* kOpenNewBeforeUnloadPage =
+    "w=window.open(); w.onbeforeunload=function(e){return 'foo'};";
 
 const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
 const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");
@@ -211,8 +211,9 @@
   EXPECT_EQ(0, browser()->selected_index());
   TabContents* second_tab = browser()->GetTabContentsAt(1);
   ASSERT_TRUE(second_tab);
-  second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"",
-      L"alert('Activate!');");
+  second_tab->render_view_host()->ExecuteJavascriptInWebFrame(
+      string16(),
+      ASCIIToUTF16("alert('Activate!');"));
   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
   alert->CloseModalDialog();
   EXPECT_EQ(2, browser()->tab_count());
@@ -246,7 +247,7 @@
 // Test for crbug.com/22004.  Reloading a page with a before unload handler and
 // then canceling the dialog should not leave the throbber spinning.
 IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
-  GURL url("data:text/html," + BEFORE_UNLOAD_HTML);
+  GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Navigate to another page, but click cancel in the dialog.  Make sure that
@@ -258,7 +259,8 @@
 
   // Clear the beforeunload handler so the test can easily exit.
   browser()->GetSelectedTabContents()->render_view_host()->
-      ExecuteJavascriptInWebFrame(L"", L"onbeforeunload=null;");
+      ExecuteJavascriptInWebFrame(string16(),
+                                  ASCIIToUTF16("onbeforeunload=null;"));
 }
 
 // Crashy on mac.  http://crbug.com/38522
@@ -274,13 +276,15 @@
 // two beforeunload dialogs shown.
 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) {
   browser()->GetSelectedTabContents()->render_view_host()->
-      ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE);
+      ExecuteJavascriptInWebFrame(string16(),
+                                  ASCIIToUTF16(kOpenNewBeforeUnloadPage));
 
   // Close the new window with JavaScript, which should show a single
   // beforeunload dialog.  Then show another alert, to make it easy to verify
   // that a second beforeunload dialog isn't shown.
   browser()->GetTabContentsAt(0)->render_view_host()->
-      ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');");
+      ExecuteJavascriptInWebFrame(string16(),
+                                  ASCIIToUTF16("w.close(); alert('bar');"));
   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
   alert->native_dialog()->AcceptAppModalDialog();
 
@@ -376,7 +380,8 @@
 }
 
 // Change a tab into an application window.
-IN_PROC_BROWSER_TEST_F(BrowserTest, ConvertTabToAppShortcut) {
+// DISABLED: http://crbug.com/72310
+IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) {
   ASSERT_TRUE(test_server()->Start());
   GURL http_url(test_server()->GetURL(""));
   ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme));
@@ -419,7 +424,7 @@
   // Normal tabs should accept load drops.
   EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
 
-  // The tab in an aopp window should not.
+  // The tab in an app window should not.
   EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
 }
 
@@ -495,6 +500,44 @@
   ASSERT_EQ(1, browser()->tab_count());
 }
 
+#if !defined(OS_MACOSX)
+// Open with --app-id=<id>, and see that an app window opens.
+IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) {
+  ASSERT_TRUE(test_server()->Start());
+
+  // Load an app.
+  host_resolver()->AddRule("www.example.com", "127.0.0.1");
+  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
+  const Extension* extension_app = GetExtension();
+
+  CommandLine command_line(CommandLine::NO_PROGRAM);
+  command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
+
+  BrowserInit::LaunchWithProfile launch(FilePath(), command_line);
+  ASSERT_TRUE(launch.OpenApplicationWindow(browser()->profile()));
+
+  // Check that the new browser has an app name.
+  // The launch should have created a new browser.
+  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
+
+  // Find the new browser.
+  Browser* new_browser = NULL;
+  for (BrowserList::const_iterator i = BrowserList::begin();
+       i != BrowserList::end() && !new_browser; ++i) {
+    if (*i != browser())
+      new_browser = *i;
+  }
+  ASSERT_TRUE(new_browser);
+  ASSERT_TRUE(new_browser != browser());
+
+  // The browser's app_name should include the app's ID.
+  ASSERT_NE(
+      new_browser->app_name_.find(extension_app->id()),
+      std::string::npos) << new_browser->app_name_;
+
+}
+#endif
+
 #if defined(OS_WIN)
 // http://crbug.com/46198. On XP/Vista, the failure rate is 5 ~ 6%.
 #define MAYBE_PageLanguageDetection FLAKY_PageLanguageDetection
@@ -654,6 +697,11 @@
   ASSERT_TRUE(new_browser != browser());
 
   EXPECT_EQ(Browser::TYPE_APP, new_browser->type());
+
+  // The browser's app name should include the extension's id.
+  std::string app_name = new_browser->app_name_;
+  EXPECT_NE(app_name.find(extension_app->id()), std::string::npos)
+      << "Name " << app_name << " should contain id "<< extension_app->id();
 }
 #endif  // !defined(OS_MACOSX)
 
diff --git a/chrome/browser/browser_child_process_host.cc b/chrome/browser/browser_child_process_host.cc
index 13bc04e..fd8af11 100644
--- a/chrome/browser/browser_child_process_host.cc
+++ b/chrome/browser/browser_child_process_host.cc
@@ -15,14 +15,12 @@
 #include "base/string_util.h"
 #include "chrome/app/breakpad_mac.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/child_process_logging.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/plugin_messages.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/process_watcher.h"
 #include "chrome/common/result_codes.h"
 #include "chrome/installer/util/google_update_settings.h"
diff --git a/chrome/browser/browser_child_process_host.h b/chrome/browser/browser_child_process_host.h
index f917a4d..28ca924 100644
--- a/chrome/browser/browser_child_process_host.h
+++ b/chrome/browser/browser_child_process_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -60,7 +60,7 @@
   // |resource_dispatcher_host| may be NULL to indicate none is needed for
   // this process type.
   // |url_request_context_getter| allows derived classes to override the
-  // URLRequestContext.
+  // net::URLRequestContext.
   BrowserChildProcessHost(
       ChildProcessInfo::ProcessType type,
       ResourceDispatcherHost* resource_dispatcher_host,
@@ -68,7 +68,7 @@
           url_request_context_override);
 
   // A convenient constructor for those classes that want to use the default
-  // URLRequestContext.
+  // net::URLRequestContext.
   BrowserChildProcessHost(
       ChildProcessInfo::ProcessType type,
       ResourceDispatcherHost* resource_dispatcher_host);
diff --git a/chrome/browser/browser_commands_unittest.cc b/chrome/browser/browser_commands_unittest.cc
index 70beb87..c022fd5 100644
--- a/chrome/browser/browser_commands_unittest.cc
+++ b/chrome/browser/browser_commands_unittest.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/browser_with_test_window_test.h"
diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc
index b8dc0e7..f46b176 100644
--- a/chrome/browser/browser_focus_uitest.cc
+++ b/chrome/browser/browser_focus_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -33,18 +33,18 @@
 #endif
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
-#include "chrome/browser/views/tab_contents/tab_contents_container.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
 #endif
 
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/view_id_util.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
 #endif
 
 #if defined(OS_WIN)
-#include <windows.h>
 #include <Psapi.h>
+#include <windows.h>
 #endif
 
 #if defined(OS_LINUX)
@@ -154,12 +154,16 @@
     return html_contents_;
   }
 
-  // Exposing render_view_host() to be public; it is declared as protected in
-  // the superclass.
+  // Exposing render_view_host() and tab() to be public; they are declared as
+  // protected in the superclass.
   virtual RenderViewHost* render_view_host() {
     return InterstitialPage::render_view_host();
   }
 
+  virtual TabContents* tab() {
+    return InterstitialPage::tab();
+  }
+
   bool HasFocus() {
     return render_view_host()->view()->HasFocus();
   }
@@ -168,7 +172,7 @@
   virtual void FocusedNodeChanged(bool is_editable_node) {
     NotificationService::current()->Notify(
         NotificationType::FOCUS_CHANGED_IN_PAGE,
-        Source<RenderViewHost>(render_view_host()),
+        Source<TabContents>(tab()),
         Details<const bool>(&is_editable_node));
   }
 
@@ -313,7 +317,7 @@
       ASSERT_TRUE(IsViewFocused(vid));
 
       ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-          browser(), app::VKEY_TAB, true, false, false, false));
+          browser(), ui::VKEY_TAB, true, false, false, false));
     }
 
     // As above, but with ctrl+shift+tab.
@@ -324,7 +328,7 @@
       ASSERT_TRUE(IsViewFocused(vid));
 
       ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-          browser(), app::VKEY_TAB, true, true, false, false));
+          browser(), ui::VKEY_TAB, true, true, false, false));
     }
   }
 }
@@ -339,7 +343,7 @@
   ui_test_utils::NavigateToURL(browser(), url);
 
   browser()->Find();
-  ui_test_utils::FindInPage(browser()->GetSelectedTabContents(),
+  ui_test_utils::FindInPage(browser()->GetSelectedTabContentsWrapper(),
                             ASCIIToUTF16("a"), true, false, NULL);
   ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
 
@@ -465,6 +469,10 @@
     // Location bar should be focused.
     ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR));
 
+    // Move the caret to the end, otherwise the next Tab key may not move focus.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
+        browser(), ui::VKEY_END, false, false, false, false));
+
     // Now let's press tab to move the focus.
     for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
       SCOPED_TRACE(StringPrintf("inner loop %" PRIuS, j));
@@ -485,15 +493,15 @@
         Details<bool> details(&is_editable_node);
 
         ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
-            browser(), app::VKEY_TAB, false, false, false, false,
+            browser(), ui::VKEY_TAB, false, false, false, false,
             NotificationType::FOCUS_CHANGED_IN_PAGE,
-            NotificationSource(Source<RenderViewHost>(
-                browser()->GetSelectedTabContents()->render_view_host())),
+            NotificationSource(Source<TabContents>(
+                browser()->GetSelectedTabContents())),
             details));
       } else {
         // On the last tab key press, the focus returns to the browser.
         ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-            browser(), app::VKEY_TAB, false, false, false, false,
+            browser(), ui::VKEY_TAB, false, false, false, false,
             NotificationType::FOCUS_RETURNED_TO_BROWSER,
             NotificationSource(Source<Browser>(browser()))));
       }
@@ -511,6 +519,10 @@
     // Location bar should be focused.
     ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR));
 
+    // Move the caret to the end, otherwise the next Tab key may not move focus.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
+        browser(), ui::VKEY_END, false, false, false, false));
+
     // Now let's press shift-tab to move the focus in reverse.
     for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
       SCOPED_TRACE(StringPrintf("inner loop: %" PRIuS, j));
@@ -524,15 +536,15 @@
         Details<bool> details(&is_editable_node);
 
         ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
-            browser(), app::VKEY_TAB, false, true, false, false,
+            browser(), ui::VKEY_TAB, false, true, false, false,
             NotificationType::FOCUS_CHANGED_IN_PAGE,
-            NotificationSource(Source<RenderViewHost>(
-                browser()->GetSelectedTabContents()->render_view_host())),
+            NotificationSource(Source<TabContents>(
+                browser()->GetSelectedTabContents())),
             details));
       } else {
         // On the last tab key press, the focus returns to the browser.
         ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-            browser(), app::VKEY_TAB, false, true, false, false,
+            browser(), ui::VKEY_TAB, false, true, false, false,
             NotificationType::FOCUS_RETURNED_TO_BROWSER,
             NotificationSource(Source<Browser>(browser()))));
       }
@@ -591,6 +603,10 @@
     // Location bar should be focused.
     ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR));
 
+    // Move the caret to the end, otherwise the next Tab key may not move focus.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
+        browser(), ui::VKEY_END, false, false, false, false));
+
     // Now let's press tab to move the focus.
     for (size_t j = 0; j < 7; ++j) {
       // Let's make sure the focus is on the expected element in the page.
@@ -606,8 +622,8 @@
           NotificationService::AllSources();
       if (j < arraysize(kExpElementIDs) - 1) {
         notification_type = NotificationType::FOCUS_CHANGED_IN_PAGE;
-        notification_source = Source<RenderViewHost>(
-            interstitial_page->render_view_host());
+        notification_source = Source<TabContents>(
+            interstitial_page->tab());
       } else {
         // On the last tab key press, the focus returns to the browser.
         notification_type = NotificationType::FOCUS_RETURNED_TO_BROWSER;
@@ -615,7 +631,7 @@
       }
 
       ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-          browser(), app::VKEY_TAB, false, false, false, false,
+          browser(), ui::VKEY_TAB, false, false, false, false,
           notification_type, notification_source));
     }
 
@@ -630,6 +646,10 @@
     // Location bar should be focused.
     ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR));
 
+    // Move the caret to the end, otherwise the next Tab key may not move focus.
+    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
+        browser(), ui::VKEY_END, false, false, false, false));
+
     // Now let's press shift-tab to move the focus in reverse.
     for (size_t j = 0; j < 7; ++j) {
       NotificationType::Type notification_type;
@@ -637,8 +657,8 @@
           NotificationService::AllSources();
       if (j < arraysize(kExpElementIDs) - 1) {
         notification_type = NotificationType::FOCUS_CHANGED_IN_PAGE;
-        notification_source = Source<RenderViewHost>(
-            interstitial_page->render_view_host());
+        notification_source = Source<TabContents>(
+            interstitial_page->tab());
       } else {
         // On the last tab key press, the focus returns to the browser.
         notification_type = NotificationType::FOCUS_RETURNED_TO_BROWSER;
@@ -646,7 +666,7 @@
       }
 
       ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
-          browser(), app::VKEY_TAB, false, true, false, false,
+          browser(), ui::VKEY_TAB, false, true, false, false,
           notification_type, notification_source));
 
       // Let's make sure the focus is on the expected element in the page.
@@ -715,11 +735,11 @@
 #if defined(OS_MACOSX)
   // Press Cmd+F, which will make the Find box open and request focus.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F, false, false, false, true));
+      browser(), ui::VKEY_F, false, false, false, true));
 #else
   // Press Ctrl+F, which will make the Find box open and request focus.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F, true, false, false, false));
+      browser(), ui::VKEY_F, true, false, false, false));
 #endif
 
   // Ideally, we wouldn't sleep here and instead would intercept the
@@ -739,10 +759,10 @@
   // Now press Ctrl+F again and focus should move to the Find box.
 #if defined(OS_MACOSX)
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F, false, false, false, true));
+      browser(), ui::VKEY_F, false, false, false, true));
 #else
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F, true, false, false, false));
+      browser(), ui::VKEY_F, true, false, false, false));
 #endif
   ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
 
@@ -753,10 +773,10 @@
   // Now press Ctrl+F again and focus should move to the Find box.
 #if defined(OS_MACOSX)
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F, false, false, false, true));
+      browser(), ui::VKEY_F, false, false, false, true));
 #else
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F, true, false, false, false));
+      browser(), ui::VKEY_F, true, false, false, false));
 #endif
 
   // See remark above on why we wait.
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc
index 3de74f7..dd025b6 100644
--- a/chrome/browser/browser_keyevents_browsertest.cc
+++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -4,7 +4,6 @@
 
 #include "build/build_config.h"
 
-#include "app/keyboard_codes.h"
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -23,6 +22,7 @@
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/test/test_server.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
 namespace {
 
@@ -61,7 +61,7 @@
 // input.
 // Please refer to chrome/test/data/keyevents_test.html for details.
 struct KeyEventTestData {
-  app::KeyboardCode key;
+  ui::KeyboardCode key;
   bool ctrl;
   bool shift;
   bool alt;
@@ -289,13 +289,13 @@
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, NormalKeyEvents) {
   static const KeyEventTestData kTestNoInput[] = {
     // a
-    { app::VKEY_A, false, false, false, false,
+    { ui::VKEY_A, false, false, false, false,
       false, false, false, false, 3,
       { "D 65 0 false false false false",
         "P 97 97 false false false false",
         "U 65 0 false false false false" } },
     // shift-a
-    { app::VKEY_A, false, true, false, false,
+    { ui::VKEY_A, false, true, false, false,
       false, false, false, false, 5,
       { "D 16 0 false true false false",
         "D 65 0 false true false false",
@@ -303,7 +303,7 @@
         "U 65 0 false true false false",
         "U 16 0 false true false false" } },
     // a, suppress keydown
-    { app::VKEY_A, false, false, false, false,
+    { ui::VKEY_A, false, false, false, false,
       true, false, false, false, 2,
       { "D 65 0 false false false false",
         "U 65 0 false false false false" } },
@@ -311,14 +311,14 @@
 
   static const KeyEventTestData kTestWithInput[] = {
     // a
-    { app::VKEY_A, false, false, false, false,
+    { ui::VKEY_A, false, false, false, false,
       false, false, false, false, 4,
       { "D 65 0 false false false false",
         "P 97 97 false false false false",
         "T a",
         "U 65 0 false false false false" } },
     // shift-a
-    { app::VKEY_A, false, true, false, false,
+    { ui::VKEY_A, false, true, false, false,
       false, false, false, false, 6,
       { "D 16 0 false true false false",
         "D 65 0 false true false false",
@@ -327,18 +327,18 @@
         "U 65 0 false true false false",
         "U 16 0 false true false false" } },
     // a, suppress keydown
-    { app::VKEY_A, false, false, false, false,
+    { ui::VKEY_A, false, false, false, false,
       true, false, false, false, 2,
       { "D 65 0 false false false false",
         "U 65 0 false false false false" } },
     // a, suppress keypress
-    { app::VKEY_A, false, false, false, false,
+    { ui::VKEY_A, false, false, false, false,
       false, true, false, false, 3,
       { "D 65 0 false false false false",
         "P 97 97 false false false false",
         "U 65 0 false false false false" } },
     // a, suppress textInput
-    { app::VKEY_A, false, false, false, false,
+    { ui::VKEY_A, false, false, false, false,
       false, false, false, true, 4,
       { "D 65 0 false false false false",
         "P 97 97 false false false false",
@@ -384,14 +384,14 @@
 #if defined(OS_WIN) || defined(OS_LINUX)
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CtrlKeyEvents) {
   static const KeyEventTestData kTestCtrlF = {
-    app::VKEY_F, true, false, false, false,
+    ui::VKEY_F, true, false, false, false,
     false, false, false, false, 2,
     { "D 17 0 true false false false",
       "D 70 0 true false false false" }
   };
 
   static const KeyEventTestData kTestCtrlFSuppressKeyDown = {
-    app::VKEY_F, true, false, false, false,
+    ui::VKEY_F, true, false, false, false,
     true, false, false, false, 4,
     { "D 17 0 true false false false",
       "D 70 0 true false false false",
@@ -402,7 +402,7 @@
   // Ctrl+Z doesn't bind to any accelerators, which then should generate a
   // keypress event with charCode=26.
   static const KeyEventTestData kTestCtrlZ = {
-    app::VKEY_Z, true, false, false, false,
+    ui::VKEY_Z, true, false, false, false,
     false, false, false, false, 5,
     { "D 17 0 true false false false",
       "D 90 0 true false false false",
@@ -412,7 +412,7 @@
   };
 
   static const KeyEventTestData kTestCtrlZSuppressKeyDown = {
-    app::VKEY_Z, true, false, false, false,
+    ui::VKEY_Z, true, false, false, false,
     true, false, false, false, 4,
     { "D 17 0 true false false false",
       "D 90 0 true false false false",
@@ -422,7 +422,7 @@
 
   // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
   static const KeyEventTestData kTestCtrlEnter = {
-    app::VKEY_RETURN, true, false, false, false,
+    ui::VKEY_RETURN, true, false, false, false,
     false, false, false, false, 5,
     { "D 17 0 true false false false",
       "D 13 0 true false false false",
@@ -447,7 +447,7 @@
 
   // Press Escape to close the Find box and move the focus back to the web page.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_ESCAPE, false, false, false, false));
+      browser(), ui::VKEY_ESCAPE, false, false, false, false));
   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
 
   // Press Ctrl+F with keydown suppressed shall not open the find box.
@@ -461,7 +461,7 @@
 #elif defined(OS_MACOSX)
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CommandKeyEvents) {
   static const KeyEventTestData kTestCmdF = {
-    app::VKEY_F, false, false, false, true,
+    ui::VKEY_F, false, false, false, true,
     false, false, false, false, 2,
     { "D 91 0 false false false true",
       "D 70 0 false false false true" }
@@ -469,7 +469,7 @@
 
   // On Mac we don't send key up events when command modifier is down.
   static const KeyEventTestData kTestCmdFSuppressKeyDown = {
-    app::VKEY_F, false, false, false, true,
+    ui::VKEY_F, false, false, false, true,
     true, false, false, false, 3,
     { "D 91 0 false false false true",
       "D 70 0 false false false true",
@@ -492,7 +492,7 @@
 
   // Press Escape to close the Find box and move the focus back to the web page.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_ESCAPE, false, false, false, false));
+      browser(), ui::VKEY_ESCAPE, false, false, false, false));
   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
 
   // Press Cmd+F with keydown suppressed shall not open the find box.
@@ -505,7 +505,7 @@
 #if defined(OS_MACOSX)
   // On Mac, access keys use ctrl+alt modifiers.
   static const KeyEventTestData kTestAccessA = {
-    app::VKEY_A, true, false, true, false,
+    ui::VKEY_A, true, false, true, false,
     false, false, false, false, 6,
     { "D 17 0 true false false false",
       "D 18 0 true false true false",
@@ -516,7 +516,7 @@
   };
 
   static const KeyEventTestData kTestAccessDSuppress = {
-    app::VKEY_D, true, false, true, false,
+    ui::VKEY_D, true, false, true, false,
     true, true, true, false, 6,
     { "D 17 0 true false false false",
       "D 18 0 true false true false",
@@ -527,7 +527,7 @@
   };
 
   static const KeyEventTestData kTestAccess1 = {
-    app::VKEY_1, true, false, true, false,
+    ui::VKEY_1, true, false, true, false,
     false, false, false, false, 6,
     { "D 17 0 true false false false",
       "D 18 0 true false true false",
@@ -538,7 +538,7 @@
   };
 #else
   static const KeyEventTestData kTestAccessA = {
-    app::VKEY_A, false, false, true, false,
+    ui::VKEY_A, false, false, true, false,
     false, false, false, false, 4,
     { "D 18 0 false false true false",
       "D 65 0 false false true false",
@@ -547,14 +547,14 @@
   };
 
   static const KeyEventTestData kTestAccessD = {
-    app::VKEY_D, false, false, true, false,
+    ui::VKEY_D, false, false, true, false,
     false, false, false, false, 2,
     { "D 18 0 false false true false",
       "D 68 0 false false true false" }
   };
 
   static const KeyEventTestData kTestAccessDSuppress = {
-    app::VKEY_D, false, false, true, false,
+    ui::VKEY_D, false, false, true, false,
     true, true, true, false, 4,
     { "D 18 0 false false true false",
       "D 68 0 false false true false",
@@ -563,7 +563,7 @@
   };
 
   static const KeyEventTestData kTestAccess1 = {
-    app::VKEY_1, false, false, true, false,
+    ui::VKEY_1, false, false, true, false,
     false, false, false, false, 4,
     { "D 18 0 false false true false",
       "D 49 0 false false true false",
@@ -636,8 +636,8 @@
 #endif
 }
 
-// Flaky, http://crbug.com/65847.
-IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FLAKY_ReservedAccelerators) {
+// Disabled, http://crbug.com/69475.
+IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_ReservedAccelerators) {
   ASSERT_TRUE(test_server()->Start());
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
@@ -651,11 +651,11 @@
 
   static const KeyEventTestData kTestCtrlOrCmdT = {
 #if defined(OS_MACOSX)
-    app::VKEY_T, false, false, false, true,
+    ui::VKEY_T, false, false, false, true,
     true, false, false, false, 1,
     { "D 91 0 false false false true" }
 #else
-    app::VKEY_T, true, false, false, false,
+    ui::VKEY_T, true, false, false, false,
     true, false, false, false, 1,
     { "D 17 0 true false false false" }
 #endif
@@ -698,10 +698,10 @@
   // Press Ctrl/Cmd+W, which will close the tab.
 #if defined(OS_MACOSX)
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_W, false, false, false, true));
+      browser(), ui::VKEY_W, false, false, false, true));
 #else
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_W, true, false, false, false));
+      browser(), ui::VKEY_W, true, false, false, false));
 #endif
 
   ASSERT_NO_FATAL_FAILURE(wait_for_tab_closed.Wait());
@@ -712,7 +712,7 @@
 #if defined(OS_MACOSX)
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) {
   static const KeyEventTestData kTestCtrlA = {
-    app::VKEY_A, true, false, false, false,
+    ui::VKEY_A, true, false, false, false,
     false, false, false, false, 4,
     { "D 17 0 true false false false",
       "D 65 0 true false false false",
@@ -721,7 +721,7 @@
   };
 
   static const KeyEventTestData kTestCtrlF = {
-    app::VKEY_F, true, false, false, false,
+    ui::VKEY_F, true, false, false, false,
     false, false, false, false, 4,
     { "D 17 0 true false false false",
       "D 70 0 true false false false",
@@ -730,7 +730,7 @@
   };
 
   static const KeyEventTestData kTestCtrlK = {
-    app::VKEY_K, true, false, false, false,
+    ui::VKEY_K, true, false, false, false,
     false, false, false, false, 4,
     { "D 17 0 true false false false",
       "D 75 0 true false false false",
@@ -762,14 +762,14 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, PageUpDownKeys) {
   static const KeyEventTestData kTestPageUp = {
-    app::VKEY_PRIOR, false, false, false, false,
+    ui::VKEY_PRIOR, false, false, false, false,
     false, false, false, false, 2,
     { "D 33 0 false false false false",
       "U 33 0 false false false false" }
   };
 
   static const KeyEventTestData kTestPageDown = {
-    app::VKEY_NEXT, false, false, false, false,
+    ui::VKEY_NEXT, false, false, false, false,
     false, false, false, false, 2,
     { "D 34 0 false false false false",
       "U 34 0 false false false false" }
@@ -794,21 +794,21 @@
 #if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) {
   static const KeyEventTestData kTestAltKey = {
-    app::VKEY_MENU, false, false, false, false,
+    ui::VKEY_MENU, false, false, false, false,
     false, false, false, false, 2,
     { "D 18 0 false false true false",
       "U 18 0 false false true false" }
   };
 
   static const KeyEventTestData kTestAltKeySuppress = {
-    app::VKEY_MENU, false, false, false, false,
+    ui::VKEY_MENU, false, false, false, false,
     true, false, false, false, 2,
     { "D 18 0 false false true false",
       "U 18 0 false false true false" }
   };
 
   static const KeyEventTestData kTestCtrlAltKey = {
-    app::VKEY_MENU, true, false, false, false,
+    ui::VKEY_MENU, true, false, false, false,
     false, false, false, false, 4,
     { "D 17 0 true false false false",
       "D 18 0 true false true false",
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 6b12dfc..b69bcd8 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,10 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "app/hi_res_timer_manager.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/system_monitor.h"
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
@@ -21,13 +17,13 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/path_service.h"
-#include "base/threading/platform_thread.h"
 #include "base/process_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_piece.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
+#include "base/threading/platform_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
@@ -35,12 +31,12 @@
 #include "build/build_config.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_main_win.h"
-#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/browser/defaults.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_impl.h"
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager_backend.h"
 #include "chrome/browser/extensions/extension_protocols.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extensions_startup.h"
@@ -52,14 +48,18 @@
 #include "chrome/browser/net/blob_url_request_job_factory.h"
 #include "chrome/browser/net/chrome_dns_cert_provenance_checker.h"
 #include "chrome/browser/net/chrome_dns_cert_provenance_checker_factory.h"
+#include "chrome/browser/net/file_system_url_request_job_factory.h"
 #include "chrome/browser/net/metadata_url_request.h"
 #include "chrome/browser/net/predictor_api.h"
 #include "chrome/browser/net/sdch_dictionary_fetcher.h"
 #include "chrome/browser/net/websocket_experiment/websocket_experiment_runner.h"
 #include "chrome/browser/plugin_service.h"
+#include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/pref_value_store.h"
+#include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
+#include "chrome/browser/printing/print_dialog_cloud.h"
 #include "chrome/browser/process_singleton.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -78,12 +78,15 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/env_vars.h"
+#include "chrome/common/gfx_resource_provider.h"
+#include "chrome/common/hi_res_timer_manager.h"
 #include "chrome/common/json_pref_store.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/common/main_function_params.h"
 #include "chrome/common/net/net_resource_provider.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/profiling.h"
 #include "chrome/common/result_codes.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "grit/app_locale_settings.h"
@@ -101,6 +104,10 @@
 #include "net/spdy/spdy_session_pool.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_throttler_manager.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/system_monitor/system_monitor.h"
+#include "ui/gfx/gfx_module.h"
 
 #if defined(USE_LINUX_BREAKPAD)
 #include "base/linux_util.h"
@@ -110,7 +117,7 @@
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
 #include <dbus/dbus-glib.h>
 #include "chrome/browser/browser_main_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -124,36 +131,37 @@
 // progress and should not be taken as an indication of a real refactoring.
 
 #if defined(OS_WIN)
-#include <windows.h>
 #include <commctrl.h>
 #include <shellapi.h>
+#include <windows.h>
 
-#include "app/l10n_util_win.h"
 #include "app/win/scoped_com_initializer.h"
 #include "chrome/browser/browser_trial.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/rlz/rlz.h"
-#include "chrome/browser/views/user_data_dir_dialog.h"
+#include "chrome/browser/ui/views/user_data_dir_dialog.h"
 #include "chrome/common/sandbox_policy.h"
 #include "chrome/installer/util/helper.h"
 #include "chrome/installer/util/install_util.h"
 #include "chrome/installer/util/shell_util.h"
-#include "gfx/platform_font_win.h"
 #include "net/base/net_util.h"
 #include "net/base/sdch_manager.h"
 #include "printing/printed_document.h"
 #include "sandbox/src/sandbox.h"
+#include "ui/base/l10n/l10n_util_win.h"
+#include "ui/gfx/platform_font_win.h"
 #endif  // defined(OS_WIN)
 
 #if defined(OS_MACOSX)
 #include <Security/Security.h>
-#include "chrome/browser/ui/cocoa/install_from_dmg.h"
+#include "chrome/browser/cocoa/install_from_dmg.h"
 #endif
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/chrome_views_delegate.h"
+#include "chrome/browser/ui/views/chrome_views_delegate.h"
 #include "views/focus/accelerator_handler.h"
+#include "views/widget/root_view.h"
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -166,11 +174,11 @@
 #include "chrome/browser/chromeos/login/screen_locker.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/metrics_cros_settings_provider.h"
-#include "chrome/browser/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
 #endif
 
 #if defined(TOOLKIT_USES_GTK)
-#include "gfx/gtk_util.h"
+#include "ui/gfx/gtk_util.h"
 #endif
 
 // BrowserMainParts ------------------------------------------------------------
@@ -191,14 +199,6 @@
   if (parsed_command_line().HasSwitch(switches::kEnableBenchmarking))
     base::FieldTrial::EnableBenchmarking();
 
-  // Note: make sure to call ConnectionFieldTrial() before
-  // ProxyConnectionsFieldTrial().
-  ConnectionFieldTrial();
-  SocketTimeoutFieldTrial();
-  ProxyConnectionsFieldTrial();
-  SpdyFieldTrial();
-  PrefetchFieldTrial();
-  ConnectBackupJobsFieldTrial();
   InitializeSSL();
 
   if (parsed_command_line().HasSwitch(switches::kEnableDNSSECCerts))
@@ -221,6 +221,18 @@
   PostEarlyInitialization();
 }
 
+// This will be called after the command-line has been mutated by about:flags
+void BrowserMainParts::SetupFieldTrials() {
+  // Note: make sure to call ConnectionFieldTrial() before
+  // ProxyConnectionsFieldTrial().
+  ConnectionFieldTrial();
+  SocketTimeoutFieldTrial();
+  ProxyConnectionsFieldTrial();
+  PrefetchAndPrerenderFieldTrial();
+  SpdyFieldTrial();
+  ConnectBackupJobsFieldTrial();
+}
+
 // This is an A/B test for the maximum number of persistent connections per
 // host. Currently Chrome, Firefox, and IE8 have this value set at 6. Safari
 // uses 4, and Fasterfox (a plugin for Firefox that supposedly configures it to
@@ -231,8 +243,16 @@
   const base::FieldTrial::Probability kConnectDivisor = 100;
   const base::FieldTrial::Probability kConnectProbability = 1;  // 1% prob.
 
+  // After June 30, 2011 builds, it will always be in default group.
   scoped_refptr<base::FieldTrial> connect_trial(
-      new base::FieldTrial("ConnCountImpact", kConnectDivisor));
+      new base::FieldTrial(
+          "ConnCountImpact", kConnectDivisor, "conn_count_6", 2011, 6, 30));
+
+  // This (6) is the current default value. Having this group declared here
+  // makes it straightforward to modify |kConnectProbability| such that the same
+  // probability value will be assigned to all the other groups, while
+  // preserving the remainder of the of probability space to the default value.
+  const int connect_6 = connect_trial->kDefaultGroupNumber;
 
   const int connect_5 = connect_trial->AppendGroup("conn_count_5",
                                                    kConnectProbability);
@@ -242,12 +262,6 @@
                                                    kConnectProbability);
   const int connect_9 = connect_trial->AppendGroup("conn_count_9",
                                                    kConnectProbability);
-  // This (6) is the current default value. Having this group declared here
-  // makes it straightforward to modify |kConnectProbability| such that the same
-  // probability value will be assigned to all the other groups, while
-  // preserving the remainder of the of probability space to the default value.
-  const int connect_6 = connect_trial->AppendGroup("conn_count_6",
-      base::FieldTrial::kAllRemainingProbability);
 
   const int connect_trial_group = connect_trial->group();
 
@@ -276,8 +290,11 @@
   // 1% probability for all experimental settings.
   const base::FieldTrial::Probability kSocketTimeoutProbability = 1;
 
+  // After June 30, 2011 builds, it will always be in default group.
   scoped_refptr<base::FieldTrial> socket_timeout_trial(
-      new base::FieldTrial("IdleSktToImpact", kIdleSocketTimeoutDivisor));
+      new base::FieldTrial("IdleSktToImpact", kIdleSocketTimeoutDivisor,
+          "idle_timeout_60", 2011, 6, 30));
+  const int socket_timeout_60 = socket_timeout_trial->kDefaultGroupNumber;
 
   const int socket_timeout_5 =
       socket_timeout_trial->AppendGroup("idle_timeout_5",
@@ -288,9 +305,6 @@
   const int socket_timeout_20 =
       socket_timeout_trial->AppendGroup("idle_timeout_20",
                                         kSocketTimeoutProbability);
-  const int socket_timeout_60 =
-      socket_timeout_trial->AppendGroup("idle_timeout_60",
-          base::FieldTrial::kAllRemainingProbability);
 
   const int idle_to_trial_group = socket_timeout_trial->group();
 
@@ -312,8 +326,16 @@
   // 25% probability
   const base::FieldTrial::Probability kProxyConnectionProbability = 1;
 
+  // After June 30, 2011 builds, it will always be in default group.
   scoped_refptr<base::FieldTrial> proxy_connection_trial(
-      new base::FieldTrial("ProxyConnectionImpact", kProxyConnectionsDivisor));
+      new base::FieldTrial("ProxyConnectionImpact", kProxyConnectionsDivisor,
+          "proxy_connections_32", 2011, 6, 30));
+
+  // This (32 connections per proxy server) is the current default value.
+  // Declaring it here allows us to easily re-assign the probability space while
+  // maintaining that the default group always has the remainder of the "share",
+  // which allows for cleaner and quicker changes down the line if needed.
+  const int proxy_connections_32 = proxy_connection_trial->kDefaultGroupNumber;
 
   // The number of max sockets per group cannot be greater than the max number
   // of sockets per proxy server.  We tried using 8, and it can easily
@@ -325,14 +347,6 @@
       proxy_connection_trial->AppendGroup("proxy_connections_64",
                                           kProxyConnectionProbability);
 
-  // This (32 connections per proxy server) is the current default value.
-  // Declaring it here allows us to easily re-assign the probability space while
-  // maintaining that the default group always has the remainder of the "share",
-  // which allows for cleaner and quicker changes down the line if needed.
-  const int proxy_connections_32 =
-      proxy_connection_trial->AppendGroup("proxy_connections_32",
-          base::FieldTrial::kAllRemainingProbability);
-
   const int proxy_connections_trial_group = proxy_connection_trial->group();
 
   if (proxy_connections_trial_group == proxy_connections_16) {
@@ -363,13 +377,18 @@
     const base::FieldTrial::Probability kSpdyDivisor = 100;
     // 10% to preclude SPDY.
     base::FieldTrial::Probability npnhttp_probability = 10;
+
+    // After June 30, 2011 builds, it will always be in default group.
     scoped_refptr<base::FieldTrial> trial(
-        new base::FieldTrial("SpdyImpact", kSpdyDivisor));
+        new base::FieldTrial(
+            "SpdyImpact", kSpdyDivisor, "npn_with_spdy", 2011, 6, 30));
+
+    // npn with spdy support is the default.
+    int npn_spdy_grp = trial->kDefaultGroupNumber;
+
     // npn with only http support, no spdy.
     int npn_http_grp = trial->AppendGroup("npn_with_http", npnhttp_probability);
-    // npn with spdy support.
-    int npn_spdy_grp = trial->AppendGroup("npn_with_spdy",
-        base::FieldTrial::kAllRemainingProbability);
+
     int trial_grp = trial->group();
     if (trial_grp == npn_http_grp) {
       is_spdy_trial = true;
@@ -388,14 +407,17 @@
   const base::FieldTrial::Probability kSpdyCwnd16 = 20;     // fixed at 16
   const base::FieldTrial::Probability kSpdyCwndMin16 = 20;  // no less than 16
   const base::FieldTrial::Probability kSpdyCwndMin10 = 20;  // no less than 10
+
+  // After June 30, 2011 builds, it will always be in default group
+  // (cwndDynamic).
   scoped_refptr<base::FieldTrial> trial(
-      new base::FieldTrial("SpdyCwnd", kSpdyCwndDivisor));
+      new base::FieldTrial(
+          "SpdyCwnd", kSpdyCwndDivisor, "cwndDynamic", 2011, 6, 30));
+
   trial->AppendGroup("cwnd32", kSpdyCwnd32);
   trial->AppendGroup("cwnd16", kSpdyCwnd16);
   trial->AppendGroup("cwndMin16", kSpdyCwndMin16);
   trial->AppendGroup("cwndMin10", kSpdyCwndMin10);
-  trial->AppendGroup("cwndDynamic",
-                     base::FieldTrial::kAllRemainingProbability);
 
   if (parsed_command_line().HasSwitch(switches::kMaxSpdyConcurrentStreams)) {
     int value = 0;
@@ -407,29 +429,77 @@
   }
 }
 
-// If any of --enable-prerender, --enable-content-prefetch or
-// --disable-content-prefetch are set, use those to determine if
-// prefetch is enabled. Otherwise, randomly assign users to an A/B test for
-// prefetching.
-void BrowserMainParts::PrefetchFieldTrial() {
-  if (parsed_command_line().HasSwitch(switches::kEnableContentPrefetch) ||
-      parsed_command_line().HasSwitch(switches::kEnablePagePrerender))
-    ResourceDispatcherHost::set_is_prefetch_enabled(true);
-  else if (parsed_command_line().HasSwitch(switches::kDisableContentPrefetch)) {
-    ResourceDispatcherHost::set_is_prefetch_enabled(false);
-  } else {
-    const base::FieldTrial::Probability kPrefetchDivisor = 1000;
-    const base::FieldTrial::Probability no_prefetch_probability = 500;
-    scoped_refptr<base::FieldTrial> trial(
-        new base::FieldTrial("Prefetch", kPrefetchDivisor));
-    trial->AppendGroup("ContentPrefetchDisabled", no_prefetch_probability);
-    const int yes_prefetch_grp =
-        trial->AppendGroup("ContentPrefetchEnabled",
-                           base::FieldTrial::kAllRemainingProbability);
-    const int trial_grp = trial->group();
-    ResourceDispatcherHost::set_is_prefetch_enabled(
-        trial_grp == yes_prefetch_grp);
+// Parse the --prerender= command line switch, which controls both prerendering
+// and prefetching.  If the switch is unset, or is set to "auto", then the user
+// is assigned to a field trial.
+void BrowserMainParts::PrefetchAndPrerenderFieldTrial() {
+  enum PrerenderOption {
+    PRERENDER_OPTION_AUTO,
+    PRERENDER_OPTION_DISABLED,
+    PRERENDER_OPTION_ENABLED,
+    PRERENDER_OPTION_PREFETCH_ONLY,
+  };
+
+  PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
+  if (parsed_command_line().HasSwitch(switches::kPrerender)) {
+    const std::string switch_value =
+        parsed_command_line().GetSwitchValueASCII(switches::kPrerender);
+
+    if (switch_value == switches::kPrerenderSwitchValueAuto) {
+      prerender_option = PRERENDER_OPTION_AUTO;
+    } else if (switch_value == switches::kPrerenderSwitchValueDisabled) {
+      prerender_option = PRERENDER_OPTION_DISABLED;
+    } else if (switch_value.empty() ||
+               switch_value == switches::kPrerenderSwitchValueEnabled) {
+      // The empty string means the option was provided with no value, and that
+      // means enable.
+      prerender_option = PRERENDER_OPTION_ENABLED;
+    } else if (switch_value == switches::kPrerenderSwitchValuePrefetchOnly) {
+      prerender_option = PRERENDER_OPTION_PREFETCH_ONLY;
+    } else {
+      prerender_option = PRERENDER_OPTION_DISABLED;
+      LOG(ERROR) << "Invalid --prerender option received on command line: "
+                 << switch_value;
+      LOG(ERROR) << "Disabling prerendering!";
+    }
   }
+
+  switch (prerender_option) {
+    case PRERENDER_OPTION_AUTO: {
+      const base::FieldTrial::Probability kPrefetchDivisor = 1000;
+      const base::FieldTrial::Probability no_prefetch_probability = 500;
+      // After June 30, 2011 builds, it will always be in default group.
+      scoped_refptr<base::FieldTrial> trial(
+          new base::FieldTrial("Prefetch", kPrefetchDivisor,
+                               "ContentPrefetchEnabled", 2011, 6, 30));
+      const int yes_prefetch_grp = trial->kDefaultGroupNumber;
+      trial->AppendGroup("ContentPrefetchDisabled", no_prefetch_probability);
+      const int trial_grp = trial->group();
+      ResourceDispatcherHost::set_is_prefetch_enabled(
+          trial_grp == yes_prefetch_grp);
+
+      // There is currently no prerendering field trial.
+      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
+      break;
+    }
+    case PRERENDER_OPTION_DISABLED:
+      ResourceDispatcherHost::set_is_prefetch_enabled(false);
+      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
+      break;
+    case PRERENDER_OPTION_ENABLED:
+      ResourceDispatcherHost::set_is_prefetch_enabled(true);
+      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
+      break;
+    case PRERENDER_OPTION_PREFETCH_ONLY:
+      ResourceDispatcherHost::set_is_prefetch_enabled(true);
+      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  UMA_HISTOGRAM_ENUMERATION("Prerender.Sessions", PrerenderManager::GetMode(),
+                            PrerenderManager::PRERENDER_MODE_MAX);
 }
 
 // If neither --enable-connect-backup-jobs or --disable-connect-backup-jobs is
@@ -447,14 +517,14 @@
     const base::FieldTrial::Probability kConnectBackupJobsDivisor = 100;
     // 1% probability.
     const base::FieldTrial::Probability kConnectBackupJobsProbability = 1;
+    // After June 30, 2011 builds, it will always be in defaut group.
     scoped_refptr<base::FieldTrial> trial(
         new base::FieldTrial("ConnnectBackupJobs",
-                             kConnectBackupJobsDivisor));
+            kConnectBackupJobsDivisor, "ConnectBackupJobsEnabled", 2011, 6,
+                30));
+    const int connect_backup_jobs_enabled = trial->kDefaultGroupNumber;
     trial->AppendGroup("ConnectBackupJobsDisabled",
                        kConnectBackupJobsProbability);
-    const int connect_backup_jobs_enabled =
-        trial->AppendGroup("ConnectBackupJobsEnabled",
-                           base::FieldTrial::kAllRemainingProbability);
     const int trial_group = trial->group();
     net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(
         trial_group == connect_backup_jobs_enabled);
@@ -469,13 +539,14 @@
   main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI));
 
   // TODO(viettrungluu): should these really go before setting the thread name?
-  system_monitor_.reset(new SystemMonitor);
+  system_monitor_.reset(new ui::SystemMonitor);
   hi_res_timer_manager_.reset(new HighResolutionTimerManager);
   network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
 
   InitializeMainThread();
 
   PostMainMessageLoopStart();
+  Profiling::MainMessageLoopStarted();
 }
 
 void BrowserMainParts::InitializeMainThread() {
@@ -519,13 +590,9 @@
 void RunUIMessageLoop(BrowserProcess* browser_process) {
   TRACE_EVENT_BEGIN("BrowserMain:MESSAGE_LOOP", 0, "");
 
-#if !defined(OS_CHROMEOS)
   // If the UI thread blocks, the whole UI is unresponsive.
   // Do not allow disk IO from the UI thread.
-  // TODO(evanm): turn this on for all platforms.
-  //   http://code.google.com/p/chromium/issues/detail?id=60211
   base::ThreadRestrictions::SetIOAllowed(false);
-#endif
 
 #if defined(TOOLKIT_VIEWS)
   views::AcceleratorHandler accelerator_handler;
@@ -587,10 +654,8 @@
     net::SpdySessionPool::set_max_sessions_per_domain(value);
   }
 
-  if (parsed_command_line.HasSwitch(switches::kDisableEnforcedThrottling)) {
-    net::URLRequestThrottlerManager::GetInstance()->
-        set_enforce_throttling(false);
-  }
+  net::URLRequestThrottlerManager::GetInstance()->InitializeOptions(
+      parsed_command_line.HasSwitch(switches::kDisableEnforcedThrottling));
 
   SetDnsCertProvenanceCheckerFactory(CreateChromeDnsCertProvenanceChecker);
 }
@@ -618,11 +683,18 @@
   PrefService* local_state = g_browser_process->local_state();
   DCHECK(local_state);
 
+  // TODO(brettw,*): this comment about ResourceBundle was here since
+  // initial commit.  This comment seems unrelated, bit-rotten and
+  // a candidate for removal.
   // Initialize ResourceBundle which handles files loaded from external
   // sources. This has to be done before uninstall code path and before prefs
   // are registered.
-  local_state->RegisterStringPref(prefs::kApplicationLocale,
+  local_state->RegisterStringPref(prefs::kApplicationLocale, std::string());
+#if defined(OS_CHROMEOS)
+  local_state->RegisterStringPref(prefs::kOwnerLocale, std::string());
+  local_state->RegisterStringPref(prefs::kHardwareKeyboardLayout,
                                   std::string());
+#endif  // defined(OS_CHROMEOS)
 #if !defined(OS_CHROMEOS)
   local_state->RegisterBooleanPref(prefs::kMetricsReportingEnabled,
       GoogleUpdateSettings::GetCollectStatsConsent());
@@ -901,6 +973,9 @@
   // display the correct icon.
   if (!views::ViewsDelegate::views_delegate)
     views::ViewsDelegate::views_delegate = new ChromeViewsDelegate;
+
+  if (parameters.command_line_.HasSwitch(switches::kDebugViewsPaint))
+    views::RootView::EnableDebugPaint();
 #endif
 
 #if defined(OS_WIN)
@@ -1048,6 +1123,11 @@
 // Main routine for running as the Browser process.
 int BrowserMain(const MainFunctionParams& parameters) {
   TRACE_EVENT_BEGIN("BrowserMain", 0, "");
+
+  // If we're running tests (ui_task is non-null).
+  if (parameters.ui_task)
+    browser_defaults::enable_help_app = false;
+
   scoped_ptr<BrowserMainParts>
       parts(BrowserMainParts::CreateBrowserMainParts(parameters));
 
@@ -1156,10 +1236,10 @@
 #if defined(OS_MACOSX)
     g_browser_process->SetApplicationLocale(l10n_util::GetLocaleOverride());
 #else
-    // On a POSIX OS other than ChromeOS, the parameter that is passed to the
-    // method InitSharedInstance is ignored.
     const std::string locale =
         local_state->GetString(prefs::kApplicationLocale);
+    // On a POSIX OS other than ChromeOS, the parameter that is passed to the
+    // method InitSharedInstance is ignored.
     const std::string loaded_locale =
         ResourceBundle::InitSharedInstance(locale);
     CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
@@ -1168,7 +1248,7 @@
     FilePath resources_pack_path;
     PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
     ResourceBundle::AddDataPackToSharedInstance(resources_pack_path);
-#endif  // !defined(OS_MACOSX)
+#endif  // defined(OS_MACOSX)
   }
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
@@ -1232,6 +1312,14 @@
   // Initialize the prefs of the local state.
   browser::RegisterLocalState(local_state);
 
+  // Convert active labs into switches. Modifies the current command line.
+  about_flags::ConvertFlagsToSwitches(local_state,
+                                      CommandLine::ForCurrentProcess());
+
+  // Now the command line has been mutated based on about:flags, we can run some
+  // field trials
+  parts->SetupFieldTrials();
+
   // Now that all preferences have been registered, set the install date
   // for the uninstall metrics if this is our first run. This only actually
   // gets used if the user has metrics reporting enabled at uninstall time.
@@ -1379,8 +1467,6 @@
   }
 #endif
 
-  // Modifies the current command line based on active experiments on
-  // about:flags.
   Profile* profile = CreateProfile(parameters, user_data_dir);
   if (!profile)
     return ResultCodes::NORMAL_EXIT;
@@ -1497,16 +1583,20 @@
 #endif
 #endif
 
-  // Configure the network module so it has access to resources.
+  // Configure modules that need access to resources.
   net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
+  gfx::GfxModule::SetResourceProvider(chrome::GfxResourceProvider);
 
   // Register our global network handler for chrome:// and
   // chrome-extension:// URLs.
-  RegisterURLRequestChromeJob();
+  ChromeURLDataManagerBackend::Register();
   RegisterExtensionProtocols();
   RegisterMetadataURLRequestHandler();
   RegisterBlobURLRequestJobFactory();
 
+  if (parsed_command_line.HasSwitch(switches::kEnableFileSystemURLScheme))
+    RegisterFileSystemURLRequestJobFactory();
+
   // In unittest mode, this will do nothing.  In normal mode, this will create
   // the global GoogleURLTracker and IntranetRedirectDetector instances, which
   // will promptly go to sleep for five and seven seconds, respectively (to
@@ -1531,8 +1621,11 @@
   // layout globally.
   base::FieldTrial::Probability kSDCH_DIVISOR = 1000;
   base::FieldTrial::Probability kSDCH_DISABLE_PROBABILITY = 1;  // 0.1% prob.
+  // After June 30, 2011 builds, it will always be in default group.
   scoped_refptr<base::FieldTrial> sdch_trial(
-      new base::FieldTrial("GlobalSdch", kSDCH_DIVISOR));
+      new base::FieldTrial("GlobalSdch", kSDCH_DIVISOR, "global_enable_sdch",
+          2011, 6, 30));
+  int sdch_enabled = sdch_trial->kDefaultGroupNumber;
 
   // Use default of "" so that all domains are supported.
   std::string sdch_supported_domain("");
@@ -1542,13 +1635,11 @@
   } else {
     sdch_trial->AppendGroup("global_disable_sdch",
                             kSDCH_DISABLE_PROBABILITY);
-    int sdch_enabled = sdch_trial->AppendGroup("global_enable_sdch",
-        base::FieldTrial::kAllRemainingProbability);
     if (sdch_enabled != sdch_trial->group())
       sdch_supported_domain = "never_enabled_sdch_for_any_domain";
   }
 
-  SdchManager sdch_manager;  // Singleton database.
+  net::SdchManager sdch_manager;  // Singleton database.
   sdch_manager.set_sdch_fetcher(new SdchDictionaryFetcher);
   sdch_manager.EnableSdchSupport(sdch_supported_domain);
 
@@ -1565,7 +1656,7 @@
 
   HandleTestParameters(parsed_command_line);
   RecordBreakpadStatusUMA(metrics);
-  about_flags::RecordUMAStatistics(user_prefs);
+  about_flags::RecordUMAStatistics(local_state);
 
   // Stat the directory with the inspector's files so that we can know if we
   // should display the entry in the context menu or not.
@@ -1623,6 +1714,29 @@
     }
   }
 
+  if (parsed_command_line.HasSwitch(switches::kCloudPrintFile)) {
+    FilePath cloud_print_file;
+    cloud_print_file =
+        parsed_command_line.GetSwitchValuePath(switches::kCloudPrintFile);
+    if (!cloud_print_file.empty()) {
+      string16 print_job_title;
+    if (parsed_command_line.HasSwitch(switches::kCloudPrintJobTitle)) {
+#ifdef OS_WIN
+      CommandLine::StringType native_job_title;
+      native_job_title = CommandLine::ForCurrentProcess()->GetSwitchValueNative(
+          switches::kCloudPrintJobTitle);
+      print_job_title = string16(native_job_title);
+#elif defined(OS_POSIX)
+      // TODO(abodenha@google.com) Implement this for OS_POSIX
+      // Command line string types are different
+#endif
+    }
+      PrintDialogCloud::CreatePrintDialogForPdf(cloud_print_file,
+                                                print_job_title,
+                                                false);
+    }
+  }
+
 #if defined(OS_CHROMEOS)
   // Run the Out of Memory priority manager while in this scope.  Wait
   // until here to start so that we give the most amount of time for
diff --git a/chrome/browser/browser_main.h b/chrome/browser/browser_main.h
index 9154a4c..1c0b371 100644
--- a/chrome/browser/browser_main.h
+++ b/chrome/browser/browser_main.h
@@ -17,12 +17,15 @@
 struct MainFunctionParams;
 class MessageLoop;
 class MetricsService;
-class SystemMonitor;
 
 namespace net {
 class NetworkChangeNotifier;
 }
 
+namespace ui {
+class SystemMonitor;
+}
+
 // BrowserMainParts:
 // This class contains different "stages" to be executed in |BrowserMain()|,
 // mostly initialization. This is made into a class rather than just functions
@@ -77,6 +80,8 @@
   void EarlyInitialization();
   void MainMessageLoopStart();
 
+  void SetupFieldTrials();
+
  protected:
   explicit BrowserMainParts(const MainFunctionParams& parameters);
 
@@ -113,8 +118,9 @@
   // A/B test for spdy when --use-spdy not set.
   void SpdyFieldTrial();
 
-  // A/B test for prefetching with --(enable|disable)-prefetch not set.
-  void PrefetchFieldTrial();
+  // A/B test for prefetching with --(enable|disable)-prefetch not set,
+  // some histograms tracking prerender sessions.
+  void PrefetchAndPrerenderFieldTrial();
 
   // A/B test for automatically establishing a backup TCP connection when a
   // specified timeout value is reached.
@@ -144,7 +150,7 @@
 
   // Members initialized in |MainMessageLoopStart()| ---------------------------
   scoped_ptr<MessageLoop> main_message_loop_;
-  scoped_ptr<SystemMonitor> system_monitor_;
+  scoped_ptr<ui::SystemMonitor> system_monitor_;
   scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
   scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
   scoped_ptr<BrowserThread> main_thread_;
diff --git a/chrome/browser/browser_main_gtk.cc b/chrome/browser/browser_main_gtk.cc
index ec73aaf..f80daa9 100644
--- a/chrome/browser/browser_main_gtk.cc
+++ b/chrome/browser/browser_main_gtk.cc
@@ -8,8 +8,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "app/x11_util.h"
-#include "app/x11_util_internal.h"
 #include "base/command_line.h"
 #include "base/debug/debugger.h"
 #include "chrome/browser/browser_list.h"
@@ -20,6 +18,8 @@
 #include "chrome/browser/zygote_host_linux.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/result_codes.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/base/x/x11_util_internal.h"
 
 #if defined(USE_NSS)
 #include "base/nss_util.h"
@@ -36,7 +36,7 @@
 
 int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) {
   if (!g_in_x11_io_error_handler)
-    LOG(ERROR) << x11_util::GetErrorEventDescription(d, error);
+    LOG(ERROR) << ui::GetErrorEventDescription(d, error);
   return 0;
 }
 
@@ -128,9 +128,7 @@
 void SetBrowserX11ErrorHandlers() {
   // Set up error handlers to make sure profile gets written if X server
   // goes away.
-  x11_util::SetX11ErrorHandlers(
-      BrowserX11ErrorHandler,
-      BrowserX11IOErrorHandler);
+  ui::SetX11ErrorHandlers(BrowserX11ErrorHandler, BrowserX11IOErrorHandler);
 }
 
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/browser_main_mac.mm b/chrome/browser/browser_main_mac.mm
index fa88bc8..e47e268 100644
--- a/chrome/browser/browser_main_mac.mm
+++ b/chrome/browser/browser_main_mac.mm
@@ -7,8 +7,6 @@
 #import <Cocoa/Cocoa.h>
 
 #include "app/app_switches.h"
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/debug/debugger.h"
 #include "base/file_path.h"
@@ -20,13 +18,15 @@
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/browser_main_win.h"
 #import "chrome/browser/chrome_browser_application_mac.h"
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
+#import "chrome/browser/cocoa/keystone_glue.h"
 #include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/main_function_params.h"
 #include "chrome/common/result_codes.h"
 #include "net/socket/ssl_client_socket_mac_factory.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 void DidEndMainMessageLoop() {
   AppController* appController = [NSApp delegate];
diff --git a/chrome/browser/browser_main_win.cc b/chrome/browser/browser_main_win.cc
index 2c763c7..cf5e783 100644
--- a/chrome/browser/browser_main_win.cc
+++ b/chrome/browser/browser_main_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,9 +10,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_win.h"
-#include "app/win/win_util.h"
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/i18n/rtl.h"
@@ -24,7 +21,7 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/metrics/metrics_service.h"
-#include "chrome/browser/views/uninstall_view.h"
+#include "chrome/browser/ui/views/uninstall_view.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/env_vars.h"
 #include "chrome/common/main_function_params.h"
@@ -37,6 +34,9 @@
 #include "grit/generated_resources.h"
 #include "net/base/winsock_init.h"
 #include "net/socket/ssl_client_socket_nss_factory.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_win.h"
+#include "ui/base/message_box_win.h"
 #include "views/focus/accelerator_handler.h"
 #include "views/window/window.h"
 
@@ -57,8 +57,7 @@
     const string16 text =
         l10n_util::GetStringUTF16(IDS_UNSUPPORTED_OS_PRE_WIN_XP);
     const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
-    app::win::MessageBox(NULL, text, caption,
-                         MB_OK | MB_ICONWARNING | MB_TOPMOST);
+    ui::MessageBox(NULL, text, caption, MB_OK | MB_ICONWARNING | MB_TOPMOST);
   }
 }
 
@@ -75,7 +74,7 @@
   const string16 text = l10n_util::GetStringUTF16(IDS_UNINSTALL_CLOSE_APP);
   const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
   const UINT flags = MB_OK | MB_ICONWARNING | MB_TOPMOST;
-  app::win::MessageBox(NULL, text, caption, flags);
+  ui::MessageBox(NULL, text, caption, flags);
 }
 
 int DoUninstallTasks(bool chrome_still_running) {
@@ -167,7 +166,7 @@
         l10n_util::GetStringFUTF16(IDS_HIDE_ICONS_NOT_SUPPORTED, cp_applet);
     const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
     const UINT flags = MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST;
-    if (IDOK == app::win::MessageBox(NULL, msg, caption, flags))
+    if (IDOK == ui::MessageBox(NULL, msg, caption, flags))
       ShellExecute(NULL, NULL, L"appwiz.cpl", NULL, NULL, SW_SHOWNORMAL);
     return ResultCodes::NORMAL_EXIT;  // Exit as we are not launching browser.
   }
@@ -194,10 +193,10 @@
           l10n_util::GetStringUTF16(IDS_MACHINE_LEVEL_INSTALL_CONFLICT);
       const string16 caption = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
       const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST;
-      app::win::MessageBox(NULL, text, caption, flags);
-      FilePath uninstall_path(InstallUtil::GetChromeUninstallCmd(false, dist));
-      CommandLine uninstall_cmd(uninstall_path);
-      if (!uninstall_cmd.GetProgram().value().empty()) {
+      ui::MessageBox(NULL, text, caption, flags);
+      CommandLine uninstall_cmd(
+          InstallUtil::GetChromeUninstallCmd(false, dist->GetType()));
+      if (!uninstall_cmd.GetProgram().empty()) {
         uninstall_cmd.AppendSwitch(installer::switches::kForceUninstall);
         uninstall_cmd.AppendSwitch(
             installer::switches::kDoNotRemoveSharedItems);
diff --git a/chrome/browser/browser_message_filter.cc b/chrome/browser/browser_message_filter.cc
index d226af4..e68de00 100644
--- a/chrome/browser/browser_message_filter.cc
+++ b/chrome/browser/browser_message_filter.cc
@@ -15,6 +15,7 @@
 }
 
 BrowserMessageFilter::~BrowserMessageFilter() {
+  base::CloseProcessHandle(peer_handle_);
 }
 
 void BrowserMessageFilter::OnFilterAdded(IPC::Channel* channel) {
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index 409771a..17979c2 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -23,7 +23,7 @@
 class ClientSideDetectionService;
 }
 
-class Clipboard;
+class ChromeNetLog;
 class DevToolsManager;
 class DownloadRequestLimiter;
 class DownloadStatusUpdater;
@@ -54,6 +54,10 @@
 class ConfigurationPolicyProviderKeeper;
 }
 
+namespace ui {
+class Clipboard;
+}
+
 // NOT THREAD SAFE, call only from the main thread.
 // These functions shouldn't return NULL unless otherwise noted.
 class BrowserProcess {
@@ -75,7 +79,7 @@
   virtual PrefService* local_state() = 0;
   virtual DevToolsManager* devtools_manager() = 0;
   virtual SidebarManager* sidebar_manager() = 0;
-  virtual Clipboard* clipboard() = 0;
+  virtual ui::Clipboard* clipboard() = 0;
 
   // Returns the manager for desktop notifications.
   virtual NotificationUIManager* notification_ui_manager() = 0;
@@ -120,7 +124,12 @@
 
   virtual AutomationProviderList* InitAutomationProviderList() = 0;
 
-  virtual void InitDebuggerWrapper(int port, bool useHttp) = 0;
+  virtual void InitDevToolsHttpProtocolHandler(
+      const std::string& ip,
+      int port,
+      const std::string& frontend_url) = 0;
+
+  virtual void InitDevToolsLegacyProtocolHandler(int port) = 0;
 
   virtual unsigned int AddRefModule() = 0;
   virtual unsigned int ReleaseModule() = 0;
@@ -177,6 +186,8 @@
   // case, we default to returning true.
   virtual bool have_inspector_files() const = 0;
 
+  virtual ChromeNetLog* net_log() = 0;
+
 #if defined(IPC_MESSAGE_LOG_ENABLED)
   // Enable or disable IPC logging for the browser, all processes
   // derived from ChildProcess (plugin etc), and all
@@ -184,10 +195,21 @@
   virtual void SetIPCLoggingEnabled(bool enable) = 0;
 #endif
 
+  const std::string& plugin_data_remover_mime_type() const {
+    return plugin_data_remover_mime_type_;
+  }
+
+  void set_plugin_data_remover_mime_type(const std::string& mime_type) {
+    plugin_data_remover_mime_type_ = mime_type;
+  }
+
  private:
   // User-data-dir based profiles.
   std::vector<std::wstring> user_data_dir_profiles_;
 
+  // Used for testing plugin data removal at shutdown.
+  std::string plugin_data_remover_mime_type_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserProcess);
 };
 
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 222ee28..b7d1115 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -6,8 +6,6 @@
 
 #include <map>
 
-#include "app/clipboard/clipboard.h"
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
@@ -15,7 +13,6 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/synchronization/waitable_event.h"
-#include "chrome/browser/appcache/chrome_appcache_service.h"
 #include "chrome/browser/automation/automation_provider_list.h"
 #include "chrome/browser/browser_child_process_host.h"
 #include "chrome/browser/browser_list.h"
@@ -23,8 +20,10 @@
 #include "chrome/browser/browser_process_sub_thread.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/browser_trial.h"
-#include "chrome/browser/debugger/debugger_wrapper.h"
+#include "chrome/browser/debugger/browser_list_tabcontents_provider.h"
+#include "chrome/browser/debugger/devtools_http_protocol_handler.h"
 #include "chrome/browser/debugger/devtools_manager.h"
+#include "chrome/browser/debugger/devtools_protocol_handler.h"
 #include "chrome/browser/download/download_file_manager.h"
 #include "chrome/browser/download/save_file_manager.h"
 #include "chrome/browser/first_run/first_run.h"
@@ -49,6 +48,7 @@
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/shell_integration.h"
 #include "chrome/browser/sidebar/sidebar_manager.h"
 #include "chrome/browser/tab_closeable_state_watcher.h"
 #include "chrome/common/chrome_constants.h"
@@ -63,6 +63,8 @@
 #include "chrome/common/switch_utils.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "ipc/ipc_logging.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/database/database_tracker.h"
 
 #if defined(OS_WIN)
@@ -98,7 +100,6 @@
       created_profile_manager_(false),
       created_local_state_(false),
       created_icon_manager_(false),
-      created_debugger_wrapper_(false),
       created_devtools_manager_(false),
       created_sidebar_manager_(false),
       created_configuration_policy_provider_keeper_(false),
@@ -110,7 +111,7 @@
       using_new_frames_(false),
       have_inspector_files_(true) {
   g_browser_process = this;
-  clipboard_.reset(new Clipboard);
+  clipboard_.reset(new ui::Clipboard);
   main_notification_service_.reset(new NotificationService);
 
   notification_registrar_.Add(this,
@@ -147,14 +148,16 @@
   // any pending URLFetchers, and avoid creating any more.
   SdchDictionaryFetcher::Shutdown();
 
-  // We need to destroy the MetricsService, GoogleURLTracker, and
-  // IntranetRedirectDetector before the io_thread_ gets destroyed, since their
-  // destructors can call the URLFetcher destructor, which does a
-  // PostDelayedTask operation on the IO thread.  (The IO thread will handle
-  // that URLFetcher operation before going away.)
+  // We need to destroy the MetricsService, GoogleURLTracker,
+  // IntranetRedirectDetector, and SafeBrowsing ClientSideDetectionService
+  // before the io_thread_ gets destroyed, since their destructors can call the
+  // URLFetcher destructor, which does a PostDelayedTask operation on the IO
+  // thread. (The IO thread will handle that URLFetcher operation before going
+  // away.)
   metrics_service_.reset();
   google_url_tracker_.reset();
   intranet_redirect_detector_.reset();
+  safe_browsing_detection_service_.reset();
 
   // Need to clear the desktop notification balloons before the io_thread_ and
   // before the profiles, since if there are any still showing we will access
@@ -165,7 +168,14 @@
   profile_manager_.reset();
 
   // Debugger must be cleaned up before IO thread and NotificationService.
-  debugger_wrapper_ = NULL;
+  if (devtools_http_handler_.get()) {
+    devtools_http_handler_->Stop();
+    devtools_http_handler_ = NULL;
+  }
+  if (devtools_legacy_handler_.get()) {
+    devtools_legacy_handler_->Stop();
+    devtools_legacy_handler_ = NULL;
+  }
 
   if (resource_dispatcher_host_.get()) {
     // Need to tell Safe Browsing Service that the IO thread is going away
@@ -408,7 +418,7 @@
   return sidebar_manager_.get();
 }
 
-Clipboard* BrowserProcessImpl::clipboard() {
+ui::Clipboard* BrowserProcessImpl::clipboard() {
   DCHECK(CalledOnValidThread());
   return clipboard_.get();
 }
@@ -451,10 +461,21 @@
   return automation_provider_list_.get();
 }
 
-void BrowserProcessImpl::InitDebuggerWrapper(int port, bool useHttp) {
+void BrowserProcessImpl::InitDevToolsHttpProtocolHandler(
+    const std::string& ip,
+    int port,
+    const std::string& frontend_url) {
   DCHECK(CalledOnValidThread());
-  if (!created_debugger_wrapper_)
-    CreateDebuggerWrapper(port, useHttp);
+  devtools_http_handler_ =
+      DevToolsHttpProtocolHandler::Start(ip,
+                                         port,
+                                         frontend_url,
+                                         new BrowserListTabContentsProvider());
+}
+
+void BrowserProcessImpl::InitDevToolsLegacyProtocolHandler(int port) {
+  DCHECK(CalledOnValidThread());
+  devtools_legacy_handler_ = DevToolsProtocolHandler::Start(port);
 }
 
 bool BrowserProcessImpl::IsShuttingDown() {
@@ -540,25 +561,28 @@
     Profile* profile = ProfileManager::GetDefaultProfile();
     if (profile) {
       PrefService* prefs = profile->GetPrefs();
-      if (prefs->GetBoolean(prefs::kClearPluginLSODataOnExit) &&
+      if (prefs->GetBoolean(prefs::kClearSiteDataOnExit) &&
           local_state()->GetBoolean(prefs::kClearPluginLSODataEnabled)) {
         plugin_data_remover_ = new PluginDataRemover();
-        plugin_data_remover_->StartRemoving(base::Time(), NULL);
+        if (!plugin_data_remover_mime_type().empty())
+          plugin_data_remover_->set_mime_type(plugin_data_remover_mime_type());
+        plugin_data_remover_->StartRemoving(base::Time());
       }
     }
+  } else if (type == NotificationType::PREF_CHANGED) {
+    std::string* pref = Details<std::string>(details).ptr();
+    if (*pref == prefs::kDefaultBrowserSettingEnabled) {
+      if (local_state_->GetBoolean(prefs::kDefaultBrowserSettingEnabled))
+        ShellIntegration::SetAsDefaultBrowser();
+    }
   } else {
     NOTREACHED();
   }
 }
 
 void BrowserProcessImpl::WaitForPluginDataRemoverToFinish() {
-  if (!plugin_data_remover_.get() || !plugin_data_remover_->is_removing())
-    return;
-  plugin_data_remover_->set_done_task(new MessageLoop::QuitTask());
-  base::Time start_time(base::Time::Now());
-  MessageLoop::current()->Run();
-  UMA_HISTOGRAM_TIMES("ClearPluginData.wait_at_shutdown",
-                      base::Time::Now() - start_time);
+  if (plugin_data_remover_.get())
+    plugin_data_remover_->Wait();
 }
 
 #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
@@ -574,9 +598,12 @@
   return have_inspector_files_;
 }
 
+ChromeNetLog* BrowserProcessImpl::net_log() {
+  return net_log_.get();
+}
+
 void BrowserProcessImpl::ClearLocalState(const FilePath& profile_path) {
   webkit_database::DatabaseTracker::ClearLocalState(profile_path);
-  ChromeAppCacheService::ClearLocalState(profile_path);
 }
 
 bool BrowserProcessImpl::ShouldClearLocalState(FilePath* profile_path) {
@@ -728,6 +755,15 @@
   print_job_manager_->set_printing_enabled(printing_enabled);
   pref_change_registrar_.Add(prefs::kPrintingEnabled,
                              print_job_manager_.get());
+
+  // Initialize the notification for the default browser setting policy.
+  local_state_->RegisterBooleanPref(prefs::kDefaultBrowserSettingEnabled,
+                                    false);
+  if (local_state_->IsManagedPreference(prefs::kDefaultBrowserSettingEnabled)) {
+    if (local_state_->GetBoolean(prefs::kDefaultBrowserSettingEnabled))
+      ShellIntegration::SetAsDefaultBrowser();
+  }
+  pref_change_registrar_.Add(prefs::kDefaultBrowserSettingEnabled, this);
 }
 
 void BrowserProcessImpl::CreateIconManager() {
@@ -736,13 +772,6 @@
   icon_manager_.reset(new IconManager);
 }
 
-void BrowserProcessImpl::CreateDebuggerWrapper(int port, bool useHttp) {
-  DCHECK(debugger_wrapper_.get() == NULL);
-  created_debugger_wrapper_ = true;
-
-  debugger_wrapper_ = new DebuggerWrapper(port, useHttp);
-}
-
 void BrowserProcessImpl::CreateDevToolsManager() {
   DCHECK(devtools_manager_.get() == NULL);
   created_devtools_manager_ = true;
@@ -806,15 +835,11 @@
 
 bool BrowserProcessImpl::IsSafeBrowsingDetectionServiceEnabled() {
   // The safe browsing client-side detection is enabled only if the switch is
-  // enabled, the user has opted in to UMA usage stats and SafeBrowsing
-  // is enabled.
-  Profile* profile = profile_manager() ?
-      profile_manager()->GetDefaultProfile() : NULL;
-  return (CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kEnableClientSidePhishingDetection) &&
-          metrics_service() && metrics_service()->reporting_active() &&
-          profile && profile->GetPrefs() &&
-          profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled));
+  // enabled and when safe browsing related stats is allowed to be collected.
+  return CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableClientSidePhishingDetection) &&
+      resource_dispatcher_host()->safe_browsing_service() &&
+      resource_dispatcher_host()->safe_browsing_service()->CanReportStats();
 }
 
 // The BrowserProcess object must outlive the file thread so we use traits
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 8ec6f81..5353a12 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -28,7 +28,8 @@
 
 class ChromeNetLog;
 class CommandLine;
-class DebuggerWrapper;
+class DevToolsHttpProtocolHandler;
+class DevToolsProtocolHandler;
 class FilePath;
 class NotificationService;
 class PluginDataRemover;
@@ -59,14 +60,18 @@
   virtual PrefService* local_state();
   virtual DevToolsManager* devtools_manager();
   virtual SidebarManager* sidebar_manager();
-  virtual Clipboard* clipboard();
+  virtual ui::Clipboard* clipboard();
   virtual NotificationUIManager* notification_ui_manager();
   virtual policy::ConfigurationPolicyProviderKeeper*
       configuration_policy_provider_keeper();
   virtual IconManager* icon_manager();
   virtual ThumbnailGenerator* GetThumbnailGenerator();
   virtual AutomationProviderList* InitAutomationProviderList();
-  virtual void InitDebuggerWrapper(int port, bool useHttp);
+  virtual void InitDevToolsHttpProtocolHandler(
+      const std::string& ip,
+      int port,
+      const std::string& frontend_url);
+  virtual void InitDevToolsLegacyProtocolHandler(int port);
   virtual unsigned int AddRefModule();
   virtual unsigned int ReleaseModule();
   virtual bool IsShuttingDown();
@@ -94,6 +99,8 @@
 
   virtual bool have_inspector_files() const;
 
+  virtual ChromeNetLog* net_log();
+
 #if defined(IPC_MESSAGE_LOG_ENABLED)
   virtual void SetIPCLoggingEnabled(bool enable);
 #endif
@@ -121,7 +128,6 @@
   void CreateLocalState();
   void CreateViewedPageTracker();
   void CreateIconManager();
-  void CreateDebuggerWrapper(int port, bool useHttp);
   void CreateDevToolsManager();
   void CreateSidebarManager();
   void CreateGoogleURLTracker();
@@ -172,8 +178,9 @@
   bool created_icon_manager_;
   scoped_ptr<IconManager> icon_manager_;
 
-  bool created_debugger_wrapper_;
-  scoped_refptr<DebuggerWrapper> debugger_wrapper_;
+  scoped_refptr<DevToolsHttpProtocolHandler> devtools_http_handler_;
+
+  scoped_refptr<DevToolsProtocolHandler> devtools_legacy_handler_;
 
   bool created_devtools_manager_;
   scoped_refptr<DevToolsManager> devtools_manager_;
@@ -188,7 +195,7 @@
   scoped_refptr<printing::PrintPreviewTabController>
       print_preview_tab_controller_;
 
-  scoped_ptr<Clipboard> clipboard_;
+  scoped_ptr<ui::Clipboard> clipboard_;
 
   // Manager for desktop notification UI.
   bool created_notification_ui_manager_;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 3d03dbf..9748ac0 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -24,7 +24,6 @@
         <include name="IDR_ABOUT_MEMORY_HTML" file="resources\about_memory.html" flattenhtml="true" type="BINDATA" />
       </if>
       <include name="IDR_ABOUT_STATS_HTML" file="resources\about_stats.html" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_ABOUT_SYNC_HTML" file="sync\resources\about_sync.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_ABOUT_VERSION_HTML" file="resources\about_version.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_BOOKMARKS_MANIFEST" file="resources\bookmark_manager\manifest.json" type="BINDATA" />
       <include name="IDR_CREDITS_HTML" file="resources\about_credits.html" flattenhtml="true" type="BINDATA" />
@@ -53,13 +52,14 @@
       <include name="IDR_NOTIFICATION_ICON_HTML" file="resources\notification_icon.html" type="BINDATA" />
       <include name="IDR_OPTIONS_HTML" file="resources\options\options.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_PLUGINS_HTML" file="resources\plugins.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_READER_OUT_OF_DATE_HTML" file="resources\reader_out_of_date.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_PRINT_PREVIEW_HTML" file="resources\print_preview.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SAFE_BROWSING_MALWARE_BLOCK" file="resources\safe_browsing_malware_block.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SAFE_BROWSING_MULTIPLE_THREAT_BLOCK" file="resources\safe_browsing_multiple_threat_block.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SAFE_BROWSING_PHISHING_BLOCK" file="resources\safe_browsing_phishing_block.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SIGNIN_HTML" file="resources\browser_signin.html" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_SSL_ERROR_HTML" file="security\resources\ssl_error.html" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_SSL_ROAD_BLOCK_HTML" file="security\resources\ssl_roadblock.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_SSL_ERROR_HTML" file="resources\ssl_error.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_SSL_ROAD_BLOCK_HTML" file="resources\ssl_roadblock.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SYNC_CONFIGURE_HTML" file="sync\resources\configure.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SYNC_ENCRYPTION_LOGIN_HTML" file="sync\resources\encryption_login.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_SYNC_PASSPHRASE_HTML" file="sync\resources\passphrase.html" flattenhtml="true" type="BINDATA" />
@@ -70,6 +70,7 @@
       <include name="IDR_REMOTING_SETUP_FLOW_HTML" file="remoting\resources\remoting_setup_flow.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_REMOTING_SETUP_DONE_HTML" file="remoting\resources\remoting_setup_done.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_REMOTING_SETUP_ERROR_HTML" file="remoting\resources\remoting_setup_error.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_REMOTING_SETTING_UP_HTML" file="remoting\resources\remoting_setting_up.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_CLOUD_PRINT_SETUP_FLOW_HTML" file="printing\cloud_print\resources\cloud_print_setup_flow.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_CLOUD_PRINT_SETUP_LOGIN_HTML" file="printing\cloud_print\resources\cloud_print_setup_login.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_CLOUD_PRINT_SETUP_DONE_HTML" file="printing\cloud_print\resources\cloud_print_setup_done.html" flattenhtml="true" type="BINDATA" />
@@ -100,6 +101,13 @@
         <include name="IDR_NETWORK_MENU_JS" file="resources\network_menu.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_WRENCH_MENU_JS" file="resources\wrench_menu.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_WRENCH_MENU_CSS" file="resources\wrench_menu.css" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_MOBILE_MANIFEST" file="resources\mobile_app\manifest.json" type="BINDATA" />
+        <!-- manifest file of ChromeVox accessibility extension -->
+        <include name="IDR_CHROMEVOX_MANIFEST" file="resources\access_chromevox\manifest.json" type="BINDATA" />
+      </if>
+      <if expr="pp_ifdef('chromeos') and pp_ifdef('_google_chrome')">
+        <include name="IDR_HELP_MANIFEST" file="resources\help_app\manifest.json" type="BINDATA" />
+        <include name="IDR_GETSTARTED_MANIFEST" file="resources\getstarted\manifest.json" type="BINDATA" />
       </if>
     </includes>
   </release>
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index 72c0350..198a75c 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/browser_shutdown.h"
 
+#include <map>
 #include <string>
 
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
@@ -33,12 +33,14 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/browser/service/service_process_control_manager.h"
+#include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/chrome_plugin_lib.h"
 #include "chrome/common/switch_utils.h"
 #include "net/predictor_api.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/rlz/rlz.h"
@@ -48,7 +50,7 @@
 #include "chrome/browser/chromeos/boot_times_loader.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/login_library.h"
-#include "chrome/browser/chromeos/wm_ipc.h"
+#include "chrome/browser/chromeos/system_key_event_listener.h"
 #endif
 
 using base::Time;
@@ -127,6 +129,12 @@
   // Shutdown all IPC channels to service processes.
   ServiceProcessControlManager::GetInstance()->Shutdown();
 
+#if defined(OS_CHROMEOS)
+  // The system key event listener needs to be shut down earlier than when
+  // Singletons are finally destroyed in AtExitManager.
+  chromeos::SystemKeyEventListener::GetInstance()->Stop();
+#endif
+
   // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough
   // time to get here. If you have something that *must* happen on end session,
   // consider putting it in BrowserProcessImpl::EndSession.
@@ -249,14 +257,11 @@
     file_util::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len);
   }
 
-  UnregisterURLRequestChromeJob();
-
 #if defined(OS_CHROMEOS)
-  chromeos::WmIpc::instance()->NotifyAboutSignout();
-  if (chromeos::CrosLibrary::Get()->EnsureLoaded()) {
-    chromeos::CrosLibrary::Get()->GetLoginLibrary()->StopSession("");
-  }
+  BrowserList::NotifyAndTerminate(false);
 #endif
+
+  ChromeURLDataManager::DeleteDataSources();
 }
 
 void ReadLastShutdownFile(
diff --git a/chrome/browser/browser_signin.cc b/chrome/browser/browser_signin.cc
index 535dcd5..bb03c8f 100644
--- a/chrome/browser/browser_signin.cc
+++ b/chrome/browser/browser_signin.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "app/resource_bundle.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/message_loop.h"
@@ -17,8 +16,8 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/dom_ui/constrained_html_ui.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
@@ -32,6 +31,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class BrowserSigninResourcesSource : public ChromeURLDataManager::DataSource {
  public:
@@ -75,7 +75,7 @@
 }
 
 class BrowserSigninHtml : public HtmlDialogUIDelegate,
-                          public DOMMessageHandler {
+                          public WebUIMessageHandler {
  public:
   BrowserSigninHtml(BrowserSignin* signin,
                     string16 suggested_email,
@@ -92,10 +92,10 @@
   virtual GURL GetDialogContentURL() const {
     return GURL("chrome://dialog/signin");
   }
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const {
-    const DOMMessageHandler* handler = this;
-    handlers->push_back(const_cast<DOMMessageHandler*>(handler));
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const {
+    const WebUIMessageHandler* handler = this;
+    handlers->push_back(const_cast<WebUIMessageHandler*>(handler));
   }
   virtual void GetDialogSize(gfx::Size* size) const {
     size->set_width(600);
@@ -112,7 +112,7 @@
   }
   virtual bool ShouldShowDialogTitle() const { return true; }
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Refreshes the UI, such as after an authentication error.
@@ -145,9 +145,9 @@
 }
 
 void BrowserSigninHtml::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "SubmitAuth", NewCallback(this, &BrowserSigninHtml::HandleSubmitAuth));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "SigninInit", NewCallback(this, &BrowserSigninHtml::HandleSigninInit));
 }
 
@@ -156,20 +156,21 @@
 }
 
 void BrowserSigninHtml::ForceDialogClose() {
-  if (!closed_ && dom_ui_) {
+  if (!closed_ && web_ui_) {
     StringValue value("DialogClose");
     ListValue close_args;
     close_args.Append(new StringValue(""));
-    dom_ui_->CallJavascriptFunction(L"chrome.send", value, close_args);
+    web_ui_->CallJavascriptFunction(L"chrome.send", value, close_args);
   }
 }
 
 void BrowserSigninHtml::HandleSigninInit(const ListValue* args) {
-  if (!dom_ui_)
+  if (!web_ui_)
     return;
 
-  RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
-  rvh->ExecuteJavascriptInWebFrame(L"//iframe[@id='login']", L"hideBlurb();");
+  RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
+  rvh->ExecuteJavascriptInWebFrame(ASCIIToUTF16("//iframe[@id='login']"),
+                                   ASCIIToUTF16("hideBlurb();"));
 
   DictionaryValue json_args;
   std::string json;
@@ -188,11 +189,12 @@
 
   base::JSONWriter::Write(&json_args, false, &json);
   javascript += L"showGaiaLogin(" + UTF8ToWide(json) + L");";
-  rvh->ExecuteJavascriptInWebFrame(L"//iframe[@id='login']", javascript);
+  rvh->ExecuteJavascriptInWebFrame(ASCIIToUTF16("//iframe[@id='login']"),
+                                   WideToUTF16Hack(javascript));
 }
 
 void BrowserSigninHtml::HandleSubmitAuth(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
   scoped_ptr<DictionaryValue> result(static_cast<DictionaryValue*>(
       base::JSONReader::Read(json, false)));
   std::string username;
@@ -215,12 +217,11 @@
     : profile_(profile),
       delegate_(NULL),
       html_dialog_ui_delegate_(NULL) {
-  BrowserSigninResourcesSource* source = new BrowserSigninResourcesSource();
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(source)));
+  // profile is NULL during testing.
+  if (profile) {
+    BrowserSigninResourcesSource* source = new BrowserSigninResourcesSource();
+    profile->GetChromeURLDataManager()->AddDataSource(source);
+  }
 }
 
 BrowserSignin::~BrowserSignin() {
@@ -285,7 +286,7 @@
 void BrowserSignin::OnLoginFinished() {
   if (html_dialog_ui_delegate_)
     html_dialog_ui_delegate_->ForceDialogClose();
-  // The dialog will be deleted by DOMUI due to the dialog close,
+  // The dialog will be deleted by WebUI due to the dialog close,
   // don't hold a reference.
   html_dialog_ui_delegate_ = NULL;
 
diff --git a/chrome/browser/browser_thread.cc b/chrome/browser/browser_thread.cc
index 60d4450..877c2c5 100644
--- a/chrome/browser/browser_thread.cc
+++ b/chrome/browser/browser_thread.cc
@@ -63,7 +63,7 @@
 };
 
 
-Lock BrowserThread::lock_;
+base::Lock BrowserThread::lock_;
 
 BrowserThread* BrowserThread::browser_threads_[ID_COUNT];
 
@@ -81,7 +81,7 @@
 }
 
 void BrowserThread::Initialize() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
   DCHECK(browser_threads_[identifier_] == NULL);
   browser_threads_[identifier_] = this;
@@ -93,7 +93,7 @@
   // correct BrowserThread succeeds.
   Stop();
 
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   browser_threads_[identifier_] = NULL;
 #ifndef NDEBUG
   // Double check that the threads are ordered correctly in the enumeration.
@@ -106,7 +106,7 @@
 
 // static
 bool BrowserThread::IsWellKnownThread(ID identifier) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   return (identifier >= 0 && identifier < ID_COUNT &&
           browser_threads_[identifier]);
 }
@@ -118,7 +118,7 @@
   // function.
   // http://crbug.com/63678
   base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK(identifier >= 0 && identifier < ID_COUNT);
   return browser_threads_[identifier] &&
          browser_threads_[identifier]->message_loop() == MessageLoop::current();
@@ -126,7 +126,7 @@
 
 // static
 bool BrowserThread::IsMessageLoopValid(ID identifier) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK(identifier >= 0 && identifier < ID_COUNT);
   return browser_threads_[identifier] &&
          browser_threads_[identifier]->message_loop();
diff --git a/chrome/browser/browser_thread.h b/chrome/browser/browser_thread.h
index ce3c295..dc4b00b 100644
--- a/chrome/browser/browser_thread.h
+++ b/chrome/browser/browser_thread.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_BROWSER_THREAD_H_
 #pragma once
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "base/threading/thread.h"
 
@@ -197,7 +197,7 @@
 
   // This lock protects |browser_threads_|.  Do not read or modify that array
   // without holding this lock.  Do not block while holding this lock.
-  static Lock lock_;
+  static base::Lock lock_;
 
   // An array of the BrowserThread objects.  This array is protected by |lock_|.
   // The threads are not owned by this array.  Typically, the threads are owned
diff --git a/chrome/browser/browser_url_handler.cc b/chrome/browser/browser_url_handler.cc
index 6d55e3e..beb1156 100644
--- a/chrome/browser/browser_url_handler.cc
+++ b/chrome/browser/browser_url_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,8 @@
 
 #include "base/string_util.h"
 #include "chrome/browser/browser_about_handler.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
@@ -59,9 +59,9 @@
   return true;
 }
 
-// Handles rewriting DOM UI URLs.
-static bool HandleDOMUI(GURL* url, Profile* profile) {
-  if (!DOMUIFactory::UseDOMUIForURL(profile, *url))
+// Handles rewriting Web UI URLs.
+static bool HandleWebUI(GURL* url, Profile* profile) {
+  if (!WebUIFactory::UseWebUIForURL(profile, *url))
     return false;
 
   // Special case the new tab page. In older versions of Chrome, the new tab
@@ -83,13 +83,23 @@
   if (!url_handlers_.empty())
     return;
 
+  // Visual Studio 2010 has problems converting NULL to the null pointer for
+  // std::pair.  See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
+  // It will work if we pass nullptr.
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+  URLHandler null_handler = nullptr;
+#else
+  URLHandler null_handler = NULL;
+#endif
+
   // Add the default URL handlers.
   url_handlers_.push_back(
-      HandlerPair(&ExtensionDOMUI::HandleChromeURLOverride, NULL));
+      HandlerPair(&ExtensionWebUI::HandleChromeURLOverride, null_handler));
   // about:
-  url_handlers_.push_back(HandlerPair(&WillHandleBrowserAboutURL, NULL));
+  url_handlers_.push_back(HandlerPair(&WillHandleBrowserAboutURL,
+                                      null_handler));
   // chrome: & friends.
-  url_handlers_.push_back(HandlerPair(&HandleDOMUI, NULL));
+  url_handlers_.push_back(HandlerPair(&HandleWebUI, null_handler));
   // view-source:
   url_handlers_.push_back(HandlerPair(&HandleViewSource, &ReverseViewSource));
 }
diff --git a/chrome/browser/browsing_data_database_helper.cc b/chrome/browser/browsing_data_database_helper.cc
index ad822bc..9f2ecd3 100644
--- a/chrome/browser/browsing_data_database_helper.cc
+++ b/chrome/browser/browsing_data_database_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,14 +11,43 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/profiles/profile.h"
 #include "net/base/net_errors.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+
+using WebKit::WebSecurityOrigin;
+
+BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo() {}
+
+BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo(
+    const std::string& host,
+    const std::string& database_name,
+    const std::string& origin_identifier,
+    const std::string& description,
+    const std::string& origin,
+    int64 size,
+    base::Time last_modified)
+    : host(host),
+      database_name(database_name),
+      origin_identifier(origin_identifier),
+      description(description),
+      origin(origin),
+      size(size),
+      last_modified(last_modified) {
+}
+
+BrowsingDataDatabaseHelper::DatabaseInfo::~DatabaseInfo() {}
+
+bool BrowsingDataDatabaseHelper::DatabaseInfo::IsFileSchemeData() {
+  return StartsWithASCII(origin_identifier,
+                         std::string(chrome::kFileScheme),
+                         true);
+}
 
 BrowsingDataDatabaseHelper::BrowsingDataDatabaseHelper(Profile* profile)
-    : tracker_(profile->GetDatabaseTracker()),
-      completion_callback_(NULL),
-      is_fetching_(false) {
+    : completion_callback_(NULL),
+      is_fetching_(false),
+      tracker_(profile->GetDatabaseTracker()) {
 }
 
 BrowsingDataDatabaseHelper::~BrowsingDataDatabaseHelper() {
@@ -32,8 +61,8 @@
   is_fetching_ = true;
   database_info_.clear();
   completion_callback_.reset(callback);
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, NewRunnableMethod(
-      this, &BrowsingDataDatabaseHelper::FetchDatabaseInfoInFileThread));
+  BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod(
+      this, &BrowsingDataDatabaseHelper::FetchDatabaseInfoInWebKitThread));
 }
 
 void BrowsingDataDatabaseHelper::CancelNotification() {
@@ -44,13 +73,13 @@
 void BrowsingDataDatabaseHelper::DeleteDatabase(const std::string& origin,
                                                 const std::string& name) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, NewRunnableMethod(
-      this, &BrowsingDataDatabaseHelper::DeleteDatabaseInFileThread, origin,
+  BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod(
+      this, &BrowsingDataDatabaseHelper::DeleteDatabaseInWebKitThread, origin,
       name));
 }
 
-void BrowsingDataDatabaseHelper::FetchDatabaseInfoInFileThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+void BrowsingDataDatabaseHelper::FetchDatabaseInfoInWebKitThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   std::vector<webkit_database::OriginInfo> origins_info;
   if (tracker_.get() && tracker_->GetAllOriginsInfo(&origins_info)) {
     for (std::vector<webkit_database::OriginInfo>::const_iterator ori =
@@ -62,8 +91,8 @@
         // Extension state is not considered browsing data.
         continue;
       }
-      WebKit::WebSecurityOrigin web_security_origin =
-          WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
+      WebSecurityOrigin web_security_origin =
+          WebSecurityOrigin::createFromDatabaseIdentifier(
               ori->GetOrigin());
       std::vector<string16> databases;
       ori->GetAllDatabaseNames(&databases);
@@ -102,15 +131,28 @@
   database_info_.clear();
 }
 
-void BrowsingDataDatabaseHelper::DeleteDatabaseInFileThread(
+void BrowsingDataDatabaseHelper::DeleteDatabaseInWebKitThread(
     const std::string& origin,
     const std::string& name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   if (!tracker_.get())
     return;
   tracker_->DeleteDatabase(UTF8ToUTF16(origin), UTF8ToUTF16(name), NULL);
 }
 
+CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo() {}
+
+CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo(
+    const GURL& origin,
+    const std::string& name,
+    const std::string& description)
+    : origin(origin),
+      name(name),
+      description(description) {
+}
+
+CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::~PendingDatabaseInfo() {}
+
 CannedBrowsingDataDatabaseHelper::CannedBrowsingDataDatabaseHelper(
     Profile* profile)
     : BrowsingDataDatabaseHelper(profile) {
@@ -120,39 +162,69 @@
     const GURL& origin,
     const std::string& name,
     const std::string& description) {
-  WebKit::WebSecurityOrigin web_security_origin =
-      WebKit::WebSecurityOrigin::createFromString(
-          UTF8ToUTF16(origin.spec()));
-  std::string origin_identifier =
-      web_security_origin.databaseIdentifier().utf8();
-
-  for (std::vector<DatabaseInfo>::iterator database = database_info_.begin();
-       database != database_info_.end(); ++database) {
-    if (database->origin_identifier == origin_identifier &&
-        database->database_name == name)
-      return;
-  }
-
-  database_info_.push_back(DatabaseInfo(
-        web_security_origin.host().utf8(),
-        name,
-        origin_identifier,
-        description,
-        web_security_origin.toString().utf8(),
-        0,
-        base::Time()));
+  base::AutoLock auto_lock(lock_);
+  pending_database_info_.push_back(PendingDatabaseInfo(
+        origin, name, description));
 }
 
 void CannedBrowsingDataDatabaseHelper::Reset() {
+  base::AutoLock auto_lock(lock_);
   database_info_.clear();
+  pending_database_info_.clear();
 }
 
 bool CannedBrowsingDataDatabaseHelper::empty() const {
- return database_info_.empty();
+  base::AutoLock auto_lock(lock_);
+ return database_info_.empty() && pending_database_info_.empty();
 }
 
 void CannedBrowsingDataDatabaseHelper::StartFetching(
     Callback1<const std::vector<DatabaseInfo>& >::Type* callback) {
-  callback->Run(database_info_);
-  delete callback;
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!is_fetching_);
+  DCHECK(callback);
+  is_fetching_ = true;
+  completion_callback_.reset(callback);
+  BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod(
+      this, &CannedBrowsingDataDatabaseHelper::ConvertInfoInWebKitThread));
+}
+
+CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {}
+
+void CannedBrowsingDataDatabaseHelper::ConvertInfoInWebKitThread() {
+  base::AutoLock auto_lock(lock_);
+  for (std::vector<PendingDatabaseInfo>::const_iterator
+       info = pending_database_info_.begin();
+       info != pending_database_info_.end(); ++info) {
+    WebSecurityOrigin web_security_origin =
+        WebSecurityOrigin::createFromString(
+            UTF8ToUTF16(info->origin.spec()));
+    std::string origin_identifier =
+        web_security_origin.databaseIdentifier().utf8();
+
+    bool duplicate = false;
+    for (std::vector<DatabaseInfo>::iterator database = database_info_.begin();
+         database != database_info_.end(); ++database) {
+      if (database->origin_identifier == origin_identifier &&
+          database->database_name == info->name) {
+        duplicate = true;
+        break;
+      }
+    }
+    if (duplicate)
+      continue;
+
+    database_info_.push_back(DatabaseInfo(
+        web_security_origin.host().utf8(),
+        info->name,
+        origin_identifier,
+        info->description,
+        web_security_origin.toString().utf8(),
+        0,
+        base::Time()));
+  }
+  pending_database_info_.clear();
+
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
+      this, &CannedBrowsingDataDatabaseHelper::NotifyInUIThread));
 }
diff --git a/chrome/browser/browsing_data_database_helper.h b/chrome/browser/browsing_data_database_helper.h
index 26210a7..2d870ee 100644
--- a/chrome/browser/browsing_data_database_helper.h
+++ b/chrome/browser/browsing_data_database_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,14 +11,15 @@
 
 #include "base/callback.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
 #include "webkit/database/database_tracker.h"
 
 class Profile;
 
-// This class fetches database information in the FILE thread, and notifies the
-// UI thread upon completion.
+// This class fetches database information in the WEBKIT thread, and notifies
+// the UI thread upon completion.
 // A client of this class need to call StartFetching from the UI thread to
 // initiate the flow, and it'll be notified by the callback in its UI
 // thread at some later point.
@@ -29,28 +30,17 @@
  public:
   // Contains detailed information about a web database.
   struct DatabaseInfo {
-    DatabaseInfo() {}
+    DatabaseInfo();
     DatabaseInfo(const std::string& host,
                  const std::string& database_name,
                  const std::string& origin_identifier,
                  const std::string& description,
                  const std::string& origin,
                  int64 size,
-                 base::Time last_modified)
-        : host(host),
-          database_name(database_name),
-          origin_identifier(origin_identifier),
-          description(description),
-          origin(origin),
-          size(size),
-          last_modified(last_modified) {
-    }
+                 base::Time last_modified);
+    ~DatabaseInfo();
 
-    bool IsFileSchemeData() {
-      return StartsWithASCII(origin_identifier,
-                             std::string(chrome::kFileScheme),
-                             true);
-    }
+    bool IsFileSchemeData();
 
     std::string host;
     std::string database_name;
@@ -74,7 +64,7 @@
   // This must be called only in the UI thread.
   virtual void CancelNotification();
 
-  // Requests a single database to be deleted in the FILE thread. This must be
+  // Requests a single database to be deleted in the WEBKIT thread. This must be
   // called in the UI thread.
   virtual void DeleteDatabase(const std::string& origin,
                               const std::string& name);
@@ -83,21 +73,11 @@
   friend class base::RefCountedThreadSafe<BrowsingDataDatabaseHelper>;
   virtual ~BrowsingDataDatabaseHelper();
 
-  // This only mutates in the FILE thread.
-  std::vector<DatabaseInfo> database_info_;
-
- private:
-  // Enumerates all databases. This must be called in the FILE thread.
-  void FetchDatabaseInfoInFileThread();
-
   // Notifies the completion callback. This must be called in the UI thread.
   void NotifyInUIThread();
 
-  // Delete a single database file. This must be called in the FILE thread.
-  void DeleteDatabaseInFileThread(const std::string& origin,
-                                  const std::string& name);
-
-  scoped_refptr<webkit_database::DatabaseTracker> tracker_;
+  // This only mutates in the WEBKIT thread.
+  std::vector<DatabaseInfo> database_info_;
 
   // This only mutates on the UI thread.
   scoped_ptr<Callback1<const std::vector<DatabaseInfo>& >::Type >
@@ -109,6 +89,16 @@
   // This only mutates on the UI thread.
   bool is_fetching_;
 
+ private:
+  // Enumerates all databases. This must be called in the WEBKIT thread.
+  void FetchDatabaseInfoInWebKitThread();
+
+  // Delete a single database file. This must be called in the WEBKIT thread.
+  void DeleteDatabaseInWebKitThread(const std::string& origin,
+                                  const std::string& name);
+
+  scoped_refptr<webkit_database::DatabaseTracker> tracker_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataDatabaseHelper);
 };
 
@@ -137,7 +127,28 @@
   virtual void CancelNotification() {}
 
  private:
-  virtual ~CannedBrowsingDataDatabaseHelper() {}
+  struct PendingDatabaseInfo {
+    PendingDatabaseInfo();
+    PendingDatabaseInfo(const GURL& origin,
+                        const std::string& name,
+                        const std::string& description);
+    ~PendingDatabaseInfo();
+
+    GURL origin;
+    std::string name;
+    std::string description;
+  };
+
+  virtual ~CannedBrowsingDataDatabaseHelper();
+
+  // Converts the pending database info structs to database info structs.
+  void ConvertInfoInWebKitThread();
+
+  // Used to protect access to pending_database_info_.
+  mutable base::Lock lock_;
+
+  // This may mutate on WEBKIT and UI threads.
+  std::vector<PendingDatabaseInfo> pending_database_info_;
 
   DISALLOW_COPY_AND_ASSIGN(CannedBrowsingDataDatabaseHelper);
 };
diff --git a/chrome/browser/browsing_data_database_helper_browsertest.cc b/chrome/browser/browsing_data_database_helper_browsertest.cc
index 82b47fb..9d2c85f 100644
--- a/chrome/browser/browsing_data_database_helper_browsertest.cc
+++ b/chrome/browser/browsing_data_database_helper_browsertest.cc
@@ -1,18 +1,23 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/file_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data_helper_browsertest.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/testing_profile.h"
 #include "chrome/test/ui_test_utils.h"
 
-static const char kTestIdentifier1[] = "http_www.google.com_0";
+namespace {
+typedef BrowsingDataHelperCallback<BrowsingDataDatabaseHelper::DatabaseInfo>
+    TestCompletionCallback;
 
-static const char kTestIdentifierExtension[] =
+const char kTestIdentifier1[] = "http_www.google.com_0";
+
+const char kTestIdentifierExtension[] =
   "chrome-extension_behllobkkfkfnphdnhnkndlbkcpglgmj_0";
 
 class BrowsingDataDatabaseHelperTest : public InProcessBrowserTest {
@@ -81,3 +86,57 @@
   // Blocks until StopTestOnCallback::Callback is notified.
   ui_test_utils::RunMessageLoop();
 }
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataDatabaseHelperTest, CannedAddDatabase) {
+  const GURL origin1("http://host1:1/");
+  const GURL origin2("http://host2:1/");
+  const char origin_str1[] = "http_host1_1";
+  const char origin_str2[] = "http_host2_1";
+  const char db1[] = "db1";
+  const char db2[] = "db2";
+  const char db3[] = "db3";
+
+  scoped_refptr<CannedBrowsingDataDatabaseHelper> helper(
+      new CannedBrowsingDataDatabaseHelper(&testing_profile_));
+  helper->AddDatabase(origin1, db1, "");
+  helper->AddDatabase(origin1, db2, "");
+  helper->AddDatabase(origin2, db3, "");
+
+  TestCompletionCallback callback;
+  helper->StartFetching(
+      NewCallback(&callback, &TestCompletionCallback::callback));
+
+  std::vector<BrowsingDataDatabaseHelper::DatabaseInfo> result =
+      callback.result();
+
+  ASSERT_EQ(3u, result.size());
+  EXPECT_STREQ(origin_str1, result[0].origin_identifier.c_str());
+  EXPECT_STREQ(db1, result[0].database_name.c_str());
+  EXPECT_STREQ(origin_str1, result[1].origin_identifier.c_str());
+  EXPECT_STREQ(db2, result[1].database_name.c_str());
+  EXPECT_STREQ(origin_str2, result[2].origin_identifier.c_str());
+  EXPECT_STREQ(db3, result[2].database_name.c_str());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataDatabaseHelperTest, CannedUnique) {
+  const GURL origin("http://host1:1/");
+  const char origin_str[] = "http_host1_1";
+  const char db[] = "db1";
+
+  scoped_refptr<CannedBrowsingDataDatabaseHelper> helper(
+      new CannedBrowsingDataDatabaseHelper(&testing_profile_));
+  helper->AddDatabase(origin, db, "");
+  helper->AddDatabase(origin, db, "");
+
+  TestCompletionCallback callback;
+  helper->StartFetching(
+      NewCallback(&callback, &TestCompletionCallback::callback));
+
+  std::vector<BrowsingDataDatabaseHelper::DatabaseInfo> result =
+      callback.result();
+
+  ASSERT_EQ(1u, result.size());
+  EXPECT_STREQ(origin_str, result[0].origin_identifier.c_str());
+  EXPECT_STREQ(db, result[0].database_name.c_str());
+}
+}  // namespace
diff --git a/chrome/browser/browsing_data_database_helper_unittest.cc b/chrome/browser/browsing_data_database_helper_unittest.cc
index ca23f39..75442ad 100644
--- a/chrome/browser/browsing_data_database_helper_unittest.cc
+++ b/chrome/browser/browsing_data_database_helper_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,91 +9,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
-class TestCompletionCallback {
- public:
-  TestCompletionCallback()
-      : have_result_(false) {
-  }
-
-  bool have_result() const { return have_result_; }
-
-  const std::vector<BrowsingDataDatabaseHelper::DatabaseInfo>& result() {
-    return result_;
-  }
-
-  void callback(const std::vector<
-          BrowsingDataDatabaseHelper::DatabaseInfo>& info) {
-    have_result_ = true;
-    result_ = info;
-  }
-
- private:
-  bool have_result_;
-  std::vector<BrowsingDataDatabaseHelper::DatabaseInfo> result_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestCompletionCallback);
-};
-}  // namespace
-
-TEST(CannedBrowsingDataDatabaseTest, AddDatabase) {
-  TestingProfile profile;
-
-  const GURL origin1("http://host1:1/");
-  const GURL origin2("http://host2:1/");
-  const char origin_str1[] = "http_host1_1";
-  const char origin_str2[] = "http_host2_1";
-  const char db1[] = "db1";
-  const char db2[] = "db2";
-  const char db3[] = "db3";
-
-  scoped_refptr<CannedBrowsingDataDatabaseHelper> helper(
-      new CannedBrowsingDataDatabaseHelper(&profile));
-  helper->AddDatabase(origin1, db1, "");
-  helper->AddDatabase(origin1, db2, "");
-  helper->AddDatabase(origin2, db3, "");
-
-  TestCompletionCallback callback;
-  helper->StartFetching(
-      NewCallback(&callback, &TestCompletionCallback::callback));
-  ASSERT_TRUE(callback.have_result());
-
-  std::vector<BrowsingDataDatabaseHelper::DatabaseInfo> result =
-      callback.result();
-
-  ASSERT_EQ(3u, result.size());
-  EXPECT_STREQ(origin_str1, result[0].origin_identifier.c_str());
-  EXPECT_STREQ(db1, result[0].database_name.c_str());
-  EXPECT_STREQ(origin_str1, result[1].origin_identifier.c_str());
-  EXPECT_STREQ(db2, result[1].database_name.c_str());
-  EXPECT_STREQ(origin_str2, result[2].origin_identifier.c_str());
-  EXPECT_STREQ(db3, result[2].database_name.c_str());
-}
-
-TEST(CannedBrowsingDataDatabaseTest, Unique) {
-  TestingProfile profile;
-
-  const GURL origin("http://host1:1/");
-  const char origin_str[] = "http_host1_1";
-  const char db[] = "db1";
-
-  scoped_refptr<CannedBrowsingDataDatabaseHelper> helper(
-      new CannedBrowsingDataDatabaseHelper(&profile));
-  helper->AddDatabase(origin, db, "");
-  helper->AddDatabase(origin, db, "");
-
-  TestCompletionCallback callback;
-  helper->StartFetching(
-      NewCallback(&callback, &TestCompletionCallback::callback));
-  ASSERT_TRUE(callback.have_result());
-
-  std::vector<BrowsingDataDatabaseHelper::DatabaseInfo> result =
-      callback.result();
-
-  ASSERT_EQ(1u, result.size());
-  EXPECT_STREQ(origin_str, result[0].origin_identifier.c_str());
-  EXPECT_STREQ(db, result[0].database_name.c_str());
-}
-
 TEST(CannedBrowsingDataDatabaseTest, Empty) {
   TestingProfile profile;
 
@@ -109,3 +24,4 @@
   helper->Reset();
   ASSERT_TRUE(helper->empty());
 }
+}  // namespace
diff --git a/chrome/browser/browsing_data_helper_browsertest.h b/chrome/browser/browsing_data_helper_browsertest.h
new file mode 100644
index 0000000..d62db7a
--- /dev/null
+++ b/chrome/browser/browsing_data_helper_browsertest.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Contains code shared by all browsing data browsertests.
+
+#ifndef CHROME_BROWSER_BROWSING_DATA_HELPER_BROWSERTEST_H_
+#define CHROME_BROWSER_BROWSING_DATA_HELPER_BROWSERTEST_H_
+#pragma once
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+
+// This template can be used for the StartFetching methods of the browsing data
+// helper classes. It is supposed to be instantiated with the respective
+// browsing data info type.
+template <typename T>
+class BrowsingDataHelperCallback {
+ public:
+  BrowsingDataHelperCallback()
+      : has_result_(false) {
+  }
+
+  const std::vector<T>& result() {
+    MessageLoop::current()->Run();
+    DCHECK(has_result_);
+    return result_;
+  }
+
+  void callback(const std::vector<T>& info) {
+    result_ = info;
+    has_result_ = true;
+    MessageLoop::current()->Quit();
+  }
+
+ private:
+  bool has_result_;
+  std::vector<T> result_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowsingDataHelperCallback);
+};
+
+#endif  // CHROME_BROWSER_BROWSING_DATA_HELPER_BROWSERTEST_H_
diff --git a/chrome/browser/browsing_data_indexed_db_helper.cc b/chrome/browser/browsing_data_indexed_db_helper.cc
index 8b07235..7afea58 100644
--- a/chrome/browser/browsing_data_indexed_db_helper.cc
+++ b/chrome/browser/browsing_data_indexed_db_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,9 +12,9 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/browser/profiles/profile.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebSecurityOrigin;
@@ -109,7 +109,7 @@
        file_path = file_enumerator.Next()) {
     if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) {
       WebSecurityOrigin web_security_origin =
-          WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
+          WebSecurityOrigin::createFromDatabaseIdentifier(
               webkit_glue::FilePathToWebString(file_path.BaseName()));
       if (EqualsASCII(web_security_origin.protocol(),
                       chrome::kExtensionScheme)) {
@@ -158,56 +158,136 @@
 
 }  // namespace
 
+BrowsingDataIndexedDBHelper::IndexedDBInfo::IndexedDBInfo(
+    const std::string& protocol,
+    const std::string& host,
+    unsigned short port,
+    const std::string& database_identifier,
+    const std::string& origin,
+    const FilePath& file_path,
+    int64 size,
+    base::Time last_modified)
+    : protocol(protocol),
+      host(host),
+      port(port),
+      database_identifier(database_identifier),
+      origin(origin),
+      file_path(file_path),
+      size(size),
+      last_modified(last_modified) {
+}
+
+BrowsingDataIndexedDBHelper::IndexedDBInfo::~IndexedDBInfo() {}
+
 // static
 BrowsingDataIndexedDBHelper* BrowsingDataIndexedDBHelper::Create(
     Profile* profile) {
   return new BrowsingDataIndexedDBHelperImpl(profile);
 }
 
+CannedBrowsingDataIndexedDBHelper::
+PendingIndexedDBInfo::PendingIndexedDBInfo() {
+}
+
+CannedBrowsingDataIndexedDBHelper::
+PendingIndexedDBInfo::PendingIndexedDBInfo(const GURL& origin,
+                                           const string16& description)
+    : origin(origin),
+      description(description) {
+}
+
+CannedBrowsingDataIndexedDBHelper::
+PendingIndexedDBInfo::~PendingIndexedDBInfo() {
+}
+
 CannedBrowsingDataIndexedDBHelper::CannedBrowsingDataIndexedDBHelper(
     Profile* profile)
-    : profile_(profile) {
+    : profile_(profile),
+      completion_callback_(NULL),
+      is_fetching_(false) {
   DCHECK(profile);
 }
 
 void CannedBrowsingDataIndexedDBHelper::AddIndexedDB(
     const GURL& origin, const string16& description) {
-  WebSecurityOrigin web_security_origin =
-      WebSecurityOrigin::createFromString(
-          UTF8ToUTF16(origin.spec()));
-  std::string security_origin(web_security_origin.toString().utf8());
-
-  for (std::vector<IndexedDBInfo>::iterator
-       indexed_db = indexed_db_info_.begin();
-       indexed_db != indexed_db_info_.end(); ++indexed_db) {
-    if (indexed_db->origin == security_origin)
-      return;
-  }
-
-  indexed_db_info_.push_back(IndexedDBInfo(
-      web_security_origin.protocol().utf8(),
-      web_security_origin.host().utf8(),
-      web_security_origin.port(),
-      web_security_origin.databaseIdentifier().utf8(),
-      security_origin,
-      profile_->GetWebKitContext()->indexed_db_context()->
-          GetIndexedDBFilePath(web_security_origin.databaseIdentifier()),
-      0,
-      base::Time()));
+  base::AutoLock auto_lock(lock_);
+  pending_indexed_db_info_.push_back(PendingIndexedDBInfo(origin, description));
 }
 
 void CannedBrowsingDataIndexedDBHelper::Reset() {
+  base::AutoLock auto_lock(lock_);
   indexed_db_info_.clear();
+  pending_indexed_db_info_.clear();
 }
 
 bool CannedBrowsingDataIndexedDBHelper::empty() const {
-  return indexed_db_info_.empty();
+  base::AutoLock auto_lock(lock_);
+  return indexed_db_info_.empty() && pending_indexed_db_info_.empty();
 }
 
 void CannedBrowsingDataIndexedDBHelper::StartFetching(
     Callback1<const std::vector<IndexedDBInfo>& >::Type* callback) {
-  callback->Run(indexed_db_info_);
-  delete callback;
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!is_fetching_);
+  DCHECK(callback);
+  is_fetching_ = true;
+  completion_callback_.reset(callback);
+  BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod(
+      this,
+      &CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread));
 }
 
 CannedBrowsingDataIndexedDBHelper::~CannedBrowsingDataIndexedDBHelper() {}
+
+void CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread() {
+  base::AutoLock auto_lock(lock_);
+  for (std::vector<PendingIndexedDBInfo>::const_iterator
+       info = pending_indexed_db_info_.begin();
+       info != pending_indexed_db_info_.end(); ++info) {
+    WebSecurityOrigin web_security_origin =
+        WebSecurityOrigin::createFromString(
+            UTF8ToUTF16(info->origin.spec()));
+    std::string security_origin(web_security_origin.toString().utf8());
+
+    bool duplicate = false;
+    for (std::vector<IndexedDBInfo>::iterator
+         indexed_db = indexed_db_info_.begin();
+         indexed_db != indexed_db_info_.end(); ++indexed_db) {
+      if (indexed_db->origin == security_origin) {
+        duplicate = true;
+        break;
+      }
+    }
+    if (duplicate)
+      continue;
+
+    indexed_db_info_.push_back(IndexedDBInfo(
+        web_security_origin.protocol().utf8(),
+        web_security_origin.host().utf8(),
+        web_security_origin.port(),
+        web_security_origin.databaseIdentifier().utf8(),
+        security_origin,
+        profile_->GetWebKitContext()->indexed_db_context()->
+            GetIndexedDBFilePath(web_security_origin.databaseIdentifier()),
+        0,
+        base::Time()));
+  }
+  pending_indexed_db_info_.clear();
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &CannedBrowsingDataIndexedDBHelper::NotifyInUIThread));
+}
+
+void CannedBrowsingDataIndexedDBHelper::NotifyInUIThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(is_fetching_);
+  // Note: completion_callback_ mutates only in the UI thread, so it's safe to
+  // test it here.
+  if (completion_callback_ != NULL) {
+    completion_callback_->Run(indexed_db_info_);
+    completion_callback_.reset();
+  }
+  is_fetching_ = false;
+}
diff --git a/chrome/browser/browsing_data_indexed_db_helper.h b/chrome/browser/browsing_data_indexed_db_helper.h
index 932c00b..e0f25b6 100644
--- a/chrome/browser/browsing_data_indexed_db_helper.h
+++ b/chrome/browser/browsing_data_indexed_db_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,8 @@
 #include "base/callback.h"
 #include "base/file_path.h"
 #include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
@@ -37,16 +39,8 @@
         const std::string& origin,
         const FilePath& file_path,
         int64 size,
-        base::Time last_modified)
-        : protocol(protocol),
-          host(host),
-          port(port),
-          database_identifier(database_identifier),
-          origin(origin),
-          file_path(file_path),
-          size(size),
-          last_modified(last_modified) {
-    }
+        base::Time last_modified);
+    ~IndexedDBInfo();
 
     bool IsFileSchemeData() {
       return protocol == chrome::kFileScheme;
@@ -109,12 +103,43 @@
   virtual void DeleteIndexedDBFile(const FilePath& file_path) {}
 
  private:
+  struct PendingIndexedDBInfo {
+    PendingIndexedDBInfo();
+    PendingIndexedDBInfo(const GURL& origin, const string16& description);
+    ~PendingIndexedDBInfo();
+
+    GURL origin;
+    string16 description;
+  };
+
   virtual ~CannedBrowsingDataIndexedDBHelper();
 
+  // Convert the pending indexed db info to indexed db info objects.
+  void ConvertPendingInfoInWebKitThread();
+
+  void NotifyInUIThread();
+
   Profile* profile_;
 
+  // Lock to protect access to pending_indexed_db_info_;
+  mutable base::Lock lock_;
+
+  // This may mutate on WEBKIT and UI threads.
+  std::vector<PendingIndexedDBInfo> pending_indexed_db_info_;
+
+  // This only mutates on the WEBKIT thread.
   std::vector<IndexedDBInfo> indexed_db_info_;
 
+  // This only mutates on the UI thread.
+  scoped_ptr<Callback1<const std::vector<IndexedDBInfo>& >::Type >
+      completion_callback_;
+
+  // Indicates whether or not we're currently fetching information:
+  // it's true when StartFetching() is called in the UI thread, and it's reset
+  // after we notified the callback in the UI thread.
+  // This only mutates on the UI thread.
+  bool is_fetching_;
+
   DISALLOW_COPY_AND_ASSIGN(CannedBrowsingDataIndexedDBHelper);
 };
 
diff --git a/chrome/browser/browsing_data_indexed_db_helper_browsertest.cc b/chrome/browser/browsing_data_indexed_db_helper_browsertest.cc
new file mode 100644
index 0000000..73b005b
--- /dev/null
+++ b/chrome/browser/browsing_data_indexed_db_helper_browsertest.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browsing_data_helper_browsertest.h"
+#include "chrome/browser/browsing_data_indexed_db_helper.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+typedef BrowsingDataHelperCallback<BrowsingDataIndexedDBHelper::IndexedDBInfo>
+    TestCompletionCallback;
+
+class BrowsingDataIndexedDBHelperTest : public InProcessBrowserTest {
+ protected:
+  TestingProfile testing_profile_;
+};
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataIndexedDBHelperTest, CannedAddIndexedDB) {
+  const GURL origin1("http://host1:1/");
+  const GURL origin2("http://host2:1/");
+  const string16 description(ASCIIToUTF16("description"));
+  const FilePath::CharType file1[] =
+      FILE_PATH_LITERAL("http_host1_1.indexeddb");
+  const FilePath::CharType file2[] =
+      FILE_PATH_LITERAL("http_host2_1.indexeddb");
+
+  scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
+      new CannedBrowsingDataIndexedDBHelper(&testing_profile_));
+  helper->AddIndexedDB(origin1, description);
+  helper->AddIndexedDB(origin2, description);
+
+  TestCompletionCallback callback;
+  helper->StartFetching(
+      NewCallback(&callback, &TestCompletionCallback::callback));
+
+  std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo> result =
+      callback.result();
+
+  ASSERT_EQ(2U, result.size());
+  EXPECT_EQ(FilePath(file1).value(), result[0].file_path.BaseName().value());
+  EXPECT_EQ(FilePath(file2).value(), result[1].file_path.BaseName().value());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataIndexedDBHelperTest, CannedUnique) {
+  const GURL origin("http://host1:1/");
+  const string16 description(ASCIIToUTF16("description"));
+  const FilePath::CharType file[] =
+      FILE_PATH_LITERAL("http_host1_1.indexeddb");
+
+  scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
+      new CannedBrowsingDataIndexedDBHelper(&testing_profile_));
+  helper->AddIndexedDB(origin, description);
+  helper->AddIndexedDB(origin, description);
+
+  TestCompletionCallback callback;
+  helper->StartFetching(
+      NewCallback(&callback, &TestCompletionCallback::callback));
+
+  std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo> result =
+      callback.result();
+
+  ASSERT_EQ(1U, result.size());
+  EXPECT_EQ(FilePath(file).value(), result[0].file_path.BaseName().value());
+}
+}  // namespace
diff --git a/chrome/browser/browsing_data_indexed_db_helper_unittest.cc b/chrome/browser/browsing_data_indexed_db_helper_unittest.cc
index 10df224..f7e1af4 100644
--- a/chrome/browser/browsing_data_indexed_db_helper_unittest.cc
+++ b/chrome/browser/browsing_data_indexed_db_helper_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,91 +7,8 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browsing_data_indexed_db_helper.h"
 #include "chrome/test/testing_profile.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
 
 namespace {
-
-class TestCompletionCallback {
- public:
-  TestCompletionCallback() : has_result_(false) {}
-
-  bool has_result() const { return has_result_; }
-
-  const std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo>& result() {
-    return result_;
-  }
-
-  void callback(
-      const std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo>& info) {
-    has_result_ = true;
-    result_ = info;
-  }
-
- private:
-  bool has_result_;
-  std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo> result_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestCompletionCallback);
-};
-
-// Functionality incomplete, needs further refactoring, http://crbug.com/60532.
-TEST(CannedBrowsingDataIndexedDBHelperTest, DISABLED_AddIndexedDB) {
-  TestingProfile profile;
-
-  const GURL origin1("http://host1:1/");
-  const GURL origin2("http://host2:1/");
-  const string16 description(ASCIIToUTF16("description"));
-  const FilePath::CharType file1[] =
-      FILE_PATH_LITERAL("http_host1_1.indexeddb");
-  const FilePath::CharType file2[] =
-      FILE_PATH_LITERAL("http_host2_1.indexeddb");
-
-  scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(&profile));
-  helper->AddIndexedDB(origin1, description);
-  helper->AddIndexedDB(origin2, description);
-
-  TestCompletionCallback callback;
-  helper->StartFetching(
-      NewCallback(&callback, &TestCompletionCallback::callback));
-  ASSERT_TRUE(callback.has_result());
-
-  std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo> result =
-      callback.result();
-
-  ASSERT_EQ(2U, result.size());
-  EXPECT_EQ(FilePath(file1).value(), result[0].file_path.BaseName().value());
-  EXPECT_EQ(FilePath(file2).value(), result[1].file_path.BaseName().value());
-}
-
-// Functionality incomplete, needs further refactoring, http://crbug.com/60532.
-TEST(CannedBrowsingDataIndexedDBHelperTest, DISABLED_Unique) {
-  TestingProfile profile;
-
-  const GURL origin("http://host1:1/");
-  const string16 description(ASCIIToUTF16("description"));
-  const FilePath::CharType file[] =
-      FILE_PATH_LITERAL("http_host1_1.indexeddb");
-
-  scoped_refptr<CannedBrowsingDataIndexedDBHelper> helper(
-      new CannedBrowsingDataIndexedDBHelper(&profile));
-  helper->AddIndexedDB(origin, description);
-  helper->AddIndexedDB(origin, description);
-
-  TestCompletionCallback callback;
-  helper->StartFetching(
-      NewCallback(&callback, &TestCompletionCallback::callback));
-  ASSERT_TRUE(callback.has_result());
-
-  std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo> result =
-      callback.result();
-
-  ASSERT_EQ(1U, result.size());
-  EXPECT_EQ(FilePath(file).value(), result[0].file_path.BaseName().value());
-}
-
 TEST(CannedBrowsingDataIndexedDBHelperTest, Empty) {
   TestingProfile profile;
 
@@ -107,5 +24,4 @@
   helper->Reset();
   ASSERT_TRUE(helper->empty());
 }
-
 } // namespace
diff --git a/chrome/browser/browsing_data_local_storage_helper.cc b/chrome/browser/browsing_data_local_storage_helper.cc
index 0894707..a08eb56 100644
--- a/chrome/browser/browsing_data_local_storage_helper.cc
+++ b/chrome/browser/browsing_data_local_storage_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,11 +11,36 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/browser/profiles/profile.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
+using WebKit::WebSecurityOrigin;
+
+BrowsingDataLocalStorageHelper::LocalStorageInfo::LocalStorageInfo() {}
+
+BrowsingDataLocalStorageHelper::LocalStorageInfo::LocalStorageInfo(
+    const std::string& protocol,
+    const std::string& host,
+    unsigned short port,
+    const std::string& database_identifier,
+    const std::string& origin,
+    const FilePath& file_path,
+    int64 size,
+    base::Time last_modified)
+    : protocol(protocol),
+      host(host),
+      port(port),
+      database_identifier(database_identifier),
+      origin(origin),
+      file_path(file_path),
+      size(size),
+      last_modified(last_modified) {
+      }
+
+BrowsingDataLocalStorageHelper::LocalStorageInfo::~LocalStorageInfo() {}
+
 BrowsingDataLocalStorageHelper::BrowsingDataLocalStorageHelper(
     Profile* profile)
     : profile_(profile),
@@ -68,8 +93,8 @@
   for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
        file_path = file_enumerator.Next()) {
     if (file_path.Extension() == DOMStorageContext::kLocalStorageExtension) {
-      WebKit::WebSecurityOrigin web_security_origin =
-          WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
+      WebSecurityOrigin web_security_origin =
+          WebSecurityOrigin::createFromDatabaseIdentifier(
               webkit_glue::FilePathToWebString(file_path.BaseName()));
       if (EqualsASCII(web_security_origin.protocol(),
                       chrome::kExtensionScheme)) {
@@ -124,40 +149,74 @@
 
 void CannedBrowsingDataLocalStorageHelper::AddLocalStorage(
     const GURL& origin) {
-  WebKit::WebSecurityOrigin web_security_origin =
-      WebKit::WebSecurityOrigin::createFromString(
-          UTF8ToUTF16(origin.spec()));
-  std::string security_origin(web_security_origin.toString().utf8());
-
-  for (std::vector<LocalStorageInfo>::iterator
-       local_storage = local_storage_info_.begin();
-       local_storage != local_storage_info_.end(); ++local_storage) {
-    if (local_storage->origin == security_origin)
-      return;
-  }
-
-  local_storage_info_.push_back(LocalStorageInfo(
-      web_security_origin.protocol().utf8(),
-      web_security_origin.host().utf8(),
-      web_security_origin.port(),
-      web_security_origin.databaseIdentifier().utf8(),
-      security_origin,
-      profile_->GetWebKitContext()->dom_storage_context()->
-          GetLocalStorageFilePath(web_security_origin.databaseIdentifier()),
-      0,
-      base::Time()));
+  base::AutoLock auto_lock(lock_);
+  pending_local_storage_info_.push_back(origin);
 }
 
 void CannedBrowsingDataLocalStorageHelper::Reset() {
+  base::AutoLock auto_lock(lock_);
   local_storage_info_.clear();
+  pending_local_storage_info_.clear();
 }
 
 bool CannedBrowsingDataLocalStorageHelper::empty() const {
-  return local_storage_info_.empty();
+  base::AutoLock auto_lock(lock_);
+  return local_storage_info_.empty() && pending_local_storage_info_.empty();
 }
 
 void CannedBrowsingDataLocalStorageHelper::StartFetching(
     Callback1<const std::vector<LocalStorageInfo>& >::Type* callback) {
-  callback->Run(local_storage_info_);
-  delete callback;
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!is_fetching_);
+  DCHECK(callback);
+  is_fetching_ = true;
+  completion_callback_.reset(callback);
+  BrowserThread::PostTask(
+      BrowserThread::WEBKIT, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &CannedBrowsingDataLocalStorageHelper::
+              ConvertPendingInfoInWebKitThread));
+}
+
+CannedBrowsingDataLocalStorageHelper::~CannedBrowsingDataLocalStorageHelper() {}
+
+void CannedBrowsingDataLocalStorageHelper::ConvertPendingInfoInWebKitThread() {
+  base::AutoLock auto_lock(lock_);
+  for (std::vector<GURL>::iterator info = pending_local_storage_info_.begin();
+       info != pending_local_storage_info_.end(); ++info) {
+    WebSecurityOrigin web_security_origin =
+        WebSecurityOrigin::createFromString(
+            UTF8ToUTF16(info->spec()));
+    std::string security_origin(web_security_origin.toString().utf8());
+
+    bool duplicate = false;
+    for (std::vector<LocalStorageInfo>::iterator
+         local_storage = local_storage_info_.begin();
+         local_storage != local_storage_info_.end(); ++local_storage) {
+      if (local_storage->origin == security_origin) {
+        duplicate = true;
+        break;
+      }
+    }
+    if (duplicate)
+      continue;
+
+    local_storage_info_.push_back(LocalStorageInfo(
+        web_security_origin.protocol().utf8(),
+        web_security_origin.host().utf8(),
+        web_security_origin.port(),
+        web_security_origin.databaseIdentifier().utf8(),
+        security_origin,
+        profile_->GetWebKitContext()->dom_storage_context()->
+            GetLocalStorageFilePath(web_security_origin.databaseIdentifier()),
+        0,
+        base::Time()));
+  }
+  pending_local_storage_info_.clear();
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &CannedBrowsingDataLocalStorageHelper::NotifyInUIThread));
 }
diff --git a/chrome/browser/browsing_data_local_storage_helper.h b/chrome/browser/browsing_data_local_storage_helper.h
index 1f61070..e1db472 100644
--- a/chrome/browser/browsing_data_local_storage_helper.h
+++ b/chrome/browser/browsing_data_local_storage_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/file_path.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
@@ -30,7 +31,7 @@
  public:
   // Contains detailed information about local storage.
   struct LocalStorageInfo {
-    LocalStorageInfo() {}
+    LocalStorageInfo();
     LocalStorageInfo(
         const std::string& protocol,
         const std::string& host,
@@ -39,16 +40,8 @@
         const std::string& origin,
         const FilePath& file_path,
         int64 size,
-        base::Time last_modified)
-        : protocol(protocol),
-          host(host),
-          port(port),
-          database_identifier(database_identifier),
-          origin(origin),
-          file_path(file_path),
-          size(size),
-          last_modified(last_modified) {
-    }
+        base::Time last_modified);
+    ~LocalStorageInfo();
 
     bool IsFileSchemeData() {
       return protocol == chrome::kFileScheme;
@@ -82,28 +75,30 @@
   friend class base::RefCountedThreadSafe<BrowsingDataLocalStorageHelper>;
   virtual ~BrowsingDataLocalStorageHelper();
 
+  // Notifies the completion callback in the UI thread.
+  void NotifyInUIThread();
+
   Profile* profile_;
 
+  // This only mutates on the UI thread.
+  scoped_ptr<Callback1<const std::vector<LocalStorageInfo>& >::Type >
+      completion_callback_;
+
+  // Indicates whether or not we're currently fetching information:
+  // it's true when StartFetching() is called in the UI thread, and it's reset
+  // after we notified the callback in the UI thread.
+  // This only mutates on the UI thread.
+  bool is_fetching_;
+
   // This only mutates in the WEBKIT thread.
   std::vector<LocalStorageInfo> local_storage_info_;
 
  private:
   // Enumerates all local storage files in the WEBKIT thread.
   void FetchLocalStorageInfoInWebKitThread();
-  // Notifies the completion callback in the UI thread.
-  void NotifyInUIThread();
   // Delete a single local storage file in the WEBKIT thread.
   void DeleteLocalStorageFileInWebKitThread(const FilePath& file_path);
 
-  // This only mutates on the UI thread.
-  scoped_ptr<Callback1<const std::vector<LocalStorageInfo>& >::Type >
-      completion_callback_;
-  // Indicates whether or not we're currently fetching information:
-  // it's true when StartFetching() is called in the UI thread, and it's reset
-  // after we notified the callback in the UI thread.
-  // This only mutates on the UI thread.
-  bool is_fetching_;
-
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataLocalStorageHelper);
 };
 
@@ -131,7 +126,16 @@
   virtual void CancelNotification() {}
 
  private:
-  virtual ~CannedBrowsingDataLocalStorageHelper() {}
+  virtual ~CannedBrowsingDataLocalStorageHelper();
+
+  // Convert the pending local storage info to local storage info objects.
+  void ConvertPendingInfoInWebKitThread();
+
+  // Used to protect access to pending_local_storage_info_.
+  mutable base::Lock lock_;
+
+  // May mutate on WEBKIT and UI threads.
+  std::vector<GURL> pending_local_storage_info_;
 
   DISALLOW_COPY_AND_ASSIGN(CannedBrowsingDataLocalStorageHelper);
 };
diff --git a/chrome/browser/browsing_data_local_storage_helper_browsertest.cc b/chrome/browser/browsing_data_local_storage_helper_browsertest.cc
index 8a94cbc..90ee6b2 100644
--- a/chrome/browser/browsing_data_local_storage_helper_browsertest.cc
+++ b/chrome/browser/browsing_data_local_storage_helper_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 #include "base/ref_counted.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/browser/in_process_webkit/webkit_thread.h"
+#include "chrome/browser/browsing_data_helper_browsertest.h"
 #include "chrome/browser/browsing_data_local_storage_helper.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/testing_profile.h"
@@ -18,20 +19,24 @@
 #include "chrome/test/ui_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-static const FilePath::CharType kTestFile0[] =
+namespace {
+typedef
+    BrowsingDataHelperCallback<BrowsingDataLocalStorageHelper::LocalStorageInfo>
+    TestCompletionCallback;
+
+const FilePath::CharType kTestFile0[] =
     FILE_PATH_LITERAL("http_www.chromium.org_0.localstorage");
 
-static const FilePath::CharType kTestFile1[] =
+const FilePath::CharType kTestFile1[] =
     FILE_PATH_LITERAL("http_www.google.com_0.localstorage");
 
-static const FilePath::CharType kTestFileInvalid[] =
+const FilePath::CharType kTestFileInvalid[] =
     FILE_PATH_LITERAL("http_www.google.com_localstorage_0.foo");
 
 // This is only here to test that extension state is not listed by the helper.
-static const FilePath::CharType kTestFileExtension[] = FILE_PATH_LITERAL(
+const FilePath::CharType kTestFileExtension[] = FILE_PATH_LITERAL(
     "chrome-extension_behllobkkfkfnphdnhnkndlbkcpglgmj_0.localstorage");
 
-
 class BrowsingDataLocalStorageHelperTest : public InProcessBrowserTest {
  protected:
   void CreateLocalStorageFilesForTest() {
@@ -128,3 +133,51 @@
   }
   ASSERT_EQ(3, num_files);
 }
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataLocalStorageHelperTest,
+                       CannedAddLocalStorage) {
+  const GURL origin1("http://host1:1/");
+  const GURL origin2("http://host2:1/");
+  const FilePath::CharType file1[] =
+      FILE_PATH_LITERAL("http_host1_1.localstorage");
+  const FilePath::CharType file2[] =
+      FILE_PATH_LITERAL("http_host2_1.localstorage");
+
+  scoped_refptr<CannedBrowsingDataLocalStorageHelper> helper(
+      new CannedBrowsingDataLocalStorageHelper(&testing_profile_));
+  helper->AddLocalStorage(origin1);
+  helper->AddLocalStorage(origin2);
+
+  TestCompletionCallback callback;
+  helper->StartFetching(
+      NewCallback(&callback, &TestCompletionCallback::callback));
+
+  std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo> result =
+      callback.result();
+
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ(FilePath(file1).value(), result[0].file_path.BaseName().value());
+  EXPECT_EQ(FilePath(file2).value(), result[1].file_path.BaseName().value());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataLocalStorageHelperTest, CannedUnique) {
+  const GURL origin("http://host1:1/");
+  const FilePath::CharType file[] =
+      FILE_PATH_LITERAL("http_host1_1.localstorage");
+
+  scoped_refptr<CannedBrowsingDataLocalStorageHelper> helper(
+      new CannedBrowsingDataLocalStorageHelper(&testing_profile_));
+  helper->AddLocalStorage(origin);
+  helper->AddLocalStorage(origin);
+
+  TestCompletionCallback callback;
+  helper->StartFetching(
+      NewCallback(&callback, &TestCompletionCallback::callback));
+
+  std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo> result =
+      callback.result();
+
+  ASSERT_EQ(1u, result.size());
+  EXPECT_EQ(FilePath(file).value(), result[0].file_path.BaseName().value());
+}
+}  // namespace
diff --git a/chrome/browser/browsing_data_local_storage_helper_unittest.cc b/chrome/browser/browsing_data_local_storage_helper_unittest.cc
index 6fbb1ee..7279151 100644
--- a/chrome/browser/browsing_data_local_storage_helper_unittest.cc
+++ b/chrome/browser/browsing_data_local_storage_helper_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,85 +8,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
-class TestCompletionCallback {
- public:
-  TestCompletionCallback()
-      : have_result_(false) {
-  }
-
-  bool have_result() const { return have_result_; }
-
-  const std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo>& result()
-  {
-    return result_;
-  }
-
-  void callback(const std::vector<
-          BrowsingDataLocalStorageHelper::LocalStorageInfo>& info) {
-    have_result_ = true;
-    result_ = info;
-  }
-
- private:
-  bool have_result_;
-  std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo> result_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestCompletionCallback);
-};
-}  // namespace
-
-TEST(CannedBrowsingDataLocalStorageTest, AddLocalStorage) {
-  TestingProfile profile;
-
-  const GURL origin1("http://host1:1/");
-  const GURL origin2("http://host2:1/");
-  const FilePath::CharType file1[] =
-      FILE_PATH_LITERAL("http_host1_1.localstorage");
-  const FilePath::CharType file2[] =
-      FILE_PATH_LITERAL("http_host2_1.localstorage");
-
-  scoped_refptr<CannedBrowsingDataLocalStorageHelper> helper(
-      new CannedBrowsingDataLocalStorageHelper(&profile));
-  helper->AddLocalStorage(origin1);
-  helper->AddLocalStorage(origin2);
-
-  TestCompletionCallback callback;
-  helper->StartFetching(
-      NewCallback(&callback, &TestCompletionCallback::callback));
-  ASSERT_TRUE(callback.have_result());
-
-  std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo> result =
-      callback.result();
-
-  ASSERT_EQ(2u, result.size());
-  EXPECT_EQ(FilePath(file1).value(), result[0].file_path.BaseName().value());
-  EXPECT_EQ(FilePath(file2).value(), result[1].file_path.BaseName().value());
-}
-
-TEST(CannedBrowsingDataLocalStorageTest, Unique) {
-  TestingProfile profile;
-
-  const GURL origin("http://host1:1/");
-  const FilePath::CharType file[] =
-      FILE_PATH_LITERAL("http_host1_1.localstorage");
-
-  scoped_refptr<CannedBrowsingDataLocalStorageHelper> helper(
-      new CannedBrowsingDataLocalStorageHelper(&profile));
-  helper->AddLocalStorage(origin);
-  helper->AddLocalStorage(origin);
-
-  TestCompletionCallback callback;
-  helper->StartFetching(
-      NewCallback(&callback, &TestCompletionCallback::callback));
-  ASSERT_TRUE(callback.have_result());
-
-  std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo> result =
-      callback.result();
-
-  ASSERT_EQ(1u, result.size());
-  EXPECT_EQ(FilePath(file).value(), result[0].file_path.BaseName().value());
-}
-
 TEST(CannedBrowsingDataLocalStorageTest, Empty) {
   TestingProfile profile;
 
@@ -101,3 +22,4 @@
   helper->Reset();
   ASSERT_TRUE(helper->empty());
 }
+}  // namespace
diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc
index 3b138ad..b9cae94 100644
--- a/chrome/browser/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data_remover.cc
@@ -9,16 +9,19 @@
 
 #include "base/callback.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
-#include "chrome/browser/plugin_data_remover.h"
-#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/io_thread.h"
 #include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/net/chrome_net_log.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/plugin_data_remover.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/sessions/session_service.h"
@@ -56,12 +59,14 @@
           this, &BrowsingDataRemover::OnGotAppCacheInfo)),
       ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_(
           this, &BrowsingDataRemover::OnAppCacheDeleted)),
-      request_context_getter_(profile->GetRequestContext()),
       appcaches_to_be_deleted_count_(0),
       next_cache_state_(STATE_NONE),
       cache_(NULL),
+      main_context_getter_(profile->GetRequestContext()),
+      media_context_getter_(profile->GetRequestContextForMedia()),
       waiting_for_clear_databases_(false),
       waiting_for_clear_history_(false),
+      waiting_for_clear_host_cache_(false),
       waiting_for_clear_cache_(false),
       waiting_for_clear_appcache_(false) {
   DCHECK(profile);
@@ -81,12 +86,14 @@
           this, &BrowsingDataRemover::OnGotAppCacheInfo)),
       ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_(
           this, &BrowsingDataRemover::OnAppCacheDeleted)),
-      request_context_getter_(profile->GetRequestContext()),
       appcaches_to_be_deleted_count_(0),
       next_cache_state_(STATE_NONE),
       cache_(NULL),
+      main_context_getter_(profile->GetRequestContext()),
+      media_context_getter_(profile->GetRequestContextForMedia()),
       waiting_for_clear_databases_(false),
       waiting_for_clear_history_(false),
+      waiting_for_clear_host_cache_(false),
       waiting_for_clear_cache_(false),
       waiting_for_clear_appcache_(false),
       waiting_for_clear_lso_data_(false) {
@@ -134,6 +141,15 @@
           NewCallback(this, &BrowsingDataRemover::OnHistoryDeletionDone));
     }
 
+    // Need to clear the host cache, as it also reveals some history.
+    waiting_for_clear_host_cache_ = true;
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        NewRunnableMethod(
+            this,
+            &BrowsingDataRemover::ClearHostCacheOnIOThread,
+            g_browser_process->io_thread()));
+
     // As part of history deletion we also delete the auto-generated keywords.
     TemplateURLModel* keywords_model = profile_->GetTemplateURLModel();
     if (keywords_model && !keywords_model->loaded()) {
@@ -246,9 +262,6 @@
     UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_Cache"),
                               profile_);
 
-    main_context_getter_ = profile_->GetRequestContext();
-    media_context_getter_ = profile_->GetRequestContextForMedia();
-
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         NewRunnableMethod(this, &BrowsingDataRemover::ClearCacheOnIOThread));
@@ -260,9 +273,9 @@
     waiting_for_clear_lso_data_ = true;
     if (!plugin_data_remover_.get())
       plugin_data_remover_ = new PluginDataRemover();
-    plugin_data_remover_->StartRemoving(
-        delete_begin_,
-        NewRunnableMethod(this, &BrowsingDataRemover::OnClearedPluginData));
+    base::WaitableEvent* event =
+        plugin_data_remover_->StartRemoving(delete_begin_);
+    watcher_.StartWatching(event, this);
   }
 
   NotifyAndDeleteIfDone();
@@ -328,6 +341,12 @@
   if (!all_done())
     return;
 
+  // The NetLog contains download history, but may also contain form data,
+  // cookies and passwords.  Simplest just to always clear it.  Must be cleared
+  // after the cache, as cleaning up the disk cache exposes some of the history
+  // in the NetLog.
+  g_browser_process->net_log()->ClearAllPassivelyCapturedEvents();
+
   removing_ = false;
   FOR_EACH_OBSERVER(Observer, observer_list_, OnBrowsingDataRemoverDone());
 
@@ -336,6 +355,24 @@
   MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
+void BrowsingDataRemover::ClearedNetworkHistory() {
+  waiting_for_clear_host_cache_ = false;
+
+  NotifyAndDeleteIfDone();
+}
+
+void BrowsingDataRemover::ClearHostCacheOnIOThread(IOThread* io_thread) {
+  // This function should be called on the IO thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  io_thread->ClearHostCache();
+
+  // Notify the UI thread that we are done.
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(this, &BrowsingDataRemover::ClearedNetworkHistory));
+}
+
 void BrowsingDataRemover::ClearedCache() {
   waiting_for_clear_cache_ = false;
 
@@ -392,8 +429,6 @@
         break;
       }
       case STATE_DONE: {
-        main_context_getter_ = NULL;
-        media_context_getter_ = NULL;
         cache_ = NULL;
 
         // Notify the UI thread that we are done.
@@ -504,12 +539,13 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   ChromeURLRequestContext* request_context =
       reinterpret_cast<ChromeURLRequestContext*>(
-          request_context_getter_->GetURLRequestContext());
+          main_context_getter_->GetURLRequestContext());
   return request_context ? request_context->appcache_service()
                          : NULL;
 }
 
-void BrowsingDataRemover::OnClearedPluginData() {
+void BrowsingDataRemover::OnWaitableEventSignaled(
+    base::WaitableEvent* waitable_event) {
   waiting_for_clear_lso_data_ = false;
   NotifyAndDeleteIfDone();
 }
diff --git a/chrome/browser/browsing_data_remover.h b/chrome/browser/browsing_data_remover.h
index 9a8addb..39b280a 100644
--- a/chrome/browser/browsing_data_remover.h
+++ b/chrome/browser/browsing_data_remover.h
@@ -10,11 +10,13 @@
 
 #include "base/observer_list.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/waitable_event_watcher.h"
 #include "base/time.h"
 #include "chrome/browser/appcache/chrome_appcache_service.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/common/notification_registrar.h"
 
+class IOThread;
 class PluginDataRemover;
 class Profile;
 class URLRequestContextGetter;
@@ -30,7 +32,8 @@
 // BrowsingDataRemover is responsible for removing data related to browsing:
 // visits in url database, downloads, cookies ...
 
-class BrowsingDataRemover : public NotificationObserver {
+class BrowsingDataRemover : public NotificationObserver,
+                            public base::WaitableEventWatcher::Delegate {
  public:
   // Time period ranges available when doing browsing data removals.
   enum TimePeriod {
@@ -106,10 +109,22 @@
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
+  // WaitableEventWatcher implementation.
+  // Called when plug-in data has been cleared. Invokes NotifyAndDeleteIfDone.
+  virtual void OnWaitableEventSignaled(base::WaitableEvent* waitable_event);
+
   // If we're not waiting on anything, notifies observers and deletes this
   // object.
   void NotifyAndDeleteIfDone();
 
+  // Callback when the network history has been deleted. Invokes
+  // NotifyAndDeleteIfDone.
+  void ClearedNetworkHistory();
+
+  // Invoked on the IO thread to clear the HostCache, which exposes some
+  // network history.
+  void ClearHostCacheOnIOThread(IOThread* io_thread);
+
   // Callback when the cache has been deleted. Invokes NotifyAndDeleteIfDone.
   void ClearedCache();
 
@@ -142,17 +157,15 @@
   void OnAppCacheDeleted(int rv);
   ChromeAppCacheService* GetAppCacheService();
 
-  // Callback when plug-in data has been cleared. Invokes NotifyAndDeleteIfDone.
-  void OnClearedPluginData();
-
   // Calculate the begin time for the deletion range specified by |time_period|.
   base::Time CalculateBeginDeleteTime(TimePeriod time_period);
 
   // Returns true if we're all done.
   bool all_done() {
     return registrar_.IsEmpty() && !waiting_for_clear_cache_ &&
-           !waiting_for_clear_history_ && !waiting_for_clear_databases_ &&
-           !waiting_for_clear_appcache_ && !waiting_for_clear_lso_data_;
+           !waiting_for_clear_history_ && !waiting_for_clear_host_cache_ &&
+           !waiting_for_clear_databases_ && !waiting_for_clear_appcache_ &&
+           !waiting_for_clear_lso_data_;
   }
 
   NotificationRegistrar registrar_;
@@ -179,22 +192,25 @@
   net::CompletionCallbackImpl<BrowsingDataRemover> appcache_got_info_callback_;
   net::CompletionCallbackImpl<BrowsingDataRemover> appcache_deleted_callback_;
   scoped_refptr<appcache::AppCacheInfoCollection> appcache_info_;
-  scoped_refptr<URLRequestContextGetter> request_context_getter_;
   std::vector<GURL> appcache_whitelist_;
   int appcaches_to_be_deleted_count_;
 
   // Used to delete data from the HTTP caches.
   CacheState next_cache_state_;
   disk_cache::Backend* cache_;
+
+  // Used to delete data from HTTP cache and appcache.
   scoped_refptr<URLRequestContextGetter> main_context_getter_;
   scoped_refptr<URLRequestContextGetter> media_context_getter_;
 
   // Used to delete plugin data.
   scoped_refptr<PluginDataRemover> plugin_data_remover_;
+  base::WaitableEventWatcher watcher_;
 
   // True if we're waiting for various data to be deleted.
   bool waiting_for_clear_databases_;
   bool waiting_for_clear_history_;
+  bool waiting_for_clear_host_cache_;
   bool waiting_for_clear_cache_;
   bool waiting_for_clear_appcache_;
   bool waiting_for_clear_lso_data_;
diff --git a/chrome/browser/browsing_instance.cc b/chrome/browser/browsing_instance.cc
index 72c121b..b729565 100644
--- a/chrome/browser/browsing_instance.cc
+++ b/chrome/browser/browsing_instance.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,13 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/site_instance.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 
-/*static*/
+// static
 BrowsingInstance::ProfileSiteInstanceMap
     BrowsingInstance::profile_site_instance_map_;
 
@@ -29,7 +29,7 @@
   if (command_line.HasSwitch(switches::kProcessPerSite))
     return true;
 
-  // We want to consolidate particular sites like extensions and DOMUI whether
+  // We want to consolidate particular sites like extensions and WebUI whether
   // it is in process-per-tab or process-per-site-instance.
   // Note that --single-process may have been specified, but that affects the
   // process creation logic in RenderProcessHost, so we do not need to worry
@@ -38,7 +38,9 @@
   if (url.SchemeIs(chrome::kExtensionScheme))
     return true;
 
-  if (DOMUIFactory::UseDOMUIForURL(profile_, url))
+  // DevTools pages have WebUI type but should not reuse the same host.
+  if (WebUIFactory::UseWebUIForURL(profile_, url) &&
+      !url.SchemeIs(chrome::kChromeDevToolsScheme))
     return true;
 
   // In all other cases, don't use process-per-site logic.
diff --git a/chrome/browser/bug_report_data.cc b/chrome/browser/bug_report_data.cc
index a0d9772..e4d4866 100644
--- a/chrome/browser/bug_report_data.cc
+++ b/chrome/browser/bug_report_data.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/bug_report_data.h"
 
-#include "chrome/browser/ui/browser.h"
-
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/notifications/system_notification.h"
 #endif
@@ -23,7 +21,6 @@
 
 void BugReportData::UpdateData(Profile* profile,
                                const std::string& target_tab_url,
-                               const string16& target_tab_title,
                                const int problem_type,
                                const std::string& page_url,
                                const std::string& description,
@@ -36,7 +33,6 @@
                                ) {
   profile_ = profile;
   target_tab_url_ = target_tab_url;
-  target_tab_title_ = target_tab_title;
   problem_type_ = problem_type;
   page_url_ = page_url;
   description_ = description;
diff --git a/chrome/browser/bug_report_data.h b/chrome/browser/bug_report_data.h
index 2c3a6dd..028e928 100644
--- a/chrome/browser/bug_report_data.h
+++ b/chrome/browser/bug_report_data.h
@@ -31,7 +31,6 @@
 
   void UpdateData(Profile* profile,
                   const std::string& target_tab_url,
-                  const string16& target_tab_title,
                   const int problem_type,
                   const std::string& page_url,
                   const std::string& description,
@@ -48,19 +47,18 @@
                        std::string* zip_content);
 #endif
 
-  const std::string& target_tab_url() { return target_tab_url_; }
-  const string16& target_tab_title() { return target_tab_title_; }
+  const std::string& target_tab_url() const { return target_tab_url_; }
 
-  int problem_type() { return problem_type_; }
-  const std::string& page_url() { return page_url_; }
-  const std::string& description() { return description_; }
-  const std::vector<unsigned char>& image() { return image_; }
+  int problem_type() const { return problem_type_; }
+  const std::string& page_url() const { return page_url_; }
+  const std::string& description() const { return description_; }
+  const std::vector<unsigned char>& image() const { return image_; }
 #if defined(OS_CHROMEOS)
-  const std::string& user_email() { return user_email_; }
-  const chromeos::LogDictionaryType* sys_info() { return sys_info_; }
-  const bool send_sys_info() { return send_sys_info_; }
-  const bool sent_report() { return sent_report_; }
-  const std::string* zip_content() { return zip_content_; }
+  const std::string& user_email() const { return user_email_; }
+  chromeos::LogDictionaryType* sys_info() const { return sys_info_; }
+  bool send_sys_info() const { return send_sys_info_; }
+  bool sent_report() const { return sent_report_; }
+  std::string* zip_content() const { return zip_content_; }
 #endif
 
 
@@ -69,8 +67,6 @@
 
   // Target tab url.
   std::string target_tab_url_;
-  // Target tab page title.
-  string16 target_tab_title_;
 
   int problem_type_;
   std::string page_url_;
diff --git a/chrome/browser/bug_report_util.cc b/chrome/browser/bug_report_util.cc
index 28cc685..1a35b63 100644
--- a/chrome/browser/bug_report_util.cc
+++ b/chrome/browser/bug_report_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 #include <sstream>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/file_version_info.h"
 #include "base/file_util.h"
@@ -27,6 +26,7 @@
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
 #include "net/url_request/url_request_status.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/locid.h"
 
 #if defined(OS_CHROMEOS)
@@ -90,7 +90,7 @@
   // Overridden from URLFetcher::Delegate.
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -112,7 +112,7 @@
 void BugReportUtil::PostCleanup::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -258,7 +258,6 @@
 
 // static
 void BugReportUtil::SendReport(Profile* profile,
-    const std::string& page_title_text,
     int problem_type,
     const std::string& page_url_text,
     const std::string& description,
@@ -288,10 +287,6 @@
   // they wish
   common_data->set_gaia_id(0);
 
-  // Add the page title.
-  AddFeedbackData(&feedback_data, std::string(kPageTitleTag),
-                  page_title_text);
-
 #if defined(OS_CHROMEOS)
   // Add the user e-mail to the feedback object
   common_data->set_user_email(user_email_text);
diff --git a/chrome/browser/bug_report_util.h b/chrome/browser/bug_report_util.h
index 3bb9ee3..f87ead7 100644
--- a/chrome/browser/bug_report_util.h
+++ b/chrome/browser/bug_report_util.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/userfeedback/proto/common.pb.h"
 #include "chrome/browser/userfeedback/proto/extension.pb.h"
 #include "chrome/browser/userfeedback/proto/math.pb.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 #if defined(OS_MACOSX)
 #include "base/sys_info.h"
@@ -64,7 +64,6 @@
 
   // Generates bug report data.
   static void SendReport(Profile* profile,
-      const std::string& page_title_text,
       int problem_type,
       const std::string& page_url_text,
       const std::string& description,
diff --git a/chrome/browser/cancelable_request.h b/chrome/browser/cancelable_request.h
index 5f2b1c7..dce7a2c 100644
--- a/chrome/browser/cancelable_request.h
+++ b/chrome/browser/cancelable_request.h
@@ -92,12 +92,12 @@
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/synchronization/cancellation_flag.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "build/build_config.h"
 
diff --git a/chrome/browser/cert_store.cc b/chrome/browser/cert_store.cc
index 30ef867..6def04e 100644
--- a/chrome/browser/cert_store.cc
+++ b/chrome/browser/cert_store.cc
@@ -46,7 +46,7 @@
 
 int CertStore::StoreCert(net::X509Certificate* cert, int process_id) {
   DCHECK(cert);
-  AutoLock autoLock(cert_lock_);
+  base::AutoLock autoLock(cert_lock_);
 
   int cert_id;
 
@@ -86,7 +86,7 @@
 
 bool CertStore::RetrieveCert(int cert_id,
                              scoped_refptr<net::X509Certificate>* cert) {
-  AutoLock autoLock(cert_lock_);
+  base::AutoLock autoLock(cert_lock_);
 
   CertMap::iterator iter = id_to_cert_.find(cert_id);
   if (iter == id_to_cert_.end())
@@ -109,7 +109,7 @@
 }
 
 void CertStore::RemoveCertsForRenderProcesHost(int process_id) {
-  AutoLock autoLock(cert_lock_);
+  base::AutoLock autoLock(cert_lock_);
 
   // We iterate through all the cert ids for that process.
   IDMap::iterator ids_iter;
diff --git a/chrome/browser/cert_store.h b/chrome/browser/cert_store.h
index 0af7ef4..fb5eeec 100644
--- a/chrome/browser/cert_store.h
+++ b/chrome/browser/cert_store.h
@@ -8,8 +8,8 @@
 
 #include <map>
 
-#include "base/lock.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "net/base/x509_certificate.h"
@@ -76,7 +76,7 @@
 
   // This lock protects: process_to_ids_, id_to_processes_, id_to_cert_ and
   //                     cert_to_id_.
-  Lock cert_lock_;
+  base::Lock cert_lock_;
 
   DISALLOW_COPY_AND_ASSIGN(CertStore);
 };
diff --git a/chrome/browser/certificate_manager_model.cc b/chrome/browser/certificate_manager_model.cc
index 619260e..067a302 100644
--- a/chrome/browser/certificate_manager_model.cc
+++ b/chrome/browser/certificate_manager_model.cc
@@ -74,9 +74,10 @@
   return rv;
 }
 
-int CertificateManagerModel::ImportFromPKCS12(const std::string& data,
+int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module,
+                                              const std::string& data,
                                               const string16& password) {
-  int result = cert_db_.ImportFromPKCS12(data, password);
+  int result = cert_db_.ImportFromPKCS12(module, data, password);
   if (result == net::OK)
     Refresh();
   return result;
diff --git a/chrome/browser/certificate_manager_model.h b/chrome/browser/certificate_manager_model.h
index 2206370..137197d 100644
--- a/chrome/browser/certificate_manager_model.h
+++ b/chrome/browser/certificate_manager_model.h
@@ -57,7 +57,8 @@
 
   // Import certificates from PKCS #12 encoded |data|, using the given
   // |password|.  Returns a net error code on failure.
-  int ImportFromPKCS12(const std::string& data, const string16& password);
+  int ImportFromPKCS12(net::CryptoModule* module, const std::string& data,
+                       const string16& password);
 
   // Import CA certificates.
   // Tries to import all the certificates given.  The root will be trusted
diff --git a/chrome/browser/certificate_viewer.h b/chrome/browser/certificate_viewer.h
index 3d2d8c5..89b0e04 100644
--- a/chrome/browser/certificate_viewer.h
+++ b/chrome/browser/certificate_viewer.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CERTIFICATE_VIEWER_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace net {
 
diff --git a/chrome/browser/character_encoding.cc b/chrome/browser/character_encoding.cc
index 4b0f92f..95134da 100644
--- a/chrome/browser/character_encoding.cc
+++ b/chrome/browser/character_encoding.cc
@@ -7,8 +7,6 @@
 #include <map>
 #include <set>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_collator.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/string_tokenizer.h"
@@ -16,6 +14,8 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
 #include "unicode/ucnv.h"
 
 namespace {
diff --git a/chrome/browser/child_process_launcher.cc b/chrome/browser/child_process_launcher.cc
index 6058cc8..0ed3f89 100644
--- a/chrome/browser/child_process_launcher.cc
+++ b/chrome/browser/child_process_launcher.cc
@@ -7,9 +7,9 @@
 #include <utility>  // For std::pair.
 
 #include "base/command_line.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/common/chrome_descriptors.h"
@@ -140,15 +140,21 @@
       bool is_plugin =
           cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
           switches::kPluginProcess;
+      bool is_gpu =
+          cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
+          switches::kGpuProcess;
 
-      if (is_renderer || is_plugin) {
+      if (is_renderer || is_plugin || is_gpu) {
         int crash_signal_fd;
         if (is_renderer) {
           crash_signal_fd = RendererCrashHandlerHostLinux::GetInstance()->
               GetDeathSignalSocket();
-        } else {
+        } else if (is_plugin) {
           crash_signal_fd = PluginCrashHandlerHostLinux::GetInstance()->
               GetDeathSignalSocket();
+        } else {
+          crash_signal_fd = GpuCrashHandlerHostLinux::GetInstance()->
+              GetDeathSignalSocket();
         }
         if (crash_signal_fd >= 0) {
           fds_to_map.push_back(std::make_pair(
@@ -174,7 +180,7 @@
       // AddPlaceholderForPid(), enabling proper cleanup.
       {  // begin scope for AutoLock
         MachBroker* broker = MachBroker::GetInstance();
-        AutoLock lock(broker->GetLock());
+        base::AutoLock lock(broker->GetLock());
 
         // This call to |PrepareForFork()| will start the MachBroker listener
         // thread, if it is not already running.  Therefore the browser process
diff --git a/chrome/browser/child_process_security_policy.cc b/chrome/browser/child_process_security_policy.cc
index ea1f725..5cd7009 100644
--- a/chrome/browser/child_process_security_policy.cc
+++ b/chrome/browser/child_process_security_policy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -88,8 +88,8 @@
     return false;
   }
 
-  bool has_dom_ui_bindings() const {
-    return BindingsPolicy::is_dom_ui_enabled(enabled_bindings_);
+  bool has_web_ui_bindings() const {
+    return BindingsPolicy::is_web_ui_enabled(enabled_bindings_);
   }
 
   bool has_extension_bindings() const {
@@ -151,7 +151,7 @@
 }
 
 void ChildProcessSecurityPolicy::Add(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (security_state_.count(child_id) != 0) {
     NOTREACHED() << "Add child process at most once.";
     return;
@@ -161,7 +161,7 @@
 }
 
 void ChildProcessSecurityPolicy::Remove(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (!security_state_.count(child_id))
     return;  // May be called multiple times.
 
@@ -171,7 +171,7 @@
 
 void ChildProcessSecurityPolicy::RegisterWebSafeScheme(
     const std::string& scheme) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK(web_safe_schemes_.count(scheme) == 0) << "Add schemes at most once.";
   DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not psuedo.";
 
@@ -179,14 +179,14 @@
 }
 
 bool ChildProcessSecurityPolicy::IsWebSafeScheme(const std::string& scheme) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   return (web_safe_schemes_.find(scheme) != web_safe_schemes_.end());
 }
 
 void ChildProcessSecurityPolicy::RegisterPseudoScheme(
     const std::string& scheme) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK(pseudo_schemes_.count(scheme) == 0) << "Add schemes at most once.";
   DCHECK(web_safe_schemes_.count(scheme) == 0) <<
       "Psuedo implies not web-safe.";
@@ -195,7 +195,7 @@
 }
 
 bool ChildProcessSecurityPolicy::IsPseudoScheme(const std::string& scheme) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   return (pseudo_schemes_.find(scheme) != pseudo_schemes_.end());
 }
@@ -224,7 +224,7 @@
   }
 
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     SecurityStateMap::iterator state = security_state_.find(child_id);
     if (state == security_state_.end())
       return;
@@ -242,7 +242,7 @@
 
 void ChildProcessSecurityPolicy::GrantPermissionsForFile(
     int child_id, const FilePath& file, int permissions) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -253,7 +253,7 @@
 
 void ChildProcessSecurityPolicy::RevokeAllPermissionsForFile(
     int child_id, const FilePath& file) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -264,7 +264,7 @@
 
 void ChildProcessSecurityPolicy::GrantScheme(int child_id,
                                              const std::string& scheme) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -273,24 +273,24 @@
   state->second->GrantScheme(scheme);
 }
 
-void ChildProcessSecurityPolicy::GrantDOMUIBindings(int child_id) {
-  AutoLock lock(lock_);
+void ChildProcessSecurityPolicy::GrantWebUIBindings(int child_id) {
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
     return;
 
-  state->second->GrantBindings(BindingsPolicy::DOM_UI);
+  state->second->GrantBindings(BindingsPolicy::WEB_UI);
 
-  // DOM UI bindings need the ability to request chrome: URLs.
+  // Web UI bindings need the ability to request chrome: URLs.
   state->second->GrantScheme(chrome::kChromeUIScheme);
 
-  // DOM UI pages can contain links to file:// URLs.
+  // Web UI pages can contain links to file:// URLs.
   state->second->GrantScheme(chrome::kFileScheme);
 }
 
 void ChildProcessSecurityPolicy::GrantExtensionBindings(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -300,7 +300,7 @@
 }
 
 void ChildProcessSecurityPolicy::GrantReadRawCookies(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -310,7 +310,7 @@
 }
 
 void ChildProcessSecurityPolicy::RevokeReadRawCookies(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -354,7 +354,7 @@
     return true;  // This URL request is destined for ShellExecute.
 
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
 
     SecurityStateMap::iterator state = security_state_.find(child_id);
     if (state == security_state_.end())
@@ -373,7 +373,7 @@
 
 bool ChildProcessSecurityPolicy::HasPermissionsForFile(
     int child_id, const FilePath& file, int permissions) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -382,18 +382,18 @@
   return state->second->HasPermissionsForFile(file, permissions);
 }
 
-bool ChildProcessSecurityPolicy::HasDOMUIBindings(int child_id) {
-  AutoLock lock(lock_);
+bool ChildProcessSecurityPolicy::HasWebUIBindings(int child_id) {
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
     return false;
 
-  return state->second->has_dom_ui_bindings();
+  return state->second->has_web_ui_bindings();
 }
 
 bool ChildProcessSecurityPolicy::HasExtensionBindings(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
@@ -403,7 +403,7 @@
 }
 
 bool ChildProcessSecurityPolicy::CanReadRawCookies(int child_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   SecurityStateMap::iterator state = security_state_.find(child_id);
   if (state == security_state_.end())
diff --git a/chrome/browser/child_process_security_policy.h b/chrome/browser/child_process_security_policy.h
index 9280400..9a99698 100644
--- a/chrome/browser/child_process_security_policy.h
+++ b/chrome/browser/child_process_security_policy.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,8 +13,8 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 
 class FilePath;
 class GURL;
@@ -84,8 +84,8 @@
   // scheme.
   void GrantScheme(int child_id, const std::string& scheme);
 
-  // Grant the child process the ability to use DOM UI Bindings.
-  void GrantDOMUIBindings(int child_id);
+  // Grant the child process the ability to use Web UI Bindings.
+  void GrantWebUIBindings(int child_id);
 
   // Grant the child process the ability to use extension Bindings.
   void GrantExtensionBindings(int child_id);
@@ -112,12 +112,12 @@
                              const FilePath& file,
                              int permissions);
 
-  // Returns true if the specified child_id has been granted DOMUIBindings.
+  // Returns true if the specified child_id has been granted WebUIBindings.
   // The browser should check this property before assuming the child process is
-  // allowed to use DOMUIBindings.
-  bool HasDOMUIBindings(int child_id);
+  // allowed to use WebUIBindings.
+  bool HasWebUIBindings(int child_id);
 
-  // Returns true if the specified child_id has been granted DOMUIBindings.
+  // Returns true if the specified child_id has been granted WebUIBindings.
   // The browser should check this property before assuming the child process is
   // allowed to use extension bindings.
   bool HasExtensionBindings(int child_id);
@@ -141,7 +141,7 @@
 
   // You must acquire this lock before reading or writing any members of this
   // class.  You must not block while holding this lock.
-  Lock lock_;
+  base::Lock lock_;
 
   // These schemes are white-listed for all child processes.  This set is
   // protected by |lock_|.
diff --git a/chrome/browser/child_process_security_policy_unittest.cc b/chrome/browser/child_process_security_policy_unittest.cc
index cc31188..9910b45 100644
--- a/chrome/browser/child_process_security_policy_unittest.cc
+++ b/chrome/browser/child_process_security_policy_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,7 +19,7 @@
   virtual void SetUp() {
     // In the real world, "chrome:" is a handled scheme.
     net::URLRequest::RegisterProtocolFactory(chrome::kChromeUIScheme,
-                                             &URLRequestTestJob::Factory);
+                                             &net::URLRequestTestJob::Factory);
   }
   virtual void TearDown() {
     net::URLRequest::RegisterProtocolFactory(chrome::kChromeUIScheme, NULL);
@@ -133,7 +133,8 @@
   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
 
   // Once we register a ProtocolFactory for "asdf", we default to deny.
-  net::URLRequest::RegisterProtocolFactory("asdf", &URLRequestTestJob::Factory);
+  net::URLRequest::RegisterProtocolFactory("asdf",
+                                           &net::URLRequestTestJob::Factory);
   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
 
   // We can allow new schemes by adding them to the whitelist.
@@ -287,17 +288,17 @@
   p->Remove(kRendererID);
 }
 
-TEST_F(ChildProcessSecurityPolicyTest, CanServiceDOMUIBindings) {
+TEST_F(ChildProcessSecurityPolicyTest, CanServiceWebUIBindings) {
   ChildProcessSecurityPolicy* p = ChildProcessSecurityPolicy::GetInstance();
 
   GURL url("chrome://thumb/http://www.google.com/");
 
   p->Add(kRendererID);
 
-  EXPECT_FALSE(p->HasDOMUIBindings(kRendererID));
+  EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
   EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
-  p->GrantDOMUIBindings(kRendererID);
-  EXPECT_TRUE(p->HasDOMUIBindings(kRendererID));
+  p->GrantWebUIBindings(kRendererID);
+  EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
   EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
 
   p->Remove(kRendererID);
@@ -313,11 +314,11 @@
 
   p->GrantRequestURL(kRendererID, url);
   p->GrantReadFile(kRendererID, file);
-  p->GrantDOMUIBindings(kRendererID);
+  p->GrantWebUIBindings(kRendererID);
 
   EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
   EXPECT_TRUE(p->CanReadFile(kRendererID, file));
-  EXPECT_TRUE(p->HasDOMUIBindings(kRendererID));
+  EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
 
   p->Remove(kRendererID);
 
@@ -328,5 +329,5 @@
   // In this case, we default to secure behavior.
   EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
   EXPECT_FALSE(p->CanReadFile(kRendererID, file));
-  EXPECT_FALSE(p->HasDOMUIBindings(kRendererID));
+  EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
 }
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm
index aea31b0..1786f91 100644
--- a/chrome/browser/chrome_browser_application_mac.mm
+++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -69,6 +69,11 @@
       if ([aReason isEqualToString:kNSMenuItemArrayBoundsCheck]) {
         fatal = YES;
       }
+
+      NSString* const kNoWindowCheck = @"View is not in any window";
+      if ([aReason isEqualToString:kNoWindowCheck]) {
+        fatal = YES;
+      }
     }
 
     // Dear reader: Something you just did provoked an NSException.
diff --git a/chrome/browser/chrome_plugin_browsing_context.cc b/chrome/browser/chrome_plugin_browsing_context.cc
index a252bbf..ff20485 100644
--- a/chrome/browser/chrome_plugin_browsing_context.cc
+++ b/chrome/browser/chrome_plugin_browsing_context.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -53,7 +53,7 @@
   net::URLRequestContext* context =
       Source<net::URLRequestContext>(source).ptr();
 
-  // Multiple CPBrowsingContexts may refer to the same URLRequestContext.
+  // Multiple CPBrowsingContexts may refer to the same net::URLRequestContext.
   for (Map::iterator it(&map_); !it.IsAtEnd(); it.Advance()) {
     if (it.GetCurrentValue() == context)
       map_.Remove(it.GetCurrentKey());
diff --git a/chrome/browser/chrome_plugin_browsing_context.h b/chrome/browser/chrome_plugin_browsing_context.h
index 9f0eb8f..8eb1b5b 100644
--- a/chrome/browser/chrome_plugin_browsing_context.h
+++ b/chrome/browser/chrome_plugin_browsing_context.h
@@ -18,10 +18,10 @@
 }  // namespace net
 
 // This class manages the mapping between CPBrowsingContexts and
-// URLRequestContexts.  It observes when URLRequestContexts go away, and
-// invalidates the corresponding CPBrowsingContexts.  CPBrowsingContexts can be
-// associated with other data as well, so there can be multiple ones referring
-// to a given URLRequestContext.
+// net::URLRequestContexts.  It observes when net::URLRequestContexts go away,
+// and invalidates the corresponding CPBrowsingContexts.  CPBrowsingContexts can
+// be associated with other data as well, so there can be multiple ones
+// referring to a given net::URLRequestContext.
 // Note: This class should be used on the IO thread only.
 class CPBrowsingContextManager : public NotificationObserver {
  public:
@@ -33,16 +33,16 @@
   ~CPBrowsingContextManager();
 
   // Generate a new unique CPBrowsingContext ID from the given
-  // URLRequestContext.  Multiple CPBrowsingContexts can map to the same
-  // URLRequestContext.
+  // net::URLRequestContext.  Multiple CPBrowsingContexts can map to the same
+  // net::URLRequestContext.
   CPBrowsingContext Allocate(net::URLRequestContext* context);
 
-  // Return the URLRequestContext that this CPBrowsingContext refers to, or NULL
-  // if not found.
+  // Return the net::URLRequestContext that this CPBrowsingContext refers to, or
+  // NULL if not found.
   net::URLRequestContext* ToURLRequestContext(CPBrowsingContext id);
 
   // Return a CPBrowsingContext ID that corresponds to the given
-  // URLRequestContext. This function differs from Allocate in that calling
+  // net::URLRequestContext. This function differs from Allocate in that calling
   // this multiple times with the same argument gives the same ID.
   CPBrowsingContext Lookup(net::URLRequestContext* context);
 
@@ -57,8 +57,8 @@
 
   NotificationRegistrar registrar_;
 
-  Map map_;  // map of CPBrowsingContext -> URLRequestContext
-  ReverseMap reverse_map_;  // map of URLRequestContext -> CPBrowsingContext
+  Map map_;  // map of CPBrowsingContext -> net::URLRequestContext
+  ReverseMap reverse_map_; // map of net::URLRequestContext -> CPBrowsingContext
 };
 
 #endif  // CHROME_BROWSER_CHROME_PLUGIN_BROWSING_CONTEXT_H_
diff --git a/chrome/browser/chrome_plugin_host.cc b/chrome/browser/chrome_plugin_host.cc
index 09abdea..2b020d4 100644
--- a/chrome/browser/chrome_plugin_host.cc
+++ b/chrome/browser/chrome_plugin_host.cc
@@ -1,10 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chrome_plugin_host.h"
 
 #include <set>
+#include <string>
+#include <vector>
 
 #include "base/basictypes.h"
 #include "base/command_line.h"
@@ -31,7 +33,6 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_plugin_lib.h"
 #include "chrome/common/chrome_plugin_util.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/gears_api.h"
 #include "chrome/common/net/url_request_context_getter.h"
 #include "chrome/common/net/url_request_intercept_job.h"
@@ -157,7 +158,7 @@
       : PluginHelper(plugin), cprequest_(cprequest), user_buffer_(NULL) {
     cprequest_->data = this;  // see FromCPRequest().
 
-    URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
+    net::URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
         ToURLRequestContext(cprequest_->context);
     // TODO(mpcomplete): remove fallback case when Gears support is prevalent.
     if (!context)
@@ -317,8 +318,8 @@
   virtual bool IsDialogModal() const { return false; }
   virtual std::wstring GetDialogTitle() const { return L"Gears"; }
   virtual GURL GetDialogContentURL() const { return params_.url; }
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const {}
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const {}
   virtual void GetDialogSize(gfx::Size* size) const {
     size->set_width(params_.width);
     size->set_height(params_.height);
@@ -387,7 +388,7 @@
 CPError STDCALL CPB_GetCookies(CPID id, CPBrowsingContext bcontext,
                                const char* url, char** cookies) {
   CHECK(ChromePluginLib::IsPluginThread());
-  URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
+  net::URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
       ToURLRequestContext(bcontext);
   // TODO(mpcomplete): remove fallback case when Gears support is prevalent.
   if (!context) {
@@ -463,8 +464,14 @@
     if (!service)
       return CPERR_FAILURE;
     FilePath path = service->GetChromePluginDataDir();
-    std::string retval = WideToUTF8(
-        path.Append(chrome::kChromePluginDataDirname).ToWStringHack());
+    // This is wrong -- we can't in general stuff a path through a std::string.
+    // But this code is Gears-specific, so Windows-only anyway for now.
+    std::string retval;
+#if defined(OS_WIN)
+    retval = WideToUTF8(path.Append(chrome::kChromePluginDataDirname).value());
+#else
+    NOTREACHED();
+#endif
     *static_cast<char**>(buf) = CPB_StringDup(CPB_Alloc, retval);
     return CPERR_SUCCESS;
     }
@@ -695,7 +702,7 @@
   PluginService* service = PluginService::GetInstance();
   if (!service)
     return false;
-  PluginProcessHost *host = service->FindPluginProcess(plugin->filename());
+  PluginProcessHost *host = service->FindNpapiPluginProcess(plugin->filename());
   return host ? true : false;
 }
 
@@ -713,7 +720,7 @@
   if (!service)
     return CPERR_FAILURE;
   PluginProcessHost *host =
-  service->FindOrStartPluginProcess(plugin->filename());
+  service->FindOrStartNpapiPluginProcess(plugin->filename());
   if (!host)
     return CPERR_FAILURE;
 
diff --git a/chrome/browser/chrome_plugin_unittest.cc b/chrome/browser/chrome_plugin_unittest.cc
index 9322678..72c4a1a 100644
--- a/chrome/browser/chrome_plugin_unittest.cc
+++ b/chrome/browser/chrome_plugin_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 // Tests exercising the Chrome Plugin API.
@@ -13,10 +13,11 @@
 #include "chrome/common/chrome_plugin_lib.h"
 #include "chrome/common/net/url_request_context_getter.h"
 #include "chrome/test/chrome_plugin/test_chrome_plugin.h"
+#include "chrome/test/test_url_request_context_getter.h"
 #include "net/base/io_buffer.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request_test_job.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "net/test/test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -26,22 +27,6 @@
 const char kPluginFilename[] = "test_chrome_plugin.dll";
 const int kResponseBufferSize = 4096;
 
-class TestURLRequestContextGetter : public URLRequestContextGetter {
- public:
-  virtual URLRequestContext* GetURLRequestContext() {
-    if (!context_)
-      context_ = new TestURLRequestContext();
-    return context_;
-  }
-  virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const {
-    return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
-  }
-
- private:
-  ~TestURLRequestContextGetter() {}
-  scoped_refptr<URLRequestContext> context_;
-};
-
 class ChromePluginTest : public testing::Test,
                          public net::URLRequest::Delegate {
  public:
@@ -74,7 +59,7 @@
   virtual void SetUp() {
     LoadPlugin();
     net::URLRequest::RegisterProtocolFactory("test",
-                                             &URLRequestTestJob::Factory);
+                                             &net::URLRequestTestJob::Factory);
 
     // We need to setup a default request context in order to issue HTTP
     // requests.
@@ -126,10 +111,10 @@
   EXPECT_TRUE(success);
   EXPECT_EQ(200, headers->response_code());
 
-  if (url == URLRequestTestJob::test_url_1()) {
-    EXPECT_EQ(URLRequestTestJob::test_data_1(), body);
-  } else if (url == URLRequestTestJob::test_url_2()) {
-    EXPECT_EQ(URLRequestTestJob::test_data_2(), body);
+  if (url == net::URLRequestTestJob::test_url_1()) {
+    EXPECT_EQ(net::URLRequestTestJob::test_data_1(), body);
+  } else if (url == net::URLRequestTestJob::test_url_2()) {
+    EXPECT_EQ(net::URLRequestTestJob::test_data_2(), body);
   } else if (url.spec().find("echo") != std::string::npos) {
     EXPECT_EQ(kChromeTestPluginPostData, body);
   }
@@ -249,7 +234,7 @@
 }
 
 static void ProcessAllPendingMessages() {
-  while (URLRequestTestJob::ProcessOnePendingMessage());
+  while (net::URLRequestTestJob::ProcessOnePendingMessage());
 }
 
 // Tests that the plugin can issue a GET request and receives the data when
@@ -257,10 +242,10 @@
 TEST_F(ChromePluginTest, CanMakeGETRequestSync) {
   // test_url_1 has a synchronous response
   EXPECT_EQ(CPERR_SUCCESS, test_funcs_.test_make_request(
-      "GET", URLRequestTestJob::test_url_1()));
+      "GET", net::URLRequestTestJob::test_url_1()));
 
   // Note: we must add this task after we make the request, so that
-  // URLRequestTestJob's StartAsync task is added and run first.
+  // net::URLRequestTestJob's StartAsync task is added and run first.
   MessageLoop::current()->PostTask(FROM_HERE,
       NewRunnableFunction(&ProcessAllPendingMessages));
   MessageLoop::current()->Run();
@@ -271,10 +256,10 @@
 TEST_F(ChromePluginTest, CanMakeGETRequestAsync) {
   // test_url_2 has an asynchronous response
   EXPECT_EQ(CPERR_SUCCESS, test_funcs_.test_make_request(
-        "GET", URLRequestTestJob::test_url_2()));
+        "GET", net::URLRequestTestJob::test_url_2()));
 
   // Note: we must add this task after we make the request, so that
-  // URLRequestTestJob's StartAsync task is added and run first.
+  // net::URLRequestTestJob's StartAsync task is added and run first.
   MessageLoop::current()->PostTask(FROM_HERE,
       NewRunnableFunction(&ProcessAllPendingMessages));
   MessageLoop::current()->Run();
@@ -290,7 +275,7 @@
   EXPECT_EQ(CPERR_SUCCESS, test_funcs_.test_make_request("POST", url));
 
   // Note: we must add this task after we make the request, so that
-  // URLRequestTestJob's StartAsync task is added and run first.
+  // net::URLRequestTestJob's StartAsync task is added and run first.
   MessageLoop::current()->PostTask(FROM_HERE,
       NewRunnableFunction(&ProcessAllPendingMessages));
   MessageLoop::current()->Run();
diff --git a/chrome/browser/chromeos/audio_handler.cc b/chrome/browser/chromeos/audio_handler.cc
index f8ad726..a0d9687 100644
--- a/chrome/browser/chromeos/audio_handler.cc
+++ b/chrome/browser/chromeos/audio_handler.cc
@@ -8,13 +8,14 @@
 
 #include "base/logging.h"
 #include "base/singleton.h"
-#include "chrome/browser/chromeos/pulse_audio_mixer.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/audio_mixer_alsa.h"
+#include "chrome/browser/chromeos/audio_mixer_pulse.h"
 
 namespace chromeos {
 
 namespace {
 
-const double kSilenceDb = -200.0;
 const double kMinVolumeDb = -90.0;
 // Choosing 6.0dB here instead of 0dB to give user chance to amplify audio some
 // in case sounds or their setup is too quiet for them.
@@ -27,10 +28,9 @@
 
 }  // namespace
 
-// This class will set volume using PulseAudio to adjust volume and mute, and
-// handles the volume level logic.
-
-// TODO(davej): Serialize volume/mute for next startup?
+// chromeos:  This class will set the volume using ALSA to adjust volume and
+// mute, and handle the volume level logic.  PulseAudio is no longer called
+// and support can be removed once there is no need to go back to using PA.
 
 double AudioHandler::GetVolumePercent() {
   if (!VerifyMixerConnection())
@@ -40,7 +40,7 @@
 }
 
 // Set volume using our internal 0-100% range.  Notice 0% is a special case of
-// silence, so we set the mixer volume to kSilenceDb instead of kMinVolumeDb.
+// silence, so we set the mixer volume to kSilenceDb instead of min_volume_db_.
 void AudioHandler::SetVolumePercent(double volume_percent) {
   if (!VerifyMixerConnection())
     return;
@@ -48,7 +48,7 @@
 
   double vol_db;
   if (volume_percent <= 0)
-    vol_db = kSilenceDb;
+    vol_db = AudioMixer::kSilenceDb;
   else
     vol_db = PercentToVolumeDb(volume_percent);
 
@@ -72,7 +72,7 @@
 
   double new_volume;
   if (pct <= 0.1)
-    new_volume = kSilenceDb;
+    new_volume = AudioMixer::kSilenceDb;
   else
     new_volume = PercentToVolumeDb(pct);
 
@@ -90,83 +90,148 @@
 void AudioHandler::SetMute(bool do_mute) {
   if (!VerifyMixerConnection())
     return;
-
   DVLOG(1) << "Setting Mute to " << do_mute;
-
   mixer_->SetMute(do_mute);
 }
 
+void AudioHandler::Disconnect() {
+  mixer_.reset();
+}
+
+bool AudioHandler::TryToConnect(bool async) {
+  if (mixer_type_ == MIXER_TYPE_PULSEAUDIO) {
+    VLOG(1) << "Trying to connect to PulseAudio";
+    mixer_.reset(new AudioMixerPulse());
+  } else if (mixer_type_ == MIXER_TYPE_ALSA) {
+    VLOG(1) << "Trying to connect to ALSA";
+    mixer_.reset(new AudioMixerAlsa());
+  } else {
+    VLOG(1) << "Cannot find valid volume mixer";
+    mixer_.reset();
+    return false;
+  }
+
+  if (async) {
+    mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized));
+  } else {
+    if (!mixer_->InitSync()) {
+      VLOG(1) << "Unable to reconnect to Mixer";
+      return false;
+    }
+  }
+  return true;
+}
+
+void AudioHandler::UseNextMixer() {
+  if (mixer_type_ == MIXER_TYPE_PULSEAUDIO)
+    mixer_type_ = MIXER_TYPE_ALSA;
+  else
+    mixer_type_ = MIXER_TYPE_NONE;
+}
+
+static void ClipVolume(double* min_volume, double* max_volume) {
+  if (*min_volume < kMinVolumeDb)
+    *min_volume = kMinVolumeDb;
+  if (*max_volume > kMaxVolumeDb)
+    *max_volume = kMaxVolumeDb;
+}
+
 void AudioHandler::OnMixerInitialized(bool success) {
   connected_ = success;
   DVLOG(1) << "OnMixerInitialized, success = " << success;
+
+  if (connected_) {
+    if (mixer_->GetVolumeLimits(&min_volume_db_, &max_volume_db_)) {
+      ClipVolume(&min_volume_db_, &max_volume_db_);
+    }
+    return;
+  }
+
+  VLOG(1) << "Unable to connect to mixer, trying next";
+  UseNextMixer();
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(this, &AudioHandler::TryToConnect, true));
 }
 
 AudioHandler::AudioHandler()
     : connected_(false),
-      reconnect_tries_(0) {
-  mixer_.reset(new PulseAudioMixer());
-  if (!mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized))) {
-    LOG(ERROR) << "Unable to connect to PulseAudio";
-  }
+      reconnect_tries_(0),
+      max_volume_db_(kMaxVolumeDb),
+      min_volume_db_(kMinVolumeDb),
+      mixer_type_(MIXER_TYPE_ALSA) {
+  // TODO(davej): Only attempting a connection to the ALSA mixer now as a first
+  // step in removing pulseaudio.  If all goes well, the other references to
+  // the pulseaudio mixer can be removed.
+
+  // Start trying to connect to mixers asynchronously, starting with the current
+  // mixer_type_.  If the connection fails, another TryToConnect() for the next
+  // mixer will be posted at that time.
+  TryToConnect(true);
 }
 
 AudioHandler::~AudioHandler() {
-  mixer_.reset();
+  Disconnect();
 };
 
 bool AudioHandler::VerifyMixerConnection() {
-  PulseAudioMixer::State mixer_state = mixer_->CheckState();
-  if (mixer_state == PulseAudioMixer::READY)
+  if (mixer_ == NULL)
+    return false;
+
+  AudioMixer::State mixer_state = mixer_->GetState();
+  if (mixer_state == AudioMixer::READY)
     return true;
   if (connected_) {
     // Something happened and the mixer is no longer valid after having been
     // initialized earlier.
     connected_ = false;
-    LOG(ERROR) << "Lost connection to PulseAudio";
+    LOG(ERROR) << "Lost connection to mixer";
   } else {
     LOG(ERROR) << "Mixer not valid";
   }
 
-  if ((mixer_state == PulseAudioMixer::INITIALIZING) ||
-      (mixer_state == PulseAudioMixer::SHUTTING_DOWN))
+  if ((mixer_state == AudioMixer::INITIALIZING) ||
+      (mixer_state == AudioMixer::SHUTTING_DOWN))
     return false;
 
   if (reconnect_tries_ < kMaxReconnectTries) {
     reconnect_tries_++;
-    VLOG(1) << "Re-connecting to PulseAudio attempt " << reconnect_tries_ << "/"
+    VLOG(1) << "Re-connecting to mixer attempt " << reconnect_tries_ << "/"
             << kMaxReconnectTries;
-    mixer_.reset(new PulseAudioMixer());
-    connected_ = mixer_->InitSync();
+
+    connected_ = TryToConnect(false);
+
     if (connected_) {
       reconnect_tries_ = 0;
       return true;
     }
-    LOG(ERROR) << "Unable to re-connect to PulseAudio";
+    LOG(ERROR) << "Unable to re-connect to mixer";
   }
   return false;
 }
 
 // VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us
 // complete control over how the 0 to 100% range is mapped to actual loudness.
-// Volume range is from kMinVolumeDb at just above 0% to kMaxVolumeDb at 100%
-// with a special case at 0% which maps to kSilenceDb.
+// Volume range is from min_volume_db_ at just above 0% to max_volume_db_
+// at 100% with a special case at 0% which maps to kSilenceDb.
 //
 // The mapping is confined to these two functions to make it easy to adjust and
 // have everything else just work.  The range is biased to give finer resolution
 // in the higher volumes if kVolumeBias is less than 1.0.
 
 // static
-double AudioHandler::VolumeDbToPercent(double volume_db) {
-  if (volume_db < kMinVolumeDb)
+double AudioHandler::VolumeDbToPercent(double volume_db) const {
+  if (volume_db < min_volume_db_)
     return 0;
-  return 100.0 * pow((volume_db - kMinVolumeDb) /
-      (kMaxVolumeDb - kMinVolumeDb), 1/kVolumeBias);
+  return 100.0 * pow((volume_db - min_volume_db_) /
+      (max_volume_db_ - min_volume_db_), 1/kVolumeBias);
 }
 
 // static
-double AudioHandler::PercentToVolumeDb(double volume_percent) {
+double AudioHandler::PercentToVolumeDb(double volume_percent) const {
   return pow(volume_percent / 100.0, kVolumeBias) *
-      (kMaxVolumeDb - kMinVolumeDb) + kMinVolumeDb;
+      (max_volume_db_ - min_volume_db_) + min_volume_db_;
 }
 
 // static
diff --git a/chrome/browser/chromeos/audio_handler.h b/chrome/browser/chromeos/audio_handler.h
index 59e9d70..85e28bd 100644
--- a/chrome/browser/chromeos/audio_handler.h
+++ b/chrome/browser/chromeos/audio_handler.h
@@ -8,12 +8,13 @@
 
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
+#include "base/threading/thread.h"
 
 template <typename T> struct DefaultSingletonTraits;
 
 namespace chromeos {
 
-class PulseAudioMixer;
+class AudioMixer;
 
 class AudioHandler {
  public:
@@ -30,7 +31,7 @@
   // as the percentage gets lower, and then switches to silence at 0%.
   void SetVolumePercent(double volume_percent);
 
-  // Adust volume up (positive percentage) or down (negative percentage),
+  // Adjust volume up (positive percentage) or down (negative percentage),
   // capping at 100%.  GetVolumePercent() will be accurate after this
   // blocking call.
   void AdjustVolumeByPercent(double adjust_by_percent);
@@ -42,11 +43,24 @@
   // Mutes all audio.  Non-blocking call.
   void SetMute(bool do_mute);
 
+  // Disconnects from mixer.  Called during shutdown.
+  void Disconnect();
+
  private:
+  enum MixerType {
+    MIXER_TYPE_PULSEAUDIO = 0,
+    MIXER_TYPE_ALSA,
+    MIXER_TYPE_NONE,
+  };
+
   // Defines the delete on exit Singleton traits we like.  Best to have this
   // and constructor/destructor private as recommended for Singletons.
   friend struct DefaultSingletonTraits<AudioHandler>;
 
+  // Connect to the current mixer_type_.
+  bool TryToConnect(bool async);
+  void UseNextMixer();
+
   void OnMixerInitialized(bool success);
 
   AudioHandler();
@@ -54,17 +68,28 @@
   bool VerifyMixerConnection();
 
   // Conversion between our internal scaling (0-100%) and decibels.
-  static double VolumeDbToPercent(double volume_db);
-  static double PercentToVolumeDb(double volume_percent);
+  double VolumeDbToPercent(double volume_db) const;
+  double PercentToVolumeDb(double volume_percent) const;
 
-  scoped_ptr<PulseAudioMixer> mixer_;
+  scoped_ptr<AudioMixer> mixer_;
+
   bool connected_;
   int reconnect_tries_;
 
+  // The min and max volume in decibels, limited to the maximum range of the
+  // audio system being used.
+  double max_volume_db_;
+  double min_volume_db_;
+
+  // Which mixer is being used, PulseAudio, ALSA or none.
+  MixerType mixer_type_;
+
   DISALLOW_COPY_AND_ASSIGN(AudioHandler);
 };
 
 }  // namespace chromeos
 
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::AudioHandler);
+
 #endif  // CHROME_BROWSER_CHROMEOS_AUDIO_HANDLER_H_
 
diff --git a/chrome/browser/chromeos/audio_mixer.h b/chrome/browser/chromeos/audio_mixer.h
new file mode 100644
index 0000000..b77e827
--- /dev/null
+++ b/chrome/browser/chromeos/audio_mixer.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_H_
+#define CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+
+namespace chromeos {
+
+class AudioMixer {
+ public:
+  // Approximation of pure silence expressed in decibels.
+  static const double kSilenceDb = -200.0;
+
+  enum State {
+    UNINITIALIZED = 0,
+    INITIALIZING,
+    READY,
+    SHUTTING_DOWN,
+    IN_ERROR,
+  };
+
+  AudioMixer() {}
+  virtual ~AudioMixer() {}
+
+  // Non-Blocking call.  Connect to Mixer, find a default device, then call the
+  // callback when complete with success code.
+  typedef Callback1<bool>::Type InitDoneCallback;
+  virtual void Init(InitDoneCallback* callback) = 0;
+
+  // Call may block.  Mixer will be connected before returning, unless error.
+  virtual bool InitSync() = 0;
+
+  // Call may block.  Returns a default of kSilenceDb on error.
+  virtual double GetVolumeDb() const = 0;
+
+  // Non-Blocking call.  Returns the actual volume limits possible according
+  // to the mixer.  Limits are left unchanged on error
+  virtual bool GetVolumeLimits(double* vol_min, double* vol_max) = 0;
+
+  // Non-blocking call.
+  virtual void SetVolumeDb(double vol_db) = 0;
+
+  // Call may block.  Gets the mute state of the default device (true == mute).
+  // Returns a default of false on error.
+  virtual bool IsMute() const = 0;
+
+  // Non-Blocking call.
+  virtual void SetMute(bool mute) = 0;
+
+  // Returns READY if we have a valid working connection to the Mixer.
+  // This can return IN_ERROR if we lose the connection, even after an original
+  // successful init.  Non-blocking call.
+  virtual State GetState() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AudioMixer);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_H_
+
diff --git a/chrome/browser/chromeos/audio_mixer_alsa.cc b/chrome/browser/chromeos/audio_mixer_alsa.cc
new file mode 100644
index 0000000..70c47a5
--- /dev/null
+++ b/chrome/browser/chromeos/audio_mixer_alsa.cc
@@ -0,0 +1,469 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/audio_mixer_alsa.h"
+
+#include <alsa/asoundlib.h>
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+
+namespace chromeos {
+
+// Connect to the ALSA mixer using their simple element API.  Init is performed
+// asynchronously on the worker thread.
+//
+// To get a wider range and finer control over volume levels, first the Master
+// level is set, then if the PCM element exists, the total level is refined by
+// adjusting that as well.  If the PCM element has more volume steps, it allows
+// for finer granularity in the total volume.
+
+typedef long alsa_long_t;  // 'long' is required for ALSA API calls.
+
+namespace {
+
+const char kMasterVolume[] = "Master";
+const char kPCMVolume[] = "PCM";
+const double kDefaultMinVolume = -90.0;
+const double kDefaultMaxVolume = 0.0;
+const double kPrefVolumeInvalid = -999.0;
+const int kPrefMuteOff = 0;
+const int kPrefMuteOn = 1;
+const int kPrefMuteInvalid = 2;
+
+}  // namespace
+
+AudioMixerAlsa::AudioMixerAlsa()
+    : min_volume_(kDefaultMinVolume),
+      max_volume_(kDefaultMaxVolume),
+      save_volume_(0),
+      mixer_state_(UNINITIALIZED),
+      alsa_mixer_(NULL),
+      elem_master_(NULL),
+      elem_pcm_(NULL),
+      prefs_(NULL),
+      done_event_(true, false) {
+}
+
+AudioMixerAlsa::~AudioMixerAlsa() {
+  if (thread_ != NULL) {
+    {
+      base::AutoLock lock(mixer_state_lock_);
+      mixer_state_ = SHUTTING_DOWN;
+      thread_->message_loop()->PostTask(FROM_HERE,
+          NewRunnableMethod(this, &AudioMixerAlsa::FreeAlsaMixer));
+    }
+    done_event_.Wait();
+
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    // A ScopedAllowIO object is required to join the thread when calling Stop.
+    // The worker thread should be idle at this time.
+    // See http://crosbug.com/11110 for discussion.
+    base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
+    thread_->message_loop()->AssertIdle();
+
+    thread_->Stop();
+    thread_.reset();
+  }
+}
+
+void AudioMixerAlsa::Init(InitDoneCallback* callback) {
+  DCHECK(callback);
+  if (!InitThread()) {
+    callback->Run(false);
+    delete callback;
+    return;
+  }
+  InitPrefs();
+
+  {
+    base::AutoLock lock(mixer_state_lock_);
+    if (mixer_state_ == SHUTTING_DOWN)
+      return;
+
+    // Post the task of starting up, which may block on the order of ms,
+    // so best not to do it on the caller's thread.
+    thread_->message_loop()->PostTask(FROM_HERE,
+        NewRunnableMethod(this, &AudioMixerAlsa::DoInit, callback));
+  }
+}
+
+bool AudioMixerAlsa::InitSync() {
+  if (!InitThread())
+    return false;
+  InitPrefs();
+  return InitializeAlsaMixer();
+}
+
+double AudioMixerAlsa::GetVolumeDb() const {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return kSilenceDb;
+
+  return DoGetVolumeDb_Locked();
+}
+
+bool AudioMixerAlsa::GetVolumeLimits(double* vol_min, double* vol_max) {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return false;
+  if (vol_min)
+    *vol_min = min_volume_;
+  if (vol_max)
+    *vol_max = max_volume_;
+  return true;
+}
+
+void AudioMixerAlsa::SetVolumeDb(double vol_db) {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return;
+  if (vol_db < kSilenceDb)
+    vol_db = kSilenceDb;
+  DoSetVolumeDb_Locked(vol_db);
+  prefs_->SetDouble(prefs::kAudioVolume, vol_db);
+}
+
+bool AudioMixerAlsa::IsMute() const {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return false;
+  return GetElementMuted_Locked(elem_master_);
+}
+
+// To indicate the volume is not valid yet, a very low volume value is stored.
+// We compare against a slightly higher value in case of rounding errors.
+static bool PrefVolumeValid(double volume) {
+  return (volume > kPrefVolumeInvalid + 0.1);
+}
+
+void AudioMixerAlsa::SetMute(bool mute) {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return;
+
+  // Set volume to minimum on mute, since switching the element off does not
+  // always mute as it should.
+
+  // TODO(davej): Remove save_volume_ and setting volume to minimum if
+  // switching the element off can be guaranteed to mute it.  Currently mute
+  // is done by setting the volume to min_volume_.
+
+  bool old_value = GetElementMuted_Locked(elem_master_);
+
+  if (old_value != mute) {
+    if (mute) {
+      save_volume_ = DoGetVolumeDb_Locked();
+      DoSetVolumeDb_Locked(min_volume_);
+    } else {
+      DoSetVolumeDb_Locked(save_volume_);
+    }
+  }
+
+  SetElementMuted_Locked(elem_master_, mute);
+  if (elem_pcm_)
+    SetElementMuted_Locked(elem_pcm_, mute);
+  prefs_->SetInteger(prefs::kAudioMute, mute ? kPrefMuteOn : kPrefMuteOff);
+}
+
+AudioMixer::State AudioMixerAlsa::GetState() const {
+  base::AutoLock lock(mixer_state_lock_);
+  // If we think it's ready, verify it is actually so.
+  if ((mixer_state_ == READY) && (alsa_mixer_ == NULL))
+    mixer_state_ = IN_ERROR;
+  return mixer_state_;
+}
+
+// static
+void AudioMixerAlsa::RegisterPrefs(PrefService* local_state) {
+  if (!local_state->FindPreference(prefs::kAudioVolume))
+    local_state->RegisterDoublePref(prefs::kAudioVolume, kPrefVolumeInvalid);
+  if (!local_state->FindPreference(prefs::kAudioMute))
+    local_state->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteInvalid);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private functions follow
+
+void AudioMixerAlsa::DoInit(InitDoneCallback* callback) {
+  bool success = InitializeAlsaMixer();
+
+  if (success) {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(this, &AudioMixerAlsa::RestoreVolumeMuteOnUIThread));
+  }
+
+  if (callback) {
+    callback->Run(success);
+    delete callback;
+  }
+}
+
+bool AudioMixerAlsa::InitThread() {
+  base::AutoLock lock(mixer_state_lock_);
+
+  if (mixer_state_ != UNINITIALIZED)
+    return false;
+
+  if (thread_ == NULL) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    thread_.reset(new base::Thread("AudioMixerAlsa"));
+    if (!thread_->Start()) {
+      thread_.reset();
+      return false;
+    }
+  }
+
+  mixer_state_ = INITIALIZING;
+  return true;
+}
+
+void AudioMixerAlsa::InitPrefs() {
+  prefs_ = g_browser_process->local_state();
+}
+
+bool AudioMixerAlsa::InitializeAlsaMixer() {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != INITIALIZING)
+    return false;
+
+  int err;
+  snd_mixer_t* handle = NULL;
+  const char* card = "default";
+
+  if ((err = snd_mixer_open(&handle, 0)) < 0) {
+    LOG(ERROR) << "ALSA mixer " << card << " open error: " << snd_strerror(err);
+    return false;
+  }
+
+  if ((err = snd_mixer_attach(handle, card)) < 0) {
+    LOG(ERROR) << "ALSA Attach to card " << card << " failed: "
+               << snd_strerror(err);
+    snd_mixer_close(handle);
+    return false;
+  }
+
+  if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
+    LOG(ERROR) << "ALSA mixer register error: " << snd_strerror(err);
+    snd_mixer_close(handle);
+    return false;
+  }
+
+  if ((err = snd_mixer_load(handle)) < 0) {
+    LOG(ERROR) << "ALSA mixer " << card << " load error: %s"
+               << snd_strerror(err);
+    snd_mixer_close(handle);
+    return false;
+  }
+
+  VLOG(1) << "Opened ALSA mixer " << card << " OK";
+
+  elem_master_ = FindElementWithName_Locked(handle, kMasterVolume);
+  if (elem_master_) {
+    alsa_long_t long_lo = static_cast<alsa_long_t>(kDefaultMinVolume * 100);
+    alsa_long_t long_hi = static_cast<alsa_long_t>(kDefaultMaxVolume * 100);
+    snd_mixer_selem_get_playback_dB_range(elem_master_, &long_lo, &long_hi);
+    min_volume_ = static_cast<double>(long_lo) / 100.0;
+    max_volume_ = static_cast<double>(long_hi) / 100.0;
+  } else {
+    LOG(ERROR) << "Cannot find 'Master' ALSA mixer element on " << card;
+    snd_mixer_close(handle);
+    return false;
+  }
+
+  elem_pcm_ = FindElementWithName_Locked(handle, kPCMVolume);
+  if (elem_pcm_) {
+    alsa_long_t long_lo = static_cast<alsa_long_t>(kDefaultMinVolume * 100);
+    alsa_long_t long_hi = static_cast<alsa_long_t>(kDefaultMaxVolume * 100);
+    snd_mixer_selem_get_playback_dB_range(elem_pcm_, &long_lo, &long_hi);
+    min_volume_ += static_cast<double>(long_lo) / 100.0;
+    max_volume_ += static_cast<double>(long_hi) / 100.0;
+  }
+
+  VLOG(1) << "ALSA volume range is " << min_volume_ << " dB to "
+          << max_volume_ << " dB";
+
+  alsa_mixer_ = handle;
+  mixer_state_ = READY;
+  return true;
+}
+
+void AudioMixerAlsa::FreeAlsaMixer() {
+  if (alsa_mixer_) {
+    snd_mixer_close(alsa_mixer_);
+    alsa_mixer_ = NULL;
+  }
+  done_event_.Signal();
+}
+
+void AudioMixerAlsa::DoSetVolumeMute(double pref_volume, int pref_mute) {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return;
+
+  // If volume or mute are invalid, set them now to the current actual values.
+  if (!PrefVolumeValid(pref_volume))
+    pref_volume = DoGetVolumeDb_Locked();
+  bool mute;
+  if (pref_mute == kPrefMuteInvalid)
+    mute = GetElementMuted_Locked(elem_master_);
+  else
+    mute = (pref_mute == kPrefMuteOn) ? true : false;
+
+  VLOG(1) << "Setting volume to " << pref_volume << " and mute to " << mute;
+
+  if (mute) {
+    save_volume_ = pref_volume;
+    DoSetVolumeDb_Locked(min_volume_);
+  } else {
+    DoSetVolumeDb_Locked(pref_volume);
+  }
+
+  SetElementMuted_Locked(elem_master_, mute);
+  if (elem_pcm_)
+    SetElementMuted_Locked(elem_pcm_, mute);
+}
+
+void AudioMixerAlsa::RestoreVolumeMuteOnUIThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  // This happens during init, so set the volume off the UI thread.
+  int mute = prefs_->GetInteger(prefs::kAudioMute);
+  double vol = prefs_->GetDouble(prefs::kAudioVolume);
+  {
+    base::AutoLock lock(mixer_state_lock_);
+    if (mixer_state_ == SHUTTING_DOWN)
+      return;
+    thread_->message_loop()->PostTask(FROM_HERE,
+        NewRunnableMethod(this, &AudioMixerAlsa::DoSetVolumeMute, vol, mute));
+  }
+}
+
+double AudioMixerAlsa::DoGetVolumeDb_Locked() const {
+  double vol_total = 0.0;
+  GetElementVolume_Locked(elem_master_, &vol_total);
+
+  double vol_pcm = 0.0;
+  if (elem_pcm_ && (GetElementVolume_Locked(elem_pcm_, &vol_pcm)))
+    vol_total += vol_pcm;
+
+  return vol_total;
+}
+
+void AudioMixerAlsa::DoSetVolumeDb_Locked(double vol_db) {
+  double actual_vol = 0.0;
+
+  // If a PCM volume slider exists, then first set the Master volume to the
+  // nearest volume >= requested volume, then adjust PCM volume down to get
+  // closer to the requested volume.
+  if (elem_pcm_) {
+    SetElementVolume_Locked(elem_master_, vol_db, &actual_vol, 0.9999f);
+    SetElementVolume_Locked(elem_pcm_, vol_db - actual_vol, NULL, 0.5f);
+  } else {
+    SetElementVolume_Locked(elem_master_, vol_db, NULL, 0.5f);
+  }
+}
+
+snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName_Locked(
+    snd_mixer_t* handle,
+    const char* element_name) const {
+  snd_mixer_selem_id_t* sid;
+
+  // Using id_malloc/id_free API instead of id_alloca since the latter gives the
+  // warning: the address of 'sid' will always evaluate as 'true'.
+  if (snd_mixer_selem_id_malloc(&sid))
+    return NULL;
+
+  snd_mixer_selem_id_set_index(sid, 0);
+  snd_mixer_selem_id_set_name(sid, element_name);
+  snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
+  if (!elem) {
+    LOG(ERROR) << "ALSA unable to find simple control "
+               << snd_mixer_selem_id_get_name(sid);
+  }
+
+  snd_mixer_selem_id_free(sid);
+  return elem;
+}
+
+bool AudioMixerAlsa::GetElementVolume_Locked(snd_mixer_elem_t* elem,
+                                             double* current_vol) const {
+  alsa_long_t long_vol = 0;
+  snd_mixer_selem_get_playback_dB(elem,
+                                  static_cast<snd_mixer_selem_channel_id_t>(0),
+                                  &long_vol);
+  *current_vol = static_cast<double>(long_vol) / 100.0;
+
+  return true;
+}
+
+bool AudioMixerAlsa::SetElementVolume_Locked(snd_mixer_elem_t* elem,
+                                             double new_vol,
+                                             double* actual_vol,
+                                             double rounding_bias) {
+  alsa_long_t vol_lo = 0;
+  alsa_long_t vol_hi = 0;
+  snd_mixer_selem_get_playback_volume_range(elem, &vol_lo, &vol_hi);
+  alsa_long_t vol_range = vol_hi - vol_lo;
+  if (vol_range <= 0)
+    return false;
+
+  alsa_long_t db_lo_int = 0;
+  alsa_long_t db_hi_int = 0;
+  snd_mixer_selem_get_playback_dB_range(elem, &db_lo_int, &db_hi_int);
+  double db_lo = static_cast<double>(db_lo_int) / 100.0;
+  double db_hi = static_cast<double>(db_hi_int) / 100.0;
+  double db_step = static_cast<double>(db_hi - db_lo) / vol_range;
+  if (db_step <= 0.0)
+    return false;
+
+  if (new_vol < db_lo)
+    new_vol = db_lo;
+
+  alsa_long_t value = static_cast<alsa_long_t>(rounding_bias +
+      (new_vol - db_lo) / db_step) + vol_lo;
+  snd_mixer_selem_set_playback_volume_all(elem, value);
+
+  VLOG(1) << "Set volume " << snd_mixer_selem_get_name(elem)
+          << " to " << new_vol << " ==> " << (value - vol_lo) * db_step + db_lo
+          << " dB";
+
+  if (actual_vol) {
+    alsa_long_t volume = vol_lo;
+    snd_mixer_selem_get_playback_volume(
+        elem,
+        static_cast<snd_mixer_selem_channel_id_t>(0),
+        &volume);
+    *actual_vol = db_lo + (volume - vol_lo) * db_step;
+
+    VLOG(1) << "Actual volume " << snd_mixer_selem_get_name(elem)
+            << " now " << *actual_vol << " dB";
+  }
+  return true;
+}
+
+bool AudioMixerAlsa::GetElementMuted_Locked(snd_mixer_elem_t* elem) const {
+  int enabled = 0;
+  snd_mixer_selem_get_playback_switch(
+      elem,
+      static_cast<snd_mixer_selem_channel_id_t>(0),
+      &enabled);
+  return (enabled) ? false : true;
+}
+
+void AudioMixerAlsa::SetElementMuted_Locked(snd_mixer_elem_t* elem, bool mute) {
+  int enabled = mute ? 0 : 1;
+  snd_mixer_selem_set_playback_switch_all(elem, enabled);
+
+  VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem)
+          << " to " << enabled;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/audio_mixer_alsa.h b/chrome/browser/chromeos/audio_mixer_alsa.h
new file mode 100644
index 0000000..1626d29
--- /dev/null
+++ b/chrome/browser/chromeos/audio_mixer_alsa.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_
+#define CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "chrome/browser/chromeos/audio_mixer.h"
+
+class PrefService;
+
+struct _snd_mixer_elem;
+struct _snd_mixer;
+
+namespace chromeos {
+
+class AudioMixerAlsa : public AudioMixer {
+ public:
+  AudioMixerAlsa();
+  virtual ~AudioMixerAlsa();
+
+  // Implementation of AudioMixer
+  virtual void Init(InitDoneCallback* callback);
+  virtual bool InitSync();
+  virtual double GetVolumeDb() const;
+  virtual bool GetVolumeLimits(double* vol_min, double* vol_max);
+  virtual void SetVolumeDb(double vol_db);
+  virtual bool IsMute() const;
+  virtual void SetMute(bool mute);
+  virtual State GetState() const;
+
+  // Registers volume and mute in preferences
+  static void RegisterPrefs(PrefService* local_state);
+
+ private:
+  // Called to do initialization in background from worker thread.
+  void DoInit(InitDoneCallback* callback);
+
+  // Helper functions to get our message loop thread and prefs initialized.
+  bool InitThread();
+  void InitPrefs();
+
+  // Try to connect to the ALSA mixer through their simple controls interface,
+  // and cache mixer handle and mixer elements we'll be using.
+  bool InitializeAlsaMixer();
+  void FreeAlsaMixer();
+  void DoSetVolumeMute(double pref_volume, int pref_mute);
+
+  // Access to PrefMember variables must be done on UI thread.
+  void RestoreVolumeMuteOnUIThread();
+
+  // All these internal volume commands must be called with the lock held.
+  double DoGetVolumeDb_Locked() const;
+  void DoSetVolumeDb_Locked(double vol_db);
+
+  _snd_mixer_elem* FindElementWithName_Locked(_snd_mixer* handle,
+                                              const char* element_name) const;
+
+  bool GetElementVolume_Locked(_snd_mixer_elem* elem,
+                               double* current_vol) const;
+
+  // Since volume is done in steps, we may not get the exact volume asked for,
+  // so actual_vol will contain the true volume that was set.  This information
+  // can be used to further refine the volume by adjust a different mixer
+  // element.  The rounding_bias is added in before rounding to the nearest
+  // volume step (use 0.5 to round to nearest).
+  bool SetElementVolume_Locked(_snd_mixer_elem* elem,
+                               double new_vol,
+                               double* actual_vol,
+                               double rounding_bias);
+
+  // In ALSA, the mixer element's 'switch' is turned off to mute.
+  bool GetElementMuted_Locked(_snd_mixer_elem* elem) const;
+  void SetElementMuted_Locked(_snd_mixer_elem* elem, bool mute);
+
+  // Volume range limits are computed once during InitializeAlsaMixer.
+  double min_volume_;
+  double max_volume_;
+
+  // Muting is done by setting volume to minimum, so we must save the original.
+  // This is the only state information kept in this object.  In some cases,
+  // ALSA can report it has a volume switch and we can turn it off, but it has
+  // no effect.
+  double save_volume_;
+
+  mutable base::Lock mixer_state_lock_;
+  mutable State mixer_state_;
+
+  // Cached contexts for use in ALSA calls.
+  _snd_mixer* alsa_mixer_;
+  _snd_mixer_elem* elem_master_;
+  _snd_mixer_elem* elem_pcm_;
+
+  PrefService* prefs_;
+  base::WaitableEvent done_event_;
+
+  scoped_ptr<base::Thread> thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(AudioMixerAlsa);
+};
+
+}  // namespace chromeos
+
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::AudioMixerAlsa);
+
+#endif  // CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_
diff --git a/chrome/browser/chromeos/audio_mixer_pulse.cc b/chrome/browser/chromeos/audio_mixer_pulse.cc
new file mode 100644
index 0000000..5ea27fe
--- /dev/null
+++ b/chrome/browser/chromeos/audio_mixer_pulse.cc
@@ -0,0 +1,488 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/audio_mixer_pulse.h"
+
+#include <pulse/pulseaudio.h>
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/browser_thread.h"
+
+namespace chromeos {
+
+// Using asynchronous versions of the threaded PulseAudio API, as well
+// as a worker thread so gets, sets, and the init sequence do not block the
+// calling thread.  GetVolume() and IsMute() can still be called synchronously
+// if needed, but take a bit longer (~2ms vs ~0.3ms).
+//
+// Set calls just return without waiting.  If you must guarantee the value has
+// been set before continuing, immediately call the blocking Get version to
+// synchronously get the value back.
+//
+// TODO(davej): Serialize volume/mute to preserve settings when restarting?
+
+namespace {
+
+const int kInvalidDeviceId = -1;
+
+const double kMinVolumeDb = -90.0;
+// Choosing 6.0dB here instead of 0dB to give user chance to amplify audio some
+// in case sounds or their setup is too quiet for them.
+const double kMaxVolumeDb = 6.0;
+
+// Used for passing custom data to the PulseAudio callbacks.
+struct CallbackWrapper {
+  AudioMixerPulse* instance;
+  bool done;
+  void* userdata;
+};
+
+}  // namespace
+
+// AudioInfo contains all the values we care about when getting info for a
+// Sink (output device) used by GetAudioInfo().
+struct AudioMixerPulse::AudioInfo {
+  pa_cvolume cvolume;
+  bool muted;
+};
+
+AudioMixerPulse::AudioMixerPulse()
+    : device_id_(kInvalidDeviceId),
+      last_channels_(0),
+      mainloop_lock_count_(0),
+      mixer_state_(UNINITIALIZED),
+      pa_context_(NULL),
+      pa_mainloop_(NULL) {
+}
+
+AudioMixerPulse::~AudioMixerPulse() {
+  bool run_all_pending = false;
+  {
+    base::AutoLock lock(mixer_state_lock_);
+    // DoInit() has not even been called yet, but is still in the thread message
+    // queue.  Force it out of the queue and exit DoInit() right away.
+    if ((!pa_mainloop_) && (mixer_state_ == INITIALIZING)) {
+      mixer_state_ = UNINITIALIZED;
+      run_all_pending = true;
+    }
+  }
+  if (run_all_pending)
+    thread_->message_loop()->RunAllPending();
+
+  PulseAudioFree();
+  if (thread_ != NULL) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    // A ScopedAllowIO object is required to join the thread when calling Stop.
+    // The worker thread should be idle at this time.
+    // See http://crosbug.com/11110 for discussion.
+    base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
+    thread_->message_loop()->AssertIdle();
+
+    thread_->Stop();
+    thread_.reset();
+  }
+}
+
+void AudioMixerPulse::Init(InitDoneCallback* callback) {
+  DCHECK(callback);
+  if (!InitThread()) {
+    callback->Run(false);
+    delete callback;
+    return;
+  }
+
+  // Post the task of starting up, which can block for 200-500ms,
+  // so best not to do it on the caller's thread.
+  thread_->message_loop()->PostTask(FROM_HERE,
+      NewRunnableMethod(this, &AudioMixerPulse::DoInit, callback));
+}
+
+bool AudioMixerPulse::InitSync() {
+  if (!InitThread())
+    return false;
+  return PulseAudioInit();
+}
+
+double AudioMixerPulse::GetVolumeDb() const {
+  if (!MainloopLockIfReady())
+    return AudioMixer::kSilenceDb;
+  AudioInfo data;
+  GetAudioInfo(&data);
+  MainloopUnlock();
+  return pa_sw_volume_to_dB(data.cvolume.values[0]);
+}
+
+bool AudioMixerPulse::GetVolumeLimits(double* vol_min, double* vol_max) {
+  if (vol_min)
+    *vol_min = kMinVolumeDb;
+  if (vol_max)
+    *vol_max = kMaxVolumeDb;
+  return true;
+}
+
+void AudioMixerPulse::SetVolumeDb(double vol_db) {
+  if (!MainloopLockIfReady())
+    return;
+
+  // last_channels_ determines the number of channels on the main output device,
+  // and is used later to set the volume on all channels at once.
+  if (!last_channels_) {
+    AudioInfo data;
+    GetAudioInfo(&data);
+    last_channels_ = data.cvolume.channels;
+  }
+
+  pa_operation* pa_op;
+  pa_cvolume cvolume;
+  pa_cvolume_set(&cvolume, last_channels_, pa_sw_volume_from_dB(vol_db));
+  pa_op = pa_context_set_sink_volume_by_index(pa_context_, device_id_,
+                                              &cvolume, NULL, NULL);
+  pa_operation_unref(pa_op);
+  MainloopUnlock();
+  VLOG(1) << "Set volume to " << vol_db << " dB";
+}
+
+bool AudioMixerPulse::IsMute() const {
+  if (!MainloopLockIfReady())
+    return false;
+  AudioInfo data;
+  GetAudioInfo(&data);
+  MainloopUnlock();
+  return data.muted;
+}
+
+void AudioMixerPulse::SetMute(bool mute) {
+  if (!MainloopLockIfReady())
+    return;
+  pa_operation* pa_op;
+  pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_,
+                                            mute ? 1 : 0, NULL, NULL);
+  pa_operation_unref(pa_op);
+  MainloopUnlock();
+  VLOG(1) << "Set mute to " << mute;
+}
+
+AudioMixer::State AudioMixerPulse::GetState() const {
+  base::AutoLock lock(mixer_state_lock_);
+  // If we think it's ready, verify it is actually so.
+  if ((mixer_state_ == READY) &&
+      (pa_context_get_state(pa_context_) != PA_CONTEXT_READY))
+    mixer_state_ = IN_ERROR;
+  return mixer_state_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private functions follow
+
+void AudioMixerPulse::DoInit(InitDoneCallback* callback) {
+  bool success = PulseAudioInit();
+  callback->Run(success);
+  delete callback;
+}
+
+bool AudioMixerPulse::InitThread() {
+  base::AutoLock lock(mixer_state_lock_);
+
+  if (mixer_state_ != UNINITIALIZED)
+    return false;
+
+  if (thread_ == NULL) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    thread_.reset(new base::Thread("AudioMixerPulse"));
+    if (!thread_->Start()) {
+      thread_.reset();
+      return false;
+    }
+  }
+  mixer_state_ = INITIALIZING;
+  return true;
+}
+
+// static
+void AudioMixerPulse::ConnectToPulseCallbackThunk(
+    pa_context* context, void* userdata) {
+  CallbackWrapper* data =
+      static_cast<CallbackWrapper*>(userdata);
+  data->instance->OnConnectToPulseCallback(context, &data->done);
+}
+
+void AudioMixerPulse::OnConnectToPulseCallback(
+    pa_context* context, bool* connect_done) {
+  pa_context_state_t state = pa_context_get_state(context);
+  if (state == PA_CONTEXT_READY ||
+      state == PA_CONTEXT_FAILED ||
+      state == PA_CONTEXT_TERMINATED) {
+    // Connection process has reached a terminal state. Wake PulseAudioInit().
+    *connect_done = true;
+    MainloopSignal();
+  }
+}
+
+bool AudioMixerPulse::PulseAudioInit() {
+  pa_context_state_t state = PA_CONTEXT_FAILED;
+
+  {
+    base::AutoLock lock(mixer_state_lock_);
+    if (mixer_state_ != INITIALIZING)
+      return false;
+
+    pa_mainloop_ = pa_threaded_mainloop_new();
+    if (!pa_mainloop_) {
+      LOG(ERROR) << "Can't create PulseAudio mainloop";
+      mixer_state_ = UNINITIALIZED;
+      return false;
+    }
+
+    if (pa_threaded_mainloop_start(pa_mainloop_) != 0) {
+      LOG(ERROR) << "Can't start PulseAudio mainloop";
+      pa_threaded_mainloop_free(pa_mainloop_);
+      mixer_state_ = UNINITIALIZED;
+      return false;
+    }
+  }
+
+  while (true) {
+    // Create connection to default server.
+    if (!MainloopSafeLock())
+      return false;
+
+    while (true) {
+      pa_mainloop_api* pa_mlapi = pa_threaded_mainloop_get_api(pa_mainloop_);
+      if (!pa_mlapi) {
+        LOG(ERROR) << "Can't get PulseAudio mainloop api";
+        break;
+      }
+      // This one takes the most time if run at app startup.
+      pa_context_ = pa_context_new(pa_mlapi, "ChromeAudio");
+      if (!pa_context_) {
+        LOG(ERROR) << "Can't create new PulseAudio context";
+        break;
+      }
+
+      MainloopUnlock();
+      if (!MainloopSafeLock())
+        return false;
+
+      CallbackWrapper data = {this, false, NULL};
+      pa_context_set_state_callback(pa_context_,
+                                    &ConnectToPulseCallbackThunk,
+                                    &data);
+
+      if (pa_context_connect(pa_context_, NULL,
+                             PA_CONTEXT_NOAUTOSPAWN, NULL) != 0) {
+        LOG(ERROR) << "Can't start connection to PulseAudio sound server";
+      } else {
+        // Wait until we have a completed connection or fail.
+        do {
+          MainloopWait();
+        } while (!data.done);
+
+        state = pa_context_get_state(pa_context_);
+
+        if (state == PA_CONTEXT_FAILED) {
+          LOG(ERROR) << "PulseAudio connection failed (daemon not running?)";
+        } else if (state == PA_CONTEXT_TERMINATED) {
+          LOG(ERROR) << "PulseAudio connection terminated early";
+        } else if (state != PA_CONTEXT_READY) {
+          LOG(ERROR) << "Unknown problem connecting to PulseAudio";
+        }
+      }
+
+      pa_context_set_state_callback(pa_context_, NULL, NULL);
+      break;
+    }
+
+    MainloopUnlock();
+
+    if (state != PA_CONTEXT_READY)
+      break;
+
+    if (!MainloopSafeLock())
+      return false;
+    GetDefaultPlaybackDevice();
+    MainloopUnlock();
+
+    if (device_id_ == kInvalidDeviceId)
+      break;
+
+    {
+      base::AutoLock lock(mixer_state_lock_);
+      if (mixer_state_ == SHUTTING_DOWN)
+        return false;
+      mixer_state_ = READY;
+    }
+
+    return true;
+  }
+
+  // Failed startup sequence, clean up now.
+  PulseAudioFree();
+  return false;
+}
+
+void AudioMixerPulse::PulseAudioFree() {
+  {
+    base::AutoLock lock(mixer_state_lock_);
+    if (!pa_mainloop_)
+      mixer_state_ = UNINITIALIZED;
+    if ((mixer_state_ == UNINITIALIZED) || (mixer_state_ == SHUTTING_DOWN))
+      return;
+
+    // If still initializing on another thread, this will cause it to exit.
+    mixer_state_ = SHUTTING_DOWN;
+  }
+
+  DCHECK(pa_mainloop_);
+
+  MainloopLock();
+  if (pa_context_) {
+    pa_context_disconnect(pa_context_);
+    pa_context_unref(pa_context_);
+    pa_context_ = NULL;
+  }
+  MainloopUnlock();
+
+  pa_threaded_mainloop_stop(pa_mainloop_);
+  pa_threaded_mainloop_free(pa_mainloop_);
+  pa_mainloop_ = NULL;
+
+  {
+    base::AutoLock lock(mixer_state_lock_);
+    mixer_state_ = UNINITIALIZED;
+  }
+}
+
+void AudioMixerPulse::CompleteOperation(pa_operation* pa_op,
+                                        bool* done) const {
+  // After starting any operation, this helper checks if it started OK, then
+  // waits for it to complete by iterating through the mainloop until the
+  // operation is not running anymore.
+  CHECK(pa_op);
+
+  while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
+    // If operation still running, but we got what we needed, cancel it now.
+    if (*done) {
+      pa_operation_cancel(pa_op);
+      break;
+    }
+    MainloopWait();
+  }
+  pa_operation_unref(pa_op);
+}
+
+// Must be called with mainloop lock held
+void AudioMixerPulse::GetDefaultPlaybackDevice() {
+  DCHECK_GT(mainloop_lock_count_, 0);
+  DCHECK(pa_context_);
+  DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY);
+
+  CallbackWrapper data = {this, false, NULL};
+
+  pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_,
+                                        EnumerateDevicesCallback,
+                                        &data);
+  CompleteOperation(pa_op, &data.done);
+  return;
+}
+
+void AudioMixerPulse::OnEnumerateDevices(const pa_sink_info* sink_info,
+                                         int eol, bool* done) {
+  if (device_id_ != kInvalidDeviceId)
+    return;
+
+  // TODO(davej): Should we handle cases of more than one output sink device?
+
+  // eol is < 0 for error, > 0 for end of list, ==0 while listing.
+  if (eol == 0) {
+    device_id_ = sink_info->index;
+  }
+  *done = true;
+  MainloopSignal();
+}
+
+// static
+void AudioMixerPulse::EnumerateDevicesCallback(pa_context* unused,
+                                               const pa_sink_info* sink_info,
+                                               int eol,
+                                               void* userdata) {
+  CallbackWrapper* data =
+      static_cast<CallbackWrapper*>(userdata);
+  data->instance->OnEnumerateDevices(sink_info, eol, &data->done);
+}
+
+// Must be called with lock held
+void AudioMixerPulse::GetAudioInfo(AudioInfo* info) const {
+  DCHECK_GT(mainloop_lock_count_, 0);
+  CallbackWrapper data = {const_cast<AudioMixerPulse*>(this), false, info};
+  pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_,
+                                                          device_id_,
+                                                          GetAudioInfoCallback,
+                                                          &data);
+  CompleteOperation(pa_op, &data.done);
+}
+
+// static
+void AudioMixerPulse::GetAudioInfoCallback(pa_context* unused,
+                                           const pa_sink_info* sink_info,
+                                           int eol,
+                                           void* userdata) {
+  CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata);
+  AudioInfo* info = static_cast<AudioInfo*>(data->userdata);
+
+  // Copy just the information we care about.
+  if (eol == 0) {
+    info->cvolume = sink_info->volume;
+    info->muted = sink_info->mute ? true : false;
+    data->done = true;
+  }
+  data->instance->MainloopSignal();
+}
+
+inline void AudioMixerPulse::MainloopLock() const {
+  pa_threaded_mainloop_lock(pa_mainloop_);
+  ++mainloop_lock_count_;
+}
+
+inline void AudioMixerPulse::MainloopUnlock() const {
+  --mainloop_lock_count_;
+  pa_threaded_mainloop_unlock(pa_mainloop_);
+}
+
+// Must be called with the lock held.
+inline void AudioMixerPulse::MainloopWait() const {
+  DCHECK_GT(mainloop_lock_count_, 0);
+  pa_threaded_mainloop_wait(pa_mainloop_);
+}
+
+// Must be called with the lock held.
+inline void AudioMixerPulse::MainloopSignal() const {
+  DCHECK_GT(mainloop_lock_count_, 0);
+  pa_threaded_mainloop_signal(pa_mainloop_, 0);
+}
+
+inline bool AudioMixerPulse::MainloopSafeLock() const {
+  base::AutoLock lock(mixer_state_lock_);
+  if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_))
+    return false;
+
+  pa_threaded_mainloop_lock(pa_mainloop_);
+  ++mainloop_lock_count_;
+  return true;
+}
+
+inline bool AudioMixerPulse::MainloopLockIfReady() const {
+  base::AutoLock lock(mixer_state_lock_);
+  if (mixer_state_ != READY)
+    return false;
+  if (!pa_mainloop_)
+    return false;
+  pa_threaded_mainloop_lock(pa_mainloop_);
+  ++mainloop_lock_count_;
+  return true;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/audio_mixer_pulse.h b/chrome/browser/chromeos/audio_mixer_pulse.h
new file mode 100644
index 0000000..4eb3f9c
--- /dev/null
+++ b/chrome/browser/chromeos/audio_mixer_pulse.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_PULSE_H_
+#define CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_PULSE_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread.h"
+#include "chrome/browser/chromeos/audio_mixer.h"
+
+struct pa_context;
+struct pa_cvolume;
+struct pa_threaded_mainloop;
+struct pa_operation;
+struct pa_sink_info;
+
+namespace chromeos {
+
+class AudioMixerPulse : public AudioMixer {
+ public:
+
+  AudioMixerPulse();
+  virtual ~AudioMixerPulse();
+
+  // Implementation of AudioMixer
+  virtual void Init(InitDoneCallback* callback);
+  virtual bool InitSync();
+  virtual double GetVolumeDb() const;
+  virtual bool GetVolumeLimits(double* vol_min, double* vol_max);
+  virtual void SetVolumeDb(double vol_db);
+  virtual bool IsMute() const;
+  virtual void SetMute(bool mute);
+  virtual State GetState() const;
+
+ private:
+  struct AudioInfo;
+
+  // The initialization task is run in the background on the worker thread.
+  void DoInit(InitDoneCallback* callback);
+
+  static void ConnectToPulseCallbackThunk(pa_context* c, void* userdata);
+  void OnConnectToPulseCallback(pa_context* c, bool* connect_done);
+
+  // Helper function to just get our messsage loop thread going.
+  bool InitThread();
+
+  // This goes through sequence of connecting to the default PulseAudio server.
+  // We will block until we either have a valid connection or something failed.
+  // If a connection is lost for some reason, delete and recreate the object.
+  bool PulseAudioInit();
+
+  // PulseAudioFree.  Disconnect from server.
+  void PulseAudioFree();
+
+  // Iterates the PA mainloop and only returns once an operation has completed
+  // (successfully or unsuccessfully) or *done is true.
+  void CompleteOperation(pa_operation* pa_op, bool* done) const;
+
+  // For now, this just gets the first device returned from the enumeration
+  // request.  This will be the 'default' or 'master' device that all further
+  // actions are taken on.  Blocking call.
+  void GetDefaultPlaybackDevice();
+  static void EnumerateDevicesCallback(pa_context* unused,
+                                       const pa_sink_info* sink_info,
+                                       int eol,
+                                       void* userdata);
+  void OnEnumerateDevices(const pa_sink_info* sink_info, int eol, bool* done);
+
+  // Get the info we're interested in from the default device. Currently this
+  // is an array of volumes, and the mute state.  Blocking call.
+  void GetAudioInfo(AudioInfo* info) const;
+  static void GetAudioInfoCallback(pa_context* unused,
+                                   const pa_sink_info* sink_info,
+                                   int eol,
+                                   void* userdata);
+
+  // These call down to PulseAudio's mainloop locking functions
+  void MainloopLock() const;
+  void MainloopUnlock() const;
+  void MainloopWait() const;
+  void MainloopSignal() const;
+
+  // Same as Lock(), but we fail if we are shutting down or mainloop invalid.
+  bool MainloopSafeLock() const;
+
+  // Lock the mainloop pa_lock_ if mixer_state_ is READY.
+  bool MainloopLockIfReady() const;
+
+  // The PulseAudio index of the main device being used.
+  int device_id_;
+
+  // Set to the number of channels on the main device.
+  int last_channels_;
+
+  // For informational purposes only, just used to assert lock is held.
+  mutable int mainloop_lock_count_;
+
+  mutable base::Lock mixer_state_lock_;
+  mutable State mixer_state_;
+
+  // Cached contexts for use in PulseAudio calls.
+  pa_context* pa_context_;
+  pa_threaded_mainloop* pa_mainloop_;
+
+  scoped_ptr<base::Thread> thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(AudioMixerPulse);
+};
+
+}  // namespace chromeos
+
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::AudioMixerPulse);
+
+#endif  // CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_PULSE_H_
+
diff --git a/chrome/browser/chromeos/brightness_bubble.cc b/chrome/browser/chromeos/brightness_bubble.cc
index 5299e4b..11664e5 100644
--- a/chrome/browser/chromeos/brightness_bubble.cc
+++ b/chrome/browser/chromeos/brightness_bubble.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/chromeos/brightness_bubble.h"
 
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/cros/burn_library.cc b/chrome/browser/chromeos/cros/burn_library.cc
index f1c2c51..dcae858 100644
--- a/chrome/browser/chromeos/cros/burn_library.cc
+++ b/chrome/browser/chromeos/cros/burn_library.cc
@@ -11,6 +11,54 @@
 
 namespace chromeos {
 
+class BurnLibraryImpl : public BurnLibrary,
+                        public base::SupportsWeakPtr<BurnLibraryImpl> {
+ public:
+
+  BurnLibraryImpl();
+  virtual ~BurnLibraryImpl();
+
+  // BurnLibrary implementation.
+  virtual void AddObserver(Observer* observer);
+  virtual void RemoveObserver(Observer* observer);
+  virtual bool DoBurn(const FilePath& from_path, const FilePath& to_path);
+
+  bool BurnImage(const FilePath& from_path, const FilePath& to_path);
+  void UpdateBurnStatus(const ImageBurnStatus& status, BurnEventType evt);
+
+ private:
+  void Init();
+  static void BurnStatusChangedHandler(void* object,
+                                       const BurnStatus& status,
+                                       BurnEventType evt);
+
+ private:
+  ObserverList<BurnLibrary::Observer> observers_;
+  BurnStatusConnection burn_status_connection_;
+
+  // Holds a path that is currently being burnt to.
+  std::string target_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(BurnLibraryImpl);
+};
+
+class BurnLibraryTaskProxy
+    : public base::RefCountedThreadSafe<BurnLibraryTaskProxy> {
+ public:
+  explicit BurnLibraryTaskProxy(const base::WeakPtr<BurnLibraryImpl>& library);
+
+  void BurnImage(const FilePath& from_path, const FilePath& to_path);
+
+  void UpdateBurnStatus(ImageBurnStatus* status, BurnEventType evt);
+
+ private:
+  base::WeakPtr<BurnLibraryImpl> library_;
+
+  friend class base::RefCountedThreadSafe<BurnLibraryTaskProxy>;
+
+  DISALLOW_COPY_AND_ASSIGN(BurnLibraryTaskProxy);
+};
+
 BurnLibraryImpl::BurnLibraryImpl() {
   if (CrosLibrary::Get()->EnsureLoaded()) {
       Init();
diff --git a/chrome/browser/chromeos/cros/burn_library.h b/chrome/browser/chromeos/cros/burn_library.h
index bc4a657..cfed778 100644
--- a/chrome/browser/chromeos/cros/burn_library.h
+++ b/chrome/browser/chromeos/cros/burn_library.h
@@ -49,54 +49,6 @@
   static BurnLibrary* GetImpl(bool stub);
 };
 
-class BurnLibraryImpl : public BurnLibrary,
-                        public base::SupportsWeakPtr<BurnLibraryImpl> {
- public:
-
-  BurnLibraryImpl();
-  virtual ~BurnLibraryImpl();
-
-  // BurnLibrary implementation.
-  virtual void AddObserver(Observer* observer);
-  virtual void RemoveObserver(Observer* observer);
-  virtual bool DoBurn(const FilePath& from_path, const FilePath& to_path);
-
-  bool BurnImage(const FilePath& from_path, const FilePath& to_path);
-  void UpdateBurnStatus(const ImageBurnStatus& status, BurnEventType evt);
-
- private:
-  void Init();
-  static void BurnStatusChangedHandler(void* object,
-                                       const BurnStatus& status,
-                                       BurnEventType evt);
-
- private:
-  ObserverList<BurnLibrary::Observer> observers_;
-  BurnStatusConnection burn_status_connection_;
-
-  // Holds a path that is currently being burnt to.
-  std::string target_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(BurnLibraryImpl);
-};
-
-class BurnLibraryTaskProxy
-    : public base::RefCountedThreadSafe<BurnLibraryTaskProxy> {
- public:
-  explicit BurnLibraryTaskProxy(const base::WeakPtr<BurnLibraryImpl>& library);
-
-  void BurnImage(const FilePath& from_path, const FilePath& to_path);
-
-  void UpdateBurnStatus(ImageBurnStatus* status, BurnEventType evt);
-
- private:
-  base::WeakPtr<BurnLibraryImpl> library_;
-
-  friend class base::RefCountedThreadSafe<BurnLibraryTaskProxy>;
-
-  DISALLOW_COPY_AND_ASSIGN(BurnLibraryTaskProxy);
-};
-
 }  // namespace chromeos
 
 #endif  // CHROME_BROWSER_CHROMEOS_CROS_BURN_LIBRARY_H_
diff --git a/chrome/browser/chromeos/cros/cros_library.cc b/chrome/browser/chromeos/cros/cros_library.cc
index af6e426..5d22643 100644
--- a/chrome/browser/chromeos/cros/cros_library.cc
+++ b/chrome/browser/chromeos/cros/cros_library.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
 #include "chrome/browser/chromeos/cros/input_method_library.h"
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
+#include "chrome/browser/chromeos/cros/libcros_service_library.h"
 #include "chrome/browser/chromeos/cros/login_library.h"
 #include "chrome/browser/chromeos/cros/mount_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
@@ -62,6 +63,7 @@
 DEFINE_GET_LIBRARY_METHOD(Cryptohome, crypto);
 DEFINE_GET_LIBRARY_METHOD(Keyboard, keyboard);
 DEFINE_GET_LIBRARY_METHOD(InputMethod, input_method);
+DEFINE_GET_LIBRARY_METHOD(LibCrosService, libcros_service);
 DEFINE_GET_LIBRARY_METHOD(Login, login);
 DEFINE_GET_LIBRARY_METHOD(Mount, mount);
 DEFINE_GET_LIBRARY_METHOD(Network, network);
@@ -120,6 +122,7 @@
 DEFINE_SET_LIBRARY_METHOD(Cryptohome, crypto);
 DEFINE_SET_LIBRARY_METHOD(Keyboard, keyboard);
 DEFINE_SET_LIBRARY_METHOD(InputMethod, input_method);
+DEFINE_SET_LIBRARY_METHOD(LibCrosService, libcros_service);
 DEFINE_SET_LIBRARY_METHOD(Login, login);
 DEFINE_SET_LIBRARY_METHOD(Mount, mount);
 DEFINE_SET_LIBRARY_METHOD(Network, network);
diff --git a/chrome/browser/chromeos/cros/cros_library.h b/chrome/browser/chromeos/cros/cros_library.h
index 9c5810c..1781d2b 100644
--- a/chrome/browser/chromeos/cros/cros_library.h
+++ b/chrome/browser/chromeos/cros/cros_library.h
@@ -23,6 +23,7 @@
 class CryptohomeLibrary;
 class InputMethodLibrary;
 class KeyboardLibrary;
+class LibCrosServiceLibrary;
 class LibraryLoader;
 class LoginLibrary;
 class MountLibrary;
@@ -62,6 +63,7 @@
     void SetCryptohomeLibrary(CryptohomeLibrary* library, bool own);
     void SetKeyboardLibrary(KeyboardLibrary* library, bool own);
     void SetInputMethodLibrary(InputMethodLibrary* library, bool own);
+    void SetLibCrosServiceLibrary(LibCrosServiceLibrary* library, bool own);
     void SetLoginLibrary(LoginLibrary* library, bool own);
     void SetMountLibrary(MountLibrary* library, bool own);
     void SetNetworkLibrary(NetworkLibrary* library, bool own);
@@ -86,6 +88,7 @@
   BurnLibrary* GetBurnLibrary();
   CryptohomeLibrary* GetCryptohomeLibrary();
   InputMethodLibrary* GetInputMethodLibrary();
+  LibCrosServiceLibrary* GetLibCrosServiceLibrary();
   KeyboardLibrary* GetKeyboardLibrary();
   LoginLibrary* GetLoginLibrary();
   MountLibrary* GetMountLibrary();
@@ -163,6 +166,7 @@
   Library<CryptohomeLibrary> crypto_lib_;
   Library<KeyboardLibrary> keyboard_lib_;
   Library<InputMethodLibrary> input_method_lib_;
+  Library<LibCrosServiceLibrary> libcros_service_lib_;
   Library<LoginLibrary> login_lib_;
   Library<MountLibrary> mount_lib_;
   Library<NetworkLibrary> network_lib_;
diff --git a/chrome/browser/chromeos/cros/cros_mock.cc b/chrome/browser/chromeos/cros/cros_mock.cc
index efdfbcc..ce33885 100644
--- a/chrome/browser/chromeos/cros/cros_mock.cc
+++ b/chrome/browser/chromeos/cros/cros_mock.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/chromeos/cros/mock_speech_synthesis_library.h"
 #include "chrome/browser/chromeos/cros/mock_system_library.h"
 #include "chrome/browser/chromeos/cros/mock_touchpad_library.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/login/wizard_screen.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -46,7 +46,12 @@
       mock_screen_lock_library_(NULL),
       mock_speech_synthesis_library_(NULL),
       mock_system_library_(NULL),
-      mock_touchpad_library_(NULL) {}
+      mock_touchpad_library_(NULL),
+      current_input_method_("", "", "", ""),
+      previous_input_method_("", "", "", "") {
+  current_input_method_ =
+      input_method::GetFallbackInputMethodDescriptor();
+}
 
 CrosMock::~CrosMock() {
 }
@@ -195,14 +200,6 @@
 }
 
 void CrosMock::SetKeyboardLibraryStatusAreaExpectations() {
-  EXPECT_CALL(*mock_keyboard_library_, GetHardwareKeyboardLayoutName())
-      .Times(AnyNumber())
-      .WillRepeatedly((Return("xkb:us::eng")))
-      .RetiresOnSaturation();
-  EXPECT_CALL(*mock_keyboard_library_, GetCurrentKeyboardLayoutName())
-      .Times(AnyNumber())
-      .WillRepeatedly((Return("us")))
-      .RetiresOnSaturation();
   EXPECT_CALL(*mock_keyboard_library_, SetCurrentKeyboardLayoutByName(_))
       .Times(AnyNumber())
       .WillRepeatedly((Return(true)))
@@ -211,14 +208,6 @@
       .Times(AnyNumber())
       .WillRepeatedly((Return(true)))
       .RetiresOnSaturation();
-  EXPECT_CALL(*mock_keyboard_library_, SetKeyboardLayoutPerWindow(_))
-      .Times(AnyNumber())
-      .WillRepeatedly((Return(true)))
-      .RetiresOnSaturation();
-  EXPECT_CALL(*mock_keyboard_library_, GetKeyboardLayoutPerWindow(_))
-      .Times(AnyNumber())
-      .WillRepeatedly((Return(true)))
-      .RetiresOnSaturation();
   EXPECT_CALL(*mock_keyboard_library_, GetAutoRepeatEnabled(_))
       .Times(AnyNumber())
       .WillRepeatedly((Return(true)))
@@ -243,16 +232,28 @@
       .RetiresOnSaturation();
   EXPECT_CALL(*mock_input_method_library_, GetActiveInputMethods())
       .Times(AnyNumber())
-      .WillRepeatedly(InvokeWithoutArgs(CreateFallbackInputMethodDescriptors))
+      .WillRepeatedly(InvokeWithoutArgs(CreateInputMethodDescriptors))
       .RetiresOnSaturation();
   EXPECT_CALL(*mock_input_method_library_, GetSupportedInputMethods())
       .Times(AnyNumber())
-      .WillRepeatedly(InvokeWithoutArgs(CreateFallbackInputMethodDescriptors))
+      .WillRepeatedly(InvokeWithoutArgs(CreateInputMethodDescriptors))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*mock_input_method_library_, current_input_method())
+      .Times(AnyNumber())
+      .WillRepeatedly((ReturnRef(current_input_method_)))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*mock_input_method_library_, previous_input_method())
+      .Times(AnyNumber())
+      .WillRepeatedly((ReturnRef(previous_input_method_)))
       .RetiresOnSaturation();
   EXPECT_CALL(*mock_input_method_library_, current_ime_properties())
       .Times(AnyNumber())
       .WillRepeatedly((ReturnRef(ime_properties_)))
       .RetiresOnSaturation();
+  EXPECT_CALL(*mock_input_method_library_, GetNumActiveInputMethods())
+      .Times(AnyNumber())
+      .WillRepeatedly((Return(1)))
+      .RetiresOnSaturation();
   EXPECT_CALL(*mock_input_method_library_, SetImeConfig(_, _, _))
       .Times(AnyNumber())
       .WillRepeatedly((Return(true)))
@@ -263,7 +264,7 @@
   EXPECT_CALL(*mock_input_method_library_, SetDeferImeStartup(_))
       .Times(AnyNumber())
       .RetiresOnSaturation();
-  EXPECT_CALL(*mock_input_method_library_, StopInputMethodProcesses())
+  EXPECT_CALL(*mock_input_method_library_, StopInputMethodDaemon())
       .Times(AnyNumber())
       .RetiresOnSaturation();
 }
@@ -280,6 +281,9 @@
       .Times(AnyNumber());
   EXPECT_CALL(*mock_network_library_, RemoveCellularDataPlanObserver(_))
       .Times(AnyNumber());
+  EXPECT_CALL(*mock_network_library_, IsLocked())
+      .Times(AnyNumber())
+      .WillRepeatedly((Return(false)));
   EXPECT_CALL(*mock_network_library_, ethernet_available())
       .Times(AnyNumber())
       .WillRepeatedly((Return(true)));
@@ -327,6 +331,10 @@
       .RetiresOnSaturation();
 
   // NetworkMenu::InitMenuItems() calls:
+  EXPECT_CALL(*mock_network_library_, IsLocked())
+      .Times(AnyNumber())
+      .WillRepeatedly((Return(false)))
+      .RetiresOnSaturation();
   EXPECT_CALL(*mock_network_library_, ethernet_connected())
       .Times(1)
       .WillRepeatedly((Return(false)))
@@ -448,4 +456,11 @@
     test_api()->SetTouchpadLibrary(NULL, false);
 }
 
+InputMethodDescriptors* CrosMock::CreateInputMethodDescriptors() {
+  InputMethodDescriptors* descriptors = new InputMethodDescriptors;
+  descriptors->push_back(
+      input_method::GetFallbackInputMethodDescriptor());
+  return descriptors;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/cros_mock.h b/chrome/browser/chromeos/cros/cros_mock.h
index 990b43f..1e8c577 100644
--- a/chrome/browser/chromeos/cros/cros_mock.h
+++ b/chrome/browser/chromeos/cros/cros_mock.h
@@ -86,6 +86,10 @@
 
   void TearDownMocks();
 
+  // Creates input method descriptors. This is a helper function for
+  // SetInputMethodLibraryStatusAreaExpectations().
+  static InputMethodDescriptors* CreateInputMethodDescriptors();
+
   // TestApi gives access to CrosLibrary private members.
   chromeos::CrosLibrary::TestApi* test_api();
 
@@ -103,6 +107,8 @@
   MockTouchpadLibrary* mock_touchpad_library_;
 
   ImePropertyList ime_properties_;
+  InputMethodDescriptor current_input_method_;
+  InputMethodDescriptor previous_input_method_;
   WifiNetwork wifi_network_;
   WifiNetworkVector wifi_networks_;
   CellularNetwork cellular_network_;
diff --git a/chrome/browser/chromeos/cros/input_method_library.cc b/chrome/browser/chromeos/cros/input_method_library.cc
index c62c3fd..37229e9 100644
--- a/chrome/browser/chromeos/cros/input_method_library.cc
+++ b/chrome/browser/chromeos/cros/input_method_library.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
+#include "chrome/browser/chromeos/input_method/candidate_window.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "chrome/common/notification_observer.h"
@@ -25,7 +26,6 @@
 namespace {
 
 const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon";
-const char kCandidateWindowPath[] = "/opt/google/chrome/candidate_window";
 
 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the
 // property with |new_prop|. Returns true if such a property is found.
@@ -49,6 +49,7 @@
 
 namespace chromeos {
 
+// The production implementation of InputMethodLibrary.
 class InputMethodLibraryImpl : public InputMethodLibrary,
                                public NotificationObserver {
  public:
@@ -62,85 +63,138 @@
         enable_auto_ime_shutdown_(true),
         should_change_input_method_(false),
         ibus_daemon_process_id_(0),
-        candidate_window_process_id_(0) {
-    // TODO(yusukes): Using both CreateFallbackInputMethodDescriptors and
-    // chromeos::GetHardwareKeyboardLayoutName doesn't look clean. Probably
-    // we should unify these APIs.
-    scoped_ptr<InputMethodDescriptors> input_method_descriptors(
-        CreateFallbackInputMethodDescriptors());
-    current_input_method_ = input_method_descriptors->at(0);
-    if (CrosLibrary::Get()->EnsureLoaded()) {
-      current_input_method_id_ = chromeos::GetHardwareKeyboardLayoutName();
-    }
-    // Observe APP_EXITING to stop input method processes gracefully.
-    // Note that even if we fail to stop input method processes from
+        initialized_successfully_(false),
+        candidate_window_controller_(NULL) {
+    // Here, we use the fallback input method descriptor but
+    // |current_input_method_| will be updated as soon as the login screen
+    // is shown or the user is logged in, so there is no problem.
+    current_input_method_ = input_method::GetFallbackInputMethodDescriptor();
+    active_input_method_ids_.push_back(current_input_method_.id);
+    // Observe APP_TERMINATING to stop input method daemon gracefully.
+    // We should not use APP_EXITING here since logout might be canceled by
+    // JavaScript after APP_EXITING is sent (crosbug.com/11055).
+    // Note that even if we fail to stop input method daemon from
     // Chrome in case of a sudden crash, we have a way to do it from an
     // upstart script. See crosbug.com/6515 and crosbug.com/6995 for
     // details.
-    notification_registrar_.Add(this, NotificationType::APP_EXITING,
+    notification_registrar_.Add(this, NotificationType::APP_TERMINATING,
                                 NotificationService::AllSources());
   }
 
-  ~InputMethodLibraryImpl() {
+  // Initializes the object. On success, returns true on and sets
+  // initialized_successfully_ to true.
+  //
+  // Note that we start monitoring input method status in here in Init()
+  // to avoid a potential race. If we start the monitoring right after
+  // starting ibus-daemon, there is a higher chance of a race between
+  // Chrome and ibus-daemon to occur.
+  bool Init() {
+    DCHECK(!initialized_successfully_) << "Already initialized";
+
+   if (!CrosLibrary::Get()->EnsureLoaded())
+     return false;
+   input_method_status_connection_ = chromeos::MonitorInputMethodStatus(
+       this,
+       &InputMethodChangedHandler,
+       &RegisterPropertiesHandler,
+       &UpdatePropertyHandler,
+       &ConnectionChangeHandler);
+   if (!input_method_status_connection_)
+     return false;
+
+   initialized_successfully_ = true;
+   return true;
   }
 
-  void AddObserver(Observer* observer) {
+  virtual ~InputMethodLibraryImpl() {
+  }
+
+  virtual void AddObserver(Observer* observer) {
+    if (!observers_.size()) {
+      observer->FirstObserverIsAdded(this);
+    }
     observers_.AddObserver(observer);
   }
 
-  void RemoveObserver(Observer* observer) {
+  virtual void RemoveObserver(Observer* observer) {
     observers_.RemoveObserver(observer);
   }
 
-  InputMethodDescriptors* GetActiveInputMethods() {
-    chromeos::InputMethodDescriptors* result = NULL;
-    // The connection does not need to be alive, but it does need to be created.
-    if (EnsureLoadedAndStarted()) {
-      result = chromeos::GetActiveInputMethods(input_method_status_connection_);
+  virtual InputMethodDescriptors* GetActiveInputMethods() {
+    chromeos::InputMethodDescriptors* result =
+        new chromeos::InputMethodDescriptors;
+    // Build the active input method descriptors from the active input
+    // methods cache |active_input_method_ids_|.
+    for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
+      const std::string& input_method_id = active_input_method_ids_[i];
+      const InputMethodDescriptor* descriptor =
+          chromeos::input_method::GetInputMethodDescriptorFromId(
+              input_method_id);
+      if (descriptor) {
+        result->push_back(*descriptor);
+      } else {
+        LOG(ERROR) << "Descriptor is not found for: " << input_method_id;
+      }
     }
-    if (!result || result->empty()) {
-      result = CreateFallbackInputMethodDescriptors();
+    // This shouldn't happen as there should be at least one active input
+    // method, but just in case.
+    if (result->empty()) {
+      LOG(ERROR) << "No active input methods found.";
+      result->push_back(input_method::GetFallbackInputMethodDescriptor());
     }
     return result;
   }
 
-  size_t GetNumActiveInputMethods() {
+  virtual size_t GetNumActiveInputMethods() {
     scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
     return input_methods->size();
   }
 
-  InputMethodDescriptors* GetSupportedInputMethods() {
-    InputMethodDescriptors* result = NULL;
-    // The connection does not need to be alive, but it does need to be created.
-    if (EnsureLoadedAndStarted()) {
-      result = chromeos::GetSupportedInputMethods(
-          input_method_status_connection_);
+  virtual InputMethodDescriptors* GetSupportedInputMethods() {
+    if (!initialized_successfully_) {
+      // If initialization was failed, return the fallback input method,
+      // as this function is guaranteed to return at least one descriptor.
+      InputMethodDescriptors* result = new InputMethodDescriptors;
+      result->push_back(input_method::GetFallbackInputMethodDescriptor());
+      return result;
     }
-    if (!result || result->empty()) {
-      result = CreateFallbackInputMethodDescriptors();
-    }
-    return result;
+
+    // This never returns NULL.
+    return chromeos::GetSupportedInputMethodDescriptors();
   }
 
-  void ChangeInputMethod(const std::string& input_method_id) {
-    current_input_method_id_ = input_method_id;
-    if (EnsureLoadedAndStarted()) {
-      if (input_method_id != chromeos::GetHardwareKeyboardLayoutName()) {
-        StartInputMethodProcesses();
+  virtual void ChangeInputMethod(const std::string& input_method_id) {
+    // If the input method daemon is not running and the specified input
+    // method is a keyboard layout, switch the keyboard directly.
+    if (ibus_daemon_process_id_ == 0 &&
+        chromeos::input_method::IsKeyboardLayout(input_method_id)) {
+      // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
+      // comments at ChangeCurrentInputMethod() for details.
+      ChangeCurrentInputMethodFromId(input_method_id);
+    } else {
+      // Otherwise, start the input method daemon, and change the input
+      // method via the damon.
+      StartInputMethodDaemon();
+      // ChangeInputMethodViaIBus() fails if the IBus daemon is not
+      // ready yet. In this case, we'll defer the input method change
+      // until the daemon is ready.
+      if (!ChangeInputMethodViaIBus(input_method_id)) {
+        pending_input_method_id_ = input_method_id;
       }
-      ChangeInputMethodInternal(input_method_id);
     }
   }
 
-  void SetImePropertyActivated(const std::string& key, bool activated) {
+  virtual void SetImePropertyActivated(const std::string& key,
+                                       bool activated) {
+    if (!initialized_successfully_)
+      return;
+
     DCHECK(!key.empty());
-    if (EnsureLoadedAndStarted()) {
-      chromeos::SetImePropertyActivated(
-          input_method_status_connection_, key.c_str(), activated);
-    }
+    chromeos::SetImePropertyActivated(
+        input_method_status_connection_, key.c_str(), activated);
   }
 
-  bool InputMethodIsActivated(const std::string& input_method_id) {
+  virtual bool InputMethodIsActivated(const std::string& input_method_id) {
     scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
         GetActiveInputMethods());
     for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
@@ -151,22 +205,24 @@
     return false;
   }
 
-  bool GetImeConfig(const std::string& section, const std::string& config_name,
-                    ImeConfigValue* out_value) {
-    bool success = false;
-    if (EnsureLoadedAndStarted()) {
-      success = chromeos::GetImeConfig(input_method_status_connection_,
-                                       section.c_str(),
-                                       config_name.c_str(),
-                                       out_value);
+  virtual bool SetImeConfig(const std::string& section,
+                            const std::string& config_name,
+                            const ImeConfigValue& value) {
+    // If the config change is for preload engines, update the active
+    // input methods cache |active_input_method_ids_| here. We need to
+    // update the cache before actually flushing the config. since we need
+    // to return active input methods from GetActiveInputMethods() before
+    // the input method daemon starts. For instance, we need to show the
+    // list of available input methods (keyboard layouts) on the login
+    // screen before the input method starts.
+    if (section == language_prefs::kGeneralSectionName &&
+        config_name == language_prefs::kPreloadEnginesConfigName &&
+        value.type == ImeConfigValue::kValueTypeStringList) {
+      active_input_method_ids_ = value.string_list_value;
     }
-    return success;
-  }
 
-  bool SetImeConfig(const std::string& section, const std::string& config_name,
-                    const ImeConfigValue& value) {
     // Before calling FlushImeConfig(), start input method process if necessary.
-    MaybeStartInputMethodProcesses(section, config_name, value);
+    MaybeStartInputMethodDaemon(section, config_name, value);
 
     const ConfigKeyType key = std::make_pair(section, config_name);
     current_config_values_[key] = value;
@@ -176,13 +232,16 @@
     }
 
     // Stop input method process if necessary.
-    MaybeStopInputMethodProcesses(section, config_name, value);
+    MaybeStopInputMethodDaemon(section, config_name, value);
+    // Change the current keyboard layout if necessary.
+    MaybeChangeCurrentKeyboardLayout(section, config_name, value);
     return pending_config_requests_.empty();
   }
 
   virtual const InputMethodDescriptor& previous_input_method() const {
     return previous_input_method_;
   }
+
   virtual const InputMethodDescriptor& current_input_method() const {
     return current_input_method_;
   }
@@ -191,65 +250,92 @@
     return current_ime_properties_;
   }
 
+  virtual std::string GetKeyboardOverlayId(const std::string& input_method_id) {
+    if (!initialized_successfully_)
+      return "";
+
+    return chromeos::GetKeyboardOverlayId(input_method_id);
+  }
+
  private:
-  // Starts input method processes based on the |defer_ime_startup_| flag and
+  // Returns true if the given input method config value is a single
+  // element string list that contains an input method ID of a keyboard
+  // layout.
+  bool ContainOnlyOneKeyboardLayout(
+      const ImeConfigValue& value) {
+    return (value.type == ImeConfigValue::kValueTypeStringList &&
+            value.string_list_value.size() == 1 &&
+            chromeos::input_method::IsKeyboardLayout(
+                value.string_list_value[0]));
+  }
+
+  // Starts input method daemon based on the |defer_ime_startup_| flag and
   // input method configuration being updated. |section| is a section name of
   // the input method configuration (e.g. "general", "general/hotkey").
   // |config_name| is a name of the configuration (e.g. "preload_engines",
   // "previous_engine"). |value| is the configuration value to be set.
-  void MaybeStartInputMethodProcesses(const std::string& section,
-                                      const std::string& config_name,
-                                      const ImeConfigValue& value) {
+  void MaybeStartInputMethodDaemon(const std::string& section,
+                                   const std::string& config_name,
+                                   const ImeConfigValue& value) {
     if (section == language_prefs::kGeneralSectionName &&
         config_name == language_prefs::kPreloadEnginesConfigName) {
-      if (EnsureLoadedAndStarted()) {
-        const std::string hardware_layout_name =
-            chromeos::GetHardwareKeyboardLayoutName();  // e.g. "xkb:us::eng"
-        if (!(value.type == ImeConfigValue::kValueTypeStringList &&
-              value.string_list_value.size() == 1 &&
-              value.string_list_value[0] == hardware_layout_name) &&
-            !defer_ime_startup_) {
-          // If there are no input methods other than one for the hardware
-          // keyboard, we don't start the input method processes.
-          // When |defer_ime_startup_| is true, we don't start it either.
-          StartInputMethodProcesses();
-        }
-        chromeos::SetActiveInputMethods(input_method_status_connection_, value);
+      // If there is only one input method which is a keyboard layout,
+      // we don't start the input method processes.  When
+      // |defer_ime_startup_| is true, we don't start it either.
+      if (ContainOnlyOneKeyboardLayout(value) ||
+          defer_ime_startup_) {
+        // Do not start the input method daemon.
+      } else {
+        // Otherwise, start the input method daemon.
+        StartInputMethodDaemon();
       }
     }
   }
 
-  // Stops input method processes based on the |enable_auto_ime_shutdown_| flag
+  // Stops input method daemon based on the |enable_auto_ime_shutdown_| flag
   // and input method configuration being updated.
-  // See also: MaybeStartInputMethodProcesses().
-  void MaybeStopInputMethodProcesses(const std::string& section,
-                                     const std::string& config_name,
-                                     const ImeConfigValue& value) {
+  // See also: MaybeStartInputMethodDaemon().
+  void MaybeStopInputMethodDaemon(const std::string& section,
+                                  const std::string& config_name,
+                                  const ImeConfigValue& value) {
+    // If there is only one input method which is a keyboard layout,
+    // and |enable_auto_ime_shutdown_| is true, we'll stop the input
+    // method daemon.
     if (section == language_prefs::kGeneralSectionName &&
-        config_name == language_prefs::kPreloadEnginesConfigName) {
-      if (EnsureLoadedAndStarted()) {
-        const std::string hardware_layout_name =
-            chromeos::GetHardwareKeyboardLayoutName();  // e.g. "xkb:us::eng"
-        if (value.type == ImeConfigValue::kValueTypeStringList &&
-            value.string_list_value.size() == 1 &&
-            value.string_list_value[0] == hardware_layout_name &&
-            enable_auto_ime_shutdown_) {
-          // If there are no input methods other than one for the hardware
-          // keyboard, and |enable_auto_ime_shutdown_| is true, we'll stop the
-          // input method processes.
-          StopInputMethodProcesses();
-        }
-        chromeos::SetActiveInputMethods(input_method_status_connection_, value);
-      }
+        config_name == language_prefs::kPreloadEnginesConfigName &&
+        ContainOnlyOneKeyboardLayout(value) &&
+        enable_auto_ime_shutdown_) {
+      StopInputMethodDaemon();
     }
   }
 
-  // Changes the current input method to |input_method_id|. If the id is not in
-  // the preload_engine list, this function changes the current method to the
-  // first preloaded engine. Returns true if the current engine is switched to
-  // |input_method_id| or the first one.
-  bool ChangeInputMethodInternal(const std::string& input_method_id) {
-    DCHECK(EnsureLoadedAndStarted());
+  // Change the keyboard layout per input method configuration being
+  // updated, if necessary. See also: MaybeStartInputMethodDaemon().
+  void MaybeChangeCurrentKeyboardLayout(const std::string& section,
+                                        const std::string& config_name,
+                                        const ImeConfigValue& value) {
+
+    // If there is only one input method which is a keyboard layout, we'll
+    // change the keyboard layout per the only one input method now
+    // available.
+    if (section == language_prefs::kGeneralSectionName &&
+        config_name == language_prefs::kPreloadEnginesConfigName &&
+        ContainOnlyOneKeyboardLayout(value)) {
+      // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
+      // comments at ChangeCurrentInputMethod() for details.
+      ChangeCurrentInputMethodFromId(value.string_list_value[0]);
+    }
+  }
+
+  // Changes the current input method to |input_method_id| via IBus
+  // daemon. If the id is not in the preload_engine list, this function
+  // changes the current method to the first preloaded engine. Returns
+  // true if the current engine is switched to |input_method_id| or the
+  // first one.
+  bool ChangeInputMethodViaIBus(const std::string& input_method_id) {
+    if (!initialized_successfully_)
+      return false;
+
     std::string input_method_id_to_switch = input_method_id;
 
     if (!InputMethodIsActivated(input_method_id)) {
@@ -272,7 +358,7 @@
       return true;
     }
 
-    // Not reached.
+    // ChangeInputMethod() fails if the IBus daemon is not yet ready.
     LOG(ERROR) << "Can't switch input method to " << input_method_id_to_switch;
     return false;
   }
@@ -283,38 +369,41 @@
   // backend starts, we use a timer to periodically attempt to send the
   // config data to the config backend.
   void FlushImeConfig() {
+    if (!initialized_successfully_)
+      return;
+
     bool active_input_methods_are_changed = false;
-    if (EnsureLoadedAndStarted()) {
-      InputMethodConfigRequests::iterator iter =
-          pending_config_requests_.begin();
-      while (iter != pending_config_requests_.end()) {
-        const std::string& section = iter->first.first;
-        const std::string& config_name = iter->first.second;
-        const ImeConfigValue& value = iter->second;
-        if (chromeos::SetImeConfig(input_method_status_connection_,
-                                   section.c_str(),
-                                   config_name.c_str(),
-                                   value)) {
-          // Check if it's a change in active input methods.
-          if (config_name == language_prefs::kPreloadEnginesConfigName) {
-            active_input_methods_are_changed = true;
-          }
-          // Successfully sent. Remove the command and proceed to the next one.
-          pending_config_requests_.erase(iter++);
-        } else {
-          // If SetImeConfig() fails, subsequent calls will likely fail.
-          break;
-        }
-      }
-      if (pending_config_requests_.empty()) {
-        // Calls to ChangeInputMethod() will fail if the input method has not
-        // yet been added to preload_engines.  As such, the call is deferred
-        // until after all config values have been sent to the IME process.
-        if (should_change_input_method_) {
-          ChangeInputMethodInternal(current_input_method_id_);
-          should_change_input_method_ = false;
+    InputMethodConfigRequests::iterator iter =
+        pending_config_requests_.begin();
+    while (iter != pending_config_requests_.end()) {
+      const std::string& section = iter->first.first;
+      const std::string& config_name = iter->first.second;
+      const ImeConfigValue& value = iter->second;
+      if (chromeos::SetImeConfig(input_method_status_connection_,
+                                 section.c_str(),
+                                 config_name.c_str(),
+                                 value)) {
+        // Check if it's a change in active input methods.
+        if (config_name == language_prefs::kPreloadEnginesConfigName) {
           active_input_methods_are_changed = true;
+          VLOG(1) << "Updated preload_engines: " << value.ToString();
         }
+        // Successfully sent. Remove the command and proceed to the next one.
+        pending_config_requests_.erase(iter++);
+      } else {
+        // If SetImeConfig() fails, subsequent calls will likely fail.
+        break;
+      }
+    }
+    if (pending_config_requests_.empty()) {
+      // Calls to ChangeInputMethod() will fail if the input method has not
+      // yet been added to preload_engines.  As such, the call is deferred
+      // until after all config values have been sent to the IME process.
+      if (should_change_input_method_ && !pending_input_method_id_.empty()) {
+        ChangeInputMethodViaIBus(pending_input_method_id_);
+        pending_input_method_id_ = "";
+        should_change_input_method_ = false;
+        active_input_methods_are_changed = true;
       }
     }
 
@@ -342,23 +431,28 @@
     //    that ibus-daemon could send a DBus signal since the daemon is killed
     //    right after this FlushImeConfig() call.
     if (active_input_methods_are_changed) {
-      scoped_ptr<InputMethodDescriptor> current_input_method(
-          chromeos::GetCurrentInputMethod(input_method_status_connection_));
-      // The |current_input_method_| member variable should not be used since
-      // the variable might be stale. SetImeConfig("preload_engine") call above
-      // might change the current input method in ibus-daemon, but the variable
-      // is not updated until InputMethodChangedHandler(), which is the handler
-      // for the global-engine-changed DBus signal, is called.
+      // The |current_input_method_| member might be stale here as
+      // SetImeConfig("preload_engine") call above might change the
+      // current input method in ibus-daemon (ex. this occurs when the
+      // input method currently in use is removed from the options
+      // page). However, it should be safe to use the member here,
+      // for the following reasons:
+      // 1. If ibus-daemon is to be killed, we'll switch to the only one
+      //    keyboard layout, and observers are notified. See
+      //    MaybeStopInputMethodDaemon() for details.
+      // 2. Otherwise, "global-engine-changed" signal is delivered from
+      //    ibus-daemon, and observers are notified. See
+      //    InputMethodChangedHandler() for details.
       const size_t num_active_input_methods = GetNumActiveInputMethods();
-      if (current_input_method.get()) {
-        FOR_EACH_OBSERVER(Observer, observers_,
-                          ActiveInputMethodsChanged(this,
-                                                    *current_input_method.get(),
-                                                    num_active_input_methods));
-      }
+      FOR_EACH_OBSERVER(Observer, observers_,
+                        ActiveInputMethodsChanged(this,
+                                                  current_input_method_,
+                                                  num_active_input_methods));
     }
   }
 
+  // Called when the input method is changed in the IBus daemon
+  // (ex. "global-engine-changed" is delivered from the IBus daemon).
   static void InputMethodChangedHandler(
       void* object,
       const chromeos::InputMethodDescriptor& current_input_method) {
@@ -376,6 +470,7 @@
     input_method_library->ChangeCurrentInputMethod(current_input_method);
   }
 
+  // Called when properties are registered in the IBus daemon.
   static void RegisterPropertiesHandler(
       void* object, const ImePropertyList& prop_list) {
     // See comments in InputMethodChangedHandler.
@@ -389,6 +484,7 @@
     input_method_library->RegisterProperties(prop_list);
   }
 
+  // Called when properties are updated in the IBus daemon.
   static void UpdatePropertyHandler(
       void* object, const ImePropertyList& prop_list) {
     // See comments in InputMethodChangedHandler.
@@ -402,6 +498,7 @@
     input_method_library->UpdateProperty(prop_list);
   }
 
+  // Called when connection to IBus is established or terminated.
   static void ConnectionChangeHandler(void* object, bool connected) {
     // See comments in InputMethodChangedHandler.
     if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -425,62 +522,74 @@
     }
   }
 
-  bool EnsureStarted() {
-    if (!input_method_status_connection_) {
-      input_method_status_connection_ = chromeos::MonitorInputMethodStatus(
-          this,
-          &InputMethodChangedHandler,
-          &RegisterPropertiesHandler,
-          &UpdatePropertyHandler,
-          &ConnectionChangeHandler);
-    }
-    return true;
-  }
-
-  bool EnsureLoadedAndStarted() {
-    return CrosLibrary::Get()->EnsureLoaded() &&
-           EnsureStarted();
-  }
-
+  // Changes the current input method from the given input method
+  // descriptor.  This function updates states like current_input_method_
+  // and notifies observers about the change (that will update the
+  // preferences), hence this function should always be used even if you
+  // just need to change the current keyboard layout.
   void ChangeCurrentInputMethod(const InputMethodDescriptor& new_input_method) {
-    // Change the keyboard layout to a preferred layout for the input method.
-    CrosLibrary::Get()->GetKeyboardLibrary()->SetCurrentKeyboardLayoutByName(
-        new_input_method.keyboard_layout);
-
     if (current_input_method_.id != new_input_method.id) {
       previous_input_method_ = current_input_method_;
       current_input_method_ = new_input_method;
+
+      // Change the keyboard layout to a preferred layout for the input method.
+      if (!CrosLibrary::Get()->GetKeyboardLibrary()->
+          SetCurrentKeyboardLayoutByName(
+              current_input_method_.keyboard_layout)) {
+        LOG(ERROR) << "Failed to change keyboard layout to "
+                   << current_input_method_.keyboard_layout;
+      }
+
+      // Ask the first observer to update preferences. We should not ask every
+      // observer to do so. Otherwise, we'll end up updating preferences many
+      // times when many observers are attached (ex. many windows are opened),
+      // which is unnecessary and expensive.
+      ObserverListBase<Observer>::Iterator it(observers_);
+      Observer* first_observer = it.GetNext();
+      if (first_observer) {
+        first_observer->PreferenceUpdateNeeded(this,
+                                               previous_input_method_,
+                                               current_input_method_);
+      }
     }
+
+    // Update input method indicators (e.g. "US", "DV") in Chrome windows.
+    // For now, we have to do this every time to keep indicators updated. See
+    // comments near the FOR_EACH_OBSERVER call in FlushImeConfig() for details.
     const size_t num_active_input_methods = GetNumActiveInputMethods();
     FOR_EACH_OBSERVER(Observer, observers_,
                       InputMethodChanged(this,
-                                         previous_input_method_,
                                          current_input_method_,
                                          num_active_input_methods));
+  }
 
-    // Ask the first observer to update preferences. We should not ask every
-    // observer to do so. Otherwise, we'll end up updating preferences many
-    // times when many observers are attached (ex. many windows are opened),
-    // which is unnecessary and expensive.
-    ObserverListBase<Observer>::Iterator it(observers_);
-    Observer* first_observer = it.GetNext();
-    if (first_observer) {
-      first_observer->PreferenceUpdateNeeded(this,
-                                             previous_input_method_,
-                                             current_input_method_);
+  // Changes the current input method from the given input method ID.
+  // This function is just a wrapper of ChangeCurrentInputMethod().
+  void ChangeCurrentInputMethodFromId(const std::string& input_method_id) {
+    const chromeos::InputMethodDescriptor* descriptor =
+        chromeos::input_method::GetInputMethodDescriptorFromId(
+            input_method_id);
+    if (descriptor) {
+      ChangeCurrentInputMethod(*descriptor);
+    } else {
+      LOG(ERROR) << "Descriptor is not found for: " << input_method_id;
     }
   }
 
+  // Registers the properties used by the current input method.
   void RegisterProperties(const ImePropertyList& prop_list) {
     // |prop_list| might be empty. This means "clear all properties."
     current_ime_properties_ = prop_list;
   }
 
-  void StartInputMethodProcesses() {
+  // Starts the input method daemon. Unlike MaybeStopInputMethodDaemon(),
+  // this function always starts the daemon.
+  void StartInputMethodDaemon() {
     should_launch_ime_ = true;
-    MaybeLaunchInputMethodProcesses();
+    MaybeLaunchInputMethodDaemon();
   }
 
+  // Updates the properties used by the current input method.
   void UpdateProperty(const ImePropertyList& prop_list) {
     for (size_t i = 0; i < prop_list.size(); ++i) {
       FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
@@ -520,71 +629,71 @@
                       this);
 
     *process_id = pid;
+    VLOG(1) << command_line << " (PID=" << pid << ") is started";
     return  true;
   }
 
-  // Launches input method processes if these are not yet running.
-  void MaybeLaunchInputMethodProcesses() {
+  // Launches input method daemon if these are not yet running.
+  void MaybeLaunchInputMethodDaemon() {
+    // CandidateWindowController requires libcros to be loaded. Besides,
+    // launching ibus-daemon without libcros loaded doesn't make sense.
+    if (!initialized_successfully_)
+      return;
+
     if (!should_launch_ime_) {
       return;
     }
 
+    if (!candidate_window_controller_.get()) {
+      candidate_window_controller_.reset(new CandidateWindowController);
+      if (!candidate_window_controller_->Init()) {
+        LOG(WARNING) << "Failed to initialize the candidate window controller";
+      }
+    }
+
     if (ibus_daemon_process_id_ == 0) {
       // TODO(zork): Send output to /var/log/ibus.log
       const std::string ibus_daemon_command_line =
           StringPrintf("%s --panel=disable --cache=none --restart --replace",
                        kIBusDaemonPath);
-      if (!LaunchInputMethodProcess(ibus_daemon_command_line,
-                                    &ibus_daemon_process_id_)) {
-        // On failure, we should not attempt to launch candidate_window.
-        return;
-      }
-    }
-
-    if (candidate_window_process_id_ == 0) {
-      // Pass the UI language info to candidate_window via --lang flag.
-      const std::string candidate_window_command_line =
-          StringPrintf("%s --lang=%s", kCandidateWindowPath,
-                       g_browser_process->GetApplicationLocale().c_str());
-      if (!LaunchInputMethodProcess(candidate_window_command_line,
-                                    &candidate_window_process_id_)) {
-        // Return here just in case we add more code below.
-        return;
+      if (!LaunchInputMethodProcess(
+              ibus_daemon_command_line, &ibus_daemon_process_id_)) {
+        LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line;
       }
     }
   }
 
+  // Called when the input method process is shut down.
   static void OnImeShutdown(int pid,
                             int status,
                             InputMethodLibraryImpl* library) {
     g_spawn_close_pid(pid);
     if (library->ibus_daemon_process_id_ == pid) {
       library->ibus_daemon_process_id_ = 0;
-    } else if (library->candidate_window_process_id_ == pid) {
-      library->candidate_window_process_id_ = 0;
     }
 
-    // Restart input method processes if needed.
-    library->MaybeLaunchInputMethodProcesses();
+    // Restart input method daemon if needed.
+    library->MaybeLaunchInputMethodDaemon();
   }
 
-  void StopInputMethodProcesses() {
+  // Stops the backend input method daemon. This function should also be
+  // called from MaybeStopInputMethodDaemon(), except one case where we
+  // stop the input method daemon at Chrome shutdown in Observe().
+  void StopInputMethodDaemon() {
+    if (!initialized_successfully_)
+      return;
+
     should_launch_ime_ = false;
     if (ibus_daemon_process_id_) {
-      const std::string xkb_engine_name =
-          chromeos::GetHardwareKeyboardLayoutName();
-      // We should not use chromeos::ChangeInputMethod() here since without the
-      // ibus-daemon process, ChangeCurrentInputMethod() callback function which
-      // actually changes the XKB layout will not be called.
-      CrosLibrary::Get()->GetKeyboardLibrary()->SetCurrentKeyboardLayoutByName(
-          chromeos::input_method::GetKeyboardLayoutName(xkb_engine_name));
-      kill(ibus_daemon_process_id_, SIGTERM);
+      if (!chromeos::StopInputMethodProcess(input_method_status_connection_)) {
+        LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to "
+                   << "PID " << ibus_daemon_process_id_;
+        kill(ibus_daemon_process_id_, SIGTERM);
+      }
+      VLOG(1) << "ibus-daemon (PID=" << ibus_daemon_process_id_ << ") is "
+              << "terminated";
       ibus_daemon_process_id_ = 0;
     }
-    if (candidate_window_process_id_) {
-      kill(candidate_window_process_id_, SIGTERM);
-      candidate_window_process_id_ = 0;
-    }
   }
 
   void SetDeferImeStartup(bool defer) {
@@ -600,9 +709,10 @@
   void Observe(NotificationType type,
                const NotificationSource& source,
                const NotificationDetails& details) {
-    // Stop the input processes on browser shutdown.
-    if (type.value == NotificationType::APP_EXITING) {
-      StopInputMethodProcesses();
+    // Stop the input method daemon on browser shutdown.
+    if (type.value == NotificationType::APP_TERMINATING) {
+      notification_registrar_.RemoveAll();
+      StopInputMethodDaemon();
     }
   }
 
@@ -639,75 +749,85 @@
   // This is used to register this object to APP_EXITING notification.
   NotificationRegistrar notification_registrar_;
 
-  // True if we should launch the input method processes.
+  // True if we should launch the input method daemon.
   bool should_launch_ime_;
   // True if the connection to the IBus daemon is alive.
   bool ime_connected_;
   // If true, we'll defer the startup until a non-default method is
   // activated.
   bool defer_ime_startup_;
-  // True if we should stop input method processes when there are no input
+  // True if we should stop input method daemon when there are no input
   // methods other than one for the hardware keyboard.
   bool enable_auto_ime_shutdown_;
-  // The ID of the current input method (ex. "mozc").
-  std::string current_input_method_id_;
-  // True if we should change the input method once the queue of the
-  // pending config requests becomes empty.
+  // The ID of the pending input method (ex. "mozc"). When we change the
+  // current input method via the IBus daemon, we use this variable to
+  // defer the operation until the IBus daemon becomes ready, as needed.
+  std::string pending_input_method_id_;
+  // True if we should change the current input method to
+  // |pending_input_method_id_| once the queue of the pending config
+  // requests becomes empty.
   bool should_change_input_method_;
 
   // The process id of the IBus daemon. 0 if it's not running. The process
   // ID 0 is not used in Linux, hence it's safe to use 0 for this purpose.
   int ibus_daemon_process_id_;
-  // The process id of the candidate window. 0 if it's not running.
-  int candidate_window_process_id_;
+
+  // True if initialization is successfully done, meaning that libcros is
+  // loaded and input method status monitoring is started. This value
+  // should be checked where we call libcros functions.
+  bool initialized_successfully_;
+
+  // The candidate window.
+  scoped_ptr<CandidateWindowController> candidate_window_controller_;
+
+  // The active input method ids cache.
+  std::vector<std::string> active_input_method_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodLibraryImpl);
 };
 
 InputMethodLibraryImpl::Observer::~Observer() {}
 
+// The stub implementation of InputMethodLibrary. Used for testing.
 class InputMethodLibraryStubImpl : public InputMethodLibrary {
  public:
   InputMethodLibraryStubImpl()
       : previous_input_method_("", "", "", ""),
-        current_input_method_("", "", "", "") {
+        current_input_method_("", "", "", ""),
+        keyboard_overlay_map_(
+            GetKeyboardOverlayMapForTesting()) {
+    current_input_method_ = input_method::GetFallbackInputMethodDescriptor();
   }
 
-  ~InputMethodLibraryStubImpl() {}
-  void AddObserver(Observer* observer) {}
-  void RemoveObserver(Observer* observer) {}
+  virtual ~InputMethodLibraryStubImpl() {}
+  virtual void AddObserver(Observer* observer) {}
+  virtual void RemoveObserver(Observer* observer) {}
 
-  InputMethodDescriptors* GetActiveInputMethods() {
-    return CreateRealisticInputMethodDescriptors();
+  virtual InputMethodDescriptors* GetActiveInputMethods() {
+    return GetInputMethodDescriptorsForTesting();
   }
 
 
-  size_t GetNumActiveInputMethods() {
-    scoped_ptr<InputMethodDescriptors> descriptors(
-        CreateRealisticInputMethodDescriptors());
+  virtual size_t GetNumActiveInputMethods() {
+    scoped_ptr<InputMethodDescriptors> descriptors(GetActiveInputMethods());
     return descriptors->size();
   }
 
-  InputMethodDescriptors* GetSupportedInputMethods() {
-    return CreateRealisticInputMethodDescriptors();
+  virtual InputMethodDescriptors* GetSupportedInputMethods() {
+    return GetInputMethodDescriptorsForTesting();
   }
 
-  void ChangeInputMethod(const std::string& input_method_id) {}
-  void SetImePropertyActivated(const std::string& key, bool activated) {}
+  virtual void ChangeInputMethod(const std::string& input_method_id) {}
+  virtual void SetImePropertyActivated(const std::string& key,
+                                       bool activated) {}
 
-  bool InputMethodIsActivated(const std::string& input_method_id) {
+  virtual bool InputMethodIsActivated(const std::string& input_method_id) {
     return true;
   }
 
-  bool GetImeConfig(const std::string& section,
-                    const std::string& config_name,
-                    ImeConfigValue* out_value) {
-    return false;
-  }
-
-  bool SetImeConfig(const std::string& section,
-                    const std::string& config_name,
-                    const ImeConfigValue& value) {
+  virtual bool SetImeConfig(const std::string& section,
+                            const std::string& config_name,
+                            const ImeConfigValue& value) {
     return false;
   }
 
@@ -723,15 +843,24 @@
     return current_ime_properties_;
   }
 
-  virtual void StartInputMethodProcesses() {}
-  virtual void StopInputMethodProcesses() {}
+  virtual void StartInputMethodDaemon() {}
+  virtual void StopInputMethodDaemon() {}
   virtual void SetDeferImeStartup(bool defer) {}
   virtual void SetEnableAutoImeShutdown(bool enable) {}
 
+  virtual std::string GetKeyboardOverlayId(const std::string& input_method_id) {
+    KeyboardOverlayMap::const_iterator iter =
+        keyboard_overlay_map_->find(input_method_id);
+    return (iter != keyboard_overlay_map_->end()) ?
+        iter->second : "";
+  }
+
  private:
-  // Creates realistic input method descriptors that can be used for
-  // testing Chrome OS version of chrome on regular Linux desktops.
-  InputMethodDescriptors* CreateRealisticInputMethodDescriptors() {
+  typedef std::map<std::string, std::string> KeyboardOverlayMap;
+
+  // Gets input method descriptors for testing. Shouldn't be used for
+  // production.
+  InputMethodDescriptors* GetInputMethodDescriptorsForTesting() {
     InputMethodDescriptors* descriptions = new InputMethodDescriptors;
     // The list is created from output of gen_engines.py in libcros.
     descriptions->push_back(InputMethodDescriptor(
@@ -779,6 +908,8 @@
     descriptions->push_back(InputMethodDescriptor(
         "xkb:us:dvorak:eng", "USA - Dvorak", "us(dvorak)", "eng"));
     descriptions->push_back(InputMethodDescriptor(
+        "xkb:us:colemak:eng", "USA - Colemak", "us(colemak)", "eng"));
+    descriptions->push_back(InputMethodDescriptor(
         "xkb:be::ger", "Belgium", "be", "ger"));
     descriptions->push_back(InputMethodDescriptor(
         "xkb:be::nld", "Belgium", "be", "nld"));
@@ -809,6 +940,8 @@
     descriptions->push_back(InputMethodDescriptor(
         "xkb:de::ger", "Germany", "de", "ger"));
     descriptions->push_back(InputMethodDescriptor(
+        "xkb:de:neo:ger", "Germany - Neo 2", "de(neo)", "ger"));
+    descriptions->push_back(InputMethodDescriptor(
         "xkb:gr::gre", "Greece", "gr", "gre"));
     descriptions->push_back(InputMethodDescriptor(
         "xkb:hu::hun", "Hungary", "hu", "hun"));
@@ -857,19 +990,100 @@
     return descriptions;
   }
 
+  // Gets keyboard overlay map for testing. Shouldn't be used for
+  // production.
+  std::map<std::string, std::string>* GetKeyboardOverlayMapForTesting() {
+    KeyboardOverlayMap* keyboard_overlay_map =
+        new KeyboardOverlayMap;
+    (*keyboard_overlay_map)["xkb:nl::nld"] = "nl";
+    (*keyboard_overlay_map)["xkb:be::nld"] = "nl";
+    (*keyboard_overlay_map)["xkb:fr::fra"] = "fr";
+    (*keyboard_overlay_map)["xkb:be::fra"] = "fr";
+    (*keyboard_overlay_map)["xkb:ca::fra"] = "fr_CA";
+    (*keyboard_overlay_map)["xkb:ch:fr:fra"] = "fr";
+    (*keyboard_overlay_map)["xkb:de::ger"] = "de";
+    (*keyboard_overlay_map)["xkb:be::ger"] = "de";
+    (*keyboard_overlay_map)["xkb:ch::ger"] = "de";
+    (*keyboard_overlay_map)["mozc"] = "en_US";
+    (*keyboard_overlay_map)["mozc-jp"] = "ja";
+    (*keyboard_overlay_map)["mozc-dv"] = "en_US_dvorak";
+    (*keyboard_overlay_map)["xkb:jp::jpn"] = "ja";
+    (*keyboard_overlay_map)["xkb:ru::rus"] = "ru";
+    (*keyboard_overlay_map)["xkb:ru:phonetic:rus"] = "ru";
+    (*keyboard_overlay_map)["m17n:th:kesmanee"] = "th";
+    (*keyboard_overlay_map)["m17n:th:pattachote"] = "th";
+    (*keyboard_overlay_map)["m17n:th:tis820"] = "th";
+    (*keyboard_overlay_map)["chewing"] = "zh_TW";
+    (*keyboard_overlay_map)["m17n:zh:cangjie"] = "zh_TW";
+    (*keyboard_overlay_map)["m17n:zh:quick"] = "zh_TW";
+    (*keyboard_overlay_map)["m17n:vi:tcvn"] = "vi";
+    (*keyboard_overlay_map)["m17n:vi:telex"] = "vi";
+    (*keyboard_overlay_map)["m17n:vi:viqr"] = "vi";
+    (*keyboard_overlay_map)["m17n:vi:vni"] = "vi";
+    (*keyboard_overlay_map)["xkb:us::eng"] = "en_US";
+    (*keyboard_overlay_map)["xkb:us:intl:eng"] = "en_US";
+    (*keyboard_overlay_map)["xkb:us:altgr-intl:eng"] = "en_US";
+    (*keyboard_overlay_map)["xkb:us:dvorak:eng"] =
+        "en_US_dvorak";
+    (*keyboard_overlay_map)["xkb:us:colemak:eng"] =
+        "en_US";
+    (*keyboard_overlay_map)["hangul"] = "ko";
+    (*keyboard_overlay_map)["pinyin"] = "zh_CN";
+    (*keyboard_overlay_map)["m17n:ar:kbd"] = "ar";
+    (*keyboard_overlay_map)["m17n:hi:itrans"] = "hi";
+    (*keyboard_overlay_map)["m17n:fa:isiri"] = "ar";
+    (*keyboard_overlay_map)["xkb:br::por"] = "pt_BR";
+    (*keyboard_overlay_map)["xkb:bg::bul"] = "bg";
+    (*keyboard_overlay_map)["xkb:bg:phonetic:bul"] = "bg";
+    (*keyboard_overlay_map)["xkb:ca:eng:eng"] = "ca";
+    (*keyboard_overlay_map)["xkb:cz::cze"] = "cs";
+    (*keyboard_overlay_map)["xkb:ee::est"] = "et";
+    (*keyboard_overlay_map)["xkb:es::spa"] = "es";
+    (*keyboard_overlay_map)["xkb:es:cat:cat"] = "ca";
+    (*keyboard_overlay_map)["xkb:dk::dan"] = "da";
+    (*keyboard_overlay_map)["xkb:gr::gre"] = "el";
+    (*keyboard_overlay_map)["xkb:il::heb"] = "iw";
+    (*keyboard_overlay_map)["xkb:kr:kr104:kor"] = "ko";
+    (*keyboard_overlay_map)["xkb:latam::spa"] = "es_419";
+    (*keyboard_overlay_map)["xkb:lt::lit"] = "lt";
+    (*keyboard_overlay_map)["xkb:lv:apostrophe:lav"] = "lv";
+    (*keyboard_overlay_map)["xkb:hr::scr"] = "hr";
+    (*keyboard_overlay_map)["xkb:gb:extd:eng"] = "en_GB";
+    (*keyboard_overlay_map)["xkb:fi::fin"] = "fi";
+    (*keyboard_overlay_map)["xkb:hu::hun"] = "hu";
+    (*keyboard_overlay_map)["xkb:it::ita"] = "it";
+    (*keyboard_overlay_map)["xkb:no::nob"] = "no";
+    (*keyboard_overlay_map)["xkb:pl::pol"] = "pl";
+    (*keyboard_overlay_map)["xkb:pt::por"] = "pt_PT";
+    (*keyboard_overlay_map)["xkb:ro::rum"] = "ro";
+    (*keyboard_overlay_map)["xkb:se::swe"] = "sv";
+    (*keyboard_overlay_map)["xkb:sk::slo"] = "sk";
+    (*keyboard_overlay_map)["xkb:si::slv"] = "sl";
+    (*keyboard_overlay_map)["xkb:rs::srp"] = "sr";
+    (*keyboard_overlay_map)["xkb:tr::tur"] = "tr";
+    (*keyboard_overlay_map)["xkb:ua::ukr"] = "uk";
+    return keyboard_overlay_map;
+  }
+
   InputMethodDescriptor previous_input_method_;
   InputMethodDescriptor current_input_method_;
   ImePropertyList current_ime_properties_;
+  scoped_ptr<KeyboardOverlayMap> keyboard_overlay_map_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodLibraryStubImpl);
 };
 
 // static
 InputMethodLibrary* InputMethodLibrary::GetImpl(bool stub) {
-  if (stub)
+  if (stub) {
     return new InputMethodLibraryStubImpl();
-  else
-    return new InputMethodLibraryImpl();
+  } else {
+    InputMethodLibraryImpl* impl = new InputMethodLibraryImpl();
+    if (!impl->Init()) {
+      LOG(ERROR) << "Failed to initialize InputMethodLibraryImpl";
+    }
+    return impl;
+  }
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/input_method_library.h b/chrome/browser/chromeos/cros/input_method_library.h
index 0c62ead..da310db 100644
--- a/chrome/browser/chromeos/cros/input_method_library.h
+++ b/chrome/browser/chromeos/cros/input_method_library.h
@@ -28,7 +28,6 @@
     // Called when the current input method is changed.
     virtual void InputMethodChanged(
         InputMethodLibrary* obj,
-        const InputMethodDescriptor& previous_input_method,
         const InputMethodDescriptor& current_input_method,
         size_t num_active_input_methods) = 0;
 
@@ -43,6 +42,9 @@
         InputMethodLibrary* obj,
         const InputMethodDescriptor& previous_input_method,
         const InputMethodDescriptor& current_input_method) = 0;
+
+    // Called by AddObserver() when the first observer is added.
+    virtual void FirstObserverIsAdded(InputMethodLibrary* obj) = 0;
   };
   virtual ~InputMethodLibrary() {}
 
@@ -80,20 +82,12 @@
   // Returns true if the input method specified by |input_method_id| is active.
   virtual bool InputMethodIsActivated(const std::string& input_method_id) = 0;
 
-  // Get a configuration of ibus-daemon or IBus engines and stores it on
-  // |out_value|. Returns true if |out_value| is successfully updated.
-  // When you would like to retrieve 'panel/custom_font', |section| should
-  // be "panel", and |config_name| should be "custom_font".
-  virtual bool GetImeConfig(const std::string& section,
-                            const std::string& config_name,
-                            ImeConfigValue* out_value) = 0;
-
   // Updates a configuration of ibus-daemon or IBus engines with |value|.
   // Returns true if the configuration (and all pending configurations, if any)
   // are processed. If ibus-daemon is not running, this function just queues
   // the request and returns false.
-  // You can specify |section| and |config_name| arguments in the same way
-  // as GetImeConfig() above.
+  // When you would like to set 'panel/custom_font', |section| should
+  // be "panel", and |config_name| should be "custom_font".
   // Notice: This function might call the Observer::ActiveInputMethodsChanged()
   // callback function immediately, before returning from the SetImeConfig
   // function. See also http://crosbug.com/5217.
@@ -101,11 +95,16 @@
                             const std::string& config_name,
                             const ImeConfigValue& value) = 0;
 
-  // Sets the IME state to enabled, and launches its processes if needed.
-  virtual void StartInputMethodProcesses() = 0;
+  // Returns the keyboard overlay ID corresponding to |input_method_id|.
+  // Returns an empty string if there is no corresponding keyboard overlay ID.
+  virtual std::string GetKeyboardOverlayId(
+      const std::string& input_method_id) = 0;
 
-  // Disables the IME, and kills the processes if they are running.
-  virtual void StopInputMethodProcesses() = 0;
+  // Sets the IME state to enabled, and launches input method daemon if needed.
+  virtual void StartInputMethodDaemon() = 0;
+
+  // Disables the IME, and kills the daemon process if they are running.
+  virtual void StopInputMethodDaemon() = 0;
 
   // Controls whether the IME process is started when preload engines are
   // specificed, or defered until a non-default method is activated.
diff --git a/chrome/browser/chromeos/cros/keyboard_library.cc b/chrome/browser/chromeos/cros/keyboard_library.cc
index c762390..0e8df03 100644
--- a/chrome/browser/chromeos/cros/keyboard_library.cc
+++ b/chrome/browser/chromeos/cros/keyboard_library.cc
@@ -14,20 +14,6 @@
   KeyboardLibraryImpl() {}
   virtual ~KeyboardLibraryImpl() {}
 
-  std::string GetHardwareKeyboardLayoutName() const {
-    if (CrosLibrary::Get()->EnsureLoaded()) {
-      return chromeos::GetHardwareKeyboardLayoutName();
-    }
-    return "";
-  }
-
-  std::string GetCurrentKeyboardLayoutName() const {
-    if (CrosLibrary::Get()->EnsureLoaded()) {
-      return chromeos::GetCurrentKeyboardLayoutName();
-    }
-    return "";
-  }
-
   bool SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
     if (CrosLibrary::Get()->EnsureLoaded()) {
       return chromeos::SetCurrentKeyboardLayoutByName(layout_name);
@@ -42,20 +28,6 @@
     return false;
   }
 
-  bool GetKeyboardLayoutPerWindow(bool* is_per_window) const {
-    if (CrosLibrary::Get()->EnsureLoaded()) {
-      return chromeos::GetKeyboardLayoutPerWindow(is_per_window);
-    }
-    return false;
-  }
-
-  bool SetKeyboardLayoutPerWindow(bool is_per_window) {
-    if (CrosLibrary::Get()->EnsureLoaded()) {
-      return chromeos::SetKeyboardLayoutPerWindow(is_per_window);
-    }
-    return false;
-  }
-
   bool GetAutoRepeatEnabled(bool* enabled) const {
     if (CrosLibrary::Get()->EnsureLoaded()) {
       return chromeos::GetAutoRepeatEnabled(enabled);
@@ -93,14 +65,6 @@
   KeyboardLibraryStubImpl() {}
   virtual ~KeyboardLibraryStubImpl() {}
 
-  std::string GetHardwareKeyboardLayoutName() const {
-    return "xkb:us::eng";
-  }
-
-  std::string GetCurrentKeyboardLayoutName() const {
-    return "";
-  }
-
   bool SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
     return false;
   }
@@ -109,14 +73,6 @@
     return false;
   }
 
-  bool GetKeyboardLayoutPerWindow(bool* is_per_window) const {
-    return false;
-  }
-
-  bool SetKeyboardLayoutPerWindow(bool is_per_window) {
-    return false;
-  }
-
   bool GetAutoRepeatEnabled(bool* enabled) const {
     return false;
   }
diff --git a/chrome/browser/chromeos/cros/keyboard_library.h b/chrome/browser/chromeos/cros/keyboard_library.h
index d29f0e6..6a4f293 100644
--- a/chrome/browser/chromeos/cros/keyboard_library.h
+++ b/chrome/browser/chromeos/cros/keyboard_library.h
@@ -18,29 +18,15 @@
  public:
   virtual ~KeyboardLibrary() {}
 
-  // Returns the hardware layout name like "xkb:us::eng". On error, returns "".
-  virtual std::string GetHardwareKeyboardLayoutName() const = 0;
-
-  // Returns the current layout name like "us". On error, returns "".
-  virtual std::string GetCurrentKeyboardLayoutName() const = 0;
-
   // Sets the current keyboard layout to |layout_name|.  Returns true on
-  // success.
+  // success. |layout_name| should look like XKB layout like "us" and
+  // "us(dvorak)".
   virtual bool SetCurrentKeyboardLayoutByName(
       const std::string& layout_name) = 0;
 
   // Remaps modifier keys.  Returns true on success.
   virtual bool RemapModifierKeys(const ModifierMap& modifier_map) = 0;
 
-  // Gets whehter we have separate keyboard layout per window, or not. The
-  // result is stored in |is_per_window|.  Returns true on success.
-  virtual bool GetKeyboardLayoutPerWindow(bool* is_per_window) const = 0;
-
-  // Sets whether we have separate keyboard layout per window, or not. If false
-  // is given, the same keyboard layout will be shared for all applications.
-  // Returns true on success.
-  virtual bool SetKeyboardLayoutPerWindow(bool is_per_window) = 0;
-
   // Gets the current auto-repeat mode of the keyboard. The result is stored in
   // |enabled|. Returns true on success.
   virtual bool GetAutoRepeatEnabled(bool* enabled) const = 0;
diff --git a/chrome/browser/chromeos/cros/libcros_service_library.cc b/chrome/browser/chromeos/cros/libcros_service_library.cc
new file mode 100644
index 0000000..9e095b4
--- /dev/null
+++ b/chrome/browser/chromeos/cros/libcros_service_library.cc
@@ -0,0 +1,335 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/cros/libcros_service_library.h"
+
+#include "base/synchronization/lock.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "cros/chromeos_libcros_service.h"
+#include "net/base/net_errors.h"
+#include "net/proxy/proxy_service.h"
+
+namespace chromeos {
+
+class LibCrosServiceLibraryImpl : public LibCrosServiceLibrary {
+ public:
+  // Base class for all services of LibCrosService.
+  // Each subclass should declare DISABLE_RUNNABLE_METHOD_REFCOUNT to disable
+  // refcounting, which is okay since the subclass's object will exist as a
+  // scoped_ptr in Singleton LibCrosServiceLibraryImpl, guaranteeing that its
+  // lifetime is longer than that of any message loop.
+  class ServicingLibrary {
+   public:
+    explicit ServicingLibrary(LibCrosServiceConnection service_connection);
+    virtual ~ServicingLibrary();
+
+    // Clears service_connection_ (which is stored as weak pointer) so that it
+    // can't be used anymore.
+    virtual void ClearServiceConnection();
+
+   protected:
+    LibCrosServiceConnection service_connection_;  // Weak pointer.
+    // Lock for data members to synchronize access on multiple threads.
+    base::Lock data_lock_;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ServicingLibrary);
+  };
+
+  // Library that provides network proxy service for LibCrosService.
+  // For now, it only processes proxy resolution requests for ChromeOS clients.
+  class NetworkProxyLibrary : public ServicingLibrary {
+   public:
+    explicit NetworkProxyLibrary(LibCrosServiceConnection connection);
+    virtual ~NetworkProxyLibrary();
+
+    // Sets the ProxyService that will handle network proxy requests, e.g.
+    // proxy resolution for a url.
+    void SetHandler(net::ProxyService* handler);
+
+   private:
+    // Data being used in one proxy resolution.
+    class Request {
+     public:
+      explicit Request(const std::string& source_url);
+      virtual ~Request() {}
+
+      // Callback on IO thread for when net::ProxyService::ResolveProxy
+      // completes, synchronously or asynchronously.
+      void OnCompletion(int result);
+      net::CompletionCallbackImpl<Request> completion_callback_;
+
+      std::string source_url_;  // URL being resolved.
+      int result_;  // Result of proxy resolution.
+      net::ProxyInfo proxy_info_;  // ProxyInfo resolved for source_url_.
+      std::string error_;  // Error from proxy resolution.
+      Task* notify_task_;  // Task to notify of resolution result.
+
+     private:
+      DISALLOW_COPY_AND_ASSIGN(Request);
+    };
+
+    // Static callback passed to LibCrosService to be invoked when ChromeOS
+    // clients send network proxy resolution requests to the service running in
+    // chrome executable.  Called on UI thread from dbus request.
+    static void ResolveProxyHandler(void* object,
+                                    const char* source_url);
+
+    void ResolveProxy(const std::string& source_url);
+
+    // Wrapper on UI thread to call LibCrosService::NotifyNetworkProxyResolved.
+    void NotifyProxyResolved(Request* request);
+
+    // ProxyService to call ResolveProxy on.
+    scoped_refptr<net::ProxyService> proxy_service_;
+
+    std::vector<Request*> all_requests_;
+
+    DISALLOW_COPY_AND_ASSIGN(NetworkProxyLibrary);
+  };
+
+  LibCrosServiceLibraryImpl();
+  virtual ~LibCrosServiceLibraryImpl();
+
+  // LibCrosServiceLibrary implementation.
+  virtual void RegisterNetworkProxyHandler(net::ProxyService* handler);
+
+ private:
+  // Starts LibCrosService running on dbus if not already started.
+  bool StartService();
+
+  // Connection to LibCrosService.
+  LibCrosServiceConnection service_connection_;
+
+  // Libraries that form LibCrosService.
+  scoped_ptr<NetworkProxyLibrary> network_proxy_lib_;
+
+  DISALLOW_COPY_AND_ASSIGN(LibCrosServiceLibraryImpl);
+};
+
+//---------------- LibCrosServiceLibraryImpl: public ---------------------------
+
+LibCrosServiceLibraryImpl::LibCrosServiceLibraryImpl()
+    : service_connection_(NULL) {
+  if (!CrosLibrary::Get()->EnsureLoaded()) {
+    LOG(ERROR) << "Cros library has not been loaded.";
+  }
+}
+
+LibCrosServiceLibraryImpl::~LibCrosServiceLibraryImpl() {
+  if (service_connection_) {
+    // Clear service connections in servicing libraries which held the former
+    // as weak pointers.
+    if (network_proxy_lib_.get())
+      network_proxy_lib_->ClearServiceConnection();
+
+    StopLibCrosService(service_connection_);
+    VLOG(1) << "LibCrosService stopped.";
+    service_connection_ = NULL;
+  }
+}
+
+// Called on UI thread to register network proxy handler for LibCrosService.
+void LibCrosServiceLibraryImpl::RegisterNetworkProxyHandler(
+    net::ProxyService* handler) {
+  // Make sure we're running on UI thread.
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    scoped_refptr<net::ProxyService> ref_handler(handler);
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(this,
+            &LibCrosServiceLibraryImpl::RegisterNetworkProxyHandler,
+            ref_handler));
+    return;
+  }
+  if (StartService()) {
+    if (!network_proxy_lib_.get())
+      network_proxy_lib_.reset(new NetworkProxyLibrary(service_connection_));
+    network_proxy_lib_->SetHandler(handler);
+  }
+}
+
+//---------------- LibCrosServiceLibraryImpl: private --------------------------
+
+bool LibCrosServiceLibraryImpl::StartService() {
+  if (service_connection_)  // Service has already been started.
+    return true;
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  // Starts LibCrosService; the returned connection is used for future
+  // interactions with the service.
+  service_connection_ = StartLibCrosService();
+  if (service_connection_) {
+    VLOG(1) << "LibCrosService started.";
+    return true;
+  }
+  LOG(WARNING) << "Error starting LibCrosService";
+  return false;
+}
+
+//------------- LibCrosServiceLibraryImpl::ServicingLibrary: public ------------
+
+LibCrosServiceLibraryImpl::ServicingLibrary::ServicingLibrary(
+    LibCrosServiceConnection connection)
+    : service_connection_(connection) {
+}
+
+LibCrosServiceLibraryImpl::ServicingLibrary::~ServicingLibrary() {
+  ClearServiceConnection();
+}
+
+void LibCrosServiceLibraryImpl::ServicingLibrary::ClearServiceConnection() {
+  base::AutoLock lock(data_lock_);
+  service_connection_ = NULL;
+}
+
+//----------- LibCrosServiceLibraryImpl::NetworkProxyLibrary: public -----------
+
+LibCrosServiceLibraryImpl::NetworkProxyLibrary::NetworkProxyLibrary(
+    LibCrosServiceConnection connection)
+    : ServicingLibrary(connection) {
+  // Register callback for LibCrosService::ResolveNetworkProxy.
+  SetNetworkProxyResolver(&ResolveProxyHandler, this, service_connection_);
+}
+
+LibCrosServiceLibraryImpl::NetworkProxyLibrary::~NetworkProxyLibrary() {
+  base::AutoLock lock(data_lock_);
+  if (!all_requests_.empty()) {
+    for (size_t i = all_requests_.size() - 1;  i >= 0; --i) {
+      LOG(WARNING) << "Pending request for " << all_requests_[i]->source_url_;
+      delete all_requests_[i];
+    }
+    all_requests_.clear();
+  }
+}
+
+// Called on UI thread to register handler for LibCrosService's network proxy
+// requests.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::SetHandler(
+    net::ProxyService* handler) {
+  base::AutoLock lock(data_lock_);
+  DCHECK(service_connection_);
+  proxy_service_ = handler;
+}
+
+//----------- LibCrosServiceLibraryImpl::NetworkProxyLibrary: private ----------
+
+// Static, called on UI thread from LibCrosService::ResolveProxy via dbus.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::ResolveProxyHandler(
+    void* object, const char* source_url) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  NetworkProxyLibrary* lib = static_cast<NetworkProxyLibrary*>(object);
+  // source_url will be freed when this function returns, so make a copy of it.
+  std::string url(source_url);
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+      NewRunnableMethod(lib, &NetworkProxyLibrary::ResolveProxy, url));
+}
+
+// Called on IO thread as task posted from ResolveProxyHandler on UI thread.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::ResolveProxy(
+    const std::string& source_url) {
+  // Make sure we're running on IO thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  Request* request = new Request(source_url);
+  request->notify_task_ = NewRunnableMethod(this,
+      &NetworkProxyLibrary::NotifyProxyResolved, request);
+  {
+    base::AutoLock lock(data_lock_);
+    all_requests_.push_back(request);
+    if (!service_connection_)
+      request->error_ = "LibCrosService not started";
+    else if (!proxy_service_)
+      request->error_ = "Network proxy resolver not registered";
+  }
+  if (request->error_ != "") {
+    LOG(ERROR) << request->error_;
+    request->result_ = net::OK;  // Set to OK since error string is set.
+  } else {
+    VLOG(1) << "Starting networy proxy resolution for " << request->source_url_;
+    request->result_ = proxy_service_->ResolveProxy(
+        GURL(request->source_url_), &request->proxy_info_,
+        &request->completion_callback_, NULL, net::BoundNetLog());
+  }
+  if (request->result_ != net::ERR_IO_PENDING) {
+    VLOG(1) << "Network proxy resolution completed synchronously.";
+    request->OnCompletion(request->result_);
+  }
+}
+
+// Called on UI thread as task posted from Request::OnCompletion on IO thread.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::NotifyProxyResolved(
+    Request* request) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  base::AutoLock lock(data_lock_);
+  if (service_connection_) {
+    if (!NotifyNetworkProxyResolved(request->source_url_.c_str(),
+                                    request->proxy_info_.ToPacString().c_str(),
+                                    request->error_.c_str(),
+                                    service_connection_)) {
+      LOG(ERROR) << "LibCrosService has error with NotifyNetworkProxyResolved";
+    } else {
+      VLOG(1) << "LibCrosService has notified proxy resoloution for "
+              << request->source_url_;
+    }
+  }
+  std::vector<Request*>::iterator iter =
+      std::find(all_requests_.begin(), all_requests_.end(), request);
+  DCHECK(iter != all_requests_.end());
+  all_requests_.erase(iter);
+  delete request;
+}
+
+//---------- LibCrosServiceLibraryImpl::NetworkProxyLibrary::Request -----------
+
+LibCrosServiceLibraryImpl::NetworkProxyLibrary::Request::Request(
+    const std::string& source_url)
+    : ALLOW_THIS_IN_INITIALIZER_LIST(
+          completion_callback_(this, &Request::OnCompletion)),
+      source_url_(source_url),
+      result_(net::ERR_FAILED),
+      notify_task_(NULL) {
+}
+
+// Called on IO thread when net::ProxyService::ResolveProxy has completed.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::Request::OnCompletion(
+    int result) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  result_ = result;
+  if (result_ != net::OK)
+    error_ = net::ErrorToString(result_);
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, notify_task_);
+  notify_task_ = NULL;
+}
+
+//--------------------- LibCrosServiceLibraryStubImpl --------------------------
+
+class LibCrosServiceLibraryStubImpl : public LibCrosServiceLibrary {
+ public:
+  LibCrosServiceLibraryStubImpl() {}
+  virtual ~LibCrosServiceLibraryStubImpl() {}
+
+  // LibCrosServiceLibrary overrides.
+  virtual void RegisterNetworkProxyHandler(net::ProxyService* handler) {}
+
+  DISALLOW_COPY_AND_ASSIGN(LibCrosServiceLibraryStubImpl);
+};
+
+//--------------------------- LibCrosServiceLibrary ----------------------------
+
+// Static.
+LibCrosServiceLibrary* LibCrosServiceLibrary::GetImpl(bool stub) {
+  if (stub)
+    return new LibCrosServiceLibraryStubImpl();
+  return new LibCrosServiceLibraryImpl();
+}
+
+}  // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run, so are all its
+// scoped_ptred class members.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::LibCrosServiceLibraryImpl);
+DISABLE_RUNNABLE_METHOD_REFCOUNT(
+    chromeos::LibCrosServiceLibraryImpl::NetworkProxyLibrary);
+
diff --git a/chrome/browser/chromeos/cros/libcros_service_library.h b/chrome/browser/chromeos/cros/libcros_service_library.h
new file mode 100644
index 0000000..d90cf33
--- /dev/null
+++ b/chrome/browser/chromeos/cros/libcros_service_library.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_CROS_LIBCROS_SERVICE_LIBRARY_H_
+#define CHROME_BROWSER_CHROMEOS_CROS_LIBCROS_SERVICE_LIBRARY_H_
+#pragma once
+
+namespace net{
+class ProxyService;
+};
+
+namespace chromeos {
+
+class LibCrosServiceLibrary {
+ public:
+  virtual ~LibCrosServiceLibrary() {}
+
+  // Registers the ProxyService that will handle network proxy requests, e.g.
+  // proxy resolution for a url.
+  virtual void RegisterNetworkProxyHandler(net::ProxyService* handler) = 0;
+
+  // Factory function, creates a new instance and returns ownership.
+  // For normal usage, access the singleton via CrosLibrary::Get().
+  static LibCrosServiceLibrary* GetImpl(bool stub);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CROS_LIBCROS_SERVICE_LIBRARY_H_
diff --git a/chrome/browser/chromeos/cros/mock_input_method_library.h b/chrome/browser/chromeos/cros/mock_input_method_library.h
index dc4f3ac..bbff415 100644
--- a/chrome/browser/chromeos/cros/mock_input_method_library.h
+++ b/chrome/browser/chromeos/cros/mock_input_method_library.h
@@ -27,15 +27,14 @@
   MOCK_METHOD1(ChangeInputMethod, void(const std::string&));
   MOCK_METHOD2(SetImePropertyActivated, void(const std::string&, bool));
   MOCK_METHOD1(InputMethodIsActivated, bool(const std::string&));
-  MOCK_METHOD3(GetImeConfig, bool(const std::string&, const std::string&,
-                                  ImeConfigValue*));
   MOCK_METHOD3(SetImeConfig, bool(const std::string&, const std::string&,
                                   const ImeConfigValue&));
   MOCK_CONST_METHOD0(previous_input_method, const InputMethodDescriptor&(void));
   MOCK_CONST_METHOD0(current_input_method, const InputMethodDescriptor&(void));
   MOCK_CONST_METHOD0(current_ime_properties, const ImePropertyList&(void));
-  MOCK_METHOD0(StartInputMethodProcesses, void(void));
-  MOCK_METHOD0(StopInputMethodProcesses, void(void));
+  MOCK_METHOD1(GetKeyboardOverlayId, std::string(const std::string&));
+  MOCK_METHOD0(StartInputMethodDaemon, void(void));
+  MOCK_METHOD0(StopInputMethodDaemon, void(void));
   MOCK_METHOD1(SetDeferImeStartup, void(bool));
   MOCK_METHOD1(SetEnableAutoImeShutdown, void(bool));
 };
diff --git a/chrome/browser/chromeos/cros/mock_keyboard_library.h b/chrome/browser/chromeos/cros/mock_keyboard_library.h
index f36d74f..d0f3c3b 100644
--- a/chrome/browser/chromeos/cros/mock_keyboard_library.h
+++ b/chrome/browser/chromeos/cros/mock_keyboard_library.h
@@ -18,12 +18,8 @@
   MockKeyboardLibrary() {}
   virtual ~MockKeyboardLibrary() {}
 
-  MOCK_CONST_METHOD0(GetHardwareKeyboardLayoutName, std::string(void));
-  MOCK_CONST_METHOD0(GetCurrentKeyboardLayoutName, std::string(void));
   MOCK_METHOD1(SetCurrentKeyboardLayoutByName, bool(const std::string&));
   MOCK_METHOD1(RemapModifierKeys, bool(const ModifierMap&));
-  MOCK_CONST_METHOD1(GetKeyboardLayoutPerWindow, bool(bool*));
-  MOCK_METHOD1(SetKeyboardLayoutPerWindow, bool(bool));
   MOCK_CONST_METHOD1(GetAutoRepeatEnabled, bool(bool*));
   MOCK_METHOD1(SetAutoRepeatEnabled, bool(bool));
   MOCK_CONST_METHOD1(GetAutoRepeatRate, bool(AutoRepeatRate*));
diff --git a/chrome/browser/chromeos/cros/mock_network_library.h b/chrome/browser/chromeos/cros/mock_network_library.h
index 3b541aa..6195bd0 100644
--- a/chrome/browser/chromeos/cros/mock_network_library.h
+++ b/chrome/browser/chromeos/cros/mock_network_library.h
@@ -25,6 +25,9 @@
   MOCK_METHOD1(RemoveObserverForAllNetworks, void(NetworkObserver*));
   MOCK_METHOD1(AddCellularDataPlanObserver, void(CellularDataPlanObserver*));
   MOCK_METHOD1(RemoveCellularDataPlanObserver, void(CellularDataPlanObserver*));
+  MOCK_METHOD0(Lock, void(void));
+  MOCK_METHOD0(Unlock, void(void));
+  MOCK_METHOD0(IsLocked, bool(void));
   MOCK_CONST_METHOD0(ethernet_network, const EthernetNetwork*(void));
   MOCK_CONST_METHOD0(ethernet_connecting, bool(void));
   MOCK_CONST_METHOD0(ethernet_connected, bool(void));
@@ -62,6 +65,8 @@
                                           bool));
   MOCK_METHOD1(ConnectToCellularNetwork, bool(const CellularNetwork*));
   MOCK_METHOD1(RefreshCellularDataPlans, void(const CellularNetwork* network));
+  MOCK_METHOD0(SignalCellularPlanPayment, void(void));
+  MOCK_METHOD0(HasRecentCellularPlanPayment, bool(void));
 
   MOCK_METHOD1(DisconnectFromWirelessNetwork, void(const WirelessNetwork*));
   MOCK_METHOD1(SaveCellularNetwork, void(const CellularNetwork*));
diff --git a/chrome/browser/chromeos/cros/mount_library.cc b/chrome/browser/chromeos/cros/mount_library.cc
index 68bc53c..552ceaa 100644
--- a/chrome/browser/chromeos/cros/mount_library.cc
+++ b/chrome/browser/chromeos/cros/mount_library.cc
@@ -39,6 +39,10 @@
     return MountDevicePath(device_path);
   }
 
+  bool IsBootPath(const char* device_path) {
+    return IsBootDevicePath(device_path);
+  }
+
   const DiskVector& disks() const { return disks_; }
 
  private:
@@ -124,6 +128,7 @@
   virtual void RemoveObserver(Observer* observer) {}
   virtual const DiskVector& disks() const { return disks_; }
   virtual bool MountPath(const char* device_path) { return false; }
+  virtual bool IsBootPath(const char* device_path) { return true; }
 
  private:
   // The list of disks found.
diff --git a/chrome/browser/chromeos/cros/mount_library.h b/chrome/browser/chromeos/cros/mount_library.h
index 21b1dac..2b0fefe 100644
--- a/chrome/browser/chromeos/cros/mount_library.h
+++ b/chrome/browser/chromeos/cros/mount_library.h
@@ -49,6 +49,7 @@
 
   class Observer {
    public:
+    virtual ~Observer() {}
     virtual void MountChanged(MountLibrary* obj,
                               MountEventType evt,
                               const std::string& path) = 0;
@@ -59,6 +60,7 @@
   virtual void RemoveObserver(Observer* observer) = 0;
   virtual const DiskVector& disks() const = 0;
   virtual bool MountPath(const char* device_path) = 0;
+  virtual bool IsBootPath(const char* device_path) = 0;
 
   // Factory function, creates a new instance and returns ownership.
   // For normal usage, access the singleton via CrosLibrary::Get().
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index b99cb95..aca6d6b 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <map>
 
-#include "app/l10n_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/stl_util-inl.h"
 #include "base/string_number_conversions.h"
@@ -15,10 +14,12 @@
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/network_login_observer.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/common/time_format.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -84,6 +85,9 @@
 static const char* kRoamingStateRoaming = "roaming";
 static const char* kRoamingStateUnknown = "unknown";
 
+// How long we should remember that cellular plan payment was received.
+const int kRecentPlanPaymentHours = 6;
+
 static ConnectionState ParseState(const std::string& state) {
   if (state == kStateIdle)
     return STATE_IDLE;
@@ -163,7 +167,7 @@
   return ROAMING_STATE_UNKNOWN;
 }
 
-}
+}  // namespace
 
 // Helper function to wrap Html with <th> tag.
 static std::string WrapWithTH(std::string text) {
@@ -467,6 +471,17 @@
   return string16();
 }
 
+std::string CellularDataPlan::GetUniqueIdentifier() const {
+  // A cellular plan is uniquely described by the union of name, type,
+  // start time, end time, and max bytes.
+  // So we just return a union of all these variables.
+  return plan_name + "|" +
+      base::Int64ToString(plan_type) + "|" +
+      base::Int64ToString(plan_start_time.ToInternalValue()) + "|" +
+      base::Int64ToString(plan_end_time.ToInternalValue()) + "|" +
+      base::Int64ToString(plan_data_bytes);
+}
+
 base::TimeDelta CellularDataPlan::remaining_time() const {
   base::TimeDelta time = plan_end_time - base::Time::Now();
   return time.InMicroseconds() < 0 ? base::TimeDelta() : time;
@@ -611,7 +626,7 @@
     return DATA_NONE;
   const CellularDataPlan* plan = GetSignificantDataPlan();
   if (!plan)
-    return DATA_NORMAL;
+    return DATA_UNKNOWN;
   if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
     base::TimeDelta remaining = plan->remaining_time();
     if (remaining <= base::TimeDelta::FromSeconds(0))
@@ -620,6 +635,7 @@
       return DATA_VERY_LOW;
     if (remaining <= base::TimeDelta::FromSeconds(kCellularDataLowSecs))
       return DATA_LOW;
+    return DATA_NORMAL;
   } else if (plan->plan_type == CELLULAR_DATA_PLAN_METERED_PAID ||
              plan->plan_type == CELLULAR_DATA_PLAN_METERED_BASE) {
     int64 remaining = plan->remaining_data();
@@ -631,8 +647,9 @@
     if (remaining <= kCellularDataLowBytes &&
         plan->plan_type != CELLULAR_DATA_PLAN_METERED_BASE)
       return DATA_LOW;
+    return DATA_NORMAL;
   }
-  return DATA_NORMAL;
+  return DATA_UNKNOWN;
 }
 
 std::string CellularNetwork::GetNetworkTechnologyString() const {
@@ -838,6 +855,7 @@
         connected_devices_(0),
         wifi_scanning_(false),
         offline_mode_(false),
+        is_locked_(false),
         update_task_(NULL) {
     if (EnsureCrosLoaded()) {
       Init();
@@ -846,6 +864,7 @@
                                 this);
       data_plan_monitor_ = MonitorCellularDataPlan(&DataPlanUpdateHandler,
                                                    this);
+      network_login_observer_.reset(new NetworkLoginObserver(this));
     } else {
       InitTestData();
     }
@@ -868,8 +887,10 @@
   }
 
   void NetworkStatusChanged() {
+    DVLOG(1) << "Got NetworkStatusChanged";
     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     if (update_task_) {
+      DVLOG(1) << "  found previous task";
       update_task_->Cancel();
     }
     update_task_ =
@@ -935,6 +956,25 @@
     }
   }
 
+  virtual void Lock() {
+    if (is_locked_)
+      return;
+    is_locked_ = true;
+    NotifyNetworkManagerChanged();
+  }
+
+  virtual void Unlock() {
+    DCHECK(is_locked_);
+    if (!is_locked_)
+      return;
+    is_locked_ = false;
+    NotifyNetworkManagerChanged();
+  }
+
+  virtual bool IsLocked() {
+    return is_locked_;
+  }
+
   virtual void AddCellularDataPlanObserver(CellularDataPlanObserver* observer) {
     if (!data_plan_observers_.HasObserver(observer))
       data_plan_observers_.AddObserver(observer);
@@ -1135,6 +1175,18 @@
     RequestCellularDataPlanUpdate(network->service_path().c_str());
   }
 
+  // Records information that cellular play payment had happened.
+  virtual void SignalCellularPlanPayment() {
+    DCHECK(!HasRecentCellularPlanPayment());
+    cellular_plan_payment_time_ = base::Time::Now();
+  }
+
+  // Returns true if cellular plan payment had been recorded recently.
+  virtual bool HasRecentCellularPlanPayment() {
+    return (base::Time::Now() -
+              cellular_plan_payment_time_).InHours() < kRecentPlanPaymentHours;
+  }
+
   virtual void DisconnectFromWirelessNetwork(const WirelessNetwork* network) {
     DCHECK(network);
     if (!EnsureCrosLoaded() || !network)
@@ -1170,7 +1222,7 @@
         GetWirelessNetworkByPath(cellular_networks_,
                                  network->service_path());
     if (!cellular) {
-      LOG(WARNING) << "Save to unknown network: " << cellular->service_path();
+      LOG(WARNING) << "Save to unknown network: " << network->service_path();
       return;
     }
 
@@ -1188,7 +1240,7 @@
     WifiNetwork* wifi = GetWirelessNetworkByPath(wifi_networks_,
                                                  network->service_path());
     if (!wifi) {
-      LOG(WARNING) << "Save to unknown network: " << wifi->service_path();
+      LOG(WARNING) << "Save to unknown network: " << network->service_path();
       return;
     }
     // Immediately update properties in the cached structure.
@@ -1283,14 +1335,20 @@
   }
 
   virtual void EnableEthernetNetworkDevice(bool enable) {
+    if (is_locked_)
+      return;
     EnableNetworkDeviceType(TYPE_ETHERNET, enable);
   }
 
   virtual void EnableWifiNetworkDevice(bool enable) {
+    if (is_locked_)
+      return;
     EnableNetworkDeviceType(TYPE_WIFI, enable);
   }
 
   virtual void EnableCellularNetworkDevice(bool enable) {
+    if (is_locked_)
+      return;
     EnableNetworkDeviceType(TYPE_CELLULAR, enable);
   }
 
@@ -1580,6 +1638,7 @@
   }
 
   void InitTestData() {
+    is_locked_ = true;
     ethernet_ = new EthernetNetwork();
     ethernet_->set_connected(true);
     ethernet_->set_service_path("eth1");
@@ -1621,7 +1680,7 @@
     cellular1->set_service_path("fc1");
     cellular1->set_name("Fake Cellular 1");
     cellular1->set_strength(70);
-    cellular1->set_connected(true);
+    cellular1->set_connected(false);
     cellular1->set_activation_state(ACTIVATION_STATE_ACTIVATED);
     cellular1->set_payment_url(std::string("http://www.google.com"));
     cellular1->set_network_technology(NETWORK_TECHNOLOGY_EVDO);
@@ -1768,7 +1827,7 @@
     bool boolval = false;
     int intval = 0;
     std::string stringval;
-    Network* network;
+    Network* network = NULL;
     if (ethernet_->service_path() == path) {
       network = ethernet_;
     } else {
@@ -1779,7 +1838,7 @@
       if (cellular == NULL && wifi == NULL)
         return;
 
-      WirelessNetwork* wireless;
+      WirelessNetwork* wireless = NULL;
       if (wifi != NULL)
         wireless = static_cast<WirelessNetwork*>(wifi);
       else
@@ -1822,7 +1881,8 @@
         network->InitIPAddress();
       }
     }
-    NotifyNetworkChanged(network);
+    if (network)
+      NotifyNetworkChanged(network);
   }
 
   void UpdateCellularDataPlan(const CellularDataPlanList* data_plans) {
@@ -1860,6 +1920,9 @@
   // For monitoring data plan changes to the connected cellular network.
   DataPlanUpdateMonitor data_plan_monitor_;
 
+  // Network login observer.
+  scoped_ptr<NetworkLoginObserver> network_login_observer_;
+
   // The ethernet network.
   EthernetNetwork* ethernet_;
 
@@ -1893,9 +1956,15 @@
   // Currently not implemented. TODO: implement or eliminate.
   bool offline_mode_;
 
+  // True if access network library is locked.
+  bool is_locked_;
+
   // Delayed task to retrieve the network information.
   CancelableTask* update_task_;
 
+  // Cellular plan payment time.
+  base::Time cellular_plan_payment_time_;
+
   DISALLOW_COPY_AND_ASSIGN(NetworkLibraryImpl);
 };
 
@@ -1915,6 +1984,9 @@
   virtual void RemoveNetworkObserver(const std::string& service_path,
                                      NetworkObserver* observer) {}
   virtual void RemoveObserverForAllNetworks(NetworkObserver* observer) {}
+  virtual void Lock() {}
+  virtual void Unlock() {}
+  virtual bool IsLocked() { return true; }
   virtual void AddCellularDataPlanObserver(
       CellularDataPlanObserver* observer) {}
   virtual void RemoveCellularDataPlanObserver(
@@ -1979,6 +2051,8 @@
     return true;
   }
   virtual void RefreshCellularDataPlans(const CellularNetwork* network) {}
+  virtual void SignalCellularPlanPayment() {}
+  virtual bool HasRecentCellularPlanPayment() { return false; }
   virtual void DisconnectFromWirelessNetwork(const WirelessNetwork* network) {}
   virtual void SaveCellularNetwork(const CellularNetwork* network) {}
   virtual void SaveWifiNetwork(const WifiNetwork* network) {}
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index 0a78cd4..483acfa 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -200,6 +200,8 @@
   string16 GetPlanExpiration() const;
   // Formats plan usage info.
   string16 GetUsageInfo() const;
+  // Returns a unique string for this plan that can be used for comparisons.
+  std::string GetUniqueIdentifier() const;
   base::TimeDelta remaining_time() const;
   int64 remaining_minutes() const;
   int64 remaining_data() const;
@@ -218,6 +220,7 @@
 class CellularNetwork : public WirelessNetwork {
  public:
   enum DataLeft {
+    DATA_UNKNOWN,
     DATA_NORMAL,
     DATA_LOW,
     DATA_VERY_LOW,
@@ -495,6 +498,15 @@
   // Stop |observer| from observing any networks
   virtual void RemoveObserverForAllNetworks(NetworkObserver* observer) = 0;
 
+  // Temporarily locks down certain functionality in network library to prevent
+  // unplanned side effects. During the lock down, Enable*Device() calls cannot
+  // be made.
+  virtual void Lock() = 0;
+  // Removes temporarily lock of network library.
+  virtual void Unlock() = 0;
+  // Checks if access to network library is locked.
+  virtual bool IsLocked() = 0;
+
   virtual void AddCellularDataPlanObserver(
       CellularDataPlanObserver* observer) = 0;
   virtual void RemoveCellularDataPlanObserver(
@@ -578,6 +590,12 @@
   // Network::Observer::CellularDataPlanChanged callback.
   virtual void RefreshCellularDataPlans(const CellularNetwork* network) = 0;
 
+  // Records information that cellular play payment had happened.
+  virtual void SignalCellularPlanPayment() = 0;
+
+  // Returns true if cellular plan payment had been recorded recently.
+  virtual bool HasRecentCellularPlanPayment() = 0;
+
   // Disconnect from the specified wireless (either cellular or wifi) network.
   virtual void DisconnectFromWirelessNetwork(
       const WirelessNetwork* network) = 0;
diff --git a/chrome/browser/chromeos/cros_settings.cc b/chrome/browser/chromeos/cros_settings.cc
index 59cdb4d..419479b 100644
--- a/chrome/browser/chromeos/cros_settings.cc
+++ b/chrome/browser/chromeos/cros_settings.cc
@@ -63,9 +63,9 @@
   Set(path, Value::CreateIntegerValue(in_value));
 }
 
-void CrosSettings::SetReal(const std::string& path, double in_value) {
+void CrosSettings::SetDouble(const std::string& path, double in_value) {
   DCHECK(CalledOnValidThread());
-  Set(path, Value::CreateRealValue(in_value));
+  Set(path, Value::CreateDoubleValue(in_value));
 }
 
 void CrosSettings::SetString(const std::string& path,
@@ -181,14 +181,14 @@
   return value->GetAsInteger(out_value);
 }
 
-bool CrosSettings::GetReal(const std::string& path,
-                           double* out_value) const {
+bool CrosSettings::GetDouble(const std::string& path,
+                             double* out_value) const {
   DCHECK(CalledOnValidThread());
   Value* value;
   if (!Get(path, &value))
     return false;
 
-  return value->GetAsReal(out_value);
+  return value->GetAsDouble(out_value);
 }
 
 bool CrosSettings::GetString(const std::string& path,
diff --git a/chrome/browser/chromeos/cros_settings.h b/chrome/browser/chromeos/cros_settings.h
index c8446c5..fe7a7e7 100644
--- a/chrome/browser/chromeos/cros_settings.h
+++ b/chrome/browser/chromeos/cros_settings.h
@@ -50,7 +50,7 @@
   // value at that path, even if it has a different type.
   void SetBoolean(const std::string& path, bool in_value);
   void SetInteger(const std::string& path, int in_value);
-  void SetReal(const std::string& path, double in_value);
+  void SetDouble(const std::string& path, double in_value);
   void SetString(const std::string& path, const std::string& in_value);
 
   // These are convenience forms of Get().  The value will be retrieved
@@ -58,7 +58,7 @@
   // the end of the path can be returned in the form specified.
   bool GetBoolean(const std::string& path, bool* out_value) const;
   bool GetInteger(const std::string& path, int* out_value) const;
-  bool GetReal(const std::string& path, double* out_value) const;
+  bool GetDouble(const std::string& path, double* out_value) const;
   bool GetString(const std::string& path, std::string* out_value) const;
 
   // adding/removing of providers
diff --git a/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc b/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc
index 9d9be53..b945f02 100644
--- a/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/accounts_options_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/json/json_reader.h"
 #include "base/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
@@ -24,22 +24,23 @@
 }
 
 void AccountsOptionsHandler::RegisterMessages() {
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("whitelistUser",
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("whitelistUser",
       NewCallback(this, &AccountsOptionsHandler::WhitelistUser));
-  dom_ui_->RegisterMessageCallback("unwhitelistUser",
+  web_ui_->RegisterMessageCallback("unwhitelistUser",
       NewCallback(this, &AccountsOptionsHandler::UnwhitelistUser));
-  dom_ui_->RegisterMessageCallback("fetchUserPictures",
+  web_ui_->RegisterMessageCallback("fetchUserPictures",
       NewCallback(this, &AccountsOptionsHandler::FetchUserPictures));
-  dom_ui_->RegisterMessageCallback("whitelistExistingUsers",
+  web_ui_->RegisterMessageCallback("whitelistExistingUsers",
       NewCallback(this, &AccountsOptionsHandler::WhitelistExistingUsers));
 }
 
 void AccountsOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  localized_strings->SetString("accountsPage", l10n_util::GetStringUTF16(
-      IDS_OPTIONS_ACCOUNTS_TAB_LABEL));
+
+  RegisterTitle(localized_strings, "accountsPage",
+                IDS_OPTIONS_ACCOUNTS_TAB_LABEL);
 
   localized_strings->SetString("allow_BWSI", l10n_util::GetStringUTF16(
       IDS_OPTIONS_ACCOUNTS_ALLOW_BWSI_DESCRIPTION));
@@ -88,26 +89,26 @@
 void AccountsOptionsHandler::FetchUserPictures(const ListValue* args) {
   DictionaryValue user_pictures;
 
-  std::vector<UserManager::User> users = UserManager::Get()->GetUsers();
-  for (std::vector<UserManager::User>::const_iterator it = users.begin();
+  UserVector users = UserManager::Get()->GetUsers();
+  for (UserVector::const_iterator it = users.begin();
        it < users.end(); ++it) {
     if (!it->image().isNull()) {
       StringValue* picture = new StringValue(
-          dom_ui_util::GetImageDataUrl(it->image()));
+          web_ui_util::GetImageDataUrl(it->image()));
       // SetWithoutPathExpansion because email has "." in it.
       user_pictures.SetWithoutPathExpansion(it->email(), picture);
     }
   }
 
-  dom_ui_->CallJavascriptFunction(L"AccountsOptions.setUserPictures",
+  web_ui_->CallJavascriptFunction(L"AccountsOptions.setUserPictures",
       user_pictures);
 }
 
 void AccountsOptionsHandler::WhitelistExistingUsers(const ListValue* args) {
   ListValue whitelist_users;
 
-  std::vector<UserManager::User> users = UserManager::Get()->GetUsers();
-  for (std::vector<UserManager::User>::const_iterator it = users.begin();
+  UserVector users = UserManager::Get()->GetUsers();
+  for (UserVector::const_iterator it = users.begin();
        it < users.end(); ++it) {
     const std::string& email = it->email();
     if (!UserCrosSettingsProvider::IsEmailInCachedWhitelist(email)) {
@@ -120,7 +121,7 @@
     }
   }
 
-  dom_ui_->CallJavascriptFunction(L"AccountsOptions.addUsers", whitelist_users);
+  web_ui_->CallJavascriptFunction(L"AccountsOptions.addUsers", whitelist_users);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/accounts_options_handler.h b/chrome/browser/chromeos/dom_ui/accounts_options_handler.h
index 2fbf76d..663f60a 100644
--- a/chrome/browser/chromeos/dom_ui/accounts_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/accounts_options_handler.h
@@ -18,7 +18,7 @@
   AccountsOptionsHandler();
   virtual ~AccountsOptionsHandler();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // OptionsUIHandler implementation:
diff --git a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc
index 43d1148..b01ccea 100644
--- a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "base/json/json_reader.h"
 #include "base/string_number_conversions.h"
 #include "chrome/browser/chromeos/cros_settings.h"
 #include "chrome/browser/metrics/user_metrics.h"
@@ -37,39 +36,17 @@
 }
 
 void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
-                                         Value::ValueType pref_type,
-                                         const std::string& value_string,
+                                         const Value* value,
                                          const std::string& metric) {
   if (!CrosSettings::IsCrosSettings(pref_name))
-    return ::CoreOptionsHandler::SetPref(pref_name, pref_type, value_string,
-                                         metric);
+    return ::CoreOptionsHandler::SetPref(pref_name, value, metric);
   handling_change_ = true;
-  CrosSettings* cros_settings = CrosSettings::Get();
-  switch (pref_type) {
-    case Value::TYPE_BOOLEAN:
-      cros_settings->SetBoolean(pref_name, value_string == "true");
-      break;
-    case Value::TYPE_INTEGER:
-      int int_value;
-      if (base::StringToInt(value_string, &int_value))
-        cros_settings->SetInteger(pref_name, int_value);
-      break;
-    case Value::TYPE_STRING:
-      cros_settings->SetString(pref_name, value_string);
-      break;
-    default: {
-      Value* pref_value = base::JSONReader().JsonToValue(
-          value_string,  // JSON
-          false,         // no check_root
-          false);        // no trailing comma
-      if (pref_value)
-        cros_settings->Set(pref_name, pref_value);
-      break;
-    }
-  }
+  // CrosSettings takes ownership of its value so we need to copy it.
+  Value* pref_value = value->DeepCopy();
+  CrosSettings::Get()->Set(pref_name, pref_value);
   handling_change_ = false;
 
-  ProcessUserMetric(pref_type, value_string, metric);
+  ProcessUserMetric(value, metric);
 }
 
 void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
@@ -95,7 +72,7 @@
 
 void CoreChromeOSOptionsHandler::NotifySettingsChanged(
     const std::string* setting_name) {
-  DCHECK(dom_ui_);
+  DCHECK(web_ui_);
   DCHECK(CrosSettings::Get()->IsCrosSettings(*setting_name));
   Value* value = NULL;
   if (!CrosSettings::Get()->Get(*setting_name, &value)) {
@@ -111,7 +88,7 @@
     ListValue result_value;
     result_value.Append(Value::CreateStringValue(setting_name->c_str()));
     result_value.Append(value->DeepCopy());
-    dom_ui_->CallJavascriptFunction(callback_function, result_value);
+    web_ui_->CallJavascriptFunction(callback_function, result_value);
   }
   if (value)
     delete value;
diff --git a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h
index 25ef417..4252556 100644
--- a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h
@@ -20,8 +20,7 @@
   virtual Value* FetchPref(const std::string& pref_name);
   virtual void ObservePref(const std::string& pref_name);
   virtual void SetPref(const std::string& pref_name,
-                       Value::ValueType pref_type,
-                       const std::string& value_string,
+                       const Value* value,
                        const std::string& metric);
   virtual void StopObservingPref(const std::string& path);
 
diff --git a/chrome/browser/chromeos/dom_ui/cros_language_options_handler.cc b/chrome/browser/chromeos/dom_ui/cros_language_options_handler.cc
new file mode 100644
index 0000000..9d6f70b
--- /dev/null
+++ b/chrome/browser/chromeos/dom_ui/cros_language_options_handler.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/dom_ui/cros_language_options_handler.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/input_method_library.h"
+
+namespace chromeos {
+
+CrosLanguageOptionsHandler::CrosLanguageOptionsHandler() {
+}
+
+CrosLanguageOptionsHandler::~CrosLanguageOptionsHandler() {
+}
+
+void CrosLanguageOptionsHandler::GetLocalizedValues(
+    DictionaryValue* localized_strings) {
+  LanguageOptionsHandlerCommon::GetLocalizedValues(localized_strings);
+
+  localized_strings->SetString("ok_button", l10n_util::GetStringUTF16(IDS_OK));
+  localized_strings->SetString("configure",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE));
+  localized_strings->SetString("input_method",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD));
+  localized_strings->SetString("please_add_another_input_method",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_INPUT_METHOD));
+  localized_strings->SetString("input_method_instructions",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD_INSTRUCTIONS));
+  localized_strings->SetString("switch_input_methods_hint",
+      l10n_util::GetStringFUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_SWITCH_INPUT_METHODS_HINT,
+          ASCIIToUTF16("alt+shift")));
+  localized_strings->SetString("select_previous_input_method_hint",
+      l10n_util::GetStringFUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_SELECT_PREVIOUS_INPUT_METHOD_HINT,
+          ASCIIToUTF16("ctrl+space")));
+  localized_strings->SetString("restart_button",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON));
+
+  // GetSupportedInputMethods() never return NULL.
+  InputMethodLibrary *im_library =
+      CrosLibrary::Get()->GetInputMethodLibrary();
+  scoped_ptr<chromeos::InputMethodDescriptors> descriptors(
+      im_library->GetSupportedInputMethods());
+  localized_strings->Set("languageList", GetLanguageList(*descriptors));
+  localized_strings->Set("inputMethodList", GetInputMethodList(*descriptors));
+}
+
+void CrosLanguageOptionsHandler::RegisterMessages() {
+  LanguageOptionsHandlerCommon::RegisterMessages();
+
+  web_ui_->RegisterMessageCallback("inputMethodDisable",
+      NewCallback(this,
+                  &CrosLanguageOptionsHandler::InputMethodDisableCallback));
+  web_ui_->RegisterMessageCallback("inputMethodEnable",
+      NewCallback(this,
+                  &CrosLanguageOptionsHandler::InputMethodEnableCallback));
+  web_ui_->RegisterMessageCallback("inputMethodOptionsOpen",
+      NewCallback(this,
+                  &CrosLanguageOptionsHandler::InputMethodOptionsOpenCallback));
+  web_ui_->RegisterMessageCallback("uiLanguageRestart",
+      NewCallback(this, &CrosLanguageOptionsHandler::RestartCallback));
+}
+
+ListValue* CrosLanguageOptionsHandler::GetInputMethodList(
+    const chromeos::InputMethodDescriptors& descriptors) {
+  ListValue* input_method_list = new ListValue();
+
+  for (size_t i = 0; i < descriptors.size(); ++i) {
+    const chromeos::InputMethodDescriptor& descriptor = descriptors[i];
+    const std::string language_code =
+        chromeos::input_method::GetLanguageCodeFromDescriptor(descriptor);
+    const std::string display_name =
+        chromeos::input_method::GetInputMethodDisplayNameFromId(descriptor.id);
+
+    DictionaryValue* dictionary = new DictionaryValue();
+    dictionary->SetString("id", descriptor.id);
+    dictionary->SetString("displayName", display_name);
+
+    // One input method can be associated with multiple languages, hence
+    // we use a dictionary here.
+    DictionaryValue* language_codes = new DictionaryValue();
+    language_codes->SetBoolean(language_code, true);
+    // Check kExtraLanguages to see if there are languages associated with
+    // this input method. If these are present, add these.
+    for (size_t j = 0; j < arraysize(chromeos::input_method::kExtraLanguages);
+         ++j) {
+      const std::string extra_input_method_id =
+          chromeos::input_method::kExtraLanguages[j].input_method_id;
+      const std::string extra_language_code =
+          chromeos::input_method::kExtraLanguages[j].language_code;
+      if (extra_input_method_id == descriptor.id) {
+        language_codes->SetBoolean(extra_language_code, true);
+      }
+    }
+    dictionary->Set("languageCodeSet", language_codes);
+
+    input_method_list->Append(dictionary);
+  }
+
+  return input_method_list;
+}
+
+ListValue* CrosLanguageOptionsHandler::GetLanguageList(
+    const chromeos::InputMethodDescriptors& descriptors) {
+  std::set<std::string> language_codes;
+  // Collect the language codes from the supported input methods.
+  for (size_t i = 0; i < descriptors.size(); ++i) {
+    const chromeos::InputMethodDescriptor& descriptor = descriptors[i];
+    const std::string language_code =
+        chromeos::input_method::GetLanguageCodeFromDescriptor(descriptor);
+    language_codes.insert(language_code);
+  }
+  // Collect the language codes from kExtraLanguages.
+  for (size_t i = 0; i < arraysize(chromeos::input_method::kExtraLanguages);
+       ++i) {
+    const char* language_code =
+        chromeos::input_method::kExtraLanguages[i].language_code;
+    language_codes.insert(language_code);
+  }
+
+  // Map of display name -> {language code, native_display_name}.
+  // In theory, we should be able to create a map that is sorted by
+  // display names using ICU comparator, but doing it is hard, thus we'll
+  // use an auxiliary vector to achieve the same result.
+  typedef std::pair<std::string, string16> LanguagePair;
+  typedef std::map<string16, LanguagePair> LanguageMap;
+  LanguageMap language_map;
+  // The auxiliary vector mentioned above.
+  std::vector<string16> display_names;
+
+  // Build the list of display names, and build the language map.
+  for (std::set<std::string>::const_iterator iter = language_codes.begin();
+       iter != language_codes.end(); ++iter) {
+    const string16 display_name =
+        chromeos::input_method::GetLanguageDisplayNameFromCode(*iter);
+    const string16 native_display_name =
+        chromeos::input_method::GetLanguageNativeDisplayNameFromCode(*iter);
+    display_names.push_back(display_name);
+    language_map[display_name] =
+        std::make_pair(*iter, native_display_name);
+  }
+  DCHECK_EQ(display_names.size(), language_map.size());
+
+  // Sort display names using locale specific sorter.
+  l10n_util::SortStrings16(g_browser_process->GetApplicationLocale(),
+                           &display_names);
+
+  // Build the language list from the language map.
+  ListValue* language_list = new ListValue();
+  for (size_t i = 0; i < display_names.size(); ++i) {
+    const LanguagePair& pair = language_map[display_names[i]];
+    DictionaryValue* dictionary = new DictionaryValue();
+    dictionary->SetString("code",  pair.first);
+    dictionary->SetString("displayName", display_names[i]);
+    dictionary->SetString("nativeDisplayName", pair.second);
+    language_list->Append(dictionary);
+  }
+
+  return language_list;
+}
+
+string16 CrosLanguageOptionsHandler::GetProductName() {
+  return l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME);
+}
+
+void CrosLanguageOptionsHandler::SetApplicationLocale(
+    std::string language_code) {
+  web_ui_->GetProfile()->ChangeAppLocale(
+      language_code, Profile::APP_LOCALE_CHANGED_VIA_SETTINGS);
+}
+
+void CrosLanguageOptionsHandler::RestartCallback(const ListValue* args) {
+  UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_SignOut"));
+
+  Browser* browser = Browser::GetBrowserForController(
+      &web_ui_->tab_contents()->controller(), NULL);
+  if (browser)
+    browser->ExecuteCommand(IDC_EXIT);
+}
+
+void CrosLanguageOptionsHandler::InputMethodDisableCallback(
+    const ListValue* args) {
+  const std::string input_method_id = WideToASCII(ExtractStringValue(args));
+  const std::string action = StringPrintf(
+      "LanguageOptions_DisableInputMethod_%s", input_method_id.c_str());
+  UserMetrics::RecordComputedAction(action);
+}
+
+void CrosLanguageOptionsHandler::InputMethodEnableCallback(
+    const ListValue* args) {
+  const std::string input_method_id = WideToASCII(ExtractStringValue(args));
+  const std::string action = StringPrintf(
+      "LanguageOptions_EnableInputMethod_%s", input_method_id.c_str());
+  UserMetrics::RecordComputedAction(action);
+}
+
+void CrosLanguageOptionsHandler::InputMethodOptionsOpenCallback(
+    const ListValue* args) {
+  const std::string input_method_id = WideToASCII(ExtractStringValue(args));
+  const std::string action = StringPrintf(
+      "InputMethodOptions_Open_%s", input_method_id.c_str());
+  UserMetrics::RecordComputedAction(action);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/cros_language_options_handler.h b/chrome/browser/chromeos/dom_ui/cros_language_options_handler.h
new file mode 100644
index 0000000..f6f6f53
--- /dev/null
+++ b/chrome/browser/chromeos/dom_ui/cros_language_options_handler.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_DOM_UI_CROS_LANGUAGE_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_DOM_UI_CROS_LANGUAGE_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/dom_ui/options/language_options_handler.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
+
+namespace chromeos {
+
+// Language options page UI handler for Chrome OS.  For non-Chrome OS,
+// see LanguageOptionsHnadler.
+class CrosLanguageOptionsHandler : public LanguageOptionsHandlerCommon {
+ public:
+  CrosLanguageOptionsHandler();
+  virtual ~CrosLanguageOptionsHandler();
+
+  // OptionsUIHandler implementation.
+  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
+
+  // DOMMessageHandler implementation.
+  virtual void RegisterMessages();
+
+  // The following static methods are public for ease of testing.
+
+  // Gets the list of input methods from the given input descriptors.
+  // The return value will look like:
+  // [{'id': 'pinyin', 'displayName': 'Pinyin',
+  //   'languageCodeSet': {'zh-CW': true}},  ...]
+  //
+  // Note that true in languageCodeSet does not mean anything. We just use
+  // the dictionary as a set.
+  static ListValue* GetInputMethodList(
+      const chromeos::InputMethodDescriptors& descriptors);
+
+  // Gets the list of languages from the given input descriptors.
+  // The return value will look like:
+  // [{'code': 'fi', 'displayName': 'Finnish', 'nativeDisplayName': 'suomi'},
+  //  ...]
+  static ListValue* GetLanguageList(
+      const chromeos::InputMethodDescriptors& descriptors);
+
+ private:
+  // LanguageOptionsHandlerCommon implementation.
+  virtual string16 GetProductName();
+  virtual void SetApplicationLocale(std::string language_code);
+
+  // Called when the sign-out button is clicked.
+  void RestartCallback(const ListValue* args);
+
+  // Called when the input method is disabled.
+  // |args| will contain the input method ID as string (ex. "mozc").
+  void InputMethodDisableCallback(const ListValue* args);
+
+  // Called when the input method is enabled.
+  // |args| will contain the input method ID as string (ex. "mozc").
+  void InputMethodEnableCallback(const ListValue* args);
+
+  // Called when the input method options page is opened.
+  // |args| will contain the input method ID as string (ex. "mozc").
+  void InputMethodOptionsOpenCallback(const ListValue* args);
+
+  DISALLOW_COPY_AND_ASSIGN(CrosLanguageOptionsHandler);
+};
+
+} // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_CROS_LANGUAGE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/chromeos/dom_ui/cros_personal_options_handler.cc b/chrome/browser/chromeos/dom_ui/cros_personal_options_handler.cc
deleted file mode 100644
index f237ad9..0000000
--- a/chrome/browser/chromeos/dom_ui/cros_personal_options_handler.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/dom_ui/cros_personal_options_handler.h"
-
-#include "app/l10n_util.h"
-#include "base/values.h"
-#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
-#include "grit/generated_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace chromeos {
-
-CrosPersonalOptionsHandler::CrosPersonalOptionsHandler() {
-}
-
-CrosPersonalOptionsHandler::~CrosPersonalOptionsHandler() {
-}
-
-// TODO(jhawkins): Move the contents of this file to PersonalOptionsHandler
-// within an OS_CHROMEOS #ifdef.
-void CrosPersonalOptionsHandler::GetLocalizedValues(
-    DictionaryValue* localized_strings) {
-  localized_strings->SetString("account",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_PERSONAL_ACCOUNT_GROUP_NAME));
-  localized_strings->SetString("enableScreenlock",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SCREENLOCKER_CHECKBOX));
-}
-
-void CrosPersonalOptionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
-      "loadAccountPicture",
-      NewCallback(this, &CrosPersonalOptionsHandler::LoadAccountPicture));
-}
-
-void CrosPersonalOptionsHandler::LoadAccountPicture(const ListValue* args) {
-  const SkBitmap& account_picture =
-      UserManager::Get()->logged_in_user().image();
-
-  if (!account_picture.isNull()) {
-    StringValue data_url(dom_ui_util::GetImageDataUrl(account_picture));
-    dom_ui_->CallJavascriptFunction(L"PersonalOptions.setAccountPicture",
-        data_url);
-  }
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/cros_personal_options_handler.h b/chrome/browser/chromeos/dom_ui/cros_personal_options_handler.h
deleted file mode 100644
index d286461..0000000
--- a/chrome/browser/chromeos/dom_ui/cros_personal_options_handler.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_CROS_PERSONAL_OPTIONS_HANDLER_H_
-#define CHROME_BROWSER_CHROMEOS_DOM_UI_CROS_PERSONAL_OPTIONS_HANDLER_H_
-
-#include "chrome/browser/dom_ui/options/options_ui.h"
-
-namespace chromeos {
-
-class CrosPersonalOptionsHandler : public OptionsPageUIHandler {
- public:
-  CrosPersonalOptionsHandler();
-  virtual ~CrosPersonalOptionsHandler();
-
-  // Overridden from PersonalOptionsHandler:
-  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
-  virtual void RegisterMessages();
-
- private:
-  void LoadAccountPicture(const ListValue* args);
-
-  DISALLOW_COPY_AND_ASSIGN(CrosPersonalOptionsHandler);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_CROS_PERSONAL_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/chromeos/dom_ui/domui_menu_control.h b/chrome/browser/chromeos/dom_ui/domui_menu_control.h
deleted file mode 100644
index 417103b..0000000
--- a/chrome/browser/chromeos/dom_ui/domui_menu_control.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_DOMUI_MENU_CONTROL_H_
-#define CHROME_BROWSER_CHROMEOS_DOM_UI_DOMUI_MENU_CONTROL_H_
-#pragma once
-
-namespace gfx {
-class Size;
-}  // namespace gfx
-
-namespace menus {
-class MenuModel;
-}  // namespace menus
-
-namespace chromeos {
-
-// DOMUIMenuControl class is used to control the UI counterpart of
-// a MenuModel. One instance of DOMUIMenuControl is created for each
-// MenuModel instance, that is, a submenu will have its own
-// DOMUIMenuControl.
-class DOMUIMenuControl {
- public:
-  enum ActivationMode {
-    ACTIVATE_NO_CLOSE,   // Activate the command without closing menu.
-    CLOSE_AND_ACTIVATE,  // Close the menu and then activate the command.
-  };
-  virtual ~DOMUIMenuControl() {}
-
-  // Returns the MenuModel associated with this control.
-  virtual menus::MenuModel* GetMenuModel() = 0;
-
-  // Activates an item in the |model| at |index|.
-  virtual void Activate(menus::MenuModel* model,
-                        int index,
-                        ActivationMode activation_mode) = 0;
-
-  // Close All menu window from root menu to leaf submenus.
-  virtual void CloseAll() = 0;
-
-  // Close the submenu (and all decendant submenus).
-  virtual void CloseSubmenu() = 0;
-
-  // Move the input to parent. Used in keyboard navigation.
-  virtual void MoveInputToParent() = 0;
-
-  // Move the input to submenu. Used in keyboard navigation.
-  virtual void MoveInputToSubmenu() = 0;
-
-  // Called when the menu page is loaded. This is used to call
-  // initialize function in JavaScript.
-  virtual void OnLoad() = 0;
-
-  // Open submenu using the submenu model at index in the model.
-  // The top coordinate of the selected menu is passed as |y_top|
-  // so that the submenu can be aligned to the selected item.
-  virtual void OpenSubmenu(int index, int y_top) =0;
-
-  // Sets the size of the menu.
-  virtual void SetSize(const gfx::Size& size) = 0;
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_DOMUI_MENU_CONTROL_H_
diff --git a/chrome/browser/chromeos/dom_ui/imageburner_ui.cc b/chrome/browser/chromeos/dom_ui/imageburner_ui.cc
index bd08dd3..9887eda 100644
--- a/chrome/browser/chromeos/dom_ui/imageburner_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/imageburner_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
@@ -27,7 +25,19 @@
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
+static const char kPropertyPath[] = "path";
+static const char kPropertyTitle[] = "title";
+static const char kPropertyDirectory[] = "isDirectory";
+static const char kImageBaseURL[] =
+    "http://chrome-master.mtv.corp.google.com/chromeos/dev-channel/";
+static const char kImageFetcherName[] = "LATEST-x86-generic";
+static const char kImageDownloadURL[] =
+    "https://dl.google.com/dl/chromeos/recovery/latest_mario_beta_channel";
+static const char kImageFileName[] = "chromeos_image.bin.zip";
+static const char kTempImageFolderName[] = "chromeos_image";
 
 ////////////////////////////////////////////////////////////////////////////////
 //
@@ -35,59 +45,125 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-ImageBurnUIHTMLSource::ImageBurnUIHTMLSource()
-    : DataSource(chrome::kChromeUIImageBurnerHost, MessageLoop::current()) {
-}
+class ImageBurnUIHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+  ImageBurnUIHTMLSource()
+      : DataSource(chrome::kChromeUIImageBurnerHost, MessageLoop::current()) {
+  }
 
-void ImageBurnUIHTMLSource::StartDataRequest(const std::string& path,
-                                             bool is_off_the_record,
-                                             int request_id) {
-  DictionaryValue localized_strings;
-  localized_strings.SetString("burnConfirmText1",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_CONFIM_BURN1));
-  localized_strings.SetString("burnConfirmText2",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_CONFIM_BURN2));
-  localized_strings.SetString("burnUnsuccessfulMessage",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_UNSUCCESSFUL));
-  localized_strings.SetString("burnSuccessfulMessage",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_SUCCESSFUL));
-  localized_strings.SetString("downloadAbortedMessage",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_UNSUCCESSFUL));
-  localized_strings.SetString("title",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_TITLE));
-  localized_strings.SetString("listTitle",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_ROOT_LIST_TITLE));
-  localized_strings.SetString("downloadStatusStart",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_STARTING_STATUS));
-  localized_strings.SetString("downloadStatusInProgress",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_IN_PROGRESS_STATUS));
-  localized_strings.SetString("downloadStatusComplete",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_COMPLETE_STATUS));
-  localized_strings.SetString("downloadStatusCanceled",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_CANCELED_STATUS));
-  localized_strings.SetString("burnStatusStart",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_STARTING_STATUS));
-  localized_strings.SetString("burnStatusInProgress",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_IN_PROGRESS_STATUS));
-  localized_strings.SetString("burnStatusComplete",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_COMPLETE_STATUS));
-  localized_strings.SetString("burnStatusCanceled",
-      l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_CANCELED_STATUS));
+  // Called when the network layer has requested a resource underneath
+  // the path we registered.
+  virtual void StartDataRequest(const std::string& path,
+                                 bool is_off_the_record,
+                                 int request_id) {
+    DictionaryValue localized_strings;
+    localized_strings.SetString("burnConfirmText1",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_CONFIM_BURN1));
+    localized_strings.SetString("burnConfirmText2",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_CONFIM_BURN2));
+    localized_strings.SetString("burnUnsuccessfulMessage",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_UNSUCCESSFUL));
+    localized_strings.SetString("burnSuccessfulMessage",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_SUCCESSFUL));
+    localized_strings.SetString("downloadAbortedMessage",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_UNSUCCESSFUL));
+    localized_strings.SetString("title",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_TITLE));
+    localized_strings.SetString("listTitle",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_ROOT_LIST_TITLE));
+    localized_strings.SetString("downloadStatusStart",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_STARTING_STATUS));
+    localized_strings.SetString("downloadStatusInProgress",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_IN_PROGRESS_STATUS));
+    localized_strings.SetString("downloadStatusComplete",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_COMPLETE_STATUS));
+    localized_strings.SetString("downloadStatusCanceled",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_DOWNLOAD_CANCELED_STATUS));
+    localized_strings.SetString("burnStatusStart",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_STARTING_STATUS));
+    localized_strings.SetString("burnStatusInProgress",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_IN_PROGRESS_STATUS));
+    localized_strings.SetString("burnStatusComplete",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_COMPLETE_STATUS));
+    localized_strings.SetString("burnStatusCanceled",
+        l10n_util::GetStringUTF16(IDS_IMAGEBURN_BURN_CANCELED_STATUS));
 
-  SetFontAndTextDirection(&localized_strings);
+    SetFontAndTextDirection(&localized_strings);
 
-  static const base::StringPiece imageburn_html(
-      ResourceBundle::GetSharedInstance().GetRawDataResource(
-      IDR_IMAGEBURNER_HTML));
-  const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
-      imageburn_html, &localized_strings);
+    static const base::StringPiece imageburn_html(
+        ResourceBundle::GetSharedInstance().GetRawDataResource(
+        IDR_IMAGEBURNER_HTML));
+    const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
+        imageburn_html, &localized_strings);
 
-  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
-  html_bytes->data.resize(full_html.size());
-  std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
+    scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
+    html_bytes->data.resize(full_html.size());
+    std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
 
-  SendResponse(request_id, html_bytes);
-}
+    SendResponse(request_id, html_bytes);
+  }
+
+  virtual std::string GetMimeType(const std::string&) const {
+    return "text/html";
+  }
+
+ private:
+  virtual ~ImageBurnUIHTMLSource() {}
+
+  DISALLOW_COPY_AND_ASSIGN(ImageBurnUIHTMLSource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// ImageBurnTaskProxy
+//
+////////////////////////////////////////////////////////////////////////////////
+
+class ImageBurnTaskProxy
+    : public base::RefCountedThreadSafe<ImageBurnTaskProxy> {
+ public:
+  explicit ImageBurnTaskProxy(const base::WeakPtr<ImageBurnHandler>& handler)
+      : handler_(handler) {
+        resource_manager_ = ImageBurnResourceManager::GetInstance();
+  }
+
+  bool ReportDownloadInitialized() {
+    bool initialized = resource_manager_-> CheckImageDownloadStarted();
+    if (!initialized)
+      resource_manager_-> ReportImageDownloadStarted();
+    return initialized;
+  }
+
+  bool CheckDownloadFinished() {
+    return resource_manager_->CheckDownloadFinished();
+  }
+
+  void BurnImage() {
+    if (!resource_manager_->CheckBurnInProgress() && handler_) {
+      resource_manager_->SetBurnInProgress(true);
+      handler_->BurnImage();
+    }
+  }
+
+  void FinalizeBurn(bool success) {
+    if (handler_) {
+      handler_->FinalizeBurn(success);
+      resource_manager_->SetBurnInProgress(false);
+    }
+  }
+
+  void CreateImageUrl(TabContents* tab_contents, ImageBurnHandler* downloader) {
+    resource_manager_->CreateImageUrl(tab_contents, downloader);
+  }
+
+ private:
+  base::WeakPtr<ImageBurnHandler> handler_;
+  ImageBurnResourceManager* resource_manager_;
+
+  friend class base::RefCountedThreadSafe<ImageBurnTaskProxy>;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageBurnTaskProxy);
+};
 
 ////////////////////////////////////////////////////////////////////////////////
 //
@@ -125,18 +201,18 @@
       download_manager_->RemoveObserver(this);
 }
 
-DOMMessageHandler* ImageBurnHandler::Attach(DOMUI* dom_ui) {
-  return DOMMessageHandler::Attach(dom_ui);
+WebUIMessageHandler* ImageBurnHandler::Attach(WebUI* web_ui) {
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void ImageBurnHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getRoots",
+  web_ui_->RegisterMessageCallback("getRoots",
       NewCallback(this, &ImageBurnHandler::HandleGetRoots));
-  dom_ui_->RegisterMessageCallback("downloadImage",
+  web_ui_->RegisterMessageCallback("downloadImage",
       NewCallback(this, &ImageBurnHandler::HandleDownloadImage));
-  dom_ui_->RegisterMessageCallback("burnImage",
+  web_ui_->RegisterMessageCallback("burnImage",
       NewCallback(this, &ImageBurnHandler::HandleBurnImage));
-  dom_ui_->RegisterMessageCallback("cancelBurnImage",
+  web_ui_->RegisterMessageCallback("cancelBurnImage",
       NewCallback(this, &ImageBurnHandler::HandleCancelBurnImage));
 }
 
@@ -146,7 +222,7 @@
   if ((evt == chromeos::DISK_REMOVED ||
       evt == chromeos::DISK_CHANGED ||
       evt == chromeos::DEVICE_REMOVED)) {
-    dom_ui_->CallJavascriptFunction(L"rootsChanged");
+    web_ui_->CallJavascriptFunction(L"rootsChanged");
   }
 }
 
@@ -171,7 +247,7 @@
       && download->state() != DownloadItem::COMPLETE) {
     scoped_ptr<DictionaryValue> result_value(
         download_util::CreateDownloadItemValue(download, 0));
-    dom_ui_->CallJavascriptFunction(L"downloadUpdated", *result_value);
+    web_ui_->CallJavascriptFunction(L"downloadUpdated", *result_value);
   }
   if (download->state() == DownloadItem::CANCELLED)
     DownloadCompleted(false);
@@ -189,14 +265,16 @@
 }
 
 void ImageBurnHandler::ModelChanged() {
+  // Find our item and observe it.
   std::vector<DownloadItem*> downloads;
   download_manager_->GetTemporaryDownloads(
       burn_resource_manager_->GetLocalImageDirPath(), &downloads);
-  if (download_item_observer_added_)
+  if (download_item_observer_added_)  // Already added.
     return;
   std::vector<DownloadItem*>::const_iterator it = downloads.begin();
   for (; it != downloads.end(); ++it) {
-    if ((*it)->url() == *image_download_url_) {
+    if ((*it)->original_url() == *image_download_url_) {
+      // Found it.
       download_item_observer_added_ = true;
       (*it)->AddObserver(this);
       active_download_item_ = *it;
@@ -214,19 +292,21 @@
   if (!burn_resource_manager_->CheckBurnInProgress()) {
     for (size_t i = 0; i < disks.size(); ++i) {
       if (!disks[i].mount_path.empty()) {
-        DictionaryValue* page_value = new DictionaryValue();
         FilePath disk_path = FilePath(disks[i].system_path).DirName();
         std::string title = "/dev/" + disk_path.BaseName().value();
-        page_value->SetString(kPropertyTitle, title);
-        page_value->SetString(kPropertyPath, title);
-        page_value->SetBoolean(kPropertyDirectory, true);
-        results_value.Append(page_value);
+        if (!mount_lib->IsBootPath(title.c_str())) {
+          DictionaryValue* page_value = new DictionaryValue();
+          page_value->SetString(std::string(kPropertyTitle), title);
+          page_value->SetString(std::string(kPropertyPath), title);
+          page_value->SetBoolean(std::string(kPropertyDirectory), true);
+          results_value.Append(page_value);
+        }
       }
     }
   }
   info_value.SetString("functionCall", "getRoots");
-  info_value.SetString(kPropertyPath, "");
-  dom_ui_->CallJavascriptFunction(L"browseFileResult",
+  info_value.SetString(std::string(kPropertyPath), "");
+  web_ui_->CallJavascriptFunction(L"browseFileResult",
                                   info_value, results_value);
 }
 
@@ -259,12 +339,12 @@
   DictionaryValue signal_value;
   if (is_successful) {
     signal_value.SetString("state", "COMPLETE");
-    dom_ui_->CallJavascriptFunction(L"downloadUpdated", signal_value);
-    dom_ui_->CallJavascriptFunction(L"promtUserDownloadFinished");
+    web_ui_->CallJavascriptFunction(L"downloadUpdated", signal_value);
+    web_ui_->CallJavascriptFunction(L"promtUserDownloadFinished");
   } else {
     signal_value.SetString("state", "CANCELLED");
-    dom_ui_->CallJavascriptFunction(L"downloadUpdated", signal_value);
-    dom_ui_->CallJavascriptFunction(L"alertUserDownloadAborted");
+    web_ui_->CallJavascriptFunction(L"downloadUpdated", signal_value);
+    web_ui_->CallJavascriptFunction(L"alertUserDownloadAborted");
   }
 }
 
@@ -277,16 +357,14 @@
     signal_value.SetString("path", image_target_.value());
     signal_value.SetInteger("received", 0);
     signal_value.SetString("progress_status_text", "");
-    dom_ui_->CallJavascriptFunction(L"burnProgressUpdated", signal_value);
+    web_ui_->CallJavascriptFunction(L"burnProgressUpdated", signal_value);
   }
 }
 
 void ImageBurnHandler::FinalizeBurn(bool successful) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (successful)
-    dom_ui_->CallJavascriptFunction(L"burnSuccessful");
-  else
-    dom_ui_->CallJavascriptFunction(L"burnUnsuccessful");
+  web_ui_->CallJavascriptFunction(successful ?
+      L"burnSuccessful" : L"burnUnsuccessful");
 }
 
 void ImageBurnHandler::UpdateBurnProgress(int64 total_burnt,
@@ -306,7 +384,7 @@
   progress_value.SetInteger("total", image_size);
   progress_value.SetString("path", path);
 
-  dom_ui_->CallJavascriptFunction(L"burnProgressUpdated", progress_value);
+  web_ui_->CallJavascriptFunction(L"burnProgressUpdated", progress_value);
 }
 
 string16 ImageBurnHandler::GetBurnProgressText(int64 total_burnt,
@@ -393,48 +471,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 //
-// ImageBurnTaskProxy
-//
-////////////////////////////////////////////////////////////////////////////////
-ImageBurnTaskProxy::ImageBurnTaskProxy(
-                        const base::WeakPtr<ImageBurnHandler>& handler)
-                            : handler_(handler) {
-  resource_manager_ = ImageBurnResourceManager::GetInstance();
-}
-
-bool ImageBurnTaskProxy::ReportDownloadInitialized() {
-  bool initialized = resource_manager_-> CheckImageDownloadStarted();
-  if (!initialized)
-    resource_manager_-> ReportImageDownloadStarted();
-  return initialized;
-}
-
-bool ImageBurnTaskProxy::CheckDownloadFinished() {
-  return resource_manager_->CheckDownloadFinished();
-}
-
-void ImageBurnTaskProxy:: BurnImage() {
-  if (!resource_manager_->CheckBurnInProgress() && handler_) {
-    resource_manager_->SetBurnInProgress(true);
-    handler_->BurnImage();
-  }
-}
-
-void ImageBurnTaskProxy::FinalizeBurn(bool success) {
-  if (handler_) {
-    handler_->FinalizeBurn(success);
-    resource_manager_->SetBurnInProgress(false);
-  }
-}
-
-void ImageBurnTaskProxy::CreateImageUrl(TabContents* tab_contents,
-                             ImageBurnHandler* downloader) {
-  resource_manager_->CreateImageUrl(tab_contents, downloader);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-//
 // ImageBurnResourceManager
 //
 ////////////////////////////////////////////////////////////////////////////////
@@ -446,10 +482,10 @@
       download_manager_(NULL),
       download_item_observer_added_(false),
       active_download_item_(NULL),
-      image_url_(NULL),
-      image_fetcher_url_(kImageBaseURL + kImageFetcherName),
+      image_url_(new GURL(kImageDownloadURL)),
+      image_fetcher_url_(std::string(kImageBaseURL) + kImageFetcherName),
       image_url_fetching_requested_(false),
-      image_url_fetched_(false) {
+      image_url_fetched_(true) {
   local_image_dir_file_path_.clear();
   image_fecher_local_path_ = GetLocalImageDirPath().Append(kImageFetcherName);
 }
@@ -481,7 +517,7 @@
   DCHECK(download->state() == DownloadItem::COMPLETE);
   std::string image_url;
   if (file_util::ReadFileToString(image_fecher_local_path_, &image_url)) {
-    image_url_.reset(new GURL(kImageBaseURL + image_url));
+    image_url_.reset(new GURL(std::string(kImageBaseURL) + image_url));
     ImageUrlFetched(true);
   } else {
     image_url_.reset();
@@ -609,14 +645,9 @@
 // ImageBurnUI
 //
 ////////////////////////////////////////////////////////////////////////////////
-ImageBurnUI::ImageBurnUI(TabContents* contents) : DOMUI(contents) {
+ImageBurnUI::ImageBurnUI(TabContents* contents) : WebUI(contents) {
   ImageBurnHandler* handler = new ImageBurnHandler(contents);
   AddMessageHandler((handler)->Attach(this));
   ImageBurnUIHTMLSource* html_source = new ImageBurnUIHTMLSource();
-  BrowserThread::PostTask(
-       BrowserThread::IO, FROM_HERE,
-       NewRunnableMethod(
-           ChromeURLDataManager::GetInstance(),
-           &ChromeURLDataManager::AddDataSource,
-           make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/chromeos/dom_ui/imageburner_ui.h b/chrome/browser/chromeos/dom_ui/imageburner_ui.h
index 97624ac..525db2d 100644
--- a/chrome/browser/chromeos/dom_ui/imageburner_ui.h
+++ b/chrome/browser/chromeos/dom_ui/imageburner_ui.h
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "app/download_file_interface.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/scoped_ptr.h"
@@ -19,47 +18,20 @@
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/mount_library.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/download/download_util.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/file_stream.h"
+#include "ui/base/dragdrop/download_file_interface.h"
 
 template <typename T> struct DefaultSingletonTraits;
 
-static const std::string kPropertyPath = "path";
-static const std::string kPropertyTitle = "title";
-static const std::string kPropertyDirectory = "isDirectory";
-static const std::string kImageBaseURL =
-    "http://chrome-master.mtv.corp.google.com/chromeos/dev-channel/";
-static const std::string kImageFetcherName = "LATEST-x86-generic";
-static const std::string kImageFileName = "chromeos_image.bin.gz";
-static const std::string kTempImageFolderName = "chromeos_image";
-
 class ImageBurnResourceManager;
 class TabContents;
 
-class ImageBurnUIHTMLSource : public ChromeURLDataManager::DataSource {
- public:
-  ImageBurnUIHTMLSource();
-
-  // Called when the network layer has requested a resource underneath
-  // the path we registered.
-  virtual void StartDataRequest(const std::string& path,
-                                 bool is_off_the_record,
-                                 int request_id);
-  virtual std::string GetMimeType(const std::string&) const {
-    return "text/html";
-  }
-
- private:
-  ~ImageBurnUIHTMLSource() {}
-
-  DISALLOW_COPY_AND_ASSIGN(ImageBurnUIHTMLSource);
-};
-
-class ImageBurnHandler : public DOMMessageHandler,
+class ImageBurnHandler : public WebUIMessageHandler,
                          public chromeos::MountLibrary::Observer,
                          public chromeos::BurnLibrary::Observer,
                          public DownloadManager::Observer,
@@ -69,8 +41,8 @@
   explicit ImageBurnHandler(TabContents* contents);
   virtual ~ImageBurnHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // chromeos::MountLibrary::Observer interface
@@ -137,27 +109,6 @@
   DISALLOW_COPY_AND_ASSIGN(ImageBurnHandler);
 };
 
-class ImageBurnTaskProxy
-    : public base::RefCountedThreadSafe<ImageBurnTaskProxy> {
- public:
-  explicit ImageBurnTaskProxy(const base::WeakPtr<ImageBurnHandler>& handler);
-
-  bool ReportDownloadInitialized();
-  bool CheckDownloadFinished();
-  void BurnImage();
-  void FinalizeBurn(bool success);
-
-  void CreateImageUrl(TabContents* tab_contents, ImageBurnHandler* downloader);
-
- private:
-  base::WeakPtr<ImageBurnHandler> handler_;
-  ImageBurnResourceManager* resource_manager_;
-
-  friend class base::RefCountedThreadSafe<ImageBurnTaskProxy>;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageBurnTaskProxy);
-};
-
 class ImageBurnResourceManager : public DownloadManager::Observer,
                                  public DownloadItem::Observer {
  public:
@@ -216,11 +167,12 @@
   DISALLOW_COPY_AND_ASSIGN(ImageBurnResourceManager);
 };
 
-class ImageBurnUI : public DOMUI {
+class ImageBurnUI : public WebUI {
  public:
   explicit ImageBurnUI(TabContents* contents);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ImageBurnUI);
 };
+
 #endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_IMAGEBURNER_UI_H_
diff --git a/chrome/browser/chromeos/dom_ui/internet_options_handler.cc b/chrome/browser/chromeos/dom_ui/internet_options_handler.cc
index 1b37cea..ac460b3 100644
--- a/chrome/browser/chromeos/dom_ui/internet_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/internet_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,10 @@
 
 #include <ctype.h>
 
+#include <map>
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/base64.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
@@ -23,9 +22,9 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/login/ownership_service.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/status/network_menu.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/window.h"
 #include "chrome/common/time_format.h"
@@ -34,8 +33,10 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
-#include "views/window/window.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "views/window/window.h"
 
 static const char kOtherNetworksFakePath[] = "?";
 
@@ -75,9 +76,9 @@
 void InternetOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  // Internet page - ChromeOS
-  localized_strings->SetString("internetPage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_INTERNET_TAB_LABEL));
+
+  RegisterTitle(localized_strings, "internetPage",
+                IDS_OPTIONS_INTERNET_TAB_LABEL);
 
   localized_strings->SetString("wired_title",
       l10n_util::GetStringUTF16(
@@ -143,6 +144,9 @@
       l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_HARDWARE_ADDRESS));
 
+  localized_strings->SetString("accessLockedMsg",
+      l10n_util::GetStringUTF16(
+          IDS_STATUSBAR_NETWORK_LOCKED));
   localized_strings->SetString("inetSsid",
       l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID));
@@ -305,30 +309,30 @@
 
 void InternetOptionsHandler::RegisterMessages() {
   // Setup handlers specific to this panel.
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("buttonClickCallback",
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("buttonClickCallback",
       NewCallback(this, &InternetOptionsHandler::ButtonClickCallback));
-  dom_ui_->RegisterMessageCallback("refreshCellularPlan",
+  web_ui_->RegisterMessageCallback("refreshCellularPlan",
       NewCallback(this, &InternetOptionsHandler::RefreshCellularPlanCallback));
-  dom_ui_->RegisterMessageCallback("loginToNetwork",
+  web_ui_->RegisterMessageCallback("loginToNetwork",
       NewCallback(this, &InternetOptionsHandler::LoginCallback));
-  dom_ui_->RegisterMessageCallback("loginToCertNetwork",
+  web_ui_->RegisterMessageCallback("loginToCertNetwork",
       NewCallback(this, &InternetOptionsHandler::LoginCertCallback));
-  dom_ui_->RegisterMessageCallback("loginToOtherNetwork",
+  web_ui_->RegisterMessageCallback("loginToOtherNetwork",
       NewCallback(this, &InternetOptionsHandler::LoginToOtherCallback));
-  dom_ui_->RegisterMessageCallback("setDetails",
+  web_ui_->RegisterMessageCallback("setDetails",
       NewCallback(this, &InternetOptionsHandler::SetDetailsCallback));
-  dom_ui_->RegisterMessageCallback("enableWifi",
+  web_ui_->RegisterMessageCallback("enableWifi",
       NewCallback(this, &InternetOptionsHandler::EnableWifiCallback));
-  dom_ui_->RegisterMessageCallback("disableWifi",
+  web_ui_->RegisterMessageCallback("disableWifi",
       NewCallback(this, &InternetOptionsHandler::DisableWifiCallback));
-  dom_ui_->RegisterMessageCallback("enableCellular",
+  web_ui_->RegisterMessageCallback("enableCellular",
       NewCallback(this, &InternetOptionsHandler::EnableCellularCallback));
-  dom_ui_->RegisterMessageCallback("disableCellular",
+  web_ui_->RegisterMessageCallback("disableCellular",
       NewCallback(this, &InternetOptionsHandler::DisableCellularCallback));
-  dom_ui_->RegisterMessageCallback("buyDataPlan",
+  web_ui_->RegisterMessageCallback("buyDataPlan",
       NewCallback(this, &InternetOptionsHandler::BuyDataPlanCallback));
-  dom_ui_->RegisterMessageCallback("showMorePlanInfo",
+  web_ui_->RegisterMessageCallback("showMorePlanInfo",
       NewCallback(this, &InternetOptionsHandler::BuyDataPlanCallback));
 }
 
@@ -357,10 +361,10 @@
 }
 
 void InternetOptionsHandler::BuyDataPlanCallback(const ListValue* args) {
-  if (!dom_ui_)
+  if (!web_ui_)
     return;
   Browser* browser = BrowserList::FindBrowserWithFeature(
-      dom_ui_->GetProfile(), Browser::FEATURE_TABSTRIP);
+      web_ui_->GetProfile(), Browser::FEATURE_TABSTRIP);
   if (browser)
     browser->OpenMobilePlanTabAndActivate();
 }
@@ -369,13 +373,13 @@
     chromeos::NetworkLibrary* cros) {
   DictionaryValue dictionary;
   FillNetworkInfo(&dictionary, cros);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.InternetOptions.refreshNetworkData", dictionary);
 }
 
 void InternetOptionsHandler::OnNetworkManagerChanged(
     chromeos::NetworkLibrary* cros) {
-  if (!dom_ui_)
+  if (!web_ui_)
     return;
   MonitorActiveNetwork(cros);
   RefreshNetworkData(cros);
@@ -384,7 +388,7 @@
 void InternetOptionsHandler::OnNetworkChanged(
     chromeos::NetworkLibrary* cros,
     const chromeos::Network* network) {
-  if (dom_ui_)
+  if (web_ui_)
     RefreshNetworkData(cros);
 }
 
@@ -410,7 +414,7 @@
 
 void InternetOptionsHandler::OnCellularDataPlanChanged(
     chromeos::NetworkLibrary* obj) {
-  if (!dom_ui_)
+  if (!web_ui_)
     return;
   const chromeos::CellularNetwork* cellular = obj->cellular_network();
   if (!cellular)
@@ -428,7 +432,7 @@
   connection_plans.SetBoolean("activated",
       cellular->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED);
   connection_plans.Set("plans", plan_list);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.InternetOptions.updateCellularPlans", connection_plans);
 }
 
@@ -455,7 +459,7 @@
     return;
   }
 
-  if (!chromeos::OwnershipService::GetSharedInstance()->CurrentUserIsOwner()) {
+  if (!chromeos::UserManager::Get()->current_user_is_owner()) {
     LOG(WARNING) << "Non-owner tried to change a network.";
     return;
   }
@@ -564,7 +568,7 @@
     }
   }
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.InternetOptions.showDetailedInfo", dictionary);
 }
 
@@ -721,7 +725,7 @@
 
   // TODO(beng): This is an improper direct dependency on Browser. Route this
   // through some sort of delegate.
-  Browser* browser = BrowserList::FindBrowserWithProfile(dom_ui_->GetProfile());
+  Browser* browser = BrowserList::FindBrowserWithProfile(web_ui_->GetProfile());
   views::Window* window = browser::CreateViewsWindow(
       browser->window()->GetNativeHandle(), gfx::Rect(), view);
   window->SetIsAlwaysOnTop(true);
@@ -762,8 +766,7 @@
       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
   chromeos::WifiNetwork* network;
   if (command == "forget") {
-    if (!chromeos::OwnershipService::GetSharedInstance()->
-        CurrentUserIsOwner()) {
+    if (!chromeos::UserManager::Get()->current_user_is_owner()) {
       LOG(WARNING) << "Non-owner tried to forget a network.";
       return;
     }
@@ -781,7 +784,7 @@
           } else {
             DictionaryValue dictionary;
             dictionary.SetString("servicePath", network->service_path());
-            dom_ui_->CallJavascriptFunction(
+            web_ui_->CallJavascriptFunction(
                 L"options.InternetOptions.showPasswordEntry", dictionary);
           }
         } else {
@@ -885,7 +888,7 @@
   network->Append(Value::CreateBooleanValue(connecting));
   // 6) icon data url
   network->Append(Value::CreateStringValue(icon.isNull() ? "" :
-      dom_ui_util::GetImageDataUrl(icon)));
+      web_ui_util::GetImageDataUrl(icon)));
   // 7) remembered
   network->Append(Value::CreateBooleanValue(remembered));
   // 8) activation state
@@ -996,27 +999,61 @@
   return list;
 }
 
+std::string GetWifiUniqueIdentifier(const chromeos::WifiNetwork* wifi) {
+  return wifi->encryption() + "|" + wifi->name();
+}
+
 ListValue* InternetOptionsHandler::GetRememberedList() {
   chromeos::NetworkLibrary* cros =
       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
   ListValue* list = new ListValue();
 
-  const chromeos::WifiNetworkVector& wifi_networks =
+  const chromeos::WifiNetworkVector& remembered_wifi_networks =
       cros->remembered_wifi_networks();
-  for (chromeos::WifiNetworkVector::const_iterator it =
-      wifi_networks.begin(); it != wifi_networks.end(); ++it) {
-    SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0_BLACK);
-    if ((*it)->encrypted()) {
+  const chromeos::WifiNetworkVector& wifi_networks =
+      cros->wifi_networks();
+
+  // The remembered networks from libcros/flimflam don't include the signal
+  // strength, so fall back to the detected networks for this data.  We
+  // consider networks to be the same if they have the same name and encryption
+  // type, so create a map of detected networks indexed by name + encryption.
+  std::map<std::string, chromeos::WifiNetwork*> wifi_map;
+  for (chromeos::WifiNetworkVector::const_iterator it = wifi_networks.begin();
+       it != wifi_networks.end(); ++it) {
+    wifi_map[GetWifiUniqueIdentifier(*it)] = *it;
+  }
+
+  for (chromeos::WifiNetworkVector::const_iterator rit =
+           remembered_wifi_networks.begin();
+       rit != remembered_wifi_networks.end(); ++rit) {
+    chromeos::WifiNetwork* wifi = *rit;
+    // Check if this remembered network has a matching detected network.
+    std::map<std::string, chromeos::WifiNetwork*>::const_iterator it =
+        wifi_map.find(GetWifiUniqueIdentifier(wifi));
+    bool found = it != wifi_map.end();
+
+    // Don't show the active network in the remembered list.
+    if (found && (it->second)->connected())
+      continue;
+    SkBitmap icon;
+    if (found)
+      icon = chromeos::NetworkMenu::IconForNetworkStrength(it->second, true);
+    else
+      icon = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0_BLACK);
+    // Place the secure badge on the icon if the remembered network is
+    // encrypted (the matching detected network, if any, will have the same
+    // encrypted property by definition).
+    if (wifi->encrypted()) {
       icon = chromeos::NetworkMenu::IconForDisplay(icon,
           *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
     }
     list->Append(GetNetwork(
-        (*it)->service_path(),
+        wifi->service_path(),
         icon,
-        (*it)->name(),
-        (*it)->connecting(),
-        (*it)->connected(),
+        wifi->name(),
+        wifi->connecting(),
+        wifi->connected(),
         true,
         chromeos::TYPE_WIFI,
         true,
@@ -1028,6 +1065,7 @@
 
 void InternetOptionsHandler::FillNetworkInfo(
     DictionaryValue* dictionary, chromeos::NetworkLibrary* cros) {
+  dictionary->SetBoolean("accessLocked", cros->IsLocked());
   dictionary->Set("wiredList", GetWiredList());
   dictionary->Set("wirelessList", GetWirelessList());
   dictionary->Set("rememberedList", GetRememberedList());
diff --git a/chrome/browser/chromeos/dom_ui/internet_options_handler.h b/chrome/browser/chromeos/dom_ui/internet_options_handler.h
index 7b857ff..f72d9cc 100644
--- a/chrome/browser/chromeos/dom_ui/internet_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/internet_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,7 +28,7 @@
   // OptionsUIHandler implementation.
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // NetworkLibrary::NetworkManagerObserver implementation.
@@ -121,7 +121,7 @@
   // If any network is currently active, this is its service path.
   std::string active_network_;
 
-  // A boolean flag of whether to use DOMUI for connect UI. True to use DOMUI
+  // A boolean flag of whether to use WebUI for connect UI. True to use WebUI
   // and false to use Views dialogs.
   bool use_settings_ui_;
 
diff --git a/chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.cc b/chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.cc
index 9a2c0ce..2ceb0ff 100644
--- a/chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/values.h"
 #include "base/weak_ptr.h"
@@ -14,11 +12,15 @@
 #include "chrome/browser/chromeos/cros/input_method_library.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "third_party/cros/chromeos_input_method.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 
 class KeyboardOverlayUIHTMLSource : public ChromeURLDataManager::DataSource {
@@ -43,14 +45,14 @@
 
 // The handler for Javascript messages related to the "keyboardoverlay" view.
 class KeyboardOverlayHandler
-    : public DOMMessageHandler,
+    : public WebUIMessageHandler,
       public base::SupportsWeakPtr<KeyboardOverlayHandler> {
  public:
   KeyboardOverlayHandler();
   virtual ~KeyboardOverlayHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
  private:
@@ -80,6 +82,8 @@
       l10n_util::GetStringUTF16(IDS_KEYBOARD_OVERLAY_TITLE));
   localized_strings.SetString("keyboardOverlayInstructions",
       l10n_util::GetStringUTF16(IDS_KEYBOARD_OVERLAY_INSTRUCTIONS));
+  localized_strings.SetString("keyboardOverlayInstructionsHide",
+      l10n_util::GetStringUTF16(IDS_KEYBOARD_OVERLAY_INSTRUCTIONS_HIDE));
   localized_strings.SetString("keyboardOverlayActivateLastTab",
       l10n_util::GetStringUTF16(IDS_KEYBOARD_OVERLAY_ACTIVATE_LAST_TAB));
   localized_strings.SetString("keyboardOverlayActivateNextTab",
@@ -258,25 +262,25 @@
 KeyboardOverlayHandler::~KeyboardOverlayHandler() {
 }
 
-DOMMessageHandler* KeyboardOverlayHandler::Attach(DOMUI* dom_ui) {
-  return DOMMessageHandler::Attach(dom_ui);
+WebUIMessageHandler* KeyboardOverlayHandler::Attach(WebUI* web_ui) {
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void KeyboardOverlayHandler::RegisterMessages() {
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("getKeyboardOverlayId",
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("getKeyboardOverlayId",
       NewCallback(this, &KeyboardOverlayHandler::GetKeyboardOverlayId));
 }
 
 void KeyboardOverlayHandler::GetKeyboardOverlayId(const ListValue* args) {
-  const chromeos::InputMethodLibrary* library =
+  chromeos::InputMethodLibrary* library =
       chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
   const chromeos::InputMethodDescriptor& descriptor =
       library->current_input_method();
   const std::string keyboard_overlay_id =
-      chromeos::input_method::GetKeyboardOverlayId(descriptor.id);
+      library->GetKeyboardOverlayId(descriptor.id);
   StringValue param(keyboard_overlay_id);
-  dom_ui_->CallJavascriptFunction(L"initKeyboardOverlayId", param);
+  web_ui_->CallJavascriptFunction(L"initKeyboardOverlayId", param);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -292,10 +296,5 @@
   KeyboardOverlayUIHTMLSource* html_source = new KeyboardOverlayUIHTMLSource();
 
   // Set up the chrome://keyboardoverlay/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/chromeos/dom_ui/language_chewing_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_chewing_options_handler.cc
index 6f1eed3..234718a 100644
--- a/chrome/browser/chromeos/dom_ui/language_chewing_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_chewing_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <limits>
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/chromeos/dom_ui/language_options_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 const char kI18nPrefix[] = "Chewing_";
@@ -30,7 +30,10 @@
 void LanguageChewingOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  // Language Chewing page - ChromeOS
+
+  RegisterTitle(localized_strings, "languageChewingPage",
+                IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTINGS_TITLE);
+
   for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
     localized_strings->SetString(
         GetI18nContentValue(language_prefs::kChewingBooleanPrefs[i],
diff --git a/chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.cc b/chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.cc
index 56e4448..0104b6e 100644
--- a/chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/values.h"
 #include "grit/generated_resources.h"
 #include "third_party/cros/chromeos_keyboard.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 const struct ModifierKeysSelectItem {
diff --git a/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc
index 46a8e2d..d9a476a 100644
--- a/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
@@ -21,7 +21,10 @@
 void LanguageHangulOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  // Language Hangul page - ChromeOS
+
+  RegisterTitle(localized_strings, "languageHangulPage",
+                IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_TITLE);
+
   localized_strings->SetString("hangul_keyboard_layout",
       l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_KEYBOARD_LAYOUT_TEXT));
 
diff --git a/chrome/browser/chromeos/dom_ui/language_mozc_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_mozc_options_handler.cc
index 7015dd9..aefa2dd 100644
--- a/chrome/browser/chromeos/dom_ui/language_mozc_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_mozc_options_handler.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/language_mozc_options_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/dom_ui/language_options_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 const char kI18nPrefix[] = "mozc_";
@@ -27,7 +27,10 @@
 void LanguageMozcOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  // Language Mozc page - ChromeOS
+
+  RegisterTitle(localized_strings, "languageMozcPage",
+                IDS_OPTIONS_SETTINGS_LANGUAGES_MOZC_SETTINGS_TITLE);
+
   for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
     localized_strings->SetString(
         GetI18nContentValue(language_prefs::kMozcBooleanPrefs[i], kI18nPrefix),
diff --git a/chrome/browser/chromeos/dom_ui/language_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_options_handler.cc
deleted file mode 100644
index b4c1b19..0000000
--- a/chrome/browser/chromeos/dom_ui/language_options_handler.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/dom_ui/language_options_handler.h"
-
-#include <map>
-#include <set>
-#include <string>
-#include <utility>
-
-#include "app/l10n_util.h"
-#include "base/basictypes.h"
-#include "base/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/spellcheck_common.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-namespace chromeos {
-
-LanguageOptionsHandler::LanguageOptionsHandler() {
-}
-
-LanguageOptionsHandler::~LanguageOptionsHandler() {
-}
-
-void LanguageOptionsHandler::GetLocalizedValues(
-    DictionaryValue* localized_strings) {
-  DCHECK(localized_strings);
-  localized_strings->SetString("languagePage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_DIALOG_TITLE));
-  localized_strings->SetString("add_button",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_BUTTON));
-  localized_strings->SetString("configure",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE));
-  localized_strings->SetString("input_method",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD));
-  localized_strings->SetString("languages",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES));
-  localized_strings->SetString("please_add_another_input_method",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_INPUT_METHOD));
-  localized_strings->SetString("please_add_another_language",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_LANGUAGE));
-  localized_strings->SetString("ok_button", l10n_util::GetStringUTF16(IDS_OK));
-  localized_strings->SetString("remove_button",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON));
-  localized_strings->SetString("sign_out_button",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON));
-  localized_strings->SetString("add_language_instructions",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_INSTRUCTIONS));
-  localized_strings->SetString("input_method_instructions",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD_INSTRUCTIONS));
-  localized_strings->SetString("switch_input_methods_hint",
-      l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_SWITCH_INPUT_METHODS_HINT,
-          ASCIIToUTF16("alt+shift")));
-  localized_strings->SetString("select_previous_input_method_hint",
-      l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_SELECT_PREVIOUS_INPUT_METHOD_HINT,
-          ASCIIToUTF16("ctrl+space")));
-  localized_strings->SetString("cannot_be_displayed_in_this_language",
-      l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
-  localized_strings->SetString("is_displayed_in_this_language",
-      l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
-  localized_strings->SetString("display_in_this_language",
-      l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
-  localized_strings->SetString("sign_out_required",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_RESTART_REQUIRED));
-  localized_strings->SetString("this_language_is_currently_in_use",
-      l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_THIS_LANGUAGE_IS_CURRENTLY_IN_USE,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
-  localized_strings->SetString("use_this_for_spell_checking",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_USE_THIS_FOR_SPELL_CHECKING));
-  localized_strings->SetString("cannot_be_used_for_spell_checking",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_CANNOT_BE_USED_FOR_SPELL_CHECKING));
-  localized_strings->SetString("is_used_for_spell_checking",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_IS_USED_FOR_SPELL_CHECKING));
-
-  // GetSupportedInputMethods() never return NULL.
-  scoped_ptr<InputMethodDescriptors> descriptors(
-      CrosLibrary::Get()->GetInputMethodLibrary()->GetSupportedInputMethods());
-
-  // The followigns are resources, rather than local strings.
-  localized_strings->SetString("currentUiLanguageCode",
-      g_browser_process->GetApplicationLocale());
-  localized_strings->Set("inputMethodList", GetInputMethodList(*descriptors));
-  localized_strings->Set("languageList", GetLanguageList(*descriptors));
-  localized_strings->Set("spellCheckLanguageCodeSet",
-                         GetSpellCheckLanguageCodeSet());
-  localized_strings->Set("uiLanguageCodeSet", GetUiLanguageCodeSet());
-}
-
-void LanguageOptionsHandler::RegisterMessages() {
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("inputMethodDisable",
-      NewCallback(this, &LanguageOptionsHandler::InputMethodDisableCallback));
-  dom_ui_->RegisterMessageCallback("inputMethodEnable",
-      NewCallback(this, &LanguageOptionsHandler::InputMethodEnableCallback));
-  dom_ui_->RegisterMessageCallback("inputMethodOptionsOpen",
-      NewCallback(this,
-                  &LanguageOptionsHandler::InputMethodOptionsOpenCallback));
-  dom_ui_->RegisterMessageCallback("languageOptionsOpen",
-      NewCallback(this, &LanguageOptionsHandler::LanguageOptionsOpenCallback));
-  dom_ui_->RegisterMessageCallback("spellCheckLanguageChange",
-      NewCallback(this,
-                  &LanguageOptionsHandler::SpellCheckLanguageChangeCallback));
-  dom_ui_->RegisterMessageCallback("uiLanguageChange",
-      NewCallback(this, &LanguageOptionsHandler::UiLanguageChangeCallback));
-  dom_ui_->RegisterMessageCallback("uiLanguageSignOut",
-      NewCallback(this, &LanguageOptionsHandler::SignOutCallback));
-}
-
-ListValue* LanguageOptionsHandler::GetInputMethodList(
-    const InputMethodDescriptors& descriptors) {
-  ListValue* input_method_list = new ListValue();
-
-  for (size_t i = 0; i < descriptors.size(); ++i) {
-    const InputMethodDescriptor& descriptor = descriptors[i];
-    const std::string language_code =
-        input_method::GetLanguageCodeFromDescriptor(descriptor);
-    const std::string display_name =
-        input_method::GetInputMethodDisplayNameFromId(descriptor.id);
-
-    DictionaryValue* dictionary = new DictionaryValue();
-    dictionary->SetString("id", descriptor.id);
-    dictionary->SetString("displayName", display_name);
-
-    // One input method can be associated with multiple languages, hence
-    // we use a dictionary here.
-    DictionaryValue* language_codes = new DictionaryValue();
-    language_codes->SetBoolean(language_code, true);
-    // Check kExtraLanguages to see if there are languages associated with
-    // this input method. If these are present, add these.
-    for (size_t j = 0; j < arraysize(input_method::kExtraLanguages); ++j) {
-      const std::string extra_input_method_id =
-          input_method::kExtraLanguages[j].input_method_id;
-      const std::string extra_language_code =
-          input_method::kExtraLanguages[j].language_code;
-      if (extra_input_method_id == descriptor.id) {
-        language_codes->SetBoolean(extra_language_code, true);
-      }
-    }
-    dictionary->Set("languageCodeSet", language_codes);
-
-    input_method_list->Append(dictionary);
-  }
-
-  return input_method_list;
-}
-
-ListValue* LanguageOptionsHandler::GetLanguageList(
-    const InputMethodDescriptors& descriptors) {
-  std::set<std::string> language_codes;
-  // Collect the language codes from the supported input methods.
-  for (size_t i = 0; i < descriptors.size(); ++i) {
-    const InputMethodDescriptor& descriptor = descriptors[i];
-    const std::string language_code =
-        input_method::GetLanguageCodeFromDescriptor(descriptor);
-    language_codes.insert(language_code);
-  }
-  // Collect the language codes from kExtraLanguages.
-  for (size_t i = 0; i < arraysize(input_method::kExtraLanguages); ++i) {
-    const char* language_code =
-        input_method::kExtraLanguages[i].language_code;
-    language_codes.insert(language_code);
-  }
-
-  // Map of display name -> {language code, native_display_name}.
-  // In theory, we should be able to create a map that is sorted by
-  // display names using ICU comparator, but doing it is hard, thus we'll
-  // use an auxiliary vector to achieve the same result.
-  typedef std::pair<std::string, string16> LanguagePair;
-  typedef std::map<string16, LanguagePair> LanguageMap;
-  LanguageMap language_map;
-  // The auxiliary vector mentioned above.
-  std::vector<string16> display_names;
-
-  // Build the list of display names, and build the language map.
-  for (std::set<std::string>::const_iterator iter = language_codes.begin();
-       iter != language_codes.end(); ++iter) {
-    const string16 display_name =
-        input_method::GetLanguageDisplayNameFromCode(*iter);
-    const string16 native_display_name =
-        input_method::GetLanguageNativeDisplayNameFromCode(*iter);
-    display_names.push_back(display_name);
-    language_map[display_name] =
-        std::make_pair(*iter, native_display_name);
-  }
-  DCHECK_EQ(display_names.size(), language_map.size());
-
-  // Sort display names using locale specific sorter.
-  l10n_util::SortStrings16(g_browser_process->GetApplicationLocale(),
-                           &display_names);
-
-  // Build the language list from the language map.
-  ListValue* language_list = new ListValue();
-  for (size_t i = 0; i < display_names.size(); ++i) {
-    const LanguagePair& pair = language_map[display_names[i]];
-    DictionaryValue* dictionary = new DictionaryValue();
-    dictionary->SetString("code",  pair.first);
-    dictionary->SetString("displayName", display_names[i]);
-    dictionary->SetString("nativeDisplayName", pair.second);
-    language_list->Append(dictionary);
-  }
-
-  return language_list;
-}
-
-DictionaryValue* LanguageOptionsHandler::GetUiLanguageCodeSet() {
-  DictionaryValue* dictionary = new DictionaryValue();
-  const std::vector<std::string>& available_locales =
-      l10n_util::GetAvailableLocales();
-  for (size_t i = 0; i < available_locales.size(); ++i) {
-    dictionary->SetBoolean(available_locales[i], true);
-  }
-  return dictionary;
-}
-
-DictionaryValue* LanguageOptionsHandler::GetSpellCheckLanguageCodeSet() {
-  DictionaryValue* dictionary = new DictionaryValue();
-  std::vector<std::string> spell_check_languages;
-  SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
-  for (size_t i = 0; i < spell_check_languages.size(); ++i) {
-    dictionary->SetBoolean(spell_check_languages[i], true);
-  }
-  return dictionary;
-}
-
-void LanguageOptionsHandler::InputMethodDisableCallback(
-    const ListValue* args) {
-  const std::string input_method_id = WideToASCII(ExtractStringValue(args));
-  const std::string action = StringPrintf(
-      "LanguageOptions_DisableInputMethod_%s", input_method_id.c_str());
-  UserMetrics::RecordComputedAction(action);
-}
-
-void LanguageOptionsHandler::InputMethodEnableCallback(
-    const ListValue* args) {
-  const std::string input_method_id = WideToASCII(ExtractStringValue(args));
-  const std::string action = StringPrintf(
-      "LanguageOptions_EnableInputMethod_%s", input_method_id.c_str());
-  UserMetrics::RecordComputedAction(action);
-}
-
-void LanguageOptionsHandler::InputMethodOptionsOpenCallback(
-    const ListValue* args) {
-  const std::string input_method_id = WideToASCII(ExtractStringValue(args));
-  const std::string action = StringPrintf(
-      "InputMethodOptions_Open_%s", input_method_id.c_str());
-  UserMetrics::RecordComputedAction(action);
-}
-
-void LanguageOptionsHandler::LanguageOptionsOpenCallback(
-    const ListValue* args) {
-  UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Open"));
-}
-
-void LanguageOptionsHandler::UiLanguageChangeCallback(
-    const ListValue* args) {
-  const std::string language_code = WideToASCII(ExtractStringValue(args));
-  CHECK(!language_code.empty());
-  const std::string action = StringPrintf(
-      "LanguageOptions_UiLanguageChange_%s", language_code.c_str());
-  UserMetrics::RecordComputedAction(action);
-
-  // We maintain kApplicationLocale property in both a global storage
-  // and user's profile.  Global property determines locale of login screen,
-  // while user's profile determines his personal locale preference.
-  PrefService* prefs[] = {
-      g_browser_process->local_state(),
-      dom_ui_->GetProfile()->GetPrefs()
-  };
-  for (size_t i = 0; i < arraysize(prefs); ++i) {
-    prefs[i]->SetString(prefs::kApplicationLocale, language_code);
-    prefs[i]->SavePersistentPrefs();
-  }
-  dom_ui_->CallJavascriptFunction(
-      L"options.LanguageOptions.uiLanguageSaved");
-}
-
-void LanguageOptionsHandler::SpellCheckLanguageChangeCallback(
-    const ListValue* args) {
-  const std::string language_code = WideToASCII(ExtractStringValue(args));
-  CHECK(!language_code.empty());
-  const std::string action = StringPrintf(
-      "LanguageOptions_SpellCheckLanguageChange_%s", language_code.c_str());
-  UserMetrics::RecordComputedAction(action);
-}
-
-void LanguageOptionsHandler::SignOutCallback(const ListValue* args) {
-  UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_SignOut"));
-
-  Browser* browser = Browser::GetBrowserForController(
-      &dom_ui_->tab_contents()->controller(), NULL);
-  if (browser)
-    browser->ExecuteCommand(IDC_EXIT);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/language_options_handler.h b/chrome/browser/chromeos/dom_ui/language_options_handler.h
deleted file mode 100644
index ecb8d34..0000000
--- a/chrome/browser/chromeos/dom_ui/language_options_handler.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_OPTIONS_HANDLER_H_
-#define CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_OPTIONS_HANDLER_H_
-#pragma once
-
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/dom_ui/options/options_ui.h"
-
-class DictionaryValue;
-class ListValue;
-
-namespace chromeos {
-
-// ChromeOS language options page UI handler.
-class LanguageOptionsHandler : public OptionsPageUIHandler {
- public:
-  LanguageOptionsHandler();
-  virtual ~LanguageOptionsHandler();
-
-  // OptionsUIHandler implementation.
-  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
-
-  // DOMMessageHandler implementation.
-  virtual void RegisterMessages();
-
-  // The following static methods are public for ease of testing.
-
-  // Gets the list of input methods from the given input descriptors.
-  // The return value will look like:
-  // [{'id': 'pinyin', 'displayName': 'Pinyin',
-  //   'languageCodeSet': {'zh-CW': true}},  ...]
-  //
-  // Note that true in languageCodeSet does not mean anything. We just use
-  // the dictionary as a set.
-  static ListValue* GetInputMethodList(
-      const InputMethodDescriptors& descriptors);
-
-  // Gets the list of languages from the given input descriptors.
-  // The return value will look like:
-  // [{'code': 'fi', 'displayName': 'Finnish', 'nativeDisplayName': 'suomi'},
-  //  ...]
-  static ListValue* GetLanguageList(const InputMethodDescriptors& descriptors);
-
-  // Gets the set of language codes that can be used as UI language.
-  // The return value will look like:
-  // {'en-US': true, 'fi': true, 'fr': true, ...}
-  //
-  // Note that true in values does not mean anything. We just use the
-  // dictionary as a set.
-  static DictionaryValue* GetUiLanguageCodeSet();
-
-  // Gets the set of language codes that can be used for spellchecking.
-  // The return value will look like:
-  // {'en-US': true, 'fi': true, 'fr': true, ...}
-  //
-  // Note that true in values does not mean anything. We just use the
-  // dictionary as a set.
-  static DictionaryValue* GetSpellCheckLanguageCodeSet();
-
- private:
-  // Called when the input method is disabled.
-  // |args| will contain the input method ID as string (ex. "mozc").
-  void InputMethodDisableCallback(const ListValue* args);
-
-  // Called when the input method is enabled.
-  // |args| will contain the input method ID as string (ex. "mozc").
-  void InputMethodEnableCallback(const ListValue* args);
-
-  // Called when the input method options page is opened.
-  // |args| will contain the input method ID as string (ex. "mozc").
-  void InputMethodOptionsOpenCallback(const ListValue* args);
-
-  // Called when the language options is opened.
-  void LanguageOptionsOpenCallback(const ListValue* args);
-
-  // Called when the UI language is changed.
-  // |args| will contain the language code as string (ex. "fr").
-  void UiLanguageChangeCallback(const ListValue* args);
-
-  // Called when the spell check language is changed.
-  // |args| will contain the language code as string (ex. "fr").
-  void SpellCheckLanguageChangeCallback(const ListValue* args);
-
-  // Called when the sign out button is clicked.
-  void SignOutCallback(const ListValue* args);
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageOptionsHandler);
-};
-
-}  // namespace
-
-#endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/chromeos/dom_ui/language_options_handler_unittest.cc b/chrome/browser/chromeos/dom_ui/language_options_handler_unittest.cc
deleted file mode 100644
index ddf58b7..0000000
--- a/chrome/browser/chromeos/dom_ui/language_options_handler_unittest.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/dom_ui/language_options_handler.h"
-
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "base/values.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromeos {
-
-static InputMethodDescriptors CreateInputMethodDescriptors() {
-  InputMethodDescriptors descriptors;
-  descriptors.push_back(
-      InputMethodDescriptor("xkb:us::eng", "USA", "us", "eng"));
-  descriptors.push_back(
-      InputMethodDescriptor("xkb:fr::fra", "France", "fr", "fra"));
-  descriptors.push_back(
-      InputMethodDescriptor("xkb:be::fra", "Belgium", "be", "fr"));
-  descriptors.push_back(
-      InputMethodDescriptor("mozc", "Mozc (US keyboard layout)", "us", "ja"));
-  return descriptors;
-}
-
-TEST(LanguageOptionsHandlerTest, GetInputMethodList) {
-  // Use the stub libcros. The object will take care of the cleanup.
-  ScopedStubCrosEnabler stub_cros_enabler;
-
-  // Reset the library implementation so it will be initialized
-  // again. Otherwise, non-stub implementation can be reused, if it's
-  // already initialized elsewhere, which results in a crash.
-  CrosLibrary::Get()->GetTestApi()->SetInputMethodLibrary(NULL, false);
-
-  InputMethodDescriptors descriptors = CreateInputMethodDescriptors();
-  scoped_ptr<ListValue> list(
-      LanguageOptionsHandler::GetInputMethodList(descriptors));
-  ASSERT_EQ(4U, list->GetSize());
-
-  DictionaryValue* entry = NULL;
-  DictionaryValue *language_code_set = NULL;
-  std::string input_method_id;
-  std::string display_name;
-  std::string language_code;
-
-  // As shown below, the list should be input method ids should appear in
-  // the same order of the descriptors.
-  ASSERT_TRUE(list->GetDictionary(0, &entry));
-  ASSERT_TRUE(entry->GetString("id", &input_method_id));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
-  EXPECT_EQ("xkb:us::eng", input_method_id);
-  // Commented out as it depends on translation in generated_resources.grd
-  // (i.e. makes the test fragile).
-  // EXPECT_EQ("English (USA) keyboard layout", display_name);
-  ASSERT_TRUE(language_code_set->HasKey("en-US"));
-  ASSERT_TRUE(language_code_set->HasKey("id"));  // From kExtraLanguages.
-  ASSERT_TRUE(language_code_set->HasKey("fil"));  // From kExtraLanguages.
-
-  ASSERT_TRUE(list->GetDictionary(1, &entry));
-  ASSERT_TRUE(entry->GetString("id", &input_method_id));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
-  EXPECT_EQ("xkb:fr::fra", input_method_id);
-  // Commented out. See above.
-  // EXPECT_EQ("French keyboard layout", display_name);
-  ASSERT_TRUE(language_code_set->HasKey("fr"));
-
-  ASSERT_TRUE(list->GetDictionary(2, &entry));
-  ASSERT_TRUE(entry->GetString("id", &input_method_id));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
-  EXPECT_EQ("xkb:be::fra", input_method_id);
-  // Commented out. See above.
-  // EXPECT_EQ("Belgian keyboard layout", display_name);
-  ASSERT_TRUE(language_code_set->HasKey("fr"));
-
-  ASSERT_TRUE(list->GetDictionary(3, &entry));
-  ASSERT_TRUE(entry->GetString("id", &input_method_id));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
-  EXPECT_EQ("mozc", input_method_id);
-  // Commented out. See above.
-  // EXPECT_EQ("Japanese input method (for US keyboard)", display_name);
-  ASSERT_TRUE(language_code_set->HasKey("ja"));
-}
-
-TEST(LanguageOptionsHandlerTest, GetLanguageList) {
-  InputMethodDescriptors descriptors = CreateInputMethodDescriptors();
-  scoped_ptr<ListValue> list(
-      LanguageOptionsHandler::GetLanguageList(descriptors));
-  ASSERT_EQ(6U, list->GetSize());
-
-  DictionaryValue* entry = NULL;
-  std::string language_code;
-  std::string display_name;
-  std::string native_display_name;
-
-  // As shown below, the list should be sorted by the display names,
-  // and these names should not have duplicates.
-  ASSERT_TRUE(list->GetDictionary(0, &entry));
-  ASSERT_TRUE(entry->GetString("code", &language_code));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
-  EXPECT_EQ("en-US", language_code);
-  EXPECT_EQ("English (United States)", display_name);
-  EXPECT_EQ("English (United States)", native_display_name);
-
-  // This comes from kExtraLanguages.
-  ASSERT_TRUE(list->GetDictionary(1, &entry));
-  ASSERT_TRUE(entry->GetString("code", &language_code));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
-  EXPECT_EQ("fil", language_code);
-  EXPECT_EQ("Filipino", display_name);
-  EXPECT_EQ("Filipino", native_display_name);
-
-  ASSERT_TRUE(list->GetDictionary(2, &entry));
-  ASSERT_TRUE(entry->GetString("code", &language_code));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
-  EXPECT_EQ("fr", language_code);
-  EXPECT_EQ("French", display_name);
-  EXPECT_EQ("fran\u00E7ais", native_display_name);
-
-  // This comes from kExtraLanguages.
-  ASSERT_TRUE(list->GetDictionary(3, &entry));
-  ASSERT_TRUE(entry->GetString("code", &language_code));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
-  EXPECT_EQ("id", language_code);
-  EXPECT_EQ("Indonesian", display_name);
-  EXPECT_EQ("Bahasa Indonesia", native_display_name);
-
-  ASSERT_TRUE(list->GetDictionary(4, &entry));
-  ASSERT_TRUE(entry->GetString("code", &language_code));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
-  EXPECT_EQ("ja", language_code);
-  EXPECT_EQ("Japanese", display_name);
-  EXPECT_EQ("\u65E5\u672C\u8A9E", native_display_name);
-
-  // This comes from kExtraLanguages.
-  ASSERT_TRUE(list->GetDictionary(5, &entry));
-  ASSERT_TRUE(entry->GetString("code", &language_code));
-  ASSERT_TRUE(entry->GetString("displayName", &display_name));
-  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
-  EXPECT_EQ("es-419", language_code);
-  EXPECT_EQ("Spanish (Latin America and the Caribbean)", display_name);
-  EXPECT_EQ("espa\u00F1ol (Latinoam\u00E9rica y el Caribe)",
-            native_display_name);
-}
-
-TEST(LanguageOptionsHandlerTest, GetUiLanguageCodeSet) {
-  scoped_ptr<DictionaryValue> dictionary(
-      LanguageOptionsHandler::GetUiLanguageCodeSet());
-  EXPECT_TRUE(dictionary->HasKey("en-US"));
-  // Note that we don't test a false case, as such an expectation will
-  // fail when we add support for the language.
-  // EXPECT_FALSE(dictionary->HasKey("no"));
-}
-
-TEST(LanguageOptionsHandlerTest, GetSpellCheckLanguageCodeSet) {
-  scoped_ptr<DictionaryValue> dictionary(
-      LanguageOptionsHandler::GetSpellCheckLanguageCodeSet());
-  EXPECT_TRUE(dictionary->HasKey("en-US"));
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/language_options_util.h b/chrome/browser/chromeos/dom_ui/language_options_util.h
index 718158f..a6a4837 100644
--- a/chrome/browser/chromeos/dom_ui/language_options_util.h
+++ b/chrome/browser/chromeos/dom_ui/language_options_util.h
@@ -8,10 +8,10 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/language_preferences.h"
+#include "ui/base/l10n/l10n_util.h"
 
 class ListValue;
 
diff --git a/chrome/browser/chromeos/dom_ui/language_pinyin_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_pinyin_options_handler.cc
index f2c1f0d..ab9790b 100644
--- a/chrome/browser/chromeos/dom_ui/language_pinyin_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_pinyin_options_handler.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/language_pinyin_options_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/dom_ui/language_options_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 const char kI18nPrefix[] = "Pinyin";
@@ -25,7 +25,10 @@
 void LanguagePinyinOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  // Language Pinyin page - ChromeOS
+
+  RegisterTitle(localized_strings, "languagePinyinPage",
+                IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTINGS_TITLE);
+
   for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
     localized_strings->SetString(
         GetI18nContentValue(language_prefs::kPinyinBooleanPrefs[i],
diff --git a/chrome/browser/chromeos/dom_ui/login/authenticator_facade.h b/chrome/browser/chromeos/dom_ui/login/authenticator_facade.h
index 0c6af1c..6aa20ef 100644
--- a/chrome/browser/chromeos/dom_ui/login/authenticator_facade.h
+++ b/chrome/browser/chromeos/dom_ui/login/authenticator_facade.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,19 +18,17 @@
 
 class LoginStatusConsumer;
 
-// AuthenticatorFacade operates as an interface between the DOMui login handling
+// AuthenticatorFacade operates as an interface between the WebUI login handling
 // layer and the authentication layer. This allows for using a stubbed version
 // of authentication during testing if needed. Also this allows for a clear
-// seperation between the DOMui login handling code and the code that deals with
+// seperation between the WebUI login handling code and the code that deals with
 // authentication.
 // What code will be compiled with what DEPS flags:
-// touchui == 0
+// touchui == 0 || chromeos == 0
 // AuthenticatorFacade is not compiled
-// touchui == 1 && chromeos == 0
-// AuthenticatorFacade is compiled in using the stubbed authentication code
 // touchui == 1 && chromes == 1
 // AuthenticatorFacade is compiled in using the functional authentication code
-// TODO(rharrison): Implement the real authentication code.
+// TODO(rharrison): Remove AuthenticatorFacade
 class AuthenticatorFacade {
  public:
   explicit AuthenticatorFacade(LoginStatusConsumer* consumer) :
diff --git a/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.cc b/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.cc
deleted file mode 100644
index 93b138b..0000000
--- a/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h"
-
-namespace chromeos {
-
-void AuthenticatorFacadeStub::AuthenticateToLogin(
-    Profile* profile,
-    const std::string& username,
-    const std::string& password,
-    const std::string& login_token,
-    const std::string& login_captcha) {
-  if (!expected_username_.compare(username) &&
-      !expected_password_.compare(password)) {
-    consumer_->OnLoginSuccess(username,
-                              password,
-                              credentials_,
-                              false);
-  } else {
-    GoogleServiceAuthError error(
-        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-    consumer_->OnLoginFailure(LoginFailure::FromNetworkAuthFailure(error));
-  }
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h b/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h
deleted file mode 100644
index b773dbb..0000000
--- a/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_LOGIN_AUTHENTICATOR_FACADE_STUB_H_
-#define CHROME_BROWSER_CHROMEOS_DOM_UI_LOGIN_AUTHENTICATOR_FACADE_STUB_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade.h"
-
-namespace chromeos {
-
-// This class is a stubbed out version of the authentication that is used for
-// functional testing of the LoginUI code. It takes in an expected user/pass
-// pair during construction, which is used for authentication. Any pair that
-// isn't the expected pair will fail authentication and the pair will pass.
-// TODO(rharrison): Once the functional authentication code is completed make
-// sure that this code isn't used in chromeos builds.
-class AuthenticatorFacadeStub : public AuthenticatorFacade {
- public:
-  AuthenticatorFacadeStub(LoginStatusConsumer* consumer,
-                          const std::string& expected_username,
-                          const std::string& expected_password) :
-      AuthenticatorFacade(consumer),
-      expected_username_(expected_username),
-      expected_password_(expected_password) {}
-  virtual ~AuthenticatorFacadeStub() {}
-
-  virtual void AuthenticateToLogin(Profile* profile,
-                                   const std::string& username,
-                                   const std::string& password,
-                                   const std::string& login_token,
-                                   const std::string& login_captcha);
-
- protected:
-  const std::string expected_username_;
-  const std::string expected_password_;
-  GaiaAuthConsumer::ClientLoginResult credentials_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AuthenticatorFacadeStub);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_LOGIN_AUTHENTICATOR_FACADE_STUB_H_
diff --git a/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub_unittest.cc b/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub_unittest.cc
deleted file mode 100644
index 4c8252a..0000000
--- a/chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub_unittest.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h"
-#include "chrome/browser/chromeos/dom_ui/login/mock_login_ui_handler.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-
-class LoginStatusConsumer;
-
-namespace {
-
-class AuthenticatorFacadeStubHarness
-    : public chromeos::AuthenticatorFacadeStub {
- public:
-  AuthenticatorFacadeStubHarness(chromeos::LoginStatusConsumer* consumer,
-                                 const std::string& username,
-                                 const std::string& password) :
-      chromeos::AuthenticatorFacadeStub(consumer,
-                                        username,
-                                        password) {}
-  const std::string GetUsername() const { return expected_username_; }
-  const std::string GetPassword() const { return expected_password_; }
-  chromeos::LoginStatusConsumer* GetConsumer() const { return consumer_; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AuthenticatorFacadeStubHarness);
-};
-
-}  // namespace
-
-namespace chromeos {
-
-// Setup Tests
-TEST(AuthenticatorFacadeStubTest, SetupSuccess) {
-  MockLoginUIHandler consumer;
-  std::string test_username("Test_User");
-  std::string test_password("Test_Password");
-  scoped_ptr<AuthenticatorFacadeStubHarness>
-      facade(new AuthenticatorFacadeStubHarness(&consumer,
-                                                test_username,
-                                                test_password));
-  ASSERT_EQ(&consumer, facade->GetConsumer());
-  ASSERT_EQ(test_username, facade->GetUsername());
-  ASSERT_EQ(test_password, facade->GetPassword());
-}
-
-// AuthenticateToLogin Tests
-TEST(AuthenticatorFacadeStubTest, AuthenticateToLoginSuccess) {
-  MockLoginUIHandler consumer;
-  std::string test_username("Test_User");
-  std::string test_password("Test_Password");
-  std::string test_token("Test_Token");
-  std::string test_captcha("Test_Captcha");
-  scoped_ptr<AuthenticatorFacadeStubHarness>
-      facade(new AuthenticatorFacadeStubHarness(&consumer,
-                                                test_username,
-                                                test_password));
-
-  EXPECT_CALL(consumer, OnLoginSuccess(test_username,
-                                       _,
-                                       _,
-                                       false))
-      .Times(1);
-
-  facade->AuthenticateToLogin(NULL,
-                              test_username,
-                              test_password,
-                              test_token,
-                              test_captcha);
-}
-
-TEST(AuthenticatorFacadeStubTest, AuthenticateToLoginFailure) {
-  MockLoginUIHandler consumer;
-  std::string test_username("Test_User");
-  std::string test_password("Test_Password");
-  std::string bad_username("Bad_User");
-  std::string bad_password("Bad_Password");
-  std::string test_token("Test_Token");
-  std::string test_captcha("Test_Captcha");
-  scoped_ptr<AuthenticatorFacadeStubHarness>
-      facade(new AuthenticatorFacadeStubHarness(&consumer,
-                                                test_username,
-                                                test_password));
-  EXPECT_CALL(consumer, OnLoginFailure(_))
-      .Times(1);
-
-  facade->AuthenticateToLogin(NULL,
-                              bad_username,
-                              test_password,
-                              test_token,
-                              test_captcha);
-
-  EXPECT_CALL(consumer, OnLoginFailure(_))
-      .Times(1);
-
-  facade->AuthenticateToLogin(NULL,
-                              test_username,
-                              bad_password,
-                              test_token,
-                              test_captcha);
-
-  EXPECT_CALL(consumer, OnLoginFailure(_))
-      .Times(1);
-
-  facade->AuthenticateToLogin(NULL,
-                              bad_username,
-                              bad_password,
-                              test_token,
-                              test_captcha);
-}
-
-// AuthenticateToUnlock
-TEST(AuthenticatorFacadeStubTest, AuthenticateToUnlockSuccess) {
-  MockLoginUIHandler consumer;
-  std::string test_username("Test_User");
-  std::string test_password("Test_Password");
-  scoped_ptr<AuthenticatorFacadeStubHarness>
-      facade(new AuthenticatorFacadeStubHarness(&consumer,
-                                                test_username,
-                                                test_password));
-
-  EXPECT_CALL(consumer, OnLoginSuccess(test_username,
-                                       _,
-                                       _,
-                                       false))
-      .Times(1);
-
-  facade->AuthenticateToUnlock(test_username, test_password);
-}
-
-TEST(AuthenticatorFacadeStubTest, AuthenticateToUnlockFailure) {
-  MockLoginUIHandler consumer;
-  std::string test_username("Test_User");
-  std::string test_password("Test_Password");
-  std::string bad_username("Bad_User");
-  std::string bad_password("Bad_Password");
-  scoped_ptr<AuthenticatorFacadeStubHarness>
-      facade(new AuthenticatorFacadeStubHarness(&consumer,
-                                                test_username,
-                                                test_password));
-  EXPECT_CALL(consumer, OnLoginFailure(_))
-      .Times(1);
-
-  facade->AuthenticateToUnlock(bad_username, test_password);
-
-  EXPECT_CALL(consumer, OnLoginFailure(_))
-      .Times(1);
-
-  facade->AuthenticateToUnlock(test_username, bad_password);
-
-  EXPECT_CALL(consumer, OnLoginFailure(_))
-      .Times(1);
-
-  facade->AuthenticateToUnlock(bad_username, bad_password);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/login/login_ui.cc b/chrome/browser/chromeos/dom_ui/login/login_ui.cc
index cf9d3f5..18bca25 100644
--- a/chrome/browser/chromeos/dom_ui/login/login_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/login/login_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,19 +7,20 @@
 #include "base/string_piece.h"
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/power_library.h"
 #include "chrome/browser/chromeos/dom_ui/login/authenticator_facade.h"
+#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_cros.h"
+#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_cros.h"
 #include "chrome/browser/chromeos/dom_ui/login/login_ui.h"
 #include "chrome/browser/chromeos/dom_ui/login/login_ui_helpers.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/url_constants.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_cros.h"
-#else
-#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h"
-#endif
-
 namespace chromeos {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -55,34 +56,29 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 LoginUIHandler::LoginUIHandler()
-    : facade_(NULL),
-      profile_operations_(NULL),
-      browser_operations_(NULL) {
-#if defined(OS_CHROMEOS)
-  facade_.reset(new chromeos::AuthenticatorFacadeCros(this));
-#else
-  facade_.reset(new chromeos::AuthenticatorFacadeStub(this,
-                                                      "chronos",
-                                                      "chronos"));
-#endif
+    : facade_(new chromeos::AuthenticatorFacadeCros(this)),
+      profile_operations_(new ProfileOperationsInterface()),
+      browser_operations_(new BrowserOperationsInterface()) {
   facade_->Setup();
-  profile_operations_.reset(new ProfileOperationsInterface());
-  browser_operations_.reset(new BrowserOperationsInterface());
 }
 
-DOMMessageHandler* LoginUIHandler::Attach(DOMUI* dom_ui) {
-  return DOMMessageHandler::Attach(dom_ui);
+WebUIMessageHandler* LoginUIHandler::Attach(WebUI* web_ui) {
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void LoginUIHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "LaunchIncognito",
       NewCallback(this,
                   &LoginUIHandler::HandleLaunchIncognito));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "AuthenticateUser",
       NewCallback(this,
                   &LoginUIHandler::HandleAuthenticateUser));
+  web_ui_->RegisterMessageCallback(
+      "ShutdownSystem",
+      NewCallback(this,
+                  &LoginUIHandler::HandleShutdownSystem));
 }
 
 void LoginUIHandler::HandleAuthenticateUser(const ListValue* args) {
@@ -115,6 +111,19 @@
   login_browser->CloseWindow();
 }
 
+void LoginUIHandler::HandleShutdownSystem(const ListValue* args) {
+#if defined(OS_CHROMEOS)
+  DCHECK(CrosLibrary::Get()->EnsureLoaded());
+  CrosLibrary::Get()->GetPowerLibrary()->RequestShutdown();
+#else
+  // When were are not running in cros we are just shutting the browser instead
+  // of trying to shutdown the system
+  Profile* profile = profile_operations_->GetDefaultProfileByPath();
+  Browser* browser = browser_operations_->GetLoginBrowser(profile);
+  browser->CloseWindow();
+#endif
+}
+
 void LoginUIHandler::OnLoginFailure(const LoginFailure& failure) {
   Profile* profile = profile_operations_->GetDefaultProfileByPath();
   Browser* login_browser = browser_operations_->GetLoginBrowser(profile);
@@ -143,18 +152,13 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 LoginUI::LoginUI(TabContents* contents)
-    : DOMUI(contents) {
+    : WebUI(contents) {
   LoginUIHandler* handler = new LoginUIHandler();
   AddMessageHandler(handler->Attach(this));
   LoginUIHTMLSource* html_source =
       new LoginUIHTMLSource(MessageLoop::current());
 
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/login/login_ui.h b/chrome/browser/chromeos/dom_ui/login/login_ui.h
index b19699e..292bc79 100644
--- a/chrome/browser/chromeos/dom_ui/login/login_ui.h
+++ b/chrome/browser/chromeos/dom_ui/login/login_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,7 @@
 #include "base/scoped_ptr.h"
 #include "chrome/browser/chromeos/login/login_status_consumer.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class Profile;
 
@@ -41,22 +41,23 @@
   DISALLOW_COPY_AND_ASSIGN(LoginUIHTMLSource);
 };
 
-// Main LoginUI handling function. It handles the DOMui hooks that are supplied
+// Main LoginUI handling function. It handles the WebUI hooks that are supplied
 // for the login page to use for authentication. It passes the key pair form the
 // login page to the AuthenticatorFacade. The facade then will call back into
 // this class with the result, which will then be used to determine the browser
 // behaviour.
-class LoginUIHandler : public DOMMessageHandler,
+class LoginUIHandler : public WebUIMessageHandler,
                        public chromeos::LoginStatusConsumer {
  public:
   LoginUIHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   void HandleAuthenticateUser(const ListValue* args);
   void HandleLaunchIncognito(const ListValue* args);
+  void HandleShutdownSystem(const ListValue* args);
 
   // Overridden from LoginStatusConsumer.
   virtual void OnLoginFailure(const chromeos::LoginFailure& failure);
@@ -76,9 +77,9 @@
   DISALLOW_COPY_AND_ASSIGN(LoginUIHandler);
 };
 
-// Boilerplate class that is used to associate the LoginUI code with the DOMui
+// Boilerplate class that is used to associate the LoginUI code with the WebUI
 // code.
-class LoginUI : public DOMUI {
+class LoginUI : public WebUI {
  public:
   explicit LoginUI(TabContents* contents);
 
diff --git a/chrome/browser/chromeos/dom_ui/login/login_ui_helpers.cc b/chrome/browser/chromeos/dom_ui/login/login_ui_helpers.cc
index c0d05d0..3cf1d52 100644
--- a/chrome/browser/chromeos/dom_ui/login/login_ui_helpers.cc
+++ b/chrome/browser/chromeos/dom_ui/login/login_ui_helpers.cc
@@ -5,7 +5,6 @@
 
 #include <algorithm>
 
-#include "app/resource_bundle.h"
 #include "base/file_path.h"
 #include "base/path_service.h"
 #include "base/values.h"
@@ -18,6 +17,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.cc b/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.cc
index e3e60b3..7667b00 100644
--- a/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.cc
+++ b/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -31,7 +31,7 @@
 // LoginUIHandler::RegisterMessage
 //
 // There is currently no test for LoginUIHandler::RegisterMessage, b/c the
-// function DOMUI::RegisterMesssageCallback is not declared virtual. This means
+// function WebUI::RegisterMesssageCallback is not declared virtual. This means
 // that it cannot be mocked easily and it is non-trivial to resolve, since just
 // making the function virtual causes other problems. Either this class or that
 // class needs to be refactored to deal with this before one can write this
@@ -53,10 +53,10 @@
 TEST(LoginUIHandlerTest, Attach) {
   // Don't care about the expected in this test
   LoginUIHandlerHarness handler_harness("", "");
-  MockDOMUI dom_ui;
+  MockWebUI web_ui;
 
-  EXPECT_EQ(&handler_harness, handler_harness.Attach(&dom_ui));
-  EXPECT_EQ(&dom_ui, handler_harness.GetDOMUI());
+  EXPECT_EQ(&handler_harness, handler_harness.Attach(&web_ui));
+  EXPECT_EQ(&web_ui, handler_harness.GetWebUI());
 }
 
 // Helper for LoginUIHandler::HandleAuthenticateUser
diff --git a/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.h b/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.h
index cb143cc..d138b6e 100644
--- a/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.h
+++ b/chrome/browser/chromeos/dom_ui/login/login_ui_unittest.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,26 +8,22 @@
 
 #include <string>
 
-#if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/dom_ui/login/mock_authenticator_facade_cros.h"
-#else
-#include "chrome/browser/chromeos/dom_ui/login/mock_authenticator_facade_stub.h"
-#endif
 #include "chrome/browser/chromeos/dom_ui/login/mock_login_ui_helpers.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace chromeos {
 
-class MockDOMUI : public DOMUI {
+class MockWebUI : public WebUI {
  public:
-  MockDOMUI() : DOMUI(NULL) {}
+  MockWebUI() : WebUI(NULL) {}
   MOCK_METHOD2(RegisterMessageCallback,
                void(const std::string& message,
                     MessageCallback* callback));
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MockDOMUI);
+  DISALLOW_COPY_AND_ASSIGN(MockWebUI);
 };
 
 class LoginUIHandlerHarness : public LoginUIHandler {
@@ -35,31 +31,18 @@
   explicit LoginUIHandlerHarness(const std::string& expected_username,
                                  const std::string& expected_password)
       : LoginUIHandler() {
-#if defined(OS_CHROMEOS)
     facade_.reset(new MockAuthenticatorFacadeCros(this,
                                                   expected_username,
                                                   expected_password));
-#else
-    facade_.reset(new MockAuthenticatorFacadeStub(this,
-                                                  expected_username,
-                                                  expected_password));
-#endif
     profile_operations_.reset(new MockProfileOperationsInterface());
     browser_operations_.reset(new MockBrowserOperationsInterface());
   }
 
-  DOMUI* GetDOMUI() const { return dom_ui_;}
-#if defined(OS_CHROMEOS)
+  WebUI* GetWebUI() const { return web_ui_;}
   MockAuthenticatorFacadeCros* GetMockFacade() const {
     return static_cast<MockAuthenticatorFacadeCros*>
         (facade_.get());
   }
-#else
-  MockAuthenticatorFacadeStub* GetMockFacade() const {
-    return static_cast<MockAuthenticatorFacadeStub*>
-        (facade_.get());
-  }
-#endif
   MockProfileOperationsInterface* GetMockProfileOperations() const {
     return static_cast<MockProfileOperationsInterface*>
         (profile_operations_.get());
diff --git a/chrome/browser/chromeos/dom_ui/login/mock_authenticator_facade_stub.h b/chrome/browser/chromeos/dom_ui/login/mock_authenticator_facade_stub.h
deleted file mode 100644
index d1b1389..0000000
--- a/chrome/browser/chromeos/dom_ui/login/mock_authenticator_facade_stub.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_LOGIN_MOCK_AUTHENTICATOR_FACADE_STUB_H_
-#define CHROME_BROWSER_CHROMEOS_DOM_UI_LOGIN_MOCK_AUTHENTICATOR_FACADE_STUB_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/chromeos/dom_ui/login/authenticator_facade_stub.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace chromeos {
-
-class MockAuthenticatorFacadeStub : public AuthenticatorFacadeStub {
- public:
-  explicit MockAuthenticatorFacadeStub(LoginStatusConsumer* consumer,
-                                       const std::string& expected_username,
-                                       const std::string& expected_password)
-      : chromeos::AuthenticatorFacadeStub(consumer,
-                                          expected_username,
-                                          expected_password) {}
-  MOCK_METHOD0(Setup,
-               void());
-  MOCK_METHOD5(AuthenticateToLogin,
-               void(Profile* profile,
-                    const std::string& username,
-                    const std::string& password,
-                    const std::string& login_token,
-                    const std::string& login_captcha));
-  MOCK_METHOD2(AuthenticateToUnlock,
-               void(const std::string& username,
-                    const std::string& password));
-  const std::string& GetUsername() { return expected_username_; }
-  const std::string& GetPassword() { return expected_password_; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockAuthenticatorFacadeStub);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_DOM_UI_LOGIN_MOCK_AUTHENTICATOR_FACADE_STUB_H_
diff --git a/chrome/browser/chromeos/dom_ui/login/mock_login_ui_handler.h b/chrome/browser/chromeos/dom_ui/login/mock_login_ui_handler.h
index 236f5c6..fa86beb 100644
--- a/chrome/browser/chromeos/dom_ui/login/mock_login_ui_handler.h
+++ b/chrome/browser/chromeos/dom_ui/login/mock_login_ui_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,7 +17,7 @@
 class MockLoginUIHandler : public chromeos::LoginUIHandler {
  public:
   MOCK_METHOD1(Attach,
-      DOMMessageHandler*(DOMUI* dom_ui));
+      WebUIMessageHandler*(WebUI* web_ui));
   MOCK_METHOD0(RegisterMessages,
       void());
   MOCK_METHOD1(OnLoginFailure,
diff --git a/chrome/browser/chromeos/dom_ui/menu_ui.cc b/chrome/browser/chromeos/dom_ui/menu_ui.cc
index 1bbc2b4..5a1941b 100644
--- a/chrome/browser/chromeos/dom_ui/menu_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/menu_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/menus/menu_model.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/json/json_writer.h"
@@ -19,22 +17,25 @@
 #include "base/values.h"
 #include "base/weak_ptr.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/chromeos/views/domui_menu_widget.h"
-#include "chrome/browser/chromeos/views/native_menu_domui.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/chromeos/views/native_menu_webui.h"
+#include "chrome/browser/chromeos/views/webui_menu_widget.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/jstemplate_builder.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/favicon_size.h"
-#include "gfx/font.h"
 #include "grit/app_resources.h"
 #include "grit/browser_resources.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/font.h"
 #include "views/accelerator.h"
 #include "views/controls/menu/menu_config.h"
-#include "views/controls/menu/radio_button_image_gtk.h"
+#include "views/controls/menu/menu_image_util_gtk.h"
 #include "views/widget/widget_gtk.h"
 
 namespace {
@@ -43,30 +44,30 @@
 const int kNoExtraResource = -1;
 
 // A utility function that generates css font property from gfx::Font.
-std::wstring GetFontShorthand(const gfx::Font* font) {
-  std::wstring out;
+// NOTE: Returns UTF-8.
+std::string GetFontShorthand(const gfx::Font* font) {
+  std::string out;
   if (font == NULL) {
     font = &(views::MenuConfig::instance().font);
   }
   if (font->GetStyle() & gfx::Font::BOLD) {
-    out.append(L"bold ");
+    out.append("bold ");
   }
   if (font->GetStyle() & gfx::Font::ITALIC) {
-    out.append(L"italic ");
+    out.append("italic ");
   }
   if (font->GetStyle() & gfx::Font::UNDERLINED) {
-    out.append(L"underline ");
+    out.append("underline ");
   }
 
   // TODO(oshima): The font size from gfx::Font is too small when
   // used in webkit. Figure out the reason.
-  out.append(ASCIIToWide(base::IntToString(font->GetFontSize() + 4)));
-  out.append(L"px/");
-  out.append(ASCIIToWide(base::IntToString(
-      std::max(kFavIconSize, font->GetHeight()))));
-  out.append(L"px \"");
-  out.append(font->GetFontName());
-  out.append(L"\",sans-serif");
+  out.append(base::IntToString(font->GetFontSize() + 4));
+  out.append("px/");
+  out.append(base::IntToString(std::max(kFavIconSize, font->GetHeight())));
+  out.append("px \"");
+  out.append(UTF16ToUTF8(font->GetFontName()));
+  out.append("\",sans-serif");
   return out;
 }
 
@@ -100,9 +101,9 @@
 // "down" image otherwise.
 const std::string& GetImageDataUrlForMenuScrollArrow(bool up) {
   static const std::string upImage =
-      dom_ui_util::GetImageDataUrl(CreateMenuScrollArrowImage(true));
+      web_ui_util::GetImageDataUrl(CreateMenuScrollArrowImage(true));
   static const std::string downImage =
-      dom_ui_util::GetImageDataUrl(CreateMenuScrollArrowImage(false));
+      web_ui_util::GetImageDataUrl(CreateMenuScrollArrowImage(false));
   return up ? upImage : downImage;
 }
 
@@ -110,9 +111,9 @@
 // "off" image otherwise.
 const std::string& GetImageDataUrlForRadio(bool on) {
   static const std::string onImage =
-      dom_ui_util::GetImageDataUrl(*views::GetRadioButtonImage(true));
+      web_ui_util::GetImageDataUrl(*views::GetRadioButtonImage(true));
   static const std::string offImage =
-       dom_ui_util::GetImageDataUrl(*views::GetRadioButtonImage(false));
+      web_ui_util::GetImageDataUrl(*views::GetRadioButtonImage(false));
   return on ? onImage : offImage;
 }
 
@@ -139,9 +140,9 @@
   value_config.SetString("radioOnUrl", GetImageDataUrlForRadio(true));
   value_config.SetString("radioOffUrl", GetImageDataUrlForRadio(false));
   value_config.SetString(
-      "arrowUrl", dom_ui_util::GetImageDataUrlFromResource(IDR_MENU_ARROW));
+      "arrowUrl", web_ui_util::GetImageDataUrlFromResource(IDR_MENU_ARROW));
   value_config.SetString(
-      "checkUrl", dom_ui_util::GetImageDataUrlFromResource(IDR_MENU_CHECK));
+      "checkUrl", web_ui_util::GetImageDataUrlFromResource(IDR_MENU_CHECK));
 
   value_config.SetString(
       "scrollUpUrl", GetImageDataUrlForMenuScrollArrow(true));
@@ -246,8 +247,8 @@
   MenuHandler();
   virtual ~MenuHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
  private:
@@ -258,10 +259,10 @@
   void HandleMoveInputToParent(const ListValue* values);
   void HandleCloseAll(const ListValue* values);
   void HandleModelUpdated(const ListValue* values);
-  // This is a utility DOMUI message to print debug message.
+  // This is a utility WebUI message to print debug message.
   // Menu can't use dev tool as it lives outside of browser.
   // TODO(oshima): This is inconvenient and figure out how we can use
-  // dev tools for menus (and other domui that does not belong to browser).
+  // dev tools for menus (and other WebUI that does not belong to browser).
   void HandleLog(const ListValue* values);
 
   // TabContentsDelegate implements:
@@ -287,7 +288,6 @@
   virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
   virtual bool IsPopup(const TabContents* source) { return false; }
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
   virtual bool CanDownload(int request_id) { return false; }
   virtual bool infobars_enabled() { return false; }
@@ -350,42 +350,42 @@
 MenuHandler::~MenuHandler() {
 }
 
-DOMMessageHandler* MenuHandler::Attach(DOMUI* dom_ui) {
-  DOMMessageHandler* handler = DOMMessageHandler::Attach(dom_ui);
-  dom_ui->tab_contents()->set_delegate(this);
+WebUIMessageHandler* MenuHandler::Attach(WebUI* web_ui) {
+  WebUIMessageHandler* handler = WebUIMessageHandler::Attach(web_ui);
+  web_ui->tab_contents()->set_delegate(this);
   return handler;
 }
 
 void MenuHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "activate",
       NewCallback(this,
                   &MenuHandler::HandleActivate));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "open_submenu",
       NewCallback(this,
                   &MenuHandler::HandleOpenSubmenu));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "close_submenu",
       NewCallback(this,
                   &MenuHandler::HandleCloseSubmenu));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "move_to_submenu",
       NewCallback(this,
                   &MenuHandler::HandleMoveInputToSubmenu));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "move_to_parent",
       NewCallback(this,
                   &MenuHandler::HandleMoveInputToParent));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "close_all",
       NewCallback(this,
                   &MenuHandler::HandleCloseAll));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "model_updated",
       NewCallback(this,
                   &MenuHandler::HandleModelUpdated));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "log",
       NewCallback(this,
                   &MenuHandler::HandleLog));
@@ -403,9 +403,9 @@
   int index;
   success = base::StringToInt(index_str, &index);
   DCHECK(success);
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control) {
-    menus::MenuModel* model = GetMenuModel();
+    ui::MenuModel* model = GetMenuModel();
     DCHECK(model);
     DCHECK_GE(index, 0);
     DCHECK(activation == "close_and_activate" ||
@@ -414,8 +414,8 @@
       control->Activate(model,
                         index,
                         activation == "close_and_activate" ?
-                        chromeos::DOMUIMenuControl::CLOSE_AND_ACTIVATE :
-                        chromeos::DOMUIMenuControl::ACTIVATE_NO_CLOSE);
+                        chromeos::WebUIMenuControl::CLOSE_AND_ACTIVATE :
+                        chromeos::WebUIMenuControl::ACTIVATE_NO_CLOSE);
     }
   }
 }
@@ -434,39 +434,39 @@
   int y;
   success = base::StringToInt(y_str, &y);
   DCHECK(success);
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control)
     control->OpenSubmenu(index, y);
 }
 
 void MenuHandler::HandleCloseSubmenu(const ListValue* values) {
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control)
     control->CloseSubmenu();
 }
 
 void MenuHandler::HandleMoveInputToSubmenu(const ListValue* values) {
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control)
     control->MoveInputToSubmenu();
 }
 
 void MenuHandler::HandleMoveInputToParent(const ListValue* values) {
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control)
     control->MoveInputToParent();
 }
 
 void MenuHandler::HandleCloseAll(const ListValue* values) {
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control)
     control->CloseAll();
 }
 
 void MenuHandler::HandleModelUpdated(const ListValue* values) {
-  menus::MenuModel* model = GetMenuModel();
+  ui::MenuModel* model = GetMenuModel();
   if (model)
-    static_cast<chromeos::MenuUI*>(dom_ui_)->ModelUpdated(model);
+    static_cast<chromeos::MenuUI*>(web_ui_)->ModelUpdated(model);
 }
 
 void MenuHandler::HandleLog(const ListValue* values) {
@@ -480,13 +480,13 @@
 void MenuHandler::UpdatePreferredSize(const gfx::Size& new_size) {
   if (!loaded_)
     return;
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control)
     control->SetSize(new_size);
 }
 
 void MenuHandler::LoadingStateChanged(TabContents* contents) {
-  chromeos::DOMUIMenuControl* control = GetMenuControl();
+  chromeos::WebUIMenuControl* control = GetMenuControl();
   if (control && !contents->is_loading()) {
     loaded_ = true;
     control->OnLoad();
@@ -504,18 +504,18 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-chromeos::DOMUIMenuControl* MenuHandlerBase::GetMenuControl() {
-  DOMUIMenuWidget* widget =
-      chromeos::DOMUIMenuWidget::FindDOMUIMenuWidget(
-          dom_ui_->tab_contents()->GetNativeView());
+chromeos::WebUIMenuControl* MenuHandlerBase::GetMenuControl() {
+  WebUIMenuWidget* widget =
+      chromeos::WebUIMenuWidget::FindWebUIMenuWidget(
+          web_ui_->tab_contents()->GetNativeView());
   if (widget)
-    return widget->domui_menu();  // NativeMenuDOMUI implements DOMUIMenuControl
+    return widget->webui_menu();  // NativeMenuWebUI implements WebUIMenuControl
   else
     return NULL;
 }
 
-menus::MenuModel* MenuHandlerBase::GetMenuModel() {
-  DOMUIMenuControl* control = GetMenuControl();
+ui::MenuModel* MenuHandlerBase::GetMenuModel() {
+  WebUIMenuControl* control = GetMenuControl();
   if (control)
     return control->GetMenuModel();
   else
@@ -528,59 +528,50 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-MenuUI::MenuUI(TabContents* contents) : DOMUI(contents) {
+MenuUI::MenuUI(TabContents* contents) : WebUI(contents) {
   MenuHandler* handler = new MenuHandler();
   AddMessageHandler((handler)->Attach(this));
 
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(CreateDataSource())));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(
+      CreateDataSource());
 }
 
 MenuUI::MenuUI(TabContents* contents, ChromeURLDataManager::DataSource* source)
-    : DOMUI(contents) {
+    : WebUI(contents) {
   MenuHandler* handler = new MenuHandler();
   AddMessageHandler((handler)->Attach(this));
 
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(source);
 }
 
-void MenuUI::ModelUpdated(const menus::MenuModel* model) {
+void MenuUI::ModelUpdated(const ui::MenuModel* model) {
   DictionaryValue json_model;
   ListValue* items = new ListValue();
   json_model.Set("items", items);
   int max_icon_width = 0;
   bool has_accelerator = false;
   for (int index = 0; index < model->GetItemCount(); ++index) {
-    menus::MenuModel::ItemType type = model->GetTypeAt(index);
+    ui::MenuModel::ItemType type = model->GetTypeAt(index);
     DictionaryValue* item;
     switch (type) {
-      case menus::MenuModel::TYPE_SEPARATOR:
+      case ui::MenuModel::TYPE_SEPARATOR:
         item = CreateMenuItem(model, index, "separator",
                               &max_icon_width, &has_accelerator);
         break;
-      case menus::MenuModel::TYPE_RADIO:
+      case ui::MenuModel::TYPE_RADIO:
         max_icon_width = std::max(max_icon_width, 12);
         item = CreateMenuItem(model, index, "radio",
                               &max_icon_width, &has_accelerator);
         break;
-      case menus::MenuModel::TYPE_SUBMENU:
+      case ui::MenuModel::TYPE_SUBMENU:
         item = CreateMenuItem(model, index, "submenu",
                               &max_icon_width, &has_accelerator);
         break;
-      case menus::MenuModel::TYPE_COMMAND:
+      case ui::MenuModel::TYPE_COMMAND:
         item = CreateMenuItem(model, index, "command",
                               &max_icon_width, &has_accelerator);
         break;
-      case menus::MenuModel::TYPE_CHECK:
+      case ui::MenuModel::TYPE_CHECK:
         // Add space even when unchecked.
         max_icon_width = std::max(max_icon_width, 12);
         item = CreateMenuItem(model, index, "check",
@@ -593,8 +584,8 @@
     }
     items->Set(index, item);
   }
-  DOMUIMenuWidget* widget =
-      chromeos::DOMUIMenuWidget::FindDOMUIMenuWidget(
+  WebUIMenuWidget* widget =
+      chromeos::WebUIMenuWidget::FindWebUIMenuWidget(
           tab_contents()->GetNativeView());
   DCHECK(widget);
   json_model.SetInteger("maxIconWidth", max_icon_width);
@@ -603,12 +594,12 @@
   CallJavascriptFunction(L"updateModel", json_model);
 }
 
-DictionaryValue* MenuUI::CreateMenuItem(const menus::MenuModel* model,
+DictionaryValue* MenuUI::CreateMenuItem(const ui::MenuModel* model,
                                         int index,
                                         const char* type,
                                         int* max_icon_width,
                                         bool* has_accel) const {
-  // Note: DOM UI uses '&' as mnemonic.
+  // Note: Web UI uses '&' as mnemonic.
   string16 label16 = model->GetLabelAt(index);
   DictionaryValue* item = new DictionaryValue();
 
@@ -619,15 +610,15 @@
   item->SetBoolean("checked", model->IsItemCheckedAt(index));
   item->SetInteger("command_id", model->GetCommandIdAt(index));
   item->SetString(
-      "font", WideToUTF16(GetFontShorthand(model->GetLabelFontAt(index))));
+      "font", GetFontShorthand(model->GetLabelFontAt(index)));
   SkBitmap icon;
   if (model->GetIconAt(index, &icon) && !icon.isNull() && !icon.empty()) {
-    item->SetString("icon", dom_ui_util::GetImageDataUrl(icon));
+    item->SetString("icon", web_ui_util::GetImageDataUrl(icon));
     *max_icon_width = std::max(*max_icon_width, icon.width());
   }
   views::Accelerator menu_accelerator;
   if (model->GetAcceleratorAt(index, &menu_accelerator)) {
-    item->SetString("accel", WideToUTF16(menu_accelerator.GetShortcutText()));
+    item->SetString("accel", menu_accelerator.GetShortcutText());
     *has_accel = true;
   }
   return item;
@@ -650,7 +641,7 @@
 // static
 bool MenuUI::IsEnabled() {
   return CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableDOMUIMenu);
+      switches::kEnableWebUIMenu);
 }
 
 ChromeURLDataManager::DataSource* MenuUI::CreateDataSource() {
diff --git a/chrome/browser/chromeos/dom_ui/menu_ui.h b/chrome/browser/chromeos/dom_ui/menu_ui.h
index 9f8c5db..62934fe 100644
--- a/chrome/browser/chromeos/dom_ui/menu_ui.h
+++ b/chrome/browser/chromeos/dom_ui/menu_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,17 +9,17 @@
 #include <string>
 
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class DictionaryValue;
 
-namespace menus {
+namespace ui{
 class MenuModel;
-}  // namespace menus
+}  // namespace ui
 
 namespace chromeos {
 
-class DOMUIMenuControl;
+class WebUIMenuControl;
 
 // MenuSourceDelegate class allows subclass to injects specific values
 // to menu javascript code.
@@ -27,7 +27,7 @@
  public:
   virtual ~MenuSourceDelegate() {}
   // Subclass can add extra parameters or replaces default configuration.
-  virtual void AddCustomConfigValues(DictionaryValue* config) const {};
+  virtual void AddCustomConfigValues(DictionaryValue* config) const {}
 
   // Subclass can add their values to |localized_strings| and those values
   // are used by JS template builder and could be accessed via JS class
@@ -35,16 +35,16 @@
   virtual void AddLocalizedStrings(DictionaryValue* localized_strings) const {}
 };
 
-class MenuUI : public DOMUI {
+class MenuUI : public WebUI {
  public:
   explicit MenuUI(TabContents* contents);
 
   // A callback method that is invoked when a menu model associated
-  // with the DOMUI Menu gets updated.
-  virtual void ModelUpdated(const menus::MenuModel* new_model);
+  // with the WebUI Menu gets updated.
+  virtual void ModelUpdated(const ui::MenuModel* new_model);
 
   // Creates a menu item for the menu item at index in the model.
-  virtual DictionaryValue* CreateMenuItem(const menus::MenuModel* model,
+  virtual DictionaryValue* CreateMenuItem(const ui::MenuModel* model,
                                           int index,
                                           const char* type,
                                           int* max_icon_width,
@@ -52,7 +52,7 @@
 
   // A utility function which creates a concrete html file from
   // template file |menu_resource_id| and |menu_css_id| for given |menu_class|.
-  // The resource_name is the host part of DOMUI's url.
+  // The resource_name is the host part of WebUI's url.
   static ChromeURLDataManager::DataSource* CreateMenuUIHTMLSource(
       const MenuSourceDelegate* delegate,
       const std::string& source_name,
@@ -75,18 +75,18 @@
   DISALLOW_COPY_AND_ASSIGN(MenuUI);
 };
 
-// Base class for MenuUI's DOMMessageHandler.
-class MenuHandlerBase : public DOMMessageHandler {
+// Base class for MenuUI's WebUIMessageHandler.
+class MenuHandlerBase : public WebUIMessageHandler {
  public:
-  MenuHandlerBase() : DOMMessageHandler() {}
+  MenuHandlerBase() : WebUIMessageHandler() {}
 
   // Returns the menu control that is associated with the
   // MenuUI. This may return null when menu is being deleted.
-  DOMUIMenuControl* GetMenuControl();
+  WebUIMenuControl* GetMenuControl();
 
   // Returns the menu model for this menu ui.
   // This may return null when menu is being deleted.
-  menus::MenuModel* GetMenuModel();
+  ui::MenuModel* GetMenuModel();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MenuHandlerBase);
diff --git a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc
index f1e980d..84fc218 100644
--- a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,6 @@
 #include <map>
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/file_util.h"
 #include "base/json/json_reader.h"
@@ -19,6 +17,8 @@
 #include "base/string_piece.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/timer.h"
 #include "base/values.h"
 #include "base/weak_ptr.h"
 #include "chrome/browser/browser_list.h"
@@ -30,7 +30,6 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -39,6 +38,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -58,8 +59,11 @@
 const char kErrorRoamingActivation[] = "roaming_activation";
 const char kErrorRoamingPartiallyActivated[] = "roaming_partially_activated";
 const char kErrorNoService[] = "no_service";
+const char kErrorDisabled[] = "disabled";
+const char kErrorNoDevice[] = "no_device";
 const char kFailedPaymentError[] = "failed_payment";
 const char kFailedConnectivity[] = "connectivity";
+const char kErrorAlreadyRunning[] = "already_running";
 
 // Cellular configuration file path.
 const char kCellularConfigPath[] =
@@ -73,9 +77,23 @@
 // there is no connectivity in the restricted pool.
 const int kMaxActivationAttempt = 3;
 // Number of times we will retry to reconnect if connection fails.
-const int kMaxConnectionRetry = 3;
+const int kMaxConnectionRetry = 10;
+// Number of times we will retry to reconnect if connection fails.
+const int kMaxConnectionRetryOTASP = 30;
+// Number of times we will retry to reconnect after payment is processed.
+const int kMaxReconnectAttemptOTASP = 30;
+// Reconnect retry delay (after payment is processed).
+const int kPostPaymentReconnectDelayMS = 30000;   // 30s.
 // Connection timeout in seconds.
-const int kConnectionTimeoutSeconds = 30;
+const int kConnectionTimeoutSeconds = 45;
+// Reconnect delay.
+const int kReconnectDelayMS = 3000;
+// Reconnect timer delay.
+const int kReconnectTimerDelayMS = 5000;
+// Reconnect delay after previous failure.
+const int kFailedReconnectDelayMS = 10000;
+// Retry delay after failed OTASP attempt.
+const int kOTASPRetryDelay = 20000;
 
 chromeos::CellularNetwork* GetCellularNetwork() {
   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
@@ -134,7 +152,7 @@
 
 // The handler for Javascript messages related to the "register" view.
 class MobileSetupHandler
-  : public DOMMessageHandler,
+  : public WebUIMessageHandler,
     public chromeos::NetworkLibrary::NetworkManagerObserver,
     public chromeos::NetworkLibrary::NetworkObserver,
     public base::SupportsWeakPtr<MobileSetupHandler> {
@@ -145,8 +163,8 @@
   // Init work after Attach.
   void Init(TabContents* contents);
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // NetworkLibrary::NetworkManagerObserver implementation.
@@ -157,19 +175,25 @@
 
  private:
   typedef enum PlanActivationState {
-    PLAN_ACTIVATION_PAGE_LOADING = -1,
-    PLAN_ACTIVATION_START = 0,
-    PLAN_ACTIVATION_INITIATING_ACTIVATION = 1,
-    PLAN_ACTIVATION_RECONNECTING = 2,
-    PLAN_ACTIVATION_SHOWING_PAYMENT = 3,
-    PLAN_ACTIVATION_DONE = 4,
-    PLAN_ACTIVATION_ERROR = 5,
+    PLAN_ACTIVATION_PAGE_LOADING            = -1,
+    PLAN_ACTIVATION_START                   = 0,
+    PLAN_ACTIVATION_TRYING_OTASP            = 1,
+    PLAN_ACTIVATION_RECONNECTING_OTASP_TRY  = 2,
+    PLAN_ACTIVATION_INITIATING_ACTIVATION   = 3,
+    PLAN_ACTIVATION_RECONNECTING            = 4,
+    PLAN_ACTIVATION_SHOWING_PAYMENT         = 5,
+    PLAN_ACTIVATION_DELAY_OTASP             = 6,
+    PLAN_ACTIVATION_START_OTASP             = 7,
+    PLAN_ACTIVATION_OTASP                   = 8,
+    PLAN_ACTIVATION_RECONNECTING_OTASP      = 9,
+    PLAN_ACTIVATION_DONE                    = 10,
+    PLAN_ACTIVATION_ERROR                   = 0xFF,
   } PlanActivationState;
 
   class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
    public:
-    explicit TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler)
-        : handler_(handler) {
+    TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler, int delay)
+        : handler_(handler), delay_(delay) {
     }
     TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler,
               const std::string& status)
@@ -183,17 +207,22 @@
       if (handler_)
         handler_->SetTransactionStatus(status_);
     }
-    void ContinueActivation() {
+    void ContinueConnecting() {
       if (handler_)
-        handler_->ContinueActivation();
+        handler_->ContinueConnecting(delay_);
+    }
+    void RetryOTASP() {
+      if (handler_)
+        handler_->RetryOTASP();
     }
    private:
     base::WeakPtr<MobileSetupHandler> handler_;
     std::string status_;
+    int delay_;
     DISALLOW_COPY_AND_ASSIGN(TaskProxy);
   };
 
-  // Handlers for JS DOMUI messages.
+  // Handlers for JS WebUI messages.
   void HandleSetTransactionStatus(const ListValue* args);
   void HandleStartActivation(const ListValue* args);
   void SetTransactionStatus(const std::string& status);
@@ -201,17 +230,29 @@
   void InitiateActivation();
   // Starts activation.
   void StartActivation();
+  // Retried OTASP.
+  void RetryOTASP();
   // Continues activation process. This method is called after we disconnect
   // due to detected connectivity issue to kick off reconnection.
-  void ContinueActivation();
+  void ContinueConnecting(int delay);
 
   // Sends message to host registration page with system/user info data.
   void SendDeviceInfo();
 
+  // Callback for when |reconnect_timer_| fires.
+  void ReconnectTimerFired();
+  // Starts OTASP process.
+  void StartOTASP();
+  // Checks if we need to reconnect due to failed connection attempt.
+  bool NeedsReconnecting(chromeos::CellularNetwork* network,
+                         PlanActivationState* new_state,
+                         std::string* error_description);
+  // Disconnect from network.
+  void DisconnectFromNetwork(chromeos::CellularNetwork* network);
   // Connects to cellular network, resets connection timer.
-  void ConnectToNetwork(chromeos::CellularNetwork* network);
+  bool ConnectToNetwork(chromeos::CellularNetwork* network, int delay);
   // Forces disconnect / reconnect when we detect portal connectivity issues.
-  void ForceReconnect(chromeos::CellularNetwork* network);
+  void ForceReconnect(chromeos::CellularNetwork* network, int delay);
   // Reports connection timeout.
   bool ConnectionTimeout();
   // Verify the state of cellular network and modify internal state.
@@ -219,7 +260,7 @@
   // Check the current cellular network for error conditions.
   bool GotActivationError(const chromeos::CellularNetwork* network,
                           std::string* error);
-  // Sends status updates to DOMUI page.
+  // Sends status updates to WebUI page.
   void UpdatePage(chromeos::CellularNetwork* network,
                   const std::string& error_description);
   // Changes internal state.
@@ -245,7 +286,7 @@
 
   // Performs activation state cellular device evaluation.
   // Returns false if device activation failed. In this case |error|
-  // will contain error message to be reported to DOM UI.
+  // will contain error message to be reported to Web UI.
   static bool EvaluateCellularDeviceState(bool* report_status,
                                           std::string* state,
                                           std::string* error);
@@ -254,6 +295,8 @@
   static std::string GetErrorMessage(const std::string& code);
   static void LoadCellularConfig();
 
+  // Returns next reconnection state based on the current activation phase.
+  static PlanActivationState GetNextReconnectState(PlanActivationState state);
   static const char* GetStateDescription(PlanActivationState state);
 
   static scoped_ptr<CellularConfigDocument> cellular_config_;
@@ -267,15 +310,20 @@
   bool reenable_wifi_;
   bool reenable_ethernet_;
   bool reenable_cert_check_;
-  bool transaction_complete_signalled_;
-  bool activation_status_test_;
   bool evaluating_;
+  // True if we think that another tab is already running activation.
+  bool already_running_;
   // Connection retry counter.
   int connection_retry_count_;
+  // Post payment reconnect wait counters.
+  int reconnect_wait_count_;
   // Activation retry attempt count;
   int activation_attempt_;
   // Connection start time.
   base::Time connection_start_time_;
+  // Timer that monitors reconnection timeouts.
+  base::RepeatingTimer<MobileSetupHandler> reconnect_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(MobileSetupHandler);
 };
 
@@ -298,8 +346,13 @@
   error_map_.clear();
 
   std::string config;
-  if (!file_util::ReadFileToString(config_path, &config))
-    return false;
+  {
+    // Reading config file causes us to do blocking IO on UI thread.
+    // Temporarily allow it until we fix http://crosbug.com/11535
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    if (!file_util::ReadFileToString(config_path, &config))
+      return false;
+  }
 
   scoped_ptr<Value> root(base::JSONReader::Read(config, true));
   DCHECK(root.get() != NULL);
@@ -370,8 +423,9 @@
   static const base::StringPiece html(
       ResourceBundle::GetSharedInstance().GetRawDataResource(
           IDR_MOBILE_SETUP_PAGE_HTML));
-  const std::string full_html = jstemplate_builder::GetTemplatesHtml(
-      html, &strings, "t" /* template root node id */);
+
+  const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
+      html, &strings);
 
   scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
   html_bytes->data.resize(full_html.size());
@@ -392,35 +446,41 @@
       reenable_wifi_(false),
       reenable_ethernet_(false),
       reenable_cert_check_(false),
-      transaction_complete_signalled_(false),
-      activation_status_test_(false),
       evaluating_(false),
+      already_running_(false),
       connection_retry_count_(0),
+      reconnect_wait_count_(0),
       activation_attempt_(0) {
 }
 
 MobileSetupHandler::~MobileSetupHandler() {
+  reconnect_timer_.Stop();
   chromeos::NetworkLibrary* lib =
       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
   lib->RemoveNetworkManagerObserver(this);
   lib->RemoveObserverForAllNetworks(this);
+  if (lib->IsLocked())
+    lib->Unlock();
   ReEnableOtherConnections();
 }
 
-DOMMessageHandler* MobileSetupHandler::Attach(DOMUI* dom_ui) {
-  return DOMMessageHandler::Attach(dom_ui);
+WebUIMessageHandler* MobileSetupHandler::Attach(WebUI* web_ui) {
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void MobileSetupHandler::Init(TabContents* contents) {
   tab_contents_ = contents;
   LoadCellularConfig();
-  SetupActivationProcess(GetCellularNetwork(service_path_));
+  if (!chromeos::CrosLibrary::Get()->GetNetworkLibrary()->IsLocked())
+    SetupActivationProcess(GetCellularNetwork(service_path_));
+  else
+    already_running_ = true;
 }
 
 void MobileSetupHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(kJsApiStartActivation,
+  web_ui_->RegisterMessageCallback(kJsApiStartActivation,
       NewCallback(this, &MobileSetupHandler::HandleStartActivation));
-  dom_ui_->RegisterMessageCallback(kJsApiSetTransactionStatus,
+  web_ui_->RegisterMessageCallback(kJsApiSetTransactionStatus,
       NewCallback(this, &MobileSetupHandler::HandleSetTransactionStatus));
 }
 
@@ -464,32 +524,56 @@
 }
 
 void MobileSetupHandler::InitiateActivation() {
-  scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
+  scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0);
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       NewRunnableMethod(task.get(), &TaskProxy::HandleStartActivation));
 }
 
 void MobileSetupHandler::StartActivation() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
-  if (!network) {
-    ChangeState(NULL, PLAN_ACTIVATION_ERROR, std::string());
-    return;
-  }
-  // Start monitoring network property changes.
   chromeos::NetworkLibrary* lib =
       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
+  chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
+  // Check if we can start activation process.
+  if (!network || already_running_) {
+    std::string error;
+    if (already_running_)
+      error = kErrorAlreadyRunning;
+    else if (!lib->cellular_available())
+      error = kErrorNoDevice;
+    else if (!lib->cellular_enabled())
+      error = kErrorDisabled;
+    else
+      error = kErrorNoService;
+    ChangeState(NULL, PLAN_ACTIVATION_ERROR, GetErrorMessage(error));
+    return;
+  }
+
+  // Start monitoring network property changes.
   lib->AddNetworkManagerObserver(this);
   lib->RemoveObserverForAllNetworks(this);
   lib->AddNetworkObserver(network->service_path(), this);
-  state_ = PLAN_ACTIVATION_START;
+  // Try to start with OTASP immediately if we have received payment recently.
+  state_ = lib->HasRecentCellularPlanPayment() ?
+               PLAN_ACTIVATION_START_OTASP :
+               PLAN_ACTIVATION_START;
   EvaluateCellularNetwork(network);
 }
 
-void MobileSetupHandler::ContinueActivation() {
+void MobileSetupHandler::RetryOTASP() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(state_ == PLAN_ACTIVATION_DELAY_OTASP);
+  StartOTASP();
+}
+
+void MobileSetupHandler::ContinueConnecting(int delay) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
-  EvaluateCellularNetwork(network);
+  if (network && network->connecting_or_connected()) {
+    EvaluateCellularNetwork(network);
+  } else {
+    ConnectToNetwork(network, delay);
+  }
 }
 
 void MobileSetupHandler::SetTransactionStatus(const std::string& status) {
@@ -498,42 +582,110 @@
   // again.
   if (LowerCaseEqualsASCII(status, "ok") &&
       state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) {
+    chromeos::NetworkLibrary* lib =
+        chromeos::CrosLibrary::Get()->GetNetworkLibrary();
+    lib->SignalCellularPlanPayment();
     UMA_HISTOGRAM_COUNTS("Cellular.PaymentReceived", 1);
-    if (transaction_complete_signalled_) {
-      LOG(WARNING) << "Transaction completion signaled more than once!?";
-      return;
-    }
-    transaction_complete_signalled_ = true;
-    activation_status_test_ = false;
-    state_ = PLAN_ACTIVATION_START;
-    chromeos::CellularNetwork* network = GetCellularNetwork();
-    if (network &&
-        network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED) {
-      chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
-          DisconnectFromWirelessNetwork(network);
-    } else {
-      EvaluateCellularNetwork(network);
-    }
+    StartOTASP();
   } else {
     UMA_HISTOGRAM_COUNTS("Cellular.PaymentFailed", 1);
   }
 }
 
-
-void MobileSetupHandler::ConnectToNetwork(chromeos::CellularNetwork* network) {
-  DCHECK(network);
-  LOG(INFO) << "Connecting to " <<
-      network->service_path().c_str();
-  connection_retry_count_++;
-  connection_start_time_ = base::Time::Now();
-  if (!chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
-          ConnectToCellularNetwork(network)) {
-    LOG(WARNING) << "Connect failed for service "
-                 << network->service_path().c_str();
+void MobileSetupHandler::StartOTASP() {
+  state_ = PLAN_ACTIVATION_START_OTASP;
+  chromeos::CellularNetwork* network = GetCellularNetwork();
+  if (network &&
+      network->connected() &&
+      network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED) {
+    chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
+        DisconnectFromWirelessNetwork(network);
+  } else {
+    EvaluateCellularNetwork(network);
   }
 }
 
-void MobileSetupHandler::ForceReconnect(chromeos::CellularNetwork* network) {
+void MobileSetupHandler::ReconnectTimerFired() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  // Permit network connection changes only in reconnecting states.
+  if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY &&
+      state_ != PLAN_ACTIVATION_RECONNECTING &&
+      state_ != PLAN_ACTIVATION_RECONNECTING_OTASP)
+    return;
+  chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
+  if (!network) {
+    // No service, try again since this is probably just transient condition.
+    LOG(WARNING) << "Service not present at reconnect attempt.";
+  }
+  EvaluateCellularNetwork(network);
+}
+
+void MobileSetupHandler::DisconnectFromNetwork(
+    chromeos::CellularNetwork* network) {
+  LOG(INFO) << "Disconnecting from " <<
+      network->service_path().c_str();
+  chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
+      DisconnectFromWirelessNetwork(network);
+  // Disconnect will force networks to be reevaluated, so
+  // we don't want to continue processing on this path anymore.
+  evaluating_ = false;
+}
+
+bool MobileSetupHandler::NeedsReconnecting(chromeos::CellularNetwork* network,
+                                           PlanActivationState* new_state,
+                                           std::string* error_description) {
+  if (!network->failed() && !ConnectionTimeout())
+    return false;
+
+  // Try to reconnect again if reconnect failed, or if for some
+  // reasons we are still not connected after 45 seconds.
+  int max_retries = (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) ?
+                        kMaxConnectionRetryOTASP : kMaxConnectionRetry;
+  if (connection_retry_count_ < max_retries) {
+    UMA_HISTOGRAM_COUNTS("Cellular.ConnectionRetry", 1);
+    ConnectToNetwork(network, kFailedReconnectDelayMS);
+    return true;
+  }
+  // We simply can't connect anymore after all these tries.
+  UMA_HISTOGRAM_COUNTS("Cellular.ConnectionFailed", 1);
+  *new_state = PLAN_ACTIVATION_ERROR;
+  *error_description = GetErrorMessage(kFailedConnectivity);
+  return false;
+}
+
+bool MobileSetupHandler::ConnectToNetwork(chromeos::CellularNetwork* network,
+                                          int delay) {
+  if (network && network->connecting_or_connected())
+    return true;
+  // Permit network connection changes only in reconnecting states.
+  if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY &&
+      state_ != PLAN_ACTIVATION_RECONNECTING &&
+      state_ != PLAN_ACTIVATION_RECONNECTING_OTASP)
+    return false;
+  if (network) {
+    LOG(INFO) << "Connecting to " <<
+        network->service_path().c_str();
+  }
+  connection_retry_count_++;
+  connection_start_time_ = base::Time::Now();
+  if (!network || !chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
+          ConnectToCellularNetwork(network)) {
+    LOG(WARNING) << "Connect failed"
+                 << network->service_path().c_str();
+    // If we coudn't connect during reconnection phase, try to reconnect
+    // with a delay (and try to reconnect if needed).
+    scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(),
+                                                  delay);
+    BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(task.get(), &TaskProxy::ContinueConnecting),
+        delay);
+    return false;
+  }
+  return true;
+}
+
+void MobileSetupHandler::ForceReconnect(chromeos::CellularNetwork* network,
+                                        int delay) {
   DCHECK(network);
   UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetry", 1);
   // Reset reconnect metrics.
@@ -546,11 +698,10 @@
       DisconnectFromWirelessNetwork(network);
   // Check the network state 3s after we disconnect to make sure.
   scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(),
-                                                std::string());
-  const int kReconnectDelayMS = 3000;
+                                                delay);
   BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(task.get(), &TaskProxy::ContinueActivation),
-      kReconnectDelayMS);
+      NewRunnableMethod(task.get(), &TaskProxy::ContinueConnecting),
+      delay);
 }
 
 bool MobileSetupHandler::ConnectionTimeout() {
@@ -560,13 +711,15 @@
 
 void MobileSetupHandler::EvaluateCellularNetwork(
     chromeos::CellularNetwork* network) {
-  if (!dom_ui_)
+  if (!web_ui_)
     return;
 
   PlanActivationState new_state = state_;
   if (!network) {
     LOG(WARNING) << "Cellular service lost";
-    if (state_ == PLAN_ACTIVATION_RECONNECTING) {
+    if (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP_TRY ||
+        state_ == PLAN_ACTIVATION_RECONNECTING ||
+        state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) {
       // This might be the legit case when service is lost after activation.
       // We need to make sure we force reconnection as soon as it shows up.
       LOG(INFO) << "Force service reconnection";
@@ -582,13 +735,13 @@
   evaluating_ = true;
   std::string error_description;
 
-  LOG(INFO) << "Cellular:\n  service=" << network->GetStateString().c_str()
-            << "\n  ui=" << GetStateDescription(state_)
-            << "\n  activation=" << network->GetActivationStateString().c_str()
-            << "\n  connectivity="
-            << network->GetConnectivityStateString().c_str()
-            << "\n  error=" << network->GetErrorString().c_str()
-            << "\n  setvice_path=" << network->service_path().c_str();
+  LOG(WARNING) << "Cellular:\n  service=" << network->GetStateString().c_str()
+      << "\n  ui=" << GetStateDescription(state_)
+      << "\n  activation=" << network->GetActivationStateString().c_str()
+      << "\n  connectivity="
+      << network->GetConnectivityStateString().c_str()
+      << "\n  error=" << network->GetErrorString().c_str()
+      << "\n  setvice_path=" << network->service_path().c_str();
   switch (state_) {
     case PLAN_ACTIVATION_START: {
       switch (network->activation_state()) {
@@ -604,58 +757,56 @@
           }
           break;
         }
-        case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: {
-          if (!activation_status_test_) {
-            if (network->failed_or_disconnected()) {
-              activation_status_test_ = true;
-              new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
-            } else if (network->connected()) {
-              LOG(INFO) << "Disconnecting from " <<
-                  network->service_path().c_str();
-              chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
-                  DisconnectFromWirelessNetwork(network);
-              // Disconnect will force networks to be reevaluated, so
-              // we don't want to continue processing on this path anymore.
-              evaluating_ = false;
-              return;
-            }
-          } else {
-            if (network->connected()) {
-              if (network->restricted_pool())
-                new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
-            } else {
-              new_state = PLAN_ACTIVATION_RECONNECTING;
-            }
-            break;
-          }
-          break;
-        }
-        case chromeos::ACTIVATION_STATE_UNKNOWN:
-        case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: {
-          if (network->failed_or_disconnected()) {
-            new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
+        default: {
+          if (network->failed_or_disconnected() ||
+              network->connection_state() ==
+                  chromeos::STATE_ACTIVATION_FAILURE) {
+            new_state = (network->activation_state() ==
+                         chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) ?
+                            PLAN_ACTIVATION_TRYING_OTASP :
+                            PLAN_ACTIVATION_INITIATING_ACTIVATION;
           } else if (network->connected()) {
-            LOG(INFO) << "Disconnecting from " <<
-                network->service_path().c_str();
-            chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
-                DisconnectFromWirelessNetwork(network);
-            // Disconnect will force networks to be reevaluated, so
-            // we don't want to continue processing on this path anymore.
-            evaluating_ = false;
+            DisconnectFromNetwork(network);
             return;
           }
           break;
         }
-        default:
-          break;
       }
       break;
     }
-    case PLAN_ACTIVATION_INITIATING_ACTIVATION: {
+    case PLAN_ACTIVATION_START_OTASP: {
+      switch (network->activation_state()) {
+        case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: {
+          if (network->failed_or_disconnected()) {
+            new_state = PLAN_ACTIVATION_OTASP;
+          } else if (network->connected()) {
+            DisconnectFromNetwork(network);
+            return;
+          }
+          break;
+        }
+        case chromeos::ACTIVATION_STATE_ACTIVATED:
+          new_state = PLAN_ACTIVATION_RECONNECTING_OTASP;
+          break;
+        default: {
+          LOG(WARNING) << "Unexpected activation state for device "
+                       << network->service_path().c_str();
+          break;
+        }
+      }
+      break;
+    }
+    case PLAN_ACTIVATION_DELAY_OTASP:
+      // Just ignore any changes until the OTASP retry timer kicks in.
+      evaluating_ = false;
+      return;
+    case PLAN_ACTIVATION_INITIATING_ACTIVATION:
+    case PLAN_ACTIVATION_OTASP:
+    case PLAN_ACTIVATION_TRYING_OTASP: {
       switch (network->activation_state()) {
         case chromeos::ACTIVATION_STATE_ACTIVATED:
           if (network->failed_or_disconnected()) {
-            new_state = PLAN_ACTIVATION_RECONNECTING;
+            new_state = GetNextReconnectState(state_);
           } else if (network->connected()) {
             if (network->restricted_pool()) {
               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
@@ -669,19 +820,19 @@
             if (network->restricted_pool())
               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
           } else {
-            new_state = PLAN_ACTIVATION_RECONNECTING;
+            new_state = GetNextReconnectState(state_);
           }
           break;
         case chromeos::ACTIVATION_STATE_NOT_ACTIVATED:
-          // Wait in this state until activation state changes.
-          break;
         case chromeos::ACTIVATION_STATE_ACTIVATING:
+          // Wait in this state until activation state changes.
           break;
         default:
           break;
       }
       break;
     }
+    case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
     case PLAN_ACTIVATION_RECONNECTING: {
       if (network->connected()) {
         // Make sure other networks are not interfering with our detection of
@@ -697,18 +848,22 @@
                            << network->service_path().c_str();
               // If we are connected but there is no connectivity at all,
               // restart the whole process again.
-              new_state = PLAN_ACTIVATION_ERROR;
               if (activation_attempt_ < kMaxActivationAttempt) {
                 activation_attempt_++;
-                ForceReconnect(network);
+                LOG(WARNING) << "Reconnect attempt #"
+                             << activation_attempt_;
+                ForceReconnect(network, kFailedReconnectDelayMS);
                 evaluating_ = false;
                 return;
               } else {
+                new_state = PLAN_ACTIVATION_ERROR;
                 UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetryFailure", 1);
                 error_description = GetErrorMessage(kFailedConnectivity);
               }
             } else if (network->connectivity_state() ==
-                chromeos::CONN_STATE_RESTRICTED) {
+                           chromeos::CONN_STATE_RESTRICTED) {
+              // If we have already received payment, don't show the payment
+              // page again. We should try to reconnect after some time instead.
               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
             } else if (network->activation_state() ==
                            chromeos::ACTIVATION_STATE_ACTIVATED) {
@@ -718,20 +873,51 @@
           default:
             break;
         }
-      } else if (network->failed() || ConnectionTimeout()) {
-        // Try to reconnect again if reconnect failed, or if for some
-        // reasons we are still not connected after 30 seconds.
-        if (connection_retry_count_ < kMaxConnectionRetry) {
-          UMA_HISTOGRAM_COUNTS("Cellular.ConnectionRetry", 1);
-          ConnectToNetwork(network);
-          evaluating_ = false;
-          return;
-        } else {
-          // We simply can't connect anymore after all these tries.
-          UMA_HISTOGRAM_COUNTS("Cellular.ConnectionFailed", 1);
-          new_state = PLAN_ACTIVATION_ERROR;
-          error_description = GetErrorMessage(kFailedConnectivity);
+      } else if (NeedsReconnecting(network, &new_state, &error_description)) {
+        evaluating_ = false;
+        return;
+      }
+      break;
+    }
+    case PLAN_ACTIVATION_RECONNECTING_OTASP: {
+      if (network->connected()) {
+        // Make sure other networks are not interfering with our detection of
+        // restricted pool.
+        DisableOtherNetworks();
+        // Wait until the service shows up and gets activated.
+        switch (network->activation_state()) {
+          case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED:
+          case chromeos::ACTIVATION_STATE_ACTIVATED:
+            if (network->connectivity_state() == chromeos::CONN_STATE_NONE ||
+                network->connectivity_state() ==
+                    chromeos::CONN_STATE_RESTRICTED) {
+              LOG(WARNING) << "Still no connectivity after OTASP for device "
+                           << network->service_path().c_str();
+              // If we have already received payment, don't show the payment
+              // page again. We should try to reconnect after some time instead.
+              if (reconnect_wait_count_ < kMaxReconnectAttemptOTASP) {
+                reconnect_wait_count_++;
+                LOG(WARNING) << "OTASP reconnect attempt #"
+                             << reconnect_wait_count_;
+                ForceReconnect(network, kPostPaymentReconnectDelayMS);
+                evaluating_ = false;
+                return;
+              } else {
+                new_state = PLAN_ACTIVATION_ERROR;
+                UMA_HISTOGRAM_COUNTS("Cellular.PostPaymentConnectFailure", 1);
+                error_description = GetErrorMessage(kFailedConnectivity);
+              }
+            } else if (network->connectivity_state() ==
+                           chromeos::CONN_STATE_UNRESTRICTED) {
+              new_state = PLAN_ACTIVATION_DONE;
+            }
+            break;
+          default:
+            break;
         }
+      } else if (NeedsReconnecting(network, &new_state, &error_description)) {
+        evaluating_ = false;
+        return;
       }
       break;
     }
@@ -754,20 +940,64 @@
             chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED ||
         network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATING) &&
         (network->error() == chromeos::ERROR_UNKNOWN ||
-            network->error() == chromeos::ERROR_OTASP_FAILED)&&
-        (state_ == PLAN_ACTIVATION_INITIATING_ACTIVATION ||
-            state_ == PLAN_ACTIVATION_RECONNECTING) &&
-        activation_status_test_ &&
+            network->error() == chromeos::ERROR_OTASP_FAILED) &&
         network->connection_state() == chromeos::STATE_ACTIVATION_FAILURE) {
-      new_state = PLAN_ACTIVATION_RECONNECTING;
+      LOG(WARNING) << "Activation failure detected "
+                   << network->service_path().c_str();
+      switch (state_) {
+        case PLAN_ACTIVATION_OTASP:
+        case PLAN_ACTIVATION_RECONNECTING_OTASP:
+          new_state = PLAN_ACTIVATION_DELAY_OTASP;
+          break;
+        case PLAN_ACTIVATION_TRYING_OTASP:
+          new_state = PLAN_ACTIVATION_RECONNECTING_OTASP_TRY;
+          break;
+        case PLAN_ACTIVATION_INITIATING_ACTIVATION:
+          new_state = PLAN_ACTIVATION_RECONNECTING;
+          break;
+        case PLAN_ACTIVATION_START:
+          // We are just starting, so this must be previous activation attempt
+          // failure.
+          new_state = PLAN_ACTIVATION_TRYING_OTASP;
+          break;
+        case PLAN_ACTIVATION_DELAY_OTASP:
+        case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
+        case PLAN_ACTIVATION_RECONNECTING:
+          new_state = state_;
+          break;
+        default:
+          new_state = PLAN_ACTIVATION_ERROR;
+          break;
+      }
     } else {
+      LOG(WARNING) << "Unexpected activation failure for "
+                   << network->service_path().c_str();
       new_state = PLAN_ACTIVATION_ERROR;
     }
   }
+
+  if (new_state == PLAN_ACTIVATION_ERROR && !error_description.length())
+    error_description = GetErrorMessage(kErrorDefault);
+
   ChangeState(network, new_state, error_description);
   evaluating_ = false;
 }
 
+MobileSetupHandler::PlanActivationState
+    MobileSetupHandler::GetNextReconnectState(
+        MobileSetupHandler::PlanActivationState state) {
+  switch (state) {
+    case PLAN_ACTIVATION_INITIATING_ACTIVATION:
+      return PLAN_ACTIVATION_RECONNECTING;
+    case PLAN_ACTIVATION_OTASP:
+      return PLAN_ACTIVATION_RECONNECTING_OTASP;
+    case PLAN_ACTIVATION_TRYING_OTASP:
+      return PLAN_ACTIVATION_RECONNECTING_OTASP_TRY;
+    default:
+      return PLAN_ACTIVATION_RECONNECTING;
+  }
+}
+
 // Debugging helper function, will take it out at the end.
 const char* MobileSetupHandler::GetStateDescription(
     PlanActivationState state) {
@@ -776,12 +1006,24 @@
       return "PAGE_LOADING";
     case PLAN_ACTIVATION_START:
       return "ACTIVATION_START";
+    case PLAN_ACTIVATION_TRYING_OTASP:
+      return "TRYING_OTASP";
+    case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
+      return "RECONNECTING_OTASP_TRY";
     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
       return "INITIATING_ACTIVATION";
     case PLAN_ACTIVATION_RECONNECTING:
       return "RECONNECTING";
     case PLAN_ACTIVATION_SHOWING_PAYMENT:
       return "SHOWING_PAYMENT";
+    case PLAN_ACTIVATION_START_OTASP:
+      return "START_OTASP";
+    case PLAN_ACTIVATION_DELAY_OTASP:
+      return "DELAY_OTASP";
+    case PLAN_ACTIVATION_OTASP:
+      return "OTASP";
+    case PLAN_ACTIVATION_RECONNECTING_OTASP:
+      return "RECONNECTING_OTASP";
     case PLAN_ACTIVATION_DONE:
       return "DONE";
     case PLAN_ACTIVATION_ERROR:
@@ -796,13 +1038,15 @@
   // Remove observers, we are done with this page.
   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
       GetNetworkLibrary();
+  lib->RemoveNetworkManagerObserver(this);
+  lib->RemoveObserverForAllNetworks(this);
+  if (lib->IsLocked())
+    lib->Unlock();
   // If we have successfully activated the connection, set autoconnect flag.
   if (network) {
     network->set_auto_connect(true);
     lib->SaveCellularNetwork(network);
   }
-  lib->RemoveNetworkManagerObserver(this);
-  lib->RemoveObserverForAllNetworks(this);
   // Reactivate other types of connections if we have
   // shut them down previously.
   ReEnableOtherConnections();
@@ -816,43 +1060,82 @@
   device_dict.SetInteger("state", state_);
   if (error_description.length())
     device_dict.SetString("error", error_description);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       kJsDeviceStatusChangedHandler, device_dict);
 }
 
+
 void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network,
                                      PlanActivationState new_state,
                                      const std::string& error_description) {
   static bool first_time = true;
   if (state_ == new_state && !first_time)
     return;
-  LOG(INFO) << "Activation state flip old = " <<
-          GetStateDescription(state_) << ", new = " <<
-          GetStateDescription(new_state);
+  LOG(WARNING) << "Activation state flip old = "
+      << GetStateDescription(state_)
+      << ", new = " << GetStateDescription(new_state);
   first_time = false;
+
+  // Pick action that should happen on leaving the old state.
+  switch (state_) {
+    case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
+    case PLAN_ACTIVATION_RECONNECTING:
+    case PLAN_ACTIVATION_RECONNECTING_OTASP:
+      if (reconnect_timer_.IsRunning()) {
+        reconnect_timer_.Stop();
+      }
+      break;
+    default:
+      break;
+  }
   state_ = new_state;
 
   // Signal to JS layer that the state is changing.
   UpdatePage(network, error_description);
 
-  // Decide what to do with network object as a result of the new state.
+  // Pick action that should happen on entering the new state.
   switch (new_state) {
     case PLAN_ACTIVATION_START:
       break;
+    case PLAN_ACTIVATION_DELAY_OTASP: {
+      UMA_HISTOGRAM_COUNTS("Cellular.RetryOTASP", 1);
+      scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0);
+      BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+          NewRunnableMethod(task.get(), &TaskProxy::RetryOTASP),
+          kOTASPRetryDelay);
+      break;
+    }
     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
+    case PLAN_ACTIVATION_TRYING_OTASP:
+    case PLAN_ACTIVATION_OTASP:
       DCHECK(network);
-      LOG(INFO) << "Activating service " << network->service_path().c_str();
+      LOG(WARNING) << "Activating service " << network->service_path().c_str();
       UMA_HISTOGRAM_COUNTS("Cellular.ActivationTry", 1);
       if (!network->StartActivation()) {
         UMA_HISTOGRAM_COUNTS("Cellular.ActivationFailure", 1);
-        ChangeState(network, PLAN_ACTIVATION_ERROR, std::string());
+        if (new_state == PLAN_ACTIVATION_OTASP) {
+          ChangeState(network, PLAN_ACTIVATION_DELAY_OTASP, std::string());
+        } else {
+          ChangeState(network, PLAN_ACTIVATION_ERROR,
+                      GetErrorMessage(kFailedConnectivity));
+        }
       }
       break;
-    case PLAN_ACTIVATION_RECONNECTING: {
+    case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
+    case PLAN_ACTIVATION_RECONNECTING:
+    case PLAN_ACTIVATION_RECONNECTING_OTASP: {
+      // Start reconnect timer. This will ensure that we are not left in
+      // limbo by the network library.
+      if (!reconnect_timer_.IsRunning()) {
+        reconnect_timer_.Start(
+            base::TimeDelta::FromMilliseconds(kReconnectTimerDelayMS),
+            this, &MobileSetupHandler::ReconnectTimerFired);
+      }
       // Reset connection metrics and try to connect.
+      reconnect_wait_count_ = 0;
       connection_retry_count_ = 0;
       connection_start_time_ = base::Time::Now();
-      ConnectToNetwork(network);
+      ConnectToNetwork(network, kReconnectDelayMS);
       break;
     }
     case PLAN_ACTIVATION_PAGE_LOADING:
@@ -866,11 +1149,10 @@
       CompleteActivation(network);
       UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupSucceeded", 1);
       break;
-    case PLAN_ACTIVATION_ERROR: {
+    case PLAN_ACTIVATION_ERROR:
       CompleteActivation(NULL);
       UMA_HISTOGRAM_COUNTS("Cellular.PlanFailed", 1);
       break;
-    }
     default:
       break;
   }
@@ -888,7 +1170,7 @@
     lib->EnableWifiNetworkDevice(true);
   }
 
-  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
   if (reenable_cert_check_) {
     prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled,
                       true);
@@ -903,7 +1185,7 @@
 
   // Disable SSL cert checks since we will be doing this in
   // restricted pool.
-  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
   if (!reenable_cert_check_ &&
       prefs->GetBoolean(
           prefs::kCertRevocationCheckingEnabled)) {
@@ -917,7 +1199,9 @@
   network->set_auto_connect(false);
   lib->SaveCellularNetwork(network);
 
+  // Prevent any other network interference.
   DisableOtherNetworks();
+  lib->Lock();
 }
 
 void MobileSetupHandler::DisableOtherNetworks() {
@@ -1001,7 +1285,14 @@
   config_loaded = true;
   // Load partner customization startup manifest if it is available.
   FilePath config_path(kCellularConfigPath);
-  if (file_util::PathExists(config_path)) {
+  bool config_exists = false;
+  {
+    // Reading config file causes us to do blocking IO on UI thread.
+    // Temporarily allow it until we fix http://crosbug.com/11535
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    config_exists = file_util::PathExists(config_path);
+  }
+  if (config_exists) {
     scoped_ptr<CellularConfigDocument> config(new CellularConfigDocument());
     bool config_loaded = config->LoadFromFile(config_path);
     if (config_loaded) {
@@ -1022,7 +1313,7 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-MobileSetupUI::MobileSetupUI(TabContents* contents) : DOMUI(contents) {
+MobileSetupUI::MobileSetupUI(TabContents* contents) : WebUI(contents) {
   const chromeos::CellularNetwork* network = GetCellularNetwork();
   std::string service_path = network ? network->service_path() : std::string();
   MobileSetupHandler* handler = new MobileSetupHandler(service_path);
@@ -1032,10 +1323,5 @@
       new MobileSetupUIHTMLSource(service_path);
 
   // Set up the chrome://mobilesetup/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.h b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.h
index f30af42..e713b9c 100644
--- a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.h
+++ b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_CHROMEOS_DOM_UI_MOBILE_SETUP_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-// A custom DOMUI that defines datasource for mobile setup registration page
+// A custom WebUI that defines datasource for mobile setup registration page
 // that is used in Chrome OS activate modem and perform plan subscription tasks.
-class MobileSetupUI : public DOMUI {
+class MobileSetupUI : public WebUI {
  public:
   explicit MobileSetupUI(TabContents* contents);
 
diff --git a/chrome/browser/chromeos/dom_ui/network_menu_ui.cc b/chrome/browser/chromeos/dom_ui/network_menu_ui.cc
index 2973432..a50b151 100644
--- a/chrome/browser/chromeos/dom_ui/network_menu_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/network_menu_ui.cc
@@ -1,24 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/network_menu_ui.h"
 
-#include "app/l10n_util.h"
 #include "base/values.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/status/network_menu.h"
-#include "chrome/browser/chromeos/views/domui_menu_widget.h"
-#include "chrome/browser/chromeos/views/native_menu_domui.h"
-#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
+#include "chrome/browser/chromeos/views/native_menu_webui.h"
+#include "chrome/browser/chromeos/views/webui_menu_widget.h"
+#include "chrome/browser/dom_ui/web_ui_theme_source.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/menu/menu_2.h"
 
 namespace {
@@ -53,7 +54,7 @@
   NetworkMenuHandler();
   virtual ~NetworkMenuHandler();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
  private:
@@ -63,26 +64,26 @@
 };
 
 void NetworkMenuHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "action",
       NewCallback(this,
                   &NetworkMenuHandler::HandleAction));
 }
 
 void NetworkMenuHandler::HandleAction(const ListValue* values) {
-  menus::MenuModel* model = GetMenuModel();
+  ui::MenuModel* model = GetMenuModel();
   if (model) {
     chromeos::NetworkMenuUI* network_menu_ui =
-        static_cast<chromeos::NetworkMenuUI*>(dom_ui_);
+        static_cast<chromeos::NetworkMenuUI*>(web_ui_);
     bool close_menu = network_menu_ui->ModelAction(model, values);
     if (close_menu) {
-      chromeos::DOMUIMenuWidget* widget
-          = chromeos::DOMUIMenuWidget::FindDOMUIMenuWidget(
-              dom_ui_->tab_contents()->GetNativeView());
+      chromeos::WebUIMenuWidget* widget
+          = chromeos::WebUIMenuWidget::FindWebUIMenuWidget(
+              web_ui_->tab_contents()->GetNativeView());
       if (widget) {
-        chromeos::NativeMenuDOMUI* domui_menu = widget->domui_menu();
-        if (domui_menu)
-          domui_menu->Hide();
+        chromeos::NativeMenuWebUI* webui_menu = widget->webui_menu();
+        if (webui_menu)
+          webui_menu->Hide();
       }
     }
   }
@@ -117,16 +118,11 @@
   AddMessageHandler((handler)->Attach(this));
 
   // Set up chrome://theme/ source.
-  DOMUIThemeSource* theme = new DOMUIThemeSource(GetProfile());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(theme)));
+  WebUIThemeSource* theme = new WebUIThemeSource(contents->profile());
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(theme);
 }
 
-bool NetworkMenuUI::ModelAction(const menus::MenuModel* model,
+bool NetworkMenuUI::ModelAction(const ui::MenuModel* model,
                                 const ListValue* values) {
   const NetworkMenu* network_menu = static_cast<const NetworkMenu*>(model);
   std::string action;
@@ -165,7 +161,7 @@
   return close_menu;
 }
 
-DictionaryValue* NetworkMenuUI::CreateMenuItem(const menus::MenuModel* model,
+DictionaryValue* NetworkMenuUI::CreateMenuItem(const ui::MenuModel* model,
                                                int index,
                                                const char* type,
                                                int* max_icon_width,
@@ -192,9 +188,9 @@
   return item;
 }
 
-views::Menu2* NetworkMenuUI::CreateMenu2(menus::MenuModel* model) {
+views::Menu2* NetworkMenuUI::CreateMenu2(ui::MenuModel* model) {
   views::Menu2* menu = new views::Menu2(model);
-  NativeMenuDOMUI::SetMenuURL(
+  NativeMenuWebUI::SetMenuURL(
       menu, GURL(StringPrintf("chrome://%s", chrome::kChromeUINetworkMenu)));
   return menu;
 }
diff --git a/chrome/browser/chromeos/dom_ui/network_menu_ui.h b/chrome/browser/chromeos/dom_ui/network_menu_ui.h
index 70a3a4d..1a236dc 100644
--- a/chrome/browser/chromeos/dom_ui/network_menu_ui.h
+++ b/chrome/browser/chromeos/dom_ui/network_menu_ui.h
@@ -8,14 +8,14 @@
 
 #include "chrome/browser/chromeos/dom_ui/menu_ui.h"
 
+namespace ui {
+class MenuModel;
+} // namespace ui
+
 namespace views {
 class Menu2;
 }  // namespace views
 
-namespace menus {
-class MenuModel;
-} // namespace menus
-
 namespace chromeos {
 
 class NetworkMenuUI : public MenuUI {
@@ -26,18 +26,18 @@
   // to invoke an action in the model.
   // By convention the first member of 'values' describes the action.
   // Returns true if the menu should be closed.
-  bool ModelAction(const menus::MenuModel* model,
+  bool ModelAction(const ui::MenuModel* model,
                    const ListValue* values);
 
   // MenuUI overrides
-  virtual DictionaryValue* CreateMenuItem(const menus::MenuModel* model,
+  virtual DictionaryValue* CreateMenuItem(const ui::MenuModel* model,
                                           int index,
                                           const char* type,
                                           int* max_icon_width,
                                           bool* has_accel) const;
 
   // A convenient factory method to create Menu2 for the network menu.
-  static views::Menu2* CreateMenu2(menus::MenuModel* model);
+  static views::Menu2* CreateMenu2(ui::MenuModel* model);
 
  private:
 
diff --git a/chrome/browser/chromeos/dom_ui/proxy_handler.cc b/chrome/browser/chromeos/dom_ui/proxy_handler.cc
index 759d8bd..e625730 100644
--- a/chrome/browser/chromeos/dom_ui/proxy_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/proxy_handler.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/chromeos/dom_ui/proxy_handler.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/stl_util-inl.h"
@@ -18,6 +16,8 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/dom_ui/register_page_ui.cc b/chrome/browser/chromeos/dom_ui/register_page_ui.cc
index 1778490..4e4323f 100644
--- a/chrome/browser/chromeos/dom_ui/register_page_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/register_page_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/string_piece.h"
@@ -22,10 +21,12 @@
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/version_loader.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -107,7 +108,7 @@
 };
 
 // The handler for Javascript messages related to the "register" view.
-class RegisterPageHandler : public DOMMessageHandler,
+class RegisterPageHandler : public WebUIMessageHandler,
                             public base::SupportsWeakPtr<RegisterPageHandler> {
  public:
   RegisterPageHandler();
@@ -116,12 +117,12 @@
   // Init work after Attach.
   void Init();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
  private:
-  // Handlers for JS DOMUI messages.
+  // Handlers for JS WebUI messages.
   void HandleGetRegistrationUrl(const ListValue* args);
   void HandleGetUserInfo(const ListValue* args);
 
@@ -200,8 +201,8 @@
 RegisterPageHandler::~RegisterPageHandler() {
 }
 
-DOMMessageHandler* RegisterPageHandler::Attach(DOMUI* dom_ui) {
-  return DOMMessageHandler::Attach(dom_ui);
+WebUIMessageHandler* RegisterPageHandler::Attach(WebUI* web_ui) {
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void RegisterPageHandler::Init() {
@@ -209,9 +210,9 @@
 
 void RegisterPageHandler::RegisterMessages() {
 #if defined(OS_CHROMEOS)
-  dom_ui_->RegisterMessageCallback(kJsCallbackGetRegistrationUrl,
+  web_ui_->RegisterMessageCallback(kJsCallbackGetRegistrationUrl,
       NewCallback(this, &RegisterPageHandler::HandleGetRegistrationUrl));
-  dom_ui_->RegisterMessageCallback(kJsCallbackUserInfo,
+  web_ui_->RegisterMessageCallback(kJsCallbackUserInfo,
       NewCallback(this, &RegisterPageHandler::HandleGetUserInfo));
 #endif
 }
@@ -229,7 +230,7 @@
       return;
     }
     StringValue url_value(url);
-    dom_ui_->CallJavascriptFunction(kJsApiSetRegistrationUrl, url_value);
+    web_ui_->CallJavascriptFunction(kJsApiSetRegistrationUrl, url_value);
   } else {
     SkipRegistration("Startup manifest not defined.");
   }
@@ -264,7 +265,7 @@
   if (WizardController::default_controller())
     WizardController::default_controller()->SkipRegistration();
   else
-    dom_ui_->CallJavascriptFunction(kJsApiSkipRegistration);
+    web_ui_->CallJavascriptFunction(kJsApiSkipRegistration);
 #endif
 }
 
@@ -306,7 +307,7 @@
   value.SetString("user_first_name", "");
   value.SetString("user_last_name", "");
 
-  dom_ui_->CallJavascriptFunction(kJsApiSetUserInfo, value);
+  web_ui_->CallJavascriptFunction(kJsApiSetUserInfo, value);
 #endif
 }
 
@@ -316,17 +317,12 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-RegisterPageUI::RegisterPageUI(TabContents* contents) : DOMUI(contents){
+RegisterPageUI::RegisterPageUI(TabContents* contents) : WebUI(contents){
   RegisterPageHandler* handler = new RegisterPageHandler();
   AddMessageHandler((handler)->Attach(this));
   handler->Init();
   RegisterPageUIHTMLSource* html_source = new RegisterPageUIHTMLSource();
 
   // Set up the chrome://register/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/chromeos/dom_ui/register_page_ui.h b/chrome/browser/chromeos/dom_ui/register_page_ui.h
index 44138eb..d7d5008 100644
--- a/chrome/browser/chromeos/dom_ui/register_page_ui.h
+++ b/chrome/browser/chromeos/dom_ui/register_page_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_CHROMEOS_DOM_UI_REGISTER_PAGE_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-// A custom DOMUI that defines datasource for host registration page that
+// A custom WebUI that defines datasource for host registration page that
 // is used in Chrome OS to register product on first sign in.
-class RegisterPageUI : public DOMUI {
+class RegisterPageUI : public WebUI {
  public:
   explicit RegisterPageUI(TabContents* contents);
 
diff --git a/chrome/browser/chromeos/dom_ui/stats_options_handler.cc b/chrome/browser/chromeos/dom_ui/stats_options_handler.cc
index 38ed546..7beb18d 100644
--- a/chrome/browser/chromeos/dom_ui/stats_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/stats_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -27,9 +27,9 @@
   SetupMetricsReportingCheckbox(false);
 }
 
-// DOMMessageHandler implementation.
+// WebUIMessageHandler implementation.
 void StatsOptionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "metricsReportingCheckboxAction",
       NewCallback(this, &StatsOptionsHandler::HandleMetricsReportingCheckbox));
 }
@@ -57,7 +57,7 @@
   FundamentalValue checked(MetricsCrosSettingsProvider::GetMetricsStatus());
   FundamentalValue disabled(!UserManager::Get()->current_user_is_owner());
   FundamentalValue user_has_changed(user_changed);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetMetricsReportingCheckboxState", checked,
       disabled, user_has_changed);
 #endif
diff --git a/chrome/browser/chromeos/dom_ui/stats_options_handler.h b/chrome/browser/chromeos/dom_ui/stats_options_handler.h
index 1f62899..49e59eb 100644
--- a/chrome/browser/chromeos/dom_ui/stats_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/stats_options_handler.h
@@ -24,7 +24,7 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void Initialize();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
  private:
diff --git a/chrome/browser/chromeos/dom_ui/system_info_ui.cc b/chrome/browser/chromeos/dom_ui/system_info_ui.cc
index 71f9865..3d485eb 100644
--- a/chrome/browser/chromeos/dom_ui/system_info_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/system_info_ui.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/system_info_ui.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
@@ -20,6 +18,8 @@
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/syslogs_library.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
@@ -29,6 +29,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class SystemInfoUIHTMLSource : public ChromeURLDataManager::DataSource {
  public:
@@ -59,14 +61,14 @@
 };
 
 // The handler for Javascript messages related to the "system" view.
-class SystemInfoHandler : public DOMMessageHandler,
+class SystemInfoHandler : public WebUIMessageHandler,
                           public base::SupportsWeakPtr<SystemInfoHandler> {
  public:
   SystemInfoHandler();
   virtual ~SystemInfoHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
  private:
@@ -158,9 +160,9 @@
 SystemInfoHandler::~SystemInfoHandler() {
 }
 
-DOMMessageHandler* SystemInfoHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* SystemInfoHandler::Attach(WebUI* web_ui) {
   // TODO(stevenjb): customize handler attach if needed...
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void SystemInfoHandler::RegisterMessages() {
@@ -173,16 +175,11 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-SystemInfoUI::SystemInfoUI(TabContents* contents) : DOMUI(contents) {
+SystemInfoUI::SystemInfoUI(TabContents* contents) : WebUI(contents) {
   SystemInfoHandler* handler = new SystemInfoHandler();
   AddMessageHandler((handler)->Attach(this));
   SystemInfoUIHTMLSource* html_source = new SystemInfoUIHTMLSource();
 
   // Set up the chrome://system/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/chromeos/dom_ui/system_info_ui.h b/chrome/browser/chromeos/dom_ui/system_info_ui.h
index 945ca24..dbb4f07 100644
--- a/chrome/browser/chromeos/dom_ui/system_info_ui.h
+++ b/chrome/browser/chromeos/dom_ui/system_info_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_CHROMEOS_DOM_UI_SYSTEM_INFO_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-class SystemInfoUI : public DOMUI {
+class SystemInfoUI : public WebUI {
  public:
   explicit SystemInfoUI(TabContents* contents);
 
diff --git a/chrome/browser/chromeos/dom_ui/system_options_handler.cc b/chrome/browser/chromeos/dom_ui/system_options_handler.cc
index d543871..f258959 100644
--- a/chrome/browser/chromeos/dom_ui/system_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/system_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,19 +6,22 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/dom_ui/system_settings_provider.h"
 #include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 SystemOptionsHandler::SystemOptionsHandler()
     : chromeos::CrosOptionsPageUIHandler(
@@ -31,9 +34,8 @@
 void SystemOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  // System page - ChromeOS
-  localized_strings->SetString("systemPage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SYSTEM_TAB_LABEL));
+
+  RegisterTitle(localized_strings, "systemPage", IDS_OPTIONS_SYSTEM_TAB_LABEL);
   localized_strings->SetString("datetime_title",
       l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME));
   localized_strings->SetString("timezone",
@@ -46,6 +48,12 @@
           IDS_OPTIONS_SETTINGS_TAP_TO_CLICK_ENABLED_DESCRIPTION));
   localized_strings->SetString("sensitivity",
       l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SENSITIVITY_DESCRIPTION));
+  localized_strings->SetString("sensitivity_less",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_SENSITIVITY_LESS_DESCRIPTION));
+  localized_strings->SetString("sensitivity_more",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_SENSITIVITY_MORE_DESCRIPTION));
 
   localized_strings->SetString("language",
       l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE));
@@ -66,3 +74,26 @@
       reinterpret_cast<chromeos::SystemSettingsProvider*>(
           settings_provider_.get())->GetTimezoneList());
 }
+
+void SystemOptionsHandler::Initialize() {
+  DCHECK(web_ui_);
+  PrefService* pref_service = g_browser_process->local_state();
+  bool acc_enabled = pref_service->GetBoolean(prefs::kAccessibilityEnabled);
+  FundamentalValue checked(acc_enabled);
+  web_ui_->CallJavascriptFunction(
+      L"options.SystemOptions.SetAccessibilityCheckboxState", checked);
+}
+
+void SystemOptionsHandler::RegisterMessages() {
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("accessibilityChange",
+      NewCallback(this, &SystemOptionsHandler::AccessibilityChangeCallback));
+}
+
+void SystemOptionsHandler::AccessibilityChangeCallback(const ListValue* args) {
+  std::string checked_str;
+  args->GetString(0, &checked_str);
+  bool accessibility_enabled = (checked_str == "true");
+  PrefService* pref_service = g_browser_process->local_state();
+  pref_service->SetBoolean(prefs::kAccessibilityEnabled, accessibility_enabled);
+}
diff --git a/chrome/browser/chromeos/dom_ui/system_options_handler.h b/chrome/browser/chromeos/dom_ui/system_options_handler.h
index 5d96050..29684ca 100644
--- a/chrome/browser/chromeos/dom_ui/system_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/system_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,6 +18,14 @@
 
   // OptionsUIHandler implementation.
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
+  virtual void Initialize();
+
+  virtual void RegisterMessages();
+
+  // Called when the accessibility checkbox value is changed.
+  // |args| will contain the checkbox checked state as a string
+  // ("true" or "false").
+  void AccessibilityChangeCallback(const ListValue* args);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SystemOptionsHandler);
diff --git a/chrome/browser/chromeos/dom_ui/system_settings_provider.cc b/chrome/browser/chromeos/dom_ui/system_settings_provider.cc
index fcfa7dc..4d9c71d 100644
--- a/chrome/browser/chromeos/dom_ui/system_settings_provider.cc
+++ b/chrome/browser/chromeos/dom_ui/system_settings_provider.cc
@@ -6,21 +6,21 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros_settings.h"
 #include "chrome/browser/chromeos/cros_settings_names.h"
-#include "chrome/browser/chromeos/login/ownership_service.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/calendar.h"
 #include "unicode/timezone.h"
 #include "unicode/ures.h"
@@ -120,7 +120,7 @@
     "Pacific/Tongatapu",
 };
 
-static Lock timezone_bundle_lock;
+static base::Lock timezone_bundle_lock;
 
 struct UResClose {
   inline void operator() (UResourceBundle* b) const {
@@ -138,7 +138,7 @@
 
   UErrorCode status = U_ZERO_ERROR;
   {
-    AutoLock lock(timezone_bundle_lock);
+    base::AutoLock lock(timezone_bundle_lock);
     if (zone_bundle == NULL)
       zone_bundle = ures_open(zone_bundle_name, uloc_getDefault(), &status);
 
@@ -196,7 +196,7 @@
 
 void SystemSettingsProvider::DoSet(const std::string& path, Value* in_value) {
   // Only the owner can change the time zone.
-  if (!OwnershipService::GetSharedInstance()->CurrentUserIsOwner())
+  if (!UserManager::Get()->current_user_is_owner())
     return;
 
   if (path == kSystemTimezone) {
diff --git a/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc b/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc
index 547615e..7bff31e 100644
--- a/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/dom_ui/wrench_menu_ui.h"
 
-#include "app/l10n_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -12,8 +11,8 @@
 #include "base/weak_ptr.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/browser_list.h"
-#include "chrome/browser/chromeos/views/domui_menu_widget.h"
-#include "chrome/browser/chromeos/views/native_menu_domui.h"
+#include "chrome/browser/chromeos/views/native_menu_webui.h"
+#include "chrome/browser/chromeos/views/webui_menu_widget.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/notification_registrar.h"
@@ -22,6 +21,7 @@
 #include "googleurl/src/gurl.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/menu/menu_2.h"
 
 namespace {
@@ -69,7 +69,7 @@
                  Source<Profile>(GetProfile()));
 }
 
-void WrenchMenuUI::ModelUpdated(const menus::MenuModel* new_model) {
+void WrenchMenuUI::ModelUpdated(const ui::MenuModel* new_model) {
   MenuUI::ModelUpdated(new_model);
   UpdateZoomControls();
 }
@@ -82,7 +82,7 @@
 }
 
 void WrenchMenuUI::UpdateZoomControls() {
-  DOMUIMenuWidget* widget = DOMUIMenuWidget::FindDOMUIMenuWidget(
+  WebUIMenuWidget* widget = WebUIMenuWidget::FindWebUIMenuWidget(
       tab_contents()->GetNativeView());
   if (!widget || !widget->is_root())
     return;
@@ -104,9 +104,9 @@
   CallJavascriptFunction(L"updateZoomControls", params);
 }
 
-views::Menu2* WrenchMenuUI::CreateMenu2(menus::MenuModel* model) {
+views::Menu2* WrenchMenuUI::CreateMenu2(ui::MenuModel* model) {
   views::Menu2* menu = new views::Menu2(model);
-  NativeMenuDOMUI::SetMenuURL(
+  NativeMenuWebUI::SetMenuURL(
       menu, GURL(StringPrintf("chrome://%s", chrome::kChromeUIWrenchMenu)));
   return menu;
 }
diff --git a/chrome/browser/chromeos/dom_ui/wrench_menu_ui.h b/chrome/browser/chromeos/dom_ui/wrench_menu_ui.h
index c12528c..3b4f1cd 100644
--- a/chrome/browser/chromeos/dom_ui/wrench_menu_ui.h
+++ b/chrome/browser/chromeos/dom_ui/wrench_menu_ui.h
@@ -14,14 +14,14 @@
 class NotificationSource;
 class NotificationDetails;
 
+namespace ui {
+class MenuModel;
+}  // namespace ui
+
 namespace views {
 class Menu2;
 }  // namespace views
 
-namespace menus {
-class MenuModel;
-} // namespace menus
-
 namespace chromeos {
 
 class WrenchMenuUI : public MenuUI,
@@ -30,7 +30,7 @@
   explicit WrenchMenuUI(TabContents* contents);
 
   // MenuUI overrides:
-  virtual void ModelUpdated(const menus::MenuModel* new_model);
+  virtual void ModelUpdated(const ui::MenuModel* new_model);
 
   // NotificationObserver:
   virtual void Observe(NotificationType type,
@@ -41,7 +41,7 @@
   void UpdateZoomControls();
 
   // A convenient factory method to create Menu2 for wrench menu.
-  static views::Menu2* CreateMenu2(menus::MenuModel* model);
+  static views::Menu2* CreateMenu2(ui::MenuModel* model);
 
  private:
   NotificationRegistrar registrar_;
diff --git a/chrome/browser/chromeos/drop_shadow_label.cc b/chrome/browser/chromeos/drop_shadow_label.cc
index 5c5fa30..575486c 100644
--- a/chrome/browser/chromeos/drop_shadow_label.cc
+++ b/chrome/browser/chromeos/drop_shadow_label.cc
@@ -4,8 +4,9 @@
 
 #include "chrome/browser/chromeos/drop_shadow_label.h"
 
-#include "gfx/canvas.h"
-#include "gfx/color_utils.h"
+#include "base/utf_string_conversions.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
 
 using views::Label;
 
@@ -44,19 +45,19 @@
                                    SkColorGetG(kDefaultColor),
                                    SkColorGetB(kDefaultColor));
     for (int i = 0; i < drop_shadow_size_; i++) {
-      canvas->DrawStringInt(text, font(), color,
+      canvas->DrawStringInt(WideToUTF16Hack(text), font(), color,
                             text_bounds.x() + i, text_bounds.y(),
                             text_bounds.width(), text_bounds.height(), flags);
-      canvas->DrawStringInt(text, font(), color,
+      canvas->DrawStringInt(WideToUTF16Hack(text), font(), color,
                             text_bounds.x() + i, text_bounds.y() + i,
                             text_bounds.width(), text_bounds.height(), flags);
-      canvas->DrawStringInt(text, font(), color,
+      canvas->DrawStringInt(WideToUTF16Hack(text), font(), color,
                             text_bounds.x(), text_bounds.y() + i,
                             text_bounds.width(), text_bounds.height(), flags);
     }
   }
 
-  canvas->DrawStringInt(text, font(), GetColor(),
+  canvas->DrawStringInt(WideToUTF16Hack(text), font(), GetColor(),
                         text_bounds.x(), text_bounds.y(),
                         text_bounds.width(), text_bounds.height(), flags);
 
diff --git a/chrome/browser/chromeos/drop_shadow_label.h b/chrome/browser/chromeos/drop_shadow_label.h
index 5848160..1c189ec 100644
--- a/chrome/browser/chromeos/drop_shadow_label.h
+++ b/chrome/browser/chromeos/drop_shadow_label.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_DROP_SHADOW_LABEL_H_
 #pragma once
 
-#include "gfx/font.h"
+#include "ui/gfx/font.h"
 #include "views/controls/label.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/external_metrics.cc b/chrome/browser/chromeos/external_metrics.cc
index 73e24d8..4eabaa2 100644
--- a/chrome/browser/chromeos/external_metrics.cc
+++ b/chrome/browser/chromeos/external_metrics.cc
@@ -18,58 +18,41 @@
 #include "base/metrics/histogram.h"
 #include "base/perftimer.h"
 #include "base/time.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/metrics/user_metrics.h"
 
-// Steps to add an action.
-//
-// 1. Enter a helper function that calls UserMetrics::RecordAction.
-//
-// 2. Add a line for that function in InitializeUserActions.
-//
-// 3. Enjoy the recompilation.
-//
-// TODO(semenzato): should see if it is possible to avoid recompiling code
-// every time a new user action is added, and register it in some other way.
-
 namespace chromeos {
 
 // The interval between external metrics collections, in milliseconds.
 static const int kExternalMetricsCollectionIntervalMs = 30 * 1000;
 
-// There is one of the following functions for every user action as we have to
-// call RecordAction in a way that gets picked up by the processing scripts.
-static void RecordTabOverviewKeystroke() {
-  UserMetrics::RecordAction(UserMetricsAction("TabOverview_Keystroke"));
-}
-
-static void RecordTabOverviewExitMouse() {
-  UserMetrics::RecordAction(UserMetricsAction("TabOverview_ExitMouse"));
+ExternalMetrics::ExternalMetrics()
+    : test_recorder_(NULL) {
 }
 
 void ExternalMetrics::Start() {
-  InitializeUserActions();
+  // Register user actions external to the browser.
+  // chrome/tools/extract_actions.py won't understand these lines, so all of
+  // these are explicitly added in that script.
+  // TODO(derat): We shouldn't need to verify actions before reporting them;
+  // remove all of this once http://crosbug.com/11125 is fixed.
+  valid_user_actions_.insert("Accel_NextWindow_Tab");
+  valid_user_actions_.insert("Accel_PrevWindow_Tab");
+  valid_user_actions_.insert("Accel_NextWindow_F5");
+  valid_user_actions_.insert("Accel_PrevWindow_F5");
+  valid_user_actions_.insert("Accel_BrightnessDown_F6");
+  valid_user_actions_.insert("Accel_BrightnessUp_F7");
+
   ScheduleCollector();
 }
 
-void ExternalMetrics::DefineUserAction(const std::string& name,
-                                       RecordFunctionType f) {
-  DCHECK(action_recorders_.find(name) == action_recorders_.end());
-  action_recorders_[name] = f;
-}
-
-void ExternalMetrics::InitializeUserActions() {
-  DefineUserAction("TabOverviewExitMouse", RecordTabOverviewExitMouse);
-  DefineUserAction("TabOverviewKeystroke", RecordTabOverviewKeystroke);
-}
-
 void ExternalMetrics::RecordActionUI(std::string action_string) {
-  base::hash_map<std::string, RecordFunctionType>::const_iterator iterator;
-  iterator = action_recorders_.find(action_string);
-  if (iterator == action_recorders_.end()) {
-    LOG(ERROR) << "undefined UMA action: " << action_string;
+  if (valid_user_actions_.count(action_string)) {
+    UserMetrics::RecordComputedAction(action_string);
   } else {
-    iterator->second();
+    LOG(ERROR) << "undefined UMA action: " << action_string;
   }
 }
 
@@ -77,7 +60,19 @@
   std::string action_string(action);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(this, &ExternalMetrics::RecordActionUI, action));
+      NewRunnableMethod(this, &ExternalMetrics::RecordActionUI, action_string));
+}
+
+void ExternalMetrics::RecordCrashUI(const std::string& crash_kind) {
+  if (g_browser_process && g_browser_process->metrics_service()) {
+    g_browser_process->metrics_service()->LogChromeOSCrash(crash_kind);
+  }
+}
+
+void ExternalMetrics::RecordCrash(const std::string& crash_kind) {
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(this, &ExternalMetrics::RecordCrashUI, crash_kind));
 }
 
 void ExternalMetrics::RecordHistogram(const char* histogram_data) {
@@ -194,6 +189,8 @@
       char* value = reinterpret_cast<char*>(p + 1);
       if (test_recorder_ != NULL) {
         test_recorder_(name, value);
+      } else if (strcmp(name, "crash") == 0) {
+        RecordCrash(value);
       } else if (strcmp(name, "histogram") == 0) {
         RecordHistogram(value);
       } else if (strcmp(name, "linearhistogram") == 0) {
diff --git a/chrome/browser/chromeos/external_metrics.h b/chrome/browser/chromeos/external_metrics.h
index eac8c64..cdb6046 100644
--- a/chrome/browser/chromeos/external_metrics.h
+++ b/chrome/browser/chromeos/external_metrics.h
@@ -26,7 +26,7 @@
   friend class base::RefCountedThreadSafe<ExternalMetrics>;
 
  public:
-  ExternalMetrics() : test_recorder_(NULL) {}
+  ExternalMetrics();
 
   // Begins the external data collection.  This service is started and stopped
   // by the chrome metrics service.  Calls to RecordAction originate in the
@@ -44,19 +44,19 @@
 
   ~ExternalMetrics() {}
 
-  // Registers a user action by associating the action name with a function
-  // that records instances of that action.
-  void DefineUserAction(const std::string& name, RecordFunctionType f);
-
-  // Registers all user actions external to the browser.
-  void InitializeUserActions();
-
   // Passes an action event to the UMA service on the UI thread.
   void RecordActionUI(std::string action_string);
 
   // Passes an action event to the UMA service.
   void RecordAction(const char* action_name);
 
+  // Records an external crash of the given string description to
+  // UMA service on the UI thread.
+  void RecordCrashUI(const std::string& crash_kind);
+
+  // Records an external crash of the given string description.
+  void RecordCrash(const std::string& crash_kind);
+
   // Passes an histogram event to the UMA service.  |histogram_data| is in the
   // form <histogram-name> <sample> <min> <max> <buckets_count>.
   void RecordHistogram(const char* histogram_data);
@@ -78,6 +78,9 @@
   // Maps histogram or action names to recorder structs.
   base::hash_map<std::string, RecordFunctionType> action_recorders_;
 
+  // Set containing known user actions.
+  base::hash_set<std::string> valid_user_actions_;
+
   // Used for testing only.
   RecorderType test_recorder_;
   FilePath test_path_;
diff --git a/chrome/browser/chromeos/external_metrics_unittest.cc b/chrome/browser/chromeos/external_metrics_unittest.cc
index 1558734..fd6605f 100644
--- a/chrome/browser/chromeos/external_metrics_unittest.cc
+++ b/chrome/browser/chromeos/external_metrics_unittest.cc
@@ -87,6 +87,12 @@
     }
   }
 
+  // Sends a crash message.
+  int expect_count = nhist;
+  SendMessage(path, "crash", "user");
+  external_metrics->CollectEvents();
+  CheckMessage("crash", "user", ++expect_count);
+
   // Sends a message that's too large.
   char b[MAXLENGTH + 100];
   for (i = 0; i < MAXLENGTH + 99; i++) {
@@ -94,35 +100,36 @@
   }
   b[i] = '\0';
   SendMessage(path, b, "yyy");
+  // Expect logged errors about bad message size.
   external_metrics->CollectEvents();
-  EXPECT_EQ(received_count, nhist);
+  EXPECT_EQ(expect_count, received_count);
 
   // Sends a malformed message (first string is not null-terminated).
   i = 100 + sizeof(i);
   int fd = open(path, O_CREAT | O_WRONLY, 0666);
   EXPECT_GT(fd, 0);
-  EXPECT_EQ(write(fd, &i, sizeof(i)), static_cast<int>(sizeof(i)));
-  EXPECT_EQ(write(fd, b, i), i);
-  EXPECT_EQ(close(fd), 0);
+  EXPECT_EQ(static_cast<int>(sizeof(i)), write(fd, &i, sizeof(i)));
+  EXPECT_EQ(i, write(fd, b, i));
+  EXPECT_EQ(0, close(fd));
 
   external_metrics->CollectEvents();
-  EXPECT_EQ(received_count, nhist);
+  EXPECT_EQ(expect_count, received_count);
 
   // Sends a malformed message (second string is not null-terminated).
   b[50] = '\0';
   fd = open(path, O_CREAT | O_WRONLY, 0666);
   EXPECT_GT(fd, 0);
-  EXPECT_EQ(write(fd, &i, sizeof(i)), static_cast<int>(sizeof(i)));
-  EXPECT_EQ(write(fd, b, i), i);
-  EXPECT_EQ(close(fd), 0);
+  EXPECT_EQ(static_cast<int>(sizeof(i)), write(fd, &i, sizeof(i)));
+  EXPECT_EQ(i, write(fd, b, i));
+  EXPECT_EQ(0, close(fd));
 
   external_metrics->CollectEvents();
-  EXPECT_EQ(received_count, nhist);
+  EXPECT_EQ(expect_count, received_count);
 
   // Checks that we survive when file doesn't exist.
-  EXPECT_EQ(unlink(path), 0);
+  EXPECT_EQ(0, unlink(path));
   external_metrics->CollectEvents();
-  EXPECT_EQ(received_count, nhist);
+  EXPECT_EQ(expect_count, received_count);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/external_protocol_dialog.cc b/chrome/browser/chromeos/external_protocol_dialog.cc
index a6b280d..92fa746 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.cc
+++ b/chrome/browser/chromeos/external_protocol_dialog.cc
@@ -1,12 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/external_protocol_dialog.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
-#include "app/text_elider.h"
 #include "base/metrics/histogram.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -14,10 +11,13 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 #include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
+#include "ui/base/text/text_elider.h"
 #include "views/controls/message_box_view.h"
 #include "views/window/window.h"
 
@@ -49,11 +49,11 @@
 // ExternalProtocolDialog, views::DialogDelegate implementation:
 
 int ExternalProtocolDialog::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK;
+  return ui::MessageBoxFlags::DIALOGBUTTON_OK;
 }
 
 std::wstring ExternalProtocolDialog::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
+    ui::MessageBoxFlags::DialogButton button) const {
   return UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT));
 }
@@ -88,7 +88,7 @@
       scheme_(url.scheme()) {
   const int kMaxUrlWithoutSchemeSize = 256;
   std::wstring elided_url_without_scheme;
-  gfx::ElideString(ASCIIToWide(url.possibly_invalid_spec()),
+  ui::ElideString(ASCIIToWide(url.possibly_invalid_spec()),
       kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
 
   std::wstring message_text = UTF16ToWide(l10n_util::GetStringFUTF16(
@@ -96,10 +96,11 @@
       ASCIIToUTF16(url.scheme() + ":"),
       WideToUTF16(elided_url_without_scheme)) + ASCIIToUTF16("\n\n"));
 
-  message_box_view_ = new MessageBoxView(MessageBoxFlags::kIsConfirmMessageBox,
-                                         message_text,
-                                         std::wstring(),
-                                         kMessageWidth);
+  message_box_view_ = new MessageBoxView(
+      ui::MessageBoxFlags::kIsConfirmMessageBox,
+      message_text,
+      std::wstring(),
+      kMessageWidth);
   message_box_view_->SetCheckBoxLabel(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT)));
 
diff --git a/chrome/browser/chromeos/frame/browser_frame_chromeos.h b/chrome/browser/chromeos/frame/browser_frame_chromeos.h
index 9f72260..b1fe5e4 100644
--- a/chrome/browser/chromeos/frame/browser_frame_chromeos.h
+++ b/chrome/browser/chromeos/frame/browser_frame_chromeos.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_FRAME_CHROMEOS_H_
 #pragma once
 
-#include "chrome/browser/views/frame/browser_frame_gtk.h"
+#include "chrome/browser/ui/views/frame/browser_frame_gtk.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc
index 870a4f6..c9e3b88 100644
--- a/chrome/browser/chromeos/frame/browser_view.cc
+++ b/chrome/browser/chromeos/frame/browser_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "app/menus/simple_menu_model.h"
 #include "base/command_line.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/chromeos/frame/panel_browser_view.h"
@@ -18,18 +17,19 @@
 #include "chrome/browser/chromeos/status/status_area_view.h"
 #include "chrome/browser/chromeos/view_ids.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/views/frame/browser_frame_gtk.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/frame/browser_view_layout.h"
-#include "chrome/browser/views/tabs/tab.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
-#include "chrome/browser/views/theme_background.h"
-#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/views/frame/browser_frame_gtk.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view_layout.h"
+#include "chrome/browser/ui/views/tabs/tab.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/theme_background.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 #include "chrome/common/chrome_switches.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/button/button.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/menu/menu_2.h"
@@ -89,7 +89,7 @@
     gfx::Rect tabstrip_bounds(
         browser_view_->frame()->GetBoundsForTabStrip(tabstrip_));
     gfx::Point tabstrip_origin = tabstrip_bounds.origin();
-    views::View::ConvertPointToView(browser_view_->GetParent(), browser_view_,
+    views::View::ConvertPointToView(browser_view_->parent(), browser_view_,
                                     &tabstrip_origin);
     tabstrip_bounds.set_origin(tabstrip_origin);
     return browser_view_->UseVerticalTabs() ?
@@ -115,7 +115,7 @@
   virtual int NonClientHitTest(const gfx::Point& point) {
     gfx::Point point_in_browser_view_coords(point);
     views::View::ConvertPointToView(
-        browser_view_->GetParent(), browser_view_,
+        browser_view_->parent(), browser_view_,
         &point_in_browser_view_coords);
     return IsPointInViewsInTitleArea(point_in_browser_view_coords) ?
         HTCLIENT : ::BrowserViewLayout::NonClientHitTest(point);
@@ -313,7 +313,7 @@
   // - HTCAPTION: in title bar or unobscured part of tabstrip
   // - HTNOWHERE: as the name implies.
   gfx::Point point_in_parent_coords(p);
-  views::View::ConvertPointToView(NULL, GetParent(), &point_in_parent_coords);
+  views::View::ConvertPointToView(NULL, parent(), &point_in_parent_coords);
   int hit_test = NonClientHitTest(point_in_parent_coords);
   if (hit_test == HTCAPTION || hit_test == HTNOWHERE)
     system_menu_menu_->RunMenuAt(p, views::Menu2::ALIGN_TOPLEFT);
@@ -352,12 +352,8 @@
   }
 }
 
-bool BrowserView::IsBrowserMode() const {
-  return true;
-}
-
-bool BrowserView::IsScreenLockerMode() const {
-  return false;
+StatusAreaHost::ScreenMode BrowserView::GetScreenMode() const {
+  return kBrowserMode;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -373,7 +369,7 @@
 // BrowserView private:
 
 void BrowserView::InitSystemMenu() {
-  system_menu_contents_.reset(new menus::SimpleMenuModel(this));
+  system_menu_contents_.reset(new ui::SimpleMenuModel(this));
   system_menu_contents_->AddItemWithStringId(IDC_RESTORE_TAB,
                                                IDS_RESTORE_TAB);
   system_menu_contents_->AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h
index a99d17c..8df86cd 100644
--- a/chrome/browser/chromeos/frame/browser_view.h
+++ b/chrome/browser/chromeos/frame/browser_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,15 +9,16 @@
 #include <vector>
 
 #include "chrome/browser/chromeos/status/status_area_host.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "views/controls/menu/menu_wrapper.h"
 
 class AccessibleToolbarView;
+class Profile;
 class TabStripModel;
 
-namespace menus {
+namespace ui {
 class SimpleMenuModel;
-}  // namespace menus
+}  // namespace ui
 
 namespace views {
 class ImageButton;
@@ -25,8 +26,6 @@
 class Menu2;
 }  // namespace views
 
-class Profile;
-
 namespace chromeos {
 
 class StatusAreaView;
@@ -73,8 +72,7 @@
       const views::View* button_view) const;
   virtual void ExecuteBrowserCommand(int id) const;
   virtual void OpenButtonOptions(const views::View* button_view);
-  virtual bool IsBrowserMode() const;
-  virtual bool IsScreenLockerMode() const;
+  virtual ScreenMode GetScreenMode() const;
 
   gfx::NativeView saved_focused_widget() const {
     return saved_focused_widget_;
@@ -91,7 +89,7 @@
   StatusAreaView* status_area_;
 
   // System menus.
-  scoped_ptr<menus::SimpleMenuModel> system_menu_contents_;
+  scoped_ptr<ui::SimpleMenuModel> system_menu_contents_;
   scoped_ptr<views::Menu2> system_menu_menu_;
 
   // Focused native widget before wench menu shows up. We need this to properly
diff --git a/chrome/browser/chromeos/frame/bubble_frame_view.cc b/chrome/browser/chromeos/frame/bubble_frame_view.cc
index f185159..8dc0f7f 100644
--- a/chrome/browser/chromeos/frame/bubble_frame_view.cc
+++ b/chrome/browser/chromeos/frame/bubble_frame_view.cc
@@ -1,19 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/frame/bubble_frame_view.h"
 
-#include "app/resource_bundle.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/font.h"
-#include "gfx/insets.h"
-#include "gfx/path.h"
-#include "gfx/rect.h"
 #include "chrome/browser/chromeos/frame/bubble_window.h"
 #include "chrome/browser/chromeos/login/helper.h"
-#include "chrome/browser/views/bubble_border.h"
+#include "chrome/browser/ui/views/bubble_border.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
@@ -210,7 +210,7 @@
   paint.setStyle(SkPaint::kFill_Style);
   paint.setColor(BubbleWindow::kBackgroundColor);
   gfx::Path path;
-  gfx::Rect bounds(GetLocalBounds(false));
+  gfx::Rect bounds(GetContentsBounds());
   SkRect rect;
   rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
            SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom()));
diff --git a/chrome/browser/chromeos/frame/bubble_window.cc b/chrome/browser/chromeos/frame/bubble_window.cc
index 9fc3684..6d3f3bb 100644
--- a/chrome/browser/chromeos/frame/bubble_window.cc
+++ b/chrome/browser/chromeos/frame/bubble_window.cc
@@ -8,12 +8,21 @@
 
 #include "chrome/browser/chromeos/frame/bubble_frame_view.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
-#include "gfx/skia_utils_gtk.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/gfx/skia_utils_gtk.h"
 #include "views/window/non_client_view.h"
 
 namespace chromeos {
 
+bool IsInsideCircle(int x0, int y0, int x1, int y1, int r) {
+  return (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1) <= r * r;
+}
+
+void SetRegionUnionWithPoint(int i, int j, GdkRegion* region) {
+  GdkRectangle rect = {i, j, 1, 1};
+  gdk_region_union_with_rect(region, &rect);
+}
+
 // static
 const SkColor BubbleWindow::kBackgroundColor = SK_ColorWHITE;
 
@@ -43,6 +52,59 @@
   gdk_window_set_back_pixmap(window_contents()->window, NULL, FALSE);
 }
 
+void BubbleWindow::TrimMargins(int margin_left, int margin_right,
+                               int margin_top, int margin_bottom,
+                               int border_radius) {
+  gfx::Size size = GetNonClientView()->GetPreferredSize();
+  const int w = size.width() - margin_left - margin_right;
+  const int h = size.height() - margin_top - margin_bottom;
+  GdkRectangle rect0 = {0, border_radius, w, h - 2 * border_radius};
+  GdkRectangle rect1 = {border_radius, 0, w - 2 * border_radius, h};
+  GdkRegion* region = gdk_region_rectangle(&rect0);
+  gdk_region_union_with_rect(region, &rect1);
+
+  // Top Left
+  for (int i = 0; i < border_radius; ++i) {
+    for (int j = 0; j < border_radius; ++j) {
+      if (IsInsideCircle(i + 0.5, j + 0.5, border_radius, border_radius,
+                         border_radius)) {
+        SetRegionUnionWithPoint(i, j, region);
+      }
+    }
+  }
+  // Top Right
+  for (int i = w - border_radius - 1; i < w; ++i) {
+    for (int j = 0; j < border_radius; ++j) {
+      if (IsInsideCircle(i + 0.5, j + 0.5, w - border_radius - 1,
+                         border_radius, border_radius)) {
+        SetRegionUnionWithPoint(i, j, region);
+      }
+    }
+  }
+  // Bottom Left
+  for (int i = 0; i < border_radius; ++i) {
+    for (int j = h - border_radius - 1; j < h; ++j) {
+      if (IsInsideCircle(i + 0.5, j + 0.5, border_radius, h - border_radius - 1,
+                         border_radius)) {
+        SetRegionUnionWithPoint(i, j, region);
+      }
+    }
+  }
+  // Bottom Right
+  for (int i = w - border_radius - 1; i < w; ++i) {
+    for (int j = h - border_radius - 1; j < h; ++j) {
+      if (IsInsideCircle(i + 0.5, j + 0.5, w - border_radius - 1,
+                         h - border_radius - 1, border_radius)) {
+        SetRegionUnionWithPoint(i, j, region);
+      }
+    }
+  }
+
+  gdk_window_shape_combine_region(window_contents()->window, region,
+                                  margin_left, margin_top);
+  gdk_region_destroy(region);
+}
+
 views::Window* BubbleWindow::Create(
     gfx::NativeWindow parent,
     const gfx::Rect& bounds,
@@ -52,6 +114,16 @@
   window->GetNonClientView()->SetFrameView(new BubbleFrameView(window, style));
   window->Init(parent, bounds);
 
+  if (style == STYLE_XSHAPE) {
+    const int kMarginLeft = 14;
+    const int kMarginRight = 14;
+    const int kMarginTop = 12;
+    const int kMarginBottom = 16;
+    const int kBorderRadius = 8;
+    window->TrimMargins(kMarginLeft, kMarginRight, kMarginTop, kMarginBottom,
+                        kBorderRadius);
+  }
+
   return window;
 }
 
diff --git a/chrome/browser/chromeos/frame/bubble_window.h b/chrome/browser/chromeos/frame/bubble_window.h
index a3b313e..2a045e6 100644
--- a/chrome/browser/chromeos/frame/bubble_window.h
+++ b/chrome/browser/chromeos/frame/bubble_window.h
@@ -26,7 +26,8 @@
   enum Style {
     STYLE_GENERIC = 0, // Default style.
     STYLE_XBAR = 1 << 0, // Show close button at the top right (left for RTL).
-    STYLE_THROBBER = 1 << 1 // Show throbber for slow rendering.
+    STYLE_THROBBER = 1 << 1, // Show throbber for slow rendering.
+    STYLE_XSHAPE = 1 << 2 // Trim the window margins and round corners.
   };
 
   static views::Window* Create(gfx::NativeWindow parent,
@@ -41,6 +42,10 @@
 
   // Overidden from views::WindowGtk:
   virtual void Init(GtkWindow* parent, const gfx::Rect& bounds);
+
+  // Trims the window margins and rounds off the corners.
+  void TrimMargins(int margin_left, int margin_right, int margin_top,
+                   int margin_bottom, int border_radius);
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/frame/panel_browser_view.cc b/chrome/browser/chromeos/frame/panel_browser_view.cc
index 74c08ae..0a4e8b5 100644
--- a/chrome/browser/chromeos/frame/panel_browser_view.cc
+++ b/chrome/browser/chromeos/frame/panel_browser_view.cc
@@ -96,7 +96,7 @@
 void PanelBrowserView::SetCreatorView(PanelBrowserView* creator) {
   DCHECK(creator);
   GtkWindow* window = creator->GetNativeHandle();
-  creator_xid_ = x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(window));
+  creator_xid_ = ui::GetX11WindowFromGtkWidget(GTK_WIDGET(window));
 }
 
 bool PanelBrowserView::GetSavedWindowBounds(gfx::Rect* bounds) const {
@@ -117,6 +117,10 @@
   return browser()->GetCurrentPageIcon();
 }
 
+bool PanelBrowserView::CanClosePanel() {
+  return ::BrowserView::CanClose();
+}
+
 void PanelBrowserView::ClosePanel() {
   Close();
 }
diff --git a/chrome/browser/chromeos/frame/panel_browser_view.h b/chrome/browser/chromeos/frame/panel_browser_view.h
index a3f3245..822d9d1 100644
--- a/chrome/browser/chromeos/frame/panel_browser_view.h
+++ b/chrome/browser/chromeos/frame/panel_browser_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,10 +6,10 @@
 #define CHROME_BROWSER_CHROMEOS_FRAME_PANEL_BROWSER_VIEW_H_
 #pragma once
 
-#include "app/x11_util.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/chromeos/frame/panel_controller.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "ui/base/x/x11_util.h"
 
 class Browser;
 
@@ -18,7 +18,7 @@
 class PanelController;
 
 // A browser view that implements Panel specific behavior.
-// NOTE: This inherits from ::BrowserView in chrome/browser/views/frame/,
+// NOTE: This inherits from ::BrowserView in chrome/browser/ui/views/frame/,
 // not chromeos::BrowserView in chrome/browser/chromeos/frame/.
 class PanelBrowserView : public ::BrowserView,
                          public PanelController::Delegate {
@@ -37,6 +37,7 @@
   // PanelController::Delegate overrides
   virtual string16 GetPanelTitle();
   virtual SkBitmap GetPanelIcon();
+  virtual bool CanClosePanel();
   virtual void ClosePanel();
   virtual void OnPanelStateChanged(PanelController::State state) {}
 
diff --git a/chrome/browser/chromeos/frame/panel_controller.cc b/chrome/browser/chromeos/frame/panel_controller.cc
index 31f4961..3ee210e 100644
--- a/chrome/browser/chromeos/frame/panel_controller.cc
+++ b/chrome/browser/chromeos/frame/panel_controller.cc
@@ -6,26 +6,25 @@
 
 #include <vector>
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/event.h"
+#include "views/events/event.h"
 #include "views/painter.h"
 #include "views/view.h"
 #include "views/widget/widget_gtk.h"
@@ -71,7 +70,7 @@
     SkPaint paint;
     paint.setStyle(SkPaint::kFill_Style);
     paint.setFlags(SkPaint::kAntiAlias_Flag);
-    SkPoint p[2] = {{0, 0}, {0, h}};
+    SkPoint p[2] = { {0, 0}, {0, h} };
     SkColor colors[2] = {kTitleActiveGradientStart, kTitleActiveGradientEnd};
     SkShader* s = SkGradientShader::CreateLinear(
         p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
@@ -108,7 +107,7 @@
                                  GtkWindow* window)
     :  delegate_(delegate),
        panel_(window),
-       panel_xid_(x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(panel_))),
+       panel_xid_(ui::GetX11WindowFromGtkWidget(GTK_WIDGET(panel_))),
        title_window_(NULL),
        title_(NULL),
        title_content_(NULL),
@@ -130,7 +129,7 @@
   gtk_widget_set_size_request(title_window_->GetNativeView(),
                               title_bounds.width(), title_bounds.height());
   title_ = title_window_->GetNativeView();
-  title_xid_ = x11_util::GetX11WindowFromGtkWidget(title_);
+  title_xid_ = ui::GetX11WindowFromGtkWidget(title_);
 
   WmIpc::instance()->SetWindowType(
       title_,
@@ -306,8 +305,11 @@
 void PanelController::OnCloseButtonPressed() {
   DCHECK(title_content_);
   if (title_window_) {
-    if (delegate_)
+    if (delegate_) {
+      if (!delegate_->CanClosePanel())
+        return;
       delegate_->ClosePanel();
+    }
     Close();
   }
 }
diff --git a/chrome/browser/chromeos/frame/panel_controller.h b/chrome/browser/chromeos/frame/panel_controller.h
index e642cfe..ec27bf2 100644
--- a/chrome/browser/chromeos/frame/panel_controller.h
+++ b/chrome/browser/chromeos/frame/panel_controller.h
@@ -8,8 +8,8 @@
 
 #include <gtk/gtk.h>
 
-#include "app/x11_util.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/x/x11_util.h"
 #include "views/controls/button/button.h"
 
 class BrowserView;
@@ -44,6 +44,10 @@
     // Retrieves the icon to use in the panel's titlebar.
     virtual SkBitmap GetPanelIcon() = 0;
 
+    // Can the panel be closed?  Called before ClosePanel() when the close
+    // button is pressed to give beforeunload handlers a chance to cancel.
+    virtual bool CanClosePanel() = 0;
+
     // Close the panel. Called when a close button is pressed.
     virtual void ClosePanel() = 0;
   };
diff --git a/chrome/browser/chromeos/gview_request_interceptor.cc b/chrome/browser/chromeos/gview_request_interceptor.cc
index 5e5c521..c6b1f9c 100644
--- a/chrome/browser/chromeos/gview_request_interceptor.cc
+++ b/chrome/browser/chromeos/gview_request_interceptor.cc
@@ -67,7 +67,7 @@
     PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
     if (webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath(
             pdf_path, &info) &&
-        info.enabled)
+            webkit::npapi::IsPluginEnabled(info))
       return NULL;
   }
   // If supported, build the URL to the Google Document Viewer
diff --git a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
index 6f9c68e..b2c8c86 100644
--- a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
+++ b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,16 +11,16 @@
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job.h"
 #include "net/url_request/url_request_test_job.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/glue/plugins/plugin_list.h"
 
 namespace chromeos {
 
-class GViewURLRequestTestJob : public URLRequestTestJob {
+class GViewURLRequestTestJob : public net::URLRequestTestJob {
  public:
   explicit GViewURLRequestTestJob(net::URLRequest* request)
-      : URLRequestTestJob(request, true) {
+      : net::URLRequestTestJob(request, true) {
   }
 
   virtual bool GetMimeType(std::string* mime_type) const {
@@ -66,9 +66,9 @@
   }
 
   void RegisterPDFPlugin() {
-    webkit::npapi::PluginVersionInfo info;
+    webkit::npapi::WebPluginInfo info;
     info.path = pdf_path_;
-    memset(&info.entry_points, 0, sizeof(info.entry_points));
+    info.enabled = webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
     webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);
     webkit::npapi::PluginList::Singleton()->RefreshPlugins();
   }
@@ -96,7 +96,7 @@
           pdf_path_, &info);
     }
     EXPECT_EQ(want_loaded, is_loaded);
-    *out_is_enabled = info.enabled;
+    *out_is_enabled = webkit::npapi::IsPluginEnabled(info);
   }
 
  protected:
diff --git a/chrome/browser/chromeos/input_method/candidate_window.cc b/chrome/browser/chromeos/input_method/candidate_window.cc
index a88b6bf..bd5c0d2 100644
--- a/chrome/browser/chromeos/input_method/candidate_window.cc
+++ b/chrome/browser/chromeos/input_method/candidate_window.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,14 +14,14 @@
 #include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
 #include "third_party/cros/chromeos_input_method_ui.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/event.h"
-#include "views/fill_layout.h"
-#include "views/grid_layout.h"
+#include "views/events/event.h"
+#include "views/layout/fill_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/screen.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget.h"
@@ -347,6 +347,9 @@
   // Commits the candidate currently being selected.
   void CommitCandidate();
 
+  // Hides the lookup table.
+  void HideLookupTable();
+
   // Hides the auxiliary text.
   void HideAuxiliaryText();
 
@@ -403,6 +406,13 @@
   // Returns 0 if no candidate is present.
   int GetHorizontalOffset();
 
+  // A function to be called when one of the |candidate_views_| receives a mouse
+  // press event.
+  void OnMousePressed();
+  // A function to be called when one of the |candidate_views_| receives a mouse
+  // release event.
+  void OnMouseReleased();
+
   void set_cursor_location(const gfx::Rect& cursor_location) {
     cursor_location_ = cursor_location;
   }
@@ -475,6 +485,9 @@
 
   // The last cursor location.
   gfx::Rect cursor_location_;
+
+  // true if a mouse button is pressed, and is not yet released.
+  bool mouse_is_pressed_;
 };
 
 // CandidateRow renderes a row of a candidate.
@@ -700,10 +713,11 @@
 }
 
 gfx::Point CandidateView::GetCandidateLabelPosition() const {
-  return candidate_label_->GetPosition();
+  return candidate_label_->GetMirroredPosition();
 }
 
 bool CandidateView::OnMousePressed(const views::MouseEvent& event) {
+  parent_candidate_window_->OnMousePressed();
   // Select the candidate. We'll commit the candidate when the mouse
   // button is released.
   parent_candidate_window_->SelectCandidateAt(index_in_page_);
@@ -727,6 +741,7 @@
   if (!canceled) {
     parent_candidate_window_->CommitCandidate();
   }
+  parent_candidate_window_->OnMouseReleased();
 }
 
 CandidateWindowView::CandidateWindowView(
@@ -740,8 +755,8 @@
       footer_label_(NULL),
       previous_shortcut_column_width_(0),
       previous_candidate_column_width_(0),
-      previous_annotation_column_width_(0) {
-
+      previous_annotation_column_width_(0),
+      mouse_is_pressed_(false) {
   SetNotifyWhenVisibleBoundsInRootChanges(true);
 }
 
@@ -778,6 +793,57 @@
   layout->AddView(footer_area_);  // |footer_area_| is owned by |this|.
 }
 
+void CandidateWindowView::HideLookupTable() {
+  if (!mouse_is_pressed_) {
+    parent_frame_->Hide();
+    return;
+  }
+
+  // We should not hide the |frame_| when a mouse is pressed, so we don't run
+  // into issues below.
+  //
+  // First, in the following scenario, it seems that the Views popup window does
+  // not release mouse/keyboard grab even after it gets hidden.
+  //
+  // 1. create a popup window by views::Widget::CreatePopupWidget() with the
+  //    views::Widget::AcceptEvents flag.
+  // 2. press a mouse button on the window.
+  // 3. before releasing the mouse button, Hide() the window.
+  // 4. release the button.
+  //
+  // And if we embed IME candidate window into Chrome, the window sometimes
+  // receives an extra 'hide-lookup-table' event before mouse button is
+  // released:
+  //
+  // 1. the candidate window is clicked.
+  // 2. The mouse click handler in this file, OnMousePressed() in CandidateView,
+  //    is called, and the handler consumes the event by returning true.
+  // 3. HOWEVER, if the candidate window is embedded into Chrome, the event is
+  //    also sent to Chrome! (problem #1)
+  // 4. im-ibus.so in Chrome sends 'focus-out' event to ibus-daemon.
+  // 5. ibus-daemon sends 'hide-lookup-table' event to the candidate window.
+  // 6. the window is hidden, but the window does not release mouse/keyboard
+  //    grab! (problem #2)
+  // 7. mouse button is released.
+  // 8. now all mouse/keyboard events are consumed by the hidden popup, and are
+  //    not sent to Chrome.
+  //
+  // TODO(yusukes): investigate why the click event is sent to both candidate
+  // window and Chrome. http://crosbug.com/11423
+  // TODO(yusukes): investigate if we could fix Views so it always releases grab
+  // when a popup window gets hidden. http://crosbug.com/11422
+  //
+  LOG(WARNING) << "Can't hide the table since a mouse button is not released.";
+}
+
+void CandidateWindowView::OnMousePressed() {
+  mouse_is_pressed_ = true;
+}
+
+void CandidateWindowView::OnMouseReleased() {
+  mouse_is_pressed_ = false;
+}
+
 void CandidateWindowView::HideAuxiliaryText() {
   views::View* target_area = (
       lookup_table_.orientation == InputMethodLookupTable::kHorizontal ?
@@ -800,7 +866,7 @@
       header_area_contents_.get() :
       footer_area_contents_.get());
 
-  if (!target_area->HasChildView(target_contents)) {
+  if (target_contents->parent() != target_area) {
     // If contents not in display area, put it in.
     target_area->RemoveAllChildViews(false);  // Don't delete child views.
     target_area->AddChildView(target_contents);
@@ -997,7 +1063,7 @@
   // moves right from the correct position in MoveParentFrame().
   // TODO(nhiroki): Figure out why it returns invalid value.
   // It seems that the x-position of the candidate labels is not set.
-  layout->Layout(this);
+  layout->Layout(candidate_area_);
 }
 
 views::View* CandidateWindowView::CreateHeaderArea() {
@@ -1267,7 +1333,7 @@
   CandidateWindowController::Impl* controller =
       static_cast<CandidateWindowController::Impl*>(input_method_library);
 
-  controller->frame_->Hide();
+  controller->candidate_window_->HideLookupTable();
 }
 
 void CandidateWindowController::Impl::OnSetCursorLocation(
@@ -1321,7 +1387,7 @@
 
   // If it's not visible, hide the window and return.
   if (!lookup_table.visible) {
-    controller->frame_->Hide();
+    controller->candidate_window_->HideLookupTable();
     return;
   }
 
@@ -1331,8 +1397,8 @@
 }
 
 void CandidateWindowController::Impl::OnCandidateCommitted(int index,
-                                                     int button,
-                                                     int flags) {
+                                                           int button,
+                                                           int flags) {
   NotifyCandidateClicked(ui_status_connection_, index, button, flags);
 }
 
@@ -1340,8 +1406,9 @@
     void* input_method_library,
     bool connected) {
   if (!connected) {
-    MessageLoopForUI::current()->PostTask(FROM_HERE,
-                                          new MessageLoop::QuitTask());
+    CandidateWindowController::Impl* controller =
+        static_cast<CandidateWindowController::Impl*>(input_method_library);
+    controller->candidate_window_->HideLookupTable();
   }
 }
 
diff --git a/chrome/browser/chromeos/input_method/candidate_window.gyp b/chrome/browser/chromeos/input_method/candidate_window.gyp
index faa3788..89ce891 100644
--- a/chrome/browser/chromeos/input_method/candidate_window.gyp
+++ b/chrome/browser/chromeos/input_method/candidate_window.gyp
@@ -10,38 +10,8 @@
     {
       'target_name': 'candidate_window',
       'type': 'executable',
-      'dependencies': [
-        '../../../../app/app.gyp:app_strings',
-        '../../../../base/base.gyp:base',
-        '../../../../build/linux/system.gyp:gtk',
-        '../../../../build/linux/system.gyp:x11',
-        '../../../../chrome/chrome.gyp:common_constants',
-        '../../../../skia/skia.gyp:skia',
-        '../../../../views/views.gyp:views',
-      ],
       'sources': [
-        'candidate_window.h',
-        'candidate_window.cc',
         'candidate_window_main.cc',
-        # For loading libcros.
-        '../cros/cros_library_loader.cc',
-      ],
-      'conditions': [
-        ['system_libcros==0', {
-          'dependencies': [
-            '../../../../third_party/cros/cros_api.gyp:cros_api',
-          ],
-          'include_dirs': [
-            '../../../../third_party/',
-          ],
-        }],
-        ['system_libcros==1', {
-          'link_settings': {
-            'libraries': [
-              '-lcrosapi',
-            ],
-          },
-        }],
       ],
     },
   ],
diff --git a/chrome/browser/chromeos/input_method/candidate_window_main.cc b/chrome/browser/chromeos/input_method/candidate_window_main.cc
index a8bc042..56252a1 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_main.cc
+++ b/chrome/browser/chromeos/input_method/candidate_window_main.cc
@@ -1,80 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/input_method/candidate_window.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/app_paths.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/process_util.h"
-#include "chrome/browser/chromeos/cros/cros_library_loader.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "grit/app_locale_settings.h"
-#include "third_party/cros/chromeos_cros_api.h"
-#include "views/focus/accelerator_handler.h"
-
+// TODO(yusukes): Modify build script so build bots don't build and install
+// candidate_window (crosbug.com/11380). Then, remove this file and the gyp
+// target (crosbug.com/11381).
 int main(int argc, char** argv) {
-  // Initialize gtk stuff.
-  g_thread_init(NULL);
-  g_type_init();
-  gtk_init(&argc, &argv);
-
-  // Initialize Chrome stuff.
-  base::AtExitManager exit_manager;
-  base::EnableTerminationOnHeapCorruption();
-  app::RegisterPathProvider();
-  CommandLine::Init(argc, argv);
-
-  // Check if the UI language code is passed from the command line,
-  // otherwise, default to "en-US".
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  std::string ui_language_code =
-      command_line.GetSwitchValueASCII(switches::kCandidateWindowLang);
-  if (ui_language_code.empty()) {
-    ui_language_code = "en-US";
-  }
-  ResourceBundle::InitSharedInstance(ui_language_code);
-
-  // Change the UI font if needed.
-  const std::string font_name =
-      l10n_util::GetStringUTF8(IDS_UI_FONT_FAMILY_CROS);
-  // The font name should not be empty here, but just in case.
-  if (font_name != "default" && !font_name.empty()) {
-    // Don't use gtk_util::SetGtkFont() in chrome/browser/gtk not to
-    // introduce a dependency to it.
-    g_object_set(gtk_settings_get_default(),
-                 "gtk-font-name", font_name.c_str(), NULL);
-  }
-
-  // Load libcros.
-  chrome::RegisterPathProvider();  // for libcros.so.
-  chromeos::CrosLibraryLoader lib_loader;
-  std::string error_string;
-  CHECK(lib_loader.Load(&error_string))
-      << "Failed to load libcros, " << error_string;
-
-  // Create the main message loop.
-  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
-
-  // Create the candidate window controller.
-  chromeos::CandidateWindowController controller;
-  if (!controller.Init()) {
-    return 1;
-  }
-
-  // Start the main loop.
-  views::AcceleratorHandler accelerator_handler;
-  MessageLoopForUI::current()->Run(&accelerator_handler);
-
   return 0;
 }
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc
index ced79ea..e31f2da 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -11,8 +11,6 @@
 
 #include "unicode/uloc.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_collator.h"
 #include "base/basictypes.h"
 #include "base/hash_tables.h"
 #include "base/scoped_ptr.h"
@@ -24,92 +22,24 @@
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
 #include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
 
 namespace {
 
-// Mapping from input method ID to keyboard overlay ID, which specifies the
-// layout and the glyphs of the keyboard overlay.
-// TODO(mazda): Move this list to whitelist.txt (http://crosbug.com/9682)
-const struct InputMethodIdToKeyboardOverlayId {
-  const char* input_method_id;
-  const char* keyboard_overlay_id;
-} kInputMethodIdToKeyboardOverlayId[] = {
-  { "xkb:nl::nld", "nl" },
-  { "xkb:be::nld", "nl" },
-  { "xkb:fr::fra", "fr" },
-  { "xkb:be::fra", "fr" },
-  { "xkb:ca::fra", "fr_CA" },
-  { "xkb:ch:fr:fra", "fr" },
-  { "xkb:de::ger", "de" },
-  { "xkb:be::ger", "de" },
-  { "xkb:ch::ger", "de" },
-  { "mozc", "en_US" },
-  { "mozc-jp", "ja" },
-  { "mozc-dv", "en_US_dvorak" },
-  { "xkb:jp::jpn", "ja" },
-  { "xkb:ru::rus", "ru" },
-  { "xkb:ru:phonetic:rus", "ru" },
-  { "m17n:th:kesmanee", "th" },
-  { "m17n:th:pattachote", "th" },
-  { "m17n:th:tis820", "th" },
-  { "chewing", "zh_TW" },
-  { "m17n:zh:cangjie", "zh_TW" },
-  { "m17n:zh:quick", "zh_TW" },
-  { "m17n:vi:tcvn", "vi" },
-  { "m17n:vi:telex", "vi" },
-  { "m17n:vi:viqr", "vi" },
-  { "m17n:vi:vni", "vi" },
-  { "xkb:us::eng", "en_US" },
-  { "xkb:us:intl:eng", "en_US" },
-  { "xkb:us:altgr-intl:eng", "en_US" },
-  { "xkb:us:dvorak:eng", "en_US_dvorak" },
-  // TODO(mazda): Add keyboard overlay definition for US Colemak.
-  { "xkb:us:colemak:eng", "en_US" },
-  { "hangul", "ko" },
-  { "pinyin", "zh_CN" },
-  { "m17n:ar:kbd", "ar" },
-  { "m17n:hi:itrans", "hi" },
-  { "m17n:fa:isiri", "ar" },
-  { "xkb:br::por", "pt_BR" },
-  { "xkb:bg::bul", "bg" },
-  { "xkb:bg:phonetic:bul", "bg" },
-  { "xkb:ca:eng:eng", "ca" },
-  { "xkb:cz::cze", "cs" },
-  { "xkb:ee::est", "et" },
-  { "xkb:es::spa", "es" },
-  { "xkb:es:cat:cat", "ca" },
-  { "xkb:dk::dan", "da" },
-  { "xkb:gr::gre", "el" },
-  { "xkb:il::heb", "iw" },
-  { "xkb:kr:kr104:kor", "ko" },
-  { "xkb:latam::spa", "es_419" },
-  { "xkb:lt::lit", "lt" },
-  { "xkb:lv:apostrophe:lav", "lv" },
-  { "xkb:hr::scr", "hr" },
-  { "xkb:gb:extd:eng", "en_GB" },
-  { "xkb:fi::fin", "fi" },
-  { "xkb:hu::hun", "hu" },
-  { "xkb:it::ita", "it" },
-  { "xkb:no::nob", "no" },
-  { "xkb:pl::pol", "pl" },
-  { "xkb:pt::por", "pt_PT" },
-  { "xkb:ro::rum", "ro" },
-  { "xkb:se::swe", "sv" },
-  { "xkb:sk::slo", "sk" },
-  { "xkb:si::slv", "sl" },
-  { "xkb:rs::srp", "sr" },
-  { "xkb:tr::tur", "tr" },
-  { "xkb:ua::ukr", "uk" },
-};
-
 // Map from language code to associated input method IDs, etc.
 typedef std::multimap<std::string, std::string> LanguageCodeToIdsMap;
+// Map from input method ID to associated input method descriptor.
+typedef std::map<std::string, chromeos::InputMethodDescriptor>
+    InputMethodIdToDescriptorMap;
+
 struct IdMaps {
   scoped_ptr<LanguageCodeToIdsMap> language_code_to_ids;
   scoped_ptr<std::map<std::string, std::string> > id_to_language_code;
-  scoped_ptr<std::map<std::string, std::string> > id_to_display_name;
-  scoped_ptr<std::map<std::string, std::string> > id_to_keyboard_overlay_id;
+  scoped_ptr<InputMethodIdToDescriptorMap> id_to_descriptor;
 
   // Returns the singleton instance.
   static IdMaps* GetInstance() {
@@ -126,32 +56,23 @@
       // TODO(yusukes): Handle this error in nicer way.
     }
 
+    // Clear the existing maps.
     language_code_to_ids->clear();
     id_to_language_code->clear();
-    id_to_display_name->clear();
-    id_to_keyboard_overlay_id->clear();
-
-    // Build the id to descriptor map for handling kExtraLanguages later.
-    typedef std::map<std::string,
-        const chromeos::InputMethodDescriptor*> DescMap;
-    DescMap id_to_descriptor_map;
+    id_to_descriptor->clear();
 
     for (size_t i = 0; i < supported_input_methods->size(); ++i) {
       const chromeos::InputMethodDescriptor& input_method =
           supported_input_methods->at(i);
       const std::string language_code =
           chromeos::input_method::GetLanguageCodeFromDescriptor(input_method);
-      AddInputMethodToMaps(language_code, input_method);
-      // Remember the pair.
-      id_to_descriptor_map.insert(
-          std::make_pair(input_method.id, &input_method));
-    }
-
-    for (size_t i = 0; i < arraysize(kInputMethodIdToKeyboardOverlayId); ++i) {
-      InputMethodIdToKeyboardOverlayId id_pair =
-          kInputMethodIdToKeyboardOverlayId[i];
-      id_to_keyboard_overlay_id->insert(
-          std::make_pair(id_pair.input_method_id, id_pair.keyboard_overlay_id));
+      language_code_to_ids->insert(
+          std::make_pair(language_code, input_method.id));
+      // Remember the pairs.
+      id_to_language_code->insert(
+          std::make_pair(input_method.id, language_code));
+      id_to_descriptor->insert(
+          std::make_pair(input_method.id, input_method));
     }
 
     // Go through the languages listed in kExtraLanguages.
@@ -159,12 +80,14 @@
     for (size_t i = 0; i < arraysize(kExtraLanguages); ++i) {
       const char* language_code = kExtraLanguages[i].language_code;
       const char* input_method_id = kExtraLanguages[i].input_method_id;
-      DescMap::const_iterator iter = id_to_descriptor_map.find(input_method_id);
+      InputMethodIdToDescriptorMap::const_iterator iter =
+          id_to_descriptor->find(input_method_id);
       // If the associated input method descriptor is found, add the
       // language code and the input method.
-      if (iter != id_to_descriptor_map.end()) {
-        const chromeos::InputMethodDescriptor& input_method = *(iter->second);
-        AddInputMethodToMaps(language_code, input_method);
+      if (iter != id_to_descriptor->end()) {
+        const chromeos::InputMethodDescriptor& input_method = iter->second;
+        language_code_to_ids->insert(
+            std::make_pair(language_code, input_method.id));
       }
     }
   }
@@ -172,23 +95,10 @@
  private:
   IdMaps() : language_code_to_ids(new LanguageCodeToIdsMap),
              id_to_language_code(new std::map<std::string, std::string>),
-             id_to_display_name(new std::map<std::string, std::string>),
-             id_to_keyboard_overlay_id(new std::map<std::string, std::string>) {
+             id_to_descriptor(new InputMethodIdToDescriptorMap) {
     ReloadMaps();
   }
 
-  void AddInputMethodToMaps(
-      const std::string& language_code,
-      const chromeos::InputMethodDescriptor& input_method) {
-    language_code_to_ids->insert(
-        std::make_pair(language_code, input_method.id));
-    id_to_language_code->insert(
-        std::make_pair(input_method.id, language_code));
-    id_to_display_name->insert(std::make_pair(
-        input_method.id,
-        chromeos::input_method::GetStringUTF8(input_method.display_name)));
-  }
-
   friend struct DefaultSingletonTraits<IdMaps>;
 
   DISALLOW_COPY_AND_ASSIGN(IdMaps);
@@ -270,6 +180,7 @@
   { "Japan", IDS_STATUSBAR_LAYOUT_JAPAN },
   { "Slovenia", IDS_STATUSBAR_LAYOUT_SLOVENIA },
   { "Germany", IDS_STATUSBAR_LAYOUT_GERMANY },
+  { "Germany - Neo 2", IDS_STATUSBAR_LAYOUT_GERMANY_NEO2 },
   { "Italy", IDS_STATUSBAR_LAYOUT_ITALY },
   { "Estonia", IDS_STATUSBAR_LAYOUT_ESTONIA },
   { "Hungary", IDS_STATUSBAR_LAYOUT_HUNGARY },
@@ -552,30 +463,26 @@
 }
 
 std::string GetKeyboardLayoutName(const std::string& input_method_id) {
-  if (!StartsWithASCII(input_method_id, "xkb:", true)) {
-    return "";
-  }
-
-  std::vector<std::string> splitted_id;
-  base::SplitString(input_method_id, ':', &splitted_id);
-  return (splitted_id.size() > 1) ? splitted_id[1] : "";
-}
-
-std::string GetKeyboardOverlayId(const std::string& input_method_id) {
-  const std::map<std::string, std::string>& id_map =
-      *(IdMaps::GetInstance()->id_to_keyboard_overlay_id);
-  std::map<std::string, std::string>::const_iterator iter =
-      id_map.find(input_method_id);
-  return (iter == id_map.end() ? "" : iter->second);
+  InputMethodIdToDescriptorMap::const_iterator iter
+      = IdMaps::GetInstance()->id_to_descriptor->find(input_method_id);
+  return (iter == IdMaps::GetInstance()->id_to_descriptor->end()) ?
+      "" : iter->second.keyboard_layout;
 }
 
 std::string GetInputMethodDisplayNameFromId(
     const std::string& input_method_id) {
-  static const char kDefaultDisplayName[] = "USA";
-  std::map<std::string, std::string>::const_iterator iter
-      = IdMaps::GetInstance()->id_to_display_name->find(input_method_id);
-  return (iter == IdMaps::GetInstance()->id_to_display_name->end()) ?
-      kDefaultDisplayName : iter->second;
+  InputMethodIdToDescriptorMap::const_iterator iter
+      = IdMaps::GetInstance()->id_to_descriptor->find(input_method_id);
+  return (iter == IdMaps::GetInstance()->id_to_descriptor->end()) ?
+      "" : GetStringUTF8(iter->second.display_name);
+}
+
+const chromeos::InputMethodDescriptor* GetInputMethodDescriptorFromId(
+    const std::string& input_method_id) {
+  InputMethodIdToDescriptorMap::const_iterator iter
+      = IdMaps::GetInstance()->id_to_descriptor->find(input_method_id);
+  return (iter == IdMaps::GetInstance()->id_to_descriptor->end()) ?
+      NULL : &(iter->second);
 }
 
 string16 GetLanguageDisplayNameFromCode(const std::string& language_code) {
@@ -671,8 +578,8 @@
   std::vector<std::string> input_method_ids;
   GetInputMethodIdsFromLanguageCode(language_code, type, &input_method_ids);
 
-  std::string keyboard = CrosLibrary::Get()->GetKeyboardLibrary()->
-      GetHardwareKeyboardLayoutName();
+  // Add the hardware keyboard.
+  const std::string keyboard = GetHardwareInputMethodId();
   if (std::count(input_method_ids.begin(), input_method_ids.end(),
                  keyboard) == 0) {
     input_method_ids.push_back(keyboard);
@@ -693,9 +600,36 @@
   }
 }
 
-void OnLocaleChanged() {
+std::string GetHardwareInputMethodId() {
+  if (!(g_browser_process && g_browser_process->local_state())) {
+    // This shouldn't happen but just in case.
+    LOG(ERROR) << "Local state is not yet ready";
+    return GetFallbackInputMethodDescriptor().id;
+  }
+
+  const std::string input_method_id =
+      g_browser_process->local_state()->GetString(
+          prefs::kHardwareKeyboardLayout);
+  if (input_method_id.empty()) {
+    // This is totally fine if it's empty. The hardware keyboard layout is
+    // not stored if startup_manifest.json (OEM customization data) is not
+    // present (ex. Cr48 doen't have that file).
+    return GetFallbackInputMethodDescriptor().id;
+  }
+  return input_method_id;
+}
+
+InputMethodDescriptor GetFallbackInputMethodDescriptor() {
+  return InputMethodDescriptor("xkb:us::eng", "USA", "us", "eng");
+}
+
+void ReloadInternalMaps() {
   IdMaps::GetInstance()->ReloadMaps();
 }
 
+void OnLocaleChanged() {
+  ReloadInternalMaps();
+}
+
 }  // namespace input_method
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_util.h b/chrome/browser/chromeos/input_method/input_method_util.h
index 66ba95f..184fa87 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.h
+++ b/chrome/browser/chromeos/input_method/input_method_util.h
@@ -71,9 +71,9 @@
 // Examples:
 //
 // "xkb:us::eng"       => "us"
-// "xkb:us:dvorak:eng" => "us"
+// "xkb:us:dvorak:eng" => "us(dvorak)"
 // "xkb:gb::eng"       => "gb"
-// "pinyin"            => ""
+// "pinyin"            => "us" (because Pinyin uses US keyboard layout)
 std::string GetKeyboardLayoutName(const std::string& input_method_id);
 
 // Gets the ID for the keyboard overlay from the given input method ID.
@@ -95,11 +95,18 @@
     const std::string& input_method_id);
 
 // Converts an input method ID to a display name of the IME. Returns
-// "USA" (US keyboard) when |input_method_id| is unknown.
+// an empty strng when |input_method_id| is unknown.
 // Examples: "pinyin" => "Pinyin"
 //           "m17n:ar:kbd" => "kbd (m17n)"
 std::string GetInputMethodDisplayNameFromId(const std::string& input_method_id);
 
+// Converts an input method ID to an input method descriptor. Returns NULL
+// when |input_method_id| is unknown.
+// Example: "pinyin" => { id: "pinyin", display_name: "Pinyin",
+//                        keyboard_layout: "us", language_code: "zh" }
+const chromeos::InputMethodDescriptor* GetInputMethodDescriptorFromId(
+    const std::string& input_method_id);
+
 // Converts a language code to a language display name, using the
 // current application locale. MaybeRewriteLanguageName() is called
 // internally.
@@ -149,6 +156,17 @@
 void EnableInputMethods(const std::string& language_code, InputMethodType type,
                         const std::string& initial_input_method_id);
 
+// Returns the input method ID of the hardware keyboard.
+std::string GetHardwareInputMethodId();
+
+// Returns the fallback input method descriptor (the very basic US
+// keyboard). This function is mostly used for testing, but may be used
+// as the fallback, when there is no other choice.
+InputMethodDescriptor GetFallbackInputMethodDescriptor();
+
+// This function should be called when Chrome's application locale is
+// changed, so that the internal maps of this library is reloaded.
+void OnLocaleChanged();
 
 // DO NOT USE Functions below. These are only exported for unit tests.
 void SortInputMethodIdsByNamesInternal(
@@ -161,7 +179,7 @@
     InputMethodType type,
     std::vector<std::string>* out_input_method_ids);
 
-void OnLocaleChanged();
+void ReloadInternalMaps();
 
 }  // namespace input_method
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
index 55cf34b..3890438 100644
--- a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
@@ -6,15 +6,30 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 namespace input_method {
 
-TEST(InputMethodUtilTest, GetStringUTF8) {
+class InputMethodUtilTest : public testing::Test {
+ public:
+  static void SetUpTestCase() {
+    // Reload the internal maps before running tests, with the stub
+    // libcros enabled, so that test data is loaded properly.
+    ScopedStubCrosEnabler stub_cros_enabler;
+    ReloadInternalMaps();
+  }
+
+ private:
+  // Ensure we always use the stub libcros in each test.
+  ScopedStubCrosEnabler stub_cros_enabler_;
+};
+
+TEST_F(InputMethodUtilTest, GetStringUTF8) {
   EXPECT_EQ("Pinyin input method",
             GetStringUTF8("Pinyin"));
   EXPECT_EQ("Japanese input method (for US Dvorak keyboard)",
@@ -23,14 +38,14 @@
             GetStringUTF8("Google Japanese Input (US Dvorak keyboard layout)"));
 }
 
-TEST(InputMethodUtilTest, StringIsSupported) {
+TEST_F(InputMethodUtilTest, StringIsSupported) {
   EXPECT_TRUE(StringIsSupported("Hiragana"));
   EXPECT_TRUE(StringIsSupported("Latin"));
   EXPECT_TRUE(StringIsSupported("Direct input"));
   EXPECT_FALSE(StringIsSupported("####THIS_STRING_IS_NOT_SUPPORTED####"));
 }
 
-TEST(InputMethodUtilTest, NormalizeLanguageCode) {
+TEST_F(InputMethodUtilTest, NormalizeLanguageCode) {
   // TODO(yusukes): test all language codes that IBus provides.
   EXPECT_EQ("ja", NormalizeLanguageCode("ja"));
   EXPECT_EQ("ja", NormalizeLanguageCode("jpn"));
@@ -53,12 +68,12 @@
   EXPECT_EQ("sk", NormalizeLanguageCode("slo"));
 }
 
-TEST(InputMethodUtilTest, IsKeyboardLayout) {
+TEST_F(InputMethodUtilTest, IsKeyboardLayout) {
   EXPECT_TRUE(IsKeyboardLayout("xkb:us::eng"));
   EXPECT_FALSE(IsKeyboardLayout("anthy"));
 }
 
-TEST(InputMethodUtilTest, GetLanguageCodeFromDescriptor) {
+TEST_F(InputMethodUtilTest, GetLanguageCodeFromDescriptor) {
   EXPECT_EQ("ja", GetLanguageCodeFromDescriptor(
       InputMethodDescriptor("anthy", "Anthy", "us", "ja")));
   EXPECT_EQ("zh-TW", GetLanguageCodeFromDescriptor(
@@ -77,149 +92,55 @@
       InputMethodDescriptor("xkb:uk::eng", "United Kingdom", "us", "eng")));
 }
 
-TEST(InputMethodUtilTest, GetKeyboardLayoutName) {
-  // Unsupported cases
+TEST_F(InputMethodUtilTest, GetKeyboardLayoutName) {
+  // Unsupported case.
   EXPECT_EQ("", GetKeyboardLayoutName("UNSUPPORTED_ID"));
-  EXPECT_EQ("", GetKeyboardLayoutName("chewing"));
-  EXPECT_EQ("", GetKeyboardLayoutName("hangul"));
-  EXPECT_EQ("", GetKeyboardLayoutName("mozc"));
-  EXPECT_EQ("", GetKeyboardLayoutName("mozc-jp"));
-  EXPECT_EQ("", GetKeyboardLayoutName("pinyin"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:ar:kbd"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:he:kbd"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:hi:itrans"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:fa:isiri"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:th:kesmanee"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:th:pattachote"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:th:tis820"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:vi:tcvn"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:vi:telex"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:vi:viqr"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:vi:vni"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:zh:cangjie"));
-  EXPECT_EQ("", GetKeyboardLayoutName("m17n:zh:quick"));
 
-  // Supported cases
-  EXPECT_EQ("be", GetKeyboardLayoutName("xkb:be::fra"));
-  EXPECT_EQ("br", GetKeyboardLayoutName("xkb:br::por"));
-  EXPECT_EQ("bg", GetKeyboardLayoutName("xkb:bg::bul"));
-  EXPECT_EQ("cz", GetKeyboardLayoutName("xkb:cz::cze"));
-  EXPECT_EQ("de", GetKeyboardLayoutName("xkb:de::ger"));
-  EXPECT_EQ("ee", GetKeyboardLayoutName("xkb:ee::est"));
+  // Supported cases (samples).
+  EXPECT_EQ("jp", GetKeyboardLayoutName("mozc-jp"));
+  EXPECT_EQ("us", GetKeyboardLayoutName("pinyin"));
+  EXPECT_EQ("us", GetKeyboardLayoutName("m17n:ar:kbd"));
   EXPECT_EQ("es", GetKeyboardLayoutName("xkb:es::spa"));
-  EXPECT_EQ("es", GetKeyboardLayoutName("xkb:es:cat:cat"));
-  EXPECT_EQ("dk", GetKeyboardLayoutName("xkb:dk::dan"));
-  EXPECT_EQ("gr", GetKeyboardLayoutName("xkb:gr::gre"));
-  EXPECT_EQ("lt", GetKeyboardLayoutName("xkb:lt::lit"));
-  EXPECT_EQ("lv", GetKeyboardLayoutName("xkb:lv::lav"));
-  EXPECT_EQ("hr", GetKeyboardLayoutName("xkb:hr::scr"));
-  EXPECT_EQ("nl", GetKeyboardLayoutName("xkb:nl::nld"));
-  EXPECT_EQ("gb", GetKeyboardLayoutName("xkb:gb::eng"));
-  EXPECT_EQ("fi", GetKeyboardLayoutName("xkb:fi::fin"));
-  EXPECT_EQ("fr", GetKeyboardLayoutName("xkb:fr::fra"));
-  EXPECT_EQ("hu", GetKeyboardLayoutName("xkb:hu::hun"));
-  EXPECT_EQ("it", GetKeyboardLayoutName("xkb:it::ita"));
-  EXPECT_EQ("jp", GetKeyboardLayoutName("xkb:jp::jpn"));
-  EXPECT_EQ("no", GetKeyboardLayoutName("xkb:no::nor"));
-  EXPECT_EQ("pl", GetKeyboardLayoutName("xkb:pl::pol"));
-  EXPECT_EQ("pt", GetKeyboardLayoutName("xkb:pt::por"));
-  EXPECT_EQ("ro", GetKeyboardLayoutName("xkb:ro::rum"));
-  EXPECT_EQ("se", GetKeyboardLayoutName("xkb:se::swe"));
-  EXPECT_EQ("sk", GetKeyboardLayoutName("xkb:sk::slo"));
-  EXPECT_EQ("si", GetKeyboardLayoutName("xkb:si::slv"));
-  EXPECT_EQ("rs", GetKeyboardLayoutName("xkb:rs::srp"));
-  EXPECT_EQ("ch", GetKeyboardLayoutName("xkb:ch::ger"));
-  EXPECT_EQ("ru", GetKeyboardLayoutName("xkb:ru::rus"));
-  EXPECT_EQ("tr", GetKeyboardLayoutName("xkb:tr::tur"));
-  EXPECT_EQ("ua", GetKeyboardLayoutName("xkb:ua::ukr"));
+  EXPECT_EQ("es(cat)", GetKeyboardLayoutName("xkb:es:cat:cat"));
+  EXPECT_EQ("gb(extd)", GetKeyboardLayoutName("xkb:gb:extd:eng"));
   EXPECT_EQ("us", GetKeyboardLayoutName("xkb:us::eng"));
-  EXPECT_EQ("us", GetKeyboardLayoutName("xkb:us:dvorak:eng"));
-  EXPECT_EQ("us", GetKeyboardLayoutName("xkb:us:colemak:eng"));
+  EXPECT_EQ("us(dvorak)", GetKeyboardLayoutName("xkb:us:dvorak:eng"));
+  EXPECT_EQ("us(colemak)", GetKeyboardLayoutName("xkb:us:colemak:eng"));
+  EXPECT_EQ("de(neo)", GetKeyboardLayoutName("xkb:de:neo:ger"));
 }
 
-TEST(InputMethodUtilTest, GetKeyboardOverlayId) {
-  // Invalid IDs
-  EXPECT_EQ("", GetKeyboardOverlayId(""));
-  EXPECT_EQ("", GetKeyboardOverlayId("aaa"));
-
-  // Valid IDs
-  EXPECT_EQ("nl", GetKeyboardOverlayId("xkb:nl::nld"));
-  EXPECT_EQ("nl", GetKeyboardOverlayId("xkb:be::nld"));
-  EXPECT_EQ("fr", GetKeyboardOverlayId("xkb:fr::fra"));
-  EXPECT_EQ("fr", GetKeyboardOverlayId("xkb:be::fra"));
-  EXPECT_EQ("fr_CA", GetKeyboardOverlayId("xkb:ca::fra"));
-  EXPECT_EQ("fr", GetKeyboardOverlayId("xkb:ch:fr:fra"));
-  EXPECT_EQ("de", GetKeyboardOverlayId("xkb:de::ger"));
-  EXPECT_EQ("de", GetKeyboardOverlayId("xkb:be::ger"));
-  EXPECT_EQ("de", GetKeyboardOverlayId("xkb:ch::ger"));
-  EXPECT_EQ("en_US", GetKeyboardOverlayId("mozc"));
-  EXPECT_EQ("ja", GetKeyboardOverlayId("mozc-jp"));
-  EXPECT_EQ("en_US_dvorak", GetKeyboardOverlayId("mozc-dv"));
-  EXPECT_EQ("ja", GetKeyboardOverlayId("xkb:jp::jpn"));
-  EXPECT_EQ("ru", GetKeyboardOverlayId("xkb:ru::rus"));
-  EXPECT_EQ("ru", GetKeyboardOverlayId("xkb:ru:phonetic:rus"));
-  EXPECT_EQ("th", GetKeyboardOverlayId("m17n:th:kesmanee"));
-  EXPECT_EQ("th", GetKeyboardOverlayId("m17n:th:pattachote"));
-  EXPECT_EQ("th", GetKeyboardOverlayId("m17n:th:tis820"));
-  EXPECT_EQ("zh_TW", GetKeyboardOverlayId("chewing"));
-  EXPECT_EQ("zh_TW", GetKeyboardOverlayId("m17n:zh:cangjie"));
-  EXPECT_EQ("zh_TW", GetKeyboardOverlayId("m17n:zh:quick"));
-  EXPECT_EQ("vi", GetKeyboardOverlayId("m17n:vi:tcvn"));
-  EXPECT_EQ("vi", GetKeyboardOverlayId("m17n:vi:telex"));
-  EXPECT_EQ("vi", GetKeyboardOverlayId("m17n:vi:viqr"));
-  EXPECT_EQ("vi", GetKeyboardOverlayId("m17n:vi:vni"));
-  EXPECT_EQ("en_US", GetKeyboardOverlayId("xkb:us::eng"));
-  EXPECT_EQ("en_US", GetKeyboardOverlayId("xkb:us:intl:eng"));
-  EXPECT_EQ("en_US", GetKeyboardOverlayId("xkb:us:altgr-intl:eng"));
-  EXPECT_EQ("en_US_dvorak", GetKeyboardOverlayId("xkb:us:dvorak:eng"));
-  // TODO(mazda): Add keyboard overlay definition for US Colemak.
-  EXPECT_EQ("en_US", GetKeyboardOverlayId("xkb:us:colemak:eng"));
-  EXPECT_EQ("ko", GetKeyboardOverlayId("hangul"));
-  EXPECT_EQ("zh_CN", GetKeyboardOverlayId("pinyin"));
-  EXPECT_EQ("ar", GetKeyboardOverlayId("m17n:ar:kbd"));
-  EXPECT_EQ("hi", GetKeyboardOverlayId("m17n:hi:itrans"));
-  EXPECT_EQ("ar", GetKeyboardOverlayId("m17n:fa:isiri"));
-  EXPECT_EQ("pt_BR", GetKeyboardOverlayId("xkb:br::por"));
-  EXPECT_EQ("bg", GetKeyboardOverlayId("xkb:bg::bul"));
-  EXPECT_EQ("bg", GetKeyboardOverlayId("xkb:bg:phonetic:bul"));
-  EXPECT_EQ("ca", GetKeyboardOverlayId("xkb:ca:eng:eng"));
-  EXPECT_EQ("cs", GetKeyboardOverlayId("xkb:cz::cze"));
-  EXPECT_EQ("et", GetKeyboardOverlayId("xkb:ee::est"));
-  EXPECT_EQ("es", GetKeyboardOverlayId("xkb:es::spa"));
-  EXPECT_EQ("ca", GetKeyboardOverlayId("xkb:es:cat:cat"));
-  EXPECT_EQ("da", GetKeyboardOverlayId("xkb:dk::dan"));
-  EXPECT_EQ("el", GetKeyboardOverlayId("xkb:gr::gre"));
-  EXPECT_EQ("iw", GetKeyboardOverlayId("xkb:il::heb"));
-  EXPECT_EQ("ko", GetKeyboardOverlayId("xkb:kr:kr104:kor"));
-  EXPECT_EQ("es_419", GetKeyboardOverlayId("xkb:latam::spa"));
-  EXPECT_EQ("lt", GetKeyboardOverlayId("xkb:lt::lit"));
-  EXPECT_EQ("lv", GetKeyboardOverlayId("xkb:lv:apostrophe:lav"));
-  EXPECT_EQ("hr", GetKeyboardOverlayId("xkb:hr::scr"));
-  EXPECT_EQ("en_GB", GetKeyboardOverlayId("xkb:gb:extd:eng"));
-  EXPECT_EQ("fi", GetKeyboardOverlayId("xkb:fi::fin"));
-  EXPECT_EQ("hu", GetKeyboardOverlayId("xkb:hu::hun"));
-  EXPECT_EQ("it", GetKeyboardOverlayId("xkb:it::ita"));
-  EXPECT_EQ("no", GetKeyboardOverlayId("xkb:no::nob"));
-  EXPECT_EQ("pl", GetKeyboardOverlayId("xkb:pl::pol"));
-  EXPECT_EQ("pt_PT", GetKeyboardOverlayId("xkb:pt::por"));
-  EXPECT_EQ("ro", GetKeyboardOverlayId("xkb:ro::rum"));
-  EXPECT_EQ("sv", GetKeyboardOverlayId("xkb:se::swe"));
-  EXPECT_EQ("sk", GetKeyboardOverlayId("xkb:sk::slo"));
-  EXPECT_EQ("sl", GetKeyboardOverlayId("xkb:si::slv"));
-  EXPECT_EQ("sr", GetKeyboardOverlayId("xkb:rs::srp"));
-  EXPECT_EQ("tr", GetKeyboardOverlayId("xkb:tr::tur"));
-  EXPECT_EQ("uk", GetKeyboardOverlayId("xkb:ua::ukr"));
+TEST_F(InputMethodUtilTest, GetLanguageCodeFromInputMethodId) {
+  // Make sure that the -CN is added properly.
+  EXPECT_EQ("zh-CN", GetLanguageCodeFromInputMethodId("pinyin"));
 }
 
-TEST(InputMethodUtilTest, GetLanguageDisplayNameFromCode) {
-  EXPECT_EQ(UTF8ToUTF16("Finnish"), GetLanguageDisplayNameFromCode("fi"));
+TEST_F(InputMethodUtilTest, GetInputMethodDisplayNameFromId) {
+  EXPECT_EQ("Pinyin input method", GetInputMethodDisplayNameFromId("pinyin"));
+  EXPECT_EQ("English (United States)",
+            GetInputMethodDisplayNameFromId("xkb:us::eng"));
+  EXPECT_EQ("", GetInputMethodDisplayNameFromId("nonexistent"));
 }
 
-TEST(InputMethodUtilTest, GetLanguageNativeDisplayNameFromCode) {
+TEST_F(InputMethodUtilTest, GetInputMethodDescriptorFromId) {
+  EXPECT_EQ(NULL, GetInputMethodDescriptorFromId("non_existent"));
+
+  const InputMethodDescriptor* descriptor =
+      GetInputMethodDescriptorFromId("pinyin");
+  ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
+  EXPECT_EQ("pinyin", descriptor->id);
+  EXPECT_EQ("Pinyin", descriptor->display_name);
+  EXPECT_EQ("us", descriptor->keyboard_layout);
+  // This is not zh-CN as the language code in InputMethodDescriptor is
+  // not normalized to our format. The normalization is done in
+  // GetLanguageCodeFromDescriptor().
+  EXPECT_EQ("zh", descriptor->language_code);
+}
+
+TEST_F(InputMethodUtilTest, GetLanguageNativeDisplayNameFromCode) {
   EXPECT_EQ(UTF8ToUTF16("suomi"), GetLanguageNativeDisplayNameFromCode("fi"));
 }
 
-TEST(InputMethodUtilTest, SortLanguageCodesByNames) {
+TEST_F(InputMethodUtilTest, SortLanguageCodesByNames) {
   std::vector<std::string> language_codes;
   // Check if this function can handle an empty list.
   SortLanguageCodesByNames(&language_codes);
@@ -244,7 +165,7 @@
   ASSERT_EQ("t",  language_codes[3]);  // Others
 }
 
-TEST(LanguageConfigModelTest, SortInputMethodIdsByNamesInternal) {
+TEST_F(InputMethodUtilTest, SortInputMethodIdsByNamesInternal) {
   std::map<std::string, std::string> id_to_language_code_map;
   id_to_language_code_map.insert(std::make_pair("mozc", "ja"));
   id_to_language_code_map.insert(std::make_pair("mozc-jp", "ja"));
@@ -284,7 +205,7 @@
   ASSERT_EQ("mozc-jp", input_method_ids[3]);         // Japanese
 }
 
-TEST(LanguageConfigModelTest, GetInputMethodIdsForLanguageCode) {
+TEST_F(InputMethodUtilTest, GetInputMethodIdsForLanguageCode) {
   std::multimap<std::string, std::string> language_code_to_ids_map;
   language_code_to_ids_map.insert(std::make_pair("ja", "mozc"));
   language_code_to_ids_map.insert(std::make_pair("ja", "mozc-jp"));
diff --git a/chrome/browser/chromeos/language_preferences.h b/chrome/browser/chromeos/language_preferences.h
index 2dfb95e..bb00d5d 100644
--- a/chrome/browser/chromeos/language_preferences.h
+++ b/chrome/browser/chromeos/language_preferences.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -145,7 +145,7 @@
 // ---------------------------------------------------------------------------
 // TODO(yusukes): Temporary solution for View version of modifier key remapper.
 // Remove RemapType and kXkbModifierMultipleChoicePrefs when we finish to
-// migrate to DOMUI.
+// migrate to WebUI.
 enum RemapType {
   kNoRemap = 0,
   kSwapCtrlAndAlt = 1,
diff --git a/chrome/browser/chromeos/locale_change_guard.cc b/chrome/browser/chromeos/locale_change_guard.cc
new file mode 100644
index 0000000..bf992cd
--- /dev/null
+++ b/chrome/browser/chromeos/locale_change_guard.cc
@@ -0,0 +1,178 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/locale_change_guard.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/notifications/system_notification.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/notifications/notification_delegate.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+base::LazyInstance<chromeos::LocaleChangeGuard> g_locale_change_guard(
+    base::LINKER_INITIALIZED);
+
+}  // namespace
+
+namespace chromeos {
+
+class LocaleChangeGuard::Delegate : public NotificationDelegate {
+ public:
+  explicit Delegate(chromeos::LocaleChangeGuard* master) : master_(master) {}
+  void Close(bool by_user);
+  void Display() {}
+  void Error() {}
+  void Click() {}
+  std::string id() const;
+
+ private:
+  chromeos::LocaleChangeGuard* master_;
+
+  DISALLOW_COPY_AND_ASSIGN(Delegate);
+};
+
+LocaleChangeGuard::LocaleChangeGuard()
+    : profile_id_(Profile::InvalidProfileId),
+      tab_contents_(NULL),
+      note_(NULL),
+      reverted_(false) {
+}
+
+void LocaleChangeGuard::RevertLocaleChange(const ListValue* list) {
+  if (note_ == NULL ||
+      tab_contents_ == NULL ||
+      from_locale_.empty() ||
+      to_locale_.empty()) {
+    NOTREACHED();
+    return;
+  }
+  if (reverted_)
+    return;
+
+  PrefService* prefs = tab_contents_->profile()->GetPrefs();
+  if (prefs == NULL)
+    return;
+
+  reverted_ = true;
+  UserMetrics::RecordAction(UserMetricsAction("LanguageChange_Revert"));
+  tab_contents_->profile()->ChangeAppLocale(
+      from_locale_, Profile::APP_LOCALE_CHANGED_VIA_REVERT);
+
+  Browser* browser = Browser::GetBrowserForController(
+      &tab_contents_->controller(), NULL);
+  if (browser)
+    browser->ExecuteCommand(IDC_EXIT);
+}
+
+void LocaleChangeGuard::CheckLocaleChange(TabContents* tab_contents) {
+  // We want notification to be shown no more than once per session.
+  if (note_ != NULL)
+    return;
+  DCHECK(note_ == NULL && tab_contents_ == NULL);
+  DCHECK(from_locale_.empty() && to_locale_.empty());
+
+  // We check profile Id because:
+  // (1) we want to exit fast in common case when nothing should be done.
+  // (2) on ChromeOS this guard may be invoked for a dummy profile first time.
+  ProfileId cur_profile_id = tab_contents->profile()->GetRuntimeId();
+  if (cur_profile_id == profile_id_)
+    return;  // We have already checked this profile, exiting fast.
+  profile_id_ = cur_profile_id;
+
+  std::string cur_locale = g_browser_process->GetApplicationLocale();
+  if (cur_locale.empty()) {
+    NOTREACHED();
+    return;
+  }
+
+  PrefService* prefs = tab_contents->profile()->GetPrefs();
+  if (prefs == NULL)
+    return;
+
+  std::string to_locale = prefs->GetString(prefs::kApplicationLocale);
+  if (to_locale != cur_locale) {
+    // This conditional branch can occur in cases like:
+    // (1) kApplicationLocale preference was modified by synchronization;
+    // (2) kApplicationLocale is managed by policy.
+    return;
+  }
+
+  std::string from_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
+  if (from_locale.empty() || from_locale == to_locale)
+    return;  // No locale change was detected, just exit.
+
+  if (prefs->GetString(prefs::kApplicationLocaleAccepted) == to_locale)
+    return;  // Already accepted.
+
+  // Locale change detected, showing notification.
+  from_locale_ = from_locale;
+  to_locale_ = to_locale;
+  tab_contents_ = tab_contents;
+  note_.reset(new chromeos::SystemNotification(
+      tab_contents->profile(),
+      new Delegate(this),
+      IDR_DEFAULT_FAVICON,
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE)));
+  note_->Show(
+      l10n_util::GetStringFUTF16(
+          IDS_LOCALE_CHANGE_MESSAGE,
+          l10n_util::GetDisplayNameForLocale(from_locale_, to_locale_, true),
+          l10n_util::GetDisplayNameForLocale(to_locale_, to_locale_, true)),
+      l10n_util::GetStringUTF16(IDS_LOCALE_CHANGE_REVERT_MESSAGE),
+      NewCallback(this, &LocaleChangeGuard::RevertLocaleChange),
+      true,  // urgent
+      false);  // non-sticky
+}
+
+void LocaleChangeGuard::AcceptLocaleChange() {
+  if (note_ == NULL ||
+      tab_contents_ == NULL ||
+      from_locale_.empty() ||
+      to_locale_.empty()) {
+    NOTREACHED();
+    return;
+  }
+
+  // Check whether locale has been reverted or changed.
+  // If not: mark current locale as accepted.
+  if (reverted_)
+    return;
+  PrefService* prefs = tab_contents_->profile()->GetPrefs();
+  if (prefs == NULL)
+    return;
+  if (prefs->GetString(prefs::kApplicationLocale) != to_locale_)
+    return;
+  UserMetrics::RecordAction(UserMetricsAction("LanguageChange_Accept"));
+  prefs->SetString(prefs::kApplicationLocaleBackup, to_locale_);
+  prefs->SetString(prefs::kApplicationLocaleAccepted, to_locale_);
+  prefs->ScheduleSavePersistentPrefs();
+}
+
+// static
+void LocaleChangeGuard::Check(TabContents* tab_contents) {
+  g_locale_change_guard.Get().CheckLocaleChange(tab_contents);
+}
+
+void LocaleChangeGuard::Delegate::Close(bool by_user) {
+  if (by_user)
+    master_->AcceptLocaleChange();
+}
+
+std::string LocaleChangeGuard::Delegate::id() const {
+  // Arbitrary unique Id.
+  return "8c386938-1e3f-11e0-ac7b-18a90520e2e5";
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/locale_change_guard.h b/chrome/browser/chromeos/locale_change_guard.h
new file mode 100644
index 0000000..0391761
--- /dev/null
+++ b/chrome/browser/chromeos/locale_change_guard.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_LOCALE_CHANGE_GUARD_H_
+#define CHROME_BROWSER_CHROMEOS_LOCALE_CHANGE_GUARD_H_
+#pragma once
+
+#include "base/lazy_instance.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/profiles/profile.h"
+
+class ListValue;
+class TabContents;
+
+namespace chromeos {
+
+class SystemNotification;
+
+class LocaleChangeGuard {
+ public:
+  // When called first time for user profile: performs check whether
+  // locale has been changed automatically recently (based on synchronized user
+  // preference).  If so: shows notification that allows user to revert change.
+  // On subsequent calls: does nothing (hopefully fast).
+  static void Check(TabContents* tab_contents);
+
+ private:
+  class Delegate;
+
+  LocaleChangeGuard();
+  void CheckLocaleChange(TabContents* tab_contents);
+  void RevertLocaleChange(const ListValue* list);
+  void AcceptLocaleChange();
+
+  std::string from_locale_;
+  std::string to_locale_;
+  ProfileId profile_id_;
+  TabContents* tab_contents_;
+  scoped_ptr<chromeos::SystemNotification> note_;
+  bool reverted_;
+
+  friend struct base::DefaultLazyInstanceTraits<LocaleChangeGuard>;
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOCALE_CHANGE_GUARD_H_
diff --git a/chrome/browser/chromeos/login/account_creation_view.cc b/chrome/browser/chromeos/login/account_creation_view.cc
index 05c66b5..d9d5124 100644
--- a/chrome/browser/chromeos/login/account_creation_view.cc
+++ b/chrome/browser/chromeos/login/account_creation_view.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/login/account_creation_view.h"
 
 #include "base/string_util.h"
+#include "chrome/common/autofill_messages.h"
 #include "webkit/glue/form_data.h"
 
 using webkit_glue::FormData;
@@ -15,8 +16,7 @@
 const char kEmailFieldName[] = "Email";
 const char kDomainFieldName[] = "edk";
 
-class AccountCreationTabContents : public WizardWebPageViewTabContents,
-                                   public RenderViewHostDelegate::AutoFill {
+class AccountCreationTabContents : public WizardWebPageViewTabContents {
  public:
   AccountCreationTabContents(Profile* profile,
                              SiteInstance* site_instance,
@@ -26,11 +26,27 @@
         delegate_(delegate) {
   }
 
-  virtual RenderViewHostDelegate::AutoFill* GetAutoFillDelegate() {
-    return this;
+  // Overriden from TabContents.
+  virtual bool OnMessageReceived(const IPC::Message& message) {
+    bool handled = true;
+    IPC_BEGIN_MESSAGE_MAP(AccountCreationTabContents, message)
+      IPC_MESSAGE_HANDLER(AutoFillHostMsg_FormSubmitted, OnFormSubmitted)
+      IPC_MESSAGE_HANDLER_GENERIC(AutoFillHostMsg_FormsSeen, )
+      IPC_MESSAGE_HANDLER_GENERIC(AutoFillHostMsg_QueryFormFieldAutoFill, )
+      IPC_MESSAGE_HANDLER_GENERIC(AutoFillHostMsg_ShowAutoFillDialog, )
+      IPC_MESSAGE_HANDLER_GENERIC(AutoFillHostMsg_FillAutoFillFormData, )
+      IPC_MESSAGE_HANDLER_GENERIC(AutoFillHostMsg_DidFillAutoFillFormData, )
+      IPC_MESSAGE_HANDLER_GENERIC(AutoFillHostMsg_DidShowAutoFillSuggestions, )
+      IPC_MESSAGE_UNHANDLED(handled = false)
+    IPC_END_MESSAGE_MAP()
+
+    if (handled)
+      return true;
+    return TabContents::OnMessageReceived(message);
   }
 
-  virtual void FormSubmitted(const FormData& form) {
+ private:
+  void OnFormSubmitted(const FormData& form) {
     if (UTF16ToASCII(form.name) == kCreateAccountFormName) {
       std::string user_name;
       std::string domain;
@@ -51,26 +67,6 @@
     }
   }
 
-  virtual void FormsSeen(const std::vector<FormData>& forms) {
-  }
-
-  virtual bool GetAutoFillSuggestions(const webkit_glue::FormData& form,
-                                      const webkit_glue::FormField& field) {
-    return false;
-  }
-
-  virtual bool FillAutoFillFormData(int query_id,
-                                    const webkit_glue::FormData& form,
-                                    const webkit_glue::FormField& field,
-                                    int unique_id) {
-    return false;
-  }
-
-  virtual void ShowAutoFillDialog() {}
-
-  virtual void Reset() {}
-
- private:
   AccountCreationViewDelegate* delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(AccountCreationTabContents);
diff --git a/chrome/browser/chromeos/login/account_screen.cc b/chrome/browser/chromeos/login/account_screen.cc
index 7d08f2a..e650b3e 100644
--- a/chrome/browser/chromeos/login/account_screen.cc
+++ b/chrome/browser/chromeos/login/account_screen.cc
@@ -126,7 +126,7 @@
     source->render_view_host()->InsertCSSInWebFrame(
         L"", kCreateAccountCSS, "");
     source->render_view_host()->ExecuteJavascriptInWebFrame(
-        L"", ASCIIToWide(kCreateAccountJS));
+        string16(), ASCIIToUTF16(kCreateAccountJS));
   }
 }
 
diff --git a/chrome/browser/chromeos/login/account_screen_browsertest.cc b/chrome/browser/chromeos/login/account_screen_browsertest.cc
deleted file mode 100644
index 7b9e8cf..0000000
--- a/chrome/browser/chromeos/login/account_screen_browsertest.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/child_process_security_policy.h"
-#include "chrome/browser/chromeos/login/account_screen.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/in_process_browser_test.h"
-#include "chrome/test/ui_test_utils.h"
-#include "net/test/test_server.h"
-#include "net/url_request/url_request_about_job.h"
-#include "net/url_request/url_request_filter.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromeos {
-
-class AccountScreenTest : public WizardInProcessBrowserTest {
- public:
-  AccountScreenTest(): WizardInProcessBrowserTest("account") {
-  }
-
- protected:
-  // Overridden from WizardInProcessBrowserTest:
-  virtual void SetUpWizard() {
-    ASSERT_TRUE(test_server()->Start());
-    GURL new_account_page_url(test_server()->GetURL("files/new_account.html"));
-    AccountScreen::set_new_account_page_url(new_account_page_url);
-    AccountScreen::set_check_for_https(false);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AccountScreenTest);
-};
-
-#if defined(OFFICIAL_BUILD)
-// Flaky on official build on autotest. Since this is not
-// used in Official build, i'm disabling it.
-// See crosbug.com/8517 .
-#define MAYBE_TestBasic DISABLED_TestBasic
-#else
-#define MAYBE_TestBasic TestBasic
-#endif
-
-// A basic test. It does not care how things evolve after the URL is
-// loaded. Thus no message loop is started. Just check that initial
-// status is expected.
-IN_PROC_BROWSER_TEST_F(AccountScreenTest, MAYBE_TestBasic) {
-  ASSERT_TRUE(controller());
-  EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());
-}
-
-static void QuitUIMessageLoop() {
-  MessageLoopForUI::current()->Quit();
-}
-
-static bool inspector_called = false;  // had to use global flag as
-                                       // InspectorHook() doesn't have context.
-
-static net::URLRequestJob* InspectorHook(net::URLRequest* request,
-                                         const std::string& scheme) {
-  VLOG(1) << "Intercepted: " << request->url() << ", scheme: " << scheme;
-
-  // Expect that the parameters are the same as new_account.html gave us.
-  EXPECT_STREQ("cros://inspector/?param1=value1+param2",
-               request->url().spec().c_str());
-  inspector_called = true;
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          NewRunnableFunction(QuitUIMessageLoop));
-
-  // Do not navigate to the given URL. Navigate to about:blank instead.
-  return new net::URLRequestAboutJob(request);
-}
-
-// Sometimes times out: http://crbug.com/60050.
-IN_PROC_BROWSER_TEST_F(AccountScreenTest, DISABLED_TestSchemeInspector) {
-  ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
-      chrome::kCrosScheme);
-  net::URLRequestFilter::GetInstance()->AddHostnameHandler(chrome::kCrosScheme,
-                                                           "inspector",
-                                                            &InspectorHook);
-  EXPECT_FALSE(inspector_called);
-  ui_test_utils::RunMessageLoop();
-  EXPECT_TRUE(inspector_called);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/apply_services_customization.cc b/chrome/browser/chromeos/login/apply_services_customization.cc
index 58e8e1d..4e51c34 100644
--- a/chrome/browser/chromeos/login/apply_services_customization.cc
+++ b/chrome/browser/chromeos/login/apply_services_customization.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/customization_document.h"
@@ -20,7 +21,6 @@
 namespace {
 
 // URL where to fetch OEM services customization manifest from.
-// TODO(denisromanov): Change this to real URL when it becomes available.
 const char kServicesCustomizationManifestUrl[] =
     "file:///mnt/partner_partition/etc/chromeos/services_manifest.json";
 
@@ -36,8 +36,9 @@
 
 }  // namespace
 
-namespace chromeos {
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::ApplyServicesCustomization);
 
+namespace chromeos {
 
 // static
 void ApplyServicesCustomization::StartIfNeeded() {
@@ -79,18 +80,14 @@
   }
 
   if (url_.SchemeIsFile()) {
-    std::string manifest;
-    if (file_util::ReadFileToString(FilePath(url_.path()), &manifest)) {
-      Apply(manifest);
-    } else {
-      LOG(ERROR) << "Failed to load services customization manifest from: "
-                 << url_.path();
-    }
-
-    return false;
+    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+        NewRunnableMethod(this,
+            &ApplyServicesCustomization::ReadFileInBackground,
+            FilePath(url_.path())));
+  } else {
+    StartFileFetch();
   }
 
-  StartFileFetch();
   return true;
 }
 
@@ -125,7 +122,29 @@
   MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
+void ApplyServicesCustomization::ReadFileInBackground(const FilePath& file) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  std::string manifest;
+  if (file_util::ReadFileToString(file, &manifest)) {
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(
+            this, &ApplyServicesCustomization::ApplyAndDelete, manifest));
+  } else {
+    VLOG(1) << "Failed to load services customization manifest from: "
+            << file.value();
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
+  }
+}
+
+void ApplyServicesCustomization::ApplyAndDelete(const std::string& manifest) {
+  Apply(manifest);
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
 void ApplyServicesCustomization::Apply(const std::string& manifest) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
   chromeos::ServicesCustomizationDocument customization;
   if (!customization.LoadManifestFromString(manifest)) {
     LOG(ERROR) << "Failed to partner parse services customizations manifest";
@@ -146,4 +165,4 @@
   SetApplied(true);
 }
 
-}
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/apply_services_customization.h b/chrome/browser/chromeos/login/apply_services_customization.h
index 757ce7c..577b94d 100644
--- a/chrome/browser/chromeos/login/apply_services_customization.h
+++ b/chrome/browser/chromeos/login/apply_services_customization.h
@@ -13,6 +13,7 @@
 #include "chrome/common/net/url_fetcher.h"
 #include "googleurl/src/gurl.h"
 
+class FilePath;
 class PrefService;
 
 namespace chromeos {
@@ -51,6 +52,12 @@
   // Applies given |manifest|.
   void Apply(const std::string& manifest);
 
+  // Applies given |manifest| and delete this object.
+  void ApplyAndDelete(const std::string& manifest);
+
+  // Executes on FILE thread and reads file to string.
+  void ReadFileInBackground(const FilePath& file);
+
   // Remember in local state status of kServicesCustomizationAppliedPref.
   static void SetApplied(bool val);
 
diff --git a/chrome/browser/chromeos/login/authenticator.cc b/chrome/browser/chromeos/login/authenticator.cc
index 1b2a42c..458b697 100644
--- a/chrome/browser/chromeos/login/authenticator.cc
+++ b/chrome/browser/chromeos/login/authenticator.cc
@@ -31,11 +31,6 @@
   DCHECK_EQ(parts.size(), 2U) << "email_address should have only one @";
   if (parts[1] == kSpecialCaseDomain)  // only strip '.' for gmail accounts.
     RemoveChars(parts[0], ".", &parts[0]);
-  // Technically the '+' handling here could be removed, as the google
-  // account servers do not tolerate them, so we don't need to either.
-  // TODO(cmasone): remove this, unless this code becomes obsolete altogether.
-  if (parts[0].find('+') != std::string::npos)
-    parts[0].erase(parts[0].find('+'));
   std::string new_email = StringToLowerASCII(JoinString(parts, at));
   VLOG(1) << "Canonicalized " << email_address << " to " << new_email;
   return new_email;
diff --git a/chrome/browser/chromeos/login/authenticator_unittest.cc b/chrome/browser/chromeos/login/authenticator_unittest.cc
index d6bd149..6359dc5 100644
--- a/chrome/browser/chromeos/login/authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/authenticator_unittest.cc
@@ -54,13 +54,13 @@
 }
 
 TEST(AuthenticatorTest, EmailAddressIgnorePlusSuffix) {
-  EXPECT_EQ(Authenticator::Canonicalize("user+cc@what.com"),
-            Authenticator::Canonicalize("user@what.com"));
+  const char with_plus[] = "user+cc@what.com";
+  EXPECT_EQ(with_plus, Authenticator::Canonicalize(with_plus));
 }
 
 TEST(AuthenticatorTest, EmailAddressIgnoreMultiPlusSuffix) {
-  EXPECT_EQ(Authenticator::Canonicalize("user+cc+bcc@what.com"),
-            Authenticator::Canonicalize("user@what.com"));
+  const char multi_plus[] = "user+cc+bcc@what.com";
+  EXPECT_EQ(multi_plus, Authenticator::Canonicalize(multi_plus));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/background_view.cc b/chrome/browser/chromeos/login/background_view.cc
index 9ce54f6..dae3336 100644
--- a/chrome/browser/chromeos/login/background_view.cc
+++ b/chrome/browser/chromeos/login/background_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,14 +7,12 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/x11_util.h"
 #include "base/string16.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/oobe_progress_bar.h"
 #include "chrome/browser/chromeos/login/proxy_settings_dialog.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
@@ -26,17 +24,22 @@
 #include "chrome/browser/chromeos/status/status_area_view.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/views/dom_view.h"
-#include "gfx/gtk_util.h"
+#include "chrome/browser/ui/views/dom_view.h"
+#include "chrome/browser/ui/views/window.h"
 #include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_util.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/label.h"
 #include "views/screen.h"
 #include "views/widget/widget_gtk.h"
+#include "views/window/window.h"
 
 // X Windows headers have "#define Status int". That interferes with
 // NetworkLibrary header which defines enum "Status".
@@ -80,7 +83,7 @@
   virtual ~TextButtonWithHandCursorOver() {}
 
   virtual gfx::NativeCursor GetCursorForPoint(
-      views::Event::EventType event_type,
+      ui::EventType event_type,
       const gfx::Point& p) {
     if (!IsEnabled()) {
       return NULL;
@@ -95,9 +98,9 @@
 // This gets rid of the ugly X default cursor.
 static void ResetXCursor() {
   // TODO(sky): nuke this once new window manager is in place.
-  Display* display = x11_util::GetXDisplay();
+  Display* display = ui::GetXDisplay();
   Cursor cursor = XCreateFontCursor(display, XC_left_ptr);
-  XID root_window = x11_util::GetX11RootWindow();
+  XID root_window = ui::GetX11RootWindow();
   XSetWindowAttributes attr;
   attr.cursor = cursor;
   XChangeWindowAttributes(display, root_window, CWCursor, &attr);
@@ -179,15 +182,29 @@
   GdkWindow* gdk_window = window->GetNativeView()->window;
   gdk_window_set_back_pixmap(gdk_window, NULL, false);
 
+  LoginUtils::Get()->SetBackgroundView(*view);
+
   return window;
 }
 
+void BackgroundView::CreateModalPopup(views::WindowDelegate* view) {
+  views::Window* window = browser::CreateViewsWindow(
+      GetNativeWindow(), gfx::Rect(), view);
+  window->SetIsAlwaysOnTop(true);
+  window->Show();
+}
+
+gfx::NativeWindow BackgroundView::GetNativeWindow() const {
+  return
+      GTK_WINDOW(static_cast<const WidgetGtk*>(GetWidget())->GetNativeView());
+}
+
 void BackgroundView::SetStatusAreaVisible(bool visible) {
   status_area_->SetVisible(visible);
 }
 
 void BackgroundView::SetStatusAreaEnabled(bool enable) {
-  status_area_->EnableButtons(enable);
+  status_area_->MakeButtonsActive(enable);
 }
 
 void BackgroundView::SetOobeProgressBarVisible(bool visible) {
@@ -241,9 +258,9 @@
 
 void BackgroundView::Layout() {
   const int kCornerPadding = 5;
-  const int kInfoLeftPadding = 15;
-  const int kInfoBottomPadding = 15;
-  const int kInfoBetweenLinesPadding = 4;
+  const int kInfoLeftPadding = 10;
+  const int kInfoBottomPadding = 10;
+  const int kInfoBetweenLinesPadding = 1;
   const int kProgressBarBottomPadding = 20;
   const int kProgressBarWidth = 750;
   const int kProgressBarHeight = 70;
@@ -256,7 +273,7 @@
   gfx::Size version_size = os_version_label_->GetPreferredSize();
   int os_version_y = height() - version_size.height() - kInfoBottomPadding;
   if (!is_official_build_)
-    os_version_y -= version_size.height() - kInfoBetweenLinesPadding;
+    os_version_y -= (version_size.height() + kInfoBetweenLinesPadding);
   os_version_label_->SetBounds(
       kInfoLeftPadding,
       os_version_y,
@@ -280,7 +297,7 @@
     shutdown_button_->LayoutIn(this);
   }
   if (background_area_)
-    background_area_->SetBounds(this->bounds());
+    background_area_->SetBoundsRect(this->bounds());
 }
 
 void BackgroundView::ChildPreferredSizeChanged(View* child) {
@@ -288,11 +305,6 @@
   SchedulePaint();
 }
 
-gfx::NativeWindow BackgroundView::GetNativeWindow() const {
-  return
-      GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
-}
-
 bool BackgroundView::ShouldOpenButtonOptions(
     const views::View* button_view) const {
   if (button_view == status_area_->network_view()) {
@@ -315,12 +327,8 @@
   }
 }
 
-bool BackgroundView::IsBrowserMode() const {
-  return false;
-}
-
-bool BackgroundView::IsScreenLockerMode() const {
-  return false;
+StatusAreaHost::ScreenMode BackgroundView::GetScreenMode() const {
+  return kLoginMode;
 }
 
 // Overridden from LoginHtmlDialog::Delegate:
diff --git a/chrome/browser/chromeos/login/background_view.h b/chrome/browser/chromeos/login/background_view.h
index 2e06924..795dd3a 100644
--- a/chrome/browser/chromeos/login/background_view.h
+++ b/chrome/browser/chromeos/login/background_view.h
@@ -17,6 +17,7 @@
 class Label;
 class TextButton;
 class Widget;
+class WindowDelegate;
 }
 
 class DOMView;
@@ -64,6 +65,12 @@
       const GURL& background_url,
       BackgroundView** view);
 
+  // Create a modal popup view.
+  void CreateModalPopup(views::WindowDelegate* view);
+
+  // Overridden from StatusAreaHost:
+  virtual gfx::NativeWindow GetNativeWindow() const;
+
   // Toggles status area visibility.
   void SetStatusAreaVisible(bool visible);
 
@@ -100,13 +107,11 @@
 
   // Overridden from StatusAreaHost:
   virtual Profile* GetProfile() const { return NULL; }
-  virtual gfx::NativeWindow GetNativeWindow() const;
   virtual void ExecuteBrowserCommand(int id) const {}
   virtual bool ShouldOpenButtonOptions(
       const views::View* button_view) const;
   virtual void OpenButtonOptions(const views::View* button_view);
-  virtual bool IsBrowserMode() const;
-  virtual bool IsScreenLockerMode() const;
+  virtual ScreenMode GetScreenMode() const;
 
   // Overridden from LoginHtmlDialog::Delegate:
   virtual void OnDialogClosed() {}
diff --git a/chrome/browser/chromeos/login/camera.cc b/chrome/browser/chromeos/login/camera.cc
index bfc8136..7580bfc 100644
--- a/chrome/browser/chromeos/login/camera.cc
+++ b/chrome/browser/chromeos/login/camera.cc
@@ -25,10 +25,10 @@
 #include "base/threading/thread.h"
 #include "base/time.h"
 #include "chrome/browser/browser_thread.h"
-#include "gfx/size.h"
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColorPriv.h"
+#include "ui/gfx/size.h"
 
 namespace chromeos {
 
@@ -324,7 +324,7 @@
 }
 
 void Camera::GetFrame(SkBitmap* frame) {
-  AutoLock lock(image_lock_);
+  base::AutoLock lock(image_lock_);
   frame->swap(frame_image_);
 }
 
@@ -527,7 +527,7 @@
   }
   image.setIsOpaque(true);
   {
-    AutoLock lock(image_lock_);
+    base::AutoLock lock(image_lock_);
     frame_image_.swap(image);
   }
   BrowserThread::PostTask(
@@ -573,13 +573,13 @@
 }
 
 bool Camera::IsOnCameraThread() const {
-  AutoLock lock(thread_lock_);
+  base::AutoLock lock(thread_lock_);
   return thread_ && MessageLoop::current() == thread_->message_loop();
 }
 
 void Camera::PostCameraTask(const tracked_objects::Location& from_here,
                             Task* task) {
-  AutoLock lock(thread_lock_);
+  base::AutoLock lock(thread_lock_);
   if (!thread_)
     return;
   DCHECK(thread_->IsRunning());
diff --git a/chrome/browser/chromeos/login/camera.h b/chrome/browser/chromeos/login/camera.h
index c30f2df..9b51088 100644
--- a/chrome/browser/chromeos/login/camera.h
+++ b/chrome/browser/chromeos/login/camera.h
@@ -9,8 +9,8 @@
 #include <string>
 #include <vector>
 
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -181,10 +181,10 @@
   SkBitmap frame_image_;
 
   // Lock that guards references to |frame_image_|.
-  mutable Lock image_lock_;
+  mutable base::Lock image_lock_;
 
   // Lock that guards references to |camera_thread_|.
-  mutable Lock thread_lock_;
+  mutable base::Lock thread_lock_;
 
   DISALLOW_COPY_AND_ASSIGN(Camera);
 };
diff --git a/chrome/browser/chromeos/login/captcha_view.cc b/chrome/browser/chromeos/login/captcha_view.cc
index ca2438f..142c97b 100644
--- a/chrome/browser/chromeos/login/captcha_view.cc
+++ b/chrome/browser/chromeos/login/captcha_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/captcha_view.h"
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/helper.h"
@@ -15,12 +14,13 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/background.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget_gtk.h"
 #include "views/window/window.h"
 
@@ -123,7 +123,7 @@
 bool CaptchaView::HandleKeyEvent(views::Textfield* sender,
                                  const views::KeyEvent& key_event) {
   if (sender == captcha_textfield_ &&
-      key_event.GetKeyCode() == app::VKEY_RETURN) {
+      key_event.key_code() == ui::VKEY_RETURN) {
     if (is_standalone_) {
       Accept();
     } else {
@@ -154,7 +154,7 @@
     set_background(views::Background::CreateBackgroundPainter(true, painter));
   }
 
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   int column_view_set_id = 0;
@@ -166,12 +166,12 @@
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_LOGIN_CAPTCHA_INSTRUCTIONS)));
   label->SetMultiLine(true);
   layout->AddView(label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, column_view_set_id);
   captcha_image_ = new views::ImageView();
   layout->AddView(captcha_image_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, column_view_set_id);
   captcha_textfield_ = new CaptchaField();
@@ -179,14 +179,14 @@
   if (is_standalone_)
     captcha_textfield_->set_background(new CopyBackground(this));
   layout->AddView(captcha_textfield_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, column_view_set_id);
   label = new views::Label(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_SYNC_GAIA_CAPTCHA_CASE_INSENSITIVE_TIP)));
   label->SetMultiLine(true);
   layout->AddView(label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   if (is_standalone_) {
     layout->StartRow(0, column_view_set_id);
diff --git a/chrome/browser/chromeos/login/cookie_fetcher.cc b/chrome/browser/chromeos/login/cookie_fetcher.cc
index 10dde76..22fb2da 100644
--- a/chrome/browser/chromeos/login/cookie_fetcher.cc
+++ b/chrome/browser/chromeos/login/cookie_fetcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -34,7 +34,7 @@
 
 void CookieFetcher::OnURLFetchComplete(const URLFetcher* source,
                                        const GURL& url,
-                                       const URLRequestStatus& status,
+                                       const net::URLRequestStatus& status,
                                        int response_code,
                                        const ResponseCookies& cookies,
                                        const std::string& data) {
diff --git a/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc b/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc
index e188b8f..f6ef428 100644
--- a/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc
+++ b/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -46,7 +46,7 @@
 // Check that successful HTTP responses from both end points results in
 // the browser window getting put up.
 TEST_F(CookieFetcherTest, SuccessfulFetchTest) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
 
   MockAuthResponseHandler* cl_handler =
       new MockAuthResponseHandler(iat_url_, status, kHttpSuccess, token_);
@@ -72,7 +72,7 @@
 // Check that a network failure when trying IssueAuthToken results in us bailing
 // and putting up the browser window.
 TEST_F(CookieFetcherTest, IssueAuthTokenNetworkFailureTest) {
-  URLRequestStatus failed(URLRequestStatus::FAILED, ECONNRESET);
+  net::URLRequestStatus failed(net::URLRequestStatus::FAILED, ECONNRESET);
 
   MockAuthResponseHandler* cl_handler =
       new MockAuthResponseHandler(iat_url_, failed, kHttpSuccess, token_);
@@ -94,8 +94,8 @@
 // Check that a network failure when trying TokenAuth results in us bailing
 // and putting up the browser window.
 TEST_F(CookieFetcherTest, TokenAuthNetworkFailureTest) {
-  URLRequestStatus success;
-  URLRequestStatus failed(URLRequestStatus::FAILED, ECONNRESET);
+  net::URLRequestStatus success;
+  net::URLRequestStatus failed(net::URLRequestStatus::FAILED, ECONNRESET);
 
   MockAuthResponseHandler* cl_handler =
       new MockAuthResponseHandler(iat_url_, success, kHttpSuccess, token_);
@@ -121,7 +121,7 @@
 // Check that an unsuccessful HTTP response when trying IssueAuthToken results
 // in us bailing and putting up the browser window.
 TEST_F(CookieFetcherTest, IssueAuthTokenDeniedTest) {
-  URLRequestStatus success;
+  net::URLRequestStatus success;
 
   MockAuthResponseHandler* cl_handler =
       new MockAuthResponseHandler(iat_url_, success, 403, std::string());
@@ -143,7 +143,7 @@
 // Check that an unsuccessful HTTP response when trying TokenAuth results
 // in us bailing and putting up the browser window.
 TEST_F(CookieFetcherTest, TokenAuthDeniedTest) {
-  URLRequestStatus success;
+  net::URLRequestStatus success;
 
   MockAuthResponseHandler* cl_handler =
       new MockAuthResponseHandler(iat_url_,
diff --git a/chrome/browser/chromeos/login/eula_view.cc b/chrome/browser/chromeos/login/eula_view.cc
index c23a89a..873870c 100644
--- a/chrome/browser/chromeos/login/eula_view.cc
+++ b/chrome/browser/chromeos/login/eula_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,6 @@
 #include <sys/types.h>
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/basictypes.h"
 #include "base/message_loop.h"
 #include "base/task.h"
@@ -19,8 +17,10 @@
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
 #include "chrome/browser/chromeos/customization_document.h"
+#include "chrome/browser/chromeos/login/background_view.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/network_screen_delegate.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
@@ -28,20 +28,22 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/renderer_host/site_instance.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/dom_view.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/dom_view.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/native_web_keyboard_event.h"
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
-#include "views/layout_manager.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
+#include "views/layout/layout_manager.h"
 #include "views/widget/widget_gtk.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
@@ -73,8 +75,8 @@
 struct FillLayoutWithBorder : public views::LayoutManager {
   // Overridden from LayoutManager:
   virtual void Layout(views::View* host) {
-    DCHECK(host->GetChildViewCount());
-    host->GetChildViewAt(0)->SetBounds(host->GetLocalBounds(false));
+    DCHECK(host->has_children());
+    host->GetChildViewAt(0)->SetBoundsRect(host->GetContentsBounds());
   }
   virtual gfx::Size GetPreferredSize(views::View* host) {
     return gfx::Size(host->width(), host->height());
@@ -130,7 +132,7 @@
 };
 
 void TpmInfoView::Init() {
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
   views::ColumnSet* column_set = layout->AddColumnSet(0);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
@@ -141,7 +143,7 @@
   label->SetMultiLine(true);
   label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   layout->AddView(label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, 0);
   label = new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
@@ -149,7 +151,7 @@
   label->SetMultiLine(true);
   label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   layout->AddView(label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   column_set = layout->AddColumnSet(1);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
@@ -162,7 +164,7 @@
   password_label_ = new views::Label(L"", password_font);
   password_label_->SetVisible(false);
   layout->AddView(password_label_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   column_set = layout->AddColumnSet(2);
   column_set->AddPaddingColumn(1, 0);
@@ -170,7 +172,7 @@
   // placed in the center.
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
                         views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
                         views::GridLayout::USE_PREF, 0, 0);
   column_set->AddPaddingColumn(1, 0);
@@ -185,7 +187,7 @@
   busy_label_ = new views::Label(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_EULA_TPM_BUSY)));
   layout->AddView(busy_label_);
-  layout->AddPaddingRow(0, kRelatedControlHorizontalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlHorizontalSpacing);
 
   PullPassword();
 }
@@ -278,7 +280,7 @@
                         views::GridLayout::USE_PREF, 0, 0);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
                         views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
                         views::GridLayout::USE_PREF, 0, 0);
   column_set->AddPaddingColumn(0, kLastButtonHorizontalMargin + kBorderSize);
@@ -341,7 +343,7 @@
   layout->AddView(google_eula_label_, 1, 1,
                   views::GridLayout::LEADING, views::GridLayout::FILL);
 
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(1, SINGLE_CONTROL_ROW);
   views::View* box_view = new views::View();
   box_view->set_border(views::Border::CreateSolidBorder(1, SK_ColorBLACK));
@@ -351,7 +353,7 @@
   google_eula_view_ = new DOMView();
   box_view->AddChildView(google_eula_view_);
 
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, SINGLE_CONTROL_WITH_SHIFT_ROW);
   usage_statistics_checkbox_ = new views::Checkbox();
   usage_statistics_checkbox_->SetMultiLine(true);
@@ -363,7 +365,7 @@
   learn_more_link_->SetController(this);
   layout->AddView(learn_more_link_);
 
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, SINGLE_CONTROL_ROW);
   oem_eula_label_ = new views::Label(std::wstring(), label_font);
   layout->AddView(oem_eula_label_, 1, 1,
@@ -371,7 +373,7 @@
 
   oem_eula_page_ = GetOemEulaPagePath();
   if (!oem_eula_page_.is_empty()) {
-    layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
     layout->StartRow(1, SINGLE_CONTROL_ROW);
     box_view = new views::View();
     box_view->SetLayoutManager(new FillLayoutWithBorder());
@@ -382,7 +384,7 @@
     box_view->AddChildView(oem_eula_view_);
   }
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, LAST_ROW);
   system_security_settings_link_ = new views::Link();
   system_security_settings_link_->SetController(this);
@@ -465,15 +467,18 @@
 // views::LinkController implementation:
 
 void EulaView::LinkActivated(views::Link* source, int event_flags) {
+  gfx::NativeWindow parent_window =
+      LoginUtils::Get()->GetBackgroundView()->GetNativeWindow();
   if (source == learn_more_link_) {
     if (!help_app_.get())
-      help_app_.reset(new HelpAppLauncher(GetNativeWindow()));
+      help_app_ = new HelpAppLauncher(parent_window);
     help_app_->ShowHelpTopic(HelpAppLauncher::HELP_STATS_USAGE);
   } else if (source == system_security_settings_link_) {
     TpmInfoView* view = new TpmInfoView(&tpm_password_);
     view->Init();
-    views::Window* window = browser::CreateViewsWindow(
-        GetNativeWindow(), gfx::Rect(), view);
+    views::Window* window = browser::CreateViewsWindow(parent_window,
+                                                       gfx::Rect(),
+                                                       view);
     window->SetIsAlwaysOnTop(true);
     window->Show();
   }
@@ -513,10 +518,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // EulaView, private:
 
-gfx::NativeWindow EulaView::GetNativeWindow() const {
-  return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
-}
-
 void EulaView::LoadEulaView(DOMView* eula_view,
                             views::Label* eula_label,
                             const GURL& eula_url) {
diff --git a/chrome/browser/chromeos/login/eula_view.h b/chrome/browser/chromeos/login/eula_view.h
index 642186a..7e9e782 100644
--- a/chrome/browser/chromeos/login/eula_view.h
+++ b/chrome/browser/chromeos/login/eula_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_EULA_VIEW_H_
 #pragma once
 
-#include "base/scoped_ptr.h"
+#include "base/ref_counted.h"
 #include "chrome/browser/chromeos/login/message_bubble.h"
 #include "chrome/browser/chromeos/login/view_screen.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/controls/button/button.h"
 #include "views/controls/link.h"
 #include "views/view.h"
@@ -56,7 +56,6 @@
   virtual void LoadingStateChanged(TabContents* source) {}
   virtual void CloseContents(TabContents* source) {}
   virtual bool IsPopup(TabContents* source) { return false; }
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
   virtual bool ShouldAddNavigationToHistory(
       const history::HistoryAddPageArgs& add_page_args,
@@ -110,9 +109,6 @@
                                       unsigned changed_flags);
   virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
 
-  // Returns corresponding native window.
-  gfx::NativeWindow GetNativeWindow() const;
-
   // Loads specified URL to the specified DOMView and updates specified
   // label with its title.
   void LoadEulaView(DOMView* eula_view,
@@ -143,7 +139,7 @@
   GURL oem_eula_page_;
 
   // Help application used for help dialogs.
-  scoped_ptr<HelpAppLauncher> help_app_;
+  scoped_refptr<HelpAppLauncher> help_app_;
 
   // Pointer to shown message bubble. We don't need to delete it because
   // it will be deleted on bubble closing.
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 1b906e0..5d51ce6 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -1,74 +1,57 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 
-#include <algorithm>
-#include <functional>
-#include <map>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
-#include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/boot_times_loader.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
 #include "chrome/browser/chromeos/cros/login_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/login/background_view.h"
-#include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
-#include "chrome/browser/chromeos/login/message_bubble.h"
+#include "chrome/browser/chromeos/login/views_login_display.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/status/status_area_view.h"
 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
-#include "chrome/browser/chromeos/view_ids.h"
-#include "chrome/browser/chromeos/wm_ipc.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
-#include "gfx/native_widget_types.h"
-#include "grit/chromium_strings.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "views/screen.h"
-#include "views/widget/widget_gtk.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/window/window.h"
 
 namespace chromeos {
 
 namespace {
 
-// Max number of users we'll show. The true max is the min of this and the
-// number of windows that fit on the screen.
-const size_t kMaxUsers = 6;
-
-// Minimum number of users we'll show (including Guest and New User pods).
-const size_t kMinUsers = 3;
-
-// Used to indicate no user has been selected.
-const size_t kNotSelected = -1;
-
-// Offset of cursor in first position from edit left side. It's used to position
-// info bubble arrow to cursor.
-const int kCursorOffset = 5;
-
 // Url for setting up sync authentication.
-const char kSettingsSyncLoginUrl[] = "chrome://settings/personal";
+const char kSettingsSyncLoginURL[] = "chrome://settings/personal";
 
 // URL that will be opened on when user logs in first time on the device.
 const char kGetStartedURL[] =
-    "chrome-extension://nbaambmfhicobichobkkokacjbaoinda/index.html";
+    "chrome-extension://cbmhffdpiobpchciemffincgahkkljig/index.html";
 
-// Path to extracted version of Get Started app.
-const char kGetStartedPath[] = "/usr/share/chromeos-assets/getstarted";
+// URL for account creation.
+const char kCreateAccountURL[] =
+    "https://www.google.com/accounts/NewAccount?service=mail";
+
+// Landing URL when launching Guest mode to fix captive portal.
+const char kCaptivePortalLaunchURL[] = "http://www.google.com/";
 
 // Used to handle the asynchronous response of deleting a cryptohome directory.
 class RemoveAttempt : public CryptohomeLibrary::Delegate {
@@ -94,90 +77,53 @@
   std::string user_email_;
 };
 
-// Checks if display names are unique. If there are duplicates, enables
-// tooltips with full emails to let users distinguish their accounts.
-// Otherwise, disables the tooltips.
-void EnableTooltipsIfNeeded(const std::vector<UserController*>& controllers) {
-  std::map<std::string, int> visible_display_names;
-  for (size_t i = 0; i + 1 < controllers.size(); ++i) {
-    const std::string& display_name =
-        controllers[i]->user().GetDisplayName();
-    ++visible_display_names[display_name];
-  }
-  for (size_t i = 0; i < controllers.size(); ++i) {
-    const std::string& display_name =
-        controllers[i]->user().GetDisplayName();
-    bool show_tooltip = controllers[i]->is_new_user() ||
-                        controllers[i]->is_guest() ||
-                        visible_display_names[display_name] > 1;
-    controllers[i]->EnableNameTooltip(show_tooltip);
-  }
-}
-
 }  // namespace
 
+// static
 ExistingUserController*
-  ExistingUserController::delete_scheduled_instance_ = NULL;
+  ExistingUserController::current_controller_ = NULL;
 
-// TODO(xiyuan): Wait for the cached settings update before using them.
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, public:
+
 ExistingUserController::ExistingUserController(
-    const std::vector<UserManager::User>& users,
     const gfx::Rect& background_bounds)
     : background_bounds_(background_bounds),
       background_window_(NULL),
       background_view_(NULL),
-      selected_view_index_(kNotSelected),
       num_login_attempts_(0),
-      bubble_(NULL),
       user_settings_(new UserCrosSettingsProvider),
       method_factory_(this) {
-  if (delete_scheduled_instance_)
-    delete_scheduled_instance_->Delete();
+  if (current_controller_)
+    current_controller_->Delete();
+  current_controller_ = this;
 
-  // Calculate the max number of users from available screen size.
-  bool show_guest = UserCrosSettingsProvider::cached_allow_guest();
-  bool show_new_user = true;
-  if (UserCrosSettingsProvider::cached_show_users_on_signin()) {
-    size_t max_users = kMaxUsers;
-    int screen_width = background_bounds.width();
-    if (screen_width > 0) {
-      size_t users_per_screen = (screen_width - login::kUserImageSize)
-          / (UserController::kUnselectedSize + UserController::kPadding);
-      max_users = std::max(kMinUsers, std::min(kMaxUsers, users_per_screen));
-    }
+  login_display_.reset(CreateLoginDisplay(this, background_bounds));
 
-    size_t visible_users_count = std::min(users.size(), max_users -
-        static_cast<int>(show_guest) - static_cast<int>(show_new_user));
-    for (size_t i = 0; i < users.size(); ++i) {
-      // TODO(xiyuan): Clean user profile whose email is not in whitelist.
-      if (UserCrosSettingsProvider::cached_allow_new_user() ||
-          UserCrosSettingsProvider::IsEmailInCachedWhitelist(
-              users[i].email())) {
-        UserController* user_controller = new UserController(this, users[i]);
-        if (controllers_.size() < visible_users_count)
-          controllers_.push_back(user_controller);
-        else
-          invisible_controllers_.push_back(user_controller);
+  registrar_.Add(this,
+                 NotificationType::LOGIN_USER_IMAGE_CHANGED,
+                 NotificationService::AllSources());
+}
+
+void ExistingUserController::Init(const UserVector& users) {
+  if (g_browser_process) {
+    PrefService* state = g_browser_process->local_state();
+    if (state) {
+      std::string owner_locale = state->GetString(prefs::kOwnerLocale);
+      // Ensure that we start with owner's locale.
+      if (!owner_locale.empty() &&
+          state->GetString(prefs::kApplicationLocale) != owner_locale &&
+          !state->IsManagedPreference(prefs::kApplicationLocale)) {
+        state->SetString(prefs::kApplicationLocale, owner_locale);
+        state->ScheduleSavePersistentPrefs();
+        LanguageSwitchMenu::SwitchLanguage(owner_locale);
       }
     }
   }
-
-  if (!controllers_.empty() && show_guest)
-    controllers_.push_back(new UserController(this, true));
-
-  if (show_new_user)
-    controllers_.push_back(new UserController(this, false));
-}
-
-void ExistingUserController::Init() {
   if (!background_window_) {
-    std::string url_string =
-        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-            switches::kScreenSaverUrl);
-
     background_window_ = BackgroundView::CreateWindowContainingView(
         background_bounds_,
-        GURL(url_string),
+        GURL(),
         &background_view_);
     background_view_->EnableShutdownButton(true);
 
@@ -188,17 +134,25 @@
 
     background_window_->Show();
   }
-  // If there's only new user pod, show the guest session link on it.
-  bool show_guest_link = controllers_.size() == 1;
-  for (size_t i = 0; i < controllers_.size(); ++i) {
-    (controllers_[i])->Init(static_cast<int>(i),
-                            static_cast<int>(controllers_.size()),
-                            show_guest_link);
+
+  UserVector filtered_users;
+  if (UserCrosSettingsProvider::cached_show_users_on_signin()) {
+    for (size_t i = 0; i < users.size(); ++i)
+      // TODO(xiyuan): Clean user profile whose email is not in whitelist.
+      if (UserCrosSettingsProvider::cached_allow_new_user() ||
+          UserCrosSettingsProvider::IsEmailInCachedWhitelist(
+              users[i].email())) {
+        filtered_users.push_back(users[i]);
+      }
   }
 
-  EnableTooltipsIfNeeded(controllers_);
-
-  WmMessageListener::GetInstance()->AddObserver(this);
+  // If no user pods are visible, fallback to single new user pod which will
+  // have guest session link.
+  bool show_guest = UserCrosSettingsProvider::cached_allow_guest() &&
+                    !filtered_users.empty();
+  bool show_new_user = true;
+  login_display_->set_parent_window(GetNativeWindow());
+  login_display_->Init(filtered_users, show_guest, show_new_user);
 
   LoginUtils::Get()->PrewarmAuthentication();
   if (CrosLibrary::Get()->EnsureLoaded())
@@ -213,104 +167,88 @@
   background_view_ = background_view;
 }
 
-void ExistingUserController::LoginNewUser(const std::string& username,
-                                          const std::string& password) {
-  SelectNewUser();
-  UserController* new_user = controllers_.back();
-  DCHECK(new_user->is_new_user());
-  if (!new_user->is_new_user())
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, NotificationObserver implementation:
+//
+
+void ExistingUserController::Observe(NotificationType type,
+                                     const NotificationSource& source,
+                                     const NotificationDetails& details) {
+  if (type != NotificationType::LOGIN_USER_IMAGE_CHANGED)
     return;
 
-  if (password.empty())
-    return;
-
-  new_user->OnLogin(username, password);
+  UserManager::User* user = Details<UserManager::User>(details).ptr();
+  login_display_->OnUserImageChanged(user);
 }
 
-void ExistingUserController::SelectNewUser() {
-  SelectUser(controllers_.size() - 1);
-}
-
-void ExistingUserController::SetStatusAreaEnabled(bool enable) {
-  if (background_view_) {
-    background_view_->SetStatusAreaEnabled(enable);
-  }
-}
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, private:
 
 ExistingUserController::~ExistingUserController() {
-  ClearErrors();
-
   if (background_window_)
     background_window_->Close();
 
-  WmMessageListener::GetInstance()->RemoveObserver(this);
-
-  STLDeleteElements(&controllers_);
-  STLDeleteElements(&invisible_controllers_);
+  DCHECK(current_controller_ != NULL);
+  current_controller_ = NULL;
 }
 
-void ExistingUserController::Delete() {
-  delete_scheduled_instance_ = NULL;
-  delete this;
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, LoginDisplay::Delegate implementation:
+//
+
+void ExistingUserController::CreateAccount() {
+  guest_mode_url_ =
+      google_util::AppendGoogleLocaleParam(GURL(kCreateAccountURL));
+  LoginAsGuest();
 }
 
-void ExistingUserController::ProcessWmMessage(const WmIpc::Message& message,
-                                              GdkWindow* window) {
-  if (message.type() != WM_IPC_MESSAGE_CHROME_CREATE_GUEST_WINDOW)
+void ExistingUserController::FixCaptivePortal() {
+  guest_mode_url_ = GURL(kCaptivePortalLaunchURL);
+  LoginAsGuest();
+}
+
+void ExistingUserController::Login(const std::string& username,
+                                   const std::string& password) {
+  if (username.empty() || password.empty())
     return;
+  SetStatusAreaEnabled(false);
+  // Disable clicking on other windows.
+  login_display_->SetUIEnabled(false);
 
-  ActivateWizard(std::string());
-}
-
-void ExistingUserController::SendSetLoginState(bool is_enabled) {
-  WmIpc::Message message(WM_IPC_MESSAGE_WM_SET_LOGIN_STATE);
-  message.set_param(0, is_enabled);
-  WmIpc::instance()->SendMessage(message);
-}
-
-void ExistingUserController::Login(UserController* source,
-                                   const string16& password) {
   BootTimesLoader::Get()->RecordLoginAttempted();
-  std::vector<UserController*>::const_iterator i =
-      std::find(controllers_.begin(), controllers_.end(), source);
-  DCHECK(i != controllers_.end());
 
-  if (i == controllers_.begin() + selected_view_index_) {
-    num_login_attempts_++;
-  } else {
-    selected_view_index_ = i - controllers_.begin();
+  if (last_login_attempt_username_ != username) {
+    last_login_attempt_username_ = username;
     num_login_attempts_ = 0;
   }
-
-  // Disable clicking on other windows.
-  SendSetLoginState(false);
+  num_login_attempts_++;
 
   // Use the same LoginPerformer for subsequent login as it has state
   // such as CAPTCHA challenge token & corresponding user input.
   if (!login_performer_.get() || num_login_attempts_ <= 1) {
-    login_performer_.reset(new LoginPerformer(this));
+    LoginPerformer::Delegate* delegate = this;
+    if (login_performer_delegate_.get())
+      delegate = login_performer_delegate_.get();
+    // Only one instance of LoginPerformer should exist at a time.
+    login_performer_.reset(NULL);
+    login_performer_.reset(new LoginPerformer(delegate));
   }
-  login_performer_->Login(controllers_[selected_view_index_]->user().email(),
-                          UTF16ToUTF8(password));
+  login_performer_->Login(username, password);
+  WizardAccessibilityHelper::GetInstance()->MaybeSpeak(
+      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN).c_str(),
+      false, true);
 }
 
-void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
-  ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
+void ExistingUserController::LoginAsGuest() {
+  SetStatusAreaEnabled(false);
+  // Disable clicking on other windows.
+  login_display_->SetUIEnabled(false);
 
-  // Reenable userview and use ClearAndEnablePassword to keep username on
-  // screen with the error bubble.
-  controllers_[selected_view_index_]->ClearAndEnablePassword();
-
-  // Reenable clicking on other windows.
-  SendSetLoginState(true);
-}
-
-void ExistingUserController::LoginOffTheRecord() {
   // Check allow_guest in case this call is fired from key accelerator.
   // Must not proceed without signature verification.
   bool trusted_setting_available = user_settings_->RequestTrustedAllowGuest(
       method_factory_.NewRunnableMethod(
-          &ExistingUserController::LoginOffTheRecord));
+          &ExistingUserController::LoginAsGuest));
   if (!trusted_setting_available) {
     // Value of AllowGuest setting is still not verified.
     // Another attempt will be invoked again after verification completion.
@@ -321,118 +259,54 @@
     return;
   }
 
-  // Disable clicking on other windows.
-  SendSetLoginState(false);
-
+  // Only one instance of LoginPerformer should exist at a time.
+  login_performer_.reset(NULL);
   login_performer_.reset(new LoginPerformer(this));
   login_performer_->LoginOffTheRecord();
+  WizardAccessibilityHelper::GetInstance()->MaybeSpeak(
+      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD).c_str(),
+      false, true);
 }
 
-void ExistingUserController::ClearErrors() {
-  // bubble_ will be set to NULL in callback.
-  if (bubble_)
-    bubble_->Close();
+void ExistingUserController::OnUserSelected(const std::string& username) {
+  login_performer_.reset(NULL);
+  num_login_attempts_ = 0;
 }
 
-void ExistingUserController::OnUserSelected(UserController* source) {
-  std::vector<UserController*>::const_iterator i =
-      std::find(controllers_.begin(), controllers_.end(), source);
-  DCHECK(i != controllers_.end());
-  size_t new_selected_index = i - controllers_.begin();
-  if (new_selected_index != selected_view_index_ &&
-      selected_view_index_ != kNotSelected) {
-    controllers_[selected_view_index_]->ClearAndEnableFields();
-    controllers_[new_selected_index]->ClearAndEnableFields();
-    login_performer_.reset(NULL);
-    num_login_attempts_ = 0;
-  }
-  selected_view_index_ = new_selected_index;
-}
-
-void ExistingUserController::ActivateWizard(const std::string& screen_name) {
-  // WizardController takes care of deleting itself when done.
-  WizardController* controller = new WizardController();
-
-  // Give the background window to the controller.
-  controller->OwnBackground(background_window_, background_view_);
-  background_window_ = NULL;
-
-  controller->Init(screen_name, background_bounds_);
-  controller->set_start_url(start_url_);
-  controller->Show();
-
-  // And schedule us for deletion. We delay for a second as the window manager
-  // is doing an animation with our windows.
-  DCHECK(!delete_scheduled_instance_);
-  delete_scheduled_instance_ = this;
-
-  delete_timer_.Start(base::TimeDelta::FromSeconds(1), this,
-                      &ExistingUserController::Delete);
-}
-
-void ExistingUserController::RemoveUser(UserController* source) {
-  ClearErrors();
-
+void ExistingUserController::RemoveUser(const std::string& username) {
   // Owner is not allowed to be removed from the device.
-  // It must be enforced at upper levels.
-  DCHECK(user_settings_->RequestTrustedOwner(NULL));
-  DCHECK(source->user().email() != UserCrosSettingsProvider::cached_owner());
+  // Must not proceed without signature verification.
+  UserCrosSettingsProvider user_settings;
+  bool trusted_owner_available = user_settings.RequestTrustedOwner(
+      method_factory_.NewRunnableMethod(&ExistingUserController::RemoveUser,
+                                        username));
+  if (!trusted_owner_available) {
+    // Value of owner email is still not verified.
+    // Another attempt will be invoked after verification completion.
+    return;
+  }
+  if (username == UserCrosSettingsProvider::cached_owner()) {
+    // Owner is not allowed to be removed from the device.
+    return;
+  }
 
-  UserManager::Get()->RemoveUser(source->user().email());
+  login_display_->OnBeforeUserRemoved(username);
 
-  controllers_.erase(controllers_.begin() + source->user_index());
-
-  EnableTooltipsIfNeeded(controllers_);
-
-  // Update user count before unmapping windows, otherwise window manager won't
-  // be in the right state.
-  int new_size = static_cast<int>(controllers_.size());
-  for (int i = 0; i < new_size; ++i)
-    controllers_[i]->UpdateUserCount(i, new_size);
+  // Delete user from user list.
+  UserManager::Get()->RemoveUser(username);
 
   // Delete the encrypted user directory.
-  new RemoveAttempt(source->user().email());
-  // We need to unmap entry windows, the windows will be unmapped in destructor.
-  delete source;
+  new RemoveAttempt(username);
 
-  // Nothing to insert.
-  if (invisible_controllers_.empty())
-    return;
-
-  // Insert just before guest or add new user pods if any.
-  int insert_position = new_size;
-  while (insert_position > 0 &&
-         (controllers_[insert_position - 1]->is_new_user() ||
-          controllers_[insert_position - 1]->is_guest()))
-    --insert_position;
-
-  controllers_.insert(controllers_.begin() + insert_position,
-                      invisible_controllers_[0]);
-  invisible_controllers_.erase(invisible_controllers_.begin());
-
-  // Update counts for exiting pods.
-  new_size = static_cast<int>(controllers_.size());
-  for (int i = 0; i < new_size; ++i) {
-    if (i != insert_position)
-      controllers_[i]->UpdateUserCount(i, new_size);
-  }
-
-  // And initialize new one that was invisible.
-  controllers_[insert_position]->Init(insert_position, new_size, false);
-
-  EnableTooltipsIfNeeded(controllers_);
+  login_display_->OnUserRemoved(username);
 }
 
-void ExistingUserController::SelectUser(int index) {
-  if (index >= 0 && index < static_cast<int>(controllers_.size()) &&
-      index != static_cast<int>(selected_view_index_)) {
-    WmIpc::Message message(WM_IPC_MESSAGE_WM_SELECT_LOGIN_USER);
-    message.set_param(0, index);
-    WmIpc::instance()->SendMessage(message);
-  }
-}
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, LoginPerformer::Delegate implementation:
+//
 
 void ExistingUserController::OnLoginFailure(const LoginFailure& failure) {
+  guest_mode_url_ = GURL::EmptyGURL();
   std::string error = failure.GetErrorString();
 
   // Check networking after trying to login in case user is
@@ -462,71 +336,25 @@
                failure.error().state() ==
                    GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
       ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
+    } else if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
+               failure.error().state() ==
+                   GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
+      // SERVICE_UNAVAILABLE is generated in 2 cases:
+      // 1. ClientLogin returns ServiceUnavailable code.
+      // 2. Internet connectivity may be behind the captive portal.
+      // Suggesting user to try sign in to a portal in Guest mode.
+      ShowError(IDS_LOGIN_ERROR_CAPTIVE_PORTAL, error);
     } else {
-      if (controllers_[selected_view_index_]->is_new_user())
+      if (!UserManager::Get()->IsKnownUser(last_login_attempt_username_))
         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
       else
         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
     }
   }
 
-  controllers_[selected_view_index_]->ClearAndEnablePassword();
-
-  // Reenable clicking on other windows.
-  SendSetLoginState(true);
-}
-
-void ExistingUserController::AppendStartUrlToCmdline() {
-  if (start_url_.is_valid())
-    CommandLine::ForCurrentProcess()->AppendArg(start_url_.spec());
-}
-
-gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
-  return GTK_WINDOW(
-      static_cast<views::WidgetGtk*>(background_window_)->GetNativeView());
-}
-
-void ExistingUserController::ShowError(int error_id,
-                                       const std::string& details) {
-  ClearErrors();
-  string16 error_text;
-  // GetStringF fails on debug build if there's no replacement in the string.
-  if (error_id == IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED) {
-    error_text = l10n_util::GetStringFUTF16(
-        error_id, l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME));
-  } else {
-    error_text = l10n_util::GetStringUTF16(error_id);
-  }
-  // TODO(dpolukhin): show detailed error info. |details| string contains
-  // low level error info that is not localized and even is not user friendly.
-  // For now just ignore it because error_text contains all required information
-  // for end users, developers can see details string in Chrome logs.
-
-  gfx::Rect bounds =
-      controllers_[selected_view_index_]->GetMainInputScreenBounds();
-  BubbleBorder::ArrowLocation arrow;
-  if (controllers_[selected_view_index_]->is_new_user()) {
-    arrow = BubbleBorder::LEFT_TOP;
-  } else {
-    // Point info bubble arrow to cursor position (approximately).
-    bounds.set_width(kCursorOffset * 2);
-    arrow = BubbleBorder::BOTTOM_LEFT;
-  }
-  string16 help_link;
-  if (error_id == IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED) {
-    help_link = l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-  } else if (num_login_attempts_ > static_cast<size_t>(1)) {
-    help_link = l10n_util::GetStringUTF16(IDS_CANT_ACCESS_ACCOUNT_BUTTON);
-  }
-
-  bubble_ = MessageBubble::Show(
-      controllers_[selected_view_index_]->controls_window(),
-      bounds,
-      arrow,
-      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
-      UTF16ToWide(error_text),
-      UTF16ToWide(help_link),
-      this);
+  // Reenable clicking on other windows and status area.
+  login_display_->SetUIEnabled(true);
+  SetStatusAreaEnabled(true);
 }
 
 void ExistingUserController::OnLoginSuccess(
@@ -543,35 +371,33 @@
   LoginPerformer* performer = login_performer_.release();
   performer = NULL;
   bool known_user = UserManager::Get()->IsKnownUser(username);
-  AppendStartUrlToCmdline();
-  controllers_[selected_view_index_]->StopThrobber();
-  if (selected_view_index_ + 1 == controllers_.size() && !known_user) {
+  bool login_only =
+      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kLoginScreen) == WizardController::kLoginScreenName;
+  // TODO(nkostylev): May add login UI implementation callback call.
+  if (!known_user && !login_only) {
 #if defined(OFFICIAL_BUILD)
-    CommandLine::ForCurrentProcess()->AppendSwitchPath(
-        switches::kLoadExtension,
-        FilePath(kGetStartedPath));
     CommandLine::ForCurrentProcess()->AppendArg(kGetStartedURL);
 #endif  // OFFICIAL_BUILD
+
     if (credentials.two_factor) {
       // If we have a two factor error and and this is a new user,
       // load the personal settings page.
       // TODO(stevenjb): direct the user to a lightweight sync login page.
-      CommandLine::ForCurrentProcess()->AppendArg(kSettingsSyncLoginUrl);
+      CommandLine::ForCurrentProcess()->AppendArg(kSettingsSyncLoginURL);
     }
+
     // For new user login don't launch browser until we pass image screen.
     LoginUtils::Get()->EnableBrowserLaunch(false);
     LoginUtils::Get()->CompleteLogin(username,
                                      password,
                                      credentials,
                                      pending_requests);
+
     ActivateWizard(WizardController::IsDeviceRegistered() ?
         WizardController::kUserImageScreenName :
         WizardController::kRegistrationScreenName);
   } else {
-    // Hide the login windows now.
-    WmIpc::Message message(WM_IPC_MESSAGE_WM_HIDE_LOGIN);
-    WmIpc::instance()->SendMessage(message);
-
     LoginUtils::Get()->CompleteLogin(username,
                                      password,
                                      credentials,
@@ -584,7 +410,7 @@
 
 void ExistingUserController::OnOffTheRecordLoginSuccess() {
   if (WizardController::IsDeviceRegistered()) {
-    LoginUtils::Get()->CompleteOffTheRecordLogin(start_url_);
+    LoginUtils::Get()->CompleteOffTheRecordLogin(guest_mode_url_);
   } else {
     // Postpone CompleteOffTheRecordLogin until registration completion.
     ActivateWizard(WizardController::kRegistrationScreenName);
@@ -593,12 +419,6 @@
 
 void ExistingUserController::OnPasswordChangeDetected(
     const GaiaAuthConsumer::ClientLoginResult& credentials) {
-  // When signing in as a "New user" always remove old cryptohome.
-  if (selected_view_index_ == controllers_.size() - 1) {
-    ResyncEncryptedData();
-    return;
-  }
-
   // Must not proceed without signature verification.
   bool trusted_setting_available = user_settings_->RequestTrustedOwner(
       method_factory_.NewRunnableMethod(
@@ -612,7 +432,7 @@
   // TODO(altimofeev): remove this constrain when full sync for the owner will
   // be correctly handled.
   bool full_sync_disabled = (UserCrosSettingsProvider::cached_owner() ==
-      controllers_[selected_view_index_]->user().email());
+      last_login_attempt_username_);
 
   PasswordChangedView* view = new PasswordChangedView(this, full_sync_disabled);
   views::Window* window = browser::CreateViewsWindow(GetNativeWindow(),
@@ -622,35 +442,26 @@
   window->Show();
 }
 
-void ExistingUserController::OnHelpLinkActivated() {
-  DCHECK(login_performer_->error().state() != GoogleServiceAuthError::NONE);
-  if (!help_app_.get())
-    help_app_.reset(new HelpAppLauncher(GetNativeWindow()));
-  switch (login_performer_->error().state()) {
-    case GoogleServiceAuthError::CONNECTION_FAILED:
-      help_app_->ShowHelpTopic(
-          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE);
-      break;
-    case GoogleServiceAuthError::ACCOUNT_DISABLED:
-        help_app_->ShowHelpTopic(
-            HelpAppLauncher::HELP_ACCOUNT_DISABLED);
-        break;
-    case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
-        help_app_->ShowHelpTopic(
-            HelpAppLauncher::HELP_HOSTED_ACCOUNT);
-        break;
-    default:
-      help_app_->ShowHelpTopic(login_performer_->login_timed_out() ?
-          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
-          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
-      break;
-  }
+void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
+  ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
+
+  // Reenable clicking on other windows and status area.
+  login_display_->SetUIEnabled(true);
+  SetStatusAreaEnabled(true);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, CaptchaView::Delegate implementation:
+//
+
 void ExistingUserController::OnCaptchaEntered(const std::string& captcha) {
   login_performer_->set_captcha(captcha);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, PasswordChangedView::Delegate implementation:
+//
+
 void ExistingUserController::RecoverEncryptedData(
     const std::string& old_password) {
   // LoginPerformer instance has state of the user so it should exist.
@@ -664,4 +475,73 @@
     login_performer_->ResyncEncryptedData();
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// ExistingUserController, private:
+
+void ExistingUserController::ActivateWizard(const std::string& screen_name) {
+  // WizardController takes care of deleting itself when done.
+  WizardController* controller = new WizardController();
+
+  // Give the background window to the controller.
+  controller->OwnBackground(background_window_, background_view_);
+  background_window_ = NULL;
+
+  controller->Init(screen_name, background_bounds_);
+  if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
+    controller->set_start_url(guest_mode_url_);
+
+  login_display_->OnFadeOut();
+
+  delete_timer_.Start(base::TimeDelta::FromSeconds(1), this,
+                      &ExistingUserController::Delete);
+}
+
+LoginDisplay* ExistingUserController::CreateLoginDisplay(
+    LoginDisplay::Delegate* delegate, const gfx::Rect& background_bounds) {
+  // TODO(rharrison): Create Web UI implementation too. http://crosbug.com/6398.
+  return new ViewsLoginDisplay(delegate, background_bounds);
+}
+
+void ExistingUserController::Delete() {
+  delete this;
+}
+
+gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
+  return background_view_->GetNativeWindow();
+}
+
+void ExistingUserController::SetStatusAreaEnabled(bool enable) {
+  if (background_view_) {
+    background_view_->SetStatusAreaEnabled(enable);
+  }
+}
+
+void ExistingUserController::ShowError(int error_id,
+                                       const std::string& details) {
+  // TODO(dpolukhin): show detailed error info. |details| string contains
+  // low level error info that is not localized and even is not user friendly.
+  // For now just ignore it because error_text contains all required information
+  // for end users, developers can see details string in Chrome logs.
+  VLOG(1) << details;
+  HelpAppLauncher::HelpTopic help_topic_id;
+  switch (login_performer_->error().state()) {
+    case GoogleServiceAuthError::CONNECTION_FAILED:
+      help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
+      break;
+    case GoogleServiceAuthError::ACCOUNT_DISABLED:
+      help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
+      break;
+    case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
+      help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
+      break;
+    default:
+      help_topic_id = login_performer_->login_timed_out() ?
+          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
+          HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
+      break;
+  }
+
+  login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index f648b22..cd57274 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,86 +7,76 @@
 #pragma once
 
 #include <string>
-#include <vector>
 
 #include "base/scoped_ptr.h"
 #include "base/task.h"
 #include "base/timer.h"
 #include "chrome/browser/chromeos/login/background_view.h"
 #include "chrome/browser/chromeos/login/captcha_view.h"
+#include "chrome/browser/chromeos/login/login_display.h"
 #include "chrome/browser/chromeos/login/login_performer.h"
-#include "chrome/browser/chromeos/login/message_bubble.h"
 #include "chrome/browser/chromeos/login/password_changed_view.h"
-#include "chrome/browser/chromeos/login/user_controller.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/wm_message_listener.h"
-#include "gfx/size.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest_prod.h"
+#include "ui/gfx/rect.h"
 
 namespace chromeos {
 
-class HelpAppLauncher;
-class MessageBubble;
 class UserCrosSettingsProvider;
 
 // ExistingUserController is used to handle login when someone has
-// already logged into the machine. When Init is invoked, a
-// UserController is created for each of the Users's in the
-// UserManager (including one for new user and one for Guest login),
-// and the window manager is then told to show the windows.
-//
+// already logged into the machine.
 // To use ExistingUserController create an instance of it and invoke Init.
-//
+// When Init is called it creates LoginDisplay instance which encapsulates
+// all login UI implementation.
 // ExistingUserController maintains it's own life cycle and deletes itself when
 // the user logs in (or chooses to see other settings).
-class ExistingUserController : public WmMessageListener::Observer,
-                               public UserController::Delegate,
+class ExistingUserController : public LoginDisplay::Delegate,
+                               public NotificationObserver,
                                public LoginPerformer::Delegate,
-                               public MessageBubbleDelegate,
                                public CaptchaView::Delegate,
                                public PasswordChangedView::Delegate {
  public:
-  // Initializes views for known users. |background_bounds| determines the
-  // bounds of background view.
-  ExistingUserController(const std::vector<UserManager::User>& users,
-                         const gfx::Rect& background_bounds);
+  // All UI initialization is deferred till Init() call.
+  // |background_bounds| determines the bounds of background view.
+  explicit ExistingUserController(const gfx::Rect& background_bounds);
 
-  // Creates and shows the appropriate set of windows.
-  void Init();
+  // Returns the current existing user controller if it has been created.
+  static ExistingUserController* current_controller() {
+    return current_controller_;
+  }
+
+  // Creates and shows login UI for known users.
+  void Init(const UserVector& users);
 
   // Takes ownership of the specified background widget and view.
   void OwnBackground(views::Widget* background_widget,
                      chromeos::BackgroundView* background_view);
 
-  // Tries to login from new user pod with given user login and password.
-  // Called after creating new account.
-  void LoginNewUser(const std::string& username, const std::string& password);
+  // LoginDisplay::Delegate: implementation
+  virtual void CreateAccount();
+  virtual void FixCaptivePortal();
+  virtual void Login(const std::string& username,
+                     const std::string& password);
+  virtual void LoginAsGuest();
+  virtual void OnUserSelected(const std::string& username);
+  virtual void RemoveUser(const std::string& username);
 
-  // Selects new user pod.
-  void SelectNewUser();
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
 
  private:
   friend class DeleteTask<ExistingUserController>;
+  friend class MockLoginPerformerDelegate;
 
   ~ExistingUserController();
 
-  // Cover for invoking the destructor. Used by delete_timer_.
-  void Delete();
-
-  // WmMessageListener::Observer:
-  virtual void ProcessWmMessage(const WmIpc::Message& message,
-                                GdkWindow* window);
-
-  // UserController::Delegate:
-  virtual void Login(UserController* source, const string16& password);
-  virtual void LoginOffTheRecord();
-  virtual void ClearErrors();
-  virtual void OnUserSelected(UserController* source);
-  virtual void ActivateWizard(const std::string& screen_name);
-  virtual void RemoveUser(UserController* source);
-  virtual void AddStartUrl(const GURL& start_url) { start_url_ = start_url; }
-  virtual void SelectUser(int index);
-  virtual void SetStatusAreaEnabled(bool enable);
-
   // LoginPerformer::Delegate implementation:
   virtual void OnLoginFailure(const LoginFailure& error);
   virtual void OnLoginSuccess(
@@ -99,15 +89,6 @@
       const GaiaAuthConsumer::ClientLoginResult& credentials);
   virtual void WhiteListCheckFailed(const std::string& email);
 
-  // Overridden from views::InfoBubbleDelegate.
-  virtual void InfoBubbleClosing(InfoBubble* info_bubble,
-                                 bool closed_by_escape) {
-    bubble_ = NULL;
-  }
-  virtual bool CloseOnEscape() { return true; }
-  virtual bool FadeInOnShow() { return false; }
-  virtual void OnHelpLinkActivated();
-
   // CaptchaView::Delegate:
   virtual void OnCaptchaEntered(const std::string& captcha);
 
@@ -115,19 +96,30 @@
   virtual void RecoverEncryptedData(const std::string& old_password);
   virtual void ResyncEncryptedData();
 
-  // Adds start url to command line.
-  void AppendStartUrlToCmdline();
+  // Starts WizardController with the specified screen.
+  void ActivateWizard(const std::string& screen_name);
+
+  // Creates LoginDisplay instance based on command line options.
+  LoginDisplay* CreateLoginDisplay(LoginDisplay::Delegate* delegate,
+                                   const gfx::Rect& background_bounds);
+
+  // Wrapper for invoking the destructor. Used by delete_timer_.
+  void Delete();
 
   // Returns corresponding native window.
   gfx::NativeWindow GetNativeWindow() const;
 
+  // Changes state of the status area. During login operation it's disabled.
+  void SetStatusAreaEnabled(bool enable);
+
   // Show error message. |error_id| error message ID in resources.
   // If |details| string is not empty, it specify additional error text
   // provided by authenticator, it is not localized.
   void ShowError(int error_id, const std::string& details);
 
-  // Send message to window manager to enable/disable click on other windows.
-  void SendSetLoginState(bool is_login);
+  void set_login_performer_delegate(LoginPerformer::Delegate* d) {
+    login_performer_delegate_.reset(d);
+  }
 
   // Bounds of the background window.
   const gfx::Rect background_bounds_;
@@ -136,45 +128,46 @@
   views::Widget* background_window_;
   BackgroundView* background_view_;
 
-  // The set of visible UserControllers.
-  std::vector<UserController*> controllers_;
-
-  // The set of invisible UserControllers.
-  std::vector<UserController*> invisible_controllers_;
-
   // Used to execute login operations.
   scoped_ptr<LoginPerformer> login_performer_;
 
-  // Index of selected view (user).
-  size_t selected_view_index_;
+  // Login UI implementation instance.
+  scoped_ptr<LoginDisplay> login_display_;
+
+  // Delegate for login performer to be overridden by tests.
+  // |this| is used if |login_performer_delegate_| is NULL.
+  scoped_ptr<LoginPerformer::Delegate> login_performer_delegate_;
+
+  // Username of the last login attempt.
+  std::string last_login_attempt_username_;
 
   // Number of login attempts. Used to show help link when > 1 unsuccessful
   // logins for the same user.
   size_t num_login_attempts_;
 
-  // See comment in ProcessWmMessage.
+  // Timer which is used to defer deleting and gave abitility to WM to smoothly
+  // hide the windows.
   base::OneShotTimer<ExistingUserController> delete_timer_;
 
-  // Pointer to the instance that was scheduled to be deleted soon or NULL
-  // if there is no such instance.
-  static ExistingUserController* delete_scheduled_instance_;
-
-  // Pointer to shown message bubble. We don't need to delete it because
-  // it will be deleted on bubble closing.
-  MessageBubble* bubble_;
-
-  // URL that will be opened on browser startup.
-  GURL start_url_;
-
-  // Help application used for help dialogs.
-  scoped_ptr<HelpAppLauncher> help_app_;
+  // Pointer to the current instance of the controller to be used by
+  // automation tests.
+  static ExistingUserController* current_controller_;
 
   // Triggers prefetching of user settings.
   scoped_ptr<UserCrosSettingsProvider> user_settings_;
 
+  // URL to append to start Guest mode with.
+  GURL guest_mode_url_;
+
+  // Used for user image changed notifications.
+  NotificationRegistrar registrar_;
+
   // Factory of callbacks.
   ScopedRunnableMethodFactory<ExistingUserController> method_factory_;
 
+  FRIEND_TEST_ALL_PREFIXES(ExistingUserControllerTest, NewUserLogin);
+  FRIEND_TEST_ALL_PREFIXES(ExistingUserControllerTest, CreateAccount);
+
   DISALLOW_COPY_AND_ASSIGN(ExistingUserController);
 };
 
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
new file mode 100644
index 0000000..f887c77
--- /dev/null
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 2011 The Chromium 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/message_loop.h"
+#include "chrome/browser/chromeos/cros/cros_mock.h"
+#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
+#include "chrome/browser/chromeos/cros/mock_login_library.h"
+#include "chrome/browser/chromeos/cros/mock_network_library.h"
+#include "chrome/browser/chromeos/login/existing_user_controller.h"
+#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/login_performer.h"
+#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/mock_authenticator.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
+#include "grit/generated_resources.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chromeos {
+
+using ::testing::AnyNumber;
+using ::testing::InvokeWithoutArgs;
+using ::testing::Return;
+
+const char kUsername[] = "test_user@gmail.com";
+const char kPassword[] = "test_password";
+
+class MockLoginPerformerDelegate : public LoginPerformer::Delegate {
+ public:
+  explicit MockLoginPerformerDelegate(ExistingUserController* controller)
+      : controller_(controller) {
+  }
+
+  void OnLoginSuccess(const std::string&,
+                      const std::string&,
+                      const GaiaAuthConsumer::ClientLoginResult&,
+                      bool) {
+    LoginPerformer* login_performer = controller_->login_performer_.release();
+    login_performer = NULL;
+    controller_->ActivateWizard(WizardController::kUserImageScreenName);
+    delete WizardController::default_controller();
+  }
+
+  MOCK_METHOD1(OnLoginFailure, void(const LoginFailure&));
+  MOCK_METHOD1(WhiteListCheckFailed, void(const std::string&));
+
+ private:
+  ExistingUserController* controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockLoginPerformerDelegate);
+};
+
+class ExistingUserControllerTest : public WizardInProcessBrowserTest {
+ protected:
+  ExistingUserControllerTest()
+      : chromeos::WizardInProcessBrowserTest(""),
+        mock_cryptohome_library_(NULL),
+        mock_login_library_(NULL),
+        mock_network_library_(NULL) {
+  }
+
+  virtual void SetUpWizard() {
+    gfx::Rect background_bounds(login::kWizardScreenWidth,
+                                login::kWizardScreenHeight);
+    ExistingUserController* controller =
+        new ExistingUserController(background_bounds);
+    controller->Init(UserVector());
+  }
+
+  ExistingUserController* existing_user_controller() {
+    return ExistingUserController::current_controller();
+  }
+
+  virtual void SetUpInProcessBrowserTestFixture() {
+    WizardInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
+    cros_mock_->InitStatusAreaMocks();
+    cros_mock_->SetStatusAreaMocksExpectations();
+
+    mock_network_library_ = cros_mock_->mock_network_library();
+
+    mock_login_library_ = new MockLoginLibrary();
+    EXPECT_CALL(*mock_login_library_, EmitLoginPromptReady())
+        .Times(1);
+    EXPECT_CALL(*mock_login_library_, RetrieveProperty(_, _, _))
+        .Times(AnyNumber())
+        .WillRepeatedly((Return(true)));
+    cros_mock_->test_api()->SetLoginLibrary(mock_login_library_, true);
+
+    cros_mock_->InitMockCryptohomeLibrary();
+    mock_cryptohome_library_ = cros_mock_->mock_cryptohome_library();
+    EXPECT_CALL(*mock_cryptohome_library_, IsMounted())
+        .Times(AnyNumber())
+        .WillRepeatedly((Return(true)));
+    LoginUtils::Set(new MockLoginUtils(kUsername, kPassword));
+  }
+
+  virtual void TearDownInProcessBrowserTestFixture() {
+    WizardInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
+    cros_mock_->test_api()->SetLoginLibrary(NULL, false);
+  }
+
+  MockCryptohomeLibrary* mock_cryptohome_library_;
+  MockLoginLibrary* mock_login_library_;
+  MockNetworkLibrary* mock_network_library_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ExistingUserControllerTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest, NewUserLogin) {
+  MockLoginPerformerDelegate* mock_delegate =
+      new MockLoginPerformerDelegate(existing_user_controller());
+  existing_user_controller()->set_login_performer_delegate(mock_delegate);
+
+  existing_user_controller()->Login(kUsername, kPassword);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/existing_user_view.cc b/chrome/browser/chromeos/login/existing_user_view.cc
index 2c3176e..352c51b 100644
--- a/chrome/browser/chromeos/login/existing_user_view.cc
+++ b/chrome/browser/chromeos/login/existing_user_view.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/existing_user_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/user_controller.h"
 #include "chrome/browser/chromeos/login/textfield_with_margin.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/background.h"
 #include "views/focus/focus_manager.h"
-#include "views/fill_layout.h"
+#include "views/layout/fill_layout.h"
 
 namespace chromeos {
 
@@ -33,22 +33,22 @@
 
   // Overridden from views::View:
   virtual bool OnKeyPressed(const views::KeyEvent& e) {
-    if (e.GetKeyCode() == app::VKEY_TAB) {
+    if (e.key_code() == ui::VKEY_TAB) {
       controller_->SelectUserRelative(e.IsShiftDown() ? -1 : 1);
       return true;
-    } else if (e.GetKeyCode() == app::VKEY_LEFT) {
+    } else if (e.key_code() == ui::VKEY_LEFT) {
       controller_->SelectUserRelative(-1);
       return true;
-    } else if (e.GetKeyCode() == app::VKEY_RIGHT) {
+    } else if (e.key_code() == ui::VKEY_RIGHT) {
       controller_->SelectUserRelative(1);
       return true;
     } else {
-      return false;
+      return TextfieldWithMargin::OnKeyPressed(e);
     }
   }
 
   virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
-    if (e.GetKeyCode() == app::VKEY_TAB)
+    if (e.key_code() == ui::VKEY_TAB)
       return true;
     else
       return views::Textfield::SkipDefaultKeyEventProcessing(e);
@@ -65,7 +65,7 @@
     : user_controller_(user_controller),
       password_field_(NULL),
       accel_login_off_the_record_(
-        views::Accelerator(app::VKEY_B, false, false, true)),
+        views::Accelerator(ui::VKEY_B, false, false, true)),
       accel_toggle_accessibility_(
           WizardAccessibilityHelper::GetAccelerator()) {
   AddAccelerator(accel_login_off_the_record_);
@@ -93,10 +93,10 @@
 bool ExistingUserView::AcceleratorPressed(
     const views::Accelerator& accelerator) {
   if (accelerator == accel_login_off_the_record_) {
-    user_controller_->OnLoginOffTheRecord();
+    user_controller_->OnLoginAsGuest();
     return true;
   } else if (accelerator == accel_toggle_accessibility_) {
-    WizardAccessibilityHelper::GetInstance()->ToggleAccessibility(this);
+    WizardAccessibilityHelper::GetInstance()->ToggleAccessibility();
     return true;
   }
   return false;
@@ -104,7 +104,7 @@
 
 bool ExistingUserView::HandleKeyEvent(views::Textfield* sender,
                                       const views::KeyEvent& key_event) {
-  if (key_event.GetKeyCode() == app::VKEY_RETURN) {
+  if (key_event.key_code() == ui::VKEY_RETURN) {
     if (!password_field_->text().empty())
       user_controller_->OnLogin("", UTF16ToUTF8(password_field_->text()));
   } else {
@@ -114,8 +114,14 @@
   return true;
 }
 
+void ExistingUserView::RequestFocus() {
+  password_field_->RequestFocus();
+}
+
 void ExistingUserView::ContentsChanged(views::Textfield* sender,
                                        const string16& new_contents) {
+  if (!new_contents.empty())
+    user_controller_->ClearErrors();
 }
 
 void ExistingUserView::EnableInputControls(bool enabled) {
@@ -131,13 +137,6 @@
   FocusPasswordField();
 }
 
-void ExistingUserView::ViewHierarchyChanged(bool is_add,
-                                            views::View* parent,
-                                            views::View* child) {
-  if (is_add && this == child)
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-}
-
 void ExistingUserView::FocusPasswordField() {
   password_field_->RequestFocus();
 }
diff --git a/chrome/browser/chromeos/login/existing_user_view.h b/chrome/browser/chromeos/login/existing_user_view.h
index 5212429..08c4eea 100644
--- a/chrome/browser/chromeos/login/existing_user_view.h
+++ b/chrome/browser/chromeos/login/existing_user_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -29,12 +29,12 @@
 
   // Overridden from views::View:
   virtual bool AcceleratorPressed(const views::Accelerator& accelerator);
-
   // Overriden from Textfield::Controller:
   virtual void ContentsChanged(views::Textfield* sender,
                                const string16& new_contents);
   virtual bool HandleKeyEvent(views::Textfield* sender,
                               const views::KeyEvent& keystroke);
+  virtual void RequestFocus();
 
   // Overriden from UserInput:
   virtual void EnableInputControls(bool enabled);
@@ -45,9 +45,6 @@
  protected:
   // Overridden from views::View:
   virtual void OnLocaleChanged();
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
 
  private:
   UserController* user_controller_;
diff --git a/chrome/browser/chromeos/login/google_authenticator_unittest.cc b/chrome/browser/chromeos/login/google_authenticator_unittest.cc
index 04437fb..3a1b766 100644
--- a/chrome/browser/chromeos/login/google_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/google_authenticator_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -492,7 +492,7 @@
 
 TEST_F(GoogleAuthenticatorTest, CheckLocalaccount) {
   GURL source(AuthResponseHandler::kTokenAuthUrl);
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
 
   MockConsumer consumer;
   EXPECT_CALL(consumer, OnLoginSuccess(username_, std::string(), _, false))
diff --git a/chrome/browser/chromeos/login/guest_user_view.cc b/chrome/browser/chromeos/login/guest_user_view.cc
index 0fcc48d..02978e2 100644
--- a/chrome/browser/chromeos/login/guest_user_view.cc
+++ b/chrome/browser/chromeos/login/guest_user_view.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/chromeos/login/guest_user_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/user_controller.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
@@ -23,7 +23,7 @@
 
   // Overridden from views::View:
   virtual bool OnKeyPressed(const views::KeyEvent& e) {
-    if (e.GetKeyCode() == app::VKEY_TAB) {
+    if (e.key_code() == ui::VKEY_TAB) {
       user_controller_->SelectUserRelative(e.IsShiftDown() ? -1 : 1);
       return true;
     }
@@ -31,7 +31,7 @@
   }
 
   virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
-    if (e.GetKeyCode() == app::VKEY_TAB)
+    if (e.key_code() == ui::VKEY_TAB)
       return true;
     return WideButton::SkipDefaultKeyEventProcessing(e);
   }
@@ -49,11 +49,11 @@
       accel_toggle_accessibility_(
           WizardAccessibilityHelper::GetAccelerator()),
       accel_login_off_the_record_(
-          views::Accelerator(app::VKEY_B, false, false, true)),
+          views::Accelerator(ui::VKEY_B, false, false, true)),
       accel_previous_pod_by_arrow_(
-          views::Accelerator(app::VKEY_LEFT, false, false, false)),
+          views::Accelerator(ui::VKEY_LEFT, false, false, false)),
       accel_next_pod_by_arrow_(
-          views::Accelerator(app::VKEY_RIGHT, false, false, false)) {
+          views::Accelerator(ui::VKEY_RIGHT, false, false, false)) {
   AddAccelerator(accel_toggle_accessibility_);
   AddAccelerator(accel_login_off_the_record_);
   AddAccelerator(accel_previous_pod_by_arrow_);
@@ -71,16 +71,12 @@
   SchedulePaint();
 }
 
-void GuestUserView::FocusSignInButton() {
-  submit_button_->RequestFocus();
-}
-
 bool GuestUserView::AcceleratorPressed(
     const views::Accelerator& accelerator) {
   if (accelerator == accel_login_off_the_record_)
-    user_controller_->OnLoginOffTheRecord();
+    user_controller_->OnLoginAsGuest();
   else if (accelerator == accel_toggle_accessibility_)
-    WizardAccessibilityHelper::GetInstance()->ToggleAccessibility(this);
+    WizardAccessibilityHelper::GetInstance()->ToggleAccessibility();
   else if (accelerator == accel_previous_pod_by_arrow_)
     user_controller_->SelectUserRelative(-1);
   else if (accelerator == accel_next_pod_by_arrow_)
@@ -90,23 +86,20 @@
   return true;
 }
 
+void GuestUserView::RequestFocus() {
+  submit_button_->RequestFocus();
+}
+
 void GuestUserView::ButtonPressed(
     views::Button* sender, const views::Event& event) {
   DCHECK(sender == submit_button_);
-  user_controller_->OnLoginOffTheRecord();
+  user_controller_->OnLoginAsGuest();
 }
 
 void GuestUserView::EnableInputControls(bool enabled) {
   submit_button_->SetEnabled(enabled);
 }
 
-void GuestUserView::ViewHierarchyChanged(bool is_add,
-                                         views::View* parent,
-                                         views::View* child) {
-  if (is_add && this == child)
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-}
-
 void GuestUserView::OnLocaleChanged() {
   RecreateFields();
 }
diff --git a/chrome/browser/chromeos/login/guest_user_view.h b/chrome/browser/chromeos/login/guest_user_view.h
index a7b31b4..f9919c6 100644
--- a/chrome/browser/chromeos/login/guest_user_view.h
+++ b/chrome/browser/chromeos/login/guest_user_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,10 +28,9 @@
 
   void RecreateFields();
 
-  void FocusSignInButton();
-
   // Overridden from views::View:
   virtual bool AcceleratorPressed(const views::Accelerator& accelerator);
+  virtual void RequestFocus();
 
   // Overridden from views::ButtonListener.
   virtual void ButtonPressed(views::Button* sender, const views::Event& event);
@@ -45,9 +44,6 @@
  private:
   // Overridden from views::View:
   virtual void OnLocaleChanged();
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
   virtual void Layout();
 
   // Button to start login.
diff --git a/chrome/browser/chromeos/login/help_app_launcher.cc b/chrome/browser/chromeos/login/help_app_launcher.cc
index 988e015..8ffe47b 100644
--- a/chrome/browser/chromeos/login/help_app_launcher.cc
+++ b/chrome/browser/chromeos/login/help_app_launcher.cc
@@ -4,13 +4,14 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
@@ -32,21 +33,8 @@
 // HelpApp, public:
 
 HelpAppLauncher::HelpAppLauncher(gfx::NativeWindow parent_window)
-    : parent_window_(parent_window) {
-}
-
-// Checks whether local file exists at specified base path and
-// returns GURL instance for it. Otherwise returns an empty GURL.
-static GURL GetLocalFileUrl(const std::string& base_path,
-                            const std::string& filename) {
-  FilePath file_path(base_path + filename);
-  if (file_util::PathExists(file_path)) {
-    const std::string path_url = std::string(chrome::kFileScheme) +
-         chrome::kStandardSchemeSeparator + file_path.value();
-    return GURL(path_url);
-  } else {
-    return GURL();
-  }
+    : help_topic_id_(HELP_CANT_ACCESS_ACCOUNT),
+      parent_window_(parent_window) {
 }
 
 void HelpAppLauncher::ShowHelpTopic(HelpTopic help_topic_id) {
@@ -54,22 +42,36 @@
     LOG(ERROR) << "Unknown help topic ID was requested: " << help_topic_id;
     return;
   }
+  help_topic_id_ = help_topic_id;
 
   // TODO(nkostylev): Detect connectivity state (offline/online).
   // Help presentation may wary based on that (dialog/launch BWSI mode).
-  GURL url = GetLocalFileUrl(kHelpTopicBasePath,
-                             kHelpTopicFiles[help_topic_id]);
-  if (!url.is_empty()) {
-    ShowHelpTopicDialog(url);
-  } else {
-    LOG(ERROR) << "Help topic static file was not found. ID: " << help_topic_id;
-  }
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+      NewRunnableMethod(this,
+                        &HelpAppLauncher::FindStaticHelpTopic,
+                        kHelpTopicFiles[help_topic_id]));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // HelpApp, private:
 
+void HelpAppLauncher::FindStaticHelpTopic(const std::string& filename) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  FilePath file_path(kHelpTopicBasePath + filename);
+  if (file_util::PathExists(file_path)) {
+    const std::string path_url = std::string(chrome::kFileScheme) +
+         chrome::kStandardSchemeSeparator + file_path.value();
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(this,
+                          &HelpAppLauncher::ShowHelpTopicDialog,
+                          GURL(path_url)));
+  } else {
+    LOG(ERROR) << "Help topic file was not found. ID: " << help_topic_id_;
+  }
+}
+
 void HelpAppLauncher::ShowHelpTopicDialog(const GURL& topic_url) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!dialog_.get()) {
     dialog_.reset(new LoginHtmlDialog(
         this,
diff --git a/chrome/browser/chromeos/login/help_app_launcher.h b/chrome/browser/chromeos/login/help_app_launcher.h
index acdfcb7..0703891 100644
--- a/chrome/browser/chromeos/login/help_app_launcher.h
+++ b/chrome/browser/chromeos/login/help_app_launcher.h
@@ -6,16 +6,18 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_HELP_APP_LAUNCHER_H_
 #pragma once
 
+#include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/chromeos/login/login_html_dialog.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace chromeos {
 
 // Provides help content during OOBE / login.
 // Based on connectivity state (offline/online) shows help topic dialog
 // or launches HelpApp in BWSI mode.
-class HelpAppLauncher : public LoginHtmlDialog::Delegate {
+class HelpAppLauncher : public LoginHtmlDialog::Delegate,
+                        public base::RefCountedThreadSafe<HelpAppLauncher> {
  public:
   // IDs of help topics available from HelpApp.
   enum HelpTopic {
@@ -49,12 +51,20 @@
   virtual void OnDialogClosed() {}
 
  private:
+  // Checks whether local help file with |filename| exists
+  // and opens it in a dialog if it does.
+  // Executed on a FILE thread.
+  void FindStaticHelpTopic(const std::string& filename);
+
   // Shows help topic dialog for specified GURL.
   void ShowHelpTopicDialog(const GURL& topic_url);
 
   // Dialog used to display help like "Can't access your account".
   scoped_ptr<LoginHtmlDialog> dialog_;
 
+  // Last requested help topic ID.
+  HelpTopic help_topic_id_;
+
   // Parent window which is passed to help dialog.
   gfx::NativeWindow parent_window_;
 
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc
index 14fc92b..999ad75 100644
--- a/chrome/browser/chromeos/login/helper.cc
+++ b/chrome/browser/chromeos/login/helper.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/browser/chromeos/login/helper.h"
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/google/google_util.h"
-#include "gfx/canvas_skia.h"
 #include "googleurl/src/gurl.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/label.h"
@@ -103,11 +103,14 @@
       new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
   widget_gtk->make_transient_to_parent();
   widget_gtk->MakeTransparent();
-  throbber_widget_ = widget_gtk;
 
+  throbber_widget_ = widget_gtk;
   throbber_bounds.Offset(host_view_->GetScreenBounds().origin());
   throbber_widget_->Init(host_gtk_window, throbber_bounds);
   throbber_widget_->SetContentsView(throbber);
+  // This keeps the window from flashing at startup.
+  gdk_window_set_back_pixmap(
+      throbber_widget_->GetNativeView()->window, NULL, false);
   throbber_widget_->Show();
   // WM can ignore bounds before widget is shown.
   throbber_widget_->SetBounds(throbber_bounds);
diff --git a/chrome/browser/chromeos/login/helper.h b/chrome/browser/chromeos/login/helper.h
index b613032..5a23224 100644
--- a/chrome/browser/chromeos/login/helper.h
+++ b/chrome/browser/chromeos/login/helper.h
@@ -153,15 +153,21 @@
 
 }  // namespace login
 
-// Font size correction in points for login/oobe controls.
+// Font size correction in pixels for login/oobe controls.
 #if defined(CROS_FONTS_USING_BCI)
 const int kFontSizeCorrectionDelta = 1;
-const int kUnselectedUsernameFontDelta = 0;
-const int kWelcomeTitleFontDelta = 5;
+const int kNetworkSelectionLabelFontDelta = 1;
+const int kSelectedUsernameFontDelta = 1;
+const int kUnselectedUsernameFontDelta = 1;
+const int kWelcomeTitleFontDelta = 8;
+const int kLoginTitleFontDelta = 3;
 #else
 const int kFontSizeCorrectionDelta = 2;
-const int kUnselectedUsernameFontDelta = 1;
-const int kWelcomeTitleFontDelta = 5;
+const int kNetworkSelectionLabelFontDelta = 1;
+const int kSelectedUsernameFontDelta = 1;
+const int kUnselectedUsernameFontDelta = 2;
+const int kWelcomeTitleFontDelta = 9;
+const int kLoginTitleFontDelta = 4;
 #endif
 
 // New pod sizes.
diff --git a/chrome/browser/chromeos/login/keyboard_switch_menu.cc b/chrome/browser/chromeos/login/keyboard_switch_menu.cc
index 62a37cc..dbb5ace 100644
--- a/chrome/browser/chromeos/login/keyboard_switch_menu.cc
+++ b/chrome/browser/chromeos/login/keyboard_switch_menu.cc
@@ -4,22 +4,23 @@
 
 #include "chrome/browser/chromeos/login/keyboard_switch_menu.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/status/status_area_host.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "views/controls/button/menu_button.h"
 #include "views/widget/widget_gtk.h"
 
 namespace chromeos {
 
 KeyboardSwitchMenu::KeyboardSwitchMenu()
     : InputMethodMenu(NULL /* pref_service */,
-                      false /* is_browser_mode */,
-                      false /* is_screen_locker_mode */,
-                      true /* is_out_of_box_experience_mode */) {
+                      StatusAreaHost::kLoginMode,
+                      true /* for_out_of_box_experience_dialog */) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -55,14 +56,11 @@
     if (IsItemCheckedAt(i))
       return GetLabelAt(i);
   }
-  VLOG(1) << "The input method menu is not ready yet.  Show a language name "
-             "that matches the hardware keyboard layout";
-  KeyboardLibrary *library = CrosLibrary::Get()->GetKeyboardLibrary();
-  const std::string keyboard_layout_id =
-      library->GetHardwareKeyboardLayoutName();
-  const std::string language_code =
-      input_method::GetLanguageCodeFromInputMethodId(keyboard_layout_id);
-  return input_method::GetLanguageDisplayNameFromCode(language_code);
+  VLOG(1) << "The input method menu is not ready yet. Show the display "
+          << "name of the current input method";
+  InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
+  return UTF8ToUTF16(input_method::GetInputMethodDisplayNameFromId(
+      library->current_input_method().id));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/keyboard_switch_menu.h b/chrome/browser/chromeos/login/keyboard_switch_menu.h
index d2692fc..ed261f8 100644
--- a/chrome/browser/chromeos/login/keyboard_switch_menu.h
+++ b/chrome/browser/chromeos/login/keyboard_switch_menu.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/scoped_ptr.h"
-#include "chrome/browser/chromeos/status/input_method_menu_button.h"
+#include "chrome/browser/chromeos/status/input_method_menu.h"
 #include "chrome/browser/chromeos/status/status_area_host.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/login/language_switch_menu.cc b/chrome/browser/chromeos/login/language_switch_menu.cc
index 595515a..36db187 100644
--- a/chrome/browser/chromeos/login/language_switch_menu.cc
+++ b/chrome/browser/chromeos/login/language_switch_menu.cc
@@ -4,18 +4,20 @@
 
 #include "chrome/browser/chromeos/login/language_switch_menu.h"
 
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/chromeos/login/ownership_service.h"
 #include "chrome/browser/chromeos/login/screen_observer.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/menu_button.h"
 #include "views/widget/widget_gtk.h"
 
@@ -82,26 +84,27 @@
   if (g_browser_process->GetApplicationLocale() == locale) {
     return;
   }
-  // Save new locale.
-  PrefService* prefs = g_browser_process->local_state();
-  // TODO(markusheintz): If the preference is managed and can not be changed by
-  // the user, changing the language should be disabled in the UI.
   // TODO(markusheintz): Change the if condition to prefs->IsUserModifiable()
   // once Mattias landed his pending patch.
-  if (!prefs->IsManagedPreference(prefs::kApplicationLocale)) {
-    prefs->SetString(prefs::kApplicationLocale, locale);
-    prefs->SavePersistentPrefs();
-
-    // Switch the locale.
-    const std::string loaded_locale =
-        ResourceBundle::ReloadSharedInstance(locale);
+  if (!g_browser_process->local_state()->
+      IsManagedPreference(prefs::kApplicationLocale)) {
+    std::string loaded_locale;
+    {
+      // Reloading resource bundle causes us to do blocking IO on UI thread.
+      // Temporarily allow it until we fix http://crosbug.com/11102
+      base::ThreadRestrictions::ScopedAllowIO allow_io;
+      // Switch the locale.
+      loaded_locale = ResourceBundle::ReloadSharedInstance(locale);
+    }
     CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
 
     // Enable the keyboard layouts that are necessary for the new locale.
+    // Change the current input method to the hardware keyboard layout
+    // since the input method currently in use may not be supported by the
+    // new locale.
     input_method::EnableInputMethods(
         locale, input_method::kKeyboardLayoutsOnly,
-        CrosLibrary::Get()->GetKeyboardLibrary()->
-            GetHardwareKeyboardLayoutName());
+        input_method::GetHardwareInputMethodId());
 
     // The following line does not seem to affect locale anyhow. Maybe in
     // future..
@@ -129,7 +132,7 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// menus::SimpleMenuModel::Delegate implementation.
+// ui::SimpleMenuModel::Delegate implementation.
 
 bool LanguageSwitchMenu::IsCommandIdChecked(int command_id) const {
   return false;
@@ -140,13 +143,16 @@
 }
 
 bool LanguageSwitchMenu::GetAcceleratorForCommandId(
-    int command_id, menus::Accelerator* accelerator) {
+    int command_id, ui::Accelerator* accelerator) {
   return false;
 }
 
 void LanguageSwitchMenu::ExecuteCommand(int command_id) {
   const std::string locale = language_list_->GetLocaleFromIndex(command_id);
   SwitchLanguage(locale);
+  g_browser_process->local_state()->SetString(
+      prefs::kApplicationLocale, locale);
+  g_browser_process->local_state()->ScheduleSavePersistentPrefs();
   InitLanguageMenu();
 
   // Update all view hierarchies that the locale has changed.
diff --git a/chrome/browser/chromeos/login/language_switch_menu.h b/chrome/browser/chromeos/login/language_switch_menu.h
index 6455a1a..c3fdb25 100644
--- a/chrome/browser/chromeos/login/language_switch_menu.h
+++ b/chrome/browser/chromeos/login/language_switch_menu.h
@@ -8,10 +8,10 @@
 
 #include <string>
 
-#include "app/menus/simple_menu_model.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/language_combobox_model.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
+#include "ui/base/models/simple_menu_model.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/controls/menu/view_menu_delegate.h"
 #include "views/view.h"
@@ -23,7 +23,7 @@
 class ScreenObserver;
 
 class LanguageSwitchMenu : public views::ViewMenuDelegate,
-                           public menus::SimpleMenuModel::Delegate {
+                           public ui::SimpleMenuModel::Delegate {
  public:
   LanguageSwitchMenu();
 
@@ -48,16 +48,16 @@
   // views::ViewMenuDelegate implementation.
   virtual void RunMenu(views::View* source, const gfx::Point& pt);
 
-  // menus::SimpleMenuModel::Delegate implementation.
+  // ui::SimpleMenuModel::Delegate implementation.
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
   // Dialog controls that we own ourselves.
-  menus::SimpleMenuModel menu_model_;
-  menus::SimpleMenuModel menu_model_submenu_;
+  ui::SimpleMenuModel menu_model_;
+  ui::SimpleMenuModel menu_model_submenu_;
   scoped_ptr<views::Menu2> menu_;
 
   // Language locale name storage.
diff --git a/chrome/browser/chromeos/login/login_display.h b/chrome/browser/chromeos/login/login_display.h
new file mode 100644
index 0000000..9137e19
--- /dev/null
+++ b/chrome/browser/chromeos/login/login_display.h
@@ -0,0 +1,109 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_DISPLAY_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_DISPLAY_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+
+namespace chromeos {
+
+// An abstract class that defines login UI implementation.
+class LoginDisplay {
+ public:
+  class Delegate {
+   public:
+    // Create new Google account.
+    virtual void CreateAccount() = 0;
+
+    // Users decides to sign in into captive portal.
+    virtual void FixCaptivePortal() = 0;
+
+    // Sign in using |username| and |password| specified.
+    // Used for both known and new users.
+    virtual void Login(const std::string& username,
+                       const std::string& password) = 0;
+
+    // Sign in into Guest session.
+    virtual void LoginAsGuest() = 0;
+
+    // Called when existing user pod is selected in the UI.
+    virtual void OnUserSelected(const std::string& username) = 0;
+
+    // Completely removes user (from the list of users and cryptohome).
+    virtual void RemoveUser(const std::string& username) = 0;
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // |background_bounds| determines the bounds of login UI background.
+  LoginDisplay(Delegate* delegate, const gfx::Rect& background_bounds)
+      : delegate_(delegate),
+        parent_window_(NULL),
+        background_bounds_(background_bounds) {}
+  virtual ~LoginDisplay() {}
+
+  // Initializes login UI with the user pods based on list of known users and
+  // guest, new user pods if those are enabled.
+  virtual void Init(const std::vector<UserManager::User>& users,
+                    bool show_guest,
+                    bool show_new_user) = 0;
+
+  // Called right before actual user removal process is initiated.
+  virtual void OnBeforeUserRemoved(const std::string& username) = 0;
+
+  // Called when user image has been changed.
+  // |user| contains updated user.
+  virtual void OnUserImageChanged(UserManager::User* user) = 0;
+
+  // Called right after user removal process has been initiated.
+  virtual void OnUserRemoved(const std::string& username) = 0;
+
+  // After this call login display should be ready to be smoothly destroyed
+  // (e.g. hide throbber, etc.).
+  virtual void OnFadeOut() = 0;
+
+  // Changes enabled state of the UI.
+  virtual void SetUIEnabled(bool is_enabled) = 0;
+
+  // Displays error with |error_msg_id| specified.
+  // |login_attempts| shows number of login attempts made by current user.
+  // |help_topic_id| is additional help topic that is presented as link.
+  virtual void ShowError(int error_msg_id,
+                         int login_attempts,
+                         HelpAppLauncher::HelpTopic help_topic_id) = 0;
+
+  gfx::Rect background_bounds() const { return background_bounds_; }
+
+  Delegate* delegate() { return delegate_; }
+  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
+
+  gfx::NativeWindow parent_window() const { return parent_window_; }
+  void set_parent_window(gfx::NativeWindow window) { parent_window_ = window; }
+
+  int width() const { return background_bounds_.width(); }
+
+ protected:
+  // Login UI delegate (controller).
+  Delegate* delegate_;
+
+  // Parent window, might be used to create dialog windows.
+  gfx::NativeWindow parent_window_;
+
+  // Bounds of the login UI background.
+  const gfx::Rect background_bounds_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginDisplay);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_DISPLAY_H_
diff --git a/chrome/browser/chromeos/login/login_html_dialog.cc b/chrome/browser/chromeos/login/login_html_dialog.cc
index 52c3635..ba3e72d 100644
--- a/chrome/browser/chromeos/login/login_html_dialog.cc
+++ b/chrome/browser/chromeos/login/login_html_dialog.cc
@@ -10,9 +10,9 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/views/html_dialog_view.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "views/window/window.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/login/login_html_dialog.h b/chrome/browser/chromeos/login/login_html_dialog.h
index bfefac4..d1ee19d 100644
--- a/chrome/browser/chromeos/login/login_html_dialog.h
+++ b/chrome/browser/chromeos/login/login_html_dialog.h
@@ -11,8 +11,8 @@
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/size.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
 
 namespace chromeos {
 
@@ -58,8 +58,8 @@
   virtual bool IsDialogModal() const { return true; }
   virtual std::wstring GetDialogTitle() const { return title_; }
   virtual GURL GetDialogContentURL() const { return url_; }
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const {}
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const {}
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const { return std::string(); }
   virtual void OnDialogClosed(const std::string& json_retval);
diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc
index d6ea7d9..85d59cd 100644
--- a/chrome/browser/chromeos/login/login_performer.cc
+++ b/chrome/browser/chromeos/login/login_performer.cc
@@ -6,8 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
@@ -17,15 +15,20 @@
 #include "chrome/browser/chromeos/boot_times_loader.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/screen_lock_library.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/screen_locker.h"
 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
 #include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace chromeos {
 
@@ -249,8 +252,23 @@
     StartAuthentication();
   } else {
     // Otherwise, do whitelist check first.
-    SignedSettingsHelper::Get()->StartCheckWhitelistOp(
-        username, this);
+    PrefService* local_state = g_browser_process->local_state();
+    CHECK(local_state);
+    if (local_state->IsManagedPreference(kAccountsPrefUsers)) {
+      if (UserCrosSettingsProvider::IsEmailInCachedWhitelist(username)) {
+        StartAuthentication();
+      } else {
+        if (delegate_)
+          delegate_->WhiteListCheckFailed(username);
+        else
+          NOTREACHED();
+      }
+    } else {
+      // In case of signed settings: with current implementation we do not
+      // trust whitelist returned by PrefService.  So make separate check.
+      SignedSettingsHelper::Get()->StartCheckWhitelistOp(
+          username, this);
+    }
   }
 }
 
@@ -338,6 +356,7 @@
       // Request screen lock & show error message there.
     case GoogleServiceAuthError::CAPTCHA_REQUIRED:
       // User is requested to enter CAPTCHA challenge.
+      captcha_token_ = last_login_failure_.error().captcha().token;
       RequestScreenLock();
       return;
     default:
@@ -405,6 +424,7 @@
       break;
     case GoogleServiceAuthError::CAPTCHA_REQUIRED:
       // User is requested to enter CAPTCHA challenge.
+      captcha_token_ = last_login_failure_.error().captcha().token;
       msg = l10n_util::GetStringUTF16(IDS_LOGIN_ERROR_PASSWORD_CHANGED);
       ScreenLocker::default_screen_locker()->ShowCaptchaAndErrorMessage(
           last_login_failure_.error().captcha().image_url,
diff --git a/chrome/browser/chromeos/login/login_screen.cc b/chrome/browser/chromeos/login/login_screen.cc
deleted file mode 100644
index 515b7be..0000000
--- a/chrome/browser/chromeos/login/login_screen.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/login/login_screen.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/process_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/chromeos/boot_times_loader.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/login/authentication_notification_details.h"
-#include "chrome/browser/chromeos/login/helper.h"
-#include "chrome/browser/chromeos/login/login_utils.h"
-#include "chrome/browser/chromeos/login/message_bubble.h"
-#include "chrome/browser/chromeos/login/screen_observer.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace chromeos {
-
-LoginScreen::LoginScreen(WizardScreenDelegate* delegate)
-    : ViewScreen<NewUserView>(delegate,
-          kNewUserPodFullWidth, kNewUserPodFullHeight),
-      bubble_(NULL),
-      authenticator_(NULL) {
-  if (CrosLibrary::Get()->EnsureLoaded()) {
-    authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
-  }
-}
-
-LoginScreen::~LoginScreen() {
-  ClearErrors();
-}
-
-NewUserView* LoginScreen::AllocateView() {
-  return new NewUserView(this, true, true);
-}
-
-void LoginScreen::OnLogin(const std::string& username,
-                          const std::string& password) {
-  BootTimesLoader::Get()->RecordLoginAttempted();
-  Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(authenticator_.get(),
-                        &Authenticator::AuthenticateToLogin,
-                        profile, username, password,
-                        std::string(), std::string()));
-}
-
-void LoginScreen::OnLoginOffTheRecord() {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(authenticator_.get(),
-                        &Authenticator::LoginOffTheRecord));
-}
-
-void LoginScreen::OnCreateAccount() {
-  delegate()->GetObserver(this)->OnExit(ScreenObserver::LOGIN_CREATE_ACCOUNT);
-}
-
-void LoginScreen::ClearErrors() {
-  // bubble_ will be set to NULL in InfoBubbleClosing callback.
-  if (bubble_)
-    bubble_->Close();
-}
-
-void LoginScreen::OnLoginFailure(const LoginFailure& failure) {
-  const std::string error = failure.GetErrorString();
-  VLOG(1) << "LoginManagerView: OnLoginFailure() " << error;
-  NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
-
-  // Check networking after trying to login in case user is
-  // cached locally or the local admin account.
-  if (!network || !CrosLibrary::Get()->EnsureLoaded()) {
-    ShowError(IDS_LOGIN_ERROR_NO_NETWORK_LIBRARY, error);
-  } else if (!network->Connected()) {
-    ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
-  } else {
-    ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
-  }
-
-  view()->ClearAndFocusPassword();
-  view()->EnableInputControls(true);
-}
-
-void LoginScreen::OnLoginSuccess(
-    const std::string& username,
-    const std::string& password,
-    const GaiaAuthConsumer::ClientLoginResult& credentials,
-    bool pending_requests) {
-
-  delegate()->GetObserver(this)->OnExit(ScreenObserver::LOGIN_SIGN_IN_SELECTED);
-  AppendStartUrlToCmdline();
-  LoginUtils::Get()->CompleteLogin(username,
-                                   password,
-                                   credentials,
-                                   pending_requests);
-}
-
-void LoginScreen::OnOffTheRecordLoginSuccess() {
-  LoginUtils::Get()->CompleteOffTheRecordLogin(start_url_);
-}
-
-void LoginScreen::OnHelpLinkActivated() {
-  AddStartUrl(GetAccountRecoveryHelpUrl());
-  OnLoginOffTheRecord();
-}
-
-void LoginScreen::AppendStartUrlToCmdline() {
-  if (start_url_.is_valid())
-    CommandLine::ForCurrentProcess()->AppendArg(start_url_.spec());
-}
-
-void LoginScreen::ShowError(int error_id, const std::string& details) {
-  ClearErrors();
-  std::wstring error_text = UTF16ToWide(l10n_util::GetStringUTF16(error_id));
-  // TODO(dpolukhin): show detailed error info. |details| string contains
-  // low level error info that is not localized and even is not user friendly.
-  // For now just ignore it because error_text contains all required information
-  // for end users, developers can see details string in Chrome logs.
-  bubble_ = MessageBubble::Show(
-      view()->GetWidget(),
-      view()->GetPasswordBounds(),
-      BubbleBorder::LEFT_TOP,
-      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
-      error_text,
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_CANT_ACCESS_ACCOUNT_BUTTON)),
-      this);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_screen.h b/chrome/browser/chromeos/login/login_screen.h
deleted file mode 100644
index 7c64dc3..0000000
--- a/chrome/browser/chromeos/login/login_screen.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SCREEN_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SCREEN_H_
-#pragma once
-
-#include <string>
-
-#include "base/ref_counted.h"
-#include "chrome/browser/chromeos/login/authenticator.h"
-#include "chrome/browser/chromeos/login/login_status_consumer.h"
-#include "chrome/browser/chromeos/login/message_bubble.h"
-#include "chrome/browser/chromeos/login/new_user_view.h"
-#include "chrome/browser/chromeos/login/view_screen.h"
-
-namespace chromeos {
-
-class MessageBubble;
-
-// This screen is obsolete, used only on test images. http://crosbug.com/7214
-// TODO(nkostylev): Use ExistingUserController sign in screen for test images.
-class LoginScreen : public ViewScreen<NewUserView>,
-                    public NewUserView::Delegate,
-                    public LoginStatusConsumer,
-                    public MessageBubbleDelegate {
- public:
-  explicit LoginScreen(WizardScreenDelegate* delegate);
-  virtual ~LoginScreen();
-
-  bool IsErrorShown() {
-    return bubble_ != NULL;
-  }
-
-  // NewUserView::Delegate:
-  virtual void OnLogin(const std::string& username,
-                       const std::string& password);
-  virtual void OnLoginOffTheRecord();
-  virtual void OnCreateAccount();
-  virtual void AddStartUrl(const GURL& start_url) { start_url_ = start_url; }
-  virtual void ClearErrors();
-  virtual void NavigateAway() {}
-  virtual void SetStatusAreaEnabled(bool enable) {}
-
-  // Overridden from LoginStatusConsumer.
-  virtual void OnLoginFailure(const LoginFailure& error);
-  virtual void OnLoginSuccess(
-      const std::string& username,
-      const std::string& password,
-      const GaiaAuthConsumer::ClientLoginResult& credentials,
-      bool pending_requests);
-  virtual void OnOffTheRecordLoginSuccess();
-
-  // Overridden from views::InfoBubbleDelegate.
-  virtual void InfoBubbleClosing(InfoBubble* info_bubble,
-                                 bool closed_by_escape) {
-    bubble_ = NULL;
-  }
-  virtual bool CloseOnEscape() { return true; }
-  virtual bool FadeInOnShow() { return false; }
-  virtual void OnHelpLinkActivated();
-
- private:
-  // ViewScreen<NewUserView>:
-  virtual NewUserView* AllocateView();
-
-  // Adds start url to command line.
-  void AppendStartUrlToCmdline();
-
-  // Shows error message with the specified message id.
-  // If |details| string is not empty, it specify additional error text
-  // provided by authenticator, it is not localized.
-  void ShowError(int error_id, const std::string& details);
-
-  // Pointer to shown message bubble. We don't need to delete it because
-  // it will be deleted on bubble closing.
-  MessageBubble* bubble_;
-
-  scoped_refptr<Authenticator> authenticator_;
-
-  // URL that will be opened on browser startup.
-  GURL start_url_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoginScreen);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SCREEN_H_
diff --git a/chrome/browser/chromeos/login/login_screen_browsertest.cc b/chrome/browser/chromeos/login/login_screen_browsertest.cc
deleted file mode 100644
index ccb9c7a..0000000
--- a/chrome/browser/chromeos/login/login_screen_browsertest.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/message_loop.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
-#include "chrome/browser/chromeos/cros/mock_login_library.h"
-#include "chrome/browser/chromeos/cros/mock_network_library.h"
-#include "chrome/browser/chromeos/login/login_screen.h"
-#include "chrome/browser/chromeos/login/mock_authenticator.h"
-#include "chrome/browser/chromeos/login/mock_screen_observer.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
-#include "chrome/browser/chromeos/login/wizard_screen.h"
-#include "grit/generated_resources.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromeos {
-
-using ::testing::AnyNumber;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Return;
-
-const char kUsername[] = "test_user@gmail.com";
-const char kPassword[] = "test_password";
-
-class LoginScreenTest : public WizardInProcessBrowserTest {
- public:
-  LoginScreenTest(): WizardInProcessBrowserTest("login"),
-                     mock_cryptohome_library_(NULL),
-                     mock_login_library_(NULL),
-                     mock_network_library_(NULL) {
-  }
-
- protected:
-  MockCryptohomeLibrary *mock_cryptohome_library_;
-  MockLoginLibrary *mock_login_library_;
-  MockNetworkLibrary *mock_network_library_;
-
-  virtual void SetUpInProcessBrowserTestFixture() {
-    WizardInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
-    cros_mock_->InitStatusAreaMocks();
-    cros_mock_->SetStatusAreaMocksExpectations();
-
-    mock_network_library_ = cros_mock_->mock_network_library();
-
-    mock_login_library_ = new MockLoginLibrary();
-    EXPECT_CALL(*mock_login_library_, EmitLoginPromptReady())
-        .Times(1);
-    cros_mock_->test_api()->SetLoginLibrary(mock_login_library_, true);
-
-    cros_mock_->InitMockCryptohomeLibrary();
-    mock_cryptohome_library_ = cros_mock_->mock_cryptohome_library();
-    EXPECT_CALL(*mock_cryptohome_library_, IsMounted())
-        .Times(AnyNumber())
-        .WillRepeatedly((Return(true)));
-    LoginUtils::Set(new MockLoginUtils(kUsername, kPassword));
-  }
-
-  virtual void TearDownInProcessBrowserTestFixture() {
-    WizardInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
-    cros_mock_->test_api()->SetLoginLibrary(NULL, false);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoginScreenTest);
-};
-
-static void Quit() {
-  VLOG(1) << "Posting a QuitTask to UI thread";
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          new MessageLoop::QuitTask);
-}
-IN_PROC_BROWSER_TEST_F(LoginScreenTest, TestBasic) {
-  ASSERT_TRUE(controller() != NULL);
-  ASSERT_EQ(controller()->current_screen(), controller()->GetLoginScreen());
-
-  scoped_ptr<MockScreenObserver> mock_screen_observer(
-      new MockScreenObserver());
-  EXPECT_CALL(*mock_screen_observer,
-              OnExit(ScreenObserver::LOGIN_SIGN_IN_SELECTED))
-      .WillOnce(InvokeWithoutArgs(Quit));
-
-  controller()->set_observer(mock_screen_observer.get());
-  NewUserView* login = controller()->GetLoginScreen()->view();
-  login->SetUsername(kUsername);
-  login->SetPassword(kPassword);
-
-  bool old_state = MessageLoop::current()->NestableTasksAllowed();
-  MessageLoop::current()->SetNestableTasksAllowed(true);
-  login->Login();
-  MessageLoop::current()->Run();
-  MessageLoop::current()->SetNestableTasksAllowed(old_state);
-  controller()->set_observer(NULL);
-}
-
-IN_PROC_BROWSER_TEST_F(LoginScreenTest, AuthenticationFailed) {
-  ASSERT_TRUE(controller() != NULL);
-  ASSERT_EQ(controller()->current_screen(), controller()->GetLoginScreen());
-
-  scoped_ptr<MockScreenObserver> mock_screen_observer(
-      new MockScreenObserver());
-  controller()->set_observer(mock_screen_observer.get());
-
-  EXPECT_CALL(*mock_network_library_, Connected())
-      .Times(AnyNumber())
-      .WillRepeatedly((Return(true)));
-
-  NewUserView* login = controller()->GetLoginScreen()->view();
-  login->SetUsername(kUsername);
-  login->SetPassword("wrong password");
-
-  bool old_state = MessageLoop::current()->NestableTasksAllowed();
-  MessageLoop::current()->SetNestableTasksAllowed(true);
-  login->Login();
-  MessageLoop::current()->Run();
-  MessageLoop::current()->SetNestableTasksAllowed(old_state);
-
-  ASSERT_EQ(controller()->current_screen(), controller()->GetLoginScreen());
-  EXPECT_TRUE(controller()->GetLoginScreen()->IsErrorShown());
-  controller()->set_observer(NULL);
-}
-
-IN_PROC_BROWSER_TEST_F(LoginScreenTest, IncognitoLogin) {
-  ASSERT_TRUE(controller() != NULL);
-  ASSERT_EQ(controller()->current_screen(), controller()->GetLoginScreen());
-
-  scoped_ptr<MockScreenObserver> mock_screen_observer(
-      new MockScreenObserver());
-  controller()->set_observer(mock_screen_observer.get());
-  NewUserView* login = controller()->GetLoginScreen()->view();
-
-  login->LinkActivated(login->guest_link_, 0);
-  controller()->set_observer(NULL);
-  Quit();
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_status_consumer.h b/chrome/browser/chromeos/login/login_status_consumer.h
index c1a18ab..eca567f 100644
--- a/chrome/browser/chromeos/login/login_status_consumer.h
+++ b/chrome/browser/chromeos/login/login_status_consumer.h
@@ -7,6 +7,8 @@
 #pragma once
 
 #include <string>
+
+#include "base/logging.h"
 #include "chrome/common/net/gaia/gaia_auth_consumer.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "net/base/net_errors.h"
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index 708f2e4..62f081a 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,12 +9,13 @@
 #include "base/command_line.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
-#include "base/lock.h"
 #include "base/path_service.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
@@ -23,6 +24,7 @@
 #include "chrome/browser/chromeos/cros/login_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/login/background_view.h"
 #include "chrome/browser/chromeos/login/cookie_fetcher.h"
 #include "chrome/browser/chromeos/login/google_authenticator.h"
 #include "chrome/browser/chromeos/login/language_switch_menu.h"
@@ -36,6 +38,7 @@
 #include "chrome/browser/net/gaia/token_service.h"
 #include "chrome/browser/net/preconnect.h"
 #include "chrome/browser/net/pref_proxy_config_service.h"
+#include "chrome/browser/plugin_updater.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -99,7 +102,8 @@
 class LoginUtilsImpl : public LoginUtils {
  public:
   LoginUtilsImpl()
-      : browser_launch_enabled_(true) {
+      : browser_launch_enabled_(true),
+        background_view_(NULL) {
   }
 
   // Invoked after the user has successfully logged in. This launches a browser
@@ -143,13 +147,28 @@
       Profile* profile,
       const GaiaAuthConsumer::ClientLoginResult& credentials);
 
+  // Sets the current background view.
+  virtual void SetBackgroundView(chromeos::BackgroundView* background_view);
+
+  // Gets the current background view.
+  virtual chromeos::BackgroundView* GetBackgroundView();
+
+ protected:
+  virtual std::string GetOffTheRecordCommandLine(
+      const GURL& start_url,
+      const CommandLine& base_command_line,
+      CommandLine *command_line);
+
  private:
   // Check user's profile for kApplicationLocale setting.
-  void RespectLocalePreference(PrefService* pref);
+  void RespectLocalePreference(Profile* pref);
 
   // Indicates if DoBrowserLaunch will actually launch the browser or not.
   bool browser_launch_enabled_;
 
+  // The current background view.
+  chromeos::BackgroundView* background_view_;
+
   DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
 };
 
@@ -160,7 +179,7 @@
   }
 
   LoginUtils* get() {
-    AutoLock create(create_lock_);
+    base::AutoLock create(create_lock_);
     if (!ptr_.get())
       reset(new LoginUtilsImpl);
     return ptr_.get();
@@ -175,7 +194,7 @@
 
   LoginUtilsWrapper() {}
 
-  Lock create_lock_;
+  base::Lock create_lock_;
   scoped_ptr<LoginUtils> ptr_;
 
   DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
@@ -209,9 +228,15 @@
   logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
   btl->AddLoginTimeMarker("LoggingRedirected", false);
 
-  // The default profile will have been changed because the ProfileManager
-  // will process the notification that the UserManager sends out.
-  Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
+  Profile* profile = NULL;
+  {
+    // Loading user profile causes us to do blocking IO on UI thread.
+    // Temporarily allow it until we fix http://crosbug.com/11104
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    // The default profile will have been changed because the ProfileManager
+    // will process the notification that the UserManager sends out.
+    profile = profile_manager->GetDefaultProfile(user_data_dir);
+  }
   btl->AddLoginTimeMarker("UserProfileGotten", false);
 
   // Change the proxy configuration service of the default request context to
@@ -268,7 +293,9 @@
 
   // Set the CrOS user by getting this constructor run with the
   // user's email on first retrieval.
-  profile->GetProfileSyncService(username)->SetPassphrase(password, false);
+  profile->GetProfileSyncService(username)->SetPassphrase(password,
+                                                          false,
+                                                          true);
   btl->AddLoginTimeMarker("SyncStarted", false);
 
   // Attempt to take ownership; this will fail if device is already owned.
@@ -288,12 +315,16 @@
   }
   btl->AddLoginTimeMarker("TPMOwned", false);
 
-  RespectLocalePreference(profile->GetPrefs());
+  RespectLocalePreference(profile);
 
   if (first_login) {
     SetFirstLoginPrefs(profile->GetPrefs());
   }
 
+  // Enable/disable plugins based on user preferences.
+  PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile);
+  btl->AddLoginTimeMarker("PluginsStateUpdated", false);
+
   // We suck. This is a hack since we do not have the enterprise feature
   // done yet to pull down policies from the domain admin. We'll take this
   // out when we get that done properly.
@@ -329,25 +360,20 @@
   }
 }
 
-void LoginUtilsImpl::RespectLocalePreference(PrefService* pref) {
-  std::string pref_locale = pref->GetString(prefs::kApplicationLocale);
-  if (pref_locale.empty()) {
-    // Profile synchronization takes time and is not completed at that moment
-    // at first login.  So we initialize locale preference in steps:
-    // (1) first save it to temporary backup;
-    // (2) on next login we assume that synchronization is already completed
-    //     and we may finalize initialization.
-    std::string pref_locale_backup =
-        pref->GetString(prefs::kApplicationLocaleBackup);
-    if (pref_locale_backup.empty()) {
-      pref->SetString(prefs::kApplicationLocaleBackup,
-                      g_browser_process->GetApplicationLocale());
-      return;
-    } else {
-      pref_locale.swap(pref_locale_backup);
-      pref->SetString(prefs::kApplicationLocale, pref_locale);
-    }
-  }
+void LoginUtilsImpl::RespectLocalePreference(Profile* profile) {
+  DCHECK(profile != NULL);
+  PrefService* prefs = profile->GetPrefs();
+  DCHECK(prefs != NULL);
+  if (g_browser_process == NULL)
+    return;
+
+  std::string pref_locale = prefs->GetString(prefs::kApplicationLocale);
+  if (pref_locale.empty())
+    pref_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
+  if (pref_locale.empty())
+    pref_locale = g_browser_process->GetApplicationLocale();
+  DCHECK(!pref_locale.empty());
+  profile->ChangeAppLocale(pref_locale, Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
   LanguageSwitchMenu::SwitchLanguage(pref_locale);
 }
 
@@ -359,58 +385,66 @@
   if (CrosLibrary::Get()->EnsureLoaded()) {
     // For guest session we ask session manager to restart Chrome with --bwsi
     // flag. We keep only some of the arguments of this process.
-    static const char* kForwardSwitches[] = {
-        switches::kEnableLogging,
-        switches::kUserDataDir,
-        switches::kScrollPixels,
-        switches::kEnableGView,
-        switches::kNoFirstRun,
-        switches::kLoginProfile,
-        switches::kCompressSystemFeedback,
-        switches::kDisableSeccompSandbox,
-#if defined(HAVE_XINPUT2)
-        switches::kTouchDevices,
-#endif
-    };
-    const CommandLine& browser_command_line =
-        *CommandLine::ForCurrentProcess();
+    const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
     CommandLine command_line(browser_command_line.GetProgram());
-    command_line.CopySwitchesFrom(browser_command_line,
-                                  kForwardSwitches,
-                                  arraysize(kForwardSwitches));
-    command_line.AppendSwitch(switches::kGuestSession);
-    command_line.AppendSwitch(switches::kIncognito);
-    command_line.AppendSwitchASCII(switches::kLoggingLevel,
-                                   kGuestModeLoggingLevel);
-    command_line.AppendSwitchASCII(
-        switches::kLoginUser,
-        UserManager::Get()->logged_in_user().email());
-
-    if (start_url.is_valid())
-      command_line.AppendArg(start_url.spec());
-
-    // Override the value of the homepage that is set in first run mode.
-    // TODO(altimofeev): extend action of the |kNoFirstRun| to cover this case.
-    command_line.AppendSwitchASCII(
-        switches::kHomePage,
-        GURL(chrome::kChromeUINewTabURL).spec());
-
-    std::string cmd_line_str = command_line.command_line_string();
-    // Special workaround for the arguments that should be quoted.
-    // Copying switches won't be needed when Guest mode won't need restart
-    // http://crosbug.com/6924
-    if (browser_command_line.HasSwitch(switches::kRegisterPepperPlugins)) {
-      cmd_line_str += base::StringPrintf(
-          kSwitchFormatString,
-          switches::kRegisterPepperPlugins,
-          browser_command_line.GetSwitchValueNative(
-              switches::kRegisterPepperPlugins).c_str());
-    }
+    std::string cmd_line_str =
+        GetOffTheRecordCommandLine(start_url,
+                                   browser_command_line,
+                                   &command_line);
 
     CrosLibrary::Get()->GetLoginLibrary()->RestartJob(getpid(), cmd_line_str);
   }
 }
 
+std::string LoginUtilsImpl::GetOffTheRecordCommandLine(
+    const GURL& start_url,
+    const CommandLine& base_command_line,
+    CommandLine* command_line) {
+  static const char* kForwardSwitches[] = {
+      switches::kEnableLogging,
+      switches::kUserDataDir,
+      switches::kScrollPixels,
+      switches::kEnableGView,
+      switches::kNoFirstRun,
+      switches::kLoginProfile,
+      switches::kCompressSystemFeedback,
+      switches::kDisableSeccompSandbox,
+#if defined(HAVE_XINPUT2)
+      switches::kTouchDevices,
+#endif
+  };
+  command_line->CopySwitchesFrom(base_command_line,
+                                 kForwardSwitches,
+                                 arraysize(kForwardSwitches));
+  command_line->AppendSwitch(switches::kGuestSession);
+  command_line->AppendSwitch(switches::kIncognito);
+  command_line->AppendSwitchASCII(switches::kLoggingLevel,
+                                 kGuestModeLoggingLevel);
+
+  if (start_url.is_valid())
+    command_line->AppendArg(start_url.spec());
+
+  // Override the value of the homepage that is set in first run mode.
+  // TODO(altimofeev): extend action of the |kNoFirstRun| to cover this case.
+  command_line->AppendSwitchASCII(
+      switches::kHomePage,
+      GURL(chrome::kChromeUINewTabURL).spec());
+
+  std::string cmd_line_str = command_line->command_line_string();
+  // Special workaround for the arguments that should be quoted.
+  // Copying switches won't be needed when Guest mode won't need restart
+  // http://crosbug.com/6924
+  if (base_command_line.HasSwitch(switches::kRegisterPepperPlugins)) {
+    cmd_line_str += base::StringPrintf(
+        kSwitchFormatString,
+        switches::kRegisterPepperPlugins,
+        base_command_line.GetSwitchValueNative(
+            switches::kRegisterPepperPlugins).c_str());
+  }
+
+  return cmd_line_str;
+}
+
 void LoginUtilsImpl::SetFirstLoginPrefs(PrefService* prefs) {
   VLOG(1) << "Setting first login prefs";
   BootTimesLoader* btl = BootTimesLoader::Get();
@@ -504,6 +538,14 @@
   }
 }
 
+void LoginUtilsImpl::SetBackgroundView(BackgroundView* background_view) {
+  background_view_ = background_view;
+}
+
+BackgroundView* LoginUtilsImpl::GetBackgroundView() {
+  return background_view_;
+}
+
 LoginUtils* LoginUtils::Get() {
   return LoginUtilsWrapper::GetInstance()->get();
 }
diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h
index 165852b..05a1a6c 100644
--- a/chrome/browser/chromeos/login/login_utils.h
+++ b/chrome/browser/chromeos/login/login_utils.h
@@ -10,13 +10,19 @@
 
 #include "chrome/common/net/gaia/gaia_auth_consumer.h"
 
+class CommandLine;
 class GURL;
 class Profile;
 class PrefService;
 
+namespace {
+class BrowserGuestSessionNavigatorTest;
+}  // namespace
+
 namespace chromeos {
 
 class Authenticator;
+class BackgroundView;
 class LoginStatusConsumer;
 
 class LoginUtils {
@@ -77,6 +83,21 @@
       Profile* profile,
       const GaiaAuthConsumer::ClientLoginResult& credentials) = 0;
 
+  // Sets the current background view.
+  virtual void SetBackgroundView(BackgroundView* background_view) = 0;
+
+  // Gets the current background view.
+  virtual BackgroundView* GetBackgroundView() = 0;
+
+ protected:
+  friend class ::BrowserGuestSessionNavigatorTest;
+
+  // Returns command line string to be used for the OTR process. Also modifies
+  // given command line.
+  virtual std::string GetOffTheRecordCommandLine(
+      const GURL& start_url,
+      const CommandLine& base_command_line,
+      CommandLine* command_line) = 0;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/message_bubble.cc b/chrome/browser/chromeos/login/message_bubble.cc
index da2415a..96a8a1c 100644
--- a/chrome/browser/chromeos/login/message_bubble.cc
+++ b/chrome/browser/chromeos/login/message_bubble.cc
@@ -4,15 +4,15 @@
 
 #include "chrome/browser/chromeos/login/message_bubble.h"
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/widget/widget.h"
 
 namespace chromeos {
@@ -115,7 +115,7 @@
   MessageBubble* bubble = new MessageBubble(
       views::WidgetGtk::TYPE_WINDOW, parent, image, text, help, true, delegate);
   bubble->Init(parent, position_relative_to, arrow_location,
-               bubble->text_->GetParent(), delegate);
+               bubble->text_->parent(), delegate);
   return bubble;
 }
 
@@ -132,7 +132,7 @@
   MessageBubble* bubble = new MessageBubble(
       views::WidgetGtk::TYPE_CHILD, parent, image, text, help, false, delegate);
   bubble->Init(parent, position_relative_to, arrow_location,
-               bubble->text_->GetParent(), delegate);
+               bubble->text_->parent(), delegate);
   return bubble;
 }
 
diff --git a/chrome/browser/chromeos/login/message_bubble.h b/chrome/browser/chromeos/login/message_bubble.h
index f29ecf8..6ef33bc 100644
--- a/chrome/browser/chromeos/login/message_bubble.h
+++ b/chrome/browser/chromeos/login/message_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_MESSAGE_BUBBLE_H_
 #pragma once
 
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "views/controls/button/button.h"
 #include "views/controls/link.h"
 #include "views/view.h"
diff --git a/chrome/browser/chromeos/login/mock_auth_response_handler.cc b/chrome/browser/chromeos/login/mock_auth_response_handler.cc
index 755064d..be82e83 100644
--- a/chrome/browser/chromeos/login/mock_auth_response_handler.cc
+++ b/chrome/browser/chromeos/login/mock_auth_response_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,10 +17,11 @@
 using ::testing::_;
 using ::testing::Invoke;
 
-MockAuthResponseHandler::MockAuthResponseHandler(const GURL& url,
-                                                 const URLRequestStatus& status,
-                                                 const int code,
-                                                 const std::string& data)
+MockAuthResponseHandler::MockAuthResponseHandler(
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    const int code,
+    const std::string& data)
     : remote_(url),
       status_(status),
       http_response_code_(code),
@@ -34,7 +35,7 @@
 
 void MockAuthResponseHandler::CompleteFetch(URLFetcher::Delegate* delegate,
                                             const GURL remote,
-                                            const URLRequestStatus status,
+                                            const net::URLRequestStatus status,
                                             const int http_response_code,
                                             const std::string data) {
   delegate->OnURLFetchComplete(NULL,
diff --git a/chrome/browser/chromeos/login/mock_authenticator.h b/chrome/browser/chromeos/login/mock_authenticator.h
index 5e0f708..320ddcf 100644
--- a/chrome/browser/chromeos/login/mock_authenticator.h
+++ b/chrome/browser/chromeos/login/mock_authenticator.h
@@ -10,6 +10,7 @@
 
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/login/authenticator.h"
+#include "chrome/browser/chromeos/login/background_view.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -149,10 +150,26 @@
       const GaiaAuthConsumer::ClientLoginResult& credentials) {
   }
 
+  void SetBackgroundView(BackgroundView* background_view) {
+    background_view_ = background_view;
+  }
+
+  BackgroundView* GetBackgroundView() {
+    return background_view_;
+  }
+
+  virtual std::string GetOffTheRecordCommandLine(
+      const GURL& start_url,
+      const CommandLine& base_command_line,
+      CommandLine* command_line) {
+    return std::string();
+  }
+
  private:
   std::string expected_username_;
   std::string expected_password_;
   std::string auth_token_;
+  chromeos::BackgroundView* background_view_;
 
   DISALLOW_COPY_AND_ASSIGN(MockLoginUtils);
 };
diff --git a/chrome/browser/chromeos/login/mock_ownership_service.h b/chrome/browser/chromeos/login/mock_ownership_service.h
index 5690cfb..8582517 100644
--- a/chrome/browser/chromeos/login/mock_ownership_service.h
+++ b/chrome/browser/chromeos/login/mock_ownership_service.h
@@ -16,8 +16,8 @@
 class MockOwnershipService : public OwnershipService {
  public:
   MOCK_METHOD0(IsAlreadyOwned, bool(void));
-  MOCK_METHOD0(StartLoadOwnerKeyAttempt, bool(void));
-  MOCK_METHOD0(StartTakeOwnershipAttempt, bool(void));
+  MOCK_METHOD0(StartLoadOwnerKeyAttempt, void(void));
+  MOCK_METHOD0(StartTakeOwnershipAttempt, void(void));
   MOCK_METHOD2(StartSigningAttempt, void(const std::string&,
                                          OwnerManager::Delegate*));
   MOCK_METHOD3(StartVerifyAttempt, void(const std::string&,
diff --git a/chrome/browser/chromeos/login/mock_url_fetchers.cc b/chrome/browser/chromeos/login/mock_url_fetchers.cc
index cc2b67a..1dc01de 100644
--- a/chrome/browser/chromeos/login/mock_url_fetchers.cc
+++ b/chrome/browser/chromeos/login/mock_url_fetchers.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,6 +7,7 @@
 #include <errno.h>
 
 #include "base/message_loop.h"
+#include "base/stringprintf.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/common/net/http_return.h"
 #include "chrome/common/net/url_fetcher.h"
@@ -55,8 +56,8 @@
 GotCanceledFetcher::~GotCanceledFetcher() {}
 
 void GotCanceledFetcher::Start() {
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::CANCELED);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::CANCELED);
   delegate()->OnURLFetchComplete(this,
                                  url_,
                                  status,
@@ -77,7 +78,7 @@
 SuccessFetcher::~SuccessFetcher() {}
 
 void SuccessFetcher::Start() {
-  URLRequestStatus success(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus success(net::URLRequestStatus::SUCCESS, 0);
   delegate()->OnURLFetchComplete(this,
                                  url_,
                                  success,
@@ -98,7 +99,7 @@
 FailFetcher::~FailFetcher() {}
 
 void FailFetcher::Start() {
-  URLRequestStatus failed(URLRequestStatus::FAILED, ECONNRESET);
+  net::URLRequestStatus failed(net::URLRequestStatus::FAILED, ECONNRESET);
   delegate()->OnURLFetchComplete(this,
                                  url_,
                                  failed,
@@ -107,7 +108,17 @@
                                  std::string());
 }
 
-HostedFetcher::HostedFetcher(bool success,
+// static
+const char CaptchaFetcher::kCaptchaToken[] = "token";
+// static
+const char CaptchaFetcher::kCaptchaUrlBase[] = "http://www.google.com/accounts/";
+// static
+const char CaptchaFetcher::kCaptchaUrlFragment[] = "fragment";
+// static
+const char CaptchaFetcher::kUnlockUrl[] = "http://what.ever";
+
+
+CaptchaFetcher::CaptchaFetcher(bool success,
                                const GURL& url,
                                const std::string& results,
                                URLFetcher::RequestType request_type,
@@ -116,10 +127,54 @@
       url_(url) {
 }
 
+CaptchaFetcher::~CaptchaFetcher() {}
+
+// static
+std::string CaptchaFetcher::GetCaptchaToken() {
+  return kCaptchaToken;
+}
+
+// static
+std::string CaptchaFetcher::GetCaptchaUrl() {
+  return std::string(kCaptchaUrlBase).append(kCaptchaUrlFragment);
+}
+
+// static
+std::string CaptchaFetcher::GetUnlockUrl() {
+  return kUnlockUrl;
+}
+
+void CaptchaFetcher::Start() {
+  net::URLRequestStatus success(net::URLRequestStatus::SUCCESS, 0);
+  std::string body = base::StringPrintf("Error=%s\n"
+                                        "Url=%s\n"
+                                        "CaptchaUrl=%s\n"
+                                        "CaptchaToken=%s\n",
+                                        "CaptchaRequired",
+                                        kUnlockUrl,
+                                        kCaptchaUrlFragment,
+                                        kCaptchaToken);
+  delegate()->OnURLFetchComplete(this,
+                                 url_,
+                                 success,
+                                 RC_FORBIDDEN,
+                                 ResponseCookies(),
+                                 body);
+}
+
+HostedFetcher::HostedFetcher(bool success,
+                             const GURL& url,
+                             const std::string& results,
+                             URLFetcher::RequestType request_type,
+                             URLFetcher::Delegate* d)
+    : URLFetcher(url, request_type, d),
+      url_(url) {
+}
+
 HostedFetcher::~HostedFetcher() {}
 
 void HostedFetcher::Start() {
-  URLRequestStatus success(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus success(net::URLRequestStatus::SUCCESS, 0);
   int response_code = RC_REQUEST_OK;
   std::string data;
   VLOG(1) << upload_data();
diff --git a/chrome/browser/chromeos/login/mock_url_fetchers.h b/chrome/browser/chromeos/login/mock_url_fetchers.h
index c3fd37b..522fc7e 100644
--- a/chrome/browser/chromeos/login/mock_url_fetchers.h
+++ b/chrome/browser/chromeos/login/mock_url_fetchers.h
@@ -87,6 +87,31 @@
   DISALLOW_COPY_AND_ASSIGN(FailFetcher);
 };
 
+class CaptchaFetcher : public URLFetcher {
+ public:
+  CaptchaFetcher(bool success,
+                 const GURL& url,
+                 const std::string& results,
+                 URLFetcher::RequestType request_type,
+                 URLFetcher::Delegate* d);
+  virtual ~CaptchaFetcher();
+
+  static std::string GetCaptchaToken();
+  static std::string GetCaptchaUrl();
+  static std::string GetUnlockUrl();
+
+  void Start();
+
+ private:
+  static const char kCaptchaToken[];
+  static const char kCaptchaUrlBase[];
+  static const char kCaptchaUrlFragment[];
+  static const char kUnlockUrl[];
+  GURL url_;
+
+  DISALLOW_COPY_AND_ASSIGN(CaptchaFetcher);
+};
+
 class HostedFetcher : public URLFetcher {
  public:
   HostedFetcher(bool success,
diff --git a/chrome/browser/chromeos/login/mock_user_manager.h b/chrome/browser/chromeos/login/mock_user_manager.h
index 87858e6..ce65c88 100644
--- a/chrome/browser/chromeos/login/mock_user_manager.h
+++ b/chrome/browser/chromeos/login/mock_user_manager.h
@@ -24,7 +24,7 @@
   MOCK_METHOD1(UserLoggedIn, void(const std::string&));
   MOCK_METHOD1(RemoveUser, void(const std::string&));
   MOCK_METHOD1(IsKnownUser, bool(const std::string&));
-  MOCK_METHOD0(logged_in_user, const User&());
+  MOCK_CONST_METHOD0(logged_in_user, const User&());
   MOCK_METHOD0(current_user_is_owner, bool());
   MOCK_METHOD1(set_current_user_is_owner, void(bool));
 };
diff --git a/chrome/browser/chromeos/login/network_screen.cc b/chrome/browser/chromeos/login/network_screen.cc
index 579687e..470e6d1 100644
--- a/chrome/browser/chromeos/login/network_screen.cc
+++ b/chrome/browser/chromeos/login/network_screen.cc
@@ -4,18 +4,20 @@
 
 #include "chrome/browser/chromeos/login/network_screen.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/login/background_view.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
+#include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/network_selection_view.h"
 #include "chrome/browser/chromeos/login/screen_observer.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -100,8 +102,10 @@
 
 void NetworkScreen::OnHelpLinkActivated() {
   ClearErrors();
-  if (!help_app_.get())
-    help_app_.reset(new HelpAppLauncher(view()->GetNativeWindow()));
+  if (!help_app_.get()) {
+    help_app_ = new HelpAppLauncher(
+        LoginUtils::Get()->GetBackgroundView()->GetNativeWindow());
+  }
   help_app_->ShowHelpTopic(HelpAppLauncher::HELP_CONNECTIVITY);
 }
 
@@ -161,8 +165,7 @@
             IDS_NETWORK_SELECTION_ERROR,
             l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME),
             network_id_)),
-        UTF16ToWide(
-            l10n_util::GetStringUTF16(IDS_NETWORK_SELECTION_ERROR_HELP)),
+        UTF16ToWide(l10n_util::GetStringUTF16(IDS_LEARN_MORE)),
         this);
     network_control->RequestFocus();
   }
diff --git a/chrome/browser/chromeos/login/network_screen.h b/chrome/browser/chromeos/login/network_screen.h
index b3aa531..4c83745 100644
--- a/chrome/browser/chromeos/login/network_screen.h
+++ b/chrome/browser/chromeos/login/network_screen.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SCREEN_H_
 #pragma once
 
-#include "base/scoped_ptr.h"
+#include "base/ref_counted.h"
 #include "base/string16.h"
 #include "base/task.h"
 #include "base/timer.h"
@@ -111,7 +111,7 @@
   MessageBubble* bubble_;
 
   // Help application used for help dialogs.
-  scoped_ptr<HelpAppLauncher> help_app_;
+  scoped_refptr<HelpAppLauncher> help_app_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkScreen);
 };
diff --git a/chrome/browser/chromeos/login/network_screen_browsertest.cc b/chrome/browser/chromeos/login/network_screen_browsertest.cc
index aa1e845..3bca37d 100644
--- a/chrome/browser/chromeos/login/network_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/network_screen_browsertest.cc
@@ -4,8 +4,6 @@
 
 #include <string>
 
-#include "app/combobox_model.h"
-#include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
@@ -26,8 +24,8 @@
 #include "grit/generated_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/text_button.h"
-#include "views/controls/combobox/combobox.h"
 
 namespace chromeos {
 using ::testing::AnyNumber;
@@ -120,9 +118,9 @@
     controller()->set_observer(mock_screen_observer.get());
     DummyButtonListener button_listener;
     views::TextButton button(&button_listener, L"Button");
-    views::MouseEvent event(views::Event::ET_MOUSE_RELEASED,
+    views::MouseEvent event(ui::ET_MOUSE_RELEASED,
                             0, 0,
-                            views::Event::EF_LEFT_BUTTON_DOWN);
+                            ui::EF_LEFT_BUTTON_DOWN);
     network_screen->ButtonPressed(&button, event);
     ui_test_utils::RunAllPendingInMessageLoop();
     controller()->set_observer(NULL);
diff --git a/chrome/browser/chromeos/login/network_screen_delegate.h b/chrome/browser/chromeos/login/network_screen_delegate.h
index e64e380..807093a 100644
--- a/chrome/browser/chromeos/login/network_screen_delegate.h
+++ b/chrome/browser/chromeos/login/network_screen_delegate.h
@@ -6,10 +6,8 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SCREEN_DELEGATE_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "views/controls/button/button.h"
-#include "views/controls/combobox/combobox.h"
 
 namespace gfx {
 class Size;
diff --git a/chrome/browser/chromeos/login/network_selection_view.cc b/chrome/browser/chromeos/login/network_selection_view.cc
index f4eb223..87c2f37 100644
--- a/chrome/browser/chromeos/login/network_selection_view.cc
+++ b/chrome/browser/chromeos/login/network_selection_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,6 @@
 #include <sys/types.h>
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/keyboard_switch_menu.h"
@@ -19,15 +17,17 @@
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "chrome/browser/chromeos/status/network_dropdown_button.h"
-#include "gfx/size.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/size.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
-#include "views/fill_layout.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/fill_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/widget/widget_gtk.h"
 #include "views/window/non_client_view.h"
@@ -263,7 +263,7 @@
   column_set->AddPaddingColumn(1, h_padding);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
   column_set->AddPaddingColumn(1, h_padding);
@@ -292,15 +292,18 @@
   welcome_label_->SetFont(welcome_label_font);
   welcome_label_->SetMultiLine(true);
 
+  gfx::Font select_label_font = rb.GetFont(ResourceBundle::MediumFont).
+      DeriveFont(kNetworkSelectionLabelFontDelta);
+
   select_language_label_ = new views::Label();
-  select_language_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  select_language_label_->SetFont(select_label_font);
 
   languages_menubutton_ = new NotifyingMenuButton(
       NULL, std::wstring(), delegate_->language_switch_menu(), true, delegate_);
   InitMenuButtonProperties(languages_menubutton_);
 
   select_keyboard_label_ = new views::Label();
-  select_keyboard_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  select_keyboard_label_->SetFont(select_label_font);
 
   keyboards_menubutton_ = new DropDownButton(
       NULL /* listener */, L"", delegate_->keyboard_switch_menu(),
@@ -308,7 +311,7 @@
   InitMenuButtonProperties(keyboards_menubutton_);
 
   select_network_label_ = new views::Label();
-  select_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  select_network_label_->SetFont(select_label_font);
 
   network_dropdown_ = new NetworkControlReportOnActivate(false,
                                                          GetNativeWindow(),
@@ -371,18 +374,12 @@
   SchedulePaint();
 }
 
-void NetworkSelectionView::ViewHierarchyChanged(bool is_add,
-                                                View* parent,
-                                                View* child) {
-  if (is_add && this == child)
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // NetworkSelectionView, public:
 
 gfx::NativeWindow NetworkSelectionView::GetNativeWindow() const {
-  return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
+  return
+      GTK_WINDOW(static_cast<const WidgetGtk*>(GetWidget())->GetNativeView());
 }
 
 views::View* NetworkSelectionView::GetNetworkControlView() const {
diff --git a/chrome/browser/chromeos/login/network_selection_view.h b/chrome/browser/chromeos/login/network_selection_view.h
index 1774d25..3b44e4b 100644
--- a/chrome/browser/chromeos/login/network_selection_view.h
+++ b/chrome/browser/chromeos/login/network_selection_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -80,9 +80,6 @@
   virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
     return true;
   }
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
 
   // LoginHtmlDialog::Delegate implementation:
   virtual void OnDialogClosed() {}
diff --git a/chrome/browser/chromeos/login/new_user_view.cc b/chrome/browser/chromeos/login/new_user_view.cc
index cd2508c..65d7f45 100644
--- a/chrome/browser/chromeos/login/new_user_view.cc
+++ b/chrome/browser/chromeos/login/new_user_view.cc
@@ -10,25 +10,29 @@
 #include <algorithm>
 #include <vector>
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/login/textfield_with_margin.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
 #include "chrome/browser/chromeos/views/copy_background.h"
-#include "gfx/font.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/font.h"
+#include "views/controls/button/menu_button.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
 #include "views/widget/widget_gtk.h"
@@ -81,10 +85,10 @@
 
   // Overridden from views::View:
   virtual bool OnKeyPressed(const views::KeyEvent& e) {
-    if (e.GetKeyCode() == app::VKEY_LEFT) {
+    if (e.key_code() == ui::VKEY_LEFT) {
       return controller_->NavigateAway();
     }
-    return false;
+    return TextfieldWithMargin::OnKeyPressed(e);
   }
 
  private:
@@ -111,22 +115,24 @@
       create_account_link_(NULL),
       guest_link_(NULL),
       languages_menubutton_(NULL),
-      accel_focus_pass_(views::Accelerator(app::VKEY_P, false, false, true)),
-      accel_focus_user_(views::Accelerator(app::VKEY_U, false, false, true)),
+      accel_focus_pass_(views::Accelerator(ui::VKEY_P, false, false, true)),
+      accel_focus_user_(views::Accelerator(ui::VKEY_U, false, false, true)),
       accel_login_off_the_record_(
-          views::Accelerator(app::VKEY_B, false, false, true)),
+          views::Accelerator(ui::VKEY_B, false, false, true)),
       accel_toggle_accessibility_(WizardAccessibilityHelper::GetAccelerator()),
       delegate_(delegate),
       ALLOW_THIS_IN_INITIALIZER_LIST(focus_grabber_factory_(this)),
-      focus_delayed_(false),
       login_in_process_(false),
       need_border_(need_border),
       need_guest_link_(false),
       need_create_account_(false),
       languages_menubutton_order_(-1),
       sign_in_button_order_(-1) {
-  if (need_guest_link && UserCrosSettingsProvider::cached_allow_guest())
-    need_guest_link_ = true;
+  if (UserCrosSettingsProvider::cached_allow_guest()) {
+    need_create_account_ = true;
+    if (need_guest_link)
+      need_guest_link_ = true;
+  }
 }
 
 NewUserView::~NewUserView() {
@@ -144,7 +150,7 @@
   // Set up fonts.
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
   gfx::Font title_font = rb.GetFont(ResourceBundle::MediumBoldFont).DeriveFont(
-      kFontSizeCorrectionDelta);
+      kLoginTitleFontDelta);
   gfx::Font title_hint_font = rb.GetFont(ResourceBundle::BoldFont);
 
   title_label_ = new views::Label();
@@ -168,7 +174,7 @@
   username_field_ = new UsernameField(this);
   username_field_->set_background(new CopyBackground(this));
   username_field_->SetAccessibleName(
-      ASCIIToWide(l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_USERNAME_LABEL)));
+      l10n_util::GetStringUTF16(IDS_CHROMEOS_ACC_USERNAME_LABEL));
   AddChildView(username_field_);
 
   password_field_ = new TextfieldWithMargin(views::Textfield::STYLE_PASSWORD);
@@ -214,9 +220,9 @@
   } else if (accelerator == accel_focus_pass_) {
     password_field_->RequestFocus();
   } else if (accelerator == accel_login_off_the_record_) {
-    delegate_->OnLoginOffTheRecord();
+    delegate_->OnLoginAsGuest();
   } else if (accelerator == accel_toggle_accessibility_) {
-    WizardAccessibilityHelper::GetInstance()->ToggleAccessibility(this);
+    WizardAccessibilityHelper::GetInstance()->ToggleAccessibility();
   } else {
     return false;
   }
@@ -234,6 +240,8 @@
           IDR_MENU_DROPARROW_SHARP));
   languages_menubutton_->SetEnabledColor(kLanguagesMenuTextColor);
   languages_menubutton_->SetFocusable(true);
+  languages_menubutton_->SetEnabled(!g_browser_process->local_state()->
+      IsManagedPreference(prefs::kApplicationLocale));
 
   // There is no way to get native button preferred size after the button was
   // sized so delete and recreate the button on text update.
@@ -263,14 +271,14 @@
   // so we restore their original position in layout.
   if (view == languages_menubutton_) {
     if (languages_menubutton_order_ < 0) {
-      languages_menubutton_order_ = GetChildViewCount();
+      languages_menubutton_order_ = child_count();
     }
-    views::View::AddChildView(languages_menubutton_order_, view);
+    views::View::AddChildViewAt(view, languages_menubutton_order_);
   } else if (view == sign_in_button_) {
     if (sign_in_button_order_ < 0) {
-      sign_in_button_order_ = GetChildViewCount();
+      sign_in_button_order_ = child_count();
     }
-    views::View::AddChildView(sign_in_button_order_, view);
+    views::View::AddChildViewAt(view, sign_in_button_order_);
   } else {
     views::View::AddChildView(view);
   }
@@ -312,49 +320,22 @@
 }
 
 void NewUserView::RequestFocus() {
-  MessageLoop::current()->PostTask(FROM_HERE,
-      focus_grabber_factory_.NewRunnableMethod(
-          &NewUserView::FocusFirstField));
+  if (username_field_->text().empty())
+    username_field_->RequestFocus();
+  else
+    password_field_->RequestFocus();
 }
 
 void NewUserView::ViewHierarchyChanged(bool is_add,
                                        View *parent,
                                        View *child) {
-  if (is_add && child == this) {
-    MessageLoop::current()->PostTask(FROM_HERE,
-        focus_grabber_factory_.NewRunnableMethod(
-            &NewUserView::FocusFirstField));
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-  } else if (is_add && (child == username_field_ || child == password_field_)) {
+  if (is_add && (child == username_field_ || child == password_field_)) {
     MessageLoop::current()->PostTask(FROM_HERE,
         focus_grabber_factory_.NewRunnableMethod(
             &NewUserView::Layout));
   }
 }
 
-void NewUserView::NativeViewHierarchyChanged(bool attached,
-                                             gfx::NativeView native_view,
-                                             views::RootView* root_view) {
-  if (focus_delayed_ && attached) {
-    focus_delayed_ = false;
-    MessageLoop::current()->PostTask(FROM_HERE,
-        focus_grabber_factory_.NewRunnableMethod(
-            &NewUserView::FocusFirstField));
-  }
-}
-
-void NewUserView::FocusFirstField() {
-  if (GetFocusManager()) {
-    if (username_field_->text().empty())
-      username_field_->RequestFocus();
-    else
-      password_field_->RequestFocus();
-  } else {
-    // We are invisible - delay until it is no longer the case.
-    focus_delayed_ = true;
-  }
-}
-
 // Sets the bounds of the view, using x and y as the origin.
 // The width is determined by the min of width and the preferred size
 // of the view, unless force_width is true in which case it is always used.
@@ -417,9 +398,10 @@
   splitter_down1_->SetBounds(0, y, this->width(), kSplitterHeight);
   splitter_down2_->SetBounds(0, y + 1, this->width(), kSplitterHeight);
 
+  y += kBottomPad;
   if (need_guest_link_) {
-    y -= setViewBounds(guest_link_,
-                       x, y + kBottomPad, max_width, false) + kRowPad;
+    y += setViewBounds(guest_link_,
+                       x, y, max_width, false) + kRowPad;
   }
   if (need_create_account_) {
     y += setViewBounds(create_account_link_, x, y, max_width, false);
@@ -483,7 +465,7 @@
   if (source == create_account_link_) {
     delegate_->OnCreateAccount();
   } else if (source == guest_link_) {
-    delegate_->OnLoginOffTheRecord();
+    delegate_->OnLoginAsGuest();
   }
 }
 
@@ -530,7 +512,7 @@
   if (!CrosLibrary::Get()->EnsureLoaded() || login_in_process_)
     return false;
 
-  if (key_event.GetKeyCode() == app::VKEY_RETURN) {
+  if (key_event.key_code() == ui::VKEY_RETURN) {
     if (!username_field_->text().empty() && !password_field_->text().empty())
       Login();
     // Return true so that processing ends
@@ -544,10 +526,13 @@
 void NewUserView::ContentsChanged(views::Textfield* sender,
                                   const string16& new_contents) {
   UpdateSignInButtonState();
+  if (!new_contents.empty())
+    delegate_->ClearErrors();
 }
 
 void NewUserView::EnableInputControls(bool enabled) {
-  languages_menubutton_->SetEnabled(enabled);
+  languages_menubutton_->SetEnabled(g_browser_process->local_state()->
+      IsManagedPreference(prefs::kApplicationLocale) ? false : enabled);
   username_field_->SetEnabled(enabled);
   password_field_->SetEnabled(enabled);
   sign_in_button_->SetEnabled(enabled);
diff --git a/chrome/browser/chromeos/login/new_user_view.h b/chrome/browser/chromeos/login/new_user_view.h
index d749035..7a38c02 100644
--- a/chrome/browser/chromeos/login/new_user_view.h
+++ b/chrome/browser/chromeos/login/new_user_view.h
@@ -14,13 +14,13 @@
 #include "chrome/browser/chromeos/login/user_input.h"
 #include "views/accelerator.h"
 #include "views/controls/button/button.h"
-#include "views/controls/button/menu_button.h"
 #include "views/controls/link.h"
 #include "views/controls/textfield/textfield.h"
 #include "views/view.h"
 
 namespace views {
 class Label;
+class MenuButton;
 class NativeButton;
 }  // namespace views
 
@@ -44,22 +44,16 @@
                          const std::string& password) = 0;
 
     // Initiates off the record (incognito) login.
-    virtual void OnLoginOffTheRecord() = 0;
+    virtual void OnLoginAsGuest() = 0;
 
     // User initiated new account creation.
     virtual void OnCreateAccount() = 0;
 
-    // Adds start URL that will be opened after login.
-    virtual void AddStartUrl(const GURL& start_url) = 0;
-
     // User started typing so clear all error messages.
     virtual void ClearErrors() = 0;
 
     // User tries to navigate away from NewUserView pod.
     virtual void NavigateAway() = 0;
-
-    // Enables/disables raw of controls at status area.
-    virtual void SetStatusAreaEnabled(bool enable) = 0;
   };
 
   // If |need_border| is true, RoundedRect border and background are required.
@@ -125,15 +119,10 @@
   virtual void ViewHierarchyChanged(bool is_add,
                                     views::View *parent,
                                     views::View *child);
-  virtual void NativeViewHierarchyChanged(bool attached,
-                                          gfx::NativeView native_view,
-                                          views::RootView* root_view);
   virtual void OnLocaleChanged();
   void AddChildView(View* view);
 
  private:
-  void FocusFirstField();
-
   // Creates Link control and adds it as a child.
   void InitLink(views::Link** link);
 
@@ -178,10 +167,6 @@
 
   LanguageSwitchMenu language_switch_menu_;
 
-  // Indicates that this view was created when focus manager was unavailable
-  // (on the hidden tab, for example).
-  bool focus_delayed_;
-
   // True when login is in process.
   bool login_in_process_;
 
@@ -199,9 +184,6 @@
   int languages_menubutton_order_;
   int sign_in_button_order_;
 
-  FRIEND_TEST_ALL_PREFIXES(LoginScreenTest, IncognitoLogin);
-  friend class LoginScreenTest;
-
   DISALLOW_COPY_AND_ASSIGN(NewUserView);
 };
 
diff --git a/chrome/browser/chromeos/login/online_attempt.cc b/chrome/browser/chromeos/login/online_attempt.cc
index 2b891bd..b90c3d1 100644
--- a/chrome/browser/chromeos/login/online_attempt.cc
+++ b/chrome/browser/chromeos/login/online_attempt.cc
@@ -43,12 +43,13 @@
 }
 
 void OnlineAttempt::Initiate(Profile* profile) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  gaia_authenticator_.reset(
-      new GaiaAuthFetcher(this,
-                          GaiaConstants::kChromeOSSource,
-                          profile->GetRequestContext()));
-  TryClientLogin();
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  gaia_authenticator_.reset(new GaiaAuthFetcher(this,
+                                                GaiaConstants::kChromeOSSource,
+                                                profile->GetRequestContext()));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      NewRunnableMethod(this, &OnlineAttempt::TryClientLogin));
 }
 
 void OnlineAttempt::OnClientLoginSuccess(
@@ -115,7 +116,7 @@
 
     return;
   }
-
+  VLOG(2) << "ClientLogin attempt failed with " << error.state();
   TriggerResolve(GaiaAuthConsumer::ClientLoginResult(),
                  LoginFailure::FromNetworkAuthFailure(error));
 }
diff --git a/chrome/browser/chromeos/login/online_attempt.h b/chrome/browser/chromeos/login/online_attempt.h
index f91c468..c5f0f35 100644
--- a/chrome/browser/chromeos/login/online_attempt.h
+++ b/chrome/browser/chromeos/login/online_attempt.h
@@ -18,6 +18,7 @@
 class CancelableTask;
 class GaiaAuthFetcher;
 class Profile;
+class URLRequestContextGetter;
 
 namespace chromeos {
 class AuthAttemptState;
@@ -34,6 +35,7 @@
   // Initiate the online login attempt.  Status will be recorded in
   // |current_attempt|, and resolver_->Resolve() will be called on the
   // IO thread when useful state is available.
+  // Must be called on the UI thread.
   void Initiate(Profile* profile);
 
   // Callbacks from GaiaAuthFetcher
diff --git a/chrome/browser/chromeos/login/online_attempt_unittest.cc b/chrome/browser/chromeos/login/online_attempt_unittest.cc
index 9e03a05..dd8d360 100644
--- a/chrome/browser/chromeos/login/online_attempt_unittest.cc
+++ b/chrome/browser/chromeos/login/online_attempt_unittest.cc
@@ -91,8 +91,7 @@
         BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask());
   }
 
-  static void RunThreadTest(OnlineAttempt* attempt, Profile* profile) {
-    attempt->Initiate(profile);
+  static void RunThreadTest() {
     MessageLoop::current()->RunAllPending();
   }
 
@@ -134,10 +133,10 @@
   MockFactory<GotCanceledFetcher> factory;
   URLFetcher::set_factory(&factory);
 
+  attempt_->Initiate(&profile);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest,
-                          attempt_, &profile));
+      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
 
   MessageLoop::current()->Run();
 
@@ -161,10 +160,10 @@
   MockFactory<ExpectCanceledFetcher> factory;
   URLFetcher::set_factory(&factory);
 
+  attempt_->Initiate(&profile);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest,
-                          attempt_, &profile));
+      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
 
   // Post a task to cancel the login attempt.
   CancelLogin(attempt_.get());
@@ -192,10 +191,10 @@
 
   TestAttemptState local_state("", "", "", "", "", true);
   attempt_ = new OnlineAttempt(&local_state, resolver_.get());
+  attempt_->Initiate(&profile);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest,
-                          attempt_, &profile));
+      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
 
   MessageLoop::current()->Run();
 
@@ -218,10 +217,10 @@
 
   TestAttemptState local_state("", "", "", "", "", true);
   attempt_ = new OnlineAttempt(&local_state, resolver_.get());
+  attempt_->Initiate(&profile);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest,
-                          attempt_, &profile));
+      NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
 
   MessageLoop::current()->Run();
 
diff --git a/chrome/browser/chromeos/login/oobe_progress_bar.cc b/chrome/browser/chromeos/login/oobe_progress_bar.cc
index 82b50de..1f0c482 100644
--- a/chrome/browser/chromeos/login/oobe_progress_bar.cc
+++ b/chrome/browser/chromeos/login/oobe_progress_bar.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/chromeos/login/oobe_progress_bar.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/canvas_skia.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 
 namespace chromeos {
 
@@ -53,7 +53,7 @@
 }
 
 void OobeProgressBar::Paint(gfx::Canvas* canvas) {
-  gfx::Rect bounds = GetLocalBounds(false);
+  gfx::Rect bounds = GetContentsBounds();
 
   int x = bounds.x();
   int y = bounds.y();
@@ -111,7 +111,7 @@
                            next_x - ix, line_->height());
     }
 
-    std::wstring str = UTF16ToWide(l10n_util::GetStringUTF16(steps_[i]));
+    string16 str = l10n_util::GetStringUTF16(steps_[i]);
     canvas->DrawStringInt(str, font_, color,
         x + kTextPadding, y + dot->height() + kTextPadding,
         (next_x - x - 2 * kTextPadding),
diff --git a/chrome/browser/chromeos/login/oobe_progress_bar.h b/chrome/browser/chromeos/login/oobe_progress_bar.h
index 63718b7..b576b7e 100644
--- a/chrome/browser/chromeos/login/oobe_progress_bar.h
+++ b/chrome/browser/chromeos/login/oobe_progress_bar.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "gfx/font.h"
+#include "ui/gfx/font.h"
 #include "views/view.h"
 
 class SkBitmap;
diff --git a/chrome/browser/chromeos/login/ownership_service.cc b/chrome/browser/chromeos/login/ownership_service.cc
index c256e96..60067bf 100644
--- a/chrome/browser/chromeos/login/ownership_service.cc
+++ b/chrome/browser/chromeos/login/ownership_service.cc
@@ -31,67 +31,47 @@
   return file_util::PathExists(utils_->GetOwnerKeyFilePath());
 }
 
-bool OwnershipService::StartLoadOwnerKeyAttempt() {
-  if (!IsAlreadyOwned()) {
-    LOG(WARNING) << "Device not yet owned";
-    return false;
-  }
+void OwnershipService::StartLoadOwnerKeyAttempt() {
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(manager_.get(), &OwnerManager::LoadOwnerKey));
-  return true;
+      NewRunnableFunction(&TryLoadOwnerKeyAttempt, this));
 }
 
-bool OwnershipService::StartTakeOwnershipAttempt(const std::string& owner) {
-  if (IsAlreadyOwned()) {
-    VLOG(1) << "Device is already owned";
-    return false;
-  }
+void OwnershipService::StartTakeOwnershipAttempt(const std::string& unused) {
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(manager_.get(),
-                        &OwnerManager::GenerateKeysAndExportPublic));
-  return true;
+      NewRunnableFunction(&OwnershipService::TryTakeOwnershipAttempt, this));
 }
 
 void OwnershipService::StartSigningAttempt(const std::string& data,
                                            OwnerManager::Delegate* d) {
-  if (!IsAlreadyOwned()) {
-    LOG(ERROR) << "Device not yet owned";
-    d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
-    return;
-  }
   BrowserThread::ID thread_id;
   if (!BrowserThread::GetCurrentThreadIdentifier(&thread_id))
     thread_id = BrowserThread::UI;
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(manager_.get(),
-                        &OwnerManager::Sign,
-                        thread_id,
-                        data, d));
+      NewRunnableFunction(&OwnershipService::TrySigningAttempt,
+                          this,
+                          thread_id,
+                          data,
+                          d));
   return;
 }
 
 void OwnershipService::StartVerifyAttempt(const std::string& data,
                                           const std::vector<uint8>& signature,
                                           OwnerManager::Delegate* d) {
-  if (!IsAlreadyOwned()) {
-    LOG(ERROR) << "Device not yet owned";
-    d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
-    return;
-  }
   BrowserThread::ID thread_id;
   if (!BrowserThread::GetCurrentThreadIdentifier(&thread_id))
     thread_id = BrowserThread::UI;
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(manager_.get(),
-                        &OwnerManager::Verify,
-                        thread_id,
-                        data,
-                        signature,
-                        d));
+      NewRunnableFunction(&OwnershipService::TryVerifyAttempt,
+                          this,
+                          thread_id,
+                          data,
+                          signature,
+                          d));
   return;
 }
 
@@ -101,4 +81,62 @@
   return IsAlreadyOwned() && manager_->EnsurePrivateKey();
 }
 
+// static
+void OwnershipService::TryLoadOwnerKeyAttempt(OwnershipService* service) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  if (!service->IsAlreadyOwned()) {
+    VLOG(1) << "Device not yet owned";
+    return;
+  }
+  service->manager()->LoadOwnerKey();
+}
+
+// static
+void OwnershipService::TryTakeOwnershipAttempt(OwnershipService* service) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  if (service->IsAlreadyOwned()) {
+    VLOG(1) << "Device is already owned";
+    return;
+  }
+  service->manager()->GenerateKeysAndExportPublic();
+}
+
+// static
+void OwnershipService::TrySigningAttempt(OwnershipService* service,
+                                         const BrowserThread::ID thread_id,
+                                         const std::string& data,
+                                         OwnerManager::Delegate* d) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  if (!service->IsAlreadyOwned()) {
+    LOG(ERROR) << "Device not yet owned";
+    BrowserThread::PostTask(
+        thread_id, FROM_HERE,
+        NewRunnableFunction(&OwnershipService::FailAttempt, d));
+    return;
+  }
+  service->manager()->Sign(thread_id, data, d);
+}
+
+// static
+void OwnershipService::TryVerifyAttempt(OwnershipService* service,
+                                        const BrowserThread::ID thread_id,
+                                        const std::string& data,
+                                        const std::vector<uint8>& signature,
+                                        OwnerManager::Delegate* d) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  if (!service->IsAlreadyOwned()) {
+    LOG(ERROR) << "Device not yet owned";
+    BrowserThread::PostTask(
+        thread_id, FROM_HERE,
+        NewRunnableFunction(&OwnershipService::FailAttempt, d));
+    return;
+  }
+  service->manager()->Verify(thread_id, data, signature, d);
+}
+
+// static
+void OwnershipService::FailAttempt(OwnerManager::Delegate* d) {
+  d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ownership_service.h b/chrome/browser/chromeos/login/ownership_service.h
index bc407d9..6cc733f 100644
--- a/chrome/browser/chromeos/login/ownership_service.h
+++ b/chrome/browser/chromeos/login/ownership_service.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/login/owner_key_utils.h"
 #include "chrome/browser/chromeos/login/owner_manager.h"
 
@@ -24,31 +25,26 @@
   static OwnershipService* GetSharedInstance();
   virtual ~OwnershipService();
 
-  virtual bool IsAlreadyOwned();
-
   // If the device has been owned already, posts a task to the FILE thread to
   // fetch the public key off disk.
-  // Returns true if the attempt was initiated, false otherwise.
   //
   // Sends out a OWNER_KEY_FETCH_ATTEMPT_SUCCESS notification on success,
   // OWNER_KEY_FETCH_ATTEMPT_FAILED on failure.
-  virtual bool StartLoadOwnerKeyAttempt();
+  virtual void StartLoadOwnerKeyAttempt();
 
   // If the device has not yet been owned, posts a task to the FILE
   // thread to generate the owner's keys and put them in the right
   // places.  Keeps them in memory as well, for later use.
-  // Returns true if the attempt was initiated, false otherwise.
   //
   // Upon failure, sends out OWNER_KEY_FETCH_ATTEMPT_FAILED.
   // Upon success, sends out OWNER_KEY_FETCH_ATTEMPT_SUCCESS.
   // If no attempt is started (if the device is already owned), no
   // notification is sent.
-  virtual bool StartTakeOwnershipAttempt(const std::string& owner);
+  virtual void StartTakeOwnershipAttempt(const std::string& unused);
 
   // Initiate an attempt to sign |data| with |private_key_|.  Will call
   // d->OnKeyOpComplete() when done.  Upon success, the signature will be passed
   // as the |payload| argument to d->OnKeyOpComplete().
-  // Returns true if the attempt was initiated, false otherwise.
   //
   // If you call this on a well-known thread, you'll be called back on that
   // thread.  Otherwise, you'll get called back on the UI thread.
@@ -58,7 +54,6 @@
   // Initiate an attempt to verify that |signature| is valid over |data| with
   // |public_key_|.  When the attempt is completed, an appropriate KeyOpCode
   // will be passed to d->OnKeyOpComplete().
-  // Returns true if the attempt was initiated, false otherwise.
   //
   // If you call this on a well-known thread, you'll be called back on that
   // thread.  Otherwise, you'll get called back on the UI thread.
@@ -66,8 +61,13 @@
                                   const std::vector<uint8>& signature,
                                   OwnerManager::Delegate* d);
 
+  // This method must be run on the FILE thread.
   virtual bool CurrentUserIsOwner();
 
+  // This method must be run on the FILE thread.
+  // Note: not static, for better mocking.
+  virtual bool IsAlreadyOwned();
+
  protected:
   OwnershipService();
 
@@ -75,6 +75,21 @@
   friend struct base::DefaultLazyInstanceTraits<OwnershipService>;
   friend class OwnershipServiceTest;
 
+  static void TryLoadOwnerKeyAttempt(OwnershipService* service);
+  static void TryTakeOwnershipAttempt(OwnershipService* service);
+  static void TrySigningAttempt(OwnershipService* service,
+                                const BrowserThread::ID thread_id,
+                                const std::string& data,
+                                OwnerManager::Delegate* d);
+  static void TryVerifyAttempt(OwnershipService* service,
+                               const BrowserThread::ID thread_id,
+                               const std::string& data,
+                               const std::vector<uint8>& signature,
+                               OwnerManager::Delegate* d);
+  static void FailAttempt(OwnerManager::Delegate* d);
+
+  OwnerManager* manager() { return manager_.get(); }
+
   scoped_refptr<OwnerManager> manager_;
   scoped_refptr<OwnerKeyUtils> utils_;
 };
diff --git a/chrome/browser/chromeos/login/ownership_service_unittest.cc b/chrome/browser/chromeos/login/ownership_service_unittest.cc
index 0982392..cbd72d7 100644
--- a/chrome/browser/chromeos/login/ownership_service_unittest.cc
+++ b/chrome/browser/chromeos/login/ownership_service_unittest.cc
@@ -94,14 +94,6 @@
   EXPECT_FALSE(service_->IsAlreadyOwned());
 }
 
-TEST_F(OwnershipServiceTest, LoadOwnerKeyUnowned) {
-  StartUnowned();
-
-  EXPECT_CALL(*mock_, GetOwnerKeyFilePath())
-      .WillRepeatedly(Return(tmpfile_));
-  EXPECT_FALSE(service_->StartLoadOwnerKeyAttempt());
-}
-
 TEST_F(OwnershipServiceTest, LoadOwnerKeyFail) {
   MockKeyLoadObserver loader;
   EXPECT_CALL(*mock_, GetOwnerKeyFilePath())
@@ -110,7 +102,7 @@
       .WillOnce(Return(false))
       .RetiresOnSaturation();
 
-  EXPECT_TRUE(service_->StartLoadOwnerKeyAttempt());
+  service_->StartLoadOwnerKeyAttempt();
 
   // Run remaining events, until ExportPublicKeyViaDbus().
   message_loop_.Run();
@@ -126,17 +118,11 @@
       .WillOnce(DoAll(SetArgumentPointee<1>(fake_public_key_),
                       Return(true)))
       .RetiresOnSaturation();
-  EXPECT_TRUE(service_->StartLoadOwnerKeyAttempt());
+  service_->StartLoadOwnerKeyAttempt();
 
   message_loop_.Run();
 }
 
-TEST_F(OwnershipServiceTest, TakeOwnershipAlreadyOwned) {
-  EXPECT_CALL(*mock_, GetOwnerKeyFilePath())
-      .WillRepeatedly(Return(tmpfile_));
-  EXPECT_FALSE(service_->StartTakeOwnershipAttempt("you"));
-}
-
 TEST_F(OwnershipServiceTest, AttemptKeyGeneration) {
   // We really only care that we initiate key generation here;
   // actual key-generation paths are tested in owner_manager_unittest.cc
@@ -150,7 +136,7 @@
   EXPECT_CALL(*mock_, GetOwnerKeyFilePath())
       .WillRepeatedly(Return(tmpfile_));
 
-  EXPECT_TRUE(service_->StartTakeOwnershipAttempt("me"));
+  service_->StartTakeOwnershipAttempt("me");
 
   message_loop_.Run();
 }
@@ -160,9 +146,11 @@
 
   EXPECT_CALL(*mock_, GetOwnerKeyFilePath())
       .WillRepeatedly(Return(tmpfile_));
-  // Create delegate that does not quit the message loop on callback.
-  MockKeyUser delegate(OwnerManager::KEY_UNAVAILABLE, false);
+
+  MockKeyUser delegate(OwnerManager::KEY_UNAVAILABLE);
   service_->StartVerifyAttempt("", std::vector<uint8>(), &delegate);
+
+  message_loop_.Run();
 }
 
 TEST_F(OwnershipServiceTest, GetKeyFailDuringVerify) {
diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc
index e8bd65a..caa7711 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator.cc
@@ -87,11 +87,7 @@
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate));
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(current_online_.get(),
-                        &OnlineAttempt::Initiate,
-                        profile));
+  current_online_->Initiate(profile);
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
       NewRunnableMethod(this,
@@ -261,11 +257,7 @@
                            login_captcha,
                            false /* not a new user */));
   current_online_ = new OnlineAttempt(reauth_state_.get(), this);
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(current_online_.get(),
-                        &OnlineAttempt::Initiate,
-                        profile));
+  current_online_->Initiate(profile);
 }
 
 void ParallelAuthenticator::Resolve() {
@@ -352,7 +344,9 @@
       BrowserThread::PostTask(
           BrowserThread::UI, FROM_HERE,
           NewRunnableMethod(this, &ParallelAuthenticator::OnLoginFailure,
-                            current_state_->online_outcome()));
+                            (reauth_state_.get() ?
+                             reauth_state_->online_outcome() :
+                             current_state_->online_outcome())));
       break;
     case HAVE_NEW_PW:
       key_migrator_ =
diff --git a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
index f6200d7..34eaea4 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
@@ -576,6 +576,49 @@
   message_loop_.Run();
 }
 
+TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetCaptchad) {
+  ExpectLoginSuccess(username_, password_, result_, true);
+  FailOnLoginFailure();
+  EXPECT_CALL(*mock_library_, GetSystemSalt())
+      .WillOnce(Return(CryptohomeBlob(2, 0)))
+      .RetiresOnSaturation();
+
+  // Set up state as though a cryptohome mount attempt has occurred and
+  // succeeded; also, an online request that never made it.
+  state_->PresetCryptohomeStatus(true, 0);
+  // state_ is released further down.
+  SetAttemptState(auth_, state_.get());
+  RunResolve(auth_.get(), &message_loop_);
+
+  // Offline login has completed, so now we "complete" the online request.
+  GoogleServiceAuthError error(
+      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+  LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error);
+  state_.release()->PresetOnlineLoginStatus(result_, failure);
+  ExpectLoginFailure(failure);
+
+  RunResolve(auth_.get(), &message_loop_);
+
+  // After the request below completes, OnLoginSuccess gets called again.
+  failure = LoginFailure::FromNetworkAuthFailure(
+      GoogleServiceAuthError::FromCaptchaChallenge(
+          CaptchaFetcher::GetCaptchaToken(),
+          GURL(CaptchaFetcher::GetCaptchaUrl()),
+          GURL(CaptchaFetcher::GetUnlockUrl())));
+  ExpectLoginFailure(failure);
+
+  MockFactory<CaptchaFetcher> factory;
+  URLFetcher::set_factory(&factory);
+  TestingProfile profile;
+
+  auth_->RetryAuth(&profile,
+                   username_,
+                   std::string(),
+                   std::string(),
+                   std::string());
+  message_loop_.Run();
+}
+
 TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) {
   GaiaAuthConsumer::ClientLoginResult success("sid", "lsid", "", "");
   ExpectLoginSuccess(username_, password_, success, false);
diff --git a/chrome/browser/chromeos/login/password_changed_view.cc b/chrome/browser/chromeos/login/password_changed_view.cc
index 3c3b835..c25ef55 100644
--- a/chrome/browser/chromeos/login/password_changed_view.cc
+++ b/chrome/browser/chromeos/login/password_changed_view.cc
@@ -1,21 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/password_changed_view.h"
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
+#include "chrome/browser/chromeos/login/textfield_with_margin.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/radio_button.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 using views::Button;
@@ -75,7 +76,6 @@
                                                views::View* child) {
   if (is_add && child == this) {
     Init();
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
   }
 }
 
@@ -110,44 +110,45 @@
   delta_sync_radio_->set_listener(this);
   delta_sync_radio_->SetMultiLine(true);
 
-  old_password_field_ = new Textfield(Textfield::STYLE_PASSWORD);
+  old_password_field_ = new TextfieldWithMargin(Textfield::STYLE_PASSWORD);
   old_password_field_->set_text_to_display_when_empty(
       l10n_util::GetStringUTF16(IDS_LOGIN_PREVIOUS_PASSWORD));
   old_password_field_->set_default_width_in_chars(kPasswordFieldWidthChars);
   old_password_field_->SetController(this);
 
   // Define controls layout.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   views::ColumnSet* column_set = layout->AddColumnSet(0);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
   column_set = layout->AddColumnSet(1);
-  column_set->AddPaddingColumn(0, kUnrelatedControlLargeHorizontalSpacing);
+  column_set->AddPaddingColumn(
+      0, views::kUnrelatedControlLargeHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, 0);
   layout->AddView(title_label_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, 0);
   layout->AddView(description_label_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, 0);
   layout->AddView(full_sync_radio_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, 0);
   layout->AddView(delta_sync_radio_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
 
   layout->StartRow(0, 1);
   layout->AddView(
       old_password_field_, 1, 1, GridLayout::LEADING, GridLayout::CENTER);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, 0);
   layout->AddView(old_password_field_);
diff --git a/chrome/browser/chromeos/login/proxy_settings_dialog.cc b/chrome/browser/chromeos/login/proxy_settings_dialog.cc
index 48865b8..1b9ad8f 100644
--- a/chrome/browser/chromeos/login/proxy_settings_dialog.cc
+++ b/chrome/browser/chromeos/login/proxy_settings_dialog.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/chromeos/login/proxy_settings_dialog.h"
 
 #include "chrome/browser/chromeos/login/helper.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 namespace {
 
diff --git a/chrome/browser/chromeos/login/proxy_settings_dialog.h b/chrome/browser/chromeos/login/proxy_settings_dialog.h
index 10d495b..ef9cda4 100644
--- a/chrome/browser/chromeos/login/proxy_settings_dialog.h
+++ b/chrome/browser/chromeos/login/proxy_settings_dialog.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "chrome/browser/chromeos/login/login_html_dialog.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/rounded_rect_painter.cc b/chrome/browser/chromeos/login/rounded_rect_painter.cc
index a4878e5..a5532c8 100644
--- a/chrome/browser/chromeos/login/rounded_rect_painter.cc
+++ b/chrome/browser/chromeos/login/rounded_rect_painter.cc
@@ -5,10 +5,10 @@
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 
 #include "base/logging.h"
-#include "gfx/canvas_skia.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/border.h"
 #include "views/painter.h"
 
diff --git a/chrome/browser/chromeos/login/rounded_view.h b/chrome/browser/chromeos/login/rounded_view.h
index 09877ba..a0b2aa6 100644
--- a/chrome/browser/chromeos/login/rounded_view.h
+++ b/chrome/browser/chromeos/login/rounded_view.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ROUNDED_VIEW_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_ROUNDED_VIEW_H_
 
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/rect.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/rect.h"
 
 namespace chromeos {
 
@@ -35,9 +35,11 @@
   // Empty constructor.
   RoundedView() {}
 
-  // One argument constructor.
+  // Constructors.
   template<typename D>
   explicit RoundedView(const D &value) : C(value) {}
+  template<typename D1, typename D2>
+  RoundedView(const D1& val1, const D2& val2) : C(val1, val2) {}
 
   // Overrides views::View.
   virtual void ProcessPaint(gfx::Canvas* canvas);
diff --git a/chrome/browser/chromeos/login/screen_lock_view.cc b/chrome/browser/chromeos/login/screen_lock_view.cc
index 0e9aa50..0ebcd09 100644
--- a/chrome/browser/chromeos/login/screen_lock_view.cc
+++ b/chrome/browser/chromeos/login/screen_lock_view.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/chromeos/login/screen_lock_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/login/screen_locker.h"
@@ -19,11 +17,13 @@
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/background.h"
 #include "views/border.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 
 namespace chromeos {
 
@@ -117,7 +117,8 @@
   std::wstring text = UTF8ToWide(user.GetDisplayName());
 
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  const gfx::Font& font = rb.GetFont(ResourceBundle::MediumBoldFont);
+  const gfx::Font& font = rb.GetFont(ResourceBundle::MediumBoldFont).DeriveFont(
+      kSelectedUsernameFontDelta);
 
   // Layouts image, textfield and button components.
   GridLayout* layout = new GridLayout(main_);
@@ -187,11 +188,17 @@
   screen_locker_->Signout();
 }
 
+void ScreenLockView::ContentsChanged(views::Textfield* sender,
+                                     const string16& new_contents) {
+  if (!new_contents.empty())
+    screen_locker_->ClearErrors();
+}
+
 bool ScreenLockView::HandleKeyEvent(
     views::Textfield* sender,
     const views::KeyEvent& key_event) {
   screen_locker_->ClearErrors();
-  if (key_event.GetKeyCode() == app::VKEY_RETURN) {
+  if (key_event.key_code() == ui::VKEY_RETURN) {
     screen_locker_->Authenticate(password_field_->text());
     return true;
   }
@@ -211,11 +218,4 @@
   user_view_->SetImage(user->image(), user->image());
 }
 
-void ScreenLockView::ViewHierarchyChanged(bool is_add,
-                                          views::View* parent,
-                                          views::View* child) {
-  if (is_add && this == child)
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screen_lock_view.h b/chrome/browser/chromeos/login/screen_lock_view.h
index d57b30c..34cc46f 100644
--- a/chrome/browser/chromeos/login/screen_lock_view.h
+++ b/chrome/browser/chromeos/login/screen_lock_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -59,18 +59,13 @@
 
   // views::Textfield::Controller implementation:
   virtual void ContentsChanged(views::Textfield* sender,
-                               const string16& new_contents) {}
+                               const string16& new_contents);
   virtual bool HandleKeyEvent(views::Textfield* sender,
                               const views::KeyEvent& keystroke);
 
   // UserView::Delegate implementation:
   virtual void OnSignout();
-
- protected:
-  // views::View implementation:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
+  virtual bool IsUserSelected() const { return true; }
 
  private:
   friend class test::ScreenLockerTester;
diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc
index 09de9ef..de04c8f 100644
--- a/chrome/browser/chromeos/login/screen_locker.cc
+++ b/chrome/browser/chromeos/login/screen_locker.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/screen_locker.h"
 
+#include <gdk/gdkkeysyms.h>
 #include <gdk/gdkx.h>
 #include <string>
 #include <vector>
@@ -12,9 +13,6 @@
 // Evil hack to undo X11 evil #define. See crosbug.com/
 #undef Status
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/x11_util.h"
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/metrics/histogram.h"
@@ -29,6 +27,7 @@
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
 #include "chrome/browser/chromeos/cros/login_library.h"
 #include "chrome/browser/chromeos/cros/screen_lock_library.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "chrome/browser/chromeos/login/authenticator.h"
 #include "chrome/browser/chromeos/login/background_view.h"
@@ -39,6 +38,7 @@
 #include "chrome/browser/chromeos/login/shutdown_button.h"
 #include "chrome/browser/chromeos/system_key_event_listener.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
+#include "chrome/browser/chromeos/view_ids.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sync/profile_sync_service.h"
@@ -49,6 +49,9 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/x/x11_util.h"
 #include "views/screen.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_gtk.h"
@@ -57,7 +60,11 @@
 
 // The maximum duration for which locker should try to grab the keyboard and
 // mouse and its interval for regrabbing on failure.
-const int kMaxGrabFailureSec = 30;
+// This was originally 30 seconds, but is temporarily increaed to 10 min
+// so that a user can report the situation when locker does not kick in.
+// This should be revereted before we moved out from pilot program and it's
+// tracked in crosbug.com/9938.
+const int kMaxGrabFailureSec = 600;
 const int64 kRetryGrabIntervalMs = 500;
 
 // Maximum number of times we'll try to grab the keyboard and mouse before
@@ -116,18 +123,16 @@
         // The LockScreen function is also called when the OS is suspended, and
         // in that case |saved_active_input_method_list_| might be non-empty.
         saved_active_input_method_list_.empty()) {
-      chromeos::InputMethodLibrary* language =
+      chromeos::InputMethodLibrary* library =
           chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
-      chromeos::KeyboardLibrary* keyboard =
-          chromeos::CrosLibrary::Get()->GetKeyboardLibrary();
 
-      saved_previous_input_method_id_ = language->previous_input_method().id;
-      saved_current_input_method_id_ = language->current_input_method().id;
+      saved_previous_input_method_id_ = library->previous_input_method().id;
+      saved_current_input_method_id_ = library->current_input_method().id;
       scoped_ptr<chromeos::InputMethodDescriptors> active_input_method_list(
-          language->GetActiveInputMethods());
+          library->GetActiveInputMethods());
 
-      const std::string hardware_keyboard =
-          keyboard->GetHardwareKeyboardLayoutName();  // e.g. "xkb:us::eng"
+      const std::string hardware_keyboard_id =
+          chromeos::input_method::GetHardwareInputMethodId();
       // We'll add the hardware keyboard if it's not included in
       // |active_input_method_list| so that the user can always use the hardware
       // keyboard on the screen locker.
@@ -143,17 +148,17 @@
         if (!StartsWithASCII(input_method_id, kValidInputMethodPrefix, true))
           continue;
         value.string_list_value.push_back(input_method_id);
-        if (input_method_id == hardware_keyboard) {
+        if (input_method_id == hardware_keyboard_id) {
           should_add_hardware_keyboard = false;
         }
       }
       if (should_add_hardware_keyboard) {
-        value.string_list_value.push_back(hardware_keyboard);
+        value.string_list_value.push_back(hardware_keyboard_id);
       }
       // We don't want to shut down the IME, even if the hardware layout is the
       // only IME left.
-      language->SetEnableAutoImeShutdown(false);
-      language->SetImeConfig(
+      library->SetEnableAutoImeShutdown(false);
+      library->SetImeConfig(
           chromeos::language_prefs::kGeneralSectionName,
           chromeos::language_prefs::kPreloadEnginesConfigName,
           value);
@@ -163,22 +168,22 @@
   void RestoreInputMethods() {
     if (chromeos::CrosLibrary::Get()->EnsureLoaded() &&
         !saved_active_input_method_list_.empty()) {
-      chromeos::InputMethodLibrary* language =
+      chromeos::InputMethodLibrary* library =
           chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
 
       chromeos::ImeConfigValue value;
       value.type = chromeos::ImeConfigValue::kValueTypeStringList;
       value.string_list_value = saved_active_input_method_list_;
-      language->SetEnableAutoImeShutdown(true);
-      language->SetImeConfig(
+      library->SetEnableAutoImeShutdown(true);
+      library->SetImeConfig(
           chromeos::language_prefs::kGeneralSectionName,
           chromeos::language_prefs::kPreloadEnginesConfigName,
           value);
       // Send previous input method id first so Ctrl+space would work fine.
       if (!saved_previous_input_method_id_.empty())
-        language->ChangeInputMethod(saved_previous_input_method_id_);
+        library->ChangeInputMethod(saved_previous_input_method_id_);
       if (!saved_current_input_method_id_.empty())
-        language->ChangeInputMethod(saved_current_input_method_id_);
+        library->ChangeInputMethod(saved_current_input_method_id_);
 
       saved_previous_input_method_id_.clear();
       saved_current_input_method_id_.clear();
@@ -209,12 +214,7 @@
 
   // GTK propagates key events from parents to children.
   // Make sure LockWindow will never handle key events.
-  virtual gboolean OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
-    // Don't handle key event in the lock window.
-    return false;
-  }
-
-  virtual gboolean OnKeyRelease(GtkWidget* widget, GdkEventKey* event) {
+  virtual gboolean OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
     // Don't handle key event in the lock window.
     return false;
   }
@@ -275,7 +275,7 @@
     }
     screen_lock_view_ =  screen_lock_view;
     if (screen_lock_view_) {
-      AddChildView(0, screen_lock_view_);
+      AddChildViewAt(screen_lock_view_, 0);
     }
     Layout();
   }
@@ -297,11 +297,17 @@
         ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
         grab_failure_count_(0),
         kbd_grab_status_(GDK_GRAB_INVALID_TIME),
-        mouse_grab_status_(GDK_GRAB_INVALID_TIME) {
+        mouse_grab_status_(GDK_GRAB_INVALID_TIME),
+        signout_link_(NULL),
+        shutdown_(NULL) {
   }
 
   virtual void Show() {
     views::WidgetGtk::Show();
+    signout_link_ =
+        screen_locker_->GetViewByID(VIEW_ID_SCREEN_LOCKER_SIGNOUT_LINK);
+    shutdown_ = screen_locker_->GetViewByID(VIEW_ID_SCREEN_LOCKER_SHUTDOWN);
+    // These can be null in guest mode.
   }
 
   void ClearGtkGrab() {
@@ -319,6 +325,30 @@
       gtk_grab_remove(current_grab_window);
   }
 
+  virtual gboolean OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
+    views::KeyEvent key_event(reinterpret_cast<GdkEvent*>(event));
+    // This is a hack to workaround the issue crosbug.com/10655 due to
+    // the limitation that a focus manager cannot handle views in
+    // TYPE_CHILD WidgetGtk correctly.
+    if (signout_link_ &&
+        event->type == GDK_KEY_PRESS &&
+        (event->keyval == GDK_Tab ||
+         event->keyval == GDK_ISO_Left_Tab ||
+         event->keyval == GDK_KP_Tab)) {
+      DCHECK(shutdown_);
+      bool reverse = event->state & GDK_SHIFT_MASK;
+      if (reverse && signout_link_->HasFocus()) {
+        shutdown_->RequestFocus();
+        return true;
+      }
+      if (!reverse && shutdown_->HasFocus()) {
+        signout_link_->RequestFocus();
+        return true;
+      }
+    }
+    return views::WidgetGtk::OnKeyEvent(widget, event);
+  }
+
   virtual gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event) {
     WidgetGtk::OnButtonPress(widget, event);
     // Never propagate event to parent.
@@ -354,6 +384,9 @@
   GdkGrabStatus kbd_grab_status_;
   GdkGrabStatus mouse_grab_status_;
 
+  views::View* signout_link_;
+  views::View* shutdown_;
+
   DISALLOW_COPY_AND_ASSIGN(GrabWidget);
 };
 
@@ -405,7 +438,7 @@
     int event_base, error_base;
     int major, minor;
     // Make sure we have XTest extension.
-    DCHECK(XTestQueryExtension(x11_util::GetXDisplay(),
+    DCHECK(XTestQueryExtension(ui::GetXDisplay(),
                                &event_base, &error_base,
                                &major, &minor));
   }
@@ -419,12 +452,12 @@
     // Successfully grabbed the keyboard, but pointer is still
     // grabbed by other client. Another attempt to close supposedly
     // opened menu by emulating keypress at the left top corner.
-    Display* display = x11_util::GetXDisplay();
+    Display* display = ui::GetXDisplay();
     Window root, child;
     int root_x, root_y, win_x, winy;
     unsigned int mask;
     XQueryPointer(display,
-                  x11_util::GetX11WindowFromGtkWidget(window_contents()),
+                  ui::GetX11WindowFromGtkWidget(window_contents()),
                   &root, &child, &root_x, &root_y,
                   &win_x, &winy, &mask);
     XTestFakeMotionEvent(display, -1, -10000, -10000, CurrentTime);
@@ -439,7 +472,7 @@
     // by other client. Another attempt to close supposedly opened
     // menu by emulating escape key.  Such situation must be very
     // rare, but handling this just in case
-    Display* display = x11_util::GetXDisplay();
+    Display* display = ui::GetXDisplay();
     KeyCode escape = XKeysymToKeycode(display, XK_Escape);
     XTestFakeKeyEvent(display, escape, True, CurrentTime);
     XTestFakeKeyEvent(display, escape, False, CurrentTime);
@@ -459,8 +492,8 @@
         screen_lock_view_(screen_lock_view) {
   }
 
-  virtual bool IsScreenLockerMode() const {
-    return true;
+  virtual ScreenMode GetScreenMode() const {
+    return kScreenLockerMode;
   }
 
   virtual void Layout() {
@@ -792,7 +825,7 @@
     ProfileSyncService* service = profile->GetProfileSyncService(username);
     if (service && !service->HasSyncSetupCompleted()) {
       // If sync has failed somehow, try setting the sync passphrase here.
-      service->SetPassphrase(password, false);
+      service->SetPassphrase(password, false, true);
     }
   }
 
@@ -924,6 +957,10 @@
     ScreenLockReady();
 }
 
+views::View* ScreenLocker::GetViewByID(int id) {
+  return lock_widget_->GetRootView()->GetViewByID(id);
+}
+
 // static
 void ScreenLocker::Show() {
   VLOG(1) << "In ScreenLocker::Show";
@@ -994,7 +1031,7 @@
     MessageLoopForUI::current()->RemoveObserver(input_event_observer_.get());
   if (locker_input_event_observer_.get()) {
     lock_widget_->GetFocusManager()->UnregisterAccelerator(
-        views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
+        views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this);
     MessageLoopForUI::current()->RemoveObserver(
         locker_input_event_observer_.get());
   }
@@ -1029,7 +1066,7 @@
 
   if (background_view_->ScreenSaverEnabled()) {
     lock_widget_->GetFocusManager()->RegisterAccelerator(
-        views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
+        views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this);
     locker_input_event_observer_.reset(new LockerInputEventObserver(this));
     MessageLoopForUI::current()->AddObserver(
         locker_input_event_observer_.get());
diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h
index a0332cf..ab401f1 100644
--- a/chrome/browser/chromeos/login/screen_locker.h
+++ b/chrome/browser/chromeos/login/screen_locker.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -115,6 +115,9 @@
     return user_;
   }
 
+  // Returns a view that has given view |id|, or null if it doesn't exist.
+  views::View* GetViewByID(int id);
+
   // Initialize ScreenLocker class. It will listen to
   // LOGIN_USER_CHANGED notification so that the screen locker accepts
   // lock event only after a user is logged in.
diff --git a/chrome/browser/chromeos/login/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/screen_locker_browsertest.cc
index 0b7023b..f89998a 100644
--- a/chrome/browser/chromeos/login/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/screen_locker_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,8 +14,9 @@
 #include "chrome/browser/chromeos/login/screen_locker.h"
 #include "chrome/browser/chromeos/login/screen_locker_tester.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
@@ -135,6 +136,18 @@
     EXPECT_FALSE(tester->IsLocked());
   }
 
+  void LockScreenWithUser(test::ScreenLockerTester* tester,
+                          const std::string& user) {
+    UserManager::Get()->UserLoggedIn(user);
+    ScreenLocker::Show();
+    tester->EmulateWindowManagerReady();
+    if (!tester->IsLocked()) {
+      ui_test_utils::WaitForNotification(
+          NotificationType::SCREEN_LOCK_STATE_CHANGED);
+    }
+    EXPECT_TRUE(tester->IsLocked());
+  }
+
  private:
   virtual void SetUpInProcessBrowserTestFixture() {
     cros_mock_->InitStatusAreaMocks();
@@ -161,8 +174,7 @@
   DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest);
 };
 
-// PulseAudioMixer sometimes crashes at exit. See http://crosbug.om/9303
-IN_PROC_BROWSER_TEST_F(ScreenLockerTest, FLAKY_TestBasic) {
+IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) {
   EXPECT_CALL(*mock_input_method_library_, GetNumActiveInputMethods())
       .Times(1)
       .WillRepeatedly((testing::Return(0)))
@@ -256,7 +268,7 @@
 
 void KeyPress(views::Widget* widget) {
   ui_controls::SendKeyPress(GTK_WINDOW(widget->GetNativeView()),
-                            app::VKEY_SPACE, false, false, false, false);
+                            ui::VKEY_SPACE, false, false, false, false);
 }
 
 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithKeyPress) {
@@ -267,15 +279,11 @@
   EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
       .Times(2)
       .RetiresOnSaturation();
-
-  UserManager::Get()->UserLoggedIn("user");
-  ScreenLocker::Show();
   scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
-  tester->EmulateWindowManagerReady();
-  if (!chromeos::ScreenLocker::GetTester()->IsLocked())
-    ui_test_utils::WaitForNotification(
-        NotificationType::SCREEN_LOCK_STATE_CHANGED);
-  EXPECT_TRUE(tester->IsLocked());
+  LockScreenWithUser(tester.get(), "user");
+
+  // Ensure there's a profile or this test crashes.
+  ProfileManager::GetDefaultProfile();
 
   // Calling Show again simply send LockCompleted signal.
   ScreenLocker::Show();
@@ -287,4 +295,28 @@
   EXPECT_FALSE(tester->IsLocked());
 }
 
+IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestEscape) {
+  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
+      .Times(1)
+      .RetiresOnSaturation();
+  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
+  LockScreenWithUser(tester.get(), "user");
+
+  // Ensure there's a profile or this test crashes.
+  ProfileManager::GetDefaultProfile();
+
+  tester->SetPassword("password");
+  EXPECT_EQ("password", tester->GetPassword());
+  // Escape clears the password.
+  ui_controls::SendKeyPress(GTK_WINDOW(tester->GetWidget()->GetNativeView()),
+                            ui::VKEY_ESCAPE, false, false, false, false);
+  ui_test_utils::RunAllPendingInMessageLoop();
+  EXPECT_EQ("", tester->GetPassword());
+
+  // Close the locker to match expectations.
+  ScreenLocker::Hide();
+  ui_test_utils::RunAllPendingInMessageLoop();
+  EXPECT_FALSE(tester->IsLocked());
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screen_locker_tester.cc b/chrome/browser/chromeos/login/screen_locker_tester.cc
index 387dbe2..209f7db 100644
--- a/chrome/browser/chromeos/login/screen_locker_tester.cc
+++ b/chrome/browser/chromeos/login/screen_locker_tester.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
 #include "views/controls/button/button.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/event.h"
+#include "views/events/event.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_gtk.h"
 
@@ -32,20 +32,30 @@
 }
 
 void ScreenLockerTester::InjectMockAuthenticator(
-    const char* user, const char* password) {
+    const std::string& user, const std::string& password) {
   DCHECK(ScreenLocker::screen_locker_);
   ScreenLocker::screen_locker_->SetAuthenticator(
       new MockAuthenticator(ScreenLocker::screen_locker_, user, password));
 }
 
-void ScreenLockerTester::EnterPassword(const char* password) {
+void ScreenLockerTester::SetPassword(const std::string& password) {
   DCHECK(ScreenLocker::screen_locker_);
   views::Textfield* pass = GetPasswordField();
-  pass->SetText(ASCIIToUTF16(password));
-  GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
+  pass->SetText(ASCIIToUTF16(password.c_str()));
+}
 
+std::string ScreenLockerTester::GetPassword() const {
+  DCHECK(ScreenLocker::screen_locker_);
+  views::Textfield* pass = GetPasswordField();
+  return UTF16ToUTF8(pass->text());
+}
+
+void ScreenLockerTester::EnterPassword(const std::string& password) {
+  SetPassword(password);
+  views::Textfield* pass = GetPasswordField();
+  GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
   event->key.keyval = GDK_Return;
-  views::KeyEvent key_event(&event->key);
+  views::KeyEvent key_event(event);
   ScreenLocker::screen_locker_->screen_lock_view_->HandleKeyEvent(
       pass, key_event);
   gdk_event_free(event);
@@ -56,17 +66,17 @@
   ScreenLocker::screen_locker_->OnWindowManagerReady();
 }
 
-views::Textfield* ScreenLockerTester::GetPasswordField() {
+views::Textfield* ScreenLockerTester::GetPasswordField() const {
   DCHECK(ScreenLocker::screen_locker_);
   return ScreenLocker::screen_locker_->screen_lock_view_->password_field_;
 }
 
-views::Widget* ScreenLockerTester::GetWidget() {
+views::Widget* ScreenLockerTester::GetWidget() const {
   DCHECK(ScreenLocker::screen_locker_);
   return ScreenLocker::screen_locker_->lock_window_;
 }
 
-views::Widget* ScreenLockerTester::GetChildWidget() {
+views::Widget* ScreenLockerTester::GetChildWidget() const {
   DCHECK(ScreenLocker::screen_locker_);
   return ScreenLocker::screen_locker_->lock_widget_;
 }
diff --git a/chrome/browser/chromeos/login/screen_locker_tester.h b/chrome/browser/chromeos/login/screen_locker_tester.h
index bc8800e..dc362fa 100644
--- a/chrome/browser/chromeos/login/screen_locker_tester.h
+++ b/chrome/browser/chromeos/login/screen_locker_tester.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_TESTER_H_
 #pragma once
 
+#include <string>
+
 #include "base/basictypes.h"
 
 namespace views {
@@ -28,25 +30,32 @@
   bool IsLocked();
 
   // Injects MockAuthenticate that uses given |user| and |password|.
-  void InjectMockAuthenticator(const char* user, const char* password);
+  void InjectMockAuthenticator(const std::string& user,
+                               const std::string& password);
+
+  // Sets the password text.
+  void SetPassword(const std::string& password);
+
+  // Gets the password text.
+  std::string GetPassword() const;
 
   // Emulates entring a password.
-  void EnterPassword(const char* password);
+  void EnterPassword(const std::string& password);
 
   // Emulates the ready message from window manager.
   void EmulateWindowManagerReady();
 
   // Returns the widget for screen locker window.
-  views::Widget* GetWidget();
+  views::Widget* GetWidget() const;
 
-  views::Widget* GetChildWidget();
+  views::Widget* GetChildWidget() const;
 
  private:
   friend class chromeos::ScreenLocker;
 
   ScreenLockerTester() {}
 
-  views::Textfield* GetPasswordField();
+  views::Textfield* GetPasswordField() const;
 
   DISALLOW_COPY_AND_ASSIGN(ScreenLockerTester);
 };
diff --git a/chrome/browser/chromeos/login/screen_observer.h b/chrome/browser/chromeos/login/screen_observer.h
index 4cba1bb..d997a7c 100644
--- a/chrome/browser/chromeos/login/screen_observer.h
+++ b/chrome/browser/chromeos/login/screen_observer.h
@@ -20,9 +20,6 @@
   // login wizard decides what is the next view to show. There must be an
   // exit code for each way to exit the screen for each screen.
   enum ExitCodes {
-    LOGIN_SIGN_IN_SELECTED,
-    LOGIN_GUEST_SELECTED,
-    LOGIN_CREATE_ACCOUNT,
     NETWORK_CONNECTED,
     NETWORK_OFFLINE,
     ACCOUNT_CREATE_BACK,
diff --git a/chrome/browser/chromeos/login/shutdown_button.cc b/chrome/browser/chromeos/login/shutdown_button.cc
index 1af583a..693a363 100644
--- a/chrome/browser/chromeos/login/shutdown_button.cc
+++ b/chrome/browser/chromeos/login/shutdown_button.cc
@@ -4,16 +4,16 @@
 
 #include "chrome/browser/chromeos/login/shutdown_button.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/power_library.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/view_ids.h"
-#include "gfx/gtk_util.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
 #include "views/background.h"
 
 namespace {
@@ -25,7 +25,7 @@
 const int kRightPadding = 12;
 
 // Normal/Hover colors.
-const SkColor kShutdownButtonColor = 0xFF242A35;
+const SkColor kShutdownButtonColor = 0xFF303845;
 const SkColor kShutdownHoverColor = 0xFF353E4E;
 
 // Padding inside button.
@@ -72,6 +72,7 @@
   SetIcon(*rb.GetBitmapNamed(IDR_SHUTDOWN_ICON));
   set_icon_text_spacing(kIconTextPadding);
   SetFocusable(true);
+  SetID(VIEW_ID_SCREEN_LOCKER_SHUTDOWN);
   // Set label colors.
   SetEnabledColor(SK_ColorWHITE);
   SetDisabledColor(SK_ColorWHITE);
@@ -96,8 +97,7 @@
 }
 
 void ShutdownButton::LayoutIn(views::View* parent) {
-  // No RTL for now. RTL will be handled in new
-  // domui based Login/Locker.
+  // No RTL for now. RTL will be handled in new WebUI based Login/Locker.
   gfx::Size button_size = GetPreferredSize();
   SetBounds(
       parent->width() - button_size.width()- kRightPadding,
@@ -108,14 +108,14 @@
 
 void ShutdownButton::OnLocaleChanged() {
   SetText(UTF8ToWide(l10n_util::GetStringUTF8(IDS_SHUTDOWN_BUTTON)));
-  if (GetParent()) {
-    GetParent()->Layout();
-    GetParent()->SchedulePaint();
+  if (parent()) {
+    parent()->Layout();
+    parent()->SchedulePaint();
   }
 }
 
 gfx::NativeCursor ShutdownButton::GetCursorForPoint(
-    views::Event::EventType event_type,
+    ui::EventType event_type,
     const gfx::Point& p) {
   if (!IsEnabled()) {
     return NULL;
diff --git a/chrome/browser/chromeos/login/shutdown_button.h b/chrome/browser/chromeos/login/shutdown_button.h
index dd0a65a..15cb2ad 100644
--- a/chrome/browser/chromeos/login/shutdown_button.h
+++ b/chrome/browser/chromeos/login/shutdown_button.h
@@ -26,7 +26,7 @@
   // views::View overrides.
   virtual void OnLocaleChanged();
   virtual gfx::NativeCursor GetCursorForPoint(
-      views::Event::EventType event_type,
+      ui::EventType event_type,
       const gfx::Point& p);
 
   // views::ButtonListener implementation.
diff --git a/chrome/browser/chromeos/login/signed_settings.cc b/chrome/browser/chromeos/login/signed_settings.cc
index 58bce4b..074d4ad 100644
--- a/chrome/browser/chromeos/login/signed_settings.cc
+++ b/chrome/browser/chromeos/login/signed_settings.cc
@@ -9,6 +9,7 @@
 
 #include "base/ref_counted.h"
 #include "base/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
@@ -241,7 +242,14 @@
 StorePropertyOp::~StorePropertyOp() {}
 
 void StorePropertyOp::Execute() {
-  if (!service_->IsAlreadyOwned()) {
+  bool is_owned = false;
+  {
+    // This should not do blocking IO from the UI thread.
+    // Temporarily allow it for now. http://crbug.com/70097
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    is_owned = service_->IsAlreadyOwned();
+  }
+  if (!is_owned) {
     if (g_browser_process &&
         g_browser_process->local_state() &&
         SignedSettingsTempStorage::Store(name_, value_,
@@ -305,7 +313,14 @@
   // device has been owned and before temp_storage settings are finally
   // persisted into signed settings.
   // In this lapse of time Retrieve loses access to those settings.
-  if (!service_->IsAlreadyOwned()) {
+  bool is_owned = false;
+  {
+    // This should not do blocking IO from the UI thread.
+    // Temporarily allow it for now. http://crbug.com/70097
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    is_owned = service_->IsAlreadyOwned();
+  }
+  if (!is_owned) {
     if (g_browser_process &&
         g_browser_process->local_state() &&
         SignedSettingsTempStorage::Retrieve(
diff --git a/chrome/browser/chromeos/login/textfield_with_margin.cc b/chrome/browser/chromeos/login/textfield_with_margin.cc
index 44d3432..eb75416 100644
--- a/chrome/browser/chromeos/login/textfield_with_margin.cc
+++ b/chrome/browser/chromeos/login/textfield_with_margin.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/login/textfield_with_margin.h"
 
 #include "chrome/browser/chromeos/login/helper.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
 namespace {
 
@@ -34,4 +35,12 @@
   views::Textfield::Layout();
 }
 
+bool TextfieldWithMargin::OnKeyPressed(const views::KeyEvent& e) {
+  if (e.key_code() == ui::VKEY_ESCAPE && !text().empty()) {
+    SetText(string16());
+    return true;
+  }
+  return false;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/textfield_with_margin.h b/chrome/browser/chromeos/login/textfield_with_margin.h
index 1bf3e54..9655f27 100644
--- a/chrome/browser/chromeos/login/textfield_with_margin.h
+++ b/chrome/browser/chromeos/login/textfield_with_margin.h
@@ -20,6 +20,7 @@
  protected:
   // Overridden from views::View:
   virtual void Layout();
+  virtual bool OnKeyPressed(const views::KeyEvent& e);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TextfieldWithMargin);
diff --git a/chrome/browser/chromeos/login/update_screen.cc b/chrome/browser/chromeos/login/update_screen.cc
index 2eb9b14..e39345c 100644
--- a/chrome/browser/chromeos/login/update_screen.cc
+++ b/chrome/browser/chromeos/login/update_screen.cc
@@ -6,6 +6,7 @@
 
 #include "base/file_util.h"
 #include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/login/screen_observer.h"
 #include "chrome/browser/chromeos/login/update_view.h"
@@ -65,11 +66,12 @@
       // check unless there is an update.
       break;
     case UPDATE_STATUS_UPDATE_AVAILABLE:
+      MakeSureScreenIsShown();
       view()->SetProgress(kBeforeDownloadProgress);
       if (!HasCriticalUpdate()) {
         LOG(INFO) << "Noncritical update available: "
                   << library->status().new_version;
-        ExitUpdate(false);
+        ExitUpdate(REASON_UPDATE_NON_CRITICAL);
       } else {
         LOG(INFO) << "Critical update available: "
                   << library->status().new_version;
@@ -77,6 +79,7 @@
       break;
     case UPDATE_STATUS_DOWNLOADING:
       {
+        MakeSureScreenIsShown();
         if (!is_downloading_update_) {
           // Because update engine doesn't send UPDATE_STATUS_UPDATE_AVAILABLE
           // we need to is update critical on first downloading notification.
@@ -84,7 +87,7 @@
           if (!HasCriticalUpdate()) {
             LOG(INFO) << "Non-critical update available: "
                       << library->status().new_version;
-            ExitUpdate(false);
+            ExitUpdate(REASON_UPDATE_NON_CRITICAL);
           } else {
             LOG(INFO) << "Critical update available: "
                       << library->status().new_version;
@@ -97,12 +100,15 @@
       }
       break;
     case UPDATE_STATUS_VERIFYING:
+      MakeSureScreenIsShown();
       view()->SetProgress(kBeforeVerifyingProgress);
       break;
     case UPDATE_STATUS_FINALIZING:
+      MakeSureScreenIsShown();
       view()->SetProgress(kBeforeFinalizingProgress);
       break;
     case UPDATE_STATUS_UPDATED_NEED_REBOOT:
+      MakeSureScreenIsShown();
       // Make sure that first OOBE stage won't be shown after reboot.
       WizardController::MarkOobeCompleted();
       view()->SetProgress(kProgressComplete);
@@ -114,13 +120,13 @@
                             this,
                             &UpdateScreen::OnWaitForRebootTimeElapsed);
       } else {
-        ExitUpdate(false);
+        ExitUpdate(REASON_UPDATE_NON_CRITICAL);
       }
       break;
     case UPDATE_STATUS_IDLE:
     case UPDATE_STATUS_ERROR:
     case UPDATE_STATUS_REPORTING_ERROR_EVENT:
-      ExitUpdate(false);
+      ExitUpdate(REASON_UPDATE_ENDED);
       break;
     default:
       NOTREACHED();
@@ -129,19 +135,22 @@
 }
 
 void UpdateScreen::StartUpdate() {
-  // Reset view.
-  view()->Reset();
-  view()->set_controller(this);
-  is_downloading_update_ = false;
-  view()->SetProgress(kBeforeUpdateCheckProgress);
+  // Reset view if view was created.
+  if (view()) {
+    view()->Reset();
+    view()->set_controller(this);
+    is_downloading_update_ = false;
+    view()->SetProgress(kBeforeUpdateCheckProgress);
+  }
 
   if (!CrosLibrary::Get()->EnsureLoaded()) {
     LOG(ERROR) << "Error loading CrosLibrary";
+    ExitUpdate(REASON_UPDATE_INIT_FAILED);
   } else {
     CrosLibrary::Get()->GetUpdateLibrary()->AddObserver(this);
     VLOG(1) << "Initiate update check";
     if (!CrosLibrary::Get()->GetUpdateLibrary()->CheckForUpdate()) {
-      ExitUpdate(true);
+      ExitUpdate(REASON_UPDATE_INIT_FAILED);
     }
   }
 }
@@ -150,41 +159,54 @@
   // Screen has longer lifetime than it's view.
   // View is deleted after wizard proceeds to the next screen.
   if (view())
-    ExitUpdate(true);
+    ExitUpdate(REASON_UPDATE_CANCELED);
 }
 
-void UpdateScreen::ExitUpdate(bool forced) {
+void UpdateScreen::Show() {
+  DefaultViewScreen<UpdateView>::Show();
+  view()->set_controller(this);
+  is_downloading_update_ = false;
+  view()->SetProgress(kBeforeUpdateCheckProgress);
+}
+
+void UpdateScreen::ExitUpdate(UpdateScreen::ExitReason reason) {
   ScreenObserver* observer = delegate()->GetObserver(this);
+  if (CrosLibrary::Get()->EnsureLoaded())
+    CrosLibrary::Get()->GetUpdateLibrary()->RemoveObserver(this);
 
-  if (!CrosLibrary::Get()->EnsureLoaded()) {
-    observer->OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE);
-    return;
-  }
-
-  if (forced) {
-    observer->OnExit(ScreenObserver::UPDATE_NOUPDATE);
-    return;
-  }
-
-  UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
-  update_library->RemoveObserver(this);
-  switch (update_library->status().status) {
-    case UPDATE_STATUS_UPDATE_AVAILABLE:
-    case UPDATE_STATUS_UPDATED_NEED_REBOOT:
-    case UPDATE_STATUS_DOWNLOADING:
-    case UPDATE_STATUS_FINALIZING:
-    case UPDATE_STATUS_VERIFYING:
-      DCHECK(!HasCriticalUpdate());
-      // Noncritical update, just exit screen as if there is no update.
-      // no break
-    case UPDATE_STATUS_IDLE:
+  switch(reason) {
+    case REASON_UPDATE_CANCELED:
       observer->OnExit(ScreenObserver::UPDATE_NOUPDATE);
       break;
-    case UPDATE_STATUS_ERROR:
-    case UPDATE_STATUS_REPORTING_ERROR_EVENT:
-      observer->OnExit(checking_for_update_ ?
-          ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE :
-          ScreenObserver::UPDATE_ERROR_UPDATING);
+    case REASON_UPDATE_INIT_FAILED:
+      observer->OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE);
+      break;
+    case REASON_UPDATE_NON_CRITICAL:
+    case REASON_UPDATE_ENDED:
+      {
+        UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
+        switch (update_library->status().status) {
+          case UPDATE_STATUS_UPDATE_AVAILABLE:
+          case UPDATE_STATUS_UPDATED_NEED_REBOOT:
+          case UPDATE_STATUS_DOWNLOADING:
+          case UPDATE_STATUS_FINALIZING:
+          case UPDATE_STATUS_VERIFYING:
+            DCHECK(!HasCriticalUpdate());
+            // Noncritical update, just exit screen as if there is no update.
+            // no break
+          case UPDATE_STATUS_IDLE:
+            observer->OnExit(ScreenObserver::UPDATE_NOUPDATE);
+            break;
+          case UPDATE_STATUS_ERROR:
+          case UPDATE_STATUS_REPORTING_ERROR_EVENT:
+            observer->OnExit(checking_for_update_ ?
+                ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE :
+                ScreenObserver::UPDATE_ERROR_UPDATING);
+            break;
+          default:
+            NOTREACHED();
+        }
+      }
       break;
     default:
       NOTREACHED();
@@ -193,9 +215,16 @@
 
 void UpdateScreen::OnWaitForRebootTimeElapsed() {
   LOG(ERROR) << "Unable to reboot - asking user for a manual reboot.";
+  MakeSureScreenIsShown();
   view()->ShowManualRebootInfo();
 }
 
+void UpdateScreen::MakeSureScreenIsShown() {
+  if (!view()) {
+    delegate()->ShowCurrentScreen();
+  }
+}
+
 void UpdateScreen::SetRebootCheckDelay(int seconds) {
   if (seconds <= 0)
     reboot_timer_.Stop();
@@ -208,6 +237,9 @@
     return true;
 
   std::string deadline;
+  // Checking for update flag file causes us to do blocking IO on UI thread.
+  // Temporarily allow it until we fix http://crosbug.com/11106
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   FilePath update_deadline_file_path(kUpdateDeadlineFile);
   if (!file_util::ReadFileToString(update_deadline_file_path, &deadline) ||
       deadline.empty()) {
diff --git a/chrome/browser/chromeos/login/update_screen.h b/chrome/browser/chromeos/login/update_screen.h
index 2e6e657..2fd9864 100644
--- a/chrome/browser/chromeos/login/update_screen.h
+++ b/chrome/browser/chromeos/login/update_screen.h
@@ -35,11 +35,18 @@
   virtual void StartUpdate();
   virtual void CancelUpdate();
 
+  // Overridden from ViewScreen.
+  virtual void Show();
+
+  enum ExitReason {
+     REASON_UPDATE_CANCELED,
+     REASON_UPDATE_INIT_FAILED,
+     REASON_UPDATE_NON_CRITICAL,
+     REASON_UPDATE_ENDED
+  };
+
   // Reports update results to the ScreenObserver.
-  // |forced| should be set to true when calling this method and update status
-  // is not one of UPDATE_STATUS_IDLE, UPDATE_STATUS_ERROR,
-  // UPDATE_STATUS_REPORTING_ERROR_EVENT.
-  virtual void ExitUpdate(bool forced);
+  virtual void ExitUpdate(ExitReason reason);
 
   // Reboot check delay get/set, in seconds.
   int reboot_check_delay() const { return reboot_check_delay_; }
@@ -57,6 +64,9 @@
   // Timer notification handlers.
   void OnWaitForRebootTimeElapsed();
 
+  // Checks that screen is shown, shows if not.
+  void MakeSureScreenIsShown();
+
   // Timer for the interval to wait for the reboot.
   // If reboot didn't happen - ask user to reboot manually.
   base::OneShotTimer<UpdateScreen> reboot_timer_;
diff --git a/chrome/browser/chromeos/login/update_screen_browsertest.cc b/chrome/browser/chromeos/login/update_screen_browsertest.cc
index 02f4eb9..5fa4eb1 100644
--- a/chrome/browser/chromeos/login/update_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/update_screen_browsertest.cc
@@ -164,8 +164,8 @@
 
   controller()->set_observer(NULL);
 }
-// TODO(zelidrag): bug chromium-os:7140 Fix this flaky test on ChromeOS.
-IN_PROC_BROWSER_TEST_F(UpdateScreenTest, FLAKY_TestErrorIssuingUpdateCheck) {
+
+IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorIssuingUpdateCheck) {
   ASSERT_TRUE(controller() != NULL);
   scoped_ptr<MockScreenObserver> mock_screen_observer(new MockScreenObserver());
   controller()->set_observer(mock_screen_observer.get());
@@ -173,12 +173,10 @@
   ASSERT_TRUE(update_screen != NULL);
   ASSERT_EQ(controller()->current_screen(), update_screen);
 
-  UpdateLibrary::Status status;
-
   // First, cancel the update that is already in progress.
-  EXPECT_CALL(*mock_update_library_, status())
-      .Times(AtLeast(1))
-      .WillRepeatedly(ReturnRef(status));
+  EXPECT_CALL(*mock_screen_observer,
+              OnExit(ScreenObserver::UPDATE_NOUPDATE))
+      .Times(1);
   update_screen->CancelUpdate();
 
   // Run UpdateScreen::StartUpdate() again, but CheckForUpdate() will fail
@@ -190,11 +188,6 @@
   EXPECT_CALL(*mock_update_library_, CheckForUpdate())
       .Times(1)
       .WillOnce(Return(false));
-
-  status.status = UPDATE_STATUS_ERROR;
-  EXPECT_CALL(*mock_update_library_, status())
-      .Times(AtLeast(1))
-      .WillRepeatedly(ReturnRef(status));
   EXPECT_CALL(*mock_screen_observer,
               OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE))
       .Times(1);
diff --git a/chrome/browser/chromeos/login/update_view.cc b/chrome/browser/chromeos/login/update_view.cc
index 7a56be2..100ccfd 100644
--- a/chrome/browser/chromeos/login/update_view.cc
+++ b/chrome/browser/chromeos/login/update_view.cc
@@ -6,8 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
@@ -15,6 +13,8 @@
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/border.h"
 #include "views/controls/label.h"
 #include "views/controls/progress_bar.h"
@@ -196,11 +196,6 @@
   SchedulePaint();
 }
 
-void UpdateView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
-  if (is_add && this == child)
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-}
-
 void UpdateView::InitLabel(views::Label** label) {
   *label = new views::Label();
   (*label)->SetColor(kLabelColor);
diff --git a/chrome/browser/chromeos/login/update_view.h b/chrome/browser/chromeos/login/update_view.h
index 0a4b790..f52d3e1 100644
--- a/chrome/browser/chromeos/login/update_view.h
+++ b/chrome/browser/chromeos/login/update_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -51,12 +51,6 @@
   // views::View implementation:
   virtual void Layout();
 
- protected:
-  // views::View implementation:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
-
  private:
   // Creates Label control and adds it as a child.
   void InitLabel(views::Label** label);
diff --git a/chrome/browser/chromeos/login/user_controller.cc b/chrome/browser/chromeos/login/user_controller.cc
index d5d14dd..253100c 100644
--- a/chrome/browser/chromeos/login/user_controller.cc
+++ b/chrome/browser/chromeos/login/user_controller.cc
@@ -7,9 +7,6 @@
 #include <algorithm>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
 #include "chrome/browser/chromeos/login/existing_user_view.h"
@@ -19,17 +16,17 @@
 #include "chrome/browser/chromeos/login/user_view.h"
 #include "chrome/browser/chromeos/login/username_view.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "third_party/cros/chromeos_wm_ipc_enums.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/painter.h"
 #include "views/screen.h"
 #include "views/widget/root_view.h"
@@ -57,6 +54,27 @@
 // Vertical interval between the image and the textfield.
 const int kVerticalIntervalSize = 10;
 
+// A window for controls that sets focus to the view when
+// it first got focus.
+class ControlsWindow : public WidgetGtk {
+ public:
+  explicit ControlsWindow(views::View* initial_focus_view)
+      : WidgetGtk(WidgetGtk::TYPE_WINDOW),
+        initial_focus_view_(initial_focus_view) {
+  }
+
+ private:
+  // WidgetGtk overrrides:
+  virtual void SetInitialFocus() {
+    if (initial_focus_view_)
+      initial_focus_view_->RequestFocus();
+  }
+
+  views::View* initial_focus_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(ControlsWindow);
+};
+
 // Widget that notifies window manager about clicking on itself.
 // Doesn't send anything if user is selected.
 class ClickNotifyingWidget : public views::WidgetGtk {
@@ -69,7 +87,7 @@
 
  private:
   gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event) {
-    if (!controller_->is_user_selected())
+    if (!controller_->IsUserSelected())
       controller_->SelectUserRelative(0);
 
     return views::WidgetGtk::OnButtonPress(widget, event);
@@ -89,9 +107,7 @@
 
 }  // namespace
 
-using login::kBackgroundColor;
 using login::kBorderSize;
-using login::kTextColor;
 using login::kUserImageSize;
 
 // static
@@ -101,6 +117,9 @@
 const int UserController::kUnselectedSize = 100;
 const int UserController::kNewUserUnselectedSize = 42;
 
+////////////////////////////////////////////////////////////////////////////////
+// UserController, public:
+
 UserController::UserController(Delegate* delegate, bool is_guest)
     : user_index_(-1),
       is_user_selected_(false),
@@ -118,12 +137,7 @@
       label_view_(NULL),
       unselected_label_view_(NULL),
       user_input_(NULL),
-      throbber_host_(NULL),
-      method_factory_(this) {
-  registrar_.Add(
-      this,
-      NotificationType::LOGIN_USER_IMAGE_CHANGED,
-      NotificationService::AllSources());
+      throbber_host_(NULL) {
 }
 
 UserController::UserController(Delegate* delegate,
@@ -147,13 +161,8 @@
       label_view_(NULL),
       unselected_label_view_(NULL),
       user_input_(NULL),
-      throbber_host_(NULL),
-      method_factory_(this) {
+      throbber_host_(NULL) {
   DCHECK(!user.email().empty());
-  registrar_.Add(
-      this,
-      NotificationType::LOGIN_USER_IMAGE_CHANGED,
-      NotificationService::AllSources());
 }
 
 UserController::~UserController() {
@@ -182,55 +191,20 @@
       CreateLabelWindow(index, WM_IPC_WINDOW_LOGIN_UNSELECTED_LABEL);
 }
 
-void UserController::StartThrobber() {
-  throbber_host_->StartThrobber();
-}
-
-void UserController::StopThrobber() {
-  throbber_host_->StopThrobber();
-}
-
-std::wstring UserController::GetNameTooltip() const {
-  if (is_new_user_)
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_ADD_USER));
-  if (is_guest_)
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
-
-  // Tooltip contains user's display name and his email domain to distinguish
-  // this user from the other one with the same display name.
-  const std::string& email = user_.email();
-  size_t at_pos = email.rfind('@');
-  if (at_pos == std::string::npos) {
-    NOTREACHED();
-    return std::wstring();
-  }
-  size_t domain_start = at_pos + 1;
-  std::string domain = email.substr(domain_start,
-                                    email.length() - domain_start);
-  return UTF8ToWide(base::StringPrintf("%s (%s)",
-                                       user_.GetDisplayName().c_str(),
-                                       domain.c_str()));
-}
-
 void UserController::ClearAndEnableFields() {
   user_input_->ClearAndFocusControls();
   user_input_->EnableInputControls(true);
-  SetStatusAreaEnabled(true);
   StopThrobber();
 }
 
 void UserController::ClearAndEnablePassword() {
   user_input_->ClearAndFocusPassword();
   user_input_->EnableInputControls(true);
-  SetStatusAreaEnabled(true);
   StopThrobber();
 }
 
-gfx::Rect UserController::GetMainInputScreenBounds() const {
-  return user_input_->GetMainInputScreenBounds();
-}
-
 void UserController::EnableNameTooltip(bool enable) {
+  name_tooltip_enabled_ = enable;
   std::wstring tooltip_text;
   if (enable)
     tooltip_text = GetNameTooltip();
@@ -243,22 +217,48 @@
     unselected_label_view_->SetTooltipText(tooltip_text);
 }
 
-void UserController::Observe(
-    NotificationType type,
-    const NotificationSource& source,
-    const NotificationDetails& details) {
-  if (type != NotificationType::LOGIN_USER_IMAGE_CHANGED ||
-      !user_view_)
-    return;
-
-  UserManager::User* user = Details<UserManager::User>(details).ptr();
-  if (user_.email() != user->email())
-    return;
-
-  user_.set_image(user->image());
-  user_view_->SetImage(user_.image(), user_.image());
+gfx::Rect UserController::GetMainInputScreenBounds() const {
+  return user_input_->GetMainInputScreenBounds();
 }
 
+void UserController::OnUserImageChanged(UserManager::User* user) {
+  if (user_.email() != user->email())
+    return;
+  user_.set_image(user->image());
+  // Controller might exist without windows,
+  // i.e. if user pod doesn't fit on the screen.
+  if (user_view_)
+    user_view_->SetImage(user_.image(), user_.image());
+}
+
+void UserController::SelectUserRelative(int shift) {
+  delegate_->SelectUser(user_index() + shift);
+}
+
+void UserController::StartThrobber() {
+  throbber_host_->StartThrobber();
+}
+
+void UserController::StopThrobber() {
+  throbber_host_->StopThrobber();
+}
+
+void UserController::UpdateUserCount(int index, int total_user_count) {
+  user_index_ = index;
+  std::vector<int> params;
+  params.push_back(index);
+  params.push_back(total_user_count);
+  params.push_back(is_new_user_ ? kNewUserUnselectedSize : kUnselectedSize);
+  params.push_back(kPadding);
+  WmIpc::instance()->SetWindowType(
+      border_window_->GetNativeView(),
+      WM_IPC_WINDOW_LOGIN_BORDER,
+      &params);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// UserController, WidgetDelegate implementation:
+//
 void UserController::IsActiveChanged(bool active) {
   is_user_selected_ = active;
   if (active) {
@@ -271,6 +271,60 @@
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// UserController, NewUserView::Delegate implementation:
+//
+void UserController::OnLogin(const std::string& username,
+                             const std::string& password) {
+  if (is_new_user_)
+    user_.set_email(username);
+
+  user_input_->EnableInputControls(false);
+  StartThrobber();
+
+  delegate_->Login(this, UTF8ToUTF16(password));
+}
+
+void UserController::OnCreateAccount() {
+  user_input_->EnableInputControls(false);
+  StartThrobber();
+
+  delegate_->CreateAccount();
+}
+
+void UserController::OnLoginAsGuest() {
+  user_input_->EnableInputControls(false);
+  StartThrobber();
+
+  delegate_->LoginAsGuest();
+}
+
+void UserController::ClearErrors() {
+  delegate_->ClearErrors();
+}
+
+void UserController::NavigateAway() {
+  SelectUserRelative(-1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// UserController, UserView::Delegate implementation:
+//
+void UserController::OnLocaleChanged() {
+  // Update text tooltips on guest and new user pods.
+  if (is_guest_ || is_new_user_) {
+    if (name_tooltip_enabled_)
+      EnableNameTooltip(name_tooltip_enabled_);
+  }
+}
+
+void UserController::OnRemoveUser() {
+  delegate_->RemoveUser(this);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// UserController, private:
+//
 void UserController::ConfigureLoginWindow(WidgetGtk* window,
                                           int index,
                                           const gfx::Rect& bounds,
@@ -328,7 +382,7 @@
     *height = size.height();
   }
 
-  WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
+  WidgetGtk* window = new ControlsWindow(control_view);
   ConfigureLoginWindow(window,
                        index,
                        gfx::Rect(*width, *height),
@@ -393,29 +447,11 @@
   border_window_->Show();
 }
 
-void UserController::UpdateUserCount(int index, int total_user_count) {
-  user_index_ = index;
-  std::vector<int> params;
-  params.push_back(index);
-  params.push_back(total_user_count);
-  params.push_back(is_new_user_ ? kNewUserUnselectedSize : kUnselectedSize);
-  params.push_back(kPadding);
-  WmIpc::instance()->SetWindowType(
-      border_window_->GetNativeView(),
-      WM_IPC_WINDOW_LOGIN_BORDER,
-      &params);
-}
-
 WidgetGtk* UserController::CreateLabelWindow(int index,
                                              WmIpcWindowType type) {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  const gfx::Font& font = (type == WM_IPC_WINDOW_LOGIN_LABEL) ?
-      rb.GetFont(ResourceBundle::MediumBoldFont) :
-      rb.GetFont(ResourceBundle::BaseFont).DeriveFont(
-          kUnselectedUsernameFontDelta, gfx::Font::BOLD);
   std::wstring text;
   if (is_guest_) {
-    text = UTF16ToWide(l10n_util::GetStringUTF16(IDS_GUEST));
+    text = std::wstring();
   } else if (is_new_user_) {
     // Add user should have label only in activated state.
     // When new user is the only, label is not needed.
@@ -425,7 +461,7 @@
     text = UTF8ToWide(user_.GetDisplayName());
   }
 
-  views::Label *label = NULL;
+  views::Label* label = NULL;
 
   if (is_new_user_) {
     label = new views::Label(text);
@@ -437,8 +473,14 @@
     label = UsernameView::CreateShapedUsernameView(text, true);
   }
 
-  label->SetColor(kTextColor);
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  const gfx::Font& font = (type == WM_IPC_WINDOW_LOGIN_LABEL) ?
+      rb.GetFont(ResourceBundle::MediumBoldFont).DeriveFont(
+          kSelectedUsernameFontDelta) :
+      rb.GetFont(ResourceBundle::BaseFont).DeriveFont(
+          kUnselectedUsernameFontDelta, gfx::Font::BOLD);
   label->SetFont(font);
+  label->SetColor(login::kTextColor);
 
   if (type == WM_IPC_WINDOW_LOGIN_LABEL)
     label_view_ = label;
@@ -462,57 +504,13 @@
   return window;
 }
 
-void UserController::OnLogin(const std::string& username,
-                             const std::string& password) {
+std::wstring UserController::GetNameTooltip() const {
   if (is_new_user_)
-    user_.set_email(username);
-
-  user_input_->EnableInputControls(false);
-  SetStatusAreaEnabled(false);
-  StartThrobber();
-
-  delegate_->Login(this, UTF8ToUTF16(password));
-}
-
-void UserController::OnCreateAccount() {
-  delegate_->ActivateWizard(WizardController::kAccountScreenName);
-}
-
-void UserController::OnLoginOffTheRecord() {
-  user_input_->EnableInputControls(false);
-  SetStatusAreaEnabled(false);
-  StartThrobber();
-
-  delegate_->LoginOffTheRecord();
-}
-
-void UserController::ClearErrors() {
-  delegate_->ClearErrors();
-}
-
-void UserController::NavigateAway() {
-  SelectUserRelative(-1);
-}
-
-void UserController::OnRemoveUser() {
-  // Must not proceed without signature verification.
-  UserCrosSettingsProvider user_settings;
-  bool trusted_owner_available = user_settings.RequestTrustedOwner(
-      method_factory_.NewRunnableMethod(&UserController::OnRemoveUser));
-  if (!trusted_owner_available) {
-    // Value of owner email is still not verified.
-    // Another attempt will be invoked after verification completion.
-    return;
-  }
-  if (user().email() == UserCrosSettingsProvider::cached_owner()) {
-    // Owner is not allowed to be removed from the device.
-    return;
-  }
-  delegate_->RemoveUser(this);
-}
-
-void UserController::SelectUserRelative(int shift) {
-  delegate_->SelectUser(user_index() + shift);
+    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_ADD_USER));
+  else if (is_guest_)
+    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
+  else
+    return UTF8ToWide(user_.GetNameTooltip());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_controller.h b/chrome/browser/chromeos/login/user_controller.h
index 7b894f1..bab0971 100644
--- a/chrome/browser/chromeos/login/user_controller.h
+++ b/chrome/browser/chromeos/login/user_controller.h
@@ -14,8 +14,6 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/user_view.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
 #include "views/controls/button/button.h"
 #include "views/controls/textfield/textfield.h"
@@ -33,20 +31,17 @@
 // the nececessary set of UserControllers.
 class UserController : public views::WidgetDelegate,
                        public NewUserView::Delegate,
-                       public NotificationObserver,
                        public UserView::Delegate {
  public:
   class Delegate {
    public:
+    virtual void CreateAccount() = 0;
     virtual void Login(UserController* source,
                        const string16& password) = 0;
-    virtual void LoginOffTheRecord() = 0;
+    virtual void LoginAsGuest() = 0;
     virtual void ClearErrors() = 0;
     virtual void OnUserSelected(UserController* source) = 0;
-    virtual void ActivateWizard(const std::string& screen_name) = 0;
     virtual void RemoveUser(UserController* source) = 0;
-    virtual void AddStartUrl(const GURL& start_url) = 0;
-    virtual void SetStatusAreaEnabled(bool enable) = 0;
 
     // Selects user entry with specified |index|.
     // Does nothing if current user is already selected.
@@ -68,19 +63,17 @@
   // number of users.
   void Init(int index, int total_user_count, bool need_browse_without_signin);
 
-  // Update border window parameters to notify window manager about new numbers.
-  // |index| of this user and |total_user_count| of users.
-  void UpdateUserCount(int index, int total_user_count);
-
   int user_index() const { return user_index_; }
-  bool is_user_selected() const { return is_user_selected_; }
   bool is_new_user() const { return is_new_user_; }
   bool is_guest() const { return is_guest_; }
+  bool is_owner() const { return is_owner_; }
 
   const UserManager::User& user() const { return user_; }
 
-  // Enables or disables tooltip with user's email.
-  void EnableNameTooltip(bool enable);
+  // Get widget that contains all controls.
+  views::WidgetGtk* controls_window() {
+    return controls_window_;
+  }
 
   // Called when user view is activated (OnUserSelected).
   void ClearAndEnableFields();
@@ -88,46 +81,44 @@
   // Called when user view is activated (OnUserSelected).
   void ClearAndEnablePassword();
 
-  // Get widget that contains all controls.
-  views::WidgetGtk* controls_window() {
-    return controls_window_;
-  }
+  // Enables or disables tooltip with user's email.
+  void EnableNameTooltip(bool enable);
+
+  // Called when user image has been changed.
+  void OnUserImageChanged(UserManager::User* user);
 
   // Returns bounds of the main input field in the screen coordinates (e.g.
   // these bounds could be used to choose positions for the error bubble).
   gfx::Rect GetMainInputScreenBounds() const;
 
+  // Selects user relative to the current user.
+  void SelectUserRelative(int shift);
+
   // Starts/Stops throbber.
   void StartThrobber();
   void StopThrobber();
 
-  // views::WidgetDelegate:
+  // Update border window parameters to notify window manager about new numbers.
+  // |index| of this user and |total_user_count| of users.
+  void UpdateUserCount(int index, int total_user_count);
+
+  // views::WidgetDelegate implementation:
   virtual void IsActiveChanged(bool active);
 
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // NewUserView::Delegate
+  // NewUserView::Delegate implementation:
   virtual void OnLogin(const std::string& username,
                        const std::string& password);
+  virtual void OnLoginAsGuest();
   virtual void OnCreateAccount();
-  virtual void OnLoginOffTheRecord();
-  virtual void AddStartUrl(const GURL& start_url) {
-    delegate_->AddStartUrl(start_url);
-  }
   virtual void ClearErrors();
   virtual void NavigateAway();
-  virtual void SetStatusAreaEnabled(bool enable) {
-    delegate_->SetStatusAreaEnabled(enable);
-  }
 
   // UserView::Delegate implementation:
   virtual void OnRemoveUser();
+  virtual bool IsUserSelected() const { return is_user_selected_; }
 
-  // Selects user relative to the current user.
-  void SelectUserRelative(int shift);
+  // UsernameView::Delegate implementation:
+  virtual void OnLocaleChanged();
 
   // Padding between the user windows.
   static const int kPadding;
@@ -154,12 +145,6 @@
                           int total_user_count,
                           int controls_width, int controls_height);
 
-  // Sets specified image on the image window. If image's size is less than
-  // 75% of window size, image size is preserved to avoid blur. Otherwise,
-  // the image is resized to fit window size precisely. Image view repaints
-  // itself.
-  void SetImage(const SkBitmap& image);
-
   // Returns tooltip text for user name.
   std::wstring GetNameTooltip() const;
 
@@ -207,9 +192,8 @@
   // Throbber host that can show a throbber.
   ThrobberHostView* throbber_host_;
 
-  NotificationRegistrar registrar_;
-
-  ScopedRunnableMethodFactory<UserController> method_factory_;
+  // Whether name tooltip is enabled.
+  bool name_tooltip_enabled_;
 
   DISALLOW_COPY_AND_ASSIGN(UserController);
 };
diff --git a/chrome/browser/chromeos/login/user_controller_unittest.cc b/chrome/browser/chromeos/login/user_controller_unittest.cc
index 3cf7ce4..5f18414 100644
--- a/chrome/browser/chromeos/login/user_controller_unittest.cc
+++ b/chrome/browser/chromeos/login/user_controller_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/chromeos/login/user_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/user_image_loader.cc b/chrome/browser/chromeos/login/user_image_loader.cc
index 4532830..7135287 100644
--- a/chrome/browser/chromeos/login/user_image_loader.cc
+++ b/chrome/browser/chromeos/login/user_image_loader.cc
@@ -8,8 +8,8 @@
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "chrome/browser/browser_thread.h"
-#include "gfx/codec/png_codec.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/user_image_screen.cc b/chrome/browser/chromeos/login/user_image_screen.cc
index 3c0abff..5180a37 100644
--- a/chrome/browser/chromeos/login/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/user_image_screen.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/chromeos/login/user_image_screen.h"
 
-#include "app/resource_bundle.h"
 #include "base/compiler_specific.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/screen_observer.h"
@@ -15,6 +15,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace chromeos {
 
@@ -39,8 +40,8 @@
 UserImageScreen::UserImageScreen(WizardScreenDelegate* delegate)
     : ViewScreen<UserImageView>(delegate),
       capture_failure_counter_(0),
-      camera_init_failure_counter_(0),
-      camera_thread_(kCameraThreadName) {
+      camera_init_failure_counter_(0) {
+  camera_thread_.reset(new base::Thread(kCameraThreadName));
   registrar_.Add(
       this,
       NotificationType::SCREEN_LOCK_STATE_CHANGED,
@@ -50,11 +51,17 @@
 UserImageScreen::~UserImageScreen() {
   if (camera_.get())
     camera_->set_delegate(NULL);
+  {
+    // A ScopedAllowIO object is required to join the thread when calling Stop.
+    // See http://crosbug.com/11392.
+    base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
+    camera_thread_.reset();
+  }
 }
 
 void UserImageScreen::Refresh() {
-  camera_thread_.Start();
-  camera_ = new Camera(this, &camera_thread_, true);
+  camera_thread_->Start();
+  camera_ = new Camera(this, camera_thread_.get(), true);
   InitCamera();
 }
 
diff --git a/chrome/browser/chromeos/login/user_image_screen.h b/chrome/browser/chromeos/login/user_image_screen.h
index 9a3fef8..20702f4 100644
--- a/chrome/browser/chromeos/login/user_image_screen.h
+++ b/chrome/browser/chromeos/login/user_image_screen.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include "base/threading/thread.h"
+#include "base/scoped_ptr.h"
 #include "chrome/browser/chromeos/login/camera.h"
 #include "chrome/browser/chromeos/login/user_image_view.h"
 #include "chrome/browser/chromeos/login/view_screen.h"
@@ -64,7 +65,7 @@
   int camera_init_failure_counter_;
 
   // Thread for camera to work on.
-  base::Thread camera_thread_;
+  scoped_ptr<base::Thread> camera_thread_;
 
   NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/chromeos/login/user_image_view.cc b/chrome/browser/chromeos/login/user_image_view.cc
index b8545cf..82de2b5 100644
--- a/chrome/browser/chromeos/login/user_image_view.cc
+++ b/chrome/browser/chromeos/login/user_image_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,24 +6,24 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/image_operations.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 
 namespace {
 
@@ -188,6 +188,8 @@
   snapshot_button_->SetImage(views::CustomButton::BS_DISABLED,
                              ResourceBundle::GetSharedInstance().GetBitmapNamed(
                                  IDR_USER_IMAGE_CAPTURE_DISABLED));
+  snapshot_button_->SetAccessibleName(l10n_util::GetStringUTF16(
+      IDS_CHROMEOS_ACC_ACCOUNT_PICTURE));
 
   ok_button_ = new login::WideButton(
       this, UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK)));
@@ -288,13 +290,6 @@
   user_image_->SetErrorState();
 }
 
-void UserImageView::ViewHierarchyChanged(bool is_add,
-                                         views::View* parent,
-                                         views::View* child) {
-  if (is_add && this == child)
-    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
-}
-
 gfx::Size UserImageView::GetPreferredSize() {
   return gfx::Size(width(), height());
 }
@@ -329,4 +324,3 @@
 }
 
 }  // namespace chromeos
-
diff --git a/chrome/browser/chromeos/login/user_image_view.h b/chrome/browser/chromeos/login/user_image_view.h
index c06dedc..275cc84 100644
--- a/chrome/browser/chromeos/login/user_image_view.h
+++ b/chrome/browser/chromeos/login/user_image_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -62,12 +62,6 @@
   // Overridden from views::ButtonListener.
   virtual void ButtonPressed(views::Button* sender, const views::Event& event);
 
- protected:
-  // views::View overrides:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
-
  private:
   // Initializes layout manager for this view.
   void InitLayout();
@@ -91,4 +85,3 @@
 }  // namespace chromeos
 
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_VIEW_H_
-
diff --git a/chrome/browser/chromeos/login/user_input.h b/chrome/browser/chromeos/login/user_input.h
index 565f928..e4d3141 100644
--- a/chrome/browser/chromeos/login/user_input.h
+++ b/chrome/browser/chromeos/login/user_input.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_INPUT_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_USER_INPUT_H_
 
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc
index 4c325c2..d296e09 100644
--- a/chrome/browser/chromeos/login/user_manager.cc
+++ b/chrome/browser/chromeos/login/user_manager.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/chromeos/login/user_manager.h"
 
-#include "app/resource_bundle.h"
 #include "base/compiler_specific.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/nss_util.h"
 #include "base/path_service.h"
+#include "base/stringprintf.h"
 #include "base/string_util.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
@@ -27,8 +27,9 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace chromeos {
 
@@ -41,7 +42,7 @@
 
 // Incognito user is represented by an empty string (since some code already
 // depends on that and it's hard to figure out what).
-const char kIncognitoUser[] = "";
+const char kGuestUser[] = "";
 
 // Special pathes to default user images.
 const char* kDefaultImageNames[] = {
@@ -167,6 +168,21 @@
   return email_.substr(0, i);
 }
 
+std::string UserManager::User::GetNameTooltip() const {
+  const std::string& user_email = email();
+  size_t at_pos = user_email.rfind('@');
+  if (at_pos == std::string::npos) {
+    NOTREACHED();
+    return std::string();
+  }
+  size_t domain_start = at_pos + 1;
+  std::string domain = user_email.substr(domain_start,
+                                         user_email.length() - domain_start);
+  return base::StringPrintf("%s (%s)",
+                            GetDisplayName().c_str(),
+                            domain.c_str());
+}
+
 // static
 UserManager* UserManager::Get() {
   if (!user_manager_)
@@ -231,12 +247,12 @@
 void UserManager::OffTheRecordUserLoggedIn() {
   user_is_logged_in_ = true;
   logged_in_user_ = User();
-  logged_in_user_.set_email(kIncognitoUser);
+  logged_in_user_.set_email(kGuestUser);
   NotifyOnLogin();
 }
 
 void UserManager::UserLoggedIn(const std::string& email) {
-  if (email == kIncognitoUser) {
+  if (email == kGuestUser) {
     OffTheRecordUserLoggedIn();
     return;
   }
@@ -403,6 +419,10 @@
       Details<const User>(&user));
 }
 
+bool UserManager::IsLoggedInAsGuest() const {
+  return logged_in_user().email() == kGuestUser;
+}
+
 // Private constructor and destructor. Do nothing.
 UserManager::UserManager()
     : ALLOW_THIS_IN_INITIALIZER_LIST(image_loader_(new UserImageLoader(this))),
@@ -434,7 +454,7 @@
       SetDeferImeStartup(false);
   // Shut down the IME so that it will reload the user's settings.
   chromeos::CrosLibrary::Get()->GetInputMethodLibrary()->
-      StopInputMethodProcesses();
+      StopInputMethodDaemon();
   // Let the window manager know that we're logged in now.
   WmIpc::instance()->SetLoggedInProperty(true);
   // Ensure we've opened the real user's key/certificate database.
diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h
index 428513f..0315b0d 100644
--- a/chrome/browser/chromeos/login/user_manager.h
+++ b/chrome/browser/chromeos/login/user_manager.h
@@ -40,6 +40,10 @@
     // Returns the name to display for this user.
     std::string GetDisplayName() const;
 
+    // Tooltip contains user's display name and his email domain to distinguish
+    // this user from the other one with the same display name.
+    std::string GetNameTooltip() const;
+
     // The image for this user.
     void set_image(const SkBitmap& image) { image_ = image; }
     const SkBitmap& image() const { return image_; }
@@ -74,7 +78,7 @@
   virtual bool IsKnownUser(const std::string& email);
 
   // Returns the logged-in user.
-  virtual const User& logged_in_user() {
+  virtual const User& logged_in_user() const {
     return logged_in_user_;
   }
 
@@ -110,6 +114,9 @@
 
   bool user_is_logged_in() const { return user_is_logged_in_; }
 
+  // Returns true if we're logged in as a Guest.
+  bool IsLoggedInAsGuest() const;
+
  protected:
   UserManager();
   virtual ~UserManager();
@@ -150,6 +157,8 @@
   DISALLOW_COPY_AND_ASSIGN(UserManager);
 };
 
+typedef std::vector<UserManager::User> UserVector;
+
 }  // namespace chromeos
 
 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_USER_MANAGER_H_
diff --git a/chrome/browser/chromeos/login/user_view.cc b/chrome/browser/chromeos/login/user_view.cc
index 980f107..85ef9df 100644
--- a/chrome/browser/chromeos/login/user_view.cc
+++ b/chrome/browser/chromeos/login/user_view.cc
@@ -1,21 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/user_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
 #include "chrome/browser/chromeos/login/rounded_view.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/gtk_util.h"
-#include "gfx/rect.h"
+#include "chrome/browser/chromeos/view_ids.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/rect.h"
 #include "views/background.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/image_view.h"
@@ -33,6 +34,7 @@
 // Horiz/Vert insets for Signout view.
 const int kSignoutViewHorizontalInsets = 10;
 const int kSignoutViewVerticalInsets = 5;
+const int kMinControlHeight = 16;
 
 // Padding between remove button and top right image corner.
 const int kRemoveButtonPadding = 3;
@@ -43,15 +45,8 @@
   virtual void Paint(int w, int h, gfx::Canvas* canvas) {
     SkRect rect = {0, 0, w, h};
     SkPath path;
-    SkScalar corners[] = {
-      0, 0,
-      0, 0,
-      kSignoutBackgroundCornerRadius,
-      kSignoutBackgroundCornerRadius,
-      kSignoutBackgroundCornerRadius,
-      kSignoutBackgroundCornerRadius,
-    };
-    path.addRoundRect(rect, corners);
+    path.addRoundRect(rect,
+        kSignoutBackgroundCornerRadius, kSignoutBackgroundCornerRadius);
     SkPaint paint;
     paint.setStyle(SkPaint::kFill_Style);
     paint.setFlags(SkPaint::kAntiAlias_Flag);
@@ -86,6 +81,10 @@
     signout_link_->SetFont(font);
     signout_link_->SetColor(kTextColor);
     signout_link_->SetFocusable(true);
+    signout_link_->SetHighlightedColor(kTextColor);
+    signout_link_->SetDisabledColor(kTextColor);
+    signout_link_->SetNormalColor(kTextColor);
+    signout_link_->SetID(VIEW_ID_SCREEN_LOCKER_SIGNOUT_LINK);
 
     AddChildView(active_user_label_);
     AddChildView(signout_link_);
@@ -110,16 +109,17 @@
   virtual gfx::Size GetPreferredSize() {
     gfx::Size label = active_user_label_->GetPreferredSize();
     gfx::Size button = signout_link_->GetPreferredSize();
-    return gfx::Size(label.width() + button.width(),
-                     std::max(label.height(), button.height()) +
-                     kSignoutViewVerticalInsets * 2);
+    int width =
+      label.width() + button.width() + 2 * kSignoutViewHorizontalInsets;
+    int height =
+      std::max(kMinControlHeight, std::max(label.height(), button.height())) +
+      kSignoutViewVerticalInsets * 2;
+    return gfx::Size(width, height);
   }
 
   views::Link* signout_link() { return signout_link_; }
 
  private:
-  friend class UserView;
-
   views::Label* active_user_label_;
   views::Link* signout_link_;
 
@@ -199,10 +199,10 @@
     gfx::Size size = GetPreferredSize();
     gfx::Point origin = top_right_;
     origin.Offset(-size.width(), 0);
-    SetBounds(gfx::Rect(origin, size));
+    SetBoundsRect(gfx::Rect(origin, size));
 
-    if (GetParent())
-      GetParent()->SchedulePaint();
+    if (parent())
+      parent()->SchedulePaint();
   }
 
   SkBitmap icon_;
@@ -215,7 +215,8 @@
 
 class PodImageView : public views::ImageView {
  public:
-  PodImageView() { }
+  explicit PodImageView(const UserView::Delegate* delegate)
+      : delegate_(delegate) { }
 
   void SetImage(const SkBitmap& image, const SkBitmap& image_hot) {
     image_ = image;
@@ -234,12 +235,14 @@
   }
 
   gfx::NativeCursor GetCursorForPoint(
-      views::Event::EventType event_type,
+      ui::EventType event_type,
       const gfx::Point& p) {
-    return gfx::GetCursor(GDK_HAND2);
+    return (delegate_->IsUserSelected()) ? NULL : gfx::GetCursor(GDK_HAND2);
   }
 
  private:
+  const UserView::Delegate* delegate_;
+
   SkBitmap image_;
   SkBitmap image_hot_;
 
@@ -256,9 +259,9 @@
     signout_view_ = new SignoutView(this);
 
   if (need_background)
-    image_view_ = new RoundedView<PodImageView>;
+    image_view_ = new RoundedView<PodImageView>(delegate);
   else
-    image_view_ = new PodImageView;
+    image_view_ = new PodImageView(delegate);
 
   Init(need_background);
 }
@@ -312,13 +315,16 @@
 
 void UserView::SetSignoutEnabled(bool enabled) {
   DCHECK(signout_view_);
-  signout_view_->signout_link_->SetEnabled(enabled);
+  signout_view_->signout_link()->SetEnabled(enabled);
+
+  // Relayout because active and inactive link has different preferred size.
+  Layout();
 }
 
 void UserView::LinkActivated(views::Link* source, int event_flags) {
   DCHECK(delegate_);
   DCHECK(signout_view_);
-  if (signout_view_->signout_link_ == source)
+  if (signout_view_->signout_link() == source)
     delegate_->OnSignout();
 }
 
@@ -335,6 +341,7 @@
 void UserView::OnLocaleChanged() {
   remove_button_->SetText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_LOGIN_REMOVE)));
+  delegate_->OnLocaleChanged();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_view.h b/chrome/browser/chromeos/login/user_view.h
index 5d4182c..d95b849 100644
--- a/chrome/browser/chromeos/login/user_view.h
+++ b/chrome/browser/chromeos/login/user_view.h
@@ -38,6 +38,12 @@
 
     // Notifies that user would like to remove this user from login screen.
     virtual void OnRemoveUser() {}
+
+    // Returns true if current user is selected.
+    virtual bool IsUserSelected() const = 0;
+
+    // Notifies about locale change.
+    virtual void OnLocaleChanged() {}
   };
 
   // Creates UserView for login screen (|is_login| == true) or screen locker.
@@ -50,7 +56,10 @@
   virtual gfx::Size GetPreferredSize();
   virtual void OnLocaleChanged();
 
-  // Sets the user's image.
+  // Sets the user's image. If image's size is less than
+  // 75% of window size, image size is preserved to avoid blur. Otherwise,
+  // the image is resized to fit window size precisely. Image view repaints
+  // itself.
   void SetImage(const SkBitmap& image, const SkBitmap& image_hot);
 
   // Sets tooltip over the image.
diff --git a/chrome/browser/chromeos/login/username_view.cc b/chrome/browser/chromeos/login/username_view.cc
index 5aead72..db22e2b 100644
--- a/chrome/browser/chromeos/login/username_view.cc
+++ b/chrome/browser/chromeos/login/username_view.cc
@@ -7,12 +7,15 @@
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/rounded_view.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/rect.h"
+#include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkColorShader.h"
 #include "third_party/skia/include/core/SkComposeShader.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/rect.h"
 
 namespace chromeos {
 
@@ -31,13 +34,13 @@
 class HalfRoundedView : public RoundedView<C> {
  public:
   HalfRoundedView(const std::wstring &text, bool use_small_shape)
-      : RoundedView<C>(text), use_small_shape_(use_small_shape) {
+      : RoundedView<C>(text, use_small_shape) {
   }
 
  protected:
   // Overrides ViewFilter.
   virtual SkPath GetClipPath() const {
-    if (!use_small_shape_) {
+    if (!C::use_small_shape()) {
       return RoundedView<C>::GetClipPath();
     } else {
       SkPath path;
@@ -66,34 +69,39 @@
                    this->y() + this->height());
     return view_rect;
   }
-
- private:
-  // Whether the shape for the smaller view should be used.
-  bool use_small_shape_;
 };
 
 }  // namespace
-UsernameView::UsernameView(const std::wstring& username)
-    : views::Label(username) {
+
+UsernameView::UsernameView(const std::wstring& username, bool use_small_shape)
+    : views::Label(username.empty()
+          ? UTF16ToWide(l10n_util::GetStringUTF16(IDS_GUEST)) : username),
+      use_small_shape_(use_small_shape),
+      is_guest_(username.empty()) {
 }
 
 void UsernameView::Paint(gfx::Canvas* canvas) {
-  gfx::Rect bounds = GetLocalBounds(false);
-  if (!text_image_.get())
+  gfx::Rect bounds = GetContentsBounds();
+  if (text_image_ == NULL)
     PaintUsername(bounds);
+  DCHECK(text_image_ != NULL);
   DCHECK(bounds.size() ==
          gfx::Size(text_image_->width(), text_image_->height()));
-
   canvas->DrawBitmapInt(*text_image_, bounds.x(), bounds.y());
 }
 
 // static
 UsernameView* UsernameView::CreateShapedUsernameView(
-    const std::wstring& username,
-    bool use_small_shape) {
+    const std::wstring& username, bool use_small_shape) {
   return new HalfRoundedView<UsernameView>(username, use_small_shape);
 }
 
+gfx::NativeCursor UsernameView::GetCursorForPoint(
+    ui::EventType event_type,
+    const gfx::Point& p) {
+  return use_small_shape_ ? gfx::GetCursor(GDK_HAND2) : NULL;
+}
+
 void UsernameView::PaintUsername(const gfx::Rect& bounds) {
   margin_width_ = bounds.height() * kMarginRatio;
   gfx::CanvasSkia canvas(bounds.width(), bounds.height(), false);
@@ -150,15 +158,15 @@
   // Note, direct call of the DrawStringInt method produces the green dots
   // along the text perimeter (when the label is place on the white background).
   SkColor kInvisibleHaloColor = 0x00000000;
-  canvas.DrawStringWithHalo(GetText(), font(), GetColor(), kInvisibleHaloColor,
-                            bounds.x() + margin_width_, bounds.y(),
-                            bounds.width() - 2 * margin_width_, bounds.height(),
-                            flags);
+  canvas.DrawStringWithHalo(WideToUTF16Hack(GetText()), font(), GetColor(),
+                            kInvisibleHaloColor, bounds.x() + margin_width_,
+                            bounds.y(), bounds.width() - 2 * margin_width_,
+                            bounds.height(), flags);
 
   text_image_.reset(new SkBitmap(canvas.ExtractBitmap()));
 
   if (use_fading_for_text) {
-    // Fade out only the text in the end. Use regualar background.
+    // Fade out only the text in the end. Use regular background.
     canvas.drawColor(kLabelBackgoundColor, SkXfermode::kSrc_Mode);
     SkShader* image_shader = SkShader::CreateBitmapShader(
         *text_image_,
@@ -177,4 +185,12 @@
   }
 }
 
+void UsernameView::OnLocaleChanged() {
+  if (is_guest_) {
+    SetText(UTF16ToWide(l10n_util::GetStringUTF16(IDS_GUEST)));
+    text_image_.reset();
+    SchedulePaint();
+  }
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/username_view.h b/chrome/browser/chromeos/login/username_view.h
index 3ea81aa..12ec105 100644
--- a/chrome/browser/chromeos/login/username_view.h
+++ b/chrome/browser/chromeos/login/username_view.h
@@ -22,22 +22,33 @@
  public:
   virtual ~UsernameView() {}
 
-  // Overriden from views::Label.
-  virtual void Paint(gfx::Canvas* canvas);
-
   // Returns the shaped username view to be used on the login screen. If
   // |user_small_shape| is true, then one pixel margins are used. This is done
   // to match the shape of the scaled frame of the user image. The caller gets
   // the ownership.
+  // Empty |username| stands for guest user.
   static UsernameView* CreateShapedUsernameView(const std::wstring& username,
                                                 bool use_small_shape);
 
  protected:
   // Constructs username view for the given |username|. Consider using
   // |CreateShapedUsernameView| to match the login page style.
-  explicit UsernameView(const std::wstring& username);
+  // Empty |username| stands for guest user.
+  UsernameView(const std::wstring& username, bool use_small_shape);
+
+  // Overriden from views::Label.
+  virtual void Paint(gfx::Canvas* canvas);
+
+  // True indicates that this UsernameView is used for a user pod not
+  // currently selected.
+  bool use_small_shape() const { return use_small_shape_; }
 
  private:
+  // Overriden from View.
+  virtual gfx::NativeCursor GetCursorForPoint(
+      ui::EventType event_type,
+      const gfx::Point& p);
+  virtual void OnLocaleChanged();
 
   // Paints username to the bitmap with the bounds given.
   void PaintUsername(const gfx::Rect& bounds);
@@ -48,6 +59,12 @@
   // Holds margins width (depends on the height).
   int margin_width_;
 
+  // Whether the shape for the smaller view should be used.
+  bool use_small_shape_;
+
+  // Whether it is a guest.
+  bool is_guest_;
+
   DISALLOW_COPY_AND_ASSIGN(UsernameView);
 };
 
diff --git a/chrome/browser/chromeos/login/view_screen.h b/chrome/browser/chromeos/login/view_screen.h
index 30ffdd8..f60ddb5 100644
--- a/chrome/browser/chromeos/login/view_screen.h
+++ b/chrome/browser/chromeos/login/view_screen.h
@@ -9,7 +9,7 @@
 #include "base/message_loop.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/wizard_screen.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 template <class V>
 class ViewScreen : public WizardScreen {
diff --git a/chrome/browser/chromeos/login/views_login_display.cc b/chrome/browser/chromeos/login/views_login_display.cc
new file mode 100644
index 0000000..9185e96
--- /dev/null
+++ b/chrome/browser/chromeos/login/views_login_display.cc
@@ -0,0 +1,324 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/login/views_login_display.h"
+
+#include <algorithm>
+
+#include "base/stl_util-inl.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
+#include "chrome/browser/chromeos/view_ids.h"
+#include "chrome/browser/chromeos/wm_ipc.h"
+#include "chrome/browser/ui/views/window.h"
+#include "grit/chromium_strings.h"
+#include "grit/theme_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "views/widget/widget_gtk.h"
+#include "views/window/window.h"
+
+namespace {
+
+// Max number of users we'll show. The true max is the min of this and the
+// number of windows that fit on the screen.
+const size_t kMaxUsers = 6;
+
+// Minimum number of users we'll show (including Guest and New User pods).
+const size_t kMinUsers = 3;
+
+// Used to indicate no user has been selected.
+const size_t kNotSelected = -1;
+
+// Offset of cursor in first position from edit left side. It's used to position
+// info bubble arrow to cursor.
+const int kCursorOffset = 5;
+
+// Checks if display names are unique. If there are duplicates, enables
+// tooltips with full emails to let users distinguish their accounts.
+// Otherwise, disables the tooltips.
+void EnableTooltipsIfNeeded(
+    const std::vector<chromeos::UserController*>& controllers) {
+  std::map<std::string, int> visible_display_names;
+  for (size_t i = 0; i + 1 < controllers.size(); ++i) {
+    const std::string& display_name =
+        controllers[i]->user().GetDisplayName();
+    ++visible_display_names[display_name];
+  }
+  for (size_t i = 0; i < controllers.size(); ++i) {
+    const std::string& display_name =
+        controllers[i]->user().GetDisplayName();
+    bool show_tooltip = controllers[i]->is_new_user() ||
+                        controllers[i]->is_guest() ||
+                        visible_display_names[display_name] > 1;
+    controllers[i]->EnableNameTooltip(show_tooltip);
+  }
+}
+
+}  // namespace
+
+namespace chromeos {
+
+ViewsLoginDisplay::ViewsLoginDisplay(LoginDisplay::Delegate* delegate,
+                                     const gfx::Rect& background_bounds)
+    : LoginDisplay(delegate, background_bounds),
+      bubble_(NULL),
+      controller_for_removal_(NULL),
+      selected_view_index_(kNotSelected) {
+}
+
+ViewsLoginDisplay::~ViewsLoginDisplay() {
+  ClearErrors();
+  STLDeleteElements(&controllers_);
+  STLDeleteElements(&invisible_controllers_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewsLoginDisplay, LoginDisplay implementation:
+//
+
+void ViewsLoginDisplay::Init(const std::vector<UserManager::User>& users,
+                             bool show_guest,
+                             bool show_new_user) {
+  size_t max_users = kMaxUsers;
+  if (width() > 0) {
+    size_t users_per_screen = (width() - login::kUserImageSize) /
+        (UserController::kUnselectedSize + UserController::kPadding);
+    max_users = std::max(kMinUsers, std::min(kMaxUsers, users_per_screen));
+  }
+
+  size_t visible_users_count = std::min(users.size(), max_users -
+      static_cast<int>(show_guest) - static_cast<int>(show_new_user));
+  for (size_t i = 0; i < users.size(); ++i) {
+    UserController* user_controller = new UserController(this, users[i]);
+    if (controllers_.size() < visible_users_count) {
+      controllers_.push_back(user_controller);
+    } else if (user_controller->is_owner()) {
+      // Make sure that owner of the device is always visible on login screen.
+      invisible_controllers_.insert(invisible_controllers_.begin(),
+                                    controllers_.back());
+      controllers_.back() = user_controller;
+    } else {
+      invisible_controllers_.push_back(user_controller);
+    }
+  }
+  if (show_guest)
+    controllers_.push_back(new UserController(this, true));
+
+  if (show_new_user)
+    controllers_.push_back(new UserController(this, false));
+
+  // If there's only new user pod, show the guest session link on it.
+  bool show_guest_link = controllers_.size() == 1;
+  for (size_t i = 0; i < controllers_.size(); ++i) {
+    (controllers_[i])->Init(static_cast<int>(i),
+                            static_cast<int>(controllers_.size()),
+                            show_guest_link);
+  }
+  EnableTooltipsIfNeeded(controllers_);
+}
+
+void ViewsLoginDisplay::OnBeforeUserRemoved(const std::string& username) {
+  controller_for_removal_ = controllers_[selected_view_index_];
+  controllers_.erase(controllers_.begin() + selected_view_index_);
+  EnableTooltipsIfNeeded(controllers_);
+
+  // Update user count before unmapping windows, otherwise window manager won't
+  // be in the right state.
+  int new_size = static_cast<int>(controllers_.size());
+  for (int i = 0; i < new_size; ++i)
+    controllers_[i]->UpdateUserCount(i, new_size);
+}
+
+void ViewsLoginDisplay::OnUserImageChanged(UserManager::User* user) {
+  UserController* controller = GetUserControllerByEmail(user->email());
+  if (controller)
+    controller->OnUserImageChanged(user);
+}
+
+void ViewsLoginDisplay::OnUserRemoved(const std::string& username) {
+  // We need to unmap entry windows, the windows will be unmapped in destructor.
+  delete controller_for_removal_;
+  controller_for_removal_ = NULL;
+
+  // Nothing to insert.
+  if (invisible_controllers_.empty())
+    return;
+
+  // Insert just before guest or add new user pods if any.
+  int new_size = static_cast<int>(controllers_.size());
+  int insert_position = new_size;
+  while (insert_position > 0 &&
+         (controllers_[insert_position - 1]->is_new_user() ||
+          controllers_[insert_position - 1]->is_guest()))
+    --insert_position;
+
+  controllers_.insert(controllers_.begin() + insert_position,
+                      invisible_controllers_[0]);
+  invisible_controllers_.erase(invisible_controllers_.begin());
+
+  // Update counts for exiting pods.
+  new_size = static_cast<int>(controllers_.size());
+  for (int i = 0; i < new_size; ++i) {
+    if (i != insert_position)
+      controllers_[i]->UpdateUserCount(i, new_size);
+  }
+
+  // And initialize new one that was invisible.
+  controllers_[insert_position]->Init(insert_position, new_size, false);
+
+  EnableTooltipsIfNeeded(controllers_);
+}
+
+void ViewsLoginDisplay::OnFadeOut() {
+  controllers_[selected_view_index_]->StopThrobber();
+}
+
+void ViewsLoginDisplay::SetUIEnabled(bool is_enabled) {
+  // Send message to WM to enable/disable click on windows.
+  WmIpc::Message message(WM_IPC_MESSAGE_WM_SET_LOGIN_STATE);
+  message.set_param(0, is_enabled);
+  WmIpc::instance()->SendMessage(message);
+
+  if (is_enabled)
+    controllers_[selected_view_index_]->ClearAndEnablePassword();
+}
+
+void ViewsLoginDisplay::ShowError(int error_msg_id,
+                                  int login_attempts,
+                                  HelpAppLauncher::HelpTopic help_topic_id) {
+  ClearErrors();
+  string16 error_text;
+  error_msg_id_ = error_msg_id;
+  help_topic_id_ = help_topic_id;
+
+  // GetStringF fails on debug build if there's no replacement in the string.
+  if (error_msg_id == IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED) {
+    error_text = l10n_util::GetStringFUTF16(
+        error_msg_id, l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME));
+  } else {
+    error_text = l10n_util::GetStringUTF16(error_msg_id);
+  }
+
+  gfx::Rect bounds =
+      controllers_[selected_view_index_]->GetMainInputScreenBounds();
+  BubbleBorder::ArrowLocation arrow;
+  if (controllers_[selected_view_index_]->is_new_user()) {
+    arrow = BubbleBorder::LEFT_TOP;
+  } else {
+    // Point info bubble arrow to cursor position (approximately).
+    bounds.set_width(kCursorOffset * 2);
+    arrow = BubbleBorder::BOTTOM_LEFT;
+  }
+
+  string16 help_link;
+  if (error_msg_id == IDS_LOGIN_ERROR_CAPTIVE_PORTAL) {
+    help_link = l10n_util::GetStringUTF16(IDS_LOGIN_FIX_CAPTIVE_PORTAL);
+  } else if (error_msg_id == IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED ||
+             login_attempts > 1) {
+    help_link = l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+  }
+
+  bubble_ = MessageBubble::Show(
+      controllers_[selected_view_index_]->controls_window(),
+      bounds,
+      arrow,
+      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
+      UTF16ToWide(error_text),
+      UTF16ToWide(help_link),
+      this);
+  WizardAccessibilityHelper::GetInstance()->MaybeSpeak(
+      UTF16ToUTF8(error_text).c_str(), false, false);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewsLoginDisplay, UserController::Delegate implementation:
+//
+
+void ViewsLoginDisplay::CreateAccount() {
+  delegate()->CreateAccount();
+}
+
+void ViewsLoginDisplay::Login(UserController* source,
+                              const string16& password) {
+  delegate()->Login(source->user().email(), UTF16ToUTF8(password));
+}
+
+void ViewsLoginDisplay::LoginAsGuest() {
+  delegate()->LoginAsGuest();
+}
+
+void ViewsLoginDisplay::ClearErrors() {
+  // bubble_ will be set to NULL in callback.
+  if (bubble_)
+    bubble_->Close();
+}
+
+void ViewsLoginDisplay::OnUserSelected(UserController* source) {
+  std::vector<UserController*>::const_iterator i =
+      std::find(controllers_.begin(), controllers_.end(), source);
+  DCHECK(i != controllers_.end());
+  size_t new_selected_index = i - controllers_.begin();
+  if (new_selected_index != selected_view_index_ &&
+      selected_view_index_ != kNotSelected) {
+    controllers_[selected_view_index_]->ClearAndEnableFields();
+    controllers_[new_selected_index]->ClearAndEnableFields();
+    delegate()->OnUserSelected(source->user().email());
+  }
+  selected_view_index_ = new_selected_index;
+}
+
+void ViewsLoginDisplay::RemoveUser(UserController* source) {
+  ClearErrors();
+  delegate()->RemoveUser(source->user().email());
+}
+
+void ViewsLoginDisplay::SelectUser(int index) {
+  if (index >= 0 && index < static_cast<int>(controllers_.size()) &&
+      index != static_cast<int>(selected_view_index_)) {
+    WmIpc::Message message(WM_IPC_MESSAGE_WM_SELECT_LOGIN_USER);
+    message.set_param(0, index);
+    WmIpc::instance()->SendMessage(message);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewsLoginDisplay, views::MessageBubbleDelegate implementation:
+//
+
+void ViewsLoginDisplay::OnHelpLinkActivated() {
+  ClearErrors();
+  if (error_msg_id_ == IDS_LOGIN_ERROR_CAPTIVE_PORTAL) {
+    delegate()->FixCaptivePortal();
+    return;
+  }
+  if (!parent_window())
+    return;
+  if (!help_app_.get())
+    help_app_ = new HelpAppLauncher(parent_window());
+  help_app_->ShowHelpTopic(help_topic_id_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewsLoginDisplay, private:
+//
+
+UserController* ViewsLoginDisplay::GetUserControllerByEmail(
+    const std::string& email) {
+  std::vector<UserController*>::iterator i;
+  for (i = controllers_.begin(); i != controllers_.end(); ++i) {
+    if ((*i)->user().email() == email)
+      return *i;
+  }
+  for (i = invisible_controllers_.begin();
+       i != invisible_controllers_.end(); ++i) {
+    if ((*i)->user().email() == email)
+      return *i;
+  }
+  return NULL;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/views_login_display.h b/chrome/browser/chromeos/login/views_login_display.h
new file mode 100644
index 0000000..121f1f6
--- /dev/null
+++ b/chrome/browser/chromeos/login/views_login_display.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_LOGIN_VIEWS_LOGIN_DISPLAY_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_VIEWS_LOGIN_DISPLAY_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "chrome/browser/chromeos/login/login_display.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
+#include "chrome/browser/chromeos/login/user_controller.h"
+#include "ui/gfx/rect.h"
+
+namespace chromeos {
+
+class HelpAppLauncher;
+class MessageBubble;
+
+// Views-based login UI implementation.
+// Uses UserController for each user pod / guest pod / new user pod and
+// ExistingUserView / GuestUserView / NewUserView as their views.
+// When Init is invoked, a UserController is created for each of the Users's
+// in the UserManager (including one for new user and one for Guest login),
+// and the window manager is then told to show the windows.
+class ViewsLoginDisplay : public LoginDisplay,
+                          public UserController::Delegate,
+                          public MessageBubbleDelegate {
+ public:
+  ViewsLoginDisplay(LoginDisplay::Delegate* delegate,
+                    const gfx::Rect& background_bounds);
+  virtual ~ViewsLoginDisplay();
+
+  // LoginDisplay implementation:
+  virtual void Init(const std::vector<UserManager::User>& users,
+                    bool show_guest,
+                    bool show_new_user);
+  virtual void OnBeforeUserRemoved(const std::string& username);
+  virtual void OnUserImageChanged(UserManager::User* user);
+  virtual void OnUserRemoved(const std::string& username);
+  virtual void OnFadeOut();
+  virtual void SetUIEnabled(bool is_enabled);
+  virtual void ShowError(int error_msg_id,
+                         int login_attempts,
+                         HelpAppLauncher::HelpTopic help_topic_id);
+
+  // UserController::Delegate implementation:
+  virtual void CreateAccount();
+  virtual void Login(UserController* source, const string16& password);
+  virtual void LoginAsGuest();
+  virtual void ClearErrors();
+  virtual void OnUserSelected(UserController* source);
+  virtual void RemoveUser(UserController* source);
+  virtual void SelectUser(int index);
+
+  // Overridden from views::MessageBubbleDelegate:
+  virtual void InfoBubbleClosing(InfoBubble* info_bubble,
+                                 bool closed_by_escape) { bubble_ = NULL; }
+  virtual bool CloseOnEscape() { return true; }
+  virtual bool FadeInOnShow() { return false; }
+  virtual void OnHelpLinkActivated();
+
+ private:
+  // Returns existing UserController instance by |email|.
+  // NULL is returned if relevant instance is not found.
+  UserController* GetUserControllerByEmail(const std::string& email);
+
+  // Pointer to shown message bubble. We don't need to delete it because
+  // it will be deleted on bubble closing.
+  MessageBubble* bubble_;
+
+  // UserController that corresponds user that's in process of being removed.
+  // Has meaningful value only between OnBeforeUserRemoved()
+  // and OnUserRemoved() calls.
+  UserController* controller_for_removal_;
+
+  // The set of visible UserControllers.
+  std::vector<UserController*> controllers_;
+
+  // Last error message ID.
+  int error_msg_id_;
+
+  // Help application used for help dialogs.
+  scoped_refptr<HelpAppLauncher> help_app_;
+
+  // Last error help topic ID.
+  HelpAppLauncher::HelpTopic help_topic_id_;
+
+  // The set of invisible UserControllers.
+  std::vector<UserController*> invisible_controllers_;
+
+  // Index of selected user (from the set of visible users).
+  size_t selected_view_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(ViewsLoginDisplay);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_VIEWS_LOGIN_DISPLAY_H_
diff --git a/chrome/browser/chromeos/login/web_page_screen.h b/chrome/browser/chromeos/login/web_page_screen.h
index c9746bf..3d4abf0 100644
--- a/chrome/browser/chromeos/login/web_page_screen.h
+++ b/chrome/browser/chromeos/login/web_page_screen.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -41,7 +41,6 @@
   virtual void LoadingStateChanged(TabContents* source) = 0;
   virtual void CloseContents(TabContents* source) {}
   virtual bool IsPopup(TabContents* source) { return false; }
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
   virtual bool ShouldAddNavigationToHistory(
       const history::HistoryAddPageArgs& add_page_args,
diff --git a/chrome/browser/chromeos/login/web_page_view.cc b/chrome/browser/chromeos/login/web_page_view.cc
index 1bd24ac..c9dd751 100644
--- a/chrome/browser/chromeos/login/web_page_view.cc
+++ b/chrome/browser/chromeos/login/web_page_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/login/web_page_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/string_util.h"
@@ -14,14 +12,16 @@
 #include "chrome/browser/child_process_security_policy.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/bindings_policy.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ipc/ipc_message.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/border.h"
 #include "views/controls/label.h"
@@ -175,7 +175,7 @@
 // WebPageView, views::View implementation:
 
 void WebPageView::Layout() {
-  dom_view()->SetBounds(GetLocalBounds(false));
+  dom_view()->SetBoundsRect(GetContentsBounds());
   int y = height() / 2  - throbber_->GetPreferredSize().height() / 2;
   throbber_->SetBounds(
       width() / 2 - throbber_->GetPreferredSize().width() / 2,
diff --git a/chrome/browser/chromeos/login/web_page_view.h b/chrome/browser/chromeos/login/web_page_view.h
index e219722..dc1bdb8 100644
--- a/chrome/browser/chromeos/login/web_page_view.h
+++ b/chrome/browser/chromeos/login/web_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 
 #include "base/timer.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/dom_view.h"
+#include "chrome/browser/ui/views/dom_view.h"
 #include "views/view.h"
 
 class Profile;
diff --git a/chrome/browser/chromeos/login/wizard_accessibility_handler.cc b/chrome/browser/chromeos/login/wizard_accessibility_handler.cc
index ab24214..16bb99b 100644
--- a/chrome/browser/chromeos/login/wizard_accessibility_handler.cc
+++ b/chrome/browser/chromeos/login/wizard_accessibility_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/i18n/char_iterator.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
@@ -18,16 +17,16 @@
 #include "chrome/browser/extensions/extension_accessibility_api_constants.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/notification_details.h"
-#include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace keys = extension_accessibility_api_constants;
 
 namespace {
 
 static std::string SubstringUTF8(std::string str, int start, int len) {
-  base::UTF8CharIterator iter(&str);
+  base::i18n::UTF8CharIterator iter(&str);
   for (int i = 0; i < start; i++) {
     if (!iter.Advance())
       return std::string();
@@ -300,7 +299,7 @@
     const AccessibilityTextBoxInfo* textbox_info) {
   std::string value = textbox_info->value();
   if (textbox_info->password()) {
-    base::UTF8CharIterator iter(&value);
+    base::i18n::UTF8CharIterator iter(&value);
     std::string obscured;
     while (!iter.end()) {
       obscured += "*";
@@ -377,7 +376,7 @@
   // character's UTF8-encoded representation.
   scoped_array<int32> old_chars(new int32[old_array_len]);
   scoped_array<int> old_indices(new int[old_array_len + 1]);
-  base::UTF8CharIterator old_iter(&old_value);
+  base::i18n::UTF8CharIterator old_iter(&old_value);
   while (!old_iter.end()) {
     old_chars[old_iter.char_pos()] = old_iter.get();
     old_indices[old_iter.char_pos()] = old_iter.array_pos();
@@ -388,7 +387,7 @@
 
   scoped_array<int32> new_chars(new int32[new_array_len]);
   scoped_array<int> new_indices(new int[new_array_len + 1]);
-  base::UTF8CharIterator new_iter(&new_value);
+  base::i18n::UTF8CharIterator new_iter(&new_value);
   while (!new_iter.end()) {
     new_chars[new_iter.char_pos()] = new_iter.get();
     new_indices[new_iter.char_pos()] = new_iter.array_pos();
diff --git a/chrome/browser/chromeos/login/wizard_accessibility_helper.cc b/chrome/browser/chromeos/login/wizard_accessibility_helper.cc
index c8c8668..7fb96c4 100644
--- a/chrome/browser/chromeos/login/wizard_accessibility_helper.cc
+++ b/chrome/browser/chromeos/login/wizard_accessibility_helper.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/stl_util-inl.h"
 #include "chrome/browser/browser_process.h"
@@ -16,6 +15,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/accelerator.h"
 #include "views/view.h"
 
@@ -27,7 +27,7 @@
 views::Accelerator WizardAccessibilityHelper::GetAccelerator() {
   if (!WizardAccessibilityHelper::accelerator_.get())
     WizardAccessibilityHelper::accelerator_.reset(
-        new views::Accelerator(app::VKEY_Z, false, true, true));
+        new views::Accelerator(ui::VKEY_Z, false, true, true));
   return *(WizardAccessibilityHelper::accelerator_.get());
 }
 
@@ -74,15 +74,6 @@
       prefs::kAccessibilityEnabled);
 }
 
-void WizardAccessibilityHelper::MaybeEnableAccessibility(
-    views::View* view_tree) {
-  if (IsAccessibilityEnabled()) {
-    EnableAccessibilityForView(view_tree);
-  } else {
-    AddViewToBuffer(view_tree);
-  }
-}
-
 void WizardAccessibilityHelper::MaybeSpeak(const char* str, bool queue,
     bool interruptible) {
   if (IsAccessibilityEnabled()) {
@@ -90,38 +81,21 @@
   }
 }
 
-void WizardAccessibilityHelper::EnableAccessibilityForView(
-    views::View* view_tree) {
-  VLOG(1) << "Enabling accessibility.";
-  if (!registered_notifications_)
-    RegisterNotifications();
-  SetAccessibilityEnabled(true);
-  if (view_tree) {
-    AddViewToBuffer(view_tree);
-    // If accessibility pref is set, enable accessibility for all views in
-    // the buffer for which access is not yet enabled.
-    for (std::map<views::View*, bool>::iterator iter =
-        views_buffer_.begin();
-        iter != views_buffer_.end(); ++iter) {
-      if (!(*iter).second) {
-        AccessibleViewHelper *helper = new AccessibleViewHelper((*iter).first,
-            profile_);
-        accessible_view_helpers_.push_back(helper);
-        (*iter).second = true;
-      }
-    }
-  }
-}
-
-void WizardAccessibilityHelper::ToggleAccessibility(views::View* view_tree) {
+void WizardAccessibilityHelper::ToggleAccessibility() {
   if (!IsAccessibilityEnabled()) {
-    EnableAccessibilityForView(view_tree);
+    VLOG(1) << "Enabling accessibility.";
+    if (!registered_notifications_)
+      RegisterNotifications();
+    SetAccessibilityEnabled(true);
   } else {
     SetAccessibilityEnabled(false);
+    if (registered_notifications_)
+      UnregisterNotifications();
   }
 }
 
 void WizardAccessibilityHelper::SetAccessibilityEnabled(bool enabled) {
+  bool doSpeak = (IsAccessibilityEnabled() != enabled);
   if (g_browser_process) {
     PrefService* prefService = g_browser_process->local_state();
     prefService->SetBoolean(prefs::kAccessibilityEnabled, enabled);
@@ -129,27 +103,12 @@
   }
   ExtensionAccessibilityEventRouter::GetInstance()->
       SetAccessibilityEnabled(enabled);
-  accessibility_handler_->Speak(enabled ?
-      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_ACCESS_ENABLED).c_str() :
-      l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_ACCESS_DISABLED).c_str(),
-      false, true);
-}
-
-void WizardAccessibilityHelper::AddViewToBuffer(views::View* view_tree) {
-  if (!view_tree->GetWidget())
-    return;
-  bool view_exists = false;
-  // Check if the view is already queued for enabling accessibility.
-  // Prevent adding the same view in the buffer twice.
-  for (std::map<views::View*, bool>::iterator iter = views_buffer_.begin();
-      iter != views_buffer_.end(); ++iter) {
-    if ((*iter).first == view_tree) {
-      view_exists = true;
-      break;
-    }
+  if (doSpeak) {
+    accessibility_handler_->Speak(enabled ?
+        l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_ACCESS_ENABLED).c_str() :
+        l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_ACCESS_DISABLED).c_str(),
+        false, true);
   }
-  if (!view_exists)
-    views_buffer_[view_tree] = false;
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/wizard_accessibility_helper.h b/chrome/browser/chromeos/login/wizard_accessibility_helper.h
index c27ef3c..64f74f1 100644
--- a/chrome/browser/chromeos/login/wizard_accessibility_helper.h
+++ b/chrome/browser/chromeos/login/wizard_accessibility_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,15 +6,11 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_ACCESSIBILITY_HELPER_H_
 #pragma once
 
-#include <map>
-#include <vector>
-
-#include "app/keyboard_codes.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
 #include "chrome/browser/chromeos/login/wizard_accessibility_handler.h"
-#include "chrome/browser/views/accessible_view_helper.h"
 #include "chrome/common/notification_registrar.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
 class Profile;
 namespace views {
@@ -34,30 +30,18 @@
   // Get accelerator for enabling accessibility.
   static views::Accelerator GetAccelerator();
 
-  // Enables Accessibility by setting the accessibility pref and registers
-  // all views in the view buffer to raise accessibility notifications,
-  // including the specified |view_tree|.
-  void EnableAccessibilityForView(views::View* view_tree);
-
-  // Enables accessibility for the specified |view_tree| if the
-  // accessibility pref is already set. Otherwise the |view_tree| is
-  // added to a view buffer so that accessibility can be enabled for it
-  // later when requested.
-  void MaybeEnableAccessibility(views::View* view_tree);
-
   // Speak the given text if the accessibility pref is already set. |queue|
   // specifies whether this utterance will be queued or spoken immediately.
   // |interruptible| specified whether this utterance can be flushed by a
   // subsequent utterance.
+  // TODO (chaitanyag): Change API to use string16 instead of char*.
   void MaybeSpeak(const char* str, bool queue, bool interruptible);
 
   // Unregisters all accessibility notifications
   void UnregisterNotifications();
 
-  // Toggles accessibility support. If |view_tree| is null, only the
-  // access preference setting is toggled. |view_tree| has no effect while
-  // disabling accessibility.
-  void ToggleAccessibility(views::View* view_tree);
+  // Toggles accessibility support.
+  void ToggleAccessibility();
 
  private:
   friend struct DefaultSingletonTraits<WizardAccessibilityHelper>;
@@ -74,12 +58,6 @@
 
   static scoped_ptr<views::Accelerator> accelerator_;
 
-  void AddViewToBuffer(views::View* view_tree);
-
-  std::map<views::View*, bool> views_buffer_;
-
-  std::vector<AccessibleViewHelper*> accessible_view_helpers_;
-
   scoped_ptr<WizardAccessibilityHandler> accessibility_handler_;
 
   Profile* profile_;
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index a3b7efd..88b1bc2 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -11,10 +11,10 @@
 #include <string>
 #include <vector>
 
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
@@ -32,7 +32,6 @@
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/html_page_screen.h"
 #include "chrome/browser/chromeos/login/language_switch_menu.h"
-#include "chrome/browser/chromeos/login/login_screen.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/network_screen.h"
 #include "chrome/browser/chromeos/login/registration_screen.h"
@@ -49,6 +48,7 @@
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "unicode/timezone.h"
 #include "views/accelerator.h"
 #include "views/painter.h"
@@ -60,21 +60,26 @@
 // A boolean pref of the EULA accepted flag.
 const char kEulaAccepted[] = "EulaAccepted";
 
-// A boolean pref of the OOBE complete flag.
+// A boolean pref of the OOBE complete flag (first OOBE part before login).
 const char kOobeComplete[] = "OobeComplete";
 
+// A boolean pref of the device registered flag (second part after first login).
+const char kDeviceRegistered[] = "DeviceRegistered";
+
 // Path to OEM partner startup customization manifest.
 const char kStartupCustomizationManifestPath[] =
     "/mnt/partner_partition/etc/chromeos/startup_manifest.json";
 
-// Path to flag file indicating that OOBE was completed successfully.
-const char kOobeCompleteFlagFilePath[] =
-    "/home/chronos/.oobe_completed";
+// Path to flag file indicating that both parts of OOBE were completed.
+const char kOobeCompleteFlagFilePath[] = "/home/chronos/.oobe_completed";
 
 // Time in seconds that we wait for the device to reboot.
 // If reboot didn't happen, ask user to reboot device manually.
 const int kWaitForRebootTimeSec = 3;
 
+// Interval in ms which is used for smooth screen showing.
+static int kShowDelayMs = 400;
+
 // RootView of the Widget WizardController creates. Contains the contents of the
 // WizardController.
 class ContentView : public views::View {
@@ -83,24 +88,24 @@
       : accel_toggle_accessibility_(
             chromeos::WizardAccessibilityHelper::GetAccelerator()) {
 #if defined(OFFICIAL_BUILD)
-    accel_cancel_update_ =  views::Accelerator(app::VKEY_ESCAPE,
+    accel_cancel_update_ =  views::Accelerator(ui::VKEY_ESCAPE,
                                                true, true, true);
 #else
-    accel_cancel_update_ =  views::Accelerator(app::VKEY_ESCAPE,
+    accel_cancel_update_ =  views::Accelerator(ui::VKEY_ESCAPE,
                                                false, false, false);
-    accel_account_screen_ = views::Accelerator(app::VKEY_A,
+    accel_account_screen_ = views::Accelerator(ui::VKEY_A,
                                                false, true, true);
-    accel_login_screen_ = views::Accelerator(app::VKEY_L,
+    accel_login_screen_ = views::Accelerator(ui::VKEY_L,
                                              false, true, true);
-    accel_network_screen_ = views::Accelerator(app::VKEY_N,
+    accel_network_screen_ = views::Accelerator(ui::VKEY_N,
                                                false, true, true);
-    accel_update_screen_ = views::Accelerator(app::VKEY_U,
+    accel_update_screen_ = views::Accelerator(ui::VKEY_U,
                                               false, true, true);
-    accel_image_screen_ = views::Accelerator(app::VKEY_I,
+    accel_image_screen_ = views::Accelerator(ui::VKEY_I,
                                              false, true, true);
-    accel_eula_screen_ = views::Accelerator(app::VKEY_E,
+    accel_eula_screen_ = views::Accelerator(ui::VKEY_E,
                                             false, true, true);
-    accel_register_screen_ = views::Accelerator(app::VKEY_R,
+    accel_register_screen_ = views::Accelerator(ui::VKEY_R,
                                                 false, true, true);
     AddAccelerator(accel_account_screen_);
     AddAccelerator(accel_login_screen_);
@@ -127,9 +132,8 @@
       return false;
 
     if (accel == accel_toggle_accessibility_) {
-      chromeos::WizardAccessibilityHelper::GetInstance()->ToggleAccessibility(
-          controller->contents()); }
-    else if (accel == accel_cancel_update_) {
+      chromeos::WizardAccessibilityHelper::GetInstance()->ToggleAccessibility();
+    } else if (accel == accel_cancel_update_) {
       controller->CancelOOBEUpdate();
 #if !defined(OFFICIAL_BUILD)
     } else if (accel == accel_account_screen_) {
@@ -155,7 +159,7 @@
   }
 
   virtual void Layout() {
-    for (int i = 0; i < GetChildViewCount(); ++i) {
+    for (int i = 0; i < child_count(); ++i) {
       views::View* cur = GetChildViewAt(i);
       if (cur->IsVisible())
         cur->SetBounds(0, 0, width(), height());
@@ -192,7 +196,9 @@
 }
 
 const chromeos::StartupCustomizationDocument* LoadStartupManifest() {
-  // Load partner customization startup manifest if it is available.
+  // Loading manifest causes us to do blocking IO on UI thread.
+  // Temporarily allow it until we fix http://crosbug.com/11103
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   FilePath startup_manifest_path(kStartupCustomizationManifestPath);
   if (file_util::PathExists(startup_manifest_path)) {
     scoped_ptr<chromeos::StartupCustomizationDocument> customization(
@@ -217,13 +223,41 @@
          GURL(startup_manifest->registration_url()).is_valid();
 }
 
-// Saves boolean "Local State" preference and forces it's persistence to disk.
+// Saves boolean "Local State" preference and forces its persistence to disk.
 void SaveBoolPreferenceForced(const char* pref_name, bool value) {
   PrefService* prefs = g_browser_process->local_state();
   prefs->SetBoolean(pref_name, value);
   prefs->SavePersistentPrefs();
 }
 
+// Saves integer "Local State" preference and forces its persistence to disk.
+void SaveIntegerPreferenceForced(const char* pref_name, int value) {
+  PrefService* prefs = g_browser_process->local_state();
+  prefs->SetInteger(pref_name, value);
+  prefs->SavePersistentPrefs();
+}
+
+// Saves the hardware keyboard to "Locale State" from the locale code.
+// The information will be used in input_method::GetHardwareInputMethodId().
+void SaveHardwareKeyboardFromLocaleCode(const std::string& locale) {
+  std::vector<std::string> input_method_ids;
+  if (chromeos::input_method::GetInputMethodIdsFromLanguageCode(
+          locale,
+          chromeos::input_method::kKeyboardLayoutsOnly,
+          &input_method_ids)) {
+    // The output list |input_method_ids| is sorted by popularity, hence
+    // input_method_ids[0] now contains the most popular keyboard layout
+    // for the given locale.
+    PrefService* prefs = g_browser_process->local_state();
+    prefs->SetString(prefs::kHardwareKeyboardLayout, input_method_ids[0]);
+    // This asks the file thread to save the prefs (i.e. doesn't block).
+    // The latest values of Local State reside in memory so we can safely
+    // get the value of kHardwareKeyboardLayout even if the data is not
+    // yet saved to disk.
+    prefs->SavePersistentPrefs();
+  }
+}
+
 }  // namespace
 
 const char WizardController::kNetworkScreenName[] = "network";
@@ -254,13 +288,13 @@
       background_view_(NULL),
       contents_(NULL),
       current_screen_(NULL),
+      initial_show_(true),
 #if defined(OFFICIAL_BUILD)
       is_official_build_(true),
 #else
       is_official_build_(false),
 #endif
       is_out_of_box_(false),
-      is_test_mode_(false),
       observer_(NULL) {
   DCHECK(default_controller_ == NULL);
   default_controller_ = this;
@@ -306,15 +340,6 @@
   ShowFirstScreen(first_screen_name);
 }
 
-void WizardController::Show() {
-  // In tests we might startup without initial screen
-  // so widget_ hasn't been created yet.
-  if (first_screen_name_ != kTestNoScreenName)
-    DCHECK(widget_);
-  if (widget_)
-    widget_->Show();
-}
-
 void WizardController::ShowBackground(const gfx::Rect& bounds) {
   DCHECK(!background_widget_);
   background_widget_ =
@@ -346,12 +371,6 @@
   return network_screen_.get();
 }
 
-chromeos::LoginScreen* WizardController::GetLoginScreen() {
-  if (!login_screen_.get())
-    login_screen_.reset(new chromeos::LoginScreen(this));
-  return login_screen_.get();
-}
-
 chromeos::AccountScreen* WizardController::GetAccountScreen() {
   if (!account_screen_.get())
     account_screen_.reset(new chromeos::AccountScreen(this));
@@ -414,30 +433,23 @@
   // Initiate services customization.
   chromeos::ApplyServicesCustomization::StartIfNeeded();
 
-  // When run under automation test show plain login screen.
-  if (!is_test_mode_ &&
-      chromeos::CrosLibrary::Get()->EnsureLoaded() &&
-      CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableLoginImages)) {
-    std::vector<chromeos::UserManager::User> users =
-        chromeos::UserManager::Get()->GetUsers();
-    // ExistingUserController deletes itself.
-    gfx::Rect screen_bounds;
-    background_widget_->GetBounds(&screen_bounds, true);
-    chromeos::ExistingUserController* controller =
-        new chromeos::ExistingUserController(users, screen_bounds);
-    controller->OwnBackground(background_widget_, background_view_);
-    controller->Init();
-    background_widget_ = NULL;
-    background_view_ = NULL;
+  std::vector<chromeos::UserManager::User> users;
+  if (chromeos::CrosLibrary::Get()->EnsureLoaded())
+    users = chromeos::UserManager::Get()->GetUsers();
 
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  // ExistingUserController deletes itself.
+  gfx::Rect screen_bounds;
+  background_widget_->GetBounds(&screen_bounds, true);
+  chromeos::ExistingUserController* controller =
+      new chromeos::ExistingUserController(screen_bounds);
+  controller->OwnBackground(background_widget_, background_view_);
+  controller->Init(users);
+  background_widget_ = NULL;
+  background_view_ = NULL;
 
-    return controller;
-  }
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 
-  SetCurrentScreen(GetLoginScreen());
-  return NULL;
+  return controller;
 }
 
 void WizardController::ShowAccountScreen() {
@@ -529,6 +541,7 @@
 // static
 void WizardController::RegisterPrefs(PrefService* local_state) {
   local_state->RegisterBooleanPref(kOobeComplete, false);
+  local_state->RegisterIntegerPref(kDeviceRegistered, -1);
   local_state->RegisterBooleanPref(kEulaAccepted, false);
   // Check if the pref is already registered in case
   // Preferences::RegisterUserPrefs runs before this code in the future.
@@ -539,26 +552,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 // WizardController, ExitHandlers:
-void WizardController::OnLoginSignInSelected() {
-  // Don't show user image screen in case of automated testing.
-  if (is_test_mode_) {
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-    return;
-  }
-  // Don't launch browser until we pass image screen.
-  chromeos::LoginUtils::Get()->EnableBrowserLaunch(false);
-  ShowUserImageScreen();
-}
-
-void WizardController::OnLoginGuestUser() {
-  // We're on the stack, so don't try and delete us now.
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void WizardController::OnLoginCreateAccount() {
-  ShowAccountScreen();
-}
-
 void WizardController::OnNetworkConnected() {
   if (is_official_build_) {
     if (!IsEulaAccepted()) {
@@ -582,17 +575,13 @@
 }
 
 void WizardController::OnAccountCreateBack() {
-  chromeos::ExistingUserController* controller = ShowLoginScreen();
-  if (controller)
-    controller->SelectNewUser();
+  ShowLoginScreen();
 }
 
 void WizardController::OnAccountCreated() {
   chromeos::ExistingUserController* controller = ShowLoginScreen();
-  if (controller)
-    controller->LoginNewUser(username_, password_);
-  else
-    Login(username_, password_);
+  DCHECK(controller);
+  controller->Login(username_, password_);
   // TODO(dpolukhin): clear password memory for real. Now it is not
   // a problem because we can't extract password from the form.
   password_.clear();
@@ -653,7 +642,7 @@
 
 void WizardController::OnRegistrationSuccess() {
   MarkDeviceRegistered();
-  if (chromeos::UserManager::Get()->logged_in_user().email().empty()) {
+  if (chromeos::UserManager::Get()->IsLoggedInAsGuest()) {
     chromeos::LoginUtils::Get()->CompleteOffTheRecordLogin(start_url_);
   } else {
     ShowUserImageScreen();
@@ -671,8 +660,8 @@
 }
 
 void WizardController::InitiateOOBEUpdate() {
-  ShowUpdateScreen();
   GetUpdateScreen()->StartUpdate();
+  SetCurrentScreenSmooth(GetUpdateScreen(), true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -712,17 +701,12 @@
 
 
 void WizardController::SetCurrentScreen(WizardScreen* new_current) {
-  if (current_screen_ == new_current ||
-      new_current == NULL)
-    return;
+  SetCurrentScreenSmooth(new_current, false);
+}
 
-  bool initial_show = true;
-  if (current_screen_) {
-    initial_show = false;
-    current_screen_->Hide();
-  }
+void WizardController::ShowCurrentScreen() {
+  smooth_show_timer_.Stop();
 
-  current_screen_ = new_current;
   bool force_widget_show = false;
   views::WidgetGtk* window = NULL;
 
@@ -736,7 +720,7 @@
     if (widget_)
       widget_->Close();
     force_widget_show = true;
-    window = CreateScreenWindow(new_bounds, initial_show);
+    window = CreateScreenWindow(new_bounds, initial_show_);
   }
   current_screen_->Show();
   contents_->Layout();
@@ -750,6 +734,32 @@
   }
 }
 
+void WizardController::SetCurrentScreenSmooth(WizardScreen* new_current,
+                                              bool use_smoothing) {
+  if (current_screen_ == new_current || new_current == NULL)
+    return;
+
+  smooth_show_timer_.Stop();
+
+  if (current_screen_) {
+    initial_show_ = false;
+    current_screen_->Hide();
+  }
+
+  current_screen_ = new_current;
+
+  if (use_smoothing) {
+    smooth_show_timer_.Start(
+        base::TimeDelta::FromMilliseconds(kShowDelayMs),
+        this,
+        &WizardController::ShowCurrentScreen);
+    contents_->Layout();
+    contents_->SchedulePaint();
+  } else {
+    ShowCurrentScreen();
+  }
+}
+
 void WizardController::SetStatusAreaVisible(bool visible) {
   // When ExistingUserController passes background ownership
   // to WizardController it happens after screen is shown.
@@ -762,8 +772,6 @@
   if (first_screen_name == kNetworkScreenName) {
     ShowNetworkScreen();
   } else if (first_screen_name == kLoginScreenName) {
-    // This flag is passed if we're running under automation test.
-    is_test_mode_ = true;
     ShowLoginScreen();
   } else if (first_screen_name == kAccountScreenName) {
     ShowAccountScreen();
@@ -791,19 +799,6 @@
   }
 }
 
-void WizardController::Login(const std::string& username,
-                             const std::string& password) {
-  chromeos::LoginScreen* login = GetLoginScreen();
-  if (username.empty())
-    return;
-  login->view()->SetUsername(username);
-
-  if (password.empty())
-    return;
-  login->view()->SetPassword(password);
-  login->view()->Login();
-}
-
 // static
 bool WizardController::IsEulaAccepted() {
   return g_browser_process->local_state()->GetBoolean(kEulaAccepted);
@@ -824,10 +819,48 @@
   SaveBoolPreferenceForced(kOobeComplete, true);
 }
 
+static void CreateOobeCompleteFlagFile() {
+  // Create flag file for boot-time init scripts.
+  FilePath oobe_complete_path(kOobeCompleteFlagFilePath);
+  if (!file_util::PathExists(oobe_complete_path)) {
+    FILE* oobe_flag_file = file_util::OpenFile(oobe_complete_path, "w+b");
+    if (oobe_flag_file == NULL)
+      DLOG(WARNING) << kOobeCompleteFlagFilePath << " doesn't exist.";
+    else
+      file_util::CloseFile(oobe_flag_file);
+  }
+}
+
 // static
 bool WizardController::IsDeviceRegistered() {
-  FilePath oobe_complete_flag_file_path(kOobeCompleteFlagFilePath);
-  return file_util::PathExists(oobe_complete_flag_file_path);
+  int value = g_browser_process->local_state()->GetInteger(kDeviceRegistered);
+  if (value > 0) {
+    // Recreate flag file in case it was lost.
+    BrowserThread::PostTask(
+        BrowserThread::FILE,
+        FROM_HERE,
+        NewRunnableFunction(&CreateOobeCompleteFlagFile));
+    return true;
+  } else if (value == 0) {
+    return false;
+  } else {
+    // Pref is not set. For compatibility check flag file. It causes blocking
+    // IO on UI thread. But it's required for update from old versions.
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    FilePath oobe_complete_flag_file_path(kOobeCompleteFlagFilePath);
+    bool file_exists = file_util::PathExists(oobe_complete_flag_file_path);
+    SaveIntegerPreferenceForced(kDeviceRegistered, file_exists ? 1 : 0);
+    return file_exists;
+  }
+}
+
+// static
+void WizardController::MarkDeviceRegistered() {
+  SaveIntegerPreferenceForced(kDeviceRegistered, 1);
+  BrowserThread::PostTask(
+      BrowserThread::FILE,
+      FROM_HERE,
+      NewRunnableFunction(&CreateOobeCompleteFlagFile));
 }
 
 // static
@@ -842,30 +875,11 @@
   return IsRegistrationScreenValid(manifest);
 }
 
-// static
-void WizardController::MarkDeviceRegistered() {
-  // Create flag file for boot-time init scripts.
-  FilePath oobe_complete_path(kOobeCompleteFlagFilePath);
-  FILE* oobe_flag_file = file_util::OpenFile(oobe_complete_path, "w+b");
-  DCHECK(oobe_flag_file != NULL) << kOobeCompleteFlagFilePath;
-  if (oobe_flag_file != NULL)
-    file_util::CloseFile(oobe_flag_file);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // WizardController, chromeos::ScreenObserver overrides:
 void WizardController::OnExit(ExitCodes exit_code) {
   LOG(INFO) << "Wizard screen exit code: " << exit_code;
   switch (exit_code) {
-    case LOGIN_SIGN_IN_SELECTED:
-      OnLoginSignInSelected();
-      break;
-    case LOGIN_GUEST_SELECTED:
-      OnLoginGuestUser();
-      break;
-    case LOGIN_CREATE_ACCOUNT:
-      OnLoginCreateAccount();
-      break;
     case NETWORK_CONNECTED:
       OnNetworkConnected();
       break;
@@ -930,6 +944,10 @@
   return observer_ ? observer_ : this;
 }
 
+void WizardController::SetZeroDelays() {
+  kShowDelayMs = 0;
+}
+
 namespace browser {
 
 // Declared in browser_dialogs.h so that others don't need to depend on our .h.
@@ -948,6 +966,7 @@
   // and US dvorak keyboard layouts.
   if (g_browser_process && g_browser_process->local_state()) {
     const std::string locale = g_browser_process->GetApplicationLocale();
+    // If the preferred keyboard for the login screen has been saved, use it.
     const std::string initial_input_method_id =
         g_browser_process->local_state()->GetString(
             chromeos::language_prefs::kPreferredKeyboardLayout);
@@ -960,18 +979,17 @@
 
   // Check whether we need to execute OOBE process.
   bool oobe_complete = WizardController::IsOobeCompleted();
+  bool show_login_screen =
+      (first_screen_name.empty() && oobe_complete) ||
+      first_screen_name == WizardController::kLoginScreenName;
 
-  if (first_screen_name.empty() &&
-      oobe_complete &&
-      chromeos::CrosLibrary::Get()->EnsureLoaded() &&
-      CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableLoginImages)) {
+  if (show_login_screen && chromeos::CrosLibrary::Get()->EnsureLoaded()) {
     std::vector<chromeos::UserManager::User> users =
         chromeos::UserManager::Get()->GetUsers();
 
     // Fix for users who updated device and thus never passed register screen.
-    // If we already have user we assume that it is not a second part of OOBE.
-    // See http://crosbug.com/6289
+    // If we already have users, we assume that it is not a second part of
+    // OOBE. See http://crosbug.com/6289
     if (!WizardController::IsDeviceRegistered() && !users.empty()) {
       VLOG(1) << "Mark device registered because there are remembered users: "
               << users.size();
@@ -979,7 +997,7 @@
     }
 
     // ExistingUserController deletes itself.
-    (new chromeos::ExistingUserController(users, screen_bounds))->Init();
+    (new chromeos::ExistingUserController(screen_bounds))->Init(users);
 
     // Initiate services customization.
     chromeos::ApplyServicesCustomization::StartIfNeeded();
@@ -1000,33 +1018,41 @@
     // chromeos::LanguageSwitchMenu::SwitchLanguage here before
     // EmitLoginPromptReady.
     const std::string current_locale =
-        g_browser_process->local_state()->GetString(
-            prefs::kApplicationLocale);
+        g_browser_process->local_state()->GetString(prefs::kApplicationLocale);
     VLOG(1) << "Current locale: " << current_locale;
     if (current_locale.empty()) {
       locale = controller->GetCustomization()->initial_locale();
       VLOG(1) << "Initial locale: " << locale;
       if (!locale.empty()) {
+        // Save the hardware keyboard from the locale code.
+        SaveHardwareKeyboardFromLocaleCode(locale);
+        // Then, enable the hardware keyboard.
+        chromeos::input_method::EnableInputMethods(
+            locale,
+            chromeos::input_method::kKeyboardLayoutsOnly,
+            chromeos::input_method::GetHardwareInputMethodId());
+        // Reloading resource bundle causes us to do blocking IO on UI thread.
+        // Temporarily allow it until we fix http://crosbug.com/11102
+        base::ThreadRestrictions::ScopedAllowIO allow_io;
         const std::string loaded_locale =
             ResourceBundle::ReloadSharedInstance(locale);
         CHECK(!loaded_locale.empty()) << "Locale could not be found for "
                                       << locale;
+        // Set the application locale here so that the language switch
+        // menu works properly with the newly loaded locale.
+        g_browser_process->SetApplicationLocale(loaded_locale);
       }
     }
   }
 
   controller->ShowBackground(screen_bounds);
   controller->Init(first_screen_name, screen_bounds);
-  controller->Show();
 
   chromeos::LoginUtils::Get()->PrewarmAuthentication();
   if (chromeos::CrosLibrary::Get()->EnsureLoaded())
     chromeos::CrosLibrary::Get()->GetLoginLibrary()->EmitLoginPromptReady();
 
   if (controller->GetCustomization()) {
-    if (!locale.empty())
-      chromeos::LanguageSwitchMenu::SwitchLanguage(locale);
-
     // Set initial timezone if specified by customization.
     const std::string timezone_name =
         controller->GetCustomization()->initial_timezone();
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 38380d6..843fdcd 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -10,14 +10,15 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/scoped_ptr.h"
+#include "base/timer.h"
 #include "chrome/browser/chromeos/login/screen_observer.h"
 #include "chrome/browser/chromeos/login/view_screen.h"
 #include "chrome/browser/chromeos/login/wizard_screen.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
+#include "ui/gfx/rect.h"
 
 class PrefService;
 class WizardContentsView;
@@ -29,12 +30,12 @@
 class EulaScreen;
 class ExistingUserController;
 class HTMLPageScreen;
-class LoginScreen;
 class NetworkScreen;
 class RegistrationScreen;
 class StartupCustomizationDocument;
 class UpdateScreen;
 class UserImageScreen;
+class WizardInProcessBrowserTest;
 }
 
 namespace gfx {
@@ -91,9 +92,6 @@
   // Returns the view that contains all the other views.
   views::View* contents() { return contents_; }
 
-  // Shows the wizard controller in a window.
-  void Show();
-
   // Creates and shows a background window.
   void ShowBackground(const gfx::Rect& bounds);
 
@@ -106,7 +104,6 @@
 
   // Lazy initializers and getters for screens.
   chromeos::NetworkScreen* GetNetworkScreen();
-  chromeos::LoginScreen* GetLoginScreen();
   chromeos::AccountScreen* GetAccountScreen();
   chromeos::UpdateScreen* GetUpdateScreen();
   chromeos::UserImageScreen* GetUserImageScreen();
@@ -122,9 +119,8 @@
   void ShowEulaScreen();
   void ShowRegistrationScreen();
   void ShowHTMLPageScreen();
-  // Shows the default login screen and returns NULL or shows images login
-  // screen and returns the corresponding controller instance for optional
-  // tweaking.
+  // Shows images login screen and returns the corresponding controller
+  // instance for optional tweaking.
   chromeos::ExistingUserController* ShowLoginScreen();
 
   // Returns a pointer to the current screen or NULL if there's no such
@@ -169,9 +165,6 @@
 
  private:
   // Exit handlers:
-  void OnLoginSignInSelected();
-  void OnLoginGuestUser();
-  void OnLoginCreateAccount();
   void OnNetworkConnected();
   void OnNetworkOffline();
   void OnAccountCreateBack();
@@ -190,6 +183,11 @@
   // Shows update screen and starts update process.
   void InitiateOOBEUpdate();
 
+  // Overridden from chromeos::ScreenObserver:
+  virtual void OnExit(ExitCodes exit_code);
+  virtual void OnSetUserNamePassword(const std::string& username,
+                                     const std::string& password);
+
   // Creates wizard screen window with the specified |bounds|.
   // If |initial_show| initial animation (window & background) is shown.
   // Otherwise only window is animated.
@@ -203,17 +201,17 @@
   // Switches from one screen to another.
   void SetCurrentScreen(WizardScreen* screen);
 
+  // Switches from one screen to another with delay before showing. Calling
+  // ShowCurrentScreen directly forces screen to be shown immediately.
+  void SetCurrentScreenSmooth(WizardScreen* screen, bool use_smoothing);
+
   // Changes status area visibility.
   void SetStatusAreaVisible(bool visible);
 
-  // Overridden from chromeos::ScreenObserver:
-  virtual void OnExit(ExitCodes exit_code);
-  virtual void OnSetUserNamePassword(const std::string& username,
-                                     const std::string& password);
-
   // Overridden from WizardScreenDelegate:
   virtual views::View* GetWizardView();
   virtual chromeos::ScreenObserver* GetObserver(WizardScreen* screen);
+  virtual void ShowCurrentScreen();
 
   // Determines which screen to show first by the parameter, shows it and
   // sets it as the current one.
@@ -222,6 +220,9 @@
   // Logs in the specified user via default login screen.
   void Login(const std::string& username, const std::string& password);
 
+  // Sets delays to zero. MUST be used only for browser tests.
+  static void SetZeroDelays();
+
   // Widget we're showing in.
   views::Widget* widget_;
 
@@ -237,7 +238,6 @@
 
   // Screens.
   scoped_ptr<chromeos::NetworkScreen> network_screen_;
-  scoped_ptr<chromeos::LoginScreen> login_screen_;
   scoped_ptr<chromeos::AccountScreen> account_screen_;
   scoped_ptr<chromeos::UpdateScreen> update_screen_;
   scoped_ptr<chromeos::UserImageScreen> user_image_screen_;
@@ -248,6 +248,9 @@
   // Screen that's currently active.
   WizardScreen* current_screen_;
 
+  // Holds whether this is initial show.
+  bool initial_show_;
+
   std::string username_;
   std::string password_;
 
@@ -257,10 +260,6 @@
   // True if full OOBE flow should be shown.
   bool is_out_of_box_;
 
-  // True if this is run under automation test and we need to show only
-  // login screen.
-  bool is_test_mode_;
-
   // Value of the screen name that WizardController was started with.
   std::string first_screen_name_;
 
@@ -278,6 +277,8 @@
 
   NotificationRegistrar registrar_;
 
+  base::OneShotTimer<WizardController> smooth_show_timer_;
+
   FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowErrorNetwork);
   FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowErrorUpdate);
   FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowEulaDeclined);
@@ -288,6 +289,7 @@
   FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowMain);
   FRIEND_TEST_ALL_PREFIXES(WizardControllerTest, SwitchLanguage);
   friend class WizardControllerFlowTest;
+  friend class chromeos::WizardInProcessBrowserTest;
 
   DISALLOW_COPY_AND_ASSIGN(WizardController);
 };
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index af8301a..ff15ac7 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -2,24 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/account_screen.h"
 #include "chrome/browser/chromeos/login/eula_view.h"
+#include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/language_switch_menu.h"
-#include "chrome/browser/chromeos/login/login_screen.h"
 #include "chrome/browser/chromeos/login/mock_update_screen.h"
 #include "chrome/browser/chromeos/login/network_screen.h"
 #include "chrome/browser/chromeos/login/network_selection_view.h"
 #include "chrome/browser/chromeos/login/user_image_screen.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/ui_test_utils.h"
 #include "grit/generated_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/locid.h"
 #include "views/accelerator.h"
 
@@ -58,6 +57,8 @@
 
 }  // namespace
 
+using chromeos::ExistingUserController;
+
 class WizardControllerTest : public chromeos::WizardInProcessBrowserTest {
  protected:
   WizardControllerTest() : chromeos::WizardInProcessBrowserTest(
@@ -115,7 +116,6 @@
 
     // Set up the mocks for all screens.
     MOCK(mock_account_screen_, account_screen_, chromeos::AccountScreen);
-    MOCK(mock_login_screen_, login_screen_, chromeos::LoginScreen);
     MOCK(mock_network_screen_, network_screen_, chromeos::NetworkScreen);
     MOCK(mock_update_screen_, update_screen_, MockUpdateScreen);
     MOCK(mock_eula_screen_, eula_screen_, chromeos::EulaScreen);
@@ -129,7 +129,6 @@
   }
 
   MockOutShowHide<chromeos::AccountScreen>* mock_account_screen_;
-  MockOutShowHide<chromeos::LoginScreen>* mock_login_screen_;
   MockOutShowHide<chromeos::NetworkScreen>* mock_network_screen_;
   MockOutShowHide<MockUpdateScreen>* mock_update_screen_;
   MockOutShowHide<chromeos::EulaScreen>* mock_eula_screen_;
@@ -139,6 +138,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowMain) {
+  EXPECT_TRUE(ExistingUserController::current_controller() == NULL);
   EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
   EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
@@ -151,23 +151,12 @@
   controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);
 
   EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
-  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, Hide()).Times(0);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
-  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
   controller()->OnExit(chromeos::ScreenObserver::UPDATE_INSTALLED);
 
-  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
-  EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
-  controller()->OnExit(chromeos::ScreenObserver::LOGIN_CREATE_ACCOUNT);
-
-  EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());
-  EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_login_screen_, Hide()).Times(0);  // last transition
-  controller()->OnExit(chromeos::ScreenObserver::ACCOUNT_CREATED);
-
-  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
+  EXPECT_FALSE(ExistingUserController::current_controller() == NULL);
+  set_controller(NULL);
 }
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorUpdate) {
@@ -185,14 +174,14 @@
   controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);
 
   EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
-  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, Hide()).Times(0);
   EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
   EXPECT_CALL(*mock_eula_screen_, Hide()).Times(0);  // last transition
-  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
   controller()->OnExit(
       chromeos::ScreenObserver::UPDATE_ERROR_UPDATING);
 
-  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
+  EXPECT_FALSE(ExistingUserController::current_controller() == NULL);
+  set_controller(NULL);
 }
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowEulaDeclined) {
@@ -213,14 +202,14 @@
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorNetwork) {
   EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
-  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
   controller()->OnExit(chromeos::ScreenObserver::NETWORK_OFFLINE);
-  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
+
+  EXPECT_FALSE(ExistingUserController::current_controller() == NULL);
+  set_controller(NULL);
 }
 
 #if defined(OFFICIAL_BUILD)
-// This test is supposed to fail on official test.
+// This test is supposed to fail on official build.
 #define MAYBE_Accelerators DISABLED_Accelerators
 #else
 #define MAYBE_Accelerators Accelerators
@@ -231,12 +220,11 @@
 
   views::FocusManager* focus_manager =
       controller()->contents()->GetFocusManager();
-  views::Accelerator accel_account_screen(app::VKEY_A, false, true, true);
-  views::Accelerator accel_login_screen(app::VKEY_L, false, true, true);
-  views::Accelerator accel_network_screen(app::VKEY_N, false, true, true);
-  views::Accelerator accel_update_screen(app::VKEY_U, false, true, true);
-  views::Accelerator accel_image_screen(app::VKEY_I, false, true, true);
-  views::Accelerator accel_eula_screen(app::VKEY_E, false, true, true);
+  views::Accelerator accel_account_screen(ui::VKEY_A, false, true, true);
+  views::Accelerator accel_network_screen(ui::VKEY_N, false, true, true);
+  views::Accelerator accel_update_screen(ui::VKEY_U, false, true, true);
+  views::Accelerator accel_image_screen(ui::VKEY_I, false, true, true);
+  views::Accelerator accel_eula_screen(ui::VKEY_E, false, true, true);
 
   EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
@@ -245,12 +233,6 @@
 
   focus_manager = controller()->contents()->GetFocusManager();
   EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
-  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_login_screen));
-  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
-
-  focus_manager = controller()->contents()->GetFocusManager();
-  EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_network_screen));
   EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
@@ -272,5 +254,5 @@
   EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
 }
 
-COMPILE_ASSERT(chromeos::ScreenObserver::EXIT_CODES_COUNT == 18,
+COMPILE_ASSERT(chromeos::ScreenObserver::EXIT_CODES_COUNT == 15,
                add_tests_for_new_control_flow_you_just_introduced);
diff --git a/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc b/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc
index e18ba3a..2eafab4 100644
--- a/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc
+++ b/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #include "base/message_loop.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
 #include "chrome/test/ui_test_utils.h"
 
 namespace chromeos {
@@ -20,8 +20,12 @@
 Browser* WizardInProcessBrowserTest::CreateBrowser(Profile* profile) {
   SetUpWizard();
 
-  browser::ShowLoginWizard(screen_name_.c_str(), gfx::Size(1024, 600));
-  controller_ = WizardController::default_controller();
+  WizardController::SetZeroDelays();
+
+  if (!screen_name_.empty()) {
+    browser::ShowLoginWizard(screen_name_.c_str(), gfx::Size(1024, 600));
+    controller_ = WizardController::default_controller();
+  }
   return NULL;
 }
 
diff --git a/chrome/browser/chromeos/login/wizard_in_process_browser_test.h b/chrome/browser/chromeos/login/wizard_in_process_browser_test.h
index da23b35..488da4e 100644
--- a/chrome/browser/chromeos/login/wizard_in_process_browser_test.h
+++ b/chrome/browser/chromeos/login/wizard_in_process_browser_test.h
@@ -34,6 +34,9 @@
   virtual void CleanUpOnMainThread();
 
   WizardController* controller() const { return controller_; }
+  void set_controller(WizardController* controller) {
+    controller_ = controller;
+  }
 
  private:
   std::string screen_name_;
diff --git a/chrome/browser/chromeos/login/wizard_screen.h b/chrome/browser/chromeos/login/wizard_screen.h
index d0b0d8b..c59679a 100644
--- a/chrome/browser/chromeos/login/wizard_screen.h
+++ b/chrome/browser/chromeos/login/wizard_screen.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_SCREEN_H_
 #pragma once
 
-#include "gfx/canvas.h"
+#include "ui/gfx/canvas.h"
 
 class WizardScreen;
 namespace chromeos {
@@ -28,6 +28,9 @@
   // Returns observer screen should notify.
   virtual chromeos::ScreenObserver* GetObserver(WizardScreen* screen) = 0;
 
+  // Forces the current screen to be shown immediately.
+  virtual void ShowCurrentScreen() = 0;
+
  protected:
   virtual ~WizardScreenDelegate() {}
 };
diff --git a/chrome/browser/chromeos/low_battery_observer.cc b/chrome/browser/chromeos/low_battery_observer.cc
index 0513cc2..6e307ea 100644
--- a/chrome/browser/chromeos/low_battery_observer.cc
+++ b/chrome/browser/chromeos/low_battery_observer.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/chromeos/low_battery_observer.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/time_format.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/metrics_cros_settings_provider.cc b/chrome/browser/chromeos/metrics_cros_settings_provider.cc
index 47759bc..f9edb24 100644
--- a/chrome/browser/chromeos/metrics_cros_settings_provider.cc
+++ b/chrome/browser/chromeos/metrics_cros_settings_provider.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/metrics_cros_settings_provider.h"
 
 #include "base/string_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/cros_settings.h"
 #include "chrome/browser/chromeos/cros_settings_names.h"
@@ -43,7 +44,14 @@
   if (user->user_is_logged_in() && !user->current_user_is_owner())
     return false;
   VLOG(1) << "Setting cros stats/crash metric reporting to " << enabled;
-  if (enabled != GoogleUpdateSettings::GetCollectStatsConsent()) {
+  bool collect_stats_consent = false;
+  {
+    // Loading consent file state causes us to do blocking IO on UI thread.
+    // Temporarily allow it until we fix http://crbug.com/62626
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    collect_stats_consent = GoogleUpdateSettings::GetCollectStatsConsent();
+  }
+  if (enabled != collect_stats_consent) {
     bool new_enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled);
 #if defined(USE_LINUX_BREAKPAD)
     if (new_enabled)
@@ -62,6 +70,9 @@
 
 // static
 bool MetricsCrosSettingsProvider::GetMetricsStatus() {
+  // Loading consent file state causes us to do blocking IO on UI thread.
+  // Temporarily allow it until we fix http://crbug.com/62626
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   return GoogleUpdateSettings::GetCollectStatsConsent();
 }
 
diff --git a/chrome/browser/chromeos/native_dialog_window.cc b/chrome/browser/chromeos/native_dialog_window.cc
index 003912e..160585a 100644
--- a/chrome/browser/chromeos/native_dialog_window.cc
+++ b/chrome/browser/chromeos/native_dialog_window.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 
 #include <gtk/gtk.h>
 
-#include "app/gtk_signal.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/frame/bubble_window.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
+#include "ui/base/gtk/gtk_signal.h"
 #include "views/controls/native/native_view_host.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/non_client_view.h"
diff --git a/chrome/browser/chromeos/native_dialog_window.h b/chrome/browser/chromeos/native_dialog_window.h
index 47a478b..1a28365 100644
--- a/chrome/browser/chromeos/native_dialog_window.h
+++ b/chrome/browser/chromeos/native_dialog_window.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_NATIVE_DIALOG_WINDOW_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace gfx {
 class Rect;
diff --git a/chrome/browser/chromeos/native_theme_chromeos.cc b/chrome/browser/chromeos/native_theme_chromeos.cc
index c0cd025..00b9939 100644
--- a/chrome/browser/chromeos/native_theme_chromeos.cc
+++ b/chrome/browser/chromeos/native_theme_chromeos.cc
@@ -4,74 +4,228 @@
 
 #include "chrome/browser/chromeos/native_theme_chromeos.h"
 
-#include <limits>
-
-#include "app/resource_bundle.h"
 #include "base/logging.h"
-#include "gfx/insets.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
-#include "gfx/skbitmap_operations.h"
 #include "grit/theme_resources.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/skbitmap_operations.h"
 
 namespace {
 
-bool IntersectsClipRectInt(
-    skia::PlatformCanvas* canvas, int x, int y, int w, int h) {
-  SkRect clip;
-  return canvas->getClipBounds(&clip) &&
-      clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w),
-                     SkIntToScalar(y + h));
+// Color constants. See theme_draw for details.
+
+// Border color used for many widgets.
+const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F);
+
+// Disabled border color used for many widgets.
+const SkColor kDisabledBaseStroke = SkColorSetRGB(0xB7, 0xB7, 0xB7);
+
+// Common gradient stop and colors.
+const SkColor kBaseGradient0 = SkColorSetRGB(255, 255, 255);
+const SkColor kBaseGradient1 = SkColorSetRGB(255, 255, 255);
+const SkColor kBaseGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8);
+
+const SkColor kPressedGradient0 = SkColorSetRGB(0x95, 0x95, 0x95);
+const SkColor kPressedGradient1 = SkColorSetRGB(0xE3, 0xE3, 0xE3);
+
+const SkColor kIndicatorStrokeDisabledColor = SkColorSetRGB(0xB4, 0xB4, 0xB4);
+// TODO: these are wrong, what should they be?
+const SkColor kIndicatorStrokePressedColor = SkColorSetRGB(0, 0, 0);
+const SkColor kIndicatorStrokeColor = SkColorSetRGB(0, 0, 0);
+
+const SkColor kRadioIndicatorGradient0 = SkColorSetRGB(0, 0, 0);
+const SkColor kRadioIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83);
+
+const SkColor kRadioIndicatorDisabledGradient0 =
+    SkColorSetRGB(0xB4, 0xB4, 0xB4);
+const SkColor kRadioIndicatorDisabledGradient1 =
+    SkColorSetRGB(0xB7, 0xB7, 0xB7);
+
+// Progressbar colors
+const SkColor kProgressBarBackgroundGradient0 = SkColorSetRGB(0xBB, 0xBB, 0xBB);
+const SkColor kProgressBarBackgroundGradient1 = SkColorSetRGB(0xE7, 0xE7, 0xE7);
+const SkColor kProgressBarBackgroundGradient2 = SkColorSetRGB(0xFE, 0xFE, 0xFE);
+const SkColor kProgressBarBorderStroke = SkColorSetRGB(0xA1, 0xA1, 0xA1);
+
+const SkColor kProgressBarIndicatorGradient0 = SkColorSetRGB(100, 116, 147);
+const SkColor kProgressBarIndicatorGradient1 = SkColorSetRGB(65, 73, 87);
+
+const SkColor kProgressBarIndicatorDisabledGradient0 =
+    SkColorSetRGB(229, 232, 237);
+const SkColor kProgressBarIndicatorDisabledGradient1 =
+    SkColorSetRGB(224, 225, 227);
+
+const SkColor kProgressBarIndicatorStroke = SkColorSetRGB(0x4A, 0x4A, 0x4A);
+const SkColor kProgressBarIndicatorDisabledStroke =
+    SkColorSetARGB(0x80, 0x4A, 0x4A, 0x4A);
+
+const SkColor kProgressBarIndicatorInnerStroke =
+    SkColorSetARGB(0x3F, 0xFF, 0xFF, 0xFF);  // 0.25 white
+const SkColor kProgressBarIndicatorInnerShadow =
+    SkColorSetARGB(0x54, 0xFF, 0xFF, 0xFF);  // 0.33 white
+
+// Geometry constants
+
+const int kBorderCornerRadius = 3;
+
+const int kRadioIndicatorSize = 7;
+
+const int kSliderThumbWidth = 16;
+const int kSliderThumbHeight = 16;
+const int kSliderTrackSize = 6;
+
+void GetRoundRectPathWithPadding(const gfx::Rect rect,
+                                 int corner_radius,
+                                 SkScalar padding,
+                                 SkPath* path) {
+  SkRect bounds = { SkDoubleToScalar(rect.x()) + padding,
+                    SkDoubleToScalar(rect.y()) + padding,
+                    SkDoubleToScalar(rect.right()) - padding,
+                    SkDoubleToScalar(rect.bottom()) - padding };
+  path->addRoundRect(bounds,
+                     SkIntToScalar(corner_radius) - padding,
+                     SkIntToScalar(corner_radius) - padding);
 }
 
-void DrawBitmapInt(
-    skia::PlatformCanvas* canvas, const SkBitmap& bitmap,
-    int src_x, int src_y, int src_w, int src_h,
-    int dest_x, int dest_y, int dest_w, int dest_h) {
-  DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() &&
-              src_y + src_h < std::numeric_limits<int16_t>::max());
-  if (src_w <= 0 || src_h <= 0 || dest_w <= 0 || dest_h <= 0) {
-    NOTREACHED() << "Attempting to draw bitmap to/from an empty rect!";
-    return;
-  }
+void GetRoundRectPath(const gfx::Rect rect,
+                      int corner_radius,
+                      SkPath* path) {
+  // Add 0.5 pixel padding so that antialias paint does not touch extra pixels.
+  GetRoundRectPathWithPadding(rect, corner_radius, SkIntToScalar(1) / 2,
+                              path);
+}
 
-  if (!IntersectsClipRectInt(canvas, dest_x, dest_y, dest_w, dest_h))
-    return;
+void GetGradientPaintForRect(const gfx::Rect& rect,
+                             const SkColor* colors,
+                             const SkScalar* stops,
+                             int count,
+                             SkPaint* paint) {
+  paint->setStyle(SkPaint::kFill_Style);
+  paint->setAntiAlias(true);
 
-  SkRect dest_rect = { SkIntToScalar(dest_x),
-                       SkIntToScalar(dest_y),
-                       SkIntToScalar(dest_x + dest_w),
-                       SkIntToScalar(dest_y + dest_h) };
+  SkPoint points[2];
+  points[0].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
+  points[1].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.bottom()));
 
-  if (src_w == dest_w && src_h == dest_h) {
-    // Workaround for apparent bug in Skia that causes image to occasionally
-    // shift.
-    SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
-    canvas->drawBitmapRect(bitmap, &src_rect, dest_rect);
-    return;
-  }
+  SkShader* shader = SkGradientShader::CreateLinear(points,
+      colors, stops, count, SkShader::kClamp_TileMode);
 
-  // Make a bitmap shader that contains the bitmap we want to draw. This is
-  // basically what SkCanvas.drawBitmap does internally, but it gives us
-  // more control over quality and will use the mipmap in the source image if
-  // it has one, whereas drawBitmap won't.
-  SkShader* shader = SkShader::CreateBitmapShader(bitmap,
-                                                  SkShader::kRepeat_TileMode,
-                                                  SkShader::kRepeat_TileMode);
-  SkMatrix shader_scale;
-  shader_scale.setScale(SkFloatToScalar(static_cast<float>(dest_w) / src_w),
-                        SkFloatToScalar(static_cast<float>(dest_h) / src_h));
-  shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
-  shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
-  shader->setLocalMatrix(shader_scale);
-
-  // The rect will be filled by the bitmap.
-  SkPaint p;
-  p.setFilterBitmap(true);
-  p.setShader(shader);
+  paint->setShader(shader);
+  // Unref shader after paint takes ownership, otherwise never deleted.
   shader->unref();
-  canvas->drawRect(dest_rect, p);
+}
+
+void GetGradientPaintForRect(const gfx::Rect& rect,
+                             SkColor start_color,
+                             SkColor end_color,
+                             SkPaint* paint) {
+  SkColor colors[2] = { start_color, end_color };
+  GetGradientPaintForRect(rect, colors, NULL, 2, paint);
+}
+
+void GetButtonGradientPaint(const gfx::Rect bounds,
+                            gfx::NativeThemeLinux::State state,
+                            SkPaint* paint) {
+  if (state == gfx::NativeThemeLinux::kPressed) {
+    static const SkColor kGradientColors[2] = {
+        kPressedGradient0,
+        kPressedGradient1
+    };
+
+    static const SkScalar kGradientPoints[2] = {
+        SkIntToScalar(0),
+        SkIntToScalar(1)
+    };
+
+    GetGradientPaintForRect(bounds,
+        kGradientColors, kGradientPoints, arraysize(kGradientPoints),
+        paint);
+  } else {
+    static const SkColor kGradientColors[3] = {
+        kBaseGradient0,
+        kBaseGradient1,
+        kBaseGradient2
+    };
+
+    static const SkScalar kGradientPoints[3] = {
+        SkIntToScalar(0),
+        SkDoubleToScalar(0.5),
+        SkIntToScalar(1)
+    };
+
+    GetGradientPaintForRect(bounds,
+        kGradientColors, kGradientPoints, arraysize(kGradientPoints),
+        paint);
+  }
+}
+
+void GetStrokePaint(SkColor color, SkPaint* paint) {
+  paint->setStyle(SkPaint::kStroke_Style);
+  paint->setAntiAlias(true);
+  paint->setColor(color);
+}
+
+void GetStrokePaint(gfx::NativeThemeLinux::State state, SkPaint* paint) {
+
+  if (state == gfx::NativeThemeLinux::kDisabled)
+    GetStrokePaint(kDisabledBaseStroke, paint);
+  else
+    GetStrokePaint(kBaseStroke, paint);
+}
+
+void GetIndicatorStrokePaint(gfx::NativeThemeLinux::State state,
+                             SkPaint* paint) {
+  paint->setStyle(SkPaint::kStroke_Style);
+  paint->setAntiAlias(true);
+
+  if (state == gfx::NativeThemeLinux::kDisabled)
+    paint->setColor(kIndicatorStrokeDisabledColor);
+  else if (state == gfx::NativeThemeLinux::kPressed)
+    paint->setColor(kIndicatorStrokePressedColor);
+  else
+    paint->setColor(kIndicatorStrokeColor);
+}
+
+void GetRadioIndicatorGradientPaint(const gfx::Rect bounds,
+                                    gfx::NativeThemeLinux::State state,
+                                    SkPaint* paint) {
+  paint->setStyle(SkPaint::kFill_Style);
+  paint->setAntiAlias(true);
+
+  SkPoint points[2];
+  points[0].set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
+  points[1].set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.bottom()));
+
+  static const SkScalar kGradientPoints[2] = {
+      SkIntToScalar(0),
+      SkIntToScalar(1)
+  };
+
+  if (state == gfx::NativeThemeLinux::kDisabled) {
+    static const SkColor kGradientColors[2] = {
+        kRadioIndicatorDisabledGradient0,
+        kRadioIndicatorDisabledGradient1
+    };
+
+    GetGradientPaintForRect(bounds,
+        kGradientColors, kGradientPoints, arraysize(kGradientPoints),
+        paint);
+  } else {
+    static const SkColor kGradientColors[2] = {
+        kRadioIndicatorGradient0,
+        kRadioIndicatorGradient1
+    };
+
+    GetGradientPaintForRect(bounds,
+        kGradientColors, kGradientPoints, arraysize(kGradientPoints),
+        paint);
+  }
 }
 
 }
@@ -89,7 +243,7 @@
 NativeThemeChromeos::~NativeThemeChromeos() {
 }
 
-gfx::Size NativeThemeChromeos::GetSize(Part part) const {
+gfx::Size NativeThemeChromeos::GetPartSize(Part part) const {
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
   int scrollbar_width = rb.GetBitmapNamed(IDR_SCROLL_BACKGROUND)->width();
   int width = 0, height = 0;
@@ -124,11 +278,19 @@
       width = scrollbar_width;
       height = scrollbar_width;
       break;
+    case kSliderThumb:
+      width = kSliderThumbWidth;
+      height = kSliderThumbHeight;
+      break;
+    case kInnerSpinButton:
+      return gfx::Size(scrollbar_width, 0);
+    default:
+      return NativeThemeLinux::GetPartSize(part);
   }
   return gfx::Size(width, height);
 }
 
-void NativeThemeChromeos::PaintTrack(skia::PlatformCanvas* canvas,
+void NativeThemeChromeos::PaintScrollbarTrack(skia::PlatformCanvas* canvas,
     Part part, State state,
     const ScrollbarTrackExtraParams& extra_params, const gfx::Rect& rect) {
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
@@ -174,11 +336,11 @@
   }
 }
 
-void NativeThemeChromeos::PaintThumb(skia::PlatformCanvas* canvas,
+void NativeThemeChromeos::PaintScrollbarThumb(skia::PlatformCanvas* canvas,
     Part part, State state, const gfx::Rect& rect) {
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
   int resource_id = IDR_SCROLL_THUMB;
-  if (state == kHover)
+  if (state == kHovered)
     resource_id++;
   else if (state == kPressed)
     resource_id += 2;
@@ -225,7 +387,7 @@
   int resource_id =
       (part == kScrollbarUpArrow || part == kScrollbarLeftArrow) ?
           IDR_SCROLL_ARROW_UP : IDR_SCROLL_ARROW_DOWN;
-  if (state == kHover)
+  if (state == kHovered)
     resource_id++;
   else if (state == kPressed)
     resource_id += 2;
@@ -234,7 +396,280 @@
     bitmap = rb.GetBitmapNamed(resource_id);
   else
     bitmap = GetHorizontalBitmapNamed(resource_id);
-  canvas->drawBitmap(*bitmap, rect.x(), rect.y());
+  DrawBitmapInt(canvas, *bitmap,
+      0, 0, bitmap->width(), bitmap->height(),
+      rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+void NativeThemeChromeos::PaintCheckbox(skia::PlatformCanvas* canvas,
+    State state, const gfx::Rect& rect,
+    const ButtonExtraParams& button) {
+  PaintButtonLike(canvas, state, rect, button);
+
+  if (button.checked) {
+    SkPaint indicator_paint;
+    GetIndicatorStrokePaint(state, &indicator_paint);
+    indicator_paint.setStrokeWidth(2);
+
+    const int kMidX = rect.x() + rect.width() / 2;
+    const int kMidY = rect.y() + rect.height() / 2;
+    canvas->drawLine(SkIntToScalar(rect.x() + 3), SkIntToScalar(kMidY),
+        SkIntToScalar(kMidX - 1), SkIntToScalar(rect.bottom() - 3),
+        indicator_paint);
+    canvas->drawLine(SkIntToScalar(kMidX - 1), SkIntToScalar(rect.bottom() - 3),
+        SkIntToScalar(rect.right() - 3), SkIntToScalar(rect.y() + 3),
+        indicator_paint);
+  }
+}
+
+void NativeThemeChromeos::PaintRadio(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const ButtonExtraParams& button) {
+  gfx::Point center = rect.CenterPoint();
+  SkPath border;
+  border.addCircle(SkIntToScalar(center.x()), SkIntToScalar(center.y()),
+                   SkDoubleToScalar(rect.width() / 2.0));
+
+  SkPaint fill_paint;
+  GetButtonGradientPaint(rect, state, &fill_paint);
+  canvas->drawPath(border, fill_paint);
+
+  SkPaint stroke_paint;
+  GetStrokePaint(state, &stroke_paint);
+  canvas->drawPath(border, stroke_paint);
+
+  if (button.checked) {
+    SkPath indicator_border;
+    indicator_border.addCircle(SkIntToScalar(center.x()),
+                               SkIntToScalar(center.y()),
+                               SkDoubleToScalar(kRadioIndicatorSize / 2.0));
+
+    SkPaint indicator_fill_paint;
+    GetRadioIndicatorGradientPaint(rect, state, &indicator_fill_paint);
+    canvas->drawPath(indicator_border, indicator_fill_paint);
+
+    SkPaint indicator_paint;
+    GetIndicatorStrokePaint(state, &indicator_paint);
+    canvas->drawPath(indicator_border, indicator_paint);
+  }
+}
+
+void NativeThemeChromeos::PaintButton(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const ButtonExtraParams& button) {
+  PaintButtonLike(canvas, state, rect, button);
+}
+
+void NativeThemeChromeos::PaintTextField(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const TextFieldExtraParams& text) {
+  if (rect.height() == 0)
+    return;
+
+  SkColor background_color = text.background_color;
+
+  SkPaint fill_paint;
+  fill_paint.setStyle(SkPaint::kFill_Style);
+  if (state == kDisabled) {
+    fill_paint.setColor(background_color);
+  } else {
+    SkScalar base_hsv[3];
+    SkColorToHSV(background_color, base_hsv);
+
+    const SkColor gradient_colors[3] = {
+        SaturateAndBrighten(base_hsv, 0, -0.18),
+        background_color,
+        background_color
+    };
+
+    const SkScalar gradient_points[3] = {
+        SkIntToScalar(0),
+        SkDoubleToScalar(4.0 / rect.height()),
+        SkIntToScalar(1)
+    };
+
+    SkPoint points[2];
+    points[0].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
+    points[1].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.bottom()));
+
+    GetGradientPaintForRect(rect,
+        gradient_colors, gradient_points, arraysize(gradient_points),
+        &fill_paint);
+  }
+
+  SkPath border;
+  GetRoundRectPath(rect, kBorderCornerRadius, &border);
+  canvas->drawPath(border, fill_paint);
+
+  SkPaint stroke_paint;
+  GetStrokePaint(state, &stroke_paint);
+  canvas->drawPath(border, stroke_paint);
+}
+
+void NativeThemeChromeos::PaintSliderTrack(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const SliderExtraParams& slider) {
+  const int kMidX = rect.x() + rect.width() / 2;
+  const int kMidY = rect.y() + rect.height() / 2;
+
+  gfx::Rect track_bounds;
+  if (slider.vertical) {
+    track_bounds.SetRect(std::max(rect.x(), kMidX - kSliderTrackSize / 2),
+                         rect.y(),
+                         std::min(rect.width(), kSliderTrackSize),
+                         rect.height());
+  } else {
+    track_bounds.SetRect(rect.x(),
+                         std::max(rect.y(), kMidY - kSliderTrackSize / 2),
+                         rect.width(),
+                         std::min(rect.height(), kSliderTrackSize));
+  }
+
+  SkPath border;
+  GetRoundRectPath(track_bounds, kBorderCornerRadius, &border);
+
+  SkPaint fill_paint;
+  // Use normal button background.
+  GetButtonGradientPaint(rect, kNormal, &fill_paint);
+  canvas->drawPath(border, fill_paint);
+
+  SkPaint stroke_paint;
+  GetStrokePaint(state, &stroke_paint);
+  canvas->drawPath(border, stroke_paint);
+}
+
+void NativeThemeChromeos::PaintSliderThumb(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const SliderExtraParams& slider) {
+  if (state != kDisabled && slider.in_drag)
+    state = kPressed;
+
+  ButtonExtraParams button = { 0 };
+  PaintButtonLike(canvas, state, rect, button);
+}
+
+void NativeThemeChromeos::PaintInnerSpinButton(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const InnerSpinButtonExtraParams& spin_button) {
+  // Adjust bounds to compensate the overridden "2px inset" parent border.
+  gfx::Rect bounds = rect;
+  bounds.Inset(0, -1, -1, -1);
+
+  NativeThemeLinux::PaintInnerSpinButton(canvas, state, bounds, spin_button);
+}
+
+void NativeThemeChromeos::PaintProgressBar(skia::PlatformCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const ProgressBarExtraParams& progress_bar) {
+  static const int kBorderWidth = 1;
+  static const SkColor kBackgroundColors[] = {
+    kProgressBarBackgroundGradient0,
+    kProgressBarBackgroundGradient1,
+    kProgressBarBackgroundGradient2
+  };
+
+  static const SkScalar kBackgroundPoints[] = {
+    SkDoubleToScalar(0),
+    SkDoubleToScalar(0.1),
+    SkDoubleToScalar(1)
+  };
+  static const SkColor kBackgroundBorderColor = kProgressBarBorderStroke;
+
+  // Draw background.
+  SkPath border;
+  GetRoundRectPath(rect, kBorderCornerRadius, &border);
+
+  SkPaint fill_paint;
+  GetGradientPaintForRect(rect,
+      kBackgroundColors, kBackgroundPoints, arraysize(kBackgroundPoints),
+      &fill_paint);
+  canvas->drawPath(border, fill_paint);
+
+  SkPaint stroke_paint;
+  GetStrokePaint(kBackgroundBorderColor, &stroke_paint);
+  canvas->drawPath(border, stroke_paint);
+
+  if (progress_bar.value_rect_width > 1) {
+    bool enabled = state != kDisabled;
+    gfx::Rect value_rect(progress_bar.value_rect_x,
+                         progress_bar.value_rect_y,
+                         progress_bar.value_rect_width,
+                         progress_bar.value_rect_height);
+
+    const SkColor bar_color_start = enabled ?
+        kProgressBarIndicatorGradient0 :
+        kProgressBarIndicatorDisabledGradient0;
+    const SkColor bar_color_end = enabled ?
+        kProgressBarIndicatorGradient1 :
+        kProgressBarIndicatorDisabledGradient1;
+
+    const SkColor bar_outer_color = enabled ?
+        kProgressBarIndicatorStroke :
+        kProgressBarIndicatorDisabledStroke;
+
+    const SkColor bar_inner_border_color = kProgressBarIndicatorInnerStroke;
+    const SkColor bar_inner_shadow_color = kProgressBarIndicatorInnerShadow;
+
+    // Draw bar background
+    SkPath value_border;
+    GetRoundRectPath(value_rect, kBorderCornerRadius, &value_border);
+
+    SkPaint value_fill_paint;
+    GetGradientPaintForRect(rect,bar_color_start, bar_color_end,
+        &value_fill_paint);
+    canvas->drawPath(value_border, value_fill_paint);
+
+    // Draw inner stroke and shadow if wide enough.
+    if (progress_bar.value_rect_width > 2 * kBorderWidth) {
+      canvas->save();
+
+      SkPath inner_path;
+      GetRoundRectPathWithPadding(value_rect, kBorderCornerRadius,
+          SkIntToScalar(kBorderWidth), &inner_path);
+      canvas->clipPath(inner_path);
+
+      // Draw bar inner stroke
+      gfx::Rect inner_stroke_rect = value_rect;
+      inner_stroke_rect.Inset(kBorderWidth, kBorderWidth);
+
+      SkPath inner_stroke_path;
+      GetRoundRectPath(inner_stroke_rect, kBorderCornerRadius - kBorderWidth,
+          &inner_stroke_path);
+
+      SkPaint inner_stroke_paint;
+      GetStrokePaint(bar_inner_border_color, &inner_stroke_paint);
+
+      canvas->drawPath(inner_stroke_path, inner_stroke_paint);
+
+      // Draw bar inner shadow
+      gfx::Rect inner_shadow_rect(progress_bar.value_rect_x,
+          progress_bar.value_rect_y + kBorderWidth,
+          progress_bar.value_rect_width,
+          progress_bar.value_rect_height);
+      SkPath inner_shadow_path;
+      GetRoundRectPath(inner_shadow_rect, kBorderCornerRadius,
+          &inner_shadow_path);
+
+      SkPaint inner_shadow_paint;
+      GetStrokePaint(bar_inner_shadow_color, &inner_shadow_paint);
+
+      canvas->drawPath(inner_shadow_path, inner_shadow_paint);
+
+      canvas->restore();
+    }
+
+    // Draw bar stroke
+    SkPaint value_stroke_paint;
+    GetStrokePaint(bar_outer_color, &value_stroke_paint);
+    canvas->drawPath(value_border, value_stroke_paint);
+  }
 }
 
 SkBitmap* NativeThemeChromeos::GetHorizontalBitmapNamed(int resource_id) {
@@ -256,3 +691,17 @@
   return NULL;
 }
 
+void NativeThemeChromeos::PaintButtonLike(skia::PlatformCanvas* canvas,
+    State state, const gfx::Rect& rect,
+    const ButtonExtraParams& button) {
+  SkPath border;
+  GetRoundRectPath(rect, kBorderCornerRadius, &border);
+
+  SkPaint fill_paint;
+  GetButtonGradientPaint(rect, state, &fill_paint);
+  canvas->drawPath(border, fill_paint);
+
+  SkPaint stroke_paint;
+  GetStrokePaint(state, &stroke_paint);
+  canvas->drawPath(border, stroke_paint);
+}
diff --git a/chrome/browser/chromeos/native_theme_chromeos.h b/chrome/browser/chromeos/native_theme_chromeos.h
index d501f68..133065d 100644
--- a/chrome/browser/chromeos/native_theme_chromeos.h
+++ b/chrome/browser/chromeos/native_theme_chromeos.h
@@ -6,7 +6,8 @@
 #define CHROME_BROWSER_CHROMEOS_NATIVE_THEME_CHROMEOS_H_
 
 #include <map>
-#include "gfx/native_theme_linux.h"
+#include "base/compiler_specific.h"
+#include "ui/gfx/native_theme_linux.h"
 
 class SkBitmap;
 
@@ -17,17 +18,70 @@
   virtual ~NativeThemeChromeos();
 
   // Scrollbar painting overrides
-  virtual gfx::Size GetSize(Part part) const;
-  virtual void PaintTrack(skia::PlatformCanvas* canvas,
+  virtual gfx::Size GetPartSize(Part part) const OVERRIDE;
+  virtual void PaintScrollbarTrack(skia::PlatformCanvas* canvas,
       Part part, State state,
       const ScrollbarTrackExtraParams& extra_params,
-      const gfx::Rect& rect);
+      const gfx::Rect& rect) OVERRIDE;
   virtual void PaintArrowButton(skia::PlatformCanvas* canvas,
-      const gfx::Rect& rect, Part direction, State state);
-  virtual void PaintThumb(skia::PlatformCanvas* canvas,
-      Part part, State state, const gfx::Rect& rect);
+      const gfx::Rect& rect, Part direction, State state) OVERRIDE;
+  virtual void PaintScrollbarThumb(skia::PlatformCanvas* canvas,
+      Part part, State state, const gfx::Rect& rect) OVERRIDE;
+
+  // Draw the checkbox.
+  virtual void PaintCheckbox(skia::PlatformCanvas* canvas,
+      State state, const gfx::Rect& rect,
+      const ButtonExtraParams& button) OVERRIDE;
+
+  // Draw the radio.
+  virtual void PaintRadio(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const ButtonExtraParams& button) OVERRIDE;
+
+  // Draw the push button.
+  virtual void PaintButton(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const ButtonExtraParams& button) OVERRIDE;
+
+  // Draw the text field.
+  virtual void PaintTextField(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const TextFieldExtraParams& text) OVERRIDE;
+
+  // Draw the slider track.
+  virtual void PaintSliderTrack(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const SliderExtraParams& slider) OVERRIDE;
+
+  // Draw the slider thumb.
+  virtual void PaintSliderThumb(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const SliderExtraParams& slider) OVERRIDE;
+
+  // Draw the inner spin button.
+  virtual void PaintInnerSpinButton(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const InnerSpinButtonExtraParams& spin_button) OVERRIDE;
+
+  // Draw the progress bar.
+  virtual void PaintProgressBar(skia::PlatformCanvas* canvas,
+      State state,
+      const gfx::Rect& rect,
+      const ProgressBarExtraParams& progress_bar) OVERRIDE;
+
   SkBitmap* GetHorizontalBitmapNamed(int resource_id);
 
+  // Paint a button like rounded rect with gradient background and stroke.
+  void PaintButtonLike(skia::PlatformCanvas* canvas,
+      State state, const gfx::Rect& rect,
+      const ButtonExtraParams& button);
+
   // Cached images. The ResourceBundle caches all retrieved bitmaps and keeps
   // ownership of the pointers.
   typedef std::map<int, SkBitmap*> SkImageMap;
diff --git a/chrome/browser/chromeos/network_list.cc b/chrome/browser/chromeos/network_list.cc
index c22795b..89cff35 100644
--- a/chrome/browser/chromeos/network_list.cc
+++ b/chrome/browser/chromeos/network_list.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/chromeos/network_list.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/network_login_observer.cc b/chrome/browser/chromeos/network_login_observer.cc
new file mode 100644
index 0000000..65b70b0
--- /dev/null
+++ b/chrome/browser/chromeos/network_login_observer.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/network_login_observer.h"
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
+#include "chrome/browser/chromeos/login/background_view.h"
+#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/options/network_config_view.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/window.h"
+#include "views/window/dialog_delegate.h"
+#include "views/window/window.h"
+
+namespace chromeos {
+
+NetworkLoginObserver::NetworkLoginObserver(NetworkLibrary* netlib) {
+  RefreshStoredNetworks(netlib->wifi_networks());
+  netlib->AddNetworkManagerObserver(this);
+}
+
+NetworkLoginObserver::~NetworkLoginObserver() {
+  CrosLibrary::Get()->GetNetworkLibrary()->RemoveNetworkManagerObserver(this);
+}
+
+void NetworkLoginObserver::CreateModalPopup(views::WindowDelegate* view) {
+  Browser* browser = BrowserList::GetLastActive();
+  if (browser && browser->type() != Browser::TYPE_NORMAL) {
+    browser = BrowserList::FindBrowserWithType(browser->profile(),
+                                               Browser::TYPE_NORMAL,
+                                               true);
+  }
+  if (browser) {
+    views::Window* window = browser::CreateViewsWindow(
+        browser->window()->GetNativeHandle(), gfx::Rect(), view);
+    window->SetIsAlwaysOnTop(true);
+    window->Show();
+  } else {
+    // Browser not found, so we should be in login/oobe screen.
+    BackgroundView* background_view = LoginUtils::Get()->GetBackgroundView();
+    if (background_view) {
+      background_view->CreateModalPopup(view);
+    }
+  }
+}
+
+void NetworkLoginObserver::RefreshStoredNetworks(
+    const WifiNetworkVector& wifi_networks) {
+  wifi_network_failures_.clear();
+  for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
+       it < wifi_networks.end(); it++) {
+    const WifiNetwork* wifi = *it;
+    wifi_network_failures_[wifi->service_path()] = wifi->failed();
+  }
+}
+
+void NetworkLoginObserver::OnNetworkManagerChanged(NetworkLibrary* obj) {
+  const WifiNetworkVector& wifi_networks = obj->wifi_networks();
+
+  NetworkConfigView* view = NULL;
+  // Check to see if we have any newly failed wifi network.
+  for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
+       it < wifi_networks.end(); it++) {
+    const WifiNetwork* wifi = *it;
+    if (wifi->failed()) {
+      WifiFailureMap::iterator iter =
+          wifi_network_failures_.find(wifi->service_path());
+      // If the network did not previously exist, then don't do anything.
+      // For example, if the user travels to a location and finds a service
+      // that has previously failed, we don't want to show an error.
+      if (iter == wifi_network_failures_.end())
+        continue;
+
+      // If this network was in a failed state previously, then it's not new.
+      if (iter->second)
+        continue;
+
+      // Display login box again for bad_passphrase and bad_wepkey errors.
+      if (wifi->error() == ERROR_BAD_PASSPHRASE ||
+          wifi->error() == ERROR_BAD_WEPKEY) {
+        // The NetworkConfigView will show the appropriate error message.
+        view = new NetworkConfigView(wifi);
+        // There should only be one wifi network that failed to connect.
+        // If for some reason, we have more than one failure,
+        // we only display the first one. So we break here.
+        break;
+      }
+    }
+  }
+
+  RefreshStoredNetworks(wifi_networks);
+
+  // Show login box if necessary.
+  if (view)
+    CreateModalPopup(view);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/network_login_observer.h b/chrome/browser/chromeos/network_login_observer.h
new file mode 100644
index 0000000..0c5df5f
--- /dev/null
+++ b/chrome/browser/chromeos/network_login_observer.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_LOGIN_OBSERVER_H_
+#define CHROME_BROWSER_CHROMEOS_NETWORK_LOGIN_OBSERVER_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
+
+namespace views {
+class WindowDelegate;
+}
+
+namespace chromeos {
+
+// The network login observer reshows a login dialog if there was an error.
+
+class NetworkLoginObserver : public NetworkLibrary::NetworkManagerObserver {
+ public:
+  explicit NetworkLoginObserver(NetworkLibrary* netlib);
+  virtual ~NetworkLoginObserver();
+
+  typedef std::map<std::string, bool> WifiFailureMap;
+ private:
+  virtual void CreateModalPopup(views::WindowDelegate* view);
+
+  virtual void RefreshStoredNetworks(const WifiNetworkVector& wifi_networks);
+
+  // NetworkLibrary::NetworkManagerObserver implementation.
+  virtual void OnNetworkManagerChanged(NetworkLibrary* obj);
+
+  // Wifi networks by service path mapped to if it failed previously.
+  WifiFailureMap wifi_network_failures_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkLoginObserver);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_NETWORK_LOGIN_OBSERVER_H_
diff --git a/chrome/browser/chromeos/network_message_observer.cc b/chrome/browser/chromeos/network_message_observer.cc
index 872dc73..9355c01 100644
--- a/chrome/browser/chromeos/network_message_observer.cc
+++ b/chrome/browser/chromeos/network_message_observer.cc
@@ -1,30 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/network_message_observer.h"
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/stl_util-inl.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_window.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/notifications/balloon_view_host.h"
-#include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/window.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/time_format.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "views/window/dialog_delegate.h"
-#include "views/window/window.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -44,8 +39,7 @@
 namespace chromeos {
 
 NetworkMessageObserver::NetworkMessageObserver(Profile* profile)
-    : initialized_(false),
-      notification_connection_error_(profile, "network_connection.chromeos",
+    : notification_connection_error_(profile, "network_connection.chromeos",
           IDR_NOTIFICATION_NETWORK_FAILED,
           l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE)),
       notification_low_data_(profile, "network_low_data.chromeos",
@@ -58,7 +52,6 @@
   OnNetworkManagerChanged(netlib);
   // Note that this gets added as a NetworkManagerObserver and a
   // CellularDataPlanObserver in browser_init.cc
-  initialized_ = true;
 }
 
 NetworkMessageObserver::~NetworkMessageObserver() {
@@ -72,18 +65,19 @@
   STLDeleteValues(&wifi_networks_);
 }
 
-void NetworkMessageObserver::CreateModalPopup(views::WindowDelegate* view) {
-  Browser* browser = BrowserList::GetLastActive();
-  if (browser && browser->type() != Browser::TYPE_NORMAL) {
-    browser = BrowserList::FindBrowserWithType(browser->profile(),
-                                               Browser::TYPE_NORMAL,
-                                               true);
-  }
-  DCHECK(browser);
-  views::Window* window = browser::CreateViewsWindow(
-      browser->window()->GetNativeHandle(), gfx::Rect(), view);
-  window->SetIsAlwaysOnTop(true);
-  window->Show();
+// static
+bool NetworkMessageObserver::IsApplicableBackupPlan(
+    const CellularDataPlan* plan, const CellularDataPlan* other_plan) {
+  // By applicable plan, we mean that the other plan has data AND the timeframe
+  // will apply: (unlimited OR used bytes < max bytes) AND
+  //   ((start time - 1 sec) <= end time of currently active plan).
+  // In other words, there is data available and there is no gap of more than a
+  // second in time between the old plan and the new plan.
+  bool has_data = other_plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED ||
+      other_plan->remaining_data() > 0;
+  bool will_apply =
+      (other_plan->plan_start_time - plan->plan_end_time).InSeconds() <= 1;
+  return has_data && will_apply;
 }
 
 void NetworkMessageObserver::OpenMobileSetupPage(const ListValue* args) {
@@ -104,11 +98,62 @@
   browser->ShowSingletonTab(GURL(cellular->payment_url()), false);
 }
 
+void NetworkMessageObserver::HideDataNotifications() {
+  notification_low_data_.Hide();
+  notification_no_data_.Hide();
+}
+
+void NetworkMessageObserver::InitNewPlan(const CellularDataPlan* plan) {
+  HideDataNotifications();
+  if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
+    notification_no_data_.set_title(
+        l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_EXPIRED_TITLE,
+                                   ASCIIToUTF16(plan->plan_name)));
+    notification_low_data_.set_title(
+        l10n_util::GetStringFUTF16(IDS_NETWORK_NEARING_EXPIRATION_TITLE,
+                                   ASCIIToUTF16(plan->plan_name)));
+  } else {
+    notification_no_data_.set_title(
+        l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE,
+                                   ASCIIToUTF16(plan->plan_name)));
+    notification_low_data_.set_title(
+        l10n_util::GetStringFUTF16(IDS_NETWORK_LOW_DATA_TITLE,
+                                   ASCIIToUTF16(plan->plan_name)));
+  }
+}
+
+void NetworkMessageObserver::ShowNoDataNotification(
+    const CellularDataPlan* plan) {
+  notification_low_data_.Hide();
+  string16 message =
+      plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED ?
+          TimeFormat::TimeRemaining(base::TimeDelta()) :
+          l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
+                                     ASCIIToUTF16("0"));
+  notification_no_data_.Show(message,
+      l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
+      NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage),
+      false, false);
+}
+
+void NetworkMessageObserver::ShowLowDataNotification(
+    const CellularDataPlan* plan) {
+  notification_no_data_.Hide();
+  string16 message =
+      plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED ?
+          plan->GetPlanExpiration() :
+          l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
+               UTF8ToUTF16(base::Int64ToString(plan->remaining_mbytes())));
+  notification_low_data_.Show(message,
+      l10n_util::GetStringUTF16(IDS_NETWORK_MORE_INFO_MESSAGE),
+      NewCallback(this, &NetworkMessageObserver::OpenMoreInfoPage),
+      false, false);
+}
+
 void NetworkMessageObserver::OnNetworkManagerChanged(NetworkLibrary* obj) {
   const WifiNetworkVector& wifi_networks = obj->wifi_networks();
   const CellularNetworkVector& cellular_networks = obj->cellular_networks();
 
-  NetworkConfigView* view = NULL;
   std::string new_failed_network;
   // Check to see if we have any newly failed wifi network.
   for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
@@ -124,21 +169,6 @@
         continue;
 
       const WifiNetwork* wifi_old = iter->second;
-      // If this network was in a failed state previously, then it's not new.
-      if (wifi_old->failed())
-        continue;
-
-      // Display login box again for bad_passphrase and bad_wepkey errors.
-      if (wifi->error() == ERROR_BAD_PASSPHRASE ||
-          wifi->error() == ERROR_BAD_WEPKEY) {
-        // The NetworkConfigView will show the appropriate error message.
-        view = new NetworkConfigView(wifi);
-        // There should only be one wifi network that failed to connect.
-        // If for some reason, we have more than one failure,
-        // we only display the first one. So we break here.
-        break;
-      }
-
       // If network connection failed, display a notification.
       // We only do this if we were trying to make a new connection.
       // So if a previously connected network got disconnected for any reason,
@@ -183,46 +213,22 @@
         IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
         ASCIIToUTF16(new_failed_network)), false, false);
   }
-
-  // Show login box if necessary.
-  if (view && initialized_)
-    CreateModalPopup(view);
 }
 
 void NetworkMessageObserver::OnCellularDataPlanChanged(NetworkLibrary* obj) {
+  if (!ShouldShowMobilePlanNotifications()) {
+    HideDataNotifications();
+    return;
+  }
+
   const CellularNetwork* cellular = obj->cellular_network();
   if (!cellular)
     return;
-  const CellularDataPlan* plan = cellular->GetSignificantDataPlan();
-  std::string new_plan_name = plan ? plan->plan_name : "";
-  CellularDataPlanType new_plan_type = plan ? plan->plan_type :
-                                              CELLULAR_DATA_PLAN_UNKNOWN;
 
-  // If connected cellular network changed, or data plan is different, then
-  // it's a new network. Then hide all previous notifications.
-  bool new_plan = false;
-  if (cellular->service_path() != cellular_service_path_) {
-    cellular_service_path_ = cellular->service_path();
-    new_plan = true;
-  } else if (new_plan_name != cellular_data_plan_name_ ||
-      new_plan_type != cellular_data_plan_type_) {
-    new_plan = true;
-  }
-
-  cellular_data_plan_name_ = new_plan_name;
-  cellular_data_plan_type_ = new_plan_type;
-
-  bool should_show_notifications = ShouldShowMobilePlanNotifications();
-  if (!should_show_notifications) {
-    notification_low_data_.Hide();
-    notification_no_data_.Hide();
-    return;
-  }
-
-  if (new_plan) {
-    notification_low_data_.Hide();
-    notification_no_data_.Hide();
-    if (!plan && cellular->needs_new_plan()) {
+  // If no plans available, check to see if we need a new plan.
+  if (cellular->GetDataPlans().size() == 0) {
+    HideDataNotifications();
+    if (cellular->needs_new_plan()) {
       notification_no_data_.set_title(
           l10n_util::GetStringFUTF16(IDS_NETWORK_NO_DATA_PLAN_TITLE,
                                      UTF8ToUTF16(cellular->service_name())));
@@ -233,54 +239,44 @@
           l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
           NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage),
           false, false);
+    }
+    return;
+  }
+
+  const CellularDataPlanVector& plans = cellular->GetDataPlans();
+  CellularDataPlanVector::const_iterator iter = plans.begin();
+  const CellularDataPlan* current_plan = *iter;
+
+  // If current plan is not the last plan (there is another backup plan),
+  // then we do not show notifications for this plan.
+  // For example, if there is another data plan available when this runs out.
+  for (++iter; iter != plans.end(); ++iter) {
+    if (IsApplicableBackupPlan(current_plan, *iter)) {
+      HideDataNotifications();
       return;
-    } else if (cellular_data_plan_type_ == CELLULAR_DATA_PLAN_UNLIMITED) {
-      notification_no_data_.set_title(
-          l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_EXPIRED_TITLE,
-                                     ASCIIToUTF16(cellular_data_plan_name_)));
-      notification_low_data_.set_title(
-          l10n_util::GetStringFUTF16(IDS_NETWORK_NEARING_EXPIRATION_TITLE,
-                                     ASCIIToUTF16(cellular_data_plan_name_)));
-    } else {
-      notification_no_data_.set_title(
-          l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE,
-                                     ASCIIToUTF16(cellular_data_plan_name_)));
-      notification_low_data_.set_title(
-          l10n_util::GetStringFUTF16(IDS_NETWORK_LOW_DATA_TITLE,
-                                     ASCIIToUTF16(cellular_data_plan_name_)));
     }
   }
 
-  if (cellular_data_plan_type_ == CELLULAR_DATA_PLAN_UNKNOWN)
-    return;
+  // If connected cellular network changed, or data plan is different, then
+  // it's a new network. Then hide all previous notifications.
+  bool new_plan = cellular->service_path() != cellular_service_path_ ||
+      current_plan->GetUniqueIdentifier() != cellular_data_plan_unique_id_;
+
+  if (new_plan) {
+    InitNewPlan(current_plan);
+  }
 
   if (cellular->GetDataLeft() == CellularNetwork::DATA_NONE) {
-    notification_low_data_.Hide();
-    string16 message =
-        cellular_data_plan_type_ == CELLULAR_DATA_PLAN_UNLIMITED ?
-            TimeFormat::TimeRemaining(base::TimeDelta()) :
-            l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
-                                       ASCIIToUTF16("0"));
-    notification_no_data_.Show(message,
-        l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
-        NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage),
-        false, false);
+    ShowNoDataNotification(current_plan);
   } else if (cellular->GetDataLeft() == CellularNetwork::DATA_VERY_LOW) {
-    notification_no_data_.Hide();
-    string16 message =
-        cellular_data_plan_type_ == CELLULAR_DATA_PLAN_UNLIMITED ?
-            plan->GetPlanExpiration() :
-            l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
-                 UTF8ToUTF16(base::Int64ToString(plan->remaining_mbytes())));
-    notification_low_data_.Show(message,
-        l10n_util::GetStringUTF16(IDS_NETWORK_MORE_INFO_MESSAGE),
-        NewCallback(this, &NetworkMessageObserver::OpenMoreInfoPage),
-        false, false);
+    ShowLowDataNotification(current_plan);
   } else {
     // Got data, so hide notifications.
-    notification_low_data_.Hide();
-    notification_no_data_.Hide();
+    HideDataNotifications();
   }
+
+  cellular_service_path_ = cellular->service_path();
+  cellular_data_plan_unique_id_ = current_plan->GetUniqueIdentifier();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/network_message_observer.h b/chrome/browser/chromeos/network_message_observer.h
index 71bc1ab..4836e03 100644
--- a/chrome/browser/chromeos/network_message_observer.h
+++ b/chrome/browser/chromeos/network_message_observer.h
@@ -14,9 +14,6 @@
 #include "chrome/browser/chromeos/notifications/system_notification.h"
 
 class Profile;
-namespace views {
-class WindowDelegate;
-}
 
 namespace chromeos {
 
@@ -31,17 +28,21 @@
 
   typedef std::map<std::string, WifiNetwork*> ServicePathWifiMap;
   typedef std::map<std::string, CellularNetwork*> ServicePathCellularMap;
+  static bool IsApplicableBackupPlan(const CellularDataPlan* plan,
+                                     const CellularDataPlan* other_plan);
  private:
-  virtual void CreateModalPopup(views::WindowDelegate* view);
   virtual void OpenMobileSetupPage(const ListValue* args);
   virtual void OpenMoreInfoPage(const ListValue* args);
+  virtual void HideDataNotifications();
+  virtual void InitNewPlan(const CellularDataPlan* plan);
+  virtual void ShowNoDataNotification(const CellularDataPlan* plan);
+  virtual void ShowLowDataNotification(const CellularDataPlan* plan);
 
   // NetworkLibrary::NetworkManagerObserver implementation.
   virtual void OnNetworkManagerChanged(NetworkLibrary* obj);
   // NetworkLibrary::CellularDataPlanObserver implementation.
   virtual void OnCellularDataPlanChanged(NetworkLibrary* obj);
 
-  bool initialized_;
   // Wifi networks by service path.
   ServicePathWifiMap wifi_networks_;
   // Cellular networks by service path.
@@ -49,9 +50,8 @@
 
   // Current connect celluar service path.
   std::string cellular_service_path_;
-  // Last cellular data plan name and type.
-  std::string cellular_data_plan_name_;
-  CellularDataPlanType cellular_data_plan_type_;
+  // Last cellular data plan unique id.
+  std::string cellular_data_plan_unique_id_;
 
   // Notification for connection errors
   SystemNotification notification_connection_error_;
diff --git a/chrome/browser/chromeos/network_message_observer_unittest.cc b/chrome/browser/chromeos/network_message_observer_unittest.cc
new file mode 100644
index 0000000..a742696
--- /dev/null
+++ b/chrome/browser/chromeos/network_message_observer_unittest.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/network_message_observer.h"
+
+#include "base/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+CellularDataPlan CreateDataPlan(CellularDataPlanType type, int64 start_sec,
+                                int64 end_sec, int64 bytes, int64 used) {
+  CellularDataPlan plan;
+  plan.plan_type = type;
+  plan.plan_start_time = base::Time::FromDoubleT(start_sec);
+  plan.plan_end_time = base::Time::FromDoubleT(end_sec);
+  plan.plan_data_bytes = bytes;
+  plan.data_bytes_used = used;
+  return plan;
+}
+
+}  // namespace
+
+// Test the code that checks if a data plan is an applicable backup plan.
+TEST(NetworkMessageObserverTest, TestIsApplicableBackupPlan) {
+  // IsApplicableBackupPlan returns true if:
+  //   (unlimited OR used bytes < max bytes) AND
+  //   ((start time - 1 sec) <= end time of currently active plan).
+
+  // Current plan that ends at 100.
+  CellularDataPlan plan =
+      CreateDataPlan(CELLULAR_DATA_PLAN_UNLIMITED, 0, 100, 0, 0);
+
+  // Test unlimited plans.
+  CellularDataPlan time_50 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_UNLIMITED, 50, 500, 0, 0);
+  CellularDataPlan time_100 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_UNLIMITED, 100, 500, 0, 0);
+  CellularDataPlan time_101 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_UNLIMITED, 101, 500, 0, 0);
+  CellularDataPlan time_102 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_UNLIMITED, 102, 500, 0, 0);
+  EXPECT_TRUE(NetworkMessageObserver::IsApplicableBackupPlan(&plan, &time_50));
+  EXPECT_TRUE(NetworkMessageObserver::IsApplicableBackupPlan(&plan, &time_100));
+  EXPECT_TRUE(NetworkMessageObserver::IsApplicableBackupPlan(&plan, &time_101));
+  EXPECT_FALSE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                              &time_102));
+
+  // Test data plans.
+  CellularDataPlan data_0_0 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_METERED_PAID, 100, 500, 0, 0);
+  CellularDataPlan data_100_0 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_METERED_PAID, 100, 500, 100, 0);
+  CellularDataPlan data_100_50 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_METERED_PAID, 100, 500, 100, 50);
+  CellularDataPlan data_100_100 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_METERED_PAID, 100, 500, 100, 100);
+  CellularDataPlan data_100_200 =
+      CreateDataPlan(CELLULAR_DATA_PLAN_METERED_PAID, 100, 500, 100, 200);
+  CellularDataPlan data_100_0_gap =
+      CreateDataPlan(CELLULAR_DATA_PLAN_METERED_PAID, 200, 500, 100, 0);
+  EXPECT_FALSE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                              &data_0_0));
+  EXPECT_TRUE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                             &data_100_0));
+  EXPECT_TRUE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                             &data_100_50));
+  EXPECT_FALSE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                              &data_100_100));
+  EXPECT_FALSE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                              &data_100_200));
+  EXPECT_FALSE(NetworkMessageObserver::IsApplicableBackupPlan(&plan,
+                                                              &data_100_0_gap));
+}
+
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/balloon_collection_impl.cc b/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
index d68978a..aa05c8c 100644
--- a/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
+++ b/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,8 +14,8 @@
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/ui/window_sizer.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 namespace {
 
@@ -49,7 +49,7 @@
     space_change_listener_->OnBalloonSpaceChanged();
 }
 
-bool BalloonCollectionImpl::AddDOMUIMessageCallback(
+bool BalloonCollectionImpl::AddWebUIMessageCallback(
     const Notification& notification,
     const std::string& message,
     MessageCallback* callback) {
@@ -60,7 +60,7 @@
   }
   BalloonViewHost* host =
       static_cast<BalloonViewHost*>(balloon->view()->GetHost());
-  return host->AddDOMUIMessageCallback(message, callback);
+  return host->AddWebUIMessageCallback(message, callback);
 }
 
 void BalloonCollectionImpl::AddSystemNotification(
diff --git a/chrome/browser/chromeos/notifications/balloon_collection_impl.h b/chrome/browser/chromeos/notifications/balloon_collection_impl.h
index 320bfd6..a837282 100644
--- a/chrome/browser/chromeos/notifications/balloon_collection_impl.h
+++ b/chrome/browser/chromeos/notifications/balloon_collection_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,8 +14,8 @@
 #include "chrome/browser/notifications/balloon_collection.h"
 #include "chrome/browser/notifications/balloon_collection_base.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 
 namespace gfx {
 class Size;
@@ -76,12 +76,12 @@
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
-  // Adds a callback for DOMUI message. Returns true if the callback
+  // Adds a callback for WebUI message. Returns true if the callback
   // is succssfully registered, or false otherwise. It fails to add if
   // there is no notification that matches NotificationDelegate::id(),
   // or a callback for given message already exists. The callback
   // object is owned and deleted by callee.
-  bool AddDOMUIMessageCallback(const Notification& notification,
+  bool AddWebUIMessageCallback(const Notification& notification,
                                const std::string& message,
                                MessageCallback* callback);
 
diff --git a/chrome/browser/chromeos/notifications/balloon_view.cc b/chrome/browser/chromeos/notifications/balloon_view.cc
index 8e9bb8d..653c6a1 100644
--- a/chrome/browser/chromeos/notifications/balloon_view.cc
+++ b/chrome/browser/chromeos/notifications/balloon_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/menus/simple_menu_model.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/notifications/balloon_view_host.h"
@@ -19,12 +16,15 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/views/notifications/balloon_view_host.h"
+#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/background.h"
 #include "views/controls/button/button.h"
 #include "views/controls/button/image_button.h"
@@ -54,7 +54,7 @@
 // overlays on top of renderer view.
 class NotificationControlView : public views::View,
                                 public views::ViewMenuDelegate,
-                                public menus::SimpleMenuModel::Delegate,
+                                public ui::SimpleMenuModel::Delegate,
                                 public views::ButtonListener {
  public:
   explicit NotificationControlView(BalloonViewImpl* view)
@@ -125,7 +125,7 @@
     balloon_view_->Close(true);
   }
 
-  // menus::SimpleMenuModel::Delegate impglements.
+  // ui::SimpleMenuModel::Delegate impglements.
   virtual bool IsCommandIdChecked(int /* command_id */) const {
     // Nothing in the menu is checked.
     return false;
@@ -137,7 +137,7 @@
   }
 
   virtual bool GetAcceleratorForCommandId(
-      int /* command_id */, menus::Accelerator* /* accelerator */) {
+      int /* command_id */, ui::Accelerator* /* accelerator */) {
     // Currently no accelerators.
     return false;
   }
@@ -162,7 +162,7 @@
         IDS_NOTIFICATION_BALLOON_REVOKE_MESSAGE,
         balloon_view_->balloon_->notification().display_source());
 
-    options_menu_contents_.reset(new menus::SimpleMenuModel(this));
+    options_menu_contents_.reset(new ui::SimpleMenuModel(this));
     // TODO(oshima): Showing the source info in the menu for now.
     // Figure out where to show the source info.
     options_menu_contents_->AddItem(kNoopCommand, source_label_text);
@@ -176,7 +176,7 @@
   views::ImageButton* close_button_;
 
   // The options menu.
-  scoped_ptr<menus::SimpleMenuModel> options_menu_contents_;
+  scoped_ptr<ui::SimpleMenuModel> options_menu_contents_;
   scoped_ptr<views::Menu2> options_menu_menu_;
   views::MenuButton* options_menu_button_;
 
@@ -191,7 +191,7 @@
       sticky_(sticky),
       controls_(controls),
       closed_(false),
-      dom_ui_(dom_ui) {
+      web_ui_(dom_ui) {
   // This object is not to be deleted by the views hierarchy,
   // as it is owned by the balloon.
   set_parent_owned(false);
@@ -212,8 +212,8 @@
 void BalloonViewImpl::Show(Balloon* balloon) {
   balloon_ = balloon;
   html_contents_ = new BalloonViewHost(balloon);
-  if (dom_ui_)
-    html_contents_->EnableDOMUI();
+  if (web_ui_)
+    html_contents_->EnableWebUI();
   AddChildView(html_contents_->view());
   notification_registrar_.Add(this,
     NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon));
diff --git a/chrome/browser/chromeos/notifications/balloon_view.h b/chrome/browser/chromeos/notifications/balloon_view.h
index 8f00ccd..7f15ea6 100644
--- a/chrome/browser/chromeos/notifications/balloon_view.h
+++ b/chrome/browser/chromeos/notifications/balloon_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,10 +14,10 @@
 #include "chrome/browser/notifications/balloon.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/path.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "views/view.h"
 
 namespace views {
@@ -123,8 +123,8 @@
   bool controls_;
   // True if the notification is being closed.
   bool closed_;
-  // True to enable domui in the notification.
-  bool dom_ui_;
+  // True to enable WebUI in the notification.
+  bool web_ui_;
 
   DISALLOW_COPY_AND_ASSIGN(BalloonViewImpl);
 };
diff --git a/chrome/browser/chromeos/notifications/balloon_view_host.cc b/chrome/browser/chromeos/notifications/balloon_view_host.cc
index c51966b..ff4c50e 100644
--- a/chrome/browser/chromeos/notifications/balloon_view_host.cc
+++ b/chrome/browser/chromeos/notifications/balloon_view_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
                                        message_callbacks_.end());
 }
 
-bool BalloonViewHost::AddDOMUIMessageCallback(
+bool BalloonViewHost::AddWebUIMessageCallback(
     const std::string& message,
     MessageCallback* callback) {
   std::pair<MessageCallbackMap::iterator, bool> ret;
@@ -26,9 +26,9 @@
   return ret.second;
 }
 
-void BalloonViewHost::ProcessDOMUIMessage(
+void BalloonViewHost::ProcessWebUIMessage(
     const ViewHostMsg_DomMessage_Params& params) {
-  ::BalloonViewHost::ProcessDOMUIMessage(params);
+  ::BalloonViewHost::ProcessWebUIMessage(params);
 
   // Look up the callback for this message.
   MessageCallbackMap::const_iterator callback =
diff --git a/chrome/browser/chromeos/notifications/balloon_view_host.h b/chrome/browser/chromeos/notifications/balloon_view_host.h
index 642ce36..db532b7 100644
--- a/chrome/browser/chromeos/notifications/balloon_view_host.h
+++ b/chrome/browser/chromeos/notifications/balloon_view_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_BALLOON_VIEW_HOST_H_
 #pragma once
 
-#include "chrome/browser/views/notifications/balloon_view_host.h"
+#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
 
 #include <map>
 #include <string>
 
 #include "base/callback.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class ListValue;
 class GURL;
@@ -26,15 +26,15 @@
   explicit BalloonViewHost(Balloon* balloon) : ::BalloonViewHost(balloon) {}
   virtual ~BalloonViewHost();
 
-  // Adds a callback for DOMUI message. Returns true if the callback
+  // Adds a callback for WebUI message. Returns true if the callback
   // is succssfully registered, or false otherwise. It fails to add if
   // a callback for given message already exists. The callback object
   // is owned and deleted by callee.
-  bool AddDOMUIMessageCallback(const std::string& message,
+  bool AddWebUIMessageCallback(const std::string& message,
                                MessageCallback* callback);
 
-  // Process DOMUI message.
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
+  // Process WebUI message.
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
 
  private:
   // A map of message name -> message handling callback.
diff --git a/chrome/browser/chromeos/notifications/notification_browsertest.cc b/chrome/browser/chromeos/notifications/notification_browsertest.cc
index 82cd702..79c5eb9 100644
--- a/chrome/browser/chromeos/notifications/notification_browsertest.cc
+++ b/chrome/browser/chromeos/notifications/notification_browsertest.cc
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/x11_util.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
@@ -21,6 +20,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
+#include "ui/base/x/x11_util.h"
 
 namespace {
 
@@ -40,7 +40,7 @@
         expected_(PanelController::INITIAL) {
   }
 
-  void HandleDOMUIMessage(const ListValue* value) {
+  void HandleWebUIMessage(const ListValue* value) {
     MessageLoop::current()->Quit();
   }
 
@@ -49,7 +49,7 @@
     // Detect if we're running under ChromeOS WindowManager. See
     // the description for "under_chromeos_" below for why we need this.
     std::string wm_name;
-    bool wm_name_valid = x11_util::GetWindowManagerName(&wm_name);
+    bool wm_name_valid = ui::GetWindowManagerName(&wm_name);
     // NOTE: On Chrome OS the wm and Chrome are started in parallel. This
     // means it's possible for us not to be able to get the name of the window
     // manager. We assume that when this happens we're on Chrome OS.
@@ -288,9 +288,7 @@
 // This test depends on the fact that the panel state change occurs
 // quicker than stale timeout, thus the stale timeout cannot be set to
 // 0. This test explicitly controls the stale state instead.
-
-// TODO(oshima): bug chromium-os:7306 Fix this flaky test on ChromeOS.
-IN_PROC_BROWSER_TEST_F(NotificationTest, FLAKY_TestStateTransition2) {
+IN_PROC_BROWSER_TEST_F(NotificationTest, TestStateTransition2) {
   // Register observer here as the registration does not work in SetUp().
   NotificationRegistrar registrar;
   registrar.Add(this,
@@ -540,41 +538,41 @@
   EXPECT_EQ(1, tester->GetStickyNotificationCount());
 }
 
-IN_PROC_BROWSER_TEST_F(NotificationTest, TestAddDOMUIMessageCallback) {
+IN_PROC_BROWSER_TEST_F(NotificationTest, TestAddWebUIMessageCallback) {
   BalloonCollectionImpl* collection = GetBalloonCollectionImpl();
   Profile* profile = browser()->profile();
 
   collection->AddSystemNotification(
       NewMockNotification("1"), profile, false, false);
 
-  EXPECT_TRUE(collection->AddDOMUIMessageCallback(
+  EXPECT_TRUE(collection->AddWebUIMessageCallback(
       NewMockNotification("1"),
       "test",
       NewCallback(
           static_cast<NotificationTest*>(this),
-          &NotificationTest::HandleDOMUIMessage)));
+          &NotificationTest::HandleWebUIMessage)));
 
   // Adding callback for the same message twice should fail.
-  EXPECT_FALSE(collection->AddDOMUIMessageCallback(
+  EXPECT_FALSE(collection->AddWebUIMessageCallback(
       NewMockNotification("1"),
       "test",
       NewCallback(
           static_cast<NotificationTest*>(this),
-          &NotificationTest::HandleDOMUIMessage)));
+          &NotificationTest::HandleWebUIMessage)));
 
   // Adding callback to nonexistent notification should fail.
-  EXPECT_FALSE(collection->AddDOMUIMessageCallback(
+  EXPECT_FALSE(collection->AddWebUIMessageCallback(
       NewMockNotification("2"),
       "test1",
       NewCallback(
           static_cast<NotificationTest*>(this),
-          &NotificationTest::HandleDOMUIMessage)));
+          &NotificationTest::HandleWebUIMessage)));
 }
 
-IN_PROC_BROWSER_TEST_F(NotificationTest, TestDOMUIMessageCallback) {
+IN_PROC_BROWSER_TEST_F(NotificationTest, TestWebUIMessageCallback) {
   BalloonCollectionImpl* collection = GetBalloonCollectionImpl();
   Profile* profile = browser()->profile();
-  // a notification that sends 'test' domui message back to chrome.
+  // A notification that sends 'test' WebUI message back to chrome.
   const GURL content_url(
       "data:text/html;charset=utf-8,"
       "<html><script>function send() { chrome.send('test', ['']); }</script>"
@@ -585,12 +583,12 @@
       profile,
       false,
       false);
-  EXPECT_TRUE(collection->AddDOMUIMessageCallback(
+  EXPECT_TRUE(collection->AddWebUIMessageCallback(
       NewMockNotification("1"),
       "test",
       NewCallback(
           static_cast<NotificationTest*>(this),
-          &NotificationTest::HandleDOMUIMessage)));
+          &NotificationTest::HandleWebUIMessage)));
   MessageLoop::current()->Run();
 }
 
diff --git a/chrome/browser/chromeos/notifications/notification_panel.cc b/chrome/browser/chromeos/notifications/notification_panel.cc
index 4bd0b3a..508e43e 100644
--- a/chrome/browser/chromeos/notifications/notification_panel.cc
+++ b/chrome/browser/chromeos/notifications/notification_panel.cc
@@ -8,15 +8,15 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
 #include "chrome/browser/chromeos/notifications/balloon_view.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/controls/native/native_view_host.h"
 #include "views/controls/scroll_view.h"
@@ -170,7 +170,7 @@
   virtual void Layout() {
     // Layout bottom up
     int height = 0;
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       views::View* child = GetChildViewAt(i);
       child->SetBounds(0, height, child->width(), child->height());
       height += child->height() + margin_;
@@ -182,7 +182,7 @@
   void UpdateBounds() {
     int height = 0;
     int max_width = 0;
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       views::View* child = GetChildViewAt(i);
       height += child->height() + margin_;
       max_width = std::max(max_width, child->width());
@@ -197,7 +197,7 @@
   // Returns the bounds that covers new notifications.
   gfx::Rect GetNewBounds() {
     gfx::Rect rect;
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       BalloonViewImpl* view =
           static_cast<BalloonViewImpl*>(GetChildViewAt(i));
       if (!view->stale()) {
@@ -214,7 +214,7 @@
   // Returns # of new notifications.
   int GetNewCount() {
     int count = 0;
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       BalloonViewImpl* view =
           static_cast<BalloonViewImpl*>(GetChildViewAt(i));
       if (!view->stale())
@@ -225,7 +225,7 @@
 
   // Make all notifications stale.
   void MakeAllStale() {
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       BalloonViewImpl* view =
           static_cast<BalloonViewImpl*>(GetChildViewAt(i));
       view->set_stale();
@@ -233,7 +233,7 @@
   }
 
   void DismissAll() {
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       BalloonViewImpl* view =
           static_cast<BalloonViewImpl*>(GetChildViewAt(i));
       view->Close(true);
@@ -241,7 +241,7 @@
   }
 
   BalloonViewImpl* FindBalloonView(const Notification& notification) {
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       BalloonViewImpl* view =
           static_cast<BalloonViewImpl*>(GetChildViewAt(i));
       if (view->IsFor(notification)) {
@@ -254,7 +254,7 @@
   BalloonViewImpl* FindBalloonView(const gfx::Point point) {
     gfx::Point copy(point);
     ConvertPointFromWidget(this, &copy);
-    for (int i = GetChildViewCount() - 1; i >= 0; --i) {
+    for (int i = child_count() - 1; i >= 0; --i) {
       views::View* view = GetChildViewAt(i);
       if (view->bounds().Contains(copy))
         return static_cast<BalloonViewImpl*>(view);
@@ -287,8 +287,8 @@
   // views::View overrides.
   virtual void Layout() {
     int margin =
-        (sticky_container_->GetChildViewCount() != 0 &&
-         non_sticky_container_->GetChildViewCount() != 0) ?
+        (sticky_container_->child_count() != 0 &&
+         non_sticky_container_->child_count() != 0) ?
         margin_ : 0;
     sticky_container_->SetBounds(
         0, 0, width(), sticky_container_->height());
@@ -322,9 +322,9 @@
   bool Update(Balloon* balloon) {
     BalloonViewImpl* view = GetBalloonViewOf(balloon);
     View* container = NULL;
-    if (sticky_container_->HasChildView(view)) {
+    if (view->parent() == sticky_container_) {
       container = sticky_container_;
-    } else if (non_sticky_container_->HasChildView(view)) {
+    } else if (view->parent() == non_sticky_container_) {
       container = non_sticky_container_;
     }
     if (container) {
@@ -345,8 +345,8 @@
 
   // Returns the number of notifications added to the panel.
   int GetNotificationCount() {
-    return sticky_container_->GetChildViewCount() +
-        non_sticky_container_->GetChildViewCount();
+    return sticky_container_->child_count() +
+        non_sticky_container_->child_count();
   }
 
   // Returns the # of new notifications.
@@ -357,19 +357,19 @@
 
   // Returns the # of sticky and new notifications.
   int GetStickyNewNotificationCount() {
-    return sticky_container_->GetChildViewCount() +
+    return sticky_container_->child_count() +
         non_sticky_container_->GetNewCount();
   }
 
   // Returns the # of sticky notifications.
   int GetStickyNotificationCount() {
-    return sticky_container_->GetChildViewCount();
+    return sticky_container_->child_count();
   }
 
   // Returns true if the |view| is contained in the panel.
   bool HasBalloonView(View* view) {
-    return sticky_container_->HasChildView(view) ||
-        non_sticky_container_->HasChildView(view);
+    return view->parent() == sticky_container_ ||
+        view->parent() == non_sticky_container_;
   }
 
   // Updates the bounds so that all notifications are visible.
@@ -610,6 +610,10 @@
   return SkBitmap();
 }
 
+bool NotificationPanel::CanClosePanel() {
+  return true;
+}
+
 void NotificationPanel::ClosePanel() {
   SET_STATE(CLOSED);
   UpdatePanel(false);
@@ -752,7 +756,7 @@
   // Update from WebKit may arrive after the panel is closed/hidden
   // and viewport widget is detached.
   if (native) {
-    native->SetBounds(balloon_container_->bounds());
+    native->SetBoundsRect(balloon_container_->bounds());
     scroll_view_->Layout();
   }
 }
@@ -862,7 +866,7 @@
   gfx::Point origin(0, 0);
   views::View::ConvertPointToView(view, panel_->balloon_container_.get(),
                                   &origin);
-  return rect.Contains(gfx::Rect(origin, view->bounds().size()));
+  return rect.Contains(gfx::Rect(origin, view->size()));
 }
 
 
diff --git a/chrome/browser/chromeos/notifications/notification_panel.h b/chrome/browser/chromeos/notifications/notification_panel.h
index 96739bc..1fdc799 100644
--- a/chrome/browser/chromeos/notifications/notification_panel.h
+++ b/chrome/browser/chromeos/notifications/notification_panel.h
@@ -13,7 +13,7 @@
 #include "chrome/browser/chromeos/frame/panel_controller.h"
 #include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class Balloon;
 class Notification;
@@ -97,9 +97,10 @@
                                   const gfx::Size& size);
   virtual void SetActiveView(BalloonViewImpl* view);
 
-  // PanelController overrides.
+  // PanelController::Delegate overrides.
   virtual string16 GetPanelTitle();
   virtual SkBitmap GetPanelIcon();
+  virtual bool CanClosePanel();
   virtual void ClosePanel();
 
   // NotificationObserver overrides:
diff --git a/chrome/browser/chromeos/notifications/system_notification.cc b/chrome/browser/chromeos/notifications/system_notification.cc
index 0d85687..d02158f 100644
--- a/chrome/browser/chromeos/notifications/system_notification.cc
+++ b/chrome/browser/chromeos/notifications/system_notification.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,27 +7,45 @@
 #include "base/callback.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/notifications/system_notification_factory.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 
 namespace chromeos {
 
+void SystemNotification::Init(int icon_resource_id) {
+  collection_ = static_cast<BalloonCollectionImpl*>(
+       g_browser_process->notification_ui_manager()->balloon_collection());
+  std::string url = web_ui_util::GetImageDataUrlFromResource(icon_resource_id);
+  DCHECK(!url.empty());
+  GURL tmp_gurl(url);
+  icon_.Swap(&tmp_gurl);
+}
+
+SystemNotification::SystemNotification(Profile* profile,
+                                       NotificationDelegate* delegate,
+                                       int icon_resource_id,
+                                       const string16& title)
+    : profile_(profile),
+      collection_(NULL),
+      delegate_(delegate),
+      title_(title),
+      visible_(false),
+      urgent_(false) {
+  Init(icon_resource_id);
+}
+
 SystemNotification::SystemNotification(Profile* profile,
                                        const std::string& id,
                                        int icon_resource_id,
                                        const string16& title)
     : profile_(profile),
-      collection_(static_cast<BalloonCollectionImpl*>(
-          g_browser_process->notification_ui_manager()->balloon_collection())),
+      collection_(NULL),
       delegate_(new Delegate(id)),
       title_(title),
       visible_(false),
       urgent_(false) {
-  std::string url = dom_ui_util::GetImageDataUrlFromResource(icon_resource_id);
-  DCHECK(!url.empty());
-  GURL tmp_gurl(url);
-  icon_.Swap(&tmp_gurl);
+  Init(icon_resource_id);
 }
 
 SystemNotification::~SystemNotification() {
@@ -57,7 +75,7 @@
     collection_->AddSystemNotification(notify, profile_,
                                        sticky,
                                        false /* no controls */);
-    collection_->AddDOMUIMessageCallback(notify, "link", callback);
+    collection_->AddWebUIMessageCallback(notify, "link", callback);
   }
   visible_ = true;
   urgent_ = urgent;
diff --git a/chrome/browser/chromeos/notifications/system_notification.h b/chrome/browser/chromeos/notifications/system_notification.h
index 81976b7..5573f2b 100644
--- a/chrome/browser/chromeos/notifications/system_notification.h
+++ b/chrome/browser/chromeos/notifications/system_notification.h
@@ -27,7 +27,14 @@
   // The profile is the current user profile. The id is any string used
   // to uniquely identify this notification. The title is the title of
   // the message to be displayed. On creation, the message is hidden.
-  SystemNotification(Profile* profile, const std::string& id,
+  SystemNotification(Profile* profile,
+                     const std::string& id,
+                     int icon_resource_id,
+                     const string16& title);
+
+  // Allows to provide custom NotificationDelegate.
+  SystemNotification(Profile* profile,
+                     NotificationDelegate* delegate,
                      int icon_resource_id,
                      const string16& title);
 
@@ -71,9 +78,11 @@
     DISALLOW_COPY_AND_ASSIGN(Delegate);
   };
 
+  void Init(int icon_resource_id);
+
   Profile* profile_;
   BalloonCollectionImpl* collection_;
-  scoped_refptr<Delegate> delegate_;
+  scoped_refptr<NotificationDelegate> delegate_;
   GURL icon_;
   string16 title_;
   bool visible_;
diff --git a/chrome/browser/chromeos/offline/offline_load_page.cc b/chrome/browser/chromeos/offline/offline_load_page.cc
index e466d75..33d88cf 100644
--- a/chrome/browser/chromeos/offline/offline_load_page.cc
+++ b/chrome/browser/chromeos/offline/offline_load_page.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/chromeos/offline/offline_load_page.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/metrics/histogram.h"
 #include "base/string_piece.h"
@@ -28,20 +26,14 @@
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
 // Maximum time to show a blank page.
 const int kMaxBlankPeriod = 3000;
 
-// This is a workaround for  crosbug.com/8285.
-// Chrome sometimes fails to load the page silently
-// when the load is requested right after network is
-// restored. This happens more often in HTTPS than HTTP.
-// This should be removed once the root cause is fixed.
-const int kSecureDelayMs = 1000;
-const int kDefaultDelayMs = 300;
-
 // A utility function to set the dictionary's value given by |resource_id|.
 void SetString(DictionaryValue* strings, const char* name, int resource_id) {
   strings->SetString(name, l10n_util::GetStringUTF16(resource_id));
@@ -185,17 +177,7 @@
 
 void OfflineLoadPage::Proceed() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  int delay = url().SchemeIsSecure() ? kSecureDelayMs : kDefaultDelayMs;
-  if (in_test_)
-    delay = 0;
   proceeded_ = true;
-  BrowserThread::PostDelayedTask(
-      BrowserThread::UI, FROM_HERE,
-      method_factory_.NewRunnableMethod(&OfflineLoadPage::DoProceed),
-      delay);
-}
-
-void OfflineLoadPage::DoProceed() {
   delegate_->OnBlockingPageComplete(true);
   InterstitialPage::Proceed();
 }
diff --git a/chrome/browser/chromeos/offline/offline_load_page.h b/chrome/browser/chromeos/offline/offline_load_page.h
index e4a6246..53b7909 100644
--- a/chrome/browser/chromeos/offline/offline_load_page.h
+++ b/chrome/browser/chromeos/offline/offline_load_page.h
@@ -11,7 +11,6 @@
 #include "base/task.h"
 #include "chrome/browser/chromeos/network_state_notifier.h"
 #include "chrome/browser/tab_contents/interstitial_page.h"
-#include "chrome/common/notification_observer.h"
 
 class DictionaryValue;
 class Extension;
@@ -74,9 +73,6 @@
   void GetNormalOfflineStrings(const string16& faield_url,
                                DictionaryValue* strings) const;
 
-  // Really proceed with loading.
-  void DoProceed();
-
   Delegate* delegate_;
   NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/chromeos/options/internet_page_view.cc b/chrome/browser/chromeos/options/internet_page_view.cc
deleted file mode 100644
index 880ac05..0000000
--- a/chrome/browser/chromeos/options/internet_page_view.cc
+++ /dev/null
@@ -1,596 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/internet_page_view.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/options/network_config_view.h"
-#include "chrome/browser/chromeos/options/options_window_view.h"
-#include "chrome/browser/chromeos/status/network_menu.h"
-#include "chrome/browser/views/window.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "views/controls/button/native_button.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/image_view.h"
-#include "views/controls/scroll_view.h"
-#include "views/widget/widget.h"
-#include "views/window/window.h"
-
-namespace chromeos {
-
-////////////////////////////////////////////////////////////////////////////////
-// NetworkSection
-
-class NetworkSection : public SettingsPageSection,
-                       public views::ButtonListener {
- public:
-  NetworkSection(InternetPageContentView* parent, Profile* profile,
-                 int title_msg_id);
-  virtual ~NetworkSection() {}
-
-  // Overriden from views::Button::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  void RefreshContents();
-
- protected:
-  enum ButtonFlags {
-    OPTIONS_BUTTON    = 1 << 0,
-    CONNECT_BUTTON    = 1 << 1,
-    DISCONNECT_BUTTON = 1 << 2,
-    FORGET_BUTTON     = 1 << 3,
-  };
-
-  // SettingsPageSection overrides:
-  virtual void InitContents(GridLayout* layout);
-
-  // Subclasses will initialize themselves in this method.
-  virtual void InitSection() = 0;
-
-  // This adds a row for a network.
-  // |id| is passed back in the ButtonClicked method.
-  // |icon|, |name|, |bold_name|, and |status| are displayed in the row.
-  // |button_flags| is an OR of ButtonFlags that should be displayed.
-  void AddNetwork(int id, const SkBitmap& icon, const std::wstring& name,
-                  bool bold_name, const std::wstring& status, int button_flags,
-                  int connection_type);
-
-  // Creates a modal popup with |view|.
-  void CreateModalPopup(views::WindowDelegate* view);
-
-  // This method is called when the user click on the |button| for |id|.
-  virtual void ButtonClicked(int button, int connection_type, int id) = 0;
-
- private:
-  // This constant determines the button tag offset for the different buttons.
-  // The ButtonFlag is multiplied by this offset to determine the button tag.
-  // For example, for disconnect buttons (DISCONNECT_BUTTON = 4), the button tag
-  //   will be offset by 4000.
-  static const int kButtonIdOffset = 1000;
-  // This constant determines the button tag offset for the connection types.
-  // The ConnectionType is multiplied by this to determine the button tag.
-  // For example, for wifi buttons (TYPE_WIFI = 2), the button tag
-  //   will be offset by 200.
-  static const int kConnectionTypeOffset = 100;
-
-  InternetPageContentView* parent_;
-
-  int quad_column_view_set_id_;
-
-  GridLayout* layout_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkSection);
-};
-
-NetworkSection::NetworkSection(InternetPageContentView* parent,
-                               Profile* profile,
-                               int title_msg_id)
-    : SettingsPageSection(profile, title_msg_id),
-      parent_(parent),
-      quad_column_view_set_id_(1) {
-}
-
-void NetworkSection::ButtonPressed(views::Button* sender,
-                                   const views::Event& event) {
-  int id = sender->tag();
-  // Determine the button from the id (div by kButtonIdOffset).
-  int button = id / kButtonIdOffset;
-  id %= kButtonIdOffset;
-  // Determine the connection type from the id (div by kConnectionTypeOffset).
-  int connection_type = id / kConnectionTypeOffset;
-  id %= kConnectionTypeOffset;
-
-  ButtonClicked(button, connection_type, id);
-}
-
-void NetworkSection::RefreshContents() {
-  RemoveAllChildViews(true);
-  InitControlLayout();
-}
-
-void NetworkSection::InitContents(GridLayout* layout) {
-  layout_ = layout;
-
-  ColumnSet* column_set = layout_->AddColumnSet(quad_column_view_set_id_);
-  // icon
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-  // network name
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-  // fill padding
-  column_set->AddPaddingColumn(10, 0);
-  // first button
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-  // padding
-  column_set->AddPaddingColumn(0, 10);
-  // second button
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  InitSection();
-}
-
-void NetworkSection::AddNetwork(int id, const SkBitmap& icon,
-                                const std::wstring& name, bool bold_name,
-                                const std::wstring& status, int button_flags,
-                                int connection_type) {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  // Offset id by connection type.
-  id += kConnectionTypeOffset * connection_type;
-
-  layout_->StartRow(0, quad_column_view_set_id_);
-  views::ImageView* icon_view = new views::ImageView();
-  icon_view->SetImage(icon);
-  layout_->AddView(icon_view, 1, 2);
-
-  views::Label* name_view = new views::Label(name);
-  if (bold_name)
-    name_view->SetFont(rb.GetFont(ResourceBundle::BoldFont));
-  name_view->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  layout_->AddView(name_view);
-
-  int num_buttons = 0;
-  if (button_flags & OPTIONS_BUTTON)
-    num_buttons++;
-  if (button_flags & CONNECT_BUTTON)
-    num_buttons++;
-  if (button_flags & DISCONNECT_BUTTON)
-    num_buttons++;
-  if (button_flags & FORGET_BUTTON)
-    num_buttons++;
-
-  if (num_buttons > 0) {
-    // We only support 2 buttons.
-    DCHECK_LE(num_buttons, 2);
-
-    if (num_buttons == 1)
-      layout_->SkipColumns(1);
-
-    if (button_flags & FORGET_BUTTON) {
-      views::NativeButton* button = new views::NativeButton(this,
-          UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_FORGET)));
-      button->set_tag(id + kButtonIdOffset * FORGET_BUTTON);
-      layout_->AddView(button, 1, 2);
-    }
-
-    if (button_flags & DISCONNECT_BUTTON) {
-      views::NativeButton* button = new views::NativeButton(this, UTF16ToWide(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_DISCONNECT)));
-      button->set_tag(id + kButtonIdOffset * DISCONNECT_BUTTON);
-      layout_->AddView(button, 1, 2);
-    }
-
-    if (button_flags & CONNECT_BUTTON) {
-      views::NativeButton* button = new views::NativeButton(this,
-          UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONNECT)));
-      button->set_tag(id + kButtonIdOffset * CONNECT_BUTTON);
-      layout_->AddView(button, 1, 2);
-    }
-
-    if (button_flags & OPTIONS_BUTTON) {
-      views::NativeButton* button = new views::NativeButton(this,
-          UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OPTIONS)));
-      button->set_tag(id + kButtonIdOffset * OPTIONS_BUTTON);
-      layout_->AddView(button, 1, 2);
-    }
-  }
-
-  layout_->StartRow(0, quad_column_view_set_id_);
-  layout_->SkipColumns(1);
-  views::Label* status_label = new views::Label(status);
-  status_label->SetFont(rb.GetFont(ResourceBundle::SmallFont));
-  status_label->SetColor(SK_ColorLTGRAY);
-  status_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  layout_->AddView(status_label);
-  layout_->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-}
-
-void NetworkSection::CreateModalPopup(views::WindowDelegate* view) {
-  views::Window* window = browser::CreateViewsWindow(
-      GetOptionsViewParent(), gfx::Rect(), view);
-  window->SetIsAlwaysOnTop(true);
-  window->Show();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WiredSection
-
-class WiredSection : public NetworkSection {
- public:
-  WiredSection(InternetPageContentView* parent, Profile* profile);
-  virtual ~WiredSection() {}
-
- protected:
-  // NetworkSection overrides:
-  virtual void InitSection();
-  virtual void ButtonClicked(int button, int connection_type, int id);
-
-  DISALLOW_COPY_AND_ASSIGN(WiredSection);
-};
-
-WiredSection::WiredSection(InternetPageContentView* parent, Profile* profile)
-    : NetworkSection(parent, profile,
-                     IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIRED_NETWORK) {
-}
-
-void WiredSection::InitSection() {
-  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_WIRED_BLACK);
-  if (!cros->ethernet_connecting() && !cros->ethernet_connected()) {
-    icon = NetworkMenu::IconForDisplay(icon,
-        *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED));
-  }
-
-  std::wstring name = UTF16ToWide(
-      l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET));
-
-  int s = IDS_STATUSBAR_NETWORK_DEVICE_DISABLED;
-  if (cros->ethernet_connecting())
-    s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING;
-  else if (cros->ethernet_connected())
-    s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED;
-  else if (cros->ethernet_enabled())
-    s = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED;
-  std::wstring status = UTF16ToWide(l10n_util::GetStringUTF16(s));
-
-  int flags = cros->ethernet_connected() ? OPTIONS_BUTTON : 0;
-  bool bold = cros->ethernet_connected() ? true : false;
-  AddNetwork(0, icon, name, bold, status, flags, TYPE_ETHERNET);
-}
-
-void WiredSection::ButtonClicked(int button, int connection_type, int id) {
-//  CreateModalPopup(new NetworkConfigView(
-//      CrosLibrary::Get()->GetNetworkLibrary()->ethernet_network()));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WirelessSection
-
-class WirelessSection : public NetworkSection {
- public:
-  WirelessSection(InternetPageContentView* parent, Profile* profile);
-  virtual ~WirelessSection() {}
-
- protected:
-  // NetworkSection overrides:
-  virtual void InitSection();
-  virtual void ButtonClicked(int button, int connection_type, int id);
-
- private:
-  // This calls NetworkSection::AddNetwork .
-  // For |connecting| or |connected| networks, the name is bold.
-  // The status is "Connecting" if |connecting|, "Connected" if |connected|,
-  // or "Disconnected".
-  // For connected networks, we show the disconnect and options buttons.
-  // For !connected and !connecting networks, we show the connect button.
-  void AddWirelessNetwork(int id, const SkBitmap& icon,
-                          const std::wstring& name, bool connecting,
-                          bool connected, int connection_type);
-
-  WifiNetworkVector wifi_networks_;
-  CellularNetworkVector cellular_networks_;
-
-  DISALLOW_COPY_AND_ASSIGN(WirelessSection);
-};
-
-WirelessSection::WirelessSection(InternetPageContentView* parent,
-                                 Profile* profile)
-    : NetworkSection(parent, profile,
-                     IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIRELESS_NETWORK) {
-}
-
-void WirelessSection::InitSection() {
-  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  // Wifi
-  wifi_networks_ = cros->wifi_networks();
-  for (size_t i = 0; i < wifi_networks_.size(); ++i) {
-    std::wstring name = ASCIIToWide(wifi_networks_[i]->name());
-
-    SkBitmap icon = NetworkMenu::IconForNetworkStrength(
-        wifi_networks_[i], true);
-    if (wifi_networks_[i]->encrypted()) {
-      icon = NetworkMenu::IconForDisplay(icon,
-          *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
-    }
-
-    bool connecting = wifi_networks_[i]->connecting();
-    bool connected = wifi_networks_[i]->connected();
-    AddWirelessNetwork(i, icon, name, connecting, connected, TYPE_WIFI);
-  }
-
-  // Cellular
-  cellular_networks_ = cros->cellular_networks();
-  for (size_t i = 0; i < cellular_networks_.size(); ++i) {
-    std::wstring name = ASCIIToWide(cellular_networks_[i]->name());
-
-    SkBitmap icon = NetworkMenu::IconForNetworkStrength(
-        cellular_networks_[i], true);
-    SkBitmap badge =
-        NetworkMenu::BadgeForNetworkTechnology(cellular_networks_[i]);
-    icon = NetworkMenu::IconForDisplay(icon, badge);
-
-    bool connecting = cellular_networks_[i]->connecting();
-    bool connected = cellular_networks_[i]->connected();
-    AddWirelessNetwork(i, icon, name, connecting, connected, TYPE_CELLULAR);
-  }
-}
-
-void WirelessSection::ButtonClicked(int button, int connection_type, int id) {
-  if (connection_type == TYPE_CELLULAR) {
-    if (static_cast<int>(cellular_networks_.size()) > id) {
-      if (button == CONNECT_BUTTON) {
-        // Connect to cellular network.
-        CrosLibrary::Get()->GetNetworkLibrary()->ConnectToCellularNetwork(
-            cellular_networks_[id]);
-      } else if (button == DISCONNECT_BUTTON) {
-        CrosLibrary::Get()->GetNetworkLibrary()->DisconnectFromWirelessNetwork(
-            cellular_networks_[id]);
-      } else {
-//        CreateModalPopup(new NetworkConfigView(cellular_networks_[id]));
-      }
-    }
-  } else if (connection_type == TYPE_WIFI) {
-    if (static_cast<int>(wifi_networks_.size()) > id) {
-      if (button == CONNECT_BUTTON) {
-        // Connect to wifi here. Open password page if appropriate.
-        if (wifi_networks_[id]->encrypted()) {
-//          NetworkConfigView* view =
-//              new NetworkConfigView(wifi_networks_[id], true);
-//          CreateModalPopup(view);
-//          view->SetLoginTextfieldFocus();
-        } else {
-          CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
-              wifi_networks_[id], std::string(), std::string(), std::string());
-        }
-      } else if (button == DISCONNECT_BUTTON) {
-        CrosLibrary::Get()->GetNetworkLibrary()->DisconnectFromWirelessNetwork(
-            wifi_networks_[id]);
-      } else {
-//        CreateModalPopup(new NetworkConfigView(wifi_networks_[id], false));
-      }
-    }
-  } else {
-    NOTREACHED();
-  }
-}
-
-void WirelessSection::AddWirelessNetwork(int id, const SkBitmap& icon,
-    const std::wstring& name, bool connecting, bool connected,
-    int connection_type) {
-  bool bold = connecting || connected;
-
-  int s = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED;
-  if (connecting)
-    s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING;
-  else if (connected)
-    s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED;
-  std::wstring status = UTF16ToWide(l10n_util::GetStringUTF16(s));
-
-  int flags = 0;
-  if (connected) {
-    flags |= DISCONNECT_BUTTON | OPTIONS_BUTTON;
-  } else if (!connecting) {
-    flags |= CONNECT_BUTTON;
-  }
-
-  AddNetwork(id, icon, name, bold, status, flags, connection_type);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RememberedSection
-
-class RememberedSection : public NetworkSection {
- public:
-  RememberedSection(InternetPageContentView* parent, Profile* profile);
-  virtual ~RememberedSection() {}
-
- protected:
-  // NetworkSection overrides:
-  virtual void InitSection();
-  virtual void ButtonClicked(int button, int connection_type, int id);
-
- private:
-  WifiNetworkVector wifi_networks_;
-
-  DISALLOW_COPY_AND_ASSIGN(RememberedSection);
-};
-
-RememberedSection::RememberedSection(InternetPageContentView* parent,
-                                     Profile* profile)
-    : NetworkSection(parent, profile,
-                     IDS_OPTIONS_SETTINGS_SECTION_TITLE_REMEMBERED_NETWORK) {
-}
-
-void RememberedSection::InitSection() {
-  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  // Wifi
-  wifi_networks_ = cros->remembered_wifi_networks();
-  for (size_t i = 0; i < wifi_networks_.size(); ++i) {
-    std::wstring name = ASCIIToWide(wifi_networks_[i]->name());
-
-    SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0_BLACK);
-    if (wifi_networks_[i]->encrypted()) {
-      icon = NetworkMenu::IconForDisplay(icon,
-          *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
-    }
-
-    AddNetwork(i, icon, name, false, std::wstring(), FORGET_BUTTON, TYPE_WIFI);
-  }
-}
-
-void RememberedSection::ButtonClicked(int button, int connection_type, int id) {
-  if (connection_type == TYPE_WIFI) {
-    if (static_cast<int>(wifi_networks_.size()) > id) {
-      CrosLibrary::Get()->GetNetworkLibrary()->ForgetWifiNetwork(
-          wifi_networks_[id]->service_path());
-    }
-  } else {
-    NOTREACHED();
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// InternetPageContentView
-
-class InternetPageContentView : public SettingsPageView {
- public:
-  explicit InternetPageContentView(Profile* profile);
-  virtual ~InternetPageContentView() {}
-
-  virtual void RefreshContents();
-
-  // views::View overrides.
-  virtual int GetLineScrollIncrement(views::ScrollView* scroll_view,
-                                     bool is_horizontal, bool is_positive);
-  virtual void Layout();
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
-
- protected:
-  // SettingsPageView implementation:
-  virtual void InitControlLayout();
-
- private:
-  int line_height_;
-  WiredSection* wired_section_;
-  WirelessSection* wireless_section_;
-  RememberedSection* remembered_section_;
-
-  DISALLOW_COPY_AND_ASSIGN(InternetPageContentView);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// InternetPageContentView, SettingsPageView implementation:
-
-InternetPageContentView::InternetPageContentView(Profile* profile)
-    : SettingsPageView(profile) {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  line_height_ = rb.GetFont(ResourceBundle::BaseFont).GetHeight();
-}
-
-void InternetPageContentView::RefreshContents() {
-  wired_section_->RefreshContents();
-  wireless_section_->RefreshContents();
-  remembered_section_->RefreshContents();
-}
-
-int InternetPageContentView::GetLineScrollIncrement(
-    views::ScrollView* scroll_view,
-    bool is_horizontal,
-    bool is_positive) {
-  if (!is_horizontal)
-    return line_height_;
-  return View::GetPageScrollIncrement(scroll_view, is_horizontal, is_positive);
-}
-
-void InternetPageContentView::Layout() {
-  // Set the width to the parent width and the height to the preferred height.
-  // We will have a vertical scrollbar if the preferred height is longer
-  // than the parent's height.
-  SetBounds(0, 0, GetParent()->width(), GetPreferredSize().height());
-  View::Layout();
-}
-
-void InternetPageContentView::DidChangeBounds(const gfx::Rect& previous,
-                                              const gfx::Rect& current) {
-  // Override to do nothing. Calling Layout() interferes with our scrolling.
-}
-
-void InternetPageContentView::InitControlLayout() {
-  GridLayout* layout = CreatePanelGridLayout(this);
-  SetLayoutManager(layout);
-
-  int single_column_view_set_id = 0;
-  ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  layout->StartRow(0, single_column_view_set_id);
-  wired_section_ = new WiredSection(this, profile());
-  layout->AddView(wired_section_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-
-  layout->StartRow(0, single_column_view_set_id);
-  wireless_section_ = new WirelessSection(this, profile());
-  layout->AddView(wireless_section_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-
-  layout->StartRow(0, single_column_view_set_id);
-  remembered_section_ = new RememberedSection(this, profile());
-  layout->AddView(remembered_section_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// InternetPageView
-
-InternetPageView::InternetPageView(Profile* profile)
-    : SettingsPageView(profile),
-      contents_view_(new InternetPageContentView(profile)),
-      scroll_view_(new views::ScrollView) {
-  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
-  cros->AddNetworkManagerObserver(this);
-}
-
-InternetPageView::~InternetPageView() {
-  CrosLibrary::Get()->GetNetworkLibrary()->RemoveNetworkManagerObserver(this);
-}
-
-void InternetPageView::OnNetworkManagerChanged(NetworkLibrary* obj) {
-  // Refresh wired, wireless, and remembered networks.
-  // Remember the current scroll region, and try to scroll back afterwards.
-  gfx::Rect rect = scroll_view_->GetVisibleRect();
-  contents_view_->RefreshContents();
-  Layout();
-  scroll_view_->ScrollContentsRegionToBeVisible(rect);
-}
-
-void InternetPageView::Layout() {
-  contents_view_->Layout();
-  scroll_view_->SetBounds(GetLocalBounds(false));
-  scroll_view_->Layout();
-}
-
-void InternetPageView::InitControlLayout() {
-  AddChildView(scroll_view_);
-  scroll_view_->SetContents(contents_view_);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/internet_page_view.h b/chrome/browser/chromeos/options/internet_page_view.h
deleted file mode 100644
index c5048df..0000000
--- a/chrome/browser/chromeos/options/internet_page_view.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_INTERNET_PAGE_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_INTERNET_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/options/settings_page_view.h"
-
-namespace views {
-class ScrollView;
-}  // namespace views
-
-namespace chromeos {
-
-class InternetPageContentView;
-
-// Internet settings page for Chrome OS
-class InternetPageView : public SettingsPageView,
-                         public NetworkLibrary::NetworkManagerObserver {
- public:
-  explicit InternetPageView(Profile* profile);
-  virtual ~InternetPageView();
-
-  // NetworkLibrary::NetworkManagerObserver implementation.
-  virtual void OnNetworkManagerChanged(NetworkLibrary* obj);
-
-  // views::View overrides:
-  virtual void Layout();
-
- protected:
-  // SettingsPageView implementation:
-  virtual void InitControlLayout();
-
- private:
-  // The contents of the internet page view.
-  InternetPageContentView* contents_view_;
-
-  // The scroll view that contains the advanced options.
-  views::ScrollView* scroll_view_;
-
-  DISALLOW_COPY_AND_ASSIGN(InternetPageView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_INTERNET_PAGE_VIEW_H_
diff --git a/chrome/browser/chromeos/options/language_chewing_config_view.cc b/chrome/browser/chromeos/options/language_chewing_config_view.cc
deleted file mode 100644
index 4aae92d..0000000
--- a/chrome/browser/chromeos/options/language_chewing_config_view.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/language_chewing_config_view.h"
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/options/language_config_util.h"
-#include "chrome/browser/chromeos/preferences.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
-#include "views/window/window.h"
-
-namespace chromeos {
-
-LanguageChewingConfigView::LanguageChewingConfigView(Profile* profile)
-    : OptionsPageView(profile), contents_(NULL) {
-  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
-    chewing_boolean_prefs_[i].Init(
-        language_prefs::kChewingBooleanPrefs[i].pref_name,
-        profile->GetPrefs(), this);
-    chewing_boolean_checkboxes_[i] = NULL;
-  }
-  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
-    ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    current.multiple_choice_pref.Init(
-        language_prefs::kChewingMultipleChoicePrefs[i].pref_name,
-        profile->GetPrefs(), this);
-    current.combobox_model =
-        new LanguageComboboxModel<const char*>(
-            &language_prefs::kChewingMultipleChoicePrefs[i]);
-    current.combobox = NULL;
-  }
-
-  hsu_sel_key_type_.multiple_choice_pref.Init(
-      language_prefs::kChewingHsuSelKeyType.pref_name, profile->GetPrefs(),
-      this);
-  hsu_sel_key_type_.combobox_model =
-      new LanguageComboboxModel<int>(&language_prefs::kChewingHsuSelKeyType);
-  hsu_sel_key_type_.combobox = NULL;
-
-  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
-    chewing_integer_prefs_[i].Init(
-        language_prefs::kChewingIntegerPrefs[i].pref_name,
-        profile->GetPrefs(), this);
-    chewing_integer_sliders_[i] = NULL;
-  }
-}
-
-LanguageChewingConfigView::~LanguageChewingConfigView() {
-}
-
-void LanguageChewingConfigView::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  views::Checkbox* checkbox = static_cast<views::Checkbox*>(sender);
-  const int pref_id = checkbox->tag();
-  DCHECK(pref_id >= 0 && pref_id < static_cast<int>(
-      language_prefs::kNumChewingBooleanPrefs));
-  chewing_boolean_prefs_[pref_id].SetValue(checkbox->checked());
-}
-
-void LanguageChewingConfigView::ItemChanged(
-    views::Combobox* sender, int prev_index, int new_index) {
-  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
-    ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    if (current.combobox == sender) {
-      const std::string config_value =
-          current.combobox_model->GetConfigValueAt(new_index);
-      VLOG(1) << "Changing Chewing pref to " << config_value;
-      // Update the Chrome pref.
-      current.multiple_choice_pref.SetValue(config_value);
-      break;
-    }
-  }
-  if (hsu_sel_key_type_.combobox == sender) {
-    const int config_value =
-        hsu_sel_key_type_.combobox_model->GetConfigValueAt(new_index);
-    VLOG(1) << "Changing Chewing pref to " << config_value;
-    // Update the Chrome pref.
-    hsu_sel_key_type_.multiple_choice_pref.SetValue(config_value);
-  }
-}
-
-void LanguageChewingConfigView::SliderValueChanged(views::Slider* sender) {
-  size_t pref_id;
-  for (pref_id = 0; pref_id < language_prefs::kNumChewingIntegerPrefs;
-       ++pref_id) {
-    if (chewing_integer_sliders_[pref_id] == sender)
-      break;
-  }
-  DCHECK(pref_id < language_prefs::kNumChewingIntegerPrefs);
-  chewing_integer_prefs_[pref_id].SetValue(sender->value());
-}
-
-
-void LanguageChewingConfigView::Layout() {
-  // Not sure why but this is needed to show contents in the dialog.
-  contents_->SetBounds(0, 0, width(), height());
-}
-
-int LanguageChewingConfigView::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK;
-}
-
-std::wstring LanguageChewingConfigView::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK));
-  }
-  return L"";
-}
-
-std::wstring LanguageChewingConfigView::GetWindowTitle() const {
-  return UTF16ToWide(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTINGS_TITLE));
-}
-
-gfx::Size LanguageChewingConfigView::GetPreferredSize() {
-  return gfx::Size(views::Window::GetLocalizedContentsSize(
-      IDS_LANGUAGES_INPUT_DIALOG_WIDTH_CHARS,
-      IDS_LANGUAGES_INPUT_DIALOG_HEIGHT_LINES));
-}
-
-void LanguageChewingConfigView::InitControlLayout() {
-  using views::ColumnSet;
-  using views::GridLayout;
-
-  contents_ = new views::View;
-  AddChildView(contents_);
-
-  GridLayout* layout = new GridLayout(contents_);
-  layout->SetInsets(kPanelVertMargin, kPanelHorizMargin,
-                    kPanelVertMargin, kPanelHorizMargin);
-  contents_->SetLayoutManager(layout);
-
-  const int kColumnSetId = 0;
-  ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
-    chewing_boolean_checkboxes_[i] = new views::Checkbox(
-        UTF16ToWide(l10n_util::GetStringUTF16(
-            language_prefs::kChewingBooleanPrefs[i].message_id)));
-    chewing_boolean_checkboxes_[i]->set_listener(this);
-    chewing_boolean_checkboxes_[i]->set_tag(i);
-  }
-  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
-    ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    current.combobox = new LanguageCombobox(current.combobox_model);
-    current.combobox->set_listener(this);
-  }
-  hsu_sel_key_type_.combobox =
-      new LanguageCombobox(hsu_sel_key_type_.combobox_model);
-  hsu_sel_key_type_.combobox->set_listener(this);
-
-  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
-    chewing_integer_sliders_[i] = new views::Slider(
-        language_prefs::kChewingIntegerPrefs[i].min_pref_value,
-        language_prefs::kChewingIntegerPrefs[i].max_pref_value,
-        1,
-        static_cast<views::Slider::StyleFlags>(
-            views::Slider::STYLE_DRAW_VALUE |
-            views::Slider::STYLE_UPDATE_ON_RELEASE),
-        this);
-  }
-  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(chewing_boolean_checkboxes_[i]);
-  }
-
-  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(new views::Label(
-        UTF16ToWide(l10n_util::GetStringUTF16(
-            language_prefs::kChewingIntegerPrefs[i].message_id))));
-    layout->AddView(chewing_integer_sliders_[i]);
-  }
-  NotifyPrefChanged();
-
-  // Show the comboboxes.
-  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
-    const ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(new views::Label(current.combobox_model->GetLabel()));
-    layout->AddView(current.combobox);
-  }
-  layout->StartRow(0, kColumnSetId);
-  layout->AddView(
-      new views::Label(hsu_sel_key_type_.combobox_model->GetLabel()));
-  layout->AddView(hsu_sel_key_type_.combobox);
-}
-
-void LanguageChewingConfigView::Observe(NotificationType type,
-                                        const NotificationSource& source,
-                                        const NotificationDetails& details) {
-  if (type == NotificationType::PREF_CHANGED) {
-    NotifyPrefChanged();
-  }
-}
-
-void LanguageChewingConfigView::NotifyPrefChanged() {
-  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
-    const bool checked = chewing_boolean_prefs_[i].GetValue();
-    chewing_boolean_checkboxes_[i]->SetChecked(checked);
-  }
-  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
-    const int value = chewing_integer_prefs_[i].GetValue();
-    chewing_integer_sliders_[i]->SetValue(value);
-  }
-  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
-    ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    const std::string value = current.multiple_choice_pref.GetValue();
-    for (int i = 0; i < current.combobox_model->num_items(); ++i) {
-      if (current.combobox_model->GetConfigValueAt(i) == value) {
-        current.combobox->SetSelectedItem(i);
-        break;
-      }
-    }
-  }
-  const int value = hsu_sel_key_type_.multiple_choice_pref.GetValue();
-  for (int i = 0; i < hsu_sel_key_type_.combobox_model->num_items(); ++i) {
-    if (hsu_sel_key_type_.combobox_model->GetConfigValueAt(i) == value) {
-      hsu_sel_key_type_.combobox->SetSelectedItem(i);
-      break;
-    }
-  }
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_chewing_config_view.h b/chrome/browser/chromeos/options/language_chewing_config_view.h
deleted file mode 100644
index d7a33cf..0000000
--- a/chrome/browser/chromeos/options/language_chewing_config_view.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CHEWING_CONFIG_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CHEWING_CONFIG_VIEW_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/label.h"
-#include "views/controls/slider/slider.h"
-#include "views/window/dialog_delegate.h"
-
-namespace chromeos {
-
-class LanguageCombobox;
-template <typename DataType>
-class LanguageComboboxModel;
-
-// A dialog box for showing Traditional Chinese (Chewing) input method
-// preferences.
-class LanguageChewingConfigView : public views::ButtonListener,
-                                  public views::Combobox::Listener,
-                                  public views::DialogDelegate,
-                                  public views::SliderListener,
-                                  public OptionsPageView {
- public:
-  explicit LanguageChewingConfigView(Profile* profile);
-  virtual ~LanguageChewingConfigView();
-
-  // views::ButtonListener overrides.
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // views::Combobox::Listener overrides.
-  virtual void ItemChanged(views::Combobox* sender,
-                           int prev_index,
-                           int new_index);
-
-  // views::SliderListener overrides.
-  virtual void SliderValueChanged(views::Slider* sender);
-
-  // views::DialogDelegate overrides.
-  virtual bool IsModal() const { return true; }
-  virtual views::View* GetContentsView() { return this; }
-  virtual int GetDialogButtons() const;
-  virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const;
-  virtual std::wstring GetWindowTitle() const;
-
-  // views::View overrides.
-  virtual void Layout();
-  virtual gfx::Size GetPreferredSize();
-
-  // OptionsPageView overrides.
-  virtual void InitControlLayout();
-
-  // NotificationObserver overrides.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  // Updates the chewing checkboxes.
-  void NotifyPrefChanged();
-
-  BooleanPrefMember chewing_boolean_prefs_[
-      language_prefs::kNumChewingBooleanPrefs];
-  IntegerPrefMember chewing_integer_prefs_[
-      language_prefs::kNumChewingIntegerPrefs];
-  views::View* contents_;
-
-  // Checkboxes for Chewing.
-  views::Checkbox* chewing_boolean_checkboxes_[
-      language_prefs::kNumChewingBooleanPrefs];
-
-  views::Slider* chewing_integer_sliders_[
-      language_prefs::kNumChewingIntegerPrefs];
-
-  struct ChewingPrefAndAssociatedCombobox {
-    StringPrefMember multiple_choice_pref;
-    LanguageComboboxModel<const char*>* combobox_model;
-    LanguageCombobox* combobox;
-  } prefs_and_comboboxes_[language_prefs::kNumChewingMultipleChoicePrefs];
-
-  struct HsuSelKeyTypePrefAndAssociatedCombobox {
-    IntegerPrefMember multiple_choice_pref;
-    LanguageComboboxModel<int>* combobox_model;
-    LanguageCombobox* combobox;
-  } hsu_sel_key_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageChewingConfigView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CHEWING_CONFIG_VIEW_H_
diff --git a/chrome/browser/chromeos/options/language_config_model.cc b/chrome/browser/chromeos/options/language_config_model.cc
deleted file mode 100644
index cd400e5..0000000
--- a/chrome/browser/chromeos/options/language_config_model.cc
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/language_config_model.h"
-
-#include <algorithm>
-#include <functional>
-#include <utility>
-
-#include "app/l10n_util.h"
-#include "base/string_split.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/chromeos/preferences.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-
-namespace chromeos {
-
-AddLanguageComboboxModel::AddLanguageComboboxModel(
-    Profile* profile,
-    const std::vector<std::string>& locale_codes)
-    : LanguageComboboxModel(profile, locale_codes) {
-}
-
-int AddLanguageComboboxModel::GetItemCount() {
-  // +1 for "Add language".
-  return get_languages_count() + 1 - ignore_set_.size();
-}
-
-string16 AddLanguageComboboxModel::GetItemAt(int index) {
-  // Show "Add language" as the first item.
-  if (index == 0) {
-    return l10n_util::GetStringUTF16(
-        IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_COMBOBOX);
-  }
-  return GetLanguageNameAt(GetLanguageIndex(index));
-}
-
-int AddLanguageComboboxModel::GetLanguageIndex(int index) const {
-  // The adjusted_index is counted while ignoring languages in ignore_set_.
-  int adjusted_index = 0;
-  for (int i = 0; i < get_languages_count(); ++i) {
-    if (ignore_set_.count(GetLocaleFromIndex(i)) > 0) {
-      continue;
-    }
-    // -1 for "Add language".
-    if (adjusted_index == index - 1) {
-      return i;
-    }
-    ++adjusted_index;
-  }
-  return 0;
-}
-
-void AddLanguageComboboxModel::SetIgnored(
-    const std::string& language_code, bool ignored) {
-  if (ignored) {
-    // Add to the ignore_set_ if the language code is known (i.e. reject
-    // unknown language codes just in case).
-    if (GetIndexFromLocale(language_code) != -1) {
-      ignore_set_.insert(language_code);
-    } else {
-      LOG(ERROR) << "Unknown language code: " << language_code;
-    }
-  } else {
-    ignore_set_.erase(language_code);
-  }
-}
-
-LanguageConfigModel::LanguageConfigModel(PrefService* pref_service)
-    : pref_service_(pref_service) {
-  // Initialize the maps and vectors.
-  InitInputMethodIdVectors();
-
-  preferred_languages_pref_.Init(
-      prefs::kLanguagePreferredLanguages, pref_service_, this);
-  preload_engines_pref_.Init(
-      prefs::kLanguagePreloadEngines, pref_service_, this);
-  // TODO(yusukes): It might be safer to call GetActiveLanguages() cros API
-  // here and compare the result and preload_engines_pref_.GetValue().
-  // If there's a discrepancy between IBus setting and Chrome prefs, we
-  // can resolve it by calling preload_engines_pref_SetValue() here.
-
-  // Initialize the language codes currently activated.
-  NotifyPrefChanged();
-}
-
-size_t LanguageConfigModel::CountNumActiveInputMethods(
-    const std::string& language_code) {
-  int num_selected_active_input_methods = 0;
-  std::vector<std::string> input_method_ids;
-  input_method::GetInputMethodIdsFromLanguageCode(
-      language_code, input_method::kAllInputMethods, &input_method_ids);
-  for (size_t i = 0; i < input_method_ids.size(); ++i) {
-    if (InputMethodIsActivated(input_method_ids[i])) {
-      ++num_selected_active_input_methods;
-    }
-  }
-  return num_selected_active_input_methods;
-}
-
-bool LanguageConfigModel::HasLanguageCode(
-    const std::string& language_code) const {
-  return std::find(preferred_language_codes_.begin(),
-                   preferred_language_codes_.end(),
-                   language_code) != preferred_language_codes_.end();
-}
-
-size_t LanguageConfigModel::AddLanguageCode(
-    const std::string& language_code) {
-  preferred_language_codes_.push_back(language_code);
-  // Sort the language codes by names. This is not efficient, but
-  // acceptable as the language list is about 40 item long at most.  In
-  // theory, we could find the position to insert rather than sorting, but
-  // it would be complex as we need to use unicode string comparator.
-  input_method::SortLanguageCodesByNames(&preferred_language_codes_);
-  // Find the language code just added in the sorted language codes.
-  const int added_at =
-      std::distance(preferred_language_codes_.begin(),
-                    std::find(preferred_language_codes_.begin(),
-                              preferred_language_codes_.end(),
-                              language_code));
-  preferred_languages_pref_.SetValue(
-      JoinString(preferred_language_codes_, ','));
-  return added_at;
-}
-
-void LanguageConfigModel::RemoveLanguageAt(size_t row) {
-  preferred_language_codes_.erase(preferred_language_codes_.begin() + row);
-  preferred_languages_pref_.SetValue(
-      JoinString(preferred_language_codes_, ','));
-}
-
-void LanguageConfigModel::UpdateInputMethodPreferences(
-    const std::vector<std::string>& in_new_input_method_ids) {
-  std::vector<std::string> new_input_method_ids = in_new_input_method_ids;
-  // Note: Since |new_input_method_ids| is alphabetically sorted and the sort
-  // function below uses stable sort, the relateve order of input methods that
-  // belong to the same language (e.g. "mozc" and "xkb:jp::jpn") is maintained.
-  input_method::SortInputMethodIdsByNames(&new_input_method_ids);
-  preload_engines_pref_.SetValue(JoinString(new_input_method_ids, ','));
-}
-
-void LanguageConfigModel::DeactivateInputMethodsFor(
-    const std::string& language_code) {
-  for (size_t i = 0; i < num_supported_input_method_ids(); ++i) {
-    if (input_method::GetLanguageCodeFromInputMethodId(
-            supported_input_method_id_at(i)) ==
-        language_code) {
-      // What happens if we disable the input method currently active?
-      // IBus should take care of it, so we don't do anything special
-      // here. See crosbug.com/2443.
-      SetInputMethodActivated(supported_input_method_id_at(i), false);
-      // Do not break; here in order to disable all engines that belong to
-      // |language_code|.
-    }
-  }
-}
-
-void LanguageConfigModel::SetInputMethodActivated(
-    const std::string& input_method_id, bool activated) {
-  DCHECK(!input_method_id.empty());
-  std::vector<std::string> input_method_ids;
-  GetActiveInputMethodIds(&input_method_ids);
-
-  std::set<std::string> input_method_id_set(input_method_ids.begin(),
-                                            input_method_ids.end());
-  if (activated) {
-    // Add |id| if it's not already added.
-    input_method_id_set.insert(input_method_id);
-  } else {
-    input_method_id_set.erase(input_method_id);
-  }
-
-  // Update Chrome's preference.
-  std::vector<std::string> new_input_method_ids(input_method_id_set.begin(),
-                                                input_method_id_set.end());
-  UpdateInputMethodPreferences(new_input_method_ids);
-}
-
-bool LanguageConfigModel::InputMethodIsActivated(
-    const std::string& input_method_id) {
-  std::vector<std::string> input_method_ids;
-  GetActiveInputMethodIds(&input_method_ids);
-  return (std::find(input_method_ids.begin(), input_method_ids.end(),
-                    input_method_id) != input_method_ids.end());
-}
-
-void LanguageConfigModel::GetActiveInputMethodIds(
-    std::vector<std::string>* out_input_method_ids) {
-  const std::string value = preload_engines_pref_.GetValue();
-  out_input_method_ids->clear();
-  if (!value.empty())
-    base::SplitString(value, ',', out_input_method_ids);
-}
-
-void LanguageConfigModel::GetPreferredLanguageCodes(
-    std::vector<std::string>* out_language_codes) {
-  const std::string value = preferred_languages_pref_.GetValue();
-  out_language_codes->clear();
-  if (!value.empty())
-    base::SplitString(value, ',', out_language_codes);
-}
-
-void LanguageConfigModel::GetInputMethodIdsFromLanguageCode(
-    const std::string& language_code,
-    std::vector<std::string>* input_method_ids) const {
-  DCHECK(input_method_ids);
-  input_method_ids->clear();
-  input_method::GetInputMethodIdsFromLanguageCode(
-      language_code, input_method::kAllInputMethods, input_method_ids);
-}
-
-void LanguageConfigModel::NotifyPrefChanged() {
-  GetPreferredLanguageCodes(&preferred_language_codes_);
-}
-
-void LanguageConfigModel::Observe(NotificationType type,
-                                  const NotificationSource& source,
-                                  const NotificationDetails& details) {
-  if (type == NotificationType::PREF_CHANGED) {
-    NotifyPrefChanged();
-  }
-}
-
-void LanguageConfigModel::InitInputMethodIdVectors() {
-  // The two sets are used to build lists without duplication.
-  std::set<std::string> supported_language_code_set;
-  std::set<std::string> supported_input_method_id_set;
-  // Build the id to descriptor map for handling kExtraLanguages later.
-  std::map<std::string, const InputMethodDescriptor*> id_to_descriptor_map;
-
-  // GetSupportedLanguages() never return NULL.
-  scoped_ptr<InputMethodDescriptors> supported_input_methods(
-      CrosLibrary::Get()->GetInputMethodLibrary()->GetSupportedInputMethods());
-  for (size_t i = 0; i < supported_input_methods->size(); ++i) {
-    const InputMethodDescriptor& input_method = supported_input_methods->at(i);
-    const std::string language_code =
-        input_method::GetLanguageCodeFromDescriptor(input_method);
-    // Add the language code and the input method id to the sets.
-    supported_language_code_set.insert(language_code);
-    supported_input_method_id_set.insert(input_method.id);
-    // Remember the pair.
-    id_to_descriptor_map.insert(
-        std::make_pair(input_method.id, &input_method));
-  }
-
-  // Go through the languages listed in kExtraLanguages.
-  for (size_t i = 0; i < arraysize(input_method::kExtraLanguages); ++i) {
-    const char* language_code = input_method::kExtraLanguages[i].language_code;
-    const char* input_method_id =
-        input_method::kExtraLanguages[i].input_method_id;
-    std::map<std::string, const InputMethodDescriptor*>::const_iterator iter =
-        id_to_descriptor_map.find(input_method_id);
-    // If the associated input method descriptor is found, add the
-    // language code and the input method.
-    if (iter != id_to_descriptor_map.end()) {
-      const InputMethodDescriptor& input_method = *(iter->second);
-      // Add the language code and the input method id to the sets.
-      supported_language_code_set.insert(language_code);
-      supported_input_method_id_set.insert(input_method.id);
-    }
-  }
-
-  // Build the vectors from the sets.
-  supported_language_codes_.assign(supported_language_code_set.begin(),
-                                   supported_language_code_set.end());
-  supported_input_method_ids_.assign(supported_input_method_id_set.begin(),
-                                     supported_input_method_id_set.end());
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_config_model.h b/chrome/browser/chromeos/options/language_config_model.h
deleted file mode 100644
index c401c6f..0000000
--- a/chrome/browser/chromeos/options/language_config_model.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_MODEL_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_MODEL_H_
-#pragma once
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/string16.h"
-#include "chrome/browser/language_combobox_model.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "third_party/cros/chromeos_input_method.h"
-
-class Profile;
-
-namespace chromeos {
-
-// The combobox model is used for adding languages in the language config
-// view.
-class AddLanguageComboboxModel : public ::LanguageComboboxModel {
- public:
-  AddLanguageComboboxModel(Profile* profile,
-                           const std::vector<std::string>& locale_codes);
-  // LanguageComboboxModel overrides.
-  virtual int GetItemCount();
-  virtual string16 GetItemAt(int index);
-
-  // Converts the given index (index of the items in the combobox) to the
-  // index of the internal language list. The returned index can be used
-  // for GetLocaleFromIndex() and GetLanguageNameAt().
-  int GetLanguageIndex(int index) const;
-
-  // Marks the given language code to be ignored. Ignored languages won't
-  // be shown in the combobox. It would be simpler if we could remove and
-  // add language codes from the model, but ComboboxModel does not allow
-  // items to be added/removed. Thus we use |ignore_set_| instead.
-  void SetIgnored(const std::string& language_code, bool ignored);
-
- private:
-  std::set<std::string> ignore_set_;
-  DISALLOW_COPY_AND_ASSIGN(AddLanguageComboboxModel);
-};
-
-// The model of LanguageConfigView.
-class LanguageConfigModel : public NotificationObserver {
- public:
-  explicit LanguageConfigModel(PrefService* pref_service);
-
-  // Counts the number of active input methods for the given language code.
-  size_t CountNumActiveInputMethods(const std::string& language_code);
-
-  // Returns true if the language code is in the preferred language list.
-  bool HasLanguageCode(const std::string& language_code) const;
-
-  // Adds the given language to the preferred language list, and returns
-  // the index of the row where the language is added.
-  size_t AddLanguageCode(const std::string& language_code);
-
-  // Removes the language at the given row.
-  void RemoveLanguageAt(size_t row);
-
-  // Updates Chrome's input method preferences.
-  void UpdateInputMethodPreferences(
-      const std::vector<std::string>& new_input_method_ids);
-
-  // Deactivates the input methods for the given language code.
-  void DeactivateInputMethodsFor(const std::string& language_code);
-
-  // Activates or deactivates an IME whose ID is |input_method_id|.
-  void SetInputMethodActivated(const std::string& input_method_id,
-                               bool activated);
-
-  // Returns true if an IME of |input_method_id| is activated.
-  bool InputMethodIsActivated(const std::string& input_method_id);
-
-  // Gets the list of active IME IDs like "pinyin" and "m17n:ar:kbd" from
-  // the underlying preference object. The original contents of
-  // |out_input_method_ids| are lost.
-  void GetActiveInputMethodIds(
-      std::vector<std::string>* out_input_method_ids);
-
-  // Gets the list of preferred language codes like "en-US" and "fr" from
-  // the underlying preference object. The original contents of
-  // |out_language_codes| are lost.
-  void GetPreferredLanguageCodes(
-      std::vector<std::string>* out_language_codes);
-
-  // Gets the list of input method ids associated with the given language
-  // code.  The original contents of |input_method_ids| will be lost.
-  void GetInputMethodIdsFromLanguageCode(
-      const std::string& language_code,
-      std::vector<std::string>* input_method_ids) const;
-
-  // Callback for |preferred_language_codes_| pref updates. Initializes
-  // the preferred language codes based on the updated pref value.
-  void NotifyPrefChanged();
-
-  // NotificationObserver overrides.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  const std::string& preferred_language_code_at(size_t at) const {
-    return preferred_language_codes_[at];
-  }
-
-  size_t num_preferred_language_codes() const {
-    return preferred_language_codes_.size();
-  }
-
-  const std::string& supported_input_method_id_at(size_t at) const {
-    return supported_input_method_ids_[at];
-  }
-
-  size_t num_supported_input_method_ids() const {
-    return supported_input_method_ids_.size();
-  }
-
-  const std::vector<std::string>& supported_language_codes() const {
-    return supported_language_codes_;
-  }
-
- private:
-  // Initializes id_to_{code,display_name}_map_ maps,
-  // as well as supported_{language_codes,input_method_ids}_ vectors.
-  void InitInputMethodIdVectors();
-
-  PrefService* pref_service_;
-  // The codes of the preferred languages.
-  std::vector<std::string> preferred_language_codes_;
-  StringPrefMember preferred_languages_pref_;
-  StringPrefMember preload_engines_pref_;
-  // List of supported language codes like "en" and "ja".
-  std::vector<std::string> supported_language_codes_;
-  // List of supported IME IDs like "pinyin" and "m17n:ar:kbd".
-  std::vector<std::string> supported_input_method_ids_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageConfigModel);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_MODEL_H_
diff --git a/chrome/browser/chromeos/options/language_config_model_unittest.cc b/chrome/browser/chromeos/options/language_config_model_unittest.cc
deleted file mode 100644
index 0d7e12f..0000000
--- a/chrome/browser/chromeos/options/language_config_model_unittest.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/options/language_config_model.h"
-#include "grit/generated_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromeos {
-
-TEST(AddLanguageComboboxModelTest, AddLanguageComboboxModel) {
-  std::vector<std::string> language_codes;
-  language_codes.push_back("de");
-  language_codes.push_back("fr");
-  language_codes.push_back("ko");
-  AddLanguageComboboxModel model(NULL, language_codes);
-
-  // GetItemCount() should return 4 ("Add language" + 3 language codes).
-  ASSERT_EQ(4, model.GetItemCount());
-
-  // The first item should be "Add language" labe.
-  EXPECT_EQ(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_COMBOBOX),
-            model.GetItemAt(0));
-  // Other items should be sorted language display names for UI (hence
-  // French comes before German).  Note that the returned display names
-  // are followed by their native representations. To simplify matching,
-  // use StartsWith() here.
-  EXPECT_TRUE(StartsWith(model.GetItemAt(1), ASCIIToUTF16("French"), true))
-      << model.GetItemAt(1);
-  EXPECT_TRUE(StartsWith(model.GetItemAt(2), ASCIIToUTF16("German"), true))
-      << model.GetItemAt(2);
-  EXPECT_TRUE(StartsWith(model.GetItemAt(3), ASCIIToUTF16("Korean"), true))
-      << model.GetItemAt(3);
-
-  // GetLanguageIndex() returns the given index -1 to offset "Add language".
-  EXPECT_EQ(0, model.GetLanguageIndex(1));
-  EXPECT_EQ(1, model.GetLanguageIndex(2));
-  EXPECT_EQ(2, model.GetLanguageIndex(3));
-
-  // The returned index can be used for GetLocaleFromIndex().
-  EXPECT_EQ("fr", model.GetLocaleFromIndex(model.GetLanguageIndex(1)));
-  EXPECT_EQ("de", model.GetLocaleFromIndex(model.GetLanguageIndex(2)));
-  EXPECT_EQ("ko", model.GetLocaleFromIndex(model.GetLanguageIndex(3)));
-
-  // GetIndexFromLocale() returns the language index.
-  EXPECT_EQ(0, model.GetIndexFromLocale("fr"));
-  EXPECT_EQ(1, model.GetIndexFromLocale("de"));
-  EXPECT_EQ(2, model.GetIndexFromLocale("ko"));
-  EXPECT_EQ(-1, model.GetIndexFromLocale("ja"));  // Not in the model.
-
-  // Mark "de" to be ignored, and check if it's gone.
-  model.SetIgnored("de", true);
-  ASSERT_EQ(3, model.GetItemCount());
-  EXPECT_EQ("fr", model.GetLocaleFromIndex(model.GetLanguageIndex(1)));
-  EXPECT_EQ("ko", model.GetLocaleFromIndex(model.GetLanguageIndex(2)));
-
-  // Mark "ko" to be ignored, and check if it's gone.
-  model.SetIgnored("ko", true);
-  ASSERT_EQ(2, model.GetItemCount());
-  EXPECT_EQ("fr", model.GetLocaleFromIndex(model.GetLanguageIndex(1)));
-
-  // Mark "fr" to be ignored, and check if it's gone.
-  model.SetIgnored("fr", true);
-  ASSERT_EQ(1, model.GetItemCount());
-
-  // Mark "de" not to be ignored, and see if it's back.
-  model.SetIgnored("de", false);
-  ASSERT_EQ(2, model.GetItemCount());
-  EXPECT_EQ("de", model.GetLocaleFromIndex(model.GetLanguageIndex(1)));
-
-  // Mark "fr" not to be ignored, and see if it's back.
-  model.SetIgnored("fr", false);
-  ASSERT_EQ(3, model.GetItemCount());
-  EXPECT_EQ("fr", model.GetLocaleFromIndex(model.GetLanguageIndex(1)));
-  EXPECT_EQ("de", model.GetLocaleFromIndex(model.GetLanguageIndex(2)));
-
-  // Mark "ko" not to be ignored, and see if it's back.
-  model.SetIgnored("ko", false);
-  ASSERT_EQ(4, model.GetItemCount());
-  EXPECT_EQ("fr", model.GetLocaleFromIndex(model.GetLanguageIndex(1)));
-  EXPECT_EQ("de", model.GetLocaleFromIndex(model.GetLanguageIndex(2)));
-  EXPECT_EQ("ko", model.GetLocaleFromIndex(model.GetLanguageIndex(3)));
-
-  // Mark "ja" (not in the model) to be ignored.
-  model.SetIgnored("ja", true);
-  // The GetItemCount() should not be changed.
-  ASSERT_EQ(4, model.GetItemCount());
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_config_util.h b/chrome/browser/chromeos/options/language_config_util.h
deleted file mode 100644
index 808fefc..0000000
--- a/chrome/browser/chromeos/options/language_config_util.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_UTIL_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_UTIL_H_
-#pragma once
-
-#include "app/combobox_model.h"
-#include "base/string16.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "views/controls/combobox/combobox.h"
-
-namespace chromeos {
-
-// The combobox model for Language input method prefs.
-template <typename DataType>
-class LanguageComboboxModel : public ComboboxModel {
- public:
-  explicit LanguageComboboxModel(
-      const language_prefs::LanguageMultipleChoicePreference<DataType>*
-      pref_data)
-          : pref_data_(pref_data), num_items_(0) {
-    // Check how many items are defined in the |pref_data->values_and_ids|
-    // array.
-    for (size_t i = 0;
-         i < language_prefs::LanguageMultipleChoicePreference<DataType>::
-             kMaxItems; ++i) {
-      if ((pref_data_->values_and_ids)[i].item_message_id == 0) {
-        break;
-      }
-      ++num_items_;
-    }
-  }
-
-  // Implements ComboboxModel interface.
-  virtual int GetItemCount() {
-    return num_items_;
-  }
-
-  // Implements ComboboxModel interface.
-  virtual string16 GetItemAt(int index) {
-    if (index < 0 || index >= num_items_) {
-      LOG(ERROR) << "Index is out of bounds: " << index;
-      return string16();
-    }
-    const int message_id = (pref_data_->values_and_ids)[index].item_message_id;
-    return l10n_util::GetStringUTF16(message_id);
-  }
-
-  // Gets a label for the combobox like "Input mode". This function is NOT part
-  // of the ComboboxModel interface.
-  std::wstring GetLabel() const {
-    return UTF16ToWide(l10n_util::GetStringUTF16(pref_data_->label_message_id));
-  }
-
-  // Gets a config value for the ibus configuration daemon (e.g. "KUTEN_TOUTEN",
-  // "KUTEN_PERIOD", ..) for an item at zero-origin |index|. This function is
-  // NOT part of the ComboboxModel interface.
-  DataType GetConfigValueAt(int index) const {
-    if (index < 0 || index >= num_items_) {
-      LOG(ERROR) << "Index is out of bounds: " << index;
-      return (pref_data_->values_and_ids)[0].ibus_config_value;
-    }
-    return (pref_data_->values_and_ids)[index].ibus_config_value;
-  }
-
-  int num_items() {
-    return num_items_;
-  }
-
- private:
-  const language_prefs::LanguageMultipleChoicePreference<DataType>* pref_data_;
-  int num_items_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageComboboxModel);
-};
-
-// The combobox for the dialog which has minimum width.
-class LanguageCombobox : public views::Combobox {
- public:
-  explicit LanguageCombobox(ComboboxModel* model) : Combobox(model) {
-  }
-
-  virtual gfx::Size GetPreferredSize() {
-    gfx::Size size = Combobox::GetPreferredSize();
-    if (size.width() < kMinComboboxWidth) {
-      size.set_width(kMinComboboxWidth);
-    }
-    return size;
-  }
-
- private:
-  static const int kMinComboboxWidth = 250;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageCombobox);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_UTIL_H_
diff --git a/chrome/browser/chromeos/options/language_config_view.cc b/chrome/browser/chromeos/options/language_config_view.cc
deleted file mode 100644
index 5e6716a..0000000
--- a/chrome/browser/chromeos/options/language_config_view.cc
+++ /dev/null
@@ -1,631 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/language_config_view.h"
-
-#include <algorithm>
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/chromeos/options/language_chewing_config_view.h"
-#include "chrome/browser/chromeos/options/language_hangul_config_view.h"
-#include "chrome/browser/chromeos/options/language_mozc_config_view.h"
-#include "chrome/browser/chromeos/options/language_pinyin_config_view.h"
-#include "chrome/browser/chromeos/options/options_window_view.h"
-#include "chrome/browser/chromeos/preferences.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/restart_message_box.h"
-#include "chrome/browser/views/window.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/font.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/label.h"
-#include "views/fill_layout.h"
-#include "views/standard_layout.h"
-#include "views/window/window.h"
-
-namespace chromeos {
-using views::ColumnSet;
-using views::GridLayout;
-
-namespace {
-
-// The width of the preferred language table shown on the left side.
-const int kPreferredLanguageTableWidth = 300;
-
-// Creates the LanguageHangulConfigView. The function is used to create
-// the object via a function pointer. See also InitInputMethodConfigViewMap().
-views::DialogDelegate* CreateLanguageChewingConfigView(Profile* profile) {
-  return new LanguageChewingConfigView(profile);
-}
-views::DialogDelegate* CreateLanguageHangulConfigView(Profile* profile) {
-  return new LanguageHangulConfigView(profile);
-}
-views::DialogDelegate* CreateLanguagePinyinConfigView(Profile* profile) {
-  return new LanguagePinyinConfigView(profile);
-}
-views::DialogDelegate* CreateLanguageMozcConfigView(Profile* profile) {
-  return new LanguageMozcConfigView(profile);
-}
-
-// The tags are used to identify buttons in ButtonPressed().
-enum ButtonTag {
-  kChangeUiLanguageButton,
-  kConfigureInputMethodButton,
-  kRemoveLanguageButton,
-  kSelectInputMethodButton,
-};
-
-// The column set IDs are used for creating the per-language config view.
-const int kPerLanguageTitleColumnSetId = 1;
-const int kPerLanguageDoubleColumnSetId = 2;
-const int kPerLanguageSingleColumnSetId = 3;
-
-}  // namespace
-
-// This is a native button associated with input method information.
-class InputMethodButton : public views::NativeButton {
- public:
-  InputMethodButton(views::ButtonListener* listener,
-                    const std::wstring& label,
-                    const std::string& input_method_id)
-      : views::NativeButton(listener, label),
-        input_method_id_(input_method_id) {
-  }
-
-  const std::string& input_method_id() const {
-    return input_method_id_;
-  }
-
- private:
-  std::string input_method_id_;
-  DISALLOW_COPY_AND_ASSIGN(InputMethodButton);
-};
-
-// This is a native button associated with UI language information.
-class UiLanguageButton : public views::NativeButton {
- public:
-  UiLanguageButton(views::ButtonListener* listener,
-                    const std::wstring& label,
-                    const std::string& language_code)
-      : views::NativeButton(listener, label),
-        language_code_(language_code) {
-  }
-
-  const std::string& language_code() const {
-    return language_code_;
-  }
-
- private:
-  std::string language_code_;
-  DISALLOW_COPY_AND_ASSIGN(UiLanguageButton);
-};
-
-// This is a checkbox button associated with input method information.
-class InputMethodCheckbox : public views::Checkbox {
- public:
-  InputMethodCheckbox(const std::wstring& display_name,
-                      const std::string& input_method_id)
-      : views::Checkbox(display_name),
-        input_method_id_(input_method_id) {
-  }
-
-  const std::string& input_method_id() const {
-    return input_method_id_;
-  }
-
- private:
-  std::string input_method_id_;
-  DISALLOW_COPY_AND_ASSIGN(InputMethodCheckbox);
-};
-
-LanguageConfigView::LanguageConfigView(Profile* profile)
-    : OptionsPageView(profile),
-      model_(profile->GetPrefs()),
-      root_container_(NULL),
-      right_container_(NULL),
-      remove_language_button_(NULL),
-      preferred_language_table_(NULL) {
-}
-
-LanguageConfigView::~LanguageConfigView() {
-}
-
-void LanguageConfigView::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  if (sender->tag() == kRemoveLanguageButton) {
-    OnRemoveLanguage();
-  } else if (sender->tag() == kSelectInputMethodButton) {
-    InputMethodCheckbox* checkbox =
-        static_cast<InputMethodCheckbox*>(sender);
-    const std::string& input_method_id = checkbox->input_method_id();
-    model_.SetInputMethodActivated(input_method_id, checkbox->checked());
-    if (checkbox->checked()) {
-      EnableAllCheckboxes();
-    } else {
-      MaybeDisableLastCheckbox();
-    }
-  } else if (sender->tag() == kConfigureInputMethodButton) {
-    InputMethodButton* button = static_cast<InputMethodButton*>(sender);
-    views::DialogDelegate* config_view =
-        CreateInputMethodConfigureView(button->input_method_id());
-    if (!config_view) {
-      DLOG(FATAL) << "Config view not found: " << button->input_method_id();
-      return;
-    }
-    views::Window* window = browser::CreateViewsWindow(
-        GetOptionsViewParent(), gfx::Rect(), config_view);
-    window->SetIsAlwaysOnTop(true);
-    window->Show();
-  } else if (sender->tag() == kChangeUiLanguageButton) {
-    UiLanguageButton* button = static_cast<UiLanguageButton*>(sender);
-    PrefService* prefs = g_browser_process->local_state();
-    if (prefs) {
-      prefs->SetString(prefs::kApplicationLocale, button->language_code());
-      prefs->SavePersistentPrefs();
-      RestartMessageBox::ShowMessageBox(GetWindow()->GetNativeWindow());
-    }
-  }
-}
-
-std::wstring LanguageConfigView::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_DONE));
-  }
-  return L"";
-}
-
-std::wstring LanguageConfigView::GetWindowTitle() const {
-  return UTF16ToWide(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_LANGUAGES_DIALOG_TITLE));
-}
-
-void LanguageConfigView::Layout() {
-  // Not sure why but this is needed to show contents in the dialog.
-  root_container_->SetBounds(0, 0, width(), height());
-}
-
-gfx::Size LanguageConfigView::GetPreferredSize() {
-  return gfx::Size(views::Window::GetLocalizedContentsSize(
-      IDS_LANGUAGES_INPUT_DIALOG_WIDTH_CHARS,
-      IDS_LANGUAGES_INPUT_DIALOG_HEIGHT_LINES));
-}
-
-void LanguageConfigView::OnSelectionChanged() {
-  right_container_->RemoveAllChildViews(true);  // Delete the child views.
-
-  const int row = preferred_language_table_->GetFirstSelectedRow();
-  const std::string& language_code = model_.preferred_language_code_at(row);
-
-  // Count the number of all active input methods.
-  std::vector<std::string> active_input_method_ids;
-  model_.GetActiveInputMethodIds(&active_input_method_ids);
-  const int num_all_active_input_methods = active_input_method_ids.size();
-
-  // Count the number of active input methods for the selected language.
-  int num_selected_active_input_methods =
-      model_.CountNumActiveInputMethods(language_code);
-
-  bool remove_button_enabled = false;
-  // Allow removing the language only if the following conditions are met:
-  // 1. There are more than one language.
-  // 2. The languge in the current row is not set to the display language.
-  // 3. Removing the selected language does not result in "zero input method".
-  if (preferred_language_table_->GetRowCount() > 1 &&
-      language_code != g_browser_process->GetApplicationLocale() &&
-      num_all_active_input_methods > num_selected_active_input_methods) {
-    remove_button_enabled = true;
-  }
-  remove_language_button_->SetEnabled(remove_button_enabled);
-
-  // Add the per language config view to the right area.
-  right_container_->AddChildView(CreatePerLanguageConfigView(language_code));
-  MaybeDisableLastCheckbox();
-  // Layout the right container. This is needed for the contents on the
-  // right to be displayed properly.
-  right_container_->Layout();
-}
-
-string16 LanguageConfigView::GetText(int row, int column_id) {
-  if (row >= 0 && row < static_cast<int>(
-          model_.num_preferred_language_codes())) {
-    return input_method::GetLanguageDisplayNameFromCode(
-        model_.preferred_language_code_at(row));
-  }
-  NOTREACHED();
-  return string16();
-}
-
-void LanguageConfigView::SetObserver(TableModelObserver* observer) {
-  // We don't need the observer for the table mode, since we implement the
-  // table model as part of the LanguageConfigView class.
-  // http://crbug.com/38266
-}
-
-int LanguageConfigView::RowCount() {
-  // Returns the number of rows of the language table.
-  return model_.num_preferred_language_codes();
-}
-
-void LanguageConfigView::ItemChanged(views::Combobox* combobox,
-                                     int prev_index,
-                                     int new_index) {
-  // Ignore the first item used for showing "Add language".
-  if (new_index <= 0) {
-    return;
-  }
-  // Get the language selected.
-  std::string language_selected = add_language_combobox_model_->
-      GetLocaleFromIndex(
-          add_language_combobox_model_->GetLanguageIndex(new_index));
-  OnAddLanguage(language_selected);
-}
-
-void LanguageConfigView::InitControlLayout() {
-  // Initialize the map.
-  InitInputMethodConfigViewMap();
-
-  root_container_ = new views::View;
-  AddChildView(root_container_);
-
-  // Set up the layout manager for the root container.  We'll place the
-  // language table on the left, and the per language config on the right.
-  GridLayout* root_layout = new GridLayout(root_container_);
-  root_container_->SetLayoutManager(root_layout);
-  root_layout->SetInsets(kPanelVertMargin, kPanelHorizMargin,
-                         kPanelVertMargin, kPanelHorizMargin);
-
-  // Set up column sets for the grid layout.
-  const int kMainColumnSetId = 0;
-  ColumnSet* column_set = root_layout->AddColumnSet(kMainColumnSetId);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
-                        GridLayout::FIXED, kPreferredLanguageTableWidth, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
-                        GridLayout::USE_PREF, 0, 0);
-  const int kBottomColumnSetId = 1;
-  column_set = root_layout->AddColumnSet(kBottomColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-
-  // Set up the container for the contents on the right.  Just adds a
-  // place holder here. This will get replaced in OnSelectionChanged().
-  right_container_ = new views::View;
-  right_container_->SetLayoutManager(new views::FillLayout);
-  right_container_->AddChildView(new views::View);
-
-  // Add the contents on the left and the right.
-  root_layout->StartRow(1 /* expand */, kMainColumnSetId);
-  root_layout->AddView(CreateContentsOnLeft());
-  root_layout->AddView(right_container_);
-
-  // Add the contents on the bottom.
-  root_layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-  root_layout->StartRow(0, kBottomColumnSetId);
-  root_layout->AddView(CreateContentsOnBottom());
-
-  // Select the first row in the language table.
-  // There should be at least one language in the table, but we check it
-  // here so this won't result in crash in case there is no row in the table.
-  if (model_.num_preferred_language_codes() > 0) {
-    preferred_language_table_->SelectRow(0);
-  }
-}
-
-void LanguageConfigView::Show(Profile* profile, gfx::NativeWindow parent) {
-  UserMetrics::RecordAction(UserMetricsAction("LanguageConfigView_Open"));
-  views::Window* window = browser::CreateViewsWindow(
-      parent, gfx::Rect(), new LanguageConfigView(profile));
-  window->SetIsAlwaysOnTop(true);
-  window->Show();
-}
-
-void LanguageConfigView::InitInputMethodConfigViewMap() {
-  input_method_config_view_map_["chewing"] = CreateLanguageChewingConfigView;
-  input_method_config_view_map_["hangul"] = CreateLanguageHangulConfigView;
-  input_method_config_view_map_["mozc"] = CreateLanguageMozcConfigView;
-  input_method_config_view_map_["mozc-dv"] = CreateLanguageMozcConfigView;
-  input_method_config_view_map_["mozc-jp"] = CreateLanguageMozcConfigView;
-  input_method_config_view_map_["pinyin"] = CreateLanguagePinyinConfigView;
-}
-
-void LanguageConfigView::OnAddLanguage(const std::string& language_code) {
-  // Skip if the language is already in the preferred_language_codes_.
-  if (model_.HasLanguageCode(language_code)) {
-    return;
-  }
-  // Activate the first input language associated with the language. We have
-  // to call this before the OnItemsAdded() call below so the checkbox
-  // for the first input language gets checked.
-  std::vector<std::string> input_method_ids;
-  model_.GetInputMethodIdsFromLanguageCode(language_code, &input_method_ids);
-  if (!input_method_ids.empty()) {
-    model_.SetInputMethodActivated(input_method_ids[0], true);
-  }
-
-  // Append the language to the list of language codes.
-  const int added_at = model_.AddLanguageCode(language_code);
-  // Notify the table that the new row added at |added_at|.
-  preferred_language_table_->OnItemsAdded(added_at, 1);
-  // For some reason, OnItemsAdded() alone does not redraw the table. Need
-  // to tell the table that items are changed. TODO(satorux): Investigate
-  // if it's a bug in TableView2.
-  preferred_language_table_->OnItemsChanged(
-      0, model_.num_preferred_language_codes());
-  // Switch to the row added.
-  preferred_language_table_->SelectRow(added_at);
-
-  // Mark the language to be ignored.
-  add_language_combobox_model_->SetIgnored(language_code, true);
-  ResetAddLanguageCombobox();
-}
-
-void LanguageConfigView::OnRemoveLanguage() {
-  const int row = preferred_language_table_->GetFirstSelectedRow();
-  const std::string& language_code = model_.preferred_language_code_at(row);
-  // Mark the language not to be ignored.
-  add_language_combobox_model_->SetIgnored(language_code, false);
-  ResetAddLanguageCombobox();
-  // Deactivate the associated input methods.
-  model_.DeactivateInputMethodsFor(language_code);
-  // Remove the language code and the row from the table.
-  model_.RemoveLanguageAt(row);
-  preferred_language_table_->OnItemsRemoved(row, 1);
-  // Switch to the previous row, or the first row.
-  // There should be at least one row in the table.
-  preferred_language_table_->SelectRow(std::max(row - 1, 0));
-}
-
-void LanguageConfigView::ResetAddLanguageCombobox() {
-  // -1 to ignore "Add language". If there are more than one language,
-  // enable the combobox. Otherwise, disable it.
-  if (add_language_combobox_model_->GetItemCount() - 1 > 0) {
-    add_language_combobox_->SetEnabled(true);
-  } else {
-    add_language_combobox_->SetEnabled(false);
-  }
-  // Go back to the initial "Add language" state.
-  add_language_combobox_->ModelChanged();
-  add_language_combobox_->SetSelectedItem(0);
-}
-
-views::View* LanguageConfigView::CreateContentsOnLeft() {
-  views::View* contents = new views::View;
-  GridLayout* layout = new GridLayout(contents);
-  contents->SetLayoutManager(layout);
-
-  // Set up column sets for the grid layout.
-  const int kTableColumnSetId = 0;
-  ColumnSet* column_set = layout->AddColumnSet(kTableColumnSetId);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  // Create the language table.
-  std::vector<TableColumn> columns;
-  TableColumn column(0,
-                     l10n_util::GetStringUTF16(
-                         IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES),
-                     TableColumn::LEFT, -1, 0);
-  columns.push_back(column);
-  // We don't show horizontal and vertical lines.
-  const int options = (views::TableView2::SINGLE_SELECTION |
-                       views::TableView2::RESIZABLE_COLUMNS |
-                       views::TableView2::AUTOSIZE_COLUMNS);
-  preferred_language_table_ =
-      new views::TableView2(this, columns, views::TEXT_ONLY, options);
-  // Set the observer so OnSelectionChanged() will be invoked when a
-  // selection is changed in the table.
-  preferred_language_table_->SetObserver(this);
-
-  // Add the language table.
-  layout->StartRow(1 /* expand vertically */, kTableColumnSetId);
-  layout->AddView(preferred_language_table_);
-
-  return contents;
-}
-
-views::View* LanguageConfigView::CreateContentsOnBottom() {
-  views::View* contents = new views::View;
-  GridLayout* layout = new GridLayout(contents);
-  contents->SetLayoutManager(layout);
-
-  // Set up column sets for the grid layout.
-  const int kButtonsColumnSetId = 0;
-  ColumnSet* column_set = layout->AddColumnSet(kButtonsColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
-                        GridLayout::USE_PREF, 0, 0);
-
-  // Create the add language combobox model_.
-  // LanguageComboboxModel sorts languages by their display names.
-  add_language_combobox_model_.reset(
-      new AddLanguageComboboxModel(NULL, model_.supported_language_codes()));
-  // Mark the existing preferred languages to be ignored.
-  for (size_t i = 0; i < model_.num_preferred_language_codes(); ++i) {
-    add_language_combobox_model_->SetIgnored(
-        model_.preferred_language_code_at(i),
-        true);
-  }
-  // Create the add language combobox.
-  add_language_combobox_
-      = new views::Combobox(add_language_combobox_model_.get());
-  add_language_combobox_->set_listener(this);
-  ResetAddLanguageCombobox();
-
-  // Create the remove button.
-  remove_language_button_ = new views::NativeButton(
-      this, UTF16ToWide(l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON)));
-  remove_language_button_->set_tag(kRemoveLanguageButton);
-
-  // Add the add and remove buttons.
-  layout->StartRow(0, kButtonsColumnSetId);
-  layout->AddView(add_language_combobox_);
-  layout->AddView(remove_language_button_);
-
-  return contents;
-}
-
-views::View* LanguageConfigView::CreatePerLanguageConfigView(
-    const std::string& target_language_code) {
-  views::View* contents = new views::View;
-  GridLayout* layout = new GridLayout(contents);
-  contents->SetLayoutManager(layout);
-
-  // Set up column sets for the grid layout.
-  ColumnSet* column_set = layout->AddColumnSet(kPerLanguageTitleColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-
-  column_set = layout->AddColumnSet(kPerLanguageDoubleColumnSetId);
-  column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-
-  column_set = layout->AddColumnSet(kPerLanguageSingleColumnSetId);
-  column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-
-  AddUiLanguageSection(target_language_code, layout);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
-  AddInputMethodSection(target_language_code, layout);
-
-  return contents;
-}
-
-void LanguageConfigView::AddUiLanguageSection(const std::string& language_code,
-                                              views::GridLayout* layout) {
-  // Create the language name label.
-  const std::string application_locale =
-      g_browser_process->GetApplicationLocale();
-  const string16 language_name16 = l10n_util::GetDisplayNameForLocale(
-      language_code, application_locale, true);
-  const std::wstring language_name = UTF16ToWide(language_name16);
-  views::Label* language_name_label = new views::Label(language_name);
-  language_name_label->SetFont(
-      language_name_label->font().DeriveFont(0, gfx::Font::BOLD));
-
-  // Add the language name label.
-  layout->StartRow(0, kPerLanguageTitleColumnSetId);
-  layout->AddView(language_name_label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-
-  layout->StartRow(0, kPerLanguageSingleColumnSetId);
-  if (application_locale == language_code) {
-    layout->AddView(
-        new views::Label(
-            UTF16ToWide(l10n_util::GetStringFUTF16(
-                IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
-                l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)))));
-  } else {
-    UiLanguageButton* button = new UiLanguageButton(
-      this, UTF16ToWide(l10n_util::GetStringFUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME))),
-      language_code);
-    button->set_tag(kChangeUiLanguageButton);
-    layout->AddView(button);
-  }
-}
-
-void LanguageConfigView::AddInputMethodSection(
-    const std::string& language_code,
-    views::GridLayout* layout) {
-  // Create the input method title label.
-  views::Label* input_method_title_label = new views::Label(
-      UTF16ToWide(l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD)));
-  input_method_title_label->SetFont(
-      input_method_title_label->font().DeriveFont(0, gfx::Font::BOLD));
-
-  // Add the input method title label.
-  layout->StartRow(0, kPerLanguageTitleColumnSetId);
-  layout->AddView(input_method_title_label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-
-  // Add input method names and configuration buttons.
-  input_method_checkboxes_.clear();
-
-  // Get the list of input method ids associated with the language code.
-  std::vector<std::string> input_method_ids;
-  model_.GetInputMethodIdsFromLanguageCode(language_code, &input_method_ids);
-
-  for (size_t i = 0; i < input_method_ids.size(); ++i) {
-    const std::string& input_method_id = input_method_ids[i];
-    const std::string display_name =
-        input_method::GetInputMethodDisplayNameFromId(input_method_id);
-    layout->StartRow(0, kPerLanguageDoubleColumnSetId);
-    InputMethodCheckbox* checkbox
-        = new InputMethodCheckbox(UTF8ToWide(display_name),
-                                  input_method_id);
-    checkbox->set_listener(this);
-    checkbox->set_tag(kSelectInputMethodButton);
-    if (model_.InputMethodIsActivated(input_method_id)) {
-      checkbox->SetChecked(true);
-    }
-
-    layout->AddView(checkbox);
-    input_method_checkboxes_.insert(checkbox);
-    // Add "configure" button for the input method if we have a
-    // configuration dialog for it.
-    if (input_method_config_view_map_.count(input_method_id) > 0) {
-      InputMethodButton* button = new InputMethodButton(
-          this,
-          UTF16ToWide(l10n_util::GetStringUTF16(
-              IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE)),
-          input_method_id);
-      button->set_tag(kConfigureInputMethodButton);
-      layout->AddView(button);
-    }
-  }
-}
-
-views::DialogDelegate* LanguageConfigView::CreateInputMethodConfigureView(
-    const std::string& input_method_id) {
-  InputMethodConfigViewMap::const_iterator iter =
-      input_method_config_view_map_.find(input_method_id);
-  if (iter != input_method_config_view_map_.end()) {
-    CreateDialogDelegateFunction function = iter->second;
-    return function(profile());
-  }
-  return NULL;
-}
-
-void LanguageConfigView::MaybeDisableLastCheckbox() {
-  std::vector<std::string> input_method_ids;
-  model_.GetActiveInputMethodIds(&input_method_ids);
-  if (input_method_ids.size() <= 1) {
-    for (std::set<InputMethodCheckbox*>::iterator checkbox =
-             input_method_checkboxes_.begin();
-         checkbox != input_method_checkboxes_.end(); ++checkbox) {
-      if ((*checkbox)->checked())
-        (*checkbox)->SetEnabled(false);
-    }
-  }
-}
-
-void LanguageConfigView::EnableAllCheckboxes() {
-  for (std::set<InputMethodCheckbox*>::iterator checkbox =
-           input_method_checkboxes_.begin();
-       checkbox != input_method_checkboxes_.end(); ++checkbox) {
-    (*checkbox)->SetEnabled(true);
-  }
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_config_view.h b/chrome/browser/chromeos/options/language_config_view.h
deleted file mode 100644
index f625f03..0000000
--- a/chrome/browser/chromeos/options/language_config_view.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_VIEW_H_
-#pragma once
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "app/table_model.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/chromeos/options/language_config_model.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "views/controls/button/native_button.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/label.h"
-#include "views/controls/table/table_view2.h"
-#include "views/controls/table/table_view_observer.h"
-#include "views/grid_layout.h"
-#include "views/window/dialog_delegate.h"
-
-namespace chromeos {
-
-class InputMethodButton;
-class InputMethodCheckbox;
-class PreferredLanguageTableModel;
-
-// A dialog box for configuring the languages.
-class LanguageConfigView : public TableModel,
-                           public views::ButtonListener,
-                           public views::Combobox::Listener,
-                           public views::DialogDelegate,
-                           public views::TableViewObserver,
-                           public OptionsPageView {
- public:
-  explicit LanguageConfigView(Profile* profile);
-  virtual ~LanguageConfigView();
-
-  // views::ButtonListener overrides.
-  virtual void ButtonPressed(views::Button* sender,
-                             const views::Event& event);
-
-  // views::DialogDelegate overrides.
-  virtual bool IsModal() const { return true; }
-  virtual views::View* GetContentsView() { return this; }
-  virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const;
-  virtual int GetDialogButtons() const {
-    return MessageBoxFlags::DIALOGBUTTON_OK;
-  }
-  virtual std::wstring GetWindowTitle() const;
-
-  // views::View overrides:
-  virtual void Layout();
-  virtual gfx::Size GetPreferredSize();
-
-  // views::TableViewObserver overrides:
-  virtual void OnSelectionChanged();
-
-  // TableModel overrides:
-  // To workaround crbug.com/38266, implement TreeModel as part of
-  // LanguageConfigView class, rather than a separate class.
-  // TODO(satorux): Implement TableModel as a separate class once the bug
-  // is fixed.
-  virtual string16 GetText(int row, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
-  virtual int RowCount() OVERRIDE;
-
-  // views::Combobox::Listener overrides:
-  virtual void ItemChanged(views::Combobox* combobox,
-                           int prev_index,
-                           int new_index);
-
-  // OptionsPageView overrides.
-  virtual void InitControlLayout();
-
-  // Shows the language config dialog in a new window.
-  static void Show(Profile* profile, gfx::NativeWindow parent);
-
- private:
-  // Initializes the input method config view.
-  void InitInputMethodConfigViewMap();
-
-  // Invoked when a language is added by the add combobox.
-  void OnAddLanguage(const std::string& language_code);
-
-  // Invoked when a language is removed by the remove button.
-  void OnRemoveLanguage();
-
-  // Resets the add language combobox to the initial "Add language" state.
-  void ResetAddLanguageCombobox();
-
-  // Creates the contents on the left, including the language table.
-  views::View* CreateContentsOnLeft();
-
-  // Creates the contents on the bottom, including the add language button.
-  views::View* CreateContentsOnBottom();
-
-  // Creates the per-language config view.
-  views::View* CreatePerLanguageConfigView(const std::string& language_code);
-
-  // Adds the UI language section in the per-language config view.
-  void AddUiLanguageSection(const std::string& language_code,
-                            views::GridLayout* layout);
-
-  // Adds the input method section in the per-language config view.
-  void AddInputMethodSection(const std::string& language_code,
-                             views::GridLayout* layout);
-
-  // Creates the input method config view based on the given |input_method_id|.
-  // Returns NULL if the config view is not found.
-  views::DialogDelegate* CreateInputMethodConfigureView(
-      const std::string& input_method_id);
-
-  // If there is only one input method left, disable the selected method.
-  // This is done to prevent the user from disabling all input methods.
-  void MaybeDisableLastCheckbox();
-
-  // Enable all input method checkboxes.
-  void EnableAllCheckboxes();
-
-  // The model of the view.
-  LanguageConfigModel model_;
-
-  // The map of the input method id to a pointer to the function for
-  // creating the input method configuration dialog.
-  typedef views::DialogDelegate* (*CreateDialogDelegateFunction)(Profile*);
-  typedef std::map<std::string,
-                   CreateDialogDelegateFunction> InputMethodConfigViewMap;
-  InputMethodConfigViewMap input_method_config_view_map_;
-
-  // The checkboxes for activating input methods for a language.
-  std::set<InputMethodCheckbox*> input_method_checkboxes_;
-
-  views::View* root_container_;
-  views::View* right_container_;
-  views::NativeButton* remove_language_button_;
-  views::TableView2* preferred_language_table_;
-  scoped_ptr<AddLanguageComboboxModel> add_language_combobox_model_;
-  views::Combobox* add_language_combobox_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageConfigView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_VIEW_H_
diff --git a/chrome/browser/chromeos/options/language_hangul_config_view.cc b/chrome/browser/chromeos/options/language_hangul_config_view.cc
deleted file mode 100644
index a7f0b70..0000000
--- a/chrome/browser/chromeos/options/language_hangul_config_view.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/language_hangul_config_view.h"
-
-#include "app/combobox_model.h"
-#include "app/l10n_util.h"
-#include "base/string16.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/chromeos/preferences.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
-#include "views/window/window.h"
-
-namespace chromeos {
-
-// The combobox model for the list of hangul keyboards.
-class HangulKeyboardComboboxModel : public ComboboxModel {
- public:
-  HangulKeyboardComboboxModel() {
-    for (size_t i = 0; i < language_prefs::kNumHangulKeyboardNameIDPairs;
-         ++i) {
-      layouts_.push_back(std::make_pair(
-          l10n_util::GetStringUTF8(
-              language_prefs::kHangulKeyboardNameIDPairs[i].message_id),
-          language_prefs::kHangulKeyboardNameIDPairs[i].keyboard_id));
-    }
-  }
-
-  // Implements ComboboxModel interface.
-  virtual int GetItemCount() {
-    return static_cast<int>(layouts_.size());
-  }
-
-  // Implements ComboboxModel interface.
-  virtual string16 GetItemAt(int index) {
-    if (index < 0 || index > GetItemCount()) {
-      LOG(ERROR) << "Index is out of bounds: " << index;
-      return string16();
-    }
-    return UTF8ToUTF16(layouts_.at(index).first);
-  }
-
-  // Gets a keyboard layout ID (e.g. "2", "3f", ..) for an item at zero-origin
-  // |index|. This function is NOT part of the ComboboxModel interface.
-  std::string GetItemIDAt(int index) {
-    if (index < 0 || index > GetItemCount()) {
-      LOG(ERROR) << "Index is out of bounds: " << index;
-      return "";
-    }
-    return layouts_.at(index).second;
-  }
-
-  // Gets an index (>= 0) of an item whose keyboard layout ID is |layout_ld|.
-  // Returns -1 if such item is not found. This function is NOT part of the
-  // ComboboxModel interface.
-  int GetIndexFromID(const std::string& layout_id) {
-    for (size_t i = 0; i < layouts_.size(); ++i) {
-      if (GetItemIDAt(i) == layout_id) {
-        return static_cast<int>(i);
-      }
-    }
-    return -1;
-  }
-
- private:
-  std::vector<std::pair<std::string, std::string> > layouts_;
-  DISALLOW_COPY_AND_ASSIGN(HangulKeyboardComboboxModel);
-};
-
-LanguageHangulConfigView::LanguageHangulConfigView(Profile* profile)
-    : OptionsPageView(profile),
-      contents_(NULL),
-      hangul_keyboard_combobox_(NULL),
-      hangul_keyboard_combobox_model_(new HangulKeyboardComboboxModel) {
-  keyboard_pref_.Init(
-      prefs::kLanguageHangulKeyboard, profile->GetPrefs(), this);
-}
-
-LanguageHangulConfigView::~LanguageHangulConfigView() {
-}
-
-void LanguageHangulConfigView::ItemChanged(
-    views::Combobox* sender, int prev_index, int new_index) {
-  const std::string id =
-      hangul_keyboard_combobox_model_->GetItemIDAt(new_index);
-  VLOG(1) << "Changing Hangul keyboard pref to " << id;
-  keyboard_pref_.SetValue(id);
-}
-
-void LanguageHangulConfigView::Layout() {
-  // Not sure why but this is needed to show contents in the dialog.
-  contents_->SetBounds(0, 0, width(), height());
-}
-
-int LanguageHangulConfigView::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK;
-}
-
-std::wstring LanguageHangulConfigView::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK));
-  }
-  return L"";
-}
-
-std::wstring LanguageHangulConfigView::GetWindowTitle() const {
-  return UTF16ToWide(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_TITLE));
-}
-
-gfx::Size LanguageHangulConfigView::GetPreferredSize() {
-  // TODO(satorux): Create our own localized content size once the UI is done.
-  return gfx::Size(views::Window::GetLocalizedContentsSize(
-      IDS_LANGUAGES_INPUT_DIALOG_WIDTH_CHARS,
-      IDS_LANGUAGES_INPUT_DIALOG_HEIGHT_LINES));
-}
-
-void LanguageHangulConfigView::InitControlLayout() {
-  using views::ColumnSet;
-  using views::GridLayout;
-
-  contents_ = new views::View;
-  AddChildView(contents_);
-
-  GridLayout* layout = new GridLayout(contents_);
-  layout->SetInsets(kPanelVertMargin, kPanelHorizMargin,
-                    kPanelVertMargin, kPanelHorizMargin);
-  contents_->SetLayoutManager(layout);
-
-  const int kColumnSetId = 0;
-  ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  layout->StartRow(0, kColumnSetId);
-
-  // Settings for the Hangul IME.
-  layout->AddView(new views::Label(UTF16ToWide(
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_KEYBOARD_LAYOUT_TEXT))));
-
-  hangul_keyboard_combobox_
-      = new views::Combobox(hangul_keyboard_combobox_model_.get());
-  hangul_keyboard_combobox_->set_listener(this);
-
-  // Initialize the combobox to what's saved in user preferences. Otherwise,
-  // ItemChanged() will be called with |new_index| == 0.
-  NotifyPrefChanged();
-  layout->AddView(hangul_keyboard_combobox_);
-}
-
-void LanguageHangulConfigView::Observe(NotificationType type,
-                                       const NotificationSource& source,
-                                       const NotificationDetails& details) {
-  if (type == NotificationType::PREF_CHANGED) {
-    // Observe(PREF_CHANGED) is called when the chromeos::Preferences object
-    // changed the prefs::kLanguageHangulKeyboard preference. Note that this
-    // function is NOT called when this dialog calls keyboard_pref_.SetValue().
-    NotifyPrefChanged();
-  }
-}
-
-void LanguageHangulConfigView::NotifyPrefChanged() {
-  const std::string id = keyboard_pref_.GetValue();
-  const int index =
-      hangul_keyboard_combobox_model_->GetIndexFromID(id);
-  if (index >= 0)
-    hangul_keyboard_combobox_->SetSelectedItem(index);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_hangul_config_view.h b/chrome/browser/chromeos/options/language_hangul_config_view.h
deleted file mode 100644
index 58466b0..0000000
--- a/chrome/browser/chromeos/options/language_hangul_config_view.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_HANGUL_CONFIG_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_HANGUL_CONFIG_VIEW_H_
-#pragma once
-
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/label.h"
-#include "views/window/dialog_delegate.h"
-
-namespace chromeos {
-
-class HangulKeyboardComboboxModel;
-
-// A dialog box for showing Korean input method preferences.
-class LanguageHangulConfigView : public views::Combobox::Listener,
-                                 public views::DialogDelegate,
-                                 public OptionsPageView {
- public:
-  explicit LanguageHangulConfigView(Profile* profile);
-  virtual ~LanguageHangulConfigView();
-
-  // views::Combobox::Listener overrides.
-  virtual void ItemChanged(views::Combobox* sender,
-                           int prev_index,
-                           int new_index);
-
-  // views::DialogDelegate overrides.
-  virtual bool IsModal() const { return true; }
-  virtual views::View* GetContentsView() { return this; }
-  virtual int GetDialogButtons() const;
-  virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const;
-  virtual std::wstring GetWindowTitle() const;
-
-  // views::View overrides.
-  virtual void Layout();
-  virtual gfx::Size GetPreferredSize();
-
-  // OptionsPageView overrides.
-  virtual void InitControlLayout();
-
-  // NotificationObserver overrides.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  // Updates the hangul keyboard combobox.
-  void NotifyPrefChanged();
-
-  StringPrefMember keyboard_pref_;
-  views::View* contents_;
-
-  // A combobox for Hangul keyboard layouts and its model.
-  views::Combobox* hangul_keyboard_combobox_;
-  scoped_ptr<HangulKeyboardComboboxModel> hangul_keyboard_combobox_model_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageHangulConfigView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_HANGUL_CONFIG_VIEW_H_
diff --git a/chrome/browser/chromeos/options/language_mozc_config_view.cc b/chrome/browser/chromeos/options/language_mozc_config_view.cc
deleted file mode 100644
index 16ffe1c..0000000
--- a/chrome/browser/chromeos/options/language_mozc_config_view.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/language_mozc_config_view.h"
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/options/language_config_util.h"
-#include "chrome/browser/chromeos/preferences.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/button/native_button.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
-#include "views/window/window.h"
-
-namespace {
-// The tags are used to identify buttons in ButtonPressed().
-enum ButtonTag {
-  // 0 to kNumMozcBooleanPrefs - 1 are reserved for the checkboxes for integer
-  // preferences.
-  kResetToDefaultsButton = chromeos::language_prefs::kNumMozcBooleanPrefs,
-};
-}  // namespace
-
-namespace chromeos {
-
-LanguageMozcConfigView::LanguageMozcConfigView(Profile* profile)
-    : OptionsPageView(profile),
-      contents_(NULL),
-      reset_to_defaults_button_(NULL) {
-  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
-    MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
-    current.boolean_pref.Init(
-        language_prefs::kMozcBooleanPrefs[i].pref_name, profile->GetPrefs(),
-        this);
-    current.checkbox = NULL;
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    current.multiple_choice_pref.Init(
-        language_prefs::kMozcMultipleChoicePrefs[i].pref_name,
-        profile->GetPrefs(), this);
-    current.combobox_model =
-        new LanguageComboboxModel<const char*>(
-            &language_prefs::kMozcMultipleChoicePrefs[i]);
-    current.combobox = NULL;
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
-    MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
-    current.integer_pref.Init(
-        language_prefs::kMozcIntegerPrefs[i].pref_name, profile->GetPrefs(),
-        this);
-    current.slider = NULL;
-  }
-}
-
-LanguageMozcConfigView::~LanguageMozcConfigView() {
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    delete prefs_and_comboboxes_[i].combobox_model;
-  }
-}
-
-void LanguageMozcConfigView::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  const int pref_id = sender->tag();
-  if (pref_id == kResetToDefaultsButton) {
-    ResetToDefaults();
-    return;
-  }
-  views::Checkbox* checkbox = static_cast<views::Checkbox*>(sender);
-  DCHECK(pref_id >= 0 && pref_id < static_cast<int>(
-      language_prefs::kNumMozcBooleanPrefs));
-  prefs_and_checkboxes_[pref_id].boolean_pref.SetValue(checkbox->checked());
-}
-
-void LanguageMozcConfigView::ItemChanged(
-    views::Combobox* sender, int prev_index, int new_index) {
-  if (new_index < 0 || sender->model()->GetItemCount() <= new_index) {
-    LOG(ERROR) << "Invalid new_index: " << new_index;
-    return;
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    if (current.combobox == sender) {
-      const std::string config_value =
-          current.combobox_model->GetConfigValueAt(new_index);
-      VLOG(1) << "Changing Mozc pref to " << config_value;
-      // Update the Chrome pref.
-      current.multiple_choice_pref.SetValue(config_value);
-      break;
-    }
-  }
-}
-
-void LanguageMozcConfigView::SliderValueChanged(views::Slider* sender) {
-  size_t pref_id;
-  for (pref_id = 0; pref_id < language_prefs::kNumMozcIntegerPrefs;
-       ++pref_id) {
-    if (prefs_and_sliders_[pref_id].slider == sender)
-      break;
-  }
-  DCHECK(pref_id < language_prefs::kNumMozcIntegerPrefs);
-  prefs_and_sliders_[pref_id].integer_pref.SetValue(sender->value());
-}
-
-void LanguageMozcConfigView::Layout() {
-  // Not sure why but this is needed to show contents in the dialog.
-  contents_->SetBounds(0, 0, width(), height());
-}
-
-int LanguageMozcConfigView::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK;
-}
-
-std::wstring LanguageMozcConfigView::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK));
-  }
-  return L"";
-}
-
-std::wstring LanguageMozcConfigView::GetWindowTitle() const {
-  return UTF16ToWide(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_LANGUAGES_MOZC_SETTINGS_TITLE));
-}
-
-gfx::Size LanguageMozcConfigView::GetPreferredSize() {
-  // TODO(satorux): Create our own localized content size once the UI is done.
-  gfx::Size preferred_size = views::Window::GetLocalizedContentsSize(
-      IDS_LANGUAGES_INPUT_DIALOG_WIDTH_CHARS,
-      IDS_LANGUAGES_INPUT_DIALOG_HEIGHT_LINES);
-  // TODO(mazda): Remove the manual adjustment.
-  // The padding is needed for accommodating all the controls in the dialog.
-  const int kHeightPadding = 80;
-  preferred_size.Enlarge(0, kHeightPadding);
-  return preferred_size;
-}
-
-void LanguageMozcConfigView::InitControlLayout() {
-  using views::ColumnSet;
-  using views::GridLayout;
-
-  contents_ = new views::View;
-  AddChildView(contents_);
-
-  GridLayout* layout = new GridLayout(contents_);
-  layout->SetInsets(kPanelVertMargin, kPanelHorizMargin,
-                    kPanelVertMargin, kPanelHorizMargin);
-  contents_->SetLayoutManager(layout);
-
-  const int kColumnSetId = 0;
-  ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
-    MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
-    current.checkbox = new views::Checkbox(UTF16ToWide(
-        l10n_util::GetStringUTF16(
-            language_prefs::kMozcBooleanPrefs[i].message_id)));
-    current.checkbox->set_listener(this);
-    current.checkbox->set_tag(i);
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    current.combobox = new LanguageCombobox(current.combobox_model);
-    current.combobox->set_listener(this);
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
-    MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
-    current.slider = new views::Slider(
-        language_prefs::kMozcIntegerPrefs[i].min_pref_value,
-        language_prefs::kMozcIntegerPrefs[i].max_pref_value,
-        1,
-        static_cast<views::Slider::StyleFlags>(
-            views::Slider::STYLE_DRAW_VALUE |
-            views::Slider::STYLE_UPDATE_ON_RELEASE),
-        this);
-  }
-  NotifyPrefChanged();  // Sync the comboboxes with current Chrome prefs.
-
-  reset_to_defaults_button_ = new views::NativeButton(
-      this, UTF16ToWide(l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_MOZC_RESET_TO_DEFAULTS_BUTTON)));
-  reset_to_defaults_button_->set_tag(kResetToDefaultsButton);
-  layout->StartRow(0, kColumnSetId);
-  layout->AddView(reset_to_defaults_button_);
-
-  // Show the checkboxes.
-  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
-    const MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(current.checkbox, 3, 1);
-  }
-  // Show the comboboxes.
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    const MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(new views::Label(current.combobox_model->GetLabel()));
-    layout->AddView(current.combobox);
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
-    const MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(new views::Label(
-        UTF16ToWide(l10n_util::GetStringUTF16(
-            language_prefs::kMozcIntegerPrefs[i].message_id))));
-    layout->AddView(current.slider);
-  }
-  NotifyPrefChanged();  // Sync the slider with current Chrome prefs.
-}
-
-void LanguageMozcConfigView::Observe(NotificationType type,
-                                     const NotificationSource& source,
-                                     const NotificationDetails& details) {
-  if (type == NotificationType::PREF_CHANGED) {
-    NotifyPrefChanged();
-  }
-}
-
-void LanguageMozcConfigView::NotifyPrefChanged() {
-  // Update comboboxes.
-  // TODO(yusukes): We don't have to update all UI controls.
-  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
-    MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
-    const bool checked = current.boolean_pref.GetValue();
-    current.checkbox->SetChecked(checked);
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
-    const std::string value = current.multiple_choice_pref.GetValue();
-    for (int i = 0; i < current.combobox_model->num_items(); ++i) {
-      if (current.combobox_model->GetConfigValueAt(i) == value) {
-        current.combobox->SetSelectedItem(i);
-        break;
-      }
-    }
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
-    MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
-    const int value = current.integer_pref.GetValue();
-    current.slider->SetValue(value);
-  }
-}
-
-void LanguageMozcConfigView::ResetToDefaults() {
-  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
-    prefs_and_checkboxes_[i].boolean_pref.SetValue(
-        language_prefs::kMozcBooleanPrefs[i].default_pref_value);
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
-    prefs_and_comboboxes_[i].multiple_choice_pref.SetValue(
-        language_prefs::kMozcMultipleChoicePrefs[i].default_pref_value);
-  }
-  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
-    prefs_and_sliders_[i].integer_pref.SetValue(
-        language_prefs::kMozcIntegerPrefs[i].default_pref_value);
-  }
-  // Reflect the preference changes to the controls.
-  NotifyPrefChanged();
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_mozc_config_view.h b/chrome/browser/chromeos/options/language_mozc_config_view.h
deleted file mode 100644
index 496ec14..0000000
--- a/chrome/browser/chromeos/options/language_mozc_config_view.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_MOZC_CONFIG_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_MOZC_CONFIG_VIEW_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/label.h"
-#include "views/controls/slider/slider.h"
-#include "views/window/dialog_delegate.h"
-
-namespace views {
-class Button;
-class Checkbox;
-}
-
-namespace chromeos {
-
-class LanguageCombobox;
-template <typename DataType>
-class LanguageComboboxModel;
-
-// A dialog box for showing Mozc (Japanese input method) preferences.
-class LanguageMozcConfigView : public views::ButtonListener,
-                               public views::Combobox::Listener,
-                               public views::DialogDelegate,
-                               public views::SliderListener,
-                               public OptionsPageView {
- public:
-  explicit LanguageMozcConfigView(Profile* profile);
-  virtual ~LanguageMozcConfigView();
-
-  // views::ButtonListener overrides.
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // views::Combobox::Listener overrides.
-  virtual void ItemChanged(views::Combobox* sender,
-                           int prev_index,
-                           int new_index);
-
-  // views::SliderListener overrides.
-  virtual void SliderValueChanged(views::Slider* sender);
-
-  // views::DialogDelegate overrides.
-  virtual bool IsModal() const { return true; }
-  virtual views::View* GetContentsView() { return this; }
-  virtual int GetDialogButtons() const;
-  virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const;
-  virtual std::wstring GetWindowTitle() const;
-
-  // views::View overrides.
-  virtual void Layout();
-  virtual gfx::Size GetPreferredSize();
-
-  // OptionsPageView overrides.
-  virtual void InitControlLayout();
-
-  // NotificationObserver overrides.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  // Updates the mozc keyboard combobox.
-  void NotifyPrefChanged();
-
-  // Resets all the preferences to the default values.
-  void ResetToDefaults();
-
-  views::View* contents_;
-
-  views::Button* reset_to_defaults_button_;
-
-  struct MozcPrefAndAssociatedCheckbox {
-    BooleanPrefMember boolean_pref;
-    views::Checkbox* checkbox;
-  } prefs_and_checkboxes_[language_prefs::kNumMozcBooleanPrefs];
-
-  struct MozcPrefAndAssociatedCombobox {
-    StringPrefMember multiple_choice_pref;
-    LanguageComboboxModel<const char*>* combobox_model;
-    LanguageCombobox* combobox;
-  } prefs_and_comboboxes_[language_prefs::kNumMozcMultipleChoicePrefs];
-
-  struct MozcPrefAndAssociatedSlider {
-    IntegerPrefMember integer_pref;
-    views::Slider* slider;
-  } prefs_and_sliders_[language_prefs::kNumMozcIntegerPrefs];
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageMozcConfigView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_MOZC_CONFIG_VIEW_H_
diff --git a/chrome/browser/chromeos/options/language_pinyin_config_view.cc b/chrome/browser/chromeos/options/language_pinyin_config_view.cc
deleted file mode 100644
index ce627b0..0000000
--- a/chrome/browser/chromeos/options/language_pinyin_config_view.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/language_pinyin_config_view.h"
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/options/language_config_util.h"
-#include "chrome/browser/chromeos/preferences.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
-#include "views/window/window.h"
-
-namespace chromeos {
-
-LanguagePinyinConfigView::LanguagePinyinConfigView(Profile* profile)
-    : OptionsPageView(profile), contents_(NULL) {
-  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
-    pinyin_boolean_prefs_[i].Init(
-        language_prefs::kPinyinBooleanPrefs[i].pref_name, profile->GetPrefs(),
-        this);
-    pinyin_boolean_checkboxes_[i] = NULL;
-  }
-
-  double_pinyin_schema_.multiple_choice_pref.Init(
-      language_prefs::kPinyinDoublePinyinSchema.pref_name,
-      profile->GetPrefs(), this);
-  double_pinyin_schema_.combobox_model =
-      new LanguageComboboxModel<int>(
-          &language_prefs::kPinyinDoublePinyinSchema);
-  double_pinyin_schema_.combobox = NULL;
-}
-
-LanguagePinyinConfigView::~LanguagePinyinConfigView() {
-}
-
-void LanguagePinyinConfigView::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  views::Checkbox* checkbox = static_cast<views::Checkbox*>(sender);
-  const int pref_id = checkbox->tag();
-  DCHECK(pref_id >= 0 && pref_id < static_cast<int>(
-      language_prefs::kNumPinyinBooleanPrefs));
-  pinyin_boolean_prefs_[pref_id].SetValue(checkbox->checked());
-}
-
-void LanguagePinyinConfigView::ItemChanged(
-    views::Combobox* sender, int prev_index, int new_index) {
-  if (double_pinyin_schema_.combobox == sender) {
-    const int config_value =
-        double_pinyin_schema_.combobox_model->GetConfigValueAt(new_index);
-    VLOG(1) << "Changing Pinyin pref to " << config_value;
-    // Update the Chrome pref.
-    double_pinyin_schema_.multiple_choice_pref.SetValue(config_value);
-  }
-}
-
-void LanguagePinyinConfigView::Layout() {
-  // Not sure why but this is needed to show contents in the dialog.
-  contents_->SetBounds(0, 0, width(), height());
-}
-
-int LanguagePinyinConfigView::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK;
-}
-
-std::wstring LanguagePinyinConfigView::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK));
-  }
-  return L"";
-}
-
-std::wstring LanguagePinyinConfigView::GetWindowTitle() const {
-  return UTF16ToWide(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTINGS_TITLE));
-}
-
-gfx::Size LanguagePinyinConfigView::GetPreferredSize() {
-  // TODO(satorux): Create our own localized content size once the UI is done.
-  return gfx::Size(views::Window::GetLocalizedContentsSize(
-      IDS_LANGUAGES_INPUT_DIALOG_WIDTH_CHARS,
-      IDS_LANGUAGES_INPUT_DIALOG_HEIGHT_LINES));
-}
-
-void LanguagePinyinConfigView::InitControlLayout() {
-  using views::ColumnSet;
-  using views::GridLayout;
-
-  contents_ = new views::View;
-  AddChildView(contents_);
-
-  GridLayout* layout = new GridLayout(contents_);
-  layout->SetInsets(kPanelVertMargin, kPanelHorizMargin,
-                    kPanelVertMargin, kPanelHorizMargin);
-  contents_->SetLayoutManager(layout);
-
-  const int kColumnSetId = 0;
-  ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-
-  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
-    pinyin_boolean_checkboxes_[i] = new views::Checkbox(
-        UTF16ToWide(l10n_util::GetStringUTF16(
-            language_prefs::kPinyinBooleanPrefs[i].message_id)));
-    pinyin_boolean_checkboxes_[i]->set_listener(this);
-    pinyin_boolean_checkboxes_[i]->set_tag(i);
-  }
-  double_pinyin_schema_.combobox =
-      new LanguageCombobox(double_pinyin_schema_.combobox_model);
-  double_pinyin_schema_.combobox->set_listener(this);
-
-  NotifyPrefChanged();
-  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
-    layout->StartRow(0, kColumnSetId);
-    layout->AddView(pinyin_boolean_checkboxes_[i]);
-  }
-  layout->StartRow(0, kColumnSetId);
-  layout->AddView(
-      new views::Label(double_pinyin_schema_.combobox_model->GetLabel()));
-  layout->AddView(double_pinyin_schema_.combobox);
-}
-
-void LanguagePinyinConfigView::Observe(NotificationType type,
-                                       const NotificationSource& source,
-                                       const NotificationDetails& details) {
-  if (type == NotificationType::PREF_CHANGED) {
-    NotifyPrefChanged();
-  }
-}
-
-void LanguagePinyinConfigView::NotifyPrefChanged() {
-  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
-    const bool checked = pinyin_boolean_prefs_[i].GetValue();
-    pinyin_boolean_checkboxes_[i]->SetChecked(checked);
-  }
-  const int value = double_pinyin_schema_.multiple_choice_pref.GetValue();
-  for (int i = 0; i < double_pinyin_schema_.combobox_model->num_items(); ++i) {
-    if (double_pinyin_schema_.combobox_model->GetConfigValueAt(i) == value) {
-      double_pinyin_schema_.combobox->SetSelectedItem(i);
-      break;
-    }
-  }
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/language_pinyin_config_view.h b/chrome/browser/chromeos/options/language_pinyin_config_view.h
deleted file mode 100644
index 6d38bd5..0000000
--- a/chrome/browser/chromeos/options/language_pinyin_config_view.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_PINYIN_CONFIG_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_PINYIN_CONFIG_VIEW_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/label.h"
-#include "views/window/dialog_delegate.h"
-
-namespace chromeos {
-
-class LanguageCombobox;
-template <typename DataType>
-class LanguageComboboxModel;
-
-// A dialog box for showing Traditional Chinese (Pinyin) input method
-// preferences.
-class LanguagePinyinConfigView : public views::ButtonListener,
-                                 public views::Combobox::Listener,
-                                 public views::DialogDelegate,
-                                 public OptionsPageView {
- public:
-  explicit LanguagePinyinConfigView(Profile* profile);
-  virtual ~LanguagePinyinConfigView();
-
-  // views::ButtonListener overrides.
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // views::Combobox::Listener overrides.
-  virtual void ItemChanged(views::Combobox* sender,
-                           int prev_index,
-                           int new_index);
-
-  // views::DialogDelegate overrides.
-  virtual bool IsModal() const { return true; }
-  virtual views::View* GetContentsView() { return this; }
-  virtual int GetDialogButtons() const;
-  virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const;
-  virtual std::wstring GetWindowTitle() const;
-
-  // views::View overrides.
-  virtual void Layout();
-  virtual gfx::Size GetPreferredSize();
-
-  // OptionsPageView overrides.
-  virtual void InitControlLayout();
-
-  // NotificationObserver overrides.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  // Updates the pinyin checkboxes.
-  void NotifyPrefChanged();
-
-  BooleanPrefMember pinyin_boolean_prefs_[
-      language_prefs::kNumPinyinBooleanPrefs];
-  // TODO(yusukes): Support integer prefs if needed.
-  views::View* contents_;
-
-  // A checkboxes for Pinyin.
-  views::Checkbox* pinyin_boolean_checkboxes_[
-      language_prefs::kNumPinyinBooleanPrefs];
-
-  struct DoublePinyinSchemaPrefAndAssociatedCombobox {
-    IntegerPrefMember multiple_choice_pref;
-    LanguageComboboxModel<int>* combobox_model;
-    LanguageCombobox* combobox;
-  } double_pinyin_schema_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguagePinyinConfigView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_PINYIN_CONFIG_VIEW_H_
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 45c1ec3..59c1d84 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,15 +6,15 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/options/wifi_config_view.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget_gtk.h"
 #include "views/window/window.h"
 
@@ -38,7 +38,8 @@
 }
 
 gfx::NativeWindow NetworkConfigView::GetNativeWindow() const {
-  return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
+  return
+      GTK_WINDOW(static_cast<const WidgetGtk*>(GetWidget())->GetNativeView());
 }
 
 std::wstring NetworkConfigView::GetDialogButtonLabel(
diff --git a/chrome/browser/chromeos/options/options_window_view.cc b/chrome/browser/chromeos/options/options_window_view.cc
deleted file mode 100644
index 320bec6..0000000
--- a/chrome/browser/chromeos/options/options_window_view.cc
+++ /dev/null
@@ -1,393 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/l10n_util.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/options/internet_page_view.h"
-#include "chrome/browser/chromeos/options/system_page_view.h"
-#include "chrome/browser/gtk/options/advanced_page_gtk.h"
-#include "chrome/browser/gtk/options/content_page_gtk.h"
-#include "chrome/browser/gtk/options/general_page_gtk.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/options/options_window.h"
-#include "chrome/browser/ui/views/accessible_view_helper.h"
-#include "chrome/browser/ui/views/window.h"
-#include "chrome/browser/ui/window_sizer.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/pref_names.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "views/controls/native/native_view_host.h"
-#include "views/controls/tabbed_pane/native_tabbed_pane_gtk.h"
-#include "views/controls/tabbed_pane/tabbed_pane.h"
-#include "views/widget/root_view.h"
-#include "views/window/dialog_delegate.h"
-#include "views/window/window.h"
-#include "views/window/window_gtk.h"
-
-
-namespace chromeos {
-
-///////////////////////////////////////////////////////////////////////////////
-// GtkPreferencePageHost
-//
-//  Hosts a GTK preference page and takes care of sizing it appropriately.
-//
-class GtkPreferencePageHost : public views::NativeViewHost {
- public:
-  explicit GtkPreferencePageHost(GtkWidget* widget);
-
- private:
-  // views::View overrides:
-  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
-  virtual gfx::Size GetPreferredSize();
-
-  GtkWidget* widget_;
-
-  DISALLOW_COPY_AND_ASSIGN(GtkPreferencePageHost);
-};
-
-GtkPreferencePageHost::GtkPreferencePageHost(GtkWidget* widget)
-    : widget_(widget) {
-  set_background(views::Background::CreateSolidBackground(SK_ColorWHITE));
-}
-
-void GtkPreferencePageHost::ViewHierarchyChanged(bool is_add,
-                                                 View* parent,
-                                                 View* child) {
-  NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
-  if (is_add && child == this)
-    Attach(widget_);
-}
-
-gfx::Size GtkPreferencePageHost::GetPreferredSize() {
-  // We need to show the widget and its children since otherwise containers like
-  // gtk_box don't compute the correct size.
-  gtk_widget_show_all(widget_);
-  GtkRequisition requisition = { 0, 0 };
-  gtk_widget_size_request(GTK_WIDGET(widget_), &requisition);
-  GtkRequisition& size(widget_->requisition);
-  return gfx::Size(size.width, size.height);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowView
-//
-//  The contents of the Options dialog window.
-//
-class OptionsWindowView : public views::View,
-                          public views::DialogDelegate,
-                          public views::TabbedPane::Listener {
- public:
-  static const int kDialogPadding;
-  static const SkColor kDialogBackground;
-  static OptionsWindowView* instance_;
-
-  explicit OptionsWindowView(Profile* profile);
-  virtual ~OptionsWindowView();
-
-  // Shows the Tab corresponding to the specified OptionsPage.
-  void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group);
-
-  // views::DialogDelegate implementation:
-  virtual int GetDialogButtons() const {
-    return 0;
-  }
-  virtual std::wstring GetWindowTitle() const;
-  virtual void WindowClosing();
-  virtual bool Cancel();
-  virtual views::View* GetContentsView();
-  virtual bool ShouldShowClientEdge() const {
-    return false;
-  }
-
-  // views::TabbedPane::Listener implementation:
-  virtual void TabSelectedAt(int index);
-
-  // views::View overrides:
-  virtual void Layout();
-  virtual gfx::Size GetPreferredSize();
-
- protected:
-  // views::View overrides:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
- private:
-  // Init the assorted Tabbed pages
-  void Init();
-
-  // Returns the currently selected OptionsPageView.
-  OptionsPageView* GetCurrentOptionsPageView() const;
-
-  // Flag of whether we are fully initialized.
-  bool initialized_;
-
-  // The Tab view that contains all of the options pages.
-  views::TabbedPane* tabs_;
-
-  // The Profile associated with these options.
-  Profile* profile_;
-
-  // Native Gtk options pages.
-  GeneralPageGtk general_page_;
-  ContentPageGtk content_page_;
-  AdvancedPageGtk advanced_page_;
-
-  // The last page the user was on when they opened the Options window.
-  IntegerPrefMember last_selected_page_;
-
-  scoped_ptr<AccessibleViewHelper> accessible_view_helper_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(OptionsWindowView);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowView, public:
-
-// No dialog padding.
-const int OptionsWindowView::kDialogPadding = 0;
-
-// Shaded frame color that matches the rendered frame. It's the result
-// of SRC_OVER frame top center image on top of frame color.
-const SkColor OptionsWindowView::kDialogBackground =
-    SkColorSetRGB(0x4E, 0x7D, 0xD0);
-
-// Live instance of the options view.
-OptionsWindowView* OptionsWindowView::instance_ = NULL;
-
-OptionsWindowView::OptionsWindowView(Profile* profile)
-      // Always show preferences for the original profile. Most state when off
-      // the record comes from the original profile, but we explicitly use
-      // the original profile to avoid potential problems.
-    : initialized_(false),
-      tabs_(NULL),
-      profile_(profile->GetOriginalProfile()),
-      general_page_(profile_),
-      content_page_(profile_),
-      advanced_page_(profile_) {
-  // We don't need to observe changes in this value.
-  last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex,
-                           g_browser_process->local_state(), NULL);
-
-  set_background(views::Background::CreateSolidBackground(kDialogBackground));
-}
-
-OptionsWindowView::~OptionsWindowView() {
-}
-
-void OptionsWindowView::ShowOptionsPage(OptionsPage page,
-                                        OptionsGroup highlight_group) {
-  // This will show invisible windows and bring visible windows to the front.
-  window()->Show();
-
-  // Show all controls in tab after tab's size is allocated. We have
-  // to do this after size allocation otherwise WrapLabelAtAllocationHack
-  // in ContentPageGtk would break.
-  GtkWidget* notebook = static_cast<views::NativeTabbedPaneGtk*>(
-      tabs_->native_wrapper())->native_view();
-  gtk_widget_show_all(notebook);
-
-  if (page == OPTIONS_PAGE_DEFAULT) {
-    // Remember the last visited page from local state.
-    page = static_cast<OptionsPage>(last_selected_page_.GetValue());
-    if (page == OPTIONS_PAGE_DEFAULT)
-      page = OPTIONS_PAGE_GENERAL;
-  }
-  // If the page number is out of bounds, reset to the first tab.
-  if (page < 0 || page >= tabs_->GetTabCount())
-    page = OPTIONS_PAGE_GENERAL;
-
-  tabs_->SelectTabAt(static_cast<int>(page));
-
-  // TODO(xiyuan): set highlight_group
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowView, views::DialogDelegate implementation:
-
-std::wstring OptionsWindowView::GetWindowTitle() const {
-  return UTF16ToWide(
-      l10n_util::GetStringFUTF16(IDS_OPTIONS_DIALOG_TITLE,
-                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
-}
-
-void OptionsWindowView::WindowClosing() {
-  // Clear the static instance so that the next time ShowOptionsWindow() is
-  // called a new window is opened.
-  instance_ = NULL;
-}
-
-bool OptionsWindowView::Cancel() {
-  OptionsPageView* selected_option_page = GetCurrentOptionsPageView();
-  if (selected_option_page) {
-    return selected_option_page->CanClose();
-  } else {
-    // Gtk option pages does not support CanClose.
-    return true;
-  }
-}
-
-views::View* OptionsWindowView::GetContentsView() {
-  return this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowView, views::TabbedPane::Listener implementation:
-
-void OptionsWindowView::TabSelectedAt(int index) {
-  if (!initialized_)
-    return;
-
-  DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT);
-  last_selected_page_.SetValue(index);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowView, views::View overrides:
-
-void OptionsWindowView::Layout() {
-  tabs_->SetBounds(kDialogPadding, kDialogPadding,
-                   width() - (2 * kDialogPadding),
-                   height() - (2 * kDialogPadding));
-  if (!accessible_view_helper_.get()) {
-    accessible_view_helper_.reset(new AccessibleViewHelper(this, profile_));
-  }
-}
-
-gfx::Size OptionsWindowView::GetPreferredSize() {
-  gfx::Size size(tabs_->GetPreferredSize());
-  size.Enlarge(2 * kDialogPadding, 2 * kDialogPadding);
-  return size;
-}
-
-void OptionsWindowView::ViewHierarchyChanged(bool is_add,
-                                             views::View* parent,
-                                             views::View* child) {
-  // Can't init before we're inserted into a Container, because we require a
-  // HWND to parent native child controls to.
-  if (is_add && child == this)
-    Init();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowView, private:
-
-void OptionsWindowView::Init() {
-  tabs_ = new views::TabbedPane;
-  tabs_->SetListener(this);
-  AddChildView(tabs_);
-
-  GtkWidget* notebook = static_cast<views::NativeTabbedPaneGtk*>(
-      tabs_->native_wrapper())->native_view();
-
-  // Set vertical padding of tab header.
-  gtk_notebook_set_tab_vborder(GTK_NOTEBOOK(notebook), 5);
-
-  // Set a name for notebook. Note that the name is also used in theme engine
-  // to apply specific drawings for this widget.
-  gtk_widget_set_name(GTK_WIDGET(notebook), "chromeos-options-tab");
-
-  // Setup tab pages.
-  int tab_index = 0;
-
-  SystemPageView* system_page = new SystemPageView(profile_);
-  system_page->set_background(views::Background::CreateSolidBackground(
-      SK_ColorWHITE));
-  tabs_->AddTabAtIndex(tab_index++,
-                       UTF16ToWide(l10n_util::GetStringUTF16(
-                           IDS_OPTIONS_SYSTEM_TAB_LABEL)),
-                       system_page, false);
-
-  InternetPageView* internet_page = new InternetPageView(profile_);
-  internet_page->set_background(views::Background::CreateSolidBackground(
-      SK_ColorWHITE));
-  tabs_->AddTabAtIndex(tab_index++,
-                       UTF16ToWide(l10n_util::GetStringUTF16(
-                           IDS_OPTIONS_INTERNET_TAB_LABEL)),
-                       internet_page, false);
-
-  tabs_->AddTabAtIndex(tab_index++,
-                       UTF16ToWide(l10n_util::GetStringUTF16(
-                           IDS_OPTIONS_GENERAL_TAB_LABEL)),
-                       new GtkPreferencePageHost(
-                           general_page_.get_page_widget()),
-                       false);
-
-  tabs_->AddTabAtIndex(tab_index++,
-                       UTF16ToWide(l10n_util::GetStringUTF16(
-                           IDS_OPTIONS_CONTENT_TAB_LABEL)),
-                       new GtkPreferencePageHost(
-                           content_page_.get_page_widget()),
-                       false);
-
-  tabs_->AddTabAtIndex(tab_index++,
-                       UTF16ToWide(l10n_util::GetStringUTF16(
-                           IDS_OPTIONS_ADVANCED_TAB_LABEL)),
-                       new GtkPreferencePageHost(
-                           advanced_page_.get_page_widget()),
-                       false);
-
-  DCHECK(tabs_->GetTabCount() == OPTIONS_PAGE_COUNT);
-
-  initialized_ = true;
-}
-
-OptionsPageView* OptionsWindowView::GetCurrentOptionsPageView() const {
-  int selected_option_page = tabs_->GetSelectedTabIndex();
-  if (selected_option_page < OPTIONS_PAGE_GENERAL) {
-    return static_cast<OptionsPageView*>(tabs_->GetSelectedTab());
-  } else {
-    return NULL;
-  }
-}
-
-void CloseOptionsWindow() {
-  if (OptionsWindowView::instance_)
-    OptionsWindowView::instance_->window()->Close();
-}
-
-gfx::NativeWindow GetOptionsViewParent() {
-  if (Browser* b = BrowserList::GetLastActive()) {
-    if (b->type() != Browser::TYPE_NORMAL) {
-      b = BrowserList::FindBrowserWithType(b->profile(),
-                                           Browser::TYPE_NORMAL,
-                                           true);
-    }
-
-    if (b)
-      return b->window()->GetNativeHandle();
-  }
-
-  return NULL;
-}
-
-};  // namespace chromeos
-
-///////////////////////////////////////////////////////////////////////////////
-// Factory/finder method:
-
-void ShowOptionsWindow(OptionsPage page,
-                       OptionsGroup highlight_group,
-                       Profile* profile) {
-  DCHECK(profile);
-
-  using chromeos::OptionsWindowView;
-
-  // If there's already an existing options window, close it and create
-  // a new one for the current active browser.
-  chromeos::CloseOptionsWindow();
-
-  OptionsWindowView::instance_ = new OptionsWindowView(profile);
-  browser::CreateViewsWindow(chromeos::GetOptionsViewParent(),
-                             gfx::Rect(),
-                             OptionsWindowView::instance_);
-
-  OptionsWindowView::instance_->ShowOptionsPage(page, highlight_group);
-}
diff --git a/chrome/browser/chromeos/options/options_window_view.h b/chrome/browser/chromeos/options/options_window_view.h
deleted file mode 100644
index 784ec8d..0000000
--- a/chrome/browser/chromeos/options/options_window_view.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_OPTIONS_WINDOW_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_OPTIONS_WINDOW_VIEW_H_
-#pragma once
-
-namespace chromeos {
-
-// Closes the options dialog.
-void CloseOptionsWindow();
-
-// Get a proper parent for options dialogs. This returns the last active browser
-// window for now.
-gfx::NativeWindow GetOptionsViewParent();
-
-}
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_OPTIONS_WINDOW_VIEW_H_
diff --git a/chrome/browser/chromeos/options/settings_page_view.cc b/chrome/browser/chromeos/options/settings_page_view.cc
deleted file mode 100644
index b4b9d73..0000000
--- a/chrome/browser/chromeos/options/settings_page_view.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/settings_page_view.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "gfx/skia_utils_gtk.h"
-#include "views/controls/label.h"
-#include "views/fill_layout.h"
-#include "views/widget/widget_gtk.h"
-
-namespace chromeos {
-
-SettingsPageView::SettingsPageView(Profile* profile)
-    : OptionsPageView(profile) {
-  SetLayoutManager(new views::FillLayout());
-}
-
-GtkWidget* SettingsPageView::WrapInGtkWidget() {
-  views::WidgetGtk* widget =
-      new views::WidgetGtk(views::WidgetGtk::TYPE_CHILD);
-  widget->Init(NULL, gfx::Rect());
-  widget->SetContentsView(this);
-  // Set to a solid background with the same color as the widget's bg color.
-  GtkStyle* window_style = gtk_widget_get_style(widget->GetNativeView());
-  set_background(views::Background::CreateSolidBackground(
-      gfx::GdkColorToSkColor(window_style->bg[GTK_STATE_NORMAL])));
-  widget->Show();
-  // Removing the widget from the container results in unref'ing the widget. We
-  // need to ref here otherwise the removal deletes the widget. The caller ends
-  // up taking ownership.
-  g_object_ref(widget->GetNativeView());
-  GtkWidget* parent = gtk_widget_get_parent(widget->GetNativeView());
-  gtk_container_remove(GTK_CONTAINER(parent), widget->GetNativeView());
-  return widget->GetNativeView();
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// SettingsPageSection
-
-SettingsPageSection::SettingsPageSection(Profile* profile, int title_msg_id)
-    : OptionsPageView(profile),
-      title_msg_id_(title_msg_id),
-      // Using 1000 so that it does not clash with ids defined in subclasses.
-      single_column_view_set_id_(1000),
-      double_column_view_set_id_(1001) {
-}
-
-void SettingsPageSection::InitControlLayout() {
-  GridLayout* layout = new GridLayout(this);
-  SetLayoutManager(layout);
-
-  int single_column_layout_id = 0;
-  ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
-  column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  int inset_column_layout_id = 1;
-  column_set = layout->AddColumnSet(inset_column_layout_id);
-  column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  layout->StartRow(0, single_column_layout_id);
-  views::Label* title_label = new views::Label(
-      UTF16ToWide(l10n_util::GetStringUTF16(title_msg_id_)));
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  gfx::Font title_font =
-      rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD);
-  title_label->SetFont(title_font);
-  layout->AddView(title_label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-  layout->StartRow(0, inset_column_layout_id);
-
-  views::View* contents = new views::View;
-  GridLayout* child_layout = new GridLayout(contents);
-  contents->SetLayoutManager(child_layout);
-
-  column_set = child_layout->AddColumnSet(single_column_view_set_id_);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  column_set = child_layout->AddColumnSet(double_column_view_set_id_);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
-                        GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  InitContents(child_layout);
-  layout->AddView(contents);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/settings_page_view.h b/chrome/browser/chromeos/options/settings_page_view.h
deleted file mode 100644
index 35e9934..0000000
--- a/chrome/browser/chromeos/options/settings_page_view.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_SETTINGS_PAGE_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_SETTINGS_PAGE_VIEW_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/views/options/options_page_view.h"
-
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
-
-using views::ColumnSet;
-using views::GridLayout;
-
-namespace chromeos {
-
-class SettingsContentsView;
-
-// Settings page for Chrome OS.
-class SettingsPageView : public OptionsPageView {
- public:
-  explicit SettingsPageView(Profile* profile);
-
-  // Wraps the SettingsPageView in a GtkWidget and returns it. It's up to the
-  // caller to delete (unref) the returned widget, which in turn deletes this
-  // SettingsPageView.
-  GtkWidget* WrapInGtkWidget();
-
- protected:
-  virtual void InitControlLayout() = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(SettingsPageView);
-};
-
-// Base section class settings
-class SettingsPageSection : public OptionsPageView {
- public:
-  explicit SettingsPageSection(Profile* profile, int title_msg_id);
-  virtual ~SettingsPageSection() {}
-
- protected:
-  // OptionsPageView overrides:
-  virtual void InitControlLayout();
-  virtual void InitContents(GridLayout* layout) = 0;
-
-  int single_column_view_set_id() const { return single_column_view_set_id_; }
-  int double_column_view_set_id() const { return double_column_view_set_id_; }
-
- private:
-  // The message id for the title of this section.
-  int title_msg_id_;
-
-  int single_column_view_set_id_;
-  int double_column_view_set_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SettingsPageSection);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_SETTINGS_PAGE_VIEW_H_
diff --git a/chrome/browser/chromeos/options/system_page_view.cc b/chrome/browser/chromeos/options/system_page_view.cc
deleted file mode 100644
index a314679..0000000
--- a/chrome/browser/chromeos/options/system_page_view.cc
+++ /dev/null
@@ -1,539 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/options/system_page_view.h"
-
-#include <string>
-#include <vector>
-
-#include "app/combobox_model.h"
-#include "app/l10n_util.h"
-#include "base/stl_util-inl.h"
-#include "base/string16.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/keyboard_library.h"
-#include "chrome/browser/chromeos/cros/system_library.h"
-#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/chromeos/options/language_config_util.h"
-#include "chrome/browser/chromeos/options/language_config_view.h"
-#include "chrome/browser/chromeos/options/options_window_view.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "unicode/timezone.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/button/native_button.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/slider/slider.h"
-#include "views/window/window.h"
-
-namespace chromeos {
-
-////////////////////////////////////////////////////////////////////////////////
-// DateTimeSection
-
-// Date/Time section for datetime settings
-class DateTimeSection : public SettingsPageSection,
-                        public views::Combobox::Listener,
-                        public SystemLibrary::Observer {
- public:
-  explicit DateTimeSection(Profile* profile);
-  virtual ~DateTimeSection();
-
-  // Overridden from views::Combobox::Listener:
-  virtual void ItemChanged(views::Combobox* sender,
-                           int prev_index,
-                           int new_index);
-
-  // Overridden from SystemLibrary::Observer:
-  virtual void TimezoneChanged(const icu::TimeZone& timezone);
-
- protected:
-  // SettingsPageSection overrides:
-  virtual void InitContents(GridLayout* layout);
-
- private:
-  // The combobox model for the list of timezones.
-  class TimezoneComboboxModel : public ComboboxModel {
-   public:
-    TimezoneComboboxModel() {
-      // TODO(chocobo): For now, add all the GMT timezones.
-      // We may eventually want to use icu::TimeZone::createEnumeration()
-      // to list all the timezones and pick the ones we want to show.
-      // NOTE: This currently does not handle daylight savings properly
-      // b/c this is just a manually selected list of timezones that
-      // happen to span the GMT-11 to GMT+12 Today. When daylight savings
-      // kick in, this list might have more than one timezone in the same
-      // GMT bucket.
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Pacific/Samoa")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("US/Hawaii")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("US/Alaska")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("US/Pacific")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("US/Mountain")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("US/Central")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("US/Eastern")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("America/Santiago")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("America/Sao_Paulo")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Atlantic/South_Georgia")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Atlantic/Cape_Verde")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Europe/London")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Europe/Rome")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Europe/Helsinki")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Europe/Moscow")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Dubai")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Karachi")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Dhaka")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Bangkok")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Hong_Kong")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Tokyo")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Australia/Sydney")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Asia/Magadan")));
-      timezones_.push_back(icu::TimeZone::createTimeZone(
-          icu::UnicodeString::fromUTF8("Pacific/Auckland")));
-    }
-
-    virtual ~TimezoneComboboxModel() {
-      STLDeleteElements(&timezones_);
-    }
-
-    virtual int GetItemCount() {
-      return static_cast<int>(timezones_.size());
-    }
-
-    virtual string16 GetItemAt(int index) {
-      icu::UnicodeString name;
-      timezones_[index]->getDisplayName(name);
-      std::wstring output;
-      UTF16ToWide(name.getBuffer(), name.length(), &output);
-      int hour_offset = timezones_[index]->getRawOffset() / 3600000;
-      return WideToUTF16Hack(
-          base::StringPrintf(hour_offset == 0 ? L"(GMT) " : (hour_offset > 0 ?
-          L"(GMT+%d) " : L"(GMT%d) "), hour_offset) + output);
-    }
-
-    virtual icu::TimeZone* GetTimeZoneAt(int index) {
-      return timezones_[index];
-    }
-
-   private:
-    std::vector<icu::TimeZone*> timezones_;
-
-    DISALLOW_COPY_AND_ASSIGN(TimezoneComboboxModel);
-  };
-
-  // TimeZone combobox model.
-  views::Combobox* timezone_combobox_;
-
-  // Controls for this section:
-  TimezoneComboboxModel timezone_combobox_model_;
-
-  DISALLOW_COPY_AND_ASSIGN(DateTimeSection);
-};
-
-DateTimeSection::DateTimeSection(Profile* profile)
-    : SettingsPageSection(profile, IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME),
-      timezone_combobox_(NULL) {
-  CrosLibrary::Get()->GetSystemLibrary()->AddObserver(this);
-}
-
-DateTimeSection::~DateTimeSection() {
-  CrosLibrary::Get()->GetSystemLibrary()->RemoveObserver(this);
-}
-
-void DateTimeSection::ItemChanged(views::Combobox* sender,
-                                  int prev_index,
-                                  int new_index) {
-  if (new_index == prev_index)
-    return;
-
-  CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(
-      timezone_combobox_model_.GetTimeZoneAt(new_index));
-}
-
-void DateTimeSection::TimezoneChanged(const icu::TimeZone& timezone) {
-  for (int i = 0; i < timezone_combobox_model_.GetItemCount(); i++) {
-    if (*timezone_combobox_model_.GetTimeZoneAt(i) == timezone) {
-      timezone_combobox_->SetSelectedItem(i);
-      return;
-    }
-  }
-}
-
-void DateTimeSection::InitContents(GridLayout* layout) {
-  timezone_combobox_ = new views::Combobox(&timezone_combobox_model_);
-  timezone_combobox_->set_listener(this);
-
-  layout->StartRow(0, double_column_view_set_id());
-  layout->AddView(new views::Label(UTF16ToWide(
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION))));
-  layout->AddView(timezone_combobox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-
-  TimezoneChanged(CrosLibrary::Get()->GetSystemLibrary()->GetTimezone());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TouchpadSection
-
-class TouchpadSection : public SettingsPageSection,
-                        public views::ButtonListener,
-                        public views::SliderListener {
- public:
-  explicit TouchpadSection(Profile* profile);
-  virtual ~TouchpadSection() {}
-
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // Overridden from views::SliderListener:
-  virtual void SliderValueChanged(views::Slider* sender);
-
- protected:
-  // SettingsPageSection overrides:
-  virtual void InitContents(GridLayout* layout);
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
- private:
-  // The View that contains the contents of the section.
-  views::View* contents_;
-
-  // Controls for this section:
-  views::Checkbox* enable_tap_to_click_checkbox_;
-  views::Slider* sensitivity_slider_;
-
-  // Preferences for this section:
-  BooleanPrefMember tap_to_click_enabled_;
-  IntegerPrefMember sensitivity_;
-
-  DISALLOW_COPY_AND_ASSIGN(TouchpadSection);
-};
-
-TouchpadSection::TouchpadSection(Profile* profile)
-    : SettingsPageSection(profile, IDS_OPTIONS_SETTINGS_SECTION_TITLE_TOUCHPAD),
-      enable_tap_to_click_checkbox_(NULL),
-      sensitivity_slider_(NULL) {
-}
-
-void TouchpadSection::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  if (sender == enable_tap_to_click_checkbox_) {
-    bool enabled = enable_tap_to_click_checkbox_->checked();
-    UserMetricsRecordAction(enabled ?
-        UserMetricsAction("Options_TapToClickCheckbox_Enable") :
-        UserMetricsAction("Options_TapToClickCheckbox_Disable"),
-        profile()->GetPrefs());
-    tap_to_click_enabled_.SetValue(enabled);
-  }
-}
-
-void TouchpadSection::SliderValueChanged(views::Slider* sender) {
-  if (sender == sensitivity_slider_) {
-    double value = sensitivity_slider_->value();
-    UserMetricsRecordAction(
-        UserMetricsAction("Options_SensitivitySlider_Changed"),
-        profile()->GetPrefs());
-    sensitivity_.SetValue(value);
-  }
-}
-
-void TouchpadSection::InitContents(GridLayout* layout) {
-  enable_tap_to_click_checkbox_ =
-      new views::Checkbox(UTF16ToWide(l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_TAP_TO_CLICK_ENABLED_DESCRIPTION)));
-  enable_tap_to_click_checkbox_->set_listener(this);
-  enable_tap_to_click_checkbox_->SetMultiLine(true);
-  // Create sensitivity slider with values between 1 and 5 step 1
-  sensitivity_slider_ = new views::Slider(1, 5, 1,
-      static_cast<views::Slider::StyleFlags>(
-          views::Slider::STYLE_DRAW_VALUE |
-          views::Slider::STYLE_UPDATE_ON_RELEASE),
-      this);
-
-  layout->StartRow(0, double_column_view_set_id());
-  layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_SENSITIVITY_DESCRIPTION))));
-  layout->AddView(sensitivity_slider_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-  layout->StartRow(0, single_column_view_set_id());
-  layout->AddView(enable_tap_to_click_checkbox_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
-
-  // Init member prefs so we can update the controls if prefs change.
-  tap_to_click_enabled_.Init(prefs::kTapToClickEnabled,
-                             profile()->GetPrefs(), this);
-  sensitivity_.Init(prefs::kTouchpadSensitivity,
-                    profile()->GetPrefs(), this);
-}
-
-void TouchpadSection::NotifyPrefChanged(const std::string* pref_name) {
-  if (!pref_name || *pref_name == prefs::kTapToClickEnabled) {
-    bool enabled =  tap_to_click_enabled_.GetValue();
-    enable_tap_to_click_checkbox_->SetChecked(enabled);
-  }
-  if (!pref_name || *pref_name == prefs::kTouchpadSensitivity) {
-    double value =  sensitivity_.GetValue();
-    sensitivity_slider_->SetValue(value);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// LanguageSection
-
-// TextInput section for text input settings.
-class LanguageSection : public SettingsPageSection,
-                        public views::ButtonListener,
-                        public views::Combobox::Listener {
- public:
-  explicit LanguageSection(Profile* profile);
-  virtual ~LanguageSection() {}
-
- private:
-  enum ButtonTag {
-    kCustomizeLanguagesButton,
-  };
-  // Overridden from SettingsPageSection:
-  virtual void InitContents(GridLayout* layout);
-  void NotifyPrefChanged(const std::string* pref_name);
-
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender,
-                             const views::Event& event);
-
-  // Overridden from views::Combobox::Listener:
-  virtual void ItemChanged(views::Combobox* sender,
-                           int prev_index,
-                           int new_index);
-
-  IntegerPrefMember xkb_remap_search_key_pref_;
-  IntegerPrefMember xkb_remap_control_key_pref_;
-  IntegerPrefMember xkb_remap_alt_key_pref_;
-  views::Combobox* xkb_modifier_combobox_;
-  chromeos::LanguageComboboxModel<int> xkb_modifier_combobox_model_;
-
-  DISALLOW_COPY_AND_ASSIGN(LanguageSection);
-};
-
-LanguageSection::LanguageSection(Profile* profile)
-    : SettingsPageSection(profile,
-                          IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE),
-      xkb_modifier_combobox_(NULL),
-      xkb_modifier_combobox_model_(
-          &language_prefs::kXkbModifierMultipleChoicePrefs) {
-  xkb_remap_search_key_pref_.Init(
-      prefs::kLanguageXkbRemapSearchKeyTo, profile->GetPrefs(), this);
-  xkb_remap_control_key_pref_.Init(
-      prefs::kLanguageXkbRemapControlKeyTo, profile->GetPrefs(), this);
-  xkb_remap_alt_key_pref_.Init(
-      prefs::kLanguageXkbRemapAltKeyTo, profile->GetPrefs(), this);
-}
-
-void LanguageSection::InitContents(GridLayout* layout) {
-  // Add the customize button and XKB combobox.
-  layout->StartRow(0, double_column_view_set_id());
-  views::NativeButton* customize_languages_button = new views::NativeButton(
-      this,
-      UTF16ToWide(l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE)));
-  customize_languages_button->set_tag(kCustomizeLanguagesButton);
-
-  xkb_modifier_combobox_ = new views::Combobox(&xkb_modifier_combobox_model_);
-  xkb_modifier_combobox_->set_listener(this);
-
-  // Initialize the combobox to what's saved in user preferences. Otherwise,
-  // ItemChanged() will be called with |new_index| == 0.
-  NotifyPrefChanged(NULL);
-
-  layout->AddView(customize_languages_button, 1, 1,
-                  GridLayout::LEADING, GridLayout::CENTER);
-  layout->AddView(xkb_modifier_combobox_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
-}
-
-void LanguageSection::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  if (sender->tag() == kCustomizeLanguagesButton) {
-    LanguageConfigView::Show(profile(), GetOptionsViewParent());
-  }
-}
-
-void LanguageSection::ItemChanged(views::Combobox* sender,
-                                  int prev_index,
-                                  int new_index) {
-  VLOG(1) << "Changing XKB modofier pref to " << new_index;
-  switch (new_index) {
-    default:
-      LOG(ERROR) << "Unexpected mapping: " << new_index;
-      /* fall through */
-    case language_prefs::kNoRemap:
-      xkb_remap_search_key_pref_.SetValue(kSearchKey);
-      xkb_remap_control_key_pref_.SetValue(kLeftControlKey);
-      xkb_remap_alt_key_pref_.SetValue(kLeftAltKey);
-      break;
-    case language_prefs::kSwapCtrlAndAlt:
-      xkb_remap_search_key_pref_.SetValue(kSearchKey);
-      xkb_remap_control_key_pref_.SetValue(kLeftAltKey);
-      xkb_remap_alt_key_pref_.SetValue(kLeftControlKey);
-      break;
-    case language_prefs::kSwapSearchAndCtrl:
-      xkb_remap_search_key_pref_.SetValue(kLeftControlKey);
-      xkb_remap_control_key_pref_.SetValue(kSearchKey);
-      xkb_remap_alt_key_pref_.SetValue(kLeftAltKey);
-      break;
-  }
-}
-
-void LanguageSection::NotifyPrefChanged(const std::string* pref_name) {
-  if (!pref_name || (*pref_name == prefs::kLanguageXkbRemapSearchKeyTo ||
-                     *pref_name == prefs::kLanguageXkbRemapControlKeyTo ||
-                     *pref_name == prefs::kLanguageXkbRemapAltKeyTo)) {
-    const int search_remap = xkb_remap_search_key_pref_.GetValue();
-    const int control_remap = xkb_remap_control_key_pref_.GetValue();
-    const int alt_remap = xkb_remap_alt_key_pref_.GetValue();
-    if ((search_remap == kSearchKey) &&
-        (control_remap == kLeftControlKey) &&
-        (alt_remap == kLeftAltKey)) {
-      xkb_modifier_combobox_->SetSelectedItem(language_prefs::kNoRemap);
-    } else if ((search_remap == kLeftControlKey) &&
-               (control_remap == kSearchKey) &&
-               (alt_remap == kLeftAltKey)) {
-      xkb_modifier_combobox_->SetSelectedItem(
-          language_prefs::kSwapSearchAndCtrl);
-    } else if ((search_remap == kSearchKey) &&
-               (control_remap == kLeftAltKey) &&
-               (alt_remap == kLeftControlKey)) {
-      xkb_modifier_combobox_->SetSelectedItem(language_prefs::kSwapCtrlAndAlt);
-    } else {
-      LOG(ERROR) << "Unexpected mapping. The prefs are updated by DOMUI?";
-      xkb_modifier_combobox_->SetSelectedItem(language_prefs::kNoRemap);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// AccessibilitySection
-
-// Checkbox for specifying if accessibility should be enabled for this profile
-class AccessibilitySection : public SettingsPageSection,
-                             public views::ButtonListener {
- public:
-  explicit AccessibilitySection(Profile* profile);
-  virtual ~AccessibilitySection() {}
-
- protected:
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender,
-                             const views::Event& event);
-
-  // Overridden from SettingsPageSection:
-  virtual void InitContents(GridLayout* layout);
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
- private:
-  // The View that contains the contents of the section.
-  views::View* contents_;
-
-  // Controls for this section:
-  views::Checkbox* accessibility_checkbox_;
-
-  // Preferences for this section:
-  BooleanPrefMember accessibility_enabled_;
-
-  DISALLOW_COPY_AND_ASSIGN(AccessibilitySection);
-};
-
-AccessibilitySection::AccessibilitySection(Profile* profile)
-    : SettingsPageSection(profile,
-                          IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY),
-      accessibility_checkbox_(NULL) {
-}
-
-void AccessibilitySection::InitContents(GridLayout* layout) {
-  accessibility_checkbox_ =
-      new views::Checkbox(UTF16ToWide(l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_ACCESSIBILITY_DESCRIPTION)));
-  accessibility_checkbox_->set_listener(this);
-  accessibility_checkbox_->SetMultiLine(true);
-
-  layout->StartRow(0, double_column_view_set_id());
-  layout->AddView(accessibility_checkbox_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
-
-  // Init member prefs so we can update the controls if prefs change.
-  accessibility_enabled_.Init(prefs::kAccessibilityEnabled,
-      profile()->GetPrefs(), this);
-}
-
-void AccessibilitySection::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  if (sender == accessibility_checkbox_) {
-    bool enabled = accessibility_checkbox_->checked();
-    // Set the accessibility enabled value in profile/prefs
-    accessibility_enabled_.SetValue(enabled);
-  }
-}
-
-void AccessibilitySection::NotifyPrefChanged(const std::string* pref_name) {
-  if (!pref_name || *pref_name == prefs::kAccessibilityEnabled) {
-    bool enabled = accessibility_enabled_.GetValue();
-    accessibility_checkbox_->SetChecked(enabled);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// SystemPageView
-
-////////////////////////////////////////////////////////////////////////////////
-// SystemPageView, SettingsPageView implementation:
-
-void SystemPageView::InitControlLayout() {
-  GridLayout* layout = CreatePanelGridLayout(this);
-  SetLayoutManager(layout);
-
-  int single_column_view_set_id = 0;
-  ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id);
-  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
-                        GridLayout::USE_PREF, 0, 0);
-
-  layout->StartRow(0, single_column_view_set_id);
-  layout->AddView(new DateTimeSection(profile()));
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-  layout->StartRow(0, single_column_view_set_id);
-  layout->AddView(new TouchpadSection(profile()));
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-  layout->StartRow(0, single_column_view_set_id);
-  layout->AddView(new LanguageSection(profile()));
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-  layout->StartRow(0, single_column_view_set_id);
-  layout->AddView(new AccessibilitySection(profile()));
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/system_page_view.h b/chrome/browser/chromeos/options/system_page_view.h
deleted file mode 100644
index 933ff98..0000000
--- a/chrome/browser/chromeos/options/system_page_view.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_SYSTEM_PAGE_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_OPTIONS_SYSTEM_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/chromeos/options/settings_page_view.h"
-
-namespace chromeos {
-
-// System settings page for Chrome OS
-class SystemPageView : public SettingsPageView {
- public:
-  explicit SystemPageView(Profile* profile) : SettingsPageView(profile) {}
-  virtual ~SystemPageView() {}
-
- protected:
-  // SettingsPageView implementation:
-  virtual void InitControlLayout();
-
-  DISALLOW_COPY_AND_ASSIGN(SystemPageView);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_OPTIONS_SYSTEM_PAGE_VIEW_H_
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 9b8fdd8..39ff35b 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/options/wifi_config_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
@@ -15,11 +13,13 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 namespace chromeos {
@@ -152,7 +152,7 @@
 bool WifiConfigView::HandleKeyEvent(views::Textfield* sender,
                                     const views::KeyEvent& key_event) {
   if (sender == passphrase_textfield_ &&
-      key_event.GetKeyCode() == app::VKEY_RETURN) {
+      key_event.key_code() == ui::VKEY_RETURN) {
     parent_->GetDialogClientView()->AcceptWindow();
   }
   return false;
@@ -194,8 +194,10 @@
 void WifiConfigView::FileSelected(const FilePath& path,
                                    int index, void* params) {
   certificate_path_ = path.value();
-  if (certificate_browse_button_)
-    certificate_browse_button_->SetLabel(path.BaseName().ToWStringHack());
+  if (certificate_browse_button_) {
+    certificate_browse_button_->SetLabel(
+        UTF16ToWide(path.BaseName().LossyDisplayName()));
+  }
   UpdateCanLogin();  // TODO(njw) Check if the passphrase decrypts the key.
 }
 
@@ -282,7 +284,7 @@
 }
 
 void WifiConfigView::Init() {
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   int column_view_set_id = 0;
@@ -310,7 +312,7 @@
     label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
     layout->AddView(label);
   }
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Certificate input
   // Loaded certificates (i.e. stored in a pkcs11 device) do not require
@@ -333,7 +335,7 @@
     if (!wifi_->identity().empty())
       identity_textfield_->SetText(UTF8ToUTF16(wifi_->identity()));
     layout->AddView(identity_textfield_);
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     layout->StartRow(0, column_view_set_id);
     layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT))));
@@ -357,7 +359,7 @@
       certificate_browse_button_ = new views::NativeButton(this, label);
       layout->AddView(certificate_browse_button_);
     }
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
 
   // Security select
@@ -368,7 +370,7 @@
     security_combobox_ = new views::Combobox(new SecurityComboboxModel());
     security_combobox_->set_listener(this);
     layout->AddView(security_combobox_);
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
 
   // Passphrase input
@@ -400,7 +402,7 @@
   passphrase_visible_button_->SetImageAlignment(
       views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE);
   layout->AddView(passphrase_visible_button_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Create an error label.
   layout->StartRow(0, column_view_set_id);
@@ -409,7 +411,7 @@
   error_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   error_label_->SetColor(SK_ColorRED);
   layout->AddView(error_label_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   // Set or hide the error text.
   UpdateErrorLabel(false);
 }
diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h
index 6dbe70e..e690cdb 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.h
+++ b/chrome/browser/chromeos/options/wifi_config_view.h
@@ -8,11 +8,11 @@
 
 #include <string>
 
-#include "app/combobox_model.h"
 #include "base/gtest_prod_util.h"
 #include "base/string16.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/button/button.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/button/image_button.h"
@@ -72,7 +72,7 @@
   bool can_login() const { return can_login_; }
 
  private:
-  class SecurityComboboxModel : public ComboboxModel {
+   class SecurityComboboxModel : public ui::ComboboxModel {
    public:
     SecurityComboboxModel() {}
     virtual ~SecurityComboboxModel() {}
diff --git a/chrome/browser/chromeos/panels/panel_scroller.cc b/chrome/browser/chromeos/panels/panel_scroller.cc
index b2c5b3c..93ba163 100644
--- a/chrome/browser/chromeos/panels/panel_scroller.cc
+++ b/chrome/browser/chromeos/panels/panel_scroller.cc
@@ -11,7 +11,7 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/panels/panel_scroller_container.h"
 #include "chrome/browser/chromeos/panels/panel_scroller_header.h"
-#include "gfx/canvas.h"
+#include "ui/gfx/canvas.h"
 #include "views/widget/widget_gtk.h"
 
 struct PanelScroller::Panel {
@@ -124,8 +124,8 @@
     if (cur_content_pos < scroll_pos_ + top_header_pixel_count) {
       // This panel is at least partially off the top. Put the header below the
       // others already there.
-      panels_[i]->header->SetBounds(gfx::Rect(0, top_header_pixel_count,
-                                              width(), divider_height_));
+      panels_[i]->header->SetBoundsRect(gfx::Rect(0, top_header_pixel_count,
+                                                  width(), divider_height_));
       top_header_pixel_count += divider_height_;
 
     } else if (cur_content_pos > height() + scroll_pos_ -
@@ -134,12 +134,13 @@
       // headers will stack up at the bottom. Counting this header, there are
       // (size() - i) left, which is used in the expression above.
       int top = height() - (panel_count - i) * divider_height_;
-      panels_[i]->header->SetBounds(gfx::Rect(0, top,
-                                              width(), divider_height_));
+      panels_[i]->header->SetBoundsRect(gfx::Rect(0, top,
+                                                  width(), divider_height_));
     } else {
       // Normal header positioning in-flow.
-      panels_[i]->header->SetBounds(gfx::Rect(0, cur_content_pos - scroll_pos_,
-                                              width(), divider_height_));
+      panels_[i]->header->SetBoundsRect(
+          gfx::Rect(0, cur_content_pos - scroll_pos_, width(),
+                    divider_height_));
     }
 
     cur_content_pos += divider_height_;
@@ -147,7 +148,7 @@
     // Now position the content. It always goes in-flow ignoring any stacked
     // up headers at the top or bottom.
     int container_height = panels_[i]->container->GetPreferredSize().height();
-    panels_[i]->container->SetBounds(
+    panels_[i]->container->SetBoundsRect(
         gfx::Rect(0, cur_content_pos - scroll_pos_,
                   width(), container_height));
     cur_content_pos += container_height;
diff --git a/chrome/browser/chromeos/panels/panel_scroller_container.cc b/chrome/browser/chromeos/panels/panel_scroller_container.cc
index e070852..e3b3caf 100644
--- a/chrome/browser/chromeos/panels/panel_scroller_container.cc
+++ b/chrome/browser/chromeos/panels/panel_scroller_container.cc
@@ -4,14 +4,14 @@
 
 #include "chrome/browser/chromeos/panels/panel_scroller_container.h"
 
-#include "gfx/canvas.h"
+#include "ui/gfx/canvas.h"
 
 PanelScrollerContainer::PanelScrollerContainer(PanelScroller* scroller,
                                                views::View* contents)
     : views::View(),
       scroller_(scroller),
       contents_(contents) {
-  AddChildView(0, contents_);
+  AddChildViewAt(contents_, 0);
   // TODO(brettw) figure out memory management.
 }
 
diff --git a/chrome/browser/chromeos/panels/panel_scroller_header.cc b/chrome/browser/chromeos/panels/panel_scroller_header.cc
index f6dceea..0a8cac0 100644
--- a/chrome/browser/chromeos/panels/panel_scroller_header.cc
+++ b/chrome/browser/chromeos/panels/panel_scroller_header.cc
@@ -1,14 +1,14 @@
-// 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.
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/panels/panel_scroller_header.h"
 
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/panels/panel_scroller.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
 
 PanelScrollerHeader::PanelScrollerHeader(PanelScroller* scroller)
     : views::View(),
@@ -45,6 +45,6 @@
   gfx::Font font =
       rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD);
   int font_top = 1;
-  canvas->DrawStringInt(UTF16ToWideHack(title_), font, 0xFF000000, 3, font_top,
+  canvas->DrawStringInt(title_, font, 0xFF000000, 3, font_top,
                         size().width(), size().height() - font_top);
 }
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 0f57dae..8d86cf7 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -50,9 +50,9 @@
                             language_prefs::kHotkeyPreviousEngine);
   prefs->RegisterStringPref(prefs::kLanguagePreferredLanguages,
                             kFallbackInputMethodLocale);
-  KeyboardLibrary* keyboard_library = CrosLibrary::Get()->GetKeyboardLibrary();
-  prefs->RegisterStringPref(prefs::kLanguagePreloadEngines,
-                            keyboard_library->GetHardwareKeyboardLayoutName());
+  prefs->RegisterStringPref(
+      prefs::kLanguagePreloadEngines,
+      input_method::GetHardwareInputMethodId());
   for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
     prefs->RegisterBooleanPref(
         language_prefs::kChewingBooleanPrefs[i].pref_name,
@@ -234,6 +234,26 @@
     // Unlike kLanguagePreloadEngines and some other input method
     // preferencs, we don't need to send this to ibus-daemon.
   }
+
+  // Here, we set up the the modifier key mapping. This has to be done
+  // before changing the current keyboard layout, so that the modifier key
+  // preference is properly preserved. For this reason, we should do this
+  // before setting preload engines, that could change the current
+  // keyboard layout as needed.
+  if (!pref_name || (*pref_name == prefs::kLanguageXkbRemapSearchKeyTo ||
+                     *pref_name == prefs::kLanguageXkbRemapControlKeyTo ||
+                     *pref_name == prefs::kLanguageXkbRemapAltKeyTo)) {
+    UpdateModifierKeyMapping();
+  }
+  if (!pref_name || *pref_name == prefs::kLanguageXkbAutoRepeatEnabled) {
+    const bool enabled = language_xkb_auto_repeat_enabled_.GetValue();
+    CrosLibrary::Get()->GetKeyboardLibrary()->SetAutoRepeatEnabled(enabled);
+  }
+  if (!pref_name || ((*pref_name == prefs::kLanguageXkbAutoRepeatDelay) ||
+                     (*pref_name == prefs::kLanguageXkbAutoRepeatInterval))) {
+    UpdateAutoRepeatRate();
+  }
+
   if (!pref_name || *pref_name == prefs::kLanguagePreloadEngines) {
     SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName,
                                      language_prefs::kPreloadEnginesConfigName,
@@ -337,19 +357,6 @@
           language_mozc_integer_prefs_[i].GetValue());
     }
   }
-  if (!pref_name || (*pref_name == prefs::kLanguageXkbRemapSearchKeyTo ||
-                     *pref_name == prefs::kLanguageXkbRemapControlKeyTo ||
-                     *pref_name == prefs::kLanguageXkbRemapAltKeyTo)) {
-    UpdateModifierKeyMapping();
-  }
-  if (!pref_name || *pref_name == prefs::kLanguageXkbAutoRepeatEnabled) {
-    const bool enabled = language_xkb_auto_repeat_enabled_.GetValue();
-    CrosLibrary::Get()->GetKeyboardLibrary()->SetAutoRepeatEnabled(enabled);
-  }
-  if (!pref_name || ((*pref_name == prefs::kLanguageXkbAutoRepeatDelay) ||
-                     (*pref_name == prefs::kLanguageXkbAutoRepeatInterval))) {
-    UpdateAutoRepeatRate();
-  }
 
   // Init or update power manager config.
   if (!pref_name || *pref_name == prefs::kEnableScreenLock) {
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.cc b/chrome/browser/chromeos/proxy_config_service_impl.cc
index 862459c..1aceb24 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl.cc
@@ -217,6 +217,48 @@
   }
 }
 
+bool ProxyConfigServiceImpl::ProxyConfig::CanBeWrittenByUser(
+    bool user_is_owner, const std::string& scheme) {
+  // Setting can only be written by user if user is owner and setting is not
+  // from policy.
+  Setting* setting = NULL;
+  switch (mode) {
+    case MODE_DIRECT:
+    case MODE_AUTO_DETECT:
+    case MODE_PAC_SCRIPT:
+      setting = &automatic_proxy;
+      break;
+    case MODE_SINGLE_PROXY:
+      setting = &single_proxy;
+      break;
+    case MODE_PROXY_PER_SCHEME:
+      setting = MapSchemeToProxy(scheme);
+      break;
+    default:
+      break;
+  }
+  if (!setting) {
+    NOTREACHED() << "Unrecognized proxy config mode";
+    return false;
+  }
+  return setting->CanBeWrittenByUser(user_is_owner);
+}
+
+ProxyConfigServiceImpl::ProxyConfig::ManualProxy*
+    ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy(
+        const std::string& scheme) {
+  if (scheme == "http")
+    return &http_proxy;
+  if (scheme == "https")
+    return &https_proxy;
+  if (scheme == "ftp")
+    return &ftp_proxy;
+  if (scheme == "socks")
+    return &socks_proxy;
+  NOTREACHED() << "Invalid scheme: " << scheme;
+  return NULL;
+}
+
 bool ProxyConfigServiceImpl::ProxyConfig::Serialize(std::string* output) {
   scoped_ptr<DictionaryValue> dict(new DictionaryValue);
   dict->SetInteger(kMode, mode);
@@ -428,15 +470,7 @@
     const std::string& scheme, const net::ProxyServer& server) {
   // Should be called from UI thread.
   CheckCurrentlyOnUIThread();
-  ProxyConfig::ManualProxy* proxy = NULL;
-  if (scheme == "http")
-    proxy = &reference_config_.http_proxy;
-  else if (scheme == "https")
-    proxy = &reference_config_.https_proxy;
-  else if (scheme == "ftp")
-    proxy = &reference_config_.ftp_proxy;
-  else if (scheme == "socks")
-    proxy = &reference_config_.socks_proxy;
+  ProxyConfig::ManualProxy* proxy = reference_config_.MapSchemeToProxy(scheme);
   if (!proxy) {
     NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]";
     return false;
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.h b/chrome/browser/chromeos/proxy_config_service_impl.h
index 2e605a8..48643ee 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.h
+++ b/chrome/browser/chromeos/proxy_config_service_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -50,7 +50,7 @@
   // (GetLatestProxyConfig, AddObserver, RemoveObserver).
   //
   // From the UI thread, it is accessed via
-  // DOMUI::GetProfile::GetChromeOSProxyConfigServiceImpl to allow user to read
+  // WebUI::GetProfile::GetChromeOSProxyConfigServiceImpl to allow user to read
   // or modify the proxy configuration via UIGetProxyConfig or
   // UISetProxyConfigTo* respectively.
   // The new modified proxy config is posted to the IO thread through
@@ -116,6 +116,15 @@
     // Converts |this| to net::ProxyConfig.
     void ToNetProxyConfig(net::ProxyConfig* net_config);
 
+    // Returns true if proxy config can be written by user.
+    // If mode is MODE_PROXY_PER_SCHEME, |scheme| is one of "http", "https",
+    // "ftp" or "socks"; otherwise, it should be empty or will be ignored.
+    bool CanBeWrittenByUser(bool user_is_owner, const std::string& scheme);
+
+    // Map |scheme| (one of "http", "https", "ftp" or "socks") to the correct
+    // ManualProxy.  Returns NULL if scheme is invalid.
+    ManualProxy* MapSchemeToProxy(const std::string& scheme);
+
     // Serializes config into a DictionaryValue and then into std::string
     // persisted as property on device.
     bool Serialize(std::string* output);
@@ -184,6 +193,7 @@
   bool UISetProxyConfigToAutoDetect();
   bool UISetProxyConfigToPACScript(const GURL& pac_url);
   bool UISetProxyConfigToSingleProxy(const net::ProxyServer& server);
+  // |scheme| is one of "http", "https", "ftp" or "socks".
   bool UISetProxyConfigToProxyPerScheme(const std::string& scheme,
                                         const net::ProxyServer& server);
   // Only valid for MODE_SINGLE_PROXY or MODE_PROXY_PER_SCHEME.
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index 15a8327..92ba816 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -51,6 +51,7 @@
   std::string description;
 
   bool is_valid;
+  bool test_read_write_access;
 
   Input input;
 
@@ -61,7 +62,9 @@
 } tests[] = {
   {
     TEST_DESC("No proxying"),
+
     true,  // is_valid
+    true,  // test_read_write_access
 
     { // Input.
       MK_MODE(DIRECT),  // mode
@@ -75,7 +78,9 @@
 
   {
     TEST_DESC("Auto detect"),
+
     true,  // is_valid
+    true,  // test_read_write_access
 
     { // Input.
       MK_MODE(AUTO_DETECT),  // mode
@@ -89,7 +94,9 @@
 
   {
     TEST_DESC("Valid PAC URL"),
+
     true,  // is_valid
+    true,  // test_read_write_access
 
     { // Input.
       MK_MODE(PAC_SCRIPT),     // mode
@@ -104,7 +111,9 @@
 
   {
     TEST_DESC("Invalid PAC URL"),
+
     false,  // is_valid
+    false,  // test_read_write_access
 
     { // Input.
       MK_MODE(PAC_SCRIPT),  // mode
@@ -119,7 +128,9 @@
 
   {
     TEST_DESC("Single-host in proxy list"),
+
     true,  // is_valid
+    true,  // test_read_write_access
 
     { // Input.
       MK_MODE(SINGLE_PROXY),  // mode
@@ -137,7 +148,9 @@
 
   {
     TEST_DESC("Single-host, different port"),
-    true,  // is_valid
+
+    true,   // is_valid
+    false,  // test_read_write_access
 
     { // Input.
       MK_MODE(SINGLE_PROXY),  // mode
@@ -155,7 +168,9 @@
 
   {
     TEST_DESC("Tolerate a scheme"),
-    true,  // is_valid
+
+    true,   // is_valid
+    false,  // test_read_write_access
 
     { // Input.
       MK_MODE(SINGLE_PROXY),       // mode
@@ -173,7 +188,9 @@
 
   {
     TEST_DESC("Per-scheme proxy rules"),
+
     true,  // is_valid
+    true,  // test_read_write_access
 
     { // Input.
       MK_MODE(PROXY_PER_SCHEME),  // mode
@@ -198,7 +215,9 @@
 
   {
     TEST_DESC("Bypass rules"),
+
     true,  // is_valid
+    true,  // test_read_write_access
 
     { // Input.
       MK_MODE(SINGLE_PROXY),      // mode
@@ -264,9 +283,8 @@
   }
 
   void InitConfigWithTestInput(
-      const Input& input,
+      const Input& input, ProxyConfigServiceImpl::ProxyConfig::Source source,
       ProxyConfigServiceImpl::ProxyConfig* init_config) {
-    ProxyConfigServiceImpl::ProxyConfig::Source source = MK_SRC(OWNER);
     switch (input.mode) {
       case MK_MODE(DIRECT):
       case MK_MODE(AUTO_DETECT):
@@ -295,6 +313,90 @@
     }
   }
 
+  void TestReadWriteAccessForMode(const Input& input,
+      ProxyConfigServiceImpl::ProxyConfig::Source source) {
+    // Init config from |source|.
+    ProxyConfigServiceImpl::ProxyConfig init_config;
+    InitConfigWithTestInput(input, source, &init_config);
+    CreateConfigService(init_config);
+
+    ProxyConfigServiceImpl::ProxyConfig config;
+    config_service()->UIGetProxyConfig(&config);
+
+    // For owner, write access to config should be equal CanBeWrittenByOwner().
+    // For non-owner, config is never writeable.
+    bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
+    if (config.mode == MK_MODE(PROXY_PER_SCHEME)) {
+      if (input.http_uri) {
+        EXPECT_EQ(expected_writeable_by_owner,
+                  config.CanBeWrittenByUser(true, "http"));
+        EXPECT_FALSE(config.CanBeWrittenByUser(false, "http"));
+      }
+      if (input.https_uri) {
+        EXPECT_EQ(expected_writeable_by_owner,
+                  config.CanBeWrittenByUser(true, "http"));
+        EXPECT_FALSE(config.CanBeWrittenByUser(false, "https"));
+      }
+      if (input.ftp_uri) {
+        EXPECT_EQ(expected_writeable_by_owner,
+                  config.CanBeWrittenByUser(true, "http"));
+        EXPECT_FALSE(config.CanBeWrittenByUser(false, "ftp"));
+      }
+      if (input.socks_uri) {
+        EXPECT_EQ(expected_writeable_by_owner,
+                  config.CanBeWrittenByUser(true, "http"));
+        EXPECT_FALSE(config.CanBeWrittenByUser(false, "socks"));
+      }
+    } else {
+      EXPECT_EQ(expected_writeable_by_owner,
+                config.CanBeWrittenByUser(true, std::string()));
+      EXPECT_FALSE(config.CanBeWrittenByUser(false, std::string()));
+    }
+  }
+
+  void TestReadWriteAccessForScheme(
+      ProxyConfigServiceImpl::ProxyConfig::Source source,
+      const char* server_uri,
+      const std::string& scheme) {
+    // Init with manual |scheme| proxy.
+    ProxyConfigServiceImpl::ProxyConfig init_config;
+    ProxyConfigServiceImpl::ProxyConfig::ManualProxy* proxy =
+        init_config.MapSchemeToProxy(scheme);
+    net::ProxyServer::Scheme net_scheme = MK_SCHM(HTTP);
+    if (scheme == "http" || scheme == "ftp")
+      net_scheme = MK_SCHM(HTTP);
+    else if (scheme == "https")
+      net_scheme = MK_SCHM(HTTPS);
+    else if (scheme == "socks")
+      net_scheme = MK_SCHM(SOCKS4);
+    SetManualProxy(MK_MODE(PROXY_PER_SCHEME), source, server_uri, net_scheme,
+                   &init_config, proxy);
+    CreateConfigService(init_config);
+
+    ProxyConfigServiceImpl::ProxyConfig config;
+    config_service()->UIGetProxyConfig(&config);
+
+    // For owner, write access to config should be equal CanBeWrittenByOwner().
+    // For non-owner, config is never writeable.
+    bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
+    EXPECT_EQ(expected_writeable_by_owner,
+              config.CanBeWrittenByUser(true, scheme));
+    EXPECT_FALSE(config.CanBeWrittenByUser(false, scheme));
+
+    const char* all_schemes[] = {
+      "http", "https", "ftp", "socks",
+    };
+
+    // Rest of protos should be writeable by owner, but not writeable by
+    // non-owner.
+    for (size_t i = 0; i < ARRAYSIZE_UNSAFE(all_schemes); ++i) {
+      if (scheme == all_schemes[i])
+        continue;
+      EXPECT_TRUE(config.CanBeWrittenByUser(true, all_schemes[i]));
+      EXPECT_FALSE(config.CanBeWrittenByUser(false, all_schemes[i]));
+    }
+  }
+
   // Synchronously gets the latest proxy config.
   bool SyncGetLatestProxyConfig(net::ProxyConfig* config) {
     // Let message loop process all messages.
@@ -309,6 +411,11 @@
   }
 
  private:
+  bool CanBeWrittenByOwner(
+    ProxyConfigServiceImpl::ProxyConfig::Source source) const {
+    return source == MK_SRC(POLICY) ? false : true;
+  }
+
   ScopedStubCrosEnabler stub_cros_enabler_;
   MessageLoop message_loop_;
   BrowserThread ui_thread_;
@@ -319,11 +426,11 @@
 
 TEST_F(ProxyConfigServiceImplTest, ChromeosProxyConfigToNetProxyConfig) {
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
-    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
-                                    tests[i].description.c_str()));
+    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+                              tests[i].description.c_str()));
 
     ProxyConfigServiceImpl::ProxyConfig init_config;
-    InitConfigWithTestInput(tests[i].input, &init_config);
+    InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &init_config);
     CreateConfigService(init_config);
 
     net::ProxyConfig config;
@@ -335,46 +442,10 @@
   }
 }
 
-TEST_F(ProxyConfigServiceImplTest, ReadWriteAccess) {
-  static const char* pac_url = "http://wpad.dat";
-
-  { // Init with pac script from policy.
-    ProxyConfigServiceImpl::ProxyConfig init_config;
-    SetAutomaticProxy(MK_MODE(PAC_SCRIPT), MK_SRC(POLICY), pac_url,
-                      &init_config, &init_config.automatic_proxy);
-    CreateConfigService(init_config);
-
-    ProxyConfigServiceImpl::ProxyConfig config;
-    config_service()->UIGetProxyConfig(&config);
-
-    EXPECT_EQ(MK_SRC(POLICY), config.automatic_proxy.source);
-    // Setting should be not be writeable by owner.
-    EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(true));
-    // Setting should be not be writeable by non-owner.
-    EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(false));
-  }
-
-  { // Init with pac script from owner.
-    ProxyConfigServiceImpl::ProxyConfig init_config;
-    SetAutomaticProxy(MK_MODE(PAC_SCRIPT), MK_SRC(OWNER), pac_url,
-                      &init_config, &init_config.automatic_proxy);
-    CreateConfigService(init_config);
-
-    ProxyConfigServiceImpl::ProxyConfig config;
-    config_service()->UIGetProxyConfig(&config);
-
-    EXPECT_EQ(MK_SRC(OWNER), config.automatic_proxy.source);
-    // Setting should be writeable by owner.
-    EXPECT_TRUE(config.automatic_proxy.CanBeWrittenByUser(true));
-    // Setting should not be writeable by non-owner.
-    EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(false));
-  }
-}
-
 TEST_F(ProxyConfigServiceImplTest, ModifyFromUI) {
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
-    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
-                                    tests[i].description.c_str()));
+    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+                              tests[i].description.c_str()));
 
     // Init with direct.
     ProxyConfigServiceImpl::ProxyConfig init_config;
@@ -512,11 +583,12 @@
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
     if (!tests[i].is_valid)
       continue;
+
     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
                               tests[i].description.c_str()));
 
     ProxyConfigServiceImpl::ProxyConfig source_config;
-    InitConfigWithTestInput(tests[i].input, &source_config);
+    InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &source_config);
 
     // Serialize source_config into std::string.
     std::string serialized_value;
@@ -546,4 +618,43 @@
   }
 }
 
+TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForPolicySource) {
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+    if (!tests[i].test_read_write_access)
+      continue;
+    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+                              tests[i].description.c_str()));
+    TestReadWriteAccessForMode(tests[i].input, MK_SRC(POLICY));
+  }
+}
+
+TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForOwnerSource) {
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+    if (!tests[i].test_read_write_access)
+      continue;
+    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+                              tests[i].description.c_str()));
+    TestReadWriteAccessForMode(tests[i].input, MK_SRC(OWNER));
+  }
+}
+
+TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForMixedSchemes) {
+  const char* http_uri = "www.google.com:80";
+  const char* https_uri = "www.foo.com:110";
+  const char* ftp_uri = "ftp.foo.com:121";
+  const char* socks_uri = "socks.com:888";
+
+  // Init with policy source.
+  TestReadWriteAccessForScheme(MK_SRC(POLICY), http_uri, "http");
+  TestReadWriteAccessForScheme(MK_SRC(POLICY), https_uri, "https");
+  TestReadWriteAccessForScheme(MK_SRC(POLICY), ftp_uri, "ftp");
+  TestReadWriteAccessForScheme(MK_SRC(POLICY), socks_uri, "socks");
+
+  // Init with owner source.
+  TestReadWriteAccessForScheme(MK_SRC(OWNER), http_uri, "http");
+  TestReadWriteAccessForScheme(MK_SRC(OWNER), https_uri, "https");
+  TestReadWriteAccessForScheme(MK_SRC(OWNER), ftp_uri, "ftp");
+  TestReadWriteAccessForScheme(MK_SRC(OWNER), socks_uri, "socks");
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/pulse_audio_mixer.cc b/chrome/browser/chromeos/pulse_audio_mixer.cc
deleted file mode 100644
index a58548e..0000000
--- a/chrome/browser/chromeos/pulse_audio_mixer.cc
+++ /dev/null
@@ -1,461 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/pulse_audio_mixer.h"
-
-#include <pulse/pulseaudio.h>
-
-#include "base/logging.h"
-#include "base/task.h"
-
-namespace chromeos {
-
-// Using asynchronous versions of the threaded PulseAudio API, as well
-// as a worker thread so gets, sets, and the init sequence do not block the
-// calling thread.  GetVolume() and IsMute() can still be called synchronously
-// if needed, but take a bit longer (~2ms vs ~0.3ms).
-//
-// Set calls just return without waiting.  If you must guarantee the value has
-// been set before continuing, immediately call the blocking Get version to
-// synchronously get the value back.
-//
-// TODO(davej): Serialize volume/mute to preserve settings when restarting?
-
-namespace {
-
-const int kInvalidDeviceId = -1;
-
-// Used for passing custom data to the PulseAudio callbacks.
-struct CallbackWrapper {
-  PulseAudioMixer* instance;
-  bool done;
-  void* userdata;
-};
-
-}  // namespace
-
-// AudioInfo contains all the values we care about when getting info for a
-// Sink (output device) used by GetAudioInfo().
-struct PulseAudioMixer::AudioInfo {
-  pa_cvolume cvolume;
-  bool muted;
-};
-
-PulseAudioMixer::PulseAudioMixer()
-    : device_id_(kInvalidDeviceId),
-      last_channels_(0),
-      mainloop_lock_count_(0),
-      mixer_state_lock_(),
-      mixer_state_(UNINITIALIZED),
-      pa_context_(NULL),
-      pa_mainloop_(NULL),
-      thread_(NULL) {
-}
-
-PulseAudioMixer::~PulseAudioMixer() {
-  PulseAudioFree();
-  thread_->Stop();
-  thread_.reset();
-}
-
-bool PulseAudioMixer::Init(InitDoneCallback* callback) {
-  if (!InitThread())
-    return false;
-
-  // Post the task of starting up, which can block for 200-500ms,
-  // so best not to do it on the caller's thread.
-  thread_->message_loop()->PostTask(FROM_HERE,
-    NewRunnableMethod(this, &PulseAudioMixer::DoInit, callback));
-  return true;
-}
-
-bool PulseAudioMixer::InitSync() {
-  if (!InitThread())
-    return false;
-  return PulseAudioInit();
-}
-
-double PulseAudioMixer::GetVolumeDb() const {
-  if (!MainloopLockIfReady())
-    return pa_sw_volume_to_dB(0);  // this returns -inf.
-  AudioInfo data;
-  GetAudioInfo(&data);
-  MainloopUnlock();
-  return pa_sw_volume_to_dB(data.cvolume.values[0]);
-}
-
-bool PulseAudioMixer::GetVolumeDbAsync(GetVolumeCallback* callback,
-                                       void* user) {
-  if (CheckState() != READY)
-    return false;
-  thread_->message_loop()->PostTask(FROM_HERE,
-      NewRunnableMethod(this,
-                        &PulseAudioMixer::DoGetVolume,
-                        callback, user));
-  return true;
-}
-
-void PulseAudioMixer::SetVolumeDb(double vol_db) {
-  if (!MainloopLockIfReady())
-    return;
-
-  // last_channels_ determines the number of channels on the main output device,
-  // and is used later to set the volume on all channels at once.
-  if (!last_channels_) {
-    AudioInfo data;
-    GetAudioInfo(&data);
-    last_channels_ = data.cvolume.channels;
-  }
-
-  pa_operation* pa_op;
-  pa_cvolume cvolume;
-  pa_cvolume_set(&cvolume, last_channels_, pa_sw_volume_from_dB(vol_db));
-  pa_op = pa_context_set_sink_volume_by_index(pa_context_, device_id_,
-                                              &cvolume, NULL, NULL);
-  pa_operation_unref(pa_op);
-  MainloopUnlock();
-}
-
-bool PulseAudioMixer::IsMute() const {
-  if (!MainloopLockIfReady())
-    return false;
-  AudioInfo data;
-  GetAudioInfo(&data);
-  MainloopUnlock();
-  return data.muted;
-}
-
-void PulseAudioMixer::SetMute(bool mute) {
-  if (!MainloopLockIfReady())
-    return;
-  pa_operation* pa_op;
-  pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_,
-                                            mute ? 1 : 0, NULL, NULL);
-  pa_operation_unref(pa_op);
-  MainloopUnlock();
-}
-
-PulseAudioMixer::State PulseAudioMixer::CheckState() const {
-  AutoLock lock(mixer_state_lock_);
-  // If we think it's ready, verify it is actually so.
-  if ((mixer_state_ == READY) &&
-      (pa_context_get_state(pa_context_) != PA_CONTEXT_READY))
-    mixer_state_ = IN_ERROR;
-  return mixer_state_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Private functions follow
-
-void PulseAudioMixer::DoInit(InitDoneCallback* callback) {
-  bool success = PulseAudioInit();
-  callback->Run(success);
-  delete callback;
-}
-
-void PulseAudioMixer::DoGetVolume(GetVolumeCallback* callback,
-                                  void* user) {
-  callback->Run(GetVolumeDb(), user);
-  delete callback;
-}
-
-bool PulseAudioMixer::InitThread() {
-  AutoLock lock(mixer_state_lock_);
-
-  if (mixer_state_ != UNINITIALIZED)
-    return false;
-  if (thread_ == NULL) {
-    thread_.reset(new base::Thread("PulseAudioMixer"));
-    if (!thread_->Start()) {
-      thread_.reset();
-      return false;
-    }
-  }
-  mixer_state_ = INITIALIZING;
-  return true;
-}
-
-// static
-void PulseAudioMixer::ConnectToPulseCallbackThunk(
-    pa_context* context, void* userdata) {
-  CallbackWrapper* data =
-      static_cast<CallbackWrapper*>(userdata);
-  data->instance->OnConnectToPulseCallback(context, &data->done);
-}
-
-void PulseAudioMixer::OnConnectToPulseCallback(
-    pa_context* context, bool* connect_done) {
-  pa_context_state_t state = pa_context_get_state(context);
-  if (state == PA_CONTEXT_READY ||
-      state == PA_CONTEXT_FAILED ||
-      state == PA_CONTEXT_TERMINATED) {
-    // Connection process has reached a terminal state. Wake PulseAudioInit().
-    *connect_done = true;
-    MainloopSignal();
-  }
-}
-
-bool PulseAudioMixer::PulseAudioInit() {
-  pa_context_state_t state = PA_CONTEXT_FAILED;
-
-  {
-    AutoLock lock(mixer_state_lock_);
-    if (mixer_state_ != INITIALIZING)
-      return false;
-
-    pa_mainloop_ = pa_threaded_mainloop_new();
-    if (!pa_mainloop_) {
-      LOG(ERROR) << "Can't create PulseAudio mainloop";
-      mixer_state_ = UNINITIALIZED;
-      return false;
-    }
-
-    if (pa_threaded_mainloop_start(pa_mainloop_) != 0) {
-      LOG(ERROR) << "Can't start PulseAudio mainloop";
-      pa_threaded_mainloop_free(pa_mainloop_);
-      mixer_state_ = UNINITIALIZED;
-      return false;
-    }
-  }
-
-  while (true) {
-    // Create connection to default server.
-    if (!MainloopSafeLock())
-      return false;
-
-    while (true) {
-      pa_mainloop_api* pa_mlapi = pa_threaded_mainloop_get_api(pa_mainloop_);
-      if (!pa_mlapi) {
-        LOG(ERROR) << "Can't get PulseAudio mainloop api";
-        break;
-      }
-      // This one takes the most time if run at app startup.
-      pa_context_ = pa_context_new(pa_mlapi, "ChromeAudio");
-      if (!pa_context_) {
-        LOG(ERROR) << "Can't create new PulseAudio context";
-        break;
-      }
-
-      MainloopUnlock();
-      if (!MainloopSafeLock())
-        return false;
-
-      CallbackWrapper data = {this, false, NULL};
-      pa_context_set_state_callback(pa_context_,
-                                    &ConnectToPulseCallbackThunk,
-                                    &data);
-
-      if (pa_context_connect(pa_context_, NULL,
-                             PA_CONTEXT_NOAUTOSPAWN, NULL) != 0) {
-        LOG(ERROR) << "Can't start connection to PulseAudio sound server";
-      } else {
-        // Wait until we have a completed connection or fail.
-        do {
-          MainloopWait();
-        } while (!data.done);
-
-        state = pa_context_get_state(pa_context_);
-
-        if (state == PA_CONTEXT_FAILED) {
-          LOG(ERROR) << "PulseAudio connection failed (daemon not running?)";
-        } else if (state == PA_CONTEXT_TERMINATED) {
-          LOG(ERROR) << "PulseAudio connection terminated early";
-        } else if (state != PA_CONTEXT_READY) {
-          LOG(ERROR) << "Unknown problem connecting to PulseAudio";
-        }
-      }
-
-      pa_context_set_state_callback(pa_context_, NULL, NULL);
-      break;
-    }
-
-    MainloopUnlock();
-
-    if (state != PA_CONTEXT_READY)
-      break;
-
-    if (!MainloopSafeLock())
-      return false;
-    GetDefaultPlaybackDevice();
-    MainloopUnlock();
-
-    if (device_id_ == kInvalidDeviceId)
-      break;
-
-    {
-      AutoLock lock(mixer_state_lock_);
-      if (mixer_state_ == SHUTTING_DOWN)
-        return false;
-      mixer_state_ = READY;
-    }
-
-    return true;
-  }
-
-  // Failed startup sequence, clean up now.
-  PulseAudioFree();
-  return false;
-}
-
-void PulseAudioMixer::PulseAudioFree() {
-  {
-    AutoLock lock(mixer_state_lock_);
-    if (!pa_mainloop_)
-      mixer_state_ = UNINITIALIZED;
-    if ((mixer_state_ == UNINITIALIZED) || (mixer_state_ == SHUTTING_DOWN))
-      return;
-    // If still initializing on another thread, this will cause it to exit.
-    mixer_state_ = SHUTTING_DOWN;
-  }
-
-  DCHECK(pa_mainloop_);
-
-  MainloopLock();
-  if (pa_context_) {
-    pa_context_disconnect(pa_context_);
-    pa_context_unref(pa_context_);
-    pa_context_ = NULL;
-  }
-  MainloopUnlock();
-
-  pa_threaded_mainloop_stop(pa_mainloop_);
-  pa_threaded_mainloop_free(pa_mainloop_);
-  pa_mainloop_ = NULL;
-
-  {
-    AutoLock lock(mixer_state_lock_);
-    mixer_state_ = UNINITIALIZED;
-  }
-}
-
-void PulseAudioMixer::CompleteOperation(pa_operation* pa_op,
-                                        bool* done) const {
-  // After starting any operation, this helper checks if it started OK, then
-  // waits for it to complete by iterating through the mainloop until the
-  // operation is not running anymore.
-  CHECK(pa_op);
-
-  while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
-    // If operation still running, but we got what we needed, cancel it now.
-    if (*done) {
-      pa_operation_cancel(pa_op);
-      break;
-    }
-    MainloopWait();
-  }
-  pa_operation_unref(pa_op);
-}
-
-// Must be called with mainloop lock held
-void PulseAudioMixer::GetDefaultPlaybackDevice() {
-  DCHECK_GT(mainloop_lock_count_, 0);
-  DCHECK(pa_context_);
-  DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY);
-
-  CallbackWrapper data = {this, false, NULL};
-
-  pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_,
-                                        EnumerateDevicesCallback,
-                                        &data);
-  CompleteOperation(pa_op, &data.done);
-  return;
-}
-
-void PulseAudioMixer::OnEnumerateDevices(const pa_sink_info* sink_info,
-                                         int eol, bool* done) {
-  if (device_id_ != kInvalidDeviceId)
-    return;
-
-  // TODO(davej): Should we handle cases of more than one output sink device?
-
-  // eol is < 0 for error, > 0 for end of list, ==0 while listing.
-  if (eol == 0) {
-    device_id_ = sink_info->index;
-  }
-  *done = true;
-  MainloopSignal();
-}
-
-// static
-void PulseAudioMixer::EnumerateDevicesCallback(pa_context* unused,
-                                               const pa_sink_info* sink_info,
-                                               int eol,
-                                               void* userdata) {
-  CallbackWrapper* data =
-      static_cast<CallbackWrapper*>(userdata);
-  data->instance->OnEnumerateDevices(sink_info, eol, &data->done);
-}
-
-// Must be called with lock held
-void PulseAudioMixer::GetAudioInfo(AudioInfo* info) const {
-  DCHECK_GT(mainloop_lock_count_, 0);
-  CallbackWrapper data = {const_cast<PulseAudioMixer*>(this), false, info};
-  pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_,
-                                                          device_id_,
-                                                          GetAudioInfoCallback,
-                                                          &data);
-  CompleteOperation(pa_op, &data.done);
-}
-
-// static
-void PulseAudioMixer::GetAudioInfoCallback(pa_context* unused,
-                                           const pa_sink_info* sink_info,
-                                           int eol,
-                                           void* userdata) {
-  CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata);
-  AudioInfo* info = static_cast<AudioInfo*>(data->userdata);
-
-  // Copy just the information we care about.
-  if (eol == 0) {
-    info->cvolume = sink_info->volume;
-    info->muted = sink_info->mute ? true : false;
-    data->done = true;
-  }
-  data->instance->MainloopSignal();
-}
-
-inline void PulseAudioMixer::MainloopLock() const {
-  pa_threaded_mainloop_lock(pa_mainloop_);
-  ++mainloop_lock_count_;
-}
-
-inline void PulseAudioMixer::MainloopUnlock() const {
-  --mainloop_lock_count_;
-  pa_threaded_mainloop_unlock(pa_mainloop_);
-}
-
-// Must be called with the lock held.
-inline void PulseAudioMixer::MainloopWait() const {
-  DCHECK_GT(mainloop_lock_count_, 0);
-  pa_threaded_mainloop_wait(pa_mainloop_);
-}
-
-// Must be called with the lock held.
-inline void PulseAudioMixer::MainloopSignal() const {
-  DCHECK_GT(mainloop_lock_count_, 0);
-  pa_threaded_mainloop_signal(pa_mainloop_, 0);
-}
-
-inline bool PulseAudioMixer::MainloopSafeLock() const {
-  AutoLock lock(mixer_state_lock_);
-  if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_))
-    return false;
-  pa_threaded_mainloop_lock(pa_mainloop_);
-  ++mainloop_lock_count_;
-  return true;
-}
-
-inline bool PulseAudioMixer::MainloopLockIfReady() const {
-  AutoLock lock(mixer_state_lock_);
-  if (mixer_state_ != READY)
-    return false;
-  if (!pa_mainloop_)
-    return false;
-  pa_threaded_mainloop_lock(pa_mainloop_);
-  ++mainloop_lock_count_;
-  return true;
-}
-
-}  // namespace chromeos
-
diff --git a/chrome/browser/chromeos/pulse_audio_mixer.h b/chrome/browser/chromeos/pulse_audio_mixer.h
deleted file mode 100644
index f01e738..0000000
--- a/chrome/browser/chromeos/pulse_audio_mixer.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_PULSE_AUDIO_MIXER_H_
-#define CHROME_BROWSER_CHROMEOS_PULSE_AUDIO_MIXER_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/lock.h"
-#include "base/scoped_ptr.h"
-#include "base/threading/thread.h"
-
-struct pa_context;
-struct pa_cvolume;
-struct pa_threaded_mainloop;
-struct pa_operation;
-struct pa_sink_info;
-
-namespace chromeos {
-
-class PulseAudioMixer {
- public:
-  enum State {
-    UNINITIALIZED = 0,
-    INITIALIZING,
-    READY,
-    SHUTTING_DOWN,
-    IN_ERROR
-  };
-
-  PulseAudioMixer();
-  ~PulseAudioMixer();
-
-  // Non-blocking, connect to PulseAudio and find a default device, and call
-  // callback when complete with success code.
-  typedef Callback1<bool>::Type InitDoneCallback;
-  bool Init(InitDoneCallback* callback);
-
-  // Blocking init call guarantees PulseAudio is started before returning.
-  bool InitSync();
-
-  // Blocking call. Returns a default of -inf on error.
-  double GetVolumeDb() const;
-
-  // Non-blocking, volume sent in as first param to callback.  The callback is
-  // only called if the function returns true.
-  typedef Callback2<double, void*>::Type GetVolumeCallback;
-  bool GetVolumeDbAsync(GetVolumeCallback* callback, void* user);
-
-  // Non-blocking call.
-  void SetVolumeDb(double vol_db);
-
-  // Gets the mute state of the default device (true == mute). Blocking call.
-  // Returns a default of false on error.
-  bool IsMute() const;
-
-  // Non-Blocking call.
-  void SetMute(bool mute);
-
-  // Returns READY if we have a valid working connection to PulseAudio.
-  // This can return IN_ERROR if we lose the connection, even after an original
-  // successful init.  Non-blocking call.
-  State CheckState() const;
-
- private:
-  struct AudioInfo;
-
-  // These are the tasks to be run in the background on the worker thread.
-  void DoInit(InitDoneCallback* callback);
-  void DoGetVolume(GetVolumeCallback* callback, void* user);
-
-  static void ConnectToPulseCallbackThunk(pa_context* c, void* userdata);
-  void OnConnectToPulseCallback(pa_context* c, bool* connect_done);
-
-  // Helper function to just get our messsage loop thread going.
-  bool InitThread();
-
-  // This goes through sequence of connecting to the default PulseAudio server.
-  // We will block until we either have a valid connection or something failed.
-  // If a connection is lost for some reason, delete and recreate the object.
-  bool PulseAudioInit();
-
-  // PulseAudioFree.  Disconnect from server.
-  void PulseAudioFree();
-
-  // Iterates the PA mainloop and only returns once an operation has completed
-  // (successfully or unsuccessfully) or *done is true.
-  void CompleteOperation(pa_operation* pa_op, bool* done) const;
-
-  // For now, this just gets the first device returned from the enumeration
-  // request.  This will be the 'default' or 'master' device that all further
-  // actions are taken on.  Blocking call.
-  void GetDefaultPlaybackDevice();
-  static void EnumerateDevicesCallback(pa_context* unused,
-                                       const pa_sink_info* sink_info,
-                                       int eol,
-                                       void* userdata);
-  void OnEnumerateDevices(const pa_sink_info* sink_info, int eol, bool* done);
-
-  // Get the info we're interested in from the default device. Currently this
-  // is an array of volumes, and the mute state.  Blocking call.
-  void GetAudioInfo(AudioInfo* info) const;
-  static void GetAudioInfoCallback(pa_context* unused,
-                                   const pa_sink_info* sink_info,
-                                   int eol,
-                                   void* userdata);
-
-  // These call down to PulseAudio's mainloop locking functions
-  void MainloopLock() const;
-  void MainloopUnlock() const;
-  void MainloopWait() const;
-  void MainloopSignal() const;
-
-  // Same as Lock(), but we fail if we are shutting down or mainloop invalid.
-  bool MainloopSafeLock() const;
-
-  // Lock the mainloop pa_lock_ if mixer_state_ is READY.
-  bool MainloopLockIfReady() const;
-
-  // The PulseAudio index of the main device being used.
-  int device_id_;
-
-  // Set to the number of channels on the main device.
-  int last_channels_;
-
-  // For informational purposes only, just used to assert lock is held.
-  mutable int mainloop_lock_count_;
-
-  mutable Lock mixer_state_lock_;
-  mutable State mixer_state_;
-
-  // Cached contexts for use in PulseAudio calls.
-  pa_context* pa_context_;
-  pa_threaded_mainloop* pa_mainloop_;
-
-  scoped_ptr<base::Thread> thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(PulseAudioMixer);
-};
-
-}  // namespace chromeos
-
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::PulseAudioMixer);
-
-#endif  // CHROME_BROWSER_CHROMEOS_PULSE_AUDIO_MIXER_H_
-
diff --git a/chrome/browser/chromeos/setting_level_bubble.cc b/chrome/browser/chromeos/setting_level_bubble.cc
index 8395673..55aec2e 100644
--- a/chrome/browser/chromeos/setting_level_bubble.cc
+++ b/chrome/browser/chromeos/setting_level_bubble.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,7 +12,7 @@
 #include "chrome/browser/chromeos/setting_level_bubble_view.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "views/widget/root_view.h"
 
 namespace {
diff --git a/chrome/browser/chromeos/setting_level_bubble.h b/chrome/browser/chromeos/setting_level_bubble.h
index 9cc43d9..372e570 100644
--- a/chrome/browser/chromeos/setting_level_bubble.h
+++ b/chrome/browser/chromeos/setting_level_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include "base/basictypes.h"
 #include "base/timer.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/slide_animation.h"
 
diff --git a/chrome/browser/chromeos/setting_level_bubble_view.cc b/chrome/browser/chromeos/setting_level_bubble_view.cc
index c566124..c4691af 100644
--- a/chrome/browser/chromeos/setting_level_bubble_view.cc
+++ b/chrome/browser/chromeos/setting_level_bubble_view.cc
@@ -7,8 +7,8 @@
 #include <string>
 
 #include "base/logging.h"
-#include "gfx/canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/progress_bar.h"
 
 using views::Background;
diff --git a/chrome/browser/chromeos/status/clock_menu_button.cc b/chrome/browser/chromeos/status/clock_menu_button.cc
index b239112..f285d28 100644
--- a/chrome/browser/chromeos/status/clock_menu_button.cc
+++ b/chrome/browser/chromeos/status/clock_menu_button.cc
@@ -4,19 +4,17 @@
 
 #include "chrome/browser/chromeos/status/clock_menu_button.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/time_formatting.h"
 #include "base/string_util.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/status/status_area_host.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
 
 namespace chromeos {
 
@@ -82,7 +80,7 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// ClockMenuButton, menus::MenuModel implementation:
+// ClockMenuButton, ui::MenuModel implementation:
 
 int ClockMenuButton::GetItemCount() const {
   // If options dialog is unavailable, don't count a separator and configure
@@ -90,11 +88,11 @@
   return host_->ShouldOpenButtonOptions(this) ? 3 : 1;
 }
 
-menus::MenuModel::ItemType ClockMenuButton::GetTypeAt(int index) const {
+ui::MenuModel::ItemType ClockMenuButton::GetTypeAt(int index) const {
   // There's a separator between the current date and the menu item to open
   // the options menu.
-  return index == 1 ? menus::MenuModel::TYPE_SEPARATOR:
-                      menus::MenuModel::TYPE_COMMAND;
+  return index == 1 ? ui::MenuModel::TYPE_SEPARATOR:
+                      ui::MenuModel::TYPE_COMMAND;
 }
 
 string16 ClockMenuButton::GetLabelAt(int index) const {
diff --git a/chrome/browser/chromeos/status/clock_menu_button.h b/chrome/browser/chromeos/status/clock_menu_button.h
index c1bea3c..38a2327 100644
--- a/chrome/browser/chromeos/status/clock_menu_button.h
+++ b/chrome/browser/chromeos/status/clock_menu_button.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,6 @@
 #include "base/timer.h"
 #include "chrome/browser/chromeos/cros/system_library.h"
 #include "chrome/browser/chromeos/status/status_area_button.h"
-#include "chrome/common/notification_observer.h"
 #include "unicode/calendar.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/menu/menu_2.h"
@@ -24,29 +23,29 @@
 // This button shows the current time.
 class ClockMenuButton : public StatusAreaButton,
                         public views::ViewMenuDelegate,
-                        public menus::MenuModel,
+                        public ui::MenuModel,
                         public SystemLibrary::Observer {
  public:
   explicit ClockMenuButton(StatusAreaHost* host);
   virtual ~ClockMenuButton();
 
-  // menus::MenuModel implementation.
+  // ui::MenuModel implementation.
   virtual bool HasIcons() const  { return false; }
   virtual int GetItemCount() const;
-  virtual menus::MenuModel::ItemType GetTypeAt(int index) const;
+  virtual ui::MenuModel::ItemType GetTypeAt(int index) const;
   virtual int GetCommandIdAt(int index) const { return index; }
   virtual string16 GetLabelAt(int index) const;
   virtual bool IsItemDynamicAt(int index) const { return true; }
   virtual bool GetAcceleratorAt(int index,
-      menus::Accelerator* accelerator) const { return false; }
+      ui::Accelerator* accelerator) const { return false; }
   virtual bool IsItemCheckedAt(int index) const { return false; }
   virtual int GetGroupIdAt(int index) const { return 0; }
   virtual bool GetIconAt(int index, SkBitmap* icon) const { return false; }
-  virtual menus::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
+  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
     return NULL;
   }
   virtual bool IsEnabledAt(int index) const;
-  virtual menus::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
+  virtual ui::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
   virtual void HighlightChangedTo(int index) {}
   virtual void ActivatedAt(int index);
   virtual void MenuWillShow() {}
diff --git a/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc b/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc
index 9f934d6..4452bbc 100644
--- a/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc
+++ b/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "unicode/calendar.h"
diff --git a/chrome/browser/chromeos/status/input_method_menu.cc b/chrome/browser/chromeos/status/input_method_menu.cc
index 3b81133..209b4a2 100644
--- a/chrome/browser/chromeos/status/input_method_menu.cc
+++ b/chrome/browser/chromeos/status/input_method_menu.cc
@@ -7,8 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/time.h"
@@ -24,6 +22,8 @@
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // The language menu consists of 3 parts (in this order):
 //
@@ -87,6 +87,7 @@
   { "xkb:us:dvorak:eng", "DV" },
   { "xkb:us:intl:eng", "INTL" },
   { "xkb:us:colemak:eng", "CO" },
+  { "xkb:de:neo:ger", "NEO" },
   // To distinguish from "xkb:jp::jpn"
   { "mozc", "\xe3\x81\x82" },  // U+3042, Japanese Hiragana letter A in UTF-8.
   { "mozc-dv", "\xe3\x81\x82" },
@@ -118,9 +119,8 @@
 // InputMethodMenu
 
 InputMethodMenu::InputMethodMenu(PrefService* pref_service,
-                                 bool is_browser_mode,
-                                 bool is_screen_locker_mode,
-                                 bool is_out_of_box_experience_mode)
+                                 StatusAreaHost::ScreenMode screen_mode,
+                                 bool for_out_of_box_experience_dialog)
     : input_method_descriptors_(CrosLibrary::Get()->GetInputMethodLibrary()->
                                 GetActiveInputMethods()),
       model_(NULL),
@@ -130,42 +130,24 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(input_method_menu_(this)),
       minimum_input_method_menu_width_(0),
       pref_service_(pref_service),
-      logged_in_(false),
-      is_browser_mode_(is_browser_mode),
-      is_screen_locker_mode_(is_screen_locker_mode),
-      is_out_of_box_experience_mode_(is_out_of_box_experience_mode) {
+      screen_mode_(screen_mode),
+      for_out_of_box_experience_dialog_(for_out_of_box_experience_dialog) {
   DCHECK(input_method_descriptors_.get() &&
          !input_method_descriptors_->empty());
 
-  // Use the same keyboard layout on all windows.
-  CrosLibrary::Get()->GetKeyboardLibrary()->SetKeyboardLayoutPerWindow(false);
-
   // Sync current and previous input methods on Chrome prefs with ibus-daemon.
-  // InputMethodChanged() will be called soon and the indicator will be updated.
-  InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
-  if (pref_service && is_browser_mode_) {
+  if (pref_service_ && (screen_mode_ == StatusAreaHost::kBrowserMode)) {
     previous_input_method_pref_.Init(
         prefs::kLanguagePreviousInputMethod, pref_service, this);
-    const std::string previous_input_method_id =
-        previous_input_method_pref_.GetValue();
-    if (!previous_input_method_id.empty()) {
-      library->ChangeInputMethod(previous_input_method_id);
-    }
-
     current_input_method_pref_.Init(
         prefs::kLanguageCurrentInputMethod, pref_service, this);
-    const std::string current_input_method_id =
-        current_input_method_pref_.GetValue();
-    if (!current_input_method_id.empty()) {
-      library->ChangeInputMethod(current_input_method_id);
-    }
   }
-  library->AddObserver(this);
 
-  if (is_browser_mode_ || is_screen_locker_mode_) {
-    logged_in_ = true;
-  }
-  if (!logged_in_) {
+  InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
+  library->AddObserver(this);  // FirstObserverIsAdded() might be called back.
+
+  if (screen_mode_ == StatusAreaHost::kLoginMode) {
+    // This button is for the login screen.
     registrar_.Add(this,
                    NotificationType::LOGIN_USER_CHANGED,
                    NotificationService::AllSources());
@@ -173,14 +155,16 @@
 }
 
 InputMethodMenu::~InputMethodMenu() {
+  // RemoveObserver() is no-op if |this| object is already removed from the
+  // observer list.
   CrosLibrary::Get()->GetInputMethodLibrary()->RemoveObserver(this);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// menus::MenuModel implementation:
+// ui::MenuModel implementation:
 
 int InputMethodMenu::GetCommandIdAt(int index) const {
-  return 0;  // dummy
+  return index;
 }
 
 bool InputMethodMenu::IsItemDynamicAt(int index) const {
@@ -189,7 +173,7 @@
 }
 
 bool InputMethodMenu::GetAcceleratorAt(
-    int index, menus::Accelerator* accelerator) const {
+    int index, ui::Accelerator* accelerator) const {
   // Views for Chromium OS does not support accelerators yet.
   return false;
 }
@@ -219,7 +203,7 @@
   DCHECK_GE(index, 0);
 
   if (IndexIsInInputMethodList(index)) {
-    return is_out_of_box_experience_mode_ ?
+    return for_out_of_box_experience_dialog_ ?
         kRadioGroupNone : kRadioGroupLanguage;
   }
 
@@ -241,7 +225,7 @@
   return false;
 }
 
-menus::ButtonMenuItemModel* InputMethodMenu::GetButtonMenuItemAt(
+ui::ButtonMenuItemModel* InputMethodMenu::GetButtonMenuItemAt(
     int index) const {
   return NULL;
 }
@@ -252,7 +236,7 @@
   return true;
 }
 
-menus::MenuModel* InputMethodMenu::GetSubmenuModelAt(int index) const {
+ui::MenuModel* InputMethodMenu::GetSubmenuModelAt(int index) const {
   // We don't use nested menus.
   return NULL;
 }
@@ -274,28 +258,28 @@
   return model_->GetItemCount();
 }
 
-menus::MenuModel::ItemType InputMethodMenu::GetTypeAt(int index) const {
+ui::MenuModel::ItemType InputMethodMenu::GetTypeAt(int index) const {
   DCHECK_GE(index, 0);
 
   if (IndexPointsToConfigureImeMenuItem(index)) {
-    return menus::MenuModel::TYPE_COMMAND;  // "Customize language and input"
+    return ui::MenuModel::TYPE_COMMAND;  // "Customize language and input"
   }
 
   if (IndexIsInInputMethodList(index)) {
-    return is_out_of_box_experience_mode_ ?
-        menus::MenuModel::TYPE_COMMAND : menus::MenuModel::TYPE_RADIO;
+    return for_out_of_box_experience_dialog_ ?
+        ui::MenuModel::TYPE_COMMAND : ui::MenuModel::TYPE_RADIO;
   }
 
   if (GetPropertyIndex(index, &index)) {
     const ImePropertyList& property_list
         = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
     if (property_list.at(index).is_selection_item) {
-      return menus::MenuModel::TYPE_RADIO;
+      return ui::MenuModel::TYPE_RADIO;
     }
-    return menus::MenuModel::TYPE_COMMAND;
+    return ui::MenuModel::TYPE_COMMAND;
   }
 
-  return menus::MenuModel::TYPE_SEPARATOR;
+  return ui::MenuModel::TYPE_SEPARATOR;
 }
 
 string16 InputMethodMenu::GetLabelAt(int index) const {
@@ -335,6 +319,8 @@
         = input_method_descriptors_->at(index);
     CrosLibrary::Get()->GetInputMethodLibrary()->ChangeInputMethod(
         input_method.id);
+    UserMetrics::RecordAction(
+        UserMetricsAction("LanguageMenuButton_InputMethodChanged"));
     return;
   }
 
@@ -382,39 +368,61 @@
 
 void InputMethodMenu::InputMethodChanged(
     InputMethodLibrary* obj,
-    const InputMethodDescriptor& previous_input_method,
     const InputMethodDescriptor& current_input_method,
     size_t num_active_input_methods) {
-  UserMetrics::RecordAction(
-      UserMetricsAction("LanguageMenuButton_InputMethodChanged"));
   UpdateUIFromInputMethod(current_input_method, num_active_input_methods);
+  PrepareMenu();
 }
 
 void InputMethodMenu::PreferenceUpdateNeeded(
     InputMethodLibrary* obj,
     const InputMethodDescriptor& previous_input_method,
     const InputMethodDescriptor& current_input_method) {
-  if (is_browser_mode_) {
+  if (screen_mode_ == StatusAreaHost::kBrowserMode) {
     if (pref_service_) {  // make sure we're not in unit tests.
       // Sometimes (e.g. initial boot) |previous_input_method.id| is empty.
       previous_input_method_pref_.SetValue(previous_input_method.id);
       current_input_method_pref_.SetValue(current_input_method.id);
     }
-  } else {
-    // We're in the login screen (i.e. not in the normal browser mode nor screen
-    // locker mode). If a user has already logged in, we should not update the
-    // local state since a profile for the user might be loaded before the
-    // buttun for the login screen is destroyed.
-    if (!logged_in_ && g_browser_process && g_browser_process->local_state()) {
-        g_browser_process->local_state()->SetString(
-            language_prefs::kPreferredKeyboardLayout, current_input_method.id);
-        g_browser_process->local_state()->SavePersistentPrefs();
+  } else if (screen_mode_ == StatusAreaHost::kLoginMode) {
+    if (g_browser_process && g_browser_process->local_state()) {
+      g_browser_process->local_state()->SetString(
+          language_prefs::kPreferredKeyboardLayout, current_input_method.id);
+      g_browser_process->local_state()->SavePersistentPrefs();
+    }
+  }
+}
+
+void InputMethodMenu::FirstObserverIsAdded(InputMethodLibrary* obj) {
+  // NOTICE: Since this function might be called from the constructor of this
+  // class, it's better to avoid calling virtual functions.
+
+  if (pref_service_ && (screen_mode_ == StatusAreaHost::kBrowserMode)) {
+    // Get the input method name in the Preferences file which was in use last
+    // time, and switch to the method. We remember two input method names in the
+    // preference so that the Control+space hot-key could work fine from the
+    // beginning. InputMethodChanged() will be called soon and the indicator
+    // will be updated.
+    InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
+    const std::string previous_input_method_id =
+        previous_input_method_pref_.GetValue();
+    if (!previous_input_method_id.empty()) {
+      library->ChangeInputMethod(previous_input_method_id);
+    }
+    const std::string current_input_method_id =
+        current_input_method_pref_.GetValue();
+    if (!current_input_method_id.empty()) {
+      library->ChangeInputMethod(current_input_method_id);
     }
   }
 }
 
 void InputMethodMenu::PrepareForMenuOpen() {
   UserMetrics::RecordAction(UserMetricsAction("LanguageMenuButton_Open"));
+  PrepareMenu();
+}
+
+void InputMethodMenu::PrepareMenu() {
   input_method_descriptors_.reset(CrosLibrary::Get()->GetInputMethodLibrary()->
                                   GetActiveInputMethods());
   RebuildModel();
@@ -442,7 +450,7 @@
 }
 
 void InputMethodMenu::RebuildModel() {
-  model_.reset(new menus::SimpleMenuModel(NULL));
+  model_.reset(new ui::SimpleMenuModel(NULL));
   string16 dummy_label = UTF8ToUTF16("");
   // Indicates if separator's needed before each section.
   bool need_separator = false;
@@ -488,7 +496,7 @@
     return false;
   }
 
-  return ((model_->GetTypeAt(index) == menus::MenuModel::TYPE_RADIO) &&
+  return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) &&
           (model_->GetCommandIdAt(index) == COMMAND_ID_INPUT_METHODS) &&
           input_method_descriptors_.get() &&
           (index < static_cast<int>(input_method_descriptors_->size())));
@@ -502,7 +510,7 @@
     return false;
   }
 
-  if ((model_->GetTypeAt(index) == menus::MenuModel::TYPE_RADIO) &&
+  if ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) &&
       (model_->GetCommandIdAt(index) == COMMAND_ID_IME_PROPERTIES)) {
     const int tmp_property_index = model_->GetGroupIdAt(index);
     const ImePropertyList& property_list
@@ -522,7 +530,7 @@
     return false;
   }
 
-  return ((model_->GetTypeAt(index) == menus::MenuModel::TYPE_RADIO) &&
+  return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) &&
           (model_->GetCommandIdAt(index) == COMMAND_ID_CUSTOMIZE_LANGUAGE));
 }
 
@@ -540,8 +548,8 @@
     }
   }
 
-  // Display the keyboard layout name when using ibus-xkb.
-  if (text.empty()) {
+  // Display the keyboard layout name when using a keyboard layout.
+  if (text.empty() && input_method::IsKeyboardLayout(input_method.id)) {
     const size_t kMaxKeyboardLayoutNameLen = 2;
     const std::wstring keyboard_layout = UTF8ToWide(
         input_method::GetKeyboardLayoutName(input_method.id));
@@ -610,7 +618,10 @@
                               const NotificationSource& source,
                               const NotificationDetails& details) {
   if (type == NotificationType::LOGIN_USER_CHANGED) {
-    logged_in_ = true;
+    // When a user logs in, we should remove |this| object from the observer
+    // list so that PreferenceUpdateNeeded() does not update the local state
+    // anymore.
+    CrosLibrary::Get()->GetInputMethodLibrary()->RemoveObserver(this);
   }
 }
 
diff --git a/chrome/browser/chromeos/status/input_method_menu.h b/chrome/browser/chromeos/status/input_method_menu.h
index 814526e..3703d30 100644
--- a/chrome/browser/chromeos/status/input_method_menu.h
+++ b/chrome/browser/chromeos/status/input_method_menu.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,12 +8,13 @@
 
 #include <string>
 
-#include "app/menus/simple_menu_model.h"
 #include "chrome/browser/chromeos/cros/input_method_library.h"
+#include "chrome/browser/chromeos/status/status_area_host.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_type.h"
+#include "ui/base/models/simple_menu_model.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/controls/menu/view_menu_delegate.h"
 
@@ -27,33 +28,30 @@
 // create a button widget (e.g. views::MenuButton, chromeos::StatusAreaButton)
 // which shows the dropdown menu on click.
 class InputMethodMenu : public views::ViewMenuDelegate,
-                        public menus::MenuModel,
+                        public ui::MenuModel,
                         public InputMethodLibrary::Observer,
                         public NotificationObserver {
  public:
   InputMethodMenu(PrefService* pref_service,
-                  // TODO(yusukes): combine the three booleans into one enum.
-                  // http://crosbug.com/8386.
-                  bool is_browser_mode,
-                  bool is_screen_locker,
-                  bool is_out_of_box_experience_mode);
+                  StatusAreaHost::ScreenMode screen_mode,
+                  bool for_out_of_box_experience_dialog);
   virtual ~InputMethodMenu();
 
-  // menus::MenuModel implementation.
+  // ui::MenuModel implementation.
   virtual bool HasIcons() const;
   virtual int GetItemCount() const;
-  virtual menus::MenuModel::ItemType GetTypeAt(int index) const;
+  virtual ui::MenuModel::ItemType GetTypeAt(int index) const;
   virtual int GetCommandIdAt(int index) const;
   virtual string16 GetLabelAt(int index) const;
   virtual bool IsItemDynamicAt(int index) const;
   virtual bool GetAcceleratorAt(int index,
-                                menus::Accelerator* accelerator) const;
+                                ui::Accelerator* accelerator) const;
   virtual bool IsItemCheckedAt(int index) const;
   virtual int GetGroupIdAt(int index) const;
   virtual bool GetIconAt(int index, SkBitmap* icon) const;
-  virtual menus::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const;
+  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const;
   virtual bool IsEnabledAt(int index) const;
-  virtual menus::MenuModel* GetSubmenuModelAt(int index) const;
+  virtual ui::MenuModel* GetSubmenuModelAt(int index) const;
   virtual void HighlightChangedTo(int index);
   virtual void ActivatedAt(int index);
   virtual void MenuWillShow();
@@ -66,7 +64,6 @@
   // InputMethodLibrary::Observer implementation.
   virtual void InputMethodChanged(
       InputMethodLibrary* obj,
-      const InputMethodDescriptor& previous_input_method,
       const InputMethodDescriptor& current_input_method,
       size_t num_active_input_methods);
   virtual void ActiveInputMethodsChanged(
@@ -77,6 +74,7 @@
     InputMethodLibrary* obj,
     const InputMethodDescriptor& previous_input_method,
     const InputMethodDescriptor& current_input_method);
+  virtual void FirstObserverIsAdded(InputMethodLibrary* obj);
 
   // NotificationObserver implementation.
   virtual void Observe(NotificationType type,
@@ -99,11 +97,7 @@
   static std::wstring GetTextForMenu(const InputMethodDescriptor& input_method);
 
  protected:
-  // Parses |input_method| and then calls UpdateUI().
-  void UpdateUIFromInputMethod(const InputMethodDescriptor& input_method,
-                               size_t num_active_input_methods);
-
-  // Rebuilds model and menu2 objects in preparetion to open the menu.
+  // Prepares menu: saves user metrics and rebuilds.
   void PrepareForMenuOpen();
 
   // Returns menu2 object for language menu.
@@ -112,6 +106,9 @@
   }
 
  private:
+  // Rebuilds model and menu2 objects.
+  void PrepareMenu();
+
   // Updates UI of a container of the menu (e.g. the "US" menu button in the
   // status area). Sub classes have to implement the interface for their own UI.
   virtual void UpdateUI(const std::string& input_method_id,  // e.g. "mozc"
@@ -121,13 +118,17 @@
 
   // Sub classes have to implement the interface. This interface should return
   // true if the dropdown menu should show an item like "Customize languages
-  // and input..." DOMUI.
+  // and input..." WebUI.
   virtual bool ShouldSupportConfigUI() = 0;
 
   // Sub classes have to implement the interface which opens an UI for
   // customizing languages and input.
   virtual void OpenConfigUI() = 0;
 
+  // Parses |input_method| and then calls UpdateUI().
+  void UpdateUIFromInputMethod(const InputMethodDescriptor& input_method,
+                               size_t num_active_input_methods);
+
   // Rebuilds |model_|. This function should be called whenever
   // |input_method_descriptors_| is updated, or ImePropertiesChanged() is
   // called.
@@ -152,10 +153,10 @@
   StringPrefMember previous_input_method_pref_;
   StringPrefMember current_input_method_pref_;
 
-  // We borrow menus::SimpleMenuModel implementation to maintain the current
-  // content of the pop-up menu. The menus::MenuModel is implemented using this
+  // We borrow ui::SimpleMenuModel implementation to maintain the current
+  // content of the pop-up menu. The ui::MenuModel is implemented using this
   // |model_|.
-  scoped_ptr<menus::SimpleMenuModel> model_;
+  scoped_ptr<ui::SimpleMenuModel> model_;
 
   // The language menu which pops up when the button in status area is clicked.
   views::Menu2 input_method_menu_;
@@ -163,10 +164,12 @@
 
   PrefService* pref_service_;
   NotificationRegistrar registrar_;
-  bool logged_in_;
-  const bool is_browser_mode_;
-  const bool is_screen_locker_mode_;
-  const bool is_out_of_box_experience_mode_;
+
+  // The mode of the host screen  (e.g. browser, screen locker, login screen.)
+  const StatusAreaHost::ScreenMode screen_mode_;
+  // true if the menu is for a dialog in OOBE screen. In the dialog, we don't
+  // use radio buttons.
+  const bool for_out_of_box_experience_dialog_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodMenu);
 };
diff --git a/chrome/browser/chromeos/status/input_method_menu_button.cc b/chrome/browser/chromeos/status/input_method_menu_button.cc
index ab5987c..3060760 100644
--- a/chrome/browser/chromeos/status/input_method_menu_button.cc
+++ b/chrome/browser/chromeos/status/input_method_menu_button.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/keyboard_library.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/chromeos/status/status_area_host.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -32,6 +32,35 @@
 const int kFontSizeDelta = 1;
 #endif
 
+// A class which implements interfaces of chromeos::InputMethodMenu. This class
+// is just for avoiding multiple inheritance.
+class MenuImpl : public chromeos::InputMethodMenu {
+ public:
+  MenuImpl(chromeos::InputMethodMenuButton* button,
+           PrefService* pref_service,
+           chromeos::StatusAreaHost::ScreenMode screen_mode)
+      : InputMethodMenu(pref_service, screen_mode, false), button_(button) {}
+
+ private:
+  // InputMethodMenu implementation.
+  virtual void UpdateUI(const std::string& input_method_id,
+                        const std::wstring& name,
+                        const std::wstring& tooltip,
+                        size_t num_active_input_methods) {
+    button_->UpdateUI(input_method_id, name, tooltip, num_active_input_methods);
+  }
+  virtual bool ShouldSupportConfigUI() {
+    return button_->ShouldSupportConfigUI();
+  }
+  virtual void OpenConfigUI() {
+    button_->OpenConfigUI();
+  }
+  // The UI (views button) to which this class delegates all requests.
+  chromeos::InputMethodMenuButton* button_;
+
+  DISALLOW_COPY_AND_ASSIGN(MenuImpl);
+};
+
 }  // namespace
 
 namespace chromeos {
@@ -41,10 +70,7 @@
 
 InputMethodMenuButton::InputMethodMenuButton(StatusAreaHost* host)
     : StatusAreaButton(this),
-      InputMethodMenu(GetPrefService(host),
-                      host->IsBrowserMode(),
-                      host->IsScreenLockerMode(),
-                      false /* is_out_of_box_experience_mode */),
+      menu_(new MenuImpl(this, GetPrefService(host), host->GetScreenMode())),
       host_(host) {
   set_border(NULL);
   set_use_menu_button_paint(true);
@@ -55,16 +81,7 @@
   SetShowMultipleIconStates(false);
   set_alignment(TextButton::ALIGN_CENTER);
 
-  chromeos::KeyboardLibrary* keyboard_library =
-      chromeos::CrosLibrary::Get()->GetKeyboardLibrary();
-  const std::string hardware_keyboard_id =  // e.g. "xkb:us::eng"
-      keyboard_library->GetHardwareKeyboardLayoutName();
-
-  // Draw the default indicator "US". The default indicator "US" is used when
-  // |pref_service| is not available (for example, unit tests) or |pref_service|
-  // is available, but Chrome preferences are not available (for example,
-  // initial OS boot).
-  InputMethodMenuButton::UpdateUI(hardware_keyboard_id, L"US", L"", 1);
+  UpdateUIFromCurrentInputMethod();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -80,27 +97,18 @@
 
 void InputMethodMenuButton::OnLocaleChanged() {
   input_method::OnLocaleChanged();
-
-  chromeos::InputMethodLibrary* input_method_library =
-      chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
-  const InputMethodDescriptor& input_method =
-      input_method_library->current_input_method();
-
-  // In general, we should not call an input method API in the input method
-  // button classes (status/input_menu_button*.cc) for performance reasons (see
-  // http://crosbug.com/8284). However, since OnLocaleChanged is called only in
-  // OOBE/Login screen which does not have two or more Chrome windows, it's okay
-  // to call GetNumActiveInputMethods here.
-  const size_t num_active_input_methods =
-      input_method_library->GetNumActiveInputMethods();
-
-  UpdateUIFromInputMethod(input_method, num_active_input_methods);
+  UpdateUIFromCurrentInputMethod();
   Layout();
   SchedulePaint();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// InputMethodMenu::InputMethodMenuHost implementation:
+// views::ViewMenuDelegate implementation:
+
+void InputMethodMenuButton::RunMenu(views::View* unused_source,
+                                    const gfx::Point& pt) {
+  menu_->RunMenu(unused_source, pt);
+}
 
 void InputMethodMenuButton::UpdateUI(const std::string& input_method_id,
                                      const std::wstring& name,
@@ -112,7 +120,7 @@
   // like Hiragana and Katakana modes in Japanese input methods.
   if (num_active_input_methods == 1 &&
       input_method::IsKeyboardLayout(input_method_id) &&
-      host_->IsBrowserMode()) {
+      host_->GetScreenMode() == StatusAreaHost::kBrowserMode) {
     // As the disabled color is set to invisible, disabling makes the
     // button disappear.
     SetEnabled(false);
@@ -126,11 +134,23 @@
 }
 
 void InputMethodMenuButton::OpenConfigUI() {
-  host_->OpenButtonOptions(this);  // ask browser to open the DOMUI page.
+  host_->OpenButtonOptions(this);  // ask browser to open the WebUI page.
 }
 
 bool InputMethodMenuButton::ShouldSupportConfigUI() {
   return host_->ShouldOpenButtonOptions(this);
 }
 
+void InputMethodMenuButton::UpdateUIFromCurrentInputMethod() {
+  chromeos::InputMethodLibrary* input_method_library =
+      chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
+  const InputMethodDescriptor& input_method =
+      input_method_library->current_input_method();
+  const std::wstring name = InputMethodMenu::GetTextForIndicator(input_method);
+  const std::wstring tooltip = InputMethodMenu::GetTextForMenu(input_method);
+  const size_t num_active_input_methods =
+      input_method_library->GetNumActiveInputMethods();
+  UpdateUI(input_method.id, name, tooltip, num_active_input_methods);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/status/input_method_menu_button.h b/chrome/browser/chromeos/status/input_method_menu_button.h
index 3a232eb..a6cd675 100644
--- a/chrome/browser/chromeos/status/input_method_menu_button.h
+++ b/chrome/browser/chromeos/status/input_method_menu_button.h
@@ -10,6 +10,7 @@
 
 #include "chrome/browser/chromeos/status/input_method_menu.h"
 #include "chrome/browser/chromeos/status/status_area_button.h"
+#include "views/controls/menu/view_menu_delegate.h"
 
 namespace chromeos {
 
@@ -18,7 +19,7 @@
 // A class for the button in the status area which expands the dropdown menu for
 // switching input method and keyboard layout.
 class InputMethodMenuButton : public StatusAreaButton,
-                              public InputMethodMenu {
+                              public views::ViewMenuDelegate {
  public:
   explicit InputMethodMenuButton(StatusAreaHost* host);
   virtual ~InputMethodMenuButton() {}
@@ -27,7 +28,9 @@
   virtual gfx::Size GetPreferredSize();
   virtual void OnLocaleChanged();
 
- private:
+  // views::ViewMenuDelegate implementation.
+  virtual void RunMenu(views::View* unused_source, const gfx::Point& pt);
+
   // InputMethodMenu implementation.
   virtual void UpdateUI(const std::string& input_method_id,
                         const std::wstring& name,
@@ -36,6 +39,11 @@
   virtual bool ShouldSupportConfigUI();
   virtual void OpenConfigUI();
 
+  // Updates the UI from the current input method.
+  void UpdateUIFromCurrentInputMethod();
+
+ private:
+  scoped_ptr<InputMethodMenu> menu_;
   StatusAreaHost* host_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodMenuButton);
diff --git a/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc b/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc
index ca9e9fe..b2db7fc 100644
--- a/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc
+++ b/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc
@@ -38,8 +38,8 @@
   InputMethodMenuButton* input_method = GetInputMethodMenuButton();
   ASSERT_TRUE(input_method != NULL);
 
-  // Since the default input method is "xkb:us::eng", "US" should be set for the
-  // indicator.
+  // By default, show the indicator of the hardware keyboard, which is set
+  // to US for tests.
   std::wstring indicator = input_method->text();
   EXPECT_EQ(L"US", indicator);
 }
diff --git a/chrome/browser/chromeos/status/input_method_menu_unittest.cc b/chrome/browser/chromeos/status/input_method_menu_unittest.cc
index 1ad1d59..38704f4 100644
--- a/chrome/browser/chromeos/status/input_method_menu_unittest.cc
+++ b/chrome/browser/chromeos/status/input_method_menu_unittest.cc
@@ -5,11 +5,13 @@
 #include "chrome/browser/chromeos/status/input_method_menu.h"
 
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
 
 TEST(InputMethodMenuTest, GetTextForIndicatorTest) {
+  ScopedStubCrosEnabler enabler;
   // Test normal cases. Two-letter language code should be returned.
   {
     InputMethodDescriptor desc("m17n:fa:isiri",  // input method engine id
@@ -47,6 +49,11 @@
     EXPECT_EQ(L"INTL", InputMethodMenu::GetTextForIndicator(desc));
   }
   {
+    InputMethodDescriptor desc("xkb:de:neo:ger", "Germany - Neo 2", "de(neo)",
+                               "ger");
+    EXPECT_EQ(L"NEO", InputMethodMenu::GetTextForIndicator(desc));
+  }
+  {
     InputMethodDescriptor desc("mozc", "Mozc", "us", "ja");
     EXPECT_EQ(UTF8ToWide("\xe3\x81\x82"),
               InputMethodMenu::GetTextForIndicator(desc));
diff --git a/chrome/browser/chromeos/status/network_dropdown_button.cc b/chrome/browser/chromeos/status/network_dropdown_button.cc
index 8244df4..7eee9cb 100644
--- a/chrome/browser/chromeos/status/network_dropdown_button.cc
+++ b/chrome/browser/chromeos/status/network_dropdown_button.cc
@@ -4,15 +4,15 @@
 
 #include "chrome/browser/chromeos/status/network_dropdown_button.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/chromeos/status/status_area_host.h"
-#include "gfx/canvas_skia.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/window/window.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc
index c09594d..03c4451 100644
--- a/chrome/browser/chromeos/status/network_menu.cc
+++ b/chrome/browser/chromeos/status/network_menu.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
@@ -17,12 +15,14 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/browser/views/window.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/skbitmap_operations.h"
+#include "chrome/browser/ui/views/window.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/skbitmap_operations.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/window/window.h"
 
@@ -217,7 +217,7 @@
       }
       if (!connected) {
         if (!MenuUI::IsEnabled()) {
-          // Show the wifi dialog on a failed attempt for non DOM UI menus.
+          // Show the wifi dialog on a failed attempt for non Web UI menus.
           ShowNetworkConfigView(new NetworkConfigView(wifi));
           return true;
         } else {
@@ -270,13 +270,13 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// NetworkMenu, menus::MenuModel implementation:
+// NetworkMenu, ui::MenuModel implementation:
 
 int NetworkMenu::GetItemCount() const {
   return static_cast<int>(menu_items_.size());
 }
 
-menus::MenuModel::ItemType NetworkMenu::GetTypeAt(int index) const {
+ui::MenuModel::ItemType NetworkMenu::GetTypeAt(int index) const {
   return menu_items_[index].type;
 }
 
@@ -291,7 +291,7 @@
 }
 
 bool NetworkMenu::IsItemCheckedAt(int index) const {
-  // All menus::MenuModel::TYPE_CHECK menu items are checked.
+  // All ui::MenuModel::TYPE_CHECK menu items are checked.
   return true;
 }
 
@@ -358,7 +358,11 @@
 SkBitmap NetworkMenu::IconForNetworkStrength(const WifiNetwork* wifi,
                                              bool black) {
   DCHECK(wifi);
-  // Compose wifi icon by superimposing various icons.
+  if (wifi->strength() == 0) {
+    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
+        black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
+                IDR_STATUSBAR_NETWORK_BARS0);
+  }
   int index = static_cast<int>(wifi->strength() / 100.0 *
       nextafter(static_cast<float>(kNumBarsImages), 0));
   index = std::max(std::min(index, kNumBarsImages - 1), 0);
@@ -371,12 +375,12 @@
                                              bool black) {
   DCHECK(cellular);
   // If no data, then we show 0 bars.
-  if (cellular->GetDataLeft() == CellularNetwork::DATA_NONE) {
+  if (cellular->strength() == 0 ||
+      cellular->GetDataLeft() == CellularNetwork::DATA_NONE) {
     return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
         black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
                 IDR_STATUSBAR_NETWORK_BARS0);
   }
-  // Compose cellular icon by superimposing various icons.
   int index = static_cast<int>(cellular->strength() / 100.0 *
       nextafter(static_cast<float>(kNumBarsImages), 0));
   index = std::max(std::min(index, kNumBarsImages - 1), 0);
@@ -418,6 +422,9 @@
       case CellularNetwork::DATA_NORMAL:
         id = IDR_STATUSBAR_NETWORK_3G;
         break;
+      case CellularNetwork::DATA_UNKNOWN:
+        id = IDR_STATUSBAR_NETWORK_3G_UNKNOWN;
+        break;
     }
   } else if (cellular->network_technology() == NETWORK_TECHNOLOGY_1XRTT) {
     switch (cellular->GetDataLeft()) {
@@ -429,6 +436,9 @@
       case CellularNetwork::DATA_NORMAL:
         id = IDR_STATUSBAR_NETWORK_1X;
         break;
+      case CellularNetwork::DATA_UNKNOWN:
+        id = IDR_STATUSBAR_NETWORK_1X_UNKNOWN;
+        break;
     }
   }
   if (id == -1)
@@ -483,6 +493,15 @@
 
   string16 label;
 
+  if (cros->IsLocked()) {
+    label = l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_LOCKED);
+    menu_items_.push_back(
+        MenuItem(ui::MenuModel::TYPE_COMMAND,
+                 label, SkBitmap(),
+                 std::string(), FLAG_DISABLED));
+    return;
+  }
+
   // Ethernet
   bool ethernet_available = cros->ethernet_available();
   bool ethernet_enabled = cros->ethernet_enabled();
@@ -505,7 +524,7 @@
     if (ethernet_connecting || ethernet_connected)
       flag |= FLAG_ASSOCIATED;
     menu_items_.push_back(
-        MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+        MenuItem(ui::MenuModel::TYPE_COMMAND, label,
                  IconForDisplay(icon, badge), std::string(), flag));
   }
 
@@ -546,7 +565,7 @@
           && wifi_networks[i]->service_path() == active_wifi->service_path())
         flag |= FLAG_ASSOCIATED;
       menu_items_.push_back(
-          MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+          MenuItem(ui::MenuModel::TYPE_COMMAND, label,
                    IconForDisplay(icon, badge),
                    wifi_networks[i]->service_path(), flag));
     }
@@ -607,7 +626,7 @@
       if (isActive)
         flag |= FLAG_ASSOCIATED;
       menu_items_.push_back(
-          MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+          MenuItem(ui::MenuModel::TYPE_COMMAND, label,
                    IconForDisplay(icon, badge),
                    cell_networks[i]->service_path(), flag));
       if (isActive) {
@@ -622,7 +641,7 @@
         }
         if (label.length()) {
           menu_items_.push_back(
-              MenuItem(menus::MenuModel::TYPE_COMMAND,
+              MenuItem(ui::MenuModel::TYPE_COMMAND,
                        label, SkBitmap(),
                        std::string(), FLAG_DISABLED));
         }
@@ -634,7 +653,7 @@
   if (menu_items_.empty()) {
     label = l10n_util::GetStringFUTF16(IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT,
                 l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE));
-    menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+    menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
         SkBitmap(), std::string(), FLAG_DISABLED));
   }
 
@@ -642,7 +661,7 @@
   if (wifi_available && wifi_enabled) {
     menu_items_.push_back(MenuItem());  // Separator
     menu_items_.push_back(MenuItem(
-        menus::MenuModel::TYPE_COMMAND,
+        ui::MenuModel::TYPE_COMMAND,
         l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_NETWORKS),
         IconForDisplay(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0_BLACK),
                        SkBitmap()),
@@ -657,7 +676,7 @@
       // Add 'Scanning...'
       if (cros->wifi_scanning()) {
         label = l10n_util::GetStringUTF16(IDS_STATUSBAR_WIFI_SCANNING_MESSAGE);
-        menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+        menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
             SkBitmap(), std::string(), FLAG_DISABLED));
       }
 
@@ -665,7 +684,7 @@
                               IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
       label = l10n_util::GetStringFUTF16(id,
           l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
-      menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+      menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
           SkBitmap(), std::string(), FLAG_TOGGLE_WIFI));
     }
 
@@ -674,7 +693,7 @@
                                   IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
       label = l10n_util::GetStringFUTF16(id,
           l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR));
-      menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+      menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
           SkBitmap(), std::string(), FLAG_TOGGLE_CELLULAR));
     }
   }
@@ -682,7 +701,7 @@
   // Offline mode.
   // TODO(chocobo): Uncomment once we figure out how to do offline mode.
   // menu_items_.push_back(MenuItem(cros->offline_mode() ?
-  //     menus::MenuModel::TYPE_CHECK : menus::MenuModel::TYPE_COMMAND,
+  //     ui::MenuModel::TYPE_CHECK : ui::MenuModel::TYPE_COMMAND,
   //     l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_OFFLINE_MODE),
   //     SkBitmap(), std::string(), FLAG_TOGGLE_OFFLINE));
 
@@ -695,7 +714,7 @@
     if (!MenuUI::IsEnabled() && connected) {
       std::string ip_address = cros->IPAddress();
       if (!ip_address.empty()) {
-        menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND,
+        menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND,
             ASCIIToUTF16(cros->IPAddress()), SkBitmap(), std::string(),
                          FLAG_DISABLED));
       }
@@ -704,7 +723,7 @@
     label = l10n_util::GetStringUTF16(IsBrowserMode() ?
         IDS_STATUSBAR_NETWORK_OPEN_OPTIONS_DIALOG :
         IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG);
-    menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
+    menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
                                    SkBitmap(), std::string(), FLAG_OPTIONS));
   }
 }
diff --git a/chrome/browser/chromeos/status/network_menu.h b/chrome/browser/chromeos/status/network_menu.h
index 4e72ad2..d4f9315 100644
--- a/chrome/browser/chromeos/status/network_menu.h
+++ b/chrome/browser/chromeos/status/network_menu.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,11 +9,11 @@
 #include <string>
 #include <vector>
 
-#include "app/menus/menu_model.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
-#include "gfx/native_widget_types.h"
-#include "views/controls/menu/view_menu_delegate.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/native_widget_types.h"
+#include "views/controls/menu/view_menu_delegate.h"
 
 namespace gfx {
 class Canvas;
@@ -49,7 +49,7 @@
 // <icon> will show the strength of the wifi/cellular networks.
 // The label will be BOLD if the network is currently connected.
 class NetworkMenu : public views::ViewMenuDelegate,
-                    public menus::MenuModel {
+                    public ui::MenuModel {
  public:
   struct NetworkInfo {
     NetworkInfo() :
@@ -75,7 +75,7 @@
   NetworkMenu();
   virtual ~NetworkMenu();
 
-  // Retrieves network info for the DOMUI NetworkMenu (NetworkMenuUI).
+  // Retrieves network info for the WebUI NetworkMenu (NetworkMenuUI).
   // |index| is the index in menu_items_, set when the menu is built.
   bool GetNetworkAt(int index, NetworkInfo* info) const;
 
@@ -87,24 +87,24 @@
                           const std::string& ssid,
                           int remember) const;
 
-  // menus::MenuModel implementation.
+  // ui::MenuModel implementation.
   virtual bool HasIcons() const  { return true; }
   virtual int GetItemCount() const;
-  virtual menus::MenuModel::ItemType GetTypeAt(int index) const;
+  virtual ui::MenuModel::ItemType GetTypeAt(int index) const;
   virtual int GetCommandIdAt(int index) const { return index; }
   virtual string16 GetLabelAt(int index) const;
   virtual bool IsItemDynamicAt(int index) const { return true; }
   virtual const gfx::Font* GetLabelFontAt(int index) const;
   virtual bool GetAcceleratorAt(int index,
-      menus::Accelerator* accelerator) const { return false; }
+      ui::Accelerator* accelerator) const { return false; }
   virtual bool IsItemCheckedAt(int index) const;
   virtual int GetGroupIdAt(int index) const { return 0; }
   virtual bool GetIconAt(int index, SkBitmap* icon) const;
-  virtual menus::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
+  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
     return NULL;
   }
   virtual bool IsEnabledAt(int index) const;
-  virtual menus::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
+  virtual ui::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
   virtual void HighlightChangedTo(int index) {}
   virtual void ActivatedAt(int index);
   virtual void MenuWillShow() {}
@@ -164,9 +164,9 @@
 
   struct MenuItem {
     MenuItem()
-        : type(menus::MenuModel::TYPE_SEPARATOR),
+        : type(ui::MenuModel::TYPE_SEPARATOR),
           flags(0) {}
-    MenuItem(menus::MenuModel::ItemType type, string16 label, SkBitmap icon,
+    MenuItem(ui::MenuModel::ItemType type, string16 label, SkBitmap icon,
              const std::string& wireless_path, int flags)
         : type(type),
           label(label),
@@ -174,7 +174,7 @@
           wireless_path(wireless_path),
           flags(flags) {}
 
-    menus::MenuModel::ItemType type;
+    ui::MenuModel::ItemType type;
     string16 label;
     SkBitmap icon;
     std::string wireless_path;
@@ -188,7 +188,7 @@
   // Called by RunMenu to initialize our list of menu items.
   void InitMenuItems();
 
-  // Shows network details in DOM UI options window.
+  // Shows network details in Web UI options window.
   void ShowTabbedNetworkSettings(const Network* network) const;
 
   // Show a NetworkConfigView modal dialog instance.
diff --git a/chrome/browser/chromeos/status/network_menu_button.cc b/chrome/browser/chromeos/status/network_menu_button.cc
index 7e7bdd0..385ee99 100644
--- a/chrome/browser/chromeos/status/network_menu_button.cc
+++ b/chrome/browser/chromeos/status/network_menu_button.cc
@@ -7,16 +7,16 @@
 #include <algorithm>
 #include <limits>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/chromeos/status/status_area_host.h"
-#include "gfx/canvas_skia.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/window/window.h"
 
 namespace chromeos {
@@ -96,7 +96,7 @@
 // NetworkMenuButton, NetworkMenu implementation:
 
 bool NetworkMenuButton::IsBrowserMode() const {
-  return host_->IsBrowserMode();
+  return host_->GetScreenMode() == StatusAreaHost::kBrowserMode;
 }
 
 gfx::NativeWindow NetworkMenuButton::GetNativeWindow() const {
diff --git a/chrome/browser/chromeos/status/power_menu_button.cc b/chrome/browser/chromeos/status/power_menu_button.cc
index e6adcdc..6692276 100644
--- a/chrome/browser/chromeos/status/power_menu_button.cc
+++ b/chrome/browser/chromeos/status/power_menu_button.cc
@@ -4,15 +4,15 @@
 
 #include "chrome/browser/chromeos/status/power_menu_button.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_number_conversions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 
 namespace chromeos {
 
@@ -39,14 +39,14 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// PowerMenuButton, menus::MenuModel implementation:
+// PowerMenuButton, ui::MenuModel implementation:
 
 int PowerMenuButton::GetItemCount() const {
   return 2;
 }
 
-menus::MenuModel::ItemType PowerMenuButton::GetTypeAt(int index) const {
-  return menus::MenuModel::TYPE_COMMAND;
+ui::MenuModel::ItemType PowerMenuButton::GetTypeAt(int index) const {
+  return ui::MenuModel::TYPE_COMMAND;
 }
 
 string16 PowerMenuButton::GetLabelAt(int index) const {
@@ -96,7 +96,6 @@
 
 void PowerMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
   power_menu_.Rebuild();
-  power_menu_.UpdateStates();
   power_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
 }
 
@@ -186,6 +185,7 @@
 
   SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id_));
   SetTooltipText(UTF16ToWide(GetLabelAt(0)));
+  power_menu_.Rebuild();
   SchedulePaint();
 }
 
diff --git a/chrome/browser/chromeos/status/power_menu_button.h b/chrome/browser/chromeos/status/power_menu_button.h
index d3146ac..79bd1d5 100644
--- a/chrome/browser/chromeos/status/power_menu_button.h
+++ b/chrome/browser/chromeos/status/power_menu_button.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_CHROMEOS_STATUS_POWER_MENU_BUTTON_H_
 #pragma once
 
-#include "app/menus/menu_model.h"
 #include "chrome/browser/chromeos/cros/power_library.h"
 #include "chrome/browser/chromeos/status/status_area_button.h"
+#include "ui/base/models/menu_model.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/controls/menu/view_menu_delegate.h"
 
@@ -24,29 +24,29 @@
 // This class will handle getting the power status and populating the menu.
 class PowerMenuButton : public StatusAreaButton,
                         public views::ViewMenuDelegate,
-                        public menus::MenuModel,
+                        public ui::MenuModel,
                         public PowerLibrary::Observer {
  public:
   PowerMenuButton();
   virtual ~PowerMenuButton();
 
-  // menus::MenuModel implementation.
+  // ui::MenuModel implementation.
   virtual bool HasIcons() const  { return false; }
   virtual int GetItemCount() const;
-  virtual menus::MenuModel::ItemType GetTypeAt(int index) const;
+  virtual ui::MenuModel::ItemType GetTypeAt(int index) const;
   virtual int GetCommandIdAt(int index) const { return index; }
   virtual string16 GetLabelAt(int index) const;
   virtual bool IsItemDynamicAt(int index) const { return true; }
   virtual bool GetAcceleratorAt(int index,
-      menus::Accelerator* accelerator) const { return false; }
+      ui::Accelerator* accelerator) const { return false; }
   virtual bool IsItemCheckedAt(int index) const { return false; }
   virtual int GetGroupIdAt(int index) const { return 0; }
   virtual bool GetIconAt(int index, SkBitmap* icon) const { return false; }
-  virtual menus::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
+  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
     return NULL;
   }
   virtual bool IsEnabledAt(int index) const { return false; }
-  virtual menus::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
+  virtual ui::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
   virtual void HighlightChangedTo(int index) {}
   virtual void ActivatedAt(int index) {}
   virtual void MenuWillShow() {}
diff --git a/chrome/browser/chromeos/status/status_area_button.cc b/chrome/browser/chromeos/status/status_area_button.cc
index a75808b..ca40163 100644
--- a/chrome/browser/chromeos/status/status_area_button.cc
+++ b/chrome/browser/chromeos/status/status_area_button.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/chromeos/status/status_area_button.h"
 
-#include "gfx/canvas.h"
-#include "gfx/skbitmap_operations.h"
 #include "grit/theme_resources.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/skbitmap_operations.h"
 #include "views/border.h"
 #include "views/view.h"
 
@@ -20,7 +20,7 @@
 
 StatusAreaButton::StatusAreaButton(views::ViewMenuDelegate* menu_delegate)
     : MenuButton(NULL, std::wstring(), menu_delegate, false),
-      use_menu_button_paint_(false), enabled_(true) {
+      use_menu_button_paint_(false), active_(true) {
   set_border(NULL);
 
   // Use an offset that is top aligned with toolbar.
@@ -88,7 +88,7 @@
 }
 
 bool StatusAreaButton::Activate() {
-  if (enabled_) {
+  if (active_) {
     return views::MenuButton::Activate();
   } else {
     return true;
diff --git a/chrome/browser/chromeos/status/status_area_button.h b/chrome/browser/chromeos/status/status_area_button.h
index fda3af8..db9716f 100644
--- a/chrome/browser/chromeos/status/status_area_button.h
+++ b/chrome/browser/chromeos/status/status_area_button.h
@@ -29,12 +29,15 @@
     use_menu_button_paint_ = use_menu_button_paint;
   }
 
-  void Enable(bool enable) { enabled_ = enable; }
-
   // views::MenuButton overrides.
   virtual bool Activate();
 
+  // Controls whether or not this status area button is able to be pressed.
+  void set_active(bool active) { active_ = active; }
+  bool active() const { return active_; }
+
  protected:
+
   // Draws the icon for this status area button on the canvas.
   // Subclasses should override this method if they need to draw their own icon.
   // Otherwise, just call SetIcon() and the it will be handled for you.
@@ -54,7 +57,10 @@
   // Insets to use for this button.
   gfx::Insets insets_;
 
-  bool enabled_;
+  // Indicates when this button can be pressed.  Independent of
+  // IsEnabled state, so that when IsEnabled is true, this can still
+  // be false, and vice versa.
+  bool active_;
 
   DISALLOW_COPY_AND_ASSIGN(StatusAreaButton);
 };
diff --git a/chrome/browser/chromeos/status/status_area_host.h b/chrome/browser/chromeos/status/status_area_host.h
index 7b7691e..b00ffed 100644
--- a/chrome/browser/chromeos/status/status_area_host.h
+++ b/chrome/browser/chromeos/status/status_area_host.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_HOST_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace views {
 class View;
@@ -38,11 +38,15 @@
   // Executes browser command.
   virtual void ExecuteBrowserCommand(int id) const = 0;
 
-  // True if status area hosted in browser. Otherwise it's OOBE/login state.
-  virtual bool IsBrowserMode() const = 0;
+  // The type of screen the host window is on.
+  enum ScreenMode {
+    kLoginMode,  // The host is for the OOBE/login screens.
+    kBrowserMode,  // The host is for browser.
+    kScreenLockerMode,  // The host is for screen locker.
+  };
 
-  // True if status area hosted in screen locker.
-  virtual bool IsScreenLockerMode() const = 0;
+  // Returns the type of screen.
+  virtual ScreenMode GetScreenMode() const = 0;
 
  protected:
   virtual ~StatusAreaHost() {}
diff --git a/chrome/browser/chromeos/status/status_area_view.cc b/chrome/browser/chromeos/status/status_area_view.cc
index 86bd3c4..81dd39e 100644
--- a/chrome/browser/chromeos/status/status_area_view.cc
+++ b/chrome/browser/chromeos/status/status_area_view.cc
@@ -11,7 +11,8 @@
 #include "chrome/browser/chromeos/status/network_menu_button.h"
 #include "chrome/browser/chromeos/status/power_menu_button.h"
 #include "chrome/browser/chromeos/status/status_area_host.h"
-#include "gfx/canvas.h"
+#include "chrome/browser/chromeos/status/window_switcher_button.h"
+#include "ui/gfx/canvas.h"
 
 namespace chromeos {
 
@@ -23,7 +24,8 @@
       clock_view_(NULL),
       input_method_view_(NULL),
       network_view_(NULL),
-      power_view_(NULL) {
+      power_view_(NULL),
+      window_switcher_view_(NULL) {
 }
 
 void StatusAreaView::Init() {
@@ -42,12 +44,16 @@
   // Power.
   power_view_ = new PowerMenuButton();
   AddChildView(power_view_);
+
+  // Window Switcher.
+  window_switcher_view_ = new WindowSwitcherButton(host_);
+  AddChildView(window_switcher_view_);
 }
 
 gfx::Size StatusAreaView::GetPreferredSize() {
   int result_w = kSeparation;
   int result_h = 0;
-  for (int i = 0; i < GetChildViewCount(); i++) {
+  for (int i = 0; i < child_count(); i++) {
     views::View* cur = GetChildViewAt(i);
     if (cur->IsVisible()) {
       gfx::Size cur_size = cur->GetPreferredSize();
@@ -62,7 +68,7 @@
 
 void StatusAreaView::Layout() {
   int cur_x = kSeparation;
-  for (int i = 0; i < GetChildViewCount(); i++) {
+  for (int i = 0; i < child_count(); i++) {
     views::View* cur = GetChildViewAt(i);
     if (cur->IsVisible()) {
       gfx::Size cur_size = cur->GetPreferredSize();
@@ -88,11 +94,11 @@
   PreferredSizeChanged();
 }
 
-void StatusAreaView::EnableButtons(bool enable) {
-  clock_view()->Enable(enable);
-  input_method_view()->Enable(enable);
-  network_view()->Enable(enable);
-  power_view()->Enable(enable);
+void StatusAreaView::MakeButtonsActive(bool active) {
+  clock_view()->set_active(active);
+  input_method_view()->set_active(active);
+  network_view()->set_active(active);
+  power_view()->set_active(active);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/status/status_area_view.h b/chrome/browser/chromeos/status/status_area_view.h
index bf852e9..1b858f7 100644
--- a/chrome/browser/chromeos/status/status_area_view.h
+++ b/chrome/browser/chromeos/status/status_area_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "chrome/browser/views/accessible_pane_view.h"
+#include "chrome/browser/ui/views/accessible_pane_view.h"
 #include "views/view.h"
 
 namespace chromeos {
@@ -17,6 +17,7 @@
 class NetworkMenuButton;
 class PowerMenuButton;
 class StatusAreaHost;
+class WindowSwitcherButton;
 
 // This class is used to wrap the small informative widgets in the upper-right
 // of the window title bar. It is used on ChromeOS only.
@@ -26,7 +27,7 @@
   virtual ~StatusAreaView() {}
 
   virtual void Init();
-  void EnableButtons(bool enable);
+  void MakeButtonsActive(bool active);
 
   // views::View* overrides.
   virtual gfx::Size GetPreferredSize();
@@ -37,6 +38,9 @@
   InputMethodMenuButton* input_method_view() { return input_method_view_; }
   NetworkMenuButton* network_view() { return network_view_; }
   PowerMenuButton* power_view() { return power_view_; }
+  WindowSwitcherButton* window_switcher_view() {
+    return window_switcher_view_;
+  }
 
  private:
   StatusAreaHost* host_;
@@ -45,6 +49,7 @@
   InputMethodMenuButton* input_method_view_;
   NetworkMenuButton* network_view_;
   PowerMenuButton* power_view_;
+  WindowSwitcherButton* window_switcher_view_;
 
   DISALLOW_COPY_AND_ASSIGN(StatusAreaView);
 };
diff --git a/chrome/browser/chromeos/status/window_switcher_button.cc b/chrome/browser/chromeos/status/window_switcher_button.cc
new file mode 100644
index 0000000..3b42461
--- /dev/null
+++ b/chrome/browser/chromeos/status/window_switcher_button.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/status/window_switcher_button.h"
+
+#include "chrome/browser/chromeos/status/status_area_host.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+
+namespace chromeos {
+
+WindowSwitcherButton::WindowSwitcherButton(StatusAreaHost* host)
+    : StatusAreaButton(this),
+      host_(host) {
+  UpdateStatus();
+  BrowserList::AddObserver(this);
+}
+
+WindowSwitcherButton::~WindowSwitcherButton() {
+  BrowserList::RemoveObserver(this);
+}
+
+void WindowSwitcherButton::UpdateStatus() {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  // If there's more than one window, we enable ourselves.
+  if (BrowserList::size() > 1) {
+    SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_WINDOW_SWITCHER));
+    SetEnabled(true);
+  } else {
+    SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_WINDOW_SWITCHER_DISABLED));
+    SetEnabled(false);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowSwitcherButton, views::ViewMenuDelegate implementation:
+
+void WindowSwitcherButton::RunMenu(views::View* source, const gfx::Point& pt) {
+  if (BrowserList::empty())
+    return;
+  Browser* last_active = BrowserList::GetLastActive();
+  if (last_active) {
+    BrowserList::const_iterator iter;
+    for (iter = BrowserList::begin(); iter != BrowserList::end(); ++iter) {
+      if (last_active == *iter) {
+        ++iter;
+        break;
+      }
+    }
+    if (iter == BrowserList::end())
+      iter = BrowserList::begin();
+    (*iter)->window()->Activate();
+  } else {
+    (*BrowserList::begin())->window()->Activate();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BrowserList::Observer implementation:
+
+// Called immediately after a browser is added to the list
+void WindowSwitcherButton::OnBrowserAdded(const Browser* browser) {
+  UpdateStatus();
+}
+
+// Called immediately after a browser is removed from the list
+void WindowSwitcherButton::OnBrowserRemoved(const Browser* browser) {
+  UpdateStatus();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/status/window_switcher_button.h b/chrome/browser/chromeos/status/window_switcher_button.h
new file mode 100644
index 0000000..40a092d
--- /dev/null
+++ b/chrome/browser/chromeos/status/window_switcher_button.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_STATUS_WINDOW_SWITCHER_BUTTON_H_
+#define CHROME_BROWSER_CHROMEOS_STATUS_WINDOW_SWITCHER_BUTTON_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/chromeos/status/status_area_button.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/notification_observer.h"
+#include "views/controls/button/menu_button.h"
+#include "views/controls/menu/view_menu_delegate.h"
+
+namespace chromeos {
+
+class StatusAreaHost;
+
+// The window switcher button in the status area.  This button allows
+// the user to move to the next window if they click on the icon.
+class WindowSwitcherButton : public StatusAreaButton,
+                             public views::ViewMenuDelegate,
+                             public BrowserList::Observer {
+ public:
+  explicit WindowSwitcherButton(StatusAreaHost* host);
+  virtual ~WindowSwitcherButton();
+
+ private:
+  // Updates the status of the button based on the state of the
+  // browser list.
+  void UpdateStatus();
+
+  // BrowserList::Observer API
+  virtual void OnBrowserAdded(const Browser* browser);
+  virtual void OnBrowserRemoved(const Browser* browser);
+
+  // views::ViewMenuDelegate implementation.
+  virtual void RunMenu(views::View* source, const gfx::Point& pt);
+
+  StatusAreaHost* host_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowSwitcherButton);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_STATUS_WINDOW_SWITCHER_BUTTON_H_
diff --git a/chrome/browser/chromeos/system_key_event_listener.cc b/chrome/browser/chromeos/system_key_event_listener.cc
index 8e5bd41..fa056bd 100644
--- a/chrome/browser/chromeos/system_key_event_listener.cc
+++ b/chrome/browser/chromeos/system_key_event_listener.cc
@@ -27,7 +27,8 @@
 }
 
 SystemKeyEventListener::SystemKeyEventListener()
-    : audio_handler_(AudioHandler::GetInstance()) {
+    : stopped_(false),
+      audio_handler_(AudioHandler::GetInstance()) {
   WmMessageListener::GetInstance()->AddObserver(this);
 
   key_volume_mute_ = XKeysymToKeycode(GDK_DISPLAY(), XF86XK_AudioMute);
@@ -50,10 +51,19 @@
 }
 
 SystemKeyEventListener::~SystemKeyEventListener() {
+  Stop();
+}
+
+void SystemKeyEventListener::Stop() {
+  if (stopped_)
+    return;
   WmMessageListener::GetInstance()->RemoveObserver(this);
   gdk_window_remove_filter(NULL, GdkEventFilter, this);
+  audio_handler_->Disconnect();
+  stopped_ = true;
 }
 
+
 void SystemKeyEventListener::ProcessWmMessage(const WmIpc::Message& message,
                                               GdkWindow* window) {
   if (message.type() != WM_IPC_MESSAGE_CHROME_NOTIFY_SYSKEY_PRESSED)
diff --git a/chrome/browser/chromeos/system_key_event_listener.h b/chrome/browser/chromeos/system_key_event_listener.h
index eb841f9..ef62ca8 100644
--- a/chrome/browser/chromeos/system_key_event_listener.h
+++ b/chrome/browser/chromeos/system_key_event_listener.h
@@ -30,6 +30,8 @@
   virtual void ProcessWmMessage(const WmIpc::Message& message,
                                 GdkWindow* window);
 
+  void Stop();
+
  private:
   // Defines the delete on exit Singleton traits we like.  Best to have this
   // and const/dest private as recommended for Singletons.
@@ -60,6 +62,8 @@
   int32 key_f9_;
   int32 key_f10_;
 
+  bool stopped_;
+
   // AudioHandler is a Singleton class we are just caching a pointer to here,
   // and we do not own the pointer.
   AudioHandler* const audio_handler_;
diff --git a/chrome/browser/chromeos/update_observer.cc b/chrome/browser/chromeos/update_observer.cc
index 60bd1e8..33b13a1 100644
--- a/chrome/browser/chromeos/update_observer.cc
+++ b/chrome/browser/chromeos/update_observer.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/browser/chromeos/update_observer.h"
 
-#include "app/l10n_util.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/time_format.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/user_cros_settings_provider.cc b/chrome/browser/chromeos/user_cros_settings_provider.cc
index 4ee00f1..b055baa 100644
--- a/chrome/browser/chromeos/user_cros_settings_provider.cc
+++ b/chrome/browser/chromeos/user_cros_settings_provider.cc
@@ -120,6 +120,9 @@
 }
 
 bool GetUserWhitelist(ListValue* user_list) {
+  PrefService* prefs = g_browser_process->local_state();
+  DCHECK(!prefs->IsManagedPreference(kAccountsPrefUsers));
+
   std::vector<std::string> whitelist;
   if (!CrosLibrary::Get()->EnsureLoaded() ||
       !CrosLibrary::Get()->GetLoginLibrary()->EnumerateWhitelisted(
@@ -128,7 +131,6 @@
     return false;
   }
 
-  PrefService* prefs = g_browser_process->local_state();
   ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers);
   cached_whitelist->Clear();
 
@@ -150,7 +152,6 @@
   }
 
   prefs->ScheduleSavePersistentPrefs();
-
   return true;
 }
 
@@ -162,9 +163,12 @@
   }
 
   // Working horse for UserCrosSettingsProvider::RequestTrusted* family.
-  bool RequestTrustedEntity(const std::string& name, Task* callback) {
+  bool RequestTrustedEntity(const std::string& name) {
     if (GetOwnershipStatus() == OWNERSHIP_NONE)
       return true;
+    PrefService* prefs = g_browser_process->local_state();
+    if (prefs->IsManagedPreference(name.c_str()))
+      return true;
     if (GetOwnershipStatus() == OWNERSHIP_TAKEN) {
       DCHECK(g_browser_process);
       PrefService* prefs = g_browser_process->local_state();
@@ -172,12 +176,24 @@
       if (prefs->GetBoolean((name + kTrustedSuffix).c_str()))
         return true;
     }
-    if (callback)
-      callbacks_[name].push_back(callback);
     return false;
   }
 
+  bool RequestTrustedEntity(const std::string& name, Task* callback) {
+    if (RequestTrustedEntity(name)) {
+      delete callback;
+      return true;
+    } else {
+      if (callback)
+        callbacks_[name].push_back(callback);
+      return false;
+    }
+  }
+
   void Set(const std::string& path, Value* in_value) {
+    PrefService* prefs = g_browser_process->local_state();
+    DCHECK(!prefs->IsManagedPreference(path.c_str()));
+
     if (!UserManager::Get()->current_user_is_owner()) {
       LOG(WARNING) << "Changing settings from non-owner, setting=" << path;
 
@@ -492,14 +508,17 @@
 const ListValue* UserCrosSettingsProvider::cached_whitelist() {
   PrefService* prefs = g_browser_process->local_state();
   const ListValue* cached_users = prefs->GetList(kAccountsPrefUsers);
-
-  if (!cached_users) {
-    // Update whitelist cache.
-    GetUserWhitelist(NULL);
-
-    cached_users = prefs->GetList(kAccountsPrefUsers);
+  if (!prefs->IsManagedPreference(kAccountsPrefUsers)) {
+    if (cached_users == NULL) {
+      // Update whitelist cache.
+      GetUserWhitelist(NULL);
+      cached_users = prefs->GetList(kAccountsPrefUsers);
+    }
   }
-
+  if (cached_users == NULL) {
+    NOTREACHED();
+    cached_users = new ListValue;
+  }
   return cached_users;
 }
 
diff --git a/chrome/browser/chromeos/view_ids.h b/chrome/browser/chromeos/view_ids.h
index e32e94e..090490e 100644
--- a/chrome/browser/chromeos/view_ids.h
+++ b/chrome/browser/chromeos/view_ids.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,8 +11,10 @@
 // View ID used in ChromeOS.
 enum ChromeOSViewIds {
   // Start with the offset that is big enough to avoid possible
-  // collison.
+  // collision.
   VIEW_ID_STATUS_AREA = VIEW_ID_PREDEFINED_COUNT + 10000,
+  VIEW_ID_SCREEN_LOCKER_SIGNOUT_LINK,
+  VIEW_ID_SCREEN_LOCKER_SHUTDOWN,
 };
 
 #endif  // CHROME_BROWSER_CHROMEOS_VIEW_IDS_H_
diff --git a/chrome/browser/chromeos/views/copy_background.cc b/chrome/browser/chromeos/views/copy_background.cc
index 617fdc4..64e329f 100644
--- a/chrome/browser/chromeos/views/copy_background.cc
+++ b/chrome/browser/chromeos/views/copy_background.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/chromeos/views/copy_background.h"
 
 #include "base/logging.h"
-#include "gfx/canvas.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/view.h"
 
diff --git a/chrome/browser/chromeos/views/domui_menu_widget.cc b/chrome/browser/chromeos/views/domui_menu_widget.cc
deleted file mode 100644
index 8a5e360..0000000
--- a/chrome/browser/chromeos/views/domui_menu_widget.cc
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/views/domui_menu_widget.h"
-
-#include <algorithm>
-
-#include "base/stringprintf.h"
-#include "base/singleton.h"
-#include "base/task.h"
-#include "chrome/browser/chromeos/views/menu_locator.h"
-#include "chrome/browser/chromeos/views/native_menu_domui.h"
-#include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/dom_view.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/canvas_skia.h"
-#include "googleurl/src/gurl.h"
-#include "third_party/cros/chromeos_wm_ipc_enums.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
-#include "views/border.h"
-#include "views/layout_manager.h"
-#include "views/widget/root_view.h"
-
-namespace {
-
-// Colors for menu's graident background.
-const SkColor kMenuStartColor = SK_ColorWHITE;
-const SkColor kMenuEndColor = 0xFFEEEEEE;
-
-// Rounded border for menu. This draws three types of rounded border,
-// for context menu, dropdown menu and submenu. Please see
-// menu_locator.cc for details.
-class RoundedBorder : public views::Border {
- public:
-  explicit RoundedBorder(chromeos::MenuLocator* locator)
-      : menu_locator_(locator) {
-  }
-
- private:
-  // views::Border implementatios.
-  virtual void Paint(const views::View& view, gfx::Canvas* canvas) const {
-    const SkScalar* corners = menu_locator_->GetCorners();
-    // The menu is in off screen so no need to draw corners.
-    if (!corners)
-      return;
-    int w = view.width();
-    int h = view.height();
-    SkRect rect = {0, 0, w, h};
-    SkPath path;
-    path.addRoundRect(rect, corners);
-    SkPaint paint;
-    paint.setStyle(SkPaint::kFill_Style);
-    paint.setFlags(SkPaint::kAntiAlias_Flag);
-    SkPoint p[2] = { {0, 0}, {0, h} };
-    SkColor colors[2] = {kMenuStartColor, kMenuEndColor};
-    SkShader* s = SkGradientShader::CreateLinear(
-        p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
-    paint.setShader(s);
-    // Need to unref shader, otherwise never deleted.
-    s->unref();
-    canvas->AsCanvasSkia()->drawPath(path, paint);
-  }
-
-  virtual void GetInsets(gfx::Insets* insets) const {
-    DCHECK(insets);
-    menu_locator_->GetInsets(insets);
-  }
-
-  chromeos::MenuLocator* menu_locator_;  // not owned
-
-  DISALLOW_COPY_AND_ASSIGN(RoundedBorder);
-};
-
-class InsetsLayout : public views::LayoutManager {
- public:
-  InsetsLayout() : views::LayoutManager() {}
-
- private:
-  // views::LayoutManager implementatios.
-  virtual void Layout(views::View* host) {
-    if (host->GetChildViewCount() == 0)
-      return;
-    gfx::Insets insets = host->GetInsets();
-    views::View* view = host->GetChildViewAt(0);
-
-    view->SetBounds(insets.left(), insets.top(),
-                    host->width() - insets.width(),
-                    host->height() - insets.height());
-  }
-
-  virtual gfx::Size GetPreferredSize(views::View* host) {
-    DCHECK(host->GetChildViewCount() == 1);
-    gfx::Insets insets = host->GetInsets();
-    gfx::Size size = host->GetChildViewAt(0)->GetPreferredSize();
-    return gfx::Size(size.width() + insets.width(),
-                     size.height() + insets.height());
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(InsetsLayout);
-};
-
-// A gtk widget key used to test if a given WidgetGtk instance is
-// DOMUIMenuWidgetKey.
-const char* kDOMUIMenuWidgetKey = "__DOMUI_MENU_WIDGET__";
-
-}  // namespace
-
-namespace chromeos {
-
-// static
-DOMUIMenuWidget* DOMUIMenuWidget::FindDOMUIMenuWidget(gfx::NativeView native) {
-  DCHECK(native);
-  native = gtk_widget_get_toplevel(native);
-  if (!native)
-    return NULL;
-  return static_cast<chromeos::DOMUIMenuWidget*>(
-      g_object_get_data(G_OBJECT(native), kDOMUIMenuWidgetKey));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DOMUIMenuWidget public:
-
-DOMUIMenuWidget::DOMUIMenuWidget(chromeos::NativeMenuDOMUI* domui_menu,
-                                 bool root)
-    : views::WidgetGtk(views::WidgetGtk::TYPE_POPUP),
-      domui_menu_(domui_menu),
-      dom_view_(NULL),
-      did_input_grab_(false),
-      is_root_(root) {
-  DCHECK(domui_menu_);
-  // TODO(oshima): Disabling transparent until we migrate bookmark
-  // menus to DOMUI.  See crosbug.com/7718.
-  // MakeTransparent();
-}
-
-DOMUIMenuWidget::~DOMUIMenuWidget() {
-}
-
-void DOMUIMenuWidget::Init(gfx::NativeView parent, const gfx::Rect& bounds) {
-  WidgetGtk::Init(parent, bounds);
-  gtk_window_set_destroy_with_parent(GTK_WINDOW(GetNativeView()), TRUE);
-  gtk_window_set_type_hint(GTK_WINDOW(GetNativeView()),
-                           GDK_WINDOW_TYPE_HINT_MENU);
-  g_object_set_data(G_OBJECT(GetNativeView()), kDOMUIMenuWidgetKey, this);
-}
-
-void DOMUIMenuWidget::Hide() {
-  ReleaseGrab();
-  WidgetGtk::Hide();
-  // Clears the content.
-  ExecuteJavascript(L"updateModel({'items':[]})");
-}
-
-void DOMUIMenuWidget::Close() {
-  if (dom_view_ != NULL) {
-    dom_view_->GetParent()->RemoveChildView(dom_view_);
-    delete dom_view_;
-    dom_view_ = NULL;
-  }
-
-  // Detach the domui_menu_ which is being deleted.
-  domui_menu_ = NULL;
-  views::WidgetGtk::Close();
-}
-
-void DOMUIMenuWidget::ReleaseGrab() {
-  WidgetGtk::ReleaseGrab();
-  if (did_input_grab_) {
-    did_input_grab_ = false;
-    gdk_pointer_ungrab(GDK_CURRENT_TIME);
-    gdk_keyboard_ungrab(GDK_CURRENT_TIME);
-
-    ClearGrabWidget();
-  }
-}
-
-gboolean DOMUIMenuWidget::OnGrabBrokeEvent(GtkWidget* widget,
-                                           GdkEvent* event) {
-  did_input_grab_ = false;
-  Hide();
-  return WidgetGtk::OnGrabBrokeEvent(widget, event);
-}
-
-void DOMUIMenuWidget::OnSizeAllocate(GtkWidget* widget,
-                                     GtkAllocation* allocation) {
-  views::WidgetGtk::OnSizeAllocate(widget, allocation);
-  // Adjust location when menu gets resized.
-  gfx::Rect bounds;
-  GetBounds(&bounds, false);
-  // Don't move until the menu gets contents.
-  if (bounds.height() > 1) {
-    menu_locator_->Move(this);
-    domui_menu_->InputIsReady();
-  }
-}
-
-gboolean MapToFocus(GtkWidget* widget, GdkEvent* event, gpointer data) {
-  DOMUIMenuWidget* menu_widget = DOMUIMenuWidget::FindDOMUIMenuWidget(widget);
-  if (menu_widget) {
-    // See EnableInput for the meaning of data.
-    bool select_item = data != NULL;
-    menu_widget->EnableInput(select_item);
-  }
-  return true;
-}
-
-void DOMUIMenuWidget::EnableScroll(bool enable) {
-  ExecuteJavascript(StringPrintf(
-      L"enableScroll(%ls)", enable ? L"true" : L"false"));
-}
-
-void DOMUIMenuWidget::EnableInput(bool select_item) {
-  if (!dom_view_)
-    return;
-  DCHECK(dom_view_->tab_contents()->render_view_host());
-  DCHECK(dom_view_->tab_contents()->render_view_host()->view());
-  GtkWidget* target =
-      dom_view_->tab_contents()->render_view_host()->view()->GetNativeView();
-  DCHECK(target);
-  // Skip if the widget already own the input.
-  if (gtk_grab_get_current() == target)
-    return;
-
-  ClearGrabWidget();
-
-  if (!GTK_WIDGET_REALIZED(target)) {
-    // Wait grabbing widget if the widget is not yet realized.
-    // Using data as a flag. |select_item| is false if data is NULL,
-    // or true otherwise.
-    g_signal_connect(G_OBJECT(target), "map-event",
-                     G_CALLBACK(&MapToFocus),
-                     select_item ? this : NULL);
-    return;
-  }
-
-  gtk_grab_add(target);
-  dom_view_->tab_contents()->Focus();
-  if (select_item) {
-    ExecuteJavascript(L"selectItem()");
-  }
-}
-
-void DOMUIMenuWidget::ExecuteJavascript(const std::wstring& script) {
-  // Don't exeute there is no DOMView associated. This is fine because
-  // 1) selectItem make sense only when DOMView is associated.
-  // 2) updateModel will be called again when a DOMView is created/assigned.
-  if (!dom_view_)
-    return;
-
-  DCHECK(dom_view_->tab_contents()->render_view_host());
-  dom_view_->tab_contents()->render_view_host()->
-      ExecuteJavascriptInWebFrame(std::wstring(), script);
-}
-
-void DOMUIMenuWidget::ShowAt(chromeos::MenuLocator* locator) {
-  DCHECK(domui_menu_);
-  menu_locator_.reset(locator);
-  if (!dom_view_) {
-    // TODO(oshima): Replace DOMView with direct use of RVH for beta.
-    // DOMView should be refactored to use RVH directly, but
-    // it'll require a lot of change and will take time.
-    dom_view_ = new DOMView();
-    dom_view_->Init(domui_menu_->GetProfile(), NULL);
-    // TODO(oshima): remove extra view to draw rounded corner.
-    views::View* container = new views::View();
-    container->AddChildView(dom_view_);
-    container->set_border(new RoundedBorder(locator));
-    container->SetLayoutManager(new InsetsLayout());
-    SetContentsView(container);
-    dom_view_->LoadURL(domui_menu_->menu_url());
-  } else {
-    domui_menu_->UpdateStates();
-    dom_view_->GetParent()->set_border(new RoundedBorder(locator));
-    menu_locator_->Move(this);
-  }
-  Show();
-
-  // The pointer grab is captured only on the top level menu,
-  // all mouse event events are delivered to submenu using gtk_add_grab.
-  if (is_root_) {
-    CaptureGrab();
-  }
-}
-
-void DOMUIMenuWidget::SetSize(const gfx::Size& new_size) {
-  DCHECK(domui_menu_);
-  // Ignore the empty new_size request which is called when
-  // menu.html is loaded.
-  if (new_size.IsEmpty())
-    return;
-  int width, height;
-  gtk_widget_get_size_request(GetNativeView(), &width, &height);
-  gfx::Size real_size(std::max(new_size.width(), width),
-                      new_size.height());
-  // Ignore the size request with the same size.
-  gfx::Rect bounds;
-  GetBounds(&bounds, false);
-  if (bounds.size() == real_size)
-    return;
-  menu_locator_->SetBounds(this, real_size);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DOMUIMenuWidget private:
-
-void DOMUIMenuWidget::CaptureGrab() {
-  // Release the current grab.
-  ClearGrabWidget();
-
-  // NOTE: we do this to ensure we get mouse/keyboard events from
-  // other apps, a grab done with gtk_grab_add doesn't get events from
-  // other apps.
-  GdkGrabStatus pointer_grab_status =
-      gdk_pointer_grab(window_contents()->window, FALSE,
-                       static_cast<GdkEventMask>(
-                           GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-                           GDK_POINTER_MOTION_MASK),
-                       NULL, NULL, GDK_CURRENT_TIME);
-  GdkGrabStatus keyboard_grab_status =
-      gdk_keyboard_grab(window_contents()->window, FALSE,
-                        GDK_CURRENT_TIME);
-
-  did_input_grab_ = pointer_grab_status == GDK_GRAB_SUCCESS &&
-      keyboard_grab_status == GDK_GRAB_SUCCESS;
-  DCHECK(did_input_grab_);
-
-  EnableInput(false /* no selection */);
-}
-
-void DOMUIMenuWidget::ClearGrabWidget() {
-  GtkWidget* grab_widget;
-  while ((grab_widget = gtk_grab_get_current()))
-    gtk_grab_remove(grab_widget);
-}
-
-}   // namespace chromeos
diff --git a/chrome/browser/chromeos/views/domui_menu_widget.h b/chrome/browser/chromeos/views/domui_menu_widget.h
deleted file mode 100644
index 095d4c4..0000000
--- a/chrome/browser/chromeos/views/domui_menu_widget.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_VIEWS_DOMUI_MENU_WIDGET_H_
-#define CHROME_BROWSER_CHROMEOS_VIEWS_DOMUI_MENU_WIDGET_H_
-#pragma once
-
-#include <string>
-
-#include "views/widget/widget_gtk.h"
-
-class DOMView;
-class ExtensionApiTest;
-
-namespace chromeos {
-
-class MenuLocator;
-class NativeMenuDOMUI;
-
-// DOMUIMenuWidget is a window widget for DOMUI based menu.
-class DOMUIMenuWidget : public views::WidgetGtk {
- public:
-  // Create a Window for the NativeMenuDMOUI. |root| specifies if
-  // the menu is root menu.
-  DOMUIMenuWidget(NativeMenuDOMUI* domui_menu, bool root);
-  virtual ~DOMUIMenuWidget();
-
-  // WidgetGtk overrides:
-  virtual void Init(gfx::NativeView parent, const gfx::Rect& bounds);
-  virtual void Hide();
-  virtual void Close();
-  virtual void ReleaseGrab();
-  virtual gboolean OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event);
-  virtual void OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation);
-
-  // Returns NativeMenuDOMUI that owns this widget.
-  NativeMenuDOMUI* domui_menu() const {
-    return domui_menu_;
-  }
-
-  // Returns true if the menu widget is a root.
-  bool is_root() const {
-    return is_root_;
-  }
-
-  // Returns true if the menu widget has input grab.
-  bool did_input_grab() const {
-    return did_input_grab_;
-  }
-
-  // Enables/Disables menu scroll.
-  void EnableScroll(bool enabled);
-
-  // Tell the gtk to send all input events (mouse, keyboard) to this
-  // Widget. If |selectItem| is true, it highlights the selected item
-  // (or select 1st selectable item if none is selected).
-  void EnableInput(bool select_item);
-
-  // Executes given |javascript|.
-  void ExecuteJavascript(const std::wstring& javascript);
-
-  // Show the menu using |locator|.  Ownership of locator is transferred
-  // to this widget.
-  void ShowAt(MenuLocator* locator);
-
-  // Updates the size
-  void SetSize(const gfx::Size& new_size);
-
-  // Returns the menu locator owned by this widget.
-  const MenuLocator* menu_locator() const {
-    return menu_locator_.get();
-  }
-
-  // Returns DOMUIMenuWidget that contains given native. This returns
-  // NULL if not found.
-  static DOMUIMenuWidget* FindDOMUIMenuWidget(gfx::NativeView native);
-
- private:
-  // Capture the X pointer grab. This also enables input on the widget by
-  // calling EnableInput(false).
-  void CaptureGrab();
-
-  // Clears GTK grab.
-  void ClearGrabWidget();
-
-  // NativeMenu object that owns this widget.
-  NativeMenuDOMUI* domui_menu_;
-
-  // DOMView to render the menu contents.
-  DOMView* dom_view_;
-
-  // MenuLocator that controls the position of this menu widget.
-  scoped_ptr<chromeos::MenuLocator> menu_locator_;
-
-  // True if the widget has input grab.
-  bool did_input_grab_;
-
-  // True if the widget is for root menu (very first menu in
-  // submenu chain).
-  bool is_root_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMUIMenuWidget);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_VIEWS_DOMUI_MENU_WIDGET_H_
diff --git a/chrome/browser/chromeos/views/dropdown_button.cc b/chrome/browser/chromeos/views/dropdown_button.cc
index 58e9d36..d6c7916 100644
--- a/chrome/browser/chromeos/views/dropdown_button.cc
+++ b/chrome/browser/chromeos/views/dropdown_button.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/chromeos/views/dropdown_button.h"
-#include "gfx/canvas_skia.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 
 namespace {
 // Asset icon particularities makes us offset focus frame.
diff --git a/chrome/browser/chromeos/views/menu_locator.cc b/chrome/browser/chromeos/views/menu_locator.cc
index 779ce76..fc3fcab 100644
--- a/chrome/browser/chromeos/views/menu_locator.cc
+++ b/chrome/browser/chromeos/views/menu_locator.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,16 +6,16 @@
 
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
-#include "chrome/browser/chromeos/views/domui_menu_widget.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/insets.h"
+#include "chrome/browser/chromeos/views/webui_menu_widget.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 #include "views/screen.h"
 #include "views/widget/widget.h"
 
 namespace {
 
-using chromeos::DOMUIMenuWidget;
+using chromeos::WebUIMenuWidget;
 
 // Menu's corner radious.
 const int kMenuCornerRadius = 0;  // crosbug.com/7718.
@@ -33,8 +33,8 @@
 }
 
 // Returns adjusted height of the menu that fits to the screen's
-// hight, and enables scrolling if necessary.
-int AdjustHeight(DOMUIMenuWidget* widget,
+// height, and enables scrolling if necessary.
+int AdjustHeight(WebUIMenuWidget* widget,
                  int screen_height,
                  int height) {
   // TODO(oshima): Locator needs a preferred size so that
@@ -52,7 +52,7 @@
 }
 
 // Updates the root menu's bounds to fit to the screen.
-void UpdateRootMenuBounds(DOMUIMenuWidget* widget,
+void UpdateRootMenuBounds(WebUIMenuWidget* widget,
                           const gfx::Point& origin,
                           const gfx::Size& size,
                           bool align_right) {
@@ -81,7 +81,7 @@
     return DEFAULT;
   }
 
-  virtual void Move(DOMUIMenuWidget* widget) {
+  virtual void Move(WebUIMenuWidget* widget) {
     // TODO(oshima):
     // Dropdown Menu has to be shown above the button, which is not currently
     // possible with Menu2. I'll update Menu2 and this code
@@ -91,7 +91,7 @@
     UpdateRootMenuBounds(widget, origin_, bounds.size(), !base::i18n::IsRTL());
   }
 
-  virtual void SetBounds(DOMUIMenuWidget* widget, const gfx::Size& size) {
+  virtual void SetBounds(WebUIMenuWidget* widget, const gfx::Size& size) {
     gfx::Size new_size(size);
     new_size.Enlarge(0, kMenuCornerRadius);
     UpdateRootMenuBounds(widget, origin_, size, !base::i18n::IsRTL());
@@ -128,13 +128,13 @@
     return DEFAULT;
   }
 
-  virtual void Move(DOMUIMenuWidget* widget) {
+  virtual void Move(WebUIMenuWidget* widget) {
     gfx::Rect bounds;
     widget->GetBounds(&bounds, false);
     UpdateRootMenuBounds(widget, origin_, bounds.size(), base::i18n::IsRTL());
   }
 
-  virtual void SetBounds(DOMUIMenuWidget* widget, const gfx::Size& size) {
+  virtual void SetBounds(WebUIMenuWidget* widget, const gfx::Size& size) {
     gfx::Size new_size(size);
     new_size.Enlarge(0, kMenuCornerRadius * 2);
     UpdateRootMenuBounds(widget, origin_, new_size, base::i18n::IsRTL());
@@ -162,7 +162,7 @@
 // MenuLocator for submenu.
 class SubMenuLocator : public chromeos::MenuLocator {
  public:
-  SubMenuLocator(const DOMUIMenuWidget* parent,
+  SubMenuLocator(const WebUIMenuWidget* parent,
                  MenuLocator::SubmenuDirection parent_direction,
                  int y)
       : parent_rect_(GetBoundsOf(parent)),
@@ -177,13 +177,13 @@
     return direction_;
   }
 
-  virtual void Move(DOMUIMenuWidget* widget) {
+  virtual void Move(WebUIMenuWidget* widget) {
     gfx::Rect bounds;
     widget->GetBounds(&bounds, false);
     UpdateBounds(widget, bounds.size());
   }
 
-  virtual void SetBounds(DOMUIMenuWidget* widget, const gfx::Size& size) {
+  virtual void SetBounds(WebUIMenuWidget* widget, const gfx::Size& size) {
     gfx::Size new_size(size);
     new_size.Enlarge(0, kMenuCornerRadius * 2);
     UpdateBounds(widget, new_size);
@@ -201,7 +201,7 @@
   static const SkScalar kRightCorners[];
   static const SkScalar kLeftCorners[];
 
-  void UpdateBounds(DOMUIMenuWidget* widget, const gfx::Size& size) {
+  void UpdateBounds(WebUIMenuWidget* widget, const gfx::Size& size) {
     gfx::Rect screen_rect = GetScreenRectAt(parent_rect_.x(), root_y_);
     int width = std::min(screen_rect.width(), size.width());
     int height = AdjustHeight(widget, size.height(), screen_rect.height());
@@ -309,7 +309,7 @@
 }
 
 MenuLocator* MenuLocator::CreateSubMenuLocator(
-    const DOMUIMenuWidget* parent,
+    const WebUIMenuWidget* parent,
     MenuLocator::SubmenuDirection parent_direction,
     int y) {
   return new SubMenuLocator(parent, parent_direction, y);
diff --git a/chrome/browser/chromeos/views/menu_locator.h b/chrome/browser/chromeos/views/menu_locator.h
index 80371f5..cb2744d 100644
--- a/chrome/browser/chromeos/views/menu_locator.h
+++ b/chrome/browser/chromeos/views/menu_locator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
 
 namespace chromeos {
 
-class DOMUIMenuWidget;
+class WebUIMenuWidget;
 
 // MenuLocator class contorls where the menu will be placed and
 // which corners are rounded.
@@ -35,10 +35,10 @@
   virtual SubmenuDirection GetSubmenuDirection() const = 0;
 
   // Move the widget to the right position.
-  virtual void Move(DOMUIMenuWidget* widget) = 0;
+  virtual void Move(WebUIMenuWidget* widget) = 0;
 
   // Resize and move the widget to the right position.
-  virtual void SetBounds(DOMUIMenuWidget* widget,
+  virtual void SetBounds(WebUIMenuWidget* widget,
                          const gfx::Size& size) = 0;
 
   // Returns the 8 length array of SkScalar that represents 4 corner
@@ -67,7 +67,7 @@
   // direction given by |parent_direction|. 3 corners are
   // rounded except for the corner that is attached to the widget.
   static MenuLocator* CreateSubMenuLocator(
-      const DOMUIMenuWidget* widget,
+      const WebUIMenuWidget* widget,
       MenuLocator::SubmenuDirection parent_direction,
       int y);
 };
diff --git a/chrome/browser/chromeos/views/native_menu_domui.cc b/chrome/browser/chromeos/views/native_menu_domui.cc
deleted file mode 100644
index 5ffb24f..0000000
--- a/chrome/browser/chromeos/views/native_menu_domui.cc
+++ /dev/null
@@ -1,423 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/views/native_menu_domui.h"
-
-#include <string>
-
-#include "app/menus/menu_model.h"
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "chrome/browser/chromeos/dom_ui/menu_ui.h"
-#include "chrome/browser/chromeos/views/domui_menu_widget.h"
-#include "chrome/browser/chromeos/views/menu_locator.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/rect.h"
-#include "views/controls/menu/menu_2.h"
-#include "views/controls/menu/nested_dispatcher_gtk.h"
-
-#if defined(TOUCH_UI)
-#include "views/focus/accelerator_handler.h"
-#include "views/controls/menu/native_menu_x.h"
-#else
-#include "views/controls/menu/native_menu_gtk.h"
-#endif
-
-namespace {
-
-using chromeos::NativeMenuDOMUI;
-using chromeos::DOMUIMenuWidget;
-
-// Returns true if the menu item type specified can be executed as a command.
-bool MenuTypeCanExecute(menus::MenuModel::ItemType type) {
-  return type == menus::MenuModel::TYPE_COMMAND ||
-      type == menus::MenuModel::TYPE_CHECK ||
-      type == menus::MenuModel::TYPE_RADIO;
-}
-
-gboolean Destroy(GtkWidget* widget, gpointer data) {
-  DOMUIMenuWidget* menu_widget = static_cast<DOMUIMenuWidget*>(data);
-  NativeMenuDOMUI* domui_menu = menu_widget->domui_menu();
-  // domui_menu can be NULL if widget is destroyed by signal.
-  if (domui_menu)
-    domui_menu->Hide();
-  return true;
-}
-
-// Returns the active toplevel window.
-gfx::NativeWindow FindActiveToplevelWindow() {
-  GList* toplevels = gtk_window_list_toplevels();
-  while (toplevels) {
-    gfx::NativeWindow window = static_cast<gfx::NativeWindow>(toplevels->data);
-    if (gtk_window_is_active(window)) {
-      return window;
-    }
-    toplevels = g_list_next(toplevels);
-  }
-  return NULL;
-}
-
-// Currently opened menu. See RunMenuAt for reason why we need this.
-NativeMenuDOMUI* current_ = NULL;
-
-}  // namespace
-
-namespace chromeos {
-
-// static
-void NativeMenuDOMUI::SetMenuURL(views::Menu2* menu2, const GURL& url) {
-  // No-op if DOMUI menu is disabled.
-  if (!MenuUI::IsEnabled())
-    return;
-
-  gfx::NativeView native = menu2->GetNativeMenu();
-  DCHECK(native);
-  DOMUIMenuWidget* widget = DOMUIMenuWidget::FindDOMUIMenuWidget(native);
-  DCHECK(widget);
-  widget->domui_menu()->set_menu_url(url);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeMenuDOMUI, public:
-
-NativeMenuDOMUI::NativeMenuDOMUI(menus::MenuModel* menu_model, bool root)
-    : parent_(NULL),
-      submenu_(NULL),
-      model_(menu_model),
-      menu_widget_(NULL),
-      menu_shown_(false),
-      activated_menu_(NULL),
-      activated_index_(-1),
-      menu_action_(MENU_ACTION_NONE),
-      menu_url_(StringPrintf("chrome://%s", chrome::kChromeUIMenu)),
-      on_menu_opened_called_(false),
-      nested_dispatcher_(NULL) {
-  menu_widget_ = new DOMUIMenuWidget(this, root);
-  // Set the initial location off the screen not to show small
-  // window with dropshadow.
-  menu_widget_->Init(NULL, gfx::Rect(-10000, -10000, 1, 1));
-}
-
-NativeMenuDOMUI::~NativeMenuDOMUI() {
-  if (nested_dispatcher_) {
-    // Menu is destroyed while its in message loop.
-    // Let nested dispatcher know the creator is deleted.
-    nested_dispatcher_->CreatorDestroyed();
-    Hide();
-  }
-  if (menu_widget_) {
-    menu_widget_->Close();
-    menu_widget_ = NULL;
-  }
-  parent_ = NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeMenuDOMUI, MenuWrapper implementation:
-
-void NativeMenuDOMUI::RunMenuAt(const gfx::Point& point, int alignment) {
-  if (current_ != NULL) {
-    // This happens when there is a nested task to show menu, which is
-    // executed after menu is open. Since we need to enable nested task,
-    // this condition has to be handled here.
-    return;
-  }
-  current_ = this;
-  bool context = false;
-
-  // TODO(oshima): This is quick hack to check if it's context menu. (in rtl)
-  // Fix this once we migrated.
-  if (alignment == views::Menu2::ALIGN_TOPLEFT) {
-    context = true;
-  }
-
-  activated_menu_ = NULL;
-  activated_index_ = -1;
-  menu_action_ = MENU_ACTION_NONE;
-
-  MenuLocator* locator = context ?
-      MenuLocator::CreateContextMenuLocator(point) :
-      MenuLocator::CreateDropDownMenuLocator(point);
-  ShowAt(locator);
-  DCHECK(!menu_shown_);
-  menu_shown_ = true;
-  on_menu_opened_called_ = false;
-
-  // TODO(oshima): A menu must be deleted when parent window is
-  // closed. Menu2 doesn't know about the parent window, however, so
-  // we're using toplevel gtkwindow. This is probably sufficient, but
-  // I will update Menu2 to pass host view (which is necessary anyway
-  // to get the right position) and get a parent widnow through
-  // it. http://crosbug/7642
-  gfx::NativeWindow parent = FindActiveToplevelWindow();
-  gulong handle = 0;
-  if (parent) {
-    handle = g_signal_connect(G_OBJECT(parent), "destroy",
-                              G_CALLBACK(&Destroy),
-                              menu_widget_);
-  }
-  // We need to turn on nestable tasks as a renderer uses tasks internally.
-  // Without this, renderer cannnot finish loading page.
-  nested_dispatcher_ =
-      new views::NestedDispatcherGtk(this, true /* allow nested */);
-  bool deleted = nested_dispatcher_->RunAndSelfDestruct();
-  current_ = NULL;  // this is static and safe to access.
-  if (deleted) {
-    // The menu was destryed while menu is shown, so return immediately.
-    // Don't touch the instance which is already deleted.
-    return;
-  }
-  nested_dispatcher_ = NULL;
-  if (menu_shown_) {
-    // If this happens it means we haven't yet gotten the hide signal and
-    // someone else quit the message loop on us.
-    NOTREACHED();
-    menu_shown_ = false;
-  }
-  if (handle)
-    g_signal_handler_disconnect(G_OBJECT(parent), handle);
-
-  menu_widget_->Hide();
-  // Close All submenus.
-  submenu_.reset();
-  ProcessActivate();
-}
-
-void NativeMenuDOMUI::CancelMenu() {
-  Hide();
-}
-
-void NativeMenuDOMUI::Rebuild() {
-  activated_menu_ = NULL;
-  menu_widget_->ExecuteJavascript(L"modelUpdated()");
-}
-
-void NativeMenuDOMUI::UpdateStates() {
-  // Update menu contnets and submenus.
-  Rebuild();
-}
-
-gfx::NativeMenu NativeMenuDOMUI::GetNativeMenu() const {
-  return menu_widget_->GetNativeView();
-}
-
-NativeMenuDOMUI::MenuAction NativeMenuDOMUI::GetMenuAction() const {
-  return menu_action_;
-}
-
-void NativeMenuDOMUI::AddMenuListener(views::MenuListener* listener) {
-  listeners_.AddObserver(listener);
-}
-
-void NativeMenuDOMUI::RemoveMenuListener(views::MenuListener* listener) {
-  listeners_.RemoveObserver(listener);
-}
-
-void NativeMenuDOMUI::SetMinimumWidth(int width) {
-  gtk_widget_set_size_request(menu_widget_->GetNativeView(), width, 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeMenuDOMUI, MessageLoopForUI::Dispatcher implementation:
-
-bool NativeMenuDOMUI::Dispatch(GdkEvent* event) {
-  switch (event->type) {
-    case GDK_MOTION_NOTIFY: {
-      NativeMenuDOMUI* target = FindMenuAt(
-          gfx::Point(event->motion.x_root, event->motion.y_root));
-      if (target)
-        target->menu_widget_->EnableInput(false);
-      break;
-    }
-    case GDK_BUTTON_PRESS: {
-      NativeMenuDOMUI* target = FindMenuAt(
-          gfx::Point(event->motion.x_root, event->motion.y_root));
-      if (!target) {
-        Hide();
-        return true;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-  gtk_main_do_event(event);
-  return true;
-}
-
-#if defined(TOUCH_UI)
-base::MessagePumpGlibXDispatcher::DispatchStatus NativeMenuDOMUI::Dispatch(
-    XEvent* xevent) {
-  return views::DispatchXEvent(xevent) ?
-      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
-      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
-
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeMenuDOMUI, MenuControl implementation:
-
-void NativeMenuDOMUI::Activate(menus::MenuModel* model,
-                               int index,
-                               ActivationMode activation) {
-  NativeMenuDOMUI* root = GetRoot();
-  if (root) {
-    if (activation == CLOSE_AND_ACTIVATE) {
-      root->activated_menu_ = model;
-      root->activated_index_ = index;
-      root->menu_action_ = MENU_ACTION_SELECTED;
-      root->Hide();
-    } else {
-      if (model->IsEnabledAt(index) &&
-          MenuTypeCanExecute(model->GetTypeAt(index))) {
-        model->ActivatedAt(index);
-      }
-    }
-  }
-}
-
-void NativeMenuDOMUI::OpenSubmenu(int index, int y) {
-  submenu_.reset();
-  // Returns the model for the submenu at the specified index.
-  menus::MenuModel* submenu = model_->GetSubmenuModelAt(index);
-  submenu_.reset(new chromeos::NativeMenuDOMUI(submenu, false));
-  submenu_->set_menu_url(menu_url_);
-  // y in menu_widget_ coordinate.
-  submenu_->set_parent(this);
-  submenu_->ShowAt(
-      MenuLocator::CreateSubMenuLocator(
-          menu_widget_,
-          menu_widget_->menu_locator()->GetSubmenuDirection(),
-          y));
-}
-
-void NativeMenuDOMUI::CloseAll() {
-  NativeMenuDOMUI* root = GetRoot();
-  // root can be null if the submenu is detached from parent.
-  if (root)
-    root->Hide();
-}
-
-void NativeMenuDOMUI::CloseSubmenu() {
-  submenu_.reset();  // This closes subsequent children.
-}
-
-void NativeMenuDOMUI::MoveInputToSubmenu() {
-  if (submenu_.get()) {
-    submenu_->menu_widget_->EnableInput(true);
-  }
-}
-
-void NativeMenuDOMUI::MoveInputToParent() {
-  if (parent_) {
-    parent_->menu_widget_->EnableInput(true);
-  }
-}
-
-void NativeMenuDOMUI::OnLoad() {
-  // TODO(oshima): OnLoad is no longer used, but kept in case
-  // we may need it. Delete this if this is not necessary to
-  // implement wrench/network/bookmark menus.
-}
-
-void NativeMenuDOMUI::SetSize(const gfx::Size& size) {
-  menu_widget_->SetSize(size);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeMenuDOMUI, public:
-
-void NativeMenuDOMUI::Hide() {
-  // Only root can hide and exit the message loop.
-  DCHECK(menu_widget_->is_root());
-  DCHECK(!parent_);
-  if (!menu_shown_) {
-    // The menu has been already hidden by us and we're in the process of
-    // quiting the message loop..
-    return;
-  }
-  CloseSubmenu();
-  menu_shown_ = false;
-  MessageLoop::current()->Quit();
-}
-
-NativeMenuDOMUI* NativeMenuDOMUI::GetRoot() {
-  NativeMenuDOMUI* ancestor = this;
-  while (ancestor->parent_)
-    ancestor = ancestor->parent_;
-  if (ancestor->menu_widget_->is_root())
-    return ancestor;
-  else
-    return NULL;
-}
-
-Profile* NativeMenuDOMUI::GetProfile() {
-  Browser* browser = BrowserList::GetLastActive();
-    // browser can be null in login screen.
-  if (!browser)
-    return ProfileManager::GetDefaultProfile();
-  return browser->GetProfile();
-}
-
-void NativeMenuDOMUI::InputIsReady() {
-  if (!on_menu_opened_called_) {
-    on_menu_opened_called_ = true;
-    FOR_EACH_OBSERVER(views::MenuListener, listeners_, OnMenuOpened());
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeMenuDOMUI, private:
-
-void NativeMenuDOMUI::ProcessActivate() {
-  if (activated_menu_ &&
-      activated_menu_->IsEnabledAt(activated_index_) &&
-      MenuTypeCanExecute(activated_menu_->GetTypeAt(activated_index_))) {
-    activated_menu_->ActivatedAt(activated_index_);
-  }
-}
-
-void NativeMenuDOMUI::ShowAt(MenuLocator* locator) {
-  model_->MenuWillShow();
-  menu_widget_->ShowAt(locator);
-}
-
-NativeMenuDOMUI* NativeMenuDOMUI::FindMenuAt(const gfx::Point& point) {
-  if (submenu_.get()) {
-    NativeMenuDOMUI* found = submenu_->FindMenuAt(point);
-    if (found)
-      return found;
-  }
-  gfx::Rect bounds;
-  menu_widget_->GetBounds(&bounds, false);
-  return bounds.Contains(point) ? this : NULL;
-}
-
-}  // namespace chromeos
-
-////////////////////////////////////////////////////////////////////////////////
-// MenuWrapper, public:
-
-namespace views {
-
-// static
-MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) {
-  menus::MenuModel* model = menu->model();
-  if (chromeos::MenuUI::IsEnabled()) {
-    return new chromeos::NativeMenuDOMUI(model, true);
-  } else {
-#if defined(TOUCH_UI)
-    return new NativeMenuX(menu);
-#else
-    return new NativeMenuGtk(menu);
-#endif
-  }
-}
-
-}  // namespace views
diff --git a/chrome/browser/chromeos/views/native_menu_domui.h b/chrome/browser/chromeos/views/native_menu_domui.h
deleted file mode 100644
index 53ef488..0000000
--- a/chrome/browser/chromeos/views/native_menu_domui.h
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_VIEWS_NATIVE_MENU_DOMUI_H_
-#define CHROME_BROWSER_CHROMEOS_VIEWS_NATIVE_MENU_DOMUI_H_
-#pragma once
-
-#include <vector>
-
-#include "base/message_loop.h"
-#include "base/observer_list.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/chromeos/dom_ui/domui_menu_control.h"
-#include "googleurl/src/gurl.h"
-#include "views/controls/menu/menu_wrapper.h"
-
-class SkBitmap;
-class DictionaryValue;
-class Profile;
-
-namespace menus {
-class MenuModel;
-}  // namespace menus
-
-namespace views {
-class NestedDispatcherGtk;
-}  // namespace views;
-
-#if defined(TOUCH_UI)
-typedef union _XEvent XEvent;
-#endif
-
-namespace chromeos {
-
-class MenuLocator;
-class DOMUIMenuWidget;
-
-// A DOMUI implementation of MenuWrapper.
-class NativeMenuDOMUI : public views::MenuWrapper,
-                        public DOMUIMenuControl,
-                        public MessageLoop::Dispatcher {
- public:
-  NativeMenuDOMUI(menus::MenuModel* menu_model, bool root);
-  virtual ~NativeMenuDOMUI();
-
-  // Returns true if menu is currently shown.
-  bool is_menu_shown() { return menu_shown_; }
-
-  // Set parent menu.
-  void set_parent(NativeMenuDOMUI* parent) { parent_ = parent; }
-
-  // Overridden from MenuWrapper:
-  virtual void RunMenuAt(const gfx::Point& point, int alignment);
-  virtual void CancelMenu();
-  virtual void Rebuild();
-  virtual void UpdateStates();
-  virtual gfx::NativeMenu GetNativeMenu() const;
-  virtual MenuAction GetMenuAction() const;
-  virtual void AddMenuListener(views::MenuListener* listener);
-  virtual void RemoveMenuListener(views::MenuListener* listener);
-  virtual void SetMinimumWidth(int width);
-
-  // Overriden from MessageLoopForUI::Dispatcher:
-  virtual bool Dispatch(GdkEvent* event);
-#if defined(TOUCH_UI)
-  virtual base::MessagePumpGlibXDispatcher::DispatchStatus Dispatch(
-      XEvent* xevent);
-#endif
-
-  // Overriden from DOMUIMenuControl;
-  virtual menus::MenuModel* GetMenuModel() { return model_; }
-  virtual void Activate(menus::MenuModel* model,
-                        int index,
-                        ActivationMode activation_mode);
-  virtual void CloseAll();
-  virtual void CloseSubmenu();
-  virtual void MoveInputToParent();
-  virtual void MoveInputToSubmenu();
-  virtual void OnLoad();
-  virtual void OpenSubmenu(int index, int y);
-  virtual void SetSize(const gfx::Size& size);
-
-  // Hide All menu (including submenus).
-  void Hide();
-
-  // Returns the root of the menu tree. Returns NULL if it cannot find
-  // a root. (i.e. detached from root)
-  NativeMenuDOMUI* GetRoot();
-
-  // Returns the profile to create DOMView.
-  Profile* GetProfile();
-
-  // Called when the menu is ready to accept input.
-  // Used in interactive_ui_test to wait for menu opened.
-  void InputIsReady();
-
-  // Sets/Gets the url for the domui menu.
-  void set_menu_url(const GURL& url) { menu_url_ = url; }
-  const GURL& menu_url() const { return menu_url_; }
-
-  // Sets the menu url of menu2. This has to be called before
-  // RunMenuAt/RunContextMenuAt is called.
-  static void SetMenuURL(views::Menu2* menu2, const GURL& url);
-
- private:
-  // Callback that we should really process the menu activation.
-  // See description above class for why we delay processing activation.
-  void ProcessActivate();
-
-  // Show the menu using given |locator|.
-  void ShowAt(MenuLocator* locator);
-
-  // Find a menu object at point.
-  NativeMenuDOMUI* FindMenuAt(const gfx::Point& point);
-
-  // If we're a submenu, this is the parent.
-  NativeMenuDOMUI* parent_;
-
-  // Holds the current submenu.
-  scoped_ptr<NativeMenuDOMUI> submenu_;
-
-  menus::MenuModel* model_;
-
-  // A window widget that draws the content of the menu.
-  DOMUIMenuWidget* menu_widget_;
-
-  // True if the menu is currently shown.
-  // Used only in root.
-  bool menu_shown_;
-
-  // If the user selects something from the menu this is the menu they selected
-  // it from. When an item is selected menu_activated_ on the root ancestor is
-  // set to the menu the user selected and after the nested message loop exits
-  // Activate is invoked on this menu.
-  menus::MenuModel* activated_menu_;
-
-  // The index of the item the user selected. This is set on the
-  // actual menu the user selects and not the root.
-  int activated_index_;
-
-  // The action that took place during the call to RunMenuAt.
-  MenuAction menu_action_;
-
-  // Vector of listeners to receive callbacks when the menu opens.
-  ObserverList<views::MenuListener> listeners_;
-
-  // URL to invoke Menu DOMUI. Default menu is chrome://menu, but
-  // custom menu can use different url using SetMenuURL method
-  // (e.g. chrome://wrench-menu for wrench menu).
-  GURL menu_url_;
-
-  // A guard flag to avoid calling MenuListener::OnMenuOpened twice.
-  bool on_menu_opened_called_;
-
-  // Nested dispatcher object that can outlive this object.
-  // This is to deal with the menu being deleted while the nested
-  // message loop is handled. see http://crosbug.com/7929 .
-  views::NestedDispatcherGtk* nested_dispatcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeMenuDOMUI);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_VIEWS_NATIVE_MENU_DOMUI_H_
diff --git a/chrome/browser/chromeos/views/native_menu_webui.cc b/chrome/browser/chromeos/views/native_menu_webui.cc
new file mode 100644
index 0000000..0cf2a82
--- /dev/null
+++ b/chrome/browser/chromeos/views/native_menu_webui.cc
@@ -0,0 +1,402 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/views/native_menu_webui.h"
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/browser/chromeos/dom_ui/menu_ui.h"
+#include "chrome/browser/chromeos/views/menu_locator.h"
+#include "chrome/browser/chromeos/views/webui_menu_widget.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/url_constants.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/rect.h"
+#include "views/controls/menu/menu_2.h"
+#include "views/controls/menu/nested_dispatcher_gtk.h"
+
+#if defined(TOUCH_UI)
+#include "views/focus/accelerator_handler.h"
+#include "views/controls/menu/native_menu_x.h"
+#else
+#include "views/controls/menu/native_menu_gtk.h"
+#endif
+
+namespace {
+
+using chromeos::NativeMenuWebUI;
+using chromeos::WebUIMenuWidget;
+
+// Returns true if the menu item type specified can be executed as a command.
+bool MenuTypeCanExecute(ui::MenuModel::ItemType type) {
+  return type == ui::MenuModel::TYPE_COMMAND ||
+      type == ui::MenuModel::TYPE_CHECK ||
+      type == ui::MenuModel::TYPE_RADIO;
+}
+
+gboolean Destroy(GtkWidget* widget, gpointer data) {
+  WebUIMenuWidget* menu_widget = static_cast<WebUIMenuWidget*>(data);
+  NativeMenuWebUI* webui_menu = menu_widget->webui_menu();
+  // webui_menu can be NULL if widget is destroyed by signal.
+  if (webui_menu)
+    webui_menu->Hide();
+  return true;
+}
+
+// Returns the active toplevel window.
+gfx::NativeWindow FindActiveToplevelWindow() {
+  GList* toplevels = gtk_window_list_toplevels();
+  while (toplevels) {
+    gfx::NativeWindow window = static_cast<gfx::NativeWindow>(toplevels->data);
+    if (gtk_window_is_active(window)) {
+      return window;
+    }
+    toplevels = g_list_next(toplevels);
+  }
+  return NULL;
+}
+
+// Currently opened menu. See RunMenuAt for reason why we need this.
+NativeMenuWebUI* current_ = NULL;
+
+}  // namespace
+
+namespace chromeos {
+
+// static
+void NativeMenuWebUI::SetMenuURL(views::Menu2* menu2, const GURL& url) {
+  // No-op if WebUI menu is disabled.
+  if (!MenuUI::IsEnabled())
+    return;
+
+  gfx::NativeView native = menu2->GetNativeMenu();
+  DCHECK(native);
+  WebUIMenuWidget* widget = WebUIMenuWidget::FindWebUIMenuWidget(native);
+  DCHECK(widget);
+  widget->webui_menu()->set_menu_url(url);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeMenuWebUI, public:
+
+NativeMenuWebUI::NativeMenuWebUI(ui::MenuModel* menu_model, bool root)
+    : parent_(NULL),
+      submenu_(NULL),
+      model_(menu_model),
+      menu_widget_(NULL),
+      menu_shown_(false),
+      activated_menu_(NULL),
+      activated_index_(-1),
+      menu_action_(MENU_ACTION_NONE),
+      menu_url_(StringPrintf("chrome://%s", chrome::kChromeUIMenu)),
+      on_menu_opened_called_(false),
+      nested_dispatcher_(NULL) {
+  menu_widget_ = new WebUIMenuWidget(this, root);
+  // Set the initial location off the screen not to show small
+  // window with dropshadow.
+  menu_widget_->Init(NULL, gfx::Rect(-10000, -10000, 1, 1));
+}
+
+NativeMenuWebUI::~NativeMenuWebUI() {
+  if (nested_dispatcher_) {
+    // Menu is destroyed while its in message loop.
+    // Let nested dispatcher know the creator is deleted.
+    nested_dispatcher_->CreatorDestroyed();
+    Hide();
+  }
+  if (menu_widget_) {
+    menu_widget_->Close();
+    menu_widget_ = NULL;
+  }
+  parent_ = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeMenuWebUI, MenuWrapper implementation:
+
+void NativeMenuWebUI::RunMenuAt(const gfx::Point& point, int alignment) {
+  if (current_ != NULL) {
+    // This happens when there is a nested task to show menu, which is
+    // executed after menu is open. Since we need to enable nested task,
+    // this condition has to be handled here.
+    return;
+  }
+  current_ = this;
+  bool context = false;
+
+  // TODO(oshima): This is quick hack to check if it's context menu. (in rtl)
+  // Fix this once we migrated.
+  if (alignment == views::Menu2::ALIGN_TOPLEFT) {
+    context = true;
+  }
+
+  activated_menu_ = NULL;
+  activated_index_ = -1;
+  menu_action_ = MENU_ACTION_NONE;
+
+  MenuLocator* locator = context ?
+      MenuLocator::CreateContextMenuLocator(point) :
+      MenuLocator::CreateDropDownMenuLocator(point);
+  ShowAt(locator);
+  DCHECK(!menu_shown_);
+  menu_shown_ = true;
+  on_menu_opened_called_ = false;
+
+  // TODO(oshima): A menu must be deleted when parent window is
+  // closed. Menu2 doesn't know about the parent window, however, so
+  // we're using toplevel gtkwindow. This is probably sufficient, but
+  // I will update Menu2 to pass host view (which is necessary anyway
+  // to get the right position) and get a parent widnow through
+  // it. http://crosbug/7642
+  gfx::NativeWindow parent = FindActiveToplevelWindow();
+  gulong handle = 0;
+  if (parent) {
+    handle = g_signal_connect(G_OBJECT(parent), "destroy",
+                              G_CALLBACK(&Destroy),
+                              menu_widget_);
+  }
+  // We need to turn on nestable tasks as a renderer uses tasks internally.
+  // Without this, renderer cannnot finish loading page.
+  nested_dispatcher_ =
+      new views::NestedDispatcherGtk(this, true /* allow nested */);
+  bool deleted = nested_dispatcher_->RunAndSelfDestruct();
+  current_ = NULL;  // this is static and safe to access.
+  if (deleted) {
+    // The menu was destryed while menu is shown, so return immediately.
+    // Don't touch the instance which is already deleted.
+    return;
+  }
+  nested_dispatcher_ = NULL;
+  if (menu_shown_) {
+    // If this happens it means we haven't yet gotten the hide signal and
+    // someone else quit the message loop on us.
+    NOTREACHED();
+    menu_shown_ = false;
+  }
+  if (handle)
+    g_signal_handler_disconnect(G_OBJECT(parent), handle);
+
+  menu_widget_->Hide();
+  // Close All submenus.
+  submenu_.reset();
+  ProcessActivate();
+}
+
+void NativeMenuWebUI::CancelMenu() {
+  Hide();
+}
+
+void NativeMenuWebUI::Rebuild() {
+  activated_menu_ = NULL;
+  menu_widget_->ExecuteJavascript(L"modelUpdated()");
+}
+
+void NativeMenuWebUI::UpdateStates() {
+  // Update menu contnets and submenus.
+  Rebuild();
+}
+
+gfx::NativeMenu NativeMenuWebUI::GetNativeMenu() const {
+  return menu_widget_->GetNativeView();
+}
+
+NativeMenuWebUI::MenuAction NativeMenuWebUI::GetMenuAction() const {
+  return menu_action_;
+}
+
+void NativeMenuWebUI::AddMenuListener(views::MenuListener* listener) {
+  listeners_.AddObserver(listener);
+}
+
+void NativeMenuWebUI::RemoveMenuListener(views::MenuListener* listener) {
+  listeners_.RemoveObserver(listener);
+}
+
+void NativeMenuWebUI::SetMinimumWidth(int width) {
+  gtk_widget_set_size_request(menu_widget_->GetNativeView(), width, 1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeMenuWebUI, MessageLoopForUI::Dispatcher implementation:
+
+bool NativeMenuWebUI::Dispatch(GdkEvent* event) {
+  switch (event->type) {
+    case GDK_MOTION_NOTIFY: {
+      NativeMenuWebUI* target = FindMenuAt(
+          gfx::Point(event->motion.x_root, event->motion.y_root));
+      if (target)
+        target->menu_widget_->EnableInput(false);
+      break;
+    }
+    case GDK_BUTTON_PRESS: {
+      NativeMenuWebUI* target = FindMenuAt(
+          gfx::Point(event->motion.x_root, event->motion.y_root));
+      if (!target) {
+        Hide();
+        return true;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+  gtk_main_do_event(event);
+  return true;
+}
+
+#if defined(TOUCH_UI)
+base::MessagePumpGlibXDispatcher::DispatchStatus
+    NativeMenuWebUI::DispatchX(XEvent* xevent) {
+  return views::DispatchXEvent(xevent) ?
+      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
+      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
+
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeMenuWebUI, MenuControl implementation:
+
+void NativeMenuWebUI::Activate(ui::MenuModel* model,
+                               int index,
+                               ActivationMode activation) {
+  NativeMenuWebUI* root = GetRoot();
+  if (root) {
+    if (activation == CLOSE_AND_ACTIVATE) {
+      root->activated_menu_ = model;
+      root->activated_index_ = index;
+      root->menu_action_ = MENU_ACTION_SELECTED;
+      root->Hide();
+    } else {
+      if (model->IsEnabledAt(index) &&
+          MenuTypeCanExecute(model->GetTypeAt(index))) {
+        model->ActivatedAt(index);
+      }
+    }
+  }
+}
+
+void NativeMenuWebUI::OpenSubmenu(int index, int y) {
+  submenu_.reset();
+  // Returns the model for the submenu at the specified index.
+  ui::MenuModel* submenu = model_->GetSubmenuModelAt(index);
+  submenu_.reset(new chromeos::NativeMenuWebUI(submenu, false));
+  submenu_->set_menu_url(menu_url_);
+  // y in menu_widget_ coordinate.
+  submenu_->set_parent(this);
+  submenu_->ShowAt(
+      MenuLocator::CreateSubMenuLocator(
+          menu_widget_,
+          menu_widget_->menu_locator()->GetSubmenuDirection(),
+          y));
+}
+
+void NativeMenuWebUI::CloseAll() {
+  NativeMenuWebUI* root = GetRoot();
+  // root can be null if the submenu is detached from parent.
+  if (root)
+    root->Hide();
+}
+
+void NativeMenuWebUI::CloseSubmenu() {
+  submenu_.reset();  // This closes subsequent children.
+}
+
+void NativeMenuWebUI::MoveInputToSubmenu() {
+  if (submenu_.get()) {
+    submenu_->menu_widget_->EnableInput(true);
+  }
+}
+
+void NativeMenuWebUI::MoveInputToParent() {
+  if (parent_) {
+    parent_->menu_widget_->EnableInput(true);
+  }
+}
+
+void NativeMenuWebUI::OnLoad() {
+  // TODO(oshima): OnLoad is no longer used, but kept in case
+  // we may need it. Delete this if this is not necessary to
+  // implement wrench/network/bookmark menus.
+}
+
+void NativeMenuWebUI::SetSize(const gfx::Size& size) {
+  menu_widget_->SetSize(size);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeMenuWebUI, public:
+
+void NativeMenuWebUI::Hide() {
+  // Only root can hide and exit the message loop.
+  DCHECK(menu_widget_->is_root());
+  DCHECK(!parent_);
+  if (!menu_shown_) {
+    // The menu has been already hidden by us and we're in the process of
+    // quiting the message loop..
+    return;
+  }
+  CloseSubmenu();
+  menu_shown_ = false;
+  MessageLoop::current()->Quit();
+}
+
+NativeMenuWebUI* NativeMenuWebUI::GetRoot() {
+  NativeMenuWebUI* ancestor = this;
+  while (ancestor->parent_)
+    ancestor = ancestor->parent_;
+  if (ancestor->menu_widget_->is_root())
+    return ancestor;
+  else
+    return NULL;
+}
+
+Profile* NativeMenuWebUI::GetProfile() {
+  Browser* browser = BrowserList::GetLastActive();
+    // browser can be null in login screen.
+  if (!browser)
+    return ProfileManager::GetDefaultProfile();
+  return browser->GetProfile();
+}
+
+void NativeMenuWebUI::InputIsReady() {
+  if (!on_menu_opened_called_) {
+    on_menu_opened_called_ = true;
+    FOR_EACH_OBSERVER(views::MenuListener, listeners_, OnMenuOpened());
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeMenuWebUI, private:
+
+void NativeMenuWebUI::ProcessActivate() {
+  if (activated_menu_ &&
+      activated_menu_->IsEnabledAt(activated_index_) &&
+      MenuTypeCanExecute(activated_menu_->GetTypeAt(activated_index_))) {
+    activated_menu_->ActivatedAt(activated_index_);
+  }
+}
+
+void NativeMenuWebUI::ShowAt(MenuLocator* locator) {
+  model_->MenuWillShow();
+  menu_widget_->ShowAt(locator);
+}
+
+NativeMenuWebUI* NativeMenuWebUI::FindMenuAt(const gfx::Point& point) {
+  if (submenu_.get()) {
+    NativeMenuWebUI* found = submenu_->FindMenuAt(point);
+    if (found)
+      return found;
+  }
+  gfx::Rect bounds;
+  menu_widget_->GetBounds(&bounds, false);
+  return bounds.Contains(point) ? this : NULL;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/views/native_menu_webui.h b/chrome/browser/chromeos/views/native_menu_webui.h
new file mode 100644
index 0000000..62c9b00
--- /dev/null
+++ b/chrome/browser/chromeos/views/native_menu_webui.h
@@ -0,0 +1,166 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_VIEWS_NATIVE_MENU_WEBUI_H_
+#define CHROME_BROWSER_CHROMEOS_VIEWS_NATIVE_MENU_WEBUI_H_
+#pragma once
+
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/observer_list.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/chromeos/webui_menu_control.h"
+#include "googleurl/src/gurl.h"
+#include "views/controls/menu/menu_wrapper.h"
+
+class DictionaryValue;
+class Profile;
+class SkBitmap;
+
+namespace ui {
+class MenuModel;
+}  // namespace ui
+
+namespace views {
+class NestedDispatcherGtk;
+}  // namespace views;
+
+#if defined(TOUCH_UI)
+typedef union _XEvent XEvent;
+#endif
+
+namespace chromeos {
+
+class MenuLocator;
+class WebUIMenuWidget;
+
+// A WebUI implementation of MenuWrapper.
+class NativeMenuWebUI : public views::MenuWrapper,
+                        public WebUIMenuControl,
+                        public MessageLoop::Dispatcher {
+ public:
+  NativeMenuWebUI(ui::MenuModel* menu_model, bool root);
+  virtual ~NativeMenuWebUI();
+
+  // Returns true if menu is currently shown.
+  bool is_menu_shown() { return menu_shown_; }
+
+  // Set parent menu.
+  void set_parent(NativeMenuWebUI* parent) { parent_ = parent; }
+
+  // Overridden from views::MenuWrapper:
+  virtual void RunMenuAt(const gfx::Point& point, int alignment);
+  virtual void CancelMenu();
+  virtual void Rebuild();
+  virtual void UpdateStates();
+  virtual gfx::NativeMenu GetNativeMenu() const;
+  virtual MenuAction GetMenuAction() const;
+  virtual void AddMenuListener(views::MenuListener* listener);
+  virtual void RemoveMenuListener(views::MenuListener* listener);
+  virtual void SetMinimumWidth(int width);
+
+  // Overridden from MessageLoopForUI::Dispatcher:
+  virtual bool Dispatch(GdkEvent* event);
+#if defined(TOUCH_UI)
+  virtual base::MessagePumpGlibXDispatcher::DispatchStatus DispatchX(
+      XEvent* xevent);
+#endif
+
+  // Overridden from WebUIMenuControl:
+  virtual ui::MenuModel* GetMenuModel() { return model_; }
+  virtual void Activate(ui::MenuModel* model,
+                        int index,
+                        ActivationMode activation_mode);
+  virtual void CloseAll();
+  virtual void CloseSubmenu();
+  virtual void MoveInputToParent();
+  virtual void MoveInputToSubmenu();
+  virtual void OnLoad();
+  virtual void OpenSubmenu(int index, int y);
+  virtual void SetSize(const gfx::Size& size);
+
+  // Hide All menu (including submenus).
+  void Hide();
+
+  // Returns the root of the menu tree. Returns NULL if it cannot find
+  // a root. (i.e. detached from root)
+  NativeMenuWebUI* GetRoot();
+
+  // Returns the profile to create DOMView.
+  Profile* GetProfile();
+
+  // Called when the menu is ready to accept input.
+  // Used in interactive_ui_test to wait for menu opened.
+  void InputIsReady();
+
+  // Sets/Gets the url for the WebUI menu.
+  void set_menu_url(const GURL& url) { menu_url_ = url; }
+  const GURL& menu_url() const { return menu_url_; }
+
+  // Sets the menu url of menu2. This has to be called before
+  // RunMenuAt/RunContextMenuAt is called.
+  static void SetMenuURL(views::Menu2* menu2, const GURL& url);
+
+ private:
+  // Callback that we should really process the menu activation.
+  // See description above class for why we delay processing activation.
+  void ProcessActivate();
+
+  // Show the menu using given |locator|.
+  void ShowAt(MenuLocator* locator);
+
+  // Find a menu object at point.
+  NativeMenuWebUI* FindMenuAt(const gfx::Point& point);
+
+  // If we're a submenu, this is the parent.
+  NativeMenuWebUI* parent_;
+
+  // Holds the current submenu.
+  scoped_ptr<NativeMenuWebUI> submenu_;
+
+  ui::MenuModel* model_;
+
+  // A window widget that draws the content of the menu.
+  WebUIMenuWidget* menu_widget_;
+
+  // True if the menu is currently shown.
+  // Used only in root.
+  bool menu_shown_;
+
+  // If the user selects something from the menu this is the menu they selected
+  // it from. When an item is selected menu_activated_ on the root ancestor is
+  // set to the menu the user selected and after the nested message loop exits
+  // Activate is invoked on this menu.
+  ui::MenuModel* activated_menu_;
+
+  // The index of the item the user selected. This is set on the
+  // actual menu the user selects and not the root.
+  int activated_index_;
+
+  // The action that took place during the call to RunMenuAt.
+  MenuAction menu_action_;
+
+  // Vector of listeners to receive callbacks when the menu opens.
+  ObserverList<views::MenuListener> listeners_;
+
+  // URL to invoke Menu WebUI. Default menu is chrome://menu, but
+  // custom menu can use different url using SetMenuURL method
+  // (e.g. chrome://wrench-menu for wrench menu).
+  GURL menu_url_;
+
+  // A guard flag to avoid calling MenuListener::OnMenuOpened twice.
+  bool on_menu_opened_called_;
+
+  // Nested dispatcher object that can outlive this object.
+  // This is to deal with the menu being deleted while the nested
+  // message loop is handled. see http://crosbug.com/7929 .
+  views::NestedDispatcherGtk* nested_dispatcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeMenuWebUI);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_VIEWS_NATIVE_MENU_WEBUI_H_
diff --git a/chrome/browser/chromeos/views/webui_menu_widget.cc b/chrome/browser/chromeos/views/webui_menu_widget.cc
new file mode 100644
index 0000000..7ce1ccb
--- /dev/null
+++ b/chrome/browser/chromeos/views/webui_menu_widget.cc
@@ -0,0 +1,341 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/views/webui_menu_widget.h"
+
+#include <algorithm>
+
+#include "base/stringprintf.h"
+#include "base/singleton.h"
+#include "base/task.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/views/menu_locator.h"
+#include "chrome/browser/chromeos/views/native_menu_webui.h"
+#include "chrome/browser/chromeos/wm_ipc.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/views/dom_view.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/gfx/canvas_skia.h"
+#include "views/border.h"
+#include "views/layout/layout_manager.h"
+#include "views/widget/root_view.h"
+
+namespace {
+
+// Colors for the menu's gradient background.
+const SkColor kMenuStartColor = SK_ColorWHITE;
+const SkColor kMenuEndColor = 0xFFEEEEEE;
+
+// Rounded border for menu. This draws three types of rounded border,
+// for context menu, dropdown menu and submenu. Please see
+// menu_locator.cc for details.
+class RoundedBorder : public views::Border {
+ public:
+  explicit RoundedBorder(chromeos::MenuLocator* locator)
+      : menu_locator_(locator) {
+  }
+
+ private:
+  // views::Border implementations.
+  virtual void Paint(const views::View& view, gfx::Canvas* canvas) const {
+    const SkScalar* corners = menu_locator_->GetCorners();
+    // The menu is in off screen so no need to draw corners.
+    if (!corners)
+      return;
+    int w = view.width();
+    int h = view.height();
+    SkRect rect = {0, 0, w, h};
+    SkPath path;
+    path.addRoundRect(rect, corners);
+    SkPaint paint;
+    paint.setStyle(SkPaint::kFill_Style);
+    paint.setFlags(SkPaint::kAntiAlias_Flag);
+    SkPoint p[2] = { {0, 0}, {0, h} };
+    SkColor colors[2] = {kMenuStartColor, kMenuEndColor};
+    SkShader* s = SkGradientShader::CreateLinear(
+        p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
+    paint.setShader(s);
+    // Need to unref shader, otherwise never deleted.
+    s->unref();
+    canvas->AsCanvasSkia()->drawPath(path, paint);
+  }
+
+  virtual void GetInsets(gfx::Insets* insets) const {
+    DCHECK(insets);
+    menu_locator_->GetInsets(insets);
+  }
+
+  chromeos::MenuLocator* menu_locator_;  // not owned
+
+  DISALLOW_COPY_AND_ASSIGN(RoundedBorder);
+};
+
+class InsetsLayout : public views::LayoutManager {
+ public:
+  InsetsLayout() : views::LayoutManager() {}
+
+ private:
+  // views::LayoutManager implementations.
+  virtual void Layout(views::View* host) {
+    if (!host->has_children())
+      return;
+    gfx::Insets insets = host->GetInsets();
+    views::View* view = host->GetChildViewAt(0);
+
+    view->SetBounds(insets.left(), insets.top(),
+                    host->width() - insets.width(),
+                    host->height() - insets.height());
+  }
+
+  virtual gfx::Size GetPreferredSize(views::View* host) {
+    DCHECK(host->child_count() == 1);
+    gfx::Insets insets = host->GetInsets();
+    gfx::Size size = host->GetChildViewAt(0)->GetPreferredSize();
+    return gfx::Size(size.width() + insets.width(),
+                     size.height() + insets.height());
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(InsetsLayout);
+};
+
+// A gtk widget key used to test if a given WidgetGtk instance is
+// a WebUIMenuWidgetKey.
+const char* kWebUIMenuWidgetKey = "__WEBUI_MENU_WIDGET__";
+
+}  // namespace
+
+namespace chromeos {
+
+// static
+WebUIMenuWidget* WebUIMenuWidget::FindWebUIMenuWidget(gfx::NativeView native) {
+  DCHECK(native);
+  native = gtk_widget_get_toplevel(native);
+  if (!native)
+    return NULL;
+  return static_cast<chromeos::WebUIMenuWidget*>(
+      g_object_get_data(G_OBJECT(native), kWebUIMenuWidgetKey));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WebUIMenuWidget public:
+
+WebUIMenuWidget::WebUIMenuWidget(chromeos::NativeMenuWebUI* webui_menu,
+                                 bool root)
+    : views::WidgetGtk(views::WidgetGtk::TYPE_POPUP),
+      webui_menu_(webui_menu),
+      dom_view_(NULL),
+      did_input_grab_(false),
+      is_root_(root) {
+  DCHECK(webui_menu_);
+  // TODO(oshima): Disabling transparent until we migrate bookmark
+  // menus to WebUI.  See crosbug.com/7718.
+  // MakeTransparent();
+}
+
+WebUIMenuWidget::~WebUIMenuWidget() {
+}
+
+void WebUIMenuWidget::Init(gfx::NativeView parent, const gfx::Rect& bounds) {
+  WidgetGtk::Init(parent, bounds);
+  gtk_window_set_destroy_with_parent(GTK_WINDOW(GetNativeView()), TRUE);
+  gtk_window_set_type_hint(GTK_WINDOW(GetNativeView()),
+                           GDK_WINDOW_TYPE_HINT_MENU);
+  g_object_set_data(G_OBJECT(GetNativeView()), kWebUIMenuWidgetKey, this);
+}
+
+void WebUIMenuWidget::Hide() {
+  ReleaseGrab();
+  WidgetGtk::Hide();
+  // Clears the content.
+  ExecuteJavascript(L"updateModel({'items':[]})");
+}
+
+void WebUIMenuWidget::Close() {
+  if (dom_view_ != NULL) {
+    dom_view_->parent()->RemoveChildView(dom_view_);
+    delete dom_view_;
+    dom_view_ = NULL;
+  }
+
+  // Detach the webui_menu_ which is being deleted.
+  webui_menu_ = NULL;
+  views::WidgetGtk::Close();
+}
+
+void WebUIMenuWidget::ReleaseGrab() {
+  WidgetGtk::ReleaseGrab();
+  if (did_input_grab_) {
+    did_input_grab_ = false;
+    gdk_pointer_ungrab(GDK_CURRENT_TIME);
+    gdk_keyboard_ungrab(GDK_CURRENT_TIME);
+
+    ClearGrabWidget();
+  }
+}
+
+gboolean WebUIMenuWidget::OnGrabBrokeEvent(GtkWidget* widget,
+                                           GdkEvent* event) {
+  did_input_grab_ = false;
+  Hide();
+  return WidgetGtk::OnGrabBrokeEvent(widget, event);
+}
+
+void WebUIMenuWidget::OnSizeAllocate(GtkWidget* widget,
+                                     GtkAllocation* allocation) {
+  views::WidgetGtk::OnSizeAllocate(widget, allocation);
+  // Adjust location when menu gets resized.
+  gfx::Rect bounds;
+  GetBounds(&bounds, false);
+  // Don't move until the menu gets contents.
+  if (bounds.height() > 1) {
+    menu_locator_->Move(this);
+    webui_menu_->InputIsReady();
+  }
+}
+
+gboolean MapToFocus(GtkWidget* widget, GdkEvent* event, gpointer data) {
+  WebUIMenuWidget* menu_widget = WebUIMenuWidget::FindWebUIMenuWidget(widget);
+  if (menu_widget) {
+    // See EnableInput for the meaning of data.
+    bool select_item = data != NULL;
+    menu_widget->EnableInput(select_item);
+  }
+  return true;
+}
+
+void WebUIMenuWidget::EnableScroll(bool enable) {
+  ExecuteJavascript(StringPrintf(
+      L"enableScroll(%ls)", enable ? L"true" : L"false"));
+}
+
+void WebUIMenuWidget::EnableInput(bool select_item) {
+  if (!dom_view_)
+    return;
+  DCHECK(dom_view_->tab_contents()->render_view_host());
+  DCHECK(dom_view_->tab_contents()->render_view_host()->view());
+  GtkWidget* target =
+      dom_view_->tab_contents()->render_view_host()->view()->GetNativeView();
+  DCHECK(target);
+  // Skip if the widget already own the input.
+  if (gtk_grab_get_current() == target)
+    return;
+
+  ClearGrabWidget();
+
+  if (!GTK_WIDGET_REALIZED(target)) {
+    // Wait grabbing widget if the widget is not yet realized.
+    // Using data as a flag. |select_item| is false if data is NULL,
+    // or true otherwise.
+    g_signal_connect(G_OBJECT(target), "map-event",
+                     G_CALLBACK(&MapToFocus),
+                     select_item ? this : NULL);
+    return;
+  }
+
+  gtk_grab_add(target);
+  dom_view_->tab_contents()->Focus();
+  if (select_item) {
+    ExecuteJavascript(L"selectItem()");
+  }
+}
+
+void WebUIMenuWidget::ExecuteJavascript(const std::wstring& script) {
+  // Don't execute if there is no DOMView associated. This is fine because
+  // 1) selectItem make sense only when DOMView is associated.
+  // 2) updateModel will be called again when a DOMView is created/assigned.
+  if (!dom_view_)
+    return;
+
+  DCHECK(dom_view_->tab_contents()->render_view_host());
+  dom_view_->tab_contents()->render_view_host()->
+      ExecuteJavascriptInWebFrame(string16(), WideToUTF16Hack(script));
+}
+
+void WebUIMenuWidget::ShowAt(chromeos::MenuLocator* locator) {
+  DCHECK(webui_menu_);
+  menu_locator_.reset(locator);
+  if (!dom_view_) {
+    // TODO(oshima): Replace DOMView with direct use of RVH for beta.
+    // DOMView should be refactored to use RVH directly, but
+    // it'll require a lot of change and will take time.
+    dom_view_ = new DOMView();
+    dom_view_->Init(webui_menu_->GetProfile(), NULL);
+    // TODO(oshima): remove extra view to draw rounded corner.
+    views::View* container = new views::View();
+    container->AddChildView(dom_view_);
+    container->set_border(new RoundedBorder(locator));
+    container->SetLayoutManager(new InsetsLayout());
+    SetContentsView(container);
+    dom_view_->LoadURL(webui_menu_->menu_url());
+  } else {
+    webui_menu_->UpdateStates();
+    dom_view_->parent()->set_border(new RoundedBorder(locator));
+    menu_locator_->Move(this);
+  }
+  Show();
+
+  // The pointer grab is captured only on the top level menu,
+  // all mouse event events are delivered to submenu using gtk_add_grab.
+  if (is_root_) {
+    CaptureGrab();
+  }
+}
+
+void WebUIMenuWidget::SetSize(const gfx::Size& new_size) {
+  DCHECK(webui_menu_);
+  // Ignore the empty new_size request which is called when
+  // menu.html is loaded.
+  if (new_size.IsEmpty())
+    return;
+  int width, height;
+  gtk_widget_get_size_request(GetNativeView(), &width, &height);
+  gfx::Size real_size(std::max(new_size.width(), width),
+                      new_size.height());
+  // Ignore the size request with the same size.
+  gfx::Rect bounds;
+  GetBounds(&bounds, false);
+  if (bounds.size() == real_size)
+    return;
+  menu_locator_->SetBounds(this, real_size);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WebUIMenuWidget private:
+
+void WebUIMenuWidget::CaptureGrab() {
+  // Release the current grab.
+  ClearGrabWidget();
+
+  // NOTE: we do this to ensure we get mouse/keyboard events from
+  // other apps, a grab done with gtk_grab_add doesn't get events from
+  // other apps.
+  GdkGrabStatus pointer_grab_status =
+      gdk_pointer_grab(window_contents()->window, FALSE,
+                       static_cast<GdkEventMask>(
+                           GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                           GDK_POINTER_MOTION_MASK),
+                       NULL, NULL, GDK_CURRENT_TIME);
+  GdkGrabStatus keyboard_grab_status =
+      gdk_keyboard_grab(window_contents()->window, FALSE,
+                        GDK_CURRENT_TIME);
+
+  did_input_grab_ = pointer_grab_status == GDK_GRAB_SUCCESS &&
+      keyboard_grab_status == GDK_GRAB_SUCCESS;
+  DCHECK(did_input_grab_);
+
+  EnableInput(false /* no selection */);
+}
+
+void WebUIMenuWidget::ClearGrabWidget() {
+  GtkWidget* grab_widget;
+  while ((grab_widget = gtk_grab_get_current()))
+    gtk_grab_remove(grab_widget);
+}
+
+}   // namespace chromeos
diff --git a/chrome/browser/chromeos/views/webui_menu_widget.h b/chrome/browser/chromeos/views/webui_menu_widget.h
new file mode 100644
index 0000000..a566920
--- /dev/null
+++ b/chrome/browser/chromeos/views/webui_menu_widget.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_VIEWS_WEBUI_MENU_WIDGET_H_
+#define CHROME_BROWSER_CHROMEOS_VIEWS_WEBUI_MENU_WIDGET_H_
+#pragma once
+
+#include <string>
+
+#include "views/widget/widget_gtk.h"
+
+class DOMView;
+class ExtensionApiTest;
+
+namespace chromeos {
+
+class MenuLocator;
+class NativeMenuWebUI;
+
+// WebUIMenuWidget is a window widget for a Web UI based menu.
+class WebUIMenuWidget : public views::WidgetGtk {
+ public:
+  // Create a Window for the NativeMenuDMOUI. |root| specifies if
+  // the menu is root menu.
+  WebUIMenuWidget(NativeMenuWebUI* webui_menu, bool root);
+  virtual ~WebUIMenuWidget();
+
+  // WidgetGtk overrides:
+  virtual void Init(gfx::NativeView parent, const gfx::Rect& bounds);
+  virtual void Hide();
+  virtual void Close();
+  virtual void ReleaseGrab();
+  virtual gboolean OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event);
+  virtual void OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation);
+
+  // Returns NativeMenuWebUI that owns this widget.
+  NativeMenuWebUI* webui_menu() const {
+    return webui_menu_;
+  }
+
+  // Returns true if the menu widget is a root.
+  bool is_root() const {
+    return is_root_;
+  }
+
+  // Returns true if the menu widget has input grab.
+  bool did_input_grab() const {
+    return did_input_grab_;
+  }
+
+  // Enables/Disables menu scroll.
+  void EnableScroll(bool enabled);
+
+  // Tell the gtk to send all input events (mouse, keyboard) to this
+  // Widget. If |selectItem| is true, it highlights the selected item
+  // (or select 1st selectable item if none is selected).
+  void EnableInput(bool select_item);
+
+  // Executes given |javascript|.
+  void ExecuteJavascript(const std::wstring& javascript);
+
+  // Show the menu using |locator|.  Ownership of locator is transferred
+  // to this widget.
+  void ShowAt(MenuLocator* locator);
+
+  // Updates the size
+  void SetSize(const gfx::Size& new_size);
+
+  // Returns the menu locator owned by this widget.
+  const MenuLocator* menu_locator() const {
+    return menu_locator_.get();
+  }
+
+  // Returns WebUIMenuWidget that contains given native. This returns
+  // NULL if not found.
+  static WebUIMenuWidget* FindWebUIMenuWidget(gfx::NativeView native);
+
+ private:
+  // Capture the X pointer grab. This also enables input on the widget by
+  // calling EnableInput(false).
+  void CaptureGrab();
+
+  // Clears GTK grab.
+  void ClearGrabWidget();
+
+  // NativeMenu object that owns this widget.
+  NativeMenuWebUI* webui_menu_;
+
+  // DOMView to render the menu contents.
+  DOMView* dom_view_;
+
+  // MenuLocator that controls the position of this menu widget.
+  scoped_ptr<chromeos::MenuLocator> menu_locator_;
+
+  // True if the widget has input grab.
+  bool did_input_grab_;
+
+  // True if the widget is for root menu (very first menu in
+  // submenu chain).
+  bool is_root_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIMenuWidget);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_VIEWS_WEBUI_MENU_WIDGET_H_
diff --git a/chrome/browser/chromeos/volume_bubble.cc b/chrome/browser/chromeos/volume_bubble.cc
index ec9d365..f081c09 100644
--- a/chrome/browser/chromeos/volume_bubble.cc
+++ b/chrome/browser/chromeos/volume_bubble.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/chromeos/volume_bubble.h"
 
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/webui_menu_control.h b/chrome/browser/chromeos/webui_menu_control.h
new file mode 100644
index 0000000..3cb545c
--- /dev/null
+++ b/chrome/browser/chromeos/webui_menu_control.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_CHROMEOS_WEBUI_MENU_CONTROL_H_
+#define CHROME_BROWSER_CHROMEOS_WEBUI_MENU_CONTROL_H_
+#pragma once
+
+namespace gfx {
+class Size;
+}  // namespace gfx
+
+namespace ui {
+class MenuModel;
+}  // namespace ui
+
+namespace chromeos {
+
+// WebUIMenuControl class is used to control the UI counterpart of
+// a MenuModel. One instance of WebUIMenuControl is created for each
+// MenuModel instance, that is, a submenu will have its own
+// WebUIMenuControl.
+class WebUIMenuControl {
+ public:
+  enum ActivationMode {
+    ACTIVATE_NO_CLOSE,   // Activate the command without closing menu.
+    CLOSE_AND_ACTIVATE,  // Close the menu and then activate the command.
+  };
+  virtual ~WebUIMenuControl() {}
+
+  // Returns the MenuModel associated with this control.
+  virtual ui::MenuModel* GetMenuModel() = 0;
+
+  // Activates an item in the |model| at |index|.
+  virtual void Activate(ui::MenuModel* model,
+                        int index,
+                        ActivationMode activation_mode) = 0;
+
+  // Close All menu window from root menu to leaf submenus.
+  virtual void CloseAll() = 0;
+
+  // Close the submenu (and all decendant submenus).
+  virtual void CloseSubmenu() = 0;
+
+  // Move the input to parent. Used in keyboard navigation.
+  virtual void MoveInputToParent() = 0;
+
+  // Move the input to submenu. Used in keyboard navigation.
+  virtual void MoveInputToSubmenu() = 0;
+
+  // Called when the menu page is loaded. This is used to call
+  // initialize function in JavaScript.
+  virtual void OnLoad() = 0;
+
+  // Open submenu using the submenu model at index in the model.
+  // The top coordinate of the selected menu is passed as |y_top|
+  // so that the submenu can be aligned to the selected item.
+  virtual void OpenSubmenu(int index, int y_top) =0;
+
+  // Sets the size of the menu.
+  virtual void SetSize(const gfx::Size& size) = 0;
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_WEBUI_MENU_CONTROL_H_
diff --git a/chrome/browser/chromeos/wm_ipc.cc b/chrome/browser/chromeos/wm_ipc.cc
index 3e856f3..6acb5e6 100644
--- a/chrome/browser/chromeos/wm_ipc.cc
+++ b/chrome/browser/chromeos/wm_ipc.cc
@@ -9,10 +9,10 @@
 #include <X11/Xlib.h>
 }
 
-#include "app/x11_util.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
+#include "ui/base/x/x11_util.h"
 
 namespace chromeos {
 
@@ -45,7 +45,7 @@
     data[i] = values[i];
 
   // TODO: Trap errors and return false on failure.
-  XChangeProperty(x11_util::GetXDisplay(),
+  XChangeProperty(ui::GetXDisplay(),
                   xid,
                   xatom,
                   xatom,
@@ -53,7 +53,7 @@
                   PropModeReplace,
                   reinterpret_cast<const unsigned char*>(data.get()),
                   values.size());  // num items
-  XFlush(x11_util::GetXDisplay());
+  XFlush(ui::GetXDisplay());
   return true;
 }
 
@@ -73,15 +73,15 @@
   values.push_back(type);
   if (params)
     values.insert(values.end(), params->begin(), params->end());
-  return SetIntProperty(x11_util::GetX11WindowFromGtkWidget(widget),
+  return SetIntProperty(ui::GetX11WindowFromGtkWidget(widget),
                         type_to_atom_[ATOM_CHROME_WINDOW_TYPE], values);
 }
 
 WmIpcWindowType WmIpc::GetWindowType(GtkWidget* widget,
                                      std::vector<int>* params) {
   std::vector<int> properties;
-  if (x11_util::GetIntArrayProperty(
-          x11_util::GetX11WindowFromGtkWidget(widget),
+  if (ui::GetIntArrayProperty(
+          ui::GetX11WindowFromGtkWidget(widget),
           atom_to_string_[type_to_atom_[ATOM_CHROME_WINDOW_TYPE]],
           &properties)) {
     int type = properties.front();
@@ -109,7 +109,7 @@
   for (int i = 0; i < msg.max_params(); ++i)
     e.xclient.data.l[i+1] = msg.param(i);
 
-  XSendEvent(x11_util::GetXDisplay(),
+  XSendEvent(ui::GetXDisplay(),
              wm_,
              False,  // propagate
              0,  // empty event mask
@@ -166,6 +166,7 @@
 void WmIpc::NotifyAboutSignout() {
   Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_SIGNING_OUT);
   SendMessage(msg);
+  XFlush(ui::GetXDisplay());
 }
 
 WmIpc::WmIpc() {
@@ -177,7 +178,7 @@
     names[i] = const_cast<char*>(kAtomInfos[i].name);
   }
 
-  XInternAtoms(x11_util::GetXDisplay(), names.get(), kNumAtoms,
+  XInternAtoms(ui::GetXDisplay(), names.get(), kNumAtoms,
                False,  // only_if_exists
                atoms.get());
 
@@ -200,7 +201,7 @@
 }
 
 void WmIpc::InitWmInfo() {
-  wm_ = XGetSelectionOwner(x11_util::GetXDisplay(), type_to_atom_[ATOM_WM_S0]);
+  wm_ = XGetSelectionOwner(ui::GetXDisplay(), type_to_atom_[ATOM_WM_S0]);
 
   // Let the window manager know which version of the IPC messages we support.
   Message msg(chromeos::WM_IPC_MESSAGE_WM_NOTIFY_IPC_VERSION);
diff --git a/chrome/browser/chromeos/wm_overview_controller.cc b/chrome/browser/chromeos/wm_overview_controller.cc
index 778af64..9f2e1ad 100644
--- a/chrome/browser/chromeos/wm_overview_controller.cc
+++ b/chrome/browser/chromeos/wm_overview_controller.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,7 +22,7 @@
 #include "chrome/browser/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/notification_service.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_gtk.h"
diff --git a/chrome/browser/chromeos/wm_overview_controller.h b/chrome/browser/chromeos/wm_overview_controller.h
index f5f5348..386189a 100644
--- a/chrome/browser/chromeos/wm_overview_controller.h
+++ b/chrome/browser/chromeos/wm_overview_controller.h
@@ -14,7 +14,7 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/chromeos/wm_message_listener.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 namespace views {
 class Widget;
diff --git a/chrome/browser/chromeos/wm_overview_fav_icon.cc b/chrome/browser/chromeos/wm_overview_fav_icon.cc
index ad9dfa8..8c36b2a 100644
--- a/chrome/browser/chromeos/wm_overview_fav_icon.cc
+++ b/chrome/browser/chromeos/wm_overview_fav_icon.cc
@@ -6,15 +6,15 @@
 
 #include <vector>
 
-#include "app/x11_util.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
 #include "chrome/browser/chromeos/wm_overview_snapshot.h"
 #include "skia/ext/image_operations.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/x/x11_util.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 
 using std::vector;
 
@@ -42,7 +42,7 @@
 
   // Set the window type
   vector<int> params;
-  params.push_back(x11_util::GetX11WindowFromGtkWidget(
+  params.push_back(ui::GetX11WindowFromGtkWidget(
       GTK_WIDGET(snapshot->GetNativeView())));
   WmIpc::instance()->SetWindowType(
       GetNativeView(),
diff --git a/chrome/browser/chromeos/wm_overview_snapshot.cc b/chrome/browser/chromeos/wm_overview_snapshot.cc
index 2182273..494ec32 100644
--- a/chrome/browser/chromeos/wm_overview_snapshot.cc
+++ b/chrome/browser/chromeos/wm_overview_snapshot.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,13 @@
 
 #include <vector>
 
-#include "app/x11_util.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
 #include "chrome/browser/ui/browser.h"
+#include "ui/base/x/x11_util.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 
 using std::vector;
 
@@ -44,7 +44,7 @@
 
 void WmOverviewSnapshot::UpdateIndex(Browser* browser, int index) {
   vector<int> params;
-  params.push_back(x11_util::GetX11WindowFromGtkWidget(
+  params.push_back(ui::GetX11WindowFromGtkWidget(
       GTK_WIDGET(browser->window()->GetNativeHandle())));
   params.push_back(index);
   WmIpc::instance()->SetWindowType(
diff --git a/chrome/browser/chromeos/wm_overview_title.cc b/chrome/browser/chromeos/wm_overview_title.cc
index 7c6c5b6..7892f18 100644
--- a/chrome/browser/chromeos/wm_overview_title.cc
+++ b/chrome/browser/chromeos/wm_overview_title.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,18 +6,17 @@
 
 #include <vector>
 
-#include "app/x11_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/chromeos/drop_shadow_label.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
 #include "chrome/browser/chromeos/wm_overview_snapshot.h"
-#include "chrome/browser/ui/browser.h"
 #include "third_party/cros/chromeos_wm_ipc_enums.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/x/x11_util.h"
 #include "views/border.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/view.h"
 
 using std::vector;
@@ -98,7 +97,7 @@
 
   // Set the window type
   vector<int> params;
-  params.push_back(x11_util::GetX11WindowFromGtkWidget(
+  params.push_back(ui::GetX11WindowFromGtkWidget(
       GTK_WIDGET(snapshot->GetNativeView())));
   WmIpc::instance()->SetWindowType(
       GetNativeView(),
diff --git a/chrome/browser/clipboard_dispatcher.h b/chrome/browser/clipboard_dispatcher.h
index 8b9b4eb..3ca3281 100644
--- a/chrome/browser/clipboard_dispatcher.h
+++ b/chrome/browser/clipboard_dispatcher.h
@@ -8,9 +8,9 @@
 
 #include <vector>
 
-#include "app/clipboard/clipboard.h"
 #include "base/basictypes.h"
 #include "base/string16.h"
+#include "ui/base/clipboard/clipboard.h"
 
 // This class backs IPC requests from the renderer for clipboard data. In this
 // context, clipboard does not only refer to the usual concept of a clipboard
@@ -23,12 +23,12 @@
 //   selection.
 class ClipboardDispatcher {
  public:
-  static bool ReadAvailableTypes(Clipboard::Buffer buffer,
+  static bool ReadAvailableTypes(ui::Clipboard::Buffer buffer,
                                  std::vector<string16>* types,
                                  bool* contains_filenames);
-  static bool ReadData(Clipboard::Buffer buffer, const string16& type,
+  static bool ReadData(ui::Clipboard::Buffer buffer, const string16& type,
                        string16* data, string16* metadata);
-  static bool ReadFilenames(Clipboard::Buffer buffer,
+  static bool ReadFilenames(ui::Clipboard::Buffer buffer,
                             std::vector<string16>* filenames);
 
  private:
diff --git a/chrome/browser/clipboard_dispatcher_gtk.cc b/chrome/browser/clipboard_dispatcher_gtk.cc
index a448468..f5a456f 100644
--- a/chrome/browser/clipboard_dispatcher_gtk.cc
+++ b/chrome/browser/clipboard_dispatcher_gtk.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/clipboard_dispatcher.h"
 #include "base/logging.h"
 
-bool ClipboardDispatcher::ReadAvailableTypes(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadAvailableTypes(ui::Clipboard::Buffer buffer,
                                              std::vector<string16>* types,
                                              bool* contains_filenames) {
   DCHECK(types);
@@ -15,7 +15,7 @@
   return false;
 }
 
-bool ClipboardDispatcher::ReadData(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadData(ui::Clipboard::Buffer buffer,
                                    const string16& type,
                                    string16* data,
                                    string16* metadata) {
@@ -24,7 +24,7 @@
   return false;
 }
 
-bool ClipboardDispatcher::ReadFilenames(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadFilenames(ui::Clipboard::Buffer buffer,
                                         std::vector<string16>* filenames) {
   DCHECK(filenames);
   filenames->clear();
diff --git a/chrome/browser/clipboard_dispatcher_mac.mm b/chrome/browser/clipboard_dispatcher_mac.mm
index ce7e39b..e91f452 100644
--- a/chrome/browser/clipboard_dispatcher_mac.mm
+++ b/chrome/browser/clipboard_dispatcher_mac.mm
@@ -5,7 +5,7 @@
 #include "chrome/browser/clipboard_dispatcher.h"
 #include "base/logging.h"
 
-bool ClipboardDispatcher::ReadAvailableTypes(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadAvailableTypes(ui::Clipboard::Buffer buffer,
                                              std::vector<string16>* types,
                                              bool* contains_filenames) {
   DCHECK(types);
@@ -15,7 +15,7 @@
   return false;
 }
 
-bool ClipboardDispatcher::ReadData(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadData(ui::Clipboard::Buffer buffer,
                                    const string16& type,
                                    string16* data,
                                    string16* metadata) {
@@ -24,7 +24,7 @@
   return false;
 }
 
-bool ClipboardDispatcher::ReadFilenames(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadFilenames(ui::Clipboard::Buffer buffer,
                                         std::vector<string16>* filenames) {
   DCHECK(filenames);
   filenames->clear();
diff --git a/chrome/browser/clipboard_dispatcher_win.cc b/chrome/browser/clipboard_dispatcher_win.cc
index a448468..f5a456f 100644
--- a/chrome/browser/clipboard_dispatcher_win.cc
+++ b/chrome/browser/clipboard_dispatcher_win.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/clipboard_dispatcher.h"
 #include "base/logging.h"
 
-bool ClipboardDispatcher::ReadAvailableTypes(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadAvailableTypes(ui::Clipboard::Buffer buffer,
                                              std::vector<string16>* types,
                                              bool* contains_filenames) {
   DCHECK(types);
@@ -15,7 +15,7 @@
   return false;
 }
 
-bool ClipboardDispatcher::ReadData(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadData(ui::Clipboard::Buffer buffer,
                                    const string16& type,
                                    string16* data,
                                    string16* metadata) {
@@ -24,7 +24,7 @@
   return false;
 }
 
-bool ClipboardDispatcher::ReadFilenames(Clipboard::Buffer buffer,
+bool ClipboardDispatcher::ReadFilenames(ui::Clipboard::Buffer buffer,
                                         std::vector<string16>* filenames) {
   DCHECK(filenames);
   filenames->clear();
diff --git a/chrome/browser/cocoa/authorization_util.h b/chrome/browser/cocoa/authorization_util.h
new file mode 100644
index 0000000..d5daf4a
--- /dev/null
+++ b/chrome/browser/cocoa/authorization_util.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COCOA_AUTHORIZATION_UTIL_H_
+#define CHROME_BROWSER_COCOA_AUTHORIZATION_UTIL_H_
+#pragma once
+
+// AuthorizationExecuteWithPrivileges fork()s and exec()s the tool, but it
+// does not wait() for it.  It also doesn't provide the caller with access to
+// the forked pid.  If used irresponsibly, zombie processes will accumulate.
+//
+// Apple's really gotten us between a rock and a hard place, here.
+//
+// Fortunately, AuthorizationExecuteWithPrivileges does give access to the
+// tool's stdout (and stdin) via a FILE* pipe.  The tool can output its pid
+// to this pipe, and the main program can read it, and then have something
+// that it can wait() for.
+//
+// The contract is that any tool executed by the wrappers declared in this
+// file must print its pid to stdout on a line by itself before doing anything
+// else.
+//
+// http://developer.apple.com/mac/library/samplecode/BetterAuthorizationSample/listing1.html
+// (Look for "What's This About Zombies?")
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Authorization.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+namespace authorization_util {
+
+// Obtains an AuthorizationRef that can be used to run commands as root.  If
+// necessary, prompts the user for authentication.  If the user is prompted,
+// |prompt| will be used as the prompt string and an icon appropriate for the
+// application will be displayed in a prompt dialog.  Note that the system
+// appends its own text to the prompt string.  Returns NULL on failure.
+AuthorizationRef AuthorizationCreateToRunAsRoot(CFStringRef prompt);
+
+// Calls straight through to AuthorizationExecuteWithPrivileges.  If that
+// call succeeds, |pid| will be set to the pid of the executed tool.  If the
+// pid can't be determined, |pid| will be set to -1.  |pid| must not be NULL.
+// |pipe| may be NULL, but the tool will always be executed with a pipe in
+// order to read the pid from its stdout.
+OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization,
+                                        const char* tool_path,
+                                        AuthorizationFlags options,
+                                        const char** arguments,
+                                        FILE** pipe,
+                                        pid_t* pid);
+
+// Calls ExecuteWithPrivilegesAndGetPID, and if that call succeeds, calls
+// waitpid() to wait for the process to exit.  If waitpid() succeeds, the
+// exit status is placed in |exit_status|, otherwise, -1 is stored.
+// |exit_status| may be NULL and this function will still wait for the process
+// to exit.
+OSStatus ExecuteWithPrivilegesAndWait(AuthorizationRef authorization,
+                                      const char* tool_path,
+                                      AuthorizationFlags options,
+                                      const char** arguments,
+                                      FILE** pipe,
+                                      int* exit_status);
+
+}  // namespace authorization_util
+
+#endif  // CHROME_BROWSER_COCOA_AUTHORIZATION_UTIL_H_
diff --git a/chrome/browser/cocoa/authorization_util.mm b/chrome/browser/cocoa/authorization_util.mm
new file mode 100644
index 0000000..81e9d4c
--- /dev/null
+++ b/chrome/browser/cocoa/authorization_util.mm
@@ -0,0 +1,183 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/cocoa/authorization_util.h"
+
+#import <Foundation/Foundation.h>
+#include <sys/wait.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/eintr_wrapper.h"
+#include "base/logging.h"
+#import "base/mac/mac_util.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "chrome/browser/cocoa/scoped_authorizationref.h"
+
+namespace authorization_util {
+
+AuthorizationRef AuthorizationCreateToRunAsRoot(CFStringRef prompt) {
+  // Create an empty AuthorizationRef.
+  scoped_AuthorizationRef authorization;
+  OSStatus status = AuthorizationCreate(NULL,
+                                        kAuthorizationEmptyEnvironment,
+                                        kAuthorizationFlagDefaults,
+                                        &authorization);
+  if (status != errAuthorizationSuccess) {
+    LOG(ERROR) << "AuthorizationCreate: " << status;
+    return NULL;
+  }
+
+  // Specify the "system.privilege.admin" right, which allows
+  // AuthorizationExecuteWithPrivileges to run commands as root.
+  AuthorizationItem right_items[] = {
+    {kAuthorizationRightExecute, 0, NULL, 0}
+  };
+  AuthorizationRights rights = {arraysize(right_items), right_items};
+
+  // product_logo_32.png is used instead of app.icns because Authorization
+  // Services can't deal with .icns files.
+  NSString* icon_path =
+      [base::mac::MainAppBundle() pathForResource:@"product_logo_32"
+                                          ofType:@"png"];
+  const char* icon_path_c = [icon_path fileSystemRepresentation];
+  size_t icon_path_length = icon_path_c ? strlen(icon_path_c) : 0;
+
+  // The OS will append " Type an administrator's name and password to allow
+  // <CFBundleDisplayName> to make changes."
+  NSString* prompt_ns = base::mac::CFToNSCast(prompt);
+  const char* prompt_c = [prompt_ns UTF8String];
+  size_t prompt_length = prompt_c ? strlen(prompt_c) : 0;
+
+  AuthorizationItem environment_items[] = {
+    {kAuthorizationEnvironmentIcon, icon_path_length, (void*)icon_path_c, 0},
+    {kAuthorizationEnvironmentPrompt, prompt_length, (void*)prompt_c, 0}
+  };
+
+  AuthorizationEnvironment environment = {arraysize(environment_items),
+                                          environment_items};
+
+  AuthorizationFlags flags = kAuthorizationFlagDefaults |
+                             kAuthorizationFlagInteractionAllowed |
+                             kAuthorizationFlagExtendRights |
+                             kAuthorizationFlagPreAuthorize;
+
+  status = AuthorizationCopyRights(authorization,
+                                   &rights,
+                                   &environment,
+                                   flags,
+                                   NULL);
+  if (status != errAuthorizationSuccess) {
+    if (status != errAuthorizationCanceled) {
+      LOG(ERROR) << "AuthorizationCopyRights: " << status;
+    }
+    return NULL;
+  }
+
+  return authorization.release();
+}
+
+OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization,
+                                        const char* tool_path,
+                                        AuthorizationFlags options,
+                                        const char** arguments,
+                                        FILE** pipe,
+                                        pid_t* pid) {
+  // pipe may be NULL, but this function needs one.  In that case, use a local
+  // pipe.
+  FILE* local_pipe;
+  FILE** pipe_pointer;
+  if (pipe) {
+    pipe_pointer = pipe;
+  } else {
+    pipe_pointer = &local_pipe;
+  }
+
+  // AuthorizationExecuteWithPrivileges wants |char* const*| for |arguments|,
+  // but it doesn't actually modify the arguments, and that type is kind of
+  // silly and callers probably aren't dealing with that.  Put the cast here
+  // to make things a little easier on callers.
+  OSStatus status = AuthorizationExecuteWithPrivileges(authorization,
+                                                       tool_path,
+                                                       options,
+                                                       (char* const*)arguments,
+                                                       pipe_pointer);
+  if (status != errAuthorizationSuccess) {
+    return status;
+  }
+
+  int line_pid = -1;
+  size_t line_length = 0;
+  char* line_c = fgetln(*pipe_pointer, &line_length);
+  if (line_c) {
+    if (line_length > 0 && line_c[line_length - 1] == '\n') {
+      // line_c + line_length is the start of the next line if there is one.
+      // Back up one character.
+      --line_length;
+    }
+    std::string line(line_c, line_length);
+    if (!base::StringToInt(line, &line_pid)) {
+      // StringToInt may have set line_pid to something, but if the conversion
+      // was imperfect, use -1.
+      LOG(ERROR) << "ExecuteWithPrivilegesAndGetPid: funny line: " << line;
+      line_pid = -1;
+    }
+  } else {
+    LOG(ERROR) << "ExecuteWithPrivilegesAndGetPid: no line";
+  }
+
+  if (!pipe) {
+    fclose(*pipe_pointer);
+  }
+
+  if (pid) {
+    *pid = line_pid;
+  }
+
+  return status;
+}
+
+OSStatus ExecuteWithPrivilegesAndWait(AuthorizationRef authorization,
+                                      const char* tool_path,
+                                      AuthorizationFlags options,
+                                      const char** arguments,
+                                      FILE** pipe,
+                                      int* exit_status) {
+  pid_t pid;
+  OSStatus status = ExecuteWithPrivilegesAndGetPID(authorization,
+                                                   tool_path,
+                                                   options,
+                                                   arguments,
+                                                   pipe,
+                                                   &pid);
+  if (status != errAuthorizationSuccess) {
+    return status;
+  }
+
+  // exit_status may be NULL, but this function needs it.  In that case, use a
+  // local version.
+  int local_exit_status;
+  int* exit_status_pointer;
+  if (exit_status) {
+    exit_status_pointer = exit_status;
+  } else {
+    exit_status_pointer = &local_exit_status;
+  }
+
+  if (pid != -1) {
+    pid_t wait_result = HANDLE_EINTR(waitpid(pid, exit_status_pointer, 0));
+    if (wait_result != pid) {
+      PLOG(ERROR) << "waitpid";
+      *exit_status_pointer = -1;
+    }
+  } else {
+    *exit_status_pointer = -1;
+  }
+
+  return status;
+}
+
+}  // namespace authorization_util
diff --git a/chrome/browser/cocoa/install_from_dmg.h b/chrome/browser/cocoa/install_from_dmg.h
new file mode 100644
index 0000000..ec9248a
--- /dev/null
+++ b/chrome/browser/cocoa/install_from_dmg.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COCOA_INSTALL_FROM_DMG_H_
+#define CHROME_BROWSER_COCOA_INSTALL_FROM_DMG_H_
+#pragma once
+
+// If the application is running from a read-only disk image, prompts the user
+// to install it to the hard drive.  If the user approves, the application
+// will be installed and launched, and MaybeInstallFromDiskImage will return
+// true.  In that case, the caller must exit expeditiously.
+bool MaybeInstallFromDiskImage();
+
+#endif  // CHROME_BROWSER_COCOA_INSTALL_FROM_DMG_H_
diff --git a/chrome/browser/cocoa/install_from_dmg.mm b/chrome/browser/cocoa/install_from_dmg.mm
new file mode 100644
index 0000000..8af44f3
--- /dev/null
+++ b/chrome/browser/cocoa/install_from_dmg.mm
@@ -0,0 +1,438 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/cocoa/install_from_dmg.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+#import <AppKit/AppKit.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+#include <IOKit/IOKitLib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#import "base/mac/mac_util.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "chrome/browser/cocoa/authorization_util.h"
+#include "chrome/browser/cocoa/scoped_authorizationref.h"
+#import "chrome/browser/cocoa/keystone_glue.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+// When C++ exceptions are disabled, the C++ library defines |try| and
+// |catch| so as to allow exception-expecting C++ code to build properly when
+// language support for exceptions is not present.  These macros interfere
+// with the use of |@try| and |@catch| in Objective-C files such as this one.
+// Undefine these macros here, after everything has been #included, since
+// there will be no C++ uses and only Objective-C uses from this point on.
+#undef try
+#undef catch
+
+namespace {
+
+// Just like ScopedCFTypeRef but for io_object_t and subclasses.
+template<typename IOT>
+class scoped_ioobject {
+ public:
+  typedef IOT element_type;
+
+  explicit scoped_ioobject(IOT object = NULL)
+      : object_(object) {
+  }
+
+  ~scoped_ioobject() {
+    if (object_)
+      IOObjectRelease(object_);
+  }
+
+  void reset(IOT object = NULL) {
+    if (object_)
+      IOObjectRelease(object_);
+    object_ = object;
+  }
+
+  bool operator==(IOT that) const {
+    return object_ == that;
+  }
+
+  bool operator!=(IOT that) const {
+    return object_ != that;
+  }
+
+  operator IOT() const {
+    return object_;
+  }
+
+  IOT get() const {
+    return object_;
+  }
+
+  void swap(scoped_ioobject& that) {
+    IOT temp = that.object_;
+    that.object_ = object_;
+    object_ = temp;
+  }
+
+  IOT release() {
+    IOT temp = object_;
+    object_ = NULL;
+    return temp;
+  }
+
+ private:
+  IOT object_;
+
+  DISALLOW_COPY_AND_ASSIGN(scoped_ioobject);
+};
+
+// Returns true if |path| is located on a read-only filesystem of a disk
+// image.  Returns false if not, or in the event of an error.
+bool IsPathOnReadOnlyDiskImage(const char path[]) {
+  struct statfs statfs_buf;
+  if (statfs(path, &statfs_buf) != 0) {
+    PLOG(ERROR) << "statfs " << path;
+    return false;
+  }
+
+  if (!(statfs_buf.f_flags & MNT_RDONLY)) {
+    // Not on a read-only filesystem.
+    return false;
+  }
+
+  const char dev_root[] = "/dev/";
+  const int dev_root_length = arraysize(dev_root) - 1;
+  if (strncmp(statfs_buf.f_mntfromname, dev_root, dev_root_length) != 0) {
+    // Not rooted at dev_root, no BSD name to search on.
+    return false;
+  }
+
+  // BSD names in IOKit don't include dev_root.
+  const char* bsd_device_name = statfs_buf.f_mntfromname + dev_root_length;
+
+  const mach_port_t master_port = kIOMasterPortDefault;
+
+  // IOBSDNameMatching gives ownership of match_dict to the caller, but
+  // IOServiceGetMatchingServices will assume that reference.
+  CFMutableDictionaryRef match_dict = IOBSDNameMatching(master_port,
+                                                        0,
+                                                        bsd_device_name);
+  if (!match_dict) {
+    LOG(ERROR) << "IOBSDNameMatching " << bsd_device_name;
+    return false;
+  }
+
+  io_iterator_t iterator_ref;
+  kern_return_t kr = IOServiceGetMatchingServices(master_port,
+                                                  match_dict,
+                                                  &iterator_ref);
+  if (kr != KERN_SUCCESS) {
+    LOG(ERROR) << "IOServiceGetMatchingServices " << bsd_device_name
+               << ": kernel error " << kr;
+    return false;
+  }
+  scoped_ioobject<io_iterator_t> iterator(iterator_ref);
+  iterator_ref = NULL;
+
+  // There needs to be exactly one matching service.
+  scoped_ioobject<io_service_t> filesystem_service(IOIteratorNext(iterator));
+  if (!filesystem_service) {
+    LOG(ERROR) << "IOIteratorNext " << bsd_device_name << ": no service";
+    return false;
+  }
+  scoped_ioobject<io_service_t> unexpected_service(IOIteratorNext(iterator));
+  if (unexpected_service) {
+    LOG(ERROR) << "IOIteratorNext " << bsd_device_name << ": too many services";
+    return false;
+  }
+
+  iterator.reset();
+
+  const char disk_image_class[] = "IOHDIXController";
+
+  // This is highly unlikely.  The filesystem service is expected to be of
+  // class IOMedia.  Since the filesystem service's entire ancestor chain
+  // will be checked, though, check the filesystem service's class itself.
+  if (IOObjectConformsTo(filesystem_service, disk_image_class)) {
+    return true;
+  }
+
+  kr = IORegistryEntryCreateIterator(filesystem_service,
+                                     kIOServicePlane,
+                                     kIORegistryIterateRecursively |
+                                         kIORegistryIterateParents,
+                                     &iterator_ref);
+  if (kr != KERN_SUCCESS) {
+    LOG(ERROR) << "IORegistryEntryCreateIterator " << bsd_device_name
+               << ": kernel error " << kr;
+    return false;
+  }
+  iterator.reset(iterator_ref);
+  iterator_ref = NULL;
+
+  // Look at each of the filesystem service's ancestor services, beginning
+  // with the parent, iterating all the way up to the device tree's root.  If
+  // any ancestor service matches the class used for disk images, the
+  // filesystem resides on a disk image.
+  for(scoped_ioobject<io_service_t> ancestor_service(IOIteratorNext(iterator));
+      ancestor_service;
+      ancestor_service.reset(IOIteratorNext(iterator))) {
+    if (IOObjectConformsTo(ancestor_service, disk_image_class)) {
+      return true;
+    }
+  }
+
+  // The filesystem does not reside on a disk image.
+  return false;
+}
+
+// Returns true if the application is located on a read-only filesystem of a
+// disk image.  Returns false if not, or in the event of an error.
+bool IsAppRunningFromReadOnlyDiskImage() {
+  return IsPathOnReadOnlyDiskImage(
+      [[[NSBundle mainBundle] bundlePath] fileSystemRepresentation]);
+}
+
+// Shows a dialog asking the user whether or not to install from the disk
+// image.  Returns true if the user approves installation.
+bool ShouldInstallDialog() {
+  NSString* title = l10n_util::GetNSStringFWithFixup(
+      IDS_INSTALL_FROM_DMG_TITLE, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  NSString* prompt = l10n_util::GetNSStringFWithFixup(
+      IDS_INSTALL_FROM_DMG_PROMPT, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  NSString* yes = l10n_util::GetNSStringWithFixup(IDS_INSTALL_FROM_DMG_YES);
+  NSString* no = l10n_util::GetNSStringWithFixup(IDS_INSTALL_FROM_DMG_NO);
+
+  NSAlert* alert = [[[NSAlert alloc] init] autorelease];
+
+  [alert setAlertStyle:NSInformationalAlertStyle];
+  [alert setMessageText:title];
+  [alert setInformativeText:prompt];
+  [alert addButtonWithTitle:yes];
+  NSButton* cancel_button = [alert addButtonWithTitle:no];
+  [cancel_button setKeyEquivalent:@"\e"];
+
+  NSInteger result = [alert runModal];
+
+  return result == NSAlertFirstButtonReturn;
+}
+
+// Potentially shows an authorization dialog to request authentication to
+// copy.  If application_directory appears to be unwritable, attempts to
+// obtain authorization, which may result in the display of the dialog.
+// Returns NULL if authorization is not performed because it does not appear
+// to be necessary because the user has permission to write to
+// application_directory.  Returns NULL if authorization fails.
+AuthorizationRef MaybeShowAuthorizationDialog(NSString* application_directory) {
+  NSFileManager* file_manager = [NSFileManager defaultManager];
+  if ([file_manager isWritableFileAtPath:application_directory]) {
+    return NULL;
+  }
+
+  NSString* prompt = l10n_util::GetNSStringFWithFixup(
+      IDS_INSTALL_FROM_DMG_AUTHENTICATION_PROMPT,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  return authorization_util::AuthorizationCreateToRunAsRoot(
+      reinterpret_cast<CFStringRef>(prompt));
+}
+
+// Invokes the installer program at installer_path to copy source_path to
+// target_path and perform any additional on-disk bookkeeping needed to be
+// able to launch target_path properly.  If authorization_arg is non-NULL,
+// function will assume ownership of it, will invoke the installer with that
+// authorization reference, and will attempt Keystone ticket promotion.
+bool InstallFromDiskImage(AuthorizationRef authorization_arg,
+                          NSString* installer_path,
+                          NSString* source_path,
+                          NSString* target_path) {
+  scoped_AuthorizationRef authorization(authorization_arg);
+  authorization_arg = NULL;
+  int exit_status;
+  if (authorization) {
+    const char* installer_path_c = [installer_path fileSystemRepresentation];
+    const char* source_path_c = [source_path fileSystemRepresentation];
+    const char* target_path_c = [target_path fileSystemRepresentation];
+    const char* arguments[] = {source_path_c, target_path_c, NULL};
+
+    OSStatus status = authorization_util::ExecuteWithPrivilegesAndWait(
+        authorization,
+        installer_path_c,
+        kAuthorizationFlagDefaults,
+        arguments,
+        NULL,  // pipe
+        &exit_status);
+    if (status != errAuthorizationSuccess) {
+      LOG(ERROR) << "AuthorizationExecuteWithPrivileges install: " << status;
+      return false;
+    }
+  } else {
+    NSArray* arguments = [NSArray arrayWithObjects:source_path,
+                                                   target_path,
+                                                   nil];
+
+    NSTask* task;
+    @try {
+      task = [NSTask launchedTaskWithLaunchPath:installer_path
+                                      arguments:arguments];
+    } @catch(NSException* exception) {
+      LOG(ERROR) << "+[NSTask launchedTaskWithLaunchPath:arguments:]: "
+                 << [[exception description] UTF8String];
+      return false;
+    }
+
+    [task waitUntilExit];
+    exit_status = [task terminationStatus];
+  }
+
+  if (exit_status != 0) {
+    LOG(ERROR) << "install.sh: exit status " << exit_status;
+    return false;
+  }
+
+  if (authorization) {
+    // As long as an AuthorizationRef is available, promote the Keystone
+    // ticket.  Inform KeystoneGlue of the new path to use.
+    KeystoneGlue* keystone_glue = [KeystoneGlue defaultKeystoneGlue];
+    [keystone_glue setAppPath:target_path];
+    [keystone_glue promoteTicketWithAuthorization:authorization.release()
+                                      synchronous:YES];
+  }
+
+  return true;
+}
+
+// Launches the application at app_path.  The arguments passed to app_path
+// will be the same as the arguments used to invoke this process, except any
+// arguments beginning with -psn_ will be stripped.
+bool LaunchInstalledApp(NSString* app_path) {
+  const UInt8* app_path_c =
+      reinterpret_cast<const UInt8*>([app_path fileSystemRepresentation]);
+  FSRef app_fsref;
+  OSStatus err = FSPathMakeRef(app_path_c, &app_fsref, NULL);
+  if (err != noErr) {
+    LOG(ERROR) << "FSPathMakeRef: " << err;
+    return false;
+  }
+
+  const std::vector<std::string>& argv =
+      CommandLine::ForCurrentProcess()->argv();
+  NSMutableArray* arguments =
+      [NSMutableArray arrayWithCapacity:argv.size() - 1];
+  // Start at argv[1].  LSOpenApplication adds its own argv[0] as the path of
+  // the launched executable.
+  for (size_t index = 1; index < argv.size(); ++index) {
+    std::string argument = argv[index];
+    const char psn_flag[] = "-psn_";
+    const int psn_flag_length = arraysize(psn_flag) - 1;
+    if (argument.compare(0, psn_flag_length, psn_flag) != 0) {
+      // Strip any -psn_ arguments, as they apply to a specific process.
+      [arguments addObject:[NSString stringWithUTF8String:argument.c_str()]];
+    }
+  }
+
+  struct LSApplicationParameters parameters = {0};
+  parameters.flags = kLSLaunchDefaults;
+  parameters.application = &app_fsref;
+  parameters.argv = reinterpret_cast<CFArrayRef>(arguments);
+
+  err = LSOpenApplication(&parameters, NULL);
+  if (err != noErr) {
+    LOG(ERROR) << "LSOpenApplication: " << err;
+    return false;
+  }
+
+  return true;
+}
+
+void ShowErrorDialog() {
+  NSString* title = l10n_util::GetNSStringWithFixup(
+      IDS_INSTALL_FROM_DMG_ERROR_TITLE);
+  NSString* error = l10n_util::GetNSStringFWithFixup(
+      IDS_INSTALL_FROM_DMG_ERROR, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  NSString* ok = l10n_util::GetNSStringWithFixup(IDS_OK);
+
+  NSAlert* alert = [[[NSAlert alloc] init] autorelease];
+
+  [alert setAlertStyle:NSWarningAlertStyle];
+  [alert setMessageText:title];
+  [alert setInformativeText:error];
+  [alert addButtonWithTitle:ok];
+
+  [alert runModal];
+}
+
+}  // namespace
+
+bool MaybeInstallFromDiskImage() {
+  base::mac::ScopedNSAutoreleasePool autorelease_pool;
+
+  if (!IsAppRunningFromReadOnlyDiskImage()) {
+    return false;
+  }
+
+  NSArray* application_directories =
+      NSSearchPathForDirectoriesInDomains(NSApplicationDirectory,
+                                          NSLocalDomainMask,
+                                          YES);
+  if ([application_directories count] == 0) {
+    LOG(ERROR) << "NSSearchPathForDirectoriesInDomains: "
+               << "no local application directories";
+    return false;
+  }
+  NSString* application_directory = [application_directories objectAtIndex:0];
+
+  NSFileManager* file_manager = [NSFileManager defaultManager];
+
+  BOOL is_directory;
+  if (![file_manager fileExistsAtPath:application_directory
+                          isDirectory:&is_directory] ||
+      !is_directory) {
+    VLOG(1) << "No application directory at "
+            << [application_directory UTF8String];
+    return false;
+  }
+
+  NSString* source_path = [[NSBundle mainBundle] bundlePath];
+  NSString* application_name = [source_path lastPathComponent];
+  NSString* target_path =
+      [application_directory stringByAppendingPathComponent:application_name];
+
+  if ([file_manager fileExistsAtPath:target_path]) {
+    VLOG(1) << "Something already exists at " << [target_path UTF8String];
+    return false;
+  }
+
+  NSString* installer_path =
+      [base::mac::MainAppBundle() pathForResource:@"install" ofType:@"sh"];
+  if (!installer_path) {
+    VLOG(1) << "Could not locate install.sh";
+    return false;
+  }
+
+  if (!ShouldInstallDialog()) {
+    return false;
+  }
+
+  scoped_AuthorizationRef authorization(
+      MaybeShowAuthorizationDialog(application_directory));
+  // authorization will be NULL if it's deemed unnecessary or if
+  // authentication fails.  In either case, try to install without privilege
+  // escalation.
+
+  if (!InstallFromDiskImage(authorization.release(),
+                            installer_path,
+                            source_path,
+                            target_path) ||
+      !LaunchInstalledApp(target_path)) {
+    ShowErrorDialog();
+    return false;
+  }
+
+  return true;
+}
diff --git a/chrome/browser/cocoa/keystone_glue.h b/chrome/browser/cocoa/keystone_glue.h
new file mode 100644
index 0000000..69b5351
--- /dev/null
+++ b/chrome/browser/cocoa/keystone_glue.h
@@ -0,0 +1,209 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COCOA_KEYSTONE_GLUE_H_
+#define CHROME_BROWSER_COCOA_KEYSTONE_GLUE_H_
+#pragma once
+
+#include "base/string16.h"
+
+#if defined(__OBJC__)
+
+#import <Foundation/Foundation.h>
+
+#import "base/scoped_nsobject.h"
+#include "chrome/browser/cocoa/scoped_authorizationref.h"
+
+// Possible outcomes of various operations.  A version may accompany some of
+// these, but beware: a version is never required.  For statuses that can be
+// accompanied by a version, the comment indicates what version is referenced.
+// A notification posted containing an asynchronous status will always be
+// followed by a notification with a terminal status.
+enum AutoupdateStatus {
+  kAutoupdateNone = 0,        // no version (initial state only)
+  kAutoupdateRegistering,     // no version (asynchronous operation in progress)
+  kAutoupdateRegistered,      // no version
+  kAutoupdateChecking,        // no version (asynchronous operation in progress)
+  kAutoupdateCurrent,         // version of the running application
+  kAutoupdateAvailable,       // version of the update that is available
+  kAutoupdateInstalling,      // no version (asynchronous operation in progress)
+  kAutoupdateInstalled,       // version of the update that was installed
+  kAutoupdatePromoting,       // no version (asynchronous operation in progress)
+  kAutoupdatePromoted,        // no version
+  kAutoupdateRegisterFailed,  // no version
+  kAutoupdateCheckFailed,     // no version
+  kAutoupdateInstallFailed,   // no version
+  kAutoupdatePromoteFailed,   // no version
+};
+
+// kAutoupdateStatusNotification is the name of the notification posted when
+// -checkForUpdate and -installUpdate complete.  This notification will be
+// sent with with its sender object set to the KeystoneGlue instance sending
+// the notification.  Its userInfo dictionary will contain an AutoupdateStatus
+// value as an intValue at key kAutoupdateStatusStatus.  If a version is
+// available (see AutoupdateStatus), it will be present at key
+// kAutoupdateStatusVersion.
+extern NSString* const kAutoupdateStatusNotification;
+extern NSString* const kAutoupdateStatusStatus;
+extern NSString* const kAutoupdateStatusVersion;
+
+namespace {
+
+enum BrandFileType {
+  kBrandFileTypeNotDetermined = 0,
+  kBrandFileTypeNone,
+  kBrandFileTypeUser,
+  kBrandFileTypeSystem,
+};
+
+} // namespace
+
+// KeystoneGlue is an adapter around the KSRegistration class, allowing it to
+// be used without linking directly against its containing KeystoneRegistration
+// framework.  This is used in an environment where most builds (such as
+// developer builds) don't want or need Keystone support and might not even
+// have the framework available.  Enabling Keystone support in an application
+// that uses KeystoneGlue is as simple as dropping
+// KeystoneRegistration.framework in the application's Frameworks directory
+// and providing the relevant information in its Info.plist.  KeystoneGlue
+// requires that the KSUpdateURL key be set in the application's Info.plist,
+// and that it contain a string identifying the update URL to be used by
+// Keystone.
+
+@class KSRegistration;
+
+@interface KeystoneGlue : NSObject {
+ @protected
+
+  // Data for Keystone registration
+  NSString* productID_;
+  NSString* appPath_;
+  NSString* url_;
+  NSString* version_;
+  NSString* channel_;  // Logically: Dev, Beta, or Stable.
+  BrandFileType brandFileType_;
+
+  // And the Keystone registration itself, with the active timer
+  KSRegistration* registration_;  // strong
+  NSTimer* timer_;  // strong
+
+  // The most recent kAutoupdateStatusNotification notification posted.
+  scoped_nsobject<NSNotification> recentNotification_;
+
+  // The authorization object, when it needs to persist because it's being
+  // carried across threads.
+  scoped_AuthorizationRef authorization_;
+
+  // YES if a synchronous promotion operation is in progress (promotion during
+  // installation).
+  BOOL synchronousPromotion_;
+
+  // YES if an update was ever successfully installed by -installUpdate.
+  BOOL updateSuccessfullyInstalled_;
+}
+
+// Return the default Keystone Glue object.
++ (id)defaultKeystoneGlue;
+
+// Load KeystoneRegistration.framework if present, call into it to register
+// with Keystone, and set up periodic activity pings.
+- (void)registerWithKeystone;
+
+// -checkForUpdate launches a check for updates, and -installUpdate begins
+// installing an available update.  For each, status will be communicated via
+// a kAutoupdateStatusNotification notification, and will also be available
+// through -recentNotification.
+- (void)checkForUpdate;
+- (void)installUpdate;
+
+// Accessor for recentNotification_.  Returns an autoreleased NSNotification.
+- (NSNotification*)recentNotification;
+
+// Accessor for the kAutoupdateStatusStatus field of recentNotification_'s
+// userInfo dictionary.
+- (AutoupdateStatus)recentStatus;
+
+// Returns YES if an asynchronous operation is pending: if an update check or
+// installation attempt is currently in progress.
+- (BOOL)asyncOperationPending;
+
+// Returns YES if the application is running from a read-only filesystem,
+// such as a disk image.
+- (BOOL)isOnReadOnlyFilesystem;
+
+// -needsPromotion is YES if the application needs its ticket promoted to
+// a system ticket.  This will be YES when the application is on a user
+// ticket and determines that the current user does not have sufficient
+// permission to perform the update.
+//
+// -wantsPromotion is YES if the application wants its ticket promoted to
+// a system ticket, even if it doesn't need it as determined by
+// -needsPromotion.  -wantsPromotion will always be YES if -needsPromotion is,
+// and it will additionally be YES when the application is on a user ticket
+// and appears to be installed in a system-wide location such as
+// /Applications.
+//
+// Use -needsPromotion to decide whether to show any update UI at all.  If
+// it's YES, there's no sense in asking the user to "update now" because it
+// will fail given the rights and permissions involved.  On the other hand,
+// when -needsPromotion is YES, the application can encourage the user to
+// promote the ticket so that updates will work properly.
+//
+// Use -wantsPromotion to decide whether to allow the user to promote.  The
+// user shouldn't be nagged about promotion on the basis of -wantsPromotion,
+// but if it's YES, the user should be allowed to promote the ticket.
+- (BOOL)needsPromotion;
+- (BOOL)wantsPromotion;
+
+// Promotes the Keystone ticket into the system store.  System Keystone will
+// be installed if necessary.  If synchronous is NO, the promotion may occur
+// in the background.  synchronous should be YES for promotion during
+// installation. The KeystoneGlue object assumes ownership of
+// authorization_arg.
+- (void)promoteTicketWithAuthorization:(AuthorizationRef)authorization_arg
+                           synchronous:(BOOL)synchronous;
+
+// Requests authorization and calls -promoteTicketWithAuthorization: in
+// asynchronous mode.
+- (void)promoteTicket;
+
+// Sets a new value for appPath.  Used during installation to point a ticket
+// at the installed copy.
+- (void)setAppPath:(NSString*)appPath;
+
+@end  // @interface KeystoneGlue
+
+@interface KeystoneGlue(ExposedForTesting)
+
+// Load any params we need for configuring Keystone.
+- (void)loadParameters;
+
+// Load the Keystone registration object.
+// Return NO on failure.
+- (BOOL)loadKeystoneRegistration;
+
+- (void)stopTimer;
+
+// Called when a checkForUpdate: notification completes.
+- (void)checkForUpdateComplete:(NSNotification*)notification;
+
+// Called when an installUpdate: notification completes.
+- (void)installUpdateComplete:(NSNotification*)notification;
+
+@end  // @interface KeystoneGlue(ExposedForTesting)
+
+#endif  // __OBJC__
+
+// Functions that may be accessed from non-Objective-C C/C++ code.
+namespace keystone_glue {
+
+// True if Keystone is enabled.
+bool KeystoneEnabled();
+
+// The version of the application currently installed on disk.
+string16 CurrentlyInstalledVersion();
+
+}  // namespace keystone_glue
+
+#endif  // CHROME_BROWSER_COCOA_KEYSTONE_GLUE_H_
diff --git a/chrome/browser/cocoa/keystone_glue.mm b/chrome/browser/cocoa/keystone_glue.mm
new file mode 100644
index 0000000..562d74a
--- /dev/null
+++ b/chrome/browser/cocoa/keystone_glue.mm
@@ -0,0 +1,957 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/cocoa/keystone_glue.h"
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/sys_string_conversions.h"
+#include "base/ref_counted.h"
+#include "base/task.h"
+#include "base/threading/worker_pool.h"
+#include "chrome/browser/cocoa/authorization_util.h"
+#include "chrome/common/chrome_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+namespace {
+
+// Provide declarations of the Keystone registration bits needed here.  From
+// KSRegistration.h.
+typedef enum {
+  kKSPathExistenceChecker,
+} KSExistenceCheckerType;
+
+typedef enum {
+  kKSRegistrationUserTicket,
+  kKSRegistrationSystemTicket,
+  kKSRegistrationDontKnowWhatKindOfTicket,
+} KSRegistrationTicketType;
+
+NSString* const KSRegistrationVersionKey = @"Version";
+NSString* const KSRegistrationExistenceCheckerTypeKey = @"ExistenceCheckerType";
+NSString* const KSRegistrationExistenceCheckerStringKey =
+    @"ExistenceCheckerString";
+NSString* const KSRegistrationServerURLStringKey = @"URLString";
+NSString* const KSRegistrationPreserveTrustedTesterTokenKey = @"PreserveTTT";
+NSString* const KSRegistrationTagKey = @"Tag";
+NSString* const KSRegistrationTagPathKey = @"TagPath";
+NSString* const KSRegistrationTagKeyKey = @"TagKey";
+NSString* const KSRegistrationBrandPathKey = @"BrandPath";
+NSString* const KSRegistrationBrandKeyKey = @"BrandKey";
+
+NSString* const KSRegistrationDidCompleteNotification =
+    @"KSRegistrationDidCompleteNotification";
+NSString* const KSRegistrationPromotionDidCompleteNotification =
+    @"KSRegistrationPromotionDidCompleteNotification";
+
+NSString* const KSRegistrationCheckForUpdateNotification =
+    @"KSRegistrationCheckForUpdateNotification";
+NSString* KSRegistrationStatusKey = @"Status";
+NSString* KSRegistrationUpdateCheckErrorKey = @"Error";
+
+NSString* const KSRegistrationStartUpdateNotification =
+    @"KSRegistrationStartUpdateNotification";
+NSString* const KSUpdateCheckSuccessfulKey = @"CheckSuccessful";
+NSString* const KSUpdateCheckSuccessfullyInstalledKey =
+    @"SuccessfullyInstalled";
+
+NSString* const KSRegistrationRemoveExistingTag = @"";
+#define KSRegistrationPreserveExistingTag nil
+
+// Constants for the brand file (uses an external file so it can survive updates
+// to Chrome.
+
+#if defined(GOOGLE_CHROME_BUILD)
+#define kBrandFileName @"Google Chrome Brand.plist";
+#elif defined(CHROMIUM_BUILD)
+#define kBrandFileName @"Chromium Brand.plist";
+#else
+#error Unknown branding
+#endif
+
+// These directories are hardcoded in Keystone promotion preflight and the
+// Keystone install script, so NSSearchPathForDirectoriesInDomains isn't used
+// since the scripts couldn't use anything like that.
+NSString* kBrandUserFile = @"~/Library/Google/" kBrandFileName;
+NSString* kBrandSystemFile = @"/Library/Google/" kBrandFileName;
+
+NSString* UserBrandFilePath() {
+  return [kBrandUserFile stringByStandardizingPath];
+}
+NSString* SystemBrandFilePath() {
+  return [kBrandSystemFile stringByStandardizingPath];
+}
+
+// Adaptor for scheduling an Objective-C method call on a |WorkerPool|
+// thread.
+class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> {
+ public:
+
+  // Call |sel| on |target| with |arg| in a WorkerPool thread.
+  // |target| and |arg| are retained, |arg| may be |nil|.
+  static void PostPerform(id target, SEL sel, id arg) {
+    DCHECK(target);
+    DCHECK(sel);
+
+    scoped_refptr<PerformBridge> op = new PerformBridge(target, sel, arg);
+    base::WorkerPool::PostTask(
+        FROM_HERE, NewRunnableMethod(op.get(), &PerformBridge::Run), true);
+  }
+
+  // Convenience for the no-argument case.
+  static void PostPerform(id target, SEL sel) {
+    PostPerform(target, sel, nil);
+  }
+
+ private:
+  // Allow RefCountedThreadSafe<> to delete.
+  friend class base::RefCountedThreadSafe<PerformBridge>;
+
+  PerformBridge(id target, SEL sel, id arg)
+      : target_([target retain]),
+        sel_(sel),
+        arg_([arg retain]) {
+  }
+
+  ~PerformBridge() {}
+
+  // Happens on a WorkerPool thread.
+  void Run() {
+    base::mac::ScopedNSAutoreleasePool pool;
+    [target_ performSelector:sel_ withObject:arg_];
+  }
+
+  scoped_nsobject<id> target_;
+  SEL sel_;
+  scoped_nsobject<id> arg_;
+};
+
+}  // namespace
+
+@interface KSRegistration : NSObject
+
++ (id)registrationWithProductID:(NSString*)productID;
+
+- (BOOL)registerWithParameters:(NSDictionary*)args;
+
+- (BOOL)promoteWithParameters:(NSDictionary*)args
+                authorization:(AuthorizationRef)authorization;
+
+- (void)setActive;
+- (void)checkForUpdate;
+- (void)startUpdate;
+- (KSRegistrationTicketType)ticketType;
+
+@end  // @interface KSRegistration
+
+@interface KeystoneGlue(Private)
+
+// Returns the path to the application's Info.plist file.  This returns the
+// outer application bundle's Info.plist, not the framework's Info.plist.
+- (NSString*)appInfoPlistPath;
+
+// Returns a dictionary containing parameters to be used for a KSRegistration
+// -registerWithParameters: or -promoteWithParameters:authorization: call.
+- (NSDictionary*)keystoneParameters;
+
+// Called when Keystone registration completes.
+- (void)registrationComplete:(NSNotification*)notification;
+
+// Called periodically to announce activity by pinging the Keystone server.
+- (void)markActive:(NSTimer*)timer;
+
+// Called when an update check or update installation is complete.  Posts the
+// kAutoupdateStatusNotification notification to the default notification
+// center.
+- (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version;
+
+// Returns the version of the currently-installed application on disk.
+- (NSString*)currentlyInstalledVersion;
+
+// These three methods are used to determine the version of the application
+// currently installed on disk, compare that to the currently-running version,
+// decide whether any updates have been installed, and call
+// -updateStatus:version:.
+//
+// In order to check the version on disk, the installed application's
+// Info.plist dictionary must be read; in order to see changes as updates are
+// applied, the dictionary must be read each time, bypassing any caches such
+// as the one that NSBundle might be maintaining.  Reading files can be a
+// blocking operation, and blocking operations are to be avoided on the main
+// thread.  I'm not quite sure what jank means, but I bet that a blocked main
+// thread would cause some of it.
+//
+// -determineUpdateStatusAsync is called on the main thread to initiate the
+// operation.  It performs initial set-up work that must be done on the main
+// thread and arranges for -determineUpdateStatus to be called on a work queue
+// thread managed by WorkerPool.
+// -determineUpdateStatus then reads the Info.plist, gets the version from the
+// CFBundleShortVersionString key, and performs
+// -determineUpdateStatusForVersion: on the main thread.
+// -determineUpdateStatusForVersion: does the actual comparison of the version
+// on disk with the running version and calls -updateStatus:version: with the
+// results of its analysis.
+- (void)determineUpdateStatusAsync;
+- (void)determineUpdateStatus;
+- (void)determineUpdateStatusForVersion:(NSString*)version;
+
+// Returns YES if registration_ is definitely on a user ticket.  If definitely
+// on a system ticket, or uncertain of ticket type (due to an older version
+// of Keystone being used), returns NO.
+- (BOOL)isUserTicket;
+
+// Called when ticket promotion completes.
+- (void)promotionComplete:(NSNotification*)notification;
+
+// Changes the application's ownership and permissions so that all files are
+// owned by root:wheel and all files and directories are writable only by
+// root, but readable and executable as needed by everyone.
+// -changePermissionsForPromotionAsync is called on the main thread by
+// -promotionComplete.  That routine calls
+// -changePermissionsForPromotionWithTool: on a work queue thread.  When done,
+// -changePermissionsForPromotionComplete is called on the main thread.
+- (void)changePermissionsForPromotionAsync;
+- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath;
+- (void)changePermissionsForPromotionComplete;
+
+// Returns the brand file path to use for Keystone.
+- (NSString*)brandFilePath;
+
+@end  // @interface KeystoneGlue(Private)
+
+NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification";
+NSString* const kAutoupdateStatusStatus = @"status";
+NSString* const kAutoupdateStatusVersion = @"version";
+
+namespace {
+
+NSString* const kChannelKey = @"KSChannelID";
+NSString* const kBrandKey = @"KSBrandID";
+
+}  // namespace
+
+@implementation KeystoneGlue
+
++ (id)defaultKeystoneGlue {
+  static bool sTriedCreatingDefaultKeystoneGlue = false;
+  // TODO(jrg): use base::SingletonObjC<KeystoneGlue>
+  static KeystoneGlue* sDefaultKeystoneGlue = nil;  // leaked
+
+  if (!sTriedCreatingDefaultKeystoneGlue) {
+    sTriedCreatingDefaultKeystoneGlue = true;
+
+    sDefaultKeystoneGlue = [[KeystoneGlue alloc] init];
+    [sDefaultKeystoneGlue loadParameters];
+    if (![sDefaultKeystoneGlue loadKeystoneRegistration]) {
+      [sDefaultKeystoneGlue release];
+      sDefaultKeystoneGlue = nil;
+    }
+  }
+  return sDefaultKeystoneGlue;
+}
+
+- (id)init {
+  if ((self = [super init])) {
+    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+
+    [center addObserver:self
+               selector:@selector(registrationComplete:)
+                   name:KSRegistrationDidCompleteNotification
+                 object:nil];
+
+    [center addObserver:self
+               selector:@selector(promotionComplete:)
+                   name:KSRegistrationPromotionDidCompleteNotification
+                 object:nil];
+
+    [center addObserver:self
+               selector:@selector(checkForUpdateComplete:)
+                   name:KSRegistrationCheckForUpdateNotification
+                 object:nil];
+
+    [center addObserver:self
+               selector:@selector(installUpdateComplete:)
+                   name:KSRegistrationStartUpdateNotification
+                 object:nil];
+  }
+
+  return self;
+}
+
+- (void)dealloc {
+  [productID_ release];
+  [appPath_ release];
+  [url_ release];
+  [version_ release];
+  [channel_ release];
+  [registration_ release];
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
+- (NSDictionary*)infoDictionary {
+  // Use [NSBundle mainBundle] to get the application's own bundle identifier
+  // and path, not the framework's.  For auto-update, the application is
+  // what's significant here: it's used to locate the outermost part of the
+  // application for the existence checker and other operations that need to
+  // see the entire application bundle.
+  return [[NSBundle mainBundle] infoDictionary];
+}
+
+- (void)loadParameters {
+  NSBundle* appBundle = [NSBundle mainBundle];
+  NSDictionary* infoDictionary = [self infoDictionary];
+
+  NSString* productID = [infoDictionary objectForKey:@"KSProductID"];
+  if (productID == nil) {
+    productID = [appBundle bundleIdentifier];
+  }
+
+  NSString* appPath = [appBundle bundlePath];
+  NSString* url = [infoDictionary objectForKey:@"KSUpdateURL"];
+  NSString* version = [infoDictionary objectForKey:@"KSVersion"];
+
+  if (!productID || !appPath || !url || !version) {
+    // If parameters required for Keystone are missing, don't use it.
+    return;
+  }
+
+  NSString* channel = [infoDictionary objectForKey:kChannelKey];
+  // The stable channel has no tag.  If updating to stable, remove the
+  // dev and beta tags since we've been "promoted".
+  if (channel == nil)
+    channel = KSRegistrationRemoveExistingTag;
+
+  productID_ = [productID retain];
+  appPath_ = [appPath retain];
+  url_ = [url retain];
+  version_ = [version retain];
+  channel_ = [channel retain];
+}
+
+- (NSString*)brandFilePath {
+  DCHECK(version_ != nil) << "-loadParameters must be called first";
+
+  if (brandFileType_ == kBrandFileTypeNotDetermined) {
+
+    // Default to none.
+    brandFileType_ = kBrandFileTypeNone;
+
+    // Having a channel means Dev/Beta, so there is no brand code to go with
+    // those.
+    if ([channel_ length] == 0) {
+
+      NSString* userBrandFile = UserBrandFilePath();
+      NSString* systemBrandFile = SystemBrandFilePath();
+
+      NSFileManager* fm = [NSFileManager defaultManager];
+
+      // If there is a system brand file, use it.
+      if ([fm fileExistsAtPath:systemBrandFile]) {
+        // System
+
+        // Use the system file that is there.
+        brandFileType_ = kBrandFileTypeSystem;
+
+        // Clean up any old user level file.
+        if ([fm fileExistsAtPath:userBrandFile]) {
+          [fm removeItemAtPath:userBrandFile error:NULL];
+        }
+
+      } else {
+        // User
+
+        NSDictionary* infoDictionary = [self infoDictionary];
+        NSString* appBundleBrandID = [infoDictionary objectForKey:kBrandKey];
+
+        NSString* storedBrandID = nil;
+        if ([fm fileExistsAtPath:userBrandFile]) {
+          NSDictionary* storedBrandDict =
+              [NSDictionary dictionaryWithContentsOfFile:userBrandFile];
+          storedBrandID = [storedBrandDict objectForKey:kBrandKey];
+        }
+
+        if ((appBundleBrandID != nil) &&
+            (![storedBrandID isEqualTo:appBundleBrandID])) {
+          // App and store don't match, update store and use it.
+          NSDictionary* storedBrandDict =
+              [NSDictionary dictionaryWithObject:appBundleBrandID
+                                          forKey:kBrandKey];
+          // If Keystone hasn't been installed yet, the location the brand file
+          // is written to won't exist, so manually create the directory.
+          NSString *userBrandFileDirectory =
+              [userBrandFile stringByDeletingLastPathComponent];
+          if (![fm fileExistsAtPath:userBrandFileDirectory]) {
+            if (![fm createDirectoryAtPath:userBrandFileDirectory
+               withIntermediateDirectories:YES
+                                attributes:nil
+                                     error:NULL]) {
+              LOG(ERROR) << "Failed to create the directory for the brand file";
+            }
+          }
+          if ([storedBrandDict writeToFile:userBrandFile atomically:YES]) {
+            brandFileType_ = kBrandFileTypeUser;
+          }
+        } else if (storedBrandID) {
+          // Had stored brand, use it.
+          brandFileType_ = kBrandFileTypeUser;
+        }
+      }
+    }
+
+  }
+
+  NSString* result = nil;
+  switch (brandFileType_) {
+    case kBrandFileTypeUser:
+      result = UserBrandFilePath();
+      break;
+
+    case kBrandFileTypeSystem:
+      result = SystemBrandFilePath();
+      break;
+
+    case kBrandFileTypeNotDetermined:
+      NOTIMPLEMENTED();
+      // Fall through
+    case kBrandFileTypeNone:
+      // Clear the value.
+      result = @"";
+      break;
+
+  }
+  return result;
+}
+
+- (BOOL)loadKeystoneRegistration {
+  if (!productID_ || !appPath_ || !url_ || !version_)
+    return NO;
+
+  // Load the KeystoneRegistration framework bundle if present.  It lives
+  // inside the framework, so use base::mac::MainAppBundle();
+  NSString* ksrPath =
+      [[base::mac::MainAppBundle() privateFrameworksPath]
+          stringByAppendingPathComponent:@"KeystoneRegistration.framework"];
+  NSBundle* ksrBundle = [NSBundle bundleWithPath:ksrPath];
+  [ksrBundle load];
+
+  // Harness the KSRegistration class.
+  Class ksrClass = [ksrBundle classNamed:@"KSRegistration"];
+  KSRegistration* ksr = [ksrClass registrationWithProductID:productID_];
+  if (!ksr)
+    return NO;
+
+  registration_ = [ksr retain];
+  return YES;
+}
+
+- (NSString*)appInfoPlistPath {
+  // NSBundle ought to have a way to access this path directly, but it
+  // doesn't.
+  return [[appPath_ stringByAppendingPathComponent:@"Contents"]
+             stringByAppendingPathComponent:@"Info.plist"];
+}
+
+- (NSDictionary*)keystoneParameters {
+  NSNumber* xcType = [NSNumber numberWithInt:kKSPathExistenceChecker];
+  NSNumber* preserveTTToken = [NSNumber numberWithBool:YES];
+  NSString* tagPath = [self appInfoPlistPath];
+
+  NSString* brandKey = kBrandKey;
+  NSString* brandPath = [self brandFilePath];
+
+  if ([brandPath length] == 0) {
+    // Brand path and brand key must be cleared together or ksadmin seems
+    // to throw an error.
+    brandKey = @"";
+  }
+
+  return [NSDictionary dictionaryWithObjectsAndKeys:
+             version_, KSRegistrationVersionKey,
+             xcType, KSRegistrationExistenceCheckerTypeKey,
+             appPath_, KSRegistrationExistenceCheckerStringKey,
+             url_, KSRegistrationServerURLStringKey,
+             preserveTTToken, KSRegistrationPreserveTrustedTesterTokenKey,
+             channel_, KSRegistrationTagKey,
+             tagPath, KSRegistrationTagPathKey,
+             kChannelKey, KSRegistrationTagKeyKey,
+             brandPath, KSRegistrationBrandPathKey,
+             brandKey, KSRegistrationBrandKeyKey,
+             nil];
+}
+
+- (void)registerWithKeystone {
+  [self updateStatus:kAutoupdateRegistering version:nil];
+
+  NSDictionary* parameters = [self keystoneParameters];
+  if (![registration_ registerWithParameters:parameters]) {
+    [self updateStatus:kAutoupdateRegisterFailed version:nil];
+    return;
+  }
+
+  // Upon completion, KSRegistrationDidCompleteNotification will be posted,
+  // and -registrationComplete: will be called.
+
+  // Mark an active RIGHT NOW; don't wait an hour for the first one.
+  [registration_ setActive];
+
+  // Set up hourly activity pings.
+  timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60  // One hour
+                                            target:self
+                                          selector:@selector(markActive:)
+                                          userInfo:registration_
+                                           repeats:YES];
+}
+
+- (void)registrationComplete:(NSNotification*)notification {
+  NSDictionary* userInfo = [notification userInfo];
+  if ([[userInfo objectForKey:KSRegistrationStatusKey] boolValue]) {
+    [self updateStatus:kAutoupdateRegistered version:nil];
+  } else {
+    // Dump registration_?
+    [self updateStatus:kAutoupdateRegisterFailed version:nil];
+  }
+}
+
+- (void)stopTimer {
+  [timer_ invalidate];
+}
+
+- (void)markActive:(NSTimer*)timer {
+  KSRegistration* ksr = [timer userInfo];
+  [ksr setActive];
+}
+
+- (void)checkForUpdate {
+  DCHECK(![self asyncOperationPending]);
+
+  if (!registration_) {
+    [self updateStatus:kAutoupdateCheckFailed version:nil];
+    return;
+  }
+
+  [self updateStatus:kAutoupdateChecking version:nil];
+
+  [registration_ checkForUpdate];
+
+  // Upon completion, KSRegistrationCheckForUpdateNotification will be posted,
+  // and -checkForUpdateComplete: will be called.
+}
+
+- (void)checkForUpdateComplete:(NSNotification*)notification {
+  NSDictionary* userInfo = [notification userInfo];
+
+  if ([[userInfo objectForKey:KSRegistrationUpdateCheckErrorKey] boolValue]) {
+    [self updateStatus:kAutoupdateCheckFailed version:nil];
+  } else if ([[userInfo objectForKey:KSRegistrationStatusKey] boolValue]) {
+    // If an update is known to be available, go straight to
+    // -updateStatus:version:.  It doesn't matter what's currently on disk.
+    NSString* version = [userInfo objectForKey:KSRegistrationVersionKey];
+    [self updateStatus:kAutoupdateAvailable version:version];
+  } else {
+    // If no updates are available, check what's on disk, because an update
+    // may have already been installed.  This check happens on another thread,
+    // and -updateStatus:version: will be called on the main thread when done.
+    [self determineUpdateStatusAsync];
+  }
+}
+
+- (void)installUpdate {
+  DCHECK(![self asyncOperationPending]);
+
+  if (!registration_) {
+    [self updateStatus:kAutoupdateInstallFailed version:nil];
+    return;
+  }
+
+  [self updateStatus:kAutoupdateInstalling version:nil];
+
+  [registration_ startUpdate];
+
+  // Upon completion, KSRegistrationStartUpdateNotification will be posted,
+  // and -installUpdateComplete: will be called.
+}
+
+- (void)installUpdateComplete:(NSNotification*)notification {
+  NSDictionary* userInfo = [notification userInfo];
+
+  if (![[userInfo objectForKey:KSUpdateCheckSuccessfulKey] boolValue] ||
+      ![[userInfo objectForKey:KSUpdateCheckSuccessfullyInstalledKey]
+          intValue]) {
+    [self updateStatus:kAutoupdateInstallFailed version:nil];
+  } else {
+    updateSuccessfullyInstalled_ = YES;
+
+    // Nothing in the notification dictionary reports the version that was
+    // installed.  Figure it out based on what's on disk.
+    [self determineUpdateStatusAsync];
+  }
+}
+
+- (NSString*)currentlyInstalledVersion {
+  NSString* appInfoPlistPath = [self appInfoPlistPath];
+  NSDictionary* infoPlist =
+      [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath];
+  return [infoPlist objectForKey:@"CFBundleShortVersionString"];
+}
+
+// Runs on the main thread.
+- (void)determineUpdateStatusAsync {
+  DCHECK([NSThread isMainThread]);
+
+  PerformBridge::PostPerform(self, @selector(determineUpdateStatus));
+}
+
+// Runs on a thread managed by WorkerPool.
+- (void)determineUpdateStatus {
+  DCHECK(![NSThread isMainThread]);
+
+  NSString* version = [self currentlyInstalledVersion];
+
+  [self performSelectorOnMainThread:@selector(determineUpdateStatusForVersion:)
+                         withObject:version
+                      waitUntilDone:NO];
+}
+
+// Runs on the main thread.
+- (void)determineUpdateStatusForVersion:(NSString*)version {
+  DCHECK([NSThread isMainThread]);
+
+  AutoupdateStatus status;
+  if (updateSuccessfullyInstalled_) {
+    // If an update was successfully installed and this object saw it happen,
+    // then don't even bother comparing versions.
+    status = kAutoupdateInstalled;
+  } else {
+    NSString* currentVersion =
+        [NSString stringWithUTF8String:chrome::kChromeVersion];
+    if (!version) {
+      // If the version on disk could not be determined, assume that
+      // whatever's running is current.
+      version = currentVersion;
+      status = kAutoupdateCurrent;
+    } else if ([version isEqualToString:currentVersion]) {
+      status = kAutoupdateCurrent;
+    } else {
+      // If the version on disk doesn't match what's currently running, an
+      // update must have been applied in the background, without this app's
+      // direct participation.  Leave updateSuccessfullyInstalled_ alone
+      // because there's no direct knowledge of what actually happened.
+      status = kAutoupdateInstalled;
+    }
+  }
+
+  [self updateStatus:status version:version];
+}
+
+- (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version {
+  NSNumber* statusNumber = [NSNumber numberWithInt:status];
+  NSMutableDictionary* dictionary =
+      [NSMutableDictionary dictionaryWithObject:statusNumber
+                                         forKey:kAutoupdateStatusStatus];
+  if (version) {
+    [dictionary setObject:version forKey:kAutoupdateStatusVersion];
+  }
+
+  NSNotification* notification =
+      [NSNotification notificationWithName:kAutoupdateStatusNotification
+                                    object:self
+                                  userInfo:dictionary];
+  recentNotification_.reset([notification retain]);
+
+  [[NSNotificationCenter defaultCenter] postNotification:notification];
+}
+
+- (NSNotification*)recentNotification {
+  return [[recentNotification_ retain] autorelease];
+}
+
+- (AutoupdateStatus)recentStatus {
+  NSDictionary* dictionary = [recentNotification_ userInfo];
+  return static_cast<AutoupdateStatus>(
+      [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
+}
+
+- (BOOL)asyncOperationPending {
+  AutoupdateStatus status = [self recentStatus];
+  return status == kAutoupdateRegistering ||
+         status == kAutoupdateChecking ||
+         status == kAutoupdateInstalling ||
+         status == kAutoupdatePromoting;
+}
+
+- (BOOL)isUserTicket {
+  return [registration_ ticketType] == kKSRegistrationUserTicket;
+}
+
+- (BOOL)isOnReadOnlyFilesystem {
+  const char* appPathC = [appPath_ fileSystemRepresentation];
+  struct statfs statfsBuf;
+
+  if (statfs(appPathC, &statfsBuf) != 0) {
+    PLOG(ERROR) << "statfs";
+    // Be optimistic about the filesystem's writability.
+    return NO;
+  }
+
+  return (statfsBuf.f_flags & MNT_RDONLY) != 0;
+}
+
+- (BOOL)needsPromotion {
+  if (![self isUserTicket] || [self isOnReadOnlyFilesystem]) {
+    return NO;
+  }
+
+  // Check the outermost bundle directory, the main executable path, and the
+  // framework directory.  It may be enough to just look at the outermost
+  // bundle directory, but checking an interior file and directory can be
+  // helpful in case permissions are set differently only on the outermost
+  // directory.  An interior file and directory are both checked because some
+  // file operations, such as Snow Leopard's Finder's copy operation when
+  // authenticating, may actually result in different ownership being applied
+  // to files and directories.
+  NSFileManager* fileManager = [NSFileManager defaultManager];
+  NSString* executablePath = [[NSBundle mainBundle] executablePath];
+  NSString* frameworkPath = [base::mac::MainAppBundle() bundlePath];
+  return ![fileManager isWritableFileAtPath:appPath_] ||
+         ![fileManager isWritableFileAtPath:executablePath] ||
+         ![fileManager isWritableFileAtPath:frameworkPath];
+}
+
+- (BOOL)wantsPromotion {
+  // -needsPromotion checks these too, but this method doesn't necessarily
+  // return NO just becuase -needsPromotion returns NO, so another check is
+  // needed here.
+  if (![self isUserTicket] || [self isOnReadOnlyFilesystem]) {
+    return NO;
+  }
+
+  if ([self needsPromotion]) {
+    return YES;
+  }
+
+  return [appPath_ hasPrefix:@"/Applications/"];
+}
+
+- (void)promoteTicket {
+  if ([self asyncOperationPending] || ![self wantsPromotion]) {
+    // Because there are multiple ways of reaching promoteTicket that might
+    // not lock each other out, it may be possible to arrive here while an
+    // asynchronous operation is pending, or even after promotion has already
+    // occurred.  Just quietly return without doing anything.
+    return;
+  }
+
+  NSString* prompt = l10n_util::GetNSStringFWithFixup(
+      IDS_PROMOTE_AUTHENTICATION_PROMPT,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  scoped_AuthorizationRef authorization(
+      authorization_util::AuthorizationCreateToRunAsRoot(
+          reinterpret_cast<CFStringRef>(prompt)));
+  if (!authorization.get()) {
+    return;
+  }
+
+  [self promoteTicketWithAuthorization:authorization.release() synchronous:NO];
+}
+
+- (void)promoteTicketWithAuthorization:(AuthorizationRef)authorization_arg
+                           synchronous:(BOOL)synchronous {
+  scoped_AuthorizationRef authorization(authorization_arg);
+  authorization_arg = NULL;
+
+  if ([self asyncOperationPending]) {
+    // Starting a synchronous operation while an asynchronous one is pending
+    // could be trouble.
+    return;
+  }
+  if (!synchronous && ![self wantsPromotion]) {
+    // If operating synchronously, the call came from the installer, which
+    // means that a system ticket is required.  Otherwise, only allow
+    // promotion if it's wanted.
+    return;
+  }
+
+  synchronousPromotion_ = synchronous;
+
+  [self updateStatus:kAutoupdatePromoting version:nil];
+
+  // TODO(mark): Remove when able!
+  //
+  // keystone_promote_preflight will copy the current brand information out to
+  // the system level so all users can share the data as part of the ticket
+  // promotion.
+  //
+  // It will also ensure that the Keystone system ticket store is in a usable
+  // state for all users on the system.  Ideally, Keystone's installer or
+  // another part of Keystone would handle this.  The underlying problem is
+  // http://b/2285921, and it causes http://b/2289908, which this workaround
+  // addresses.
+  //
+  // This is run synchronously, which isn't optimal, but
+  // -[KSRegistration promoteWithParameters:authorization:] is currently
+  // synchronous too, and this operation needs to happen before that one.
+  //
+  // TODO(mark): Make asynchronous.  That only makes sense if the promotion
+  // operation itself is asynchronous too.  http://b/2290009.  Hopefully,
+  // the Keystone promotion code will just be changed to do what preflight
+  // now does, and then the preflight script can be removed instead.
+  // However, preflight operation (and promotion) should only be asynchronous
+  // if the synchronous parameter is NO.
+  NSString* preflightPath =
+      [base::mac::MainAppBundle() pathForResource:@"keystone_promote_preflight"
+                                          ofType:@"sh"];
+  const char* preflightPathC = [preflightPath fileSystemRepresentation];
+  const char* userBrandFile = NULL;
+  const char* systemBrandFile = NULL;
+  if (brandFileType_ == kBrandFileTypeUser) {
+    // Running with user level brand file, promote to the system level.
+    userBrandFile = [UserBrandFilePath() fileSystemRepresentation];
+    systemBrandFile = [SystemBrandFilePath() fileSystemRepresentation];
+  }
+  const char* arguments[] = {userBrandFile, systemBrandFile, NULL};
+
+  int exit_status;
+  OSStatus status = authorization_util::ExecuteWithPrivilegesAndWait(
+      authorization,
+      preflightPathC,
+      kAuthorizationFlagDefaults,
+      arguments,
+      NULL,  // pipe
+      &exit_status);
+  if (status != errAuthorizationSuccess) {
+    LOG(ERROR) << "AuthorizationExecuteWithPrivileges preflight: " << status;
+    [self updateStatus:kAutoupdatePromoteFailed version:nil];
+    return;
+  }
+  if (exit_status != 0) {
+    LOG(ERROR) << "keystone_promote_preflight status " << exit_status;
+    [self updateStatus:kAutoupdatePromoteFailed version:nil];
+    return;
+  }
+
+  // Hang on to the AuthorizationRef so that it can be used once promotion is
+  // complete.  Do this before asking Keystone to promote the ticket, because
+  // -promotionComplete: may be called from inside the Keystone promotion
+  // call.
+  authorization_.swap(authorization);
+
+  NSDictionary* parameters = [self keystoneParameters];
+
+  // If the brand file is user level, update parameters to point to the new
+  // system level file during promotion.
+  if (brandFileType_ == kBrandFileTypeUser) {
+    NSMutableDictionary* temp_parameters =
+        [[parameters mutableCopy] autorelease];
+    [temp_parameters setObject:SystemBrandFilePath()
+                        forKey:KSRegistrationBrandPathKey];
+    parameters = temp_parameters;
+  }
+
+  if (![registration_ promoteWithParameters:parameters
+                              authorization:authorization_]) {
+    [self updateStatus:kAutoupdatePromoteFailed version:nil];
+    authorization_.reset();
+    return;
+  }
+
+  // Upon completion, KSRegistrationPromotionDidCompleteNotification will be
+  // posted, and -promotionComplete: will be called.
+}
+
+- (void)promotionComplete:(NSNotification*)notification {
+  NSDictionary* userInfo = [notification userInfo];
+  if ([[userInfo objectForKey:KSRegistrationStatusKey] boolValue]) {
+    if (synchronousPromotion_) {
+      // Short-circuit: if performing a synchronous promotion, the promotion
+      // came from the installer, which already set the permissions properly.
+      // Rather than run a duplicate permission-changing operation, jump
+      // straight to "done."
+      [self changePermissionsForPromotionComplete];
+    } else {
+      [self changePermissionsForPromotionAsync];
+    }
+  } else {
+    authorization_.reset();
+    [self updateStatus:kAutoupdatePromoteFailed version:nil];
+  }
+}
+
+- (void)changePermissionsForPromotionAsync {
+  // NSBundle is not documented as being thread-safe.  Do NSBundle operations
+  // on the main thread before jumping over to a WorkerPool-managed
+  // thread to run the tool.
+  DCHECK([NSThread isMainThread]);
+
+  SEL selector = @selector(changePermissionsForPromotionWithTool:);
+  NSString* toolPath =
+      [base::mac::MainAppBundle() pathForResource:@"keystone_promote_postflight"
+                                          ofType:@"sh"];
+
+  PerformBridge::PostPerform(self, selector, toolPath);
+}
+
+- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath {
+  const char* toolPathC = [toolPath fileSystemRepresentation];
+
+  const char* appPathC = [appPath_ fileSystemRepresentation];
+  const char* arguments[] = {appPathC, NULL};
+
+  int exit_status;
+  OSStatus status = authorization_util::ExecuteWithPrivilegesAndWait(
+      authorization_,
+      toolPathC,
+      kAuthorizationFlagDefaults,
+      arguments,
+      NULL,  // pipe
+      &exit_status);
+  if (status != errAuthorizationSuccess) {
+    LOG(ERROR) << "AuthorizationExecuteWithPrivileges postflight: " << status;
+  } else if (exit_status != 0) {
+    LOG(ERROR) << "keystone_promote_postflight status " << exit_status;
+  }
+
+  SEL selector = @selector(changePermissionsForPromotionComplete);
+  [self performSelectorOnMainThread:selector
+                         withObject:nil
+                      waitUntilDone:NO];
+}
+
+- (void)changePermissionsForPromotionComplete {
+  authorization_.reset();
+
+  [self updateStatus:kAutoupdatePromoted version:nil];
+}
+
+- (void)setAppPath:(NSString*)appPath {
+  if (appPath != appPath_) {
+    [appPath_ release];
+    appPath_ = [appPath copy];
+  }
+}
+
+@end  // @implementation KeystoneGlue
+
+namespace keystone_glue {
+
+bool KeystoneEnabled() {
+  return [KeystoneGlue defaultKeystoneGlue] != nil;
+}
+
+string16 CurrentlyInstalledVersion() {
+  KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
+  NSString* version = [keystoneGlue currentlyInstalledVersion];
+  return base::SysNSStringToUTF16(version);
+}
+
+}  // namespace keystone_glue
diff --git a/chrome/browser/cocoa/keystone_glue_unittest.mm b/chrome/browser/cocoa/keystone_glue_unittest.mm
new file mode 100644
index 0000000..9d49a09
--- /dev/null
+++ b/chrome/browser/cocoa/keystone_glue_unittest.mm
@@ -0,0 +1,184 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+#import <objc/objc-class.h>
+
+#import "chrome/browser/cocoa/keystone_glue.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface FakeGlueRegistration : NSObject
+@end
+
+
+@implementation FakeGlueRegistration
+
+// Send the notifications that a real KeystoneGlue object would send.
+
+- (void)checkForUpdate {
+  NSNumber* yesNumber = [NSNumber numberWithBool:YES];
+  NSString* statusKey = @"Status";
+  NSDictionary* dictionary = [NSDictionary dictionaryWithObject:yesNumber
+                                                         forKey:statusKey];
+  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+  [center postNotificationName:@"KSRegistrationCheckForUpdateNotification"
+                        object:nil
+                      userInfo:dictionary];
+}
+
+- (void)startUpdate {
+  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+  [center postNotificationName:@"KSRegistrationStartUpdateNotification"
+                        object:nil];
+}
+
+@end
+
+
+@interface FakeKeystoneGlue : KeystoneGlue {
+ @public
+  BOOL upToDate_;
+  NSString *latestVersion_;
+  BOOL successful_;
+  int installs_;
+}
+
+- (void)fakeAboutWindowCallback:(NSNotification*)notification;
+@end
+
+
+@implementation FakeKeystoneGlue
+
+- (id)init {
+  if ((self = [super init])) {
+    // some lies
+    upToDate_ = YES;
+    latestVersion_ = @"foo bar";
+    successful_ = YES;
+    installs_ = 1010101010;
+
+    // Set up an observer that takes the notification that the About window
+    // listens for.
+    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+    [center addObserver:self
+               selector:@selector(fakeAboutWindowCallback:)
+                   name:kAutoupdateStatusNotification
+                 object:nil];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
+// For mocking
+- (NSDictionary*)infoDictionary {
+  NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
+                                     @"http://foo.bar", @"KSUpdateURL",
+                                     @"com.google.whatever", @"KSProductID",
+                                     @"0.0.0.1", @"KSVersion",
+                                     nil];
+  return dict;
+}
+
+// For mocking
+- (BOOL)loadKeystoneRegistration {
+  return YES;
+}
+
+// Confirms certain things are happy
+- (BOOL)dictReadCorrectly {
+  return ([url_ isEqual:@"http://foo.bar"] &&
+          [productID_ isEqual:@"com.google.whatever"] &&
+          [version_ isEqual:@"0.0.0.1"]);
+}
+
+// Confirms certain things are happy
+- (BOOL)hasATimer {
+  return timer_ ? YES : NO;
+}
+
+- (void)addFakeRegistration {
+  registration_ = [[FakeGlueRegistration alloc] init];
+}
+
+- (void)fakeAboutWindowCallback:(NSNotification*)notification {
+  NSDictionary* dictionary = [notification userInfo];
+  AutoupdateStatus status = static_cast<AutoupdateStatus>(
+      [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
+
+  if (status == kAutoupdateAvailable) {
+    upToDate_ = NO;
+    latestVersion_ = [dictionary objectForKey:kAutoupdateStatusVersion];
+  } else if (status == kAutoupdateInstallFailed) {
+    successful_ = NO;
+    installs_ = 0;
+  }
+}
+
+// Confirm we look like callbacks with nil NSNotifications
+- (BOOL)confirmCallbacks {
+  return (!upToDate_ &&
+          (latestVersion_ == nil) &&
+          !successful_ &&
+          (installs_ == 0));
+}
+
+@end
+
+
+namespace {
+
+class KeystoneGlueTest : public PlatformTest {
+};
+
+// DISABLED because the mocking isn't currently working.
+TEST_F(KeystoneGlueTest, DISABLED_BasicGlobalCreate) {
+  // Allow creation of a KeystoneGlue by mocking out a few calls
+  SEL ids = @selector(infoDictionary);
+  IMP oldInfoImp_ = [[KeystoneGlue class] instanceMethodForSelector:ids];
+  IMP newInfoImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:ids];
+  Method infoMethod_ = class_getInstanceMethod([KeystoneGlue class], ids);
+  method_setImplementation(infoMethod_, newInfoImp_);
+
+  SEL lks = @selector(loadKeystoneRegistration);
+  IMP oldLoadImp_ = [[KeystoneGlue class] instanceMethodForSelector:lks];
+  IMP newLoadImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:lks];
+  Method loadMethod_ = class_getInstanceMethod([KeystoneGlue class], lks);
+  method_setImplementation(loadMethod_, newLoadImp_);
+
+  KeystoneGlue *glue = [KeystoneGlue defaultKeystoneGlue];
+  ASSERT_TRUE(glue);
+
+  // Fix back up the class to the way we found it.
+  method_setImplementation(infoMethod_, oldInfoImp_);
+  method_setImplementation(loadMethod_, oldLoadImp_);
+}
+
+// DISABLED because the mocking isn't currently working.
+TEST_F(KeystoneGlueTest, DISABLED_BasicUse) {
+  FakeKeystoneGlue* glue = [[[FakeKeystoneGlue alloc] init] autorelease];
+  [glue loadParameters];
+  ASSERT_TRUE([glue dictReadCorrectly]);
+
+  // Likely returns NO in the unit test, but call it anyway to make
+  // sure it doesn't crash.
+  [glue loadKeystoneRegistration];
+
+  // Confirm we start up an active timer
+  [glue registerWithKeystone];
+  ASSERT_TRUE([glue hasATimer]);
+  [glue stopTimer];
+
+  // Brief exercise of callbacks
+  [glue addFakeRegistration];
+  [glue checkForUpdate];
+  [glue installUpdate];
+  ASSERT_TRUE([glue confirmCallbacks]);
+}
+
+}  // namespace
diff --git a/chrome/browser/cocoa/scoped_authorizationref.h b/chrome/browser/cocoa/scoped_authorizationref.h
new file mode 100644
index 0000000..3ffa18b
--- /dev/null
+++ b/chrome/browser/cocoa/scoped_authorizationref.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COCOA_SCOPED_AUTHORIZATIONREF_H_
+#define CHROME_BROWSER_COCOA_SCOPED_AUTHORIZATIONREF_H_
+#pragma once
+
+#include <Security/Authorization.h>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+// scoped_AuthorizationRef maintains ownership of an AuthorizationRef.  It is
+// patterned after the scoped_ptr interface.
+
+class scoped_AuthorizationRef {
+ public:
+  explicit scoped_AuthorizationRef(AuthorizationRef authorization = NULL)
+      : authorization_(authorization) {
+  }
+
+  ~scoped_AuthorizationRef() {
+    if (authorization_) {
+      AuthorizationFree(authorization_, kAuthorizationFlagDestroyRights);
+    }
+  }
+
+  void reset(AuthorizationRef authorization = NULL) {
+    if (authorization_ != authorization) {
+      if (authorization_) {
+        AuthorizationFree(authorization_, kAuthorizationFlagDestroyRights);
+      }
+      authorization_ = authorization;
+    }
+  }
+
+  bool operator==(AuthorizationRef that) const {
+    return authorization_ == that;
+  }
+
+  bool operator!=(AuthorizationRef that) const {
+    return authorization_ != that;
+  }
+
+  operator AuthorizationRef() const {
+    return authorization_;
+  }
+
+  AuthorizationRef* operator&() {
+    return &authorization_;
+  }
+
+  AuthorizationRef get() const {
+    return authorization_;
+  }
+
+  void swap(scoped_AuthorizationRef& that) {
+    AuthorizationRef temp = that.authorization_;
+    that.authorization_ = authorization_;
+    authorization_ = temp;
+  }
+
+  // scoped_AuthorizationRef::release() is like scoped_ptr<>::release.  It is
+  // NOT a wrapper for AuthorizationFree().  To force a
+  // scoped_AuthorizationRef object to call AuthorizationFree(), use
+  // scoped_AuthorizaitonRef::reset().
+  AuthorizationRef release() WARN_UNUSED_RESULT {
+    AuthorizationRef temp = authorization_;
+    authorization_ = NULL;
+    return temp;
+  }
+
+ private:
+  AuthorizationRef authorization_;
+
+  DISALLOW_COPY_AND_ASSIGN(scoped_AuthorizationRef);
+};
+
+#endif  // CHROME_BROWSER_COCOA_SCOPED_AUTHORIZATIONREF_H_
diff --git a/chrome/browser/collected_cookies_uitest.cc b/chrome/browser/collected_cookies_uitest.cc
index 6c241ce..ce60e04 100644
--- a/chrome/browser/collected_cookies_uitest.cc
+++ b/chrome/browser/collected_cookies_uitest.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/browser_proxy.h"
diff --git a/chrome/browser/content_exceptions_table_model.cc b/chrome/browser/content_exceptions_table_model.cc
index 6eecfaa..8383c2f 100644
--- a/chrome/browser/content_exceptions_table_model.cc
+++ b/chrome/browser/content_exceptions_table_model.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/content_exceptions_table_model.h"
 
-#include "app/l10n_util.h"
-#include "app/table_model_observer.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
 
 ContentExceptionsTableModel::ContentExceptionsTableModel(
     HostContentSettingsMap* map,
@@ -129,6 +129,7 @@
   return string16();
 }
 
-void ContentExceptionsTableModel::SetObserver(TableModelObserver* observer) {
+void ContentExceptionsTableModel::SetObserver(
+    ui::TableModelObserver* observer) {
   observer_ = observer;
 }
diff --git a/chrome/browser/content_exceptions_table_model.h b/chrome/browser/content_exceptions_table_model.h
index a8371fe..b96f9ca 100644
--- a/chrome/browser/content_exceptions_table_model.h
+++ b/chrome/browser/content_exceptions_table_model.h
@@ -8,14 +8,14 @@
 
 #include <string>
 
-#include "app/table_model.h"
 #include "base/compiler_specific.h"
 #include "base/ref_counted.h"
 #include "chrome/common/content_settings.h"
 #include "chrome/common/content_settings_types.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "ui/base/models/table_model.h"
 
-class ContentExceptionsTableModel : public TableModel {
+class ContentExceptionsTableModel : public ui::TableModel {
  public:
   ContentExceptionsTableModel(HostContentSettingsMap* map,
                               HostContentSettingsMap* off_the_record_map,
@@ -56,7 +56,7 @@
   // TableModel overrides:
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
  private:
   HostContentSettingsMap* map(bool is_off_the_record) {
@@ -71,7 +71,7 @@
   ContentSettingsType content_type_;
   HostContentSettingsMap::SettingsForOneType entries_;
   HostContentSettingsMap::SettingsForOneType off_the_record_entries_;
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentExceptionsTableModel);
 };
diff --git a/chrome/browser/content_setting_bubble_model.cc b/chrome/browser/content_setting_bubble_model.cc
index 71889d8..c6f7a8e 100644
--- a/chrome/browser/content_setting_bubble_model.cc
+++ b/chrome/browser/content_setting_bubble_model.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/content_setting_bubble_model.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/blocked_content_container.h"
@@ -17,11 +16,11 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/tab_specific_content_settings.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 class ContentSettingTitleAndLinkModel : public ContentSettingBubbleModel {
  public:
diff --git a/chrome/browser/content_setting_combo_model.cc b/chrome/browser/content_setting_combo_model.cc
index 3606587..8519ecc 100644
--- a/chrome/browser/content_setting_combo_model.cc
+++ b/chrome/browser/content_setting_combo_model.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/content_setting_combo_model.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/string16.h"
 #include "chrome/common/chrome_switches.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/content_setting_combo_model.h b/chrome/browser/content_setting_combo_model.h
index 3aec600..274285f 100644
--- a/chrome/browser/content_setting_combo_model.h
+++ b/chrome/browser/content_setting_combo_model.h
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_CONTENT_SETTING_COMBO_MODEL_H_
 #pragma once
 
-#include "app/combobox_model.h"
-
 #include "base/basictypes.h"
 #include "base/string16.h"
 #include "chrome/common/content_settings.h"
+#include "ui/base/models/combobox_model.h"
 
-class ContentSettingComboModel : public ComboboxModel {
+class ContentSettingComboModel : public ui::ComboboxModel {
  public:
   explicit ContentSettingComboModel(ContentSettingsType content_type);
   virtual ~ContentSettingComboModel();
diff --git a/chrome/browser/content_setting_image_model.cc b/chrome/browser/content_setting_image_model.cc
index 4aeea3a..e67f721 100644
--- a/chrome/browser/content_setting_image_model.cc
+++ b/chrome/browser/content_setting_image_model.cc
@@ -4,14 +4,13 @@
 
 #include "chrome/browser/content_setting_image_model.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_switches.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 class ContentSettingBlockedImageModel : public ContentSettingImageModel {
  public:
diff --git a/chrome/browser/content_settings/content_settings_pattern.h b/chrome/browser/content_settings/content_settings_pattern.h
index 330042f..344d31e 100644
--- a/chrome/browser/content_settings/content_settings_pattern.h
+++ b/chrome/browser/content_settings/content_settings_pattern.h
@@ -8,6 +8,7 @@
 #define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PATTERN_H_
 #pragma once
 
+#include <ostream>
 #include <string>
 
 class GURL;
diff --git a/chrome/browser/content_settings/content_settings_provider.h b/chrome/browser/content_settings/content_settings_provider.h
index 2754bfc..621c522 100644
--- a/chrome/browser/content_settings/content_settings_provider.h
+++ b/chrome/browser/content_settings/content_settings_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,15 +8,19 @@
 #define CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PROVIDER_H_
 #pragma once
 
+#include <string>
+#include <vector>
+
+#include "chrome/browser/content_settings/content_settings_pattern.h"
 #include "chrome/common/content_settings.h"
 
-class ContentSettingsProviderInterface {
- public:
-  virtual ~ContentSettingsProviderInterface() {}
+class GURL;
 
-  // True if this provider can provide a default setting for the |content_type|.
-  virtual bool CanProvideDefaultSetting(
-      ContentSettingsType content_type) const = 0;
+namespace content_settings {
+
+class DefaultProviderInterface {
+ public:
+  virtual ~DefaultProviderInterface() {}
 
   // Returns the default content setting this provider has for the given
   // |content_type|, or CONTENT_SETTING_DEFAULT if nothing be provided for this
@@ -39,4 +43,82 @@
       ContentSettingsType content_type) const = 0;
 };
 
+class ProviderInterface {
+ public:
+  typedef std::string ResourceIdentifier;
+
+  struct Rule {
+    Rule() {}
+    Rule(const ContentSettingsPattern& requesting_pattern,
+         const ContentSettingsPattern& embedding_pattern,
+         ContentSetting setting)
+      : requesting_url_pattern(requesting_pattern),
+        embedding_url_pattern(embedding_pattern),
+        content_setting(setting) {}
+
+    ContentSettingsPattern requesting_url_pattern;
+    ContentSettingsPattern embedding_url_pattern;
+    ContentSetting content_setting;
+  };
+
+  typedef std::vector<Rule> Rules;
+
+  virtual ~ProviderInterface() {}
+
+  // Returns a single ContentSetting which applies to a given |requesting_url|,
+  // |embedding_url| pair or CONTENT_SETTING_DEFAULT, if no rule applies. For
+  // ContentSettingsTypes that require a resource identifier to be specified,
+  // the |resource_identifier| must be non-empty.
+  //
+  // This may be called on any thread.
+  virtual ContentSetting GetContentSetting(
+      const GURL& requesting_url,
+      const GURL& embedding_url,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) const = 0;
+
+  // Sets the content setting for a particular |requesting_pattern|,
+  // |embedding_pattern|, |content_type| tuple. For ContentSettingsTypes that
+  // require a resource identifier to be specified, the |resource_identifier|
+  // must be non-empty.
+  //
+  // This should only be called on the UI thread.
+  virtual void SetContentSetting(
+      const ContentSettingsPattern& requesting_url_pattern,
+      const ContentSettingsPattern& embedding_url_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      ContentSetting content_setting) = 0;
+
+  // For a given content type, returns all content setting rules with a
+  // non-default setting, mapped to their actual settings.
+  // |content_settings_rules| must be non-NULL. If this provider was created for
+  // the off-the-record profile, it will only return those settings differing
+  // from the corresponding regular provider. For ContentSettingsTypes that
+  // require a resource identifier to be specified, the |resource_identifier|
+  // must be non-empty.
+  //
+  // This may be called on any thread.
+  virtual void GetAllContentSettingsRules(
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      Rules* content_setting_rules) const = 0;
+
+  // Resets all content settings for the given |content_type| to
+  // CONTENT_SETTING_DEFAULT. For content types that require a resource
+  // identifier all content settings for any resource identifieres of the given
+  // |content_type| will be reset to CONTENT_SETTING_DEFAULT.
+  //
+  // This should only be called on the UI thread.
+  virtual void ClearAllContentSettingsRules(
+      ContentSettingsType content_type) = 0;
+
+  // Resets all content settings to CONTENT_SETTINGS_DEFAULT.
+  //
+  // This should only be called on the UI thread.
+  virtual void ResetToDefaults() = 0;
+};
+
+}  // namespace content_settings
+
 #endif  // CHROME_BROWSER_CONTENT_SETTINGS_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/content_settings_provider_unittest.cc b/chrome/browser/content_settings/content_settings_provider_unittest.cc
index bb625ef..71cded4 100644
--- a/chrome/browser/content_settings/content_settings_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_provider_unittest.cc
@@ -5,14 +5,15 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #include "chrome/browser/content_settings/mock_content_settings_provider.h"
+#include "googleurl/src/gurl.h"
+
+namespace content_settings {
 
 TEST(ContentSettingsProviderTest, Mock) {
-  MockContentSettingsProvider provider(CONTENT_SETTINGS_TYPE_COOKIES,
+  MockDefaultProvider provider(CONTENT_SETTINGS_TYPE_COOKIES,
                                        CONTENT_SETTING_ALLOW,
                                        false,
                                        true);
-  EXPECT_TRUE(provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
-  EXPECT_FALSE(provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS));
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
             provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
@@ -23,4 +24,47 @@
                                 CONTENT_SETTING_BLOCK);
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
             provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
+
+  ContentSettingsPattern pattern("[*.]youtube.com");
+  GURL url("http://www.youtube.com");
+
+  MockProvider mock_provider(
+      pattern,
+      pattern,
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "java_plugin",
+      CONTENT_SETTING_BLOCK,
+      false);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK, mock_provider.GetContentSetting(
+      url, url, CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin"));
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT, mock_provider.GetContentSetting(
+      url, url, CONTENT_SETTINGS_TYPE_PLUGINS, "flash_plugin"));
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT, mock_provider.GetContentSetting(
+      url, url, CONTENT_SETTINGS_TYPE_GEOLOCATION, ""));
+
+  mock_provider.SetContentSetting(
+      pattern,
+      pattern,
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "java_plugin",
+      CONTENT_SETTING_ALLOW);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW, mock_provider.GetContentSetting(
+      url, url, CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin"));
+
+  mock_provider.set_read_only(true);
+  mock_provider.SetContentSetting(
+      pattern,
+      pattern,
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      "java_plugin",
+      CONTENT_SETTING_BLOCK);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW, mock_provider.GetContentSetting(
+      url, url, CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin"));
+
+  EXPECT_TRUE(mock_provider.read_only());
+  mock_provider.set_setting(CONTENT_SETTING_BLOCK);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK, mock_provider.GetContentSetting(
+      url, url, CONTENT_SETTINGS_TYPE_PLUGINS, "java_plugin"));
 }
+
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/host_content_settings_map.cc b/chrome/browser/content_settings/host_content_settings_map.cc
index 7de7a80..bcdd538 100644
--- a/chrome/browser/content_settings/host_content_settings_map.cc
+++ b/chrome/browser/content_settings/host_content_settings_map.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/content_settings/content_settings_details.h"
+#include "chrome/browser/content_settings/content_settings_provider.h"
 #include "chrome/browser/content_settings/policy_content_settings_provider.h"
 #include "chrome/browser/content_settings/pref_content_settings_provider.h"
 #include "chrome/browser/metrics/user_metrics.h"
@@ -27,41 +28,6 @@
 
 namespace {
 
-// The preference keys where resource identifiers are stored for
-// ContentSettingsType values that support resource identifiers.
-const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
-  NULL,
-  NULL,
-  NULL,
-  "per_plugin",
-  NULL,
-  NULL,  // Not used for Geolocation
-  NULL,  // Not used for Notifications
-};
-
-// The names of the ContentSettingsType values, for use with dictionary prefs.
-const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
-  "cookies",
-  "images",
-  "javascript",
-  "plugins",
-  "popups",
-  NULL,  // Not used for Geolocation
-  NULL,  // Not used for Notifications
-};
-
-// True if a given content settings type requires additional resource
-// identifiers.
-const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = {
-  false,  // CONTENT_SETTINGS_TYPE_COOKIES
-  false,  // CONTENT_SETTINGS_TYPE_IMAGES
-  false,  // CONTENT_SETTINGS_TYPE_JAVASCRIPT
-  true,   // CONTENT_SETTINGS_TYPE_PLUGINS
-  false,  // CONTENT_SETTINGS_TYPE_POPUPS
-  false,  // Not used for Geolocation
-  false,  // Not used for Notifications
-};
-
 // Returns true if we should allow all content types for this URL.  This is
 // true for various internal objects like chrome:// URLs, so UI and other
 // things users think of as "not webpages" don't break.
@@ -74,81 +40,70 @@
          url.SchemeIs(chrome::kUserScriptScheme);
 }
 
-// Map ASK for the plugins content type to BLOCK if click-to-play is
-// not enabled.
-ContentSetting ClickToPlayFixup(ContentSettingsType content_type,
-                                ContentSetting setting) {
-  if (setting == CONTENT_SETTING_ASK &&
-      content_type == CONTENT_SETTINGS_TYPE_PLUGINS &&
-      !CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableClickToPlay)) {
-    return CONTENT_SETTING_BLOCK;
-  }
-  return setting;
-}
+typedef linked_ptr<content_settings::DefaultProviderInterface>
+    DefaultContentSettingsProviderPtr;
+typedef std::vector<DefaultContentSettingsProviderPtr>::iterator
+    DefaultProviderIterator;
+typedef std::vector<DefaultContentSettingsProviderPtr>::const_iterator
+    ConstDefaultProviderIterator;
 
-typedef std::vector<linked_ptr<ContentSettingsProviderInterface> >::iterator
-    provider_iterator;
-typedef
-    std::vector<linked_ptr<ContentSettingsProviderInterface> >::const_iterator
-        const_provider_iterator;
+typedef linked_ptr<content_settings::ProviderInterface> ProviderPtr;
+typedef std::vector<ProviderPtr>::iterator ProviderIterator;
+typedef std::vector<ProviderPtr>::const_iterator ConstProviderIterator;
+
+typedef content_settings::ProviderInterface::Rules Rules;
+typedef content_settings::ProviderInterface::Rules::iterator
+    rules_iterator;
+typedef content_settings::ProviderInterface::Rules::const_iterator
+    const_rules_iterator;
 
 }  // namespace
 
-
-struct HostContentSettingsMap::ExtendedContentSettings {
-  ContentSettings content_settings;
-  ResourceContentSettings content_settings_for_resources;
-};
-
 HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
     : profile_(profile),
       is_off_the_record_(profile_->IsOffTheRecord()),
       updating_preferences_(false),
       block_third_party_cookies_(false),
       is_block_third_party_cookies_managed_(false) {
-  // The order in which the content settings providers are created is critical,
-  // as providers that are further down in the list (i.e. added later) override
-  // providers further up.
-  content_settings_providers_.push_back(
-      linked_ptr<ContentSettingsProviderInterface>(
-          new PrefContentSettingsProvider(profile)));
-  content_settings_providers_.push_back(
-      linked_ptr<ContentSettingsProviderInterface>(
-          new PolicyContentSettingsProvider(profile)));
+  // The order in which the default content settings providers are created is
+  // critical, as providers that are further down in the list (i.e. added later)
+  // override providers further up.
+  default_content_settings_providers_.push_back(
+      DefaultContentSettingsProviderPtr(
+          new content_settings::PrefDefaultProvider(profile)));
+  default_content_settings_providers_.push_back(
+      DefaultContentSettingsProviderPtr(
+          new content_settings::PolicyDefaultProvider(profile)));
 
   PrefService* prefs = profile_->GetPrefs();
 
+  // TODO(markusheintz): Discuss whether it is sensible to move migration code
+  // to PrefContentSettingsProvider.
   MigrateObsoleteCookiePref(prefs);
 
-  MigrateObsoletePopupsPref(prefs);
-
-  MigrateObsoletePerhostPref(prefs);
-
   // Read misc. global settings.
   block_third_party_cookies_ =
       prefs->GetBoolean(prefs::kBlockThirdPartyCookies);
+  if (block_third_party_cookies_) {
+    UserMetrics::RecordAction(
+        UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
+  } else {
+    UserMetrics::RecordAction(
+        UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
+  }
   is_block_third_party_cookies_managed_ =
       prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies);
   block_nonsandboxed_plugins_ =
       prefs->GetBoolean(prefs::kBlockNonsandboxedPlugins);
 
-  // Verify preferences version.
-  if (!prefs->HasPrefPath(prefs::kContentSettingsVersion)) {
-    prefs->SetInteger(prefs::kContentSettingsVersion,
-                      ContentSettingsPattern::kContentSettingsPatternVersion);
-  }
-  if (prefs->GetInteger(prefs::kContentSettingsVersion) >
-      ContentSettingsPattern::kContentSettingsPatternVersion) {
-    LOG(ERROR) << "Unknown content settings version in preferences.";
-    return;
-  }
-
-  // Read exceptions.
-  ReadExceptions(false);
+  // User defined non default content settings are provided by the PrefProvider.
+  // The order in which the content settings providers are created is critical,
+  // as providers that are further up in the list (i.e. added earlier) override
+  // providers further down.
+  content_settings_providers_.push_back(ProviderPtr(
+      new content_settings::PrefProvider(profile)));
 
   pref_change_registrar_.Init(prefs);
-  pref_change_registrar_.Add(prefs::kContentSettingsPatterns, this);
   pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
   pref_change_registrar_.Add(prefs::kBlockNonsandboxedPlugins, this);
   notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
@@ -157,9 +112,6 @@
 
 // static
 void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
-  prefs->RegisterIntegerPref(prefs::kContentSettingsVersion,
-      ContentSettingsPattern::kContentSettingsPatternVersion);
-  prefs->RegisterDictionaryPref(prefs::kContentSettingsPatterns);
   prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies, false);
   prefs->RegisterBooleanPref(prefs::kBlockNonsandboxedPlugins, false);
   prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0);
@@ -167,17 +119,19 @@
   // Obsolete prefs, for migration:
   prefs->RegisterIntegerPref(prefs::kCookieBehavior,
                              net::StaticCookiePolicy::ALLOW_ALL_COOKIES);
-  prefs->RegisterListPref(prefs::kPopupWhitelistedHosts);
-  prefs->RegisterDictionaryPref(prefs::kPerHostContentSettings);
+
+  // Register the prefs for the content settings providers.
+  content_settings::PrefDefaultProvider::RegisterUserPrefs(prefs);
+  content_settings::PolicyDefaultProvider::RegisterUserPrefs(prefs);
+  content_settings::PrefProvider::RegisterUserPrefs(prefs);
 }
 
 ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
     ContentSettingsType content_type) const {
   ContentSetting setting = CONTENT_SETTING_DEFAULT;
-  for (const_provider_iterator provider = content_settings_providers_.begin();
-       provider != content_settings_providers_.end(); ++provider) {
-    if (!(*provider)->CanProvideDefaultSetting(content_type))
-      continue;
+  for (ConstDefaultProviderIterator provider =
+           default_content_settings_providers_.begin();
+       provider != default_content_settings_providers_.end(); ++provider) {
     ContentSetting provided_setting =
         (*provider)->ProvideDefaultSetting(content_type);
     if (provided_setting != CONTENT_SETTING_DEFAULT)
@@ -211,74 +165,18 @@
   if (ShouldAllowAllContent(url))
     return CONTENT_SETTING_ALLOW;
 
-  if (!RequiresResourceIdentifier(content_type))
-    return GetNonDefaultContentSettings(url).settings[content_type];
-
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableResourceContentSettings)) {
-    DCHECK(!resource_identifier.empty());
-  }
-
-  // Host content settings are ignored if the default_content_setting is
-  // managed.
-  if (IsDefaultContentSettingManaged(content_type)) {
-    return GetDefaultContentSetting(content_type);
-  }
-
-  AutoLock auto_lock(lock_);
-
-  const std::string host(net::GetHostOrSpecFromURL(url));
-  ContentSettingsTypeResourceIdentifierPair
-      requested_setting(content_type, resource_identifier);
-
-  // Check for exact matches first.
-  HostContentSettings::const_iterator i(host_content_settings_.find(host));
-  if (i != host_content_settings_.end() &&
-      i->second.content_settings_for_resources.find(requested_setting) !=
-      i->second.content_settings_for_resources.end()) {
-    return i->second.content_settings_for_resources.find(
-        requested_setting)->second;
-  }
-
-  // If this map is not for an off-the-record profile, these searches will never
-  // match. The additional off-the-record exceptions always overwrite the
-  // regular ones.
-  i = off_the_record_settings_.find(host);
-  if (i != off_the_record_settings_.end() &&
-      i->second.content_settings_for_resources.find(requested_setting) !=
-      i->second.content_settings_for_resources.end()) {
-    return i->second.content_settings_for_resources.find(
-        requested_setting)->second;
-  }
-
-  // Match patterns starting with the most concrete pattern match.
-  for (std::string key =
-       std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
-    HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
-    if (i != off_the_record_settings_.end() &&
-        i->second.content_settings_for_resources.find(requested_setting) !=
-        i->second.content_settings_for_resources.end()) {
-      return i->second.content_settings_for_resources.find(
-          requested_setting)->second;
-    }
-
-    i = host_content_settings_.find(key);
-    if (i != host_content_settings_.end() &&
-        i->second.content_settings_for_resources.find(requested_setting) !=
-        i->second.content_settings_for_resources.end()) {
-      return i->second.content_settings_for_resources.find(
-          requested_setting)->second;
-    }
-
-    const size_t next_dot =
-        key.find('.', ContentSettingsPattern::kDomainWildcardLength);
-    if (next_dot == std::string::npos)
+  // Iterate through the list of providers and break when the first non default
+  // setting is found.
+  ContentSetting provided_setting(CONTENT_SETTING_DEFAULT);
+  for (ConstProviderIterator provider = content_settings_providers_.begin();
+       provider != content_settings_providers_.end();
+       ++provider) {
+    provided_setting = (*provider)->GetContentSetting(
+        url, url, content_type, resource_identifier);
+    if (provided_setting != CONTENT_SETTING_DEFAULT)
       break;
-    key.erase(ContentSettingsPattern::kDomainWildcardLength,
-              next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
   }
-
-  return CONTENT_SETTING_DEFAULT;
+  return provided_setting;
 }
 
 ContentSettings HostContentSettingsMap::GetContentSettings(
@@ -288,15 +186,12 @@
   // If we require a resource identifier, set the content settings to default,
   // otherwise make the defaults explicit.
   for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
-    if (RequiresResourceIdentifier(ContentSettingsType(j))) {
-      output.settings[j] = CONTENT_SETTING_DEFAULT;
-    } else {
-      // A managed default content setting has the highest priority and hence
-      // will overwrite any previously set value.
-      if ((output.settings[j] == CONTENT_SETTING_DEFAULT) ||
-          IsDefaultContentSettingManaged(ContentSettingsType(j))) {
-        output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j));
-      }
+    // A managed default content setting has the highest priority and hence
+    // will overwrite any previously set value.
+    if ((output.settings[j] == CONTENT_SETTING_DEFAULT &&
+         j != CONTENT_SETTINGS_TYPE_PLUGINS) ||
+         IsDefaultContentSettingManaged(ContentSettingsType(j))) {
+      output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j));
     }
   }
   return output;
@@ -307,53 +202,11 @@
   if (ShouldAllowAllContent(url))
       return ContentSettings(CONTENT_SETTING_ALLOW);
 
-  AutoLock auto_lock(lock_);
-
-  const std::string host(net::GetHostOrSpecFromURL(url));
-  ContentSettings output;
-  for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
-    output.settings[j] = CONTENT_SETTING_DEFAULT;
-
-  // Check for exact matches first.
-  HostContentSettings::const_iterator i(host_content_settings_.find(host));
-  if (i != host_content_settings_.end())
-    output = i->second.content_settings;
-
-  // If this map is not for an off-the-record profile, these searches will never
-  // match. The additional off-the-record exceptions always overwrite the
-  // regular ones.
-  i = off_the_record_settings_.find(host);
-  if (i != off_the_record_settings_.end()) {
-    for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
-      if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT)
-        output.settings[j] = i->second.content_settings.settings[j];
+  ContentSettings output(CONTENT_SETTING_DEFAULT);
+  for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+    output.settings[j] = GetNonDefaultContentSetting(
+        url, ContentSettingsType(j) , "");
   }
-
-  // Match patterns starting with the most concrete pattern match.
-  for (std::string key =
-       std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
-    HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
-    if (i != off_the_record_settings_.end()) {
-      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
-        if (output.settings[j] == CONTENT_SETTING_DEFAULT)
-          output.settings[j] = i->second.content_settings.settings[j];
-      }
-    }
-    i = host_content_settings_.find(key);
-    if (i != host_content_settings_.end()) {
-      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
-        if (output.settings[j] == CONTENT_SETTING_DEFAULT)
-          output.settings[j] = i->second.content_settings.settings[j];
-      }
-    }
-    const size_t next_dot =
-        key.find('.', ContentSettingsPattern::kDomainWildcardLength);
-    if (next_dot == std::string::npos)
-      break;
-    key.erase(ContentSettingsPattern::kDomainWildcardLength,
-              next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
-  }
-
   return output;
 }
 
@@ -361,166 +214,53 @@
     ContentSettingsType content_type,
     const std::string& resource_identifier,
     SettingsForOneType* settings) const {
-  DCHECK(RequiresResourceIdentifier(content_type) !=
-         resource_identifier.empty());
   DCHECK(settings);
   settings->clear();
 
-  const HostContentSettings* map_to_return =
-      is_off_the_record_ ? &off_the_record_settings_ : &host_content_settings_;
-  ContentSettingsTypeResourceIdentifierPair
-      requested_setting(content_type, resource_identifier);
+  // Collect content_settings::Rules for the given content_type and
+  // resource_identifier from the content settings providers.
+  Rules content_settings_rules;
+  for (ConstProviderIterator provider = content_settings_providers_.begin();
+       provider != content_settings_providers_.end();
+       ++provider) {
+    // TODO(markusheintz): Only the rules that are applied should be collected.
+    // Merge rules.
+    (*provider)->GetAllContentSettingsRules(
+      content_type, resource_identifier, &content_settings_rules);
+  }
 
-  AutoLock auto_lock(lock_);
-  for (HostContentSettings::const_iterator i(map_to_return->begin());
-       i != map_to_return->end(); ++i) {
-    ContentSetting setting;
-    if (RequiresResourceIdentifier(content_type)) {
-      if (i->second.content_settings_for_resources.find(requested_setting) !=
-          i->second.content_settings_for_resources.end())
-        setting = i->second.content_settings_for_resources.find(
-            requested_setting)->second;
-      else
-        setting = CONTENT_SETTING_DEFAULT;
-    } else {
-     setting = i->second.content_settings.settings[content_type];
-    }
-    if (setting != CONTENT_SETTING_DEFAULT) {
-      // Use of push_back() relies on the map iterator traversing in order of
-      // ascending keys.
-      settings->push_back(
-          std::make_pair(ContentSettingsPattern(i->first), setting));
-    }
+  // convert Rules to SettingsForOneType
+  for (const_rules_iterator rule_iterator =
+           content_settings_rules.begin();
+       rule_iterator != content_settings_rules.end();
+       ++rule_iterator) {
+    settings->push_back(std::make_pair(ContentSettingsPattern(
+        rule_iterator->requesting_url_pattern),
+        rule_iterator->content_setting));
   }
 }
 
 void HostContentSettingsMap::SetDefaultContentSetting(
     ContentSettingsType content_type,
     ContentSetting setting) {
-  DCHECK(kTypeNames[content_type] != NULL);  // Don't call this for Geolocation.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS ||
-         setting != CONTENT_SETTING_ASK ||
-         CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kEnableClickToPlay));
-
-  // The default settings may not be directly modified for OTR sessions.
-  // Instead, they are synced to the main profile's setting.
-  if (is_off_the_record_) {
-    NOTREACHED();
-    return;
-  }
-
-  for (provider_iterator provider = content_settings_providers_.begin();
-       provider != content_settings_providers_.end(); ++provider) {
+  for (DefaultProviderIterator provider =
+           default_content_settings_providers_.begin();
+       provider != default_content_settings_providers_.end(); ++provider) {
     (*provider)->UpdateDefaultSetting(content_type, setting);
   }
 }
 
 void HostContentSettingsMap::SetContentSetting(
-    const ContentSettingsPattern& original_pattern,
+    const ContentSettingsPattern& pattern,
     ContentSettingsType content_type,
     const std::string& resource_identifier,
     ContentSetting setting) {
-  DCHECK(kTypeNames[content_type] != NULL);  // Don't call this for Geolocation.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK_NE(RequiresResourceIdentifier(content_type),
-            resource_identifier.empty());
-  DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS ||
-         setting != CONTENT_SETTING_ASK ||
-         CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kEnableClickToPlay));
-
-  const ContentSettingsPattern pattern(original_pattern.CanonicalizePattern());
-
-  bool early_exit = false;
-  std::string pattern_str(pattern.AsString());
-  PrefService* prefs = NULL;
-  DictionaryValue* all_settings_dictionary = NULL;
-  HostContentSettings* map_to_modify = &off_the_record_settings_;
-  if (!is_off_the_record_) {
-    prefs = profile_->GetPrefs();
-    all_settings_dictionary =
-      prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
-    map_to_modify = &host_content_settings_;
+  for (ProviderIterator provider = content_settings_providers_.begin();
+       provider != content_settings_providers_.end();
+       ++provider) {
+    (*provider)->SetContentSetting(
+        pattern, pattern, content_type, resource_identifier, setting);
   }
-
-  {
-    AutoLock auto_lock(lock_);
-    if (!map_to_modify->count(pattern_str))
-      (*map_to_modify)[pattern_str].content_settings = ContentSettings();
-    HostContentSettings::iterator
-        i(map_to_modify->find(pattern_str));
-    ContentSettings& settings = i->second.content_settings;
-    if (RequiresResourceIdentifier(content_type)) {
-      settings.settings[content_type] = CONTENT_SETTING_DEFAULT;
-      if (setting != CONTENT_SETTING_DEFAULT) {
-        i->second.content_settings_for_resources[
-            ContentSettingsTypeResourceIdentifierPair(content_type,
-            resource_identifier)] = setting;
-      } else {
-        i->second.content_settings_for_resources.erase(
-            ContentSettingsTypeResourceIdentifierPair(content_type,
-            resource_identifier));
-      }
-    } else {
-      settings.settings[content_type] = setting;
-    }
-    if (AllDefault(i->second)) {
-      map_to_modify->erase(i);
-      if (all_settings_dictionary)
-        all_settings_dictionary->RemoveWithoutPathExpansion(pattern_str, NULL);
-
-      // We can't just return because |NotifyObservers()| needs to be called,
-      // without |lock_| being held.
-      early_exit = true;
-    }
-  }
-
-  if (!early_exit && all_settings_dictionary) {
-    DictionaryValue* host_settings_dictionary = NULL;
-    bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-        pattern_str, &host_settings_dictionary);
-    if (!found) {
-      host_settings_dictionary = new DictionaryValue;
-      all_settings_dictionary->SetWithoutPathExpansion(
-          pattern_str, host_settings_dictionary);
-      DCHECK_NE(setting, CONTENT_SETTING_DEFAULT);
-    }
-    if (RequiresResourceIdentifier(content_type)) {
-      std::string dictionary_path(kResourceTypeNames[content_type]);
-      DictionaryValue* resource_dictionary = NULL;
-      found = host_settings_dictionary->GetDictionary(
-          dictionary_path, &resource_dictionary);
-      if (!found) {
-        resource_dictionary = new DictionaryValue;
-        host_settings_dictionary->Set(dictionary_path, resource_dictionary);
-      }
-      if (setting == CONTENT_SETTING_DEFAULT) {
-        resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
-                                                        NULL);
-      } else {
-        resource_dictionary->SetWithoutPathExpansion(
-            resource_identifier, Value::CreateIntegerValue(setting));
-      }
-    } else {
-      std::string dictionary_path(kTypeNames[content_type]);
-      if (setting == CONTENT_SETTING_DEFAULT) {
-        host_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path,
-                                                             NULL);
-      } else {
-        host_settings_dictionary->SetWithoutPathExpansion(
-            dictionary_path, Value::CreateIntegerValue(setting));
-      }
-    }
-  }
-
-  updating_preferences_ = true;
-  if (!is_off_the_record_)
-    ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
-  updating_preferences_ = false;
-
-  NotifyObservers(ContentSettingsDetails(pattern, content_type, ""));
 }
 
 void HostContentSettingsMap::AddExceptionForURL(
@@ -542,68 +282,10 @@
 
 void HostContentSettingsMap::ClearSettingsForOneType(
     ContentSettingsType content_type) {
-  DCHECK(kTypeNames[content_type] != NULL);  // Don't call this for Geolocation.
-
-  PrefService* prefs = NULL;
-  DictionaryValue* all_settings_dictionary = NULL;
-  HostContentSettings* map_to_modify = &off_the_record_settings_;
-
-  if (!is_off_the_record_) {
-    prefs = profile_->GetPrefs();
-    all_settings_dictionary =
-      prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
-    map_to_modify = &host_content_settings_;
-  }
-
-  {
-    AutoLock auto_lock(lock_);
-    for (HostContentSettings::iterator i(map_to_modify->begin());
-         i != map_to_modify->end(); ) {
-      if (RequiresResourceIdentifier(content_type) ||
-          i->second.content_settings.settings[content_type] !=
-          CONTENT_SETTING_DEFAULT) {
-        if (RequiresResourceIdentifier(content_type))
-          i->second.content_settings_for_resources.clear();
-        i->second.content_settings.settings[content_type] =
-            CONTENT_SETTING_DEFAULT;
-        std::string host(i->first);
-        if (AllDefault(i->second)) {
-          if (all_settings_dictionary)
-            all_settings_dictionary->
-                RemoveWithoutPathExpansion(host, NULL);
-          map_to_modify->erase(i++);
-        } else if (all_settings_dictionary) {
-          DictionaryValue* host_settings_dictionary;
-          bool found =
-              all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-                  host, &host_settings_dictionary);
-          DCHECK(found);
-          host_settings_dictionary->RemoveWithoutPathExpansion(
-              kTypeNames[content_type], NULL);
-          ++i;
-        }
-      } else {
-        ++i;
-      }
-    }
-  }
-
-  updating_preferences_ = true;
-  if (!is_off_the_record_)
-    ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
-  updating_preferences_ = false;
-
-  NotifyObservers(
-      ContentSettingsDetails(ContentSettingsPattern(), content_type, ""));
-}
-
-bool HostContentSettingsMap::RequiresResourceIdentifier(
-    ContentSettingsType content_type) const {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableResourceContentSettings)) {
-    return kRequiresResourceIdentifier[content_type];
-  } else {
-    return false;
+  for (ProviderIterator provider = content_settings_providers_.begin();
+       provider != content_settings_providers_.end();
+       ++provider) {
+    (*provider)->ClearAllContentSettingsRules(content_type);
   }
 }
 
@@ -626,7 +308,7 @@
   }
 
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     block_third_party_cookies_ = block;
   }
 
@@ -647,11 +329,10 @@
   }
 
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     block_nonsandboxed_plugins_ = block;
   }
 
-
   PrefService* prefs = profile_->GetPrefs();
   if (block) {
     UserMetrics::RecordAction(
@@ -668,13 +349,19 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   {
-    AutoLock auto_lock(lock_);
-    for (provider_iterator provider = content_settings_providers_.begin();
-         provider != content_settings_providers_.end(); ++provider) {
+    base::AutoLock auto_lock(lock_);
+    for (DefaultProviderIterator provider =
+             default_content_settings_providers_.begin();
+         provider != default_content_settings_providers_.end(); ++provider) {
       (*provider)->ResetToDefaults();
     }
-    host_content_settings_.clear();
-    off_the_record_settings_.clear();
+
+    for (ProviderIterator provider = content_settings_providers_.begin();
+         provider != content_settings_providers_.end();
+         ++provider) {
+      (*provider)->ResetToDefaults();
+    }
+
     // Don't reset block third party cookies if they are managed.
     if (!IsBlockThirdPartyCookiesManaged())
       block_third_party_cookies_ = false;
@@ -684,7 +371,6 @@
   if (!is_off_the_record_) {
     PrefService* prefs = profile_->GetPrefs();
     updating_preferences_ = true;
-    prefs->ClearPref(prefs::kContentSettingsPatterns);
     // If the block third party cookies preference is managed we still must
     // clear it in order to restore the default value for later when the
     // preference is not managed anymore.
@@ -708,17 +394,15 @@
       return;
 
     std::string* name = Details<std::string>(details).ptr();
-    if (*name == prefs::kContentSettingsPatterns) {
-      ReadExceptions(true);
-    } else if (*name == prefs::kBlockThirdPartyCookies) {
-      AutoLock auto_lock(lock_);
+    if (*name == prefs::kBlockThirdPartyCookies) {
+      base::AutoLock auto_lock(lock_);
       block_third_party_cookies_ = profile_->GetPrefs()->GetBoolean(
           prefs::kBlockThirdPartyCookies);
       is_block_third_party_cookies_managed_ =
           profile_->GetPrefs()->IsManagedPreference(
               prefs::kBlockThirdPartyCookies);
     } else if (*name == prefs::kBlockNonsandboxedPlugins) {
-      AutoLock auto_lock(lock_);
+      base::AutoLock auto_lock(lock_);
       block_nonsandboxed_plugins_ = profile_->GetPrefs()->GetBoolean(
           prefs::kBlockNonsandboxedPlugins);
     } else {
@@ -743,118 +427,17 @@
   UnregisterObservers();
 }
 
-void HostContentSettingsMap::GetSettingsFromDictionary(
-    const DictionaryValue* dictionary,
-    ContentSettings* settings) {
-  for (DictionaryValue::key_iterator i(dictionary->begin_keys());
-       i != dictionary->end_keys(); ++i) {
-    const std::string& content_type(*i);
-    for (size_t type = 0; type < arraysize(kTypeNames); ++type) {
-      if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type)) {
-        int setting = CONTENT_SETTING_DEFAULT;
-        bool found = dictionary->GetIntegerWithoutPathExpansion(content_type,
-                                                                &setting);
-        DCHECK(found);
-        settings->settings[type] = IntToContentSetting(setting);
-        break;
-      }
-    }
-  }
-  // Migrate obsolete cookie prompt mode.
-  if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] ==
-      CONTENT_SETTING_ASK)
-    settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK;
-
-  settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] =
-      ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS,
-                       settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]);
-}
-
-void HostContentSettingsMap::GetResourceSettingsFromDictionary(
-    const DictionaryValue* dictionary,
-    ResourceContentSettings* settings) {
-  for (DictionaryValue::key_iterator i(dictionary->begin_keys());
-       i != dictionary->end_keys(); ++i) {
-    const std::string& content_type(*i);
-    for (size_t type = 0; type < arraysize(kResourceTypeNames); ++type) {
-      if ((kResourceTypeNames[type] != NULL) &&
-          (kResourceTypeNames[type] == content_type)) {
-        DictionaryValue* resource_dictionary = NULL;
-        bool found = dictionary->GetDictionary(content_type,
-                                               &resource_dictionary);
-        DCHECK(found);
-        for (DictionaryValue::key_iterator j(resource_dictionary->begin_keys());
-             j != resource_dictionary->end_keys(); ++j) {
-          const std::string& resource_identifier(*j);
-          int setting = CONTENT_SETTING_DEFAULT;
-          bool found = resource_dictionary->GetIntegerWithoutPathExpansion(
-              resource_identifier, &setting);
-          DCHECK(found);
-          (*settings)[ContentSettingsTypeResourceIdentifierPair(
-              ContentSettingsType(type), resource_identifier)] =
-                  ClickToPlayFixup(ContentSettingsType(type),
-                                   ContentSetting(setting));
-        }
-
-        break;
-      }
-    }
-  }
-}
-
-bool HostContentSettingsMap::AllDefault(
-    const ExtendedContentSettings& settings) const {
-  for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) {
-    if (settings.content_settings.settings[i] != CONTENT_SETTING_DEFAULT)
-      return false;
-  }
-  return settings.content_settings_for_resources.empty();
-}
-
 bool HostContentSettingsMap::IsDefaultContentSettingManaged(
     ContentSettingsType content_type) const {
-  for (const_provider_iterator provider = content_settings_providers_.begin();
-       provider != content_settings_providers_.end(); ++provider) {
+  for (ConstDefaultProviderIterator provider =
+           default_content_settings_providers_.begin();
+       provider != default_content_settings_providers_.end(); ++provider) {
     if ((*provider)->DefaultSettingIsManaged(content_type))
       return true;
   }
   return false;
 }
 
-void HostContentSettingsMap::ReadExceptions(bool overwrite) {
-  AutoLock lock(lock_);
-
-  PrefService* prefs = profile_->GetPrefs();
-  DictionaryValue* all_settings_dictionary =
-      prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
-
-  if (overwrite)
-    host_content_settings_.clear();
-
-  // Careful: The returned value could be NULL if the pref has never been set.
-  if (all_settings_dictionary != NULL) {
-    // Convert all Unicode patterns into punycode form, then read.
-    CanonicalizeContentSettingsExceptions(all_settings_dictionary);
-
-    for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
-         i != all_settings_dictionary->end_keys(); ++i) {
-      const std::string& pattern(*i);
-      if (!ContentSettingsPattern(pattern).IsValid())
-        LOG(WARNING) << "Invalid pattern stored in content settings";
-      DictionaryValue* pattern_settings_dictionary = NULL;
-      bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-          pattern, &pattern_settings_dictionary);
-      DCHECK(found);
-      ContentSettings settings;
-      GetSettingsFromDictionary(pattern_settings_dictionary, &settings);
-      host_content_settings_[pattern].content_settings = settings;
-      GetResourceSettingsFromDictionary(
-          pattern_settings_dictionary,
-          &host_content_settings_[pattern].content_settings_for_resources);
-    }
-  }
-}
-
 void HostContentSettingsMap::NotifyObservers(
     const ContentSettingsDetails& details) {
   NotificationService::current()->Notify(
@@ -884,94 +467,7 @@
     }
     if (!prefs->HasPrefPath(prefs::kBlockThirdPartyCookies)) {
       SetBlockThirdPartyCookies(cookie_behavior ==
-          net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES);
+          net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
     }
   }
 }
-
-void HostContentSettingsMap::MigrateObsoletePopupsPref(PrefService* prefs) {
-  if (prefs->HasPrefPath(prefs::kPopupWhitelistedHosts)) {
-    const ListValue* whitelist_pref =
-        prefs->GetList(prefs::kPopupWhitelistedHosts);
-    for (ListValue::const_iterator i(whitelist_pref->begin());
-         i != whitelist_pref->end(); ++i) {
-      std::string host;
-      (*i)->GetAsString(&host);
-      SetContentSetting(ContentSettingsPattern(host),
-                        CONTENT_SETTINGS_TYPE_POPUPS,
-                        "",
-                        CONTENT_SETTING_ALLOW);
-    }
-    prefs->ClearPref(prefs::kPopupWhitelistedHosts);
-  }
-}
-
-void HostContentSettingsMap::MigrateObsoletePerhostPref(PrefService* prefs) {
-  if (prefs->HasPrefPath(prefs::kPerHostContentSettings)) {
-    const DictionaryValue* all_settings_dictionary =
-        prefs->GetDictionary(prefs::kPerHostContentSettings);
-    for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
-         i != all_settings_dictionary->end_keys(); ++i) {
-      const std::string& host(*i);
-      ContentSettingsPattern pattern(
-          std::string(ContentSettingsPattern::kDomainWildcard) + host);
-      DictionaryValue* host_settings_dictionary = NULL;
-      bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-          host, &host_settings_dictionary);
-      DCHECK(found);
-      ContentSettings settings;
-      GetSettingsFromDictionary(host_settings_dictionary, &settings);
-      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
-        if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
-            !RequiresResourceIdentifier(ContentSettingsType(j)))
-          SetContentSetting(
-              pattern, ContentSettingsType(j), "", settings.settings[j]);
-      }
-    }
-    prefs->ClearPref(prefs::kPerHostContentSettings);
-  }
-}
-
-void HostContentSettingsMap::CanonicalizeContentSettingsExceptions(
-    DictionaryValue* all_settings_dictionary) {
-  DCHECK(all_settings_dictionary);
-
-  std::vector<std::string> remove_items;
-  std::vector<std::pair<std::string, std::string> > move_items;
-  for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
-       i != all_settings_dictionary->end_keys(); ++i) {
-    const std::string& pattern(*i);
-    const std::string canonicalized_pattern =
-        ContentSettingsPattern(pattern).CanonicalizePattern();
-
-    if (canonicalized_pattern.empty() || canonicalized_pattern == pattern)
-      continue;
-
-    // Clear old pattern if prefs already have canonicalized pattern.
-    DictionaryValue* new_pattern_settings_dictionary = NULL;
-    if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-            canonicalized_pattern, &new_pattern_settings_dictionary)) {
-      remove_items.push_back(pattern);
-      continue;
-    }
-
-    // Move old pattern to canonicalized pattern.
-    DictionaryValue* old_pattern_settings_dictionary = NULL;
-    if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
-            pattern, &old_pattern_settings_dictionary)) {
-      move_items.push_back(std::make_pair(pattern, canonicalized_pattern));
-    }
-  }
-
-  for (size_t i = 0; i < remove_items.size(); ++i) {
-    all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL);
-  }
-
-  for (size_t i = 0; i < move_items.size(); ++i) {
-    Value* pattern_settings_dictionary = NULL;
-    all_settings_dictionary->RemoveWithoutPathExpansion(
-        move_items[i].first, &pattern_settings_dictionary);
-    all_settings_dictionary->SetWithoutPathExpansion(
-        move_items[i].second, pattern_settings_dictionary);
-  }
-}
diff --git a/chrome/browser/content_settings/host_content_settings_map.h b/chrome/browser/content_settings/host_content_settings_map.h
index 915d974..c2658e8 100644
--- a/chrome/browser/content_settings/host_content_settings_map.h
+++ b/chrome/browser/content_settings/host_content_settings_map.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,8 +16,8 @@
 
 #include "base/basictypes.h"
 #include "base/linked_ptr.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/content_settings/content_settings_pattern.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
@@ -25,8 +25,12 @@
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
+namespace content_settings {
+class DefaultProviderInterface;
+class ProviderInterface;
+}  // namespace content_settings
+
 class ContentSettingsDetails;
-class ContentSettingsProviderInterface;
 class DictionaryValue;
 class GURL;
 class PrefService;
@@ -135,10 +139,6 @@
   // This should only be called on the UI thread.
   void ClearSettingsForOneType(ContentSettingsType content_type);
 
-  // Whether the |content_type| requires an additional resource identifier for
-  // accessing content settings.
-  bool RequiresResourceIdentifier(ContentSettingsType content_type) const;
-
   // This setting trumps any host-specific settings.
   bool BlockThirdPartyCookies() const { return block_third_party_cookies_; }
   bool IsBlockThirdPartyCookiesManaged() const {
@@ -173,29 +173,6 @@
  private:
   friend class base::RefCountedThreadSafe<HostContentSettingsMap>;
 
-  typedef std::pair<ContentSettingsType, std::string>
-      ContentSettingsTypeResourceIdentifierPair;
-  typedef std::map<ContentSettingsTypeResourceIdentifierPair, ContentSetting>
-      ResourceContentSettings;
-
-  struct ExtendedContentSettings;
-  typedef std::map<std::string, ExtendedContentSettings> HostContentSettings;
-
-  // Sets the fields of |settings| based on the values in |dictionary|.
-  void GetSettingsFromDictionary(const DictionaryValue* dictionary,
-                                 ContentSettings* settings);
-
-  // Populates |settings| based on the values in |dictionary|.
-  void GetResourceSettingsFromDictionary(const DictionaryValue* dictionary,
-                                         ResourceContentSettings* settings);
-
-  // Returns true if |settings| consists entirely of CONTENT_SETTING_DEFAULT.
-  bool AllDefault(const ExtendedContentSettings& settings) const;
-
-  // Reads the host exceptions from the prefereces service. If |overwrite| is
-  // true and the preference is missing, the local copy will be cleared as well.
-  void ReadExceptions(bool overwrite);
-
   // Informs observers that content settings have changed. Make sure that
   // |lock_| is not held when calling this, as listeners will usually call one
   // of the GetSettings functions in response, which would then lead to a
@@ -207,13 +184,6 @@
   // Various migration methods (old cookie, popup and per-host data gets
   // migrated to the new format).
   void MigrateObsoleteCookiePref(PrefService* prefs);
-  void MigrateObsoletePopupsPref(PrefService* prefs);
-  void MigrateObsoletePerhostPref(PrefService* prefs);
-
-  // Converts all exceptions that have non-canonicalized pattern into
-  // canonicalized pattern. If such pattern already exists, we just remove the
-  // old exception.
-  void CanonicalizeContentSettingsExceptions(DictionaryValue* settings);
 
   // The profile we're associated with.
   Profile* profile_;
@@ -228,20 +198,16 @@
   // notifications from the preferences service that we triggered ourself.
   bool updating_preferences_;
 
+  // Default content setting providers.
+  std::vector<linked_ptr<content_settings::DefaultProviderInterface> >
+      default_content_settings_providers_;
+
   // Content setting providers.
-  std::vector<linked_ptr<ContentSettingsProviderInterface> >
+  std::vector<linked_ptr<content_settings::ProviderInterface> >
       content_settings_providers_;
 
   // Used around accesses to the following objects to guarantee thread safety.
-  mutable Lock lock_;
-
-  // Copies of the pref data, so that we can read it on threads other than the
-  // UI thread.
-  HostContentSettings host_content_settings_;
-
-  // Differences to the preference-stored host content settings for
-  // off-the-record settings.
-  HostContentSettings off_the_record_settings_;
+  mutable base::Lock lock_;
 
   // Misc global settings.
   bool block_third_party_cookies_;
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
index e7540e2..7de163d 100644
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
@@ -2,16 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/content_settings/host_content_settings_map_unittest.h"
-
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "chrome/browser/content_settings/content_settings_details.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_settings/stub_settings_observer.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_registrar.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/testing_pref_service.h"
@@ -20,7 +19,6 @@
 #include "net/base/static_cookie_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-
 namespace {
 
 bool SettingsEqual(const ContentSettings& settings1,
@@ -616,6 +614,14 @@
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
             host_content_settings_map->GetContentSetting(
                 host, CONTENT_SETTINGS_TYPE_PLUGINS, resource2));
+
+  // If resource content settings are enabled GetContentSettings should return
+  // CONTENT_SETTING_DEFAULT for content types that require resource
+  // identifiers.
+  ContentSettings settings =
+      host_content_settings_map->GetContentSettings(host);
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+            settings.settings[CONTENT_SETTINGS_TYPE_PLUGINS]);
 }
 
 TEST_F(HostContentSettingsMapTest, ResourceIdentifierPrefs) {
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.h b/chrome/browser/content_settings/host_content_settings_map_unittest.h
deleted file mode 100644
index ba56ab4..0000000
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_UNITTEST_H_
-#define CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_UNITTEST_H_
-#pragma once
-
-#include "chrome/browser/content_settings/content_settings_details.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/common/notification_service.h"
-#include "googleurl/src/gurl.h"
-
-class HostContentSettingsMap;
-
-class StubSettingsObserver : public NotificationObserver {
- public:
-  StubSettingsObserver() : last_notifier(NULL), counter(0) {
-    registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
-                   NotificationService::AllSources());
-  }
-
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    ++counter;
-    Source<HostContentSettingsMap> content_settings(source);
-    Details<ContentSettingsDetails> settings_details(details);
-    last_notifier = content_settings.ptr();
-    last_pattern = settings_details.ptr()->pattern();
-    last_update_all = settings_details.ptr()->update_all();
-    last_update_all_types = settings_details.ptr()->update_all_types();
-    last_type = settings_details.ptr()->type();
-    // This checks that calling a Get function from an observer doesn't
-    // deadlock.
-    last_notifier->GetContentSettings(GURL("http://random-hostname.com/"));
-  }
-
-  HostContentSettingsMap* last_notifier;
-  ContentSettingsPattern last_pattern;
-  bool last_update_all;
-  bool last_update_all_types;
-  int counter;
-  ContentSettingsType last_type;
-
- private:
-  NotificationRegistrar registrar_;
-};
-#endif  // CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_UNITTEST_H_
diff --git a/chrome/browser/content_settings/mock_content_settings_provider.cc b/chrome/browser/content_settings/mock_content_settings_provider.cc
index ee3e845..f73280f 100644
--- a/chrome/browser/content_settings/mock_content_settings_provider.cc
+++ b/chrome/browser/content_settings/mock_content_settings_provider.cc
@@ -1,10 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/content_settings/mock_content_settings_provider.h"
 
-MockContentSettingsProvider::MockContentSettingsProvider(
+namespace content_settings {
+
+MockDefaultProvider::MockDefaultProvider(
     ContentSettingsType content_type,
     ContentSetting setting,
     bool is_managed,
@@ -15,30 +17,78 @@
       can_override_(can_override) {
 }
 
-MockContentSettingsProvider::~MockContentSettingsProvider() {
+MockDefaultProvider::~MockDefaultProvider() {
 }
 
-bool MockContentSettingsProvider::CanProvideDefaultSetting(
-    ContentSettingsType content_type) const {
-  return content_type == content_type_;
-}
-
-ContentSetting MockContentSettingsProvider::ProvideDefaultSetting(
+ContentSetting MockDefaultProvider::ProvideDefaultSetting(
     ContentSettingsType content_type) const {
   return content_type == content_type_ ? setting_ : CONTENT_SETTING_DEFAULT;
 }
 
-void MockContentSettingsProvider::UpdateDefaultSetting(
+void MockDefaultProvider::UpdateDefaultSetting(
     ContentSettingsType content_type,
     ContentSetting setting) {
   if (can_override_ && content_type == content_type_)
     setting_ = setting;
 }
 
-bool MockContentSettingsProvider::DefaultSettingIsManaged(
+bool MockDefaultProvider::DefaultSettingIsManaged(
     ContentSettingsType content_type) const {
   return content_type == content_type_ && is_managed_;
 }
 
-void MockContentSettingsProvider::ResetToDefaults() {
+void MockDefaultProvider::ResetToDefaults() {
 }
+
+MockProvider::MockProvider()
+    : requesting_url_pattern_(ContentSettingsPattern()),
+      embedding_url_pattern_(ContentSettingsPattern()),
+      content_type_(CONTENT_SETTINGS_TYPE_COOKIES),
+      resource_identifier_(""),
+      setting_(CONTENT_SETTING_DEFAULT),
+      read_only_(false) {}
+
+MockProvider::MockProvider(ContentSettingsPattern requesting_url_pattern,
+                           ContentSettingsPattern embedding_url_pattern,
+                           ContentSettingsType content_type,
+                           ResourceIdentifier resource_identifier,
+                           ContentSetting setting,
+                           bool read_only)
+    : requesting_url_pattern_(requesting_url_pattern),
+      embedding_url_pattern_(embedding_url_pattern),
+      content_type_(content_type),
+      resource_identifier_(resource_identifier),
+      setting_(setting),
+      read_only_(read_only) {}
+
+MockProvider::~MockProvider() {}
+
+ContentSetting MockProvider::GetContentSetting(
+    const GURL& requesting_url,
+    const GURL& embedding_url,
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier) const {
+  if (requesting_url_pattern_.Matches(requesting_url) &&
+      content_type_ == content_type &&
+      resource_identifier_ == resource_identifier) {
+    return setting_;
+  }
+  return CONTENT_SETTING_DEFAULT;
+}
+
+void MockProvider::SetContentSetting(
+    const ContentSettingsPattern& requesting_url_pattern,
+    const ContentSettingsPattern& embedding_url_pattern,
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier,
+    ContentSetting content_setting) {
+  if (read_only_)
+    return;
+  requesting_url_pattern_ = ContentSettingsPattern(requesting_url_pattern);
+  embedding_url_pattern_ = ContentSettingsPattern(embedding_url_pattern);
+  content_type_ = content_type;
+  resource_identifier_ = resource_identifier;
+  setting_ = content_setting;
+}
+
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/mock_content_settings_provider.h b/chrome/browser/content_settings/mock_content_settings_provider.h
index 113a8ae..4393868 100644
--- a/chrome/browser/content_settings/mock_content_settings_provider.h
+++ b/chrome/browser/content_settings/mock_content_settings_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,18 +9,21 @@
 #include "base/basictypes.h"
 #include "chrome/browser/content_settings/content_settings_provider.h"
 
-class MockContentSettingsProvider : public ContentSettingsProviderInterface {
+namespace content_settings {
+
+// The class MockDefaultProvider is a mock for a default content settings
+// provider.
+class MockDefaultProvider : public DefaultProviderInterface {
  public:
   // Create a content settings provider that provides a given setting for a
   // given type.
-  MockContentSettingsProvider(ContentSettingsType content_type,
+  MockDefaultProvider(ContentSettingsType content_type,
                               ContentSetting setting,
                               bool is_managed,
                               bool can_override);
-  virtual ~MockContentSettingsProvider();
+  virtual ~MockDefaultProvider();
 
-  // ContentSettingsProviderInterface implementation.
-  virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) const;
+  // DefaultProviderInterface implementation.
   virtual ContentSetting ProvideDefaultSetting(
       ContentSettingsType content_type) const;
   virtual void UpdateDefaultSetting(ContentSettingsType content_type,
@@ -34,7 +37,107 @@
   bool is_managed_;
   bool can_override_;
 
-  DISALLOW_COPY_AND_ASSIGN(MockContentSettingsProvider);
+  DISALLOW_COPY_AND_ASSIGN(MockDefaultProvider);
 };
 
+// The class MockProvider is a mock for a non default content settings provider.
+class MockProvider : public ProviderInterface {
+ public:
+  MockProvider();
+  MockProvider(ContentSettingsPattern requesting_url_pattern,
+               ContentSettingsPattern embedding_url_pattern,
+               ContentSettingsType content_type,
+               ResourceIdentifier resource_identifier,
+               ContentSetting setting,
+               bool read_only);
+  virtual ~MockProvider();
+
+  // ProviderInterface implementation
+  virtual ContentSetting GetContentSetting(
+      const GURL& requesting_url,
+      const GURL& embedding_url,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) const;
+
+  // The MockProvider is only able to store one content setting. So every time
+  // this method is called the previously set content settings is overwritten.
+  virtual void SetContentSetting(
+      const ContentSettingsPattern& requesting_url_pattern,
+      const ContentSettingsPattern& embedding_url_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      ContentSetting content_setting);
+
+  virtual void GetAllContentSettingsRules(
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      Rules* content_setting_rules) const {}
+
+  virtual void ClearAllContentSettingsRules(
+      ContentSettingsType content_type) {}
+
+  virtual void ResetToDefaults() {}
+
+  // Accessors
+  void set_requesting_url_pattern(ContentSettingsPattern pattern) {
+    requesting_url_pattern_ = pattern;
+  }
+
+  ContentSettingsPattern requesting_url_pattern() {
+    return requesting_url_pattern_;
+  }
+
+  void set_embedding_url_pattern(ContentSettingsPattern pattern) {
+    embedding_url_pattern_ = pattern;
+  }
+
+  ContentSettingsPattern embedding_url_pattern() {
+    return embedding_url_pattern_;
+  }
+
+  void set_content_type(ContentSettingsType content_type) {
+    content_type_ = content_type;
+  }
+
+  ContentSettingsType content_type() {
+    return content_type_;
+  }
+
+  void set_resource_identifier(ResourceIdentifier resource_identifier) {
+    resource_identifier_ = resource_identifier;
+  }
+
+  ResourceIdentifier resource_identifier() {
+    return resource_identifier_;
+  }
+
+  void set_setting(ContentSetting setting) {
+    setting_ = setting;
+  }
+
+  ContentSetting setting() {
+    return setting_;
+  }
+
+  void set_read_only(bool read_only) {
+    read_only_ = read_only;
+  }
+
+  bool read_only() {
+    return read_only_;
+  }
+
+ private:
+  ContentSettingsPattern requesting_url_pattern_;
+  ContentSettingsPattern embedding_url_pattern_;
+  ContentSettingsType content_type_;
+  ResourceIdentifier resource_identifier_;
+  ContentSetting setting_;
+  bool read_only_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockProvider);
+};
+
+}  // namespace content_settings
+
 #endif  // CHROME_BROWSER_CONTENT_SETTINGS_MOCK_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/policy_content_settings_provider.cc b/chrome/browser/content_settings/policy_content_settings_provider.cc
index 5bc8e9f..d39acef 100644
--- a/chrome/browser/content_settings/policy_content_settings_provider.cc
+++ b/chrome/browser/content_settings/policy_content_settings_provider.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/content_settings/policy_content_settings_provider.h"
 
+#include <string>
+
 #include "base/command_line.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/content_settings/content_settings_details.h"
@@ -11,7 +13,6 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/scoped_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_source.h"
@@ -37,7 +38,9 @@
 
 }  // namespace
 
-PolicyContentSettingsProvider::PolicyContentSettingsProvider(Profile* profile)
+namespace content_settings {
+
+PolicyDefaultProvider::PolicyDefaultProvider(Profile* profile)
     : profile_(profile),
       is_off_the_record_(profile_->IsOffTheRecord()) {
   PrefService* prefs = profile->GetPrefs();
@@ -64,35 +67,24 @@
                               Source<Profile>(profile_));
 }
 
-PolicyContentSettingsProvider::~PolicyContentSettingsProvider() {
+PolicyDefaultProvider::~PolicyDefaultProvider() {
   UnregisterObservers();
 }
 
-bool PolicyContentSettingsProvider::CanProvideDefaultSetting(
+ContentSetting PolicyDefaultProvider::ProvideDefaultSetting(
     ContentSettingsType content_type) const {
-  AutoLock lock(lock_);
-  if (managed_default_content_settings_.settings[content_type] !=
-      CONTENT_SETTING_DEFAULT) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-ContentSetting PolicyContentSettingsProvider::ProvideDefaultSetting(
-    ContentSettingsType content_type) const {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   return managed_default_content_settings_.settings[content_type];
 }
 
-void PolicyContentSettingsProvider::UpdateDefaultSetting(
+void PolicyDefaultProvider::UpdateDefaultSetting(
     ContentSettingsType content_type,
     ContentSetting setting) {
 }
 
-bool PolicyContentSettingsProvider::DefaultSettingIsManaged(
+bool PolicyDefaultProvider::DefaultSettingIsManaged(
     ContentSettingsType content_type) const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (managed_default_content_settings_.settings[content_type] !=
       CONTENT_SETTING_DEFAULT) {
     return true;
@@ -101,12 +93,12 @@
   }
 }
 
-void PolicyContentSettingsProvider::ResetToDefaults() {
+void PolicyDefaultProvider::ResetToDefaults() {
 }
 
-void PolicyContentSettingsProvider::Observe(NotificationType type,
-                                          const NotificationSource& source,
-                                          const NotificationDetails& details) {
+void PolicyDefaultProvider::Observe(NotificationType type,
+                                    const NotificationSource& source,
+                                    const NotificationDetails& details) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   if (type == NotificationType::PREF_CHANGED) {
@@ -139,7 +131,7 @@
   }
 }
 
-void PolicyContentSettingsProvider::UnregisterObservers() {
+void PolicyDefaultProvider::UnregisterObservers() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!profile_)
     return;
@@ -150,7 +142,7 @@
 }
 
 
-void PolicyContentSettingsProvider::NotifyObservers(
+void PolicyDefaultProvider::NotifyObservers(
     const ContentSettingsDetails& details) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (profile_ == NULL)
@@ -161,7 +153,7 @@
       Details<const ContentSettingsDetails>(&details));
 }
 
-void PolicyContentSettingsProvider::ReadManagedDefaultSettings() {
+void PolicyDefaultProvider::ReadManagedDefaultSettings() {
   for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) {
     if (kPrefToManageType[type] == NULL) {
       // TODO(markusheintz): Handle Geolocation and notification separately.
@@ -171,24 +163,24 @@
   }
 }
 
-void PolicyContentSettingsProvider::UpdateManagedDefaultSetting(
+void PolicyDefaultProvider::UpdateManagedDefaultSetting(
     ContentSettingsType type) {
   // If a pref to manage a default-content-setting was not set (NOTICE:
   // "HasPrefPath" returns false if no value was set for a registered pref) then
   // the default value of the preference is used. The default value of a
-  // preference to manage a default-content-settings is
-  // CONTENT_SETTING_DEFAULT. This indicates that no managed value is set. If a
-  // pref was set, than it MUST be managed.
+  // preference to manage a default-content-settings is CONTENT_SETTING_DEFAULT.
+  // This indicates that no managed value is set. If a pref was set, than it
+  // MUST be managed.
   PrefService* prefs = profile_->GetPrefs();
   DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) ||
           prefs->IsManagedPreference(kPrefToManageType[type]));
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   managed_default_content_settings_.settings[type] = IntToContentSetting(
       prefs->GetInteger(kPrefToManageType[type]));
 }
 
 // static
-void PolicyContentSettingsProvider::RegisterUserPrefs(PrefService* prefs) {
+void PolicyDefaultProvider::RegisterUserPrefs(PrefService* prefs) {
   // Preferences for default content setting policies. A policy is not set of
   // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT.
   prefs->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting,
@@ -202,3 +194,5 @@
   prefs->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting,
       CONTENT_SETTING_DEFAULT);
 }
+
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/policy_content_settings_provider.h b/chrome/browser/content_settings/policy_content_settings_provider.h
index 1844234..b63e19b 100644
--- a/chrome/browser/content_settings/policy_content_settings_provider.h
+++ b/chrome/browser/content_settings/policy_content_settings_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 // A content settings provider that takes its settings out of policies.
 
 #include "base/basictypes.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/content_settings/content_settings_provider.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/common/notification_observer.h"
@@ -20,14 +20,15 @@
 class PrefService;
 class Profile;
 
-class PolicyContentSettingsProvider : public ContentSettingsProviderInterface,
-                                      public NotificationObserver {
- public:
-  explicit PolicyContentSettingsProvider(Profile* profile);
-  virtual ~PolicyContentSettingsProvider();
+namespace content_settings {
 
-  // ContentSettingsProviderInterface implementation.
-  virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) const;
+class PolicyDefaultProvider : public DefaultProviderInterface,
+                              public NotificationObserver {
+ public:
+  explicit PolicyDefaultProvider(Profile* profile);
+  virtual ~PolicyDefaultProvider();
+
+  // DefaultContentSettingsProvider implementation.
   virtual ContentSetting ProvideDefaultSetting(
       ContentSettingsType content_type) const;
   virtual void UpdateDefaultSetting(ContentSettingsType content_type,
@@ -67,12 +68,14 @@
 
   // Used around accesses to the managed_default_content_settings_ object to
   // guarantee thread safety.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   PrefChangeRegistrar pref_change_registrar_;
   NotificationRegistrar notification_registrar_;
 
-  DISALLOW_COPY_AND_ASSIGN(PolicyContentSettingsProvider);
+  DISALLOW_COPY_AND_ASSIGN(PolicyDefaultProvider);
 };
 
+}  // namespace content_settings
+
 #endif  // CHROME_BROWSER_CONTENT_SETTINGS_POLICY_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc b/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc
index 9c639ab..6aa9a88 100644
--- a/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc
+++ b/chrome/browser/content_settings/policy_content_settings_provider_unittest.cc
@@ -4,7 +4,8 @@
 
 #include "chrome/browser/content_settings/policy_content_settings_provider.h"
 
-#include "chrome/browser/content_settings/host_content_settings_map_unittest.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/content_settings/stub_settings_observer.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -13,11 +14,11 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 
-namespace {
+namespace content_settings {
 
-class PolicyContentSettingsProviderTest : public testing::Test {
+class PolicyDefaultProviderTest : public testing::Test {
  public:
-  PolicyContentSettingsProviderTest()
+  PolicyDefaultProviderTest()
       : ui_thread_(BrowserThread::UI, &message_loop_) {
   }
 
@@ -26,23 +27,19 @@
   BrowserThread ui_thread_;
 };
 
-TEST_F(PolicyContentSettingsProviderTest, DefaultValues) {
+TEST_F(PolicyDefaultProviderTest, DefaultValues) {
   TestingProfile profile;
-  PolicyContentSettingsProvider provider(&profile);
+  PolicyDefaultProvider provider(&profile);
   TestingPrefService* prefs = profile.GetTestingPrefService();
 
   // By default, policies should be off.
   ASSERT_FALSE(
-      provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
-  ASSERT_FALSE(
       provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES));
 
   // Set managed-default-content-setting through the coresponding preferences.
   prefs->SetManagedPref(prefs::kManagedDefaultCookiesSetting,
                         Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
   ASSERT_TRUE(
-      provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
-  ASSERT_TRUE(
       provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES));
   ASSERT_EQ(CONTENT_SETTING_BLOCK,
             provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
@@ -50,15 +47,13 @@
   // Remove managed-default-content-settings-preferences.
   prefs->RemoveManagedPref(prefs::kManagedDefaultCookiesSetting);
   ASSERT_FALSE(
-      provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
-  ASSERT_FALSE(
       provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES));
 }
 
 // When a default-content-setting is set to a managed setting a
 // CONTENT_SETTINGS_CHANGED notification should be fired. The same should happen
 // if the managed setting is removed.
-TEST_F(PolicyContentSettingsProviderTest, ObserveManagedSettingsChange) {
+TEST_F(PolicyDefaultProviderTest, ObserveManagedSettingsChange) {
   TestingProfile profile;
   StubSettingsObserver observer;
   // Make sure the content settings map exists.
@@ -85,4 +80,4 @@
   EXPECT_EQ(2, observer.counter);
 }
 
-}  // namespace
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/pref_content_settings_provider.cc b/chrome/browser/content_settings/pref_content_settings_provider.cc
index 01ac055..bb6360e 100644
--- a/chrome/browser/content_settings/pref_content_settings_provider.cc
+++ b/chrome/browser/content_settings/pref_content_settings_provider.cc
@@ -4,6 +4,10 @@
 
 #include "chrome/browser/content_settings/pref_content_settings_provider.h"
 
+#include <string>
+#include <vector>
+#include <utility>
+
 #include "base/command_line.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/content_settings/content_settings_details.h"
@@ -12,13 +16,28 @@
 #include "chrome/browser/prefs/scoped_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/content_settings.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/pref_names.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
 
 namespace {
 
+// The preference keys where resource identifiers are stored for
+// ContentSettingsType values that support resource identifiers.
+const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
+  NULL,
+  NULL,
+  NULL,
+  "per_plugin",
+  NULL,
+  NULL,  // Not used for Geolocation
+  NULL,  // Not used for Notifications
+};
+
 // The default setting for each content type.
 const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = {
   CONTENT_SETTING_ALLOW,  // CONTENT_SETTINGS_TYPE_COOKIES
@@ -41,6 +60,17 @@
   NULL,  // Not used for Notifications
 };
 
+// True if a given content settings type requires additional resource
+// identifiers.
+const bool kRequiresResourceIdentifier[CONTENT_SETTINGS_NUM_TYPES] = {
+  false,  // CONTENT_SETTINGS_TYPE_COOKIES
+  false,  // CONTENT_SETTINGS_TYPE_IMAGES
+  false,  // CONTET_SETTINGS_TYPE_JAVASCRIPT
+  true,   // CONTENT_SETTINGS_TYPE_PLUGINS
+  false,  // CONTENT_SETTINGS_TYPE_POPUPS
+  false,  // Not used for Geolocation
+  false,  // Not used for Notifications
+};
 
 // Map ASK for the plugins content type to BLOCK if click-to-play is
 // not enabled.
@@ -57,7 +87,14 @@
 
 }  // namespace
 
-PrefContentSettingsProvider::PrefContentSettingsProvider(Profile* profile)
+namespace content_settings {
+
+struct PrefProvider::ExtendedContentSettings {
+  ContentSettings content_settings;
+  ResourceContentSettings content_settings_for_resources;
+};
+
+PrefDefaultProvider::PrefDefaultProvider(Profile* profile)
     : profile_(profile),
       is_off_the_record_(profile_->IsOffTheRecord()),
       updating_preferences_(false) {
@@ -74,22 +111,17 @@
                               Source<Profile>(profile_));
 }
 
-PrefContentSettingsProvider::~PrefContentSettingsProvider() {
+PrefDefaultProvider::~PrefDefaultProvider() {
   UnregisterObservers();
 }
 
-bool PrefContentSettingsProvider::CanProvideDefaultSetting(
+ContentSetting PrefDefaultProvider::ProvideDefaultSetting(
     ContentSettingsType content_type) const {
-  return true;
-}
-
-ContentSetting PrefContentSettingsProvider::ProvideDefaultSetting(
-    ContentSettingsType content_type) const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   return default_content_settings_.settings[content_type];
 }
 
-void PrefContentSettingsProvider::UpdateDefaultSetting(
+void PrefDefaultProvider::UpdateDefaultSetting(
     ContentSettingsType content_type,
     ContentSetting setting) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -111,7 +143,7 @@
   std::string dictionary_path(kTypeNames[content_type]);
   updating_preferences_ = true;
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     ScopedPrefUpdate update(prefs, prefs::kDefaultContentSettings);
     if ((setting == CONTENT_SETTING_DEFAULT) ||
         (setting == kDefaultSettings[content_type])) {
@@ -131,14 +163,14 @@
       ContentSettingsDetails(ContentSettingsPattern(), content_type, ""));
 }
 
-bool PrefContentSettingsProvider::DefaultSettingIsManaged(
+bool PrefDefaultProvider::DefaultSettingIsManaged(
     ContentSettingsType content_type) const {
   return false;
 }
 
-void PrefContentSettingsProvider::ResetToDefaults() {
+void PrefDefaultProvider::ResetToDefaults() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   default_content_settings_ = ContentSettings();
   ForceDefaultsToBeExplicit();
 
@@ -150,9 +182,9 @@
   }
 }
 
-void PrefContentSettingsProvider::Observe(NotificationType type,
-                                          const NotificationSource& source,
-                                          const NotificationDetails& details) {
+void PrefDefaultProvider::Observe(NotificationType type,
+                                  const NotificationSource& source,
+                                  const NotificationDetails& details) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   if (type == NotificationType::PREF_CHANGED) {
@@ -180,7 +212,7 @@
   }
 }
 
-void PrefContentSettingsProvider::UnregisterObservers() {
+void PrefDefaultProvider::UnregisterObservers() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!profile_)
     return;
@@ -190,12 +222,12 @@
   profile_ = NULL;
 }
 
-void PrefContentSettingsProvider::ReadDefaultSettings(bool overwrite) {
+void PrefDefaultProvider::ReadDefaultSettings(bool overwrite) {
   PrefService* prefs = profile_->GetPrefs();
   const DictionaryValue* default_settings_dictionary =
       prefs->GetDictionary(prefs::kDefaultContentSettings);
 
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   if (overwrite)
     default_content_settings_ = ContentSettings();
@@ -208,7 +240,7 @@
   ForceDefaultsToBeExplicit();
 }
 
-void PrefContentSettingsProvider::ForceDefaultsToBeExplicit() {
+void PrefDefaultProvider::ForceDefaultsToBeExplicit() {
   DCHECK_EQ(arraysize(kDefaultSettings),
             static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
 
@@ -218,7 +250,7 @@
   }
 }
 
-void PrefContentSettingsProvider::GetSettingsFromDictionary(
+void PrefDefaultProvider::GetSettingsFromDictionary(
     const DictionaryValue* dictionary,
     ContentSettings* settings) {
   for (DictionaryValue::key_iterator i(dictionary->begin_keys());
@@ -245,7 +277,7 @@
                        settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]);
 }
 
-void PrefContentSettingsProvider::NotifyObservers(
+void PrefDefaultProvider::NotifyObservers(
     const ContentSettingsDetails& details) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (profile_ == NULL)
@@ -258,6 +290,681 @@
 
 
 // static
-void PrefContentSettingsProvider::RegisterUserPrefs(PrefService* prefs) {
+void PrefDefaultProvider::RegisterUserPrefs(PrefService* prefs) {
   prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings);
 }
+
+// ////////////////////////////////////////////////////////////////////////////
+// PrefProvider::
+//
+
+// static
+void PrefProvider::RegisterUserPrefs(PrefService* prefs) {
+  prefs->RegisterIntegerPref(prefs::kContentSettingsVersion,
+      ContentSettingsPattern::kContentSettingsPatternVersion);
+  prefs->RegisterDictionaryPref(prefs::kContentSettingsPatterns);
+
+  // Obsolete prefs, for migration:
+  prefs->RegisterListPref(prefs::kPopupWhitelistedHosts);
+  prefs->RegisterDictionaryPref(prefs::kPerHostContentSettings);
+}
+
+PrefProvider::PrefProvider(Profile* profile)
+  : profile_(profile),
+    is_off_the_record_(profile_->IsOffTheRecord()),
+    updating_preferences_(false) {
+  initializing_ = true;
+  PrefService* prefs = profile_->GetPrefs();
+
+  // Migrate obsolete preferences.
+  MigrateObsoletePerhostPref(prefs);
+  MigrateObsoletePopupsPref(prefs);
+
+  // Verify preferences version.
+  if (!prefs->HasPrefPath(prefs::kContentSettingsVersion)) {
+    prefs->SetInteger(prefs::kContentSettingsVersion,
+                      ContentSettingsPattern::kContentSettingsPatternVersion);
+  }
+  if (prefs->GetInteger(prefs::kContentSettingsVersion) >
+      ContentSettingsPattern::kContentSettingsPatternVersion) {
+    LOG(ERROR) << "Unknown content settings version in preferences.";
+    return;
+  }
+
+  // Read exceptions.
+  ReadExceptions(false);
+
+  pref_change_registrar_.Init(prefs);
+  pref_change_registrar_.Add(prefs::kContentSettingsPatterns, this);
+
+  notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
+                              Source<Profile>(profile_));
+  initializing_ = false;
+}
+
+bool PrefProvider::ContentSettingsTypeIsManaged(
+    ContentSettingsType content_type) {
+  return false;
+}
+
+ContentSetting PrefProvider::GetContentSetting(
+    const GURL& requesting_url,
+    const GURL& embedding_url,
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier) const {
+  // Support for embedding_patterns is not implemented yet.
+  DCHECK(requesting_url == embedding_url);
+
+  if (!RequiresResourceIdentifier(content_type))
+    return GetNonDefaultContentSettings(requesting_url).settings[content_type];
+
+  if (RequiresResourceIdentifier(content_type) && resource_identifier.empty())
+    return CONTENT_SETTING_DEFAULT;
+
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableResourceContentSettings)) {
+    DCHECK(!resource_identifier.empty());
+  }
+
+  base::AutoLock auto_lock(lock_);
+
+  const std::string host(net::GetHostOrSpecFromURL(requesting_url));
+  ContentSettingsTypeResourceIdentifierPair
+      requested_setting(content_type, resource_identifier);
+
+  // Check for exact matches first.
+  HostContentSettings::const_iterator i(host_content_settings_.find(host));
+  if (i != host_content_settings_.end() &&
+      i->second.content_settings_for_resources.find(requested_setting) !=
+      i->second.content_settings_for_resources.end()) {
+    return i->second.content_settings_for_resources.find(
+        requested_setting)->second;
+  }
+
+  // If this map is not for an off-the-record profile, these searches will never
+  // match. The additional off-the-record exceptions always overwrite the
+  // regular ones.
+  i = off_the_record_settings_.find(host);
+  if (i != off_the_record_settings_.end() &&
+      i->second.content_settings_for_resources.find(requested_setting) !=
+      i->second.content_settings_for_resources.end()) {
+    return i->second.content_settings_for_resources.find(
+        requested_setting)->second;
+  }
+
+  // Match patterns starting with the most concrete pattern match.
+  for (std::string key =
+       std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
+    HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
+    if (i != off_the_record_settings_.end() &&
+        i->second.content_settings_for_resources.find(requested_setting) !=
+        i->second.content_settings_for_resources.end()) {
+      return i->second.content_settings_for_resources.find(
+          requested_setting)->second;
+    }
+
+    i = host_content_settings_.find(key);
+    if (i != host_content_settings_.end() &&
+        i->second.content_settings_for_resources.find(requested_setting) !=
+        i->second.content_settings_for_resources.end()) {
+      return i->second.content_settings_for_resources.find(
+          requested_setting)->second;
+    }
+
+    const size_t next_dot =
+        key.find('.', ContentSettingsPattern::kDomainWildcardLength);
+    if (next_dot == std::string::npos)
+      break;
+    key.erase(ContentSettingsPattern::kDomainWildcardLength,
+              next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
+  }
+
+  return CONTENT_SETTING_DEFAULT;
+}
+
+void PrefProvider::SetContentSetting(
+    const ContentSettingsPattern& requesting_pattern,
+    const ContentSettingsPattern& embedding_pattern,
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier,
+    ContentSetting setting) {
+  // Support for embedding_patterns is not implemented yet.
+  DCHECK(requesting_pattern == embedding_pattern);
+
+  DCHECK(kTypeNames[content_type] != NULL);  // Don't call this for Geolocation.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_NE(RequiresResourceIdentifier(content_type),
+            resource_identifier.empty());
+  DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS ||
+         setting != CONTENT_SETTING_ASK ||
+         CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kEnableClickToPlay));
+
+  const ContentSettingsPattern pattern(
+      requesting_pattern.CanonicalizePattern());
+
+  bool early_exit = false;
+  std::string pattern_str(pattern.AsString());
+  PrefService* prefs = NULL;
+  DictionaryValue* all_settings_dictionary = NULL;
+  HostContentSettings* map_to_modify = &off_the_record_settings_;
+  if (!is_off_the_record_) {
+    prefs = profile_->GetPrefs();
+    all_settings_dictionary =
+        prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
+    map_to_modify = &host_content_settings_;
+  }
+
+  {
+    base::AutoLock auto_lock(lock_);
+    if (!map_to_modify->count(pattern_str))
+      (*map_to_modify)[pattern_str].content_settings = ContentSettings();
+    HostContentSettings::iterator i(
+        map_to_modify->find(pattern_str));
+    ContentSettings& settings = i->second.content_settings;
+    if (RequiresResourceIdentifier(content_type)) {
+      settings.settings[content_type] = CONTENT_SETTING_DEFAULT;
+      if (setting != CONTENT_SETTING_DEFAULT) {
+        i->second.content_settings_for_resources[
+            ContentSettingsTypeResourceIdentifierPair(content_type,
+            resource_identifier)] = setting;
+      } else {
+        i->second.content_settings_for_resources.erase(
+            ContentSettingsTypeResourceIdentifierPair(content_type,
+            resource_identifier));
+      }
+    } else {
+      settings.settings[content_type] = setting;
+    }
+    if (AllDefault(i->second)) {
+      map_to_modify->erase(i);
+      if (all_settings_dictionary)
+        all_settings_dictionary->RemoveWithoutPathExpansion(pattern_str, NULL);
+
+      // We can't just return because |NotifyObservers()| needs to be called,
+      // without |lock_| being held.
+      early_exit = true;
+    }
+  }
+
+  if (!early_exit && all_settings_dictionary) {
+    DictionaryValue* host_settings_dictionary = NULL;
+    bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+        pattern_str, &host_settings_dictionary);
+    if (!found) {
+      host_settings_dictionary = new DictionaryValue;
+      all_settings_dictionary->SetWithoutPathExpansion(
+          pattern_str, host_settings_dictionary);
+      DCHECK_NE(setting, CONTENT_SETTING_DEFAULT);
+    }
+    if (RequiresResourceIdentifier(content_type)) {
+      std::string dictionary_path(kResourceTypeNames[content_type]);
+      DictionaryValue* resource_dictionary = NULL;
+      found = host_settings_dictionary->GetDictionary(
+          dictionary_path, &resource_dictionary);
+      if (!found) {
+        resource_dictionary = new DictionaryValue;
+        host_settings_dictionary->Set(dictionary_path, resource_dictionary);
+      }
+      if (setting == CONTENT_SETTING_DEFAULT) {
+        resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
+                                                        NULL);
+      } else {
+        resource_dictionary->SetWithoutPathExpansion(
+            resource_identifier, Value::CreateIntegerValue(setting));
+      }
+    } else {
+      std::string dictionary_path(kTypeNames[content_type]);
+      if (setting == CONTENT_SETTING_DEFAULT) {
+        host_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path,
+                                                             NULL);
+      } else {
+        host_settings_dictionary->SetWithoutPathExpansion(
+            dictionary_path, Value::CreateIntegerValue(setting));
+      }
+    }
+  }
+
+  updating_preferences_ = true;
+  if (!is_off_the_record_)
+    ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
+  updating_preferences_ = false;
+
+  NotifyObservers(ContentSettingsDetails(pattern, content_type, ""));
+}
+
+void PrefProvider::GetAllContentSettingsRules(
+    ContentSettingsType content_type,
+    const ResourceIdentifier& resource_identifier,
+    Rules* content_setting_rules) const {
+  DCHECK(RequiresResourceIdentifier(content_type) !=
+         resource_identifier.empty());
+  DCHECK(content_setting_rules);
+  content_setting_rules->clear();
+
+  const HostContentSettings* map_to_return =
+      is_off_the_record_ ? &off_the_record_settings_ : &host_content_settings_;
+  ContentSettingsTypeResourceIdentifierPair requested_setting(
+      content_type, resource_identifier);
+
+  base::AutoLock auto_lock(lock_);
+  for (HostContentSettings::const_iterator i(map_to_return->begin());
+       i != map_to_return->end(); ++i) {
+    ContentSetting setting;
+    if (RequiresResourceIdentifier(content_type)) {
+      if (i->second.content_settings_for_resources.find(requested_setting) !=
+          i->second.content_settings_for_resources.end()) {
+        setting = i->second.content_settings_for_resources.find(
+            requested_setting)->second;
+      } else {
+        setting = CONTENT_SETTING_DEFAULT;
+      }
+    } else {
+     setting = i->second.content_settings.settings[content_type];
+    }
+    if (setting != CONTENT_SETTING_DEFAULT) {
+      // Use of push_back() relies on the map iterator traversing in order of
+      // ascending keys.
+      content_setting_rules->push_back(Rule(ContentSettingsPattern(i->first),
+                                            ContentSettingsPattern(i->first),
+                                            setting));
+    }
+  }
+}
+
+void PrefProvider::ResetToDefaults() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  {
+    base::AutoLock auto_lock(lock_);
+    host_content_settings_.clear();
+    off_the_record_settings_.clear();
+  }
+
+  if (!is_off_the_record_) {
+    PrefService* prefs = profile_->GetPrefs();
+    updating_preferences_ = true;
+    prefs->ClearPref(prefs::kContentSettingsPatterns);
+    updating_preferences_ = false;
+  }
+}
+
+void PrefProvider::ClearAllContentSettingsRules(
+    ContentSettingsType content_type) {
+  DCHECK(kTypeNames[content_type] != NULL);  // Don't call this for Geolocation.
+
+  PrefService* prefs = NULL;
+  DictionaryValue* all_settings_dictionary = NULL;
+  HostContentSettings* map_to_modify = &off_the_record_settings_;
+
+  if (!is_off_the_record_) {
+    prefs = profile_->GetPrefs();
+    all_settings_dictionary =
+        prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
+    map_to_modify = &host_content_settings_;
+  }
+
+  {
+    base::AutoLock auto_lock(lock_);
+    for (HostContentSettings::iterator i(map_to_modify->begin());
+         i != map_to_modify->end(); ) {
+      if (RequiresResourceIdentifier(content_type) ||
+          i->second.content_settings.settings[content_type] !=
+          CONTENT_SETTING_DEFAULT) {
+        if (RequiresResourceIdentifier(content_type))
+          i->second.content_settings_for_resources.clear();
+        i->second.content_settings.settings[content_type] =
+            CONTENT_SETTING_DEFAULT;
+        std::string host(i->first);
+        if (AllDefault(i->second)) {
+          if (all_settings_dictionary)
+            all_settings_dictionary->RemoveWithoutPathExpansion(host, NULL);
+          map_to_modify->erase(i++);
+        } else if (all_settings_dictionary) {
+          DictionaryValue* host_settings_dictionary;
+          bool found =
+              all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+                  host, &host_settings_dictionary);
+          DCHECK(found);
+          host_settings_dictionary->RemoveWithoutPathExpansion(
+              kTypeNames[content_type], NULL);
+          ++i;
+        }
+      } else {
+        ++i;
+      }
+    }
+  }
+
+  updating_preferences_ = true;
+  if (!is_off_the_record_)
+    ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
+  updating_preferences_ = false;
+
+  NotifyObservers(
+      ContentSettingsDetails(ContentSettingsPattern(), content_type, ""));
+}
+
+void PrefProvider::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (type == NotificationType::PREF_CHANGED) {
+    DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
+    if (updating_preferences_)
+      return;
+
+    std::string* name = Details<std::string>(details).ptr();
+    if (*name == prefs::kContentSettingsPatterns) {
+      ReadExceptions(true);
+    } else {
+      NOTREACHED() << "Unexpected preference observed";
+      return;
+    }
+
+    if (!is_off_the_record_) {
+      NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(),
+                                             CONTENT_SETTINGS_TYPE_DEFAULT,
+                                             ""));
+    }
+  } else if (type == NotificationType::PROFILE_DESTROYED) {
+    DCHECK_EQ(profile_, Source<Profile>(source).ptr());
+    UnregisterObservers();
+  } else {
+    NOTREACHED() << "Unexpected notification";
+  }
+}
+
+PrefProvider::~PrefProvider() {
+  UnregisterObservers();
+}
+
+// ////////////////////////////////////////////////////////////////////////////
+// Private
+
+bool PrefProvider::RequiresResourceIdentifier(
+    ContentSettingsType content_type) const {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableResourceContentSettings)) {
+    return kRequiresResourceIdentifier[content_type];
+  } else {
+    return false;
+  }
+}
+
+bool PrefProvider::AllDefault(
+    const ExtendedContentSettings& settings) const {
+  for (size_t i = 0; i < arraysize(settings.content_settings.settings); ++i) {
+    if (settings.content_settings.settings[i] != CONTENT_SETTING_DEFAULT)
+      return false;
+  }
+  return settings.content_settings_for_resources.empty();
+}
+
+void PrefProvider::ReadExceptions(bool overwrite) {
+  base::AutoLock lock(lock_);
+
+  PrefService* prefs = profile_->GetPrefs();
+  DictionaryValue* all_settings_dictionary =
+      prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
+
+  if (overwrite)
+    host_content_settings_.clear();
+
+  // Careful: The returned value could be NULL if the pref has never been set.
+  if (all_settings_dictionary != NULL) {
+    // Convert all Unicode patterns into punycode form, then read.
+    CanonicalizeContentSettingsExceptions(all_settings_dictionary);
+
+    for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
+         i != all_settings_dictionary->end_keys(); ++i) {
+      const std::string& pattern(*i);
+      if (!ContentSettingsPattern(pattern).IsValid())
+        LOG(WARNING) << "Invalid pattern stored in content settings";
+      DictionaryValue* pattern_settings_dictionary = NULL;
+      bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+          pattern, &pattern_settings_dictionary);
+      DCHECK(found);
+      ContentSettings settings;
+      GetSettingsFromDictionary(pattern_settings_dictionary, &settings);
+      host_content_settings_[pattern].content_settings = settings;
+      GetResourceSettingsFromDictionary(
+          pattern_settings_dictionary,
+          &host_content_settings_[pattern].content_settings_for_resources);
+    }
+  }
+}
+
+void PrefProvider::CanonicalizeContentSettingsExceptions(
+    DictionaryValue* all_settings_dictionary) {
+  DCHECK(all_settings_dictionary);
+
+  std::vector<std::string> remove_items;
+  std::vector<std::pair<std::string, std::string> > move_items;
+  for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
+       i != all_settings_dictionary->end_keys(); ++i) {
+    const std::string& pattern(*i);
+    const std::string canonicalized_pattern =
+        ContentSettingsPattern(pattern).CanonicalizePattern();
+
+    if (canonicalized_pattern.empty() || canonicalized_pattern == pattern)
+      continue;
+
+    // Clear old pattern if prefs already have canonicalized pattern.
+    DictionaryValue* new_pattern_settings_dictionary = NULL;
+    if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+            canonicalized_pattern, &new_pattern_settings_dictionary)) {
+      remove_items.push_back(pattern);
+      continue;
+    }
+
+    // Move old pattern to canonicalized pattern.
+    DictionaryValue* old_pattern_settings_dictionary = NULL;
+    if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+            pattern, &old_pattern_settings_dictionary)) {
+      move_items.push_back(std::make_pair(pattern, canonicalized_pattern));
+    }
+  }
+
+  for (size_t i = 0; i < remove_items.size(); ++i) {
+    all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL);
+  }
+
+  for (size_t i = 0; i < move_items.size(); ++i) {
+    Value* pattern_settings_dictionary = NULL;
+    all_settings_dictionary->RemoveWithoutPathExpansion(
+        move_items[i].first, &pattern_settings_dictionary);
+    all_settings_dictionary->SetWithoutPathExpansion(
+        move_items[i].second, pattern_settings_dictionary);
+  }
+}
+
+void PrefProvider::GetSettingsFromDictionary(
+    const DictionaryValue* dictionary,
+    ContentSettings* settings) {
+  for (DictionaryValue::key_iterator i(dictionary->begin_keys());
+       i != dictionary->end_keys(); ++i) {
+    const std::string& content_type(*i);
+    for (size_t type = 0; type < arraysize(kTypeNames); ++type) {
+      if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type)) {
+        int setting = CONTENT_SETTING_DEFAULT;
+        bool found = dictionary->GetIntegerWithoutPathExpansion(content_type,
+                                                                &setting);
+        DCHECK(found);
+        settings->settings[type] = IntToContentSetting(setting);
+        break;
+      }
+    }
+  }
+  // Migrate obsolete cookie prompt mode.
+  if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] ==
+      CONTENT_SETTING_ASK)
+    settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK;
+
+  settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] =
+      ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS,
+                       settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]);
+}
+
+void PrefProvider::GetResourceSettingsFromDictionary(
+    const DictionaryValue* dictionary,
+    ResourceContentSettings* settings) {
+  for (DictionaryValue::key_iterator i(dictionary->begin_keys());
+       i != dictionary->end_keys(); ++i) {
+    const std::string& content_type(*i);
+    for (size_t type = 0; type < arraysize(kResourceTypeNames); ++type) {
+      if ((kResourceTypeNames[type] != NULL) &&
+          (kResourceTypeNames[type] == content_type)) {
+        DictionaryValue* resource_dictionary = NULL;
+        bool found = dictionary->GetDictionary(content_type,
+                                               &resource_dictionary);
+        DCHECK(found);
+        for (DictionaryValue::key_iterator j(resource_dictionary->begin_keys());
+             j != resource_dictionary->end_keys(); ++j) {
+          const std::string& resource_identifier(*j);
+          int setting = CONTENT_SETTING_DEFAULT;
+          bool found = resource_dictionary->GetIntegerWithoutPathExpansion(
+              resource_identifier, &setting);
+          DCHECK(found);
+          (*settings)[ContentSettingsTypeResourceIdentifierPair(
+              ContentSettingsType(type), resource_identifier)] =
+                  ClickToPlayFixup(ContentSettingsType(type),
+                                   ContentSetting(setting));
+        }
+
+        break;
+      }
+    }
+  }
+}
+
+void PrefProvider::NotifyObservers(
+    const ContentSettingsDetails& details) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (initializing_ || profile_ == NULL)
+    return;
+  NotificationService::current()->Notify(
+      NotificationType::CONTENT_SETTINGS_CHANGED,
+      Source<HostContentSettingsMap>(
+          profile_->GetHostContentSettingsMap()),
+      Details<const ContentSettingsDetails>(&details));
+}
+
+void PrefProvider::UnregisterObservers() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!profile_)
+    return;
+  pref_change_registrar_.RemoveAll();
+  notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
+                                 Source<Profile>(profile_));
+  profile_ = NULL;
+}
+
+void PrefProvider::MigrateObsoletePerhostPref(PrefService* prefs) {
+  if (prefs->HasPrefPath(prefs::kPerHostContentSettings)) {
+    const DictionaryValue* all_settings_dictionary =
+        prefs->GetDictionary(prefs::kPerHostContentSettings);
+    for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
+         i != all_settings_dictionary->end_keys(); ++i) {
+      const std::string& host(*i);
+      ContentSettingsPattern pattern(
+          std::string(ContentSettingsPattern::kDomainWildcard) + host);
+      DictionaryValue* host_settings_dictionary = NULL;
+      bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+          host, &host_settings_dictionary);
+      DCHECK(found);
+      ContentSettings settings;
+      GetSettingsFromDictionary(host_settings_dictionary, &settings);
+      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+        if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
+            !RequiresResourceIdentifier(ContentSettingsType(j))) {
+          SetContentSetting(
+              pattern,
+              pattern,
+              ContentSettingsType(j),
+              "",
+              settings.settings[j]);
+        }
+      }
+    }
+    prefs->ClearPref(prefs::kPerHostContentSettings);
+  }
+}
+
+void PrefProvider::MigrateObsoletePopupsPref(PrefService* prefs) {
+  if (prefs->HasPrefPath(prefs::kPopupWhitelistedHosts)) {
+    const ListValue* whitelist_pref =
+        prefs->GetList(prefs::kPopupWhitelistedHosts);
+    for (ListValue::const_iterator i(whitelist_pref->begin());
+         i != whitelist_pref->end(); ++i) {
+      std::string host;
+      (*i)->GetAsString(&host);
+      SetContentSetting(ContentSettingsPattern(host),
+                        ContentSettingsPattern(host),
+                        CONTENT_SETTINGS_TYPE_POPUPS,
+                        "",
+                        CONTENT_SETTING_ALLOW);
+    }
+    prefs->ClearPref(prefs::kPopupWhitelistedHosts);
+  }
+}
+
+// ////////////////////////////////////////////////////////////////////////////
+// LEGACY TBR
+//
+
+ContentSettings PrefProvider::GetNonDefaultContentSettings(
+    const GURL& url) const {
+  base::AutoLock auto_lock(lock_);
+
+  const std::string host(net::GetHostOrSpecFromURL(url));
+  ContentSettings output;
+  for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
+    output.settings[j] = CONTENT_SETTING_DEFAULT;
+
+  // Check for exact matches first.
+  HostContentSettings::const_iterator i(host_content_settings_.find(host));
+  if (i != host_content_settings_.end())
+    output = i->second.content_settings;
+
+  // If this map is not for an off-the-record profile, these searches will never
+  // match. The additional off-the-record exceptions always overwrite the
+  // regular ones.
+  i = off_the_record_settings_.find(host);
+  if (i != off_the_record_settings_.end()) {
+    for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j)
+      if (i->second.content_settings.settings[j] != CONTENT_SETTING_DEFAULT)
+        output.settings[j] = i->second.content_settings.settings[j];
+  }
+
+  // Match patterns starting with the most concrete pattern match.
+  for (std::string key =
+       std::string(ContentSettingsPattern::kDomainWildcard) + host; ; ) {
+    HostContentSettings::const_iterator i(off_the_record_settings_.find(key));
+    if (i != off_the_record_settings_.end()) {
+      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+        if (output.settings[j] == CONTENT_SETTING_DEFAULT)
+          output.settings[j] = i->second.content_settings.settings[j];
+      }
+    }
+    i = host_content_settings_.find(key);
+    if (i != host_content_settings_.end()) {
+      for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+        if (output.settings[j] == CONTENT_SETTING_DEFAULT)
+          output.settings[j] = i->second.content_settings.settings[j];
+      }
+    }
+    const size_t next_dot =
+        key.find('.', ContentSettingsPattern::kDomainWildcardLength);
+    if (next_dot == std::string::npos)
+      break;
+    key.erase(ContentSettingsPattern::kDomainWildcardLength,
+              next_dot - ContentSettingsPattern::kDomainWildcardLength + 1);
+  }
+
+  return output;
+}
+
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/pref_content_settings_provider.h b/chrome/browser/content_settings/pref_content_settings_provider.h
index 178e903..b4631b8 100644
--- a/chrome/browser/content_settings/pref_content_settings_provider.h
+++ b/chrome/browser/content_settings/pref_content_settings_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,12 @@
 
 // A content settings provider that takes its settings out of the pref service.
 
+#include <map>
+#include <string>
+#include <utility>
+
 #include "base/basictypes.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/content_settings/content_settings_provider.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/common/notification_observer.h"
@@ -20,14 +24,15 @@
 class PrefService;
 class Profile;
 
-class PrefContentSettingsProvider : public ContentSettingsProviderInterface,
-                                    public NotificationObserver {
- public:
-  explicit PrefContentSettingsProvider(Profile* profile);
-  virtual ~PrefContentSettingsProvider();
+namespace content_settings {
 
-  // ContentSettingsProviderInterface implementation.
-  virtual bool CanProvideDefaultSetting(ContentSettingsType content_type) const;
+class PrefDefaultProvider : public DefaultProviderInterface,
+                            public NotificationObserver {
+ public:
+  explicit PrefDefaultProvider(Profile* profile);
+  virtual ~PrefDefaultProvider();
+
+  // DefaultContentSettingsProvider implementation.
   virtual ContentSetting ProvideDefaultSetting(
       ContentSettingsType content_type) const;
   virtual void UpdateDefaultSetting(ContentSettingsType content_type,
@@ -73,7 +78,7 @@
 
   // Used around accesses to the default_content_settings_ object to guarantee
   // thread safety.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   PrefChangeRegistrar pref_change_registrar_;
   NotificationRegistrar notification_registrar_;
@@ -82,7 +87,119 @@
   // notifications from the preferences service that we triggered ourself.
   bool updating_preferences_;
 
-  DISALLOW_COPY_AND_ASSIGN(PrefContentSettingsProvider);
+  DISALLOW_COPY_AND_ASSIGN(PrefDefaultProvider);
 };
 
+class PrefProvider : public ProviderInterface,
+                     public NotificationObserver {
+ public:
+  static void RegisterUserPrefs(PrefService* prefs);
+
+  explicit PrefProvider(Profile* profile);
+  virtual ~PrefProvider();
+
+  // ContentSettingsProvider implementation.
+  virtual bool ContentSettingsTypeIsManaged(
+      ContentSettingsType content_type);
+
+  virtual ContentSetting GetContentSetting(
+      const GURL& requesting_url,
+      const GURL& embedding_url,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier) const;
+
+  virtual void SetContentSetting(
+      const ContentSettingsPattern& requesting_pattern,
+      const ContentSettingsPattern& embedding_pattern,
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      ContentSetting content_setting);
+
+  virtual void GetAllContentSettingsRules(
+      ContentSettingsType content_type,
+      const ResourceIdentifier& resource_identifier,
+      Rules* content_setting_rules) const;
+
+  virtual void ClearAllContentSettingsRules(
+      ContentSettingsType content_type);
+
+  virtual void ResetToDefaults();
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  typedef std::pair<ContentSettingsType, std::string>
+      ContentSettingsTypeResourceIdentifierPair;
+  typedef std::map<ContentSettingsTypeResourceIdentifierPair, ContentSetting>
+      ResourceContentSettings;
+
+  struct ExtendedContentSettings;
+
+  typedef std::map<std::string, ExtendedContentSettings> HostContentSettings;
+
+  // Various migration methods (old cookie, popup and per-host data gets
+  // migrated to the new format).
+  void MigrateObsoletePerhostPref(PrefService* prefs);
+  void MigrateObsoletePopupsPref(PrefService* prefs);
+
+  bool AllDefault(const ExtendedContentSettings& settings) const;
+
+  void ReadExceptions(bool overwrite);
+
+  bool RequiresResourceIdentifier(
+      ContentSettingsType content_type) const;
+
+  void CanonicalizeContentSettingsExceptions(
+      DictionaryValue* all_settings_dictionary);
+
+  void GetSettingsFromDictionary(
+      const DictionaryValue* dictionary,
+      ContentSettings* settings);
+
+  void GetResourceSettingsFromDictionary(
+      const DictionaryValue* dictionary,
+      ResourceContentSettings* settings);
+
+  void NotifyObservers(const ContentSettingsDetails& details);
+
+  void UnregisterObservers();
+
+  Profile* profile_;
+
+  // Whether this settings map is for an OTR session.
+  bool is_off_the_record_;
+
+  // Used around accesses to the content_settings_ object to guarantee
+  // thread safety.
+  mutable base::Lock lock_;
+
+  PrefChangeRegistrar pref_change_registrar_;
+  NotificationRegistrar notification_registrar_;
+
+  // Copies of the pref data, so that we can read it on threads other than the
+  // UI thread.
+  HostContentSettings host_content_settings_;
+
+  // Differences to the preference-stored host content settings for
+  // off-the-record settings.
+  HostContentSettings off_the_record_settings_;
+
+  // Whether we are currently updating preferences, this is used to ignore
+  // notifications from the preferences service that we triggered ourself.
+  bool updating_preferences_;
+
+  // Do not fire any Notifications as long as we are in the constructor.
+  bool initializing_;
+
+  // LEGACY: TBR
+  ContentSettings GetNonDefaultContentSettings(const GURL& url) const;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefProvider);
+};
+
+}  // namespace content_settings
+
 #endif  // CHROME_BROWSER_CONTENT_SETTINGS_PREF_CONTENT_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc b/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc
index f4289f3..80b62c3 100644
--- a/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc
+++ b/chrome/browser/content_settings/pref_content_settings_provider_unittest.cc
@@ -4,20 +4,24 @@
 
 #include "chrome/browser/content_settings/pref_content_settings_provider.h"
 
-#include "chrome/browser/content_settings/host_content_settings_map_unittest.h"
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/content_settings/stub_settings_observer.h"
 #include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/testing_pref_service.h"
 #include "chrome/test/testing_profile.h"
+#include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace content_settings {
 
-namespace {
-
-class PrefContentSettingsProviderTest : public testing::Test {
+class PrefDefaultProviderTest : public testing::Test {
  public:
-  PrefContentSettingsProviderTest()
+  PrefDefaultProviderTest()
       : ui_thread_(BrowserThread::UI, &message_loop_) {
   }
 
@@ -26,12 +30,10 @@
   BrowserThread ui_thread_;
 };
 
-TEST_F(PrefContentSettingsProviderTest, DefaultValues) {
+TEST_F(PrefDefaultProviderTest, DefaultValues) {
   TestingProfile profile;
-  PrefContentSettingsProvider provider(&profile);
+  content_settings::PrefDefaultProvider provider(&profile);
 
-  ASSERT_TRUE(
-      provider.CanProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
   ASSERT_FALSE(
       provider.DefaultSettingIsManaged(CONTENT_SETTINGS_TYPE_COOKIES));
 
@@ -47,9 +49,9 @@
             provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
 }
 
-TEST_F(PrefContentSettingsProviderTest, Observer) {
+TEST_F(PrefDefaultProviderTest, Observer) {
   TestingProfile profile;
-  PrefContentSettingsProvider provider(&profile);
+  PrefDefaultProvider provider(&profile);
   StubSettingsObserver observer;
 
   provider.UpdateDefaultSetting(
@@ -60,9 +62,9 @@
   EXPECT_EQ(1, observer.counter);
 }
 
-TEST_F(PrefContentSettingsProviderTest, ObserveDefaultPref) {
+TEST_F(PrefDefaultProviderTest, ObserveDefaultPref) {
   TestingProfile profile;
-  PrefContentSettingsProvider provider(&profile);
+  PrefDefaultProvider provider(&profile);
 
   PrefService* prefs = profile.GetPrefs();
 
@@ -90,12 +92,12 @@
             provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
 }
 
-TEST_F(PrefContentSettingsProviderTest, OffTheRecord) {
+TEST_F(PrefDefaultProviderTest, OffTheRecord) {
   TestingProfile profile;
-  PrefContentSettingsProvider provider(&profile);
+  PrefDefaultProvider provider(&profile);
 
   profile.set_off_the_record(true);
-  PrefContentSettingsProvider otr_provider(&profile);
+  PrefDefaultProvider otr_provider(&profile);
   profile.set_off_the_record(false);
 
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
@@ -121,4 +123,121 @@
             otr_provider.ProvideDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES));
 }
 
-}  // namespace
+// ////////////////////////////////////////////////////////////////////////////
+// PrefProviderTest
+//
+
+bool SettingsEqual(const ContentSettings& settings1,
+                   const ContentSettings& settings2) {
+  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+    if (settings1.settings[i] != settings2.settings[i])
+      return false;
+  }
+  return true;
+}
+
+class PrefProviderTest : public testing::Test {
+ public:
+  PrefProviderTest() : ui_thread_(
+      BrowserThread::UI, &message_loop_) {
+  }
+
+ protected:
+  MessageLoop message_loop_;
+  BrowserThread ui_thread_;
+};
+
+TEST_F(PrefProviderTest, Observer) {
+  TestingProfile profile;
+  Profile* p = &profile;
+  PrefProvider pref_content_settings_provider(p);
+  StubSettingsObserver observer;
+  ContentSettingsPattern pattern("[*.]example.com");
+
+  pref_content_settings_provider.SetContentSetting(
+      pattern,
+      pattern,
+      CONTENT_SETTINGS_TYPE_IMAGES,
+      "",
+      CONTENT_SETTING_ALLOW);
+  EXPECT_EQ(profile.GetHostContentSettingsMap(), observer.last_notifier);
+  EXPECT_EQ(pattern, observer.last_pattern);
+  EXPECT_FALSE(observer.last_update_all);
+  EXPECT_FALSE(observer.last_update_all_types);
+  EXPECT_EQ(1, observer.counter);
+}
+
+TEST_F(PrefProviderTest, Patterns) {
+  TestingProfile testing_profile;
+  PrefProvider pref_content_settings_provider(
+      testing_profile.GetOriginalProfile());
+
+  GURL host1("http://example.com/");
+  GURL host2("http://www.example.com/");
+  GURL host3("http://example.org/");
+  ContentSettingsPattern pattern1("[*.]example.com");
+  ContentSettingsPattern pattern2("example.org");
+
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+            pref_content_settings_provider.GetContentSetting(
+                host1, host1, CONTENT_SETTINGS_TYPE_IMAGES, ""));
+  pref_content_settings_provider.SetContentSetting(
+      pattern1,
+      pattern1,
+      CONTENT_SETTINGS_TYPE_IMAGES,
+      "",
+      CONTENT_SETTING_BLOCK);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
+            pref_content_settings_provider.GetContentSetting(
+                host1, host1, CONTENT_SETTINGS_TYPE_IMAGES, ""));
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
+            pref_content_settings_provider.GetContentSetting(
+                host2, host2, CONTENT_SETTINGS_TYPE_IMAGES, ""));
+
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+            pref_content_settings_provider.GetContentSetting(
+                host3, host3, CONTENT_SETTINGS_TYPE_IMAGES, ""));
+  pref_content_settings_provider.SetContentSetting(
+      pattern2,
+      pattern2,
+      CONTENT_SETTINGS_TYPE_IMAGES,
+      "",
+      CONTENT_SETTING_BLOCK);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
+            pref_content_settings_provider.GetContentSetting(
+                host3, host3, CONTENT_SETTINGS_TYPE_IMAGES, ""));
+}
+
+TEST_F(PrefProviderTest, ResourceIdentifier) {
+  // This feature is currently behind a flag.
+  CommandLine* cmd = CommandLine::ForCurrentProcess();
+  AutoReset<CommandLine> auto_reset(cmd, *cmd);
+  cmd->AppendSwitch(switches::kEnableResourceContentSettings);
+
+  TestingProfile testing_profile;
+  PrefProvider pref_content_settings_provider(
+      testing_profile.GetOriginalProfile());
+
+  GURL host("http://example.com/");
+  ContentSettingsPattern pattern("[*.]example.com");
+  std::string resource1("someplugin");
+  std::string resource2("otherplugin");
+
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+            pref_content_settings_provider.GetContentSetting(
+                host, host, CONTENT_SETTINGS_TYPE_PLUGINS, resource1));
+  pref_content_settings_provider.SetContentSetting(
+      pattern,
+      pattern,
+      CONTENT_SETTINGS_TYPE_PLUGINS,
+      resource1,
+      CONTENT_SETTING_BLOCK);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
+            pref_content_settings_provider.GetContentSetting(
+                host, host, CONTENT_SETTINGS_TYPE_PLUGINS, resource1));
+  EXPECT_EQ(CONTENT_SETTING_DEFAULT,
+            pref_content_settings_provider.GetContentSetting(
+                host, host, CONTENT_SETTINGS_TYPE_PLUGINS, resource2));
+}
+
+}  // namespace content_settings
diff --git a/chrome/browser/content_settings/stub_settings_observer.cc b/chrome/browser/content_settings/stub_settings_observer.cc
new file mode 100644
index 0000000..b042412
--- /dev/null
+++ b/chrome/browser/content_settings/stub_settings_observer.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/content_settings/stub_settings_observer.h"
+
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "googleurl/src/gurl.h"
+
+StubSettingsObserver::StubSettingsObserver()
+    : last_notifier(NULL),
+      counter(0) {
+  registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
+                 NotificationService::AllSources());
+}
+
+StubSettingsObserver::~StubSettingsObserver() {}
+
+void StubSettingsObserver::Observe(NotificationType type,
+                                   const NotificationSource& source,
+                                   const NotificationDetails& details) {
+  ++counter;
+  Source<HostContentSettingsMap> content_settings(source);
+  Details<ContentSettingsDetails> settings_details(details);
+  last_notifier = content_settings.ptr();
+  last_pattern = settings_details.ptr()->pattern();
+  last_update_all = settings_details.ptr()->update_all();
+  last_update_all_types = settings_details.ptr()->update_all_types();
+  last_type = settings_details.ptr()->type();
+  // This checks that calling a Get function from an observer doesn't
+  // deadlock.
+  last_notifier->GetContentSettings(GURL("http://random-hostname.com/"));
+}
diff --git a/chrome/browser/content_settings/stub_settings_observer.h b/chrome/browser/content_settings/stub_settings_observer.h
new file mode 100644
index 0000000..452de07
--- /dev/null
+++ b/chrome/browser/content_settings/stub_settings_observer.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CONTENT_SETTINGS_STUB_SETTINGS_OBSERVER_H_
+#define CHROME_BROWSER_CONTENT_SETTINGS_STUB_SETTINGS_OBSERVER_H_
+#pragma once
+
+#include "chrome/browser/content_settings/content_settings_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
+
+class HostContentSettingsMap;
+
+class StubSettingsObserver : public NotificationObserver {
+ public:
+  StubSettingsObserver();
+  virtual ~StubSettingsObserver();
+
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  HostContentSettingsMap* last_notifier;
+  ContentSettingsPattern last_pattern;
+  bool last_update_all;
+  bool last_update_all_types;
+  int counter;
+  ContentSettingsType last_type;
+
+ private:
+  NotificationRegistrar registrar_;
+};
+
+#endif  // CHROME_BROWSER_CONTENT_SETTINGS_STUB_SETTINGS_OBSERVER_H_
diff --git a/chrome/browser/cookies_tree_model.cc b/chrome/browser/cookies_tree_model.cc
index 78a873c..4f07e10 100644
--- a/chrome/browser/cookies_tree_model.cc
+++ b/chrome/browser/cookies_tree_model.cc
@@ -8,8 +8,6 @@
 #include <functional>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/linked_ptr.h"
 #include "base/string_util.h"
@@ -23,6 +21,8 @@
 #include "net/base/registry_controlled_domain.h"
 #include "net/url_request/url_request_context.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 static const char kFileOriginNodeName[] = "file://";
 
@@ -505,7 +505,7 @@
     BrowsingDataLocalStorageHelper* session_storage_helper,
     BrowsingDataAppCacheHelper* appcache_helper,
     BrowsingDataIndexedDBHelper* indexed_db_helper)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(TreeNodeModel<CookieTreeNode>(
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::TreeNodeModel<CookieTreeNode>(
           new CookieTreeRootNode(this))),
       cookie_monster_(cookie_monster),
       appcache_helper_(appcache_helper),
@@ -568,33 +568,27 @@
 // Returns the index of the icon to use for |node|. Return -1 to use the
 // default icon. The index is relative to the list of icons returned from
 // GetIcons.
-int CookiesTreeModel::GetIconIndex(TreeModelNode* node) {
+int CookiesTreeModel::GetIconIndex(ui::TreeModelNode* node) {
   CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
   switch (ct_node->GetDetailedInfo().node_type) {
     case CookieTreeNode::DetailedInfo::TYPE_ORIGIN:
       return ORIGIN;
-      break;
     case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
       return COOKIE;
-      break;
     case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
       return DATABASE;
-      break;
     case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
       return DATABASE;  // close enough
-      break;
     case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
       return DATABASE;  // ditto
-      break;
     case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
       return DATABASE;  // ditto
-      break;
     case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
       return DATABASE;  // ditto
-      break;
     default:
-      return -1;
+      break;
   }
+  return -1;
 }
 
 void CookiesTreeModel::LoadCookies() {
@@ -666,16 +660,16 @@
   NotifyObserverEndBatch();
 }
 
-void CookiesTreeModel::AddObserver(Observer* observer) {
+void CookiesTreeModel::AddCookiesTreeObserver(Observer* observer) {
   cookies_observer_list_.AddObserver(observer);
   // Call super so that TreeNodeModel can notify, too.
-  TreeNodeModel<CookieTreeNode>::AddObserver(observer);
+  ui::TreeNodeModel<CookieTreeNode>::AddObserver(observer);
 }
 
-void CookiesTreeModel::RemoveObserver(Observer* observer) {
+void CookiesTreeModel::RemoveCookiesTreeObserver(Observer* observer) {
   cookies_observer_list_.RemoveObserver(observer);
   // Call super so that TreeNodeModel doesn't have dead pointers.
-  TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
+  ui::TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
 }
 
 void CookiesTreeModel::OnAppCacheModelInfoLoaded() {
diff --git a/chrome/browser/cookies_tree_model.h b/chrome/browser/cookies_tree_model.h
index 20b2a71..206174c 100644
--- a/chrome/browser/cookies_tree_model.h
+++ b/chrome/browser/cookies_tree_model.h
@@ -12,7 +12,6 @@
 #include <string>
 #include <vector>
 
-#include "app/tree_node_model.h"
 #include "base/observer_list.h"
 #include "base/ref_counted.h"
 #include "base/string16.h"
@@ -22,6 +21,7 @@
 #include "chrome/browser/browsing_data_indexed_db_helper.h"
 #include "chrome/browser/browsing_data_local_storage_helper.h"
 #include "net/base/cookie_monster.h"
+#include "ui/base/models/tree_node_model.h"
 
 class CookiesTreeModel;
 class CookieTreeAppCacheNode;
@@ -43,7 +43,7 @@
 // view, from which all other types are derived. Specialized from TreeNode in
 // that it has a notion of deleting objects stored in the profile, and being
 // able to have its children do the same.
-class CookieTreeNode : public TreeNode<CookieTreeNode> {
+class CookieTreeNode : public ui::TreeNode<CookieTreeNode> {
  public:
   // Used to pull out information for the InfoView (the details display below
   // the tree control.)
@@ -131,7 +131,7 @@
 
   CookieTreeNode() {}
   explicit CookieTreeNode(const string16& title)
-      : TreeNode<CookieTreeNode>(title) {}
+      : ui::TreeNode<CookieTreeNode>(title) {}
   virtual ~CookieTreeNode() {}
 
   // Delete backend storage for this node, and any children nodes. (E.g. delete
@@ -448,14 +448,14 @@
 
 
 // CookiesTreeModel -----------------------------------------------------------
-class CookiesTreeModel : public TreeNodeModel<CookieTreeNode> {
+class CookiesTreeModel : public ui::TreeNodeModel<CookieTreeNode> {
  public:
   // Because non-cookie nodes are fetched in a background thread, they are not
   // present at the time the Model is created. The Model then notifies its
   // observers for every item added from databases, local storage, and
   // appcache. We extend the Observer interface to add notifications before and
   // after these batch inserts.
-  class Observer : public TreeModelObserver {
+  class Observer : public ui::TreeModelObserver {
    public:
     virtual void TreeModelBeginBatch(CookiesTreeModel* model) {}
     virtual void TreeModelEndBatch(CookiesTreeModel* model) {}
@@ -470,7 +470,7 @@
       BrowsingDataIndexedDBHelper* indexed_db_helper);
   virtual ~CookiesTreeModel();
 
-  // TreeModel methods:
+  // ui::TreeModel methods:
   // Returns the set of icons for the nodes in the tree. You only need override
   // this if you don't want to use the default folder icons.
   virtual void GetIcons(std::vector<SkBitmap>* icons);
@@ -478,7 +478,7 @@
   // Returns the index of the icon to use for |node|. Return -1 to use the
   // default icon. The index is relative to the list of icons returned from
   // GetIcons.
-  virtual int GetIconIndex(TreeModelNode* node);
+  virtual int GetIconIndex(ui::TreeModelNode* node);
 
   // CookiesTreeModel methods:
   void DeleteAllStoredObjects();
@@ -487,15 +487,12 @@
   // Filter the origins to only display matched results.
   void UpdateSearchResults(const std::wstring& filter);
 
-  // Overload the Add/Remove observer methods so we can notify about
-  // CookiesTreeModel-specific things. Note that this is NOT overriding the
-  // method by the same name in TreeNodeModel because the argument type is
-  // different. Therefore, if this AddObserver(TreeModelObserver*) is called,
-  // the observer will NOT be notified about batching. This is also why we
-  // maintain a separate list of observers that are specifically Observer*
-  // objects.
-  virtual void AddObserver(Observer* observer);
-  virtual void RemoveObserver(Observer* observer);
+  // Manages CookiesTreeModel::Observers. This will also call
+  // TreeNodeModel::AddObserver so that it gets all the proper notifications.
+  // Note that the converse is not true: simply adding a TreeModelObserver will
+  // not get CookiesTreeModel::Observer notifications.
+  virtual void AddCookiesTreeObserver(Observer* observer);
+  virtual void RemoveCookiesTreeObserver(Observer* observer);
 
  private:
   enum CookieIconIndex {
diff --git a/chrome/browser/cookies_tree_model_unittest.cc b/chrome/browser/cookies_tree_model_unittest.cc
index 8d03b2a..ccf43f2 100644
--- a/chrome/browser/cookies_tree_model_unittest.cc
+++ b/chrome/browser/cookies_tree_model_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <string>
 
-#include "chrome/browser/content_settings/host_content_settings_map_unittest.h"
+#include "chrome/browser/content_settings/stub_settings_observer.h"
 #include "chrome/browser/mock_browsing_data_appcache_helper.h"
 #include "chrome/browser/mock_browsing_data_database_helper.h"
 #include "chrome/browser/mock_browsing_data_indexed_db_helper.h"
diff --git a/chrome/browser/crash_handler_host_linux.cc b/chrome/browser/crash_handler_host_linux.cc
index a22ff95..aa14cf5 100644
--- a/chrome/browser/crash_handler_host_linux.cc
+++ b/chrome/browser/crash_handler_host_linux.cc
@@ -354,6 +354,22 @@
   return shutting_down_;
 }
 
+GpuCrashHandlerHostLinux::GpuCrashHandlerHostLinux() {
+  InitCrashUploaderThread();
+}
+
+GpuCrashHandlerHostLinux::~GpuCrashHandlerHostLinux() {
+}
+
+void GpuCrashHandlerHostLinux::SetProcessType() {
+  process_type_ = "gpu-process";
+}
+
+// static
+GpuCrashHandlerHostLinux* GpuCrashHandlerHostLinux::GetInstance() {
+  return Singleton<GpuCrashHandlerHostLinux>::get();
+}
+
 PluginCrashHandlerHostLinux::PluginCrashHandlerHostLinux() {
   InitCrashUploaderThread();
 }
diff --git a/chrome/browser/crash_handler_host_linux.h b/chrome/browser/crash_handler_host_linux.h
index 9ff5333..8eb5947 100644
--- a/chrome/browser/crash_handler_host_linux.h
+++ b/chrome/browser/crash_handler_host_linux.h
@@ -79,6 +79,23 @@
   DISALLOW_COPY_AND_ASSIGN(CrashHandlerHostLinux);
 };
 
+class GpuCrashHandlerHostLinux : public CrashHandlerHostLinux {
+ public:
+  // Returns the singleton instance.
+  static GpuCrashHandlerHostLinux* GetInstance();
+
+ private:
+  friend struct DefaultSingletonTraits<GpuCrashHandlerHostLinux>;
+  GpuCrashHandlerHostLinux();
+  virtual ~GpuCrashHandlerHostLinux();
+
+#if defined(USE_LINUX_BREAKPAD)
+  virtual void SetProcessType();
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(GpuCrashHandlerHostLinux);
+};
+
 class PluginCrashHandlerHostLinux : public CrashHandlerHostLinux {
  public:
   // Returns the singleton instance.
diff --git a/chrome/browser/crash_handler_host_linux_stub.cc b/chrome/browser/crash_handler_host_linux_stub.cc
index 157d772..3ec9ebb 100644
--- a/chrome/browser/crash_handler_host_linux_stub.cc
+++ b/chrome/browser/crash_handler_host_linux_stub.cc
@@ -26,6 +26,17 @@
 void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {
 }
 
+GpuCrashHandlerHostLinux::GpuCrashHandlerHostLinux() {
+}
+
+GpuCrashHandlerHostLinux::~GpuCrashHandlerHostLinux() {
+}
+
+// static
+GpuCrashHandlerHostLinux* GpuCrashHandlerHostLinux::GetInstance() {
+  return Singleton<GpuCrashHandlerHostLinux>::get();
+}
+
 PluginCrashHandlerHostLinux::PluginCrashHandlerHostLinux() {
 }
 
diff --git a/chrome/browser/crash_recovery_browsertest.cc b/chrome/browser/crash_recovery_browsertest.cc
index 92b5393..190e798 100644
--- a/chrome/browser/crash_recovery_browsertest.cc
+++ b/chrome/browser/crash_recovery_browsertest.cc
@@ -17,8 +17,10 @@
 void SimulateRendererCrash(Browser* browser) {
   browser->OpenURL(GURL(chrome::kAboutCrashURL), GURL(), CURRENT_TAB,
                    PageTransition::TYPED);
+  LOG(ERROR) << "SimulateRendererCrash, before WaitForNotification";
   ui_test_utils::WaitForNotification(
       NotificationType::TAB_CONTENTS_DISCONNECTED);
+  LOG(ERROR) << "SimulateRendererCrash, after WaitForNotification";
 }
 
 }  // namespace
@@ -26,16 +28,9 @@
 class CrashRecoveryBrowserTest : public InProcessBrowserTest {
 };
 
-// http://crbug.com/29331 - Causes an OS crash dialog in release mode, needs to
-// be fixed before it can be enabled to not cause the bots issues.
-#if defined(OS_MACOSX)
-#define MAYBE_Reload DISABLED_Reload
-#else
-#define MAYBE_Reload Reload
-#endif
-
 // Test that reload works after a crash.
-IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, MAYBE_Reload) {
+// Disabled, http://crbug.com/29331, http://crbug.com/69637.
+IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, Reload) {
   // The title of the active tab should change each time this URL is loaded.
   GURL url(
       "data:text/html,<script>document.title=new Date().valueOf()</script>");
@@ -48,7 +43,9 @@
                                                 &title_before_crash));
   SimulateRendererCrash(browser());
   browser()->Reload(CURRENT_TAB);
+  LOG(ERROR) << "Before WaitForNavigationInCurrentTab";
   ASSERT_TRUE(ui_test_utils::WaitForNavigationInCurrentTab(browser()));
+  LOG(ERROR) << "After WaitForNavigationInCurrentTab";
   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                 &title_after_crash));
   EXPECT_NE(title_before_crash, title_after_crash);
@@ -59,7 +56,7 @@
 // ID of the RenderProcessHost was stale, so the NavigationEntry in the new tab
 // was not committed.  This prevents regression of that bug.
 // http://crbug.com/57158 - Times out sometimes on all platforms.
-IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, DISABLED_LoadInNewTab) {
+IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, LoadInNewTab) {
   const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");
 
   ui_test_utils::NavigateToURL(browser(),
@@ -73,7 +70,9 @@
                                                 &title_before_crash));
   SimulateRendererCrash(browser());
   browser()->Reload(CURRENT_TAB);
+  LOG(ERROR) << "Before WaitForNavigationInCurrentTab";
   ASSERT_TRUE(ui_test_utils::WaitForNavigationInCurrentTab(browser()));
+  LOG(ERROR) << "After WaitForNavigationInCurrentTab";
   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                 &title_after_crash));
   EXPECT_EQ(title_before_crash, title_after_crash);
diff --git a/chrome/browser/cross_site_request_manager.cc b/chrome/browser/cross_site_request_manager.cc
index d12e9a4..6514933 100644
--- a/chrome/browser/cross_site_request_manager.cc
+++ b/chrome/browser/cross_site_request_manager.cc
@@ -8,7 +8,7 @@
 
 bool CrossSiteRequestManager::HasPendingCrossSiteRequest(int renderer_id,
                                                          int render_view_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   std::pair<int, int> key(renderer_id, render_view_id);
   return pending_cross_site_views_.find(key) !=
@@ -18,7 +18,7 @@
 void CrossSiteRequestManager::SetHasPendingCrossSiteRequest(int renderer_id,
                                                             int render_view_id,
                                                             bool has_pending) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   std::pair<int, int> key(renderer_id, render_view_id);
   if (has_pending) {
diff --git a/chrome/browser/cross_site_request_manager.h b/chrome/browser/cross_site_request_manager.h
index 6c90b24..6615ad1 100644
--- a/chrome/browser/cross_site_request_manager.h
+++ b/chrome/browser/cross_site_request_manager.h
@@ -10,7 +10,7 @@
 #include <utility>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 
 template <typename T> struct DefaultSingletonTraits;
 
@@ -47,7 +47,7 @@
 
   // You must acquire this lock before reading or writing any members of this
   // class.  You must not block while holding this lock.
-  Lock lock_;
+  base::Lock lock_;
 
   // Set of (render_process_host_id, render_view_id) pairs of all
   // RenderViewHosts that have pending cross-site requests.  Used to pass
diff --git a/chrome/browser/custom_home_pages_table_model.cc b/chrome/browser/custom_home_pages_table_model.cc
index f63cf79..ae8dedc 100644
--- a/chrome/browser/custom_home_pages_table_model.cc
+++ b/chrome/browser/custom_home_pages_table_model.cc
@@ -4,9 +4,6 @@
 
 #include "chrome/browser/custom_home_pages_table_model.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/table_model_observer.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
@@ -16,12 +13,15 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
 #include "googleurl/src/gurl.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
 
 struct CustomHomePagesTableModel::Entry {
   Entry() : title_handle(0), fav_icon_handle(0) {}
@@ -70,6 +70,7 @@
   DCHECK(index >= 0 && index <= RowCount());
   entries_.insert(entries_.begin() + static_cast<size_t>(index), Entry());
   entries_[index].url = url;
+  LoadTitleAndFavIcon(&(entries_[index]));
   if (observer_)
     observer_->OnItemsAdded(index, 1);
 }
@@ -147,7 +148,7 @@
                                  entries_[row].title, FormattedURL(row));
 }
 
-void CustomHomePagesTableModel::SetObserver(TableModelObserver* observer) {
+void CustomHomePagesTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
diff --git a/chrome/browser/custom_home_pages_table_model.h b/chrome/browser/custom_home_pages_table_model.h
index 6699fc1..b452e8d 100644
--- a/chrome/browser/custom_home_pages_table_model.h
+++ b/chrome/browser/custom_home_pages_table_model.h
@@ -9,20 +9,23 @@
 #include <string>
 #include <vector>
 
-#include "app/table_model.h"
 #include "base/compiler_specific.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/browser/favicon_service.h"
+#include "ui/base/models/table_model.h"
 
 class GURL;
 class Profile;
 class SkBitmap;
+
+namespace ui {
 class TableModelObserver;
+}
 
 // CustomHomePagesTableModel is the model for the TableView showing the list
 // of pages the user wants opened on startup.
 
-class CustomHomePagesTableModel : public TableModel {
+class CustomHomePagesTableModel : public ui::TableModel {
  public:
   explicit CustomHomePagesTableModel(Profile* profile);
   virtual ~CustomHomePagesTableModel();
@@ -48,7 +51,7 @@
   virtual string16 GetText(int row, int column_id) OVERRIDE;
   virtual SkBitmap GetIcon(int row) OVERRIDE;
   virtual string16 GetTooltip(int row) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
  private:
   // Each item in the model is represented as an Entry. Entry stores the URL,
@@ -96,7 +99,7 @@
   // Profile used to load titles and icons.
   Profile* profile_;
 
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   // Used in loading titles and favicons.
   CancelableRequestConsumer query_consumer_;
diff --git a/chrome/browser/debugger/browser_list_tabcontents_provider.cc b/chrome/browser/debugger/browser_list_tabcontents_provider.cc
new file mode 100644
index 0000000..9321241
--- /dev/null
+++ b/chrome/browser/debugger/browser_list_tabcontents_provider.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/debugger/browser_list_tabcontents_provider.h"
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+
+DevToolsHttpProtocolHandler::InspectableTabs
+BrowserListTabContentsProvider::GetInspectableTabs() {
+  DevToolsHttpProtocolHandler::InspectableTabs tabs;
+  for (BrowserList::const_iterator it = BrowserList::begin(),
+       end = BrowserList::end(); it != end; ++it) {
+    TabStripModel* model = (*it)->tabstrip_model();
+    for (int i = 0, size = model->count(); i < size; ++i)
+      tabs.push_back(model->GetTabContentsAt(i));
+  }
+  return tabs;
+}
diff --git a/chrome/browser/debugger/browser_list_tabcontents_provider.h b/chrome/browser/debugger/browser_list_tabcontents_provider.h
new file mode 100644
index 0000000..5db5f3d
--- /dev/null
+++ b/chrome/browser/debugger/browser_list_tabcontents_provider.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DEBUGGER_BROWSER_LIST_TABCONTENTS_PROVIDER_H_
+#define CHROME_BROWSER_DEBUGGER_BROWSER_LIST_TABCONTENTS_PROVIDER_H_
+
+#include "chrome/browser/debugger/devtools_http_protocol_handler.h"
+
+class BrowserListTabContentsProvider :
+    public DevToolsHttpProtocolHandler::TabContentsProvider {
+ public:
+  BrowserListTabContentsProvider() {}
+  ~BrowserListTabContentsProvider() {}
+
+  virtual DevToolsHttpProtocolHandler::InspectableTabs GetInspectableTabs();
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowserListTabContentsProvider);
+};
+
+#endif  // CHROME_BROWSER_DEBUGGER_BROWSER_LIST_TABCONTENTS_PROVIDER_H_
diff --git a/chrome/browser/debugger/debugger_remote_service.cc b/chrome/browser/debugger/debugger_remote_service.cc
index e2ea5f2..b930365 100644
--- a/chrome/browser/debugger/debugger_remote_service.cc
+++ b/chrome/browser/debugger/debugger_remote_service.cc
@@ -330,7 +330,7 @@
   }
   std::string javascript;
   content->GetString(kDataKey, &javascript);
-  render_view_host->ExecuteJavascriptInWebFrame(std::wstring(),
-                                                UTF8ToWide(javascript));
+  render_view_host->ExecuteJavascriptInWebFrame(string16(),
+                                                UTF8ToUTF16(javascript));
   return false;
 }
diff --git a/chrome/browser/debugger/debugger_wrapper.cc b/chrome/browser/debugger/debugger_wrapper.cc
deleted file mode 100644
index 644bf05..0000000
--- a/chrome/browser/debugger/debugger_wrapper.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/debugger/debugger_wrapper.h"
-
-#include "chrome/browser/debugger/devtools_http_protocol_handler.h"
-#include "chrome/browser/debugger/debugger_remote_service.h"
-#include "chrome/browser/debugger/devtools_protocol_handler.h"
-#include "chrome/browser/debugger/devtools_remote_service.h"
-#include "chrome/browser/debugger/extension_ports_remote_service.h"
-
-DebuggerWrapper::DebuggerWrapper(int port, bool useHttp) {
-  if (port > 0) {
-    if (useHttp) {
-      http_handler_ = new DevToolsHttpProtocolHandler(port);
-      http_handler_->Start();
-    } else {
-      proto_handler_ = new DevToolsProtocolHandler(port);
-      proto_handler_->RegisterDestination(
-          new DevToolsRemoteService(proto_handler_),
-          DevToolsRemoteService::kToolName);
-      proto_handler_->RegisterDestination(
-          new DebuggerRemoteService(proto_handler_),
-          DebuggerRemoteService::kToolName);
-      proto_handler_->RegisterDestination(
-          new ExtensionPortsRemoteService(proto_handler_),
-          ExtensionPortsRemoteService::kToolName);
-      proto_handler_->Start();
-    }
-  }
-}
-
-DebuggerWrapper::~DebuggerWrapper() {
-  if (proto_handler_.get() != NULL)
-    proto_handler_->Stop();
-
-  if (http_handler_.get() != NULL)
-    http_handler_->Stop();
-}
diff --git a/chrome/browser/debugger/debugger_wrapper.h b/chrome/browser/debugger/debugger_wrapper.h
deleted file mode 100644
index a9cf7bf..0000000
--- a/chrome/browser/debugger/debugger_wrapper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Include this file if you need to access the Debugger outside of the debugger
-// project.  Don't include debugger.h directly.  If there's functionality from
-// Debugger needed, add new wrapper methods to this file.
-
-#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_WRAPPER_H_
-#define CHROME_BROWSER_DEBUGGER_DEBUGGER_WRAPPER_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-
-class DebuggerHost;
-class DevToolsHttpProtocolHandler;
-class DevToolsProtocolHandler;
-class DevToolsRemoteListenSocket;
-
-class DebuggerWrapper : public base::RefCountedThreadSafe<DebuggerWrapper> {
- public:
-  DebuggerWrapper(int port, bool useHttp);
-
- private:
-  friend class base::RefCountedThreadSafe<DebuggerWrapper>;
-
-  virtual ~DebuggerWrapper();
-
-  scoped_refptr<DevToolsProtocolHandler> proto_handler_;
-  scoped_refptr<DevToolsHttpProtocolHandler> http_handler_;
-};
-
-#endif  // CHROME_BROWSER_DEBUGGER_DEBUGGER_WRAPPER_H_
diff --git a/chrome/browser/debugger/devtools_client_host.h b/chrome/browser/debugger/devtools_client_host.h
index 952f532..4c81e87 100644
--- a/chrome/browser/debugger/devtools_client_host.h
+++ b/chrome/browser/debugger/devtools_client_host.h
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_DEBUGGER_DEVTOOLS_CLIENT_HOST_H_
 #pragma once
 
+#include <string>
+
 #include "base/basictypes.h"
 
 namespace IPC {
@@ -13,6 +15,7 @@
 }
 
 class DevToolsWindow;
+class TabContentsWrapper;
 
 // Describes interface for managing devtools clients from browser process. There
 // are currently two types of clients: devtools windows and TCP socket
@@ -34,6 +37,10 @@
   // closing.
   virtual void InspectedTabClosing() = 0;
 
+  // This method is called when tab inspected by this devtools client is
+  // navigating to |url|.
+  virtual void FrameNavigating(const std::string& url) = 0;
+
   // Sends the message to the devtools client hosted by this object.
   virtual void SendMessageToClient(const IPC::Message& msg) = 0;
 
@@ -43,6 +50,10 @@
 
   virtual DevToolsWindow* AsDevToolsWindow();
 
+  // Invoked when a tab is replaced by another tab. This is triggered by
+  // TabStripModel::ReplaceTabContentsAt.
+  virtual void TabReplaced(TabContentsWrapper* new_tab) = 0;
+
  protected:
   DevToolsClientHost() : close_listener_(NULL) {}
 
diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.cc b/chrome/browser/debugger/devtools_http_protocol_handler.cc
index 6f2deb4..43ac93b 100644
--- a/chrome/browser/debugger/devtools_http_protocol_handler.cc
+++ b/chrome/browser/debugger/devtools_http_protocol_handler.cc
@@ -4,26 +4,24 @@
 
 #include "chrome/browser/debugger/devtools_http_protocol_handler.h"
 
+#include <utility>
+
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/message_loop_proxy.h"
 #include "base/string_number_conversions.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/debugger/devtools_client_host.h"
 #include "chrome/browser/debugger/devtools_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/devtools_messages.h"
 #include "chrome/common/net/url_request_context_getter.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/io_buffer.h"
-#include "net/base/listen_socket.h"
 #include "net/server/http_server_request_info.h"
 #include "net/url_request/url_request_context.h"
 
@@ -35,8 +33,12 @@
 // messages sent for DevToolsClient to a DebuggerShell instance.
 class DevToolsClientHostImpl : public DevToolsClientHost {
  public:
-  explicit DevToolsClientHostImpl(HttpListenSocket* socket)
-      : socket_(socket) {}
+  DevToolsClientHostImpl(
+      HttpServer* server,
+      int connection_id)
+      : server_(server),
+        connection_id_(connection_id) {
+  }
   ~DevToolsClientHostImpl() {}
 
   // DevToolsClientHost interface
@@ -44,8 +46,9 @@
     BrowserThread::PostTask(
         BrowserThread::IO,
         FROM_HERE,
-        NewRunnableMethod(socket_,
-                          &HttpListenSocket::Close));
+        NewRunnableMethod(server_,
+                          &HttpServer::Close,
+                          connection_id_));
   }
 
   virtual void SendMessageToClient(const IPC::Message& msg) {
@@ -56,17 +59,42 @@
     IPC_END_MESSAGE_MAP()
   }
 
+  virtual void TabReplaced(TabContentsWrapper* new_tab) {
+  }
+
   void NotifyCloseListener() {
     DevToolsClientHost::NotifyCloseListener();
   }
  private:
   // Message handling routines
   void OnDispatchOnInspectorFrontend(const std::string& data) {
-    socket_->SendOverWebSocket(data);
+    BrowserThread::PostTask(
+        BrowserThread::IO,
+        FROM_HERE,
+        NewRunnableMethod(server_,
+                          &HttpServer::SendOverWebSocket,
+                          connection_id_,
+                          data));
   }
-  HttpListenSocket* socket_;
+
+  virtual void FrameNavigating(const std::string& url) {}
+  HttpServer* server_;
+  int connection_id_;
 };
 
+}  // namespace
+
+
+// static
+scoped_refptr<DevToolsHttpProtocolHandler> DevToolsHttpProtocolHandler::Start(
+    const std::string& ip,
+    int port,
+    const std::string& frontend_url,
+    TabContentsProvider* provider) {
+  scoped_refptr<DevToolsHttpProtocolHandler> http_handler =
+      new DevToolsHttpProtocolHandler(ip, port, frontend_url, provider);
+  http_handler->Start();
+  return http_handler;
 }
 
 DevToolsHttpProtocolHandler::~DevToolsHttpProtocolHandler() {
@@ -87,7 +115,7 @@
 }
 
 void DevToolsHttpProtocolHandler::OnHttpRequest(
-    HttpListenSocket* socket,
+    int connection_id,
     const HttpServerRequestInfo& info) {
   if (info.path == "" || info.path == "/") {
     // Pages discovery request.
@@ -96,28 +124,28 @@
         FROM_HERE,
         NewRunnableMethod(this,
                           &DevToolsHttpProtocolHandler::OnHttpRequestUI,
-                          make_scoped_refptr(socket),
+                          connection_id,
                           info));
     return;
   }
 
   size_t pos = info.path.find("/devtools/");
   if (pos != 0) {
-    socket->Send404();
+    server_->Send404(connection_id);
     return;
   }
 
   // Proxy static files from chrome://devtools/*.
   net::URLRequest* request = new net::URLRequest(
       GURL("chrome:/" + info.path), this);
-  Bind(request, socket);
+  Bind(request, connection_id);
   request->set_context(
       Profile::GetDefaultRequestContext()->GetURLRequestContext());
   request->Start();
 }
 
 void DevToolsHttpProtocolHandler::OnWebSocketRequest(
-    HttpListenSocket* socket,
+    int connection_id,
     const HttpServerRequestInfo& request) {
   BrowserThread::PostTask(
       BrowserThread::UI,
@@ -125,35 +153,37 @@
       NewRunnableMethod(
           this,
           &DevToolsHttpProtocolHandler::OnWebSocketRequestUI,
-          make_scoped_refptr(socket),
+          connection_id,
           request));
 }
 
-void DevToolsHttpProtocolHandler::OnWebSocketMessage(HttpListenSocket* socket,
-                                                     const std::string& data) {
+void DevToolsHttpProtocolHandler::OnWebSocketMessage(
+    int connection_id,
+    const std::string& data) {
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
       NewRunnableMethod(
           this,
           &DevToolsHttpProtocolHandler::OnWebSocketMessageUI,
-          make_scoped_refptr(socket),
+          connection_id,
           data));
 }
 
-void DevToolsHttpProtocolHandler::OnClose(HttpListenSocket* socket) {
-  SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
-  if (it != socket_to_requests_io_.end()) {
+void DevToolsHttpProtocolHandler::OnClose(int connection_id) {
+  ConnectionToRequestsMap::iterator it =
+      connection_to_requests_io_.find(connection_id);
+  if (it != connection_to_requests_io_.end()) {
     // Dispose delegating socket.
     for (std::set<net::URLRequest*>::iterator it2 = it->second.begin();
          it2 != it->second.end(); ++it2) {
       net::URLRequest* request = *it2;
       request->Cancel();
-      request_to_socket_io_.erase(request);
+      request_to_connection_io_.erase(request);
       request_to_buffer_io_.erase(request);
       delete request;
     }
-    socket_to_requests_io_.erase(socket);
+    connection_to_requests_io_.erase(connection_id);
   }
 
   BrowserThread::PostTask(
@@ -162,134 +192,137 @@
       NewRunnableMethod(
           this,
           &DevToolsHttpProtocolHandler::OnCloseUI,
-          make_scoped_refptr(socket)));
+          connection_id));
 }
 
 void DevToolsHttpProtocolHandler::OnHttpRequestUI(
-    HttpListenSocket* socket,
+    int connection_id,
     const HttpServerRequestInfo& info) {
-  std::string response = "<html><body>";
-  for (BrowserList::const_iterator it = BrowserList::begin(),
-       end = BrowserList::end(); it != end; ++it) {
-    TabStripModel* model = (*it)->tabstrip_model();
-    for (int i = 0, size = model->count(); i < size; ++i) {
-      TabContentsWrapper* tab_contents = model->GetTabContentsAt(i);
-      NavigationController& controller = tab_contents->controller();
-      NavigationEntry* entry = controller.GetActiveEntry();
-      if (entry == NULL)
-        continue;
+  std::string response = "<html><body><script>"
+      "function addTab(id, url, attached, frontendUrl) {"
+      "    if (!attached) {"
+      "        var a = document.createElement('a');"
+      "        a.textContent = url;"
+      "        a.href = frontendUrl + '?host=' + window.location.host +"
+      "            '&page=' + id;"
+      "        document.body.appendChild(a);"
+      "    } else {"
+      "        var span = document.createElement('span');"
+      "        span.textContent = url + ' (attached)';"
+      "        document.body.appendChild(span);"
+      "    }"
+      "    document.body.appendChild(document.createElement('br'));"
+      "}";
 
-      if (!entry->url().is_valid())
-        continue;
+  InspectableTabs inspectable_tabs =
+      tab_contents_provider_->GetInspectableTabs();
 
-      DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
-          GetDevToolsClientHostFor(tab_contents->tab_contents()->
+  for (InspectableTabs::iterator it = inspectable_tabs.begin();
+       it != inspectable_tabs.end(); ++it) {
+
+    TabContentsWrapper* tab_contents = *it;
+    NavigationController& controller = tab_contents->controller();
+    NavigationEntry* entry = controller.GetActiveEntry();
+    if (entry == NULL)
+      continue;
+
+    if (!entry->url().is_valid())
+      continue;
+
+    DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
+        GetDevToolsClientHostFor(tab_contents->tab_contents()->
                                       render_view_host());
-      if (!client_host) {
-        response += StringPrintf(
-            "<a href='/devtools/devtools.html?page=%d'>%s (%s)</a><br>",
-            controller.session_id().id(),
-            UTF16ToUTF8(entry->title()).c_str(),
-            entry->url().spec().c_str());
-      } else {
-        response += StringPrintf(
-            "%s (%s)<br>",
-            UTF16ToUTF8(entry->title()).c_str(),
-            entry->url().spec().c_str());
-      }
-    }
+    response += StringPrintf(
+        "addTab(%d, '%s', %s, '%s');\n",
+        controller.session_id().id(),
+        entry->url().spec().c_str(),
+        client_host ? "true" : "false",
+        overriden_frontend_url_.c_str());
   }
-  response += "</body></html>";
-  Send200(socket, response, "text/html; charset=UTF-8");
+
+  response += "</script></body></html>";
+  Send200(connection_id, response, "text/html; charset=UTF-8");
 }
 
 void DevToolsHttpProtocolHandler::OnWebSocketRequestUI(
-    HttpListenSocket* socket,
+    int connection_id,
     const HttpServerRequestInfo& request) {
   std::string prefix = "/devtools/page/";
   size_t pos = request.path.find(prefix);
   if (pos != 0) {
-    Send404(socket);
+    Send404(connection_id);
     return;
   }
   std::string page_id = request.path.substr(prefix.length());
   int id = 0;
   if (!base::StringToInt(page_id, &id)) {
-    Send500(socket, "Invalid page id: " + page_id);
+    Send500(connection_id, "Invalid page id: " + page_id);
     return;
   }
 
   TabContents* tab_contents = GetTabContents(id);
   if (tab_contents == NULL) {
-    Send500(socket, "No such page id: " + page_id);
+    Send500(connection_id, "No such page id: " + page_id);
     return;
   }
 
   DevToolsManager* manager = DevToolsManager::GetInstance();
   if (manager->GetDevToolsClientHostFor(tab_contents->render_view_host())) {
-    Send500(socket, "Page with given id is being inspected: " + page_id);
+    Send500(connection_id, "Page with given id is being inspected: " + page_id);
     return;
   }
 
-  DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl(socket);
-  socket_to_client_host_ui_[socket] = client_host;
+  DevToolsClientHostImpl* client_host =
+      new DevToolsClientHostImpl(server_, connection_id);
+  connection_to_client_host_ui_[connection_id] = client_host;
 
   manager->RegisterDevToolsClientHostFor(
       tab_contents->render_view_host(),
       client_host);
-  AcceptWebSocket(socket, request);
+  manager->ForwardToDevToolsAgent(
+      client_host,
+      DevToolsAgentMsg_FrontendLoaded());
+
+  AcceptWebSocket(connection_id, request);
 }
 
 void DevToolsHttpProtocolHandler::OnWebSocketMessageUI(
-    HttpListenSocket* socket,
+    int connection_id,
     const std::string& data) {
-  SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
-  if (it == socket_to_client_host_ui_.end())
+  ConnectionToClientHostMap::iterator it =
+      connection_to_client_host_ui_.find(connection_id);
+  if (it == connection_to_client_host_ui_.end())
     return;
 
   DevToolsManager* manager = DevToolsManager::GetInstance();
 
-  if (data == "loaded") {
-    manager->ForwardToDevToolsAgent(
-        it->second,
-        DevToolsAgentMsg_FrontendLoaded());
+  //TODO(pfeldman): remove this once front-end stops sending it upstream.
+  if (data == "loaded")
     return;
-  }
 
   manager->ForwardToDevToolsAgent(
       it->second,
       DevToolsAgentMsg_DispatchOnInspectorBackend(data));
 }
 
-void DevToolsHttpProtocolHandler::OnCloseUI(HttpListenSocket* socket) {
-  SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
-  if (it != socket_to_client_host_ui_.end()) {
+void DevToolsHttpProtocolHandler::OnCloseUI(int connection_id) {
+  ConnectionToClientHostMap::iterator it =
+      connection_to_client_host_ui_.find(connection_id);
+  if (it != connection_to_client_host_ui_.end()) {
     DevToolsClientHostImpl* client_host =
         static_cast<DevToolsClientHostImpl*>(it->second);
     client_host->NotifyCloseListener();
     delete client_host;
-    socket_to_client_host_ui_.erase(socket);
+    connection_to_client_host_ui_.erase(connection_id);
   }
-
-  // We are holding last reference to scoped refptr 'socket' here.
-  // We can't exit method just like that since 'socket' is going to
-  // be destroyed on the UI thread then. Schedule no-op to IO thread
-  // so that socket is destroyed on IO instead.
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      NewRunnableMethod(
-          this,
-          &DevToolsHttpProtocolHandler::ReleaseSocket,
-          make_scoped_refptr(socket)));
 }
 
 void DevToolsHttpProtocolHandler::OnResponseStarted(net::URLRequest* request) {
-  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
-  if (it == request_to_socket_io_.end())
+  RequestToSocketMap::iterator it = request_to_connection_io_.find(request);
+  if (it == request_to_connection_io_.end())
     return;
 
-  HttpListenSocket* socket = it->second;
+  int connection_id = it->second;
 
   int expected_size = static_cast<int>(request->GetExpectedContentSize());
 
@@ -297,14 +330,14 @@
   request->GetMimeType(&content_type);
 
   if (request->status().is_success()) {
-    socket->Send(StringPrintf("HTTP/1.1 200 OK\r\n"
-                              "Content-Type:%s\r\n"
-                              "Content-Length:%d\r\n"
-                              "\r\n",
-                              content_type.c_str(),
-                              expected_size));
+    server_->Send(connection_id, StringPrintf("HTTP/1.1 200 OK\r\n"
+                                              "Content-Type:%s\r\n"
+                                              "Content-Length:%d\r\n"
+                                              "\r\n",
+                                              content_type.c_str(),
+                                              expected_size));
   } else {
-    socket->Send404();
+    server_->Send404(connection_id);
   }
 
   int bytes_read = 0;
@@ -320,17 +353,17 @@
 
 void DevToolsHttpProtocolHandler::OnReadCompleted(net::URLRequest* request,
                                                   int bytes_read) {
-  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
-  if (it == request_to_socket_io_.end())
+  RequestToSocketMap::iterator it = request_to_connection_io_.find(request);
+  if (it == request_to_connection_io_.end())
     return;
 
-  HttpListenSocket* socket = it->second;
+  int connection_id = it->second;
 
   net::IOBuffer* buffer = request_to_buffer_io_[request].get();
   do {
     if (!request->status().is_success() || bytes_read <= 0)
       break;
-    socket->Send(buffer->data(), bytes_read);
+    server_->Send(connection_id, buffer->data(), bytes_read);
   } while (request->Read(buffer, kBufferSize, &bytes_read));
 
   // See comments re: HEAD requests in OnResponseStarted().
@@ -338,13 +371,21 @@
     RequestCompleted(request);
 }
 
-DevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler(int port)
-    : port_(port),
-      server_(NULL) {
+DevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler(
+    const std::string& ip,
+    int port,
+    const std::string& frontend_host,
+    TabContentsProvider* provider)
+    : ip_(ip),
+      port_(port),
+      overriden_frontend_url_(frontend_host),
+      tab_contents_provider_(provider) {
+  if (overriden_frontend_url_.empty())
+      overriden_frontend_url_ = "/devtools/devtools.html";
 }
 
 void DevToolsHttpProtocolHandler::Init() {
-  server_ = HttpListenSocket::Listen("127.0.0.1", port_, this);
+  server_ = new HttpServer(ip_, port_, this);
 }
 
 // Run on I/O thread
@@ -353,84 +394,86 @@
 }
 
 void DevToolsHttpProtocolHandler::Bind(net::URLRequest* request,
-                                       HttpListenSocket* socket) {
-  request_to_socket_io_[request] = socket;
-  SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
-  if (it == socket_to_requests_io_.end()) {
-    std::pair<HttpListenSocket*, std::set<net::URLRequest*> > value(
-        socket,
+                                       int connection_id) {
+  request_to_connection_io_[request] = connection_id;
+  ConnectionToRequestsMap::iterator it =
+      connection_to_requests_io_.find(connection_id);
+  if (it == connection_to_requests_io_.end()) {
+    std::pair<int, std::set<net::URLRequest*> > value(
+        connection_id,
         std::set<net::URLRequest*>());
-    it = socket_to_requests_io_.insert(value).first;
+    it = connection_to_requests_io_.insert(value).first;
   }
   it->second.insert(request);
   request_to_buffer_io_[request] = new net::IOBuffer(kBufferSize);
 }
 
 void DevToolsHttpProtocolHandler::RequestCompleted(net::URLRequest* request) {
-  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
-  if (it == request_to_socket_io_.end())
+  RequestToSocketMap::iterator it = request_to_connection_io_.find(request);
+  if (it == request_to_connection_io_.end())
     return;
 
-  HttpListenSocket* socket = it->second;
-  request_to_socket_io_.erase(request);
-  SocketToRequestsMap::iterator it2 = socket_to_requests_io_.find(socket);
+  int connection_id = it->second;
+  request_to_connection_io_.erase(request);
+  ConnectionToRequestsMap::iterator it2 =
+      connection_to_requests_io_.find(connection_id);
   it2->second.erase(request);
   request_to_buffer_io_.erase(request);
   delete request;
 }
 
-void DevToolsHttpProtocolHandler::Send200(HttpListenSocket* socket,
+void DevToolsHttpProtocolHandler::Send200(int connection_id,
                                           const std::string& data,
                                           const std::string& mime_type) {
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(socket,
-                        &HttpListenSocket::Send200,
+      NewRunnableMethod(server_.get(),
+                        &HttpServer::Send200,
+                        connection_id,
                         data,
                         mime_type));
 }
 
-void DevToolsHttpProtocolHandler::Send404(HttpListenSocket* socket) {
+void DevToolsHttpProtocolHandler::Send404(int connection_id) {
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(socket,
-                        &HttpListenSocket::Send404));
+      NewRunnableMethod(server_.get(),
+                        &HttpServer::Send404,
+                        connection_id));
 }
 
-void DevToolsHttpProtocolHandler::Send500(HttpListenSocket* socket,
+void DevToolsHttpProtocolHandler::Send500(int connection_id,
                                           const std::string& message) {
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(socket,
-                        &HttpListenSocket::Send500,
+      NewRunnableMethod(server_.get(),
+                        &HttpServer::Send500,
+                        connection_id,
                         message));
 }
 
 void DevToolsHttpProtocolHandler::AcceptWebSocket(
-    HttpListenSocket* socket,
+    int connection_id,
     const HttpServerRequestInfo& request) {
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(socket,
-                        &HttpListenSocket::AcceptWebSocket,
+      NewRunnableMethod(server_.get(),
+                        &HttpServer::AcceptWebSocket,
+                        connection_id,
                         request));
 }
 
-void DevToolsHttpProtocolHandler::ReleaseSocket(
-    HttpListenSocket* socket) {
-  // This in fact is scoped ref ptr. It'll get nuked on exit.
-}
-
 TabContents* DevToolsHttpProtocolHandler::GetTabContents(int session_id) {
-  for (BrowserList::const_iterator it = BrowserList::begin(),
-       end = BrowserList::end(); it != end; ++it) {
-    TabStripModel* model = (*it)->tabstrip_model();
-    for (int i = 0, size = model->count(); i < size; ++i) {
-      NavigationController& controller =
-          model->GetTabContentsAt(i)->controller();
-      if (controller.session_id().id() == session_id)
-        return controller.tab_contents();
-    }
+  InspectableTabs inspectable_tabs =
+      tab_contents_provider_->GetInspectableTabs();
+
+  for (InspectableTabs::iterator it = inspectable_tabs.begin();
+       it != inspectable_tabs.end(); ++it) {
+    TabContentsWrapper* tab_contents = *it;
+    NavigationController& controller =
+        tab_contents->controller();
+    if (controller.session_id().id() == session_id)
+      return controller.tab_contents();
   }
   return NULL;
 }
diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.h b/chrome/browser/debugger/devtools_http_protocol_handler.h
index c5c485f..aa6392b 100644
--- a/chrome/browser/debugger/devtools_http_protocol_handler.h
+++ b/chrome/browser/debugger/devtools_http_protocol_handler.h
@@ -8,48 +8,70 @@
 
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/ref_counted.h"
-#include "net/server/http_listen_socket.h"
+#include "base/scoped_ptr.h"
+#include "net/server/http_server.h"
 #include "net/url_request/url_request.h"
 
 class DevToolsClientHost;
 class DevToolsHttpServer;
 class TabContents;
+class TabContentsWrapper;
 
 class DevToolsHttpProtocolHandler
-    : public HttpListenSocket::Delegate,
+    : public HttpServer::Delegate,
       public net::URLRequest::Delegate,
       public base::RefCountedThreadSafe<DevToolsHttpProtocolHandler> {
  public:
-  explicit DevToolsHttpProtocolHandler(int port);
+  typedef std::vector<TabContentsWrapper*> InspectableTabs;
+  class TabContentsProvider {
+   public:
+    TabContentsProvider() {}
+    virtual ~TabContentsProvider() {}
+    virtual InspectableTabs GetInspectableTabs() = 0;
+   private:
+    DISALLOW_COPY_AND_ASSIGN(TabContentsProvider);
+  };
 
-  // This method should be called after the object construction.
-  void Start();
+  // Takes ownership over |provider|.
+  static scoped_refptr<DevToolsHttpProtocolHandler> Start(
+      const std::string& ip,
+      int port,
+      const std::string& frontend_url,
+      TabContentsProvider* provider);
 
-  // This method should be called before the object destruction.
+  // Called from the main thread in order to stop protocol handler.
+  // Will schedule tear down task on IO thread.
   void Stop();
 
  private:
   friend class base::RefCountedThreadSafe<DevToolsHttpProtocolHandler>;
+
+  DevToolsHttpProtocolHandler(const std::string& ip,
+                              int port,
+                              const std::string& frontend_url,
+                              TabContentsProvider* provider);
   virtual ~DevToolsHttpProtocolHandler();
+  void Start();
 
-  // HttpListenSocket::Delegate implementation.
-  virtual void OnHttpRequest(HttpListenSocket* socket,
+  // HttpServer::Delegate implementation.
+  virtual void OnHttpRequest(int connection_id,
                              const HttpServerRequestInfo& info);
-  virtual void OnWebSocketRequest(HttpListenSocket* socket,
+  virtual void OnWebSocketRequest(int connection_id,
                                   const HttpServerRequestInfo& info);
-  virtual void OnWebSocketMessage(HttpListenSocket* socket,
+  virtual void OnWebSocketMessage(int connection_id,
                                   const std::string& data);
-  virtual void OnClose(HttpListenSocket* socket);
+  virtual void OnClose(int connection_id);
 
-  virtual void OnHttpRequestUI(HttpListenSocket* socket,
+  virtual void OnHttpRequestUI(int connection_id,
                                const HttpServerRequestInfo& info);
-  virtual void OnWebSocketRequestUI(HttpListenSocket* socket,
+  virtual void OnWebSocketRequestUI(int connection_id,
                                     const HttpServerRequestInfo& info);
-  virtual void OnWebSocketMessageUI(HttpListenSocket* socket,
+  virtual void OnWebSocketMessageUI(int connection_id,
                                     const std::string& data);
-  virtual void OnCloseUI(HttpListenSocket* socket);
+  virtual void OnCloseUI(int connection_id);
 
   // net::URLRequest::Delegate implementation.
   virtual void OnResponseStarted(net::URLRequest* request);
@@ -57,35 +79,37 @@
 
   void Init();
   void Teardown();
-  void Bind(net::URLRequest* request, HttpListenSocket* socket);
+  void Bind(net::URLRequest* request, int connection_id);
   void RequestCompleted(net::URLRequest* request);
 
-  void Send200(HttpListenSocket* socket,
+  void Send200(int connection_id,
                const std::string& data,
                const std::string& mime_type = "text/html");
-  void Send404(HttpListenSocket* socket);
-  void Send500(HttpListenSocket* socket,
+  void Send404(int connection_id);
+  void Send500(int connection_id,
                const std::string& message);
-  void AcceptWebSocket(HttpListenSocket* socket,
+  void AcceptWebSocket(int connection_id,
                        const HttpServerRequestInfo& request);
-  void ReleaseSocket(HttpListenSocket* socket);
 
   TabContents* GetTabContents(int session_id);
 
+  std::string ip_;
   int port_;
-  scoped_refptr<HttpListenSocket> server_;
-  typedef std::map<net::URLRequest*, HttpListenSocket*>
+  std::string overriden_frontend_url_;
+  scoped_refptr<HttpServer> server_;
+  typedef std::map<net::URLRequest*, int>
       RequestToSocketMap;
-  RequestToSocketMap request_to_socket_io_;
-  typedef std::map<HttpListenSocket*, std::set<net::URLRequest*> >
-      SocketToRequestsMap;
-  SocketToRequestsMap socket_to_requests_io_;
+  RequestToSocketMap request_to_connection_io_;
+  typedef std::map<int, std::set<net::URLRequest*> >
+      ConnectionToRequestsMap;
+  ConnectionToRequestsMap connection_to_requests_io_;
   typedef std::map<net::URLRequest*, scoped_refptr<net::IOBuffer> >
       BuffersMap;
   BuffersMap request_to_buffer_io_;
-  typedef std::map<HttpListenSocket*, DevToolsClientHost*>
-      SocketToClientHostMap;
-  SocketToClientHostMap socket_to_client_host_ui_;
+  typedef std::map<int, DevToolsClientHost*>
+      ConnectionToClientHostMap;
+  ConnectionToClientHostMap connection_to_client_host_ui_;
+  scoped_ptr<TabContentsProvider> tab_contents_provider_;
   DISALLOW_COPY_AND_ASSIGN(DevToolsHttpProtocolHandler);
 };
 
diff --git a/chrome/browser/debugger/devtools_manager.cc b/chrome/browser/debugger/devtools_manager.cc
index e8e69e1..e7d3b53 100644
--- a/chrome/browser/debugger/devtools_manager.cc
+++ b/chrome/browser/debugger/devtools_manager.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/devtools_messages.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
@@ -221,6 +223,10 @@
   if (cookie != -1) {
     // Navigating to URL in the inspected window.
     AttachClientHost(cookie, dest_rvh);
+
+    DevToolsClientHost* client_host = GetDevToolsClientHostFor(dest_rvh);
+    client_host->FrameNavigating(gurl.spec());
+
     return;
   }
 
@@ -241,6 +247,20 @@
   }
 }
 
+void DevToolsManager::TabReplaced(TabContentsWrapper* old_tab,
+                                  TabContentsWrapper* new_tab) {
+  RenderViewHost* old_rvh = old_tab->tab_contents()->render_view_host();
+  DevToolsClientHost* client_host = GetDevToolsClientHostFor(old_rvh);
+  if (!client_host)
+    return;  // Didn't know about old_tab.
+  int cookie = DetachClientHost(old_rvh);
+  if (cookie == -1)
+    return;  // Didn't know about old_tab.
+
+  client_host->TabReplaced(new_tab);
+  AttachClientHost(cookie, new_tab->tab_contents()->render_view_host());
+}
+
 int DevToolsManager::DetachClientHost(RenderViewHost* from_rvh) {
   DevToolsClientHost* client_host = GetDevToolsClientHostFor(from_rvh);
   if (!client_host)
diff --git a/chrome/browser/debugger/devtools_manager.h b/chrome/browser/debugger/devtools_manager.h
index 736fb48..89e0498 100644
--- a/chrome/browser/debugger/devtools_manager.h
+++ b/chrome/browser/debugger/devtools_manager.h
@@ -12,7 +12,6 @@
 #include "base/ref_counted.h"
 #include "chrome/browser/debugger/devtools_client_host.h"
 #include "chrome/browser/debugger/devtools_toggle_action.h"
-#include "chrome/common/devtools_messages.h"
 #include "webkit/glue/resource_loader_bridge.h"
 
 namespace IPC {
@@ -24,8 +23,12 @@
 class IOThread;
 class PrefService;
 class RenderViewHost;
+class TabContentsWraper;
+
 using webkit_glue::ResourceLoaderBridge;
 
+typedef std::map<std::string, std::string> DevToolsRuntimeProperties;
+
 // This class is a singleton that manages DevToolsClientHost instances and
 // routes messages between developer tools clients and agents.
 class DevToolsManager : public DevToolsClientHost::CloseListener,
@@ -77,6 +80,10 @@
                                   RenderViewHost* dest_rvh,
                                   const GURL& gurl);
 
+  // Invoked when a tab is replaced by another tab. This is triggered by
+  // TabStripModel::ReplaceTabContentsAt.
+  void TabReplaced(TabContentsWrapper* old_tab, TabContentsWrapper* new_tab);
+
   // Detaches client host and returns cookie that can be used in
   // AttachClientHost.
   int DetachClientHost(RenderViewHost* from_rvh);
@@ -124,10 +131,8 @@
                         DevToolsClientHost* client_host);
 
   // These two maps are for tracking dependencies between inspected tabs and
-  // their DevToolsClientHosts. They are usful for routing devtools messages
-  // and allow us to have at most one devtools client host per tab. We use
-  // NavigationController* as key because it survives crosee-site navigation in
-  // cases when tab contents may change.
+  // their DevToolsClientHosts. They are useful for routing devtools messages
+  // and allow us to have at most one devtools client host per tab.
   //
   // DevToolsManager start listening to DevToolsClientHosts when they are put
   // into these maps and removes them when they are closing.
diff --git a/chrome/browser/debugger/devtools_manager_unittest.cc b/chrome/browser/debugger/devtools_manager_unittest.cc
index a66b986..751410a 100644
--- a/chrome/browser/debugger/devtools_manager_unittest.cc
+++ b/chrome/browser/debugger/devtools_manager_unittest.cc
@@ -40,6 +40,9 @@
     last_sent_message = &message;
   }
 
+  virtual void TabReplaced(TabContentsWrapper* new_tab) {
+  }
+
   static void ResetCounters() {
     close_counter = 0;
   }
@@ -51,6 +54,8 @@
  private:
   bool closed_;
 
+  virtual void FrameNavigating(const std::string& url) {}
+
   DISALLOW_COPY_AND_ASSIGN(TestDevToolsClientHost);
 };
 
diff --git a/chrome/browser/debugger/devtools_protocol_handler.cc b/chrome/browser/debugger/devtools_protocol_handler.cc
index 6e72ef0..0024164 100644
--- a/chrome/browser/debugger/devtools_protocol_handler.cc
+++ b/chrome/browser/debugger/devtools_protocol_handler.cc
@@ -7,8 +7,29 @@
 #include "base/logging.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/debugger/inspectable_tab_proxy.h"
+#include "chrome/browser/debugger/debugger_remote_service.h"
 #include "chrome/browser/debugger/devtools_remote_message.h"
 #include "chrome/browser/debugger/devtools_remote_listen_socket.h"
+#include "chrome/browser/debugger/devtools_remote_service.h"
+#include "chrome/browser/debugger/extension_ports_remote_service.h"
+
+// static
+scoped_refptr<DevToolsProtocolHandler> DevToolsProtocolHandler::Start(
+    int port) {
+  scoped_refptr<DevToolsProtocolHandler> proto_handler =
+      new DevToolsProtocolHandler(port);
+  proto_handler->RegisterDestination(
+      new DevToolsRemoteService(proto_handler),
+      DevToolsRemoteService::kToolName);
+  proto_handler->RegisterDestination(
+      new DebuggerRemoteService(proto_handler),
+      DebuggerRemoteService::kToolName);
+  proto_handler->RegisterDestination(
+      new ExtensionPortsRemoteService(proto_handler),
+      ExtensionPortsRemoteService::kToolName);
+  proto_handler->Start();
+  return proto_handler;
+}
 
 DevToolsProtocolHandler::DevToolsProtocolHandler(int port)
     : port_(port),
diff --git a/chrome/browser/debugger/devtools_protocol_handler.h b/chrome/browser/debugger/devtools_protocol_handler.h
index 92889cc..a91cefb 100644
--- a/chrome/browser/debugger/devtools_protocol_handler.h
+++ b/chrome/browser/debugger/devtools_protocol_handler.h
@@ -27,12 +27,10 @@
   typedef base::hash_map< std::string, scoped_refptr<DevToolsRemoteListener> >
       ToolToListenerMap;
 
-  explicit DevToolsProtocolHandler(int port);
+  static scoped_refptr<DevToolsProtocolHandler> Start(int port);
 
-  // This method should be called after the object construction.
-  void Start();
-
-  // This method should be called before the object destruction.
+  // Called from the main thread in order to stop protocol handler.
+  // Will schedule tear down task on IO thread.
   void Stop();
 
   // Registers a |listener| to handle messages for a certain |tool_name| Tool.
@@ -61,7 +59,9 @@
   virtual void Send(const DevToolsRemoteMessage& message);
 
  private:
+  explicit DevToolsProtocolHandler(int port);
   virtual ~DevToolsProtocolHandler();
+  void Start();
 
   void Init();
   void Teardown();
diff --git a/chrome/browser/debugger/devtools_remote_listen_socket_unittest.cc b/chrome/browser/debugger/devtools_remote_listen_socket_unittest.cc
index 84cc4a6..f877473 100644
--- a/chrome/browser/debugger/devtools_remote_listen_socket_unittest.cc
+++ b/chrome/browser/debugger/devtools_remote_listen_socket_unittest.cc
@@ -48,10 +48,38 @@
 #endif
 
 
+ListenSocketTestAction::ListenSocketTestAction() : action_(ACTION_NONE) {}
+
+ListenSocketTestAction::ListenSocketTestAction(ActionType action)
+      : action_(action) {}
+
+ListenSocketTestAction::ListenSocketTestAction(ActionType action,
+                                               std::string data)
+    : action_(action),
+      data_(data) {}
+
+ListenSocketTestAction::ListenSocketTestAction(
+    ActionType action,
+    const DevToolsRemoteMessage& message)
+    : action_(action),
+      message_(message) {}
+
+ListenSocketTestAction::~ListenSocketTestAction() {}
+
 ListenSocket* DevToolsRemoteListenSocketTester::DoListen() {
   return DevToolsRemoteListenSocket::Listen(kLoopback, kTestPort, this);
 }
 
+DevToolsRemoteListenSocketTester::DevToolsRemoteListenSocketTester()
+    : semaphore_(NULL),
+      thread_(NULL),
+      loop_(NULL),
+      server_(NULL),
+      connection_(NULL),
+      test_socket_(INVALID_SOCKET) {
+  memset(&lock_, 0, sizeof(lock_));
+}
+
 void DevToolsRemoteListenSocketTester::SetUp() {
 #if defined(OS_WIN)
   InitializeCriticalSection(&lock_);
@@ -322,6 +350,7 @@
   ASSERT_STREQ(buf, kChromeDevToolsHandshake);
 }
 
+DevToolsRemoteListenSocketTester::~DevToolsRemoteListenSocketTester() {}
 
 class DevToolsRemoteListenSocketTest: public PlatformTest {
  public:
diff --git a/chrome/browser/debugger/devtools_remote_listen_socket_unittest.h b/chrome/browser/debugger/devtools_remote_listen_socket_unittest.h
index 6bba3ba..537b881 100644
--- a/chrome/browser/debugger/devtools_remote_listen_socket_unittest.h
+++ b/chrome/browser/debugger/devtools_remote_listen_socket_unittest.h
@@ -54,16 +54,12 @@
 
 class ListenSocketTestAction {
  public:
-  ListenSocketTestAction() : action_(ACTION_NONE) {}
-  explicit ListenSocketTestAction(ActionType action)
-      : action_(action) {}
-  ListenSocketTestAction(ActionType action, std::string data)
-      : action_(action),
-        data_(data) {}
+  ListenSocketTestAction();
+  explicit ListenSocketTestAction(ActionType action);
+  ListenSocketTestAction(ActionType action, std::string data);
   ListenSocketTestAction(ActionType action,
-                         const DevToolsRemoteMessage& message)
-      : action_(action),
-        message_(message) {}
+                         const DevToolsRemoteMessage& message);
+  ~ListenSocketTestAction();
 
   const std::string data() const { return data_; }
   const DevToolsRemoteMessage message() { return message_; }
@@ -81,15 +77,7 @@
 class DevToolsRemoteListenSocketTester :
     public DevToolsRemoteListener {
  public:
-  DevToolsRemoteListenSocketTester()
-      : semaphore_(NULL),
-        thread_(NULL),
-        loop_(NULL),
-        server_(NULL),
-        connection_(NULL),
-        test_socket_(INVALID_SOCKET) {
-    memset(&lock_, 0, sizeof(lock_));
-  }
+  DevToolsRemoteListenSocketTester();
 
   virtual void SetUp();
   virtual void TearDown();
@@ -135,7 +123,7 @@
   virtual ListenSocket* DoListen();
 
  private:
-  virtual ~DevToolsRemoteListenSocketTester() {}
+  virtual ~DevToolsRemoteListenSocketTester();
 };
 
 #endif  // CHROME_BROWSER_DEBUGGER_DEVTOOLS_REMOTE_LISTEN_SOCKET_UNITTEST_H_
diff --git a/chrome/browser/debugger/devtools_sanity_unittest.cc b/chrome/browser/debugger/devtools_sanity_unittest.cc
index caf3db3..5498dfd 100644
--- a/chrome/browser/debugger/devtools_sanity_unittest.cc
+++ b/chrome/browser/debugger/devtools_sanity_unittest.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/test/in_process_browser_test.h"
@@ -49,19 +48,12 @@
 // action we take.
 const int kActionDelayMs = 500;
 
-const char kConsoleTestPage[] = "files/devtools/console_test_page.html";
 const char kDebuggerTestPage[] = "files/devtools/debugger_test_page.html";
-const char kJsPage[] = "files/devtools/js_page.html";
 const char kHeapProfilerPage[] = "files/devtools/heap_profiler.html";
 const char kPauseWhenLoadingDevTools[] =
     "files/devtools/pause_when_loading_devtools.html";
 const char kPauseWhenScriptIsRunning[] =
     "files/devtools/pause_when_script_is_running.html";
-const char kResourceContentLengthTestPage[] = "files/devtools/image.html";
-const char kResourceTestPage[] = "files/devtools/resource_test_page.html";
-const char kSimplePage[] = "files/devtools/simple_page.html";
-const char kCompletionOnPause[] =
-    "files/devtools/completion_on_pause.html";
 const char kPageWithContentScript[] =
     "files/devtools/page_with_content_script.html";
 
@@ -254,31 +246,6 @@
   FilePath test_extensions_dir_;
 };
 
-// Fails after WebKit roll 69808:70011, http://crbug.com/59727.
-#if defined(OS_LINUX) || defined(OS_WIN)
-#define MAYBE_TestEnableResourcesTab DISABLED_TestEnableResourcesTab
-#else
-#define MAYBE_TestEnableResourcesTab TestEnableResourcesTab
-#endif  // defined(OS_LINUX) || defined(OS_WIN)
-
-// Tests resources panel enabling.
-IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, MAYBE_TestEnableResourcesTab) {
-  RunTest("testEnableResourcesTab", kSimplePage);
-}
-
-// Fails after WebKit roll 59365:59477, http://crbug.com/44202.
-#if defined(OS_LINUX)
-#define MAYBE_TestResourceContentLength FLAKY_TestResourceContentLength
-#else
-#define MAYBE_TestResourceContentLength TestResourceContentLength
-#endif  // defined(OS_LINUX)
-
-// Tests profiler panel.
-// Disabled, http://crbug.com/68447.
-IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DISABLED_TestProfilerTab) {
-  RunTest("testProfilerTab", kJsPage);
-}
-
 // Tests heap profiler.
 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestHeapProfiler) {
   RunTest("testHeapProfiler", kHeapProfilerPage);
@@ -327,19 +294,4 @@
   RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning);
 }
 
-// Fails after WebKit roll 66724:66804, http://crbug.com/54592
-#if defined(OS_LINUX) || defined(OS_WIN)
-#define MAYBE_TestCompletionOnPause FAILS_TestCompletionOnPause
-#else
-#define MAYBE_TestCompletionOnPause TestCompletionOnPause
-#endif  // defined(OS_LINUX) || defined(OS_WIN)
-IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, MAYBE_TestCompletionOnPause) {
-  RunTest("testCompletionOnPause", kCompletionOnPause);
-}
-
-// Tests that 'Pause' button works for eval.
-IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DISABLED_TestPauseInEval) {
-  RunTest("testPauseInEval", kDebuggerTestPage);
-}
-
 }  // namespace
diff --git a/chrome/browser/debugger/devtools_window.cc b/chrome/browser/debugger/devtools_window.cc
index cb3295b..4bfe6a4 100644
--- a/chrome/browser/debugger/devtools_window.cc
+++ b/chrome/browser/debugger/devtools_window.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -27,7 +27,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/bindings_policy.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
@@ -70,7 +69,7 @@
   tab_contents_ =
       Browser::TabContentsFactory(profile, NULL, MSG_ROUTING_NONE, NULL, NULL);
   tab_contents_->tab_contents()->
-      render_view_host()->AllowBindings(BindingsPolicy::DOM_UI);
+      render_view_host()->AllowBindings(BindingsPolicy::WEB_UI);
   tab_contents_->controller().LoadURL(
       GetDevToolsUrl(), GURL(), PageTransition::START_PAGE);
 
@@ -127,12 +126,18 @@
   }
 }
 
+void DevToolsWindow::TabReplaced(TabContentsWrapper* new_tab) {
+  DCHECK_EQ(profile_, new_tab->profile());
+  inspected_tab_ = new_tab->tab_contents();
+}
+
 void DevToolsWindow::Show(DevToolsToggleAction action) {
   if (docked_) {
     Browser* inspected_browser;
     int inspected_tab_index;
     // Tell inspected browser to update splitter and switch to inspected panel.
-    if (FindInspectedBrowserAndTabIndex(&inspected_browser,
+    if (!IsInspectedBrowserPopup() &&
+        FindInspectedBrowserAndTabIndex(&inspected_browser,
                                         &inspected_tab_index)) {
       BrowserWindow* inspected_window = inspected_browser->window();
       tab_contents_->tab_contents()->set_delegate(this);
@@ -182,7 +187,7 @@
 void DevToolsWindow::SetDocked(bool docked) {
   if (docked_ == docked)
     return;
-  if (docked && !GetInspectedBrowserWindow()) {
+  if (docked && (!GetInspectedBrowserWindow() || IsInspectedBrowserPopup())) {
     // Cannot dock, avoid window flashing due to close-reopen cycle.
     return;
   }
@@ -217,7 +222,7 @@
   wp_key.append("_");
   wp_key.append(kDevToolsApp);
 
-  PrefService* prefs = g_browser_process->local_state();
+  PrefService* prefs = profile_->GetPrefs();
   if (!prefs->FindPreference(wp_key.c_str())) {
     prefs->RegisterDictionaryPref(wp_key.c_str());
   }
@@ -261,18 +266,27 @@
       browser->window() : NULL;
 }
 
+bool DevToolsWindow::IsInspectedBrowserPopup() {
+  Browser* browser = NULL;
+  int tab;
+  if (!FindInspectedBrowserAndTabIndex(&browser, &tab))
+    return false;
+
+  return (browser->type() & Browser::TYPE_POPUP) != 0;
+}
+
 void DevToolsWindow::SetAttachedWindow() {
-  tab_contents_->render_view_host()->
-      ExecuteJavascriptInWebFrame(
-          L"", docked_ ? L"WebInspector.setAttachedWindow(true);" :
-                         L"WebInspector.setAttachedWindow(false);");
+  tab_contents_->render_view_host()->ExecuteJavascriptInWebFrame(
+      string16(),
+      docked_ ? ASCIIToUTF16("WebInspector.setAttachedWindow(true);")
+              : ASCIIToUTF16("WebInspector.setAttachedWindow(false);"));
 }
 
 
 void DevToolsWindow::AddDevToolsExtensionsToClient() {
   if (inspected_tab_) {
     FundamentalValue tabId(inspected_tab_->controller().session_id().id());
-    CallClientFunction(L"WebInspector.setInspectedTabId", tabId);
+    CallClientFunction(ASCIIToUTF16("WebInspector.setInspectedTabId"), tabId);
   }
   ListValue results;
   const ExtensionService* extension_service =
@@ -292,16 +306,17 @@
         new StringValue((*extension)->devtools_url().spec()));
     results.Append(extension_info);
   }
-  CallClientFunction(L"WebInspector.addExtensions", results);
+  CallClientFunction(ASCIIToUTF16("WebInspector.addExtensions"), results);
 }
 
-void DevToolsWindow::CallClientFunction(const std::wstring& function_name,
-                                         const Value& arg) {
+void DevToolsWindow::CallClientFunction(const string16& function_name,
+                                        const Value& arg) {
   std::string json;
   base::JSONWriter::Write(&arg, false, &json);
-  std::wstring javascript = function_name + L"(" + UTF8ToWide(json) + L");";
+  string16 javascript = function_name + char16('(') + UTF8ToUTF16(json) +
+      ASCIIToUTF16(");");
   tab_contents_->render_view_host()->
-      ExecuteJavascriptInWebFrame(L"", javascript);
+      ExecuteJavascriptInWebFrame(string16(), javascript);
 }
 
 void DevToolsWindow::Observe(NotificationType type,
@@ -338,13 +353,12 @@
   // TODO: these messages should be pushed through the WebKit API instead.
   switch (action_on_load_) {
     case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE:
-      tab_contents_->render_view_host()->
-          ExecuteJavascriptInWebFrame(L"", L"WebInspector.showConsole();");
+      tab_contents_->render_view_host()->ExecuteJavascriptInWebFrame(
+          string16(), ASCIIToUTF16("WebInspector.showConsole();"));
       break;
     case DEVTOOLS_TOGGLE_ACTION_INSPECT:
-      tab_contents_->render_view_host()->
-          ExecuteJavascriptInWebFrame(
-              L"", L"WebInspector.toggleSearchingForNode();");
+      tab_contents_->render_view_host()->ExecuteJavascriptInWebFrame(
+          string16(), ASCIIToUTF16("WebInspector.toggleSearchingForNode();"));
     case DEVTOOLS_TOGGLE_ACTION_NONE:
       // Do nothing.
       break;
@@ -393,7 +407,19 @@
       SkColorToRGBAString(color_toolbar).c_str(),
       SkColorToRGBAString(color_tab_text).c_str());
   tab_contents_->render_view_host()->
-      ExecuteJavascriptInWebFrame(L"", UTF8ToWide(command));
+      ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(command));
+}
+
+void DevToolsWindow::AddNewContents(TabContents* source,
+                                    TabContents* new_contents,
+                                    WindowOpenDisposition disposition,
+                                    const gfx::Rect& initial_pos,
+                                    bool user_gesture) {
+  inspected_tab_->delegate()->AddNewContents(source,
+                                             new_contents,
+                                             disposition,
+                                             initial_pos,
+                                             user_gesture);
 }
 
 bool DevToolsWindow::CanReloadContents(TabContents* source) const {
diff --git a/chrome/browser/debugger/devtools_window.h b/chrome/browser/debugger/devtools_window.h
index e7b9afc..689ae40 100644
--- a/chrome/browser/debugger/devtools_window.h
+++ b/chrome/browser/debugger/devtools_window.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,7 +23,6 @@
 class BrowserWindow;
 class Profile;
 class RenderViewHost;
-class TabContentsWrapper;
 class Value;
 
 class DevToolsWindow
@@ -41,6 +40,7 @@
   virtual DevToolsWindow* AsDevToolsWindow();
   virtual void SendMessageToClient(const IPC::Message& message);
   virtual void InspectedTabClosing();
+  virtual void TabReplaced(TabContentsWrapper* new_tab);
 
   void Show(DevToolsToggleAction action);
   void Activate();
@@ -55,6 +55,7 @@
   void CreateDevToolsBrowser();
   bool FindInspectedBrowserAndTabIndex(Browser**, int* tab);
   BrowserWindow* GetInspectedBrowserWindow();
+  bool IsInspectedBrowserPopup();
   void SetAttachedWindow();
 
   // Overridden from NotificationObserver.
@@ -67,7 +68,7 @@
   GURL GetDevToolsUrl();
   void UpdateTheme();
   void AddDevToolsExtensionsToClient();
-  void CallClientFunction(const std::wstring& function_name,
+  void CallClientFunction(const string16& function_name,
                           const Value& arg);
   // Overridden from TabContentsDelegate.
   virtual void OpenURLFromTab(TabContents* source,
@@ -81,20 +82,21 @@
                               TabContents* new_contents,
                               WindowOpenDisposition disposition,
                               const gfx::Rect& initial_pos,
-                              bool user_gesture) {}
+                              bool user_gesture);
   virtual void ActivateContents(TabContents* contents) {}
   virtual void DeactivateContents(TabContents* contents) {}
   virtual void LoadingStateChanged(TabContents* source) {}
   virtual void CloseContents(TabContents* source) {}
   virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
   virtual bool CanReloadContents(TabContents* source) const;
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
   virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
                                       bool* is_keyboard_shortcut);
   virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
 
+  virtual void FrameNavigating(const std::string& url) {}
+
   Profile* profile_;
   TabContents* inspected_tab_;
   TabContentsWrapper* tab_contents_;
diff --git a/chrome/browser/debugger/inspectable_tab_proxy.cc b/chrome/browser/debugger/inspectable_tab_proxy.cc
index 9aa0622..652e540 100644
--- a/chrome/browser/debugger/inspectable_tab_proxy.cc
+++ b/chrome/browser/debugger/inspectable_tab_proxy.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/devtools_messages.h"
 
@@ -49,12 +48,17 @@
   IPC_END_MESSAGE_MAP()
 }
 
+void DevToolsClientHostImpl::TabReplaced(TabContentsWrapper* new_tab) {
+  map_->erase(id_);
+  id_ = new_tab->controller().session_id().id();
+  (*map_)[id_] = this;
+}
 
 void DevToolsClientHostImpl::OnDebuggerOutput(const std::string& data) {
   service_->DebuggerOutput(id_, data);
 }
 
-void DevToolsClientHostImpl::FrameNavigate(const std::string& url) {
+void DevToolsClientHostImpl::FrameNavigating(const std::string& url) {
   service_->FrameNavigate(id_, url);
 }
 
diff --git a/chrome/browser/debugger/inspectable_tab_proxy.h b/chrome/browser/debugger/inspectable_tab_proxy.h
index 8d02727..e521b31 100644
--- a/chrome/browser/debugger/inspectable_tab_proxy.h
+++ b/chrome/browser/debugger/inspectable_tab_proxy.h
@@ -76,11 +76,12 @@
   // DevToolsClientHost interface
   virtual void InspectedTabClosing();
   virtual void SendMessageToClient(const IPC::Message& msg);
+  virtual void TabReplaced(TabContentsWrapper* new_tab);
 
  private:
   // Message handling routines
   void OnDebuggerOutput(const std::string& msg);
-  void FrameNavigate(const std::string& url);
+  virtual void FrameNavigating(const std::string& url);
   void TabClosed();
 
   int32 id_;
diff --git a/chrome/browser/default_encoding_combo_model.cc b/chrome/browser/default_encoding_combo_model.cc
index 22746ac..4fdb87a 100644
--- a/chrome/browser/default_encoding_combo_model.cc
+++ b/chrome/browser/default_encoding_combo_model.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/default_encoding_combo_model.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_collator.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
 
 DefaultEncodingComboboxModel::DefaultEncodingComboboxModel() {
   // Initialize the vector of all sorted encodings according to current
diff --git a/chrome/browser/default_encoding_combo_model.h b/chrome/browser/default_encoding_combo_model.h
index a4d5a50..137fe64 100644
--- a/chrome/browser/default_encoding_combo_model.h
+++ b/chrome/browser/default_encoding_combo_model.h
@@ -9,17 +9,17 @@
 #include <string>
 #include <vector>
 
-#include "app/combobox_model.h"
 #include "chrome/browser/character_encoding.h"
+#include "ui/base/models/combobox_model.h"
 
 class Profile;
 
-class DefaultEncodingComboboxModel : public ComboboxModel {
+class DefaultEncodingComboboxModel : public ui::ComboboxModel {
  public:
   DefaultEncodingComboboxModel();
   virtual ~DefaultEncodingComboboxModel();
 
-  // Overridden from ComboboxModel.
+  // Overridden from ui::ComboboxModel.
   virtual int GetItemCount();
 
   virtual string16 GetItemAt(int index);
diff --git a/chrome/browser/defaults.cc b/chrome/browser/defaults.cc
index 4bb5288..50ed612 100644
--- a/chrome/browser/defaults.cc
+++ b/chrome/browser/defaults.cc
@@ -10,12 +10,9 @@
 
 // Make the regular omnibox text two points larger than the nine-point font
 // used in the tab strip (11pt / 72pt/in * 96px/in = 14.667px).
-const double kAutocompleteEditFontPixelSize = 14.7;
-const double kAutocompleteEditFontPixelSizeInPopup = 10.0;
+const int kAutocompleteEditFontPixelSize = 15;
 
-// This is only used by AutocompletePopupViewGtk which is unused
-// unless TOOLKIT_VIEWS is undefined:
-const int kAutocompletePopupFontSize = 7;
+const int kAutocompleteEditFontPixelSizeInPopup = 10;
 
 const SessionStartupPref::Type kDefaultSessionStartupType =
     SessionStartupPref::LAST;
@@ -36,15 +33,13 @@
 #elif defined(TOOLKIT_USES_GTK)
 
 // 13.4px = 10pt @ 96dpi.
-const double kAutocompleteEditFontPixelSize = 13.4;
+const int kAutocompleteEditFontPixelSize = 13;
 
-// On Windows, popup windows' autocomplete box have a font 5/6 the size of a
-// regular window, which we duplicate here for GTK.
-const double kAutocompleteEditFontPixelSizeInPopup =
+// On Windows, popup windows' location text uses a font 5/6 the size of
+// that in a regular window, which we duplicate here for GTK.
+const int kAutocompleteEditFontPixelSizeInPopup =
     kAutocompleteEditFontPixelSize * 5.0 / 6.0;
 
-const int kAutocompletePopupFontSize = 10;
-
 #if defined(TOOLKIT_VIEWS)
 const bool kCanToggleSystemTitleBar = false;
 #else
@@ -86,4 +81,6 @@
 
 bool skip_restore = false;
 
+bool enable_help_app = true;
+
 }  // namespace browser_defaults
diff --git a/chrome/browser/defaults.h b/chrome/browser/defaults.h
index b20cc12..147c29e 100644
--- a/chrome/browser/defaults.h
+++ b/chrome/browser/defaults.h
@@ -15,14 +15,11 @@
 
 #if defined(USE_X11)
 
-// Size of the font in pixels used in the autocomplete box for normal windows.
-extern const double kAutocompleteEditFontPixelSize;
+// Size of the font used in the autocomplete box for normal windows, in pixels.
+extern const int kAutocompleteEditFontPixelSize;
 
-// Size of the font in pixels used in the autocomplete box for popup windows.
-extern const double kAutocompleteEditFontPixelSizeInPopup;
-
-// Size of the font used in the autocomplete popup.
-extern const int kAutocompletePopupFontSize;
+// Size of the font used in the autocomplete box for popup windows, in pixels.
+extern const int kAutocompleteEditFontPixelSizeInPopup;
 
 // Can the user toggle the system title bar?
 extern const bool kCanToggleSystemTitleBar;
@@ -84,6 +81,10 @@
 // Should we skip the user's preference for restore. False by default.
 extern bool skip_restore;
 
+// Whether HelpApp is enabled. True by default. This is only used by Chrome OS
+// today.
+extern bool enable_help_app;
+
 }  // namespace browser_defaults
 
 #endif  // CHROME_BROWSER_DEFAULTS_H_
diff --git a/chrome/browser/desktop_notification_handler.cc b/chrome/browser/desktop_notification_handler.cc
new file mode 100644
index 0000000..7f6cab2
--- /dev/null
+++ b/chrome/browser/desktop_notification_handler.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/desktop_notification_handler.h"
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/render_messages_params.h"
+
+DesktopNotificationHandler::DesktopNotificationHandler(
+    TabContents* tab, RenderProcessHost* process)
+  : tab_(tab),
+    process_(process) {
+}
+
+bool DesktopNotificationHandler::OnMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+
+  IPC_BEGIN_MESSAGE_MAP(DesktopNotificationHandler, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDesktopNotification,
+                        OnShowDesktopNotification)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_CancelDesktopNotification,
+                        OnCancelDesktopNotification)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_RequestNotificationPermission,
+                        OnRequestNotificationPermission)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+
+  return handled;
+}
+
+void DesktopNotificationHandler::OnShowDesktopNotification(
+    const IPC::Message& message,
+    const ViewHostMsg_ShowNotification_Params& params) {
+  RenderProcessHost* process = GetRenderProcessHost();
+  DesktopNotificationService* service =
+      process->profile()->GetDesktopNotificationService();
+
+  service->ShowDesktopNotification(
+    params,
+    process->id(),
+    message.routing_id(),
+    DesktopNotificationService::PageNotification);
+}
+
+void DesktopNotificationHandler::OnCancelDesktopNotification(
+    const IPC::Message& message, int notification_id) {
+  RenderProcessHost* process = GetRenderProcessHost();
+  DesktopNotificationService* service =
+      process->profile()->GetDesktopNotificationService();
+
+  service->CancelDesktopNotification(
+      process->id(),
+      message.routing_id(),
+      notification_id);
+}
+
+void DesktopNotificationHandler::OnRequestNotificationPermission(
+    const IPC::Message& message, const GURL& source_origin,
+    int callback_context) {
+  RenderProcessHost* process = GetRenderProcessHost();
+  Browser* browser = BrowserList::GetLastActive();
+  // We may not have a BrowserList if the chrome browser process is launched as
+  // a ChromeFrame process in which case we attempt to use the TabContents
+  // provided by the RenderViewHostDelegate.
+  TabContents* tab = browser ? browser->GetSelectedTabContents() : tab_;
+  if (!tab)
+    return;
+
+  DesktopNotificationService* service =
+      tab->profile()->GetDesktopNotificationService();
+  service->RequestPermission(
+      source_origin,
+      process->id(),
+      message.routing_id(),
+      callback_context,
+      tab);
+}
+
+RenderProcessHost* DesktopNotificationHandler::GetRenderProcessHost() {
+  return tab_ ? tab_->GetRenderProcessHost() : process_;
+}
+
diff --git a/chrome/browser/desktop_notification_handler.h b/chrome/browser/desktop_notification_handler.h
new file mode 100644
index 0000000..d8c37cf
--- /dev/null
+++ b/chrome/browser/desktop_notification_handler.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DESKTOP_NOTIFICATION_HANDLER_H_
+#define CHROME_BROWSER_DESKTOP_NOTIFICATION_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+#include "ipc/ipc_message.h"
+
+struct ViewHostMsg_ShowNotification_Params;
+class RenderProcessHost;
+
+// Per-tab Desktop notification handler. Handles desktop notification IPCs
+// coming in from the renderer.
+class DesktopNotificationHandler : public TabContentsObserver {
+ public:
+  explicit DesktopNotificationHandler(TabContents* tab_contents,
+                                      RenderProcessHost* process);
+  virtual ~DesktopNotificationHandler() {}
+
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+  RenderProcessHost* GetRenderProcessHost();
+
+ private:
+  // IPC handlers.
+  void OnShowDesktopNotification(
+      const IPC::Message& message,
+      const ViewHostMsg_ShowNotification_Params& params);
+  void OnCancelDesktopNotification(const IPC::Message& message,
+                                   int notification_id);
+  void OnRequestNotificationPermission(const IPC::Message& message,
+                                       const GURL& origin,
+                                       int callback_id);
+
+ private:
+  TabContents* tab_;
+  RenderProcessHost* process_;
+
+  DISALLOW_COPY_AND_ASSIGN(DesktopNotificationHandler);
+};
+
+#endif  // CHROME_BROWSER_DESKTOP_NOTIFICATION_HANDLER_H_
+
diff --git a/chrome/browser/device_orientation/accelerometer_mac.cc b/chrome/browser/device_orientation/accelerometer_mac.cc
index 8634db2..b4924a2 100644
--- a/chrome/browser/device_orientation/accelerometer_mac.cc
+++ b/chrome/browser/device_orientation/accelerometer_mac.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -108,33 +108,73 @@
 // All non-tested entries from SMSLib have been removed.
 const AccelerometerMac::SensorDescriptor
     AccelerometerMac::kSupportedSensors[] = {
-  // Tested by leandrogracia on a 15'' MacBook Pro.
+  // Tested by S.Selz. (via avi) on a 13" MacBook.
+  { "MacBook2,1",    { { 0, true  }, { 2, false }, { 4, true  } } },
+
+  // Tested by adlr on a 13" MacBook.
+  { "MacBook4,1",    { { 0, true  }, { 2, true  }, { 4, false } } },
+
+  // Tested by avi on a 13" MacBook.
+  { "MacBook7,1",    { { 0, true  }, { 2, true  }, { 4, false } } },
+
+  // Tested by sfiera, pjw on a 13" MacBook Air.
+  { "MacBookAir2,1", { { 0, true  }, { 2, true  }, { 4, false } } },
+
+  // Note: MacBookAir3,1 (11" MacBook Air) and MacBookAir3,2 (13" MacBook Air)
+  // have no accelerometer sensors.
+
+  // Tested by L.V. (via avi) on a 17" MacBook Pro.
+  { "MacBookPro2,1", { { 0, true  }, { 2, false }, { 4, true  } } },
+
+  // Tested by leandrogracia on a 15" MacBook Pro.
   { "MacBookPro2,2", { { 0, true  }, { 2, true  }, { 4, false } } },
 
-  // Tested by leandrogracia on a 15'' MacBook Pro.
+  // Tested by leandrogracia on a 15" MacBook Pro.
+  // TODO(avi): this model name was also used for the 17" version; verify that
+  // these parameters are also valid for that model.
   { "MacBookPro3,1", { { 0, false }, { 2, true  }, { 4, true  } } },
 
-  // Tested by leandrogracia on a 15'' MacBook Pro.
+  // Tested by leandrogracia on a 15" MacBook Pro.
+  // Tested by Eric Shapiro (via avi) on a 17" MacBook Pro.
   { "MacBookPro4,1", { { 0, true  }, { 2, true  }, { 4, false } } },
 
-  // Tested by leandrogracia on a 15'' MacBook Pro.
+  // Tested by leandrogracia on a 15" MacBook Pro.
   { "MacBookPro5,1", { { 0, false }, { 2, false }, { 4, false } } },
 
-  // Tested by leandrogracia on a 15'' MacBook Pro.
+  // Tested by S.Selz. (via avi) on a 17" MacBook Pro.
+  { "MacBookPro5,2", { { 0, false }, { 2, false }, { 4, false } } },
+
+  // Tested by dmaclach on a 15" MacBook Pro.
+  { "MacBookPro5,3", { { 2, false }, { 0, false }, { 4, true  } } },
+
+  // Tested by leandrogracia on a 15" MacBook Pro.
   { "MacBookPro5,4", { { 0, false }, { 2, false }, { 4, false } } },
 
-  // Tested by leandrogracia on a 13'' MacBook Pro.
+  // Tested by leandrogracia on a 13" MacBook Pro.
   { "MacBookPro5,5", { { 0, true  }, { 2, true  }, { 4, false } } },
 
-  // Tested by leandrogracia on a 15'' MacBook Pro.
+  // Tested by khom, leadpipe on a 17" MacBook Pro.
+  { "MacBookPro6,1", { { 0, false }, { 2, false }, { 4, false } } },
+
+  // Tested by leandrogracia on a 15" MacBook Pro.
   { "MacBookPro6,2", { { 0, true  }, { 2, false }, { 4, true  } } },
 
-  // Tested by leandrogracia on a 13'' MacBook Pro.
+  // Tested by leandrogracia on a 13" MacBook Pro.
   { "MacBookPro7,1", { { 0, true  }, { 2, true  }, { 4, false } } },
 
-  // Generic MacBook accelerometer sensor data.
-  // Added for compatibility with non-tested models
-  // Note: there may be problems with inverted axes.
+  // Generic MacBook accelerometer sensor data, used for for both future models
+  // and past models for which there has been no testing. Note that this generic
+  // configuration may well have problems with inverted axes.
+  // TODO(avi): Find these past models and test on them; test on future models.
+  //  MacBook1,1
+  //  MacBook3,1
+  //  MacBook5,1
+  //  MacBook5,2
+  //  MacBook6,1
+  //  MacBookAir1,1
+  //  MacBookPro1,1
+  //  MacBookPro1,2
+  //  MacBookPro3,1 (17" to compare to 15")
   { "", { { 0, true  }, { 2, true  }, { 4, false } } }
 };
 
@@ -271,7 +311,6 @@
   const SensorDescriptor* sensor_candidate = NULL;
 
   // Look for the current model in the supported sensor list.
-  io_object_t device = 0;
   const int kNumSensors = arraysize(kSupportedSensors);
 
   for (int i = 0; i < kNumSensors; ++i) {
@@ -300,7 +339,9 @@
     }
 
     // Get the first device in the list.
-    if ((device = IOIteratorNext(device_iterator)) == 0)
+    io_object_t device = IOIteratorNext(device_iterator);
+    IOObjectRelease(device_iterator);
+    if (device == 0)
       continue;
 
     // Try to open device.
diff --git a/chrome/browser/device_orientation/provider_impl.cc b/chrome/browser/device_orientation/provider_impl.cc
index 330740d..6fe33cf 100644
--- a/chrome/browser/device_orientation/provider_impl.cc
+++ b/chrome/browser/device_orientation/provider_impl.cc
@@ -10,6 +10,7 @@
 #include "base/message_loop.h"
 #include "base/task.h"
 #include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/device_orientation/orientation.h"
 #include "chrome/browser/device_orientation/provider_impl.h"
 
@@ -58,6 +59,10 @@
 
 void ProviderImpl::Stop() {
   DCHECK(MessageLoop::current() == creator_loop_);
+
+  // TODO(hans): Don't join the thread. See crbug.com/72286.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
   polling_thread_.reset();
   data_fetcher_.reset();
 }
diff --git a/chrome/browser/device_orientation/provider_unittest.cc b/chrome/browser/device_orientation/provider_unittest.cc
index a84de5b..131504a 100644
--- a/chrome/browser/device_orientation/provider_unittest.cc
+++ b/chrome/browser/device_orientation/provider_unittest.cc
@@ -4,8 +4,8 @@
 
 #include <queue>
 
-#include "base/lock.h"
 #include "base/message_loop.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "chrome/browser/device_orientation/data_fetcher.h"
 #include "chrome/browser/device_orientation/orientation.h"
@@ -78,7 +78,7 @@
   }
 
   void SetOrientation(const Orientation& orientation) {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     orientation_ = orientation;
   }
 
@@ -91,7 +91,7 @@
 
     // From DataFetcher. Called by the Provider.
     virtual bool GetOrientation(Orientation* orientation) {
-      AutoLock auto_lock(orientation_factory_->lock_);
+      base::AutoLock auto_lock(orientation_factory_->lock_);
       *orientation = orientation_factory_->orientation_;
       return true;
     }
@@ -102,7 +102,7 @@
 
   static MockOrientationFactory* instance_;
   Orientation orientation_;
-  Lock lock_;
+  base::Lock lock_;
 };
 
 MockOrientationFactory* MockOrientationFactory::instance_;
diff --git a/chrome/browser/diagnostics/diagnostics_main.cc b/chrome/browser/diagnostics/diagnostics_main.cc
index 059dd59..6cbcb28 100644
--- a/chrome/browser/diagnostics/diagnostics_main.cc
+++ b/chrome/browser/diagnostics/diagnostics_main.cc
@@ -21,6 +21,7 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/diagnostics/diagnostics_model.h"
 #include "chrome/common/chrome_paths.h"
+#include "ui/base/ui_base_paths.h"
 
 namespace {
 // This is a minimalistic interface to wrap the platform console.  This will be
@@ -343,6 +344,7 @@
   // We need to have the path providers registered. They both
   // return void so there is no early error signal that we can use.
   app::RegisterPathProvider();
+  ui::RegisterPathProvider();
   chrome::RegisterPathProvider();
 
   TestWriter writer(console);
diff --git a/chrome/browser/diagnostics/recon_diagnostics.cc b/chrome/browser/diagnostics/recon_diagnostics.cc
index 2cacd86..218e85f 100644
--- a/chrome/browser/diagnostics/recon_diagnostics.cc
+++ b/chrome/browser/diagnostics/recon_diagnostics.cc
@@ -97,7 +97,8 @@
     string16 failures = ASCIIToUTF16("Possibly conflicting modules:");
     DictionaryValue* dictionary;
     for (size_t i = 0; i < list->GetSize(); ++i) {
-      list->GetDictionary(i, &dictionary);
+      if (!list->GetDictionary(i, &dictionary))
+        RecordFailure(ASCIIToUTF16("Dictionary lookup failed"));
       int status;
       string16 location;
       string16 name;
@@ -144,8 +145,7 @@
       RecordFailure(ASCIIToUTF16("Path provider failure"));
       return false;
     }
-    user_level_ = InstallUtil::IsPerUserInstall(
-        chrome_exe.ToWStringHack().c_str());
+    user_level_ = InstallUtil::IsPerUserInstall(chrome_exe.value().c_str());
     const char* type = user_level_ ? "User Level" : "System Level";
     string16 install_type(ASCIIToUTF16(type));
 #else
@@ -240,7 +240,8 @@
       return false;
     }
     if (!file_util::PathExists(dir_or_file)) {
-      RecordFailure(ASCIIToUTF16("Path not found"));
+      RecordFailure(ASCIIToUTF16("Path not found: ") +
+                    dir_or_file.LossyDisplayName());
       return true;
     }
 
@@ -251,7 +252,8 @@
       file_util::GetFileSize(dir_or_file, &dir_or_file_size);
     }
     if (!dir_or_file_size && !path_info_.is_optional) {
-      RecordFailure(ASCIIToUTF16("Cannot obtain size"));
+      RecordFailure(ASCIIToUTF16("Cannot obtain size for: ") +
+                    dir_or_file.LossyDisplayName());
       return true;
     }
     DataUnits units = GetByteDisplayUnits(dir_or_file_size);
@@ -259,7 +261,10 @@
 
     if (path_info_.max_size > 0) {
       if (dir_or_file_size > path_info_.max_size) {
-        RecordFailure(ASCIIToUTF16("Path is too big: ") + printable_size);
+        RecordFailure(ASCIIToUTF16("Path contents too large (") +
+                      printable_size +
+                      ASCIIToUTF16(") for: ") +
+                      dir_or_file.LossyDisplayName());
         return true;
       }
     }
@@ -268,7 +273,8 @@
       return true;
     }
     if (!file_util::PathIsWritable(dir_or_file)) {
-      RecordFailure(ASCIIToUTF16("Path is not writable"));
+      RecordFailure(ASCIIToUTF16("Path is not writable: ") +
+                    dir_or_file.LossyDisplayName());
       return true;
     }
     RecordSuccess(ASCIIToUTF16("Path exists and is writable: ")
@@ -327,7 +333,11 @@
       return true;
     }
     int64 file_size;
-    file_util::GetFileSize(path_, &file_size);
+    if (!file_util::GetFileSize(path_, &file_size)) {
+      RecordFailure(ASCIIToUTF16("Cannot obtain file size"));
+      return true;
+    }
+
     if (file_size > max_file_size_) {
       RecordFailure(ASCIIToUTF16("File too big"));
       return true;
diff --git a/chrome/browser/disposition_utils.cc b/chrome/browser/disposition_utils.cc
new file mode 100644
index 0000000..326a323
--- /dev/null
+++ b/chrome/browser/disposition_utils.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/disposition_utils.h"
+
+#include "build/build_config.h"
+
+namespace disposition_utils {
+
+WindowOpenDisposition DispositionFromClick(bool middle_button,
+                                           bool alt_key,
+                                           bool ctrl_key,
+                                           bool meta_key,
+                                           bool shift_key) {
+  // MacOS uses meta key (Command key) to spawn new tabs.
+#if defined(OS_MACOSX)
+  if (middle_button || meta_key)
+#else
+  if (middle_button || ctrl_key)
+#endif
+    return shift_key ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
+  if (shift_key)
+    return NEW_WINDOW;
+  if (alt_key)
+    return SAVE_TO_DISK;
+  return CURRENT_TAB;
+}
+
+}
diff --git a/chrome/browser/disposition_utils.h b/chrome/browser/disposition_utils.h
new file mode 100644
index 0000000..eb847f9
--- /dev/null
+++ b/chrome/browser/disposition_utils.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DISPOSITION_UTILS_H_
+#define CHROME_BROWSER_DISPOSITION_UTILS_H_
+#pragma once
+
+#include "webkit/glue/window_open_disposition.h"
+
+namespace disposition_utils {
+
+// Translates event flags from a click on a link into the user's desired
+// window disposition.  For example, a middle click would mean to open
+// a background tab.
+WindowOpenDisposition DispositionFromClick(bool middle_button,
+                                           bool alt_key,
+                                           bool ctrl_key,
+                                           bool meta_key,
+                                           bool shift_key);
+
+}
+
+#endif  // CHROME_BROWSER_DISPOSITION_UTILS_H_
diff --git a/chrome/browser/dom_ui/OWNERS b/chrome/browser/dom_ui/OWNERS
new file mode 100644
index 0000000..741a5c4
--- /dev/null
+++ b/chrome/browser/dom_ui/OWNERS
@@ -0,0 +1 @@
+arv@chromium.org
diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc
index aba23f1..1355f92 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.cc
+++ b/chrome/browser/dom_ui/app_launcher_handler.cc
@@ -1,16 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/app_launcher_handler.h"
 
+#include <string>
+#include <vector>
+
 #include "base/metrics/histogram.h"
 #include "base/string_number_conversions.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/app_launched_animation.h"
+#include "chrome/browser/disposition_utils.h"
+#include "chrome/browser/dom_ui/shown_sections_handler.h"
 #include "chrome/browser/extensions/default_apps.h"
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -20,7 +24,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_icon_set.h"
@@ -28,10 +31,11 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/rect.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "ui/base/animation/animation.h"
+#include "ui/gfx/rect.h"
+#include "webkit/glue/window_open_disposition.h"
 
 namespace {
 
@@ -40,18 +44,6 @@
 const char* kLaunchAppPingURL = "record-app-launch";
 const char* kLaunchWebStorePingURL = "record-webstore-launch";
 
-// This extracts an int from a ListValue at the given |index|.
-bool ExtractInt(const ListValue* list, size_t index, int* out_int) {
-  std::string string_value;
-
-  if (list->GetString(index, &string_value)) {
-    base::StringToInt(string_value, out_int);
-    return true;
-  }
-
-  return false;
-}
-
 std::string GetIconURL(const Extension* extension, Extension::Icons icon,
                        const std::string& default_val) {
   GURL url = extension->GetIconURL(icon, ExtensionIconSet::MATCH_EXACTLY);
@@ -75,7 +67,8 @@
 
 AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service)
     : extensions_service_(extension_service),
-      promo_active_(false) {
+      promo_active_(false),
+      ignore_changes_(false) {
 }
 
 AppLauncherHandler::~AppLauncherHandler() {}
@@ -99,7 +92,7 @@
   value->SetInteger("launch_container", extension->launch_container());
   value->SetInteger("launch_type",
       extension_prefs->GetLaunchType(extension->id(),
-                                     ExtensionPrefs::LAUNCH_REGULAR));
+                                     ExtensionPrefs::LAUNCH_DEFAULT));
 
   int app_launch_index = extension_prefs->GetAppLaunchIndex(extension->id());
   if (app_launch_index == -1) {
@@ -111,54 +104,72 @@
 }
 
 // static
-bool AppLauncherHandler::HandlePing(const std::string& path) {
-  if (path.find(kLaunchWebStorePingURL) != std::string::npos) {
-    RecordWebStoreLaunch(IsPromoActive(path));
-    return true;
-  } else if (path.find(kLaunchAppPingURL) != std::string::npos) {
-    RecordAppLaunch(IsPromoActive(path));
-    return true;
-  }
+bool AppLauncherHandler::HandlePing(Profile* profile, const std::string& path) {
+  bool is_web_store_ping =
+      path.find(kLaunchWebStorePingURL) != std::string::npos;
+  bool is_app_launch_ping =
+      path.find(kLaunchAppPingURL) != std::string::npos;
 
-  return false;
+  // We get called for every URL in chrome://newtab/. Return false if it isn't
+  // one we handle.
+  if (!is_web_store_ping && !is_app_launch_ping)
+    return false;
+
+  bool is_promo_active = IsPromoActive(path);
+
+  if (is_web_store_ping)
+    RecordWebStoreLaunch(is_promo_active);
+  else
+    RecordAppLaunch(is_promo_active);
+
+  if (is_promo_active)
+    profile->GetExtensionService()->default_apps()->SetPromoHidden();
+
+  return true;
 }
 
-DOMMessageHandler* AppLauncherHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* AppLauncherHandler::Attach(WebUI* web_ui) {
   // TODO(arv): Add initialization code to the Apps store etc.
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void AppLauncherHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getApps",
+  web_ui_->RegisterMessageCallback("getApps",
       NewCallback(this, &AppLauncherHandler::HandleGetApps));
-  dom_ui_->RegisterMessageCallback("launchApp",
+  web_ui_->RegisterMessageCallback("launchApp",
       NewCallback(this, &AppLauncherHandler::HandleLaunchApp));
-  dom_ui_->RegisterMessageCallback("setLaunchType",
+  web_ui_->RegisterMessageCallback("setLaunchType",
       NewCallback(this, &AppLauncherHandler::HandleSetLaunchType));
-  dom_ui_->RegisterMessageCallback("uninstallApp",
+  web_ui_->RegisterMessageCallback("uninstallApp",
       NewCallback(this, &AppLauncherHandler::HandleUninstallApp));
-  dom_ui_->RegisterMessageCallback("hideAppsPromo",
+  web_ui_->RegisterMessageCallback("hideAppsPromo",
       NewCallback(this, &AppLauncherHandler::HandleHideAppsPromo));
-  dom_ui_->RegisterMessageCallback("createAppShortcut",
+  web_ui_->RegisterMessageCallback("createAppShortcut",
       NewCallback(this, &AppLauncherHandler::HandleCreateAppShortcut));
+  web_ui_->RegisterMessageCallback("reorderApps",
+      NewCallback(this, &AppLauncherHandler::HandleReorderApps));
 }
 
 void AppLauncherHandler::Observe(NotificationType type,
                                  const NotificationSource& source,
                                  const NotificationDetails& details) {
+  if (ignore_changes_)
+    return;
+
   switch (type.value) {
     case NotificationType::EXTENSION_LOADED:
     case NotificationType::EXTENSION_UNLOADED:
-      if (dom_ui_->tab_contents())
+    case NotificationType::EXTENSION_LAUNCHER_REORDERED:
+      if (web_ui_->tab_contents())
         HandleGetApps(NULL);
       break;
     case NotificationType::PREF_CHANGED: {
-      if (!dom_ui_->tab_contents())
+      if (!web_ui_->tab_contents())
         break;
 
       DictionaryValue dictionary;
       FillAppDictionary(&dictionary);
-      dom_ui_->CallJavascriptFunction(L"appsPrefChangeCallback", dictionary);
+      web_ui_->CallJavascriptFunction(L"appsPrefChangeCallback", dictionary);
       break;
     }
     default:
@@ -171,9 +182,9 @@
   const ExtensionList* extensions = extensions_service_->extensions();
   for (ExtensionList::const_iterator it = extensions->begin();
        it != extensions->end(); ++it) {
-    // Don't include the WebStore component app. The WebStore launcher
-    // gets special treatment in ntp/apps.js.
-    if ((*it)->is_app() && (*it)->id() != extension_misc::kWebStoreAppId) {
+    // Don't include the WebStore and other component apps.
+    // The WebStore launcher gets special treatment in ntp/apps.js.
+    if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) {
       DictionaryValue* app_info = new DictionaryValue();
       CreateAppInfo(*it, extensions_service_->extension_prefs(), app_info);
       list->Append(app_info);
@@ -201,7 +212,6 @@
 
 void AppLauncherHandler::HandleGetApps(const ListValue* args) {
   DictionaryValue dictionary;
-  FillAppDictionary(&dictionary);
 
   // Tell the client whether to show the promo for this view. We don't do this
   // in the case of PREF_CHANGED because:
@@ -212,16 +222,25 @@
   // b) Conceptually, it doesn't really make sense to count a
   //    prefchange-triggered refresh as a promo 'view'.
   DefaultApps* default_apps = extensions_service_->default_apps();
-  if (default_apps->ShouldShowPromo(extensions_service_->GetAppIds())) {
+  bool promo_just_expired = false;
+  if (default_apps->ShouldShowPromo(extensions_service_->GetAppIds(),
+                                    &promo_just_expired)) {
     dictionary.SetBoolean("showPromo", true);
-    default_apps->DidShowPromo();
     promo_active_ = true;
   } else {
+    if (promo_just_expired) {
+      ignore_changes_ = true;
+      UninstallDefaultApps();
+      ignore_changes_ = false;
+      ShownSectionsHandler::SetShownSection(web_ui_->GetProfile()->GetPrefs(),
+                                            THUMB);
+    }
     dictionary.SetBoolean("showPromo", false);
     promo_active_ = false;
   }
 
-  dom_ui_->CallJavascriptFunction(L"getAppsCallback", dictionary);
+  FillAppDictionary(&dictionary);
+  web_ui_->CallJavascriptFunction(L"getAppsCallback", dictionary);
 
   // First time we get here we set up the observer so that we can tell update
   // the apps as they change.
@@ -230,6 +249,8 @@
         NotificationService::AllSources());
     registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
         NotificationService::AllSources());
+    registrar_.Add(this, NotificationType::EXTENSION_LAUNCHER_REORDERED,
+        NotificationService::AllSources());
   }
   if (pref_change_registrar_.IsEmpty()) {
     pref_change_registrar_.Init(
@@ -240,25 +261,33 @@
 
 void AppLauncherHandler::HandleLaunchApp(const ListValue* args) {
   std::string extension_id;
-  int left = 0;
-  int top = 0;
-  int width = 0;
-  int height = 0;
+  double left;
+  double top;
+  double width;
+  double height;
+  bool alt_key;
+  bool ctrl_key;
+  bool meta_key;
+  bool shift_key;
+  double button;
 
-  if (!args->GetString(0, &extension_id) ||
-      !ExtractInt(args, 1, &left) ||
-      !ExtractInt(args, 2, &top) ||
-      !ExtractInt(args, 3, &width) ||
-      !ExtractInt(args, 4, &height)) {
-    NOTREACHED();
-    return;
-  }
+  CHECK(args->GetString(0, &extension_id));
+  CHECK(args->GetDouble(1, &left));
+  CHECK(args->GetDouble(2, &top));
+  CHECK(args->GetDouble(3, &width));
+  CHECK(args->GetDouble(4, &height));
+  CHECK(args->GetBoolean(5, &alt_key));
+  CHECK(args->GetBoolean(6, &ctrl_key));
+  CHECK(args->GetBoolean(7, &meta_key));
+  CHECK(args->GetBoolean(8, &shift_key));
+  CHECK(args->GetDouble(9, &button));
 
   // The rect we get from the client is relative to the browser client viewport.
   // Offset the rect by the tab contents bounds.
-  gfx::Rect rect(left, top, width, height);
+  gfx::Rect rect(static_cast<int>(left), static_cast<int>(top),
+                 static_cast<int>(width), static_cast<int>(height));
   gfx::Rect tab_contents_bounds;
-  dom_ui_->tab_contents()->GetContainerBounds(&tab_contents_bounds);
+  web_ui_->tab_contents()->GetContainerBounds(&tab_contents_bounds);
   rect.Offset(tab_contents_bounds.origin());
 
   const Extension* extension =
@@ -266,39 +295,52 @@
   DCHECK(extension);
   Profile* profile = extensions_service_->profile();
 
-  // To give a more "launchy" experience when using the NTP launcher, we close
-  // it automatically.
-  Browser* browser = BrowserList::GetLastActive();
-  TabContents* old_contents = NULL;
-  if (browser)
-    old_contents = browser->GetSelectedTabContents();
+  // If the user pressed special keys when clicking, override the saved
+  // preference for launch container.
+  bool middle_button = (button == 1.0);
+  WindowOpenDisposition disposition =
+        disposition_utils::DispositionFromClick(middle_button, alt_key,
+                                                ctrl_key, meta_key, shift_key);
+  if (disposition == NEW_FOREGROUND_TAB || disposition == NEW_BACKGROUND_TAB) {
+    // TODO(jamescook): Proper support for background tabs.
+    Browser::OpenApplication(
+        profile, extension, extension_misc::LAUNCH_TAB, NULL);
+  } else if (disposition == NEW_WINDOW) {
+    // Force a new window open.
+    Browser::OpenApplication(
+            profile, extension, extension_misc::LAUNCH_WINDOW, NULL);
+  } else {
+    // Look at preference to find the right launch container.  If no preference
+    // is set, launch as a regular tab.
+    extension_misc::LaunchContainer launch_container =
+        extensions_service_->extension_prefs()->GetLaunchContainer(
+            extension, ExtensionPrefs::LAUNCH_REGULAR);
 
-  AnimateAppIcon(extension, rect);
+    // To give a more "launchy" experience when using the NTP launcher, we close
+    // it automatically.
+    Browser* browser = BrowserList::GetLastActive();
+    TabContents* old_contents = NULL;
+    if (browser)
+      old_contents = browser->GetSelectedTabContents();
 
-  // Look at preference to find the right launch container.  If no preference
-  // is set, launch as a regular tab.
-  extension_misc::LaunchContainer launch_container =
-      extensions_service_->extension_prefs()->GetLaunchContainer(
-          extension, ExtensionPrefs::LAUNCH_REGULAR);
+    TabContents* new_contents = Browser::OpenApplication(
+        profile, extension, launch_container, old_contents);
 
-  TabContents* new_contents = Browser::OpenApplication(
-      profile, extension, launch_container, old_contents);
+    if (new_contents != old_contents && browser->tab_count() > 1)
+      browser->CloseTabContents(old_contents);
+  }
 
-  if (new_contents != old_contents && browser->tab_count() > 1)
-    browser->CloseTabContents(old_contents);
-
-  if (extension_id != extension_misc::kWebStoreAppId)
+  if (extension_id != extension_misc::kWebStoreAppId) {
     RecordAppLaunch(promo_active_);
+    extensions_service_->default_apps()->SetPromoHidden();
+  }
 }
 
 void AppLauncherHandler::HandleSetLaunchType(const ListValue* args) {
   std::string extension_id;
-  int launch_type;
-  if (!args->GetString(0, &extension_id) ||
-      !ExtractInt(args, 1, &launch_type)) {
-    NOTREACHED();
-    return;
-  }
+  double launch_type;
+  CHECK(args->GetString(0, &extension_id));
+  CHECK(args->GetDouble(1, &launch_type));
 
   const Extension* extension =
       extensions_service_->GetExtensionById(extension_id, false);
@@ -306,7 +348,8 @@
 
   extensions_service_->extension_prefs()->SetLaunchType(
       extension_id,
-      static_cast<ExtensionPrefs::LaunchType>(launch_type));
+      static_cast<ExtensionPrefs::LaunchType>(
+          static_cast<int>(launch_type)));
 }
 
 void AppLauncherHandler::HandleUninstallApp(const ListValue* args) {
@@ -331,15 +374,13 @@
                             extension_misc::PROMO_CLOSE,
                             extension_misc::PROMO_BUCKET_BOUNDARY);
 
-  DefaultApps* default_apps = extensions_service_->default_apps();
-  const ExtensionIdSet& app_ids = default_apps->default_apps();
-  for (ExtensionIdSet::const_iterator iter = app_ids.begin();
-       iter != app_ids.end(); ++iter) {
-    if (extensions_service_->GetExtensionById(*iter, true))
-      extensions_service_->UninstallExtension(*iter, false);
-  }
-
+  ShownSectionsHandler::SetShownSection(web_ui_->GetProfile()->GetPrefs(),
+                                        THUMB);
+  ignore_changes_ = true;
+  UninstallDefaultApps();
   extensions_service_->default_apps()->SetPromoHidden();
+  ignore_changes_ = false;
+  HandleGetApps(NULL);
 }
 
 void AppLauncherHandler::HandleCreateAppShortcut(const ListValue* args) {
@@ -360,6 +401,17 @@
       browser->profile(), extension);
 }
 
+void AppLauncherHandler::HandleReorderApps(const ListValue* args) {
+  std::vector<std::string> extension_ids;
+  for (size_t i = 0; i < args->GetSize(); ++i) {
+    std::string value;
+    if (args->GetString(i, &value))
+      extension_ids.push_back(value);
+  }
+
+  extensions_service_->extension_prefs()->SetAppLauncherOrder(extension_ids);
+}
+
 // static
 void AppLauncherHandler::RecordWebStoreLaunch(bool promo_active) {
   if (!promo_active) return;
@@ -402,19 +454,16 @@
 
 ExtensionInstallUI* AppLauncherHandler::GetExtensionInstallUI() {
   if (!install_ui_.get())
-    install_ui_.reset(new ExtensionInstallUI(dom_ui_->GetProfile()));
+    install_ui_.reset(new ExtensionInstallUI(web_ui_->GetProfile()));
   return install_ui_.get();
 }
 
-void AppLauncherHandler::AnimateAppIcon(const Extension* extension,
-                                        const gfx::Rect& rect) {
-  // We make this check for the case of minimized windows, unit tests, etc.
-  if (platform_util::IsVisible(dom_ui_->tab_contents()->GetNativeView()) &&
-      ui::Animation::ShouldRenderRichAnimation()) {
-#if defined(OS_WIN)
-    AppLaunchedAnimation::Show(extension, rect);
-#else
-    NOTIMPLEMENTED();
-#endif
+void AppLauncherHandler::UninstallDefaultApps() {
+  DefaultApps* default_apps = extensions_service_->default_apps();
+  const ExtensionIdSet& app_ids = default_apps->default_apps();
+  for (ExtensionIdSet::const_iterator iter = app_ids.begin();
+       iter != app_ids.end(); ++iter) {
+    if (extensions_service_->GetExtensionById(*iter, true))
+      extensions_service_->UninstallExtension(*iter, false);
   }
 }
diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h
index 5f946d9..b31f16c 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.h
+++ b/chrome/browser/dom_ui/app_launcher_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/scoped_ptr.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/common/notification_observer.h"
@@ -18,6 +18,7 @@
 class ExtensionService;
 class NotificationRegistrar;
 class PrefChangeRegistrar;
+class Profile;
 
 namespace gfx {
   class Rect;
@@ -25,7 +26,7 @@
 
 // The handler for Javascript messages related to the "apps" view.
 class AppLauncherHandler
-    : public DOMMessageHandler,
+    : public WebUIMessageHandler,
       public ExtensionInstallUI::Delegate,
       public NotificationObserver {
  public:
@@ -38,10 +39,10 @@
                             DictionaryValue* value);
 
   // Callback for pings related to launching apps on the NTP.
-  static bool HandlePing(const std::string& path);
+  static bool HandlePing(Profile* profile, const std::string& path);
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // NotificationObserver
@@ -70,6 +71,9 @@
   // Callback for the "createAppShortcut" message.
   void HandleCreateAppShortcut(const ListValue* args);
 
+  // Callback for the 'reorderApps" message.
+  void HandleReorderApps(const ListValue* args);
+
  private:
   // Records a web store launch in the appropriate histograms. |promo_active|
   // specifies if the web store promotion was active.
@@ -88,8 +92,8 @@
   // needed.
   ExtensionInstallUI* GetExtensionInstallUI();
 
-  // Starts the animation of the app icon.
-  void AnimateAppIcon(const Extension* extension, const gfx::Rect& rect);
+  // Helper that uninstalls all the default apps.
+  void UninstallDefaultApps();
 
   // The apps are represented in the extensions model.
   scoped_refptr<ExtensionService> extensions_service_;
@@ -98,7 +102,7 @@
   // when necessary.
   NotificationRegistrar registrar_;
 
-  // Monitor extension preference changes so that the DOM UI can be notified.
+  // Monitor extension preference changes so that the Web UI can be notified.
   PrefChangeRegistrar pref_change_registrar_;
 
   // Used to show confirmation UI for uninstalling/enabling extensions in
@@ -111,6 +115,10 @@
   // Whether the promo is currently being shown.
   bool promo_active_;
 
+  // When true, we ignore changes to the underlying data rather than immediately
+  // refreshing. This is useful when making many batch updates to avoid flicker.
+  bool ignore_changes_;
+
   DISALLOW_COPY_AND_ASSIGN(AppLauncherHandler);
 };
 
diff --git a/chrome/browser/dom_ui/bookmarks_ui.cc b/chrome/browser/dom_ui/bookmarks_ui.cc
index 1875d45..828ab54 100644
--- a/chrome/browser/dom_ui/bookmarks_ui.cc
+++ b/chrome/browser/dom_ui/bookmarks_ui.cc
@@ -1,17 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/bookmarks_ui.h"
 
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/ref_counted_memory.h"
 #include "base/singleton.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/url_constants.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 //
@@ -44,16 +46,11 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-BookmarksUI::BookmarksUI(TabContents* contents) : DOMUI(contents) {
+BookmarksUI::BookmarksUI(TabContents* contents) : WebUI(contents) {
   BookmarksUIHTMLSource* html_source = new BookmarksUIHTMLSource();
 
   // Set up the chrome://bookmarks/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/bookmarks_ui.h b/chrome/browser/dom_ui/bookmarks_ui.h
index 8e8e61b..10cef4a 100644
--- a/chrome/browser/dom_ui/bookmarks_ui.h
+++ b/chrome/browser/dom_ui/bookmarks_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class GURL;
 class RefCountedMemory;
@@ -32,7 +32,7 @@
 
 // This class is used to hook up chrome://bookmarks/ which in turn gets
 // overridden by an extension.
-class BookmarksUI : public DOMUI {
+class BookmarksUI : public WebUI {
  public:
   explicit BookmarksUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/bookmarks_ui_uitest.cc b/chrome/browser/dom_ui/bookmarks_ui_uitest.cc
index 304c9ac..04c37f6 100644
--- a/chrome/browser/dom_ui/bookmarks_ui_uitest.cc
+++ b/chrome/browser/dom_ui/bookmarks_ui_uitest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/test/ui/ui_test.h"
 
+#include "base/test/test_timeouts.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/automation/browser_proxy.h"
@@ -21,7 +22,7 @@
         L"domAutomationController.send("
         L"    location.protocol == 'chrome-extension:' && "
         L"    document.readyState == 'complete')",
-        test_timeout_ms());
+        TestTimeouts::huge_test_timeout_ms());
   }
 
   scoped_refptr<TabProxy> GetBookmarksUITab() {
@@ -110,7 +111,8 @@
 
   // Bring up the bookmarks manager tab.
   ASSERT_TRUE(browser->RunCommand(IDC_SHOW_BOOKMARK_MANAGER));
-  ASSERT_TRUE(browser->WaitForTabToBecomeActive(1, action_max_timeout_ms()));
+  ASSERT_TRUE(browser->WaitForTabToBecomeActive(
+      1, TestTimeouts::action_max_timeout_ms()));
   ASSERT_TRUE(browser->GetTabCount(&tab_count));
   ASSERT_EQ(2, tab_count);
 
@@ -121,11 +123,13 @@
 
   // Switch to first tab and run command again.
   ASSERT_TRUE(browser->ActivateTab(0));
-  ASSERT_TRUE(browser->WaitForTabToBecomeActive(0, action_max_timeout_ms()));
+  ASSERT_TRUE(browser->WaitForTabToBecomeActive(
+      0, TestTimeouts::action_max_timeout_ms()));
   ASSERT_TRUE(browser->RunCommand(IDC_SHOW_BOOKMARK_MANAGER));
 
   // Ensure the bookmarks ui tab is active.
-  ASSERT_TRUE(browser->WaitForTabToBecomeActive(1, action_max_timeout_ms()));
+  ASSERT_TRUE(browser->WaitForTabToBecomeActive(
+      1, TestTimeouts::action_max_timeout_ms()));
   ASSERT_TRUE(browser->GetTabCount(&tab_count));
   ASSERT_EQ(2, tab_count);
 }
diff --git a/chrome/browser/dom_ui/bug_report_ui.cc b/chrome/browser/dom_ui/bug_report_ui.cc
index dc75bad..8423877 100644
--- a/chrome/browser/dom_ui/bug_report_ui.cc
+++ b/chrome/browser/dom_ui/bug_report_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -22,31 +20,23 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/bug_report_data.h"
 #include "chrome/browser/bug_report_util.h"
-#include "chrome/browser/dom_ui/dom_ui_screenshot_source.h"
+#include "chrome/browser/dom_ui/web_ui_screenshot_source.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/window_snapshot/window_snapshot.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/rect.h"
-
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-
-#if defined(USE_X11)
-#include "app/x11_util.h"
-#elif defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#elif defined(OS_WIN)
-#include "app/win/win_util.h"
-#endif
-
-#if defined(TOOLKIT_VIEWS)
-#include "views/window/window.h"
-#endif
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/rect.h"
 
 #if defined(OS_CHROMEOS)
 #include "base/file_util.h"
@@ -142,55 +132,17 @@
 std::vector<unsigned char>* last_screenshot_png = 0;
 gfx::Rect screen_size;
 
-// Get bounds in different ways for different OS's;
-#if defined(TOOLKIT_VIEWS)
-// Windows/ChromeOS support Views - so we get dimensions from the
-// views::Window object
-void RefreshLastScreenshot(views::Window* parent) {
-  gfx::NativeWindow window = parent->GetNativeWindow();
-  int width = parent->GetBounds().width();
-  int height = parent->GetBounds().height();
-#elif defined(OS_LINUX)
-// Linux provides its bounds and a native window handle to the screen
-void RefreshLastScreenshot(gfx::NativeWindow window,
-                           const gfx::Rect& bounds) {
-  int width = bounds.width();
-  int height = bounds.height();
-#elif defined(OS_MACOSX)
-// Mac gets its bounds from the GrabWindowSnapshot function
-void RefreshLastScreenshot(NSWindow* window) {
-  int width = 0;
-  int height = 0;
-#endif
-
-  // Grab an exact snapshot of the window that the user is seeing (i.e. as
-  // rendered--do not re-render, and include windowed plugins).
+void RefreshLastScreenshot(Browser* browser) {
   if (last_screenshot_png)
     last_screenshot_png->clear();
   else
     last_screenshot_png = new std::vector<unsigned char>;
 
-#if defined(USE_X11)
-  x11_util::GrabWindowSnapshot(window, last_screenshot_png);
-#elif defined(OS_MACOSX)
-  base::mac::GrabWindowSnapshot(window, last_screenshot_png, &width, &height);
-#elif defined(OS_WIN)
-  app::win::GrabWindowSnapshot(window, last_screenshot_png);
-#endif
-
-  screen_size.set_width(width);
-  screen_size.set_height(height);
+  gfx::NativeWindow native_window = browser->window()->GetNativeHandle();
+  screen_size = browser::GrabWindowSnapshot(native_window, last_screenshot_png);
 }
 
-#if defined(TOOLKIT_VIEWS)
-void ShowHtmlBugReportView(views::Window* parent, Browser* browser) {
-#elif defined(OS_LINUX)
-void ShowHtmlBugReportView(gfx::NativeWindow window, const gfx::Rect& bounds,
-                           Browser* browser) {
-#elif defined(OS_MACOSX)
-void ShowHtmlBugReportView(NSWindow* window, Browser* browser) {
-#endif
-
+void ShowHtmlBugReportView(Browser* browser) {
   // First check if we're already open (we cannot depend on ShowSingletonTab
   // for this functionality since we need to make *sure* we never get
   // instantiated again while we are open - with singleton tabs, that can
@@ -199,17 +151,10 @@
   if (feedback_tab_index >=0) {
     // Do not refresh screenshot, do not create a new tab
     browser->SelectTabContentsAt(feedback_tab_index, true);
+    return;
   }
 
-  // now for refreshing the last screenshot
-#if defined(TOOLKIT_VIEWS)
-  RefreshLastScreenshot(parent);
-#elif defined(OS_LINUX)
-  RefreshLastScreenshot(window, bounds);
-#elif defined(OS_MACOSX)
-  RefreshLastScreenshot(window);
-#endif
-
+  RefreshLastScreenshot(browser);
   std::string bug_report_url = std::string(chrome::kChromeUIBugReportURL) +
       "#" + base::IntToString(browser->selected_index());
   browser->ShowSingletonTab(GURL(bug_report_url), false);
@@ -239,7 +184,7 @@
 };
 
 // The handler for Javascript messages related to the "bug report" dialog
-class BugReportHandler : public DOMMessageHandler,
+class BugReportHandler : public WebUIMessageHandler,
                          public base::SupportsWeakPtr<BugReportHandler> {
  public:
   explicit BugReportHandler(TabContents* tab);
@@ -248,8 +193,8 @@
   // Init work after Attach.
   base::StringPiece Init();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
  private:
@@ -269,10 +214,9 @@
   void CloseFeedbackTab();
 
   TabContents* tab_;
-  DOMUIScreenshotSource* screenshot_source_;
+  WebUIScreenshotSource* screenshot_source_;
 
   BugReportData* bug_report_;
-  string16 target_tab_title_;
   std::string target_tab_url_;
 #if defined(OS_CHROMEOS)
   // Variables to track SyslogsLibrary::RequestSyslogs callback.
@@ -451,7 +395,6 @@
   char* image_data = image_data_size ?
       reinterpret_cast<char*>(&(image_.front())) : NULL;
   BugReportUtil::SendReport(profile_
-                            , UTF16ToUTF8(target_tab_title_)
                             , problem_type_
                             , page_url_
                             , description_
@@ -490,9 +433,9 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 BugReportHandler::BugReportHandler(TabContents* tab)
-    : tab_(tab)
-    , screenshot_source_(NULL)
-    , bug_report_(NULL)
+    : tab_(tab),
+      screenshot_source_(NULL),
+      bug_report_(NULL)
 #if defined(OS_CHROMEOS)
     , syslogs_handle_(0)
 #endif
@@ -512,12 +455,8 @@
   // Re-create our screenshots data source (this clobbers the last source)
   // setting the screenshot to NULL, effectively disabling the source
   // TODO(rkc): Once there is a method to 'remove' a source, change this code
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIScreenshotSource(NULL))));
+  tab_->profile()->GetChromeURLDataManager()->AddDataSource(
+      new WebUIScreenshotSource(NULL));
 
   // clobber last screenshot
   if (browser::last_screenshot_png)
@@ -527,21 +466,16 @@
 void BugReportHandler::SetupScreenshotsSource() {
   // If we don't already have a screenshot source object created, create one.
   if (!screenshot_source_)
-    screenshot_source_ = new DOMUIScreenshotSource(
+    screenshot_source_ = new WebUIScreenshotSource(
         browser::last_screenshot_png);
 
   // Add the source to the data manager.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(screenshot_source_)));
+  tab_->profile()->GetChromeURLDataManager()->AddDataSource(screenshot_source_);
 }
 
-DOMMessageHandler* BugReportHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* BugReportHandler::Attach(WebUI* web_ui) {
   SetupScreenshotsSource();
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 base::StringPiece BugReportHandler::Init() {
@@ -573,7 +507,6 @@
 
   TabContents* target_tab = browser->GetTabContentsAt(index);
   if (target_tab) {
-    target_tab_title_ = target_tab->GetTitle();
     target_tab_url_ = target_tab->GetURL().spec();
   }
 
@@ -586,19 +519,19 @@
 }
 
 void BugReportHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getDialogDefaults",
+  web_ui_->RegisterMessageCallback("getDialogDefaults",
       NewCallback(this, &BugReportHandler::HandleGetDialogDefaults));
-  dom_ui_->RegisterMessageCallback("refreshCurrentScreenshot",
+  web_ui_->RegisterMessageCallback("refreshCurrentScreenshot",
       NewCallback(this, &BugReportHandler::HandleRefreshCurrentScreenshot));
 #if defined(OS_CHROMEOS)
-  dom_ui_->RegisterMessageCallback("refreshSavedScreenshots",
+  web_ui_->RegisterMessageCallback("refreshSavedScreenshots",
       NewCallback(this, &BugReportHandler::HandleRefreshSavedScreenshots));
 #endif
-  dom_ui_->RegisterMessageCallback("sendReport",
+  web_ui_->RegisterMessageCallback("sendReport",
       NewCallback(this, &BugReportHandler::HandleSendReport));
-  dom_ui_->RegisterMessageCallback("cancel",
+  web_ui_->RegisterMessageCallback("cancel",
       NewCallback(this, &BugReportHandler::HandleCancel));
-  dom_ui_->RegisterMessageCallback("openSystemTab",
+  web_ui_->RegisterMessageCallback("openSystemTab",
       NewCallback(this, &BugReportHandler::HandleOpenSystemTab));
 }
 
@@ -629,13 +562,13 @@
   dialog_defaults.Append(new StringValue(GetUserEmail()));
 #endif
 
-  dom_ui_->CallJavascriptFunction(L"setupDialogDefaults", dialog_defaults);
+  web_ui_->CallJavascriptFunction(L"setupDialogDefaults", dialog_defaults);
 }
 
 void BugReportHandler::HandleRefreshCurrentScreenshot(const ListValue*) {
   std::string current_screenshot(kCurrentScreenshotUrl);
   StringValue screenshot(current_screenshot);
-  dom_ui_->CallJavascriptFunction(L"setupCurrentScreenshot", screenshot);
+  web_ui_->CallJavascriptFunction(L"setupCurrentScreenshot", screenshot);
 }
 
 
@@ -647,7 +580,7 @@
   ListValue screenshots_list;
   for (size_t i = 0; i < saved_screenshots.size(); ++i)
     screenshots_list.Append(new StringValue(saved_screenshots[i]));
-  dom_ui_->CallJavascriptFunction(L"setupSavedScreenshots", screenshots_list);
+  web_ui_->CallJavascriptFunction(L"setupSavedScreenshots", screenshots_list);
 }
 #endif
 
@@ -729,9 +662,8 @@
 #endif
 
   // Update the data in bug_report_ so it can be sent
-  bug_report_->UpdateData(dom_ui_->GetProfile()
+  bug_report_->UpdateData(web_ui_->GetProfile()
                           , target_tab_url_
-                          , target_tab_title_
                           , problem_type
                           , page_url
                           , description
@@ -809,10 +741,5 @@
   BugReportUIHTMLSource* html_source =
       new BugReportUIHTMLSource(handler->Init());
   // Set up the chrome://bugreport/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  tab->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/dom_ui/bug_report_ui.h b/chrome/browser/dom_ui/bug_report_ui.h
index 31d9eae..83835aa 100644
--- a/chrome/browser/dom_ui/bug_report_ui.h
+++ b/chrome/browser/dom_ui/bug_report_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,28 +6,18 @@
 #define CHROME_BROWSER_DOM_UI_BUG_REPORT_UI_H_
 
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/window.h"
 
 namespace gfx {
 class Rect;
 }  // namespace gfx
 
-class TabContents;
+class Browser;
 class NSWindow;
+class TabContents;
 
-
-// TODO(rkc): The following code is very ugly and needs to be refactored.
-// http://code.google.com/p/chromium/issues/detail?id=65119
 namespace browser {
-#if defined(TOOLKIT_VIEWS)
-void ShowHtmlBugReportView(views::Window* parent, Browser* browser);
-#elif defined(OS_LINUX)
-void ShowHtmlBugReportView(gfx::NativeWindow window, const gfx::Rect& bounds,
-                           Browser* browser);
-#elif defined(OS_MACOSX)
-void ShowHtmlBugReportView(NSWindow* window, Browser* browser);
-#endif
+void ShowHtmlBugReportView(Browser* browser);
 }  // namespace browser
 
 class BugReportUI : public HtmlDialogUI {
diff --git a/chrome/browser/dom_ui/chrome_url_data_manager.cc b/chrome/browser/dom_ui/chrome_url_data_manager.cc
index 5b69fe5..477770c 100644
--- a/chrome/browser/dom_ui/chrome_url_data_manager.cc
+++ b/chrome/browser/dom_ui/chrome_url_data_manager.cc
@@ -1,300 +1,142 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 
-#include "app/l10n_util.h"
-#include "base/file_util.h"
+#include <vector>
+
 #include "base/i18n/rtl.h"
 #include "base/message_loop.h"
-#include "base/path_service.h"
 #include "base/ref_counted_memory.h"
-#include "base/singleton.h"
 #include "base/string_util.h"
-#include "base/threading/thread.h"
+#include "base/synchronization/lock.h"
 #include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager_backend.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/profiles/profile.h"
+#include "grit/platform_locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
 #endif
-#include "chrome/browser/appcache/view_appcache_internals_job_factory.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/shared_resources_data_source.h"
-#include "chrome/browser/net/chrome_url_request_context.h"
-#include "chrome/browser/net/view_blob_internals_job_factory.h"
-#include "chrome/browser/net/view_http_cache_job_factory.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/ref_counted_util.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/url_util.h"
-#include "grit/platform_locale_settings.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_file_job.h"
-#include "net/url_request/url_request_job.h"
 
-// URLRequestChromeJob is a net::URLRequestJob that manages running
-// chrome-internal resource requests asynchronously.
-// It hands off URL requests to ChromeURLDataManager, which asynchronously
-// calls back once the data is available.
-class URLRequestChromeJob : public net::URLRequestJob {
- public:
-  explicit URLRequestChromeJob(net::URLRequest* request);
+// static
+base::Lock ChromeURLDataManager::delete_lock_;
 
-  // net::URLRequestJob implementation.
-  virtual void Start();
-  virtual void Kill();
-  virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
-  virtual bool GetMimeType(std::string* mime_type) const;
+// static
+ChromeURLDataManager::DataSources* ChromeURLDataManager::data_sources_ = NULL;
 
-  // Called by ChromeURLDataManager to notify us that the data blob is ready
-  // for us.
-  void DataAvailable(RefCountedMemory* bytes);
-
-  void SetMimeType(const std::string& mime_type) {
-    mime_type_ = mime_type;
-  }
-
- private:
-  virtual ~URLRequestChromeJob();
-
-  // Helper for Start(), to let us start asynchronously.
-  // (This pattern is shared by most net::URLRequestJob implementations.)
-  void StartAsync();
-
-  // Do the actual copy from data_ (the data we're serving) into |buf|.
-  // Separate from ReadRawData so we can handle async I/O.
-  void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read);
-
-  // The actual data we're serving.  NULL until it's been fetched.
-  scoped_refptr<RefCountedMemory> data_;
-  // The current offset into the data that we're handing off to our
-  // callers via the Read interfaces.
-  int data_offset_;
-
-  // For async reads, we keep around a pointer to the buffer that
-  // we're reading into.
-  scoped_refptr<net::IOBuffer> pending_buf_;
-  int pending_buf_size_;
-  std::string mime_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob);
-};
-
-// URLRequestChromeFileJob is a net::URLRequestJob that acts like a file:// URL
-class URLRequestChromeFileJob : public net::URLRequestFileJob {
- public:
-  URLRequestChromeFileJob(net::URLRequest* request, const FilePath& path);
-
- private:
-  virtual ~URLRequestChromeFileJob();
-
-  DISALLOW_COPY_AND_ASSIGN(URLRequestChromeFileJob);
-};
-
-void RegisterURLRequestChromeJob() {
-  FilePath inspector_dir;
-  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir)) {
-    ChromeURLDataManager::GetInstance()->AddFileSource(
-        chrome::kChromeUIDevToolsHost, inspector_dir);
-  }
-
-  SharedResourcesDataSource::Register();
-  net::URLRequest::RegisterProtocolFactory(chrome::kChromeDevToolsScheme,
-                                           &ChromeURLDataManager::Factory);
-  net::URLRequest::RegisterProtocolFactory(chrome::kChromeUIScheme,
-                                           &ChromeURLDataManager::Factory);
+// Invoked on the IO thread to do the actual adding of the DataSource.
+static void AddDataSourceOnIOThread(
+    scoped_refptr<URLRequestContextGetter> context_getter,
+    scoped_refptr<ChromeURLDataManager::DataSource> data_source) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  static_cast<ChromeURLRequestContext*>(
+      context_getter->GetURLRequestContext())->
+      GetChromeURLDataManagerBackend()->AddDataSource(data_source.get());
 }
 
-void UnregisterURLRequestChromeJob() {
-  FilePath inspector_dir;
-  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir)) {
-    ChromeURLDataManager::GetInstance()->RemoveFileSource(
-        chrome::kChromeUIDevToolsHost);
-  }
+ChromeURLDataManager::ChromeURLDataManager(Profile* profile)
+    : profile_(profile) {
+}
+
+ChromeURLDataManager::~ChromeURLDataManager() {
+}
+
+void ChromeURLDataManager::AddDataSource(DataSource* source) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      NewRunnableFunction(AddDataSourceOnIOThread,
+                          make_scoped_refptr(profile_->GetRequestContext()),
+                          make_scoped_refptr(source)));
 }
 
 // static
-void ChromeURLDataManager::URLToRequest(const GURL& url,
-                                        std::string* source_name,
-                                        std::string* path) {
-  DCHECK(url.SchemeIs(chrome::kChromeDevToolsScheme) ||
-         url.SchemeIs(chrome::kChromeUIScheme));
+void ChromeURLDataManager::DeleteDataSources() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DataSources sources;
+  {
+    base::AutoLock lock(delete_lock_);
+    if (!data_sources_)
+      return;
+    data_sources_->swap(sources);
+  }
+  for (size_t i = 0; i < sources.size(); ++i)
+    delete sources[i];
+}
 
-  if (!url.is_valid()) {
-    NOTREACHED();
+// static
+void ChromeURLDataManager::DeleteDataSource(const DataSource* data_source) {
+  // Invoked when a DataSource is no longer referenced and needs to be deleted.
+  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    // We're on the UI thread, delete right away.
+    delete data_source;
     return;
   }
 
-  // Our input looks like: chrome://source_name/extra_bits?foo .
-  // So the url's "host" is our source, and everything after the host is
-  // the path.
-  source_name->assign(url.host());
-
-  const std::string& spec = url.possibly_invalid_spec();
-  const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
-  // + 1 to skip the slash at the beginning of the path.
-  int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false) + 1;
-
-  if (offset < static_cast<int>(spec.size()))
-    path->assign(spec.substr(offset));
+  // We're not on the UI thread, add the DataSource to the list of DataSources
+  // to delete.
+  bool schedule_delete = false;
+  {
+    base::AutoLock lock(delete_lock_);
+    if (!data_sources_)
+      data_sources_ = new DataSources();
+    schedule_delete = data_sources_->empty();
+    data_sources_->push_back(data_source);
+  }
+  if (schedule_delete) {
+    // Schedule a task to delete the DataSource back on the UI thread.
+    BrowserThread::PostTask(BrowserThread::UI,
+                            FROM_HERE,
+                            NewRunnableFunction(
+                                &ChromeURLDataManager::DeleteDataSources));
+  }
 }
 
 // static
-bool ChromeURLDataManager::URLToFilePath(const GURL& url,
-                                         FilePath* file_path) {
-  // Parse the URL into a request for a source and path.
-  std::string source_name;
-  std::string relative_path;
-
-  // Remove Query and Ref from URL.
-  GURL stripped_url;
-  GURL::Replacements replacements;
-  replacements.ClearQuery();
-  replacements.ClearRef();
-  stripped_url = url.ReplaceComponents(replacements);
-
-  URLToRequest(stripped_url, &source_name, &relative_path);
-
-  FileSourceMap::const_iterator i(
-      ChromeURLDataManager::GetInstance()->file_sources_.find(source_name));
-  if (i == ChromeURLDataManager::GetInstance()->file_sources_.end())
+bool ChromeURLDataManager::IsScheduledForDeletion(
+    const DataSource* data_source) {
+  base::AutoLock lock(delete_lock_);
+  if (!data_sources_)
     return false;
-
-  // Check that |relative_path| is not an absolute path (otherwise AppendASCII()
-  // will DCHECK). The awkward use of StringType is because on some systems
-  // FilePath expects a std::string, but on others a std::wstring.
-  FilePath p(FilePath::StringType(relative_path.begin(), relative_path.end()));
-  if (p.IsAbsolute())
-    return false;
-
-  *file_path = i->second.AppendASCII(relative_path);
-
-  return true;
-}
-
-ChromeURLDataManager::ChromeURLDataManager() : next_request_id_(0) { }
-
-ChromeURLDataManager::~ChromeURLDataManager() { }
-
-// static
-ChromeURLDataManager* ChromeURLDataManager::GetInstance() {
-  return Singleton<ChromeURLDataManager>::get();
-}
-
-void ChromeURLDataManager::AddDataSource(scoped_refptr<DataSource> source) {
-  // TODO(jackson): A new data source with same name should not clobber the
-  // existing one.
-  data_sources_[source->source_name()] = source;
-}
-
-void ChromeURLDataManager::AddFileSource(const std::string& source_name,
-                                         const FilePath& file_path) {
-  DCHECK(file_sources_.count(source_name) == 0);
-  file_sources_[source_name] = file_path;
-}
-
-void ChromeURLDataManager::RemoveFileSource(const std::string& source_name) {
-  DCHECK(file_sources_.count(source_name) == 1);
-  file_sources_.erase(source_name);
-}
-
-bool ChromeURLDataManager::HasPendingJob(URLRequestChromeJob* job) const {
-  for (PendingRequestMap::const_iterator i = pending_requests_.begin();
-       i != pending_requests_.end(); ++i) {
-    if (i->second == job)
-      return true;
-  }
-
-  return false;
-}
-
-bool ChromeURLDataManager::StartRequest(const GURL& url,
-                                        URLRequestChromeJob* job) {
-  // Parse the URL into a request for a source and path.
-  std::string source_name;
-  std::string path;
-  URLToRequest(url, &source_name, &path);
-
-  // Look up the data source for the request.
-  DataSourceMap::iterator i = data_sources_.find(source_name);
-  if (i == data_sources_.end())
-    return false;
-  DataSource* source = i->second;
-
-  // Save this request so we know where to send the data.
-  RequestID request_id = next_request_id_++;
-  pending_requests_.insert(std::make_pair(request_id, job));
-
-  // TODO(eroman): would be nicer if the mimetype were set at the same time
-  // as the data blob. For now do it here, since NotifyHeadersComplete() is
-  // going to get called once we return.
-  job->SetMimeType(source->GetMimeType(path));
-
-  ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>(
-      job->request()->context());
-
-  // Forward along the request to the data source.
-  MessageLoop* target_message_loop = source->MessageLoopForRequestPath(path);
-  if (!target_message_loop) {
-    // The DataSource is agnostic to which thread StartDataRequest is called
-    // on for this path.  Call directly into it from this thread, the IO
-    // thread.
-    source->StartDataRequest(path, context->is_off_the_record(), request_id);
-  } else {
-    // The DataSource wants StartDataRequest to be called on a specific thread,
-    // usually the UI thread, for this path.
-    target_message_loop->PostTask(FROM_HERE,
-        NewRunnableMethod(source, &DataSource::StartDataRequest,
-                          path, context->is_off_the_record(), request_id));
-  }
-  return true;
-}
-
-void ChromeURLDataManager::RemoveRequest(URLRequestChromeJob* job) {
-  // Remove the request from our list of pending requests.
-  // If/when the source sends the data that was requested, the data will just
-  // be thrown away.
-  for (PendingRequestMap::iterator i = pending_requests_.begin();
-       i != pending_requests_.end(); ++i) {
-    if (i->second == job) {
-      pending_requests_.erase(i);
-      return;
-    }
-  }
-}
-
-void ChromeURLDataManager::DataAvailable(
-    RequestID request_id,
-    scoped_refptr<RefCountedMemory> bytes) {
-  // Forward this data on to the pending net::URLRequest, if it exists.
-  PendingRequestMap::iterator i = pending_requests_.find(request_id);
-  if (i != pending_requests_.end()) {
-    // We acquire a reference to the job so that it doesn't disappear under the
-    // feet of any method invoked here (we could trigger a callback).
-    scoped_refptr<URLRequestChromeJob> job(i->second);
-    pending_requests_.erase(i);
-    job->DataAvailable(bytes);
-  }
+  return std::find(data_sources_->begin(), data_sources_->end(), data_source) !=
+      data_sources_->end();
 }
 
 ChromeURLDataManager::DataSource::DataSource(const std::string& source_name,
                                              MessageLoop* message_loop)
-    : source_name_(source_name), message_loop_(message_loop) {
+    : source_name_(source_name),
+      message_loop_(message_loop),
+      backend_(NULL) {
 }
 
 ChromeURLDataManager::DataSource::~DataSource() {
 }
 
-void ChromeURLDataManager::DataSource::SendResponse(
-    RequestID request_id,
-    RefCountedMemory* bytes) {
+void ChromeURLDataManager::DataSource::SendResponse(int request_id,
+                                                    RefCountedMemory* bytes) {
+  if (IsScheduledForDeletion(this)) {
+    // We're scheduled for deletion. Servicing the request would result in
+    // this->AddRef being invoked, even though the ref count is 0 and 'this' is
+    // about to be deleted. If the AddRef were allowed through, when 'this' is
+    // released it would be deleted again.
+    //
+    // This scenario occurs with DataSources that make history requests. Such
+    // DataSources do a history query in |StartDataRequest| and the request is
+    // live until the object is deleted (history requests don't up the ref
+    // count). This means it's entirely possible for the DataSource to invoke
+    // |SendResponse| between the time when there are no more refs and the time
+    // when the object is deleted.
+    return;
+  }
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::DataAvailable,
-                        request_id, scoped_refptr<RefCountedMemory>(bytes)));
+      NewRunnableMethod(this, &DataSource::SendResponseOnIOThread,
+                        request_id, make_scoped_refptr(bytes)));
 }
 
 MessageLoop* ChromeURLDataManager::DataSource::MessageLoopForRequestPath(
@@ -322,119 +164,10 @@
       base::i18n::IsRTL() ? "rtl" : "ltr");
 }
 
-net::URLRequestJob* ChromeURLDataManager::Factory(net::URLRequest* request,
-                                                  const std::string& scheme) {
-  // Try first with a file handler
-  FilePath path;
-  if (ChromeURLDataManager::URLToFilePath(request->url(), &path))
-    return new URLRequestChromeFileJob(request, path);
-
-  // Next check for chrome://view-http-cache/*, which uses its own job type.
-  if (ViewHttpCacheJobFactory::IsSupportedURL(request->url()))
-    return ViewHttpCacheJobFactory::CreateJobForRequest(request);
-
-  // Next check for chrome://appcache-internals/, which uses its own job type.
-  if (ViewAppCacheInternalsJobFactory::IsSupportedURL(request->url()))
-    return ViewAppCacheInternalsJobFactory::CreateJobForRequest(request);
-
-  // Next check for chrome://blob-internals/, which uses its own job type.
-  if (ViewBlobInternalsJobFactory::IsSupportedURL(request->url()))
-    return ViewBlobInternalsJobFactory::CreateJobForRequest(request);
-
-  // Fall back to using a custom handler
-  return new URLRequestChromeJob(request);
+void ChromeURLDataManager::DataSource::SendResponseOnIOThread(
+    int request_id,
+    scoped_refptr<RefCountedMemory> bytes) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (backend_)
+    backend_->DataAvailable(request_id, bytes);
 }
-
-URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request)
-    : net::URLRequestJob(request),
-      data_offset_(0),
-      pending_buf_size_(0) {
-}
-
-URLRequestChromeJob::~URLRequestChromeJob() {
-  CHECK(!ChromeURLDataManager::GetInstance()->HasPendingJob(this));
-}
-
-void URLRequestChromeJob::Start() {
-  // Start reading asynchronously so that all error reporting and data
-  // callbacks happen as they would for network requests.
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      this, &URLRequestChromeJob::StartAsync));
-}
-
-void URLRequestChromeJob::Kill() {
-  ChromeURLDataManager::GetInstance()->RemoveRequest(this);
-}
-
-bool URLRequestChromeJob::GetMimeType(std::string* mime_type) const {
-  *mime_type = mime_type_;
-  return !mime_type_.empty();
-}
-
-void URLRequestChromeJob::DataAvailable(RefCountedMemory* bytes) {
-  if (bytes) {
-    // The request completed, and we have all the data.
-    // Clear any IO pending status.
-    SetStatus(URLRequestStatus());
-
-    data_ = bytes;
-    int bytes_read;
-    if (pending_buf_.get()) {
-      CHECK(pending_buf_->data());
-      CompleteRead(pending_buf_, pending_buf_size_, &bytes_read);
-      pending_buf_ = NULL;
-      NotifyReadComplete(bytes_read);
-    }
-  } else {
-    // The request failed.
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
-  }
-}
-
-bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size,
-                                      int* bytes_read) {
-  if (!data_.get()) {
-    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-    DCHECK(!pending_buf_.get());
-    CHECK(buf->data());
-    pending_buf_ = buf;
-    pending_buf_size_ = buf_size;
-    return false;  // Tell the caller we're still waiting for data.
-  }
-
-  // Otherwise, the data is available.
-  CompleteRead(buf, buf_size, bytes_read);
-  return true;
-}
-
-void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size,
-                                       int* bytes_read) {
-  int remaining = static_cast<int>(data_->size()) - data_offset_;
-  if (buf_size > remaining)
-    buf_size = remaining;
-  if (buf_size > 0) {
-    memcpy(buf->data(), data_->front() + data_offset_, buf_size);
-    data_offset_ += buf_size;
-  }
-  *bytes_read = buf_size;
-}
-
-void URLRequestChromeJob::StartAsync() {
-  if (!request_)
-    return;
-
-  if (ChromeURLDataManager::GetInstance()->StartRequest(request_->url(),
-                                                        this)) {
-    NotifyHeadersComplete();
-  } else {
-    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
-                                      net::ERR_INVALID_URL));
-  }
-}
-
-URLRequestChromeFileJob::URLRequestChromeFileJob(net::URLRequest* request,
-                                                 const FilePath& path)
-    : net::URLRequestFileJob(request, path) {
-}
-
-URLRequestChromeFileJob::~URLRequestChromeFileJob() { }
diff --git a/chrome/browser/dom_ui/chrome_url_data_manager.h b/chrome/browser/dom_ui/chrome_url_data_manager.h
index 709cdcb..86eb305 100644
--- a/chrome/browser/dom_ui/chrome_url_data_manager.h
+++ b/chrome/browser/dom_ui/chrome_url_data_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,49 +9,60 @@
 #include <map>
 #include <string>
 
-#include "base/singleton.h"
 #include "base/task.h"
 #include "base/ref_counted.h"
+#include "chrome/browser/browser_thread.h"
 
+class ChromeURLDataManagerBackend;
 class DictionaryValue;
 class FilePath;
-class GURL;
 class MessageLoop;
+class Profile;
 class RefCountedMemory;
-class URLRequestChromeJob;
-
-namespace net {
-class URLRequest;
-class URLRequestJob;
-}  // namespace net
 
 // To serve dynamic data off of chrome: URLs, implement the
 // ChromeURLDataManager::DataSource interface and register your handler
-// with AddDataSource.
-
-// ChromeURLDataManager lives on the IO thread, so any interfacing with
-// it from the UI thread needs to go through an InvokeLater.
+// with AddDataSource. DataSources must be added on the UI thread (they are also
+// deleted on the UI thread). Internally the DataSources are maintained by
+// ChromeURLDataManagerBackend, see it for details.
 class ChromeURLDataManager {
  public:
-  // Returns the singleton instance.
-  static ChromeURLDataManager* GetInstance();
+  class DataSource;
 
-  typedef int RequestID;
+  // Trait used to handle deleting a DataSource. Deletion happens on the UI
+  // thread.
+  //
+  // Implementation note: the normal shutdown sequence is for the UI loop to
+  // stop pumping events then the IO loop and thread are stopped. When the
+  // DataSources are no longer referenced (which happens when IO thread stops)
+  // they get added to the UI message loop for deletion. But because the UI loop
+  // has stopped by the time this happens the DataSources would be leaked.
+  //
+  // To make sure DataSources are properly deleted ChromeURLDataManager manages
+  // deletion of the DataSources.  When a DataSource is no longer referenced it
+  // is added to |data_sources_| and a task is posted to the UI thread to handle
+  // the actual deletion. During shutdown |DeleteDataSources| is invoked so that
+  // all pending DataSources are properly deleted.
+  struct DeleteDataSource {
+    static void Destruct(const DataSource* data_source) {
+      ChromeURLDataManager::DeleteDataSource(data_source);
+    }
+  };
 
   // A DataSource is an object that can answer requests for data
   // asynchronously. DataSources are collectively owned with refcounting smart
   // pointers and should never be deleted on the IO thread, since their calls
   // are handled almost always on the UI thread and there's a possibility of a
-  // data race.
+  // data race.  The |DeleteOnUIThread| trait is used to enforce this.
   //
   // An implementation of DataSource should handle calls to
   // StartDataRequest() by starting its (implementation-specific) asynchronous
-  // request for the data, then call SendResponse() to notify
-  class DataSource : public base::RefCountedThreadSafe<DataSource> {
+  // request for the data, then call SendResponse() to notify.
+  class DataSource : public base::RefCountedThreadSafe<
+      DataSource, DeleteDataSource> {
    public:
     // See source_name_ and message_loop_ below for docs on these parameters.
-    DataSource(const std::string& source_name,
-               MessageLoop* message_loop);
+    DataSource(const std::string& source_name, MessageLoop* message_loop);
 
     // Sent by the DataManager to request data at |path|.  The source should
     // call SendResponse() when the data is available or if the request could
@@ -86,11 +97,18 @@
     static void SetFontAndTextDirection(DictionaryValue* localized_strings);
 
    protected:
-    friend class base::RefCountedThreadSafe<DataSource>;
-
     virtual ~DataSource();
 
    private:
+    friend class ChromeURLDataManagerBackend;
+    friend class ChromeURLDataManager;
+    friend class DeleteTask<DataSource>;
+
+    // SendResponse invokes this on the IO thread. Notifies the backend to
+    // handle the actual work of sending the data.
+    virtual void SendResponseOnIOThread(int request_id,
+                                        scoped_refptr<RefCountedMemory> bytes);
+
     // The name of this source.
     // E.g., for favicons, this could be "favicon", which results in paths for
     // specific resources like "favicon/34" getting sent to this source.
@@ -99,86 +117,57 @@
     // The MessageLoop for the thread where this DataSource lives.
     // Used to send messages to the DataSource.
     MessageLoop* message_loop_;
+
+    // This field is set and maintained by ChromeURLDataManagerBackend. It is
+    // set when the DataSource is added, and unset if the DataSource is removed.
+    // A DataSource can be removed in two ways: the ChromeURLDataManagerBackend
+    // is deleted, or another DataSource is registered with the same
+    // name. backend_ should only be accessed on the IO thread.
+    // This reference can't be via a scoped_refptr else there would be a cycle
+    // between the backend and data source.
+    ChromeURLDataManagerBackend* backend_;
   };
 
-  // Add a DataSource to the collection of data sources.
-  // Because we don't track users of a given path, we can't know when it's
-  // safe to remove them, so the added source effectively leaks.
-  // This could be improved in the future but currently the users of this
-  // interface are conceptually permanent registration anyway.
-  // Adding a second DataSource with the same name clobbers the first.
-  // NOTE: Calling this from threads other the IO thread must be done via
-  // InvokeLater.
-  void AddDataSource(scoped_refptr<DataSource> source);
-
-  // Add/remove a path from the collection of file sources.
-  // A file source acts like a file:// URL to the specified path.
-  // Calling this from threads other the IO thread must be done via
-  // InvokeLater.
-  void AddFileSource(const std::string& source_name, const FilePath& path);
-  void RemoveFileSource(const std::string& source_name);
-
-  static net::URLRequestJob* Factory(net::URLRequest* request,
-                                     const std::string& scheme);
-
- private:
-  friend class URLRequestChromeJob;
-  friend struct DefaultSingletonTraits<ChromeURLDataManager>;
-
-  ChromeURLDataManager();
+  explicit ChromeURLDataManager(Profile* profile);
   ~ChromeURLDataManager();
 
-  // Parse a URL into the components used to resolve its request.
-  static void URLToRequest(const GURL& url,
-                           std::string* source,
-                           std::string* path);
+  // Adds a DataSource to the collection of data sources. This *must* be invoked
+  // on the UI thread.
+  //
+  // If |AddDataSource| is called more than once for a particular name it will
+  // release the old |DataSource|, most likely resulting in it getting deleted
+  // as there are no other references to it. |DataSource| uses the
+  // |DeleteOnUIThread| trait to insure that the destructor is called on the UI
+  // thread. This is necessary as some |DataSource|s notably |FileIconSource|
+  // and |WebUIFavIconSource|, have members that will DCHECK if they are not
+  // destructed in the same thread as they are constructed (the UI thread).
+  void AddDataSource(DataSource* source);
 
-  // Translate a chrome resource URL into a local file path if there is one.
-  // Returns false if there is no file handler for this URL
-  static bool URLToFilePath(const GURL& url, FilePath* file_path);
+  // Deletes any data sources no longer referenced. This is normally invoked
+  // for you, but can be invoked to force deletion (such as during shutdown).
+  static void DeleteDataSources();
 
-  // Called by the job when it's starting up.
-  // Returns false if |url| is not a URL managed by this object.
-  bool StartRequest(const GURL& url, URLRequestChromeJob* job);
-  // Remove a request from the list of pending requests.
-  void RemoveRequest(URLRequestChromeJob* job);
+ private:
+  typedef std::vector<const ChromeURLDataManager::DataSource*> DataSources;
 
-  // Returns true if the job exists in |pending_requests_|. False otherwise.
-  // Called by ~URLRequestChromeJob to verify that |pending_requests_| is kept
-  // up to date.
-  bool HasPendingJob(URLRequestChromeJob* job) const;
+  // If invoked on the UI thread the DataSource is deleted immediatlye,
+  // otherwise it is added to |data_sources_| and a task is scheduled to handle
+  // deletion on the UI thread. See note abouve DeleteDataSource for more info.
+  static void DeleteDataSource(const DataSource* data_source);
 
-  // Sent by Request::SendResponse.
-  void DataAvailable(RequestID request_id,
-                     scoped_refptr<RefCountedMemory> bytes);
+  // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource|
+  // was invoked).
+  static bool IsScheduledForDeletion(const DataSource* data_source);
 
-  // File sources of data, keyed by source name (e.g. "inspector").
-  typedef std::map<std::string, FilePath> FileSourceMap;
-  FileSourceMap file_sources_;
+  Profile* profile_;
 
-  // Custom sources of data, keyed by source path (e.g. "favicon").
-  typedef std::map<std::string, scoped_refptr<DataSource> > DataSourceMap;
-  DataSourceMap data_sources_;
+  // Lock used when accessing |data_sources_|.
+  static base::Lock delete_lock_;
 
-  // All pending URLRequestChromeJobs, keyed by ID of the request.
-  // URLRequestChromeJob calls into this object when it's constructed and
-  // destructed to ensure that the pointers in this map remain valid.
-  typedef std::map<RequestID, URLRequestChromeJob*> PendingRequestMap;
-  PendingRequestMap pending_requests_;
+  // |data_sources_| that are no longer referenced and scheduled for deletion.
+  static DataSources* data_sources_;
 
-  // The ID we'll use for the next request we receive.
-  RequestID next_request_id_;
+  DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager);
 };
 
-// Since we have a single global ChromeURLDataManager, we don't need to
-// grab a reference to it when creating Tasks involving it.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(ChromeURLDataManager);
-
-// Register our special URL handler under our special URL scheme.
-// Must be done once at startup.
-void RegisterURLRequestChromeJob();
-
-// Undoes the registration done by RegisterURLRequestChromeJob.
-void UnregisterURLRequestChromeJob();
-
 #endif  // CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_
diff --git a/chrome/browser/dom_ui/chrome_url_data_manager_backend.cc b/chrome/browser/dom_ui/chrome_url_data_manager_backend.cc
new file mode 100644
index 0000000..0048828
--- /dev/null
+++ b/chrome/browser/dom_ui/chrome_url_data_manager_backend.cc
@@ -0,0 +1,393 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/chrome_url_data_manager_backend.h"
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/ref_counted_memory.h"
+#include "base/string_util.h"
+#include "chrome/browser/appcache/view_appcache_internals_job_factory.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/shared_resources_data_source.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/net/view_blob_internals_job_factory.h"
+#include "chrome/browser/net/view_http_cache_job_factory.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/url_util.h"
+#include "grit/platform_locale_settings.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_file_job.h"
+#include "net/url_request/url_request_job.h"
+
+static ChromeURLDataManagerBackend* GetBackend(net::URLRequest* request) {
+  return static_cast<ChromeURLRequestContext*>(request->context())->
+      GetChromeURLDataManagerBackend();
+}
+
+// URLRequestChromeJob is a net::URLRequestJob that manages running
+// chrome-internal resource requests asynchronously.
+// It hands off URL requests to ChromeURLDataManager, which asynchronously
+// calls back once the data is available.
+class URLRequestChromeJob : public net::URLRequestJob {
+ public:
+  explicit URLRequestChromeJob(net::URLRequest* request);
+
+  // net::URLRequestJob implementation.
+  virtual void Start();
+  virtual void Kill();
+  virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
+  virtual bool GetMimeType(std::string* mime_type) const;
+
+  // Called by ChromeURLDataManager to notify us that the data blob is ready
+  // for us.
+  void DataAvailable(RefCountedMemory* bytes);
+
+  void SetMimeType(const std::string& mime_type) {
+    mime_type_ = mime_type;
+  }
+
+ private:
+  virtual ~URLRequestChromeJob();
+
+  // Helper for Start(), to let us start asynchronously.
+  // (This pattern is shared by most net::URLRequestJob implementations.)
+  void StartAsync();
+
+  // Do the actual copy from data_ (the data we're serving) into |buf|.
+  // Separate from ReadRawData so we can handle async I/O.
+  void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read);
+
+  // The actual data we're serving.  NULL until it's been fetched.
+  scoped_refptr<RefCountedMemory> data_;
+  // The current offset into the data that we're handing off to our
+  // callers via the Read interfaces.
+  int data_offset_;
+
+  // For async reads, we keep around a pointer to the buffer that
+  // we're reading into.
+  scoped_refptr<net::IOBuffer> pending_buf_;
+  int pending_buf_size_;
+  std::string mime_type_;
+
+  // The backend is owned by ChromeURLRequestContext and always outlives us.
+  ChromeURLDataManagerBackend* backend_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob);
+};
+
+// URLRequestChromeFileJob is a net::URLRequestJob that acts like a file:// URL
+class URLRequestChromeFileJob : public net::URLRequestFileJob {
+ public:
+  URLRequestChromeFileJob(net::URLRequest* request, const FilePath& path);
+
+ private:
+  virtual ~URLRequestChromeFileJob();
+
+  DISALLOW_COPY_AND_ASSIGN(URLRequestChromeFileJob);
+};
+
+void ChromeURLDataManagerBackend::URLToRequest(const GURL& url,
+                                               std::string* source_name,
+                                               std::string* path) {
+  DCHECK(url.SchemeIs(chrome::kChromeDevToolsScheme) ||
+         url.SchemeIs(chrome::kChromeUIScheme));
+
+  if (!url.is_valid()) {
+    NOTREACHED();
+    return;
+  }
+
+  // Our input looks like: chrome://source_name/extra_bits?foo .
+  // So the url's "host" is our source, and everything after the host is
+  // the path.
+  source_name->assign(url.host());
+
+  const std::string& spec = url.possibly_invalid_spec();
+  const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
+  // + 1 to skip the slash at the beginning of the path.
+  int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false) + 1;
+
+  if (offset < static_cast<int>(spec.size()))
+    path->assign(spec.substr(offset));
+}
+
+bool ChromeURLDataManagerBackend::URLToFilePath(const GURL& url,
+                                                FilePath* file_path) {
+  // Parse the URL into a request for a source and path.
+  std::string source_name;
+  std::string relative_path;
+
+  // Remove Query and Ref from URL.
+  GURL stripped_url;
+  GURL::Replacements replacements;
+  replacements.ClearQuery();
+  replacements.ClearRef();
+  stripped_url = url.ReplaceComponents(replacements);
+
+  URLToRequest(stripped_url, &source_name, &relative_path);
+
+  FileSourceMap::const_iterator i(file_sources_.find(source_name));
+  if (i == file_sources_.end())
+    return false;
+
+  // Check that |relative_path| is not an absolute path (otherwise AppendASCII()
+  // will DCHECK). The awkward use of StringType is because on some systems
+  // FilePath expects a std::string, but on others a std::wstring.
+  FilePath p(FilePath::StringType(relative_path.begin(), relative_path.end()));
+  if (p.IsAbsolute())
+    return false;
+
+  *file_path = i->second.AppendASCII(relative_path);
+
+  return true;
+}
+
+ChromeURLDataManagerBackend::ChromeURLDataManagerBackend()
+    : next_request_id_(0) {
+  FilePath inspector_dir;
+  if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
+    AddFileSource(chrome::kChromeUIDevToolsHost, inspector_dir);
+  AddDataSource(new SharedResourcesDataSource());
+}
+
+ChromeURLDataManagerBackend::~ChromeURLDataManagerBackend() {
+  for (DataSourceMap::iterator i = data_sources_.begin();
+       i != data_sources_.end(); ++i) {
+    i->second->backend_ = NULL;
+  }
+  data_sources_.clear();
+}
+
+// static
+void ChromeURLDataManagerBackend::Register() {
+  net::URLRequest::RegisterProtocolFactory(
+      chrome::kChromeDevToolsScheme,
+      &ChromeURLDataManagerBackend::Factory);
+  net::URLRequest::RegisterProtocolFactory(
+      chrome::kChromeUIScheme,
+      &ChromeURLDataManagerBackend::Factory);
+}
+
+void ChromeURLDataManagerBackend::AddDataSource(
+    ChromeURLDataManager::DataSource* source) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DataSourceMap::iterator i = data_sources_.find(source->source_name());
+  if (i != data_sources_.end())
+    i->second->backend_ = NULL;
+  data_sources_[source->source_name()] = source;
+  source->backend_ = this;
+}
+
+void ChromeURLDataManagerBackend::AddFileSource(const std::string& source_name,
+                                                const FilePath& file_path) {
+  DCHECK(file_sources_.count(source_name) == 0);
+  file_sources_[source_name] = file_path;
+}
+
+bool ChromeURLDataManagerBackend::HasPendingJob(
+    URLRequestChromeJob* job) const {
+  for (PendingRequestMap::const_iterator i = pending_requests_.begin();
+       i != pending_requests_.end(); ++i) {
+    if (i->second == job)
+      return true;
+  }
+  return false;
+}
+
+bool ChromeURLDataManagerBackend::StartRequest(const GURL& url,
+                                               URLRequestChromeJob* job) {
+  // Parse the URL into a request for a source and path.
+  std::string source_name;
+  std::string path;
+  URLToRequest(url, &source_name, &path);
+
+  // Look up the data source for the request.
+  DataSourceMap::iterator i = data_sources_.find(source_name);
+  if (i == data_sources_.end())
+    return false;
+
+  ChromeURLDataManager::DataSource* source = i->second;
+
+  // Save this request so we know where to send the data.
+  RequestID request_id = next_request_id_++;
+  pending_requests_.insert(std::make_pair(request_id, job));
+
+  // TODO(eroman): would be nicer if the mimetype were set at the same time
+  // as the data blob. For now do it here, since NotifyHeadersComplete() is
+  // going to get called once we return.
+  job->SetMimeType(source->GetMimeType(path));
+
+  ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>(
+      job->request()->context());
+
+  // Forward along the request to the data source.
+  MessageLoop* target_message_loop = source->MessageLoopForRequestPath(path);
+  if (!target_message_loop) {
+    // The DataSource is agnostic to which thread StartDataRequest is called
+    // on for this path.  Call directly into it from this thread, the IO
+    // thread.
+    source->StartDataRequest(path, context->is_off_the_record(), request_id);
+  } else {
+    // The DataSource wants StartDataRequest to be called on a specific thread,
+    // usually the UI thread, for this path.
+    target_message_loop->PostTask(
+        FROM_HERE,
+        NewRunnableMethod(source,
+                          &ChromeURLDataManager::DataSource::StartDataRequest,
+                          path, context->is_off_the_record(), request_id));
+  }
+  return true;
+}
+
+void ChromeURLDataManagerBackend::RemoveRequest(URLRequestChromeJob* job) {
+  // Remove the request from our list of pending requests.
+  // If/when the source sends the data that was requested, the data will just
+  // be thrown away.
+  for (PendingRequestMap::iterator i = pending_requests_.begin();
+       i != pending_requests_.end(); ++i) {
+    if (i->second == job) {
+      pending_requests_.erase(i);
+      return;
+    }
+  }
+}
+
+void ChromeURLDataManagerBackend::DataAvailable(RequestID request_id,
+                                                RefCountedMemory* bytes) {
+  // Forward this data on to the pending net::URLRequest, if it exists.
+  PendingRequestMap::iterator i = pending_requests_.find(request_id);
+  if (i != pending_requests_.end()) {
+    // We acquire a reference to the job so that it doesn't disappear under the
+    // feet of any method invoked here (we could trigger a callback).
+    scoped_refptr<URLRequestChromeJob> job(i->second);
+    pending_requests_.erase(i);
+    job->DataAvailable(bytes);
+  }
+}
+
+// static
+net::URLRequestJob* ChromeURLDataManagerBackend::Factory(
+    net::URLRequest* request,
+    const std::string& scheme) {
+  // Try first with a file handler
+  FilePath path;
+  ChromeURLDataManagerBackend* backend = GetBackend(request);
+  if (backend->URLToFilePath(request->url(), &path))
+    return new URLRequestChromeFileJob(request, path);
+
+  // Next check for chrome://view-http-cache/*, which uses its own job type.
+  if (ViewHttpCacheJobFactory::IsSupportedURL(request->url()))
+    return ViewHttpCacheJobFactory::CreateJobForRequest(request);
+
+  // Next check for chrome://appcache-internals/, which uses its own job type.
+  if (ViewAppCacheInternalsJobFactory::IsSupportedURL(request->url()))
+    return ViewAppCacheInternalsJobFactory::CreateJobForRequest(request);
+
+  // Next check for chrome://blob-internals/, which uses its own job type.
+  if (ViewBlobInternalsJobFactory::IsSupportedURL(request->url()))
+    return ViewBlobInternalsJobFactory::CreateJobForRequest(request);
+
+  // Fall back to using a custom handler
+  return new URLRequestChromeJob(request);
+}
+
+URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request)
+    : net::URLRequestJob(request),
+      data_offset_(0),
+      pending_buf_size_(0),
+      backend_(GetBackend(request)) {
+}
+
+URLRequestChromeJob::~URLRequestChromeJob() {
+  CHECK(!backend_->HasPendingJob(this));
+}
+
+void URLRequestChromeJob::Start() {
+  // Start reading asynchronously so that all error reporting and data
+  // callbacks happen as they would for network requests.
+  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &URLRequestChromeJob::StartAsync));
+}
+
+void URLRequestChromeJob::Kill() {
+  backend_->RemoveRequest(this);
+}
+
+bool URLRequestChromeJob::GetMimeType(std::string* mime_type) const {
+  *mime_type = mime_type_;
+  return !mime_type_.empty();
+}
+
+void URLRequestChromeJob::DataAvailable(RefCountedMemory* bytes) {
+  if (bytes) {
+    // The request completed, and we have all the data.
+    // Clear any IO pending status.
+    SetStatus(net::URLRequestStatus());
+
+    data_ = bytes;
+    int bytes_read;
+    if (pending_buf_.get()) {
+      CHECK(pending_buf_->data());
+      CompleteRead(pending_buf_, pending_buf_size_, &bytes_read);
+      pending_buf_ = NULL;
+      NotifyReadComplete(bytes_read);
+    }
+  } else {
+    // The request failed.
+    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                     net::ERR_FAILED));
+  }
+}
+
+bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size,
+                                      int* bytes_read) {
+  if (!data_.get()) {
+    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
+    DCHECK(!pending_buf_.get());
+    CHECK(buf->data());
+    pending_buf_ = buf;
+    pending_buf_size_ = buf_size;
+    return false;  // Tell the caller we're still waiting for data.
+  }
+
+  // Otherwise, the data is available.
+  CompleteRead(buf, buf_size, bytes_read);
+  return true;
+}
+
+void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size,
+                                       int* bytes_read) {
+  int remaining = static_cast<int>(data_->size()) - data_offset_;
+  if (buf_size > remaining)
+    buf_size = remaining;
+  if (buf_size > 0) {
+    memcpy(buf->data(), data_->front() + data_offset_, buf_size);
+    data_offset_ += buf_size;
+  }
+  *bytes_read = buf_size;
+}
+
+void URLRequestChromeJob::StartAsync() {
+  if (!request_)
+    return;
+
+  if (backend_->StartRequest(request_->url(), this)) {
+    NotifyHeadersComplete();
+  } else {
+    NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                           net::ERR_INVALID_URL));
+  }
+}
+
+URLRequestChromeFileJob::URLRequestChromeFileJob(net::URLRequest* request,
+                                                 const FilePath& path)
+    : net::URLRequestFileJob(request, path) {
+}
+
+URLRequestChromeFileJob::~URLRequestChromeFileJob() {}
diff --git a/chrome/browser/dom_ui/chrome_url_data_manager_backend.h b/chrome/browser/dom_ui/chrome_url_data_manager_backend.h
new file mode 100644
index 0000000..fe900bc
--- /dev/null
+++ b/chrome/browser/dom_ui/chrome_url_data_manager_backend.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_BACKEND_H_
+#define CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_BACKEND_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+class FilePath;
+class GURL;
+class URLRequestChromeJob;
+
+namespace net {
+class URLRequest;
+class URLRequestJob;
+}
+
+// ChromeURLDataManagerBackend is used internally by ChromeURLDataManager on the
+// IO thread. In most cases you can use the API in ChromeURLDataManager and
+// ignore this class. ChromeURLDataManagerBackend is owned by
+// ChromeURLRequestContext.
+class ChromeURLDataManagerBackend {
+ public:
+  typedef int RequestID;
+
+  ChromeURLDataManagerBackend();
+  ~ChromeURLDataManagerBackend();
+
+  // Invoked to register the protocol factories.
+  static void Register();
+
+  // Adds a DataSource to the collection of data sources.
+  void AddDataSource(ChromeURLDataManager::DataSource* source);
+
+  // Add/remove a path from the collection of file sources.
+  // A file source acts like a file:// URL to the specified path.
+  // Calling this from threads other the IO thread must be done via
+  // InvokeLater.
+  void AddFileSource(const std::string& source_name, const FilePath& path);
+
+  // DataSource invokes this. Sends the data to the URLRequest.
+  void DataAvailable(RequestID request_id, RefCountedMemory* bytes);
+
+  static net::URLRequestJob* Factory(net::URLRequest* request,
+                                     const std::string& scheme);
+
+ private:
+  friend class URLRequestChromeJob;
+
+  typedef std::map<std::string,
+      scoped_refptr<ChromeURLDataManager::DataSource> > DataSourceMap;
+  typedef std::map<std::string, FilePath> FileSourceMap;
+  typedef std::map<RequestID, URLRequestChromeJob*> PendingRequestMap;
+
+  // Parse a URL into the components used to resolve its request.
+  void URLToRequest(const GURL& url, std::string* source, std::string* path);
+
+  // Translate a chrome resource URL into a local file path if there is one.
+  // Returns false if there is no file handler for this URL
+  bool URLToFilePath(const GURL& url, FilePath* file_path);
+
+  // Called by the job when it's starting up.
+  // Returns false if |url| is not a URL managed by this object.
+  bool StartRequest(const GURL& url, URLRequestChromeJob* job);
+
+  // Remove a request from the list of pending requests.
+  void RemoveRequest(URLRequestChromeJob* job);
+
+  // Returns true if the job exists in |pending_requests_|. False otherwise.
+  // Called by ~URLRequestChromeJob to verify that |pending_requests_| is kept
+  // up to date.
+  bool HasPendingJob(URLRequestChromeJob* job) const;
+
+  // File sources of data, keyed by source name (e.g. "inspector").
+  FileSourceMap file_sources_;
+
+  // Custom sources of data, keyed by source path (e.g. "favicon").
+  DataSourceMap data_sources_;
+
+  // All pending URLRequestChromeJobs, keyed by ID of the request.
+  // URLRequestChromeJob calls into this object when it's constructed and
+  // destructed to ensure that the pointers in this map remain valid.
+  PendingRequestMap pending_requests_;
+
+  // The ID we'll use for the next request we receive.
+  RequestID next_request_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManagerBackend);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_BACKEND_H_
diff --git a/chrome/browser/dom_ui/conflicts_ui.cc b/chrome/browser/dom_ui/conflicts_ui.cc
index 9f4df7d..455b446 100644
--- a/chrome/browser/dom_ui/conflicts_ui.cc
+++ b/chrome/browser/dom_ui/conflicts_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,14 +8,13 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/enumerate_modules_model_win.h"
 #include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/notification_observer.h"
@@ -26,6 +25,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -109,13 +110,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // The handler for JavaScript messages for the about:flags page.
-class ConflictsDOMHandler : public DOMMessageHandler,
+class ConflictsDOMHandler : public WebUIMessageHandler,
                             public NotificationObserver {
  public:
   ConflictsDOMHandler() {}
   virtual ~ConflictsDOMHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callback for the "requestModuleList" message.
@@ -134,7 +135,7 @@
 };
 
 void ConflictsDOMHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("requestModuleList",
+  web_ui_->RegisterMessageCallback("requestModuleList",
       NewCallback(this, &ConflictsDOMHandler::HandleRequestModuleList));
 }
 
@@ -168,7 +169,7 @@
   }
   results.SetString("modulesTableTitle", table_title);
 
-  dom_ui_->CallJavascriptFunction(L"returnModuleList", results);
+  web_ui_->CallJavascriptFunction(L"returnModuleList", results);
 }
 
 void ConflictsDOMHandler::Observe(NotificationType type,
@@ -193,7 +194,7 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-ConflictsUI::ConflictsUI(TabContents* contents) : DOMUI(contents) {
+ConflictsUI::ConflictsUI(TabContents* contents) : WebUI(contents) {
   UserMetrics::RecordAction(
       UserMetricsAction("ViewAboutConflicts"), contents->profile());
 
@@ -202,11 +203,7 @@
   ConflictsUIHTMLSource* html_source = new ConflictsUIHTMLSource();
 
   // Set up the about:conflicts source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/conflicts_ui.h b/chrome/browser/dom_ui/conflicts_ui.h
index d683a9c..48ea0fd 100644
--- a/chrome/browser/dom_ui/conflicts_ui.h
+++ b/chrome/browser/dom_ui/conflicts_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_DOM_UI_CONFLICTS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 #if defined(OS_WIN)
 
 class RefCountedMemory;
 
-// The DOM UI handler for about:conflicts.
-class ConflictsUI : public DOMUI {
+// The Web UI handler for about:conflicts.
+class ConflictsUI : public WebUI {
  public:
   explicit ConflictsUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/constrained_html_ui.cc b/chrome/browser/dom_ui/constrained_html_ui.cc
index 75aeda1..5eac45d 100644
--- a/chrome/browser/dom_ui/constrained_html_ui.cc
+++ b/chrome/browser/dom_ui/constrained_html_ui.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/constrained_html_ui.h"
 
 #include "base/lazy_instance.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/common/bindings_policy.h"
@@ -15,7 +15,7 @@
     g_constrained_html_ui_property_accessor(base::LINKER_INITIALIZED);
 
 ConstrainedHtmlUI::ConstrainedHtmlUI(TabContents* contents)
-    : DOMUI(contents) {
+    : WebUI(contents) {
 }
 
 ConstrainedHtmlUI::~ConstrainedHtmlUI() {
@@ -23,13 +23,16 @@
 
 void ConstrainedHtmlUI::RenderViewCreated(
     RenderViewHost* render_view_host) {
-  HtmlDialogUIDelegate* delegate =
-      GetConstrainedDelegate()->GetHtmlDialogUIDelegate();
-  std::vector<DOMMessageHandler*> handlers;
-  delegate->GetDOMMessageHandlers(&handlers);
-  render_view_host->SetDOMUIProperty("dialogArguments",
-                                     delegate->GetDialogArgs());
-  for (std::vector<DOMMessageHandler*>::iterator it = handlers.begin();
+  ConstrainedHtmlUIDelegate* delegate = GetConstrainedDelegate();
+  if (!delegate)
+    return;
+
+  HtmlDialogUIDelegate* dialog_delegate = delegate->GetHtmlDialogUIDelegate();
+  std::vector<WebUIMessageHandler*> handlers;
+  dialog_delegate->GetWebUIMessageHandlers(&handlers);
+  render_view_host->SetWebUIProperty("dialogArguments",
+                                     dialog_delegate->GetDialogArgs());
+  for (std::vector<WebUIMessageHandler*>::iterator it = handlers.begin();
        it != handlers.end(); ++it) {
     (*it)->Attach(this);
     AddMessageHandler(*it);
@@ -41,14 +44,20 @@
 }
 
 void ConstrainedHtmlUI::OnDialogClose(const ListValue* args) {
-  GetConstrainedDelegate()->GetHtmlDialogUIDelegate()->OnDialogClosed(
-      dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
-  GetConstrainedDelegate()->OnDialogClose();
+  ConstrainedHtmlUIDelegate* delegate = GetConstrainedDelegate();
+  if (!delegate)
+    return;
+
+  delegate->GetHtmlDialogUIDelegate()->OnDialogClosed(
+      web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  delegate->OnDialogClose();
 }
 
 ConstrainedHtmlUIDelegate*
     ConstrainedHtmlUI::GetConstrainedDelegate() {
-  return *GetPropertyAccessor().GetProperty(tab_contents()->property_bag());
+  ConstrainedHtmlUIDelegate** property =
+      GetPropertyAccessor().GetProperty(tab_contents()->property_bag());
+  return property ? *property : NULL;
 }
 
 // static
diff --git a/chrome/browser/dom_ui/constrained_html_ui.h b/chrome/browser/dom_ui/constrained_html_ui.h
index 48b769f..f2ca192 100644
--- a/chrome/browser/dom_ui/constrained_html_ui.h
+++ b/chrome/browser/dom_ui/constrained_html_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include <vector>
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/tab_contents/constrained_window.h"
 #include "chrome/common/property_bag.h"
 
@@ -25,13 +25,13 @@
   virtual void OnDialogClose() = 0;
 };
 
-// ConstrainedHtmlUI is a facility to show HTML DOM_UI content
+// ConstrainedHtmlUI is a facility to show HTML WebUI content
 // in a tab-modal constrained dialog.  It is implemented as an adapter
 // between an HtmlDialogUI object and a ConstrainedWindow object.
 //
 // Since ConstrainedWindow requires platform-specific delegate
 // implementations, this class is just a factory stub.
-class ConstrainedHtmlUI : public DOMUI {
+class ConstrainedHtmlUI : public WebUI {
  public:
   explicit ConstrainedHtmlUI(TabContents* contents);
   virtual ~ConstrainedHtmlUI();
@@ -51,6 +51,8 @@
       GetPropertyAccessor();
 
  private:
+  // Returns the TabContents' PropertyBag's ConstrainedHtmlUIDelegate.
+  // Returns NULL if that property is not set.
   ConstrainedHtmlUIDelegate* GetConstrainedDelegate();
 
   // JS Message Handler
diff --git a/chrome/browser/dom_ui/constrained_html_ui_browsertest.cc b/chrome/browser/dom_ui/constrained_html_ui_browsertest.cc
index 2862dbe..a0221ae 100644
--- a/chrome/browser/dom_ui/constrained_html_ui_browsertest.cc
+++ b/chrome/browser/dom_ui/constrained_html_ui_browsertest.cc
@@ -35,8 +35,8 @@
   virtual GURL GetDialogContentURL() const {
     return GURL(chrome::kChromeUIConstrainedHTMLTestURL);
   }
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const {}
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const {}
   virtual void GetDialogSize(gfx::Size* size) const {
     size->set_width(400);
     size->set_height(400);
diff --git a/chrome/browser/dom_ui/devtools_ui.cc b/chrome/browser/dom_ui/devtools_ui.cc
index ddb55c8..45b2bb3 100644
--- a/chrome/browser/dom_ui/devtools_ui.cc
+++ b/chrome/browser/dom_ui/devtools_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/common/render_messages.h"
 
-DevToolsUI::DevToolsUI(TabContents* contents) : DOMUI(contents) {
+DevToolsUI::DevToolsUI(TabContents* contents) : WebUI(contents) {
 }
 
 void DevToolsUI::RenderViewCreated(RenderViewHost* render_view_host) {
diff --git a/chrome/browser/dom_ui/devtools_ui.h b/chrome/browser/dom_ui/devtools_ui.h
index f41c871..6fb2644 100644
--- a/chrome/browser/dom_ui/devtools_ui.h
+++ b/chrome/browser/dom_ui/devtools_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_DOM_UI_DEVTOOLS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-class DevToolsUI : public DOMUI {
+class DevToolsUI : public WebUI {
  public:
   explicit DevToolsUI(TabContents* contents);
 
-  // DOMUI overrides.
+  // WebUI
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
 
  private:
diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc
deleted file mode 100644
index fdefd38..0000000
--- a/chrome/browser/dom_ui/dom_ui.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui.h"
-
-#include "base/i18n/rtl.h"
-#include "base/json/json_writer.h"
-#include "base/stl_util-inl.h"
-#include "base/string_number_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/common/bindings_policy.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/common/render_messages_params.h"
-
-namespace {
-
-std::wstring GetJavascript(const std::wstring& function_name,
-                           const std::vector<const Value*>& arg_list) {
-  std::wstring parameters;
-  std::string json;
-  for (size_t i = 0; i < arg_list.size(); ++i) {
-    if (i > 0)
-      parameters += L",";
-
-    base::JSONWriter::Write(arg_list[i], false, &json);
-    parameters += UTF8ToWide(json);
-  }
-  return function_name + L"(" + parameters + L");";
-}
-
-}  // namespace
-
-DOMUI::DOMUI(TabContents* contents)
-    : hide_favicon_(false),
-      force_bookmark_bar_visible_(false),
-      focus_location_bar_by_default_(false),
-      should_hide_url_(false),
-      link_transition_type_(PageTransition::LINK),
-      bindings_(BindingsPolicy::DOM_UI),
-      tab_contents_(contents) {
-}
-
-DOMUI::~DOMUI() {
-  STLDeleteContainerPairSecondPointers(message_callbacks_.begin(),
-                                       message_callbacks_.end());
-  STLDeleteContainerPointers(handlers_.begin(), handlers_.end());
-}
-
-// DOMUI, public: -------------------------------------------------------------
-
-void DOMUI::ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params) {
-  // Look up the callback for this message.
-  MessageCallbackMap::const_iterator callback =
-      message_callbacks_.find(params.name);
-  if (callback == message_callbacks_.end())
-    return;
-
-  // Forward this message and content on.
-  callback->second->Run(&params.arguments);
-}
-
-void DOMUI::CallJavascriptFunction(const std::wstring& function_name) {
-  std::wstring javascript = function_name + L"();";
-  ExecuteJavascript(javascript);
-}
-
-void DOMUI::CallJavascriptFunction(const std::wstring& function_name,
-                                   const Value& arg) {
-  std::vector<const Value*> args;
-  args.push_back(&arg);
-  ExecuteJavascript(GetJavascript(function_name, args));
-}
-
-void DOMUI::CallJavascriptFunction(
-    const std::wstring& function_name,
-    const Value& arg1, const Value& arg2) {
-  std::vector<const Value*> args;
-  args.push_back(&arg1);
-  args.push_back(&arg2);
-  ExecuteJavascript(GetJavascript(function_name, args));
-}
-
-void DOMUI::CallJavascriptFunction(
-    const std::wstring& function_name,
-    const Value& arg1, const Value& arg2, const Value& arg3) {
-  std::vector<const Value*> args;
-  args.push_back(&arg1);
-  args.push_back(&arg2);
-  args.push_back(&arg3);
-  ExecuteJavascript(GetJavascript(function_name, args));
-}
-
-void DOMUI::CallJavascriptFunction(
-    const std::wstring& function_name,
-    const Value& arg1,
-    const Value& arg2,
-    const Value& arg3,
-    const Value& arg4) {
-  std::vector<const Value*> args;
-  args.push_back(&arg1);
-  args.push_back(&arg2);
-  args.push_back(&arg3);
-  args.push_back(&arg4);
-  ExecuteJavascript(GetJavascript(function_name, args));
-}
-
-void DOMUI::CallJavascriptFunction(
-    const std::wstring& function_name,
-    const std::vector<const Value*>& args) {
-  ExecuteJavascript(GetJavascript(function_name, args));
-}
-
-ThemeProvider* DOMUI::GetThemeProvider() const {
-  return GetProfile()->GetThemeProvider();
-}
-
-void DOMUI::RegisterMessageCallback(const std::string &message,
-                                    MessageCallback *callback) {
-  message_callbacks_.insert(std::make_pair(message, callback));
-}
-
-Profile* DOMUI::GetProfile() const {
-  DCHECK(tab_contents());
-  return tab_contents()->profile();
-}
-
-// DOMUI, protected: ----------------------------------------------------------
-
-void DOMUI::AddMessageHandler(DOMMessageHandler* handler) {
-  handlers_.push_back(handler);
-}
-
-RenderViewHost* DOMUI::GetRenderViewHost() const {
-  DCHECK(tab_contents());
-  return tab_contents()->render_view_host();
-}
-
-// DOMUI, private: ------------------------------------------------------------
-
-void DOMUI::ExecuteJavascript(const std::wstring& javascript) {
-  GetRenderViewHost()->ExecuteJavascriptInWebFrame(std::wstring(), javascript);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DOMMessageHandler
-
-DOMMessageHandler* DOMMessageHandler::Attach(DOMUI* dom_ui) {
-  dom_ui_ = dom_ui;
-  RegisterMessages();
-  return this;
-}
-
-// DOMMessageHandler, protected: ----------------------------------------------
-
-void DOMMessageHandler::SetURLAndTitle(DictionaryValue* dictionary,
-                                       string16 title,
-                                       const GURL& gurl) {
-  dictionary->SetString("url", gurl.spec());
-
-  bool using_url_as_the_title = false;
-  if (title.empty()) {
-    using_url_as_the_title = true;
-    title = UTF8ToUTF16(gurl.spec());
-  }
-
-  // Since the title can contain BiDi text, we need to mark the text as either
-  // RTL or LTR, depending on the characters in the string. If we use the URL
-  // as the title, we mark the title as LTR since URLs are always treated as
-  // left to right strings.
-  string16 title_to_set(title);
-  if (base::i18n::IsRTL()) {
-    if (using_url_as_the_title) {
-      base::i18n::WrapStringWithLTRFormatting(&title_to_set);
-    } else {
-      base::i18n::AdjustStringForLocaleDirection(&title_to_set);
-    }
-  }
-  dictionary->SetString("title", title_to_set);
-}
-
-bool DOMMessageHandler::ExtractIntegerValue(const ListValue* value,
-                                            int* out_int) {
-  std::string string_value;
-  if (value->GetString(0, &string_value))
-    return base::StringToInt(string_value, out_int);
-  NOTREACHED();
-  return false;
-}
-
-// TODO(viettrungluu): convert to string16 (or UTF-8 std::string?).
-std::wstring DOMMessageHandler::ExtractStringValue(const ListValue* value) {
-  string16 string16_value;
-  if (value->GetString(0, &string16_value))
-    return UTF16ToWideHack(string16_value);
-  NOTREACHED();
-  return std::wstring();
-}
diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h
deleted file mode 100644
index a74186d..0000000
--- a/chrome/browser/dom_ui/dom_ui.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_H_
-#pragma once
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/string16.h"
-#include "chrome/common/page_transition_types.h"
-
-class DictionaryValue;
-class DOMMessageHandler;
-class GURL;
-class ListValue;
-class Profile;
-class RenderViewHost;
-class TabContents;
-class ThemeProvider;
-class Value;
-struct ViewHostMsg_DomMessage_Params;
-
-// A DOMUI sets up the datasources and message handlers for a given HTML-based
-// UI. It is contained by a DOMUIManager.
-class DOMUI {
- public:
-  explicit DOMUI(TabContents* contents);
-  virtual ~DOMUI();
-
-  // Called by RenderViewHost when the RenderView is first created. This is
-  // *not* called for every page load because in some cases
-  // RenderViewHostManager will reuse RenderView instances. In those cases,
-  // RenderViewReused will be called instead.
-  virtual void RenderViewCreated(RenderViewHost* render_view_host) {}
-
-  // Called by RenderViewHostManager when a RenderView is reused to display a
-  // page.
-  virtual void RenderViewReused(RenderViewHost* render_view_host) {}
-
-  // Called when this becomes the active DOMUI instance for a re-used
-  // RenderView; this is the point at which this DOMUI instance will receive
-  // DOM messages instead of the previous DOMUI instance.
-  //
-  // If a DOMUI instance has code that is usually triggered from a JavaScript
-  // onload handler, this should be overridden to check to see if the web page's
-  // DOM is still intact (e.g., due to a back/forward navigation that remains
-  // within the same page), and if so trigger that code manually since onload
-  // won't be run in that case.
-  virtual void DidBecomeActiveForReusedRenderView() {}
-
-  // Called from TabContents.
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
-
-  // Used by DOMMessageHandlers.
-  typedef Callback1<const ListValue*>::Type MessageCallback;
-  void RegisterMessageCallback(const std::string& message,
-                               MessageCallback* callback);
-
-  // Returns true if the favicon should be hidden for the current tab.
-  bool hide_favicon() const {
-    return hide_favicon_;
-  }
-
-  // Returns true if the bookmark bar should be forced to being visible,
-  // overriding the user's preference.
-  bool force_bookmark_bar_visible() const {
-    return force_bookmark_bar_visible_;
-  }
-
-  // Returns true if the location bar should be focused by default rather than
-  // the page contents. Some pages will want to use this to encourage the user
-  // to type in the URL bar.
-  bool focus_location_bar_by_default() const {
-    return focus_location_bar_by_default_;
-  }
-
-  // Returns true if the page's URL should be hidden. Some DOM UI pages
-  // like the new tab page will want to hide it.
-  bool should_hide_url() const {
-    return should_hide_url_;
-  }
-
-  // Gets a custom tab title provided by the DOM UI. If there is no title
-  // override, the string will be empty which should trigger the default title
-  // behavior for the tab.
-  const string16& overridden_title() const {
-    return overridden_title_;
-  }
-
-  // Returns the transition type that should be used for link clicks on this
-  // DOM UI. This will default to LINK but may be overridden.
-  PageTransition::Type link_transition_type() const {
-    return link_transition_type_;
-  }
-
-  int bindings() const {
-    return bindings_;
-  }
-
-  // Call a Javascript function by sending its name and arguments down to
-  // the renderer.  This is asynchronous; there's no way to get the result
-  // of the call, and should be thought of more like sending a message to
-  // the page.
-  // There are variants for calls with more arguments.
-  void CallJavascriptFunction(const std::wstring& function_name);
-  void CallJavascriptFunction(const std::wstring& function_name,
-                              const Value& arg);
-  void CallJavascriptFunction(const std::wstring& function_name,
-                              const Value& arg1,
-                              const Value& arg2);
-  void CallJavascriptFunction(const std::wstring& function_name,
-                              const Value& arg1,
-                              const Value& arg2,
-                              const Value& arg3);
-  void CallJavascriptFunction(const std::wstring& function_name,
-                              const Value& arg1,
-                              const Value& arg2,
-                              const Value& arg3,
-                              const Value& arg4);
-  void CallJavascriptFunction(const std::wstring& function_name,
-                              const std::vector<const Value*>& args);
-
-  ThemeProvider* GetThemeProvider() const;
-
-  // May be overridden by DOMUI's which do not have a tab contents.
-  virtual Profile* GetProfile() const;
-
-  // May be overridden by DOMUI's which do not have a tab contents.
-  virtual RenderViewHost* GetRenderViewHost() const;
-
-  TabContents* tab_contents() const { return tab_contents_; }
-
- protected:
-  void AddMessageHandler(DOMMessageHandler* handler);
-
-  // Options that may be overridden by individual DOM UI implementations. The
-  // bool options default to false. See the public getters for more information.
-  bool hide_favicon_;
-  bool force_bookmark_bar_visible_;
-  bool focus_location_bar_by_default_;
-  bool should_hide_url_;
-  string16 overridden_title_;  // Defaults to empty string.
-  PageTransition::Type link_transition_type_;  // Defaults to LINK.
-  int bindings_;  // The bindings from BindingsPolicy that should be enabled for
-                  // this page.
-
-  // The DOMMessageHandlers we own.
-  std::vector<DOMMessageHandler*> handlers_;
-
-  // Non-owning pointer to the TabContents this DOMUI is associated with.
-  TabContents* tab_contents_;
-
- private:
-  // Execute a string of raw Javascript on the page.
-  void ExecuteJavascript(const std::wstring& javascript);
-
-  // A map of message name -> message handling callback.
-  typedef std::map<std::string, MessageCallback*> MessageCallbackMap;
-  MessageCallbackMap message_callbacks_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMUI);
-};
-
-// Messages sent from the DOM are forwarded via the DOMUI to handler
-// classes. These objects are owned by DOMUI and destroyed when the
-// host is destroyed.
-class DOMMessageHandler {
- public:
-  DOMMessageHandler() : dom_ui_(NULL) {}
-  virtual ~DOMMessageHandler() {}
-
-  // Attaches |this| to |dom_ui| in order to handle messages from it.  Declared
-  // virtual so that subclasses can do special init work as soon as the dom_ui
-  // is provided.  Returns |this| for convenience.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
-
- protected:
-  // Adds "url" and "title" keys on incoming dictionary, setting title
-  // as the url as a fallback on empty title.
-  static void SetURLAndTitle(DictionaryValue* dictionary,
-                             string16 title,
-                             const GURL& gurl);
-
-  // This is where subclasses specify which messages they'd like to handle.
-  virtual void RegisterMessages() = 0;
-
-  // Extract an integer value from a list Value.
-  bool ExtractIntegerValue(const ListValue* value, int* out_int);
-
-  // Extract a string value from a list Value.
-  std::wstring ExtractStringValue(const ListValue* value);
-
-  DOMUI* dom_ui_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DOMMessageHandler);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_H_
diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc
deleted file mode 100644
index 3ef5f5b..0000000
--- a/chrome/browser/dom_ui/dom_ui_factory.cc
+++ /dev/null
@@ -1,338 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
-
-#include "base/command_line.h"
-#include "chrome/browser/about_flags.h"
-#include "chrome/browser/dom_ui/bookmarks_ui.h"
-#include "chrome/browser/dom_ui/bug_report_ui.h"
-#include "chrome/browser/dom_ui/constrained_html_ui.h"
-#include "chrome/browser/dom_ui/downloads_ui.h"
-#include "chrome/browser/dom_ui/devtools_ui.h"
-#include "chrome/browser/dom_ui/gpu_internals_ui.h"
-#include "chrome/browser/dom_ui/history_ui.h"
-#include "chrome/browser/dom_ui/history2_ui.h"
-#include "chrome/browser/dom_ui/html_dialog_ui.h"
-#include "chrome/browser/dom_ui/flags_ui.h"
-#include "chrome/browser/dom_ui/net_internals_ui.h"
-#include "chrome/browser/dom_ui/new_tab_ui.h"
-#include "chrome/browser/dom_ui/plugins_ui.h"
-#include "chrome/browser/dom_ui/print_preview_ui.h"
-#include "chrome/browser/dom_ui/remoting_ui.h"
-#include "chrome/browser/dom_ui/options/options_ui.h"
-#include "chrome/browser/dom_ui/slideshow_ui.h"
-#include "chrome/browser/dom_ui/textfields_ui.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extensions_ui.h"
-#include "chrome/browser/printing/print_dialog_cloud.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/dom_ui/imageburner_ui.h"
-#include "chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.h"
-#include "chrome/browser/chromeos/dom_ui/menu_ui.h"
-#include "chrome/browser/chromeos/dom_ui/mobile_setup_ui.h"
-#include "chrome/browser/chromeos/dom_ui/register_page_ui.h"
-#include "chrome/browser/chromeos/dom_ui/system_info_ui.h"
-#include "chrome/browser/chromeos/dom_ui/wrench_menu_ui.h"
-#include "chrome/browser/chromeos/dom_ui/network_menu_ui.h"
-#include "chrome/browser/dom_ui/filebrowse_ui.h"
-#include "chrome/browser/dom_ui/mediaplayer_ui.h"
-#endif
-
-#if defined(TOUCH_UI)
-#include "chrome/browser/dom_ui/keyboard_ui.h"
-#include "chrome/browser/chromeos/dom_ui/login/login_ui.h"
-#endif
-
-#if defined(OS_WIN)
-#include "chrome/browser/dom_ui/conflicts_ui.h"
-#endif
-
-const DOMUITypeID DOMUIFactory::kNoDOMUI = NULL;
-
-// A function for creating a new DOMUI. The caller owns the return value, which
-// may be NULL (for example, if the URL refers to an non-existent extension).
-typedef DOMUI* (*DOMUIFactoryFunction)(TabContents* tab_contents,
-                                       const GURL& url);
-
-// Template for defining DOMUIFactoryFunction.
-template<class T>
-DOMUI* NewDOMUI(TabContents* contents, const GURL& url) {
-  return new T(contents);
-}
-
-// Special case for extensions.
-template<>
-DOMUI* NewDOMUI<ExtensionDOMUI>(TabContents* contents, const GURL& url) {
-  // Don't use a DOMUI for incognito tabs because we require extensions to run
-  // within a single process.
-  ExtensionService* service = contents->profile()->GetExtensionService();
-  if (service &&
-      service->ExtensionBindingsAllowed(url)) {
-    return new ExtensionDOMUI(contents, url);
-  }
-  return NULL;
-}
-
-// Returns a function that can be used to create the right type of DOMUI for a
-// tab, based on its URL. Returns NULL if the URL doesn't have DOMUI associated
-// with it. Even if the factory function is valid, it may yield a NULL DOMUI
-// when invoked for a particular tab - see NewDOMUI<ExtensionDOMUI>.
-static DOMUIFactoryFunction GetDOMUIFactoryFunction(Profile* profile,
-    const GURL& url) {
-  // Currently, any gears: URL means an HTML dialog.
-  if (url.SchemeIs(chrome::kGearsScheme))
-    return &NewDOMUI<HtmlDialogUI>;
-
-  if (url.host() == chrome::kChromeUIDialogHost)
-    return &NewDOMUI<ConstrainedHtmlUI>;
-
-  ExtensionService* service = profile ? profile->GetExtensionService() : NULL;
-  if (service && service->ExtensionBindingsAllowed(url))
-    return &NewDOMUI<ExtensionDOMUI>;
-
-  // All platform builds of Chrome will need to have a cloud printing
-  // dialog as backup.  It's just that on Chrome OS, it's the only
-  // print dialog.
-  if (url.host() == chrome::kCloudPrintResourcesHost)
-    return &NewDOMUI<ExternalHtmlDialogUI>;
-
-  // This will get called a lot to check all URLs, so do a quick check of other
-  // schemes (gears was handled above) to filter out most URLs.
-  if (!url.SchemeIs(chrome::kChromeDevToolsScheme) &&
-      !url.SchemeIs(chrome::kChromeInternalScheme) &&
-      !url.SchemeIs(chrome::kChromeUIScheme))
-    return NULL;
-
-  if (url.host() == chrome::kChromeUISyncResourcesHost ||
-      url.host() == chrome::kChromeUIRemotingResourcesHost ||
-      url.host() == chrome::kCloudPrintSetupHost)
-    return &NewDOMUI<HtmlDialogUI>;
-
-  // Special case the new tab page. In older versions of Chrome, the new tab
-  // page was hosted at chrome-internal:<blah>. This might be in people's saved
-  // sessions or bookmarks, so we say any URL with that scheme triggers the new
-  // tab page.
-  if (url.host() == chrome::kChromeUINewTabHost ||
-      url.SchemeIs(chrome::kChromeInternalScheme))
-    return &NewDOMUI<NewTabUI>;
-
-  // Give about:about a generic DOM UI so it can navigate to pages with DOM UIs.
-  if (url.spec() == chrome::kChromeUIAboutAboutURL)
-    return &NewDOMUI<DOMUI>;
-
-  // We must compare hosts only since some of the DOM UIs append extra stuff
-  // after the host name.
-  if (url.host() == chrome::kChromeUIBookmarksHost)
-    return &NewDOMUI<BookmarksUI>;
-  if (url.host() == chrome::kChromeUIBugReportHost)
-    return &NewDOMUI<BugReportUI>;
-  if (url.host() == chrome::kChromeUIDevToolsHost)
-    return &NewDOMUI<DevToolsUI>;
-#if defined(OS_WIN)
-  if (url.host() == chrome::kChromeUIConflictsHost)
-    return &NewDOMUI<ConflictsUI>;
-#endif
-  if (url.host() == chrome::kChromeUIDownloadsHost)
-    return &NewDOMUI<DownloadsUI>;
-  if (url.host() == chrome::kChromeUITextfieldsHost)
-    return &NewDOMUI<TextfieldsUI>;
-  if (url.host() == chrome::kChromeUIExtensionsHost)
-    return &NewDOMUI<ExtensionsUI>;
-  if (url.host() == chrome::kChromeUIHistoryHost)
-    return &NewDOMUI<HistoryUI>;
-  if (url.host() == chrome::kChromeUIHistory2Host)
-    return &NewDOMUI<HistoryUI2>;
-  if (url.host() == chrome::kChromeUIFlagsHost)
-    return &NewDOMUI<FlagsUI>;
-#if defined(TOUCH_UI)
-  if (url.host() == chrome::kChromeUIKeyboardHost)
-    return &NewDOMUI<KeyboardUI>;
-#endif
-  if (url.host() == chrome::kChromeUIGpuInternalsHost)
-    return &NewDOMUI<GpuInternalsUI>;
-  if (url.host() == chrome::kChromeUINetInternalsHost)
-    return &NewDOMUI<NetInternalsUI>;
-  if (url.host() == chrome::kChromeUIPluginsHost)
-    return &NewDOMUI<PluginsUI>;
-#if defined(ENABLE_REMOTING)
-  if (url.host() == chrome::kChromeUIRemotingHost) {
-    if (CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kEnableRemoting)) {
-      return &NewDOMUI<RemotingUI>;
-    }
-  }
-#endif
-
-#if defined(OS_CHROMEOS)
-  if (url.host() == chrome::kChromeUIFileBrowseHost)
-    return &NewDOMUI<FileBrowseUI>;
-  if (url.host() == chrome::kChromeUIImageBurnerHost)
-    return &NewDOMUI<ImageBurnUI>;
-  if (url.host() == chrome::kChromeUIKeyboardOverlayHost)
-    return &NewDOMUI<KeyboardOverlayUI>;
-  if (url.host() == chrome::kChromeUIMediaplayerHost)
-    return &NewDOMUI<MediaplayerUI>;
-  if (url.host() == chrome::kChromeUIMobileSetupHost)
-    return &NewDOMUI<MobileSetupUI>;
-  if (url.host() == chrome::kChromeUIRegisterPageHost)
-    return &NewDOMUI<RegisterPageUI>;
-  if (url.host() == chrome::kChromeUISettingsHost)
-    return &NewDOMUI<OptionsUI>;
-  if (url.host() == chrome::kChromeUISlideshowHost)
-    return &NewDOMUI<SlideshowUI>;
-  if (url.host() == chrome::kChromeUISystemInfoHost)
-    return &NewDOMUI<SystemInfoUI>;
-  if (url.host() == chrome::kChromeUIMenu)
-    return &NewDOMUI<chromeos::MenuUI>;
-  if (url.host() == chrome::kChromeUIWrenchMenu)
-    return &NewDOMUI<chromeos::WrenchMenuUI>;
-  if (url.host() == chrome::kChromeUINetworkMenu)
-    return &NewDOMUI<chromeos::NetworkMenuUI>;
-#else
-  if (url.host() == chrome::kChromeUISettingsHost) {
-    if (!CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kDisableTabbedOptions)) {
-      return &NewDOMUI<OptionsUI>;
-    }
-  }
-  if (url.host() == chrome::kChromeUIPrintHost) {
-    if (CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kEnablePrintPreview)) {
-      return &NewDOMUI<PrintPreviewUI>;
-    }
-  }
-#endif  // defined(OS_CHROMEOS)
-
-#if defined(OS_CHROMEOS) && defined(TOUCH_UI)
-  if (url.host() == chrome::kChromeUILoginHost)
-    return &NewDOMUI<chromeos::LoginUI>;
-#endif
-
-  if (url.spec() == chrome::kChromeUIConstrainedHTMLTestURL)
-    return &NewDOMUI<ConstrainedHtmlUI>;
-
-  return NULL;
-}
-
-// static
-DOMUITypeID DOMUIFactory::GetDOMUIType(Profile* profile, const GURL& url) {
-  DOMUIFactoryFunction function = GetDOMUIFactoryFunction(profile, url);
-  return function ? reinterpret_cast<DOMUITypeID>(function) : kNoDOMUI;
-}
-
-// static
-bool DOMUIFactory::HasDOMUIScheme(const GURL& url) {
-  return url.SchemeIs(chrome::kChromeDevToolsScheme) ||
-         url.SchemeIs(chrome::kChromeInternalScheme) ||
-         url.SchemeIs(chrome::kChromeUIScheme) ||
-         url.SchemeIs(chrome::kExtensionScheme);
-}
-
-// static
-bool DOMUIFactory::UseDOMUIForURL(Profile* profile, const GURL& url) {
-  return GetDOMUIFactoryFunction(profile, url) != NULL;
-}
-
-// static
-bool DOMUIFactory::IsURLAcceptableForDOMUI(Profile* profile, const GURL& url) {
-  return UseDOMUIForURL(profile, url) ||
-      // javacsript: URLs are allowed to run in DOM UI pages
-      url.SchemeIs(chrome::kJavaScriptScheme) ||
-      // It's possible to load about:blank in a DOM UI renderer.
-      // See http://crbug.com/42547
-      url.spec() == chrome::kAboutBlankURL ||
-      // about:crash, about:hang, and about:shorthang are allowed.
-      url.spec() == chrome::kAboutCrashURL ||
-      url.spec() == chrome::kAboutHangURL ||
-      url.spec() == chrome::kAboutShorthangURL;
-}
-
-// static
-DOMUI* DOMUIFactory::CreateDOMUIForURL(TabContents* tab_contents,
-                                       const GURL& url) {
-  DOMUIFactoryFunction function = GetDOMUIFactoryFunction(
-      tab_contents->profile(), url);
-  if (!function)
-    return NULL;
-  return (*function)(tab_contents, url);
-}
-
-// static
-void DOMUIFactory::GetFaviconForURL(Profile* profile,
-                                    FaviconService::GetFaviconRequest* request,
-                                    const GURL& page_url) {
-  // All extensions but the bookmark manager get their favicon from the icons
-  // part of the manifest.
-  if (page_url.SchemeIs(chrome::kExtensionScheme) &&
-      page_url.host() != extension_misc::kBookmarkManagerId) {
-    ExtensionDOMUI::GetFaviconForURL(profile, request, page_url);
-  } else {
-    scoped_refptr<RefCountedMemory> icon_data(
-        DOMUIFactory::GetFaviconResourceBytes(profile, page_url));
-    bool know_icon = icon_data.get() != NULL && icon_data->size() > 0;
-    request->ForwardResultAsync(
-        FaviconService::FaviconDataCallback::TupleType(request->handle(),
-            know_icon, icon_data, false, GURL()));
-  }
-}
-
-// static
-RefCountedMemory* DOMUIFactory::GetFaviconResourceBytes(Profile* profile,
-                                                        const GURL& page_url) {
-  // The bookmark manager is a chrome extension, so we have to check for it
-  // before we check for extension scheme.
-  if (page_url.host() == extension_misc::kBookmarkManagerId)
-    return BookmarksUI::GetFaviconResourceBytes();
-
-  // The extension scheme is handled in GetFaviconForURL.
-  if (page_url.SchemeIs(chrome::kExtensionScheme)) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  if (!HasDOMUIScheme(page_url))
-    return NULL;
-
-#if defined(OS_WIN)
-  if (page_url.host() == chrome::kChromeUIConflictsHost)
-    return ConflictsUI::GetFaviconResourceBytes();
-#endif
-
-  if (page_url.host() == chrome::kChromeUIDownloadsHost)
-    return DownloadsUI::GetFaviconResourceBytes();
-
-  if (page_url.host() == chrome::kChromeUIExtensionsHost)
-    return ExtensionsUI::GetFaviconResourceBytes();
-
-  if (page_url.host() == chrome::kChromeUIHistoryHost)
-    return HistoryUI::GetFaviconResourceBytes();
-
-  if (page_url.host() == chrome::kChromeUIHistory2Host)
-    return HistoryUI2::GetFaviconResourceBytes();
-
-  if (page_url.host() == chrome::kChromeUIFlagsHost)
-    return FlagsUI::GetFaviconResourceBytes();
-
-  if (page_url.host() == chrome::kChromeUISettingsHost)
-    return OptionsUI::GetFaviconResourceBytes();
-
-  if (page_url.host() == chrome::kChromeUIPluginsHost)
-    return PluginsUI::GetFaviconResourceBytes();
-
-#if defined(ENABLE_REMOTING)
-  if (page_url.host() == chrome::kChromeUIRemotingHost)
-    return RemotingUI::GetFaviconResourceBytes();
-#endif
-
-  return NULL;
-}
diff --git a/chrome/browser/dom_ui/dom_ui_factory.h b/chrome/browser/dom_ui/dom_ui_factory.h
deleted file mode 100644
index 1e1ed87..0000000
--- a/chrome/browser/dom_ui/dom_ui_factory.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_FACTORY_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_FACTORY_H_
-#pragma once
-
-#include "chrome/browser/favicon_service.h"
-
-class DOMUI;
-class GURL;
-class Profile;
-class RefCountedMemory;
-class TabContents;
-
-// An opaque identifier used to identify a DOMUI. This can only be compared to
-// kNoDOMUI or other DOMUI types. See GetDOMUIType.
-typedef void* DOMUITypeID;
-
-class DOMUIFactory {
- public:
-  // A special DOMUI type that signifies that a given page would not use the
-  // DOM UI system.
-  static const DOMUITypeID kNoDOMUI;
-
-  // Returns a type identifier indicating what DOMUI we would use for the
-  // given URL. This is useful for comparing the potential DOMUIs for two URLs.
-  // Returns kNoDOMUI if the given URL will not use the DOM UI system.
-  static DOMUITypeID GetDOMUIType(Profile* profile, const GURL& url);
-
-  // Returns true if the given URL's scheme would trigger the DOM UI system.
-  // This is a less precise test than UseDONUIForURL, which tells you whether
-  // that specific URL matches a known one. This one is faster and can be used
-  // to determine security policy.
-  static bool HasDOMUIScheme(const GURL& url);
-
-  // Returns true if the given URL must use the DOM UI system.
-  static bool UseDOMUIForURL(Profile* profile, const GURL& url);
-
-  // Returns true if the given URL can be loaded by DOM UI system.  This
-  // includes URLs that can be loaded by normal tabs as well, such as
-  // javascript: URLs or about:hang.
-  static bool IsURLAcceptableForDOMUI(Profile* profile, const GURL& url);
-
-  // Allocates a new DOMUI object for the given URL, and returns it. If the URL
-  // is not a DOM UI URL, then it will return NULL. When non-NULL, ownership of
-  // the returned pointer is passed to the caller.
-  static DOMUI* CreateDOMUIForURL(TabContents* tab_contents, const GURL& url);
-
-  // Get the favicon for |page_url| and forward the result to the |request|
-  // when loaded.
-  static void GetFaviconForURL(Profile* profile,
-                               FaviconService::GetFaviconRequest* request,
-                               const GURL& page_url);
-
- private:
-  // Class is for scoping only.
-  DOMUIFactory() {}
-
-  // Gets the data for the favicon for a DOMUI page. Returns NULL if the DOMUI
-  // does not have a favicon.
-  static RefCountedMemory* GetFaviconResourceBytes(Profile* profile,
-                                                   const GURL& page_url);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_FACTORY_H_
diff --git a/chrome/browser/dom_ui/dom_ui_favicon_source.cc b/chrome/browser/dom_ui/dom_ui_favicon_source.cc
deleted file mode 100644
index 565d4ed..0000000
--- a/chrome/browser/dom_ui/dom_ui_favicon_source.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
-
-#include "app/resource_bundle.h"
-#include "base/callback.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/url_constants.h"
-#include "grit/app_resources.h"
-
-DOMUIFavIconSource::DOMUIFavIconSource(Profile* profile)
-    : DataSource(chrome::kChromeUIFavIconHost, MessageLoop::current()),
-      profile_(profile->GetOriginalProfile()) {
-}
-
-DOMUIFavIconSource::~DOMUIFavIconSource() {
-}
-
-void DOMUIFavIconSource::StartDataRequest(const std::string& path,
-                                          bool is_off_the_record,
-                                          int request_id) {
-  FaviconService* favicon_service =
-      profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
-  if (favicon_service) {
-    FaviconService::Handle handle;
-    if (path.empty()) {
-      SendDefaultResponse(request_id);
-      return;
-    }
-
-    if (path.size() > 8 && path.substr(0, 8) == "iconurl/") {
-      handle = favicon_service->GetFavicon(
-          GURL(path.substr(8)),
-          &cancelable_consumer_,
-          NewCallback(this, &DOMUIFavIconSource::OnFavIconDataAvailable));
-    } else {
-      handle = favicon_service->GetFaviconForURL(
-          GURL(path),
-          &cancelable_consumer_,
-          NewCallback(this, &DOMUIFavIconSource::OnFavIconDataAvailable));
-    }
-    // Attach the ChromeURLDataManager request ID to the history request.
-    cancelable_consumer_.SetClientData(favicon_service, handle, request_id);
-  } else {
-    SendResponse(request_id, NULL);
-  }
-}
-
-std::string DOMUIFavIconSource::GetMimeType(const std::string&) const {
-  // We need to explicitly return a mime type, otherwise if the user tries to
-  // drag the image they get no extension.
-  return "image/png";
-}
-
-void DOMUIFavIconSource::OnFavIconDataAvailable(
-    FaviconService::Handle request_handle,
-    bool know_favicon,
-    scoped_refptr<RefCountedMemory> data,
-    bool expired,
-    GURL icon_url) {
-  FaviconService* favicon_service =
-      profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
-  int request_id = cancelable_consumer_.GetClientData(favicon_service,
-                                                      request_handle);
-
-  if (know_favicon && data.get() && data->size()) {
-    // Forward the data along to the networking system.
-    SendResponse(request_id, data);
-  } else {
-    SendDefaultResponse(request_id);
-  }
-}
-
-void DOMUIFavIconSource::SendDefaultResponse(int request_id) {
-  if (!default_favicon_.get()) {
-    default_favicon_ =
-        ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
-            IDR_DEFAULT_FAVICON);
-  }
-
-  SendResponse(request_id, default_favicon_);
-}
diff --git a/chrome/browser/dom_ui/dom_ui_favicon_source.h b/chrome/browser/dom_ui/dom_ui_favicon_source.h
deleted file mode 100644
index 84c29fc..0000000
--- a/chrome/browser/dom_ui/dom_ui_favicon_source.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_FAVICON_SOURCE_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_FAVICON_SOURCE_H_
-#pragma once
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/favicon_service.h"
-
-class GURL;
-class Profile;
-
-// FavIconSource is the gateway between network-level chrome:
-// requests for favicons and the history backend that serves these.
-class DOMUIFavIconSource : public ChromeURLDataManager::DataSource {
- public:
-  explicit DOMUIFavIconSource(Profile* profile);
-
-  // Called when the network layer has requested a resource underneath
-  // the path we registered.
-  virtual void StartDataRequest(const std::string& path,
-                                bool is_off_the_record,
-                                int request_id);
-
-  virtual std::string GetMimeType(const std::string&) const;
-
-  // Called when favicon data is available from the history backend.
-  void OnFavIconDataAvailable(FaviconService::Handle request_handle,
-                              bool know_favicon,
-                              scoped_refptr<RefCountedMemory> data,
-                              bool expired,
-                              GURL url);
-
- private:
-  // Sends the default favicon.
-  void SendDefaultResponse(int request_id);
-
-  virtual ~DOMUIFavIconSource();
-
-  Profile* profile_;
-  CancelableRequestConsumerT<int, 0> cancelable_consumer_;
-
-  // Raw PNG representation of the favicon to show when the favicon
-  // database doesn't have a favicon for a webpage.
-  scoped_refptr<RefCountedMemory> default_favicon_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMUIFavIconSource);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_FAVICON_SOURCE_H_
diff --git a/chrome/browser/dom_ui/dom_ui_screenshot_source.cc b/chrome/browser/dom_ui/dom_ui_screenshot_source.cc
deleted file mode 100644
index 7efbae8..0000000
--- a/chrome/browser/dom_ui/dom_ui_screenshot_source.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui_screenshot_source.h"
-
-#include "base/callback.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/ref_counted_memory.h"
-#include "base/task.h"
-#include "base/threading/thread.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/codec/jpeg_codec.h"
-#include "googleurl/src/gurl.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-static const char kCurrentScreenshot[] = "current";
-#if defined(OS_CHROMEOS)
-static const char kSavedScreenshots[] = "saved/";
-#endif
-
-static const char kScreenshotsRelativePath[] = "/Screenshots/";
-
-#if defined(OS_CHROMEOS)
-// Read the file from the screenshots directory into the read_bytes vector.
-void ReadScreenshot(const std::string& filename,
-                   std::vector<unsigned char>* read_bytes,
-                   base::WaitableEvent* read_complete) {
-  read_bytes->clear();
-
-  FilePath fileshelf_path;
-  if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &fileshelf_path)) {
-    read_complete->Signal();
-    return;
-  }
-
-  FilePath file(fileshelf_path.value() + std::string(kScreenshotsRelativePath) +
-                filename);
-
-  int64 file_size = 0;
-  if (!file_util::GetFileSize(file, &file_size)) {
-    read_complete->Signal();
-    return;
-  }
-
-  // expand vector to file size
-  read_bytes->resize(file_size);
-  // read file into the vector
-  int bytes_read = 0;
-  if (!(bytes_read = file_util::ReadFile(file,
-                                         reinterpret_cast<char*>(
-                                             &read_bytes->front()),
-                                             static_cast<int>(file_size))))
-    read_bytes->clear();
-
-  // We're done, if successful, read_bytes will have the data
-  // otherwise, it'll be empty.
-  read_complete->Signal();
-}
-
-// Get a saved screenshot - read on the FILE thread.
-std::vector<unsigned char> GetSavedScreenshot(std::string filename) {
-  base::WaitableEvent read_complete(true, false);
-  std::vector<unsigned char> bytes;
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          NewRunnableFunction(&ReadScreenshot, filename,
-                                              &bytes, &read_complete));
-  read_complete.Wait();
-  return bytes;
-}
-#endif
-
-std::vector<unsigned char> DOMUIScreenshotSource::GetScreenshot(
-    const std::string& full_path) {
-  // Strip the query param value - we only use it as a hack to ensure our
-  // image gets reloaded instead of being pulled from the browser cache
-  std::string path = full_path.substr(0, full_path.find_first_of("?"));
-  if (path == kCurrentScreenshot) {
-    return current_screenshot_;
-#if defined(OS_CHROMEOS)
-  } else if (path.compare(0, strlen(kSavedScreenshots),
-                          kSavedScreenshots) == 0) {
-    // Split the saved screenshot filename from the path
-    std::string filename = path.substr(strlen(kSavedScreenshots));
-
-    return GetSavedScreenshot(filename);
-#endif
-  } else {
-    std::vector<unsigned char> ret;
-    // TODO(rkc): Weird vc bug, return std::vector<unsigned char>() causes
-    // the object assigned to the return value of this function magically
-    // change it's address 0x0; look into this eventually.
-    return ret;
-  }
-}
-
-DOMUIScreenshotSource::DOMUIScreenshotSource(
-    std::vector<unsigned char>* current_screenshot)
-    : DataSource(chrome::kChromeUIScreenshotPath, MessageLoop::current()) {
-  // Setup the last screenshot taken.
-  if (current_screenshot)
-    current_screenshot_ = *current_screenshot;
-  else
-    current_screenshot_.clear();
-}
-
-DOMUIScreenshotSource::~DOMUIScreenshotSource() {}
-
-void DOMUIScreenshotSource::StartDataRequest(const std::string& path,
-                                            bool is_off_the_record,
-                                            int request_id) {
-  SendResponse(request_id, new RefCountedBytes(GetScreenshot(path)));
-}
-
-std::string DOMUIScreenshotSource::GetMimeType(const std::string&) const {
-  // We need to explicitly return a mime type, otherwise if the user tries to
-  // drag the image they get no extension.
-  return "image/png";
-}
diff --git a/chrome/browser/dom_ui/dom_ui_screenshot_source.h b/chrome/browser/dom_ui/dom_ui_screenshot_source.h
deleted file mode 100644
index 3a9aafc..0000000
--- a/chrome/browser/dom_ui/dom_ui_screenshot_source.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_SCREENSHOT_SOURCE_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_SCREENSHOT_SOURCE_H_
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/html_dialog_ui.h"
-
-// ScreenshotSource is the data source that serves screenshots (saved
-// or current) to the bug report html ui
-class DOMUIScreenshotSource : public ChromeURLDataManager::DataSource {
- public:
-  explicit DOMUIScreenshotSource(
-      std::vector<unsigned char>* current_screenshot);
-
-  // Called when the network layer has requested a resource underneath
-  // the path we registered.
-  virtual void StartDataRequest(const std::string& path,
-                                bool is_off_the_record,
-                                int request_id);
-
-  virtual std::string GetMimeType(const std::string&) const;
-
-  std::vector<unsigned char> GetScreenshot(const std::string& path);
-
- private:
-  virtual ~DOMUIScreenshotSource();
-
-//  scoped_refptr<RefCountedBytes> current_screenshot_;
-  std::vector<unsigned char> current_screenshot_;
-  DISALLOW_COPY_AND_ASSIGN(DOMUIScreenshotSource);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_SCREENSHOT_SOURCE_H_
diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.cc b/chrome/browser/dom_ui/dom_ui_theme_source.cc
deleted file mode 100644
index cbddafd..0000000
--- a/chrome/browser/dom_ui/dom_ui_theme_source.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
-
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
-#include "base/message_loop.h"
-#include "base/ref_counted_memory.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/ntp_resource_cache.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/resources_util.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-
-// use a resource map rather than hard-coded strings.
-static const char* kNewTabCSSPath = "css/newtab.css";
-static const char* kNewIncognitoTabCSSPath = "css/newincognitotab.css";
-
-static std::string StripQueryParams(const std::string& path) {
-  GURL path_url = GURL(std::string(chrome::kChromeUIScheme) + "://" +
-                       std::string(chrome::kChromeUIThemePath) + "/" + path);
-  return path_url.path().substr(1);  // path() always includes a leading '/'.
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DOMUIThemeSource, public:
-
-DOMUIThemeSource::DOMUIThemeSource(Profile* profile)
-    : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()),
-      profile_(profile->GetOriginalProfile()) {
-  css_bytes_ = profile_->GetNTPResourceCache()->GetNewTabCSS(
-      profile->IsOffTheRecord());
-}
-
-DOMUIThemeSource::~DOMUIThemeSource() {
-}
-
-void DOMUIThemeSource::StartDataRequest(const std::string& path,
-                                        bool is_off_the_record,
-                                        int request_id) {
-  // Our path may include cachebuster arguments, so trim them off.
-  std::string uncached_path = StripQueryParams(path);
-
-  if (uncached_path == kNewTabCSSPath ||
-      uncached_path == kNewIncognitoTabCSSPath) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    DCHECK((uncached_path == kNewTabCSSPath && !is_off_the_record) ||
-           (uncached_path == kNewIncognitoTabCSSPath && is_off_the_record));
-
-    SendResponse(request_id, css_bytes_);
-    return;
-  } else {
-    int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path);
-    if (resource_id != -1) {
-      SendThemeBitmap(request_id, resource_id);
-      return;
-    }
-  }
-  // We don't have any data to send back.
-  SendResponse(request_id, NULL);
-}
-
-std::string DOMUIThemeSource::GetMimeType(const std::string& path) const {
-  std::string uncached_path = StripQueryParams(path);
-
-  if (uncached_path == kNewTabCSSPath ||
-      uncached_path == kNewIncognitoTabCSSPath) {
-    return "text/css";
-  }
-
-  return "image/png";
-}
-
-MessageLoop* DOMUIThemeSource::MessageLoopForRequestPath(
-    const std::string& path) const {
-  std::string uncached_path = StripQueryParams(path);
-
-  if (uncached_path == kNewTabCSSPath ||
-      uncached_path == kNewIncognitoTabCSSPath) {
-    // We generated and cached this when we initialized the object.  We don't
-    // have to go back to the UI thread to send the data.
-    return NULL;
-  }
-
-  // If it's not a themeable image, we don't need to go to the UI thread.
-  int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path);
-  if (!BrowserThemeProvider::IsThemeableImage(resource_id))
-    return NULL;
-
-  return DataSource::MessageLoopForRequestPath(path);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DOMUIThemeSource, private:
-
-void DOMUIThemeSource::SendThemeBitmap(int request_id, int resource_id) {
-  if (BrowserThemeProvider::IsThemeableImage(resource_id)) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    ThemeProvider* tp = profile_->GetThemeProvider();
-    DCHECK(tp);
-
-    scoped_refptr<RefCountedMemory> image_data(tp->GetRawData(resource_id));
-    SendResponse(request_id, image_data);
-  } else {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    SendResponse(request_id, rb.LoadDataResourceBytes(resource_id));
-  }
-}
diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.h b/chrome/browser/dom_ui/dom_ui_theme_source.h
deleted file mode 100644
index 2d55aaa..0000000
--- a/chrome/browser/dom_ui/dom_ui_theme_source.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_THEME_SOURCE_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_THEME_SOURCE_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-
-class Profile;
-class RefCountedBytes;
-
-class DOMUIThemeSource : public ChromeURLDataManager::DataSource {
- public:
-  explicit DOMUIThemeSource(Profile* profile);
-
-  // Called when the network layer has requested a resource underneath
-  // the path we registered.
-  virtual void StartDataRequest(const std::string& path,
-                                bool is_off_the_record,
-                                int request_id);
-  virtual std::string GetMimeType(const std::string& path) const;
-
-  // Used to tell ChromeURLDataManager which thread to handle the request on.
-  virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const;
-
- protected:
-  virtual ~DOMUIThemeSource();
-
- private:
-  // Fetch and send the theme bitmap.
-  void SendThemeBitmap(int request_id, int resource_id);
-
-  // The original profile (never an OTR profile).
-  Profile* profile_;
-
-  // We grab the CSS early so we don't have to go back to the UI thread later.
-  scoped_refptr<RefCountedBytes> css_bytes_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMUIThemeSource);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_THEME_SOURCE_H_
diff --git a/chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc b/chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc
deleted file mode 100644
index fb7a0ad..0000000
--- a/chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/ref_counted_memory.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/testing_profile.h"
-#include "grit/theme_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// A mock ThemeSource (so we can override SendResponse to get at its data).
-class MockThemeSource : public DOMUIThemeSource {
- public:
-  explicit MockThemeSource(Profile* profile)
-      : DOMUIThemeSource(profile),
-        result_request_id_(-1),
-        result_data_size_(0) {
-  }
-
-  virtual void SendResponse(int request_id, RefCountedMemory* data) {
-    result_data_size_ = data ? data->size() : 0;
-    result_request_id_ = request_id;
-  }
-
-  int result_request_id_;
-  size_t result_data_size_;
-
- private:
-  ~MockThemeSource() {}
-};
-
-class DOMUISourcesTest : public testing::Test {
- public:
-  DOMUISourcesTest() : ui_thread_(BrowserThread::UI, MessageLoop::current()) {}
-
-  TestingProfile* profile() const { return profile_.get(); }
-  MockThemeSource* theme_source() const { return theme_source_.get(); }
- private:
-  virtual void SetUp() {
-    profile_.reset(new TestingProfile());
-    profile_->InitThemes();
-    theme_source_ = new MockThemeSource(profile_.get());
-  }
-
-  virtual void TearDown() {
-    theme_source_ = NULL;
-    profile_.reset(NULL);
-  }
-
-  MessageLoop loop_;
-  BrowserThread ui_thread_;
-
-  scoped_ptr<TestingProfile> profile_;
-  scoped_refptr<MockThemeSource> theme_source_;
-};
-
-TEST_F(DOMUISourcesTest, ThemeSourceMimeTypes) {
-  EXPECT_EQ(theme_source()->GetMimeType("css/newtab.css"), "text/css");
-  EXPECT_EQ(theme_source()->GetMimeType("css/newtab.css?foo"), "text/css");
-  EXPECT_EQ(theme_source()->GetMimeType("WRONGURL"), "image/png");
-}
-
-TEST_F(DOMUISourcesTest, ThemeSourceImages) {
-  // We used to PNGEncode the images ourselves, but encoder differences
-  // invalidated that. We now just check that the image exists.
-  theme_source()->StartDataRequest("IDR_THEME_FRAME_INCOGNITO", true, 1);
-  size_t min = 0;
-  EXPECT_EQ(theme_source()->result_request_id_, 1);
-  EXPECT_GT(theme_source()->result_data_size_, min);
-
-  theme_source()->StartDataRequest("IDR_THEME_TOOLBAR", true, 2);
-  EXPECT_EQ(theme_source()->result_request_id_, 2);
-  EXPECT_GT(theme_source()->result_data_size_, min);
-}
-
-TEST_F(DOMUISourcesTest, ThemeSourceCSS) {
-  BrowserThread io_thread(BrowserThread::IO, MessageLoop::current());
-  // Generating the test data for the NTP CSS would just involve copying the
-  // method, or being super brittle and hard-coding the result (requiring
-  // an update to the unittest every time the CSS template changes), so we
-  // just check for a successful request and data that is non-null.
-  size_t empty_size = 0;
-
-  theme_source()->StartDataRequest("css/newtab.css", false, 1);
-  EXPECT_EQ(theme_source()->result_request_id_, 1);
-  EXPECT_NE(theme_source()->result_data_size_, empty_size);
-
-  theme_source()->StartDataRequest("css/newtab.css?pie", false, 3);
-  EXPECT_EQ(theme_source()->result_request_id_, 3);
-  EXPECT_NE(theme_source()->result_data_size_, empty_size);
-
-  // Check that we send NULL back when we can't find what we're looking for.
-  theme_source()->StartDataRequest("css/WRONGURL", false, 7);
-  EXPECT_EQ(theme_source()->result_request_id_, 7);
-  EXPECT_EQ(theme_source()->result_data_size_, empty_size);
-}
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
deleted file mode 100644
index 8b15821..0000000
--- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui_thumbnail_source.h"
-
-#include "app/resource_bundle.h"
-#include "base/callback.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/history/top_sites.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "grit/theme_resources.h"
-
-DOMUIThumbnailSource::DOMUIThumbnailSource(Profile* profile)
-    : DataSource(chrome::kChromeUIThumbnailPath, MessageLoop::current()),
-      profile_(profile) {
-  if (history::TopSites::IsEnabled()) {
-    // Set TopSites now as Profile isn't thread safe.
-    top_sites_ = profile_->GetTopSites();
-  }
-}
-
-DOMUIThumbnailSource::~DOMUIThumbnailSource() {
-}
-
-void DOMUIThumbnailSource::StartDataRequest(const std::string& path,
-                                            bool is_off_the_record,
-                                            int request_id) {
-  if (top_sites_.get()) {
-    scoped_refptr<RefCountedBytes> data;
-    if (top_sites_->GetPageThumbnail(GURL(path), &data)) {
-      // We have the thumbnail.
-      SendResponse(request_id, data.get());
-    } else {
-      SendDefaultThumbnail(request_id);
-    }
-    return;
-  }
-
-  HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
-  if (hs) {
-    HistoryService::Handle handle = hs->GetPageThumbnail(
-        GURL(path),
-        &cancelable_consumer_,
-        NewCallback(this, &DOMUIThumbnailSource::OnThumbnailDataAvailable));
-    // Attach the ChromeURLDataManager request ID to the history request.
-    cancelable_consumer_.SetClientData(hs, handle, request_id);
-  } else {
-    // Tell the caller that no thumbnail is available.
-    SendResponse(request_id, NULL);
-  }
-}
-
-std::string DOMUIThumbnailSource::GetMimeType(const std::string&) const {
-  // We need to explicitly return a mime type, otherwise if the user tries to
-  // drag the image they get no extension.
-  return "image/png";
-}
-
-MessageLoop* DOMUIThumbnailSource::MessageLoopForRequestPath(
-    const std::string& path) const {
-  // TopSites can be accessed from the IO thread.
-  return top_sites_.get() ? NULL : DataSource::MessageLoopForRequestPath(path);
-}
-
-void DOMUIThumbnailSource::SendDefaultThumbnail(int request_id) {
-  // Use placeholder thumbnail.
-  if (!default_thumbnail_.get()) {
-    default_thumbnail_ =
-        ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
-            IDR_DEFAULT_THUMBNAIL);
-  }
-  SendResponse(request_id, default_thumbnail_);
-}
-
-void DOMUIThumbnailSource::OnThumbnailDataAvailable(
-    HistoryService::Handle request_handle,
-    scoped_refptr<RefCountedBytes> data) {
-  int request_id = cancelable_consumer_.GetClientDataForCurrentRequest();
-  // Forward the data along to the networking system.
-  if (data.get() && !data->data.empty()) {
-    SendResponse(request_id, data);
-  } else {
-    SendDefaultThumbnail(request_id);
-  }
-}
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
deleted file mode 100644
index 8dd3a2d..0000000
--- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_THUMBNAIL_SOURCE_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_THUMBNAIL_SOURCE_H_
-#pragma once
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/history/history.h"
-#include "chrome/common/notification_registrar.h"
-
-class Profile;
-
-namespace history {
-class TopSites;
-}
-
-// ThumbnailSource is the gateway between network-level chrome: requests for
-// thumbnails and the history/top-sites backend that serves these.
-class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource {
- public:
-  explicit DOMUIThumbnailSource(Profile* profile);
-
-  // Called when the network layer has requested a resource underneath
-  // the path we registered.
-  virtual void StartDataRequest(const std::string& path,
-                                bool is_off_the_record,
-                                int request_id);
-
-  virtual std::string GetMimeType(const std::string& path) const;
-
-  virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const;
-
-  // Called when thumbnail data is available from the history backend.
-  void OnThumbnailDataAvailable(HistoryService::Handle request_handle,
-                                scoped_refptr<RefCountedBytes> data);
-
- private:
-  virtual ~DOMUIThumbnailSource();
-
-  // Send the default thumbnail when we are missing a real one.
-  void SendDefaultThumbnail(int request_id);
-
-  Profile* profile_;
-
-  CancelableRequestConsumerT<int, 0> cancelable_consumer_;
-
-  // Raw PNG representation of the thumbnail to show when the thumbnail
-  // database doesn't have a thumbnail for a webpage.
-  scoped_refptr<RefCountedMemory> default_thumbnail_;
-
-  // TopSites. If non-null we're using TopSites.
-  scoped_refptr<history::TopSites> top_sites_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMUIThumbnailSource);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_THUMBNAIL_SOURCE_H_
diff --git a/chrome/browser/dom_ui/dom_ui_unittest.cc b/chrome/browser/dom_ui/dom_ui_unittest.cc
deleted file mode 100644
index f3b6b72..0000000
--- a/chrome/browser/dom_ui/dom_ui_unittest.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/new_tab_ui.h"
-#include "chrome/browser/renderer_host/site_instance.h"
-#include "chrome/browser/renderer_host/test/test_render_view_host.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/browser/tab_contents/test_tab_contents.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class DOMUITest : public RenderViewHostTestHarness {
- public:
-  DOMUITest() : ui_thread_(BrowserThread::UI, MessageLoop::current()) {}
-
-  // Tests navigating with a DOM UI from a fresh (nothing pending or committed)
-  // state, through pending, committed, then another navigation. The first page
-  // ID that we should use is passed as a parameter. We'll use the next two
-  // values. This must be increasing for the life of the tests.
-  static void DoNavigationTest(TabContents* contents, int page_id) {
-    NavigationController* controller = &contents->controller();
-
-    // Start a pending load.
-    GURL new_tab_url(chrome::kChromeUINewTabURL);
-    controller->LoadURL(new_tab_url, GURL(), PageTransition::LINK);
-
-    // The navigation entry should be pending with no committed entry.
-    ASSERT_TRUE(controller->pending_entry());
-    ASSERT_FALSE(controller->GetLastCommittedEntry());
-
-    // Check the things the pending DOM UI should have set.
-    EXPECT_FALSE(contents->ShouldDisplayURL());
-    EXPECT_FALSE(contents->ShouldDisplayFavIcon());
-    EXPECT_TRUE(contents->ShouldShowBookmarkBar());
-    EXPECT_TRUE(contents->FocusLocationBarByDefault());
-
-    // Now commit the load.
-    static_cast<TestRenderViewHost*>(
-        contents->render_view_host())->SendNavigate(page_id, new_tab_url);
-
-    // The same flags should be set as before now that the load has committed.
-    EXPECT_FALSE(contents->ShouldDisplayURL());
-    EXPECT_FALSE(contents->ShouldDisplayFavIcon());
-    EXPECT_TRUE(contents->ShouldShowBookmarkBar());
-    EXPECT_TRUE(contents->FocusLocationBarByDefault());
-
-    // Start a pending navigation to a regular page.
-    GURL next_url("http://google.com/");
-    controller->LoadURL(next_url, GURL(), PageTransition::LINK);
-
-    // Check the flags. Some should reflect the new page (URL, title), some
-    // should reflect the old one (bookmark bar) until it has committed.
-    EXPECT_TRUE(contents->ShouldDisplayURL());
-    EXPECT_TRUE(contents->ShouldDisplayFavIcon());
-    EXPECT_TRUE(contents->ShouldShowBookmarkBar());
-    EXPECT_FALSE(contents->FocusLocationBarByDefault());
-
-    // Commit the regular page load. Note that we must send it to the "pending"
-    // RenderViewHost if there is one, since this transition will also cause a
-    // process transition, and our RVH pointer will be the "committed" one.
-    // In the second call to this function from DOMUIToStandard, it won't
-    // actually be pending, which is the point of this test.
-    if (contents->render_manager()->pending_render_view_host()) {
-      static_cast<TestRenderViewHost*>(
-          contents->render_manager()->pending_render_view_host())->SendNavigate(
-              page_id + 1, next_url);
-    } else {
-      static_cast<TestRenderViewHost*>(
-          contents->render_view_host())->SendNavigate(page_id + 1, next_url);
-    }
-
-    // The state should now reflect a regular page.
-    EXPECT_TRUE(contents->ShouldDisplayURL());
-    EXPECT_TRUE(contents->ShouldDisplayFavIcon());
-    EXPECT_FALSE(contents->ShouldShowBookmarkBar());
-    EXPECT_FALSE(contents->FocusLocationBarByDefault());
-  }
-
- private:
-  BrowserThread ui_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMUITest);
-};
-
-// Tests that the New Tab Page flags are correctly set and propogated by
-// TabContents when we first navigate to a DOM UI page, then to a standard
-// non-DOM-UI page.
-TEST_F(DOMUITest, DOMUIToStandard) {
-  DoNavigationTest(contents(), 1);
-
-  // Test the case where we're not doing the initial navigation. This is
-  // slightly different than the very-first-navigation case since the
-  // SiteInstance will be the same (the original TabContents must still be
-  // alive), which will trigger different behavior in RenderViewHostManager.
-  TestTabContents contents2(profile_.get(), NULL);
-
-  DoNavigationTest(&contents2, 101);
-}
-
-TEST_F(DOMUITest, DOMUIToDOMUI) {
-  // Do a load (this state is tested above).
-  GURL new_tab_url(chrome::kChromeUINewTabURL);
-  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
-  rvh()->SendNavigate(1, new_tab_url);
-
-  // Start another pending load of the new tab page.
-  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
-  rvh()->SendNavigate(2, new_tab_url);
-
-  // The flags should be the same as the non-pending state.
-  EXPECT_FALSE(contents()->ShouldDisplayURL());
-  EXPECT_FALSE(contents()->ShouldDisplayFavIcon());
-  EXPECT_TRUE(contents()->ShouldShowBookmarkBar());
-  EXPECT_TRUE(contents()->FocusLocationBarByDefault());
-}
-
-TEST_F(DOMUITest, StandardToDOMUI) {
-  // Start a pending navigation to a regular page.
-  GURL std_url("http://google.com/");
-
-  controller().LoadURL(std_url, GURL(), PageTransition::LINK);
-
-  // The state should now reflect the default.
-  EXPECT_TRUE(contents()->ShouldDisplayURL());
-  EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
-  EXPECT_FALSE(contents()->ShouldShowBookmarkBar());
-  EXPECT_FALSE(contents()->FocusLocationBarByDefault());
-
-  // Commit the load, the state should be the same.
-  rvh()->SendNavigate(1, std_url);
-  EXPECT_TRUE(contents()->ShouldDisplayURL());
-  EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
-  EXPECT_FALSE(contents()->ShouldShowBookmarkBar());
-  EXPECT_FALSE(contents()->FocusLocationBarByDefault());
-
-  // Start a pending load for a DOMUI.
-  GURL new_tab_url(chrome::kChromeUINewTabURL);
-  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
-  EXPECT_FALSE(contents()->ShouldDisplayURL());
-  EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
-  EXPECT_FALSE(contents()->ShouldShowBookmarkBar());
-  EXPECT_TRUE(contents()->FocusLocationBarByDefault());
-
-  // Committing DOM UI is tested above.
-}
-
-class TabContentsForFocusTest : public TestTabContents {
- public:
-  TabContentsForFocusTest(Profile* profile, SiteInstance* instance)
-      : TestTabContents(profile, instance), focus_called_(0) {
-  }
-
-  virtual void SetFocusToLocationBar(bool select_all) { ++focus_called_; }
-  int focus_called() const { return focus_called_; }
-
- private:
-  int focus_called_;
-};
-
-TEST_F(DOMUITest, FocusOnNavigate) {
-  // Setup.  |tc| will be used to track when we try to focus the location bar.
-  TabContentsForFocusTest* tc = new TabContentsForFocusTest(
-      contents()->profile(),
-      SiteInstance::CreateSiteInstance(contents()->profile()));
-  tc->controller().CopyStateFrom(controller());
-  scoped_ptr<TestTabContents> tc_scoped_ptr(tc);
-  contents_.swap(tc_scoped_ptr);
-  int page_id = 200;
-
-  // Load the NTP.
-  GURL new_tab_url(chrome::kChromeUINewTabURL);
-  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
-  rvh()->SendNavigate(page_id, new_tab_url);
-
-  // Navigate to another page.
-  GURL next_url("http://google.com/");
-  int next_page_id = page_id + 1;
-  controller().LoadURL(next_url, GURL(), PageTransition::LINK);
-  pending_rvh()->SendNavigate(next_page_id, next_url);
-
-  // Navigate back.  Should focus the location bar.
-  int focus_called = tc->focus_called();
-  ASSERT_TRUE(controller().CanGoBack());
-  controller().GoBack();
-  pending_rvh()->SendNavigate(page_id, new_tab_url);
-  EXPECT_LT(focus_called, tc->focus_called());
-
-  // Navigate forward.  Shouldn't focus the location bar.
-  focus_called = tc->focus_called();
-  ASSERT_TRUE(controller().CanGoForward());
-  controller().GoForward();
-  pending_rvh()->SendNavigate(next_page_id, next_url);
-  EXPECT_EQ(focus_called, tc->focus_called());
-
-  contents_.swap(tc_scoped_ptr);
-}
diff --git a/chrome/browser/dom_ui/dom_ui_util.cc b/chrome/browser/dom_ui/dom_ui_util.cc
deleted file mode 100644
index a5d36e4..0000000
--- a/chrome/browser/dom_ui/dom_ui_util.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/dom_ui_util.h"
-
-#include <vector>
-
-#include "app/resource_bundle.h"
-#include "base/base64.h"
-#include "base/logging.h"
-#include "base/values.h"
-#include "gfx/codec/png_codec.h"
-
-namespace dom_ui_util {
-
-std::string GetJsonResponseFromFirstArgumentInList(const ListValue* args) {
-  return GetJsonResponseFromArgumentList(args, 0);
-}
-
-std::string GetJsonResponseFromArgumentList(const ListValue* args,
-                                            size_t list_index) {
-  std::string result;
-  if (args->GetSize() <= list_index) {
-    NOTREACHED();
-    return result;
-  }
-
-  Value* value = NULL;
-  if (args->Get(list_index, &value))
-    value->GetAsString(&result);
-  else
-    NOTREACHED();
-
-  return result;
-}
-
-std::string GetImageDataUrl(const SkBitmap& bitmap) {
-  std::vector<unsigned char> output;
-  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output);
-  std::string str_url;
-  std::copy(output.begin(), output.end(),
-            std::back_inserter(str_url));
-  base::Base64Encode(str_url, &str_url);
-  str_url.insert(0, "data:image/png;base64,");
-  return str_url;
-}
-
-std::string GetImageDataUrlFromResource(int res) {
-  // Load resource icon and covert to base64 encoded data url
-  RefCountedStaticMemory* icon_data =
-      ResourceBundle::GetSharedInstance().LoadDataResourceBytes(res);
-  if (!icon_data)
-    return std::string();
-  scoped_refptr<RefCountedMemory> raw_icon(icon_data);
-  std::string str_url;
-  std::copy(raw_icon->front(), raw_icon->front() + raw_icon->size(),
-            std::back_inserter(str_url));
-  base::Base64Encode(str_url, &str_url);
-  str_url.insert(0, "data:image/png;base64,");
-  return str_url;
-}
-
-}  // end of namespace dom_ui_util
diff --git a/chrome/browser/dom_ui/dom_ui_util.h b/chrome/browser/dom_ui/dom_ui_util.h
deleted file mode 100644
index 335ef05..0000000
--- a/chrome/browser/dom_ui/dom_ui_util.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_UTIL_H_
-#define CHROME_BROWSER_DOM_UI_DOM_UI_UTIL_H_
-#pragma once
-
-#include <string>
-
-class ListValue;
-class SkBitmap;
-
-namespace dom_ui_util {
-
-// Convenience routine to get the response string from an argument
-// list.  Typically used when supporting a DOMUI and getting calls
-// from the hosted code.  Content must be a ListValue with at least
-// one entry in it, and that first entry must be a string, which is
-// returned.  The parameter is a Value for convenience.  Returns an
-// empty string on error or if the parameter is not a ListValue.
-std::string GetJsonResponseFromFirstArgumentInList(const ListValue* args);
-
-// Convenience routine to get one of the response strings from an
-// argument list.  content must be a ListValue, with at least
-// (list_index+1) entries in it.  list_index is the 0-based index of
-// the entry to pull from that list, and that entry must be a string,
-// which is returned.  The parameter is a Value for convenience.
-// Returns an empty string on error or if the parameter is not a
-// ListValue.
-std::string GetJsonResponseFromArgumentList(const ListValue* args,
-                                            size_t list_index);
-
-
-// Convenience routine to convert SkBitmap object to data url
-// so that it can be used in DOMUI.
-std::string GetImageDataUrl(const SkBitmap& bitmap);
-
-// Convenience routine to get data url that corresponds to given
-// resource_id as an image. This function does not check if the
-// resource for the |resource_id| is an image, therefore it is the
-// caller's responsibility to make sure the resource is indeed an
-// image. Returns empty string if a resource does not exist for given
-// |resource_id|.
-std::string GetImageDataUrlFromResource(int resource_id);
-
-}  // end of namespace
-
-#endif  // CHROME_BROWSER_DOM_UI_DOM_UI_UTIL_H_
diff --git a/chrome/browser/dom_ui/downloads_dom_handler.cc b/chrome/browser/dom_ui/downloads_dom_handler.cc
index c6a22ec..9f072b3 100644
--- a/chrome/browser/dom_ui/downloads_dom_handler.cc
+++ b/chrome/browser/dom_ui/downloads_dom_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,6 +22,7 @@
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
@@ -51,12 +52,8 @@
       download_manager_(dlm),
       callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
   // Create our fileicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new FileIconSource())));
+  dlm->profile()->GetChromeURLDataManager()->AddDataSource(
+      new FileIconSource());
 }
 
 DownloadsDOMHandler::~DownloadsDOMHandler() {
@@ -71,29 +68,29 @@
 }
 
 void DownloadsDOMHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getDownloads",
+  web_ui_->RegisterMessageCallback("getDownloads",
       NewCallback(this, &DownloadsDOMHandler::HandleGetDownloads));
-  dom_ui_->RegisterMessageCallback("openFile",
+  web_ui_->RegisterMessageCallback("openFile",
       NewCallback(this, &DownloadsDOMHandler::HandleOpenFile));
 
-  dom_ui_->RegisterMessageCallback("drag",
+  web_ui_->RegisterMessageCallback("drag",
       NewCallback(this, &DownloadsDOMHandler::HandleDrag));
 
-  dom_ui_->RegisterMessageCallback("saveDangerous",
+  web_ui_->RegisterMessageCallback("saveDangerous",
       NewCallback(this, &DownloadsDOMHandler::HandleSaveDangerous));
-  dom_ui_->RegisterMessageCallback("discardDangerous",
+  web_ui_->RegisterMessageCallback("discardDangerous",
       NewCallback(this, &DownloadsDOMHandler::HandleDiscardDangerous));
-  dom_ui_->RegisterMessageCallback("show",
+  web_ui_->RegisterMessageCallback("show",
       NewCallback(this, &DownloadsDOMHandler::HandleShow));
-  dom_ui_->RegisterMessageCallback("togglepause",
+  web_ui_->RegisterMessageCallback("togglepause",
       NewCallback(this, &DownloadsDOMHandler::HandlePause));
-  dom_ui_->RegisterMessageCallback("resume",
+  web_ui_->RegisterMessageCallback("resume",
       NewCallback(this, &DownloadsDOMHandler::HandlePause));
-  dom_ui_->RegisterMessageCallback("remove",
+  web_ui_->RegisterMessageCallback("remove",
       NewCallback(this, &DownloadsDOMHandler::HandleRemove));
-  dom_ui_->RegisterMessageCallback("cancel",
+  web_ui_->RegisterMessageCallback("cancel",
       NewCallback(this, &DownloadsDOMHandler::HandleCancel));
-  dom_ui_->RegisterMessageCallback("clearAll",
+  web_ui_->RegisterMessageCallback("clearAll",
       NewCallback(this, &DownloadsDOMHandler::HandleClearAll));
 }
 
@@ -111,7 +108,7 @@
 
   ListValue results_value;
   results_value.Append(download_util::CreateDownloadItemValue(download, id));
-  dom_ui_->CallJavascriptFunction(L"downloadUpdated", results_value);
+  web_ui_->CallJavascriptFunction(L"downloadUpdated", results_value);
 }
 
 // A download has started or been deleted. Query our DownloadManager for the
@@ -163,7 +160,7 @@
     IconManager* im = g_browser_process->icon_manager();
     SkBitmap* icon = im->LookupIcon(file->GetUserVerifiedFilePath(),
                                     IconLoader::NORMAL);
-    gfx::NativeView view = dom_ui_->tab_contents()->GetNativeView();
+    gfx::NativeView view = web_ui_->tab_contents()->GetNativeView();
     download_util::DragDownload(file, icon, view);
   }
 }
@@ -220,7 +217,7 @@
     results_value.Append(download_util::CreateDownloadItemValue(*it, index));
   }
 
-  dom_ui_->CallJavascriptFunction(L"downloadsList", results_value);
+  web_ui_->CallJavascriptFunction(L"downloadsList", results_value);
 }
 
 void DownloadsDOMHandler::ClearDownloadItems() {
diff --git a/chrome/browser/dom_ui/downloads_dom_handler.h b/chrome/browser/dom_ui/downloads_dom_handler.h
index 5013db5..2e5b3fc 100644
--- a/chrome/browser/dom_ui/downloads_dom_handler.h
+++ b/chrome/browser/dom_ui/downloads_dom_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/scoped_callback_factory.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 
@@ -17,7 +17,7 @@
 
 // The handler for Javascript messages related to the "downloads" view,
 // also observes changes to the download manager.
-class DownloadsDOMHandler : public DOMMessageHandler,
+class DownloadsDOMHandler : public WebUIMessageHandler,
                             public DownloadManager::Observer,
                             public DownloadItem::Observer {
  public:
@@ -26,7 +26,7 @@
 
   void Init();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // DownloadItem::Observer interface
diff --git a/chrome/browser/dom_ui/downloads_ui.cc b/chrome/browser/dom_ui/downloads_ui.cc
index 2ef2656..4f326f4 100644
--- a/chrome/browser/dom_ui/downloads_ui.cc
+++ b/chrome/browser/dom_ui/downloads_ui.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/downloads_ui.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "base/string_piece.h"
 #include "base/threading/thread.h"
@@ -16,11 +14,14 @@
 #include "chrome/browser/dom_ui/downloads_dom_handler.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -123,7 +124,7 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-DownloadsUI::DownloadsUI(TabContents* contents) : DOMUI(contents) {
+DownloadsUI::DownloadsUI(TabContents* contents) : WebUI(contents) {
   DownloadManager* dlm = GetProfile()->GetDownloadManager();
 
   DownloadsDOMHandler* handler = new DownloadsDOMHandler(dlm);
@@ -134,11 +135,7 @@
   DownloadsUIHTMLSource* html_source = new DownloadsUIHTMLSource();
 
   // Set up the chrome://downloads/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/downloads_ui.h b/chrome/browser/dom_ui/downloads_ui.h
index c6f5727..c5afe95 100644
--- a/chrome/browser/dom_ui/downloads_ui.h
+++ b/chrome/browser/dom_ui/downloads_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_DOM_UI_DOWNLOADS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class RefCountedMemory;
 
-class DownloadsUI : public DOMUI {
+class DownloadsUI : public WebUI {
  public:
   explicit DownloadsUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/file_browse_browsertest.cc b/chrome/browser/dom_ui/file_browse_browsertest.cc
index c8d7a1f..c77d87f 100644
--- a/chrome/browser/dom_ui/file_browse_browsertest.cc
+++ b/chrome/browser/dom_ui/file_browse_browsertest.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/task.h"
 #include "base/path_service.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/html_dialog_view.h"
+#include "chrome/browser/ui/views/html_dialog_view.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/url_constants.h"
@@ -89,8 +89,8 @@
     return file_browse_tab_;
   }
 
-  DOMUI* file_browse_ui() {
-    return file_browse_tab_ ? file_browse_tab_->render_manager()->dom_ui() :
+  WebUI* file_browse_ui() {
+    return file_browse_tab_ ? file_browse_tab_->render_manager()->web_ui() :
                               NULL;
   }
 
@@ -119,7 +119,7 @@
   input_file->Click();
 
   observer.WaitForFileBrowseLoad();
-  DOMUI* file_browser_ui = observer.file_browse_ui();
+  WebUI* file_browser_ui = observer.file_browse_ui();
   ASSERT_TRUE(file_browser_ui);
 
   file_browser_ui->CallJavascriptFunction(L"dialogCancelClick");
diff --git a/chrome/browser/dom_ui/filebrowse_ui.cc b/chrome/browser/dom_ui/filebrowse_ui.cc
index 833341c..2b7ba40 100644
--- a/chrome/browser/dom_ui/filebrowse_ui.cc
+++ b/chrome/browser/dom_ui/filebrowse_ui.cc
@@ -1,11 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/filebrowse_ui.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include <algorithm>
+#include <vector>
+
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -22,8 +23,8 @@
 #include "base/weak_ptr.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
 #include "chrome/browser/dom_ui/mediaplayer_ui.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/download/download_util.h"
@@ -48,6 +49,8 @@
 #include "grit/locale_settings.h"
 #include "net/base/escape.h"
 #include "net/url_request/url_request_file_job.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/cros/cros_library.h"
@@ -94,7 +97,7 @@
 
 // The handler for Javascript messages related to the "filebrowse" view.
 class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
-                          public DOMMessageHandler,
+                          public WebUIMessageHandler,
 #if defined(OS_CHROMEOS)
                           public chromeos::MountLibrary::Observer,
 #endif
@@ -114,8 +117,8 @@
       const net::DirectoryLister::DirectoryListerData& data);
   virtual void OnListDone(int error);
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
 #if defined(OS_CHROMEOS)
@@ -126,7 +129,7 @@
 
   // DownloadItem::Observer interface
   virtual void OnDownloadUpdated(DownloadItem* download);
-  virtual void OnDownloadFileCompleted(DownloadItem* download) { }
+  virtual void OnDownloadFileCompleted(DownloadItem* download);
   virtual void OnDownloadOpened(DownloadItem* download) { }
 
   // DownloadManager::Observer interface
@@ -135,25 +138,25 @@
   // Callback for the "getRoots" message.
   void HandleGetRoots(const ListValue* args);
 
-  void GetChildrenForPath(FilePath& path, bool is_refresh);
+  void GetChildrenForPath(const FilePath& path, bool is_refresh);
 
   void OnURLFetchComplete(const URLFetcher* source,
                           const GURL& url,
-                          const URLRequestStatus& status,
+                          const net::URLRequestStatus& status,
                           int response_code,
                           const ResponseCookies& cookies,
                           const std::string& data);
 
   // Callback for the "getChildren" message.
   void HandleGetChildren(const ListValue* args);
- // Callback for the "refreshDirectory" message.
+  // Callback for the "refreshDirectory" message.
   void HandleRefreshDirectory(const ListValue* args);
   void HandleIsAdvancedEnabled(const ListValue* args);
 
   // Callback for the "getMetadata" message.
   void HandleGetMetadata(const ListValue* args);
 
- // Callback for the "openNewWindow" message.
+  // Callback for the "openNewWindow" message.
   void OpenNewFullWindow(const ListValue* args);
   void OpenNewPopupWindow(const ListValue* args);
 
@@ -170,8 +173,8 @@
 
   void HandleDeleteFile(const ListValue* args);
   void HandleCopyFile(const ListValue* value);
-  void CopyFile(const FilePath& src, const FilePath& dest);
-  void DeleteFile(const FilePath& path);
+  void CopyFile(const FilePath& src, const FilePath& dest, TaskProxy* task);
+  void DeleteFile(const FilePath& path, TaskProxy* task);
   void FireDeleteComplete(const FilePath& path);
   void FireCopyComplete(const FilePath& src, const FilePath& dest);
 
@@ -180,6 +183,8 @@
   void HandleCancelDownload(const ListValue* args);
   void HandleAllowDownload(const ListValue* args);
 
+  void CreateNewFolder(const FilePath& path) const;
+
   void ReadInFile();
   void FireUploadComplete();
 
@@ -189,13 +194,16 @@
   void HandleValidateSavePath(const ListValue* args);
 
   // Validate a save path on file thread.
-  void ValidateSavePathOnFileThread(const FilePath& save_path);
+  void ValidateSavePathOnFileThread(const FilePath& save_path, TaskProxy* task);
 
   // Fire save path validation result to JS onValidatedSavePath.
   void FireOnValidatedSavePathOnUIThread(bool valid, const FilePath& save_path);
 
  private:
 
+  // Retrieves downloads from the DownloadManager and updates the page.
+  void UpdateDownloadList();
+
   void OpenNewWindow(const ListValue* args, bool popup);
 
   // Clear all download items and their observers.
@@ -206,6 +214,9 @@
 
   void SendNewDownload(DownloadItem* download);
 
+  bool ValidateSaveDir(const FilePath& save_dir, bool exists) const;
+  bool AccessDisabled(const FilePath& path) const;
+
   scoped_ptr<ListValue> filelist_value_;
   FilePath currentpath_;
   Profile* profile_;
@@ -237,56 +248,71 @@
             const FilePath& path)
       : handler_(handler),
         src_(path) {}
-  void ReadInFileProxy() {
-    if (handler_) {
-      handler_->ReadInFile();
-    }
+
+  // TaskProxy is created on the UI thread, so in some cases,
+  // we need to post back to the UI thread for destruction.
+  void DeleteOnUIThread() {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(this, &TaskProxy::DoNothing));
   }
+
+  void DoNothing() {}
+
+  void ReadInFileProxy() {
+    if (handler_)
+      handler_->ReadInFile();
+    DeleteOnUIThread();
+  }
+
   void DeleteFetcher(URLFetcher* fetch) {
     delete fetch;
   }
+
   void SendPicasawebRequestProxy() {
-    if (handler_) {
+    if (handler_)
       handler_->SendPicasawebRequest();
-    }
+    DeleteOnUIThread();
   }
+
   void FireUploadCompleteProxy() {
-    if (handler_) {
+    if (handler_)
       handler_->FireUploadComplete();
-    }
   }
 
   void DeleteFileProxy() {
-    if (handler_) {
-      handler_->DeleteFile(src_);
-    }
+    if (handler_)
+      handler_->DeleteFile(src_, this);
   }
 
   void CopyFileProxy() {
-    if (handler_) {
-      handler_->CopyFile(src_, dest_);
-    }
+    if (handler_)
+      handler_->CopyFile(src_, dest_, this);
+  }
+
+  void CreateNewFolderProxy() {
+    if (handler_)
+      handler_->CreateNewFolder(src_);
+    DeleteOnUIThread();
   }
 
   void FireDeleteCompleteProxy() {
-    if (handler_) {
+    if (handler_)
       handler_->FireDeleteComplete(src_);
-    }
   }
   void FireCopyCompleteProxy() {
-    if (handler_) {
+    if (handler_)
       handler_->FireCopyComplete(src_, dest_);
-    }
   }
 
   void ValidateSavePathOnFileThread() {
     if (handler_)
-      handler_->ValidateSavePathOnFileThread(src_);
+      handler_->ValidateSavePathOnFileThread(src_, this);
   }
-  void FireOnValidatedSavePathOnUIThread(bool valid,
-                                         const FilePath& save_path) {
+
+  void FireOnValidatedSavePathOnUIThread(bool valid) {
     if (handler_)
-      handler_->FireOnValidatedSavePathOnUIThread(valid, save_path);
+      handler_->FireOnValidatedSavePathOnUIThread(valid, src_);
   }
 
  private:
@@ -408,82 +434,76 @@
   download_manager_->RemoveObserver(this);
   URLFetcher* fetch = fetch_.release();
   if (fetch) {
-    TaskProxy* task = new TaskProxy(AsWeakPtr(), currentpath_);
-    task->AddRef();
+    scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), currentpath_);
     BrowserThread::PostTask(
         BrowserThread::FILE, FROM_HERE,
         NewRunnableMethod(
-            task, &TaskProxy::DeleteFetcher, fetch));
+            task.get(), &TaskProxy::DeleteFetcher, fetch));
   }
 }
 
-DOMMessageHandler* FilebrowseHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* FilebrowseHandler::Attach(WebUI* web_ui) {
   // Create our favicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
-  profile_ = dom_ui->GetProfile();
-  tab_contents_ = dom_ui->tab_contents();
-  return DOMMessageHandler::Attach(dom_ui);
+  profile_ = web_ui->GetProfile();
+  profile_->GetChromeURLDataManager()->AddDataSource(
+      new WebUIFavIconSource(profile_));
+  tab_contents_ = web_ui->tab_contents();
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void FilebrowseHandler::Init() {
   download_manager_ = profile_->GetDownloadManager();
   download_manager_->AddObserver(this);
-  TaskProxy* task = new TaskProxy(AsWeakPtr(), currentpath_);
-  task->AddRef();
-  current_task_ = task;
   static bool sent_request = false;
   if (!sent_request) {
     // If we have not sent a request before, we should do one in order to
     // ensure that we have the correct cookies. This is for uploads.
+    scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), currentpath_);
+    current_task_ = task;
     BrowserThread::PostTask(
         BrowserThread::FILE, FROM_HERE,
         NewRunnableMethod(
-            task, &TaskProxy::SendPicasawebRequestProxy));
+            task.get(), &TaskProxy::SendPicasawebRequestProxy));
     sent_request = true;
   }
 }
 
 void FilebrowseHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getRoots",
+  web_ui_->RegisterMessageCallback("getRoots",
       NewCallback(this, &FilebrowseHandler::HandleGetRoots));
-  dom_ui_->RegisterMessageCallback("getChildren",
+  web_ui_->RegisterMessageCallback("getChildren",
       NewCallback(this, &FilebrowseHandler::HandleGetChildren));
-  dom_ui_->RegisterMessageCallback("getMetadata",
+  web_ui_->RegisterMessageCallback("getMetadata",
       NewCallback(this, &FilebrowseHandler::HandleGetMetadata));
-  dom_ui_->RegisterMessageCallback("openNewPopupWindow",
+  web_ui_->RegisterMessageCallback("openNewPopupWindow",
       NewCallback(this, &FilebrowseHandler::OpenNewPopupWindow));
-  dom_ui_->RegisterMessageCallback("openNewFullWindow",
+  web_ui_->RegisterMessageCallback("openNewFullWindow",
       NewCallback(this, &FilebrowseHandler::OpenNewFullWindow));
-  dom_ui_->RegisterMessageCallback("uploadToPicasaweb",
+  web_ui_->RegisterMessageCallback("uploadToPicasaweb",
       NewCallback(this, &FilebrowseHandler::UploadToPicasaweb));
-  dom_ui_->RegisterMessageCallback("getDownloads",
+  web_ui_->RegisterMessageCallback("getDownloads",
       NewCallback(this, &FilebrowseHandler::HandleGetDownloads));
-  dom_ui_->RegisterMessageCallback("createNewFolder",
+  web_ui_->RegisterMessageCallback("createNewFolder",
       NewCallback(this, &FilebrowseHandler::HandleCreateNewFolder));
-  dom_ui_->RegisterMessageCallback("playMediaFile",
+  web_ui_->RegisterMessageCallback("playMediaFile",
       NewCallback(this, &FilebrowseHandler::PlayMediaFile));
-  dom_ui_->RegisterMessageCallback("enqueueMediaFile",
+  web_ui_->RegisterMessageCallback("enqueueMediaFile",
       NewCallback(this, &FilebrowseHandler::EnqueueMediaFile));
-  dom_ui_->RegisterMessageCallback("pauseToggleDownload",
+  web_ui_->RegisterMessageCallback("pauseToggleDownload",
       NewCallback(this, &FilebrowseHandler::HandlePauseToggleDownload));
-  dom_ui_->RegisterMessageCallback("deleteFile",
+  web_ui_->RegisterMessageCallback("deleteFile",
       NewCallback(this, &FilebrowseHandler::HandleDeleteFile));
-  dom_ui_->RegisterMessageCallback("copyFile",
+  web_ui_->RegisterMessageCallback("copyFile",
       NewCallback(this, &FilebrowseHandler::HandleCopyFile));
-  dom_ui_->RegisterMessageCallback("cancelDownload",
+  web_ui_->RegisterMessageCallback("cancelDownload",
       NewCallback(this, &FilebrowseHandler::HandleCancelDownload));
-  dom_ui_->RegisterMessageCallback("allowDownload",
+  web_ui_->RegisterMessageCallback("allowDownload",
       NewCallback(this, &FilebrowseHandler::HandleAllowDownload));
-  dom_ui_->RegisterMessageCallback("refreshDirectory",
+  web_ui_->RegisterMessageCallback("refreshDirectory",
       NewCallback(this, &FilebrowseHandler::HandleRefreshDirectory));
-  dom_ui_->RegisterMessageCallback("isAdvancedEnabled",
+  web_ui_->RegisterMessageCallback("isAdvancedEnabled",
       NewCallback(this, &FilebrowseHandler::HandleIsAdvancedEnabled));
-  dom_ui_->RegisterMessageCallback("validateSavePath",
+  web_ui_->RegisterMessageCallback("validateSavePath",
       NewCallback(this, &FilebrowseHandler::HandleValidateSavePath));
 }
 
@@ -514,18 +534,18 @@
     LOG(ERROR) << "Unable to get username";
     return;
   }
-  int location = username.find_first_of('@',0);
+  int location = username.find_first_of('@', 0);
   if (location <= 0) {
     LOG(ERROR) << "Username not formatted correctly";
     return;
   }
-  username = username.erase(username.find_first_of('@',0));
+  username = username.erase(username.find_first_of('@', 0));
   std::string picture_url = kPicasawebBaseUrl;
   picture_url += username;
   picture_url += kPicasawebDropBox;
   info_value.SetString("url", picture_url);
   info_value.SetInteger("status_code", upload_response_code_);
-  dom_ui_->CallJavascriptFunction(L"uploadComplete", info_value);
+  web_ui_->CallJavascriptFunction(L"uploadComplete", info_value);
 #endif
 }
 
@@ -535,14 +555,14 @@
                                      const std::string& path) {
   if (evt == chromeos::DISK_REMOVED ||
       evt == chromeos::DISK_CHANGED) {
-    dom_ui_->CallJavascriptFunction(L"rootsChanged");
+    web_ui_->CallJavascriptFunction(L"rootsChanged");
   }
 }
 #endif
 
 void FilebrowseHandler::OnURLFetchComplete(const URLFetcher* source,
                                            const GURL& url,
-                                           const URLRequestStatus& status,
+                                           const net::URLRequestStatus& status,
                                            int response_code,
                                            const ResponseCookies& cookies,
                                            const std::string& data) {
@@ -583,7 +603,6 @@
   page_value->SetString(kPropertyPath, "/media");
   page_value->SetString(kPropertyTitle, "Removeable");
   page_value->SetBoolean(kPropertyDirectory, true);
-
   results_value.Append(page_value);
 #endif
   FilePath default_download_path;
@@ -601,7 +620,7 @@
 
   info_value.SetString("functionCall", "getRoots");
   info_value.SetString(kPropertyPath, "");
-  dom_ui_->CallJavascriptFunction(L"browseFileResult",
+  web_ui_->CallJavascriptFunction(L"browseFileResult",
                                   info_value, results_value);
 }
 
@@ -610,11 +629,20 @@
   std::string path = WideToUTF8(ExtractStringValue(args));
   FilePath currentpath(path);
 
-  if (!file_util::CreateDirectory(currentpath))
-    LOG(ERROR) << "unable to create directory";
+  scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), currentpath);
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      NewRunnableMethod(
+          task.get(), &TaskProxy::CreateNewFolderProxy));
 #endif
 }
 
+void FilebrowseHandler::CreateNewFolder(const FilePath& currentpath) const {
+  if (!ValidateSaveDir(currentpath, false) ||
+      !file_util::CreateDirectory(currentpath))
+    LOG(ERROR) << "Unable to create directory " << currentpath.value();
+}
+
 void FilebrowseHandler::PlayMediaFile(const ListValue* args) {
 #if defined(OS_CHROMEOS)
   std::string url = WideToUTF8(ExtractStringValue(args));
@@ -648,7 +676,7 @@
   DictionaryValue info_value;
   info_value.SetBoolean("enabled", is_enabled);
   info_value.SetBoolean("mpEnabled", mp_enabled);
-  dom_ui_->CallJavascriptFunction(L"enabledResult",
+  web_ui_->CallJavascriptFunction(L"enabledResult",
                                   info_value);
 
 #endif
@@ -666,7 +694,7 @@
 #if defined(OS_CHROMEOS)
   int id;
   ExtractIntegerValue(args, &id);
-  if ((id - 1) >= (int)active_download_items_.size()) {
+  if ((id - 1) >= static_cast<int>(active_download_items_.size())) {
     return;
   }
   DownloadItem* item = active_download_items_[id];
@@ -678,7 +706,7 @@
 #if defined(OS_CHROMEOS)
   int id;
   ExtractIntegerValue(args, &id);
-  if ((id - 1) >= (int)active_download_items_.size()) {
+  if ((id - 1) >= static_cast<int>(active_download_items_.size())) {
     return;
   }
 
@@ -691,7 +719,7 @@
 #if defined(OS_CHROMEOS)
   int id;
   ExtractIntegerValue(args, &id);
-  if ((id - 1) >= (int)active_download_items_.size()) {
+  if ((id - 1) >= static_cast<int>(active_download_items_.size())) {
     return;
   }
   DownloadItem* item = active_download_items_[id];
@@ -758,12 +786,12 @@
     LOG(ERROR) << "Unable to get username";
     return;
   }
-  int location = username.find_first_of('@',0);
+  int location = username.find_first_of('@', 0);
   if (location <= 0) {
     LOG(ERROR) << "Username not formatted correctly";
     return;
   }
-  username = username.erase(username.find_first_of('@',0));
+  username = username.erase(username.find_first_of('@', 0));
   std::string url = kPicasawebUserPrefix;
   url += username;
   url += kPicasawebDefault;
@@ -799,17 +827,17 @@
   current_file_uploaded_ = search_string;
   //  ReadInFile();
   FilePath current_path(search_string);
-  TaskProxy* task = new TaskProxy(AsWeakPtr(), current_path);
-  task->AddRef();
+  scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), current_path);
   current_task_ = task;
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
       NewRunnableMethod(
-          task, &TaskProxy::ReadInFileProxy));
+          task.get(), &TaskProxy::ReadInFileProxy));
 #endif
 }
 
-void FilebrowseHandler::GetChildrenForPath(FilePath& path, bool is_refresh) {
+void FilebrowseHandler::GetChildrenForPath(const FilePath& path,
+                                           bool is_refresh) {
   filelist_value_.reset(new ListValue());
   currentpath_ = path;
 
@@ -823,15 +851,16 @@
 
 #if defined(OS_CHROMEOS)
   // Don't allow listing files in inaccessible dirs.
-  if (net::URLRequestFileJob::AccessDisabled(path))
+  if (AccessDisabled(path))
     return;
-#endif  // OS_CHROMEOS
+#endif
 
   FilePath default_download_path;
   if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
                         &default_download_path)) {
     NOTREACHED();
   }
+
   if (currentpath_ == default_download_path) {
     lister_ = new net::DirectoryLister(currentpath_,
                                        false,
@@ -863,6 +892,14 @@
   if (data.info.filename[0] == '.') {
     return;
   }
+
+  // Suppress .crdownload files.
+  static const char crdownload[] = (".crdownload");
+  static const size_t crdownload_size = arraysize(crdownload);
+  const std::string& filename = data.info.filename;
+  if ((filename.size() > crdownload_size) &&
+      (filename.rfind(crdownload) == (filename.size() - crdownload_size)))
+    return;
 #endif
 
   DictionaryValue* file_value = new DictionaryValue();
@@ -892,19 +929,25 @@
     info_value.SetString("functionCall", "getChildren");
   }
   info_value.SetString(kPropertyPath, currentpath_.value());
-  dom_ui_->CallJavascriptFunction(L"browseFileResult",
+  web_ui_->CallJavascriptFunction(L"browseFileResult",
                                   info_value, *(filelist_value_.get()));
-  SendCurrentDownloads();
 }
 
 void FilebrowseHandler::HandleGetMetadata(const ListValue* args) {
 }
 
 void FilebrowseHandler::HandleGetDownloads(const ListValue* args) {
-  ModelChanged();
+  UpdateDownloadList();
 }
 
 void FilebrowseHandler::ModelChanged() {
+  if (!currentpath_.empty())
+    GetChildrenForPath(currentpath_, true);
+  else
+    UpdateDownloadList();
+}
+
+void FilebrowseHandler::UpdateDownloadList() {
   ClearDownloadItems();
 
   std::vector<DownloadItem*> downloads;
@@ -938,19 +981,21 @@
 void FilebrowseHandler::SendNewDownload(DownloadItem* download) {
   ListValue results_value;
   results_value.Append(download_util::CreateDownloadItemValue(download, -1));
-  dom_ui_->CallJavascriptFunction(L"newDownload", results_value);
+  web_ui_->CallJavascriptFunction(L"newDownload", results_value);
 }
 
-void FilebrowseHandler::DeleteFile(const FilePath& path) {
+void FilebrowseHandler::DeleteFile(const FilePath& path, TaskProxy* task) {
   if (!file_util::Delete(path, true)) {
     LOG(ERROR) << "unable to delete directory";
   }
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(current_task_, &TaskProxy::FireDeleteCompleteProxy));
+      NewRunnableMethod(task, &TaskProxy::FireDeleteCompleteProxy));
 }
 
-void FilebrowseHandler::CopyFile(const FilePath& src, const FilePath& dest) {
+void FilebrowseHandler::CopyFile(const FilePath& src,
+                                 const FilePath& dest,
+                                 TaskProxy* task) {
   if (file_util::DirectoryExists(src)) {
     if (!file_util::CopyDirectory(src, dest, true)) {
       LOG(ERROR) << "unable to copy directory:" << src.value();
@@ -962,7 +1007,7 @@
   }
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(current_task_, &TaskProxy::FireCopyCompleteProxy));
+      NewRunnableMethod(task, &TaskProxy::FireCopyCompleteProxy));
 }
 
 void FilebrowseHandler::HandleDeleteFile(const ListValue* args) {
@@ -971,7 +1016,7 @@
   FilePath currentpath(path);
 
   // Don't allow file deletion in inaccessible dirs.
-  if (net::URLRequestFileJob::AccessDisabled(currentpath))
+  if (AccessDisabled(currentpath))
     return;
 
   for (unsigned int x = 0; x < active_download_items_.size(); x++) {
@@ -984,13 +1029,11 @@
       return;
     }
   }
-  TaskProxy* task = new TaskProxy(AsWeakPtr(), currentpath);
-  task->AddRef();
-  current_task_ = task;
+  scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), currentpath);
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
       NewRunnableMethod(
-          task, &TaskProxy::DeleteFileProxy));
+          task.get(), &TaskProxy::DeleteFileProxy));
 #endif
 }
 
@@ -1008,16 +1051,15 @@
       FilePath DestPath = FilePath(dest);
 
       // Don't allow file copy to inaccessible dirs.
-      if (net::URLRequestFileJob::AccessDisabled(DestPath))
+      if (AccessDisabled(DestPath))
         return;
 
-      TaskProxy* task = new TaskProxy(AsWeakPtr(), SrcPath, DestPath);
-      task->AddRef();
-      current_task_ = task;
+      scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(),
+                                                    SrcPath, DestPath);
       BrowserThread::PostTask(
           BrowserThread::FILE, FROM_HERE,
           NewRunnableMethod(
-              task, &TaskProxy::CopyFileProxy));
+              task.get(), &TaskProxy::CopyFileProxy));
     } else {
       LOG(ERROR) << "Unable to get string";
       return;
@@ -1046,29 +1088,39 @@
 }
 
 void FilebrowseHandler::ValidateSavePathOnFileThread(
-    const FilePath& save_path) {
+    const FilePath& save_path, TaskProxy* task) {
 #if defined(OS_CHROMEOS)
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
+  const bool valid = ValidateSaveDir(save_path.DirName(), true);
+
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(task,
+                        &TaskProxy::FireOnValidatedSavePathOnUIThread,
+                        valid));
+#endif
+}
+
+bool FilebrowseHandler::ValidateSaveDir(const FilePath& save_dir,
+                                        bool exists) const {
+#if defined(OS_CHROMEOS)
   FilePath default_download_path;
   if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
                         &default_download_path)) {
     NOTREACHED();
   }
 
-  // Get containing folder of save_path.
-  FilePath save_dir = save_path.DirName();
-
-  // Valid save path must be inside default download dir.
-  bool valid = default_download_path == save_dir ||
-               file_util::ContainsPath(default_download_path, save_dir);
-
-  scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), save_path);
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(task.get(),
-                        &TaskProxy::FireOnValidatedSavePathOnUIThread,
-                        valid, save_path));
+  // Valid save dir must be inside default download dir.
+  if (default_download_path == save_dir)
+    return true;
+  if (exists) {
+      DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+      return file_util::ContainsPath(default_download_path, save_dir);
+  } else {
+    return default_download_path.IsParent(save_dir);
+  }
 #endif
+  return false;
 }
 
 void FilebrowseHandler::FireOnValidatedSavePathOnUIThread(bool valid,
@@ -1077,7 +1129,7 @@
 
   FundamentalValue valid_value(valid);
   StringValue path_value(save_path.value());
-  dom_ui_->CallJavascriptFunction(L"onValidatedSavePath",
+  web_ui_->CallJavascriptFunction(L"onValidatedSavePath",
       valid_value, path_value);
 }
 
@@ -1091,7 +1143,7 @@
 
   scoped_ptr<DictionaryValue> download_item(
       download_util::CreateDownloadItemValue(download, id));
-  dom_ui_->CallJavascriptFunction(L"downloadUpdated", *download_item.get());
+  web_ui_->CallJavascriptFunction(L"downloadUpdated", *download_item.get());
 }
 
 void FilebrowseHandler::ClearDownloadItems() {
@@ -1110,7 +1162,16 @@
     results_value.Append(download_util::CreateDownloadItemValue(*it, index));
   }
 
-  dom_ui_->CallJavascriptFunction(L"downloadsList", results_value);
+  web_ui_->CallJavascriptFunction(L"downloadsList", results_value);
+}
+
+void FilebrowseHandler::OnDownloadFileCompleted(DownloadItem* download) {
+  GetChildrenForPath(currentpath_, true);
+}
+
+bool FilebrowseHandler::AccessDisabled(const FilePath& path) const {
+  return !ValidateSaveDir(path, false) &&
+        net::URLRequestFileJob::AccessDisabled(path);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1126,12 +1187,7 @@
   FileBrowseUIHTMLSource* html_source = new FileBrowseUIHTMLSource();
 
   // Set up the chrome://filebrowse/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/fileicon_source.cc b/chrome/browser/dom_ui/fileicon_source.cc
index a720df8..78f69fe 100644
--- a/chrome/browser/dom_ui/fileicon_source.cc
+++ b/chrome/browser/dom_ui/fileicon_source.cc
@@ -10,9 +10,9 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/time_format.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
+#include "ui/gfx/codec/png_codec.h"
 
 // The path used in internal URLs to file icon data.
 static const char kFileIconPath[] = "fileicon";
diff --git a/chrome/browser/dom_ui/flags_ui.cc b/chrome/browser/dom_ui/flags_ui.cc
index 76d4bdd..8b14361 100644
--- a/chrome/browser/dom_ui/flags_ui.cc
+++ b/chrome/browser/dom_ui/flags_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "base/values.h"
 #include "chrome/browser/about_flags.h"
@@ -17,6 +15,7 @@
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -24,6 +23,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -69,10 +70,10 @@
   localized_strings.SetString("flagsBlurb", l10n_util::GetStringUTF16(
       IDS_FLAGS_WARNING_TEXT));
   localized_strings.SetString("flagsRestartNotice", l10n_util::GetStringFUTF16(
-      IDS_FLAGS_RESTART_NOTICE,
+      IDS_FLAGS_RELAUNCH_NOTICE,
       l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
   localized_strings.SetString("flagsRestartButton",
-      l10n_util::GetStringUTF16(IDS_FLAGS_RESTART_BUTTON));
+      l10n_util::GetStringUTF16(IDS_FLAGS_RELAUNCH_BUTTON));
   localized_strings.SetString("disable",
       l10n_util::GetStringUTF16(IDS_FLAGS_DISABLE));
   localized_strings.SetString("enable",
@@ -102,12 +103,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // The handler for Javascript messages for the about:flags page.
-class FlagsDOMHandler : public DOMMessageHandler {
+class FlagsDOMHandler : public WebUIMessageHandler {
  public:
   FlagsDOMHandler() {}
   virtual ~FlagsDOMHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callback for the "requestFlagsExperiments" message.
@@ -124,11 +125,11 @@
 };
 
 void FlagsDOMHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("requestFlagsExperiments",
+  web_ui_->RegisterMessageCallback("requestFlagsExperiments",
       NewCallback(this, &FlagsDOMHandler::HandleRequestFlagsExperiments));
-  dom_ui_->RegisterMessageCallback("enableFlagsExperiment",
+  web_ui_->RegisterMessageCallback("enableFlagsExperiment",
       NewCallback(this, &FlagsDOMHandler::HandleEnableFlagsExperimentMessage));
-  dom_ui_->RegisterMessageCallback("restartBrowser",
+  web_ui_->RegisterMessageCallback("restartBrowser",
       NewCallback(this, &FlagsDOMHandler::HandleRestartBrowser));
 }
 
@@ -136,10 +137,10 @@
   DictionaryValue results;
   results.Set("flagsExperiments",
               about_flags::GetFlagsExperimentsData(
-                  dom_ui_->GetProfile()->GetPrefs()));
+                  g_browser_process->local_state()));
   results.SetBoolean("needsRestart",
                      about_flags::IsRestartNeededToCommitChanges());
-  dom_ui_->CallJavascriptFunction(L"returnFlagsExperiments", results);
+  web_ui_->CallJavascriptFunction(L"returnFlagsExperiments", results);
 }
 
 void FlagsDOMHandler::HandleEnableFlagsExperimentMessage(
@@ -155,7 +156,7 @@
     return;
 
   about_flags::SetExperimentEnabled(
-      dom_ui_->GetProfile()->GetPrefs(),
+      g_browser_process->local_state(),
       experiment_internal_name,
       enable_str == "true");
 }
@@ -175,17 +176,13 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-FlagsUI::FlagsUI(TabContents* contents) : DOMUI(contents) {
+FlagsUI::FlagsUI(TabContents* contents) : WebUI(contents) {
   AddMessageHandler((new FlagsDOMHandler())->Attach(this));
 
   FlagsUIHTMLSource* html_source = new FlagsUIHTMLSource();
 
   // Set up the about:flags source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
@@ -195,6 +192,6 @@
 }
 
 // static
-void FlagsUI::RegisterUserPrefs(PrefService* prefs) {
+void FlagsUI::RegisterPrefs(PrefService* prefs) {
   prefs->RegisterListPref(prefs::kEnabledLabsExperiments);
 }
diff --git a/chrome/browser/dom_ui/flags_ui.h b/chrome/browser/dom_ui/flags_ui.h
index 831ffe4..81fe05e 100644
--- a/chrome/browser/dom_ui/flags_ui.h
+++ b/chrome/browser/dom_ui/flags_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,17 +6,17 @@
 #define CHROME_BROWSER_DOM_UI_FLAGS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class PrefService;
 class RefCountedMemory;
 
-class FlagsUI : public DOMUI {
+class FlagsUI : public WebUI {
  public:
   explicit FlagsUI(TabContents* contents);
 
   static RefCountedMemory* GetFaviconResourceBytes();
-  static void RegisterUserPrefs(PrefService* prefs);
+  static void RegisterPrefs(PrefService* prefs);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FlagsUI);
diff --git a/chrome/browser/dom_ui/foreign_session_handler.cc b/chrome/browser/dom_ui/foreign_session_handler.cc
index cdc66a2..77b953a 100644
--- a/chrome/browser/dom_ui/foreign_session_handler.cc
+++ b/chrome/browser/dom_ui/foreign_session_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,6 @@
 #include "chrome/browser/sessions/session_restore.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/url_constants.h"
@@ -34,10 +33,10 @@
 }
 
 void ForeignSessionHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getForeignSessions",
+  web_ui_->RegisterMessageCallback("getForeignSessions",
       NewCallback(this,
       &ForeignSessionHandler::HandleGetForeignSessions));
-  dom_ui_->RegisterMessageCallback("openForeignSession",
+  web_ui_->RegisterMessageCallback("openForeignSession",
       NewCallback(this,
       &ForeignSessionHandler::HandleOpenForeignSession));
 }
@@ -63,7 +62,7 @@
     case NotificationType::FOREIGN_SESSION_DISABLED:
       // Calling foreignSessions with empty list will automatically hide
       // foreign session section.
-      dom_ui_->CallJavascriptFunction(L"foreignSessions", list_value);
+      web_ui_->CallJavascriptFunction(L"foreignSessions", list_value);
       break;
     default:
       NOTREACHED();
@@ -71,7 +70,7 @@
 }
 
 SessionModelAssociator* ForeignSessionHandler::GetModelAssociator() {
-  ProfileSyncService* service = dom_ui_->GetProfile()->GetProfileSyncService();
+  ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
   if (service == NULL)
     return NULL;
   // We only want to set the model associator if there is one, and it is done
@@ -82,7 +81,7 @@
       !service->ShouldPushChanges()) {
     return NULL;
   }
-  return dom_ui_->GetProfile()->GetProfileSyncService()->
+  return web_ui_->GetProfile()->GetProfileSyncService()->
       GetSessionModelAssociator();
 }
 
@@ -126,7 +125,7 @@
     // Give ownership to |session_list|
     session_list.Append(window_list.release());
   }
-  dom_ui_->CallJavascriptFunction(L"foreignSessions", session_list);
+  web_ui_->CallJavascriptFunction(L"foreignSessions", session_list);
 }
 
 void ForeignSessionHandler::HandleOpenForeignSession(
@@ -173,7 +172,7 @@
       LOG(ERROR) << "Failed to load foreign tab.";
       return;
     }
-    SessionRestore::RestoreForeignSessionTab(dom_ui_->GetProfile(), *tab);
+    SessionRestore::RestoreForeignSessionTab(web_ui_->GetProfile(), *tab);
   } else {
     std::vector<SessionWindow*> windows;
     // Note: we don't own the ForeignSessions themselves.
@@ -188,7 +187,7 @@
         ((window_num == kInvalidId) ?
         std::vector<SessionWindow*>::const_iterator(windows.end()) :
         iter_begin+1);
-    SessionRestore::RestoreForeignSessionWindows(dom_ui_->GetProfile(),
+    SessionRestore::RestoreForeignSessionWindows(web_ui_->GetProfile(),
                                                  iter_begin,
                                                  iter_end);
   }
@@ -211,8 +210,8 @@
   NewTabUI::SetURLTitleAndDirection(dictionary, current_navigation.title(),
                                     current_navigation.virtual_url());
   dictionary->SetString("type", "tab");
-  dictionary->SetReal("timestamp",
-                      static_cast<double>(tab.timestamp.ToInternalValue()));
+  dictionary->SetDouble("timestamp",
+                        static_cast<double>(tab.timestamp.ToInternalValue()));
   dictionary->SetInteger("sessionId", tab.tab_id.id());
   return true;
 }
@@ -233,8 +232,8 @@
   if (tab_values->GetSize() == 0)
     return false;
   dictionary->SetString("type", "window");
-  dictionary->SetReal("timestamp",
-                      static_cast<double>(window.timestamp.ToInternalValue()));
+  dictionary->SetDouble("timestamp",
+      static_cast<double>(window.timestamp.ToInternalValue()));
   dictionary->SetInteger("sessionId", window.window_id.id());
   dictionary->Set("tabs", tab_values.release());
   return true;
diff --git a/chrome/browser/dom_ui/foreign_session_handler.h b/chrome/browser/dom_ui/foreign_session_handler.h
index f6c00ec..c1cb9f4 100644
--- a/chrome/browser/dom_ui/foreign_session_handler.h
+++ b/chrome/browser/dom_ui/foreign_session_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include <vector>
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sync/glue/session_model_associator.h"
 #include "chrome/common/notification_observer.h"
@@ -16,10 +16,10 @@
 
 namespace browser_sync {
 
-class ForeignSessionHandler : public DOMMessageHandler,
+class ForeignSessionHandler : public WebUIMessageHandler,
                               public NotificationObserver {
  public:
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   ForeignSessionHandler();
diff --git a/chrome/browser/dom_ui/generic_handler.cc b/chrome/browser/dom_ui/generic_handler.cc
new file mode 100644
index 0000000..d293cfb
--- /dev/null
+++ b/chrome/browser/dom_ui/generic_handler.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/generic_handler.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/disposition_utils.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "googleurl/src/gurl.h"
+
+GenericHandler::GenericHandler() {
+}
+
+GenericHandler::~GenericHandler() {
+}
+
+void GenericHandler::RegisterMessages() {
+  web_ui_->RegisterMessageCallback("navigateToUrl",
+      NewCallback(this, &GenericHandler::HandleNavigateToUrl));
+}
+
+void GenericHandler::HandleNavigateToUrl(const ListValue* args) {
+  std::string url_string;
+  double button;
+  bool alt_key;
+  bool ctrl_key;
+  bool meta_key;
+  bool shift_key;
+
+  CHECK(args->GetString(0, &url_string));
+  CHECK(args->GetDouble(1, &button));
+  CHECK(args->GetBoolean(2, &alt_key));
+  CHECK(args->GetBoolean(3, &ctrl_key));
+  CHECK(args->GetBoolean(4, &meta_key));
+  CHECK(args->GetBoolean(5, &shift_key));
+
+  CHECK(button == 0.0 || button == 1.0);
+  bool middle_button = (button == 1.0);
+
+  WindowOpenDisposition disposition =
+      disposition_utils::DispositionFromClick(middle_button, alt_key, ctrl_key,
+                                              meta_key, shift_key);
+
+  web_ui_->tab_contents()->OpenURL(
+      GURL(url_string), GURL(), disposition, PageTransition::LINK);
+
+  // This may delete us!
+}
diff --git a/chrome/browser/dom_ui/generic_handler.h b/chrome/browser/dom_ui/generic_handler.h
new file mode 100644
index 0000000..3e7b7c5
--- /dev/null
+++ b/chrome/browser/dom_ui/generic_handler.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_GENERIC_HANDLER_H_
+#define CHROME_BROWSER_DOM_UI_GENERIC_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/dom_ui/web_ui.h"
+
+class ListValue;
+
+// A place to add handlers for messages shared across all WebUI pages.
+class GenericHandler : public WebUIMessageHandler {
+ public:
+  GenericHandler();
+  virtual ~GenericHandler();
+
+  // WebUIMessageHandler implementation.
+  virtual void RegisterMessages();
+
+ private:
+  void HandleNavigateToUrl(const ListValue* args);
+
+  DISALLOW_COPY_AND_ASSIGN(GenericHandler);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_GENERIC_HANDLER_H_
diff --git a/chrome/browser/dom_ui/gpu_internals_ui.cc b/chrome/browser/dom_ui/gpu_internals_ui.cc
index 9b93bfb..1dcc3d8 100644
--- a/chrome/browser/dom_ui/gpu_internals_ui.cc
+++ b/chrome/browser/dom_ui/gpu_internals_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/message_loop.h"
@@ -31,6 +29,8 @@
 #include "chrome/browser/net/passive_log_collector.h"
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/platform_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/jstemplate_builder.h"
@@ -39,7 +39,8 @@
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
-
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -60,17 +61,17 @@
 };
 
 // This class receives javascript messages from the renderer.
-// Note that the DOMUI infrastructure runs on the UI thread, therefore all of
+// Note that the WebUI infrastructure runs on the UI thread, therefore all of
 // this class's methods are expected to run on the UI thread.
 class GpuMessageHandler
-    : public DOMMessageHandler,
+    : public WebUIMessageHandler,
       public base::SupportsWeakPtr<GpuMessageHandler> {
  public:
   GpuMessageHandler();
   virtual ~GpuMessageHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Mesages
@@ -79,6 +80,7 @@
   // Submessages dispatched from OnCallAsync
   Value* OnRequestGpuInfo(const ListValue* list);
   Value* OnRequestClientInfo(const ListValue* list);
+  Value* OnRequestLogMessages(const ListValue* list);
 
   // Executes the javascript function |function_name| in the renderer, passing
   // it the argument |value|.
@@ -137,9 +139,9 @@
 
 GpuMessageHandler::~GpuMessageHandler() {}
 
-DOMMessageHandler* GpuMessageHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* GpuMessageHandler::Attach(WebUI* web_ui) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
+  WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
   return result;
 }
 
@@ -147,7 +149,7 @@
 void GpuMessageHandler::RegisterMessages() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "callAsync",
       NewCallback(this, &GpuMessageHandler::OnCallAsync));
 }
@@ -180,6 +182,8 @@
     ret = OnRequestGpuInfo(submessageArgs);
   } else if (submessage == "requestClientInfo") {
     ret = OnRequestClientInfo(submessageArgs);
+  } else if (submessage == "requestLogMessages") {
+    ret = OnRequestLogMessages(submessageArgs);
   } else {  // unrecognized submessage
     NOTREACHED();
     delete submessageArgs;
@@ -189,12 +193,12 @@
 
   // call BrowserBridge.onCallAsyncReply with result
   if (ret) {
-    dom_ui_->CallJavascriptFunction(L"browserBridge.onCallAsyncReply",
+    web_ui_->CallJavascriptFunction(L"browserBridge.onCallAsyncReply",
         *requestId,
         *ret);
     delete ret;
   } else {
-    dom_ui_->CallJavascriptFunction(L"browserBridge.onCallAsyncReply",
+    web_ui_->CallJavascriptFunction(L"browserBridge.onCallAsyncReply",
         *requestId);
   }
 }
@@ -280,25 +284,41 @@
       base::StringPrintf("0x%04x", gpu_info.vendor_id())));
   basic_info->Append(NewDescriptionValuePair("Device Id",
       base::StringPrintf("0x%04x", gpu_info.device_id())));
+  basic_info->Append(NewDescriptionValuePair("Driver vendor",
+      gpu_info.driver_vendor()));
   basic_info->Append(NewDescriptionValuePair("Driver version",
-      WideToASCII(gpu_info.driver_version()).c_str()));
+      gpu_info.driver_version()));
   basic_info->Append(NewDescriptionValuePair("Pixel shader version",
       VersionNumberToString(gpu_info.pixel_shader_version())));
   basic_info->Append(NewDescriptionValuePair("Vertex shader version",
       VersionNumberToString(gpu_info.vertex_shader_version())));
   basic_info->Append(NewDescriptionValuePair("GL version",
       VersionNumberToString(gpu_info.gl_version())));
+  basic_info->Append(NewDescriptionValuePair("GL_VENDOR",
+      gpu_info.gl_vendor()));
+  basic_info->Append(NewDescriptionValuePair("GL_RENDERER",
+      gpu_info.gl_renderer()));
+  basic_info->Append(NewDescriptionValuePair("GL_VERSION",
+      gpu_info.gl_version_string()));
+  basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS",
+      gpu_info.gl_extensions()));
 
   DictionaryValue* info = new DictionaryValue();
   info->Set("basic_info", basic_info);
 
-  if (gpu_info.progress() == GPUInfo::kPartial) {
-    info->SetString("progress", "partial");
+  if (gpu_info.level() == GPUInfo::kPartial) {
+    info->SetString("level", "partial");
+  } else if (gpu_info.level() == GPUInfo::kCompleting) {
+    info->SetString("level", "completing");
+  } else if (gpu_info.level() == GPUInfo::kComplete) {
+    info->SetString("level", "complete");
   } else {
-    info->SetString("progress", "complete");
+    DCHECK(false) << "Unrecognized GPUInfo::Level value";
+    info->SetString("level", "");
   }
+
 #if defined(OS_WIN)
-  if (gpu_info.progress() == GPUInfo::kComplete) {
+  if (gpu_info.level() == GPUInfo::kComplete) {
     ListValue* dx_info = DxDiagNodeToList(gpu_info.dx_diagnostics());
     info->Set("diagnostics", dx_info);
   }
@@ -314,37 +334,39 @@
   GPUInfo gpu_info = GpuProcessHostUIShim::GetInstance()->gpu_info();
 
   std::string html;
-  if (gpu_info.progress() != GPUInfo::kComplete) {
-    GpuProcessHostUIShim::GetInstance()->CollectGraphicsInfoAsynchronously();
+  if (gpu_info.level() != GPUInfo::kComplete) {
+    GpuProcessHostUIShim::GetInstance()->CollectGraphicsInfoAsynchronously(
+        GPUInfo::kComplete);
   }
 
-  if (gpu_info.progress() != GPUInfo::kUninitialized) {
+  if (gpu_info.level() != GPUInfo::kUninitialized) {
     return GpuInfoToDict(gpu_info);
   } else {
     return NULL;
   }
 }
 
+Value* GpuMessageHandler::OnRequestLogMessages(const ListValue*) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  return GpuProcessHostUIShim::GetInstance()->logMessages();
+}
+
 }  // namespace
 
 
+
 ////////////////////////////////////////////////////////////////////////////////
 //
 // GpuInternalsUI
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-GpuInternalsUI::GpuInternalsUI(TabContents* contents) : DOMUI(contents) {
+GpuInternalsUI::GpuInternalsUI(TabContents* contents) : WebUI(contents) {
   AddMessageHandler((new GpuMessageHandler())->Attach(this));
 
   GpuHTMLSource* html_source = new GpuHTMLSource();
 
   // Set up the chrome://gpu/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
diff --git a/chrome/browser/dom_ui/gpu_internals_ui.h b/chrome/browser/dom_ui/gpu_internals_ui.h
index 8b45692..1930827 100644
--- a/chrome/browser/dom_ui/gpu_internals_ui.h
+++ b/chrome/browser/dom_ui/gpu_internals_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_DOM_UI_GPU_INTERNALS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-class GpuInternalsUI : public DOMUI {
+class GpuInternalsUI : public WebUI {
  public:
   explicit GpuInternalsUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/history2_ui.cc b/chrome/browser/dom_ui/history2_ui.cc
index 89b3b7c..ceb754f 100644
--- a/chrome/browser/dom_ui/history2_ui.cc
+++ b/chrome/browser/dom_ui/history2_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,8 +7,6 @@
 #include <algorithm>
 #include <set>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/i18n/time_formatting.h"
 #include "base/message_loop.h"
@@ -22,7 +20,7 @@
 #include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/profiles/profile.h"
@@ -34,13 +32,14 @@
 #include "chrome/common/notification_source.h"
 #include "chrome/common/time_format.h"
 #include "chrome/common/url_constants.h"
-#include "net/base/escape.h"
-
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Maximum number of search results to return in a given search. We should
 // eventually remove this.
@@ -128,29 +127,26 @@
   cancelable_delete_consumer_.CancelAllRequests();
 }
 
-DOMMessageHandler* BrowsingHistoryHandler2::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* BrowsingHistoryHandler2::Attach(WebUI* web_ui) {
   // Create our favicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
+  Profile* profile = web_ui->GetProfile();
+  profile->GetChromeURLDataManager()->AddDataSource(
+      new WebUIFavIconSource(profile));
 
   // Get notifications when history is cleared.
   registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED,
-      Source<Profile>(dom_ui->GetProfile()->GetOriginalProfile()));
-  return DOMMessageHandler::Attach(dom_ui);
+      Source<Profile>(web_ui->GetProfile()->GetOriginalProfile()));
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void BrowsingHistoryHandler2::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getHistory",
+  web_ui_->RegisterMessageCallback("getHistory",
       NewCallback(this, &BrowsingHistoryHandler2::HandleGetHistory));
-  dom_ui_->RegisterMessageCallback("searchHistory",
+  web_ui_->RegisterMessageCallback("searchHistory",
       NewCallback(this, &BrowsingHistoryHandler2::HandleSearchHistory));
-  dom_ui_->RegisterMessageCallback("removeURLsOnOneDay",
+  web_ui_->RegisterMessageCallback("removeURLsOnOneDay",
       NewCallback(this, &BrowsingHistoryHandler2::HandleRemoveURLsOnOneDay));
-  dom_ui_->RegisterMessageCallback("clearBrowsingData",
+  web_ui_->RegisterMessageCallback("clearBrowsingData",
       NewCallback(this, &BrowsingHistoryHandler2::HandleClearBrowsingData));
 }
 
@@ -173,7 +169,7 @@
   search_text_ = string16();
 
   HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   hs->QueryHistory(search_text_,
       options,
       &cancelable_search_consumer_,
@@ -198,7 +194,7 @@
   // Need to remember the query string for our results.
   search_text_ = query;
   HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   hs->QueryHistory(search_text_,
       options,
       &cancelable_search_consumer_,
@@ -207,7 +203,7 @@
 
 void BrowsingHistoryHandler2::HandleRemoveURLsOnOneDay(const ListValue* args) {
   if (cancelable_delete_consumer_.HasPendingRequests()) {
-    dom_ui_->CallJavascriptFunction(L"deleteFailed");
+    web_ui_->CallJavascriptFunction(L"deleteFailed");
     return;
   }
 
@@ -235,7 +231,7 @@
   }
 
   HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   hs->ExpireHistoryBetween(
       urls, begin_time, end_time, &cancelable_delete_consumer_,
       NewCallback(this, &BrowsingHistoryHandler2::RemoveComplete));
@@ -244,7 +240,7 @@
 void BrowsingHistoryHandler2::HandleClearBrowsingData(const ListValue* args) {
   // TODO(beng): This is an improper direct dependency on Browser. Route this
   // through some sort of delegate.
-  Browser* browser = BrowserList::FindBrowserWithProfile(dom_ui_->GetProfile());
+  Browser* browser = BrowserList::FindBrowserWithProfile(web_ui_->GetProfile());
   if (browser)
     browser->OpenClearBrowsingDataDialog();
 }
@@ -292,7 +288,7 @@
       page_value->SetString("snippet", page.snippet().text());
     }
     page_value->SetBoolean("starred",
-        dom_ui_->GetProfile()->GetBookmarkModel()->IsBookmarked(page.url()));
+        web_ui_->GetProfile()->GetBookmarkModel()->IsBookmarked(page.url()));
     results_value.Append(page_value);
   }
 
@@ -300,12 +296,12 @@
   info_value.SetString("term", search_text_);
   info_value.SetBoolean("finished", results->reached_beginning());
 
-  dom_ui_->CallJavascriptFunction(L"historyResult", info_value, results_value);
+  web_ui_->CallJavascriptFunction(L"historyResult", info_value, results_value);
 }
 
 void BrowsingHistoryHandler2::RemoveComplete() {
   // Some Visits were deleted from history. Reload the list.
-  dom_ui_->CallJavascriptFunction(L"deleteComplete");
+  web_ui_->CallJavascriptFunction(L"deleteComplete");
 }
 
 void BrowsingHistoryHandler2::ExtractSearchHistoryArguments(
@@ -386,7 +382,7 @@
   }
 
   // Some URLs were deleted from history. Reload the list.
-  dom_ui_->CallJavascriptFunction(L"historyDeleted");
+  web_ui_->CallJavascriptFunction(L"historyDeleted");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -395,18 +391,13 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-HistoryUI2::HistoryUI2(TabContents* contents) : DOMUI(contents) {
+HistoryUI2::HistoryUI2(TabContents* contents) : WebUI(contents) {
   AddMessageHandler((new BrowsingHistoryHandler2())->Attach(this));
 
   HistoryUIHTMLSource2* html_source = new HistoryUIHTMLSource2();
 
   // Set up the chrome://history2/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/history2_ui.h b/chrome/browser/dom_ui/history2_ui.h
index a9e1d26..9eda410 100644
--- a/chrome/browser/dom_ui/history2_ui.h
+++ b/chrome/browser/dom_ui/history2_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 
 #include "base/string16.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/common/notification_registrar.h"
@@ -39,14 +39,14 @@
 };
 
 // The handler for Javascript messages related to the "history" view.
-class BrowsingHistoryHandler2 : public DOMMessageHandler,
+class BrowsingHistoryHandler2 : public WebUIMessageHandler,
                                 public NotificationObserver {
  public:
   BrowsingHistoryHandler2();
   virtual ~BrowsingHistoryHandler2();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback for the "getHistory" message.
@@ -96,7 +96,7 @@
   DISALLOW_COPY_AND_ASSIGN(BrowsingHistoryHandler2);
 };
 
-class HistoryUI2 : public DOMUI {
+class HistoryUI2 : public WebUI {
  public:
   explicit HistoryUI2(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/history_ui.cc b/chrome/browser/dom_ui/history_ui.cc
index c599a76..680ada9 100644
--- a/chrome/browser/dom_ui/history_ui.cc
+++ b/chrome/browser/dom_ui/history_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,8 +7,6 @@
 #include <algorithm>
 #include <set>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/i18n/time_formatting.h"
 #include "base/message_loop.h"
@@ -22,7 +20,7 @@
 #include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/profiles/profile.h"
@@ -34,13 +32,14 @@
 #include "chrome/common/notification_source.h"
 #include "chrome/common/time_format.h"
 #include "chrome/common/url_constants.h"
-#include "net/base/escape.h"
-
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Maximum number of search results to return in a given search. We should
 // eventually remove this.
@@ -128,29 +127,26 @@
   cancelable_delete_consumer_.CancelAllRequests();
 }
 
-DOMMessageHandler* BrowsingHistoryHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* BrowsingHistoryHandler::Attach(WebUI* web_ui) {
   // Create our favicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
+  Profile* profile = web_ui->GetProfile();
+  profile->GetChromeURLDataManager()->AddDataSource(
+      new WebUIFavIconSource(profile));
 
   // Get notifications when history is cleared.
   registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED,
-      Source<Profile>(dom_ui->GetProfile()->GetOriginalProfile()));
-  return DOMMessageHandler::Attach(dom_ui);
+      Source<Profile>(profile->GetOriginalProfile()));
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void BrowsingHistoryHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getHistory",
+  web_ui_->RegisterMessageCallback("getHistory",
       NewCallback(this, &BrowsingHistoryHandler::HandleGetHistory));
-  dom_ui_->RegisterMessageCallback("searchHistory",
+  web_ui_->RegisterMessageCallback("searchHistory",
       NewCallback(this, &BrowsingHistoryHandler::HandleSearchHistory));
-  dom_ui_->RegisterMessageCallback("removeURLsOnOneDay",
+  web_ui_->RegisterMessageCallback("removeURLsOnOneDay",
       NewCallback(this, &BrowsingHistoryHandler::HandleRemoveURLsOnOneDay));
-  dom_ui_->RegisterMessageCallback("clearBrowsingData",
+  web_ui_->RegisterMessageCallback("clearBrowsingData",
       NewCallback(this, &BrowsingHistoryHandler::HandleClearBrowsingData));
 }
 
@@ -173,7 +169,7 @@
   search_text_ = string16();
 
   HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   hs->QueryHistory(search_text_,
       options,
       &cancelable_search_consumer_,
@@ -198,7 +194,7 @@
   // Need to remember the query string for our results.
   search_text_ = query;
   HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   hs->QueryHistory(search_text_,
       options,
       &cancelable_search_consumer_,
@@ -207,7 +203,7 @@
 
 void BrowsingHistoryHandler::HandleRemoveURLsOnOneDay(const ListValue* args) {
   if (cancelable_delete_consumer_.HasPendingRequests()) {
-    dom_ui_->CallJavascriptFunction(L"deleteFailed");
+    web_ui_->CallJavascriptFunction(L"deleteFailed");
     return;
   }
 
@@ -235,7 +231,7 @@
   }
 
   HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   hs->ExpireHistoryBetween(
       urls, begin_time, end_time, &cancelable_delete_consumer_,
       NewCallback(this, &BrowsingHistoryHandler::RemoveComplete));
@@ -244,7 +240,7 @@
 void BrowsingHistoryHandler::HandleClearBrowsingData(const ListValue* args) {
   // TODO(beng): This is an improper direct dependency on Browser. Route this
   // through some sort of delegate.
-  Browser* browser = BrowserList::FindBrowserWithProfile(dom_ui_->GetProfile());
+  Browser* browser = BrowserList::FindBrowserWithProfile(web_ui_->GetProfile());
   if (browser)
     browser->OpenClearBrowsingDataDialog();
 }
@@ -292,7 +288,7 @@
       page_value->SetString("snippet", page.snippet().text());
     }
     page_value->SetBoolean("starred",
-        dom_ui_->GetProfile()->GetBookmarkModel()->IsBookmarked(page.url()));
+        web_ui_->GetProfile()->GetBookmarkModel()->IsBookmarked(page.url()));
     results_value.Append(page_value);
   }
 
@@ -300,12 +296,12 @@
   info_value.SetString("term", search_text_);
   info_value.SetBoolean("finished", results->reached_beginning());
 
-  dom_ui_->CallJavascriptFunction(L"historyResult", info_value, results_value);
+  web_ui_->CallJavascriptFunction(L"historyResult", info_value, results_value);
 }
 
 void BrowsingHistoryHandler::RemoveComplete() {
   // Some Visits were deleted from history. Reload the list.
-  dom_ui_->CallJavascriptFunction(L"deleteComplete");
+  web_ui_->CallJavascriptFunction(L"deleteComplete");
 }
 
 void BrowsingHistoryHandler::ExtractSearchHistoryArguments(
@@ -374,7 +370,7 @@
   }
 
   // Some URLs were deleted from history. Reload the list.
-  dom_ui_->CallJavascriptFunction(L"historyDeleted");
+  web_ui_->CallJavascriptFunction(L"historyDeleted");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -383,18 +379,13 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-HistoryUI::HistoryUI(TabContents* contents) : DOMUI(contents) {
+HistoryUI::HistoryUI(TabContents* contents) : WebUI(contents) {
   AddMessageHandler((new BrowsingHistoryHandler())->Attach(this));
 
   HistoryUIHTMLSource* html_source = new HistoryUIHTMLSource();
 
   // Set up the chrome://history/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/history_ui.h b/chrome/browser/dom_ui/history_ui.h
index f31a9d8..f1788bd 100644
--- a/chrome/browser/dom_ui/history_ui.h
+++ b/chrome/browser/dom_ui/history_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 
 #include "base/string16.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/common/notification_registrar.h"
@@ -35,14 +35,14 @@
 };
 
 // The handler for Javascript messages related to the "history" view.
-class BrowsingHistoryHandler : public DOMMessageHandler,
+class BrowsingHistoryHandler : public WebUIMessageHandler,
                                public NotificationObserver {
  public:
   BrowsingHistoryHandler();
   virtual ~BrowsingHistoryHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback for the "getHistory" message.
@@ -92,7 +92,7 @@
   DISALLOW_COPY_AND_ASSIGN(BrowsingHistoryHandler);
 };
 
-class HistoryUI : public DOMUI {
+class HistoryUI : public WebUI {
  public:
   explicit HistoryUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc
index 6f8d825..4a41b83 100644
--- a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc
+++ b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -96,12 +96,6 @@
   return true;
 }
 
-void HtmlDialogTabContentsDelegate::URLStarredChanged(TabContents* source,
-                                                      bool starred) {
-  // We don't have a visible star to click in the window.
-  NOTREACHED();
-}
-
 void HtmlDialogTabContentsDelegate::UpdateTargetURL(TabContents* source,
                                                     const GURL& url) {
   // Ignored.
diff --git a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h
index c6ec732..4642fdd 100644
--- a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h
+++ b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -52,7 +52,6 @@
   virtual void LoadingStateChanged(TabContents* source);
   virtual void CloseContents(TabContents* source);
   virtual bool IsPopup(const TabContents* source) const;
-  virtual void URLStarredChanged(TabContents* source, bool starred);
   virtual void UpdateTargetURL(TabContents* source, const GURL& url);
   virtual bool ShouldAddNavigationToHistory(
       const history::HistoryAddPageArgs& add_page_args,
diff --git a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc
index d8af35d..e1c7f34 100644
--- a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc
+++ b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,10 +16,10 @@
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/test_browser_window.h"
 #include "chrome/test/testing_profile.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/rect.h"
 
 namespace {
 
@@ -67,10 +67,6 @@
   test_tab_contents_delegate_->ActivateContents(NULL);
   test_tab_contents_delegate_->LoadingStateChanged(NULL);
   test_tab_contents_delegate_->CloseContents(NULL);
-  // URLStarredChanged() calls NOTREACHED() which immediately crashes.
-  // Death tests take too long for unit_test tests on OS X and
-  // there's http://code.google.com/p/chromium/issues/detail?id=24885 on
-  // death tests on Windows so we simply don't call it.
   test_tab_contents_delegate_->UpdateTargetURL(NULL, GURL());
   test_tab_contents_delegate_->MoveContents(NULL, gfx::Rect());
   test_tab_contents_delegate_->ToolbarSizeChanged(NULL, false);
diff --git a/chrome/browser/dom_ui/html_dialog_ui.cc b/chrome/browser/dom_ui/html_dialog_ui.cc
index fbea1f6..afe66e8 100644
--- a/chrome/browser/dom_ui/html_dialog_ui.cc
+++ b/chrome/browser/dom_ui/html_dialog_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #include "base/callback.h"
 #include "base/lazy_instance.h"
 #include "base/values.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/common/bindings_policy.h"
@@ -15,18 +15,18 @@
 static base::LazyInstance<PropertyAccessor<HtmlDialogUIDelegate*> >
     g_html_dialog_ui_property_accessor(base::LINKER_INITIALIZED);
 
-HtmlDialogUI::HtmlDialogUI(TabContents* tab_contents) : DOMUI(tab_contents) {
+HtmlDialogUI::HtmlDialogUI(TabContents* tab_contents) : WebUI(tab_contents) {
 }
 
 HtmlDialogUI::~HtmlDialogUI() {
   // Don't unregister our property. During the teardown of the TabContents,
   // this will be deleted, but the TabContents will already be destroyed.
   //
-  // This object is owned indirectly by the TabContents. DOMUIs can change, so
-  // it's scary if this DOMUI is changed out and replaced with something else,
+  // This object is owned indirectly by the TabContents. WebUIs can change, so
+  // it's scary if this WebUI is changed out and replaced with something else,
   // since the property will still point to the old delegate. But the delegate
   // is itself the owner of the TabContents for a dialog so will be in scope,
-  // and the HTML dialogs won't swap DOMUIs anyway since they don't navigate.
+  // and the HTML dialogs won't swap WebUIs anyway since they don't navigate.
 }
 
 // static
@@ -45,17 +45,17 @@
 
   // Pass the arguments to the renderer supplied by the delegate.
   std::string dialog_args;
-  std::vector<DOMMessageHandler*> handlers;
+  std::vector<WebUIMessageHandler*> handlers;
   HtmlDialogUIDelegate** delegate = GetPropertyAccessor().GetProperty(
       tab_contents()->property_bag());
   if (delegate) {
     dialog_args = (*delegate)->GetDialogArgs();
-    (*delegate)->GetDOMMessageHandlers(&handlers);
+    (*delegate)->GetWebUIMessageHandlers(&handlers);
   }
 
-  if (0 != (bindings_ & BindingsPolicy::DOM_UI))
-    render_view_host->SetDOMUIProperty("dialogArguments", dialog_args);
-  for (std::vector<DOMMessageHandler*>::iterator it = handlers.begin();
+  if (0 != (bindings_ & BindingsPolicy::WEB_UI))
+    render_view_host->SetWebUIProperty("dialogArguments", dialog_args);
+  for (std::vector<WebUIMessageHandler*>::iterator it = handlers.begin();
        it != handlers.end(); ++it) {
     (*it)->Attach(this);
     AddMessageHandler(*it);
@@ -67,17 +67,17 @@
       tab_contents()->property_bag());
   if (delegate) {
     (*delegate)->OnDialogClosed(
-        dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+        web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
   }
 }
 
 ExternalHtmlDialogUI::ExternalHtmlDialogUI(TabContents* tab_contents)
     : HtmlDialogUI(tab_contents) {
-  // Non-file based UI needs to not have access to the DOM UI bindings
+  // Non-file based UI needs to not have access to the Web UI bindings
   // for security reasons. The code hosting the dialog should provide
   // dialog specific functionality through other bindings and methods
   // that are scoped in duration to the dialogs existence.
-  bindings_ &= ~BindingsPolicy::DOM_UI;
+  bindings_ &= ~BindingsPolicy::WEB_UI;
 }
 
 ExternalHtmlDialogUI::~ExternalHtmlDialogUI() {
diff --git a/chrome/browser/dom_ui/html_dialog_ui.h b/chrome/browser/dom_ui/html_dialog_ui.h
index 5cd9eed..d682fa2 100644
--- a/chrome/browser/dom_ui/html_dialog_ui.h
+++ b/chrome/browser/dom_ui/html_dialog_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include <string>
 #include <vector>
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/common/property_bag.h"
 #include "googleurl/src/gurl.h"
 
@@ -31,12 +31,12 @@
   // Get the HTML file path for the content to load in the dialog.
   virtual GURL GetDialogContentURL() const = 0;
 
-  // Get DOMMessageHandler objects to handle messages from the HTML/JS page.
+  // Get WebUIMessageHandler objects to handle messages from the HTML/JS page.
   // The handlers are used to send and receive messages from the page while it
-  // is still open.  Ownership of each handler is taken over by the DOMUI
+  // is still open.  Ownership of each handler is taken over by the WebUI
   // hosting the page.
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const = 0;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const = 0;
 
   // Get the size of the dialog.
   virtual void GetDialogSize(gfx::Size* size) const = 0;
@@ -67,15 +67,15 @@
 
 // Displays file URL contents inside a modal HTML dialog.
 //
-// This application really should not use TabContents + DOMUI. It should instead
+// This application really should not use TabContents + WebUI. It should instead
 // just embed a RenderView in a dialog and be done with it.
 //
-// Before loading a URL corresponding to this DOMUI, the caller should set its
-// delegate as a property on the TabContents. This DOMUI will pick it up from
+// Before loading a URL corresponding to this WebUI, the caller should set its
+// delegate as a property on the TabContents. This WebUI will pick it up from
 // there and call it back. This is a bit of a hack to allow the dialog to pass
-// its delegate to the DOM UI without having nasty accessors on the TabContents.
+// its delegate to the Web UI without having nasty accessors on the TabContents.
 // The correct design using RVH directly would avoid all of this.
-class HtmlDialogUI : public DOMUI {
+class HtmlDialogUI : public WebUI {
  public:
   struct HtmlDialogParams {
     // The URL for the content that will be loaded in the dialog.
@@ -97,7 +97,7 @@
   static PropertyAccessor<HtmlDialogUIDelegate*>& GetPropertyAccessor();
 
  private:
-  // DOMUI overrides.
+  // WebUI
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
 
   // JS message handler.
diff --git a/chrome/browser/dom_ui/keyboard_ui.cc b/chrome/browser/dom_ui/keyboard_ui.cc
index 9fddd04..a85b92d 100644
--- a/chrome/browser/dom_ui/keyboard_ui.cc
+++ b/chrome/browser/dom_ui/keyboard_ui.cc
@@ -1,30 +1,27 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/keyboard_ui.h"
 
-#include "app/resource_bundle.h"
 #include "base/ref_counted_memory.h"
 #include "base/singleton.h"
 #include "base/string_piece.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // KeyboardUI
 
 KeyboardUI::KeyboardUI(TabContents* contents)
-    : DOMUI(contents) {
+    : WebUI(contents) {
   KeyboardHTMLSource* html_source = new KeyboardHTMLSource();
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 KeyboardUI::~KeyboardUI() {
diff --git a/chrome/browser/dom_ui/keyboard_ui.h b/chrome/browser/dom_ui/keyboard_ui.h
index abb23d3..0448407 100644
--- a/chrome/browser/dom_ui/keyboard_ui.h
+++ b/chrome/browser/dom_ui/keyboard_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,13 +8,13 @@
 
 #include <string>
 
-#include "chrome/browser/dom_ui/dom_ui.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class Profile;
 
 // The TabContents used for the keyboard page.
-class KeyboardUI : public DOMUI {
+class KeyboardUI : public WebUI {
  public:
   explicit KeyboardUI(TabContents* manager);
   ~KeyboardUI();
diff --git a/chrome/browser/dom_ui/mediaplayer_ui.cc b/chrome/browser/dom_ui/mediaplayer_ui.cc
index 2f1cec7..23fc229 100644
--- a/chrome/browser/dom_ui/mediaplayer_ui.cc
+++ b/chrome/browser/dom_ui/mediaplayer_ui.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/mediaplayer_ui.h"
 
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -18,7 +17,7 @@
 #include "base/weak_ptr.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/history/history_types.h"
@@ -42,6 +41,7 @@
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request_job.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/frame/panel_browser_view.h"
@@ -80,7 +80,7 @@
 };
 
 // The handler for Javascript messages related to the "mediaplayer" view.
-class MediaplayerHandler : public DOMMessageHandler,
+class MediaplayerHandler : public WebUIMessageHandler,
                            public base::SupportsWeakPtr<MediaplayerHandler> {
  public:
 
@@ -101,8 +101,8 @@
   // Init work after Attach.
   void Init(bool is_playlist, TabContents* contents);
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback for the "currentOffsetChanged" message.
@@ -207,16 +207,13 @@
 MediaplayerHandler::~MediaplayerHandler() {
 }
 
-DOMMessageHandler* MediaplayerHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* MediaplayerHandler::Attach(WebUI* web_ui) {
   // Create our favicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
+  Profile* profile = web_ui->GetProfile();
+  profile->GetChromeURLDataManager()->AddDataSource(
+      new WebUIFavIconSource(profile));
 
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void MediaplayerHandler::Init(bool is_playlist, TabContents* contents) {
@@ -229,19 +226,19 @@
 }
 
 void MediaplayerHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("currentOffsetChanged",
+  web_ui_->RegisterMessageCallback("currentOffsetChanged",
       NewCallback(this, &MediaplayerHandler::HandleCurrentOffsetChanged));
-  dom_ui_->RegisterMessageCallback("playbackError",
+  web_ui_->RegisterMessageCallback("playbackError",
       NewCallback(this, &MediaplayerHandler::HandlePlaybackError));
-  dom_ui_->RegisterMessageCallback("getCurrentPlaylist",
+  web_ui_->RegisterMessageCallback("getCurrentPlaylist",
       NewCallback(this, &MediaplayerHandler::HandleGetCurrentPlaylist));
-  dom_ui_->RegisterMessageCallback("togglePlaylist",
+  web_ui_->RegisterMessageCallback("togglePlaylist",
       NewCallback(this, &MediaplayerHandler::HandleTogglePlaylist));
-  dom_ui_->RegisterMessageCallback("setCurrentPlaylistOffset",
+  web_ui_->RegisterMessageCallback("setCurrentPlaylistOffset",
       NewCallback(this, &MediaplayerHandler::HandleSetCurrentPlaylistOffset));
-  dom_ui_->RegisterMessageCallback("toggleFullscreen",
+  web_ui_->RegisterMessageCallback("toggleFullscreen",
       NewCallback(this, &MediaplayerHandler::HandleToggleFullscreen));
-  dom_ui_->RegisterMessageCallback("showPlaylist",
+  web_ui_->RegisterMessageCallback("showPlaylist",
       NewCallback(this, &MediaplayerHandler::HandleShowPlaylist));
 }
 
@@ -288,7 +285,7 @@
   info_value.SetString(kPropertyPath, path);
   info_value.SetBoolean(kPropertyForce, force);
   info_value.SetInteger(kPropertyOffset, offset);
-  dom_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
+  web_ui_->CallJavascriptFunction(L"playlistChanged", info_value, urls);
 }
 
 void MediaplayerHandler::SetCurrentPlaylistOffset(int offset) {
@@ -597,7 +594,7 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-MediaplayerUI::MediaplayerUI(TabContents* contents) : DOMUI(contents) {
+MediaplayerUI::MediaplayerUI(TabContents* contents) : WebUI(contents) {
   const GURL& url = contents->GetURL();
   bool is_playlist = (url.ref() == "playlist");
   MediaplayerHandler* handler = new MediaplayerHandler(is_playlist);
@@ -612,10 +609,5 @@
       new MediaplayerUIHTMLSource(is_playlist);
 
   // Set up the chrome://mediaplayer/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/dom_ui/mediaplayer_ui.h b/chrome/browser/dom_ui/mediaplayer_ui.h
index 921190a..c304954 100644
--- a/chrome/browser/dom_ui/mediaplayer_ui.h
+++ b/chrome/browser/dom_ui/mediaplayer_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
@@ -150,7 +150,7 @@
   DISALLOW_COPY_AND_ASSIGN(MediaPlayer);
 };
 
-class MediaplayerUI : public DOMUI {
+class MediaplayerUI : public WebUI {
  public:
   explicit MediaplayerUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/most_visited_handler.cc b/chrome/browser/dom_ui/most_visited_handler.cc
index d4f724c..6c762f4 100644
--- a/chrome/browser/dom_ui/most_visited_handler.cc
+++ b/chrome/browser/dom_ui/most_visited_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/md5.h"
@@ -19,16 +18,14 @@
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
-#include "chrome/browser/dom_ui/dom_ui_thumbnail_source.h"
 #include "chrome/browser/dom_ui/new_tab_ui.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
+#include "chrome/browser/dom_ui/web_ui_thumbnail_source.h"
 #include "chrome/browser/history/page_usage_data.h"
-#include "chrome/browser/history/history.h"
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/pref_names.h"
@@ -36,6 +33,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -65,33 +63,24 @@
 MostVisitedHandler::~MostVisitedHandler() {
 }
 
-DOMMessageHandler* MostVisitedHandler::Attach(DOMUI* dom_ui) {
-  url_blacklist_ = dom_ui->GetProfile()->GetPrefs()->
-      GetMutableDictionary(prefs::kNTPMostVisitedURLsBlacklist);
-  pinned_urls_ = dom_ui->GetProfile()->GetPrefs()->
-      GetMutableDictionary(prefs::kNTPMostVisitedPinnedURLs);
+WebUIMessageHandler* MostVisitedHandler::Attach(WebUI* web_ui) {
+  Profile* profile = web_ui->GetProfile();
+  url_blacklist_ = profile->GetPrefs()->GetMutableDictionary(
+      prefs::kNTPMostVisitedURLsBlacklist);
+  pinned_urls_ = profile->GetPrefs()->GetMutableDictionary(
+      prefs::kNTPMostVisitedPinnedURLs);
   // Set up our sources for thumbnail and favicon data.
-  DOMUIThumbnailSource* thumbnail_src =
-      new DOMUIThumbnailSource(dom_ui->GetProfile());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(thumbnail_src)));
+  WebUIThumbnailSource* thumbnail_src = new WebUIThumbnailSource(profile);
+  profile->GetChromeURLDataManager()->AddDataSource(thumbnail_src);
 
-  DOMUIFavIconSource* favicon_src =
-      new DOMUIFavIconSource(dom_ui->GetProfile());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(favicon_src)));
+  WebUIFavIconSource* favicon_src = new WebUIFavIconSource(profile);
+  profile->GetChromeURLDataManager()->AddDataSource(favicon_src);
 
   // Get notifications when history is cleared.
   registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED,
-      Source<Profile>(dom_ui->GetProfile()));
+                 Source<Profile>(profile));
 
-  DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
+  WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
 
   // We pre-emptively make a fetch for the most visited pages so we have the
   // results sooner.
@@ -102,21 +91,21 @@
 void MostVisitedHandler::RegisterMessages() {
   // Register ourselves as the handler for the "mostvisited" message from
   // Javascript.
-  dom_ui_->RegisterMessageCallback("getMostVisited",
+  web_ui_->RegisterMessageCallback("getMostVisited",
       NewCallback(this, &MostVisitedHandler::HandleGetMostVisited));
 
   // Register ourselves for any most-visited item blacklisting.
-  dom_ui_->RegisterMessageCallback("blacklistURLFromMostVisited",
+  web_ui_->RegisterMessageCallback("blacklistURLFromMostVisited",
       NewCallback(this, &MostVisitedHandler::HandleBlacklistURL));
-  dom_ui_->RegisterMessageCallback("removeURLsFromMostVisitedBlacklist",
+  web_ui_->RegisterMessageCallback("removeURLsFromMostVisitedBlacklist",
       NewCallback(this, &MostVisitedHandler::HandleRemoveURLsFromBlacklist));
-  dom_ui_->RegisterMessageCallback("clearMostVisitedURLsBlacklist",
+  web_ui_->RegisterMessageCallback("clearMostVisitedURLsBlacklist",
       NewCallback(this, &MostVisitedHandler::HandleClearBlacklist));
 
   // Register ourself for pinned URL messages.
-  dom_ui_->RegisterMessageCallback("addPinnedURL",
+  web_ui_->RegisterMessageCallback("addPinnedURL",
       NewCallback(this, &MostVisitedHandler::HandleAddPinnedURL));
-  dom_ui_->RegisterMessageCallback("removePinnedURL",
+  web_ui_->RegisterMessageCallback("removePinnedURL",
       NewCallback(this, &MostVisitedHandler::HandleRemovePinnedURL));
 }
 
@@ -133,14 +122,12 @@
 void MostVisitedHandler::SendPagesValue() {
   if (pages_value_.get()) {
     bool has_blacklisted_urls = !url_blacklist_->empty();
-    if (history::TopSites::IsEnabled()) {
-      history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-      if (ts)
-        has_blacklisted_urls = ts->HasBlacklistedItems();
-    }
+    history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+    if (ts)
+      has_blacklisted_urls = ts->HasBlacklistedItems();
     FundamentalValue first_run(IsFirstRun());
     FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls);
-    dom_ui_->CallJavascriptFunction(L"mostVisitedPages",
+    web_ui_->CallJavascriptFunction(L"mostVisitedPages",
                                     *(pages_value_.get()),
                                     first_run,
                                     has_blacklisted_urls_value);
@@ -149,32 +136,12 @@
 }
 
 void MostVisitedHandler::StartQueryForMostVisited() {
-  if (history::TopSites::IsEnabled()) {
-    // Use TopSites.
-    history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-    if (ts) {
-      ts->GetMostVisitedURLs(
-          &topsites_consumer_,
-          NewCallback(this, &MostVisitedHandler::OnMostVisitedURLsAvailable));
-    }
-    return;
-  }
-
-  const int page_count = kMostVisitedPages;
-  // Let's query for the number of items we want plus the blacklist size as
-  // we'll be filtering-out the returned list with the blacklist URLs.
-  // We do not subtract the number of pinned URLs we have because the
-  // HistoryService does not know about those.
-  const int result_count = page_count + url_blacklist_->size();
-  HistoryService* hs =
-      dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
-  // |hs| may be null during unit tests.
-  if (hs) {
-    hs->QuerySegmentUsageSince(
-        &cancelable_consumer_,
-        base::Time::Now() - base::TimeDelta::FromDays(kMostVisitedScope),
-        result_count,
-        NewCallback(this, &MostVisitedHandler::OnSegmentUsageAvailable));
+  // Use TopSites.
+  history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+  if (ts) {
+    ts->GetMostVisitedURLs(
+        &topsites_consumer_,
+        NewCallback(this, &MostVisitedHandler::OnMostVisitedURLsAvailable));
   }
 }
 
@@ -195,31 +162,20 @@
       return;
     }
     UserMetrics::RecordAction(UserMetricsAction("MostVisited_UrlRemoved"),
-                              dom_ui_->GetProfile());
-    if (history::TopSites::IsEnabled()) {
-      history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-      if (ts)
-        ts->RemoveBlacklistedURL(GURL(url));
-      return;
-    }
-
-    r = url_blacklist_->Remove(GetDictionaryKeyForURL(url), NULL);
-    DCHECK(r) << "Unknown URL removed from the NTP Most Visited blacklist.";
+                              web_ui_->GetProfile());
+    history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+    if (ts)
+      ts->RemoveBlacklistedURL(GURL(url));
   }
 }
 
 void MostVisitedHandler::HandleClearBlacklist(const ListValue* args) {
   UserMetrics::RecordAction(UserMetricsAction("MostVisited_BlacklistCleared"),
-                            dom_ui_->GetProfile());
+                            web_ui_->GetProfile());
 
-  if (history::TopSites::IsEnabled()) {
-    history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-    if (ts)
-      ts->ClearBlacklistedURLs();
-    return;
-  }
-
-  url_blacklist_->Clear();
+  history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+  if (ts)
+    ts->ClearBlacklistedURLs();
 }
 
 void MostVisitedHandler::HandleAddPinnedURL(const ListValue* args) {
@@ -257,28 +213,9 @@
 }
 
 void MostVisitedHandler::AddPinnedURL(const MostVisitedPage& page, int index) {
-  if (history::TopSites::IsEnabled()) {
-    history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-    if (ts)
-      ts->AddPinnedURL(page.url, index);
-    return;
-  }
-
-  // Remove any pinned URL at the given index.
-  MostVisitedPage old_page;
-  if (GetPinnedURLAtIndex(index, &old_page)) {
-    RemovePinnedURL(old_page.url);
-  }
-
-  DictionaryValue* new_value = new DictionaryValue();
-  SetMostVisistedPage(new_value, page);
-
-  new_value->SetInteger("index", index);
-  pinned_urls_->Set(GetDictionaryKeyForURL(page.url.spec()), new_value);
-
-  // TODO(arv): Notify observers?
-
-  // Don't call HandleGetMostVisited. Let the client call this as needed.
+  history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+  if (ts)
+    ts->AddPinnedURL(page.url, index);
 }
 
 void MostVisitedHandler::HandleRemovePinnedURL(const ListValue* args) {
@@ -287,20 +224,9 @@
 }
 
 void MostVisitedHandler::RemovePinnedURL(const GURL& url) {
-  if (history::TopSites::IsEnabled()) {
-    history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-    if (ts)
-      ts->RemovePinnedURL(url);
-    return;
-  }
-
-  const std::string key = GetDictionaryKeyForURL(url.spec());
-  if (pinned_urls_->HasKey(key))
-    pinned_urls_->Remove(key, NULL);
-
-  // TODO(arv): Notify observers?
-
-  // Don't call HandleGetMostVisited. Let the client call this as needed.
+  history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+  if (ts)
+    ts->RemovePinnedURL(url);
 }
 
 bool MostVisitedHandler::GetPinnedURLAtIndex(int index,
@@ -344,84 +270,8 @@
   return false;
 }
 
-void MostVisitedHandler::OnSegmentUsageAvailable(
-    CancelableRequestProvider::Handle handle,
-    std::vector<PageUsageData*>* data) {
-  SetPagesValue(data);
-  if (got_first_most_visited_request_) {
-    SendPagesValue();
-  }
-}
-
-void MostVisitedHandler::SetPagesValue(std::vector<PageUsageData*>* data) {
-  most_visited_urls_.clear();
-  pages_value_.reset(new ListValue);
-  std::set<GURL> seen_urls;
-
-  size_t data_index = 0;
-  size_t output_index = 0;
-  size_t pre_populated_index = 0;
-  const std::vector<MostVisitedPage> pre_populated_pages =
-      MostVisitedHandler::GetPrePopulatedPages();
-
-  while (output_index < kMostVisitedPages) {
-    bool found = false;
-    bool pinned = false;
-    std::string pinned_url;
-    std::string pinned_title;
-    MostVisitedPage mvp;
-
-    if (MostVisitedHandler::GetPinnedURLAtIndex(output_index, &mvp)) {
-      pinned = true;
-      found = true;
-    }
-
-    while (!found && data_index < data->size()) {
-      const PageUsageData& page = *(*data)[data_index];
-      data_index++;
-      mvp.url = page.GetURL();
-
-      // Don't include blacklisted or pinned URLs.
-      std::string key = GetDictionaryKeyForURL(mvp.url.spec());
-      if (pinned_urls_->HasKey(key) || url_blacklist_->HasKey(key))
-        continue;
-
-      mvp.title = page.GetTitle();
-      found = true;
-    }
-
-    while (!found && pre_populated_index < pre_populated_pages.size()) {
-      mvp = pre_populated_pages[pre_populated_index++];
-      std::string key = GetDictionaryKeyForURL(mvp.url.spec());
-      if (pinned_urls_->HasKey(key) || url_blacklist_->HasKey(key) ||
-          seen_urls.find(mvp.url) != seen_urls.end())
-        continue;
-
-      found = true;
-    }
-
-    if (found) {
-      // Add fillers as needed.
-      while (pages_value_->GetSize() < output_index) {
-        DictionaryValue* filler_value = new DictionaryValue();
-        filler_value->SetBoolean("filler", true);
-        pages_value_->Append(filler_value);
-      }
-
-      DictionaryValue* page_value = new DictionaryValue();
-      SetMostVisistedPage(page_value, mvp);
-      page_value->SetBoolean("pinned", pinned);
-      pages_value_->Append(page_value);
-      most_visited_urls_.push_back(mvp.url);
-      seen_urls.insert(mvp.url);
-    }
-    output_index++;
-  }
-}
-
 void MostVisitedHandler::SetPagesValueFromTopSites(
     const history::MostVisitedURLList& data) {
-  DCHECK(history::TopSites::IsEnabled());
   pages_value_.reset(new ListValue);
   for (size_t i = 0; i < data.size(); i++) {
     const history::MostVisitedURL& url = data[i];
@@ -448,7 +298,7 @@
           "chrome://theme/IDR_NEWTAB_THEMES_GALLERY_THUMBNAIL");
     }
 
-    history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
+    history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
     if (ts && ts->IsURLPinned(url.url))
       page_value->SetBoolean("pinned", true);
     pages_value_->Append(page_value);
@@ -474,18 +324,6 @@
 }
 
 // static
-void MostVisitedHandler::SetMostVisistedPage(
-    DictionaryValue* dict,
-    const MostVisitedHandler::MostVisitedPage& page) {
-  NewTabUI::SetURLTitleAndDirection(dict, page.title, page.url);
-  if (!page.favicon_url.is_empty())
-    dict->SetString("faviconUrl", page.favicon_url.spec());
-  if (!page.thumbnail_url.is_empty())
-    dict->SetString("thumbnailUrl", page.thumbnail_url.spec());
-}
-
-
-// static
 const std::vector<MostVisitedHandler::MostVisitedPage>&
     MostVisitedHandler::GetPrePopulatedPages() {
   // TODO(arv): This needs to get the data from some configurable place.
@@ -523,19 +361,9 @@
 }
 
 void MostVisitedHandler::BlacklistURL(const GURL& url) {
-  if (history::TopSites::IsEnabled()) {
-    history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
-    if (ts)
-      ts->AddBlacklistedURL(url);
-    return;
-  }
-
-  RemovePinnedURL(url);
-
-  std::string key = GetDictionaryKeyForURL(url.spec());
-  if (url_blacklist_->HasKey(key))
-    return;
-  url_blacklist_->SetBoolean(key, true);
+  history::TopSites* ts = web_ui_->GetProfile()->GetTopSites();
+  if (ts)
+    ts->AddBlacklistedURL(url);
 }
 
 std::string MostVisitedHandler::GetDictionaryKeyForURL(const std::string& url) {
diff --git a/chrome/browser/dom_ui/most_visited_handler.h b/chrome/browser/dom_ui/most_visited_handler.h
index 469aad9..97a93dc 100644
--- a/chrome/browser/dom_ui/most_visited_handler.h
+++ b/chrome/browser/dom_ui/most_visited_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "chrome/browser/cancelable_request.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
@@ -23,15 +23,15 @@
 class Value;
 
 // The handler for Javascript messages related to the "most visited" view.
-class MostVisitedHandler : public DOMMessageHandler,
+class MostVisitedHandler : public WebUIMessageHandler,
                            public NotificationObserver {
  public:
 
   MostVisitedHandler();
   virtual ~MostVisitedHandler();
 
-  // DOMMessageHandler override and implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler override and implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback for the "getMostVisited" message.
@@ -73,13 +73,6 @@
   // Send a request to the HistoryService to get the most visited pages.
   void StartQueryForMostVisited();
 
-  // Callback from the history system when the most visited list is available.
-  void OnSegmentUsageAvailable(CancelableRequestProvider::Handle handle,
-                               std::vector<PageUsageData*>* data);
-
-  // Sets pages_value_ from a vector of URLs.
-  void SetPagesValue(std::vector<PageUsageData*>* data);
-
   // Sets pages_value_ from a format produced by TopSites.
   void SetPagesValueFromTopSites(const history::MostVisitedURLList& data);
 
@@ -106,11 +99,6 @@
   // Returns true if we should treat this as the first run of the new tab page.
   bool IsFirstRun();
 
-  // Adds the fields in the page to the dictionary.
-  static void SetMostVisistedPage(
-      DictionaryValue* dict,
-      const MostVisitedHandler::MostVisitedPage& page);
-
   static const std::vector<MostVisitedPage>& GetPrePopulatedPages();
 
   NotificationRegistrar registrar_;
diff --git a/chrome/browser/dom_ui/net_internals_ui.cc b/chrome/browser/dom_ui/net_internals_ui.cc
index 07109ba..a9b661d 100644
--- a/chrome/browser/dom_ui/net_internals_ui.cc
+++ b/chrome/browser/dom_ui/net_internals_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/message_loop.h"
@@ -30,6 +28,9 @@
 #include "chrome/browser/net/url_fixer_upper.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/jstemplate_builder.h"
@@ -43,11 +44,16 @@
 #include "net/base/net_util.h"
 #include "net/base/sys_addrinfo.h"
 #include "net/disk_cache/disk_cache.h"
+#include "net/http/http_alternate_protocols.h"
 #include "net/http/http_cache.h"
+#include "net/http/http_stream_factory.h"
 #include "net/http/http_network_layer.h"
 #include "net/http/http_network_session.h"
 #include "net/proxy/proxy_service.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
 #ifdef OS_WIN
 #include "chrome/browser/net/service_providers_win.h"
 #endif
@@ -61,7 +67,7 @@
 
 // Returns the HostCache for |context|'s primary HostResolver, or NULL if
 // there is none.
-net::HostCache* GetHostResolverCache(URLRequestContext* context) {
+net::HostCache* GetHostResolverCache(net::URLRequestContext* context) {
   net::HostResolverImpl* host_resolver_impl =
       context->host_resolver()->GetAsHostResolverImpl();
 
@@ -72,7 +78,7 @@
 }
 
 // Returns the disk cache backend for |context| if there is one, or NULL.
-disk_cache::Backend* GetDiskCacheBackend(URLRequestContext* context) {
+disk_cache::Backend* GetDiskCacheBackend(net::URLRequestContext* context) {
   if (!context->http_transaction_factory())
     return NULL;
 
@@ -85,7 +91,8 @@
 
 // Returns the http network session for |context| if there is one.
 // Otherwise, returns NULL.
-net::HttpNetworkSession* GetHttpNetworkSession(URLRequestContext* context) {
+net::HttpNetworkSession* GetHttpNetworkSession(
+    net::URLRequestContext* context) {
   if (!context->http_transaction_factory())
     return NULL;
 
@@ -124,7 +131,7 @@
 };
 
 // This class receives javascript messages from the renderer.
-// Note that the DOMUI infrastructure runs on the UI thread, therefore all of
+// Note that the WebUI infrastructure runs on the UI thread, therefore all of
 // this class's methods are expected to run on the UI thread.
 //
 // Since the network code we want to run lives on the IO thread, we proxy
@@ -133,14 +140,15 @@
 //
 // TODO(eroman): Can we start on the IO thread to begin with?
 class NetInternalsMessageHandler
-    : public DOMMessageHandler,
+    : public WebUIMessageHandler,
+      public SelectFileDialog::Listener,
       public base::SupportsWeakPtr<NetInternalsMessageHandler> {
  public:
   NetInternalsMessageHandler();
   virtual ~NetInternalsMessageHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Executes the javascript function |function_name| in the renderer, passing
@@ -148,20 +156,51 @@
   void CallJavascriptFunction(const std::wstring& function_name,
                               const Value* value);
 
+  // SelectFileDialog::Listener implementation
+  virtual void FileSelected(const FilePath& path, int index, void* params);
+  virtual void FileSelectionCanceled(void* params);
+
+  // The only callback handled on the UI thread.  As it needs to access fields
+  // from |web_ui_|, it can't be called on the IO thread.
+  void OnLoadLogFile(const ListValue* list);
+
  private:
   class IOThreadImpl;
 
+  // Task run on the FILE thread to read the contents of a log file.  The result
+  // is then passed to IOThreadImpl's CallJavascriptFunction, which sends it
+  // back to the web page.  IOThreadImpl is used instead of the
+  // NetInternalsMessageHandler directly because it checks if the message
+  // handler has been destroyed in the meantime.
+  class ReadLogFileTask : public Task {
+   public:
+    ReadLogFileTask(IOThreadImpl* proxy, const FilePath& path);
+
+    virtual void Run();
+
+   private:
+    // IOThreadImpl implements existence checks already.  Simpler to reused them
+    // then to reimplement them.
+    scoped_refptr<IOThreadImpl> proxy_;
+
+    // Path of the file to open.
+    const FilePath path_;
+  };
+
   // This is the "real" message handler, which lives on the IO thread.
   scoped_refptr<IOThreadImpl> proxy_;
 
+  // Used for loading log files.
+  scoped_refptr<SelectFileDialog> select_log_file_dialog_;
+
   DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
 };
 
 // This class is the "real" message handler. It is allocated and destroyed on
-// the UI thread.  With the exception of OnAddEntry, OnDOMUIDeleted, and
+// the UI thread.  With the exception of OnAddEntry, OnWebUIDeleted, and
 // CallJavascriptFunction, its methods are all expected to be called from the IO
 // thread.  OnAddEntry and CallJavascriptFunction can be called from any thread,
-// and OnDOMUIDeleted can only be called from the UI thread.
+// and OnWebUIDeleted can only be called from the UI thread.
 class NetInternalsMessageHandler::IOThreadImpl
     : public base::RefCountedThreadSafe<
           NetInternalsMessageHandler::IOThreadImpl,
@@ -173,10 +212,10 @@
   typedef void (IOThreadImpl::*MessageHandler)(const ListValue*);
 
   // Creates a proxy for |handler| that will live on the IO thread.
-  // |handler| is a weak pointer, since it is possible for the DOMMessageHandler
-  // to be deleted on the UI thread while we were executing on the IO thread.
-  // |io_thread| is the global IOThread (it is passed in as an argument since
-  // we need to grab it from the UI thread).
+  // |handler| is a weak pointer, since it is possible for the
+  // WebUIMessageHandler to be deleted on the UI thread while we were executing
+  // on the IO thread. |io_thread| is the global IOThread (it is passed in as
+  // an argument since we need to grab it from the UI thread).
   IOThreadImpl(
       const base::WeakPtr<NetInternalsMessageHandler>& handler,
       IOThread* io_thread,
@@ -186,11 +225,11 @@
 
   // Creates a callback that will run |method| on the IO thread.
   //
-  // This can be used with DOMUI::RegisterMessageCallback() to bind to a method
+  // This can be used with WebUI::RegisterMessageCallback() to bind to a method
   // on the IO thread.
-  DOMUI::MessageCallback* CreateCallback(MessageHandler method);
+  WebUI::MessageCallback* CreateCallback(MessageHandler method);
 
-  // Called once the DOMUI has been deleted (i.e. renderer went away), on the
+  // Called once the WebUI has been deleted (i.e. renderer went away), on the
   // IO thread.
   void Detach();
 
@@ -198,9 +237,9 @@
   // handler, called on the IO thread.
   void SendPassiveLogEntries(const ChromeNetLog::EntryList& passive_entries);
 
-  // Called when the DOMUI is deleted.  Prevents calling Javascript functions
+  // Called when the WebUI is deleted.  Prevents calling Javascript functions
   // afterwards.  Called on UI thread.
-  void OnDOMUIDeleted();
+  void OnWebUIDeleted();
 
   //--------------------------------
   // Javascript message handlers:
@@ -219,6 +258,8 @@
   void OnGetHttpCacheInfo(const ListValue* list);
   void OnGetSocketPoolInfo(const ListValue* list);
   void OnGetSpdySessionInfo(const ListValue* list);
+  void OnGetSpdyStatus(const ListValue* list);
+  void OnGetSpdyAlternateProtocolMappings(const ListValue* list);
 #ifdef OS_WIN
   void OnGetServiceProviders(const ListValue* list);
 #endif
@@ -241,17 +282,17 @@
       int result);
   virtual void OnCompletedConnectionTestSuite();
 
+  // Helper that executes |function_name| in the attached renderer.
+  // The function takes ownership of |arg|.  Note that this can be called from
+  // any thread.
+  void CallJavascriptFunction(const std::wstring& function_name, Value* arg);
+
  private:
   class CallbackHelper;
 
   // Helper that runs |method| with |arg|, and deletes |arg| on completion.
   void DispatchToMessageHandler(ListValue* arg, MessageHandler method);
 
-  // Helper that executes |function_name| in the attached renderer.
-  // The function takes ownership of |arg|.  Note that this can be called from
-  // any thread.
-  void CallJavascriptFunction(const std::wstring& function_name, Value* arg);
-
   // Adds |entry| to the queue of pending log entries to be sent to the page via
   // Javascript.  Must be called on the IO Thread.  Also creates a delayed task
   // that will call PostPendingEntries, if there isn't one already.
@@ -275,13 +316,13 @@
   // Helper that runs the suite of connection tests.
   scoped_ptr<ConnectionTester> connection_tester_;
 
-  // True if the DOM UI has been deleted.  This is used to prevent calling
-  // Javascript functions after the DOM UI is destroyed.  On refresh, the
+  // True if the Web UI has been deleted.  This is used to prevent calling
+  // Javascript functions after the Web UI is destroyed.  On refresh, the
   // messages can end up being sent to the refreshed page, causing duplicate
   // or partial entries.
   //
   // This is only read and written to on the UI thread.
-  bool was_domui_deleted_;
+  bool was_webui_deleted_;
 
   // True if we have attached an observer to the NetLog already.
   bool is_observing_log_;
@@ -293,10 +334,10 @@
   scoped_ptr<ListValue> pending_entries_;
 };
 
-// Helper class for a DOMUI::MessageCallback which when excuted calls
+// Helper class for a WebUI::MessageCallback which when excuted calls
 // instance->*method(value) on the IO thread.
 class NetInternalsMessageHandler::IOThreadImpl::CallbackHelper
-    : public DOMUI::MessageCallback {
+    : public WebUI::MessageCallback {
  public:
   CallbackHelper(IOThreadImpl* instance, IOThreadImpl::MessageHandler method)
       : instance_(instance),
@@ -391,67 +432,103 @@
 
 NetInternalsMessageHandler::~NetInternalsMessageHandler() {
   if (proxy_) {
-    proxy_.get()->OnDOMUIDeleted();
+    proxy_.get()->OnWebUIDeleted();
     // Notify the handler on the IO thread that the renderer is gone.
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
         NewRunnableMethod(proxy_.get(), &IOThreadImpl::Detach));
   }
+  if (select_log_file_dialog_)
+    select_log_file_dialog_->ListenerDestroyed();
 }
 
-DOMMessageHandler* NetInternalsMessageHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* NetInternalsMessageHandler::Attach(WebUI* web_ui) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread(),
-                            dom_ui->GetProfile()->GetRequestContext());
-  DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
+                            web_ui->GetProfile()->GetRequestContext());
+  WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
   return result;
 }
 
+void NetInternalsMessageHandler::FileSelected(
+    const FilePath& path, int index, void* params) {
+  select_log_file_dialog_.release();
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      new ReadLogFileTask(proxy_.get(), path));
+}
+
+void NetInternalsMessageHandler::FileSelectionCanceled(void* params) {
+  select_log_file_dialog_.release();
+}
+
+void NetInternalsMessageHandler::OnLoadLogFile(const ListValue* list) {
+  // Only allow a single dialog at a time.
+  if (select_log_file_dialog_.get())
+    return;
+  select_log_file_dialog_ = SelectFileDialog::Create(this);
+  select_log_file_dialog_->SelectFile(
+      SelectFileDialog::SELECT_OPEN_FILE, string16(), FilePath(), NULL, 0,
+      FILE_PATH_LITERAL(""),
+      web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
+}
+
 void NetInternalsMessageHandler::RegisterMessages() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  // Only callback handled on UI thread.
+  web_ui_->RegisterMessageCallback(
+      "loadLogFile",
+      NewCallback(this, &NetInternalsMessageHandler::OnLoadLogFile));
 
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "notifyReady",
       proxy_->CreateCallback(&IOThreadImpl::OnRendererReady));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getProxySettings",
       proxy_->CreateCallback(&IOThreadImpl::OnGetProxySettings));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "reloadProxySettings",
       proxy_->CreateCallback(&IOThreadImpl::OnReloadProxySettings));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getBadProxies",
       proxy_->CreateCallback(&IOThreadImpl::OnGetBadProxies));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "clearBadProxies",
       proxy_->CreateCallback(&IOThreadImpl::OnClearBadProxies));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getHostResolverInfo",
       proxy_->CreateCallback(&IOThreadImpl::OnGetHostResolverInfo));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "clearHostResolverCache",
       proxy_->CreateCallback(&IOThreadImpl::OnClearHostResolverCache));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "enableIPv6",
       proxy_->CreateCallback(&IOThreadImpl::OnEnableIPv6));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "startConnectionTests",
       proxy_->CreateCallback(&IOThreadImpl::OnStartConnectionTests));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getHttpCacheInfo",
       proxy_->CreateCallback(&IOThreadImpl::OnGetHttpCacheInfo));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getSocketPoolInfo",
       proxy_->CreateCallback(&IOThreadImpl::OnGetSocketPoolInfo));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getSpdySessionInfo",
       proxy_->CreateCallback(&IOThreadImpl::OnGetSpdySessionInfo));
+  web_ui_->RegisterMessageCallback(
+      "getSpdyStatus",
+      proxy_->CreateCallback(&IOThreadImpl::OnGetSpdyStatus));
+  web_ui_->RegisterMessageCallback(
+      "getSpdyAlternateProtocolMappings",
+      proxy_->CreateCallback(
+          &IOThreadImpl::OnGetSpdyAlternateProtocolMappings));
 #ifdef OS_WIN
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "getServiceProviders",
       proxy_->CreateCallback(&IOThreadImpl::OnGetServiceProviders));
 #endif
 
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "setLogLevel",
       proxy_->CreateCallback(&IOThreadImpl::OnSetLogLevel));
 }
@@ -461,14 +538,33 @@
     const Value* value) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (value) {
-    dom_ui_->CallJavascriptFunction(function_name, *value);
+    web_ui_->CallJavascriptFunction(function_name, *value);
   } else {
-    dom_ui_->CallJavascriptFunction(function_name);
+    web_ui_->CallJavascriptFunction(function_name);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //
+// NetInternalsMessageHandler::ReadLogFileTask
+//
+////////////////////////////////////////////////////////////////////////////////
+
+NetInternalsMessageHandler::ReadLogFileTask::ReadLogFileTask(
+    IOThreadImpl* proxy, const FilePath& path)
+    : proxy_(proxy), path_(path) {
+}
+
+void NetInternalsMessageHandler::ReadLogFileTask::Run() {
+  std::string file_contents;
+  if (!file_util::ReadFileToString(path_, &file_contents))
+    return;
+  proxy_->CallJavascriptFunction(L"g_browser.loadedLogFile",
+                                 new StringValue(file_contents));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
 // NetInternalsMessageHandler::IOThreadImpl
 //
 ////////////////////////////////////////////////////////////////////////////////
@@ -481,7 +577,7 @@
       handler_(handler),
       io_thread_(io_thread),
       context_getter_(context_getter),
-      was_domui_deleted_(false),
+      was_webui_deleted_(false),
       is_observing_log_(false) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
@@ -490,7 +586,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
-DOMUI::MessageCallback*
+WebUI::MessageCallback*
 NetInternalsMessageHandler::IOThreadImpl::CreateCallback(
     MessageHandler method) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -524,9 +620,9 @@
   CallJavascriptFunction(L"g_browser.receivedPassiveLogEntries", dict_list);
 }
 
-void NetInternalsMessageHandler::IOThreadImpl::OnDOMUIDeleted() {
+void NetInternalsMessageHandler::IOThreadImpl::OnWebUIDeleted() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  was_domui_deleted_ = true;
+  was_webui_deleted_ = true;
 }
 
 void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
@@ -691,7 +787,7 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::OnGetProxySettings(
     const ListValue* list) {
-  URLRequestContext* context = context_getter_->GetURLRequestContext();
+  net::URLRequestContext* context = context_getter_->GetURLRequestContext();
   net::ProxyService* proxy_service = context->proxy_service();
 
   DictionaryValue* dict = new DictionaryValue();
@@ -705,7 +801,7 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::OnReloadProxySettings(
     const ListValue* list) {
-  URLRequestContext* context = context_getter_->GetURLRequestContext();
+  net::URLRequestContext* context = context_getter_->GetURLRequestContext();
   context->proxy_service()->ForceReloadProxyConfig();
 
   // Cause the renderer to be notified of the new values.
@@ -714,7 +810,7 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::OnGetBadProxies(
     const ListValue* list) {
-  URLRequestContext* context = context_getter_->GetURLRequestContext();
+  net::URLRequestContext* context = context_getter_->GetURLRequestContext();
 
   const net::ProxyRetryInfoMap& bad_proxies_map =
       context->proxy_service()->proxy_retry_info();
@@ -739,7 +835,7 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::OnClearBadProxies(
     const ListValue* list) {
-  URLRequestContext* context = context_getter_->GetURLRequestContext();
+  net::URLRequestContext* context = context_getter_->GetURLRequestContext();
   context->proxy_service()->ClearBadProxiesCache();
 
   // Cause the renderer to be notified of the new values.
@@ -748,7 +844,7 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::OnGetHostResolverInfo(
     const ListValue* list) {
-  URLRequestContext* context = context_getter_->GetURLRequestContext();
+  net::URLRequestContext* context = context_getter_->GetURLRequestContext();
   net::HostResolverImpl* host_resolver_impl =
       context->host_resolver()->GetAsHostResolverImpl();
   net::HostCache* cache = GetHostResolverCache(context);
@@ -830,7 +926,7 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::OnEnableIPv6(
     const ListValue* list) {
-  URLRequestContext* context = context_getter_->GetURLRequestContext();
+  net::URLRequestContext* context = context_getter_->GetURLRequestContext();
   net::HostResolverImpl* host_resolver_impl =
       context->host_resolver()->GetAsHostResolverImpl();
 
@@ -906,6 +1002,57 @@
   CallJavascriptFunction(L"g_browser.receivedSpdySessionInfo", spdy_info);
 }
 
+void NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyStatus(
+    const ListValue* list) {
+  DictionaryValue* status_dict = new DictionaryValue();
+
+  status_dict->Set("spdy_enabled",
+                   Value::CreateBooleanValue(
+                       net::HttpStreamFactory::spdy_enabled()));
+  status_dict->Set("use_alternate_protocols",
+                   Value::CreateBooleanValue(
+                       net::HttpStreamFactory::use_alternate_protocols()));
+  status_dict->Set("force_spdy_over_ssl",
+                   Value::CreateBooleanValue(
+                       net::HttpStreamFactory::force_spdy_over_ssl()));
+  status_dict->Set("force_spdy_always",
+                   Value::CreateBooleanValue(
+                       net::HttpStreamFactory::force_spdy_always()));
+  status_dict->Set("next_protos",
+                   Value::CreateStringValue(
+                       *net::HttpStreamFactory::next_protos()));
+
+  CallJavascriptFunction(L"g_browser.receivedSpdyStatus", status_dict);
+}
+
+void
+NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyAlternateProtocolMappings(
+    const ListValue* list) {
+  net::HttpNetworkSession* http_network_session =
+      GetHttpNetworkSession(context_getter_->GetURLRequestContext());
+
+  ListValue* dict_list = new ListValue();
+
+  if (http_network_session) {
+    const net::HttpAlternateProtocols& http_alternate_protocols =
+        http_network_session->alternate_protocols();
+    const net::HttpAlternateProtocols::ProtocolMap& map =
+        http_alternate_protocols.protocol_map();
+
+    for (net::HttpAlternateProtocols::ProtocolMap::const_iterator it =
+             map.begin();
+         it != map.end(); ++it) {
+      DictionaryValue* dict = new DictionaryValue();
+      dict->SetString("host_port_pair", it->first.ToString());
+      dict->SetString("alternate_protocol", it->second.ToString());
+      dict_list->Append(dict);
+    }
+  }
+
+  CallJavascriptFunction(L"g_browser.receivedSpdyAlternateProtocolMappings",
+                         dict_list);
+}
+
 #ifdef OS_WIN
 void NetInternalsMessageHandler::IOThreadImpl::OnGetServiceProviders(
     const ListValue* list) {
@@ -1042,7 +1189,7 @@
     const std::wstring& function_name,
     Value* arg) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    if (handler_ && !was_domui_deleted_) {
+    if (handler_ && !was_webui_deleted_) {
       // We check |handler_| in case it was deleted on the UI thread earlier
       // while we were running on the IO thread.
       handler_->CallJavascriptFunction(function_name, arg);
@@ -1071,16 +1218,11 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-NetInternalsUI::NetInternalsUI(TabContents* contents) : DOMUI(contents) {
+NetInternalsUI::NetInternalsUI(TabContents* contents) : WebUI(contents) {
   AddMessageHandler((new NetInternalsMessageHandler())->Attach(this));
 
   NetInternalsHTMLSource* html_source = new NetInternalsHTMLSource();
 
   // Set up the chrome://net-internals/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/dom_ui/net_internals_ui.h b/chrome/browser/dom_ui/net_internals_ui.h
index 3c67963..36abca3 100644
--- a/chrome/browser/dom_ui/net_internals_ui.h
+++ b/chrome/browser/dom_ui/net_internals_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_DOM_UI_NET_INTERNALS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-class NetInternalsUI : public DOMUI {
+class NetInternalsUI : public WebUI {
  public:
   explicit NetInternalsUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
index d7a5543..ec3da8b 100644
--- a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
+++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,21 +6,19 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/common/pref_names.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "net/base/cookie_monster.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // Default URL for the sync web interface.
 //
@@ -99,18 +97,18 @@
   }
 }
 
-DOMMessageHandler* NewTabPageSyncHandler::Attach(DOMUI* dom_ui) {
-  sync_service_ = dom_ui->GetProfile()->GetProfileSyncService();
+WebUIMessageHandler* NewTabPageSyncHandler::Attach(WebUI* web_ui) {
+  sync_service_ = web_ui->GetProfile()->GetProfileSyncService();
   DCHECK(sync_service_);  // This shouldn't get called by an incognito NTP.
   DCHECK(!sync_service_->IsManaged());  // And neither if sync is managed.
   sync_service_->AddObserver(this);
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void NewTabPageSyncHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("GetSyncMessage",
+  web_ui_->RegisterMessageCallback("GetSyncMessage",
       NewCallback(this, &NewTabPageSyncHandler::HandleGetSyncMessage));
-  dom_ui_->RegisterMessageCallback("SyncLinkClicked",
+  web_ui_->RegisterMessageCallback("SyncLinkClicked",
       NewCallback(this, &NewTabPageSyncHandler::HandleSyncLinkClicked));
 }
 
@@ -146,7 +144,9 @@
   string16 status_msg;
   string16 link_text;
   sync_ui_util::MessageType type =
-      sync_ui_util::GetStatusLabels(sync_service_, &status_msg, &link_text);
+      sync_ui_util::GetStatusLabelsForNewTabPage(sync_service_,
+                                                 &status_msg,
+                                                 &link_text);
   SendSyncMessageToPage(FromSyncStatusMessageType(type),
                         UTF16ToUTF8(status_msg), UTF16ToUTF8(link_text));
 }
@@ -157,31 +157,12 @@
   if (!sync_service_->IsSyncEnabled())
     return;
   if (sync_service_->HasSyncSetupCompleted()) {
-    if (sync_service_->observed_passphrase_required()) {
-      if (sync_service_->IsUsingSecondaryPassphrase())
-        sync_service_->PromptForExistingPassphrase(NULL);
-      else
-        sync_service_->SigninForPassphrase(dom_ui_->tab_contents());
-      return;
-    }
-    if (sync_service_->GetAuthError().state() ==
-        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
-        sync_service_->GetAuthError().state() ==
-        GoogleServiceAuthError::CAPTCHA_REQUIRED ||
-        sync_service_->GetAuthError().state() ==
-        GoogleServiceAuthError::ACCOUNT_DELETED ||
-        sync_service_->GetAuthError().state() ==
-        GoogleServiceAuthError::ACCOUNT_DISABLED ||
-        sync_service_->GetAuthError().state() ==
-        GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
-      sync_service_->ShowLoginDialog(NULL);
-      return;
-    }
+    sync_service_->ShowErrorUI(NULL);
     DictionaryValue value;
     value.SetString("syncEnabledMessage",
                     l10n_util::GetStringFUTF16(IDS_SYNC_NTP_SYNCED_TO,
                         sync_service_->GetAuthenticatedUsername()));
-    dom_ui_->CallJavascriptFunction(L"syncAlreadyEnabled", value);
+    web_ui_->CallJavascriptFunction(L"syncAlreadyEnabled", value);
   } else {
     // User clicked the 'Start now' link to begin syncing.
     ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_NTP);
@@ -236,5 +217,5 @@
       }
     }
   }
-  dom_ui_->CallJavascriptFunction(L"syncMessageChanged", value);
+  web_ui_->CallJavascriptFunction(L"syncMessageChanged", value);
 }
diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.h b/chrome/browser/dom_ui/new_tab_page_sync_handler.h
index 99c817e..f3e35a5 100644
--- a/chrome/browser/dom_ui/new_tab_page_sync_handler.h
+++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include <string>
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 
@@ -16,14 +16,14 @@
 
 // Sends sync-state changes to the New Tab Page for UI updating and forwards
 // link clicks on the page to the sync service.
-class NewTabPageSyncHandler : public DOMMessageHandler,
+class NewTabPageSyncHandler : public WebUIMessageHandler,
                               public ProfileSyncServiceObserver {
  public:
   NewTabPageSyncHandler();
   virtual ~NewTabPageSyncHandler();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback for "GetSyncMessage".
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index c43a8f5..1cc4f55 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,6 @@
 
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
@@ -19,7 +18,6 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/app_launcher_handler.h"
-#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
 #include "chrome/browser/dom_ui/foreign_session_handler.h"
 #include "chrome/browser/dom_ui/most_visited_handler.h"
 #include "chrome/browser/dom_ui/new_tab_page_sync_handler.h"
@@ -28,6 +26,7 @@
 #include "chrome/browser/dom_ui/shown_sections_handler.h"
 #include "chrome/browser/dom_ui/tips_handler.h"
 #include "chrome/browser/dom_ui/value_helper.h"
+#include "chrome/browser/dom_ui/web_ui_theme_source.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
 #include "chrome/browser/prefs/pref_service.h"
@@ -46,6 +45,7 @@
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -55,84 +55,25 @@
 // The number of search URLs to show.
 const int kSearchURLs = 3;
 
+// The amount of time there must be no painting for us to consider painting
+// finished.  Observed times are in the ~1200ms range on Windows.
+const int kTimeoutMs = 2000;
+
 // Strings sent to the page via jstemplates used to set the direction of the
 // HTML document based on locale.
 const char kRTLHtmlTextDirection[] = "rtl";
 const char kDefaultHtmlTextDirection[] = "ltr";
 
-////////////////////////////////////////////////////////////////////////////////
-// PaintTimer
-
-// To measure end-to-end performance of the new tab page, we observe paint
-// messages and wait for the page to stop repainting.
-class PaintTimer : public RenderWidgetHost::PaintObserver {
- public:
-  PaintTimer() {
-    Start();
-  }
-
-  // Start the benchmarking and the timer.
-  void Start() {
-    start_ = base::TimeTicks::Now();
-    last_paint_ = start_;
-
-    timer_.Start(base::TimeDelta::FromMilliseconds(kTimeoutMs), this,
-                 &PaintTimer::Timeout);
-  }
-
-  // A callback that is invoked whenever our RenderWidgetHost paints.
-  virtual void RenderWidgetHostWillPaint(RenderWidgetHost* rhw) {}
-
-  virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh) {
-    last_paint_ = base::TimeTicks::Now();
-  }
-
-  // The timer callback.  If enough time has elapsed since the last paint
-  // message, we say we're done painting; otherwise, we keep waiting.
-  void Timeout() {
-    base::TimeTicks now = base::TimeTicks::Now();
-    if ((now - last_paint_) >= base::TimeDelta::FromMilliseconds(kTimeoutMs)) {
-      // Painting has quieted down.  Log this as the full time to run.
-      base::TimeDelta load_time = last_paint_ - start_;
-      int load_time_ms = static_cast<int>(load_time.InMilliseconds());
-      NotificationService::current()->Notify(
-          NotificationType::INITIAL_NEW_TAB_UI_LOAD,
-          NotificationService::AllSources(),
-          Details<int>(&load_time_ms));
-      UMA_HISTOGRAM_TIMES("NewTabUI load", load_time);
-    } else {
-      // Not enough quiet time has elapsed.
-      // Some more paints must've occurred since we set the timeout.
-      // Wait some more.
-      timer_.Start(base::TimeDelta::FromMilliseconds(kTimeoutMs), this,
-                   &PaintTimer::Timeout);
-    }
-  }
-
- private:
-  // The amount of time there must be no painting for us to consider painting
-  // finished.  Observed times are in the ~1200ms range on Windows.
-  static const int kTimeoutMs = 2000;
-  // The time when we started benchmarking.
-  base::TimeTicks start_;
-  // The last time we got a paint notification.
-  base::TimeTicks last_paint_;
-  // Scoping so we can be sure our timeouts don't outlive us.
-  base::OneShotTimer<PaintTimer> timer_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintTimer);
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 // RecentlyClosedTabsHandler
 
-class RecentlyClosedTabsHandler : public DOMMessageHandler,
+class RecentlyClosedTabsHandler : public WebUIMessageHandler,
                                   public TabRestoreServiceObserver {
  public:
   RecentlyClosedTabsHandler() : tab_restore_service_(NULL) {}
   virtual ~RecentlyClosedTabsHandler();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callback for the "reopenTab" message. Rewrites the history of the
@@ -160,10 +101,10 @@
 };
 
 void RecentlyClosedTabsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getRecentlyClosedTabs",
+  web_ui_->RegisterMessageCallback("getRecentlyClosedTabs",
       NewCallback(this,
                   &RecentlyClosedTabsHandler::HandleGetRecentlyClosedTabs));
-  dom_ui_->RegisterMessageCallback("reopenTab",
+  web_ui_->RegisterMessageCallback("reopenTab",
       NewCallback(this, &RecentlyClosedTabsHandler::HandleReopenTab));
 }
 
@@ -174,7 +115,7 @@
 
 void RecentlyClosedTabsHandler::HandleReopenTab(const ListValue* args) {
   Browser* browser = Browser::GetBrowserForController(
-      &dom_ui_->tab_contents()->controller(), NULL);
+      &web_ui_->tab_contents()->controller(), NULL);
   if (!browser)
     return;
 
@@ -188,7 +129,7 @@
 void RecentlyClosedTabsHandler::HandleGetRecentlyClosedTabs(
     const ListValue* args) {
   if (!tab_restore_service_) {
-    tab_restore_service_ = dom_ui_->GetProfile()->GetTabRestoreService();
+    tab_restore_service_ = web_ui_->GetProfile()->GetTabRestoreService();
 
     // GetTabRestoreService() can return NULL (i.e., when in Off the
     // Record mode)
@@ -210,7 +151,7 @@
   ListValue list_value;
   NewTabUI::AddRecentlyClosedEntries(service->entries(), &list_value);
 
-  dom_ui_->CallJavascriptFunction(L"recentlyClosedTabs", list_value);
+  web_ui_->CallJavascriptFunction(L"recentlyClosedTabs", list_value);
 }
 
 void RecentlyClosedTabsHandler::TabRestoreServiceDestroyed(
@@ -218,7 +159,6 @@
   tab_restore_service_ = NULL;
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 // MetricsHandler
 
@@ -228,12 +168,12 @@
 // information through RequestOpenURL. You will need to update the metrics
 // dashboard with the action names you use, as our processor won't catch that
 // information (treat it as RecordComputedMetrics)
-class MetricsHandler : public DOMMessageHandler {
+class MetricsHandler : public WebUIMessageHandler {
  public:
   MetricsHandler() {}
   virtual ~MetricsHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callback which records a user action.
@@ -248,21 +188,21 @@
 };
 
 void MetricsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("metrics",
+  web_ui_->RegisterMessageCallback("metrics",
       NewCallback(this, &MetricsHandler::HandleMetrics));
 
-  dom_ui_->RegisterMessageCallback("logEventTime",
+  web_ui_->RegisterMessageCallback("logEventTime",
       NewCallback(this, &MetricsHandler::HandleLogEventTime));
 }
 
 void MetricsHandler::HandleMetrics(const ListValue* args) {
   std::string string_action = WideToUTF8(ExtractStringValue(args));
-  UserMetrics::RecordComputedAction(string_action, dom_ui_->GetProfile());
+  UserMetrics::RecordComputedAction(string_action, web_ui_->GetProfile());
 }
 
 void MetricsHandler::HandleLogEventTime(const ListValue* args) {
   std::string event_name = WideToUTF8(ExtractStringValue(args));
-  dom_ui_->tab_contents()->LogNewTabTime(event_name);
+  web_ui_->tab_contents()->LogNewTabTime(event_name);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -270,12 +210,12 @@
 
 // Sets the new tab page as home page when user clicks on "make this my home
 // page" link.
-class NewTabPageSetHomePageHandler : public DOMMessageHandler {
+class NewTabPageSetHomePageHandler : public WebUIMessageHandler {
  public:
   NewTabPageSetHomePageHandler() {}
   virtual ~NewTabPageSetHomePageHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callback for "setHomePage".
@@ -287,20 +227,20 @@
 };
 
 void NewTabPageSetHomePageHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("setHomePage", NewCallback(
+  web_ui_->RegisterMessageCallback("setHomePage", NewCallback(
       this, &NewTabPageSetHomePageHandler::HandleSetHomePage));
 }
 
 void NewTabPageSetHomePageHandler::HandleSetHomePage(
     const ListValue* args) {
-  dom_ui_->GetProfile()->GetPrefs()->SetBoolean(prefs::kHomePageIsNewTabPage,
+  web_ui_->GetProfile()->GetPrefs()->SetBoolean(prefs::kHomePageIsNewTabPage,
                                                 true);
   ListValue list_value;
   list_value.Append(new StringValue(
       l10n_util::GetStringUTF16(IDS_NEW_TAB_HOME_PAGE_SET_NOTIFICATION)));
   list_value.Append(new StringValue(
       l10n_util::GetStringUTF16(IDS_NEW_TAB_HOME_PAGE_HIDE_NOTIFICATION)));
-  dom_ui_->CallJavascriptFunction(L"onHomePageSet", list_value);
+  web_ui_->CallJavascriptFunction(L"onHomePageSet", list_value);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -308,12 +248,12 @@
 
 // Turns off the promo line permanently when it has been explicitly closed by
 // the user.
-class NewTabPageClosePromoHandler : public DOMMessageHandler {
+class NewTabPageClosePromoHandler : public WebUIMessageHandler {
  public:
   NewTabPageClosePromoHandler() {}
   virtual ~NewTabPageClosePromoHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callback for "closePromo".
@@ -325,13 +265,13 @@
 };
 
 void NewTabPageClosePromoHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("closePromo", NewCallback(
+  web_ui_->RegisterMessageCallback("closePromo", NewCallback(
       this, &NewTabPageClosePromoHandler::HandleClosePromo));
 }
 
 void NewTabPageClosePromoHandler::HandleClosePromo(
     const ListValue* args) {
-  dom_ui_->GetProfile()->GetPrefs()->SetBoolean(prefs::kNTPPromoClosed, true);
+  web_ui_->GetProfile()->GetPrefs()->SetBoolean(prefs::kNTPPromoClosed, true);
   NotificationService* service = NotificationService::current();
   service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED,
                   Source<NewTabPageClosePromoHandler>(this),
@@ -344,8 +284,8 @@
 // NewTabUI
 
 NewTabUI::NewTabUI(TabContents* contents)
-    : DOMUI(contents) {
-  // Override some options on the DOM UI.
+    : WebUI(contents) {
+  // Override some options on the Web UI.
   hide_favicon_ = true;
   force_bookmark_bar_visible_ = true;
   focus_location_bar_by_default_ = true;
@@ -392,12 +332,7 @@
   InitializeCSSCaches();
   NewTabHTMLSource* html_source =
       new NewTabHTMLSource(GetProfile()->GetOriginalProfile());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 
   // Listen for theme installation.
   registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
@@ -410,41 +345,81 @@
 NewTabUI::~NewTabUI() {
 }
 
+// The timer callback.  If enough time has elapsed since the last paint
+// message, we say we're done painting; otherwise, we keep waiting.
+void NewTabUI::PaintTimeout() {
+  // The amount of time there must be no painting for us to consider painting
+  // finished.  Observed times are in the ~1200ms range on Windows.
+  base::TimeTicks now = base::TimeTicks::Now();
+  if ((now - last_paint_) >= base::TimeDelta::FromMilliseconds(kTimeoutMs)) {
+    // Painting has quieted down.  Log this as the full time to run.
+    base::TimeDelta load_time = last_paint_ - start_;
+    int load_time_ms = static_cast<int>(load_time.InMilliseconds());
+    NotificationService::current()->Notify(
+        NotificationType::INITIAL_NEW_TAB_UI_LOAD,
+        NotificationService::AllSources(),
+        Details<int>(&load_time_ms));
+    UMA_HISTOGRAM_TIMES("NewTabUI load", load_time);
+  } else {
+    // Not enough quiet time has elapsed.
+    // Some more paints must've occurred since we set the timeout.
+    // Wait some more.
+    timer_.Start(base::TimeDelta::FromMilliseconds(kTimeoutMs), this,
+                 &NewTabUI::PaintTimeout);
+  }
+}
+
+void NewTabUI::StartTimingPaint(RenderViewHost* render_view_host) {
+  start_ = base::TimeTicks::Now();
+  last_paint_ = start_;
+  registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
+      Source<RenderWidgetHost>(render_view_host));
+  timer_.Start(base::TimeDelta::FromMilliseconds(kTimeoutMs), this,
+               &NewTabUI::PaintTimeout);
+
+}
 void NewTabUI::RenderViewCreated(RenderViewHost* render_view_host) {
-  render_view_host->set_paint_observer(new PaintTimer);
+  StartTimingPaint(render_view_host);
 }
 
 void NewTabUI::RenderViewReused(RenderViewHost* render_view_host) {
-  render_view_host->set_paint_observer(new PaintTimer);
+  StartTimingPaint(render_view_host);
 }
 
 void NewTabUI::Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details) {
-  if (NotificationType::BROWSER_THEME_CHANGED == type) {
-    InitializeCSSCaches();
-    ListValue args;
-    args.Append(Value::CreateStringValue(
-        GetProfile()->GetThemeProvider()->HasCustomImage(
-            IDR_THEME_NTP_ATTRIBUTION) ?
-        "true" : "false"));
-    CallJavascriptFunction(L"themeChanged", args);
-  } else if (NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED) {
-    if (GetProfile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar))
-      CallJavascriptFunction(L"bookmarkBarAttached");
-    else
-      CallJavascriptFunction(L"bookmarkBarDetached");
+  switch (type.value) {
+    case NotificationType::BROWSER_THEME_CHANGED: {
+      InitializeCSSCaches();
+      ListValue args;
+      args.Append(Value::CreateStringValue(
+          GetProfile()->GetThemeProvider()->HasCustomImage(
+              IDR_THEME_NTP_ATTRIBUTION) ?
+          "true" : "false"));
+      CallJavascriptFunction(L"themeChanged", args);
+      break;
+    }
+    case NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED: {
+      if (GetProfile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar))
+        CallJavascriptFunction(L"bookmarkBarAttached");
+      else
+        CallJavascriptFunction(L"bookmarkBarDetached");
+      break;
+    }
+    case NotificationType::RENDER_WIDGET_HOST_DID_PAINT: {
+      last_paint_ = base::TimeTicks::Now();
+      break;
+    }
+    default:
+      CHECK(false) << "Unexpected notification: " << type.value;
   }
 }
 
 void NewTabUI::InitializeCSSCaches() {
-  DOMUIThemeSource* theme = new DOMUIThemeSource(GetProfile());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(theme)));
+  Profile* profile = GetProfile();
+  WebUIThemeSource* theme = new WebUIThemeSource(profile);
+  profile->GetChromeURLDataManager()->AddDataSource(theme);
 }
 
 // static
@@ -605,7 +580,7 @@
                                                   int request_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (AppLauncherHandler::HandlePing(path)) {
+  if (AppLauncherHandler::HandlePing(profile_, path)) {
     return;
   } else if (!path.empty() && path[0] != '#') {
     // A path under new-tab was requested; it's likely a bad relative
diff --git a/chrome/browser/dom_ui/new_tab_ui.h b/chrome/browser/dom_ui/new_tab_ui.h
index 40add03..badc476 100644
--- a/chrome/browser/dom_ui/new_tab_ui.h
+++ b/chrome/browser/dom_ui/new_tab_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,9 @@
 #include <string>
 
 #include "base/gtest_prod_util.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "base/timer.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/sessions/tab_restore_service.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
@@ -21,13 +22,13 @@
 class Profile;
 
 // The TabContents used for the New Tab page.
-class NewTabUI : public DOMUI,
+class NewTabUI : public WebUI,
                  public NotificationObserver {
  public:
   explicit NewTabUI(TabContents* manager);
   ~NewTabUI();
 
-  // Override DOMUI methods so we can hook up the paint timer to the render
+  // Override WebUI methods so we can hook up the paint timer to the render
   // view host.
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
   virtual void RenderViewReused(RenderViewHost* render_view_host);
@@ -96,12 +97,21 @@
   // Reset the CSS caches.
   void InitializeCSSCaches();
 
+  void StartTimingPaint(RenderViewHost* render_view_host);
+  void PaintTimeout();
+
   // Updates the user prefs version and calls |MigrateUserPrefs| if needed.
   // Returns true if the version was updated.
   static bool UpdateUserPrefsVersion(PrefService* prefs);
 
   NotificationRegistrar registrar_;
 
+  // The time when we started benchmarking.
+  base::TimeTicks start_;
+  // The last time we got a paint notification.
+  base::TimeTicks last_paint_;
+  // Scoping so we can be sure our timeouts don't outlive us.
+  base::OneShotTimer<NewTabUI> timer_;
   // The preference version. This used for migrating prefs of the NTP.
   static const int current_pref_version_ = 3;
 
diff --git a/chrome/browser/dom_ui/new_tab_ui_uitest.cc b/chrome/browser/dom_ui/new_tab_ui_uitest.cc
index 5b3bd0d..62c33e2 100644
--- a/chrome/browser/dom_ui/new_tab_ui_uitest.cc
+++ b/chrome/browser/dom_ui/new_tab_ui_uitest.cc
@@ -1,13 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/test/ui/ui_test.h"
 
+#include "base/test/test_timeouts.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/dom_ui/new_tab_ui.h"
 #include "chrome/browser/prefs/pref_value_store.h"
 #include "chrome/browser/sync/signin_manager.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/json_pref_store.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -38,8 +40,6 @@
 
   // Bring up a new tab page.
   ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
-  int load_time;
-  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
 
   scoped_refptr<TabProxy> tab = window->GetActiveTab();
   ASSERT_TRUE(tab.get());
@@ -49,10 +49,11 @@
   ASSERT_TRUE(WaitUntilJavaScriptCondition(tab, L"",
       L"window.domAutomationController.send("
       L"document.getElementsByClassName('filler').length <= 5)",
-      action_max_timeout_ms()));
+      TestTimeouts::action_max_timeout_ms()));
 }
 
-TEST_F(NewTabUITest, NTPHasLoginName) {
+// Sometimes hangs: http://crbug.com/70157
+TEST_F(NewTabUITest, DISABLED_NTPHasLoginName) {
   scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(window.get());
 
@@ -60,8 +61,6 @@
                                           "user@gmail.com"));
   // Bring up a new tab page.
   ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
-  int load_time;
-  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
 
   scoped_refptr<TabProxy> tab = window->GetActiveTab();
   ASSERT_TRUE(tab.get());
@@ -72,7 +71,7 @@
   ASSERT_TRUE(WaitUntilJavaScriptCondition(tab, L"",
       L"window.domAutomationController.send("
       L"document.getElementById('login-username').innerText.length > 0)",
-      action_max_timeout_ms()));
+      TestTimeouts::action_max_timeout_ms()));
 
   ASSERT_TRUE(tab->ExecuteAndExtractString(
       L"",
@@ -91,8 +90,6 @@
 
   // Bring up a new tab page.
   ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
-  int load_time;
-  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
   scoped_refptr<TabProxy> tab = window->GetActiveTab();
   ASSERT_TRUE(tab.get());
 
@@ -101,12 +98,46 @@
 
   // Visit about:hang again in another NTP.  Don't bother waiting for the
   // NTP to load, because it's hung.
-  ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
+  ASSERT_TRUE(window->RunCommandAsync(IDC_NEW_TAB));
   scoped_refptr<TabProxy> tab2 = window->GetActiveTab();
   ASSERT_TRUE(tab2.get());
   ASSERT_TRUE(tab2->NavigateToURLAsync(GURL(chrome::kAboutHangURL)));
 }
 
+// Allows testing NTP in process-per-tab mode.
+class NewTabUIProcessPerTabTest : public NewTabUITest {
+ public:
+  NewTabUIProcessPerTabTest() : NewTabUITest() {}
+
+ protected:
+  virtual void SetUp() {
+    launch_arguments_.AppendSwitch(switches::kProcessPerTab);
+    UITest::SetUp();
+  }
+};
+
+// Navigates away from NTP before it commits, in process-per-tab mode.
+// Ensures that we don't load the normal page in the NTP process (and thus
+// crash), as in http://crbug.com/69224.
+TEST_F(NewTabUIProcessPerTabTest, NavBeforeNTPCommits) {
+  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+  ASSERT_TRUE(window.get());
+
+  // Bring up a new tab page.
+  ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
+  scoped_refptr<TabProxy> tab = window->GetActiveTab();
+  ASSERT_TRUE(tab.get());
+
+  // Navigate to about:hang to stall the process.
+  ASSERT_TRUE(tab->NavigateToURLAsync(GURL(chrome::kAboutHangURL)));
+
+  // Visit a normal URL in another NTP that hasn't committed.
+  ASSERT_TRUE(window->RunCommandAsync(IDC_NEW_TAB));
+  scoped_refptr<TabProxy> tab2 = window->GetActiveTab();
+  ASSERT_TRUE(tab2.get());
+  ASSERT_TRUE(tab2->NavigateToURL(GURL("data:text/html,hello world")));
+}
+
 // Fails about ~5% of the time on all platforms. http://crbug.com/45001
 TEST_F(NewTabUITest, FLAKY_ChromeInternalLoadsNTP) {
   scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
@@ -128,8 +159,7 @@
   EXPECT_GT(thumbnails_count, 0);
 }
 
-// Flaky on XP bots: http://crbug.com/51726
-TEST_F(NewTabUITest, FLAKY_UpdateUserPrefsVersion) {
+TEST_F(NewTabUITest, UpdateUserPrefsVersion) {
   // PrefService with JSON user-pref file only, no enforced or advised prefs.
   scoped_ptr<PrefService> prefs(new TestingPrefService);
 
diff --git a/chrome/browser/dom_ui/ntp_login_handler.cc b/chrome/browser/dom_ui/ntp_login_handler.cc
index 67939d0..52faf92 100644
--- a/chrome/browser/dom_ui/ntp_login_handler.cc
+++ b/chrome/browser/dom_ui/ntp_login_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #include <string>
 
 #include "base/values.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/prefs/pref_notifier.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -22,15 +22,15 @@
 NTPLoginHandler::~NTPLoginHandler() {
 }
 
-DOMMessageHandler* NTPLoginHandler::Attach(DOMUI* dom_ui) {
-  PrefService* pref_service = dom_ui->GetProfile()->GetPrefs();
+WebUIMessageHandler* NTPLoginHandler::Attach(WebUI* web_ui) {
+  PrefService* pref_service = web_ui->GetProfile()->GetPrefs();
   username_pref_.Init(prefs::kGoogleServicesUsername, pref_service, this);
 
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void NTPLoginHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("initializeLogin",
+  web_ui_->RegisterMessageCallback("initializeLogin",
       NewCallback(this, &NTPLoginHandler::HandleInitializeLogin));
 }
 
@@ -48,8 +48,8 @@
 }
 
 void NTPLoginHandler::UpdateLogin() {
-  std::string username = dom_ui_->GetProfile()->GetPrefs()->GetString(
+  std::string username = web_ui_->GetProfile()->GetPrefs()->GetString(
       prefs::kGoogleServicesUsername);
   StringValue string_value(username);
-  dom_ui_->CallJavascriptFunction(L"updateLogin", string_value);
+  web_ui_->CallJavascriptFunction(L"updateLogin", string_value);
 }
diff --git a/chrome/browser/dom_ui/ntp_login_handler.h b/chrome/browser/dom_ui/ntp_login_handler.h
index d6eabfe..6b661cb 100644
--- a/chrome/browser/dom_ui/ntp_login_handler.h
+++ b/chrome/browser/dom_ui/ntp_login_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,22 +6,22 @@
 #define CHROME_BROWSER_DOM_UI_NTP_LOGIN_HANDLER_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/common/notification_observer.h"
 
 // The NTP login handler currently simply displays the current logged in
 // username at the top of the NTP (and update itself when that changes).
 // In the future it may expand to allow users to login from the NTP.
-class NTPLoginHandler : public DOMMessageHandler,
+class NTPLoginHandler : public WebUIMessageHandler,
                         public NotificationObserver {
  public:
   NTPLoginHandler();
   ~NTPLoginHandler();
 
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
 
-  // DOMMessageHandler interface
+  // WebUIMessageHandler interface
   virtual void RegisterMessages();
 
   // NotificationObserver interface
diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc
index 8cca8b4..3df1391 100644
--- a/chrome/browser/dom_ui/ntp_resource_cache.cc
+++ b/chrome/browser/dom_ui/ntp_resource_cache.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,9 +7,6 @@
 #include <algorithm>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/ref_counted_memory.h"
@@ -34,20 +31,23 @@
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/color_utils.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/color_utils.h"
 
 #if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 #elif defined(OS_MACOSX)
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
 #elif defined(OS_POSIX)
-#include "chrome/browser/gtk/bookmark_bar_gtk.h"
+#include "chrome/browser/ui/gtk/bookmark_bar_gtk.h"
 #endif
 
 using base::Time;
@@ -88,7 +88,7 @@
 
 // Get the CSS string for the background position on the new tab page for the
 // states when the bar is attached or detached.
-std::string GetNewTabBackgroundCSS(const ThemeProvider* theme_provider,
+std::string GetNewTabBackgroundCSS(const ui::ThemeProvider* theme_provider,
                                    bool bar_attached) {
   int alignment;
   theme_provider->GetDisplayProperty(
@@ -129,7 +129,8 @@
 
 // How the background image on the new tab page should be tiled (see tiling
 // masks in browser_theme_provider.h).
-std::string GetNewTabBackgroundTilingCSS(const ThemeProvider* theme_provider) {
+std::string GetNewTabBackgroundTilingCSS(
+    const ui::ThemeProvider* theme_provider) {
   int repeat_mode;
   theme_provider->GetDisplayProperty(
       BrowserThemeProvider::NTP_BACKGROUND_TILING, &repeat_mode);
@@ -336,6 +337,8 @@
       l10n_util::GetStringUTF16(IDS_APPS_PROMO_TEXT_1));
   localized_strings.SetString("appspromotext2",
       l10n_util::GetStringUTF16(IDS_APPS_PROMO_TEXT_2));
+  localized_strings.SetString("syncpromotext",
+      l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL));
 #if defined(OS_CHROMEOS)
   localized_strings.SetString("expandMenu",
       l10n_util::GetStringUTF16(IDS_NEW_TAB_CLOSE_MENU_EXPAND));
@@ -365,8 +368,8 @@
   if (profile_->GetPrefs()->FindPreference(prefs::kNTPCustomLogoStart) &&
       profile_->GetPrefs()->FindPreference(prefs::kNTPCustomLogoEnd)) {
     localized_strings.SetString("customlogo",
-        InDateRange(profile_->GetPrefs()->GetReal(prefs::kNTPCustomLogoStart),
-                    profile_->GetPrefs()->GetReal(prefs::kNTPCustomLogoEnd)) ?
+        InDateRange(profile_->GetPrefs()->GetDouble(prefs::kNTPCustomLogoStart),
+                    profile_->GetPrefs()->GetDouble(prefs::kNTPCustomLogoEnd)) ?
         "true" : "false");
   } else {
     localized_strings.SetString("customlogo", "false");
@@ -379,8 +382,8 @@
       profile_->GetPrefs()->FindPreference(prefs::kNTPPromoLine) &&
       WebResourceServiceUtil::CanShowPromo(profile_)) {
     localized_strings.SetString("serverpromo",
-        InDateRange(profile_->GetPrefs()->GetReal(prefs::kNTPPromoStart),
-                    profile_->GetPrefs()->GetReal(prefs::kNTPPromoEnd)) ?
+        InDateRange(profile_->GetPrefs()->GetDouble(prefs::kNTPPromoStart),
+                    profile_->GetPrefs()->GetDouble(prefs::kNTPPromoEnd)) ?
                     profile_->GetPrefs()->GetString(prefs::kNTPPromoLine) :
                                                     std::string());
   }
@@ -415,7 +418,7 @@
 }
 
 void NTPResourceCache::CreateNewTabIncognitoCSS() {
-  ThemeProvider* tp = profile_->GetThemeProvider();
+  ui::ThemeProvider* tp = profile_->GetThemeProvider();
   DCHECK(tp);
 
   // Get our theme colors
@@ -451,7 +454,7 @@
 }
 
 void NTPResourceCache::CreateNewTabCSS() {
-  ThemeProvider* tp = profile_->GetThemeProvider();
+  ui::ThemeProvider* tp = profile_->GetThemeProvider();
   DCHECK(tp);
 
   // Get our theme colors
diff --git a/chrome/browser/dom_ui/options/OWNERS b/chrome/browser/dom_ui/options/OWNERS
new file mode 100644
index 0000000..67257e6
--- /dev/null
+++ b/chrome/browser/dom_ui/options/OWNERS
@@ -0,0 +1,4 @@
+csilv@chromium.org
+estade@chromium.org
+jhawkins@chromium.org
+stuartmorgan@chromium.org
diff --git a/chrome/browser/dom_ui/options/about_page_handler.cc b/chrome/browser/dom_ui/options/about_page_handler.cc
index 8100392..703d1f9 100644
--- a/chrome/browser/dom_ui/options/about_page_handler.cc
+++ b/chrome/browser/dom_ui/options/about_page_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -27,6 +25,8 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/glue/webkit_glue.h"
 
 #if defined(CHROME_V8)
@@ -37,6 +37,7 @@
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/power_library.h"
 #include "chrome/browser/chromeos/cros/update_library.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #endif
 
@@ -62,45 +63,6 @@
   return text.substr(start, end - start);
 }
 
-struct LocalizeEntry {
-  const char* identifier;
-  int resource;
-};
-
-const LocalizeEntry localize_table[] = {
-#if defined (OS_CHROMEOS)
-    { "product", IDS_PRODUCT_OS_NAME },
-    { "os", IDS_PRODUCT_OS_NAME },
-    { "loading", IDS_ABOUT_PAGE_LOADING },
-    { "check_now", IDS_ABOUT_PAGE_CHECK_NOW },
-    { "update_status", IDS_UPGRADE_CHECK_STARTED },
-    { "restart_now", IDS_RESTART_AND_UPDATE },
-#else
-    { "product", IDS_PRODUCT_NAME },
-    { "check_now", IDS_ABOUT_CHROME_UPDATE_CHECK },
-#endif
-    { "browser", IDS_PRODUCT_NAME },
-    { "more_info", IDS_ABOUT_PAGE_MORE_INFO },
-    { "copyright", IDS_ABOUT_VERSION_COPYRIGHT },
-    { "channel", IDS_ABOUT_PAGE_CHANNEL },
-    { "release", IDS_ABOUT_PAGE_CHANNEL_RELEASE },
-    { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA },
-    { "development", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT },
-    { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY },
-    { "channel_warning_header", IDS_ABOUT_PAGE_CHANNEL_WARNING_HEADER },
-    { "channel_warning_text", IDS_ABOUT_PAGE_CHANNEL_WARNING_TEXT },
-    { "user_agent", IDS_ABOUT_VERSION_USER_AGENT },
-    { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE },
-    { "aboutPage", IDS_ABOUT }
-};
-
-void LocalizedStrings(DictionaryValue* localized_strings) {
-  for (size_t n = 0; n != arraysize(localize_table); ++n) {
-    localized_strings->SetString(localize_table[n].identifier,
-        l10n_util::GetStringUTF16(localize_table[n].resource));
-  }
-}
-
 }  // namespace
 
 #if defined(OS_CHROMEOS)
@@ -143,7 +105,34 @@
 void AboutPageHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  LocalizedStrings(localized_strings);
+  static OptionsStringResource resources[] = {
+#if defined (OS_CHROMEOS)
+    { "product", IDS_PRODUCT_OS_NAME },
+    { "os", IDS_PRODUCT_OS_NAME },
+    { "loading", IDS_ABOUT_PAGE_LOADING },
+    { "check_now", IDS_ABOUT_PAGE_CHECK_NOW },
+    { "update_status", IDS_UPGRADE_CHECK_STARTED },
+    { "restart_now", IDS_RELAUNCH_AND_UPDATE },
+#else
+    { "product", IDS_PRODUCT_NAME },
+    { "check_now", IDS_ABOUT_CHROME_UPDATE_CHECK },
+#endif
+    { "browser", IDS_PRODUCT_NAME },
+    { "more_info", IDS_ABOUT_PAGE_MORE_INFO },
+    { "copyright", IDS_ABOUT_VERSION_COPYRIGHT },
+    { "channel", IDS_ABOUT_PAGE_CHANNEL },
+    { "release", IDS_ABOUT_PAGE_CHANNEL_RELEASE },
+    { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA },
+    { "development", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT },
+    { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY },
+    { "channel_warning_header", IDS_ABOUT_PAGE_CHANNEL_WARNING_HEADER },
+    { "channel_warning_text", IDS_ABOUT_PAGE_CHANNEL_WARNING_TEXT },
+    { "user_agent", IDS_ABOUT_VERSION_USER_AGENT },
+    { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE },
+  };
+
+  RegisterStrings(localized_strings, resources, arraysize(resources));
+  RegisterTitle(localized_strings, "aboutPage", IDS_ABOUT_TAB_TITLE);
 
   // browser version
 
@@ -266,15 +255,15 @@
 }
 
 void AboutPageHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("PageReady",
+  web_ui_->RegisterMessageCallback("PageReady",
       NewCallback(this, &AboutPageHandler::PageReady));
-  dom_ui_->RegisterMessageCallback("SetReleaseTrack",
+  web_ui_->RegisterMessageCallback("SetReleaseTrack",
       NewCallback(this, &AboutPageHandler::SetReleaseTrack));
 
 #if defined(OS_CHROMEOS)
-  dom_ui_->RegisterMessageCallback("CheckNow",
+  web_ui_->RegisterMessageCallback("CheckNow",
       NewCallback(this, &AboutPageHandler::CheckNow));
-  dom_ui_->RegisterMessageCallback("RestartNow",
+  web_ui_->RegisterMessageCallback("RestartNow",
       NewCallback(this, &AboutPageHandler::RestartNow));
 #endif
 }
@@ -292,25 +281,29 @@
   // Update the channel information.
   std::string channel = update_library->GetReleaseTrack();
   scoped_ptr<Value> channel_string(Value::CreateStringValue(channel));
-  dom_ui_->CallJavascriptFunction(L"AboutPage.updateSelectedOptionCallback",
+  web_ui_->CallJavascriptFunction(L"AboutPage.updateSelectedOptionCallback",
                                   *channel_string);
 
   update_observer_.reset(new UpdateObserver(this));
   update_library->AddObserver(update_observer_.get());
 
-  // Update the DOMUI page with the current status. See comments below.
+  // Update the WebUI page with the current status. See comments below.
   UpdateStatus(update_library->status());
 
   // Initiate update check. UpdateStatus() below will be called when we
   // get update status via update_observer_. If the update has been
   // already complete, update_observer_ won't receive a notification.
-  // This is why we manually update the DOMUI page above.
+  // This is why we manually update the WebUI page above.
   CheckNow(NULL);
 #endif
 }
 
 void AboutPageHandler::SetReleaseTrack(const ListValue* args) {
 #if defined(OS_CHROMEOS)
+  if (!chromeos::UserManager::Get()->current_user_is_owner()) {
+    LOG(WARNING) << "Non-owner tried to change release track.";
+    return;
+  }
   const std::string channel = WideToUTF8(ExtractStringValue(args));
   chromeos::CrosLibrary::Get()->GetUpdateLibrary()->SetReleaseTrack(channel);
 #endif
@@ -398,20 +391,20 @@
     // can read it, hence insert delay for this.
     scoped_ptr<Value> insert_delay(Value::CreateBooleanValue(
         status.status == chromeos::UPDATE_STATUS_CHECKING_FOR_UPDATE));
-    dom_ui_->CallJavascriptFunction(L"AboutPage.updateStatusCallback",
+    web_ui_->CallJavascriptFunction(L"AboutPage.updateStatusCallback",
                                     *update_message, *insert_delay);
 
     scoped_ptr<Value> enabled_value(Value::CreateBooleanValue(enabled));
-    dom_ui_->CallJavascriptFunction(L"AboutPage.updateEnableCallback",
+    web_ui_->CallJavascriptFunction(L"AboutPage.updateEnableCallback",
                                     *enabled_value);
 
     scoped_ptr<Value> image_string(Value::CreateStringValue(image));
-    dom_ui_->CallJavascriptFunction(L"AboutPage.setUpdateImage",
+    web_ui_->CallJavascriptFunction(L"AboutPage.setUpdateImage",
                                     *image_string);
   }
   // We'll change the "Check For Update" button to "Restart" button.
   if (status.status == chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
-    dom_ui_->CallJavascriptFunction(L"AboutPage.changeToRestartButton");
+    web_ui_->CallJavascriptFunction(L"AboutPage.changeToRestartButton");
   }
 }
 
@@ -419,7 +412,7 @@
                                    std::string version) {
   if (version.size()) {
     scoped_ptr<Value> version_string(Value::CreateStringValue(version));
-    dom_ui_->CallJavascriptFunction(L"AboutPage.updateOSVersionCallback",
+    web_ui_->CallJavascriptFunction(L"AboutPage.updateOSVersionCallback",
                                     *version_string);
   }
 }
diff --git a/chrome/browser/dom_ui/options/add_startup_page_handler.cc b/chrome/browser/dom_ui/options/add_startup_page_handler.cc
index 33b2326..9ecf5d0 100644
--- a/chrome/browser/dom_ui/options/add_startup_page_handler.cc
+++ b/chrome/browser/dom_ui/options/add_startup_page_handler.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/add_startup_page_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
@@ -15,6 +14,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 AddStartupPageHandler::AddStartupPageHandler() {
 }
@@ -27,8 +27,7 @@
 void AddStartupPageHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  localized_strings->SetString("addStartupPageTitle",
-      l10n_util::GetStringUTF16(IDS_ASI_ADD_TITLE));
+  RegisterTitle(localized_strings, "addStartupPage", IDS_ASI_ADD_TITLE);
   localized_strings->SetString("addStartupPageURLLabel",
       l10n_util::GetStringUTF16(IDS_ASI_URL));
   localized_strings->SetString("addStartupPageAddButton",
@@ -41,12 +40,12 @@
   url_table_model_.reset(new PossibleURLModel());
   if (url_table_model_.get()) {
     url_table_model_->SetObserver(this);
-    url_table_model_->Reload(dom_ui_->GetProfile());
+    url_table_model_->Reload(web_ui_->GetProfile());
   }
 }
 
 void AddStartupPageHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "updateAddStartupFieldWithPage",
       NewCallback(this, &AddStartupPageHandler::UpdateFieldWithRecentPage));
 }
@@ -58,7 +57,7 @@
     return;
   }
   std::string languages =
-      dom_ui_->GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
+      web_ui_->GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
   // Because this gets parsed by FixupURL(), it's safe to omit the scheme or
   // trailing slash, and unescape most characters, but we need to not drop any
   // username/password, or unescape anything that changes the meaning.
@@ -67,7 +66,7 @@
       UnescapeRule::SPACES, NULL, NULL, NULL);
 
   scoped_ptr<Value> url_value(Value::CreateStringValue(url_string));
-  dom_ui_->CallJavascriptFunction(L"AddStartupPageOverlay.setInputFieldValue",
+  web_ui_->CallJavascriptFunction(L"AddStartupPageOverlay.setInputFieldValue",
                                   *url_value.get());
 }
 
@@ -82,7 +81,7 @@
     pages.Append(dict);
   }
 
-  dom_ui_->CallJavascriptFunction(L"AddStartupPageOverlay.updateRecentPageList",
+  web_ui_->CallJavascriptFunction(L"AddStartupPageOverlay.updateRecentPageList",
                                   pages);
 }
 
diff --git a/chrome/browser/dom_ui/options/add_startup_page_handler.h b/chrome/browser/dom_ui/options/add_startup_page_handler.h
index 9ca2e2a..da87a82 100644
--- a/chrome/browser/dom_ui/options/add_startup_page_handler.h
+++ b/chrome/browser/dom_ui/options/add_startup_page_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,15 +6,15 @@
 #define CHROME_BROWSER_DOM_UI_OPTIONS_ADD_STARTUP_PAGE_HANDLER_H_
 #pragma once
 
-#include "app/table_model_observer.h"
 #include "base/basictypes.h"
 #include "chrome/browser/dom_ui/options/options_ui.h"
+#include "ui/base/models/table_model_observer.h"
 
 class PossibleURLModel;
 
 // Chrome personal options page UI handler.
 class AddStartupPageHandler : public OptionsPageUIHandler,
-                              public TableModelObserver {
+                              public ui::TableModelObserver {
  public:
   AddStartupPageHandler();
   virtual ~AddStartupPageHandler();
@@ -24,7 +24,7 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void RegisterMessages();
 
-  // TableModelObserver implementation.
+  // ui::TableModelObserver implementation.
   virtual void OnModelChanged();
   virtual void OnItemsChanged(int start, int length);
   virtual void OnItemsAdded(int start, int length);
@@ -32,7 +32,7 @@
 
  private:
   // Request to update the text field with the URL of the recent page at the
-  // given index, formatted for user input. Called from DOMUI.
+  // given index, formatted for user input. Called from WebUI.
   void UpdateFieldWithRecentPage(const ListValue* args);
 
   scoped_ptr<PossibleURLModel> url_table_model_;
diff --git a/chrome/browser/dom_ui/options/advanced_options_handler.cc b/chrome/browser/dom_ui/options/advanced_options_handler.cc
index 9d66ee9..a5b841b 100644
--- a/chrome/browser/dom_ui/options/advanced_options_handler.cc
+++ b/chrome/browser/dom_ui/options/advanced_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -24,6 +23,8 @@
 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/remoting/setup_flow.h"
+#include "chrome/browser/service/service_process_control.h"
+#include "chrome/browser/service/service_process_control_manager.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/ui/options/options_util.h"
@@ -36,6 +37,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(OS_CHROMEOS)
 #include "chrome/browser/browser_process.h"
@@ -64,143 +66,136 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
+  static OptionsStringResource resources[] = {
+    { "downloadLocationGroupName",
+      IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME },
+    { "downloadLocationChangeButton",
+      IDS_OPTIONS_DOWNLOADLOCATION_CHANGE_BUTTON },
+    { "downloadLocationBrowseTitle",
+      IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE },
+    { "downloadLocationBrowseWindowTitle",
+      IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE },
+    { "downloadLocationAskForSaveLocation",
+      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION },
+    { "autoOpenFileTypesInfo",
+      IDS_OPTIONS_OPEN_FILE_TYPES_AUTOMATICALLY },
+    { "autoOpenFileTypesResetToDefault",
+      IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT },
+    { "gearSettingsConfigureGearsButton",
+      IDS_OPTIONS_GEARSSETTINGS_CONFIGUREGEARS_BUTTON },
+    { "translateEnableTranslate",
+      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE },
+    { "certificatesManageButton",
+      IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON },
+    { "proxiesLabel",
+      IDS_OPTIONS_PROXIES_LABEL },
+    { "proxiesConfigureButton",
+      IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON },
+    { "safeBrowsingEnableProtection",
+      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION },
+    { "sslGroupDescription",
+      IDS_OPTIONS_SSL_GROUP_DESCRIPTION },
+    { "sslCheckRevocation",
+      IDS_OPTIONS_SSL_CHECKREVOCATION },
+    { "sslUseSSL3",
+      IDS_OPTIONS_SSL_USESSL3 },
+    { "sslUseTLS1",
+      IDS_OPTIONS_SSL_USETLS1 },
+    { "networkDNSPrefetchEnabledDescription",
+      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION },
+    { "privacyContentSettingsButton",
+      IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON },
+    { "privacyClearDataButton",
+      IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON },
+    { "linkDoctorPref",
+      IDS_OPTIONS_LINKDOCTOR_PREF },
+    { "suggestPref",
+      IDS_OPTIONS_SUGGEST_PREF },
+    { "tabsToLinksPref",
+      IDS_OPTIONS_TABS_TO_LINKS_PREF },
+    { "fontSettingsInfo",
+      IDS_OPTIONS_FONTSETTINGS_INFO },
+    { "defaultZoomLevelLabel",
+      IDS_OPTIONS_DEFAULT_ZOOM_LEVEL_LABEL },
+    { "defaultFontSizeLabel",
+      IDS_OPTIONS_DEFAULT_FONT_SIZE_LABEL },
+    { "fontSizeLabelVerySmall",
+      IDS_OPTIONS_FONT_SIZE_LABEL_VERY_SMALL },
+    { "fontSizeLabelSmall",
+      IDS_OPTIONS_FONT_SIZE_LABEL_SMALL },
+    { "fontSizeLabelMedium",
+      IDS_OPTIONS_FONT_SIZE_LABEL_MEDIUM },
+    { "fontSizeLabelLarge",
+      IDS_OPTIONS_FONT_SIZE_LABEL_LARGE },
+    { "fontSizeLabelVeryLarge",
+      IDS_OPTIONS_FONT_SIZE_LABEL_VERY_LARGE },
+    { "fontSizeLabelCustom",
+      IDS_OPTIONS_FONT_SIZE_LABEL_CUSTOM },
+    { "fontSettingsCustomizeFontsButton",
+      IDS_OPTIONS_FONTSETTINGS_CUSTOMIZE_FONTS_BUTTON },
+    { "languageAndSpellCheckSettingsButton",
+      IDS_OPTIONS_LANGUAGE_AND_SPELLCHECK_BUTTON },
+    { "advancedSectionTitlePrivacy",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY },
+    { "advancedSectionTitleContent",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT },
+    { "advancedSectionTitleSecurity",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY },
+    { "advancedSectionTitleNetwork",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK },
+    { "advancedSectionTitleTranslate",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE },
+    { "translateEnableTranslate",
+      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE },
+    { "enableLogging",
+      IDS_OPTIONS_ENABLE_LOGGING },
+    { "improveBrowsingExperience",
+      IDS_OPTIONS_IMPROVE_BROWSING_EXPERIENCE },
+    { "disableWebServices",
+      IDS_OPTIONS_DISABLE_WEB_SERVICES },
+#if !defined(OS_CHROMEOS)
+    { "advancedSectionTitleCloudPrint",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_CLOUD_PRINT },
+    { "cloudPrintProxyDisabledLabel",
+      IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_LABEL },
+    { "cloudPrintProxyDisabledButton",
+      IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_BUTTON },
+    { "cloudPrintProxyEnabledButton",
+      IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_BUTTON },
+    { "cloudPrintProxyEnabledManageButton",
+      IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_MANAGE_BUTTON },
+    { "cloudPrintProxyEnablingButton",
+      IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLING_BUTTON },
+#endif
+#if defined(ENABLE_REMOTING)
+    { "advancedSectionTitleRemoting",
+      IDS_OPTIONS_ADVANCED_SECTION_TITLE_REMOTING },
+    { "remotingSetupButton",
+      IDS_OPTIONS_REMOTING_SETUP_BUTTON },
+    { "remotingStopButton",
+      IDS_OPTIONS_REMOTING_STOP_BUTTON },
+#endif
+  };
+
+  RegisterStrings(localized_strings, resources, arraysize(resources));
+  RegisterTitle(localized_strings, "advancedPage",
+                IDS_OPTIONS_ADVANCED_TAB_LABEL);
+
   localized_strings->SetString("privacyLearnMoreURL",
       google_util::AppendGoogleLocaleParam(
           GURL(chrome::kPrivacyLearnMoreURL)).spec());
-  localized_strings->SetString("downloadLocationGroupName",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME));
-  localized_strings->SetString("downloadLocationChangeButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_CHANGE_BUTTON));
-  localized_strings->SetString("downloadLocationBrowseTitle",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE));
-  localized_strings->SetString("downloadLocationBrowseWindowTitle",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE));
-  localized_strings->SetString("downloadLocationAskForSaveLocation",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION));
-  localized_strings->SetString("autoOpenFileTypesInfo",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_OPEN_FILE_TYPES_AUTOMATICALLY));
-  localized_strings->SetString("autoOpenFileTypesResetToDefault",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT));
-  localized_strings->SetString("gearSettingsGroupName",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_GEARSSETTINGS_GROUP_NAME)));
-  localized_strings->SetString("gearSettingsConfigureGearsButton",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_GEARSSETTINGS_CONFIGUREGEARS_BUTTON));
-  localized_strings->SetString("translateEnableTranslate",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE));
-  localized_strings->SetString("certificatesManageButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON));
-  localized_strings->SetString("proxiesLabel",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_PROXIES_LABEL));
-  localized_strings->SetString("proxiesConfigureButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON));
-  localized_strings->SetString("safeBrowsingEnableProtection",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION));
-  localized_strings->SetString("sslGroupDescription",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SSL_GROUP_DESCRIPTION));
-  localized_strings->SetString("sslCheckRevocation",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SSL_CHECKREVOCATION));
-  localized_strings->SetString("sslUseSSL3",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SSL_USESSL3));
-  localized_strings->SetString("sslUseTLS1",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SSL_USETLS1));
-  localized_strings->SetString("networkDNSPrefetchEnabledDescription",
-      l10n_util::GetStringUTF16(IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION));
-  localized_strings->SetString("privacyContentSettingsButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON));
-  localized_strings->SetString("privacyClearDataButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON));
-  localized_strings->SetString("linkDoctorPref",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_LINKDOCTOR_PREF));
-  localized_strings->SetString("suggestPref",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_SUGGEST_PREF));
-  localized_strings->SetString("tabsToLinksPref",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_TABS_TO_LINKS_PREF));
-  localized_strings->SetString("fontSettingsInfo",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONTSETTINGS_INFO));
-  localized_strings->SetString("defaultZoomLevelLabel",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULT_ZOOM_LEVEL_LABEL));
-  localized_strings->SetString("defaultFontSizeLabel",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULT_FONT_SIZE_LABEL));
-  localized_strings->SetString("fontSizeLabelVerySmall",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONT_SIZE_LABEL_VERY_SMALL));
-  localized_strings->SetString("fontSizeLabelSmall",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONT_SIZE_LABEL_SMALL));
-  localized_strings->SetString("fontSizeLabelMedium",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONT_SIZE_LABEL_MEDIUM));
-  localized_strings->SetString("fontSizeLabelLarge",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONT_SIZE_LABEL_LARGE));
-  localized_strings->SetString("fontSizeLabelVeryLarge",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONT_SIZE_LABEL_VERY_LARGE));
-  localized_strings->SetString("fontSizeLabelCustom",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_FONT_SIZE_LABEL_CUSTOM));
-  localized_strings->SetString("fontSettingsCustomizeFontsButton",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_FONTSETTINGS_CUSTOMIZE_FONTS_BUTTON));
-  localized_strings->SetString("advancedSectionTitlePrivacy",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(
-              IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY)));
-  localized_strings->SetString("advancedSectionTitleContent",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(
-              IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT)));
-  localized_strings->SetString("advancedSectionTitleSecurity",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(
-              IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY)));
-  localized_strings->SetString("advancedSectionTitleNetwork",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(
-              IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK)));
-  localized_strings->SetString("advancedSectionTitleTranslate",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(
-              IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE)));
-  localized_strings->SetString("translateEnableTranslate",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE));
 #if !defined(OS_CHROMEOS)
   // Add the cloud print proxy management ui section if it's been runtime
   // enabled.
-  localized_strings->SetString("enable-cloud-print-proxy",
-      cloud_print_proxy_ui_enabled_ ? "true" : "false");
-  localized_strings->SetString("advancedSectionTitleCloudPrint",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_ADVANCED_SECTION_TITLE_CLOUD_PRINT));
-  localized_strings->SetString("cloudPrintProxyDisabledLabel",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_LABEL));
-  localized_strings->SetString("cloudPrintProxyDisabledButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_BUTTON));
-  localized_strings->SetString("cloudPrintProxyEnabledButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_BUTTON));
-  localized_strings->SetString("cloudPrintProxyEnabledManageButton",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_MANAGE_BUTTON));
-  localized_strings->SetString("cloudPrintProxyEnablingButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLING_BUTTON));
+  localized_strings->SetBoolean("enable-cloud-print-proxy",
+                                cloud_print_proxy_ui_enabled_);
 #endif
-#if defined(ENABLE_REMOTING)
-  localized_strings->SetString("advancedSectionTitleRemoting",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_ADVANCED_SECTION_TITLE_REMOTING));
-  localized_strings->SetString("remotingSetupButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_REMOTING_SETUP_BUTTON));
-#endif
-  localized_strings->SetString("enableLogging",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_LOGGING));
-  localized_strings->SetString("improveBrowsingExperience",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_IMPROVE_BROWSING_EXPERIENCE));
-  localized_strings->SetString("disableWebServices",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DISABLE_WEB_SERVICES));
 }
 
 void AdvancedOptionsHandler::Initialize() {
-  DCHECK(dom_ui_);
+  DCHECK(web_ui_);
   SetupMetricsReportingCheckbox();
   SetupMetricsReportingSettingVisibility();
-  SetupDefaultZoomLevel();
   SetupFontSizeLabel();
   SetupDownloadLocationPath();
   SetupAutoOpenFileTypesDisabledAttribute();
@@ -216,36 +211,37 @@
     RemoveCloudPrintProxySection();
   }
 #endif
-#if defined(ENABLE_REMOTING)
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableRemoting)) {
+#if defined(ENABLE_REMOTING) && !defined(OS_CHROMEOS)
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableRemoting)) {
     RemoveRemotingSection();
+  } else {
+    remoting_options_handler_.Init(web_ui_);
   }
 #endif
 
   banner_handler_.reset(
-      new OptionsManagedBannerHandler(dom_ui_,
+      new OptionsManagedBannerHandler(web_ui_,
                                       ASCIIToUTF16("AdvancedOptions"),
                                       OPTIONS_PAGE_ADVANCED));
 }
 
-DOMMessageHandler* AdvancedOptionsHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* AdvancedOptionsHandler::Attach(WebUI* web_ui) {
   // Call through to superclass.
-  DOMMessageHandler* handler = OptionsPageUIHandler::Attach(dom_ui);
+  WebUIMessageHandler* handler = OptionsPageUIHandler::Attach(web_ui);
 
   // Register for preferences that we need to observe manually.  These have
   // special behaviors that aren't handled by the standard prefs UI.
-  DCHECK(dom_ui_);
-  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();
+  DCHECK(web_ui_);
+  PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
 #if !defined(OS_CHROMEOS)
   enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled,
                                  g_browser_process->local_state(), this);
   cloud_print_proxy_email_.Init(prefs::kCloudPrintEmail, prefs, this);
+  cloud_print_proxy_enabled_.Init(prefs::kCloudPrintProxyEnabled, prefs, this);
 #endif
   default_download_location_.Init(prefs::kDownloadDefaultDirectory,
                                   prefs, this);
   auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, prefs, this);
-  default_zoom_level_.Init(prefs::kDefaultZoomLevel, prefs, this);
   default_font_size_.Init(prefs::kWebKitDefaultFontSize, prefs, this);
   default_fixed_font_size_.Init(prefs::kWebKitDefaultFixedFontSize, prefs,
                                 this);
@@ -258,60 +254,61 @@
 
 void AdvancedOptionsHandler::RegisterMessages() {
   // Setup handlers specific to this panel.
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("selectDownloadLocation",
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("selectDownloadLocation",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleSelectDownloadLocation));
-  dom_ui_->RegisterMessageCallback("autoOpenFileTypesAction",
+  web_ui_->RegisterMessageCallback("autoOpenFileTypesAction",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleAutoOpenButton));
-  dom_ui_->RegisterMessageCallback("defaultZoomLevelAction",
-      NewCallback(this, &AdvancedOptionsHandler::HandleDefaultZoomLevel));
-  dom_ui_->RegisterMessageCallback("defaultFontSizeAction",
+  web_ui_->RegisterMessageCallback("defaultFontSizeAction",
       NewCallback(this, &AdvancedOptionsHandler::HandleDefaultFontSize));
 #if !defined(OS_CHROMEOS)
-  dom_ui_->RegisterMessageCallback("metricsReportingCheckboxAction",
+  web_ui_->RegisterMessageCallback("metricsReportingCheckboxAction",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleMetricsReportingCheckbox));
 #endif
 #if !defined(USE_NSS) && !defined(USE_OPENSSL)
-  dom_ui_->RegisterMessageCallback("showManageSSLCertificates",
+  web_ui_->RegisterMessageCallback("showManageSSLCertificates",
       NewCallback(this,
                   &AdvancedOptionsHandler::ShowManageSSLCertificates));
 #endif
 #if !defined(OS_CHROMEOS)
   if (cloud_print_proxy_ui_enabled_) {
-    dom_ui_->RegisterMessageCallback("showCloudPrintSetupDialog",
+    web_ui_->RegisterMessageCallback("showCloudPrintSetupDialog",
         NewCallback(this,
                     &AdvancedOptionsHandler::ShowCloudPrintSetupDialog));
-    dom_ui_->RegisterMessageCallback("disableCloudPrintProxy",
+    web_ui_->RegisterMessageCallback("disableCloudPrintProxy",
         NewCallback(this,
                     &AdvancedOptionsHandler::HandleDisableCloudPrintProxy));
-    dom_ui_->RegisterMessageCallback("showCloudPrintManagePage",
+    web_ui_->RegisterMessageCallback("showCloudPrintManagePage",
         NewCallback(this,
                     &AdvancedOptionsHandler::ShowCloudPrintManagePage));
   }
-  dom_ui_->RegisterMessageCallback("showNetworkProxySettings",
+  web_ui_->RegisterMessageCallback("showNetworkProxySettings",
       NewCallback(this,
                   &AdvancedOptionsHandler::ShowNetworkProxySettings));
 #endif
-#if defined(ENABLE_REMOTING)
-  dom_ui_->RegisterMessageCallback("showRemotingSetupDialog",
+#if defined(ENABLE_REMOTING) && !defined(OS_CHROMEOS)
+  web_ui_->RegisterMessageCallback("showRemotingSetupDialog",
       NewCallback(this,
                   &AdvancedOptionsHandler::ShowRemotingSetupDialog));
+  web_ui_->RegisterMessageCallback("disableRemoting",
+      NewCallback(this,
+                  &AdvancedOptionsHandler::DisableRemoting));
 #endif
 #if defined(OS_WIN)
   // Setup Windows specific callbacks.
-  dom_ui_->RegisterMessageCallback("checkRevocationCheckboxAction",
+  web_ui_->RegisterMessageCallback("checkRevocationCheckboxAction",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleCheckRevocationCheckbox));
-  dom_ui_->RegisterMessageCallback("useSSL3CheckboxAction",
+  web_ui_->RegisterMessageCallback("useSSL3CheckboxAction",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleUseSSL3Checkbox));
-  dom_ui_->RegisterMessageCallback("useTLS1CheckboxAction",
+  web_ui_->RegisterMessageCallback("useTLS1CheckboxAction",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleUseTLS1Checkbox));
-  dom_ui_->RegisterMessageCallback("showGearsSettings",
+  web_ui_->RegisterMessageCallback("showGearsSettings",
       NewCallback(this,
                   &AdvancedOptionsHandler::HandleShowGearsSettings));
 #endif
@@ -328,7 +325,8 @@
       SetupAutoOpenFileTypesDisabledAttribute();
     } else if (proxy_prefs_->IsObserved(*pref_name)) {
       SetupProxySettingsSection();
-    } else if (*pref_name == prefs::kCloudPrintEmail) {
+    } else if ((*pref_name == prefs::kCloudPrintEmail) ||
+               (*pref_name == prefs::kCloudPrintProxyEnabled)) {
 #if !defined(OS_CHROMEOS)
       if (cloud_print_proxy_ui_enabled_)
         SetupCloudPrintProxySection();
@@ -342,14 +340,14 @@
 
 void AdvancedOptionsHandler::HandleSelectDownloadLocation(
     const ListValue* args) {
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
   select_folder_dialog_ = SelectFileDialog::Create(this);
   select_folder_dialog_->SelectFile(
       SelectFileDialog::SELECT_FOLDER,
       l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE),
       pref_service->GetFilePath(prefs::kDownloadDefaultDirectory),
       NULL, 0, FILE_PATH_LITERAL(""),
-      dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
+      web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
 }
 
 void AdvancedOptionsHandler::FileSelected(const FilePath& path, int index,
@@ -368,7 +366,7 @@
 
 void AdvancedOptionsHandler::HandleAutoOpenButton(const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_ResetAutoOpenFiles"));
-  DownloadManager* manager = dom_ui_->GetProfile()->GetDownloadManager();
+  DownloadManager* manager = web_ui_->GetProfile()->GetDownloadManager();
   if (manager)
     manager->download_prefs()->ResetAutoOpen();
 }
@@ -377,7 +375,7 @@
     const ListValue* args) {
 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_CHROMEOS)
   std::string checked_str = WideToUTF8(ExtractStringValue(args));
-  bool enabled = (checked_str == "true");
+  bool enabled = checked_str == "true";
   UserMetricsRecordAction(
       enabled ?
           UserMetricsAction("Options_MetricsReportingCheckbox_Enable") :
@@ -388,14 +386,6 @@
 #endif
 }
 
-void AdvancedOptionsHandler::HandleDefaultZoomLevel(const ListValue* args) {
-  UserMetricsRecordAction(UserMetricsAction("Options_ChangeDefaultZoomLevel"));
-  int zoom_level;
-  if (ExtractIntegerValue(args, &zoom_level)) {
-    default_zoom_level_.SetValue(static_cast<double>(zoom_level));
-  }
-}
-
 void AdvancedOptionsHandler::HandleDefaultFontSize(const ListValue* args) {
   int font_size;
   if (ExtractIntegerValue(args, &font_size)) {
@@ -411,7 +401,7 @@
 void AdvancedOptionsHandler::HandleCheckRevocationCheckbox(
     const ListValue* args) {
   std::string checked_str = WideToUTF8(ExtractStringValue(args));
-  bool enabled = (checked_str == "true");
+  bool enabled = checked_str == "true";
   std::string metric =
       (enabled ? "Options_CheckCertRevocation_Enable"
                : "Options_CheckCertRevocation_Disable");
@@ -421,7 +411,7 @@
 
 void AdvancedOptionsHandler::HandleUseSSL3Checkbox(const ListValue* args) {
   std::string checked_str = WideToUTF8(ExtractStringValue(args));
-  bool enabled = (checked_str == "true");
+  bool enabled = checked_str == "true";
   std::string metric =
       (enabled ? "Options_SSL3_Enable" : "Options_SSL3_Disable");
   UserMetricsRecordAction(UserMetricsAction(metric.c_str()));
@@ -430,7 +420,7 @@
 
 void AdvancedOptionsHandler::HandleUseTLS1Checkbox(const ListValue* args) {
   std::string checked_str = WideToUTF8(ExtractStringValue(args));
-  bool enabled = (checked_str == "true");
+  bool enabled = checked_str == "true";
   std::string metric =
       (enabled ? "Options_TLS1_Enable" : "Options_TLS1_Disable");
   UserMetricsRecordAction(UserMetricsAction(metric.c_str()));
@@ -440,21 +430,21 @@
 void AdvancedOptionsHandler::HandleShowGearsSettings(const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_GearsSettings"));
   GearsSettingsPressed(
-      dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow());
+      web_ui_->tab_contents()->view()->GetTopLevelNativeWindow());
 }
 #endif
 
 #if !defined(OS_CHROMEOS)
 void AdvancedOptionsHandler::ShowNetworkProxySettings(const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_ShowProxySettings"));
-  AdvancedOptionsUtilities::ShowNetworkProxySettings(dom_ui_->tab_contents());
+  AdvancedOptionsUtilities::ShowNetworkProxySettings(web_ui_->tab_contents());
 }
 #endif
 
 #if !defined(USE_NSS) && !defined(USE_OPENSSL)
 void AdvancedOptionsHandler::ShowManageSSLCertificates(const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_ManageSSLCertificates"));
-  AdvancedOptionsUtilities::ShowManageSSLCertificates(dom_ui_->tab_contents());
+  AdvancedOptionsUtilities::ShowManageSSLCertificates(web_ui_->tab_contents());
 }
 #endif
 
@@ -462,42 +452,49 @@
 void AdvancedOptionsHandler::ShowCloudPrintSetupDialog(const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_EnableCloudPrintProxy"));
   CloudPrintSetupFlow::OpenDialog(
-      dom_ui_->GetProfile(), this,
-      dom_ui_->tab_contents()->GetMessageBoxRootWindow());
+      web_ui_->GetProfile(), this,
+      web_ui_->tab_contents()->GetMessageBoxRootWindow());
 }
 
 void AdvancedOptionsHandler::HandleDisableCloudPrintProxy(
     const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_DisableCloudPrintProxy"));
-  dom_ui_->GetProfile()->GetCloudPrintProxyService()->DisableForUser();
+  web_ui_->GetProfile()->GetCloudPrintProxyService()->DisableForUser();
 }
 
 void AdvancedOptionsHandler::ShowCloudPrintManagePage(const ListValue* args) {
   UserMetricsRecordAction(UserMetricsAction("Options_ManageCloudPrinters"));
   // Open a new tab in the current window for the management page.
-  dom_ui_->tab_contents()->OpenURL(
-      CloudPrintURL(dom_ui_->GetProfile()).GetCloudPrintServiceManageURL(),
+  web_ui_->tab_contents()->OpenURL(
+      CloudPrintURL(web_ui_->GetProfile()).GetCloudPrintServiceManageURL(),
       GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
 }
 
 void AdvancedOptionsHandler::RefreshCloudPrintStatusFromService() {
-  DCHECK(dom_ui_);
+  DCHECK(web_ui_);
   if (cloud_print_proxy_ui_enabled_)
-    dom_ui_->GetProfile()->GetCloudPrintProxyService()->
+    web_ui_->GetProfile()->GetCloudPrintProxyService()->
         RefreshStatusFromService();
 }
 
 void AdvancedOptionsHandler::SetupCloudPrintProxySection() {
-  if (NULL == dom_ui_->GetProfile()->GetCloudPrintProxyService()) {
+  if (NULL == web_ui_->GetProfile()->GetCloudPrintProxyService()) {
     cloud_print_proxy_ui_enabled_ = false;
     RemoveCloudPrintProxySection();
     return;
   }
 
+  bool cloud_print_proxy_allowed =
+      !cloud_print_proxy_enabled_.IsManaged() ||
+      cloud_print_proxy_enabled_.GetValue();
+  FundamentalValue allowed(cloud_print_proxy_allowed);
+
   std::string email;
-  if (dom_ui_->GetProfile()->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail))
-    email = dom_ui_->GetProfile()->GetPrefs()->GetString(
+  if (web_ui_->GetProfile()->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
+      cloud_print_proxy_allowed) {
+    email = web_ui_->GetProfile()->GetPrefs()->GetString(
         prefs::kCloudPrintEmail);
+  }
   FundamentalValue disabled(email.empty());
 
   string16 label_str;
@@ -510,26 +507,35 @@
   }
   StringValue label(label_str);
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetupCloudPrintProxySection",
-      disabled, label);
+      disabled, label, allowed);
 }
 
 void AdvancedOptionsHandler::RemoveCloudPrintProxySection() {
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.RemoveCloudPrintProxySection");
 }
 
 #endif
 
-#if defined(ENABLE_REMOTING)
+#if defined(ENABLE_REMOTING) && !defined(OS_CHROMEOS)
 void AdvancedOptionsHandler::RemoveRemotingSection() {
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.RemoveRemotingSection");
 }
 
 void AdvancedOptionsHandler::ShowRemotingSetupDialog(const ListValue* args) {
-  remoting::SetupFlow::OpenSetupDialog(dom_ui_->GetProfile());
+  remoting::SetupFlow::OpenSetupDialog(web_ui_->GetProfile());
+}
+
+void AdvancedOptionsHandler::DisableRemoting(const ListValue* args) {
+  ServiceProcessControl* process_control =
+      ServiceProcessControlManager::GetInstance()->GetProcessControl(
+          web_ui_->GetProfile());
+  if (!process_control || !process_control->is_connected())
+    return;
+  process_control->DisableRemotingHost();
 }
 #endif
 
@@ -537,7 +543,7 @@
 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_CHROMEOS)
   FundamentalValue checked(enable_metrics_recording_.GetValue());
   FundamentalValue disabled(enable_metrics_recording_.IsManaged());
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetMetricsReportingCheckboxState", checked,
       disabled);
 #endif
@@ -548,53 +554,46 @@
   // Don't show the reporting setting if we are in the guest mode.
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) {
     FundamentalValue visible(false);
-    dom_ui_->CallJavascriptFunction(
+    web_ui_->CallJavascriptFunction(
         L"options.AdvancedOptions.SetMetricsReportingSettingVisibility",
         visible);
   }
 #endif
 }
 
-void AdvancedOptionsHandler::SetupDefaultZoomLevel() {
-  // We're only interested in integer values, so convert to int.
-  FundamentalValue value(static_cast<int>(default_zoom_level_.GetValue()));
-  dom_ui_->CallJavascriptFunction(
-      L"options.AdvancedOptions.SetDefaultZoomLevel", value);
-}
-
 void AdvancedOptionsHandler::SetupFontSizeLabel() {
   // We're only interested in integer values, so convert to int.
   FundamentalValue fixed_font_size(default_fixed_font_size_.GetValue());
   FundamentalValue font_size(default_font_size_.GetValue());
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetFontSize", fixed_font_size,
       font_size);
 }
 
 void AdvancedOptionsHandler::SetupDownloadLocationPath() {
   StringValue value(default_download_location_.GetValue().value());
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetDownloadLocationPath", value);
 }
 
 void AdvancedOptionsHandler::SetupAutoOpenFileTypesDisabledAttribute() {
   // Set the enabled state for the AutoOpenFileTypesResetToDefault button.
   // We enable the button if the user has any auto-open file types registered.
-  DownloadManager* manager = dom_ui_->GetProfile()->GetDownloadManager();
+  DownloadManager* manager = web_ui_->GetProfile()->GetDownloadManager();
   bool disabled = !(manager && manager->download_prefs()->IsAutoOpenUsed());
   FundamentalValue value(disabled);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetAutoOpenFileTypesDisabledAttribute", value);
 }
 
 void AdvancedOptionsHandler::SetupProxySettingsSection() {
   // Disable the button if proxy settings are managed by a sysadmin or
   // overridden by an extension.
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
-  const PrefService::Preference* proxy_server =
-      pref_service->FindPreference(prefs::kProxyServer);
-  bool is_extension_controlled = (proxy_server &&
-                                  proxy_server->IsExtensionControlled());
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
+  const PrefService::Preference* proxy_config =
+      pref_service->FindPreference(prefs::kProxy);
+  bool is_extension_controlled = (proxy_config &&
+                                  proxy_config->IsExtensionControlled());
 
   FundamentalValue disabled(proxy_prefs_->IsManaged() ||
                             is_extension_controlled);
@@ -609,7 +608,7 @@
   }
   StringValue label(label_str);
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetupProxySettingsSection", disabled, label);
 }
 
@@ -630,15 +629,15 @@
   }
   FundamentalValue disabledValue(disabled);
   FundamentalValue checkRevocationValue(checkRevocationSetting);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetCheckRevocationCheckboxState",
       checkRevocationValue, disabledValue);
   FundamentalValue useSSL3Value(useSSL3Setting);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetUseSSL3CheckboxState",
       useSSL3Value, disabledValue);
   FundamentalValue useTLS1Value(useTLS1Setting);
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.AdvancedOptions.SetUseTLS1CheckboxState",
       useTLS1Value, disabledValue);
 }
diff --git a/chrome/browser/dom_ui/options/advanced_options_handler.h b/chrome/browser/dom_ui/options/advanced_options_handler.h
index 59ad1db..d5fdda5 100644
--- a/chrome/browser/dom_ui/options/advanced_options_handler.h
+++ b/chrome/browser/dom_ui/options/advanced_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,8 @@
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/prefs/pref_set_observer.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/remoting/remoting_options_handler.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 
 class OptionsManagedBannerHandler;
 
@@ -27,8 +28,8 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void Initialize();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // NotificationObserver implementation.
@@ -55,11 +56,6 @@
   // if the user toggles the metrics reporting checkbox.
   void HandleMetricsReportingCheckbox(const ListValue* args);
 
-  // Callback for the "defaultZoomLevelAction" message.  This is called if the
-  // user changes the default zoom level.  |args| is an array that contains
-  // one item, the zoom level as a numeric value.
-  void HandleDefaultZoomLevel(const ListValue* args);
-
   // Callback for the "defaultFontSizeAction" message.  This is called if the
   // user changes the default font size.  |args| is an array that contains
   // one item, the font size as a numeric value.
@@ -120,12 +116,15 @@
 
 #endif
 
-#if defined(ENABLE_REMOTING)
+#if defined(ENABLE_REMOTING) && !defined(OS_CHROMEOS)
   // Removes remoting section. Called if remoting is not enabled.
   void RemoveRemotingSection();
 
   // Callback for Setup Remoting button.
   void ShowRemotingSetupDialog(const ListValue* args);
+
+  // Disable Remoting.
+  void DisableRemoting(const ListValue* args);
 #endif
 
   // Setup the checked state for the metrics reporting checkbox.
@@ -134,7 +133,6 @@
   // Setup the visibility for the metrics reporting setting.
   void SetupMetricsReportingSettingVisibility();
 
-  void SetupDefaultZoomLevel();
   void SetupFontSizeLabel();
 
   // Setup the download path based on user preferences.
@@ -156,12 +154,16 @@
 #if !defined(OS_CHROMEOS)
   BooleanPrefMember enable_metrics_recording_;
   StringPrefMember cloud_print_proxy_email_;
+  BooleanPrefMember cloud_print_proxy_enabled_;
   bool cloud_print_proxy_ui_enabled_;
 #endif
 
+#if defined(ENABLE_REMOTING) && !defined(OS_CHROMEOS)
+  remoting::RemotingOptionsHandler remoting_options_handler_;
+#endif
+
   FilePathPrefMember default_download_location_;
   StringPrefMember auto_open_files_;
-  RealPrefMember default_zoom_level_;
   IntegerPrefMember default_font_size_;
   IntegerPrefMember default_fixed_font_size_;
   scoped_ptr<PrefSetObserver> proxy_prefs_;
diff --git a/chrome/browser/dom_ui/options/advanced_options_utils_gtk.cc b/chrome/browser/dom_ui/options/advanced_options_utils_gtk.cc
index 3c1a871..7b89b50 100644
--- a/chrome/browser/dom_ui/options/advanced_options_utils_gtk.cc
+++ b/chrome/browser/dom_ui/options/advanced_options_utils_gtk.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/browser/dom_ui/options/advanced_options_utils.h"
 
-#include "app/gtk_signal.h"
 #include "base/file_util.h"
 #include "base/environment.h"
 #include "base/process_util.h"
@@ -16,6 +15,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/process_watcher.h"
+#include "ui/base/gtk/gtk_signal.h"
 
 // Command used to configure GNOME proxy settings. The command was renamed
 // in January 2009, so both are used to work on both old and new systems.
diff --git a/chrome/browser/dom_ui/options/autofill_options_handler.cc b/chrome/browser/dom_ui/options/autofill_options_handler.cc
index 9e95ece..4ab22e4 100644
--- a/chrome/browser/dom_ui/options/autofill_options_handler.cc
+++ b/chrome/browser/dom_ui/options/autofill_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/string16.h"
 #include "base/string_number_conversions.h"
@@ -14,11 +13,12 @@
 #include "base/values.h"
 #include "chrome/browser/autofill/autofill_profile.h"
 #include "chrome/browser/autofill/credit_card.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/guid.h"
 #include "grit/generated_resources.h"
 #include "grit/webkit_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -63,8 +63,8 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("autoFillOptionsTitle",
-      l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_TITLE));
+  RegisterTitle(localized_strings, "autoFillOptionsPage",
+                IDS_AUTOFILL_OPTIONS_TITLE);
   localized_strings->SetString("autoFillAddresses",
       l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESSES_GROUP_NAME));
   localized_strings->SetString("autoFillCreditCards",
@@ -84,34 +84,39 @@
   localized_strings->SetString("editCreditCardTitle",
       l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION));
 
+#if defined(OS_MACOSX)
+  localized_strings->SetString("auxiliaryProfilesEnabled",
+      l10n_util::GetStringUTF16(IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK));
+#endif  // defined(OS_MACOSX)
+
   SetAddressOverlayStrings(localized_strings);
   SetCreditCardOverlayStrings(localized_strings);
 }
 
 void AutoFillOptionsHandler::Initialize() {
-  personal_data_ = dom_ui_->GetProfile()->GetPersonalDataManager();
+  personal_data_ = web_ui_->GetProfile()->GetPersonalDataManager();
   personal_data_->SetObserver(this);
 
   LoadAutoFillData();
 }
 
 void AutoFillOptionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "removeAddress",
       NewCallback(this, &AutoFillOptionsHandler::RemoveAddress));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "removeCreditCard",
       NewCallback(this, &AutoFillOptionsHandler::RemoveCreditCard));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "loadAddressEditor",
       NewCallback(this, &AutoFillOptionsHandler::LoadAddressEditor));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "loadCreditCardEditor",
       NewCallback(this, &AutoFillOptionsHandler::LoadCreditCardEditor));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "setAddress",
       NewCallback(this, &AutoFillOptionsHandler::SetAddress));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "setCreditCard",
       NewCallback(this, &AutoFillOptionsHandler::SetCreditCard));
 }
@@ -182,7 +187,7 @@
     addresses.Append(entry);
   }
 
-  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.setAddressList",
+  web_ui_->CallJavascriptFunction(L"AutoFillOptions.setAddressList",
                                   addresses);
 
   ListValue credit_cards;
@@ -194,11 +199,11 @@
     entry->Append(new StringValue((*i)->PreviewSummary()));
     int res = CreditCardTypeToResourceID((*i)->type());
     entry->Append(
-        new StringValue(dom_ui_util::GetImageDataUrlFromResource(res)));
+        new StringValue(web_ui_util::GetImageDataUrlFromResource(res)));
     credit_cards.Append(entry);
   }
 
-  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.setCreditCardList",
+  web_ui_->CallJavascriptFunction(L"AutoFillOptions.setCreditCardList",
                                   credit_cards);
 }
 
@@ -236,41 +241,43 @@
   }
 
   AutoFillProfile* profile = personal_data_->GetProfileByGUID(guid);
-  DCHECK(profile);
+  if (!profile) {
+    // There is a race where a user can click once on the close button and
+    // quickly click again on the list item before the item is removed (since
+    // the list is not updated until the model tells the list an item has been
+    // removed). This will activate the editor for a profile that has been
+    // removed. Do nothing in that case.
+    return;
+  }
 
-  // TODO(jhawkins): This is hacky because we can't send DictionaryValue
-  // directly to CallJavascriptFunction().
-  ListValue addressList;
-  DictionaryValue* address = new DictionaryValue();
-  address->SetString("guid", profile->guid());
-  address->SetString("fullName",
-                     profile->GetFieldText(AutoFillType(NAME_FULL)));
-  address->SetString("companyName",
-                     profile->GetFieldText(AutoFillType(COMPANY_NAME)));
-  address->SetString("addrLine1",
-                     profile->GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)));
-  address->SetString("addrLine2",
-                     profile->GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)));
-  address->SetString("city",
-                     profile->GetFieldText(AutoFillType(ADDRESS_HOME_CITY)));
-  address->SetString("state",
-                     profile->GetFieldText(AutoFillType(ADDRESS_HOME_STATE)));
-  address->SetString("zipCode",
-                     profile->GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)));
-  address->SetString("country",
+  DictionaryValue address;
+  address.SetString("guid", profile->guid());
+  address.SetString("fullName",
+                    profile->GetFieldText(AutoFillType(NAME_FULL)));
+  address.SetString("companyName",
+                    profile->GetFieldText(AutoFillType(COMPANY_NAME)));
+  address.SetString("addrLine1",
+                    profile->GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)));
+  address.SetString("addrLine2",
+                    profile->GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)));
+  address.SetString("city",
+                    profile->GetFieldText(AutoFillType(ADDRESS_HOME_CITY)));
+  address.SetString("state",
+                    profile->GetFieldText(AutoFillType(ADDRESS_HOME_STATE)));
+  address.SetString("zipCode",
+                    profile->GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)));
+  address.SetString("country",
                      profile->GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY)));
-  address->SetString(
+  address.SetString(
       "phone",
       profile->GetFieldText(AutoFillType(PHONE_HOME_WHOLE_NUMBER)));
-  address->SetString(
+  address.SetString(
       "fax",
       profile->GetFieldText(AutoFillType(PHONE_FAX_WHOLE_NUMBER)));
-  address->SetString("email",
+  address.SetString("email",
                      profile->GetFieldText(AutoFillType(EMAIL_ADDRESS)));
-  addressList.Append(address);
 
-  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.editAddress",
-                                  addressList);
+  web_ui_->CallJavascriptFunction(L"AutoFillOptions.editAddress", address);
 }
 
 void AutoFillOptionsHandler::LoadCreditCardEditor(const ListValue* args) {
@@ -283,29 +290,34 @@
   }
 
   CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
-  DCHECK(credit_card);
+  if (!credit_card) {
+    // There is a race where a user can click once on the close button and
+    // quickly click again on the list item before the item is removed (since
+    // the list is not updated until the model tells the list an item has been
+    // removed). This will activate the editor for a profile that has been
+    // removed. Do nothing in that case.
+    return;
+  }
 
-  // TODO(jhawkins): This is hacky because we can't send DictionaryValue
-  // directly to CallJavascriptFunction().
-  ListValue credit_card_list;
-  DictionaryValue* credit_card_data = new DictionaryValue();
-  credit_card_data->SetString("guid", credit_card->guid());
-  credit_card_data->SetString(
+  DictionaryValue credit_card_data;
+  credit_card_data.SetString("guid", credit_card->guid());
+  credit_card_data.SetString(
       "nameOnCard",
       credit_card->GetFieldText(AutoFillType(CREDIT_CARD_NAME)));
-  credit_card_data->SetString(
+  credit_card_data.SetString(
       "creditCardNumber",
       credit_card->GetFieldText(AutoFillType(CREDIT_CARD_NUMBER)));
-  credit_card_data->SetString(
+  credit_card_data.SetString("obfuscatedCardNumber",
+                             credit_card->ObfuscatedNumber());
+  credit_card_data.SetString(
       "expirationMonth",
       credit_card->GetFieldText(AutoFillType(CREDIT_CARD_EXP_MONTH)));
-  credit_card_data->SetString(
+  credit_card_data.SetString(
       "expirationYear",
       credit_card->GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)));
-  credit_card_list.Append(credit_card_data);
 
-  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.editCreditCard",
-                                  credit_card_list);
+  web_ui_->CallJavascriptFunction(L"AutoFillOptions.editCreditCard",
+                                  credit_card_data);
 }
 
 void AutoFillOptionsHandler::SetAddress(const ListValue* args) {
diff --git a/chrome/browser/dom_ui/options/autofill_options_handler.h b/chrome/browser/dom_ui/options/autofill_options_handler.h
index 1eaed4f..52de3e2 100644
--- a/chrome/browser/dom_ui/options/autofill_options_handler.h
+++ b/chrome/browser/dom_ui/options/autofill_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -44,26 +44,26 @@
   // |args| - A string, the GUID of the credit card to remove.
   void RemoveCreditCard(const ListValue* args);
 
-  // Requests profile data for a specific address. Calls into DOMUI with the
+  // Requests profile data for a specific address. Calls into WebUI with the
   // loaded profile data to open the address editor.
   // |args| - A string, the GUID of the address to load.
   void LoadAddressEditor(const ListValue* args);
 
-  // Requests profile data for a specific credit card. Calls into DOMUI with the
+  // Requests profile data for a specific credit card. Calls into WebUI with the
   // loaded profile data to open the credit card editor.
   // |args| - A string, the GUID of the credit card to load.
   void LoadCreditCardEditor(const ListValue* args);
 
   // Adds or updates an address, depending on the GUID of the profile. If the
   // GUID is empty, a new address is added to the WebDatabase; otherwise, the
-  // address with the matching GUID is updated. Called from DOMUI.
+  // address with the matching GUID is updated. Called from WebUI.
   // |args| - an array containing the GUID of the address followed by the
   // address data.
   void SetAddress(const ListValue* args);
 
   // Adds or updates a credit card, depending on the GUID of the profile. If the
   // GUID is empty, a new credit card is added to the WebDatabase; otherwise,
-  // the credit card with the matching GUID is updated. Called from DOMUI.
+  // the credit card with the matching GUID is updated. Called from WebUI.
   // |args| - an array containing the GUID of the credit card followed by the
   // credit card data.
   void SetCreditCard(const ListValue* args);
diff --git a/chrome/browser/dom_ui/options/browser_options_handler.cc b/chrome/browser/dom_ui/options/browser_options_handler.cc
index 6d9a962..4a3aaaf 100644
--- a/chrome/browser/dom_ui/options/browser_options_handler.cc
+++ b/chrome/browser/dom_ui/options/browser_options_handler.cc
@@ -1,21 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/browser_options_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/custom_home_pages_table_model.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
 #include "chrome/browser/dom_ui/options/dom_options_util.h"
 #include "chrome/browser/dom_ui/options/options_managed_banner_handler.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/instant/instant_confirm_dialog.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/net/url_fixer_upper.h"
@@ -24,9 +24,11 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/ui/options/options_window.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 BrowserOptionsHandler::BrowserOptionsHandler()
     : template_url_model_(NULL), startup_custom_pages_table_model_(NULL) {
@@ -45,49 +47,35 @@
 void BrowserOptionsHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  localized_strings->SetString("startupGroupName",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_GROUP_NAME)));
-  localized_strings->SetString("startupShowDefaultAndNewTab",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB));
-  localized_strings->SetString("startupShowLastSession",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION));
-  localized_strings->SetString("startupShowPages",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_PAGES));
-  localized_strings->SetString("startupShowManyPages",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_MANY_PAGES));
-  localized_strings->SetString("startupUseCurrent",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_USE_CURRENT));
-  localized_strings->SetString("homepageGroupName",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_GROUP_NAME)));
-  localized_strings->SetString("homepageUseNewTab",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_USE_NEWTAB));
-  localized_strings->SetString("homepageUseURL",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_HOMEPAGE_USE_URL));
-  localized_strings->SetString("toolbarGroupName",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_TOOLBAR_GROUP_NAME)));
-  localized_strings->SetString("toolbarShowHomeButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_TOOLBAR_SHOW_HOME_BUTTON));
-  localized_strings->SetString("defaultSearchGroupName",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME)));
-  localized_strings->SetString("defaultSearchManageEngines",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES));
-  localized_strings->SetString("instantName",
-      l10n_util::GetStringUTF16(IDS_INSTANT_PREF));
-  localized_strings->SetString("instantWarningText",
-      l10n_util::GetStringUTF16(IDS_INSTANT_PREF_WARNING));
+
+  static OptionsStringResource resources[] = {
+    { "startupGroupName", IDS_OPTIONS_STARTUP_GROUP_NAME, true },
+    { "startupShowDefaultAndNewTab",
+      IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB},
+    { "startupShowLastSession", IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION },
+    { "startupShowPages", IDS_OPTIONS_STARTUP_SHOW_PAGES },
+    { "startupAddButton", IDS_OPTIONS_STARTUP_ADD_BUTTON },
+    { "startupUseCurrent", IDS_OPTIONS_STARTUP_USE_CURRENT },
+    { "homepageGroupName", IDS_OPTIONS_HOMEPAGE_GROUP_NAME },
+    { "homepageUseNewTab", IDS_OPTIONS_HOMEPAGE_USE_NEWTAB },
+    { "homepageUseURL", IDS_OPTIONS_HOMEPAGE_USE_URL },
+    { "toolbarGroupName", IDS_OPTIONS_TOOLBAR_GROUP_NAME, true },
+    { "toolbarShowHomeButton", IDS_OPTIONS_TOOLBAR_SHOW_HOME_BUTTON },
+    { "defaultSearchGroupName", IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME, true },
+    { "defaultSearchManageEngines", IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES },
+    { "instantName", IDS_INSTANT_PREF },
+    { "instantWarningText", IDS_INSTANT_PREF_WARNING },
+    { "instantConfirmTitle", IDS_INSTANT_OPT_IN_TITLE },
+    { "instantConfirmMessage", IDS_INSTANT_OPT_IN_MESSAGE },
+    { "defaultBrowserGroupName", IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME, true },
+  };
+
+  RegisterStrings(localized_strings, resources, arraysize(resources));
+  RegisterTitle(localized_strings, "browserPage",
+                IDS_OPTIONS_GENERAL_TAB_LABEL);
+
   localized_strings->SetString("instantLearnMoreLink",
       ASCIIToUTF16(browser::InstantLearnMoreURL().spec()));
-  localized_strings->SetString("instantConfirmTitle",
-      l10n_util::GetStringUTF16(IDS_INSTANT_OPT_IN_TITLE));
-  localized_strings->SetString("instantConfirmMessage",
-      l10n_util::GetStringUTF16(IDS_INSTANT_OPT_IN_MESSAGE));
-  localized_strings->SetString("defaultBrowserGroupName",
-      dom_options_util::StripColon(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME)));
   localized_strings->SetString("defaultBrowserUnknown",
       l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
@@ -97,41 +85,67 @@
 }
 
 void BrowserOptionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
+      "setHomePage",
+      NewCallback(this, &BrowserOptionsHandler::SetHomePage));
+  web_ui_->RegisterMessageCallback(
       "becomeDefaultBrowser",
       NewCallback(this, &BrowserOptionsHandler::BecomeDefaultBrowser));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "setDefaultSearchEngine",
       NewCallback(this, &BrowserOptionsHandler::SetDefaultSearchEngine));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "removeStartupPages",
       NewCallback(this, &BrowserOptionsHandler::RemoveStartupPages));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "addStartupPage",
       NewCallback(this, &BrowserOptionsHandler::AddStartupPage));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
+      "editStartupPage",
+      NewCallback(this, &BrowserOptionsHandler::EditStartupPage));
+  web_ui_->RegisterMessageCallback(
       "setStartupPagesToCurrentPages",
       NewCallback(this, &BrowserOptionsHandler::SetStartupPagesToCurrentPages));
 }
 
 void BrowserOptionsHandler::Initialize() {
-  // Create our favicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIFavIconSource(dom_ui_->GetProfile()))));
+  Profile* profile = web_ui_->GetProfile();
 
+  // Create our favicon data source.
+  profile->GetChromeURLDataManager()->AddDataSource(
+      new WebUIFavIconSource(profile));
+
+  homepage_.Init(prefs::kHomePage, profile->GetPrefs(), NULL);
+  default_browser_policy_.Init(prefs::kDefaultBrowserSettingEnabled,
+                               g_browser_process->local_state(),
+                               this);
   UpdateDefaultBrowserState();
   UpdateStartupPages();
   UpdateSearchEngines();
   banner_handler_.reset(
-      new OptionsManagedBannerHandler(dom_ui_,
+      new OptionsManagedBannerHandler(web_ui_,
                                       ASCIIToUTF16("BrowserOptions"),
                                       OPTIONS_PAGE_GENERAL));
 }
 
+void BrowserOptionsHandler::SetHomePage(const ListValue* args) {
+  std::string url_string;
+  std::string do_fixup_string;
+  int do_fixup;
+  if (args->GetSize() != 2 ||
+      !args->GetString(0, &url_string) ||
+      !args->GetString(1, &do_fixup_string) ||
+      !base::StringToInt(do_fixup_string, &do_fixup)) {
+    CHECK(false);
+  };
+
+  if (do_fixup) {
+    GURL fixed_url = URLFixerUpper::FixupURL(url_string, std::string());
+    url_string = fixed_url.spec();
+  }
+  homepage_.SetValueIfNotManaged(url_string);
+}
+
 void BrowserOptionsHandler::UpdateDefaultBrowserState() {
 #if defined(OS_WIN)
   // Check for side-by-side first.
@@ -159,6 +173,11 @@
 }
 
 void BrowserOptionsHandler::BecomeDefaultBrowser(const ListValue* args) {
+  // If the default browser setting is managed then we should not be able to
+  // call this function.
+  if (default_browser_policy_.IsManaged())
+    return;
+
   UserMetricsRecordAction(UserMetricsAction("Options_SetAsDefaultBrowser"));
 #if defined(OS_MACOSX)
   if (ShellIntegration::SetAsDefaultBrowser())
@@ -202,10 +221,11 @@
       status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT));
 
   scoped_ptr<Value> can_be_default(Value::CreateBooleanValue(
-      status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT ||
-      status_string_id == IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT));
+      !default_browser_policy_.IsManaged() &&
+      (status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT ||
+       status_string_id == IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT)));
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"BrowserOptions.updateDefaultBrowserState",
       *(status_string.get()), *(is_default.get()), *(can_be_default.get()));
 }
@@ -226,7 +246,7 @@
       continue;
 
     DictionaryValue* entry = new DictionaryValue();
-    entry->SetString("name", WideToUTF16Hack(model_urls[i]->short_name()));
+    entry->SetString("name", model_urls[i]->short_name());
     entry->SetInteger("index", i);
     search_engines.Append(entry);
     if (model_urls[i] == default_url)
@@ -235,7 +255,7 @@
 
   scoped_ptr<Value> default_value(Value::CreateIntegerValue(default_index));
 
-  dom_ui_->CallJavascriptFunction(L"BrowserOptions.updateSearchEngines",
+  web_ui_->CallJavascriptFunction(L"BrowserOptions.updateSearchEngines",
                                   search_engines, *(default_value.get()));
 }
 
@@ -256,7 +276,7 @@
 }
 
 void BrowserOptionsHandler::UpdateSearchEngines() {
-  template_url_model_ = dom_ui_->GetProfile()->GetTemplateURLModel();
+  template_url_model_ = web_ui_->GetProfile()->GetTemplateURLModel();
   if (template_url_model_) {
     template_url_model_->Load();
     template_url_model_->AddObserver(this);
@@ -265,7 +285,7 @@
 }
 
 void BrowserOptionsHandler::UpdateStartupPages() {
-  Profile* profile = dom_ui_->GetProfile();
+  Profile* profile = web_ui_->GetProfile();
   startup_custom_pages_table_model_.reset(
       new CustomHomePagesTableModel(profile));
   startup_custom_pages_table_model_->SetObserver(this);
@@ -285,10 +305,11 @@
     entry->SetString("url", urls[i].spec());
     entry->SetString("tooltip",
                      startup_custom_pages_table_model_->GetTooltip(i));
+    entry->SetString("modelIndex", base::IntToString(i));
     startup_pages.Append(entry);
   }
 
-  dom_ui_->CallJavascriptFunction(L"BrowserOptions.updateStartupPages",
+  web_ui_->CallJavascriptFunction(L"BrowserOptions.updateStartupPages",
                                   startup_pages);
 }
 
@@ -304,6 +325,12 @@
   OnModelChanged();
 }
 
+void BrowserOptionsHandler::Observe(NotificationType type,
+                     const NotificationSource& source,
+                     const NotificationDetails& details) {
+  UpdateDefaultBrowserState();
+}
+
 void BrowserOptionsHandler::SetStartupPagesToCurrentPages(
     const ListValue* args) {
   startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
@@ -314,8 +341,7 @@
   for (int i = args->GetSize() - 1; i >= 0; --i) {
     std::string string_value;
     if (!args->GetString(i, &string_value)) {
-      NOTREACHED();
-      return;
+      CHECK(false);
     }
     int selected_index;
     base::StringToInt(string_value, &selected_index);
@@ -338,8 +364,7 @@
       !args->GetString(0, &url_string) ||
       !args->GetString(1, &index_string) ||
       !base::StringToInt(index_string, &index)) {
-    NOTREACHED();
-    return;
+    CHECK(false);
   };
 
   if (index == -1)
@@ -353,8 +378,29 @@
   SaveStartupPagesPref();
 }
 
+void BrowserOptionsHandler::EditStartupPage(const ListValue* args) {
+  std::string url_string;
+  std::string index_string;
+  int index;
+  if (args->GetSize() != 2 ||
+      !args->GetString(0, &index_string) ||
+      !base::StringToInt(index_string, &index) ||
+      !args->GetString(1, &url_string)) {
+    CHECK(false);
+  };
+
+  if (index < 0 || index > startup_custom_pages_table_model_->RowCount()) {
+    NOTREACHED();
+    return;
+  }
+
+  std::vector<GURL> urls = startup_custom_pages_table_model_->GetURLs();
+  urls[index] = URLFixerUpper::FixupURL(url_string, std::string());
+  startup_custom_pages_table_model_->SetURLs(urls);
+}
+
 void BrowserOptionsHandler::SaveStartupPagesPref() {
-  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
 
   SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
   pref.urls = startup_custom_pages_table_model_->GetURLs();
diff --git a/chrome/browser/dom_ui/options/browser_options_handler.h b/chrome/browser/dom_ui/options/browser_options_handler.h
index fd70ccf..be174dd 100644
--- a/chrome/browser/dom_ui/options/browser_options_handler.h
+++ b/chrome/browser/dom_ui/options/browser_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,20 +6,22 @@
 #define CHROME_BROWSER_DOM_UI_OPTIONS_BROWSER_OPTIONS_HANDLER_H_
 #pragma once
 
-#include "app/table_model_observer.h"
 #include "chrome/browser/dom_ui/options/options_ui.h"
+#include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/search_engines/template_url_model_observer.h"
 #include "chrome/browser/shell_integration.h"
+#include "ui/base/models/table_model_observer.h"
 
 class CustomHomePagesTableModel;
 class OptionsManagedBannerHandler;
+class StringPrefMember;
 class TemplateURLModel;
 
 // Chrome browser options page UI handler.
 class BrowserOptionsHandler : public OptionsPageUIHandler,
                               public ShellIntegration::DefaultBrowserObserver,
                               public TemplateURLModelObserver,
-                              public TableModelObserver {
+                              public ui::TableModelObserver {
  public:
   BrowserOptionsHandler();
   virtual ~BrowserOptionsHandler();
@@ -37,43 +39,55 @@
   // TemplateURLModelObserver implementation.
   virtual void OnTemplateURLModelChanged();
 
-  // TableModelObserver implementation.
+  // ui::TableModelObserver implementation.
   virtual void OnModelChanged();
   virtual void OnItemsChanged(int start, int length);
   virtual void OnItemsAdded(int start, int length);
   virtual void OnItemsRemoved(int start, int length);
 
  private:
-  // Makes this the default browser. Called from DOMUI.
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Sets the home page to the given string. Called from WebUI.
+  void SetHomePage(const ListValue* args);
+
+  // Makes this the default browser. Called from WebUI.
   void BecomeDefaultBrowser(const ListValue* args);
 
-  // Sets the search engine at the given index to be default. Called from DOMUI.
+  // Sets the search engine at the given index to be default. Called from WebUI.
   void SetDefaultSearchEngine(const ListValue* args);
 
-  // Removes the startup page at the given indexes. Called from DOMUI.
+  // Removes the startup page at the given indexes. Called from WebUI.
   void RemoveStartupPages(const ListValue* args);
 
   // Adds a startup page with the given URL after the given index.
-  // Called from DOMUI.
+  // Called from WebUI.
   void AddStartupPage(const ListValue* args);
 
-  // Sets the startup page set to the current pages. Called from DOMUI.
+  // Changes the startup page at the given index to the given URL.
+  // Called from WebUI.
+  void EditStartupPage(const ListValue* args);
+
+  // Sets the startup page set to the current pages. Called from WebUI.
   void SetStartupPagesToCurrentPages(const ListValue* args);
 
   // Returns the string ID for the given default browser state.
   int StatusStringIdForState(ShellIntegration::DefaultBrowserState state);
 
   // Gets the current default browser state, and asynchronously reports it to
-  // the DOMUI page.
+  // the WebUI page.
   void UpdateDefaultBrowserState();
 
   // Updates the UI with the given state for the default browser.
   void SetDefaultBrowserUIString(int status_string_id);
 
-  // Loads the current set of custom startup pages and reports it to the DOMUI.
+  // Loads the current set of custom startup pages and reports it to the WebUI.
   void UpdateStartupPages();
 
-  // Loads the possible default search engine list and reports it to the DOMUI.
+  // Loads the possible default search engine list and reports it to the WebUI.
   void UpdateSearchEngines();
 
   // Writes the current set of startup pages to prefs.
@@ -81,6 +95,9 @@
 
   scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
 
+  StringPrefMember homepage_;
+  BooleanPrefMember default_browser_policy_;
+
   TemplateURLModel* template_url_model_;  // Weak.
 
   // TODO(stuartmorgan): Once there are no other clients of
diff --git a/chrome/browser/dom_ui/options/certificate_manager_handler.cc b/chrome/browser/dom_ui/options/certificate_manager_handler.cc
index 480fcb4..a0cd4ba 100644
--- a/chrome/browser/dom_ui/options/certificate_manager_handler.cc
+++ b/chrome/browser/dom_ui/options/certificate_manager_handler.cc
@@ -1,24 +1,27 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/certificate_manager_handler.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_collator.h"
 #include "base/file_util.h"  // for FileAccessProvider
 #include "base/safe_strerror_posix.h"
+#include "base/scoped_vector.h"
 #include "base/string_number_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"  // for FileAccessProvider
 #include "chrome/browser/certificate_manager_model.h"
 #include "chrome/browser/certificate_viewer.h"
-#include "chrome/browser/gtk/certificate_dialogs.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/ui/crypto_module_password_dialog.h"
+#include "chrome/browser/ui/gtk/certificate_dialogs.h"
 #include "grit/generated_resources.h"
+#include "net/base/crypto_module.h"
 #include "net/base/x509_certificate.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
 
 namespace {
 
@@ -244,8 +247,8 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("certificateManagerPage",
-      l10n_util::GetStringUTF16(IDS_CERTIFICATE_MANAGER_TITLE));
+  RegisterTitle(localized_strings, "certificateManagerPage",
+                IDS_CERTIFICATE_MANAGER_TITLE);
 
   // Tabs.
   localized_strings->SetString("personalCertsTabTitle",
@@ -342,49 +345,49 @@
 }
 
 void CertificateManagerHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("viewCertificate",
+  web_ui_->RegisterMessageCallback("viewCertificate",
       NewCallback(this, &CertificateManagerHandler::View));
 
-  dom_ui_->RegisterMessageCallback("getCaCertificateTrust",
+  web_ui_->RegisterMessageCallback("getCaCertificateTrust",
       NewCallback(this, &CertificateManagerHandler::GetCATrust));
-  dom_ui_->RegisterMessageCallback("editCaCertificateTrust",
+  web_ui_->RegisterMessageCallback("editCaCertificateTrust",
       NewCallback(this, &CertificateManagerHandler::EditCATrust));
 
-  dom_ui_->RegisterMessageCallback("editServerCertificate",
+  web_ui_->RegisterMessageCallback("editServerCertificate",
       NewCallback(this, &CertificateManagerHandler::EditServer));
 
-  dom_ui_->RegisterMessageCallback("cancelImportExportCertificate",
+  web_ui_->RegisterMessageCallback("cancelImportExportCertificate",
       NewCallback(this, &CertificateManagerHandler::CancelImportExportProcess));
 
-  dom_ui_->RegisterMessageCallback("exportPersonalCertificate",
+  web_ui_->RegisterMessageCallback("exportPersonalCertificate",
       NewCallback(this, &CertificateManagerHandler::ExportPersonal));
-  dom_ui_->RegisterMessageCallback("exportAllPersonalCertificates",
+  web_ui_->RegisterMessageCallback("exportAllPersonalCertificates",
       NewCallback(this, &CertificateManagerHandler::ExportAllPersonal));
-  dom_ui_->RegisterMessageCallback("exportPersonalCertificatePasswordSelected",
+  web_ui_->RegisterMessageCallback("exportPersonalCertificatePasswordSelected",
       NewCallback(this,
                   &CertificateManagerHandler::ExportPersonalPasswordSelected));
 
-  dom_ui_->RegisterMessageCallback("importPersonalCertificate",
+  web_ui_->RegisterMessageCallback("importPersonalCertificate",
       NewCallback(this, &CertificateManagerHandler::StartImportPersonal));
-  dom_ui_->RegisterMessageCallback("importPersonalCertificatePasswordSelected",
+  web_ui_->RegisterMessageCallback("importPersonalCertificatePasswordSelected",
       NewCallback(this,
                   &CertificateManagerHandler::ImportPersonalPasswordSelected));
 
-  dom_ui_->RegisterMessageCallback("importCaCertificate",
+  web_ui_->RegisterMessageCallback("importCaCertificate",
       NewCallback(this, &CertificateManagerHandler::ImportCA));
-  dom_ui_->RegisterMessageCallback("importCaCertificateTrustSelected",
+  web_ui_->RegisterMessageCallback("importCaCertificateTrustSelected",
       NewCallback(this, &CertificateManagerHandler::ImportCATrustSelected));
 
-  dom_ui_->RegisterMessageCallback("importServerCertificate",
+  web_ui_->RegisterMessageCallback("importServerCertificate",
       NewCallback(this, &CertificateManagerHandler::ImportServer));
 
-  dom_ui_->RegisterMessageCallback("exportCertificate",
+  web_ui_->RegisterMessageCallback("exportCertificate",
       NewCallback(this, &CertificateManagerHandler::Export));
 
-  dom_ui_->RegisterMessageCallback("deleteCertificate",
+  web_ui_->RegisterMessageCallback("deleteCertificate",
       NewCallback(this, &CertificateManagerHandler::Delete));
 
-  dom_ui_->RegisterMessageCallback("populateCertificateManager",
+  web_ui_->RegisterMessageCallback("populateCertificateManager",
       NewCallback(this, &CertificateManagerHandler::Populate));
 }
 
@@ -439,7 +442,7 @@
 void CertificateManagerHandler::GetCATrust(const ListValue* args) {
   net::X509Certificate* cert = CallbackArgsToCert(args);
   if (!cert) {
-    dom_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
     return;
   }
 
@@ -449,7 +452,7 @@
   FundamentalValue email_value(bool(trust & net::CertDatabase::TRUSTED_EMAIL));
   FundamentalValue obj_sign_value(
       bool(trust & net::CertDatabase::TRUSTED_OBJ_SIGN));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"CertificateEditCaTrustOverlay.populateTrust",
       ssl_value, email_value, obj_sign_value);
 }
@@ -465,7 +468,7 @@
   fail |= !CallbackArgsToBool(args, 3, &trust_obj_sign);
   if (fail) {
     LOG(ERROR) << "EditCATrust args fail";
-    dom_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
     return;
   }
 
@@ -475,7 +478,7 @@
       trust_ssl * net::CertDatabase::TRUSTED_SSL +
           trust_email * net::CertDatabase::TRUSTED_EMAIL +
           trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN);
-  dom_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
+  web_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
   if (!result) {
     // TODO(mattm): better error messages?
     ShowError(
@@ -516,24 +519,39 @@
 void CertificateManagerHandler::ExportPersonalFileSelected(
     const FilePath& path) {
   file_path_ = path;
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"CertificateManager.exportPersonalAskPassword");
 }
 
 void CertificateManagerHandler::ExportPersonalPasswordSelected(
     const ListValue* args) {
   if (!args->GetString(0, &password_)){
-    dom_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
     ImportExportCleanup();
     return;
   }
+
+  // Currently, we don't support exporting more than one at a time.  If we do,
+  // this would need some cleanup to handle unlocking multiple slots.
+  DCHECK_EQ(selected_cert_list_.size(), 1U);
+
+  // TODO(mattm): do something smarter about non-extractable keys
+  browser::UnlockCertSlotIfNecessary(
+      selected_cert_list_[0].get(),
+      browser::kCryptoModulePasswordCertExport,
+      "",  // unused.
+      NewCallback(this,
+                  &CertificateManagerHandler::ExportPersonalSlotsUnlocked));
+}
+
+void CertificateManagerHandler::ExportPersonalSlotsUnlocked() {
   std::string output;
   int num_exported = certificate_manager_model_->cert_db().ExportToPKCS12(
       selected_cert_list_,
       password_,
       &output);
   if (!num_exported) {
-    dom_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
     ShowError(
         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
@@ -549,7 +567,7 @@
 
 void CertificateManagerHandler::ExportPersonalFileWritten(int write_errno,
                                                           int bytes_written) {
-  dom_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
+  web_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
   ImportExportCleanup();
   if (write_errno) {
     ShowError(
@@ -577,14 +595,14 @@
 void CertificateManagerHandler::ImportPersonalFileSelected(
     const FilePath& path) {
   file_path_ = path;
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"CertificateManager.importPersonalAskPassword");
 }
 
 void CertificateManagerHandler::ImportPersonalPasswordSelected(
     const ListValue* args) {
   if (!args->GetString(0, &password_)){
-    dom_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
     ImportExportCleanup();
     return;
   }
@@ -598,16 +616,32 @@
     int read_errno, std::string data) {
   if (read_errno) {
     ImportExportCleanup();
-    dom_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
     ShowError(
         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
                                   UTF8ToUTF16(safe_strerror(read_errno))));
     return;
   }
-  int result = certificate_manager_model_->ImportFromPKCS12(data, password_);
+
+  file_data_ = data;
+
+  // TODO(mattm): allow user to choose a slot to import to.
+  module_ = certificate_manager_model_->cert_db().GetDefaultModule();
+
+  browser::UnlockSlotIfNecessary(
+      module_.get(),
+      browser::kCryptoModulePasswordCertImport,
+      "",  // unused.
+      NewCallback(this,
+                  &CertificateManagerHandler::ImportPersonalSlotUnlocked));
+}
+
+void CertificateManagerHandler::ImportPersonalSlotUnlocked() {
+  int result = certificate_manager_model_->ImportFromPKCS12(
+      module_, file_data_, password_);
   ImportExportCleanup();
-  dom_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
+  web_ui_->CallJavascriptFunction(L"CertificateRestoreOverlay.dismiss");
   switch (result) {
     case net::OK:
       break;
@@ -634,8 +668,10 @@
 void CertificateManagerHandler::ImportExportCleanup() {
   file_path_.clear();
   password_.clear();
+  file_data_.clear();
   selected_cert_list_.clear();
   select_file_dialog_ = NULL;
+  module_ = NULL;
 }
 
 void CertificateManagerHandler::ImportServer(const ListValue* args) {
@@ -737,22 +773,22 @@
   // TODO(mattm): check here if root_cert is not a CA cert and show error.
 
   StringValue cert_name(root_cert->subject().GetDisplayName());
-  dom_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.showImport",
+  web_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.showImport",
                                   cert_name);
 }
 
 void CertificateManagerHandler::ImportCATrustSelected(const ListValue* args) {
   bool fail = false;
-  bool trust_ssl;
-  bool trust_email;
-  bool trust_obj_sign;
+  bool trust_ssl = false;
+  bool trust_email = false;
+  bool trust_obj_sign = false;
   fail |= !CallbackArgsToBool(args, 0, &trust_ssl);
   fail |= !CallbackArgsToBool(args, 1, &trust_email);
   fail |= !CallbackArgsToBool(args, 2, &trust_obj_sign);
   if (fail) {
     LOG(ERROR) << "ImportCATrustSelected args fail";
     ImportExportCleanup();
-    dom_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
+    web_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
     return;
   }
 
@@ -763,7 +799,7 @@
           trust_email * net::CertDatabase::TRUSTED_EMAIL +
           trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN,
       &not_imported);
-  dom_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
+  web_ui_->CallJavascriptFunction(L"CertificateEditCaTrustOverlay.dismiss");
   if (!result) {
     ShowError(
         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
@@ -852,20 +888,20 @@
     ListValue args;
     args.Append(Value::CreateStringValue(tree_name));
     args.Append(nodes);
-    dom_ui_->CallJavascriptFunction(L"CertificateManager.onPopulateTree", args);
+    web_ui_->CallJavascriptFunction(L"CertificateManager.onPopulateTree", args);
   }
 }
 
 void CertificateManagerHandler::ShowError(const std::string& title,
                                           const std::string& error) const {
-  std::vector<const Value*> args;
+  ScopedVector<const Value> args;
   args.push_back(Value::CreateStringValue(title));
   args.push_back(Value::CreateStringValue(error));
-  args.push_back(Value::CreateNullValue());  // okTitle
-  args.push_back(Value::CreateStringValue(""));  // cancelTitle
+  args.push_back(Value::CreateStringValue(l10n_util::GetStringUTF8(IDS_OK)));
+  args.push_back(Value::CreateNullValue());  // cancelTitle
   args.push_back(Value::CreateNullValue());  // okCallback
   args.push_back(Value::CreateNullValue());  // cancelCallback
-  dom_ui_->CallJavascriptFunction(L"AlertOverlay.show", args);
+  web_ui_->CallJavascriptFunction(L"AlertOverlay.show", args.get());
 }
 
 void CertificateManagerHandler::ShowImportErrors(
@@ -891,12 +927,12 @@
 
   StringValue title_value(title);
   StringValue error_value(error);
-  dom_ui_->CallJavascriptFunction(L"CertificateImportErrorOverlay.show",
+  web_ui_->CallJavascriptFunction(L"CertificateImportErrorOverlay.show",
                                   title_value,
                                   error_value,
                                   cert_error_list);
 }
 
 gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
-  return dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow();
+  return web_ui_->tab_contents()->view()->GetTopLevelNativeWindow();
 }
diff --git a/chrome/browser/dom_ui/options/certificate_manager_handler.h b/chrome/browser/dom_ui/options/certificate_manager_handler.h
index 3ac3898..24a6169 100644
--- a/chrome/browser/dom_ui/options/certificate_manager_handler.h
+++ b/chrome/browser/dom_ui/options/certificate_manager_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,15 @@
 #define CHROME_BROWSER_DOM_UI_OPTIONS_CERTIFICATE_MANAGER_HANDLER_H_
 #pragma once
 
+#include <string>
+
 #include "base/scoped_ptr.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/certificate_manager_model.h"
 #include "chrome/browser/dom_ui/options/options_ui.h"
-#include "chrome/browser/shell_dialogs.h"
-#include "gfx/native_widget_types.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "net/base/cert_database.h"
+#include "ui/gfx/native_widget_types.h"
 
 class FileAccessProvider;
 
@@ -59,13 +61,15 @@
   //  selector
   //  2. user selects file -> ExportPersonalFileSelected -> launches password
   //  dialog
-  //  3. user enters password -> ExportPersonalPasswordSelected -> exports to
-  //  memory buffer -> starts async write operation
-  //  4. write finishes (or fails) -> ExportPersonalFileWritten
+  //  3. user enters password -> ExportPersonalPasswordSelected -> unlock slots
+  //  4. slots unlocked -> ExportPersonalSlotsUnlocked -> exports to memory
+  //  buffer -> starts async write operation
+  //  5. write finishes (or fails) -> ExportPersonalFileWritten
   void ExportPersonal(const ListValue* args);
   void ExportAllPersonal(const ListValue* args);
   void ExportPersonalFileSelected(const FilePath& path);
   void ExportPersonalPasswordSelected(const ListValue* args);
+  void ExportPersonalSlotsUnlocked();
   void ExportPersonalFileWritten(int write_errno, int bytes_written);
 
   // Import from PKCS #12 file.  The sequence goes like:
@@ -75,15 +79,17 @@
   //  dialog
   //  3. user enters password -> ImportPersonalPasswordSelected -> starts async
   //  read operation
-  //  4. read operation completes -> ImportPersonalFileRead -> attempts to
+  //  4. read operation completes -> ImportPersonalFileRead -> unlock slot
+  //  5. slot unlocked -> ImportPersonalSlotUnlocked attempts to
   //  import with previously entered password
-  //  5a. if import succeeds -> ImportExportCleanup
-  //  5b. if import fails -> show error, ImportExportCleanup
+  //  6a. if import succeeds -> ImportExportCleanup
+  //  6b. if import fails -> show error, ImportExportCleanup
   //  TODO(mattm): allow retrying with different password
   void StartImportPersonal(const ListValue* args);
   void ImportPersonalFileSelected(const FilePath& path);
   void ImportPersonalPasswordSelected(const ListValue* args);
   void ImportPersonalFileRead(int read_errno, std::string data);
+  void ImportPersonalSlotUnlocked();
 
   // Import Server certificates from file.  Sequence goes like:
   //  1. user clicks on import button -> ImportServer -> launches file selector
@@ -120,10 +126,10 @@
   // Populate the given tab's tree.
   void PopulateTree(const std::string& tab_name, net::CertType type);
 
-  // Display a domui error message box.
+  // Display a WebUI error message box.
   void ShowError(const std::string& title, const std::string& error) const;
 
-  // Display a domui error message box for import failures.
+  // Display a WebUI error message box for import failures.
   // Depends on |selected_cert_list_| being set to the imports that we
   // attempted to import.
   void ShowImportErrors(
@@ -140,8 +146,10 @@
   // wait for file to be read, etc.
   FilePath file_path_;
   string16 password_;
+  std::string file_data_;
   net::CertificateList selected_cert_list_;
   scoped_refptr<SelectFileDialog> select_file_dialog_;
+  scoped_refptr<net::CryptoModule> module_;
 
   // Used in reading and writing certificate files.
   CancelableRequestConsumer consumer_;
diff --git a/chrome/browser/dom_ui/options/clear_browser_data_handler.cc b/chrome/browser/dom_ui/options/clear_browser_data_handler.cc
index 21f2121..08afd5d 100644
--- a/chrome/browser/dom_ui/options/clear_browser_data_handler.cc
+++ b/chrome/browser/dom_ui/options/clear_browser_data_handler.cc
@@ -1,19 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/clear_browser_data_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/string16.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/notification_details.h"
 #include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 ClearBrowserDataHandler::ClearBrowserDataHandler() : remover_(NULL) {
 }
@@ -24,15 +26,21 @@
   }
 }
 
+void ClearBrowserDataHandler::Initialize() {
+  clear_plugin_lso_data_enabled_.Init(prefs::kClearPluginLSODataEnabled,
+                                      g_browser_process->local_state(),
+                                      this);
+  UpdateClearPluginLSOData();
+}
+
 void ClearBrowserDataHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  localized_strings->SetString("clearBrowsingDataTitle",
-      l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_TITLE));
-  localized_strings->SetString("clearBrowsingDataLabel",
+  RegisterTitle(localized_strings, "clearBrowserDataOverlay",
+                IDS_CLEAR_BROWSING_DATA_TITLE);
+
+  localized_strings->SetString("clearBrowserDataLabel",
       l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_LABEL));
-  localized_strings->SetString("clearBrowsingDataTimeLabel",
-      l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_TIME_LABEL));
   localized_strings->SetString("deleteBrowsingHistoryCheckbox",
       l10n_util::GetStringUTF16(IDS_DEL_BROWSING_HISTORY_CHKBOX));
   localized_strings->SetString("deleteDownloadHistoryCheckbox",
@@ -45,7 +53,7 @@
       l10n_util::GetStringUTF16(IDS_DEL_PASSWORDS_CHKBOX));
   localized_strings->SetString("deleteFormDataCheckbox",
       l10n_util::GetStringUTF16(IDS_DEL_FORM_DATA_CHKBOX));
-  localized_strings->SetString("clearBrowsingDataCommit",
+  localized_strings->SetString("clearBrowserDataCommit",
       l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_COMMIT));
   localized_strings->SetString("flashStorageSettings",
       l10n_util::GetStringUTF16(IDS_FLASH_STORAGE_SETTINGS));
@@ -79,19 +87,37 @@
     option->Append(Value::CreateStringValue(label_string));
     time_list->Append(option);
   }
-  localized_strings->Set("clearBrowsingDataTimeList", time_list);
+  localized_strings->Set("clearBrowserDataTimeList", time_list);
 }
 
 void ClearBrowserDataHandler::RegisterMessages() {
   // Setup handlers specific to this panel.
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("performClearBrowserData",
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("performClearBrowserData",
       NewCallback(this, &ClearBrowserDataHandler::HandleClearBrowserData));
 }
 
+void ClearBrowserDataHandler::Observe(NotificationType type,
+                                      const NotificationSource& source,
+                                      const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::PREF_CHANGED: {
+      const std::string& pref_name = *Details<std::string>(details).ptr();
+      if (pref_name == prefs::kClearPluginLSODataEnabled)
+        UpdateClearPluginLSOData();
+      else
+        OptionsPageUIHandler::Observe(type, source, details);
+      break;
+    }
+
+    default:
+      OptionsPageUIHandler::Observe(type, source, details);
+  }
+}
+
 void ClearBrowserDataHandler::HandleClearBrowserData(const ListValue* value) {
-  Profile *profile = dom_ui_->GetProfile();
-  PrefService *prefs = profile->GetPrefs();
+  Profile* profile = web_ui_->GetProfile();
+  PrefService* prefs = profile->GetPrefs();
 
   int remove_mask = 0;
   if (prefs->GetBoolean(prefs::kDeleteBrowsingHistory))
@@ -100,8 +126,11 @@
     remove_mask |= BrowsingDataRemover::REMOVE_DOWNLOADS;
   if (prefs->GetBoolean(prefs::kDeleteCache))
     remove_mask |= BrowsingDataRemover::REMOVE_CACHE;
-  if (prefs->GetBoolean(prefs::kDeleteCookies))
+  if (prefs->GetBoolean(prefs::kDeleteCookies)) {
     remove_mask |= BrowsingDataRemover::REMOVE_COOKIES;
+    if (clear_plugin_lso_data_enabled_.GetValue())
+      remove_mask |= BrowsingDataRemover::REMOVE_LSO_DATA;
+  }
   if (prefs->GetBoolean(prefs::kDeletePasswords))
     remove_mask |= BrowsingDataRemover::REMOVE_PASSWORDS;
   if (prefs->GetBoolean(prefs::kDeleteFormData))
@@ -110,7 +139,7 @@
   int period_selected = prefs->GetInteger(prefs::kDeleteTimePeriod);
 
   FundamentalValue state(true);
-  dom_ui_->CallJavascriptFunction(L"ClearBrowserDataOverlay.setClearingState",
+  web_ui_->CallJavascriptFunction(L"ClearBrowserDataOverlay.setClearingState",
                                   state);
 
   // BrowsingDataRemover deletes itself when done.
@@ -121,11 +150,20 @@
   remover_->Remove(remove_mask);
 }
 
+void ClearBrowserDataHandler::UpdateClearPluginLSOData() {
+  int label_id = clear_plugin_lso_data_enabled_.GetValue() ?
+      IDS_DEL_COOKIES_FLASH_CHKBOX :
+      IDS_DEL_COOKIES_CHKBOX;
+  scoped_ptr<Value> label(
+      Value::CreateStringValue(l10n_util::GetStringUTF16(label_id)));
+  web_ui_->CallJavascriptFunction(
+      L"ClearBrowserDataOverlay.setClearLocalDataLabel", *label);
+}
+
 void ClearBrowserDataHandler::OnBrowsingDataRemoverDone() {
   // No need to remove ourselves as an observer as BrowsingDataRemover deletes
   // itself after we return.
   remover_ = NULL;
-  DCHECK(dom_ui_);
-  dom_ui_->CallJavascriptFunction(L"ClearBrowserDataOverlay.dismiss");
+  DCHECK(web_ui_);
+  web_ui_->CallJavascriptFunction(L"ClearBrowserDataOverlay.doneClearing");
 }
-
diff --git a/chrome/browser/dom_ui/options/clear_browser_data_handler.h b/chrome/browser/dom_ui/options/clear_browser_data_handler.h
index 7789bff..e475eb0 100644
--- a/chrome/browser/dom_ui/options/clear_browser_data_handler.h
+++ b/chrome/browser/dom_ui/options/clear_browser_data_handler.h
@@ -8,6 +8,7 @@
 
 #include "chrome/browser/dom_ui/options/options_ui.h"
 #include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/plugin_data_remover_helper.h"
 
 // Clear browser data handler page UI handler.
 class ClearBrowserDataHandler : public OptionsPageUIHandler,
@@ -17,14 +18,25 @@
   virtual ~ClearBrowserDataHandler();
 
   // OptionsUIHandler implementation.
+  virtual void Initialize();
+
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
  private:
+  // Javascript callback to start clearing data.
   void HandleClearBrowserData(const ListValue* value);
 
+  // Updates the UI to reflect whether clearing LSO data is supported.
+  void UpdateClearPluginLSOData();
+
   // Callback from BrowsingDataRemover. Closes the dialog.
   virtual void OnBrowsingDataRemoverDone();
 
@@ -32,6 +44,10 @@
   // of deleting itself when done.
   BrowsingDataRemover* remover_;
 
+  // Used for asynchronously updating the preference stating whether clearing
+  // LSO data is supported.
+  PluginDataRemoverHelper clear_plugin_lso_data_enabled_;
+
   DISALLOW_COPY_AND_ASSIGN(ClearBrowserDataHandler);
 };
 
diff --git a/chrome/browser/dom_ui/options/content_settings_handler.cc b/chrome/browser/dom_ui/options/content_settings_handler.cc
index d1bccf8..4a7a649 100644
--- a/chrome/browser/dom_ui/options/content_settings_handler.cc
+++ b/chrome/browser/dom_ui/options/content_settings_handler.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/content_settings_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/content_settings_details.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
@@ -24,6 +24,7 @@
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -176,134 +177,85 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("content_exceptions",
-      l10n_util::GetStringUTF16(IDS_COOKIES_EXCEPTIONS_BUTTON));
-  localized_strings->SetString("contentSettingsPage",
-      l10n_util::GetStringUTF16(IDS_CONTENT_SETTINGS_TITLE));
-  localized_strings->SetString("allowException",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ALLOW_BUTTON));
-  localized_strings->SetString("blockException",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_BLOCK_BUTTON));
-  localized_strings->SetString("sessionException",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_SESSION_ONLY_BUTTON));
-  localized_strings->SetString("askException",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ASK_BUTTON));
-  localized_strings->SetString("addExceptionRow",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ADD_BUTTON));
-  localized_strings->SetString("removeExceptionRow",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_REMOVE_BUTTON));
-  localized_strings->SetString("editExceptionRow",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_EDIT_BUTTON));
-  localized_strings->SetString("otr_exceptions_explanation",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_OTR_LABEL));
-  localized_strings->SetString("examplePattern",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_PATTERN_EXAMPLE));
-  localized_strings->SetString("addNewExceptionInstructions",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS));
-  localized_strings->SetString("manage_exceptions",
-      l10n_util::GetStringUTF16(IDS_EXCEPTIONS_MANAGE));
+  static OptionsStringResource resources[] = {
+    { "content_exceptions", IDS_COOKIES_EXCEPTIONS_BUTTON },
+    { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
+    { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
+    { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
+    { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
+    { "addExceptionRow", IDS_EXCEPTIONS_ADD_BUTTON },
+    { "removeExceptionRow", IDS_EXCEPTIONS_REMOVE_BUTTON },
+    { "editExceptionRow", IDS_EXCEPTIONS_EDIT_BUTTON },
+    { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
+    { "examplePattern", IDS_EXCEPTIONS_PATTERN_EXAMPLE },
+    { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
+    { "manage_exceptions", IDS_EXCEPTIONS_MANAGE },
+    // Cookies filter.
+    { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
+    { "cookies_header", IDS_COOKIES_HEADER },
+    { "cookies_allow", IDS_COOKIES_ALLOW_RADIO },
+    { "cookies_ask", IDS_COOKIES_ASK_EVERY_TIME_RADIO },
+    { "cookies_block", IDS_COOKIES_BLOCK_RADIO },
+    { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
+    { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
+    { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
+    { "flash_storage_url", IDS_FLASH_STORAGE_URL },
+    // Image filter.
+    { "images_tab_label", IDS_IMAGES_TAB_LABEL },
+    { "images_header", IDS_IMAGES_HEADER },
+    { "images_allow", IDS_IMAGES_LOAD_RADIO },
+    { "images_block", IDS_IMAGES_NOLOAD_RADIO },
+    // JavaScript filter.
+    { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL },
+    { "javascript_header", IDS_JAVASCRIPT_HEADER },
+    { "javascript_allow", IDS_JS_ALLOW_RADIO },
+    { "javascript_block", IDS_JS_DONOTALLOW_RADIO },
+    // Plug-ins filter.
+    { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL },
+    { "plugins_header", IDS_PLUGIN_HEADER },
+    { "plugins_ask", IDS_PLUGIN_ASK_RADIO },
+    { "plugins_allow", IDS_PLUGIN_LOAD_RADIO },
+    { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO },
+    { "disable_individual_plugins", IDS_PLUGIN_SELECTIVE_DISABLE },
+    // Pop-ups filter.
+    { "popups_tab_label", IDS_POPUP_TAB_LABEL },
+    { "popups_header", IDS_POPUP_HEADER },
+    { "popups_allow", IDS_POPUP_ALLOW_RADIO },
+    { "popups_block", IDS_POPUP_BLOCK_RADIO },
+    // Location filter.
+    { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL },
+    { "location_header", IDS_GEOLOCATION_HEADER },
+    { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO },
+    { "location_ask", IDS_GEOLOCATION_ASK_RADIO },
+    { "location_block", IDS_GEOLOCATION_BLOCK_RADIO },
+    // Notifications filter.
+    { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL },
+    { "notifications_header", IDS_NOTIFICATIONS_HEADER },
+    { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO },
+    { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO },
+    { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO },
+  };
 
-  // Cookies filter.
-  localized_strings->SetString("cookies_tab_label",
-      l10n_util::GetStringUTF16(IDS_COOKIES_TAB_LABEL));
-  localized_strings->SetString("cookies_header",
-      l10n_util::GetStringUTF16(IDS_COOKIES_HEADER));
-  localized_strings->SetString("cookies_allow",
-      l10n_util::GetStringUTF16(IDS_COOKIES_ALLOW_RADIO));
-  localized_strings->SetString("cookies_ask",
-      l10n_util::GetStringUTF16(IDS_COOKIES_ASK_EVERY_TIME_RADIO));
-  localized_strings->SetString("cookies_block",
-      l10n_util::GetStringUTF16(IDS_COOKIES_BLOCK_RADIO));
-  localized_strings->SetString("cookies_block_3rd_party",
-      l10n_util::GetStringUTF16(IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX));
-  localized_strings->SetString("cookies_clear_on_exit",
-      l10n_util::GetStringUTF16(IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX));
-  localized_strings->SetString("cookies_show_cookies",
-      l10n_util::GetStringUTF16(IDS_COOKIES_SHOW_COOKIES_BUTTON));
-  localized_strings->SetString("flash_storage_settings",
-      l10n_util::GetStringUTF16(IDS_FLASH_STORAGE_SETTINGS));
-  localized_strings->SetString("flash_storage_url",
-      l10n_util::GetStringUTF16(IDS_FLASH_STORAGE_URL));
-
-  // Image filter.
-  localized_strings->SetString("images_tab_label",
-      l10n_util::GetStringUTF16(IDS_IMAGES_TAB_LABEL));
-  localized_strings->SetString("images_header",
-      l10n_util::GetStringUTF16(IDS_IMAGES_HEADER));
-  localized_strings->SetString("images_allow",
-      l10n_util::GetStringUTF16(IDS_IMAGES_LOAD_RADIO));
-  localized_strings->SetString("images_block",
-      l10n_util::GetStringUTF16(IDS_IMAGES_NOLOAD_RADIO));
-
-  // JavaScript filter.
-  localized_strings->SetString("javascript_tab_label",
-      l10n_util::GetStringUTF16(IDS_JAVASCRIPT_TAB_LABEL));
-  localized_strings->SetString("javascript_header",
-      l10n_util::GetStringUTF16(IDS_JAVASCRIPT_HEADER));
-  localized_strings->SetString("javascript_allow",
-      l10n_util::GetStringUTF16(IDS_JS_ALLOW_RADIO));
-  localized_strings->SetString("javascript_block",
-      l10n_util::GetStringUTF16(IDS_JS_DONOTALLOW_RADIO));
-
-  // Plug-ins filter.
-  localized_strings->SetString("plugins_tab_label",
-      l10n_util::GetStringUTF16(IDS_PLUGIN_TAB_LABEL));
-  localized_strings->SetString("plugins_header",
-      l10n_util::GetStringUTF16(IDS_PLUGIN_HEADER));
-  localized_strings->SetString("plugins_ask",
-      l10n_util::GetStringUTF16(IDS_PLUGIN_ASK_RADIO));
-  localized_strings->SetString("plugins_allow",
-      l10n_util::GetStringUTF16(IDS_PLUGIN_LOAD_RADIO));
-  localized_strings->SetString("plugins_block",
-      l10n_util::GetStringUTF16(IDS_PLUGIN_NOLOAD_RADIO));
-  localized_strings->SetString("disable_individual_plugins",
-      l10n_util::GetStringUTF16(IDS_PLUGIN_SELECTIVE_DISABLE));
+  RegisterStrings(localized_strings, resources, arraysize(resources));
+  RegisterTitle(localized_strings, "contentSettingsPage",
+                IDS_CONTENT_SETTINGS_TITLE);
   localized_strings->SetBoolean("enable_click_to_play",
       CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableClickToPlay));
-
-  // Pop-ups filter.
-  localized_strings->SetString("popups_tab_label",
-      l10n_util::GetStringUTF16(IDS_POPUP_TAB_LABEL));
-  localized_strings->SetString("popups_header",
-      l10n_util::GetStringUTF16(IDS_POPUP_HEADER));
-  localized_strings->SetString("popups_allow",
-      l10n_util::GetStringUTF16(IDS_POPUP_ALLOW_RADIO));
-  localized_strings->SetString("popups_block",
-      l10n_util::GetStringUTF16(IDS_POPUP_BLOCK_RADIO));
-
-  // Location filter.
-  localized_strings->SetString("location_tab_label",
-      l10n_util::GetStringUTF16(IDS_GEOLOCATION_TAB_LABEL));
-  localized_strings->SetString("location_header",
-      l10n_util::GetStringUTF16(IDS_GEOLOCATION_HEADER));
-  localized_strings->SetString("location_allow",
-      l10n_util::GetStringUTF16(IDS_GEOLOCATION_ALLOW_RADIO));
-  localized_strings->SetString("location_ask",
-      l10n_util::GetStringUTF16(IDS_GEOLOCATION_ASK_RADIO));
-  localized_strings->SetString("location_block",
-      l10n_util::GetStringUTF16(IDS_GEOLOCATION_BLOCK_RADIO));
-
-  // Notifications filter.
-  localized_strings->SetString("notifications_tab_label",
-      l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_TAB_LABEL));
-  localized_strings->SetString("notifications_header",
-      l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_HEADER));
-  localized_strings->SetString("notifications_allow",
-      l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_ALLOW_RADIO));
-  localized_strings->SetString("notifications_ask",
-      l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_ASK_RADIO));
-  localized_strings->SetString("notifications_block",
-      l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_BLOCK_RADIO));
 }
 
 void ContentSettingsHandler::Initialize() {
   const HostContentSettingsMap* settings_map = GetContentSettingsMap();
   scoped_ptr<Value> block_3rd_party(Value::CreateBooleanValue(
       settings_map->BlockThirdPartyCookies()));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.setBlockThirdPartyCookies", *block_3rd_party.get());
 
+  clear_plugin_lso_data_enabled_.Init(prefs::kClearPluginLSODataEnabled,
+                                      g_browser_process->local_state(),
+                                      this);
+  UpdateClearPluginLSOData();
+
   notification_registrar_.Add(
       this, NotificationType::OTR_PROFILE_CREATED,
       NotificationService::AllSources());
@@ -322,7 +274,7 @@
       this, NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
       NotificationService::AllSources());
 
-  PrefService* prefs = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
   pref_change_registrar_.Init(prefs);
   pref_change_registrar_.Add(prefs::kGeolocationDefaultContentSetting, this);
   pref_change_registrar_.Add(prefs::kGeolocationContentSettings, this);
@@ -335,7 +287,7 @@
     case NotificationType::PROFILE_DESTROYED: {
       Profile* profile = static_cast<Source<Profile> >(source).ptr();
       if (profile->IsOffTheRecord()) {
-        dom_ui_->CallJavascriptFunction(
+        web_ui_->CallJavascriptFunction(
             L"ContentSettingsExceptionsArea.OTRProfileDestroyed");
       }
       break;
@@ -364,6 +316,8 @@
         UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
       else if (pref_name == prefs::kGeolocationContentSettings)
         UpdateGeolocationExceptionsView();
+      else if (pref_name == prefs::kClearPluginLSODataEnabled)
+        UpdateClearPluginLSOData();
       break;
     }
 
@@ -382,6 +336,16 @@
   }
 }
 
+void ContentSettingsHandler::UpdateClearPluginLSOData() {
+  int label_id = clear_plugin_lso_data_enabled_.GetValue() ?
+      IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX :
+      IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX;
+  scoped_ptr<Value> label(
+      Value::CreateStringValue(l10n_util::GetStringUTF16(label_id)));
+  web_ui_->CallJavascriptFunction(
+      L"ContentSettings.setClearLocalDataOnShutdownLabel", *label);
+}
+
 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
     ContentSettingsType type) {
   DictionaryValue filter_settings;
@@ -390,7 +354,7 @@
   filter_settings.SetBoolean(ContentSettingsTypeToGroupName(type) + ".managed",
       GetDefaultSettingManagedFromModel(type));
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.setContentFilterSettingsValue", filter_settings);
 }
 
@@ -398,10 +362,10 @@
     ContentSettingsType type) {
   ContentSetting default_setting;
   if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    default_setting = dom_ui_->GetProfile()->
+    default_setting = web_ui_->GetProfile()->
         GetGeolocationContentSettingsMap()->GetDefaultContentSetting();
   } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-    default_setting = dom_ui_->GetProfile()->
+    default_setting = web_ui_->GetProfile()->
         GetDesktopNotificationService()->GetDefaultContentSetting();
   } else {
     default_setting = GetContentSettingsMap()->GetDefaultContentSetting(type);
@@ -413,10 +377,10 @@
 bool ContentSettingsHandler::GetDefaultSettingManagedFromModel(
     ContentSettingsType type) {
   if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    return dom_ui_->GetProfile()->
+    return web_ui_->GetProfile()->
         GetGeolocationContentSettingsMap()->IsDefaultContentSettingManaged();
   } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-    return dom_ui_->GetProfile()->
+    return web_ui_->GetProfile()->
         GetDesktopNotificationService()->IsDefaultContentSettingManaged();
   } else {
     return GetContentSettingsMap()->IsDefaultContentSettingManaged(type);
@@ -455,7 +419,7 @@
 
 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
   GeolocationContentSettingsMap* map =
-      dom_ui_->GetProfile()->GetGeolocationContentSettingsMap();
+      web_ui_->GetProfile()->GetGeolocationContentSettingsMap();
   GeolocationContentSettingsMap::AllOriginsSettings all_settings =
       map->GetAllOriginsSettings();
   GeolocationContentSettingsMap::AllOriginsSettings::const_iterator i;
@@ -489,7 +453,7 @@
 
   StringValue type_string(
       ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.setExceptions", type_string, exceptions);
 
   // This is mainly here to keep this function ideologically parallel to
@@ -499,7 +463,7 @@
 
 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
   DesktopNotificationService* service =
-      dom_ui_->GetProfile()->GetDesktopNotificationService();
+      web_ui_->GetProfile()->GetDesktopNotificationService();
 
   std::vector<GURL> allowed(service->GetAllowedOrigins());
   std::vector<GURL> blocked(service->GetBlockedOrigins());
@@ -516,7 +480,7 @@
 
   StringValue type_string(
       ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.setExceptions", type_string, exceptions);
 
   // This is mainly here to keep this function ideologically parallel to
@@ -535,7 +499,7 @@
   }
 
   StringValue type_string(ContentSettingsTypeToGroupName(type));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.setExceptions", type_string, exceptions);
 
   UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
@@ -561,29 +525,26 @@
   }
 
   StringValue type_string(ContentSettingsTypeToGroupName(type));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.setOTRExceptions", type_string, otr_exceptions);
 }
 
 void ContentSettingsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("setContentFilter",
+  web_ui_->RegisterMessageCallback("setContentFilter",
       NewCallback(this,
                   &ContentSettingsHandler::SetContentFilter));
-  dom_ui_->RegisterMessageCallback("setAllowThirdPartyCookies",
+  web_ui_->RegisterMessageCallback("setAllowThirdPartyCookies",
       NewCallback(this,
                   &ContentSettingsHandler::SetAllowThirdPartyCookies));
-  dom_ui_->RegisterMessageCallback("removeException",
+  web_ui_->RegisterMessageCallback("removeException",
       NewCallback(this,
                   &ContentSettingsHandler::RemoveException));
-  dom_ui_->RegisterMessageCallback("setException",
+  web_ui_->RegisterMessageCallback("setException",
       NewCallback(this,
                   &ContentSettingsHandler::SetException));
-  dom_ui_->RegisterMessageCallback("checkExceptionPatternValidity",
+  web_ui_->RegisterMessageCallback("checkExceptionPatternValidity",
       NewCallback(this,
                   &ContentSettingsHandler::CheckExceptionPatternValidity));
-  dom_ui_->RegisterMessageCallback(
-      "openPluginsTab",
-      NewCallback(this, &ContentSettingsHandler::OpenPluginsTab));
 }
 
 void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
@@ -598,10 +559,10 @@
   ContentSetting default_setting = ContentSettingFromString(setting);
   ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
   if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    dom_ui_->GetProfile()->GetGeolocationContentSettingsMap()->
+    web_ui_->GetProfile()->GetGeolocationContentSettingsMap()->
         SetDefaultContentSetting(default_setting);
   } else if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-    dom_ui_->GetProfile()->GetDesktopNotificationService()->
+    web_ui_->GetProfile()->GetDesktopNotificationService()->
         SetDefaultContentSetting(default_setting);
   } else {
     GetContentSettingsMap()->
@@ -629,7 +590,7 @@
     rv = args->GetString(arg_i++, &embedding_origin);
     DCHECK(rv);
 
-    dom_ui_->GetProfile()->GetGeolocationContentSettingsMap()->
+    web_ui_->GetProfile()->GetGeolocationContentSettingsMap()->
         SetContentSetting(GURL(origin),
                           GURL(embedding_origin),
                           CONTENT_SETTING_DEFAULT);
@@ -642,11 +603,11 @@
     DCHECK(rv);
     ContentSetting content_setting = ContentSettingFromString(setting);
     if (content_setting == CONTENT_SETTING_ALLOW) {
-      dom_ui_->GetProfile()->GetDesktopNotificationService()->
+      web_ui_->GetProfile()->GetDesktopNotificationService()->
           ResetAllowedOrigin(GURL(origin));
     } else {
       DCHECK_EQ(content_setting, CONTENT_SETTING_BLOCK);
-      dom_ui_->GetProfile()->GetDesktopNotificationService()->
+      web_ui_->GetProfile()->GetDesktopNotificationService()->
           ResetBlockedOrigin(GURL(origin));
     }
   } else {
@@ -722,17 +683,13 @@
   scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string));
   scoped_ptr<Value> valid_value(Value::CreateBooleanValue(pattern.IsValid()));
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"ContentSettings.patternValidityCheckComplete", *type,
                                                        *mode_value.get(),
                                                        *pattern_value.get(),
                                                        *valid_value.get());
 }
 
-void ContentSettingsHandler::OpenPluginsTab(const ListValue* args) {
-  BrowserList::GetLastActive()->OpenPluginsTabAndActivate();
-}
-
 // static
 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
     ContentSettingsType type) {
@@ -759,12 +716,12 @@
 }
 
 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
-  return dom_ui_->GetProfile()->GetHostContentSettingsMap();
+  return web_ui_->GetProfile()->GetHostContentSettingsMap();
 }
 
 HostContentSettingsMap*
     ContentSettingsHandler::GetOTRContentSettingsMap() {
-  Profile* profile = dom_ui_->GetProfile();
+  Profile* profile = web_ui_->GetProfile();
   if (profile->HasOffTheRecordProfile())
     return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
   return NULL;
diff --git a/chrome/browser/dom_ui/options/content_settings_handler.h b/chrome/browser/dom_ui/options/content_settings_handler.h
index 1542539..adc16db 100644
--- a/chrome/browser/dom_ui/options/content_settings_handler.h
+++ b/chrome/browser/dom_ui/options/content_settings_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,6 +7,7 @@
 #pragma once
 
 #include "chrome/browser/dom_ui/options/options_ui.h"
+#include "chrome/browser/plugin_data_remover_helper.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/common/content_settings_types.h"
 #include "chrome/common/notification_observer.h"
@@ -39,6 +40,8 @@
 
   // Updates the page with the default settings (allow, ask, block, etc.)
   void UpdateSettingDefaultFromModel(ContentSettingsType type);
+  // Updates the state of the "Clear plugin LSO data on exit" checkbox.
+  void UpdateClearPluginLSOData();
 
   // Clobbers and rebuilds the specific content setting type exceptions table.
   void UpdateExceptionsViewFromModel(ContentSettingsType type);
@@ -78,9 +81,6 @@
   // rejected. Called while the user is editing an exception pattern.
   void CheckExceptionPatternValidity(const ListValue* args);
 
-  // Show the about:plugins page in a new tab.
-  void OpenPluginsTab(const ListValue* args);
-
   // Sets the global 3rd party cookies pref.
   void SetAllowThirdPartyCookies(const ListValue* args);
 
@@ -104,6 +104,7 @@
 
   NotificationRegistrar notification_registrar_;
   PrefChangeRegistrar pref_change_registrar_;
+  PluginDataRemoverHelper clear_plugin_lso_data_enabled_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentSettingsHandler);
 };
diff --git a/chrome/browser/dom_ui/options/cookies_view_handler.cc b/chrome/browser/dom_ui/options/cookies_view_handler.cc
index 5cfeb7a..edde6b6 100644
--- a/chrome/browser/dom_ui/options/cookies_view_handler.cc
+++ b/chrome/browser/dom_ui/options/cookies_view_handler.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/cookies_view_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/string_number_conversions.h"
 #include "base/string_split.h"
@@ -18,29 +17,31 @@
 #include "chrome/browser/profiles/profile.h"
 #include "grit/generated_resources.h"
 #include "net/base/cookie_monster.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
-static const char kKeyId[]          = "id";
-static const char kKeyTitle[]       = "title";
-static const char kKeyIcon[]        = "icon";
-static const char kKeyType[]        = "type";
+static const char kKeyId[] = "id";
+static const char kKeyTitle[] = "title";
+static const char kKeyIcon[] = "icon";
+static const char kKeyType[] = "type";
 static const char kKeyHasChildren[] = "hasChildren";
 
-static const char kKeyName[]        = "name";
-static const char kKeyContent[]     = "content";
-static const char kKeyDomain[]      = "domain";
-static const char kKeyPath[]        = "path";
-static const char kKeySendFor[]     = "sendfor";
-static const char kKeyDesc[]        = "desc";
-static const char kKeySize[]        = "size";
-static const char kKeyOrigin[]      = "origin";
-static const char kKeyManifest[]    = "manifest";
+static const char kKeyName[] = "name";
+static const char kKeyContent[] = "content";
+static const char kKeyDomain[] = "domain";
+static const char kKeyPath[] = "path";
+static const char kKeySendFor[] = "sendfor";
+static const char kKeyAccessibleToScript[] = "accessibleToScript";
+static const char kKeyDesc[] = "desc";
+static const char kKeySize[] = "size";
+static const char kKeyOrigin[] = "origin";
+static const char kKeyManifest[] = "manifest";
 
-static const char kKeyAccessed[]    = "accessed";
-static const char kKeyCreated[]     = "created";
-static const char kKeyExpires[]     = "expires";
-static const char kKeyModified[]    = "modified";
+static const char kKeyAccessed[] = "accessed";
+static const char kKeyCreated[] = "created";
+static const char kKeyExpires[] = "expires";
+static const char kKeyModified[] = "modified";
 
 // Encodes a pointer value into a hex string.
 std::string PointerToHexString(const void* pointer) {
@@ -61,7 +62,7 @@
 // Populate given |dict| with cookie tree node properties.
 void GetCookieTreeNodeDictionary(const CookieTreeNode& node,
                                  DictionaryValue* dict) {
-  // Use node's address as an id for DOMUI to look it up.
+  // Use node's address as an id for WebUI to look it up.
   dict->SetString(kKeyId, PointerToHexString(&node));
   dict->SetString(kKeyTitle, node.GetTitle());
   dict->SetBoolean(kKeyHasChildren, !!node.GetChildCount());
@@ -69,6 +70,9 @@
   switch (node.GetDetailedInfo().node_type) {
     case CookieTreeNode::DetailedInfo::TYPE_ORIGIN: {
       dict->SetString(kKeyType, "origin");
+#if defined(OS_MACOSX)
+      dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
+#endif
       break;
     }
     case CookieTreeNode::DetailedInfo::TYPE_COOKIE: {
@@ -85,6 +89,10 @@
       dict->SetString(kKeySendFor, cookie.IsSecure() ?
           l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_SECURE) :
           l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_ANY));
+      std::string accessible = cookie.IsHttpOnly() ?
+          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO) :
+          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES);
+      dict->SetString(kKeyAccessibleToScript, accessible);
       dict->SetString(kKeyCreated, UTF16ToUTF8(
           base::TimeFormatFriendlyDateAndTime(cookie.CreationDate())));
       dict->SetString(kKeyExpires, cookie.DoesExpire() ? UTF16ToUTF8(
@@ -168,6 +176,9 @@
       break;
     }
     default:
+#if defined(OS_MACOSX)
+      dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
+#endif
       break;
   }
 }
@@ -184,7 +195,7 @@
 }
 
 // TODO(xiyuan): Remove this function when strings are updated.
-// Remove "&" in button label for DOMUI.
+// Remove "&" in button label for WebUI.
 string16 CleanButtonLabel(const string16& text) {
   string16 out(text);
   ReplaceFirstSubstringAfterOffset(&out, 0, ASCIIToUTF16("&"), string16());
@@ -203,8 +214,8 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("cookiesViewPage",
-      l10n_util::GetStringUTF16(IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE));
+  RegisterTitle(localized_strings, "cookiesViewPage",
+                IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE);
 
   localized_strings->SetString("label_cookie_search",
       l10n_util::GetStringUTF16(IDS_COOKIES_SEARCH_LABEL));
@@ -219,6 +230,8 @@
       l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_PATH_LABEL));
   localized_strings->SetString("label_cookie_send_for",
       l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_SENDFOR_LABEL));
+  localized_strings->SetString("label_cookie_accessible_to_script",
+      l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_LABEL));
   localized_strings->SetString("label_cookie_created",
       l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_CREATED_LABEL));
   localized_strings->SetString("label_cookie_expires",
@@ -256,18 +269,18 @@
 }
 
 void CookiesViewHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("updateCookieSearchResults",
+  web_ui_->RegisterMessageCallback("updateCookieSearchResults",
       NewCallback(this, &CookiesViewHandler::UpdateSearchResults));
-  dom_ui_->RegisterMessageCallback("removeAllCookies",
+  web_ui_->RegisterMessageCallback("removeAllCookies",
       NewCallback(this, &CookiesViewHandler::RemoveAll));
-  dom_ui_->RegisterMessageCallback("removeCookie",
+  web_ui_->RegisterMessageCallback("removeCookie",
       NewCallback(this, &CookiesViewHandler::Remove));
-  dom_ui_->RegisterMessageCallback("loadCookie",
+  web_ui_->RegisterMessageCallback("loadCookie",
       NewCallback(this, &CookiesViewHandler::LoadChildren));
 }
 
-void CookiesViewHandler::TreeNodesAdded(TreeModel* model,
-                                        TreeModelNode* parent,
+void CookiesViewHandler::TreeNodesAdded(ui::TreeModel* model,
+                                        ui::TreeModelNode* parent,
                                         int start,
                                         int count) {
   // Skip if there is a batch update in progress.
@@ -283,11 +296,11 @@
       Value::CreateStringValue(PointerToHexString(parent)));
   args.Append(Value::CreateIntegerValue(start));
   args.Append(children);
-  dom_ui_->CallJavascriptFunction(L"CookiesView.onTreeItemAdded", args);
+  web_ui_->CallJavascriptFunction(L"CookiesView.onTreeItemAdded", args);
 }
 
-void CookiesViewHandler::TreeNodesRemoved(TreeModel* model,
-                                          TreeModelNode* parent,
+void CookiesViewHandler::TreeNodesRemoved(ui::TreeModel* model,
+                                          ui::TreeModelNode* parent,
                                           int start,
                                           int count) {
   // Skip if there is a batch update in progress.
@@ -300,7 +313,7 @@
       Value::CreateStringValue(PointerToHexString(parent)));
   args.Append(Value::CreateIntegerValue(start));
   args.Append(Value::CreateIntegerValue(count));
-  dom_ui_->CallJavascriptFunction(L"CookiesView.onTreeItemRemoved", args);
+  web_ui_->CallJavascriptFunction(L"CookiesView.onTreeItemRemoved", args);
 }
 
 void CookiesViewHandler::TreeModelBeginBatch(CookiesTreeModel* model) {
@@ -322,7 +335,7 @@
   }
 
   if (!cookies_tree_model_.get()) {
-    Profile* profile = dom_ui_->GetProfile();
+    Profile* profile = web_ui_->GetProfile();
     cookies_tree_model_.reset(new CookiesTreeModel(
         profile->GetRequestContext()->GetCookieStore()->GetCookieMonster(),
         new BrowsingDataDatabaseHelper(profile),
@@ -330,7 +343,7 @@
         NULL,
         new BrowsingDataAppCacheHelper(profile),
         BrowsingDataIndexedDBHelper::Create(profile)));
-    cookies_tree_model_->AddObserver(this);
+    cookies_tree_model_->AddCookiesTreeObserver(this);
   }
 
   cookies_tree_model_->UpdateSearchResults(UTF8ToWide(query));
@@ -396,5 +409,5 @@
       Value::CreateStringValue(PointerToHexString(parent)));
   args.Append(children);
 
-  dom_ui_->CallJavascriptFunction(L"CookiesView.loadChildren", args);
+  web_ui_->CallJavascriptFunction(L"CookiesView.loadChildren", args);
 }
diff --git a/chrome/browser/dom_ui/options/cookies_view_handler.h b/chrome/browser/dom_ui/options/cookies_view_handler.h
index b114d37..12e52be 100644
--- a/chrome/browser/dom_ui/options/cookies_view_handler.h
+++ b/chrome/browser/dom_ui/options/cookies_view_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -20,16 +20,16 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void RegisterMessages();
 
-  // TreeModel::Observer implementation.
-  virtual void TreeNodesAdded(TreeModel* model,
-                              TreeModelNode* parent,
+  // ui::TreeModel::Observer implementation.
+  virtual void TreeNodesAdded(ui::TreeModel* model,
+                              ui::TreeModelNode* parent,
                               int start,
                               int count);
-  virtual void TreeNodesRemoved(TreeModel* model,
-                                TreeModelNode* parent,
+  virtual void TreeNodesRemoved(ui::TreeModel* model,
+                                ui::TreeModelNode* parent,
                                 int start,
                                 int count);
-  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) {}
+  virtual void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) {}
   virtual void TreeModelBeginBatch(CookiesTreeModel* model);
   virtual void TreeModelEndBatch(CookiesTreeModel* model);
 
@@ -44,14 +44,14 @@
   void Remove(const ListValue* args);
 
   // Get the tree node using the tree path info in |args| and call
-  // SendChildren to pass back children nodes data to DOMUI.
+  // SendChildren to pass back children nodes data to WebUI.
   void LoadChildren(const ListValue* args);
 
   // Gets tree node from given path. Return NULL if path is not valid.
   CookieTreeNode* GetTreeNodeFromPath(const std::string& path);
 
   // Get children nodes data and pass it to 'CookiesView.loadChildren' to
-  // update the DOMUI.
+  // update the WebUI.
   void SendChildren(CookieTreeNode* parent);
 
   // The Cookies Tree model
diff --git a/chrome/browser/dom_ui/options/core_options_handler.cc b/chrome/browser/dom_ui/options/core_options_handler.cc
index ab8a6d4..5a20e8b 100644
--- a/chrome/browser/dom_ui/options/core_options_handler.cc
+++ b/chrome/browser/dom_ui/options/core_options_handler.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/core_options_handler.h"
 
-#include "app/l10n_util.h"
+#include "base/json/json_reader.h"
+#include "base/scoped_ptr.h"
 #include "base/string16.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -22,6 +23,7 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 CoreOptionsHandler::CoreOptionsHandler() {}
 
@@ -33,37 +35,14 @@
   // Main
   localized_strings->SetString("title",
       l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
-  localized_strings->SetString("browserPage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_GENERAL_TAB_LABEL));
-  localized_strings->SetString("personalPage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTENT_TAB_LABEL));
-  localized_strings->SetString("advancedPage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_ADVANCED_TAB_LABEL));
-#if defined(OS_CHROMEOS)
-  localized_strings->SetString("internetPage",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_INTERNET_TAB_LABEL));
-  localized_strings->SetString("languageChewingPage",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTINGS_TITLE));
-  localized_strings->SetString("languageHangulPage",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_TITLE));
-  localized_strings->SetString("languageMozcPage",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_MOZC_SETTINGS_TITLE));
-  localized_strings->SetString("languagePinyinPage",
-      l10n_util::GetStringUTF16(
-          IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTINGS_TITLE));
-#endif
+
+  // Managed prefs
   localized_strings->SetString("managedPrefsBannerText",
       l10n_util::GetStringUTF16(IDS_OPTIONS_MANAGED_PREFS));
 
   // Search
   localized_strings->SetString("searchPageTitle",
       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_TITLE));
-  localized_strings->SetString("searchPageInfo",
-      l10n_util::GetStringFUTF16(IDS_OPTIONS_SEARCH_PAGE_INFO,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
   localized_strings->SetString("searchPageNoMatches",
       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_NO_MATCHES));
   localized_strings->SetString("searchPageHelpLabel",
@@ -110,10 +89,10 @@
   }
 }
 
-DOMMessageHandler* CoreOptionsHandler::Attach(DOMUI* dom_ui) {
-  DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
-  DCHECK(dom_ui_);
-  registrar_.Init(dom_ui_->GetProfile()->GetPrefs());
+WebUIMessageHandler* CoreOptionsHandler::Attach(WebUI* web_ui) {
+  WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
+  DCHECK(web_ui_);
+  registrar_.Init(web_ui_->GetProfile()->GetPrefs());
   return result;
 }
 
@@ -125,32 +104,34 @@
 }
 
 void CoreOptionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("coreOptionsInitialize",
+  web_ui_->RegisterMessageCallback("coreOptionsInitialize",
       NewCallback(this, &CoreOptionsHandler::HandleInitialize));
-  dom_ui_->RegisterMessageCallback("fetchPrefs",
+  web_ui_->RegisterMessageCallback("fetchPrefs",
       NewCallback(this, &CoreOptionsHandler::HandleFetchPrefs));
-  dom_ui_->RegisterMessageCallback("observePrefs",
+  web_ui_->RegisterMessageCallback("observePrefs",
       NewCallback(this, &CoreOptionsHandler::HandleObservePrefs));
-  dom_ui_->RegisterMessageCallback("setBooleanPref",
+  web_ui_->RegisterMessageCallback("setBooleanPref",
       NewCallback(this, &CoreOptionsHandler::HandleSetBooleanPref));
-  dom_ui_->RegisterMessageCallback("setIntegerPref",
+  web_ui_->RegisterMessageCallback("setIntegerPref",
       NewCallback(this, &CoreOptionsHandler::HandleSetIntegerPref));
-  dom_ui_->RegisterMessageCallback("setStringPref",
+  web_ui_->RegisterMessageCallback("setDoublePref",
+      NewCallback(this, &CoreOptionsHandler::HandleSetDoublePref));
+  web_ui_->RegisterMessageCallback("setStringPref",
       NewCallback(this, &CoreOptionsHandler::HandleSetStringPref));
-  dom_ui_->RegisterMessageCallback("setObjectPref",
-      NewCallback(this, &CoreOptionsHandler::HandleSetObjectPref));
-  dom_ui_->RegisterMessageCallback("clearPref",
+  web_ui_->RegisterMessageCallback("setListPref",
+      NewCallback(this, &CoreOptionsHandler::HandleSetListPref));
+  web_ui_->RegisterMessageCallback("clearPref",
       NewCallback(this, &CoreOptionsHandler::HandleClearPref));
-  dom_ui_->RegisterMessageCallback("coreOptionsUserMetricsAction",
+  web_ui_->RegisterMessageCallback("coreOptionsUserMetricsAction",
       NewCallback(this, &CoreOptionsHandler::HandleUserMetricsAction));
 }
 
 void CoreOptionsHandler::HandleInitialize(const ListValue* args) {
-  static_cast<OptionsUI*>(dom_ui_)->InitializeHandlers();
+  static_cast<OptionsUI*>(web_ui_)->InitializeHandlers();
 }
 
 Value* CoreOptionsHandler::FetchPref(const std::string& pref_name) {
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
 
   const PrefService::Preference* pref =
       pref_service->FindPreference(pref_name.c_str());
@@ -172,35 +153,30 @@
 }
 
 void CoreOptionsHandler::SetPref(const std::string& pref_name,
-                                 Value::ValueType pref_type,
-                                 const std::string& value_string,
+                                 const Value* value,
                                  const std::string& metric) {
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
 
-  switch (pref_type) {
+  switch (value->GetType()) {
     case Value::TYPE_BOOLEAN:
-      pref_service->SetBoolean(pref_name.c_str(), value_string == "true");
-      break;
     case Value::TYPE_INTEGER:
-      int int_value;
-      if (base::StringToInt(value_string, &int_value))
-        pref_service->SetInteger(pref_name.c_str(), int_value);
-      break;
+    case Value::TYPE_DOUBLE:
     case Value::TYPE_STRING:
-      pref_service->SetString(pref_name.c_str(), value_string);
+      pref_service->Set(pref_name.c_str(), *value);
       break;
+
     default:
       NOTREACHED();
       return;
   }
 
   pref_service->ScheduleSavePersistentPrefs();
-  ProcessUserMetric(pref_type, value_string, metric);
+  ProcessUserMetric(value, metric);
 }
 
 void CoreOptionsHandler::ClearPref(const std::string& pref_name,
                                    const std::string& metric) {
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
   pref_service->ClearPref(pref_name.c_str());
   pref_service->ScheduleSavePersistentPrefs();
 
@@ -208,15 +184,17 @@
     UserMetricsRecordAction(UserMetricsAction(metric.c_str()));
 }
 
-void CoreOptionsHandler::ProcessUserMetric(Value::ValueType pref_type,
-                                           const std::string& value_string,
+void CoreOptionsHandler::ProcessUserMetric(const Value* value,
                                            const std::string& metric) {
   if (metric.empty())
     return;
 
   std::string metric_string = metric;
-  if (pref_type == Value::TYPE_BOOLEAN)
-    metric_string += (value_string == "true" ? "_Enable" : "_Disable");
+  if (value->IsType(Value::TYPE_BOOLEAN)) {
+    bool bool_value;
+    CHECK(value->GetAsBoolean(&bool_value));
+    metric_string += bool_value ? "_Enable" : "_Disable";
+  }
 
   UserMetricsRecordAction(UserMetricsAction(metric_string.c_str()));
 }
@@ -256,7 +234,7 @@
 
     result_value.Set(pref_name.c_str(), FetchPref(pref_name));
   }
-  dom_ui_->CallJavascriptFunction(UTF16ToWideHack(callback_function).c_str(),
+  web_ui_->CallJavascriptFunction(UTF16ToWideHack(callback_function).c_str(),
                                   result_value);
 }
 
@@ -299,12 +277,16 @@
   HandleSetPref(args, Value::TYPE_INTEGER);
 }
 
+void CoreOptionsHandler::HandleSetDoublePref(const ListValue* args) {
+  HandleSetPref(args, Value::TYPE_DOUBLE);
+}
+
 void CoreOptionsHandler::HandleSetStringPref(const ListValue* args) {
   HandleSetPref(args, Value::TYPE_STRING);
 }
 
-void CoreOptionsHandler::HandleSetObjectPref(const ListValue* args) {
-  HandleSetPref(args, Value::TYPE_NULL);
+void CoreOptionsHandler::HandleSetListPref(const ListValue* args) {
+  HandleSetPref(args, Value::TYPE_LIST);
 }
 
 void CoreOptionsHandler::HandleSetPref(const ListValue* args,
@@ -315,15 +297,37 @@
   if (!args->GetString(0, &pref_name))
     return;
 
-  std::string value_string;
-  if (!args->GetString(1, &value_string))
+  Value* value;
+  if (!args->Get(1, &value))
     return;
 
+  scoped_ptr<Value> temp_value;
+
+  // In JS all numbers are doubles.
+  if (type == Value::TYPE_INTEGER) {
+    double double_value;
+    CHECK(value->GetAsDouble(&double_value));
+    temp_value.reset(Value::CreateIntegerValue(static_cast<int>(double_value)));
+    value = temp_value.get();
+
+  // In case we have a List pref we got a JSON string.
+  } else if (type == Value::TYPE_LIST) {
+    std::string json_string;
+    CHECK(value->GetAsString(&json_string));
+    temp_value.reset(
+        base::JSONReader().JsonToValue(json_string,
+                                       false,  // no check_root
+                                       false));  // no trailing comma
+    value = temp_value.get();
+  }
+
+  CHECK_EQ(type, value->GetType());
+
   std::string metric;
   if (args->GetSize() > 2)
     args->GetString(2, &metric);
 
-  SetPref(pref_name, type, value_string, metric);
+  SetPref(pref_name, value, metric);
 }
 
 void CoreOptionsHandler::HandleClearPref(const ListValue* args) {
@@ -347,7 +351,7 @@
 }
 
 void CoreOptionsHandler::NotifyPrefChanged(const std::string* pref_name) {
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
   const PrefService::Preference* pref =
       pref_service->FindPreference(pref_name->c_str());
   if (pref) {
@@ -363,7 +367,7 @@
       dict->SetBoolean("managed", pref->IsManaged());
       result_value.Append(dict);
 
-      dom_ui_->CallJavascriptFunction(callback_function, result_value);
+      web_ui_->CallJavascriptFunction(callback_function, result_value);
     }
   }
 }
diff --git a/chrome/browser/dom_ui/options/core_options_handler.h b/chrome/browser/dom_ui/options/core_options_handler.h
index 7860525..cc6c2c1 100644
--- a/chrome/browser/dom_ui/options/core_options_handler.h
+++ b/chrome/browser/dom_ui/options/core_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -29,9 +29,9 @@
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
 
  protected:
   // Fetches a pref value of given |pref_name|.
@@ -41,10 +41,9 @@
   // Observes a pref of given |pref_name|.
   virtual void ObservePref(const std::string& pref_name);
 
-  // Sets a pref value |value_string| of |pref_type| to given |pref_name|.
+  // Sets a pref |value| to given |pref_name|.
   virtual void SetPref(const std::string& pref_name,
-                       Value::ValueType pref_type,
-                       const std::string& value_string,
+                       const Value* value,
                        const std::string& metric);
 
   // Clears pref value for given |pref_name|.
@@ -54,8 +53,7 @@
   virtual void StopObservingPref(const std::string& path);
 
   // Records a user metric action for the given value.
-  void ProcessUserMetric(Value::ValueType pref_type,
-                         const std::string& value_string,
+  void ProcessUserMetric(const Value* value,
                          const std::string& metric);
 
   typedef std::multimap<std::string, std::wstring> PreferenceCallbackMap;
@@ -83,8 +81,9 @@
   //  item 2 - name of the metric identifier (optional).
   void HandleSetBooleanPref(const ListValue* args);
   void HandleSetIntegerPref(const ListValue* args);
+  void HandleSetDoublePref(const ListValue* args);
   void HandleSetStringPref(const ListValue* args);
-  void HandleSetObjectPref(const ListValue* args);
+  void HandleSetListPref(const ListValue* args);
 
   void HandleSetPref(const ListValue* args, Value::ValueType type);
 
diff --git a/chrome/browser/dom_ui/options/dom_options_util.cc b/chrome/browser/dom_ui/options/dom_options_util.cc
index f528a47..2eb8ec3 100644
--- a/chrome/browser/dom_ui/options/dom_options_util.cc
+++ b/chrome/browser/dom_ui/options/dom_options_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,10 +8,12 @@
 
 namespace dom_options_util {
 
+// TODO(estade): update all strings that have a trailing colon once we get rid
+// of the native dialogs.
 string16 StripColon(const string16& str) {
-  const string16::value_type kColon[] = {':',0};
+  const string16::value_type kColon[] = { ':', 0 };
   string16 result;
-  RemoveChars(str, kColon, &result);
+  TrimString(str, kColon, &result);
   return result;
 }
 
diff --git a/chrome/browser/dom_ui/options/font_settings_handler.cc b/chrome/browser/dom_ui/options/font_settings_handler.cc
index 64eef14..6942acd 100644
--- a/chrome/browser/dom_ui/options/font_settings_handler.cc
+++ b/chrome/browser/dom_ui/options/font_settings_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,12 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/character_encoding.h"
+#include "chrome/browser/dom_ui/options/dom_options_util.h"
 #include "chrome/browser/dom_ui/options/font_settings_utils.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -20,6 +20,7 @@
 #include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 FontSettingsHandler::FontSettingsHandler() {
 }
@@ -31,34 +32,37 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("fontSettingsTitle",
-      l10n_util::GetStringUTF16(IDS_FONT_LANGUAGE_SETTING_FONT_TAB_TITLE));
-  localized_strings->SetString("fontSettingsFontTitle",
+  RegisterTitle(localized_strings, "fontSettingsPage",
+                IDS_FONT_LANGUAGE_SETTING_FONT_TAB_TITLE);
+  localized_strings->SetString("fontSettingsStandard",
+      dom_options_util::StripColon(
+          l10n_util::GetStringUTF16(
+              IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_STANDARD_LABEL)));
+  localized_strings->SetString("fontSettingsFixedWidth",
+      dom_options_util::StripColon(
+          l10n_util::GetStringUTF16(
+              IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_FIXED_WIDTH_LABEL)));
+  localized_strings->SetString("fontSettingsMinimumSize",
       l10n_util::GetStringUTF16(
-          IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_FONT_TITLE));
-  localized_strings->SetString("fontSettingsSerifLabel",
+          IDS_FONT_LANGUAGE_SETTING_MINIMUM_FONT_SIZE_TITLE));
+  localized_strings->SetString("fontSettingsEncoding",
       l10n_util::GetStringUTF16(
-          IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SERIF_LABEL));
-  localized_strings->SetString("fontSettingsSansSerifLabel",
-      l10n_util::GetStringUTF16(
-          IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SANS_SERIF_LABEL));
-  localized_strings->SetString("fontSettingsFixedWidthLabel",
-      l10n_util::GetStringUTF16(
-          IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_FIXED_WIDTH_LABEL));
+          IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_ENCODING_TITLE));
   localized_strings->SetString("fontSettingsSizeLabel",
       l10n_util::GetStringUTF16(
           IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_SELECTOR_LABEL));
-
-  localized_strings->SetString("fontSettingsMinimumSizeTitle",
+  localized_strings->SetString("fontSettingsSizeTiny",
       l10n_util::GetStringUTF16(
-          IDS_FONT_LANGUAGE_SETTING_MINIMUM_FONT_SIZE_TITLE));
-
-  localized_strings->SetString("fontSettingsEncodingTitle",
+          IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_TINY));
+  localized_strings->SetString("fontSettingsSizeHuge",
       l10n_util::GetStringUTF16(
-          IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_ENCODING_TITLE));
+          IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_HUGE));
   localized_strings->SetString("fontSettingsEncodingLabel",
       l10n_util::GetStringUTF16(
           IDS_FONT_LANGUAGE_SETTING_FONT_DEFAULT_ENCODING_SELECTOR_LABEL));
+  localized_strings->SetString("fontSettingsLoremIpsum",
+      l10n_util::GetStringUTF16(
+          IDS_FONT_LANGUAGE_SETTING_LOREM_IPSUM));
 
   // Fonts
   ListValue* font_list = FontSettingsUtilities::GetFontsList();
@@ -117,27 +121,27 @@
 }
 
 void FontSettingsHandler::Initialize() {
-  SetupSerifFontPreview();
-  SetupSansSerifFontPreview();
-  SetupFixedFontPreview();
+  SetupSerifFontSample();
+  SetupMinimumFontSample();
+  SetupFixedFontSample();
 }
 
-DOMMessageHandler* FontSettingsHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* FontSettingsHandler::Attach(WebUI* web_ui) {
   // Call through to superclass.
-  DOMMessageHandler* handler = OptionsPageUIHandler::Attach(dom_ui);
+  WebUIMessageHandler* handler = OptionsPageUIHandler::Attach(web_ui);
 
   // Perform validation for saved fonts.
-  DCHECK(dom_ui_);
-  PrefService* pref_service = dom_ui_->GetProfile()->GetPrefs();
+  DCHECK(web_ui_);
+  PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
   FontSettingsUtilities::ValidateSavedFonts(pref_service);
 
   // Register for preferences that we need to observe manually.
   serif_font_.Init(prefs::kWebKitSerifFontFamily, pref_service, this);
-  sans_serif_font_.Init(prefs::kWebKitSansSerifFontFamily, pref_service, this);
   fixed_font_.Init(prefs::kWebKitFixedFontFamily, pref_service, this);
   default_font_size_.Init(prefs::kWebKitDefaultFontSize, pref_service, this);
   default_fixed_font_size_.Init(prefs::kWebKitDefaultFixedFontSize,
                                 pref_service, this);
+  minimum_font_size_.Init(prefs::kWebKitMinimumFontSize, pref_service, this);
 
   // Return result from the superclass.
   return handler;
@@ -150,37 +154,35 @@
     std::string* pref_name = Details<std::string>(details).ptr();
     if (*pref_name == prefs::kWebKitSerifFontFamily ||
         *pref_name == prefs::kWebKitDefaultFontSize) {
-      SetupSerifFontPreview();
-    } else if (*pref_name == prefs::kWebKitSansSerifFontFamily ||
-               *pref_name == prefs::kWebKitDefaultFontSize) {
-      SetupSansSerifFontPreview();
+      SetupSerifFontSample();
     } else if (*pref_name == prefs::kWebKitFixedFontFamily ||
                *pref_name == prefs::kWebKitDefaultFixedFontSize) {
-      SetupFixedFontPreview();
+      SetupFixedFontSample();
+    } else if (*pref_name == prefs::kWebKitMinimumFontSize) {
+      SetupMinimumFontSample();
     }
   }
 }
 
-void FontSettingsHandler::SetupSerifFontPreview() {
-  DCHECK(dom_ui_);
+void FontSettingsHandler::SetupSerifFontSample() {
+  DCHECK(web_ui_);
   StringValue font_value(serif_font_.GetValue());
   FundamentalValue size_value(default_font_size_.GetValue());
-  dom_ui_->CallJavascriptFunction(
-      L"FontSettings.setupSerifFontPreview", font_value, size_value);
+  web_ui_->CallJavascriptFunction(
+      L"FontSettings.setupSerifFontSample", font_value, size_value);
 }
 
-void FontSettingsHandler::SetupSansSerifFontPreview() {
-  DCHECK(dom_ui_);
-  StringValue font_value(sans_serif_font_.GetValue());
-  FundamentalValue size_value(default_font_size_.GetValue());
-  dom_ui_->CallJavascriptFunction(
-      L"FontSettings.setupSansSerifFontPreview", font_value, size_value);
-}
-
-void FontSettingsHandler::SetupFixedFontPreview() {
-  DCHECK(dom_ui_);
+void FontSettingsHandler::SetupFixedFontSample() {
+  DCHECK(web_ui_);
   StringValue font_value(fixed_font_.GetValue());
   FundamentalValue size_value(default_fixed_font_size_.GetValue());
-  dom_ui_->CallJavascriptFunction(
-      L"FontSettings.setupFixedFontPreview", font_value, size_value);
+  web_ui_->CallJavascriptFunction(
+      L"FontSettings.setupFixedFontSample", font_value, size_value);
+}
+
+void FontSettingsHandler::SetupMinimumFontSample() {
+  DCHECK(web_ui_);
+  FundamentalValue size_value(minimum_font_size_.GetValue());
+  web_ui_->CallJavascriptFunction(
+      L"FontSettings.setupMinimumFontSample", size_value);
 }
diff --git a/chrome/browser/dom_ui/options/font_settings_handler.h b/chrome/browser/dom_ui/options/font_settings_handler.h
index c3e72c8..ad7a907 100644
--- a/chrome/browser/dom_ui/options/font_settings_handler.h
+++ b/chrome/browser/dom_ui/options/font_settings_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,8 +19,8 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void Initialize();
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
 
   // NotificationObserver implementation.
   virtual void Observe(NotificationType type,
@@ -28,15 +28,15 @@
                        const NotificationDetails& details);
 
  private:
-  void SetupSerifFontPreview();
-  void SetupSansSerifFontPreview();
-  void SetupFixedFontPreview();
+  void SetupSerifFontSample();
+  void SetupFixedFontSample();
+  void SetupMinimumFontSample();
 
   StringPrefMember serif_font_;
-  StringPrefMember sans_serif_font_;
   StringPrefMember fixed_font_;
   IntegerPrefMember default_font_size_;
   IntegerPrefMember default_fixed_font_size_;
+  IntegerPrefMember minimum_font_size_;
 
   DISALLOW_COPY_AND_ASSIGN(FontSettingsHandler);
 };
diff --git a/chrome/browser/dom_ui/options/font_settings_utils_win.cc b/chrome/browser/dom_ui/options/font_settings_utils_win.cc
index 482e6e1..9a7c9bb 100644
--- a/chrome/browser/dom_ui/options/font_settings_utils_win.cc
+++ b/chrome/browser/dom_ui/options/font_settings_utils_win.cc
@@ -1,9 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/font_settings_utils.h"
 
+#include <set>
+#include <string>
 #include <windows.h>
 
 #include "base/values.h"
@@ -12,22 +14,20 @@
                                       NEWTEXTMETRICEXW *physical_font,
                                       DWORD font_type,
                                       LPARAM lparam) {
-  ListValue* font_list = reinterpret_cast<ListValue*>(lparam);
-  if (font_list) {
+  std::set<std::wstring>* font_names =
+      reinterpret_cast<std::set<std::wstring>*>(lparam);
+  if (font_names) {
     const LOGFONTW& lf = logical_font->elfLogFont;
     if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@') {
-      ListValue* font_item = new ListValue();
       std::wstring face_name(lf.lfFaceName);
-      font_item->Append(Value::CreateStringValue(face_name));
-      font_item->Append(Value::CreateStringValue(face_name));
-      font_list->Append(font_item);
+      font_names->insert(face_name);
     }
   }
   return 1;
 }
 
 ListValue* FontSettingsUtilities::GetFontsList() {
-  ListValue* font_list = new ListValue;
+  std::set<std::wstring> font_names;
 
   LOGFONTW logfont;
   memset(&logfont, 0, sizeof(logfont));
@@ -35,9 +35,17 @@
 
   HDC hdc = ::GetDC(NULL);
   ::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontFamExProc,
-                        (LPARAM)font_list, 0);
+                        (LPARAM)&font_names, 0);
   ::ReleaseDC(NULL, hdc);
 
+  ListValue* font_list = new ListValue;
+  std::set<std::wstring>::iterator iter;
+  for (iter = font_names.begin(); iter != font_names.end(); iter++) {
+    ListValue* font_item = new ListValue();
+    font_item->Append(Value::CreateStringValue(*iter));
+    font_item->Append(Value::CreateStringValue(*iter));
+    font_list->Append(font_item);
+  }
   return font_list;
 }
 
diff --git a/chrome/browser/dom_ui/options/import_data_handler.cc b/chrome/browser/dom_ui/options/import_data_handler.cc
index 03d7716..3931d09 100644
--- a/chrome/browser/dom_ui/options/import_data_handler.cc
+++ b/chrome/browser/dom_ui/options/import_data_handler.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/import_data_handler.h"
 
-#include "app/l10n_util.h"
+#include <string>
+
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/scoped_ptr.h"
@@ -14,16 +15,19 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "chrome/browser/importer/importer_data_types.h"
+#include "ui/base/l10n/l10n_util.h"
 
 ImportDataHandler::ImportDataHandler() : importer_host_(NULL) {
 }
 
 ImportDataHandler::~ImportDataHandler() {
+  if (importer_list_)
+    importer_list_->SetObserver(NULL);
+
   if (importer_host_)
     importer_host_->SetObserver(NULL);
 }
@@ -31,8 +35,8 @@
 void ImportDataHandler::GetLocalizedValues(
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
-  localized_strings->SetString("importDataTitle",
-      l10n_util::GetStringUTF16(IDS_IMPORT_SETTINGS_TITLE));
+  RegisterTitle(localized_strings, "importDataOverlay",
+                IDS_IMPORT_SETTINGS_TITLE);
   localized_strings->SetString("importFromLabel",
       l10n_util::GetStringUTF16(IDS_IMPORT_FROM_LABEL));
   localized_strings->SetString("importLoading",
@@ -59,7 +63,7 @@
 }
 
 void ImportDataHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "importData", NewCallback(this, &ImportDataHandler::ImportData));
 }
 
@@ -94,7 +98,7 @@
   uint16 import_services = (selected_items & supported_items);
   if (import_services) {
     FundamentalValue state(true);
-    dom_ui_->CallJavascriptFunction(
+    web_ui_->CallJavascriptFunction(
         L"ImportDataOverlay.setImportingState", state);
 
     // TODO(csilv): Out-of-process import has only been qualified on MacOS X,
@@ -102,12 +106,12 @@
     // conditional logic once oop import is qualified for Linux/Windows.
     // http://crbug.com/22142
 #if defined(OS_MACOSX)
-    importer_host_ = new ExternalProcessImporterHost(this);
+    importer_host_ = new ExternalProcessImporterHost;
 #else
-    importer_host_ = new ImporterHost(this);
+    importer_host_ = new ImporterHost;
 #endif
     importer_host_->SetObserver(this);
-    Profile* profile = dom_ui_->GetProfile();
+    Profile* profile = web_ui_->GetProfile();
     importer_host_->StartImportSettings(source_profile, profile,
                                         import_services,
                                         new ProfileWriter(profile), false);
@@ -132,7 +136,7 @@
   importer_host_->SetObserver(NULL);
   importer_host_ = NULL;
 
-  dom_ui_->CallJavascriptFunction(L"ImportDataOverlay.dismiss");
+  web_ui_->CallJavascriptFunction(L"ImportDataOverlay.dismiss");
 }
 
 void ImportDataHandler::SourceProfilesLoaded() {
@@ -159,7 +163,7 @@
     browser_profiles.Append(browser_profile);
   }
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"options.ImportDataOverlay.updateSupportedBrowsers",
       browser_profiles);
 }
diff --git a/chrome/browser/dom_ui/options/import_data_handler.h b/chrome/browser/dom_ui/options/import_data_handler.h
index 8f4ed61..bc50ad1 100644
--- a/chrome/browser/dom_ui/options/import_data_handler.h
+++ b/chrome/browser/dom_ui/options/import_data_handler.h
@@ -21,7 +21,7 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void Initialize();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
  private:
@@ -39,7 +39,7 @@
   scoped_refptr<ImporterList> importer_list_;
 
   // If non-null it means importing is in progress. ImporterHost takes care
-  // of deleting itself when done import.
+  // of deleting itself when import is complete.
   ImporterHost* importer_host_;  // weak
 
   DISALLOW_COPY_AND_ASSIGN(ImportDataHandler);
diff --git a/chrome/browser/dom_ui/options/language_options_handler.cc b/chrome/browser/dom_ui/options/language_options_handler.cc
new file mode 100644
index 0000000..f3119d5
--- /dev/null
+++ b/chrome/browser/dom_ui/options/language_options_handler.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/options/language_options_handler.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+LanguageOptionsHandler::LanguageOptionsHandler() {
+}
+
+LanguageOptionsHandler::~LanguageOptionsHandler() {
+}
+
+void LanguageOptionsHandler::GetLocalizedValues(
+    DictionaryValue* localized_strings) {
+  LanguageOptionsHandlerCommon::GetLocalizedValues(localized_strings);
+
+  localized_strings->SetString("restart_button",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON));
+  localized_strings->Set("languageList", GetLanguageList());
+}
+
+void LanguageOptionsHandler::RegisterMessages() {
+  LanguageOptionsHandlerCommon::RegisterMessages();
+
+  web_ui_->RegisterMessageCallback("uiLanguageRestart",
+      NewCallback(this, &LanguageOptionsHandler::RestartCallback));
+}
+
+ListValue* LanguageOptionsHandler::GetLanguageList() {
+  // Collect the language codes from the supported accept-languages.
+  const std::string app_locale = g_browser_process->GetApplicationLocale();
+  std::vector<std::string> language_codes;
+  l10n_util::GetAcceptLanguagesForLocale(app_locale, &language_codes);
+
+  // Map of display name -> {language code, native_display_name}.
+  // In theory, we should be able to create a map that is sorted by
+  // display names using ICU comparator, but doing it is hard, thus we'll
+  // use an auxiliary vector to achieve the same result.
+  typedef std::pair<std::string, string16> LanguagePair;
+  typedef std::map<string16, LanguagePair> LanguageMap;
+  LanguageMap language_map;
+  // The auxiliary vector mentioned above.
+  std::vector<string16> display_names;
+
+  // Build the list of display names, and build the language map.
+  for (size_t i = 0; i < language_codes.size(); ++i) {
+    const string16 display_name =
+        l10n_util::GetDisplayNameForLocale(language_codes[i], app_locale, true);
+    const string16 native_display_name =
+        l10n_util::GetDisplayNameForLocale(language_codes[i], language_codes[i],
+                                           true);
+    display_names.push_back(display_name);
+    language_map[display_name] =
+        std::make_pair(language_codes[i], native_display_name);
+  }
+  DCHECK_EQ(display_names.size(), language_map.size());
+
+  // Sort display names using locale specific sorter.
+  l10n_util::SortStrings16(app_locale, &display_names);
+
+  // Build the language list from the language map.
+  ListValue* language_list = new ListValue();
+  for (size_t i = 0; i < display_names.size(); ++i) {
+    const LanguagePair& pair = language_map[display_names[i]];
+    DictionaryValue* dictionary = new DictionaryValue();
+    dictionary->SetString("code",  pair.first);
+    dictionary->SetString("displayName", display_names[i]);
+    dictionary->SetString("nativeDisplayName", pair.second);
+    language_list->Append(dictionary);
+  }
+
+  return language_list;
+}
+
+string16 LanguageOptionsHandler::GetProductName() {
+  return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
+}
+
+void LanguageOptionsHandler::SetApplicationLocale(std::string language_code) {
+  PrefService* pref_service = g_browser_process->local_state();
+  pref_service->SetString(prefs::kApplicationLocale, language_code);
+}
+
+void LanguageOptionsHandler::RestartCallback(const ListValue* args) {
+  UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Restart"));
+
+  // Set the flag to restore state after the restart.
+  PrefService* pref_service = g_browser_process->local_state();
+  pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
+  BrowserList::CloseAllBrowsersAndExit();
+}
diff --git a/chrome/browser/dom_ui/options/language_options_handler.h b/chrome/browser/dom_ui/options/language_options_handler.h
new file mode 100644
index 0000000..1f1181c
--- /dev/null
+++ b/chrome/browser/dom_ui/options/language_options_handler.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOM_UI_OPTIONS_LANGUAGE_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_DOM_UI_OPTIONS_LANGUAGE_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/dom_ui/options/language_options_handler_common.h"
+
+// Language options UI page handler for non-Chrome OS platforms.  For Chrome OS,
+// see chromeos::CrosLanguageOptionsHandler.
+class LanguageOptionsHandler : public LanguageOptionsHandlerCommon {
+ public:
+  LanguageOptionsHandler();
+  virtual ~LanguageOptionsHandler();
+
+  // OptionsUIHandler implementation.
+  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
+
+  // WebUIMessageHandler implementation.
+  virtual void RegisterMessages();
+
+  // The following static method is public for ease of testing.
+
+  // Gets the list of languages from the given input descriptors.
+  // The return value will look like:
+  // [{'code': 'fi', 'displayName': 'Finnish', 'nativeDisplayName': 'suomi'},
+  //  ...]
+  static ListValue* GetLanguageList();
+
+ private:
+  // LanguageOptionsHandlerCommon implementation.
+  virtual string16 GetProductName();
+  virtual void SetApplicationLocale(std::string language_code);
+
+  // Called when the restart button is clicked.
+  void RestartCallback(const ListValue* args);
+
+  DISALLOW_COPY_AND_ASSIGN(LanguageOptionsHandler);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_OPTIONS_LANGUAGE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/dom_ui/options/language_options_handler_common.cc b/chrome/browser/dom_ui/options/language_options_handler_common.cc
new file mode 100644
index 0000000..e2e4403
--- /dev/null
+++ b/chrome/browser/dom_ui/options/language_options_handler_common.cc
@@ -0,0 +1,164 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/options/language_options_handler_common.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/spellcheck_common.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+LanguageOptionsHandlerCommon::LanguageOptionsHandlerCommon() {
+}
+
+LanguageOptionsHandlerCommon::~LanguageOptionsHandlerCommon() {
+}
+
+void LanguageOptionsHandlerCommon::GetLocalizedValues(
+    DictionaryValue* localized_strings) {
+  DCHECK(localized_strings);
+  string16 product_name = GetProductName();
+  RegisterTitle(localized_strings, "languagePage",
+                IDS_OPTIONS_SETTINGS_LANGUAGES_DIALOG_TITLE);
+  localized_strings->SetString("add_button",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_BUTTON));
+  localized_strings->SetString("languages",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES));
+  localized_strings->SetString("please_add_another_language",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_LANGUAGE));
+  localized_strings->SetString("remove_button",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON));
+  localized_strings->SetString("add_language_instructions",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_INSTRUCTIONS));
+  localized_strings->SetString("cannot_be_displayed_in_this_language",
+      l10n_util::GetStringFUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE,
+          product_name));
+  localized_strings->SetString("is_displayed_in_this_language",
+      l10n_util::GetStringFUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
+          product_name));
+  localized_strings->SetString("display_in_this_language",
+      l10n_util::GetStringFUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
+          product_name));
+  localized_strings->SetString("this_language_is_currently_in_use",
+      l10n_util::GetStringFUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_THIS_LANGUAGE_IS_CURRENTLY_IN_USE,
+          product_name));
+  localized_strings->SetString("use_this_for_spell_checking",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_USE_THIS_FOR_SPELL_CHECKING));
+  localized_strings->SetString("cannot_be_used_for_spell_checking",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_CANNOT_BE_USED_FOR_SPELL_CHECKING));
+  localized_strings->SetString("is_used_for_spell_checking",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_IS_USED_FOR_SPELL_CHECKING));
+  localized_strings->SetString("restart_required",
+          l10n_util::GetStringUTF16(IDS_OPTIONS_RELAUNCH_REQUIRED));
+  localized_strings->SetString("enable_spell_check",
+          l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SPELLCHECK));
+  localized_strings->SetString("enable_auto_spell_correction",
+          l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_AUTO_SPELL_CORRECTION));
+  localized_strings->SetString("add_language_title",
+          l10n_util::GetStringUTF16(IDS_OPTIONS_LANGUAGES_ADD_TITLE));
+  localized_strings->SetString("add_language_select_label",
+          l10n_util::GetStringUTF16(IDS_OPTIONS_LANGUAGES_ADD_SELECT_LABEL));
+  localized_strings->SetString("restart_button",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON));
+
+  // The following are resources, rather than local strings.
+  localized_strings->SetString("currentUiLanguageCode",
+                               g_browser_process->GetApplicationLocale());
+  localized_strings->Set("spellCheckLanguageCodeSet",
+                         GetSpellCheckLanguageCodeSet());
+  localized_strings->Set("uiLanguageCodeSet", GetUILanguageCodeSet());
+
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  bool experimental_spell_check_features =
+      command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures);
+  localized_strings->SetBoolean("experimentalSpellCheckFeatures",
+                                experimental_spell_check_features);
+}
+
+void LanguageOptionsHandlerCommon::RegisterMessages() {
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("languageOptionsOpen",
+      NewCallback(
+          this,
+          &LanguageOptionsHandlerCommon::LanguageOptionsOpenCallback));
+  web_ui_->RegisterMessageCallback("spellCheckLanguageChange",
+      NewCallback(
+          this,
+          &LanguageOptionsHandlerCommon::SpellCheckLanguageChangeCallback));
+  web_ui_->RegisterMessageCallback("uiLanguageChange",
+      NewCallback(
+          this,
+          &LanguageOptionsHandlerCommon::UiLanguageChangeCallback));
+}
+
+DictionaryValue* LanguageOptionsHandlerCommon::GetUILanguageCodeSet() {
+  DictionaryValue* dictionary = new DictionaryValue();
+  const std::vector<std::string>& available_locales =
+      l10n_util::GetAvailableLocales();
+  for (size_t i = 0; i < available_locales.size(); ++i) {
+    dictionary->SetBoolean(available_locales[i], true);
+  }
+  return dictionary;
+}
+
+DictionaryValue* LanguageOptionsHandlerCommon::GetSpellCheckLanguageCodeSet() {
+  DictionaryValue* dictionary = new DictionaryValue();
+  std::vector<std::string> spell_check_languages;
+  SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
+  for (size_t i = 0; i < spell_check_languages.size(); ++i) {
+    dictionary->SetBoolean(spell_check_languages[i], true);
+  }
+  return dictionary;
+}
+
+void LanguageOptionsHandlerCommon::LanguageOptionsOpenCallback(
+    const ListValue* args) {
+  UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Open"));
+}
+
+void LanguageOptionsHandlerCommon::UiLanguageChangeCallback(
+    const ListValue* args) {
+  const std::string language_code = WideToASCII(ExtractStringValue(args));
+  CHECK(!language_code.empty());
+  const std::string action = StringPrintf(
+      "LanguageOptions_UiLanguageChange_%s", language_code.c_str());
+  UserMetrics::RecordComputedAction(action);
+  SetApplicationLocale(language_code);
+    web_ui_->CallJavascriptFunction(
+      L"options.LanguageOptions.uiLanguageSaved");
+}
+
+void LanguageOptionsHandlerCommon::SpellCheckLanguageChangeCallback(
+    const ListValue* args) {
+  const std::string language_code = WideToASCII(ExtractStringValue(args));
+  CHECK(!language_code.empty());
+  const std::string action = StringPrintf(
+      "LanguageOptions_SpellCheckLanguageChange_%s", language_code.c_str());
+  UserMetrics::RecordComputedAction(action);
+}
diff --git a/chrome/browser/dom_ui/options/language_options_handler_common.h b/chrome/browser/dom_ui/options/language_options_handler_common.h
new file mode 100644
index 0000000..9871ce4
--- /dev/null
+++ b/chrome/browser/dom_ui/options/language_options_handler_common.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_OPTIONS_LANGUAGE_OPTIONS_HANDLER_COMMON_H_
+#define CHROME_BROWSER_DOM_UI_OPTIONS_LANGUAGE_OPTIONS_HANDLER_COMMON_H_
+#pragma once
+
+#include "chrome/browser/dom_ui/options/options_ui.h"
+
+class DictionaryValue;
+class ListValue;
+
+// The base class for language options page UI handlers.  This class has code
+// common to the Chrome OS and non-Chrome OS implementation of the handler.
+class LanguageOptionsHandlerCommon : public OptionsPageUIHandler {
+ public:
+  LanguageOptionsHandlerCommon();
+  virtual ~LanguageOptionsHandlerCommon();
+
+  // OptionsUIHandler implementation.
+  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
+
+  // DOMMessageHandler implementation.
+  virtual void RegisterMessages();
+
+  // The following static methods are public for ease of testing.
+
+  // Gets the set of language codes that can be used as UI language.
+  // The return value will look like:
+  // {'en-US': true, 'fi': true, 'fr': true, ...}
+  //
+  // Note that true in values does not mean anything. We just use the
+  // dictionary as a set.
+  static DictionaryValue* GetUILanguageCodeSet();
+
+  // Gets the set of language codes that can be used for spellchecking.
+  // The return value will look like:
+  // {'en-US': true, 'fi': true, 'fr': true, ...}
+  //
+  // Note that true in values does not mean anything. We just use the
+  // dictionary as a set.
+  static DictionaryValue* GetSpellCheckLanguageCodeSet();
+
+ private:
+  // Returns the name of the product (ex. "Chrome" or "Chrome OS").
+  virtual string16 GetProductName() = 0;
+
+  // Sets the application locale.
+  virtual void SetApplicationLocale(std::string language_code) = 0;
+
+  // Called when the language options is opened.
+  void LanguageOptionsOpenCallback(const ListValue* args);
+
+  // Called when the UI language is changed.
+  // |args| will contain the language code as string (ex. "fr").
+  void UiLanguageChangeCallback(const ListValue* args);
+
+  // Called when the spell check language is changed.
+  // |args| will contain the language code as string (ex. "fr").
+  void SpellCheckLanguageChangeCallback(const ListValue* args);
+
+  DISALLOW_COPY_AND_ASSIGN(LanguageOptionsHandlerCommon);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_OPTIONS_LANGUAGE_OPTIONS_HANDLER_COMMON_H_
diff --git a/chrome/browser/dom_ui/options/language_options_handler_unittest.cc b/chrome/browser/dom_ui/options/language_options_handler_unittest.cc
new file mode 100644
index 0000000..425c249
--- /dev/null
+++ b/chrome/browser/dom_ui/options/language_options_handler_unittest.cc
@@ -0,0 +1,179 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/options/language_options_handler.h"
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/input_method_library.h"
+#include "chrome/browser/chromeos/dom_ui/cros_language_options_handler.h"
+#endif  // defined(OS_CHROMEOS)
+
+#if defined(OS_CHROMEOS)
+static chromeos::InputMethodDescriptors CreateInputMethodDescriptors() {
+  chromeos::InputMethodDescriptors descriptors;
+  descriptors.push_back(
+      chromeos::InputMethodDescriptor("xkb:us::eng", "USA", "us", "eng"));
+  descriptors.push_back(
+      chromeos::InputMethodDescriptor("xkb:fr::fra", "France", "fr", "fra"));
+  descriptors.push_back(
+      chromeos::InputMethodDescriptor("xkb:be::fra", "Belgium", "be", "fr"));
+  descriptors.push_back(
+      chromeos::InputMethodDescriptor("mozc", "Mozc (US keyboard layout)", "us",
+                                      "ja"));
+  return descriptors;
+}
+
+TEST(LanguageOptionsHandlerTest, GetInputMethodList) {
+  // Use the stub libcros. The object will take care of the cleanup.
+  chromeos::ScopedStubCrosEnabler stub_cros_enabler;
+
+  // Reset the library implementation so it will be initialized
+  // again. Otherwise, non-stub implementation can be reused, if it's
+  // already initialized elsewhere, which results in a crash.
+  chromeos::CrosLibrary::Get()->GetTestApi()->SetInputMethodLibrary(NULL,
+                                                                    false);
+
+  chromeos::InputMethodDescriptors descriptors = CreateInputMethodDescriptors();
+  scoped_ptr<ListValue> list(
+      chromeos::CrosLanguageOptionsHandler::GetInputMethodList(descriptors));
+  ASSERT_EQ(4U, list->GetSize());
+
+  DictionaryValue* entry = NULL;
+  DictionaryValue *language_code_set = NULL;
+  std::string input_method_id;
+  std::string display_name;
+  std::string language_code;
+
+  // As shown below, the list should be input method ids should appear in
+  // the same order of the descriptors.
+  ASSERT_TRUE(list->GetDictionary(0, &entry));
+  ASSERT_TRUE(entry->GetString("id", &input_method_id));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+  EXPECT_EQ("xkb:us::eng", input_method_id);
+  // Commented out as it depends on translation in generated_resources.grd
+  // (i.e. makes the test fragile).
+  // EXPECT_EQ("English (USA) keyboard layout", display_name);
+  ASSERT_TRUE(language_code_set->HasKey("en-US"));
+  ASSERT_TRUE(language_code_set->HasKey("id"));  // From kExtraLanguages.
+  ASSERT_TRUE(language_code_set->HasKey("fil"));  // From kExtraLanguages.
+
+  ASSERT_TRUE(list->GetDictionary(1, &entry));
+  ASSERT_TRUE(entry->GetString("id", &input_method_id));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+  EXPECT_EQ("xkb:fr::fra", input_method_id);
+  // Commented out. See above.
+  // EXPECT_EQ("French keyboard layout", display_name);
+  ASSERT_TRUE(language_code_set->HasKey("fr"));
+
+  ASSERT_TRUE(list->GetDictionary(2, &entry));
+  ASSERT_TRUE(entry->GetString("id", &input_method_id));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+  EXPECT_EQ("xkb:be::fra", input_method_id);
+  // Commented out. See above.
+  // EXPECT_EQ("Belgian keyboard layout", display_name);
+  ASSERT_TRUE(language_code_set->HasKey("fr"));
+
+  ASSERT_TRUE(list->GetDictionary(3, &entry));
+  ASSERT_TRUE(entry->GetString("id", &input_method_id));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+  EXPECT_EQ("mozc", input_method_id);
+  // Commented out. See above.
+  // EXPECT_EQ("Japanese input method (for US keyboard)", display_name);
+  ASSERT_TRUE(language_code_set->HasKey("ja"));
+}
+
+TEST(LanguageOptionsHandlerTest, GetLanguageList) {
+  chromeos::InputMethodDescriptors descriptors = CreateInputMethodDescriptors();
+  scoped_ptr<ListValue> list(
+      chromeos::CrosLanguageOptionsHandler::GetLanguageList(descriptors));
+  ASSERT_EQ(6U, list->GetSize());
+
+  DictionaryValue* entry = NULL;
+  std::string language_code;
+  std::string display_name;
+  std::string native_display_name;
+
+  // As shown below, the list should be sorted by the display names,
+  // and these names should not have duplicates.
+  ASSERT_TRUE(list->GetDictionary(0, &entry));
+  ASSERT_TRUE(entry->GetString("code", &language_code));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+  EXPECT_EQ("en-US", language_code);
+  EXPECT_EQ("English (United States)", display_name);
+  EXPECT_EQ("English (United States)", native_display_name);
+
+  // This comes from kExtraLanguages.
+  ASSERT_TRUE(list->GetDictionary(1, &entry));
+  ASSERT_TRUE(entry->GetString("code", &language_code));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+  EXPECT_EQ("fil", language_code);
+  EXPECT_EQ("Filipino", display_name);
+  EXPECT_EQ("Filipino", native_display_name);
+
+  ASSERT_TRUE(list->GetDictionary(2, &entry));
+  ASSERT_TRUE(entry->GetString("code", &language_code));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+  EXPECT_EQ("fr", language_code);
+  EXPECT_EQ("French", display_name);
+  EXPECT_EQ("fran\u00E7ais", native_display_name);
+
+  // This comes from kExtraLanguages.
+  ASSERT_TRUE(list->GetDictionary(3, &entry));
+  ASSERT_TRUE(entry->GetString("code", &language_code));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+  EXPECT_EQ("id", language_code);
+  EXPECT_EQ("Indonesian", display_name);
+  EXPECT_EQ("Bahasa Indonesia", native_display_name);
+
+  ASSERT_TRUE(list->GetDictionary(4, &entry));
+  ASSERT_TRUE(entry->GetString("code", &language_code));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+  EXPECT_EQ("ja", language_code);
+  EXPECT_EQ("Japanese", display_name);
+  EXPECT_EQ("\u65E5\u672C\u8A9E", native_display_name);
+
+  // This comes from kExtraLanguages.
+  ASSERT_TRUE(list->GetDictionary(5, &entry));
+  ASSERT_TRUE(entry->GetString("code", &language_code));
+  ASSERT_TRUE(entry->GetString("displayName", &display_name));
+  ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+  EXPECT_EQ("es-419", language_code);
+  EXPECT_EQ("Spanish (Latin America and the Caribbean)", display_name);
+  EXPECT_EQ("espa\u00F1ol (Latinoam\u00E9rica y el Caribe)",
+            native_display_name);
+}
+#endif  // defined(OS_CHROMEOS)
+
+#if !defined(OS_MACOSX)
+TEST(LanguageOptionsHandlerTest, GetUILanguageCodeSet) {
+  scoped_ptr<DictionaryValue> dictionary(
+      LanguageOptionsHandler::GetUILanguageCodeSet());
+  EXPECT_TRUE(dictionary->HasKey("en-US"));
+  // Note that we don't test a false case, as such an expectation will
+  // fail when we add support for the language.
+  // EXPECT_FALSE(dictionary->HasKey("no"));
+}
+#endif  // !defined(OS_MACOSX)
+
+TEST(LanguageOptionsHandlerTest, GetSpellCheckLanguageCodeSet) {
+  scoped_ptr<DictionaryValue> dictionary(
+      LanguageOptionsHandler::GetSpellCheckLanguageCodeSet());
+  EXPECT_TRUE(dictionary->HasKey("en-US"));
+}
diff --git a/chrome/browser/dom_ui/options/options_managed_banner_handler.cc b/chrome/browser/dom_ui/options/options_managed_banner_handler.cc
index 5f01e4f..e28a731 100644
--- a/chrome/browser/dom_ui/options/options_managed_banner_handler.cc
+++ b/chrome/browser/dom_ui/options/options_managed_banner_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,13 @@
 
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/profiles/profile.h"
 
 OptionsManagedBannerHandler::OptionsManagedBannerHandler(
-    DOMUI* dom_ui, const string16& page_name, OptionsPage page)
-    : policy::ManagedPrefsBannerBase(dom_ui->GetProfile()->GetPrefs(), page),
-      dom_ui_(dom_ui), page_name_(page_name), page_(page) {
+    WebUI* web_ui, const string16& page_name, OptionsPage page)
+    : policy::ManagedPrefsBannerBase(web_ui->GetProfile()->GetPrefs(), page),
+      web_ui_(web_ui), page_name_(page_name), page_(page) {
   // Initialize the visibility state of the banner.
   SetupBannerVisibilty();
 }
@@ -34,5 +34,5 @@
   FundamentalValue visibility(DetermineVisibility());
 
   // Set the managed state in the javascript handler.
-  dom_ui_->CallJavascriptFunction(UTF16ToWideHack(script), visibility);
+  web_ui_->CallJavascriptFunction(UTF16ToWideHack(script), visibility);
 }
diff --git a/chrome/browser/dom_ui/options/options_managed_banner_handler.h b/chrome/browser/dom_ui/options/options_managed_banner_handler.h
index 9cfc5e9..49047df 100644
--- a/chrome/browser/dom_ui/options/options_managed_banner_handler.h
+++ b/chrome/browser/dom_ui/options/options_managed_banner_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,14 +10,14 @@
 #include "chrome/browser/policy/managed_prefs_banner_base.h"
 #include "chrome/browser/ui/options/options_window.h"
 
-class DOMUI;
+class WebUI;
 
 // Managed options banner handler.
 // Controls the display of a banner if an options panel contains options
 // that are under administator control.
 class OptionsManagedBannerHandler : public policy::ManagedPrefsBannerBase {
  public:
-  OptionsManagedBannerHandler(DOMUI* dom_ui, const string16& page_name,
+  OptionsManagedBannerHandler(WebUI* web_ui, const string16& page_name,
                               OptionsPage page);
   virtual ~OptionsManagedBannerHandler();
 
@@ -29,7 +29,7 @@
   // Set the managed options banner to be visible or invisible.
   void SetupBannerVisibilty();
 
-  DOMUI* dom_ui_;  // weak reference to the dom-ui.
+  WebUI* web_ui_;  // weak reference to the WebUI.
   string16 page_name_;  // current options page name.
   OptionsPage page_;  // current options page value.
 
diff --git a/chrome/browser/dom_ui/options/options_ui.cc b/chrome/browser/dom_ui/options/options_ui.cc
index 932de34..e4565e6 100644
--- a/chrome/browser/dom_ui/options/options_ui.cc
+++ b/chrome/browser/dom_ui/options/options_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <vector>
 
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
@@ -19,7 +18,6 @@
 #include "base/values.h"
 #include "chrome/browser/browser_about_handler.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
 #include "chrome/browser/dom_ui/options/about_page_handler.h"
 #include "chrome/browser/dom_ui/options/add_startup_page_handler.h"
 #include "chrome/browser/dom_ui/options/advanced_options_handler.h"
@@ -29,17 +27,17 @@
 #include "chrome/browser/dom_ui/options/content_settings_handler.h"
 #include "chrome/browser/dom_ui/options/cookies_view_handler.h"
 #include "chrome/browser/dom_ui/options/core_options_handler.h"
+#include "chrome/browser/dom_ui/options/dom_options_util.h"
 #include "chrome/browser/dom_ui/options/font_settings_handler.h"
 #include "chrome/browser/dom_ui/options/import_data_handler.h"
+#include "chrome/browser/dom_ui/options/language_options_handler.h"
 #include "chrome/browser/dom_ui/options/password_manager_handler.h"
 #include "chrome/browser/dom_ui/options/personal_options_handler.h"
 #include "chrome/browser/dom_ui/options/search_engine_manager_handler.h"
-#include "chrome/browser/dom_ui/options/startup_page_manager_handler.h"
 #include "chrome/browser/dom_ui/options/stop_syncing_handler.h"
-#include "chrome/browser/dom_ui/options/sync_options_handler.h"
+#include "chrome/browser/dom_ui/web_ui_theme_source.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
@@ -53,17 +51,17 @@
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
 #include "net/base/escape.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/dom_ui/accounts_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h"
-#include "chrome/browser/chromeos/dom_ui/cros_personal_options_handler.h"
+#include "chrome/browser/chromeos/dom_ui/cros_language_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/internet_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/language_chewing_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.h"
 #include "chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/language_mozc_options_handler.h"
-#include "chrome/browser/chromeos/dom_ui/language_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/language_pinyin_options_handler.h"
 #include "chrome/browser/chromeos/dom_ui/proxy_handler.h"
 #include "chrome/browser/chromeos/dom_ui/stats_options_handler.h"
@@ -128,7 +126,31 @@
 
 void OptionsPageUIHandler::UserMetricsRecordAction(
     const UserMetricsAction& action) {
-  UserMetrics::RecordAction(action, dom_ui_->GetProfile());
+  UserMetrics::RecordAction(action, web_ui_->GetProfile());
+}
+
+// static
+void OptionsPageUIHandler::RegisterStrings(
+    DictionaryValue* localized_strings,
+    const OptionsStringResource* resources,
+    size_t length) {
+  for (size_t i = 0; i < length; ++i) {
+    const string16& value = l10n_util::GetStringUTF16(resources[i].id);
+    localized_strings->SetString(
+        resources[i].name,
+        resources[i].strip_colon ? dom_options_util::StripColon(value) : value);
+  }
+}
+
+void OptionsPageUIHandler::RegisterTitle(DictionaryValue* localized_strings,
+                                         const std::string& variable_name,
+                                         int title_id) {
+  localized_strings->SetString(variable_name,
+      l10n_util::GetStringUTF16(title_id));
+  localized_strings->SetString(variable_name + "TabTitle",
+      l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE,
+          l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE),
+          l10n_util::GetStringUTF16(title_id)));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -137,7 +159,8 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-OptionsUI::OptionsUI(TabContents* contents) : DOMUI(contents) {
+OptionsUI::OptionsUI(TabContents* contents)
+    : WebUI(contents), initialized_handlers_(false) {
   DictionaryValue* localized_strings = new DictionaryValue();
 
 #if defined(OS_CHROMEOS)
@@ -155,13 +178,17 @@
   AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
   AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
   AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
+#if defined(OS_CHROMEOS)
+  AddOptionsPageUIHandler(localized_strings,
+                          new chromeos::CrosLanguageOptionsHandler());
+#else
+  AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler());
+#endif
   AddOptionsPageUIHandler(localized_strings, new PasswordManagerHandler());
   AddOptionsPageUIHandler(localized_strings, new PersonalOptionsHandler());
   AddOptionsPageUIHandler(localized_strings, new SearchEngineManagerHandler());
-  AddOptionsPageUIHandler(localized_strings, new StartupPageManagerHandler());
   AddOptionsPageUIHandler(localized_strings, new ImportDataHandler());
   AddOptionsPageUIHandler(localized_strings, new StopSyncingHandler());
-  AddOptionsPageUIHandler(localized_strings, new SyncOptionsHandler());
 #if defined(OS_CHROMEOS)
   AddOptionsPageUIHandler(localized_strings, new AboutPageHandler());
   AddOptionsPageUIHandler(localized_strings,
@@ -176,15 +203,11 @@
   AddOptionsPageUIHandler(localized_strings,
                           new chromeos::LanguageMozcOptionsHandler());
   AddOptionsPageUIHandler(localized_strings,
-                          new chromeos::LanguageOptionsHandler());
-  AddOptionsPageUIHandler(localized_strings,
                           new chromeos::LanguagePinyinOptionsHandler());
   AddOptionsPageUIHandler(localized_strings, new chromeos::ProxyHandler());
   AddOptionsPageUIHandler(localized_strings,
                           new chromeos::StatsOptionsHandler());
   AddOptionsPageUIHandler(localized_strings, new SystemOptionsHandler());
-  AddOptionsPageUIHandler(localized_strings,
-                           new chromeos::CrosPersonalOptionsHandler());
 #endif
 #if defined(USE_NSS)
   AddOptionsPageUIHandler(localized_strings, new CertificateManagerHandler());
@@ -195,31 +218,21 @@
       new OptionsUIHTMLSource(localized_strings);
 
   // Set up the chrome://settings/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 
   // Set up the chrome://theme/ source.
-  DOMUIThemeSource* theme = new DOMUIThemeSource(GetProfile());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(theme)));
+  WebUIThemeSource* theme = new WebUIThemeSource(contents->profile());
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(theme);
 
   // Initialize the chrome://about/ source in case the user clicks the credits
   // link.
-  InitializeAboutDataSource();
+  InitializeAboutDataSource(contents->profile());
 }
 
 OptionsUI::~OptionsUI() {
   // Uninitialize all registered handlers. The base class owns them and it will
-  // eventually delete them.
-  for (std::vector<DOMMessageHandler*>::iterator iter = handlers_.begin();
+  // eventually delete them. Skip over the generic handler.
+  for (std::vector<WebUIMessageHandler*>::iterator iter = handlers_.begin() + 1;
        iter != handlers_.end();
        ++iter) {
     static_cast<OptionsPageUIHandler*>(*iter)->Uninitialize();
@@ -237,8 +250,8 @@
   command_line_string = CommandLine::ForCurrentProcess()->command_line_string();
 #endif
 
-  render_view_host->SetDOMUIProperty("commandLineString", command_line_string);
-  DOMUI::RenderViewCreated(render_view_host);
+  render_view_host->SetWebUIProperty("commandLineString", command_line_string);
+  WebUI::RenderViewCreated(render_view_host);
 }
 
 void OptionsUI::DidBecomeActiveForReusedRenderView() {
@@ -250,7 +263,7 @@
   // initialized).
   CallJavascriptFunction(L"OptionsPage.reinitializeCore");
 
-  DOMUI::DidBecomeActiveForReusedRenderView();
+  WebUI::DidBecomeActiveForReusedRenderView();
 }
 
 // static
@@ -260,10 +273,19 @@
 }
 
 void OptionsUI::InitializeHandlers() {
-  DCHECK(!GetProfile()->IsOffTheRecord());
+  DCHECK(!GetProfile()->IsOffTheRecord() || Profile::IsGuestSession());
 
-  std::vector<DOMMessageHandler*>::iterator iter;
-  for (iter = handlers_.begin(); iter != handlers_.end(); ++iter) {
+  // The reinitialize call from DidBecomeActiveForReusedRenderView end up being
+  // delivered after a new web page DOM has been brought up in an existing
+  // renderer (due to IPC delays), causing this method to be called twice. If
+  // that happens, ignore the second call.
+  if (initialized_handlers_)
+    return;
+  initialized_handlers_ = true;
+
+  std::vector<WebUIMessageHandler*>::iterator iter;
+  // Skip over the generic handler.
+  for (iter = handlers_.begin() + 1; iter != handlers_.end(); ++iter) {
     (static_cast<OptionsPageUIHandler*>(*iter))->Initialize();
   }
 }
diff --git a/chrome/browser/dom_ui/options/options_ui.h b/chrome/browser/dom_ui/options/options_ui.h
index ad1007d..bcfd54e 100644
--- a/chrome/browser/dom_ui/options/options_ui.h
+++ b/chrome/browser/dom_ui/options/options_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_type.h"
@@ -40,7 +40,7 @@
 };
 
 // The base class handler of Javascript messages of options pages.
-class OptionsPageUIHandler : public DOMMessageHandler,
+class OptionsPageUIHandler : public WebUIMessageHandler,
                              public NotificationObserver {
  public:
   OptionsPageUIHandler();
@@ -53,12 +53,13 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings) = 0;
 
   // Initialize the page.  Called once the DOM is available for manipulation.
+  // This will be called only once.
   virtual void Initialize() {}
 
   // Uninitializes the page.  Called just before the object is destructed.
   virtual void Uninitialize() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages() {}
 
   // NotificationObserver implementation.
@@ -69,13 +70,32 @@
   void UserMetricsRecordAction(const UserMetricsAction& action);
 
  protected:
+  struct OptionsStringResource {
+    // The name of the resource in templateData.
+    const char* name;
+    // The .grd ID for the resource (IDS_*).
+    int id;
+    // True if the trailing colon should be stripped on platforms that
+    // don't want trailing colons.
+    bool strip_colon;
+  };
+  // A helper for simplifying the process of registering strings in WebUI.
+  static void RegisterStrings(DictionaryValue* localized_strings,
+                              const OptionsStringResource* resources,
+                              size_t length);
+
+  // Registers string resources for a page's header and tab title.
+  static void RegisterTitle(DictionaryValue* localized_strings,
+                            const std::string& variable_name,
+                            int title_id);
+
   NotificationRegistrar registrar_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(OptionsPageUIHandler);
 };
 
-class OptionsUI : public DOMUI {
+class OptionsUI : public WebUI {
  public:
   explicit OptionsUI(TabContents* contents);
   virtual ~OptionsUI();
@@ -91,6 +111,8 @@
   void AddOptionsPageUIHandler(DictionaryValue* localized_strings,
                                OptionsPageUIHandler* handler);
 
+  bool initialized_handlers_;
+
   DISALLOW_COPY_AND_ASSIGN(OptionsUI);
 };
 
diff --git a/chrome/browser/dom_ui/options/options_ui_uitest.cc b/chrome/browser/dom_ui/options/options_ui_uitest.cc
index b6c8bd2..d6061aa 100644
--- a/chrome/browser/dom_ui/options/options_ui_uitest.cc
+++ b/chrome/browser/dom_ui/options/options_ui_uitest.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/string16.h"
+#include "base/test/test_timeouts.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/chrome_switches.h"
@@ -13,9 +13,9 @@
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -29,7 +29,9 @@
     std::wstring title;
     ASSERT_TRUE(tab->GetTabTitle(&title));
     string16 expected_title = l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE);
-    ASSERT_EQ(expected_title, WideToUTF16Hack(title));
+    // The only guarantee we can make about the title of a settings tab is that
+    // it should contain IDS_SETTINGS_TITLE somewhere.
+    ASSERT_FALSE(WideToUTF16Hack(title).find(expected_title) == string16::npos);
   }
 };
 
@@ -45,7 +47,8 @@
   AssertIsOptionsPage(tab);
 }
 
-TEST_F(OptionsUITest, CommandOpensOptionsTab) {
+// Flaky, and takes very long to fail. http://crbug.com/64619.
+TEST_F(OptionsUITest, DISABLED_CommandOpensOptionsTab) {
   scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser.get());
 
@@ -63,17 +66,8 @@
   AssertIsOptionsPage(tab);
 }
 
-// TODO(csilv): Investigate why this fails and fix. http://crbug.com/48521
-// Also, crashing on linux/views.
-#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
-#define MAYBE_CommandAgainGoesBackToOptionsTab \
-    DISABLED_CommandAgainGoesBackToOptionsTab
-#else
-#define MAYBE_CommandAgainGoesBackToOptionsTab \
-    FLAKY_CommandAgainGoesBackToOptionsTab
-#endif
-
-TEST_F(OptionsUITest, MAYBE_CommandAgainGoesBackToOptionsTab) {
+// Flaky, and takes very long to fail. http://crbug.com/48521
+TEST_F(OptionsUITest, DISABLED_CommandAgainGoesBackToOptionsTab) {
   scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser.get());
 
@@ -92,24 +86,19 @@
 
   // Switch to first tab and run command again.
   ASSERT_TRUE(browser->ActivateTab(0));
-  ASSERT_TRUE(browser->WaitForTabToBecomeActive(0, action_max_timeout_ms()));
+  ASSERT_TRUE(browser->WaitForTabToBecomeActive(
+      0, TestTimeouts::action_max_timeout_ms()));
   ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
 
   // Ensure the options ui tab is active.
-  ASSERT_TRUE(browser->WaitForTabToBecomeActive(1, action_max_timeout_ms()));
+  ASSERT_TRUE(browser->WaitForTabToBecomeActive(
+      1, TestTimeouts::action_max_timeout_ms()));
   ASSERT_TRUE(browser->GetTabCount(&tab_count));
   ASSERT_EQ(2, tab_count);
 }
 
-// TODO(csilv): Investigate why this fails (sometimes) on 10.5 and fix.
-// http://crbug.com/48521. Also, crashing on linux/views.
-#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
-#define MAYBE_TwoCommandsOneTab DISABLED_TwoCommandsOneTab
-#else
-#define MAYBE_TwoCommandsOneTab FLAKY_TwoCommandsOneTab
-#endif
-
-TEST_F(OptionsUITest, MAYBE_TwoCommandsOneTab) {
+// Flaky, and takes very long to fail. http://crbug.com/48521
+TEST_F(OptionsUITest, DISABLED_TwoCommandsOneTab) {
   scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser.get());
 
diff --git a/chrome/browser/dom_ui/options/password_manager_handler.cc b/chrome/browser/dom_ui/options/password_manager_handler.cc
index 6076bc7..f14643f 100644
--- a/chrome/browser/dom_ui/options/password_manager_handler.cc
+++ b/chrome/browser/dom_ui/options/password_manager_handler.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/password_manager_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/stl_util-inl.h"
 #include "base/string_number_conversions.h"
@@ -17,6 +16,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 PasswordManagerHandler::PasswordManagerHandler()
     : ALLOW_THIS_IN_INITIALIZER_LIST(populater_(this)),
@@ -30,12 +30,16 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("passwordsTitle",
-      l10n_util::GetStringUTF16(IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE));
+  RegisterTitle(localized_strings, "passwordsPage",
+                IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
   localized_strings->SetString("savedPasswordsTitle",
       l10n_util::GetStringUTF16(IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE));
   localized_strings->SetString("passwordExceptionsTitle",
       l10n_util::GetStringUTF16(IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE));
+  localized_strings->SetString("passwordShowButton",
+      l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON));
+  localized_strings->SetString("passwordHideButton",
+      l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON));
   localized_strings->SetString("passwordsSiteColumn",
       l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN));
   localized_strings->SetString("passwordsUsernameColumn",
@@ -44,10 +48,6 @@
       l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON));
   localized_strings->SetString("passwordsRemoveAllButton",
       l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON));
-  localized_strings->SetString("passwordsShowButton",
-      l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON));
-  localized_strings->SetString("passwordsHideButton",
-      l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON));
   localized_strings->SetString("passwordsRemoveAllTitle",
       l10n_util::GetStringUTF16(
           IDS_PASSWORDS_PAGE_VIEW_CAPTION_DELETE_ALL_PASSWORDS));
@@ -57,31 +57,31 @@
 }
 
 void PasswordManagerHandler::Initialize() {
-  // We should not cache dom_ui_->GetProfile(). See crosbug.com/6304.
+  // We should not cache web_ui_->GetProfile(). See crosbug.com/6304.
 }
 
 void PasswordManagerHandler::RegisterMessages() {
-  DCHECK(dom_ui_);
+  DCHECK(web_ui_);
 
-  dom_ui_->RegisterMessageCallback("updatePasswordLists",
+  web_ui_->RegisterMessageCallback("updatePasswordLists",
       NewCallback(this, &PasswordManagerHandler::UpdatePasswordLists));
-  dom_ui_->RegisterMessageCallback("removeSavedPassword",
+  web_ui_->RegisterMessageCallback("removeSavedPassword",
       NewCallback(this, &PasswordManagerHandler::RemoveSavedPassword));
-  dom_ui_->RegisterMessageCallback("removePasswordException",
+  web_ui_->RegisterMessageCallback("removePasswordException",
       NewCallback(this, &PasswordManagerHandler::RemovePasswordException));
-  dom_ui_->RegisterMessageCallback("removeAllSavedPasswords",
+  web_ui_->RegisterMessageCallback("removeAllSavedPasswords",
       NewCallback(this, &PasswordManagerHandler::RemoveAllSavedPasswords));
-  dom_ui_->RegisterMessageCallback("removeAllPasswordExceptions", NewCallback(
+  web_ui_->RegisterMessageCallback("removeAllPasswordExceptions", NewCallback(
       this, &PasswordManagerHandler::RemoveAllPasswordExceptions));
 }
 
 PasswordStore* PasswordManagerHandler::GetPasswordStore() {
-  return dom_ui_->GetProfile()->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+  return web_ui_->GetProfile()->GetPasswordStore(Profile::EXPLICIT_ACCESS);
 }
 
 void PasswordManagerHandler::UpdatePasswordLists(const ListValue* args) {
   languages_ =
-      dom_ui_->GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
+      web_ui_->GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
   populater_.Populate();
   exception_populater_.Populate();
 }
@@ -138,7 +138,7 @@
     entries.Append(entry);
   }
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"PasswordManager.setSavedPasswordsList", entries);
 }
 
@@ -149,10 +149,25 @@
         net::FormatUrl(password_exception_list_[i]->origin, languages_)));
   }
 
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
       L"PasswordManager.setPasswordExceptionsList", entries);
 }
 
+PasswordManagerHandler::ListPopulater::ListPopulater(
+    PasswordManagerHandler* page) : page_(page),
+                                    pending_login_query_(0) {
+}
+
+PasswordManagerHandler::ListPopulater::~ListPopulater() {
+  PasswordStore* store = page_->GetPasswordStore();
+  if (store)
+    store->CancelLoginsQuery(pending_login_query_);
+}
+
+PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater(
+    PasswordManagerHandler* page) : ListPopulater(page) {
+}
+
 void PasswordManagerHandler::PasswordListPopulater::Populate() {
   DCHECK(!pending_login_query_);
   PasswordStore* store = page_->GetPasswordStore();
@@ -171,6 +186,11 @@
   page_->SetPasswordList();
 }
 
+PasswordManagerHandler::PasswordExceptionListPopulater::
+    PasswordExceptionListPopulater(PasswordManagerHandler* page)
+        : ListPopulater(page) {
+}
+
 void PasswordManagerHandler::PasswordExceptionListPopulater::Populate() {
   DCHECK(!pending_login_query_);
   PasswordStore* store = page_->GetPasswordStore();
diff --git a/chrome/browser/dom_ui/options/password_manager_handler.h b/chrome/browser/dom_ui/options/password_manager_handler.h
index 5cd3080..af94e6b 100644
--- a/chrome/browser/dom_ui/options/password_manager_handler.h
+++ b/chrome/browser/dom_ui/options/password_manager_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -56,10 +56,8 @@
   // A short class to mediate requests to the password store.
   class ListPopulater : public PasswordStoreConsumer {
    public:
-    explicit ListPopulater(PasswordManagerHandler* page)
-        : page_(page),
-          pending_login_query_(0) {
-    }
+    explicit ListPopulater(PasswordManagerHandler* page);
+    virtual ~ListPopulater();
 
     // Send a query to the password store to populate a list.
     virtual void Populate() = 0;
@@ -76,9 +74,7 @@
   // A short class to mediate requests to the password store for passwordlist.
   class PasswordListPopulater : public ListPopulater {
    public:
-    explicit PasswordListPopulater(PasswordManagerHandler* page)
-      : ListPopulater(page) {
-    }
+    explicit PasswordListPopulater(PasswordManagerHandler* page);
 
     // Send a query to the password store to populate a password list.
     virtual void Populate();
@@ -91,9 +87,7 @@
   // A short class to mediate requests to the password store for exceptions.
   class PasswordExceptionListPopulater : public ListPopulater {
    public:
-    explicit PasswordExceptionListPopulater(
-        PasswordManagerHandler* page) : ListPopulater(page) {
-    }
+    explicit PasswordExceptionListPopulater(PasswordManagerHandler* page);
 
     // Send a query to the password store to populate a passwordException list.
     virtual void Populate();
diff --git a/chrome/browser/dom_ui/options/personal_options_handler.cc b/chrome/browser/dom_ui/options/personal_options_handler.cc
index bc14c1f..45f727e 100644
--- a/chrome/browser/dom_ui/options/personal_options_handler.cc
+++ b/chrome/browser/dom_ui/options/personal_options_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/path_service.h"
@@ -20,24 +19,28 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/sync_setup_flow.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
 #include "chrome/browser/ui/options/options_page_base.h"
 #include "chrome/browser/ui/options/options_window.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/chrome_paths.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #endif  // defined(OS_CHROMEOS)
 #if defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
 #endif  // defined(TOOLKIT_GTK)
 
 PersonalOptionsHandler::PersonalOptionsHandler() {
@@ -45,7 +48,7 @@
 
 PersonalOptionsHandler::~PersonalOptionsHandler() {
   ProfileSyncService* sync_service =
-      dom_ui_->GetProfile()->GetProfileSyncService();
+      web_ui_->GetProfile()->GetProfileSyncService();
   if (sync_service)
     sync_service->RemoveObserver(this);
 }
@@ -54,9 +57,14 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
+  RegisterTitle(localized_strings, "personalPage",
+                IDS_OPTIONS_CONTENT_TAB_LABEL);
+
   localized_strings->SetString("syncSection",
       dom_options_util::StripColon(
           l10n_util::GetStringUTF16(IDS_SYNC_OPTIONS_GROUP_NAME)));
+  localized_strings->SetString("customizeSync",
+      l10n_util::GetStringUTF16(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL));
   localized_strings->SetString("privacyDashboardLink",
       l10n_util::GetStringUTF16(IDS_SYNC_PRIVACY_DASHBOARD_LINK_LABEL));
 
@@ -124,21 +132,65 @@
           l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_EVERYTHING)));
   sync_select_list->Append(everything);
   localized_strings->Set("syncSelectList", sync_select_list);
+
+  // Sync page.
+  localized_strings->SetString("syncPage",
+      l10n_util::GetStringUTF16(IDS_SYNC_NTP_SYNC_SECTION_TITLE));
+  localized_strings->SetString("sync_title",
+      l10n_util::GetStringUTF16(IDS_CUSTOMIZE_SYNC_DESCRIPTION));
+  localized_strings->SetString("syncsettings",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES));
+  localized_strings->SetString("syncbookmarks",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS));
+  localized_strings->SetString("synctypedurls",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS));
+  localized_strings->SetString("syncpasswords",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS));
+  localized_strings->SetString("syncextensions",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS));
+  localized_strings->SetString("syncautofill",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL));
+  localized_strings->SetString("syncthemes",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES));
+  localized_strings->SetString("syncapps",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS));
+  localized_strings->SetString("syncsessions",
+      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_SESSIONS));
+
+#if defined(OS_CHROMEOS)
+  localized_strings->SetString("account",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_PERSONAL_ACCOUNT_GROUP_NAME));
+  localized_strings->SetString("enableScreenlock",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SCREENLOCKER_CHECKBOX));
+#endif
 }
 
 void PersonalOptionsHandler::RegisterMessages() {
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback(
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback(
+      "showSyncActionDialog",
+      NewCallback(this, &PersonalOptionsHandler::ShowSyncActionDialog));
+  web_ui_->RegisterMessageCallback(
       "showSyncLoginDialog",
       NewCallback(this, &PersonalOptionsHandler::ShowSyncLoginDialog));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
+      "showCustomizeSyncDialog",
+      NewCallback(this, &PersonalOptionsHandler::ShowCustomizeSyncDialog));
+  web_ui_->RegisterMessageCallback(
       "themesReset",
       NewCallback(this, &PersonalOptionsHandler::ThemesReset));
 #if defined(TOOLKIT_GTK)
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "themesSetGTK",
       NewCallback(this, &PersonalOptionsHandler::ThemesSetGTK));
 #endif
+  web_ui_->RegisterMessageCallback("updatePreferredDataTypes",
+      NewCallback(this, &PersonalOptionsHandler::OnPreferredDataTypesUpdated));
+#if defined(OS_CHROMEOS)
+  web_ui_->RegisterMessageCallback(
+      "loadAccountPicture",
+      NewCallback(this, &PersonalOptionsHandler::LoadAccountPicture));
+#endif
 }
 
 void PersonalOptionsHandler::Observe(NotificationType type,
@@ -153,7 +205,8 @@
 void PersonalOptionsHandler::OnStateChanged() {
   string16 status_label;
   string16 link_label;
-  ProfileSyncService* service = dom_ui_->GetProfile()->GetProfileSyncService();
+  ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
+  DCHECK(service);
   bool managed = service->IsManaged();
   bool sync_setup_completed = service->HasSyncSetupCompleted();
   bool status_has_error = sync_ui_util::GetStatusLabels(service,
@@ -169,7 +222,7 @@
     is_start_stop_button_visible = false;
 #else
     is_start_stop_button_visible = true;
-#endif
+#endif  // defined(OS_CHROMEOS)
     is_start_stop_button_enabled = !managed;
   } else if (service->SetupInProgress()) {
     start_stop_button_label =
@@ -184,114 +237,40 @@
   }
 
   scoped_ptr<Value> completed(Value::CreateBooleanValue(sync_setup_completed));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncSetupCompleted",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncSetupCompleted",
                                   *completed);
 
   scoped_ptr<Value> label(Value::CreateStringValue(status_label));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncStatus",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncStatus",
                                   *label);
 
   scoped_ptr<Value> enabled(
       Value::CreateBooleanValue(is_start_stop_button_enabled));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setStartStopButtonEnabled",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setStartStopButtonEnabled",
                                   *enabled);
 
   scoped_ptr<Value> visible(
       Value::CreateBooleanValue(is_start_stop_button_visible));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setStartStopButtonVisible",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setStartStopButtonVisible",
                                   *visible);
 
   label.reset(Value::CreateStringValue(start_stop_button_label));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setStartStopButtonLabel",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setStartStopButtonLabel",
                                   *label);
 
-#if !defined(OS_CHROMEOS)
   label.reset(Value::CreateStringValue(link_label));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncActionLinkLabel",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncActionLinkLabel",
                                   *label);
 
   enabled.reset(Value::CreateBooleanValue(!managed));
-  dom_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncActionLinkEnabled",
+  web_ui_->CallJavascriptFunction(L"PersonalOptions.setSyncActionLinkEnabled",
                                   *enabled);
-#endif
 
   visible.reset(Value::CreateBooleanValue(status_has_error));
-  dom_ui_->CallJavascriptFunction(
+  web_ui_->CallJavascriptFunction(
     L"PersonalOptions.setSyncStatusErrorVisible", *visible);
-#if !defined(OS_CHROMEOS)
-  dom_ui_->CallJavascriptFunction(
-    L"PersonalOptions.setSyncActionLinkErrorVisible", *visible);
-#endif
 }
 
-void PersonalOptionsHandler::ObserveThemeChanged() {
-  Profile* profile = dom_ui_->GetProfile();
-#if defined(TOOLKIT_GTK)
-  GtkThemeProvider* provider = GtkThemeProvider::GetFrom(profile);
-  bool is_gtk_theme = provider->UseGtkTheme();
-  FundamentalValue gtk_enabled(!is_gtk_theme);
-  dom_ui_->CallJavascriptFunction(
-      L"options.PersonalOptions.setGtkThemeButtonEnabled", gtk_enabled);
-#else
-  BrowserThemeProvider* provider =
-      reinterpret_cast<BrowserThemeProvider*>(profile->GetThemeProvider());
-  bool is_gtk_theme = false;
-#endif
-
-  bool is_classic_theme = !is_gtk_theme && provider->GetThemeID().empty();
-  FundamentalValue enabled(!is_classic_theme);
-  dom_ui_->CallJavascriptFunction(
-      L"options.PersonalOptions.setThemesResetButtonEnabled", enabled);
-}
-
-void PersonalOptionsHandler::Initialize() {
-  banner_handler_.reset(
-      new OptionsManagedBannerHandler(dom_ui_,
-                                      ASCIIToUTF16("PersonalOptions"),
-                                      OPTIONS_PAGE_CONTENT));
-
-  // Listen for theme installation.
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  ObserveThemeChanged();
-
-  ProfileSyncService* sync_service =
-      dom_ui_->GetProfile()->GetProfileSyncService();
-  if (sync_service) {
-    sync_service->AddObserver(this);
-    OnStateChanged();
-  } else {
-    dom_ui_->CallJavascriptFunction(L"options.PersonalOptions.hideSyncSection");
-  }
-}
-
-void PersonalOptionsHandler::ShowSyncLoginDialog(const ListValue* args) {
-#if defined(OS_CHROMEOS)
-  std::string email = chromeos::UserManager::Get()->logged_in_user().email();
-  string16 message = l10n_util::GetStringFUTF16(
-      IDS_SYNC_LOGIN_INTRODUCTION,
-      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  dom_ui_->GetProfile()->GetBrowserSignin()->RequestSignin(
-      dom_ui_->tab_contents(), UTF8ToUTF16(email), message, this);
-#else
-  ProfileSyncService* service = dom_ui_->GetProfile()->GetProfileSyncService();
-  service->ShowLoginDialog(NULL);
-  ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
-#endif
-}
-
-void PersonalOptionsHandler::ThemesReset(const ListValue* args) {
-  UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset"));
-  dom_ui_->GetProfile()->ClearTheme();
-}
-
-#if defined(TOOLKIT_GTK)
-void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) {
-  UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet"));
-  dom_ui_->GetProfile()->SetNativeTheme();
-}
-#endif
-
 void PersonalOptionsHandler::OnLoginSuccess() {
   OnStateChanged();
 }
@@ -300,3 +279,125 @@
     const GoogleServiceAuthError& error) {
   OnStateChanged();
 }
+
+void PersonalOptionsHandler::ObserveThemeChanged() {
+  Profile* profile = web_ui_->GetProfile();
+#if defined(TOOLKIT_GTK)
+  GtkThemeProvider* provider = GtkThemeProvider::GetFrom(profile);
+  bool is_gtk_theme = provider->UseGtkTheme();
+  FundamentalValue gtk_enabled(!is_gtk_theme);
+  web_ui_->CallJavascriptFunction(
+      L"options.PersonalOptions.setGtkThemeButtonEnabled", gtk_enabled);
+#else
+  BrowserThemeProvider* provider =
+      reinterpret_cast<BrowserThemeProvider*>(profile->GetThemeProvider());
+  bool is_gtk_theme = false;
+#endif
+
+  bool is_classic_theme = !is_gtk_theme && provider->GetThemeID().empty();
+  FundamentalValue enabled(!is_classic_theme);
+  web_ui_->CallJavascriptFunction(
+      L"options.PersonalOptions.setThemesResetButtonEnabled", enabled);
+}
+
+void PersonalOptionsHandler::Initialize() {
+  banner_handler_.reset(
+      new OptionsManagedBannerHandler(web_ui_,
+                                      ASCIIToUTF16("PersonalOptions"),
+                                      OPTIONS_PAGE_CONTENT));
+
+  // Listen for theme installation.
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  ObserveThemeChanged();
+
+  ProfileSyncService* sync_service =
+      web_ui_->GetProfile()->GetProfileSyncService();
+  if (sync_service) {
+    sync_service->AddObserver(this);
+    OnStateChanged();
+
+    DictionaryValue args;
+    SyncSetupFlow::GetArgsForConfigure(sync_service, &args);
+
+    web_ui_->CallJavascriptFunction(
+        L"PersonalOptions.setRegisteredDataTypes", args);
+  } else {
+    web_ui_->CallJavascriptFunction(L"options.PersonalOptions.hideSyncSection");
+  }
+}
+
+void PersonalOptionsHandler::ShowSyncActionDialog(const ListValue* args) {
+  ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
+  DCHECK(service);
+#if defined(OS_CHROMEOS)
+  // ProfileSyncService calls ProfileSyncService::ShowLoginDialog()
+  // for these errors, which currently does not work on ChromeOS.
+  // TODO(stevenjb + jhawkins): This code path should go away for R11 when
+  // we switch to DOM based sync setup UI.
+  const GoogleServiceAuthError& error = service->GetAuthError();
+  if (error.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
+      error.state() == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
+      error.state() == GoogleServiceAuthError::ACCOUNT_DELETED ||
+      error.state() == GoogleServiceAuthError::ACCOUNT_DISABLED ||
+      error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
+    ShowSyncLoginDialog(args);
+  }
+#endif
+  service->ShowErrorUI(NULL);
+}
+
+void PersonalOptionsHandler::ShowSyncLoginDialog(const ListValue* args) {
+#if defined(OS_CHROMEOS)
+  std::string email = chromeos::UserManager::Get()->logged_in_user().email();
+  string16 message = l10n_util::GetStringFUTF16(
+      IDS_SYNC_LOGIN_INTRODUCTION,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  web_ui_->GetProfile()->GetBrowserSignin()->RequestSignin(
+      web_ui_->tab_contents(), UTF8ToUTF16(email), message, this);
+#else
+  ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
+  DCHECK(service);
+  service->ShowLoginDialog(NULL);
+  ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
+#endif
+}
+
+void PersonalOptionsHandler::ShowCustomizeSyncDialog(const ListValue* args) {
+  ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
+  DCHECK(service);
+  service->ShowConfigure(NULL);
+}
+
+void PersonalOptionsHandler::ThemesReset(const ListValue* args) {
+  UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset"));
+  web_ui_->GetProfile()->ClearTheme();
+}
+
+#if defined(TOOLKIT_GTK)
+void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) {
+  UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet"));
+  web_ui_->GetProfile()->SetNativeTheme();
+}
+#endif
+
+void PersonalOptionsHandler::OnPreferredDataTypesUpdated(
+    const ListValue* args) {
+  NotificationService::current()->Notify(
+      NotificationType::SYNC_DATA_TYPES_UPDATED,
+      Source<Profile>(web_ui_->GetProfile()),
+      NotificationService::NoDetails());
+}
+
+#if defined(OS_CHROMEOS)
+void PersonalOptionsHandler::LoadAccountPicture(const ListValue* args) {
+  const SkBitmap& account_picture =
+      chromeos::UserManager::Get()->logged_in_user().image();
+
+  if (!account_picture.isNull()) {
+    StringValue data_url(web_ui_util::GetImageDataUrl(account_picture));
+    web_ui_->CallJavascriptFunction(L"PersonalOptions.setAccountPicture",
+        data_url);
+  }
+}
+#endif
diff --git a/chrome/browser/dom_ui/options/personal_options_handler.h b/chrome/browser/dom_ui/options/personal_options_handler.h
index 451ccff..0340f79 100644
--- a/chrome/browser/dom_ui/options/personal_options_handler.h
+++ b/chrome/browser/dom_ui/options/personal_options_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_DOM_UI_OPTIONS_PERSONAL_OPTIONS_HANDLER_H_
 #pragma once
 
+#include "base/basictypes.h"
 #include "chrome/browser/browser_signin.h"
 #include "chrome/browser/dom_ui/options/options_ui.h"
 #include "chrome/browser/sync/profile_sync_service.h"
@@ -24,7 +25,7 @@
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
   virtual void Initialize();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // NotificationObserver implementation.
@@ -41,12 +42,22 @@
 
  private:
   void ObserveThemeChanged();
+  void ShowSyncActionDialog(const ListValue* args);
   void ShowSyncLoginDialog(const ListValue* args);
+  void ShowCustomizeSyncDialog(const ListValue* args);
   void ThemesReset(const ListValue* args);
 #if defined(TOOLKIT_GTK)
   void ThemesSetGTK(const ListValue* args);
 #endif
 
+  // Called when the user updates the set of enabled data types to sync. |args|
+  // is ignored.
+  void OnPreferredDataTypesUpdated(const ListValue* args);
+
+#if defined(OS_CHROMEOS)
+  void LoadAccountPicture(const ListValue* args);
+#endif
+
   scoped_ptr<OptionsManagedBannerHandler> banner_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(PersonalOptionsHandler);
diff --git a/chrome/browser/dom_ui/options/search_engine_manager_handler.cc b/chrome/browser/dom_ui/options/search_engine_manager_handler.cc
index 78c8cd3..607ce46 100644
--- a/chrome/browser/dom_ui/options/search_engine_manager_handler.cc
+++ b/chrome/browser/dom_ui/options/search_engine_manager_handler.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/search_engine_manager_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -17,6 +16,7 @@
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -37,7 +37,7 @@
 }
 
 void SearchEngineManagerHandler::Initialize() {
-  list_controller_.reset(new KeywordEditorController(dom_ui_->GetProfile()));
+  list_controller_.reset(new KeywordEditorController(web_ui_->GetProfile()));
   if (list_controller_.get()) {
     list_controller_->table_model()->SetObserver(this);
     OnModelChanged();
@@ -48,60 +48,52 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
-  localized_strings->SetString("searchEngineManagerPage",
-      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE));
+  RegisterTitle(localized_strings, "searchEngineManagerPage",
+                IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE);
+  localized_strings->SetString("defaultSearchEngineListTitle",
+      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR));
+  localized_strings->SetString("otherSearchEngineListTitle",
+      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR));
   localized_strings->SetString("searchEngineTableNameHeader",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
   localized_strings->SetString("searchEngineTableKeywordHeader",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
-  localized_strings->SetString("addSearchEngineButton",
-      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON));
-  localized_strings->SetString("editSearchEngineButton",
+  localized_strings->SetString("searchEngineTableURLHeader",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON));
   localized_strings->SetString("makeDefaultSearchEngineButton",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON));
-  // Overlay strings.
-  localized_strings->SetString("editSearchEngineTitle",
-      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE));
-  localized_strings->SetString("editSearchEngineNameLabel",
-      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL));
-  localized_strings->SetString("editSearchEngineKeywordLabel",
-      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL));
-  localized_strings->SetString("editSearchEngineURLLabel",
-      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_URL_LABEL));
+  localized_strings->SetString("searchEngineTableNamePlaceholder",
+      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_NAME_PLACEHOLDER));
+  localized_strings->SetString("searchEngineTableKeywordPlaceholder",
+      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_KEYWORD_PLACEHOLDER));
+  localized_strings->SetString("searchEngineTableURLPlaceholder",
+      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_URL_PLACEHOLDER));
   localized_strings->SetString("editSearchEngineInvalidTitleToolTip",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_TITLE_TT));
   localized_strings->SetString("editSearchEngineInvalidKeywordToolTip",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT));
   localized_strings->SetString("editSearchEngineInvalidURLToolTip",
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_URL_TT));
-  localized_strings->SetString("editSearchEngineURLExplanation",
-      l10n_util::GetStringUTF16(
-          IDS_SEARCH_ENGINES_EDITOR_URL_DESCRIPTION_LABEL));
-  localized_strings->SetString("editSearchEngineOkayButton",
-      l10n_util::GetStringUTF16(IDS_OK));
-  localized_strings->SetString("editSearchEngineCancelButton",
-      l10n_util::GetStringUTF16(IDS_CANCEL));
 }
 
 void SearchEngineManagerHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "managerSetDefaultSearchEngine",
       NewCallback(this, &SearchEngineManagerHandler::SetDefaultSearchEngine));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "removeSearchEngine",
       NewCallback(this, &SearchEngineManagerHandler::RemoveSearchEngine));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "editSearchEngine",
       NewCallback(this, &SearchEngineManagerHandler::EditSearchEngine));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "checkSearchEngineInfoValidity",
       NewCallback(this,
                   &SearchEngineManagerHandler::CheckSearchEngineInfoValidity));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "searchEngineEditCancelled",
       NewCallback(this, &SearchEngineManagerHandler::EditCancelled));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "searchEngineEditCompleted",
       NewCallback(this, &SearchEngineManagerHandler::EditCompleted));
 }
@@ -110,33 +102,31 @@
   if (!list_controller_->loaded())
     return;
 
-  ListValue engine_list;
-
   // Find the default engine.
   const TemplateURL* default_engine =
       list_controller_->url_model()->GetDefaultSearchProvider();
   int default_index = list_controller_->table_model()->IndexOfTemplateURL(
       default_engine);
 
-  // Add the first group (default search engine options).
-  engine_list.Append(CreateDictionaryForHeading(0));
+  // Build the first list (default search engine options).
+  ListValue defaults_list;
   int last_default_engine_index =
       list_controller_->table_model()->last_search_engine_index();
   for (int i = 0; i < last_default_engine_index; ++i) {
-    engine_list.Append(CreateDictionaryForEngine(i, i == default_index));
+    defaults_list.Append(CreateDictionaryForEngine(i, i == default_index));
   }
 
-  // Add the second group (other search templates).
-  engine_list.Append(CreateDictionaryForHeading(1));
+  // Build the second list (other search templates).
+  ListValue others_list;
   if (last_default_engine_index < 0)
     last_default_engine_index = 0;
   int engine_count = list_controller_->table_model()->RowCount();
   for (int i = last_default_engine_index; i < engine_count; ++i) {
-    engine_list.Append(CreateDictionaryForEngine(i, i == default_index));
+    others_list.Append(CreateDictionaryForEngine(i, i == default_index));
   }
 
-  dom_ui_->CallJavascriptFunction(L"SearchEngineManager.updateSearchEngineList",
-                                  engine_list);
+  web_ui_->CallJavascriptFunction(L"SearchEngineManager.updateSearchEngineList",
+                                  defaults_list, others_list);
 }
 
 void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
@@ -151,15 +141,6 @@
   OnModelChanged();
 }
 
-DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForHeading(
-    int group_index) {
-  TableModel::Groups groups = list_controller_->table_model()->GetGroups();
-
-  DictionaryValue* dict = new DictionaryValue();
-  dict->SetString("heading", groups[group_index].title);
-  return dict;
-}
-
 DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
     int index, bool is_default) {
   TemplateURLTableModel* table_model = list_controller_->table_model();
@@ -170,6 +151,8 @@
   dict->SetString("keyword", table_model->GetText(
     index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
   const TemplateURL* template_url = list_controller_->GetTemplateURL(index);
+  dict->SetString("url", template_url->url()->DisplayURL());
+  dict->SetBoolean("urlLocked", template_url->prepopulate_id() > 0);
   GURL icon_url = template_url->GetFavIconURL();
   if (icon_url.is_valid())
     dict->SetString("iconURL", icon_url.spec());
@@ -224,18 +207,7 @@
   if (index != -1)
     edit_url = list_controller_->GetTemplateURL(index);
   edit_controller_.reset(
-      new EditSearchEngineController(edit_url, this, dom_ui_->GetProfile()));
-
-  if (edit_url) {
-    DictionaryValue engine_details;
-    engine_details.SetString("name", WideToUTF16Hack(edit_url->short_name()));
-    engine_details.SetString("keyword", WideToUTF16Hack(edit_url->keyword()));
-    engine_details.SetString("url",
-                             WideToUTF16Hack(edit_url->url()->DisplayURL()));
-    engine_details.SetBoolean("urlLocked", edit_url->prepopulate_id() > 0);
-    dom_ui_->CallJavascriptFunction(L"EditSearchEngineOverlay.setEditDetails",
-                                    engine_details);
-  }
+      new EditSearchEngineController(edit_url, this, web_ui_->GetProfile()));
 }
 
 void SearchEngineManagerHandler::OnEditedKeyword(
@@ -259,9 +231,11 @@
   string16 name;
   string16 keyword;
   std::string url;
+  std::string modelIndex;
   if (!args->GetString(ENGINE_NAME, &name) ||
       !args->GetString(ENGINE_KEYWORD, &keyword) ||
-      !args->GetString(ENGINE_URL, &url)) {
+      !args->GetString(ENGINE_URL, &url) ||
+      !args->GetString(3, &modelIndex)) {
     NOTREACHED();
     return;
   }
@@ -270,8 +244,9 @@
   validity.SetBoolean("name", edit_controller_->IsTitleValid(name));
   validity.SetBoolean("keyword", edit_controller_->IsKeywordValid(keyword));
   validity.SetBoolean("url", edit_controller_->IsURLValid(url));
-  dom_ui_->CallJavascriptFunction(
-      L"EditSearchEngineOverlay.validityCheckCallback", validity);
+  StringValue indexValue(modelIndex);
+  web_ui_->CallJavascriptFunction(
+      L"SearchEngineManager.validityCheckCallback", validity, indexValue);
 }
 
 void SearchEngineManagerHandler::EditCancelled(const ListValue* args) {
diff --git a/chrome/browser/dom_ui/options/search_engine_manager_handler.h b/chrome/browser/dom_ui/options/search_engine_manager_handler.h
index f837d38..1a87cc6 100644
--- a/chrome/browser/dom_ui/options/search_engine_manager_handler.h
+++ b/chrome/browser/dom_ui/options/search_engine_manager_handler.h
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef CHROME_BROWSER_DOM_UI_OPTIONS_SEARCH_ENGINE_MANAGER_HANDLER_H_
 #define CHROME_BROWSER_DOM_UI_OPTIONS_SEARCH_ENGINE_MANAGER_HANDLER_H_
 
-#include "app/table_model_observer.h"
 #include "chrome/browser/dom_ui/options/options_ui.h"
 #include "chrome/browser/search_engines/edit_search_engine_controller.h"
+#include "ui/base/models/table_model_observer.h"
 
 class KeywordEditorController;
 
 class SearchEngineManagerHandler : public OptionsPageUIHandler,
-                                   public TableModelObserver,
+                                   public ui::TableModelObserver,
                                    public EditSearchEngineControllerDelegate {
  public:
   SearchEngineManagerHandler();
@@ -23,7 +23,7 @@
   // OptionsUIHandler implementation.
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
 
-  // TableModelObserver implementation.
+  // ui::TableModelObserver implementation.
   virtual void OnModelChanged();
   virtual void OnItemsChanged(int start, int length);
   virtual void OnItemsAdded(int start, int length);
@@ -41,32 +41,30 @@
   scoped_ptr<KeywordEditorController> list_controller_;
   scoped_ptr<EditSearchEngineController> edit_controller_;
 
-  // Removes the search engine at the given index. Called from DOMUI.
+  // Removes the search engine at the given index. Called from WebUI.
   void RemoveSearchEngine(const ListValue* args);
 
-  // Sets the search engine at the given index to be default. Called from DOMUI.
+  // Sets the search engine at the given index to be default. Called from WebUI.
   void SetDefaultSearchEngine(const ListValue* args);
 
   // Starts an edit session for the search engine at the given index. If the
   // index is -1, starts editing a new search engine instead of an existing one.
-  // Called from DOMUI.
+  // Called from WebUI.
   void EditSearchEngine(const ListValue* args);
 
   // Validates the given search engine values, and reports the results back
-  // to DOMUI. Called from DOMUI.
+  // to WebUI. Called from WebUI.
   void CheckSearchEngineInfoValidity(const ListValue* args);
 
   // Called when an edit is cancelled.
-  // Called from DOMUI.
+  // Called from WebUI.
   void EditCancelled(const ListValue* args);
 
   // Called when an edit is finished and should be saved.
-  // Called from DOMUI.
+  // Called from WebUI.
   void EditCompleted(const ListValue* args);
 
-  // Returns a dictionary to pass to DOMUI representing the given group heading.
-  DictionaryValue* CreateDictionaryForHeading(int group_index);
-  // Returns a dictionary to pass to DOMUI representing the given search engine.
+  // Returns a dictionary to pass to WebUI representing the given search engine.
   DictionaryValue* CreateDictionaryForEngine(int index, bool is_default);
 
   DISALLOW_COPY_AND_ASSIGN(SearchEngineManagerHandler);
diff --git a/chrome/browser/dom_ui/options/startup_page_manager_handler.cc b/chrome/browser/dom_ui/options/startup_page_manager_handler.cc
deleted file mode 100644
index aabae28..0000000
--- a/chrome/browser/dom_ui/options/startup_page_manager_handler.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/options/startup_page_manager_handler.h"
-
-#include "app/l10n_util.h"
-#include "base/values.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-StartupPageManagerHandler::StartupPageManagerHandler() {
-}
-
-StartupPageManagerHandler::~StartupPageManagerHandler() {
-}
-
-void StartupPageManagerHandler::GetLocalizedValues(
-    DictionaryValue* localized_strings) {
-  DCHECK(localized_strings);
-
-  localized_strings->SetString("startupAddButton",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_ADD_BUTTON));
-  localized_strings->SetString("startupPageManagerPage",
-      l10n_util::GetStringUTF16(IDS_STARTUP_PAGE_SUBPAGE_TITLE));
-  localized_strings->SetString("startupManagePages",
-      l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_MANAGE_BUTTON));
-}
diff --git a/chrome/browser/dom_ui/options/startup_page_manager_handler.h b/chrome/browser/dom_ui/options/startup_page_manager_handler.h
deleted file mode 100644
index 440e887..0000000
--- a/chrome/browser/dom_ui/options/startup_page_manager_handler.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_OPTIONS_STARTUP_PAGE_MANAGER_HANDLER_H_
-#define CHROME_BROWSER_DOM_UI_OPTIONS_STARTUP_PAGE_MANAGER_HANDLER_H_
-
-#include "chrome/browser/dom_ui/options/options_ui.h"
-
-class StartupPageManagerHandler : public OptionsPageUIHandler {
- public:
-  StartupPageManagerHandler();
-  virtual ~StartupPageManagerHandler();
-
-  // OptionsUIHandler implementation.
-  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
-
- private:
-
-  DISALLOW_COPY_AND_ASSIGN(StartupPageManagerHandler);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_OPTIONS_STARTUP_PAGE_MANAGER_HANDLER_H_
diff --git a/chrome/browser/dom_ui/options/stop_syncing_handler.cc b/chrome/browser/dom_ui/options/stop_syncing_handler.cc
index 833c88e..9c0c579 100644
--- a/chrome/browser/dom_ui/options/stop_syncing_handler.cc
+++ b/chrome/browser/dom_ui/options/stop_syncing_handler.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/options/stop_syncing_handler.h"
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/values.h"
 #include "base/callback.h"
@@ -13,6 +12,7 @@
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "ui/base/l10n/l10n_util.h"
 
 StopSyncingHandler::StopSyncingHandler() {
 }
@@ -24,8 +24,7 @@
     DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
   localized_strings->SetString("stop_syncing_explanation",
-      l10n_util::GetStringFUTF16(IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+      l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL));
   localized_strings->SetString("stop_syncing_title",
       l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_DIALOG_TITLE));
   localized_strings->SetString("stop_syncing_confirm",
@@ -33,13 +32,13 @@
 }
 
 void StopSyncingHandler::RegisterMessages() {
-  DCHECK(dom_ui_);
-  dom_ui_->RegisterMessageCallback("stopSyncing",
+  DCHECK(web_ui_);
+  web_ui_->RegisterMessageCallback("stopSyncing",
       NewCallback(this, &StopSyncingHandler::StopSyncing));
 }
 
 void StopSyncingHandler::StopSyncing(const ListValue* args){
-  ProfileSyncService* service = dom_ui_->GetProfile()->GetProfileSyncService();
+  ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
   if (service != NULL && ProfileSyncService::IsSyncEnabled()) {
     service->DisableForUser();
     ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
diff --git a/chrome/browser/dom_ui/options/stop_syncing_handler.h b/chrome/browser/dom_ui/options/stop_syncing_handler.h
index 9ad82f2..f586556 100644
--- a/chrome/browser/dom_ui/options/stop_syncing_handler.h
+++ b/chrome/browser/dom_ui/options/stop_syncing_handler.h
@@ -16,7 +16,7 @@
   // OptionsUIHandler implementation.
   virtual void GetLocalizedValues(DictionaryValue* localized_strings);
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
  private:
diff --git a/chrome/browser/dom_ui/options/sync_options_handler.cc b/chrome/browser/dom_ui/options/sync_options_handler.cc
deleted file mode 100644
index e67050c..0000000
--- a/chrome/browser/dom_ui/options/sync_options_handler.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/options/sync_options_handler.h"
-
-#include "app/l10n_util.h"
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/stl_util-inl.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/sync_setup_flow.h"
-#include "chrome/common/notification_service.h"
-#include "grit/browser_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-
-SyncOptionsHandler::SyncOptionsHandler() {}
-
-SyncOptionsHandler::~SyncOptionsHandler() {}
-
-bool SyncOptionsHandler::IsEnabled() {
-  return ProfileSyncService::IsSyncEnabled();
-}
-
-void SyncOptionsHandler::GetLocalizedValues(
-    DictionaryValue* localized_strings) {
-  DCHECK(localized_strings);
-  // Sync page - ChromeOS
-  localized_strings->SetString("syncPage",
-      l10n_util::GetStringUTF16(IDS_SYNC_NTP_SYNC_SECTION_TITLE));
-  localized_strings->SetString("sync_title",
-      l10n_util::GetStringUTF16(IDS_CUSTOMIZE_SYNC_DESCRIPTION));
-  localized_strings->SetString("syncsettings",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES));
-  localized_strings->SetString("syncbookmarks",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS));
-  localized_strings->SetString("synctypedurls",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS));
-  localized_strings->SetString("syncpasswords",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS));
-  localized_strings->SetString("syncextensions",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS));
-  localized_strings->SetString("syncautofill",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL));
-  localized_strings->SetString("syncthemes",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES));
-  localized_strings->SetString("syncapps",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS));
-  localized_strings->SetString("syncsessions",
-      l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_SESSIONS));
-}
-
-void SyncOptionsHandler::Initialize() {
-  ProfileSyncService* service =
-      dom_ui_->GetProfile()->GetOriginalProfile()->GetProfileSyncService();
-  // If service is unavailable for some good reason, 'IsEnabled()' method
-  // should return false. Otherwise something is broken.
-  DCHECK(service);
-
-  DictionaryValue args;
-  SyncSetupFlow::GetArgsForConfigure(service, &args);
-
-  dom_ui_->CallJavascriptFunction(
-      L"PersonalOptions.setRegisteredDataTypes", args);
-}
-
-void SyncOptionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("updatePreferredDataTypes",
-      NewCallback(this, &SyncOptionsHandler::OnPreferredDataTypesUpdated));
-}
-
-void SyncOptionsHandler::OnPreferredDataTypesUpdated(const ListValue* args) {
-  NotificationService::current()->Notify(
-      NotificationType::SYNC_DATA_TYPES_UPDATED,
-      Source<Profile>(dom_ui_->GetProfile()),
-      NotificationService::NoDetails());
-}
diff --git a/chrome/browser/dom_ui/options/sync_options_handler.h b/chrome/browser/dom_ui/options/sync_options_handler.h
deleted file mode 100644
index 79bf46d..0000000
--- a/chrome/browser/dom_ui/options/sync_options_handler.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOM_UI_OPTIONS_SYNC_OPTIONS_HANDLER_H_
-#define CHROME_BROWSER_DOM_UI_OPTIONS_SYNC_OPTIONS_HANDLER_H_
-#pragma once
-
-#include "chrome/browser/dom_ui/options/options_ui.h"
-
-// Chrome sync options page UI handler.
-// TODO(jhawkins): Move the meat of this class to PersonalOptionsHandler.
-class SyncOptionsHandler : public OptionsPageUIHandler {
- public:
-  SyncOptionsHandler();
-  virtual ~SyncOptionsHandler();
-
-  // OptionsUIHandler implementation.
-  virtual bool IsEnabled();
-  virtual void GetLocalizedValues(DictionaryValue* localized_strings);
-  virtual void Initialize();
-  virtual void RegisterMessages();
-
- private:
-  // Called when the user updates the set of enabled data types to sync. |args|
-  // is ignored.
-  void OnPreferredDataTypesUpdated(const ListValue* args);
-
-  DISALLOW_COPY_AND_ASSIGN(SyncOptionsHandler);
-};
-
-#endif  // CHROME_BROWSER_DOM_UI_OPTIONS_SYNC_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/dom_ui/plugins_ui.cc b/chrome/browser/dom_ui/plugins_ui.cc
index aaf59f1..e895ff9 100644
--- a/chrome/browser/dom_ui/plugins_ui.cc
+++ b/chrome/browser/dom_ui/plugins_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/singleton.h"
@@ -18,6 +16,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/plugin_updater.h"
+#include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
@@ -32,6 +31,8 @@
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/plugins/npapi/plugin_list.h"
 
 namespace {
@@ -83,8 +84,6 @@
       l10n_util::GetStringUTF16(IDS_PLUGINS_DOWNLOAD));
   localized_strings.SetString("pluginName",
       l10n_util::GetStringUTF16(IDS_PLUGINS_NAME));
-  localized_strings.SetString("pluginPriority",
-      l10n_util::GetStringUTF16(IDS_PLUGINS_PRIORITY));
   localized_strings.SetString("pluginVersion",
       l10n_util::GetStringUTF16(IDS_PLUGINS_VERSION));
   localized_strings.SetString("pluginDescription",
@@ -131,13 +130,14 @@
 // TODO(viettrungluu): Make plugin list updates notify, and then observe
 // changes; maybe replumb plugin list through plugin service?
 // <http://crbug.com/39101>
-class PluginsDOMHandler : public DOMMessageHandler,
+class PluginsDOMHandler : public WebUIMessageHandler,
                           public NotificationObserver {
  public:
   explicit PluginsDOMHandler();
   virtual ~PluginsDOMHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback for the "requestPluginsData" message.
@@ -151,6 +151,12 @@
   // the security model.
   void HandleShowTermsOfServiceMessage(const ListValue* args);
 
+  // Callback for the "saveShowDetailsToPrefs" message.
+  void HandleSaveShowDetailsToPrefs(const ListValue* args);
+
+  // Calback for the "getShowDetails" message.
+  void HandleGetShowDetails(const ListValue* args);
+
   // NotificationObserver method overrides
   void Observe(NotificationType type,
                const NotificationSource& source,
@@ -179,6 +185,10 @@
 
   ScopedRunnableMethodFactory<PluginsDOMHandler> get_plugins_factory_;
 
+  // This pref guards the value whether about:plugins is in the details mode or
+  // not.
+  BooleanPrefMember show_details_;
+
   DISALLOW_COPY_AND_ASSIGN(PluginsDOMHandler);
 };
 
@@ -189,13 +199,25 @@
                  NotificationService::AllSources());
 }
 
+WebUIMessageHandler* PluginsDOMHandler::Attach(WebUI* web_ui) {
+  PrefService* prefs = web_ui->GetProfile()->GetPrefs();
+
+  show_details_.Init(prefs::kPluginsShowDetails, prefs, this);
+
+  return WebUIMessageHandler::Attach(web_ui);
+}
+
 void PluginsDOMHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("requestPluginsData",
+  web_ui_->RegisterMessageCallback("requestPluginsData",
       NewCallback(this, &PluginsDOMHandler::HandleRequestPluginsData));
-  dom_ui_->RegisterMessageCallback("enablePlugin",
+  web_ui_->RegisterMessageCallback("enablePlugin",
       NewCallback(this, &PluginsDOMHandler::HandleEnablePluginMessage));
-  dom_ui_->RegisterMessageCallback("showTermsOfService",
+  web_ui_->RegisterMessageCallback("showTermsOfService",
       NewCallback(this, &PluginsDOMHandler::HandleShowTermsOfServiceMessage));
+  web_ui_->RegisterMessageCallback("saveShowDetailsToPrefs",
+      NewCallback(this, &PluginsDOMHandler::HandleSaveShowDetailsToPrefs));
+  web_ui_->RegisterMessageCallback("getShowDetails",
+      NewCallback(this, &PluginsDOMHandler::HandleGetShowDetails));
 }
 
 void PluginsDOMHandler::HandleRequestPluginsData(const ListValue* args) {
@@ -237,23 +259,37 @@
     if (!args->GetString(0, &file_path))
       return;
 
-    plugin_updater->EnablePluginFile(enable, file_path);
+    plugin_updater->EnablePlugin(enable, file_path);
   }
 
   // TODO(viettrungluu): We might also want to ensure that the plugins
   // list is always written to prefs even when the user hasn't disabled a
   // plugin. <http://crbug.com/39101>
-  plugin_updater->UpdatePreferences(dom_ui_->GetProfile(), 0);
+  plugin_updater->UpdatePreferences(web_ui_->GetProfile(), 0);
 }
 
 void PluginsDOMHandler::HandleShowTermsOfServiceMessage(const ListValue* args) {
   // Show it in a new browser window....
-  Browser* browser = Browser::Create(dom_ui_->GetProfile());
+  Browser* browser = Browser::Create(web_ui_->GetProfile());
   browser->OpenURL(GURL(chrome::kAboutTermsURL),
                    GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
   browser->window()->Show();
 }
 
+void PluginsDOMHandler::HandleSaveShowDetailsToPrefs(const ListValue* args) {
+  std::string details_mode;
+  if (!args->GetString(0, &details_mode)) {
+    NOTREACHED();
+    return;
+  }
+  show_details_.SetValue(details_mode == "true");
+}
+
+void PluginsDOMHandler::HandleGetShowDetails(const ListValue* args) {
+  FundamentalValue show_details(show_details_.GetValue());
+  web_ui_->CallJavascriptFunction(L"loadShowDetailsFromPrefs", show_details);
+}
+
 void PluginsDOMHandler::Observe(NotificationType type,
                                 const NotificationSource& source,
                                 const NotificationDetails& details) {
@@ -296,7 +332,7 @@
   DictionaryValue results;
   results.Set("plugins", wrapper->list);
   wrapper->list = NULL;  // So it doesn't get deleted.
-  dom_ui_->CallJavascriptFunction(L"returnPluginsData", results);
+  web_ui_->CallJavascriptFunction(L"returnPluginsData", results);
 }
 
 }  // namespace
@@ -307,17 +343,13 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-PluginsUI::PluginsUI(TabContents* contents) : DOMUI(contents) {
+PluginsUI::PluginsUI(TabContents* contents) : WebUI(contents) {
   AddMessageHandler((new PluginsDOMHandler())->Attach(this));
 
   PluginsUIHTMLSource* html_source = new PluginsUIHTMLSource();
 
   // Set up the chrome://plugins/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 
@@ -337,4 +369,6 @@
   prefs->RegisterListPref(prefs::kPluginsPluginsBlacklist);
   prefs->RegisterListPref(prefs::kPluginsPluginsList);
   prefs->RegisterBooleanPref(prefs::kPluginsEnabledInternalPDF, false);
+  prefs->RegisterBooleanPref(prefs::kPluginsShowDetails, false);
+  prefs->RegisterBooleanPref(prefs::kPluginsShowSetReaderDefaultInfobar, true);
 }
diff --git a/chrome/browser/dom_ui/plugins_ui.h b/chrome/browser/dom_ui/plugins_ui.h
index d2813a8..8ce0e62 100644
--- a/chrome/browser/dom_ui/plugins_ui.h
+++ b/chrome/browser/dom_ui/plugins_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_DOM_UI_PLUGINS_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class PrefService;
 class RefCountedMemory;
 
-class PluginsUI : public DOMUI {
+class PluginsUI : public WebUI {
  public:
   explicit PluginsUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/print_preview_handler.cc b/chrome/browser/dom_ui/print_preview_handler.cc
index cee9be4..80e53fb 100644
--- a/chrome/browser/dom_ui/print_preview_handler.cc
+++ b/chrome/browser/dom_ui/print_preview_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,18 +15,10 @@
 }
 
 void PrintPreviewHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getPreview",
-      NewCallback(this, &PrintPreviewHandler::HandleGetPreview));
-  dom_ui_->RegisterMessageCallback("getPrinters",
+  web_ui_->RegisterMessageCallback("getPrinters",
       NewCallback(this, &PrintPreviewHandler::HandleGetPrinters));
 }
 
-void PrintPreviewHandler::HandleGetPreview(const ListValue*) {
-  // TODO(thestig) Hook this up properly when PDF generation works.
-  StringValue dummy_url("chrome://print/dummy.pdf");
-  dom_ui_->CallJavascriptFunction(L"createPDFPlugin", dummy_url);
-}
-
 void PrintPreviewHandler::HandleGetPrinters(const ListValue*) {
   ListValue printers;
 
@@ -37,5 +29,5 @@
     printers.Append(new StringValue(index->printer_name));
   }
 
-  dom_ui_->CallJavascriptFunction(L"setPrinters", printers);
+  web_ui_->CallJavascriptFunction(L"setPrinters", printers);
 }
diff --git a/chrome/browser/dom_ui/print_preview_handler.h b/chrome/browser/dom_ui/print_preview_handler.h
index b5d454d..4149146 100644
--- a/chrome/browser/dom_ui/print_preview_handler.h
+++ b/chrome/browser/dom_ui/print_preview_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,29 +6,26 @@
 #define CHROME_BROWSER_DOM_UI_PRINT_PREVIEW_HANDLER_H_
 #pragma once
 
-#include "base/scoped_ptr.h"
+#include "base/ref_counted.h"
 #include "base/weak_ptr.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 namespace printing {
 class PrintBackend;
-}  // namespace printing
+}
 
 // The handler for Javascript messages related to the "print preview" dialog.
-class PrintPreviewHandler : public DOMMessageHandler,
+class PrintPreviewHandler : public WebUIMessageHandler,
                             public base::SupportsWeakPtr<PrintPreviewHandler> {
  public:
   PrintPreviewHandler();
   virtual ~PrintPreviewHandler();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
  private:
-  // Get the PDF preview and refresh the PDF plugin. |args| is unused.
-  void HandleGetPreview(const ListValue* args);
-
-  // Get the list of printers and send it to the DOM UI. |args| is unused.
+  // Get the list of printers and send it to the Web UI. |args| is unused.
   void HandleGetPrinters(const ListValue* args);
 
   // Pointer to current print system.
diff --git a/chrome/browser/dom_ui/print_preview_ui.cc b/chrome/browser/dom_ui/print_preview_ui.cc
index f0f7656..688ec81 100644
--- a/chrome/browser/dom_ui/print_preview_ui.cc
+++ b/chrome/browser/dom_ui/print_preview_ui.cc
@@ -1,149 +1,35 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/print_preview_ui.h"
 
-#include <algorithm>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/message_loop.h"
-#include "base/singleton.h"
-#include "base/string_piece.h"
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
 #include "chrome/browser/dom_ui/print_preview_handler.h"
+#include "chrome/browser/dom_ui/print_preview_ui_html_source.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/jstemplate_builder.h"
-#include "chrome/common/url_constants.h"
 
-#include "grit/browser_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-void SetLocalizedStrings(DictionaryValue* localized_strings) {
-  localized_strings->SetString(std::string("title"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_TITLE));
-  localized_strings->SetString(std::string("loading"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_LOADING));
-  localized_strings->SetString(std::string("noPlugin"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_NO_PLUGIN));
-  localized_strings->SetString(std::string("noPrinter"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_NO_PRINTER));
-
-  localized_strings->SetString(std::string("printButton"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_PRINT_BUTTON));
-  localized_strings->SetString(std::string("cancelButton"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_CANCEL_BUTTON));
-
-  localized_strings->SetString(std::string("optionAllPages"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_ALL_PAGES));
-  localized_strings->SetString(std::string("optionBw"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_BW));
-  localized_strings->SetString(std::string("optionCollate"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_COLLATE));
-  localized_strings->SetString(std::string("optionColor"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_COLOR));
-  localized_strings->SetString(std::string("optionLandscape"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_LANDSCAPE));
-  localized_strings->SetString(std::string("optionPortrait"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_PORTRAIT));
-  localized_strings->SetString(std::string("optionTwoSided"),
-      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_TWO_SIDED));
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// PrintPreviewUIHTMLSource
-//
-////////////////////////////////////////////////////////////////////////////////
-
-class PrintPreviewUIHTMLSource : public ChromeURLDataManager::DataSource {
- public:
-  PrintPreviewUIHTMLSource();
-  virtual ~PrintPreviewUIHTMLSource();
-
-  // Called when the network layer has requested a resource underneath
-  // the path we registered.
-  virtual void StartDataRequest(const std::string& path,
-                                bool is_off_the_record,
-                                int request_id);
-  virtual std::string GetMimeType(const std::string&) const;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PrintPreviewUIHTMLSource);
-};
-
-PrintPreviewUIHTMLSource::PrintPreviewUIHTMLSource()
-    : DataSource(chrome::kChromeUIPrintHost, MessageLoop::current()) {
-}
-
-PrintPreviewUIHTMLSource::~PrintPreviewUIHTMLSource() {}
-
-void PrintPreviewUIHTMLSource::StartDataRequest(const std::string& path,
-                                                bool is_off_the_record,
-                                                int request_id) {
-  // Print Preview Index page.
-  if (path.empty()) {
-    DictionaryValue localized_strings;
-    SetLocalizedStrings(&localized_strings);
-    SetFontAndTextDirection(&localized_strings);
-
-    static const base::StringPiece print_html(
-        ResourceBundle::GetSharedInstance().GetRawDataResource(
-            IDR_PRINT_PREVIEW_HTML));
-    const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
-        print_html, &localized_strings);
-
-    scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
-    html_bytes->data.resize(full_html.size());
-    std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
-
-    SendResponse(request_id, html_bytes);
-    return;
-  }
-
-  // Print Preview data.
-  NOTIMPLEMENTED() << "No PDF for you";
-  scoped_refptr<RefCountedBytes> data_bytes(new RefCountedBytes);
-  SendResponse(request_id, data_bytes);
-}
-
-std::string PrintPreviewUIHTMLSource::GetMimeType(
-    const std::string& path) const {
-  // Print Preview Index page.
-  if (path.empty())
-    return "text/html";
-  // Print Preview data.
-  return "application/pdf";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// PrintPreviewUI
-//
-////////////////////////////////////////////////////////////////////////////////
-
-PrintPreviewUI::PrintPreviewUI(TabContents* contents) : DOMUI(contents) {
+PrintPreviewUI::PrintPreviewUI(TabContents* contents)
+    : WebUI(contents),
+      html_source_(new PrintPreviewUIHTMLSource()) {
   // PrintPreviewUI owns |handler|.
   PrintPreviewHandler* handler = new PrintPreviewHandler();
   AddMessageHandler(handler->Attach(this));
 
   // Set up the chrome://print/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new PrintPreviewUIHTMLSource())));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source_);
 }
 
 PrintPreviewUI::~PrintPreviewUI() {
 }
+
+PrintPreviewUIHTMLSource* PrintPreviewUI::html_source() {
+  return html_source_.get();
+}
+
+void PrintPreviewUI::PreviewDataIsAvailable() {
+  StringValue dummy_url("chrome://print/print.pdf");
+  CallJavascriptFunction(L"createPDFPlugin", dummy_url);
+}
diff --git a/chrome/browser/dom_ui/print_preview_ui.h b/chrome/browser/dom_ui/print_preview_ui.h
index 5745856..8367695 100644
--- a/chrome/browser/dom_ui/print_preview_ui.h
+++ b/chrome/browser/dom_ui/print_preview_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,16 +6,24 @@
 #define CHROME_BROWSER_DOM_UI_PRINT_PREVIEW_UI_H_
 #pragma once
 
-#include <string>
+#include "base/ref_counted.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+class PrintPreviewUIHTMLSource;
 
-class PrintPreviewUI : public DOMUI {
+class PrintPreviewUI : public WebUI {
  public:
   explicit PrintPreviewUI(TabContents* contents);
   virtual ~PrintPreviewUI();
 
+  PrintPreviewUIHTMLSource* html_source();
+
+  // Notify the Web UI renderer that preview data is available.
+  void PreviewDataIsAvailable();
+
  private:
+  scoped_refptr<PrintPreviewUIHTMLSource> html_source_;
+
   DISALLOW_COPY_AND_ASSIGN(PrintPreviewUI);
 };
 
diff --git a/chrome/browser/dom_ui/print_preview_ui_html_source.cc b/chrome/browser/dom_ui/print_preview_ui_html_source.cc
new file mode 100644
index 0000000..f46771f
--- /dev/null
+++ b/chrome/browser/dom_ui/print_preview_ui_html_source.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/print_preview_ui_html_source.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/shared_memory.h"
+#include "base/string_piece.h"
+#include "base/values.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/url_constants.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+void SetLocalizedStrings(DictionaryValue* localized_strings) {
+  localized_strings->SetString(std::string("title"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_TITLE));
+  localized_strings->SetString(std::string("loading"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_LOADING));
+  localized_strings->SetString(std::string("noPlugin"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_NO_PLUGIN));
+  localized_strings->SetString(std::string("noPrinter"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_NO_PRINTER));
+
+  localized_strings->SetString(std::string("printButton"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_PRINT_BUTTON));
+  localized_strings->SetString(std::string("cancelButton"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_CANCEL_BUTTON));
+
+  localized_strings->SetString(std::string("optionAllPages"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_ALL_PAGES));
+  localized_strings->SetString(std::string("optionBw"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_BW));
+  localized_strings->SetString(std::string("optionCollate"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_COLLATE));
+  localized_strings->SetString(std::string("optionColor"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_COLOR));
+  localized_strings->SetString(std::string("optionLandscape"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_LANDSCAPE));
+  localized_strings->SetString(std::string("optionPortrait"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_PORTRAIT));
+  localized_strings->SetString(std::string("optionTwoSided"),
+      l10n_util::GetStringUTF8(IDS_PRINT_PREVIEW_OPTION_TWO_SIDED));
+}
+
+}  // namespace
+
+PrintPreviewUIHTMLSource::PrintPreviewUIHTMLSource()
+    : DataSource(chrome::kChromeUIPrintHost, MessageLoop::current()),
+      data_(std::make_pair(static_cast<base::SharedMemory*>(NULL), 0U)) {
+}
+
+PrintPreviewUIHTMLSource::~PrintPreviewUIHTMLSource() {
+  delete data_.first;
+}
+
+void PrintPreviewUIHTMLSource::GetPrintPreviewData(PrintPreviewData* data) {
+  *data = data_;
+}
+
+void PrintPreviewUIHTMLSource::SetPrintPreviewData(
+    const PrintPreviewData& data) {
+  delete data_.first;
+  data_ = data;
+}
+
+void PrintPreviewUIHTMLSource::StartDataRequest(const std::string& path,
+                                                bool is_off_the_record,
+                                                int request_id) {
+  if (path.empty()) {
+    // Print Preview Index page.
+    DictionaryValue localized_strings;
+    SetLocalizedStrings(&localized_strings);
+    SetFontAndTextDirection(&localized_strings);
+
+    static const base::StringPiece print_html(
+        ResourceBundle::GetSharedInstance().GetRawDataResource(
+            IDR_PRINT_PREVIEW_HTML));
+    const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
+        print_html, &localized_strings);
+
+    scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
+    html_bytes->data.resize(full_html.size());
+    std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
+
+    SendResponse(request_id, html_bytes);
+    return;
+  } else if (path == "print.pdf" && data_.first) {
+    // Print Preview data.
+    char* preview_data = reinterpret_cast<char*>(data_.first->memory());
+    uint32 preview_data_size = data_.second;
+
+    scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
+    html_bytes->data.resize(preview_data_size);
+    std::vector<unsigned char>::iterator it = html_bytes->data.begin();
+    for (uint32 i = 0; i < preview_data_size; ++i, ++it)
+      *it = *(preview_data + i);
+    SendResponse(request_id, html_bytes);
+    return;
+  } else {
+    // Invalid request.
+    scoped_refptr<RefCountedBytes> empty_bytes(new RefCountedBytes);
+    SendResponse(request_id, empty_bytes);
+    return;
+  }
+}
+
+std::string PrintPreviewUIHTMLSource::GetMimeType(
+    const std::string& path) const {
+  // Print Preview Index page.
+  if (path.empty())
+    return "text/html";
+  // Print Preview data.
+  return "application/pdf";
+}
diff --git a/chrome/browser/dom_ui/print_preview_ui_html_source.h b/chrome/browser/dom_ui/print_preview_ui_html_source.h
new file mode 100644
index 0000000..6b6f42e
--- /dev/null
+++ b/chrome/browser/dom_ui/print_preview_ui_html_source.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOM_UI_PRINT_PREVIEW_UI_HTML_SOURCE_H_
+#define CHROME_BROWSER_DOM_UI_PRINT_PREVIEW_UI_HTML_SOURCE_H_
+#pragma once
+
+#include <string>
+#include <utility>
+
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+
+namespace base {
+class SharedMemory;
+}
+
+class PrintPreviewUIHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+  // A SharedMemory that contains the data for print preview,
+  // and the size of the print preview data in bytes.
+  typedef std::pair<base::SharedMemory*, uint32> PrintPreviewData;
+
+  PrintPreviewUIHTMLSource();
+  virtual ~PrintPreviewUIHTMLSource();
+
+  // Gets the print preview |data|. The data is valid as long as the
+  // PrintPreviewHandler is valid and SetPrintPreviewData() does not get called.
+  void GetPrintPreviewData(PrintPreviewData* data);
+
+  // Sets the print preview |data|. PrintPreviewHandler owns the data and is
+  // responsible for freeing it when either:
+  // a) there is new data.
+  // b) when PrintPreviewHandler is destroyed.
+  void SetPrintPreviewData(const PrintPreviewData& data);
+
+  // ChromeURLDataManager::DataSource implementation.
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+  virtual std::string GetMimeType(const std::string&) const;
+
+ private:
+  // Current print preview data, the contents of which are owned by
+  // PrintPreviewHandler.
+  PrintPreviewData data_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrintPreviewUIHTMLSource);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_PRINT_PREVIEW_UI_HTML_SOURCE_H_
diff --git a/chrome/browser/dom_ui/print_preview_ui_html_source_unittest.cc b/chrome/browser/dom_ui/print_preview_ui_html_source_unittest.cc
new file mode 100644
index 0000000..0dc4646
--- /dev/null
+++ b/chrome/browser/dom_ui/print_preview_ui_html_source_unittest.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2011 The Chromium 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/command_line.h"
+#include "base/shared_memory.h"
+#include "chrome/browser/dom_ui/print_preview_ui.h"
+#include "chrome/browser/dom_ui/print_preview_ui_html_source.h"
+#include "chrome/browser/printing/print_preview_tab_controller.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/browser_with_test_window_test.h"
+#include "chrome/test/testing_profile.h"
+
+typedef BrowserWithTestWindowTest PrintPreviewUIHTMLSourceTest;
+
+// Create/Get a preview tab for initiator tab.
+TEST_F(PrintPreviewUIHTMLSourceTest, PrintPreviewData) {
+  // TODO(thestig) Remove when print preview is enabled by default.
+  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnablePrintPreview);
+  ASSERT_TRUE(browser());
+  BrowserList::SetLastActive(browser());
+  ASSERT_TRUE(BrowserList::GetLastActive());
+
+  browser()->NewTab();
+  TabContents* initiator_tab = browser()->GetSelectedTabContents();
+  ASSERT_TRUE(initiator_tab);
+
+  scoped_refptr<printing::PrintPreviewTabController>
+      controller(new printing::PrintPreviewTabController());
+  ASSERT_TRUE(controller);
+
+  TabContents* preview_tab = controller->GetOrCreatePreviewTab(
+      initiator_tab, initiator_tab->controller().window_id().id());
+
+  EXPECT_NE(initiator_tab, preview_tab);
+  EXPECT_EQ(2, browser()->tab_count());
+
+  PrintPreviewUI* preview_ui =
+      reinterpret_cast<PrintPreviewUI*>(preview_tab->web_ui());
+  ASSERT_TRUE(preview_ui != NULL);
+  PrintPreviewUIHTMLSource* html_source = preview_ui->html_source();
+
+  PrintPreviewUIHTMLSource::PrintPreviewData data;
+  html_source->GetPrintPreviewData(&data);
+  EXPECT_EQ(NULL, data.first);
+  EXPECT_EQ(0U, data.second);
+
+  PrintPreviewUIHTMLSource::PrintPreviewData dummy_data =
+      std::make_pair(new base::SharedMemory(), 1234);
+
+  html_source->SetPrintPreviewData(dummy_data);
+  html_source->GetPrintPreviewData(&data);
+  EXPECT_EQ(dummy_data, data);
+
+  // This should not cause any memory leaks.
+  dummy_data.first = new base::SharedMemory();
+  html_source->SetPrintPreviewData(dummy_data);
+}
diff --git a/chrome/browser/dom_ui/print_preview_ui_uitest.cc b/chrome/browser/dom_ui/print_preview_ui_uitest.cc
index 4be0a28..33dd66e 100644
--- a/chrome/browser/dom_ui/print_preview_ui_uitest.cc
+++ b/chrome/browser/dom_ui/print_preview_ui_uitest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -11,8 +10,8 @@
 #include "chrome/test/automation/browser_proxy.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -47,7 +46,8 @@
   AssertIsPrintPage(tab);
 }
 
-TEST_F(PrintPreviewUITest, PrintCommandDisabled) {
+// Flaky on interactive tests builder. See http://crbug.com/69389
+TEST_F(PrintPreviewUITest, FLAKY_PrintCommandDisabled) {
   scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser.get());
 
diff --git a/chrome/browser/dom_ui/remoting_ui.cc b/chrome/browser/dom_ui/remoting_ui.cc
index 0bdb717..e849bb0 100644
--- a/chrome/browser/dom_ui/remoting_ui.cc
+++ b/chrome/browser/dom_ui/remoting_ui.cc
@@ -1,15 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/remoting_ui.h"
 
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/url_constants.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -60,15 +62,11 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-RemotingUI::RemotingUI(TabContents* contents) : DOMUI(contents) {
+RemotingUI::RemotingUI(TabContents* contents) : WebUI(contents) {
   RemotingUIHTMLSource* html_source = new RemotingUIHTMLSource();
 
   // Set up the chrome://remoting source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 
diff --git a/chrome/browser/dom_ui/remoting_ui.h b/chrome/browser/dom_ui/remoting_ui.h
index 8012a82..9c25513 100644
--- a/chrome/browser/dom_ui/remoting_ui.h
+++ b/chrome/browser/dom_ui/remoting_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_DOM_UI_REMOTING_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class PrefService;
 class RefCountedMemory;
 
-class RemotingUI : public DOMUI {
+class RemotingUI : public WebUI {
  public:
   explicit RemotingUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/settings_browsertest.cc b/chrome/browser/dom_ui/settings_browsertest.cc
new file mode 100644
index 0000000..9f63ada
--- /dev/null
+++ b/chrome/browser/dom_ui/settings_browsertest.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_browsertest.h"
+#include "chrome/browser/dom_ui/options/core_options_handler.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/ui_test_utils.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::StrictMock;
+using ::testing::_;
+
+MATCHER_P(Eq_ListValue, inList, "") {
+  return arg->Equals(inList);
+}
+
+class MockCoreOptionsHandler : public CoreOptionsHandler {
+ public:
+  MOCK_METHOD1(HandleInitialize,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleFetchPrefs,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleObservePrefs,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleSetBooleanPref,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleSetIntegerPref,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleSetDoublePref,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleSetStringPref,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleSetObjectPref,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleClearPref,
+      void(const ListValue* args));
+  MOCK_METHOD1(HandleUserMetricsAction,
+      void(const ListValue* args));
+
+  virtual void RegisterMessages() {
+    web_ui_->RegisterMessageCallback("coreOptionsInitialize",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleInitialize));
+    web_ui_->RegisterMessageCallback("fetchPrefs",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleFetchPrefs));
+    web_ui_->RegisterMessageCallback("observePrefs",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleObservePrefs));
+    web_ui_->RegisterMessageCallback("setBooleanPref",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleSetBooleanPref));
+    web_ui_->RegisterMessageCallback("setIntegerPref",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleSetIntegerPref));
+    web_ui_->RegisterMessageCallback("setDoublePref",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleSetDoublePref));
+    web_ui_->RegisterMessageCallback("setStringPref",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleSetStringPref));
+    web_ui_->RegisterMessageCallback("setObjectPref",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleSetObjectPref));
+    web_ui_->RegisterMessageCallback("clearPref",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleClearPref));
+    web_ui_->RegisterMessageCallback("coreOptionsUserMetricsAction",
+        NewCallback(this, &MockCoreOptionsHandler ::HandleUserMetricsAction));
+  }
+};
+
+class SettingsWebUITest : public WebUIBrowserTest {
+ protected:
+  virtual WebUIMessageHandler* GetMockMessageHandler() {
+    return &mock_core_options_handler_;
+  }
+
+  StrictMock<MockCoreOptionsHandler> mock_core_options_handler_;
+};
+
+// Test the end to end js to WebUI handler code path for
+// the message setBooleanPref.
+// TODO(dtseng): add more EXPECT_CALL's when updating js test.
+IN_PROC_BROWSER_TEST_F(SettingsWebUITest, TestSetBooleanPrefTriggers) {
+  // This serves as an example of a very constrained test.
+  ListValue true_list_value;
+  true_list_value.Append(Value::CreateStringValue("browser.show_home_button"));
+  true_list_value.Append(Value::CreateBooleanValue(true));
+  true_list_value.Append(
+      Value::CreateStringValue("Options_Homepage_HomeButton"));
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUISettingsURL));
+  EXPECT_CALL(mock_core_options_handler_,
+      HandleSetBooleanPref(Eq_ListValue(&true_list_value)));
+  ASSERT_TRUE(RunWebUITest(
+      FILE_PATH_LITERAL("settings_set_boolean_pref_triggers.js")));
+}
+
diff --git a/chrome/browser/dom_ui/shared_resources_data_source.cc b/chrome/browser/dom_ui/shared_resources_data_source.cc
index 709b33c..167a67a 100644
--- a/chrome/browser/dom_ui/shared_resources_data_source.cc
+++ b/chrome/browser/dom_ui/shared_resources_data_source.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_thread.h"
@@ -19,6 +18,7 @@
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/mime_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -32,6 +32,8 @@
     idr = IDR_FOLDER_OPEN;
   } else if (path == "app/resources/folder_open_rtl.png") {
     idr = IDR_FOLDER_OPEN_RTL;
+  } else if (path == "app/resources/throbber.png") {
+    idr = IDR_THROBBER;
   } else {
     // The name of the files in the grd list are prefixed with the following
     // directory:
@@ -51,17 +53,6 @@
 
 }  // namespace
 
-// static
-void SharedResourcesDataSource::Register() {
-  SharedResourcesDataSource* source = new SharedResourcesDataSource();
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(source)));
-}
-
 SharedResourcesDataSource::SharedResourcesDataSource()
     : DataSource(chrome::kChromeUIResourcesHost, NULL) {
 }
diff --git a/chrome/browser/dom_ui/shared_resources_data_source.h b/chrome/browser/dom_ui/shared_resources_data_source.h
index a162b43..1aec881 100644
--- a/chrome/browser/dom_ui/shared_resources_data_source.h
+++ b/chrome/browser/dom_ui/shared_resources_data_source.h
@@ -18,8 +18,7 @@
 // A DataSource for chrome://resources/ URLs.
 class SharedResourcesDataSource : public ChromeURLDataManager::DataSource {
  public:
-  // Registers an instance of this data source with the ChromeUrlDataManager.
-  static void Register();
+  SharedResourcesDataSource();
 
   // Overridden from ChromeURLDataManager::DataSource:
   virtual void StartDataRequest(const std::string& path,
@@ -28,7 +27,6 @@
   virtual std::string GetMimeType(const std::string&) const;
 
  private:
-  SharedResourcesDataSource();
   ~SharedResourcesDataSource();
 
   DISALLOW_COPY_AND_ASSIGN(SharedResourcesDataSource);
diff --git a/chrome/browser/dom_ui/shown_sections_handler.cc b/chrome/browser/dom_ui/shown_sections_handler.cc
index 6a2e3ca..96afe93 100644
--- a/chrome/browser/dom_ui/shown_sections_handler.cc
+++ b/chrome/browser/dom_ui/shown_sections_handler.cc
@@ -1,9 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/shown_sections_handler.h"
 
+#include <string>
+
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/string_number_conversions.h"
@@ -11,7 +13,6 @@
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_type.h"
@@ -24,8 +25,8 @@
 // TODO(aa): Needs to be updated to match newest NTP - http://crbug.com/57440
 void NotifySectionDisabled(int new_mode, int old_mode, Profile *profile) {
   // If the oldmode HAD either thumbs or lists visible.
-  bool old_had_it = (old_mode & THUMB) && !(old_mode & MINIMIZED_THUMB);
-  bool new_has_it = (new_mode & THUMB) && !(new_mode & MINIMIZED_THUMB);
+  bool old_had_it = (old_mode & THUMB) && !(old_mode & MENU_THUMB);
+  bool new_has_it = (new_mode & THUMB) && !(new_mode & MENU_THUMB);
 
   if (old_had_it && !new_has_it) {
     UserMetrics::RecordAction(
@@ -47,6 +48,15 @@
   return prefs->GetInteger(prefs::kNTPShownSections);
 }
 
+// static
+void ShownSectionsHandler::SetShownSection(PrefService* prefs,
+                                           Section section) {
+  int shown_sections = GetShownSections(prefs);
+  shown_sections &= ~ALL_SECTIONS_MASK;
+  shown_sections |= section;
+  prefs->SetInteger(prefs::kNTPShownSections, shown_sections);
+}
+
 ShownSectionsHandler::ShownSectionsHandler(PrefService* pref_service)
     : pref_service_(pref_service) {
   pref_registrar_.Init(pref_service);
@@ -54,9 +64,9 @@
 }
 
 void ShownSectionsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getShownSections",
+  web_ui_->RegisterMessageCallback("getShownSections",
       NewCallback(this, &ShownSectionsHandler::HandleGetShownSections));
-  dom_ui_->RegisterMessageCallback("setShownSections",
+  web_ui_->RegisterMessageCallback("setShownSections",
       NewCallback(this, &ShownSectionsHandler::HandleSetShownSections));
 }
 
@@ -68,7 +78,7 @@
     DCHECK(*pref_name == prefs::kNTPShownSections);
     int sections = pref_service_->GetInteger(prefs::kNTPShownSections);
     FundamentalValue sections_value(sections);
-    dom_ui_->CallJavascriptFunction(L"setShownSections", sections_value);
+    web_ui_->CallJavascriptFunction(L"setShownSections", sections_value);
   } else {
     NOTREACHED();
   }
@@ -77,16 +87,17 @@
 void ShownSectionsHandler::HandleGetShownSections(const ListValue* args) {
   int sections = GetShownSections(pref_service_);
   FundamentalValue sections_value(sections);
-  dom_ui_->CallJavascriptFunction(L"onShownSections", sections_value);
+  web_ui_->CallJavascriptFunction(L"onShownSections", sections_value);
 }
 
 void ShownSectionsHandler::HandleSetShownSections(const ListValue* args) {
-  int mode;
-  CHECK(ExtractIntegerValue(args, &mode));
+  double mode_double;
+  CHECK(args->GetDouble(0, &mode_double));
+  int mode = static_cast<int>(mode_double);
   int old_mode = pref_service_->GetInteger(prefs::kNTPShownSections);
 
   if (old_mode != mode) {
-    NotifySectionDisabled(mode, old_mode, dom_ui_->GetProfile());
+    NotifySectionDisabled(mode, old_mode, web_ui_->GetProfile());
     pref_service_->SetInteger(prefs::kNTPShownSections, mode);
   }
 }
@@ -96,7 +107,7 @@
 #if defined(OS_CHROMEOS)
   // Default to have expanded APPS and all other secions are minimized.
   pref_service->RegisterIntegerPref(prefs::kNTPShownSections,
-                                    APPS | MINIMIZED_THUMB | MINIMIZED_RECENT);
+                                    APPS | MENU_THUMB | MENU_RECENT);
 #else
   pref_service->RegisterIntegerPref(prefs::kNTPShownSections, THUMB);
 #endif
@@ -137,8 +148,8 @@
   if (extension->is_app()) {
     int mode = prefs->GetInteger(prefs::kNTPShownSections);
 
-    // De-minimize the apps section.
-    mode &= ~MINIMIZED_APPS;
+    // De-menu-mode the apps section.
+    mode &= ~MENU_APPS;
 
     // Hide any open sections.
     mode &= ~ALL_SECTIONS_MASK;
diff --git a/chrome/browser/dom_ui/shown_sections_handler.h b/chrome/browser/dom_ui/shown_sections_handler.h
index ad227b4..5fa0776 100644
--- a/chrome/browser/dom_ui/shown_sections_handler.h
+++ b/chrome/browser/dom_ui/shown_sections_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,10 @@
 #define CHROME_BROWSER_DOM_UI_SHOWN_SECTIONS_HANDLER_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 
-class DOMUI;
 class Extension;
 class Value;
 class PrefService;
@@ -24,17 +23,17 @@
   THUMB = 1 << 0,
   APPS = 1 << 6,
 
-  // We use the low 16 bits for sections, the high 16 bits for minimized state.
+  // We use the low 16 bits for sections, the high 16 bits for menu mode.
   ALL_SECTIONS_MASK = 0x0000FFFF,
 
-  // If one of these is set, then the corresponding section is shown minimized
+  // If one of these is set, then the corresponding section is shown in a menu
   // at the bottom of the NTP and no data is directly visible on the NTP.
-  MINIMIZED_THUMB = 1 << (0 + 16),
-  MINIMIZED_RECENT = 1 << (2 + 16),
-  MINIMIZED_APPS = 1 << (6 + 16),
+  MENU_THUMB = 1 << (0 + 16),
+  MENU_RECENT = 1 << (2 + 16),
+  MENU_APPS = 1 << (6 + 16),
 };
 
-class ShownSectionsHandler : public DOMMessageHandler,
+class ShownSectionsHandler : public WebUIMessageHandler,
                              public NotificationObserver {
  public:
   explicit ShownSectionsHandler(PrefService* pref_service);
@@ -43,7 +42,11 @@
   // Helper to get the current shown sections.
   static int GetShownSections(PrefService* pref_service);
 
-  // DOMMessageHandler implementation.
+  // Expands |section|, collapsing any previously expanded section. This is the
+  // same thing that happens if a user clicks on |section|.
+  static void SetShownSection(PrefService* prefs, Section section);
+
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // NotificationObserver implementation.
diff --git a/chrome/browser/dom_ui/slideshow_ui.cc b/chrome/browser/dom_ui/slideshow_ui.cc
index a086372..5552e6a 100644
--- a/chrome/browser/dom_ui/slideshow_ui.cc
+++ b/chrome/browser/dom_ui/slideshow_ui.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/dom_ui/slideshow_ui.h"
 
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
@@ -17,7 +16,7 @@
 #include "base/values.h"
 #include "base/weak_ptr.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/profiles/profile.h"
@@ -25,13 +24,13 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
-#include "net/base/escape.h"
-#include "net/base/directory_lister.h"
-
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "net/base/escape.h"
+#include "net/base/directory_lister.h"
+#include "ui/base/resource/resource_bundle.h"
 
 static const char kPropertyPath[] = "path";
 static const char kPropertyTitle[] = "title";
@@ -59,7 +58,7 @@
 
 // The handler for Javascript messages related to the "slideshow" view.
 class SlideshowHandler : public net::DirectoryLister::DirectoryListerDelegate,
-                         public DOMMessageHandler,
+                         public WebUIMessageHandler,
                          public base::SupportsWeakPtr<SlideshowHandler> {
  public:
   SlideshowHandler();
@@ -73,8 +72,8 @@
       const net::DirectoryLister::DirectoryListerData& data);
   virtual void OnListDone(int error);
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   void GetChildrenForPath(const FilePath& path, bool is_refresh);
@@ -148,25 +147,21 @@
   }
 }
 
-DOMMessageHandler* SlideshowHandler::Attach(DOMUI* dom_ui) {
+WebUIMessageHandler* SlideshowHandler::Attach(WebUI* web_ui) {
+  profile_ = web_ui->GetProfile();
   // Create our favicon data source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
-  profile_ = dom_ui->GetProfile();
-  return DOMMessageHandler::Attach(dom_ui);
+  profile_->GetChromeURLDataManager()->AddDataSource(
+      new WebUIFavIconSource(profile_));
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void SlideshowHandler::Init() {
 }
 
 void SlideshowHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getChildren",
+  web_ui_->RegisterMessageCallback("getChildren",
       NewCallback(this, &SlideshowHandler::HandleGetChildren));
-  dom_ui_->RegisterMessageCallback("refreshDirectory",
+  web_ui_->RegisterMessageCallback("refreshDirectory",
       NewCallback(this, &SlideshowHandler::HandleRefreshDirectory));
 }
 
@@ -268,7 +263,7 @@
     info_value.SetString("functionCall", "getChildren");
   }
   info_value.SetString(kPropertyPath, currentpath_.value());
-  dom_ui_->CallJavascriptFunction(L"browseFileResult",
+  web_ui_->CallJavascriptFunction(L"browseFileResult",
                                   info_value, *(filelist_value_.get()));
 }
 
@@ -278,17 +273,12 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-SlideshowUI::SlideshowUI(TabContents* contents) : DOMUI(contents) {
+SlideshowUI::SlideshowUI(TabContents* contents) : WebUI(contents) {
   SlideshowHandler* handler = new SlideshowHandler();
   AddMessageHandler((handler)->Attach(this));
   handler->Init();
   SlideshowUIHTMLSource* html_source = new SlideshowUIHTMLSource();
 
   // Set up the chrome://slideshow/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/dom_ui/slideshow_ui.h b/chrome/browser/dom_ui/slideshow_ui.h
index 51fbeb0..c5a90b3 100644
--- a/chrome/browser/dom_ui/slideshow_ui.h
+++ b/chrome/browser/dom_ui/slideshow_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_DOM_UI_SLIDESHOW_UI_H_
 #pragma once
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
-class SlideshowUI : public DOMUI {
+class SlideshowUI : public WebUI {
  public:
   explicit SlideshowUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/sync_internals_html_source.cc b/chrome/browser/dom_ui/sync_internals_html_source.cc
new file mode 100644
index 0000000..c35aaab
--- /dev/null
+++ b/chrome/browser/dom_ui/sync_internals_html_source.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/sync_internals_html_source.h"
+
+#include <algorithm>
+
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/ref_counted_memory.h"
+#include "base/string_piece.h"
+#include "base/values.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/url_constants.h"
+#include "grit/sync_internals_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+SyncInternalsHTMLSource::SyncInternalsHTMLSource()
+    : DataSource(chrome::kChromeUISyncInternalsHost,
+                 MessageLoop::current()) {}
+
+SyncInternalsHTMLSource::~SyncInternalsHTMLSource() {}
+
+void SyncInternalsHTMLSource::StartDataRequest(const std::string& path,
+                                               bool is_off_the_record,
+                                               int request_id) {
+  base::StringPiece html_template(
+      ResourceBundle::GetSharedInstance().GetRawDataResource(
+          IDR_SYNC_INTERNALS_INDEX_HTML));
+  DictionaryValue localized_strings;
+  SetFontAndTextDirection(&localized_strings);
+
+  std::string html(html_template.data(), html_template.size());
+  jstemplate_builder::AppendI18nTemplateSourceHtml(&html);
+  jstemplate_builder::AppendJsTemplateSourceHtml(&html);
+  jstemplate_builder::AppendJsonHtml(&localized_strings, &html);
+  jstemplate_builder::AppendI18nTemplateProcessHtml(&html);
+
+  scoped_refptr<RefCountedBytes> bytes(new RefCountedBytes());
+  bytes->data.resize(html.size());
+  std::copy(html.begin(), html.end(), bytes->data.begin());
+  SendResponse(request_id, bytes);
+}
+
+std::string SyncInternalsHTMLSource::GetMimeType(
+    const std::string& path) const {
+  return "text/html";
+}
diff --git a/chrome/browser/dom_ui/sync_internals_html_source.h b/chrome/browser/dom_ui/sync_internals_html_source.h
new file mode 100644
index 0000000..bb8ab48
--- /dev/null
+++ b/chrome/browser/dom_ui/sync_internals_html_source.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOM_UI_SYNC_INTERNALS_HTML_SOURCE_H_
+#define CHROME_BROWSER_DOM_UI_SYNC_INTERNALS_HTML_SOURCE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+
+class SyncInternalsHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+  SyncInternalsHTMLSource();
+
+  // ChromeURLDataManager::DataSource implementation.
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+  virtual std::string GetMimeType(const std::string& path) const;
+
+ protected:
+  virtual ~SyncInternalsHTMLSource();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SyncInternalsHTMLSource);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_SYNC_INTERNALS_HTML_SOURCE_H_
diff --git a/chrome/browser/dom_ui/sync_internals_ui.cc b/chrome/browser/dom_ui/sync_internals_ui.cc
new file mode 100644
index 0000000..3cfbdcd
--- /dev/null
+++ b/chrome/browser/dom_ui/sync_internals_ui.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/sync_internals_ui.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "base/task.h"
+#include "base/tracked_objects.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/dom_ui/sync_internals_html_source.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_frontend.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/sync_ui_util.h"
+#include "chrome/common/render_messages_params.h"
+
+SyncInternalsUI::SyncInternalsUI(TabContents* contents)
+    : WebUI(contents) {
+  browser_sync::JsFrontend* backend = GetJsFrontend();
+  if (backend) {
+    backend->AddHandler(this);
+  }
+  // If this PostTask() call fails, it's most likely because this is
+  // being run from a unit test.  The created objects will be cleaned
+  // up, anyway.
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(
+      new SyncInternalsHTMLSource());
+}
+
+SyncInternalsUI::~SyncInternalsUI() {
+  browser_sync::JsFrontend* backend = GetJsFrontend();
+  if (backend) {
+    backend->RemoveHandler(this);
+  }
+}
+
+void SyncInternalsUI::ProcessWebUIMessage(
+    const ViewHostMsg_DomMessage_Params& params) {
+  const std::string& name = params.name;
+  browser_sync::JsArgList args(params.arguments);
+  VLOG(1) << "Received message: " << name << " with args "
+          << args.ToString();
+  // We handle this case directly because it needs to work even if
+  // the sync service doesn't exist.
+  if (name == "getAboutInfo") {
+    ListValue args;
+    DictionaryValue* about_info = new DictionaryValue();
+    args.Append(about_info);
+    ProfileSyncService* service = GetProfile()->GetProfileSyncService();
+    sync_ui_util::ConstructAboutInformation(service, about_info);
+    HandleJsEvent("onGetAboutInfoFinished",
+                  browser_sync::JsArgList(args));
+  } else {
+    browser_sync::JsFrontend* backend = GetJsFrontend();
+    if (backend) {
+      backend->ProcessMessage(name, args, this);
+    } else {
+      LOG(WARNING) << "No sync service; dropping message " << name
+                   << " with args " << args.ToString();
+    }
+  }
+}
+
+void SyncInternalsUI::HandleJsEvent(const std::string& name,
+                                    const browser_sync::JsArgList& args) {
+  VLOG(1) << "Handling event: " << name << " with args " << args.ToString();
+  std::vector<const Value*> arg_list(args.Get().begin(), args.Get().end());
+  CallJavascriptFunction(UTF8ToWide(name), arg_list);
+}
+
+browser_sync::JsFrontend* SyncInternalsUI::GetJsFrontend() {
+  // If this returns NULL that means that sync is disabled for
+  // whatever reason.
+  ProfileSyncService* sync_service = GetProfile()->GetProfileSyncService();
+  return sync_service ? sync_service->GetJsFrontend() : NULL;
+}
diff --git a/chrome/browser/dom_ui/sync_internals_ui.h b/chrome/browser/dom_ui/sync_internals_ui.h
new file mode 100644
index 0000000..2a1e8e4
--- /dev/null
+++ b/chrome/browser/dom_ui/sync_internals_ui.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_SYNC_INTERNALS_UI_H_
+#define CHROME_BROWSER_DOM_UI_SYNC_INTERNALS_UI_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/dom_ui/web_ui.h"
+#include "chrome/browser/sync/js_event_handler.h"
+
+namespace browser_sync {
+class JsFrontend;
+}  // namespace browser_sync
+
+// The implementation for the chrome://sync-internals page.
+class SyncInternalsUI : public WebUI, public browser_sync::JsEventHandler {
+ public:
+  explicit SyncInternalsUI(TabContents* contents);
+  virtual ~SyncInternalsUI();
+
+  // WebUI implementation.
+  //
+  // The following messages are processed:
+  //
+  // getAboutInfo():
+  //   Immediately fires a onGetAboutInfoFinished() event with a
+  //   dictionary of sync-related stats and info.
+  //
+  // All other messages are routed to the sync service if it exists,
+  // and dropped otherwise.
+  //
+  // TODO(akalin): Add a simple isSyncEnabled() message and make
+  // getAboutInfo() be handled by the sync service.
+  virtual void ProcessWebUIMessage(
+      const ViewHostMsg_DomMessage_Params& params);
+
+  // browser_sync::JsEventHandler implementation.
+  virtual void HandleJsEvent(const std::string& name,
+                             const browser_sync::JsArgList& args);
+
+ private:
+  // Returns the sync service's JsFrontend object, or NULL if the sync
+  // service does not exist.
+  browser_sync::JsFrontend* GetJsFrontend();
+
+  DISALLOW_COPY_AND_ASSIGN(SyncInternalsUI);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_SYNC_INTERNALS_UI_H_
diff --git a/chrome/browser/dom_ui/sync_internals_ui_unittest.cc b/chrome/browser/dom_ui/sync_internals_ui_unittest.cc
new file mode 100644
index 0000000..a1f392e
--- /dev/null
+++ b/chrome/browser/dom_ui/sync_internals_ui_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/sync_internals_ui.h"
+
+#include <cstddef>
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_test_util.h"
+#include "chrome/browser/sync/profile_sync_service_mock.h"
+#include "chrome/browser/tab_contents/test_tab_contents.h"
+#include "chrome/common/render_messages_params.h"
+#include "chrome/test/profile_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using browser_sync::HasArgsAsList;
+using browser_sync::JsArgList;
+using testing::NiceMock;
+using testing::Return;
+using testing::StrictMock;
+
+// Subclass of SyncInternalsUI to mock out ExecuteJavascript.
+class TestSyncInternalsUI : public SyncInternalsUI {
+ public:
+  explicit TestSyncInternalsUI(TabContents* contents)
+      : SyncInternalsUI(contents) {}
+  virtual ~TestSyncInternalsUI() {}
+
+  MOCK_METHOD1(ExecuteJavascript, void(const std::wstring&));
+};
+
+class SyncInternalsUITest : public RenderViewHostTestHarness {
+ protected:
+  // We allocate memory for |sync_internals_ui_| but we don't
+  // construct it.  This is because we want to set mock expectations
+  // with its address before we construct it, and its constructor
+  // calls into our mocks.
+  SyncInternalsUITest()
+      // The message loop is provided by RenderViewHostTestHarness.
+      : ui_thread_(BrowserThread::UI, MessageLoopForUI::current()),
+        test_sync_internals_ui_buf_(NULL),
+        test_sync_internals_ui_constructor_called_(false) {}
+
+  virtual void SetUp() {
+    test_sync_internals_ui_buf_ = operator new(sizeof(TestSyncInternalsUI));
+    test_sync_internals_ui_constructor_called_ = false;
+    profile_.reset(new NiceMock<ProfileMock>());
+    RenderViewHostTestHarness::SetUp();
+  }
+
+  virtual void TearDown() {
+    if (test_sync_internals_ui_constructor_called_) {
+      GetTestSyncInternalsUI()->~TestSyncInternalsUI();
+    }
+    operator delete(test_sync_internals_ui_buf_);
+    RenderViewHostTestHarness::TearDown();
+  }
+
+  NiceMock<ProfileMock>* GetProfileMock() {
+    return static_cast<NiceMock<ProfileMock>*>(profile());
+  }
+
+  // Set up boilerplate expectations for calls done during
+  // SyncInternalUI's construction/destruction.
+  void ExpectSetupTeardownCalls() {
+    EXPECT_CALL(*GetProfileMock(), GetProfileSyncService())
+        .WillRepeatedly(Return(&profile_sync_service_mock_));
+
+    EXPECT_CALL(profile_sync_service_mock_, GetJsFrontend())
+        .WillRepeatedly(Return(&mock_js_backend_));
+
+    // Called by sync_ui_util::ConstructAboutInformation().
+    EXPECT_CALL(profile_sync_service_mock_, HasSyncSetupCompleted())
+        .WillRepeatedly(Return(false));
+
+    // Called by SyncInternalsUI's constructor.
+    EXPECT_CALL(mock_js_backend_,
+                AddHandler(GetTestSyncInternalsUIAddress()));
+
+    // Called by SyncInternalUI's destructor.
+    EXPECT_CALL(mock_js_backend_,
+                RemoveHandler(GetTestSyncInternalsUIAddress()));
+  }
+
+  // Like ExpectSetupTeardownCalls() but with a NULL
+  // ProfileSyncService.
+  void ExpectSetupTeardownCallsNullService() {
+    EXPECT_CALL(*GetProfileMock(), GetProfileSyncService())
+        .WillRepeatedly(Return(static_cast<ProfileSyncService*>(NULL)));
+  }
+
+  void ConstructTestSyncInternalsUI() {
+    if (test_sync_internals_ui_constructor_called_) {
+      ADD_FAILURE() << "ConstructTestSyncInternalsUI() should be called "
+                    << "at most once per test";
+      return;
+    }
+    new(test_sync_internals_ui_buf_) TestSyncInternalsUI(contents());
+    test_sync_internals_ui_constructor_called_ = true;
+  }
+
+  TestSyncInternalsUI* GetTestSyncInternalsUI() {
+    if (!test_sync_internals_ui_constructor_called_) {
+      ADD_FAILURE() << "ConstructTestSyncInternalsUI() should be called "
+                    << "before GetTestSyncInternalsUI()";
+      return NULL;
+    }
+    return GetTestSyncInternalsUIAddress();
+  }
+
+  // Used for passing into EXPECT_CALL().
+  TestSyncInternalsUI* GetTestSyncInternalsUIAddress() {
+    EXPECT_TRUE(test_sync_internals_ui_buf_);
+    return static_cast<TestSyncInternalsUI*>(test_sync_internals_ui_buf_);
+  }
+
+  StrictMock<ProfileSyncServiceMock> profile_sync_service_mock_;
+  StrictMock<browser_sync::MockJsFrontend> mock_js_backend_;
+
+ private:
+  // Needed by |contents()|.
+  BrowserThread ui_thread_;
+  void* test_sync_internals_ui_buf_;
+  bool test_sync_internals_ui_constructor_called_;
+};
+
+TEST_F(SyncInternalsUITest, HandleJsEvent) {
+  ExpectSetupTeardownCalls();
+
+  ConstructTestSyncInternalsUI();
+
+  EXPECT_CALL(*GetTestSyncInternalsUI(),
+              ExecuteJavascript(std::wstring(L"testMessage(5,true);")));
+
+  ListValue args;
+  args.Append(Value::CreateIntegerValue(5));
+  args.Append(Value::CreateBooleanValue(true));
+  GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(args));
+}
+
+TEST_F(SyncInternalsUITest, HandleJsEventNullService) {
+  ExpectSetupTeardownCallsNullService();
+
+  ConstructTestSyncInternalsUI();
+
+  EXPECT_CALL(*GetTestSyncInternalsUI(),
+              ExecuteJavascript(std::wstring(L"testMessage(5,true);")));
+
+  ListValue args;
+  args.Append(Value::CreateIntegerValue(5));
+  args.Append(Value::CreateBooleanValue(true));
+  GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(args));
+}
+
+TEST_F(SyncInternalsUITest, ProcessWebUIMessageBasic) {
+  ExpectSetupTeardownCalls();
+
+  ViewHostMsg_DomMessage_Params params;
+  params.name = "testName";
+  params.arguments.Append(Value::CreateIntegerValue(10));
+
+  EXPECT_CALL(mock_js_backend_,
+              ProcessMessage(params.name, HasArgsAsList(params.arguments),
+                             GetTestSyncInternalsUIAddress()));
+
+  ConstructTestSyncInternalsUI();
+
+  GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
+}
+
+TEST_F(SyncInternalsUITest, ProcessWebUIMessageBasicNullService) {
+  ExpectSetupTeardownCallsNullService();
+
+  ConstructTestSyncInternalsUI();
+
+  ViewHostMsg_DomMessage_Params params;
+  params.name = "testName";
+  params.arguments.Append(Value::CreateIntegerValue(5));
+
+  // Should drop the message.
+  GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
+}
+
+namespace {
+const wchar_t kAboutInfoCall[] =
+    L"onGetAboutInfoFinished({\"summary\":\"SYNC DISABLED\"});";
+}  // namespace
+
+TEST_F(SyncInternalsUITest, ProcessWebUIMessageGetAboutInfo) {
+  ExpectSetupTeardownCalls();
+
+  ViewHostMsg_DomMessage_Params params;
+  params.name = "getAboutInfo";
+
+  ConstructTestSyncInternalsUI();
+
+  EXPECT_CALL(*GetTestSyncInternalsUI(),
+              ExecuteJavascript(std::wstring(kAboutInfoCall)));
+
+  GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
+}
+
+TEST_F(SyncInternalsUITest, ProcessWebUIMessageGetAboutInfoNullService) {
+  ExpectSetupTeardownCallsNullService();
+
+  ViewHostMsg_DomMessage_Params params;
+  params.name = "getAboutInfo";
+
+  ConstructTestSyncInternalsUI();
+
+  EXPECT_CALL(*GetTestSyncInternalsUI(),
+              ExecuteJavascript(std::wstring(kAboutInfoCall)));
+
+  GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
+}
+
+}  // namespace
diff --git a/chrome/browser/dom_ui/textfields_ui.cc b/chrome/browser/dom_ui/textfields_ui.cc
index a74f10d..7d8891d 100644
--- a/chrome/browser/dom_ui/textfields_ui.cc
+++ b/chrome/browser/dom_ui/textfields_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,14 +7,16 @@
 #include <algorithm>
 #include <string>
 
-#include "app/resource_bundle.h"
 #include "base/singleton.h"
 #include "base/string_piece.h"
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 /**
  * TextfieldsUIHTMLSource implementation.
@@ -46,21 +48,21 @@
 /**
  * TextfieldsDOMHandler implementation.
  */
-TextfieldsDOMHandler::TextfieldsDOMHandler() : DOMMessageHandler() {}
+TextfieldsDOMHandler::TextfieldsDOMHandler() : WebUIMessageHandler() {}
 
 void TextfieldsDOMHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("textfieldValue",
+  web_ui_->RegisterMessageCallback("textfieldValue",
       NewCallback(this, &TextfieldsDOMHandler::HandleTextfieldValue));
 }
 
 void TextfieldsDOMHandler::HandleTextfieldValue(const ListValue* args) {
-  static_cast<TextfieldsUI*>(dom_ui_)->set_text(ExtractStringValue(args));
+  static_cast<TextfieldsUI*>(web_ui_)->set_text(ExtractStringValue(args));
 }
 
 /**
  * TextfieldsUI implementation.
  */
-TextfieldsUI::TextfieldsUI(TabContents* contents) : DOMUI(contents) {
+TextfieldsUI::TextfieldsUI(TabContents* contents) : WebUI(contents) {
   TextfieldsDOMHandler* handler = new TextfieldsDOMHandler();
   AddMessageHandler(handler);
   handler->Attach(this);
@@ -68,9 +70,5 @@
   TextfieldsUIHTMLSource* html_source = new TextfieldsUIHTMLSource();
 
   // Set up the chrome://textfields/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
diff --git a/chrome/browser/dom_ui/textfields_ui.h b/chrome/browser/dom_ui/textfields_ui.h
index f70d45e..9ec2828 100644
--- a/chrome/browser/dom_ui/textfields_ui.h
+++ b/chrome/browser/dom_ui/textfields_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class RefCountedMemory;
 
@@ -39,7 +39,7 @@
 /**
  * Handler for JavaScript calls from the DOM.
  */
-class TextfieldsDOMHandler : public DOMMessageHandler {
+class TextfieldsDOMHandler : public WebUIMessageHandler {
  public:
   TextfieldsDOMHandler();
 
@@ -55,7 +55,7 @@
   DISALLOW_COPY_AND_ASSIGN(TextfieldsDOMHandler);
 };
 
-class TextfieldsUI : public DOMUI {
+class TextfieldsUI : public WebUI {
  public:
   explicit TextfieldsUI(TabContents* contents);
 
diff --git a/chrome/browser/dom_ui/tips_handler.cc b/chrome/browser/dom_ui/tips_handler.cc
index 411da1f..7f7b565 100644
--- a/chrome/browser/dom_ui/tips_handler.cc
+++ b/chrome/browser/dom_ui/tips_handler.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/dom_ui/tips_handler.h"
+
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/dom_ui/tips_handler.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_resource/web_resource_service.h"
 #include "chrome/common/pref_names.h"
@@ -17,16 +17,17 @@
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
-DOMMessageHandler* TipsHandler::Attach(DOMUI* dom_ui) {
-  dom_ui_ = dom_ui;
-  tips_cache_ = dom_ui_->GetProfile()->GetPrefs()->
+WebUIMessageHandler* TipsHandler::Attach(WebUI* web_ui) {
+  web_ui_ = web_ui;
+  tips_cache_ = web_ui_->GetProfile()->GetPrefs()->
       GetMutableDictionary(prefs::kNTPWebResourceCache);
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void TipsHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("getTips",
+  web_ui_->RegisterMessageCallback("getTips",
       NewCallback(this, &TipsHandler::HandleGetTips));
 }
 
@@ -44,13 +45,13 @@
   // If tips are not correct for our language, do not send.  Wait for update.
   // We need to check here because the new tab page calls for tips before
   // the tip service starts up.
-  PrefService* current_prefs = dom_ui_->GetProfile()->GetPrefs();
+  PrefService* current_prefs = web_ui_->GetProfile()->GetPrefs();
   if (current_prefs->HasPrefPath(prefs::kNTPTipsResourceServer)) {
     std::string server = current_prefs->GetString(
         prefs::kNTPTipsResourceServer);
     std::string locale = g_browser_process->GetApplicationLocale();
     if (!EndsWith(server, locale, false)) {
-      dom_ui_->CallJavascriptFunction(L"tips", list_value);
+      web_ui_->CallJavascriptFunction(L"tips", list_value);
       return;
     }
   }
@@ -66,7 +67,7 @@
         // to set home page before resetting tip index to 0.
         current_tip_index = 0;
         const PrefService::Preference* pref =
-            dom_ui_->GetProfile()->GetPrefs()->FindPreference(
+            web_ui_->GetProfile()->GetPrefs()->FindPreference(
                 prefs::kHomePageIsNewTabPage);
         bool value;
         if (pref && !pref->IsManaged() &&
@@ -93,7 +94,7 @@
   tips_cache_->SetInteger(WebResourceService::kCurrentTipPrefName,
                           tip_index);
   // Send list of web resource items back out to the DOM.
-  dom_ui_->CallJavascriptFunction(L"tips", list_value);
+  web_ui_->CallJavascriptFunction(L"tips", list_value);
 }
 
 // static
diff --git a/chrome/browser/dom_ui/tips_handler.h b/chrome/browser/dom_ui/tips_handler.h
index b02f233..2890054 100644
--- a/chrome/browser/dom_ui/tips_handler.h
+++ b/chrome/browser/dom_ui/tips_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,20 +12,19 @@
 
 #include <string>
 
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 
 class DictionaryValue;
-class DOMUI;
 class ListValue;
 class PrefService;
 
-class TipsHandler : public DOMMessageHandler {
+class TipsHandler : public WebUIMessageHandler {
  public:
   TipsHandler() : tips_cache_(NULL) {}
   virtual ~TipsHandler() {}
 
-  // DOMMessageHandler implementation and overrides.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation and overrides.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Callback which pulls tips data from the preferences.
@@ -45,7 +44,7 @@
                int tip_index);
 
   // So we can push data out to the page that has called this handler.
-  DOMUI* dom_ui_;
+  WebUI* web_ui_;
 
   // Filled with data from cache in preferences.
   DictionaryValue* tips_cache_;
diff --git a/chrome/browser/dom_ui/value_helper.cc b/chrome/browser/dom_ui/value_helper.cc
index 92bee3c..93c1137 100644
--- a/chrome/browser/dom_ui/value_helper.cc
+++ b/chrome/browser/dom_ui/value_helper.cc
@@ -20,7 +20,7 @@
   NewTabUI::SetURLTitleAndDirection(dictionary, current_navigation.title(),
                                     current_navigation.virtual_url());
   dictionary->SetString("type", "tab");
-  dictionary->SetReal("timestamp", tab.timestamp.ToDoubleT());
+  dictionary->SetDouble("timestamp", tab.timestamp.ToDoubleT());
   return true;
 }
 
@@ -40,7 +40,7 @@
   if (tab_values->GetSize() == 0)
     return false;
   dictionary->SetString("type", "window");
-  dictionary->SetReal("timestamp", window.timestamp.ToDoubleT());
+  dictionary->SetDouble("timestamp", window.timestamp.ToDoubleT());
   dictionary->Set("tabs", tab_values.release());
   return true;
 }
diff --git a/chrome/browser/dom_ui/web_ui.cc b/chrome/browser/dom_ui/web_ui.cc
new file mode 100644
index 0000000..ba11fbf
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui.cc
@@ -0,0 +1,217 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui.h"
+
+#include "base/i18n/rtl.h"
+#include "base/json/json_writer.h"
+#include "base/stl_util-inl.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/dom_ui/generic_handler.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/common/bindings_policy.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/render_messages_params.h"
+
+namespace {
+
+std::wstring GetJavascript(const std::wstring& function_name,
+                           const std::vector<const Value*>& arg_list) {
+  std::wstring parameters;
+  std::string json;
+  for (size_t i = 0; i < arg_list.size(); ++i) {
+    if (i > 0)
+      parameters += L",";
+
+    base::JSONWriter::Write(arg_list[i], false, &json);
+    parameters += UTF8ToWide(json);
+  }
+  return function_name + L"(" + parameters + L");";
+}
+
+}  // namespace
+
+WebUI::WebUI(TabContents* contents)
+    : hide_favicon_(false),
+      force_bookmark_bar_visible_(false),
+      focus_location_bar_by_default_(false),
+      should_hide_url_(false),
+      link_transition_type_(PageTransition::LINK),
+      bindings_(BindingsPolicy::WEB_UI),
+      register_callback_overwrites_(false),
+      tab_contents_(contents) {
+  GenericHandler* handler = new GenericHandler();
+  AddMessageHandler(handler->Attach(this));
+}
+
+WebUI::~WebUI() {
+  STLDeleteContainerPairSecondPointers(message_callbacks_.begin(),
+                                       message_callbacks_.end());
+  STLDeleteContainerPointers(handlers_.begin(), handlers_.end());
+}
+
+// WebUI, public: -------------------------------------------------------------
+
+void WebUI::ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params) {
+  // Look up the callback for this message.
+  MessageCallbackMap::const_iterator callback =
+      message_callbacks_.find(params.name);
+  if (callback == message_callbacks_.end())
+    return;
+
+  // Forward this message and content on.
+  callback->second->Run(&params.arguments);
+}
+
+void WebUI::CallJavascriptFunction(const std::wstring& function_name) {
+  std::wstring javascript = function_name + L"();";
+  ExecuteJavascript(javascript);
+}
+
+void WebUI::CallJavascriptFunction(const std::wstring& function_name,
+                                   const Value& arg) {
+  std::vector<const Value*> args;
+  args.push_back(&arg);
+  ExecuteJavascript(GetJavascript(function_name, args));
+}
+
+void WebUI::CallJavascriptFunction(
+    const std::wstring& function_name,
+    const Value& arg1, const Value& arg2) {
+  std::vector<const Value*> args;
+  args.push_back(&arg1);
+  args.push_back(&arg2);
+  ExecuteJavascript(GetJavascript(function_name, args));
+}
+
+void WebUI::CallJavascriptFunction(
+    const std::wstring& function_name,
+    const Value& arg1, const Value& arg2, const Value& arg3) {
+  std::vector<const Value*> args;
+  args.push_back(&arg1);
+  args.push_back(&arg2);
+  args.push_back(&arg3);
+  ExecuteJavascript(GetJavascript(function_name, args));
+}
+
+void WebUI::CallJavascriptFunction(
+    const std::wstring& function_name,
+    const Value& arg1,
+    const Value& arg2,
+    const Value& arg3,
+    const Value& arg4) {
+  std::vector<const Value*> args;
+  args.push_back(&arg1);
+  args.push_back(&arg2);
+  args.push_back(&arg3);
+  args.push_back(&arg4);
+  ExecuteJavascript(GetJavascript(function_name, args));
+}
+
+void WebUI::CallJavascriptFunction(
+    const std::wstring& function_name,
+    const std::vector<const Value*>& args) {
+  ExecuteJavascript(GetJavascript(function_name, args));
+}
+
+ui::ThemeProvider* WebUI::GetThemeProvider() const {
+  return GetProfile()->GetThemeProvider();
+}
+
+void WebUI::RegisterMessageCallback(const std::string &message,
+                                    MessageCallback *callback) {
+  std::pair<MessageCallbackMap::iterator, bool> result =
+      message_callbacks_.insert(std::make_pair(message, callback));
+
+  // Overwrite preexisting message callback mappings.
+  if (register_callback_overwrites() && !result.second)
+    result.first->second = callback;
+}
+
+Profile* WebUI::GetProfile() const {
+  DCHECK(tab_contents());
+  return tab_contents()->profile();
+}
+
+RenderViewHost* WebUI::GetRenderViewHost() const {
+  DCHECK(tab_contents());
+  return tab_contents()->render_view_host();
+}
+
+// WebUI, protected: ----------------------------------------------------------
+
+void WebUI::AddMessageHandler(WebUIMessageHandler* handler) {
+  handlers_.push_back(handler);
+}
+
+void WebUI::ExecuteJavascript(const std::wstring& javascript) {
+  GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(),
+                                                   WideToUTF16Hack(javascript));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WebUIMessageHandler
+WebUIMessageHandler::WebUIMessageHandler() : web_ui_(NULL) {
+}
+
+WebUIMessageHandler::~WebUIMessageHandler() {
+}
+
+WebUIMessageHandler* WebUIMessageHandler::Attach(WebUI* web_ui) {
+  web_ui_ = web_ui;
+  RegisterMessages();
+  return this;
+}
+
+// WebUIMessageHandler, protected: ---------------------------------------------
+
+void WebUIMessageHandler::SetURLAndTitle(DictionaryValue* dictionary,
+                                         string16 title,
+                                         const GURL& gurl) {
+  dictionary->SetString("url", gurl.spec());
+
+  bool using_url_as_the_title = false;
+  if (title.empty()) {
+    using_url_as_the_title = true;
+    title = UTF8ToUTF16(gurl.spec());
+  }
+
+  // Since the title can contain BiDi text, we need to mark the text as either
+  // RTL or LTR, depending on the characters in the string. If we use the URL
+  // as the title, we mark the title as LTR since URLs are always treated as
+  // left to right strings.
+  string16 title_to_set(title);
+  if (base::i18n::IsRTL()) {
+    if (using_url_as_the_title) {
+      base::i18n::WrapStringWithLTRFormatting(&title_to_set);
+    } else {
+      base::i18n::AdjustStringForLocaleDirection(&title_to_set);
+    }
+  }
+  dictionary->SetString("title", title_to_set);
+}
+
+bool WebUIMessageHandler::ExtractIntegerValue(const ListValue* value,
+                                              int* out_int) {
+  std::string string_value;
+  if (value->GetString(0, &string_value))
+    return base::StringToInt(string_value, out_int);
+  NOTREACHED();
+  return false;
+}
+
+// TODO(viettrungluu): convert to string16 (or UTF-8 std::string?).
+std::wstring WebUIMessageHandler::ExtractStringValue(const ListValue* value) {
+  string16 string16_value;
+  if (value->GetString(0, &string16_value))
+    return UTF16ToWideHack(string16_value);
+  NOTREACHED();
+  return std::wstring();
+}
diff --git a/chrome/browser/dom_ui/web_ui.h b/chrome/browser/dom_ui/web_ui.h
new file mode 100644
index 0000000..1e680fc
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui.h
@@ -0,0 +1,221 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_H_
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/string16.h"
+#include "chrome/common/page_transition_types.h"
+
+class DictionaryValue;
+class WebUIMessageHandler;
+class GURL;
+class ListValue;
+class Profile;
+class RenderViewHost;
+class TabContents;
+class Value;
+struct ViewHostMsg_DomMessage_Params;
+
+namespace ui {
+class ThemeProvider;
+}
+
+// A WebUI sets up the datasources and message handlers for a given HTML-based
+// UI. It is contained by a WebUIManager.
+class WebUI {
+ public:
+  explicit WebUI(TabContents* contents);
+  virtual ~WebUI();
+
+  // Called by RenderViewHost when the RenderView is first created. This is
+  // *not* called for every page load because in some cases
+  // RenderViewHostManager will reuse RenderView instances. In those cases,
+  // RenderViewReused will be called instead.
+  virtual void RenderViewCreated(RenderViewHost* render_view_host) {}
+
+  // Called by RenderViewHostManager when a RenderView is reused to display a
+  // page.
+  virtual void RenderViewReused(RenderViewHost* render_view_host) {}
+
+  // Called when this becomes the active WebUI instance for a re-used
+  // RenderView; this is the point at which this WebUI instance will receive
+  // DOM messages instead of the previous WebUI instance.
+  //
+  // If a WebUI instance has code that is usually triggered from a JavaScript
+  // onload handler, this should be overridden to check to see if the web page's
+  // DOM is still intact (e.g., due to a back/forward navigation that remains
+  // within the same page), and if so trigger that code manually since onload
+  // won't be run in that case.
+  virtual void DidBecomeActiveForReusedRenderView() {}
+
+  // Called from TabContents.
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
+
+  // Used by WebUIMessageHandlers.
+  typedef Callback1<const ListValue*>::Type MessageCallback;
+  void RegisterMessageCallback(const std::string& message,
+                               MessageCallback* callback);
+
+  // Returns true if the favicon should be hidden for the current tab.
+  bool hide_favicon() const {
+    return hide_favicon_;
+  }
+
+  // Returns true if the bookmark bar should be forced to being visible,
+  // overriding the user's preference.
+  bool force_bookmark_bar_visible() const {
+    return force_bookmark_bar_visible_;
+  }
+
+  // Returns true if the location bar should be focused by default rather than
+  // the page contents. Some pages will want to use this to encourage the user
+  // to type in the URL bar.
+  bool focus_location_bar_by_default() const {
+    return focus_location_bar_by_default_;
+  }
+
+  // Returns true if the page's URL should be hidden. Some Web UI pages
+  // like the new tab page will want to hide it.
+  bool should_hide_url() const {
+    return should_hide_url_;
+  }
+
+  // Gets a custom tab title provided by the Web UI. If there is no title
+  // override, the string will be empty which should trigger the default title
+  // behavior for the tab.
+  const string16& overridden_title() const {
+    return overridden_title_;
+  }
+
+  // Returns the transition type that should be used for link clicks on this
+  // Web UI. This will default to LINK but may be overridden.
+  PageTransition::Type link_transition_type() const {
+    return link_transition_type_;
+  }
+
+  int bindings() const {
+    return bindings_;
+  }
+
+  // Indicates whether RegisterMessageCallback() will overwrite an existing
+  // message callback mapping.  Serves as the hook for test mocks.
+  bool register_callback_overwrites() const {
+    return register_callback_overwrites_;
+  }
+
+  void register_callback_overwrites(bool value) {
+    register_callback_overwrites_ = value;
+  }
+
+  // Call a Javascript function by sending its name and arguments down to
+  // the renderer.  This is asynchronous; there's no way to get the result
+  // of the call, and should be thought of more like sending a message to
+  // the page.
+  // There are variants for calls with more arguments.
+  void CallJavascriptFunction(const std::wstring& function_name);
+  void CallJavascriptFunction(const std::wstring& function_name,
+                              const Value& arg);
+  void CallJavascriptFunction(const std::wstring& function_name,
+                              const Value& arg1,
+                              const Value& arg2);
+  void CallJavascriptFunction(const std::wstring& function_name,
+                              const Value& arg1,
+                              const Value& arg2,
+                              const Value& arg3);
+  void CallJavascriptFunction(const std::wstring& function_name,
+                              const Value& arg1,
+                              const Value& arg2,
+                              const Value& arg3,
+                              const Value& arg4);
+  void CallJavascriptFunction(const std::wstring& function_name,
+                              const std::vector<const Value*>& args);
+
+  ui::ThemeProvider* GetThemeProvider() const;
+
+  // May be overridden by WebUI's which do not have a tab contents.
+  virtual Profile* GetProfile() const;
+
+  // May be overridden by WebUI's which do not have a tab contents.
+  virtual RenderViewHost* GetRenderViewHost() const;
+
+  TabContents* tab_contents() const { return tab_contents_; }
+
+ protected:
+  void AddMessageHandler(WebUIMessageHandler* handler);
+
+  // Execute a string of raw Javascript on the page.  Overridable for
+  // testing purposes.
+  virtual void ExecuteJavascript(const std::wstring& javascript);
+
+  // Options that may be overridden by individual Web UI implementations. The
+  // bool options default to false. See the public getters for more information.
+  bool hide_favicon_;
+  bool force_bookmark_bar_visible_;
+  bool focus_location_bar_by_default_;
+  bool should_hide_url_;
+  string16 overridden_title_;  // Defaults to empty string.
+  PageTransition::Type link_transition_type_;  // Defaults to LINK.
+  int bindings_;  // The bindings from BindingsPolicy that should be enabled for
+                  // this page.
+
+  // Used by test mocks. See the public getters for more information.
+  bool register_callback_overwrites_;  // Defaults to false.
+
+  // The WebUIMessageHandlers we own.
+  std::vector<WebUIMessageHandler*> handlers_;
+
+  // Non-owning pointer to the TabContents this WebUI is associated with.
+  TabContents* tab_contents_;
+
+ private:
+  // A map of message name -> message handling callback.
+  typedef std::map<std::string, MessageCallback*> MessageCallbackMap;
+  MessageCallbackMap message_callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUI);
+};
+
+// Messages sent from the DOM are forwarded via the WebUI to handler
+// classes. These objects are owned by WebUI and destroyed when the
+// host is destroyed.
+class WebUIMessageHandler {
+ public:
+  WebUIMessageHandler();
+  virtual ~WebUIMessageHandler();
+
+  // Attaches |this| to |web_ui| in order to handle messages from it.  Declared
+  // virtual so that subclasses can do special init work as soon as the web_ui
+  // is provided.  Returns |this| for convenience.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
+
+ protected:
+  // Adds "url" and "title" keys on incoming dictionary, setting title
+  // as the url as a fallback on empty title.
+  static void SetURLAndTitle(DictionaryValue* dictionary,
+                             string16 title,
+                             const GURL& gurl);
+
+  // This is where subclasses specify which messages they'd like to handle.
+  virtual void RegisterMessages() = 0;
+
+  // Extract an integer value from a list Value.
+  bool ExtractIntegerValue(const ListValue* value, int* out_int);
+
+  // Extract a string value from a list Value.
+  std::wstring ExtractStringValue(const ListValue* value);
+
+  WebUI* web_ui_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebUIMessageHandler);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_H_
diff --git a/chrome/browser/dom_ui/web_ui_browsertest.cc b/chrome/browser/dom_ui/web_ui_browsertest.cc
new file mode 100644
index 0000000..6bb35bf
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_browsertest.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_browsertest.h"
+
+#include "base/path_service.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/ui_test_utils.h"
+#include "ui/base/resource/resource_bundle.h"
+
+static const FilePath::CharType* kWebUILibraryJS =
+    FILE_PATH_LITERAL("test_api.js");
+static const FilePath::CharType* kWebUITestFolder =
+    FILE_PATH_LITERAL("dom_ui");
+
+WebUIBrowserTest::~WebUIBrowserTest() {}
+
+bool WebUIBrowserTest::RunWebUITest(const FilePath::CharType* src_path) {
+  std::string content;
+  BuildJavaScriptTest(FilePath(src_path), &content);
+  SetupHandlers();
+  return test_handler_->Execute(content);
+}
+
+WebUIBrowserTest::WebUIBrowserTest()
+    : test_handler_(new WebUIHandlerBrowserTest()) {}
+
+void WebUIBrowserTest::SetUpInProcessBrowserTestFixture() {
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_));
+  test_data_directory_ = test_data_directory_.Append(kWebUITestFolder);
+
+  // TODO(dtseng): should this be part of every BrowserTest or just WebUI test.
+  FilePath resources_pack_path;
+  PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
+  ResourceBundle::AddDataPackToSharedInstance(resources_pack_path);
+}
+
+WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() {
+  return NULL;
+}
+
+void WebUIBrowserTest::BuildJavaScriptTest(const FilePath& src_path,
+                                           std::string* content) {
+  ASSERT_TRUE(content != NULL);
+  std::string library_content, src_content;
+  ASSERT_TRUE(file_util::ReadFileToString(
+      test_data_directory_.Append(FilePath(kWebUILibraryJS)),
+          &library_content));
+  ASSERT_TRUE(file_util::ReadFileToString(
+      test_data_directory_.Append(src_path), &src_content));
+
+  content->append(library_content);
+  content->append(";\n");
+  content->append(src_content);
+}
+
+void WebUIBrowserTest::SetupHandlers() {
+  WebUI* web_ui_instance =
+      browser()->GetSelectedTabContents()->web_ui();
+  ASSERT_TRUE(web_ui_instance != NULL);
+  web_ui_instance->register_callback_overwrites(true);
+  test_handler_->Attach(web_ui_instance);
+
+  if (GetMockMessageHandler())
+    GetMockMessageHandler()->Attach(web_ui_instance);
+}
+
+IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) {
+  // Navigate to UI.
+  // TODO(dtseng): make accessor for subclasses to return?
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL));
+
+  ASSERT_TRUE(RunWebUITest(FILE_PATH_LITERAL("sample_downloads.js")));
+}
diff --git a/chrome/browser/dom_ui/web_ui_browsertest.h b/chrome/browser/dom_ui/web_ui_browsertest.h
new file mode 100644
index 0000000..44db102
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_browsertest.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_BROWSERTEST_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_BROWSERTEST_H_
+#pragma once
+
+#include <string>
+
+#include "base/file_path.h"
+#include "chrome/browser/dom_ui/web_ui_handler_browsertest.h"
+#include "chrome/test/in_process_browser_test.h"
+
+class WebUIMessageHandler;
+
+// The runner of WebUI javascript based tests.
+// See chrome/test/data/dom_ui/test_api.js for the javascript side test API's.
+//
+// These tests should follow the form given in:
+// chrome/test/data/dom_ui/sample_downloads.js.
+// and the lone test within this class.
+class WebUIBrowserTest : public InProcessBrowserTest {
+ public:
+  virtual ~WebUIBrowserTest();
+
+  bool RunWebUITest(const FilePath::CharType* src_path);
+
+ protected:
+  WebUIBrowserTest();
+
+  // Setup test path.
+  virtual void SetUpInProcessBrowserTestFixture();
+
+  // Returns a mock WebUI object under test (if any).
+  virtual WebUIMessageHandler* GetMockMessageHandler();
+
+ private:
+  // Builds a javascript test in the form:
+  // <js_library> ...
+  // <src_path> ...
+  //   runTests(function test1() {...},
+  //      ...
+  //   );
+  void BuildJavaScriptTest(const FilePath& src_path,
+                           std::string* content);
+
+  // Attaches mock and test handlers.
+  void SetupHandlers();
+
+  // Handles test framework messages.
+  scoped_ptr<WebUIHandlerBrowserTest> test_handler_;
+
+  // Location of test data (currently test/data/dom_ui).
+  FilePath test_data_directory_;
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_BROWSERTEST_H_
diff --git a/chrome/browser/dom_ui/web_ui_factory.cc b/chrome/browser/dom_ui/web_ui_factory.cc
new file mode 100644
index 0000000..657373f
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_factory.cc
@@ -0,0 +1,345 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_factory.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/about_flags.h"
+#include "chrome/browser/dom_ui/bookmarks_ui.h"
+#include "chrome/browser/dom_ui/bug_report_ui.h"
+#include "chrome/browser/dom_ui/constrained_html_ui.h"
+#include "chrome/browser/dom_ui/downloads_ui.h"
+#include "chrome/browser/dom_ui/devtools_ui.h"
+#include "chrome/browser/dom_ui/gpu_internals_ui.h"
+#include "chrome/browser/dom_ui/history_ui.h"
+#include "chrome/browser/dom_ui/history2_ui.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/flags_ui.h"
+#include "chrome/browser/dom_ui/net_internals_ui.h"
+#include "chrome/browser/dom_ui/new_tab_ui.h"
+#include "chrome/browser/dom_ui/plugins_ui.h"
+#include "chrome/browser/dom_ui/print_preview_ui.h"
+#include "chrome/browser/dom_ui/remoting_ui.h"
+#include "chrome/browser/dom_ui/options/options_ui.h"
+#include "chrome/browser/dom_ui/slideshow_ui.h"
+#include "chrome/browser/dom_ui/sync_internals_ui.h"
+#include "chrome/browser/dom_ui/textfields_ui.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
+#include "chrome/browser/extensions/extensions_ui.h"
+#include "chrome/browser/printing/print_dialog_cloud.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/dom_ui/imageburner_ui.h"
+#include "chrome/browser/chromeos/dom_ui/keyboard_overlay_ui.h"
+#include "chrome/browser/chromeos/dom_ui/menu_ui.h"
+#include "chrome/browser/chromeos/dom_ui/mobile_setup_ui.h"
+#include "chrome/browser/chromeos/dom_ui/register_page_ui.h"
+#include "chrome/browser/chromeos/dom_ui/system_info_ui.h"
+#include "chrome/browser/chromeos/dom_ui/wrench_menu_ui.h"
+#include "chrome/browser/chromeos/dom_ui/network_menu_ui.h"
+#include "chrome/browser/dom_ui/filebrowse_ui.h"
+#include "chrome/browser/dom_ui/mediaplayer_ui.h"
+#endif
+
+#if defined(TOUCH_UI)
+#include "chrome/browser/dom_ui/keyboard_ui.h"
+#endif
+
+#if defined(TOUCH_UI) && defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/dom_ui/login/login_ui.h"
+#endif
+
+#if defined(OS_WIN)
+#include "chrome/browser/dom_ui/conflicts_ui.h"
+#endif
+
+const WebUITypeID WebUIFactory::kNoWebUI = NULL;
+
+// A function for creating a new WebUI. The caller owns the return value, which
+// may be NULL (for example, if the URL refers to an non-existent extension).
+typedef WebUI* (*WebUIFactoryFunction)(TabContents* tab_contents,
+                                       const GURL& url);
+
+// Template for defining WebUIFactoryFunction.
+template<class T>
+WebUI* NewWebUI(TabContents* contents, const GURL& url) {
+  return new T(contents);
+}
+
+// Special case for extensions.
+template<>
+WebUI* NewWebUI<ExtensionWebUI>(TabContents* contents, const GURL& url) {
+  // Don't use a WebUI for incognito tabs because we require extensions to run
+  // within a single process.
+  ExtensionService* service = contents->profile()->GetExtensionService();
+  if (service &&
+      service->ExtensionBindingsAllowed(url)) {
+    return new ExtensionWebUI(contents, url);
+  }
+  return NULL;
+}
+
+// Returns a function that can be used to create the right type of WebUI for a
+// tab, based on its URL. Returns NULL if the URL doesn't have WebUI associated
+// with it. Even if the factory function is valid, it may yield a NULL WebUI
+// when invoked for a particular tab - see NewWebUI<ExtensionWebUI>.
+static WebUIFactoryFunction GetWebUIFactoryFunction(Profile* profile,
+    const GURL& url) {
+  // Currently, any gears: URL means an HTML dialog.
+  if (url.SchemeIs(chrome::kGearsScheme))
+    return &NewWebUI<HtmlDialogUI>;
+
+  if (url.host() == chrome::kChromeUIDialogHost)
+    return &NewWebUI<ConstrainedHtmlUI>;
+
+  ExtensionService* service = profile ? profile->GetExtensionService() : NULL;
+  if (service && service->ExtensionBindingsAllowed(url))
+    return &NewWebUI<ExtensionWebUI>;
+
+  // All platform builds of Chrome will need to have a cloud printing
+  // dialog as backup.  It's just that on Chrome OS, it's the only
+  // print dialog.
+  if (url.host() == chrome::kCloudPrintResourcesHost)
+    return &NewWebUI<ExternalHtmlDialogUI>;
+
+  // This will get called a lot to check all URLs, so do a quick check of other
+  // schemes (gears was handled above) to filter out most URLs.
+  if (!url.SchemeIs(chrome::kChromeDevToolsScheme) &&
+      !url.SchemeIs(chrome::kChromeInternalScheme) &&
+      !url.SchemeIs(chrome::kChromeUIScheme))
+    return NULL;
+
+  if (url.host() == chrome::kChromeUISyncResourcesHost ||
+      url.host() == chrome::kChromeUIRemotingResourcesHost ||
+      url.host() == chrome::kCloudPrintSetupHost)
+    return &NewWebUI<HtmlDialogUI>;
+
+  // Special case the new tab page. In older versions of Chrome, the new tab
+  // page was hosted at chrome-internal:<blah>. This might be in people's saved
+  // sessions or bookmarks, so we say any URL with that scheme triggers the new
+  // tab page.
+  if (url.host() == chrome::kChromeUINewTabHost ||
+      url.SchemeIs(chrome::kChromeInternalScheme))
+    return &NewWebUI<NewTabUI>;
+
+  // Give about:about a generic Web UI so it can navigate to pages with Web UIs.
+  if (url.spec() == chrome::kChromeUIAboutAboutURL)
+    return &NewWebUI<WebUI>;
+
+  // We must compare hosts only since some of the Web UIs append extra stuff
+  // after the host name.
+  if (url.host() == chrome::kChromeUIBookmarksHost)
+    return &NewWebUI<BookmarksUI>;
+  if (url.host() == chrome::kChromeUIBugReportHost)
+    return &NewWebUI<BugReportUI>;
+  if (url.host() == chrome::kChromeUIDevToolsHost)
+    return &NewWebUI<DevToolsUI>;
+#if defined(OS_WIN)
+  if (url.host() == chrome::kChromeUIConflictsHost)
+    return &NewWebUI<ConflictsUI>;
+#endif
+  if (url.host() == chrome::kChromeUIDownloadsHost)
+    return &NewWebUI<DownloadsUI>;
+  if (url.host() == chrome::kChromeUITextfieldsHost)
+    return &NewWebUI<TextfieldsUI>;
+  if (url.host() == chrome::kChromeUIExtensionsHost)
+    return &NewWebUI<ExtensionsUI>;
+  if (url.host() == chrome::kChromeUIHistoryHost)
+    return &NewWebUI<HistoryUI>;
+  if (url.host() == chrome::kChromeUIHistory2Host)
+    return &NewWebUI<HistoryUI2>;
+  if (url.host() == chrome::kChromeUIFlagsHost)
+    return &NewWebUI<FlagsUI>;
+#if defined(TOUCH_UI)
+  if (url.host() == chrome::kChromeUIKeyboardHost)
+    return &NewWebUI<KeyboardUI>;
+#endif
+  if (url.host() == chrome::kChromeUIGpuInternalsHost)
+    return &NewWebUI<GpuInternalsUI>;
+  if (url.host() == chrome::kChromeUINetInternalsHost)
+    return &NewWebUI<NetInternalsUI>;
+  if (url.host() == chrome::kChromeUIPluginsHost)
+    return &NewWebUI<PluginsUI>;
+  if (url.host() == chrome::kChromeUISyncInternalsHost)
+    return &NewWebUI<SyncInternalsUI>;
+#if defined(ENABLE_REMOTING)
+  if (url.host() == chrome::kChromeUIRemotingHost) {
+    if (CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kEnableRemoting)) {
+      return &NewWebUI<RemotingUI>;
+    }
+  }
+#endif
+
+#if defined(OS_CHROMEOS)
+  if (url.host() == chrome::kChromeUIFileBrowseHost)
+    return &NewWebUI<FileBrowseUI>;
+  if (url.host() == chrome::kChromeUIImageBurnerHost)
+    return &NewWebUI<ImageBurnUI>;
+  if (url.host() == chrome::kChromeUIKeyboardOverlayHost)
+    return &NewWebUI<KeyboardOverlayUI>;
+  if (url.host() == chrome::kChromeUIMediaplayerHost)
+    return &NewWebUI<MediaplayerUI>;
+  if (url.host() == chrome::kChromeUIMobileSetupHost)
+    return &NewWebUI<MobileSetupUI>;
+  if (url.host() == chrome::kChromeUIRegisterPageHost)
+    return &NewWebUI<RegisterPageUI>;
+  if (url.host() == chrome::kChromeUISettingsHost)
+    return &NewWebUI<OptionsUI>;
+  if (url.host() == chrome::kChromeUISlideshowHost)
+    return &NewWebUI<SlideshowUI>;
+  if (url.host() == chrome::kChromeUISystemInfoHost)
+    return &NewWebUI<SystemInfoUI>;
+  if (url.host() == chrome::kChromeUIMenu)
+    return &NewWebUI<chromeos::MenuUI>;
+  if (url.host() == chrome::kChromeUIWrenchMenu)
+    return &NewWebUI<chromeos::WrenchMenuUI>;
+  if (url.host() == chrome::kChromeUINetworkMenu)
+    return &NewWebUI<chromeos::NetworkMenuUI>;
+#else
+  if (url.host() == chrome::kChromeUISettingsHost) {
+    if (!CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kDisableTabbedOptions)) {
+      return &NewWebUI<OptionsUI>;
+    }
+  }
+  if (url.host() == chrome::kChromeUIPrintHost) {
+    if (CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kEnablePrintPreview)) {
+      return &NewWebUI<PrintPreviewUI>;
+    }
+  }
+#endif  // defined(OS_CHROMEOS)
+
+#if defined(TOUCH_UI) && defined(OS_CHROMEOS)
+  if (url.host() == chrome::kChromeUILoginHost)
+    return &NewWebUI<chromeos::LoginUI>;
+#endif
+
+  if (url.spec() == chrome::kChromeUIConstrainedHTMLTestURL)
+    return &NewWebUI<ConstrainedHtmlUI>;
+
+  return NULL;
+}
+
+// static
+WebUITypeID WebUIFactory::GetWebUIType(Profile* profile, const GURL& url) {
+  WebUIFactoryFunction function = GetWebUIFactoryFunction(profile, url);
+  return function ? reinterpret_cast<WebUITypeID>(function) : kNoWebUI;
+}
+
+// static
+bool WebUIFactory::HasWebUIScheme(const GURL& url) {
+  return url.SchemeIs(chrome::kChromeDevToolsScheme) ||
+         url.SchemeIs(chrome::kChromeInternalScheme) ||
+         url.SchemeIs(chrome::kChromeUIScheme) ||
+         url.SchemeIs(chrome::kExtensionScheme);
+}
+
+// static
+bool WebUIFactory::UseWebUIForURL(Profile* profile, const GURL& url) {
+  return GetWebUIFactoryFunction(profile, url) != NULL;
+}
+
+// static
+bool WebUIFactory::IsURLAcceptableForWebUI(Profile* profile, const GURL& url) {
+  return UseWebUIForURL(profile, url) ||
+      // javacsript: URLs are allowed to run in Web UI pages
+      url.SchemeIs(chrome::kJavaScriptScheme) ||
+      // It's possible to load about:blank in a Web UI renderer.
+      // See http://crbug.com/42547
+      url.spec() == chrome::kAboutBlankURL ||
+      // about:crash, about:kill, about:hang, and about:shorthang are allowed.
+      url.spec() == chrome::kAboutCrashURL ||
+      url.spec() == chrome::kAboutKillURL ||
+      url.spec() == chrome::kAboutHangURL ||
+      url.spec() == chrome::kAboutShorthangURL;
+}
+
+// static
+WebUI* WebUIFactory::CreateWebUIForURL(TabContents* tab_contents,
+                                       const GURL& url) {
+  WebUIFactoryFunction function = GetWebUIFactoryFunction(
+      tab_contents->profile(), url);
+  if (!function)
+    return NULL;
+  return (*function)(tab_contents, url);
+}
+
+// static
+void WebUIFactory::GetFaviconForURL(Profile* profile,
+                                    FaviconService::GetFaviconRequest* request,
+                                    const GURL& page_url) {
+  // All extensions but the bookmark manager get their favicon from the icons
+  // part of the manifest.
+  if (page_url.SchemeIs(chrome::kExtensionScheme) &&
+      page_url.host() != extension_misc::kBookmarkManagerId) {
+    ExtensionWebUI::GetFaviconForURL(profile, request, page_url);
+  } else {
+    scoped_refptr<RefCountedMemory> icon_data(
+        WebUIFactory::GetFaviconResourceBytes(profile, page_url));
+    bool know_icon = icon_data.get() != NULL && icon_data->size() > 0;
+    request->ForwardResultAsync(
+        FaviconService::FaviconDataCallback::TupleType(request->handle(),
+            know_icon, icon_data, false, GURL()));
+  }
+}
+
+// static
+RefCountedMemory* WebUIFactory::GetFaviconResourceBytes(Profile* profile,
+                                                        const GURL& page_url) {
+  // The bookmark manager is a chrome extension, so we have to check for it
+  // before we check for extension scheme.
+  if (page_url.host() == extension_misc::kBookmarkManagerId)
+    return BookmarksUI::GetFaviconResourceBytes();
+
+  // The extension scheme is handled in GetFaviconForURL.
+  if (page_url.SchemeIs(chrome::kExtensionScheme)) {
+    NOTREACHED();
+    return NULL;
+  }
+
+  if (!HasWebUIScheme(page_url))
+    return NULL;
+
+#if defined(OS_WIN)
+  if (page_url.host() == chrome::kChromeUIConflictsHost)
+    return ConflictsUI::GetFaviconResourceBytes();
+#endif
+
+  if (page_url.host() == chrome::kChromeUIDownloadsHost)
+    return DownloadsUI::GetFaviconResourceBytes();
+
+  if (page_url.host() == chrome::kChromeUIExtensionsHost)
+    return ExtensionsUI::GetFaviconResourceBytes();
+
+  if (page_url.host() == chrome::kChromeUIHistoryHost)
+    return HistoryUI::GetFaviconResourceBytes();
+
+  if (page_url.host() == chrome::kChromeUIHistory2Host)
+    return HistoryUI2::GetFaviconResourceBytes();
+
+  if (page_url.host() == chrome::kChromeUIFlagsHost)
+    return FlagsUI::GetFaviconResourceBytes();
+
+  if (page_url.host() == chrome::kChromeUISettingsHost)
+    return OptionsUI::GetFaviconResourceBytes();
+
+  if (page_url.host() == chrome::kChromeUIPluginsHost)
+    return PluginsUI::GetFaviconResourceBytes();
+
+#if defined(ENABLE_REMOTING)
+  if (page_url.host() == chrome::kChromeUIRemotingHost)
+    return RemotingUI::GetFaviconResourceBytes();
+#endif
+
+  return NULL;
+}
diff --git a/chrome/browser/dom_ui/web_ui_factory.h b/chrome/browser/dom_ui/web_ui_factory.h
new file mode 100644
index 0000000..08b3a2f
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_factory.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_FACTORY_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_FACTORY_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "chrome/browser/favicon_service.h"
+
+class WebUI;
+class GURL;
+class Profile;
+class RefCountedMemory;
+class TabContents;
+
+// An opaque identifier used to identify a WebUI. This can only be compared to
+// kNoWebUI or other WebUI types. See GetWebUIType.
+typedef void* WebUITypeID;
+
+class WebUIFactory {
+ public:
+  // A special WebUI type that signifies that a given page would not use the
+  // Web UI system.
+  static const WebUITypeID kNoWebUI;
+
+  // Returns a type identifier indicating what WebUI we would use for the
+  // given URL. This is useful for comparing the potential WebUIs for two URLs.
+  // Returns kNoWebUI if the given URL will not use the Web UI system.
+  static WebUITypeID GetWebUIType(Profile* profile, const GURL& url);
+
+  // Returns true if the given URL's scheme would trigger the Web UI system.
+  // This is a less precise test than UseDONUIForURL, which tells you whether
+  // that specific URL matches a known one. This one is faster and can be used
+  // to determine security policy.
+  static bool HasWebUIScheme(const GURL& url);
+
+  // Returns true if the given URL must use the Web UI system.
+  static bool UseWebUIForURL(Profile* profile, const GURL& url);
+
+  // Returns true if the given URL can be loaded by Web UI system.  This
+  // includes URLs that can be loaded by normal tabs as well, such as
+  // javascript: URLs or about:hang.
+  static bool IsURLAcceptableForWebUI(Profile* profile, const GURL& url);
+
+  // Allocates a new WebUI object for the given URL, and returns it. If the URL
+  // is not a Web UI URL, then it will return NULL. When non-NULL, ownership of
+  // the returned pointer is passed to the caller.
+  static WebUI* CreateWebUIForURL(TabContents* tab_contents, const GURL& url);
+
+  // Get the favicon for |page_url| and forward the result to the |request|
+  // when loaded.
+  static void GetFaviconForURL(Profile* profile,
+                               FaviconService::GetFaviconRequest* request,
+                               const GURL& page_url);
+
+ private:
+  // Gets the data for the favicon for a WebUI page. Returns NULL if the WebUI
+  // does not have a favicon.
+  static RefCountedMemory* GetFaviconResourceBytes(Profile* profile,
+                                                   const GURL& page_url);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(WebUIFactory);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_FACTORY_H_
diff --git a/chrome/browser/dom_ui/web_ui_favicon_source.cc b/chrome/browser/dom_ui/web_ui_favicon_source.cc
new file mode 100644
index 0000000..f2d7128
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_favicon_source.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_favicon_source.h"
+
+#include "base/callback.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
+#include "grit/app_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+WebUIFavIconSource::WebUIFavIconSource(Profile* profile)
+    : DataSource(chrome::kChromeUIFavIconHost, MessageLoop::current()),
+      profile_(profile->GetOriginalProfile()) {
+}
+
+WebUIFavIconSource::~WebUIFavIconSource() {
+}
+
+void WebUIFavIconSource::StartDataRequest(const std::string& path,
+                                          bool is_off_the_record,
+                                          int request_id) {
+  FaviconService* favicon_service =
+      profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
+  if (favicon_service) {
+    FaviconService::Handle handle;
+    if (path.empty()) {
+      SendDefaultResponse(request_id);
+      return;
+    }
+
+    if (path.size() > 8 && path.substr(0, 8) == "iconurl/") {
+      handle = favicon_service->GetFavicon(
+          GURL(path.substr(8)),
+          &cancelable_consumer_,
+          NewCallback(this, &WebUIFavIconSource::OnFavIconDataAvailable));
+    } else {
+      handle = favicon_service->GetFaviconForURL(
+          GURL(path),
+          &cancelable_consumer_,
+          NewCallback(this, &WebUIFavIconSource::OnFavIconDataAvailable));
+    }
+    // Attach the ChromeURLDataManager request ID to the history request.
+    cancelable_consumer_.SetClientData(favicon_service, handle, request_id);
+  } else {
+    SendResponse(request_id, NULL);
+  }
+}
+
+std::string WebUIFavIconSource::GetMimeType(const std::string&) const {
+  // We need to explicitly return a mime type, otherwise if the user tries to
+  // drag the image they get no extension.
+  return "image/png";
+}
+
+void WebUIFavIconSource::OnFavIconDataAvailable(
+    FaviconService::Handle request_handle,
+    bool know_favicon,
+    scoped_refptr<RefCountedMemory> data,
+    bool expired,
+    GURL icon_url) {
+  FaviconService* favicon_service =
+      profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
+  int request_id = cancelable_consumer_.GetClientData(favicon_service,
+                                                      request_handle);
+
+  if (know_favicon && data.get() && data->size()) {
+    // Forward the data along to the networking system.
+    SendResponse(request_id, data);
+  } else {
+    SendDefaultResponse(request_id);
+  }
+}
+
+void WebUIFavIconSource::SendDefaultResponse(int request_id) {
+  if (!default_favicon_.get()) {
+    default_favicon_ =
+        ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
+            IDR_DEFAULT_FAVICON);
+  }
+
+  SendResponse(request_id, default_favicon_);
+}
diff --git a/chrome/browser/dom_ui/web_ui_favicon_source.h b/chrome/browser/dom_ui/web_ui_favicon_source.h
new file mode 100644
index 0000000..71f8cde
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_favicon_source.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_FAVICON_SOURCE_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_FAVICON_SOURCE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/favicon_service.h"
+
+class GURL;
+class Profile;
+
+// FavIconSource is the gateway between network-level chrome:
+// requests for favicons and the history backend that serves these.
+class WebUIFavIconSource : public ChromeURLDataManager::DataSource {
+ public:
+  explicit WebUIFavIconSource(Profile* profile);
+
+  // Called when the network layer has requested a resource underneath
+  // the path we registered.
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+
+  virtual std::string GetMimeType(const std::string&) const;
+
+  // Called when favicon data is available from the history backend.
+  void OnFavIconDataAvailable(FaviconService::Handle request_handle,
+                              bool know_favicon,
+                              scoped_refptr<RefCountedMemory> data,
+                              bool expired,
+                              GURL url);
+
+ private:
+  // Sends the default favicon.
+  void SendDefaultResponse(int request_id);
+
+  virtual ~WebUIFavIconSource();
+
+  Profile* profile_;
+  CancelableRequestConsumerT<int, 0> cancelable_consumer_;
+
+  // Raw PNG representation of the favicon to show when the favicon
+  // database doesn't have a favicon for a webpage.
+  scoped_refptr<RefCountedMemory> default_favicon_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIFavIconSource);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_FAVICON_SOURCE_H_
diff --git a/chrome/browser/dom_ui/web_ui_handler_browsertest.cc b/chrome/browser/dom_ui/web_ui_handler_browsertest.cc
new file mode 100644
index 0000000..de15805
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_handler_browsertest.cc
@@ -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.
+
+#include "chrome/browser/dom_ui/web_ui_handler_browsertest.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/test/ui_test_utils.h"
+
+bool WebUIHandlerBrowserTest::Execute(const std::string& js_test) {
+  web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
+      string16(), UTF8ToUTF16(js_test));
+  return WaitForResult();
+}
+
+void WebUIHandlerBrowserTest::HandlePass(const ListValue* args) {
+  test_succeeded_ = true;
+  if (is_waiting_)
+    MessageLoopForUI::current()->Quit();
+}
+
+void WebUIHandlerBrowserTest::HandleFail(const ListValue* args) {
+  test_succeeded_ = false;
+  if (is_waiting_)
+    MessageLoopForUI::current()->Quit();
+}
+
+void WebUIHandlerBrowserTest::RegisterMessages() {
+  web_ui_->RegisterMessageCallback("Pass",
+      NewCallback(this, &WebUIHandlerBrowserTest::HandlePass));
+  web_ui_->RegisterMessageCallback("Fail",
+      NewCallback(this, &WebUIHandlerBrowserTest::HandleFail));
+}
+
+bool WebUIHandlerBrowserTest::WaitForResult() {
+  is_waiting_ = true;
+  ui_test_utils::RunMessageLoop();
+  is_waiting_ = false;
+  return test_succeeded_;
+}
diff --git a/chrome/browser/dom_ui/web_ui_handler_browsertest.h b/chrome/browser/dom_ui/web_ui_handler_browsertest.h
new file mode 100644
index 0000000..771e7fd
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_handler_browsertest.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_HANDLER_BROWSERTEST_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_HANDLER_BROWSERTEST_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/browser/dom_ui/web_ui.h"
+
+// This class registers test framework specific handlers on WebUI objects.
+class WebUIHandlerBrowserTest : public WebUIMessageHandler {
+ public:
+  // Executes a string of javascript.  Returns pass fail.
+  bool Execute(const std::string& js_test);
+
+ protected:
+  // WebUI handlers which deliver results to any waiting message loops.
+  // |args| is currently ignored.
+  void HandlePass(const ListValue* args);
+  void HandleFail(const ListValue* args);
+
+  // WebUIMessageHandler overrides.
+  // Add test handlers to the current WebUI object.
+  virtual void RegisterMessages();
+
+ private:
+  // Runs a message loop until test finishes.  Returns the result of the test.
+  bool WaitForResult();
+
+  // Pass fail result of current tests.
+  bool test_succeeded_;
+
+  // Waiting for a test to finish.
+  bool is_waiting_;
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_HANDLER_BROWSERTEST_H_
diff --git a/chrome/browser/dom_ui/web_ui_screenshot_source.cc b/chrome/browser/dom_ui/web_ui_screenshot_source.cc
new file mode 100644
index 0000000..84b78e1
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_screenshot_source.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_screenshot_source.h"
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/ref_counted_memory.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/url_constants.h"
+
+static const char kCurrentScreenshot[] = "current";
+#if defined(OS_CHROMEOS)
+static const char kSavedScreenshots[] = "saved/";
+#endif
+
+static const char kScreenshotsRelativePath[] = "/Screenshots/";
+
+#if defined(OS_CHROMEOS)
+// Read the file from the screenshots directory into the read_bytes vector.
+void ReadScreenshot(const std::string& filename,
+                   std::vector<unsigned char>* read_bytes,
+                   base::WaitableEvent* read_complete) {
+  read_bytes->clear();
+
+  FilePath fileshelf_path;
+  if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &fileshelf_path)) {
+    read_complete->Signal();
+    return;
+  }
+
+  FilePath file(fileshelf_path.value() + std::string(kScreenshotsRelativePath) +
+                filename);
+
+  int64 file_size = 0;
+  if (!file_util::GetFileSize(file, &file_size)) {
+    read_complete->Signal();
+    return;
+  }
+
+  // expand vector to file size
+  read_bytes->resize(file_size);
+  // read file into the vector
+  int bytes_read = 0;
+  if (!(bytes_read = file_util::ReadFile(file,
+                                         reinterpret_cast<char*>(
+                                             &read_bytes->front()),
+                                             static_cast<int>(file_size))))
+    read_bytes->clear();
+
+  // We're done, if successful, read_bytes will have the data
+  // otherwise, it'll be empty.
+  read_complete->Signal();
+}
+
+// Get a saved screenshot - read on the FILE thread.
+std::vector<unsigned char> GetSavedScreenshot(std::string filename) {
+  base::WaitableEvent read_complete(true, false);
+  std::vector<unsigned char> bytes;
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          NewRunnableFunction(&ReadScreenshot, filename,
+                                              &bytes, &read_complete));
+  read_complete.Wait();
+  return bytes;
+}
+#endif
+
+std::vector<unsigned char> WebUIScreenshotSource::GetScreenshot(
+    const std::string& full_path) {
+  // Strip the query param value - we only use it as a hack to ensure our
+  // image gets reloaded instead of being pulled from the browser cache
+  std::string path = full_path.substr(0, full_path.find_first_of("?"));
+  if (path == kCurrentScreenshot) {
+    return current_screenshot_;
+#if defined(OS_CHROMEOS)
+  } else if (path.compare(0, strlen(kSavedScreenshots),
+                          kSavedScreenshots) == 0) {
+    // Split the saved screenshot filename from the path
+    std::string filename = path.substr(strlen(kSavedScreenshots));
+
+    return GetSavedScreenshot(filename);
+#endif
+  } else {
+    std::vector<unsigned char> ret;
+    // TODO(rkc): Weird vc bug, return std::vector<unsigned char>() causes
+    // the object assigned to the return value of this function magically
+    // change it's address 0x0; look into this eventually.
+    return ret;
+  }
+}
+
+WebUIScreenshotSource::WebUIScreenshotSource(
+    std::vector<unsigned char>* current_screenshot)
+    : DataSource(chrome::kChromeUIScreenshotPath, MessageLoop::current()) {
+  // Setup the last screenshot taken.
+  if (current_screenshot)
+    current_screenshot_ = *current_screenshot;
+  else
+    current_screenshot_.clear();
+}
+
+WebUIScreenshotSource::~WebUIScreenshotSource() {}
+
+void WebUIScreenshotSource::StartDataRequest(const std::string& path,
+                                            bool is_off_the_record,
+                                            int request_id) {
+  SendResponse(request_id, new RefCountedBytes(GetScreenshot(path)));
+}
+
+std::string WebUIScreenshotSource::GetMimeType(const std::string&) const {
+  // We need to explicitly return a mime type, otherwise if the user tries to
+  // drag the image they get no extension.
+  return "image/png";
+}
diff --git a/chrome/browser/dom_ui/web_ui_screenshot_source.h b/chrome/browser/dom_ui/web_ui_screenshot_source.h
new file mode 100644
index 0000000..bc88a02
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_screenshot_source.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOM_UI_WEB_UI_SCREENSHOT_SOURCE_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_SCREENSHOT_SOURCE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+
+// ScreenshotSource is the data source that serves screenshots (saved
+// or current) to the bug report html ui
+class WebUIScreenshotSource : public ChromeURLDataManager::DataSource {
+ public:
+  explicit WebUIScreenshotSource(
+      std::vector<unsigned char>* current_screenshot);
+
+  // Called when the network layer has requested a resource underneath
+  // the path we registered.
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+
+  virtual std::string GetMimeType(const std::string&) const;
+
+  std::vector<unsigned char> GetScreenshot(const std::string& path);
+
+ private:
+  virtual ~WebUIScreenshotSource();
+
+  std::vector<unsigned char> current_screenshot_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIScreenshotSource);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_SCREENSHOT_SOURCE_H_
diff --git a/chrome/browser/dom_ui/web_ui_theme_source.cc b/chrome/browser/dom_ui/web_ui_theme_source.cc
new file mode 100644
index 0000000..b91ab6a
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_theme_source.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_theme_source.h"
+
+#include "base/message_loop.h"
+#include "base/ref_counted_memory.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/ntp_resource_cache.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/resources_util.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+
+// use a resource map rather than hard-coded strings.
+static const char* kNewTabCSSPath = "css/newtab.css";
+static const char* kNewIncognitoTabCSSPath = "css/newincognitotab.css";
+
+static std::string StripQueryParams(const std::string& path) {
+  GURL path_url = GURL(std::string(chrome::kChromeUIScheme) + "://" +
+                       std::string(chrome::kChromeUIThemePath) + "/" + path);
+  return path_url.path().substr(1);  // path() always includes a leading '/'.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebUIThemeSource, public:
+
+WebUIThemeSource::WebUIThemeSource(Profile* profile)
+    : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()),
+      profile_(profile->GetOriginalProfile()) {
+  css_bytes_ = profile_->GetNTPResourceCache()->GetNewTabCSS(
+      profile->IsOffTheRecord());
+}
+
+WebUIThemeSource::~WebUIThemeSource() {
+}
+
+void WebUIThemeSource::StartDataRequest(const std::string& path,
+                                        bool is_off_the_record,
+                                        int request_id) {
+  // Our path may include cachebuster arguments, so trim them off.
+  std::string uncached_path = StripQueryParams(path);
+
+  if (uncached_path == kNewTabCSSPath ||
+      uncached_path == kNewIncognitoTabCSSPath) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK((uncached_path == kNewTabCSSPath && !is_off_the_record) ||
+           (uncached_path == kNewIncognitoTabCSSPath && is_off_the_record));
+
+    SendResponse(request_id, css_bytes_);
+    return;
+  } else {
+    int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path);
+    if (resource_id != -1) {
+      SendThemeBitmap(request_id, resource_id);
+      return;
+    }
+  }
+  // We don't have any data to send back.
+  SendResponse(request_id, NULL);
+}
+
+std::string WebUIThemeSource::GetMimeType(const std::string& path) const {
+  std::string uncached_path = StripQueryParams(path);
+
+  if (uncached_path == kNewTabCSSPath ||
+      uncached_path == kNewIncognitoTabCSSPath) {
+    return "text/css";
+  }
+
+  return "image/png";
+}
+
+MessageLoop* WebUIThemeSource::MessageLoopForRequestPath(
+    const std::string& path) const {
+  std::string uncached_path = StripQueryParams(path);
+
+  if (uncached_path == kNewTabCSSPath ||
+      uncached_path == kNewIncognitoTabCSSPath) {
+    // We generated and cached this when we initialized the object.  We don't
+    // have to go back to the UI thread to send the data.
+    return NULL;
+  }
+
+  // If it's not a themeable image, we don't need to go to the UI thread.
+  int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path);
+  if (!BrowserThemeProvider::IsThemeableImage(resource_id))
+    return NULL;
+
+  return DataSource::MessageLoopForRequestPath(path);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebUIThemeSource, private:
+
+void WebUIThemeSource::SendThemeBitmap(int request_id, int resource_id) {
+  if (BrowserThemeProvider::IsThemeableImage(resource_id)) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    ui::ThemeProvider* tp = profile_->GetThemeProvider();
+    DCHECK(tp);
+
+    scoped_refptr<RefCountedMemory> image_data(tp->GetRawData(resource_id));
+    SendResponse(request_id, image_data);
+  } else {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    SendResponse(request_id, rb.LoadDataResourceBytes(resource_id));
+  }
+}
diff --git a/chrome/browser/dom_ui/web_ui_theme_source.h b/chrome/browser/dom_ui/web_ui_theme_source.h
new file mode 100644
index 0000000..4a7e2ed
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_theme_source.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_THEME_SOURCE_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_THEME_SOURCE_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+
+class Profile;
+class RefCountedBytes;
+
+class WebUIThemeSource : public ChromeURLDataManager::DataSource {
+ public:
+  explicit WebUIThemeSource(Profile* profile);
+
+  // Called when the network layer has requested a resource underneath
+  // the path we registered.
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+  virtual std::string GetMimeType(const std::string& path) const;
+
+  // Used to tell ChromeURLDataManager which thread to handle the request on.
+  virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const;
+
+ protected:
+  virtual ~WebUIThemeSource();
+
+ private:
+  // Fetch and send the theme bitmap.
+  void SendThemeBitmap(int request_id, int resource_id);
+
+  // The original profile (never an OTR profile).
+  Profile* profile_;
+
+  // We grab the CSS early so we don't have to go back to the UI thread later.
+  scoped_refptr<RefCountedBytes> css_bytes_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIThemeSource);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_THEME_SOURCE_H_
diff --git a/chrome/browser/dom_ui/web_ui_theme_source_unittest.cc b/chrome/browser/dom_ui/web_ui_theme_source_unittest.cc
new file mode 100644
index 0000000..5d9b3cd
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_theme_source_unittest.cc
@@ -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.
+
+#include "base/ref_counted_memory.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/web_ui_theme_source.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/testing_profile.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// A mock ThemeSource (so we can override SendResponse to get at its data).
+class MockThemeSource : public WebUIThemeSource {
+ public:
+  explicit MockThemeSource(Profile* profile)
+      : WebUIThemeSource(profile),
+        result_request_id_(-1),
+        result_data_size_(0) {
+  }
+
+  virtual void SendResponse(int request_id, RefCountedMemory* data) {
+    result_data_size_ = data ? data->size() : 0;
+    result_request_id_ = request_id;
+  }
+
+  int result_request_id_;
+  size_t result_data_size_;
+
+ private:
+  ~MockThemeSource() {}
+};
+
+class WebUISourcesTest : public testing::Test {
+ public:
+  WebUISourcesTest() : ui_thread_(BrowserThread::UI, MessageLoop::current()) {}
+
+  TestingProfile* profile() const { return profile_.get(); }
+  MockThemeSource* theme_source() const { return theme_source_.get(); }
+ private:
+  virtual void SetUp() {
+    profile_.reset(new TestingProfile());
+    profile_->InitThemes();
+    theme_source_ = new MockThemeSource(profile_.get());
+  }
+
+  virtual void TearDown() {
+    theme_source_ = NULL;
+    profile_.reset(NULL);
+  }
+
+  MessageLoop loop_;
+  BrowserThread ui_thread_;
+
+  scoped_ptr<TestingProfile> profile_;
+  scoped_refptr<MockThemeSource> theme_source_;
+};
+
+TEST_F(WebUISourcesTest, ThemeSourceMimeTypes) {
+  EXPECT_EQ(theme_source()->GetMimeType("css/newtab.css"), "text/css");
+  EXPECT_EQ(theme_source()->GetMimeType("css/newtab.css?foo"), "text/css");
+  EXPECT_EQ(theme_source()->GetMimeType("WRONGURL"), "image/png");
+}
+
+TEST_F(WebUISourcesTest, ThemeSourceImages) {
+  // We used to PNGEncode the images ourselves, but encoder differences
+  // invalidated that. We now just check that the image exists.
+  theme_source()->StartDataRequest("IDR_THEME_FRAME_INCOGNITO", true, 1);
+  size_t min = 0;
+  EXPECT_EQ(theme_source()->result_request_id_, 1);
+  EXPECT_GT(theme_source()->result_data_size_, min);
+
+  theme_source()->StartDataRequest("IDR_THEME_TOOLBAR", true, 2);
+  EXPECT_EQ(theme_source()->result_request_id_, 2);
+  EXPECT_GT(theme_source()->result_data_size_, min);
+}
+
+TEST_F(WebUISourcesTest, ThemeSourceCSS) {
+  BrowserThread io_thread(BrowserThread::IO, MessageLoop::current());
+  // Generating the test data for the NTP CSS would just involve copying the
+  // method, or being super brittle and hard-coding the result (requiring
+  // an update to the unittest every time the CSS template changes), so we
+  // just check for a successful request and data that is non-null.
+  size_t empty_size = 0;
+
+  theme_source()->StartDataRequest("css/newtab.css", false, 1);
+  EXPECT_EQ(theme_source()->result_request_id_, 1);
+  EXPECT_NE(theme_source()->result_data_size_, empty_size);
+
+  theme_source()->StartDataRequest("css/newtab.css?pie", false, 3);
+  EXPECT_EQ(theme_source()->result_request_id_, 3);
+  EXPECT_NE(theme_source()->result_data_size_, empty_size);
+
+  // Check that we send NULL back when we can't find what we're looking for.
+  theme_source()->StartDataRequest("css/WRONGURL", false, 7);
+  EXPECT_EQ(theme_source()->result_request_id_, 7);
+  EXPECT_EQ(theme_source()->result_data_size_, empty_size);
+}
diff --git a/chrome/browser/dom_ui/web_ui_thumbnail_source.cc b/chrome/browser/dom_ui/web_ui_thumbnail_source.cc
new file mode 100644
index 0000000..0f28b30
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_thumbnail_source.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/web_ui_thumbnail_source.h"
+
+#include "base/callback.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/history/top_sites.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+WebUIThumbnailSource::WebUIThumbnailSource(Profile* profile)
+    : DataSource(chrome::kChromeUIThumbnailPath, MessageLoop::current()),
+      // Set TopSites now as Profile isn't thread safe.
+      top_sites_(profile->GetTopSites()) {
+}
+
+WebUIThumbnailSource::~WebUIThumbnailSource() {
+}
+
+void WebUIThumbnailSource::StartDataRequest(const std::string& path,
+                                            bool is_off_the_record,
+                                            int request_id) {
+  scoped_refptr<RefCountedBytes> data;
+  if (top_sites_->GetPageThumbnail(GURL(path), &data)) {
+    // We have the thumbnail.
+    SendResponse(request_id, data.get());
+  } else {
+    SendDefaultThumbnail(request_id);
+  }
+}
+
+std::string WebUIThumbnailSource::GetMimeType(const std::string&) const {
+  // We need to explicitly return a mime type, otherwise if the user tries to
+  // drag the image they get no extension.
+  return "image/png";
+}
+
+MessageLoop* WebUIThumbnailSource::MessageLoopForRequestPath(
+    const std::string& path) const {
+  // TopSites can be accessed from the IO thread.
+  return top_sites_.get() ? NULL : DataSource::MessageLoopForRequestPath(path);
+}
+
+void WebUIThumbnailSource::SendDefaultThumbnail(int request_id) {
+  // Use placeholder thumbnail.
+  if (!default_thumbnail_.get()) {
+    default_thumbnail_ =
+        ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
+            IDR_DEFAULT_THUMBNAIL);
+  }
+  SendResponse(request_id, default_thumbnail_);
+}
diff --git a/chrome/browser/dom_ui/web_ui_thumbnail_source.h b/chrome/browser/dom_ui/web_ui_thumbnail_source.h
new file mode 100644
index 0000000..7891fe2
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_thumbnail_source.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_THUMBNAIL_SOURCE_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_THUMBNAIL_SOURCE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/ref_counted_memory.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+
+class Profile;
+
+namespace history {
+class TopSites;
+}
+
+// ThumbnailSource is the gateway between network-level chrome: requests for
+// thumbnails and the history/top-sites backend that serves these.
+class WebUIThumbnailSource : public ChromeURLDataManager::DataSource {
+ public:
+  explicit WebUIThumbnailSource(Profile* profile);
+
+  // Called when the network layer has requested a resource underneath
+  // the path we registered.
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+
+  virtual std::string GetMimeType(const std::string& path) const;
+
+  virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const;
+
+ private:
+  virtual ~WebUIThumbnailSource();
+
+  // Send the default thumbnail when we are missing a real one.
+  void SendDefaultThumbnail(int request_id);
+
+  // Raw PNG representation of the thumbnail to show when the thumbnail
+  // database doesn't have a thumbnail for a webpage.
+  scoped_refptr<RefCountedMemory> default_thumbnail_;
+
+  // TopSites.
+  scoped_refptr<history::TopSites> top_sites_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIThumbnailSource);
+};
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_THUMBNAIL_SOURCE_H_
diff --git a/chrome/browser/dom_ui/web_ui_unittest.cc b/chrome/browser/dom_ui/web_ui_unittest.cc
new file mode 100644
index 0000000..c0ccc1c
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_unittest.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/new_tab_ui.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/test_tab_contents.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class WebUITest : public RenderViewHostTestHarness {
+ public:
+  WebUITest() : ui_thread_(BrowserThread::UI, MessageLoop::current()) {}
+
+  // Tests navigating with a Web UI from a fresh (nothing pending or committed)
+  // state, through pending, committed, then another navigation. The first page
+  // ID that we should use is passed as a parameter. We'll use the next two
+  // values. This must be increasing for the life of the tests.
+  static void DoNavigationTest(TabContents* contents, int page_id) {
+    NavigationController* controller = &contents->controller();
+
+    // Start a pending load.
+    GURL new_tab_url(chrome::kChromeUINewTabURL);
+    controller->LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+
+    // The navigation entry should be pending with no committed entry.
+    ASSERT_TRUE(controller->pending_entry());
+    ASSERT_FALSE(controller->GetLastCommittedEntry());
+
+    // Check the things the pending Web UI should have set.
+    EXPECT_FALSE(contents->ShouldDisplayURL());
+    EXPECT_FALSE(contents->ShouldDisplayFavIcon());
+    EXPECT_TRUE(contents->ShouldShowBookmarkBar());
+    EXPECT_TRUE(contents->FocusLocationBarByDefault());
+
+    // Now commit the load.
+    static_cast<TestRenderViewHost*>(
+        contents->render_view_host())->SendNavigate(page_id, new_tab_url);
+
+    // The same flags should be set as before now that the load has committed.
+    EXPECT_FALSE(contents->ShouldDisplayURL());
+    EXPECT_FALSE(contents->ShouldDisplayFavIcon());
+    EXPECT_TRUE(contents->ShouldShowBookmarkBar());
+    EXPECT_TRUE(contents->FocusLocationBarByDefault());
+
+    // Start a pending navigation to a regular page.
+    GURL next_url("http://google.com/");
+    controller->LoadURL(next_url, GURL(), PageTransition::LINK);
+
+    // Check the flags. Some should reflect the new page (URL, title), some
+    // should reflect the old one (bookmark bar) until it has committed.
+    EXPECT_TRUE(contents->ShouldDisplayURL());
+    EXPECT_TRUE(contents->ShouldDisplayFavIcon());
+    EXPECT_TRUE(contents->ShouldShowBookmarkBar());
+    EXPECT_FALSE(contents->FocusLocationBarByDefault());
+
+    // Commit the regular page load. Note that we must send it to the "pending"
+    // RenderViewHost if there is one, since this transition will also cause a
+    // process transition, and our RVH pointer will be the "committed" one.
+    // In the second call to this function from WebUIToStandard, it won't
+    // actually be pending, which is the point of this test.
+    if (contents->render_manager()->pending_render_view_host()) {
+      static_cast<TestRenderViewHost*>(
+          contents->render_manager()->pending_render_view_host())->SendNavigate(
+              page_id + 1, next_url);
+    } else {
+      static_cast<TestRenderViewHost*>(
+          contents->render_view_host())->SendNavigate(page_id + 1, next_url);
+    }
+
+    // The state should now reflect a regular page.
+    EXPECT_TRUE(contents->ShouldDisplayURL());
+    EXPECT_TRUE(contents->ShouldDisplayFavIcon());
+    EXPECT_FALSE(contents->ShouldShowBookmarkBar());
+    EXPECT_FALSE(contents->FocusLocationBarByDefault());
+  }
+
+ private:
+  BrowserThread ui_thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUITest);
+};
+
+// Tests that the New Tab Page flags are correctly set and propogated by
+// TabContents when we first navigate to a Web UI page, then to a standard
+// non-DOM-UI page.
+TEST_F(WebUITest, WebUIToStandard) {
+  DoNavigationTest(contents(), 1);
+
+  // Test the case where we're not doing the initial navigation. This is
+  // slightly different than the very-first-navigation case since the
+  // SiteInstance will be the same (the original TabContents must still be
+  // alive), which will trigger different behavior in RenderViewHostManager.
+  TestTabContents contents2(profile_.get(), NULL);
+
+  DoNavigationTest(&contents2, 101);
+}
+
+TEST_F(WebUITest, WebUIToWebUI) {
+  // Do a load (this state is tested above).
+  GURL new_tab_url(chrome::kChromeUINewTabURL);
+  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+  rvh()->SendNavigate(1, new_tab_url);
+
+  // Start another pending load of the new tab page.
+  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+  rvh()->SendNavigate(2, new_tab_url);
+
+  // The flags should be the same as the non-pending state.
+  EXPECT_FALSE(contents()->ShouldDisplayURL());
+  EXPECT_FALSE(contents()->ShouldDisplayFavIcon());
+  EXPECT_TRUE(contents()->ShouldShowBookmarkBar());
+  EXPECT_TRUE(contents()->FocusLocationBarByDefault());
+}
+
+TEST_F(WebUITest, StandardToWebUI) {
+  // Start a pending navigation to a regular page.
+  GURL std_url("http://google.com/");
+
+  controller().LoadURL(std_url, GURL(), PageTransition::LINK);
+
+  // The state should now reflect the default.
+  EXPECT_TRUE(contents()->ShouldDisplayURL());
+  EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+  EXPECT_FALSE(contents()->ShouldShowBookmarkBar());
+  EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+
+  // Commit the load, the state should be the same.
+  rvh()->SendNavigate(1, std_url);
+  EXPECT_TRUE(contents()->ShouldDisplayURL());
+  EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+  EXPECT_FALSE(contents()->ShouldShowBookmarkBar());
+  EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+
+  // Start a pending load for a WebUI.
+  GURL new_tab_url(chrome::kChromeUINewTabURL);
+  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+  EXPECT_FALSE(contents()->ShouldDisplayURL());
+  EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+  EXPECT_FALSE(contents()->ShouldShowBookmarkBar());
+  EXPECT_TRUE(contents()->FocusLocationBarByDefault());
+
+  // Committing Web UI is tested above.
+}
+
+class TabContentsForFocusTest : public TestTabContents {
+ public:
+  TabContentsForFocusTest(Profile* profile, SiteInstance* instance)
+      : TestTabContents(profile, instance), focus_called_(0) {
+  }
+
+  virtual void SetFocusToLocationBar(bool select_all) { ++focus_called_; }
+  int focus_called() const { return focus_called_; }
+
+ private:
+  int focus_called_;
+};
+
+TEST_F(WebUITest, FocusOnNavigate) {
+  // Setup.  |tc| will be used to track when we try to focus the location bar.
+  TabContentsForFocusTest* tc = new TabContentsForFocusTest(
+      contents()->profile(),
+      SiteInstance::CreateSiteInstance(contents()->profile()));
+  tc->controller().CopyStateFrom(controller());
+  scoped_ptr<TestTabContents> tc_scoped_ptr(tc);
+  contents_.swap(tc_scoped_ptr);
+  int page_id = 200;
+
+  // Load the NTP.
+  GURL new_tab_url(chrome::kChromeUINewTabURL);
+  controller().LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+  rvh()->SendNavigate(page_id, new_tab_url);
+
+  // Navigate to another page.
+  GURL next_url("http://google.com/");
+  int next_page_id = page_id + 1;
+  controller().LoadURL(next_url, GURL(), PageTransition::LINK);
+  pending_rvh()->SendNavigate(next_page_id, next_url);
+
+  // Navigate back.  Should focus the location bar.
+  int focus_called = tc->focus_called();
+  ASSERT_TRUE(controller().CanGoBack());
+  controller().GoBack();
+  pending_rvh()->SendNavigate(page_id, new_tab_url);
+  EXPECT_LT(focus_called, tc->focus_called());
+
+  // Navigate forward.  Shouldn't focus the location bar.
+  focus_called = tc->focus_called();
+  ASSERT_TRUE(controller().CanGoForward());
+  controller().GoForward();
+  pending_rvh()->SendNavigate(next_page_id, next_url);
+  EXPECT_EQ(focus_called, tc->focus_called());
+
+  contents_.swap(tc_scoped_ptr);
+}
diff --git a/chrome/browser/dom_ui/web_ui_util.cc b/chrome/browser/dom_ui/web_ui_util.cc
new file mode 100644
index 0000000..2c95191
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_util.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/dom_ui/web_ui_util.h"
+
+#include <vector>
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
+
+namespace web_ui_util {
+
+std::string GetJsonResponseFromFirstArgumentInList(const ListValue* args) {
+  return GetJsonResponseFromArgumentList(args, 0);
+}
+
+std::string GetJsonResponseFromArgumentList(const ListValue* args,
+                                            size_t list_index) {
+  std::string result;
+  if (args->GetSize() <= list_index) {
+    NOTREACHED();
+    return result;
+  }
+
+  Value* value = NULL;
+  if (args->Get(list_index, &value))
+    value->GetAsString(&result);
+  else
+    NOTREACHED();
+
+  return result;
+}
+
+std::string GetImageDataUrl(const SkBitmap& bitmap) {
+  std::vector<unsigned char> output;
+  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output);
+  std::string str_url;
+  std::copy(output.begin(), output.end(),
+            std::back_inserter(str_url));
+  base::Base64Encode(str_url, &str_url);
+  str_url.insert(0, "data:image/png;base64,");
+  return str_url;
+}
+
+std::string GetImageDataUrlFromResource(int res) {
+  // Load resource icon and covert to base64 encoded data url
+  RefCountedStaticMemory* icon_data =
+      ResourceBundle::GetSharedInstance().LoadDataResourceBytes(res);
+  if (!icon_data)
+    return std::string();
+  scoped_refptr<RefCountedMemory> raw_icon(icon_data);
+  std::string str_url;
+  std::copy(raw_icon->front(), raw_icon->front() + raw_icon->size(),
+            std::back_inserter(str_url));
+  base::Base64Encode(str_url, &str_url);
+  str_url.insert(0, "data:image/png;base64,");
+  return str_url;
+}
+
+}  // namespace web_ui_util
diff --git a/chrome/browser/dom_ui/web_ui_util.h b/chrome/browser/dom_ui/web_ui_util.h
new file mode 100644
index 0000000..3f13362
--- /dev/null
+++ b/chrome/browser/dom_ui/web_ui_util.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_DOM_UI_WEB_UI_UTIL_H_
+#define CHROME_BROWSER_DOM_UI_WEB_UI_UTIL_H_
+#pragma once
+
+#include <string>
+
+class ListValue;
+class SkBitmap;
+
+namespace web_ui_util {
+
+// Convenience routine to get the response string from an argument
+// list.  Typically used when supporting a WebUI and getting calls
+// from the hosted code.  Content must be a ListValue with at least
+// one entry in it, and that first entry must be a string, which is
+// returned.  The parameter is a Value for convenience.  Returns an
+// empty string on error or if the parameter is not a ListValue.
+std::string GetJsonResponseFromFirstArgumentInList(const ListValue* args);
+
+// Convenience routine to get one of the response strings from an
+// argument list.  content must be a ListValue, with at least
+// (list_index+1) entries in it.  list_index is the 0-based index of
+// the entry to pull from that list, and that entry must be a string,
+// which is returned.  The parameter is a Value for convenience.
+// Returns an empty string on error or if the parameter is not a
+// ListValue.
+std::string GetJsonResponseFromArgumentList(const ListValue* args,
+                                            size_t list_index);
+
+
+// Convenience routine to convert SkBitmap object to data url
+// so that it can be used in WebUI.
+std::string GetImageDataUrl(const SkBitmap& bitmap);
+
+// Convenience routine to get data url that corresponds to given
+// resource_id as an image. This function does not check if the
+// resource for the |resource_id| is an image, therefore it is the
+// caller's responsibility to make sure the resource is indeed an
+// image. Returns empty string if a resource does not exist for given
+// |resource_id|.
+std::string GetImageDataUrlFromResource(int resource_id);
+
+}  // namespace web_ui_util
+
+#endif  // CHROME_BROWSER_DOM_UI_WEB_UI_UTIL_H_
diff --git a/chrome/browser/download/OWNERS b/chrome/browser/download/OWNERS
new file mode 100644
index 0000000..1cf8d24
--- /dev/null
+++ b/chrome/browser/download/OWNERS
@@ -0,0 +1,2 @@
+rdsmith@chromium.org
+phajdan.jr@chromium.org
diff --git a/chrome/browser/download/base_file.cc b/chrome/browser/download/base_file.cc
index 9d77233..79f38e9 100644
--- a/chrome/browser/download/base_file.cc
+++ b/chrome/browser/download/base_file.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/download/base_file.h"
 
+#include "base/crypto/secure_hash.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
@@ -13,7 +14,6 @@
 #include "chrome/browser/download/download_util.h"
 
 #if defined(OS_WIN)
-#include "app/win/win_util.h"
 #include "chrome/common/win_safe_util.h"
 #elif defined(OS_MACOSX)
 #include "chrome/browser/ui/cocoa/file_metadata.h"
@@ -30,7 +30,8 @@
       referrer_url_(referrer_url),
       file_stream_(file_stream),
       bytes_so_far_(received_bytes),
-      power_save_blocker_(true) {
+      power_save_blocker_(true),
+      calculate_hash_(false) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 }
 
@@ -41,8 +42,14 @@
   Close();
 }
 
-bool BaseFile::Initialize() {
+bool BaseFile::Initialize(bool calculate_hash) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  calculate_hash_ = calculate_hash;
+
+  if (calculate_hash_)
+    secure_hash_.reset(base::SecureHash::Create(base::SecureHash::SHA256));
+
   if (!full_path_.empty() ||
       download_util::CreateTemporaryFileForDownload(&full_path_))
     return Open();
@@ -63,7 +70,13 @@
 
   // TODO(phajdan.jr): handle errors on file writes. http://crbug.com/58355
   size_t written = file_stream_->Write(data, data_len, NULL);
-  return (written == data_len);
+  if (written != data_len)
+    return false;
+
+  if (calculate_hash_)
+    secure_hash_->Update(data, data_len);
+
+  return true;
 }
 
 bool BaseFile::Rename(const FilePath& new_path, bool is_final_rename) {
@@ -139,9 +152,21 @@
 
 void BaseFile::Finish() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  if (calculate_hash_)
+    secure_hash_->Finish(sha256_hash_, kSha256HashLen);
+
   Close();
 }
 
+bool BaseFile::GetSha256Hash(std::string* hash) {
+  if (!calculate_hash_ || in_progress())
+    return false;
+  hash->assign(reinterpret_cast<const char*>(sha256_hash_),
+               sizeof(sha256_hash_));
+  return true;
+}
+
 void BaseFile::AnnotateWithSourceInformation() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 #if defined(OS_WIN)
diff --git a/chrome/browser/download/base_file.h b/chrome/browser/download/base_file.h
index ffa63cc..2dfaf14 100644
--- a/chrome/browser/download/base_file.h
+++ b/chrome/browser/download/base_file.h
@@ -10,9 +10,13 @@
 
 #include "base/file_path.h"
 #include "base/linked_ptr.h"
+#include "base/scoped_ptr.h"
 #include "chrome/browser/power_save_blocker.h"
 #include "googleurl/src/gurl.h"
 
+namespace base {
+class SecureHash;
+}
 namespace net {
 class FileStream;
 }
@@ -28,7 +32,8 @@
            const linked_ptr<net::FileStream>& file_stream);
   ~BaseFile();
 
-  bool Initialize();
+  // If calculate_hash is true, sha256 hash will be calculated.
+  bool Initialize(bool calculate_hash);
 
   // Write a new chunk of data to the file. Returns true on success (all bytes
   // written to the file).
@@ -53,6 +58,10 @@
   bool in_progress() const { return file_stream_ != NULL; }
   int64 bytes_so_far() const { return bytes_so_far_; }
 
+  // Set |hash| with sha256 digest for the file.
+  // Returns true if digest is successfully calculated.
+  virtual bool GetSha256Hash(std::string* hash);
+
   virtual std::string DebugString() const;
 
  protected:
@@ -66,6 +75,8 @@
   bool path_renamed_;
 
  private:
+  static const size_t kSha256HashLen = 32;
+
   // Source URL for the file being downloaded.
   GURL source_url_;
 
@@ -81,6 +92,15 @@
   // RAII handle to keep the system from sleeping while we're downloading.
   PowerSaveBlocker power_save_blocker_;
 
+  // Indicates if sha256 hash should be calculated for the file.
+  bool calculate_hash_;
+
+  // Used to calculate sha256 hash for the file when calculate_hash_
+  // is set.
+  scoped_ptr<base::SecureHash> secure_hash_;
+
+  unsigned char sha256_hash_[kSha256HashLen];
+
   DISALLOW_COPY_AND_ASSIGN(BaseFile);
 };
 
diff --git a/chrome/browser/download/base_file_unittest.cc b/chrome/browser/download/base_file_unittest.cc
index 88698d2..c005a1c 100644
--- a/chrome/browser/download/base_file_unittest.cc
+++ b/chrome/browser/download/base_file_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "base/scoped_temp_dir.h"
+#include "base/string_number_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/download/base_file.h"
 #include "net/base/file_stream.h"
@@ -23,7 +24,8 @@
 
   virtual void SetUp() {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    base_file_.reset(new BaseFile(FilePath(), GURL(), GURL(), 0, file_stream_));
+    base_file_.reset(
+        new BaseFile(FilePath(), GURL(), GURL(), 0, file_stream_));
   }
 
   virtual void TearDown() {
@@ -80,7 +82,7 @@
 
 // Cancel the download explicitly.
 TEST_F(BaseFileTest, Cancel) {
-  ASSERT_TRUE(base_file_->Initialize());
+  ASSERT_TRUE(base_file_->Initialize(false));
   EXPECT_TRUE(file_util::PathExists(base_file_->full_path()));
   base_file_->Cancel();
   EXPECT_FALSE(file_util::PathExists(base_file_->full_path()));
@@ -90,7 +92,7 @@
 
 // Write data to the file once.
 TEST_F(BaseFileTest, SingleWrite) {
-  ASSERT_TRUE(base_file_->Initialize());
+  ASSERT_TRUE(base_file_->Initialize(false));
   AppendDataToFile(kTestData1);
   base_file_->Finish();
 
@@ -99,18 +101,52 @@
 
 // Write data to the file multiple times.
 TEST_F(BaseFileTest, MultipleWrites) {
-  ASSERT_TRUE(base_file_->Initialize());
+  ASSERT_TRUE(base_file_->Initialize(false));
   AppendDataToFile(kTestData1);
   AppendDataToFile(kTestData2);
   AppendDataToFile(kTestData3);
+  std::string hash;
+  EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
   base_file_->Finish();
 
   EXPECT_FALSE(base_file_->path_renamed());
 }
 
+// Write data to the file once and calculate its sha256 hash.
+TEST_F(BaseFileTest, SingleWriteWithHash) {
+  ASSERT_TRUE(base_file_->Initialize(true));
+  AppendDataToFile(kTestData1);
+  base_file_->Finish();
+
+  EXPECT_FALSE(base_file_->path_renamed());
+
+  std::string hash;
+  base_file_->GetSha256Hash(&hash);
+  EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
+            base::HexEncode(hash.data(), hash.size()));
+}
+
+// Write data to the file multiple times and calculate its sha256 hash.
+TEST_F(BaseFileTest, MultipleWritesWithHash) {
+  std::string hash;
+
+  ASSERT_TRUE(base_file_->Initialize(true));
+  AppendDataToFile(kTestData1);
+  AppendDataToFile(kTestData2);
+  AppendDataToFile(kTestData3);
+  // no hash before Finish() is called either.
+  EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
+  base_file_->Finish();
+
+  EXPECT_FALSE(base_file_->path_renamed());
+  EXPECT_TRUE(base_file_->GetSha256Hash(&hash));
+  EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
+            base::HexEncode(hash.data(), hash.size()));
+}
+
 // Rename the file after all writes to it.
 TEST_F(BaseFileTest, WriteThenRename) {
-  ASSERT_TRUE(base_file_->Initialize());
+  ASSERT_TRUE(base_file_->Initialize(false));
 
   FilePath initial_path(base_file_->full_path());
   EXPECT_TRUE(file_util::PathExists(initial_path));
@@ -130,7 +166,7 @@
 
 // Rename the file while the download is still in progress.
 TEST_F(BaseFileTest, RenameWhileInProgress) {
-  ASSERT_TRUE(base_file_->Initialize());
+  ASSERT_TRUE(base_file_->Initialize(false));
 
   FilePath initial_path(base_file_->full_path());
   EXPECT_TRUE(file_util::PathExists(initial_path));
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 6f0d998..d88af5b 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -7,19 +7,25 @@
 #include "base/path_service.h"
 #include "base/scoped_temp_dir.h"
 #include "base/test/test_file_util.h"
-#include "chrome/browser/ui/browser.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/download/download_shelf.h"
 #include "chrome/browser/net/url_request_mock_http_job.h"
+#include "chrome/browser/net/url_request_slow_download_job.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/common/page_transition_types.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
+#include "net/base/net_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -213,54 +219,142 @@
 };
 
 class DownloadTest : public InProcessBrowserTest {
- protected:
-  void SetUpInProcessBrowserTestFixture() {
-    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
+ public:
+  enum SelectExpectation {
+    EXPECT_NO_SELECT_DIALOG = -1,
+    EXPECT_NOTHING,
+    EXPECT_SELECT_DIALOG
+  };
+
+  // Returning false indicates a failure of the setup, and should be asserted
+  // in the caller.
+  virtual bool InitialSetup(bool prompt_for_download) {
+    bool have_test_dir = PathService::Get(chrome::DIR_TEST_DATA, &test_dir_);
+    EXPECT_TRUE(have_test_dir);
+    if (!have_test_dir)
+      return false;
+
+    // Sanity check default values for window / tab count and shelf visibility.
+    int window_count = BrowserList::size();
+    EXPECT_EQ(1, window_count);
+    EXPECT_EQ(1, browser()->tab_count());
+    bool is_shelf_visible = browser()->window()->IsDownloadShelfVisible();
+    EXPECT_FALSE(is_shelf_visible);
+
+    // Set up the temporary download folder.
+    bool created_downloads_dir = CreateAndSetDownloadsDirectory(browser());
+    EXPECT_TRUE(created_downloads_dir);
+    if (!created_downloads_dir)
+      return false;
+    browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
+                                                 prompt_for_download);
+
+    return true;
   }
 
+ protected:
+
   // Must be called after browser creation.  Creates a temporary
   // directory for downloads that is auto-deleted on destruction.
-  bool CreateAndSetDownloadsDirectory() {
-    if (downloads_directory_.CreateUniqueTempDir()) {
-      browser()->profile()->GetPrefs()->SetFilePath(
-          prefs::kDownloadDefaultDirectory,
-          downloads_directory_.path());
-      return true;
-    }
-    return false;
+  // Returning false indicates a failure of the function, and should be asserted
+  // in the caller.
+  bool CreateAndSetDownloadsDirectory(Browser* browser) {
+    if (!browser)
+      return false;
+
+    if (!downloads_directory_.CreateUniqueTempDir())
+      return false;
+
+    browser->profile()->GetPrefs()->SetFilePath(
+        prefs::kDownloadDefaultDirectory,
+        downloads_directory_.path());
+
+    return true;
   }
 
-  // May only be called inside of an individual test; browser() is NULL
-  // outside of that context.
-  FilePath GetDownloadDirectory() {
+  FilePath GetDownloadDirectory(Browser* browser) {
     DownloadManager* download_mananger =
-        browser()->profile()->GetDownloadManager();
+        browser->profile()->GetDownloadManager();
     return download_mananger->download_prefs()->download_path();
   }
 
-  DownloadsObserver* CreateWaiter(int num_downloads) {
+  DownloadsObserver* CreateWaiter(Browser* browser, int num_downloads) {
     DownloadManager* download_manager =
-        browser()->profile()->GetDownloadManager();
+        browser->profile()->GetDownloadManager();
     return new DownloadsObserver(
         download_manager, num_downloads,
         DownloadsObserver::FILE_RENAME,  // Really done
-        true);                          // Bail on select file
+        true);                           // Bail on select file
+  }
+
+  // Download |url|, then wait for the download to finish.
+  // |disposition| indicates where the navigation occurs (current tab, new
+  // foreground tab, etc).
+  // |expectation| indicates whether or not a Select File dialog should be
+  // open when the download is finished, or if we don't care.
+  // If the dialog appears, the test completes.  The only effect |expectation|
+  // has is whether or not the test succeeds.
+  // |browser_test_flags| indicate what to wait for, and is an OR of 0 or more
+  // values in the ui_test_utils::BrowserTestWaitFlags enum.
+  void DownloadAndWaitWithDisposition(Browser* browser,
+                                      const GURL& url,
+                                      WindowOpenDisposition disposition,
+                                      SelectExpectation expectation,
+                                      int browser_test_flags) {
+    // Setup notification, navigate, and block.
+    scoped_ptr<DownloadsObserver> observer(CreateWaiter(browser, 1));
+    // This call will block until the condition specified by
+    // |browser_test_flags|, but will not wait for the download to finish.
+    ui_test_utils::NavigateToURLWithDisposition(browser,
+                                                url,
+                                                disposition,
+                                                browser_test_flags);
+    // Waits for the download to complete.
+    observer->WaitForFinished();
+
+    // If specified, check the state of the select file dialog.
+    if (expectation != EXPECT_NOTHING) {
+      EXPECT_EQ(expectation == EXPECT_SELECT_DIALOG,
+                observer->select_file_dialog_seen());
+    }
+  }
+
+  // Download a file in the current tab, then wait for the download to finish.
+  void DownloadAndWait(Browser* browser,
+                       const GURL& url,
+                       SelectExpectation expectation) {
+    DownloadAndWaitWithDisposition(
+        browser,
+        url,
+        CURRENT_TAB,
+        expectation,
+        ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   }
 
   // Should only be called when the download is known to have finished
   // (in error or not).
-  void CheckDownload(const FilePath& downloaded_filename,
+  // Returning false indicates a failure of the function, and should be asserted
+  // in the caller.
+  bool CheckDownload(Browser* browser,
+                     const FilePath& downloaded_filename,
                      const FilePath& origin_filename) {
     // Find the path to which the data will be downloaded.
     FilePath downloaded_file =
-        GetDownloadDirectory().Append(downloaded_filename);
+        GetDownloadDirectory(browser).Append(downloaded_filename);
 
     // Find the origin path (from which the data comes).
     FilePath origin_file(test_dir_.Append(origin_filename));
-    ASSERT_TRUE(file_util::PathExists(origin_file));
+    bool origin_file_exists = file_util::PathExists(origin_file);
+    EXPECT_TRUE(origin_file_exists);
+    if (!origin_file_exists)
+      return false;
 
     // Confirm the downloaded data file exists.
-    ASSERT_TRUE(file_util::PathExists(downloaded_file));
+    bool downloaded_file_exists = file_util::PathExists(downloaded_file);
+    EXPECT_TRUE(downloaded_file_exists);
+    if (!downloaded_file_exists)
+      return false;
+
     int64 origin_file_size = 0;
     int64 downloaded_file_size = 0;
     EXPECT_TRUE(file_util::GetFileSize(origin_file, &origin_file_size));
@@ -268,14 +362,69 @@
     EXPECT_EQ(origin_file_size, downloaded_file_size);
     EXPECT_TRUE(file_util::ContentsEqual(downloaded_file, origin_file));
 
-#if defined(OS_WIN)
-    // Check if the Zone Identifier is correctly set.
-    if (file_util::VolumeSupportsADS(downloaded_file))
-      EXPECT_TRUE(file_util::HasInternetZoneIdentifier(downloaded_file));
-#endif
-
     // Delete the downloaded copy of the file.
-    EXPECT_TRUE(file_util::DieFileDie(downloaded_file, false));
+    bool downloaded_file_deleted =
+        file_util::DieFileDie(downloaded_file, false);
+    EXPECT_TRUE(downloaded_file_deleted);
+    return downloaded_file_deleted;
+  }
+
+  // TODO(ahendrickson) -- |expected_title_in_progress| and
+  // |expected_title_finished| need to be checked.
+  bool RunSizeTest(Browser* browser,
+                   const GURL& url,
+                   const string16& expected_title_in_progress,
+                   const string16& expected_title_finished) {
+    if (!InitialSetup(false))
+      return false;
+
+    // Download a partial web page in a background tab and wait.
+    // The mock system will not complete until it gets a special URL.
+    scoped_ptr<DownloadsObserver> observer(CreateWaiter(browser, 1));
+    ui_test_utils::NavigateToURL(browser, url);
+
+    // TODO(ahendrickson): check download status text before downloading.
+    // Need to:
+    //  - Add a member function to the |DownloadShelf| interface class, that
+    //    indicates how many members it has.
+    //  - Add a member function to |DownloadShelf| to get the status text
+    //    of a given member (for example, via |DownloadItemView|'s
+    //    GetAccessibleName() member function), by index.
+    //  - Iterate over browser->window()->GetDownloadShelf()'s members
+    //    to see if any match the status text we want.  Start with the last one.
+
+    // Complete sending the request.  We do this by loading a second URL in a
+    // separate tab.
+    GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
+    ui_test_utils::NavigateToURLWithDisposition(
+        browser,
+        finish_url,
+        NEW_FOREGROUND_TAB,
+        ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+    observer->WaitForFinished();
+
+    EXPECT_EQ(2, browser->tab_count());
+
+    // TODO(ahendrickson): check download status text after downloading.
+
+    // Make sure the download shelf is showing.
+    EXPECT_TRUE(browser->window()->IsDownloadShelfVisible());
+
+    FilePath filename;
+    net::FileURLToFilePath(url, &filename);
+    filename = filename.BaseName();
+    FilePath download_path = downloads_directory_.path().Append(filename);
+
+    bool downloaded_path_exists = file_util::PathExists(download_path);
+    EXPECT_TRUE(downloaded_path_exists);
+    if (!downloaded_path_exists)
+      return false;
+
+    // Delete the file we just downloaded.
+    EXPECT_TRUE(file_util::DieFileDie(download_path, true));
+    EXPECT_FALSE(file_util::PathExists(download_path));
+
+    return true;
   }
 
  private:
@@ -286,51 +435,534 @@
   ScopedTempDir downloads_directory_;
 };
 
+// NOTES:
+//
+// Files for these tests are found in DIR_TEST_DATA (currently
+// "chrome\test\data\", see chrome_paths.cc).
+// Mock responses have extension .mock-http-headers appended to the file name.
+
+// Download a file due to the associated MIME type.
+//
 // Test is believed good (non-flaky) in itself, but it
 // sometimes trips over underlying flakiness in the downloads
 // subsystem in in http://crbug.com/63237.  Until that bug is
 // fixed, this test should be considered flaky.  It's entered as
 // DISABLED since if 63237 does cause a failure, it'll be a timeout.
 IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DownloadMimeType) {
+  ASSERT_TRUE(InitialSetup(false));
   FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
-  ASSERT_TRUE(CreateAndSetDownloadsDirectory());
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
 
+  // Download the file and wait.  We do not expect the Select File dialog.
+  DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
+
+  // Check state.
   EXPECT_EQ(1, browser()->tab_count());
-
-  // Setup notification, navigate, and block.
-  scoped_ptr<DownloadsObserver> observer(CreateWaiter(1));
-  ui_test_utils::NavigateToURL(
-      browser(), URLRequestMockHTTPJob::GetMockUrl(file));
-  observer->WaitForFinished();
-
-  // Download should be finished; check state.
-  EXPECT_FALSE(observer->select_file_dialog_seen());
-  EXPECT_EQ(1, browser()->tab_count());
-  CheckDownload(file, file);
+  CheckDownload(browser(), file, file);
   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
 }
 
+#if defined(OS_WIN)
+// Download a file and confirm that the zone identifier (on windows)
+// is set to internet.
+// This is flaky due to http://crbug.com/20809.  It's marked as
+// DISABLED because when the test fails it fails via a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_CheckInternetZone) {
+  ASSERT_TRUE(InitialSetup(false));
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+
+  // Download the file and wait.  We do not expect the Select File dialog.
+  DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
+
+  // Check state.
+  EXPECT_EQ(1, browser()->tab_count());
+  CheckDownload(browser(), file, file);
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+
+  FilePath downloaded_file = GetDownloadDirectory(browser()).Append(file);
+  if (file_util::VolumeSupportsADS(downloaded_file))
+    EXPECT_TRUE(file_util::HasInternetZoneIdentifier(downloaded_file));
+}
+#endif
+
+// Put up a Select File dialog when the file is downloaded, due to its MIME
+// type.
+//
 // This test runs correctly, but leaves behind turds in the test user's
 // download directory because of http://crbug.com/62099.  No big loss; it
 // was primarily confirming DownloadsObserver wait on select file dialog
 // functionality anyway.
 IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DownloadMimeTypeSelect) {
+  ASSERT_TRUE(InitialSetup(true));
   FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
-  ASSERT_TRUE(CreateAndSetDownloadsDirectory());
-  browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload, true);
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
 
+  // Download the file and wait.  We expect the Select File dialog to appear
+  // due to the MIME type.
+  DownloadAndWait(browser(), url, EXPECT_SELECT_DIALOG);
+
+  // Check state.
   EXPECT_EQ(1, browser()->tab_count());
+  // Since we exited while the Select File dialog was visible, there should not
+  // be anything in the download shelf and so it should not be visible.
+  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
+}
 
-  // Setup notification, navigate, and block.
-  scoped_ptr<DownloadsObserver> observer(CreateWaiter(1));
-  ui_test_utils::NavigateToURL(
-      browser(), URLRequestMockHTTPJob::GetMockUrl(file));
-  observer->WaitForFinished();
+// Access a file with a viewable mime-type, verify that a download
+// did not initiate.
+IN_PROC_BROWSER_TEST_F(DownloadTest, NoDownload) {
+  ASSERT_TRUE(InitialSetup(false));
+  FilePath file(FILE_PATH_LITERAL("download-test2.html"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+  FilePath file_path = GetDownloadDirectory(browser()).Append(file);
 
-  // Download should not be finished; check state.
-  EXPECT_TRUE(observer->select_file_dialog_seen());
+  // Open a web page and wait.
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // Check that we did not download the web page.
+  EXPECT_FALSE(file_util::PathExists(file_path));
+
+  // Check state.
   EXPECT_EQ(1, browser()->tab_count());
   EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
 }
 
+// Download a 0-size file with a content-disposition header, verify that the
+// download tab opened and the file exists as the filename specified in the
+// header.  This also ensures we properly handle empty file downloads.
+// The download shelf should be visible in the current tab.
+//
+// Test is believed mostly good (non-flaky) in itself, but it
+// sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  Until that bug is
+// fixed, this test should be considered flaky.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_ContentDisposition) {
+  ASSERT_TRUE(InitialSetup(false));
+  FilePath file(FILE_PATH_LITERAL("download-test3.gif"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+  FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif"));
+
+  // Download a file and wait.
+  DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
+
+  CheckDownload(browser(), download_file, file);
+
+  // Check state.
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+}
+
+// Test that the download shelf is per-window by starting a download in one
+// tab, opening a second tab, closing the shelf, going back to the first tab,
+// and checking that the shelf is closed.
+//
+// The test sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_PerWindowShelf) {
+  ASSERT_TRUE(InitialSetup(false));
+  FilePath file(FILE_PATH_LITERAL("download-test3.gif"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+  FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif"));
+
+  // Download a file and wait.
+  DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
+
+  CheckDownload(browser(), download_file, file);
+
+  // Check state.
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+
+  // Open a second tab and wait.
+  EXPECT_NE(static_cast<TabContentsWrapper*>(NULL),
+            browser()->AddSelectedTabWithURL(GURL(), PageTransition::TYPED));
+  EXPECT_EQ(2, browser()->tab_count());
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+
+  // Hide the download shelf.
+  browser()->window()->GetDownloadShelf()->Close();
+  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
+
+  // Go to the first tab.
+  browser()->SelectTabContentsAt(0, true);
+  EXPECT_EQ(2, browser()->tab_count());
+
+  // The download shelf should not be visible.
+  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
+}
+
+// UnknownSize and KnownSize are tests which depend on
+// URLRequestSlowDownloadJob to serve content in a certain way. Data will be
+// sent in two chunks where the first chunk is 35K and the second chunk is 10K.
+// The test will first attempt to download a file; but the server will "pause"
+// in the middle until the server receives a second request for
+// "download-finish".  At that time, the download will finish.
+// These tests don't currently test much due to holes in |RunSizeTest()|.  See
+// comments in that routine for details.
+
+// Test is believed mostly good (non-flaky) in itself, but it
+// very occasionally trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  Until that bug is
+// fixed, this test should be considered flaky.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_UnknownSize) {
+  GURL url(URLRequestSlowDownloadJob::kUnknownSizeUrl);
+  FilePath filename;
+  net::FileURLToFilePath(url, &filename);
+  filename = filename.BaseName();
+  ASSERT_TRUE(RunSizeTest(
+                  browser(),
+                  url,
+                  ASCIIToUTF16("32.0 KB - ") + filename.LossyDisplayName(),
+                  ASCIIToUTF16("100% - ") + filename.LossyDisplayName()));
+}
+
+// Test is believed mostly good (non-flaky) in itself, but it
+// very occasionally trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  Until that bug is
+// fixed, this test should be considered flaky.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_KnownSize) {
+  GURL url(URLRequestSlowDownloadJob::kKnownSizeUrl);
+  FilePath filename;
+  net::FileURLToFilePath(url, &filename);
+  filename = filename.BaseName();
+  ASSERT_TRUE(RunSizeTest(
+                  browser(),
+                  url,
+                  ASCIIToUTF16("71% - ") + filename.LossyDisplayName(),
+                  ASCIIToUTF16("100% - ") + filename.LossyDisplayName()));
+}
+
+// Test that when downloading an item in Incognito mode, we don't crash when
+// closing the last Incognito window (http://crbug.com/13983).
+// Also check that the download shelf is not visible after closing the
+// Incognito window.
+//
+// Test is believed mostly good (non-flaky) in itself, but it
+// sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  Until that bug is
+// fixed, this test should be considered flaky.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_IncognitoDownload) {
+  ASSERT_TRUE(InitialSetup(false));
+
+  // Open an Incognito window.
+  Browser* incognito = CreateIncognitoBrowser();  // Waits.
+  ASSERT_TRUE(incognito);
+  int window_count = BrowserList::size();
+  EXPECT_EQ(2, window_count);
+
+  // Download a file in the Incognito window and wait.
+  CreateAndSetDownloadsDirectory(incognito);
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+  // Since |incognito| is a separate browser, we have to set it up explicitly.
+  incognito->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
+                                               false);
+  DownloadAndWait(incognito, url, EXPECT_NO_SELECT_DIALOG);
+
+  // We should still have 2 windows.
+  window_count = BrowserList::size();
+  EXPECT_EQ(2, window_count);
+
+  // Verify that the download shelf is showing for the Incognito window.
+  bool is_shelf_visible = incognito->window()->IsDownloadShelfVisible();
+  EXPECT_TRUE(is_shelf_visible);
+
+  // Close the Incognito window and don't crash.
+  incognito->CloseWindow();
+#if !defined(OS_MACOSX)
+  // On Mac OS X, the UI window close is delayed until the outermost
+  // message loop runs.  So it isn't possible to get a BROWSER_CLOSED
+  // notification inside of a test.
+  ui_test_utils::WaitForNotificationFrom(NotificationType::BROWSER_CLOSED,
+                                         Source<Browser>(incognito));
+
+  window_count = BrowserList::size();
+  EXPECT_EQ(1, window_count);
+#endif
+
+  // Verify that the regular window does not have a download shelf.
+  is_shelf_visible = browser()->window()->IsDownloadShelfVisible();
+  EXPECT_FALSE(is_shelf_visible);
+
+  CheckDownload(browser(), file, file);
+}
+
+// Navigate to a new background page, but don't download.  Confirm that the
+// download shelf is not visible and that we have two tabs.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab1) {
+  ASSERT_TRUE(InitialSetup(false));
+  // Because it's an HTML link, it should open a web page rather than
+  // downloading.
+  FilePath file1(FILE_PATH_LITERAL("download-test2.html"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
+
+  // Open a web page and wait.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      url,
+      NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  // We should have two tabs now.
+  EXPECT_EQ(2, browser()->tab_count());
+  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
+}
+
+// Download a file in a background tab. Verify that the tab is closed
+// automatically, and that the download shelf is visible in the current tab.
+//
+// The test sometimes trips over underlying flakiness in the downloads
+// subsystem in http://crbug.com/63237.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_CloseNewTab1) {
+  ASSERT_TRUE(InitialSetup(false));
+
+  // Download a file in a new background tab and wait.  The tab is automatically
+  // closed when the download begins.
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+  DownloadAndWaitWithDisposition(
+      browser(),
+      url,
+      NEW_BACKGROUND_TAB,
+      EXPECT_NO_SELECT_DIALOG,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  // When the download finishes, we should still have one tab.
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+  EXPECT_EQ(1, browser()->tab_count());
+
+  CheckDownload(browser(), file, file);
+}
+
+// Open a web page in the current tab, then download a file in another tab via
+// a Javascript call.
+// Verify that we have 2 tabs, and the download shelf is visible in the current
+// tab.
+//
+// The download_page1.html page contains an openNew() function that opens a
+// tab and then downloads download-test1.lib.
+//
+// The test sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DontCloseNewTab2) {
+  ASSERT_TRUE(InitialSetup(false));
+  // Because it's an HTML link, it should open a web page rather than
+  // downloading.
+  FilePath file1(FILE_PATH_LITERAL("download_page1.html"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
+
+  // Open a web page and wait.
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // Download a file in a new tab and wait (via Javascript).
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  DownloadAndWaitWithDisposition(browser(),
+                                 GURL("javascript:openNew()"),
+                                 CURRENT_TAB,
+                                 EXPECT_NO_SELECT_DIALOG,
+                                 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  // When the download finishes, we should have two tabs.
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+  EXPECT_EQ(2, browser()->tab_count());
+
+  CheckDownload(browser(), file, file);
+}
+
+// Open a web page in the current tab, open another tab via a Javascript call,
+// then download a file in the new tab.
+// Verify that we have 2 tabs, and the download shelf is visible in the current
+// tab.
+//
+// The download_page2.html page contains an openNew() function that opens a
+// tab.
+//
+// The test sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DontCloseNewTab3) {
+  ASSERT_TRUE(InitialSetup(false));
+  // Because it's an HTML link, it should open a web page rather than
+  // downloading.
+  FilePath file1(FILE_PATH_LITERAL("download_page2.html"));
+  GURL url1(URLRequestMockHTTPJob::GetMockUrl(file1));
+
+  // Open a web page and wait.
+  ui_test_utils::NavigateToURL(browser(), url1);
+
+  // Open a new tab and wait.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL("javascript:openNew()"),
+      CURRENT_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  EXPECT_EQ(2, browser()->tab_count());
+
+  // Download a file and wait.
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+  DownloadAndWaitWithDisposition(browser(),
+                                 url,
+                                 CURRENT_TAB,
+                                 EXPECT_NO_SELECT_DIALOG,
+                                 ui_test_utils::BROWSER_TEST_NONE);
+
+  // When the download finishes, we should have two tabs.
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+  EXPECT_EQ(2, browser()->tab_count());
+
+  CheckDownload(browser(), file, file);
+}
+
+// Open a web page in the current tab, then download a file via Javascript,
+// which will do so in a temporary tab.
+// Verify that we have 1 tab, and the download shelf is visible.
+//
+// The download_page3.html page contains an openNew() function that opens a
+// tab with download-test1.lib in the URL.  When the URL is determined to be
+// a download, the tab is closed automatically.
+//
+// The test sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_CloseNewTab2) {
+  ASSERT_TRUE(InitialSetup(false));
+  // Because it's an HTML link, it should open a web page rather than
+  // downloading.
+  FilePath file1(FILE_PATH_LITERAL("download_page3.html"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
+
+  // Open a web page and wait.
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // Download a file and wait.
+  // The file to download is "download-test1.lib".
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  DownloadAndWaitWithDisposition(browser(),
+                                 GURL("javascript:openNew()"),
+                                 CURRENT_TAB,
+                                 EXPECT_NO_SELECT_DIALOG,
+                                 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  // When the download finishes, we should still have one tab.
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+  EXPECT_EQ(1, browser()->tab_count());
+
+  CheckDownload(browser(), file, file);
+}
+
+// Open a web page in the current tab, then call Javascript via a button to
+// download a file in a new tab, which is closed automatically when the
+// download begins.
+// Verify that we have 1 tab, and the download shelf is visible.
+//
+// The download_page4.html page contains a form with download-test1.lib as the
+// action.
+//
+// The test sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_CloseNewTab3) {
+  ASSERT_TRUE(InitialSetup(false));
+  // Because it's an HTML link, it should open a web page rather than
+  // downloading.
+  FilePath file1(FILE_PATH_LITERAL("download_page4.html"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
+
+  // Open a web page and wait.
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // Download a file in a new tab and wait.  The tab will automatically close
+  // when the download begins.
+  // The file to download is "download-test1.lib".
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  DownloadAndWaitWithDisposition(
+      browser(),
+      GURL("javascript:document.getElementById('form').submit()"),
+      CURRENT_TAB,
+      EXPECT_NO_SELECT_DIALOG,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  // When the download finishes, we should still have one tab.
+  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+  EXPECT_EQ(1, browser()->tab_count());
+
+  CheckDownload(browser(), file, file);
+}
+
+// Download a file in a new window.
+// Verify that we have 2 windows, and the download shelf is not visible in the
+// first window, but is visible in the second window.
+// Close the new window.
+// Verify that we have 1 window, and the download shelf is not visible.
+//
+// Regression test for http://crbug.com/44454
+//
+// Test is believed mostly good (non-flaky) in itself, but it
+// sometimes trips over underlying flakiness in the downloads
+// subsystem in in http://crbug.com/63237.  Until that bug is
+// fixed, this test should be considered flaky.  It's entered as
+// DISABLED since if 63237 does cause a failure, it'll be a timeout.
+IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_NewWindow) {
+  ASSERT_TRUE(InitialSetup(false));
+  FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
+  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+#if !defined(OS_MACOSX)
+  // See below.
+  Browser* first_browser = browser();
+#endif
+
+  // Download a file in a new window and wait.
+  DownloadAndWaitWithDisposition(browser(),
+                                 url,
+                                 NEW_WINDOW,
+                                 EXPECT_NO_SELECT_DIALOG,
+                                 ui_test_utils::BROWSER_TEST_NONE);
+
+  // When the download finishes, the download shelf SHOULD NOT be visible in
+  // the first window.
+  int window_count = BrowserList::size();
+  EXPECT_EQ(2, window_count);
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
+
+  // The download shelf SHOULD be visible in the second window.
+  std::set<Browser*> original_browsers;
+  original_browsers.insert(browser());
+  Browser* download_browser =
+      ui_test_utils::GetBrowserNotInSet(original_browsers);
+  ASSERT_TRUE(download_browser != NULL);
+  EXPECT_NE(download_browser, browser());
+  EXPECT_EQ(1, download_browser->tab_count());
+  EXPECT_TRUE(download_browser->window()->IsDownloadShelfVisible());
+
+  // Close the new window.
+  download_browser->CloseWindow();
+#if !defined(OS_MACOSX)
+  // On Mac OS X, the UI window close is delayed until the outermost
+  // message loop runs.  So it isn't possible to get a BROWSER_CLOSED
+  // notification inside of a test.
+  ui_test_utils::WaitForNotificationFrom(NotificationType::BROWSER_CLOSED,
+                                         Source<Browser>(download_browser));
+  EXPECT_EQ(first_browser, browser());
+  window_count = BrowserList::size();
+  EXPECT_EQ(1, window_count);
+#endif
+
+  EXPECT_EQ(1, browser()->tab_count());
+  // The download shelf should not be visible in the remaining window.
+  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
+
+  CheckDownload(browser(), file, file);
+}
+
 }  // namespace
diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc
index f9bcd1b..a6a7b97 100644
--- a/chrome/browser/download/download_file.cc
+++ b/chrome/browser/download/download_file.cc
@@ -32,10 +32,10 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 }
 
-void DownloadFile::DeleteCrDownload() {
+bool DownloadFile::DeleteCrDownload() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   FilePath crdownload = download_util::GetCrDownloadPath(full_path_);
-  file_util::Delete(crdownload, false);
+  return file_util::Delete(crdownload, false);
 }
 
 void DownloadFile::CancelDownloadRequest(ResourceDispatcherHost* rdh) {
diff --git a/chrome/browser/download/download_file.h b/chrome/browser/download/download_file.h
index fb00f06..a233717 100644
--- a/chrome/browser/download/download_file.h
+++ b/chrome/browser/download/download_file.h
@@ -29,7 +29,8 @@
 
   // Deletes its .crdownload intermediate file.
   // Marked virtual for testing.
-  virtual void DeleteCrDownload();
+  // Returns true if the file was deleted.
+  virtual bool DeleteCrDownload();
 
   // Cancels the download request associated with this file.
   void CancelDownloadRequest(ResourceDispatcherHost* rdh);
diff --git a/chrome/browser/download/download_file_manager.cc b/chrome/browser/download/download_file_manager.cc
index 07eb72d..69f6dbd 100644
--- a/chrome/browser/download/download_file_manager.cc
+++ b/chrome/browser/download/download_file_manager.cc
@@ -18,17 +18,12 @@
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/io_buffer.h"
 
-#if defined(OS_WIN)
-#include "chrome/common/win_safe_util.h"
-#elif defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/file_metadata.h"
-#endif
-
 namespace {
 
 // Throttle updates to the UI thread so that a fast moving download doesn't
@@ -74,14 +69,15 @@
   STLDeleteValues(&downloads_);
 }
 
-void DownloadFileManager::CreateDownloadFile(
-    DownloadCreateInfo* info, DownloadManager* download_manager) {
+void DownloadFileManager::CreateDownloadFile(DownloadCreateInfo* info,
+                                             DownloadManager* download_manager,
+                                             bool get_hash) {
   VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
-  scoped_ptr<DownloadFile> download_file(
-      new DownloadFile(info, download_manager));
-  if (!download_file->Initialize()) {
+  scoped_ptr<DownloadFile>
+      download_file(new DownloadFile(info, download_manager));
+  if (!download_file->Initialize(get_hash)) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         NewRunnableFunction(&download_util::CancelDownloadRequest,
@@ -177,9 +173,12 @@
 
   manager->CreateDownloadItem(info);
 
+  bool hash_needed = resource_dispatcher_host_->safe_browsing_service()->
+      DownloadBinHashNeeded();
+
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
       NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile,
-                        info, make_scoped_refptr(manager)));
+                        info, make_scoped_refptr(manager), hash_needed));
 }
 
 // We don't forward an update to the UI thread here, since we want to throttle
@@ -191,7 +190,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   std::vector<DownloadBuffer::Contents> contents;
   {
-    AutoLock auto_lock(buffer->lock);
+    base::AutoLock auto_lock(buffer->lock);
     contents.swap(buffer->contents);
   }
 
@@ -312,7 +311,7 @@
 // There are 3 possible rename cases where this method can be called:
 // 1. tmp -> foo            (need_delete_crdownload=T)
 // 2. foo.crdownload -> foo (need_delete_crdownload=F)
-// 3. tmp-> unconfirmed.xxx.crdownload (need_delete_crdownload=F)
+// 3. tmp-> Unconfirmed.xxx.crdownload (need_delete_crdownload=F)
 void DownloadFileManager::OnFinalDownloadName(
     int id, const FilePath& full_path, bool need_delete_crdownload,
     DownloadManager* download_manager) {
diff --git a/chrome/browser/download/download_file_manager.h b/chrome/browser/download/download_file_manager.h
index 5ccf533..00b14fe 100644
--- a/chrome/browser/download/download_file_manager.h
+++ b/chrome/browser/download/download_file_manager.h
@@ -46,7 +46,7 @@
 #include "base/hash_tables.h"
 #include "base/ref_counted.h"
 #include "base/timer.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 struct DownloadBuffer;
 struct DownloadCreateInfo;
@@ -115,7 +115,8 @@
   // Creates DownloadFile on FILE thread and continues starting the download
   // process.
   void CreateDownloadFile(DownloadCreateInfo* info,
-                          DownloadManager* download_manager);
+                          DownloadManager* download_manager,
+                          bool hash_needed);
 
   // Tells the ResourceDispatcherHost to resume a download request
   // that was paused to wait for the on-disk file to be created.
diff --git a/chrome/browser/download/download_file_unittest.cc b/chrome/browser/download/download_file_unittest.cc
new file mode 100644
index 0000000..06cd7c3
--- /dev/null
+++ b/chrome/browser/download/download_file_unittest.cc
@@ -0,0 +1,295 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/scoped_temp_dir.h"
+#include "base/string_number_conversions.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/download/download_file.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_status_updater.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/mock_download_manager.h"
+#include "chrome/browser/history/download_create_info.h"
+#include "net/base/file_stream.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class DownloadFileTest : public testing::Test {
+ public:
+
+  static const char* kTestData1;
+  static const char* kTestData2;
+  static const char* kTestData3;
+  static const char* kDataHash;
+  static const int32 kDummyDownloadId;
+  static const int kDummyChildId;
+  static const int kDummyRequestId;
+
+  // We need a UI |BrowserThread| in order to destruct |download_manager_|,
+  // which has trait |BrowserThread::DeleteOnUIThread|.  Without this,
+  // calling Release() on |download_manager_| won't ever result in its
+  // destructor being called and we get a leak.
+  DownloadFileTest() :
+      ui_thread_(BrowserThread::UI, &loop_),
+      file_thread_(BrowserThread::FILE, &loop_) {
+  }
+
+  ~DownloadFileTest() {
+  }
+
+  virtual void SetUp() {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    download_manager_ = new MockDownloadManager(&download_status_updater_);
+  }
+
+  virtual void TearDown() {
+    // When a DownloadManager's reference count drops to 0, it is not
+    // deleted immediately. Instead, a task is posted to the UI thread's
+    // message loop to delete it.
+    // So, drop the reference count to 0 and run the message loop once
+    // to ensure that all resources are cleaned up before the test exits.
+    download_manager_ = NULL;
+    ui_thread_.message_loop()->RunAllPending();
+  }
+
+  virtual void CreateDownloadFile(scoped_ptr<DownloadFile>* file, int offset) {
+    DownloadCreateInfo info;
+    info.download_id = kDummyDownloadId + offset;
+    info.child_id = kDummyChildId;
+    info.request_id = kDummyRequestId - offset;
+    info.save_info.file_stream = file_stream_;
+    file->reset(new DownloadFile(&info, download_manager_));
+  }
+
+  virtual void DestroyDownloadFile(scoped_ptr<DownloadFile>* file, int offset) {
+    EXPECT_EQ(kDummyDownloadId + offset, (*file)->id());
+    EXPECT_EQ(download_manager_, (*file)->GetDownloadManager());
+    EXPECT_FALSE((*file)->in_progress());
+    EXPECT_EQ(static_cast<int64>(expected_data_.size()),
+              (*file)->bytes_so_far());
+
+    // Make sure the data has been properly written to disk.
+    std::string disk_data;
+    EXPECT_TRUE(file_util::ReadFileToString((*file)->full_path(),
+                                            &disk_data));
+    EXPECT_EQ(expected_data_, disk_data);
+
+    // Make sure the mock BrowserThread outlives the DownloadFile to satisfy
+    // thread checks inside it.
+    file->reset();
+  }
+
+  void AppendDataToFile(scoped_ptr<DownloadFile>* file,
+                        const std::string& data) {
+    EXPECT_TRUE((*file)->in_progress());
+    (*file)->AppendDataToFile(data.data(), data.size());
+    expected_data_ += data;
+    EXPECT_EQ(static_cast<int64>(expected_data_.size()),
+              (*file)->bytes_so_far());
+  }
+
+ protected:
+  // Temporary directory for renamed downloads.
+  ScopedTempDir temp_dir_;
+
+  DownloadStatusUpdater download_status_updater_;
+  scoped_refptr<DownloadManager> download_manager_;
+
+  linked_ptr<net::FileStream> file_stream_;
+
+  // DownloadFile instance we are testing.
+  scoped_ptr<DownloadFile> download_file_;
+
+ private:
+  MessageLoop loop_;
+  // UI thread.
+  BrowserThread ui_thread_;
+  // File thread to satisfy debug checks in DownloadFile.
+  BrowserThread file_thread_;
+
+  // Keep track of what data should be saved to the disk file.
+  std::string expected_data_;
+};
+
+const char* DownloadFileTest::kTestData1 =
+    "Let's write some data to the file!\n";
+const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
+const char* DownloadFileTest::kTestData3 = "Final line.";
+const char* DownloadFileTest::kDataHash =
+    "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
+
+const int32 DownloadFileTest::kDummyDownloadId = 23;
+const int DownloadFileTest::kDummyChildId = 3;
+const int DownloadFileTest::kDummyRequestId = 67;
+
+// Rename the file before any data is downloaded, after some has, after it all
+// has, and after it's closed.  File is marked as having the final rename.
+TEST_F(DownloadFileTest, RenameFileFinal) {
+  CreateDownloadFile(&download_file_, 0);
+  ASSERT_TRUE(download_file_->Initialize(true));
+  FilePath initial_path(download_file_->full_path());
+  EXPECT_TRUE(file_util::PathExists(initial_path));
+  FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
+  FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2"));
+  FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3"));
+  FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4"));
+
+  // Rename the file before downloading any data.
+  EXPECT_TRUE(download_file_->Rename(path_1, true));
+  FilePath renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_1, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(initial_path));
+  EXPECT_TRUE(file_util::PathExists(path_1));
+
+  // Download the data.
+  AppendDataToFile(&download_file_, kTestData1);
+  AppendDataToFile(&download_file_, kTestData2);
+
+  // Rename the file after downloading some data.
+  EXPECT_TRUE(download_file_->Rename(path_2, true));
+  renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_2, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(path_1));
+  EXPECT_TRUE(file_util::PathExists(path_2));
+
+  AppendDataToFile(&download_file_, kTestData3);
+
+  // Rename the file after downloading all the data.
+  EXPECT_TRUE(download_file_->Rename(path_3, true));
+  renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_3, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(path_2));
+  EXPECT_TRUE(file_util::PathExists(path_3));
+
+  // Should not be able to get the hash until the file is closed.
+  std::string hash;
+  EXPECT_FALSE(download_file_->GetSha256Hash(&hash));
+
+  download_file_->Finish();
+
+  // Rename the file after downloading all the data and closing the file.
+  EXPECT_TRUE(download_file_->Rename(path_4, true));
+  renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_4, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(path_3));
+  EXPECT_TRUE(file_util::PathExists(path_4));
+
+  // Check the hash.
+  EXPECT_TRUE(download_file_->path_renamed());
+  EXPECT_TRUE(download_file_->GetSha256Hash(&hash));
+  EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));
+
+  DestroyDownloadFile(&download_file_, 0);
+}
+
+// Rename the file before any data is downloaded, after some has, after it all
+// has, and after it's closed.  File is not marked as having the final rename.
+TEST_F(DownloadFileTest, RenameFileNoFinal) {
+  CreateDownloadFile(&download_file_, 1);
+  ASSERT_TRUE(download_file_->Initialize(true));
+  FilePath initial_path(download_file_->full_path());
+  EXPECT_TRUE(file_util::PathExists(initial_path));
+  FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
+  FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2"));
+  FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3"));
+  FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4"));
+
+  // Rename the file before downloading any data.
+  EXPECT_TRUE(download_file_->Rename(path_1, false));
+  FilePath renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_1, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(initial_path));
+  EXPECT_TRUE(file_util::PathExists(path_1));
+
+  // Download the data.
+  AppendDataToFile(&download_file_, kTestData1);
+  AppendDataToFile(&download_file_, kTestData2);
+
+  // Rename the file after downloading some data.
+  EXPECT_TRUE(download_file_->Rename(path_2, false));
+  renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_2, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(path_1));
+  EXPECT_TRUE(file_util::PathExists(path_2));
+
+  AppendDataToFile(&download_file_, kTestData3);
+
+  // Rename the file after downloading all the data.
+  EXPECT_TRUE(download_file_->Rename(path_3, false));
+  renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_3, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(path_2));
+  EXPECT_TRUE(file_util::PathExists(path_3));
+
+  // Should not be able to get the hash until the file is closed.
+  std::string hash;
+  EXPECT_FALSE(download_file_->GetSha256Hash(&hash));
+
+  download_file_->Finish();
+
+  // Rename the file after downloading all the data and closing the file.
+  EXPECT_TRUE(download_file_->Rename(path_4, false));
+  renamed_path = download_file_->full_path();
+  EXPECT_EQ(path_4, renamed_path);
+
+  // Check the files.
+  EXPECT_FALSE(file_util::PathExists(path_3));
+  EXPECT_TRUE(file_util::PathExists(path_4));
+
+  // Check the hash.
+  EXPECT_FALSE(download_file_->path_renamed());
+  EXPECT_TRUE(download_file_->GetSha256Hash(&hash));
+  EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));
+
+  DestroyDownloadFile(&download_file_, 1);
+}
+
+// Test that DeleteCrDownload deletes the file specified in DonloadFile, but
+// with '.crdownload' appended to the name.
+TEST_F(DownloadFileTest, DeleteCrDownload) {
+  // Create and delete a temporary file, to use its file name.
+  FilePath primary_path;
+  EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
+                                                  &primary_path));
+  file_util::Delete(primary_path, false);
+  EXPECT_FALSE(file_util::PathExists(primary_path));
+
+  // Create a '.crdownload' version of the file.
+  FilePath crdownload_path(download_util::GetCrDownloadPath(primary_path));
+  FILE* f = file_util::OpenFile(crdownload_path, "w");
+  file_util::CloseFile(f);
+  EXPECT_TRUE(file_util::PathExists(crdownload_path));
+
+  // Create a DownloadFile with the temp file name.
+  scoped_ptr<DownloadFile> checked_file;
+  CreateDownloadFile(&checked_file, 3);
+
+  ASSERT_TRUE(checked_file->Initialize(false));
+  EXPECT_TRUE(checked_file->Rename(primary_path, false));
+  FilePath renamed_path(checked_file->full_path());
+  EXPECT_TRUE(file_util::PathExists(renamed_path));
+
+  // Delete the '.crdownload' version.
+  EXPECT_TRUE(checked_file->DeleteCrDownload());
+  EXPECT_FALSE(file_util::PathExists(crdownload_path));
+
+  checked_file->Finish();
+
+  DestroyDownloadFile(&checked_file, 3);
+}
diff --git a/chrome/browser/download/download_item.cc b/chrome/browser/download/download_item.cc
index db0c9ea..beb9cf7 100644
--- a/chrome/browser/download/download_item.cc
+++ b/chrome/browser/download/download_item.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/download/download_item.h"
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/file_util.h"
 #include "base/format_macros.h"
@@ -26,6 +25,24 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/pref_names.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// A DownloadItem normally goes through the following states:
+//      * Created (when download starts)
+//      * Made visible to consumers (e.g. Javascript) after the
+//        destination file has been determined.
+//      * Entered into the history database.
+//      * Made visible in the download shelf.
+//      * All data is received.  Note that the actual data download occurs
+//        in parallel with the above steps, but until those steps are
+//        complete, completion of the data download will be ignored.
+//      * Download file is renamed to its final name, and possibly
+//        auto-opened.
+// TODO(rdsmith): This progress should be reflected in
+// DownloadItem::DownloadState and a state transition table/state diagram.
+//
+// TODO(rdsmith): This description should be updated to reflect the cancel
+// pathways.
 
 namespace {
 
@@ -79,6 +96,7 @@
       full_path_(info.path),
       path_uniquifier_(0),
       url_(info.url),
+      original_url_(info.original_url),
       referrer_url_(info.referrer_url),
       mime_type_(info.mime_type),
       original_mime_type_(info.original_mime_type),
@@ -101,9 +119,12 @@
       is_extension_install_(info.is_extension_install),
       name_finalized_(false),
       is_temporary_(false),
+      all_data_saved_(false),
       opened_(false) {
   if (state_ == IN_PROGRESS)
     state_ = CANCELLED;
+  if (state_ == COMPLETE)
+    all_data_saved_ = true;
   Init(false /* don't start progress timer */);
 }
 
@@ -115,6 +136,7 @@
       full_path_(info.path),
       path_uniquifier_(info.path_uniquifier),
       url_(info.url),
+      original_url_(info.original_url),
       referrer_url_(info.referrer_url),
       mime_type_(info.mime_type),
       original_mime_type_(info.original_mime_type),
@@ -137,6 +159,7 @@
       is_extension_install_(info.is_extension_install),
       name_finalized_(false),
       is_temporary_(!info.save_info.file_path.empty()),
+      all_data_saved_(false),
       opened_(false) {
   Init(true /* start progress timer */);
 }
@@ -150,6 +173,7 @@
       full_path_(path),
       path_uniquifier_(0),
       url_(url),
+      original_url_(url),
       referrer_url_(GURL()),
       mime_type_(std::string()),
       original_mime_type_(std::string()),
@@ -171,6 +195,7 @@
       is_extension_install_(false),
       name_finalized_(false),
       is_temporary_(false),
+      all_data_saved_(false),
       opened_(false) {
   Init(true /* start progress timer */);
 }
@@ -296,8 +321,14 @@
     download_manager_->DownloadCancelled(id_);
 }
 
-void DownloadItem::OnAllDataSaved(int64 size) {
+void DownloadItem::MarkAsComplete() {
+  DCHECK(all_data_saved_);
   state_ = COMPLETE;
+}
+
+void DownloadItem::OnAllDataSaved(int64 size) {
+  DCHECK(!all_data_saved_);
+  all_data_saved_ = true;
   UpdateSize(size);
   StopProgressTimer();
 }
@@ -321,7 +352,7 @@
     auto_opened_ = true;
   }
 
-  // Notify our observers that we are complete (the call to OnAllDataSaved()
+  // Notify our observers that we are complete (the call to MarkAsComplete()
   // set the state to complete but did not notify).
   UpdateObservers();
 
@@ -329,8 +360,10 @@
   // finalized and the file data is downloaded. The ordering of these two
   // actions is indeterministic. Thus, if the filename is not finalized yet,
   // delay the notification.
-  if (name_finalized())
+  if (name_finalized()) {
     NotifyObserversDownloadFileCompleted();
+    download_manager_->RemoveFromActiveList(id());
+  }
 }
 
 void DownloadItem::Remove(bool delete_on_disk) {
@@ -395,8 +428,10 @@
   // finalized and the file data is downloaded. The ordering of these two
   // actions is indeterministic. Thus, if we are still in downloading the
   // file, delay the notification.
-  if (state() == DownloadItem::COMPLETE)
+  if (state() == DownloadItem::COMPLETE) {
     NotifyObserversDownloadFileCompleted();
+    download_manager_->RemoveFromActiveList(id());
+  }
 }
 
 void DownloadItem::OnSafeDownloadFinished(DownloadFileManager* file_manager) {
@@ -451,8 +486,12 @@
   if (url_formatted.find(query) != string16::npos)
     return true;
 
-  string16 path(l10n_util::ToLower(WideToUTF16(full_path().ToWStringHack())));
-  if (path.find(query) != std::wstring::npos)
+  string16 path(l10n_util::ToLower(full_path().LossyDisplayName()));
+  // This shouldn't just do a substring match; it is wrong for Unicode
+  // due to normalization and we have a fancier search-query system
+  // used elsewhere.
+  // http://code.google.com/p/chromium/issues/detail?id=71982
+  if (path.find(query) != string16::npos)
     return true;
 
   return false;
diff --git a/chrome/browser/download/download_item.h b/chrome/browser/download/download_item.h
index 788ea98..eaa9a55 100644
--- a/chrome/browser/download/download_item.h
+++ b/chrome/browser/download/download_item.h
@@ -34,12 +34,25 @@
 // One DownloadItem per download. This is the model class that stores all the
 // state for a download. Multiple views, such as a tab's download shelf and the
 // Destination tab's download view, may refer to a given DownloadItem.
+//
+// This is intended to be used only on the UI thread.
 class DownloadItem {
  public:
   enum DownloadState {
     IN_PROGRESS,
+
+    // Note that COMPLETE indicates that the download has gotten all of its
+    // data, has figured out its final destination file, has been entered
+    // into the history store, and has been shown in the UI.  The only
+    // operations remaining are acceptance by the user of
+    // a dangerous download (if dangerous), renaming the file
+    // to the final name, and auto-opening it (if it auto-opens).
     COMPLETE,
+
     CANCELLED,
+
+    // This state indicates that the download item is about to be destroyed,
+    // and observers seeing this state should release all references.
     REMOVING
   };
 
@@ -126,9 +139,13 @@
   // when resuming a download (assuming the server supports byte ranges).
   void Cancel(bool update_history);
 
-  // Called when all data has been saved.
+  // Called when all data has been saved.  Only has display effects.
   void OnAllDataSaved(int64 size);
 
+  // Called when ready to consider the data received and move on to the
+  // next stage.
+  void MarkAsComplete();
+
   // Called when the entire download operation (including renaming etc)
   // is finished.
   void Finished();
@@ -150,6 +167,9 @@
   // total size).
   int PercentComplete() const;
 
+  // Whether or not this download has saved all of its data.
+  bool all_data_saved() const { return all_data_saved_; }
+
   // Update the fields that may have changed in DownloadCreateInfo as a
   // result of analyzing the file and figuring out its type, location, etc.
   // May only be called once.
@@ -186,6 +206,7 @@
   FilePath full_path() const { return full_path_; }
   void set_path_uniquifier(int uniquifier) { path_uniquifier_ = uniquifier; }
   GURL url() const { return url_; }
+  GURL original_url() const { return original_url_; }
   GURL referrer_url() const { return referrer_url_; }
   std::string mime_type() const { return mime_type_; }
   std::string original_mime_type() const { return original_mime_type_; }
@@ -254,9 +275,13 @@
   // path should be used as is.
   int path_uniquifier_;
 
-  // The URL from whence we came.
+  // The URL from which we are downloading. This is the final URL after any
+  // redirection by the server for |original_url_|.
   GURL url_;
 
+  // The original URL before any redirection by the server for this URL.
+  GURL original_url_;
+
   // The URL of the page that initiated the download.
   GURL referrer_url_;
 
@@ -333,6 +358,9 @@
   // True if the item was downloaded temporarily.
   bool is_temporary_;
 
+  // True if we've saved all the data for the download.
+  bool all_data_saved_;
+
   // Did the user open the item either directly or indirectly (such as by
   // setting always open files of this type)? The shelf also sets this field
   // when the user closes the shelf before the item has been opened but should
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 68c1861..e7da0ec 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/download/download_item_model.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
 #include "base/string16.h"
@@ -13,6 +12,7 @@
 #include "chrome/browser/download/save_package.h"
 #include "chrome/common/time_format.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::TimeDelta;
 
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc
index 268c417..66afe04 100644
--- a/chrome/browser/download/download_manager.cc
+++ b/chrome/browser/download/download_manager.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/download/download_manager.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/file_util.h"
 #include "base/logging.h"
@@ -35,18 +33,18 @@
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/mime_util.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater)
     : shutdown_needed_(false),
@@ -116,6 +114,7 @@
 
   // And clear all non-owning containers.
   in_progress_.clear();
+  active_downloads_.clear();
 #if !defined(NDEBUG)
   save_page_as_downloads_.clear();
 #endif
@@ -128,6 +127,7 @@
     select_file_dialog_->ListenerDestroyed();
 
   download_history_.reset();
+  download_prefs_.reset();
 
   request_context_getter_ = NULL;
 
@@ -241,7 +241,7 @@
 // history system of a new download. Since this method can be called while the
 // history service thread is still reading the persistent state, we do not
 // insert the new DownloadItem into 'history_downloads_' or inform our
-// observers at this point. OnCreateDatabaseEntryComplete() handles that
+// observers at this point. OnCreateDownloadEntryComplete() handles that
 // finalization of the the download creation as a callback from the
 // history thread.
 void DownloadManager::StartDownload(DownloadCreateInfo* info) {
@@ -290,7 +290,8 @@
 
   if (!info->prompt_user_for_save_location &&
       info->save_info.file_path.empty()) {
-    info->is_dangerous = download_util::IsDangerous(info, profile());
+    info->is_dangerous = download_util::IsDangerous(
+        info, profile(), ShouldOpenFileBasedOnExtension(info->suggested_path));
   }
 
   // We need to move over to the download thread because we don't want to stat
@@ -334,10 +335,19 @@
     // download.
     FilePath::StringType file_name;
     FilePath path;
+#if defined(OS_WIN)
+    string16 unconfirmed_prefix =
+        l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
+#else
+    std::string unconfirmed_prefix =
+        l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
+#endif
+
     while (path.empty()) {
       base::SStringPrintf(
           &file_name,
-          FILE_PATH_LITERAL("unconfirmed %d.crdownload"),
+          unconfirmed_prefix.append(
+              FILE_PATH_LITERAL(" %d.crdownload")).c_str(),
           base::RandInt(0, 100000));
       path = dir.Append(file_name);
       if (file_util::PathExists(path))
@@ -423,32 +433,28 @@
   DownloadItem* download = new DownloadItem(this, *info,
                                             profile_->IsOffTheRecord());
   DCHECK(!ContainsKey(in_progress_, info->download_id));
+  DCHECK(!ContainsKey(active_downloads_, info->download_id));
   downloads_.insert(download);
+  active_downloads_[info->download_id] = download;
 }
 
 void DownloadManager::AttachDownloadItem(DownloadCreateInfo* info,
                                          const FilePath& target_path) {
+  VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
+
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   scoped_ptr<DownloadCreateInfo> infop(info);
   info->path = target_path;
 
-  // NOTE(ahendrickson) We will be adding a new map |active_downloads_|, into
-  // which we will be adding the download as soon as it's created.  This will
-  // make this loop unnecessary.
-  // Eventually |active_downloads_| will replace |in_progress_|, but we don't
-  // want to change the semantics yet.
+  // NOTE(ahendrickson) Eventually |active_downloads_| will replace
+  // |in_progress_|, but we don't want to change the semantics yet.
   DCHECK(!ContainsKey(in_progress_, info->download_id));
-  DownloadItem* download = NULL;
-  for (std::set<DownloadItem*>::iterator i = downloads_.begin();
-       i != downloads_.end(); ++i) {
-    DownloadItem* item = (*i);
-    if (item && (item->id() == info->download_id)) {
-      download = item;
-      break;
-    }
-  }
+  DCHECK(ContainsKey(active_downloads_, info->download_id));
+  DownloadItem* download = active_downloads_[info->download_id];
   DCHECK(download != NULL);
+  DCHECK(ContainsKey(downloads_, download));
+
   download->SetFileCheckResults(info->path,
                                 info->is_dangerous,
                                 info->path_uniquifier,
@@ -456,29 +462,25 @@
                                 info->is_extension_install,
                                 info->original_name);
   in_progress_[info->download_id] = download;
+  UpdateAppIcon();  // Reflect entry into in_progress_.
 
-  bool download_finished = ContainsKey(pending_finished_downloads_,
-                                       info->download_id);
-
-  VLOG(20) << __FUNCTION__ << "()"
-           << " target_path = \"" << target_path.value() << "\""
-           << " download_finished = " << download_finished
-           << " info = " << info->DebugString()
-           << " download = " << download->DebugString(true);
-
-  if (download_finished || info->is_dangerous) {
-    // The download has already finished or the download is not safe.
-    // We can now rename the file to its final name (or its tentative name
-    // in dangerous download cases).
+  // Rename to intermediate name.
+  if (info->is_dangerous) {
+    // The download is not safe.  We can now rename the file to its
+    // tentative name using OnFinalDownloadName (the actual final
+    // name after user confirmation will be set in
+    // ProceedWithFinishedDangerousDownload).
     BrowserThread::PostTask(
         BrowserThread::FILE, FROM_HERE,
         NewRunnableMethod(
             file_manager_, &DownloadFileManager::OnFinalDownloadName,
-            download->id(), target_path, !info->is_dangerous,
+            download->id(), target_path, false,
             make_scoped_refptr(this)));
   } else {
-    // The download hasn't finished and it is a safe download.  We need to
-    // rename it to its intermediate '.crdownload' path.
+    // The download is a safe download.  We need to
+    // rename it to its intermediate '.crdownload' path.  The final
+    // name after user confirmation will be set from
+    // DownloadItem::OnSafeDownloadFinished.
     FilePath download_path = download_util::GetCrDownloadPath(target_path);
     BrowserThread::PostTask(
         BrowserThread::FILE, FROM_HERE,
@@ -488,92 +490,113 @@
     download->Rename(download_path);
   }
 
-  if (download_finished) {
-    // If the download already completed by the time we reached this point, then
-    // notify observers that it did.
-    OnAllDataSaved(info->download_id,
-                   pending_finished_downloads_[info->download_id]);
-  }
-
   download_history_->AddEntry(*info, download,
       NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete));
-
-  UpdateAppIcon();
 }
 
 void DownloadManager::UpdateDownload(int32 download_id, int64 size) {
-  DownloadMap::iterator it = in_progress_.find(download_id);
-  if (it != in_progress_.end()) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DownloadMap::iterator it = active_downloads_.find(download_id);
+  if (it != active_downloads_.end()) {
     DownloadItem* download = it->second;
-    download->Update(size);
-    download_history_->UpdateEntry(download);
+    if (download->state() == DownloadItem::IN_PROGRESS) {
+      download->Update(size);
+      UpdateAppIcon();  // Reflect size updates.
+      download_history_->UpdateEntry(download);
+    }
   }
-  UpdateAppIcon();
 }
 
 void DownloadManager::OnAllDataSaved(int32 download_id, int64 size) {
   VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
            << " size = " << size;
-  DownloadMap::iterator it = in_progress_.find(download_id);
-  if (it == in_progress_.end()) {
-    // The download is done, but the user hasn't selected a final location for
-    // it yet (the Save As dialog box is probably still showing), so just keep
-    // track of the fact that this download id is complete, when the
-    // DownloadItem is constructed later we'll notify its completion then.
-    PendingFinishedMap::iterator erase_it =
-        pending_finished_downloads_.find(download_id);
-    DCHECK(erase_it == pending_finished_downloads_.end());
-    pending_finished_downloads_[download_id] = size;
-    VLOG(20) << __FUNCTION__ << "()" << " Added download_id = " << download_id
-             << " to pending_finished_downloads_";
+
+  // If it's not in active_downloads_, that means it was cancelled; just
+  // ignore the notification.
+  if (active_downloads_.count(download_id) == 0)
     return;
-  }
 
-  // Remove the id from the list of pending ids.
-  PendingFinishedMap::iterator erase_it =
-      pending_finished_downloads_.find(download_id);
-  if (erase_it != pending_finished_downloads_.end()) {
-    pending_finished_downloads_.erase(erase_it);
-    VLOG(20) << __FUNCTION__ << "()" << " Removed download_id = " << download_id
-             << " from pending_finished_downloads_";
-  }
-
-  DownloadItem* download = it->second;
-
-  VLOG(20) << __FUNCTION__ << "()"
-           << " download = " << download->DebugString(true);
-
+  DownloadItem* download = active_downloads_[download_id];
   download->OnAllDataSaved(size);
 
-  // Clean up will happen when the history system create callback runs if we
-  // don't have a valid db_handle yet.
-  if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
-    in_progress_.erase(it);
-    download_history_->UpdateEntry(download);
-  }
+  MaybeCompleteDownload(download);
+}
 
-  UpdateAppIcon();
+bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
+  // If we don't have all the data, the download is not ready for
+  // completion.
+  if (!download->all_data_saved())
+    return false;
 
-  // If this a dangerous download not yet validated by the user, don't do
-  // anything. When the user notifies us, it will trigger a call to
-  // ProceedWithFinishedDangerousDownload.
-  if (download->safety_state() == DownloadItem::DANGEROUS) {
+  // If the download isn't active (e.g. has been cancelled) it's not
+  // ready for completion.
+  if (active_downloads_.count(download->id()) == 0)
+    return false;
+
+  // If the download hasn't been inserted into the history system
+  // (which occurs strictly after file name determination, intermediate
+  // file rename, and UI display) then it's not ready for completion.
+  return (download->db_handle() != DownloadHistory::kUninitializedHandle);
+}
+
+void DownloadManager::MaybeCompleteDownload(DownloadItem* download) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  VLOG(20) << __FUNCTION__ << "()" << " download = "
+           << download->DebugString(false);
+
+  if (!IsDownloadReadyForCompletion(download))
     return;
-  }
 
-  if (download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) {
-    // We first need to rename the downloaded file from its temporary name to
-    // its final name before we can continue.
-    BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-        NewRunnableMethod(
-            this, &DownloadManager::ProceedWithFinishedDangerousDownload,
-            download->db_handle(),
-            download->full_path(), download->target_name()));
-    return;
-  }
+  // TODO(rdsmith): DCHECK that we only pass through this point
+  // once per download.  The natural way to do this is by a state
+  // transition on the DownloadItem.
 
-  download->OnSafeDownloadFinished(file_manager_);
+  // Confirm we're in the proper set of states to be here;
+  // in in_progress_, have all data, have a history handle.
+  DCHECK_EQ(1u, in_progress_.count(download->id()));
+  DCHECK(download->all_data_saved());
+  DCHECK(download->db_handle() != DownloadHistory::kUninitializedHandle);
+  DCHECK_EQ(1u, history_downloads_.count(download->db_handle()));
+
+  VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
+           << download->DebugString(false);
+
+  // Remove the id from in_progress
+  in_progress_.erase(download->id());
+  UpdateAppIcon();  // Reflect removal from in_progress_.
+
+  // Final update of download item and history.
+  download->MarkAsComplete();
+  download_history_->UpdateEntry(download);
+
+  switch (download->safety_state()) {
+    case DownloadItem::DANGEROUS:
+      // If this a dangerous download not yet validated by the user, don't do
+      // anything. When the user notifies us, it will trigger a call to
+      // ProceedWithFinishedDangerousDownload.
+      return;
+    case DownloadItem::DANGEROUS_BUT_VALIDATED:
+      // The dangerous download has been validated by the user.  We first
+      // need to rename the downloaded file from its temporary name to
+      // its final name.  We will continue the download processing in the
+      // callback.
+      BrowserThread::PostTask(
+          BrowserThread::FILE, FROM_HERE,
+          NewRunnableMethod(
+              this, &DownloadManager::ProceedWithFinishedDangerousDownload,
+              download->db_handle(),
+              download->full_path(), download->target_name()));
+      return;
+    case DownloadItem::SAFE:
+      // The download is safe; just finish it.
+      download->OnSafeDownloadFinished(file_manager_);
+      return;
+  }
+}
+
+void DownloadManager::RemoveFromActiveList(int32 download_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  active_downloads_.erase(download_id);
 }
 
 void DownloadManager::DownloadRenamedToFinalName(int download_id,
@@ -645,6 +668,7 @@
 }
 
 void DownloadManager::DownloadCancelled(int32 download_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DownloadMap::iterator it = in_progress_.find(download_id);
   if (it == in_progress_.end())
     return;
@@ -657,13 +681,14 @@
   // don't have a valid db_handle yet.
   if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
     in_progress_.erase(it);
+    active_downloads_.erase(download_id);
+    UpdateAppIcon();  // Reflect removal from in_progress_.
     download_history_->UpdateEntry(download);
   }
 
   DownloadCancelledInternal(download_id,
                             download->render_process_id(),
                             download->request_id());
-  UpdateAppIcon();
 }
 
 void DownloadManager::DownloadCancelledInternal(int download_id,
@@ -953,6 +978,7 @@
 void DownloadManager::OnCreateDownloadEntryComplete(
     DownloadCreateInfo info,
     int64 db_handle) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DownloadMap::iterator it = in_progress_.find(info.download_id);
   DCHECK(it != in_progress_.end());
 
@@ -973,27 +999,30 @@
   download->set_db_handle(db_handle);
 
   // Insert into our full map.
-  DCHECK(history_downloads_.find(download->db_handle()) ==
-         history_downloads_.end());
+  DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
   history_downloads_[download->db_handle()] = download;
 
-  // Show in the appropropriate browser UI.
+  // Show in the appropriate browser UI.
   ShowDownloadInBrowser(info, download);
 
   // Inform interested objects about the new download.
   NotifyModelChanged();
 
-  // If this download has been completed before we've received the db handle,
+  // If this download has been cancelled before we've received the DB handle,
   // post one final message to the history service so that it can be properly
   // in sync with the DownloadItem's completion status, and also inform any
   // observers so that they get more than just the start notification.
+  //
+  // Otherwise, try to complete the download
   if (download->state() != DownloadItem::IN_PROGRESS) {
+    DCHECK_EQ(DownloadItem::CANCELLED, download->state());
     in_progress_.erase(it);
+    active_downloads_.erase(info.download_id);
     download_history_->UpdateEntry(download);
     download->UpdateObservers();
+  } else {
+    MaybeCompleteDownload(download);
   }
-
-  UpdateAppIcon();
 }
 
 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info,
@@ -1041,9 +1070,9 @@
 void DownloadManager::AssertContainersConsistent() const {
 #if !defined(NDEBUG)
   // Turn everything into sets.
-  DownloadSet in_progress_set, history_set;
-  const DownloadMap* input_maps[] = {&in_progress_, &history_downloads_};
-  DownloadSet* local_sets[] = {&in_progress_set, &history_set};
+  DownloadSet active_set, history_set;
+  const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_};
+  DownloadSet* local_sets[] = {&active_set, &history_set};
   DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets));
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
     for (DownloadMap::const_iterator it = input_maps[i]->begin();
@@ -1053,7 +1082,7 @@
   }
 
   // Check if each set is fully present in downloads, and create a union.
-  const DownloadSet* all_sets[] = {&in_progress_set, &history_set,
+  const DownloadSet* all_sets[] = {&active_set, &history_set,
                                    &save_page_as_downloads_};
   DownloadSet downloads_union;
   for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h
index 4f5ebcf..e103a79 100644
--- a/chrome/browser/download/download_manager.h
+++ b/chrome/browser/download/download_manager.h
@@ -42,7 +42,7 @@
 #include "base/weak_ptr.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/download/download_status_updater_delegate.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 
 class DownloadFileManager;
 class DownloadHistory;
@@ -63,10 +63,6 @@
                                         BrowserThread::DeleteOnUIThread>,
       public DownloadStatusUpdaterDelegate,
       public SelectFileDialog::Listener {
-  // For testing.
-  friend class DownloadManagerTest;
-  friend class MockDownloadManager;
-
  public:
   explicit DownloadManager(DownloadStatusUpdater* status_updater);
 
@@ -125,6 +121,17 @@
   void PauseDownload(int32 download_id, bool pause);
   void RemoveDownload(int64 download_handle);
 
+  // Determine if the download is ready for completion, i.e. has had
+  // all data received, and completed the filename determination and
+  // history insertion.
+  bool IsDownloadReadyForCompletion(DownloadItem* download);
+
+  // If all pre-requisites have been met, complete download processing, i.e.
+  // do internal cleanup, file rename, and potentially auto-open.
+  // (Dangerous downloads still may block on user acceptance after this
+  // point.)
+  void MaybeCompleteDownload(DownloadItem* download);
+
   // Called when the download is renamed to its final name.
   void DownloadRenamedToFinalName(int download_id, const FilePath& full_path);
 
@@ -143,6 +150,9 @@
   // deleted is returned back to the caller.
   int RemoveAllDownloads();
 
+  // Remove the download with id |download_id| from |active_downloads_|.
+  void RemoveFromActiveList(int32 download_id);
+
   // Called when a Save Page As download is started. Transfers ownership
   // of |download_item| to the DownloadManager.
   void SavePageAsDownloadStarted(DownloadItem* download_item);
@@ -212,6 +222,10 @@
   void DangerousDownloadValidated(DownloadItem* download);
 
  private:
+  // For testing.
+  friend class DownloadManagerTest;
+  friend class MockDownloadManager;
+
   // This class is used to let an incognito DownloadManager observe changes to
   // a normal DownloadManager, to propagate ModelChanged() calls from the parent
   // DownloadManager to the observers of the incognito DownloadManager.
@@ -310,6 +324,10 @@
   // is the handle returned by the history system, which is unique
   // across sessions.
   //
+  // |active_downloads_| is a map of all downloads that are currently being
+  // processed. The key is the ID assigned by the ResourceDispatcherHost,
+  // which is unique for the current session.
+  //
   // |in_progress_| is a map of all downloads that are in progress and that have
   // not yet received a valid history handle. The key is the ID assigned by the
   // ResourceDispatcherHost, which is unique for the current session.
@@ -319,11 +337,12 @@
   // until we are destroyed.  It is only used for debugging.
   //
   // When a download is created through a user action, the corresponding
-  // DownloadItem* is placed in |in_progress_| and remains there until it has
-  // received a valid handle from the history system. Once it has a valid
-  // handle, the DownloadItem* is placed in the |history_downloads_|
-  // map.  When the download is complete, it is removed from
-  // |in_progress_|.  Downloads from past sessions read from a
+  // DownloadItem* is placed in |active_downloads_| and remains there until the
+  // download has finished.  It is also placed in |in_progress_| and remains
+  // there until it has received a valid handle from the history system. Once
+  // it has a valid handle, the DownloadItem* is placed in the
+  // |history_downloads_| map.  When the download is complete, it is removed
+  // from |in_progress_|.  Downloads from past sessions read from a
   // persisted state from the history system are placed directly into
   // |history_downloads_| since they have valid handles in the history system.
   typedef std::set<DownloadItem*> DownloadSet;
@@ -332,6 +351,7 @@
   DownloadSet downloads_;
   DownloadMap history_downloads_;
   DownloadMap in_progress_;
+  DownloadMap active_downloads_;
 #if !defined(NDEBUG)
   DownloadSet save_page_as_downloads_;
 #endif
@@ -360,14 +380,6 @@
   // user wants us to prompt for a save location for each download.
   FilePath last_download_path_;
 
-  // Keep track of downloads that are completed before the user selects the
-  // destination, so that observers are appropriately notified of completion
-  // after this determination is made.
-  // The map is of download_id->remaining size (bytes), both of which are
-  // required when calling OnAllDataSaved.
-  typedef std::map<int32, int64> PendingFinishedMap;
-  PendingFinishedMap pending_finished_downloads_;
-
   // The "Save As" dialog box used to ask the user where a file should be
   // saved.
   scoped_refptr<SelectFileDialog> select_file_dialog_;
diff --git a/chrome/browser/download/download_manager_unittest.cc b/chrome/browser/download/download_manager_unittest.cc
index 2db13be..74a21ac 100644
--- a/chrome/browser/download/download_manager_unittest.cc
+++ b/chrome/browser/download/download_manager_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/download/download_status_updater.h"
 #include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/mock_download_manager.h"
 #include "chrome/browser/history/download_create_info.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/pref_names.h"
@@ -21,17 +22,6 @@
 #include "testing/gmock_mutant.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-class MockDownloadManager : public DownloadManager {
- public:
-  explicit MockDownloadManager(DownloadStatusUpdater* updater)
-      : DownloadManager(updater) {
-  }
-
-  // Override some functions.
-  virtual void UpdateHistoryForDownload(DownloadItem*) { }
-  virtual void ContinueDownloadFinished(DownloadItem*) { }
-};
-
 class DownloadManagerTest : public testing::Test {
  public:
   DownloadManagerTest()
@@ -157,30 +147,31 @@
   bool will_delete_crdownload;
   int expected_rename_count;
 } kDownloadRenameCases[] = {
-  // Safe download, download finishes BEFORE rename.
-  // Needs to be renamed only once.  Crdownload file needs to be deleted.
+  // Safe download, download finishes BEFORE file name determined.
+  // Renamed twice (linear path through UI).  Crdownload file does not need
+  // to be deleted.
   { FILE_PATH_LITERAL("foo.zip"),
     false,
     true,
-    true,
-    1, },
-  // Dangerous download, download finishes BEFORE rename.
+    false,
+    2, },
+  // Dangerous download, download finishes BEFORE file name determined.
   // Needs to be renamed only once.
-  { FILE_PATH_LITERAL("unconfirmed xxx.crdownload"),
+  { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
     true,
     true,
     false,
     1, },
-  // Safe download, download finishes AFTER rename.
+  // Safe download, download finishes AFTER file name determined.
   // Needs to be renamed twice.
   { FILE_PATH_LITERAL("foo.zip"),
     false,
     false,
     false,
     2, },
-  // Dangerous download, download finishes AFTER rename.
+  // Dangerous download, download finishes AFTER file name determined.
   // Needs to be renamed only once.
-  { FILE_PATH_LITERAL("unconfirmed xxx.crdownload"),
+  { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
     true,
     false,
     false,
@@ -193,7 +184,7 @@
       : DownloadFile(info, NULL), renamed_count_(0) { }
   virtual ~MockDownloadFile() { Destructed(); }
   MOCK_METHOD2(Rename, bool(const FilePath&, bool));
-  MOCK_METHOD0(DeleteCrDownload, void());
+  MOCK_METHOD0(DeleteCrDownload, bool());
   MOCK_METHOD0(Destructed, void());
 
   bool TestMultipleRename(
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index 40be829..ec36422 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,12 +12,14 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/download/download_extensions.h"
 #include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/save_package.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/pref_names.h"
 
 DownloadPrefs::DownloadPrefs(PrefService* prefs) : prefs_(prefs) {
   prompt_for_download_.Init(prefs::kPromptForDownload, prefs, NULL);
   download_path_.Init(prefs::kDownloadDefaultDirectory, prefs, NULL);
+  save_file_type_.Init(prefs::kSaveFileType, prefs, NULL);
 
   // We store any file extension that should be opened automatically at
   // download completion in this pref.
@@ -46,6 +48,8 @@
   prefs->RegisterBooleanPref(prefs::kPromptForDownload, false);
   prefs->RegisterStringPref(prefs::kDownloadExtensionsToOpen, "");
   prefs->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false);
+  prefs->RegisterIntegerPref(prefs::kSaveFileType,
+                             SavePackage::SAVE_AS_COMPLETE_HTML);
 
   // The default download path is userprofile\download.
   const FilePath& default_download_path =
diff --git a/chrome/browser/download/download_prefs.h b/chrome/browser/download/download_prefs.h
index 1345a44..b65bb29 100644
--- a/chrome/browser/download/download_prefs.h
+++ b/chrome/browser/download/download_prefs.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,6 +23,7 @@
 
   bool prompt_for_download() const { return *prompt_for_download_; }
   FilePath download_path() const { return *download_path_; }
+  int save_file_type() const { return *save_file_type_; }
 
   // Returns true if there is at least one file extension registered
   // for auto-open.
@@ -48,6 +49,7 @@
 
   BooleanPrefMember prompt_for_download_;
   FilePathPrefMember download_path_;
+  IntegerPrefMember save_file_type_;
 
   // Set of file extensions to open at download completion.
   struct AutoOpenCompareFunctor {
diff --git a/chrome/browser/download/download_request_infobar_delegate.cc b/chrome/browser/download/download_request_infobar_delegate.cc
index ecbc108..34f0f02 100644
--- a/chrome/browser/download/download_request_infobar_delegate.cc
+++ b/chrome/browser/download/download_request_infobar_delegate.cc
@@ -1,34 +1,29 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/download/download_request_infobar_delegate.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
-DownloadRequestInfoBarDelegate::DownloadRequestInfoBarDelegate(TabContents* tab,
+DownloadRequestInfoBarDelegate::DownloadRequestInfoBarDelegate(
+    TabContents* tab,
     DownloadRequestLimiter::TabDownloadState* host)
     : ConfirmInfoBarDelegate(tab),
       host_(host) {
-  if (tab)
-    tab->AddInfoBar(this);
 }
 
 DownloadRequestInfoBarDelegate::~DownloadRequestInfoBarDelegate() {
 }
 
 void DownloadRequestInfoBarDelegate::InfoBarClosed() {
-  Cancel();
-  // This will delete us.
-  ConfirmInfoBarDelegate::InfoBarClosed();
-}
-
-string16 DownloadRequestInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringUTF16(IDS_MULTI_DOWNLOAD_WARNING);
+  if (host_)
+    host_->Cancel();
+  delete this;
 }
 
 SkBitmap* DownloadRequestInfoBarDelegate::GetIcon() const {
@@ -36,16 +31,14 @@
       IDR_INFOBAR_MULTIPLE_DOWNLOADS);
 }
 
-int DownloadRequestInfoBarDelegate::GetButtons() const {
-  return BUTTON_OK | BUTTON_CANCEL;
+string16 DownloadRequestInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_MULTI_DOWNLOAD_WARNING);
 }
 
 string16 DownloadRequestInfoBarDelegate::GetButtonLabel(
-    ConfirmInfoBarDelegate::InfoBarButton button) const {
-  if (button == BUTTON_OK)
-    return l10n_util::GetStringUTF16(IDS_MULTI_DOWNLOAD_WARNING_ALLOW);
-  else
-    return l10n_util::GetStringUTF16(IDS_MULTI_DOWNLOAD_WARNING_DENY);
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_MULTI_DOWNLOAD_WARNING_ALLOW : IDS_MULTI_DOWNLOAD_WARNING_DENY);
 }
 
 bool DownloadRequestInfoBarDelegate::Accept() {
@@ -56,11 +49,3 @@
 
   return !host_;
 }
-
-bool DownloadRequestInfoBarDelegate::Cancel() {
-  if (host_) {
-    host_->Cancel();
-    host_ = NULL;
-  }
-  return true;
-}
diff --git a/chrome/browser/download/download_request_infobar_delegate.h b/chrome/browser/download/download_request_infobar_delegate.h
index c1280cf..16d3f4b 100644
--- a/chrome/browser/download/download_request_infobar_delegate.h
+++ b/chrome/browser/download/download_request_infobar_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,30 +19,23 @@
 class DownloadRequestInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   DownloadRequestInfoBarDelegate(
-      TabContents* tab, DownloadRequestLimiter::TabDownloadState* host);
-
-  virtual ~DownloadRequestInfoBarDelegate();
+      TabContents* tab,
+      DownloadRequestLimiter::TabDownloadState* host);
 
   void set_host(DownloadRequestLimiter::TabDownloadState* host) {
     host_ = host;
   }
 
+ private:
+  virtual ~DownloadRequestInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
   virtual void InfoBarClosed();
-
-  virtual string16 GetMessageText() const;
-
   virtual SkBitmap* GetIcon() const;
-
-  virtual int GetButtons() const;
-
-  virtual string16 GetButtonLabel(
-      ConfirmInfoBarDelegate::InfoBarButton button) const;
-
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
   virtual bool Accept();
 
-  virtual bool Cancel();
-
- private:
   DownloadRequestLimiter::TabDownloadState* host_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadRequestInfoBarDelegate);
diff --git a/chrome/browser/download/download_request_infobar_delegate_unittest.cc b/chrome/browser/download/download_request_infobar_delegate_unittest.cc
index 1ceb247..5a8b251 100644
--- a/chrome/browser/download/download_request_infobar_delegate_unittest.cc
+++ b/chrome/browser/download/download_request_infobar_delegate_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,36 +6,35 @@
 #include "chrome/browser/download/download_request_limiter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// MockTabDownloadState -------------------------------------------------------
+
 class MockTabDownloadState : public DownloadRequestLimiter::TabDownloadState {
  public:
-  MockTabDownloadState() : responded_(false), accepted_(false) {
-  }
+  MockTabDownloadState();
+  virtual ~MockTabDownloadState();
 
-  virtual ~MockTabDownloadState() {
-    EXPECT_TRUE(responded_);
-  }
+  // DownloadRequestLimiter::TabDownloadState
+  virtual void Cancel();
+  virtual void Accept();
 
-  virtual void Accept() {
-    EXPECT_FALSE(responded_);
-    responded_ = true;
-    accepted_ = true;
+  ConfirmInfoBarDelegate* infobar() {
+    return infobar_->AsConfirmInfoBarDelegate();
   }
-
-  virtual void Cancel() {
-    EXPECT_FALSE(responded_);
-    responded_ = true;
-    accepted_ = false;
+  void close_infobar() {
+    // TODO(pkasting): Right now InfoBarDelegates delete themselves via
+    // InfoBarClosed(); once InfoBars own their delegates, this can become a
+    // simple reset() call and ~MockTabDownloadState() will no longer need to
+    // call it.
+    if (infobar_ != NULL)
+      infobar_.release()->InfoBarClosed();
   }
-
-  bool responded() {
-    return responded_;
-  }
-
-  bool accepted() {
-    return responded_ && accepted_;
-  }
+  bool responded() const { return responded_; }
+  bool accepted() const { return accepted_; }
 
  private:
+  // The actual infobar delegate we're listening to.
+  scoped_ptr<InfoBarDelegate> infobar_;
+
   // True if we have gotten some sort of response.
   bool responded_;
 
@@ -44,23 +43,46 @@
   bool accepted_;
 };
 
-TEST(DownloadRequestInfobar, AcceptTest) {
+MockTabDownloadState::MockTabDownloadState()
+    : responded_(false), accepted_(false) {
+  infobar_.reset(new DownloadRequestInfoBarDelegate(NULL, this));
+}
+
+MockTabDownloadState::~MockTabDownloadState() {
+  close_infobar();
+  EXPECT_TRUE(responded_);
+}
+
+void MockTabDownloadState::Cancel() {
+  EXPECT_FALSE(responded_);
+  responded_ = true;
+  accepted_ = false;
+}
+
+void MockTabDownloadState::Accept() {
+  EXPECT_FALSE(responded_);
+  responded_ = true;
+  accepted_ = true;
+  static_cast<DownloadRequestInfoBarDelegate*>(infobar_.get())->set_host(NULL);
+}
+
+
+// Tests ----------------------------------------------------------------------
+
+TEST(DownloadRequestInfobarDelegate, AcceptTest) {
   MockTabDownloadState state;
-  DownloadRequestInfoBarDelegate infobar(NULL, &state);
-  infobar.Accept();
+  state.infobar()->Accept();
   EXPECT_TRUE(state.accepted());
 }
 
-TEST(DownloadRequestInfobar, CancelTest) {
+TEST(DownloadRequestInfobarDelegate, CancelTest) {
   MockTabDownloadState state;
-  DownloadRequestInfoBarDelegate infobar(NULL, &state);
-  infobar.Cancel();
+  state.infobar()->Cancel();
   EXPECT_FALSE(state.accepted());
 }
 
-TEST(DownloadRequestInfobar, CloseTest) {
+TEST(DownloadRequestInfobarDelegate, CloseTest) {
   MockTabDownloadState state;
-  DownloadRequestInfoBarDelegate infobar(NULL, &state);
-  infobar.InfoBarClosed();
+  state.close_infobar();
   EXPECT_FALSE(state.accepted());
 }
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc
index fae07c9..075d103 100644
--- a/chrome/browser/download/download_request_limiter.cc
+++ b/chrome/browser/download/download_request_limiter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -71,6 +71,7 @@
     NotifyCallbacks(DownloadRequestLimiter::delegate_->ShouldAllowDownload());
   } else {
     infobar_ = new DownloadRequestInfoBarDelegate(tab, this);
+    tab->AddInfoBar(infobar_);
   }
 }
 
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc
index 3380789..ce000f4 100644
--- a/chrome/browser/download/download_shelf.cc
+++ b/chrome/browser/download/download_shelf.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/download/download_shelf.h"
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "chrome/browser/dom_ui/downloads_ui.h"
 #include "chrome/browser/download/download_item.h"
@@ -12,9 +11,9 @@
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // DownloadShelfContextMenu ----------------------------------------------------
 
@@ -110,7 +109,7 @@
 }
 
 bool DownloadShelfContextMenu::GetAcceleratorForCommandId(
-    int command_id, menus::Accelerator* accelerator) {
+    int command_id, ui::Accelerator* accelerator) {
   return false;
 }
 
@@ -119,11 +118,11 @@
   return command_id == TOGGLE_PAUSE;
 }
 
-menus::SimpleMenuModel* DownloadShelfContextMenu::GetInProgressMenuModel() {
+ui::SimpleMenuModel* DownloadShelfContextMenu::GetInProgressMenuModel() {
   if (in_progress_download_menu_model_.get())
     return in_progress_download_menu_model_.get();
 
-  in_progress_download_menu_model_.reset(new menus::SimpleMenuModel(this));
+  in_progress_download_menu_model_.reset(new ui::SimpleMenuModel(this));
 
   in_progress_download_menu_model_->AddCheckItemWithStringId(
       OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE);
@@ -141,11 +140,11 @@
   return in_progress_download_menu_model_.get();
 }
 
-menus::SimpleMenuModel* DownloadShelfContextMenu::GetFinishedMenuModel() {
+ui::SimpleMenuModel* DownloadShelfContextMenu::GetFinishedMenuModel() {
   if (finished_download_menu_model_.get())
     return finished_download_menu_model_.get();
 
-  finished_download_menu_model_.reset(new menus::SimpleMenuModel(this));
+  finished_download_menu_model_.reset(new ui::SimpleMenuModel(this));
 
   finished_download_menu_model_->AddItemWithStringId(
       OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN);
diff --git a/chrome/browser/download/download_shelf.h b/chrome/browser/download/download_shelf.h
index ab565fa..56700d2 100644
--- a/chrome/browser/download/download_shelf.h
+++ b/chrome/browser/download/download_shelf.h
@@ -6,10 +6,10 @@
 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SHELF_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class BaseDownloadItemModel;
 class Browser;
@@ -44,7 +44,7 @@
 
 // Logic for the download shelf context menu. Platform specific subclasses are
 // responsible for creating and running the menu.
-class DownloadShelfContextMenu : public menus::SimpleMenuModel::Delegate {
+class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate {
  public:
   virtual ~DownloadShelfContextMenu();
 
@@ -62,17 +62,17 @@
  protected:
   explicit DownloadShelfContextMenu(BaseDownloadItemModel* download_model);
 
-  menus::SimpleMenuModel* GetInProgressMenuModel();
-  menus::SimpleMenuModel* GetFinishedMenuModel();
+  ui::SimpleMenuModel* GetInProgressMenuModel();
+  ui::SimpleMenuModel* GetFinishedMenuModel();
   // Information source.
   DownloadItem* download_;
 
-  // menus::SimpleMenuModel::Delegate implementation:
+  // ui::SimpleMenuModel::Delegate implementation:
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual void ExecuteCommand(int command_id);
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual bool IsItemForCommandIdDynamic(int command_id) const;
   virtual string16 GetLabelForCommandId(int command_id) const;
 
@@ -82,8 +82,8 @@
  private:
   // We show slightly different menus if the download is in progress vs. if the
   // download has finished.
-  scoped_ptr<menus::SimpleMenuModel> in_progress_download_menu_model_;
-  scoped_ptr<menus::SimpleMenuModel> finished_download_menu_model_;
+  scoped_ptr<ui::SimpleMenuModel> in_progress_download_menu_model_;
+  scoped_ptr<ui::SimpleMenuModel> finished_download_menu_model_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadShelfContextMenu);
 };
diff --git a/chrome/browser/download/download_types.h b/chrome/browser/download/download_types.h
index bf3a9c7..56d07af 100644
--- a/chrome/browser/download/download_types.h
+++ b/chrome/browser/download/download_types.h
@@ -10,7 +10,7 @@
 
 #include "base/file_path.h"
 #include "base/linked_ptr.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "net/base/file_stream.h"
 
 namespace net {
@@ -27,7 +27,7 @@
   DownloadBuffer();
   ~DownloadBuffer();
 
-  Lock lock;
+  base::Lock lock;
   typedef std::pair<net::IOBuffer*, int> Contents;
   std::vector<Contents> contents;
 };
diff --git a/chrome/browser/download/download_uitest.cc b/chrome/browser/download/download_uitest.cc
index b347a77..0f6971a 100644
--- a/chrome/browser/download/download_uitest.cc
+++ b/chrome/browser/download/download_uitest.cc
@@ -1,33 +1,33 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <sstream>
 #include <string>
 
-#include "build/build_config.h"
-#if defined(OS_WIN)
-#include <shlwapi.h>
-#endif
-
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
 #include "base/test/test_file_util.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
+#include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/net/url_request_mock_http_job.h"
 #include "chrome/browser/net/url_request_slow_download_job.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/ui/ui_test.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/browser_proxy.h"
 #include "net/base/net_util.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
+
+#if defined(OS_WIN)
+#include <shlwapi.h>
+#endif
 
 namespace {
 
@@ -79,8 +79,8 @@
 
  protected:
   void RunSizeTest(const GURL& url,
-                   const std::wstring& expected_title_in_progress,
-                   const std::wstring& expected_title_finished) {
+                   const string16& expected_title_in_progress,
+                   const string16& expected_title_finished) {
     FilePath filename;
     net::FileURLToFilePath(url, &filename);
     filename = filename.BaseName();
@@ -154,7 +154,7 @@
   WaitUntilTabCount(1);
 
   // Wait to see if the file will be downloaded.
-  base::PlatformThread::Sleep(sleep_timeout_ms());
+  base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
 
   EXPECT_FALSE(file_util::PathExists(file_path));
   if (file_util::PathExists(file_path))
@@ -242,8 +242,9 @@
   FilePath filename;
   net::FileURLToFilePath(url, &filename);
   filename = filename.BaseName();
-  RunSizeTest(url, L"32.0 KB - " + filename.ToWStringHack(),
-              L"100% - " + filename.ToWStringHack());
+  RunSizeTest(url,
+              ASCIIToUTF16("32.0 KB - ") + filename.LossyDisplayName(),
+              ASCIIToUTF16("100% - ") + filename.LossyDisplayName());
 }
 
 // All download tests are flaky on all platforms, http://crbug.com/35275,
@@ -254,8 +255,9 @@
   FilePath filename;
   net::FileURLToFilePath(url, &filename);
   filename = filename.BaseName();
-  RunSizeTest(url, L"71% - " + filename.ToWStringHack(),
-              L"100% - " + filename.ToWStringHack());
+  RunSizeTest(url,
+              ASCIIToUTF16("71% - ") + filename.LossyDisplayName(),
+              ASCIIToUTF16("100% - ") + filename.LossyDisplayName());
 }
 
 // Test that when downloading an item in Incognito mode, we don't crash when
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index f00db36..9fdc560 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -11,8 +11,6 @@
 #endif
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/file_util.h"
 #include "base/i18n/rtl.h"
 #include "base/i18n/time_formatting.h"
@@ -38,14 +36,11 @@
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/time_format.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/rect.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
@@ -54,28 +49,31 @@
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/rect.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "app/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
 #include "views/drag_utils.h"
 #endif
 
 #if defined(TOOLKIT_USES_GTK)
 #if defined(TOOLKIT_VIEWS)
-#include "app/drag_drop_types.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
 #include "views/widget/widget_gtk.h"
 #elif defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/custom_drag.h"
+#include "chrome/browser/ui/gtk/custom_drag.h"
 #endif  // defined(TOOLKIT_GTK)
 #endif  // defined(TOOLKIT_USES_GTK)
 
 #if defined(OS_WIN)
-#include "app/os_exchange_data_provider_win.h"
-#include "app/win/drag_source.h"
-#include "app/win/win_util.h"
 #include "base/win/scoped_comptr.h"
 #include "chrome/browser/browser_list.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "ui/base/dragdrop/drag_source.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
 #endif
 
 namespace download_util {
@@ -120,6 +118,44 @@
 
   return false;
 }
+
+// Returns whether the specified file name is a reserved name on windows.
+// This includes names like "com2.zip" (which correspond to devices) and
+// desktop.ini and thumbs.db which have special meaning to the windows shell.
+bool IsReservedName(const string16& filename) {
+  // This list is taken from the MSDN article "Naming a file"
+  // http://msdn2.microsoft.com/en-us/library/aa365247(VS.85).aspx
+  // I also added clock$ because GetSaveFileName seems to consider it as a
+  // reserved name too.
+  static const wchar_t* const known_devices[] = {
+    L"con", L"prn", L"aux", L"nul", L"com1", L"com2", L"com3", L"com4", L"com5",
+    L"com6", L"com7", L"com8", L"com9", L"lpt1", L"lpt2", L"lpt3", L"lpt4",
+    L"lpt5", L"lpt6", L"lpt7", L"lpt8", L"lpt9", L"clock$"
+  };
+  string16 filename_lower = StringToLowerASCII(filename);
+
+  for (int i = 0; i < arraysize(known_devices); ++i) {
+    // Exact match.
+    if (filename_lower == known_devices[i])
+      return true;
+    // Starts with "DEVICE.".
+    if (filename_lower.find(string16(known_devices[i]) + L".") == 0)
+      return true;
+  }
+
+  static const wchar_t* const magic_names[] = {
+    // These file names are used by the "Customize folder" feature of the shell.
+    L"desktop.ini",
+    L"thumbs.db",
+  };
+
+  for (int i = 0; i < arraysize(magic_names); ++i) {
+    if (filename_lower == magic_names[i])
+      return true;
+  }
+
+  return false;
+}
 #endif  // OS_WIN
 
 }  // namespace
@@ -218,20 +254,24 @@
                       const std::string& referrer_charset,
                       const std::string& mime_type,
                       FilePath* generated_name) {
-#if defined(OS_WIN)
-  FilePath default_file_path(
+  string16 default_file_name(
       l10n_util::GetStringUTF16(IDS_DEFAULT_DOWNLOAD_FILENAME));
-#elif defined(OS_POSIX)
-  std::string default_file =
-      l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME);
-  FilePath default_file_path(
-      base::SysWideToNativeMB(base::SysUTF8ToWide(default_file)));
-#endif
 
-  *generated_name = net::GetSuggestedFilename(GURL(url),
-                                              content_disposition,
-                                              referrer_charset,
-                                              default_file_path);
+  string16 new_name = net::GetSuggestedFilename(GURL(url),
+                                                content_disposition,
+                                                referrer_charset,
+                                                default_file_name);
+
+  // TODO(evan): this code is totally wrong -- we should just generate
+  // Unicode filenames and do all this encoding switching at the end.
+  // However, I'm just shuffling wrong code around, at least not adding
+  // to it.
+#if defined(OS_WIN)
+  *generated_name = FilePath(new_name);
+#else
+  *generated_name = FilePath(
+      base::SysWideToNativeMB(UTF16ToWide(new_name)));
+#endif
 
   DCHECK(!generated_name->empty());
 
@@ -248,7 +288,7 @@
   // Prepend "_" to the file name if it's a reserved name
   FilePath::StringType leaf_name = file_name->BaseName().value();
   DCHECK(!leaf_name.empty());
-  if (app::win::IsReservedName(leaf_name)) {
+  if (IsReservedName(leaf_name)) {
     leaf_name = FilePath::StringType(FILE_PATH_LITERAL("_")) + leaf_name;
     *file_name = file_name->DirName();
     if (file_name->value() == FilePath::kCurrentDirectory) {
@@ -337,9 +377,9 @@
 
 #if defined(TOOLKIT_VIEWS)
   // Mirror the positions if necessary.
-  int mirrored_x = containing_view->MirroredLeftPointForRect(background_bounds);
+  int mirrored_x = containing_view->GetMirroredXForRect(background_bounds);
   background_bounds.set_x(mirrored_x);
-  mirrored_x = containing_view->MirroredLeftPointForRect(foreground_bounds);
+  mirrored_x = containing_view->GetMirroredXForRect(foreground_bounds);
   foreground_bounds.set_x(mirrored_x);
 #endif
 
@@ -424,8 +464,7 @@
                             complete->width(), complete->height());
 #if defined(TOOLKIT_VIEWS)
   // Mirror the positions if necessary.
-  complete_bounds.set_x(
-      containing_view->MirroredLeftPointForRect(complete_bounds));
+  complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds));
 #endif
 
   // Start at full opacity, then loop back and forth five times before ending
@@ -469,7 +508,7 @@
   DCHECK(download);
 
   // Set up our OLE machinery
-  OSExchangeData data;
+  ui::OSExchangeData data;
 
   if (icon) {
     drag_utils::CreateDragImageForFile(
@@ -477,7 +516,7 @@
   }
 
   const FilePath full_path = download->full_path();
-  data.SetFilename(full_path.ToWStringHack());
+  data.SetFilename(full_path);
 
   std::string mime_type = download->mime_type();
   if (mime_type.empty())
@@ -490,12 +529,12 @@
   }
 
 #if defined(OS_WIN)
-  scoped_refptr<app::win::DragSource> drag_source(new app::win::DragSource);
+  scoped_refptr<ui::DragSource> drag_source(new ui::DragSource);
 
   // Run the drag and drop loop
   DWORD effects;
-  DoDragDrop(OSExchangeDataProviderWin::GetIDataObject(data), drag_source.get(),
-             DROPEFFECT_COPY | DROPEFFECT_LINK, &effects);
+  DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data),
+             drag_source.get(), DROPEFFECT_COPY | DROPEFFECT_LINK, &effects);
 #elif defined(TOOLKIT_USES_GTK)
   GtkWidget* root = gtk_widget_get_toplevel(view);
   if (!root)
@@ -504,7 +543,8 @@
   if (!widget)
     return;
 
-  widget->DoDrag(data, DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK);
+  widget->DoDrag(data,
+                 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK);
 #endif  // OS_WIN
 }
 #elif defined(USE_X11)
@@ -637,7 +677,11 @@
   // Iterate through all the browser windows, and draw the progress bar.
   for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
       browser_iterator != BrowserList::end(); browser_iterator++) {
-    HWND frame = (*browser_iterator)->window()->GetNativeHandle();
+    Browser* browser = *browser_iterator;
+    BrowserWindow* window = browser->window();
+    if (!window)
+      continue;
+    HWND frame = window->GetNativeHandle();
     if (download_count == 0 || progress == 1.0f)
       taskbar->SetProgressState(frame, TBPF_NOPROGRESS);
     else if (!progress_known)
@@ -685,7 +729,8 @@
     URLRequestContextGetter* request_context_getter) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  URLRequestContext* context = request_context_getter->GetURLRequestContext();
+  net::URLRequestContext* context =
+      request_context_getter->GetURLRequestContext();
   context->set_referrer_charset(referrer_charset);
 
   rdh->BeginDownload(url,
@@ -753,24 +798,25 @@
 }
 
 // TODO(erikkay,phajdan.jr): This is apparently not being exercised in tests.
-bool IsDangerous(DownloadCreateInfo* info, Profile* profile) {
+bool IsDangerous(DownloadCreateInfo* info, Profile* profile, bool auto_open) {
   DownloadDangerLevel danger_level = GetFileDangerLevel(
       info->suggested_path.BaseName());
 
+  bool ret = false;
   if (danger_level == Dangerous) {
-    return true;
+    ret = !(auto_open && info->has_user_gesture);
   } else if (danger_level == AllowOnUserGesture && !info->has_user_gesture) {
-    return true;
+    ret = true;
   } else if (info->is_extension_install) {
     ExtensionService* service = profile->GetExtensionService();
     if (!service ||
         !service->IsDownloadFromGallery(info->url, info->referrer_url)) {
       // Extensions that are not from the gallery are considered dangerous.
-      return true;
+      ret = true;
     }
   }
 
-  return false;
+  return ret;
 }
 
 }  // namespace download_util
diff --git a/chrome/browser/download/download_util.h b/chrome/browser/download/download_util.h
index c1013a3..630c00f 100644
--- a/chrome/browser/download/download_util.h
+++ b/chrome/browser/download/download_util.h
@@ -13,7 +13,7 @@
 #include "base/basictypes.h"
 #include "base/file_path.h"
 #include "base/string16.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 #if defined(TOOLKIT_VIEWS)
 #include "views/view.h"
@@ -207,8 +207,11 @@
 // Returns a .crdownload intermediate path for the |suggested_path|.
 FilePath GetCrDownloadPath(const FilePath& suggested_path);
 
-// Whether a given download should be considered potentially dangerous.
-bool IsDangerous(DownloadCreateInfo *info, Profile* profile);
+// Returns true if this download should show the "dangerous file" warning.
+// Various factors are considered, such as the type of the file, whether a
+// user action initiated the download, and whether the user has explictly
+// marked the file type as "auto open".
+bool IsDangerous(DownloadCreateInfo* info, Profile* profile, bool auto_open);
 
 }  // namespace download_util
 
diff --git a/chrome/browser/download/download_util_unittest.cc b/chrome/browser/download/download_util_unittest.cc
index 1a905b1..9368938 100644
--- a/chrome/browser/download/download_util_unittest.cc
+++ b/chrome/browser/download/download_util_unittest.cc
@@ -42,17 +42,29 @@
    "text/plain",
    L"my_download.txt"},
 
-  // Disposition has relative paths, remove them
+  // Disposition has relative paths, remove directory separators
   {"filename=../../../../././../a_file_name.txt",
    "http://www.evil.com/my_download.txt",
    "text/plain",
-   L"a_file_name.txt"},
+   L"_.._.._.._._._.._a_file_name.txt"},
 
-  // Disposition has parent directories, remove them
+  // Disposition has parent directories, remove directory separators
   {"filename=dir1/dir2/a_file_name.txt",
    "http://www.evil.com/my_download.txt",
    "text/plain",
-   L"a_file_name.txt"},
+   L"dir1_dir2_a_file_name.txt"},
+
+  // Disposition has relative paths, remove directory separators
+  {"filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt",
+   "http://www.evil.com/my_download.txt",
+   "text/plain",
+   L"_.._.._.._._._.._a_file_name.txt"},
+
+  // Disposition has parent directories, remove directory separators
+  {"filename=dir1\\dir2\\a_file_name.txt",
+   "http://www.evil.com/my_download.txt",
+   "text/plain",
+   L"dir1_dir2_a_file_name.txt"},
 
   // No useful information in disposition or URL, use default
   {"", "http://www.truncated.com/path/", "text/plain",
@@ -183,16 +195,12 @@
   {"filename=../foo.txt",
    "http://www.evil.com/../foo.txt",
    "text/plain",
-   L"foo.txt"},
+   L"_foo.txt"},
 
   {"filename=..\\foo.txt",
    "http://www.evil.com/..\\foo.txt",
    "text/plain",
-#if defined(OS_WIN)
-   L"foo.txt"
-#else
-   L"\\foo.txt"
-#endif
+   L"_foo.txt"
   },
 
   {"filename=.hidden",
@@ -437,7 +445,8 @@
   std::string locale = setlocale(LC_CTYPE, NULL);
   StringToLowerASCII(&locale);
   EXPECT_NE(std::string::npos, locale.find("utf-8"))
-      << "Your locale must be set to UTF-8 for this test to pass!";
+      << "Your locale (" << locale << ") must be set to UTF-8 "
+      << "for this test to pass!";
 #endif
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGenerateFileNameTestCases); ++i) {
diff --git a/chrome/browser/download/drag_download_file.cc b/chrome/browser/download/drag_download_file.cc
index 3426ef7..9d16105 100644
--- a/chrome/browser/download/drag_download_file.cc
+++ b/chrome/browser/download/drag_download_file.cc
@@ -57,7 +57,7 @@
     download_manager_->RemoveObserver(this);
 }
 
-bool DragDownloadFile::Start(DownloadFileObserver* observer) {
+bool DragDownloadFile::Start(ui::DownloadFileObserver* observer) {
   AssertCurrentlyOnDragThread();
 
   if (is_started_)
@@ -155,7 +155,7 @@
   download_manager_->GetTemporaryDownloads(file_path_.DirName(), &downloads);
   for (std::vector<DownloadItem*>::const_iterator i = downloads.begin();
        i != downloads.end(); ++i) {
-    if (!download_item_observer_added_ && (*i)->url() == url_) {
+    if (!download_item_observer_added_ && (*i)->original_url() == url_) {
       download_item_observer_added_ = true;
       (*i)->AddObserver(this);
     }
diff --git a/chrome/browser/download/drag_download_file.h b/chrome/browser/download/drag_download_file.h
index a6cb190..3bbe9c6 100644
--- a/chrome/browser/download/drag_download_file.h
+++ b/chrome/browser/download/drag_download_file.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_DOWNLOAD_DRAG_DOWNLOAD_FILE_H_
 #pragma once
 
-#include "app/download_file_interface.h"
 #include "base/file_path.h"
 #include "base/linked_ptr.h"
 #include "chrome/browser/download/download_file.h"
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 #include "googleurl/src/gurl.h"
+#include "ui/base/dragdrop/download_file_interface.h"
 
 class TabContents;
 
@@ -20,7 +20,7 @@
 class FileStream;
 }
 
-class DragDownloadFile : public DownloadFileProvider,
+class DragDownloadFile : public ui::DownloadFileProvider,
                          public DownloadManager::Observer,
                          public DownloadItem::Observer {
  public:
@@ -43,7 +43,7 @@
   // DownloadFileProvider methods.
   // Called on drag-and-drop thread (Windows).
   // Called on UI thread (MacOSX).
-  virtual bool Start(DownloadFileObserver* observer);
+  virtual bool Start(ui::DownloadFileObserver* observer);
   virtual void Stop();
 #if defined(OS_WIN)
   virtual IStream* GetStream() { return NULL; }
@@ -96,7 +96,7 @@
   // Accessed on UI thread (MacOSX).
   bool is_started_;
   bool is_successful_;
-  scoped_refptr<DownloadFileObserver> observer_;
+  scoped_refptr<ui::DownloadFileObserver> observer_;
 
   // Accessed on drag-and-drop thread (Windows only).
 #if defined(OS_WIN)
diff --git a/chrome/browser/download/drag_download_util.h b/chrome/browser/download/drag_download_util.h
index 31bda47..f4d6b55 100644
--- a/chrome/browser/download/drag_download_util.h
+++ b/chrome/browser/download/drag_download_util.h
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_DOWNLOAD_DRAG_DOWNLOAD_UTIL_H_
 #pragma once
 
-#include "app/download_file_interface.h"
 #include "base/basictypes.h"
 #include "base/ref_counted.h"
 #include "base/string16.h"
 #include "chrome/browser/download/drag_download_file.h"
+#include "ui/base/dragdrop/download_file_interface.h"
 
 class FilePath;
 class GURL;
@@ -40,7 +40,7 @@
 net::FileStream* CreateFileStreamForDrop(FilePath* file_path);
 
 // Implementation of DownloadFileObserver to finalize the download process.
-class PromiseFileFinalizer : public DownloadFileObserver {
+class PromiseFileFinalizer : public ui::DownloadFileObserver {
  public:
   explicit PromiseFileFinalizer(DragDownloadFile* drag_file_downloader);
   virtual ~PromiseFileFinalizer();
diff --git a/chrome/browser/download/mock_download_manager.h b/chrome/browser/download/mock_download_manager.h
new file mode 100644
index 0000000..270ae0f
--- /dev/null
+++ b/chrome/browser/download/mock_download_manager.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_DOWNLOAD_MANAGER_H_
+#define MOCK_DOWNLOAD_MANAGER_H_
+#pragma once
+
+#include "chrome/browser/download/download_manager.h"
+
+class DownloadStatusUpdater;
+class DownloadItem;
+
+class MockDownloadManager : public DownloadManager {
+ public:
+  explicit MockDownloadManager(DownloadStatusUpdater* updater)
+      : DownloadManager(updater) {
+  }
+
+  // Override some functions.
+  virtual void UpdateHistoryForDownload(DownloadItem*) { }
+  virtual void ContinueDownloadFinished(DownloadItem*) { }
+};
+
+#endif  // MOCK_DOWNLOAD_MANAGER_H_
diff --git a/chrome/browser/download/save_file_manager.cc b/chrome/browser/download/save_file_manager.cc
index 5b25ea6..c18dd3f 100644
--- a/chrome/browser/download/save_file_manager.cc
+++ b/chrome/browser/download/save_file_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -222,7 +222,7 @@
   SaveFile* save_file = new SaveFile(info);
 
   // TODO(phajdan.jr): We should check the return value and handle errors here.
-  save_file->Initialize();
+  save_file->Initialize(false);  // No need to calculate hash.
 
   DCHECK(!LookupSaveFile(info->save_id));
   save_file_map_[info->save_id] = save_file;
@@ -354,7 +354,8 @@
     int render_view_id,
     URLRequestContextGetter* request_context_getter) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  URLRequestContext* context = request_context_getter->GetURLRequestContext();
+  net::URLRequestContext* context =
+      request_context_getter->GetURLRequestContext();
   resource_dispatcher_host_->BeginSaveFile(url,
                                            referrer,
                                            render_process_host_id,
diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc
index 23c062c..01edafe 100644
--- a/chrome/browser/download/save_package.cc
+++ b/chrome/browser/download/save_package.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/i18n/file_util_icu.h"
@@ -15,6 +14,7 @@
 #include "base/stl_util-inl.h"
 #include "base/string_piece.h"
 #include "base/string_split.h"
+#include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/task.h"
 #include "base/threading/thread.h"
@@ -23,6 +23,7 @@
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/download/download_shelf.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/download/save_file.h"
@@ -44,13 +45,15 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "net/base/io_buffer.h"
 #include "net/base/mime_util.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request_context.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPageSerializerClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializerClient.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::Time;
 using WebKit::WebPageSerializerClient;
@@ -62,8 +65,7 @@
 
 // Default name which will be used when we can not get proper name from
 // resource URL.
-const FilePath::CharType kDefaultSaveName[] =
-    FILE_PATH_LITERAL("saved_resource");
+const char kDefaultSaveName[] = "saved_resource";
 
 const FilePath::CharType kDefaultHtmlExtension[] =
 #if defined(OS_WIN)
@@ -94,6 +96,32 @@
 // exists only for testing.
 bool g_should_prompt_for_filename = true;
 
+// Indexes used for specifying which element in the extensions dropdown
+// the user chooses when picking a save type.
+const int kSelectFileHtmlOnlyIndex = 1;
+const int kSelectFileCompleteIndex = 2;
+
+// Used for mapping between SavePackageType constants and the indexes above.
+const SavePackage::SavePackageType kIndexToSaveType[] = {
+  SavePackage::SAVE_TYPE_UNKNOWN,
+  SavePackage::SAVE_AS_ONLY_HTML,
+  SavePackage::SAVE_AS_COMPLETE_HTML,
+};
+
+// Used for mapping between the IDS_ string identifiers and the indexes above.
+const int kIndexToIDS[] = {
+  0, IDS_SAVE_PAGE_DESC_HTML_ONLY, IDS_SAVE_PAGE_DESC_COMPLETE,
+};
+
+int SavePackageTypeToIndex(SavePackage::SavePackageType type) {
+  for (size_t i = 0; i < arraysize(kIndexToSaveType); ++i) {
+    if (kIndexToSaveType[i] == type)
+      return i;
+  }
+  NOTREACHED();
+  return -1;
+}
+
 // Strip current ordinal number, if any. Should only be used on pure
 // file names, i.e. those stripped of their extensions.
 // TODO(estade): improve this to not choke on alternate encodings.
@@ -123,50 +151,6 @@
          contents_mime_type == "application/xhtml+xml";
 }
 
-// File name is considered being consist of pure file name, dot and file
-// extension name. File name might has no dot and file extension, or has
-// multiple dot inside file name. The dot, which separates the pure file
-// name and file extension name, is last dot in the whole file name.
-// This function is for making sure the length of specified file path is not
-// great than the specified maximum length of file path and getting safe pure
-// file name part if the input pure file name is too long.
-// The parameter |dir_path| specifies directory part of the specified
-// file path. The parameter |file_name_ext| specifies file extension
-// name part of the specified file path (including start dot). The parameter
-// |max_file_path_len| specifies maximum length of the specified file path.
-// The parameter |pure_file_name| input pure file name part of the specified
-// file path. If the length of specified file path is great than
-// |max_file_path_len|, the |pure_file_name| will output new pure file name
-// part for making sure the length of specified file path is less than
-// specified maximum length of file path. Return false if the function can
-// not get a safe pure file name, otherwise it returns true.
-bool GetSafePureFileName(const FilePath& dir_path,
-                         const FilePath::StringType& file_name_ext,
-                         uint32 max_file_path_len,
-                         FilePath::StringType* pure_file_name) {
-  DCHECK(!pure_file_name->empty());
-  int available_length = static_cast<int>(
-    max_file_path_len - dir_path.value().length() - file_name_ext.length());
-  // Need an extra space for the separator.
-  if (!file_util::EndsWithSeparator(dir_path))
-    --available_length;
-
-  // Plenty of room.
-  if (static_cast<int>(pure_file_name->length()) <= available_length)
-    return true;
-
-  // Limited room. Truncate |pure_file_name| to fit.
-  if (available_length > 0) {
-    *pure_file_name =
-        pure_file_name->substr(0, available_length);
-    return true;
-  }
-
-  // Not enough room to even use a shortened |pure_file_name|.
-  pure_file_name->clear();
-  return false;
-}
-
 }  // namespace
 
 SavePackage::SavePackage(TabContents* tab_contents,
@@ -368,6 +352,63 @@
   return true;
 }
 
+// On POSIX, the length of |pure_file_name| + |file_name_ext| is further
+// restricted by NAME_MAX. The maximum allowed path looks like:
+// '/path/to/save_dir' + '/' + NAME_MAX.
+uint32 SavePackage::GetMaxPathLengthForDirectory(const FilePath& base_dir) {
+#if defined(OS_POSIX)
+  return std::min(kMaxFilePathLength,
+                  static_cast<uint32>(base_dir.value().length()) +
+                  NAME_MAX + 1);
+#else
+  return kMaxFilePathLength;
+#endif
+}
+
+// File name is considered being consist of pure file name, dot and file
+// extension name. File name might has no dot and file extension, or has
+// multiple dot inside file name. The dot, which separates the pure file
+// name and file extension name, is last dot in the whole file name.
+// This function is for making sure the length of specified file path is not
+// great than the specified maximum length of file path and getting safe pure
+// file name part if the input pure file name is too long.
+// The parameter |dir_path| specifies directory part of the specified
+// file path. The parameter |file_name_ext| specifies file extension
+// name part of the specified file path (including start dot). The parameter
+// |max_file_path_len| specifies maximum length of the specified file path.
+// The parameter |pure_file_name| input pure file name part of the specified
+// file path. If the length of specified file path is great than
+// |max_file_path_len|, the |pure_file_name| will output new pure file name
+// part for making sure the length of specified file path is less than
+// specified maximum length of file path. Return false if the function can
+// not get a safe pure file name, otherwise it returns true.
+bool SavePackage::GetSafePureFileName(const FilePath& dir_path,
+                                      const FilePath::StringType& file_name_ext,
+                                      uint32 max_file_path_len,
+                                      FilePath::StringType* pure_file_name) {
+  DCHECK(!pure_file_name->empty());
+  int available_length = static_cast<int>(max_file_path_len -
+                                          dir_path.value().length() -
+                                          file_name_ext.length());
+  // Need an extra space for the separator.
+  if (!file_util::EndsWithSeparator(dir_path))
+    --available_length;
+
+  // Plenty of room.
+  if (static_cast<int>(pure_file_name->length()) <= available_length)
+    return true;
+
+  // Limited room. Truncate |pure_file_name| to fit.
+  if (available_length > 0) {
+    *pure_file_name = pure_file_name->substr(0, available_length);
+    return true;
+  }
+
+  // Not enough room to even use a shortened |pure_file_name|.
+  pure_file_name->clear();
+  return false;
+}
+
 // Generate name for saving resource.
 bool SavePackage::GenerateFileName(const std::string& disposition,
                                    const GURL& url,
@@ -375,8 +416,20 @@
                                    FilePath::StringType* generated_name) {
   // TODO(jungshik): Figure out the referrer charset when having one
   // makes sense and pass it to GetSuggestedFilename.
-  FilePath file_path = net::GetSuggestedFilename(url, disposition, "",
-                                                 FilePath(kDefaultSaveName));
+  string16 suggested_name =
+      net::GetSuggestedFilename(url, disposition, "",
+                                ASCIIToUTF16(kDefaultSaveName));
+
+  // TODO(evan): this code is totally wrong -- we should just generate
+  // Unicode filenames and do all this encoding switching at the end.
+  // However, I'm just shuffling wrong code around, at least not adding
+  // to it.
+#if defined(OS_WIN)
+  FilePath file_path = FilePath(suggested_name);
+#else
+  FilePath file_path = FilePath(
+      base::SysWideToNativeMB(UTF16ToWide(suggested_name)));
+#endif
 
   DCHECK(!file_path.empty());
   FilePath::StringType pure_file_name =
@@ -389,9 +442,12 @@
     file_name_ext.append(kDefaultHtmlExtension);
   }
 
+  // Need to make sure the suggested file name is not too long.
+  uint32 max_path = GetMaxPathLengthForDirectory(saved_main_directory_path_);
+
   // Get safe pure file name.
   if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
-                           kMaxFilePathLength, &pure_file_name))
+                           max_path, &pure_file_name))
     return false;
 
   FilePath::StringType file_name = pure_file_name + file_name_ext;
@@ -406,7 +462,7 @@
     // We need to make sure the length of base file name plus maximum ordinal
     // number path will be less than or equal to kMaxFilePathLength.
     if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
-        kMaxFilePathLength - kMaxFileOrdinalNumberPartLength, &base_file_name))
+        max_path - kMaxFileOrdinalNumberPartLength, &base_file_name))
       return false;
 
     // Prepare the new ordinal number.
@@ -429,7 +485,7 @@
       // Get safe pure file name.
       if (!GetSafePureFileName(saved_main_directory_path_,
                                FilePath::StringType(),
-                               kMaxFilePathLength, &file_name))
+                               max_path, &file_name))
         return false;
     } else {
       for (int i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) {
@@ -687,8 +743,9 @@
                         save_ids));
 
   download_->OnAllDataSaved(all_save_items_count_);
+  download_->MarkAsComplete();
   // Notify download observers that we are complete (the call
-  // to OnAllDataSaved() set the state to complete but did not notify).
+  // to OnReadyToFinish() set the state to complete but did not notify).
   download_->UpdateObservers();
 
   NotificationService::current()->Notify(
@@ -886,6 +943,18 @@
   }
 }
 
+bool SavePackage::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(SavePackage, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_SendCurrentPageAllSavableResourceLinks,
+                        OnReceivedSavableResourceLinksForCurrentPage)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData,
+                        OnReceivedSerializedHtmlData)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
 // After finishing all SaveItems which need to get data from net.
 // We collect all URLs which have local storage and send the
 // map:(originalURL:currentLocalPath) to render process (backend).
@@ -1221,15 +1290,8 @@
   FilePath::StringType file_name_ext = suggested_filename.Extension();
 
   // Need to make sure the suggested file name is not too long.
-  uint32 max_path = kMaxFilePathLength;
-#if defined(OS_POSIX)
-  // On POSIX, the length of |pure_file_name| + |file_name_ext| is further
-  // restricted by NAME_MAX. The maximum allowed path looks like:
-  // '/path/to/save_dir' + '/' + NAME_MAX.
-  max_path = std::min(max_path,
-                      static_cast<uint32>(save_dir.value().length()) +
-                      NAME_MAX + 1);
-#endif
+  uint32 max_path = GetMaxPathLengthForDirectory(save_dir);
+
   if (GetSafePureFileName(save_dir, file_name_ext, max_path, &pure_file_name)) {
     save_dir = save_dir.Append(pure_file_name + file_name_ext);
   } else {
@@ -1248,8 +1310,12 @@
 
 void SavePackage::ContinueGetSaveInfo(const FilePath& suggested_path,
                                       bool can_save_as_complete) {
-  // Use "Web Page, Complete" option as default choice of saving page.
-  int file_type_index = 2;
+  DownloadPrefs* download_prefs =
+      tab_contents_->profile()->GetDownloadManager()->download_prefs();
+  int file_type_index =
+      SavePackageTypeToIndex(
+          static_cast<SavePackageType>(download_prefs->save_file_type()));
+
   SelectFileDialog::FileTypeInfo file_type_info;
   FilePath::StringType default_extension;
 
@@ -1264,26 +1330,44 @@
       add_extra_extension = true;
       extra_extension = suggested_path.Extension().substr(1);
     }
+
     file_type_info.extensions.resize(2);
-    file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("htm"));
-    file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
-    if (add_extra_extension)
-      file_type_info.extensions[0].push_back(extra_extension);
+    file_type_info.extensions[kSelectFileHtmlOnlyIndex - 1].push_back(
+        FILE_PATH_LITERAL("htm"));
+    file_type_info.extensions[kSelectFileHtmlOnlyIndex - 1].push_back(
+        FILE_PATH_LITERAL("html"));
+
+    if (add_extra_extension) {
+      file_type_info.extensions[kSelectFileHtmlOnlyIndex - 1].push_back(
+          extra_extension);
+    }
+
     file_type_info.extension_description_overrides.push_back(
-        l10n_util::GetStringUTF16(IDS_SAVE_PAGE_DESC_HTML_ONLY));
-    file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("htm"));
-    file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("html"));
-    if (add_extra_extension)
-      file_type_info.extensions[1].push_back(extra_extension);
+        l10n_util::GetStringUTF16(kIndexToIDS[kSelectFileCompleteIndex - 1]));
+    file_type_info.extensions[kSelectFileCompleteIndex - 1].push_back(
+        FILE_PATH_LITERAL("htm"));
+    file_type_info.extensions[kSelectFileCompleteIndex - 1].push_back(
+        FILE_PATH_LITERAL("html"));
+
+    if (add_extra_extension) {
+      file_type_info.extensions[kSelectFileCompleteIndex - 1].push_back(
+          extra_extension);
+    }
+
     file_type_info.extension_description_overrides.push_back(
-        l10n_util::GetStringUTF16(IDS_SAVE_PAGE_DESC_COMPLETE));
+        l10n_util::GetStringUTF16(kIndexToIDS[kSelectFileCompleteIndex]));
     file_type_info.include_all_files = false;
     default_extension = kDefaultHtmlExtension;
   } else {
     file_type_info.extensions.resize(1);
-    file_type_info.extensions[0].push_back(suggested_path.Extension());
-    if (!file_type_info.extensions[0][0].empty())
-      file_type_info.extensions[0][0].erase(0, 1);  // drop the .
+    file_type_info.extensions[kSelectFileHtmlOnlyIndex - 1].push_back(
+        suggested_path.Extension());
+
+    if (!file_type_info.extensions[kSelectFileHtmlOnlyIndex - 1][0].empty()) {
+      // Drop the .
+      file_type_info.extensions[kSelectFileHtmlOnlyIndex - 1][0].erase(0, 1);
+    }
+
     file_type_info.include_all_files = true;
     file_type_index = 1;
   }
@@ -1315,7 +1399,9 @@
                                       &saved_main_file_path_);
 
   // The option index is not zero-based.
-  DCHECK(index > 0 && index < 3);
+  DCHECK(index >= kSelectFileHtmlOnlyIndex &&
+         index <= kSelectFileCompleteIndex);
+
   saved_main_directory_path_ = saved_main_file_path_.DirName();
 
   PrefService* prefs = tab_contents_->profile()->GetPrefs();
@@ -1333,8 +1419,9 @@
     save_file_path.SetValue(path_string);
   }
 
-  save_type_ = (index == 1) ? SavePackage::SAVE_AS_ONLY_HTML :
-                             SavePackage::SAVE_AS_COMPLETE_HTML;
+  save_type_ = kIndexToSaveType[index];
+
+  prefs->SetInteger(prefs::kSaveFileType, save_type_);
 
   if (save_type_ == SavePackage::SAVE_AS_COMPLETE_HTML) {
     // Make new directory for saving complete file.
diff --git a/chrome/browser/download/save_package.h b/chrome/browser/download/save_package.h
index ddfc172..59e27f3 100644
--- a/chrome/browser/download/save_package.h
+++ b/chrome/browser/download/save_package.h
@@ -16,8 +16,8 @@
 #include "base/hash_tables.h"
 #include "base/ref_counted.h"
 #include "base/task.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "googleurl/src/gurl.h"
 
 class SaveFileManager;
@@ -54,7 +54,7 @@
 // by the SavePackage. SaveItems are created when a user initiates a page
 // saving job, and exist for the duration of one tab's life time.
 class SavePackage : public base::RefCountedThreadSafe<SavePackage>,
-                    public RenderViewHostDelegate::Save,
+                    public TabContentsObserver,
                     public SelectFileDialog::Listener {
  public:
   enum SavePackageType {
@@ -128,22 +128,6 @@
 
   void GetSaveInfo();
 
-  // RenderViewHostDelegate::Save ----------------------------------------------
-
-  // Process all of the current page's savable links of subresources, resources
-  // referrers and frames (including the main frame and subframes) from the
-  // render view host.
-  virtual void OnReceivedSavableResourceLinksForCurrentPage(
-      const std::vector<GURL>& resources_list,
-      const std::vector<GURL>& referrers_list,
-      const std::vector<GURL>& frames_list);
-
-  // Process the serialized html content data of a specified web page
-  // gotten from render process.
-  virtual void OnReceivedSerializedHtmlData(const GURL& frame_url,
-                                            const std::string& data,
-                                            int32 status);
-
   // Statics -------------------------------------------------------------------
 
   // Used to disable prompting the user for a directory/filename of the saved
@@ -179,6 +163,20 @@
   void SaveNextFile(bool process_all_remainder_items);
   void DoSavingProcess();
 
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+  // Return max length of a path for a specific base directory.
+  // This is needed on POSIX, which restrict the length of file names in
+  // addition to the restriction on the length of path names.
+  // |base_dir| is assumed to be a directory name with no trailing slash.
+  static uint32 GetMaxPathLengthForDirectory(const FilePath& base_dir);
+
+  static bool GetSafePureFileName(const FilePath& dir_path,
+                                  const FilePath::StringType& file_name_ext,
+                                  uint32 max_file_path_len,
+                                  FilePath::StringType* pure_file_name);
+
   // Create a file name based on the response from the server.
   bool GenerateFileName(const std::string& disposition,
                         const GURL& url,
@@ -205,6 +203,15 @@
                            bool can_save_as_complete);
   void ContinueSave(const FilePath& final_name, int index);
 
+  void OnReceivedSavableResourceLinksForCurrentPage(
+      const std::vector<GURL>& resources_list,
+      const std::vector<GURL>& referrers_list,
+      const std::vector<GURL>& frames_list);
+
+  void OnReceivedSerializedHtmlData(const GURL& frame_url,
+                                    const std::string& data,
+                                    int32 status);
+
 
   typedef base::hash_map<std::string, SaveItem*> SaveUrlItemMap;
   // in_progress_items_ is map of all saving job in in-progress state.
@@ -315,6 +322,7 @@
 
   friend class SavePackageTest;
   FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestSuggestedSaveNames);
+  FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestLongSafePureFilename);
 
   ScopedRunnableMethodFactory<SavePackage> method_factory_;
 
diff --git a/chrome/browser/download/save_package_unittest.cc b/chrome/browser/download/save_package_unittest.cc
index 948280f..908fab7 100644
--- a/chrome/browser/download/save_package_unittest.cc
+++ b/chrome/browser/download/save_package_unittest.cc
@@ -30,8 +30,10 @@
 // This constant copied from save_package.cc.
 #if defined(OS_WIN)
 const uint32 kMaxFilePathLength = MAX_PATH - 1;
+const uint32 kMaxFileNameLength = MAX_PATH - 1;
 #elif defined(OS_POSIX)
 const uint32 kMaxFilePathLength = PATH_MAX - 1;
+const uint32 kMaxFileNameLength = NAME_MAX;
 #endif
 
 // Used to make long filenames.
@@ -209,6 +211,23 @@
   EXPECT_NE(filename, filename2);
 }
 
+TEST_F(SavePackageTest, TestLongSafePureFilename) {
+  const FilePath save_dir(FPL("test_dir"));
+  const FilePath::StringType ext(FPL_HTML_EXTENSION);
+  FilePath::StringType filename =
+#if defined(OS_WIN)
+      ASCIIToWide(long_file_name);
+#else
+      long_file_name;
+#endif
+
+  // Test that the filename + extension doesn't exceed kMaxFileNameLength
+  uint32 max_path = SavePackage::GetMaxPathLengthForDirectory(save_dir);
+  ASSERT_TRUE(SavePackage::GetSafePureFileName(save_dir, ext, max_path,
+                                               &filename));
+  EXPECT_TRUE(filename.length() <= kMaxFileNameLength-ext.length());
+}
+
 static const struct {
   const FilePath::CharType* page_title;
   const FilePath::CharType* expected_name;
@@ -369,4 +388,3 @@
   EXPECT_EQ(actual_url, GetUrlToBeSaved());
   EXPECT_EQ(view_source_url, contents()->GetURL());
 }
-
diff --git a/chrome/browser/download/save_page_uitest.cc b/chrome/browser/download/save_page_uitest.cc
index d6078b3..3f72d80 100644
--- a/chrome/browser/download/save_page_uitest.cc
+++ b/chrome/browser/download/save_page_uitest.cc
@@ -14,7 +14,7 @@
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_test.h"
 #include "chrome/test/ui_test_utils.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 
 namespace {
 
diff --git a/chrome/browser/enumerate_modules_model_win.cc b/chrome/browser/enumerate_modules_model_win.cc
index 79e0604..807e3fb 100644
--- a/chrome/browser/enumerate_modules_model_win.cc
+++ b/chrome/browser/enumerate_modules_model_win.cc
@@ -7,8 +7,6 @@
 #include <Tlhelp32.h>
 #include <wintrust.h>
 
-#include "app/l10n_util.h"
-#include "app/win/win_util.h"
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/file_path.h"
@@ -28,6 +26,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // The period of time (in milliseconds) to wait until checking to see if any
 // incompatible modules exist.
@@ -59,7 +58,7 @@
 
 // Used to protect the LoadedModuleVector which is accessed
 // from both the UI thread and the FILE thread.
-Lock* lock = NULL;
+base::Lock* lock = NULL;
 
 // A struct to help de-duping modules before adding them to the enumerated
 // modules vector.
@@ -75,8 +74,23 @@
   const ModuleEnumerator::Module& module;
 };
 
+// Returns the long path name given a short path name. A short path name is a
+// path that follows the 8.3 convention and has ~x in it. If the path is already
+// a long path name, the function returns the current path without modification.
+bool ConvertToLongPath(const string16& short_path, string16* long_path) {
+  wchar_t long_path_buf[MAX_PATH];
+  DWORD return_value = GetLongPathName(short_path.c_str(), long_path_buf,
+                                       MAX_PATH);
+  if (return_value != 0 && return_value < MAX_PATH) {
+    *long_path = long_path_buf;
+    return true;
+  }
+
+  return false;
 }
 
+}  // namespace
+
 // The browser process module blacklist. This lists modules that are known
 // to cause compatibility issues within the browser process. When adding to this
 // list, make sure that all paths are lower-case, in long pathname form, end
@@ -220,7 +234,7 @@
 // static
 void ModuleEnumerator::NormalizeModule(Module* module) {
   string16 path = module->location;
-  if (!app::win::ConvertToLongPath(path, &module->location))
+  if (!ConvertToLongPath(path, &module->location))
     module->location = path;
 
   module->location = l10n_util::ToLower(module->location);
@@ -312,7 +326,8 @@
 }
 
 ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer)
-    : observer_(observer),
+    : enumerated_modules_(NULL),
+      observer_(observer),
       limited_mode_(false),
       callback_thread_id_(BrowserThread::ID_COUNT) {
 }
@@ -423,12 +438,12 @@
     std::wstring key(std::wstring(L"CLSID\\") + registration.Name() +
         L"\\InProcServer32");
     base::win::RegKey clsid;
-    if (!clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ)) {
+    if (clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ) != ERROR_SUCCESS) {
       ++registration;
       continue;
     }
     string16 dll;
-    if (!clsid.ReadValue(L"", &dll)) {
+    if (clsid.ReadValue(L"", &dll) != ERROR_SUCCESS) {
       ++registration;
       continue;
     }
@@ -817,7 +832,7 @@
         this, &EnumerateModulesModel::ScanNow);
   }
 
-  lock = new Lock();
+  lock = new base::Lock();
 }
 
 EnumerateModulesModel::~EnumerateModulesModel() {
diff --git a/chrome/browser/errorpage_uitest.cc b/chrome/browser/errorpage_uitest.cc
index 51b9754..7f10083 100644
--- a/chrome/browser/errorpage_uitest.cc
+++ b/chrome/browser/errorpage_uitest.cc
@@ -1,8 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/string_util.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_test.h"
@@ -16,7 +17,7 @@
     for (int i = 0; i < 10; ++i) {
       if (GetActiveTabTitle() == title)
         return true;
-      base::PlatformThread::Sleep(sleep_timeout_ms());
+      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
     }
     EXPECT_EQ(title, GetActiveTabTitle());
     return false;
diff --git a/chrome/browser/extensions/alert_apitest.cc b/chrome/browser/extensions/alert_apitest.cc
index 10b310b..cbe2a78 100644
--- a/chrome/browser/extensions/alert_apitest.cc
+++ b/chrome/browser/extensions/alert_apitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
@@ -18,8 +19,8 @@
   ExtensionHost* host = browser()->profile()->GetExtensionProcessManager()->
       GetBackgroundHostForExtension(extension);
   ASSERT_TRUE(host);
-  host->render_view_host()->ExecuteJavascriptInWebFrame(L"",
-      L"alert('This should not crash.');");
+  host->render_view_host()->ExecuteJavascriptInWebFrame(string16(),
+      ASCIIToUTF16("alert('This should not crash.');"));
 
   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
   ASSERT_TRUE(alert);
diff --git a/chrome/browser/extensions/all_urls_apitest.cc b/chrome/browser/extensions/all_urls_apitest.cc
index 522610e..36a7750 100644
--- a/chrome/browser/extensions/all_urls_apitest.cc
+++ b/chrome/browser/extensions/all_urls_apitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -26,9 +26,6 @@
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(AllUrlsApiTest, WhitelistedExtension) {
-  base::TimeTicks start_time = base::TimeTicks::Now();
-  Checkpoint("Setting up extensions", start_time);
-
   // First setup the two extensions.
   FilePath extension_dir1 = test_data_dir_.AppendASCII("all_urls")
                                           .AppendASCII("content_script");
@@ -36,106 +33,94 @@
                                           .AppendASCII("execute_script");
 
   // Then add the two extensions to the whitelist.
-  Checkpoint("Setting up whitelist", start_time);
   Extension::ScriptingWhitelist whitelist;
   whitelist.push_back(Extension::GenerateIdForPath(extension_dir1));
   whitelist.push_back(Extension::GenerateIdForPath(extension_dir2));
   Extension::SetScriptingWhitelist(whitelist);
 
   // Then load extensions.
-  Checkpoint("LoadExtension1", start_time);
   ExtensionService* service = browser()->profile()->GetExtensionService();
   const size_t size_before = service->extensions()->size();
   ASSERT_TRUE(LoadExtension(extension_dir1));
-  Checkpoint("LoadExtension2", start_time);
   ASSERT_TRUE(LoadExtension(extension_dir2));
   EXPECT_EQ(size_before + 2, service->extensions()->size());
 
   std::string url;
 
   // Now verify we run content scripts on chrome://newtab/.
-  Checkpoint("Verify content scripts", start_time);
   url = "chrome://newtab/";
   ExtensionTestMessageListener listener1a("content script: " + url, false);
   ExtensionTestMessageListener listener1b("execute: " + url, false);
   ui_test_utils::NavigateToURL(browser(), GURL(url));
-  Checkpoint("Wait for 1a", start_time);
   ASSERT_TRUE(listener1a.WaitUntilSatisfied());
-  Checkpoint("Wait for 1b", start_time);
   ASSERT_TRUE(listener1b.WaitUntilSatisfied());
 
   // Now verify data: urls.
-  Checkpoint("Verify data:urls", start_time);
   url = "data:text/html;charset=utf-8,<html>asdf</html>";
   ExtensionTestMessageListener listener2a("content script: " + url, false);
   ExtensionTestMessageListener listener2b("execute: " + url, false);
   ui_test_utils::NavigateToURL(browser(), GURL(url));
-  Checkpoint("Wait for 2a", start_time);
   ASSERT_TRUE(listener2a.WaitUntilSatisfied());
-  Checkpoint("Wait for 2b", start_time);
   ASSERT_TRUE(listener2b.WaitUntilSatisfied());
 
   // Now verify about:version.
-  Checkpoint("Verify about:version", start_time);
   url = "about:version";
   ExtensionTestMessageListener listener3a("content script: " + url, false);
   ExtensionTestMessageListener listener3b("execute: " + url, false);
   ui_test_utils::NavigateToURL(browser(), GURL(url));
-  Checkpoint("Wait for 3a", start_time);
   ASSERT_TRUE(listener3a.WaitUntilSatisfied());
-  Checkpoint("Wait for 3b", start_time);
   ASSERT_TRUE(listener3b.WaitUntilSatisfied());
 
   // Now verify about:blank.
-  Checkpoint("Verify about:blank", start_time);
   url = "about:blank";
   ExtensionTestMessageListener listener4a("content script: " + url, false);
   ExtensionTestMessageListener listener4b("execute: " + url, false);
   ui_test_utils::NavigateToURL(browser(), GURL(url));
-  Checkpoint("Wait for 4a", start_time);
   ASSERT_TRUE(listener4a.WaitUntilSatisfied());
-  Checkpoint("Wait for 4b", start_time);
   ASSERT_TRUE(listener4b.WaitUntilSatisfied());
 
   // Now verify we can script a regular http page.
-  Checkpoint("Verify regular http page", start_time);
   ASSERT_TRUE(test_server()->Start());
   GURL page_url = test_server()->GetURL(kAllUrlsTarget);
   ExtensionTestMessageListener listener5a("content script: " + page_url.spec(),
                                           false);
   ExtensionTestMessageListener listener5b("execute: " + page_url.spec(), false);
   ui_test_utils::NavigateToURL(browser(), page_url);
-  Checkpoint("Wait for 5a", start_time);
   ASSERT_TRUE(listener5a.WaitUntilSatisfied());
-  Checkpoint("Wait for 5ba", start_time);
   ASSERT_TRUE(listener5b.WaitUntilSatisfied());
-
-  Checkpoint("Test complete", start_time);
 }
 
 // Test that an extension NOT whitelisted for scripting can ask for <all_urls>
 // and run scripts on non-restricted all pages.
-// Disabled, http://crbug.com/64304.
-IN_PROC_BROWSER_TEST_F(AllUrlsApiTest, DISABLED_RegularExtensions) {
+IN_PROC_BROWSER_TEST_F(AllUrlsApiTest, RegularExtensions) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
+  Checkpoint("Test starting", start_time);
+
   // First load the two extension.
   FilePath extension_dir1 = test_data_dir_.AppendASCII("all_urls")
                                           .AppendASCII("content_script");
   FilePath extension_dir2 = test_data_dir_.AppendASCII("all_urls")
                                           .AppendASCII("execute_script");
 
+  Checkpoint("Loading extensions", start_time);
+
   ExtensionService* service = browser()->profile()->GetExtensionService();
   const size_t size_before = service->extensions()->size();
   ASSERT_TRUE(LoadExtension(extension_dir1));
   ASSERT_TRUE(LoadExtension(extension_dir2));
   EXPECT_EQ(size_before + 2, service->extensions()->size());
 
+  Checkpoint("Starting server", start_time);
+
   // Now verify we can script a regular http page.
   ASSERT_TRUE(test_server()->Start());
   GURL page_url = test_server()->GetURL(kAllUrlsTarget);
   ExtensionTestMessageListener listener1a("content script: " + page_url.spec(),
                                           false);
   ExtensionTestMessageListener listener1b("execute: " + page_url.spec(), false);
+  Checkpoint("Navigate to URL", start_time);
   ui_test_utils::NavigateToURL(browser(), page_url);
   ASSERT_TRUE(listener1a.WaitUntilSatisfied());
   ASSERT_TRUE(listener1b.WaitUntilSatisfied());
+  Checkpoint("Test ending", start_time);
 }
diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc
index 89a19a1..f1f98bf 100644
--- a/chrome/browser/extensions/app_background_page_apitest.cc
+++ b/chrome/browser/extensions/app_background_page_apitest.cc
@@ -4,7 +4,6 @@
 
 #include "base/string_util.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/base/mock_host_resolver.h"
@@ -65,7 +64,8 @@
   ASSERT_TRUE(RunExtensionTest("app_background_page/basic")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, LacksPermission) {
+// Crashy, http://crbug.com/49215.
+IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, DISABLED_LacksPermission) {
   host_resolver()->AddRule("a.com", "127.0.0.1");
   ASSERT_TRUE(StartTestServer());
 
diff --git a/chrome/browser/extensions/autoupdate_interceptor.cc b/chrome/browser/extensions/autoupdate_interceptor.cc
index 751658b..7f90a10 100644
--- a/chrome/browser/extensions/autoupdate_interceptor.cc
+++ b/chrome/browser/extensions/autoupdate_interceptor.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,14 +10,19 @@
 #include "net/url_request/url_request_test_job.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// This is a specialized version of URLRequestTestJob that lets us specify
+// This is a specialized version of net::URLRequestTestJob that lets us specify
 // response data and make sure the response code is 200, which the autoupdate
 // code relies on.
-class AutoUpdateTestRequestJob : public URLRequestTestJob {
+class AutoUpdateTestRequestJob : public net::URLRequestTestJob {
  public:
   AutoUpdateTestRequestJob(net::URLRequest* request,
-    const std::string& response_data) : URLRequestTestJob(
-    request, URLRequestTestJob::test_headers(), response_data, true) {}
+                           const std::string& response_data)
+      : net::URLRequestTestJob(request,
+                               net::URLRequestTestJob::test_headers(),
+                               response_data,
+                               true) {
+  }
+
   virtual int GetResponseCode() const { return 200; }
 
  private:
diff --git a/chrome/browser/extensions/browser_action_apitest.cc b/chrome/browser/extensions/browser_action_apitest.cc
index 8c413e4..fd4b8ff 100644
--- a/chrome/browser/extensions/browser_action_apitest.cc
+++ b/chrome/browser/extensions/browser_action_apitest.cc
@@ -17,12 +17,11 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/ui_test_utils.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 class BrowserActionApiTest : public ExtensionApiTest {
  public:
@@ -70,7 +69,8 @@
   ui_test_utils::NavigateToURL(browser(),
       test_server()->GetURL("files/extensions/test_file.txt"));
 
-  ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
+  ExtensionService* service = browser()->profile()->GetExtensionService();
+  service->browser_event_router()->BrowserActionExecuted(
       browser()->profile(), action->extension_id(), browser());
 
   // Verify the command worked.
@@ -143,7 +143,14 @@
   EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0));
 }
 
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopup) {
+// http://code.google.com/p/chromium/issues/detail?id=70829
+// Only mac is okay.
+#if !defined(OS_MACOSX)
+#define MAYBE_BrowserActionPopup DISABLED_BrowserActionPopup
+#else
+#define MAYBE_BrowserActionPopup BrowserActionPopup
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, MAYBE_BrowserActionPopup) {
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
       "browser_action/popup")));
   BrowserActionTestUtil actions_bar = GetBrowserActionsBar();
diff --git a/chrome/browser/extensions/browser_action_test_util_gtk.cc b/chrome/browser/extensions/browser_action_test_util_gtk.cc
index 3781bd6..936fe73 100644
--- a/chrome/browser/extensions/browser_action_test_util_gtk.cc
+++ b/chrome/browser/extensions/browser_action_test_util_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,10 +7,10 @@
 #include <gtk/gtk.h>
 
 #include "chrome/browser/browser_window.h"
-#include "chrome/browser/gtk/extension_popup_gtk.h"
-#include "chrome/browser/gtk/extension_view_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/extension_popup_gtk.h"
+#include "chrome/browser/ui/gtk/extension_view_gtk.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
 
 namespace {
 
diff --git a/chrome/browser/extensions/browser_action_test_util_mac.mm b/chrome/browser/extensions/browser_action_test_util_mac.mm
index 3b6dcc6..2eeeffc 100644
--- a/chrome/browser/extensions/browser_action_test_util_mac.mm
+++ b/chrome/browser/extensions/browser_action_test_util_mac.mm
@@ -11,9 +11,9 @@
 #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 namespace {
 
diff --git a/chrome/browser/extensions/browser_action_test_util_views.cc b/chrome/browser/extensions/browser_action_test_util_views.cc
index 0a384c5..3372094 100644
--- a/chrome/browser/extensions/browser_action_test_util_views.cc
+++ b/chrome/browser/extensions/browser_action_test_util_views.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,13 +7,13 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/views/browser_actions_container.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
-#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/browser/ui/views/browser_actions_container.h"
+#include "chrome/browser/ui/views/extensions/extension_popup.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 namespace {
 
diff --git a/chrome/browser/extensions/content_script_all_frames_apitest.cc b/chrome/browser/extensions/content_script_all_frames_apitest.cc
deleted file mode 100644
index b465c42..0000000
--- a/chrome/browser/extensions/content_script_all_frames_apitest.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_apitest.h"
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) {
-  ASSERT_TRUE(StartTestServer());
-  ASSERT_TRUE(RunExtensionTest("content_scripts/all_frames")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionIframe) {
-  ASSERT_TRUE(StartTestServer());
-  ASSERT_TRUE(RunExtensionTest("content_scripts/extension_iframe")) << message_;
-}
diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc
new file mode 100644
index 0000000..01232eb
--- /dev/null
+++ b/chrome/browser/extensions/content_script_apitest.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/test/ui_test_utils.h"
+#include "net/base/mock_host_resolver.h"
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) {
+  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(RunExtensionTest("content_scripts/all_frames")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionIframe) {
+  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(RunExtensionTest("content_scripts/extension_iframe")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionProcess) {
+  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(
+      RunExtensionTest("content_scripts/extension_process")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptFragmentNavigation) {
+  ASSERT_TRUE(StartTestServer());
+  const char* extension_name = "content_scripts/fragment";
+  ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptIsolatedWorlds) {
+  // This extension runs various bits of script and tests that they all run in
+  // the same isolated world.
+  ASSERT_TRUE(StartTestServer());
+  ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world1")) << message_;
+
+  // Now load a different extension, inject into same page, verify worlds aren't
+  // shared.
+  ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world2")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptIgnoreHostPermissions) {
+  ASSERT_TRUE(StartTestServer());
+  host_resolver()->AddRule("a.com", "127.0.0.1");
+  host_resolver()->AddRule("b.com", "127.0.0.1");
+  ASSERT_TRUE(RunExtensionTest(
+      "content_scripts/dont_match_host_permissions")) << message_;
+}
diff --git a/chrome/browser/extensions/content_script_extension_process_apitest.cc b/chrome/browser/extensions/content_script_extension_process_apitest.cc
deleted file mode 100644
index 100e77b..0000000
--- a/chrome/browser/extensions/content_script_extension_process_apitest.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/test/ui_test_utils.h"
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptExtensionProcess) {
-  ASSERT_TRUE(StartTestServer());
-  ASSERT_TRUE(
-      RunExtensionTest("content_scripts/extension_process")) << message_;
-}
diff --git a/chrome/browser/extensions/convert_user_script.cc b/chrome/browser/extensions/convert_user_script.cc
index bcb0f5a..0b45da8 100644
--- a/chrome/browser/extensions/convert_user_script.cc
+++ b/chrome/browser/extensions/convert_user_script.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,6 +18,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_file_util.h"
 #include "chrome/common/extensions/user_script.h"
 #include "chrome/common/json_value_serializer.h"
 #include "googleurl/src/gurl.h"
@@ -29,8 +30,7 @@
     std::string* error) {
   std::string content;
   if (!file_util::ReadFileToString(user_script_path, &content)) {
-    *error = "Could not read source file: " +
-        WideToASCII(user_script_path.ToWStringHack());
+    *error = "Could not read source file.";
     return NULL;
   }
 
@@ -46,8 +46,11 @@
     return NULL;
   }
 
-  FilePath user_data_temp_dir;
-  CHECK(PathService::Get(chrome::DIR_USER_DATA_TEMP, &user_data_temp_dir));
+  FilePath user_data_temp_dir = extension_file_util::GetUserDataTempDir();
+  if (user_data_temp_dir.empty()) {
+    *error = "Could not get path to profile temporary directory.";
+    return NULL;
+  }
 
   ScopedTempDir temp_dir;
   if (!temp_dir.CreateUniqueTempDirUnderPath(user_data_temp_dir)) {
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc
index e1c8c92..fe082d9 100644
--- a/chrome/browser/extensions/convert_web_app.cc
+++ b/chrome/browser/extensions/convert_web_app.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,11 +22,12 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_file_util.h"
 #include "chrome/common/json_value_serializer.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/codec/png_codec.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace keys = extension_manifest_keys;
 
@@ -84,8 +85,11 @@
 scoped_refptr<Extension> ConvertWebAppToExtension(
     const WebApplicationInfo& web_app,
     const Time& create_time) {
-  FilePath user_data_temp_dir;
-  CHECK(PathService::Get(chrome::DIR_USER_DATA_TEMP, &user_data_temp_dir));
+  FilePath user_data_temp_dir = extension_file_util::GetUserDataTempDir();
+  if (user_data_temp_dir.empty()) {
+    LOG(ERROR) << "Could not get path to profile temporary directory.";
+    return NULL;
+  }
 
   ScopedTempDir temp_dir;
   if (!temp_dir.CreateUniqueTempDirUnderPath(user_data_temp_dir)) {
diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc
index eab9b8f..00198be 100644
--- a/chrome/browser/extensions/convert_web_app_unittest.cc
+++ b/chrome/browser/extensions/convert_web_app_unittest.cc
@@ -21,9 +21,9 @@
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/extensions/url_pattern.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/codec/png_codec.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "webkit/glue/image_decoder.h"
 
 namespace {
@@ -110,7 +110,7 @@
   ASSERT_TRUE(extension.get());
 
   ScopedTempDir extension_dir;
-  extension_dir.Set(extension->path());
+  EXPECT_TRUE(extension_dir.Set(extension->path()));
 
   EXPECT_TRUE(extension->is_app());
   EXPECT_TRUE(extension->is_hosted_app());
@@ -153,7 +153,7 @@
   ASSERT_TRUE(extension.get());
 
   ScopedTempDir extension_dir;
-  extension_dir.Set(extension->path());
+  EXPECT_TRUE(extension_dir.Set(extension->path()));
 
   EXPECT_TRUE(extension->is_app());
   EXPECT_TRUE(extension->is_hosted_app());
diff --git a/chrome/browser/extensions/crashed_extension_infobar.cc b/chrome/browser/extensions/crashed_extension_infobar.cc
index fbed6e6..b462446 100644
--- a/chrome/browser/extensions/crashed_extension_infobar.cc
+++ b/chrome/browser/extensions/crashed_extension_infobar.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/crashed_extension_infobar.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/common/extensions/extension.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 CrashedExtensionInfoBarDelegate::CrashedExtensionInfoBarDelegate(
     TabContents* tab_contents,
@@ -25,9 +25,7 @@
   DCHECK(!extension_id_.empty());
 }
 
-CrashedExtensionInfoBarDelegate* CrashedExtensionInfoBarDelegate::
-AsCrashedExtensionInfoBarDelegate() {
-  return this;
+CrashedExtensionInfoBarDelegate::~CrashedExtensionInfoBarDelegate() {
 }
 
 bool CrashedExtensionInfoBarDelegate::ShouldExpire(
@@ -35,11 +33,6 @@
   return false;
 }
 
-string16 CrashedExtensionInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringFUTF16(IDS_EXTENSION_CRASHED_INFOBAR_MESSAGE,
-      UTF8ToUTF16(extension_name_));
-}
-
 void CrashedExtensionInfoBarDelegate::InfoBarClosed() {
   delete this;
 }
@@ -50,17 +43,25 @@
       IDR_INFOBAR_PLUGIN_CRASHED);
 }
 
+CrashedExtensionInfoBarDelegate*
+    CrashedExtensionInfoBarDelegate::AsCrashedExtensionInfoBarDelegate() {
+  return this;
+}
+
+string16 CrashedExtensionInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_EXTENSION_CRASHED_INFOBAR_MESSAGE,
+                                    UTF8ToUTF16(extension_name_));
+}
+
 int CrashedExtensionInfoBarDelegate::GetButtons() const {
   return BUTTON_OK;
 }
 
 string16 CrashedExtensionInfoBarDelegate::GetButtonLabel(
-    ConfirmInfoBarDelegate::InfoBarButton button) const {
-  if (button == BUTTON_OK) {
-    return l10n_util::GetStringUTF16(
-        IDS_EXTENSION_CRASHED_INFOBAR_RESTART_BUTTON);
-  }
-  return ConfirmInfoBarDelegate::GetButtonLabel(button);
+    InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(
+      IDS_EXTENSION_CRASHED_INFOBAR_RELOAD_BUTTON);
 }
 
 bool CrashedExtensionInfoBarDelegate::Accept() {
diff --git a/chrome/browser/extensions/crashed_extension_infobar.h b/chrome/browser/extensions/crashed_extension_infobar.h
index 201e606..d4d08a7 100644
--- a/chrome/browser/extensions/crashed_extension_infobar.h
+++ b/chrome/browser/extensions/crashed_extension_infobar.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,21 +28,20 @@
 
   const std::string extension_id() { return extension_id_; }
 
-  // InfoBarDelegate
-  virtual CrashedExtensionInfoBarDelegate* AsCrashedExtensionInfoBarDelegate();
+ private:
+  virtual ~CrashedExtensionInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
   virtual bool ShouldExpire(
       const NavigationController::LoadCommittedDetails& details) const;
-
-  // ConfirmInfoBarDelegate
-  virtual string16 GetMessageText() const;
   virtual void InfoBarClosed();
   virtual SkBitmap* GetIcon() const;
+  virtual CrashedExtensionInfoBarDelegate* AsCrashedExtensionInfoBarDelegate();
+  virtual string16 GetMessageText() const;
   virtual int GetButtons() const;
-  virtual string16 GetButtonLabel(
-      ConfirmInfoBarDelegate::InfoBarButton button) const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
   virtual bool Accept();
 
- private:
   ExtensionService* extensions_service_;
 
   const std::string extension_id_;
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 1593aea..a1a001a 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <set>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/path_service.h"
@@ -36,6 +34,8 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -117,18 +117,9 @@
 void CrxInstaller::InstallCrx(const FilePath& source_file) {
   source_file_ = source_file;
 
-  FilePath user_data_temp_dir;
-  {
-    // We shouldn't be doing disk IO on the UI thread.
-    //   http://code.google.com/p/chromium/issues/detail?id=60634
-    base::ThreadRestrictions::ScopedAllowIO allow_io;
-    CHECK(PathService::Get(chrome::DIR_USER_DATA_TEMP, &user_data_temp_dir));
-  }
-
   scoped_refptr<SandboxedExtensionUnpacker> unpacker(
       new SandboxedExtensionUnpacker(
           source_file,
-          user_data_temp_dir,
           g_browser_process->resource_dispatcher_host(),
           this));
 
@@ -310,7 +301,8 @@
   GURL overlapping_url;
   const Extension* overlapping_extension =
       frontend_->GetExtensionByOverlappingWebExtent(extension_->web_extent());
-  if (overlapping_extension) {
+  if (overlapping_extension &&
+      overlapping_extension->id() != extension_->id()) {
     ReportFailureFromUIThread(l10n_util::GetStringFUTF8(
         IDS_EXTENSION_OVERLAPPING_WEB_EXTENT,
         UTF8ToUTF16(overlapping_extension->name())));
diff --git a/chrome/browser/extensions/default_apps.cc b/chrome/browser/extensions/default_apps.cc
index 4afe325..bf8aa9a 100644
--- a/chrome/browser/extensions/default_apps.cc
+++ b/chrome/browser/extensions/default_apps.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "chrome/browser/extensions/default_apps.h"
 
 #include "base/command_line.h"
@@ -87,7 +89,10 @@
 #endif
 }
 
-bool DefaultApps::ShouldShowPromo(const ExtensionIdSet& installed_ids) {
+bool DefaultApps::ShouldShowPromo(const ExtensionIdSet& installed_ids,
+                                  bool* just_expired) {
+  *just_expired = false;
+
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kForceAppsPromoVisible)) {
     return true;
@@ -96,16 +101,35 @@
   if (!DefaultAppSupported())
     return false;
 
-  if (GetDefaultAppsInstalled() && GetPromoCounter() < kAppsPromoCounterMax) {
+  if (!GetDefaultAppsInstalled())
+    return false;
+
+  int promo_counter = GetPromoCounter();
+  if (promo_counter <= kAppsPromoCounterMax) {
     // If we have the exact set of default apps, show the promo. If we don't
     // have the exact set of default apps, this means that the user manually
     // installed or uninstalled one. The promo doesn't make sense if it shows
     // apps the user manually installed, so expire it immediately in that
     // situation.
-    if (installed_ids == ids_)
-      return true;
-    else
+    if (ids_ != installed_ids) {
       SetPromoHidden();
+      return false;
+    }
+
+    if (promo_counter == kAppsPromoCounterMax) {
+      *just_expired = true;
+      UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram,
+                                extension_misc::PROMO_EXPIRE,
+                                extension_misc::PROMO_BUCKET_BOUNDARY);
+      SetPromoCounter(++promo_counter);
+      return false;
+    } else {
+      UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram,
+                                extension_misc::PROMO_SEEN,
+                                extension_misc::PROMO_BUCKET_BOUNDARY);
+      SetPromoCounter(++promo_counter);
+      return true;
+    }
   }
 
   return false;
@@ -123,29 +147,6 @@
   }
 }
 
-void DefaultApps::DidShowPromo() {
-  if (!GetDefaultAppsInstalled()) {
-    NOTREACHED() << "Should not show promo until default apps are installed.";
-    return;
-  }
-
-  int promo_counter = GetPromoCounter();
-  if (promo_counter == kAppsPromoCounterMax) {
-    NOTREACHED() << "Promo has already been shown the maximum number of times.";
-    return;
-  }
-
-  if (promo_counter < kAppsPromoCounterMax) {
-    if (promo_counter + 1 == kAppsPromoCounterMax)
-      UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram,
-                                extension_misc::PROMO_EXPIRE,
-                                extension_misc::PROMO_BUCKET_BOUNDARY);
-    SetPromoCounter(++promo_counter);
-  } else {
-    SetPromoHidden();
-  }
-}
-
 bool DefaultApps::NonDefaultAppIsInstalled(
     const ExtensionIdSet& installed_ids) const {
   for (ExtensionIdSet::const_iterator iter = installed_ids.begin();
@@ -158,7 +159,7 @@
 }
 
 void DefaultApps::SetPromoHidden() {
-  SetPromoCounter(kAppsPromoCounterMax);
+  SetPromoCounter(kAppsPromoCounterMax + 1);
 }
 
 int DefaultApps::GetPromoCounter() const {
diff --git a/chrome/browser/extensions/default_apps.h b/chrome/browser/extensions/default_apps.h
index a8b162c..2ff8801 100644
--- a/chrome/browser/extensions/default_apps.h
+++ b/chrome/browser/extensions/default_apps.h
@@ -19,7 +19,9 @@
 // - Whether to show the apps promo in the launcher
 class DefaultApps {
  public:
-  // The maximum number of times to show the apps promo.
+  // The maximum number of times to show the apps promo. The promo counter
+  // actually goes up to this number + 1 because we need to differentiate
+  // between the first time we overflow and subsequent times.
   static const int kAppsPromoCounterMax;
 
   // Register our preferences.
@@ -42,15 +44,12 @@
   //
   // NOTE: If the default apps have been installed, but |installed_ids| is
   // different than GetDefaultApps(), this will permanently expire the promo.
-  bool ShouldShowPromo(const ExtensionIdSet& installed_ids);
+  bool ShouldShowPromo(const ExtensionIdSet& installed_ids, bool* just_expired);
 
   // Should be called after each app is installed. Once installed_ids contains
   // all the default apps, GetAppsToInstall() will start returning NULL.
   void DidInstallApp(const ExtensionIdSet& installed_ids);
 
-  // Should be called after each time the promo is installed.
-  void DidShowPromo();
-
   // Force the promo to be hidden.
   void SetPromoHidden();
 
diff --git a/chrome/browser/extensions/default_apps_unittest.cc b/chrome/browser/extensions/default_apps_unittest.cc
index fd87d58..316568d 100644
--- a/chrome/browser/extensions/default_apps_unittest.cc
+++ b/chrome/browser/extensions/default_apps_unittest.cc
@@ -30,7 +30,10 @@
   EXPECT_FALSE(default_apps.ShouldShowAppLauncher(installed_app_ids));
 
   // The promo should not be shown until the default apps have been installed.
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
+  bool promo_just_expired = false;
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 
   // Simulate installing the apps one by one and notifying default_apps after
   // each intallation. Nothing should change until we have installed all the
@@ -44,7 +47,9 @@
     EXPECT_FALSE(default_apps.GetDefaultAppsInstalled());
     EXPECT_TRUE(default_apps.ShouldInstallDefaultApps(installed_app_ids));
     EXPECT_FALSE(default_apps.ShouldShowAppLauncher(installed_app_ids));
-    EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
+    EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids,
+                                              &promo_just_expired));
+    EXPECT_FALSE(promo_just_expired);
   }
 
   // Simulate all the default apps being installed. Now we should stop getting
@@ -56,23 +61,36 @@
 
   // And the promo and launcher should become available.
   EXPECT_TRUE(default_apps.ShouldShowAppLauncher(installed_app_ids));
-  EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids));
+  EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids,
+                                           &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 
   // The promo should be available up to the max allowed times, then stop.
-  for (int i = 0; i < DefaultApps::kAppsPromoCounterMax; ++i) {
-    EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids));
-    default_apps.DidShowPromo();
+  // We start counting at 1 because of the call to ShouldShowPromo() above.
+  for (int i = 1; i < DefaultApps::kAppsPromoCounterMax; ++i) {
+    EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids,
+                                             &promo_just_expired));
+    EXPECT_FALSE(promo_just_expired);
     EXPECT_EQ(i + 1, default_apps.GetPromoCounter());
   }
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
-  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+
+  // The first time, should_show_promo should flip to true, then back to false.
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids,
+                                            &promo_just_expired));
+  EXPECT_TRUE(promo_just_expired);
+  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax + 1,
+            default_apps.GetPromoCounter());
 
   // Even if all the apps are subsequently removed, the apps section should
   // remain.
   installed_app_ids.clear();
   EXPECT_FALSE(default_apps.ShouldInstallDefaultApps(installed_app_ids));
   EXPECT_TRUE(default_apps.ShouldShowAppLauncher(installed_app_ids));
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
+  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax + 1,
+            default_apps.GetPromoCounter());
 }
 
 TEST(ExtensionDefaultApps, UnsupportedLocale) {
@@ -88,28 +106,38 @@
   ExtensionIdSet installed_ids;
   EXPECT_FALSE(default_apps.ShouldInstallDefaultApps(installed_ids));
   EXPECT_FALSE(default_apps.ShouldShowAppLauncher(installed_ids));
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
+
+  bool promo_just_expired = false;
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 
   // If the user installs an app manually, then we show the apps section, but
   // no promotion or default apps.
   installed_ids.insert(*(default_app_ids.begin()));
   EXPECT_FALSE(default_apps.ShouldInstallDefaultApps(installed_ids));
   EXPECT_TRUE(default_apps.ShouldShowAppLauncher(installed_ids));
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 
   // Even if the user installs the exact set of default apps, we don't show the
   // promo.
   installed_ids = default_app_ids;
   EXPECT_FALSE(default_apps.ShouldInstallDefaultApps(installed_ids));
   EXPECT_TRUE(default_apps.ShouldShowAppLauncher(installed_ids));
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 
   // If the user uninstalls the apps again, we go back to not showing the
   // apps section.
   installed_ids.clear();
   EXPECT_FALSE(default_apps.ShouldInstallDefaultApps(installed_ids));
   EXPECT_FALSE(default_apps.ShouldShowAppLauncher(installed_ids));
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 }
 
 TEST(ExtensionDefaultApps, HidePromo) {
@@ -120,13 +148,18 @@
   const ExtensionIdSet& default_app_ids = default_apps.default_apps();
   default_apps.DidInstallApp(default_app_ids);
 
-  EXPECT_TRUE(default_apps.ShouldShowPromo(default_app_ids));
-  default_apps.DidShowPromo();
+  bool promo_just_expired = false;
+  EXPECT_TRUE(default_apps.ShouldShowPromo(default_app_ids,
+                                           &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
   EXPECT_EQ(1, default_apps.GetPromoCounter());
 
   default_apps.SetPromoHidden();
-  EXPECT_FALSE(default_apps.ShouldShowPromo(default_app_ids));
-  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+  EXPECT_FALSE(default_apps.ShouldShowPromo(default_app_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
+  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax + 1,
+            default_apps.GetPromoCounter());
 }
 
 TEST(ExtensionDefaultApps, InstallingAnAppHidesPromo) {
@@ -138,15 +171,20 @@
   ExtensionIdSet installed_app_ids = default_app_ids;
   default_apps.DidInstallApp(installed_app_ids);
 
-  EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids));
-  default_apps.DidShowPromo();
+  bool promo_just_expired = false;
+  EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids,
+                                           &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
   EXPECT_EQ(1, default_apps.GetPromoCounter());
 
   // Now simulate a new extension being installed. This should cause the promo
   // to be hidden.
   installed_app_ids.insert("foo");
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
-  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
+  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax + 1,
+            default_apps.GetPromoCounter());
 }
 
 TEST(ExtensionDefaultApps, ManualAppInstalledWhileInstallingDefaultApps) {
@@ -173,8 +211,12 @@
 
   // The promo shouldn't turn on though, because it would look weird with the
   // user's extra, manually installed extensions.
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
-  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+  bool promo_just_expired = false;
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
+  EXPECT_EQ(DefaultApps::kAppsPromoCounterMax + 1,
+            default_apps.GetPromoCounter());
 
   // Going back to a subset of the default apps shouldn't allow the default app
   // install to continue.
@@ -182,9 +224,13 @@
   EXPECT_FALSE(default_apps.ShouldInstallDefaultApps(installed_ids));
   EXPECT_TRUE(default_apps.GetDefaultAppsInstalled());
   EXPECT_TRUE(default_apps.ShouldShowAppLauncher(installed_ids));
-  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
+  EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids,
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 
   // Going to the exact set of default apps shouldn't show the promo.
-  EXPECT_FALSE(default_apps.ShouldShowPromo(default_apps.default_apps()));
+  EXPECT_FALSE(default_apps.ShouldShowPromo(default_apps.default_apps(),
+                                            &promo_just_expired));
+  EXPECT_FALSE(promo_just_expired);
 }
 #endif  // OS_CHROMEOS
diff --git a/chrome/browser/extensions/events_apitest.cc b/chrome/browser/extensions/events_apitest.cc
index 8319ae6..3420022 100644
--- a/chrome/browser/extensions/events_apitest.cc
+++ b/chrome/browser/extensions/events_apitest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Events) {
   ASSERT_TRUE(RunExtensionTest("events")) << message_;
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc
index b3bfee0..7c51573 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.cc
+++ b/chrome/browser/extensions/execute_code_in_tab_function.cc
@@ -79,15 +79,8 @@
 
   // NOTE: This can give the wrong answer due to race conditions, but it is OK,
   // we check again in the renderer.
-  const Extension* extension = GetExtension();
-  const std::vector<URLPattern> host_permissions =
-      extension->host_permissions();
-  if (!Extension::CanExecuteScriptOnPage(
-        contents->tab_contents()->GetURL(),
-        extension->CanExecuteScriptEverywhere(),
-        &host_permissions,
-        NULL,
-        &error_)) {
+  if (!GetExtension()->CanExecuteScriptOnPage(
+          contents->tab_contents()->GetURL(), NULL, &error_)) {
     return false;
   }
 
diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc
index 0015de9..8295ca4 100644
--- a/chrome/browser/extensions/execute_script_apitest.cc
+++ b/chrome/browser/extensions/execute_script_apitest.cc
@@ -38,3 +38,11 @@
   ASSERT_TRUE(StartTestServer());
   ASSERT_TRUE(RunExtensionTest("executescript/file_after_close")) << message_;
 }
+
+// Crashy, http://crbug.com/67774.
+IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest,
+                       DISABLED_ExecuteScriptFragmentNavigation) {
+  ASSERT_TRUE(StartTestServer());
+  const char* extension_name = "executescript/fragment";
+  ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
+}
diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc
index fa0ee0e..fd083b2 100644
--- a/chrome/browser/extensions/extension_accessibility_api.cc
+++ b/chrome/browser/extensions/extension_accessibility_api.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_service.h"
 
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index dbb47cd..744c142 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -19,6 +19,10 @@
 
 };  // namespace
 
+ExtensionApiTest::ExtensionApiTest() {}
+
+ExtensionApiTest::~ExtensionApiTest() {}
+
 ExtensionApiTest::ResultCatcher::ResultCatcher()
     : profile_restriction_(NULL),
       waiting_(false) {
@@ -152,7 +156,6 @@
       url = extension->GetResourceURL(page_url);
     }
 
-    LOG(ERROR) << "Loading page url: " << url.spec();
     ui_test_utils::NavigateToURL(browser(), url);
   }
 
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h
index 4f76d28..e7d2af6 100644
--- a/chrome/browser/extensions/extension_apitest.h
+++ b/chrome/browser/extensions/extension_apitest.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/common/notification_registrar.h"
 
 class Extension;
 
@@ -24,6 +25,10 @@
 // TODO(erikkay): There should also be a way to drive events in these tests.
 
 class ExtensionApiTest : public ExtensionBrowserTest {
+ public:
+  ExtensionApiTest();
+  virtual ~ExtensionApiTest();
+
  protected:
   // Helper class that observes tests failing or passing. Observation starts
   // when the class is constructed. Get the next result by calling
diff --git a/chrome/browser/extensions/extension_bookmark_helpers.cc b/chrome/browser/extensions/extension_bookmark_helpers.cc
index ad7cbb0..a48a12c 100644
--- a/chrome/browser/extensions/extension_bookmark_helpers.cc
+++ b/chrome/browser/extensions/extension_bookmark_helpers.cc
@@ -33,15 +33,15 @@
     // seconds.
     base::Time t = node->date_group_modified();
     if (!t.is_null())
-      dict->SetReal(keys::kDateGroupModifiedKey, floor(t.ToDoubleT() * 1000));
+      dict->SetDouble(keys::kDateGroupModifiedKey, floor(t.ToDoubleT() * 1000));
   }
 
   dict->SetString(keys::kTitleKey, node->GetTitle());
   if (!node->date_added().is_null()) {
     // Javascript Date wants milliseconds since the epoch, ToDoubleT is
     // seconds.
-    dict->SetReal(keys::kDateAddedKey,
-                  floor(node->date_added().ToDoubleT() * 1000));
+    dict->SetDouble(keys::kDateAddedKey,
+                    floor(node->date_added().ToDoubleT() * 1000));
   }
 
   if (recurse && node->is_folder()) {
diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc
index 67963b2..074f69f 100644
--- a/chrome/browser/extensions/extension_bookmark_manager_api.cc
+++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/json/json_writer.h"
 #include "base/string_number_conversions.h"
 #include "base/values.h"
@@ -16,12 +15,13 @@
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/extensions/extension_bookmark_helpers.h"
 #include "chrome/browser/extensions/extension_bookmarks_module_constants.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
 #include "chrome/browser/extensions/extension_event_router.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace keys = extension_bookmarks_module_constants;
 
@@ -43,10 +43,10 @@
 // Gets a vector of bookmark nodes from the argument list of IDs.
 // This returns false in the case of failure.
 bool GetNodesFromArguments(BookmarkModel* model, const ListValue* args,
-    std::vector<const BookmarkNode*>* nodes) {
+    size_t args_index, std::vector<const BookmarkNode*>* nodes) {
 
   ListValue* ids;
-  if (!args->GetList(0, &ids))
+  if (!args->GetList(args_index, &ids))
     return false;
 
   size_t count = ids->GetSize();
@@ -214,7 +214,7 @@
   BookmarkModel* model = profile()->GetBookmarkModel();
   std::vector<const BookmarkNode*> nodes;
   EXTENSION_FUNCTION_VALIDATE(GetNodesFromArguments(model, args_.get(),
-                                                    &nodes));
+                                                    0, &nodes));
   bookmark_utils::CopyToClipboard(model, nodes, cut);
   return true;
 }
@@ -237,7 +237,20 @@
   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
   if (!can_paste)
     return false;
-  bookmark_utils::PasteFromClipboard(model, parent_node, -1);
+
+  // We want to use the highest index of the selected nodes as a destination.
+  std::vector<const BookmarkNode*> nodes;
+  // No need to test return value, if we got an empty list, we insert at end.
+  GetNodesFromArguments(model, args_.get(), 1, &nodes);
+  int highest_index = -1;  // -1 means insert at end of list.
+  for (size_t node = 0; node < nodes.size(); ++node) {
+    // + 1 so that we insert after the selection.
+    int this_node_index = parent_node->IndexOfChild(nodes[node]) + 1;
+    if (this_node_index > highest_index)
+      highest_index = this_node_index;
+  }
+
+  bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
   return true;
 }
 
@@ -340,14 +353,14 @@
   BookmarkModel* model = profile()->GetBookmarkModel();
   std::vector<const BookmarkNode*> nodes;
   EXTENSION_FUNCTION_VALIDATE(
-      GetNodesFromArguments(model, args_.get(), &nodes));
+      GetNodesFromArguments(model, args_.get(), 0, &nodes));
 
   if (dispatcher()->render_view_host()->delegate()->GetRenderViewType() ==
       ViewType::TAB_CONTENTS) {
-    ExtensionDOMUI* dom_ui =
-        static_cast<ExtensionDOMUI*>(dispatcher()->delegate());
+    ExtensionWebUI* web_ui =
+        static_cast<ExtensionWebUI*>(dispatcher()->delegate());
     bookmark_utils::DragBookmarks(
-        profile(), nodes, dom_ui->tab_contents()->GetNativeView());
+        profile(), nodes, web_ui->tab_contents()->GetNativeView());
 
     return true;
   } else {
@@ -382,10 +395,10 @@
 
   if (dispatcher()->render_view_host()->delegate()->GetRenderViewType() ==
       ViewType::TAB_CONTENTS) {
-    ExtensionDOMUI* dom_ui =
-        static_cast<ExtensionDOMUI*>(dispatcher()->delegate());
+    ExtensionWebUI* web_ui =
+        static_cast<ExtensionWebUI*>(dispatcher()->delegate());
     ExtensionBookmarkManagerEventRouter* router =
-        dom_ui->extension_bookmark_manager_event_router();
+        web_ui->extension_bookmark_manager_event_router();
 
     DCHECK(router);
     const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
index 180a5bb..afe5298 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ b/chrome/browser/extensions/extension_bookmarks_module.cc
@@ -1,14 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_bookmarks_module.h"
 
+#include "base/file_path.h"
+#include "base/i18n/file_util_icu.h"
+#include "base/i18n/time_formatting.h"
 #include "base/json/json_writer.h"
 #include "base/sha1.h"
 #include "base/stl_util-inl.h"
 #include "base/string16.h"
 #include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_codec.h"
 #include "chrome/browser/bookmarks/bookmark_html_writer.h"
@@ -19,12 +24,13 @@
 #include "chrome/browser/extensions/extension_bookmarks_module_constants.h"
 #include "chrome/browser/extensions/extension_event_router.h"
 #include "chrome/browser/extensions/extensions_quota_service.h"
-#include "chrome/browser/importer/importer.h"
 #include "chrome/browser/importer/importer_data_types.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace keys = extension_bookmarks_module_constants;
 
@@ -36,6 +42,30 @@
 typedef ExtensionsQuotaService::SustainedLimit SustainedLimit;
 typedef QuotaLimitHeuristic::BucketMapper BucketMapper;
 
+namespace {
+
+// Generates a default filename that will be used for pre-populating
+// the "Export Bookmarks" file chooser dialog box.
+FilePath::StringType GetDefaultFilenameForBookmarkExport() {
+  base::Time time = base::Time::Now();
+
+  // Concatenate a date stamp to the filename.
+#if defined(OS_POSIX)
+  FilePath::StringType filename =
+      l10n_util::GetStringFUTF8(EXPORT_BOOKMARKS_DEFAULT_FILENAME,
+                                base::TimeFormatShortDateNumeric(time));
+#elif defined(OS_WIN)
+  FilePath::StringType filename =
+      l10n_util::GetStringFUTF16(EXPORT_BOOKMARKS_DEFAULT_FILENAME,
+                                 base::TimeFormatShortDateNumeric(time));
+#endif
+
+  file_util::ReplaceIllegalCharactersInPath(&filename, '_');
+  return filename;
+}
+
+}  // namespace
+
 void BookmarksFunction::Run() {
   BookmarkModel* model = profile()->GetBookmarkModel();
   if (!model->IsLoaded()) {
@@ -775,9 +805,17 @@
   file_type_info.extensions.resize(1);
   file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
 
+  // Pre-populating the filename field in case this is a SELECT_SAVEAS_FILE
+  // dialog. If not, there is no filename field in the dialog box.
+  FilePath default_path;
+  if (type == SelectFileDialog::SELECT_SAVEAS_FILE)
+    default_path = FilePath(GetDefaultFilenameForBookmarkExport());
+  else
+    DCHECK(type == SelectFileDialog::SELECT_OPEN_FILE);
+
   select_file_dialog_->SelectFile(type,
                                   string16(),
-                                  FilePath(),
+                                  default_path,
                                   &file_type_info,
                                   0,
                                   FILE_PATH_LITERAL(""),
@@ -803,15 +841,15 @@
 void ImportBookmarksFunction::FileSelected(const FilePath& path,
                                            int index,
                                            void* params) {
-  ImporterHost* host = new ImporterHost();
+  scoped_refptr<ImporterHost> importer_host(new ImporterHost);
   importer::ProfileInfo profile_info;
   profile_info.browser_type = importer::BOOKMARKS_HTML;
   profile_info.source_path = path;
-  host->StartImportSettings(profile_info,
-                            profile(),
-                            importer::FAVORITES,
-                            new ProfileWriter(profile()),
-                            true);
+  importer_host->StartImportSettings(profile_info,
+                                     profile(),
+                                     importer::FAVORITES,
+                                     new ProfileWriter(profile()),
+                                     true);
   Release();  // Balanced in BookmarksIOFunction::SelectFile()
 }
 
diff --git a/chrome/browser/extensions/extension_bookmarks_module.h b/chrome/browser/extensions/extension_bookmarks_module.h
index 21b9ad8..7b50b4e 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.h
+++ b/chrome/browser/extensions/extension_bookmarks_module.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,10 +10,13 @@
 #include <set>
 #include <string>
 
+#include "base/ref_counted.h"
 #include "base/singleton.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
 #include "chrome/browser/extensions/extension_function.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/importer/importer_list.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
@@ -190,7 +193,7 @@
 
 class ImportBookmarksFunction : public BookmarksIOFunction {
  public:
-  // Override BookmarkManagerIOFunction.
+  // BookmarkManagerIOFunction implementation.
   virtual bool RunImpl();
   virtual void FileSelected(const FilePath& path, int index, void* params);
 
diff --git a/chrome/browser/extensions/extension_browser_actions_api.cc b/chrome/browser/extensions/extension_browser_actions_api.cc
index 8e17a35..973b034 100644
--- a/chrome/browser/extensions/extension_browser_actions_api.cc
+++ b/chrome/browser/extensions/extension_browser_actions_api.cc
@@ -4,9 +4,10 @@
 
 #include "chrome/browser/extensions/extension_browser_actions_api.h"
 
+#include <string>
+
 #include "base/values.h"
 #include "chrome/browser/browser_list.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/render_messages.h"
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc
index 6df9ede..e0341a5 100644
--- a/chrome/browser/extensions/extension_browser_event_router.cc
+++ b/chrome/browser/extensions/extension_browser_event_router.cc
@@ -61,10 +61,6 @@
   return changed_properties;
 }
 
-ExtensionBrowserEventRouter* ExtensionBrowserEventRouter::GetInstance() {
-  return Singleton<ExtensionBrowserEventRouter>::get();
-}
-
 static void DispatchEvent(Profile* profile,
                           const char* event_name,
                           const std::string& json_args) {
@@ -111,16 +107,14 @@
   DispatchEvent(profile, event_name, json_args);
 }
 
-void ExtensionBrowserEventRouter::Init(Profile* profile) {
+void ExtensionBrowserEventRouter::Init() {
   if (initialized_)
     return;
-  DCHECK(!profile->IsOffTheRecord());
-  profile_ = profile;
   BrowserList::AddObserver(this);
 #if defined(TOOLKIT_VIEWS)
   views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this);
 #elif defined(TOOLKIT_GTK)
-  ActiveWindowWatcherX::AddObserver(this);
+  ui::ActiveWindowWatcherX::AddObserver(this);
 #elif defined(OS_MACOSX)
   // Needed for when no suitable window can be passed to an extension as the
   // currently focused window.
@@ -148,12 +142,21 @@
   initialized_ = true;
 }
 
-ExtensionBrowserEventRouter::ExtensionBrowserEventRouter()
+ExtensionBrowserEventRouter::ExtensionBrowserEventRouter(Profile* profile)
     : initialized_(false),
       focused_window_id_(extension_misc::kUnknownWindowId),
-      profile_(NULL) { }
+      profile_(profile) {
+  DCHECK(!profile->IsOffTheRecord());
+}
 
-ExtensionBrowserEventRouter::~ExtensionBrowserEventRouter() {}
+ExtensionBrowserEventRouter::~ExtensionBrowserEventRouter() {
+  BrowserList::RemoveObserver(this);
+#if defined(TOOLKIT_VIEWS)
+  views::FocusManager::GetWidgetFocusManager()->RemoveFocusChangeListener(this);
+#elif defined(TOOLKIT_GTK)
+  ui::ActiveWindowWatcherX::RemoveObserver(this);
+#endif
+}
 
 void ExtensionBrowserEventRouter::OnBrowserAdded(const Browser* browser) {
   RegisterForBrowserNotifications(browser);
@@ -466,11 +469,13 @@
 }
 
 void ExtensionBrowserEventRouter::TabReplacedAt(
+    TabStripModel* tab_strip_model,
     TabContentsWrapper* old_contents,
     TabContentsWrapper* new_contents,
     int index) {
-  UnregisterForTabNotifications(old_contents->tab_contents());
-  RegisterForTabNotifications(new_contents->tab_contents());
+  TabClosingAt(tab_strip_model, old_contents, index);
+  TabInsertedAt(new_contents, index,
+                tab_strip_model->selected_index() == index);
 }
 
 void ExtensionBrowserEventRouter::TabPinnedStateChanged(
diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h
index cdf2efe..27c562d 100644
--- a/chrome/browser/extensions/extension_browser_event_router.h
+++ b/chrome/browser/extensions/extension_browser_event_router.h
@@ -10,7 +10,6 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/singleton.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/extensions/extension_tabs_module.h"
 #include "chrome/browser/tabs/tab_strip_model_observer.h"
@@ -19,7 +18,7 @@
 #include "views/view.h"
 #include "views/focus/focus_manager.h"
 #elif defined(TOOLKIT_GTK)
-#include "app/active_window_watcher_x.h"
+#include "ui/base/x/active_window_watcher_x.h"
 #endif
 
 // The ExtensionBrowserEventRouter listens to Browser window & tab events
@@ -31,16 +30,16 @@
 #if defined(TOOLKIT_VIEWS)
                                     public views::WidgetFocusChangeListener,
 #elif defined(TOOLKIT_GTK)
-                                    public ActiveWindowWatcherX::Observer,
+                                    public ui::ActiveWindowWatcherX::Observer,
 #endif
                                     public BrowserList::Observer,
                                     public NotificationObserver {
  public:
-  // Get Browser-Global instance.
-  static ExtensionBrowserEventRouter* GetInstance();
+  explicit ExtensionBrowserEventRouter(Profile* profile);
+  ~ExtensionBrowserEventRouter();
 
   // Must be called once. Subsequent calls have no effect.
-  void Init(Profile* profile);
+  void Init();
 
   // BrowserList::Observer
   virtual void OnBrowserAdded(const Browser* browser);
@@ -73,7 +72,8 @@
                         int to_index);
   virtual void TabChangedAt(TabContentsWrapper* contents, int index,
                             TabChangeType change_type);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int index);
   virtual void TabPinnedStateChanged(TabContentsWrapper* contents, int index);
@@ -129,10 +129,6 @@
   // Removes notifications added in RegisterForTabNotifications.
   void UnregisterForTabNotifications(TabContents* contents);
 
-  ExtensionBrowserEventRouter();
-  ~ExtensionBrowserEventRouter();
-  friend struct DefaultSingletonTraits<ExtensionBrowserEventRouter>;
-
   NotificationRegistrar registrar_;
 
   bool initialized_;
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 8178848..16bacc7 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -8,10 +8,12 @@
 
 #include "base/command_line.h"
 #include "base/file_path.h"
+#include "base/file_util.h"
 #include "base/path_service.h"
 #include "base/string_number_conversions.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/extension_creator.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
@@ -101,6 +103,45 @@
   return LoadExtensionImpl(path, true);
 }
 
+FilePath ExtensionBrowserTest::PackExtension(const FilePath& dir_path) {
+  FilePath crx_path;
+  if (!PathService::Get(base::DIR_TEMP, &crx_path)) {
+    ADD_FAILURE() << "Failed to get DIR_TEMP from PathService.";
+    return FilePath();
+  }
+  crx_path = crx_path.AppendASCII("temp.crx");
+  if (!file_util::Delete(crx_path, false)) {
+    ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
+    return FilePath();
+  }
+
+  FilePath pem_path = crx_path.DirName().AppendASCII("temp.pem");
+  if (!file_util::Delete(pem_path, false)) {
+    ADD_FAILURE() << "Failed to delete pem: " << pem_path.value();
+    return FilePath();
+  }
+
+  if (!file_util::PathExists(dir_path)) {
+    ADD_FAILURE() << "Extension dir not found: " << dir_path.value();
+    return FilePath();
+  }
+
+  scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
+  if (!creator->Run(dir_path,
+                    crx_path,
+                    FilePath(),  // no existing pem, use empty path
+                    pem_path)) {
+    ADD_FAILURE() << "ExtensionCreator::Run() failed.";
+    return FilePath();
+  }
+
+  if (!file_util::PathExists(crx_path)) {
+    ADD_FAILURE() << crx_path.value() << " was not created.";
+    return FilePath();
+  }
+  return crx_path;
+}
+
 // This class is used to simulate an installation abort by the user.
 class MockAbortExtensionInstallUI : public ExtensionInstallUI {
  public:
@@ -120,11 +161,31 @@
   virtual void OnInstallFailure(const std::string& error) {}
 };
 
+class MockAutoConfirmExtensionInstallUI : public ExtensionInstallUI {
+ public:
+  MockAutoConfirmExtensionInstallUI(Profile* profile) :
+      ExtensionInstallUI(profile) {}
+
+  // Proceed without confirmation prompt.
+  virtual void ConfirmInstall(Delegate* delegate, const Extension* extension) {
+    delegate->InstallUIProceed();
+  }
+};
+
 bool ExtensionBrowserTest::InstallOrUpdateExtension(const std::string& id,
                                                     const FilePath& path,
                                                     InstallUIType ui_type,
                                                     int expected_change) {
-  ExtensionService* service = browser()->profile()->GetExtensionService();
+  return InstallOrUpdateExtension(id, path, ui_type, expected_change,
+                                  browser()->profile());
+}
+
+bool ExtensionBrowserTest::InstallOrUpdateExtension(const std::string& id,
+                                                    const FilePath& path,
+                                                    InstallUIType ui_type,
+                                                    int expected_change,
+                                                    Profile* profile) {
+  ExtensionService* service = profile->GetExtensionService();
   service->set_show_extensions_prompts(false);
   size_t num_before = service->extensions()->size();
 
@@ -141,12 +202,23 @@
     if (ui_type == INSTALL_UI_TYPE_CANCEL)
       install_ui = new MockAbortExtensionInstallUI();
     else if (ui_type == INSTALL_UI_TYPE_NORMAL)
-      install_ui = new ExtensionInstallUI(browser()->profile());
+      install_ui = new ExtensionInstallUI(profile);
+    else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM)
+      install_ui = new MockAutoConfirmExtensionInstallUI(profile);
+
+    // TODO(tessamac): Update callers to always pass an unpacked extension
+    //                 and then always pack the extension here.
+    FilePath crx_path = path;
+    if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) {
+      crx_path = PackExtension(path);
+    }
+    if (crx_path.empty())
+      return false;
 
     scoped_refptr<CrxInstaller> installer(
         new CrxInstaller(service, install_ui));
     installer->set_expected_id(id);
-    installer->InstallCrx(path);
+    installer->InstallCrx(crx_path);
 
     ui_test_utils::RunMessageLoop();
   }
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 9b7f5f0..40a71be 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -12,7 +12,6 @@
 #include "base/file_path.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/test/in_process_browser_test.h"
 
@@ -29,6 +28,10 @@
   // Same as above, but enables the extension in incognito mode first.
   bool LoadExtensionIncognito(const FilePath& path);
 
+  // Pack the extension in |dir_path| into a crx file and return its path.
+  // Return an empty FilePath if there were errors.
+  FilePath PackExtension(const FilePath& dir_path);
+
   // |expected_change| indicates how many extensions should be installed (or
   // disabled, if negative).
   // 1 means you expect a new install, 0 means you expect an upgrade, -1 means
@@ -52,6 +55,12 @@
     return InstallOrUpdateExtension("", path, INSTALL_UI_TYPE_NORMAL,
                                     expected_change);
   }
+  bool InstallExtensionWithUIAutoConfirm(const FilePath& path,
+                                         int expected_change,
+                                         Profile* profile) {
+    return InstallOrUpdateExtension("", path, INSTALL_UI_TYPE_AUTO_CONFIRM,
+                                    expected_change, profile);
+  }
 
   // Begins install process but simulates a user cancel.
   bool StartInstallButCancel(const FilePath& path) {
@@ -109,11 +118,16 @@
     INSTALL_UI_TYPE_NONE,
     INSTALL_UI_TYPE_CANCEL,
     INSTALL_UI_TYPE_NORMAL,
+    INSTALL_UI_TYPE_AUTO_CONFIRM,
   };
 
   bool InstallOrUpdateExtension(const std::string& id, const FilePath& path,
                                 InstallUIType ui_type,
                                 int expected_change);
+  bool InstallOrUpdateExtension(const std::string& id, const FilePath& path,
+                                InstallUIType ui_type,
+                                int expected_change,
+                                Profile* profile);
   bool LoadExtensionImpl(const FilePath& path, bool incognito_enabled);
 
   bool WaitForExtensionHostsToLoad();
diff --git a/chrome/browser/extensions/extension_browsertests_misc.cc b/chrome/browser/extensions/extension_browsertests_misc.cc
index df03580..b767aa0 100644
--- a/chrome/browser/extensions/extension_browsertests_misc.cc
+++ b/chrome/browser/extensions/extension_browsertests_misc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -31,7 +31,7 @@
 #include "net/test/test_server.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #endif
 
 const std::string kSubscribePage = "/subscribe.html";
@@ -50,6 +50,10 @@
 const std::string kInvalidFeed2 = "files/feeds/feed_invalid2.xml";
 const std::string kLocalization =
     "files/extensions/browsertest/title_localized_pa/simple.html";
+// We need a triple encoded string to prove that we are not decoding twice in
+// subscribe.js because one layer is also stripped off when subscribe.js passes
+// it to the XMLHttpRequest object.
+const std::string kFeedTripleEncoded = "files/feeds/url%25255Fdecoding.html";
 const std::string kHashPageA =
     "files/extensions/api_test/page_action/hash_change/test_page_A.html";
 const std::string kHashPageAHash = kHashPageA + "#asdf";
@@ -75,72 +79,6 @@
   return host;
 }
 
-// Tests that extension resources can be loaded from origins which the
-// extension specifies in permissions but not from others.
-IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OriginPrivileges) {
-  host_resolver()->AddRule("*", "127.0.0.1");
-  ASSERT_TRUE(test_server()->Start());
-  ASSERT_TRUE(LoadExtension(test_data_dir_
-    .AppendASCII("origin_privileges").AppendASCII("extension")));
-
-  GURL origin_privileges_index(
-      test_server()->GetURL("files/extensions/origin_privileges/index.html"));
-
-  std::string host_a("a.com");
-  GURL::Replacements make_host_a_com;
-  make_host_a_com.SetHostStr(host_a);
-
-  std::string host_b("b.com");
-  GURL::Replacements make_host_b_com;
-  make_host_b_com.SetHostStr(host_b);
-
-  // A web host that has permission.
-  ui_test_utils::NavigateToURL(
-      browser(), origin_privileges_index.ReplaceComponents(make_host_a_com));
-  std::string result;
-  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
-    browser()->GetSelectedTabContents()->render_view_host(), L"",
-      L"window.domAutomationController.send(document.title)",
-    &result));
-  EXPECT_EQ(result, "Loaded");
-
-  // A web host that does not have permission.
-  ui_test_utils::NavigateToURL(
-      browser(), origin_privileges_index.ReplaceComponents(make_host_b_com));
-  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
-      browser()->GetSelectedTabContents()->render_view_host(), L"",
-      L"window.domAutomationController.send(document.title)",
-      &result));
-  EXPECT_EQ(result, "Image failed to load");
-
-  // A data URL. Data URLs should always be able to load chrome-extension://
-  // resources.
-  std::string file_source;
-  ASSERT_TRUE(file_util::ReadFileToString(
-      test_data_dir_.AppendASCII("origin_privileges")
-                    .AppendASCII("index.html"), &file_source));
-  ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string("data:text/html;charset=utf-8,") + file_source));
-  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
-      browser()->GetSelectedTabContents()->render_view_host(), L"",
-      L"window.domAutomationController.send(document.title)",
-      &result));
-  EXPECT_EQ(result, "Loaded");
-
-  // A different extension. Extensions should always be able to load each
-  // other's resources.
-  ASSERT_TRUE(LoadExtension(test_data_dir_
-    .AppendASCII("origin_privileges").AppendASCII("extension2")));
-  ui_test_utils::NavigateToURL(
-      browser(),
-      GURL("chrome-extension://pbkkcbgdkliohhfaeefcijaghglkahja/index.html"));
-  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
-      browser()->GetSelectedTabContents()->render_view_host(), L"",
-      L"window.domAutomationController.send(document.title)",
-      &result));
-  EXPECT_EQ(result, "Loaded");
-}
-
 // Tests that we can load extension pages into the tab area and they can call
 // extension APIs.
 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, TabContents) {
@@ -622,6 +560,26 @@
                             "This feed contains no entries.");
 }
 
+IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed4) {
+  ASSERT_TRUE(test_server()->Start());
+
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("subscribe_page_action")));
+
+  // subscribe.js shouldn't double-decode the URL passed in. Otherwise feed
+  // links such as http://search.twitter.com/search.atom?lang=en&q=%23chrome
+  // will result in no feed being downloaded because %23 gets decoded to # and
+  // therefore #chrome is not treated as part of the Twitter query. This test
+  // uses an underscore instead of a hash, but the principle is the same. If
+  // we start erroneously double decoding again, the path (and the feed) will
+  // become valid resulting in a failure for this test.
+  NavigateToFeedAndValidate(test_server(), kFeedTripleEncoded, browser(), true,
+                            "Feed for Unknown feed name",
+                            "element 'anchor_0' not found",
+                            "element 'desc_0' not found",
+                            "This feed contains no entries.");
+}
+
 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeedNoLinks) {
   ASSERT_TRUE(test_server()->Start());
 
@@ -797,6 +755,44 @@
   EXPECT_TRUE(result);
 }
 
+#if defined(OS_CHROMEOS)
+// ChromeOS doesn't support NPAPI.
+#define MAYBE_PluginPrivate DISABLED_PluginPrivate
+#elif defined(OS_WIN) || defined(OS_LINUX)
+#define MAYBE_PluginPrivate PluginPrivate
+#else
+// TODO(mpcomplete): http://crbug.com/29900 need cross platform plugin support.
+#define MAYBE_PluginPrivate DISABLED_PluginPrivate
+#endif
+
+// Tests that private extension plugins are only visible to the extension.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, MAYBE_PluginPrivate) {
+  FilePath extension_dir =
+      test_data_dir_.AppendASCII("uitest").AppendASCII("plugins_private");
+
+  ExtensionService* service = browser()->profile()->GetExtensionService();
+  const size_t size_before = service->extensions()->size();
+  ASSERT_TRUE(LoadExtension(extension_dir));
+  EXPECT_EQ(size_before + 1, service->extensions()->size());
+
+  // Load the test page through the extension URL, and the plugin should work.
+  const Extension* extension = service->extensions()->back();
+  ui_test_utils::NavigateToURL(browser(),
+      extension->GetResourceURL("test.html"));
+  TabContents* tab = browser()->GetSelectedTabContents();
+  bool result = false;
+  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+      tab->render_view_host(), L"", L"testPluginWorks()", &result));
+  EXPECT_TRUE(result);
+
+  // Now load it through a file URL. The plugin should not load.
+  ui_test_utils::NavigateToURL(browser(),
+      net::FilePathToFileURL(extension_dir.AppendASCII("test.html")));
+  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+      tab->render_view_host(), L"", L"testPluginWorks()", &result));
+  EXPECT_FALSE(result);
+}
+
 // Used to simulate a click on the first button named 'Options'.
 static const wchar_t* jscript_click_option_button =
     L"(function() { "
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc
index fe893f9..e3e9c12 100644
--- a/chrome/browser/extensions/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/menus/menu_model.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/browser_list.h"
@@ -13,13 +12,13 @@
 #include "chrome/browser/tab_contents/render_view_context_menu.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/base/mock_host_resolver.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
+#include "ui/base/models/menu_model.h"
 #include "webkit/glue/context_menu.h"
 
-using menus::MenuModel;
+using ui::MenuModel;
 using WebKit::WebContextMenuData;
 
 // This test class helps us sidestep platform-specific issues with popping up a
@@ -93,7 +92,7 @@
   // These two functions implement pure virtual methods of
   // RenderViewContextMenu.
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator) {
+                                          ui::Accelerator* accelerator) {
     // None of our commands have accelerators, so always return false.
     return false;
   }
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index 70d4189..3dd09b2 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -96,7 +96,7 @@
 }
 
 bool ExtensionContextMenuModel::GetAcceleratorForCommandId(
-    int command_id, menus::Accelerator* accelerator) {
+    int command_id, ui::Accelerator* accelerator) {
   return false;
 }
 
diff --git a/chrome/browser/extensions/extension_context_menu_model.h b/chrome/browser/extensions/extension_context_menu_model.h
index b1fe0af..34f8e48 100644
--- a/chrome/browser/extensions/extension_context_menu_model.h
+++ b/chrome/browser/extensions/extension_context_menu_model.h
@@ -8,8 +8,8 @@
 
 #include <string>
 
-#include "app/menus/simple_menu_model.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class Browser;
 class Extension;
@@ -20,8 +20,8 @@
 // page actions).
 class ExtensionContextMenuModel
     : public base::RefCounted<ExtensionContextMenuModel>,
-      public menus::SimpleMenuModel,
-      public menus::SimpleMenuModel::Delegate,
+      public ui::SimpleMenuModel,
+      public ui::SimpleMenuModel::Delegate,
       public ExtensionInstallUI::Delegate {
  public:
   // Delegate to handle showing an ExtensionAction popup.
@@ -48,7 +48,7 @@
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
   // ExtensionInstallUI::Delegate overrides.
diff --git a/chrome/browser/extensions/extension_cookies_api.cc b/chrome/browser/extensions/extension_cookies_api.cc
index 0f61602..04d5600 100644
--- a/chrome/browser/extensions/extension_cookies_api.cc
+++ b/chrome/browser/extensions/extension_cookies_api.cc
@@ -312,7 +312,7 @@
       expiration_date = static_cast<double>(expiration_date_int);
     } else {
       EXTENSION_FUNCTION_VALIDATE(
-          expiration_date_value->GetAsReal(&expiration_date));
+          expiration_date_value->GetAsDouble(&expiration_date));
     }
     // Time::FromDoubleT converts double time 0 to empty Time object. So we need
     // to do special handling here.
diff --git a/chrome/browser/extensions/extension_cookies_apitest.cc b/chrome/browser/extensions/extension_cookies_apitest.cc
index 1da9500..427a7ee 100644
--- a/chrome/browser/extensions/extension_cookies_apitest.cc
+++ b/chrome/browser/extensions/extension_cookies_apitest.cc
@@ -4,7 +4,6 @@
 
 #include "base/command_line.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Cookies) {
   ASSERT_TRUE(RunExtensionTest("cookies/api")) << message_;
diff --git a/chrome/browser/extensions/extension_cookies_helpers.cc b/chrome/browser/extensions/extension_cookies_helpers.cc
index 42e2fae..418eb97 100644
--- a/chrome/browser/extensions/extension_cookies_helpers.cc
+++ b/chrome/browser/extensions/extension_cookies_helpers.cc
@@ -59,8 +59,10 @@
   result->SetBoolean(keys::kSecureKey, cookie.IsSecure());
   result->SetBoolean(keys::kHttpOnlyKey, cookie.IsHttpOnly());
   result->SetBoolean(keys::kSessionKey, !cookie.DoesExpire());
-  if (cookie.DoesExpire())
-    result->SetReal(keys::kExpirationDateKey, cookie.ExpiryDate().ToDoubleT());
+  if (cookie.DoesExpire()) {
+    result->SetDouble(keys::kExpirationDateKey,
+                      cookie.ExpiryDate().ToDoubleT());
+  }
   result->SetString(keys::kStoreIdKey, store_id);
 
   return result;
diff --git a/chrome/browser/extensions/extension_cookies_unittest.cc b/chrome/browser/extensions/extension_cookies_unittest.cc
index 2aa34a3..2063c4f 100644
--- a/chrome/browser/extensions/extension_cookies_unittest.cc
+++ b/chrome/browser/extensions/extension_cookies_unittest.cc
@@ -130,7 +130,7 @@
   EXPECT_TRUE(cookie_value1->GetBoolean(keys::kSessionKey, &boolean_value));
   EXPECT_TRUE(boolean_value);
   EXPECT_FALSE(
-      cookie_value1->GetReal(keys::kExpirationDateKey, &double_value));
+      cookie_value1->GetDouble(keys::kExpirationDateKey, &double_value));
   EXPECT_TRUE(cookie_value1->GetString(keys::kStoreIdKey, &string_value));
   EXPECT_EQ("some cookie store", string_value);
 
@@ -144,7 +144,8 @@
   EXPECT_FALSE(boolean_value);
   EXPECT_TRUE(cookie_value2->GetBoolean(keys::kSessionKey, &boolean_value));
   EXPECT_FALSE(boolean_value);
-  EXPECT_TRUE(cookie_value2->GetReal(keys::kExpirationDateKey, &double_value));
+  EXPECT_TRUE(
+      cookie_value2->GetDouble(keys::kExpirationDateKey, &double_value));
   EXPECT_EQ(10000, double_value);
 
   TestingProfile profile;
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
index cb489a1..121bd0f 100644
--- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
+++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,25 +28,21 @@
     return browser()->profile()->GetExtensionProcessManager();
   }
 
-  CrashedExtensionInfoBarDelegate* GetCrashedExtensionInfoBarDelegate(
-      int index) {
+  ConfirmInfoBarDelegate* GetInfoBarDelegate(size_t index) {
     TabContents* current_tab = browser()->GetSelectedTabContents();
-    EXPECT_LT(index, current_tab->infobar_delegate_count());
-    InfoBarDelegate* delegate = current_tab->GetInfoBarDelegateAt(index);
-    return delegate->AsCrashedExtensionInfoBarDelegate();
+    EXPECT_LT(index, current_tab->infobar_count());
+    return current_tab->GetInfoBarDelegateAt(index)->AsConfirmInfoBarDelegate();
   }
 
-  void AcceptCrashedExtensionInfobar(int index) {
-    CrashedExtensionInfoBarDelegate* infobar =
-        GetCrashedExtensionInfoBarDelegate(index);
+  void AcceptInfoBar(size_t index) {
+    ConfirmInfoBarDelegate* infobar = GetInfoBarDelegate(index);
     ASSERT_TRUE(infobar);
     infobar->Accept();
     WaitForExtensionLoad();
   }
 
-  void CancelCrashedExtensionInfobar(int index) {
-    CrashedExtensionInfoBarDelegate* infobar =
-        GetCrashedExtensionInfoBarDelegate(index);
+  void CancelInfoBar(size_t index) {
+    ConfirmInfoBarDelegate* infobar = GetInfoBarDelegate(index);
     ASSERT_TRUE(infobar);
     infobar->Cancel();
   }
@@ -111,25 +107,38 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest, Basic) {
   const size_t size_before = GetExtensionService()->extensions()->size();
+  const size_t crash_size_before =
+      GetExtensionService()->terminated_extensions()->size();
   LoadTestExtension();
   CrashExtension(size_before);
   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
-  AcceptCrashedExtensionInfobar(0);
+  ASSERT_EQ(crash_size_before + 1,
+            GetExtensionService()->terminated_extensions()->size());
+  AcceptInfoBar(0);
 
   SCOPED_TRACE("after clicking the infobar");
   CheckExtensionConsistency(size_before);
+  ASSERT_EQ(crash_size_before,
+            GetExtensionService()->terminated_extensions()->size());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest, CloseAndReload) {
   const size_t size_before = GetExtensionService()->extensions()->size();
+  const size_t crash_size_before =
+      GetExtensionService()->terminated_extensions()->size();
   LoadTestExtension();
   CrashExtension(size_before);
   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
-  CancelCrashedExtensionInfobar(0);
+  ASSERT_EQ(crash_size_before + 1,
+            GetExtensionService()->terminated_extensions()->size());
+
+  CancelInfoBar(0);
   ReloadExtension(first_extension_id_);
 
   SCOPED_TRACE("after reloading");
   CheckExtensionConsistency(size_before);
+  ASSERT_EQ(crash_size_before,
+            GetExtensionService()->terminated_extensions()->size());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest, ReloadIndependently) {
@@ -148,7 +157,7 @@
 
   // The infobar should automatically hide after the extension is successfully
   // reloaded.
-  ASSERT_EQ(0, current_tab->infobar_delegate_count());
+  ASSERT_EQ(0U, current_tab->infobar_count());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
@@ -160,14 +169,14 @@
 
   TabContents* original_tab = browser()->GetSelectedTabContents();
   ASSERT_TRUE(original_tab);
-  ASSERT_EQ(1, original_tab->infobar_delegate_count());
+  ASSERT_EQ(1U, original_tab->infobar_count());
 
   // Open a new tab so the info bar will not be in the current tab.
   browser()->NewTab();
   TabContents* new_current_tab = browser()->GetSelectedTabContents();
   ASSERT_TRUE(new_current_tab);
   ASSERT_NE(new_current_tab, original_tab);
-  ASSERT_EQ(0, new_current_tab->infobar_delegate_count());
+  ASSERT_EQ(0U, new_current_tab->infobar_count());
 
   ReloadExtension(first_extension_id_);
 
@@ -176,7 +185,7 @@
 
   // The infobar should automatically hide after the extension is successfully
   // reloaded.
-  ASSERT_EQ(0, original_tab->infobar_delegate_count());
+  ASSERT_EQ(0U, original_tab->infobar_count());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
@@ -188,13 +197,13 @@
 
   TabContents* current_tab = browser()->GetSelectedTabContents();
   ASSERT_TRUE(current_tab);
-  ASSERT_EQ(1, current_tab->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab->infobar_count());
 
   // Navigate to another page.
   ui_test_utils::NavigateToURL(browser(),
       ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                 FilePath(FILE_PATH_LITERAL("title1.html"))));
-  ASSERT_EQ(1, current_tab->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab->infobar_count());
 
   ReloadExtension(first_extension_id_);
 
@@ -203,7 +212,7 @@
 
   // The infobar should automatically hide after the extension is successfully
   // reloaded.
-  ASSERT_EQ(0, current_tab->infobar_delegate_count());
+  ASSERT_EQ(0U, current_tab->infobar_count());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
@@ -219,11 +228,11 @@
 
   TabContents* current_tab = browser()->GetSelectedTabContents();
   ASSERT_TRUE(current_tab);
-  ASSERT_EQ(1, current_tab->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab->infobar_count());
 
   TabContents* current_tab2 = browser2->GetSelectedTabContents();
   ASSERT_TRUE(current_tab2);
-  ASSERT_EQ(1, current_tab2->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab2->infobar_count());
 
   ReloadExtension(first_extension_id_);
 
@@ -232,8 +241,8 @@
 
   // Both infobars should automatically hide after the extension is successfully
   // reloaded.
-  ASSERT_EQ(0, current_tab->infobar_delegate_count());
-  ASSERT_EQ(0, current_tab2->infobar_delegate_count());
+  ASSERT_EQ(0U, current_tab->infobar_count());
+  ASSERT_EQ(0U, current_tab2->infobar_count());
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
@@ -249,11 +258,11 @@
 
   TabContents* current_tab = browser()->GetSelectedTabContents();
   ASSERT_TRUE(current_tab);
-  ASSERT_EQ(1, current_tab->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab->infobar_count());
 
   TabContents* current_tab2 = browser2->GetSelectedTabContents();
   ASSERT_TRUE(current_tab2);
-  ASSERT_EQ(1, current_tab2->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab2->infobar_count());
 
   // Move second window into first browser so there will be multiple tabs
   // with the info bar for the same extension in one browser.
@@ -261,7 +270,7 @@
       browser2->tabstrip_model()->DetachTabContentsAt(0);
   browser()->tabstrip_model()->AppendTabContents(contents, true);
   current_tab2 = browser()->GetSelectedTabContents();
-  ASSERT_EQ(1, current_tab2->infobar_delegate_count());
+  ASSERT_EQ(1U, current_tab2->infobar_count());
   ASSERT_NE(current_tab2, current_tab);
 
   ReloadExtension(first_extension_id_);
@@ -271,10 +280,10 @@
 
   // Both infobars should automatically hide after the extension is successfully
   // reloaded.
-  ASSERT_EQ(0, current_tab2->infobar_delegate_count());
+  ASSERT_EQ(0U, current_tab2->infobar_count());
   browser()->SelectPreviousTab();
   ASSERT_EQ(current_tab, browser()->GetSelectedTabContents());
-  ASSERT_EQ(0, current_tab->infobar_delegate_count());
+  ASSERT_EQ(0U, current_tab->infobar_count());
 }
 
 // Make sure that when we don't do anything about the crashed extension
@@ -293,7 +302,7 @@
   LoadSecondExtension();
   CrashExtension(size_before);
   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
-  AcceptCrashedExtensionInfobar(0);
+  AcceptInfoBar(0);
 
   SCOPED_TRACE("after clicking the infobar");
   CheckExtensionConsistency(size_before);
@@ -306,7 +315,7 @@
   LoadSecondExtension();
   CrashExtension(size_before + 1);
   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
-  AcceptCrashedExtensionInfobar(0);
+  AcceptInfoBar(0);
 
   SCOPED_TRACE("after clicking the infobar");
   CheckExtensionConsistency(size_before);
@@ -316,22 +325,28 @@
 IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
                        TwoExtensionsCrashBothAtOnce) {
   const size_t size_before = GetExtensionService()->extensions()->size();
+  const size_t crash_size_before =
+      GetExtensionService()->terminated_extensions()->size();
   LoadTestExtension();
   LoadSecondExtension();
   CrashExtension(size_before);
   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
+  ASSERT_EQ(crash_size_before + 1,
+            GetExtensionService()->terminated_extensions()->size());
   CrashExtension(size_before);
   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
+  ASSERT_EQ(crash_size_before + 2,
+            GetExtensionService()->terminated_extensions()->size());
 
   {
     SCOPED_TRACE("first infobar");
-    AcceptCrashedExtensionInfobar(0);
+    AcceptInfoBar(0);
     CheckExtensionConsistency(size_before);
   }
 
   {
     SCOPED_TRACE("second infobar");
-    AcceptCrashedExtensionInfobar(0);
+    AcceptInfoBar(0);
     CheckExtensionConsistency(size_before);
     CheckExtensionConsistency(size_before + 1);
   }
@@ -348,13 +363,13 @@
 
   {
     SCOPED_TRACE("first infobar");
-    AcceptCrashedExtensionInfobar(0);
+    AcceptInfoBar(0);
     CheckExtensionConsistency(size_before);
   }
 
   {
     SCOPED_TRACE("second infobar");
-    AcceptCrashedExtensionInfobar(0);
+    AcceptInfoBar(0);
     CheckExtensionConsistency(size_before);
     CheckExtensionConsistency(size_before + 1);
   }
@@ -384,8 +399,8 @@
   CrashExtension(size_before);
   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
 
-  CancelCrashedExtensionInfobar(0);
-  AcceptCrashedExtensionInfobar(1);
+  CancelInfoBar(0);
+  AcceptInfoBar(1);
 
   SCOPED_TRACE("infobars done");
   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
@@ -407,17 +422,33 @@
     TabContents* current_tab = browser()->GetSelectedTabContents();
     ASSERT_TRUE(current_tab);
     // At the beginning we should have one infobar displayed for each extension.
-    ASSERT_EQ(2, current_tab->infobar_delegate_count());
+    ASSERT_EQ(2U, current_tab->infobar_count());
     ReloadExtension(first_extension_id_);
     // One of the infobars should hide after the extension is reloaded.
-    ASSERT_EQ(1, current_tab->infobar_delegate_count());
+    ASSERT_EQ(1U, current_tab->infobar_count());
     CheckExtensionConsistency(size_before);
   }
 
   {
     SCOPED_TRACE("second: infobar");
-    AcceptCrashedExtensionInfobar(0);
+    AcceptInfoBar(0);
     CheckExtensionConsistency(size_before);
     CheckExtensionConsistency(size_before + 1);
   }
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest, CrashAndUnloadAll) {
+  const size_t size_before = GetExtensionService()->extensions()->size();
+  const size_t crash_size_before =
+      GetExtensionService()->terminated_extensions()->size();
+  LoadTestExtension();
+  LoadSecondExtension();
+  CrashExtension(size_before);
+  ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
+  ASSERT_EQ(crash_size_before + 1,
+            GetExtensionService()->terminated_extensions()->size());
+
+  GetExtensionService()->UnloadAllExtensions();
+  ASSERT_EQ(crash_size_before,
+            GetExtensionService()->terminated_extensions()->size());
+}
diff --git a/chrome/browser/extensions/extension_creator.cc b/chrome/browser/extensions/extension_creator.cc
index 8bd68a2..a211071 100644
--- a/chrome/browser/extensions/extension_creator.cc
+++ b/chrome/browser/extensions/extension_creator.cc
@@ -7,7 +7,6 @@
 #include <vector>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/crypto/rsa_private_key.h"
 #include "base/crypto/signature_creator.h"
 #include "base/file_util.h"
@@ -19,6 +18,7 @@
 #include "chrome/common/extensions/extension_file_util.h"
 #include "chrome/common/zip.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
   const int kRSAKeySize = 1024;
diff --git a/chrome/browser/extensions/extension_data_deleter.cc b/chrome/browser/extensions/extension_data_deleter.cc
index f98ac86..05f51fa 100644
--- a/chrome/browser/extensions/extension_data_deleter.cc
+++ b/chrome/browser/extensions/extension_data_deleter.cc
@@ -10,9 +10,9 @@
 #include "chrome/common/net/url_request_context_getter.h"
 #include "net/base/cookie_monster.h"
 #include "net/base/net_errors.h"
-#include "webkit/database/database_util.h"
 #include "webkit/database/database_tracker.h"
-#include "webkit/fileapi/sandboxed_file_system_context.h"
+#include "webkit/database/database_util.h"
+#include "webkit/fileapi/file_system_context.h"
 
 ExtensionDataDeleter::ExtensionDataDeleter(Profile* profile,
                                            const GURL& extension_url) {
diff --git a/chrome/browser/extensions/extension_data_deleter.h b/chrome/browser/extensions/extension_data_deleter.h
index 960f06f..0382850 100644
--- a/chrome/browser/extensions/extension_data_deleter.h
+++ b/chrome/browser/extensions/extension_data_deleter.h
@@ -16,7 +16,7 @@
 }
 
 namespace fileapi {
-class SandboxedFileSystemContext;
+class FileSystemContext;
 }
 
 class Profile;
@@ -75,7 +75,7 @@
   // Webkit context for accessing the DOM storage helper.
   scoped_refptr<WebKitContext> webkit_context_;
 
-  scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+  scoped_refptr<fileapi::FileSystemContext> file_system_context_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionDataDeleter);
 };
diff --git a/chrome/browser/extensions/extension_devtools_bridge.cc b/chrome/browser/extensions/extension_devtools_bridge.cc
index 8394ad0..7035ded 100644
--- a/chrome/browser/extensions/extension_devtools_bridge.cc
+++ b/chrome/browser/extensions/extension_devtools_bridge.cc
@@ -4,9 +4,11 @@
 
 #include "chrome/browser/extensions/extension_devtools_bridge.h"
 
+#include "base/json/json_writer.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#include "base/values.h"
 #include "chrome/browser/debugger/devtools_manager.h"
 #include "chrome/browser/extensions/extension_devtools_events.h"
 #include "chrome/browser/extensions/extension_devtools_manager.h"
@@ -32,6 +34,22 @@
 ExtensionDevToolsBridge::~ExtensionDevToolsBridge() {
 }
 
+static std::string FormatDevToolsMessage(int seq,
+                                         const std::string& domain,
+                                         const std::string& command,
+                                         DictionaryValue* arguments) {
+
+  DictionaryValue message;
+  message.SetInteger("seq", seq);
+  message.SetString("domain", domain);
+  message.SetString("command", command);
+  message.Set("arguments", arguments);
+
+  std::string json;
+  base::JSONWriter::Write(&message, false, &json);
+  return json;
+}
+
 bool ExtensionDevToolsBridge::RegisterAsDevToolsClientHost() {
   DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
 
@@ -43,11 +61,51 @@
                                    &browser, &tab_strip,
                                    &contents, &tab_index)) {
     DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
+    if (devtools_manager->GetDevToolsClientHostFor(contents->
+            render_view_host()) != NULL)
+      return false;
+
     devtools_manager->RegisterDevToolsClientHostFor(
         contents->render_view_host(), this);
+
+    // Following messages depend on inspector protocol that is not yet
+    // finalized.
+
+    // 1. Set injected script content.
+    DictionaryValue* arguments = new DictionaryValue();
+    arguments->SetString("scriptSource", "'{}'");
     devtools_manager->ForwardToDevToolsAgent(
         this,
-        DevToolsAgentMsg_SetApuAgentEnabled(true));
+        DevToolsAgentMsg_DispatchOnInspectorBackend(
+            FormatDevToolsMessage(0,
+                                  "Inspector",
+                                  "setInjectedScriptSource",
+                                  arguments)));
+
+    // 2. Report front-end is loaded.
+    devtools_manager->ForwardToDevToolsAgent(
+        this,
+        DevToolsAgentMsg_FrontendLoaded());
+
+    // 3. Do not break on exceptions.
+    arguments = new DictionaryValue();
+    arguments->SetInteger("pauseOnExceptionsState", 0);
+    devtools_manager->ForwardToDevToolsAgent(
+        this,
+        DevToolsAgentMsg_DispatchOnInspectorBackend(
+            FormatDevToolsMessage(1,
+                                  "Debugger",
+                                  "setPauseOnExceptionsState",
+                                  arguments)));
+
+    // 4. Start timeline profiler.
+    devtools_manager->ForwardToDevToolsAgent(
+        this,
+        DevToolsAgentMsg_DispatchOnInspectorBackend(
+            FormatDevToolsMessage(2,
+                                  "Inspector",
+                                  "startTimelineProfiler",
+                                  new DictionaryValue())));
     return true;
   }
   return false;
@@ -76,16 +134,23 @@
 
 void ExtensionDevToolsBridge::SendMessageToClient(const IPC::Message& msg) {
   IPC_BEGIN_MESSAGE_MAP(ExtensionDevToolsBridge, msg)
-    IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchToAPU, OnDispatchToAPU);
+    IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
+                        OnDispatchOnInspectorFrontend);
     IPC_MESSAGE_UNHANDLED_ERROR()
   IPC_END_MESSAGE_MAP()
 }
 
-void ExtensionDevToolsBridge::OnDispatchToAPU(const std::string& data) {
+void ExtensionDevToolsBridge::TabReplaced(TabContentsWrapper* new_tab) {
+  DCHECK_EQ(profile_, new_tab->profile());
+  // We don't update the tab id as it needs to remain the same so that we can
+  // properly unregister.
+}
+
+void ExtensionDevToolsBridge::OnDispatchOnInspectorFrontend(
+    const std::string& data) {
   DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
 
   std::string json = base::StringPrintf("[%s]", data.c_str());
   profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
       on_page_event_name_, json, profile_, GURL());
 }
-
diff --git a/chrome/browser/extensions/extension_devtools_bridge.h b/chrome/browser/extensions/extension_devtools_bridge.h
index ad103a2..7e628e5 100644
--- a/chrome/browser/extensions/extension_devtools_bridge.h
+++ b/chrome/browser/extensions/extension_devtools_bridge.h
@@ -31,8 +31,12 @@
   // DevToolsClientHost, called to send a message to this host.
   virtual void SendMessageToClient(const IPC::Message& msg);
 
+  virtual void TabReplaced(TabContentsWrapper* new_tab);
+
  private:
-  void OnDispatchToAPU(const std::string& data);
+  void OnDispatchOnInspectorFrontend(const std::string& data);
+
+  virtual void FrameNavigating(const std::string& url) {}
 
   // ID of the tab we are monitoring.
   int tab_id_;
diff --git a/chrome/browser/extensions/extension_devtools_browsertests.cc b/chrome/browser/extensions/extension_devtools_browsertests.cc
index c29a4ca..ce8b8d3 100644
--- a/chrome/browser/extensions/extension_devtools_browsertests.cc
+++ b/chrome/browser/extensions/extension_devtools_browsertests.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/renderer_host/site_instance.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/devtools_messages.h"
 #include "chrome/common/url_constants.h"
@@ -82,7 +81,7 @@
   // Test onPageEvent event.
   result = false;
 
-  DevToolsClientMsg_DispatchToAPU pageEventMessage("");
+  DevToolsClientMsg_DispatchOnInspectorFrontend pageEventMessage("");
   devtools_client_host->SendMessageToClient(pageEventMessage);
   ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
       host->render_view_host(), L"", L"testReceivePageEvent()", &result));
diff --git a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc
index 28e0709..7005adb 100644
--- a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc
+++ b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -19,6 +18,9 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// ExtensionDisabledDialogDelegate --------------------------------------------
 
 class ExtensionDisabledDialogDelegate
     : public ExtensionInstallUI::Delegate,
@@ -26,28 +28,16 @@
  public:
   ExtensionDisabledDialogDelegate(Profile* profile,
                                   ExtensionService* service,
-                                  const Extension* extension)
-        : service_(service), extension_(extension) {
-    AddRef();  // Balanced in Proceed or Abort.
-
-    install_ui_.reset(new ExtensionInstallUI(profile));
-    install_ui_->ConfirmInstall(this, extension_);
-  }
-
-  // Overridden from ExtensionInstallUI::Delegate:
-  virtual void InstallUIProceed() {
-    service_->GrantPermissionsAndEnableExtension(extension_);
-    Release();
-  }
-  virtual void InstallUIAbort() {
-    // Do nothing. The extension will remain disabled.
-    Release();
-  }
+                                  const Extension* extension);
 
  private:
   friend class base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate>;
 
-  virtual ~ExtensionDisabledDialogDelegate() {}
+  virtual ~ExtensionDisabledDialogDelegate();
+
+  // ExtensionInstallUI::Delegate:
+  virtual void InstallUIProceed();
+  virtual void InstallUIAbort();
 
   // The UI for showing the install dialog when enabling.
   scoped_ptr<ExtensionInstallUI> install_ui_;
@@ -56,83 +46,129 @@
   const Extension* extension_;
 };
 
-class ExtensionDisabledInfobarDelegate
-    : public ConfirmInfoBarDelegate,
-      public NotificationObserver {
+ExtensionDisabledDialogDelegate::ExtensionDisabledDialogDelegate(
+    Profile* profile,
+    ExtensionService* service,
+    const Extension* extension)
+    : service_(service), extension_(extension) {
+  AddRef();  // Balanced in Proceed or Abort.
+
+  install_ui_.reset(new ExtensionInstallUI(profile));
+  install_ui_->ConfirmInstall(this, extension_);
+}
+
+ExtensionDisabledDialogDelegate::~ExtensionDisabledDialogDelegate() {
+}
+
+void ExtensionDisabledDialogDelegate::InstallUIProceed() {
+  service_->GrantPermissionsAndEnableExtension(extension_);
+  Release();
+}
+
+void ExtensionDisabledDialogDelegate::InstallUIAbort() {
+  // Do nothing. The extension will remain disabled.
+  Release();
+}
+
+
+// ExtensionDisabledInfobarDelegate -------------------------------------------
+
+class ExtensionDisabledInfobarDelegate : public ConfirmInfoBarDelegate,
+                                         public NotificationObserver {
  public:
   ExtensionDisabledInfobarDelegate(TabContents* tab_contents,
                                    ExtensionService* service,
-                                   const Extension* extension)
-      : ConfirmInfoBarDelegate(tab_contents),
-        tab_contents_(tab_contents),
-        service_(service),
-        extension_(extension) {
-    // The user might re-enable the extension in other ways, so watch for that.
-    registrar_.Add(this, NotificationType::EXTENSION_LOADED,
-                   Source<Profile>(service->profile()));
-    registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
-                   Source<Profile>(service->profile()));
-  }
-  virtual ~ExtensionDisabledInfobarDelegate() {
-  }
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringFUTF16(extension_->is_app() ?
-        IDS_APP_DISABLED_INFOBAR_LABEL : IDS_EXTENSION_DISABLED_INFOBAR_LABEL,
-        UTF8ToUTF16(extension_->name()));
-  }
-  virtual SkBitmap* GetIcon() const {
-    return NULL;
-  }
-  virtual int GetButtons() const {
-    return BUTTON_OK;
-  }
-  virtual string16 GetButtonLabel(
-      ConfirmInfoBarDelegate::InfoBarButton button) const {
-    return l10n_util::GetStringUTF16(
-        IDS_EXTENSION_DISABLED_INFOBAR_ENABLE_BUTTON);
-  }
-  virtual bool Accept() {
-    // This object manages its own lifetime.
-    new ExtensionDisabledDialogDelegate(tab_contents_->profile(),
-                                        service_, extension_);
-    return true;
-  }
-  virtual void InfoBarClosed() {
-    delete this;
-  }
-
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    // TODO(mpcomplete): RemoveInfoBar doesn't seem to always result in us
-    // getting deleted.
-    const Extension* extension = NULL;
-    switch (type.value) {
-      case NotificationType::EXTENSION_LOADED:
-        extension = Details<const Extension>(details).ptr();
-        break;
-      case NotificationType::EXTENSION_UNLOADED: {
-        UnloadedExtensionInfo* info =
-            Details<UnloadedExtensionInfo>(details).ptr();
-        if (info->reason == UnloadedExtensionInfo::DISABLE)
-          extension = info->extension;
-        break;
-      }
-      default:
-        NOTREACHED();
-        return;
-    }
-    if (extension == extension_)
-      tab_contents_->RemoveInfoBar(this);
-  }
+                                   const Extension* extension);
 
  private:
+  virtual ~ExtensionDisabledInfobarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+
+  // NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
   NotificationRegistrar registrar_;
   TabContents* tab_contents_;
   ExtensionService* service_;
   const Extension* extension_;
 };
 
+ExtensionDisabledInfobarDelegate::ExtensionDisabledInfobarDelegate(
+    TabContents* tab_contents,
+    ExtensionService* service,
+    const Extension* extension)
+    : ConfirmInfoBarDelegate(tab_contents),
+      tab_contents_(tab_contents),
+      service_(service),
+      extension_(extension) {
+  // The user might re-enable the extension in other ways, so watch for that.
+  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
+                 Source<Profile>(service->profile()));
+  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+                 Source<Profile>(service->profile()));
+}
+
+ExtensionDisabledInfobarDelegate::~ExtensionDisabledInfobarDelegate() {
+}
+
+void ExtensionDisabledInfobarDelegate::InfoBarClosed() {
+  delete this;
+}
+
+string16 ExtensionDisabledInfobarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(extension_->is_app() ?
+      IDS_APP_DISABLED_INFOBAR_LABEL : IDS_EXTENSION_DISABLED_INFOBAR_LABEL,
+      UTF8ToUTF16(extension_->name()));
+}
+
+int ExtensionDisabledInfobarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
+
+string16 ExtensionDisabledInfobarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(
+      IDS_EXTENSION_DISABLED_INFOBAR_ENABLE_BUTTON);
+}
+
+bool ExtensionDisabledInfobarDelegate::Accept() {
+  // This object manages its own lifetime.
+  new ExtensionDisabledDialogDelegate(tab_contents_->profile(), service_,
+                                      extension_);
+  return true;
+}
+
+void ExtensionDisabledInfobarDelegate::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  // TODO(mpcomplete): RemoveInfoBar doesn't seem to always result in us getting
+  // deleted.
+  const Extension* extension;
+  if (type.value == NotificationType::EXTENSION_LOADED) {
+    extension = Details<const Extension>(details).ptr();
+  } else {
+    DCHECK_EQ(NotificationType::EXTENSION_UNLOADED, type.value);
+    UnloadedExtensionInfo* info = Details<UnloadedExtensionInfo>(details).ptr();
+    extension = (info->reason == UnloadedExtensionInfo::DISABLE) ?
+        info->extension : NULL;
+  }
+  if (extension == extension_)
+    tab_contents_->RemoveInfoBar(this);
+}
+
+
+// Globals --------------------------------------------------------------------
+
 void ShowExtensionDisabledUI(ExtensionService* service, Profile* profile,
                              const Extension* extension) {
   Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc
deleted file mode 100644
index 97889d7..0000000
--- a/chrome/browser/extensions/extension_dom_ui.cc
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_dom_ui.h"
-
-#include <set>
-#include <vector>
-
-#include "net/base/file_stream.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/bindings_policy.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_icon_set.h"
-#include "chrome/common/extensions/extension_resource.h"
-#include "chrome/common/page_transition_types.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/favicon_size.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-// De-dupes the items in |list|. Assumes the values are strings.
-void CleanUpDuplicates(ListValue* list) {
-  std::set<std::string> seen_values;
-
-  // Loop backwards as we may be removing items.
-  for (size_t i = list->GetSize() - 1; (i + 1) > 0; --i) {
-    std::string value;
-    if (!list->GetString(i, &value)) {
-      NOTREACHED();
-      continue;
-    }
-
-    if (seen_values.find(value) == seen_values.end())
-      seen_values.insert(value);
-    else
-      list->Remove(i, NULL);
-  }
-}
-
-// Helper class that is used to track the loading of the favicon of an
-// extension.
-class ExtensionDOMUIImageLoadingTracker : public ImageLoadingTracker::Observer {
- public:
-  ExtensionDOMUIImageLoadingTracker(Profile* profile,
-                                    FaviconService::GetFaviconRequest* request,
-                                    const GURL& page_url)
-      : ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
-        request_(request),
-        extension_(NULL) {
-    // Even when the extensions service is enabled by default, it's still
-    // disabled in incognito mode.
-    ExtensionService* service = profile->GetExtensionService();
-    if (service)
-      extension_ = service->GetExtensionByURL(page_url);
-  }
-
-  void Init() {
-    if (extension_) {
-      ExtensionResource icon_resource =
-          extension_->GetIconResource(Extension::EXTENSION_ICON_BITTY,
-                                      ExtensionIconSet::MATCH_EXACTLY);
-
-      tracker_.LoadImage(extension_, icon_resource,
-                         gfx::Size(kFavIconSize, kFavIconSize),
-                         ImageLoadingTracker::DONT_CACHE);
-    } else {
-      ForwardResult(NULL);
-    }
-  }
-
-  virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
-                             int index) {
-    if (image) {
-      std::vector<unsigned char> image_data;
-      if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_data)) {
-        NOTREACHED() << "Could not encode extension favicon";
-      }
-      ForwardResult(RefCountedBytes::TakeVector(&image_data));
-    } else {
-      ForwardResult(NULL);
-    }
-  }
-
- private:
-  ~ExtensionDOMUIImageLoadingTracker() {}
-
-  // Forwards the result on the request. If no favicon was available then
-  // |icon_data| may be backed by NULL. Once the result has been forwarded the
-  // instance is deleted.
-  void ForwardResult(scoped_refptr<RefCountedMemory> icon_data) {
-    bool know_icon = icon_data.get() != NULL && icon_data->size() > 0;
-    request_->ForwardResultAsync(
-        FaviconService::FaviconDataCallback::TupleType(request_->handle(),
-            know_icon, icon_data, false, GURL()));
-    delete this;
-  }
-
-  ImageLoadingTracker tracker_;
-  scoped_refptr<FaviconService::GetFaviconRequest> request_;
-  const Extension* extension_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionDOMUIImageLoadingTracker);
-};
-
-}  // namespace
-
-const char ExtensionDOMUI::kExtensionURLOverrides[] =
-    "extensions.chrome_url_overrides";
-
-ExtensionDOMUI::ExtensionDOMUI(TabContents* tab_contents, const GURL& url)
-    : DOMUI(tab_contents),
-      url_(url) {
-  ExtensionService* service = tab_contents->profile()->GetExtensionService();
-  const Extension* extension = service->GetExtensionByURL(url);
-  if (!extension)
-    extension = service->GetExtensionByWebExtent(url);
-  DCHECK(extension);
-  // Only hide the url for internal pages (e.g. chrome-extension or packaged
-  // component apps like bookmark manager.
-  should_hide_url_ = !extension->is_hosted_app();
-
-  bindings_ = BindingsPolicy::EXTENSION;
-  // Bind externalHost to Extension DOMUI loaded in Chrome Frame.
-  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
-  if (browser_command_line.HasSwitch(switches::kChromeFrame))
-    bindings_ |= BindingsPolicy::EXTERNAL_HOST;
-  // For chrome:// overrides, some of the defaults are a little different.
-  GURL effective_url = tab_contents->GetURL();
-  if (effective_url.SchemeIs(chrome::kChromeUIScheme) &&
-      effective_url.host() == chrome::kChromeUINewTabHost) {
-    focus_location_bar_by_default_ = true;
-  }
-}
-
-ExtensionDOMUI::~ExtensionDOMUI() {}
-
-void ExtensionDOMUI::ResetExtensionFunctionDispatcher(
-    RenderViewHost* render_view_host) {
-  // TODO(jcivelli): http://crbug.com/60608 we should get the URL out of the
-  //                 active entry of the navigation controller.
-  extension_function_dispatcher_.reset(
-      ExtensionFunctionDispatcher::Create(render_view_host, this, url_));
-  DCHECK(extension_function_dispatcher_.get());
-}
-
-void ExtensionDOMUI::ResetExtensionBookmarkManagerEventRouter() {
-  // Hack: A few things we specialize just for the bookmark manager.
-  if (extension_function_dispatcher_->extension_id() ==
-      extension_misc::kBookmarkManagerId) {
-    extension_bookmark_manager_event_router_.reset(
-        new ExtensionBookmarkManagerEventRouter(GetProfile(), tab_contents()));
-
-    link_transition_type_ = PageTransition::AUTO_BOOKMARK;
-  }
-}
-
-void ExtensionDOMUI::RenderViewCreated(RenderViewHost* render_view_host) {
-  ResetExtensionFunctionDispatcher(render_view_host);
-  ResetExtensionBookmarkManagerEventRouter();
-}
-
-void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) {
-  ResetExtensionFunctionDispatcher(render_view_host);
-  ResetExtensionBookmarkManagerEventRouter();
-}
-
-void ExtensionDOMUI::ProcessDOMUIMessage(
-    const ViewHostMsg_DomMessage_Params& params) {
-  extension_function_dispatcher_->HandleRequest(params);
-}
-
-Browser* ExtensionDOMUI::GetBrowser() const {
-  TabContents* contents = tab_contents();
-  TabContentsIterator tab_iterator;
-  for (; !tab_iterator.done(); ++tab_iterator) {
-    if (contents == *tab_iterator)
-      return tab_iterator.browser();
-  }
-
-  return NULL;
-}
-
-TabContents* ExtensionDOMUI::associated_tab_contents() const {
-  return tab_contents();
-}
-
-ExtensionBookmarkManagerEventRouter*
-ExtensionDOMUI::extension_bookmark_manager_event_router() {
-  return extension_bookmark_manager_event_router_.get();
-}
-
-gfx::NativeWindow ExtensionDOMUI::GetCustomFrameNativeWindow() {
-  if (GetBrowser())
-    return NULL;
-
-  // If there was no browser associated with the function dispatcher delegate,
-  // then this DOMUI may be hosted in an ExternalTabContainer, and a framing
-  // window will be accessible through the tab_contents.
-  TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
-  if (tab_contents_delegate)
-    return tab_contents_delegate->GetFrameNativeWindow();
-  else
-    return NULL;
-}
-
-gfx::NativeView ExtensionDOMUI::GetNativeViewOfHost() {
-  return tab_contents()->GetRenderWidgetHostView()->GetNativeView();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// chrome:// URL overrides
-
-// static
-void ExtensionDOMUI::RegisterUserPrefs(PrefService* prefs) {
-  prefs->RegisterDictionaryPref(kExtensionURLOverrides);
-}
-
-// static
-bool ExtensionDOMUI::HandleChromeURLOverride(GURL* url, Profile* profile) {
-  if (!url->SchemeIs(chrome::kChromeUIScheme))
-    return false;
-
-  const DictionaryValue* overrides =
-      profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
-  std::string page = url->host();
-  ListValue* url_list;
-  if (!overrides || !overrides->GetList(page, &url_list))
-    return false;
-
-  ExtensionService* service = profile->GetExtensionService();
-
-  size_t i = 0;
-  while (i < url_list->GetSize()) {
-    Value* val = NULL;
-    url_list->Get(i, &val);
-
-    // Verify that the override value is good.  If not, unregister it and find
-    // the next one.
-    std::string override;
-    if (!val->GetAsString(&override)) {
-      NOTREACHED();
-      UnregisterChromeURLOverride(page, profile, val);
-      continue;
-    }
-    GURL extension_url(override);
-    if (!extension_url.is_valid()) {
-      NOTREACHED();
-      UnregisterChromeURLOverride(page, profile, val);
-      continue;
-    }
-
-    // Verify that the extension that's being referred to actually exists.
-    const Extension* extension = service->GetExtensionByURL(extension_url);
-    if (!extension) {
-      // This can currently happen if you use --load-extension one run, and
-      // then don't use it the next.  It could also happen if an extension
-      // were deleted directly from the filesystem, etc.
-      LOG(WARNING) << "chrome URL override present for non-existant extension";
-      UnregisterChromeURLOverride(page, profile, val);
-      continue;
-    }
-
-    // We can't handle chrome-extension URLs in incognito mode unless the
-    // extension uses split mode.
-    bool incognito_override_allowed =
-        extension->incognito_split_mode() &&
-        service->IsIncognitoEnabled(extension);
-    if (profile->IsOffTheRecord() && !incognito_override_allowed) {
-      ++i;
-      continue;
-    }
-
-    *url = extension_url;
-    return true;
-  }
-  return false;
-}
-
-// static
-void ExtensionDOMUI::RegisterChromeURLOverrides(
-    Profile* profile, const Extension::URLOverrideMap& overrides) {
-  if (overrides.empty())
-    return;
-
-  PrefService* prefs = profile->GetPrefs();
-  DictionaryValue* all_overrides =
-      prefs->GetMutableDictionary(kExtensionURLOverrides);
-
-  // For each override provided by the extension, add it to the front of
-  // the override list if it's not already in the list.
-  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
-  for (; iter != overrides.end(); ++iter) {
-    const std::string& key = iter->first;
-    ListValue* page_overrides;
-    if (!all_overrides->GetList(key, &page_overrides)) {
-      page_overrides = new ListValue();
-      all_overrides->Set(key, page_overrides);
-    } else {
-      CleanUpDuplicates(page_overrides);
-
-      // Verify that the override isn't already in the list.
-      ListValue::iterator i = page_overrides->begin();
-      for (; i != page_overrides->end(); ++i) {
-        std::string override_val;
-        if (!(*i)->GetAsString(&override_val)) {
-          NOTREACHED();
-          continue;
-        }
-        if (override_val == iter->second.spec())
-          break;
-      }
-      // This value is already in the list, leave it alone.
-      if (i != page_overrides->end())
-        continue;
-    }
-    // Insert the override at the front of the list.  Last registered override
-    // wins.
-    page_overrides->Insert(0, new StringValue(iter->second.spec()));
-  }
-}
-
-// static
-void ExtensionDOMUI::UnregisterAndReplaceOverride(const std::string& page,
-    Profile* profile, ListValue* list, Value* override) {
-  int index = list->Remove(*override);
-  if (index == 0) {
-    // This is the active override, so we need to find all existing
-    // tabs for this override and get them to reload the original URL.
-    for (TabContentsIterator iterator; !iterator.done(); ++iterator) {
-      TabContents* tab = *iterator;
-      if (tab->profile() != profile)
-        continue;
-
-      GURL url = tab->GetURL();
-      if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page)
-        continue;
-
-      // Don't use Reload() since |url| isn't the same as the internal URL
-      // that NavigationController has.
-      tab->controller().LoadURL(url, url, PageTransition::RELOAD);
-    }
-  }
-}
-
-// static
-void ExtensionDOMUI::UnregisterChromeURLOverride(const std::string& page,
-    Profile* profile, Value* override) {
-  if (!override)
-    return;
-  PrefService* prefs = profile->GetPrefs();
-  DictionaryValue* all_overrides =
-      prefs->GetMutableDictionary(kExtensionURLOverrides);
-  ListValue* page_overrides;
-  if (!all_overrides->GetList(page, &page_overrides)) {
-    // If it's being unregistered, it should already be in the list.
-    NOTREACHED();
-    return;
-  } else {
-    UnregisterAndReplaceOverride(page, profile, page_overrides, override);
-  }
-}
-
-// static
-void ExtensionDOMUI::UnregisterChromeURLOverrides(
-    Profile* profile, const Extension::URLOverrideMap& overrides) {
-  if (overrides.empty())
-    return;
-  PrefService* prefs = profile->GetPrefs();
-  DictionaryValue* all_overrides =
-      prefs->GetMutableDictionary(kExtensionURLOverrides);
-  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
-  for (; iter != overrides.end(); ++iter) {
-    const std::string& page = iter->first;
-    ListValue* page_overrides;
-    if (!all_overrides->GetList(page, &page_overrides)) {
-      // If it's being unregistered, it should already be in the list.
-      NOTREACHED();
-      continue;
-    } else {
-      StringValue override(iter->second.spec());
-      UnregisterAndReplaceOverride(iter->first, profile,
-                                   page_overrides, &override);
-    }
-  }
-}
-
-// static
-void ExtensionDOMUI::GetFaviconForURL(Profile* profile,
-    FaviconService::GetFaviconRequest* request, const GURL& page_url) {
-  // tracker deletes itself when done.
-  ExtensionDOMUIImageLoadingTracker* tracker =
-      new ExtensionDOMUIImageLoadingTracker(profile, request, page_url);
-  tracker->Init();
-}
diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h
deleted file mode 100644
index ea59b41..0000000
--- a/chrome/browser/extensions/extension_dom_ui.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_DOM_UI_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_DOM_UI_H_
-#pragma once
-
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
-#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
-#include "chrome/browser/extensions/extension_function_dispatcher.h"
-#include "chrome/browser/favicon_service.h"
-#include "chrome/common/extensions/extension.h"
-
-class GURL;
-class ListValue;
-class PrefService;
-class Profile;
-class RenderViewHost;
-class TabContents;
-struct ViewHostMsg_DomMessage_Params;
-
-// This class implements DOMUI for extensions and allows extensions to put UI in
-// the main tab contents area. For example, each extension can specify an
-// "options_page", and that page is displayed in the tab contents area and is
-// hosted by this class.
-class ExtensionDOMUI
-    : public DOMUI,
-      public ExtensionFunctionDispatcher::Delegate {
- public:
-  static const char kExtensionURLOverrides[];
-
-  explicit ExtensionDOMUI(TabContents* tab_contents, const GURL& url);
-
-  virtual ~ExtensionDOMUI();
-
-  ExtensionFunctionDispatcher* extension_function_dispatcher() const {
-    return extension_function_dispatcher_.get();
-  }
-
-  // DOMUI
-  virtual void RenderViewCreated(RenderViewHost* render_view_host);
-  virtual void RenderViewReused(RenderViewHost* render_view_host);
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
-
-  // ExtensionFunctionDispatcher::Delegate
-  virtual Browser* GetBrowser() const;
-  virtual gfx::NativeView GetNativeViewOfHost();
-  virtual gfx::NativeWindow GetCustomFrameNativeWindow();
-  virtual TabContents* associated_tab_contents() const;
-
-  virtual ExtensionBookmarkManagerEventRouter*
-      extension_bookmark_manager_event_router();
-
-  // BrowserURLHandler
-  static bool HandleChromeURLOverride(GURL* url, Profile* profile);
-
-  // Register and unregister a dictionary of one or more overrides.
-  // Page names are the keys, and chrome-extension: URLs are the values.
-  // (e.g. { "newtab": "chrome-extension://<id>/my_new_tab.html" }
-  static void RegisterChromeURLOverrides(Profile* profile,
-      const Extension::URLOverrideMap& overrides);
-  static void UnregisterChromeURLOverrides(Profile* profile,
-      const Extension::URLOverrideMap& overrides);
-  static void UnregisterChromeURLOverride(const std::string& page,
-                                          Profile* profile,
-                                          Value* override);
-
-  // Called from BrowserPrefs
-  static void RegisterUserPrefs(PrefService* prefs);
-
-  // Get the favicon for the extension by getting an icon from the manifest.
-  static void GetFaviconForURL(Profile* profile,
-                               FaviconService::GetFaviconRequest* request,
-                               const GURL& page_url);
-
- private:
-  // Unregister the specified override, and if it's the currently active one,
-  // ensure that something takes its place.
-  static void UnregisterAndReplaceOverride(const std::string& page,
-                                           Profile* profile,
-                                           ListValue* list,
-                                           Value* override);
-
-  // When the RenderViewHost changes (RenderViewCreated and RenderViewReused),
-  // we need to reset the ExtensionFunctionDispatcher so it's talking to the
-  // right one, as well as being linked to the correct URL.
-  void ResetExtensionFunctionDispatcher(RenderViewHost* render_view_host);
-
-  void ResetExtensionBookmarkManagerEventRouter();
-
-  scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
-
-  // TODO(aa): This seems out of place. Why is it not with the event routers for
-  // the other extension APIs?
-  scoped_ptr<ExtensionBookmarkManagerEventRouter>
-      extension_bookmark_manager_event_router_;
-
-  // The URL this DOMUI was created for.
-  GURL url_;
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_DOM_UI_H_
diff --git a/chrome/browser/extensions/extension_event_router.cc b/chrome/browser/extensions/extension_event_router.cc
index 0b4f799..13532d7 100644
--- a/chrome/browser/extensions/extension_event_router.cc
+++ b/chrome/browser/extensions/extension_event_router.cc
@@ -9,8 +9,9 @@
 #include "chrome/browser/extensions/extension_devtools_manager.h"
 #include "chrome/browser/extensions/extension_processes_api.h"
 #include "chrome/browser/extensions/extension_processes_api_constants.h"
-#include "chrome/browser/extensions/extension_tabs_module.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/extensions/extension_webrequest_api.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/common/extensions/extension.h"
@@ -108,6 +109,8 @@
       " PID=" << process->id() << " extension=" << extension_id <<
       " event=" << event_name;
   listeners_[event_name].erase(listener);
+  // Note: extension_id may point to data in the now-deleted listeners_ object.
+  // Do not use.
 
   if (extension_devtools_manager_.get())
     extension_devtools_manager_->RemoveEventListener(event_name, process->id());
@@ -116,6 +119,9 @@
   // exits), then we let the TaskManager know that it has one fewer listener.
   if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0)
     ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved();
+
+  ExtensionWebRequestEventRouter::RemoveEventListenerOnUIThread(
+      listener.extension_id, event_name);
 }
 
 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) {
diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc
index 054c882..9f0d065 100644
--- a/chrome/browser/extensions/extension_function.cc
+++ b/chrome/browser/extensions/extension_function.cc
@@ -40,7 +40,7 @@
 
 void AsyncExtensionFunction::SetArgs(const ListValue* args) {
   DCHECK(!args_.get());  // Should only be called once.
-  args_.reset(static_cast<ListValue*>(args->DeepCopy()));
+  args_.reset(args->DeepCopy());
 }
 
 const std::string AsyncExtensionFunction::GetResult() {
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 3c98cf3..3d6a965 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/dom_ui/web_ui_favicon_source.h"
 #include "chrome/browser/external_protocol_handler.h"
 #include "chrome/browser/extensions/execute_code_in_tab_function.h"
 #include "chrome/browser/extensions/extension_accessibility_api.h"
@@ -24,22 +24,17 @@
 #include "chrome/browser/extensions/extension_clipboard_api.h"
 #include "chrome/browser/extensions/extension_context_menu_api.h"
 #include "chrome/browser/extensions/extension_cookies_api.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
 #include "chrome/browser/extensions/extension_function.h"
 #include "chrome/browser/extensions/extension_history_api.h"
 #include "chrome/browser/extensions/extension_idle_api.h"
 #include "chrome/browser/extensions/extension_i18n_api.h"
 #include "chrome/browser/extensions/extension_infobar_module.h"
-#if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/extensions/extension_input_api.h"
-#endif
 #include "chrome/browser/extensions/extension_management_api.h"
 #include "chrome/browser/extensions/extension_message_service.h"
 #include "chrome/browser/extensions/extension_metrics_module.h"
 #include "chrome/browser/extensions/extension_module.h"
 #include "chrome/browser/extensions/extension_omnibox_api.h"
 #include "chrome/browser/extensions/extension_page_actions_module.h"
-#include "chrome/browser/extensions/extension_popup_api.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_processes_api.h"
 #include "chrome/browser/extensions/extension_proxy_api.h"
@@ -48,6 +43,8 @@
 #include "chrome/browser/extensions/extension_tabs_module.h"
 #include "chrome/browser/extensions/extension_test_api.h"
 #include "chrome/browser/extensions/extension_tts_api.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
+#include "chrome/browser/extensions/extension_webrequest_api.h"
 #include "chrome/browser/extensions/extension_webstore_private_api.h"
 #include "chrome/browser/extensions/extensions_quota_service.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -62,6 +59,9 @@
 #include "chrome/common/url_constants.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
+#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/extensions/extension_input_api.h"
+#endif
 
 // FactoryRegistry -------------------------------------------------------------
 
@@ -192,13 +192,12 @@
   // I18N.
   RegisterFunction<GetAcceptLanguagesFunction>();
 
-  // Popup API.
-  RegisterFunction<PopupShowFunction>();
-
   // Processes.
   RegisterFunction<GetProcessIdForTabFunction>();
 
   // Metrics.
+  RegisterFunction<MetricsGetEnabledFunction>();
+  RegisterFunction<MetricsSetEnabledFunction>();
   RegisterFunction<MetricsRecordUserActionFunction>();
   RegisterFunction<MetricsRecordValueFunction>();
   RegisterFunction<MetricsRecordPercentageFunction>();
@@ -260,6 +259,8 @@
 
   // Proxies.
   RegisterFunction<UseCustomProxySettingsFunction>();
+  RegisterFunction<RemoveCustomProxySettingsFunction>();
+  RegisterFunction<GetCurrentProxySettingsFunction>();
 
   // Sidebar.
   RegisterFunction<CollapseSidebarFunction>();
@@ -294,6 +295,9 @@
   RegisterFunction<PromptBrowserLoginFunction>();
   RegisterFunction<BeginInstallFunction>();
   RegisterFunction<CompleteInstallFunction>();
+
+  // WebRequest.
+  RegisterFunction<WebRequestAddEventListener>();
 }
 
 void FactoryRegistry::GetAllNames(std::vector<std::string>* names) {
@@ -384,15 +388,11 @@
                                 render_view_host->process()->id());
 
   // If the extension has permission to load chrome://favicon/ resources we need
-  // to make sure that the DOMUIFavIconSource is registered with the
+  // to make sure that the WebUIFavIconSource is registered with the
   // ChromeURLDataManager.
   if (extension->HasHostPermission(GURL(chrome::kChromeUIFavIconURL))) {
-    DOMUIFavIconSource* favicon_source = new DOMUIFavIconSource(profile_);
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                          &ChromeURLDataManager::AddDataSource,
-                          make_scoped_refptr(favicon_source)));
+    WebUIFavIconSource* favicon_source = new WebUIFavIconSource(profile_);
+    profile_->GetChromeURLDataManager()->AddDataSource(favicon_source);
   }
 
   // Update the extension permissions. Doing this each time we create an EFD
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index 9969b1f..e87489b 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,8 +10,8 @@
 #include <vector>
 
 #include "base/ref_counted.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Browser;
 class Extension;
@@ -34,19 +34,12 @@
    public:
     // Returns the browser that this delegate is associated with, if any.
     // Returns NULL otherwise.
-    virtual Browser* GetBrowser() const = 0;
+    virtual Browser* GetBrowser() = 0;
 
     // Returns the native view for this extension view, if any. This may be NULL
     // if the view is not visible.
     virtual gfx::NativeView GetNativeViewOfHost() = 0;
 
-    // Typically, the window is assumed to be the window associated with the
-    // result of GetBrowser(). Implementations may override this behavior with
-    // this method.
-    virtual gfx::NativeWindow GetCustomFrameNativeWindow() {
-      return NULL;
-    }
-
     // Asks the delegate for any relevant TabContents associated with this
     // context. For example, the TabContents in which an infobar or
     // chrome-extension://<id> URL are being shown. Callers must check for a
diff --git a/chrome/browser/extensions/extension_geolocation_apitest.cc b/chrome/browser/extensions/extension_geolocation_apitest.cc
index de67c89..1ce6570 100644
--- a/chrome/browser/extensions/extension_geolocation_apitest.cc
+++ b/chrome/browser/extensions/extension_geolocation_apitest.cc
@@ -5,19 +5,34 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/geolocation/location_arbitrator.h"
 #include "chrome/browser/geolocation/mock_location_provider.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h"
 
 class GeolocationApiTest : public ExtensionApiTest {
-public:
-  // InProcessBrowserTest
-  void SetUpInProcessBrowserTestFixture() {
-    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
-    GeolocationArbitrator::SetProviderFactoryForTest(
-        &NewAutoSuccessMockLocationProvider);
+ public:
+  GeolocationApiTest()
+      : dependency_factory_(
+          new GeolocationArbitratorDependencyFactoryWithLocationProvider(
+              &NewAutoSuccessMockLocationProvider)) {
   }
+
+  // InProcessBrowserTest
+  virtual void SetUpInProcessBrowserTestFixture() {
+    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
+    GeolocationArbitrator::SetDependencyFactoryForTest(
+        dependency_factory_.get());
+  }
+
+  // InProcessBrowserTest
+  virtual void TearDownInProcessBrowserTestFixture() {
+    GeolocationArbitrator::SetDependencyFactoryForTest(NULL);
+  }
+
+ private:
+  scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory_;
 };
 
-IN_PROC_BROWSER_TEST_F(GeolocationApiTest, FLAKY_ExtensionGeolocationAccessFail) {
+IN_PROC_BROWSER_TEST_F(GeolocationApiTest,
+                       FLAKY_ExtensionGeolocationAccessFail) {
   // Test that geolocation cannot be accessed from extension without permission.
   ASSERT_TRUE(RunExtensionTest("geolocation/no_permission")) << message_;
 }
diff --git a/chrome/browser/extensions/extension_history_api.cc b/chrome/browser/extensions/extension_history_api.cc
index 5ff98e3..65bef38 100644
--- a/chrome/browser/extensions/extension_history_api.cc
+++ b/chrome/browser/extensions/extension_history_api.cc
@@ -31,7 +31,8 @@
   value->SetString(keys::kIdKey, base::Int64ToString(row.id()));
   value->SetString(keys::kUrlKey, row.url().spec());
   value->SetString(keys::kTitleKey, row.title());
-  value->SetReal(keys::kLastVisitdKey, MilliSecondsFromTime(row.last_visit()));
+  value->SetDouble(keys::kLastVisitdKey,
+                   MilliSecondsFromTime(row.last_visit()));
   value->SetInteger(keys::kTypedCountKey, row.typed_count());
   value->SetInteger(keys::kVisitCountKey, row.visit_count());
 }
@@ -46,7 +47,7 @@
                             DictionaryValue* value) {
   value->SetString(keys::kIdKey, base::Int64ToString(row.url_id));
   value->SetString(keys::kVisitId, base::Int64ToString(row.visit_id));
-  value->SetReal(keys::kVisitTime, MilliSecondsFromTime(row.visit_time));
+  value->SetDouble(keys::kVisitTime, MilliSecondsFromTime(row.visit_time));
   value->SetString(keys::kReferringVisitId,
                    base::Int64ToString(row.referring_visit));
 
@@ -175,7 +176,7 @@
 
 bool HistoryFunction::GetTimeFromValue(Value* value, base::Time* time) {
   double ms_from_epoch = 0.0;
-  if (!value->GetAsReal(&ms_from_epoch)) {
+  if (!value->GetAsDouble(&ms_from_epoch)) {
     int ms_from_epoch_as_int = 0;
     if (!value->GetAsInteger(&ms_from_epoch_as_int))
       return false;
diff --git a/chrome/browser/extensions/extension_history_apitest.cc b/chrome/browser/extensions/extension_history_apitest.cc
index 874f868..a0b3fbe 100644
--- a/chrome/browser/extensions/extension_history_apitest.cc
+++ b/chrome/browser/extensions/extension_history_apitest.cc
@@ -2,16 +2,50 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/base_switches.h"
 #include "base/command_line.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
 #include "net/base/mock_host_resolver.h"
 
-// Disabled, http://crbug.com/26296.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_History) {
-  host_resolver()->AddRule("www.a.com", "127.0.0.1");
-  host_resolver()->AddRule("www.b.com", "127.0.0.1");
-  ASSERT_TRUE(StartTestServer());
+class ExtensionHistoryApiTest : public ExtensionApiTest {
+ public:
+  virtual void SetUpInProcessBrowserTestFixture() {
+    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
 
-  ASSERT_TRUE(RunExtensionTest("history")) << message_;
+    host_resolver()->AddRule("www.a.com", "127.0.0.1");
+    host_resolver()->AddRule("www.b.com", "127.0.0.1");
+
+    ASSERT_TRUE(StartTestServer());
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) {
+    ExtensionApiTest::SetUpCommandLine(command_line);
+
+    // Tests are flaky, but only on the waterfall (crbug.com/26296).
+    // Failures involve a call to chrome.history.search() not finding
+    // a result whose addition caused event chrome.history.onVisited
+    // to fire.  Turn on verbose logging.
+    // TODO(skerner): Remove this once the flakiness is fixed.
+    command_line->AppendSwitchASCII(switches::kVModule, "*/history/*=1");
+  }
+};
+
+// Flaky, http://crbug.com/26296.
+IN_PROC_BROWSER_TEST_F(ExtensionHistoryApiTest, FLAKY_MiscSearch) {
+  ASSERT_TRUE(RunExtensionSubtest("history", "misc_search.html")) << message_;
+}
+
+// Flaky, http://crbug.com/26296.
+IN_PROC_BROWSER_TEST_F(ExtensionHistoryApiTest, FLAKY_TimedSearch) {
+  ASSERT_TRUE(RunExtensionSubtest("history", "timed_search.html")) << message_;
+}
+
+// Flaky, http://crbug.com/26296.
+IN_PROC_BROWSER_TEST_F(ExtensionHistoryApiTest, FLAKY_Delete) {
+  ASSERT_TRUE(RunExtensionSubtest("history", "delete.html")) << message_;
+}
+
+// Flaky, http://crbug.com/26296.
+IN_PROC_BROWSER_TEST_F(ExtensionHistoryApiTest, FLAKY_GetVisits) {
+  ASSERT_TRUE(RunExtensionSubtest("history", "get_visits.html")) << message_;
 }
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 1d60390..be92d80 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,6 @@
 
 #include <list>
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/singleton.h"
 #include "base/metrics/histogram.h"
@@ -18,13 +15,13 @@
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/browsing_instance.h"
 #include "chrome/browser/debugger/devtools_manager.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/desktop_notification_handler.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/browser/extensions/extension_message_service.h"
 #include "chrome/browser/extensions/extension_tabs_module.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/file_select_helper.h"
 #include "chrome/browser/platform_util.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
@@ -43,13 +40,15 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/native_web_keyboard_event.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/view_types.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/glue/context_menu.h"
 
 #if defined(TOOLKIT_VIEWS)
@@ -148,6 +147,9 @@
   // be the same extension that this points to.
   registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                  Source<Profile>(profile_));
+
+  desktop_notification_handler_.reset(
+      new DesktopNotificationHandler(NULL, render_process_host()));
 }
 
 ExtensionHost::~ExtensionHost() {
@@ -214,7 +216,11 @@
         this);
 }
 
-Browser* ExtensionHost::GetBrowser() const {
+const Browser* ExtensionHost::GetBrowser() const {
+  return view() ? view()->browser() : NULL;
+}
+
+Browser* ExtensionHost::GetBrowser() {
   return view() ? view()->browser() : NULL;
 }
 
@@ -518,7 +524,7 @@
   return webkit_prefs;
 }
 
-void ExtensionHost::ProcessDOMUIMessage(
+void ExtensionHost::ProcessWebUIMessage(
     const ViewHostMsg_DomMessage_Params& params) {
   if (extension_function_dispatcher_.get()) {
     extension_function_dispatcher_->HandleRequest(params);
@@ -531,19 +537,18 @@
 
 void ExtensionHost::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   // TODO(aa): Use the browser's profile if the extension is split mode
   // incognito.
   TabContents* new_contents = delegate_view_helper_.CreateNewWindow(
       route_id,
       render_view_host()->process()->profile(),
       site_instance(),
-      DOMUIFactory::GetDOMUIType(render_view_host()->process()->profile(),
+      WebUIFactory::GetWebUIType(render_view_host()->process()->profile(),
           url_),
       this,
-      window_container_type,
-      frame_name);
+      params.window_container_type,
+      params.frame_name);
 
   TabContents* associated_contents = associated_tab_contents();
   if (associated_contents && associated_contents->delegate())
@@ -555,8 +560,7 @@
   CreateNewWidgetInternal(route_id, popup_type);
 }
 
-void ExtensionHost::CreateNewFullscreenWidget(int route_id,
-                                              WebKit::WebPopupType popup_type) {
+void ExtensionHost::CreateNewFullscreenWidget(int route_id) {
   NOTREACHED()
       << "ExtensionHost does not support showing full screen popups yet.";
 }
@@ -708,7 +712,7 @@
                                            bool* is_keyboard_shortcut) {
   if (extension_host_type_ == ViewType::EXTENSION_POPUP &&
       event.type == NativeWebKeyboardEvent::RawKeyDown &&
-      event.windowsKeyCode == app::VKEY_ESCAPE) {
+      event.windowsKeyCode == ui::VKEY_ESCAPE) {
     DCHECK(is_keyboard_shortcut != NULL);
     *is_keyboard_shortcut = true;
   }
@@ -718,7 +722,7 @@
 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
   if (extension_host_type_ == ViewType::EXTENSION_POPUP) {
     if (event.type == NativeWebKeyboardEvent::RawKeyDown &&
-        event.windowsKeyCode == app::VKEY_ESCAPE) {
+        event.windowsKeyCode == ui::VKEY_ESCAPE) {
       NotificationService::current()->Notify(
           NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
           Source<Profile>(profile_),
@@ -756,6 +760,20 @@
   return extension_host_type_;
 }
 
+bool ExtensionHost::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+
+  if (!handled) {
+    // Pass desktop notification IPCs to the DesktopNotificationHandler.
+    handled = desktop_notification_handler_->OnMessageReceived(message);
+  }
+  return handled;
+}
+
 const GURL& ExtensionHost::GetURL() const {
   return url_;
 }
@@ -778,12 +796,6 @@
   }
 }
 
-RenderViewHostDelegate::FileSelect* ExtensionHost::GetFileSelectDelegate() {
-  if (file_select_helper_.get() == NULL)
-    file_select_helper_.reset(new FileSelectHelper(profile()));
-  return file_select_helper_.get();
-}
-
 int ExtensionHost::GetBrowserWindowID() const {
   // Hosts not attached to any browser window have an id of -1.  This includes
   // those mentioned below, and background pages.
@@ -793,7 +805,7 @@
     // If the host is bound to a browser, then extract its window id.
     // Extensions hosted in ExternalTabContainer objects may not have
     // an associated browser.
-    Browser* browser = GetBrowser();
+    const Browser* browser = GetBrowser();
     if (browser)
       window_id = ExtensionTabUtil::GetWindowId(browser);
   } else if (extension_host_type_ != ViewType::EXTENSION_BACKGROUND_PAGE) {
@@ -801,3 +813,10 @@
   }
   return window_id;
 }
+
+void ExtensionHost::OnRunFileChooser(
+    const ViewHostMsg_RunFileChooser_Params& params) {
+  if (file_select_helper_.get() == NULL)
+    file_select_helper_.reset(new FileSelectHelper(profile()));
+  file_select_helper_->RunFileChooser(render_view_host_, params);
+}
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 801bdab..d5e0423 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,20 +16,22 @@
 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/extensions/extension_view.h"
+#include "chrome/browser/ui/views/extensions/extension_view.h"
 #elif defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/extension_view_mac.h"
+#include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h"
 #elif defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/extension_view_gtk.h"
+#include "chrome/browser/ui/gtk/extension_view_gtk.h"
 #endif
 #include "chrome/common/notification_registrar.h"
 
 class Browser;
+class DesktopNotificationHandler;
 class Extension;
 class FileSelectHelper;
 class RenderProcessHost;
 class RenderWidgetHostView;
 class TabContents;
+struct ViewHostMsg_RunFileChooser_Params;
 struct WebPreferences;
 
 // This class is the browser component of an extension component's RenderView.
@@ -53,14 +55,14 @@
 
 #if defined(TOOLKIT_VIEWS)
   void set_view(ExtensionView* view) { view_.reset(view); }
-  ExtensionView* view() const { return view_.get(); }
+  const ExtensionView* view() const { return view_.get(); }
+  ExtensionView* view() { return view_.get(); }
 #elif defined(OS_MACOSX)
-  ExtensionViewMac* view() const { return view_.get(); }
+  const ExtensionViewMac* view() const { return view_.get(); }
+  ExtensionViewMac* view() { return view_.get(); }
 #elif defined(TOOLKIT_GTK)
-  ExtensionViewGtk* view() const { return view_.get(); }
-#else
-  // TODO(port): implement
-  void* view() const { return NULL; }
+  const ExtensionViewGtk* view() const { return view_.get(); }
+  ExtensionViewGtk* view() { return view_.get(); }
 #endif
 
   // Create an ExtensionView and tie it to this host and |browser|.  Note NULL
@@ -69,7 +71,7 @@
   // instantiate Browser objects.
   void CreateView(Browser* browser);
 
-  const Extension* extension() { return extension_; }
+  const Extension* extension() const { return extension_; }
   RenderViewHost* render_view_host() const { return render_view_host_; }
   RenderProcessHost* render_process_host() const;
   SiteInstance* site_instance() const;
@@ -106,11 +108,11 @@
   // |size_limit| in both width and height.
   void DisableScrollbarsForSmallWindows(const gfx::Size& size_limit);
 
-  // RenderViewHostDelegate::View implementation.
+  // RenderViewHostDelegate implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
   virtual const GURL& GetURL() const;
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
   virtual ViewType::Type GetRenderViewType() const;
-  virtual FileSelect* GetFileSelectDelegate();
   virtual int GetBrowserWindowID() const;
   virtual void RenderViewGone(RenderViewHost* render_view_host,
                               base::TerminationStatus status,
@@ -126,7 +128,7 @@
   // RenderViewHostDelegate implementation.
   virtual RenderViewHostDelegate::View* GetViewDelegate();
   virtual WebPreferences GetWebkitPrefs();
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
   virtual void RunJavaScriptMessage(const std::wstring& message,
                                     const std::wstring& default_prompt,
                                     const GURL& frame_url,
@@ -139,11 +141,9 @@
   // RenderViewHostDelegate::View
   virtual void CreateNewWindow(
       int route_id,
-      WindowContainerType window_container_type,
-      const string16& frame_name);
+      const ViewHostMsg_CreateWindow_Params& params);
   virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
-  virtual void CreateNewFullscreenWidget(int route_id,
-                                         WebKit::WebPopupType popup_type);
+  virtual void CreateNewFullscreenWidget(int route_id);
   virtual void ShowCreatedWindow(int route_id,
                                  WindowOpenDisposition disposition,
                                  const gfx::Rect& initial_pos,
@@ -220,10 +220,16 @@
   // Actually create the RenderView for this host. See CreateRenderViewSoon.
   void CreateRenderViewNow();
 
+  // Const version of below function.
+  const Browser* GetBrowser() const;
+
   // ExtensionFunctionDispatcher::Delegate
-  virtual Browser* GetBrowser() const;
+  virtual Browser* GetBrowser();
   virtual gfx::NativeView GetNativeViewOfHost();
 
+  // Message handlers.
+  void OnRunFileChooser(const ViewHostMsg_RunFileChooser_Params& params);
+
   // Handles keyboard events that were not handled by HandleKeyboardEvent().
   // Platform specific implementation may override this method to handle the
   // event in platform specific way.
@@ -280,6 +286,9 @@
   // FileSelectHelper, lazily created.
   scoped_ptr<FileSelectHelper> file_select_helper_;
 
+  // Handles desktop notification IPCs.
+  scoped_ptr<DesktopNotificationHandler> desktop_notification_handler_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionHost);
 };
 
diff --git a/chrome/browser/extensions/extension_host_mac.mm b/chrome/browser/extensions/extension_host_mac.mm
index 67bc851..73e29fb 100644
--- a/chrome/browser/extensions/extension_host_mac.mm
+++ b/chrome/browser/extensions/extension_host_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,8 @@
 ExtensionHostMac::~ExtensionHostMac() {
   // If there is a popup open for this host's extension, close it.
   ExtensionPopupController* popup = [ExtensionPopupController popup];
-  if (popup && [popup extensionHost]->extension() == this->extension()) {
+  if ([[popup window] isVisible] &&
+      [popup extensionHost]->extension() == this->extension()) {
     InfoBubbleWindow* window = (InfoBubbleWindow*)[popup window];
     [window setDelayOnClose:NO];
     [popup close];
diff --git a/chrome/browser/extensions/extension_icon_manager.cc b/chrome/browser/extensions/extension_icon_manager.cc
index 887dc3f..8709cb7 100644
--- a/chrome/browser/extensions/extension_icon_manager.cc
+++ b/chrome/browser/extensions/extension_icon_manager.cc
@@ -4,19 +4,19 @@
 
 #include "chrome/browser/extensions/extension_icon_manager.h"
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/stl_util-inl.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/extension_resource.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
-#include "gfx/favicon_size.h"
-#include "gfx/skbitmap_operations.h"
-#include "gfx/size.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/image_operations.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/skbitmap_operations.h"
 
 namespace {
 
diff --git a/chrome/browser/extensions/extension_icon_manager.h b/chrome/browser/extensions/extension_icon_manager.h
index cc0deb9..e5fc381 100644
--- a/chrome/browser/extensions/extension_icon_manager.h
+++ b/chrome/browser/extensions/extension_icon_manager.h
@@ -12,8 +12,8 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
-#include "gfx/insets.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/insets.h"
 
 class Extension;
 
diff --git a/chrome/browser/extensions/extension_icon_manager_unittest.cc b/chrome/browser/extensions/extension_icon_manager_unittest.cc
index 37f3453..d3c476b 100644
--- a/chrome/browser/extensions/extension_icon_manager_unittest.cc
+++ b/chrome/browser/extensions/extension_icon_manager_unittest.cc
@@ -11,8 +11,8 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/json_value_serializer.h"
-#include "gfx/skia_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/skia_util.h"
 
 // Our test class that takes care of managing the necessary threads for loading
 // extension icons, and waiting for those loads to happen.
diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc
index b43e6c8..781b501 100644
--- a/chrome/browser/extensions/extension_idle_api.cc
+++ b/chrome/browser/extensions/extension_idle_api.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 
 namespace keys = extension_idle_api_constants;
diff --git a/chrome/browser/extensions/extension_idle_apitest.cc b/chrome/browser/extensions/extension_idle_apitest.cc
index 03406ce..e1a9b33 100644
--- a/chrome/browser/extensions/extension_idle_apitest.cc
+++ b/chrome/browser/extensions/extension_idle_apitest.cc
@@ -4,7 +4,6 @@
 
 #include "base/command_line.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
 #include "net/base/mock_host_resolver.h"
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Idle) {
diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc
index 315ac99..498aa68 100644
--- a/chrome/browser/extensions/extension_incognito_apitest.cc
+++ b/chrome/browser/extensions/extension_incognito_apitest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/base/mock_host_resolver.h"
@@ -82,9 +81,15 @@
   EXPECT_TRUE(result);
 }
 
+// http://crbug.com/70913 flaky hangs on linux so disabling.
+#if defined(OS_LINUX)
+#define MAYBE_DontCreateIncognitoProfile DISABLED_DontCreateIncognitoProfile
+#else
+#define MAYBE_DontCreateIncognitoProfile DontCreateIncognitoProfile
+#endif
 // Tests that an extension which is enabled for incognito mode doesn't
 // accidentially create and incognito profile.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DontCreateIncognitoProfile) {
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_DontCreateIncognitoProfile) {
   ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
   ASSERT_TRUE(RunExtensionTestIncognito(
       "incognito/dont_create_profile")) << message_;
@@ -109,16 +114,10 @@
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
 }
 
-// Hangs flakily on mac and linux: http://crbug.com/53991
-#if defined(OS_MACOSX) || defined(OS_LINUX)
-#define MAYBE_IncognitoSplitMode DISABLED_IncognitoSplitMode
-#else
-#define MAYBE_IncognitoSplitMode IncognitoSplitMode
-#endif
-
 // Tests that the APIs in an incognito-enabled split-mode extension work
 // properly.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoSplitMode) {
+// Hangs flakily on mac, linux, win: http://crbug.com/53991
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_IncognitoSplitMode) {
   host_resolver()->AddRule("*", "127.0.0.1");
   ASSERT_TRUE(StartTestServer());
 
diff --git a/chrome/browser/extensions/extension_infobar_delegate.cc b/chrome/browser/extensions/extension_infobar_delegate.cc
index 140a82f..c37e5d0 100644
--- a/chrome/browser/extensions/extension_infobar_delegate.cc
+++ b/chrome/browser/extensions/extension_infobar_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -39,10 +39,6 @@
     observer_->OnDelegateDeleted();
 }
 
-void ExtensionInfoBarDelegate::InfoBarDismissed() {
-  closing_ = true;
-}
-
 bool ExtensionInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
   ExtensionInfoBarDelegate* extension_delegate =
       delegate->AsExtensionInfoBarDelegate();
@@ -59,17 +55,21 @@
          extension_host_->extension();
 }
 
+void ExtensionInfoBarDelegate::InfoBarDismissed() {
+  closing_ = true;
+}
+
 void ExtensionInfoBarDelegate::InfoBarClosed() {
   delete this;
 }
 
-ExtensionInfoBarDelegate*
-ExtensionInfoBarDelegate::AsExtensionInfoBarDelegate() {
-  return this;
+InfoBarDelegate::Type ExtensionInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
 }
 
-InfoBarDelegate::Type ExtensionInfoBarDelegate::GetInfoBarType() {
-  return PAGE_ACTION_TYPE;
+ExtensionInfoBarDelegate*
+    ExtensionInfoBarDelegate::AsExtensionInfoBarDelegate() {
+  return this;
 }
 
 void ExtensionInfoBarDelegate::Observe(NotificationType type,
diff --git a/chrome/browser/extensions/extension_infobar_delegate.h b/chrome/browser/extensions/extension_infobar_delegate.h
index f286a11..95f73aa 100644
--- a/chrome/browser/extensions/extension_infobar_delegate.h
+++ b/chrome/browser/extensions/extension_infobar_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -27,30 +27,34 @@
     virtual ~DelegateObserver() {}
   };
 
-  ExtensionInfoBarDelegate(Browser* browser, TabContents* contents,
-                           const Extension* extension, const GURL& url);
-  ~ExtensionInfoBarDelegate();
+  ExtensionInfoBarDelegate(Browser* browser,
+                           TabContents* contents,
+                           const Extension* extension,
+                           const GURL& url);
 
   const Extension* extension() { return extension_; }
   ExtensionHost* extension_host() { return extension_host_.get(); }
 
   void set_observer(DelegateObserver* observer) { observer_ = observer; }
 
-  // Overridden from InfoBarDelegate:
-  virtual void InfoBarDismissed();
-  virtual bool EqualsDelegate(InfoBarDelegate* delegate) const;
-  virtual void InfoBarClosed();
-  virtual InfoBar* CreateInfoBar();
-  virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate();
-  virtual Type GetInfoBarType();
+  bool closing() const { return closing_; }
 
-  // Overridden from NotificationObserver:
+ private:
+  virtual ~ExtensionInfoBarDelegate();
+
+  // InfoBarDelegate:
+  virtual InfoBar* CreateInfoBar();
+  virtual bool EqualsDelegate(InfoBarDelegate* delegate) const;
+  virtual void InfoBarDismissed();
+  virtual void InfoBarClosed();
+  virtual Type GetInfoBarType() const;
+  virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate();
+
+  // NotificationObserver:
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
-  bool closing() { return closing_; }
- private:
   // The extension host we are showing the InfoBar for. The delegate needs to
   // own this since the InfoBar gets deleted and recreated when you switch tabs
   // and come back (and we don't want the user's interaction with the InfoBar to
@@ -61,9 +65,7 @@
   DelegateObserver* observer_;
 
   const Extension* extension_;
-
   TabContents* tab_contents_;
-
   NotificationRegistrar registrar_;
 
   // Whether we are currently animating to close. This is used to ignore
diff --git a/chrome/browser/extensions/extension_input_api.cc b/chrome/browser/extensions/extension_input_api.cc
index cc5cb43..84dba8e 100644
--- a/chrome/browser/extensions/extension_input_api.cc
+++ b/chrome/browser/extensions/extension_input_api.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,16 +6,17 @@
 
 #include <string>
 
-#include "app/keyboard_code_conversion.h"
+#include "base/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/extensions/key_identifier_conversion_views.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/native_web_keyboard_event.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
-#include "views/event.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "views/events/event.h"
 #include "views/widget/root_view.h"
 
 namespace {
@@ -34,16 +35,17 @@
 const char kUnknownEventTypeError[] = "Unknown event type.";
 const char kUnknownOrUnsupportedKeyIdentiferError[] = "Unknown or unsupported "
     "key identifier.";
+const char kUnsupportedModifier[] = "Unsupported modifier.";
 const char kNoValidRecipientError[] = "No valid recipient for event.";
 const char kKeyEventUnprocessedError[] = "Event was not handled.";
 
-views::Event::EventType GetTypeFromString(const std::string& type) {
+ui::EventType GetTypeFromString(const std::string& type) {
   if (type == kKeyDown) {
-    return views::Event::ET_KEY_PRESSED;
+    return ui::ET_KEY_PRESSED;
   } else if (type == kKeyUp) {
-    return views::Event::ET_KEY_RELEASED;
+    return ui::ET_KEY_RELEASED;
   }
-  return views::Event::ET_UNKNOWN;
+  return ui::ET_UNKNOWN;
 }
 
 }  // namespace
@@ -75,33 +77,41 @@
 
   std::string type_name;
   EXTENSION_FUNCTION_VALIDATE(args->GetString(kType, &type_name));
-  views::Event::EventType type = GetTypeFromString(type_name);
-  if (type == views::Event::ET_UNKNOWN) {
+  ui::EventType type = GetTypeFromString(type_name);
+  if (type == ui::ET_UNKNOWN) {
     error_ = kUnknownEventTypeError;
     return false;
   }
 
   std::string identifier;
   EXTENSION_FUNCTION_VALIDATE(args->GetString(kKeyIdentifier, &identifier));
-  app::KeyboardCode code = app::KeyCodeFromKeyIdentifier(identifier);
-  if (code == app::VKEY_UNKNOWN) {
+  TrimWhitespaceASCII(identifier, TRIM_ALL, &identifier);
+
+  const views::KeyEvent& prototype_event =
+      KeyEventFromKeyIdentifier(identifier);
+  if (prototype_event.key_code() == ui::VKEY_UNKNOWN) {
     error_ = kUnknownOrUnsupportedKeyIdentiferError;
     return false;
   }
 
-  int flags = 0;
+  int flags = prototype_event.flags();
   bool alt = false;
   if (args->GetBoolean(kAlt, &alt))
-    flags |= alt ? WebKit::WebInputEvent::AltKey : 0;
+    flags |= alt ? ui::EF_ALT_DOWN : 0;
   bool ctrl = false;
   if (args->GetBoolean(kCtrl, &ctrl))
-    flags |= ctrl ? WebKit::WebInputEvent::ControlKey : 0;
-  bool meta = false;
-  if (args->GetBoolean(kMeta, &meta))
-    flags |= meta ? WebKit::WebInputEvent::MetaKey : 0;
+    flags |= ctrl ? ui::EF_CONTROL_DOWN : 0;
   bool shift = false;
   if (args->GetBoolean(kShift, &shift))
-    flags |= shift ? WebKit::WebInputEvent::ShiftKey : 0;
+    flags |= shift ? ui::EF_SHIFT_DOWN : 0;
+  bool meta = false;
+  if (args->GetBoolean(kMeta, &meta)) {
+    // Views does not have a Meta event flag, so return an error for now.
+    if (meta) {
+      error_ = kUnsupportedModifier;
+      return false;
+    }
+  }
 
   views::RootView* root_view = GetRootView();
   if (!root_view) {
@@ -109,7 +119,7 @@
     return false;
   }
 
-  views::KeyEvent event(type, code, flags, 0, 0);
+  views::KeyEvent event(type, prototype_event.key_code(), flags);
   if (!root_view->ProcessKeyEvent(event)) {
     error_ = kKeyEventUnprocessedError;
     return false;
diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc
index 18013e0..a0df0a9 100644
--- a/chrome/browser/extensions/extension_install_ui.cc
+++ b/chrome/browser/extensions/extension_install_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,8 @@
 
 #include <map>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
-#include "base/i18n/rtl.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -21,9 +18,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/extensions/url_pattern.h"
@@ -32,19 +28,12 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-
-#if defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/extension_installed_bubble_bridge.h"
-#endif
-
-#if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/extensions/extension_installed_bubble.h"
-#endif
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(TOOLKIT_GTK)
 #include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
-#include "chrome/browser/gtk/extension_installed_bubble_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
 #endif
 
 // static
@@ -154,24 +143,7 @@
     return;
   }
 
-#if defined(TOOLKIT_VIEWS)
-  ExtensionInstalledBubble::Show(extension, browser, icon_);
-#elif defined(OS_MACOSX)
-  if ((extension->browser_action()) || !extension->omnibox_keyword().empty() ||
-      (extension->page_action() &&
-      !extension->page_action()->default_icon_path().empty())) {
-    ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble(
-        browser->window()->GetNativeHandle(),
-        extension, browser, icon_);
-  } else {
-    // If the extension is of type GENERIC, meaning it doesn't have a UI
-    // surface to display for this window, launch infobar instead of popup
-    // bubble, because we have no guaranteed wrench menu button to point to.
-    ShowGenericExtensionInstalledInfoBar(extension);
-  }
-#elif defined(TOOLKIT_GTK)
-  ExtensionInstalledBubbleGtk::Show(extension, browser, icon_);
-#endif  // TOOLKIT_VIEWS
+  browser::ShowExtensionInstalledBubble(extension, browser, icon_, profile);
 }
 
 void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
@@ -229,9 +201,10 @@
   }
 }
 
-void ExtensionInstallUI::ShowThemeInfoBar(
-    const std::string& previous_theme_id, bool previous_use_system_theme,
-    const Extension* new_theme, Profile* profile) {
+void ExtensionInstallUI::ShowThemeInfoBar(const std::string& previous_theme_id,
+                                          bool previous_use_system_theme,
+                                          const Extension* new_theme,
+                                          Profile* profile) {
   if (!new_theme->is_theme())
     return;
 
@@ -248,7 +221,7 @@
 
   // First find any previous theme preview infobars.
   InfoBarDelegate* old_delegate = NULL;
-  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
+  for (size_t i = 0; i < tab_contents->infobar_count(); ++i) {
     InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
     ThemeInstalledInfoBarDelegate* theme_infobar =
         delegate->AsThemePreviewInfobarDelegate();
@@ -264,10 +237,8 @@
   }
 
   // Then either replace that old one or add a new one.
-  InfoBarDelegate* new_delegate =
-      GetNewThemeInstalledInfoBarDelegate(
-          tab_contents, new_theme,
-          previous_theme_id, previous_use_system_theme);
+  InfoBarDelegate* new_delegate = GetNewThemeInstalledInfoBarDelegate(
+      tab_contents, new_theme, previous_theme_id, previous_use_system_theme);
 
   if (old_delegate)
     tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
@@ -286,38 +257,16 @@
                      ImageLoadingTracker::DONT_CACHE);
 }
 
-#if defined(OS_MACOSX)
-void ExtensionInstallUI::ShowGenericExtensionInstalledInfoBar(
-    const Extension* new_extension) {
-  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
-  if (!browser)
-    return;
-
-  TabContents* tab_contents = browser->GetSelectedTabContents();
-  if (!tab_contents)
-    return;
-
-  string16 extension_name = UTF8ToUTF16(new_extension->name());
-  base::i18n::AdjustStringForLocaleDirection(&extension_name);
-  string16 msg =
-      l10n_util::GetStringFUTF16(IDS_EXTENSION_INSTALLED_HEADING,
-                                 extension_name) +
-      UTF8ToUTF16(" ") +
-      l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_INFO_MAC);
-  InfoBarDelegate* delegate = new SimpleAlertInfoBarDelegate(
-      tab_contents, msg, new SkBitmap(icon_), true);
-  tab_contents->AddInfoBar(delegate);
-}
-#endif
-
 InfoBarDelegate* ExtensionInstallUI::GetNewThemeInstalledInfoBarDelegate(
-    TabContents* tab_contents, const Extension* new_theme,
-    const std::string& previous_theme_id, bool previous_use_system_theme) {
+    TabContents* tab_contents,
+    const Extension* new_theme,
+    const std::string& previous_theme_id,
+    bool previous_use_system_theme) {
 #if defined(TOOLKIT_GTK)
   return new GtkThemeInstalledInfoBarDelegate(tab_contents, new_theme,
       previous_theme_id, previous_use_system_theme);
 #else
   return new ThemeInstalledInfoBarDelegate(tab_contents, new_theme,
-      previous_theme_id);
+                                           previous_theme_id);
 #endif
 }
diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h
index 1a9b4d7..0e41409 100644
--- a/chrome/browser/extensions/extension_install_ui.h
+++ b/chrome/browser/extensions/extension_install_ui.h
@@ -12,8 +12,8 @@
 #include "base/string16.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
 #include "chrome/common/extensions/url_pattern.h"
-#include "gfx/native_widget_types.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Extension;
 class MessageLoop;
@@ -97,12 +97,6 @@
   // 2) Handle the load icon response and show the UI (OnImageLoaded).
   void ShowConfirmation(PromptType prompt_type);
 
-#if defined(OS_MACOSX)
-  // When an extension is installed on Mac with neither browser action nor
-  // page action icons, show an infobar instead of a popup bubble.
-  void ShowGenericExtensionInstalledInfoBar(const Extension* new_extension);
-#endif
-
   // Returns the delegate to control the browser's info bar. This is
   // within its own function due to its platform-specific nature.
   static InfoBarDelegate* GetNewThemeInstalledInfoBarDelegate(
diff --git a/chrome/browser/extensions/extension_install_ui_browsertest.cc b/chrome/browser/extensions/extension_install_ui_browsertest.cc
index 6866325..3cf6564 100644
--- a/chrome/browser/extensions/extension_install_ui_browsertest.cc
+++ b/chrome/browser/extensions/extension_install_ui_browsertest.cc
@@ -1,7 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/string_util.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
@@ -12,9 +13,6 @@
 
 namespace {
 
-// Theme ID used for testing.
-const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad";
-
 }  // namespace
 
 class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest {
@@ -24,24 +22,23 @@
   void VerifyThemeInfoBarAndUndoInstall() {
     TabContents* tab_contents = browser()->GetSelectedTabContents();
     ASSERT_TRUE(tab_contents);
-    ASSERT_EQ(1, tab_contents->infobar_delegate_count());
-    ThemeInstalledInfoBarDelegate* delegate = tab_contents->
-        GetInfoBarDelegateAt(0)->AsThemePreviewInfobarDelegate();
+    ASSERT_EQ(1U, tab_contents->infobar_count());
+    ConfirmInfoBarDelegate* delegate =
+        tab_contents->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
     ASSERT_TRUE(delegate);
     delegate->Cancel();
-    ASSERT_EQ(0, tab_contents->infobar_delegate_count());
+    ASSERT_EQ(0U, tab_contents->infobar_count());
   }
 };
 
-// Crashy, http://crbug.com/44548.
 IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
-                       DISABLED_TestThemeInstallUndoResetsToDefault) {
+                       TestThemeInstallUndoResetsToDefault) {
   // Install theme once and undo to verify we go back to default theme.
-  FilePath theme_path = test_data_dir_.AppendASCII("theme.crx");
-  ASSERT_TRUE(InstallExtensionWithUI(theme_path, 1));
+  FilePath theme_crx = PackExtension(test_data_dir_.AppendASCII("theme"));
+  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 1));
   const Extension* theme = browser()->profile()->GetTheme();
   ASSERT_TRUE(theme);
-  ASSERT_EQ(theme_crx, theme->id());
+  std::string theme_id = theme->id();
   VerifyThemeInfoBarAndUndoInstall();
   ASSERT_EQ(NULL, browser()->profile()->GetTheme());
 
@@ -49,14 +46,73 @@
   // We set the |expected_change| to zero in these 'InstallExtensionWithUI'
   // calls since the theme has already been installed above and this is an
   // overinstall to set the active theme.
-  ASSERT_TRUE(InstallExtensionWithUI(theme_path, 0));
+  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 0));
   theme = browser()->profile()->GetTheme();
   ASSERT_TRUE(theme);
-  ASSERT_EQ(theme_crx, theme->id());
-  ASSERT_TRUE(InstallExtensionWithUI(theme_path, 0));
+  ASSERT_EQ(theme_id, theme->id());
+  ASSERT_TRUE(InstallExtensionWithUI(theme_crx, 0));
   theme = browser()->profile()->GetTheme();
   ASSERT_TRUE(theme);
-  ASSERT_EQ(theme_crx, theme->id());
+  ASSERT_EQ(theme_id, theme->id());
   VerifyThemeInfoBarAndUndoInstall();
   ASSERT_EQ(NULL, browser()->profile()->GetTheme());
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
+                       TestThemeInstallUndoResetsToPreviousTheme) {
+  // Install first theme.
+  FilePath theme_path = test_data_dir_.AppendASCII("theme");
+  ASSERT_TRUE(InstallExtensionWithUI(theme_path, 1));
+  const Extension* theme = browser()->profile()->GetTheme();
+  ASSERT_TRUE(theme);
+  std::string theme_id = theme->id();
+
+  // Then install second theme.
+  FilePath theme_path2 = test_data_dir_.AppendASCII("theme2");
+  ASSERT_TRUE(InstallExtensionWithUI(theme_path2, 1));
+  const Extension* theme2 = browser()->profile()->GetTheme();
+  ASSERT_TRUE(theme2);
+  EXPECT_FALSE(theme_id == theme2->id());
+
+  // Undo second theme will revert to first theme.
+  VerifyThemeInfoBarAndUndoInstall();
+  EXPECT_EQ(theme, browser()->profile()->GetTheme());
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
+                       AppInstallConfirmation) {
+  int num_tabs = browser()->tab_count();
+
+  FilePath app_dir = test_data_dir_.AppendASCII("app");
+  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
+                                                browser()->profile()));
+
+  EXPECT_EQ(num_tabs + 1, browser()->tab_count());
+  TabContents* tab_contents = browser()->GetSelectedTabContents();
+  ASSERT_TRUE(tab_contents);
+  EXPECT_TRUE(StartsWithASCII(tab_contents->GetURL().spec(),
+                              "chrome://newtab/#app-id=",  // id changes
+                              false));
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionInstallUIBrowserTest,
+                       AppInstallConfirmation_Incognito) {
+  Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
+  Browser* incognito_browser = Browser::GetOrCreateTabbedBrowser(
+      incognito_profile);
+
+  int num_incognito_tabs = incognito_browser->tab_count();
+  int num_normal_tabs = browser()->tab_count();
+
+  FilePath app_dir = test_data_dir_.AppendASCII("app");
+  ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(app_dir, 1,
+                                                incognito_profile));
+
+  EXPECT_EQ(num_incognito_tabs, incognito_browser->tab_count());
+  EXPECT_EQ(num_normal_tabs + 1, browser()->tab_count());
+  TabContents* tab_contents = browser()->GetSelectedTabContents();
+  ASSERT_TRUE(tab_contents);
+  EXPECT_TRUE(StartsWithASCII(tab_contents->GetURL().spec(),
+                              "chrome://newtab/#app-id=",  // id changes
+                              false));
+}
diff --git a/chrome/browser/extensions/extension_io_event_router.cc b/chrome/browser/extensions/extension_io_event_router.cc
new file mode 100644
index 0000000..5beb4b8
--- /dev/null
+++ b/chrome/browser/extensions/extension_io_event_router.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_io_event_router.h"
+
+#include "googleurl/src/gurl.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/extension_event_router.h"
+#include "chrome/browser/profiles/profile.h"
+
+ExtensionIOEventRouter::ExtensionIOEventRouter(Profile* profile)
+    : profile_(profile) {
+}
+
+ExtensionIOEventRouter::~ExtensionIOEventRouter() {
+}
+
+void ExtensionIOEventRouter::DispatchEventToExtension(
+    const std::string& extension_id,
+    const std::string& event_name,
+    const std::string& event_args) const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(this,
+                        &ExtensionIOEventRouter::DispatchEventOnUIThread,
+                        extension_id, event_name, event_args));
+}
+
+void ExtensionIOEventRouter::DispatchEventOnUIThread(
+    const std::string& extension_id,
+    const std::string& event_name,
+    const std::string& event_args) const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // If the profile has gone away, we're shutting down. If there's no event
+  // router, the extension system hasn't been initialized.
+  if (!profile_ || !profile_->GetExtensionEventRouter())
+    return;
+
+  profile_->GetExtensionEventRouter()->DispatchEventToExtension(
+      extension_id, event_name, event_args, profile_, GURL());
+}
diff --git a/chrome/browser/extensions/extension_io_event_router.h b/chrome/browser/extensions/extension_io_event_router.h
new file mode 100644
index 0000000..eae207b
--- /dev/null
+++ b/chrome/browser/extensions/extension_io_event_router.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_IO_EVENT_ROUTER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_IO_EVENT_ROUTER_H_
+#pragma once
+
+#include <string>
+
+#include "base/ref_counted.h"
+
+class Profile;
+
+// For now, this just forwards events from the IO thread to the
+// ExtensionEventRouter on the UI thread.
+// TODO(mpcomplete): eventually I want this to have its own copy of the event
+// listeners so it can bypass the jump to the UI thread.
+class ExtensionIOEventRouter
+    : public base::RefCountedThreadSafe<ExtensionIOEventRouter> {
+ public:
+  explicit ExtensionIOEventRouter(Profile* profile);
+  ~ExtensionIOEventRouter();
+
+  void DestroyingProfile() { profile_ = NULL; }
+
+  // Dispatch the named event to every extension listening to that event.
+  void DispatchEventToExtension(const std::string& extension_id,
+                                const std::string& event_name,
+                                const std::string& event_args) const;
+
+ private:
+  void DispatchEventOnUIThread(const std::string& extension_id,
+                               const std::string& event_name,
+                               const std::string& event_args) const;
+
+  Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionIOEventRouter);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_IO_EVENT_ROUTER_H_
diff --git a/chrome/browser/extensions/extension_management_api.cc b/chrome/browser/extensions/extension_management_api.cc
index 50117c4..d6b5a35 100644
--- a/chrome/browser/extensions/extension_management_api.cc
+++ b/chrome/browser/extensions/extension_management_api.cc
@@ -167,8 +167,13 @@
     return false;
   }
 
-  extension_misc::LaunchContainer container = extension->launch_container();
-  Browser::OpenApplication(profile(), extension, container, NULL);
+  // Look at prefs to find the right launch container.
+  // |default_pref_value| is set to LAUNCH_REGULAR so that if
+  // the user has not set a preference, we open the app in a tab.
+  extension_misc::LaunchContainer launch_container =
+      service()->extension_prefs()->GetLaunchContainer(
+          extension, ExtensionPrefs::LAUNCH_DEFAULT);
+  Browser::OpenApplication(profile(), extension, launch_container, NULL);
 
   return true;
 }
diff --git a/chrome/browser/extensions/extension_management_api_browsertest.cc b/chrome/browser/extensions/extension_management_api_browsertest.cc
index 80955ba..e6a7c11 100644
--- a/chrome/browser/extensions/extension_management_api_browsertest.cc
+++ b/chrome/browser/extensions/extension_management_api_browsertest.cc
@@ -33,3 +33,13 @@
   ASSERT_TRUE(listener1.WaitUntilSatisfied());
   ASSERT_TRUE(listener2.WaitUntilSatisfied());
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
+                       LaunchAppFromBackground) {
+  ExtensionTestMessageListener listener1("success", false);
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("management/packaged_app")));
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("management/launch_app_from_background")));
+  ASSERT_TRUE(listener1.WaitUntilSatisfied());
+}
diff --git a/chrome/browser/extensions/extension_management_apitest.cc b/chrome/browser/extensions/extension_management_apitest.cc
index 9883f5d..c2c6bbe 100644
--- a/chrome/browser/extensions/extension_management_apitest.cc
+++ b/chrome/browser/extensions/extension_management_apitest.cc
@@ -4,8 +4,28 @@
 
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/test/ui_test_utils.h"
+
+namespace {
+
+// Find a browser other than |browser|.
+Browser* FindOtherBrowser(Browser* browser) {
+  Browser* found = NULL;
+  for (BrowserList::const_iterator it = BrowserList::begin();
+       it != BrowserList::end(); ++it) {
+    if (*it == browser)
+      continue;
+    found = *it;
+  }
+
+  return found;
+}
+
+}  // namespace
 
 class ExtensionManagementApiTest : public ExtensionApiTest {
  public:
@@ -25,6 +45,19 @@
     ASSERT_TRUE(LoadExtension(basedir.AppendASCII("disabled_app")));
     service->DisableExtension(last_loaded_extension_id_);
   }
+
+  // Load an app, and wait for a message from app "management/launch_on_install"
+  // indicating that the new app has been launched.
+  void LoadAndWaitForLaunch(const std::string& app_path,
+                            std::string* out_app_id) {
+    ExtensionTestMessageListener launched_app("launched app", false);
+    ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_path)));
+
+    if (out_app_id)
+      *out_app_id = last_loaded_extension_id_;
+
+    ASSERT_TRUE(launched_app.WaitUntilSatisfied());
+  }
 };
 
 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, Basics) {
@@ -36,3 +69,107 @@
   InstallExtensions();
   ASSERT_TRUE(RunExtensionSubtest("management/test", "uninstall.html"));
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, LaunchPanelApp) {
+  ExtensionService* service = browser()->profile()->GetExtensionService();
+
+  // Load an extension that calls launchApp() on any app that gets
+  // installed.
+  ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("management/launch_on_install")));
+  ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
+
+  // Load an app with app.launch.container = "panel".
+  std::string app_id;
+  LoadAndWaitForLaunch("management/launch_app_panel", &app_id);
+  ASSERT_FALSE(HasFatalFailure());  // Stop the test if any ASSERT failed.
+
+  // Find the app's browser.  Check that it is a panel.
+  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
+  Browser* app_browser = FindOtherBrowser(browser());
+  ASSERT_EQ(Browser::TYPE_APP_POPUP, app_browser->type());
+
+  // Close the app panel.
+  app_browser->CloseWindow();
+  ui_test_utils::WaitForNotificationFrom(NotificationType::BROWSER_CLOSED,
+                                           Source<Browser>(app_browser));
+
+  // Unload the extension.
+  UninstallExtension(app_id);
+  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
+  ASSERT_FALSE(service->GetExtensionById(app_id, true));
+
+  // Set a pref indicating that the user wants to launch in a regular tab.
+  // This should be ignored, because panel apps always load in a panel.
+  service->extension_prefs()->SetLaunchType(
+      app_id, ExtensionPrefs::LAUNCH_REGULAR);
+
+  // Load the extension again.
+  std::string app_id_new;
+  LoadAndWaitForLaunch("management/launch_app_panel", &app_id_new);
+  ASSERT_FALSE(HasFatalFailure());
+
+  // If the ID changed, then the pref will not apply to the app.
+  ASSERT_EQ(app_id, app_id_new);
+
+  // Find the app's browser.  Apps that should load in a panel ignore
+  // prefs, so we should still see the launch in a panel.
+  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
+  app_browser = FindOtherBrowser(browser());
+  ASSERT_EQ(Browser::TYPE_APP_POPUP, app_browser->type());
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, LaunchTabApp) {
+  ExtensionService* service = browser()->profile()->GetExtensionService();
+
+  // Load an extension that calls launchApp() on any app that gets
+  // installed.
+  ExtensionTestMessageListener launcher_loaded("launcher loaded", false);
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("management/launch_on_install")));
+  ASSERT_TRUE(launcher_loaded.WaitUntilSatisfied());
+
+  // Code below assumes that the test starts with a single browser window
+  // hosting one tab.
+  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
+  ASSERT_EQ(1, browser()->tab_count());
+
+  // Load an app with app.launch.container = "tab".
+  std::string app_id;
+  LoadAndWaitForLaunch("management/launch_app_tab", &app_id);
+  ASSERT_FALSE(HasFatalFailure());
+
+  // Check that the app opened in a new tab of the existing browser.
+  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
+  ASSERT_EQ(2, browser()->tab_count());
+
+  // Unload the extension.
+  UninstallExtension(app_id);
+  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
+  ASSERT_FALSE(service->GetExtensionById(app_id, true));
+
+  // Set a pref indicating that the user wants to launch in a window.
+  service->extension_prefs()->SetLaunchType(
+      app_id, ExtensionPrefs::LAUNCH_WINDOW);
+
+  std::string app_id_new;
+  LoadAndWaitForLaunch("management/launch_app_tab", &app_id_new);
+  ASSERT_FALSE(HasFatalFailure());
+
+  // If the ID changed, then the pref will not apply to the app.
+  ASSERT_EQ(app_id, app_id_new);
+
+#if defined(OS_MACOSX)
+  // App windows are not yet implemented on mac os.  We should fall back
+  // to a normal tab.
+  ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
+  ASSERT_EQ(2, browser()->tab_count());
+#else
+  // Find the app's browser.  Opening in a new window will create
+  // a new browser.
+  ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
+  Browser* app_browser = FindOtherBrowser(browser());
+  ASSERT_EQ(Browser::TYPE_APP, app_browser->type());
+#endif
+}
diff --git a/chrome/browser/extensions/extension_management_browsertest.cc b/chrome/browser/extensions/extension_management_browsertest.cc
index a1eb2f6..4239940 100644
--- a/chrome/browser/extensions/extension_management_browsertest.cc
+++ b/chrome/browser/extensions/extension_management_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -352,8 +352,8 @@
         prefs->GetMutableList(prefs::kExtensionInstallForceList);
     ASSERT_TRUE(forcelist->empty());
     forcelist->Append(Value::CreateStringValue(
-        "ogjcoiohnmldgjemafoockdghcjciccf;"
-        "http://localhost/autoupdate/manifest"));
+        std::string(kExtensionId) +
+        ";http://localhost/autoupdate/manifest"));
   }
 
   // Check if the extension got installed.
@@ -365,6 +365,13 @@
   EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD,
             extensions->at(size_before)->location());
 
-  // Check that emptying the list doesn't cause any trouble.
-  prefs->ClearPref(prefs::kExtensionInstallForceList);
+  // Check that emptying the list triggers uninstall.
+  {
+    ScopedPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
+    prefs->ClearPref(prefs::kExtensionInstallForceList);
+  }
+  EXPECT_EQ(size_before, extensions->size());
+  ExtensionList::const_iterator i;
+  for (i = extensions->begin(); i != extensions->end(); ++i)
+    EXPECT_NE(kExtensionId, (*i)->id());
 }
diff --git a/chrome/browser/extensions/extension_menu_manager.cc b/chrome/browser/extensions/extension_menu_manager.cc
index 0d3c891..aa0fa60 100644
--- a/chrome/browser/extensions/extension_menu_manager.cc
+++ b/chrome/browser/extensions/extension_menu_manager.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
@@ -18,7 +17,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/favicon_size.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/favicon_size.h"
 #include "webkit/glue/context_menu.h"
 
 ExtensionMenuItem::ExtensionMenuItem(const Id& id,
diff --git a/chrome/browser/extensions/extension_metrics_module.cc b/chrome/browser/extensions/extension_metrics_module.cc
index a1815f2..a06d6fd 100644
--- a/chrome/browser/extensions/extension_metrics_module.cc
+++ b/chrome/browser/extensions/extension_metrics_module.cc
@@ -8,6 +8,8 @@
 #include "base/values.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/ui/options/options_util.h"
+#include "chrome/installer/util/google_update_settings.h"
 
 using base::Histogram;
 using base::LinearHistogram;
@@ -31,6 +33,25 @@
 // enable-metrics-extension-api command line switch is used.  Refer to
 // extension_function_dispatcher.cc to see how they are enabled.
 
+bool MetricsSetEnabledFunction::RunImpl() {
+  bool enabled = false;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled));
+
+  // Using OptionsUtil is better because it actually ensures we reset all the
+  // necessary threads. This is the main way for starting / stopping UMA and
+  // crash reporting.
+  // This method will return the resulting enabled, which we send to JS.
+  bool result = OptionsUtil::ResolveMetricsReportingEnabled(enabled);
+  result_.reset(Value::CreateBooleanValue(result));
+  return true;
+}
+
+bool MetricsGetEnabledFunction::RunImpl() {
+  bool enabled = GoogleUpdateSettings::GetCollectStatsConsent();
+  result_.reset(Value::CreateBooleanValue(enabled));
+  return true;
+}
+
 bool MetricsRecordUserActionFunction::RunImpl() {
   std::string name;
   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &name));
diff --git a/chrome/browser/extensions/extension_metrics_module.h b/chrome/browser/extensions/extension_metrics_module.h
index 523acc0..333ae2f 100644
--- a/chrome/browser/extensions/extension_metrics_module.h
+++ b/chrome/browser/extensions/extension_metrics_module.h
@@ -11,6 +11,18 @@
 #include "base/metrics/histogram.h"
 #include "chrome/browser/extensions/extension_function.h"
 
+class MetricsSetEnabledFunction : public SyncExtensionFunction {
+  DECLARE_EXTENSION_FUNCTION_NAME("experimental.metrics.setEnabled")
+ protected:
+  virtual bool RunImpl();
+};
+
+class MetricsGetEnabledFunction : public SyncExtensionFunction {
+  DECLARE_EXTENSION_FUNCTION_NAME("experimental.metrics.getEnabled")
+ protected:
+  virtual bool RunImpl();
+};
+
 class MetricsRecordUserActionFunction : public SyncExtensionFunction {
   virtual bool RunImpl();
   DECLARE_EXTENSION_FUNCTION_NAME("experimental.metrics.recordUserAction")
diff --git a/chrome/browser/extensions/extension_omnibox_api.cc b/chrome/browser/extensions/extension_omnibox_api.cc
index 4981c98..408fa1f 100644
--- a/chrome/browser/extensions/extension_omnibox_api.cc
+++ b/chrome/browser/extensions/extension_omnibox_api.cc
@@ -261,5 +261,5 @@
     }
   }
 
-  match->contents.assign(UTF16ToWide(description));
+  match->contents.assign(description);
 }
diff --git a/chrome/browser/extensions/extension_omnibox_apitest.cc b/chrome/browser/extensions/extension_omnibox_apitest.cc
index 0eba9be..82c9f32 100644
--- a/chrome/browser/extensions/extension_omnibox_apitest.cc
+++ b/chrome/browser/extensions/extension_omnibox_apitest.cc
@@ -1,7 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/format_macros.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
@@ -17,7 +18,6 @@
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/ui_test_utils.h"
@@ -32,16 +32,16 @@
 
 namespace {
 
-std::wstring AutocompleteResultAsString(const AutocompleteResult& result) {
-  std::wstring output(base::StringPrintf(L"{%d} ", result.size()));
+string16 AutocompleteResultAsString(const AutocompleteResult& result) {
+  std::string output(base::StringPrintf("{%" PRIuS "} ", result.size()));
   for (size_t i = 0; i < result.size(); ++i) {
     AutocompleteMatch match = result.match_at(i);
-    std::wstring provider_name(ASCIIToWide(match.provider->name()));
-    output.append(base::StringPrintf(L"[\"%ls\" by \"%ls\"] ",
-                                     match.contents.c_str(),
+    std::string provider_name = match.provider->name();
+    output.append(base::StringPrintf("[\"%s\" by \"%s\"] ",
+                                     UTF16ToUTF8(match.contents).c_str(),
                                      provider_name.c_str()));
   }
-  return output;
+  return UTF8ToUTF16(output);
 }
 
 }  // namespace
@@ -89,13 +89,13 @@
   // Test that our extension's keyword is suggested to us when we partially type
   // it.
   {
-    autocomplete_controller->Start(L"keywor", std::wstring(),
+    autocomplete_controller->Start(ASCIIToUTF16("keywor"), string16(),
                                    true, false, true, false);
 
     WaitForAutocompleteDone(autocomplete_controller);
     EXPECT_TRUE(autocomplete_controller->done());
     EXPECT_EQ(std::wstring(), location_bar->GetInputString());
-    EXPECT_EQ(std::wstring(), location_bar->location_entry()->GetText());
+    EXPECT_EQ(string16(), location_bar->location_entry()->GetText());
     EXPECT_TRUE(location_bar->location_entry()->IsSelectAll());
 
     // First result should be to search for what was typed, second should be to
@@ -109,13 +109,13 @@
     match = result.match_at(1);
     ASSERT_TRUE(match.template_url);
     EXPECT_TRUE(match.template_url->IsExtensionKeyword());
-    EXPECT_EQ(L"keyword", match.template_url->keyword());
+    EXPECT_EQ(ASCIIToUTF16("keyword"), match.template_url->keyword());
   }
 
   // Test that our extension can send suggestions back to us.
   {
-    autocomplete_controller->Start(L"keyword suggestio", std::wstring(),
-                                   true, false, true, false);
+    autocomplete_controller->Start(ASCIIToUTF16("keyword suggestio"),
+                                   string16(), true, false, true, false);
 
     WaitForAutocompleteDone(autocomplete_controller);
     EXPECT_TRUE(autocomplete_controller->done());
@@ -127,13 +127,17 @@
     ASSERT_EQ(5U, result.size()) << AutocompleteResultAsString(result);
 
     ASSERT_TRUE(result.match_at(0).template_url);
-    EXPECT_EQ(L"keyword suggestio", result.match_at(0).fill_into_edit);
-    EXPECT_EQ(L"keyword suggestion1", result.match_at(1).fill_into_edit);
-    EXPECT_EQ(L"keyword suggestion2", result.match_at(2).fill_into_edit);
-    EXPECT_EQ(L"keyword suggestion3", result.match_at(3).fill_into_edit);
+    EXPECT_EQ(ASCIIToUTF16("keyword suggestio"),
+              result.match_at(0).fill_into_edit);
+    EXPECT_EQ(ASCIIToUTF16("keyword suggestion1"),
+              result.match_at(1).fill_into_edit);
+    EXPECT_EQ(ASCIIToUTF16("keyword suggestion2"),
+              result.match_at(2).fill_into_edit);
+    EXPECT_EQ(ASCIIToUTF16("keyword suggestion3"),
+              result.match_at(3).fill_into_edit);
 
-    std::wstring description =
-        L"Description with style: <match>, [dim], (url till end)";
+    string16 description =
+        ASCIIToUTF16("Description with style: <match>, [dim], (url till end)");
     EXPECT_EQ(description, result.match_at(1).contents);
     ASSERT_EQ(6u, result.match_at(1).contents_class.size());
 
@@ -174,7 +178,7 @@
 
   {
     ResultCatcher catcher;
-    autocomplete_controller->Start(L"keyword command", std::wstring(),
+    autocomplete_controller->Start(ASCIIToUTF16("keyword command"), string16(),
                                    true, false, true, false);
     location_bar->AcceptInput();
     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
diff --git a/chrome/browser/extensions/extension_override_apitest.cc b/chrome/browser/extensions/extension_override_apitest.cc
index 4fd73f4..877fe11 100644
--- a/chrome/browser/extensions/extension_override_apitest.cc
+++ b/chrome/browser/extensions/extension_override_apitest.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
@@ -19,7 +19,7 @@
     // There should be no duplicate entries in the preferences.
     const DictionaryValue* overrides =
         browser()->profile()->GetPrefs()->GetDictionary(
-            ExtensionDOMUI::kExtensionURLOverrides);
+            ExtensionWebUI::kExtensionURLOverrides);
 
     ListValue* values = NULL;
     if (!overrides->GetList("history", &values))
@@ -72,7 +72,13 @@
   // Verify behavior, then unload the first and verify behavior, etc.
 }
 
-IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, OverrideNewtabIncognito) {
+#if defined(OS_MACOSX)
+// Hangy: http://crbug.com/70511
+#define MAYBE_OverrideNewtabIncognito DISABLED_OverrideNewtabIncognito
+#else
+#define MAYBE_OverrideNewtabIncognito OverrideNewtabIncognito
+#endif
+IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, MAYBE_OverrideNewtabIncognito) {
   ASSERT_TRUE(RunExtensionTest("override/newtab")) << message_;
 
   // Navigate an incognito tab to the new tab page.  We should get the actual
@@ -113,7 +119,7 @@
   // Simulate several LoadExtension() calls happening over the lifetime of
   // a preferences file without corresponding UnloadExtension() calls.
   for (size_t i = 0; i < 3; ++i) {
-    ExtensionDOMUI::RegisterChromeURLOverrides(
+    ExtensionWebUI::RegisterChromeURLOverrides(
         browser()->profile(),
         browser()->profile()->GetExtensionService()->extensions()->back()->
             GetChromeURLOverrides());
@@ -132,7 +138,7 @@
     list->Append(Value::CreateStringValue("http://www.google.com/"));
 
   browser()->profile()->GetPrefs()->GetMutableDictionary(
-      ExtensionDOMUI::kExtensionURLOverrides)->Set("history", list);
+      ExtensionWebUI::kExtensionURLOverrides)->Set("history", list);
 
   ASSERT_FALSE(CheckHistoryOverridesContainsNoDupes());
 
diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc
index 0e26d60..94a1790 100644
--- a/chrome/browser/extensions/extension_page_actions_module.cc
+++ b/chrome/browser/extensions/extension_page_actions_module.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/extensions/extension_page_actions_module.h"
 
+#include <string>
+
 #include "base/string_number_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/extensions/extension_page_actions_module_constants.h"
@@ -12,7 +14,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_action.h"
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
deleted file mode 100644
index 25d3657..0000000
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ /dev/null
@@ -1,555 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_popup_api.h"
-
-#include <string>
-
-#include "base/json/json_writer.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "base/values.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
-#include "chrome/browser/extensions/extension_event_router.h"
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/window_sizer.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/point.h"
-
-#if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/bubble_border.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
-#include "views/view.h"
-#include "views/focus/focus_manager.h"
-#endif  // TOOLKIT_VIEWS
-
-namespace extension_popup_module_events {
-
-const char kOnPopupClosed[] = "experimental.popup.onClosed.%d";
-
-}  // namespace extension_popup_module_events
-
-namespace {
-
-// Errors.
-const char kBadAnchorArgument[] = "Invalid anchor argument.";
-const char kInvalidURLError[] = "Invalid URL.";
-const char kNotAnExtension[] = "Not an extension view.";
-const char kPopupsDisallowed[] =
-    "Popups are only supported from tab-contents views.";
-
-// Keys.
-const char kWidthKey[] = "width";
-const char kHeightKey[] = "height";
-const char kTopKey[] = "top";
-const char kLeftKey[] = "left";
-const char kGiveFocusKey[] = "giveFocus";
-const char kDomAnchorKey[] = "domAnchor";
-const char kBorderStyleKey[] = "borderStyle";
-const char kMaxSizeKey[] = "maxSize";
-
-// chrome enumeration values
-const char kRectangleChrome[] = "rectangle";
-
-#if defined(TOOLKIT_VIEWS)
-// Returns an updated arrow location, conditioned on the type of intersection
-// between the popup window, and the screen.  |location| is the current position
-// of the arrow on the popup.  |intersection| is the rect representing the
-// intersection between the popup view and its working screen.  |popup_rect|
-// is the rect of the popup window in screen space coordinates.
-// The returned location will be horizontally or vertically inverted based on
-// if the popup has been clipped horizontally or vertically.
-BubbleBorder::ArrowLocation ToggleArrowLocation(
-    BubbleBorder::ArrowLocation location, const gfx::Rect& intersection,
-    const gfx::Rect& popup_rect) {
-  // If the popup has been clipped horizontally, flip the right-left position
-  // of the arrow.
-  if (intersection.right() != popup_rect.right() ||
-      intersection.x() != popup_rect.x()) {
-    location = BubbleBorder::horizontal_mirror(location);
-  }
-
-  // If the popup has been clipped vertically, flip the bottom-top position
-  // of the arrow.
-  if (intersection.y() != popup_rect.y() ||
-      intersection.bottom() != popup_rect.bottom()) {
-    location = BubbleBorder::vertical_mirror(location);
-  }
-
-  return location;
-}
-#endif  // TOOLKIT_VIEWS
-
-};  // namespace
-
-#if defined(TOOLKIT_VIEWS)
-// ExtensionPopupHost objects implement the environment necessary to host
-// an ExtensionPopup views for the popup api. Its main job is to handle
-// its lifetime and to fire the popup-closed event when the popup is closed.
-// Because the close-on-focus-lost behavior is different from page action
-// and browser action, it also manages its own focus change listening. The
-// difference in close-on-focus-lost is that in the page action and browser
-// action cases, the popup closes when the focus leaves the popup or any of its
-// children. In this case, the popup closes when the focus leaves the popups
-// containing view or any of *its* children.
-class ExtensionPopupHost : public ExtensionPopup::Observer,
-                           public views::WidgetFocusChangeListener,
-                           public base::RefCounted<ExtensionPopupHost>,
-                           public NotificationObserver {
- public:
-  // Pass |max_popup_size| to specify the maximal size to which the popup
-  // will expand.  A width or height of 0 will result in the popup making use
-  // of the default max width or height, respectively: ExtensionPopup:kMaxWidth,
-  // and ExtensionPopup::kMaxHeight.
-  explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher,
-                              const gfx::Size& max_popup_size)
-      : dispatcher_(dispatcher), popup_(NULL), max_popup_size_(max_popup_size) {
-    AddRef();  // Balanced in DispatchPopupClosedEvent().
-    views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this);
-  }
-
-  ~ExtensionPopupHost() {
-    views::FocusManager::GetWidgetFocusManager()->
-        RemoveFocusChangeListener(this);
-  }
-
-  void set_popup(ExtensionPopup* popup) {
-    popup_ = popup;
-
-    // Now that a popup has been assigned, listen for subsequent popups being
-    // created in the same extension - we want to disallow more than one
-    // concurrently displayed popup windows.
-    registrar_.Add(
-        this,
-        NotificationType::EXTENSION_HOST_CREATED,
-        Source<ExtensionProcessManager>(
-            dispatcher_->profile()->GetExtensionProcessManager()));
-
-    registrar_.Add(
-        this,
-        NotificationType::RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
-        Source<RenderViewHost>(dispatcher_->render_view_host()));
-
-    registrar_.Add(
-        this,
-        NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED,
-        Source<Profile>(dispatcher_->profile()));
-  }
-
-  // Overridden from ExtensionPopup::Observer
-  virtual void ExtensionPopupIsClosing(ExtensionPopup* popup) {
-    // Unregister the automation resource routing registered upon host
-    // creation.
-    AutomationResourceRoutingDelegate* router =
-        GetRoutingFromDispatcher(dispatcher_);
-    if (router)
-      router->UnregisterRenderViewHost(popup_->host()->render_view_host());
-  }
-
-  virtual void ExtensionPopupClosed(void* popup_token) {
-    if (popup_ == popup_token) {
-      popup_ = NULL;
-      DispatchPopupClosedEvent();
-    }
-  }
-
-  virtual void ExtensionHostCreated(ExtensionHost* host) {
-    // Pop-up views should share the same automation routing configuration as
-    // their hosting views, so register the RenderViewHost of the pop-up with
-    // the AutomationResourceRoutingDelegate interface of the dispatcher.
-    AutomationResourceRoutingDelegate* router =
-        GetRoutingFromDispatcher(dispatcher_);
-    if (router)
-      router->RegisterRenderViewHost(host->render_view_host());
-
-    // Extension hosts created for popup contents exist in the same tab
-    // contents as the ExtensionFunctionDispatcher that requested the popup.
-    // For example, '_blank' link navigation should be routed through the tab
-    // contents that requested the popup.
-    if (dispatcher_ && dispatcher_->delegate()) {
-      host->set_associated_tab_contents(
-          dispatcher_->delegate()->associated_tab_contents());
-    }
-  }
-
-  virtual void ExtensionPopupCreated(ExtensionPopup* popup) {
-    // The popup has been created, but not yet displayed, so install the max
-    // size overrides before the first positioning.
-    if (max_popup_size_.width())
-      popup->set_max_width(max_popup_size_.width());
-
-    if (max_popup_size_.height())
-      popup->set_max_height(max_popup_size_.height());
-  }
-
-  virtual void ExtensionPopupResized(ExtensionPopup* popup) {
-    // Reposition the location of the arrow on the popup so that the popup
-    // better fits on the working monitor.
-    gfx::Rect popup_rect = popup->GetOuterBounds();
-    if (popup_rect.IsEmpty())
-      return;
-
-    scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
-        WindowSizer::CreateDefaultMonitorInfoProvider());
-    gfx::Rect monitor_bounds(
-        monitor_provider->GetMonitorWorkAreaMatching(popup_rect));
-    gfx::Rect intersection = monitor_bounds.Intersect(popup_rect);
-
-    // If the popup is totally out of the bounds of the monitor, then toggling
-    // the arrow location will not result in an un-clipped window.
-    if (intersection.IsEmpty())
-      return;
-
-    if (!intersection.Equals(popup_rect)) {
-      // The popup was clipped by the monitor.  Toggle the arrow position
-      // to see if that improves visibility.  Note:  The assignment and
-      // re-assignment of the arrow-position will not trigger an intermittent
-      // display.
-      BubbleBorder::ArrowLocation previous_location = popup->arrow_position();
-      BubbleBorder::ArrowLocation flipped_location = ToggleArrowLocation(
-          previous_location, intersection, popup_rect);
-      popup->SetArrowPosition(flipped_location);
-
-      // Double check that toggling the position actually improved the
-      // situation - the popup will be contained entirely in its working monitor
-      // bounds.
-      gfx::Rect flipped_bounds = popup->GetOuterBounds();
-      gfx::Rect updated_monitor_bounds =
-          monitor_provider->GetMonitorWorkAreaMatching(flipped_bounds);
-      if (!updated_monitor_bounds.Contains(flipped_bounds))
-        popup->SetArrowPosition(previous_location);
-    }
-  }
-
-  // Overridden from views::WidgetFocusChangeListener
-  virtual void NativeFocusWillChange(gfx::NativeView focused_before,
-                                     gfx::NativeView focused_now) {
-    // If the popup doesn't exist, then do nothing.
-    if (!popup_)
-      return;
-
-    // If no view is to be focused, then Chrome was deactivated, so hide the
-    // popup.
-    if (focused_now) {
-      // On XP, the focus change handler may be invoked when the delegate has
-      // already been revoked.
-      // TODO(twiz@chromium.org):  Resolve the trigger of this behaviour.
-      if (!dispatcher_ || !dispatcher_->delegate())
-        return;
-
-      gfx::NativeView host_view =
-          dispatcher_->delegate()->GetNativeViewOfHost();
-
-      // If the widget hosting the popup contains the newly focused view, then
-      // don't dismiss the pop-up.
-      ExtensionView* view = popup_->host()->view();
-      if (view) {
-        views::Widget* popup_root_widget = view->GetWidget();
-        if (popup_root_widget &&
-            popup_root_widget->ContainsNativeView(focused_now))
-          return;
-      }
-
-      // If the widget or RenderWidgetHostView hosting the extension that
-      // launched the pop-up is receiving focus, then don't dismiss the popup.
-      views::Widget* host_widget =
-          views::Widget::GetWidgetFromNativeView(host_view);
-      if (host_widget && host_widget->ContainsNativeView(focused_now))
-        return;
-
-      RenderWidgetHostView* render_host_view =
-          RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView(
-              host_view);
-      if (render_host_view &&
-          render_host_view->ContainsNativeView(focused_now))
-        return;
-    }
-
-    // We are careful here to let the current event loop unwind before
-    // causing the popup to be closed.
-    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(popup_,
-        &ExtensionPopup::Close));
-  }
-
-  // Overridden from NotificationObserver
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    if (NotificationType::EXTENSION_HOST_CREATED == type) {
-      Details<ExtensionHost> details_host(details);
-      // Disallow multiple pop-ups from the same extension, by closing
-      // the presently opened popup during construction of any new popups.
-      if (ViewType::EXTENSION_POPUP == details_host->GetRenderViewType() &&
-          popup_->host()->extension() == details_host->extension() &&
-          Details<ExtensionHost>(popup_->host()) != details) {
-        popup_->Close();
-      }
-    } else if (NotificationType::RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW ==
-        type) {
-      if (Source<RenderViewHost>(dispatcher_->render_view_host()) == source) {
-        // If the parent render view is about to be closed, signal closure
-        // of the popup.
-        popup_->Close();
-      }
-    } else if (NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED ==
-        type) {
-      // Popups should not outlive the dispatchers that launched them.
-      // Normally, long-lived popups will be dismissed in response to the
-      // RENDER_VIEW_WILL_CLOSE_BY_RENDER_VIEW_HOST message.  Unfortunately,
-      // if the hosting view invokes window.close(), there is no communication
-      // back to the browser until the entire view has been torn down, at which
-      // time the dispatcher will be invoked.
-      // Note:  The onClosed event will not be fired, but because the hosting
-      // view has already been torn down, it is already too late to process it.
-      // TODO(twiz):  Add a communication path between the renderer and browser
-      // for RenderView closure notifications initiatied within the renderer.
-      if (Details<ExtensionFunctionDispatcher>(dispatcher_) == details) {
-        dispatcher_ = NULL;
-        popup_->Close();
-      }
-    }
-  }
-
- private:
-  // Returns the AutomationResourceRoutingDelegate interface for |dispatcher|.
-  static AutomationResourceRoutingDelegate*
-      GetRoutingFromDispatcher(ExtensionFunctionDispatcher* dispatcher) {
-    if (!dispatcher)
-      return NULL;
-
-    RenderViewHost* render_view_host = dispatcher->render_view_host();
-    RenderViewHostDelegate* delegate =
-        render_view_host ? render_view_host->delegate() : NULL;
-
-    return delegate ? delegate->GetAutomationResourceRoutingDelegate() : NULL;
-  }
-
-  void DispatchPopupClosedEvent() {
-    if (dispatcher_) {
-      PopupEventRouter::OnPopupClosed(
-          dispatcher_->profile(),
-          dispatcher_->render_view_host()->routing_id());
-      dispatcher_ = NULL;
-    }
-    Release();  // Balanced in ctor.
-  }
-
-  // A pointer to the dispatcher that handled the request that opened this
-  // popup view.
-  ExtensionFunctionDispatcher* dispatcher_;
-
-  // A pointer to the popup.
-  ExtensionPopup* popup_;
-
-  // The maximal size to which the popup is permitted to expand.
-  gfx::Size max_popup_size_;
-
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost);
-};
-#endif  // TOOLKIT_VIEWS
-
-PopupShowFunction::PopupShowFunction()
-#if defined (TOOLKIT_VIEWS)
-    : popup_(NULL)
-#endif
-{}
-
-void PopupShowFunction::Run() {
-#if defined(TOOLKIT_VIEWS)
-  if (!RunImpl()) {
-    SendResponse(false);
-  } else {
-    // If the contents of the popup are already available, then immediately
-    // send the response.  Otherwise wait for the EXTENSION_POPUP_VIEW_READY
-    // notification.
-    if (popup_->host() && popup_->host()->document_element_available()) {
-      SendResponse(true);
-    } else {
-      AddRef();
-      registrar_.Add(this, NotificationType::EXTENSION_POPUP_VIEW_READY,
-                     NotificationService::AllSources());
-      registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED,
-                     NotificationService::AllSources());
-    }
-  }
-#else
-  SendResponse(false);
-#endif
-}
-
-bool PopupShowFunction::RunImpl() {
-  // Popups may only be displayed from TAB_CONTENTS and EXTENSION_INFOBAR.
-  ViewType::Type view_type =
-      dispatcher()->render_view_host()->delegate()->GetRenderViewType();
-  if (ViewType::TAB_CONTENTS != view_type &&
-      ViewType::EXTENSION_INFOBAR != view_type) {
-    error_ = kPopupsDisallowed;
-    return false;
-  }
-
-  std::string url_string;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url_string));
-
-  DictionaryValue* show_details = NULL;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &show_details));
-
-  DictionaryValue* dom_anchor = NULL;
-  EXTENSION_FUNCTION_VALIDATE(show_details->GetDictionary(kDomAnchorKey,
-                                                          &dom_anchor));
-
-  int dom_top, dom_left;
-  EXTENSION_FUNCTION_VALIDATE(dom_anchor->GetInteger(kTopKey,
-                                                     &dom_top));
-  EXTENSION_FUNCTION_VALIDATE(dom_anchor->GetInteger(kLeftKey,
-                                                     &dom_left));
-
-  int dom_width, dom_height;
-  EXTENSION_FUNCTION_VALIDATE(dom_anchor->GetInteger(kWidthKey,
-                                                     &dom_width));
-  EXTENSION_FUNCTION_VALIDATE(dom_anchor->GetInteger(kHeightKey,
-                                                     &dom_height));
-  EXTENSION_FUNCTION_VALIDATE(dom_top >= 0 && dom_left >= 0 &&
-                              dom_width >= 0 && dom_height >= 0);
-
-  // The default behaviour is to give the focus to the pop-up window.
-  bool give_focus = true;
-  if (show_details->HasKey(kGiveFocusKey)) {
-    EXTENSION_FUNCTION_VALIDATE(show_details->GetBoolean(kGiveFocusKey,
-                                                         &give_focus));
-  }
-
-  int max_width = 0;
-  int max_height = 0;
-  if (show_details->HasKey(kMaxSizeKey)) {
-    DictionaryValue* max_size = NULL;
-    EXTENSION_FUNCTION_VALIDATE(show_details->GetDictionary(kMaxSizeKey,
-                                                            &max_size));
-
-    if (max_size->HasKey(kWidthKey))
-      EXTENSION_FUNCTION_VALIDATE(max_size->GetInteger(kWidthKey, &max_width));
-
-    if (max_size->HasKey(kHeightKey))
-      EXTENSION_FUNCTION_VALIDATE(max_size->GetInteger(kHeightKey,
-                                                       &max_height));
-  }
-
-#if defined(TOOLKIT_VIEWS)
-  // The default behaviour is to provide the bubble-chrome to the popup.
-  ExtensionPopup::PopupChrome chrome = ExtensionPopup::BUBBLE_CHROME;
-  if (show_details->HasKey(kBorderStyleKey)) {
-    std::string chrome_string;
-    EXTENSION_FUNCTION_VALIDATE(show_details->GetString(kBorderStyleKey,
-                                                        &chrome_string));
-    if (chrome_string == kRectangleChrome)
-      chrome = ExtensionPopup::RECTANGLE_CHROME;
-  }
-#endif
-
-  GURL url = dispatcher()->url().Resolve(url_string);
-  if (!url.is_valid()) {
-    error_ = kInvalidURLError;
-    return false;
-  }
-
-  // Disallow non-extension requests, or requests outside of the requesting
-  // extension view's extension.
-  const std::string& extension_id = url.host();
-  if (extension_id != GetExtension()->id() ||
-      !url.SchemeIs(chrome::kExtensionScheme)) {
-    error_ = kInvalidURLError;
-    return false;
-  }
-
-  gfx::Point origin(dom_left, dom_top);
-  if (!dispatcher()->render_view_host()->view()) {
-    error_ = kNotAnExtension;
-    return false;
-  }
-
-  gfx::Rect content_bounds =
-      dispatcher()->render_view_host()->view()->GetViewBounds();
-  origin.Offset(content_bounds.x(), content_bounds.y());
-  gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height);
-
-  // Get the correct native window to pass to ExtensionPopup.
-  // ExtensionFunctionDispatcher::Delegate may provide a custom implementation
-  // of this.
-  gfx::NativeWindow window =
-      dispatcher()->delegate()->GetCustomFrameNativeWindow();
-  if (!window)
-    window = GetCurrentBrowser()->window()->GetNativeHandle();
-
-#if defined(TOOLKIT_VIEWS)
-  BubbleBorder::ArrowLocation arrow_location = BubbleBorder::TOP_LEFT;
-
-  // ExtensionPopupHost manages it's own lifetime.
-  ExtensionPopupHost* popup_host =
-      new ExtensionPopupHost(dispatcher(), gfx::Size(max_width, max_height));
-  popup_ = ExtensionPopup::Show(url,
-                                GetCurrentBrowser(),
-                                dispatcher()->profile(),
-                                window,
-                                rect,
-                                arrow_location,
-                                give_focus,
-                                false,  // inspect_with_devtools
-                                chrome,
-                                popup_host);  // ExtensionPopup::Observer
-
-  // popup_host will handle focus change listening and close the popup when
-  // focus leaves the containing views hierarchy.
-  popup_->set_close_on_lost_focus(false);
-  popup_host->set_popup(popup_);
-#endif  // defined(TOOLKIT_VIEWS)
-
-  return true;
-}
-
-void PopupShowFunction::Observe(NotificationType type,
-                                const NotificationSource& source,
-                                const NotificationDetails& details) {
-#if defined(TOOLKIT_VIEWS)
-  DCHECK(type == NotificationType::EXTENSION_POPUP_VIEW_READY ||
-         type == NotificationType::EXTENSION_HOST_DESTROYED);
-  DCHECK(popup_ != NULL);
-
-  // Wait for notification that the popup view is ready (and onload has been
-  // called), before completing the API call.
-  if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY &&
-      Details<ExtensionHost>(popup_->host()) == details) {
-    SendResponse(true);
-    Release();  // Balanced in Run().
-  } else if (popup_ && type == NotificationType::EXTENSION_HOST_DESTROYED &&
-             Details<ExtensionHost>(popup_->host()) == details) {
-    // If the host was destroyed, then report failure, and release the remaining
-    // reference.
-    SendResponse(false);
-    Release();  // Balanced in Run().
-  }
-#endif  // defined(TOOLKIT_VIEWS)
-}
-
-// static
-void PopupEventRouter::OnPopupClosed(Profile* profile,
-                                     int routing_id) {
-  std::string full_event_name = base::StringPrintf(
-      extension_popup_module_events::kOnPopupClosed,
-      routing_id);
-
-  profile->GetExtensionEventRouter()->DispatchEventToRenderers(
-      full_event_name, base::JSONWriter::kEmptyArray, profile, GURL());
-}
diff --git a/chrome/browser/extensions/extension_popup_api.h b/chrome/browser/extensions/extension_popup_api.h
deleted file mode 100644
index 0b62fe4..0000000
--- a/chrome/browser/extensions/extension_popup_api.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_POPUP_API_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_POPUP_API_H_
-#pragma once
-
-#include "chrome/browser/extensions/extension_function.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class Profile;
-class ExtensionPopup;
-
-// This extension function shows a pop-up extension view.  It is asynchronous
-// because the callback must be invoked only after the associated render
-// process/view has been created and fully initialized.
-class PopupShowFunction : public AsyncExtensionFunction,
-                          public NotificationObserver {
- public:
-  PopupShowFunction();
-
-  virtual void Run();
-  virtual bool RunImpl();
-  DECLARE_EXTENSION_FUNCTION_NAME("experimental.popup.show")
-
- private:
-  // NotificationObserver methods.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-  NotificationRegistrar registrar_;
-
-#if defined(TOOLKIT_VIEWS)
-  // The pop-up view created by this function, saved for access during
-  // event notification.  The pop-up is not owned by the PopupShowFunction
-  // instance.
-  ExtensionPopup* popup_;
-#endif
-};
-
-// Event router class for events related to the chrome.popup.* set of APIs.
-class PopupEventRouter {
- public:
-  static void OnPopupClosed(Profile* profile,
-                            int routing_id);
- private:
-  DISALLOW_COPY_AND_ASSIGN(PopupEventRouter);
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_POPUP_API_H_
diff --git a/chrome/browser/extensions/extension_popup_apitest.cc b/chrome/browser/extensions/extension_popup_apitest.cc
deleted file mode 100644
index d4afd66..0000000
--- a/chrome/browser/extensions/extension_popup_apitest.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Popup) {
-  CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableExperimentalExtensionApis);
-
-  ASSERT_TRUE(RunExtensionTest("popup/popup_main")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PopupFromInfobar) {
-  CommandLine::ForCurrentProcess()->AppendSwitch(
-    switches::kEnableExperimentalExtensionApis);
-
-  ASSERT_TRUE(RunExtensionTest("popup/popup_from_infobar")) << message_;
-}
diff --git a/chrome/browser/extensions/extension_pref_store.cc b/chrome/browser/extensions/extension_pref_store.cc
index b3aba44..74504c1 100644
--- a/chrome/browser/extensions/extension_pref_store.cc
+++ b/chrome/browser/extensions/extension_pref_store.cc
@@ -1,28 +1,42 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_pref_store.h"
 
-ExtensionPrefStore::ExtensionPrefStore()
-    : initialization_complete_(false) {
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
+
+ExtensionPrefStore::ExtensionPrefStore(
+    ExtensionPrefValueMap* extension_pref_value_map,
+    bool incognito_pref_store)
+    : extension_pref_value_map_(extension_pref_value_map),
+      incognito_pref_store_(incognito_pref_store) {
+  extension_pref_value_map_->AddObserver(this);
 }
 
-void ExtensionPrefStore::SetExtensionPref(const std::string& key,
-                                          Value* value) {
-  SetValue(key, value);
-}
-
-void ExtensionPrefStore::RemoveExtensionPref(const std::string& key) {
-  RemoveValue(key);
+ExtensionPrefStore::~ExtensionPrefStore() {
+  if (extension_pref_value_map_)
+    extension_pref_value_map_->RemoveObserver(this);
 }
 
 void ExtensionPrefStore::OnInitializationCompleted() {
-  DCHECK(!initialization_complete_);
-  initialization_complete_ = true;
   NotifyInitializationCompleted();
 }
 
-bool ExtensionPrefStore::IsInitializationComplete() const {
-  return initialization_complete_;
+void ExtensionPrefStore::OnPrefValueChanged(const std::string& key) {
+  CHECK(extension_pref_value_map_);
+  const Value *winner =
+      extension_pref_value_map_->GetEffectivePrefValue(key,
+                                                       incognito_pref_store_);
+  if (winner)
+    SetValue(key, winner->DeepCopy());
+  else
+    RemoveValue(key);
+}
+
+void ExtensionPrefStore::OnExtensionPrefValueMapDestruction() {
+  CHECK(extension_pref_value_map_);
+  extension_pref_value_map_->RemoveObserver(this);
+  extension_pref_value_map_ = NULL;
 }
diff --git a/chrome/browser/extensions/extension_pref_store.h b/chrome/browser/extensions/extension_pref_store.h
index f2db809..80b82e3 100644
--- a/chrome/browser/extensions/extension_pref_store.h
+++ b/chrome/browser/extensions/extension_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,31 +6,33 @@
 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_STORE_H_
 #pragma once
 
+#include <string>
+
+#include "base/time.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
 #include "chrome/browser/prefs/value_map_pref_store.h"
 
-// A PrefStore implementation that holds preferences set by extensions.
-class ExtensionPrefStore : public ValueMapPrefStore {
+// A (non-persistent) PrefStore implementation that holds effective preferences
+// set by extensions. These preferences are managed by and fetched from an
+// ExtensionPrefValueMap.
+class ExtensionPrefStore : public ValueMapPrefStore,
+                           public ExtensionPrefValueMap::Observer {
  public:
-  ExtensionPrefStore();
-  virtual ~ExtensionPrefStore() {}
-
-  // Set an extension preference |value| for |key|. Takes ownership of |value|.
-  void SetExtensionPref(const std::string& key, Value* value);
-
-  // Remove the extension preference value for |key|.
-  void RemoveExtensionPref(const std::string& key);
-
-  // Tell the store it's now fully initialized.
-  void OnInitializationCompleted();
+  // Constructs an ExtensionPrefStore for a regular or an incognito profile.
+  explicit ExtensionPrefStore(ExtensionPrefValueMap* extension_pref_value_map,
+                              bool incognito_pref_store);
+  virtual ~ExtensionPrefStore();
 
  private:
-  // PrefStore overrides:
-  virtual bool IsInitializationComplete() const;
+  // Overrides for ExtensionPrefValueMap::Observer:
+  virtual void OnInitializationCompleted();
+  virtual void OnPrefValueChanged(const std::string& key);
+  virtual void OnExtensionPrefValueMapDestruction();
 
-  bool initialization_complete_;
+  ExtensionPrefValueMap* extension_pref_value_map_;  // Weak pointer.
+  bool incognito_pref_store_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionPrefStore);
 };
 
-
 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_STORE_H_
diff --git a/chrome/browser/extensions/extension_pref_value_map.cc b/chrome/browser/extensions/extension_pref_value_map.cc
new file mode 100644
index 0000000..e410a73
--- /dev/null
+++ b/chrome/browser/extensions/extension_pref_value_map.cc
@@ -0,0 +1,192 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/extension_pref_value_map.h"
+
+#include "base/stl_util-inl.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/pref_value_map.h"
+
+struct ExtensionPrefValueMap::ExtensionEntry {
+  // Installation time of the extension.
+  base::Time install_time;
+  // Whether extension is enabled in the profile.
+  bool enabled;
+  // Regular preferences.
+  PrefValueMap reg_preferences;
+  // Incognito preferences, empty for regular ExtensionPrefStore.
+  PrefValueMap inc_preferences;
+};
+
+ExtensionPrefValueMap::ExtensionPrefValueMap() {
+}
+
+ExtensionPrefValueMap::~ExtensionPrefValueMap() {
+  NotifyOfDestruction();
+  STLDeleteValues(&entries_);
+  entries_.clear();
+}
+
+void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
+                                             const std::string& key,
+                                             bool incognito,
+                                             Value* value) {
+  PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, incognito);
+
+  if (prefs->SetValue(key, value))
+    NotifyPrefValueChanged(key);
+}
+
+void ExtensionPrefValueMap::RemoveExtensionPref(const std::string& ext_id,
+                                                const std::string& key,
+                                                bool incognito) {
+  PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, incognito);
+  if (prefs->RemoveValue(key))
+    NotifyPrefValueChanged(key);
+}
+
+void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
+                                              const base::Time& install_time,
+                                              bool is_enabled) {
+  if (entries_.find(ext_id) != entries_.end())
+    UnregisterExtension(ext_id);
+  entries_[ext_id] = new ExtensionEntry;
+  entries_[ext_id]->install_time = install_time;
+  entries_[ext_id]->enabled = is_enabled;
+}
+
+void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
+  ExtensionEntryMap::iterator i = entries_.find(ext_id);
+  if (i == entries_.end())
+    return;
+  std::set<std::string> keys;  // keys set by this extension
+  GetExtensionControlledKeys(*(i->second), &keys);
+
+  delete i->second;
+  entries_.erase(i);
+
+  NotifyPrefValueChanged(keys);
+}
+
+void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
+                                              bool is_enabled) {
+  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+  CHECK(i != entries_.end());
+  if (i->second->enabled == is_enabled)
+    return;
+  std::set<std::string> keys;  // keys set by this extension
+  GetExtensionControlledKeys(*(i->second), &keys);
+  i->second->enabled = is_enabled;
+  NotifyPrefValueChanged(keys);
+}
+
+PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+    const std::string& ext_id,
+    bool incognito) {
+  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+  CHECK(i != entries_.end());
+  return incognito ? &(i->second->inc_preferences)
+                   : &(i->second->reg_preferences);
+}
+
+const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+    const std::string& ext_id,
+    bool incognito) const {
+  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+  CHECK(i != entries_.end());
+  return incognito ? &(i->second->inc_preferences)
+                   : &(i->second->reg_preferences);
+}
+
+void ExtensionPrefValueMap::GetExtensionControlledKeys(
+    const ExtensionEntry& entry,
+    std::set<std::string>* out) const {
+  PrefValueMap::const_iterator i;
+
+  const PrefValueMap& reg_prefs = entry.reg_preferences;
+  for (i = reg_prefs.begin(); i != reg_prefs.end(); ++i)
+    out->insert(i->first);
+
+  const PrefValueMap& inc_prefs = entry.inc_preferences;
+  for (i = inc_prefs.begin(); i != inc_prefs.end(); ++i)
+    out->insert(i->first);
+}
+
+const Value* ExtensionPrefValueMap::GetEffectivePrefValue(
+    const std::string& key,
+    bool incognito) const {
+  Value *winner = NULL;
+  base::Time winners_install_time;
+
+  ExtensionEntryMap::const_iterator i;
+  for (i = entries_.begin(); i != entries_.end(); ++i) {
+    const std::string& ext_id = i->first;
+    const base::Time& install_time = i->second->install_time;
+    const bool enabled = i->second->enabled;
+
+    if (!enabled)
+      continue;
+    if (install_time < winners_install_time)
+      continue;
+
+    Value* value = NULL;
+    const PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, false);
+    if (prefs->GetValue(key, &value)) {
+      winner = value;
+      winners_install_time = install_time;
+    }
+
+    if (!incognito)
+      continue;
+
+    prefs = GetExtensionPrefValueMap(ext_id, true);
+    if (prefs->GetValue(key, &value)) {
+      winner = value;
+      winners_install_time = install_time;
+    }
+  }
+  return winner;
+}
+
+void ExtensionPrefValueMap::AddObserver(
+    ExtensionPrefValueMap::Observer* observer) {
+  observers_.AddObserver(observer);
+
+  // Collect all currently used keys and notify the new observer.
+  std::set<std::string> keys;
+  ExtensionEntryMap::const_iterator i;
+  for (i = entries_.begin(); i != entries_.end(); ++i)
+    GetExtensionControlledKeys(*(i->second), &keys);
+
+  std::set<std::string>::const_iterator j;
+  for (j = keys.begin(); j != keys.end(); ++j)
+    observer->OnPrefValueChanged(*j);
+}
+
+void ExtensionPrefValueMap::RemoveObserver(
+    ExtensionPrefValueMap::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void ExtensionPrefValueMap::NotifyInitializationCompleted() {
+  FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+                    OnInitializationCompleted());
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(
+    const std::set<std::string>& keys) {
+  std::set<std::string>::const_iterator i;
+  for (i = keys.begin(); i != keys.end(); ++i)
+    NotifyPrefValueChanged(*i);
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
+  FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+                    OnPrefValueChanged(key));
+}
+
+void ExtensionPrefValueMap::NotifyOfDestruction() {
+  FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+                    OnExtensionPrefValueMapDestruction());
+}
diff --git a/chrome/browser/extensions/extension_pref_value_map.h b/chrome/browser/extensions/extension_pref_value_map.h
new file mode 100644
index 0000000..896a68c
--- /dev/null
+++ b/chrome/browser/extensions/extension_pref_value_map.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_VALUE_MAP_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_VALUE_MAP_H_
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/time.h"
+#include "chrome/browser/prefs/value_map_pref_store.h"
+
+// Non-persistent data container that is shared by ExtensionPrefStores. All
+// extension pref values (incognito and regular) are stored herein and
+// provided to ExtensionPrefStores.
+//
+// The semantics of the ExtensionPrefValueMap are:
+// - The precedence of extensions is determined by their installation time.
+//   The extension that has been installed later takes higher precedence.
+// - If two extensions set a value for the same preference, the following
+//   rules determine which value becomes effective (visible).
+// - The effective regular extension pref value is determined by the regular
+//   extension pref value of the extension with the highest precedence.
+// - The effective incognito extension pref value is determined by the incognito
+//   extension pref value of the extension with the highest precedence, unless
+//   another extension with higher precedence overrides it with a regular
+//   extension pref value.
+//
+// The following table illustrates the behavior:
+//   A.reg | A.inc | B.reg | B.inc | E.reg | E.inc
+//     1   |   -   |   -   |   -   |   1   |   1
+//     1   |   2   |   -   |   -   |   1   |   2
+//     1   |   -   |   3   |   -   |   3   |   3
+//     1   |   -   |   -   |   4   |   1   |   4
+//     1   |   2   |   3   |   -   |   3   |   3(!)
+//     1   |   2   |   -   |   4   |   1   |   4
+//     1   |   2   |   3   |   4   |   3   |   4
+// A = extension A, B = extension B, E = effective value
+// .reg = regular value
+// .inc = incognito value
+// Extension B has higher precedence than A.
+class ExtensionPrefValueMap {
+ public:
+  // Observer interface for monitoring ExtensionPrefValueMap.
+  class Observer {
+   public:
+    virtual ~Observer() {}
+
+    // Called when the value for the given |key| set by one of the extensions
+    // changes. This does not necessarily mean that the effective value has
+    // changed.
+    virtual void OnPrefValueChanged(const std::string& key) = 0;
+    // Notification about the ExtensionPrefValueMap being fully initialized.
+    virtual void OnInitializationCompleted() = 0;
+    // Called when the ExtensionPrefValueMap is being destroyed. When called,
+    // observers must unsubscribe.
+    virtual void OnExtensionPrefValueMapDestruction() = 0;
+  };
+
+  ExtensionPrefValueMap();
+  virtual ~ExtensionPrefValueMap();
+
+  // Set an extension preference |value| for |key| of extension |ext_id|.
+  // Takes ownership of |value|.
+  // Note that regular extension pref values need to be reported to
+  // incognito and to regular ExtensionPrefStores.
+  // Precondition: the extension must be registered.
+  void SetExtensionPref(const std::string& ext_id,
+                        const std::string& key,
+                        bool incognito,
+                        Value* value);
+
+  // Remove the extension preference value for |key| of extension |ext_id|.
+  // Precondition: the extension must be registered.
+  void RemoveExtensionPref(const std::string& ext_id,
+                           const std::string& key,
+                           bool incognito);
+
+  // Tell the store it's now fully initialized.
+  void NotifyInitializationCompleted();
+
+  // Registers the time when an extension |ext_id| is installed.
+  void RegisterExtension(const std::string& ext_id,
+                         const base::Time& install_time,
+                         bool is_enabled);
+
+  // Deletes all entries related to extension |ext_id|.
+  void UnregisterExtension(const std::string& ext_id);
+
+  // Hides or makes the extension preference values of the specified extension
+  // visible.
+  void SetExtensionState(const std::string& ext_id, bool is_enabled);
+
+  // Adds an observer and notifies it about the currently stored keys.
+  void AddObserver(Observer* observer);
+
+  void RemoveObserver(Observer* observer);
+
+  const Value* GetEffectivePrefValue(const std::string& key,
+                                     bool incognito) const;
+
+ private:
+  struct ExtensionEntry;
+
+  typedef std::map<std::string, ExtensionEntry*> ExtensionEntryMap;
+
+  const PrefValueMap* GetExtensionPrefValueMap(const std::string& ext_id,
+                                               bool incognito) const;
+
+  PrefValueMap* GetExtensionPrefValueMap(const std::string& ext_id,
+                                         bool incognito);
+
+  // Returns all keys of pref values that are set by the extension of |entry|,
+  // regardless whether they are set for incognito or regular pref values.
+  void GetExtensionControlledKeys(const ExtensionEntry& entry,
+                                  std::set<std::string>* out) const;
+
+  void NotifyOfDestruction();
+  void NotifyPrefValueChanged(const std::string& key);
+  void NotifyPrefValueChanged(const std::set<std::string>& keys);
+
+  // Mapping of which extension set which preference value. The effective
+  // preferences values (i.e. the ones with the highest precedence)
+  // are stored in ExtensionPrefStores.
+  ExtensionEntryMap entries_;
+
+  ObserverList<Observer, true> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMap);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_VALUE_MAP_H_
diff --git a/chrome/browser/extensions/extension_pref_value_map_unittest.cc b/chrome/browser/extensions/extension_pref_value_map_unittest.cc
new file mode 100644
index 0000000..642bb03
--- /dev/null
+++ b/chrome/browser/extensions/extension_pref_value_map_unittest.cc
@@ -0,0 +1,326 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
+#include "chrome/common/pref_store_observer_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kExt1[] = "ext1";
+const char kExt2[] = "ext2";
+const char kExt3[] = "ext3";
+
+const char kPref1[] = "path1.subpath";
+const char kPref2[] = "path2";
+const char kPref3[] = "path3";
+const char kPref4[] = "path4";
+}  // namespace
+
+static Value* CreateVal(const char* str) {
+  return Value::CreateStringValue(str);
+}
+
+static base::Time CreateTime(int64 t) {
+  return base::Time::FromInternalValue(10);
+}
+
+template <typename BASECLASS>
+class ExtensionPrefValueMapTestBase : public BASECLASS {
+ public:
+  // Returns an empty string if the key is not set.
+  std::string GetValue(const char * key, bool incognito) const {
+    const Value *value = epvm_.GetEffectivePrefValue(key, incognito);
+    std::string string_value = "";
+    if (value)
+      value->GetAsString(&string_value);
+    return string_value;
+  }
+
+ protected:
+  ExtensionPrefValueMap epvm_;
+};
+
+class ExtensionPrefValueMapTest
+    : public ExtensionPrefValueMapTestBase<testing::Test> {
+};
+
+// A gmock-ified implementation of PrefStore::Observer.
+class ExtensionPrefValueMapObserverMock
+    : public ExtensionPrefValueMap::Observer {
+ public:
+  ExtensionPrefValueMapObserverMock() {}
+  virtual ~ExtensionPrefValueMapObserverMock() {}
+
+  MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
+  MOCK_METHOD0(OnInitializationCompleted, void());
+  MOCK_METHOD0(OnExtensionPrefValueMapDestruction, void());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMapObserverMock);
+};
+
+TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValue) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  EXPECT_EQ("val1", GetValue(kPref1, false));
+};
+
+TEST_F(ExtensionPrefValueMapTest, GetNotSetPrefValue) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  EXPECT_EQ("", GetValue(kPref1, false));
+};
+
+// Make sure the last-installed extension wins for each preference.
+TEST_F(ExtensionPrefValueMapTest, Override) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+  epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
+
+  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
+  epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val5"));
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val6"));
+  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val7"));
+  epvm_.SetExtensionPref(kExt1, kPref3, false, CreateVal("val8"));
+
+  EXPECT_EQ("val3", GetValue(kPref1, false));
+  EXPECT_EQ("val5", GetValue(kPref2, false));
+  EXPECT_EQ("val8", GetValue(kPref3, false));
+}
+
+TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValueIncognito) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  EXPECT_EQ("val1", GetValue(kPref1, true));
+}
+
+TEST_F(ExtensionPrefValueMapTest, UninstallOnlyExtension) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.UnregisterExtension(kExt1);
+
+  EXPECT_EQ("", GetValue(kPref1, false));
+}
+
+// Tests uninstalling an extension that wasn't winning for any preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallIrrelevantExtension) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.RegisterExtension(kExt2, CreateTime(10), true);
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+
+  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val3"));
+  epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val4"));
+
+  epvm_.UnregisterExtension(kExt1);
+
+  EXPECT_EQ("val2", GetValue(kPref1, false));
+  EXPECT_EQ("val4", GetValue(kPref2, false));
+}
+
+// Tests uninstalling an extension that was winning for all preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromTop) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+  epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
+
+  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
+  epvm_.SetExtensionPref(kExt3, kPref2, false, CreateVal("val5"));
+
+  epvm_.UnregisterExtension(kExt3);
+
+  EXPECT_EQ("val2", GetValue(kPref1, false));
+  EXPECT_EQ("val4", GetValue(kPref2, false));
+}
+
+// Tests uninstalling an extension that was winning for only some preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromMiddle) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+  epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
+
+  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
+  epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val5"));
+
+  epvm_.SetExtensionPref(kExt1, kPref3, false, CreateVal("val6"));
+
+  epvm_.SetExtensionPref(kExt2, kPref4, false, CreateVal("val7"));
+
+  epvm_.UnregisterExtension(kExt2);
+
+  EXPECT_EQ("val3", GetValue(kPref1, false));
+  EXPECT_EQ("val4", GetValue(kPref2, false));
+  EXPECT_EQ("val6", GetValue(kPref3, false));
+  EXPECT_EQ("", GetValue(kPref4, false));
+}
+
+// Tests triggering of notifications to registered observers.
+TEST_F(ExtensionPrefValueMapTest, NotifyWhenNeeded) {
+  using testing::_;
+  using testing::Mock;
+  using testing::StrEq;
+
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+  ExtensionPrefValueMapObserverMock observer;
+  epvm_.AddObserver(&observer);
+
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Write the same value again.
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Override incognito value.
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+  epvm_.SetExtensionPref(kExt1, kPref1, true, CreateVal("val2"));
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Override non-incognito value.
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val3"));
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Disable.
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+  epvm_.SetExtensionState(kExt1, false);
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Enable.
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+  epvm_.SetExtensionState(kExt1, true);
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Uninstall
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+  epvm_.UnregisterExtension(kExt1);
+  Mock::VerifyAndClearExpectations(&observer);
+
+  epvm_.RemoveObserver(&observer);
+
+  // Write new value --> no notification after removing observer.
+  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val4"));
+  Mock::VerifyAndClearExpectations(&observer);
+}
+
+// Tests disabling an extension.
+TEST_F(ExtensionPrefValueMapTest, DisableExt) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.SetExtensionState(kExt1, false);
+  EXPECT_EQ("", GetValue(kPref1, false));
+}
+
+// Tests disabling and reenabling an extension.
+TEST_F(ExtensionPrefValueMapTest, ReenableExt) {
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+  epvm_.SetExtensionState(kExt1, false);
+  epvm_.SetExtensionState(kExt1, true);
+  EXPECT_EQ("val1", GetValue(kPref1, false));
+}
+
+struct OverrideIncognitoTestCase {
+  OverrideIncognitoTestCase(int val_ext1_regular,
+                            int val_ext1_incognito,
+                            int val_ext2_regular,
+                            int val_ext2_incognito,
+                            int effective_value_regular,
+                            int effective_value_incognito)
+      : val_ext1_regular_(val_ext1_regular),
+        val_ext1_incognito_(val_ext1_incognito),
+        val_ext2_regular_(val_ext2_regular),
+        val_ext2_incognito_(val_ext2_incognito),
+        effective_value_regular_(effective_value_regular),
+        effective_value_incognito_(effective_value_incognito) {}
+
+  int val_ext1_regular_;           // pref value of extension 1
+  int val_ext1_incognito_;         // pref value of extension 1 incognito
+  int val_ext2_regular_;           // pref value of extension 2
+  int val_ext2_incognito_;         // pref value of extension 2 incognito
+  int effective_value_regular_;    // desired winner regular
+  int effective_value_incognito_;  // desired winner incognito
+};
+
+class ExtensionPrefValueMapTestIncognitoTests
+    : public ExtensionPrefValueMapTestBase<
+          testing::TestWithParam<OverrideIncognitoTestCase> > {
+};
+
+TEST_P(ExtensionPrefValueMapTestIncognitoTests, OverrideIncognito) {
+  OverrideIncognitoTestCase test = GetParam();
+  const char* strings[] = {
+      "undefined",
+      "val1",
+      "val2",
+      "val3",
+      "val4"
+  };
+
+  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+  if (test.val_ext1_regular_) {
+    epvm_.SetExtensionPref(kExt1, kPref1, false,
+                           CreateVal(strings[test.val_ext1_regular_]));
+  }
+  if (test.val_ext1_incognito_) {
+    epvm_.SetExtensionPref(kExt1, kPref1, true,
+                           CreateVal(strings[test.val_ext1_incognito_]));
+  }
+  if (test.val_ext2_regular_) {
+    epvm_.SetExtensionPref(kExt2, kPref1, false,
+                           CreateVal(strings[test.val_ext2_regular_]));
+  }
+  if (test.val_ext2_incognito_) {
+    epvm_.SetExtensionPref(kExt2, kPref1, true,
+                           CreateVal(strings[test.val_ext2_incognito_]));
+  }
+  std::string actual;
+  EXPECT_EQ(strings[test.effective_value_regular_], GetValue(kPref1, false));
+  EXPECT_EQ(strings[test.effective_value_incognito_], GetValue(kPref1, true));
+  epvm_.UnregisterExtension(kExt1);
+  epvm_.UnregisterExtension(kExt2);
+}
+
+INSTANTIATE_TEST_CASE_P(
+    ExtensionPrefValueMapTestIncognitoTestsInstance,
+    ExtensionPrefValueMapTestIncognitoTests,
+    testing::Values(
+        // e.g. (1, 0, 0, 4,  1, 4), means:
+        // ext1 regular is set to "val1", ext2 incognito is set to "val4"
+        // --> the winning regular value is "val1", the winning incognito
+        //     value is "val4".
+        OverrideIncognitoTestCase(1, 0, 0, 0,  1, 1),
+        OverrideIncognitoTestCase(1, 2, 0, 0,  1, 2),
+        OverrideIncognitoTestCase(1, 0, 3, 0,  3, 3),
+        OverrideIncognitoTestCase(1, 0, 0, 4,  1, 4),
+        // The last 3 in the following line is intentional!
+        OverrideIncognitoTestCase(1, 2, 3, 0,  3, 3),
+        OverrideIncognitoTestCase(1, 2, 0, 4,  1, 4),
+        OverrideIncognitoTestCase(1, 2, 3, 4,  3, 4)));
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index 1f128ab..c358dd6 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -141,12 +141,13 @@
 
 }  // namespace
 
-ExtensionPrefs::ExtensionPrefs(PrefService* prefs,
-                               const FilePath& root_dir,
-                               ExtensionPrefStore* pref_store)
+ExtensionPrefs::ExtensionPrefs(
+    PrefService* prefs,
+    const FilePath& root_dir,
+    ExtensionPrefValueMap* extension_pref_value_map)
     : prefs_(prefs),
       install_directory_(root_dir),
-      pref_store_(pref_store) {
+      extension_pref_value_map_(extension_pref_value_map) {
   // TODO(asargent) - Remove this in a couple of months. (See comment above
   // CleanupBadExtensionKeys).
   CleanupBadExtensionKeys(prefs_);
@@ -239,8 +240,7 @@
 DictionaryValue* ExtensionPrefs::CopyCurrentExtensions() {
   const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
   if (extensions) {
-    DictionaryValue* copy =
-        static_cast<DictionaryValue*>(extensions->DeepCopy());
+    DictionaryValue* copy = extensions->DeepCopy();
     MakePathsAbsolute(copy);
     return copy;
   }
@@ -611,23 +611,51 @@
 extension_misc::LaunchContainer ExtensionPrefs::GetLaunchContainer(
     const Extension* extension,
     ExtensionPrefs::LaunchType default_pref_value) {
-  extension_misc::LaunchContainer launch_container =
+  extension_misc::LaunchContainer manifest_launch_container =
       extension->launch_container();
 
-  // Apps with app.launch.container = 'panel' should always
-  // open in a panel.
-  if (launch_container == extension_misc::LAUNCH_PANEL)
-    return extension_misc::LAUNCH_PANEL;
+  const extension_misc::LaunchContainer kInvalidLaunchContainer =
+      static_cast<extension_misc::LaunchContainer>(-1);
 
-  ExtensionPrefs::LaunchType prefs_launch_type =
-      GetLaunchType(extension->id(), default_pref_value);
+  extension_misc::LaunchContainer result = kInvalidLaunchContainer;
 
-  // If the user chose to open in a window, then launch in one.
-  if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW)
-    return extension_misc::LAUNCH_WINDOW;
+  if (manifest_launch_container == extension_misc::LAUNCH_PANEL) {
+    // Apps with app.launch.container = 'panel' should always
+    // open in a panel.
+    result = extension_misc::LAUNCH_PANEL;
 
-  // Otherwise, use the container the extension chose.
-  return launch_container;
+  } else if (manifest_launch_container == extension_misc::LAUNCH_TAB) {
+    // Look for prefs that indicate the user's choice of launch
+    // container.  The app's menu on the NTP provides a UI to set
+    // this preference.  If no preference is set, |default_pref_value|
+    // is used.
+    ExtensionPrefs::LaunchType prefs_launch_type =
+        GetLaunchType(extension->id(), default_pref_value);
+
+    if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW) {
+      // If the pref is set to launch a window (or no pref is set, and
+      // window opening is the default), make the container a window.
+      result = extension_misc::LAUNCH_WINDOW;
+
+    } else {
+      // All other launch types (tab, pinned, fullscreen) are
+      // implemented as tabs in a window.
+      result = extension_misc::LAUNCH_TAB;
+    }
+  } else {
+    // If a new value for app.launch.container is added, logic
+    // for it should be added here.  extension_misc::LAUNCH_WINDOW
+    // is not present because there is no way to set it in a manifest.
+    NOTREACHED() << manifest_launch_container;
+  }
+
+  // All paths should set |result|.
+  if (result == kInvalidLaunchContainer) {
+    DLOG(FATAL) << "Failed to set a launch container.";
+    result = extension_misc::LAUNCH_TAB;
+  }
+
+  return result;
 }
 
 void ExtensionPrefs::SetLaunchType(const std::string& extension_id,
@@ -697,15 +725,14 @@
   }
   UpdateExtensionPref(id, kPrefAppLaunchIndex,
                       Value::CreateIntegerValue(GetNextAppLaunchIndex()));
+  extension_pref_value_map_->RegisterExtension(
+      id, install_time, initial_state == Extension::ENABLED);
   SavePrefsAndNotify();
 }
 
 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
                                             const Extension::Location& location,
                                             bool external_uninstall) {
-  PrefKeySet pref_keys;
-  GetExtensionControlledPrefKeys(extension_id, &pref_keys);
-
   // For external extensions, we save a preference reminding ourself not to try
   // and install the extension anymore (except when |external_uninstall| is
   // true, which signifies that the registry key was deleted or the pref file
@@ -714,11 +741,10 @@
     UpdateExtensionPref(extension_id, kPrefState,
                         Value::CreateIntegerValue(Extension::KILLBIT));
     SavePrefsAndNotify();
+    extension_pref_value_map_->SetExtensionState(extension_id, false);
   } else {
     DeleteExtensionPrefs(extension_id);
   }
-
-  UpdatePrefStore(pref_keys);
 }
 
 Extension::State ExtensionPrefs::GetExtensionState(
@@ -743,12 +769,10 @@
                                        Extension::State state) {
   UpdateExtensionPref(extension->id(), kPrefState,
                       Value::CreateIntegerValue(state));
-
-  PrefKeySet pref_keys;
-  GetExtensionControlledPrefKeys(extension->id(), &pref_keys);
-  UpdatePrefStore(pref_keys);
-
   SavePrefsAndNotify();
+
+  bool enabled = (state == Extension::ENABLED);
+  extension_pref_value_map_->SetExtensionState(extension->id(), enabled);
 }
 
 bool ExtensionPrefs::GetBrowserActionVisibility(const Extension* extension) {
@@ -828,6 +852,7 @@
     dict->Remove(extension_id, NULL);
     SavePrefsAndNotify();
   }
+  extension_pref_value_map_->UnregisterExtension(extension_id);
 }
 
 DictionaryValue* ExtensionPrefs::GetOrCreateExtensionPref(
@@ -853,18 +878,6 @@
   return extension;
 }
 
-DictionaryValue* ExtensionPrefs::GetExtensionControlledPrefs(
-    const std::string& extension_id) const {
-  DictionaryValue* extension = GetExtensionPref(extension_id);
-  if (!extension) {
-    NOTREACHED();
-    return NULL;
-  }
-  DictionaryValue* preferences = NULL;
-  extension->GetDictionary(kPrefPreferences, &preferences);
-  return preferences;
-}
-
 // Helper function for GetInstalledExtensionsInfo.
 static ExtensionInfo* GetInstalledExtensionInfoImpl(
     DictionaryValue* extension_data,
@@ -1102,6 +1115,17 @@
   return max_value + 1;
 }
 
+void ExtensionPrefs::SetAppLauncherOrder(
+    const std::vector<std::string>& extension_ids) {
+  for (size_t i = 0; i < extension_ids.size(); ++i)
+    SetAppLaunchIndex(extension_ids.at(i), i);
+
+  NotificationService::current()->Notify(
+      NotificationType::EXTENSION_LAUNCHER_REORDERED,
+      Source<ExtensionPrefs>(this),
+      NotificationService::NoDetails());
+}
+
 void ExtensionPrefs::SetUpdateUrlData(const std::string& extension_id,
                                       const std::string& data) {
   DictionaryValue* dictionary = GetExtensionPref(extension_id);
@@ -1135,25 +1159,23 @@
     NOTREACHED();
     return base::Time();
   }
-  std::string install_time_str("0");
-  extension->GetString(kPrefInstallTime, &install_time_str);
+  std::string install_time_str;
+  if (!extension->GetString(kPrefInstallTime, &install_time_str))
+    return base::Time();
   int64 install_time_i64 = 0;
-  base::StringToInt64(install_time_str, &install_time_i64);
-  LOG_IF(ERROR, install_time_i64 == 0)
-      << "Error parsing installation time of an extension.";
+  if (!base::StringToInt64(install_time_str, &install_time_i64))
+    return base::Time();
   return base::Time::FromInternalValue(install_time_i64);
 }
 
-void ExtensionPrefs::GetEnabledExtensions(ExtensionIdSet* out) const {
+void ExtensionPrefs::GetExtensions(ExtensionIdSet* out) {
   CHECK(out);
-  const DictionaryValue* extensions =
-      pref_service()->GetDictionary(kExtensionsPref);
 
-  for (DictionaryValue::key_iterator ext_id = extensions->begin_keys();
-       ext_id != extensions->end_keys(); ++ext_id) {
-    if (GetExtensionState(*ext_id) != Extension::ENABLED)
-      continue;
-    out->push_back(*ext_id);
+  scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
+
+  for (size_t i = 0; i < extensions_info->size(); ++i) {
+    ExtensionInfo* info = extensions_info->at(i).get();
+    out->push_back(info->extension_id);
   }
 }
 
@@ -1167,6 +1189,10 @@
     CHECK(extension);
 
     if (GetInstallTime(*ext_id) == base::Time()) {
+      LOG(INFO) << "Could not parse installation time of extension "
+                << *ext_id << ". It was probably installed before setting "
+                << kPrefInstallTime << " was introduced. Updating "
+                << kPrefInstallTime << " to the current time.";
       const base::Time install_time = GetCurrentTime();
       extension->Set(kPrefInstallTime,
                      Value::CreateStringValue(
@@ -1178,119 +1204,89 @@
     SavePrefsAndNotify();
 }
 
+DictionaryValue* ExtensionPrefs::GetExtensionControlledPrefs(
+    const std::string& extension_id) const {
+  DictionaryValue* source_dict = prefs_->GetMutableDictionary(kExtensionsPref);
+  DictionaryValue* preferences = NULL;
+  std::string key = extension_id + std::string(".") + kPrefPreferences;
+  if (!source_dict->GetDictionary(key, &preferences)) {
+    source_dict->Set(key, new DictionaryValue);
+    bool success = source_dict->GetDictionary(key, &preferences);
+    DCHECK(success);
+  }
+  return preferences;
+}
+
 void ExtensionPrefs::InitPrefStore() {
   // When this is called, the PrefService is initialized and provides access
   // to the user preferences stored in a JSON file.
   ExtensionIdSet extension_ids;
-  GetEnabledExtensions(&extension_ids);
+  GetExtensions(&extension_ids);
   FixMissingPrefs(extension_ids);
 
-  // Collect the unique extension controlled preference keys of all extensions.
-  PrefKeySet ext_controlled_prefs;
+  // Store extension controlled preference values in the
+  // |extension_pref_value_map_|, which then informs the subscribers
+  // (ExtensionPrefStores) about the winning values.
   for (ExtensionIdSet::iterator ext_id = extension_ids.begin();
        ext_id != extension_ids.end(); ++ext_id) {
-    GetExtensionControlledPrefKeys(*ext_id, &ext_controlled_prefs);
-  }
+    extension_pref_value_map_->RegisterExtension(
+        *ext_id,
+        GetInstallTime(*ext_id),
+        GetExtensionState(*ext_id) == Extension::ENABLED);
 
-  // Store winning preference for each extension controlled preference.
-  UpdatePrefStore(ext_controlled_prefs);
-  pref_store_->OnInitializationCompleted();
-}
-
-const Value* ExtensionPrefs::GetWinningExtensionControlledPrefValue(
-    const std::string& key) const {
-  Value *winner = NULL;
-  base::Time winners_install_time = base::Time();
-
-  ExtensionIdSet extension_ids;
-  GetEnabledExtensions(&extension_ids);
-  for (ExtensionIdSet::iterator ext_id = extension_ids.begin();
-       ext_id != extension_ids.end(); ++ext_id) {
-    base::Time extension_install_time = GetInstallTime(*ext_id);
-
-    // We do not need to consider extensions that were installed before the
-    // most recent extension found that provides the requested preference.
-    if (extension_install_time < winners_install_time)
-      continue;
-
-    DictionaryValue* preferences = GetExtensionControlledPrefs(*ext_id);
-    Value *value = NULL;
-    if (preferences && preferences->GetWithoutPathExpansion(key, &value)) {
-      // This extension is more recent than the last one providing this pref.
-      winner = value;
-      winners_install_time = extension_install_time;
+    DictionaryValue* prefs = GetExtensionControlledPrefs(*ext_id);
+    for (DictionaryValue::key_iterator i = prefs->begin_keys();
+         i != prefs->end_keys(); ++i) {
+      Value* value;
+      if (!prefs->GetWithoutPathExpansion(*i, &value))
+        continue;
+      extension_pref_value_map_->SetExtensionPref(
+          *ext_id, *i, false, value->DeepCopy());
     }
   }
 
-  return winner;
+  extension_pref_value_map_->NotifyInitializationCompleted();
 }
 
-void ExtensionPrefs::UpdatePrefStore(
-    const ExtensionPrefs::PrefKeySet& pref_keys) {
-  for (PrefKeySet::const_iterator i = pref_keys.begin();
-       i != pref_keys.end(); ++i) {
-    UpdatePrefStore(*i);
-  }
-}
-
-void ExtensionPrefs::UpdatePrefStore(const std::string& pref_key) {
-  if (pref_store_ == NULL)
-    return;
-  const Value* winning_pref_value =
-      GetWinningExtensionControlledPrefValue(pref_key);
-
-  if (winning_pref_value)
-    pref_store_->SetExtensionPref(pref_key, winning_pref_value->DeepCopy());
-  else
-    pref_store_->RemoveExtensionPref(pref_key);
-}
 
 void ExtensionPrefs::SetExtensionControlledPref(const std::string& extension_id,
                                                 const std::string& pref_key,
+                                                bool incognito,
                                                 Value* value) {
-  scoped_ptr<Value> scoped_value(value);
   DCHECK(pref_service()->FindPreference(pref_key.c_str()))
       << "Extension controlled preference key " << pref_key
       << " not registered.";
-  DictionaryValue* extension_preferences =
-      GetExtensionControlledPrefs(extension_id);
 
-  if (extension_preferences == NULL) {  // May be pruned when writing to disk.
-    DictionaryValue* extension = GetExtensionPref(extension_id);
-    if (extension == NULL) {
-      LOG(ERROR) << "Extension preference for " << extension_id << " undefined";
-      return;
-    }
-    extension_preferences = new DictionaryValue;
-    extension->Set(kPrefPreferences, extension_preferences);
+  if (!incognito) {
+    // Also store in persisted Preferences file to recover after a
+    // browser restart.
+    DictionaryValue* dict = GetExtensionControlledPrefs(extension_id);
+    dict->SetWithoutPathExpansion(pref_key, value->DeepCopy());
+    pref_service()->ScheduleSavePersistentPrefs();
   }
 
-  Value* oldValue = NULL;
-  extension_preferences->GetWithoutPathExpansion(pref_key, &oldValue);
-  bool modified = !Value::Equals(oldValue, scoped_value.get());
-  if (!modified)
-    return;
-
-  if (scoped_value.get() == NULL)
-    extension_preferences->RemoveWithoutPathExpansion(pref_key, NULL);
-  else
-    extension_preferences->SetWithoutPathExpansion(pref_key,
-                                                   scoped_value.release());
-  pref_service()->ScheduleSavePersistentPrefs();
-
-  UpdatePrefStore(pref_key);
+  extension_pref_value_map_->SetExtensionPref(
+      extension_id, pref_key, incognito, value);
 }
 
-void ExtensionPrefs::GetExtensionControlledPrefKeys(
-    const std::string& extension_id, PrefKeySet *out) const {
-  DCHECK(out != NULL);
-  DictionaryValue* ext_prefs = GetExtensionControlledPrefs(extension_id);
-  if (ext_prefs) {
-    for (DictionaryValue::key_iterator i = ext_prefs->begin_keys();
-         i != ext_prefs->end_keys(); ++i) {
-      out->insert(*i);
-    }
+void ExtensionPrefs::RemoveExtensionControlledPref(
+    const std::string& extension_id,
+    const std::string& pref_key,
+    bool incognito) {
+  DCHECK(pref_service()->FindPreference(pref_key.c_str()))
+      << "Extension controlled preference key " << pref_key
+      << " not registered.";
+
+  if (!incognito) {
+    // Also store in persisted Preferences file to recover after a
+    // browser restart.
+    DictionaryValue* dict = GetExtensionControlledPrefs(extension_id);
+    dict->RemoveWithoutPathExpansion(pref_key, NULL);
+    pref_service()->ScheduleSavePersistentPrefs();
   }
+
+  extension_pref_value_map_->RemoveExtensionPref(
+      extension_id, pref_key, incognito);
 }
 
 // static
diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h
index 8c8be82..12ed88a 100644
--- a/chrome/browser/extensions/extension_prefs.h
+++ b/chrome/browser/extensions/extension_prefs.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
 #include "chrome/common/extensions/extension.h"
 #include "googleurl/src/gurl.h"
 
-class ExtensionPrefStore;
+class ExtensionPrefValueMap;
 
 // Class for managing global and per-extension preferences.
 //
@@ -56,12 +56,18 @@
     LAUNCH_PINNED,
     LAUNCH_REGULAR,
     LAUNCH_FULLSCREEN,
-    LAUNCH_WINDOW
+    LAUNCH_WINDOW,
+
+    // Launch an app in the in the way a click on the NTP would,
+    // if no user pref were set.  Update this constant to change
+    // the default for the NTP and chrome.management.launchApp().
+    LAUNCH_DEFAULT = LAUNCH_REGULAR
   };
 
+  // Does not assume ownership of |prefs| and |incognito_prefs|.
   explicit ExtensionPrefs(PrefService* prefs,
                           const FilePath& root_dir,
-                          ExtensionPrefStore* extension_pref_store);
+                          ExtensionPrefValueMap* extension_pref_value_map);
   ~ExtensionPrefs();
 
   // Returns a copy of the Extensions prefs.
@@ -102,8 +108,8 @@
   // Called to change the extension's state when it is enabled/disabled.
   void SetExtensionState(const Extension* extension, Extension::State);
 
-  // Returns all installed and enabled extensions
-  void GetEnabledExtensions(ExtensionIdSet* out) const;
+  // Returns all installed extensions
+  void GetExtensions(ExtensionIdSet* out);
 
   // Getter and setter for browser action visibility.
   bool GetBrowserActionVisibility(const Extension* extension);
@@ -251,6 +257,9 @@
   // highest current application launch index found.
   int GetNextAppLaunchIndex();
 
+  // Sets the order the apps should be displayed in the app launcher.
+  void SetAppLauncherOrder(const std::vector<std::string>& extension_ids);
+
   // The extension's update URL data.  If not empty, the ExtensionUpdater
   // will append a ap= parameter to the URL when checking if a new version
   // of the extension is available.
@@ -263,8 +272,13 @@
   // global the extension wants to override.
   void SetExtensionControlledPref(const std::string& extension_id,
                                   const std::string& pref_key,
+                                  bool incognito,
                                   Value* value);
 
+  void RemoveExtensionControlledPref(const std::string& extension_id,
+                                     const std::string& pref_key,
+                                     bool incognito);
+
   static void RegisterUserPrefs(PrefService* prefs);
 
   // The underlying PrefService.
@@ -335,7 +349,7 @@
   DictionaryValue* GetExtensionPref(const std::string& id) const;
 
   // Returns the dictionary of preferences controlled by the specified extension
-  // or NULL if unknown. All entries in the dictionary contain non-expanded
+  // or creates a new one. All entries in the dictionary contain non-expanded
   // paths.
   DictionaryValue* GetExtensionControlledPrefs(const std::string& id) const;
 
@@ -357,6 +371,8 @@
   void SetLastPingDayImpl(const base::Time& time, DictionaryValue* dictionary);
 
   // Helper method to acquire the installation time of an extension.
+  // Returns base::Time() if the installation time could not be parsed or
+  // found.
   base::Time GetInstallTime(const std::string& extension_id) const;
 
   // Fix missing preference entries in the extensions that are were introduced
@@ -367,32 +383,14 @@
   // pref store.
   void InitPrefStore();
 
-  // Returns the extension controlled preference value of the extension that was
-  // installed most recently.
-  const Value* GetWinningExtensionControlledPrefValue(
-      const std::string& key) const;
-
-  // Executes UpdatePrefStore for all |pref_keys|.
-  void UpdatePrefStore(const PrefKeySet& pref_keys);
-
-  // Finds the most recently installed extension that defines a preference
-  // for |pref_key|, then stores its value in the PrefValueStore's extension
-  // pref store and sends notifications to observers in case the value changed.
-  void UpdatePrefStore(const std::string& pref_key);
-
-  // Retrieves a list of preference keys that the specified extension
-  // intends to manage. Keys are always appended, |out| is not cleared.
-  void GetExtensionControlledPrefKeys(const std::string& extension_id,
-                                      PrefKeySet *out) const;
-
-  // The pref service specific to this set of extension prefs.
+  // The pref service specific to this set of extension prefs. Owned by profile.
   PrefService* prefs_;
 
   // Base extensions install directory.
   FilePath install_directory_;
 
-  // Used to manipulate extension preferences.
-  ExtensionPrefStore* pref_store_;
+  // Weak pointer, owned by Profile.
+  ExtensionPrefValueMap* extension_pref_value_map_;
 
   // The URLs of all of the toolstrips.
   URLList shelf_order_;
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 6b59740..910ee0f 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,6 @@
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/test_extension_prefs.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/notification_details.h"
@@ -22,6 +21,8 @@
 using base::Time;
 using base::TimeDelta;
 
+namespace {
+
 const char kPref1[] = "path1.subpath";
 const char kPref2[] = "path2";
 const char kPref3[] = "path3";
@@ -33,6 +34,8 @@
 const char kDefaultPref3[] = "default pref 3";
 const char kDefaultPref4[] = "default pref 4";
 
+}  // namespace
+
 static void AddPattern(ExtensionExtent* extent, const std::string& pattern) {
   int schemes = URLPattern::SCHEME_ALL;
   extent->AddPattern(URLPattern(schemes, pattern));
@@ -178,7 +181,7 @@
   }
 
   virtual void Verify() {
-    EXPECT_EQ(true, prefs()->DidExtensionEscalatePermissions(extension->id()));
+    EXPECT_TRUE(prefs()->DidExtensionEscalatePermissions(extension->id()));
   }
 
  private:
@@ -564,13 +567,13 @@
     simple_dict.SetString(keys::kName, "unused");
 
     ext1_scoped_ = Extension::Create(
-        prefs_.temp_dir().AppendASCII("ext1_"), Extension::INVALID,
+        prefs_.temp_dir().AppendASCII("ext1_"), Extension::EXTERNAL_PREF,
         simple_dict, false, &error);
     ext2_scoped_ = Extension::Create(
-        prefs_.temp_dir().AppendASCII("ext2_"), Extension::INVALID,
+        prefs_.temp_dir().AppendASCII("ext2_"), Extension::EXTERNAL_PREF,
         simple_dict, false, &error);
     ext3_scoped_ = Extension::Create(
-        prefs_.temp_dir().AppendASCII("ext3_"), Extension::INVALID,
+        prefs_.temp_dir().AppendASCII("ext3_"), Extension::EXTERNAL_PREF,
         simple_dict, false, &error);
 
     ext1_ = ext1_scoped_.get();
@@ -591,21 +594,23 @@
   void InstallExtControlledPref(Extension *ext,
                                 const std::string& key,
                                 Value* val) {
-    // Install extension the first time a preference is set for it.
-    Extension* extensions[] = {ext1_, ext2_, ext3_};
-    for (int i = 0; i < 3; ++i) {
-      if (ext == extensions[i] && !installed[i]) {
-        prefs()->OnExtensionInstalled(ext, Extension::ENABLED, true);
-        installed[i] = true;
-        break;
-      }
-    }
+    EnsureExtensionInstalled(ext);
+    prefs()->SetExtensionControlledPref(ext->id(), key, false, val);
+  }
 
-    prefs()->SetExtensionControlledPref(ext->id(), key, val);
+  void InstallExtControlledPrefIncognito(Extension *ext,
+                                         const std::string& key,
+                                         Value* val) {
+    EnsureExtensionInstalled(ext);
+    prefs()->SetExtensionControlledPref(ext->id(), key, true, val);
+  }
+
+  void InstallExtension(Extension *ext) {
+    EnsureExtensionInstalled(ext);
   }
 
   void UninstallExtension(const std::string& extension_id) {
-    prefs()->OnExtensionUninstalled(extension_id, Extension::INTERNAL, false);
+    EnsureExtensionUninstalled(extension_id);
   }
 
   // Weak references, for convenience.
@@ -617,6 +622,29 @@
   bool installed[3];
 
  private:
+  void EnsureExtensionInstalled(Extension *ext) {
+    // Install extension the first time a preference is set for it.
+    Extension* extensions[] = {ext1_, ext2_, ext3_};
+    for (int i = 0; i < 3; ++i) {
+      if (ext == extensions[i] && !installed[i]) {
+        prefs()->OnExtensionInstalled(ext, Extension::ENABLED, true);
+        installed[i] = true;
+        break;
+      }
+    }
+  }
+
+  void EnsureExtensionUninstalled(const std::string& extension_id) {
+    Extension* extensions[] = {ext1_, ext2_, ext3_};
+    for (int i = 0; i < 3; ++i) {
+      if (extensions[i]->id() == extension_id) {
+        installed[i] = false;
+        break;
+      }
+    }
+    prefs()->OnExtensionUninstalled(extension_id, Extension::INTERNAL, false);
+  }
+
   scoped_refptr<Extension> ext1_scoped_;
   scoped_refptr<Extension> ext2_scoped_;
   scoped_refptr<Extension> ext3_scoped_;
@@ -634,63 +662,40 @@
 };
 TEST_F(ExtensionPrefsInstallOneExtension, ExtensionPrefsInstallOneExtension) {}
 
-// Make sure the last-installed extension wins for each preference.
-class ExtensionPrefsInstallOverwrittenExtensions
+// Check that we forget incognito values after a reload.
+class ExtensionPrefsInstallIncognito
     : public ExtensionPrefsPreferencesBase {
+ public:
+  ExtensionPrefsInstallIncognito() : iteration_(0) {}
+
   virtual void Initialize() {
     InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
-    InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
-    InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val3"));
-
-    InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val4"));
-    InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val5"));
-
-    InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val6"));
-    InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val7"));
-    InstallExtControlledPref(ext1_, kPref3, Value::CreateStringValue("val8"));
-  }
-  virtual void Verify() {
-    std::string actual;
-    actual = prefs()->pref_service()->GetString(kPref1);
-    EXPECT_EQ("val3", actual);
-    actual = prefs()->pref_service()->GetString(kPref2);
-    EXPECT_EQ("val5", actual);
-    actual = prefs()->pref_service()->GetString(kPref3);
-    EXPECT_EQ("val8", actual);
-  }
-};
-TEST_F(ExtensionPrefsInstallOverwrittenExtensions,
-    ExtensionPrefsInstallOverwrittenExtensions) {}
-
-// Make sure the last-installed extension wins even if other extensions set
-// the same or different preferences later.
-class ExtensionPrefsInstallInterleavedExtensions
-    : public ExtensionPrefsPreferencesBase {
-  virtual void Initialize() {
-    InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
-    InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val2"));
-    InstallExtControlledPref(ext3_, kPref3, Value::CreateStringValue("val3"));
-
-    InstallExtControlledPref(ext3_, kPref3, Value::CreateStringValue("val4"));
-    InstallExtControlledPref(ext2_, kPref3, Value::CreateStringValue("val5"));
-    InstallExtControlledPref(ext1_, kPref3, Value::CreateStringValue("val6"));
-
-    InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val7"));
-  }
-  virtual void Verify() {
-    std::string actual;
-    actual = prefs()->pref_service()->GetString(kPref1);
-    EXPECT_EQ("val7", actual);
-    actual = prefs()->pref_service()->GetString(kPref2);
+    InstallExtControlledPrefIncognito(ext1_, kPref1,
+                                      Value::CreateStringValue("val2"));
+    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
+    std::string actual = incog_prefs->GetString(kPref1);
     EXPECT_EQ("val2", actual);
-    actual = prefs()->pref_service()->GetString(kPref3);
-    EXPECT_EQ("val4", actual);
   }
+  virtual void Verify() {
+    // Main pref service shall see only non-incognito settings.
+    std::string actual = prefs()->pref_service()->GetString(kPref1);
+    EXPECT_EQ("val1", actual);
+    // Incognito pref service shall see incognito values only during first run.
+    // Once the pref service was reloaded, all values shall be discarded.
+    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
+    actual = incog_prefs->GetString(kPref1);
+    if (iteration_ == 0) {
+      EXPECT_EQ("val2", actual);
+    } else {
+      EXPECT_EQ("val1", actual);
+    }
+    ++iteration_;
+  }
+  int iteration_;
 };
-TEST_F(ExtensionPrefsInstallInterleavedExtensions,
-    ExtensionPrefsInstallInterleavedExtensions) {}
+TEST_F(ExtensionPrefsInstallIncognito, ExtensionPrefsInstallOneExtension) {}
 
-class ExtensionPrefsUninstallOnlyExtension
+class ExtensionPrefsUninstallExtension
     : public ExtensionPrefsPreferencesBase {
   virtual void Initialize() {
     InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
@@ -706,89 +711,10 @@
     EXPECT_EQ(kDefaultPref2, actual);
   }
 };
-TEST_F(ExtensionPrefsUninstallOnlyExtension,
-    ExtensionPrefsUninstallOnlyExtension) {}
+TEST_F(ExtensionPrefsUninstallExtension,
+    ExtensionPrefsUninstallExtension) {}
 
-// Tests uninstalling an extension that wasn't winning for any preferences.
-class ExtensionPrefsUninstallIrrelevantExtension
-    : public ExtensionPrefsPreferencesBase {
-  virtual void Initialize() {
-    InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
-    InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
-
-    InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val3"));
-    InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val4"));
-
-    UninstallExtension(ext1_->id());
-  }
-  virtual void Verify() {
-    std::string actual;
-    actual = prefs()->pref_service()->GetString(kPref1);
-    EXPECT_EQ("val2", actual);
-    actual = prefs()->pref_service()->GetString(kPref2);
-    EXPECT_EQ("val4", actual);
-  }
-};
-TEST_F(ExtensionPrefsUninstallIrrelevantExtension,
-    ExtensionPrefsUninstallIrrelevantExtension) {}
-
-// Tests uninstalling an extension that was winning for all preferences.
-class ExtensionPrefsUninstallExtensionFromTop
-    : public ExtensionPrefsPreferencesBase {
-  virtual void Initialize() {
-    InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
-    InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
-    InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val3"));
-
-    InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val4"));
-    InstallExtControlledPref(ext3_, kPref2, Value::CreateStringValue("val5"));
-
-    UninstallExtension(ext3_->id());
-  }
-  virtual void Verify() {
-    std::string actual;
-    actual = prefs()->pref_service()->GetString(kPref1);
-    EXPECT_EQ("val2", actual);
-    actual = prefs()->pref_service()->GetString(kPref2);
-    EXPECT_EQ("val4", actual);
-  }
-};
-TEST_F(ExtensionPrefsUninstallExtensionFromTop,
-    ExtensionPrefsUninstallExtensionFromTop) {}
-
-// Tests uninstalling an extension that was winning for only some preferences.
-class ExtensionPrefsUninstallExtensionFromMiddle
-    : public ExtensionPrefsPreferencesBase {
-  virtual void Initialize() {
-    InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
-    InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
-    InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val3"));
-
-    InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val4"));
-    InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val5"));
-
-    InstallExtControlledPref(ext1_, kPref3, Value::CreateStringValue("val6"));
-
-    InstallExtControlledPref(ext2_, kPref4, Value::CreateStringValue("val7"));
-
-    UninstallExtension(ext2_->id());
-  }
-  virtual void Verify() {
-    std::string actual;
-    actual = prefs()->pref_service()->GetString(kPref1);
-    EXPECT_EQ("val3", actual);
-    actual = prefs()->pref_service()->GetString(kPref2);
-    EXPECT_EQ("val4", actual);
-    actual = prefs()->pref_service()->GetString(kPref3);
-    EXPECT_EQ("val6", actual);
-    actual = prefs()->pref_service()->GetString(kPref4);
-    EXPECT_EQ(kDefaultPref4, actual);
-  }
-};
-TEST_F(ExtensionPrefsUninstallExtensionFromMiddle,
-    ExtensionPrefsUninstallExtensionFromMiddle) {}
-
-// Tests triggering of notifications to registered observers
+// Tests triggering of notifications to registered observers.
 class ExtensionPrefsNotifyWhenNeeded
     : public ExtensionPrefsPreferencesBase {
   virtual void Initialize() {
@@ -796,28 +722,58 @@
     using testing::Mock;
     using testing::StrEq;
 
-    scoped_ptr<NotificationObserverMock> observer(
-        new NotificationObserverMock());
+    NotificationObserverMock observer;
     PrefChangeRegistrar registrar;
     registrar.Init(prefs()->pref_service());
-    registrar.Add(kPref1, observer.get());
+    registrar.Add(kPref1, &observer);
 
-    EXPECT_CALL(*observer, Observe(_, _, _));
+    NotificationObserverMock incognito_observer;
+    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
+    PrefChangeRegistrar incognito_registrar;
+    incognito_registrar.Init(incog_prefs.get());
+    incognito_registrar.Add(kPref1, &incognito_observer);
+
+    // Write value and check notification.
+    EXPECT_CALL(observer, Observe(_, _, _));
+    EXPECT_CALL(incognito_observer, Observe(_, _, _));
     InstallExtControlledPref(ext1_, kPref1,
         Value::CreateStringValue("https://www.chromium.org"));
-    Mock::VerifyAndClearExpectations(observer.get());
+    Mock::VerifyAndClearExpectations(&observer);
+    Mock::VerifyAndClearExpectations(&incognito_observer);
 
-    EXPECT_CALL(*observer, Observe(_, _, _)).Times(0);
+    // Write same value.
+    EXPECT_CALL(observer, Observe(_, _, _)).Times(0);
+    EXPECT_CALL(incognito_observer, Observe(_, _, _)).Times(0);
     InstallExtControlledPref(ext1_, kPref1,
         Value::CreateStringValue("https://www.chromium.org"));
-    Mock::VerifyAndClearExpectations(observer.get());
+    Mock::VerifyAndClearExpectations(&observer);
+    Mock::VerifyAndClearExpectations(&incognito_observer);
 
-    EXPECT_CALL(*observer, Observe(_, _, _)).Times(2);
+    // Change value.
+    EXPECT_CALL(observer, Observe(_, _, _));
+    EXPECT_CALL(incognito_observer, Observe(_, _, _));
     InstallExtControlledPref(ext1_, kPref1,
         Value::CreateStringValue("chrome://newtab"));
+    Mock::VerifyAndClearExpectations(&observer);
+    Mock::VerifyAndClearExpectations(&incognito_observer);
 
+    // Change only incognito value.
+    EXPECT_CALL(observer, Observe(_, _, _)).Times(0);
+    EXPECT_CALL(incognito_observer, Observe(_, _, _));
+    InstallExtControlledPrefIncognito(ext1_, kPref1,
+        Value::CreateStringValue("chrome://newtab2"));
+    Mock::VerifyAndClearExpectations(&observer);
+    Mock::VerifyAndClearExpectations(&incognito_observer);
+
+    // Uninstall.
+    EXPECT_CALL(observer, Observe(_, _, _));
+    EXPECT_CALL(incognito_observer, Observe(_, _, _));
     UninstallExtension(ext1_->id());
-    registrar.Remove(kPref1, observer.get());
+    Mock::VerifyAndClearExpectations(&observer);
+    Mock::VerifyAndClearExpectations(&incognito_observer);
+
+    registrar.Remove(kPref1, &observer);
+    incognito_registrar.Remove(kPref1, &incognito_observer);
   }
   virtual void Verify() {
     std::string actual = prefs()->pref_service()->GetString(kPref1);
@@ -827,7 +783,7 @@
 TEST_F(ExtensionPrefsNotifyWhenNeeded,
     ExtensionPrefsNotifyWhenNeeded) {}
 
-// Tests disabling an extension
+// Tests disabling an extension.
 class ExtensionPrefsDisableExt
     : public ExtensionPrefsPreferencesBase {
   virtual void Initialize() {
@@ -843,7 +799,7 @@
 };
 TEST_F(ExtensionPrefsDisableExt,  ExtensionPrefsDisableExt) {}
 
-// Tests disabling and reenabling an extension
+// Tests disabling and reenabling an extension.
 class ExtensionPrefsReenableExt
     : public ExtensionPrefsPreferencesBase {
   virtual void Initialize() {
@@ -876,15 +832,27 @@
   virtual void Initialize() {
     MockStringValue* v1 = new MockStringValue("https://www.chromium.org");
     MockStringValue* v2 = new MockStringValue("https://www.chromium.org");
+    MockStringValue* v1i = new MockStringValue("https://www.chromium.org");
+    MockStringValue* v2i = new MockStringValue("https://www.chromium.org");
     // Ownership is taken, value shall not be deleted.
     EXPECT_CALL(*v1, Die()).Times(0);
+    EXPECT_CALL(*v1i, Die()).Times(0);
     InstallExtControlledPref(ext1_, kPref1, v1);
+    InstallExtControlledPrefIncognito(ext1_, kPref1, v1i);
     testing::Mock::VerifyAndClearExpectations(v1);
+    testing::Mock::VerifyAndClearExpectations(v1i);
     // Make sure there is no memory leak and both values are deleted.
-    EXPECT_CALL(*v2, Die()).Times(1);
     EXPECT_CALL(*v1, Die()).Times(1);
+    EXPECT_CALL(*v1i, Die()).Times(1);
+    EXPECT_CALL(*v2, Die()).Times(1);
+    EXPECT_CALL(*v2i, Die()).Times(1);
     InstallExtControlledPref(ext1_, kPref1, v2);
+    InstallExtControlledPrefIncognito(ext1_, kPref1, v2i);
     prefs_.RecreateExtensionPrefs();
+    testing::Mock::VerifyAndClearExpectations(v1);
+    testing::Mock::VerifyAndClearExpectations(v1i);
+    testing::Mock::VerifyAndClearExpectations(v2);
+    testing::Mock::VerifyAndClearExpectations(v2i);
   }
 
   virtual void Verify() {
diff --git a/chrome/browser/extensions/extension_processes_api.cc b/chrome/browser/extensions/extension_processes_api.cc
index 5edc2f0..c4a5dd7 100644
--- a/chrome/browser/extensions/extension_processes_api.cc
+++ b/chrome/browser/extensions/extension_processes_api.cc
@@ -35,10 +35,10 @@
   DictionaryValue* result = new DictionaryValue();
   result->SetInteger(keys::kIdKey, process_id);
   result->SetString(keys::kTypeKey, type);
-  result->SetReal(keys::kCpuKey, cpu);
-  result->SetReal(keys::kNetworkKey, static_cast<double>(net));
-  result->SetReal(keys::kPrivateMemoryKey, static_cast<double>(pr_mem));
-  result->SetReal(keys::kSharedMemoryKey, static_cast<double>(sh_mem));
+  result->SetDouble(keys::kCpuKey, cpu);
+  result->SetDouble(keys::kNetworkKey, static_cast<double>(net));
+  result->SetDouble(keys::kPrivateMemoryKey, static_cast<double>(pr_mem));
+  result->SetDouble(keys::kSharedMemoryKey, static_cast<double>(sh_mem));
   return result;
 }
 
diff --git a/chrome/browser/extensions/extension_processes_api.h b/chrome/browser/extensions/extension_processes_api.h
index 5eb54a1..590d27a 100644
--- a/chrome/browser/extensions/extension_processes_api.h
+++ b/chrome/browser/extensions/extension_processes_api.h
@@ -11,7 +11,6 @@
 
 #include "chrome/browser/extensions/extension_function.h"
 #include "chrome/browser/task_manager/task_manager.h"
-#include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
 // Observes the Task Manager and routes the notifications as events to the
diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc
index faa7ae9..91222c7 100644
--- a/chrome/browser/extensions/extension_protocols.cc
+++ b/chrome/browser/extensions/extension_protocols.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "app/resource_bundle.h"
 #include "base/file_path.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -29,6 +28,7 @@
 #include "net/url_request/url_request_error_job.h"
 #include "net/url_request/url_request_file_job.h"
 #include "net/url_request/url_request_simple_job.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -67,6 +67,8 @@
 };
 
 // Returns true if an chrome-extension:// resource should be allowed to load.
+// TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we
+// first need to find a way to get CanLoadInIncognito state into the renderers.
 bool AllowExtensionResourceLoad(net::URLRequest* request,
                                 ChromeURLRequestContext* context,
                                 const std::string& scheme) {
@@ -81,27 +83,6 @@
     return true;
   }
 
-  GURL origin_url(info->frame_origin());
-
-  // chrome:// URLs are always allowed to load chrome-extension:// resources.
-  // The app launcher in the NTP uses this feature, as does dev tools.
-  if (origin_url.SchemeIs(chrome::kChromeDevToolsScheme) ||
-      origin_url.SchemeIs(chrome::kChromeUIScheme))
-    return true;
-
-  // Disallow loading of packaged resources for hosted apps. We don't allow
-  // hybrid hosted/packaged apps. The one exception is access to icons, since
-  // some extensions want to be able to do things like create their own
-  // launchers.
-  if (context->extension_info_map()->
-          ExtensionHasWebExtent(request->url().host())) {
-    if (!context->extension_info_map()->URLIsForExtensionIcon(request->url())) {
-      LOG(ERROR) << "Denying load of " << request->url().spec() << " from "
-                 << "hosted app.";
-      return false;
-    }
-  }
-
   // Don't allow toplevel navigations to extension resources in incognito mode.
   // This is because an extension must run in a single process, and an
   // incognito tab prevents that.
@@ -114,30 +95,7 @@
     return false;
   }
 
-  // Otherwise, pages are allowed to load resources from extensions if the
-  // extension has host permissions to (and therefore could be running script
-  // in, which might need access to the extension resources).
-  //
-  // Exceptions are:
-  // - empty origin (needed for some edge cases when we have empty origins)
-  // - chrome-extension:// (for legacy reasons -- some extensions interop)
-  // - data: (basic HTML notifications use data URLs internally)
-  if (origin_url.is_empty() ||
-      origin_url.SchemeIs(chrome::kExtensionScheme) |
-      origin_url.SchemeIs(chrome::kDataScheme)) {
-    return true;
-  } else {
-    ExtensionExtent host_permissions = context->extension_info_map()->
-        GetEffectiveHostPermissionsForExtension(request->url().host());
-    if (host_permissions.ContainsURL(origin_url)) {
-      return true;
-    } else {
-      LOG(ERROR) << "Denying load of " << request->url().spec() << " from "
-                 << origin_url.spec() << " because the extension does not have "
-                 << "access to the requesting page.";
-      return false;
-    }
-  }
+  return true;
 }
 
 }  // namespace
@@ -151,8 +109,10 @@
       static_cast<ChromeURLRequestContext*>(request->context());
 
   // TODO(mpcomplete): better error code.
-  if (!AllowExtensionResourceLoad(request, context, scheme))
+  if (!AllowExtensionResourceLoad(request, context, scheme)) {
+    LOG(ERROR) << "disallowed in extension protocols";
     return new net::URLRequestErrorJob(request, net::ERR_ADDRESS_UNREACHABLE);
+  }
 
   // chrome-extension://extension-id/resource/path.js
   const std::string& extension_id = request->url().host();
diff --git a/chrome/browser/extensions/extension_proxy_api.cc b/chrome/browser/extensions/extension_proxy_api.cc
index d71c055..6256b39 100644
--- a/chrome/browser/extensions/extension_proxy_api.cc
+++ b/chrome/browser/extensions/extension_proxy_api.cc
@@ -1,16 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_proxy_api.h"
 
 #include "base/string_util.h"
-#include "base/stringprintf.h"
+#include "base/string_tokenizer.h"
 #include "base/values.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/common/pref_names.h"
+#include "net/proxy/proxy_config.h"
 
 namespace {
 
@@ -42,75 +43,91 @@
                               "ftp",
                               "socks" };
 
-}  // namespace
+// String literals in dictionaries used to communicate with extension.
+const char kProxyCfgMode[] = "mode";
+const char kProxyCfgPacScript[] = "pacScript";
+const char kProxyCfgPacScriptUrl[] = "url";
+const char kProxyCfgRules[] = "rules";
+const char kProxyCfgRuleHost[] = "host";
+const char kProxyCfgRulePort[] = "port";
+const char kProxyCfgBypassList[] = "bypassList";
+const char kProxyCfgScheme[] = "scheme";
 
 COMPILE_ASSERT(SCHEME_MAX == SCHEME_SOCKS, SCHEME_MAX_must_equal_SCHEME_SOCKS);
 COMPILE_ASSERT(arraysize(field_name) == SCHEME_MAX + 1,
                field_name_array_is_wrong_size);
 COMPILE_ASSERT(arraysize(scheme_name) == SCHEME_MAX + 1,
                scheme_name_array_is_wrong_size);
+COMPILE_ASSERT(SCHEME_ALL == 0, singleProxy_must_be_first_option);
 
-bool UseCustomProxySettingsFunction::RunImpl() {
-  DictionaryValue* proxy_config;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &proxy_config));
-
-  std::string proxy_mode;
-  proxy_config->GetString("mode", &proxy_mode);
-
-  DictionaryValue* pac_dict = NULL;
-  proxy_config->GetDictionary("pacScript", &pac_dict);
-
-  DictionaryValue* proxy_rules = NULL;
-  proxy_config->GetDictionary("rules", &proxy_rules);
-
-  // TODO(battre,gfeher): Make sure all the preferences get always
-  // overwritten.
-  return ApplyMode(proxy_mode) &&
-      ApplyPacScript(pac_dict) &&
-      ApplyProxyRules(proxy_rules);
-}
-
-bool UseCustomProxySettingsFunction::GetProxyServer(
-    const DictionaryValue* dict, ProxyServer* proxy_server) {
-  dict->GetString("scheme", &proxy_server->scheme);
-  EXTENSION_FUNCTION_VALIDATE(dict->GetString("host", &proxy_server->host));
-  dict->GetInteger("port", &proxy_server->port);
+bool TokenizeToStringList(
+    const std::string& in, const std::string& delims, ListValue** out) {
+  scoped_ptr<ListValue> result(new ListValue);
+  StringTokenizer entries(in, delims);
+  while (entries.GetNext()) {
+    result->Append(Value::CreateStringValue(entries.token()));
+  }
+  *out = result.release();
   return true;
 }
 
-bool UseCustomProxySettingsFunction::ApplyMode(const std::string& mode) {
-  // We take control of the mode preference even if none was specified, so that
-  // all proxy preferences are controlled by the same extension (if not by a
-  // higher-priority source).
-  bool result = true;
-  ProxyPrefs::ProxyMode mode_enum;
-  if (!ProxyPrefs::StringToProxyMode(mode, &mode_enum)) {
-    mode_enum = ProxyPrefs::MODE_SYSTEM;
-    LOG(WARNING) << "Invalid mode for proxy settings: " << mode;
-    result = false;
+bool JoinStringList(
+    ListValue* list, const std::string& joiner, std::string* out) {
+  std::string result;
+  for (size_t i = 0; i < list->GetSize(); ++i) {
+    if (!result.empty())
+      result.append(joiner);
+    // TODO(battre): handle UTF-8 (http://crbug.com/72692)
+    string16 entry;
+    if (!list->GetString(i, &entry))
+      return false;
+    if (!IsStringASCII(entry))
+      return false;
+    result.append(UTF16ToASCII(entry));
   }
-  ApplyPreference(prefs::kProxyMode, Value::CreateIntegerValue(mode_enum));
-  return result;
-}
-
-bool UseCustomProxySettingsFunction::ApplyPacScript(DictionaryValue* pac_dict) {
-  std::string pac_url;
-  if (pac_dict)
-    pac_dict->GetString("url", &pac_url);
-
-  // We take control of the PAC preference even if none was specified, so that
-  // all proxy preferences are controlled by the same extension (if not by a
-  // higher-priority source).
-  ApplyPreference(prefs::kProxyPacUrl, Value::CreateStringValue(pac_url));
+  *out = result;
   return true;
 }
 
-bool UseCustomProxySettingsFunction::ApplyProxyRules(
-    DictionaryValue* proxy_rules) {
-  if (!proxy_rules) {
-    ApplyPreference(prefs::kProxyServer, Value::CreateStringValue(""));
-    return true;
-  }
+// Converts a proxy server description |dict| as passed by the API caller
+// (e.g. for the http proxy in the rules element) and converts it to a
+// ProxyServer. Returns true if successful.
+bool GetProxyServer(const DictionaryValue* dict,
+                    net::ProxyServer::Scheme default_scheme,
+                    net::ProxyServer* proxy_server) {
+  std::string scheme_string;  // optional.
+  // We can safely assume that this is ASCII due to the allowed enumeration
+  // values specified in extension_api.json.
+  dict->GetStringASCII(kProxyCfgScheme, &scheme_string);
+
+  net::ProxyServer::Scheme scheme =
+      net::ProxyServer::GetSchemeFromURI(scheme_string);
+  if (scheme == net::ProxyServer::SCHEME_INVALID)
+    scheme = default_scheme;
+
+  // TODO(battre): handle UTF-8 in hostnames (http://crbug.com/72692)
+  string16 host16;
+  if (!dict->GetString(kProxyCfgRuleHost, &host16))
+    return false;
+  if (!IsStringASCII(host16))
+    return false;
+  std::string host = UTF16ToASCII(host16);
+
+  int port;  // optional.
+  if (!dict->GetInteger(kProxyCfgRulePort, &port))
+    port = net::ProxyServer::GetDefaultPortForScheme(scheme);
+
+  *proxy_server = net::ProxyServer(scheme, net::HostPortPair(host, port));
+
+  return true;
+}
+
+// Converts a proxy "rules" element passed by the API caller into a proxy
+// configuration string that can be used by the proxy subsystem (see
+// proxy_config.h). Returns true if successful.
+bool GetProxyRules(DictionaryValue* proxy_rules, std::string* out) {
+  if (!proxy_rules)
+    return false;
 
   // Local data into which the parameters will be parsed. has_proxy describes
   // whether a setting was found for the scheme; proxy_dict holds the
@@ -118,7 +135,7 @@
   // proxy_server holds ProxyServer structs containing those descriptions.
   bool has_proxy[SCHEME_MAX + 1];
   DictionaryValue* proxy_dict[SCHEME_MAX + 1];
-  ProxyServer proxy_server[SCHEME_MAX + 1];
+  net::ProxyServer proxy_server[SCHEME_MAX + 1];
 
   // Looking for all possible proxy types is inefficient if we have a
   // singleProxy that will supersede per-URL proxies, but it's worth it to keep
@@ -126,50 +143,339 @@
   for (size_t i = 0; i <= SCHEME_MAX; ++i) {
     has_proxy[i] = proxy_rules->GetDictionary(field_name[i], &proxy_dict[i]);
     if (has_proxy[i]) {
-      if (!GetProxyServer(proxy_dict[i], &proxy_server[i]))
+      net::ProxyServer::Scheme default_scheme =
+          (i != SCHEME_SOCKS) ? net::ProxyServer::SCHEME_HTTP
+                              : net::ProxyServer::SCHEME_SOCKS5;
+      if (!GetProxyServer(proxy_dict[i], default_scheme, &proxy_server[i]))
         return false;
     }
   }
 
-  // A single proxy supersedes individual HTTP, HTTPS, and FTP proxies.
+  // Handle case that only singleProxy is specified.
   if (has_proxy[SCHEME_ALL]) {
-    proxy_server[SCHEME_HTTP] = proxy_server[SCHEME_ALL];
-    proxy_server[SCHEME_HTTPS] = proxy_server[SCHEME_ALL];
-    proxy_server[SCHEME_FTP] = proxy_server[SCHEME_ALL];
-    has_proxy[SCHEME_HTTP] = true;
-    has_proxy[SCHEME_HTTPS] = true;
-    has_proxy[SCHEME_FTP] = true;
-    has_proxy[SCHEME_ALL] = false;
+    for (size_t i = 1; i <= SCHEME_MAX; ++i) {
+      if (has_proxy[i]) {
+        LOG(ERROR) << "Proxy rule for " << field_name[SCHEME_ALL] << " and "
+                   << field_name[i] << " cannot be set at the same time.";
+        return false;
+      }
+    }
+    *out = proxy_server[SCHEME_ALL].ToURI();
+    return true;
   }
 
-  // TODO(pamg): Ensure that if a value is empty, that means "don't use a proxy
-  // for this scheme".
+  // Handle case that anything but singleProxy is specified.
 
   // Build the proxy preference string.
   std::string proxy_pref;
-  for (size_t i = 0; i <= SCHEME_MAX; ++i) {
+  for (size_t i = 1; i <= SCHEME_MAX; ++i) {
     if (has_proxy[i]) {
       // http=foopy:4010;ftp=socks://foopy2:80
       if (!proxy_pref.empty())
         proxy_pref.append(";");
       proxy_pref.append(scheme_name[i]);
       proxy_pref.append("=");
-      proxy_pref.append(proxy_server[i].scheme);
-      proxy_pref.append("://");
-      proxy_pref.append(proxy_server[i].host);
-      if (proxy_server[i].port != ProxyServer::INVALID_PORT) {
-        proxy_pref.append(":");
-        proxy_pref.append(base::StringPrintf("%d", proxy_server[i].port));
-      }
+      proxy_pref.append(proxy_server[i].ToURI());
     }
   }
 
-  ApplyPreference(prefs::kProxyServer, Value::CreateStringValue(proxy_pref));
+  *out = proxy_pref;
   return true;
 }
 
-void UseCustomProxySettingsFunction::ApplyPreference(const char* pref_path,
-                                                     Value* pref_value) {
-  profile()->GetExtensionService()->extension_prefs()
-      ->SetExtensionControlledPref(extension_id(), pref_path, pref_value);
+// Creates a string of the "bypassList" entries of a ProxyRules object (see API
+// documentation) by joining the elements with commas.
+// Returns true if successful (i.e. string could be delivered or no "bypassList"
+// exists in the |proxy_rules|).
+bool GetBypassList(DictionaryValue* proxy_rules, std::string* out) {
+  if (!proxy_rules)
+    return false;
+
+  ListValue* bypass_list;
+  if (!proxy_rules->HasKey(kProxyCfgBypassList)) {
+    *out = "";
+    return true;
+  }
+  if (!proxy_rules->GetList(kProxyCfgBypassList, &bypass_list))
+    return false;
+
+  return JoinStringList(bypass_list, ",", out);
+}
+
+}  // namespace
+
+void ProxySettingsFunction::ApplyPreference(const char* pref_path,
+                                            Value* pref_value,
+                                            bool incognito) {
+  Profile* use_profile = profile();
+  if (use_profile->IsOffTheRecord())
+    use_profile = use_profile->GetOriginalProfile();
+
+  use_profile->GetExtensionService()->extension_prefs()->
+      SetExtensionControlledPref(extension_id(), pref_path, incognito,
+                                 pref_value);
+}
+
+void ProxySettingsFunction::RemovePreference(const char* pref_path,
+                                             bool incognito) {
+  Profile* use_profile = profile();
+  if (use_profile->IsOffTheRecord())
+    use_profile = use_profile->GetOriginalProfile();
+
+  use_profile->GetExtensionService()->extension_prefs()->
+      RemoveExtensionControlledPref(extension_id(), pref_path, incognito);
+}
+
+bool UseCustomProxySettingsFunction::RunImpl() {
+  DictionaryValue* proxy_config;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &proxy_config));
+
+  bool incognito = false;  // Optional argument, defaults to false.
+  if (HasOptionalArgument(1)) {
+    EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &incognito));
+  }
+
+  std::string proxy_mode;
+  // We can safely assume that this is ASCII due to the allowed enumeration
+  // values specified in extension_api.json.
+  proxy_config->GetStringASCII(kProxyCfgMode, &proxy_mode);
+  ProxyPrefs::ProxyMode mode_enum;
+  if (!ProxyPrefs::StringToProxyMode(proxy_mode, &mode_enum)) {
+    LOG(ERROR) << "Invalid mode for proxy settings: " << proxy_mode << ". "
+               << "Setting custom proxy settings failed.";
+    return false;
+  }
+
+  DictionaryValue* pac_dict = NULL;
+  proxy_config->GetDictionary(kProxyCfgPacScript, &pac_dict);
+  // TODO(battre): Handle UTF-8 URLs (http://crbug.com/72692)
+  string16 pac_url16;
+  if (pac_dict && !pac_dict->GetString(kProxyCfgPacScriptUrl, &pac_url16)) {
+    LOG(ERROR) << "'pacScript' requires a 'url' field. "
+               << "Setting custom proxy settings failed.";
+    return false;
+  }
+  if (!IsStringASCII(pac_url16)) {
+    LOG(ERROR) << "Only ASCII URLs are supported, yet";
+    return false;
+  }
+  std::string pac_url = UTF16ToASCII(pac_url16);
+
+  DictionaryValue* proxy_rules = NULL;
+  proxy_config->GetDictionary(kProxyCfgRules, &proxy_rules);
+  std::string proxy_rules_string;
+  if (proxy_rules && !GetProxyRules(proxy_rules, &proxy_rules_string)) {
+    LOG(ERROR) << "Invalid 'rules' specified. "
+               << "Setting custom proxy settings failed.";
+    return false;
+  }
+  std::string bypass_list;
+  if (proxy_rules && !GetBypassList(proxy_rules, &bypass_list)) {
+    LOG(ERROR) << "Invalid 'bypassList' specified. "
+               << "Setting custom proxy settings failed.";
+    return false;
+  }
+
+  DictionaryValue* result_proxy_config = NULL;
+  switch (mode_enum) {
+    case ProxyPrefs::MODE_DIRECT:
+      result_proxy_config = ProxyConfigDictionary::CreateDirect();
+      break;
+    case ProxyPrefs::MODE_AUTO_DETECT:
+      result_proxy_config = ProxyConfigDictionary::CreateAutoDetect();
+      break;
+    case ProxyPrefs::MODE_PAC_SCRIPT: {
+      if (!pac_dict) {
+        LOG(ERROR) << "Proxy mode 'pac_script' requires a 'pacScript' field. "
+                   << "Setting custom proxy settings failed.";
+        return false;
+      }
+      result_proxy_config = ProxyConfigDictionary::CreatePacScript(pac_url);
+      break;
+    }
+    case ProxyPrefs::MODE_FIXED_SERVERS: {
+      if (!proxy_rules) {
+        LOG(ERROR) << "Proxy mode 'fixed_servers' requires a 'rules' field. "
+                   << "Setting custom proxy settings failed.";
+        return false;
+      }
+      result_proxy_config = ProxyConfigDictionary::CreateFixedServers(
+          proxy_rules_string, bypass_list);
+      break;
+    }
+    case ProxyPrefs::MODE_SYSTEM:
+      result_proxy_config = ProxyConfigDictionary::CreateSystem();
+      break;
+    case ProxyPrefs::kModeCount:
+      NOTREACHED();
+  }
+  if (!result_proxy_config)
+    return false;
+
+  ApplyPreference(prefs::kProxy, result_proxy_config, incognito);
+  return true;
+}
+
+bool RemoveCustomProxySettingsFunction::RunImpl() {
+  bool incognito = false;
+  if (HasOptionalArgument(0)) {
+    EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &incognito));
+  }
+
+  RemovePreference(prefs::kProxy, incognito);
+  return true;
+}
+
+bool GetCurrentProxySettingsFunction::RunImpl() {
+  bool incognito = false;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &incognito));
+
+  // This is how it is stored in the PrefStores:
+  const DictionaryValue* proxy_prefs;
+
+  Profile* use_profile = profile();
+  if (use_profile->IsOffTheRecord())
+    use_profile = use_profile->GetOriginalProfile();
+
+  PrefService* prefs = incognito ? use_profile->GetOffTheRecordPrefs()
+                                 : use_profile->GetPrefs();
+  proxy_prefs = prefs->GetDictionary(prefs::kProxy);
+
+  // This is how it is presented to the API caller:
+  scoped_ptr<DictionaryValue> out(new DictionaryValue);
+
+  if (!ConvertToApiFormat(proxy_prefs, out.get()))
+    return false;
+
+  result_.reset(out.release());
+  return true;
+}
+
+bool GetCurrentProxySettingsFunction::ConvertToApiFormat(
+    const DictionaryValue* proxy_prefs,
+    DictionaryValue* api_proxy_config) const {
+  ProxyConfigDictionary dict(proxy_prefs);
+
+  ProxyPrefs::ProxyMode mode;
+  if (!dict.GetMode(&mode)) {
+    LOG(ERROR) << "Cannot determine proxy mode.";
+    return false;
+  }
+  api_proxy_config->SetString(kProxyCfgMode,
+                              ProxyPrefs::ProxyModeToString(mode));
+
+  switch (mode) {
+    case ProxyPrefs::MODE_DIRECT:
+    case ProxyPrefs::MODE_AUTO_DETECT:
+    case ProxyPrefs::MODE_SYSTEM:
+      // These modes have no further parameters.
+      break;
+    case ProxyPrefs::MODE_PAC_SCRIPT: {
+      std::string pac_url;
+      if (!dict.GetPacUrl(&pac_url)) {
+        LOG(ERROR) << "Missing pac url";
+        return false;
+      }
+      DictionaryValue* pac_dict = new DictionaryValue;
+      pac_dict->SetString(kProxyCfgPacScriptUrl, pac_url);
+      api_proxy_config->Set(kProxyCfgPacScript, pac_dict);
+      break;
+    }
+    case ProxyPrefs::MODE_FIXED_SERVERS: {
+      scoped_ptr<DictionaryValue> rules_dict(new DictionaryValue);
+
+      std::string proxy_servers;
+      if (!dict.GetProxyServer(&proxy_servers)) {
+        LOG(ERROR) << "Missing proxy servers in configuration";
+        return false;
+      }
+      if (!ParseRules(proxy_servers, rules_dict.get())) {
+        LOG(ERROR) << "Could not parse proxy rules";
+        return false;
+      }
+
+      bool hasBypassList = dict.HasBypassList();
+      if (hasBypassList) {
+        std::string bypass_list_string;
+        if (!dict.GetBypassList(&bypass_list_string)) {
+          LOG(ERROR) << "Invalid bypassList in configuration";
+          return false;
+        }
+        ListValue* bypass_list = NULL;
+        if (TokenizeToStringList(bypass_list_string, ",;", &bypass_list)) {
+          rules_dict->Set(kProxyCfgBypassList, bypass_list);
+        } else {
+          LOG(ERROR) << "Error parsing bypassList " << bypass_list_string;
+          return false;
+        }
+      }
+      api_proxy_config->Set(kProxyCfgRules, rules_dict.release());
+      break;
+    }
+    case ProxyPrefs::kModeCount:
+      NOTREACHED();
+  }
+  return true;
+}
+
+bool GetCurrentProxySettingsFunction::ParseRules(const std::string& rules,
+                                                 DictionaryValue* out) const {
+  net::ProxyConfig::ProxyRules config;
+  config.ParseFromString(rules);
+  switch (config.type) {
+    case net::ProxyConfig::ProxyRules::TYPE_NO_RULES:
+      return false;
+    case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY:
+      if (config.single_proxy.is_valid()) {
+        out->Set(field_name[SCHEME_ALL],
+                 ConvertToDictionary(config.single_proxy));
+      }
+      break;
+    case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME:
+      if (config.proxy_for_http.is_valid()) {
+        out->Set(field_name[SCHEME_HTTP],
+                 ConvertToDictionary(config.proxy_for_http));
+      }
+      if (config.proxy_for_https.is_valid()) {
+        out->Set(field_name[SCHEME_HTTPS],
+                 ConvertToDictionary(config.proxy_for_https));
+      }
+      if (config.proxy_for_ftp.is_valid()) {
+        out->Set(field_name[SCHEME_FTP],
+                 ConvertToDictionary(config.proxy_for_ftp));
+      }
+      if (config.fallback_proxy.is_valid()) {
+        out->Set(field_name[SCHEME_SOCKS],
+                 ConvertToDictionary(config.fallback_proxy));
+      }
+      COMPILE_ASSERT(SCHEME_MAX == 4, SCHEME_FORGOTTEN);
+      break;
+  }
+  return true;
+}
+
+DictionaryValue* GetCurrentProxySettingsFunction::ConvertToDictionary(
+    const net::ProxyServer& proxy) const {
+  DictionaryValue* out = new DictionaryValue;
+  switch (proxy.scheme()) {
+    case net::ProxyServer::SCHEME_HTTP:
+      out->SetString(kProxyCfgScheme, "http");
+      break;
+    case net::ProxyServer::SCHEME_HTTPS:
+      out->SetString(kProxyCfgScheme, "https");
+      break;
+    case net::ProxyServer::SCHEME_SOCKS4:
+      out->SetString(kProxyCfgScheme, "socks4");
+      break;
+    case net::ProxyServer::SCHEME_SOCKS5:
+      out->SetString(kProxyCfgScheme, "socks5");
+      break;
+    case net::ProxyServer::SCHEME_DIRECT:
+    case net::ProxyServer::SCHEME_INVALID:
+      NOTREACHED();
+      return out;
+  }
+  out->SetString(kProxyCfgRuleHost, proxy.host_port_pair().host());
+  out->SetInteger(kProxyCfgRulePort, proxy.host_port_pair().port());
+  return out;
 }
diff --git a/chrome/browser/extensions/extension_proxy_api.h b/chrome/browser/extensions/extension_proxy_api.h
index d645c44..6c9d3bd 100644
--- a/chrome/browser/extensions/extension_proxy_api.h
+++ b/chrome/browser/extensions/extension_proxy_api.h
@@ -9,36 +9,55 @@
 
 #include "chrome/browser/extensions/extension_function.h"
 
+namespace net {
+class ProxyServer;
+}
+
 class DictionaryValue;
 
-class UseCustomProxySettingsFunction : public SyncExtensionFunction {
+class ProxySettingsFunction : public SyncExtensionFunction {
  public:
-  ~UseCustomProxySettingsFunction() {}
+  virtual ~ProxySettingsFunction() {}
+  virtual bool RunImpl() = 0;
+ protected:
+  // Takes ownership of |pref_value|.
+  void ApplyPreference(
+      const char* pref_path, Value* pref_value, bool incognito);
+  void RemovePreference(const char* pref_path, bool incognito);
+};
+
+class UseCustomProxySettingsFunction : public ProxySettingsFunction {
+ public:
+  virtual ~UseCustomProxySettingsFunction() {}
   virtual bool RunImpl();
 
   DECLARE_EXTENSION_FUNCTION_NAME("experimental.proxy.useCustomProxySettings")
+};
 
+class RemoveCustomProxySettingsFunction : public ProxySettingsFunction {
+ public:
+  virtual ~RemoveCustomProxySettingsFunction() {}
+  virtual bool RunImpl();
+
+  DECLARE_EXTENSION_FUNCTION_NAME(
+      "experimental.proxy.removeCustomProxySettings")
+};
+
+class GetCurrentProxySettingsFunction : public ProxySettingsFunction {
+ public:
+  virtual ~GetCurrentProxySettingsFunction() {}
+  virtual bool RunImpl();
+
+  DECLARE_EXTENSION_FUNCTION_NAME(
+      "experimental.proxy.getCurrentProxySettings")
  private:
-  struct ProxyServer {
-    enum {
-      INVALID_PORT = -1
-    };
-    ProxyServer() : scheme("http"), host(""), port(INVALID_PORT) {}
-
-    // The scheme of the proxy URI itself.
-    std::string scheme;
-    std::string host;
-    int port;
-  };
-
-  bool GetProxyServer(const DictionaryValue* dict, ProxyServer* proxy_server);
-
-  bool ApplyMode(const std::string& mode);
-  bool ApplyPacScript(DictionaryValue* pac_dict);
-  bool ApplyProxyRules(DictionaryValue* proxy_rules);
-
-  // Takes ownership of |pref_value|.
-  void ApplyPreference(const char* pref_path, Value* pref_value);
+  // Convert the representation of a proxy configuration from the format
+  // that is stored in the pref stores to the format that is used by the API.
+  // See ProxyServer type defined in |experimental.proxy|.
+  bool ConvertToApiFormat(const DictionaryValue* proxy_prefs,
+                          DictionaryValue* api_proxy_config) const;
+  bool ParseRules(const std::string& rules, DictionaryValue* out) const;
+  DictionaryValue* ConvertToDictionary(const net::ProxyServer& proxy) const;
 };
 
 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_PROXY_API_H_
diff --git a/chrome/browser/extensions/extension_proxy_apitest.cc b/chrome/browser/extensions/extension_proxy_apitest.cc
index 5537f32..71ddde5 100644
--- a/chrome/browser/extensions/extension_proxy_apitest.cc
+++ b/chrome/browser/extensions/extension_proxy_apitest.cc
@@ -4,15 +4,72 @@
 
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/pref_names.h"
 
+namespace {
+
+const char kNoServer[] = "";
+const char kNoBypass[] = "";
+const char kNoPac[] = "";
+
+}  // namespace
+
+class ProxySettingsApiTest : public ExtensionApiTest {
+ protected:
+  void ValidateSettings(int expected_mode,
+                        const std::string& expected_server,
+                        const std::string& bypass,
+                        const std::string& expected_pac_url,
+                        PrefService* pref_service) {
+    const PrefService::Preference* pref =
+        pref_service->FindPreference(prefs::kProxy);
+    ASSERT_TRUE(pref != NULL);
+    EXPECT_TRUE(pref->IsExtensionControlled());
+
+    ProxyConfigDictionary dict(pref_service->GetDictionary(prefs::kProxy));
+
+    ProxyPrefs::ProxyMode mode;
+    ASSERT_TRUE(dict.GetMode(&mode));
+    EXPECT_EQ(expected_mode, mode);
+
+    std::string value;
+    if (!bypass.empty()) {
+       ASSERT_TRUE(dict.GetBypassList(&value));
+       EXPECT_EQ(bypass, value);
+     } else {
+       EXPECT_FALSE(dict.GetBypassList(&value));
+     }
+
+    if (!expected_pac_url.empty()) {
+       ASSERT_TRUE(dict.GetPacUrl(&value));
+       EXPECT_EQ(expected_pac_url, value);
+     } else {
+       EXPECT_FALSE(dict.GetPacUrl(&value));
+     }
+
+    if (!expected_server.empty()) {
+      ASSERT_TRUE(dict.GetProxyServer(&value));
+      EXPECT_EQ(expected_server, value);
+    } else {
+      EXPECT_FALSE(dict.GetProxyServer(&value));
+    }
+  }
+
+  void ExpectNoSettings(PrefService* pref_service) {
+    const PrefService::Preference* pref =
+        pref_service->FindPreference(prefs::kProxy);
+    ASSERT_TRUE(pref != NULL);
+    EXPECT_FALSE(pref->IsExtensionControlled());
+  }
+};
+
 // Tests direct connection settings.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxyDirectSettings) {
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyDirectSettings) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
@@ -21,30 +78,12 @@
   ASSERT_TRUE(extension);
 
   PrefService* pref_service = browser()->profile()->GetPrefs();
-
-  const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kProxyMode);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
-  int mode = pref_service->GetInteger(prefs::kProxyMode);
-  EXPECT_EQ(ProxyPrefs::MODE_DIRECT, mode);
-
-  // Other proxy prefs should also be set, so they're all controlled from one
-  // place.
-  pref = pref_service->FindPreference(prefs::kProxyPacUrl);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyPacUrl));
-
-  // No manual proxy prefs were set.
-  pref = pref_service->FindPreference(prefs::kProxyServer);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyServer));
+  ValidateSettings(ProxyPrefs::MODE_DIRECT, kNoServer, kNoBypass, kNoPac,
+                   pref_service);
 }
 
 // Tests auto-detect settings.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxyAutoSettings) {
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyAutoSettings) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
@@ -53,24 +92,12 @@
   ASSERT_TRUE(extension);
 
   PrefService* pref_service = browser()->profile()->GetPrefs();
-
-  const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kProxyMode);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
-  int mode = pref_service->GetInteger(prefs::kProxyMode);
-  EXPECT_EQ(ProxyPrefs::MODE_AUTO_DETECT, mode);
-
-  // Other proxy prefs should also be set, so they're all controlled from one
-  // place.
-  pref = pref_service->FindPreference(prefs::kProxyPacUrl);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyPacUrl));
+  ValidateSettings(ProxyPrefs::MODE_AUTO_DETECT, kNoServer, kNoBypass, kNoPac,
+                   pref_service);
 }
 
 // Tests PAC proxy settings.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxyPacScript) {
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyPacScript) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
@@ -79,29 +106,12 @@
   ASSERT_TRUE(extension);
 
   PrefService* pref_service = browser()->profile()->GetPrefs();
-
-  const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kProxyMode);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
-  int mode = pref_service->GetInteger(prefs::kProxyMode);
-  EXPECT_EQ(ProxyPrefs::MODE_PAC_SCRIPT, mode);
-
-  pref = pref_service->FindPreference(prefs::kProxyPacUrl);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
-  std::string pac_url = pref_service->GetString(prefs::kProxyPacUrl);
-  EXPECT_EQ("http://wpad/windows.pac", pac_url);
-
-  // No manual proxy prefs were set.
-  pref = pref_service->FindPreference(prefs::kProxyServer);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyServer));
+  ValidateSettings(ProxyPrefs::MODE_PAC_SCRIPT, kNoServer, kNoBypass,
+                   "http://wpad/windows.pac", pref_service);
 }
 
 // Tests setting a single proxy to cover all schemes.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxyFixedSingle) {
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyFixedSingle) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
@@ -110,34 +120,15 @@
   ASSERT_TRUE(extension);
 
   PrefService* pref_service = browser()->profile()->GetPrefs();
-
-  // There should be no values superseding the extension-set proxy in this test.
-  const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kProxyServer);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
-  std::string proxy_server = pref_service->GetString(prefs::kProxyServer);
-  EXPECT_EQ("http=http://127.0.0.1:100;"
-            "https=http://127.0.0.1:100;"
-            "ftp=http://127.0.0.1:100;"
-            "socks=http://9.9.9.9", proxy_server);
-
-  // Other proxy prefs should also be set, so they're all controlled from one
-  // place.
-  pref = pref_service->FindPreference(prefs::kProxyMode);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ(ProxyPrefs::MODE_FIXED_SERVERS,
-            pref_service->GetInteger(prefs::kProxyMode));
-
-  pref = pref_service->FindPreference(prefs::kProxyPacUrl);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyPacUrl));
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                 "127.0.0.1:100",
+                 kNoBypass,
+                 kNoPac,
+                 pref_service);
 }
 
 // Tests setting to use the system's proxy settings.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxySystem) {
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxySystem) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
@@ -146,31 +137,12 @@
   ASSERT_TRUE(extension);
 
   PrefService* pref_service = browser()->profile()->GetPrefs();
-
-  // There should be no values superseding the extension-set proxy in this test.
-  const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kProxyMode);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
-  int proxy_server_mode = pref_service->GetInteger(prefs::kProxyMode);
-  EXPECT_EQ(ProxyPrefs::MODE_SYSTEM, proxy_server_mode);
-
-  // Other proxy prefs should also be set, so they're all controlled from one
-  // place.
-  pref = pref_service->FindPreference(prefs::kProxyPacUrl);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyPacUrl));
-
-  // No manual proxy prefs were set.
-  pref = pref_service->FindPreference(prefs::kProxyServer);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyServer));
+  ValidateSettings(ProxyPrefs::MODE_SYSTEM, kNoServer, kNoBypass, kNoPac,
+                   pref_service);
 }
 
 // Tests setting separate proxies for each scheme.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxyFixedIndividual) {
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyFixedIndividual) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
@@ -179,29 +151,118 @@
   ASSERT_TRUE(extension);
 
   PrefService* pref_service = browser()->profile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=1.1.1.1:80;"  // http:// is pruned.
+                       "https=2.2.2.2:80;"  // http:// is pruned.
+                       "ftp=3.3.3.3:9000;"  // http:// is pruned.
+                       "socks=socks4://4.4.4.4:9090",
+                   kNoBypass,
+                   kNoPac,
+                   pref_service);
 
-  // There should be no values superseding the extension-set proxy in this test.
-  const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kProxyServer);
-  ASSERT_TRUE(pref != NULL);
-  ASSERT_TRUE(pref->IsExtensionControlled());
+  // Now check the incognito preferences.
+  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=1.1.1.1:80;"
+                       "https=2.2.2.2:80;"
+                       "ftp=3.3.3.3:9000;"
+                       "socks=socks4://4.4.4.4:9090",
+                   kNoBypass,
+                   kNoPac,
+                   pref_service);
+}
 
-  std::string proxy_server = pref_service->GetString(prefs::kProxyServer);
-  EXPECT_EQ("http=http://1.1.1.1;"
-            "https=socks://2.2.2.2;"
-            "ftp=http://3.3.3.3:9000;"
-            "socks=socks4://4.4.4.4:9090", proxy_server);
+// Tests setting values only for incognito mode
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
+    ProxyFixedIndividualIncognitoOnly) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExperimentalExtensionApis);
 
-  // Other proxy prefs should also be set, so they're all controlled from one
-  // place.
-  pref = pref_service->FindPreference(prefs::kProxyMode);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ(ProxyPrefs::MODE_FIXED_SERVERS,
-            pref_service->GetInteger(prefs::kProxyMode));
+  ASSERT_TRUE(RunExtensionTest("proxy/individual_incognito_only")) << message_;
+  const Extension* extension = GetSingleLoadedExtension();
+  ASSERT_TRUE(extension);
 
-  pref = pref_service->FindPreference(prefs::kProxyPacUrl);
-  ASSERT_TRUE(pref != NULL);
-  EXPECT_TRUE(pref->IsExtensionControlled());
-  EXPECT_EQ("", pref_service->GetString(prefs::kProxyPacUrl));
+  PrefService* pref_service = browser()->profile()->GetPrefs();
+  ExpectNoSettings(pref_service);
+
+  // Now check the incognito preferences.
+  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=1.1.1.1:80;"
+                       "https=socks5://2.2.2.2:1080;"  // socks5 equals socks.
+                       "ftp=3.3.3.3:9000;"
+                       "socks=socks4://4.4.4.4:9090",
+                   kNoBypass,
+                   kNoPac,
+                   pref_service);
+}
+
+// Tests setting values also for incognito mode
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
+    ProxyFixedIndividualIncognitoAlso) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExperimentalExtensionApis);
+
+  ASSERT_TRUE(RunExtensionTest("proxy/individual_incognito_also")) << message_;
+  const Extension* extension = GetSingleLoadedExtension();
+  ASSERT_TRUE(extension);
+
+  PrefService* pref_service = browser()->profile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=1.1.1.1:80;"
+                       "https=socks5://2.2.2.2:1080;"
+                       "ftp=3.3.3.3:9000;"
+                       "socks=socks4://4.4.4.4:9090",
+                   kNoBypass,
+                   kNoPac,
+                   pref_service);
+
+  // Now check the incognito preferences.
+  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=5.5.5.5:80;"
+                       "https=socks5://6.6.6.6:1080;"
+                       "ftp=7.7.7.7:9000;"
+                       "socks=socks4://8.8.8.8:9090",
+                   kNoBypass,
+                   kNoPac,
+                   pref_service);
+}
+
+// Tests setting and unsetting values
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyFixedIndividualRemove) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExperimentalExtensionApis);
+
+  ASSERT_TRUE(RunExtensionTest("proxy/individual_remove")) << message_;
+  const Extension* extension = GetSingleLoadedExtension();
+  ASSERT_TRUE(extension);
+
+  PrefService* pref_service = browser()->profile()->GetPrefs();
+  ExpectNoSettings(pref_service);
+}
+
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
+    ProxyBypass) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExperimentalExtensionApis);
+
+  ASSERT_TRUE(RunExtensionTest("proxy/bypass")) << message_;
+  const Extension* extension = GetSingleLoadedExtension();
+  ASSERT_TRUE(extension);
+
+  PrefService* pref_service = browser()->profile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=1.1.1.1:80",
+                   "localhost,::1,foo.bar,<local>",
+                   kNoPac,
+                   pref_service);
+
+  // Now check the incognito preferences.
+  pref_service = browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
+  ValidateSettings(ProxyPrefs::MODE_FIXED_SERVERS,
+                   "http=1.1.1.1:80",
+                   "localhost,::1,foo.bar,<local>",
+                   kNoPac,
+                   pref_service);
 }
diff --git a/chrome/browser/extensions/extension_resource_request_policy_apitest.cc b/chrome/browser/extensions/extension_resource_request_policy_apitest.cc
new file mode 100644
index 0000000..f6f14ab
--- /dev/null
+++ b/chrome/browser/extensions/extension_resource_request_policy_apitest.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/ui_test_utils.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/mock_host_resolver.h"
+
+class ExtensionResourceRequestPolicyTest : public ExtensionApiTest {
+};
+
+// Note, this mostly tests the logic of chrome/renderer/extensions/
+// extension_resource_request_policy.*, but we have it as a browser test so that
+// can make sure it works end-to-end.
+IN_PROC_BROWSER_TEST_F(ExtensionResourceRequestPolicyTest, OriginPrivileges) {
+  host_resolver()->AddRule("*", "127.0.0.1");
+  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(LoadExtension(test_data_dir_
+      .AppendASCII("extension_resource_request_policy")
+      .AppendASCII("extension")));
+
+  GURL web_resource(
+      test_server()->GetURL(
+          "files/extensions/api_test/extension_resource_request_policy/"
+          "index.html"));
+
+  std::string host_a("a.com");
+  GURL::Replacements make_host_a_com;
+  make_host_a_com.SetHostStr(host_a);
+
+  std::string host_b("b.com");
+  GURL::Replacements make_host_b_com;
+  make_host_b_com.SetHostStr(host_b);
+
+  // A web host that has permission.
+  ui_test_utils::NavigateToURL(
+      browser(), web_resource.ReplaceComponents(make_host_a_com));
+  std::string result;
+  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
+    browser()->GetSelectedTabContents()->render_view_host(), L"",
+      L"window.domAutomationController.send(document.title)",
+    &result));
+  EXPECT_EQ(result, "Loaded");
+
+  // A web host that loads a non-existent extension.
+  GURL non_existent_extension(
+      test_server()->GetURL(
+          "files/extensions/api_test/extension_resource_request_policy/"
+          "non_existent_extension.html"));
+  ui_test_utils::NavigateToURL(browser(), non_existent_extension);
+  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
+    browser()->GetSelectedTabContents()->render_view_host(), L"",
+      L"window.domAutomationController.send(document.title)",
+    &result));
+  EXPECT_EQ(result, "Image failed to load");
+
+  // A data URL. Data URLs should always be able to load chrome-extension://
+  // resources.
+  std::string file_source;
+  ASSERT_TRUE(file_util::ReadFileToString(
+      test_data_dir_.AppendASCII("extension_resource_request_policy")
+                    .AppendASCII("index.html"), &file_source));
+  ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string("data:text/html;charset=utf-8,") + file_source));
+  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
+      browser()->GetSelectedTabContents()->render_view_host(), L"",
+      L"window.domAutomationController.send(document.title)",
+      &result));
+  EXPECT_EQ(result, "Loaded");
+
+  // A different extension. Extensions should always be able to load each
+  // other's resources.
+  ASSERT_TRUE(LoadExtension(test_data_dir_
+      .AppendASCII("extension_resource_request_policy")
+      .AppendASCII("extension2")));
+  ui_test_utils::NavigateToURL(
+      browser(),
+      GURL("chrome-extension://pbkkcbgdkliohhfaeefcijaghglkahja/index.html"));
+  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
+      browser()->GetSelectedTabContents()->render_view_host(), L"",
+      L"window.domAutomationController.send(document.title)",
+      &result));
+  EXPECT_EQ(result, "Loaded");
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionResourceRequestPolicyTest,
+                       ExtensionCanLoadHostedAppIcons) {
+  ASSERT_TRUE(LoadExtension(test_data_dir_
+      .AppendASCII("extension_resource_request_policy")
+      .AppendASCII("extension")));
+
+  ASSERT_TRUE(RunExtensionSubtest(
+      "extension_resource_request_policy/extension2/",
+      "can_load_icons_from_hosted_apps.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionResourceRequestPolicyTest, Audio) {
+  EXPECT_TRUE(RunExtensionSubtest(
+      "extension_resource_request_policy/extension2",
+      "audio.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionResourceRequestPolicyTest, Video) {
+  EXPECT_TRUE(RunExtensionSubtest(
+      "extension_resource_request_policy/extension2",
+      "video.html"));
+}
diff --git a/chrome/browser/extensions/extension_rlz_apitest.cc b/chrome/browser/extensions/extension_rlz_apitest.cc
index efb275a..f7f264d 100644
--- a/chrome/browser/extensions/extension_rlz_apitest.cc
+++ b/chrome/browser/extensions/extension_rlz_apitest.cc
@@ -80,14 +80,14 @@
   ASSERT_TRUE(key.Valid());
 
   DWORD value;
-  ASSERT_TRUE(key.ReadValueDW(L"D3I", &value));
+  ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"D3I", &value));
   ASSERT_EQ(1, value);
-  ASSERT_TRUE(key.ReadValueDW(L"D3S", &value));
+  ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"D3S", &value));
   ASSERT_EQ(1, value);
-  ASSERT_TRUE(key.ReadValueDW(L"D3F", &value));
+  ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"D3F", &value));
   ASSERT_EQ(1, value);
 
-  ASSERT_TRUE(key.ReadValueDW(L"D4I", &value));
+  ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"D4I", &value));
   ASSERT_EQ(1, value);
 
   key.Open(HKEY_CURRENT_USER, L"Software\\Google\\Common\\Rlz\\Events\\D",
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 8140d2b..7b3cba2 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_service.h"
 
 #include <algorithm>
+#include <set>
 
 #include "base/basictypes.h"
 #include "base/command_line.h"
@@ -19,7 +20,6 @@
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "base/values_util.h"
 #include "base/version.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
@@ -33,7 +33,6 @@
 #include "chrome/browser/extensions/extension_browser_event_router.h"
 #include "chrome/browser/extensions/extension_cookies_api.h"
 #include "chrome/browser/extensions/extension_data_deleter.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_history_api.h"
 #include "chrome/browser/extensions/extension_host.h"
@@ -41,10 +40,10 @@
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_processes_api.h"
 #include "chrome/browser/extensions/extension_updater.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/extensions/extension_webnavigation_api.h"
-#include "chrome/browser/extensions/external_extension_provider.h"
-#include "chrome/browser/extensions/external_policy_extension_provider.h"
-#include "chrome/browser/extensions/external_pref_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -67,10 +66,6 @@
 #include "webkit/database/database_tracker.h"
 #include "webkit/database/database_util.h"
 
-#if defined(OS_WIN)
-#include "chrome/browser/extensions/external_registry_extension_provider_win.h"
-#endif
-
 using base::Time;
 
 namespace errors = extension_manifest_errors;
@@ -184,52 +179,20 @@
 // Implements IO for the ExtensionService.
 
 class ExtensionServiceBackend
-    : public base::RefCountedThreadSafe<ExtensionServiceBackend>,
-      public ExternalExtensionProvider::Visitor {
+    : public base::RefCountedThreadSafe<ExtensionServiceBackend> {
  public:
   // |install_directory| is a path where to look for extensions to load.
-  ExtensionServiceBackend(PrefService* prefs,
-                           const FilePath& install_directory);
+  explicit ExtensionServiceBackend(const FilePath& install_directory);
 
   // Loads a single extension from |path| where |path| is the top directory of
   // a specific extension where its manifest file lives.
   // Errors are reported through ExtensionErrorReporter. On success,
-  // OnExtensionLoaded() is called.
+  // AddExtension() is called.
   // TODO(erikkay): It might be useful to be able to load a packed extension
   // (presumably into memory) without installing it.
   void LoadSingleExtension(const FilePath &path,
                            scoped_refptr<ExtensionService> frontend);
 
-  // Check externally updated extensions for updates and install if necessary.
-  // Errors are reported through ExtensionErrorReporter. Succcess is not
-  // reported.
-  void CheckForExternalUpdates(scoped_refptr<ExtensionService> frontend);
-
-  // For the extension in |version_path| with |id|, check to see if it's an
-  // externally managed extension.  If so, tell the frontend to uninstall it.
-  void CheckExternalUninstall(scoped_refptr<ExtensionService> frontend,
-                              const std::string& id);
-
-  // Clear all ExternalExtensionProviders.
-  void ClearProvidersForTesting();
-
-  // Adds an ExternalExtensionProvider for the service to use during testing.
-  // Takes ownership of |test_provider|.
-  void AddProviderForTesting(ExternalExtensionProvider* test_provider);
-
-  // ExternalExtensionProvider::Visitor implementation.
-  virtual void OnExternalExtensionFileFound(const std::string& id,
-                                            const Version* version,
-                                            const FilePath& path,
-                                            Extension::Location location);
-
-  virtual void OnExternalExtensionUpdateUrlFound(const std::string& id,
-                                                 const GURL& update_url,
-                                                 Extension::Location location);
-
-  virtual void UpdateExternalPolicyExtensionProvider(
-      scoped_refptr<RefCountedList> forcelist);
-
  private:
   friend class base::RefCountedThreadSafe<ExtensionServiceBackend>;
 
@@ -261,48 +224,14 @@
   // Whether errors result in noisy alerts.
   bool alert_on_error_;
 
-  // A collection of external extension providers.  Each provider reads
-  // a source of external extension information.  Examples include the
-  // windows registry and external_extensions.json.
-  typedef std::vector<linked_ptr<ExternalExtensionProvider> >
-      ProviderCollection;
-  ProviderCollection external_extension_providers_;
-  linked_ptr<ExternalPolicyExtensionProvider>
-      external_policy_extension_provider_;
-
-  // Set to true by OnExternalExtensionUpdateUrlFound() when an external
-  // extension URL is found.  Used in CheckForExternalUpdates() to see
-  // if an update check is needed to install pending extensions.
-  bool external_extension_added_;
-
   DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend);
 };
 
 ExtensionServiceBackend::ExtensionServiceBackend(
-    PrefService* prefs,
     const FilePath& install_directory)
         : frontend_(NULL),
           install_directory_(install_directory),
-          alert_on_error_(false),
-          external_extension_added_(false) {
-  // TODO(aa): This ends up doing blocking IO on the UI thread because it reads
-  // pref data in the ctor and that is called on the UI thread. Would be better
-  // to re-read data each time we list external extensions, anyway.
-  external_extension_providers_.push_back(
-      linked_ptr<ExternalExtensionProvider>(
-          new ExternalPrefExtensionProvider()));
-#if defined(OS_WIN)
-  external_extension_providers_.push_back(
-      linked_ptr<ExternalExtensionProvider>(
-          new ExternalRegistryExtensionProvider()));
-#endif
-  // The policy-controlled extension provider is also stored in a member
-  // variable so that UpdateExternalPolicyExtensionProvider can access it and
-  // update its extension list later.
-  external_policy_extension_provider_.reset(
-      new ExternalPolicyExtensionProvider(
-          prefs->GetList(prefs::kExtensionInstallForceList)));
-  external_extension_providers_.push_back(external_policy_extension_provider_);
+          alert_on_error_(false) {
 }
 
 ExtensionServiceBackend::~ExtensionServiceBackend() {
@@ -310,7 +239,7 @@
 
 void ExtensionServiceBackend::LoadSingleExtension(
     const FilePath& path_in, scoped_refptr<ExtensionService> frontend) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   frontend_ = frontend;
 
@@ -343,7 +272,7 @@
 
 void ExtensionServiceBackend::ReportExtensionLoadError(
     const FilePath& extension_path, const std::string &error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       NewRunnableMethod(
@@ -352,113 +281,50 @@
           error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_));
 }
 
-// Some extensions will autoupdate themselves externally from Chrome.  These
-// are typically part of some larger client application package.  To support
-// these, the extension will register its location in the the preferences file
-// (and also, on Windows, in the registry) and this code will periodically
-// check that location for a .crx file, which it will then install locally if
-// a new version is available.
-void ExtensionServiceBackend::CheckForExternalUpdates(
-    scoped_refptr<ExtensionService> frontend) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
-  // Note that this installation is intentionally silent (since it didn't
-  // go through the front-end).  Extensions that are registered in this
-  // way are effectively considered 'pre-bundled', and so implicitly
-  // trusted.  In general, if something has HKLM or filesystem access,
-  // they could install an extension manually themselves anyway.
-  alert_on_error_ = false;
-  frontend_ = frontend;
-  external_extension_added_ = false;
-
-  // Ask each external extension provider to give us a call back for each
-  // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
-  ProviderCollection::const_iterator i;
-  for (i = external_extension_providers_.begin();
-       i != external_extension_providers_.end(); ++i) {
-    ExternalExtensionProvider* provider = i->get();
-    provider->VisitRegisteredExtension(this);
-  }
-
-  if (external_extension_added_ && frontend->updater()) {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-            NewRunnableMethod(
-                frontend->updater(), &ExtensionUpdater::CheckNow));
-  }
-}
-
-void ExtensionServiceBackend::CheckExternalUninstall(
-    scoped_refptr<ExtensionService> frontend, const std::string& id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+void ExtensionService::CheckExternalUninstall(const std::string& id) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Check if the providers know about this extension.
   ProviderCollection::const_iterator i;
   for (i = external_extension_providers_.begin();
        i != external_extension_providers_.end(); ++i) {
+    DCHECK(i->get()->IsReady());
     if (i->get()->HasExtension(id))
       return;  // Yup, known extension, don't uninstall.
   }
 
   // This is an external extension that we don't have registered.  Uninstall.
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          frontend.get(), &ExtensionService::UninstallExtension, id, true));
+  UninstallExtension(id, true);
 }
 
-void ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider(
-    scoped_refptr<RefCountedList> forcelist) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  external_policy_extension_provider_->SetPreferences(forcelist->Get());
-}
-
-void ExtensionServiceBackend::ClearProvidersForTesting() {
+void ExtensionService::ClearProvidersForTesting() {
   external_extension_providers_.clear();
 }
 
-void ExtensionServiceBackend::AddProviderForTesting(
-    ExternalExtensionProvider* test_provider) {
-  DCHECK(test_provider);
+void ExtensionService::AddProviderForTesting(
+    ExternalExtensionProviderInterface* test_provider) {
+  CHECK(test_provider);
   external_extension_providers_.push_back(
-      linked_ptr<ExternalExtensionProvider>(test_provider));
+      linked_ptr<ExternalExtensionProviderInterface>(test_provider));
 }
 
-void ExtensionServiceBackend::OnExternalExtensionFileFound(
-    const std::string& id, const Version* version, const FilePath& path,
-    Extension::Location location) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
-  DCHECK(version);
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          frontend_, &ExtensionService::OnExternalExtensionFileFound, id,
-          version->GetString(), path, location));
-}
-
-void ExtensionServiceBackend::OnExternalExtensionUpdateUrlFound(
+void ExtensionService::OnExternalExtensionUpdateUrlFound(
     const std::string& id,
     const GURL& update_url,
     Extension::Location location) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(Extension::IdIsValid(id));
 
-  if (frontend_->GetExtensionById(id, true)) {
+  if (GetExtensionById(id, true)) {
     // Already installed.  Do not change the update URL that the extension set.
     return;
   }
-
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          frontend_,
-          &ExtensionService::AddPendingExtensionFromExternalUpdateUrl,
-          id, update_url, location));
-  external_extension_added_ |= true;
+  AddPendingExtensionFromExternalUpdateUrl(id, update_url, location);
+  external_extension_url_added_ |= true;
 }
 
 bool ExtensionService::IsDownloadFromGallery(const GURL& download_url,
-                                              const GURL& referrer_url) {
+                                             const GURL& referrer_url) {
   // Special-case the themes mini-gallery.
   // TODO(erikkay) When that gallery goes away, remove this code.
   if (IsDownloadFromMiniGallery(download_url) &&
@@ -526,7 +392,6 @@
 bool ExtensionService::UninstallExtensionHelper(
     ExtensionService* extensions_service,
     const std::string& extension_id) {
-  DCHECK(extensions_service);
 
   // We can't call UninstallExtension with an invalid extension ID, so check it
   // first.
@@ -542,10 +407,10 @@
 }
 
 ExtensionService::ExtensionService(Profile* profile,
-                                     const CommandLine* command_line,
-                                     const FilePath& install_directory,
-                                     ExtensionPrefs* extension_prefs,
-                                     bool autoupdate_enabled)
+                                   const CommandLine* command_line,
+                                   const FilePath& install_directory,
+                                   ExtensionPrefs* extension_prefs,
+                                   bool autoupdate_enabled)
     : profile_(profile),
       extension_prefs_(extension_prefs),
       install_directory_(install_directory),
@@ -556,7 +421,7 @@
       default_apps_(profile->GetPrefs(),
                     g_browser_process->GetApplicationLocale()),
       event_routers_initialized_(false) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Figure out if extension installation should be enabled.
   if (command_line->HasSwitch(switches::kDisableExtensions)) {
@@ -570,7 +435,6 @@
   pref_change_registrar_.Init(profile->GetPrefs());
   pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this);
   pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this);
-  pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this);
 
   // Set up the ExtensionUpdater
   if (autoupdate_enabled) {
@@ -585,8 +449,10 @@
                                     update_frequency);
   }
 
-  backend_ = new ExtensionServiceBackend(profile->GetPrefs(),
-                                          install_directory_);
+  backend_ = new ExtensionServiceBackend(install_directory_);
+
+  ExternalExtensionProviderImpl::CreateExternalProviders(
+      this, profile_, &external_extension_providers_);
 
   // Use monochrome icons for Omnibox icons.
   omnibox_popup_icon_manager_.set_monochrome(true);
@@ -603,6 +469,10 @@
   return &disabled_extensions_;
 }
 
+const ExtensionList* ExtensionService::terminated_extensions() const {
+  return &terminated_extensions_;
+}
+
 const PendingExtensionMap& ExtensionService::pending_extensions() const {
   return pending_extensions_;
 }
@@ -614,8 +484,12 @@
 ExtensionService::~ExtensionService() {
   DCHECK(!profile_);  // Profile should have told us it's going away.
   UnloadAllExtensions();
-  if (updater_.get()) {
-    updater_->Stop();
+
+  ProviderCollection::const_iterator i;
+  for (i = external_extension_providers_.begin();
+       i != external_extension_providers_.end(); ++i) {
+    ExternalExtensionProviderInterface* provider = i->get();
+    provider->ServiceShutdown();
   }
 }
 
@@ -625,7 +499,8 @@
 
   ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_);
   ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_);
-  ExtensionBrowserEventRouter::GetInstance()->Init(profile_);
+  browser_event_router_.reset(new ExtensionBrowserEventRouter(profile_));
+  browser_event_router_->Init();
   ExtensionBookmarkEventRouter::GetInstance()->Observe(
       profile_->GetBookmarkModel());
   ExtensionCookiesEventRouter::GetInstance()->Init();
@@ -641,7 +516,7 @@
 }
 
 void ExtensionService::Init() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   DCHECK(!ready_);  // Can't redo init.
   DCHECK_EQ(extensions_.size(), 0u);
@@ -671,15 +546,15 @@
   // TODO(akalin): Put this somewhere where both crx_installer.cc and
   // this file can use it.
   void DeleteFileHelper(const FilePath& path, bool recursive) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     file_util::Delete(path, recursive);
   }
 }  // namespace
 
 void ExtensionService::UpdateExtension(const std::string& id,
-                                        const FilePath& extension_path,
-                                        const GURL& download_url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+                                       const FilePath& extension_path,
+                                       const GURL& download_url) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   PendingExtensionMap::const_iterator it = pending_extensions_.find(id);
   bool is_pending_extension = (it != pending_extensions_.end());
@@ -797,7 +672,7 @@
     bool is_from_sync, bool install_silently,
     bool enable_on_install, bool enable_incognito_on_install,
     Extension::Location install_source) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // If a non-sync update is pending, a sync request should not
   // overwrite it.  This is important for external extensions.
@@ -824,7 +699,7 @@
 }
 
 void ExtensionService::ReloadExtension(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   FilePath path;
   const Extension* current_extension = GetExtensionById(extension_id, false);
 
@@ -868,7 +743,7 @@
 
 void ExtensionService::UninstallExtension(const std::string& extension_id,
                                            bool external_uninstall) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   const Extension* extension =
       GetExtensionByIdInternal(extension_id, true, true);
@@ -925,7 +800,7 @@
 }
 
 void ExtensionService::EnableExtension(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   const Extension* extension =
       GetExtensionByIdInternal(extension_id, false, true);
@@ -944,7 +819,7 @@
   // Make sure any browser action contained within it is not hidden.
   extension_prefs_->SetBrowserActionVisibility(extension, true);
 
-  ExtensionDOMUI::RegisterChromeURLOverrides(profile_,
+  ExtensionWebUI::RegisterChromeURLOverrides(profile_,
       extension->GetChromeURLOverrides());
 
   NotifyExtensionLoaded(extension);
@@ -952,7 +827,7 @@
 }
 
 void ExtensionService::DisableExtension(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   const Extension* extension =
       GetExtensionByIdInternal(extension_id, true, false);
@@ -969,7 +844,7 @@
                                            extension);
   extensions_.erase(iter);
 
-  ExtensionDOMUI::UnregisterChromeURLOverrides(profile_,
+  ExtensionWebUI::UnregisterChromeURLOverrides(profile_,
       extension->GetChromeURLOverrides());
 
   NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE);
@@ -1028,13 +903,12 @@
       NOTREACHED() << error;
       return;
     }
-
-    OnExtensionLoaded(extension);
+    AddExtension(extension);
   }
 }
 
 void ExtensionService::LoadAllExtensions() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   base::TimeTicks start_time = base::TimeTicks::Now();
 
@@ -1200,17 +1074,7 @@
   if (write_to_prefs)
     extension_prefs_->UpdateManifest(extension);
 
-  OnExtensionLoaded(extension);
-
-  if (Extension::IsExternalLocation(info.extension_location)) {
-    BrowserThread::PostTask(
-        BrowserThread::FILE, FROM_HERE,
-        NewRunnableMethod(
-            backend_.get(),
-            &ExtensionServiceBackend::CheckExternalUninstall,
-            scoped_refptr<ExtensionService>(this),
-            info.extension_id));
-  }
+  AddExtension(extension);
 }
 
 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
@@ -1311,7 +1175,7 @@
           BrowserThread::IO, FROM_HERE,
           NewRunnableMethod(
               profile_->GetFileSystemContext(),
-              &fileapi::SandboxedFileSystemContext::SetOriginQuotaUnlimited,
+              &fileapi::FileSystemContext::SetOriginQuotaUnlimited,
               origin));
     }
   }
@@ -1346,7 +1210,7 @@
           BrowserThread::IO, FROM_HERE,
           NewRunnableMethod(
               profile_->GetFileSystemContext(),
-              &fileapi::SandboxedFileSystemContext::ResetOriginQuotaUnlimited,
+              &fileapi::FileSystemContext::ResetOriginQuotaUnlimited,
               origin));
     }
   }
@@ -1379,7 +1243,15 @@
   }
 }
 
+Profile* ExtensionService::profile() {
+  return profile_;
+}
+
 void ExtensionService::DestroyingProfile() {
+  if (updater_.get()) {
+    updater_->Stop();
+  }
+  browser_event_router_.reset();
   pref_change_registrar_.RemoveAll();
   profile_ = NULL;
   toolbar_model_.DestroyingProfile();
@@ -1456,31 +1328,77 @@
 }
 
 void ExtensionService::SetBrowserActionVisibility(const Extension* extension,
-                                                   bool visible) {
+                                                  bool visible) {
   extension_prefs_->SetBrowserActionVisibility(extension, visible);
 }
 
+// Some extensions will autoupdate themselves externally from Chrome.  These
+// are typically part of some larger client application package.  To support
+// these, the extension will register its location in the the preferences file
+// (and also, on Windows, in the registry) and this code will periodically
+// check that location for a .crx file, which it will then install locally if
+// a new version is available.
+// Errors are reported through ExtensionErrorReporter. Succcess is not
+// reported.
 void ExtensionService::CheckForExternalUpdates() {
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(
-          backend_.get(), &ExtensionServiceBackend::CheckForExternalUpdates,
-          scoped_refptr<ExtensionService>(this)));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // Note that this installation is intentionally silent (since it didn't
+  // go through the front-end).  Extensions that are registered in this
+  // way are effectively considered 'pre-bundled', and so implicitly
+  // trusted.  In general, if something has HKLM or filesystem access,
+  // they could install an extension manually themselves anyway.
+
+  // If any external extension records give a URL, a provider will set
+  // this to true.  Used by OnExternalProviderReady() to see if we need
+  // to start an update check to fetch a new external extension.
+  external_extension_url_added_ = false;
+
+  // Ask each external extension provider to give us a call back for each
+  // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
+  ProviderCollection::const_iterator i;
+  for (i = external_extension_providers_.begin();
+       i != external_extension_providers_.end(); ++i) {
+    ExternalExtensionProviderInterface* provider = i->get();
+    provider->VisitRegisteredExtension();
+  }
+
+  // Uninstall of unclaimed extensions will happen after all the providers
+  // had reported ready.  Every provider calls OnExternalProviderReady()
+  // when it finishes, and OnExternalProviderReady() only acts when all
+  // providers are ready.  In case there are no providers, we call it
+  // to trigger removal of extensions that used to have an external source.
+  if (external_extension_providers_.empty())
+    OnExternalProviderReady();
 }
 
-void ExtensionService::UpdateExternalPolicyExtensionProvider() {
-  const ListValue* list_pref =
-      profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList);
-  ListValue* list_copy = NULL;
-  if (list_pref)
-    list_copy = static_cast<ListValue*>(list_pref->DeepCopy());
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(
-          backend_.get(),
-          &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider,
-          scoped_refptr<RefCountedList>(
-              new RefCountedList(list_copy))));
+void ExtensionService::OnExternalProviderReady() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // An external provider has finished loading.  We only take action
+  // if all of them are finished. So we check them first.
+  ProviderCollection::const_iterator i;
+  for (i = external_extension_providers_.begin();
+       i != external_extension_providers_.end(); ++i) {
+    ExternalExtensionProviderInterface* provider = i->get();
+    if (!provider->IsReady())
+      return;
+  }
+
+  // All the providers are ready.  Install any pending extensions.
+  if (external_extension_url_added_ && updater()) {
+    external_extension_url_added_ = false;
+    updater()->CheckNow();
+  }
+
+  // Uninstall all the unclaimed extensions.
+  scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
+      extension_prefs_->GetInstalledExtensionsInfo());
+  for (size_t i = 0; i < extensions_info->size(); ++i) {
+    ExtensionInfo* info = extensions_info->at(i).get();
+    if (Extension::IsExternalLocation(info->extension_location))
+      CheckExternalUninstall(info->extension_id);
+  }
 }
 
 void ExtensionService::UnloadExtension(
@@ -1505,7 +1423,7 @@
   // Clean up runtime data.
   extension_runtime_data_.erase(extension_id);
 
-  ExtensionDOMUI::UnregisterChromeURLOverrides(profile_,
+  ExtensionWebUI::UnregisterChromeURLOverrides(profile_,
       extension->GetChromeURLOverrides());
 
   ExtensionList::iterator iter = std::find(disabled_extensions_.begin(),
@@ -1534,6 +1452,8 @@
 void ExtensionService::UnloadAllExtensions() {
   extensions_.clear();
   disabled_extensions_.clear();
+  terminated_extension_ids_.clear();
+  terminated_extensions_.clear();
   extension_runtime_data_.clear();
 
   // TODO(erikkay) should there be a notification for this?  We can't use
@@ -1583,13 +1503,16 @@
       NotificationService::NoDetails());
 }
 
-void ExtensionService::OnExtensionLoaded(const Extension* extension) {
+void ExtensionService::AddExtension(const Extension* extension) {
   // Ensure extension is deleted unless we transfer ownership.
   scoped_refptr<const Extension> scoped_extension(extension);
 
   // The extension is now loaded, remove its data from unloaded extension map.
   unloaded_extension_paths_.erase(extension->id());
 
+  // If a terminated extension is loaded, remove it from the terminated list.
+  UntrackTerminatedExtension(extension->id());
+
   // If the extension was disabled for a reload, then enable it.
   if (disabled_extension_paths_.erase(extension->id()) > 0)
     EnableExtension(extension->id());
@@ -1613,7 +1536,7 @@
 
       NotifyExtensionLoaded(extension);
 
-      ExtensionDOMUI::RegisterChromeURLOverrides(
+      ExtensionWebUI::RegisterChromeURLOverrides(
           profile_, extension->GetChromeURLOverrides());
       break;
     case Extension::DISABLED:
@@ -1737,7 +1660,7 @@
 }
 
 void ExtensionService::OnExtensionInstalled(const Extension* extension) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Ensure extension is deleted unless we transfer ownership.
   scoped_refptr<const Extension> scoped_extension(extension);
@@ -1820,8 +1743,8 @@
     default_apps_.DidInstallApp(installed_ids);
   }
 
-  // Transfer ownership of |extension| to OnExtensionLoaded.
-  OnExtensionLoaded(scoped_extension);
+  // Transfer ownership of |extension| to AddExtension.
+  AddExtension(scoped_extension);
 }
 
 const Extension* ExtensionService::GetExtensionByIdInternal(
@@ -1844,6 +1767,25 @@
   return NULL;
 }
 
+void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
+  if (terminated_extension_ids_.insert(extension->id()).second)
+    terminated_extensions_.push_back(make_scoped_refptr(extension));
+}
+
+void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
+  if (terminated_extension_ids_.erase(id) <= 0)
+    return;
+
+  std::string lowercase_id = StringToLowerASCII(id);
+  for (ExtensionList::iterator iter = terminated_extensions_.begin();
+       iter != terminated_extensions_.end(); ++iter) {
+    if ((*iter)->id() == lowercase_id) {
+      terminated_extensions_.erase(iter);
+      return;
+    }
+  }
+}
+
 const Extension* ExtensionService::GetWebStoreApp() {
   return GetExtensionById(extension_misc::kWebStoreAppId, false);
 }
@@ -1891,38 +1833,24 @@
   return omnibox_popup_icon_manager_.GetIcon(extension_id);
 }
 
-void ExtensionService::ClearProvidersForTesting() {
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(
-          backend_.get(), &ExtensionServiceBackend::ClearProvidersForTesting));
-}
-
-void ExtensionService::AddProviderForTesting(
-    ExternalExtensionProvider* test_provider) {
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(
-          backend_.get(), &ExtensionServiceBackend::AddProviderForTesting,
-          test_provider));
-}
-
 void ExtensionService::OnExternalExtensionFileFound(
          const std::string& id,
-         const std::string& version,
+         const Version* version,
          const FilePath& path,
          Extension::Location location) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(Extension::IdIsValid(id));
   if (extension_prefs_->IsExtensionKilled(id))
     return;
 
+  DCHECK(version);
+
   // Before even bothering to unpack, check and see if we already have this
   // version. This is important because these extensions are going to get
   // installed on every startup.
   const Extension* existing = GetExtensionById(id, true);
-  scoped_ptr<Version> other(Version::GetVersionFromString(version));
   if (existing) {
-    switch (existing->version()->CompareTo(*other)) {
+    switch (existing->version()->CompareTo(*version)) {
       case -1:  // existing version is older, we should upgrade
         break;
       case 0:  // existing version is same, do nothing
@@ -1968,8 +1896,7 @@
                   Source<Profile>(profile_),
                   Details<const std::string>(&error));
 
-  // TODO(port): note that this isn't guaranteed to work properly on Linux.
-  std::string path_str = WideToUTF8(extension_path.ToWStringHack());
+  std::string path_str = UTF16ToUTF8(extension_path.LossyDisplayName());
   std::string message = base::StringPrintf(
       "Could not load extension from '%s'. %s",
       path_str.c_str(), error.c_str());
@@ -1997,6 +1924,7 @@
         break;
 
       ExtensionHost* host = Details<ExtensionHost>(details).ptr();
+      TrackTerminatedExtension(host->extension());
 
       // Unload the entire extension. We want it to be in a consistent state:
       // either fully working or not loaded at all, but never half-crashed.
@@ -2015,12 +1943,6 @@
       if (*pref_name == prefs::kExtensionInstallAllowList ||
           *pref_name == prefs::kExtensionInstallDenyList) {
         CheckAdminBlacklist();
-      } else if (*pref_name == prefs::kExtensionInstallForceList) {
-        UpdateExternalPolicyExtensionProvider();
-        CheckForExternalUpdates();
-        // TODO(gfeher): Also check for external extensions that can be
-        // uninstalled because they were removed from the pref.
-        // (crbug.com/63667)
       } else {
         NOTREACHED() << "Unexpected preference name.";
       }
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 9e4206c..ca38d6e 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <map>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -26,7 +27,7 @@
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_toolbar_model.h"
 #include "chrome/browser/extensions/extensions_quota_service.h"
-#include "chrome/browser/extensions/external_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
 #include "chrome/browser/extensions/sandboxed_extension_unpacker.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/common/notification_observer.h"
@@ -34,6 +35,7 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/property_bag.h"
 
+class ExtensionBrowserEventRouter;
 class ExtensionServiceBackend;
 class ExtensionToolbarModel;
 class ExtensionUpdater;
@@ -92,6 +94,7 @@
   virtual bool HasInstalledExtensions() = 0;
 
   virtual ExtensionPrefs* extension_prefs() = 0;
+  virtual Profile* profile() = 0;
 };
 
 // Manages installed and running Chromium extensions.
@@ -99,6 +102,7 @@
     : public base::RefCountedThreadSafe<ExtensionService,
                                         BrowserThread::DeleteOnUIThread>,
       public ExtensionUpdateService,
+      public ExternalExtensionProviderInterface::VisitorInterface,
       public NotificationObserver {
  public:
   // Information about a registered component extension.
@@ -148,14 +152,15 @@
   // Constructor stores pointers to |profile| and |extension_prefs| but
   // ownership remains at caller.
   ExtensionService(Profile* profile,
-                    const CommandLine* command_line,
-                    const FilePath& install_directory,
-                    ExtensionPrefs* extension_prefs,
-                    bool autoupdate_enabled);
+                   const CommandLine* command_line,
+                   const FilePath& install_directory,
+                   ExtensionPrefs* extension_prefs,
+                   bool autoupdate_enabled);
 
   // Gets the list of currently installed extensions.
   virtual const ExtensionList* extensions() const;
   virtual const ExtensionList* disabled_extensions() const;
+  virtual const ExtensionList* terminated_extensions() const;
 
   // Gets the set of pending extensions.
   virtual const PendingExtensionMap& pending_extensions() const;
@@ -297,10 +302,6 @@
   // Check for updates (or potentially new extensions from external providers)
   void CheckForExternalUpdates();
 
-  // Copies the list of force-installed extensions from the user PrefService
-  // to ExternalPolicyExtensionProvider.
-  void UpdateExternalPolicyExtensionProvider();
-
   // Unload the specified extension.
   void UnloadExtension(const std::string& extension_id,
                        UnloadedExtensionInfo::Reason reason);
@@ -342,28 +343,17 @@
   // extension.
   const SkBitmap& GetOmniboxPopupIcon(const std::string& extension_id);
 
-  // Clear all ExternalExtensionProviders.
-  void ClearProvidersForTesting();
-
-  // Sets an ExternalExtensionProvider for the service to use during testing.
-  // Takes ownership of |test_provider|.
-  void AddProviderForTesting(ExternalExtensionProvider* test_provider);
-
   // Called when the initial extensions load has completed.
   virtual void OnLoadedInstalledExtensions();
 
-  // Called when an extension has been loaded.
-  void OnExtensionLoaded(const Extension* extension);
+  // Adds |extension| to this ExtensionService and notifies observers than an
+  // extension has been loaded.  Called by the backend after an extension has
+  // been loaded from a file and installed.
+  void AddExtension(const Extension* extension);
 
   // Called by the backend when an extension has been installed.
   void OnExtensionInstalled(const Extension* extension);
 
-  // Called by the backend when an external extension is found.
-  void OnExternalExtensionFileFound(const std::string& id,
-                                    const std::string& version,
-                                    const FilePath& path,
-                                    Extension::Location location);
-
   // Checks if the privileges requested by |extension| have increased, and if
   // so, disables the extension and prompts the user to approve the change.
   void DisableIfPrivilegeIncrease(const Extension* extension);
@@ -389,7 +379,7 @@
     return show_extensions_prompts_;
   }
 
-  Profile* profile() { return profile_; }
+  virtual Profile* profile();
 
   // Profile calls this when it is being destroyed so that we know not to call
   // it.
@@ -410,6 +400,10 @@
 
   ExtensionMenuManager* menu_manager() { return &menu_manager_; }
 
+  ExtensionBrowserEventRouter* browser_event_router() {
+    return browser_event_router_.get();
+  }
+
   const std::map<GURL, int>& protected_storage_map() const {
     return protected_storage_map_;
   }
@@ -425,6 +419,29 @@
   // view has been created.
   void DidCreateRenderViewForBackgroundPage(ExtensionHost* host);
 
+  // For the extension in |version_path| with |id|, check to see if it's an
+  // externally managed extension.  If so, uninstall it.
+  void CheckExternalUninstall(const std::string& id);
+
+  // Clear all ExternalExtensionProviders.
+  void ClearProvidersForTesting();
+
+  // Adds an ExternalExtensionProviderInterface for the service to use during
+  // testing. Takes ownership of |test_provider|.
+  void AddProviderForTesting(ExternalExtensionProviderInterface* test_provider);
+
+  // ExternalExtensionProvider::Visitor implementation.
+  virtual void OnExternalExtensionFileFound(const std::string& id,
+                                            const Version* version,
+                                            const FilePath& path,
+                                            Extension::Location location);
+
+  virtual void OnExternalExtensionUpdateUrlFound(const std::string& id,
+                                                 const GURL& update_url,
+                                                 Extension::Location location);
+
+  virtual void OnExternalProviderReady();
+
   // NotificationObserver
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -468,6 +485,11 @@
                                             bool include_enabled,
                                             bool include_disabled);
 
+
+  // Keep track of terminated extensions.
+  void TrackTerminatedExtension(const Extension* extension);
+  void UntrackTerminatedExtension(const std::string& id);
+
   // Like AddPendingExtension*() functions above, but assumes an
   // extension with the same id is not already installed.
   void AddPendingExtensionInternal(
@@ -503,11 +525,18 @@
   ExtensionPrefs* extension_prefs_;
 
   // The current list of installed extensions.
+  // TODO(aa): This should use chrome/common/extensions/extension_set.h.
   ExtensionList extensions_;
 
   // The list of installed extensions that have been disabled.
   ExtensionList disabled_extensions_;
 
+  // The list of installed extensions that have been terminated.
+  ExtensionList terminated_extensions_;
+
+  // Used to quickly check if an extension was terminated.
+  std::set<std::string> terminated_extension_ids_;
+
   // The set of pending extensions.
   PendingExtensionMap pending_extensions_;
 
@@ -589,6 +618,18 @@
   // Flag to make sure event routers are only initialized once.
   bool event_routers_initialized_;
 
+  scoped_ptr<ExtensionBrowserEventRouter> browser_event_router_;
+
+  // A collection of external extension providers.  Each provider reads
+  // a source of external extension information.  Examples include the
+  // windows registry and external_extensions.json.
+  ProviderCollection external_extension_providers_;
+
+  // Set to true by OnExternalExtensionUpdateUrlFound() when an external
+  // extension URL is found.  Used in CheckForExternalUpdates() to see
+  // if an update check is needed to install pending extensions.
+  bool external_extension_url_added_;
+
   FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
                            UpdatePendingExtensionAlreadyInstalled);
   FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 7f052b6..426be5c 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,8 +28,9 @@
 #include "chrome/browser/extensions/extension_creator.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/external_extension_provider.h"
-#include "chrome/browser/extensions/external_pref_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+#include "chrome/browser/extensions/external_pref_extension_loader.h"
 #include "chrome/browser/extensions/pack_extension_job.cc"
 #include "chrome/browser/file_system/browser_file_system_helper.h"
 #include "chrome/browser/in_process_webkit/dom_storage_context.h"
@@ -125,10 +126,13 @@
 
 }  // namespace
 
-class MockExtensionProvider : public ExternalExtensionProvider {
+class MockExtensionProvider : public ExternalExtensionProviderInterface {
  public:
-  explicit MockExtensionProvider(Extension::Location location)
-    : location_(location), visit_count_(0) {}
+  explicit MockExtensionProvider(
+      VisitorInterface* visitor,
+      Extension::Location location)
+  : location_(location), visitor_(visitor), visit_count_(0) {
+  }
   virtual ~MockExtensionProvider() {}
 
   void UpdateOrAddExtension(const std::string& id,
@@ -142,16 +146,17 @@
   }
 
   // ExternalExtensionProvider implementation:
-  virtual void VisitRegisteredExtension(Visitor* visitor) const {
+  virtual void VisitRegisteredExtension() const {
     visit_count_++;
     for (DataMap::const_iterator i = extension_map_.begin();
          i != extension_map_.end(); ++i) {
       scoped_ptr<Version> version;
       version.reset(Version::GetVersionFromString(i->second.first));
 
-      visitor->OnExternalExtensionFileFound(
+      visitor_->OnExternalExtensionFileFound(
           i->first, version.get(), i->second.second, location_);
     }
+    visitor_->OnExternalProviderReady();
   }
 
   virtual bool HasExtension(const std::string& id) const {
@@ -173,6 +178,14 @@
 
     return true;
   }
+
+  virtual bool IsReady() {
+    return true;
+  }
+
+  virtual void ServiceShutdown() {
+  }
+
   int visit_count() const { return visit_count_; }
   void set_visit_count(int visit_count) {
     visit_count_ = visit_count;
@@ -182,6 +195,7 @@
   typedef std::map< std::string, std::pair<std::string, FilePath> > DataMap;
   DataMap extension_map_;
   Extension::Location location_;
+  VisitorInterface* visitor_;
 
   // visit_count_ tracks the number of calls to VisitRegisteredExtension().
   // Mutable because it must be incremented on each call to
@@ -192,15 +206,25 @@
   DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider);
 };
 
-class MockProviderVisitor : public ExternalExtensionProvider::Visitor {
+class MockProviderVisitor
+    : public ExternalExtensionProviderInterface::VisitorInterface {
  public:
-  MockProviderVisitor() : ids_found_(0) {
+
+  // The provider will return |fake_base_path| from
+  // GetBaseCrxFilePath().  User can test the behavior with
+  // and without an empty path using this parameter.
+  explicit MockProviderVisitor(FilePath fake_base_path)
+      : ids_found_(0),
+        fake_base_path_(fake_base_path) {
   }
 
   int Visit(const std::string& json_data) {
     // Give the test json file to the provider for parsing.
-    provider_.reset(new ExternalPrefExtensionProvider());
-    provider_->SetPreferencesForTesting(json_data);
+    provider_.reset(new ExternalExtensionProviderImpl(
+        this,
+        new ExternalTestingExtensionLoader(json_data, fake_base_path_),
+        Extension::EXTERNAL_PREF,
+        Extension::EXTERNAL_PREF_DOWNLOAD));
 
     // We also parse the file into a dictionary to compare what we get back
     // from the provider.
@@ -219,7 +243,7 @@
     // Reset our counter.
     ids_found_ = 0;
     // Ask the provider to look up all extensions and return them.
-    provider_->VisitRegisteredExtension(this);
+    provider_->VisitRegisteredExtension();
 
     return ids_found_;
   }
@@ -236,6 +260,10 @@
     EXPECT_TRUE(prefs_->GetDictionary(id, &pref))
        << "Got back ID (" << id.c_str() << ") we weren't expecting";
 
+    EXPECT_TRUE(path.IsAbsolute());
+    if (!fake_base_path_.empty())
+      EXPECT_TRUE(fake_base_path_.IsParent(path));
+
     if (pref) {
       EXPECT_TRUE(provider_->HasExtension(id));
 
@@ -285,10 +313,14 @@
     }
   }
 
+  virtual void OnExternalProviderReady() {
+    EXPECT_TRUE(provider_->IsReady());
+  }
+
  private:
   int ids_found_;
-
-  scoped_ptr<ExternalPrefExtensionProvider> provider_;
+  FilePath fake_base_path_;
+  scoped_ptr<ExternalExtensionProviderImpl> provider_;
   scoped_ptr<DictionaryValue> prefs_;
 
   DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor);
@@ -312,12 +344,13 @@
           NewRunnableMethod(appcache_service_.get(),
                             &ChromeAppCacheService::InitializeOnIOThread,
                             GetPath(), IsOffTheRecord(),
-                            make_scoped_refptr(GetHostContentSettingsMap())));
+                            make_scoped_refptr(GetHostContentSettingsMap()),
+                            false));
     }
     return appcache_service_;
   }
 
-  virtual fileapi::SandboxedFileSystemContext* GetFileSystemContext() {
+  virtual fileapi::FileSystemContext* GetFileSystemContext() {
     if (!file_system_context_)
       file_system_context_ = CreateFileSystemContext(
           GetPath(), IsOffTheRecord());
@@ -327,7 +360,7 @@
  private:
   ExtensionService* service_;
   scoped_refptr<ChromeAppCacheService> appcache_service_;
-  scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+  scoped_refptr<fileapi::FileSystemContext> file_system_context_;
 };
 
 // Our message loop may be used in tests which require it to be an IO loop.
@@ -470,7 +503,7 @@
     }
   }
 
-  void AddMockExternalProvider(ExternalExtensionProvider* provider) {
+  void AddMockExternalProvider(ExternalExtensionProviderInterface* provider) {
     service_->AddProviderForTesting(provider);
   }
 
@@ -1070,8 +1103,10 @@
   FilePath path = extensions_path.AppendASCII("good.crx");
   set_extensions_enabled(true);
 
+  scoped_ptr<Version> version;
+  version.reset(Version::GetVersionFromString("1.0.0.0"));
   // Install an external extension.
-  service_->OnExternalExtensionFileFound(good_crx, "1.0.0.0",
+  service_->OnExternalExtensionFileFound(good_crx, version.get(),
                                          path, Extension::EXTERNAL_PREF);
   loop_.RunAllPending();
   ASSERT_TRUE(NULL != service_->GetExtensionById(good_crx, false));
@@ -1082,15 +1117,16 @@
   ValidateIntegerPref(good_crx, "location", Extension::KILLBIT);
 
   // Try to re-install it externally. This should fail because of the killbit.
-  service_->OnExternalExtensionFileFound(good_crx, "1.0.0.0",
+  service_->OnExternalExtensionFileFound(good_crx, version.get(),
                                          path, Extension::EXTERNAL_PREF);
   loop_.RunAllPending();
   ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
   ValidateIntegerPref(good_crx, "location", Extension::KILLBIT);
 
+  version.reset(Version::GetVersionFromString("1.0.0.1"));
   // Repeat the same thing with a newer version of the extension.
   path = extensions_path.AppendASCII("good2.crx");
-  service_->OnExternalExtensionFileFound(good_crx, "1.0.0.1",
+  service_->OnExternalExtensionFileFound(good_crx, version.get(),
                                          path, Extension::EXTERNAL_PREF);
   loop_.RunAllPending();
   ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
@@ -1613,6 +1649,28 @@
   ValidatePrefKeyCount(pref_count);
 }
 
+TEST_F(ExtensionServiceTest, UpdateApps) {
+  InitializeEmptyExtensionService();
+  FilePath extensions_path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
+  extensions_path =
+      extensions_path.AppendASCII("extensions").AppendASCII("app_update");
+
+  // First install v1 of a hosted app.
+  InstallExtension(extensions_path.AppendASCII("v1.crx"), true);
+  ASSERT_EQ(1u, service_->extensions()->size());
+  std::string id = service_->extensions()->at(0)->id();
+  ASSERT_EQ(std::string("1"),
+            service_->extensions()->at(0)->version()->GetString());
+
+  // Now try updating to v2.
+  UpdateExtension(id,
+                  extensions_path.AppendASCII("v2.crx"),
+                  ENABLED);
+  ASSERT_EQ(std::string("2"),
+            service_->extensions()->at(0)->version()->GetString());
+}
+
 TEST_F(ExtensionServiceTest, InstallAppsWithUnlimtedStorage) {
   InitializeEmptyExtensionService();
   EXPECT_TRUE(service_->extensions()->empty());
@@ -2861,8 +2919,7 @@
   provider->RemoveExtension(good_crx);
 
   loaded_.clear();
-  service_->UnloadAllExtensions();
-  service_->LoadAllExtensions();
+  service_->OnExternalProviderReady();
   loop_.RunAllPending();
   ASSERT_EQ(0u, loaded_.size());
   ValidatePrefKeyCount(0);
@@ -2908,7 +2965,7 @@
 
   // Now add providers. Extension system takes ownership of the objects.
   MockExtensionProvider* reg_provider =
-      new MockExtensionProvider(Extension::EXTERNAL_REGISTRY);
+      new MockExtensionProvider(service_.get(), Extension::EXTERNAL_REGISTRY);
   AddMockExternalProvider(reg_provider);
   TestExternalProvider(reg_provider, Extension::EXTERNAL_REGISTRY);
 }
@@ -2919,7 +2976,7 @@
 
   // Now add providers. Extension system takes ownership of the objects.
   MockExtensionProvider* pref_provider =
-      new MockExtensionProvider(Extension::EXTERNAL_PREF);
+      new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF);
 
   AddMockExternalProvider(pref_provider);
   TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF);
@@ -2938,7 +2995,8 @@
   // what the visitor does results in an extension being downloaded and
   // installed.
   MockExtensionProvider* pref_provider =
-      new MockExtensionProvider(Extension::EXTERNAL_PREF_DOWNLOAD);
+      new MockExtensionProvider(service_.get(),
+                                Extension::EXTERNAL_PREF_DOWNLOAD);
   AddMockExternalProvider(pref_provider);
   TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF_DOWNLOAD);
 }
@@ -2976,11 +3034,79 @@
   ASSERT_EQ(0u, loaded_.size());
 }
 
+// Test that running multiple update checks simultaneously does not
+// keep the update from succeeding.
+TEST_F(ExtensionServiceTest, MultipleExternalUpdateCheck) {
+  InitializeEmptyExtensionService();
+
+  MockExtensionProvider* provider =
+      new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF);
+  AddMockExternalProvider(provider);
+
+  // Verify that starting with no providers loads no extensions.
+  service_->Init();
+  loop_.RunAllPending();
+  ASSERT_EQ(0u, loaded_.size());
+
+  // Start two checks for updates.
+  provider->set_visit_count(0);
+  service_->CheckForExternalUpdates();
+  service_->CheckForExternalUpdates();
+  loop_.RunAllPending();
+
+  // Two calls should cause two checks for external extensions.
+  EXPECT_EQ(2, provider->visit_count());
+  EXPECT_EQ(0u, GetErrors().size());
+  EXPECT_EQ(0u, loaded_.size());
+
+  // Register a test extension externally using the mock registry provider.
+  FilePath source_path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_path));
+  source_path = source_path.AppendASCII("extensions").AppendASCII("good.crx");
+  provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path);
+
+  // Two checks for external updates should find the extension, and install it
+  // once.
+  provider->set_visit_count(0);
+  service_->CheckForExternalUpdates();
+  service_->CheckForExternalUpdates();
+  loop_.RunAllPending();
+  EXPECT_EQ(2, provider->visit_count());
+  ASSERT_EQ(0u, GetErrors().size());
+  ASSERT_EQ(1u, loaded_.size());
+  ASSERT_EQ(Extension::EXTERNAL_PREF, loaded_[0]->location());
+  ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
+  ValidatePrefKeyCount(1);
+  ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
+  ValidateIntegerPref(good_crx, "location", Extension::EXTERNAL_PREF);
+
+  provider->RemoveExtension(good_crx);
+  provider->set_visit_count(0);
+  service_->CheckForExternalUpdates();
+  service_->CheckForExternalUpdates();
+  loop_.RunAllPending();
+
+  // Two calls should cause two checks for external extensions.
+  // Because the external source no longer includes good_crx,
+  // good_crx will be uninstalled.  So, expect that no extensions
+  // are loaded.
+  EXPECT_EQ(2, provider->visit_count());
+  EXPECT_EQ(0u, GetErrors().size());
+  EXPECT_EQ(0u, loaded_.size());
+}
+
 TEST_F(ExtensionServiceTest, ExternalPrefProvider) {
   InitializeEmptyExtensionService();
+
+  // Test some valid extension records.
+  // Set a base path to avoid erroring out on relative paths.
+  // Paths starting with // are absolute on every platform we support.
+  FilePath base_path(FILE_PATH_LITERAL("//base/path"));
+  ASSERT_TRUE(base_path.IsAbsolute());
+  MockProviderVisitor visitor(base_path);
   std::string json_data =
       "{"
-      "  \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
+      "  \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
       "    \"external_crx\": \"RandomExtension.crx\","
       "    \"external_version\": \"1.0\""
       "  },"
@@ -2992,11 +3118,10 @@
       "    \"external_update_url\": \"http:\\\\foo.com/update\""
       "  }"
       "}";
-
-  MockProviderVisitor visitor;
+  EXPECT_EQ(3, visitor.Visit(json_data));
 
   // Simulate an external_extensions.json file that contains seven invalid
-  // extensions:
+  // records:
   // - One that is missing the 'external_crx' key.
   // - One that is missing the 'external_version' key.
   // - One that is specifying .. in the path.
@@ -3004,6 +3129,8 @@
   // - One that specifies no file or update URL.
   // - One that has an update URL that is not well formed.
   // - One that contains a malformed version.
+  // - One that has an invalid id.
+  // - One that has a non-dictionary value.
   // The final extension is valid, and we check that it is read to make sure
   // failures don't stop valid records from being read.
   json_data =
@@ -3032,12 +3159,43 @@
       "    \"external_crx\": \"RandomExtension3.crx\","
       "    \"external_version\": \"This is not a valid version!\""
       "  },"
-      "  \"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\": {"
+      "  \"This is not a valid id!\": {},"
+      "  \"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\": true,"
+      "  \"pppppppppppppppppppppppppppppppp\": {"
       "    \"external_crx\": \"RandomValidExtension.crx\","
       "    \"external_version\": \"1.0\""
       "  }"
       "}";
   EXPECT_EQ(1, visitor.Visit(json_data));
+
+  // Check that if a base path is not provided, use of a relative
+  // path fails.
+  FilePath empty;
+  MockProviderVisitor visitor_no_relative_paths(empty);
+
+  // Use absolute paths.  Expect success.
+  json_data =
+      "{"
+      "  \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
+      "    \"external_crx\": \"//RandomExtension1.crx\","
+      "    \"external_version\": \"3.0\""
+      "  },"
+      "  \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
+      "    \"external_crx\": \"//path/to/RandomExtension2.crx\","
+      "    \"external_version\": \"3.0\""
+      "  }"
+      "}";
+  EXPECT_EQ(2, visitor_no_relative_paths.Visit(json_data));
+
+  // Use a relative path.  Expect that it will error out.
+  json_data =
+      "{"
+      "  \"cccccccccccccccccccccccccccccccc\": {"
+      "    \"external_crx\": \"RandomExtension2.crx\","
+      "    \"external_version\": \"3.0\""
+      "  }"
+      "}";
+  EXPECT_EQ(0, visitor_no_relative_paths.Visit(json_data));
 }
 
 // Test loading good extensions from the profile directory.
@@ -3118,7 +3276,7 @@
   // By default, we are enabled.
   command_line.reset(new CommandLine(CommandLine::NO_PROGRAM));
   service = profile->CreateExtensionService(command_line.get(),
-                                             install_dir);
+                                            install_dir);
   EXPECT_TRUE(service->extensions_enabled());
   service->Init();
   loop.RunAllPending();
@@ -3139,7 +3297,7 @@
   profile.reset(new TestingProfile());
   profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
   service = profile->CreateExtensionService(command_line.get(),
-                                             install_dir);
+                                            install_dir);
   EXPECT_FALSE(service->extensions_enabled());
   service->Init();
   loop.RunAllPending();
diff --git a/chrome/browser/extensions/extension_sidebar_api.cc b/chrome/browser/extensions/extension_sidebar_api.cc
index bd32d5a..fc90615 100644
--- a/chrome/browser/extensions/extension_sidebar_api.cc
+++ b/chrome/browser/extensions/extension_sidebar_api.cc
@@ -20,15 +20,16 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_error_utils.h"
+#include "chrome/common/extensions/extension_sidebar_utils.h"
 #include "chrome/common/render_messages.h"
-#include "chrome/common/url_constants.h"
 #include "ipc/ipc_message_utils.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 namespace {
 // Errors.
+const char kNoSidebarError[] =
+    "This extension has no sidebar specified.";
 const char kNoTabError[] = "No tab with id: *.";
-const char kInvalidUrlError[] = "Invalid url: \"*\".";
 const char kNoCurrentWindowError[] = "No current browser window was found";
 const char kNoDefaultTabError[] = "No default tab was found";
 const char kInvalidExpandContextError[] =
@@ -36,10 +37,10 @@
 // Keys.
 const char kBadgeTextKey[] = "text";
 const char kImageDataKey[] = "imageData";
+const char kPathKey[] = "path";
 const char kStateKey[] = "state";
 const char kTabIdKey[] = "tabId";
 const char kTitleKey[] = "title";
-const char kUrlKey[] = "url";
 // Events.
 const char kOnStateChanged[] = "experimental.sidebar.onStateChanged";
 }  // namespace
@@ -49,31 +50,7 @@
 const char kActiveState[] = "active";
 const char kHiddenState[] = "hidden";
 const char kShownState[] = "shown";
-}
-
-static GURL ResolvePossiblyRelativeURL(const std::string& url_string,
-                                       const Extension* extension) {
-  GURL url = GURL(url_string);
-  if (!url.is_valid())
-    url = extension->GetResourceURL(url_string);
-
-  return url;
-}
-
-static bool CanUseHost(const Extension* extension,
-                       const GURL& url,
-                       std::string* error) {
-  if (extension->HasHostPermission(url))
-      return true;
-
-  if (error) {
-    *error = ExtensionErrorUtils::FormatErrorMessage(
-        extension_manifest_errors::kCannotAccessPage, url.spec());
-  }
-
-  return false;
-}
-
+}  // namespace extension_sidebar_constants
 
 // static
 void ExtensionSidebarEventRouter::OnStateChanged(
@@ -89,9 +66,9 @@
   std::string json_args;
   base::JSONWriter::Write(&args, false, &json_args);
 
-  const std::string& extension_id(content_id);
   profile->GetExtensionEventRouter()->DispatchEventToExtension(
-      extension_id, kOnStateChanged, json_args, profile, GURL());
+      extension_sidebar_utils::GetExtensionIdByContentId(content_id),
+      kOnStateChanged, json_args, profile, GURL());
 }
 
 
@@ -111,6 +88,11 @@
 }
 
 bool SidebarFunction::RunImpl() {
+  if (!GetExtension()->sidebar_defaults()) {
+    error_ = kNoSidebarError;
+    return false;
+  }
+
   if (!args_.get())
     return false;
 
@@ -222,26 +204,15 @@
 bool NavigateSidebarFunction::RunImpl(TabContents* tab,
                                       const std::string& content_id,
                                       const DictionaryValue& details) {
-  std::string url_string;
-  EXTENSION_FUNCTION_VALIDATE(details.GetString(kUrlKey, &url_string));
-  GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension());
-  if (!url.is_valid()) {
-    error_ = ExtensionErrorUtils::FormatErrorMessage(kInvalidUrlError,
-                                                     url_string);
-    return false;
-  }
-  if (!url.SchemeIs(chrome::kExtensionScheme) &&
-      !CanUseHost(GetExtension(), url, &error_)) {
-    return false;
-  }
-  // Disallow requests outside of the requesting extension view's extension.
-  if (url.SchemeIs(chrome::kExtensionScheme)) {
-    std::string extension_id(url.host());
-    if (extension_id != GetExtension()->id())
-      return false;
-  }
+  std::string path_string;
+  EXTENSION_FUNCTION_VALIDATE(details.GetString(kPathKey, &path_string));
 
-  SidebarManager::GetInstance()->NavigateSidebar(tab, content_id, GURL(url));
+  GURL url = extension_sidebar_utils::ResolveRelativePath(
+      path_string, GetExtension(), &error_);
+  if (!url.is_valid())
+    return false;
+
+  SidebarManager::GetInstance()->NavigateSidebar(tab, content_id, url);
   return true;
 }
 
diff --git a/chrome/browser/extensions/extension_startup_browsertest.cc b/chrome/browser/extensions/extension_startup_browsertest.cc
index 25bad91..968fe69 100644
--- a/chrome/browser/extensions/extension_startup_browsertest.cc
+++ b/chrome/browser/extensions/extension_startup_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,8 +16,6 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
diff --git a/chrome/browser/extensions/extension_tabs_apitest.cc b/chrome/browser/extensions/extension_tabs_apitest.cc
index b736777..acb2a48 100644
--- a/chrome/browser/extensions/extension_tabs_apitest.cc
+++ b/chrome/browser/extensions/extension_tabs_apitest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_apitest.h"
 
+#include "chrome/browser/browser_window.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -23,8 +24,20 @@
 #define MAYBE_Tabs Tabs
 #endif
 
+// Window resizes are not completed by the time the callback happens,
+// so these tests fail on linux. http://crbug.com/72369
+#if defined(OS_LINUX)
+#define MAYBE_FocusWindowDoesNotExitFullscreen \
+  DISABLED_FocusWindowDoesNotExitFullscreen
+#define MAYBE_UpdateWindowSizeExitsFullscreen \
+  DISABLED_UpdateWindowSizeExitsFullscreen
+#else
+#define MAYBE_FocusWindowDoesNotExitFullscreen FocusWindowDoesNotExitFullscreen
+#define MAYBE_UpdateWindowSizeExitsFullscreen UpdateWindowSizeExitsFullscreen
+#endif
+
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Tabs) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(StartTestServer());
 
   // The test creates a tab and checks that the URL of the new tab
   // is that of the new tab page.  Make sure the pref that controls
@@ -36,22 +49,22 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabPinned) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(StartTestServer());
   ASSERT_TRUE(RunExtensionSubtest("tabs/basics", "pinned.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabMove) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(StartTestServer());
   ASSERT_TRUE(RunExtensionSubtest("tabs/basics", "move.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabEvents) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(StartTestServer());
   ASSERT_TRUE(RunExtensionSubtest("tabs/basics", "events.html")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabRelativeURLs) {
-  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(StartTestServer());
   ASSERT_TRUE(RunExtensionSubtest("tabs/basics", "relative_urls.html"))
       << message_;
 }
@@ -87,3 +100,37 @@
   ASSERT_TRUE(StartTestServer());
   ASSERT_TRUE(RunExtensionTest("tabs/on_updated")) << message_;
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
+                       MAYBE_FocusWindowDoesNotExitFullscreen) {
+  browser()->window()->SetFullscreen(true);
+  bool is_fullscreen = browser()->window()->IsFullscreen();
+  ASSERT_TRUE(RunExtensionTest("window_update/focus")) << message_;
+  ASSERT_EQ(is_fullscreen, browser()->window()->IsFullscreen());
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
+                       MAYBE_UpdateWindowSizeExitsFullscreen) {
+  browser()->window()->SetFullscreen(true);
+  ASSERT_TRUE(RunExtensionTest("window_update/sizing")) << message_;
+  ASSERT_FALSE(browser()->window()->IsFullscreen());
+}
+
+#if defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FocusWindowDoesNotUnmaximize) {
+  gfx::NativeWindow window = browser()->window()->GetNativeHandle();
+  ::SendMessage(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+  ASSERT_TRUE(RunExtensionTest("window_update/focus")) << message_;
+  ASSERT_TRUE(::IsZoomed(window));
+}
+#endif  // OS_WIN
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabledByPref) {
+  ASSERT_TRUE(StartTestServer());
+
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kIncognitoEnabled, false);
+
+  // This makes sure that creating an incognito window fails due to pref
+  // (policy) being set.
+  ASSERT_TRUE(RunExtensionTest("tabs/incognito_disabled")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index b58e07c..1931ba2 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,6 @@
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_infobar_delegate.h"
 #include "chrome/browser/extensions/extension_tabs_module_constants.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -34,12 +33,13 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_error_utils.h"
 #include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/jpeg_codec.h"
-#include "gfx/codec/png_codec.h"
 #include "skia/ext/image_operations.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/jpeg_codec.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace keys = extension_tabs_module_constants;
 
@@ -154,7 +154,11 @@
   result->SetBoolean(keys::kIncognitoKey,
                      browser->profile()->IsOffTheRecord());
   result->SetBoolean(keys::kFocusedKey, browser->window()->IsActive());
-  gfx::Rect bounds = browser->window()->GetRestoredBounds();
+  gfx::Rect bounds;
+  if (browser->window()->IsMaximized() || browser->window()->IsFullscreen())
+    bounds = browser->window()->GetBounds();
+  else
+    bounds = browser->window()->GetRestoredBounds();
 
   result->SetInteger(keys::kLeftKey, bounds.x());
   result->SetInteger(keys::kTopKey, bounds.y());
@@ -435,6 +439,11 @@
     if (args->HasKey(keys::kIncognitoKey)) {
       EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kIncognitoKey,
                                                    &incognito));
+      if (!profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)) {
+        error_ = keys::kIncognitoModeIsDisabled;
+        return false;
+      }
+
       if (incognito)
         window_profile = window_profile->GetOffTheRecordProfile();
     }
@@ -495,6 +504,7 @@
   }
 
   gfx::Rect bounds = browser->window()->GetRestoredBounds();
+  bool set_bounds = false;
   // Any part of the bounds can optionally be set by the caller.
   int bounds_val;
   if (update_props->HasKey(keys::kLeftKey)) {
@@ -502,6 +512,7 @@
         keys::kLeftKey,
         &bounds_val));
     bounds.set_x(bounds_val);
+    set_bounds = true;
   }
 
   if (update_props->HasKey(keys::kTopKey)) {
@@ -509,6 +520,7 @@
         keys::kTopKey,
         &bounds_val));
     bounds.set_y(bounds_val);
+    set_bounds = true;
   }
 
   if (update_props->HasKey(keys::kWidthKey)) {
@@ -516,6 +528,7 @@
         keys::kWidthKey,
         &bounds_val));
     bounds.set_width(bounds_val);
+    set_bounds = true;
   }
 
   if (update_props->HasKey(keys::kHeightKey)) {
@@ -523,8 +536,10 @@
         keys::kHeightKey,
         &bounds_val));
     bounds.set_height(bounds_val);
+    set_bounds = true;
   }
-  browser->window()->SetBounds(bounds);
+  if (set_bounds)
+    browser->window()->SetBounds(bounds);
 
   bool selected_val = false;
   if (update_props->HasKey(keys::kFocusedKey)) {
@@ -776,15 +791,8 @@
     // JavaScript URLs can do the same kinds of things as cross-origin XHR, so
     // we need to check host permissions before allowing them.
     if (url.SchemeIs(chrome::kJavaScriptScheme)) {
-      const Extension* extension = GetExtension();
-      const std::vector<URLPattern> host_permissions =
-          extension->host_permissions();
-      if (!Extension::CanExecuteScriptOnPage(
-              contents->tab_contents()->GetURL(),
-              extension->CanExecuteScriptEverywhere(),
-              &host_permissions,
-              NULL,
-              &error_)) {
+      if (!GetExtension()->CanExecuteScriptOnPage(
+              contents->tab_contents()->GetURL(), NULL, &error_)) {
         return false;
       }
 
@@ -881,6 +889,11 @@
       return false;
     }
 
+    if (target_browser->profile() != source_browser->profile()) {
+      error_ = keys::kCanOnlyMoveTabsWithinSameProfileError;
+      return false;
+    }
+
     // If windowId is different from the current window, move between windows.
     if (ExtensionTabUtil::GetWindowId(target_browser) !=
         ExtensionTabUtil::GetWindowId(source_browser)) {
diff --git a/chrome/browser/extensions/extension_tabs_module_constants.cc b/chrome/browser/extensions/extension_tabs_module_constants.cc
index 6ea521f..74eff33 100644
--- a/chrome/browser/extensions/extension_tabs_module_constants.cc
+++ b/chrome/browser/extensions/extension_tabs_module_constants.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -54,6 +54,8 @@
 
 const char kCanOnlyMoveTabsWithinNormalWindowsError[] = "Tabs can only be "
     "moved to and from normal windows.";
+const char kCanOnlyMoveTabsWithinSameProfileError[] = "Tabs can only be moved "
+    "between windows in the same profile.";
 const char kNoCurrentWindowError[] = "No current window";
 const char kNoLastFocusedWindowError[] = "No last-focused window";
 const char kWindowNotFoundError[] = "No window with id: *.";
@@ -61,6 +63,7 @@
 const char kTabStripNotEditableError[] =
     "Tabs cannot be edited right now (user may be dragging a tab).";
 const char kNoSelectedTabError[] = "No selected tab";
+const char kIncognitoModeIsDisabled[] = "Incognito mode is disabled.";
 const char kInvalidUrlError[] = "Invalid url: \"*\".";
 const char kInternalVisibleTabCaptureError[] =
     "Internal error while trying to capture visible region of the current tab";
diff --git a/chrome/browser/extensions/extension_tabs_module_constants.h b/chrome/browser/extensions/extension_tabs_module_constants.h
index 4ac09de..977727d 100644
--- a/chrome/browser/extensions/extension_tabs_module_constants.h
+++ b/chrome/browser/extensions/extension_tabs_module_constants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -46,6 +46,7 @@
 
 // Value consts.
 extern const char kCanOnlyMoveTabsWithinNormalWindowsError[];
+extern const char kCanOnlyMoveTabsWithinSameProfileError[];
 extern const char kFormatValueJpeg[];
 extern const char kFormatValuePng[];
 extern const char kMimeTypeJpeg[];
@@ -63,6 +64,7 @@
 extern const char kTabNotFoundError[];
 extern const char kTabStripNotEditableError[];
 extern const char kNoSelectedTabError[];
+extern const char kIncognitoModeIsDisabled[];
 extern const char kInvalidUrlError[];
 extern const char kInternalVisibleTabCaptureError[];
 extern const char kNotImplementedError[];
diff --git a/chrome/browser/extensions/extension_tts_api_util.cc b/chrome/browser/extensions/extension_tts_api_util.cc
index b3ef18c..b630387 100644
--- a/chrome/browser/extensions/extension_tts_api_util.cc
+++ b/chrome/browser/extensions/extension_tts_api_util.cc
@@ -27,8 +27,8 @@
     if (!dict->GetInteger(key, &int_value))
       return false;
     *ret_value = int_value;
-  } else if (value->IsType(Value::TYPE_REAL)) {
-    if (!dict->GetReal(key, ret_value))
+  } else if (value->IsType(Value::TYPE_DOUBLE)) {
+    if (!dict->GetDouble(key, ret_value))
       return false;
   } else {
     return false;
diff --git a/chrome/browser/extensions/extension_tts_api_win.cc b/chrome/browser/extensions/extension_tts_api_win.cc
index a9a6062..5b2a846 100644
--- a/chrome/browser/extensions/extension_tts_api_win.cc
+++ b/chrome/browser/extensions/extension_tts_api_win.cc
@@ -85,8 +85,10 @@
     speech_synthesizer_->SetVolume(static_cast<uint16>(volume * 100));
   }
 
-  if (paused_)
+  if (paused_) {
     speech_synthesizer_->Resume();
+    paused_ = false;
+  }
   speech_synthesizer_->Speak(
       utterance.c_str(), SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL);
 
@@ -94,7 +96,7 @@
 }
 
 bool ExtensionTtsPlatformImplWin::StopSpeaking() {
-  if (!speech_synthesizer_ && !paused_) {
+  if (speech_synthesizer_ && !paused_) {
     speech_synthesizer_->Pause();
     paused_ = true;
   }
@@ -102,6 +104,16 @@
 }
 
 bool ExtensionTtsPlatformImplWin::IsSpeaking() {
+  if (speech_synthesizer_ && !paused_) {
+    SPVOICESTATUS status;
+    HRESULT result = speech_synthesizer_->GetStatus(&status, NULL);
+    if (result == S_OK) {
+      if (status.dwRunningState == 0 ||  // 0 == waiting to speak
+          status.dwRunningState == SPRS_IS_SPEAKING) {
+        return true;
+      }
+    }
+  }
   return false;
 }
 
diff --git a/chrome/browser/extensions/extension_tts_apitest.cc b/chrome/browser/extensions/extension_tts_apitest.cc
index f7ed0d8..560235d 100644
--- a/chrome/browser/extensions/extension_tts_apitest.cc
+++ b/chrome/browser/extensions/extension_tts_apitest.cc
@@ -180,7 +180,13 @@
   ASSERT_TRUE(RunExtensionTest("tts/speak_error")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(TtsApiTest, Provide) {
+#if defined(OS_WIN)
+// Flakily fails on Windows: http://crbug.com/70198
+#define MAYBE_Provide FLAKY_Provide
+#else
+#define MAYBE_Provide Provide
+#endif
+IN_PROC_BROWSER_TEST_F(TtsApiTest, MAYBE_Provide) {
   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
       .WillRepeatedly(Return(true));
   EXPECT_CALL(mock_platform_impl_, IsSpeaking())
diff --git a/chrome/browser/extensions/extension_ui_unittest.cc b/chrome/browser/extensions/extension_ui_unittest.cc
index 1bda60a..5980109 100644
--- a/chrome/browser/extensions/extension_ui_unittest.cc
+++ b/chrome/browser/extensions/extension_ui_unittest.cc
@@ -53,7 +53,7 @@
     // Produce test output.
     scoped_ptr<DictionaryValue> actual_output_data(
         ExtensionsDOMHandler::CreateExtensionDetailValue(NULL, extension.get(),
-                                                         pages, true));
+                                                         pages, true, false));
 
     // Compare the outputs.
     return expected_output_data->Equals(actual_output_data.get());
diff --git a/chrome/browser/extensions/extension_uitest.cc b/chrome/browser/extensions/extension_uitest.cc
index 845696e..e00957d 100644
--- a/chrome/browser/extensions/extension_uitest.cc
+++ b/chrome/browser/extensions/extension_uitest.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
+#include "base/test/test_timeouts.h"
 #include "base/values.h"
 #include "chrome/browser/automation/extension_automation_constants.h"
 #include "chrome/browser/extensions/extension_tabs_module_constants.h"
@@ -15,10 +16,10 @@
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_test.h"
 #include "chrome/test/ui_test_utils.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
 #include "testing/gmock_mutant.h"
+#include "ui/gfx/rect.h"
 
 namespace {
 
@@ -144,7 +145,7 @@
       GURL("chrome-extension://pmgpglkggjdpkpghhdmbdhababjpcohk/test.html"),
       GURL("")));
 
-  loop_.RunFor(action_max_timeout_ms());
+  loop_.RunFor(TestTimeouts::action_max_timeout_ms());
   ASSERT_FALSE(message_received.empty());
 
   scoped_ptr<Value> message_value(base::JSONReader::Read(message_received,
@@ -297,7 +298,7 @@
 
   // CheckAndSendResponse (called by OnForwardMessageToExternalHost)
   // will end the loop once it has received both of our expected messages.
-  loop_.RunFor(action_max_timeout_ms());
+  loop_.RunFor(TestTimeouts::action_max_timeout_ms());
 }
 
 class ExtensionTestBrowserEvents : public ExtensionUITest {
@@ -484,7 +485,7 @@
 
   // HandleMessageFromChrome (called by OnForwardMessageToExternalHost) ends
   // the loop when we've received the number of response messages we expect.
-  loop_.RunFor(action_max_timeout_ms());
+  loop_.RunFor(TestTimeouts::action_max_timeout_ms());
 
   // If this assert hits and the actual size is 0 then you need to look at:
   // src\chrome\test\data\extensions\uitest\event_sink\test.html and see if
diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc
index 04fb637..8e8aa72 100644
--- a/chrome/browser/extensions/extension_updater.cc
+++ b/chrome/browser/extensions/extension_updater.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -336,7 +336,7 @@
     }
     if (file_util::WriteFile(path, data.c_str(), data.length()) !=
         static_cast<int>(data.length())) {
-      // TODO(asargent) - It would be nice to back off updating alltogether if
+      // TODO(asargent) - It would be nice to back off updating altogether if
       // the disk is full. (http://crbug.com/12763).
       LOG(ERROR) << "Failed to write temporary file";
       file_util::Delete(path, false);
@@ -357,6 +357,20 @@
   ~ExtensionUpdaterFileHandler() {}
 };
 
+ExtensionUpdater::ExtensionFetch::ExtensionFetch()
+    : id(""),
+      url(),
+      package_hash(""),
+      version("") {}
+
+ExtensionUpdater::ExtensionFetch::ExtensionFetch(const std::string& i,
+                                                 const GURL& u,
+                                                 const std::string& h,
+                                                 const std::string& v)
+    : id(i), url(u), package_hash(h), version(v) {}
+
+ExtensionUpdater::ExtensionFetch::~ExtensionFetch() {}
+
 ExtensionUpdater::ExtensionUpdater(ExtensionUpdateService* service,
                                    PrefService* prefs,
                                    int frequency_seconds)
@@ -463,8 +477,11 @@
 }
 
 void ExtensionUpdater::OnURLFetchComplete(
-    const URLFetcher* source, const GURL& url, const URLRequestStatus& status,
-    int response_code, const ResponseCookies& cookies,
+    const URLFetcher* source,
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
     const std::string& data) {
   // Stop() destroys all our URLFetchers, which means we shouldn't be
   // called after Stop() is called.
@@ -553,13 +570,15 @@
 };
 
 
-void ExtensionUpdater::OnManifestFetchComplete(const GURL& url,
-                                               const URLRequestStatus& status,
-                                               int response_code,
-                                               const std::string& data) {
+void ExtensionUpdater::OnManifestFetchComplete(
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const std::string& data) {
   // We want to try parsing the manifest, and if it indicates updates are
   // available, we want to fire off requests to fetch those updates.
-  if (status.status() == URLRequestStatus::SUCCESS && response_code == 200) {
+  if (status.status() == net::URLRequestStatus::SUCCESS &&
+      (response_code == 200 || (url.SchemeIsFile() && data.length() > 0))) {
     scoped_refptr<SafeManifestParser> safe_parser(
         new SafeManifestParser(data, current_manifest_fetch_.release(), this));
     safe_parser->Start();
@@ -643,11 +662,11 @@
 }
 
 void ExtensionUpdater::OnCRXFetchComplete(const GURL& url,
-                                          const URLRequestStatus& status,
+                                          const net::URLRequestStatus& status,
                                           int response_code,
                                           const std::string& data) {
-  if (status.status() == URLRequestStatus::SUCCESS &&
-      response_code == 200) {
+  if (status.status() == net::URLRequestStatus::SUCCESS &&
+      (response_code == 200 || (url.SchemeIsFile() && data.length() > 0))) {
     if (current_extension_fetch_.id == kBlacklistAppID) {
       ProcessBlacklist(data);
     } else {
@@ -761,7 +780,7 @@
 
   // Start a fetch of the blacklist if needed.
   if (blacklist_checks_enabled_ && service_->HasInstalledExtensions()) {
-    // Note: it is very important that we use the https version of the update
+    // Note: it is very important that we use  the https version of the update
     // url here to avoid DNS hijacking of the blacklist, which is not validated
     // by a public key signature like .crx files are.
     ManifestFetchData* blacklist_fetch =
@@ -891,7 +910,8 @@
     manifest_fetcher_.reset(
         URLFetcher::Create(kManifestFetcherId, fetch_data->full_url(),
                            URLFetcher::GET, this));
-    manifest_fetcher_->set_request_context(Profile::GetDefaultRequestContext());
+    manifest_fetcher_->set_request_context(
+        service_->profile()->GetRequestContext());
     manifest_fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES |
                                       net::LOAD_DO_NOT_SAVE_COOKIES |
                                       net::LOAD_DISABLE_CACHE);
@@ -919,7 +939,7 @@
     extension_fetcher_.reset(
         URLFetcher::Create(kExtensionFetcherId, url, URLFetcher::GET, this));
     extension_fetcher_->set_request_context(
-        Profile::GetDefaultRequestContext());
+        service_->profile()->GetRequestContext());
     extension_fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES |
                                        net::LOAD_DO_NOT_SAVE_COOKIES |
                                        net::LOAD_DISABLE_CACHE);
diff --git a/chrome/browser/extensions/extension_updater.h b/chrome/browser/extensions/extension_updater.h
index 3d7986c..d5ed01f 100644
--- a/chrome/browser/extensions/extension_updater.h
+++ b/chrome/browser/extensions/extension_updater.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -178,14 +178,15 @@
   // We need to keep track of some information associated with a url
   // when doing a fetch.
   struct ExtensionFetch {
+    ExtensionFetch();
+    ExtensionFetch(const std::string& i, const GURL& u,
+                   const std::string& h, const std::string& v);
+    ~ExtensionFetch();
+
     std::string id;
     GURL url;
     std::string package_hash;
     std::string version;
-    ExtensionFetch() : id(""), url(), package_hash(""), version("") {}
-    ExtensionFetch(const std::string& i, const GURL& u,
-      const std::string& h, const std::string& v)
-      : id(i), url(u), package_hash(h), version(v) {}
   };
 
   // These are needed for unit testing, to help identify the correct mock
diff --git a/chrome/browser/extensions/extension_updater_unittest.cc b/chrome/browser/extensions/extension_updater_unittest.cc
index d806b6e..0fb7119 100644
--- a/chrome/browser/extensions/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/extension_updater_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,6 +23,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/net/test_url_fetcher_factory.h"
+#include "chrome/test/testing_profile.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request_status.h"
@@ -86,12 +87,16 @@
 
   virtual ExtensionPrefs* extension_prefs() { return prefs_.prefs(); }
 
+  virtual Profile* profile() { return &profile_; }
+
   PrefService* pref_service() { return prefs_.pref_service(); }
 
   // Creates test extensions and inserts them into list. The name and
   // version are all based on their index. If |update_url| is non-null, it
   // will be used as the update_url for each extension.
-  void CreateTestExtensions(int count, ExtensionList *list,
+  // The |id| is used to distinguish extension names and make sure that
+  // no two extensions share the same name.
+  void CreateTestExtensions(int id, int count, ExtensionList *list,
                             const std::string* update_url,
                             Extension::Location location) {
     for (int i = 1; i <= count; i++) {
@@ -99,7 +104,7 @@
       manifest.SetString(extension_manifest_keys::kVersion,
                          base::StringPrintf("%d.0.0.0", i));
       manifest.SetString(extension_manifest_keys::kName,
-                         base::StringPrintf("Extension %d", i));
+                         base::StringPrintf("Extension %d.%d", id, i));
       if (update_url)
         manifest.SetString(extension_manifest_keys::kUpdateURL, *update_url);
       scoped_refptr<Extension> e =
@@ -112,6 +117,7 @@
  protected:
   PendingExtensionMap pending_extensions_;
   TestExtensionPrefs prefs_;
+  TestingProfile profile_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockService);
@@ -316,7 +322,7 @@
       CreateTestPendingExtensions(1, GURL(update_url), &pending_extensions);
       service.set_pending_extensions(pending_extensions);
     } else {
-      service.CreateTestExtensions(1, &extensions, &update_url,
+      service.CreateTestExtensions(1, 1, &extensions, &update_url,
                                    Extension::INTERNAL);
       service.set_extensions(extensions);
     }
@@ -468,7 +474,7 @@
     ExtensionList extensions;
     std::string url(gallery_url);
 
-    service.CreateTestExtensions(1, &extensions, &url, Extension::INTERNAL);
+    service.CreateTestExtensions(1, 1, &extensions, &url, Extension::INTERNAL);
     builder.AddExtension(*extensions[0]);
     std::vector<ManifestFetchData*> fetches = builder.GetFetches();
     EXPECT_EQ(1u, fetches.size());
@@ -488,7 +494,7 @@
     // Create a set of test extensions
     ServiceForManifestTests service;
     ExtensionList tmp;
-    service.CreateTestExtensions(3, &tmp, NULL, Extension::INTERNAL);
+    service.CreateTestExtensions(1, 3, &tmp, NULL, Extension::INTERNAL);
     service.set_extensions(tmp);
 
     MessageLoop message_loop;
@@ -591,7 +597,7 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, url1, URLRequestStatus(), 200, ResponseCookies(),
+        fetcher, url1, net::URLRequestStatus(), 200, ResponseCookies(),
         invalid_xml);
 
     // Now that the first request is complete, make sure the second one has
@@ -609,7 +615,7 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, url2, URLRequestStatus(), 200, ResponseCookies(),
+        fetcher, url2, net::URLRequestStatus(), 200, ResponseCookies(),
         kValidXml);
 
     // This should run the manifest parsing, then we want to make sure that our
@@ -666,7 +672,7 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, test_url, URLRequestStatus(), 200, ResponseCookies(),
+        fetcher, test_url, net::URLRequestStatus(), 200, ResponseCookies(),
         extension_data);
 
     file_thread.Stop();
@@ -716,7 +722,7 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, test_url, URLRequestStatus(), 200, ResponseCookies(),
+        fetcher, test_url, net::URLRequestStatus(), 200, ResponseCookies(),
         extension_data);
 
     message_loop.RunAllPending();
@@ -768,7 +774,7 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, url1, URLRequestStatus(), 200, ResponseCookies(),
+        fetcher, url1, net::URLRequestStatus(), 200, ResponseCookies(),
         extension_data1);
     message_loop.RunAllPending();
 
@@ -787,7 +793,7 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     EXPECT_TRUE(fetcher->load_flags() == expected_load_flags);
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, url2, URLRequestStatus(), 200, ResponseCookies(),
+        fetcher, url2, net::URLRequestStatus(), 200, ResponseCookies(),
         extension_data2);
     message_loop.RunAllPending();
     EXPECT_EQ(id2, service.extension_id());
@@ -812,9 +818,9 @@
     ExtensionList tmp;
     GURL url1("http://clients2.google.com/service/update2/crx");
     GURL url2("http://www.somewebsite.com");
-    service.CreateTestExtensions(1, &tmp, &url1.possibly_invalid_spec(),
+    service.CreateTestExtensions(1, 1, &tmp, &url1.possibly_invalid_spec(),
                                  Extension::INTERNAL);
-    service.CreateTestExtensions(1, &tmp, &url2.possibly_invalid_spec(),
+    service.CreateTestExtensions(2, 1, &tmp, &url2.possibly_invalid_spec(),
                                  Extension::INTERNAL);
     EXPECT_EQ(2u, tmp.size());
     service.set_extensions(tmp);
@@ -845,7 +851,8 @@
     EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
     fetched_urls.push_back(fetcher->original_url());
     fetcher->delegate()->OnURLFetchComplete(
-      fetcher, fetched_urls[0], URLRequestStatus(), 500, ResponseCookies(), "");
+      fetcher, fetched_urls[0], net::URLRequestStatus(), 500,
+      ResponseCookies(), "");
     fetcher =
       factory.GetFetcherByID(ExtensionUpdater::kManifestFetcherId);
     fetched_urls.push_back(fetcher->original_url());
@@ -891,7 +898,7 @@
 
     GURL update_url("http://www.google.com/manifest");
     ExtensionList tmp;
-    service.CreateTestExtensions(1, &tmp, &update_url.spec(),
+    service.CreateTestExtensions(1, 1, &tmp, &update_url.spec(),
                                  Extension::INTERNAL);
     service.set_extensions(tmp);
 
@@ -986,7 +993,7 @@
   // Non-internal non-external extensions should be rejected.
   {
     ExtensionList extensions;
-    service.CreateTestExtensions(1, &extensions, NULL, Extension::INVALID);
+    service.CreateTestExtensions(1, 1, &extensions, NULL, Extension::INVALID);
     ASSERT_FALSE(extensions.empty());
     builder.AddExtension(*extensions[0]);
     EXPECT_TRUE(builder.GetFetches().empty());
@@ -1063,8 +1070,6 @@
 // TODO(asargent) - (http://crbug.com/12780) add tests for:
 // -prodversionmin (shouldn't update if browser version too old)
 // -manifests & updates arriving out of order / interleaved
-// -Profile::GetDefaultRequestContext() returning null
-//  (should not crash, but just do check later)
 // -malformed update url (empty, file://, has query, has a # fragment, etc.)
 // -An extension gets uninstalled while updates are in progress (so it doesn't
 //  "come back from the dead")
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
new file mode 100644
index 0000000..2d5aff3
--- /dev/null
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -0,0 +1,409 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/extension_web_ui.h"
+
+#include <set>
+#include <vector>
+
+#include "net/base/file_stream.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/bindings_policy.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_icon_set.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/page_transition_types.h"
+#include "chrome/common/url_constants.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/favicon_size.h"
+
+namespace {
+
+// De-dupes the items in |list|. Assumes the values are strings.
+void CleanUpDuplicates(ListValue* list) {
+  std::set<std::string> seen_values;
+
+  // Loop backwards as we may be removing items.
+  for (size_t i = list->GetSize() - 1; (i + 1) > 0; --i) {
+    std::string value;
+    if (!list->GetString(i, &value)) {
+      NOTREACHED();
+      continue;
+    }
+
+    if (seen_values.find(value) == seen_values.end())
+      seen_values.insert(value);
+    else
+      list->Remove(i, NULL);
+  }
+}
+
+// Helper class that is used to track the loading of the favicon of an
+// extension.
+class ExtensionWebUIImageLoadingTracker : public ImageLoadingTracker::Observer {
+ public:
+  ExtensionWebUIImageLoadingTracker(Profile* profile,
+                                    FaviconService::GetFaviconRequest* request,
+                                    const GURL& page_url)
+      : ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
+        request_(request),
+        extension_(NULL) {
+    // Even when the extensions service is enabled by default, it's still
+    // disabled in incognito mode.
+    ExtensionService* service = profile->GetExtensionService();
+    if (service)
+      extension_ = service->GetExtensionByURL(page_url);
+  }
+
+  void Init() {
+    if (extension_) {
+      ExtensionResource icon_resource =
+          extension_->GetIconResource(Extension::EXTENSION_ICON_BITTY,
+                                      ExtensionIconSet::MATCH_EXACTLY);
+
+      tracker_.LoadImage(extension_, icon_resource,
+                         gfx::Size(kFavIconSize, kFavIconSize),
+                         ImageLoadingTracker::DONT_CACHE);
+    } else {
+      ForwardResult(NULL);
+    }
+  }
+
+  virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
+                             int index) {
+    if (image) {
+      std::vector<unsigned char> image_data;
+      if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_data)) {
+        NOTREACHED() << "Could not encode extension favicon";
+      }
+      ForwardResult(RefCountedBytes::TakeVector(&image_data));
+    } else {
+      ForwardResult(NULL);
+    }
+  }
+
+ private:
+  ~ExtensionWebUIImageLoadingTracker() {}
+
+  // Forwards the result on the request. If no favicon was available then
+  // |icon_data| may be backed by NULL. Once the result has been forwarded the
+  // instance is deleted.
+  void ForwardResult(scoped_refptr<RefCountedMemory> icon_data) {
+    bool know_icon = icon_data.get() != NULL && icon_data->size() > 0;
+    request_->ForwardResultAsync(
+        FaviconService::FaviconDataCallback::TupleType(request_->handle(),
+            know_icon, icon_data, false, GURL()));
+    delete this;
+  }
+
+  ImageLoadingTracker tracker_;
+  scoped_refptr<FaviconService::GetFaviconRequest> request_;
+  const Extension* extension_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionWebUIImageLoadingTracker);
+};
+
+}  // namespace
+
+const char ExtensionWebUI::kExtensionURLOverrides[] =
+    "extensions.chrome_url_overrides";
+
+ExtensionWebUI::ExtensionWebUI(TabContents* tab_contents, const GURL& url)
+    : WebUI(tab_contents),
+      url_(url) {
+  ExtensionService* service = tab_contents->profile()->GetExtensionService();
+  const Extension* extension = service->GetExtensionByURL(url);
+  if (!extension)
+    extension = service->GetExtensionByWebExtent(url);
+  DCHECK(extension);
+  // Only hide the url for internal pages (e.g. chrome-extension or packaged
+  // component apps like bookmark manager.
+  should_hide_url_ = !extension->is_hosted_app();
+
+  bindings_ = BindingsPolicy::EXTENSION;
+  // Bind externalHost to Extension WebUI loaded in Chrome Frame.
+  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+  if (browser_command_line.HasSwitch(switches::kChromeFrame))
+    bindings_ |= BindingsPolicy::EXTERNAL_HOST;
+  // For chrome:// overrides, some of the defaults are a little different.
+  GURL effective_url = tab_contents->GetURL();
+  if (effective_url.SchemeIs(chrome::kChromeUIScheme) &&
+      effective_url.host() == chrome::kChromeUINewTabHost) {
+    focus_location_bar_by_default_ = true;
+  }
+}
+
+ExtensionWebUI::~ExtensionWebUI() {}
+
+void ExtensionWebUI::ResetExtensionFunctionDispatcher(
+    RenderViewHost* render_view_host) {
+  // TODO(jcivelli): http://crbug.com/60608 we should get the URL out of the
+  //                 active entry of the navigation controller.
+  extension_function_dispatcher_.reset(
+      ExtensionFunctionDispatcher::Create(render_view_host, this, url_));
+  DCHECK(extension_function_dispatcher_.get());
+}
+
+void ExtensionWebUI::ResetExtensionBookmarkManagerEventRouter() {
+  // Hack: A few things we specialize just for the bookmark manager.
+  if (extension_function_dispatcher_->extension_id() ==
+      extension_misc::kBookmarkManagerId) {
+    extension_bookmark_manager_event_router_.reset(
+        new ExtensionBookmarkManagerEventRouter(GetProfile(), tab_contents()));
+
+    link_transition_type_ = PageTransition::AUTO_BOOKMARK;
+  }
+}
+
+void ExtensionWebUI::RenderViewCreated(RenderViewHost* render_view_host) {
+  ResetExtensionFunctionDispatcher(render_view_host);
+  ResetExtensionBookmarkManagerEventRouter();
+}
+
+void ExtensionWebUI::RenderViewReused(RenderViewHost* render_view_host) {
+  ResetExtensionFunctionDispatcher(render_view_host);
+  ResetExtensionBookmarkManagerEventRouter();
+}
+
+void ExtensionWebUI::ProcessWebUIMessage(
+    const ViewHostMsg_DomMessage_Params& params) {
+  extension_function_dispatcher_->HandleRequest(params);
+}
+
+Browser* ExtensionWebUI::GetBrowser() {
+  TabContents* contents = tab_contents();
+  TabContentsIterator tab_iterator;
+  for (; !tab_iterator.done(); ++tab_iterator) {
+    if (contents == *tab_iterator)
+      return tab_iterator.browser();
+  }
+
+  return NULL;
+}
+
+TabContents* ExtensionWebUI::associated_tab_contents() const {
+  return tab_contents();
+}
+
+ExtensionBookmarkManagerEventRouter*
+ExtensionWebUI::extension_bookmark_manager_event_router() {
+  return extension_bookmark_manager_event_router_.get();
+}
+
+gfx::NativeWindow ExtensionWebUI::GetCustomFrameNativeWindow() {
+  if (GetBrowser())
+    return NULL;
+
+  // If there was no browser associated with the function dispatcher delegate,
+  // then this WebUI may be hosted in an ExternalTabContainer, and a framing
+  // window will be accessible through the tab_contents.
+  TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
+  if (tab_contents_delegate)
+    return tab_contents_delegate->GetFrameNativeWindow();
+  else
+    return NULL;
+}
+
+gfx::NativeView ExtensionWebUI::GetNativeViewOfHost() {
+  return tab_contents()->GetRenderWidgetHostView()->GetNativeView();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// chrome:// URL overrides
+
+// static
+void ExtensionWebUI::RegisterUserPrefs(PrefService* prefs) {
+  prefs->RegisterDictionaryPref(kExtensionURLOverrides);
+}
+
+// static
+bool ExtensionWebUI::HandleChromeURLOverride(GURL* url, Profile* profile) {
+  if (!url->SchemeIs(chrome::kChromeUIScheme))
+    return false;
+
+  const DictionaryValue* overrides =
+      profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
+  std::string page = url->host();
+  ListValue* url_list;
+  if (!overrides || !overrides->GetList(page, &url_list))
+    return false;
+
+  ExtensionService* service = profile->GetExtensionService();
+
+  size_t i = 0;
+  while (i < url_list->GetSize()) {
+    Value* val = NULL;
+    url_list->Get(i, &val);
+
+    // Verify that the override value is good.  If not, unregister it and find
+    // the next one.
+    std::string override;
+    if (!val->GetAsString(&override)) {
+      NOTREACHED();
+      UnregisterChromeURLOverride(page, profile, val);
+      continue;
+    }
+    GURL extension_url(override);
+    if (!extension_url.is_valid()) {
+      NOTREACHED();
+      UnregisterChromeURLOverride(page, profile, val);
+      continue;
+    }
+
+    // Verify that the extension that's being referred to actually exists.
+    const Extension* extension = service->GetExtensionByURL(extension_url);
+    if (!extension) {
+      // This can currently happen if you use --load-extension one run, and
+      // then don't use it the next.  It could also happen if an extension
+      // were deleted directly from the filesystem, etc.
+      LOG(WARNING) << "chrome URL override present for non-existant extension";
+      UnregisterChromeURLOverride(page, profile, val);
+      continue;
+    }
+
+    // We can't handle chrome-extension URLs in incognito mode unless the
+    // extension uses split mode.
+    bool incognito_override_allowed =
+        extension->incognito_split_mode() &&
+        service->IsIncognitoEnabled(extension);
+    if (profile->IsOffTheRecord() && !incognito_override_allowed) {
+      ++i;
+      continue;
+    }
+
+    *url = extension_url;
+    return true;
+  }
+  return false;
+}
+
+// static
+void ExtensionWebUI::RegisterChromeURLOverrides(
+    Profile* profile, const Extension::URLOverrideMap& overrides) {
+  if (overrides.empty())
+    return;
+
+  PrefService* prefs = profile->GetPrefs();
+  DictionaryValue* all_overrides =
+      prefs->GetMutableDictionary(kExtensionURLOverrides);
+
+  // For each override provided by the extension, add it to the front of
+  // the override list if it's not already in the list.
+  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
+  for (; iter != overrides.end(); ++iter) {
+    const std::string& key = iter->first;
+    ListValue* page_overrides;
+    if (!all_overrides->GetList(key, &page_overrides)) {
+      page_overrides = new ListValue();
+      all_overrides->Set(key, page_overrides);
+    } else {
+      CleanUpDuplicates(page_overrides);
+
+      // Verify that the override isn't already in the list.
+      ListValue::iterator i = page_overrides->begin();
+      for (; i != page_overrides->end(); ++i) {
+        std::string override_val;
+        if (!(*i)->GetAsString(&override_val)) {
+          NOTREACHED();
+          continue;
+        }
+        if (override_val == iter->second.spec())
+          break;
+      }
+      // This value is already in the list, leave it alone.
+      if (i != page_overrides->end())
+        continue;
+    }
+    // Insert the override at the front of the list.  Last registered override
+    // wins.
+    page_overrides->Insert(0, new StringValue(iter->second.spec()));
+  }
+}
+
+// static
+void ExtensionWebUI::UnregisterAndReplaceOverride(const std::string& page,
+    Profile* profile, ListValue* list, Value* override) {
+  int index = list->Remove(*override);
+  if (index == 0) {
+    // This is the active override, so we need to find all existing
+    // tabs for this override and get them to reload the original URL.
+    for (TabContentsIterator iterator; !iterator.done(); ++iterator) {
+      TabContents* tab = *iterator;
+      if (tab->profile() != profile)
+        continue;
+
+      GURL url = tab->GetURL();
+      if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page)
+        continue;
+
+      // Don't use Reload() since |url| isn't the same as the internal URL
+      // that NavigationController has.
+      tab->controller().LoadURL(url, url, PageTransition::RELOAD);
+    }
+  }
+}
+
+// static
+void ExtensionWebUI::UnregisterChromeURLOverride(const std::string& page,
+    Profile* profile, Value* override) {
+  if (!override)
+    return;
+  PrefService* prefs = profile->GetPrefs();
+  DictionaryValue* all_overrides =
+      prefs->GetMutableDictionary(kExtensionURLOverrides);
+  ListValue* page_overrides;
+  if (!all_overrides->GetList(page, &page_overrides)) {
+    // If it's being unregistered, it should already be in the list.
+    NOTREACHED();
+    return;
+  } else {
+    UnregisterAndReplaceOverride(page, profile, page_overrides, override);
+  }
+}
+
+// static
+void ExtensionWebUI::UnregisterChromeURLOverrides(
+    Profile* profile, const Extension::URLOverrideMap& overrides) {
+  if (overrides.empty())
+    return;
+  PrefService* prefs = profile->GetPrefs();
+  DictionaryValue* all_overrides =
+      prefs->GetMutableDictionary(kExtensionURLOverrides);
+  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
+  for (; iter != overrides.end(); ++iter) {
+    const std::string& page = iter->first;
+    ListValue* page_overrides;
+    if (!all_overrides->GetList(page, &page_overrides)) {
+      // If it's being unregistered, it should already be in the list.
+      NOTREACHED();
+      continue;
+    } else {
+      StringValue override(iter->second.spec());
+      UnregisterAndReplaceOverride(iter->first, profile,
+                                   page_overrides, &override);
+    }
+  }
+}
+
+// static
+void ExtensionWebUI::GetFaviconForURL(Profile* profile,
+    FaviconService::GetFaviconRequest* request, const GURL& page_url) {
+  // tracker deletes itself when done.
+  ExtensionWebUIImageLoadingTracker* tracker =
+      new ExtensionWebUIImageLoadingTracker(profile, request, page_url);
+  tracker->Init();
+}
diff --git a/chrome/browser/extensions/extension_web_ui.h b/chrome/browser/extensions/extension_web_ui.h
new file mode 100644
index 0000000..50c2a61
--- /dev/null
+++ b/chrome/browser/extensions/extension_web_ui.h
@@ -0,0 +1,106 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_WEB_UI_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEB_UI_H_
+#pragma once
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/dom_ui/web_ui.h"
+#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
+#include "chrome/browser/favicon_service.h"
+#include "chrome/common/extensions/extension.h"
+
+class GURL;
+class ListValue;
+class PrefService;
+class Profile;
+class RenderViewHost;
+class TabContents;
+struct ViewHostMsg_DomMessage_Params;
+
+// This class implements WebUI for extensions and allows extensions to put UI in
+// the main tab contents area. For example, each extension can specify an
+// "options_page", and that page is displayed in the tab contents area and is
+// hosted by this class.
+class ExtensionWebUI
+    : public WebUI,
+      public ExtensionFunctionDispatcher::Delegate {
+ public:
+  static const char kExtensionURLOverrides[];
+
+  explicit ExtensionWebUI(TabContents* tab_contents, const GURL& url);
+
+  virtual ~ExtensionWebUI();
+
+  ExtensionFunctionDispatcher* extension_function_dispatcher() const {
+    return extension_function_dispatcher_.get();
+  }
+
+  // WebUI
+  virtual void RenderViewCreated(RenderViewHost* render_view_host);
+  virtual void RenderViewReused(RenderViewHost* render_view_host);
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
+
+  // ExtensionFunctionDispatcher::Delegate
+  virtual Browser* GetBrowser();
+  virtual gfx::NativeView GetNativeViewOfHost();
+  virtual gfx::NativeWindow GetCustomFrameNativeWindow();
+  virtual TabContents* associated_tab_contents() const;
+
+  virtual ExtensionBookmarkManagerEventRouter*
+      extension_bookmark_manager_event_router();
+
+  // BrowserURLHandler
+  static bool HandleChromeURLOverride(GURL* url, Profile* profile);
+
+  // Register and unregister a dictionary of one or more overrides.
+  // Page names are the keys, and chrome-extension: URLs are the values.
+  // (e.g. { "newtab": "chrome-extension://<id>/my_new_tab.html" }
+  static void RegisterChromeURLOverrides(Profile* profile,
+      const Extension::URLOverrideMap& overrides);
+  static void UnregisterChromeURLOverrides(Profile* profile,
+      const Extension::URLOverrideMap& overrides);
+  static void UnregisterChromeURLOverride(const std::string& page,
+                                          Profile* profile,
+                                          Value* override);
+
+  // Called from BrowserPrefs
+  static void RegisterUserPrefs(PrefService* prefs);
+
+  // Get the favicon for the extension by getting an icon from the manifest.
+  static void GetFaviconForURL(Profile* profile,
+                               FaviconService::GetFaviconRequest* request,
+                               const GURL& page_url);
+
+ private:
+  // Unregister the specified override, and if it's the currently active one,
+  // ensure that something takes its place.
+  static void UnregisterAndReplaceOverride(const std::string& page,
+                                           Profile* profile,
+                                           ListValue* list,
+                                           Value* override);
+
+  // When the RenderViewHost changes (RenderViewCreated and RenderViewReused),
+  // we need to reset the ExtensionFunctionDispatcher so it's talking to the
+  // right one, as well as being linked to the correct URL.
+  void ResetExtensionFunctionDispatcher(RenderViewHost* render_view_host);
+
+  void ResetExtensionBookmarkManagerEventRouter();
+
+  scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
+
+  // TODO(aa): This seems out of place. Why is it not with the event routers for
+  // the other extension APIs?
+  scoped_ptr<ExtensionBookmarkManagerEventRouter>
+      extension_bookmark_manager_event_router_;
+
+  // The URL this WebUI was created for.
+  GURL url_;
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEB_UI_H_
diff --git a/chrome/browser/extensions/extension_webnavigation_api.cc b/chrome/browser/extensions/extension_webnavigation_api.cc
index 2e3a1ca..0a4db21 100644
--- a/chrome/browser/extensions/extension_webnavigation_api.cc
+++ b/chrome/browser/extensions/extension_webnavigation_api.cc
@@ -15,8 +15,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/provisional_load_details.h"
-#include "chrome/common/notification_type.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_service.h"
+#include "chrome/common/render_messages_params.h"
 #include "net/base/net_errors.h"
 
 namespace keys = extension_webnavigation_api_constants;
@@ -126,6 +127,9 @@
                    NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
                    NotificationService::AllSources());
     registrar_.Add(this,
+                   NotificationType::CREATING_NEW_WINDOW,
+                   NotificationService::AllSources());
+    registrar_.Add(this,
                    NotificationType::TAB_CONTENTS_DESTROYED,
                    NotificationService::AllSources());
   }
@@ -161,6 +165,11 @@
           Source<NavigationController>(source).ptr(),
           Details<ProvisionalLoadDetails>(details).ptr());
       break;
+    case NotificationType::CREATING_NEW_WINDOW:
+      CreatingNewWindow(
+          Source<TabContents>(source).ptr(),
+          Details<const ViewHostMsg_CreateWindow_Params>(details).ptr());
+      break;
     case NotificationType::TAB_CONTENTS_DESTROYED:
       navigation_state_.RemoveTabContentsState(
           Source<TabContents>(source).ptr());
@@ -187,7 +196,7 @@
   dict->SetString(keys::kUrlKey, details->url().spec());
   dict->SetInteger(keys::kFrameIdKey, GetFrameId(details));
   dict->SetInteger(keys::kRequestIdKey, 0);
-  dict->SetReal(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
+  dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
   args.Append(dict);
 
   std::string json_args;
@@ -212,7 +221,7 @@
   dict->SetString(keys::kTransitionQualifiersKey,
                   PageTransition::QualifierString(
                       details->transition_type()));
-  dict->SetReal(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
+  dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
   args.Append(dict);
 
   std::string json_args;
@@ -232,7 +241,7 @@
   dict->SetString(keys::kUrlKey, navigation_state_.GetUrl(frame_id).spec());
   dict->SetInteger(keys::kFrameIdKey,
       navigation_state_.IsMainFrame(frame_id) ? 0 : static_cast<int>(frame_id));
-  dict->SetReal(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
+  dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
   args.Append(dict);
 
   std::string json_args;
@@ -252,7 +261,7 @@
   dict->SetString(keys::kUrlKey, navigation_state_.GetUrl(frame_id).spec());
   dict->SetInteger(keys::kFrameIdKey,
       navigation_state_.IsMainFrame(frame_id) ? 0 : static_cast<int>(frame_id));
-  dict->SetReal(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
+  dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
   args.Append(dict);
 
   std::string json_args;
@@ -273,7 +282,7 @@
   dict->SetInteger(keys::kFrameIdKey, GetFrameId(details));
   dict->SetString(keys::kErrorKey,
                   std::string(net::ErrorToString(details->error_code())));
-  dict->SetReal(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
+  dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
   args.Append(dict);
 
   std::string json_args;
@@ -282,6 +291,24 @@
   DispatchEvent(controller->profile(), keys::kOnErrorOccurred, json_args);
 }
 
+void ExtensionWebNavigationEventRouter::CreatingNewWindow(
+    TabContents* tab_contents,
+    const ViewHostMsg_CreateWindow_Params* details) {
+  ListValue args;
+  DictionaryValue* dict = new DictionaryValue();
+  dict->SetInteger(keys::kSourceTabIdKey,
+                   ExtensionTabUtil::GetTabId(tab_contents));
+  dict->SetString(keys::kSourceUrlKey, details->opener_url.spec());
+  dict->SetString(keys::kTargetUrlKey,
+                  details->target_url.possibly_invalid_spec());
+  dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
+  args.Append(dict);
+
+  std::string json_args;
+  base::JSONWriter::Write(&args, false, &json_args);
+  DispatchEvent(tab_contents->profile(), keys::kOnBeforeRetarget, json_args);
+}
+
 void ExtensionWebNavigationEventRouter::DispatchEvent(
     Profile* profile,
     const char* event_name,
diff --git a/chrome/browser/extensions/extension_webnavigation_api.h b/chrome/browser/extensions/extension_webnavigation_api.h
index 0f5948e..0ecac0d 100644
--- a/chrome/browser/extensions/extension_webnavigation_api.h
+++ b/chrome/browser/extensions/extension_webnavigation_api.h
@@ -21,6 +21,7 @@
 class NavigationController;
 class ProvisionalLoadDetails;
 class TabContents;
+struct ViewHostMsg_CreateWindow_Params;
 
 // Tracks the navigation state of all frames currently known to the
 // webNavigation API. It is mainly used to track in which frames an error
@@ -121,6 +122,12 @@
   void FailProvisionalLoadWithError(NavigationController* controller,
                                     ProvisionalLoadDetails* details);
 
+  // Handler for the CREATING_NEW_WINDOW event. The method takes the details of
+  // such an event and constructs a suitable JSON formatted extension event from
+  // it.
+  void CreatingNewWindow(TabContents* tab_content,
+                         const ViewHostMsg_CreateWindow_Params* details);
+
   // Dispatches events to the extension message service.
   void DispatchEvent(Profile* context,
                      const char* event_name,
diff --git a/chrome/browser/extensions/extension_webnavigation_apitest.cc b/chrome/browser/extensions/extension_webnavigation_apitest.cc
index 8e833b0..1a47667 100644
--- a/chrome/browser/extensions/extension_webnavigation_apitest.cc
+++ b/chrome/browser/extensions/extension_webnavigation_apitest.cc
@@ -14,7 +14,8 @@
   ASSERT_TRUE(RunExtensionTest("webnavigation/api")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigationEvents1) {
+// Disabled, flakily exceeds timeout, http://crbug.com/72165.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_WebNavigationEvents1) {
   CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExperimentalExtensionApis);
 
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc
new file mode 100644
index 0000000..8653e1d
--- /dev/null
+++ b/chrome/browser/extensions/extension_webrequest_api.cc
@@ -0,0 +1,324 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/extension_webrequest_api.h"
+
+#include <algorithm>
+
+#include "base/json/json_writer.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/extension_io_event_router.h"
+#include "chrome/browser/extensions/extension_webrequest_api_constants.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_extent.h"
+#include "chrome/common/extensions/url_pattern.h"
+#include "googleurl/src/gurl.h"
+
+namespace keys = extension_webrequest_api_constants;
+
+namespace {
+
+// List of all the webRequest events.
+static const char *kWebRequestEvents[] = {
+  keys::kOnBeforeRedirect,
+  keys::kOnBeforeRequest,
+  keys::kOnCompleted,
+  keys::kOnErrorOccurred,
+  keys::kOnHeadersReceived,
+  keys::kOnRequestSent
+};
+
+// TODO(mpcomplete): should this be a set of flags?
+static const char* kRequestFilterTypes[] = {
+  "main_frame",
+  "sub_frame",
+  "stylesheet",
+  "script",
+  "image",
+  "object",
+  "other",
+};
+
+static bool IsWebRequestEvent(const std::string& event_name) {
+  return std::find(kWebRequestEvents,
+                   kWebRequestEvents + arraysize(kWebRequestEvents),
+                   event_name) !=
+         kWebRequestEvents + arraysize(kWebRequestEvents);
+}
+
+static bool IsValidRequestFilterType(const std::string& type) {
+  return std::find(kRequestFilterTypes,
+                   kRequestFilterTypes + arraysize(kRequestFilterTypes),
+                   type) !=
+         kRequestFilterTypes + arraysize(kRequestFilterTypes);
+}
+
+static void AddEventListenerOnIOThread(
+    const std::string& extension_id,
+    const std::string& event_name,
+    const std::string& sub_event_name,
+    const ExtensionWebRequestEventRouter::RequestFilter& filter,
+    int extra_info_spec) {
+  ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
+      extension_id, event_name, sub_event_name, filter, extra_info_spec);
+}
+
+static void RemoveEventListenerOnIOThread(
+    const std::string& extension_id, const std::string& sub_event_name) {
+  ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
+      extension_id, sub_event_name);
+}
+
+}  // namespace
+
+// Internal representation of the webRequest.RequestFilter type, used to
+// filter what network events an extension cares about.
+struct ExtensionWebRequestEventRouter::RequestFilter {
+  ExtensionExtent urls;
+  std::vector<std::string> types;
+  int tab_id;
+  int window_id;
+
+  bool InitFromValue(const DictionaryValue& value);
+};
+
+// Internal representation of the extraInfoSpec parameter on webRequest events,
+// used to specify extra information to be included with network events.
+struct ExtensionWebRequestEventRouter::ExtraInfoSpec {
+  enum Flags {
+    REQUEST_LINE = 1<<0,
+    REQUEST_HEADERS = 1<<1,
+    STATUS_LINE = 1<<2,
+    RESPONSE_HEADERS = 1<<3,
+    REDIRECT_REQUEST_LINE = 1<<4,
+    REDIRECT_REQUEST_HEADERS = 1<<5,
+  };
+
+  static bool InitFromValue(const ListValue& value, int* extra_info_spec);
+};
+
+// Represents a single unique listener to an event, along with whatever filter
+// parameters and extra_info_spec were specified at the time the listener was
+// added.
+struct ExtensionWebRequestEventRouter::EventListener {
+  std::string extension_id;
+  std::string sub_event_name;
+  RequestFilter filter;
+  int extra_info_spec;
+
+  // Comparator to work with std::set.
+  bool operator<(const EventListener& that) const {
+    if (extension_id < that.extension_id)
+      return true;
+    if (extension_id == that.extension_id &&
+        sub_event_name < that.sub_event_name)
+      return true;
+    return false;
+  }
+};
+
+bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
+    const DictionaryValue& value) {
+  for (DictionaryValue::key_iterator key = value.begin_keys();
+       key != value.end_keys(); ++key) {
+    if (*key == "urls") {
+      ListValue* urls_value = NULL;
+      if (!value.GetList("urls", &urls_value))
+        return false;
+      for (size_t i = 0; i < urls_value->GetSize(); ++i) {
+        std::string url;
+        URLPattern pattern(URLPattern::SCHEME_ALL);
+        if (!urls_value->GetString(i, &url) ||
+            pattern.Parse(url) != URLPattern::PARSE_SUCCESS)
+          return false;
+        urls.AddPattern(pattern);
+      }
+    } else if (*key == "types") {
+      ListValue* types_value = NULL;
+      if (!value.GetList("urls", &types_value))
+        return false;
+      for (size_t i = 0; i < types_value->GetSize(); ++i) {
+        std::string type;
+        if (!types_value->GetString(i, &type) ||
+            !IsValidRequestFilterType(type))
+          return false;
+        types.push_back(type);
+      }
+    } else if (*key == "tabId") {
+      if (!value.GetInteger("tabId", &tab_id))
+        return false;
+    } else if (*key == "windowId") {
+      if (!value.GetInteger("windowId", &window_id))
+        return false;
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+// static
+bool ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
+    const ListValue& value, int* extra_info_spec) {
+  *extra_info_spec = 0;
+  for (size_t i = 0; i < value.GetSize(); ++i) {
+    std::string str;
+    if (!value.GetString(i, &str))
+      return false;
+
+    // TODO(mpcomplete): not all of these are valid for every event.
+    if (str == "requestLine")
+      *extra_info_spec |= REQUEST_LINE;
+    else if (str == "requestHeaders")
+      *extra_info_spec |= REQUEST_HEADERS;
+    else if (str == "statusLine")
+      *extra_info_spec |= STATUS_LINE;
+    else if (str == "responseHeaders")
+      *extra_info_spec |= RESPONSE_HEADERS;
+    else if (str == "redirectRequestLine")
+      *extra_info_spec |= REDIRECT_REQUEST_LINE;
+    else if (str == "redirectRequestHeaders")
+      *extra_info_spec |= REDIRECT_REQUEST_HEADERS;
+    else
+      return false;
+  }
+  return true;
+}
+
+// static
+ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() {
+  return Singleton<ExtensionWebRequestEventRouter>::get();
+}
+
+ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() {
+}
+
+ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
+}
+
+// static
+void ExtensionWebRequestEventRouter::RemoveEventListenerOnUIThread(
+    const std::string& extension_id, const std::string& sub_event_name) {
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      NewRunnableFunction(
+          &RemoveEventListenerOnIOThread,
+          extension_id, sub_event_name));
+}
+
+void ExtensionWebRequestEventRouter::OnBeforeRequest(
+    const ExtensionIOEventRouter* event_router,
+    const GURL& url,
+    const std::string& method) {
+  std::vector<const EventListener*> listeners =
+      GetMatchingListeners(keys::kOnBeforeRequest, url);
+  if (listeners.empty())
+    return;
+
+  ListValue args;
+  DictionaryValue* dict = new DictionaryValue();
+  dict->SetString(keys::kUrlKey, url.spec());
+  dict->SetString(keys::kMethodKey, method);
+  // TODO(mpcomplete): implement
+  dict->SetInteger(keys::kTabIdKey, 0);
+  dict->SetInteger(keys::kRequestIdKey, 0);
+  dict->SetString(keys::kTypeKey, "main_frame");
+  dict->SetInteger(keys::kTimeStampKey, 1);
+  args.Append(dict);
+
+  std::string json_args;
+  base::JSONWriter::Write(&args, false, &json_args);
+
+  for (std::vector<const EventListener*>::iterator it = listeners.begin();
+       it != listeners.end(); ++it) {
+    event_router->DispatchEventToExtension(
+        (*it)->extension_id, (*it)->sub_event_name, json_args);
+  }
+}
+
+void ExtensionWebRequestEventRouter::AddEventListener(
+    const std::string& extension_id,
+    const std::string& event_name,
+    const std::string& sub_event_name,
+    const RequestFilter& filter,
+    int extra_info_spec) {
+  if (!IsWebRequestEvent(event_name))
+    return;
+
+  EventListener listener;
+  listener.extension_id = extension_id;
+  listener.sub_event_name = sub_event_name;
+  listener.filter = filter;
+  listener.extra_info_spec = extra_info_spec;
+
+  CHECK_EQ(listeners_[event_name].count(listener), 0u) <<
+      "extension=" << extension_id << " event=" << event_name;
+  listeners_[event_name].insert(listener);
+}
+
+void ExtensionWebRequestEventRouter::RemoveEventListener(
+    const std::string& extension_id,
+    const std::string& sub_event_name) {
+  size_t slash_sep = sub_event_name.find('/');
+  std::string event_name = sub_event_name.substr(0, slash_sep);
+
+  if (!IsWebRequestEvent(event_name))
+    return;
+
+  EventListener listener;
+  listener.extension_id = extension_id;
+  listener.sub_event_name = sub_event_name;
+
+  CHECK_EQ(listeners_[event_name].count(listener), 1u) <<
+      "extension=" << extension_id << " event=" << event_name;
+  listeners_[event_name].erase(listener);
+}
+
+std::vector<const ExtensionWebRequestEventRouter::EventListener*>
+ExtensionWebRequestEventRouter::GetMatchingListeners(
+    const std::string& event_name, const GURL& url) {
+  std::vector<const EventListener*> matching_listeners;
+  std::set<EventListener>& listeners = listeners_[event_name];
+  for (std::set<EventListener>::iterator it = listeners.begin();
+       it != listeners.end(); ++it) {
+    if (it->filter.urls.is_empty() || it->filter.urls.ContainsURL(url))
+      matching_listeners.push_back(&(*it));
+  }
+  return matching_listeners;
+}
+
+bool WebRequestAddEventListener::RunImpl() {
+  // Argument 0 is the callback, which we don't use here.
+
+  ExtensionWebRequestEventRouter::RequestFilter filter;
+  if (HasOptionalArgument(1)) {
+    DictionaryValue* value = NULL;
+    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value));
+    EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value));
+  }
+
+  int extra_info_spec = 0;
+  if (HasOptionalArgument(2)) {
+    ListValue* value = NULL;
+    EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value));
+    EXTENSION_FUNCTION_VALIDATE(
+        ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
+            *value, &extra_info_spec));
+  }
+
+  std::string event_name;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name));
+
+  std::string sub_event_name;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));
+
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      NewRunnableFunction(
+          &AddEventListenerOnIOThread,
+          extension_id(), event_name, sub_event_name, filter, extra_info_spec));
+
+  return true;
+}
diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h
new file mode 100644
index 0000000..27fb5cb
--- /dev/null
+++ b/chrome/browser/extensions/extension_webrequest_api.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/singleton.h"
+#include "ipc/ipc_message.h"
+#include "chrome/browser/extensions/extension_function.h"
+
+class ExtensionIOEventRouter;
+class GURL;
+
+// This class observes network events and routes them to the appropriate
+// extensions listening to those events. All methods must be called on the IO
+// thread unless otherwise specified.
+class ExtensionWebRequestEventRouter {
+ public:
+  struct RequestFilter;
+  struct ExtraInfoSpec;
+
+  static ExtensionWebRequestEventRouter* GetInstance();
+
+  // Removes the listener for the given sub-event. Can be called on the UI
+  // thread.
+  static void RemoveEventListenerOnUIThread(
+      const std::string& extension_id,
+      const std::string& sub_event_name);
+
+  // TODO(mpcomplete): additional params
+  void OnBeforeRequest(
+      const ExtensionIOEventRouter* event_router,
+      const GURL& url,
+      const std::string& method);
+
+  // Adds a listener to the given event. |event_name| specifies the event being
+  // listened to. |sub_event_name| is an internal event uniquely generated in
+  // the extension process to correspond to the given filter and
+  // extra_info_spec.
+  void AddEventListener(
+      const std::string& extension_id,
+      const std::string& event_name,
+      const std::string& sub_event_name,
+      const RequestFilter& filter,
+      int extra_info_spec);
+
+  // Removes the listener for the given sub-event.
+  void RemoveEventListener(
+      const std::string& extension_id,
+      const std::string& sub_event_name);
+
+ private:
+  friend struct DefaultSingletonTraits<ExtensionWebRequestEventRouter>;
+  struct EventListener;
+  typedef std::map<std::string, std::set<EventListener> > ListenerMap;
+
+  ExtensionWebRequestEventRouter();
+  ~ExtensionWebRequestEventRouter();
+
+  // Returns a list of event listeners that care about the given event, based
+  // on their filter parameters.
+  std::vector<const EventListener*> GetMatchingListeners(
+      const std::string& event_name, const GURL& url);
+
+  // A map between an event name and a set of extensions that are listening
+  // to that event.
+  ListenerMap listeners_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestEventRouter);
+};
+
+class WebRequestAddEventListener : public SyncExtensionFunction {
+ public:
+  virtual bool RunImpl();
+  DECLARE_EXTENSION_FUNCTION_NAME("experimental.webRequest.addEventListener");
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_
diff --git a/chrome/browser/extensions/extension_webrequest_apitest.cc b/chrome/browser/extensions/extension_webrequest_apitest.cc
index 833312f..7c25be8 100644
--- a/chrome/browser/extensions/extension_webrequest_apitest.cc
+++ b/chrome/browser/extensions/extension_webrequest_apitest.cc
@@ -12,3 +12,10 @@
 
   ASSERT_TRUE(RunExtensionTest("webrequest/api")) << message_;
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebRequestEvents) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+    switches::kEnableExperimentalExtensionApis);
+
+  ASSERT_TRUE(RunExtensionTest("webrequest/events")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_websocket_apitest.cc b/chrome/browser/extensions/extension_websocket_apitest.cc
index 227a01a..f8cbebc 100644
--- a/chrome/browser/extensions/extension_websocket_apitest.cc
+++ b/chrome/browser/extensions/extension_websocket_apitest.cc
@@ -20,6 +20,7 @@
   PathService::Get(chrome::DIR_TEST_DATA, &websocket_root_dir);
   websocket_root_dir = websocket_root_dir.AppendASCII("layout_tests")
       .AppendASCII("LayoutTests");
-  ui_test_utils::TestWebSocketServer server(websocket_root_dir);
+  ui_test_utils::TestWebSocketServer server;
+  ASSERT_TRUE(server.Start(websocket_root_dir));
   ASSERT_TRUE(RunExtensionTest("websocket")) << message_;
 }
diff --git a/chrome/browser/extensions/extension_webstore_private_api.cc b/chrome/browser/extensions/extension_webstore_private_api.cc
index 32b7c65..46db494 100644
--- a/chrome/browser/extensions/extension_webstore_private_api.cc
+++ b/chrome/browser/extensions/extension_webstore_private_api.cc
@@ -7,7 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -28,6 +27,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/extensions/extensions_startup.cc b/chrome/browser/extensions/extensions_startup.cc
index b44aade..cd395cf 100644
--- a/chrome/browser/extensions/extensions_startup.cc
+++ b/chrome/browser/extensions/extensions_startup.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,7 +12,7 @@
 #include "chrome/common/chrome_switches.h"
 
 #if defined(OS_WIN)
-#include "app/win/win_util.h"
+#include "ui/base/message_box_win.h"
 #endif
 
 ExtensionsStartupUtil::ExtensionsStartupUtil() : pack_job_succeeded_(false) {}
@@ -36,7 +36,7 @@
     const std::wstring& caption,
     const std::wstring& message) {
 #if defined(OS_WIN)
-  app::win::MessageBox(NULL, message, caption, MB_OK | MB_SETFOREGROUND);
+  ui::MessageBox(NULL, message, caption, MB_OK | MB_SETFOREGROUND);
 #else
   // Just send caption & text to stdout on mac & linux.
   std::string out_text = WideToASCII(caption);
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index ec1f9bd..157eacb 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/base64.h"
 #include "base/callback.h"
 #include "base/file_util.h"
@@ -37,8 +35,6 @@
 #include "chrome/browser/tab_contents/background_contents.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/user_script.h"
@@ -48,14 +44,16 @@
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/color_utils.h"
-#include "gfx/skbitmap_operations.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/skbitmap_operations.h"
 #include "webkit/glue/image_decoder.h"
 
 namespace {
@@ -124,6 +122,8 @@
       ASCIIToUTF16("'>") +
       l10n_util::GetStringUTF16(IDS_GET_MORE_EXTENSIONS) +
       ASCIIToUTF16("</a>"));
+  localized_strings.SetString("extensionCrashed",
+      l10n_util::GetStringUTF16(IDS_EXTENSIONS_CRASHED_EXTENSION));
   localized_strings.SetString("extensionDisabled",
       l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLED_EXTENSION));
   localized_strings.SetString("inDevelopment",
@@ -300,33 +300,33 @@
 }
 
 void ExtensionsDOMHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("requestExtensionsData",
+  web_ui_->RegisterMessageCallback("requestExtensionsData",
       NewCallback(this, &ExtensionsDOMHandler::HandleRequestExtensionsData));
-  dom_ui_->RegisterMessageCallback("toggleDeveloperMode",
+  web_ui_->RegisterMessageCallback("toggleDeveloperMode",
       NewCallback(this, &ExtensionsDOMHandler::HandleToggleDeveloperMode));
-  dom_ui_->RegisterMessageCallback("inspect",
+  web_ui_->RegisterMessageCallback("inspect",
       NewCallback(this, &ExtensionsDOMHandler::HandleInspectMessage));
-  dom_ui_->RegisterMessageCallback("reload",
+  web_ui_->RegisterMessageCallback("reload",
       NewCallback(this, &ExtensionsDOMHandler::HandleReloadMessage));
-  dom_ui_->RegisterMessageCallback("enable",
+  web_ui_->RegisterMessageCallback("enable",
       NewCallback(this, &ExtensionsDOMHandler::HandleEnableMessage));
-  dom_ui_->RegisterMessageCallback("enableIncognito",
+  web_ui_->RegisterMessageCallback("enableIncognito",
       NewCallback(this, &ExtensionsDOMHandler::HandleEnableIncognitoMessage));
-  dom_ui_->RegisterMessageCallback("allowFileAccess",
+  web_ui_->RegisterMessageCallback("allowFileAccess",
       NewCallback(this, &ExtensionsDOMHandler::HandleAllowFileAccessMessage));
-  dom_ui_->RegisterMessageCallback("uninstall",
+  web_ui_->RegisterMessageCallback("uninstall",
       NewCallback(this, &ExtensionsDOMHandler::HandleUninstallMessage));
-  dom_ui_->RegisterMessageCallback("options",
+  web_ui_->RegisterMessageCallback("options",
       NewCallback(this, &ExtensionsDOMHandler::HandleOptionsMessage));
-  dom_ui_->RegisterMessageCallback("showButton",
+  web_ui_->RegisterMessageCallback("showButton",
       NewCallback(this, &ExtensionsDOMHandler::HandleShowButtonMessage));
-  dom_ui_->RegisterMessageCallback("load",
+  web_ui_->RegisterMessageCallback("load",
       NewCallback(this, &ExtensionsDOMHandler::HandleLoadMessage));
-  dom_ui_->RegisterMessageCallback("pack",
+  web_ui_->RegisterMessageCallback("pack",
       NewCallback(this, &ExtensionsDOMHandler::HandlePackMessage));
-  dom_ui_->RegisterMessageCallback("autoupdate",
+  web_ui_->RegisterMessageCallback("autoupdate",
       NewCallback(this, &ExtensionsDOMHandler::HandleAutoUpdateMessage));
-  dom_ui_->RegisterMessageCallback("selectFilePath",
+  web_ui_->RegisterMessageCallback("selectFilePath",
       NewCallback(this, &ExtensionsDOMHandler::HandleSelectFilePathMessage));
 }
 
@@ -350,7 +350,7 @@
           extensions_service_.get(),
           *extension,
           GetActivePagesForExtension(*extension),
-          true));  // enabled
+          true, false));  // enabled, terminated
       extension_icons->push_back(PickExtensionIcon(*extension));
     }
   }
@@ -362,13 +362,26 @@
           extensions_service_.get(),
           *extension,
           GetActivePagesForExtension(*extension),
-          false));  // enabled
+          false, false));  // enabled, terminated
+      extension_icons->push_back(PickExtensionIcon(*extension));
+    }
+  }
+  extensions = extensions_service_->terminated_extensions();
+  std::vector<ExtensionPage> empty_pages;
+  for (ExtensionList::const_iterator extension = extensions->begin();
+       extension != extensions->end(); ++extension) {
+    if (ShouldShowExtension(*extension)) {
+      extensions_list->Append(CreateExtensionDetailValue(
+          extensions_service_.get(),
+          *extension,
+          empty_pages,  // Terminated process has no active pages.
+          false, true));  // enabled, terminated
       extension_icons->push_back(PickExtensionIcon(*extension));
     }
   }
   results->Set("extensions", extensions_list);
 
-  bool developer_mode = dom_ui_->GetProfile()->GetPrefs()
+  bool developer_mode = web_ui_->GetProfile()->GetPrefs()
       ->GetBoolean(prefs::kExtensionsUIDeveloperMode);
   results->SetBoolean("developerMode", developer_mode);
 
@@ -380,7 +393,7 @@
 }
 
 void ExtensionsDOMHandler::OnIconsLoaded(DictionaryValue* json) {
-  dom_ui_->CallJavascriptFunction(L"returnExtensionsData", *json);
+  web_ui_->CallJavascriptFunction(L"returnExtensionsData", *json);
   delete json;
 
   // Register for notifications that we need to reload the page.
@@ -423,14 +436,14 @@
 
 ExtensionInstallUI* ExtensionsDOMHandler::GetExtensionInstallUI() {
   if (!install_ui_.get())
-    install_ui_.reset(new ExtensionInstallUI(dom_ui_->GetProfile()));
+    install_ui_.reset(new ExtensionInstallUI(web_ui_->GetProfile()));
   return install_ui_.get();
 }
 
 void ExtensionsDOMHandler::HandleToggleDeveloperMode(const ListValue* args) {
-  bool developer_mode = dom_ui_->GetProfile()->GetPrefs()
+  bool developer_mode = web_ui_->GetProfile()->GetPrefs()
       ->GetBoolean(prefs::kExtensionsUIDeveloperMode);
-  dom_ui_->GetProfile()->GetPrefs()->SetBoolean(
+  web_ui_->GetProfile()->GetPrefs()->SetBoolean(
       prefs::kExtensionsUIDeveloperMode, !developer_mode);
 }
 
@@ -471,7 +484,7 @@
       const Extension* extension =
           extensions_service_->GetExtensionById(extension_id, true);
       ShowExtensionDisabledDialog(extensions_service_,
-                                  dom_ui_->GetProfile(), extension);
+                                  web_ui_->GetProfile(), extension);
     } else {
       extensions_service_->EnableExtension(extension_id);
     }
@@ -554,7 +567,7 @@
   const Extension* extension = GetExtension(args);
   if (!extension || extension->options_url().is_empty())
     return;
-  dom_ui_->GetProfile()->GetExtensionProcessManager()->OpenOptionsPage(
+  web_ui_->GetProfile()->GetExtensionProcessManager()->OpenOptionsPage(
       extension, NULL);
 }
 
@@ -573,7 +586,7 @@
 void ExtensionsDOMHandler::ShowAlert(const std::string& message) {
   ListValue arguments;
   arguments.Append(Value::CreateStringValue(message));
-  dom_ui_->CallJavascriptFunction(L"alert", arguments);
+  web_ui_->CallJavascriptFunction(L"alert", arguments);
 }
 
 void ExtensionsDOMHandler::HandlePackMessage(const ListValue* args) {
@@ -615,7 +628,7 @@
                                                                  pem_file)));
 
   ListValue results;
-  dom_ui_->CallJavascriptFunction(L"hidePackDialog", results);
+  web_ui_->CallJavascriptFunction(L"hidePackDialog", results);
 }
 
 void ExtensionsDOMHandler::OnPackFailure(const std::string& error) {
@@ -665,7 +678,7 @@
   load_extension_dialog_ = SelectFileDialog::Create(this);
   load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info,
       file_type_index, FILE_PATH_LITERAL(""),
-      dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
+      web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
 }
 
 
@@ -674,7 +687,7 @@
   // Add the extensions to the results structure.
   ListValue results;
   results.Append(Value::CreateStringValue(path.value()));
-  dom_ui_->CallJavascriptFunction(L"window.handleFilePathSelected", results);
+  web_ui_->CallJavascriptFunction(L"window.handleFilePathSelected", results);
 }
 
 void ExtensionsDOMHandler::MultiFilesSelected(
@@ -729,7 +742,7 @@
 }
 
 void ExtensionsDOMHandler::MaybeUpdateAfterNotification() {
-  if (!ignore_notifications_ && dom_ui_->tab_contents())
+  if (!ignore_notifications_ && web_ui_->tab_contents())
     HandleRequestExtensionsData(NULL);
   deleting_rvh_ = NULL;
 }
@@ -791,7 +804,7 @@
 // Static
 DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
     ExtensionService* service, const Extension* extension,
-    const std::vector<ExtensionPage>& pages, bool enabled) {
+    const std::vector<ExtensionPage>& pages, bool enabled, bool terminated) {
   DictionaryValue* extension_data = new DictionaryValue();
 
   extension_data->SetString("id", extension->id());
@@ -799,6 +812,7 @@
   extension_data->SetString("description", extension->description());
   extension_data->SetString("version", extension->version()->GetString());
   extension_data->SetBoolean("enabled", enabled);
+  extension_data->SetBoolean("terminated", terminated);
   extension_data->SetBoolean("enabledIncognito",
       service ? service->IsIncognitoEnabled(extension) : false);
   extension_data->SetBoolean("wantsFileAccess",
@@ -934,7 +948,7 @@
 
 // ExtensionsDOMHandler, public: -----------------------------------------------
 
-ExtensionsUI::ExtensionsUI(TabContents* contents) : DOMUI(contents) {
+ExtensionsUI::ExtensionsUI(TabContents* contents) : WebUI(contents) {
   ExtensionService *exstension_service =
       GetProfile()->GetOriginalProfile()->GetExtensionService();
 
@@ -945,12 +959,7 @@
   ExtensionsUIHTMLSource* html_source = new ExtensionsUIHTMLSource();
 
   // Set up the chrome://extensions/ source.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(
-          ChromeURLDataManager::GetInstance(),
-          &ChromeURLDataManager::AddDataSource,
-          make_scoped_refptr(html_source)));
+  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
 }
 
 // static
diff --git a/chrome/browser/extensions/extensions_ui.h b/chrome/browser/extensions/extensions_ui.h
index b7a9b69..94d8afd 100644
--- a/chrome/browser/extensions/extensions_ui.h
+++ b/chrome/browser/extensions/extensions_ui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,10 +11,10 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
 #include "chrome/browser/extensions/pack_extension_job.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
@@ -61,7 +61,7 @@
 
 // The handler for JavaScript messages related to the "extensions" view.
 class ExtensionsDOMHandler
-    : public DOMMessageHandler,
+    : public WebUIMessageHandler,
       public NotificationObserver,
       public PackExtensionJob::Client,
       public SelectFileDialog::Listener,
@@ -105,7 +105,7 @@
   explicit ExtensionsDOMHandler(ExtensionService* extension_service);
   virtual ~ExtensionsDOMHandler();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Extension Detail JSON Struct for page. (static for ease of testing).
@@ -114,7 +114,8 @@
       ExtensionService* service,
       const Extension* extension,
       const std::vector<ExtensionPage>& pages,
-      bool enabled);
+      bool enabled,
+      bool terminated);
 
   // ContentScript JSON Struct for page. (static for ease of testing).
   static DictionaryValue* CreateContentScriptDetailValue(
@@ -260,7 +261,7 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionsDOMHandler);
 };
 
-class ExtensionsUI : public DOMUI {
+class ExtensionsUI : public WebUI {
  public:
   explicit ExtensionsUI(TabContents* contents);
 
diff --git a/chrome/browser/extensions/external_extension_loader.cc b/chrome/browser/extensions/external_extension_loader.cc
new file mode 100644
index 0000000..357f5b7
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_loader.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/external_extension_loader.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+
+ExternalExtensionLoader::ExternalExtensionLoader()
+    : owner_(NULL),
+      running_(false) {
+}
+
+void ExternalExtensionLoader::Init(
+    ExternalExtensionProviderImpl* owner) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  owner_ = owner;
+}
+
+const FilePath ExternalExtensionLoader::GetBaseCrxFilePath() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // By default, relative paths are not supported.
+  // Subclasses that wish to support them should override this method.
+  return FilePath();
+}
+
+void ExternalExtensionLoader::OwnerShutdown() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  owner_ = NULL;
+}
+
+ExternalExtensionLoader::~ExternalExtensionLoader() {}
+
+void ExternalExtensionLoader::LoadFinished() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  running_ = false;
+  if (owner_) {
+    owner_->SetPrefs(prefs_.release());
+  }
+}
diff --git a/chrome/browser/extensions/external_extension_loader.h b/chrome/browser/extensions/external_extension_loader.h
new file mode 100644
index 0000000..7791664
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_loader.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_LOADER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_LOADER_H_
+#pragma once
+
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+
+class DictionaryValue;
+class ExternalExtensionProviderImpl;
+
+// Base class for gathering a list of external extensions. Subclasses
+// implement loading from registry, JSON file, policy.
+// Instances are owned by ExternalExtensionProviderImpl objects.
+// Instances are created on the UI thread and expect public method calls from
+// the UI thread. Some subclasses introduce new methods that are executed on the
+// FILE thread.
+// The sequence of loading the extension list:
+// 1.) StartLoading() - checks if a loading task is already running
+// 2.) Load() - implemented in subclasses
+// 3.) FinishLoading()
+// 4.) owner_->SetPrefs()
+class ExternalExtensionLoader
+    : public base::RefCountedThreadSafe<ExternalExtensionLoader> {
+ public:
+  explicit ExternalExtensionLoader();
+
+  // Specifies the provider that owns this object.
+  void Init(ExternalExtensionProviderImpl* owner);
+
+  // Called by the owner before it gets deleted.
+  void OwnerShutdown();
+
+  // Initiates the possibly asynchronous loading of extension list.
+  // It is the responsibility of the caller to ensure that calls to
+  // this method do not overlap with each other.
+  // Implementations of this method should save the loaded results
+  // in prefs_ and then call LoadFinished.
+  virtual void StartLoading() = 0;
+
+  // Some external providers allow relative file paths to local CRX files.
+  // Subclasses that want this behavior should override this method to
+  // return the absolute path from which relative paths should be resolved.
+  // By default, return an empty path, which indicates that relative paths
+  // are not allowed.
+  virtual const FilePath GetBaseCrxFilePath();
+
+ protected:
+  virtual ~ExternalExtensionLoader();
+
+  // Notifies the provider that the list of extensions has been loaded.
+  void LoadFinished();
+
+  // Used for passing the list of extensions from the method that loads them
+  // to |LoadFinished|. To ensure thread safety, the rules are the following:
+  // if this value is written on another thread than the UI, then it should
+  // only be written in a task that was posted from |StartLoading|. After that,
+  // this task should invoke |LoadFinished| with a PostTask. This scheme of
+  // posting tasks will avoid concurrent access and imply the necessary memory
+  // barriers.
+  scoped_ptr<DictionaryValue> prefs_;
+
+ private:
+  friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+  ExternalExtensionProviderImpl* owner_;  // weak
+
+  // Set to true if loading the extensions is already running. New requests
+  // are ignored while this is set true.
+  bool running_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalExtensionLoader);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_LOADER_H_
diff --git a/chrome/browser/extensions/external_extension_provider.h b/chrome/browser/extensions/external_extension_provider.h
deleted file mode 100644
index 5bcce1d..0000000
--- a/chrome/browser/extensions/external_extension_provider.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/common/extensions/extension.h"
-
-class FilePath;
-class Version;
-
-// This class is an abstract class for implementing external extensions
-// providers.
-class ExternalExtensionProvider {
- public:
-  // ExternalExtensionProvider uses this interface to communicate back to the
-  // caller what extensions are registered, and which |id|, |version| and |path|
-  // they have. See also VisitRegisteredExtension below. Ownership of |version|
-  // is not transferred to the visitor.
-  class Visitor {
-   public:
-     virtual void OnExternalExtensionFileFound(
-         const std::string& id,
-         const Version* version,
-         const FilePath& path,
-         Extension::Location location) = 0;
-
-     virtual void OnExternalExtensionUpdateUrlFound(
-         const std::string& id,
-         const GURL& update_url,
-         Extension::Location location) = 0;
-
-   protected:
-     virtual ~Visitor() {}
-  };
-
-  virtual ~ExternalExtensionProvider() {}
-
-  // Enumerate registered extension, calling OnExternalExtensionFound on
-  // the |visitor| object for each registered extension found. |ids_to_ignore|
-  // contains a list of extension ids that should not result in a call back.
-  virtual void VisitRegisteredExtension(Visitor* visitor) const = 0;
-
-  // Test if this provider has an extension with id |id| registered.
-  virtual bool HasExtension(const std::string& id) const = 0;
-
-  // Gets details of an extension by its id.  Output params will be set only
-  // if they are not NULL.  If an output parameter is not specified by the
-  // provider type, it will not be changed.
-  // This function is no longer used outside unit tests.
-  virtual bool GetExtensionDetails(const std::string& id,
-                                   Extension::Location* location,
-                                   scoped_ptr<Version>* version) const = 0;
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_H_
diff --git a/chrome/browser/extensions/external_extension_provider_impl.cc b/chrome/browser/extensions/external_extension_provider_impl.cc
new file mode 100644
index 0000000..7a0af09
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_provider_impl.cc
@@ -0,0 +1,262 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+
+#include "app/app_paths.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/linked_ptr.h"
+#include "base/path_service.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_policy_extension_loader.h"
+#include "chrome/browser/extensions/external_pref_extension_loader.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/extensions/external_registry_extension_loader_win.h"
+#endif
+
+// Constants for keeping track of extension preferences in a dictionary.
+const char ExternalExtensionProviderImpl::kLocation[] = "location";
+const char ExternalExtensionProviderImpl::kState[] = "state";
+const char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx";
+const char ExternalExtensionProviderImpl::kExternalVersion[] =
+    "external_version";
+const char ExternalExtensionProviderImpl::kExternalUpdateUrl[] =
+    "external_update_url";
+
+ExternalExtensionProviderImpl::ExternalExtensionProviderImpl(
+    VisitorInterface* service,
+    ExternalExtensionLoader* loader,
+    Extension::Location crx_location,
+    Extension::Location download_location)
+  : crx_location_(crx_location),
+    download_location_(download_location),
+    service_(service),
+    prefs_(NULL),
+    ready_(false),
+    loader_(loader) {
+  loader_->Init(this);
+}
+
+ExternalExtensionProviderImpl::~ExternalExtensionProviderImpl() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  loader_->OwnerShutdown();
+}
+
+void ExternalExtensionProviderImpl::VisitRegisteredExtension() const {
+  // The loader will call back to SetPrefs.
+  loader_->StartLoading();
+}
+
+void ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // Check if the service is still alive. It is possible that it had went
+  // away while |loader_| was working on the FILE thread.
+  if (!service_) return;
+
+  prefs_.reset(prefs);
+  ready_ = true; // Queries for extensions are allowed from this point.
+
+  // Notify ExtensionService about all the extensions this provider has.
+  for (DictionaryValue::key_iterator i = prefs_->begin_keys();
+       i != prefs_->end_keys(); ++i) {
+    const std::string& extension_id = *i;
+    DictionaryValue* extension;
+
+    if (!Extension::IdIsValid(extension_id)) {
+      LOG(WARNING) << "Malformed extension dictionary: key "
+                   << extension_id.c_str() << " is not a valid id.";
+      continue;
+    }
+
+    if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension)) {
+      LOG(WARNING) << "Malformed extension dictionary: key "
+                   << extension_id.c_str()
+                   << " has a value that is not a dictionary.";
+      continue;
+    }
+
+    FilePath::StringType external_crx;
+    std::string external_version;
+    std::string external_update_url;
+
+    bool has_external_crx = extension->GetString(kExternalCrx, &external_crx);
+    bool has_external_version = extension->GetString(kExternalVersion,
+                                                     &external_version);
+    bool has_external_update_url = extension->GetString(kExternalUpdateUrl,
+                                                        &external_update_url);
+    if (has_external_crx != has_external_version) {
+      LOG(WARNING) << "Malformed extension dictionary for extension: "
+                   << extension_id.c_str() << ".  " << kExternalCrx
+                   << " and " << kExternalVersion << " must be used together.";
+      continue;
+    }
+
+    if (has_external_crx == has_external_update_url) {
+      LOG(WARNING) << "Malformed extension dictionary for extension: "
+                   << extension_id.c_str() << ".  Exactly one of the "
+                   << "followng keys should be used: " << kExternalCrx
+                   << ", " << kExternalUpdateUrl << ".";
+      continue;
+    }
+
+    if (has_external_crx) {
+      if (crx_location_ == Extension::INVALID) {
+        LOG(WARNING) << "This provider does not support installing external "
+                     << "extensions from crx files.";
+        continue;
+      }
+      if (external_crx.find(FilePath::kParentDirectory) !=
+          base::StringPiece::npos) {
+        LOG(WARNING) << "Path traversal not allowed in path: "
+                     << external_crx.c_str();
+        continue;
+      }
+
+      // If the path is relative, and the provider has a base path,
+      // build the absolute path to the crx file.
+      FilePath path(external_crx);
+      if (!path.IsAbsolute()) {
+        FilePath base_path = loader_->GetBaseCrxFilePath();
+        if (base_path.empty()) {
+          LOG(WARNING) << "File path " << external_crx.c_str()
+                       << " is relative.  An absolute path is required.";
+          continue;
+        }
+        path = base_path.Append(external_crx);
+      }
+
+      scoped_ptr<Version> version;
+      version.reset(Version::GetVersionFromString(external_version));
+      if (!version.get()) {
+        LOG(WARNING) << "Malformed extension dictionary for extension: "
+                     << extension_id.c_str() << ".  Invalid version string \""
+                     << external_version << "\".";
+        continue;
+      }
+      service_->OnExternalExtensionFileFound(extension_id, version.get(), path,
+                                             crx_location_);
+    } else { // if (has_external_update_url)
+      CHECK(has_external_update_url);  // Checking of keys above ensures this.
+      if (download_location_ == Extension::INVALID) {
+        LOG(WARNING) << "This provider does not support installing external "
+                     << "extensions from update URLs.";
+        continue;
+      }
+      GURL update_url(external_update_url);
+      if (!update_url.is_valid()) {
+        LOG(WARNING) << "Malformed extension dictionary for extension: "
+                     << extension_id.c_str() << ".  Key " << kExternalUpdateUrl
+                     << " has value \"" << external_update_url
+                     << "\", which is not a valid URL.";
+        continue;
+      }
+      service_->OnExternalExtensionUpdateUrlFound(
+          extension_id, update_url, download_location_);
+    }
+  }
+
+  service_->OnExternalProviderReady();
+}
+
+void ExternalExtensionProviderImpl::ServiceShutdown() {
+  service_ = NULL;
+}
+
+bool ExternalExtensionProviderImpl::IsReady() {
+  return ready_;
+}
+
+bool ExternalExtensionProviderImpl::HasExtension(
+    const std::string& id) const {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(prefs_.get());
+  CHECK(ready_);
+  return prefs_->HasKey(id);
+}
+
+bool ExternalExtensionProviderImpl::GetExtensionDetails(
+    const std::string& id, Extension::Location* location,
+    scoped_ptr<Version>* version) const {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  CHECK(prefs_.get());
+  CHECK(ready_);
+  DictionaryValue* extension = NULL;
+  if (!prefs_->GetDictionary(id, &extension))
+    return false;
+
+  Extension::Location loc = Extension::INVALID;
+  if (extension->HasKey(kExternalUpdateUrl)) {
+    loc = download_location_;
+
+  } else if (extension->HasKey(kExternalCrx)) {
+    loc = crx_location_;
+
+    std::string external_version;
+    if (!extension->GetString(kExternalVersion, &external_version))
+      return false;
+
+    if (version)
+      version->reset(Version::GetVersionFromString(external_version));
+
+  } else {
+    NOTREACHED();  // Chrome should not allow prefs to get into this state.
+    return false;
+  }
+
+  if (location)
+    *location = loc;
+
+  return true;
+}
+
+// static
+void ExternalExtensionProviderImpl::CreateExternalProviders(
+    VisitorInterface* service,
+    Profile* profile,
+    ProviderCollection* provider_list) {
+  provider_list->push_back(
+      linked_ptr<ExternalExtensionProviderInterface>(
+          new ExternalExtensionProviderImpl(
+              service,
+              new ExternalPrefExtensionLoader(
+                  app::DIR_EXTERNAL_EXTENSIONS),
+              Extension::EXTERNAL_PREF,
+              Extension::EXTERNAL_PREF_DOWNLOAD)));
+
+#if defined(OS_CHROMEOS)
+  // Chrome OS specific source for OEM customization.
+  provider_list->push_back(
+      linked_ptr<ExternalExtensionProviderInterface>(
+          new ExternalExtensionProviderImpl(
+              service,
+              new ExternalPrefExtensionLoader(
+                  chrome::DIR_USER_EXTERNAL_EXTENSIONS),
+              Extension::EXTERNAL_PREF,
+              Extension::EXTERNAL_PREF_DOWNLOAD)));
+#endif
+#if defined(OS_WIN)
+  provider_list->push_back(
+      linked_ptr<ExternalExtensionProviderInterface>(
+          new ExternalExtensionProviderImpl(
+              service,
+              new ExternalRegistryExtensionLoader,
+              Extension::EXTERNAL_REGISTRY,
+              Extension::INVALID)));
+#endif
+  provider_list->push_back(
+      linked_ptr<ExternalExtensionProviderInterface>(
+          new ExternalExtensionProviderImpl(
+              service,
+              new ExternalPolicyExtensionLoader(profile),
+              Extension::INVALID,
+              Extension::EXTERNAL_POLICY_DOWNLOAD)));
+}
diff --git a/chrome/browser/extensions/external_extension_provider_impl.h b/chrome/browser/extensions/external_extension_provider_impl.h
new file mode 100644
index 0000000..2856db9
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_provider_impl.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_IMPL_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_IMPL_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+
+#include "base/ref_counted.h"
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+class DictionaryValue;
+class ExternalExtensionLoader;
+class Profile;
+class ValueSerializer;
+class Version;
+
+// A specialization of the ExternalExtensionProvider that uses an instance
+// of ExternalExtensionLoader to provide external extensions. This class
+// can be seen as a bridge between the extension system and an
+// ExternalExtensionLoader. Instances live their entire life on the UI thread.
+class ExternalExtensionProviderImpl
+    : public ExternalExtensionProviderInterface {
+ public:
+  // The constructed provider will provide the extensions loaded from |loader|
+  // to |service|, that will deal with the installation. The location
+  // attributes of the provided extensions are also specified here:
+  // |crx_location|: extensions originating from crx files
+  // |download_location|: extensions originating from update URLs
+  // If either of the origins is not supported by this provider, then it should
+  // be initialized as Extensions::INVALID.
+  ExternalExtensionProviderImpl(
+      VisitorInterface* service,
+      ExternalExtensionLoader* loader,
+      Extension::Location crx_location,
+      Extension::Location download_location);
+
+  virtual ~ExternalExtensionProviderImpl();
+
+  // Populates a list with providers for all known sources.
+  static void CreateExternalProviders(
+      VisitorInterface* service,
+      Profile* profile,
+      ProviderCollection* provider_list);
+
+  // Sets underlying prefs and notifies provider. Only to be called by the
+  // owned ExternalExtensionLoader instance.
+  void SetPrefs(DictionaryValue* prefs);
+
+  // ExternalExtensionProvider implementation:
+  virtual void VisitRegisteredExtension() const;
+
+  virtual bool HasExtension(const std::string& id) const;
+
+  virtual bool GetExtensionDetails(const std::string& id,
+                                   Extension::Location* location,
+                                   scoped_ptr<Version>* version) const;
+
+  virtual void ServiceShutdown();
+
+  virtual bool IsReady();
+
+  static const char kLocation[];
+  static const char kState[];
+  static const char kExternalCrx[];
+  static const char kExternalVersion[];
+  static const char kExternalUpdateUrl[];
+
+ private:
+  // Location for external extensions that are provided by this provider from
+  // local crx files.
+  const Extension::Location crx_location_;
+
+  // Location for external extensions that are provided by this provider from
+  // update URLs.
+  const Extension::Location download_location_;
+
+ private:
+  // Weak pointer to the object that consumes the external extensions.
+  // This is zeroed out by: ServiceShutdown()
+  VisitorInterface* service_;  // weak
+
+  // Dictionary of the external extensions that are provided by this provider.
+  scoped_ptr<DictionaryValue> prefs_;
+
+  // Indicates that the extensions provided by this provider are loaded
+  // entirely.
+  bool ready_;
+
+  // The loader that loads the list of external extensions and reports them
+  // via |SetPrefs|.
+  scoped_refptr<ExternalExtensionLoader> loader_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalExtensionProviderImpl);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_IMPL_H_
diff --git a/chrome/browser/extensions/external_extension_provider_interface.h b/chrome/browser/extensions/external_extension_provider_interface.h
new file mode 100644
index 0000000..982b738
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_provider_interface.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 CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_INTERFACE_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_INTERFACE_H_
+#pragma once
+
+#include <vector>
+
+#include "base/linked_ptr.h"
+#include "chrome/common/extensions/extension.h"
+
+class FilePath;
+class Version;
+
+// This class is an abstract class for implementing external extensions
+// providers.
+class ExternalExtensionProviderInterface {
+ public:
+  // ExternalExtensionProvider uses this interface to communicate back to the
+  // caller what extensions are registered, and which |id|, |version| and |path|
+  // they have. See also VisitRegisteredExtension below. Ownership of |version|
+  // is not transferred to the visitor.  Callers of the methods below must
+  // ensure that |id| is a valid extension id (use Extension::IdIsValid(id)).
+  class VisitorInterface {
+   public:
+    virtual void OnExternalExtensionFileFound(
+        const std::string& id,
+        const Version* version,
+        const FilePath& path,
+        Extension::Location location) = 0;
+
+    virtual void OnExternalExtensionUpdateUrlFound(
+        const std::string& id,
+        const GURL& update_url,
+        Extension::Location location) = 0;
+
+     // Called after all the external extensions have been reported through
+     // the above two methods.
+    virtual void OnExternalProviderReady() = 0;
+
+   protected:
+    virtual ~VisitorInterface() {}
+  };
+
+  virtual ~ExternalExtensionProviderInterface() {}
+
+  // The visitor (ExtensionsService) calls this function before it goes away.
+  virtual void ServiceShutdown() = 0;
+
+  // Enumerate registered extensions, calling
+  // OnExternalExtension(File|UpdateUrl)Found on the |visitor| object for each
+  // registered extension found.
+  virtual void VisitRegisteredExtension() const = 0;
+
+  // Test if this provider has an extension with id |id| registered.
+  virtual bool HasExtension(const std::string& id) const = 0;
+
+  // Gets details of an extension by its id.  Output params will be set only
+  // if they are not NULL.  If an output parameter is not specified by the
+  // provider type, it will not be changed.
+  // This function is no longer used outside unit tests.
+  virtual bool GetExtensionDetails(const std::string& id,
+                                   Extension::Location* location,
+                                   scoped_ptr<Version>* version) const = 0;
+
+  // Determines if this provider had loaded the list of external extensions
+  // from its source.
+  virtual bool IsReady() = 0;
+};
+
+typedef std::vector<linked_ptr<ExternalExtensionProviderInterface> >
+    ProviderCollection;
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_INTERFACE_H_
diff --git a/chrome/browser/extensions/external_policy_extension_loader.cc b/chrome/browser/extensions/external_policy_extension_loader.cc
new file mode 100644
index 0000000..99f2922
--- /dev/null
+++ b/chrome/browser/extensions/external_policy_extension_loader.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/external_policy_extension_loader.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "googleurl/src/gurl.h"
+
+namespace {
+
+// Check an extension ID and an URL to be syntactically correct.
+bool CheckExtension(std::string id, std::string update_url) {
+  GURL url(update_url);
+  if (!url.is_valid()) {
+    LOG(WARNING) << "Policy specifies invalid update URL for external "
+                 << "extension: " << update_url;
+    return false;
+  }
+  if (!Extension::IdIsValid(id)) {
+    LOG(WARNING) << "Policy specifies invalid ID for external "
+                 << "extension: " << id;
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+ExternalPolicyExtensionLoader::ExternalPolicyExtensionLoader(
+    Profile* profile)
+    : profile_(profile) {
+  pref_change_registrar_.Init(profile_->GetPrefs());
+  pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this);
+  notification_registrar_.Add(this,
+                              NotificationType::PROFILE_DESTROYED,
+                              Source<Profile>(profile_));
+}
+
+void ExternalPolicyExtensionLoader::StartLoading() {
+  const ListValue* forcelist =
+      profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList);
+  DictionaryValue* result = new DictionaryValue();
+  if (forcelist != NULL) {
+    std::string extension_desc;
+    for (ListValue::const_iterator it = forcelist->begin();
+         it != forcelist->end(); ++it) {
+      if (!(*it)->GetAsString(&extension_desc)) {
+        LOG(WARNING) << "Failed to read forcelist string.";
+      } else {
+        // Each string item of the list has the following form:
+        // extension_id_code;extension_update_url
+        // The update URL might also contain semicolons.
+        size_t pos = extension_desc.find(';');
+        std::string id = extension_desc.substr(0, pos);
+        std::string update_url = extension_desc.substr(pos+1);
+        if (CheckExtension(id, update_url)) {
+          result->SetString(id + ".external_update_url", update_url);
+        }
+      }
+    }
+  }
+  prefs_.reset(result);
+  LoadFinished();
+}
+
+void ExternalPolicyExtensionLoader::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  if (profile_ == NULL) return;
+  switch (type.value) {
+    case NotificationType::PREF_CHANGED: {
+      if (Source<PrefService>(source).ptr() == profile_->GetPrefs()) {
+        std::string* pref_name = Details<std::string>(details).ptr();
+        if (*pref_name == prefs::kExtensionInstallForceList) {
+          StartLoading();
+        } else {
+          NOTREACHED() << "Unexpected preference name.";
+        }
+      }
+      break;
+    }
+    case NotificationType::PROFILE_DESTROYED: {
+      if (Source<Profile>(source).ptr() == profile_) {
+        notification_registrar_.RemoveAll();
+        pref_change_registrar_.RemoveAll();
+        profile_ = NULL;
+      }
+      break;
+    }
+    default:
+      NOTREACHED() << "Unexpected notification type.";
+  }
+}
diff --git a/chrome/browser/extensions/external_policy_extension_loader.h b/chrome/browser/extensions/external_policy_extension_loader.h
new file mode 100644
index 0000000..7a78071
--- /dev/null
+++ b/chrome/browser/extensions/external_policy_extension_loader.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_LOADER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_LOADER_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class ListValue;
+class MockExternalPolicyExtensionProviderVisitor;
+class Profile;
+
+// A specialization of the ExternalExtensionProvider that uses
+// prefs::kExtensionInstallForceList to look up which external extensions are
+// registered.
+class ExternalPolicyExtensionLoader
+    : public ExternalExtensionLoader,
+      public NotificationObserver {
+ public:
+  explicit ExternalPolicyExtensionLoader(Profile* profile);
+
+  // NotificationObserver implementation
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ protected:
+  virtual void StartLoading();
+
+ private:
+  friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+  virtual ~ExternalPolicyExtensionLoader() {}
+
+  PrefChangeRegistrar pref_change_registrar_;
+  NotificationRegistrar notification_registrar_;
+
+  Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalPolicyExtensionLoader);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_LOADER_H_
diff --git a/chrome/browser/extensions/external_policy_extension_loader_unittest.cc b/chrome/browser/extensions/external_policy_extension_loader_unittest.cc
new file mode 100644
index 0000000..3e01e12
--- /dev/null
+++ b/chrome/browser/extensions/external_policy_extension_loader_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+#include "chrome/browser/extensions/external_policy_extension_loader.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_pref_service.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class ExternalPolicyExtensionProviderTest : public testing::Test {
+ public:
+  ExternalPolicyExtensionProviderTest()
+      : loop_(MessageLoop::TYPE_IO),
+        ui_thread_(BrowserThread::UI, &loop_) {
+  }
+
+  virtual ~ExternalPolicyExtensionProviderTest() {}
+
+ private:
+  // We need these to satisfy BrowserThread::CurrentlyOn(BrowserThread::UI)
+  // checks in ExternalExtensionProviderImpl.
+  MessageLoop loop_;
+  BrowserThread ui_thread_;
+};
+
+class MockExternalPolicyExtensionProviderVisitor
+    : public ExternalExtensionProviderInterface::VisitorInterface {
+ public:
+  MockExternalPolicyExtensionProviderVisitor() {
+  }
+
+  // Initialize a provider with |policy_forcelist|, and check that it parses
+  // exactly those extensions, that are specified in |policy_validlist|.
+  void Visit(ListValue* policy_forcelist,
+             ListValue* policy_validlist,
+             const std::set<std::string>& ignore_list) {
+    profile_.reset(new TestingProfile);
+    profile_->GetTestingPrefService()->SetManagedPref(
+        prefs::kExtensionInstallForceList,
+        policy_forcelist->DeepCopy());
+    provider_.reset(new ExternalExtensionProviderImpl(
+        this,
+        new ExternalPolicyExtensionLoader(profile_.get()),
+        Extension::INVALID,
+        Extension::EXTERNAL_POLICY_DOWNLOAD));
+
+    // Extensions will be removed from this list as they visited,
+    // so it should be emptied by the end.
+    remaining_extensions = policy_validlist;
+    provider_->VisitRegisteredExtension();
+    EXPECT_EQ(0u, remaining_extensions->GetSize());
+  }
+
+  virtual void OnExternalExtensionFileFound(const std::string& id,
+                                            const Version* version,
+                                            const FilePath& path,
+                                            Extension::Location unused) {
+    ADD_FAILURE() << "There should be no external extensions from files.";
+  }
+
+  virtual void OnExternalExtensionUpdateUrlFound(
+      const std::string& id, const GURL& update_url,
+      Extension::Location location) {
+    // Extension has the correct location.
+    EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD, location);
+
+    // Provider returns the correct location when asked.
+    Extension::Location location1;
+    scoped_ptr<Version> version1;
+    provider_->GetExtensionDetails(id, &location1, &version1);
+    EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD, location1);
+    EXPECT_FALSE(version1.get());
+
+    // Remove the extension from our list.
+    StringValue ext_str(id + ";" + update_url.spec());
+    EXPECT_NE(-1, remaining_extensions->Remove(ext_str));
+  }
+
+  virtual void OnExternalProviderReady() {
+    EXPECT_TRUE(provider_->IsReady());
+  }
+
+ private:
+  ListValue* remaining_extensions;
+
+  scoped_ptr<TestingProfile> profile_;
+
+  scoped_ptr<ExternalExtensionProviderImpl> provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockExternalPolicyExtensionProviderVisitor);
+};
+
+TEST_F(ExternalPolicyExtensionProviderTest, PolicyIsParsed) {
+  ListValue forced_extensions;
+  forced_extensions.Append(Value::CreateStringValue(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;http://www.example.com/crx?a=5;b=6"));
+  forced_extensions.Append(Value::CreateStringValue(
+      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;"
+      "https://clients2.google.com/service/update2/crx"));
+
+  MockExternalPolicyExtensionProviderVisitor mv;
+  std::set<std::string> empty;
+  mv.Visit(&forced_extensions, &forced_extensions, empty);
+}
+
+TEST_F(ExternalPolicyExtensionProviderTest, InvalidPolicyIsNotParsed) {
+  ListValue forced_extensions, valid_extensions;
+  StringValue valid(
+      "cccccccccccccccccccccccccccccccc;http://www.example.com/crx");
+  valid_extensions.Append(valid.DeepCopy());
+  forced_extensions.Append(valid.DeepCopy());
+  // Add invalid strings:
+  forced_extensions.Append(Value::CreateStringValue(""));
+  forced_extensions.Append(Value::CreateStringValue(";"));
+  forced_extensions.Append(Value::CreateStringValue(";;"));
+  forced_extensions.Append(Value::CreateStringValue(
+      ";http://www.example.com/crx"));
+  forced_extensions.Append(Value::CreateStringValue(
+      ";aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+  forced_extensions.Append(Value::CreateStringValue(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;"));
+  forced_extensions.Append(Value::CreateStringValue(
+      "http://www.example.com/crx;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+  forced_extensions.Append(Value::CreateStringValue(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;http#//www.example.com/crx"));
+  forced_extensions.Append(Value::CreateStringValue(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+  forced_extensions.Append(Value::CreateStringValue(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahttp#//www.example.com/crx"));
+
+  MockExternalPolicyExtensionProviderVisitor mv;
+  std::set<std::string> empty;
+  mv.Visit(&forced_extensions, &valid_extensions, empty);
+}
diff --git a/chrome/browser/extensions/external_policy_extension_provider.cc b/chrome/browser/extensions/external_policy_extension_provider.cc
deleted file mode 100644
index 5e87379..0000000
--- a/chrome/browser/extensions/external_policy_extension_provider.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/external_policy_extension_provider.h"
-
-#include "base/logging.h"
-#include "base/values.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-#include "chrome/browser/prefs/pref_service.h"
-
-namespace {
-
-// Check an extension ID and an URL to be syntactically correct.
-bool CheckExtension(std::string id, std::string update_url) {
-  GURL url(update_url);
-  if (!url.is_valid()) {
-    LOG(WARNING) << "Policy specifies invalid update URL for external "
-                 << "extension: " << update_url;
-    return false;
-  }
-  if (!Extension::IdIsValid(id)) {
-    LOG(WARNING) << "Policy specifies invalid ID for external "
-                 << "extension: " << id;
-    return false;
-  }
-  return true;
-}
-
-}
-
-ExternalPolicyExtensionProvider::ExternalPolicyExtensionProvider(
-    const ListValue* forcelist)
-        : StatefulExternalExtensionProvider(
-            Extension::INVALID,
-            Extension::EXTERNAL_POLICY_DOWNLOAD) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  ProcessPreferences(forcelist);
-}
-
-ExternalPolicyExtensionProvider::~ExternalPolicyExtensionProvider() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void ExternalPolicyExtensionProvider::SetPreferences(
-    const ListValue* forcelist) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  ProcessPreferences(forcelist);
-}
-
-void ExternalPolicyExtensionProvider::ProcessPreferences(
-    const ListValue* forcelist) {
-  DictionaryValue* result = new DictionaryValue();
-  if (forcelist != NULL) {
-    std::string extension_desc;
-    for (ListValue::const_iterator it = forcelist->begin();
-         it != forcelist->end(); ++it) {
-      if (!(*it)->GetAsString(&extension_desc)) {
-        LOG(WARNING) << "Failed to read forcelist string.";
-      } else {
-        // Each string item of the list has the following form:
-        // extension_id_code;extension_update_url
-        // The update URL might also contain semicolons.
-        size_t pos = extension_desc.find(';');
-        std::string id = extension_desc.substr(0, pos);
-        std::string update_url = extension_desc.substr(pos+1);
-        if (CheckExtension(id, update_url)) {
-          result->SetString(id + ".external_update_url", update_url);
-        }
-      }
-    }
-  }
-  set_prefs(result);
-}
diff --git a/chrome/browser/extensions/external_policy_extension_provider.h b/chrome/browser/extensions/external_policy_extension_provider.h
deleted file mode 100644
index 9c36960..0000000
--- a/chrome/browser/extensions/external_policy_extension_provider.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-
-class ListValue;
-class MockExternalPolicyExtensionProviderVisitor;
-class PrefService;
-
-// A specialization of the ExternalExtensionProvider that uses
-// prefs::kExtensionInstallForceList to look up which external extensions are
-// registered. The value of this preference is received via the constructor and
-// via |SetPreferences| in case of run-time updates.
-// Instances of this class are expected to be created and destroyed on the UI
-// thread and they are expecting public method calls from the FILE thread.
-class ExternalPolicyExtensionProvider
-    : public StatefulExternalExtensionProvider {
- public:
-  explicit ExternalPolicyExtensionProvider(const ListValue* forcelist);
-  virtual ~ExternalPolicyExtensionProvider();
-
-  // Set the internal list of extensions based on |forcelist|.
-  // Does not take ownership of |forcelist|.
-  void SetPreferences(const ListValue* forcelist);
-
- private:
-  friend class MockExternalPolicyExtensionProviderVisitor;
-
-  // Set the internal list of extensions based on |forcelist|.
-  // Does not take ownership of |forcelist|.
-  void ProcessPreferences(const ListValue* forcelist);
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_PROVIDER_H_
diff --git a/chrome/browser/extensions/external_policy_extension_provider_unittest.cc b/chrome/browser/extensions/external_policy_extension_provider_unittest.cc
deleted file mode 100644
index cd5a3df..0000000
--- a/chrome/browser/extensions/external_policy_extension_provider_unittest.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/values.h"
-#include "base/version.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/external_policy_extension_provider.h"
-#include "chrome/common/extensions/extension.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class ExternalPolicyExtensionProviderTest : public testing::Test {
- public:
-  ExternalPolicyExtensionProviderTest()
-      : loop_(MessageLoop::TYPE_IO),
-        ui_thread_(BrowserThread::UI, &loop_),
-        file_thread_(BrowserThread::FILE, &loop_) {
-  }
-
-  virtual ~ExternalPolicyExtensionProviderTest() {
-  }
-
- private:
-  MessageLoop loop_;
-  BrowserThread ui_thread_;
-  BrowserThread file_thread_;
-};
-
-class MockExternalPolicyExtensionProviderVisitor
-    : public ExternalExtensionProvider::Visitor {
- public:
-  MockExternalPolicyExtensionProviderVisitor() {
-  }
-
-  // Initialize a provider with |policy_forcelist|, and check that it parses
-  // exactly those extensions, that are specified in |policy_validlist|.
-  void Visit(ListValue* policy_forcelist,
-             ListValue* policy_validlist,
-             const std::set<std::string>& ignore_list) {
-    provider_.reset(new ExternalPolicyExtensionProvider(policy_forcelist));
-
-    // Extensions will be removed from this list as they visited,
-    // so it should be emptied by the end.
-    remaining_extensions = policy_validlist;
-    provider_->VisitRegisteredExtension(this);
-    EXPECT_EQ(0u, remaining_extensions->GetSize());
-  }
-
-  virtual void OnExternalExtensionFileFound(const std::string& id,
-                                            const Version* version,
-                                            const FilePath& path,
-                                            Extension::Location unused) {
-    ADD_FAILURE() << "There should be no external extensions from files.";
-  }
-
-  virtual void OnExternalExtensionUpdateUrlFound(
-      const std::string& id, const GURL& update_url,
-      Extension::Location location) {
-    // Extension has the correct location.
-    EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD, location);
-
-    // Provider returns the correct location when asked.
-    Extension::Location location1;
-    scoped_ptr<Version> version1;
-    provider_->GetExtensionDetails(id, &location1, &version1);
-    EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD, location1);
-    EXPECT_FALSE(version1.get());
-
-    // Remove the extension from our list.
-    StringValue ext_str(id + ";" + update_url.spec());
-    EXPECT_NE(-1, remaining_extensions->Remove(ext_str));
- }
-
- private:
-  ListValue* remaining_extensions;
-
-  scoped_ptr<ExternalPolicyExtensionProvider> provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockExternalPolicyExtensionProviderVisitor);
-};
-
-TEST_F(ExternalPolicyExtensionProviderTest, PolicyIsParsed) {
-  ListValue forced_extensions;
-  forced_extensions.Append(Value::CreateStringValue(
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;http://www.example.com/crx?a=5;b=6"));
-  forced_extensions.Append(Value::CreateStringValue(
-      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;"
-      "https://clients2.google.com/service/update2/crx"));
-
-  MockExternalPolicyExtensionProviderVisitor mv;
-  std::set<std::string> empty;
-  mv.Visit(&forced_extensions, &forced_extensions, empty);
-}
-
-TEST_F(ExternalPolicyExtensionProviderTest, InvalidPolicyIsNotParsed) {
-  ListValue forced_extensions, valid_extensions;
-  StringValue valid(
-      "cccccccccccccccccccccccccccccccc;http://www.example.com/crx");
-  valid_extensions.Append(valid.DeepCopy());
-  forced_extensions.Append(valid.DeepCopy());
-  // Add invalid strings:
-  forced_extensions.Append(Value::CreateStringValue(""));
-  forced_extensions.Append(Value::CreateStringValue(";"));
-  forced_extensions.Append(Value::CreateStringValue(";;"));
-  forced_extensions.Append(Value::CreateStringValue(
-      ";http://www.example.com/crx"));
-  forced_extensions.Append(Value::CreateStringValue(
-      ";aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
-  forced_extensions.Append(Value::CreateStringValue(
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;"));
-  forced_extensions.Append(Value::CreateStringValue(
-      "http://www.example.com/crx;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
-  forced_extensions.Append(Value::CreateStringValue(
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;http#//www.example.com/crx"));
-  forced_extensions.Append(Value::CreateStringValue(
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
-  forced_extensions.Append(Value::CreateStringValue(
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahttp#//www.example.com/crx"));
-
-  MockExternalPolicyExtensionProviderVisitor mv;
-  std::set<std::string> empty;
-  mv.Visit(&forced_extensions, &valid_extensions, empty);
-}
diff --git a/chrome/browser/extensions/external_pref_extension_loader.cc b/chrome/browser/extensions/external_pref_extension_loader.cc
new file mode 100644
index 0000000..8d264a9
--- /dev/null
+++ b/chrome/browser/extensions/external_pref_extension_loader.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/external_pref_extension_loader.h"
+
+#include "app/app_paths.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/common/json_value_serializer.h"
+
+namespace {
+
+// Caller takes ownership of the returned dictionary.
+DictionaryValue* ExtractPrefs(const FilePath& path,
+                              ValueSerializer* serializer) {
+  std::string error_msg;
+  Value* extensions = serializer->Deserialize(NULL, &error_msg);
+  if (!extensions) {
+    LOG(WARNING) << "Unable to deserialize json data: " << error_msg
+                 << " In file " << path.value() << " .";
+  } else {
+    if (!extensions->IsType(Value::TYPE_DICTIONARY)) {
+      LOG(WARNING) << "Expected a JSON dictionary in file "
+                   << path.value() << " .";
+    } else {
+      return static_cast<DictionaryValue*>(extensions);
+    }
+  }
+  return new DictionaryValue;
+}
+
+}  // namespace
+
+ExternalPrefExtensionLoader::ExternalPrefExtensionLoader(int base_path_key)
+    : base_path_key_(base_path_key) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+const FilePath ExternalPrefExtensionLoader::GetBaseCrxFilePath() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // |base_path_| was set in LoadOnFileThread().
+  return base_path_;
+}
+
+void ExternalPrefExtensionLoader::StartLoading() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &ExternalPrefExtensionLoader::LoadOnFileThread));
+}
+
+void ExternalPrefExtensionLoader::LoadOnFileThread() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  // TODO(skerner): Some values of base_path_key_ will cause
+  // PathService::Get() to return false, because the path does
+  // not exist.  Find and fix the build/install scripts so that
+  // this can become a CHECK().  Known examples include chrome
+  // OS developer builds and linux install packages.
+  // Tracked as crbug.com/70402 .
+
+  scoped_ptr<DictionaryValue> prefs;
+  if (PathService::Get(base_path_key_, &base_path_)) {
+    FilePath json_file;
+    json_file =
+        base_path_.Append(FILE_PATH_LITERAL("external_extensions.json"));
+
+    if (file_util::PathExists(json_file)) {
+      JSONFileValueSerializer serializer(json_file);
+      prefs.reset(ExtractPrefs(json_file, &serializer));
+    }
+  }
+
+  if (!prefs.get())
+    prefs.reset(new DictionaryValue());
+
+  prefs_.reset(prefs.release());
+
+  // If we have any records to process, then we must have
+  // read the .json file.  If we read the .json file, then
+  // we were should have set |base_path_|.
+  if (!prefs_->empty())
+    CHECK(!base_path_.empty());
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &ExternalPrefExtensionLoader::LoadFinished));
+}
+
+ExternalTestingExtensionLoader::ExternalTestingExtensionLoader(
+    const std::string& json_data,
+    const FilePath& fake_base_path)
+    : fake_base_path_(fake_base_path) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  JSONStringValueSerializer serializer(json_data);
+  FilePath fake_json_path = fake_base_path.AppendASCII("fake.json");
+  testing_prefs_.reset(ExtractPrefs(fake_json_path, &serializer));
+}
+
+void ExternalTestingExtensionLoader::StartLoading() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  prefs_.reset(testing_prefs_->DeepCopy());
+  LoadFinished();
+}
+
+ExternalTestingExtensionLoader::~ExternalTestingExtensionLoader() {}
+
+const FilePath ExternalTestingExtensionLoader::GetBaseCrxFilePath() {
+  return fake_base_path_;
+}
diff --git a/chrome/browser/extensions/external_pref_extension_loader.h b/chrome/browser/extensions/external_pref_extension_loader.h
new file mode 100644
index 0000000..0590014
--- /dev/null
+++ b/chrome/browser/extensions/external_pref_extension_loader.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_LOADER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_LOADER_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+
+// A specialization of the ExternalExtensionLoader that uses a json file to
+// look up which external extensions are registered.
+// Instances of this class are expected to be created and destroyed on the UI
+// thread and they are expecting public method calls from the UI thread.
+class ExternalPrefExtensionLoader : public ExternalExtensionLoader {
+ public:
+  // |base_path_key| is the directory containing the external_extensions.json
+  // file.  Relative file paths to extension files are resolved relative
+  // to this path.
+  explicit ExternalPrefExtensionLoader(int base_path_key);
+
+  virtual const FilePath GetBaseCrxFilePath();
+
+ protected:
+  virtual void StartLoading();
+
+ private:
+  friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+  virtual ~ExternalPrefExtensionLoader() {}
+
+  void LoadOnFileThread();
+
+  int base_path_key_;
+  FilePath base_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalPrefExtensionLoader);
+};
+
+// A simplified version of ExternalPrefExtensionLoader that loads the dictionary
+// from json data specified in a string.
+class ExternalTestingExtensionLoader : public ExternalExtensionLoader {
+ public:
+  ExternalTestingExtensionLoader(
+      const std::string& json_data,
+      const FilePath& fake_base_path);
+
+  virtual const FilePath GetBaseCrxFilePath();
+
+ protected:
+  virtual void StartLoading();
+
+ private:
+  friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+  virtual ~ExternalTestingExtensionLoader();
+
+  FilePath fake_base_path_;
+  scoped_ptr<DictionaryValue> testing_prefs_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalTestingExtensionLoader);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_LOADER_H_
diff --git a/chrome/browser/extensions/external_pref_extension_provider.cc b/chrome/browser/extensions/external_pref_extension_provider.cc
deleted file mode 100644
index 7ea5f4a..0000000
--- a/chrome/browser/extensions/external_pref_extension_provider.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/external_pref_extension_provider.h"
-
-#include "app/app_paths.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-#include "chrome/common/json_value_serializer.h"
-
-ExternalPrefExtensionProvider::ExternalPrefExtensionProvider()
-  : StatefulExternalExtensionProvider(Extension::EXTERNAL_PREF,
-                                      Extension::EXTERNAL_PREF_DOWNLOAD) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  FilePath json_file;
-  PathService::Get(app::DIR_EXTERNAL_EXTENSIONS, &json_file);
-  json_file = json_file.Append(FILE_PATH_LITERAL("external_extensions.json"));
-
-  if (file_util::PathExists(json_file)) {
-    JSONFileValueSerializer serializer(json_file);
-    SetPreferences(&serializer);
-  } else {
-    set_prefs(new DictionaryValue());
-  }
-}
-
-ExternalPrefExtensionProvider::~ExternalPrefExtensionProvider() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void ExternalPrefExtensionProvider::SetPreferencesForTesting(
-    const std::string& json_data_for_testing) {
-  JSONStringValueSerializer serializer(json_data_for_testing);
-  SetPreferences(&serializer);
-}
-
-void ExternalPrefExtensionProvider::SetPreferences(
-    ValueSerializer* serializer) {
-  std::string error_msg;
-  Value* extensions = serializer->Deserialize(NULL, &error_msg);
-  scoped_ptr<DictionaryValue> dictionary(new DictionaryValue());
-  if (!extensions) {
-    LOG(WARNING) << "Unable to deserialize json data: " << error_msg;
-  } else {
-    if (!extensions->IsType(Value::TYPE_DICTIONARY)) {
-      NOTREACHED() << "Invalid json data";
-    } else {
-      dictionary.reset(static_cast<DictionaryValue*>(extensions));
-    }
-  }
-  set_prefs(dictionary.release());
-}
diff --git a/chrome/browser/extensions/external_pref_extension_provider.h b/chrome/browser/extensions/external_pref_extension_provider.h
deleted file mode 100644
index b74be39..0000000
--- a/chrome/browser/extensions/external_pref_extension_provider.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-
-// A specialization of the ExternalExtensionProvider that uses a json file to
-// look up which external extensions are registered.
-// Instances of this class are expected to be created and destroyed on the UI
-// thread and they are expecting public method calls from the FILE thread.
-class ExternalPrefExtensionProvider : public StatefulExternalExtensionProvider {
- public:
-  explicit ExternalPrefExtensionProvider();
-  virtual ~ExternalPrefExtensionProvider();
-
-  // Used only during testing to not use the json file for external extensions,
-  // but instead parse a json file specified by the test.
-  void SetPreferencesForTesting(const std::string& json_data_for_testing);
-
- private:
-  void SetPreferences(ValueSerializer* serializer);
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_PROVIDER_H_
diff --git a/chrome/browser/extensions/external_registry_extension_loader_win.cc b/chrome/browser/extensions/external_registry_extension_loader_win.cc
new file mode 100644
index 0000000..c78a41b
--- /dev/null
+++ b/chrome/browser/extensions/external_registry_extension_loader_win.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/external_registry_extension_loader_win.h"
+
+#include "base/file_path.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "base/win/registry.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+
+namespace {
+
+// The Registry hive where to look for external extensions.
+const HKEY kRegRoot = HKEY_LOCAL_MACHINE;
+
+// The Registry subkey that contains information about external extensions.
+const char kRegistryExtensions[] = "Software\\Google\\Chrome\\Extensions";
+
+// Registry value of of that key that defines the path to the .crx file.
+const wchar_t kRegistryExtensionPath[] = L"path";
+
+// Registry value of that key that defines the current version of the .crx file.
+const wchar_t kRegistryExtensionVersion[] = L"version";
+
+}  // namespace
+
+void ExternalRegistryExtensionLoader::StartLoading() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &ExternalRegistryExtensionLoader::LoadOnFileThread));
+}
+
+void ExternalRegistryExtensionLoader::LoadOnFileThread() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  scoped_ptr<DictionaryValue> prefs(new DictionaryValue);
+
+  base::win::RegistryKeyIterator iterator(
+      kRegRoot, ASCIIToWide(kRegistryExtensions).c_str());
+  while (iterator.Valid()) {
+    base::win::RegKey key;
+    std::wstring key_path = ASCIIToWide(kRegistryExtensions);
+    key_path.append(L"\\");
+    key_path.append(iterator.Name());
+    if (key.Open(kRegRoot, key_path.c_str(), KEY_READ)  == ERROR_SUCCESS) {
+      std::wstring extension_path_str;
+      if (key.ReadValue(kRegistryExtensionPath, &extension_path_str)
+          == ERROR_SUCCESS) {
+        FilePath extension_path(extension_path_str);
+        if (!extension_path.IsAbsolute()) {
+          LOG(ERROR) << "Path " << extension_path_str
+                     << " needs to be absolute in key "
+                     << key_path;
+          ++iterator;
+          continue;
+        }
+        std::wstring extension_version;
+        if (key.ReadValue(kRegistryExtensionVersion, &extension_version)
+            == ERROR_SUCCESS) {
+          std::string id = WideToASCII(iterator.Name());
+          StringToLowerASCII(&id);
+
+          if (!Extension::IdIsValid(id)) {
+            LOG(ERROR) << "Invalid id value " << id
+                       << " for key " << key_path << " .";
+            ++iterator;
+            continue;
+          }
+
+          scoped_ptr<Version> version;
+          version.reset(Version::GetVersionFromString(
+                            WideToASCII(extension_version)));
+          if (!version.get()) {
+            LOG(ERROR) << "Invalid version value " << extension_version
+                       << " for key " << key_path << " .";
+            ++iterator;
+            continue;
+          }
+
+          prefs->SetString(
+              id + "." + ExternalExtensionProviderImpl::kExternalVersion,
+              WideToASCII(extension_version));
+          prefs->SetString(
+              id + "." + ExternalExtensionProviderImpl::kExternalCrx,
+              extension_path_str);
+        } else {
+          // TODO(erikkay): find a way to get this into about:extensions
+          LOG(ERROR) << "Missing value " << kRegistryExtensionVersion
+                     << " for key " << key_path << " .";
+        }
+      } else {
+        // TODO(erikkay): find a way to get this into about:extensions
+        LOG(ERROR) << "Missing value " << kRegistryExtensionPath
+                   << " for key " << key_path << " .";
+      }
+    }
+    ++iterator;
+  }
+
+  prefs_.reset(prefs.release());
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this,
+          &ExternalRegistryExtensionLoader::LoadFinished));
+}
diff --git a/chrome/browser/extensions/external_registry_extension_loader_win.h b/chrome/browser/extensions/external_registry_extension_loader_win.h
new file mode 100644
index 0000000..7b0d189
--- /dev/null
+++ b/chrome/browser/extensions/external_registry_extension_loader_win.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_LOADER_WIN_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_LOADER_WIN_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+class ExternalRegistryExtensionLoader : public ExternalExtensionLoader {
+ public:
+  ExternalRegistryExtensionLoader() {}
+
+ protected:
+  virtual void StartLoading();
+
+ private:
+  friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+  virtual ~ExternalRegistryExtensionLoader() {}
+
+  void LoadOnFileThread();
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalRegistryExtensionLoader);
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_LOADER_WIN_H_
diff --git a/chrome/browser/extensions/external_registry_extension_provider_win.cc b/chrome/browser/extensions/external_registry_extension_provider_win.cc
deleted file mode 100644
index 16b107f..0000000
--- a/chrome/browser/extensions/external_registry_extension_provider_win.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/external_registry_extension_provider_win.h"
-
-#include "base/file_path.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "base/version.h"
-#include "base/win/registry.h"
-
-namespace {
-
-// The Registry hive where to look for external extensions.
-const HKEY kRegRoot = HKEY_LOCAL_MACHINE;
-
-// The Registry subkey that contains information about external extensions.
-const char kRegistryExtensions[] = "Software\\Google\\Chrome\\Extensions";
-
-// Registry value of of that key that defines the path to the .crx file.
-const wchar_t kRegistryExtensionPath[] = L"path";
-
-// Registry value of that key that defines the current version of the .crx file.
-const wchar_t kRegistryExtensionVersion[] = L"version";
-
-bool OpenKeyById(const std::string& id, base::win::RegKey *key) {
-  std::wstring key_path = ASCIIToWide(kRegistryExtensions);
-  key_path.append(L"\\");
-  key_path.append(ASCIIToWide(id));
-
-  return key->Open(kRegRoot, key_path.c_str(), KEY_READ);
-}
-
-}  // namespace
-
-ExternalRegistryExtensionProvider::ExternalRegistryExtensionProvider() {
-}
-
-ExternalRegistryExtensionProvider::~ExternalRegistryExtensionProvider() {
-}
-
-void ExternalRegistryExtensionProvider::VisitRegisteredExtension(
-    Visitor* visitor) const {
-  base::win::RegistryKeyIterator iterator(
-      kRegRoot, ASCIIToWide(kRegistryExtensions).c_str());
-  while (iterator.Valid()) {
-    base::win::RegKey key;
-    std::wstring key_path = ASCIIToWide(kRegistryExtensions);
-    key_path.append(L"\\");
-    key_path.append(iterator.Name());
-    if (key.Open(kRegRoot, key_path.c_str(), KEY_READ)) {
-      std::wstring extension_path;
-      if (key.ReadValue(kRegistryExtensionPath, &extension_path)) {
-        std::wstring extension_version;
-        if (key.ReadValue(kRegistryExtensionVersion, &extension_version)) {
-          std::string id = WideToASCII(iterator.Name());
-          StringToLowerASCII(&id);
-
-          scoped_ptr<Version> version;
-          version.reset(Version::GetVersionFromString(
-                            WideToASCII(extension_version)));
-          if (!version.get()) {
-            LOG(ERROR) << "Invalid version value " << extension_version
-                       << " for key " << key_path;
-            ++iterator;
-            continue;
-          }
-
-          FilePath path = FilePath::FromWStringHack(extension_path);
-          visitor->OnExternalExtensionFileFound(id, version.get(), path,
-                                                Extension::EXTERNAL_REGISTRY);
-        } else {
-          // TODO(erikkay): find a way to get this into about:extensions
-          LOG(ERROR) << "Missing value " << kRegistryExtensionVersion
-                     << " for key " << key_path;
-        }
-      } else {
-        // TODO(erikkay): find a way to get this into about:extensions
-        LOG(ERROR) << "Missing value " << kRegistryExtensionPath
-                   << " for key " << key_path;
-      }
-    }
-    ++iterator;
-  }
-}
-
-
-bool ExternalRegistryExtensionProvider::HasExtension(
-    const std::string& id) const {
-  base::win::RegKey key;
-  return OpenKeyById(id, &key);
-}
-
-bool ExternalRegistryExtensionProvider::GetExtensionDetails(
-    const std::string& id,
-    Extension::Location* location,
-    scoped_ptr<Version>* version) const  {
-  base::win::RegKey key;
-  if (!OpenKeyById(id, &key))
-    return false;
-
-  std::wstring extension_version;
-  if (!key.ReadValue(kRegistryExtensionVersion, &extension_version))
-    return false;
-
-  if (version) {
-    version->reset(Version::GetVersionFromString(
-                       WideToASCII(extension_version)));
-  }
-
-  if (location)
-    *location = Extension::EXTERNAL_REGISTRY;
-  return true;
-}
diff --git a/chrome/browser/extensions/external_registry_extension_provider_win.h b/chrome/browser/extensions/external_registry_extension_provider_win.h
deleted file mode 100644
index 34899ae..0000000
--- a/chrome/browser/extensions/external_registry_extension_provider_win.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_PROVIDER_WIN_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_PROVIDER_WIN_H_
-#pragma once
-
-#include "chrome/browser/extensions/external_extension_provider.h"
-
-class Version;
-
-// A specialization of the ExternalExtensionProvider that uses the Registry to
-// look up which external extensions are registered.
-class ExternalRegistryExtensionProvider : public ExternalExtensionProvider {
- public:
-  ExternalRegistryExtensionProvider();
-  virtual ~ExternalRegistryExtensionProvider();
-
-  // ExternalExtensionProvider implementation:
-  virtual void VisitRegisteredExtension(Visitor* visitor) const;
-
-  virtual bool HasExtension(const std::string& id) const;
-
-  virtual bool GetExtensionDetails(const std::string& id,
-                                   Extension::Location* location,
-                                   scoped_ptr<Version>* version) const;
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_PROVIDER_WIN_H_
diff --git a/chrome/browser/extensions/fragment_navigation_apitest.cc b/chrome/browser/extensions/fragment_navigation_apitest.cc
deleted file mode 100644
index 8d931a8..0000000
--- a/chrome/browser/extensions/fragment_navigation_apitest.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_apitest.h"
-
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptFragmentNavigation) {
-  ASSERT_TRUE(StartTestServer());
-  const char* extension_name = "content_scripts/fragment";
-  ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
-}
-
-// Crashy, http://crbug.com/67774.
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
-                       DISABLED_ExecuteScriptFragmentNavigation) {
-  ASSERT_TRUE(StartTestServer());
-  const char* extension_name = "executescript/fragment";
-  ASSERT_TRUE(RunExtensionTest(extension_name)) << message_;
-}
diff --git a/chrome/browser/extensions/image_loading_tracker_unittest.cc b/chrome/browser/extensions/image_loading_tracker_unittest.cc
index 4c9734f..b0516ad 100644
--- a/chrome/browser/extensions/image_loading_tracker_unittest.cc
+++ b/chrome/browser/extensions/image_loading_tracker_unittest.cc
@@ -13,9 +13,9 @@
 #include "chrome/common/json_value_serializer.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/size.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/size.h"
 
 class ImageLoadingTrackerTest : public testing::Test,
                                 public ImageLoadingTracker::Observer {
diff --git a/chrome/browser/extensions/isolated_world_apitest.cc b/chrome/browser/extensions/isolated_world_apitest.cc
deleted file mode 100644
index 6a71b5b..0000000
--- a/chrome/browser/extensions/isolated_world_apitest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/extension_apitest.h"
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IsolatedWorld1) {
-  // This extension runs various bits of script and tests that they all run in
-  // the same isolated world.
-  ASSERT_TRUE(StartTestServer());
-  ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world1")) << message_;
-
-  // Now load a different extension, inject into same page, verify worlds aren't
-  // shared.
-  ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world2")) << message_;
-}
diff --git a/chrome/browser/extensions/key_identifier_conversion_views.cc b/chrome/browser/extensions/key_identifier_conversion_views.cc
new file mode 100644
index 0000000..a9829be
--- /dev/null
+++ b/chrome/browser/extensions/key_identifier_conversion_views.cc
@@ -0,0 +1,336 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/key_identifier_conversion_views.h"
+
+#include <string.h>
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "chrome/browser/browser_thread.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "views/events/event.h"
+
+namespace {
+
+static const int kNumIdentifierTypes = 3;
+
+typedef struct KeyIdentifier {
+  // In order: key identifier, character and unicode codepoint.  They are
+  // searched in that order as well.
+  // These are all placed into a single array as they are treated uniformly and
+  // we never refer to a specific type of identifier.  This reduces code
+  // duplication below.
+  const char* identifiers[kNumIdentifierTypes];
+  const ui::KeyboardCode key_code;
+  const int event_flags;
+} KeyIdentifier;
+
+// Taken from Section 6.3.3 here:
+// http://www.w3.org/TR/DOM-Level-3-Events/#keyset-keyidentifiers
+// TODO(bryeung): keycodes could be wrong: I took the keydown code only
+static const KeyIdentifier kKeyIdentifiers[] = {
+  { {"Accept", "", ""}, ui::VKEY_ACCEPT, 0 },
+  { {"Add", "", ""}, ui::VKEY_ADD, 0 },
+  { {"Again", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"AllCandidates", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Alphanumeric", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Alt", "", ""}, ui::VKEY_MENU, 0 },
+  { {"AltGraph", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Apps", "", ""}, ui::VKEY_APPS, 0 },
+  { {"Attn", "", ""}, ui::VKEY_ATTN, 0 },
+  { {"BrowserBack", "", ""}, ui::VKEY_BROWSER_BACK, 0 },
+  { {"BrowserFavorites", "", ""}, ui::VKEY_BROWSER_FAVORITES, 0 },
+  { {"BrowserForward", "", ""}, ui::VKEY_BROWSER_FAVORITES, 0 },
+  { {"BrowserHome", "", ""}, ui::VKEY_BROWSER_HOME, 0 },
+  { {"BrowserRefresh", "", ""}, ui::VKEY_BROWSER_REFRESH, 0 },
+  { {"BrowserSearch", "", ""}, ui::VKEY_BROWSER_SEARCH, 0 },
+  { {"BrowserStop", "", ""}, ui::VKEY_BROWSER_STOP, 0 },
+  { {"CapsLock", "", ""}, ui::VKEY_CAPITAL, 0 },
+  { {"Clear", "", ""}, ui::VKEY_OEM_CLEAR, 0 },
+  { {"CodeInput", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Compose", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Control", "", ""}, ui::VKEY_CONTROL, 0 },
+  { {"Crsel", "", ""}, ui::VKEY_CRSEL, 0 },
+  { {"Convert", "", ""}, ui::VKEY_CONVERT, 0 },
+  { {"Copy", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Cut", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Decimal", "", ""}, ui::VKEY_DECIMAL, 0 },
+  { {"Divide", "", ""}, ui::VKEY_DIVIDE, 0 },
+  { {"Down", "", ""}, ui::VKEY_DOWN, 0 },
+  { {"DownLeft", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"DownRight", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"End", "", ""}, ui::VKEY_END, 0 },
+  { {"Enter", "", ""}, ui::VKEY_RETURN, 0 },
+  { {"EraseEof", "", ""}, ui::VKEY_EREOF, 0 },
+  { {"Execute", "", ""}, ui::VKEY_EXECUTE, 0 },
+  { {"Exsel", "", ""}, ui::VKEY_EXSEL, 0 },
+  { {"Fn", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"F1", "", ""}, ui::VKEY_F1, 0 },
+  { {"F2", "", ""}, ui::VKEY_F2, 0 },
+  { {"F3", "", ""}, ui::VKEY_F3, 0 },
+  { {"F4", "", ""}, ui::VKEY_F4, 0 },
+  { {"F5", "", ""}, ui::VKEY_F5, 0 },
+  { {"F6", "", ""}, ui::VKEY_F6, 0 },
+  { {"F7", "", ""}, ui::VKEY_F7, 0 },
+  { {"F8", "", ""}, ui::VKEY_F8, 0 },
+  { {"F9", "", ""}, ui::VKEY_F9, 0 },
+  { {"F10", "", ""}, ui::VKEY_F10, 0 },
+  { {"F11", "", ""}, ui::VKEY_F11, 0 },
+  { {"F12", "", ""}, ui::VKEY_F12, 0 },
+  { {"F13", "", ""}, ui::VKEY_F13, 0 },
+  { {"F14", "", ""}, ui::VKEY_F14, 0 },
+  { {"F15", "", ""}, ui::VKEY_F15, 0 },
+  { {"F16", "", ""}, ui::VKEY_F16, 0 },
+  { {"F17", "", ""}, ui::VKEY_F17, 0 },
+  { {"F18", "", ""}, ui::VKEY_F18, 0 },
+  { {"F19", "", ""}, ui::VKEY_F19, 0 },
+  { {"F20", "", ""}, ui::VKEY_F20, 0 },
+  { {"F21", "", ""}, ui::VKEY_F21, 0 },
+  { {"F22", "", ""}, ui::VKEY_F22, 0 },
+  { {"F23", "", ""}, ui::VKEY_F23, 0 },
+  { {"F24", "", ""}, ui::VKEY_F24, 0 },
+  { {"FinalMode", "", ""}, ui::VKEY_FINAL, 0 },
+  { {"Find", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"FullWidth", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"HalfWidth", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"HangulMode", "", ""}, ui::VKEY_HANGUL, 0 },
+  { {"HanjaMode", "", ""}, ui::VKEY_HANJA, 0 },
+  { {"Help", "", ""}, ui::VKEY_HELP, 0 },
+  { {"Hiragana", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Home", "", ""}, ui::VKEY_HOME, 0 },
+  { {"Insert", "", ""}, ui::VKEY_INSERT, 0 },
+  { {"JapaneseHiragana", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"JapaneseKatakana", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"JapaneseRomaji", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"JunjaMode", "", ""}, ui::VKEY_JUNJA, 0 },
+  { {"KanaMode", "", ""}, ui::VKEY_KANA, 0 },
+  { {"KanjiMode", "", ""}, ui::VKEY_KANJI, 0 },
+  { {"Katakana", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"LaunchApplication1", "", ""}, ui::VKEY_MEDIA_LAUNCH_APP1, 0 },
+  { {"LaunchApplication2", "", ""}, ui::VKEY_MEDIA_LAUNCH_APP2, 0 },
+  { {"LaunchMail", "", ""}, ui::VKEY_MEDIA_LAUNCH_MAIL, 0 },
+  { {"Left", "", ""}, ui::VKEY_LEFT, 0 },
+  { {"Menu", "", ""}, ui::VKEY_MENU, 0 },
+  { {"Meta", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"MediaNextTrack", "", ""}, ui::VKEY_MEDIA_NEXT_TRACK, 0 },
+  { {"MediaPlayPause", "", ""}, ui::VKEY_MEDIA_PLAY_PAUSE, 0 },
+  { {"MediaPreviousTrack", "", ""}, ui::VKEY_MEDIA_PREV_TRACK, 0 },
+  { {"MediaStop", "", ""}, ui::VKEY_MEDIA_STOP, 0 },
+  { {"ModeChange", "", ""}, ui::VKEY_MODECHANGE, 0 },
+  { {"Multiply", "", ""}, ui::VKEY_MULTIPLY, 0 },
+  { {"NextCandidate", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Nonconvert", "", ""}, ui::VKEY_NONCONVERT, 0 },
+  { {"NumLock", "", ""}, ui::VKEY_NUMLOCK, 0 },
+  { {"PageDown", "", ""}, ui::VKEY_NEXT, 0 },
+  { {"PageUp", "", ""}, ui::VKEY_PRIOR, 0 },
+  { {"Paste", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Pause", "", ""}, ui::VKEY_PAUSE, 0 },
+  { {"Play", "", ""}, ui::VKEY_PLAY, 0 },
+  { {"PreviousCandidate", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"PrintScreen", "", ""}, ui::VKEY_SNAPSHOT, 0 },
+  { {"Process", "", ""}, ui::VKEY_PROCESSKEY, 0 },
+  { {"Props", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Right", "", ""}, ui::VKEY_RIGHT, 0 },
+  { {"RomanCharacters", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Scroll", "", ""}, ui::VKEY_SCROLL, 0 },
+  { {"Select", "", ""}, ui::VKEY_SELECT, 0 },
+  { {"SelectMedia", "", ""}, ui::VKEY_MEDIA_LAUNCH_MEDIA_SELECT, 0 },
+  { {"Separator", "", ""}, ui::VKEY_SEPARATOR, 0 },
+  { {"Shift", "", ""}, ui::VKEY_SHIFT, 0 },
+  { {"Soft1", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Soft2", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Soft3", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Soft4", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Stop", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Subtract", "", ""}, ui::VKEY_SUBTRACT, 0 },
+  { {"Up", "", ""}, ui::VKEY_UP, 0 },
+  { {"UpLeft", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"UpRight", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"Undo", "", ""}, ui::VKEY_UNKNOWN, 0 },
+  { {"VolumeDown", "", ""}, ui::VKEY_VOLUME_DOWN, 0 },
+  { {"VolumeMute", "", ""}, ui::VKEY_VOLUME_MUTE, 0 },
+  { {"VolumeUp", "", ""}, ui::VKEY_VOLUME_UP, 0 },
+  { {"Win", "", ""}, ui::VKEY_LWIN, 0 },
+  { {"Zoom", "", ""}, ui::VKEY_ZOOM, 0 },
+  { {"Backspace", "", "U+0008"}, ui::VKEY_BACK, 0 },
+  { {"Tab", "", "U+0009"}, ui::VKEY_TAB, 0 },
+  { {"Cancel", "", "U+0018"}, ui::VKEY_UNKNOWN, 0 },
+  { {"Esc", "", "U+001B"}, ui::VKEY_ESCAPE, 0 },
+  { {"Spacebar", " ", "U+0020"}, ui::VKEY_SPACE, 0 },
+  { {"Exclamation", "!", "U+0021"}, ui::VKEY_1, ui::EF_SHIFT_DOWN },
+  { {"DoubleQuote", "\"", "U+0022"},
+      ui::VKEY_OEM_7, ui::EF_SHIFT_DOWN },
+  { {"Hash", "#", "U+0023"}, ui::VKEY_3, ui::EF_SHIFT_DOWN },
+  { {"Dollar", "$", "U+0024"}, ui::VKEY_4, ui::EF_SHIFT_DOWN },
+  { {"Ampersand", "&", "U+0026"}, ui::VKEY_7, ui::EF_SHIFT_DOWN },
+  { {"Apostrophe", "\'", "U+0027"}, ui::VKEY_OEM_7, 0 },
+  { {"LeftParen", "(", "U+0028"}, ui::VKEY_9, ui::EF_SHIFT_DOWN },
+  { {"RightParen", ")", "U+0029"}, ui::VKEY_0, ui::EF_SHIFT_DOWN },
+  { {"Asterisk", "*", "U+002A"}, ui::VKEY_8, ui::EF_SHIFT_DOWN },
+  { {"Plus", "+", "U+002B"}, ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN },
+  { {"Percent", "%", "U+0025"}, ui::VKEY_5, ui::EF_SHIFT_DOWN },
+  { {"Comma", ",", "U+002C"}, ui::VKEY_OEM_COMMA, 0 },
+  { {"HyphenMinus", "-", "U+002D"}, ui::VKEY_OEM_MINUS, 0 },
+  { {"Period", ".", "U+002E"}, ui::VKEY_OEM_PERIOD, 0 },
+  { {"Solidus", "/", "U+002F"}, ui::VKEY_OEM_2, 0 },
+  { {"", "0", "U+0030"}, ui::VKEY_0, 0 },
+  { {"", "1", "U+0031"}, ui::VKEY_1, 0 },
+  { {"", "2", "U+0032"}, ui::VKEY_2, 0 },
+  { {"", "3", "U+0033"}, ui::VKEY_3, 0 },
+  { {"", "4", "U+0034"}, ui::VKEY_4, 0 },
+  { {"", "5", "U+0035"}, ui::VKEY_5, 0 },
+  { {"", "6", "U+0036"}, ui::VKEY_6, 0 },
+  { {"", "7", "U+0037"}, ui::VKEY_7, 0 },
+  { {"", "8", "U+0038"}, ui::VKEY_8, 0 },
+  { {"", "9", "U+0039"}, ui::VKEY_9, 0 },
+  { {"Colon", ":", "U+003A"}, ui::VKEY_OEM_1, ui::EF_SHIFT_DOWN },
+  { {"Semicolon", ";", "U+003B"}, ui::VKEY_OEM_1, 0 },
+  { {"LessThan", "<", "U+003C"},
+      ui::VKEY_OEM_COMMA, ui::EF_SHIFT_DOWN },
+  { {"Equals", "=", "U+003D"}, ui::VKEY_OEM_PLUS, 0 },
+  { {"GreaterThan", ">", "U+003E"},
+      ui::VKEY_OEM_PERIOD, ui::EF_SHIFT_DOWN },
+  { {"QuestionMark", "?", "U+003F"},
+      ui::VKEY_OEM_2, ui::EF_SHIFT_DOWN },
+  { {"At", "@", "U+0040"}, ui::VKEY_2, ui::EF_SHIFT_DOWN },
+  { {"", "A", "U+0041"}, ui::VKEY_A, 0 },
+  { {"", "B", "U+0042"}, ui::VKEY_B, 0 },
+  { {"", "C", "U+0043"}, ui::VKEY_C, 0 },
+  { {"", "D", "U+0044"}, ui::VKEY_D, 0 },
+  { {"", "E", "U+0045"}, ui::VKEY_E, 0 },
+  { {"", "F", "U+0046"}, ui::VKEY_F, 0 },
+  { {"", "G", "U+0047"}, ui::VKEY_G, 0 },
+  { {"", "H", "U+0048"}, ui::VKEY_H, 0 },
+  { {"", "I", "U+0049"}, ui::VKEY_I, 0 },
+  { {"", "J", "U+004A"}, ui::VKEY_J, 0 },
+  { {"", "K", "U+004B"}, ui::VKEY_K, 0 },
+  { {"", "L", "U+004C"}, ui::VKEY_L, 0 },
+  { {"", "M", "U+004D"}, ui::VKEY_M, 0 },
+  { {"", "N", "U+004E"}, ui::VKEY_N, 0 },
+  { {"", "O", "U+004F"}, ui::VKEY_O, 0 },
+  { {"", "P", "U+0050"}, ui::VKEY_P, 0 },
+  { {"", "Q", "U+0051"}, ui::VKEY_Q, 0 },
+  { {"", "R", "U+0052"}, ui::VKEY_R, 0 },
+  { {"", "S", "U+0053"}, ui::VKEY_S, 0 },
+  { {"", "T", "U+0054"}, ui::VKEY_T, 0 },
+  { {"", "U", "U+0055"}, ui::VKEY_U, 0 },
+  { {"", "V", "U+0056"}, ui::VKEY_V, 0 },
+  { {"", "W", "U+0057"}, ui::VKEY_W, 0 },
+  { {"", "X", "U+0058"}, ui::VKEY_X, 0 },
+  { {"", "Y", "U+0059"}, ui::VKEY_Y, 0 },
+  { {"", "Z", "U+005A"}, ui::VKEY_Z, 0 },
+  { {"", "a", "U+0061"}, ui::VKEY_A, 0 },
+  { {"", "b", "U+0062"}, ui::VKEY_B, 0 },
+  { {"", "c", "U+0063"}, ui::VKEY_C, 0 },
+  { {"", "d", "U+0064"}, ui::VKEY_D, 0 },
+  { {"", "e", "U+0065"}, ui::VKEY_E, 0 },
+  { {"", "f", "U+0066"}, ui::VKEY_F, 0 },
+  { {"", "g", "U+0067"}, ui::VKEY_G, 0 },
+  { {"", "h", "U+0068"}, ui::VKEY_H, 0 },
+  { {"", "i", "U+0069"}, ui::VKEY_I, 0 },
+  { {"", "j", "U+006A"}, ui::VKEY_J, 0 },
+  { {"", "k", "U+006B"}, ui::VKEY_K, 0 },
+  { {"", "l", "U+006C"}, ui::VKEY_L, 0 },
+  { {"", "m", "U+006D"}, ui::VKEY_M, 0 },
+  { {"", "n", "U+006E"}, ui::VKEY_N, 0 },
+  { {"", "o", "U+006F"}, ui::VKEY_O, 0 },
+  { {"", "p", "U+0070"}, ui::VKEY_P, 0 },
+  { {"", "q", "U+0071"}, ui::VKEY_Q, 0 },
+  { {"", "r", "U+0072"}, ui::VKEY_R, 0 },
+  { {"", "s", "U+0073"}, ui::VKEY_S, 0 },
+  { {"", "t", "U+0074"}, ui::VKEY_T, 0 },
+  { {"", "u", "U+0075"}, ui::VKEY_U, 0 },
+  { {"", "v", "U+0076"}, ui::VKEY_V, 0 },
+  { {"", "w", "U+0077"}, ui::VKEY_W, 0 },
+  { {"", "x", "U+0078"}, ui::VKEY_X, 0 },
+  { {"", "y", "U+0079"}, ui::VKEY_Y, 0 },
+  { {"", "z", "U+007A"}, ui::VKEY_Z, 0 },
+  { {"LeftSquareBracket", "[", "U+005B"}, ui::VKEY_OEM_4, 0 },
+  { {"Backslash", "\\", "U+005C"}, ui::VKEY_OEM_5, 0 },
+  { {"RightSquareBracket", "]", "U+005D"}, ui::VKEY_OEM_6, 0 },
+  { {"Circumflex", "^", "U+005E"}, ui::VKEY_6, ui::EF_SHIFT_DOWN },
+  { {"Underscore", "_", "U+005F"},
+      ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN },
+  { {"Grave", "`", "U+0060"}, ui::VKEY_OEM_3, 0 },
+  { {"Tilde", "~", "U+007E"}, ui::VKEY_OEM_3, ui::EF_SHIFT_DOWN },
+  { {"LeftCurlyBracket", "{", "U+007B"},
+      ui::VKEY_OEM_4, ui::EF_SHIFT_DOWN },
+  { {"Pipe", "|", "U+007C"}, ui::VKEY_OEM_5, ui::EF_SHIFT_DOWN },
+  { {"RightCurlyBracket", "}", "U+007D"},
+      ui::VKEY_OEM_6, ui::EF_SHIFT_DOWN },
+  { {"Del", "", "U+007F"}, ui::VKEY_DELETE, 0 },
+  { {"InvertedExclamation", "", "U+00A1"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadGrave", "", "U+0300"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadEacute", "", "U+0301"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadCircumflex", "", "U+0302"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadTilde", "", "U+0303"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadMacron", "", "U+0304"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadBreve", "", "U+0306"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadAboveDot", "", "U+0307"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadUmlaut", "", "U+0308"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadAboveRing", "", "U+030A"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadDoubleacute", "", "U+030B"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadCaron", "", "U+030C"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadCedilla", "", "U+0327"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadOgonek", "", "U+0328"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadIota", "", "U+0345"}, ui::VKEY_UNKNOWN, 0 },
+  { {"Euro", "", "U+20AC"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadVoicedSound", "", "U+3099"}, ui::VKEY_UNKNOWN, 0 },
+  { {"DeadSemivoicedSound", "", "U+309A"}, ui::VKEY_UNKNOWN, 0 }
+};
+
+static const int kNumKeyIdentifiers = arraysize(kKeyIdentifiers);
+
+typedef base::hash_map<std::string, const views::KeyEvent*> IdentifierMap;
+typedef std::pair<std::string, const views::KeyEvent*> IdentifierPair;
+static IdentifierMap* identifierMaps[kNumIdentifierTypes] = { NULL };
+
+static views::KeyEvent* kUnknownKeyEvent = NULL;
+
+static void InitializeMaps() {
+  if (identifierMaps[0])
+    return;
+
+  kUnknownKeyEvent = new views::KeyEvent(
+    ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, 0);
+
+  for (int i = 0; i < kNumIdentifierTypes; ++i)
+    identifierMaps[i] = new IdentifierMap;
+
+  for (int i = 0; i < kNumKeyIdentifiers; ++i) {
+    const KeyIdentifier& key = kKeyIdentifiers[i];
+
+    views::KeyEvent* event = new views::KeyEvent(
+        ui::ET_KEY_PRESSED, key.key_code, key.event_flags);
+
+    for (int j = 0; j < kNumIdentifierTypes; ++j) {
+      if (key.identifiers[j][0] != '\0') {
+        std::pair<IdentifierMap::iterator, bool> result =
+            identifierMaps[j]->insert(
+                IdentifierPair(key.identifiers[j], event));
+        DCHECK(result.second);
+      }
+    }
+  }
+}
+
+}  // namespace
+
+
+const views::KeyEvent& KeyEventFromKeyIdentifier(
+    const std::string& key_identifier) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  InitializeMaps();
+
+  for (int i = 0; i < kNumIdentifierTypes; ++i) {
+    const IdentifierMap& map = *identifierMaps[i];
+
+    IdentifierMap::const_iterator iter = map.find(key_identifier);
+    if (iter != map.end())
+      return *iter->second;
+  }
+
+  return *kUnknownKeyEvent;
+}
diff --git a/chrome/browser/extensions/key_identifier_conversion_views.h b/chrome/browser/extensions/key_identifier_conversion_views.h
new file mode 100644
index 0000000..51d6171
--- /dev/null
+++ b/chrome/browser/extensions/key_identifier_conversion_views.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_KEY_IDENTIFIER_CONVERSION_VIEWS_H_
+#define CHROME_BROWSER_EXTENSIONS_KEY_IDENTIFIER_CONVERSION_VIEWS_H_
+#pragma once
+
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "views/events/event.h"
+
+#include <string>
+
+// Convert a KeyIdentifer (see Section 6.3.3 here:
+// http://www.w3.org/TR/DOM-Level-3-Events/#keyset-keyidentifiers)
+// to a views::KeyEvent.
+const views::KeyEvent& KeyEventFromKeyIdentifier(
+    const std::string& key_identifier);
+
+#endif  // CHROME_BROWSER_EXTENSIONS_KEY_IDENTIFIER_CONVERSION_VIEWS_H_
diff --git a/chrome/browser/extensions/key_identifier_conversion_views_unittest.cc b/chrome/browser/extensions/key_identifier_conversion_views_unittest.cc
new file mode 100644
index 0000000..43c7f76
--- /dev/null
+++ b/chrome/browser/extensions/key_identifier_conversion_views_unittest.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/extensions/key_identifier_conversion_views.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "chrome/browser/browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+
+namespace {
+
+class KeyEventFromKeyIdentifierTest : public testing::Test {
+ protected:
+  KeyEventFromKeyIdentifierTest()
+      : ui_thread_(BrowserThread::UI, &message_loop_) {}
+
+  MessageLoopForUI message_loop_;
+  BrowserThread ui_thread_;
+};
+
+TEST_F(KeyEventFromKeyIdentifierTest, MatchOnIdentifier) {
+  EXPECT_EQ(ui::VKEY_APPS, KeyEventFromKeyIdentifier("Apps").key_code());
+  EXPECT_EQ(ui::VKEY_UNKNOWN,
+      KeyEventFromKeyIdentifier("Nonsense").key_code());
+}
+
+TEST_F(KeyEventFromKeyIdentifierTest, MatchOnCharacter) {
+  EXPECT_EQ(ui::VKEY_A, KeyEventFromKeyIdentifier("a").key_code());
+  EXPECT_EQ(ui::VKEY_A, KeyEventFromKeyIdentifier("A").key_code());
+  EXPECT_EQ(ui::VKEY_OEM_PERIOD, KeyEventFromKeyIdentifier(">").key_code());
+
+  std::string non_printing_char(" ");
+  non_printing_char[0] = static_cast<char>(1);
+  EXPECT_EQ(ui::VKEY_UNKNOWN,
+      KeyEventFromKeyIdentifier(non_printing_char).key_code());
+}
+
+TEST_F(KeyEventFromKeyIdentifierTest, MatchOnUnicodeCodepoint) {
+  EXPECT_EQ(ui::VKEY_A, KeyEventFromKeyIdentifier("U+0041").key_code());
+  EXPECT_EQ(ui::VKEY_A, KeyEventFromKeyIdentifier("U+0061").key_code());
+  EXPECT_EQ(ui::VKEY_DELETE, KeyEventFromKeyIdentifier("U+007F").key_code());
+
+  // this one exists in the map, but has no valid ui::VKEY
+  EXPECT_EQ(ui::VKEY_UNKNOWN, KeyEventFromKeyIdentifier("U+030A").key_code());
+
+  // this one is not in the map
+  EXPECT_EQ(ui::VKEY_UNKNOWN, KeyEventFromKeyIdentifier("U+0001").key_code());
+}
+
+TEST_F(KeyEventFromKeyIdentifierTest, DoesNotMatchEmptyString) {
+  EXPECT_EQ(ui::VKEY_UNKNOWN, KeyEventFromKeyIdentifier("").key_code());
+}
+
+TEST_F(KeyEventFromKeyIdentifierTest, ShiftModifiersAreSet) {
+  EXPECT_EQ(0, KeyEventFromKeyIdentifier("1").flags());
+
+  const char* keys_with_shift[] = {
+    "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+",
+    "{", "}", "|", ":", "<", ">", "?", "\""
+  };
+  int kNumKeysWithShift = arraysize(keys_with_shift);
+
+  for (int i = 0; i < kNumKeysWithShift; ++i) {
+    EXPECT_EQ(ui::EF_SHIFT_DOWN,
+        KeyEventFromKeyIdentifier(keys_with_shift[i]).flags());
+  }
+}
+
+}  // namespace
diff --git a/chrome/browser/extensions/pack_extension_job.cc b/chrome/browser/extensions/pack_extension_job.cc
index f4e2a03..41f87d2 100644
--- a/chrome/browser/extensions/pack_extension_job.cc
+++ b/chrome/browser/extensions/pack_extension_job.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/extensions/pack_extension_job.h"
 
-#include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -12,6 +11,7 @@
 #include "chrome/browser/extensions/extension_creator.h"
 #include "chrome/common/chrome_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 PackExtensionJob::PackExtensionJob(Client* client,
                                    const FilePath& root_directory,
diff --git a/chrome/browser/extensions/page_action_apitest.cc b/chrome/browser/extensions/page_action_apitest.cc
index 504f909..e4b80e5 100644
--- a/chrome/browser/extensions/page_action_apitest.cc
+++ b/chrome/browser/extensions/page_action_apitest.cc
@@ -40,7 +40,8 @@
     ResultCatcher catcher;
     int tab_id =
         ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents());
-    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+    ExtensionService* service = browser()->profile()->GetExtensionService();
+    service->browser_event_router()->PageActionExecuted(
         browser()->profile(), extension->id(), "", tab_id, "", 0);
     EXPECT_TRUE(catcher.GetNextResult());
   }
@@ -77,7 +78,8 @@
   // install a page action popup.
   {
     ResultCatcher catcher;
-    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+    ExtensionService* service = browser()->profile()->GetExtensionService();
+    service->browser_event_router()->PageActionExecuted(
         browser()->profile(), extension->id(), "action", tab_id, "", 1);
     ASSERT_TRUE(catcher.GetNextResult());
   }
@@ -152,7 +154,8 @@
     ResultCatcher catcher;
     int tab_id =
         ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents());
-    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+    ExtensionService* service = browser()->profile()->GetExtensionService();
+    service->browser_event_router()->PageActionExecuted(
         browser()->profile(), extension->id(), "action", tab_id, "", 1);
     EXPECT_TRUE(catcher.GetNextResult());
   }
diff --git a/chrome/browser/extensions/permissions_apitest.cc b/chrome/browser/extensions/permissions_apitest.cc
index e1db706..33adfe2 100644
--- a/chrome/browser/extensions/permissions_apitest.cc
+++ b/chrome/browser/extensions/permissions_apitest.cc
@@ -47,18 +47,3 @@
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, AlwaysAllowed) {
   ASSERT_TRUE(RunExtensionTest("permissions/always_allowed")) << message_;
 }
-
-// TODO(gregoryd): run the NaCl test on all systems once
-// http://code.google.com/p/chromium/issues/detail?id=51335 is fixed.
-// Meanwhile we run it on Mac OSX only, since we can be sure that an x86-32 NaCl
-// module will work there.
-// Mark as Flaky.  http://crbug.com/51861
-//
-// FLAKY --> DISABLED since it takes 10sec to timeout a dialog.  Need
-// faster timeout.
-#if defined(OS_MACOSX)
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_NaClPermissionEnabled) {
-  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kInternalNaCl);
-  ASSERT_TRUE(RunExtensionTest("permissions/nacl_enabled")) << message_;
-}
-#endif
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
index 9d7e45b..31c4aff 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,18 +6,20 @@
 
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/base64.h"
 #include "base/crypto/signature_verifier.h"
 #include "base/file_util.h"
 #include "base/file_util_proxy.h"
 #include "base/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/path_service.h"
 #include "base/scoped_handle.h"
 #include "base/task.h"
 #include "base/utf_string_conversions.h"  // TODO(viettrungluu): delete me.
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
@@ -25,35 +27,54 @@
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/extension_unpacker.h"
 #include "chrome/common/json_value_serializer.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
 
 const char SandboxedExtensionUnpacker::kExtensionHeaderMagic[] = "Cr24";
 
 SandboxedExtensionUnpacker::SandboxedExtensionUnpacker(
     const FilePath& crx_path,
-    const FilePath& temp_path,
     ResourceDispatcherHost* rdh,
     SandboxedExtensionUnpackerClient* client)
-    : crx_path_(crx_path), temp_path_(temp_path),
+    : crx_path_(crx_path),
       thread_identifier_(BrowserThread::ID_COUNT),
       rdh_(rdh), client_(client), got_response_(false) {
 }
 
+bool SandboxedExtensionUnpacker::CreateTempDirectory() {
+  CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_));
+
+  FilePath user_data_temp_dir = extension_file_util::GetUserDataTempDir();
+  if (user_data_temp_dir.empty()) {
+    ReportFailure(
+        COULD_NOT_GET_TEMP_DIRECTORY,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY")));
+    return false;
+  }
+
+  if (!temp_dir_.CreateUniqueTempDirUnderPath(user_data_temp_dir)) {
+    ReportFailure(
+        COULD_NOT_CREATE_TEMP_DIRECTORY,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY")));
+    return false;
+  }
+
+  return true;
+}
+
 void SandboxedExtensionUnpacker::Start() {
   // We assume that we are started on the thread that the client wants us to do
   // file IO on.
   CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_));
 
-  // Create a temporary directory to work in.
-  if (!temp_dir_.CreateUniqueTempDirUnderPath(temp_path_)) {
-    // Could not create temporary directory.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY")));
-    return;
-  }
+  if (!CreateTempDirectory())
+    return;  // ReportFailure() already called.
 
   // Initialize the path that will eventually contain the unpacked extension.
   extension_root_ = temp_dir_.path().AppendASCII(
@@ -67,9 +88,11 @@
   FilePath temp_crx_path = temp_dir_.path().Append(crx_path_.BaseName());
   if (!file_util::CopyFile(crx_path_, temp_crx_path)) {
     // Failed to copy extension file to temporary directory.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY")));
+    ReportFailure(
+        FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY")));
     return;
   }
 
@@ -89,7 +112,9 @@
     if (!file_util::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) {
       LOG(ERROR) << "Could not get the normalized path of "
                  << temp_crx_path.value();
-      ReportFailure(l10n_util::GetStringUTF8(IDS_EXTENSION_UNPACK_FAILED));
+      ReportFailure(
+          COULD_NOT_GET_SANDBOX_FRIENDLY_PATH,
+          l10n_util::GetStringUTF8(IDS_EXTENSION_UNPACK_FAILED));
       return;
     }
 
@@ -130,7 +155,7 @@
     const DictionaryValue& manifest) {
   // Skip check for unittests.
   if (thread_identifier_ != BrowserThread::ID_COUNT)
-    DCHECK(BrowserThread::CurrentlyOn(thread_identifier_));
+    CHECK(BrowserThread::CurrentlyOn(thread_identifier_));
   got_response_ = true;
 
   scoped_ptr<DictionaryValue> final_manifest(RewriteManifestFile(manifest));
@@ -147,9 +172,11 @@
   if (!extension_l10n_util::LocalizeExtension(extension_root_,
                                               final_manifest.get(),
                                               &error)) {
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_MESSAGE,
-        ASCIIToUTF16(error)));
+    ReportFailure(
+        COULD_NOT_LOCALIZE_EXTENSION,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_MESSAGE,
+            ASCIIToUTF16(error)));
     return;
   }
 
@@ -157,7 +184,9 @@
       extension_root_, Extension::INTERNAL, *final_manifest, true, &error);
 
   if (!extension_.get()) {
-    ReportFailure(std::string("Manifest is invalid: ") + error);
+    ReportFailure(
+        INVALID_MANIFEST,
+        std::string("Manifest is invalid: ") + error);
     return;
   }
 
@@ -172,11 +201,13 @@
 
 void SandboxedExtensionUnpacker::OnUnpackExtensionFailed(
     const std::string& error) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_identifier_));
+  CHECK(BrowserThread::CurrentlyOn(thread_identifier_));
   got_response_ = true;
-  ReportFailure(l10n_util::GetStringFUTF8(
-      IDS_EXTENSION_PACKAGE_ERROR_MESSAGE,
-      ASCIIToUTF16(error)));
+  ReportFailure(
+      UNPACKER_CLIENT_FAILED,
+      l10n_util::GetStringFUTF8(
+           IDS_EXTENSION_PACKAGE_ERROR_MESSAGE,
+           ASCIIToUTF16(error)));
 }
 
 void SandboxedExtensionUnpacker::OnProcessCrashed(int exit_code) {
@@ -185,18 +216,22 @@
     return;
 
   // Utility process crashed while trying to install.
-  ReportFailure(l10n_util::GetStringFUTF8(
-      IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-      ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")));
+  ReportFailure(
+     UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
+     l10n_util::GetStringFUTF8(
+         IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+         ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")));
 }
 
 bool SandboxedExtensionUnpacker::ValidateSignature() {
   ScopedStdioHandle file(file_util::OpenFile(crx_path_, "rb"));
   if (!file.get()) {
     // Could not open crx file for reading
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_FILE_NOT_READABLE")));
+    ReportFailure(
+        CRX_FILE_NOT_READABLE,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_FILE_NOT_READABLE")));
     return false;
   }
 
@@ -212,46 +247,57 @@
       file.get());
   if (len < sizeof(ExtensionHeader)) {
     // Invalid crx header
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_HEADER_INVALID")));
+    ReportFailure(
+        CRX_HEADER_INVALID,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_HEADER_INVALID")));
     return false;
   }
   if (strncmp(kExtensionHeaderMagic, header.magic,
       sizeof(header.magic))) {
     // Bad magic number
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID")));
+    ReportFailure(
+        CRX_MAGIC_NUMBER_INVALID,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID")));
     return false;
   }
   if (header.version != kCurrentVersion) {
     // Bad version numer
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID")));
+    ReportFailure(CRX_VERSION_NUMBER_INVALID,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID")));
     return false;
   }
   if (header.key_size > kMaxPublicKeySize ||
       header.signature_size > kMaxSignatureSize) {
     // Excessively large key or signature
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE")));
+    ReportFailure(
+        CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE")));
     return false;
   }
   if (header.key_size == 0) {
     // Key length is zero
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_ZERO_KEY_LENGTH")));
+    ReportFailure(
+        CRX_ZERO_KEY_LENGTH,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_ZERO_KEY_LENGTH")));
     return false;
   }
   if (header.signature_size == 0) {
     // Signature length is zero
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH")));
+    ReportFailure(
+        CRX_ZERO_SIGNATURE_LENGTH,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH")));
     return false;
   }
 
@@ -260,9 +306,11 @@
   len = fread(&key.front(), sizeof(uint8), header.key_size, file.get());
   if (len < header.key_size) {
     // Invalid public key
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID")));
+    ReportFailure(
+        CRX_PUBLIC_KEY_INVALID,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID")));
     return false;
   }
 
@@ -272,9 +320,11 @@
       file.get());
   if (len < header.signature_size) {
     // Invalid signature
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_SIGNATURE_INVALID")));
+    ReportFailure(
+        CRX_SIGNATURE_INVALID,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_SIGNATURE_INVALID")));
     return false;
   }
 
@@ -287,9 +337,11 @@
                            key.size())) {
     // Signature verification initialization failed. This is most likely
     // caused by a public key in the wrong format (should encode algorithm).
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED")));
+    ReportFailure(
+        CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED")));
     return false;
   }
 
@@ -299,9 +351,11 @@
 
   if (!verifier.VerifyFinal()) {
     // Signature verification failed
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_ERROR_CODE,
-        ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED")));
+    ReportFailure(
+        CRX_SIGNATURE_VERIFICATION_FAILED,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_ERROR_CODE,
+            ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED")));
     return false;
   }
 
@@ -310,11 +364,18 @@
   return true;
 }
 
-void SandboxedExtensionUnpacker::ReportFailure(const std::string& error) {
+void SandboxedExtensionUnpacker::ReportFailure(FailureReason reason,
+                                               const std::string& error) {
+  UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackFailure", 1);
+  UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason",
+                            reason, NUM_FAILURE_REASONS);
+
   client_->OnUnpackFailure(error);
 }
 
 void SandboxedExtensionUnpacker::ReportSuccess() {
+  UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1);
+
   // Client takes ownership of temporary directory and extension.
   client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_, extension_);
   extension_ = NULL;
@@ -325,8 +386,7 @@
   // Add the public key extracted earlier to the parsed manifest and overwrite
   // the original manifest. We do this to ensure the manifest doesn't contain an
   // exploitable bug that could be used to compromise the browser.
-  scoped_ptr<DictionaryValue> final_manifest(
-      static_cast<DictionaryValue*>(manifest.DeepCopy()));
+  scoped_ptr<DictionaryValue> final_manifest(manifest.DeepCopy());
   final_manifest->SetString(extension_manifest_keys::kPublicKey, public_key_);
 
   std::string manifest_json;
@@ -334,9 +394,11 @@
   serializer.set_pretty_print(true);
   if (!serializer.Serialize(*final_manifest)) {
     // Error serializing manifest.json.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON")));
+    ReportFailure(
+        ERROR_SERIALIZING_MANIFEST_JSON,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON")));
     return NULL;
   }
 
@@ -345,9 +407,11 @@
   if (!file_util::WriteFile(manifest_path,
                             manifest_json.data(), manifest_json.size())) {
     // Error saving manifest.json.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON")));
+    ReportFailure(
+        ERROR_SAVING_MANIFEST_JSON,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON")));
     return NULL;
   }
 
@@ -358,9 +422,11 @@
   ExtensionUnpacker::DecodedImages images;
   if (!ExtensionUnpacker::ReadImagesFromFile(temp_dir_.path(), &images)) {
     // Couldn't read image data from disk.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK")));
+    ReportFailure(
+        COULD_NOT_READ_IMAGE_DATA_FROM_DISK,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK")));
     return false;
   }
 
@@ -370,9 +436,11 @@
   std::set<FilePath> image_paths = extension_->GetBrowserImages();
   if (image_paths.size() != images.size()) {
     // Decoded images don't match what's in the manifest.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST")));
+    ReportFailure(
+        DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST")));
     return false;
   }
 
@@ -381,16 +449,20 @@
     FilePath path = *it;
     if (path.IsAbsolute() || path.ReferencesParent()) {
       // Invalid path for browser image.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
+      ReportFailure(
+          INVALID_PATH_FOR_BROWSER_IMAGE,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
       return false;
     }
     if (!file_util::Delete(extension_root_.Append(path), false)) {
       // Error removing old image file.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE")));
+      ReportFailure(
+          ERROR_REMOVING_OLD_IMAGE_FILE,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE")));
       return false;
     }
   }
@@ -401,9 +473,11 @@
     FilePath path_suffix = images[i].b;
     if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) {
       // Invalid path for bitmap image.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE")));
+      ReportFailure(
+          INVALID_PATH_FOR_BITMAP_IMAGE,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE")));
       return false;
     }
     FilePath path = extension_root_.Append(path_suffix);
@@ -414,9 +488,11 @@
     // http://code.google.com/p/chromium/issues/detail?id=12459
     if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) {
       // Error re-encoding theme image.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE")));
+      ReportFailure(
+          ERROR_RE_ENCODING_THEME_IMAGE,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE")));
       return false;
     }
 
@@ -425,9 +501,11 @@
     const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
     if (!file_util::WriteFile(path, image_data_ptr, image_data.size())) {
       // Error saving theme image.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE")));
+      ReportFailure(
+          ERROR_SAVING_THEME_IMAGE,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE")));
       return false;
     }
   }
@@ -440,9 +518,11 @@
   if (!ExtensionUnpacker::ReadMessageCatalogsFromFile(temp_dir_.path(),
                                                       &catalogs)) {
     // Could not read catalog data from disk.
-    ReportFailure(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-        ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK")));
+    ReportFailure(
+        COULD_NOT_READ_CATALOG_DATA_FROM_DISK,
+        l10n_util::GetStringFUTF8(
+            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+            ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK")));
     return false;
   }
 
@@ -452,9 +532,11 @@
     DictionaryValue* catalog;
     if (!catalogs.GetDictionaryWithoutPathExpansion(*key_it, &catalog)) {
       // Invalid catalog data.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("INVALID_CATALOG_DATA")));
+      ReportFailure(
+          INVALID_CATALOG_DATA,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("INVALID_CATALOG_DATA")));
       return false;
     }
 
@@ -464,9 +546,11 @@
     relative_path = relative_path.Append(Extension::kMessagesFilename);
     if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) {
       // Invalid path for catalog.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("INVALID_PATH_FOR_CATALOG")));
+      ReportFailure(
+          INVALID_PATH_FOR_CATALOG,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("INVALID_PATH_FOR_CATALOG")));
       return false;
     }
     FilePath path = extension_root_.Append(relative_path);
@@ -476,9 +560,11 @@
     serializer.set_pretty_print(true);
     if (!serializer.Serialize(*catalog)) {
       // Error serializing catalog.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("ERROR_SERIALIZING_CATALOG")));
+      ReportFailure(
+          ERROR_SERIALIZING_CATALOG,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("ERROR_SERIALIZING_CATALOG")));
       return false;
     }
 
@@ -488,9 +574,11 @@
                               catalog_json.c_str(),
                               catalog_json.size())) {
       // Error saving catalog.
-      ReportFailure(l10n_util::GetStringFUTF8(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("ERROR_SAVING_CATALOG")));
+      ReportFailure(
+          ERROR_SAVING_CATALOG,
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("ERROR_SAVING_CATALOG")));
       return false;
     }
   }
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.h b/chrome/browser/extensions/sandboxed_extension_unpacker.h
index e47b26c..ee78a8e 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.h
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -93,7 +93,6 @@
   // |client| with the result. If |rdh| is provided, unpacking is done in a
   // sandboxed subprocess. Otherwise, it is done in-process.
   SandboxedExtensionUnpacker(const FilePath& crx_path,
-                             const FilePath& temp_path,
                              ResourceDispatcherHost* rdh,
                              SandboxedExtensionUnpackerClient* cilent);
 
@@ -102,11 +101,74 @@
 
  private:
   class ProcessHostClient;
+
+  // Enumerate all the ways unpacking can fail.  Calls to ReportFailure()
+  // take a failure reason as an argument, and put it in histogram
+  // Extensions.SandboxUnpackFailureReason.
+  enum FailureReason {
+    // SandboxedExtensionUnpacker::CreateTempDirectory()
+    COULD_NOT_GET_TEMP_DIRECTORY,
+    COULD_NOT_CREATE_TEMP_DIRECTORY,
+
+    // SandboxedExtensionUnpacker::Start()
+    FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY,
+    COULD_NOT_GET_SANDBOX_FRIENDLY_PATH,
+
+    // SandboxedExtensionUnpacker::OnUnpackExtensionSucceeded()
+    COULD_NOT_LOCALIZE_EXTENSION,
+    INVALID_MANIFEST,
+
+    //SandboxedExtensionUnpacker::OnUnpackExtensionFailed()
+    UNPACKER_CLIENT_FAILED,
+
+    // SandboxedExtensionUnpacker::OnProcessCrashed()
+    UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
+
+    // SandboxedExtensionUnpacker::ValidateSignature()
+    CRX_FILE_NOT_READABLE,
+    CRX_HEADER_INVALID,
+    CRX_MAGIC_NUMBER_INVALID,
+    CRX_VERSION_NUMBER_INVALID,
+    CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE,
+    CRX_ZERO_KEY_LENGTH,
+    CRX_ZERO_SIGNATURE_LENGTH,
+    CRX_PUBLIC_KEY_INVALID,
+    CRX_SIGNATURE_INVALID,
+    CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED,
+    CRX_SIGNATURE_VERIFICATION_FAILED,
+
+    // SandboxedExtensionUnpacker::RewriteManifestFile()
+    ERROR_SERIALIZING_MANIFEST_JSON,
+    ERROR_SAVING_MANIFEST_JSON,
+
+    // SandboxedExtensionUnpacker::RewriteImageFiles()
+    COULD_NOT_READ_IMAGE_DATA_FROM_DISK,
+    DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST,
+    INVALID_PATH_FOR_BROWSER_IMAGE,
+    ERROR_REMOVING_OLD_IMAGE_FILE,
+    INVALID_PATH_FOR_BITMAP_IMAGE,
+    ERROR_RE_ENCODING_THEME_IMAGE,
+    ERROR_SAVING_THEME_IMAGE,
+
+    // SandboxedExtensionUnpacker::RewriteCatalogFiles()
+    COULD_NOT_READ_CATALOG_DATA_FROM_DISK,
+    INVALID_CATALOG_DATA,
+    INVALID_PATH_FOR_CATALOG,
+    ERROR_SERIALIZING_CATALOG,
+    ERROR_SAVING_CATALOG,
+
+    NUM_FAILURE_REASONS
+  };
+
   friend class ProcessHostClient;
   friend class SandboxedExtensionUnpackerTest;
 
   virtual ~SandboxedExtensionUnpacker();
 
+  // Set |temp_dir_| as a temporary directory to unpack the extension in.
+  // Return true on success.
+  virtual bool CreateTempDirectory();
+
   // Validates the signature of the extension and extract the key to
   // |public_key_|. Returns true if the signature validates, false otherwise.
   //
@@ -126,7 +188,7 @@
   virtual void OnUnpackExtensionFailed(const std::string& error_message);
   virtual void OnProcessCrashed(int exit_code);
 
-  void ReportFailure(const std::string& message);
+  void ReportFailure(FailureReason reason, const std::string& message);
   void ReportSuccess();
 
   // Overwrites original manifest with safe result from utility process.
@@ -141,9 +203,6 @@
   // The path to the CRX to unpack.
   FilePath crx_path_;
 
-  // A path to a temp dir to unpack in.
-  FilePath temp_path_;
-
   // Our client's thread. This is the thread we respond on.
   BrowserThread::ID thread_identifier_;
 
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker_unittest.cc b/chrome/browser/extensions/sandboxed_extension_unpacker_unittest.cc
index 19cd379..ecc521c 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker_unittest.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,12 +22,16 @@
 using testing::_;
 using testing::Invoke;
 
+namespace {
+
 void OnUnpackSuccess(const FilePath& temp_dir,
                      const FilePath& extension_root,
                      const Extension* extension) {
   // Don't delete temp_dir here, we need to do some post op checking.
 }
 
+}  // namespace
+
 class MockSandboxedExtensionUnpackerClient
     : public SandboxedExtensionUnpackerClient {
  public:
@@ -78,7 +82,7 @@
     // a temp folder to play in.
     ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &install_dir_));
     install_dir_ =
-      install_dir_.AppendASCII("sandboxed_extension_unpacker_test");
+        install_dir_.AppendASCII("sandboxed_extension_unpacker_test");
     file_util::Delete(install_dir_, true);
     file_util::CreateDirectory(install_dir_);
 
@@ -89,27 +93,29 @@
 
     unpacker_.reset(new ExtensionUnpacker(crx_path));
 
-
     // Build a temp area where the extension will be unpacked.
     ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &temp_dir_));
     temp_dir_ = temp_dir_.AppendASCII("sandboxed_extension_unpacker_test_Temp");
-    file_util::CreateDirectory(temp_dir_);
+    ASSERT_TRUE(file_util::CreateDirectory(temp_dir_));
 
     sandboxed_unpacker_ =
-      new SandboxedExtensionUnpacker(crx_path, temp_dir_, NULL, client_);
+        new SandboxedExtensionUnpacker(crx_path, NULL, client_);
+
     // Hack since SandboxedExtensionUnpacker gets its background thread id from
     // the Start call, but we don't call it here.
     sandboxed_unpacker_->thread_identifier_ = BrowserThread::FILE;
-    PrepareUnpackerEnv();
+    EXPECT_TRUE(PrepareUnpackerEnv());
   }
 
-  void PrepareUnpackerEnv() {
+  bool PrepareUnpackerEnv() {
     sandboxed_unpacker_->extension_root_ =
       install_dir_.AppendASCII(extension_filenames::kTempExtensionName);
 
-    sandboxed_unpacker_->temp_dir_.Set(install_dir_);
+    if (!sandboxed_unpacker_->temp_dir_.Set(install_dir_))
+      return false;
     sandboxed_unpacker_->public_key_ =
       "ocnapchkplbmjmpfehjocmjnipfmogkh";
+    return true;
   }
 
   void OnUnpackSucceeded() {
@@ -157,6 +163,7 @@
 
 TEST_F(SandboxedExtensionUnpackerTest, NoCatalogsSuccess) {
   EXPECT_CALL(*client_, OnUnpackSuccess(_, _, _));
+  EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(0);
 
   SetupUnpacker("no_l10n.crx");
   ASSERT_TRUE(unpacker_->Run());
@@ -178,6 +185,7 @@
 
 TEST_F(SandboxedExtensionUnpackerTest, WithCatalogsSuccess) {
   EXPECT_CALL(*client_, OnUnpackSuccess(_, _, _));
+  EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(0);
 
   SetupUnpacker("good_l10n.crx");
   ASSERT_TRUE(unpacker_->Run());
diff --git a/chrome/browser/extensions/stateful_external_extension_provider.cc b/chrome/browser/extensions/stateful_external_extension_provider.cc
deleted file mode 100644
index fd1a42a..0000000
--- a/chrome/browser/extensions/stateful_external_extension_provider.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-
-#include "app/app_paths.h"
-#include "base/file_path.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/values.h"
-#include "base/version.h"
-#include "chrome/browser/browser_thread.h"
-
-namespace {
-
-// Constants for keeping track of extension preferences.
-const char kLocation[] = "location";
-const char kState[] = "state";
-const char kExternalCrx[] = "external_crx";
-const char kExternalVersion[] = "external_version";
-const char kExternalUpdateUrl[] = "external_update_url";
-
-}
-
-StatefulExternalExtensionProvider::StatefulExternalExtensionProvider(
-    Extension::Location crx_location,
-    Extension::Location download_location)
-  : crx_location_(crx_location),
-    download_location_(download_location) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-StatefulExternalExtensionProvider::~StatefulExternalExtensionProvider() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void StatefulExternalExtensionProvider::VisitRegisteredExtension(
-    Visitor* visitor) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  DCHECK(prefs_.get());
-  for (DictionaryValue::key_iterator i = prefs_->begin_keys();
-       i != prefs_->end_keys(); ++i) {
-    const std::string& extension_id = *i;
-    DictionaryValue* extension;
-    if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension))
-      continue;
-
-    FilePath::StringType external_crx;
-    std::string external_version;
-    std::string external_update_url;
-
-    bool has_external_crx = extension->GetString(kExternalCrx, &external_crx);
-    bool has_external_version = extension->GetString(kExternalVersion,
-                                                     &external_version);
-    bool has_external_update_url = extension->GetString(kExternalUpdateUrl,
-                                                        &external_update_url);
-    if (has_external_crx != has_external_version) {
-      LOG(WARNING) << "Malformed extension dictionary for extension: "
-                   << extension_id.c_str() << ".  " << kExternalCrx
-                   << " and " << kExternalVersion << " must be used together.";
-      continue;
-    }
-
-    if (has_external_crx == has_external_update_url) {
-      LOG(WARNING) << "Malformed extension dictionary for extension: "
-                   << extension_id.c_str() << ".  Exactly one of the "
-                   << "followng keys should be used: " << kExternalCrx
-                   << ", " << kExternalUpdateUrl << ".";
-      continue;
-    }
-
-    if (has_external_crx) {
-      if (crx_location_ == Extension::INVALID) {
-        LOG(WARNING) << "This provider does not support installing external "
-                     << "extensions from crx files.";
-        continue;
-      }
-      if (external_crx.find(FilePath::kParentDirectory) !=
-          base::StringPiece::npos) {
-        LOG(WARNING) << "Path traversal not allowed in path: "
-                     << external_crx.c_str();
-        continue;
-      }
-
-      // If the path is relative, make it absolute.
-      FilePath path(external_crx);
-      if (!path.IsAbsolute()) {
-        // Try path as relative path from external extension dir.
-        FilePath base_path;
-        PathService::Get(app::DIR_EXTERNAL_EXTENSIONS, &base_path);
-        path = base_path.Append(external_crx);
-      }
-
-      scoped_ptr<Version> version;
-      version.reset(Version::GetVersionFromString(external_version));
-      if (!version.get()) {
-        LOG(WARNING) << "Malformed extension dictionary for extension: "
-                     << extension_id.c_str() << ".  Invalid version string \""
-                     << external_version << "\".";
-        continue;
-      }
-      visitor->OnExternalExtensionFileFound(extension_id, version.get(), path,
-                                            crx_location_);
-    } else { // if (has_external_update_url)
-      DCHECK(has_external_update_url);  // Checking of keys above ensures this.
-      if (download_location_ == Extension::INVALID) {
-        LOG(WARNING) << "This provider does not support installing external "
-                     << "extensions from update URLs.";
-        continue;
-      }
-      GURL update_url(external_update_url);
-      if (!update_url.is_valid()) {
-        LOG(WARNING) << "Malformed extension dictionary for extension: "
-                     << extension_id.c_str() << ".  " << kExternalUpdateUrl
-                     << " must be a valid URL.  Saw \"" << external_update_url
-                     << "\".";
-        continue;
-      }
-      visitor->OnExternalExtensionUpdateUrlFound(
-          extension_id, update_url, download_location_);
-    }
-  }
-}
-
-bool StatefulExternalExtensionProvider::HasExtension(
-    const std::string& id) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  DCHECK(prefs_.get());
-  return prefs_->HasKey(id);
-}
-
-bool StatefulExternalExtensionProvider::GetExtensionDetails(
-    const std::string& id, Extension::Location* location,
-    scoped_ptr<Version>* version) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  DCHECK(prefs_.get());
-  DictionaryValue* extension = NULL;
-  if (!prefs_->GetDictionary(id, &extension))
-    return false;
-
-  Extension::Location loc = Extension::INVALID;
-  if (extension->HasKey(kExternalUpdateUrl)) {
-    loc = download_location_;
-
-  } else if (extension->HasKey(kExternalCrx)) {
-    loc = crx_location_;
-
-    std::string external_version;
-    if (!extension->GetString(kExternalVersion, &external_version))
-      return false;
-
-    if (version)
-      version->reset(Version::GetVersionFromString(external_version));
-
-  } else {
-    NOTREACHED();  // Chrome should not allow prefs to get into this state.
-    return false;
-  }
-
-  if (location)
-    *location = loc;
-
-  return true;
-}
-
-void StatefulExternalExtensionProvider::set_prefs(DictionaryValue* prefs) {
-  prefs_.reset(prefs);
-}
diff --git a/chrome/browser/extensions/stateful_external_extension_provider.h b/chrome/browser/extensions/stateful_external_extension_provider.h
deleted file mode 100644
index 2fd481c..0000000
--- a/chrome/browser/extensions/stateful_external_extension_provider.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_STATEFUL_EXTERNAL_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_STATEFUL_EXTERNAL_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/browser/extensions/external_extension_provider.h"
-
-class DictionaryValue;
-class ValueSerializer;
-class Version;
-
-// A specialization of the ExternalExtensionProvider that stores the registered
-// external extensions in a dictionary. This dictionary (|prefs_|) will be used
-// by HasExtension() and GetExtensionDetails() to return information about the
-// stored external extensions. It is the responsibility of specialized
-// subclasses to initialize this internal dictionary.
-// This provider can provide external extensions from two sources: crx files
-// and udpate URLs. The locations that the provider will report for these
-// are specified at the constructor.
-// Instances of this class are expected to be created and destroyed on the UI
-// thread and they are expecting public method calls from the FILE thread.
-class StatefulExternalExtensionProvider : public ExternalExtensionProvider {
- public:
-  // Initialize the location for external extensions originating from crx
-  // files: |crx_location|, and originating from update URLs:
-  // |download_location|. If either of the origins is not supported by this
-  // provider, then it should be initialized as Extensions::INVALID.
-  StatefulExternalExtensionProvider(
-      Extension::Location crx_location,
-      Extension::Location download_location);
-  virtual ~StatefulExternalExtensionProvider();
-
-  // ExternalExtensionProvider implementation:
-  virtual void VisitRegisteredExtension(Visitor* visitor) const;
-
-  virtual bool HasExtension(const std::string& id) const;
-
-  virtual bool GetExtensionDetails(const std::string& id,
-                                   Extension::Location* location,
-                                   scoped_ptr<Version>* version) const;
- protected:
-  // Location for external extensions that are provided by this provider from
-  // local crx files.
-  const Extension::Location crx_location_;
-  // Location for external extensions that are provided by this provider from
-  // update URLs.
-  const Extension::Location download_location_;
-
-  // Stores the dictionary of external extensions internally. Takes ownership
-  // of |prefs|.
-  void set_prefs(DictionaryValue* prefs);
-
- private:
-  // Dictionary of the external extensions that are provided by this provider.
-  scoped_ptr<DictionaryValue> prefs_;
-};
-
-#endif  // CHROME_BROWSER_EXTENSIONS_STATEFUL_EXTERNAL_EXTENSION_PROVIDER_H_
diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc
index 5b0ee7b..c88fffb 100644
--- a/chrome/browser/extensions/test_extension_prefs.cc
+++ b/chrome/browser/extensions/test_extension_prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/extensions/extension_pref_store.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/pref_service_mock_builder.h"
@@ -28,9 +29,9 @@
 class MockExtensionPrefs : public ExtensionPrefs {
  public:
   MockExtensionPrefs(PrefService* prefs,
-                     const FilePath& root_dir_,
-                     ExtensionPrefStore* pref_store)
-    : ExtensionPrefs(prefs, root_dir_, pref_store),
+                     const FilePath& root_dir,
+                     ExtensionPrefValueMap* extension_pref_value_map)
+    : ExtensionPrefs(prefs, root_dir, extension_pref_value_map),
       currentTime(base::Time::Now()) {}
   ~MockExtensionPrefs() {}
 
@@ -70,14 +71,17 @@
     file_loop.RunAllPending();
   }
 
-  ExtensionPrefStore* pref_store = new ExtensionPrefStore;
+  extension_pref_value_map_.reset(new ExtensionPrefValueMap);
   PrefServiceMockBuilder builder;
   builder.WithUserFilePrefs(preferences_file_);
-  builder.WithExtensionPrefs(pref_store);
+  builder.WithExtensionPrefs(
+      new ExtensionPrefStore(extension_pref_value_map_.get(), false));
   pref_service_.reset(builder.Create());
   ExtensionPrefs::RegisterUserPrefs(pref_service_.get());
-  prefs_.reset(new MockExtensionPrefs(pref_service_.get(), temp_dir_.path(),
-                                      pref_store));
+
+  prefs_.reset(new MockExtensionPrefs(pref_service_.get(),
+                                      temp_dir_.path(),
+                                      extension_pref_value_map_.get()));
 }
 
 scoped_refptr<Extension> TestExtensionPrefs::AddExtension(std::string name) {
@@ -110,3 +114,8 @@
   scoped_refptr<Extension> extension(AddExtension(name));
   return extension->id();
 }
+
+PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const {
+  return pref_service_->CreateIncognitoPrefService(
+      new ExtensionPrefStore(extension_pref_value_map_.get(), true));
+}
diff --git a/chrome/browser/extensions/test_extension_prefs.h b/chrome/browser/extensions/test_extension_prefs.h
index 3220d7a..1fa2351 100644
--- a/chrome/browser/extensions/test_extension_prefs.h
+++ b/chrome/browser/extensions/test_extension_prefs.h
@@ -14,6 +14,7 @@
 
 class DictionaryValue;
 class ExtensionPrefs;
+class ExtensionPrefValueMap;
 class PrefService;
 
 // This is a test class intended to make it easier to work with ExtensionPrefs
@@ -44,12 +45,15 @@
   // assigned.
   std::string AddExtensionAndReturnId(std::string name);
 
+  PrefService* CreateIncognitoPrefService() const;
+
  protected:
   ScopedTempDir temp_dir_;
   FilePath preferences_file_;
   FilePath extensions_dir_;
   scoped_ptr<PrefService> pref_service_;
   scoped_ptr<ExtensionPrefs> prefs_;
+  scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TestExtensionPrefs);
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.cc b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
index 5f47084..308516c 100644
--- a/chrome/browser/extensions/theme_installed_infobar_delegate.cc
+++ b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -17,6 +15,8 @@
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 ThemeInstalledInfoBarDelegate::ThemeInstalledInfoBarDelegate(
     TabContents* tab_contents,
@@ -33,6 +33,10 @@
                  NotificationService::AllSources());
 }
 
+bool ThemeInstalledInfoBarDelegate::MatchesTheme(const Extension* theme) const {
+  return theme && (theme->id() == theme_id_);
+}
+
 ThemeInstalledInfoBarDelegate::~ThemeInstalledInfoBarDelegate() {
   // We don't want any notifications while we're running our destructor.
   registrar_.RemoveAll();
@@ -40,39 +44,6 @@
   profile_->GetThemeProvider()->OnInfobarDestroyed();
 }
 
-void ThemeInstalledInfoBarDelegate::InfoBarClosed() {
-  delete this;
-}
-
-string16 ThemeInstalledInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringFUTF16(IDS_THEME_INSTALL_INFOBAR_LABEL,
-                                    UTF8ToUTF16(name_));
-}
-
-SkBitmap* ThemeInstalledInfoBarDelegate::GetIcon() const {
-  // TODO(aa): Reply with the theme's icon, but this requires reading it
-  // asynchronously from disk.
-  return ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_INFOBAR_THEME);
-}
-
-ThemeInstalledInfoBarDelegate*
-    ThemeInstalledInfoBarDelegate::AsThemePreviewInfobarDelegate() {
-  return this;
-}
-
-int ThemeInstalledInfoBarDelegate::GetButtons() const {
-  return BUTTON_CANCEL;
-}
-
-string16 ThemeInstalledInfoBarDelegate::GetButtonLabel(
-    ConfirmInfoBarDelegate::InfoBarButton button) const {
-  // The InfoBar will create a default OK button and make it invisible.
-  // TODO(mirandac): remove the default OK button from ConfirmInfoBar.
-  return (button == BUTTON_CANCEL) ?
-      l10n_util::GetStringUTF16(IDS_THEME_INSTALL_INFOBAR_UNDO_BUTTON) :
-      string16();
-}
-
 bool ThemeInstalledInfoBarDelegate::Cancel() {
   if (!previous_theme_id_.empty()) {
     ExtensionService* service = profile_->GetExtensionService();
@@ -90,6 +61,36 @@
   return true;
 }
 
+void ThemeInstalledInfoBarDelegate::InfoBarClosed() {
+  delete this;
+}
+
+SkBitmap* ThemeInstalledInfoBarDelegate::GetIcon() const {
+  // TODO(aa): Reply with the theme's icon, but this requires reading it
+  // asynchronously from disk.
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_INFOBAR_THEME);
+}
+
+ThemeInstalledInfoBarDelegate*
+    ThemeInstalledInfoBarDelegate::AsThemePreviewInfobarDelegate() {
+  return this;
+}
+
+string16 ThemeInstalledInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_THEME_INSTALL_INFOBAR_LABEL,
+                                    UTF8ToUTF16(name_));
+}
+
+int ThemeInstalledInfoBarDelegate::GetButtons() const {
+  return BUTTON_CANCEL;
+}
+
+string16 ThemeInstalledInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_CANCEL, button);
+  return l10n_util::GetStringUTF16(IDS_THEME_INSTALL_INFOBAR_UNDO_BUTTON);
+}
+
 void ThemeInstalledInfoBarDelegate::Observe(
     NotificationType type,
     const NotificationSource& source,
@@ -115,7 +116,3 @@
     }
   }
 }
-
-bool ThemeInstalledInfoBarDelegate::MatchesTheme(const Extension* theme) {
-  return (theme && theme->id() == theme_id_);
-}
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.h b/chrome/browser/extensions/theme_installed_infobar_delegate.h
index b1ed99e..c565a33 100644
--- a/chrome/browser/extensions/theme_installed_infobar_delegate.h
+++ b/chrome/browser/extensions/theme_installed_infobar_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -21,28 +21,33 @@
   ThemeInstalledInfoBarDelegate(TabContents* tab_contents,
                                 const Extension* new_theme,
                                 const std::string& previous_theme_id);
-  virtual ~ThemeInstalledInfoBarDelegate();
-  virtual void InfoBarClosed();
-  virtual string16 GetMessageText() const;
-  virtual SkBitmap* GetIcon() const;
-  virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
-  virtual int GetButtons() const;
-  virtual string16 GetButtonLabel(
-      ConfirmInfoBarDelegate::InfoBarButton button) const;
-  virtual bool Cancel();
 
   // Returns true if the given theme is the same as the one associated with this
   // info bar.
-  bool MatchesTheme(const Extension* theme);
+  bool MatchesTheme(const Extension* theme) const;
 
-  // NotificationObserver implementation.
+ protected:
+  virtual ~ThemeInstalledInfoBarDelegate();
+
+  Profile* profile() { return profile_; }
+
+  // ConfirmInfoBarDelegate:
+  virtual bool Cancel();
+
+ private:
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+
+  // NotificationObserver:
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details);
- protected:
-  Profile* profile() { return profile_; }
 
- private:
   Profile* profile_;
 
   // Name of theme that's just been installed.
diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc
index fe735ae..220cd06 100644
--- a/chrome/browser/extensions/user_script_listener_unittest.cc
+++ b/chrome/browser/extensions/user_script_listener_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
 #include "chrome/common/notification_type.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_job.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class Profile;
@@ -73,7 +73,7 @@
   }
 
   virtual bool OnResponseCompleted(int request_id,
-                                   const URLRequestStatus& status,
+                                   const net::URLRequestStatus& status,
                                    const std::string& security_info) {
     NOTREACHED();
     return true;
@@ -95,10 +95,10 @@
 
 // A simple test net::URLRequestJob. We don't care what it does, only that
 // whether it starts and finishes.
-class SimpleTestJob : public URLRequestTestJob {
+class SimpleTestJob : public net::URLRequestTestJob {
  public:
   explicit SimpleTestJob(net::URLRequest* request)
-    : URLRequestTestJob(request, test_headers(), kTestData, true) {}
+    : net::URLRequestTestJob(request, test_headers(), kTestData, true) {}
  private:
   ~SimpleTestJob() {}
 };
diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc
index 820ab5a..317a2d5 100644
--- a/chrome/browser/extensions/user_script_master.cc
+++ b/chrome/browser/extensions/user_script_master.cc
@@ -236,6 +236,9 @@
   pickle.WriteSize(scripts.size());
   for (size_t i = 0; i < scripts.size(); i++) {
     const UserScript& script = scripts[i];
+    // TODO(aa): This can be replaced by sending content script metadata to
+    // renderers along with other extension data in ViewMsg_ExtensionLoaded.
+    // See crbug.com/70516.
     script.Pickle(&pickle);
     // Write scripts as 'data' so that we can read it out in the slave without
     // allocating a new string.
diff --git a/chrome/browser/external_protocol_handler.cc b/chrome/browser/external_protocol_handler.cc
index e9b4326..d2994c3 100644
--- a/chrome/browser/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol_handler.cc
@@ -4,18 +4,16 @@
 
 #include "chrome/browser/external_protocol_handler.h"
 
-#include "build/build_config.h"
-
 #include <set>
 
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/threading/thread.h"
+#include "build/build_config.h"
 #include "chrome/browser/browser_process_impl.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
diff --git a/chrome/browser/external_tab_container_win.cc b/chrome/browser/external_tab_container_win.cc
index ac4cfba..d5f7a7c 100644
--- a/chrome/browser/external_tab_container_win.cc
+++ b/chrome/browser/external_tab_container_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/view_prop.h"
 #include "base/debug/trace_event.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
@@ -29,11 +27,12 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
 #include "chrome/browser/tab_contents/provisional_load_details.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/browser_dialogs.h"
-#include "chrome/browser/views/page_info_bubble_view.h"
-#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
-#include "chrome/browser/views/tab_contents/tab_contents_container.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/page_info_bubble_view.h"
+#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
 #include "chrome/common/automation_messages.h"
 #include "chrome/common/bindings_policy.h"
 #include "chrome/common/chrome_constants.h"
@@ -45,11 +44,13 @@
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/view_prop.h"
+#include "views/layout/grid_layout.h"
 #include "views/widget/root_view.h"
 #include "views/window/window.h"
 
-using app::ViewProp;
+using ui::ViewProp;
 
 static const char kWindowObjectKey[] = "ChromeWindowObject";
 
@@ -87,7 +88,6 @@
 ExternalTabContainer::ExternalTabContainer(
     AutomationProvider* automation, AutomationResourceMessageFilter* filter)
     : automation_(automation),
-      tab_contents_(NULL),
       tab_contents_container_(NULL),
       tab_handle_(0),
       ignore_next_load_notification_(false),
@@ -108,13 +108,17 @@
   Uninitialize();
 }
 
+TabContents* ExternalTabContainer::tab_contents() const {
+  return tab_contents_.get() ? tab_contents_->tab_contents() : NULL;
+}
+
 bool ExternalTabContainer::Init(Profile* profile,
                                 HWND parent,
                                 const gfx::Rect& bounds,
                                 DWORD style,
                                 bool load_requests_via_automation,
                                 bool handle_top_level_requests,
-                                TabContents* existing_contents,
+                                TabContentsWrapper* existing_contents,
                                 const GURL& initial_url,
                                 const GURL& referrer,
                                 bool infobars_enabled,
@@ -141,17 +145,19 @@
   prop_.reset(new ViewProp(GetNativeView(), kWindowObjectKey, this));
 
   if (existing_contents) {
-    tab_contents_ = existing_contents;
+    tab_contents_.reset(existing_contents);
     tab_contents_->controller().set_profile(profile);
   } else {
-    tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE,
-                                    NULL, NULL);
+    TabContents* new_contents = new TabContents(profile, NULL, MSG_ROUTING_NONE,
+                                                NULL, NULL);
+    tab_contents_.reset(new TabContentsWrapper(new_contents));
   }
 
-  tab_contents_->set_delegate(this);
+  tab_contents_->tab_contents()->set_delegate(this);
 
-  tab_contents_->GetMutableRendererPrefs()->browser_handles_top_level_requests =
-      handle_top_level_requests;
+  tab_contents_->tab_contents()->
+      GetMutableRendererPrefs()->browser_handles_top_level_requests =
+          handle_top_level_requests;
 
   if (!existing_contents) {
     tab_contents_->render_view_host()->AllowBindings(
@@ -166,9 +172,9 @@
   registrar_.Add(this, NotificationType::LOAD_STOP,
                  Source<NavigationController>(controller));
   registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
-                 Source<TabContents>(tab_contents_));
+                 Source<TabContents>(tab_contents_->tab_contents()));
   registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
-                 Source<TabContents>(tab_contents_));
+                 Source<TabContents>(tab_contents_->tab_contents()));
 
   NotificationService::current()->Notify(
       NotificationType::EXTERNAL_TAB_CREATED,
@@ -196,7 +202,7 @@
   if (parent)
     SetParent(GetNativeView(), parent);
 
-  ::ShowWindow(tab_contents_->GetNativeView(), SW_SHOWNA);
+  ::ShowWindow(tab_contents_->tab_contents()->GetNativeView(), SW_SHOWNA);
 
   LoadAccelerators();
   SetupExternalTabView();
@@ -209,7 +215,7 @@
   }
 
   registrar_.RemoveAll();
-  if (tab_contents_) {
+  if (tab_contents_.get()) {
     RenderViewHost* rvh = tab_contents_->render_view_host();
     if (rvh) {
       if (DevToolsManager::GetInstance())
@@ -218,13 +224,16 @@
       UnregisterRenderViewHost(rvh);
     }
 
+    if (GetRootView()) {
+      GetRootView()->RemoveAllChildViews(true);
+    }
+
     NotificationService::current()->Notify(
         NotificationType::EXTERNAL_TAB_CLOSED,
         Source<NavigationController>(&tab_contents_->controller()),
         Details<ExternalTabContainer>(this));
 
-    delete tab_contents_;
-    tab_contents_ = NULL;
+    tab_contents_.reset(NULL);
   }
 
   if (focus_manager_) {
@@ -273,16 +282,16 @@
 
 void ExternalTabContainer::FocusThroughTabTraversal(
     bool reverse, bool restore_focus_to_view) {
-  DCHECK(tab_contents_);
-  if (tab_contents_)
-    tab_contents_->Focus();
+  DCHECK(tab_contents_.get());
+  if (tab_contents_.get())
+    tab_contents_->tab_contents()->Focus();
 
   // The tab_contents_ member can get destroyed in the context of the call to
   // TabContentsViewWin::Focus() above. This method eventually calls SetFocus
   // on the native window, which could end up dispatching messages like
   // WM_DESTROY for the external tab.
-  if (tab_contents_ && restore_focus_to_view)
-    tab_contents_->FocusThroughTabTraversal(reverse);
+  if (tab_contents_.get() && restore_focus_to_view)
+    tab_contents_->tab_contents()->FocusThroughTabTraversal(reverse);
 }
 
 // static
@@ -361,8 +370,10 @@
         details.did_replace_entry = false;
 
         scoped_refptr<history::HistoryAddPageArgs> add_page_args(
-            tab_contents_->CreateHistoryAddPageArgs(url, details, params));
-        tab_contents_->UpdateHistoryForNavigation(add_page_args);
+            tab_contents_->tab_contents()->
+                CreateHistoryAddPageArgs(url, details, params));
+        tab_contents_->tab_contents()->
+            UpdateHistoryForNavigation(add_page_args);
       }
       break;
     default:
@@ -412,6 +423,7 @@
 
   // Make sure that ExternalTabContainer instance is initialized with
   // an unwrapped Profile.
+  scoped_ptr<TabContentsWrapper> wrapper(new TabContentsWrapper(new_contents));
   bool result = new_container->Init(
       new_contents->profile()->GetOriginalProfile(),
       NULL,
@@ -419,13 +431,14 @@
       WS_CHILD,
       load_requests_via_automation_,
       handle_top_level_requests_,
-      new_contents,
+      wrapper.get(),
       GURL(),
       GURL(),
       true,
       route_all_top_level_navigations_);
 
   if (result) {
+    wrapper.release();  // Ownership has been transferred.
     if (route_all_top_level_navigations_) {
       return;
     }
@@ -487,10 +500,6 @@
                                         const gfx::Rect& pos) {
 }
 
-void ExternalTabContainer::URLStarredChanged(TabContents* source,
-                                             bool starred) {
-}
-
 void ExternalTabContainer::UpdateTargetURL(TabContents* source,
                                            const GURL& url) {
   if (automation_) {
@@ -827,7 +836,8 @@
      automation_->Send(reply_message);
      return;
   }
-  if (tab_contents_ && Browser::RunUnloadEventsHelper(tab_contents_)) {
+  if (tab_contents_.get() &&
+      Browser::RunUnloadEventsHelper(tab_contents_->tab_contents())) {
     unload_reply_message_ = reply_message;
   } else {
     AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message, true);
@@ -907,12 +917,13 @@
 void ExternalTabContainer::SetEnableExtensionAutomation(
     const std::vector<std::string>& functions_enabled) {
   if (functions_enabled.size() > 0) {
-    if (!tab_contents_) {
+    if (!tab_contents_.get()) {
       NOTREACHED() << "Being invoked via tab so should have TabContents";
       return;
     }
 
-    AutomationExtensionFunction::Enable(tab_contents_, functions_enabled);
+    AutomationExtensionFunction::Enable(tab_contents_->tab_contents(),
+                                        functions_enabled);
     enabled_extension_automation_ = true;
   } else {
     AutomationExtensionFunction::Disable();
@@ -920,10 +931,9 @@
   }
 }
 
-void ExternalTabContainer::InfoBarSizeChanged(bool is_animating) {
-  if (external_tab_view_) {
+void ExternalTabContainer::InfoBarContainerSizeChanged(bool is_animating) {
+  if (external_tab_view_)
     external_tab_view_->Layout();
-  }
 }
 
 // ExternalTabContainer instances do not have a window.
@@ -937,7 +947,7 @@
       accelerator_table_.find(accelerator);
   DCHECK(iter != accelerator_table_.end());
 
-  if (!tab_contents_ || !tab_contents_->render_view_host()) {
+  if (!tab_contents_.get() || !tab_contents_->render_view_host()) {
     NOTREACHED();
     return false;
   }
@@ -975,7 +985,7 @@
 }
 
 void ExternalTabContainer::Navigate(const GURL& url, const GURL& referrer) {
-  if (!tab_contents_) {
+  if (!tab_contents_.get()) {
     NOTREACHED();
     return;
   }
@@ -1022,7 +1032,7 @@
     bool ctrl_down = (accelerators[i].fVirt & FCONTROL) == FCONTROL;
     bool shift_down = (accelerators[i].fVirt & FSHIFT) == FSHIFT;
     views::Accelerator accelerator(
-        static_cast<app::KeyboardCode>(accelerators[i].key),
+        static_cast<ui::KeyboardCode>(accelerators[i].key),
         shift_down, ctrl_down, alt_down);
     accelerator_table_[accelerator] = accelerators[i].cmd;
 
@@ -1042,7 +1052,7 @@
     }
   }
 
-  NavigationStateChanged(tab_contents_, 0);
+  NavigationStateChanged(tab_contents(), 0);
   ServicePendingOpenURLRequests();
 }
 
@@ -1052,10 +1062,10 @@
   set_pending(false);
 
   for (size_t index = 0; index < pending_open_url_requests_.size();
-       index ++) {
+       ++index) {
     const PendingTopLevelNavigation& url_request =
         pending_open_url_requests_[index];
-    OpenURLFromTab(tab_contents_, url_request.url, url_request.referrer,
+    OpenURLFromTab(tab_contents(), url_request.url, url_request.referrer,
                    url_request.disposition, url_request.transition);
   }
   pending_open_url_requests_.clear();
@@ -1071,7 +1081,7 @@
   external_tab_view_ = new views::View();
 
   InfoBarContainer* info_bar_container = new InfoBarContainer(this);
-  info_bar_container->ChangeTabContents(tab_contents_);
+  info_bar_container->ChangeTabContents(tab_contents());
 
   views::GridLayout* layout = new views::GridLayout(external_tab_view_);
   // Give this column an identifier of 0.
@@ -1091,7 +1101,7 @@
   layout->AddView(tab_contents_container_);
   SetContentsView(external_tab_view_);
   // Note that SetTabContents must be called after AddChildView is called
-  tab_contents_container_->ChangeTabContents(tab_contents_);
+  tab_contents_container_->ChangeTabContents(tab_contents());
 }
 
 TemporaryPopupExternalTabContainer::TemporaryPopupExternalTabContainer(
diff --git a/chrome/browser/external_tab_container_win.h b/chrome/browser/external_tab_container_win.h
index f08f364..63a5958 100644
--- a/chrome/browser/external_tab_container_win.h
+++ b/chrome/browser/external_tab_container_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,10 +15,9 @@
 #include "chrome/browser/automation/automation_resource_message_filter.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/frame/browser_bubble_host.h"
-#include "chrome/browser/views/infobars/infobar_container.h"
-#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
+#include "chrome/browser/ui/views/frame/browser_bubble_host.h"
+#include "chrome/browser/ui/views/infobars/infobar_container.h"
+#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h"
 #include "chrome/common/navigation_types.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
@@ -26,19 +25,21 @@
 #include "views/widget/widget_win.h"
 
 class AutomationProvider;
+class Browser;
 class Profile;
 class TabContentsContainer;
+class TabContentsWrapper;
 class RenderViewContextMenuViews;
 struct NavigationInfo;
 
-namespace app {
+namespace ui {
 class ViewProp;
 }
 
 // This class serves as the container window for an external tab.
 // An external tab is a Chrome tab that is meant to displayed in an
 // external process. This class provides the FocusManger needed by the
-// TabContents as well as an implementation of TabContentsDelagate.
+// TabContents as well as an implementation of TabContentsDelegate.
 class ExternalTabContainer : public TabContentsDelegate,
                              public NotificationObserver,
                              public views::WidgetWin,
@@ -52,7 +53,7 @@
   ExternalTabContainer(AutomationProvider* automation,
       AutomationResourceMessageFilter* filter);
 
-  TabContents* tab_contents() const { return tab_contents_; }
+  TabContents* tab_contents() const;
 
   // Temporary hack so we can send notifications back
   void SetTabHandle(int handle);
@@ -67,7 +68,7 @@
             DWORD style,
             bool load_requests_via_automation,
             bool handle_top_level_requests,
-            TabContents* existing_tab_contents,
+            TabContentsWrapper* existing_tab_contents,
             const GURL& initial_url,
             const GURL& referrer,
             bool infobars_enabled,
@@ -126,7 +127,6 @@
   virtual void LoadingStateChanged(TabContents* source);
   virtual void CloseContents(TabContents* source);
   virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
-  virtual void URLStarredChanged(TabContents* source, bool starred);
   virtual void UpdateTargetURL(TabContents* source, const GURL& url);
   virtual void ContentsZoomChange(bool zoom_in);
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
@@ -207,7 +207,7 @@
   }
 
   // InfoBarContainer::Delegate overrides
-  virtual void InfoBarSizeChanged(bool is_animating);
+  virtual void InfoBarContainerSizeChanged(bool is_animating);
 
   virtual void TabContentsCreated(TabContents* new_contents);
 
@@ -266,7 +266,7 @@
   // Creates and initializes the view hierarchy for this ExternalTabContainer.
   void SetupExternalTabView();
 
-  TabContents* tab_contents_;
+  scoped_ptr<TabContentsWrapper> tab_contents_;
   scoped_refptr<AutomationProvider> automation_;
 
   NotificationRegistrar registrar_;
@@ -336,7 +336,7 @@
   // page without chrome frame.
   bool route_all_top_level_navigations_;
 
-  scoped_ptr<app::ViewProp> prop_;
+  scoped_ptr<ui::ViewProp> prop_;
 
   DISALLOW_COPY_AND_ASSIGN(ExternalTabContainer);
 };
diff --git a/chrome/browser/fav_icon_helper.cc b/chrome/browser/fav_icon_helper.cc
index 544b4e8..0f19eca 100644
--- a/chrome/browser/fav_icon_helper.cc
+++ b/chrome/browser/fav_icon_helper.cc
@@ -17,9 +17,10 @@
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/favicon_size.h"
+#include "chrome/common/render_messages.h"
 #include "skia/ext/image_operations.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/favicon_size.h"
 
 FavIconHelper::FavIconHelper(TabContents* tab_contents)
     : tab_contents_(tab_contents),
@@ -111,9 +112,7 @@
   tab_contents_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TAB);
 }
 
-void FavIconHelper::UpdateFavIconURL(RenderViewHost* render_view_host,
-                                     int32 page_id,
-                                     const GURL& icon_url) {
+void FavIconHelper::OnUpdateFavIconURL(int32 page_id, const GURL& icon_url) {
   // TODO(davemoore) Should clear on empty url. Currently we ignore it.
   // This appears to be what FF does as well.
   if (icon_url.is_empty())
@@ -140,11 +139,20 @@
     DownloadFavIconOrAskHistory(entry);
 }
 
-void FavIconHelper::DidDownloadFavIcon(RenderViewHost* render_view_host,
-                                       int id,
-                                       const GURL& image_url,
-                                       bool errored,
-                                       const SkBitmap& image) {
+bool FavIconHelper::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(FavIconHelper, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFavIconURL, OnUpdateFavIconURL)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_DidDownloadFavIcon, OnDidDownloadFavIcon)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void FavIconHelper::OnDidDownloadFavIcon(int id,
+                                         const GURL& image_url,
+                                         bool errored,
+                                         const SkBitmap& image) {
   DownloadRequests::iterator i = download_requests_.find(id);
   if (i == download_requests_.end()) {
     // Currently TabContents notifies us of ANY downloads so that it is
diff --git a/chrome/browser/fav_icon_helper.h b/chrome/browser/fav_icon_helper.h
index a64eba2..3ec480f 100644
--- a/chrome/browser/fav_icon_helper.h
+++ b/chrome/browser/fav_icon_helper.h
@@ -13,7 +13,7 @@
 #include "base/ref_counted.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/favicon_service.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
 #include "chrome/common/ref_counted_util.h"
 #include "googleurl/src/gurl.h"
 
@@ -65,7 +65,7 @@
 // at which point we update the favicon of the NavigationEntry and notify
 // the database to save the favicon.
 
-class FavIconHelper : public RenderViewHostDelegate::FavIcon {
+class FavIconHelper : public TabContentsObserver {
  public:
   explicit FavIconHelper(TabContents* tab_contents);
   virtual ~FavIconHelper();
@@ -84,6 +84,10 @@
   int DownloadImage(const GURL& image_url, int image_size,
                     ImageDownloadCallback* callback);
 
+  // Message Handler.  Must be public, becaue also called from
+  // PrerenderContents.
+  void OnUpdateFavIconURL(int32 page_id, const GURL& icon_url);
+
  private:
   struct DownloadRequest {
     DownloadRequest() {}
@@ -99,15 +103,13 @@
     ImageDownloadCallback* callback;
   };
 
-  // RenderViewHostDelegate::Favicon implementation.
-  virtual void DidDownloadFavIcon(RenderViewHost* render_view_host,
-                                  int id,
-                                  const GURL& image_url,
-                                  bool errored,
-                                  const SkBitmap& image);
-  virtual void UpdateFavIconURL(RenderViewHost* render_view_host,
-                                int32 page_id,
-                                const GURL& icon_url);
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+  void OnDidDownloadFavIcon(int id,
+                            const GURL& image_url,
+                            bool errored,
+                            const SkBitmap& image);
 
   // Return the NavigationEntry for the active entry, or NULL if the active
   // entries URL does not match that of the URL last passed to FetchFavIcon.
diff --git a/chrome/browser/favicon_service.cc b/chrome/browser/favicon_service.cc
index b476a41..f977119 100644
--- a/chrome/browser/favicon_service.cc
+++ b/chrome/browser/favicon_service.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/favicon_service.h"
 
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/profiles/profile.h"
@@ -51,7 +51,7 @@
   FaviconService::Handle handle = request->handle();
   if (page_url.SchemeIs(chrome::kChromeUIScheme) ||
       page_url.SchemeIs(chrome::kExtensionScheme)) {
-    DOMUIFactory::GetFaviconForURL(profile_, request, page_url);
+    WebUIFactory::GetFaviconForURL(profile_, request, page_url);
   } else {
     HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
     if (hs)
diff --git a/chrome/browser/favicon_service.h b/chrome/browser/favicon_service.h
index b6ef85b..70c814a 100644
--- a/chrome/browser/favicon_service.h
+++ b/chrome/browser/favicon_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,6 @@
 #include "base/task.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/history/history_types.h"
-#include "chrome/common/notification_observer.h"
 #include "chrome/common/ref_counted_util.h"
 
 class GURL;
diff --git a/chrome/browser/file_path_watcher/file_path_watcher_inotify.cc b/chrome/browser/file_path_watcher/file_path_watcher_inotify.cc
index bc59a2e..19a18a6 100644
--- a/chrome/browser/file_path_watcher/file_path_watcher_inotify.cc
+++ b/chrome/browser/file_path_watcher/file_path_watcher_inotify.cc
@@ -21,10 +21,10 @@
 #include "base/file_util.h"
 #include "base/hash_tables.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "base/threading/thread.h"
 
@@ -62,7 +62,7 @@
   base::hash_map<Watch, WatcherSet> watchers_;
 
   // Lock to protect watchers_.
-  Lock lock_;
+  base::Lock lock_;
 
   // Separate thread on which we run blocking read for inotify events.
   base::Thread thread_;
@@ -237,7 +237,7 @@
   if (!valid_)
     return kInvalidWatch;
 
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
 
   Watch watch = inotify_add_watch(inotify_fd_, path.value().c_str(),
                                   IN_CREATE | IN_DELETE |
@@ -257,7 +257,7 @@
   if (!valid_)
     return false;
 
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
 
   watchers_[watch].erase(watcher);
 
@@ -274,7 +274,7 @@
     return;
 
   FilePath::StringType child(event->len ? event->name : FILE_PATH_LITERAL(""));
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
 
   for (WatcherSet::iterator watcher = watchers_[event->wd].begin();
        watcher != watchers_[event->wd].end();
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc
index 1604b0d..74e74a7 100644
--- a/chrome/browser/file_select_helper.cc
+++ b/chrome/browser/file_select_helper.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
@@ -16,11 +15,11 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/shell_dialogs.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/render_messages_params.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 FileSelectHelper::FileSelectHelper(Profile* profile)
     : profile_(profile),
@@ -96,12 +95,14 @@
 
 void FileSelectHelper::OnListFile(
     const net::DirectoryLister::DirectoryListerData& data) {
-  // Directory upload only cares about files.  This util call just checks
+  // Directory upload returns directories via a "." file, so that
+  // empty directories are included.  This util call just checks
   // the flags in the structure; there's no file I/O going on.
   if (file_util::FileEnumerator::IsDirectory(data.info))
-    return;
-
-  directory_lister_results_.push_back(data.path);
+    directory_lister_results_.push_back(
+        data.path.Append(FILE_PATH_LITERAL(".")));
+  else
+    directory_lister_results_.push_back(data.path);
 }
 
 void FileSelectHelper::OnListDone(int error) {
diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h
index ba8441b..10d7260 100644
--- a/chrome/browser/file_select_helper.h
+++ b/chrome/browser/file_select_helper.h
@@ -8,8 +8,7 @@
 
 #include <vector>
 
-#include "chrome/browser/shell_dialogs.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "net/base/directory_lister.h"
@@ -21,7 +20,6 @@
 class FileSelectHelper
     : public SelectFileDialog::Listener,
       public net::DirectoryLister::DirectoryListerDelegate,
-      public RenderViewHostDelegate::FileSelect,
       public NotificationObserver {
  public:
   explicit FileSelectHelper(Profile* profile);
@@ -38,9 +36,9 @@
       const net::DirectoryLister::DirectoryListerData& data);
   virtual void OnListDone(int error);
 
-  // RenderViewHostDelegate::FileSelect
-  virtual void RunFileChooser(RenderViewHost* render_view_host,
-                              const ViewHostMsg_RunFileChooser_Params& params);
+  // Show the file chooser dialog.
+  void RunFileChooser(RenderViewHost* render_view_host,
+                      const ViewHostMsg_RunFileChooser_Params& params);
 
  private:
   // NotificationObserver implementation.
diff --git a/chrome/browser/file_system/browser_file_system_helper.cc b/chrome/browser/file_system/browser_file_system_helper.cc
index 2ce4f36..47b3e5e 100644
--- a/chrome/browser/file_system/browser_file_system_helper.cc
+++ b/chrome/browser/file_system/browser_file_system_helper.cc
@@ -9,9 +9,9 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/common/chrome_switches.h"
 
-scoped_refptr<fileapi::SandboxedFileSystemContext> CreateFileSystemContext(
+scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
         const FilePath& profile_path, bool is_incognito) {
-  return new fileapi::SandboxedFileSystemContext(
+  return new fileapi::FileSystemContext(
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
       profile_path,
diff --git a/chrome/browser/file_system/browser_file_system_helper.h b/chrome/browser/file_system/browser_file_system_helper.h
index 56ec3e2..b99f9d1 100644
--- a/chrome/browser/file_system/browser_file_system_helper.h
+++ b/chrome/browser/file_system/browser_file_system_helper.h
@@ -7,11 +7,11 @@
 
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
-#include "webkit/fileapi/sandboxed_file_system_context.h"
+#include "webkit/fileapi/file_system_context.h"
 
-// Convenient method that returns SandboxedFileSystemContext
-// constructed for the browser process.
-scoped_refptr<fileapi::SandboxedFileSystemContext> CreateFileSystemContext(
+// Helper method that returns FileSystemContext constructed for
+// the browser process.
+scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
         const FilePath& profile_path, bool is_incognito);
 
 #endif  // CHROME_BROWSER_FILE_SYSTEM_BROWSER_FILE_SYSTEM_HELPER_H_
diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc
index cf28585..4360b52 100644
--- a/chrome/browser/file_system/file_system_dispatcher_host.cc
+++ b/chrome/browser/file_system/file_system_dispatcher_host.cc
@@ -20,15 +20,15 @@
 #include "googleurl/src/gurl.h"
 #include "net/url_request/url_request_context.h"
 #include "webkit/fileapi/file_system_callback_dispatcher.h"
+#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_operation.h"
 #include "webkit/fileapi/file_system_operation.h"
 #include "webkit/fileapi/file_system_path_manager.h"
 #include "webkit/fileapi/file_system_quota_manager.h"
-#include "webkit/fileapi/sandboxed_file_system_context.h"
-#include "webkit/fileapi/sandboxed_file_system_operation.h"
 
 using fileapi::FileSystemCallbackDispatcher;
+using fileapi::FileSystemOperation;
 using fileapi::FileSystemQuotaManager;
-using fileapi::SandboxedFileSystemOperation;
 
 class BrowserFileSystemCallbackDispatcher
     : public FileSystemCallbackDispatcher {
@@ -219,7 +219,7 @@
 void FileSystemDispatcherHost::OnCancel(
     int request_id,
     int request_id_to_cancel) {
-  SandboxedFileSystemOperation* write = operations_.Lookup(
+  FileSystemOperation* write = operations_.Lookup(
       request_id_to_cancel);
   if (write) {
     // The cancel will eventually send both the write failure and the cancel
@@ -232,11 +232,11 @@
   }
 }
 
-SandboxedFileSystemOperation* FileSystemDispatcherHost::GetNewOperation(
+FileSystemOperation* FileSystemDispatcherHost::GetNewOperation(
     int request_id) {
   BrowserFileSystemCallbackDispatcher* dispatcher =
       new BrowserFileSystemCallbackDispatcher(this, request_id);
-  SandboxedFileSystemOperation* operation = new SandboxedFileSystemOperation(
+  FileSystemOperation* operation = new FileSystemOperation(
       dispatcher,
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
       context_);
diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h
index 865ef70..bf807bb 100644
--- a/chrome/browser/file_system/file_system_dispatcher_host.h
+++ b/chrome/browser/file_system/file_system_dispatcher_host.h
@@ -30,8 +30,8 @@
 }  // namespace net
 
 namespace fileapi {
-class SandboxedFileSystemContext;
-class SandboxedFileSystemOperation;
+class FileSystemContext;
+class FileSystemOperation;
 }
 
 class FileSystemDispatcherHost : public BrowserMessageFilter {
@@ -81,20 +81,20 @@
   void UnregisterOperation(int request_id);
 
  private:
-  // Creates a new SandboxedFileSystemOperation.
-  fileapi::SandboxedFileSystemOperation* GetNewOperation(int request_id);
+  // Creates a new FileSystemOperation.
+  fileapi::FileSystemOperation* GetNewOperation(int request_id);
 
-  scoped_refptr<fileapi::SandboxedFileSystemContext> context_;
+  scoped_refptr<fileapi::FileSystemContext> context_;
 
   // Used to look up permissions.
   scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
 
   // Keeps ongoing file system operations.
-  typedef IDMap<fileapi::SandboxedFileSystemOperation> OperationsMap;
+  typedef IDMap<fileapi::FileSystemOperation> OperationsMap;
   OperationsMap operations_;
 
   // This holds the URLRequestContextGetter until Init() can be called from the
-  // IO thread, which will extract the URLRequestContext from it.
+  // IO thread, which will extract the net::URLRequestContext from it.
   scoped_refptr<URLRequestContextGetter> request_context_getter_;
   scoped_refptr<net::URLRequestContext> request_context_;
 
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index 4235a8a..31efea8 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -126,7 +126,7 @@
     if (WriteEULAtoTempFile(&inner_html)) {
       int retcode = 0;
       if (!LaunchSetupWithParam(installer::switches::kShowEula,
-                                inner_html.ToWStringHack(), &retcode) ||
+                                inner_html.value(), &retcode) ||
           (retcode == installer::EULA_REJECTED)) {
         LOG(WARNING) << "EULA rejected. Fast exit.";
         ::ExitProcess(1);
@@ -281,9 +281,10 @@
   if (out_prefs->do_import_items || !import_bookmarks_path.empty()) {
     // There is something to import from the default browser. This launches
     // the importer process and blocks until done or until it fails.
-    scoped_refptr<ImporterHost> importer_host = new ImporterHost();
+    scoped_refptr<ImporterList> importer_list(new ImporterList);
+    importer_list->DetectSourceProfilesHack();
     if (!FirstRun::ImportSettings(NULL,
-          importer_host->GetSourceProfileInfoAt(0).browser_type,
+          importer_list->GetSourceProfileInfoAt(0).browser_type,
           out_prefs->do_import_items,
           FilePath::FromWStringHack(UTF8ToWide(import_bookmarks_path)),
           true, NULL)) {
@@ -301,10 +302,20 @@
   }
 #endif
 
-  if (prefs.GetBool(
-          installer::master_preferences::kMakeChromeDefaultForUser,
-          &value) && value) {
-    ShellIntegration::SetAsDefaultBrowser();
+  // Even on the first run we only allow for the user choice to take effect if
+  // no policy has been set by the admin.
+  if (!g_browser_process->local_state()->IsManagedPreference(
+          prefs::kDefaultBrowserSettingEnabled)) {
+    if (prefs.GetBool(
+            installer::master_preferences::kMakeChromeDefaultForUser,
+            &value) && value) {
+      ShellIntegration::SetAsDefaultBrowser();
+    }
+  } else {
+    if (g_browser_process->local_state()->GetBoolean(
+            prefs::kDefaultBrowserSettingEnabled)) {
+      ShellIntegration::SetAsDefaultBrowser();
+    }
   }
 
   return false;
@@ -412,7 +423,7 @@
     NOTREACHED();
     return false;
   }
-  scoped_refptr<ImporterHost> importer_host(new ImporterHost());
+  scoped_refptr<ImporterHost> importer_host(new ImporterHost);
   FirstRunImportObserver observer;
 
   importer_host->set_headless();
@@ -546,8 +557,12 @@
 #else
   importer_host = new ImporterHost;
 #endif
+
+  scoped_refptr<ImporterList> importer_list(new ImporterList);
+  importer_list->DetectSourceProfilesHack();
+
   // Do import if there is an available profile for us to import.
-  if (importer_host->GetAvailableProfileCount() > 0) {
+  if (importer_list->GetAvailableProfileCount() > 0) {
     // Don't show the warning dialog if import fails.
     importer_host->set_headless();
     int items = 0;
@@ -580,7 +595,7 @@
     if (import_items & importer::FAVORITES)
       items = items | importer::FAVORITES;
 
-    ImportSettings(profile, importer_host, items);
+    ImportSettings(profile, importer_host, importer_list, items);
   }
 
   UserMetrics::RecordAction(UserMetricsAction("FirstRunDef_Accept"));
@@ -656,8 +671,9 @@
 // static
 bool FirstRun::ImportSettings(Profile* profile,
                               scoped_refptr<ImporterHost> importer_host,
+                              scoped_refptr<ImporterList> importer_list,
                               int items_to_import) {
-  const ProfileInfo& source_profile = importer_host->GetSourceProfileInfoAt(0);
+  const ProfileInfo& source_profile = importer_list->GetSourceProfileInfoAt(0);
 
   // Ensure that importers aren't requested to import items that they do not
   // support.
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index 415753f..d663518 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,8 +12,8 @@
 #include "chrome/browser/browser_process_impl.h"
 #include "chrome/browser/importer/importer.h"
 #include "chrome/common/result_codes.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/native_widget_types.h"
 
 class CommandLine;
 class FilePath;
@@ -122,6 +122,7 @@
   // success.
   static bool ImportSettings(Profile* profile,
                              scoped_refptr<ImporterHost> importer_host,
+                             scoped_refptr<ImporterList> importer_list,
                              int items_to_import);
 
   // Sets the kShouldShowFirstRunBubble local state pref so that the browser
diff --git a/chrome/browser/first_run/first_run_gtk.cc b/chrome/browser/first_run/first_run_gtk.cc
index 3dd5ffa..85f072d 100644
--- a/chrome/browser/first_run/first_run_gtk.cc
+++ b/chrome/browser/first_run/first_run_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,13 +14,13 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/gtk/first_run_dialog.h"
 #include "chrome/browser/shell_integration.h"
+#include "chrome/browser/ui/gtk/first_run_dialog.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/result_codes.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "googleurl/src/gurl.h"
+#include "ui/base/ui_base_switches.h"
 
 // TODO(port): This is just a piece of the silent import functionality from
 // ImportSettings for Windows.  It would be nice to get the rest of it ported.
diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc
index 5f6a0b0..4f3fe85 100644
--- a/chrome/browser/first_run/first_run_win.cc
+++ b/chrome/browser/first_run/first_run_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,9 +11,6 @@
 #include <set>
 #include <sstream>
 
-#include "app/app_switches.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/environment.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
@@ -32,11 +29,10 @@
 #include "chrome/browser/process_singleton.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/views/first_run_search_engine_view.h"
+#include "chrome/browser/ui/views/first_run_search_engine_view.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/worker_thread_ticker.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/google_update_constants.h"
@@ -54,11 +50,14 @@
 #include "views/controls/image_view.h"
 #include "views/controls/link.h"
 #include "views/focus/accelerator_handler.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_win.h"
 #include "views/window/window.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_switches.h"
 
 namespace {
 
@@ -279,8 +278,10 @@
   BrowserDistribution *dist = BrowserDistribution::GetDistribution();
   base::win::RegKey key;
   std::wstring rename_cmd;
-  if (key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) &&
-      key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd)) {
+  if ((key.Open(reg_root, dist->GetVersionKey().c_str(),
+                KEY_READ) == ERROR_SUCCESS) &&
+      (key.ReadValue(google_update::kRegRenameCmdField,
+                     &rename_cmd) == ERROR_SUCCESS)) {
     base::ProcessHandle handle;
     if (base::LaunchApp(rename_cmd, true, true, &handle)) {
       DWORD exit_code;
@@ -523,10 +524,11 @@
 // static
 bool FirstRun::ImportSettings(Profile* profile,
                               scoped_refptr<ImporterHost> importer_host,
+                              scoped_refptr<ImporterList> importer_list,
                               int items_to_import) {
   return ImportSettings(
       profile,
-      importer_host->GetSourceProfileInfoAt(0).browser_type,
+      importer_list->GetSourceProfileInfoAt(0).browser_type,
       items_to_import,
       FilePath(), false, NULL);
 }
@@ -547,9 +549,12 @@
     NOTREACHED();
     return false;
   }
-  scoped_refptr<ImporterHost> importer_host = new ImporterHost();
+  scoped_refptr<ImporterHost> importer_host(new ImporterHost);
   FirstRunImportObserver observer;
 
+  scoped_refptr<ImporterList> importer_list(new ImporterList);
+  importer_list->DetectSourceProfilesHack();
+
   // If |skip_first_run_ui|, we run in headless mode.  This means that if
   // there is user action required the import is automatically canceled.
   if (skip_first_run_ui > 0)
@@ -559,7 +564,7 @@
       parent_window,
       static_cast<uint16>(items_to_import),
       importer_host,
-      importer_host->GetSourceProfileInfoForBrowserType(browser_type),
+      importer_list->GetSourceProfileInfoForBrowserType(browser_type),
       profile,
       &observer,
       true);
@@ -641,7 +646,7 @@
     root_view->set_background(
         views::Background::CreateSolidBackground(0xfc, 0xfc, 0xfc));
 
-    views::GridLayout* layout = CreatePanelGridLayout(root_view);
+    views::GridLayout* layout = views::GridLayout::CreatePanel(root_view);
     if (!layout) {
       NOTREACHED();
       return Upgrade::TD_DIALOG_ERROR;
@@ -654,7 +659,7 @@
     columns->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
                        GridLayout::FIXED, icon_size.width(),
                        icon_size.height());
-    columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     columns->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                        GridLayout::USE_PREF, 0, 0);
     columns->AddColumn(GridLayout::TRAILING, GridLayout::FILL, 1,
@@ -662,28 +667,28 @@
     // Second row: [pad][pad][radio 1].
     columns = layout->AddColumnSet(1);
     columns->AddPaddingColumn(0, icon_size.width());
-    columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
                        GridLayout::USE_PREF, 0, 0);
     // Third row: [pad][pad][radio 2].
     columns = layout->AddColumnSet(2);
     columns->AddPaddingColumn(0, icon_size.width());
-    columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
                        GridLayout::USE_PREF, 0, 0);
     // Fourth row: [pad][pad][button][pad][button].
     columns = layout->AddColumnSet(3);
     columns->AddPaddingColumn(0, icon_size.width());
-    columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
                        GridLayout::USE_PREF, 0, 0);
-    columns->AddPaddingColumn(0, kRelatedButtonHSpacing);
+    columns->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
     columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
                        GridLayout::USE_PREF, 0, 0);
     // Fifth row: [pad][pad][link].
     columns = layout->AddColumnSet(4);
     columns->AddPaddingColumn(0, icon_size.width());
-    columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
                        GridLayout::USE_PREF, 0, 0);
     // First row views.
diff --git a/chrome/browser/fonts_languages_window.h b/chrome/browser/fonts_languages_window.h
index 0e47c92..0615ce4 100644
--- a/chrome/browser/fonts_languages_window.h
+++ b/chrome/browser/fonts_languages_window.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_FONTS_LANGUAGES_WINDOW_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Profile;
 
diff --git a/chrome/browser/fullscreen.h b/chrome/browser/fullscreen.h
new file mode 100644
index 0000000..3ed7ecc
--- /dev/null
+++ b/chrome/browser/fullscreen.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FULLSCREEN_H_
+#define CHROME_BROWSER_FULLSCREEN_H_
+#pragma once
+
+#include "build/build_config.h"
+
+// For MacOSX, InitFullScreenMonitor needs to be called first to setup the
+// monitor. StopFullScreenMonitor should be called if it is not needed any more.
+#if defined(OS_MACOSX)
+void InitFullScreenMonitor();
+void StopFullScreenMonitor();
+#endif
+
+bool IsFullScreenMode();
+
+#endif  // CHROME_BROWSER_FULLSCREEN_H_
diff --git a/chrome/browser/fullscreen_linux.cc b/chrome/browser/fullscreen_linux.cc
new file mode 100644
index 0000000..da69642
--- /dev/null
+++ b/chrome/browser/fullscreen_linux.cc
@@ -0,0 +1,144 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/fullscreen.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/rect.h"
+
+namespace {
+
+// TODO (jianli): Merge with gtk_util::EnumerateTopLevelWindows.
+void EnumerateAllChildWindows(ui::EnumerateWindowsDelegate* delegate,
+                              XID window) {
+  std::vector<XID> windows;
+
+  if (!ui::GetXWindowStack(window, &windows)) {
+    // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
+    // to old school enumeration of all X windows.
+    XID root, parent, *children;
+    unsigned int num_children;
+    int status = XQueryTree(ui::GetXDisplay(), window, &root, &parent,
+                            &children, &num_children);
+    if (status) {
+      for (long i = static_cast<long>(num_children) - 1; i >= 0; i--)
+        windows.push_back(children[i]);
+      XFree(children);
+    }
+  }
+
+  std::vector<XID>::iterator iter;
+  for (iter = windows.begin(); iter != windows.end(); iter++) {
+    if (delegate->ShouldStopIterating(*iter))
+      return;
+  }
+}
+
+// To find the top-most window:
+// 1) Enumerate all top-level windows from the top to the bottom.
+// 2) For each window:
+//    2.1) If it is hidden, continue the iteration.
+//    2.2) If it is managed by the Window Manager (has a WM_STATE property).
+//         Return this window as the top-most window.
+//    2.3) Enumerate all its child windows. If there is a child window that is
+//         managed by the Window Manager (has a WM_STATE property). Return this
+//         child window as the top-most window.
+//    2.4) Otherwise, continue the iteration.
+
+class WindowManagerWindowFinder : public ui::EnumerateWindowsDelegate {
+ public:
+  WindowManagerWindowFinder() : window_(None) { }
+
+  XID window() const { return window_; }
+
+ protected:
+  virtual bool ShouldStopIterating(XID window) {
+    if (ui::PropertyExists(window, "WM_STATE")) {
+      window_ = window;
+      return true;
+    }
+    return false;
+  }
+
+ private:
+  XID window_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowManagerWindowFinder);
+};
+
+class TopMostWindowFinder : public ui::EnumerateWindowsDelegate {
+ public:
+  TopMostWindowFinder()
+      : top_most_window_(None) {}
+
+  XID top_most_window() const { return top_most_window_; }
+
+ protected:
+   virtual bool ShouldStopIterating(XID window) {
+     if (!ui::IsWindowVisible(window))
+       return false;
+     if (ui::PropertyExists(window, "WM_STATE")) {
+      top_most_window_ = window;
+      return true;
+    }
+     WindowManagerWindowFinder child_finder;
+     EnumerateAllChildWindows(&child_finder, window);
+     XID child_window = child_finder.window();
+     if (child_window == None)
+       return false;
+     top_most_window_ = child_window;
+     return true;
+   }
+
+ private:
+  XID top_most_window_;
+
+  DISALLOW_COPY_AND_ASSIGN(TopMostWindowFinder);
+};
+
+bool IsTopMostWindowFullScreen() {
+  // Find the topmost window.
+  TopMostWindowFinder finder;
+  EnumerateAllChildWindows(&finder, ui::GetX11RootWindow());
+  XID window = finder.top_most_window();
+  if (window == None)
+    return false;
+
+  // Make sure it is not the desktop window.
+  static Atom desktop_atom = gdk_x11_get_xatom_by_name_for_display(
+      gdk_display_get_default(), "_NET_WM_WINDOW_TYPE_DESKTOP");
+
+  std::vector<Atom> atom_properties;
+  if (ui::GetAtomArrayProperty(window,
+                               "_NET_WM_WINDOW_TYPE",
+                               &atom_properties) &&
+      std::find(atom_properties.begin(), atom_properties.end(), desktop_atom)
+          != atom_properties.end())
+    return false;
+
+  // If it is a GDK window, check it using gdk function.
+  GdkWindow* gwindow = gdk_window_lookup(window);
+  if (gwindow && window != GDK_ROOT_WINDOW())
+    return gdk_window_get_state(gwindow) == GDK_WINDOW_STATE_FULLSCREEN;
+
+  // Otherwise, do the check via xlib function.
+  return ui::IsX11WindowFullScreen(window);
+}
+
+}
+
+bool IsFullScreenMode() {
+  gdk_error_trap_push();
+  bool result = IsTopMostWindowFullScreen();
+  bool got_error = gdk_error_trap_pop();
+  return result && !got_error;
+}
diff --git a/chrome/browser/fullscreen_mac.mm b/chrome/browser/fullscreen_mac.mm
new file mode 100644
index 0000000..303f6f2
--- /dev/null
+++ b/chrome/browser/fullscreen_mac.mm
@@ -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.
+
+#import "chrome/browser/fullscreen.h"
+
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+
+#import "base/logging.h"
+
+@interface FullScreenMonitor : NSObject {
+ @private
+  BOOL fullScreen_;
+  EventHandlerRef eventHandler_;
+}
+
+@property (nonatomic, getter=isFullScreen) BOOL fullScreen;
+
+@end
+
+static OSStatus handleAppEvent(EventHandlerCallRef myHandler,
+                               EventRef event,
+                               void* userData) {
+  DCHECK(userData);
+
+  FullScreenMonitor* fullScreenMonitor =
+      reinterpret_cast<FullScreenMonitor*>(userData);
+
+  UInt32 mode = 0;
+  OSStatus status = GetEventParameter(event,
+                                      kEventParamSystemUIMode,
+                                      typeUInt32,
+                                      NULL,
+                                      sizeof(UInt32),
+                                      NULL,
+                                      &mode);
+  if (status != noErr)
+    return status;
+  BOOL isFullScreenMode = mode == kUIModeAllHidden;
+  [fullScreenMonitor setFullScreen:isFullScreenMode];
+  return noErr;
+}
+
+@implementation FullScreenMonitor
+
+@synthesize fullScreen = fullScreen_;
+
+- (id)init {
+  if ((self = [super init])) {
+    // Check if the user is in presentation mode initially.
+    SystemUIMode currentMode;
+    GetSystemUIMode(&currentMode, NULL);
+    fullScreen_ = currentMode == kUIModeAllHidden;
+
+    // Register a Carbon event to receive the notification about the login
+    // session's UI mode change.
+    EventTypeSpec events[] =
+      {{ kEventClassApplication, kEventAppSystemUIModeChanged }};
+    OSStatus status = InstallApplicationEventHandler(
+        NewEventHandlerUPP(handleAppEvent),
+        GetEventTypeCount(events),
+        events,
+        self,
+        &eventHandler_);
+    if (status) {
+      [self release];
+      self = nil;
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if (eventHandler_)
+    RemoveEventHandler(eventHandler_);
+  [super dealloc];
+}
+
+@end
+
+static FullScreenMonitor* g_fullScreenMonitor = nil;
+
+void InitFullScreenMonitor() {
+  if (!g_fullScreenMonitor)
+    g_fullScreenMonitor = [[FullScreenMonitor alloc] init];
+}
+
+void StopFullScreenMonitor() {
+  [g_fullScreenMonitor release];
+  g_fullScreenMonitor = nil;
+}
+
+bool IsFullScreenMode() {
+  // Check if the main display has been captured (game in particular).
+  if (CGDisplayIsCaptured(CGMainDisplayID()))
+    return true;
+
+  return [g_fullScreenMonitor isFullScreen];
+}
diff --git a/chrome/browser/fullscreen_win.cc b/chrome/browser/fullscreen_win.cc
new file mode 100644
index 0000000..ac50ed4
--- /dev/null
+++ b/chrome/browser/fullscreen_win.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/fullscreen.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "base/logging.h"
+#include "base/sys_info.h"
+
+static bool IsPlatformFullScreenMode() {
+  // SHQueryUserNotificationState is only available for Vista and above.
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_VISTA)
+  int32 major_version, minor_version, fix_version;
+  base::SysInfo::OperatingSystemVersionNumbers(&major_version,
+                                               &minor_version,
+                                               &fix_version);
+  if (major_version < 6)
+    return false;
+
+  typedef HRESULT(WINAPI *SHQueryUserNotificationStatePtr)(
+      QUERY_USER_NOTIFICATION_STATE* state);
+
+  HMODULE shell32_base = ::GetModuleHandle(L"shell32.dll");
+  if (!shell32_base) {
+    NOTREACHED();
+    return false;
+  }
+  SHQueryUserNotificationStatePtr query_user_notification_state_ptr =
+        reinterpret_cast<SHQueryUserNotificationStatePtr>
+            (::GetProcAddress(shell32_base, "SHQueryUserNotificationState"));
+  if (!query_user_notification_state_ptr) {
+    NOTREACHED();
+    return false;
+  }
+
+  QUERY_USER_NOTIFICATION_STATE state;
+  if (FAILED((*query_user_notification_state_ptr)(&state)))
+    return false;
+  return state == QUNS_RUNNING_D3D_FULL_SCREEN ||
+         state == QUNS_PRESENTATION_MODE;
+#else
+  return false;
+#endif
+}
+
+static bool IsFullScreenWindowMode() {
+  // Get the foreground window which the user is currently working on.
+  HWND wnd = ::GetForegroundWindow();
+  if (!wnd)
+    return false;
+
+  // Get the monitor where the window is located.
+  RECT wnd_rect;
+  if (!::GetWindowRect(wnd, &wnd_rect))
+    return false;
+  HMONITOR monitor = ::MonitorFromRect(&wnd_rect, MONITOR_DEFAULTTONULL);
+  if (!monitor)
+    return false;
+  MONITORINFO monitor_info = { sizeof(monitor_info) };
+  if (!::GetMonitorInfo(monitor, &monitor_info))
+    return false;
+
+  // It should be the main monitor.
+  if (!(monitor_info.dwFlags & MONITORINFOF_PRIMARY))
+    return false;
+
+  // The window should be at least as large as the monitor.
+  if (!::IntersectRect(&wnd_rect, &wnd_rect, &monitor_info.rcMonitor))
+    return false;
+  if (!::EqualRect(&wnd_rect, &monitor_info.rcMonitor))
+    return false;
+
+  // At last, the window style should not have WS_DLGFRAME and WS_THICKFRAME and
+  // its extended style should not have WS_EX_WINDOWEDGE and WS_EX_TOOLWINDOW.
+  LONG style = ::GetWindowLong(wnd, GWL_STYLE);
+  LONG ext_style = ::GetWindowLong(wnd, GWL_EXSTYLE);
+  return !((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
+           (ext_style & (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW)));
+}
+
+static bool IsFullScreenConsoleMode() {
+  // We detect this by attaching the current process to the console of the
+  // foreground window and then checking if it is in full screen mode.
+  DWORD pid = 0;
+  ::GetWindowThreadProcessId(::GetForegroundWindow(), &pid);
+  if (!pid)
+    return false;
+
+  if (!::AttachConsole(pid))
+    return false;
+
+  DWORD modes = 0;
+  ::GetConsoleDisplayMode(&modes);
+  ::FreeConsole();
+
+  return (modes & (CONSOLE_FULLSCREEN | CONSOLE_FULLSCREEN_HARDWARE)) != 0;
+}
+
+bool IsFullScreenMode() {
+  return IsPlatformFullScreenMode() ||
+         IsFullScreenWindowMode() ||
+         IsFullScreenConsoleMode();
+}
diff --git a/chrome/browser/gears_integration.cc b/chrome/browser/gears_integration.cc
index 1ab162a..648d255 100644
--- a/chrome/browser/gears_integration.cc
+++ b/chrome/browser/gears_integration.cc
@@ -16,9 +16,9 @@
 #include "chrome/common/chrome_plugin_util.h"
 #include "chrome/common/gears_api.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/codec/png_codec.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
 
 // The following 2 helpers are borrowed from the Gears codebase.
 
diff --git a/chrome/browser/gears_integration.h b/chrome/browser/gears_integration.h
index 6461377..3c20555 100644
--- a/chrome/browser/gears_integration.h
+++ b/chrome/browser/gears_integration.h
@@ -9,7 +9,7 @@
 #include "base/callback.h"
 #include "base/string16.h"
 #include "chrome/common/gears_api.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 // TODO(michaeln): Rework this interface to match how other first class
 // citizens of chrome are structured, as a GearsService with an accessor
diff --git a/chrome/browser/geolocation/access_token_store_browsertest.cc b/chrome/browser/geolocation/access_token_store_browsertest.cc
index 802d16d..4893194 100644
--- a/chrome/browser/geolocation/access_token_store_browsertest.cc
+++ b/chrome/browser/geolocation/access_token_store_browsertest.cc
@@ -11,13 +11,13 @@
 #include "chrome/test/ui_test_utils.h"
 
 namespace {
+
 // The token store factory implementation expects to be used from any well-known
 // chrome thread other than UI. We could use any arbitrary thread; IO is
 // a good choice as this is the expected usage.
 const BrowserThread::ID kExpectedClientThreadId = BrowserThread::IO;
 const char* kRefServerUrl1 = "https://test.domain.example/foo?id=bar.bar";
 const char* kRefServerUrl2 = "http://another.domain.example/foo?id=bar.bar#2";
-}  // namespace
 
 class GeolocationAccessTokenStoreTest
     : public InProcessBrowserTest {
@@ -149,3 +149,5 @@
           RunCancelTestInClientTread));
   ui_test_utils::RunMessageLoop();
 }
+
+}  // namespace
diff --git a/chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h b/chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h
new file mode 100644
index 0000000..1f9ae75
--- /dev/null
+++ b/chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GEOLOCATION_ARBITRATOR_DEPENDENCY_FACTORIES_FOR_TEST_H_
+#define CHROME_BROWSER_GEOLOCATION_ARBITRATOR_DEPENDENCY_FACTORIES_FOR_TEST_H_
+#pragma once
+
+#include "chrome/browser/geolocation/arbitrator_dependency_factory.h"
+
+class GeolocationArbitratorDependencyFactoryWithLocationProvider
+    : public DefaultGeolocationArbitratorDependencyFactory {
+ public:
+  typedef LocationProviderBase* (*LocationProviderFactoryFunction)(void);
+
+  GeolocationArbitratorDependencyFactoryWithLocationProvider(
+      LocationProviderFactoryFunction factory_function)
+      : factory_function_(factory_function) {
+  }
+
+  virtual LocationProviderBase* NewNetworkLocationProvider(
+      AccessTokenStore* access_token_store,
+      URLRequestContextGetter* context,
+      const GURL& url,
+      const string16& access_token) {
+    return factory_function_();
+  }
+
+  virtual LocationProviderBase* NewSystemLocationProvider() {
+    return NULL;
+  }
+
+ protected:
+  LocationProviderFactoryFunction factory_function_;
+};
+
+
+#endif  // CHROME_BROWSER_GEOLOCATION_ARBITRATOR_DEPENDENCY_FACTORIES_FOR_TEST_H_
diff --git a/chrome/browser/geolocation/arbitrator_dependency_factory.cc b/chrome/browser/geolocation/arbitrator_dependency_factory.cc
new file mode 100644
index 0000000..eeea56f
--- /dev/null
+++ b/chrome/browser/geolocation/arbitrator_dependency_factory.cc
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/geolocation/arbitrator_dependency_factory.h"
+
+#include "chrome/browser/geolocation/access_token_store.h"
+#include "chrome/browser/geolocation/location_provider.h"
+#include "chrome/browser/profiles/profile.h"
+
+// GeolocationArbitratorDependencyFactory
+GeolocationArbitratorDependencyFactory::
+~GeolocationArbitratorDependencyFactory() {
+}
+
+// DefaultGeolocationArbitratorDependencyFactory
+URLRequestContextGetter*
+DefaultGeolocationArbitratorDependencyFactory::GetContextGetter() {
+  return Profile::GetDefaultRequestContext();
+}
+
+DefaultGeolocationArbitratorDependencyFactory::GetTimeNow
+DefaultGeolocationArbitratorDependencyFactory::GetTimeFunction() {
+  return base::Time::Now;
+}
+
+AccessTokenStore*
+DefaultGeolocationArbitratorDependencyFactory::NewAccessTokenStore() {
+  return NewChromePrefsAccessTokenStore();
+}
+
+LocationProviderBase*
+DefaultGeolocationArbitratorDependencyFactory::NewNetworkLocationProvider(
+    AccessTokenStore* access_token_store,
+    URLRequestContextGetter* context,
+    const GURL& url,
+    const string16& access_token) {
+  return ::NewNetworkLocationProvider(access_token_store, context,
+                                      url, access_token);
+}
+
+LocationProviderBase*
+DefaultGeolocationArbitratorDependencyFactory::NewSystemLocationProvider() {
+  return ::NewSystemLocationProvider();
+}
+
diff --git a/chrome/browser/geolocation/arbitrator_dependency_factory.h b/chrome/browser/geolocation/arbitrator_dependency_factory.h
new file mode 100644
index 0000000..4c7580e
--- /dev/null
+++ b/chrome/browser/geolocation/arbitrator_dependency_factory.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_GEOLOCATION_ARBITRATOR_DEPENDENCY_FACTORY_H_
+#define CHROME_BROWSER_GEOLOCATION_ARBITRATOR_DEPENDENCY_FACTORY_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/string16.h"
+
+class AccessTokenStore;
+class GURL;
+class LocationProviderBase;
+class URLRequestContextGetter;
+
+namespace base {
+class Time;
+}
+
+// Allows injection of factory methods for creating the location providers.
+// RefCounted for simplicity of writing tests.
+class GeolocationArbitratorDependencyFactory
+    : public base::RefCounted<GeolocationArbitratorDependencyFactory> {
+ public:
+  // Defines a function that returns the current time.
+  typedef base::Time (*GetTimeNow)();
+
+  virtual GetTimeNow GetTimeFunction() = 0;
+  virtual URLRequestContextGetter* GetContextGetter() = 0;
+  virtual AccessTokenStore* NewAccessTokenStore() = 0;
+  virtual LocationProviderBase* NewNetworkLocationProvider(
+      AccessTokenStore* access_token_store,
+      URLRequestContextGetter* context,
+      const GURL& url,
+      const string16& access_token) = 0;
+  virtual LocationProviderBase* NewSystemLocationProvider() = 0;
+
+ protected:
+  friend class base::RefCounted<GeolocationArbitratorDependencyFactory>;
+  virtual ~GeolocationArbitratorDependencyFactory();
+};
+
+// The default dependency factory, exposed so that it is possible
+// to override only certain parts (e.g. the location providers).
+class DefaultGeolocationArbitratorDependencyFactory
+    : public GeolocationArbitratorDependencyFactory {
+ public:
+  // GeolocationArbitratorDependencyFactory
+  virtual URLRequestContextGetter* GetContextGetter();
+  virtual GetTimeNow GetTimeFunction();
+  virtual AccessTokenStore* NewAccessTokenStore();
+  virtual LocationProviderBase* NewNetworkLocationProvider(
+      AccessTokenStore* access_token_store,
+      URLRequestContextGetter* context,
+      const GURL& url,
+      const string16& access_token);
+  virtual LocationProviderBase* NewSystemLocationProvider();
+};
+
+#endif  // CHROME_BROWSER_GEOLOCATION_ARBITRATOR_DEPENDENCY_FACTORY_H_
diff --git a/chrome/browser/geolocation/device_data_provider_unittest.cc b/chrome/browser/geolocation/device_data_provider_unittest.cc
index a361fc6..b4d4ac6 100644
--- a/chrome/browser/geolocation/device_data_provider_unittest.cc
+++ b/chrome/browser/geolocation/device_data_provider_unittest.cc
@@ -9,6 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
+
 class NullWifiDataListenerInterface
     : public WifiDataProviderCommon::ListenerInterface {
  public:
@@ -16,7 +17,6 @@
   virtual void DeviceDataUpdateAvailable(
       DeviceDataProvider<WifiData>* provider) {}
 };
-}
 
 TEST(GeolocationDeviceDataProviderWifiData, CreateDestroy) {
   // See http://crbug.com/59913 .  The main_message_loop is not required to be
@@ -38,3 +38,5 @@
     }
   }
 }
+
+}  // namespace
diff --git a/chrome/browser/geolocation/fake_access_token_store.cc b/chrome/browser/geolocation/fake_access_token_store.cc
new file mode 100644
index 0000000..1865436
--- /dev/null
+++ b/chrome/browser/geolocation/fake_access_token_store.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/geolocation/fake_access_token_store.h"
+
+FakeAccessTokenStore::FakeAccessTokenStore() {}
+
+void FakeAccessTokenStore::NotifyDelegateTokensLoaded() {
+  CHECK(request_ != NULL);
+  request_->ForwardResult(MakeTuple(access_token_set_));
+  request_ = NULL;
+}
+
+void FakeAccessTokenStore::DoLoadAccessTokens(
+    scoped_refptr<CancelableRequest<LoadAccessTokensCallbackType> > request) {
+  DCHECK(request_ == NULL)
+      << "Fake token store currently only allows one request at a time";
+  request_ = request;
+}
+
+void FakeAccessTokenStore::SaveAccessToken(
+    const GURL& server_url, const string16& access_token) {
+  DCHECK(server_url.is_valid());
+  access_token_set_[server_url] = access_token;
+}
+
+FakeAccessTokenStore::~FakeAccessTokenStore() {}
diff --git a/chrome/browser/geolocation/fake_access_token_store.h b/chrome/browser/geolocation/fake_access_token_store.h
index 5c68267..8a4a9f6 100644
--- a/chrome/browser/geolocation/fake_access_token_store.h
+++ b/chrome/browser/geolocation/fake_access_token_store.h
@@ -12,32 +12,21 @@
 // A fake (non-persisted) access token store instance useful for testing.
 class FakeAccessTokenStore : public AccessTokenStore {
  public:
-  FakeAccessTokenStore() {}
+  FakeAccessTokenStore();
 
-  void NotifyDelegateTokensLoaded() {
-    CHECK(request_ != NULL);
-    request_->ForwardResult(MakeTuple(access_token_set_));
-    request_ = NULL;
-  }
+  void NotifyDelegateTokensLoaded();
 
   // AccessTokenStore
   virtual void DoLoadAccessTokens(
-      scoped_refptr<CancelableRequest<LoadAccessTokensCallbackType> > request) {
-    DCHECK(request_ == NULL)
-        << "Fake token store currently only allows one request at a time";
-    request_ = request;
-  }
+      scoped_refptr<CancelableRequest<LoadAccessTokensCallbackType> > request);
   virtual void SaveAccessToken(
-      const GURL& server_url, const string16& access_token) {
-    DCHECK(server_url.is_valid());
-    access_token_set_[server_url] = access_token;
-  }
+      const GURL& server_url, const string16& access_token);
 
   AccessTokenSet access_token_set_;
   scoped_refptr<CancelableRequest<LoadAccessTokensCallbackType> > request_;
 
  private:
-  virtual ~FakeAccessTokenStore() {}
+  virtual ~FakeAccessTokenStore();
 
   DISALLOW_COPY_AND_ASSIGN(FakeAccessTokenStore);
 };
diff --git a/chrome/browser/geolocation/gateway_data_provider_common.cc b/chrome/browser/geolocation/gateway_data_provider_common.cc
index 363967c..2289371 100644
--- a/chrome/browser/geolocation/gateway_data_provider_common.cc
+++ b/chrome/browser/geolocation/gateway_data_provider_common.cc
@@ -32,7 +32,7 @@
 bool GatewayDataProviderCommon::GetData(GatewayData *data) {
   DCHECK(CalledOnClientThread());
   DCHECK(data);
-  AutoLock lock(data_mutex_);
+  base::AutoLock lock(data_mutex_);
   *data = gateway_data_;
   // If we've successfully completed a scan, indicate that we have all of the
   // data we can get.
@@ -67,7 +67,7 @@
     ScheduleNextScan(polling_policy_->NoRouterInterval());
   } else {
     {
-      AutoLock lock(data_mutex_);
+      base::AutoLock lock(data_mutex_);
       update_available = gateway_data_.DiffersSignificantly(new_data);
       gateway_data_ = new_data;
     }
diff --git a/chrome/browser/geolocation/gateway_data_provider_common.h b/chrome/browser/geolocation/gateway_data_provider_common.h
index cc1c85a..ba0eb58 100644
--- a/chrome/browser/geolocation/gateway_data_provider_common.h
+++ b/chrome/browser/geolocation/gateway_data_provider_common.h
@@ -83,7 +83,7 @@
   // Will schedule a scan; i.e. enqueue DoRouterScanTask deferred task.
   void ScheduleNextScan(int interval);
 
-  Lock data_mutex_;
+  base::Lock data_mutex_;
   // Whether we've successfully completed a scan for gateway data (or the
   // polling thread has terminated early).
   bool is_first_scan_complete_;
diff --git a/chrome/browser/geolocation/gateway_data_provider_common_unittest.cc b/chrome/browser/geolocation/gateway_data_provider_common_unittest.cc
index 1f8b072..cc7b83f 100644
--- a/chrome/browser/geolocation/gateway_data_provider_common_unittest.cc
+++ b/chrome/browser/geolocation/gateway_data_provider_common_unittest.cc
@@ -17,6 +17,8 @@
 using testing::Invoke;
 using testing::Return;
 
+namespace {
+
 class MockGatewayApi : public GatewayDataProviderCommon::GatewayApiInterface {
  public:
   MockGatewayApi() {
@@ -185,3 +187,5 @@
   EXPECT_EQ(1, static_cast<int>(data.router_data.size()));
   EXPECT_EQ(single_router.mac_address, data.router_data.begin()->mac_address);
 }
+
+}  // namespace
diff --git a/chrome/browser/geolocation/gateway_data_provider_linux.cc b/chrome/browser/geolocation/gateway_data_provider_linux.cc
index f1779cb..e8f8cf4 100644
--- a/chrome/browser/geolocation/gateway_data_provider_linux.cc
+++ b/chrome/browser/geolocation/gateway_data_provider_linux.cc
@@ -40,9 +40,10 @@
   if (hex_address.size() != 8)
     return "";
   std::vector<uint8> bytes;
-  base::HexStringToBytes(hex_address, &bytes);
-  if (bytes.size() != 4)
+  if (!base::HexStringToBytes(hex_address, &bytes) ||
+      bytes.size() != 4) {
     return "";
+  }
   struct in_addr in;
   uint32 ip_native_endian;
   memcpy(&ip_native_endian, &bytes[0], 4);
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
index 2696850..d31ba67 100644
--- a/chrome/browser/geolocation/geolocation_browsertest.cc
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/dom_operation_notification_details.h"
+#include "chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h"
 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
 #include "chrome/browser/geolocation/geolocation_settings_state.h"
 #include "chrome/browser/geolocation/location_arbitrator.h"
@@ -27,6 +28,8 @@
 #include "net/base/net_util.h"
 #include "net/test/test_server.h"
 
+namespace {
+
 // Used to block until an iframe is loaded via a javascript call.
 // Note: NavigateToURLBlockUntilNavigationsComplete doesn't seem to work for
 // multiple embedded iframes, as notifications seem to be 'batched'. Instead, we
@@ -48,7 +51,7 @@
         iframe_id,
         url.spec().c_str());
     browser->GetSelectedTabContents()->render_view_host()->
-        ExecuteJavascriptInWebFrame(L"", UTF8ToWide(script));
+        ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(script));
     ui_test_utils::RunMessageLoop();
 
     EXPECT_EQ(StringPrintf("\"%d\"", iframe_id), javascript_response_);
@@ -127,8 +130,8 @@
     std::string script =
         "window.domAutomationController.setAutomationId(0);"
         "window.domAutomationController.send(geoStart());";
-    render_view_host->ExecuteJavascriptInWebFrame(iframe_xpath,
-                                                  UTF8ToWide(script));
+    render_view_host->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath),
+                                                  UTF8ToUTF16(script));
     ui_test_utils::RunMessageLoop();
     registrar_.RemoveAll();
     LOG(WARNING) << "got geolocation watch" << javascript_response_;
@@ -199,10 +202,25 @@
     : infobar_(NULL),
       current_browser_(NULL),
       html_for_tests_("files/geolocation/simple.html"),
-      started_test_server_(false) {
+      started_test_server_(false),
+      dependency_factory_(
+          new GeolocationArbitratorDependencyFactoryWithLocationProvider(
+              &NewAutoSuccessMockNetworkLocationProvider)) {
     EnableDOMAutomation();
   }
 
+  // InProcessBrowserTest
+  virtual void SetUpInProcessBrowserTestFixture() {
+    GeolocationArbitrator::SetDependencyFactoryForTest(
+        dependency_factory_.get());
+  }
+
+  // InProcessBrowserTest
+  virtual void TearDownInProcessBrowserTestFixture() {
+    LOG(WARNING) << "TearDownInProcessBrowserTestFixture. Test Finished.";
+    GeolocationArbitrator::SetDependencyFactoryForTest(NULL);
+  }
+
   enum InitializationOptions {
     INITIALIZATION_NONE,
     INITIALIZATION_OFFTHERECORD,
@@ -211,9 +229,6 @@
   };
 
   bool Initialize(InitializationOptions options) WARN_UNUSED_RESULT {
-    GeolocationArbitrator::SetProviderFactoryForTest(
-        &NewAutoSuccessMockNetworkLocationProvider);
-
     if (!started_test_server_)
       started_test_server_ = test_server()->Start();
     EXPECT_TRUE(started_test_server_);
@@ -234,11 +249,6 @@
     } else if (options == INITIALIZATION_IFRAMES) {
       current_browser_ = browser();
       ui_test_utils::NavigateToURL(current_browser_, current_url_);
-      IFrameLoader iframe0(current_browser_, 0, GURL());
-      iframe0_url_ = iframe0.iframe_url();
-
-      IFrameLoader iframe1(current_browser_, 1, GURL());
-      iframe1_url_ = iframe1.iframe_url();
     } else {
       current_browser_ = browser();
       ui_test_utils::NavigateToURL(current_browser_, current_url_);
@@ -252,6 +262,16 @@
     return true;
   }
 
+  void LoadIFrames(int number_iframes) {
+      // Limit to 3 iframes.
+      DCHECK(0 < number_iframes && number_iframes <= 3);
+      iframe_urls_.resize(number_iframes);
+      for (int i = 0; i < number_iframes; ++i) {
+        IFrameLoader loader(current_browser_, i, GURL());
+        iframe_urls_[i] = loader.iframe_url();
+      }
+  }
+
   void AddGeolocationWatch(bool wait_for_infobar) {
     GeolocationNotificationObserver notification_observer(wait_for_infobar);
     notification_observer.AddWatchAndWaitForNotification(
@@ -337,11 +357,6 @@
         expected, function, current_browser_->GetSelectedTabContents());
   }
 
-  // InProcessBrowserTest
-  virtual void TearDownInProcessBrowserTestFixture() {
-    LOG(WARNING) << "TearDownInProcessBrowserTestFixture. Test Finished.";
-  }
-
   InfoBarDelegate* infobar_;
   Browser* current_browser_;
   // path element of a URL referencing the html content for this test.
@@ -351,13 +366,13 @@
   std::wstring iframe_xpath_;
   // The current url for the top level page.
   GURL current_url_;
-  // If not empty, the GURL for the first iframe.
-  GURL iframe0_url_;
-  // If not empty, the GURL for the second iframe.
-  GURL iframe1_url_;
+  // If not empty, the GURLs for the iframes loaded by LoadIFrames().
+  std::vector<GURL> iframe_urls_;
 
   // TODO(phajdan.jr): Remove after we can ask TestServer whether it is started.
   bool started_test_server_;
+
+  scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory_;
 };
 
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DisplaysPermissionBar) {
@@ -372,7 +387,9 @@
   CheckGeoposition(MockLocationProvider::instance_->position_);
 }
 
-IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, ErrorOnPermissionDenied) {
+// Crashy, http://crbug.com/70585.
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest,
+                       DISABLED_ErrorOnPermissionDenied) {
   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
   AddGeolocationWatch(true);
   // Infobar was displayed, deny access and check for error code.
@@ -445,11 +462,12 @@
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, IFramesWithFreshPosition) {
   html_for_tests_ = "files/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
+  LoadIFrames(2);
   LOG(WARNING) << "frames loaded";
 
   iframe_xpath_ = L"//iframe[@id='iframe_0']";
   AddGeolocationWatch(true);
-  SetInfobarResponse(iframe0_url_, true);
+  SetInfobarResponse(iframe_urls_[0], true);
   CheckGeoposition(MockLocationProvider::instance_->position_);
   // Disables further prompts from this iframe.
   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
@@ -475,7 +493,7 @@
   // Now go ahead an authorize the second frame.
   iframe_xpath_ = L"//iframe[@id='iframe_1']";
   // Infobar was displayed, allow access and check there's no error code.
-  SetInfobarResponse(iframe1_url_, true);
+  SetInfobarResponse(iframe_urls_[1], true);
   LOG(WARNING) << "Checking position...";
   CheckGeoposition(fresh_position);
   LOG(WARNING) << "...done.";
@@ -484,10 +502,11 @@
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, IFramesWithCachedPosition) {
   html_for_tests_ = "files/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
+  LoadIFrames(2);
 
   iframe_xpath_ = L"//iframe[@id='iframe_0']";
   AddGeolocationWatch(true);
-  SetInfobarResponse(iframe0_url_, true);
+  SetInfobarResponse(iframe_urls_[0], true);
   CheckGeoposition(MockLocationProvider::instance_->position_);
 
   // Refresh geoposition, but let's not yet create the watch on the second frame
@@ -509,7 +528,7 @@
   // afterwards. We're only interested in the first navigation for the success
   // callback from the cached position.
   CheckStringValueFromJavascript("1", "geoSetMaxNavigateCount(1)");
-  SetInfobarResponse(iframe1_url_, true);
+  SetInfobarResponse(iframe_urls_[1], true);
   CheckGeoposition(cached_position);
 }
 
@@ -518,11 +537,12 @@
                        DISABLED_CancelPermissionForFrame) {
   html_for_tests_ = "files/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
+  LoadIFrames(2);
   LOG(WARNING) << "frames loaded";
 
   iframe_xpath_ = L"//iframe[@id='iframe_0']";
   AddGeolocationWatch(true);
-  SetInfobarResponse(iframe0_url_, true);
+  SetInfobarResponse(iframe_urls_[0], true);
   CheckGeoposition(MockLocationProvider::instance_->position_);
   // Disables further prompts from this iframe.
   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
@@ -532,12 +552,12 @@
   iframe_xpath_ = L"//iframe[@id='iframe_1']";
   AddGeolocationWatch(true);
 
-  int num_infobars_before_cancel =
-      current_browser_->GetSelectedTabContents()->infobar_delegate_count();
+  size_t num_infobars_before_cancel =
+      current_browser_->GetSelectedTabContents()->infobar_count();
   // Change the iframe, and ensure the infobar is gone.
   IFrameLoader change_iframe_1(current_browser_, 1, current_url_);
-  int num_infobars_after_cancel =
-      current_browser_->GetSelectedTabContents()->infobar_delegate_count();
+  size_t num_infobars_after_cancel =
+      current_browser_->GetSelectedTabContents()->infobar_count();
   EXPECT_EQ(num_infobars_before_cancel, num_infobars_after_cancel + 1);
 }
 
@@ -557,6 +577,7 @@
   // See http://crbug.com/42789
   html_for_tests_ = "files/geolocation/iframes_different_origin.html";
   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
+  LoadIFrames(2);
   LOG(WARNING) << "frames loaded";
 
   // Access navigator.geolocation, but ensure it won't request permission.
@@ -565,14 +586,14 @@
 
   iframe_xpath_ = L"//iframe[@id='iframe_0']";
   AddGeolocationWatch(true);
-  SetInfobarResponse(iframe0_url_, true);
+  SetInfobarResponse(iframe_urls_[0], true);
   CheckGeoposition(MockLocationProvider::instance_->position_);
   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
 
   // Permission should be requested after adding a watch.
   iframe_xpath_ = L"//iframe[@id='iframe_1']";
   AddGeolocationWatch(true);
-  SetInfobarResponse(iframe1_url_, true);
+  SetInfobarResponse(iframe_urls_[1], true);
   CheckGeoposition(MockLocationProvider::instance_->position_);
 }
 
@@ -601,3 +622,30 @@
   WaitForNavigation();
   CheckGeoposition(final_position);
 }
+
+// Hangs flakily, http://crbug.com/70588.
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DISABLED_TabDestroyed) {
+  html_for_tests_ = "files/geolocation/tab_destroyed.html";
+  ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
+  LoadIFrames(3);
+
+  iframe_xpath_ = L"//iframe[@id='iframe_0']";
+  AddGeolocationWatch(true);
+
+  iframe_xpath_ = L"//iframe[@id='iframe_1']";
+  AddGeolocationWatch(false);
+
+  iframe_xpath_ = L"//iframe[@id='iframe_2']";
+  AddGeolocationWatch(false);
+
+  std::string script =
+      "window.domAutomationController.setAutomationId(0);"
+      "window.domAutomationController.send(window.close());";
+  bool result =
+      ui_test_utils::ExecuteJavaScript(
+      current_browser_->GetSelectedTabContents()->render_view_host(),
+      L"", UTF8ToWide(script));
+  EXPECT_EQ(result, true);
+}
+
+}  // namespace
diff --git a/chrome/browser/geolocation/geolocation_exceptions_table_model.cc b/chrome/browser/geolocation/geolocation_exceptions_table_model.cc
index 9bd57fe..df32cb7 100644
--- a/chrome/browser/geolocation/geolocation_exceptions_table_model.cc
+++ b/chrome/browser/geolocation/geolocation_exceptions_table_model.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_collator.h"
-#include "app/table_model_observer.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/content_settings_helper.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_collator.h"
+#include "ui/base/models/table_model_observer.h"
 
 namespace {
 // Return -1, 0, or 1 depending on whether |origin1| should be sorted before,
@@ -180,7 +180,7 @@
 }
 
 void GeolocationExceptionsTableModel::SetObserver(
-    TableModelObserver* observer) {
+    ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
diff --git a/chrome/browser/geolocation/geolocation_exceptions_table_model.h b/chrome/browser/geolocation/geolocation_exceptions_table_model.h
index d1223e6..0617b46 100644
--- a/chrome/browser/geolocation/geolocation_exceptions_table_model.h
+++ b/chrome/browser/geolocation/geolocation_exceptions_table_model.h
@@ -40,7 +40,7 @@
   // TableModel overrides:
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
   virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE;
 
  private:
@@ -54,7 +54,7 @@
   typedef std::vector<Entry> EntriesVector;
   EntriesVector entries_;
 
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(GeolocationExceptionsTableModel);
 };
diff --git a/chrome/browser/geolocation/geolocation_exceptions_table_model_unittest.cc b/chrome/browser/geolocation/geolocation_exceptions_table_model_unittest.cc
index 301a7b2..5dd18a1 100644
--- a/chrome/browser/geolocation/geolocation_exceptions_table_model_unittest.cc
+++ b/chrome/browser/geolocation/geolocation_exceptions_table_model_unittest.cc
@@ -15,7 +15,6 @@
 const GURL kUrl0("http://www.example.com");
 const GURL kUrl1("http://www.example1.com");
 const GURL kUrl2("http://www.example2.com");
-}  // namespace
 
 class GeolocationExceptionsTableModelTest : public RenderViewHostTestHarness {
  public:
@@ -141,3 +140,5 @@
   EXPECT_NE(string16::npos,
             text.find(content_settings_helper::OriginToString16(kUrl2)));
 }
+
+}  // namespace
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc
index 76bc3d7..e642fda 100644
--- a/chrome/browser/geolocation/geolocation_permission_context.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context.cc
@@ -1,11 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/geolocation/geolocation_permission_context.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include <functional>
+#include <string>
+#include <vector>
+
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -20,25 +22,20 @@
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
-namespace {
-
-const char kGeolocationLearnMoreUrl[] =
-#if defined(OS_CHROMEOS)
-    "http://www.google.com/support/chromeos/bin/answer.py?answer=142065";
-#else
-    "http://www.google.com/support/chrome/bin/answer.py?answer=142065";
-#endif
-
-}  // namespace
+// GeolocationInfoBarQueueController ------------------------------------------
 
 // This class controls the geolocation infobar queue per profile, and it's an
 // internal class to GeolocationPermissionContext.
@@ -48,7 +45,7 @@
 // things listening for such notifications.
 // For the time being this class is self-contained and it doesn't seem pulling
 // the notification infrastructure would simplify.
-class GeolocationInfoBarQueueController {
+class GeolocationInfoBarQueueController : NotificationObserver {
  public:
   GeolocationInfoBarQueueController(
       GeolocationPermissionContext* geolocation_permission_context,
@@ -57,113 +54,87 @@
 
   // The InfoBar will be displayed immediately if the tab is not already
   // displaying one, otherwise it'll be queued.
-  void CreateInfoBarRequest(
-      int render_process_id, int render_view_id, int bridge_id,
-      const GURL& requesting_frame, const GURL& emebedder);
+  void CreateInfoBarRequest(int render_process_id,
+                            int render_view_id,
+                            int bridge_id,
+                            const GURL& requesting_frame,
+                            const GURL& emebedder);
 
   // Cancels a specific infobar request.
-  void CancelInfoBarRequest(
-      int render_process_id, int render_view_id, int bridge_id);
+  void CancelInfoBarRequest(int render_process_id,
+                            int render_view_id,
+                            int bridge_id);
 
   // Called by the InfoBarDelegate to notify it's closed. It'll display a new
   // InfoBar if there's any request pending for this tab.
-  void OnInfoBarClosed(
-      int render_process_id, int render_view_id, int bridge_id);
+  void OnInfoBarClosed(int render_process_id,
+                       int render_view_id,
+                       int bridge_id);
 
   // Called by the InfoBarDelegate to notify permission has been set.
   // It'll notify and dismiss any other pending InfoBar request for the same
   // |requesting_frame| and embedder.
-  void OnPermissionSet(
-      int render_process_id, int render_view_id, int bridge_id,
-      const GURL& requesting_frame, const GURL& embedder, bool allowed);
+  void OnPermissionSet(int render_process_id,
+                       int render_view_id,
+                       int bridge_id,
+                       const GURL& requesting_frame,
+                       const GURL& embedder,
+                       bool allowed);
+
+  // NotificationObserver
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
 
  private:
   struct PendingInfoBarRequest;
+  class RequestEquals;
+
   typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests;
 
   // Shows the first pending infobar for this tab.
   void ShowQueuedInfoBar(int render_process_id, int render_view_id);
 
   // Cancels an InfoBar request and returns the next iterator position.
-  std::vector<PendingInfoBarRequest>::iterator CancelInfoBarRequestInternal(
-      std::vector<PendingInfoBarRequest>::iterator i);
+  PendingInfoBarRequests::iterator CancelInfoBarRequestInternal(
+      PendingInfoBarRequests::iterator i);
+
+  NotificationRegistrar registrar_;
 
   GeolocationPermissionContext* const geolocation_permission_context_;
   Profile* const profile_;
-  // Contains all pending infobar requests.
   PendingInfoBarRequests pending_infobar_requests_;
 };
 
+
+// GeolocationConfirmInfoBarDelegate ------------------------------------------
+
 namespace {
 
-// This is the delegate used to display the confirmation info bar.
 class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   GeolocationConfirmInfoBarDelegate(
-      TabContents* tab_contents, GeolocationInfoBarQueueController* controller,
-      int render_process_id, int render_view_id, int bridge_id,
+      TabContents* tab_contents,
+      GeolocationInfoBarQueueController* controller,
+      int render_process_id,
+      int render_view_id,
+      int bridge_id,
       const GURL& requesting_frame_url,
-      const std::string& display_languages)
-      : ConfirmInfoBarDelegate(tab_contents),
-        tab_contents_(tab_contents),
-        controller_(controller),
-        render_process_id_(render_process_id),
-        render_view_id_(render_view_id),
-        bridge_id_(bridge_id),
-        requesting_frame_url_(requesting_frame_url),
-        display_languages_(display_languages) {
-  }
-
-  // ConfirmInfoBarDelegate
-  virtual void InfoBarClosed() {
-    controller_->OnInfoBarClosed(render_process_id_, render_view_id_,
-                                 bridge_id_);
-    delete this;
-  }
-  virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
-  virtual bool Accept() { return OnPermissionSet(true); }
-  virtual bool Cancel() { return OnPermissionSet(false); }
-  virtual int GetButtons() const { return BUTTON_OK | BUTTON_CANCEL; }
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    switch (button) {
-      case BUTTON_OK:
-        return l10n_util::GetStringUTF16(IDS_GEOLOCATION_ALLOW_BUTTON);
-      case BUTTON_CANCEL:
-        return l10n_util::GetStringUTF16(IDS_GEOLOCATION_DENY_BUTTON);
-      default:
-        // All buttons are labeled above.
-        NOTREACHED() << "Bad button id " << button;
-        return string16();
-    }
-  }
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringFUTF16(
-        IDS_GEOLOCATION_INFOBAR_QUESTION,
-        net::FormatUrl(requesting_frame_url_.GetOrigin(), display_languages_));
-  }
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-        IDR_GEOLOCATION_INFOBAR_ICON);
-  }
-  virtual string16 GetLinkText() {
-    return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-  }
-  virtual bool LinkClicked(WindowOpenDisposition disposition) {
-    GURL learn_more_url =
-        google_util::AppendGoogleLocaleParam(GURL(kGeolocationLearnMoreUrl));
-    // Ignore the click disposition and always open in a new top level tab.
-    tab_contents_->OpenURL(
-        learn_more_url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
-    return false;  // Do not dismiss the info bar.
-  }
+      const std::string& display_languages);
 
  private:
-  bool OnPermissionSet(bool confirm) {
-    controller_->OnPermissionSet(
-        render_process_id_, render_view_id_, bridge_id_, requesting_frame_url_,
-        tab_contents_->GetURL(), confirm);
-    return true;
-  }
+  virtual ~GeolocationConfirmInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+  virtual string16 GetLinkText();
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
 
   TabContents* tab_contents_;
   GeolocationInfoBarQueueController* controller_;
@@ -176,35 +147,183 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(GeolocationConfirmInfoBarDelegate);
 };
 
+GeolocationConfirmInfoBarDelegate::GeolocationConfirmInfoBarDelegate(
+    TabContents* tab_contents,
+    GeolocationInfoBarQueueController* controller,
+    int render_process_id,
+    int render_view_id,
+    int bridge_id,
+    const GURL& requesting_frame_url,
+    const std::string& display_languages)
+    : ConfirmInfoBarDelegate(tab_contents),
+      tab_contents_(tab_contents),
+      controller_(controller),
+      render_process_id_(render_process_id),
+      render_view_id_(render_view_id),
+      bridge_id_(bridge_id),
+      requesting_frame_url_(requesting_frame_url),
+      display_languages_(display_languages) {
+}
+
+GeolocationConfirmInfoBarDelegate::~GeolocationConfirmInfoBarDelegate() {
+}
+
+void GeolocationConfirmInfoBarDelegate::InfoBarClosed() {
+  controller_->OnInfoBarClosed(render_process_id_, render_view_id_,
+                               bridge_id_);
+  delete this;
+}
+
+SkBitmap* GeolocationConfirmInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_GEOLOCATION_INFOBAR_ICON);
+}
+
+InfoBarDelegate::Type
+    GeolocationConfirmInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+string16 GeolocationConfirmInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_GEOLOCATION_INFOBAR_QUESTION,
+      net::FormatUrl(requesting_frame_url_.GetOrigin(), display_languages_));
+}
+
+string16 GeolocationConfirmInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_GEOLOCATION_ALLOW_BUTTON : IDS_GEOLOCATION_DENY_BUTTON);
+}
+
+bool GeolocationConfirmInfoBarDelegate::Accept() {
+  controller_->OnPermissionSet(render_process_id_, render_view_id_, bridge_id_,
+      requesting_frame_url_, tab_contents_->GetURL(), true);
+  return true;
+}
+
+bool GeolocationConfirmInfoBarDelegate::Cancel() {
+  controller_->OnPermissionSet(render_process_id_, render_view_id_, bridge_id_,
+      requesting_frame_url_, tab_contents_->GetURL(), false);
+  return true;
+}
+
+string16 GeolocationConfirmInfoBarDelegate::GetLinkText() {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+bool GeolocationConfirmInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  const char kGeolocationLearnMoreUrl[] =
+#if defined(OS_CHROMEOS)
+      "http://www.google.com/support/chromeos/bin/answer.py?answer=142065";
+#else
+      "http://www.google.com/support/chrome/bin/answer.py?answer=142065";
+#endif
+
+  // Ignore the click disposition and always open in a new top level tab.
+  tab_contents_->OpenURL(
+      google_util::AppendGoogleLocaleParam(GURL(kGeolocationLearnMoreUrl)),
+      GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+  return false;  // Do not dismiss the info bar.
+}
+
 }  // namespace
 
+
+// GeolocationInfoBarQueueController::PendingInfoBarRequest -------------------
+
 struct GeolocationInfoBarQueueController::PendingInfoBarRequest {
+ public:
+  PendingInfoBarRequest(int render_process_id,
+                        int render_view_id,
+                        int bridge_id,
+                        GURL requesting_frame,
+                        GURL embedder);
+
+  bool IsForTab(int p_render_process_id, int p_render_view_id) const;
+  bool IsForPair(const GURL& p_requesting_frame,
+                 const GURL& p_embedder) const;
+  bool Equals(int p_render_process_id,
+              int p_render_view_id,
+              int p_bridge_id) const;
+
   int render_process_id;
   int render_view_id;
   int bridge_id;
   GURL requesting_frame;
   GURL embedder;
-  // If non-NULL, it's the current geolocation infobar for this tab.
   InfoBarDelegate* infobar_delegate;
-
-  bool IsForTab(int p_render_process_id, int p_render_view_id) const {
-    return render_process_id == p_render_process_id &&
-           render_view_id == p_render_view_id;
-  }
-
-  bool IsForPair(const GURL& p_requesting_frame, const GURL& p_embedder) const {
-    return requesting_frame == p_requesting_frame &&
-           embedder == p_embedder;
-  }
-
-  bool Equals(int p_render_process_id,
-              int p_render_view_id,
-              int p_bridge_id) const {
-    return IsForTab(p_render_process_id, p_render_view_id) &&
-           bridge_id == p_bridge_id;
-  }
 };
 
+GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
+    int render_process_id,
+    int render_view_id,
+    int bridge_id,
+    GURL requesting_frame,
+    GURL embedder)
+    : render_process_id(render_process_id),
+      render_view_id(render_view_id),
+      bridge_id(bridge_id),
+      requesting_frame(requesting_frame),
+      embedder(embedder),
+      infobar_delegate(NULL) {
+}
+
+bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForTab(
+    int p_render_process_id,
+    int p_render_view_id) const {
+  return (render_process_id == p_render_process_id) &&
+      (render_view_id == p_render_view_id);
+}
+
+bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair(
+    const GURL& p_requesting_frame,
+    const GURL& p_embedder) const {
+  return (requesting_frame == p_requesting_frame) && (embedder == p_embedder);
+}
+
+bool GeolocationInfoBarQueueController::PendingInfoBarRequest::Equals(
+    int p_render_process_id,
+    int p_render_view_id,
+    int p_bridge_id) const {
+  return IsForTab(p_render_process_id, p_render_view_id) &&
+     (bridge_id == p_bridge_id);
+}
+
+
+// GeolocationInfoBarQueueController::RequestEquals ---------------------------
+
+// Useful predicate for checking PendingInfoBarRequest equality.
+class GeolocationInfoBarQueueController::RequestEquals
+    : public std::unary_function<PendingInfoBarRequest, bool> {
+ public:
+  RequestEquals(int render_process_id, int render_view_id, int bridge_id);
+
+  bool operator()(const PendingInfoBarRequest& request) const;
+
+ private:
+  int render_process_id_;
+  int render_view_id_;
+  int bridge_id_;
+};
+
+GeolocationInfoBarQueueController::RequestEquals::RequestEquals(
+    int render_process_id,
+    int render_view_id,
+    int bridge_id)
+    : render_process_id_(render_process_id),
+      render_view_id_(render_view_id),
+      bridge_id_(bridge_id) {
+}
+
+bool GeolocationInfoBarQueueController::RequestEquals::operator()(
+    const PendingInfoBarRequest& request) const {
+  return request.Equals(render_process_id_, render_view_id_, bridge_id_);
+}
+
+
+// GeolocationInfoBarQueueController ------------------------------------------
+
 GeolocationInfoBarQueueController::GeolocationInfoBarQueueController(
     GeolocationPermissionContext* geolocation_permission_context,
     Profile* profile)
@@ -216,144 +335,169 @@
 }
 
 void GeolocationInfoBarQueueController::CreateInfoBarRequest(
-    int render_process_id, int render_view_id, int bridge_id,
-    const GURL& requesting_frame, const GURL& embedder) {
-  // This makes sure that no duplicates are added to
-  // |pending_infobar_requests_| as an artificial permission request may
-  // already exist in the queue as per
-  // GeolocationPermissionContext::StartUpdatingRequested
-  // See http://crbug.com/51899 for more details.
-  // TODO(joth): Once we have CLIENT_BASED_GEOLOCATION and
-  // WTF_USE_PREEMPT_GEOLOCATION_PERMISSION set in WebKit we should be able to
-  // just use a DCHECK to check if a duplicate is attempting to be added.
-  PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
-  while (i != pending_infobar_requests_.end()) {
-    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
-      // The request already exists.
-      DCHECK(i->IsForPair(requesting_frame, embedder));
-      return;
-    }
-    ++i;
-  }
-  PendingInfoBarRequest pending_infobar_request;
-  pending_infobar_request.render_process_id = render_process_id;
-  pending_infobar_request.render_view_id = render_view_id;
-  pending_infobar_request.bridge_id = bridge_id;
-  pending_infobar_request.requesting_frame = requesting_frame;
-  pending_infobar_request.embedder = embedder;
-  pending_infobar_request.infobar_delegate = NULL;
-  pending_infobar_requests_.push_back(pending_infobar_request);
+    int render_process_id,
+    int render_view_id,
+    int bridge_id,
+    const GURL& requesting_frame,
+    const GURL& embedder) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // We shouldn't get duplicate requests.
+  DCHECK(std::find_if(pending_infobar_requests_.begin(),
+      pending_infobar_requests_.end(),
+      RequestEquals(render_process_id, render_view_id, bridge_id)) ==
+      pending_infobar_requests_.end());
+
+  pending_infobar_requests_.push_back(PendingInfoBarRequest(render_process_id,
+      render_view_id, bridge_id, requesting_frame, embedder));
   ShowQueuedInfoBar(render_process_id, render_view_id);
 }
 
 void GeolocationInfoBarQueueController::CancelInfoBarRequest(
-    int render_process_id, int render_view_id, int bridge_id) {
-  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
-       i != pending_infobar_requests_.end(); ++i) {
-    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
-      CancelInfoBarRequestInternal(i);
-      break;
-    }
-  }
+    int render_process_id,
+    int render_view_id,
+    int bridge_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  PendingInfoBarRequests::iterator i = std::find_if(
+      pending_infobar_requests_.begin(), pending_infobar_requests_.end(),
+      RequestEquals(render_process_id, render_view_id, bridge_id));
+  // TODO(pkasting): Can this conditional become a DCHECK()?
+  if (i != pending_infobar_requests_.end())
+    CancelInfoBarRequestInternal(i);
 }
 
-void GeolocationInfoBarQueueController::OnInfoBarClosed(
-    int render_process_id, int render_view_id, int bridge_id) {
+void GeolocationInfoBarQueueController::OnInfoBarClosed(int render_process_id,
+                                                        int render_view_id,
+                                                        int bridge_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
-       i != pending_infobar_requests_.end(); ++i) {
-    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
-      pending_infobar_requests_.erase(i);
-      break;
-    }
-  }
+
+  PendingInfoBarRequests::iterator i = std::find_if(
+      pending_infobar_requests_.begin(), pending_infobar_requests_.end(),
+      RequestEquals(render_process_id, render_view_id, bridge_id));
+  if (i != pending_infobar_requests_.end())
+    pending_infobar_requests_.erase(i);
+
   ShowQueuedInfoBar(render_process_id, render_view_id);
 }
 
 void GeolocationInfoBarQueueController::OnPermissionSet(
-    int render_process_id, int render_view_id, int bridge_id,
-    const GURL& requesting_frame, const GURL& embedder, bool allowed) {
+    int render_process_id,
+    int render_view_id,
+    int bridge_id,
+    const GURL& requesting_frame,
+    const GURL& embedder,
+    bool allowed) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  // Persist the permission.
+
   ContentSetting content_setting =
       allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
   profile_->GetGeolocationContentSettingsMap()->SetContentSetting(
       requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting);
 
-  // Now notify all pending requests that the permission has been set.
   for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
-       i != pending_infobar_requests_.end();) {
+       i != pending_infobar_requests_.end(); ) {
     if (i->IsForPair(requesting_frame, embedder)) {
-      // There was a pending request for the same [frame, embedder].
-      if (i->Equals(render_process_id, render_view_id, bridge_id)) {
-        // The request that set permission will be removed by TabContents
-        // itself, that is, we should not try to cancel the infobar that has
-        // just notified us.
+      // Cancel this request first, then notify listeners.  TODO(pkasting): Why
+      // is this order important?
+      // NOTE: If the pending request had an infobar, TabContents will close it
+      // either synchronously or asynchronously, which will then pump the queue
+      // via OnInfoBarClosed().
+      PendingInfoBarRequest copied_request = *i;
+      // Don't let CancelInfoBarRequestInternal() call RemoveInfoBar() on the
+      // delegate that's currently calling us.  That delegate is in either
+      // Accept() or Cancel(), so its owning InfoBar will call RemoveInfoBar()
+      // later on in this callstack anyway; and if we do it here, and it causes
+      // the delegate to be deleted, our GURL& args will point to garbage and we
+      // may also cause other problems during stack unwinding.
+      if (i->Equals(render_process_id, render_view_id, bridge_id))
         i->infobar_delegate = NULL;
-      }
-      // Cancel it first, and then notify the permission.
-      // Note: if the pending request had an infobar, TabContents will
-      // eventually close it and we will pump the queue via OnInfoBarClosed().
-      PendingInfoBarRequest other_request = *i;
       i = CancelInfoBarRequestInternal(i);
+
       geolocation_permission_context_->NotifyPermissionSet(
-          other_request.render_process_id, other_request.render_view_id,
-          other_request.bridge_id, other_request.requesting_frame, allowed);
+          copied_request.render_process_id, copied_request.render_view_id,
+          copied_request.bridge_id, copied_request.requesting_frame, allowed);
     } else {
       ++i;
     }
   }
 }
 
-void GeolocationInfoBarQueueController::ShowQueuedInfoBar(
-    int render_process_id, int render_view_id) {
-  TabContents* tab_contents =
-      tab_util::GetTabContentsByID(render_process_id, render_view_id);
+void GeolocationInfoBarQueueController::Observe(
+    NotificationType type, const NotificationSource& source,
+    const NotificationDetails& details) {
+  registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                    source);
+  TabContents* tab_contents = Source<TabContents>(source).ptr();
   for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
        i != pending_infobar_requests_.end();) {
-    if (!i->IsForTab(render_process_id, render_view_id)) {
-      ++i;
-      continue;
-    }
-    if (!tab_contents) {
+    if (i->infobar_delegate == NULL &&
+        tab_contents == tab_util::GetTabContentsByID(i->render_process_id,
+                                                     i->render_view_id)) {
       i = pending_infobar_requests_.erase(i);
-      continue;
+    } else {
+      ++i;
     }
-    // Check if already displayed.
-    if (i->infobar_delegate)
-      break;
-    i->infobar_delegate = new GeolocationConfirmInfoBarDelegate(
-        tab_contents, this,
-        render_process_id, render_view_id,
-        i->bridge_id, i->requesting_frame,
-        profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
-    tab_contents->AddInfoBar(i->infobar_delegate);
-    break;
   }
 }
 
-std::vector<GeolocationInfoBarQueueController::PendingInfoBarRequest>::iterator
-    GeolocationInfoBarQueueController::CancelInfoBarRequestInternal(
-        std::vector<PendingInfoBarRequest>::iterator i) {
+void GeolocationInfoBarQueueController::ShowQueuedInfoBar(int render_process_id,
+                                                          int render_view_id) {
   TabContents* tab_contents =
-      tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id);
-  if (tab_contents && i->infobar_delegate) {
-    // TabContents will destroy the InfoBar, which will remove from our vector
-    // asynchronously.
-    tab_contents->RemoveInfoBar(i->infobar_delegate);
-    return ++i;
-  } else {
-    // Remove it directly from the pending vector.
-    return pending_infobar_requests_.erase(i);
+      tab_util::GetTabContentsByID(render_process_id, render_view_id);
+  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
+       i != pending_infobar_requests_.end(); ) {
+    if (i->IsForTab(render_process_id, render_view_id)) {
+      if (!tab_contents) {
+        i = pending_infobar_requests_.erase(i);
+        continue;
+      }
+
+      if (!i->infobar_delegate) {
+        if (!registrar_.IsRegistered(this,
+                                     NotificationType::TAB_CONTENTS_DESTROYED,
+                                     Source<TabContents>(tab_contents))) {
+          registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                         Source<TabContents>(tab_contents));
+        }
+        i->infobar_delegate = new GeolocationConfirmInfoBarDelegate(
+            tab_contents, this, render_process_id, render_view_id, i->bridge_id,
+            i->requesting_frame,
+            profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
+        tab_contents->AddInfoBar(i->infobar_delegate);
+      }
+      break;
+    }
+    ++i;
   }
 }
 
+GeolocationInfoBarQueueController::PendingInfoBarRequests::iterator
+    GeolocationInfoBarQueueController::CancelInfoBarRequestInternal(
+    PendingInfoBarRequests::iterator i) {
+  InfoBarDelegate* delegate = i->infobar_delegate;
+  if (!delegate)
+    return pending_infobar_requests_.erase(i);
+
+  TabContents* tab_contents =
+      tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id);
+  if (!tab_contents)
+    return pending_infobar_requests_.erase(i);
+
+  // TabContents will destroy the InfoBar, which will remove from our vector
+  // asynchronously.
+  tab_contents->RemoveInfoBar(i->infobar_delegate);
+  return ++i;
+}
+
+
+// GeolocationPermissionContext -----------------------------------------------
+
 GeolocationPermissionContext::GeolocationPermissionContext(
     Profile* profile)
     : profile_(profile),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          geolocation_infobar_queue_controller_(
-             new GeolocationInfoBarQueueController(this, profile))) {
+      ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_infobar_queue_controller_(
+         new GeolocationInfoBarQueueController(this, profile))) {
 }
 
 GeolocationPermissionContext::~GeolocationPermissionContext() {
@@ -363,11 +507,9 @@
     int render_process_id, int render_view_id, int bridge_id,
     const GURL& requesting_frame) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        NewRunnableMethod(this,
-            &GeolocationPermissionContext::RequestGeolocationPermission,
-            render_process_id, render_view_id, bridge_id, requesting_frame));
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
+        this, &GeolocationPermissionContext::RequestGeolocationPermission,
+        render_process_id, render_view_id, bridge_id, requesting_frame));
     return;
   }
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -393,8 +535,8 @@
   if (!tab_contents) {
     // The tab may have gone away, or the request may not be from a tab at all.
     LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
-        << render_process_id << "," << render_view_id << "," << bridge_id
-        << " (can't prompt user without a visible tab)";
+                 << render_process_id << "," << render_view_id << ","
+                 << bridge_id << " (can't prompt user without a visible tab)";
     NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
                         requesting_frame, false);
     return;
@@ -403,8 +545,8 @@
   GURL embedder = tab_contents->GetURL();
   if (!requesting_frame.is_valid() || !embedder.is_valid()) {
     LOG(WARNING) << "Attempt to use geolocation from an invalid URL: "
-        << requesting_frame << "," << embedder
-        << " (geolocation is not supported in popups)";
+                 << requesting_frame << "," << embedder
+                 << " (geolocation is not supported in popups)";
     NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
                         requesting_frame, false);
     return;
@@ -419,7 +561,7 @@
   } else if (content_setting == CONTENT_SETTING_ALLOW) {
     NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
                         requesting_frame, true);
-  } else { // setting == ask. Prompt the user.
+  } else {  // setting == ask. Prompt the user.
     geolocation_infobar_queue_controller_->CreateInfoBarRequest(
         render_process_id, render_view_id, bridge_id, requesting_frame,
         embedder);
@@ -427,14 +569,19 @@
 }
 
 void GeolocationPermissionContext::CancelGeolocationPermissionRequest(
-    int render_process_id, int render_view_id, int bridge_id,
+    int render_process_id,
+    int render_view_id,
+    int bridge_id,
     const GURL& requesting_frame) {
   CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id);
 }
 
 void GeolocationPermissionContext::NotifyPermissionSet(
-    int render_process_id, int render_view_id, int bridge_id,
-    const GURL& requesting_frame, bool allowed) {
+    int render_process_id,
+    int render_view_id,
+    int bridge_id,
+    const GURL& requesting_frame,
+    bool allowed) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   TabContents* tab_contents =
@@ -448,17 +595,13 @@
                                                  allowed);
   }
 
-  CallRenderViewHost(
-      render_process_id, render_view_id,
-      &RenderViewHost::Send,
+  CallRenderViewHost(render_process_id, render_view_id, &RenderViewHost::Send,
       new ViewMsg_Geolocation_PermissionSet(render_view_id, bridge_id,
-          allowed));
+                                            allowed));
   if (allowed) {
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        NewRunnableMethod(this,
-            &GeolocationPermissionContext::NotifyArbitratorPermissionGranted,
-            requesting_frame));
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableMethod(
+        this, &GeolocationPermissionContext::NotifyArbitratorPermissionGranted,
+        requesting_frame));
   }
 }
 
@@ -469,16 +612,16 @@
 }
 
 void GeolocationPermissionContext::CancelPendingInfoBarRequest(
-    int render_process_id, int render_view_id, int bridge_id) {
+    int render_process_id,
+    int render_view_id,
+    int bridge_id) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        NewRunnableMethod(this,
-            &GeolocationPermissionContext::CancelPendingInfoBarRequest,
-            render_process_id, render_view_id, bridge_id));
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
+        this, &GeolocationPermissionContext::CancelPendingInfoBarRequest,
+        render_process_id, render_view_id, bridge_id));
      return;
   }
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  geolocation_infobar_queue_controller_->CancelInfoBarRequest(
-      render_process_id, render_view_id, bridge_id);
+  geolocation_infobar_queue_controller_->CancelInfoBarRequest(render_process_id,
+      render_view_id, bridge_id);
 }
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
index cd1426e..7cb2d9d 100644
--- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 
 #include "base/scoped_vector.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h"
 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
 #include "chrome/browser/geolocation/geolocation_permission_context.h"
 #include "chrome/browser/geolocation/location_arbitrator.h"
@@ -21,171 +22,206 @@
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// TestTabContentsWithPendingInfoBar ------------------------------------------
+
+namespace {
+
 // TestTabContents short-circuits TAB_CONTENTS_INFOBAR_REMOVED to call
 // InfoBarClosed() directly. We need to observe it and call InfoBarClosed()
 // later.
 class TestTabContentsWithPendingInfoBar : public TestTabContents {
  public:
-   TestTabContentsWithPendingInfoBar(Profile* profile, SiteInstance* instance)
-    : TestTabContents(profile, instance),
-      removed_infobar_delegate_(NULL) {
-  }
+  TestTabContentsWithPendingInfoBar(Profile* profile, SiteInstance* instance);
+  virtual ~TestTabContentsWithPendingInfoBar();
 
-  void Observe(NotificationType type,
-               const NotificationSource& source,
-               const NotificationDetails& details) {
-    // We need to special case TAB_CONTENTS_INFOBAR_REMOVED to track which
-    // delegate was removed and avoid calling InfoBarClosed() supplied in the
-    // base class. All other notification types are delegated to the base class.
-    switch (type.value) {
-      case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
-        removed_infobar_delegate_ = Details<InfoBarDelegate>(details).ptr();
-        break;
-      default:
-        TestTabContents::Observe(type, source, details);
-        break;
-    }
-  }
+  // TestTabContents:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
 
   InfoBarDelegate* removed_infobar_delegate_;
 };
 
-// This class sets up GeolocationArbitrator and injects
-// TestTabContentsWithPendingInfoBar.
+TestTabContentsWithPendingInfoBar::TestTabContentsWithPendingInfoBar(
+    Profile* profile,
+    SiteInstance* instance)
+    : TestTabContents(profile, instance),
+      removed_infobar_delegate_(NULL) {
+}
+
+TestTabContentsWithPendingInfoBar::~TestTabContentsWithPendingInfoBar() {
+}
+
+void TestTabContentsWithPendingInfoBar::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  if (type.value == NotificationType::TAB_CONTENTS_INFOBAR_REMOVED)
+    removed_infobar_delegate_ = Details<InfoBarDelegate>(details).ptr();
+  else
+    TestTabContents::Observe(type, source, details);
+}
+
+}  // namespace
+
+
+// GeolocationPermissionContextTests ------------------------------------------
+
+// This class sets up GeolocationArbitrator.
 class GeolocationPermissionContextTests : public RenderViewHostTestHarness {
  public:
-  GeolocationPermissionContextTests()
-    : RenderViewHostTestHarness(),
-      ui_thread_(BrowserThread::UI, MessageLoop::current()),
-      tab_contents_with_pending_infobar_(NULL) {
-  }
+  GeolocationPermissionContextTests();
 
-  virtual ~GeolocationPermissionContextTests() {
-  }
+ protected:
+  virtual ~GeolocationPermissionContextTests();
 
-  virtual void SetUp() {
-    RenderViewHostTestHarness::SetUp();
-    GeolocationArbitrator::SetProviderFactoryForTest(
-        &NewAutoSuccessMockNetworkLocationProvider);
-    SiteInstance* site_instance = contents_->GetSiteInstance();
-    tab_contents_with_pending_infobar_ =
-        new TestTabContentsWithPendingInfoBar(profile_.get(), site_instance);
-    contents_.reset(tab_contents_with_pending_infobar_);
-    geolocation_permission_context_ =
-        new GeolocationPermissionContext(profile());
-  }
-
-  virtual void TearDown() {
-    RenderViewHostTestHarness::TearDown();
-    GeolocationArbitrator::SetProviderFactoryForTest(NULL);
-  }
-
-  int process_id() {
-    return contents()->render_view_host()->process()->id();
-  }
+  int process_id() { return contents()->render_view_host()->process()->id(); }
   int process_id_for_tab(int tab) {
     return extra_tabs_[tab]->render_view_host()->process()->id();
   }
-
-  int render_id() {
-    return contents()->render_view_host()->routing_id();
-  }
+  int render_id() { return contents()->render_view_host()->routing_id(); }
   int render_id_for_tab(int tab) {
     return extra_tabs_[tab]->render_view_host()->routing_id();
   }
+  int bridge_id() const { return 42; }  // Not relevant at this level.
 
-  int bridge_id() {
-    // Bridge id is not relevant at this level.
-    return 42;
-  }
-
-  void CheckPermissionMessageSent(int bridge_id, bool allowed) {
-    CheckPermissionMessageSentInternal(process(), bridge_id, allowed);
-  }
-  void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed) {
-    CheckPermissionMessageSentInternal(
-      static_cast<MockRenderProcessHost*>(
-          extra_tabs_[tab]->render_view_host()->process()),
-      bridge_id, allowed);
-  }
-
+  void CheckPermissionMessageSent(int bridge_id, bool allowed);
+  void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed);
   void CheckPermissionMessageSentInternal(MockRenderProcessHost* process,
                                           int bridge_id,
-                                          bool allowed) {
-    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
-    MessageLoop::current()->Run();
-    const IPC::Message* message =
-        process->sink().GetFirstMessageMatching(
-            ViewMsg_Geolocation_PermissionSet::ID);
-    ASSERT_TRUE(message);
-    ViewMsg_Geolocation_PermissionSet::Param param;
-    ViewMsg_Geolocation_PermissionSet::Read(message, &param);
-    EXPECT_EQ(bridge_id, param.a);
-    EXPECT_EQ(allowed, param.b);
-    process->sink().ClearMessages();
-  }
-
-  void AddNewTab(const GURL& url) {
-    TestTabContentsWithPendingInfoBar* new_tab =
-        new TestTabContentsWithPendingInfoBar(profile(), NULL);
-    new_tab->controller().LoadURL(url, GURL(), PageTransition::TYPED);
-    static_cast<TestRenderViewHost*>(new_tab->render_manager()->
-       current_host())->SendNavigate(extra_tabs_.size() + 1, url);
-    extra_tabs_.push_back(new_tab);
-  }
-
+                                          bool allowed);
+  void AddNewTab(const GURL& url);
   void CheckTabContentsState(const GURL& requesting_frame,
-                             ContentSetting expected_content_setting) {
-    TabSpecificContentSettings* content_settings =
-        contents()->GetTabSpecificContentSettings();
-    const GeolocationSettingsState::StateMap& state_map =
-        content_settings->geolocation_settings_state().state_map();
-    EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin()));
-    EXPECT_EQ(0U, state_map.count(requesting_frame));
-    GeolocationSettingsState::StateMap::const_iterator settings =
-        state_map.find(requesting_frame.GetOrigin());
-    ASSERT_FALSE(settings == state_map.end())
-        << "geolocation state not found " << requesting_frame;
-    EXPECT_EQ(expected_content_setting, settings->second);
-  }
+                             ContentSetting expected_content_setting);
 
- protected:
-  BrowserThread ui_thread_;
   TestTabContentsWithPendingInfoBar* tab_contents_with_pending_infobar_;
   scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_;
   ScopedVector<TestTabContentsWithPendingInfoBar> extra_tabs_;
+
+ private:
+  // RenderViewHostTestHarness:
+  virtual void SetUp();
+  virtual void TearDown();
+
+  BrowserThread ui_thread_;
+  scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory_;
 };
 
+GeolocationPermissionContextTests::GeolocationPermissionContextTests()
+    : RenderViewHostTestHarness(),
+      tab_contents_with_pending_infobar_(NULL),
+      ui_thread_(BrowserThread::UI, MessageLoop::current()),
+      dependency_factory_(
+          new GeolocationArbitratorDependencyFactoryWithLocationProvider(
+              &NewAutoSuccessMockNetworkLocationProvider)) {
+}
+
+GeolocationPermissionContextTests::~GeolocationPermissionContextTests() {
+}
+
+void GeolocationPermissionContextTests::CheckPermissionMessageSent(
+    int bridge_id,
+    bool allowed) {
+  CheckPermissionMessageSentInternal(process(), bridge_id, allowed);
+}
+
+void GeolocationPermissionContextTests::CheckPermissionMessageSentForTab(
+    int tab,
+    int bridge_id,
+    bool allowed) {
+  CheckPermissionMessageSentInternal(static_cast<MockRenderProcessHost*>(
+      extra_tabs_[tab]->render_view_host()->process()), bridge_id, allowed);
+}
+
+void GeolocationPermissionContextTests::CheckPermissionMessageSentInternal(
+    MockRenderProcessHost* process,
+    int bridge_id,
+    bool allowed) {
+  MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+  MessageLoop::current()->Run();
+  const IPC::Message* message = process->sink().GetFirstMessageMatching(
+      ViewMsg_Geolocation_PermissionSet::ID);
+  ASSERT_TRUE(message);
+  ViewMsg_Geolocation_PermissionSet::Param param;
+  ViewMsg_Geolocation_PermissionSet::Read(message, &param);
+  EXPECT_EQ(bridge_id, param.a);
+  EXPECT_EQ(allowed, param.b);
+  process->sink().ClearMessages();
+}
+
+void GeolocationPermissionContextTests::AddNewTab(const GURL& url) {
+  TestTabContentsWithPendingInfoBar* new_tab =
+      new TestTabContentsWithPendingInfoBar(profile(), NULL);
+  new_tab->controller().LoadURL(url, GURL(), PageTransition::TYPED);
+  static_cast<TestRenderViewHost*>(new_tab->render_manager()->current_host())->
+      SendNavigate(extra_tabs_.size() + 1, url);
+  extra_tabs_.push_back(new_tab);
+}
+
+void GeolocationPermissionContextTests::CheckTabContentsState(
+    const GURL& requesting_frame,
+    ContentSetting expected_content_setting) {
+  TabSpecificContentSettings* content_settings =
+      contents()->GetTabSpecificContentSettings();
+  const GeolocationSettingsState::StateMap& state_map =
+      content_settings->geolocation_settings_state().state_map();
+  EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin()));
+  EXPECT_EQ(0U, state_map.count(requesting_frame));
+  GeolocationSettingsState::StateMap::const_iterator settings =
+      state_map.find(requesting_frame.GetOrigin());
+  ASSERT_FALSE(settings == state_map.end())
+      << "geolocation state not found " << requesting_frame;
+  EXPECT_EQ(expected_content_setting, settings->second);
+}
+
+void GeolocationPermissionContextTests::SetUp() {
+  RenderViewHostTestHarness::SetUp();
+  GeolocationArbitrator::SetDependencyFactoryForTest(
+      dependency_factory_.get());
+  SiteInstance* site_instance = contents_->GetSiteInstance();
+  tab_contents_with_pending_infobar_ =
+      new TestTabContentsWithPendingInfoBar(profile_.get(), site_instance);
+  contents_.reset(tab_contents_with_pending_infobar_);
+  geolocation_permission_context_ =
+      new GeolocationPermissionContext(profile());
+}
+
+void GeolocationPermissionContextTests::TearDown() {
+  GeolocationArbitrator::SetDependencyFactoryForTest(NULL);
+  RenderViewHostTestHarness::TearDown();
+}
+
+
+// Tests ----------------------------------------------------------------------
+
 TEST_F(GeolocationPermissionContextTests, SinglePermission) {
   GURL requesting_frame("http://www.example.com/geolocation");
   NavigateAndCommit(requesting_frame);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id(), requesting_frame);
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
 }
 
 TEST_F(GeolocationPermissionContextTests, QueuedPermission) {
   GURL requesting_frame_0("http://www.example.com/geolocation");
   GURL requesting_frame_1("http://www.example-2.com/geolocation");
-  EXPECT_EQ(
-      CONTENT_SETTING_ASK,
+  EXPECT_EQ(CONTENT_SETTING_ASK,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_0, requesting_frame_0));
-  EXPECT_EQ(
-      CONTENT_SETTING_ASK,
+  EXPECT_EQ(CONTENT_SETTING_ASK,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_1, requesting_frame_0));
 
   NavigateAndCommit(requesting_frame_0);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   // Request permission for two frames.
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id(), requesting_frame_0);
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id() + 1, requesting_frame_1);
   // Ensure only one infobar is created.
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
   ConfirmInfoBarDelegate* infobar_0 =
       contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
   ASSERT_TRUE(infobar_0);
@@ -201,7 +237,7 @@
             tab_contents_with_pending_infobar_->removed_infobar_delegate_);
   infobar_0->InfoBarClosed();
   // Now we should have a new infobar for the second frame.
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
 
   ConfirmInfoBarDelegate* infobar_1 =
       contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
@@ -217,14 +253,12 @@
   EXPECT_EQ(infobar_1,
             tab_contents_with_pending_infobar_->removed_infobar_delegate_);
   infobar_1->InfoBarClosed();
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   // Ensure the persisted permissions are ok.
-  EXPECT_EQ(
-      CONTENT_SETTING_ALLOW,
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_0, requesting_frame_0));
-  EXPECT_EQ(
-      CONTENT_SETTING_BLOCK,
+  EXPECT_EQ(CONTENT_SETTING_BLOCK,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_1, requesting_frame_0));
 }
@@ -232,23 +266,21 @@
 TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) {
   GURL requesting_frame_0("http://www.example.com/geolocation");
   GURL requesting_frame_1("http://www.example-2.com/geolocation");
-  EXPECT_EQ(
-      CONTENT_SETTING_ASK,
+  EXPECT_EQ(CONTENT_SETTING_ASK,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_0, requesting_frame_0));
-  EXPECT_EQ(
-      CONTENT_SETTING_ASK,
+  EXPECT_EQ(CONTENT_SETTING_ASK,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_1, requesting_frame_0));
 
   NavigateAndCommit(requesting_frame_0);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   // Request permission for two frames.
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id(), requesting_frame_0);
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id() + 1, requesting_frame_1);
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
 
   ConfirmInfoBarDelegate* infobar_0 =
       contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
@@ -262,7 +294,7 @@
   EXPECT_EQ(infobar_0,
             tab_contents_with_pending_infobar_->removed_infobar_delegate_);
   infobar_0->InfoBarClosed();
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
 
   ConfirmInfoBarDelegate* infobar_1 =
       contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
@@ -278,14 +310,12 @@
   EXPECT_EQ(infobar_1,
             tab_contents_with_pending_infobar_->removed_infobar_delegate_);
   infobar_1->InfoBarClosed();
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   // Ensure the persisted permissions are ok.
-  EXPECT_EQ(
-      CONTENT_SETTING_ASK,
+  EXPECT_EQ(CONTENT_SETTING_ASK,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_0, requesting_frame_0));
-  EXPECT_EQ(
-      CONTENT_SETTING_ALLOW,
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
       profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
           requesting_frame_1, requesting_frame_0));
 }
@@ -294,10 +324,10 @@
   GURL invalid_embedder;
   GURL requesting_frame("about:blank");
   NavigateAndCommit(invalid_embedder);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id(), requesting_frame);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   CheckPermissionMessageSent(bridge_id(), false);
 }
 
@@ -308,18 +338,18 @@
   AddNewTab(url_b);
   AddNewTab(url_a);
 
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id(), url_a);
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
 
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id_for_tab(0), render_id_for_tab(0), bridge_id(), url_b);
-  EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count());
+  EXPECT_EQ(1U, extra_tabs_[0]->infobar_count());
 
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id_for_tab(1), render_id_for_tab(1), bridge_id(), url_a);
-  EXPECT_EQ(1, extra_tabs_[1]->infobar_delegate_count());
+  EXPECT_EQ(1U, extra_tabs_[1]->infobar_count());
 
   ConfirmInfoBarDelegate* removed_infobar =
       extra_tabs_[1]->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
@@ -335,13 +365,13 @@
             tab_contents_with_pending_infobar_->removed_infobar_delegate_);
   infobar_0->InfoBarClosed();
   // Now the infobar for the tab with the same origin should have gone.
-  EXPECT_EQ(0, extra_tabs_[1]->infobar_delegate_count());
+  EXPECT_EQ(0U, extra_tabs_[1]->infobar_count());
   CheckPermissionMessageSentForTab(1, bridge_id(), true);
   // Destroy the infobar that has just been removed.
   removed_infobar->InfoBarClosed();
 
   // But the other tab should still have the info bar...
-  EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count());
+  EXPECT_EQ(1U, extra_tabs_[0]->infobar_count());
   extra_tabs_.reset();
 }
 
@@ -351,18 +381,18 @@
   NavigateAndCommit(url_a);
   AddNewTab(url_a);
 
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id(), render_id(), bridge_id(), url_a);
-  EXPECT_EQ(1, contents()->infobar_delegate_count());
+  EXPECT_EQ(1U, contents()->infobar_count());
 
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id_for_tab(0), render_id_for_tab(0), bridge_id(), url_a);
-  EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count());
+  EXPECT_EQ(1U, extra_tabs_[0]->infobar_count());
 
   geolocation_permission_context_->RequestGeolocationPermission(
       process_id_for_tab(0), render_id_for_tab(0), bridge_id() + 1, url_b);
-  EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count());
+  EXPECT_EQ(1U, extra_tabs_[0]->infobar_count());
 
   ConfirmInfoBarDelegate* removed_infobar =
       contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
@@ -378,13 +408,13 @@
             extra_tabs_[0]->removed_infobar_delegate_);
   infobar_0->InfoBarClosed();
   // Now the infobar for the tab with the same origin should have gone.
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   CheckPermissionMessageSent(bridge_id(), true);
   // Destroy the infobar that has just been removed.
   removed_infobar->InfoBarClosed();
 
   // And we should have the queued infobar displayed now.
-  EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count());
+  EXPECT_EQ(1U, extra_tabs_[0]->infobar_count());
 
   // Accept the second infobar.
   ConfirmInfoBarDelegate* infobar_1 =
@@ -399,3 +429,33 @@
 
   extra_tabs_.reset();
 }
+
+TEST_F(GeolocationPermissionContextTests, TabDestroyed) {
+  GURL requesting_frame_0("http://www.example.com/geolocation");
+  GURL requesting_frame_1("http://www.example-2.com/geolocation");
+  EXPECT_EQ(
+      CONTENT_SETTING_ASK,
+      profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
+          requesting_frame_0, requesting_frame_0));
+  EXPECT_EQ(
+      CONTENT_SETTING_ASK,
+      profile()->GetGeolocationContentSettingsMap()->GetContentSetting(
+          requesting_frame_1, requesting_frame_0));
+
+  NavigateAndCommit(requesting_frame_0);
+  EXPECT_EQ(0U, contents()->infobar_count());
+  // Request permission for two frames.
+  geolocation_permission_context_->RequestGeolocationPermission(
+      process_id(), render_id(), bridge_id(), requesting_frame_0);
+  geolocation_permission_context_->RequestGeolocationPermission(
+      process_id(), render_id(), bridge_id() + 1, requesting_frame_1);
+  // Ensure only one infobar is created.
+  EXPECT_EQ(1U, contents()->infobar_count());
+  ConfirmInfoBarDelegate* infobar_0 =
+      contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
+  ASSERT_TRUE(infobar_0);
+  string16 text_0 = infobar_0->GetMessageText();
+
+  // Delete the tab contents.
+  DeleteContents();
+}
diff --git a/chrome/browser/geolocation/geolocation_provider.cc b/chrome/browser/geolocation/geolocation_provider.cc
index 59365b1..0b3d499 100644
--- a/chrome/browser/geolocation/geolocation_provider.cc
+++ b/chrome/browser/geolocation/geolocation_provider.cc
@@ -24,7 +24,6 @@
 
 GeolocationProvider::~GeolocationProvider() {
   DCHECK(observers_.empty());  // observers must unregister.
-  DCHECK(!IsRunning());
   Stop();
   DCHECK(!arbitrator_);
 }
@@ -47,12 +46,10 @@
 
 void GeolocationProvider::OnObserversChanged() {
   DCHECK(OnClientThread());
+  Task* task = NULL;
   if (observers_.empty()) {
-    // http://crbug.com/66077: This is a bug.  The geolocation thread may
-    // transitively (via other threads it joins) block on long-running tasks /
-    // IO.
-    base::ThreadRestrictions::ScopedAllowIO allow_io;
-    Stop();
+    DCHECK(IsRunning());
+    task = NewRunnableMethod(this, &GeolocationProvider::StopProviders);
   } else {
     if (!IsRunning()) {
       Start();
@@ -60,11 +57,12 @@
         InformProvidersPermissionGranted(most_recent_authorized_frame_);
     }
     // The high accuracy requirement may have changed.
-    Task* task = NewRunnableMethod(this,
-        &GeolocationProvider::SetObserverOptions,
-            GeolocationObserverOptions::Collapse(observers_));
-    message_loop()->PostTask(FROM_HERE, task);
+    task = NewRunnableMethod(
+        this,
+        &GeolocationProvider::StartProviders,
+        GeolocationObserverOptions::Collapse(observers_));
   }
+  message_loop()->PostTask(FROM_HERE, task);
 }
 
 void GeolocationProvider::NotifyObservers(const Geoposition& position) {
@@ -80,11 +78,17 @@
   }
 }
 
-void GeolocationProvider::SetObserverOptions(
+void GeolocationProvider::StartProviders(
     const GeolocationObserverOptions& options) {
   DCHECK(OnGeolocationThread());
   DCHECK(arbitrator_);
-  arbitrator_->SetObserverOptions(options);
+  arbitrator_->StartProviders(options);
+}
+
+void GeolocationProvider::StopProviders() {
+  DCHECK(OnGeolocationThread());
+  DCHECK(arbitrator_);
+  arbitrator_->StopProviders();
 }
 
 void GeolocationProvider::OnPermissionGranted(const GURL& requesting_frame) {
diff --git a/chrome/browser/geolocation/geolocation_provider.h b/chrome/browser/geolocation/geolocation_provider.h
index f83c427..2e1f851 100644
--- a/chrome/browser/geolocation/geolocation_provider.h
+++ b/chrome/browser/geolocation/geolocation_provider.h
@@ -36,9 +36,11 @@
   // but only a single call to RemoveObserver() is required to remove it.
   void AddObserver(GeolocationObserver* delegate,
                    const GeolocationObserverOptions& update_options);
+
   // Remove a previously registered observer. No-op if not previously registered
   // via AddObserver(). Returns true if the observer was removed.
   bool RemoveObserver(GeolocationObserver* delegate);
+
   void OnPermissionGranted(const GURL& requesting_frame);
   bool HasPermissionBeenGranted() const;
 
@@ -59,11 +61,22 @@
 
   bool OnClientThread() const;
   bool OnGeolocationThread() const;
+
+  // When the observer list changes, we may start the thread and the required
+  // providers, or stop them.
   void OnObserversChanged();
-  // Passes the observers' geolocation options through to the arbitrator.
-  void SetObserverOptions(const GeolocationObserverOptions& options);
+
+  // Stop the providers when there are no more observers. Note that once our
+  // thread is started, we'll keep it alive (but with no pending messages).
+  void StopProviders();
+
+  // Starts or updates the observers' geolocation options
+  // (delegates to arbitrator).
+  void StartProviders(const GeolocationObserverOptions& options);
+
   // Update the providers on the geolocation thread, which must be running.
   void InformProvidersPermissionGranted(const GURL& requesting_frame);
+
   // Notifies observers when a new position fix is available.
   void NotifyObservers(const Geoposition& position);
 
diff --git a/chrome/browser/geolocation/geolocation_provider_unittest.cc b/chrome/browser/geolocation/geolocation_provider_unittest.cc
index ec9cc96..190f2a4 100644
--- a/chrome/browser/geolocation/geolocation_provider_unittest.cc
+++ b/chrome/browser/geolocation/geolocation_provider_unittest.cc
@@ -5,27 +5,48 @@
 #include "chrome/browser/geolocation/geolocation_provider.h"
 
 #include "base/singleton.h"
+#include "chrome/browser/geolocation/arbitrator_dependency_factories_for_test.h"
+#include "chrome/browser/geolocation/fake_access_token_store.h"
+#include "chrome/browser/geolocation/location_arbitrator.h"
+#include "chrome/browser/geolocation/mock_location_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
 class GeolocationProviderTest : public testing::Test {
  protected:
-  // TODO(joth): This test should inject a mock arbitrator rather than cause
-  // the real one to be instantiated. For now, this is not an issue as the
-  // arbitrator is never started.
   GeolocationProviderTest()
-      : provider_(new GeolocationProvider) {}
+      : provider_(new GeolocationProvider),
+        dependency_factory_(
+            new GeolocationArbitratorDependencyFactoryWithLocationProvider(
+                &NewAutoSuccessMockNetworkLocationProvider))
+  {
+  }
 
   ~GeolocationProviderTest() {
     DefaultSingletonTraits<GeolocationProvider>::Delete(provider_);
   }
+
+  // testing::Test
+  virtual void SetUp() {
+    GeolocationArbitrator::SetDependencyFactoryForTest(
+        dependency_factory_.get());
+  }
+
+  // testing::Test
+  virtual void TearDown() {
+    provider_->Stop();
+    GeolocationArbitrator::SetDependencyFactoryForTest(NULL);
+  }
+
   // Message loop for main thread, as provider depends on it existing.
   MessageLoop message_loop_;
 
   // Object under tests. Owned, but not a scoped_ptr due to specialized
   // destruction protocol.
   GeolocationProvider* provider_;
+
+  scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory_;
 };
 
 // Regression test for http://crbug.com/59377
@@ -35,4 +56,97 @@
   EXPECT_TRUE(provider_->HasPermissionBeenGranted());
 }
 
+class NullGeolocationObserver : public GeolocationObserver {
+ public:
+  // GeolocationObserver
+  virtual void OnLocationUpdate(const Geoposition& position) {}
+};
+
+class StartStopMockLocationProvider : public MockLocationProvider {
+ public:
+  explicit StartStopMockLocationProvider(MessageLoop* test_loop)
+      : MockLocationProvider(&instance_),
+        test_loop_(test_loop) {
+  }
+
+  virtual bool StartProvider(bool high_accuracy) {
+    bool result = MockLocationProvider::StartProvider(high_accuracy);
+    test_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+    return result;
+  }
+
+  virtual void StopProvider() {
+    MockLocationProvider::StopProvider();
+    test_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+  }
+
+ private:
+  MessageLoop* test_loop_;
+};
+
+class MockDependencyFactory : public GeolocationArbitratorDependencyFactory {
+ public:
+  MockDependencyFactory(MessageLoop* test_loop_,
+                        AccessTokenStore* access_token_store)
+      : test_loop_(test_loop_),
+        access_token_store_(access_token_store) {
+  }
+
+  virtual URLRequestContextGetter* GetContextGetter() {
+    return NULL;
+  }
+
+  virtual GeolocationArbitrator::GetTimeNow GetTimeFunction() {
+    return base::Time::Now;
+  }
+
+  virtual AccessTokenStore* NewAccessTokenStore() {
+    return access_token_store_.get();
+  }
+
+  virtual LocationProviderBase* NewNetworkLocationProvider(
+      AccessTokenStore* access_token_store,
+      URLRequestContextGetter* context,
+      const GURL& url,
+      const string16& access_token) {
+    return new StartStopMockLocationProvider(test_loop_);
+  }
+
+  virtual LocationProviderBase* NewSystemLocationProvider() {
+    return NULL;
+  }
+
+ private:
+  MessageLoop* test_loop_;
+  scoped_refptr<AccessTokenStore> access_token_store_;
+};
+
+TEST_F(GeolocationProviderTest, StartStop) {
+  scoped_refptr<FakeAccessTokenStore> fake_access_token_store =
+      new FakeAccessTokenStore;
+  scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory =
+      new MockDependencyFactory(&message_loop_, fake_access_token_store.get());
+
+  GeolocationArbitrator::SetDependencyFactoryForTest(dependency_factory.get());
+
+  EXPECT_FALSE(provider_->IsRunning());
+  NullGeolocationObserver null_observer;
+  GeolocationObserverOptions options;
+  provider_->AddObserver(&null_observer, options);
+  // The GeolocationArbitrator won't start the providers until it has
+  // finished loading access tokens.
+  fake_access_token_store->NotifyDelegateTokensLoaded();
+  EXPECT_TRUE(provider_->IsRunning());
+  message_loop_.Run();
+  EXPECT_EQ(MockLocationProvider::instance_->state_,
+            MockLocationProvider::LOW_ACCURACY);
+  provider_->RemoveObserver(&null_observer);
+  message_loop_.Run();
+  EXPECT_EQ(MockLocationProvider::instance_->state_,
+            MockLocationProvider::STOPPED);
+  EXPECT_TRUE(provider_->IsRunning());
+
+  GeolocationArbitrator::SetDependencyFactoryForTest(NULL);
+}
+
 }  // namespace
diff --git a/chrome/browser/geolocation/location_arbitrator.cc b/chrome/browser/geolocation/location_arbitrator.cc
index 4ae6ee7..2d455ad 100644
--- a/chrome/browser/geolocation/location_arbitrator.cc
+++ b/chrome/browser/geolocation/location_arbitrator.cc
@@ -6,53 +6,29 @@
 
 #include <map>
 
+#include "chrome/browser/geolocation/arbitrator_dependency_factory.h"
 #include "chrome/browser/profiles/profile.h"
 
 namespace {
+
 const char* kDefaultNetworkProviderUrl = "https://www.google.com/loc/json";
-// TODO(joth): Remove this global function pointer and update all tests to use
-// an injected ProviderFactory class instead.
-GeolocationArbitrator::LocationProviderFactoryFunction
-    g_provider_factory_function_for_test = NULL;
+GeolocationArbitratorDependencyFactory* g_dependency_factory_for_test = NULL;
+
 }  // namespace
 
-
-class DefaultLocationProviderFactory
-    : public GeolocationArbitrator::ProviderFactory {
- public:
-  virtual LocationProviderBase* NewNetworkLocationProvider(
-      AccessTokenStore* access_token_store,
-      URLRequestContextGetter* context,
-      const GURL& url,
-      const string16& access_token) {
-    if (g_provider_factory_function_for_test)
-      return g_provider_factory_function_for_test();
-    return ::NewNetworkLocationProvider(access_token_store, context,
-                                        url, access_token);
-  }
-  virtual LocationProviderBase* NewSystemLocationProvider() {
-    if (g_provider_factory_function_for_test)
-      return NULL;
-    return ::NewSystemLocationProvider();
-  }
-};
-
 // To avoid oscillations, set this to twice the expected update interval of a
 // a GPS-type location provider (in case it misses a beat) plus a little.
 const int64 GeolocationArbitrator::kFixStaleTimeoutMilliseconds =
     11 * base::Time::kMillisecondsPerSecond;
 
 GeolocationArbitrator::GeolocationArbitrator(
-    AccessTokenStore* access_token_store,
-    URLRequestContextGetter* context_getter,
-    GetTimeNow get_time_now,
-    GeolocationObserver* observer,
-    ProviderFactory* provider_factory)
-    : access_token_store_(access_token_store),
-      context_getter_(context_getter),
-      get_time_now_(get_time_now),
+    GeolocationArbitratorDependencyFactory* dependency_factory,
+    GeolocationObserver* observer)
+    : dependency_factory_(dependency_factory),
+      access_token_store_(dependency_factory->NewAccessTokenStore()),
+      context_getter_(dependency_factory->GetContextGetter()),
+      get_time_now_(dependency_factory->GetTimeFunction()),
       observer_(observer),
-      provider_factory_(provider_factory),
       position_provider_(NULL) {
   DCHECK(GURL(kDefaultNetworkProviderUrl).is_valid());
   access_token_store_->LoadAccessTokens(
@@ -66,15 +42,14 @@
 
 GeolocationArbitrator* GeolocationArbitrator::Create(
     GeolocationObserver* observer) {
-  // Construct the arbitrator using default token store and url context. We
-  // get the url context getter from the default profile as it's not
-  // particularly important which profile it is attached to: the network
-  // request implementation disables cookies anyhow.
-  return new GeolocationArbitrator(NewChromePrefsAccessTokenStore(),
-                                   Profile::GetDefaultRequestContext(),
-                                   base::Time::Now,
-                                   observer,
-                                   new DefaultLocationProviderFactory);
+  GeolocationArbitratorDependencyFactory* dependency_factory =
+      g_dependency_factory_for_test ?
+      g_dependency_factory_for_test :
+      new DefaultGeolocationArbitratorDependencyFactory;
+  GeolocationArbitrator* arbitrator =
+      new GeolocationArbitrator(dependency_factory, observer);
+  g_dependency_factory_for_test = NULL;
+  return arbitrator;
 }
 
 void GeolocationArbitrator::OnPermissionGranted(
@@ -86,7 +61,7 @@
   }
 }
 
-void GeolocationArbitrator::SetObserverOptions(
+void GeolocationArbitrator::StartProviders(
     const GeolocationObserverOptions& options) {
   // Stash options incase OnAccessTokenStoresLoaded has not yet been called
   // (in which case |providers_| will be empty).
@@ -101,6 +76,13 @@
   }
 }
 
+void GeolocationArbitrator::StopProviders() {
+  for (ScopedVector<LocationProviderBase>::iterator i = providers_.begin();
+       i != providers_.end(); ++i) {
+    (*i)->StopProvider();
+  }
+}
+
 void GeolocationArbitrator::OnAccessTokenStoresLoaded(
     AccessTokenStore::AccessTokenSet access_token_set) {
   DCHECK(providers_.empty())
@@ -113,11 +95,11 @@
            access_token_set.begin();
       i != access_token_set.end(); ++i) {
     RegisterProvider(
-        provider_factory_->NewNetworkLocationProvider(
+        dependency_factory_->NewNetworkLocationProvider(
             access_token_store_.get(), context_getter_.get(),
             i->first, i->second));
   }
-  RegisterProvider(provider_factory_->NewSystemLocationProvider());
+  RegisterProvider(dependency_factory_->NewSystemLocationProvider());
   StartProviders();
 }
 
@@ -175,10 +157,7 @@
   return most_recent_authorized_frame_.is_valid();
 }
 
-GeolocationArbitrator::ProviderFactory::~ProviderFactory() {
-}
-
-void GeolocationArbitrator::SetProviderFactoryForTest(
-      LocationProviderFactoryFunction factory_function) {
-  g_provider_factory_function_for_test = factory_function;
+void GeolocationArbitrator::SetDependencyFactoryForTest(
+    GeolocationArbitratorDependencyFactory* dependency_factory) {
+  g_dependency_factory_for_test = dependency_factory;
 }
diff --git a/chrome/browser/geolocation/location_arbitrator.h b/chrome/browser/geolocation/location_arbitrator.h
index 6957cc2..6a45756 100644
--- a/chrome/browser/geolocation/location_arbitrator.h
+++ b/chrome/browser/geolocation/location_arbitrator.h
@@ -17,6 +17,7 @@
 #include "googleurl/src/gurl.h"
 
 class AccessTokenStore;
+class GeolocationArbitratorDependencyFactory;
 class GURL;
 class LocationProviderBase;
 class URLRequestContextGetter;
@@ -35,32 +36,13 @@
   // Defines a function that returns the current time.
   typedef base::Time (*GetTimeNow)();
 
-  // Allows injection of factory methods for creating the location providers.
-  // RefCounted for simplicity of writing tests.
-  class ProviderFactory  : public base::RefCounted<ProviderFactory> {
-   public:
-    virtual LocationProviderBase* NewNetworkLocationProvider(
-        AccessTokenStore* access_token_store,
-        URLRequestContextGetter* context,
-        const GURL& url,
-        const string16& access_token) = 0;
-    virtual LocationProviderBase* NewSystemLocationProvider() = 0;
-
-   protected:
-    friend class base::RefCounted<ProviderFactory>;
-    virtual ~ProviderFactory();
-  };
-
-  GeolocationArbitrator(AccessTokenStore* access_token_store,
-                        URLRequestContextGetter* context_getter,
-                        GetTimeNow get_time_now,
-                        GeolocationObserver* observer,
-                        ProviderFactory* provider_factory);
   ~GeolocationArbitrator();
 
   static GeolocationArbitrator* Create(GeolocationObserver* observer);
 
-  void SetObserverOptions(const GeolocationObserverOptions& options);
+  // See more details in geolocation_provider.
+  void StartProviders(const GeolocationObserverOptions& options);
+  void StopProviders();
 
   // Called everytime permission is granted to a page for using geolocation.
   // This may either be through explicit user action (e.g. responding to the
@@ -73,18 +55,18 @@
   // OnPermissionGranted().
   bool HasPermissionBeenGranted() const;
 
-  // For testing, a factory function can be set which will be used to create
-  // a specified test provider. Pass NULL to reset to the default behavior.
-  // For finer grained control, use class ProviderFactory instead.
-  // TODO(joth): Move all tests to use ProviderFactory and remove this.
-  typedef LocationProviderBase* (*LocationProviderFactoryFunction)(void);
-  static void SetProviderFactoryForTest(
-      LocationProviderFactoryFunction factory_function);
+  // Call this function every time you need to create an specially parameterised
+  // arbitrator.
+  static void SetDependencyFactoryForTest(
+      GeolocationArbitratorDependencyFactory* factory);
 
   // ListenerInterface
   virtual void LocationUpdateAvailable(LocationProviderBase* provider);
 
  private:
+  GeolocationArbitrator(
+      GeolocationArbitratorDependencyFactory* dependency_factory,
+      GeolocationObserver* observer);
   // Takes ownership of |provider| on entry; it will either be added to
   // |providers_| or deleted on error (e.g. it fails to start).
   void RegisterProvider(LocationProviderBase* provider);
@@ -98,11 +80,11 @@
                            const Geoposition& new_position,
                            bool from_same_provider) const;
 
+  scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory_;
   scoped_refptr<AccessTokenStore> access_token_store_;
   scoped_refptr<URLRequestContextGetter> context_getter_;
   GetTimeNow get_time_now_;
   GeolocationObserver* observer_;
-  scoped_refptr<ProviderFactory> provider_factory_;
   ScopedVector<LocationProviderBase> providers_;
   GeolocationObserverOptions current_provider_options_;
   // The provider which supplied the current |position_|
diff --git a/chrome/browser/geolocation/location_arbitrator_unittest.cc b/chrome/browser/geolocation/location_arbitrator_unittest.cc
index 7a76566..b272edd 100644
--- a/chrome/browser/geolocation/location_arbitrator_unittest.cc
+++ b/chrome/browser/geolocation/location_arbitrator_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/geolocation/location_arbitrator.h"
 
 #include "base/scoped_ptr.h"
+#include "chrome/browser/geolocation/arbitrator_dependency_factory.h"
 #include "chrome/browser/geolocation/fake_access_token_store.h"
 #include "chrome/browser/geolocation/geolocation_observer.h"
 #include "chrome/browser/geolocation/location_provider.h"
@@ -29,10 +30,50 @@
   Geoposition last_position_;
 };
 
-class MockProviderFactory : public GeolocationArbitrator::ProviderFactory {
+double g_fake_time_now_secs = 1;
+
+base::Time GetTimeNowForTest() {
+  return base::Time::FromDoubleT(g_fake_time_now_secs);
+}
+
+void AdvanceTimeNow(const base::TimeDelta& delta) {
+  g_fake_time_now_secs += delta.InSecondsF();
+}
+
+void SetPositionFix(MockLocationProvider* provider,
+                    double latitude,
+                    double longitude,
+                    double accuracy) {
+  Geoposition position;
+  position.error_code = Geoposition::ERROR_CODE_NONE;
+  position.latitude = latitude;
+  position.longitude = longitude;
+  position.accuracy = accuracy;
+  position.timestamp = GetTimeNowForTest();
+  ASSERT_TRUE(position.IsInitialized());
+  ASSERT_TRUE(position.IsValidFix());
+  provider->HandlePositionChanged(position);
+}
+
+void SetReferencePosition(MockLocationProvider* provider) {
+  SetPositionFix(provider, 51.0, -0.1, 400);
+}
+
+class MockDependencyFactory : public GeolocationArbitratorDependencyFactory {
  public:
-  MockProviderFactory()
-      : cell_(NULL), gps_(NULL) {
+  explicit MockDependencyFactory(AccessTokenStore* access_token_store)
+      : cell_(NULL),
+        gps_(NULL),
+        access_token_store_(access_token_store) {
+  }
+  virtual GeolocationArbitrator::GetTimeNow GetTimeFunction() {
+    return GetTimeNowForTest;
+  }
+  virtual URLRequestContextGetter* GetContextGetter() {
+    return NULL;
+  }
+  virtual AccessTokenStore* NewAccessTokenStore() {
+    return access_token_store_.get();
   }
   virtual LocationProviderBase* NewNetworkLocationProvider(
       AccessTokenStore* access_token_store,
@@ -51,52 +92,26 @@
   // type).
   MockLocationProvider* cell_;
   MockLocationProvider* gps_;
+
+  scoped_refptr<AccessTokenStore> access_token_store_;
 };
 
-double g_fake_time_now_secs = 1;
-
-base::Time GetTimeNow() {
-  return base::Time::FromDoubleT(g_fake_time_now_secs);
-}
-
-void AdvanceTimeNow(const base::TimeDelta& delta) {
-  g_fake_time_now_secs += delta.InSecondsF();
-}
-
-void SetPositionFix(MockLocationProvider* provider,
-                    double latitude,
-                    double longitude,
-                    double accuracy) {
-  Geoposition position;
-  position.error_code = Geoposition::ERROR_CODE_NONE;
-  position.latitude = latitude;
-  position.longitude = longitude;
-  position.accuracy = accuracy;
-  position.timestamp = GetTimeNow();
-  ASSERT_TRUE(position.IsInitialized());
-  ASSERT_TRUE(position.IsValidFix());
-  provider->HandlePositionChanged(position);
-}
-
-void SetReferencePosition(MockLocationProvider* provider) {
-  SetPositionFix(provider, 51.0, -0.1, 400);
-}
-
 class GeolocationLocationArbitratorTest : public testing::Test {
  protected:
+  // testing::Test
   virtual void SetUp() {
     access_token_store_ = new FakeAccessTokenStore;
-    observer_.reset(new MockLocationObserver());
-    providers_ = new MockProviderFactory();
-    arbitrator_.reset(new GeolocationArbitrator(access_token_store_.get(),
-                                                NULL,
-                                                GetTimeNow,
-                                                observer_.get(),
-                                                providers_));
+    observer_.reset(new MockLocationObserver);
+    dependency_factory_ = new MockDependencyFactory(access_token_store_);
+    GeolocationArbitrator::SetDependencyFactoryForTest(
+        dependency_factory_.get());
+    arbitrator_.reset(GeolocationArbitrator::Create(observer_.get()));
   }
 
+  // testing::Test
   virtual void TearDown() {
-    providers_ = NULL;
+    GeolocationArbitrator::SetDependencyFactoryForTest(NULL);
+    dependency_factory_ = NULL;
   }
 
   void CheckLastPositionInfo(double latitude,
@@ -115,8 +130,16 @@
         GeolocationArbitrator::kFixStaleTimeoutMilliseconds + 1);
   }
 
+  MockLocationProvider* cell() {
+    return dependency_factory_->cell_;
+  }
+
+  MockLocationProvider* gps() {
+    return dependency_factory_->gps_;
+  }
+
   scoped_refptr<FakeAccessTokenStore> access_token_store_;
-  scoped_refptr<MockProviderFactory> providers_;
+  scoped_refptr<MockDependencyFactory> dependency_factory_;
   scoped_ptr<MockLocationObserver> observer_;
   scoped_ptr<GeolocationArbitrator> arbitrator_;
   MessageLoop loop_;
@@ -135,8 +158,8 @@
   EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted());
   // Can't check the provider has been notified without going through the
   // motions to create the provider (see next test).
-  EXPECT_FALSE(providers_->cell_);
-  EXPECT_FALSE(providers_->gps_);
+  EXPECT_FALSE(cell());
+  EXPECT_FALSE(gps());
 }
 
 TEST_F(GeolocationLocationArbitratorTest, NormalUsage) {
@@ -148,107 +171,107 @@
   EXPECT_TRUE(access_token_store_->access_token_set_.empty());
   ASSERT_TRUE(access_token_store_->request_);
 
-  EXPECT_FALSE(providers_->cell_);
-  EXPECT_FALSE(providers_->gps_);
+  EXPECT_FALSE(cell());
+  EXPECT_FALSE(gps());
   access_token_store_->NotifyDelegateTokensLoaded();
-  ASSERT_TRUE(providers_->cell_);
-  EXPECT_TRUE(providers_->gps_);
-  EXPECT_TRUE(providers_->cell_->has_listeners());
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->cell_->state_);
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->gps_->state_);
+  ASSERT_TRUE(cell());
+  EXPECT_TRUE(gps());
+  EXPECT_TRUE(cell()->has_listeners());
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
   EXPECT_FALSE(observer_->last_position_.IsInitialized());
 
-  SetReferencePosition(providers_->cell_);
+  SetReferencePosition(cell());
 
   EXPECT_TRUE(observer_->last_position_.IsInitialized());
-  EXPECT_EQ(providers_->cell_->position_.latitude,
+  EXPECT_EQ(cell()->position_.latitude,
             observer_->last_position_.latitude);
 
   EXPECT_FALSE(
-      providers_->cell_->permission_granted_url_.is_valid());
+      cell()->permission_granted_url_.is_valid());
   EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted());
   GURL frame_url("http://frame.test");
   arbitrator_->OnPermissionGranted(frame_url);
   EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted());
   EXPECT_TRUE(
-      providers_->cell_->permission_granted_url_.is_valid());
+      cell()->permission_granted_url_.is_valid());
   EXPECT_EQ(frame_url,
-            providers_->cell_->permission_granted_url_);
+            cell()->permission_granted_url_);
 }
 
 TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) {
   access_token_store_->NotifyDelegateTokensLoaded();
-  ASSERT_TRUE(providers_->cell_);
-  ASSERT_TRUE(providers_->gps_);
-  arbitrator_->SetObserverOptions(GeolocationObserverOptions(true));
-  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, providers_->cell_->state_);
-  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, providers_->gps_->state_);
-  arbitrator_->SetObserverOptions(GeolocationObserverOptions(false));
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->cell_->state_);
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->gps_->state_);
+  ASSERT_TRUE(cell());
+  ASSERT_TRUE(gps());
+  arbitrator_->StartProviders(GeolocationObserverOptions(true));
+  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, cell()->state_);
+  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, gps()->state_);
+  arbitrator_->StartProviders(GeolocationObserverOptions(false));
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
 }
 
-TEST_F(GeolocationLocationArbitratorTest, SetObserverOptionsAfterFixArrives) {
+TEST_F(GeolocationLocationArbitratorTest, StartProvidersAfterFixArrives) {
   access_token_store_->NotifyDelegateTokensLoaded();
-  ASSERT_TRUE(providers_->cell_);
-  ASSERT_TRUE(providers_->gps_);
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->cell_->state_);
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->gps_->state_);
-  SetReferencePosition(providers_->cell_);
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->cell_->state_);
-  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, providers_->gps_->state_);
-  arbitrator_->SetObserverOptions(GeolocationObserverOptions(true));
-  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, providers_->cell_->state_);
-  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, providers_->gps_->state_);
+  ASSERT_TRUE(cell());
+  ASSERT_TRUE(gps());
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
+  SetReferencePosition(cell());
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
+  EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
+  arbitrator_->StartProviders(GeolocationObserverOptions(true));
+  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, cell()->state_);
+  EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, gps()->state_);
 }
 
 TEST_F(GeolocationLocationArbitratorTest, Arbitration) {
   access_token_store_->NotifyDelegateTokensLoaded();
-  ASSERT_TRUE(providers_->cell_);
-  ASSERT_TRUE(providers_->gps_);
+  ASSERT_TRUE(cell());
+  ASSERT_TRUE(gps());
 
-  SetPositionFix(providers_->cell_, 1, 2, 150);
+  SetPositionFix(cell(), 1, 2, 150);
 
   // First position available
   EXPECT_TRUE(observer_->last_position_.IsValidFix());
   CheckLastPositionInfo(1, 2, 150);
 
-  SetPositionFix(providers_->gps_, 3, 4, 50);
+  SetPositionFix(gps(), 3, 4, 50);
 
   // More accurate fix available
   CheckLastPositionInfo(3, 4, 50);
 
-  SetPositionFix(providers_->cell_, 5, 6, 150);
+  SetPositionFix(cell(), 5, 6, 150);
 
   // New fix is available but it's less accurate, older fix should be kept.
   CheckLastPositionInfo(3, 4, 50);
 
   // Advance time, and notify once again
   AdvanceTimeNow(SwitchOnFreshnessCliff());
-  providers_->cell_->HandlePositionChanged(providers_->cell_->position_);
+  cell()->HandlePositionChanged(cell()->position_);
 
   // New fix is available, less accurate but fresher
   CheckLastPositionInfo(5, 6, 150);
 
   // Advance time, and set a low accuracy position
   AdvanceTimeNow(SwitchOnFreshnessCliff());
-  SetPositionFix(providers_->cell_, 5.676731, 139.629385, 1000);
+  SetPositionFix(cell(), 5.676731, 139.629385, 1000);
   CheckLastPositionInfo(5.676731, 139.629385, 1000);
 
   // 15 secs later, step outside. Switches to gps signal.
   AdvanceTimeNow(base::TimeDelta::FromSeconds(15));
-  SetPositionFix(providers_->gps_, 3.5676457, 139.629198, 50);
+  SetPositionFix(gps(), 3.5676457, 139.629198, 50);
   CheckLastPositionInfo(3.5676457, 139.629198, 50);
 
   // 5 mins later switch cells while walking. Stay on gps.
   AdvanceTimeNow(base::TimeDelta::FromMinutes(5));
-  SetPositionFix(providers_->cell_, 3.567832, 139.634648, 300);
-  SetPositionFix(providers_->gps_, 3.5677675, 139.632314, 50);
+  SetPositionFix(cell(), 3.567832, 139.634648, 300);
+  SetPositionFix(gps(), 3.5677675, 139.632314, 50);
   CheckLastPositionInfo(3.5677675, 139.632314, 50);
 
   // Ride train and gps signal degrades slightly. Stay on fresher gps
   AdvanceTimeNow(base::TimeDelta::FromMinutes(5));
-  SetPositionFix(providers_->gps_, 3.5679026, 139.634777, 300);
+  SetPositionFix(gps(), 3.5679026, 139.634777, 300);
   CheckLastPositionInfo(3.5679026, 139.634777, 300);
 
   // 14 minutes later
@@ -256,24 +279,24 @@
 
   // GPS reading misses a beat, but don't switch to cell yet to avoid
   // oscillating.
-  SetPositionFix(providers_->gps_, 3.5659005, 139.682579, 300);
+  SetPositionFix(gps(), 3.5659005, 139.682579, 300);
 
   AdvanceTimeNow(base::TimeDelta::FromSeconds(7));
-  SetPositionFix(providers_->cell_, 3.5689579, 139.691420, 1000);
+  SetPositionFix(cell(), 3.5689579, 139.691420, 1000);
   CheckLastPositionInfo(3.5659005, 139.682579, 300);
 
   // 1 minute later
   AdvanceTimeNow(base::TimeDelta::FromMinutes(1));
 
   // Enter tunnel. Stay on fresher gps for a moment.
-  SetPositionFix(providers_->cell_, 3.5657078, 139.68922, 300);
-  SetPositionFix(providers_->gps_, 3.5657104, 139.690341, 300);
+  SetPositionFix(cell(), 3.5657078, 139.68922, 300);
+  SetPositionFix(gps(), 3.5657104, 139.690341, 300);
   CheckLastPositionInfo(3.5657104, 139.690341, 300);
 
   // 2 minutes later
   AdvanceTimeNow(base::TimeDelta::FromMinutes(2));
   // Arrive in station. Cell moves but GPS is stale. Switch to fresher cell.
-  SetPositionFix(providers_->cell_, 3.5658700, 139.069979, 1000);
+  SetPositionFix(cell(), 3.5658700, 139.069979, 1000);
   CheckLastPositionInfo(3.5658700, 139.069979, 1000);
 }
 
diff --git a/chrome/browser/geolocation/network_location_provider_unittest.cc b/chrome/browser/geolocation/network_location_provider_unittest.cc
index 9bef39c..3969ad1 100644
--- a/chrome/browser/geolocation/network_location_provider_unittest.cc
+++ b/chrome/browser/geolocation/network_location_provider_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,6 +14,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
+
 // Constants used in multiple tests.
 const char kTestServerUrl[] = "https://www.geolocation.test/service";
 const char kTestHost[] = "myclienthost.test";
@@ -21,8 +22,6 @@
 // Using #define so we can easily paste this into various other strings.
 #define REFERENCE_ACCESS_TOKEN "2:k7j3G6LaL6u_lafw:4iXOeOpTh1glSXe"
 
-}  // namespace
-
 // Stops the specified (nested) message loop when the listener is called back.
 class MessageLoopQuitListener
     : public LocationProviderBase::ListenerInterface {
@@ -433,7 +432,7 @@
       "  \"access_token\": \"" REFERENCE_ACCESS_TOKEN "\""
       "}";
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, test_server_url_, URLRequestStatus(), 200,  // OK
+      fetcher, test_server_url_, net::URLRequestStatus(), 200,  // OK
       ResponseCookies(), kNoFixNetworkResponse);
 
   // This should have set the access token anyhow
@@ -467,7 +466,7 @@
       "  }"
       "}";
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, test_server_url_, URLRequestStatus(), 200,  // OK
+      fetcher, test_server_url_, net::URLRequestStatus(), 200,  // OK
       ResponseCookies(), kReferenceNetworkResponse);
 
   provider->GetPosition(&position);
@@ -505,7 +504,7 @@
   // ...reply with a network error.
   fetcher->delegate()->OnURLFetchComplete(
       fetcher, test_server_url_,
-      URLRequestStatus(URLRequestStatus::FAILED, -1),
+      net::URLRequestStatus(net::URLRequestStatus::FAILED, -1),
       200,  // should be ignored
       ResponseCookies(), "");
 
@@ -541,7 +540,7 @@
       "  \"access_token\": \"" REFERENCE_ACCESS_TOKEN "\""
       "}";
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, test_server_url_, URLRequestStatus(), 200,  // OK
+      fetcher, test_server_url_, net::URLRequestStatus(), 200,  // OK
       ResponseCookies(), kNoFixNetworkResponse);
 
   // This should have set the access token anyhow
@@ -576,7 +575,7 @@
       "  }"
       "}";
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, test_server_url_, URLRequestStatus(), 200,  // OK
+      fetcher, test_server_url_, net::URLRequestStatus(), 200,  // OK
       ResponseCookies(), kReferenceNetworkResponse_1);
 
   provider->GetPosition(&position);
@@ -616,7 +615,7 @@
       "  }"
       "}";
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, test_server_url_, URLRequestStatus(), 200,  // OK
+      fetcher, test_server_url_, net::URLRequestStatus(), 200,  // OK
       ResponseCookies(), kReferenceNetworkResponse_2);
 
   provider->GetPosition(&position);
@@ -649,7 +648,7 @@
       "  }"
       "}";
   fetcher->delegate()->OnURLFetchComplete(
-      fetcher, test_server_url_, URLRequestStatus(), 200,  // OK
+      fetcher, test_server_url_, net::URLRequestStatus(), 200,  // OK
       ResponseCookies(), kReferenceNetworkResponse_3);
 
   provider->GetPosition(&position);
@@ -779,3 +778,4 @@
   }
 }
 
+}  // namespace
diff --git a/chrome/browser/geolocation/network_location_request.cc b/chrome/browser/geolocation/network_location_request.cc
index cc56caf..928d621 100644
--- a/chrome/browser/geolocation/network_location_request.cc
+++ b/chrome/browser/geolocation/network_location_request.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -116,12 +116,13 @@
   return true;
 }
 
-void NetworkLocationRequest::OnURLFetchComplete(const URLFetcher* source,
-                                                const GURL& url,
-                                                const URLRequestStatus& status,
-                                                int response_code,
-                                                const ResponseCookies& cookies,
-                                                const std::string& data) {
+void NetworkLocationRequest::OnURLFetchComplete(
+    const URLFetcher* source,
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
+    const std::string& data) {
   DCHECK_EQ(url_fetcher_.get(), source);
   DCHECK(url_.possibly_invalid_spec() == url.possibly_invalid_spec());
 
@@ -281,7 +282,7 @@
     *out = value_as_int;
     return true;
   }
-  return value->GetAsReal(out);
+  return value->GetAsDouble(out);
 }
 
 bool ParseServerResponse(const std::string& response_body,
diff --git a/chrome/browser/geolocation/wifi_data_provider_common.cc b/chrome/browser/geolocation/wifi_data_provider_common.cc
index bfa1c5e..3874cfd 100644
--- a/chrome/browser/geolocation/wifi_data_provider_common.cc
+++ b/chrome/browser/geolocation/wifi_data_provider_common.cc
@@ -42,7 +42,7 @@
 bool WifiDataProviderCommon::GetData(WifiData *data) {
   DCHECK(CalledOnClientThread());
   DCHECK(data);
-  AutoLock lock(data_mutex_);
+  base::AutoLock lock(data_mutex_);
   *data = wifi_data_;
   // If we've successfully completed a scan, indicate that we have all of the
   // data we can get.
@@ -81,7 +81,7 @@
     ScheduleNextScan(polling_policy_->NoWifiInterval());
   } else {
     {
-      AutoLock lock(data_mutex_);
+      base::AutoLock lock(data_mutex_);
       update_available = wifi_data_.DiffersSignificantly(new_data);
       wifi_data_ = new_data;
     }
diff --git a/chrome/browser/geolocation/wifi_data_provider_common.h b/chrome/browser/geolocation/wifi_data_provider_common.h
index c647c06..70477c1 100644
--- a/chrome/browser/geolocation/wifi_data_provider_common.h
+++ b/chrome/browser/geolocation/wifi_data_provider_common.h
@@ -105,7 +105,7 @@
   void ScheduleNextScan(int interval);
 
   WifiData wifi_data_;
-  Lock data_mutex_;
+  base::Lock data_mutex_;
 
   // Whether we've successfully completed a scan for WiFi data (or the polling
   // thread has terminated early).
diff --git a/chrome/browser/geolocation/wifi_data_provider_common_unittest.cc b/chrome/browser/geolocation/wifi_data_provider_common_unittest.cc
index 256fbcb..783114c 100644
--- a/chrome/browser/geolocation/wifi_data_provider_common_unittest.cc
+++ b/chrome/browser/geolocation/wifi_data_provider_common_unittest.cc
@@ -19,6 +19,8 @@
 using testing::Invoke;
 using testing::Return;
 
+namespace {
+
 class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
  public:
   MockWlanApi() : calls_(0), bool_return_(true) {
@@ -225,3 +227,6 @@
   DeviceDataProvider<WifiData>::Unregister(&quit_listener);
   DeviceDataProvider<WifiData>::ResetFactory();
 }
+
+}  // namespace
+
diff --git a/chrome/browser/geolocation/win7_location_api_unittest_win.cc b/chrome/browser/geolocation/win7_location_api_unittest_win.cc
index a22b99b..66470cf 100644
--- a/chrome/browser/geolocation/win7_location_api_unittest_win.cc
+++ b/chrome/browser/geolocation/win7_location_api_unittest_win.cc
@@ -23,6 +23,8 @@
 using testing::Invoke;
 using testing::Return;
 
+namespace {
+
 class MockLatLongReport : public ILatLongReport {
  public:
   MockLatLongReport() : ref_count_(1) {
@@ -293,9 +295,8 @@
   Win7LocationApi* CreateMock() {
     MockLocation* locator = new MockLocation();
     locator_ = locator;
-    return new Win7LocationApi(NULL,
-                               &MockPropVariantToDoubleFunction,
-                               locator);
+    return Win7LocationApi::CreateForTesting(&MockPropVariantToDoubleFunction,
+                                             locator);
   }
 
   scoped_ptr<Win7LocationApi> api_;
@@ -332,3 +333,5 @@
   api_->GetPosition(&position);
   EXPECT_FALSE(position.IsValidFix());
 }
+
+}  // namespace
diff --git a/chrome/browser/geolocation/win7_location_api_win.cc b/chrome/browser/geolocation/win7_location_api_win.cc
index 7b6c3ca..7df0340 100644
--- a/chrome/browser/geolocation/win7_location_api_win.cc
+++ b/chrome/browser/geolocation/win7_location_api_win.cc
@@ -9,6 +9,7 @@
 #include "base/file_path.h"
 #include "base/logging.h"
 #include "base/path_service.h"
+#include "base/scoped_ptr.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/geoposition.h"
 
@@ -26,13 +27,18 @@
 }
 }
 
-Win7LocationApi::Win7LocationApi(
-    HINSTANCE prop_library,
+Win7LocationApi::Win7LocationApi()
+    : prop_lib_(0),
+      PropVariantToDouble_function_(0),
+      locator_(0) {
+}
+
+void Win7LocationApi::Init(HINSTANCE prop_library,
     PropVariantToDoubleFunction PropVariantToDouble_function,
-    ILocation* locator)
-    : prop_lib_(prop_library),
-      PropVariantToDouble_function_(PropVariantToDouble_function),
-      locator_(locator) {
+    ILocation* locator) {
+  prop_lib_ = prop_library;
+  PropVariantToDouble_function_ = PropVariantToDouble_function;
+  locator_ = locator;
 }
 
 Win7LocationApi::~Win7LocationApi() {
@@ -44,6 +50,8 @@
   if (!CommandLine::ForCurrentProcess()
       ->HasSwitch(switches::kExperimentalLocationFeatures))
     return NULL;
+
+  scoped_ptr<Win7LocationApi> result(new Win7LocationApi);
   // Load probsys.dll
   string16 lib_needed = L"propsys.dll";
   HINSTANCE prop_lib = LoadWin7Library(lib_needed);
@@ -69,9 +77,16 @@
   }
   IID reports_needed[] = { IID_ILatLongReport };
   result_type = locator->RequestPermissions(NULL, reports_needed, 1, TRUE);
-  return new Win7LocationApi(prop_lib,
-                             PropVariantToDouble_function,
-                             locator);
+  result->Init(prop_lib, PropVariantToDouble_function, locator);
+  return result.release();
+}
+
+Win7LocationApi* Win7LocationApi::CreateForTesting(
+    PropVariantToDoubleFunction PropVariantToDouble_function,
+    ILocation* locator) {
+  Win7LocationApi* result = new Win7LocationApi;
+  result->Init(NULL, PropVariantToDouble_function, locator);
+  return result;
 }
 
 void Win7LocationApi::GetPosition(Geoposition* position) {
@@ -101,19 +116,19 @@
   CComPtr<ILatLongReport> lat_long_report;
   result_type = locator_->GetReport(IID_ILatLongReport, &location_report);
   // Checks to see if location access is allowed.
-  if (result_type == E_ACCESSDENIED) 
+  if (result_type == E_ACCESSDENIED)
     position->error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
   // Checks for any other errors while requesting a location report.
-  if(!SUCCEEDED(result_type))
+  if (!SUCCEEDED(result_type))
     return false;
   result_type = location_report->QueryInterface(&lat_long_report);
-  if(!SUCCEEDED(result_type))
+  if (!SUCCEEDED(result_type))
     return false;
   result_type = lat_long_report->GetLatitude(&position->latitude);
-  if(!SUCCEEDED(result_type))
+  if (!SUCCEEDED(result_type))
     return false;
   result_type = lat_long_report->GetLongitude(&position->longitude);
-  if(!SUCCEEDED(result_type))
+  if (!SUCCEEDED(result_type))
     return false;
   result_type = lat_long_report->GetErrorRadius(&position->accuracy);
   if (!SUCCEEDED(result_type) || position->accuracy <= 0)
@@ -124,7 +139,7 @@
     position->altitude = temp_dbl;
   result_type = lat_long_report->GetAltitudeError(&temp_dbl);
   if (SUCCEEDED(result_type))
-    position->altitude_accuracy = temp_dbl; 
+    position->altitude_accuracy = temp_dbl;
   PROPVARIANT heading;
   PropVariantInit(&heading);
   result_type = lat_long_report->GetValue(
diff --git a/chrome/browser/geolocation/win7_location_api_win.h b/chrome/browser/geolocation/win7_location_api_win.h
index 78bbed4..afdf1b8 100644
--- a/chrome/browser/geolocation/win7_location_api_win.h
+++ b/chrome/browser/geolocation/win7_location_api_win.h
@@ -11,6 +11,7 @@
 #include <sensors.h>
 #include <Windows.h>
 
+#include "app/win/scoped_com_initializer.h"
 #include "base/time.h"
 
 struct Geoposition;
@@ -21,28 +22,35 @@
 
 class Win7LocationApi {
  public:
-  // Public for testing. See Create() below for normal usage.
-  Win7LocationApi(HINSTANCE prop_library,
-                  PropVariantToDoubleFunction PropVariantToDouble_function,
-                  ILocation* locator);
   virtual ~Win7LocationApi();
-
   // Attempts to load propsys.dll, initialise |location_| and requests the user
   // for access to location information. Creates and returns ownership of an
   // instance of Win7LocationApi if all succeed.
   static Win7LocationApi* Create();
+  static Win7LocationApi* CreateForTesting(
+            PropVariantToDoubleFunction PropVariantToDouble_function,
+            ILocation* locator);
   // Gives the best available position.
   // Returns false if no valid position is available.
   virtual void GetPosition(Geoposition* position);
   // Changes the "accuracy" needed. Affects power levels of devices.
   virtual bool SetHighAccuracy(bool acc);
 
+ protected:
+  Win7LocationApi();
+
  private:
+  void Init(HINSTANCE prop_library,
+            PropVariantToDoubleFunction PropVariantToDouble_function,
+            ILocation* locator);
+
   // Provides the best position fix if one is available.
   // Does this by requesting a location report and querying it to obtain
   // location information.
   virtual bool GetPositionIfFixed(Geoposition* position);
 
+  // Ensure that COM has been initialized for this thread.
+  app::win::ScopedCOMInitializer com_initializer_;
   // ILocation object that lets us communicate with the Location and
   // Sensors platform.
   CComPtr<ILocation> locator_;
diff --git a/chrome/browser/geolocation/win7_location_provider_unittest_win.cc b/chrome/browser/geolocation/win7_location_provider_unittest_win.cc
index ababadd..d997bf2 100644
--- a/chrome/browser/geolocation/win7_location_provider_unittest_win.cc
+++ b/chrome/browser/geolocation/win7_location_provider_unittest_win.cc
@@ -16,6 +16,7 @@
 using testing::Invoke;
 using testing::Return;
 
+namespace {
 
 class MockWin7LocationApi : public Win7LocationApi {
  public:
@@ -49,7 +50,7 @@
   }
 
  private:
-  MockWin7LocationApi() : Win7LocationApi(NULL, NULL, NULL) {
+  MockWin7LocationApi() {
     ON_CALL(*this, GetPosition(_))
         .WillByDefault(Invoke(this,
                               &MockWin7LocationApi::GetPositionValid));
@@ -136,3 +137,5 @@
   provider_->GetPosition(&position);
   EXPECT_FALSE(position.IsValidFix());
 }
+
+}  // namespace
\ No newline at end of file
diff --git a/chrome/browser/google/google_update.cc b/chrome/browser/google/google_update.cc
index f12192d..826b740 100644
--- a/chrome/browser/google/google_update.cc
+++ b/chrome/browser/google/google_update.cc
@@ -14,6 +14,7 @@
 #include "base/string_util.h"
 #include "base/task.h"
 #include "base/threading/thread.h"
+#include "base/win/registry.h"
 #include "base/win/windows_version.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/installer/util/browser_distribution.h"
@@ -26,12 +27,40 @@
 using views::Window;
 
 namespace {
+
+// The registry location of the Google Update policies.
+const wchar_t kGUPolicyRegistrySubKey[] =
+    L"SOFTWARE\\Policies\\Google\\Update";
+const wchar_t kGUPolicyGlobalValue[] = L"UpdateDefault";
+const wchar_t kGUPolicyAppValuePrefix[] = L"Update";
+const DWORD kGUPolicyUpdatesDisabled = 0;
+
+// Checks if the updates have been disabled by policy.
+bool IsUpdateDisabledByPolicy(const std::wstring& guid) {
+#if !defined(GOOGLE_CHROME_BUILD)
+  return true;
+#else
+  std::wstring value_name(kGUPolicyAppValuePrefix);
+  value_name.append(guid);
+  DWORD value = 0;
+  base::win::RegKey policy(HKEY_LOCAL_MACHINE,
+                           kGUPolicyRegistrySubKey, KEY_READ);
+  // Per application settings override global setting.
+  if ((policy.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) ||
+      (policy.ReadValueDW(kGUPolicyGlobalValue, &value) == ERROR_SUCCESS)) {
+    return value == kGUPolicyUpdatesDisabled;
+  }
+  return false;
+#endif  // defined(GOOGLE_CHROME_BUILD)
+}
+
 // Check if the currently running instance can be updated by Google Update.
 // Returns true only if the instance running is a Google Chrome
 // distribution installed in a standard location.
-bool CanUpdateCurrentChrome(const std::wstring& chrome_exe_path) {
+GoogleUpdateErrorCode CanUpdateCurrentChrome(
+    const std::wstring& chrome_exe_path) {
 #if !defined(GOOGLE_CHROME_BUILD)
-  return false;
+  return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
 #else
   // TODO(tommi): Check if using the default distribution is always the right
   // thing to do.
@@ -50,10 +79,17 @@
                << L"non-standard location: " << chrome_exe_path.c_str()
                << L". The standard location is: " << user_exe_path.c_str()
                << L" or " << machine_exe_path.c_str() << L".";
-    return false;
+    return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
   }
 
-  return true;
+  std::wstring app_guid = installer::GetAppGuidForUpdates(
+      !InstallUtil::IsPerUserInstall(chrome_exe_path.c_str()));
+  DCHECK(!app_guid.empty());
+
+  if (IsUpdateDisabledByPolicy(app_guid))
+    return GOOGLE_UPDATE_DISABLED_BY_POLICY;
+
+  return GOOGLE_UPDATE_NO_ERROR;
 #endif
 }
 
@@ -241,10 +277,10 @@
   std::transform(chrome_exe.begin(), chrome_exe.end(),
                  chrome_exe.begin(), tolower);
 
-  if (!CanUpdateCurrentChrome(chrome_exe)) {
+  GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe);
+  if (error_code != GOOGLE_UPDATE_NO_ERROR) {
     main_loop->PostTask(FROM_HERE, NewRunnableMethod(this,
-        &GoogleUpdate::ReportResults, UPGRADE_ERROR,
-        CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY));
+        &GoogleUpdate::ReportResults, UPGRADE_ERROR, error_code));
     return false;
   }
 
diff --git a/chrome/browser/google/google_update.h b/chrome/browser/google/google_update.h
index 24ff093..bb810a1 100644
--- a/chrome/browser/google/google_update.h
+++ b/chrome/browser/google/google_update.h
@@ -57,6 +57,8 @@
   // An error occurred while upgrading (or while checking for update).
   // Check the Google Update log in %TEMP% for more details.
   GOOGLE_UPDATE_ERROR_UPDATING,
+  // Updates can not be downloaded because the administrator has disabled them.
+  GOOGLE_UPDATE_DISABLED_BY_POLICY,
 };
 
 // The GoogleUpdateStatusListener interface is used by components to receive
diff --git a/chrome/browser/google/google_update_settings_unittest.cc b/chrome/browser/google/google_update_settings_unittest.cc
index 8dc56bb..13a7e33 100644
--- a/chrome/browser/google/google_update_settings_unittest.cc
+++ b/chrome/browser/google/google_update_settings_unittest.cc
@@ -9,7 +9,7 @@
 class GoogleUpdateTest : public PlatformTest {
 };
 
-TEST_F(GoogleUpdateTest, StatsConstent) {
+TEST_F(GoogleUpdateTest, StatsConsent) {
   // Stats are off by default.
   EXPECT_FALSE(GoogleUpdateSettings::GetCollectStatsConsent());
   // Stats reporting is ON.
diff --git a/chrome/browser/google/google_url_tracker.cc b/chrome/browser/google/google_url_tracker.cc
index 0070cfb..5c0e05d 100644
--- a/chrome/browser/google/google_url_tracker.cc
+++ b/chrome/browser/google/google_url_tracker.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/string_util.h"
@@ -23,6 +22,7 @@
 #include "grit/generated_resources.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request_status.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -73,15 +73,11 @@
                                     UTF8ToUTF16(new_google_url_.spec()));
 }
 
-int GoogleURLTrackerInfoBarDelegate::GetButtons() const {
-  return BUTTON_OK | BUTTON_CANCEL;
-}
-
 string16 GoogleURLTrackerInfoBarDelegate::GetButtonLabel(
     InfoBarButton button) const {
   return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
-                                   IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL :
-                                   IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
+      IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL :
+      IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
 }
 
 
@@ -213,7 +209,7 @@
 
 void GoogleURLTracker::OnURLFetchComplete(const URLFetcher* source,
                                           const GURL& url,
-                                          const URLRequestStatus& status,
+                                          const net::URLRequestStatus& status,
                                           int response_code,
                                           const ResponseCookies& cookies,
                                           const std::string& data) {
diff --git a/chrome/browser/google/google_url_tracker.h b/chrome/browser/google/google_url_tracker.h
index 7f58ab1..5edc75a 100644
--- a/chrome/browser/google/google_url_tracker.h
+++ b/chrome/browser/google/google_url_tracker.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -171,7 +171,7 @@
                                   GoogleURLTracker* google_url_tracker,
                                   const GURL& new_google_url);
 
-  // ConfirmInfoBarDelegate
+  // ConfirmInfoBarDelegate:
   virtual bool Accept();
   virtual bool Cancel();
   virtual void InfoBarClosed();
@@ -183,9 +183,8 @@
   const GURL new_google_url_;
 
  private:
-  // ConfirmInfoBarDelegate
+  // ConfirmInfoBarDelegate:
   virtual string16 GetMessageText() const;
-  virtual int GetButtons() const;
   virtual string16 GetButtonLabel(InfoBarButton button) const;
 
   DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerInfoBarDelegate);
diff --git a/chrome/browser/google/google_url_tracker_unittest.cc b/chrome/browser/google/google_url_tracker_unittest.cc
index 0892ee3..9507150 100644
--- a/chrome/browser/google/google_url_tracker_unittest.cc
+++ b/chrome/browser/google/google_url_tracker_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,7 +19,7 @@
 #include "chrome/test/testing_pref_service.h"
 #include "chrome/test/testing_profile.h"
 #include "net/url_request/url_request.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 // TestNotificationObserver ---------------------------------------------------
@@ -60,15 +60,16 @@
  public:
   TestInfoBarDelegate(GoogleURLTracker* google_url_tracker,
                       const GURL& new_google_url);
-  virtual ~TestInfoBarDelegate();
-
-  // InfoBarDelegate
-  virtual InfoBar* CreateInfoBar();
 
   GoogleURLTracker* google_url_tracker() const { return google_url_tracker_; }
   GURL new_google_url() const { return new_google_url_; }
 
  private:
+  virtual ~TestInfoBarDelegate();
+
+  // InfoBarDelegate:
+  virtual InfoBar* CreateInfoBar();
+
   GoogleURLTracker* google_url_tracker_;
   GURL new_google_url_;
 };
@@ -206,8 +207,8 @@
   if (!fetcher)
     return;
   fetcher->delegate()->OnURLFetchComplete(fetcher,
-      GURL(GoogleURLTracker::kSearchDomainCheckURL), URLRequestStatus(), 200,
-      ResponseCookies(), domain);
+      GURL(GoogleURLTracker::kSearchDomainCheckURL), net::URLRequestStatus(),
+      200, ResponseCookies(), domain);
   // At this point, |fetcher| is deleted.
   MessageLoop::current()->RunAllPending();
 }
@@ -294,11 +295,12 @@
 }
 
 void GoogleURLTrackerTest::InfoBarClosed() {
-  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
-      g_browser_process->google_url_tracker()->infobar_);
+  InfoBarDelegate* infobar = g_browser_process->google_url_tracker()->infobar_;
   ASSERT_TRUE(infobar);
-  ASSERT_TRUE(infobar->google_url_tracker());
-  infobar->google_url_tracker()->InfoBarClosed();
+  GoogleURLTracker* url_tracker =
+      static_cast<TestInfoBarDelegate*>(infobar)->google_url_tracker();
+  ASSERT_TRUE(url_tracker);
+  url_tracker->InfoBarClosed();
   delete infobar;
 }
 
diff --git a/chrome/browser/gpu_blacklist.cc b/chrome/browser/gpu_blacklist.cc
index 85063a8..33511bd 100644
--- a/chrome/browser/gpu_blacklist.cc
+++ b/chrome/browser/gpu_blacklist.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -135,6 +135,45 @@
   return kOsUnknown;
 }
 
+GpuBlacklist::StringInfo::StringInfo(const std::string& string_op,
+                                     const std::string& string_value) {
+  op_ = StringToOp(string_op);
+  value_ = StringToLowerASCII(string_value);
+}
+
+bool GpuBlacklist::StringInfo::Contains(const std::string& value) const {
+  std::string my_value = StringToLowerASCII(value);
+  switch (op_) {
+    case kContains:
+      return strstr(my_value.c_str(), value_.c_str()) != NULL;
+    case kBeginWith:
+      return StartsWithASCII(my_value, value_, false);
+    case kEndWith:
+      return EndsWith(my_value, value_, false);
+    case kEQ:
+      return value_ == my_value;
+    default:
+      return false;
+  }
+}
+
+bool GpuBlacklist::StringInfo::IsValid() const {
+  return op_ != kUnknown;
+}
+
+GpuBlacklist::StringInfo::Op GpuBlacklist::StringInfo::StringToOp(
+    const std::string& string_op) {
+  if (string_op == "=")
+    return kEQ;
+  else if (string_op == "contains")
+    return kContains;
+  else if (string_op == "beginwith")
+    return kBeginWith;
+  else if (string_op == "endwith")
+    return kEndWith;
+  return kUnknown;
+}
+
 GpuBlacklist::GpuBlacklistEntry*
 GpuBlacklist::GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(
     DictionaryValue* value) {
@@ -143,6 +182,12 @@
 
   GpuBlacklistEntry* entry = new GpuBlacklistEntry();
 
+  std::string id;
+  if (!value->GetString("id", &id) || !entry->SetId(id)) {
+    delete entry;
+    return NULL;
+  }
+
   DictionaryValue* os_value = NULL;
   if (value->GetDictionary("os", &os_value)) {
     std::string os_type;
@@ -179,6 +224,18 @@
     }
   }
 
+  DictionaryValue* driver_vendor_value = NULL;
+  if (value->GetDictionary("driver_vendor", &driver_vendor_value)) {
+    std::string vendor_op;
+    std::string vendor_value;
+    driver_vendor_value->GetString("op", &vendor_op);
+    driver_vendor_value->GetString("value", &vendor_value);
+    if (!entry->SetDriverVendorInfo(vendor_op, vendor_value)) {
+      delete entry;
+      return NULL;
+    }
+  }
+
   DictionaryValue* driver_version_value = NULL;
   if (value->GetDictionary("driver_version", &driver_version_value)) {
     std::string driver_version_op = "any";
@@ -194,6 +251,18 @@
     }
   }
 
+  DictionaryValue* gl_renderer_value = NULL;
+  if (value->GetDictionary("gl_renderer", &gl_renderer_value)) {
+    std::string renderer_op;
+    std::string renderer_value;
+    gl_renderer_value->GetString("op", &renderer_op);
+    gl_renderer_value->GetString("value", &renderer_value);
+    if (!entry->SetGLRendererInfo(renderer_op, renderer_value)) {
+      delete entry;
+      return NULL;
+    }
+  }
+
   ListValue* blacklist_value = NULL;
   if (!value->GetList("blacklist", &blacklist_value)) {
     delete entry;
@@ -220,10 +289,21 @@
 GpuBlacklist::GpuBlacklistEntry::~GpuBlacklistEntry() {}
 
 GpuBlacklist::GpuBlacklistEntry::GpuBlacklistEntry()
-    : vendor_id_(0),
+    : id_(0),
+      vendor_id_(0),
       device_id_(0) {
 }
 
+bool GpuBlacklist::GpuBlacklistEntry::SetId(
+    const std::string& id_string) {
+  int my_id;
+  if (base::HexStringToInt(id_string, &my_id) && my_id != 0) {
+    id_ = static_cast<uint32>(my_id);
+    return true;
+  }
+  return false;
+}
+
 bool GpuBlacklist::GpuBlacklistEntry::SetOsInfo(
     const std::string& os,
     const std::string& version_op,
@@ -247,6 +327,14 @@
                               reinterpret_cast<int*>(&device_id_));
 }
 
+bool GpuBlacklist::GpuBlacklistEntry::SetDriverVendorInfo(
+    const std::string& vendor_op,
+    const std::string& vendor_value) {
+  driver_vendor_info_.reset(
+      new StringInfo(vendor_op, vendor_value));
+  return driver_vendor_info_->IsValid();
+}
+
 bool GpuBlacklist::GpuBlacklistEntry::SetDriverVersionInfo(
     const std::string& version_op,
     const std::string& version_string,
@@ -256,6 +344,14 @@
   return driver_version_info_->IsValid();
 }
 
+bool GpuBlacklist::GpuBlacklistEntry::SetGLRendererInfo(
+    const std::string& renderer_op,
+    const std::string& renderer_value) {
+  gl_renderer_info_.reset(
+      new StringInfo(renderer_op, renderer_value));
+  return gl_renderer_info_->IsValid();
+}
+
 bool GpuBlacklist::GpuBlacklistEntry::SetBlacklistedFeatures(
     const std::vector<std::string>& blacklisted_features) {
   size_t size = blacklisted_features.size();
@@ -284,7 +380,9 @@
 bool GpuBlacklist::GpuBlacklistEntry::Contains(
     OsType os_type, const Version& os_version,
     uint32 vendor_id, uint32 device_id,
-    const Version& driver_version) const {
+    const std::string& driver_vendor,
+    const Version& driver_version,
+    const std::string& gl_renderer) const {
   DCHECK(os_type != kOsAny);
   if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version))
     return false;
@@ -292,22 +390,34 @@
     return false;
   if (device_id_ != 0 && device_id_ != device_id)
     return false;
-  if (driver_version_info_.get() == NULL)
-    return true;
-  return driver_version_info_->Contains(driver_version);
+  if (driver_vendor_info_.get() != NULL &&
+      !driver_vendor_info_->Contains(driver_vendor))
+    return false;
+  if (driver_version_info_.get() != NULL &&
+      !driver_version_info_->Contains(driver_version))
+    return false;
+  if (gl_renderer_info_.get() != NULL &&
+      !gl_renderer_info_->Contains(gl_renderer))
+    return false;
+  return true;
 }
 
 GpuBlacklist::OsType GpuBlacklist::GpuBlacklistEntry::GetOsType() const {
   if (os_info_.get() == NULL)
-    return kOsUnknown;
+    return kOsAny;
   return os_info_->type();
 }
 
+uint32 GpuBlacklist::GpuBlacklistEntry::id() const {
+  return id_;
+}
+
 GpuFeatureFlags GpuBlacklist::GpuBlacklistEntry::GetGpuFeatureFlags() const {
   return *feature_flags_;
 }
 
-GpuBlacklist::GpuBlacklist() {
+GpuBlacklist::GpuBlacklist()
+    : max_entry_id_(0) {
 }
 
 GpuBlacklist::~GpuBlacklist() {
@@ -322,11 +432,20 @@
   if (root.get() == NULL || !root->IsType(Value::TYPE_DICTIONARY))
     return false;
 
+  DictionaryValue* root_dictionary = static_cast<DictionaryValue*>(root.get());
+  DCHECK(root_dictionary);
+  std::string version_string;
+  root_dictionary->GetString("version", &version_string);
+  version_.reset(Version::GetVersionFromString(version_string));
+  if (version_.get() == NULL)
+    return false;
+
   ListValue* list = NULL;
-  static_cast<DictionaryValue*>(root.get())->GetList("entries", &list);
+  root_dictionary->GetList("entries", &list);
   if (list == NULL)
     return false;
 
+  uint32 max_entry_id = 0;
   for (size_t i = 0; i < list->GetSize(); ++i) {
     DictionaryValue* list_item = NULL;
     bool valid = list->GetDictionary(i, &list_item);
@@ -336,6 +455,8 @@
         GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(list_item);
     if (entry == NULL)
       break;
+    if (entry->id() > max_entry_id)
+      max_entry_id = entry->id();
     entries.push_back(entry);
   }
 
@@ -358,19 +479,21 @@
         delete entries[i];
     }
   }
+  max_entry_id_ = max_entry_id;
   return true;
 }
 
 GpuFeatureFlags GpuBlacklist::DetermineGpuFeatureFlags(
     GpuBlacklist::OsType os,
     Version* os_version,
-    const GPUInfo& gpu_info) const {
+    const GPUInfo& gpu_info) {
+  active_entries_.clear();
   GpuFeatureFlags flags;
   // No need to go through blacklist entries if GPUInfo isn't available.
-  if (gpu_info.progress() == GPUInfo::kUninitialized)
+  if (gpu_info.level() == GPUInfo::kUninitialized)
     return flags;
   scoped_ptr<Version> driver_version(
-      Version::GetVersionFromString(WideToASCII(gpu_info.driver_version())));
+      Version::GetVersionFromString(gpu_info.driver_version()));
   if (driver_version.get() == NULL)
     return flags;
 
@@ -391,6 +514,9 @@
                                         version_bugfix);
 #else
     version_string = base::SysInfo::OperatingSystemVersion();
+    size_t pos = version_string.find_first_not_of("0123456789.");
+    if (pos != std::string::npos)
+      version_string = version_string.substr(0, pos);
 #endif
     my_os_version.reset(Version::GetVersionFromString(version_string));
     os_version = my_os_version.get();
@@ -400,13 +526,44 @@
   for (size_t i = 0; i < blacklist_.size(); ++i) {
     if (blacklist_[i]->Contains(os, *os_version,
                                 gpu_info.vendor_id(), gpu_info.device_id(),
-                                *driver_version)) {
+                                gpu_info.driver_vendor(),
+                                *driver_version,
+                                gpu_info.gl_renderer())) {
       flags.Combine(blacklist_[i]->GetGpuFeatureFlags());
+      active_entries_.push_back(blacklist_[i]);
     }
   }
   return flags;
 }
 
+void GpuBlacklist::GetGpuFeatureFlagEntries(
+    GpuFeatureFlags::GpuFeatureType feature,
+    std::vector<uint32>& entry_ids) const {
+  entry_ids.clear();
+  for (size_t i = 0; i < active_entries_.size(); ++i) {
+    if ((feature & active_entries_[i]->GetGpuFeatureFlags().flags()) != 0)
+      entry_ids.push_back(active_entries_[i]->id());
+  }
+}
+
+uint32 GpuBlacklist::max_entry_id() const {
+  return max_entry_id_;
+}
+
+bool GpuBlacklist::GetVersion(uint16* major, uint16* minor) const {
+  DCHECK(major && minor);
+  *major = 0;
+  *minor = 0;
+  if (version_.get() == NULL)
+    return false;
+  const std::vector<uint16>& components_reference = version_->components();
+  if (components_reference.size() != 2)
+    return false;
+  *major = components_reference[0];
+  *minor = components_reference[1];
+  return true;
+}
+
 GpuBlacklist::OsType GpuBlacklist::GetOsType() {
 #if defined(OS_WIN)
   return kOsWin;
@@ -423,5 +580,6 @@
   for (size_t i = 0; i < blacklist_.size(); ++i)
     delete blacklist_[i];
   blacklist_.clear();
+  active_entries_.clear();
 }
 
diff --git a/chrome/browser/gpu_blacklist.h b/chrome/browser/gpu_blacklist.h
index 85c4145..e5e04b1 100644
--- a/chrome/browser/gpu_blacklist.h
+++ b/chrome/browser/gpu_blacklist.h
@@ -6,36 +6,6 @@
 #define CHROME_BROWSER_GPU_BLACKLIST_H_
 #pragma once
 
-// Determines whether certain gpu-related features are blacklisted or not.
-// A valid gpu_blacklist.json file are in the format of
-// {
-//   "entries": [
-//     { // entry 1
-//     },
-//     ...
-//     { // entry n
-//     }
-//   ]
-// }
-// Each entry contains the following fields:
-// "os", "vendor_id", "device_id", "driver_version", and "blacklist".
-// Only "blacklist" is mandatory.
-// 1. "os" contains "type" and an optional "version". "type" could be "macosx",
-//    "linux", "win", or "any".  "any" is the same as not specifying "os".
-//    "version" is a VERSION structure (defined later).
-// 2. "vendor_id" has the value of a string.
-// 3. "device_id" has the value of a string.
-// 4. "driver_version" is a VERSION structure (defined later).
-// 5. "blacklist" is a list of gpu feature strings, valid values include
-//    "accelerated_2d_canvas", "accelerated_compositing", "webgl", and "all".
-//    Currently whatever feature is selected, the effect is the same as "all",
-//    i.e., it's not supported to turn off one GPU feature and not the others.
-// VERSION includes "op" "number", and "number2".  "op" can be any of the
-// following value: "=", "<", "<=", ">", ">=", "any", "between".  "number2" is
-// only used if "op" is "between".  "number" is used for all "op" values except
-// "any". "number" and "number2" are in the format of x, x.x, x.x.x, ect.
-// Check out "gpu_blacklist_unittest.cc" for examples.
-
 #include <string>
 #include <vector>
 
@@ -74,7 +44,24 @@
   // current OS version.
   GpuFeatureFlags DetermineGpuFeatureFlags(OsType os,
                                            Version* os_version,
-                                           const GPUInfo& gpu_info) const;
+                                           const GPUInfo& gpu_info);
+
+  // Collects the entries that set the "feature" flag from the last
+  // DetermineGpuFeatureFlags() call.  This tells which entries are responsible
+  // for raising a certain flag, i.e, for blacklisting a certain feature.
+  // Examples of "feature":
+  //   kGpuFeatureAll - any of the supported features;
+  //   kGpuFeatureWebgl - a single feature;
+  //   kGpuFeatureWebgl | kGpuFeatureAcceleratedCompositing - two features.
+  void GetGpuFeatureFlagEntries(GpuFeatureFlags::GpuFeatureType feature,
+                                std::vector<uint32>& entry_ids) const;
+
+  // Return the largest entry id.  This is used for histogramming.
+  uint32 max_entry_id() const;
+
+  // Collects the version of the current blacklist.  Returns false and sets
+  // major and minor to 0 on failure.
+  bool GetVersion(uint16* major, uint16* monir) const;
 
  private:
   class VersionInfo {
@@ -134,6 +121,32 @@
     scoped_ptr<VersionInfo> version_info_;
   };
 
+  class StringInfo {
+   public:
+    StringInfo(const std::string& string_op, const std::string& string_value);
+
+    // Determines if a given string is included in the StringInfo.
+    bool Contains(const std::string& value) const;
+
+    // Determines if the StringInfo contains valid information.
+    bool IsValid() const;
+
+   private:
+    enum Op {
+      kContains,
+      kBeginWith,
+      kEndWith,
+      kEQ,  // =
+      kUnknown  // Indicates StringInfo data is invalid.
+    };
+
+    // Maps string to Op; returns kUnknown if it's not a valid Op.
+    static Op StringToOp(const std::string& string_op);
+
+    Op op_;
+    std::string value_;
+  };
+
   class GpuBlacklistEntry {
    public:
     // Constructs GpuBlacklistEntry from DictionaryValue loaded from json.
@@ -143,11 +156,16 @@
     // Determines if a given os/gc/driver is included in the Entry set.
     bool Contains(OsType os_type, const Version& os_version,
                   uint32 vendor_id, uint32 device_id,
-                  const Version& driver_version) const;
+                  const std::string& driver_vendor,
+                  const Version& driver_version,
+                  const std::string& gl_renderer) const;
 
     // Returns the OsType.
     OsType GetOsType() const;
 
+    // Returns the entry's unique id.  0 is reserved.
+    uint32 id() const;
+
     // Returns the GpuFeatureFlags.
     GpuFeatureFlags GetGpuFeatureFlags() const;
 
@@ -156,6 +174,8 @@
    private:
     GpuBlacklistEntry();
 
+    bool SetId(const std::string& id_string);
+
     bool SetOsInfo(const std::string& os,
                    const std::string& version_op,
                    const std::string& version_string,
@@ -165,17 +185,26 @@
 
     bool SetDeviceId(const std::string& device_id_string);
 
+    bool SetDriverVendorInfo(const std::string& vendor_op,
+                             const std::string& vendor_value);
+
     bool SetDriverVersionInfo(const std::string& version_op,
                               const std::string& version_string,
                               const std::string& version_string2);
 
+    bool SetGLRendererInfo(const std::string& renderer_op,
+                           const std::string& renderer_value);
+
     bool SetBlacklistedFeatures(
         const std::vector<std::string>& blacklisted_features);
 
+    uint32 id_;
     scoped_ptr<OsInfo> os_info_;
     uint32 vendor_id_;
     uint32 device_id_;
+    scoped_ptr<StringInfo> driver_vendor_info_;
     scoped_ptr<VersionInfo> driver_version_info_;
+    scoped_ptr<StringInfo> gl_renderer_info_;
     scoped_ptr<GpuFeatureFlags> feature_flags_;
   };
 
@@ -184,8 +213,16 @@
 
   void Clear();
 
+  scoped_ptr<Version> version_;
   std::vector<GpuBlacklistEntry*> blacklist_;
 
+  // This records all the blacklist entries that are appliable to the current
+  // user machine.  It is updated everytime DetermineGpuFeatureFlags() is
+  // called and is used later by GetGpuFeatureFlagEntries().
+  std::vector<GpuBlacklistEntry*> active_entries_;
+
+  uint32 max_entry_id_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuBlacklist);
 };
 
diff --git a/chrome/browser/gpu_blacklist_unittest.cc b/chrome/browser/gpu_blacklist_unittest.cc
index f30d2ab..a61cd28 100644
--- a/chrome/browser/gpu_blacklist_unittest.cc
+++ b/chrome/browser/gpu_blacklist_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/version.h"
 #include "chrome/browser/gpu_blacklist.h"
 #include "chrome/common/gpu_info.h"
@@ -9,14 +11,11 @@
 
 TEST(GpuBlacklistTest, BlacklistLogic) {
   GPUInfo gpu_info;
-  gpu_info.SetGraphicsInfo(0x10de,  // Vendor ID
-                           0x0640,  // Device ID
-                           L"1.6.18",  // Driver Version
-                           0x0114,  // Pixel Shader Version
-                           0x0114,  // Vertex Shader Version
-                           0x0201,  // GL version,
-                           true);  // can_lose_context
-  gpu_info.SetProgress(GPUInfo::kComplete);
+  gpu_info.SetVideoCardInfo(0x10de,  // Vendor ID
+                            0x0640);  // Device ID
+  gpu_info.SetDriverInfo("NVIDIA",  // Driver vendor
+                         "1.6.18");  // Driver Version
+  gpu_info.SetLevel(GPUInfo::kComplete);
   scoped_ptr<Version> os_version(Version::GetVersionFromString("10.6.4"));
 
   GpuBlacklist blacklist;
@@ -30,11 +29,15 @@
   const std::string empty_list_json =
       "{\n"
       "  \"name\": \"gpu blacklist\",\n"
-      "  \"version\": \"0.0\",\n"
+      "  \"version\": \"2.5\",\n"
       "  \"entries\": [\n"
       "  ]\n"
       "}";
   EXPECT_TRUE(blacklist.LoadGpuBlacklist(empty_list_json, false));
+  uint16 major, minor;
+  EXPECT_TRUE(blacklist.GetVersion(&major, &minor));
+  EXPECT_EQ(major, 2u);
+  EXPECT_EQ(minor, 5u);
   flags = blacklist.DetermineGpuFeatureFlags(
       GpuBlacklist::kOsMacosx, os_version.get(), gpu_info);
   EXPECT_EQ(flags.flags(), 0u);
@@ -46,6 +49,7 @@
       "  \"version\": \"0.1\",\n"
       "  \"entries\": [\n"
       "    {\n"
+      "      \"id\": \"5\",\n"
       "      \"os\": {\n"
       "        \"type\": \"macosx\",\n"
       "        \"version\": {\n"
@@ -80,6 +84,16 @@
   EXPECT_EQ(
       flags.flags(),
       static_cast<uint32>(GpuFeatureFlags::kGpuFeatureAcceleratedCompositing));
+  std::vector<uint32> entries;
+  blacklist.GetGpuFeatureFlagEntries(
+      GpuFeatureFlags::kGpuFeatureAcceleratedCompositing, entries);
+  EXPECT_EQ(entries.size(), 1u);
+  EXPECT_EQ(entries[0], 5u);
+  blacklist.GetGpuFeatureFlagEntries(
+      GpuFeatureFlags::kGpuFeatureAll, entries);
+  EXPECT_EQ(entries.size(), 1u);
+  EXPECT_EQ(entries[0], 5u);
+  EXPECT_EQ(blacklist.max_entry_id(), 5u);
 
   // Blacklist a vendor on all OS.
   const std::string vendor_json =
@@ -88,6 +102,7 @@
       "  \"version\": \"0.1\",\n"
       "  \"entries\": [\n"
       "    {\n"
+      "      \"id\": \"1\",\n"
       "      \"vendor_id\": \"0x10de\",\n"
       "      \"blacklist\": [\n"
       "        \"webgl\"\n"
@@ -95,6 +110,7 @@
       "    }\n"
       "  ]\n"
       "}";
+  // Blacklist entries won't be filtered to the current OS only upon loading.
   EXPECT_TRUE(blacklist.LoadGpuBlacklist(vendor_json, false));
   flags = blacklist.DetermineGpuFeatureFlags(
       GpuBlacklist::kOsMacosx, os_version.get(), gpu_info);
@@ -108,6 +124,23 @@
       GpuBlacklist::kOsLinux, os_version.get(), gpu_info);
   EXPECT_EQ(flags.flags(),
             static_cast<uint32>(GpuFeatureFlags::kGpuFeatureWebgl));
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX)
+  // Blacklist entries will be filtered to the current OS only upon loading.
+  EXPECT_TRUE(blacklist.LoadGpuBlacklist(vendor_json, true));
+  flags = blacklist.DetermineGpuFeatureFlags(
+      GpuBlacklist::kOsMacosx, os_version.get(), gpu_info);
+  EXPECT_EQ(flags.flags(),
+            static_cast<uint32>(GpuFeatureFlags::kGpuFeatureWebgl));
+  flags = blacklist.DetermineGpuFeatureFlags(
+      GpuBlacklist::kOsWin, os_version.get(), gpu_info);
+  EXPECT_EQ(flags.flags(),
+            static_cast<uint32>(GpuFeatureFlags::kGpuFeatureWebgl));
+  flags = blacklist.DetermineGpuFeatureFlags(
+      GpuBlacklist::kOsLinux, os_version.get(), gpu_info);
+  EXPECT_EQ(flags.flags(),
+            static_cast<uint32>(GpuFeatureFlags::kGpuFeatureWebgl));
+#endif
+
 
   // Blacklist a vendor on Linux only.
   const std::string vendor_linux_json =
@@ -116,6 +149,7 @@
       "  \"version\": \"0.1\",\n"
       "  \"entries\": [\n"
       "    {\n"
+      "      \"id\": \"1\",\n"
       "      \"os\": {\n"
       "        \"type\": \"linux\"\n"
       "      },\n"
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index 8e7ac68..64e8e46 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -5,16 +5,13 @@
 #include "chrome/browser/gpu_process_host.h"
 
 #include "app/app_switches.h"
-#include "app/resource_bundle.h"
-#include "base/command_line.h"
 #include "base/metrics/histogram.h"
+#include "base/ref_counted.h"
 #include "base/string_piece.h"
 #include "base/threading/thread.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gpu_blacklist.h"
 #include "chrome/browser/gpu_process_host_ui_shim.h"
-#include "chrome/browser/renderer_host/render_message_filter.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
 #include "chrome/common/chrome_switches.h"
@@ -22,26 +19,24 @@
 #include "chrome/common/gpu_info.h"
 #include "chrome/common/gpu_messages.h"
 #include "chrome/common/render_messages.h"
-#include "grit/browser_resources.h"
+#include "chrome/gpu/gpu_thread.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_switches.h"
 #include "media/base/media_switches.h"
 
 #if defined(OS_LINUX)
-// These two #includes need to come after render_messages.h.
-#include <gdk/gdkwindow.h>  // NOLINT
-#include <gdk/gdkx.h>  // NOLINT
-#include "app/x11_util.h"
-#include "gfx/gtk_native_view_id_manager.h"
-#include "gfx/size.h"
+#include "ui/gfx/gtk_native_view_id_manager.h"
 #endif  // defined(OS_LINUX)
 
 namespace {
 
 enum GPUProcessLifetimeEvent {
-  kLaunched,
-  kCrashed,
-  kGPUProcessLifetimeEvent_Max
+  LAUNCHED,
+  DIED_FIRST_TIME,
+  DIED_SECOND_TIME,
+  DIED_THIRD_TIME,
+  DIED_FOURTH_TIME,
+  GPU_PROCESS_LIFETIME_EVENT_MAX
   };
 
 // Tasks used by this file
@@ -75,8 +70,42 @@
                           FROM_HERE,
                           new RouteOnUIThreadTask(message));
 }
+
+bool SendDelayedMsg(IPC::Message* reply_msg) {
+  return GpuProcessHost::Get()->Send(reply_msg);
+}
+
 }  // anonymous namespace
 
+class GpuMainThread : public base::Thread {
+ public:
+  explicit GpuMainThread(const std::string& channel_id)
+      : base::Thread("CrGpuMain"),
+        channel_id_(channel_id) {
+  }
+
+  ~GpuMainThread() {
+    Stop();
+  }
+
+ protected:
+  virtual void Init() {
+    // Must be created on GPU thread.
+    gpu_thread_.reset(new GpuThread(channel_id_));
+    gpu_thread_->Init(base::Time::Now());
+  }
+
+  virtual void CleanUp() {
+    // Must be destroyed on GPU thread.
+    gpu_thread_.reset();
+  }
+
+ private:
+  scoped_ptr<GpuThread> gpu_thread_;
+  std::string channel_id_;
+  DISALLOW_COPY_AND_ASSIGN(GpuMainThread);
+};
+
 GpuProcessHost::GpuProcessHost()
     : BrowserChildProcessHost(GPU_PROCESS, NULL),
       initialized_(false),
@@ -85,10 +114,6 @@
 }
 
 GpuProcessHost::~GpuProcessHost() {
-  while (!queued_synchronization_replies_.empty()) {
-    delete queued_synchronization_replies_.front().reply;
-    queued_synchronization_replies_.pop();
-  }
   DCHECK_EQ(sole_instance_, this);
   sole_instance_ = NULL;
 }
@@ -105,9 +130,6 @@
 }
 
 bool GpuProcessHost::Init() {
-  if (!LoadGpuBlacklist())
-    return false;
-
   if (!CreateChannel())
     return false;
 
@@ -137,379 +159,35 @@
 
 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
   DCHECK(CalledOnValidThread());
-
-  if (message.routing_id() == MSG_ROUTING_CONTROL)
-    return OnControlMessageReceived(message);
-
   RouteOnUIThread(message);
   return true;
 }
 
-void GpuProcessHost::EstablishGpuChannel(int renderer_id,
-                                         RenderMessageFilter* filter) {
-  DCHECK(CalledOnValidThread());
-
-  if (Send(new GpuMsg_EstablishChannel(renderer_id))) {
-    sent_requests_.push(ChannelRequest(filter));
-  } else {
-    SendEstablishChannelReply(IPC::ChannelHandle(), GPUInfo(), filter);
-  }
-}
-
-void GpuProcessHost::Synchronize(IPC::Message* reply,
-                                 RenderMessageFilter* filter) {
-  DCHECK(CalledOnValidThread());
-
-  if (Send(new GpuMsg_Synchronize())) {
-    queued_synchronization_replies_.push(SynchronizationRequest(reply, filter));
-  } else {
-    SendSynchronizationReply(reply, filter);
-  }
-}
-
-GpuProcessHost::ChannelRequest::ChannelRequest(RenderMessageFilter* filter)
-    : filter(filter) {
-}
-
-GpuProcessHost::ChannelRequest::~ChannelRequest() {}
-
-GpuProcessHost::SynchronizationRequest::SynchronizationRequest(
-    IPC::Message* reply,
-    RenderMessageFilter* filter)
-    : reply(reply),
-      filter(filter) {
-}
-
-GpuProcessHost::SynchronizationRequest::~SynchronizationRequest() {}
-
-bool GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
-
-  IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply, OnSynchronizeReply)
-#if defined(OS_LINUX)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_GetViewXID, OnGetViewXID)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_ReleaseXID, OnReleaseXID)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_ResizeXID, OnResizeXID)
-#elif defined(OS_MACOSX)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSetIOSurface,
-                        OnAcceleratedSurfaceSetIOSurface)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
-                        OnAcceleratedSurfaceBuffersSwapped)
-#elif defined(OS_WIN)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_GetCompositorHostWindow,
-                                    OnGetCompositorHostWindow)
-#endif
-    // If the IO thread does not handle the message then automatically route it
-    // to the UI thread. The UI thread will report an error if it does not
-    // handle it.
-    IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message))
-  IPC_END_MESSAGE_MAP()
-
-  return true;
-}
-
-void GpuProcessHost::OnChannelEstablished(
-    const IPC::ChannelHandle& channel_handle,
-    const GPUInfo& gpu_info) {
-  GpuFeatureFlags gpu_feature_flags;
-  if (channel_handle.name.size() != 0) {
-    gpu_feature_flags = gpu_blacklist_->DetermineGpuFeatureFlags(
-        GpuBlacklist::kOsAny, NULL, gpu_info);
-  }
-  const ChannelRequest& request = sent_requests_.front();
-  // Currently if any of the GPU features are blacklised, we don't establish a
-  // GPU channel.
-  if (gpu_feature_flags.flags() != 0) {
-    Send(new GpuMsg_CloseChannel(channel_handle));
-    SendEstablishChannelReply(IPC::ChannelHandle(), gpu_info, request.filter);
-  } else {
-    SendEstablishChannelReply(channel_handle, gpu_info, request.filter);
-  }
-  sent_requests_.pop();
-}
-
-void GpuProcessHost::OnSynchronizeReply() {
-  // Guard against race conditions in abrupt GPU process termination.
-  if (queued_synchronization_replies_.size() > 0) {
-    const SynchronizationRequest& request =
-        queued_synchronization_replies_.front();
-    SendSynchronizationReply(request.reply, request.filter);
-    queued_synchronization_replies_.pop();
-  }
-}
-
-#if defined(OS_LINUX)
-
-namespace {
-
-void SendDelayedReply(IPC::Message* reply_msg) {
-  GpuProcessHost::Get()->Send(reply_msg);
-}
-
-void GetViewXIDDispatcher(gfx::NativeViewId id, IPC::Message* reply_msg) {
-  XID xid;
-
-  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
-  if (!manager->GetPermanentXIDForId(&xid, id)) {
-    DLOG(ERROR) << "Can't find XID for view id " << id;
-    xid = 0;
-  }
-
-  GpuHostMsg_GetViewXID::WriteReplyParams(reply_msg, xid);
-
-  // Have to reply from IO thread.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&SendDelayedReply, reply_msg));
-}
-
-void ReleaseXIDDispatcher(unsigned long xid) {
-  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
-  manager->ReleasePermanentXID(xid);
-}
-
-void ResizeXIDDispatcher(unsigned long xid, gfx::Size size,
-    IPC::Message *reply_msg) {
-  GdkWindow* window = reinterpret_cast<GdkWindow*>(gdk_xid_table_lookup(xid));
-  if (window) {
-    Display* display = GDK_WINDOW_XDISPLAY(window);
-    gdk_window_resize(window, size.width(), size.height());
-    XSync(display, False);
-  }
-
-  GpuHostMsg_ResizeXID::WriteReplyParams(reply_msg, (window != NULL));
-
-  // Have to reply from IO thread.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&SendDelayedReply, reply_msg));
-}
-
-}  // namespace
-
-void GpuProcessHost::OnGetViewXID(gfx::NativeViewId id,
-                                  IPC::Message *reply_msg) {
-  // Have to request a permanent XID from UI thread.
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableFunction(&GetViewXIDDispatcher, id, reply_msg));
-}
-
-void GpuProcessHost::OnReleaseXID(unsigned long xid) {
-  // Have to release a permanent XID from UI thread.
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableFunction(&ReleaseXIDDispatcher, xid));
-}
-
-void GpuProcessHost::OnResizeXID(unsigned long xid, gfx::Size size,
-                                 IPC::Message *reply_msg) {
-  // Have to resize the window from UI thread.
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableFunction(&ResizeXIDDispatcher, xid, size, reply_msg));
-}
-
-#elif defined(OS_MACOSX)
-
-namespace {
-
-class SetIOSurfaceDispatcher : public Task {
- public:
-  SetIOSurfaceDispatcher(
-      const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params)
-      : params_(params) {
-  }
-
-  void Run() {
-    RenderViewHost* host = RenderViewHost::FromID(params_.renderer_id,
-                                                  params_.render_view_id);
-    if (!host)
-      return;
-    RenderWidgetHostView* view = host->view();
-    if (!view)
-      return;
-    view->AcceleratedSurfaceSetIOSurface(params_.window,
-                                         params_.width,
-                                         params_.height,
-                                         params_.identifier);
-  }
-
- private:
-  GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params_;
-
-  DISALLOW_COPY_AND_ASSIGN(SetIOSurfaceDispatcher);
-};
-
-}  // namespace
-
-void GpuProcessHost::OnAcceleratedSurfaceSetIOSurface(
-    const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      new SetIOSurfaceDispatcher(params));
-}
-
-namespace {
-
-class BuffersSwappedDispatcher : public Task {
- public:
-  BuffersSwappedDispatcher(
-      int renderer_id,
-      int render_view_id,
-      gfx::PluginWindowHandle window,
-      uint64 surface_id,
-      int32 route_id,
-      uint64 swap_buffers_count)
-      : renderer_id_(renderer_id),
-        render_view_id_(render_view_id),
-        window_(window),
-        surface_id_(surface_id),
-        route_id_(route_id),
-        swap_buffers_count_(swap_buffers_count) {
-  }
-
-  void Run() {
-    RenderViewHost* host = RenderViewHost::FromID(renderer_id_,
-                                                  render_view_id_);
-    if (!host)
-      return;
-    RenderWidgetHostView* view = host->view();
-    if (!view)
-      return;
-    view->AcceleratedSurfaceBuffersSwapped(
-        // Parameters needed to swap the IOSurface.
-        window_,
-        surface_id_,
-        // Parameters needed to formulate an acknowledgment.
-        renderer_id_,
-        route_id_,
-        swap_buffers_count_);
-  }
-
- private:
-  int renderer_id_;
-  int render_view_id_;
-  gfx::PluginWindowHandle window_;
-  uint64 surface_id_;
-  int32 route_id_;
-  uint64 swap_buffers_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(BuffersSwappedDispatcher);
-};
-
-}  // namespace
-
-void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
-    const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      new BuffersSwappedDispatcher(
-          // These are the parameters needed to look up the IOSurface
-          // on this side.
-          params.renderer_id,
-          params.render_view_id,
-          params.window,
-          params.surface_id,
-          // These are additional parameters needed to formulate an
-          // acknowledgment.
-          params.route_id,
-          params.swap_buffers_count));
-}
-
-#elif defined(OS_WIN)
-
-namespace {
-
-void SendDelayedReply(IPC::Message* reply_msg) {
-  GpuProcessHost::Get()->Send(reply_msg);
-}
-
-void GetCompositorHostWindowDispatcher(
-    int renderer_id,
-    int render_view_id,
-    IPC::Message* reply_msg) {
-  RenderViewHost* host = RenderViewHost::FromID(renderer_id,
-                                                render_view_id);
-  if (!host) {
-    GpuHostMsg_GetCompositorHostWindow::WriteReplyParams(reply_msg,
-        gfx::kNullPluginWindow);
-    BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableFunction(&SendDelayedReply, reply_msg));
-    return;
-  }
-
-  RenderWidgetHostView* view = host->view();
-  gfx::PluginWindowHandle id = view->GetCompositorHostWindow();
-
-
-  GpuHostMsg_GetCompositorHostWindow::WriteReplyParams(reply_msg, id);
-  BrowserThread::PostTask(
-    BrowserThread::IO, FROM_HERE,
-    NewRunnableFunction(&SendDelayedReply, reply_msg));
-}
-
-}  // namespace
-
-void GpuProcessHost::OnGetCompositorHostWindow(
-    int renderer_id,
-    int render_view_id,
-    IPC::Message* reply_message) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableFunction(&GetCompositorHostWindowDispatcher,
-          renderer_id, render_view_id, reply_message));
-}
-
-#endif
-
-void GpuProcessHost::SendEstablishChannelReply(
-    const IPC::ChannelHandle& channel,
-    const GPUInfo& gpu_info,
-    RenderMessageFilter* filter) {
-  ViewMsg_GpuChannelEstablished* message =
-      new ViewMsg_GpuChannelEstablished(channel, gpu_info);
-  // If the renderer process is performing synchronous initialization,
-  // it needs to handle this message before receiving the reply for
-  // the synchronous ViewHostMsg_SynchronizeGpu message.
-  message->set_unblock(true);
-  filter->Send(message);
-}
-
-// Sends the response for synchronization request to the renderer.
-void GpuProcessHost::SendSynchronizationReply(
-    IPC::Message* reply,
-    RenderMessageFilter* filter) {
-  filter->Send(reply);
-}
-
-void GpuProcessHost::SendOutstandingReplies() {
-  // First send empty channel handles for all EstablishChannel requests.
-  while (!sent_requests_.empty()) {
-    const ChannelRequest& request = sent_requests_.front();
-    SendEstablishChannelReply(IPC::ChannelHandle(), GPUInfo(), request.filter);
-    sent_requests_.pop();
-  }
-
-  // Now unblock all renderers waiting for synchronization replies.
-  while (!queued_synchronization_replies_.empty()) {
-    OnSynchronizeReply();
-  }
-}
-
 bool GpuProcessHost::CanShutdown() {
   return true;
 }
 
+namespace {
+
+void SendOutstandingRepliesDispatcher() {
+  GpuProcessHostUIShim::GetInstance()->SendOutstandingReplies();
+}
+
+void SendOutstandingReplies() {
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableFunction(&SendOutstandingRepliesDispatcher));
+}
+
+}  // namespace
+
 void GpuProcessHost::OnChildDied() {
   SendOutstandingReplies();
   // Located in OnChildDied because OnProcessCrashed suffers from a race
-  // condition on Linux. The GPU process will only die if it crashes.
+  // condition on Linux.
   UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
-                            kCrashed, kGPUProcessLifetimeEvent_Max);
+                            DIED_FIRST_TIME + g_gpu_crash_count,
+                            GPU_PROCESS_LIFETIME_EVENT_MAX);
   BrowserChildProcessHost::OnChildDied();
 }
 
@@ -527,7 +205,29 @@
 }
 
 bool GpuProcessHost::LaunchGpuProcess() {
+  if (g_gpu_crash_count >= kGpuMaxCrashCount)
+    return false;
+
   const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+
+  // If the single-process switch is present, just launch the GPU service in a
+  // new thread in the browser process.
+  if (browser_command_line.HasSwitch(switches::kSingleProcess)) {
+    GpuMainThread* thread = new GpuMainThread(channel_id());
+
+    base::Thread::Options options;
+#if defined(OS_LINUX)
+    options.message_loop_type = MessageLoop::TYPE_IO;
+#else
+    options.message_loop_type = MessageLoop::TYPE_UI;
+#endif
+
+    if (!thread->StartWithOptions(options))
+      return false;
+
+    return true;
+  }
+
   CommandLine::StringType gpu_launcher =
       browser_command_line.GetSwitchValueNative(switches::kGpuLauncher);
 
@@ -539,6 +239,8 @@
   cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
   cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
 
+  SetCrashReporterCommandLine(cmd_line);
+
   // Propagate relevant command line switches.
   static const char* const kSwitchNames[] = {
     switches::kUseGL,
@@ -572,24 +274,6 @@
       cmd_line);
 
   UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
-                            kLaunched, kGPUProcessLifetimeEvent_Max);
+                            LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX);
   return true;
 }
-
-bool GpuProcessHost::LoadGpuBlacklist() {
-  if (gpu_blacklist_.get() != NULL)
-    return true;
-  static const base::StringPiece gpu_blacklist_json(
-      ResourceBundle::GetSharedInstance().GetRawDataResource(
-          IDR_GPU_BLACKLIST));
-  GpuBlacklist* blacklist = new GpuBlacklist();
-  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
-  if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) ||
-      blacklist->LoadGpuBlacklist(gpu_blacklist_json.as_string(), true)) {
-    gpu_blacklist_.reset(blacklist);
-    return true;
-  }
-  delete blacklist;
-  return false;
-}
-
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index 9a7a90d..4ac4326 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -6,26 +6,10 @@
 #define CHROME_BROWSER_GPU_PROCESS_HOST_H_
 #pragma once
 
-#include <queue>
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
 #include "base/threading/non_thread_safe.h"
 #include "chrome/browser/browser_child_process_host.h"
-#include "gfx/native_widget_types.h"
-
-struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params;
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-class GpuBlacklist;
-class GPUInfo;
-class RenderMessageFilter;
-
-namespace gfx {
-class Size;
-}
 
 namespace IPC {
-struct ChannelHandle;
 class Message;
 }
 
@@ -40,78 +24,13 @@
   // IPC::Channel::Listener implementation.
   virtual bool OnMessageReceived(const IPC::Message& message);
 
-  // Tells the GPU process to create a new channel for communication with a
-  // renderer. Will asynchronously send message to object with given routing id
-  // on completion.
-  void EstablishGpuChannel(int renderer_id, RenderMessageFilter* filter);
-
-  // Sends a reply message later when the next GpuHostMsg_SynchronizeReply comes
-  // in.
-  void Synchronize(IPC::Message* reply, RenderMessageFilter* filter);
-
  private:
-  // Used to queue pending channel requests.
-  struct ChannelRequest {
-    explicit ChannelRequest(RenderMessageFilter* filter);
-    ~ChannelRequest();
-
-    // Used to send the reply message back to the renderer.
-    scoped_refptr<RenderMessageFilter> filter;
-  };
-
-  // Used to queue pending synchronization requests.
-  struct SynchronizationRequest {
-    SynchronizationRequest(IPC::Message* reply, RenderMessageFilter* filter);
-    ~SynchronizationRequest();
-
-    // The delayed reply message which needs to be sent to the
-    // renderer.
-    IPC::Message* reply;
-
-    // Used to send the reply message back to the renderer.
-    scoped_refptr<RenderMessageFilter> filter;
-  };
-
   GpuProcessHost();
   virtual ~GpuProcessHost();
 
   bool EnsureInitialized();
   bool Init();
 
-  bool OnControlMessageReceived(const IPC::Message& message);
-
-  // Message handlers.
-  void OnChannelEstablished(const IPC::ChannelHandle& channel_handle,
-                            const GPUInfo& gpu_info);
-  void OnSynchronizeReply();
-#if defined(OS_LINUX)
-  void OnGetViewXID(gfx::NativeViewId id, IPC::Message* reply_msg);
-  void OnReleaseXID(unsigned long xid);
-  void OnResizeXID(unsigned long xid, gfx::Size size, IPC::Message* reply_msg);
-#elif defined(OS_MACOSX)
-  void OnAcceleratedSurfaceSetIOSurface(
-      const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params);
-  void OnAcceleratedSurfaceBuffersSwapped(
-      const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
-#elif defined(OS_WIN)
-  void OnGetCompositorHostWindow(int renderer_id,
-                                    int render_view_id,
-                                    IPC::Message* reply_message);
-#endif
-
-  // Sends the response for establish channel request to the renderer.
-  void SendEstablishChannelReply(const IPC::ChannelHandle& channel,
-                                 const GPUInfo& gpu_info,
-                                 RenderMessageFilter* filter);
-  // Sends the response for synchronization request to the renderer.
-  void SendSynchronizationReply(IPC::Message* reply,
-                                RenderMessageFilter* filter);
-
-  // Sends outstanding replies to renderer processes. This is only called
-  // in error situations like the GPU process crashing -- but is necessary
-  // to prevent the renderer process from hanging.
-  void SendOutstandingReplies();
-
   virtual bool CanShutdown();
   virtual void OnChildDied();
   virtual void OnProcessCrashed(int exit_code);
@@ -119,20 +38,9 @@
   bool CanLaunchGpuProcess() const;
   bool LaunchGpuProcess();
 
-  bool LoadGpuBlacklist();
-
   bool initialized_;
   bool initialized_successfully_;
 
-  scoped_ptr<GpuBlacklist> gpu_blacklist_;
-
-  // These are the channel requests that we have already sent to
-  // the GPU process, but haven't heard back about yet.
-  std::queue<ChannelRequest> sent_requests_;
-
-  // The pending synchronization requests we need to reply to.
-  std::queue<SynchronizationRequest> queued_synchronization_replies_;
-
   DISALLOW_COPY_AND_ASSIGN(GpuProcessHost);
 };
 
diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc
index 87c7be2..93d455a 100644
--- a/chrome/browser/gpu_process_host_ui_shim.cc
+++ b/chrome/browser/gpu_process_host_ui_shim.cc
@@ -4,11 +4,28 @@
 
 #include "chrome/browser/gpu_process_host_ui_shim.h"
 
+#include "base/command_line.h"
+#include "base/metrics/histogram.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/gpu_blacklist.h"
 #include "chrome/browser/gpu_process_host.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/common/child_process_logging.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/gpu_messages.h"
+#include "grit/browser_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if defined(OS_LINUX)
+// These two #includes need to come after gpu_messages.h.
+#include <gdk/gdkwindow.h>  // NOLINT
+#include <gdk/gdkx.h>  // NOLINT
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_native_view_id_manager.h"
+#include "ui/gfx/size.h"
+#endif  // defined(OS_LINUX)
 
 // Tasks used by this file
 namespace {
@@ -27,12 +44,28 @@
 
 }  // namespace
 
-GpuProcessHostUIShim::GpuProcessHostUIShim() : last_routing_id_(1) {
+GpuProcessHostUIShim::GpuProcessHostUIShim()
+    : last_routing_id_(1),
+      initialized_(false),
+      initialized_successfully_(false),
+      gpu_feature_flags_set_(false) {
 }
 
 GpuProcessHostUIShim::~GpuProcessHostUIShim() {
 }
 
+bool GpuProcessHostUIShim::EnsureInitialized() {
+  if (!initialized_) {
+    initialized_ = true;
+    initialized_successfully_ = Init();
+  }
+  return initialized_successfully_;
+}
+
+bool GpuProcessHostUIShim::Init() {
+  return LoadGpuBlacklist();
+}
+
 // static
 GpuProcessHostUIShim* GpuProcessHostUIShim::GetInstance() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -41,12 +74,87 @@
 
 bool GpuProcessHostUIShim::Send(IPC::Message* msg) {
   DCHECK(CalledOnValidThread());
+  if (!EnsureInitialized())
+    return false;
+
   BrowserThread::PostTask(BrowserThread::IO,
                           FROM_HERE,
                           new SendOnIOThreadTask(msg));
   return true;
 }
 
+// Post a Task to execute callbacks on a error conditions in order to
+// clear the call stacks (and aid debugging).
+namespace {
+
+void EstablishChannelCallbackDispatcher(
+    GpuProcessHostUIShim::EstablishChannelCallback* callback,
+    const IPC::ChannelHandle& channel_handle,
+    const GPUInfo& gpu_info) {
+  scoped_ptr<GpuProcessHostUIShim::EstablishChannelCallback>
+    wrapped_callback(callback);
+  wrapped_callback->Run(channel_handle, gpu_info);
+}
+
+void EstablishChannelError(
+    GpuProcessHostUIShim::EstablishChannelCallback* callback,
+    const IPC::ChannelHandle& channel_handle,
+    const GPUInfo& gpu_info) {
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableFunction(&EstablishChannelCallbackDispatcher,
+                          callback, channel_handle, gpu_info));
+}
+
+void SynchronizeCallbackDispatcher(
+    GpuProcessHostUIShim::SynchronizeCallback* callback) {
+  scoped_ptr<GpuProcessHostUIShim::SynchronizeCallback>
+    wrapped_callback(callback);
+  wrapped_callback->Run();
+}
+
+void SynchronizeError(
+    GpuProcessHostUIShim::SynchronizeCallback* callback) {
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableFunction(&SynchronizeCallbackDispatcher, callback));
+}
+
+void CreateCommandBufferCallbackDispatcher(
+    GpuProcessHostUIShim::CreateCommandBufferCallback* callback,
+    int32 route_id) {
+  scoped_ptr<GpuProcessHostUIShim::CreateCommandBufferCallback>
+    wrapped_callback(callback);
+  callback->Run(route_id);
+}
+
+void CreateCommandBufferError(
+    GpuProcessHostUIShim::CreateCommandBufferCallback* callback,
+    int32 route_id) {
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableFunction(&CreateCommandBufferCallbackDispatcher,
+                          callback, route_id));
+}
+
+}  // namespace
+
+void GpuProcessHostUIShim::SendOutstandingReplies() {
+  // First send empty channel handles for all EstablishChannel requests.
+  while (!channel_requests_.empty()) {
+    linked_ptr<EstablishChannelCallback> callback = channel_requests_.front();
+    channel_requests_.pop();
+    EstablishChannelError(callback.release(), IPC::ChannelHandle(), GPUInfo());
+  }
+
+  // Now unblock all renderers waiting for synchronization replies.
+  while (!synchronize_requests_.empty()) {
+    linked_ptr<SynchronizeCallback> callback = synchronize_requests_.front();
+    synchronize_requests_.pop();
+    SynchronizeError(callback.release());
+  }
+}
+
 int32 GpuProcessHostUIShim::GetNextRoutingId() {
   DCHECK(CalledOnValidThread());
   return ++last_routing_id_;
@@ -72,28 +180,94 @@
   return router_.RouteMessage(message);
 }
 
-void GpuProcessHostUIShim::CollectGraphicsInfoAsynchronously() {
+void GpuProcessHostUIShim::EstablishGpuChannel(
+    int renderer_id, EstablishChannelCallback *callback) {
   DCHECK(CalledOnValidThread());
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      new SendOnIOThreadTask(new GpuMsg_CollectGraphicsInfo()));
+  linked_ptr<EstablishChannelCallback> wrapped_callback(callback);
+
+  if (Send(new GpuMsg_EstablishChannel(renderer_id))) {
+    channel_requests_.push(wrapped_callback);
+  } else {
+    EstablishChannelError(
+        wrapped_callback.release(), IPC::ChannelHandle(), GPUInfo());
+  }
+}
+
+void GpuProcessHostUIShim::Synchronize(SynchronizeCallback* callback) {
+  DCHECK(CalledOnValidThread());
+  linked_ptr<SynchronizeCallback> wrapped_callback(callback);
+
+  if (Send(new GpuMsg_Synchronize())) {
+    synchronize_requests_.push(wrapped_callback);
+  } else {
+    SynchronizeError(wrapped_callback.release());
+  }
+}
+
+void GpuProcessHostUIShim::CreateViewCommandBuffer(
+    int32 render_view_id,
+    int32 renderer_id,
+    const GPUCreateCommandBufferConfig& init_params,
+    CreateCommandBufferCallback* callback) {
+  DCHECK(CalledOnValidThread());
+  linked_ptr<CreateCommandBufferCallback> wrapped_callback(callback);
+
+  gfx::PluginWindowHandle window = gfx::kNullPluginWindow;
+  RenderProcessHost* process = RenderProcessHost::FromID(renderer_id);
+  RenderWidgetHost* host = NULL;
+  if (process) {
+    host = static_cast<RenderWidgetHost*>(
+        process->GetListenerByID(render_view_id));
+  }
+
+  RenderWidgetHostView* view = NULL;
+  if (host)
+    view = host->view();
+
+  if (view) {
+#if defined(OS_LINUX)
+    gfx::NativeViewId view_id = NULL;
+    view_id = gfx::IdFromNativeView(view->GetNativeView());
+
+    // Lock the window that we will draw into.
+    GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
+    if (!manager->GetPermanentXIDForId(&window, view_id)) {
+      DLOG(ERROR) << "Can't find XID for view id " << view_id;
+    }
+#elif defined(OS_MACOSX)
+    // On Mac OS X we currently pass a (fake) PluginWindowHandle for the
+    // window that we draw to.
+    window = view->AllocateFakePluginWindowHandle(
+        /*opaque=*/true, /*root=*/true);
+#elif defined(OS_WIN)
+    // Create a window that we will overlay.
+    window = view->GetCompositorHostWindow();
+#endif
+  }
+
+  if (window != gfx::kNullPluginWindow &&
+      Send(new GpuMsg_CreateViewCommandBuffer(
+          window, render_view_id, renderer_id, init_params))) {
+    create_command_buffer_requests_.push(wrapped_callback);
+  } else {
+    CreateCommandBufferError(wrapped_callback.release(), MSG_ROUTING_NONE);
+  }
+}
+
+void GpuProcessHostUIShim::CollectGraphicsInfoAsynchronously(
+    GPUInfo::Level level) {
+  DCHECK(CalledOnValidThread());
+  Send(new GpuMsg_CollectGraphicsInfo(level));
 }
 
 void GpuProcessHostUIShim::SendAboutGpuCrash() {
   DCHECK(CalledOnValidThread());
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      new SendOnIOThreadTask(new GpuMsg_Crash()));
+  Send(new GpuMsg_Crash());
 }
 
 void GpuProcessHostUIShim::SendAboutGpuHang() {
   DCHECK(CalledOnValidThread());
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      new SendOnIOThreadTask(new GpuMsg_Hang()));
+  Send(new GpuMsg_Hang());
 }
 
 const GPUInfo& GpuProcessHostUIShim::gpu_info() const {
@@ -101,6 +275,143 @@
   return gpu_info_;
 }
 
+void GpuProcessHostUIShim::AddCustomLogMessage(int level,
+    const std::string& header,
+    const std::string& message) {
+ OnLogMessage(level, header, message);
+}
+
+bool GpuProcessHostUIShim::OnControlMessageReceived(
+    const IPC::Message& message) {
+  DCHECK(CalledOnValidThread());
+
+  IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished,
+                        OnChannelEstablished)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated,
+                        OnCommandBufferCreated)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer,
+                        OnDestroyCommandBuffer)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected,
+                        OnGraphicsInfoCollected)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage,
+                        OnLogMessage)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply,
+                        OnSynchronizeReply)
+#if defined(OS_LINUX)
+    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_ResizeXID, OnResizeXID)
+#elif defined(OS_MACOSX)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSetIOSurface,
+                        OnAcceleratedSurfaceSetIOSurface)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
+                        OnAcceleratedSurfaceBuffersSwapped)
+#elif defined(OS_WIN)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_ScheduleComposite, OnScheduleComposite);
+#endif
+    IPC_MESSAGE_UNHANDLED_ERROR()
+  IPC_END_MESSAGE_MAP()
+
+  return true;
+}
+
+void GpuProcessHostUIShim::OnChannelEstablished(
+    const IPC::ChannelHandle& channel_handle,
+    const GPUInfo& gpu_info) {
+  uint32 max_entry_id = gpu_blacklist_->max_entry_id();
+  // max_entry_id can be zero if we failed to load the GPU blacklist, don't
+  // bother with histograms then.
+  if (channel_handle.name.size() != 0 && !gpu_feature_flags_set_ &&
+      max_entry_id != 0)
+  {
+    gpu_feature_flags_set_ = true;
+
+    const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+    if (!browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist)) {
+      gpu_feature_flags_ = gpu_blacklist_->DetermineGpuFeatureFlags(
+          GpuBlacklist::kOsAny, NULL, gpu_info);
+
+      if (gpu_feature_flags_.flags() != 0) {
+        std::vector<uint32> flag_entries;
+        gpu_blacklist_->GetGpuFeatureFlagEntries(
+            GpuFeatureFlags::kGpuFeatureAll, flag_entries);
+        DCHECK_GT(flag_entries.size(), 0u);
+        for (size_t i = 0; i < flag_entries.size(); ++i) {
+          UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
+              flag_entries[i], max_entry_id + 1);
+        }
+      } else {
+        // id 0 is never used by any entry, so we use it here to indicate that
+        // gpu is allowed.
+        UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
+            0, max_entry_id + 1);
+      }
+    }
+  }
+  linked_ptr<EstablishChannelCallback> callback = channel_requests_.front();
+  channel_requests_.pop();
+
+  // Currently if any of the GPU features are blacklisted, we don't establish a
+  // GPU channel.
+  if (gpu_feature_flags_.flags() != 0) {
+    Send(new GpuMsg_CloseChannel(channel_handle));
+    EstablishChannelError(callback.release(), IPC::ChannelHandle(), gpu_info);
+    AddCustomLogMessage(logging::LOG_WARNING, "WARNING", "GPU is blacklisted.");
+  } else {
+    callback->Run(channel_handle, gpu_info);
+  }
+}
+
+void GpuProcessHostUIShim::OnSynchronizeReply() {
+  // Guard against race conditions in abrupt GPU process termination.
+  if (synchronize_requests_.size() > 0) {
+    linked_ptr<SynchronizeCallback> callback(synchronize_requests_.front());
+    synchronize_requests_.pop();
+    callback->Run();
+  }
+}
+
+void GpuProcessHostUIShim::OnCommandBufferCreated(const int32 route_id) {
+  if (create_command_buffer_requests_.size() > 0) {
+    linked_ptr<CreateCommandBufferCallback> callback =
+        create_command_buffer_requests_.front();
+    create_command_buffer_requests_.pop();
+    if (route_id == MSG_ROUTING_NONE)
+      CreateCommandBufferError(callback.release(), route_id);
+    else
+      callback->Run(route_id);
+  }
+}
+
+void GpuProcessHostUIShim::OnDestroyCommandBuffer(
+    gfx::PluginWindowHandle window, int32 renderer_id,
+    int32 render_view_id) {
+  if (!window)
+    return;
+
+#if defined(OS_LINUX)
+  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
+  manager->ReleasePermanentXID(window);
+#elif defined(OS_MACOSX) || defined(OS_WIN)
+  RenderProcessHost* process = RenderProcessHost::FromID(renderer_id);
+  RenderWidgetHost* host = NULL;
+  if (process) {
+    host = static_cast<RenderWidgetHost*>(
+        process->GetListenerByID(render_view_id));
+  }
+  RenderWidgetHostView* view = NULL;
+  if (host)
+    view = host->view();
+
+  if (view) {
+#if defined(OS_MACOSX)
+    view->DestroyFakePluginWindowHandle(window);
+#elif defined(OS_WIN)
+    view->ShowCompositorHostWindow(false);
+#endif
+  }
+#endif  // defined(OS_MACOSX) || defined(OS_WIN)
+}
+
 void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) {
   gpu_info_ = gpu_info;
   child_process_logging::SetGpuInfo(gpu_info);
@@ -110,6 +421,69 @@
     gpu_info_collected_callback_->Run();
 }
 
+void GpuProcessHostUIShim::OnLogMessage(int level,
+    const std::string& header,
+    const std::string& message) {
+  DictionaryValue* dict = new DictionaryValue();
+  dict->SetInteger("level", level);
+  dict->SetString("header", header);
+  dict->SetString("message", message);
+  log_messages_.Append(dict);
+}
+
+#if defined(OS_LINUX)
+
+void GpuProcessHostUIShim::OnResizeXID(unsigned long xid, gfx::Size size,
+                                       IPC::Message *reply_msg) {
+  GdkWindow* window = reinterpret_cast<GdkWindow*>(gdk_xid_table_lookup(xid));
+  if (window) {
+    Display* display = GDK_WINDOW_XDISPLAY(window);
+    gdk_window_resize(window, size.width(), size.height());
+    XSync(display, False);
+  }
+
+  GpuHostMsg_ResizeXID::WriteReplyParams(reply_msg, (window != NULL));
+  Send(reply_msg);
+}
+
+#elif defined(OS_MACOSX)
+
+void GpuProcessHostUIShim::OnAcceleratedSurfaceSetIOSurface(
+    const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params) {
+  RenderViewHost* host = RenderViewHost::FromID(params.renderer_id,
+                                                params.render_view_id);
+  if (!host)
+    return;
+  RenderWidgetHostView* view = host->view();
+  if (!view)
+    return;
+  view->AcceleratedSurfaceSetIOSurface(params.window,
+                                       params.width,
+                                       params.height,
+                                       params.identifier);
+}
+
+void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
+    const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
+  RenderViewHost* host = RenderViewHost::FromID(params.renderer_id,
+                                                params.render_view_id);
+  if (!host)
+    return;
+  RenderWidgetHostView* view = host->view();
+  if (!view)
+    return;
+  view->AcceleratedSurfaceBuffersSwapped(
+      // Parameters needed to swap the IOSurface.
+      params.window,
+      params.surface_id,
+      // Parameters needed to formulate an acknowledgment.
+      params.renderer_id,
+      params.route_id,
+      params.swap_buffers_count);
+}
+
+#elif defined(OS_WIN)
+
 void GpuProcessHostUIShim::OnScheduleComposite(int renderer_id,
     int render_view_id) {
   RenderViewHost* host = RenderViewHost::FromID(renderer_id,
@@ -120,18 +494,17 @@
   host->ScheduleComposite();
 }
 
-bool GpuProcessHostUIShim::OnControlMessageReceived(
-    const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
-
-  IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected,
-                        OnGraphicsInfoCollected)
-#if defined(OS_WIN)
-    IPC_MESSAGE_HANDLER(GpuHostMsg_ScheduleComposite, OnScheduleComposite);
 #endif
-    IPC_MESSAGE_UNHANDLED_ERROR()
-  IPC_END_MESSAGE_MAP()
 
-  return true;
+bool GpuProcessHostUIShim::LoadGpuBlacklist() {
+  if (gpu_blacklist_.get() != NULL)
+    return true;
+  static const base::StringPiece gpu_blacklist_json(
+      ResourceBundle::GetSharedInstance().GetRawDataResource(
+          IDR_GPU_BLACKLIST));
+  gpu_blacklist_.reset(new GpuBlacklist());
+  if (gpu_blacklist_->LoadGpuBlacklist(gpu_blacklist_json.as_string(), true))
+    return true;
+  gpu_blacklist_.reset(NULL);
+  return false;
 }
diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h
index 17bf970..396c2fc 100644
--- a/chrome/browser/gpu_process_host_ui_shim.h
+++ b/chrome/browser/gpu_process_host_ui_shim.h
@@ -11,14 +11,34 @@
 // portion of this class, the GpuProcessHost, is responsible for
 // shuttling messages between the browser and GPU processes.
 
+#include <queue>
+
 #include "base/callback.h"
+#include "base/linked_ptr.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
+#include "base/values.h"
 #include "base/threading/non_thread_safe.h"
+#include "chrome/common/gpu_feature_flags.h"
 #include "chrome/common/gpu_info.h"
 #include "chrome/common/message_router.h"
 #include "ipc/ipc_channel.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Size;
+}
+
+class GpuBlacklist;
+struct GPUCreateCommandBufferConfig;
+class GPUInfo;
+struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params;
+struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
+
+namespace IPC {
+struct ChannelHandle;
+class Message;
+}
 
 class GpuProcessHostUIShim : public IPC::Channel::Sender,
                              public IPC::Channel::Listener,
@@ -32,19 +52,49 @@
   // IPC::Channel::Sender implementation.
   virtual bool Send(IPC::Message* msg);
 
+  // Sends outstanding replies. This is only called
+  // in error situations like the GPU process crashing -- but is necessary
+  // to prevent the blocked clients from hanging.
+  void SendOutstandingReplies();
+
   // IPC::Channel::Listener implementation.
   // The GpuProcessHost causes this to be called on the UI thread to
   // dispatch the incoming messages from the GPU process, which are
   // actually received on the IO thread.
   virtual bool OnMessageReceived(const IPC::Message& message);
 
+  typedef Callback2<const IPC::ChannelHandle&, const GPUInfo&>::Type
+    EstablishChannelCallback;
+
+  // Tells the GPU process to create a new channel for communication with a
+  // renderer. Once the GPU process responds asynchronously with the IPC handle
+  // and GPUInfo, we call the callback.
+  void EstablishGpuChannel(
+      int renderer_id, EstablishChannelCallback* callback);
+
+  typedef Callback0::Type SynchronizeCallback;
+
+  // Sends a reply message later when the next GpuHostMsg_SynchronizeReply comes
+  // in.
+  void Synchronize(SynchronizeCallback* callback);
+
+  typedef Callback1<int32>::Type CreateCommandBufferCallback;
+
+  // Tells the GPU process to create a new command buffer that draws into the
+  // window associated with the given renderer.
+  void CreateViewCommandBuffer(
+      int32 render_view_id,
+      int32 renderer_id,
+      const GPUCreateCommandBufferConfig& init_params,
+      CreateCommandBufferCallback* callback);
+
   // See documentation on MessageRouter for AddRoute and RemoveRoute
   void AddRoute(int32 routing_id, IPC::Channel::Listener* listener);
   void RemoveRoute(int32 routing_id);
 
   // Sends a message to the browser process to collect the information from the
   // graphics card.
-  void CollectGraphicsInfoAsynchronously();
+  void CollectGraphicsInfoAsynchronously(GPUInfo::Level level);
 
   // Tells the GPU process to crash. Useful for testing.
   void SendAboutGpuCrash();
@@ -63,26 +113,76 @@
     gpu_info_collected_callback_.reset(callback);
   }
 
+  ListValue* logMessages() const { return log_messages_.DeepCopy(); }
+
+  // Can be called directly from the UI thread to log a message.
+  void AddCustomLogMessage(int level, const std::string& header,
+      const std::string& message);
+
+  bool LoadGpuBlacklist();
+
  private:
   friend struct DefaultSingletonTraits<GpuProcessHostUIShim>;
 
   GpuProcessHostUIShim();
   virtual ~GpuProcessHostUIShim();
 
+  // TODO(apatrick): Following the pattern from GpuProcessHost. Talk to zmo
+  // and see if we can find a better mechanism.
+  bool EnsureInitialized();
+  bool Init();
+
   // Message handlers.
-  void OnGraphicsInfoCollected(const GPUInfo& gpu_info);
-  void OnScheduleComposite(int32 renderer_id, int32 render_view_id);
   bool OnControlMessageReceived(const IPC::Message& message);
 
+  void OnChannelEstablished(const IPC::ChannelHandle& channel_handle,
+                            const GPUInfo& gpu_info);
+  void OnCommandBufferCreated(const int32 route_id);
+  void OnDestroyCommandBuffer(gfx::PluginWindowHandle window,
+                              int32 renderer_id, int32 render_view_id);
+  void OnGraphicsInfoCollected(const GPUInfo& gpu_info);
+  void OnLogMessage(int level, const std::string& header,
+      const std::string& message);
+  void OnSynchronizeReply();
+#if defined(OS_LINUX)
+  void OnResizeXID(unsigned long xid, gfx::Size size, IPC::Message* reply_msg);
+#elif defined(OS_MACOSX)
+  void OnAcceleratedSurfaceSetIOSurface(
+      const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params);
+  void OnAcceleratedSurfaceBuffersSwapped(
+      const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
+#elif defined(OS_WIN)
+  void OnScheduleComposite(int32 renderer_id, int32 render_view_id);
+#endif
+
   int last_routing_id_;
 
   GPUInfo gpu_info_;
+  ListValue log_messages_;
 
   MessageRouter router_;
 
   // Used only in testing. If set, the callback is invoked when the GPU info
   // has been collected.
   scoped_ptr<Callback0::Type> gpu_info_collected_callback_;
+
+  // These are the channel requests that we have already sent to
+  // the GPU process, but haven't heard back about yet.
+  std::queue<linked_ptr<EstablishChannelCallback> > channel_requests_;
+
+  // The pending synchronization requests we need to reply to.
+  std::queue<linked_ptr<SynchronizeCallback> > synchronize_requests_;
+
+  // The pending create command buffer requests we need to reply to.
+  std::queue<linked_ptr<CreateCommandBufferCallback> >
+      create_command_buffer_requests_;
+
+  bool initialized_;
+  bool initialized_successfully_;
+
+  bool gpu_feature_flags_set_;
+  scoped_ptr<GpuBlacklist> gpu_blacklist_;
+  GpuFeatureFlags gpu_feature_flags_;
 };
 
 #endif  // CHROME_BROWSER_GPU_PROCESS_HOST_UI_SHIM_H_
diff --git a/chrome/browser/gtk/about_chrome_dialog.cc b/chrome/browser/gtk/about_chrome_dialog.cc
deleted file mode 100644
index 3d1ffa9..0000000
--- a/chrome/browser/gtk/about_chrome_dialog.cc
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/about_chrome_dialog.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_version_info.h"
-#include "chrome/common/url_constants.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-#include "webkit/glue/webkit_glue.h"
-
-namespace {
-
-// Left or right margin.
-const int kPanelHorizMargin = 13;
-
-// Top or bottom margin.
-const int kPanelVertMargin = 20;
-
-// Extra spacing between product name and version number.
-const int kExtraLineSpacing = 5;
-
-// These are used as placeholder text around the links in the text in the about
-// dialog.
-const char* kBeginLinkChr = "BEGIN_LINK_CHR";
-const char* kBeginLinkOss = "BEGIN_LINK_OSS";
-// We don't actually use this one.
-// const char* kEndLinkChr = "END_LINK_CHR";
-const char* kEndLinkOss = "END_LINK_OSS";
-const char* kBeginLink = "BEGIN_LINK";
-const char* kEndLink = "END_LINK";
-
-void OnDialogResponse(GtkDialog* dialog, int response_id) {
-  // We're done.
-  gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-void FixLabelWrappingCallback(GtkWidget *label,
-                              GtkAllocation *allocation,
-                              gpointer data) {
-  gtk_widget_set_size_request(label, allocation->width, -1);
-}
-
-GtkWidget* MakeMarkupLabel(const char* format, const std::string& str) {
-  GtkWidget* label = gtk_label_new(NULL);
-  char* markup = g_markup_printf_escaped(format, str.c_str());
-  gtk_label_set_markup(GTK_LABEL(label), markup);
-  g_free(markup);
-
-  // Left align it.
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
-  return label;
-}
-
-void OnLinkButtonClick(GtkWidget* button, const char* url) {
-  BrowserList::GetLastActive()->
-      OpenURL(GURL(url), GURL(), NEW_WINDOW, PageTransition::LINK);
-}
-
-const char* GetChromiumUrl() {
-  static GURL url = google_util::AppendGoogleLocaleParam(
-      GURL(chrome::kChromiumProjectURL));
-  return url.spec().c_str();
-}
-
-gboolean OnEventBoxExpose(GtkWidget* event_box,
-                          GdkEventExpose* expose,
-                          gboolean user_data) {
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(event_box->window));
-  gdk_cairo_rectangle(cr, &expose->area);
-  cairo_clip(cr);
-  GtkThemeProvider* theme_provider =
-      GtkThemeProvider::GetFrom(BrowserList::GetLastActive()->profile());
-  CairoCachedSurface* background = theme_provider->GetSurfaceNamed(
-      IDR_ABOUT_BACKGROUND_COLOR, event_box);
-
-  background->SetSource(cr, 0, 0);
-  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-  gdk_cairo_rectangle(cr, &expose->area);
-  cairo_fill(cr);
-  cairo_destroy(cr);
-  return FALSE;
-}
-
-}  // namespace
-
-void ShowAboutDialogForProfile(GtkWindow* parent, Profile* profile) {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  static GdkPixbuf* background = rb.GetPixbufNamed(IDR_ABOUT_BACKGROUND);
-  chrome::VersionInfo version_info;
-  std::string current_version = version_info.Version();
-#if !defined(GOOGLE_CHROME_BUILD)
-  current_version += " (";
-  current_version += version_info.LastChange();
-  current_version += ")";
-#endif
-  std::string channel = platform_util::GetVersionStringModifier();
-  if (!channel.empty())
-    current_version += " " + channel;
-
-  // Build the dialog.
-  GtkWidget* dialog = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_ABOUT_CHROME_TITLE).c_str(),
-      parent,
-      GTK_DIALOG_MODAL,
-      NULL);
-  // Pick up the style set in gtk_util.cc:InitRCStyles().
-  // The layout of this dialog is special because the logo should be flush
-  // with the edges of the window.
-  gtk_widget_set_name(dialog, "about-dialog");
-  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
-
-  GtkWidget* close_button = gtk_dialog_add_button(GTK_DIALOG(dialog),
-      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
-
-  GtkWidget* content_area = GTK_DIALOG(dialog)->vbox;
-
-  // Use an event box to get the background painting correctly
-  GtkWidget* ebox = gtk_event_box_new();
-  gtk_widget_set_app_paintable(ebox, TRUE);
-  g_signal_connect(ebox, "expose-event", G_CALLBACK(OnEventBoxExpose), NULL);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-
-  GtkWidget* text_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(text_alignment),
-                            kPanelVertMargin, kPanelVertMargin,
-                            kPanelHorizMargin, kPanelHorizMargin);
-
-  GtkWidget* text_vbox = gtk_vbox_new(FALSE, kExtraLineSpacing);
-
-  GdkColor black = gtk_util::kGdkBlack;
-  GtkWidget* product_label = MakeMarkupLabel(
-      "<span font_desc=\"18\" style=\"normal\">%s</span>",
-      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
-  gtk_widget_modify_fg(product_label, GTK_STATE_NORMAL, &black);
-  gtk_box_pack_start(GTK_BOX(text_vbox), product_label, FALSE, FALSE, 0);
-
-  GtkWidget* version_label = gtk_label_new(current_version.c_str());
-  gtk_misc_set_alignment(GTK_MISC(version_label), 0.0, 0.5);
-  gtk_label_set_selectable(GTK_LABEL(version_label), TRUE);
-  gtk_widget_modify_fg(version_label, GTK_STATE_NORMAL, &black);
-  gtk_box_pack_start(GTK_BOX(text_vbox), version_label, FALSE, FALSE, 0);
-
-  gtk_container_add(GTK_CONTAINER(text_alignment), text_vbox);
-  gtk_box_pack_start(GTK_BOX(hbox), text_alignment, TRUE, TRUE, 0);
-
-  GtkWidget* image_vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(image_vbox),
-                   gtk_image_new_from_pixbuf(background),
-                   FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(hbox), image_vbox, FALSE, FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(ebox), hbox);
-  gtk_box_pack_start(GTK_BOX(content_area), ebox, TRUE, TRUE, 0);
-
-  // We use a separate box for the licensing etc. text.  See the comment near
-  // the top of this function about using a special layout for this dialog.
-  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
-
-  GtkWidget* copyright_label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_COPYRIGHT).c_str());
-  gtk_misc_set_alignment(GTK_MISC(copyright_label), 0.0, 0.5);
-  gtk_box_pack_start(GTK_BOX(vbox), copyright_label, FALSE, FALSE, 5);
-
-  std::string license = l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_LICENSE);
-  bool chromium_url_appears_first =
-      license.find(kBeginLinkChr) < license.find(kBeginLinkOss);
-  size_t link1 = license.find(kBeginLink);
-  DCHECK(link1 != std::string::npos);
-  size_t link1_end = license.find(kEndLink, link1);
-  DCHECK(link1_end != std::string::npos);
-  size_t link2 = license.find(kBeginLink, link1_end);
-  DCHECK(link2 != std::string::npos);
-  size_t link2_end = license.find(kEndLink, link2);
-  DCHECK(link1_end != std::string::npos);
-
-  GtkWidget* license_chunk1 = gtk_label_new(license.substr(0, link1).c_str());
-  gtk_misc_set_alignment(GTK_MISC(license_chunk1), 0.0, 0.5);
-  GtkWidget* license_chunk2 = gtk_label_new(
-      license.substr(link1_end + strlen(kEndLinkOss),
-                     link2 - link1_end - strlen(kEndLinkOss)).c_str());
-  gtk_misc_set_alignment(GTK_MISC(license_chunk2), 0.0, 0.5);
-  GtkWidget* license_chunk3 = gtk_label_new(
-      license.substr(link2_end + strlen(kEndLinkOss)).c_str());
-  gtk_misc_set_alignment(GTK_MISC(license_chunk3), 0.0, 0.5);
-
-  std::string first_link_text =
-      license.substr(link1 + strlen(kBeginLinkOss),
-                     link1_end - link1 - strlen(kBeginLinkOss));
-  std::string second_link_text =
-      license.substr(link2 + strlen(kBeginLinkOss),
-                     link2_end - link2 - strlen(kBeginLinkOss));
-
-  GtkWidget* first_link = gtk_chrome_link_button_new(first_link_text.c_str());
-  GtkWidget* second_link = gtk_chrome_link_button_new(second_link_text.c_str());
-  if (!chromium_url_appears_first) {
-    GtkWidget* swap = second_link;
-    second_link = first_link;
-    first_link = swap;
-  }
-
-  g_signal_connect(chromium_url_appears_first ? first_link : second_link,
-                   "clicked", G_CALLBACK(OnLinkButtonClick),
-                   const_cast<char*>(GetChromiumUrl()));
-  g_signal_connect(chromium_url_appears_first ? second_link : first_link,
-                   "clicked", G_CALLBACK(OnLinkButtonClick),
-                   const_cast<char*>(chrome::kAboutCreditsURL));
-
-  GtkWidget* license_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_hbox), license_chunk1,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_hbox), first_link,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_hbox), license_chunk2,
-                     FALSE, FALSE, 0);
-
-  // Since there's no good way to dynamically wrap the license block, force
-  // a line break right before the second link (which matches en-US Windows
-  // chromium).
-  GtkWidget* license_hbox2 = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_hbox2), second_link,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_hbox2), license_chunk3,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* license_vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_vbox), license_hbox, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(license_vbox), license_hbox2, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), license_vbox, FALSE, FALSE, 0);
-
-#if defined(GOOGLE_CHROME_BUILD)
-  // Spacing line.
-  gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new(""), FALSE, FALSE, 0);
-
-  std::vector<size_t> url_offsets;
-  string16 text = l10n_util::GetStringFUTF16(IDS_ABOUT_TERMS_OF_SERVICE,
-                                             string16(),
-                                             string16(),
-                                             &url_offsets);
-
-  GtkWidget* tos_chunk1 = gtk_label_new(
-      UTF16ToUTF8(text.substr(0, url_offsets[0])).c_str());
-  gtk_misc_set_alignment(GTK_MISC(tos_chunk1), 0.0, 0.5);
-  GtkWidget* tos_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_TERMS_OF_SERVICE).c_str());
-  GtkWidget* tos_chunk2 = gtk_label_new(
-      UTF16ToUTF8(text.substr(url_offsets[0])).c_str());
-  gtk_misc_set_alignment(GTK_MISC(tos_chunk2), 0.0, 0.5);
-
-  GtkWidget* tos_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tos_hbox), tos_chunk1, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tos_hbox), tos_link, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tos_hbox), tos_chunk2, FALSE, FALSE, 0);
-
-  g_signal_connect(tos_link, "clicked", G_CALLBACK(OnLinkButtonClick),
-    const_cast<char*>(chrome::kAboutTermsURL));
-  gtk_box_pack_start(GTK_BOX(vbox), tos_hbox, TRUE, TRUE, 0);
-#endif
-
-  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
-      gtk_util::kContentAreaBorder, 0,
-      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
-  gtk_container_add(GTK_CONTAINER(alignment), vbox);
-  gtk_box_pack_start(GTK_BOX(content_area), alignment, FALSE, FALSE, 0);
-
-  g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), NULL);
-  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-  gtk_widget_show_all(dialog);
-  gtk_widget_grab_focus(close_button);
-}
diff --git a/chrome/browser/gtk/about_chrome_dialog.h b/chrome/browser/gtk/about_chrome_dialog.h
deleted file mode 100644
index 020e3e5..0000000
--- a/chrome/browser/gtk/about_chrome_dialog.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_ABOUT_CHROME_DIALOG_H_
-#define CHROME_BROWSER_GTK_ABOUT_CHROME_DIALOG_H_
-#pragma once
-
-class Profile;
-typedef struct _GtkWindow GtkWindow;
-
-// Displays the about box, using data copied from |profile|.
-void ShowAboutDialogForProfile(GtkWindow* parent, Profile* profile);
-
-#endif  // CHROME_BROWSER_GTK_ABOUT_CHROME_DIALOG_H_
diff --git a/chrome/browser/gtk/accelerators_gtk.cc b/chrome/browser/gtk/accelerators_gtk.cc
deleted file mode 100644
index 5456b0d..0000000
--- a/chrome/browser/gtk/accelerators_gtk.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/accelerators_gtk.h"
-
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#include <X11/XF86keysym.h>
-
-#include "base/singleton.h"
-#include "chrome/app/chrome_command_ids.h"
-
-namespace {
-
-// A mostly complete list of chrome's accelerators. When one command has
-// multiple shortcuts, the first one in this list is considered "primary",
-// meaning that it will be displayed in context menus.
-const struct AcceleratorMapping {
-  guint keyval;
-  int command_id;
-  GdkModifierType modifier_type;
-} kAcceleratorMap[] = {
-  // Focus.
-  { GDK_k, IDC_FOCUS_SEARCH, GDK_CONTROL_MASK },
-  { GDK_e, IDC_FOCUS_SEARCH, GDK_CONTROL_MASK },
-  { XF86XK_Search, IDC_FOCUS_SEARCH, GdkModifierType(0) },
-  { GDK_l, IDC_FOCUS_LOCATION, GDK_CONTROL_MASK },
-  { GDK_d, IDC_FOCUS_LOCATION, GDK_MOD1_MASK },
-  { GDK_F6, IDC_FOCUS_LOCATION, GdkModifierType(0) },
-  { XF86XK_OpenURL, IDC_FOCUS_LOCATION, GdkModifierType(0) },
-  { XF86XK_Go, IDC_FOCUS_LOCATION, GdkModifierType(0) },
-
-  // Tab/window controls.
-  { GDK_Page_Down, IDC_SELECT_NEXT_TAB, GDK_CONTROL_MASK },
-  { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK },
-  { GDK_Page_Down, IDC_MOVE_TAB_NEXT,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_Page_Up, IDC_MOVE_TAB_PREVIOUS,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK },
-  { GDK_w, IDC_CLOSE_TAB, GDK_CONTROL_MASK },
-  { GDK_t, IDC_RESTORE_TAB,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_t, IDC_NEW_TAB, GDK_CONTROL_MASK },
-  { GDK_n, IDC_NEW_WINDOW, GDK_CONTROL_MASK },
-  { GDK_n, IDC_NEW_INCOGNITO_WINDOW,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-
-  { GDK_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK },
-  { GDK_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK },
-  { GDK_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK },
-  { GDK_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK },
-  { GDK_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK },
-  { GDK_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK },
-  { GDK_7, IDC_SELECT_TAB_6, GDK_CONTROL_MASK },
-  { GDK_8, IDC_SELECT_TAB_7, GDK_CONTROL_MASK },
-  { GDK_9, IDC_SELECT_LAST_TAB, GDK_CONTROL_MASK },
-
-  { GDK_1, IDC_SELECT_TAB_0, GDK_MOD1_MASK },
-  { GDK_2, IDC_SELECT_TAB_1, GDK_MOD1_MASK },
-  { GDK_3, IDC_SELECT_TAB_2, GDK_MOD1_MASK },
-  { GDK_4, IDC_SELECT_TAB_3, GDK_MOD1_MASK },
-  { GDK_5, IDC_SELECT_TAB_4, GDK_MOD1_MASK },
-  { GDK_6, IDC_SELECT_TAB_5, GDK_MOD1_MASK },
-  { GDK_7, IDC_SELECT_TAB_6, GDK_MOD1_MASK },
-  { GDK_8, IDC_SELECT_TAB_7, GDK_MOD1_MASK },
-  { GDK_9, IDC_SELECT_LAST_TAB, GDK_MOD1_MASK },
-
-  { GDK_KP_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK },
-  { GDK_KP_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK },
-  { GDK_KP_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK },
-  { GDK_KP_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK },
-  { GDK_KP_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK },
-  { GDK_KP_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK },
-  { GDK_KP_7, IDC_SELECT_TAB_6, GDK_CONTROL_MASK },
-  { GDK_KP_8, IDC_SELECT_TAB_7, GDK_CONTROL_MASK },
-  { GDK_KP_9, IDC_SELECT_LAST_TAB, GDK_CONTROL_MASK },
-
-  { GDK_KP_1, IDC_SELECT_TAB_0, GDK_MOD1_MASK },
-  { GDK_KP_2, IDC_SELECT_TAB_1, GDK_MOD1_MASK },
-  { GDK_KP_3, IDC_SELECT_TAB_2, GDK_MOD1_MASK },
-  { GDK_KP_4, IDC_SELECT_TAB_3, GDK_MOD1_MASK },
-  { GDK_KP_5, IDC_SELECT_TAB_4, GDK_MOD1_MASK },
-  { GDK_KP_6, IDC_SELECT_TAB_5, GDK_MOD1_MASK },
-  { GDK_KP_7, IDC_SELECT_TAB_6, GDK_MOD1_MASK },
-  { GDK_KP_8, IDC_SELECT_TAB_7, GDK_MOD1_MASK },
-  { GDK_KP_9, IDC_SELECT_LAST_TAB, GDK_MOD1_MASK },
-
-  { GDK_F4, IDC_CLOSE_TAB, GDK_CONTROL_MASK },
-  { GDK_F4, IDC_CLOSE_WINDOW, GDK_MOD1_MASK },
-
-  // Zoom level.
-  { GDK_KP_Add, IDC_ZOOM_PLUS, GDK_CONTROL_MASK },
-  { GDK_plus, IDC_ZOOM_PLUS,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_equal, IDC_ZOOM_PLUS, GDK_CONTROL_MASK },
-  { XF86XK_ZoomIn, IDC_ZOOM_PLUS, GdkModifierType(0) },
-  { GDK_KP_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK },
-  { GDK_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK },
-  { GDK_KP_Subtract, IDC_ZOOM_MINUS, GDK_CONTROL_MASK },
-  { GDK_minus, IDC_ZOOM_MINUS, GDK_CONTROL_MASK },
-  { GDK_underscore, IDC_ZOOM_MINUS,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { XF86XK_ZoomOut, IDC_ZOOM_MINUS, GdkModifierType(0) },
-
-  // Find in page.
-  { GDK_g, IDC_FIND_NEXT, GDK_CONTROL_MASK },
-  { GDK_F3, IDC_FIND_NEXT, GdkModifierType(0) },
-  { GDK_g, IDC_FIND_PREVIOUS,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_F3, IDC_FIND_PREVIOUS, GDK_SHIFT_MASK },
-
-  // Navigation / toolbar buttons.
-  { GDK_Home, IDC_HOME, GDK_MOD1_MASK },
-  { XF86XK_HomePage, IDC_HOME, GdkModifierType(0) },
-  { GDK_Escape, IDC_STOP, GdkModifierType(0) },
-  { XF86XK_Stop, IDC_STOP, GdkModifierType(0) },
-  { GDK_Left, IDC_BACK, GDK_MOD1_MASK },
-  { XF86XK_Back, IDC_BACK, GdkModifierType(0) },
-  { GDK_Right, IDC_FORWARD, GDK_MOD1_MASK },
-  { XF86XK_Forward, IDC_FORWARD, GdkModifierType(0) },
-  { GDK_r, IDC_RELOAD, GDK_CONTROL_MASK },
-  { GDK_r, IDC_RELOAD_IGNORING_CACHE,
-    GdkModifierType(GDK_CONTROL_MASK|GDK_SHIFT_MASK) },
-  { GDK_F5, IDC_RELOAD, GdkModifierType(0) },
-  { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_CONTROL_MASK },
-  { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_SHIFT_MASK },
-  { XF86XK_Reload, IDC_RELOAD, GdkModifierType(0) },
-  { XF86XK_Refresh, IDC_RELOAD, GdkModifierType(0) },
-
-  // Dev tools.
-  { GDK_u, IDC_VIEW_SOURCE, GDK_CONTROL_MASK },
-  { GDK_i, IDC_DEV_TOOLS,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_j, IDC_DEV_TOOLS_CONSOLE,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_c, IDC_DEV_TOOLS_INSPECT,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_Escape, IDC_TASK_MANAGER, GDK_SHIFT_MASK },
-
-  // Editing.
-  { GDK_c, IDC_COPY, GDK_CONTROL_MASK },
-  { GDK_x, IDC_CUT, GDK_CONTROL_MASK },
-  { GDK_v, IDC_PASTE, GDK_CONTROL_MASK },
-
-  // AutoFill.
-  { GDK_a, IDC_AUTOFILL_DEFAULT,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-
-  // Miscellany.
-  { GDK_d, IDC_BOOKMARK_ALL_TABS,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_d, IDC_BOOKMARK_PAGE, GDK_CONTROL_MASK },
-  { GDK_o, IDC_OPEN_FILE, GDK_CONTROL_MASK },
-  { GDK_f, IDC_FIND, GDK_CONTROL_MASK },
-  { GDK_p, IDC_PRINT, GDK_CONTROL_MASK },
-  { GDK_b, IDC_SHOW_BOOKMARK_BAR,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_F11, IDC_FULLSCREEN, GdkModifierType(0) },
-  { GDK_Delete, IDC_CLEAR_BROWSING_DATA,
-    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_h, IDC_SHOW_HISTORY, GDK_CONTROL_MASK },
-  { GDK_j, IDC_SHOW_DOWNLOADS, GDK_CONTROL_MASK },
-  { GDK_F1, IDC_HELP_PAGE, GdkModifierType(0) },
-  { XF86XK_AddFavorite, IDC_BOOKMARK_PAGE, GdkModifierType(0) },
-  { XF86XK_Favorites, IDC_SHOW_BOOKMARK_BAR, GdkModifierType(0) },
-  { XF86XK_History, IDC_SHOW_HISTORY, GdkModifierType(0) },
-  { GDK_q, IDC_EXIT, GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_s, IDC_SAVE_PAGE, GDK_CONTROL_MASK },
-  { GDK_e, IDC_SHOW_APP_MENU, GDK_MOD1_MASK },
-  { GDK_f, IDC_SHOW_APP_MENU, GDK_MOD1_MASK },
-};
-
-}  // namespace
-
-AcceleratorsGtk::AcceleratorsGtk() {
-  for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) {
-    int command_id = kAcceleratorMap[i].command_id;
-    menus::AcceleratorGtk accelerator(kAcceleratorMap[i].keyval,
-                                      kAcceleratorMap[i].modifier_type);
-    all_accelerators_.push_back(
-        std::pair<int, menus::AcceleratorGtk>(command_id, accelerator));
-
-    if (primary_accelerators_.find(command_id) ==
-        primary_accelerators_.end()) {
-      primary_accelerators_[command_id] = accelerator;
-    }
-  }
-}
-
-AcceleratorsGtk::~AcceleratorsGtk() {}
-
-// static
-AcceleratorsGtk* AcceleratorsGtk::GetInstance() {
-  return Singleton<AcceleratorsGtk>::get();
-}
-
-const menus::AcceleratorGtk* AcceleratorsGtk::GetPrimaryAcceleratorForCommand(
-    int command_id) {
-  base::hash_map<int, menus::AcceleratorGtk>::const_iterator iter =
-      primary_accelerators_.find(command_id);
-
-  if (iter == primary_accelerators_.end())
-    return NULL;
-
-  return &iter->second;
-}
diff --git a/chrome/browser/gtk/accelerators_gtk.h b/chrome/browser/gtk/accelerators_gtk.h
deleted file mode 100644
index 2e45700..0000000
--- a/chrome/browser/gtk/accelerators_gtk.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_ACCELERATORS_GTK_H_
-#define CHROME_BROWSER_GTK_ACCELERATORS_GTK_H_
-#pragma once
-
-#include "app/menus/accelerator_gtk.h"
-#include "base/hash_tables.h"
-
-template <typename T> struct DefaultSingletonTraits;
-
-class AcceleratorsGtk {
- public:
-  typedef std::vector<std::pair<int, menus::AcceleratorGtk> >
-      AcceleratorGtkList;
-  typedef AcceleratorGtkList::const_iterator const_iterator;
-
-  // Returns the singleton instance.
-  static AcceleratorsGtk* GetInstance();
-
-  const_iterator const begin() {
-    return all_accelerators_.begin();
-  }
-
-  const_iterator const end() {
-    return all_accelerators_.end();
-  }
-
-  // Returns NULL if there is no accelerator for the command.
-  const menus::AcceleratorGtk* GetPrimaryAcceleratorForCommand(int command_id);
-
- private:
-  friend struct DefaultSingletonTraits<AcceleratorsGtk>;
-
-  AcceleratorsGtk();
-  ~AcceleratorsGtk();
-
-  base::hash_map<int, menus::AcceleratorGtk> primary_accelerators_;
-
-  AcceleratorGtkList all_accelerators_;
-};
-
-#endif  // CHROME_BROWSER_GTK_ACCELERATORS_GTK_H_
diff --git a/chrome/browser/gtk/accessibility_event_router_gtk.cc b/chrome/browser/gtk/accessibility_event_router_gtk.cc
deleted file mode 100644
index 1248247..0000000
--- a/chrome/browser/gtk/accessibility_event_router_gtk.cc
+++ /dev/null
@@ -1,658 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/accessibility_event_router_gtk.h"
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
-#include "chrome/browser/extensions/extension_accessibility_api.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_type.h"
-
-#if defined(TOOLKIT_VIEWS)
-#include "views/controls/textfield/gtk_views_textview.h"
-#include "views/controls/textfield/gtk_views_entry.h"
-#include "views/controls/textfield/native_textfield_gtk.h"
-#endif
-
-namespace {
-
-//
-// Callbacks triggered by signals on gtk widgets.
-//
-
-gboolean OnWidgetFocused(GSignalInvocationHint *ihint,
-                         guint n_param_values,
-                         const GValue* param_values,
-                         gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      DispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
-  return TRUE;
-}
-
-gboolean OnButtonClicked(GSignalInvocationHint *ihint,
-                         guint n_param_values,
-                         const GValue* param_values,
-                         gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  // Skip toggle buttons because we're also listening on "toggle" events.
-  if (GTK_IS_TOGGLE_BUTTON(widget))
-    return true;
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      DispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
-  return TRUE;
-}
-
-gboolean OnButtonToggled(GSignalInvocationHint *ihint,
-                         guint n_param_values,
-                         const GValue* param_values,
-                         gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  // Skip propagating an "uncheck" event for a radio button because it's
-  // redundant; there will always be a corresponding "check" event for
-  // a different radio button the group.
-  if (GTK_IS_RADIO_BUTTON(widget) && !checked)
-    return true;
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      DispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
-  return TRUE;
-}
-
-gboolean OnPageSwitched(GSignalInvocationHint *ihint,
-                        guint n_param_values,
-                        const GValue* param_values,
-                        gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  // The page hasn't switched yet, so defer calling
-  // DispatchAccessibilityNotification.
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      PostDispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
-  return TRUE;
-}
-
-gboolean OnComboBoxChanged(GSignalInvocationHint *ihint,
-                           guint n_param_values,
-                           const GValue* param_values,
-                           gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  if (!GTK_IS_COMBO_BOX(widget))
-    return true;
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      DispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
-  return TRUE;
-}
-
-gboolean OnTreeViewCursorChanged(GSignalInvocationHint *ihint,
-                                 guint n_param_values,
-                                 const GValue* param_values,
-                                 gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  if (!GTK_IS_TREE_VIEW(widget)) {
-    return true;
-  }
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      DispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
-  return TRUE;
-}
-
-gboolean OnEntryChanged(GSignalInvocationHint *ihint,
-                        guint n_param_values,
-                        const GValue* param_values,
-                        gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  if (!GTK_IS_ENTRY(widget)) {
-    return TRUE;
-  }
-  // The text hasn't changed yet, so defer calling
-  // DispatchAccessibilityNotification.
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      PostDispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
-  return TRUE;
-}
-
-gboolean OnTextBufferChanged(GSignalInvocationHint *ihint,
-                             guint n_param_values,
-                             const GValue* param_values,
-                             gpointer user_data) {
-  // The text hasn't changed yet, so defer calling
-  // DispatchAccessibilityNotification.
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      PostDispatchAccessibilityNotification(
-          NULL, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
-  return TRUE;
-}
-
-gboolean OnTextViewChanged(GSignalInvocationHint *ihint,
-                           guint n_param_values,
-                           const GValue* param_values,
-                           gpointer user_data) {
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-  if (!GTK_IS_TEXT_VIEW(widget)) {
-    return TRUE;
-  }
-  // The text hasn't changed yet, so defer calling
-  // DispatchAccessibilityNotification.
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      PostDispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
-  return TRUE;
-}
-
-gboolean OnMenuMoveCurrent(GSignalInvocationHint *ihint,
-                           guint n_param_values,
-                           const GValue* param_values,
-                           gpointer user_data) {
-  // Get the widget (the GtkMenu).
-  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-
-  // Moving may move us into or out of a submenu, so after the menu
-  // item moves, |widget| may not be valid anymore. To be safe, then,
-  // find the topmost ancestor of this menu and post the notification
-  // dispatch on that menu. Then the dispatcher will recurse into submenus
-  // as necessary to figure out which item is focused.
-  while (GTK_MENU_SHELL(widget)->parent_menu_shell)
-    widget = GTK_MENU_SHELL(widget)->parent_menu_shell;
-
-  // The menu item hasn't moved yet, so we want to defer calling
-  // DispatchAccessibilityNotification until after it does.
-  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
-      PostDispatchAccessibilityNotification(
-          widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
-  return TRUE;
-}
-
-}  // anonymous namespace
-
-AccessibilityEventRouterGtk::AccessibilityEventRouterGtk()
-    : listening_(false),
-      most_recent_profile_(NULL),
-      most_recent_widget_(NULL),
-      method_factory_(this) {
-  // We don't want our event listeners to be installed if accessibility is
-  // disabled. Install listeners so we can install and uninstall them as
-  // needed, then install them now if it's currently enabled.
-  ExtensionAccessibilityEventRouter *extension_event_router =
-      ExtensionAccessibilityEventRouter::GetInstance();
-  extension_event_router->AddOnEnabledListener(
-      NewCallback(this,
-                  &AccessibilityEventRouterGtk::InstallEventListeners));
-  extension_event_router->AddOnDisabledListener(
-      NewCallback(this,
-                  &AccessibilityEventRouterGtk::RemoveEventListeners));
-  if (extension_event_router->IsAccessibilityEnabled()) {
-    InstallEventListeners();
-  }
-}
-
-AccessibilityEventRouterGtk::~AccessibilityEventRouterGtk() {
-  RemoveEventListeners();
-}
-
-// static
-AccessibilityEventRouterGtk* AccessibilityEventRouterGtk::GetInstance() {
-  return Singleton<AccessibilityEventRouterGtk>::get();
-}
-
-void AccessibilityEventRouterGtk::InstallEventListener(
-    const char* signal_name,
-    GType widget_type,
-    GSignalEmissionHook hook_func) {
-  guint signal_id = g_signal_lookup(signal_name, widget_type);
-  gulong hook_id = g_signal_add_emission_hook(
-      signal_id, 0, hook_func, reinterpret_cast<gpointer>(this), NULL);
-  installed_hooks_.push_back(InstalledHook(signal_id, hook_id));
-}
-
-bool AccessibilityEventRouterGtk::IsPassword(GtkWidget* widget) {
-  bool is_password = false;
-#if defined (TOOLKIT_VIEWS)
-  is_password = (GTK_IS_VIEWS_ENTRY(widget) &&
-                 GTK_VIEWS_ENTRY(widget)->host != NULL &&
-                 GTK_VIEWS_ENTRY(widget)->host->IsPassword()) ||
-                (GTK_IS_VIEWS_TEXTVIEW(widget) &&
-                 GTK_VIEWS_TEXTVIEW(widget)->host != NULL &&
-                 GTK_VIEWS_TEXTVIEW(widget)->host->IsPassword());
-#endif
-  return is_password;
-}
-
-
-void AccessibilityEventRouterGtk::InstallEventListeners() {
-  // Create and destroy each type of widget we need signals for,
-  // to ensure their modules are loaded, otherwise g_signal_lookup
-  // might fail.
-  g_object_unref(g_object_ref_sink(gtk_combo_box_new()));
-  g_object_unref(g_object_ref_sink(gtk_entry_new()));
-  g_object_unref(g_object_ref_sink(gtk_notebook_new()));
-  g_object_unref(g_object_ref_sink(gtk_toggle_button_new()));
-  g_object_unref(g_object_ref_sink(gtk_tree_view_new()));
-  g_object_unref(g_object_ref_sink(gtk_text_view_new()));
-  g_object_unref(g_object_ref_sink(gtk_text_buffer_new(NULL)));
-
-  // Add signal emission hooks for the events we're interested in.
-  InstallEventListener("clicked", GTK_TYPE_BUTTON, OnButtonClicked);
-  InstallEventListener("changed", GTK_TYPE_COMBO_BOX, OnComboBoxChanged);
-  InstallEventListener("cursor-changed", GTK_TYPE_TREE_VIEW,
-                       OnTreeViewCursorChanged);
-  InstallEventListener("changed", GTK_TYPE_ENTRY, OnEntryChanged);
-  InstallEventListener("insert-text", GTK_TYPE_ENTRY, OnEntryChanged);
-  InstallEventListener("delete-text", GTK_TYPE_ENTRY, OnEntryChanged);
-  InstallEventListener("move-cursor", GTK_TYPE_ENTRY, OnEntryChanged);
-  InstallEventListener("focus-in-event", GTK_TYPE_WIDGET, OnWidgetFocused);
-  InstallEventListener("switch-page", GTK_TYPE_NOTEBOOK, OnPageSwitched);
-  InstallEventListener("toggled", GTK_TYPE_TOGGLE_BUTTON, OnButtonToggled);
-  InstallEventListener("move-current", GTK_TYPE_MENU, OnMenuMoveCurrent);
-  InstallEventListener("changed", GTK_TYPE_TEXT_BUFFER, OnTextBufferChanged);
-  InstallEventListener("move-cursor", GTK_TYPE_TEXT_VIEW, OnTextViewChanged);
-
-  listening_ = true;
-}
-
-void AccessibilityEventRouterGtk::RemoveEventListeners() {
-  for (size_t i = 0; i < installed_hooks_.size(); i++) {
-    g_signal_remove_emission_hook(
-        installed_hooks_[i].signal_id,
-        installed_hooks_[i].hook_id);
-  }
-  installed_hooks_.clear();
-
-  listening_ = false;
-}
-
-void AccessibilityEventRouterGtk::AddRootWidget(
-    GtkWidget* root_widget, Profile* profile) {
-  root_widget_info_map_[root_widget].refcount++;
-  root_widget_info_map_[root_widget].profile = profile;
-}
-
-void AccessibilityEventRouterGtk::RemoveRootWidget(GtkWidget* root_widget) {
-  DCHECK(root_widget_info_map_.find(root_widget) !=
-         root_widget_info_map_.end());
-  root_widget_info_map_[root_widget].refcount--;
-  if (root_widget_info_map_[root_widget].refcount == 0) {
-    root_widget_info_map_.erase(root_widget);
-  }
-}
-
-void AccessibilityEventRouterGtk::AddWidgetNameOverride(
-    GtkWidget* widget, std::string name) {
-  widget_info_map_[widget].name = name;
-  widget_info_map_[widget].refcount++;
-}
-
-void AccessibilityEventRouterGtk::RemoveWidgetNameOverride(GtkWidget* widget) {
-  DCHECK(widget_info_map_.find(widget) != widget_info_map_.end());
-  widget_info_map_[widget].refcount--;
-  if (widget_info_map_[widget].refcount == 0) {
-    widget_info_map_.erase(widget);
-  }
-}
-
-void AccessibilityEventRouterGtk::FindWidget(
-    GtkWidget* widget, Profile** profile, bool* is_accessible) {
-  *is_accessible = false;
-
-  for (base::hash_map<GtkWidget*, RootWidgetInfo>::const_iterator iter =
-           root_widget_info_map_.begin();
-       iter != root_widget_info_map_.end();
-       ++iter) {
-    if (widget == iter->first || gtk_widget_is_ancestor(widget, iter->first)) {
-      *is_accessible = true;
-      if (profile)
-        *profile = iter->second.profile;
-      break;
-    }
-  }
-}
-
-std::string AccessibilityEventRouterGtk::GetWidgetName(GtkWidget* widget) {
-  base::hash_map<GtkWidget*, WidgetInfo>::const_iterator iter =
-      widget_info_map_.find(widget);
-  if (iter != widget_info_map_.end()) {
-    return iter->second.name;
-  } else {
-    return "";
-  }
-}
-
-void AccessibilityEventRouterGtk::StartListening() {
-  listening_ = true;
-}
-
-void AccessibilityEventRouterGtk::StopListening() {
-  listening_ = false;
-}
-
-void AccessibilityEventRouterGtk::DispatchAccessibilityNotification(
-    GtkWidget* widget, NotificationType type) {
-  // If there's no message loop, we must be about to shutdown or we're
-  // running inside a test; either way, there's no reason to do any
-  // further processing.
-  if (!MessageLoop::current())
-    return;
-
-  if (!listening_)
-    return;
-
-  Profile* profile = NULL;
-  bool is_accessible;
-
-  // Special case: when we get ACCESSIBILITY_TEXT_CHANGED, we don't get
-  // a pointer to the widget, so we try to retrieve it from the most recent
-  // widget.
-  if (widget == NULL &&
-      type == NotificationType::ACCESSIBILITY_TEXT_CHANGED &&
-      most_recent_widget_ &&
-      GTK_IS_TEXT_VIEW(most_recent_widget_)) {
-    widget = most_recent_widget_;
-  }
-
-  if (!widget)
-    return;
-
-  most_recent_widget_ = widget;
-  FindWidget(widget, &profile, &is_accessible);
-  if (profile)
-    most_recent_profile_ = profile;
-
-  // Special case: a GtkMenu isn't associated with any particular
-  // toplevel window, so menu events get routed to the profile of
-  // the most recent event that was associated with a window.
-  if (GTK_IS_MENU_SHELL(widget) && most_recent_profile_) {
-    SendMenuItemNotification(widget, type, most_recent_profile_);
-    return;
-  }
-
-  // In all other cases, return if this widget wasn't marked as accessible.
-  if (!is_accessible)
-    return;
-
-  // The order of these checks matters, because, for example, a radio button
-  // is a subclass of button, and a combo box is a composite control where
-  // the focus event goes to the button that's a child of the combo box.
-  GtkWidget* parent = gtk_widget_get_parent(widget);
-  if (parent && GTK_IS_BUTTON(widget) && GTK_IS_TREE_VIEW(parent)) {
-    // This is a list box column header.  Currently not supported.
-    return;
-  } else if (GTK_IS_COMBO_BOX(widget)) {
-    SendComboBoxNotification(widget, type, profile);
-  } else if (parent && GTK_IS_COMBO_BOX(parent)) {
-    SendComboBoxNotification(parent, type, profile);
-  } else if (GTK_IS_RADIO_BUTTON(widget)) {
-    SendRadioButtonNotification(widget, type, profile);
-  } else if (GTK_IS_TOGGLE_BUTTON(widget)) {
-    SendCheckboxNotification(widget, type, profile);
-  } else if (GTK_IS_BUTTON(widget)) {
-    SendButtonNotification(widget, type, profile);
-  } else if (GTK_IS_ENTRY(widget)) {
-    SendEntryNotification(widget, type, profile);
-  } else if (GTK_IS_TEXT_VIEW(widget)) {
-    SendTextViewNotification(widget, type, profile);
-  } else if (GTK_IS_NOTEBOOK(widget)) {
-    SendTabNotification(widget, type, profile);
-  } else if (GTK_IS_TREE_VIEW(widget)) {
-    SendListBoxNotification(widget, type, profile);
-  } else {
-    // If we have no idea what this control is, return and skip the
-    // temporary pause in event listening.
-    return;
-  }
-
-  // After this method returns, additional signal handlers will run,
-  // which will sometimes generate additional signals.  To avoid
-  // generating redundant accessibility notifications for the same
-  // initial event, stop listening to all signals generated from now
-  // until this posted task runs.
-  StopListening();
-  MessageLoop::current()->PostTask(
-      FROM_HERE, method_factory_.NewRunnableMethod(
-          &AccessibilityEventRouterGtk::StartListening));
-}
-
-void AccessibilityEventRouterGtk::PostDispatchAccessibilityNotification(
-    GtkWidget* widget, NotificationType type) {
-  if (!MessageLoop::current())
-    return;
-
-  MessageLoop::current()->PostTask(
-      FROM_HERE, method_factory_.NewRunnableMethod(
-          &AccessibilityEventRouterGtk::DispatchAccessibilityNotification,
-          widget,
-          type));
-}
-
-void AccessibilityEventRouterGtk::SendRadioButtonNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  // Get the radio button name
-  std::string button_name = GetWidgetName(widget);
-  if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
-    button_name = gtk_button_get_label(GTK_BUTTON(widget));
-
-  // Get its state
-  bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-
-  // Get the index of this radio button and the total number of
-  // radio buttons in the group.
-  int item_count = 0;
-  int item_index = -1;
-  for (GSList* group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(widget));
-       group;
-       group = group->next) {
-    if (group->data == widget) {
-      item_index = item_count;
-    }
-    item_count++;
-  }
-  item_index = item_count - 1 - item_index;
-
-  AccessibilityRadioButtonInfo info(
-      profile, button_name, checked, item_index, item_count);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendCheckboxNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  std::string button_name = GetWidgetName(widget);
-  if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
-    button_name = gtk_button_get_label(GTK_BUTTON(widget));
-  bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  AccessibilityCheckboxInfo info(profile, button_name, checked);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendButtonNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  std::string button_name = GetWidgetName(widget);
-  if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
-    button_name = gtk_button_get_label(GTK_BUTTON(widget));
-  AccessibilityButtonInfo info(profile, button_name);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendEntryNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  std::string name = GetWidgetName(widget);
-  std::string value = gtk_entry_get_text(GTK_ENTRY(widget));
-  gint start_pos;
-  gint end_pos;
-  gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start_pos, &end_pos);
-  AccessibilityTextBoxInfo info(profile, name, IsPassword(widget));
-  info.SetValue(value, start_pos, end_pos);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendTextViewNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  std::string name = GetWidgetName(widget);
-  GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
-  GtkTextIter start, end;
-  gtk_text_buffer_get_bounds(buffer, &start, &end);
-  gchar* text = gtk_text_buffer_get_text(buffer, &start, &end, false);
-  std::string value = text;
-  g_free(text);
-  GtkTextIter sel_start, sel_end;
-  gtk_text_buffer_get_selection_bounds(buffer, &sel_start, &sel_end);
-  int start_pos = gtk_text_iter_get_offset(&sel_start);
-  int end_pos = gtk_text_iter_get_offset(&sel_end);
-  AccessibilityTextBoxInfo info(profile, name, IsPassword(widget));
-  info.SetValue(value, start_pos, end_pos);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendTabNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
-  int page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget));
-  GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget), index);
-  GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(widget), page);
-  std::string name = GetWidgetName(widget);
-  if (name.empty() && gtk_label_get_text(GTK_LABEL(label))) {
-    name = gtk_label_get_text(GTK_LABEL(label));
-  }
-  AccessibilityTabInfo info(profile, name, index, page_count);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendComboBoxNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  // Get the index of the selected item.  Will return -1 if no item is
-  // active, which matches the semantics of the extension API.
-  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
-
-  // Get the number of items.
-  GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
-  int count = gtk_tree_model_iter_n_children(model, NULL);
-
-  // Get the value of the current item, if possible.  Note that the
-  // model behind the combo box could be arbitrarily complex in theory,
-  // but this code just handles flat lists where the first string column
-  // contains the display value.
-  std::string value;
-  int string_column_index = -1;
-  for (int i = 0; i < gtk_tree_model_get_n_columns(model); i++) {
-    if (gtk_tree_model_get_column_type(model, i) == G_TYPE_STRING) {
-      string_column_index = i;
-      break;
-    }
-  }
-  if (string_column_index) {
-    GtkTreeIter iter;
-    if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) {
-      GValue gvalue = { 0 };
-      gtk_tree_model_get_value(model, &iter, string_column_index, &gvalue);
-      const char* string_value = g_value_get_string(&gvalue);
-      if (string_value) {
-        value = string_value;
-      }
-      g_value_unset(&gvalue);
-    }
-  } else {
-    // Otherwise this must be a gtk_combo_box_text, in which case this
-    // function will return the value of the current item, instead.
-    value = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
-  }
-
-  // Get the name of this combo box.
-  std::string name = GetWidgetName(widget);
-
-  // Send the notification.
-  AccessibilityComboBoxInfo info(profile, name, value, index, count);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendListBoxNotification(
-    GtkWidget* widget, NotificationType type, Profile* profile) {
-  // Get the number of items.
-  GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
-  int count = gtk_tree_model_iter_n_children(model, NULL);
-
-  // Get the current selected index and its value.
-  int index = -1;
-  std::string value;
-  GtkTreePath* path;
-  gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &path, NULL);
-  if (path != NULL) {
-    gint* indices = gtk_tree_path_get_indices(path);
-    if (indices)
-      index = indices[0];
-
-    GtkTreeIter iter;
-    if (gtk_tree_model_get_iter(model, &iter, path)) {
-      for (int i = 0; i < gtk_tree_model_get_n_columns(model); i++) {
-        if (gtk_tree_model_get_column_type(model, i) == G_TYPE_STRING) {
-          GValue gvalue = { 0 };
-          gtk_tree_model_get_value(model, &iter, i, &gvalue);
-          const char* string_value = g_value_get_string(&gvalue);
-          if (string_value) {
-            if (!value.empty())
-              value += " ";
-            value += string_value;
-          }
-          g_value_unset(&gvalue);
-        }
-      }
-    }
-
-    gtk_tree_path_free(path);
-  }
-
-  // Get the name of this control.
-  std::string name = GetWidgetName(widget);
-
-  // Send the notification.
-  AccessibilityListBoxInfo info(profile, name, value, index, count);
-  SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendMenuItemNotification(
-    GtkWidget* menu, NotificationType type, Profile* profile) {
-  // Find the focused menu item, recursing into submenus as needed.
-  GtkWidget* menu_item = GTK_MENU_SHELL(menu)->active_menu_item;
-  if (!menu_item)
-    return;
-  GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item));
-  while (submenu && GTK_MENU_SHELL(submenu)->active_menu_item) {
-    menu = submenu;
-    menu_item = GTK_MENU_SHELL(menu)->active_menu_item;
-    if (!menu_item)
-      return;
-    submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item));
-  }
-
-  // Figure out the item index and total number of items.
-  GList* items = gtk_container_get_children(GTK_CONTAINER(menu));
-  guint count = g_list_length(items);
-  int index = g_list_index(items, static_cast<gconstpointer>(menu_item));
-
-  // Get the menu item's label.
-  std::string name;
-#if GTK_CHECK_VERSION(2, 16, 0)
-  name = gtk_menu_item_get_label(GTK_MENU_ITEM(menu_item));
-#else
-  GList* children = gtk_container_get_children(GTK_CONTAINER(menu_item));
-  for (GList* l = g_list_first(children); l != NULL; l = g_list_next(l)) {
-    GtkWidget* child = static_cast<GtkWidget*>(l->data);
-    if (GTK_IS_LABEL(child)) {
-      name = gtk_label_get_label(GTK_LABEL(child));
-      break;
-    }
-  }
-#endif
-
-  // Send the event.
-  AccessibilityMenuItemInfo info(profile, name, submenu != NULL, index, count);
-  SendAccessibilityNotification(type, &info);
-}
diff --git a/chrome/browser/gtk/accessibility_event_router_gtk.h b/chrome/browser/gtk/accessibility_event_router_gtk.h
deleted file mode 100644
index 2cc2cf9..0000000
--- a/chrome/browser/gtk/accessibility_event_router_gtk.h
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_ACCESSIBILITY_EVENT_ROUTER_GTK_H_
-#define CHROME_BROWSER_GTK_ACCESSIBILITY_EVENT_ROUTER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/hash_tables.h"
-#include "base/singleton.h"
-#include "base/task.h"
-#include "chrome/browser/accessibility_events.h"
-
-class Profile;
-#if defined (TOOLKIT_VIEWS)
-namespace views {
-class NativeTextfieldGtk;
-}
-#endif
-
-// Allows us to use (GtkWidget*) in a hash_map with gcc.
-namespace __gnu_cxx {
-template<>
-struct hash<GtkWidget*> {
-  size_t operator()(GtkWidget* widget) const {
-    return reinterpret_cast<size_t>(widget);
-  }
-};
-}  // namespace __gnu_cxx
-
-// Struct to keep track of event listener hook ids to remove them later.
-struct InstalledHook {
-  InstalledHook(guint _signal_id, gulong _hook_id)
-      : signal_id(_signal_id), hook_id(_hook_id) { }
-  guint signal_id;
-  gulong hook_id;
-};
-
-// NOTE: This class is part of the Accessibility Extension API, which lets
-// extensions receive accessibility events. It's distinct from code that
-// implements platform accessibility APIs like MSAA or ATK.
-//
-// Singleton class that adds a signal emission hook to many gtk events, and
-// then sends an accessibility notification whenever a relevant event is
-// sent to an accessible control.
-//
-// Gtk widgets are not accessible by default. When you register a root widget,
-// that widget and all of its descendants will start sending accessibility
-// event notifications. You can then override the default behavior for
-// specific descendants using other methods.
-//
-// You can use Profile::PauseAccessibilityEvents to prevent a flurry
-// of accessibility events when a window is being created or initialized.
-class AccessibilityEventRouterGtk {
- public:
-  // Internal information about a particular widget to override the
-  // information we get directly from gtk.
-  struct WidgetInfo {
-    WidgetInfo() : refcount(0) { }
-
-    // The number of times that AddWidgetNameOverride has been called on this
-    // widget. When RemoveWidget has been called an equal number of
-    // times and the refcount reaches zero, this entry will be deleted.
-    int refcount;
-
-    // If nonempty, will use this name instead of the widget's label.
-    std::string name;
-  };
-
-  // Internal information about a root widget
-  struct RootWidgetInfo {
-    RootWidgetInfo() : refcount(0), profile(NULL) { }
-
-    // The number of times that AddRootWidget has been called on this
-    // widget. When RemoveRootWidget has been called an equal number of
-    // times and the refcount reaches zero, this entry will be deleted.
-    int refcount;
-
-    // The profile associated with this root widget; accessibility
-    // notifications for any descendant of this root widget will get routed
-    // to this profile.
-    Profile* profile;
-  };
-
-  // Get the single instance of this class.
-  static AccessibilityEventRouterGtk* GetInstance();
-
-  // Start sending accessibility events for this widget and all of its
-  // descendants.  Notifications will go to the specified profile.
-  // Uses reference counting, so it's safe to call this twice on the
-  // same widget, as long as each call is paired with a call to
-  // RemoveRootWidget.
-  void AddRootWidget(GtkWidget* root_widget, Profile* profile);
-
-  // Stop sending accessibility events for this widget and all of its
-  // descendants.
-  void RemoveRootWidget(GtkWidget* root_widget);
-
-  // Use the following string as the name of this widget, instead of the
-  // gtk label associated with the widget. Must be paired with a call to
-  // RemoveWidgetNameOverride.
-  void AddWidgetNameOverride(GtkWidget* widget, std::string name);
-
-  // Forget widget name override. Must be paired with a call to
-  // AddWidgetNameOverride (uses reference counting).
-  void RemoveWidgetNameOverride(GtkWidget* widget);
-
-  //
-  // The following methods are only for use by gtk signal handlers.
-  //
-
-  // Called by the signal handler.  Checks the type of the widget and
-  // calls one of the more specific Send*Notification methods, below.
-  void DispatchAccessibilityNotification(
-      GtkWidget* widget, NotificationType type);
-
-  // Post a task to call DispatchAccessibilityNotification the next time
-  // through the event loop.
-  void PostDispatchAccessibilityNotification(
-      GtkWidget* widget, NotificationType type);
-
- private:
-  AccessibilityEventRouterGtk();
-  virtual ~AccessibilityEventRouterGtk();
-
-  // Given a widget, determine if it's the descendant of a root widget
-  // that's mapped to a profile and if so, if it's marked as accessible.
-  void FindWidget(GtkWidget* widget, Profile** profile, bool* is_accessible);
-
-  // Return the name of a widget.
-  std::string GetWidgetName(GtkWidget* widget);
-
-  // Each of these methods constructs an AccessibilityControlInfo object
-  // and sends a notification of a specific accessibility event.
-  void SendButtonNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendCheckboxNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendComboBoxNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendListBoxNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendMenuItemNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendRadioButtonNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendTabNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendEntryNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-  void SendTextViewNotification(
-      GtkWidget* widget, NotificationType type, Profile* profile);
-
-  bool IsPassword(GtkWidget* widget);
-  void InstallEventListeners();
-  void RemoveEventListeners();
-
-  // Start and stop listening to signals.
-  void StartListening();
-  void StopListening();
-
-  // Add a signal emission hook for one particular signal name and
-  // widget type, and save the hook_id in installed_hooks so we can
-  // remove it later.
-  void InstallEventListener(
-      const char *signal_name,
-      GType widget_type,
-      GSignalEmissionHook hook_func);
-
-  friend struct DefaultSingletonTraits<AccessibilityEventRouterGtk>;
-
-  // The set of all root widgets; only descendants of these will generate
-  // accessibility notifications.
-  base::hash_map<GtkWidget*, RootWidgetInfo> root_widget_info_map_;
-
-  // Extra information about specific widgets.
-  base::hash_map<GtkWidget*, WidgetInfo> widget_info_map_;
-
-  // Installed event listener hook ids so we can remove them later.
-  std::vector<InstalledHook> installed_hooks_;
-
-  // True if we are currently listening to signals.
-  bool listening_;
-
-  // The profile associated with the most recent window event  - used to
-  // figure out where to route a few events that can't be directly traced
-  // to a window with a profile (like menu events).
-  Profile* most_recent_profile_;
-
-  // The most recent focused widget.
-  GtkWidget* most_recent_widget_;
-
-  // Used to schedule invocations of StartListening() and to defer handling
-  // of some events until the next time through the event loop.
-  ScopedRunnableMethodFactory<AccessibilityEventRouterGtk> method_factory_;
-
-  friend class AccessibilityEventRouterGtkTest;
-  FRIEND_TEST_ALL_PREFIXES(AccessibilityEventRouterGtkTest, AddRootWidgetTwice);
-};
-
-#endif  // CHROME_BROWSER_GTK_ACCESSIBILITY_EVENT_ROUTER_GTK_H_
diff --git a/chrome/browser/gtk/accessibility_event_router_gtk_unittest.cc b/chrome/browser/gtk/accessibility_event_router_gtk_unittest.cc
deleted file mode 100644
index 7264da7..0000000
--- a/chrome/browser/gtk/accessibility_event_router_gtk_unittest.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/accessibility_event_router_gtk.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class AccessibilityEventRouterGtkTest : public testing::Test {
- protected:
-  AccessibilityEventRouterGtkTest() { }
-};
-
-TEST_F(AccessibilityEventRouterGtkTest, AddRootWidgetTwice) {
-  AccessibilityEventRouterGtk* event_router =
-      AccessibilityEventRouterGtk::GetInstance();
-  TestingProfile profile;
-
-  GtkWidget* widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
-  bool found = false;
-  event_router->FindWidget(widget, NULL, &found);
-  EXPECT_FALSE(found);
-
-  event_router->AddRootWidget(widget, &profile);
-  event_router->FindWidget(widget, NULL, &found);
-  EXPECT_TRUE(found);
-
-  event_router->AddRootWidget(widget, &profile);
-  event_router->FindWidget(widget, NULL, &found);
-  EXPECT_TRUE(found);
-
-  event_router->RemoveRootWidget(widget);
-  event_router->FindWidget(widget, NULL, &found);
-  EXPECT_TRUE(found);
-
-  event_router->RemoveRootWidget(widget);
-  event_router->FindWidget(widget, NULL, &found);
-  EXPECT_FALSE(found);
-
-  gtk_widget_destroy(widget);
-};
diff --git a/chrome/browser/gtk/accessible_widget_helper_gtk.cc b/chrome/browser/gtk/accessible_widget_helper_gtk.cc
deleted file mode 100644
index 029aca4..0000000
--- a/chrome/browser/gtk/accessible_widget_helper_gtk.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-
-#include "app/l10n_util.h"
-#include "chrome/browser/accessibility_events.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_service.h"
-
-AccessibleWidgetHelper::AccessibleWidgetHelper(
-    GtkWidget* root_widget, Profile* profile)
-    : accessibility_event_router_(AccessibilityEventRouterGtk::GetInstance()),
-      profile_(profile),
-      root_widget_(root_widget) {
-  CHECK(profile_);
-  accessibility_event_router_->AddRootWidget(root_widget_, profile_);
-}
-
-AccessibleWidgetHelper::~AccessibleWidgetHelper() {
-  if (!window_title_.empty()) {
-    AccessibilityWindowInfo info(profile_, window_title_);
-    NotificationService::current()->Notify(
-        NotificationType::ACCESSIBILITY_WINDOW_CLOSED,
-        Source<Profile>(profile_),
-        Details<AccessibilityWindowInfo>(&info));
-  }
-
-  if (root_widget_)
-    accessibility_event_router_->RemoveRootWidget(root_widget_);
-  for (std::set<GtkWidget*>::iterator it = managed_widgets_.begin();
-       it != managed_widgets_.end();
-       ++it) {
-    accessibility_event_router_->RemoveWidgetNameOverride(*it);
-  }
-}
-
-void AccessibleWidgetHelper::SendOpenWindowNotification(
-    const std::string& window_title) {
-  window_title_ = window_title;
-  AccessibilityWindowInfo info(profile_, window_title);
-  NotificationService::current()->Notify(
-      NotificationType::ACCESSIBILITY_WINDOW_OPENED,
-      Source<Profile>(profile_),
-      Details<AccessibilityWindowInfo>(&info));
-}
-
-void AccessibleWidgetHelper::SetWidgetName(
-    GtkWidget* widget, std::string name) {
-  if (managed_widgets_.find(widget) != managed_widgets_.end()) {
-    // AccessibilityEventRouterGtk reference-counts its widgets, but we
-    // don't. In order to avoid a memory leak, tell the event router
-    // to deref first, so the resulting refcount is unchanged after we
-    // call SetWidgetName.
-    accessibility_event_router_->RemoveWidgetNameOverride(widget);
-  }
-
-  accessibility_event_router_->AddWidgetNameOverride(widget, name);
-  managed_widgets_.insert(widget);
-}
-
-void AccessibleWidgetHelper::SetWidgetName(
-    GtkWidget* widget, int string_id) {
-  SetWidgetName(widget, l10n_util::GetStringUTF8(string_id));
-}
diff --git a/chrome/browser/gtk/accessible_widget_helper_gtk.h b/chrome/browser/gtk/accessible_widget_helper_gtk.h
deleted file mode 100644
index 2b06fac..0000000
--- a/chrome/browser/gtk/accessible_widget_helper_gtk.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_ACCESSIBLE_WIDGET_HELPER_GTK_H_
-#define CHROME_BROWSER_GTK_ACCESSIBLE_WIDGET_HELPER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <set>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/singleton.h"
-#include "chrome/browser/accessibility_events.h"
-#include "chrome/browser/gtk/accessibility_event_router_gtk.h"
-
-class Profile;
-
-// NOTE: This class is part of the Accessibility Extension API, which lets
-// extensions receive accessibility events. It's distinct from code that
-// implements platform accessibility APIs like MSAA or ATK.
-//
-// Helper class that helps to manage the accessibility information for all
-// of the widgets in a container.  Create an instance of this class for
-// each container GtkWidget (like a dialog) that should send accessibility
-// events for all of its descendants.
-//
-// Most controls have default behavior for accessibility; when this needs
-// to be augmented, call one of the methods below to change its details.
-//
-// All of the information managed by this class is registered with the
-// (global) AccessibilityEventRouterGtk and unregistered when this object is
-// destroyed.
-class AccessibleWidgetHelper {
- public:
-  // Contruct an AccessibleWidgetHelper that makes the given root widget
-  // accessible for the lifetime of this object, sending accessibility
-  // notifications to the given profile.
-  AccessibleWidgetHelper(GtkWidget* root_widget, Profile* profile);
-
-  virtual ~AccessibleWidgetHelper();
-
-  // Send a notification that a new window was opened now, and a
-  // corresponding close window notification when this object
-  // goes out of scope.
-  void SendOpenWindowNotification(const std::string& window_title);
-
-  // Use the following string as the name of this widget, instead of the
-  // gtk label associated with the widget.
-  void SetWidgetName(GtkWidget* widget, std::string name);
-
-  // Use the following string as the name of this widget, instead of the
-  // gtk label associated with the widget.
-  void SetWidgetName(GtkWidget* widget, int string_id);
-
- private:
-  AccessibilityEventRouterGtk* accessibility_event_router_;
-  Profile* profile_;
-  GtkWidget* root_widget_;
-  std::string window_title_;
-  std::set<GtkWidget*> managed_widgets_;
-};
-
-#endif  // CHROME_BROWSER_GTK_ACCESSIBLE_WIDGET_HELPER_GTK_H_
diff --git a/chrome/browser/gtk/back_forward_button_gtk.cc b/chrome/browser/gtk/back_forward_button_gtk.cc
deleted file mode 100644
index 29cf61c..0000000
--- a/chrome/browser/gtk/back_forward_button_gtk.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/back_forward_button_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-// The time in milliseconds between when the user clicks and the menu appears.
-static const int kMenuTimerDelay = 500;
-
-BackForwardButtonGtk::BackForwardButtonGtk(Browser* browser, bool is_forward)
-    : browser_(browser),
-      is_forward_(is_forward),
-      show_menu_factory_(this) {
-  int normal, pushed, hover, disabled, tooltip;
-  const char* stock;
-  if (is_forward) {
-    normal = IDR_FORWARD;
-    pushed = IDR_FORWARD_P;
-    hover = IDR_FORWARD_H;
-    disabled = IDR_FORWARD_D;
-    tooltip = IDS_TOOLTIP_FORWARD;
-    stock = GTK_STOCK_GO_FORWARD;
-  } else {
-    normal = IDR_BACK;
-    pushed = IDR_BACK_P;
-    hover = IDR_BACK_H;
-    disabled = IDR_BACK_D;
-    tooltip = IDS_TOOLTIP_BACK;
-    stock = GTK_STOCK_GO_BACK;
-  }
-  button_.reset(new CustomDrawButton(
-      GtkThemeProvider::GetFrom(browser_->profile()),
-      normal, pushed, hover, disabled, stock, GTK_ICON_SIZE_SMALL_TOOLBAR));
-  gtk_widget_set_tooltip_text(widget(),
-                              l10n_util::GetStringUTF8(tooltip).c_str());
-  menu_model_.reset(new BackForwardMenuModel(browser, is_forward ?
-      BackForwardMenuModel::FORWARD_MENU :
-      BackForwardMenuModel::BACKWARD_MENU));
-
-  g_signal_connect(widget(), "clicked",
-                   G_CALLBACK(OnClickThunk), this);
-  g_signal_connect(widget(), "button-press-event",
-                   G_CALLBACK(OnButtonPressThunk), this);
-  gtk_widget_add_events(widget(), GDK_POINTER_MOTION_MASK);
-  g_signal_connect(widget(), "motion-notify-event",
-                   G_CALLBACK(OnMouseMoveThunk), this);
-
-  // Popup the menu as left-aligned relative to this widget rather than the
-  // default of right aligned.
-  g_object_set_data(G_OBJECT(widget()), "left-align-popup",
-                    reinterpret_cast<void*>(true));
-
-  gtk_util::SetButtonTriggersNavigation(widget());
-}
-
-BackForwardButtonGtk::~BackForwardButtonGtk() {
-}
-
-void BackForwardButtonGtk::StoppedShowing() {
-  button_->UnsetPaintOverride();
-}
-
-bool BackForwardButtonGtk::AlwaysShowIconForCmd(int command_id) const {
-  return true;
-}
-
-void BackForwardButtonGtk::ShowBackForwardMenu() {
-  menu_.reset(new MenuGtk(this, menu_model_.get()));
-  button_->SetPaintOverride(GTK_STATE_ACTIVE);
-
-  // gtk_menu_popup will ignore the first mouse button release if it matches
-  // the button type and is within a short span of the time we pass here.
-  // Since this menu is not popped up by a button press (instead, it is popped
-  // up either on a timer or on a drag) this doesn't apply to us and we can
-  // pass arbitrary values.
-  menu_->Popup(widget(), 1, gtk_get_current_event_time());
-}
-
-void BackForwardButtonGtk::OnClick(GtkWidget* widget) {
-  show_menu_factory_.RevokeAll();
-
-  browser_->ExecuteCommandWithDisposition(
-      is_forward_ ? IDC_FORWARD : IDC_BACK,
-      gtk_util::DispositionForCurrentButtonPressEvent());
-}
-
-gboolean BackForwardButtonGtk::OnButtonPress(GtkWidget* widget,
-                                             GdkEventButton* event) {
-  if (event->button == 3)
-    ShowBackForwardMenu();
-
-  if (event->button != 1)
-    return FALSE;
-
-  y_position_of_last_press_ = static_cast<int>(event->y);
-  MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      show_menu_factory_.NewRunnableMethod(
-          &BackForwardButtonGtk::ShowBackForwardMenu),
-      kMenuTimerDelay);
-  return FALSE;
-}
-
-gboolean BackForwardButtonGtk::OnMouseMove(GtkWidget* widget,
-                                           GdkEventMotion* event) {
-  // If we aren't waiting to show the back forward menu, do nothing.
-  if (show_menu_factory_.empty())
-    return FALSE;
-
-  // We only count moves about a certain threshold.
-  GtkSettings* settings = gtk_widget_get_settings(widget);
-  int drag_min_distance;
-  g_object_get(settings, "gtk-dnd-drag-threshold", &drag_min_distance, NULL);
-  if (event->y - y_position_of_last_press_ < drag_min_distance)
-    return FALSE;
-
-  // We will show the menu now. Cancel the delayed event.
-  show_menu_factory_.RevokeAll();
-  ShowBackForwardMenu();
-  return FALSE;
-}
diff --git a/chrome/browser/gtk/back_forward_button_gtk.h b/chrome/browser/gtk/back_forward_button_gtk.h
deleted file mode 100644
index c136627..0000000
--- a/chrome/browser/gtk/back_forward_button_gtk.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_H_
-#define CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-
-class BackForwardMenuModel;
-class Browser;
-
-typedef struct _GtkWidget GtkWidget;
-
-// When clicked, these buttons will navigate forward or backward. When
-// pressed and held, they show a dropdown menu of recent web sites.
-class BackForwardButtonGtk : MenuGtk::Delegate {
- public:
-  BackForwardButtonGtk(Browser* browser, bool is_forward);
-  virtual ~BackForwardButtonGtk();
-
-  // MenuGtk::Delegate implementation.
-  virtual void StoppedShowing();
-  virtual bool AlwaysShowIconForCmd(int command_id) const;
-
-  GtkWidget* widget() { return button_->widget(); }
-
- private:
-  // Executes the browser command.
-  CHROMEGTK_CALLBACK_0(BackForwardButtonGtk, void, OnClick);
-
-  // Starts a timer to show the dropdown menu.
-  CHROMEGTK_CALLBACK_1(BackForwardButtonGtk, gboolean, OnButtonPress,
-                       GdkEventButton*);
-
-  // If there is a timer to show the dropdown menu, and the mouse has moved
-  // sufficiently down the screen, cancel the timer and immediately show the
-  // menu.
-  CHROMEGTK_CALLBACK_1(BackForwardButtonGtk, gboolean, OnMouseMove,
-                       GdkEventMotion*);
-
-  // Shows the dropdown menu.
-  void ShowBackForwardMenu();
-
-  // The menu gets reset every time it is shown.
-  scoped_ptr<MenuGtk> menu_;
-
-  scoped_ptr<CustomDrawButton> button_;
-
-  // The browser to which we will send commands.
-  Browser* browser_;
-
-  // Whether this button is a forward button.
-  bool is_forward_;
-
-  // The dropdown menu model.
-  scoped_ptr<BackForwardMenuModel> menu_model_;
-
-  // The y position of the last mouse down event.
-  int y_position_of_last_press_;
-
-  ScopedRunnableMethodFactory<BackForwardButtonGtk> show_menu_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackForwardButtonGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc
deleted file mode 100644
index cd1ea94..0000000
--- a/chrome/browser/gtk/bookmark_bar_gtk.cc
+++ /dev/null
@@ -1,1418 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_bar_gtk.h"
-
-#include <vector>
-
-#include "app/gtk_dnd_util.h"
-#include "app/resource_bundle.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/browser_shutdown.h"
-#include "chrome/browser/gtk/bookmark_menu_controller_gtk.h"
-#include "chrome/browser/gtk/bookmark_tree_model.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/hover_controller_gtk.h"
-#include "chrome/browser/gtk/import_dialog_gtk.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "chrome/browser/gtk/tabstrip_origin_provider.h"
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/ntp_background_util.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-// The showing height of the bar.
-const int kBookmarkBarHeight = 29;
-
-// Padding for when the bookmark bar is floating.
-const int kTopBottomNTPPadding = 12;
-const int kLeftRightNTPPadding = 8;
-
-// Padding around the bar's content area when the bookmark bar is floating.
-const int kNTPPadding = 2;
-
-// The number of pixels of rounding on the corners of the bookmark bar content
-// area when in floating mode.
-const int kNTPRoundedness = 3;
-
-// The height of the bar when it is "hidden". It is usually not completely
-// hidden because even when it is closed it forms the bottom few pixels of
-// the toolbar.
-const int kBookmarkBarMinimumHeight = 3;
-
-// Left-padding for the instructional text.
-const int kInstructionsPadding = 6;
-
-// Padding around the "Other Bookmarks" button.
-const int kOtherBookmarksPaddingHorizontal = 2;
-const int kOtherBookmarksPaddingVertical = 1;
-
-// The targets accepted by the toolbar and folder buttons for DnD.
-const int kDestTargetList[] = { gtk_dnd_util::CHROME_BOOKMARK_ITEM,
-                                gtk_dnd_util::CHROME_NAMED_URL,
-                                gtk_dnd_util::TEXT_URI_LIST,
-                                gtk_dnd_util::NETSCAPE_URL,
-                                gtk_dnd_util::TEXT_PLAIN, -1 };
-
-// Acceptable drag actions for the bookmark bar drag destinations.
-const GdkDragAction kDragAction =
-    GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY);
-
-void SetToolBarStyle() {
-  static bool style_was_set = false;
-
-  if (style_was_set)
-    return;
-  style_was_set = true;
-
-  gtk_rc_parse_string(
-      "style \"chrome-bookmark-toolbar\" {"
-      "  xthickness = 0\n"
-      "  ythickness = 0\n"
-      "  GtkWidget::focus-padding = 0\n"
-      "  GtkContainer::border-width = 0\n"
-      "  GtkToolbar::internal-padding = 1\n"
-      "  GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
-      "}\n"
-      "widget \"*chrome-bookmark-toolbar\" style \"chrome-bookmark-toolbar\"");
-}
-
-}  // namespace
-
-const int BookmarkBarGtk::kBookmarkBarNTPHeight = 57;
-
-BookmarkBarGtk::BookmarkBarGtk(BrowserWindowGtk* window,
-                               Profile* profile, Browser* browser,
-                               TabstripOriginProvider* tabstrip_origin_provider)
-    : profile_(NULL),
-      page_navigator_(NULL),
-      browser_(browser),
-      window_(window),
-      tabstrip_origin_provider_(tabstrip_origin_provider),
-      model_(NULL),
-      instructions_(NULL),
-      sync_service_(NULL),
-      dragged_node_(NULL),
-      drag_icon_(NULL),
-      toolbar_drop_item_(NULL),
-      theme_provider_(GtkThemeProvider::GetFrom(profile)),
-      show_instructions_(true),
-      menu_bar_helper_(this),
-      floating_(false),
-      last_allocation_width_(-1),
-      throbbing_widget_(NULL),
-      method_factory_(this) {
-  if (profile->GetProfileSyncService()) {
-    // Obtain a pointer to the profile sync service and add our instance as an
-    // observer.
-    sync_service_ = profile->GetProfileSyncService();
-    sync_service_->AddObserver(this);
-  }
-
-  Init(profile);
-  SetProfile(profile);
-  // Force an update by simulating being in the wrong state.
-  floating_ = !ShouldBeFloating();
-  UpdateFloatingState();
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-BookmarkBarGtk::~BookmarkBarGtk() {
-  RemoveAllBookmarkButtons();
-  bookmark_toolbar_.Destroy();
-  event_box_.Destroy();
-}
-
-void BookmarkBarGtk::SetProfile(Profile* profile) {
-  DCHECK(profile);
-  if (profile_ == profile)
-    return;
-
-  RemoveAllBookmarkButtons();
-
-  profile_ = profile;
-
-  if (model_)
-    model_->RemoveObserver(this);
-
-  // TODO(erg): Handle extensions
-
-  model_ = profile_->GetBookmarkModel();
-  model_->AddObserver(this);
-  if (model_->IsLoaded())
-    Loaded(model_);
-
-  // else case: we'll receive notification back from the BookmarkModel when done
-  // loading, then we'll populate the bar.
-}
-
-void BookmarkBarGtk::SetPageNavigator(PageNavigator* navigator) {
-  page_navigator_ = navigator;
-}
-
-void BookmarkBarGtk::Init(Profile* profile) {
-  event_box_.Own(gtk_event_box_new());
-  g_signal_connect(event_box_.get(), "destroy",
-                   G_CALLBACK(&OnEventBoxDestroyThunk), this);
-  g_signal_connect(event_box_.get(), "button-press-event",
-                   G_CALLBACK(&OnButtonPressedThunk), this);
-
-  ntp_padding_box_ = gtk_alignment_new(0, 0, 1, 1);
-  gtk_container_add(GTK_CONTAINER(event_box_.get()), ntp_padding_box_);
-
-  paint_box_ = gtk_event_box_new();
-  gtk_container_add(GTK_CONTAINER(ntp_padding_box_), paint_box_);
-  GdkColor paint_box_color =
-      theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
-  gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
-  gtk_widget_add_events(paint_box_, GDK_POINTER_MOTION_MASK |
-                                    GDK_BUTTON_PRESS_MASK);
-
-  bookmark_hbox_ = gtk_hbox_new(FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(paint_box_), bookmark_hbox_);
-
-  instructions_ = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(instructions_), 0, 0,
-                            kInstructionsPadding, 0);
-  instructions_gtk_.reset(new BookmarkBarInstructionsGtk(this, profile));
-  gtk_container_add(GTK_CONTAINER(instructions_), instructions_gtk_->widget());
-  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), instructions_,
-                     TRUE, TRUE, 0);
-
-  gtk_drag_dest_set(instructions_,
-      GtkDestDefaults(GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION),
-      NULL, 0, kDragAction);
-  gtk_dnd_util::SetDestTargetList(instructions_, kDestTargetList);
-  g_signal_connect(instructions_, "drag-data-received",
-                   G_CALLBACK(&OnDragReceivedThunk), this);
-
-  g_signal_connect(event_box_.get(), "expose-event",
-                   G_CALLBACK(&OnEventBoxExposeThunk), this);
-  UpdateEventBoxPaintability();
-
-  bookmark_toolbar_.Own(gtk_toolbar_new());
-  SetToolBarStyle();
-  gtk_widget_set_name(bookmark_toolbar_.get(), "chrome-bookmark-toolbar");
-  gtk_util::SuppressDefaultPainting(bookmark_toolbar_.get());
-  g_signal_connect(bookmark_toolbar_.get(), "size-allocate",
-                   G_CALLBACK(&OnToolbarSizeAllocateThunk), this);
-  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), bookmark_toolbar_.get(),
-                     TRUE, TRUE, 0);
-
-  overflow_button_ = theme_provider_->BuildChromeButton();
-  g_object_set_data(G_OBJECT(overflow_button_), "left-align-popup",
-                    reinterpret_cast<void*>(true));
-  SetOverflowButtonAppearance();
-  ConnectFolderButtonEvents(overflow_button_, false);
-  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), overflow_button_,
-                     FALSE, FALSE, 0);
-
-  gtk_drag_dest_set(bookmark_toolbar_.get(), GTK_DEST_DEFAULT_DROP,
-                    NULL, 0, kDragAction);
-  gtk_dnd_util::SetDestTargetList(bookmark_toolbar_.get(), kDestTargetList);
-  g_signal_connect(bookmark_toolbar_.get(), "drag-motion",
-                   G_CALLBACK(&OnToolbarDragMotionThunk), this);
-  g_signal_connect(bookmark_toolbar_.get(), "drag-leave",
-                   G_CALLBACK(&OnDragLeaveThunk), this);
-  g_signal_connect(bookmark_toolbar_.get(), "drag-data-received",
-                   G_CALLBACK(&OnDragReceivedThunk), this);
-
-  GtkWidget* vseparator = theme_provider_->CreateToolbarSeparator();
-  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), vseparator,
-                     FALSE, FALSE, 0);
-
-  // We pack the button manually (rather than using gtk_button_set_*) so that
-  // we can have finer control over its label.
-  other_bookmarks_button_ = theme_provider_->BuildChromeButton();
-  ConnectFolderButtonEvents(other_bookmarks_button_, false);
-  GtkWidget* other_padding = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(other_padding),
-                            kOtherBookmarksPaddingVertical,
-                            kOtherBookmarksPaddingVertical,
-                            kOtherBookmarksPaddingHorizontal,
-                            kOtherBookmarksPaddingHorizontal);
-  gtk_container_add(GTK_CONTAINER(other_padding), other_bookmarks_button_);
-  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_padding,
-                     FALSE, FALSE, 0);
-
-  sync_error_button_ = theme_provider_->BuildChromeButton();
-  gtk_button_set_image(
-      GTK_BUTTON(sync_error_button_),
-      gtk_image_new_from_pixbuf(
-          ResourceBundle::GetSharedInstance().GetPixbufNamed(IDR_WARNING)));
-  g_signal_connect(sync_error_button_, "button-press-event",
-                   G_CALLBACK(OnSyncErrorButtonPressedThunk), this);
-  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), sync_error_button_,
-                     FALSE, FALSE, 0);
-
-  gtk_widget_set_size_request(event_box_.get(), -1, kBookmarkBarMinimumHeight);
-
-  slide_animation_.reset(new ui::SlideAnimation(this));
-
-  ViewIDUtil::SetID(other_bookmarks_button_, VIEW_ID_OTHER_BOOKMARKS);
-  ViewIDUtil::SetID(widget(), VIEW_ID_BOOKMARK_BAR);
-
-  gtk_widget_show_all(widget());
-  gtk_widget_hide(widget());
-}
-
-void BookmarkBarGtk::Show(bool animate) {
-  gtk_widget_show_all(widget());
-  bool old_floating = floating_;
-  UpdateFloatingState();
-  // TODO(estade): animate the transition between floating and non.
-  animate = animate && (old_floating == floating_);
-  if (animate) {
-    slide_animation_->Show();
-  } else {
-    slide_animation_->Reset(1);
-    AnimationProgressed(slide_animation_.get());
-  }
-
-  // Hide out behind the findbar. This is rather fragile code, it could
-  // probably be improved.
-  if (floating_) {
-    if (theme_provider_->UseGtkTheme()) {
-      if (GTK_WIDGET_REALIZED(event_box_->parent))
-        gdk_window_lower(event_box_->parent->window);
-      if (GTK_WIDGET_REALIZED(event_box_.get()))
-        gdk_window_lower(event_box_->window);
-    } else {  // Chromium theme mode.
-      if (GTK_WIDGET_REALIZED(paint_box_)) {
-        gdk_window_lower(paint_box_->window);
-        // The event box won't stay below its children's GdkWindows unless we
-        // toggle the above-child property here. If the event box doesn't stay
-        // below its children then events will be routed to it rather than the
-        // children.
-        gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), TRUE);
-        gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), FALSE);
-      }
-    }
-  }
-
-  if (sync_ui_util::ShouldShowSyncErrorButton(sync_service_)) {
-    gtk_widget_show(sync_error_button_);
-  } else {
-    gtk_widget_hide(sync_error_button_);
-  }
-
-  // Maybe show the instructions
-  if (show_instructions_) {
-    gtk_widget_hide(bookmark_toolbar_.get());
-    gtk_widget_show(instructions_);
-  } else {
-    gtk_widget_hide(instructions_);
-    gtk_widget_show(bookmark_toolbar_.get());
-  }
-
-  SetChevronState();
-}
-
-void BookmarkBarGtk::Hide(bool animate) {
-  UpdateFloatingState();
-
-  // After coming out of fullscreen, the browser window sets the bookmark bar
-  // to the "hidden" state, which means we need to show our minimum height.
-  gtk_widget_show(widget());
-  // Sometimes we get called without a matching call to open. If that happens
-  // then force hide.
-  if (slide_animation_->IsShowing() && animate) {
-    slide_animation_->Hide();
-  } else {
-    gtk_widget_hide(bookmark_hbox_);
-    slide_animation_->Reset(0);
-    AnimationProgressed(slide_animation_.get());
-  }
-}
-
-void BookmarkBarGtk::OnStateChanged() {
-  if (sync_ui_util::ShouldShowSyncErrorButton(sync_service_)) {
-    gtk_widget_show(sync_error_button_);
-  } else {
-    gtk_widget_hide(sync_error_button_);
-  }
-}
-
-void BookmarkBarGtk::ShowImportDialog() {
-  ImportDialogGtk::Show(window_->window(), browser_->profile(),
-                        importer::FAVORITES);
-}
-
-void BookmarkBarGtk::EnterFullscreen() {
-  if (ShouldBeFloating())
-    Show(false);
-  else
-    gtk_widget_hide(widget());
-}
-
-int BookmarkBarGtk::GetHeight() {
-  return event_box_->allocation.height - kBookmarkBarMinimumHeight;
-}
-
-bool BookmarkBarGtk::IsAnimating() {
-  return slide_animation_->is_animating();
-}
-
-bool BookmarkBarGtk::OnNewTabPage() {
-  return (browser_ && browser_->GetSelectedTabContents() &&
-          browser_->GetSelectedTabContents()->ShouldShowBookmarkBar());
-}
-
-void BookmarkBarGtk::Loaded(BookmarkModel* model) {
-  // If |instructions_| has been nulled, we are in the middle of browser
-  // shutdown. Do nothing.
-  if (!instructions_)
-    return;
-
-  RemoveAllBookmarkButtons();
-  CreateAllBookmarkButtons();
-}
-
-void BookmarkBarGtk::BookmarkModelBeingDeleted(BookmarkModel* model) {
-  // The bookmark model should never be deleted before us. This code exists
-  // to check for regressions in shutdown code and not crash.
-  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
-    NOTREACHED();
-
-  // Do minimal cleanup, presumably we'll be deleted shortly.
-  model_->RemoveObserver(this);
-  model_ = NULL;
-}
-
-void BookmarkBarGtk::BookmarkNodeMoved(BookmarkModel* model,
-                                       const BookmarkNode* old_parent,
-                                       int old_index,
-                                       const BookmarkNode* new_parent,
-                                       int new_index) {
-  const BookmarkNode* node = new_parent->GetChild(new_index);
-  BookmarkNodeRemoved(model, old_parent, old_index, node);
-  BookmarkNodeAdded(model, new_parent, new_index);
-}
-
-void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model,
-                                       const BookmarkNode* parent,
-                                       int index) {
-  const BookmarkNode* node = parent->GetChild(index);
-  if (parent != model_->GetBookmarkBarNode()) {
-    StartThrobbing(node);
-    return;
-  }
-  DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
-
-  GtkToolItem* item = CreateBookmarkToolItem(node);
-  gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()),
-                     item, index);
-  if (node->is_folder())
-    menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
-
-  SetInstructionState();
-  SetChevronState();
-
-  MessageLoop::current()->PostTask(FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &BookmarkBarGtk::StartThrobbing, node));
-}
-
-void BookmarkBarGtk::BookmarkNodeRemoved(BookmarkModel* model,
-                                         const BookmarkNode* parent,
-                                         int old_index,
-                                         const BookmarkNode* node) {
-  if (parent != model_->GetBookmarkBarNode()) {
-    // We only care about nodes on the bookmark bar.
-    return;
-  }
-  DCHECK(old_index >= 0 && old_index < GetBookmarkButtonCount());
-
-  GtkWidget* to_remove = GTK_WIDGET(gtk_toolbar_get_nth_item(
-      GTK_TOOLBAR(bookmark_toolbar_.get()), old_index));
-  if (node->is_folder())
-    menu_bar_helper_.Remove(gtk_bin_get_child(GTK_BIN(to_remove)));
-  gtk_container_remove(GTK_CONTAINER(bookmark_toolbar_.get()),
-                       to_remove);
-
-  SetInstructionState();
-  SetChevronState();
-}
-
-void BookmarkBarGtk::BookmarkNodeChanged(BookmarkModel* model,
-                                         const BookmarkNode* node) {
-  if (node->GetParent() != model_->GetBookmarkBarNode()) {
-    // We only care about nodes on the bookmark bar.
-    return;
-  }
-  int index = model_->GetBookmarkBarNode()->IndexOfChild(node);
-  DCHECK(index != -1);
-
-  GtkToolItem* item = gtk_toolbar_get_nth_item(
-      GTK_TOOLBAR(bookmark_toolbar_.get()), index);
-  GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
-  bookmark_utils::ConfigureButtonForNode(node, model, button, theme_provider_);
-  SetChevronState();
-}
-
-void BookmarkBarGtk::BookmarkNodeFavIconLoaded(BookmarkModel* model,
-                                               const BookmarkNode* node) {
-  BookmarkNodeChanged(model, node);
-}
-
-void BookmarkBarGtk::BookmarkNodeChildrenReordered(BookmarkModel* model,
-                                                   const BookmarkNode* node) {
-  if (node != model_->GetBookmarkBarNode())
-    return;  // We only care about reordering of the bookmark bar node.
-
-  // Purge and rebuild the bar.
-  RemoveAllBookmarkButtons();
-  CreateAllBookmarkButtons();
-}
-
-void BookmarkBarGtk::CreateAllBookmarkButtons() {
-  const BookmarkNode* bar = model_->GetBookmarkBarNode();
-  DCHECK(bar && model_->other_node());
-
-  // Create a button for each of the children on the bookmark bar.
-  for (int i = 0; i < bar->GetChildCount(); ++i) {
-    const BookmarkNode* node = bar->GetChild(i);
-    GtkToolItem* item = CreateBookmarkToolItem(node);
-    gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1);
-    if (node->is_folder())
-      menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
-  }
-
-  bookmark_utils::ConfigureButtonForNode(model_->other_node(),
-      model_, other_bookmarks_button_, theme_provider_);
-
-  SetInstructionState();
-  SetChevronState();
-}
-
-void BookmarkBarGtk::SetInstructionState() {
-  show_instructions_ = (model_->GetBookmarkBarNode()->GetChildCount() == 0);
-  if (show_instructions_) {
-    gtk_widget_hide(bookmark_toolbar_.get());
-    gtk_widget_show_all(instructions_);
-  } else {
-    gtk_widget_hide(instructions_);
-    gtk_widget_show(bookmark_toolbar_.get());
-  }
-}
-
-void BookmarkBarGtk::SetChevronState() {
-  if (!GTK_WIDGET_VISIBLE(bookmark_hbox_))
-    return;
-
-  if (show_instructions_) {
-    gtk_widget_hide(overflow_button_);
-    return;
-  }
-
-  int extra_space = 0;
-  if (GTK_WIDGET_VISIBLE(overflow_button_))
-    extra_space = overflow_button_->allocation.width;
-
-  int overflow_idx = GetFirstHiddenBookmark(extra_space, NULL);
-  if (overflow_idx == -1)
-    gtk_widget_hide(overflow_button_);
-  else
-    gtk_widget_show_all(overflow_button_);
-}
-
-void BookmarkBarGtk::RemoveAllBookmarkButtons() {
-  gtk_util::RemoveAllChildren(bookmark_toolbar_.get());
-  menu_bar_helper_.Clear();
-  menu_bar_helper_.Add(other_bookmarks_button_);
-  menu_bar_helper_.Add(overflow_button_);
-}
-
-int BookmarkBarGtk::GetBookmarkButtonCount() {
-  GList* children = gtk_container_get_children(
-      GTK_CONTAINER(bookmark_toolbar_.get()));
-  int count = g_list_length(children);
-  g_list_free(children);
-  return count;
-}
-
-void BookmarkBarGtk::SetOverflowButtonAppearance() {
-  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(overflow_button_));
-  if (former_child)
-    gtk_widget_destroy(former_child);
-
-  GtkWidget* new_child = theme_provider_->UseGtkTheme() ?
-      gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE) :
-      gtk_image_new_from_pixbuf(ResourceBundle::GetSharedInstance().
-          GetRTLEnabledPixbufNamed(IDR_BOOKMARK_BAR_CHEVRONS));
-
-  gtk_container_add(GTK_CONTAINER(overflow_button_), new_child);
-  SetChevronState();
-}
-
-int BookmarkBarGtk::GetFirstHiddenBookmark(
-    int extra_space, std::vector<GtkWidget*>* showing_folders) {
-  int rv = 0;
-  bool overflow = false;
-  GList* toolbar_items =
-      gtk_container_get_children(GTK_CONTAINER(bookmark_toolbar_.get()));
-  for (GList* iter = toolbar_items; iter; iter = g_list_next(iter)) {
-    GtkWidget* tool_item = reinterpret_cast<GtkWidget*>(iter->data);
-    if (gtk_widget_get_direction(tool_item) == GTK_TEXT_DIR_RTL) {
-      overflow = (tool_item->allocation.x + tool_item->style->xthickness <
-                  bookmark_toolbar_.get()->allocation.x - extra_space);
-    } else {
-      overflow =
-        (tool_item->allocation.x + tool_item->allocation.width +
-         tool_item->style->xthickness >
-         bookmark_toolbar_.get()->allocation.width +
-         bookmark_toolbar_.get()->allocation.x + extra_space);
-    }
-    overflow = overflow || tool_item->allocation.x == -1;
-
-    if (overflow)
-      break;
-
-    if (showing_folders &&
-        model_->GetBookmarkBarNode()->GetChild(rv)->is_folder()) {
-      showing_folders->push_back(gtk_bin_get_child(GTK_BIN(tool_item)));
-    }
-    rv++;
-  }
-
-  g_list_free(toolbar_items);
-
-  if (!overflow)
-    return -1;
-
-  return rv;
-}
-
-bool BookmarkBarGtk::ShouldBeFloating() {
-  return (!IsAlwaysShown() || (window_ && window_->IsFullscreen())) &&
-      window_ && window_->GetDisplayedTabContents() &&
-      window_->GetDisplayedTabContents()->ShouldShowBookmarkBar();
-}
-
-void BookmarkBarGtk::UpdateFloatingState() {
-  bool old_floating = floating_;
-  floating_ = ShouldBeFloating();
-  if (floating_ == old_floating)
-    return;
-
-  if (floating_) {
-#if !defined(OS_CHROMEOS)
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), TRUE);
-#endif
-    GdkColor stroke_color = theme_provider_->UseGtkTheme() ?
-        theme_provider_->GetBorderColor() :
-        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_NTP_HEADER);
-    gtk_util::ActAsRoundedWindow(paint_box_, stroke_color, kNTPRoundedness,
-                                 gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
-
-    gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_),
-        kTopBottomNTPPadding, kTopBottomNTPPadding,
-        kLeftRightNTPPadding, kLeftRightNTPPadding);
-    gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), kNTPPadding);
-  } else {
-    gtk_util::StopActingAsRoundedWindow(paint_box_);
-#if !defined(OS_CHROMEOS)
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), FALSE);
-#endif
-    gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_), 0, 0, 0, 0);
-    gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), 0);
-  }
-
-  UpdateEventBoxPaintability();
-  // |window_| can be NULL during testing.
-  if (window_) {
-    window_->BookmarkBarIsFloating(floating_);
-
-    // Listen for parent size allocations.
-    if (floating_ && widget()->parent) {
-      // Only connect once.
-      if (g_signal_handler_find(widget()->parent, G_SIGNAL_MATCH_FUNC,
-          0, 0, NULL, reinterpret_cast<gpointer>(OnParentSizeAllocateThunk),
-          NULL) == 0) {
-        g_signal_connect(widget()->parent, "size-allocate",
-                         G_CALLBACK(OnParentSizeAllocateThunk), this);
-      }
-    }
-  }
-}
-
-void BookmarkBarGtk::UpdateEventBoxPaintability() {
-  gtk_widget_set_app_paintable(event_box_.get(),
-                               !theme_provider_->UseGtkTheme() || floating_);
-  // When using the GTK+ theme, we need to have the event box be visible so
-  // buttons don't get a halo color from the background.  When using Chromium
-  // themes, we want to let the background show through the toolbar.
-
-#if !defined(OS_CHROMEOS)
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()),
-                                   theme_provider_->UseGtkTheme());
-#endif
-}
-
-void BookmarkBarGtk::PaintEventBox() {
-  gfx::Size tab_contents_size;
-  if (GetTabContentsSize(&tab_contents_size) &&
-      tab_contents_size != last_tab_contents_size_) {
-    last_tab_contents_size_ = tab_contents_size;
-    gtk_widget_queue_draw(event_box_.get());
-  }
-}
-
-bool BookmarkBarGtk::GetTabContentsSize(gfx::Size* size) {
-  Browser* browser = browser_;
-  if (!browser) {
-    NOTREACHED();
-    return false;
-  }
-  TabContents* tab_contents = browser->GetSelectedTabContents();
-  if (!tab_contents) {
-    // It is possible to have a browser but no TabContents while under testing,
-    // so don't NOTREACHED() and error the program.
-    return false;
-  }
-  if (!tab_contents->view()) {
-    NOTREACHED();
-    return false;
-  }
-  *size = tab_contents->view()->GetContainerSize();
-  return true;
-}
-
-void BookmarkBarGtk::StartThrobbing(const BookmarkNode* node) {
-  const BookmarkNode* parent_on_bb = NULL;
-  for (const BookmarkNode* parent = node; parent;
-       parent = parent->GetParent()) {
-    if (parent->GetParent() == model_->GetBookmarkBarNode()) {
-      parent_on_bb = parent;
-      break;
-    }
-  }
-
-  GtkWidget* widget_to_throb = NULL;
-
-  if (!parent_on_bb) {
-    // Descendant of "Other Bookmarks".
-    widget_to_throb = other_bookmarks_button_;
-  } else {
-    int hidden = GetFirstHiddenBookmark(0, NULL);
-    int idx = model_->GetBookmarkBarNode()->IndexOfChild(parent_on_bb);
-
-    if (hidden >= 0 && hidden <= idx) {
-      widget_to_throb = overflow_button_;
-    } else {
-      if (parent_on_bb->is_url())
-        return;
-      widget_to_throb = gtk_bin_get_child(GTK_BIN(gtk_toolbar_get_nth_item(
-          GTK_TOOLBAR(bookmark_toolbar_.get()), idx)));
-    }
-  }
-
-  SetThrobbingWidget(widget_to_throb);
-}
-
-void BookmarkBarGtk::SetThrobbingWidget(GtkWidget* widget) {
-  if (throbbing_widget_) {
-    HoverControllerGtk* hover_controller =
-        HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
-    if (hover_controller)
-      hover_controller->StartThrobbing(0);
-
-    g_signal_handlers_disconnect_by_func(
-        throbbing_widget_,
-        reinterpret_cast<gpointer>(OnThrobbingWidgetDestroyThunk),
-        this);
-    g_object_unref(throbbing_widget_);
-    throbbing_widget_ = NULL;
-  }
-
-  if (widget) {
-    throbbing_widget_ = widget;
-    g_object_ref(throbbing_widget_);
-    g_signal_connect(throbbing_widget_, "destroy",
-                     G_CALLBACK(OnThrobbingWidgetDestroyThunk), this);
-
-    HoverControllerGtk* hover_controller =
-        HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
-    if (hover_controller)
-      hover_controller->StartThrobbing(4);
-  }
-}
-
-bool BookmarkBarGtk::IsAlwaysShown() {
-  return profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
-}
-
-void BookmarkBarGtk::AnimationProgressed(const ui::Animation* animation) {
-  DCHECK_EQ(animation, slide_animation_.get());
-
-  int max_height = ShouldBeFloating() ?
-                   kBookmarkBarNTPHeight : kBookmarkBarHeight;
-  gint height =
-      static_cast<gint>(animation->GetCurrentValue() *
-                        (max_height - kBookmarkBarMinimumHeight)) +
-      kBookmarkBarMinimumHeight;
-  gtk_widget_set_size_request(event_box_.get(), -1, height);
-}
-
-void BookmarkBarGtk::AnimationEnded(const ui::Animation* animation) {
-  DCHECK_EQ(animation, slide_animation_.get());
-
-  if (!slide_animation_->IsShowing()) {
-    gtk_widget_hide(bookmark_hbox_);
-
-    // We can be windowless during unit tests.
-    if (window_) {
-      // Because of our constant resizing and our toolbar/bookmark bar overlap
-      // shenanigans, gtk+ gets confused, partially draws parts of the bookmark
-      // bar into the toolbar and than doesn't queue a redraw to fix it. So do
-      // it manually by telling the toolbar area to redraw itself.
-      window_->QueueToolbarRedraw();
-    }
-  }
-}
-
-void BookmarkBarGtk::Observe(NotificationType type,
-                             const NotificationSource& source,
-                             const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    if (model_) {
-      // Regenerate the bookmark bar with all new objects with their theme
-      // properties set correctly for the new theme.
-      RemoveAllBookmarkButtons();
-      CreateAllBookmarkButtons();
-    } else {
-      DLOG(ERROR) << "Received a theme change notification while we "
-                  << "don't have a BookmarkModel. Taking no action.";
-    }
-
-    UpdateEventBoxPaintability();
-
-    GdkColor paint_box_color =
-        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
-    gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
-
-    if (floating_) {
-      GdkColor stroke_color = theme_provider_->UseGtkTheme() ?
-          theme_provider_->GetBorderColor() :
-          theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_NTP_HEADER);
-      gtk_util::SetRoundedWindowBorderColor(paint_box_, stroke_color);
-    }
-
-    SetOverflowButtonAppearance();
-  }
-}
-
-GtkWidget* BookmarkBarGtk::CreateBookmarkButton(const BookmarkNode* node) {
-  GtkWidget* button = theme_provider_->BuildChromeButton();
-  bookmark_utils::ConfigureButtonForNode(node, model_, button, theme_provider_);
-
-  // The tool item is also a source for dragging
-  gtk_drag_source_set(button, GDK_BUTTON1_MASK, NULL, 0,
-      static_cast<GdkDragAction>(GDK_ACTION_MOVE | GDK_ACTION_COPY));
-  int target_mask = bookmark_utils::GetCodeMask(node->is_folder());
-  gtk_dnd_util::SetSourceTargetListFromCodeMask(button, target_mask);
-  g_signal_connect(button, "drag-begin",
-                   G_CALLBACK(&OnButtonDragBeginThunk), this);
-  g_signal_connect(button, "drag-end",
-                   G_CALLBACK(&OnButtonDragEndThunk), this);
-  g_signal_connect(button, "drag-data-get",
-                   G_CALLBACK(&OnButtonDragGetThunk), this);
-  // We deliberately don't connect to "drag-data-delete" because the action of
-  // moving a button will regenerate all the contents of the bookmarks bar
-  // anyway.
-
-  if (node->is_url()) {
-    // Connect to 'button-release-event' instead of 'clicked' because we need
-    // access to the modifier keys and we do different things on each
-    // button.
-    g_signal_connect(button, "button-press-event",
-                     G_CALLBACK(OnButtonPressedThunk), this);
-    g_signal_connect(button, "clicked",
-                     G_CALLBACK(OnClickedThunk), this);
-    gtk_util::SetButtonTriggersNavigation(button);
-  } else {
-    ConnectFolderButtonEvents(button, true);
-  }
-
-  return button;
-}
-
-GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) {
-  GtkWidget* button = CreateBookmarkButton(node);
-  g_object_set_data(G_OBJECT(button), "left-align-popup",
-                    reinterpret_cast<void*>(true));
-
-  GtkToolItem* item = gtk_tool_item_new();
-  gtk_container_add(GTK_CONTAINER(item), button);
-  gtk_widget_show_all(GTK_WIDGET(item));
-
-  return item;
-}
-
-void BookmarkBarGtk::ConnectFolderButtonEvents(GtkWidget* widget,
-                                               bool is_tool_item) {
-  // For toolbar items (i.e. not the overflow button or other bookmarks
-  // button), we handle motion and highlighting manually.
-  gtk_drag_dest_set(widget,
-                    is_tool_item ? GTK_DEST_DEFAULT_DROP :
-                                   GTK_DEST_DEFAULT_ALL,
-                    NULL,
-                    0,
-                    kDragAction);
-  gtk_dnd_util::SetDestTargetList(widget, kDestTargetList);
-  g_signal_connect(widget, "drag-data-received",
-                   G_CALLBACK(&OnDragReceivedThunk), this);
-  if (is_tool_item) {
-    g_signal_connect(widget, "drag-motion",
-                     G_CALLBACK(&OnFolderDragMotionThunk), this);
-    g_signal_connect(widget, "drag-leave",
-                     G_CALLBACK(&OnDragLeaveThunk), this);
-  }
-
-  g_signal_connect(widget, "button-press-event",
-                   G_CALLBACK(OnButtonPressedThunk), this);
-  g_signal_connect(widget, "clicked",
-                   G_CALLBACK(OnFolderClickedThunk), this);
-
-  // Accept middle mouse clicking (which opens all). This must be called after
-  // connecting to "button-press-event" because the handler it attaches stops
-  // the propagation of that signal.
-  gtk_util::SetButtonClickableByMouseButtons(widget, true, true, false);
-}
-
-const BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* widget) {
-  // First check to see if |button| is special cased.
-  if (widget == other_bookmarks_button_)
-    return model_->other_node();
-  else if (widget == event_box_.get() || widget == overflow_button_)
-    return model_->GetBookmarkBarNode();
-
-  // Search the contents of |bookmark_toolbar_| for the corresponding widget
-  // and find its index.
-  GtkWidget* item_to_find = gtk_widget_get_parent(widget);
-  int index_to_use = -1;
-  int index = 0;
-  GList* children = gtk_container_get_children(
-      GTK_CONTAINER(bookmark_toolbar_.get()));
-  for (GList* item = children; item; item = item->next, index++) {
-    if (item->data == item_to_find) {
-      index_to_use = index;
-      break;
-    }
-  }
-  g_list_free(children);
-
-  if (index_to_use != -1)
-    return model_->GetBookmarkBarNode()->GetChild(index_to_use);
-
-  return NULL;
-}
-
-void BookmarkBarGtk::PopupMenuForNode(GtkWidget* sender,
-                                      const BookmarkNode* node,
-                                      GdkEventButton* event) {
-  if (!model_->IsLoaded()) {
-    // Don't do anything if the model isn't loaded.
-    return;
-  }
-
-  const BookmarkNode* parent = NULL;
-  std::vector<const BookmarkNode*> nodes;
-  if (sender == other_bookmarks_button_) {
-    nodes.push_back(node);
-    parent = model_->GetBookmarkBarNode();
-  } else if (sender != bookmark_toolbar_.get()) {
-    nodes.push_back(node);
-    parent = node->GetParent();
-  } else {
-    parent = model_->GetBookmarkBarNode();
-    nodes.push_back(parent);
-  }
-
-  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(sender));
-  current_context_menu_controller_.reset(
-      new BookmarkContextMenuController(
-          window, this, profile_, page_navigator_, parent, nodes));
-  current_context_menu_.reset(
-      new MenuGtk(NULL, current_context_menu_controller_->menu_model()));
-  current_context_menu_->PopupAsContext(event->time);
-}
-
-gboolean BookmarkBarGtk::OnButtonPressed(GtkWidget* sender,
-                                         GdkEventButton* event) {
-  last_pressed_coordinates_ = gfx::Point(event->x, event->y);
-
-  if (event->button == 3 && GTK_WIDGET_VISIBLE(bookmark_hbox_)) {
-    const BookmarkNode* node = GetNodeForToolButton(sender);
-    DCHECK(node);
-    DCHECK(page_navigator_);
-    PopupMenuForNode(sender, node, event);
-  }
-
-  return FALSE;
-}
-
-gboolean BookmarkBarGtk::OnSyncErrorButtonPressed(GtkWidget* sender,
-                                                  GdkEventButton* event) {
-  if (sender == sync_error_button_) {
-    DCHECK(sync_service_ && !sync_service_->IsManaged());
-    sync_service_->ShowLoginDialog(NULL);
-  }
-
-  return FALSE;
-}
-
-void BookmarkBarGtk::OnClicked(GtkWidget* sender) {
-  const BookmarkNode* node = GetNodeForToolButton(sender);
-  DCHECK(node);
-  DCHECK(node->is_url());
-  DCHECK(page_navigator_);
-
-  page_navigator_->OpenURL(
-      node->GetURL(), GURL(),
-      gtk_util::DispositionForCurrentButtonPressEvent(),
-      PageTransition::AUTO_BOOKMARK);
-
-  UserMetrics::RecordAction(UserMetricsAction("ClickedBookmarkBarURLButton"),
-                            profile_);
-}
-
-void BookmarkBarGtk::OnButtonDragBegin(GtkWidget* button,
-                                       GdkDragContext* drag_context) {
-  // The parent tool item might be removed during the drag. Ref it so |button|
-  // won't get destroyed.
-  g_object_ref(button->parent);
-
-  const BookmarkNode* node = GetNodeForToolButton(button);
-  DCHECK(!dragged_node_);
-  dragged_node_ = node;
-  DCHECK(dragged_node_);
-
-  drag_icon_ = bookmark_utils::GetDragRepresentationForNode(
-      node, model_, theme_provider_);
-
-  // We have to jump through some hoops to get the drag icon to line up because
-  // it is a different size than the button.
-  GtkRequisition req;
-  gtk_widget_size_request(drag_icon_, &req);
-  gfx::Rect button_rect = gtk_util::WidgetBounds(button);
-  gfx::Point drag_icon_relative =
-      gfx::Rect(req.width, req.height).CenterPoint().Add(
-          (last_pressed_coordinates_.Subtract(button_rect.CenterPoint())));
-  gtk_drag_set_icon_widget(drag_context, drag_icon_,
-                           drag_icon_relative.x(),
-                           drag_icon_relative.y());
-
-  // Hide our node, but reserve space for it on the toolbar.
-  int index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
-                                         GTK_TOOL_ITEM(button->parent));
-  gtk_widget_hide(button);
-  toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
-  g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
-  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
-                                      GTK_TOOL_ITEM(toolbar_drop_item_), index);
-  // Make sure it stays hidden for the duration of the drag.
-  gtk_widget_set_no_show_all(button, TRUE);
-}
-
-void BookmarkBarGtk::OnButtonDragEnd(GtkWidget* button,
-                                     GdkDragContext* drag_context) {
-  gtk_widget_show(button);
-  gtk_widget_set_no_show_all(button, FALSE);
-
-  ClearToolbarDropHighlighting();
-
-  DCHECK(dragged_node_);
-  dragged_node_ = NULL;
-
-  DCHECK(drag_icon_);
-  gtk_widget_destroy(drag_icon_);
-  drag_icon_ = NULL;
-
-  g_object_unref(button->parent);
-}
-
-void BookmarkBarGtk::OnButtonDragGet(GtkWidget* widget, GdkDragContext* context,
-                                     GtkSelectionData* selection_data,
-                                     guint target_type, guint time) {
-  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
-  bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
-                                           profile_);
-}
-
-void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender) {
-  // Stop its throbbing, if any.
-  HoverControllerGtk* hover_controller =
-      HoverControllerGtk::GetHoverControllerGtk(sender);
-  if (hover_controller)
-    hover_controller->StartThrobbing(0);
-
-  GdkEvent* event = gtk_get_current_event();
-  if (event->button.button == 1) {
-    PopupForButton(sender);
-  } else if (event->button.button == 2) {
-    const BookmarkNode* node = GetNodeForToolButton(sender);
-    bookmark_utils::OpenAll(window_->GetNativeHandle(),
-                            profile_, page_navigator_,
-                            node, NEW_BACKGROUND_TAB);
-  }
-}
-
-gboolean BookmarkBarGtk::ItemDraggedOverToolbar(GdkDragContext* context,
-                                                int index,
-                                                guint time) {
-  GdkAtom target_type =
-      gtk_drag_dest_find_target(bookmark_toolbar_.get(), context, NULL);
-  if (target_type == GDK_NONE) {
-    // We shouldn't act like a drop target when something that we can't deal
-    // with is dragged over the toolbar.
-    return FALSE;
-  }
-
-  if (!toolbar_drop_item_) {
-    if (dragged_node_) {
-      toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
-      g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
-    } else {
-      // Create a fake item the size of other_node().
-      //
-      // TODO(erg): Maybe somehow figure out the real size for the drop target?
-      toolbar_drop_item_ =
-          CreateBookmarkToolItem(model_->other_node());
-      g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
-    }
-  }
-
-  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
-                                      GTK_TOOL_ITEM(toolbar_drop_item_),
-                                      index);
-  if (target_type ==
-      gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_BOOKMARK_ITEM)) {
-    gdk_drag_status(context, GDK_ACTION_MOVE, time);
-  } else {
-    gdk_drag_status(context, GDK_ACTION_COPY, time);
-  }
-
-  return TRUE;
-}
-
-gboolean BookmarkBarGtk::OnToolbarDragMotion(GtkWidget* toolbar,
-                                             GdkDragContext* context,
-                                             gint x,
-                                             gint y,
-                                             guint time) {
-  gint index = gtk_toolbar_get_drop_index(GTK_TOOLBAR(toolbar), x, y);
-  return ItemDraggedOverToolbar(context, index, time);
-}
-
-int BookmarkBarGtk::GetToolbarIndexForDragOverFolder(
-    GtkWidget* button, gint x) {
-  int margin = std::min(15, static_cast<int>(0.3 * button->allocation.width));
-  if (x > margin && x < (button->allocation.width - margin))
-    return -1;
-
-  gint index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
-                                          GTK_TOOL_ITEM(button->parent));
-  if (x > margin)
-    index++;
-  return index;
-}
-
-gboolean BookmarkBarGtk::OnFolderDragMotion(GtkWidget* button,
-                                            GdkDragContext* context,
-                                            gint x,
-                                            gint y,
-                                            guint time) {
-  GdkAtom target_type = gtk_drag_dest_find_target(button, context, NULL);
-  if (target_type == GDK_NONE)
-    return FALSE;
-
-  int index = GetToolbarIndexForDragOverFolder(button, x);
-  if (index < 0) {
-    ClearToolbarDropHighlighting();
-
-    // Drag is over middle of folder.
-    gtk_drag_highlight(button);
-    if (target_type ==
-        gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_BOOKMARK_ITEM)) {
-      gdk_drag_status(context, GDK_ACTION_MOVE, time);
-    } else {
-      gdk_drag_status(context, GDK_ACTION_COPY, time);
-    }
-
-    return TRUE;
-  }
-
-  // Remove previous highlighting.
-  gtk_drag_unhighlight(button);
-  return ItemDraggedOverToolbar(context, index, time);
-}
-
-void BookmarkBarGtk::ClearToolbarDropHighlighting() {
-  if (toolbar_drop_item_) {
-    g_object_unref(toolbar_drop_item_);
-    toolbar_drop_item_ = NULL;
-  }
-
-  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
-                                      NULL, 0);
-}
-
-void BookmarkBarGtk::OnDragLeave(GtkWidget* sender,
-                                 GdkDragContext* context,
-                                 guint time) {
-  if (GTK_IS_BUTTON(sender))
-    gtk_drag_unhighlight(sender);
-
-  ClearToolbarDropHighlighting();
-}
-
-void BookmarkBarGtk::OnToolbarSizeAllocate(GtkWidget* widget,
-                                           GtkAllocation* allocation) {
-  if (bookmark_toolbar_.get()->allocation.width ==
-      last_allocation_width_) {
-    // If the width hasn't changed, then the visibility of the chevron
-    // doesn't need to change. This check prevents us from getting stuck in a
-    // loop where allocates are queued indefinitely while the visibility of
-    // overflow chevron toggles without actual resizes of the toolbar.
-    return;
-  }
-  last_allocation_width_ = bookmark_toolbar_.get()->allocation.width;
-
-  SetChevronState();
-}
-
-void BookmarkBarGtk::OnDragReceived(GtkWidget* widget,
-                                    GdkDragContext* context,
-                                    gint x, gint y,
-                                    GtkSelectionData* selection_data,
-                                    guint target_type, guint time) {
-  gboolean dnd_success = FALSE;
-  gboolean delete_selection_data = FALSE;
-
-  const BookmarkNode* dest_node = model_->GetBookmarkBarNode();
-  gint index;
-  if (widget == bookmark_toolbar_.get()) {
-    index = gtk_toolbar_get_drop_index(
-      GTK_TOOLBAR(bookmark_toolbar_.get()), x, y);
-  } else if (widget == instructions_) {
-    dest_node = model_->GetBookmarkBarNode();
-    index = 0;
-  } else {
-    index = GetToolbarIndexForDragOverFolder(widget, x);
-    if (index < 0) {
-      dest_node = GetNodeForToolButton(widget);
-      index = dest_node->GetChildCount();
-    }
-  }
-
-  switch (target_type) {
-    case gtk_dnd_util::CHROME_BOOKMARK_ITEM: {
-      std::vector<const BookmarkNode*> nodes =
-          bookmark_utils::GetNodesFromSelection(context, selection_data,
-                                                target_type,
-                                                profile_,
-                                                &delete_selection_data,
-                                                &dnd_success);
-      DCHECK(!nodes.empty());
-      for (std::vector<const BookmarkNode*>::iterator it = nodes.begin();
-           it != nodes.end(); ++it) {
-        model_->Move(*it, dest_node, index);
-        index = dest_node->IndexOfChild(*it) + 1;
-      }
-      break;
-    }
-
-    case gtk_dnd_util::CHROME_NAMED_URL: {
-      dnd_success = bookmark_utils::CreateNewBookmarkFromNamedUrl(
-          selection_data, model_, dest_node, index);
-      break;
-    }
-
-    case gtk_dnd_util::TEXT_URI_LIST: {
-      dnd_success = bookmark_utils::CreateNewBookmarksFromURIList(
-          selection_data, model_, dest_node, index);
-      break;
-    }
-
-    case gtk_dnd_util::NETSCAPE_URL: {
-      dnd_success = bookmark_utils::CreateNewBookmarkFromNetscapeURL(
-          selection_data, model_, dest_node, index);
-      break;
-    }
-
-    case gtk_dnd_util::TEXT_PLAIN: {
-      guchar* text = gtk_selection_data_get_text(selection_data);
-      if (!text)
-        break;
-      GURL url(reinterpret_cast<char*>(text));
-      g_free(text);
-      // TODO(estade): It would be nice to head this case off at drag motion,
-      // so that it doesn't look like we can drag onto the bookmark bar.
-      if (!url.is_valid())
-        break;
-      std::string title = bookmark_utils::GetNameForURL(url);
-      model_->AddURL(dest_node, index, UTF8ToUTF16(title), url);
-      dnd_success = TRUE;
-      break;
-    }
-  }
-
-  gtk_drag_finish(context, dnd_success, delete_selection_data, time);
-}
-
-gboolean BookmarkBarGtk::OnEventBoxExpose(GtkWidget* widget,
-                                          GdkEventExpose* event) {
-  GtkThemeProvider* theme_provider = theme_provider_;
-
-  // We don't need to render the toolbar image in GTK mode, except when
-  // detached.
-  if (theme_provider->UseGtkTheme() && !floating_)
-    return FALSE;
-
-  if (!floating_) {
-    cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-    gdk_cairo_rectangle(cr, &event->area);
-    cairo_clip(cr);
-
-    // Paint the background theme image.
-    gfx::Point tabstrip_origin =
-        tabstrip_origin_provider_->GetTabStripOriginForWidget(widget);
-    gtk_util::DrawThemedToolbarBackground(widget, cr, event, tabstrip_origin,
-                                          theme_provider);
-
-    cairo_destroy(cr);
-  } else {
-    gfx::Size tab_contents_size;
-    if (!GetTabContentsSize(&tab_contents_size))
-      return FALSE;
-    gfx::CanvasSkiaPaint canvas(event, true);
-
-    gfx::Rect area = GTK_WIDGET_NO_WINDOW(widget) ?
-        gfx::Rect(widget->allocation) :
-        gfx::Rect(0, 0, widget->allocation.width, widget->allocation.height);
-    NtpBackgroundUtil::PaintBackgroundDetachedMode(theme_provider, &canvas,
-        area, tab_contents_size.height());
-  }
-
-  return FALSE;  // Propagate expose to children.
-}
-
-void BookmarkBarGtk::OnEventBoxDestroy(GtkWidget* widget) {
-  if (model_)
-    model_->RemoveObserver(this);
-
-  if (sync_service_)
-    sync_service_->RemoveObserver(this);
-}
-
-void BookmarkBarGtk::OnParentSizeAllocate(GtkWidget* widget,
-                                          GtkAllocation* allocation) {
-  // In floating mode, our layout depends on the size of the tab contents.
-  // We get the size-allocate signal before the tab contents does, hence we
-  // need to post a delayed task so we will paint correctly. Note that
-  // gtk_widget_queue_draw by itself does not work, despite that it claims to
-  // be asynchronous.
-  if (floating_) {
-    MessageLoop::current()->PostTask(FROM_HERE,
-        method_factory_.NewRunnableMethod(
-            &BookmarkBarGtk::PaintEventBox));
-  }
-}
-
-void BookmarkBarGtk::OnThrobbingWidgetDestroy(GtkWidget* widget) {
-  SetThrobbingWidget(NULL);
-}
-
-// MenuBarHelper::Delegate implementation --------------------------------------
-void BookmarkBarGtk::PopupForButton(GtkWidget* button) {
-  const BookmarkNode* node = GetNodeForToolButton(button);
-  DCHECK(node);
-  DCHECK(page_navigator_);
-
-  int first_hidden = GetFirstHiddenBookmark(0, NULL);
-  if (first_hidden == -1) {
-    // No overflow exists: don't show anything for the overflow button.
-    if (button == overflow_button_)
-      return;
-  } else {
-    // Overflow exists: don't show anything for an overflowed folder button.
-    if (button != overflow_button_ && button != other_bookmarks_button_ &&
-        node->GetParent()->IndexOfChild(node) >= first_hidden) {
-      return;
-    }
-  }
-
-  current_menu_.reset(
-      new BookmarkMenuController(browser_, profile_, page_navigator_,
-                                 GTK_WINDOW(gtk_widget_get_toplevel(button)),
-                                 node,
-                                 button == overflow_button_ ?
-                                     first_hidden : 0));
-  menu_bar_helper_.MenuStartedShowing(button, current_menu_->widget());
-  GdkEvent* event = gtk_get_current_event();
-  current_menu_->Popup(button, event->button.button, event->button.time);
-  gdk_event_free(event);
-}
-
-void BookmarkBarGtk::PopupForButtonNextTo(GtkWidget* button,
-                                          GtkMenuDirectionType dir) {
-  const BookmarkNode* relative_node = GetNodeForToolButton(button);
-  DCHECK(relative_node);
-
-  // Find out the order of the buttons.
-  std::vector<GtkWidget*> folder_list;
-  const int first_hidden = GetFirstHiddenBookmark(0, &folder_list);
-  if (first_hidden != -1)
-    folder_list.push_back(overflow_button_);
-  folder_list.push_back(other_bookmarks_button_);
-
-  // Find the position of |button|.
-  int button_idx = -1;
-  for (size_t i = 0; i < folder_list.size(); ++i) {
-    if (folder_list[i] == button) {
-      button_idx = i;
-      break;
-    }
-  }
-  DCHECK_NE(button_idx, -1);
-
-  // Find the GtkWidget* for the actual target button.
-  int shift = dir == GTK_MENU_DIR_PARENT ? -1 : 1;
-  button_idx = (button_idx + shift + folder_list.size()) % folder_list.size();
-  PopupForButton(folder_list[button_idx]);
-}
-
-void BookmarkBarGtk::CloseMenu() {
-  current_context_menu_->Cancel();
-}
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.h b/chrome/browser/gtk/bookmark_bar_gtk.h
deleted file mode 100644
index 7d62572..0000000
--- a/chrome/browser/gtk/bookmark_bar_gtk.h
+++ /dev/null
@@ -1,401 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_BAR_GTK_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_BAR_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/gtest_prod_util.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
-#include "chrome/browser/bookmarks/bookmark_model_observer.h"
-#include "chrome/browser/gtk/bookmark_bar_instructions_gtk.h"
-#include "chrome/browser/gtk/menu_bar_helper.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/point.h"
-#include "gfx/size.h"
-#include "ui/base/animation/animation_delegate.h"
-
-class BookmarkMenuController;
-class Browser;
-class BrowserWindowGtk;
-class CustomContainerButton;
-class GtkThemeProvider;
-class MenuGtk;
-class PageNavigator;
-class Profile;
-class TabstripOriginProvider;
-
-namespace ui {
-class SlideAnimation;
-}
-
-class BookmarkBarGtk : public ui::AnimationDelegate,
-                       public ProfileSyncServiceObserver,
-                       public BookmarkModelObserver,
-                       public MenuBarHelper::Delegate,
-                       public NotificationObserver,
-                       public BookmarkBarInstructionsGtk::Delegate,
-                       public BookmarkContextMenuControllerDelegate {
- public:
-  BookmarkBarGtk(BrowserWindowGtk* window,
-                 Profile* profile,
-                 Browser* browser,
-                 TabstripOriginProvider* tabstrip_origin_provider);
-  virtual ~BookmarkBarGtk();
-
-  // Resets the profile. This removes any buttons for the current profile and
-  // recreates the models.
-  void SetProfile(Profile* profile);
-
-  // Returns the current profile.
-  Profile* GetProfile() { return profile_; }
-
-  // Returns the current browser.
-  Browser* browser() const { return browser_; }
-
-  // Returns the top level widget.
-  GtkWidget* widget() const { return event_box_.get(); }
-
-  // Sets the PageNavigator that is used when the user selects an entry on
-  // the bookmark bar.
-  void SetPageNavigator(PageNavigator* navigator);
-
-  // Create the contents of the bookmark bar.
-  void Init(Profile* profile);
-
-  // Whether the current page is the New Tag Page (which requires different
-  // rendering).
-  bool OnNewTabPage();
-
-  // Change the visibility of the bookmarks bar. (Starts out hidden, per GTK's
-  // default behaviour). There are three visiblity states:
-  //
-  //   Showing    - bookmark bar is fully visible.
-  //   Hidden     - bookmark bar is hidden except for a few pixels that give
-  //                extra padding to the bottom of the toolbar. Buttons are not
-  //                clickable.
-  //   Fullscreen - bookmark bar is fully hidden.
-  void Show(bool animate);
-  void Hide(bool animate);
-  void EnterFullscreen();
-
-  // Get the current height of the bookmark bar.
-  int GetHeight();
-
-  // Returns true if the bookmark bar is showing an animation.
-  bool IsAnimating();
-
-  // Returns true if the bookmarks bar preference is set to 'always show'.
-  bool IsAlwaysShown();
-
-  // ui::AnimationDelegate implementation --------------------------------------
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-
-  // MenuBarHelper::Delegate implementation ------------------------------------
-  virtual void PopupForButton(GtkWidget* button);
-  virtual void PopupForButtonNextTo(GtkWidget* button,
-                                    GtkMenuDirectionType dir);
-
-  // The NTP needs to have access to this.
-  static const int kBookmarkBarNTPHeight;
-
-  // BookmarkContextMenuController::Delegate implementation --------------------
-  virtual void CloseMenu();
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, DisplaysHelpMessageOnEmpty);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest,
-                           HidesHelpMessageWithBookmark);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, BuildsButtons);
-
-  // Helper function which generates GtkToolItems for |bookmark_toolbar_|.
-  void CreateAllBookmarkButtons();
-
-  // Sets the visibility of the instructional text based on whether there are
-  // any bookmarks in the bookmark bar node.
-  void SetInstructionState();
-
-  // Sets the visibility of the overflow chevron.
-  void SetChevronState();
-
-  // Helper function which destroys all the bookmark buttons in the GtkToolbar.
-  void RemoveAllBookmarkButtons();
-
-  // Returns the number of buttons corresponding to starred urls/groups. This
-  // is equivalent to the number of children the bookmark bar node from the
-  // bookmark bar model has.
-  int GetBookmarkButtonCount();
-
-  // Set the appearance of the overflow button appropriately (either chromium
-  // style or GTK style).
-  void SetOverflowButtonAppearance();
-
-  // Returns the index of the first bookmark that is not visible on the bar.
-  // Returns -1 if they are all visible.
-  // |extra_space| is how much extra space to give the toolbar during the
-  // calculation (for the purposes of determining if ditching the chevron
-  // would be a good idea).
-  // If non-NULL, |showing_folders| will be packed with all the folders that are
-  // showing on the bar.
-  int GetFirstHiddenBookmark(int extra_space,
-                             std::vector<GtkWidget*>* showing_folders);
-
-  // Returns true if the bookmark bar should be floating on the page (for
-  // NTP).
-  bool ShouldBeFloating();
-  // Update the floating state (either enable or disable it, or do nothing).
-  void UpdateFloatingState();
-
-  // Turns on or off the app_paintable flag on |event_box_|, depending on our
-  // state.
-  void UpdateEventBoxPaintability();
-
-  // Queue a paint on the event box.
-  void PaintEventBox();
-
-  // Finds the size of the current tab contents, if it exists and sets |size|
-  // to the correct value. Returns false if there isn't a TabContents, a
-  // condition that can happen during testing.
-  bool GetTabContentsSize(gfx::Size* size);
-
-  // Makes the appropriate widget on the bookmark bar stop throbbing
-  // (a folder, the overflow chevron, or nothing).
-  void StartThrobbing(const BookmarkNode* node);
-
-  // Set |throbbing_widget_| to |widget|. Also makes sure that
-  // |throbbing_widget_| doesn't become stale.
-  void SetThrobbingWidget(GtkWidget* widget);
-
-  // An item has been dragged over the toolbar, update the drag context
-  // and toolbar UI appropriately.
-  gboolean ItemDraggedOverToolbar(
-      GdkDragContext* context, int index, guint time);
-
-  // When dragging in the middle of a folder, assume the user wants to drop
-  // on the folder. Towards the edges, assume the user wants to drop on the
-  // toolbar. This makes it possible to drop between two folders. This function
-  // returns the index on the toolbar the drag should target, or -1 if the
-  // drag should hit the folder.
-  int GetToolbarIndexForDragOverFolder(GtkWidget* button, gint x);
-
-  void ClearToolbarDropHighlighting();
-
-  // Overridden from BookmarkModelObserver:
-
-  // Invoked when the bookmark model has finished loading. Creates a button
-  // for each of the children of the root node from the model.
-  virtual void Loaded(BookmarkModel* model);
-
-  // Invoked when the model is being deleted.
-  virtual void BookmarkModelBeingDeleted(BookmarkModel* model);
-
-  // Invoked when a node has moved.
-  virtual void BookmarkNodeMoved(BookmarkModel* model,
-                                 const BookmarkNode* old_parent,
-                                 int old_index,
-                                 const BookmarkNode* new_parent,
-                                 int new_index);
-  virtual void BookmarkNodeAdded(BookmarkModel* model,
-                                 const BookmarkNode* parent,
-                                 int index);
-  virtual void BookmarkNodeRemoved(BookmarkModel* model,
-                                   const BookmarkNode* parent,
-                                   int old_index,
-                                   const BookmarkNode* node);
-  virtual void BookmarkNodeChanged(BookmarkModel* model,
-                                   const BookmarkNode* node);
-  // Invoked when a favicon has finished loading.
-  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
-                                         const BookmarkNode* node);
-  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
-                                             const BookmarkNode* node);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  GtkWidget* CreateBookmarkButton(const BookmarkNode* node);
-  GtkToolItem* CreateBookmarkToolItem(const BookmarkNode* node);
-
-  void ConnectFolderButtonEvents(GtkWidget* widget, bool is_tool_item);
-
-  // Finds the BookmarkNode from the model associated with |button|.
-  const BookmarkNode* GetNodeForToolButton(GtkWidget* button);
-
-  // Creates and displays a popup menu for BookmarkNode |node|.
-  void PopupMenuForNode(GtkWidget* sender, const BookmarkNode* node,
-                        GdkEventButton* event);
-
-  // GtkButton callbacks.
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnButtonPressed,
-                       GdkEventButton*);
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnSyncErrorButtonPressed,
-                       GdkEventButton*);
-  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnClicked);
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragBegin,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragEnd, GdkDragContext*);
-  CHROMEGTK_CALLBACK_4(BookmarkBarGtk, void, OnButtonDragGet,
-                       GdkDragContext*, GtkSelectionData*, guint, guint);
-
-  // GtkButton callbacks for folder buttons.
-  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnFolderClicked);
-
-  // GtkToolbar callbacks.
-  CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnToolbarDragMotion,
-                       GdkDragContext*, gint, gint, guint);
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnToolbarSizeAllocate,
-                       GtkAllocation*);
-
-  // Used for both folder buttons and the toolbar.
-  CHROMEGTK_CALLBACK_6(BookmarkBarGtk, void, OnDragReceived,
-                       GdkDragContext*, gint, gint, GtkSelectionData*,
-                       guint, guint);
-  CHROMEGTK_CALLBACK_2(BookmarkBarGtk, void, OnDragLeave,
-                       GdkDragContext*, guint);
-
-  // Used for folder buttons.
-  CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnFolderDragMotion,
-                       GdkDragContext*, gint, gint, guint);
-
-  // GtkEventBox callbacks.
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnEventBoxExpose,
-                       GdkEventExpose*);
-  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnEventBoxDestroy);
-
-  // Callbacks on our parent widget.
-  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnParentSizeAllocate,
-                       GtkAllocation*);
-
-  // |throbbing_widget_| callback.
-  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnThrobbingWidgetDestroy);
-
-  // ProfileSyncServiceObserver method.
-  virtual void OnStateChanged();
-
-  // Overriden from BookmarkBarInstructionsGtk::Delegate.
-  virtual void ShowImportDialog();
-
-  Profile* profile_;
-
-  // Used for opening urls.
-  PageNavigator* page_navigator_;
-
-  Browser* browser_;
-  BrowserWindowGtk* window_;
-
-  // Provides us with the offset into the background theme image.
-  TabstripOriginProvider* tabstrip_origin_provider_;
-
-  // Model providing details as to the starred entries/groups that should be
-  // shown. This is owned by the Profile.
-  BookmarkModel* model_;
-
-  // Contains |bookmark_hbox_|. Event box exists to prevent leakage of
-  // background color from the toplevel application window's GDK window.
-  OwnedWidgetGtk event_box_;
-
-  // Used to float the bookmark bar when on the NTP.
-  GtkWidget* ntp_padding_box_;
-
-  // Used to paint the background of the bookmark bar when in floating mode.
-  GtkWidget* paint_box_;
-
-  // Used to position all children.
-  GtkWidget* bookmark_hbox_;
-
-  // Alignment widget that is visible if there are no bookmarks on
-  // the bookmar bar.
-  GtkWidget* instructions_;
-
-  // BookmarkBarInstructionsGtk that holds the label and the link for importing
-  // bookmarks when there are no bookmarks on the bookmark bar.
-  scoped_ptr<BookmarkBarInstructionsGtk> instructions_gtk_;
-
-  // GtkToolbar which contains all the bookmark buttons.
-  OwnedWidgetGtk bookmark_toolbar_;
-
-  // The button that shows extra bookmarks that don't fit on the bookmark
-  // bar.
-  GtkWidget* overflow_button_;
-
-  // The other bookmarks button.
-  GtkWidget* other_bookmarks_button_;
-
-  // The sync error button.
-  GtkWidget* sync_error_button_;
-
-  // A pointer to the ProfileSyncService instance if one exists.
-  ProfileSyncService* sync_service_;
-
-  // The BookmarkNode from the model being dragged. NULL when we aren't
-  // dragging.
-  const BookmarkNode* dragged_node_;
-
-  // The visual representation that follows the cursor during drags.
-  GtkWidget* drag_icon_;
-
-  // We create a GtkToolbarItem from |dragged_node_| ;or display.
-  GtkToolItem* toolbar_drop_item_;
-
-  // Theme provider for building buttons.
-  GtkThemeProvider* theme_provider_;
-
-  // Whether we should show the instructional text in the bookmark bar.
-  bool show_instructions_;
-
-  MenuBarHelper menu_bar_helper_;
-
-  // The last displayed right click menu, or NULL if no menus have been
-  // displayed yet.
-  // The controller.
-  scoped_ptr<BookmarkContextMenuController> current_context_menu_controller_;
-  // The view.
-  scoped_ptr<MenuGtk> current_context_menu_;
-
-  // The last displayed left click menu, or NULL if no menus have been
-  // displayed yet.
-  scoped_ptr<BookmarkMenuController> current_menu_;
-
-  scoped_ptr<ui::SlideAnimation> slide_animation_;
-
-  // Whether we are currently configured as floating (detached from the
-  // toolbar). This reflects our actual state, and can be out of sync with
-  // what ShouldShowFloating() returns.
-  bool floating_;
-
-  // Used to optimize out |bookmark_toolbar_| size-allocate events we don't
-  // need to respond to.
-  int last_allocation_width_;
-
-  NotificationRegistrar registrar_;
-
-  // The size of the tab contents last time we forced a paint. We keep track
-  // of this so we don't force too many paints.
-  gfx::Size last_tab_contents_size_;
-
-  // The last coordinates recorded by OnButtonPress; used to line up the
-  // drag icon during bookmark drags.
-  gfx::Point last_pressed_coordinates_;
-
-  // The currently throbbing widget. This is NULL if no widget is throbbing.
-  // We track it because we only want to allow one widget to throb at a time.
-  GtkWidget* throbbing_widget_;
-
-  ScopedRunnableMethodFactory<BookmarkBarGtk> method_factory_;
-};
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_BAR_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc b/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc
deleted file mode 100644
index cb027a8..0000000
--- a/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/in_process_browser_test.h"
-#include "chrome/test/ui_test_utils.h"
-#include "net/test/test_server.h"
-
-namespace {
-
-const char kSimplePage[] = "404_is_enough_for_us.html";
-
-void OnClicked(GtkWidget* widget, bool* clicked_bit) {
-  *clicked_bit = true;
-}
-
-}  // namespace
-
-class BookmarkBarGtkInteractiveUITest : public InProcessBrowserTest {
-};
-
-// Makes sure that when you switch back to an NTP with an active findbar,
-// the findbar is above the floating bookmark bar.
-IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, FindBarTest) {
-  ASSERT_TRUE(test_server()->Start());
-
-  // Create new tab; open findbar.
-  browser()->NewTab();
-  browser()->Find();
-
-  // Create new tab with an arbitrary URL.
-  GURL url = test_server()->GetURL(kSimplePage);
-  browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
-
-  // Switch back to the NTP with the active findbar.
-  browser()->SelectTabContentsAt(1, false);
-
-  // Wait for the findbar to show.
-  MessageLoop::current()->RunAllPending();
-
-  // Set focus somewhere else, so that we can test clicking on the findbar
-  // works.
-  browser()->FocusLocationBar();
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
-  ui_test_utils::IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
-}
-
-// Makes sure that you can click on the floating bookmark bar.
-IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, ClickOnFloatingTest) {
-  ASSERT_TRUE(test_server()->Start());
-
-  GtkWidget* other_bookmarks =
-      ViewIDUtil::GetWidget(GTK_WIDGET(browser()->window()->GetNativeHandle()),
-      VIEW_ID_OTHER_BOOKMARKS);
-  bool has_been_clicked = false;
-  g_signal_connect(other_bookmarks, "clicked",
-                   G_CALLBACK(OnClicked), &has_been_clicked);
-
-  // Create new tab.
-  browser()->NewTab();
-
-  // Wait for the floating bar to appear.
-  MessageLoop::current()->RunAllPending();
-
-  // This is kind of a hack. Calling this just once doesn't seem to send a click
-  // event, but doing it twice works.
-  // http://crbug.com/35581
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_OTHER_BOOKMARKS);
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_OTHER_BOOKMARKS);
-
-  EXPECT_TRUE(has_been_clicked);
-}
diff --git a/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc b/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc
deleted file mode 100644
index 074e8fc..0000000
--- a/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_bar_gtk.h"
-
-#include "base/task.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gtk/tabstrip_origin_provider.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Dummy implementation that's good enough for the tests; we don't test
-// rendering here so all we need is a non-NULL object.
-class EmptyTabstripOriginProvider : public TabstripOriginProvider {
- public:
-  virtual gfx::Point GetTabStripOriginForWidget(GtkWidget* widget) {
-    return gfx::Point(0, 0);
-  }
-};
-
-class BookmarkBarGtkUnittest : public ::testing::Test {
- protected:
-  BookmarkBarGtkUnittest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_) {
-  }
-
-  virtual void SetUp() {
-    profile_.reset(new TestingProfile());
-    profile_->CreateBookmarkModel(true);
-    profile_->BlockUntilBookmarkModelLoaded();
-    browser_.reset(new Browser(Browser::TYPE_NORMAL, profile_.get()));
-
-    origin_provider_.reset(new EmptyTabstripOriginProvider);
-    bookmark_bar_.reset(new BookmarkBarGtk(NULL, profile_.get(), browser_.get(),
-                                           origin_provider_.get()));
-  }
-
-  virtual void TearDown() {
-    message_loop_.RunAllPending();
-
-    bookmark_bar_.reset();
-    origin_provider_.reset();
-    browser_.reset();
-    profile_.reset();
-  }
-
-  MessageLoopForUI message_loop_;
-  BrowserThread ui_thread_;
-  BrowserThread file_thread_;
-
-  scoped_ptr<TestingProfile> profile_;
-  scoped_ptr<Browser> browser_;
-  scoped_ptr<TabstripOriginProvider> origin_provider_;
-  scoped_ptr<BookmarkBarGtk> bookmark_bar_;
-};
-
-TEST_F(BookmarkBarGtkUnittest, DisplaysHelpMessageOnEmpty) {
-  BookmarkModel* model = profile_->GetBookmarkModel();
-  bookmark_bar_->Loaded(model);
-
-  // There are no bookmarks in the model by default. Expect that the
-  // |instructions_label| is shown.
-  EXPECT_TRUE(bookmark_bar_->show_instructions_);
-}
-
-TEST_F(BookmarkBarGtkUnittest, HidesHelpMessageWithBookmark) {
-  BookmarkModel* model = profile_->GetBookmarkModel();
-
-  const BookmarkNode* parent = model->GetBookmarkBarNode();
-  model->AddURL(parent, parent->GetChildCount(),
-                ASCIIToUTF16("title"), GURL("http://one.com"));
-
-  bookmark_bar_->Loaded(model);
-  EXPECT_FALSE(bookmark_bar_->show_instructions_);
-}
-
-TEST_F(BookmarkBarGtkUnittest, BuildsButtons) {
-  BookmarkModel* model = profile_->GetBookmarkModel();
-
-  const BookmarkNode* parent = model->GetBookmarkBarNode();
-  model->AddURL(parent, parent->GetChildCount(),
-                ASCIIToUTF16("title"), GURL("http://one.com"));
-  model->AddURL(parent, parent->GetChildCount(),
-                ASCIIToUTF16("other"), GURL("http://two.com"));
-
-  bookmark_bar_->Loaded(model);
-
-  // We should expect two children to the bookmark bar's toolbar.
-  GList* children = gtk_container_get_children(
-      GTK_CONTAINER(bookmark_bar_->bookmark_toolbar_.get()));
-  EXPECT_EQ(2U, g_list_length(children));
-  g_list_free(children);
-}
diff --git a/chrome/browser/gtk/bookmark_bar_instructions_gtk.cc b/chrome/browser/gtk/bookmark_bar_instructions_gtk.cc
deleted file mode 100644
index 8090c06..0000000
--- a/chrome/browser/gtk/bookmark_bar_instructions_gtk.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_CC_
-#define CHROME_BROWSER_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_CC_
-
-#include "chrome/browser/gtk/bookmark_bar_instructions_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/observer_list.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/common/notification_service.h"
-#include "grit/generated_resources.h"
-
-BookmarkBarInstructionsGtk::BookmarkBarInstructionsGtk(Delegate* delegate,
-                                                       Profile* profile)
-    : delegate_(delegate),
-      profile_(profile),
-      theme_provider_(GtkThemeProvider::GetFrom(profile_)) {
-  instructions_hbox_ = gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, 0);
-  gtk_widget_set_size_request(instructions_hbox_, 0, -1);
-
-  instructions_label_ = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_BOOKMARKS_NO_ITEMS).c_str());
-  gtk_misc_set_alignment(GTK_MISC(instructions_label_), 0, 0.5);
-  gtk_util::CenterWidgetInHBox(instructions_hbox_, instructions_label_,
-                               false, 1);
-  g_signal_connect(instructions_label_, "map",
-                   G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
-                   NULL);
-
-  instructions_link_ = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_BOOKMARK_BAR_IMPORT_LINK).c_str());
-  gtk_misc_set_alignment(
-      GTK_MISC(GTK_CHROME_LINK_BUTTON(instructions_link_)->label), 0, 0.5);
-  g_signal_connect(instructions_link_, "clicked",
-                   G_CALLBACK(OnButtonClickThunk), this);
-  gtk_util::SetButtonTriggersNavigation(instructions_link_);
-  // Until we switch to vector graphics, force the font size.
-  // 13.4px == 10pt @ 96dpi
-  gtk_util::ForceFontSizePixels(
-      GTK_CHROME_LINK_BUTTON(instructions_link_)->label, 13.4);
-  gtk_util::CenterWidgetInHBox(instructions_hbox_, instructions_link_,
-                               false, 6);
-  g_signal_connect(GTK_CHROME_LINK_BUTTON(instructions_link_)->label, "map",
-                   G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
-                   NULL);
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_->InitThemesFor(this);
-}
-
-void BookmarkBarInstructionsGtk::Observe(NotificationType type,
-                                         const NotificationSource& source,
-                                         const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED)
-    UpdateColors();
-}
-
-void BookmarkBarInstructionsGtk::OnButtonClick(GtkWidget* button) {
-  delegate_->ShowImportDialog();
-}
-
-void BookmarkBarInstructionsGtk::UpdateColors() {
-  gtk_chrome_link_button_set_use_gtk_theme(
-      GTK_CHROME_LINK_BUTTON(instructions_link_),
-      theme_provider_->UseGtkTheme());
-
-  GdkColor bookmark_color = theme_provider_->GetGdkColor(
-      BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-  if (theme_provider_->UseGtkTheme()) {
-    gtk_util::SetLabelColor(instructions_label_, NULL);
-    gtk_chrome_link_button_set_normal_color(
-        GTK_CHROME_LINK_BUTTON(instructions_link_), NULL);
-  } else {
-    gtk_util::SetLabelColor(instructions_label_, &bookmark_color);
-
-    // When using a non-standard, non-gtk theme, we make the link color match
-    // the bookmark text color. Otherwise, standard link blue can look very
-    // bad for some dark themes.
-    if (theme_provider_->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT) ==
-        BrowserThemeProvider::GetDefaultColor(
-            BrowserThemeProvider::COLOR_BOOKMARK_TEXT)) {
-      gtk_chrome_link_button_set_normal_color(
-          GTK_CHROME_LINK_BUTTON(instructions_link_), NULL);
-    } else {
-      gtk_chrome_link_button_set_normal_color(
-          GTK_CHROME_LINK_BUTTON(instructions_link_), &bookmark_color);
-    }
-  }
-}
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_CC_
diff --git a/chrome/browser/gtk/bookmark_bar_instructions_gtk.h b/chrome/browser/gtk/bookmark_bar_instructions_gtk.h
deleted file mode 100644
index b58e507..0000000
--- a/chrome/browser/gtk/bookmark_bar_instructions_gtk.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-typedef struct _GtkWidget GtkWidget;
-class GtkThemeProvider;
-class Profile;
-
-class BookmarkBarInstructionsGtk : public NotificationObserver {
- public:
-  // The delegate is notified once the user clicks on the link to import
-  // bookmarks.
-  class Delegate {
-   public:
-    virtual void ShowImportDialog() = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  explicit BookmarkBarInstructionsGtk(Delegate* delegate, Profile* profile);
-
-  // Get the native widget.
-  GtkWidget* widget() const { return instructions_hbox_; }
-
- private:
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  CHROMEGTK_CALLBACK_0(BookmarkBarInstructionsGtk, void, OnButtonClick);
-
-  // Sets the correct color for |instructions_label_| and |instructions_link_|.
-  void UpdateColors();
-
-  Delegate* delegate_;
-
-  Profile* profile_;
-
-  GtkThemeProvider* theme_provider_;
-
-  // HBox that holds the the label and link of bookmark bar import promotion.
-  GtkWidget* instructions_hbox_;
-  GtkWidget* instructions_label_;
-  GtkWidget* instructions_link_;
-
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(BookmarkBarInstructionsGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.cc b/chrome/browser/gtk/bookmark_bubble_gtk.cc
deleted file mode 100644
index ba0e198..0000000
--- a/chrome/browser/gtk/bookmark_bubble_gtk.cc
+++ /dev/null
@@ -1,346 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_bubble_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/basictypes.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/string16.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/bookmarks/recently_used_folders_combo_model.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_service.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// We basically have a singleton, since a bubble is sort of app-modal.  This
-// keeps track of the currently open bubble, or NULL if none is open.
-BookmarkBubbleGtk* g_bubble = NULL;
-
-// Padding between content and edge of info bubble.
-const int kContentBorder = 7;
-
-
-}  // namespace
-
-// static
-void BookmarkBubbleGtk::Show(GtkWidget* anchor,
-                             Profile* profile,
-                             const GURL& url,
-                             bool newly_bookmarked) {
-  DCHECK(!g_bubble);
-  g_bubble = new BookmarkBubbleGtk(anchor, profile, url, newly_bookmarked);
-}
-
-void BookmarkBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                          bool closed_by_escape) {
-  if (closed_by_escape) {
-    remove_bookmark_ = newly_bookmarked_;
-    apply_edits_ = false;
-  }
-
-  NotificationService::current()->Notify(
-      NotificationType::BOOKMARK_BUBBLE_HIDDEN,
-      Source<Profile>(profile_->GetOriginalProfile()),
-      NotificationService::NoDetails());
-}
-
-void BookmarkBubbleGtk::Observe(NotificationType type,
-                                const NotificationSource& source,
-                                const NotificationDetails& details) {
-  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
-
-  gtk_chrome_link_button_set_use_gtk_theme(
-      GTK_CHROME_LINK_BUTTON(remove_button_),
-      theme_provider_->UseGtkTheme());
-
-  if (theme_provider_->UseGtkTheme()) {
-    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
-         it != labels_.end(); ++it) {
-      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
-    }
-  } else {
-    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
-         it != labels_.end(); ++it) {
-      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-    }
-  }
-}
-
-BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWidget* anchor,
-                                     Profile* profile,
-                                     const GURL& url,
-                                     bool newly_bookmarked)
-    : url_(url),
-      profile_(profile),
-      theme_provider_(GtkThemeProvider::GetFrom(profile_)),
-      anchor_(anchor),
-      content_(NULL),
-      name_entry_(NULL),
-      folder_combo_(NULL),
-      bubble_(NULL),
-      factory_(this),
-      newly_bookmarked_(newly_bookmarked),
-      apply_edits_(true),
-      remove_bookmark_(false) {
-  GtkWidget* label = gtk_label_new(l10n_util::GetStringUTF8(
-      newly_bookmarked_ ? IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED :
-                          IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK).c_str());
-  labels_.push_back(label);
-  remove_button_ = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_REMOVE_BOOKMARK).c_str());
-  GtkWidget* edit_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_OPTIONS).c_str());
-  GtkWidget* close_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DONE).c_str());
-
-  // Our content is arranged in 3 rows.  |top| contains a left justified
-  // message, and a right justified remove link button.  |table| is the middle
-  // portion with the name entry and the folder combo.  |bottom| is the final
-  // row with a spacer, and the edit... and close buttons on the right.
-  GtkWidget* content = gtk_vbox_new(FALSE, 5);
-  gtk_container_set_border_width(GTK_CONTAINER(content), kContentBorder);
-  GtkWidget* top = gtk_hbox_new(FALSE, 0);
-
-  gtk_misc_set_alignment(GTK_MISC(label), 0, 1);
-  gtk_box_pack_start(GTK_BOX(top), label,
-                     TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(top), remove_button_,
-                     FALSE, FALSE, 0);
-
-  folder_combo_ = gtk_combo_box_new_text();
-  InitFolderComboModel();
-
-  // Create the edit entry for updating the bookmark name / title.
-  name_entry_ = gtk_entry_new();
-  gtk_entry_set_text(GTK_ENTRY(name_entry_), GetTitle().c_str());
-
-  // We use a table to allow the labels to line up with each other, along
-  // with the entry and folder combo lining up.
-  GtkWidget* table = gtk_util::CreateLabeledControlsGroup(
-      &labels_,
-      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_TITLE_TEXT).c_str(),
-      name_entry_,
-      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_FOLDER_TEXT).c_str(),
-      folder_combo_,
-      NULL);
-
-  GtkWidget* bottom = gtk_hbox_new(FALSE, 0);
-  // We want the buttons on the right, so just use an expanding label to fill
-  // all of the extra space on the right.
-  gtk_box_pack_start(GTK_BOX(bottom), gtk_label_new(""),
-                     TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(bottom), edit_button,
-                     FALSE, FALSE, 4);
-  gtk_box_pack_start(GTK_BOX(bottom), close_button,
-                     FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(content), top, TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(content), table, TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(content), bottom, TRUE, TRUE, 0);
-  // We want the focus to start on the entry, not on the remove button.
-  gtk_container_set_focus_child(GTK_CONTAINER(content), table);
-
-  InfoBubbleGtk::ArrowLocationGtk arrow_location =
-      base::i18n::IsRTL() ?
-      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
-      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
-  bubble_ = InfoBubbleGtk::Show(anchor_,
-                                NULL,
-                                content,
-                                arrow_location,
-                                true,  // match_system_theme
-                                true,  // grab_input
-                                theme_provider_,
-                                this);  // delegate
-  if (!bubble_) {
-    NOTREACHED();
-    return;
-  }
-
-  g_signal_connect(content, "destroy",
-                   G_CALLBACK(&OnDestroyThunk), this);
-  g_signal_connect(name_entry_, "activate",
-                   G_CALLBACK(&OnNameActivateThunk), this);
-  g_signal_connect(folder_combo_, "changed",
-                   G_CALLBACK(&OnFolderChangedThunk), this);
-  g_signal_connect(folder_combo_, "notify::popup-shown",
-                   G_CALLBACK(&OnFolderPopupShownThunk), this);
-  g_signal_connect(edit_button, "clicked",
-                   G_CALLBACK(&OnEditClickedThunk), this);
-  g_signal_connect(close_button, "clicked",
-                   G_CALLBACK(&OnCloseClickedThunk), this);
-  g_signal_connect(remove_button_, "clicked",
-                   G_CALLBACK(&OnRemoveClickedThunk), this);
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_->InitThemesFor(this);
-}
-
-BookmarkBubbleGtk::~BookmarkBubbleGtk() {
-  DCHECK(!content_);  // |content_| should have already been destroyed.
-
-  DCHECK(g_bubble);
-  g_bubble = NULL;
-
-  if (apply_edits_) {
-    ApplyEdits();
-  } else if (remove_bookmark_) {
-    BookmarkModel* model = profile_->GetBookmarkModel();
-    const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
-    if (node)
-      model->Remove(node->GetParent(), node->GetParent()->IndexOfChild(node));
-  }
-}
-
-void BookmarkBubbleGtk::OnDestroy(GtkWidget* widget) {
-  // We are self deleting, we have a destroy signal setup to catch when we
-  // destroyed (via the InfoBubble being destroyed), and delete ourself.
-  content_ = NULL;  // We are being destroyed.
-  delete this;
-}
-
-void BookmarkBubbleGtk::OnNameActivate(GtkWidget* widget) {
-  bubble_->Close();
-}
-
-void BookmarkBubbleGtk::OnFolderChanged(GtkWidget* widget) {
-  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(folder_combo_));
-  if (index == folder_combo_model_->GetItemCount() - 1) {
-    UserMetrics::RecordAction(
-        UserMetricsAction("BookmarkBubble_EditFromCombobox"), profile_);
-    // GTK doesn't handle having the combo box destroyed from the changed
-    // signal.  Since showing the editor also closes the bubble, delay this
-    // so that GTK can unwind.  Specifically gtk_menu_shell_button_release
-    // will run, and we need to keep the combo box alive until then.
-    MessageLoop::current()->PostTask(FROM_HERE,
-        factory_.NewRunnableMethod(&BookmarkBubbleGtk::ShowEditor));
-  }
-}
-
-void BookmarkBubbleGtk::OnFolderPopupShown(GtkWidget* widget,
-                                           GParamSpec* property) {
-  // GtkComboBox grabs the keyboard and pointer when it displays its popup,
-  // which steals the grabs that InfoBubbleGtk had installed.  When the popup is
-  // hidden, we notify InfoBubbleGtk so it can try to reacquire the grabs
-  // (otherwise, GTK won't activate our widgets when the user clicks in them).
-  gboolean popup_shown = FALSE;
-  g_object_get(G_OBJECT(folder_combo_), "popup-shown", &popup_shown, NULL);
-  if (!popup_shown)
-    bubble_->HandlePointerAndKeyboardUngrabbedByContent();
-}
-
-void BookmarkBubbleGtk::OnEditClicked(GtkWidget* widget) {
-  UserMetrics::RecordAction(UserMetricsAction("BookmarkBubble_Edit"),
-                            profile_);
-  ShowEditor();
-}
-
-void BookmarkBubbleGtk::OnCloseClicked(GtkWidget* widget) {
-  bubble_->Close();
-}
-
-void BookmarkBubbleGtk::OnRemoveClicked(GtkWidget* widget) {
-  UserMetrics::RecordAction(UserMetricsAction("BookmarkBubble_Unstar"),
-                            profile_);
-
-  apply_edits_ = false;
-  remove_bookmark_ = true;
-  bubble_->Close();
-}
-
-void BookmarkBubbleGtk::ApplyEdits() {
-  // Set this to make sure we don't attempt to apply edits again.
-  apply_edits_ = false;
-
-  BookmarkModel* model = profile_->GetBookmarkModel();
-  const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
-  if (node) {
-    const string16 new_title(
-        UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(name_entry_))));
-
-    if (new_title != node->GetTitle()) {
-      model->SetTitle(node, new_title);
-      UserMetrics::RecordAction(
-          UserMetricsAction("BookmarkBubble_ChangeTitleInBubble"),
-          profile_);
-    }
-
-    int index = gtk_combo_box_get_active(GTK_COMBO_BOX(folder_combo_));
-
-    // Last index means 'Choose another folder...'
-    if (index < folder_combo_model_->GetItemCount() - 1) {
-      const BookmarkNode* new_parent = folder_combo_model_->GetNodeAt(index);
-      if (new_parent != node->GetParent()) {
-        UserMetrics::RecordAction(
-            UserMetricsAction("BookmarkBubble_ChangeParent"), profile_);
-        model->Move(node, new_parent, new_parent->GetChildCount());
-      }
-    }
-  }
-}
-
-std::string BookmarkBubbleGtk::GetTitle() {
-  BookmarkModel* bookmark_model= profile_->GetBookmarkModel();
-  const BookmarkNode* node =
-      bookmark_model->GetMostRecentlyAddedNodeForURL(url_);
-  if (!node) {
-    NOTREACHED();
-    return std::string();
-  }
-
-  return UTF16ToUTF8(node->GetTitle());
-}
-
-void BookmarkBubbleGtk::ShowEditor() {
-  const BookmarkNode* node =
-      profile_->GetBookmarkModel()->GetMostRecentlyAddedNodeForURL(url_);
-
-  // Commit any edits now.
-  ApplyEdits();
-
-  // Closing might delete us, so we'll cache what we need on the stack.
-  Profile* profile = profile_;
-  GtkWindow* toplevel = GTK_WINDOW(gtk_widget_get_toplevel(anchor_));
-
-  // Close the bubble, deleting the C++ objects, etc.
-  bubble_->Close();
-
-  if (node) {
-    BookmarkEditor::Show(toplevel, profile, NULL,
-                         BookmarkEditor::EditDetails(node),
-                         BookmarkEditor::SHOW_TREE);
-  }
-}
-
-void BookmarkBubbleGtk::InitFolderComboModel() {
-  folder_combo_model_.reset(new RecentlyUsedFoldersComboModel(
-      profile_->GetBookmarkModel(),
-      profile_->GetBookmarkModel()->GetMostRecentlyAddedNodeForURL(url_)));
-
-  // We always have nodes + 1 entries in the combo.  The last entry will be
-  // the 'Select another folder...' entry that opens the bookmark editor.
-  for (int i = 0; i < folder_combo_model_->GetItemCount(); ++i) {
-    gtk_combo_box_append_text(GTK_COMBO_BOX(folder_combo_),
-        UTF16ToUTF8(folder_combo_model_->GetItemAt(i)).c_str());
-  }
-
-  gtk_combo_box_set_active(GTK_COMBO_BOX(folder_combo_),
-                           folder_combo_model_->node_parent_index());
-}
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.h b/chrome/browser/gtk/bookmark_bubble_gtk.h
deleted file mode 100644
index 6c7de88..0000000
--- a/chrome/browser/gtk/bookmark_bubble_gtk.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This is the GTK implementation of the bookmark bubble, the dialog box
-// presented to create or edit a bookmark.  There can only ever be a single
-// bubble open, so the class presents only static methods, and handles the
-// singleton behavior for you.  It also handles the object and widget
-// lifetimes, destroying everything and possibly committing any changes when
-// the bubble is closed.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_BUBBLE_GTK_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_BUBBLE_GTK_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "googleurl/src/gurl.h"
-
-class BookmarkNode;
-class Profile;
-class RecentlyUsedFoldersComboModel;
-
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GParamSpec GParamSpec;
-
-class BookmarkBubbleGtk : public InfoBubbleGtkDelegate,
-                          public NotificationObserver {
- public:
-  // Shows the bookmark bubble, pointing at |anchor_widget|.
-  static void Show(GtkWidget* anchor_widget,
-                   Profile* profile,
-                   const GURL& url,
-                   bool newly_bookmarked);
-
-  // Implements the InfoBubbleGtkDelegate.  We are notified when the bubble
-  // is about to be closed, so we have a chance to save any state / input in
-  // our widgets before they are destroyed.
-  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                 bool closed_by_escape);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  BookmarkBubbleGtk(GtkWidget* anchor,
-                    Profile* profile,
-                    const GURL& url,
-                    bool newly_bookmarked);
-  ~BookmarkBubbleGtk();
-
-  // Notified when |content_| is destroyed so we can delete our instance.
-  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnDestroy);
-  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnNameActivate);
-  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnFolderChanged);
-  CHROMEGTK_CALLBACK_1(BookmarkBubbleGtk, void, OnFolderPopupShown,
-                       GParamSpec*);
-  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnEditClicked);
-  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnCloseClicked);
-  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnRemoveClicked);
-
-  // Update the bookmark with any edits that have been made.
-  void ApplyEdits();
-
-  // Open the bookmark editor for the current url and close the bubble.
-  void ShowEditor();
-
-  // Return the UTF8 encoded title for the current |url_|.
-  std::string GetTitle();
-
-  void InitFolderComboModel();
-
-  // The URL of the bookmark.
-  GURL url_;
-  // Our current profile (used to access the bookmark system).
-  Profile* profile_;
-
-  // Provides colors and stuff.
-  GtkThemeProvider* theme_provider_;
-
-  // The widget relative to which we are positioned.
-  GtkWidget* anchor_;
-
-  // We let the InfoBubble own our content, and then we delete ourself
-  // when the widget is destroyed (when the InfoBubble is destroyed).
-  GtkWidget* content_;
-
-  // The button that removes the bookmark.
-  GtkWidget* remove_button_;
-
-  // The various labels in the interface. We keep track of them for theme
-  // changes.
-  std::vector<GtkWidget*> labels_;
-
-  // The GtkEntry for editing the bookmark name / title.
-  GtkWidget* name_entry_;
-
-  // The combo box for selecting the bookmark folder.
-  GtkWidget* folder_combo_;
-  scoped_ptr<RecentlyUsedFoldersComboModel> folder_combo_model_;
-
-  InfoBubbleGtk* bubble_;
-
-  // We need to push some things on the back of the message loop, so we have
-  // a factory attached to our instance to manage task lifetimes.
-  ScopedRunnableMethodFactory<BookmarkBubbleGtk> factory_;
-
-  // Whether the bubble is creating or editing an existing bookmark.
-  bool newly_bookmarked_;
-  // When closing the window, whether we should update or remove the bookmark.
-  bool apply_edits_;
-  bool remove_bookmark_;
-
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(BookmarkBubbleGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_editor_gtk.cc b/chrome/browser/gtk/bookmark_editor_gtk.cc
deleted file mode 100644
index 74558e1..0000000
--- a/chrome/browser/gtk/bookmark_editor_gtk.cc
+++ /dev/null
@@ -1,589 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_editor_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "app/menus/simple_menu_model.h"
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/gtk/bookmark_tree_model.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/history/history.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/profiles/profile.h"
-#include "gfx/gtk_util.h"
-#include "gfx/point.h"
-#include "googleurl/src/gurl.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-#if defined(TOOLKIT_VIEWS)
-#include "views/controls/menu/menu_2.h"
-#else
-#include "chrome/browser/gtk/menu_gtk.h"
-#endif
-
-namespace {
-
-// Background color of text field when URL is invalid.
-const GdkColor kErrorColor = GDK_COLOR_RGB(0xFF, 0xBC, 0xBC);
-
-// Preferred initial dimensions, in pixels, of the folder tree.
-static const int kTreeWidth = 300;
-static const int kTreeHeight = 150;
-
-}  // namespace
-
-class BookmarkEditorGtk::ContextMenuController
-    : public menus::SimpleMenuModel::Delegate {
- public:
-  explicit ContextMenuController(BookmarkEditorGtk* editor)
-      : editor_(editor),
-        running_menu_for_root_(false) {
-    menu_model_.reset(new menus::SimpleMenuModel(this));
-    menu_model_->AddItemWithStringId(COMMAND_EDIT, IDS_EDIT);
-    menu_model_->AddItemWithStringId(
-        COMMAND_NEW_FOLDER,
-        IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM);
-#if defined(TOOLKIT_VIEWS)
-    menu_.reset(new views::Menu2(menu_model_.get()));
-#else
-    menu_.reset(new MenuGtk(NULL, menu_model_.get()));
-#endif
-  }
-  virtual ~ContextMenuController() {}
-
-  void RunMenu(const gfx::Point& point) {
-    const BookmarkNode* selected_node = GetSelectedNode();
-    if (selected_node)
-      running_menu_for_root_ = selected_node->GetParent()->IsRoot();
-#if defined(TOOLKIT_VIEWS)
-    menu_->RunContextMenuAt(point);
-#else
-    menu_->PopupAsContextAt(gtk_get_current_event_time(), point);
-#endif
-  }
-
-  void Cancel() {
-    editor_ = NULL;
-#if defined(TOOLKIT_VIEWS)
-    menu_->CancelMenu();
-#else
-    menu_->Cancel();
-#endif
-  }
-
- private:
-  enum ContextMenuCommand {
-    COMMAND_EDIT,
-    COMMAND_NEW_FOLDER
-  };
-
-  // Overridden from menus::SimpleMenuModel::Delegate:
-  virtual bool IsCommandIdEnabled(int command_id) const {
-    return !(command_id == COMMAND_EDIT && running_menu_for_root_) &&
-        (editor_ != NULL);
-  }
-
-  virtual bool IsCommandIdChecked(int command_id) const {
-    return false;
-  }
-
-  virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator) {
-    return false;
-  }
-
-  virtual void ExecuteCommand(int command_id) {
-    if (!editor_)
-      return;
-
-    switch (command_id) {
-      case COMMAND_EDIT: {
-        GtkTreeIter iter;
-        if (!gtk_tree_selection_get_selected(editor_->tree_selection_,
-                                             NULL,
-                                             &iter)) {
-          return;
-        }
-
-        GtkTreePath* path = gtk_tree_model_get_path(
-            GTK_TREE_MODEL(editor_->tree_store_), &iter);
-        gtk_tree_view_expand_to_path(GTK_TREE_VIEW(editor_->tree_view_), path);
-
-        // Make the folder name editable.
-        gtk_tree_view_set_cursor(GTK_TREE_VIEW(editor_->tree_view_), path,
-            gtk_tree_view_get_column(GTK_TREE_VIEW(editor_->tree_view_), 0),
-            TRUE);
-
-        gtk_tree_path_free(path);
-        break;
-      }
-      case COMMAND_NEW_FOLDER:
-        editor_->NewFolder();
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
-  }
-
-  int64 GetRowIdAt(GtkTreeModel* model, GtkTreeIter* iter) {
-    GValue value = { 0, };
-    gtk_tree_model_get_value(model, iter, bookmark_utils::ITEM_ID, &value);
-    int64 id = g_value_get_int64(&value);
-    g_value_unset(&value);
-    return id;
-  }
-
-  const BookmarkNode* GetNodeAt(GtkTreeModel* model, GtkTreeIter* iter) {
-    int64 id = GetRowIdAt(model, iter);
-    return (id > 0) ? editor_->bb_model_->GetNodeByID(id) : NULL;
-  }
-
-  const BookmarkNode* GetSelectedNode() {
-    GtkTreeModel* model;
-    GtkTreeIter iter;
-    if (!gtk_tree_selection_get_selected(editor_->tree_selection_,
-                                         &model,
-                                         &iter)) {
-      return NULL;
-    }
-
-    return GetNodeAt(model, &iter);
-  }
-
-  // The model and view for the right click context menu.
-  scoped_ptr<menus::SimpleMenuModel> menu_model_;
-#if defined(TOOLKIT_VIEWS)
-  scoped_ptr<views::Menu2> menu_;
-#else
-  scoped_ptr<MenuGtk> menu_;
-#endif
-
-  // The context menu was brought up for. Set to NULL when the menu is canceled.
-  BookmarkEditorGtk* editor_;
-
-  // If true, we're running the menu for the bookmark bar or other bookmarks
-  // nodes.
-  bool running_menu_for_root_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
-};
-
-// static
-void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
-                          Profile* profile,
-                          const BookmarkNode* parent,
-                          const EditDetails& details,
-                          Configuration configuration) {
-  DCHECK(profile);
-  BookmarkEditorGtk* editor =
-      new BookmarkEditorGtk(parent_hwnd, profile, parent, details,
-                            configuration);
-  editor->Show();
-}
-
-BookmarkEditorGtk::BookmarkEditorGtk(
-    GtkWindow* window,
-    Profile* profile,
-    const BookmarkNode* parent,
-    const EditDetails& details,
-    BookmarkEditor::Configuration configuration)
-    : profile_(profile),
-      dialog_(NULL),
-      parent_(parent),
-      details_(details),
-      running_menu_for_root_(false),
-      show_tree_(configuration == SHOW_TREE) {
-  DCHECK(profile);
-  Init(window);
-}
-
-BookmarkEditorGtk::~BookmarkEditorGtk() {
-  // The tree model is deleted before the view. Reset the model otherwise the
-  // tree will reference a deleted model.
-
-  bb_model_->RemoveObserver(this);
-}
-
-void BookmarkEditorGtk::Init(GtkWindow* parent_window) {
-  bb_model_ = profile_->GetBookmarkModel();
-  DCHECK(bb_model_);
-  bb_model_->AddObserver(this);
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_TITLE).c_str(),
-      parent_window,
-      GTK_DIALOG_MODAL,
-      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
-      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-      NULL);
-  gtk_dialog_set_has_separator(GTK_DIALOG(dialog_), FALSE);
-
-  if (show_tree_) {
-    GtkWidget* action_area = GTK_DIALOG(dialog_)->action_area;
-    new_folder_button_ = gtk_button_new_with_label(
-        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_BUTTON).c_str());
-    g_signal_connect(new_folder_button_, "clicked",
-                     G_CALLBACK(OnNewFolderClickedThunk), this);
-    gtk_container_add(GTK_CONTAINER(action_area), new_folder_button_);
-    gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(action_area),
-                                       new_folder_button_, TRUE);
-  }
-
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
-
-  // The GTK dialog content area layout (overview)
-  //
-  // +- GtkVBox |vbox| ----------------------------------------------+
-  // |+- GtkTable |table| ------------------------------------------+|
-  // ||+- GtkLabel ------+ +- GtkEntry |name_entry_| --------------+||
-  // |||                 | |                                       |||
-  // ||+-----------------+ +---------------------------------------+||
-  // ||+- GtkLabel ------+ +- GtkEntry |url_entry_| ---------------+|| *
-  // |||                 | |                                       |||
-  // ||+-----------------+ +---------------------------------------+||
-  // |+-------------------------------------------------------------+|
-  // |+- GtkScrollWindow |scroll_window| ---------------------------+|
-  // ||+- GtkTreeView |tree_view_| --------------------------------+||
-  // |||+- GtkTreeViewColumn |name_column| -----------------------+|||
-  // ||||                                                         ||||
-  // ||||                                                         ||||
-  // ||||                                                         ||||
-  // ||||                                                         ||||
-  // |||+---------------------------------------------------------+|||
-  // ||+-----------------------------------------------------------+||
-  // |+-------------------------------------------------------------+|
-  // +---------------------------------------------------------------+
-  //
-  // * The url and corresponding label are not shown if creating a new folder.
-  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, 12);
-
-  name_entry_ = gtk_entry_new();
-  std::string title;
-  if (details_.type == EditDetails::EXISTING_NODE) {
-    title = UTF16ToUTF8(details_.existing_node->GetTitle());
-  } else if (details_.type == EditDetails::NEW_FOLDER) {
-    title = l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME);
-  }
-  gtk_entry_set_text(GTK_ENTRY(name_entry_), title.c_str());
-  g_signal_connect(name_entry_, "changed",
-                   G_CALLBACK(OnEntryChangedThunk), this);
-  gtk_entry_set_activates_default(GTK_ENTRY(name_entry_), TRUE);
-
-  GtkWidget* table;
-  if (details_.type != EditDetails::NEW_FOLDER) {
-    url_entry_ = gtk_entry_new();
-    std::string url_spec;
-    if (details_.type == EditDetails::EXISTING_NODE)
-      url_spec = details_.existing_node->GetURL().spec();
-    gtk_entry_set_text(GTK_ENTRY(url_entry_), url_spec.c_str());
-    g_signal_connect(url_entry_, "changed",
-                     G_CALLBACK(OnEntryChangedThunk), this);
-    gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
-    table = gtk_util::CreateLabeledControlsGroup(NULL,
-        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str(),
-        name_entry_,
-        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_URL_LABEL).c_str(),
-        url_entry_,
-        NULL);
-
-  } else {
-    url_entry_ = NULL;
-    table = gtk_util::CreateLabeledControlsGroup(NULL,
-        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str(),
-        name_entry_,
-        NULL);
-  }
-
-  gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
-
-  if (show_tree_) {
-    GtkTreeIter selected_iter;
-    int64 selected_id = 0;
-    if (details_.type == EditDetails::EXISTING_NODE)
-      selected_id = details_.existing_node->GetParent()->id();
-    else if (parent_)
-      selected_id = parent_->id();
-    tree_store_ = bookmark_utils::MakeFolderTreeStore();
-    bookmark_utils::AddToTreeStore(bb_model_, selected_id, tree_store_,
-                                   &selected_iter);
-    tree_view_ = bookmark_utils::MakeTreeViewForStore(tree_store_);
-    gtk_widget_set_size_request(tree_view_, kTreeWidth, kTreeHeight);
-    tree_selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_));
-    g_signal_connect(tree_view_, "button-press-event",
-                     G_CALLBACK(OnTreeViewButtonPressEventThunk), this);
-
-    GtkTreePath* path = NULL;
-    if (selected_id) {
-      path = gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store_),
-                                     &selected_iter);
-    } else {
-      // We don't have a selected parent (Probably because we're making a new
-      // bookmark). Select the first item in the list.
-      path = gtk_tree_path_new_from_string("0");
-    }
-
-    gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_view_), path);
-    gtk_tree_selection_select_path(tree_selection_, path);
-    gtk_tree_path_free(path);
-
-    GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                    GTK_POLICY_NEVER,
-                                   GTK_POLICY_AUTOMATIC);
-    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                        GTK_SHADOW_ETCHED_IN);
-    gtk_container_add(GTK_CONTAINER(scroll_window), tree_view_);
-
-    gtk_box_pack_start(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 0);
-
-    g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_)),
-                     "changed", G_CALLBACK(OnSelectionChangedThunk), this);
-  }
-
-  gtk_box_pack_start(GTK_BOX(content_area), vbox, TRUE, TRUE, 0);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnResponseThunk), this);
-  g_signal_connect(dialog_, "delete-event",
-                   G_CALLBACK(OnWindowDeleteEventThunk), this);
-  g_signal_connect(dialog_, "destroy",
-                   G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-void BookmarkEditorGtk::Show() {
-  // Manually call our OnEntryChanged handler to set the initial state.
-  OnEntryChanged(NULL);
-
-  gtk_util::ShowDialog(dialog_);
-}
-
-void BookmarkEditorGtk::Close() {
-  // Under the model that we've inherited from Windows, dialogs can receive
-  // more than one Close() call inside the current message loop event.
-  if (dialog_) {
-    gtk_widget_destroy(dialog_);
-    dialog_ = NULL;
-  }
-}
-
-void BookmarkEditorGtk::BookmarkNodeMoved(BookmarkModel* model,
-                                          const BookmarkNode* old_parent,
-                                          int old_index,
-                                          const BookmarkNode* new_parent,
-                                          int new_index) {
-  Reset();
-}
-
-void BookmarkEditorGtk::BookmarkNodeAdded(BookmarkModel* model,
-                                          const BookmarkNode* parent,
-                                          int index) {
-  Reset();
-}
-
-void BookmarkEditorGtk::BookmarkNodeRemoved(BookmarkModel* model,
-                                            const BookmarkNode* parent,
-                                            int index,
-                                            const BookmarkNode* node) {
-  if ((details_.type == EditDetails::EXISTING_NODE &&
-       details_.existing_node->HasAncestor(node)) ||
-      (parent_ && parent_->HasAncestor(node))) {
-    // The node, or its parent was removed. Close the dialog.
-    Close();
-  } else {
-    Reset();
-  }
-}
-
-void BookmarkEditorGtk::BookmarkNodeChildrenReordered(
-    BookmarkModel* model, const BookmarkNode* node) {
-  Reset();
-}
-
-void BookmarkEditorGtk::Reset() {
-  // TODO(erg): The windows implementation tries to be smart. For now, just
-  // close the window.
-  Close();
-}
-
-GURL BookmarkEditorGtk::GetInputURL() const {
-  if (!url_entry_)
-    return GURL();  // Happens when we're editing a folder.
-  return URLFixerUpper::FixupURL(gtk_entry_get_text(GTK_ENTRY(url_entry_)),
-                                 std::string());
-}
-
-string16 BookmarkEditorGtk::GetInputTitle() const {
-  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(name_entry_)));
-}
-
-void BookmarkEditorGtk::ApplyEdits() {
-  DCHECK(bb_model_->IsLoaded());
-
-  GtkTreeIter currently_selected_iter;
-  if (show_tree_) {
-    if (!gtk_tree_selection_get_selected(tree_selection_, NULL,
-                                         &currently_selected_iter)) {
-      ApplyEdits(NULL);
-      return;
-    }
-  }
-
-  ApplyEdits(&currently_selected_iter);
-}
-
-void BookmarkEditorGtk::ApplyEdits(GtkTreeIter* selected_parent) {
-  // We're going to apply edits to the bookmark bar model, which will call us
-  // back. Normally when a structural edit occurs we reset the tree model.
-  // We don't want to do that here, so we remove ourselves as an observer.
-  bb_model_->RemoveObserver(this);
-
-  GURL new_url(GetInputURL());
-  string16 new_title(GetInputTitle());
-
-  if (!show_tree_ || !selected_parent) {
-    bookmark_utils::ApplyEditsWithNoGroupChange(
-        bb_model_, parent_, details_, new_title, new_url);
-    return;
-  }
-
-  // Create the new groups and update the titles.
-  const BookmarkNode* new_parent =
-      bookmark_utils::CommitTreeStoreDifferencesBetween(
-      bb_model_, tree_store_, selected_parent);
-
-  if (!new_parent) {
-    // Bookmarks must be parented.
-    NOTREACHED();
-    return;
-  }
-
-  bookmark_utils::ApplyEditsWithPossibleGroupChange(
-      bb_model_, new_parent, details_, new_title, new_url);
-}
-
-void BookmarkEditorGtk::AddNewGroup(GtkTreeIter* parent, GtkTreeIter* child) {
-  gtk_tree_store_append(tree_store_, child, parent);
-  gtk_tree_store_set(
-      tree_store_, child,
-      bookmark_utils::FOLDER_ICON, GtkThemeProvider::GetFolderIcon(true),
-      bookmark_utils::FOLDER_NAME,
-          l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME).c_str(),
-      bookmark_utils::ITEM_ID, static_cast<int64>(0),
-      bookmark_utils::IS_EDITABLE, TRUE,
-      -1);
-}
-
-void BookmarkEditorGtk::OnSelectionChanged(GtkWidget* selection) {
-  if (!gtk_tree_selection_get_selected(tree_selection_, NULL, NULL))
-    gtk_widget_set_sensitive(new_folder_button_, FALSE);
-  else
-    gtk_widget_set_sensitive(new_folder_button_, TRUE);
-}
-
-void BookmarkEditorGtk::OnResponse(GtkWidget* dialog, int response_id) {
-  if (response_id == GTK_RESPONSE_ACCEPT)
-    ApplyEdits();
-
-  Close();
-}
-
-gboolean BookmarkEditorGtk::OnWindowDeleteEvent(GtkWidget* widget,
-                                                GdkEvent* event) {
-  Close();
-
-  // Return true to prevent the gtk dialog from being destroyed. Close will
-  // destroy it for us and the default gtk_dialog_delete_event_handler() will
-  // force the destruction without us being able to stop it.
-  return TRUE;
-}
-
-void BookmarkEditorGtk::OnWindowDestroy(GtkWidget* widget) {
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void BookmarkEditorGtk::OnEntryChanged(GtkWidget* entry) {
-  gboolean can_close = TRUE;
-  if (details_.type == EditDetails::NEW_FOLDER) {
-    if (GetInputTitle().empty()) {
-      gtk_widget_modify_base(name_entry_, GTK_STATE_NORMAL,
-                             &kErrorColor);
-      can_close = FALSE;
-    } else {
-      gtk_widget_modify_base(name_entry_, GTK_STATE_NORMAL, NULL);
-    }
-  } else {
-    GURL url(GetInputURL());
-    if (!url.is_valid()) {
-      gtk_widget_modify_base(url_entry_, GTK_STATE_NORMAL,
-                             &kErrorColor);
-      can_close = FALSE;
-    } else {
-      gtk_widget_modify_base(url_entry_, GTK_STATE_NORMAL, NULL);
-    }
-  }
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
-                                    GTK_RESPONSE_ACCEPT, can_close);
-}
-
-void BookmarkEditorGtk::OnNewFolderClicked(GtkWidget* button) {
-  NewFolder();
-}
-
-gboolean BookmarkEditorGtk::OnTreeViewButtonPressEvent(GtkWidget* widget,
-                                                       GdkEventButton* event) {
-  if (event->button == 3) {
-    gfx::Point pt(event->x_root, event->y_root);
-    ShowContextMenu(pt);
-  }
-
-  return FALSE;
-}
-
-void BookmarkEditorGtk::ShowContextMenu(const gfx::Point& point) {
-  if (!menu_controller_.get())
-    menu_controller_.reset(new ContextMenuController(this));
-
-  menu_controller_->RunMenu(point);
-}
-
-void BookmarkEditorGtk::NewFolder() {
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(tree_selection_,
-                                       NULL,
-                                       &iter)) {
-    NOTREACHED() << "Something should always be selected if New Folder " <<
-                    "is clicked";
-    return;
-  }
-
-  GtkTreeIter new_item_iter;
-  AddNewGroup(&iter, &new_item_iter);
-
-  GtkTreePath* path = gtk_tree_model_get_path(
-      GTK_TREE_MODEL(tree_store_), &new_item_iter);
-  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_view_), path);
-
-  // Make the folder name editable.
-  gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view_), path,
-      gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view_), 0),
-      TRUE);
-
-  gtk_tree_path_free(path);
-}
diff --git a/chrome/browser/gtk/bookmark_editor_gtk.h b/chrome/browser/gtk/bookmark_editor_gtk.h
deleted file mode 100644
index 7295689..0000000
--- a/chrome/browser/gtk/bookmark_editor_gtk.h
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_EDITOR_GTK_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_EDITOR_GTK_H_
-#pragma once
-
-#include "app/gtk_integers.h"
-#include "app/gtk_signal.h"
-#include "base/gtest_prod_util.h"
-#include "base/scoped_ptr.h"
-#include "base/string16.h"
-#include "chrome/browser/bookmarks/bookmark_editor.h"
-#include "chrome/browser/bookmarks/bookmark_model_observer.h"
-
-class GURL;
-
-typedef union  _GdkEvent GdkEvent;
-typedef struct _GdkEventButton GdkEventButton;
-typedef struct _GtkTreeIter GtkTreeIter;
-typedef struct _GtkTreeSelection GtkTreeSelection;
-typedef struct _GtkTreeStore GtkTreeStore;
-typedef struct _GtkWidget GtkWidget;
-
-namespace gfx {
-class Point;
-}  // namespace gfx
-
-// GTK version of the bookmark editor dialog.
-class BookmarkEditorGtk : public BookmarkEditor,
-                          public BookmarkModelObserver {
- public:
-  BookmarkEditorGtk(GtkWindow* window,
-                    Profile* profile,
-                    const BookmarkNode* parent,
-                    const EditDetails& details,
-                    BookmarkEditor::Configuration configuration);
-
-  virtual ~BookmarkEditorGtk();
-
-  void Show();
-  void Close();
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParent);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParentAndURL);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLToExistingURL);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditTitleKeepsPosition);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditURLKeepsPosition);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ModelsMatch);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, MoveToNewParent);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, NewURL);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLNoTree);
-  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeTitleNoTree);
-
-  class ContextMenuController;
-  friend class ContextMenuController;
-
-  void Init(GtkWindow* parent_window);
-
-  // BookmarkModel observer methods. Any structural change results in
-  // resetting the tree model.
-  virtual void Loaded(BookmarkModel* model) { }
-  virtual void BookmarkNodeMoved(BookmarkModel* model,
-                                 const BookmarkNode* old_parent,
-                                 int old_index,
-                                 const BookmarkNode* new_parent,
-                                 int new_index);
-  virtual void BookmarkNodeAdded(BookmarkModel* model,
-                                 const BookmarkNode* parent,
-                                 int index);
-  virtual void BookmarkNodeRemoved(BookmarkModel* model,
-                                   const BookmarkNode* parent,
-                                   int old_index,
-                                   const BookmarkNode* node);
-  virtual void BookmarkNodeChanged(BookmarkModel* model,
-                                   const BookmarkNode* node) {}
-  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
-                                             const BookmarkNode* node);
-  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
-                                         const BookmarkNode* node) {}
-
-  // Resets the model of the tree and updates the various buttons appropriately.
-  void Reset();
-
-  // Returns the current url the user has input.
-  GURL GetInputURL() const;
-
-  // Returns the title the user has input.
-  string16 GetInputTitle() const;
-
-  // Invokes ApplyEdits with the selected node.
-  //
-  // TODO(erg): This was copied from the windows version. Both should be
-  // cleaned up so that we don't overload ApplyEdits.
-  void ApplyEdits();
-
-  // Applies the edits done by the user. |selected_parent| gives the parent of
-  // the URL being edited.
-  void ApplyEdits(GtkTreeIter* selected_parent);
-
-  // Adds a new group parented on |parent| and sets |child| to point to this
-  // new group.
-  void AddNewGroup(GtkTreeIter* parent, GtkTreeIter* child);
-
-  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnSelectionChanged);
-  CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, void, OnResponse, int);
-  CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, gboolean, OnWindowDeleteEvent,
-                       GdkEvent*);
-
-  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnWindowDestroy);
-  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnEntryChanged);
-
-  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnNewFolderClicked);
-
-  CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, gboolean, OnTreeViewButtonPressEvent,
-                       GdkEventButton*);
-
-  void ShowContextMenu(const gfx::Point& point);
-
-  void NewFolder();
-
-  // Profile the entry is from.
-  Profile* profile_;
-
-  // The dialog to display on screen.
-  GtkWidget* dialog_;
-  GtkWidget* name_entry_;
-  GtkWidget* url_entry_;  // This is NULL if IsEditingFolder.
-  GtkWidget* tree_view_;
-  GtkWidget* new_folder_button_;
-
-  // Helper object that manages the currently selected item in |tree_view_|.
-  GtkTreeSelection* tree_selection_;
-
-  // Our local copy of the bookmark data that we make from the BookmarkModel
-  // that we can modify as much as we want and still discard when the user
-  // clicks Cancel.
-  GtkTreeStore* tree_store_;
-
-  // TODO(erg): BookmarkEditorView has an EditorTreeModel object here; convert
-  // that into a GObject that implements the interface GtkTreeModel.
-
-  // Initial parent to select. Is only used if node_ is NULL.
-  const BookmarkNode* parent_;
-
-  // Details about the node we're editing.
-  const EditDetails details_;
-
-  // Mode used to create nodes from.
-  BookmarkModel* bb_model_;
-
-  // If true, we're running the menu for the bookmark bar or other bookmarks
-  // nodes.
-  bool running_menu_for_root_;
-
-  // Is the tree shown?
-  bool show_tree_;
-
-  // The context menu controller.
-  scoped_ptr<ContextMenuController> menu_controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(BookmarkEditorGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_EDITOR_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_editor_gtk_unittest.cc b/chrome/browser/gtk/bookmark_editor_gtk_unittest.cc
deleted file mode 100644
index 9a8c651..0000000
--- a/chrome/browser/gtk/bookmark_editor_gtk_unittest.cc
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gtk/bookmark_editor_gtk.h"
-#include "chrome/browser/gtk/bookmark_tree_model.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Time;
-using base::TimeDelta;
-using bookmark_utils::GetTitleFromTreeIter;
-
-// Base class for bookmark editor tests. This class is a copy from
-// bookmark_editor_view_unittest.cc, and all the tests in this file are
-// GTK-ifications of the corresponding views tests. Testing here is really
-// important because on Linux, we make round trip copies from chrome's
-// BookmarkModel class to GTK's native GtkTreeStore.
-class BookmarkEditorGtkTest : public testing::Test {
- public:
-  BookmarkEditorGtkTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
-        model_(NULL) {
-  }
-
-  virtual void SetUp() {
-    profile_.reset(new TestingProfile());
-    profile_->set_has_history_service(true);
-    profile_->CreateBookmarkModel(true);
-    profile_->BlockUntilBookmarkModelLoaded();
-
-    model_ = profile_->GetBookmarkModel();
-
-    AddTestData();
-  }
-
-  virtual void TearDown() {
-  }
-
- protected:
-  MessageLoopForUI message_loop_;
-  BrowserThread ui_thread_;
-  BrowserThread file_thread_;
-  BookmarkModel* model_;
-  scoped_ptr<TestingProfile> profile_;
-
-  std::string base_path() const { return "file:///c:/tmp/"; }
-
-  const BookmarkNode* GetNode(const std::string& name) {
-    return model_->GetMostRecentlyAddedNodeForURL(GURL(base_path() + name));
-  }
-
- private:
-  // Creates the following structure:
-  // bookmark bar node
-  //   a
-  //   F1
-  //    f1a
-  //    F11
-  //     f11a
-  //   F2
-  // other node
-  //   oa
-  //   OF1
-  //     of1a
-  void AddTestData() {
-    std::string test_base = base_path();
-
-    model_->AddURL(model_->GetBookmarkBarNode(), 0, ASCIIToUTF16("a"),
-                   GURL(test_base + "a"));
-    const BookmarkNode* f1 =
-        model_->AddGroup(model_->GetBookmarkBarNode(), 1, ASCIIToUTF16("F1"));
-    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
-    const BookmarkNode* f11 = model_->AddGroup(f1, 1, ASCIIToUTF16("F11"));
-    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
-    model_->AddGroup(model_->GetBookmarkBarNode(), 2, ASCIIToUTF16("F2"));
-
-    // Children of the other node.
-    model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
-                   GURL(test_base + "oa"));
-    const BookmarkNode* of1 =
-        model_->AddGroup(model_->other_node(), 1, ASCIIToUTF16("OF1"));
-    model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
-  }
-};
-
-// Makes sure the tree model matches that of the bookmark bar model.
-TEST_F(BookmarkEditorGtkTest, ModelsMatch) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(),
-                           BookmarkEditor::SHOW_TREE);
-
-  // The root should have two children, one for the bookmark bar node,
-  // the other for the 'other bookmarks' folder.
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  GtkTreeIter toplevel;
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &toplevel));
-  GtkTreeIter bookmark_bar_node = toplevel;
-  ASSERT_TRUE(gtk_tree_model_iter_next(store, &toplevel));
-  GtkTreeIter other_node = toplevel;
-  ASSERT_FALSE(gtk_tree_model_iter_next(store, &toplevel));
-
-  // The bookmark bar should have 2 nodes: folder F1 and F2.
-  GtkTreeIter f1_iter;
-  GtkTreeIter child;
-  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
-  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &bookmark_bar_node));
-  f1_iter = child;
-  ASSERT_EQ("F1", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
-  ASSERT_TRUE(gtk_tree_model_iter_next(store, &child));
-  ASSERT_EQ("F2", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
-  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
-
-  // F1 should have one child, F11
-  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f1_iter));
-  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &f1_iter));
-  ASSERT_EQ("F11", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
-  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
-
-  // Other node should have one child (OF1).
-  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &other_node));
-  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &other_node));
-  ASSERT_EQ("OF1", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
-  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
-}
-
-// Changes the title and makes sure parent/visual order doesn't change.
-TEST_F(BookmarkEditorGtkTest, EditTitleKeepsPosition) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(GetNode("a")),
-                           BookmarkEditor::SHOW_TREE);
-  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
-
-  GtkTreeIter bookmark_bar_node;
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
-  editor.ApplyEdits(&bookmark_bar_node);
-
-  const BookmarkNode* bb_node =
-      profile_->GetBookmarkModel()->GetBookmarkBarNode();
-  ASSERT_EQ(ASCIIToUTF16("new_a"), bb_node->GetChild(0)->GetTitle());
-  // The URL shouldn't have changed.
-  ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->GetURL());
-}
-
-// Changes the url and makes sure parent/visual order doesn't change.
-TEST_F(BookmarkEditorGtkTest, EditURLKeepsPosition) {
-  Time node_time = GetNode("a")->date_added();
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(GetNode("a")),
-                           BookmarkEditor::SHOW_TREE);
-  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
-                     GURL(base_path() + "new_a").spec().c_str());
-
-  GtkTreeIter bookmark_bar_node;
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
-  editor.ApplyEdits(&bookmark_bar_node);
-
-  const BookmarkNode* bb_node =
-      profile_->GetBookmarkModel()->GetBookmarkBarNode();
-  ASSERT_EQ(ASCIIToUTF16("a"), bb_node->GetChild(0)->GetTitle());
-  // The URL should have changed.
-  ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->GetURL());
-  ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
-}
-
-// Moves 'a' to be a child of the other node.
-TEST_F(BookmarkEditorGtkTest, ChangeParent) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(GetNode("a")),
-                           BookmarkEditor::SHOW_TREE);
-
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  GtkTreeIter gtk_other_node;
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
-  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
-  editor.ApplyEdits(&gtk_other_node);
-
-  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
-  ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
-  ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->GetURL());
-}
-
-// Moves 'a' to be a child of the other node.
-// Moves 'a' to be a child of the other node and changes its url to new_a.
-TEST_F(BookmarkEditorGtkTest, ChangeParentAndURL) {
-  Time node_time = GetNode("a")->date_added();
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(GetNode("a")),
-                           BookmarkEditor::SHOW_TREE);
-
-  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
-                     GURL(base_path() + "new_a").spec().c_str());
-
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  GtkTreeIter gtk_other_node;
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
-  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
-  editor.ApplyEdits(&gtk_other_node);
-
-  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
-  ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
-  ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->GetURL());
-  ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
-}
-
-// Creates a new folder and moves a node to it.
-TEST_F(BookmarkEditorGtkTest, MoveToNewParent) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(GetNode("a")),
-                           BookmarkEditor::SHOW_TREE);
-
-  GtkTreeIter bookmark_bar_node;
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
-
-  // The bookmark bar should have 2 nodes: folder F1 and F2.
-  GtkTreeIter f2_iter;
-  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
-  ASSERT_TRUE(gtk_tree_model_iter_children(store, &f2_iter,
-                                           &bookmark_bar_node));
-  ASSERT_TRUE(gtk_tree_model_iter_next(store, &f2_iter));
-
-  // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
-  GtkTreeIter f21_iter;
-  editor.AddNewGroup(&f2_iter, &f21_iter);
-  gtk_tree_store_set(editor.tree_store_, &f21_iter,
-                     bookmark_utils::FOLDER_NAME, "F21", -1);
-  GtkTreeIter f211_iter;
-  editor.AddNewGroup(&f21_iter, &f211_iter);
-  gtk_tree_store_set(editor.tree_store_, &f211_iter,
-                     bookmark_utils::FOLDER_NAME, "F211", -1);
-
-  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f2_iter));
-
-  editor.ApplyEdits(&f2_iter);
-
-  const BookmarkNode* bb_node =
-      profile_->GetBookmarkModel()->GetBookmarkBarNode();
-  const BookmarkNode* mf2 = bb_node->GetChild(1);
-
-  // F2 in the model should have two children now: F21 and the node edited.
-  ASSERT_EQ(2, mf2->GetChildCount());
-  // F21 should be first.
-  ASSERT_EQ(ASCIIToUTF16("F21"), mf2->GetChild(0)->GetTitle());
-  // Then a.
-  ASSERT_EQ(ASCIIToUTF16("a"), mf2->GetChild(1)->GetTitle());
-
-  // F21 should have one child, F211.
-  const BookmarkNode* mf21 = mf2->GetChild(0);
-  ASSERT_EQ(1, mf21->GetChildCount());
-  ASSERT_EQ(ASCIIToUTF16("F211"), mf21->GetChild(0)->GetTitle());
-}
-
-// Brings up the editor, creating a new URL on the bookmark bar.
-TEST_F(BookmarkEditorGtkTest, NewURL) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(),
-                           BookmarkEditor::SHOW_TREE);
-
-  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
-                     GURL(base_path() + "a").spec().c_str());
-  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
-
-  GtkTreeIter bookmark_bar_node;
-  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
-  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
-  editor.ApplyEdits(&bookmark_bar_node);
-
-  const BookmarkNode* bb_node =
-      profile_->GetBookmarkModel()->GetBookmarkBarNode();
-  ASSERT_EQ(4, bb_node->GetChildCount());
-
-  const BookmarkNode* new_node = bb_node->GetChild(3);
-  EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
-  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
-}
-
-// Brings up the editor with no tree and modifies the url.
-TEST_F(BookmarkEditorGtkTest, ChangeURLNoTree) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(
-                               model_->other_node()->GetChild(0)),
-                           BookmarkEditor::NO_TREE);
-
-  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
-                     GURL(base_path() + "a").spec().c_str());
-  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
-
-  editor.ApplyEdits(NULL);
-
-  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
-  ASSERT_EQ(2, other_node->GetChildCount());
-
-  const BookmarkNode* new_node = other_node->GetChild(0);
-
-  EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
-  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
-}
-
-// Brings up the editor with no tree and modifies only the title.
-TEST_F(BookmarkEditorGtkTest, ChangeTitleNoTree) {
-  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
-                           BookmarkEditor::EditDetails(
-                               model_->other_node()->GetChild(0)),
-                           BookmarkEditor::NO_TREE);
-  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
-
-  editor.ApplyEdits();
-
-  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
-  ASSERT_EQ(2, other_node->GetChildCount());
-
-  const BookmarkNode* new_node = other_node->GetChild(0);
-  EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
-}
diff --git a/chrome/browser/gtk/bookmark_menu_controller_gtk.cc b/chrome/browser/gtk/bookmark_menu_controller_gtk.cc
deleted file mode 100644
index 21939c1..0000000
--- a/chrome/browser/gtk/bookmark_menu_controller_gtk.cc
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_menu_controller_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_dnd_util.h"
-#include "app/l10n_util.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/page_navigator.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "webkit/glue/window_open_disposition.h"
-
-namespace {
-
-// TODO(estade): It might be a good idea to vary this by locale.
-const int kMaxChars = 50;
-
-void SetImageMenuItem(GtkWidget* menu_item,
-                      const BookmarkNode* node,
-                      BookmarkModel* model) {
-  GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model, true);
-  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
-                                gtk_image_new_from_pixbuf(pixbuf));
-  g_object_unref(pixbuf);
-}
-
-const BookmarkNode* GetNodeFromMenuItem(GtkWidget* menu_item) {
-  return static_cast<const BookmarkNode*>(
-      g_object_get_data(G_OBJECT(menu_item), "bookmark-node"));
-}
-
-const BookmarkNode* GetParentNodeFromEmptyMenu(GtkWidget* menu) {
-  return static_cast<const BookmarkNode*>(
-      g_object_get_data(G_OBJECT(menu), "parent-node"));
-}
-
-void* AsVoid(const BookmarkNode* node) {
-  return const_cast<BookmarkNode*>(node);
-}
-
-// The context menu has been dismissed, restore the X and application grabs
-// to whichever menu last had them. (Assuming that menu is still showing.)
-void OnContextMenuHide(GtkWidget* context_menu, GtkWidget* grab_menu) {
-  gtk_util::GrabAllInput(grab_menu);
-
-  // Match the ref we took when connecting this signal.
-  g_object_unref(grab_menu);
-}
-
-}  // namespace
-
-BookmarkMenuController::BookmarkMenuController(Browser* browser,
-                                               Profile* profile,
-                                               PageNavigator* navigator,
-                                               GtkWindow* window,
-                                               const BookmarkNode* node,
-                                               int start_child_index)
-    : browser_(browser),
-      profile_(profile),
-      page_navigator_(navigator),
-      parent_window_(window),
-      model_(profile->GetBookmarkModel()),
-      node_(node),
-      drag_icon_(NULL),
-      ignore_button_release_(false),
-      triggering_widget_(NULL) {
-  menu_ = gtk_menu_new();
-  g_object_ref_sink(menu_);
-  BuildMenu(node, start_child_index, menu_);
-  signals_.Connect(menu_, "hide",
-                   G_CALLBACK(OnMenuHiddenThunk), this);
-  gtk_widget_show_all(menu_);
-}
-
-BookmarkMenuController::~BookmarkMenuController() {
-  profile_->GetBookmarkModel()->RemoveObserver(this);
-  // Make sure the hide handler runs.
-  gtk_widget_hide(menu_);
-  gtk_widget_destroy(menu_);
-  g_object_unref(menu_);
-}
-
-void BookmarkMenuController::Popup(GtkWidget* widget, gint button_type,
-                                   guint32 timestamp) {
-  profile_->GetBookmarkModel()->AddObserver(this);
-
-  triggering_widget_ = widget;
-  signals_.Connect(triggering_widget_, "destroy",
-                   G_CALLBACK(gtk_widget_destroyed), &triggering_widget_);
-  gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget),
-                                    GTK_STATE_ACTIVE);
-  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
-                 &MenuGtk::WidgetMenuPositionFunc,
-                 widget, button_type, timestamp);
-}
-
-void BookmarkMenuController::BookmarkModelChanged() {
-  gtk_menu_popdown(GTK_MENU(menu_));
-}
-
-void BookmarkMenuController::BookmarkNodeFavIconLoaded(
-    BookmarkModel* model, const BookmarkNode* node) {
-  std::map<const BookmarkNode*, GtkWidget*>::iterator it =
-      node_to_menu_widget_map_.find(node);
-  if (it != node_to_menu_widget_map_.end())
-    SetImageMenuItem(it->second, node, model);
-}
-
-void BookmarkMenuController::WillExecuteCommand() {
-  gtk_menu_popdown(GTK_MENU(menu_));
-}
-
-void BookmarkMenuController::CloseMenu() {
-  context_menu_->Cancel();
-}
-
-void BookmarkMenuController::NavigateToMenuItem(
-    GtkWidget* menu_item,
-    WindowOpenDisposition disposition) {
-  const BookmarkNode* node = GetNodeFromMenuItem(menu_item);
-  DCHECK(node);
-  DCHECK(page_navigator_);
-  page_navigator_->OpenURL(
-      node->GetURL(), GURL(), disposition, PageTransition::AUTO_BOOKMARK);
-}
-
-void BookmarkMenuController::BuildMenu(const BookmarkNode* parent,
-                                       int start_child_index,
-                                       GtkWidget* menu) {
-  DCHECK(!parent->GetChildCount() ||
-         start_child_index < parent->GetChildCount());
-
-  signals_.Connect(menu, "button-press-event",
-                   G_CALLBACK(OnMenuButtonPressedOrReleasedThunk), this);
-  signals_.Connect(menu, "button-release-event",
-                   G_CALLBACK(OnMenuButtonPressedOrReleasedThunk), this);
-
-  for (int i = start_child_index; i < parent->GetChildCount(); ++i) {
-    const BookmarkNode* node = parent->GetChild(i);
-
-    // This breaks on word boundaries. Ideally we would break on character
-    // boundaries.
-    string16 elided_name = l10n_util::TruncateString(node->GetTitle(),
-                                                     kMaxChars);
-    GtkWidget* menu_item =
-        gtk_image_menu_item_new_with_label(UTF16ToUTF8(elided_name).c_str());
-    g_object_set_data(G_OBJECT(menu_item), "bookmark-node", AsVoid(node));
-    SetImageMenuItem(menu_item, node, profile_->GetBookmarkModel());
-    gtk_util::SetAlwaysShowImage(menu_item);
-
-    signals_.Connect(menu_item, "button-release-event",
-                     G_CALLBACK(OnButtonReleasedThunk), this);
-    if (node->is_url()) {
-      signals_.Connect(menu_item, "activate",
-                       G_CALLBACK(OnMenuItemActivatedThunk), this);
-    } else if (node->is_folder()) {
-      GtkWidget* submenu = gtk_menu_new();
-      BuildMenu(node, 0, submenu);
-      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
-    } else {
-      NOTREACHED();
-    }
-
-    gtk_drag_source_set(menu_item, GDK_BUTTON1_MASK, NULL, 0,
-        static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_LINK));
-    int target_mask = gtk_dnd_util::CHROME_BOOKMARK_ITEM;
-    if (node->is_url())
-      target_mask |= gtk_dnd_util::TEXT_URI_LIST | gtk_dnd_util::NETSCAPE_URL;
-    gtk_dnd_util::SetSourceTargetListFromCodeMask(menu_item, target_mask);
-    signals_.Connect(menu_item, "drag-begin",
-                     G_CALLBACK(OnMenuItemDragBeginThunk), this);
-    signals_.Connect(menu_item, "drag-end",
-                     G_CALLBACK(OnMenuItemDragEndThunk), this);
-    signals_.Connect(menu_item, "drag-data-get",
-                     G_CALLBACK(OnMenuItemDragGetThunk), this);
-
-    // It is important to connect to this signal after setting up the drag
-    // source because we only want to stifle the menu's default handler and
-    // not the handler that the drag source uses.
-    if (node->is_folder()) {
-      signals_.Connect(menu_item, "button-press-event",
-                       G_CALLBACK(OnFolderButtonPressedThunk), this);
-    }
-
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-    node_to_menu_widget_map_[node] = menu_item;
-  }
-
-  if (parent->GetChildCount() == 0) {
-    GtkWidget* empty_menu = gtk_menu_item_new_with_label(
-        l10n_util::GetStringUTF8(IDS_MENU_EMPTY_SUBMENU).c_str());
-    gtk_widget_set_sensitive(empty_menu, FALSE);
-    g_object_set_data(G_OBJECT(menu), "parent-node", AsVoid(parent));
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), empty_menu);
-  }
-}
-
-gboolean BookmarkMenuController::OnMenuButtonPressedOrReleased(
-    GtkWidget* sender,
-    GdkEventButton* event) {
-  // Handle middle mouse downs and right mouse ups.
-  if (!((event->button == 2 && event->type == GDK_BUTTON_RELEASE) ||
-      (event->button == 3 && event->type == GDK_BUTTON_PRESS))) {
-    return FALSE;
-  }
-
-  ignore_button_release_ = false;
-  GtkMenuShell* menu_shell = GTK_MENU_SHELL(sender);
-  // If the cursor is outside our bounds, pass this event up to the parent.
-  if (!gtk_util::WidgetContainsCursor(sender)) {
-    if (menu_shell->parent_menu_shell) {
-      return OnMenuButtonPressedOrReleased(menu_shell->parent_menu_shell,
-                                           event);
-    } else {
-      // We are the top level menu; we can propagate no further.
-      return FALSE;
-    }
-  }
-
-  // This will return NULL if we are not an empty menu.
-  const BookmarkNode* parent = GetParentNodeFromEmptyMenu(sender);
-  bool is_empty_menu = !!parent;
-  // If there is no active menu item and we are not an empty menu, then do
-  // nothing. This can happen if the user has canceled a context menu while
-  // the cursor is hovering over a bookmark menu. Doing nothing is not optimal
-  // (the hovered item should be active), but it's a hopefully rare corner
-  // case.
-  GtkWidget* menu_item = menu_shell->active_menu_item;
-  if (!is_empty_menu && !menu_item)
-    return TRUE;
-  const BookmarkNode* node =
-      menu_item ? GetNodeFromMenuItem(menu_item) : NULL;
-
-  if (event->button == 2 && node && node->is_folder()) {
-    bookmark_utils::OpenAll(parent_window_,
-                            profile_, page_navigator_,
-                            node, NEW_BACKGROUND_TAB);
-    gtk_menu_popdown(GTK_MENU(menu_));
-    return TRUE;
-  } else if (event->button == 3) {
-    DCHECK_NE(is_empty_menu, !!node);
-    if (!is_empty_menu)
-      parent = node->GetParent();
-
-    // Show the right click menu and stop processing this button event.
-    std::vector<const BookmarkNode*> nodes;
-    if (node)
-      nodes.push_back(node);
-    context_menu_controller_.reset(
-        new BookmarkContextMenuController(
-            parent_window_, this, profile_,
-            page_navigator_, parent, nodes));
-    context_menu_.reset(
-        new MenuGtk(NULL, context_menu_controller_->menu_model()));
-
-    // Our bookmark folder menu loses the grab to the context menu. When the
-    // context menu is hidden, re-assert our grab.
-    GtkWidget* grabbing_menu = gtk_grab_get_current();
-    g_object_ref(grabbing_menu);
-    signals_.Connect(context_menu_->widget(), "hide",
-                     G_CALLBACK(OnContextMenuHide), grabbing_menu);
-
-    context_menu_->PopupAsContext(event->time);
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-gboolean BookmarkMenuController::OnButtonReleased(
-    GtkWidget* sender,
-    GdkEventButton* event) {
-  if (ignore_button_release_) {
-    // Don't handle this message; it was a drag.
-    ignore_button_release_ = false;
-    return FALSE;
-  }
-
-  // Releasing either button 1 or 2 should trigger the bookmark.
-  if (!gtk_menu_item_get_submenu(GTK_MENU_ITEM(sender))) {
-    // The menu item is a link node.
-    if (event->button == 1 || event->button == 2) {
-      WindowOpenDisposition disposition =
-          event_utils::DispositionFromEventFlags(event->state);
-      NavigateToMenuItem(sender, disposition);
-
-      // We need to manually dismiss the popup menu because we're overriding
-      // button-release-event.
-      gtk_menu_popdown(GTK_MENU(menu_));
-      return TRUE;
-    }
-  } else {
-    // The menu item is a folder node.
-    if (event->button == 1) {
-      // Having overriden the normal handling, we need to manually activate
-      // the item.
-      gtk_menu_shell_select_item(GTK_MENU_SHELL(sender->parent), sender);
-      g_signal_emit_by_name(sender->parent, "activate-current");
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-gboolean BookmarkMenuController::OnFolderButtonPressed(
-    GtkWidget* sender, GdkEventButton* event) {
-  // The button press may start a drag; don't let the default handler run.
-  if (event->button == 1)
-    return TRUE;
-  return FALSE;
-}
-
-void BookmarkMenuController::OnMenuHidden(GtkWidget* menu) {
-  if (triggering_widget_)
-    gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(triggering_widget_));
-}
-
-void BookmarkMenuController::OnMenuItemActivated(GtkWidget* menu_item) {
-  NavigateToMenuItem(menu_item, CURRENT_TAB);
-}
-
-void BookmarkMenuController::OnMenuItemDragBegin(GtkWidget* menu_item,
-                                                 GdkDragContext* drag_context) {
-  // The parent menu item might be removed during the drag. Ref it so |button|
-  // won't get destroyed.
-  g_object_ref(menu_item->parent);
-
-  // Signal to any future OnButtonReleased calls that we're dragging instead of
-  // pressing.
-  ignore_button_release_ = true;
-
-  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(menu_item);
-  drag_icon_ = bookmark_utils::GetDragRepresentationForNode(
-      node, model_, GtkThemeProvider::GetFrom(profile_));
-  gint x, y;
-  gtk_widget_get_pointer(menu_item, &x, &y);
-  gtk_drag_set_icon_widget(drag_context, drag_icon_, x, y);
-
-  // Hide our node.
-  gtk_widget_hide(menu_item);
-}
-
-void BookmarkMenuController::OnMenuItemDragEnd(GtkWidget* menu_item,
-                                               GdkDragContext* drag_context) {
-  gtk_widget_show(menu_item);
-  g_object_unref(menu_item->parent);
-
-  gtk_widget_destroy(drag_icon_);
-  drag_icon_ = NULL;
-}
-
-void BookmarkMenuController::OnMenuItemDragGet(
-    GtkWidget* widget, GdkDragContext* context,
-    GtkSelectionData* selection_data,
-    guint target_type, guint time) {
-  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
-  bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
-                                           profile_);
-}
diff --git a/chrome/browser/gtk/bookmark_menu_controller_gtk.h b/chrome/browser/gtk/bookmark_menu_controller_gtk.h
deleted file mode 100644
index 0060267..0000000
--- a/chrome/browser/gtk/bookmark_menu_controller_gtk.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_MENU_CONTROLLER_GTK_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_MENU_CONTROLLER_GTK_H_
-#pragma once
-
-#include <map>
-
-#include "app/gtk_integers.h"
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
-#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "webkit/glue/window_open_disposition.h"
-
-class Browser;
-class Profile;
-class Profiler;
-class PageNavigator;
-class BookmarkModel;
-class BookmarkNode;
-class MenuGtk;
-
-typedef struct _GdkDragContext GdkDragContext;
-typedef struct _GdkEventButton GdkEventButton;
-typedef struct _GtkSelectionData GtkSelectionData;
-typedef struct _GtkWidget GtkWidget;
-
-class BookmarkMenuController : public BaseBookmarkModelObserver,
-                               public BookmarkContextMenuControllerDelegate {
- public:
-  // Creates a BookmarkMenuController showing the children of |node| starting
-  // at index |start_child_index|.
-  BookmarkMenuController(Browser* browser,
-                         Profile* profile,
-                         PageNavigator* page_navigator,
-                         GtkWindow* window,
-                         const BookmarkNode* node,
-                         int start_child_index);
-  virtual ~BookmarkMenuController();
-
-  GtkWidget* widget() { return menu_; }
-
-  // Pops up the menu. |widget| must be a GtkChromeButton.
-  void Popup(GtkWidget* widget, gint button_type, guint32 timestamp);
-
-  // Overridden from BaseBookmarkModelObserver:
-  virtual void BookmarkModelChanged();
-  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
-                                         const BookmarkNode* node);
-
-  // Overridden from BookmarkContextMenuController::Delegate:
-  virtual void WillExecuteCommand();
-  virtual void CloseMenu();
-
- private:
-  // Recursively change the bookmark hierarchy rooted in |parent| into a set of
-  // gtk menus rooted in |menu|.
-  void BuildMenu(const BookmarkNode* parent,
-                 int start_child_index,
-                 GtkWidget* menu);
-
-  // Calls the page navigator to navigate to the node represented by
-  // |menu_item|.
-  void NavigateToMenuItem(GtkWidget* menu_item,
-                          WindowOpenDisposition disposition);
-
-  // Button press and release events for a GtkMenu.
-  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean,
-                       OnMenuButtonPressedOrReleased, GdkEventButton*);
-
-  // Button release event for a GtkMenuItem.
-  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean, OnButtonReleased,
-                       GdkEventButton*);
-
-  // We connect this handler to the button-press-event signal for folder nodes.
-  // It suppresses the normal behavior (popping up the submenu) to allow these
-  // nodes to be draggable. The submenu is instead popped up on a
-  // button-release-event.
-  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean, OnFolderButtonPressed,
-                       GdkEventButton*);
-
-  // We have to stop drawing |triggering_widget_| as active when the menu
-  // closes.
-  CHROMEGTK_CALLBACK_0(BookmarkMenuController, void, OnMenuHidden)
-
-  // We respond to the activate signal because things other than mouse button
-  // events can trigger it.
-  CHROMEGTK_CALLBACK_0(BookmarkMenuController, void, OnMenuItemActivated);
-
-  // The individual GtkMenuItems in the BookmarkMenu are all drag sources.
-  CHROMEGTK_CALLBACK_1(BookmarkMenuController, void, OnMenuItemDragBegin,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_1(BookmarkMenuController, void, OnMenuItemDragEnd,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_4(BookmarkMenuController, void, OnMenuItemDragGet,
-                       GdkDragContext*, GtkSelectionData*, guint, guint);
-
-  Browser* browser_;
-  Profile* profile_;
-  PageNavigator* page_navigator_;
-
-  // Parent window of this menu.
-  GtkWindow* parent_window_;
-
-  // The bookmark model.
-  BookmarkModel* model_;
-
-  // The node we're showing the contents of.
-  const BookmarkNode* node_;
-
-  // Our bookmark menus. We don't use the MenuGtk class because we have to do
-  // all sorts of weird non-standard things with this menu, like:
-  // - The menu is a drag target
-  // - The menu items have context menus.
-  GtkWidget* menu_;
-
-  // The visual representation that follows the cursor during drags.
-  GtkWidget* drag_icon_;
-
-  // Whether we should ignore the next button release event (because we were
-  // dragging).
-  bool ignore_button_release_;
-
-  // The widget we are showing for (i.e. the bookmark bar folder button).
-  GtkWidget* triggering_widget_;
-
-  // Mapping from node to GtkMenuItem menu id. This only contains entries for
-  // nodes of type URL.
-  std::map<const BookmarkNode*, GtkWidget*> node_to_menu_widget_map_;
-
-  // The controller and view for the right click context menu.
-  scoped_ptr<BookmarkContextMenuController> context_menu_controller_;
-  scoped_ptr<MenuGtk> context_menu_;
-
-  GtkSignalRegistrar signals_;
-
-  DISALLOW_COPY_AND_ASSIGN(BookmarkMenuController);
-};
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_MENU_CONTROLLER_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_tree_model.cc b/chrome/browser/gtk/bookmark_tree_model.cc
deleted file mode 100644
index d6ef4de..0000000
--- a/chrome/browser/gtk/bookmark_tree_model.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_tree_model.h"
-
-#include <gtk/gtk.h>
-
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-
-namespace {
-
-const char* kCellRendererTextKey = "__CELL_RENDERER_TEXT__";
-
-void AddSingleNodeToTreeStore(GtkTreeStore* store, const BookmarkNode* node,
-                              GtkTreeIter *iter, GtkTreeIter* parent) {
-  gtk_tree_store_append(store, iter, parent);
-  // It would be easy to show a different icon when the folder is open (as they
-  // do on Windows, for example), using pixbuf-expander-closed and
-  // pixbuf-expander-open. Unfortunately there is no GTK_STOCK_OPEN_DIRECTORY
-  // (and indeed, Nautilus does not render an expanded directory any
-  // differently).
-  gtk_tree_store_set(store, iter,
-      bookmark_utils::FOLDER_ICON, GtkThemeProvider::GetFolderIcon(true),
-      bookmark_utils::FOLDER_NAME,
-      UTF16ToUTF8(node->GetTitle()).c_str(),
-      bookmark_utils::ITEM_ID, node->id(),
-      // We don't want to use node->is_folder() because that would let the
-      // user edit "Bookmarks Bar" and "Other Bookmarks".
-      bookmark_utils::IS_EDITABLE, node->type() == BookmarkNode::FOLDER,
-      -1);
-}
-
-// Helper function for CommitTreeStoreDifferencesBetween() which recursively
-// merges changes back from a GtkTreeStore into a tree of BookmarkNodes. This
-// function only works on non-root nodes; our caller handles that special case.
-void RecursiveResolve(BookmarkModel* bb_model, const BookmarkNode* bb_node,
-                      GtkTreeModel* tree_model, GtkTreeIter* parent_iter,
-                      GtkTreePath* selected_path,
-                      const BookmarkNode** selected_node) {
-  GtkTreePath* current_path = gtk_tree_model_get_path(tree_model, parent_iter);
-  if (gtk_tree_path_compare(current_path, selected_path) == 0)
-    *selected_node = bb_node;
-  gtk_tree_path_free(current_path);
-
-  GtkTreeIter child_iter;
-  if (gtk_tree_model_iter_children(tree_model, &child_iter, parent_iter)) {
-    do {
-      int64 id = bookmark_utils::GetIdFromTreeIter(tree_model, &child_iter);
-      string16 title =
-          bookmark_utils::GetTitleFromTreeIter(tree_model, &child_iter);
-      const BookmarkNode* child_bb_node = NULL;
-      if (id == 0) {
-        child_bb_node = bb_model->AddGroup(bb_node, bb_node->GetChildCount(),
-                                           title);
-      } else {
-        // Existing node, reset the title (BBModel ignores changes if the title
-        // is the same).
-        for (int j = 0; j < bb_node->GetChildCount(); ++j) {
-          const BookmarkNode* node = bb_node->GetChild(j);
-          if (node->is_folder() && node->id() == id) {
-            child_bb_node = node;
-            break;
-          }
-        }
-        DCHECK(child_bb_node);
-        bb_model->SetTitle(child_bb_node, title);
-      }
-      RecursiveResolve(bb_model, child_bb_node,
-                       tree_model, &child_iter,
-                       selected_path, selected_node);
-    } while (gtk_tree_model_iter_next(tree_model, &child_iter));
-  }
-}
-
-// Update the folder name in the GtkTreeStore.
-void OnFolderNameEdited(GtkCellRendererText* render,
-    gchar* path, gchar* new_folder_name, GtkTreeStore* tree_store) {
-  GtkTreeIter folder_iter;
-  GtkTreePath* tree_path = gtk_tree_path_new_from_string(path);
-  gboolean rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store),
-                                        &folder_iter, tree_path);
-  DCHECK(rv);
-  gtk_tree_store_set(tree_store, &folder_iter,
-                     bookmark_utils::FOLDER_NAME, new_folder_name,
-                     -1);
-  gtk_tree_path_free(tree_path);
-}
-
-}  // namespace
-
-namespace bookmark_utils {
-
-GtkTreeStore* MakeFolderTreeStore() {
-  return gtk_tree_store_new(FOLDER_STORE_NUM_COLUMNS, GDK_TYPE_PIXBUF,
-                            G_TYPE_STRING, G_TYPE_INT64, G_TYPE_BOOLEAN);
-}
-
-void AddToTreeStore(BookmarkModel* model, int64 selected_id,
-                    GtkTreeStore* store, GtkTreeIter* selected_iter) {
-  const BookmarkNode* root_node = model->root_node();
-  for (int i = 0; i < root_node->GetChildCount(); ++i) {
-    AddToTreeStoreAt(root_node->GetChild(i), selected_id, store, selected_iter,
-                     NULL);
-  }
-}
-
-GtkWidget* MakeTreeViewForStore(GtkTreeStore* store) {
-  GtkTreeViewColumn* column = gtk_tree_view_column_new();
-  GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
-  gtk_tree_view_column_add_attribute(column, image_renderer,
-                                     "pixbuf", FOLDER_ICON);
-  GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
-  g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-  g_signal_connect(text_renderer, "edited", G_CALLBACK(OnFolderNameEdited),
-                   store);
-  gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
-  gtk_tree_view_column_set_attributes(column, text_renderer,
-                                      "text", FOLDER_NAME,
-                                      "editable", IS_EDITABLE,
-                                      NULL);
-
-  GtkWidget* tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
-  // Let |tree_view| own the store.
-  g_object_unref(store);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
-  g_object_set_data(G_OBJECT(tree_view), kCellRendererTextKey, text_renderer);
-  return tree_view;
-}
-
-GtkCellRenderer* GetCellRendererText(GtkTreeView* tree_view) {
-  return static_cast<GtkCellRenderer*>(
-      g_object_get_data(G_OBJECT(tree_view), kCellRendererTextKey));
-}
-
-void AddToTreeStoreAt(const BookmarkNode* node, int64 selected_id,
-                      GtkTreeStore* store, GtkTreeIter* selected_iter,
-                      GtkTreeIter* parent) {
-  if (!node->is_folder())
-    return;
-
-  GtkTreeIter iter;
-  AddSingleNodeToTreeStore(store, node, &iter, parent);
-  if (selected_iter && node->id() == selected_id) {
-     // Save the iterator. Since we're using a GtkTreeStore, we're
-     // guaranteed that the iterator will remain valid as long as the above
-     // appended item exists.
-     *selected_iter = iter;
-  }
-
-  for (int i = 0; i < node->GetChildCount(); ++i) {
-    AddToTreeStoreAt(node->GetChild(i), selected_id, store, selected_iter,
-                     &iter);
-  }
-}
-
-const BookmarkNode* CommitTreeStoreDifferencesBetween(
-    BookmarkModel* bb_model, GtkTreeStore* tree_store, GtkTreeIter* selected) {
-  const BookmarkNode* node_to_return = NULL;
-  GtkTreeModel* tree_model = GTK_TREE_MODEL(tree_store);
-
-  GtkTreePath* selected_path = gtk_tree_model_get_path(tree_model, selected);
-
-  GtkTreeIter tree_root;
-  if (!gtk_tree_model_get_iter_first(tree_model, &tree_root))
-    NOTREACHED() << "Impossible missing bookmarks case";
-
-  // The top level of this tree is weird and needs to be special cased. The
-  // BookmarksNode tree is rooted on a root node while the GtkTreeStore has a
-  // set of top level nodes that are the root BookmarksNode's children. These
-  // items in the top level are not editable and therefore don't need the extra
-  // complexity of trying to modify their title.
-  const BookmarkNode* root_node = bb_model->root_node();
-  do {
-    DCHECK(GetIdFromTreeIter(tree_model, &tree_root) != 0)
-        << "It should be impossible to add another toplevel node";
-
-    int64 id = GetIdFromTreeIter(tree_model, &tree_root);
-    const BookmarkNode* child_node = NULL;
-    for (int j = 0; j < root_node->GetChildCount(); ++j) {
-      const BookmarkNode* node = root_node->GetChild(j);
-      if (node->is_folder() && node->id() == id) {
-        child_node = node;
-        break;
-      }
-    }
-    DCHECK(child_node);
-
-    GtkTreeIter child_iter = tree_root;
-    RecursiveResolve(bb_model, child_node, tree_model, &child_iter,
-                     selected_path, &node_to_return);
-  } while (gtk_tree_model_iter_next(tree_model, &tree_root));
-
-  gtk_tree_path_free(selected_path);
-  return node_to_return;
-}
-
-int64 GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
-  GValue value = { 0, };
-  int64 ret_val = -1;
-  gtk_tree_model_get_value(model, iter, ITEM_ID, &value);
-  if (G_VALUE_HOLDS_INT64(&value))
-    ret_val = g_value_get_int64(&value);
-  else
-    NOTREACHED() << "Impossible type mismatch";
-
-  return ret_val;
-}
-
-string16 GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
-  GValue value = { 0, };
-  string16 ret_val;
-  gtk_tree_model_get_value(model, iter, FOLDER_NAME, &value);
-  if (G_VALUE_HOLDS_STRING(&value)) {
-    const gchar* utf8str = g_value_get_string(&value);
-    ret_val = UTF8ToUTF16(utf8str);
-    g_value_unset(&value);
-  } else {
-    NOTREACHED() << "Impossible type mismatch";
-  }
-
-  return ret_val;
-}
-
-}  // namespace bookmark_utils
diff --git a/chrome/browser/gtk/bookmark_tree_model.h b/chrome/browser/gtk/bookmark_tree_model.h
deleted file mode 100644
index 1d28fbd..0000000
--- a/chrome/browser/gtk/bookmark_tree_model.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_TREE_MODEL_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_TREE_MODEL_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "base/string16.h"
-
-class BookmarkModel;
-class BookmarkNode;
-
-typedef struct _GtkCellRenderer GtkCellRenderer;
-typedef struct _GtkTreeIter GtkTreeIter;
-typedef struct _GtkTreeModel GtkTreeModel;
-typedef struct _GtkTreeStore GtkTreeStore;
-typedef struct _GtkTreeView GtkTreeView;
-typedef struct _GdkPixbuf GdkPixbuf;
-typedef struct _GtkWidget GtkWidget;
-
-namespace bookmark_utils {
-
-enum FolderTreeStoreColumns {
-  FOLDER_ICON,
-  FOLDER_NAME,
-  ITEM_ID,
-  IS_EDITABLE,
-  FOLDER_STORE_NUM_COLUMNS
-};
-
-// Make a tree store that has two columns: name and id.
-GtkTreeStore* MakeFolderTreeStore();
-
-// Copies the folders in the model's root node into a GtkTreeStore. We
-// want the user to be able to modify the tree of folders, but to be able to
-// click Cancel and discard their modifications. |selected_id| is the
-// node->id() of the BookmarkNode that should selected on
-// node->screen. |selected_iter| is an out value that points to the
-// node->representation of the node associated with |selected_id| in |store|.
-// |recursive| indicates whether to recurse into sub-directories (if false,
-// the tree store will effectively be a list). |only_folders| indicates whether
-// to include bookmarks in the tree, or to only show folders.
-void AddToTreeStore(BookmarkModel* model, int64 selected_id,
-                    GtkTreeStore* store, GtkTreeIter* selected_iter);
-
-// As above, but inserts just the tree rooted at |node| as a child of |parent|.
-// If |parent| is NULL, add it at the top level.
-void AddToTreeStoreAt(const BookmarkNode* node, int64 selected_id,
-                      GtkTreeStore* store, GtkTreeIter* selected_iter,
-                      GtkTreeIter* parent);
-
-// Makes a tree view for the store. This will take ownership of |store| and the
-// returned widget has a floating reference.
-GtkWidget* MakeTreeViewForStore(GtkTreeStore* store);
-
-// A helper method for getting pointer back to the GtkCellRendererText used for
-// the folder names.
-GtkCellRenderer* GetCellRendererText(GtkTreeView* tree_view);
-
-// Commits changes to a GtkTreeStore built from BuildTreeStoreFrom() back
-// into the BookmarkModel it was generated from.  Returns the BookmarkNode that
-// represented by |selected|.
-const BookmarkNode* CommitTreeStoreDifferencesBetween(
-    BookmarkModel* model, GtkTreeStore* tree_store,
-    GtkTreeIter* selected);
-
-// Returns the id field of the row pointed to by |iter|.
-int64 GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter);
-
-// Returns the title field in utf8 of the row pointed to by |iter|.
-string16 GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter);
-
-}  // namespace bookmark_utils
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_TREE_MODEL_H_
diff --git a/chrome/browser/gtk/bookmark_utils_gtk.cc b/chrome/browser/gtk/bookmark_utils_gtk.cc
deleted file mode 100644
index 62acc14..0000000
--- a/chrome/browser/gtk/bookmark_utils_gtk.cc
+++ /dev/null
@@ -1,441 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-
-#include "app/gtk_dnd_util.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/pickle.h"
-#include "base/string16.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/font.h"
-#include "gfx/gtk_util.h"
-
-namespace {
-
-// Spacing between the favicon and the text.
-const int kBarButtonPadding = 4;
-
-// Used in gtk_selection_data_set(). (I assume from this parameter that gtk has
-// to some really exotic hardware...)
-const int kBitsInAByte = 8;
-
-// Maximum number of characters on a bookmark button.
-const size_t kMaxCharsOnAButton = 15;
-
-// Max size of each component of the button tooltips.
-const size_t kMaxTooltipTitleLength = 100;
-const size_t kMaxTooltipURLLength = 400;
-
-// Padding between the chrome button highlight border and the contents (favicon,
-// text).
-const int kButtonPaddingTop = 0;
-const int kButtonPaddingBottom = 0;
-const int kButtonPaddingLeft = 5;
-const int kButtonPaddingRight = 0;
-
-void* AsVoid(const BookmarkNode* node) {
-  return const_cast<BookmarkNode*>(node);
-}
-
-// Creates the widget hierarchy for a bookmark button.
-void PackButton(GdkPixbuf* pixbuf, const string16& title, bool ellipsize,
-                GtkThemeProvider* provider, GtkWidget* button) {
-  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
-  if (former_child)
-    gtk_container_remove(GTK_CONTAINER(button), former_child);
-
-  // We pack the button manually (rather than using gtk_button_set_*) so that
-  // we can have finer control over its label.
-  GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
-
-  GtkWidget* box = gtk_hbox_new(FALSE, kBarButtonPadding);
-  gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
-
-  std::string label_string = UTF16ToUTF8(title);
-  if (!label_string.empty()) {
-    GtkWidget* label = gtk_label_new(label_string.c_str());
-    // Until we switch to vector graphics, force the font size.
-    gtk_util::ForceFontSizePixels(label, 13.4);  // 13.4px == 10pt @ 96dpi
-
-    // Ellipsize long bookmark names.
-    if (ellipsize) {
-      gtk_label_set_max_width_chars(GTK_LABEL(label), kMaxCharsOnAButton);
-      gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
-    }
-
-    gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
-    bookmark_utils::SetButtonTextColors(label, provider);
-  }
-
-  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  // If we are not showing the label, don't set any padding, so that the icon
-  // will just be centered.
-  if (label_string.c_str()) {
-    gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
-        kButtonPaddingTop, kButtonPaddingBottom,
-        kButtonPaddingLeft, kButtonPaddingRight);
-  }
-  gtk_container_add(GTK_CONTAINER(alignment), box);
-  gtk_container_add(GTK_CONTAINER(button), alignment);
-
-  gtk_widget_show_all(alignment);
-}
-
-const int kDragRepresentationWidth = 140;
-
-struct DragRepresentationData {
- public:
-  GdkPixbuf* favicon;
-  string16 text;
-  SkColor text_color;
-
-  DragRepresentationData(GdkPixbuf* favicon,
-                         const string16& text,
-                         SkColor text_color)
-      : favicon(favicon),
-        text(text),
-        text_color(text_color) {
-    g_object_ref(favicon);
-  }
-
-  ~DragRepresentationData() {
-    g_object_unref(favicon);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DragRepresentationData);
-};
-
-gboolean OnDragIconExpose(GtkWidget* sender,
-                          GdkEventExpose* event,
-                          DragRepresentationData* data) {
-  // Clear the background.
-  cairo_t* cr = gdk_cairo_create(event->window);
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-  cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
-  cairo_paint(cr);
-
-  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-  gdk_cairo_set_source_pixbuf(cr, data->favicon, 0, 0);
-  cairo_paint(cr);
-  cairo_destroy(cr);
-
-  // Paint the title text.
-  gfx::CanvasSkiaPaint canvas(event, false);
-  int text_x = gdk_pixbuf_get_width(data->favicon) + kBarButtonPadding;
-  int text_width = sender->allocation.width - text_x;
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
-  canvas.DrawStringInt(UTF16ToWide(data->text),
-                       base_font, data->text_color,
-                       text_x, 0, text_width, sender->allocation.height);
-
-  return TRUE;
-}
-
-void OnDragIconDestroy(GtkWidget* drag_icon,
-                       DragRepresentationData* data) {
-  g_object_unref(drag_icon);
-  delete data;
-}
-
-}  // namespace
-
-namespace bookmark_utils {
-
-const char kBookmarkNode[] = "bookmark-node";
-
-GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model,
-                            bool native) {
-  GdkPixbuf* pixbuf;
-
-  if (node->is_url()) {
-    if (model->GetFavIcon(node).width() != 0) {
-      pixbuf = gfx::GdkPixbufFromSkBitmap(&model->GetFavIcon(node));
-    } else {
-      pixbuf = GtkThemeProvider::GetDefaultFavicon(native);
-      g_object_ref(pixbuf);
-    }
-  } else {
-    pixbuf = GtkThemeProvider::GetFolderIcon(native);
-    g_object_ref(pixbuf);
-  }
-
-  return pixbuf;
-}
-
-GtkWidget* GetDragRepresentation(GdkPixbuf* pixbuf,
-                                 const string16& title,
-                                 GtkThemeProvider* provider) {
-  GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
-
-  if (gtk_util::IsScreenComposited() &&
-      gtk_util::AddWindowAlphaChannel(window)) {
-    DragRepresentationData* data = new DragRepresentationData(
-        pixbuf, title,
-        provider->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT));
-    g_signal_connect(window, "expose-event", G_CALLBACK(OnDragIconExpose),
-                     data);
-    g_object_ref(window);
-    g_signal_connect(window, "destroy", G_CALLBACK(OnDragIconDestroy), data);
-
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
-    gtk_widget_set_size_request(window, kDragRepresentationWidth,
-                                base_font.GetHeight());
-  } else {
-    if (!provider->UseGtkTheme()) {
-      GdkColor color = provider->GetGdkColor(
-          BrowserThemeProvider::COLOR_TOOLBAR);
-      gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
-    }
-    gtk_widget_realize(window);
-
-    GtkWidget* frame = gtk_frame_new(NULL);
-    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
-    gtk_container_add(GTK_CONTAINER(window), frame);
-
-    GtkWidget* floating_button = provider->BuildChromeButton();
-    PackButton(pixbuf, title, true, provider, floating_button);
-    gtk_container_add(GTK_CONTAINER(frame), floating_button);
-    gtk_widget_show_all(frame);
-  }
-
-  return window;
-}
-
-GtkWidget* GetDragRepresentationForNode(const BookmarkNode* node,
-                                        BookmarkModel* model,
-                                        GtkThemeProvider* provider) {
-  GdkPixbuf* pixbuf = GetPixbufForNode(node, model, provider->UseGtkTheme());
-  GtkWidget* widget = GetDragRepresentation(pixbuf, node->GetTitle(), provider);
-  g_object_unref(pixbuf);
-  return widget;
-}
-
-void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model,
-                            GtkWidget* button, GtkThemeProvider* provider) {
-  GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model,
-                                                       provider->UseGtkTheme());
-  PackButton(pixbuf, node->GetTitle(), node != model->other_node(), provider,
-             button);
-  g_object_unref(pixbuf);
-
-  std::string tooltip = BuildTooltipFor(node);
-  if (!tooltip.empty())
-    gtk_widget_set_tooltip_markup(button, tooltip.c_str());
-
-  g_object_set_data(G_OBJECT(button), bookmark_utils::kBookmarkNode,
-                    AsVoid(node));
-}
-
-std::string BuildTooltipFor(const BookmarkNode* node) {
-  const std::string& url = node->GetURL().possibly_invalid_spec();
-  const std::string& title = UTF16ToUTF8(node->GetTitle());
-
-  std::string truncated_url = UTF16ToUTF8(l10n_util::TruncateString(
-      UTF8ToUTF16(url), kMaxTooltipURLLength));
-  gchar* escaped_url_cstr = g_markup_escape_text(truncated_url.c_str(),
-                                                 truncated_url.size());
-  std::string escaped_url(escaped_url_cstr);
-  g_free(escaped_url_cstr);
-
-  std::string tooltip;
-  if (url == title || title.empty()) {
-    return escaped_url;
-  } else {
-    std::string truncated_title = UTF16ToUTF8(l10n_util::TruncateString(
-        node->GetTitle(), kMaxTooltipTitleLength));
-    gchar* escaped_title_cstr = g_markup_escape_text(truncated_title.c_str(),
-                                                     truncated_title.size());
-    std::string escaped_title(escaped_title_cstr);
-    g_free(escaped_title_cstr);
-
-    if (!escaped_url.empty())
-      return std::string("<b>") + escaped_title + "</b>\n" + escaped_url;
-    else
-      return std::string("<b>") + escaped_title + "</b>";
-  }
-}
-
-const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget) {
-  return reinterpret_cast<const BookmarkNode*>(
-      g_object_get_data(G_OBJECT(widget), bookmark_utils::kBookmarkNode));
-}
-
-void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) {
-  if (provider->UseGtkTheme()) {
-    gtk_util::SetLabelColor(label, NULL);
-  } else {
-    GdkColor color = provider->GetGdkColor(
-        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-    gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color);
-    gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, &color);
-
-    // Because the prelight state is a white image that doesn't change by the
-    // theme, force the text color to black when it would be used.
-    gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &gtk_util::kGdkBlack);
-    gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &gtk_util::kGdkBlack);
-  }
-}
-
-// DnD-related -----------------------------------------------------------------
-
-int GetCodeMask(bool folder) {
-  int rv = gtk_dnd_util::CHROME_BOOKMARK_ITEM;
-  if (!folder) {
-    rv |= gtk_dnd_util::TEXT_URI_LIST |
-          gtk_dnd_util::TEXT_PLAIN |
-          gtk_dnd_util::NETSCAPE_URL;
-  }
-  return rv;
-}
-
-void WriteBookmarkToSelection(const BookmarkNode* node,
-                              GtkSelectionData* selection_data,
-                              guint target_type,
-                              Profile* profile) {
-  DCHECK(node);
-  std::vector<const BookmarkNode*> nodes;
-  nodes.push_back(node);
-  WriteBookmarksToSelection(nodes, selection_data, target_type, profile);
-}
-
-void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
-                               GtkSelectionData* selection_data,
-                               guint target_type,
-                               Profile* profile) {
-  switch (target_type) {
-    case gtk_dnd_util::CHROME_BOOKMARK_ITEM: {
-      BookmarkNodeData data(nodes);
-      Pickle pickle;
-      data.WriteToPickle(profile, &pickle);
-
-      gtk_selection_data_set(selection_data, selection_data->target,
-                             kBitsInAByte,
-                             static_cast<const guchar*>(pickle.data()),
-                             pickle.size());
-      break;
-    }
-    case gtk_dnd_util::NETSCAPE_URL: {
-      // _NETSCAPE_URL format is URL + \n + title.
-      std::string utf8_text = nodes[0]->GetURL().spec() + "\n" +
-          UTF16ToUTF8(nodes[0]->GetTitle());
-      gtk_selection_data_set(selection_data,
-                             selection_data->target,
-                             kBitsInAByte,
-                             reinterpret_cast<const guchar*>(utf8_text.c_str()),
-                             utf8_text.length());
-      break;
-    }
-    case gtk_dnd_util::TEXT_URI_LIST: {
-      gchar** uris = reinterpret_cast<gchar**>(malloc(sizeof(gchar*) *
-                                               (nodes.size() + 1)));
-      for (size_t i = 0; i < nodes.size(); ++i) {
-        // If the node is a folder, this will be empty. TODO(estade): figure out
-        // if there are any ramifications to passing an empty URI. After a
-        // little testing, it seems fine.
-        const GURL& url = nodes[i]->GetURL();
-        // This const cast should be safe as gtk_selection_data_set_uris()
-        // makes copies.
-        uris[i] = const_cast<gchar*>(url.spec().c_str());
-      }
-      uris[nodes.size()] = NULL;
-
-      gtk_selection_data_set_uris(selection_data, uris);
-      free(uris);
-      break;
-    }
-    case gtk_dnd_util::TEXT_PLAIN: {
-      gtk_selection_data_set_text(selection_data,
-                                  nodes[0]->GetURL().spec().c_str(), -1);
-      break;
-    }
-    default: {
-      DLOG(ERROR) << "Unsupported drag get type!";
-    }
-  }
-}
-
-std::vector<const BookmarkNode*> GetNodesFromSelection(
-    GdkDragContext* context,
-    GtkSelectionData* selection_data,
-    guint target_type,
-    Profile* profile,
-    gboolean* delete_selection_data,
-    gboolean* dnd_success) {
-  if (delete_selection_data)
-    *delete_selection_data = FALSE;
-  if (dnd_success)
-    *dnd_success = FALSE;
-
-  if (selection_data && selection_data->length > 0) {
-    if (context && delete_selection_data && context->action == GDK_ACTION_MOVE)
-      *delete_selection_data = TRUE;
-
-    switch (target_type) {
-      case gtk_dnd_util::CHROME_BOOKMARK_ITEM: {
-        if (dnd_success)
-          *dnd_success = TRUE;
-        Pickle pickle(reinterpret_cast<char*>(selection_data->data),
-                      selection_data->length);
-        BookmarkNodeData drag_data;
-        drag_data.ReadFromPickle(&pickle);
-        return drag_data.GetNodes(profile);
-      }
-      default: {
-        DLOG(ERROR) << "Unsupported drag received type: " << target_type;
-      }
-    }
-  }
-
-  return std::vector<const BookmarkNode*>();
-}
-
-bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data,
-    BookmarkModel* model, const BookmarkNode* parent, int idx) {
-  GURL url;
-  string16 title;
-  if (!gtk_dnd_util::ExtractNamedURL(selection_data, &url, &title))
-    return false;
-
-  model->AddURL(parent, idx, title, url);
-  return true;
-}
-
-bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data,
-    BookmarkModel* model, const BookmarkNode* parent, int idx) {
-  std::vector<GURL> urls;
-  gtk_dnd_util::ExtractURIList(selection_data, &urls);
-  for (size_t i = 0; i < urls.size(); ++i) {
-    std::string title = GetNameForURL(urls[i]);
-    model->AddURL(parent, idx++, UTF8ToUTF16(title), urls[i]);
-  }
-  return true;
-}
-
-bool CreateNewBookmarkFromNetscapeURL(GtkSelectionData* selection_data,
-    BookmarkModel* model, const BookmarkNode* parent, int idx) {
-  GURL url;
-  string16 title;
-  if (!gtk_dnd_util::ExtractNetscapeURL(selection_data, &url, &title))
-    return false;
-
-  model->AddURL(parent, idx, title, url);
-  return true;
-}
-
-}  // namespace bookmark_utils
diff --git a/chrome/browser/gtk/bookmark_utils_gtk.h b/chrome/browser/gtk/bookmark_utils_gtk.h
deleted file mode 100644
index 1ebc627..0000000
--- a/chrome/browser/gtk/bookmark_utils_gtk.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BOOKMARK_UTILS_GTK_H_
-#define CHROME_BROWSER_GTK_BOOKMARK_UTILS_GTK_H_
-#pragma once
-
-#include <vector>
-#include <string>
-
-#include "app/gtk_integers.h"
-#include "base/string16.h"
-
-class BookmarkModel;
-class BookmarkNode;
-class GtkThemeProvider;
-class Profile;
-
-typedef struct _GdkDragContext GdkDragContext;
-typedef struct _GdkPixbuf GdkPixbuf;
-typedef struct _GtkSelectionData GtkSelectionData;
-typedef struct _GtkWidget GtkWidget;
-
-namespace bookmark_utils {
-
-extern const char kBookmarkNode[];
-
-// Get the image that is used to represent the node. This function adds a ref
-// to the returned pixbuf, so it requires a matching call to g_object_unref().
-GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model,
-                            bool native);
-
-// Returns a GtkWindow with a visual hierarchy for passing to
-// gtk_drag_set_icon_widget().
-GtkWidget* GetDragRepresentation(GdkPixbuf* pixbuf,
-                                 const string16& title,
-                                 GtkThemeProvider* provider);
-GtkWidget* GetDragRepresentationForNode(const BookmarkNode* node,
-                                        BookmarkModel* model,
-                                        GtkThemeProvider* provider);
-
-// Helper function that sets visual properties of GtkButton |button| to the
-// contents of |node|.
-void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model,
-                            GtkWidget* button, GtkThemeProvider* provider);
-
-// Returns the tooltip.
-std::string BuildTooltipFor(const BookmarkNode* node);
-
-// Returns the "bookmark-node" property of |widget| casted to the correct type.
-const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget);
-
-// Set the colors on |label| as per the theme.
-void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider);
-
-// Drag and drop. --------------------------------------------------------------
-
-// Get the DnD target mask for a bookmark drag. This will vary based on whether
-// the node in question is a folder.
-int GetCodeMask(bool folder);
-
-// Pickle a node into a GtkSelection.
-void WriteBookmarkToSelection(const BookmarkNode* node,
-                              GtkSelectionData* selection_data,
-                              guint target_type,
-                              Profile* profile);
-
-// Pickle a vector of nodes into a GtkSelection.
-void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
-                               GtkSelectionData* selection_data,
-                               guint target_type,
-                               Profile* profile);
-
-// Un-pickle node(s) from a GtkSelection.
-// The last two arguments are out parameters.
-std::vector<const BookmarkNode*> GetNodesFromSelection(
-    GdkDragContext* context,
-    GtkSelectionData* selection_data,
-    guint target_type,
-    Profile* profile,
-    gboolean* delete_selection_data,
-    gboolean* dnd_success);
-
-// Unpickle a new bookmark of the CHROME_NAMED_URL drag type, and put it in
-// the appropriate location in the model.
-bool CreateNewBookmarkFromNamedUrl(
-    GtkSelectionData* selection_data,
-    BookmarkModel* model,
-    const BookmarkNode* parent,
-    int idx);
-
-// Add the URIs in |selection_data| into the model at the given position. They
-// will be added whether or not the URL is valid.
-bool CreateNewBookmarksFromURIList(
-    GtkSelectionData* selection_data,
-    BookmarkModel* model,
-    const BookmarkNode* parent,
-    int idx);
-
-// Add the "url\ntitle" combination into the model at the given position.
-bool CreateNewBookmarkFromNetscapeURL(
-    GtkSelectionData* selection_data,
-    BookmarkModel* model,
-    const BookmarkNode* parent,
-    int idx);
-
-}  // namespace bookmark_utils
-
-#endif  // CHROME_BROWSER_GTK_BOOKMARK_UTILS_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_utils_gtk_unittest.cc b/chrome/browser/gtk/bookmark_utils_gtk_unittest.cc
deleted file mode 100644
index be22a10..0000000
--- a/chrome/browser/gtk/bookmark_utils_gtk_unittest.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/gtk_dnd_util.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(BookmarkUtilsGtkTest, GetNodesFromSelectionInvalid) {
-  std::vector<const BookmarkNode*> nodes;
-  nodes = bookmark_utils::GetNodesFromSelection(NULL, NULL, 0, NULL, NULL,
-                                                NULL);
-  EXPECT_EQ(0u, nodes.size());
-
-  GtkSelectionData data;
-  data.data = NULL;
-  data.length = 0;
-  nodes = bookmark_utils::GetNodesFromSelection(NULL, &data, 0, NULL, NULL,
-                                                NULL);
-  EXPECT_EQ(0u, nodes.size());
-
-  nodes = bookmark_utils::GetNodesFromSelection(NULL, NULL,
-      gtk_dnd_util::CHROME_BOOKMARK_ITEM, NULL, NULL, NULL);
-  EXPECT_EQ(0u, nodes.size());
-
-  data.data = NULL;
-  data.length = 0;
-  nodes = bookmark_utils::GetNodesFromSelection(NULL, &data,
-      gtk_dnd_util::CHROME_BOOKMARK_ITEM, NULL, NULL, NULL);
-  EXPECT_EQ(0u, nodes.size());
-
-  guchar test_data[] = "";
-  data.data = test_data;
-  data.length = 0;
-  nodes = bookmark_utils::GetNodesFromSelection(NULL, &data,
-      gtk_dnd_util::CHROME_BOOKMARK_ITEM, NULL, NULL, NULL);
-  EXPECT_EQ(0u, nodes.size());
-}
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
deleted file mode 100644
index 93b126d..0000000
--- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
+++ /dev/null
@@ -1,945 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/browser_actions_toolbar_gtk.h"
-
-#include <vector>
-
-#include "base/i18n/rtl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/extensions/extension_browser_event_router.h"
-#include "chrome/browser/extensions/extension_context_menu_model.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/extension_popup_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/hover_controller_gtk.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_action.h"
-#include "chrome/common/extensions/extension_resource.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// The width of the browser action buttons.
-const int kButtonWidth = 27;
-
-// The padding between browser action buttons.
-const int kButtonPadding = 4;
-
-// The padding to the right of the browser action buttons (between the buttons
-// and chevron if they are both showing).
-const int kButtonChevronPadding = 2;
-
-// The padding to the left, top and bottom of the browser actions toolbar
-// separator.
-const int kSeparatorPadding = 2;
-
-// Width of the invisible gripper for resizing the toolbar.
-const int kResizeGripperWidth = 4;
-
-const char* kDragTarget = "application/x-chrome-browseraction";
-
-GtkTargetEntry GetDragTargetEntry() {
-  static std::string drag_target_string(kDragTarget);
-  GtkTargetEntry drag_target;
-  drag_target.target = const_cast<char*>(drag_target_string.c_str());
-  drag_target.flags = GTK_TARGET_SAME_APP;
-  drag_target.info = 0;
-  return drag_target;
-}
-
-// The minimum width in pixels of the button hbox if |icon_count| icons are
-// showing.
-gint WidthForIconCount(gint icon_count) {
-  return std::max((kButtonWidth + kButtonPadding) * icon_count - kButtonPadding,
-                  0);
-}
-
-}  // namespace
-
-using menus::SimpleMenuModel;
-
-class BrowserActionButton : public NotificationObserver,
-                            public ImageLoadingTracker::Observer,
-                            public ExtensionContextMenuModel::PopupDelegate,
-                            public MenuGtk::Delegate {
- public:
-  BrowserActionButton(BrowserActionsToolbarGtk* toolbar,
-                      const Extension* extension,
-                      GtkThemeProvider* theme_provider)
-      : toolbar_(toolbar),
-        extension_(extension),
-        image_(NULL),
-        tracker_(this),
-        tab_specific_icon_(NULL),
-        default_icon_(NULL) {
-    button_.reset(new CustomDrawButton(
-        theme_provider,
-        IDR_BROWSER_ACTION,
-        IDR_BROWSER_ACTION_P,
-        IDR_BROWSER_ACTION_H,
-        0,
-        NULL));
-    alignment_.Own(gtk_alignment_new(0, 0, 1, 1));
-    gtk_container_add(GTK_CONTAINER(alignment_.get()), button());
-    gtk_widget_show(button());
-
-    DCHECK(extension_->browser_action());
-
-    UpdateState();
-
-    // The Browser Action API does not allow the default icon path to be
-    // changed at runtime, so we can load this now and cache it.
-    std::string path = extension_->browser_action()->default_icon_path();
-    if (!path.empty()) {
-      tracker_.LoadImage(extension_, extension_->GetResource(path),
-                         gfx::Size(Extension::kBrowserActionIconMaxSize,
-                                   Extension::kBrowserActionIconMaxSize),
-                         ImageLoadingTracker::DONT_CACHE);
-    }
-
-    signals_.Connect(button(), "button-press-event",
-                     G_CALLBACK(OnButtonPress), this);
-    signals_.Connect(button(), "clicked",
-                     G_CALLBACK(OnClicked), this);
-    signals_.Connect(button(), "drag-begin",
-                     G_CALLBACK(&OnDragBegin), this);
-    signals_.ConnectAfter(widget(), "expose-event",
-                          G_CALLBACK(OnExposeEvent), this);
-
-    registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
-                   Source<ExtensionAction>(extension->browser_action()));
-  }
-
-  ~BrowserActionButton() {
-    if (tab_specific_icon_)
-      g_object_unref(tab_specific_icon_);
-
-    if (default_icon_)
-      g_object_unref(default_icon_);
-
-    alignment_.Destroy();
-  }
-
-  GtkWidget* button() { return button_->widget(); }
-
-  GtkWidget* widget() { return alignment_.get(); }
-
-  const Extension* extension() { return extension_; }
-
-  // NotificationObserver implementation.
-  void Observe(NotificationType type,
-               const NotificationSource& source,
-               const NotificationDetails& details) {
-    if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED)
-      UpdateState();
-    else
-      NOTREACHED();
-  }
-
-  // ImageLoadingTracker::Observer implementation.
-  void OnImageLoaded(SkBitmap* image, ExtensionResource resource, int index) {
-    if (image) {
-      default_skbitmap_ = *image;
-      default_icon_ = gfx::GdkPixbufFromSkBitmap(image);
-    }
-    UpdateState();
-  }
-
-  // Updates the button based on the latest state from the associated
-  // browser action.
-  void UpdateState() {
-    int tab_id = toolbar_->GetCurrentTabId();
-    if (tab_id < 0)
-      return;
-
-    std::string tooltip = extension_->browser_action()->GetTitle(tab_id);
-    if (tooltip.empty())
-      gtk_widget_set_has_tooltip(button(), FALSE);
-    else
-      gtk_widget_set_tooltip_text(button(), tooltip.c_str());
-
-    SkBitmap image = extension_->browser_action()->GetIcon(tab_id);
-    if (!image.isNull()) {
-      GdkPixbuf* previous_gdk_icon = tab_specific_icon_;
-      tab_specific_icon_ = gfx::GdkPixbufFromSkBitmap(&image);
-      SetImage(tab_specific_icon_);
-      if (previous_gdk_icon)
-        g_object_unref(previous_gdk_icon);
-    } else if (default_icon_) {
-      SetImage(default_icon_);
-    }
-    gtk_widget_queue_draw(button());
-  }
-
-  SkBitmap GetIcon() {
-    const SkBitmap& image = extension_->browser_action()->GetIcon(
-        toolbar_->GetCurrentTabId());
-    if (!image.isNull()) {
-      return image;
-    } else {
-      return default_skbitmap_;
-    }
-  }
-
-  MenuGtk* GetContextMenu() {
-    context_menu_model_ =
-        new ExtensionContextMenuModel(extension_, toolbar_->browser(), this);
-    context_menu_.reset(
-        new MenuGtk(this, context_menu_model_.get()));
-    return context_menu_.get();
-  }
-
- private:
-  // MenuGtk::Delegate implementation.
-  virtual void StoppedShowing() {
-    button_->UnsetPaintOverride();
-
-    // If the context menu was showing for the overflow menu, re-assert the
-    // grab that was shadowed.
-    if (toolbar_->overflow_menu_.get())
-      gtk_util::GrabAllInput(toolbar_->overflow_menu_->widget());
-  }
-
-  virtual void CommandWillBeExecuted() {
-    // If the context menu was showing for the overflow menu, and a command
-    // is executed, then stop showing the overflow menu.
-    if (toolbar_->overflow_menu_.get())
-      toolbar_->overflow_menu_->Cancel();
-  }
-
-  // Returns true to prevent further processing of the event that caused us to
-  // show the popup, or false to continue processing.
-  bool ShowPopup(bool devtools) {
-    ExtensionAction* browser_action = extension_->browser_action();
-
-    int tab_id = toolbar_->GetCurrentTabId();
-    if (tab_id < 0) {
-      NOTREACHED() << "No current tab.";
-      return true;
-    }
-
-    if (browser_action->HasPopup(tab_id)) {
-      ExtensionPopupGtk::Show(
-          browser_action->GetPopupUrl(tab_id), toolbar_->browser(),
-          widget(), devtools);
-      return true;
-    }
-
-    return false;
-  }
-
-  // ExtensionContextMenuModel::PopupDelegate implementation.
-  virtual void InspectPopup(ExtensionAction* action) {
-    ShowPopup(true);
-  }
-
-  void SetImage(GdkPixbuf* image) {
-    if (!image_) {
-      image_ = gtk_image_new_from_pixbuf(image);
-      gtk_button_set_image(GTK_BUTTON(button()), image_);
-    } else {
-      gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image);
-    }
-  }
-
-  static gboolean OnButtonPress(GtkWidget* widget,
-                                GdkEvent* event,
-                                BrowserActionButton* action) {
-    if (event->button.button != 3)
-      return FALSE;
-
-    action->button_->SetPaintOverride(GTK_STATE_ACTIVE);
-    action->GetContextMenu()->Popup(widget, event);
-
-    return TRUE;
-  }
-
-  static void OnClicked(GtkWidget* widget, BrowserActionButton* action) {
-    if (action->ShowPopup(false))
-      return;
-
-    ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
-        action->toolbar_->browser()->profile(), action->extension_->id(),
-        action->toolbar_->browser());
-  }
-
-  static gboolean OnExposeEvent(GtkWidget* widget,
-                                GdkEventExpose* event,
-                                BrowserActionButton* button) {
-    int tab_id = button->toolbar_->GetCurrentTabId();
-    if (tab_id < 0)
-      return FALSE;
-
-    ExtensionAction* action = button->extension_->browser_action();
-    if (action->GetBadgeText(tab_id).empty())
-      return FALSE;
-
-    gfx::CanvasSkiaPaint canvas(event, false);
-    gfx::Rect bounding_rect(widget->allocation);
-    action->PaintBadge(&canvas, bounding_rect, tab_id);
-    return FALSE;
-  }
-
-  static void OnDragBegin(GtkWidget* widget,
-                          GdkDragContext* drag_context,
-                          BrowserActionButton* button) {
-    // Simply pass along the notification to the toolbar. The point of this
-    // function is to tell the toolbar which BrowserActionButton initiated the
-    // drag.
-    button->toolbar_->DragStarted(button, drag_context);
-  }
-
-  // The toolbar containing this button.
-  BrowserActionsToolbarGtk* toolbar_;
-
-  // The extension that contains this browser action.
-  const Extension* extension_;
-
-  // The button for this browser action.
-  scoped_ptr<CustomDrawButton> button_;
-
-  // The top level widget (parent of |button_|).
-  OwnedWidgetGtk alignment_;
-
-  // The one image subwidget in |button_|. We keep this out so we don't alter
-  // the widget hierarchy while changing the button image because changing the
-  // GTK widget hierarchy invalidates all tooltips and several popular
-  // extensions change browser action icon in a loop.
-  GtkWidget* image_;
-
-  // Loads the button's icons for us on the file thread.
-  ImageLoadingTracker tracker_;
-
-  // If we are displaying a tab-specific icon, it will be here.
-  GdkPixbuf* tab_specific_icon_;
-
-  // If the browser action has a default icon, it will be here.
-  GdkPixbuf* default_icon_;
-
-  // Same as |default_icon_|, but stored as SkBitmap.
-  SkBitmap default_skbitmap_;
-
-  GtkSignalRegistrar signals_;
-  NotificationRegistrar registrar_;
-
-  // The context menu view and model for this extension action.
-  scoped_ptr<MenuGtk> context_menu_;
-  scoped_refptr<ExtensionContextMenuModel> context_menu_model_;
-
-  friend class BrowserActionsToolbarGtk;
-};
-
-// BrowserActionsToolbarGtk ----------------------------------------------------
-
-BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser)
-    : browser_(browser),
-      profile_(browser->profile()),
-      theme_provider_(GtkThemeProvider::GetFrom(browser->profile())),
-      model_(NULL),
-      hbox_(gtk_hbox_new(FALSE, 0)),
-      button_hbox_(gtk_chrome_shrinkable_hbox_new(TRUE, FALSE, kButtonPadding)),
-      drag_button_(NULL),
-      drop_index_(-1),
-      resize_animation_(this),
-      desired_width_(0),
-      start_width_(0),
-      method_factory_(this) {
-  ExtensionService* extension_service = profile_->GetExtensionService();
-  // The |extension_service| can be NULL in Incognito.
-  if (!extension_service)
-    return;
-
- overflow_button_.reset(new CustomDrawButton(
-      theme_provider_,
-      IDR_BROWSER_ACTIONS_OVERFLOW,
-      IDR_BROWSER_ACTIONS_OVERFLOW_P,
-      IDR_BROWSER_ACTIONS_OVERFLOW_H,
-      0,
-      gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)));
-
-  GtkWidget* gripper = gtk_button_new();
-  gtk_widget_set_size_request(gripper, kResizeGripperWidth, -1);
-  GTK_WIDGET_UNSET_FLAGS(gripper, GTK_CAN_FOCUS);
-  gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK);
-  signals_.Connect(gripper, "motion-notify-event",
-                   G_CALLBACK(OnGripperMotionNotifyThunk), this);
-  signals_.Connect(gripper, "expose-event",
-                   G_CALLBACK(OnGripperExposeThunk), this);
-  signals_.Connect(gripper, "enter-notify-event",
-                   G_CALLBACK(OnGripperEnterNotifyThunk), this);
-  signals_.Connect(gripper, "leave-notify-event",
-                   G_CALLBACK(OnGripperLeaveNotifyThunk), this);
-  signals_.Connect(gripper, "button-release-event",
-                   G_CALLBACK(OnGripperButtonReleaseThunk), this);
-  signals_.Connect(gripper, "button-press-event",
-                   G_CALLBACK(OnGripperButtonPressThunk), this);
-  signals_.Connect(chevron(), "button-press-event",
-                   G_CALLBACK(OnOverflowButtonPressThunk), this);
-
-  // |overflow_alignment| adds padding to the right of the browser action
-  // buttons, but only appears when the overflow menu is showing.
-  overflow_alignment_ = gtk_alignment_new(0, 0, 1, 1);
-  gtk_container_add(GTK_CONTAINER(overflow_alignment_), chevron());
-
-  // |overflow_area_| holds the overflow chevron and the separator, which
-  // is only shown in GTK+ theme mode.
-  overflow_area_ = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(overflow_area_), overflow_alignment_,
-                     FALSE, FALSE, 0);
-
-  separator_ = gtk_vseparator_new();
-  gtk_box_pack_start(GTK_BOX(overflow_area_), separator_,
-                     FALSE, FALSE, 0);
-  gtk_widget_set_no_show_all(separator_, TRUE);
-
-  gtk_widget_show_all(overflow_area_);
-  gtk_widget_set_no_show_all(overflow_area_, TRUE);
-
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_area_, FALSE, FALSE, 0);
-
-  model_ = extension_service->toolbar_model();
-  model_->AddObserver(this);
-  SetupDrags();
-
-  if (model_->extensions_initialized()) {
-    CreateAllButtons();
-    SetContainerWidth();
-  }
-
-  // We want to connect to "set-focus" on the toplevel window; we have to wait
-  // until we are added to a toplevel window to do so.
-  signals_.Connect(widget(), "hierarchy-changed",
-                   G_CALLBACK(OnHierarchyChangedThunk), this);
-
-  ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR);
-
-  registrar_.Add(this,
-                 NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_->InitThemesFor(this);
-}
-
-BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() {
-  if (model_)
-    model_->RemoveObserver(this);
-  button_hbox_.Destroy();
-  hbox_.Destroy();
-}
-
-int BrowserActionsToolbarGtk::GetCurrentTabId() {
-  TabContents* selected_tab = browser_->GetSelectedTabContents();
-  if (!selected_tab)
-    return -1;
-
-  return selected_tab->controller().session_id().id();
-}
-
-void BrowserActionsToolbarGtk::Update() {
-  for (ExtensionButtonMap::iterator iter = extension_button_map_.begin();
-       iter != extension_button_map_.end(); ++iter) {
-    iter->second->UpdateState();
-  }
-}
-
-void BrowserActionsToolbarGtk::Observe(NotificationType type,
-                                       const NotificationSource& source,
-                                       const NotificationDetails& details) {
-  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
-  if (theme_provider_->UseGtkTheme())
-    gtk_widget_show(separator_);
-  else
-    gtk_widget_hide(separator_);
-}
-
-void BrowserActionsToolbarGtk::SetupDrags() {
-  GtkTargetEntry drag_target = GetDragTargetEntry();
-  gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1,
-                    GDK_ACTION_MOVE);
-
-  signals_.Connect(button_hbox_.get(), "drag-motion",
-                   G_CALLBACK(OnDragMotionThunk), this);
-}
-
-void BrowserActionsToolbarGtk::CreateAllButtons() {
-  extension_button_map_.clear();
-
-  int i = 0;
-  for (ExtensionList::iterator iter = model_->begin();
-       iter != model_->end(); ++iter) {
-    CreateButtonForExtension(*iter, i++);
-  }
-}
-
-void BrowserActionsToolbarGtk::SetContainerWidth() {
-  int showing_actions = model_->GetVisibleIconCount();
-  if (showing_actions >= 0)
-    SetButtonHBoxWidth(WidthForIconCount(showing_actions));
-}
-
-void BrowserActionsToolbarGtk::CreateButtonForExtension(
-    const Extension* extension, int index) {
-  if (!ShouldDisplayBrowserAction(extension))
-    return;
-
-  if (profile_->IsOffTheRecord())
-    index = model_->OriginalIndexToIncognito(index);
-
-  RemoveButtonForExtension(extension);
-  linked_ptr<BrowserActionButton> button(
-      new BrowserActionButton(this, extension, theme_provider_));
-  gtk_chrome_shrinkable_hbox_pack_start(
-      GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0);
-  gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index);
-  extension_button_map_[extension->id()] = button;
-
-  GtkTargetEntry drag_target = GetDragTargetEntry();
-  gtk_drag_source_set(button->button(), GDK_BUTTON1_MASK, &drag_target, 1,
-                      GDK_ACTION_MOVE);
-  // We ignore whether the drag was a "success" or "failure" in Gtk's opinion.
-  signals_.Connect(button->button(), "drag-end",
-                   G_CALLBACK(&OnDragEndThunk), this);
-  signals_.Connect(button->button(), "drag-failed",
-                   G_CALLBACK(&OnDragFailedThunk), this);
-
-  // Any time a browser action button is shown or hidden we have to update
-  // the chevron state.
-  signals_.Connect(button->widget(), "show",
-                   G_CALLBACK(&OnButtonShowOrHideThunk), this);
-  signals_.Connect(button->widget(), "hide",
-                   G_CALLBACK(&OnButtonShowOrHideThunk), this);
-
-  gtk_widget_show(button->widget());
-
-  UpdateVisibility();
-}
-
-GtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget(
-    const Extension* extension) {
-  ExtensionButtonMap::iterator it = extension_button_map_.find(
-      extension->id());
-  if (it == extension_button_map_.end())
-    return NULL;
-
-  return it->second.get()->widget();
-}
-
-void BrowserActionsToolbarGtk::RemoveButtonForExtension(
-    const Extension* extension) {
-  if (extension_button_map_.erase(extension->id()))
-    UpdateVisibility();
-  UpdateChevronVisibility();
-}
-
-void BrowserActionsToolbarGtk::UpdateVisibility() {
-  if (button_count() == 0)
-    gtk_widget_hide(widget());
-  else
-    gtk_widget_show(widget());
-}
-
-bool BrowserActionsToolbarGtk::ShouldDisplayBrowserAction(
-    const Extension* extension) {
-  // Only display incognito-enabled extensions while in incognito mode.
-  return (!profile_->IsOffTheRecord() ||
-          profile_->GetExtensionService()->IsIncognitoEnabled(extension));
-}
-
-void BrowserActionsToolbarGtk::HidePopup() {
-  ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup();
-  if (popup)
-    popup->DestroyPopup();
-}
-
-void BrowserActionsToolbarGtk::AnimateToShowNIcons(int count) {
-  desired_width_ = WidthForIconCount(count);
-  start_width_ = button_hbox_->allocation.width;
-  resize_animation_.Reset();
-  resize_animation_.Show();
-}
-
-void BrowserActionsToolbarGtk::BrowserActionAdded(const Extension* extension,
-                                                  int index) {
-  overflow_menu_.reset();
-
-  CreateButtonForExtension(extension, index);
-
-  // If we are still initializing the container, don't bother animating.
-  if (!model_->extensions_initialized())
-    return;
-
-  // Animate the addition if we are showing all browser action buttons.
-  if (!GTK_WIDGET_VISIBLE(overflow_area_)) {
-    AnimateToShowNIcons(button_count());
-    model_->SetVisibleIconCount(button_count());
-  }
-}
-
-void BrowserActionsToolbarGtk::BrowserActionRemoved(
-    const Extension* extension) {
-  overflow_menu_.reset();
-
-  if (drag_button_ != NULL) {
-    // Break the current drag.
-    gtk_grab_remove(button_hbox_.get());
-  }
-
-  RemoveButtonForExtension(extension);
-
-  if (!GTK_WIDGET_VISIBLE(overflow_area_)) {
-    AnimateToShowNIcons(button_count());
-    model_->SetVisibleIconCount(button_count());
-  }
-}
-
-void BrowserActionsToolbarGtk::BrowserActionMoved(const Extension* extension,
-                                                  int index) {
-  // We initiated this move action, and have already moved the button.
-  if (drag_button_ != NULL)
-    return;
-
-  GtkWidget* button_widget = GetBrowserActionWidget(extension);
-  if (!button_widget) {
-    if (ShouldDisplayBrowserAction(extension))
-      NOTREACHED();
-    return;
-  }
-
-  if (profile_->IsOffTheRecord())
-    index = model_->OriginalIndexToIncognito(index);
-
-  gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button_widget, index);
-}
-
-void BrowserActionsToolbarGtk::ModelLoaded() {
-  SetContainerWidth();
-}
-
-void BrowserActionsToolbarGtk::AnimationProgressed(
-    const ui::Animation* animation) {
-  int width = start_width_ + (desired_width_ - start_width_) *
-      animation->GetCurrentValue();
-  gtk_widget_set_size_request(button_hbox_.get(), width, -1);
-
-  if (width == desired_width_)
-    resize_animation_.Reset();
-}
-
-void BrowserActionsToolbarGtk::AnimationEnded(const ui::Animation* animation) {
-  gtk_widget_set_size_request(button_hbox_.get(), desired_width_, -1);
-  UpdateChevronVisibility();
-}
-
-bool BrowserActionsToolbarGtk::IsCommandIdChecked(int command_id) const {
-  return false;
-}
-
-bool BrowserActionsToolbarGtk::IsCommandIdEnabled(int command_id) const {
-  return true;
-}
-
-bool BrowserActionsToolbarGtk::GetAcceleratorForCommandId(
-    int command_id,
-    menus::Accelerator* accelerator) {
-  return false;
-}
-
-void BrowserActionsToolbarGtk::ExecuteCommand(int command_id) {
-  const Extension* extension = model_->GetExtensionByIndex(command_id);
-  ExtensionAction* browser_action = extension->browser_action();
-
-  int tab_id = GetCurrentTabId();
-  if (tab_id < 0) {
-    NOTREACHED() << "No current tab.";
-    return;
-  }
-
-  if (browser_action->HasPopup(tab_id)) {
-    ExtensionPopupGtk::Show(
-        browser_action->GetPopupUrl(tab_id), browser(),
-        chevron(),
-        false);
-  } else {
-    ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
-        browser()->profile(), extension->id(), browser());
-  }
-}
-
-void BrowserActionsToolbarGtk::StoppedShowing() {
-  overflow_button_->UnsetPaintOverride();
-}
-
-bool BrowserActionsToolbarGtk::AlwaysShowIconForCmd(int command_id) const {
-  return true;
-}
-
-void BrowserActionsToolbarGtk::DragStarted(BrowserActionButton* button,
-                                           GdkDragContext* drag_context) {
-  // No representation of the widget following the cursor.
-  GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
-  gtk_drag_set_icon_pixbuf(drag_context, pixbuf, 0, 0);
-  g_object_unref(pixbuf);
-
-  DCHECK(!drag_button_);
-  drag_button_ = button;
-}
-
-void BrowserActionsToolbarGtk::SetButtonHBoxWidth(int new_width) {
-  gint max_width = WidthForIconCount(button_count());
-  new_width = std::min(max_width, new_width);
-  new_width = std::max(new_width, 0);
-  gtk_widget_set_size_request(button_hbox_.get(), new_width, -1);
-}
-
-void BrowserActionsToolbarGtk::UpdateChevronVisibility() {
-  int showing_icon_count =
-      gtk_chrome_shrinkable_hbox_get_visible_child_count(
-          GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
-  if (showing_icon_count == 0) {
-    gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0, 0, 0);
-  } else {
-    gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0,
-                              kButtonChevronPadding, 0);
-  }
-
-  if (button_count() > showing_icon_count) {
-    if (!GTK_WIDGET_VISIBLE(overflow_area_)) {
-      if (drag_button_) {
-        // During drags, when the overflow chevron shows for the first time,
-        // take that much space away from |button_hbox_| to make the drag look
-        // smoother.
-        GtkRequisition req;
-        gtk_widget_size_request(chevron(), &req);
-        gint overflow_width = req.width;
-        gtk_widget_size_request(button_hbox_.get(), &req);
-        gint button_hbox_width = req.width;
-        button_hbox_width = std::max(button_hbox_width - overflow_width, 0);
-        gtk_widget_set_size_request(button_hbox_.get(), button_hbox_width, -1);
-      }
-
-      gtk_widget_show(overflow_area_);
-    }
-  } else {
-    gtk_widget_hide(overflow_area_);
-  }
-}
-
-gboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget,
-                                                GdkDragContext* drag_context,
-                                                gint x, gint y, guint time) {
-  // Only handle drags we initiated.
-  if (!drag_button_)
-    return FALSE;
-
-  if (base::i18n::IsRTL())
-    x = widget->allocation.width - x;
-  drop_index_ = x < kButtonWidth ? 0 : x / (kButtonWidth + kButtonPadding);
-
-  // We will go ahead and reorder the child in order to provide visual feedback
-  // to the user. We don't inform the model that it has moved until the drag
-  // ends.
-  gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), drag_button_->widget(),
-                        drop_index_);
-
-  gdk_drag_status(drag_context, GDK_ACTION_MOVE, time);
-  return TRUE;
-}
-
-void BrowserActionsToolbarGtk::OnDragEnd(GtkWidget* button,
-                                         GdkDragContext* drag_context) {
-  if (drop_index_ != -1) {
-    if (profile_->IsOffTheRecord())
-      drop_index_ = model_->IncognitoIndexToOriginal(drop_index_);
-
-    model_->MoveBrowserAction(drag_button_->extension(), drop_index_);
-  }
-
-  drag_button_ = NULL;
-  drop_index_ = -1;
-}
-
-gboolean BrowserActionsToolbarGtk::OnDragFailed(GtkWidget* widget,
-                                                GdkDragContext* drag_context,
-                                                GtkDragResult result) {
-  // We connect to this signal and return TRUE so that the default failure
-  // animation (wherein the drag widget floats back to the start of the drag)
-  // does not show, and the drag-end signal is emitted immediately instead of
-  // several seconds later.
-  return TRUE;
-}
-
-void BrowserActionsToolbarGtk::OnHierarchyChanged(
-    GtkWidget* widget, GtkWidget* previous_toplevel) {
-  GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
-  if (!GTK_WIDGET_TOPLEVEL(toplevel))
-    return;
-
-  signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this);
-}
-
-void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget,
-                                          GtkWidget* focus_widget) {
-  ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup();
-  // The focus of the parent window has changed. Close the popup. Delay the hide
-  // because it will destroy the RenderViewHost, which may still be on the
-  // call stack.
-  if (!popup || popup->being_inspected())
-    return;
-  MessageLoop::current()->PostTask(FROM_HERE,
-      method_factory_.NewRunnableMethod(&BrowserActionsToolbarGtk::HidePopup));
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperMotionNotify(
-    GtkWidget* widget, GdkEventMotion* event) {
-  if (!(event->state & GDK_BUTTON1_MASK))
-    return FALSE;
-
-  // Calculate how much the user dragged the gripper and subtract that off the
-  // button container's width.
-  int distance_dragged = base::i18n::IsRTL() ?
-      -event->x :
-      event->x - widget->allocation.width;
-  gint new_width = button_hbox_->allocation.width - distance_dragged;
-  SetButtonHBoxWidth(new_width);
-
-  return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperExpose(GtkWidget* gripper,
-                                                   GdkEventExpose* expose) {
-  return TRUE;
-}
-
-// These three signal handlers (EnterNotify, LeaveNotify, and ButtonRelease)
-// are used to give the gripper the resize cursor. Since it doesn't have its
-// own window, we have to set the cursor whenever the pointer moves into the
-// button or leaves the button, and be sure to leave it on when the user is
-// dragging.
-gboolean BrowserActionsToolbarGtk::OnGripperEnterNotify(
-    GtkWidget* gripper, GdkEventCrossing* event) {
-  gdk_window_set_cursor(gripper->window,
-                        gfx::GetCursor(GDK_SB_H_DOUBLE_ARROW));
-  return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperLeaveNotify(
-    GtkWidget* gripper, GdkEventCrossing* event) {
-  if (!(event->state & GDK_BUTTON1_MASK))
-    gdk_window_set_cursor(gripper->window, NULL);
-  return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperButtonRelease(
-    GtkWidget* gripper, GdkEventButton* event) {
-  gfx::Rect gripper_rect(0, 0,
-                         gripper->allocation.width, gripper->allocation.height);
-  gfx::Point release_point(event->x, event->y);
-  if (!gripper_rect.Contains(release_point))
-    gdk_window_set_cursor(gripper->window, NULL);
-
-  // After the user resizes the toolbar, we want to smartly resize it to be
-  // the perfect size to fit the buttons.
-  int visible_icon_count =
-      gtk_chrome_shrinkable_hbox_get_visible_child_count(
-          GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
-  AnimateToShowNIcons(visible_icon_count);
-  model_->SetVisibleIconCount(visible_icon_count);
-
-  return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperButtonPress(
-    GtkWidget* gripper, GdkEventButton* event) {
-  resize_animation_.Reset();
-
-  return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnOverflowButtonPress(
-    GtkWidget* overflow, GdkEventButton* event) {
-  overflow_menu_model_.reset(new SimpleMenuModel(this));
-
-  int visible_icon_count =
-      gtk_chrome_shrinkable_hbox_get_visible_child_count(
-          GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
-  for (int i = visible_icon_count; i < button_count(); ++i) {
-    int model_index = i;
-    if (profile_->IsOffTheRecord())
-      model_index = model_->IncognitoIndexToOriginal(i);
-
-    const Extension* extension = model_->GetExtensionByIndex(model_index);
-    BrowserActionButton* button = extension_button_map_[extension->id()].get();
-
-    overflow_menu_model_->AddItem(model_index, UTF8ToUTF16(extension->name()));
-    overflow_menu_model_->SetIcon(overflow_menu_model_->GetItemCount() - 1,
-                                  button->GetIcon());
-
-    // TODO(estade): set the menu item's tooltip.
-  }
-
-  overflow_menu_.reset(new MenuGtk(this, overflow_menu_model_.get()));
-  signals_.Connect(overflow_menu_->widget(), "button-press-event",
-                   G_CALLBACK(OnOverflowMenuButtonPressThunk), this);
-
-  overflow_button_->SetPaintOverride(GTK_STATE_ACTIVE);
-  overflow_menu_->PopupAsFromKeyEvent(chevron());
-
-  return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress(
-    GtkWidget* overflow, GdkEventButton* event) {
-  if (event->button != 3)
-    return FALSE;
-
-  GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item;
-  if (!menu_item)
-    return FALSE;
-
-  int item_index = g_list_index(GTK_MENU_SHELL(overflow)->children, menu_item);
-  if (item_index == -1) {
-    NOTREACHED();
-    return FALSE;
-  }
-
-  item_index += gtk_chrome_shrinkable_hbox_get_visible_child_count(
-      GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
-  if (profile_->IsOffTheRecord())
-    item_index = model_->IncognitoIndexToOriginal(item_index);
-
-  const Extension* extension = model_->GetExtensionByIndex(item_index);
-  ExtensionButtonMap::iterator it = extension_button_map_.find(
-      extension->id());
-  if (it == extension_button_map_.end()) {
-    NOTREACHED();
-    return FALSE;
-  }
-
-  it->second.get()->GetContextMenu()->PopupAsContext(event->time);
-  return TRUE;
-}
-
-void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) {
-  if (!resize_animation_.is_animating())
-    UpdateChevronVisibility();
-}
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/gtk/browser_actions_toolbar_gtk.h
deleted file mode 100644
index 4d49416..0000000
--- a/chrome/browser/gtk/browser_actions_toolbar_gtk.h
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BROWSER_ACTIONS_TOOLBAR_GTK_H_
-#define CHROME_BROWSER_GTK_BROWSER_ACTIONS_TOOLBAR_GTK_H_
-#pragma once
-
-#include <map>
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "app/menus/simple_menu_model.h"
-#include "base/linked_ptr.h"
-#include "base/task.h"
-#include "chrome/browser/extensions/extension_toolbar_model.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/overflow_button.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-
-class Browser;
-class BrowserActionButton;
-class Extension;
-class GtkThemeProvider;
-class Profile;
-
-typedef struct _GdkDragContext GdkDragContext;
-typedef struct _GtkWidget GtkWidget;
-
-class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer,
-                                 public ui::AnimationDelegate,
-                                 public MenuGtk::Delegate,
-                                 public menus::SimpleMenuModel::Delegate,
-                                 public NotificationObserver {
- public:
-  explicit BrowserActionsToolbarGtk(Browser* browser);
-  virtual ~BrowserActionsToolbarGtk();
-
-  GtkWidget* widget() { return hbox_.get(); }
-  GtkWidget* chevron() { return overflow_button_->widget(); }
-
-  // Returns the widget in use by the BrowserActionButton corresponding to
-  // |extension|. Used in positioning the ExtensionInstalledBubble for
-  // BrowserActions.
-  GtkWidget* GetBrowserActionWidget(const Extension* extension);
-
-  int button_count() { return extension_button_map_.size(); }
-
-  Browser* browser() { return browser_; }
-
-  // Returns the currently selected tab ID, or -1 if there is none.
-  int GetCurrentTabId();
-
-  // Update the display of all buttons.
-  void Update();
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  bool animating() {
-    return resize_animation_.is_animating();
-  }
-
- private:
-  friend class BrowserActionButton;
-
-  // Initialize drag and drop.
-  void SetupDrags();
-
-  // Query the extensions service for all extensions with browser actions,
-  // and create the UI for them.
-  void CreateAllButtons();
-
-  // Sets the width of the container and overflow state according to the model.
-  void SetContainerWidth();
-
-  // Create the UI for a single browser action. This will stick the button
-  // at the end of the toolbar.
-  void CreateButtonForExtension(const Extension* extension, int index);
-
-  // Delete resources associated with UI for a browser action.
-  void RemoveButtonForExtension(const Extension* extension);
-
-  // Change the visibility of widget() based on whether we have any buttons
-  // to show.
-  void UpdateVisibility();
-
-  // Hide the extension popup, if any.
-  void HidePopup();
-
-  // Animate the toolbar to show the given number of icons. This assumes the
-  // visibility of the overflow button will not change.
-  void AnimateToShowNIcons(int count);
-
-  // Returns true if this extension should be shown in this toolbar. This can
-  // return false if we are in an incognito window and the extension is disabled
-  // for incognito.
-  bool ShouldDisplayBrowserAction(const Extension* extension);
-
-  // ExtensionToolbarModel::Observer implementation.
-  virtual void BrowserActionAdded(const Extension* extension, int index);
-  virtual void BrowserActionRemoved(const Extension* extension);
-  virtual void BrowserActionMoved(const Extension* extension, int index);
-  virtual void ModelLoaded();
-
-  // ui::AnimationDelegate implementation.
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-
-  // SimpleMenuModel::Delegate implementation.
-  // In our case, |command_id| is be the index into the model's extension list.
-  virtual bool IsCommandIdChecked(int command_id) const;
-  virtual bool IsCommandIdEnabled(int command_id) const;
-  virtual bool GetAcceleratorForCommandId(
-      int command_id,
-      menus::Accelerator* accelerator);
-  virtual void ExecuteCommand(int command_id);
-
-  // MenuGtk::Delegate implementation.
-  virtual void StoppedShowing();
-  virtual bool AlwaysShowIconForCmd(int command_id) const;
-
-  // Called by the BrowserActionButton in response to drag-begin.
-  void DragStarted(BrowserActionButton* button, GdkDragContext* drag_context);
-
-  // Sets the width of the button area of the toolbar to |new_width|, clamping
-  // it to appropriate values.
-  void SetButtonHBoxWidth(int new_width);
-
-  // Shows or hides the chevron as appropriate.
-  void UpdateChevronVisibility();
-
-  CHROMEGTK_CALLBACK_4(BrowserActionsToolbarGtk, gboolean, OnDragMotion,
-                       GdkDragContext*, gint, gint, guint);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, void, OnDragEnd,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_2(BrowserActionsToolbarGtk, gboolean, OnDragFailed,
-                       GdkDragContext*, GtkDragResult);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, void, OnHierarchyChanged,
-                       GtkWidget*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, void, OnSetFocus, GtkWidget*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnGripperMotionNotify, GdkEventMotion*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean, OnGripperExpose,
-                       GdkEventExpose*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnGripperEnterNotify, GdkEventCrossing*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnGripperLeaveNotify, GdkEventCrossing*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnGripperButtonRelease, GdkEventButton*);
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnGripperButtonPress, GdkEventButton*);
-  // The overflow button is pressed.
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnOverflowButtonPress, GdkEventButton*);
-  // The user presses a mouse button over the popped up overflow menu.
-  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
-                       OnOverflowMenuButtonPress, GdkEventButton*);
-  CHROMEGTK_CALLBACK_0(BrowserActionsToolbarGtk, void, OnButtonShowOrHide);
-
-  Browser* browser_;
-
-  Profile* profile_;
-  GtkThemeProvider* theme_provider_;
-
-  ExtensionToolbarModel* model_;
-
-  // Contains the drag gripper, browser action buttons, and overflow chevron.
-  OwnedWidgetGtk hbox_;
-
-  // Contains the browser action buttons.
-  OwnedWidgetGtk button_hbox_;
-
-  // The overflow button for chrome theme mode.
-  scoped_ptr<CustomDrawButton> overflow_button_;
-  // The separator just next to the overflow button. Only shown in GTK+ theme
-  // mode. In Chrome theme mode, the overflow button has a separator built in.
-  GtkWidget* separator_;
-  scoped_ptr<MenuGtk> overflow_menu_;
-  scoped_ptr<menus::SimpleMenuModel> overflow_menu_model_;
-  GtkWidget* overflow_area_;
-  // A widget for adding extra padding to the left of the overflow button.
-  GtkWidget* overflow_alignment_;
-
-  // The button that is currently being dragged, or NULL.
-  BrowserActionButton* drag_button_;
-
-  // The new position of the button in the drag, or -1.
-  int drop_index_;
-
-  // Map from extension ID to BrowserActionButton, which is a wrapper for
-  // a chrome button and related functionality. There should be one entry
-  // for every extension that has a browser action.
-  typedef std::map<std::string, linked_ptr<BrowserActionButton> >
-      ExtensionButtonMap;
-  ExtensionButtonMap extension_button_map_;
-
-  // We use this animation for the smart resizing of the toolbar.
-  ui::SlideAnimation resize_animation_;
-  // This is the final width we are animating towards.
-  int desired_width_;
-  // This is the width we were at when we started animating.
-  int start_width_;
-
-  GtkSignalRegistrar signals_;
-
-  NotificationRegistrar registrar_;
-
-  ScopedRunnableMethodFactory<BrowserActionsToolbarGtk> method_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserActionsToolbarGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BROWSER_ACTIONS_TOOLBAR_GTK_H_
diff --git a/chrome/browser/gtk/browser_titlebar.cc b/chrome/browser/gtk/browser_titlebar.cc
deleted file mode 100644
index 7af5a5e..0000000
--- a/chrome/browser/gtk/browser_titlebar.cc
+++ /dev/null
@@ -1,948 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/browser_titlebar.h"
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/command_line.h"
-#include "base/singleton.h"
-#include "base/string_piece.h"
-#include "base/string_tokenizer.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gtk/accelerators_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/custom_button.h"
-#if defined(USE_GCONF)
-#include "chrome/browser/gtk/gconf_titlebar_listener.h"
-#endif
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/nine_box.h"
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
-#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/gtk_util.h"
-#include "gfx/skbitmap_operations.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// The space above the titlebars.
-const int kTitlebarHeight = 14;
-
-// The thickness in pixels of the tab border.
-const int kTabOuterThickness = 1;
-
-// Amount to offset the tab images relative to the background.
-const int kNormalVerticalOffset = kTitlebarHeight + kTabOuterThickness;
-
-// A linux specific menu item for toggling window decorations.
-const int kShowWindowDecorationsCommand = 200;
-
-const int kOTRBottomSpacing = 1;
-// There are 2 px on each side of the OTR avatar (between the frame border and
-// it on the left, and between it and the tabstrip on the right).
-const int kOTRSideSpacing = 2;
-
-// The thickness of the custom frame border; we need it here to enlarge the
-// close button whent the custom frame border isn't showing but the custom
-// titlebar is showing.
-const int kFrameBorderThickness = 4;
-
-// There is a 4px gap between the icon and the title text.
-const int kIconTitleSpacing = 4;
-
-// Padding around the icon when in app mode or popup mode.
-const int kAppModePaddingTop = 5;
-const int kAppModePaddingBottom = 4;
-const int kAppModePaddingLeft = 2;
-
-// The left padding of the tab strip.  In Views, the tab strip has a left
-// margin of FrameBorderThickness + kClientEdgeThickness.  This offset is to
-// account for kClientEdgeThickness.
-const int kTabStripLeftPadding = 1;
-
-// Spacing between buttons of the titlebar.
-const int kButtonSpacing = 2;
-
-// Spacing around outside of titlebar buttons.
-const int kButtonOuterPadding = 2;
-
-// Spacing between tabstrip and window control buttons (when the window is
-// maximized).
-const int kMaximizedTabstripPadding = 16;
-
-gboolean OnMouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
-                          BrowserWindowGtk* browser_window) {
-  // Reset to the default mouse cursor.
-  browser_window->ResetCustomFrameCursor();
-  return TRUE;
-}
-
-GdkPixbuf* GetOTRAvatar() {
-  static GdkPixbuf* otr_avatar = NULL;
-  if (!otr_avatar) {
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    otr_avatar = rb.GetRTLEnabledPixbufNamed(IDR_OTR_ICON);
-  }
-  return otr_avatar;
-}
-
-// Converts a GdkColor to a color_utils::HSL.
-color_utils::HSL GdkColorToHSL(const GdkColor* color) {
-  color_utils::HSL hsl;
-  color_utils::SkColorToHSL(SkColorSetRGB(color->red >> 8,
-                                          color->green >> 8,
-                                          color->blue >> 8), &hsl);
-  return hsl;
-}
-
-// Returns either |one| or |two| based on which has a greater difference in
-// luminosity.
-GdkColor PickLuminosityContrastingColor(const GdkColor* base,
-                                        const GdkColor* one,
-                                        const GdkColor* two) {
-  // Convert all GdkColors to color_utils::HSLs.
-  color_utils::HSL baseHSL = GdkColorToHSL(base);
-  color_utils::HSL oneHSL = GdkColorToHSL(one);
-  color_utils::HSL twoHSL = GdkColorToHSL(two);
-  double one_difference = fabs(baseHSL.l - oneHSL.l);
-  double two_difference = fabs(baseHSL.l - twoHSL.l);
-
-  // Be biased towards the first color presented.
-  if (two_difference > one_difference + 0.1)
-    return *two;
-  else
-    return *one;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// PopupPageMenuModel
-
-// A menu model that builds the contents of the menu shown for popups (when the
-// user clicks on the favicon) and all of its submenus.
-class PopupPageMenuModel : public menus::SimpleMenuModel {
- public:
-  explicit PopupPageMenuModel(menus::SimpleMenuModel::Delegate* delegate,
-                              Browser* browser);
-  virtual ~PopupPageMenuModel() { }
-
- private:
-  void Build();
-
-  // Models for submenus referenced by this model. SimpleMenuModel only uses
-  // weak references so these must be kept for the lifetime of the top-level
-  // model.
-  scoped_ptr<ZoomMenuModel> zoom_menu_model_;
-  scoped_ptr<EncodingMenuModel> encoding_menu_model_;
-  Browser* browser_;  // weak
-
-  DISALLOW_COPY_AND_ASSIGN(PopupPageMenuModel);
-};
-
-PopupPageMenuModel::PopupPageMenuModel(
-    menus::SimpleMenuModel::Delegate* delegate,
-    Browser* browser)
-    : menus::SimpleMenuModel(delegate), browser_(browser) {
-  Build();
-}
-
-void PopupPageMenuModel::Build() {
-  AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
-  AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
-  AddItemWithStringId(IDC_RELOAD, IDS_APP_MENU_RELOAD);
-  AddSeparator();
-  AddItemWithStringId(IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB);
-  AddItemWithStringId(IDC_COPY_URL, IDS_APP_MENU_COPY_URL);
-  AddSeparator();
-  AddItemWithStringId(IDC_CUT, IDS_CUT);
-  AddItemWithStringId(IDC_COPY, IDS_COPY);
-  AddItemWithStringId(IDC_PASTE, IDS_PASTE);
-  AddSeparator();
-  AddItemWithStringId(IDC_FIND, IDS_FIND);
-  AddItemWithStringId(IDC_PRINT, IDS_PRINT);
-  zoom_menu_model_.reset(new ZoomMenuModel(delegate()));
-  AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU, zoom_menu_model_.get());
-
-  encoding_menu_model_.reset(new EncodingMenuModel(browser_));
-  AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
-                         encoding_menu_model_.get());
-
-  AddSeparator();
-  AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// BrowserTitlebar
-
-// static
-const char BrowserTitlebar::kDefaultButtonString[] = ":minimize,maximize,close";
-
-BrowserTitlebar::BrowserTitlebar(BrowserWindowGtk* browser_window,
-                                 GtkWindow* window)
-    : browser_window_(browser_window),
-      window_(window),
-      titlebar_left_buttons_vbox_(NULL),
-      titlebar_right_buttons_vbox_(NULL),
-      titlebar_left_buttons_hbox_(NULL),
-      titlebar_right_buttons_hbox_(NULL),
-      titlebar_left_spy_frame_(NULL),
-      titlebar_right_spy_frame_(NULL),
-      top_padding_left_(NULL),
-      top_padding_right_(NULL),
-      app_mode_favicon_(NULL),
-      app_mode_title_(NULL),
-      using_custom_frame_(false),
-      window_has_focus_(false),
-      theme_provider_(NULL) {
-  Init();
-}
-
-void BrowserTitlebar::Init() {
-  // The widget hierarchy is shown below.
-  //
-  // +- EventBox (container_) ------------------------------------------------+
-  // +- HBox (container_hbox_) -----------------------------------------------+
-  // |+ VBox ---++- Algn. -++- Alignment --------------++- Algn. -++ VBox ---+|
-  // || titlebar||titlebar ||   (titlebar_alignment_)  ||titlebar || titlebar||
-  // || left    ||left     ||                          ||right    || right   ||
-  // || button  ||spy      ||                          ||spy      || button  ||
-  // || vbox    ||frame    ||+- TabStripGtk  ---------+||frame    || vbox    ||
-  // ||         ||         || tab   tab   tabclose    |||         ||         ||
-  // ||         ||         ||+------------------------+||         ||         ||
-  // |+---------++---------++--------------------------++---------++---------+|
-  // +------------------------------------------------------------------------+
-  //
-  // There are two vboxes on either side of |container_hbox_| because when the
-  // desktop is GNOME, the button placement is configurable based on a metacity
-  // gconf key. We can't just have one vbox and move it back and forth because
-  // the gconf language allows you to place buttons on both sides of the
-  // window.  This being Linux, I'm sure there's a bunch of people who have
-  // already configured their window manager to do so and we don't want to get
-  // confused when that happens. The actual contents of these vboxes are lazily
-  // generated so they don't interfere with alignment when everything is
-  // stuffed in the other box.
-  //
-  // Each vbox has the contains the following hierarchy if it contains buttons:
-  //
-  // +- VBox (titlebar_{l,r}_buttons_vbox_) ---------+
-  // |+- Fixed (top_padding_{l,r}_) ----------------+|
-  // ||+- HBox (titlebar_{l,r}_buttons_hbox_ ------+||
-  // ||| (buttons of a configurable layout)        |||
-  // ||+-------------------------------------------+||
-  // |+---------------------------------------------+|
-  // +-----------------------------------------------+
-  //
-  // The two spy alignments are only allocated if this window is an incognito
-  // window. Only one of them holds the spy image.
-  //
-  // If we're a popup window or in app mode, we don't display the spy guy or
-  // the tab strip.  Instead, put an hbox in titlebar_alignment_ in place of
-  // the tab strip.
-  // +- Alignment (titlebar_alignment_) -----------------------------------+
-  // |+ HBox -------------------------------------------------------------+|
-  // ||+- TabStripGtk -++- Image ----------------++- Label --------------+||
-  // ||| hidden        ++    (app_mode_favicon_) ||    (app_mode_title_) |||
-  // |||               ||  favicon               ||  page title          |||
-  // ||+---------------++------------------------++----------------------+||
-  // |+-------------------------------------------------------------------+|
-  // +---------------------------------------------------------------------+
-  container_hbox_ = gtk_hbox_new(FALSE, 0);
-
-  container_ = gtk_event_box_new();
-  gtk_widget_set_name(container_, "chrome-browser-titlebar");
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(container_), FALSE);
-  gtk_container_add(GTK_CONTAINER(container_), container_hbox_);
-
-  g_signal_connect(container_, "scroll-event", G_CALLBACK(OnScrollThunk), this);
-
-  g_signal_connect(window_, "window-state-event",
-                   G_CALLBACK(OnWindowStateChangedThunk), this);
-
-  // Allocate the two button boxes on the left and right parts of the bar, and
-  // spyguy frames in case of incognito mode.
-  titlebar_left_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_buttons_vbox_,
-                     FALSE, FALSE, 0);
-  if (browser_window_->browser()->profile()->IsOffTheRecord() &&
-      browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
-    titlebar_left_spy_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-    gtk_widget_set_no_show_all(titlebar_left_spy_frame_, TRUE);
-    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_left_spy_frame_), 0,
-        kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
-    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_spy_frame_,
-                       FALSE, FALSE, 0);
-
-    titlebar_right_spy_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-    gtk_widget_set_no_show_all(titlebar_right_spy_frame_, TRUE);
-    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_right_spy_frame_), 0,
-        kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
-    gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_spy_frame_,
-                     FALSE, FALSE, 0);
-  }
-  titlebar_right_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_buttons_vbox_,
-                   FALSE, FALSE, 0);
-
-#if defined(USE_GCONF)
-  // Either read the gconf database and register for updates (on GNOME), or use
-  // the default value (anywhere else).
-  GConfTitlebarListener::GetInstance()->SetTitlebarButtons(this);
-#else
-  BuildButtons(kDefaultButtonString);
-#endif
-
-  // We use an alignment to control the titlebar height.
-  titlebar_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  if (browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
-    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
-                       TRUE, 0);
-
-    // Put the tab strip in the titlebar.
-    gtk_container_add(GTK_CONTAINER(titlebar_alignment_),
-                      browser_window_->tabstrip()->widget());
-  } else {
-    // App mode specific widgets.
-    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
-                       TRUE, 0);
-    GtkWidget* app_mode_hbox = gtk_hbox_new(FALSE, kIconTitleSpacing);
-    gtk_container_add(GTK_CONTAINER(titlebar_alignment_), app_mode_hbox);
-
-    // Put the tab strip in the hbox even though we don't show it.  Sometimes
-    // we need the position of the tab strip so make sure it's in our widget
-    // hierarchy.
-    gtk_box_pack_start(GTK_BOX(app_mode_hbox),
-        browser_window_->tabstrip()->widget(), FALSE, FALSE, 0);
-
-    GtkWidget* favicon_event_box = gtk_event_box_new();
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(favicon_event_box), FALSE);
-    g_signal_connect(favicon_event_box, "button-press-event",
-                     G_CALLBACK(OnButtonPressedThunk), this);
-    gtk_box_pack_start(GTK_BOX(app_mode_hbox), favicon_event_box, FALSE,
-                       FALSE, 0);
-    // We use the app logo as a placeholder image so the title doesn't jump
-    // around.
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    app_mode_favicon_ = gtk_image_new_from_pixbuf(
-        rb.GetRTLEnabledPixbufNamed(IDR_PRODUCT_LOGO_16));
-    g_object_set_data(G_OBJECT(app_mode_favicon_), "left-align-popup",
-                      reinterpret_cast<void*>(true));
-    gtk_container_add(GTK_CONTAINER(favicon_event_box), app_mode_favicon_);
-
-    app_mode_title_ = gtk_label_new(NULL);
-    gtk_label_set_ellipsize(GTK_LABEL(app_mode_title_), PANGO_ELLIPSIZE_END);
-    gtk_misc_set_alignment(GTK_MISC(app_mode_title_), 0.0, 0.5);
-    gtk_box_pack_start(GTK_BOX(app_mode_hbox), app_mode_title_, TRUE, TRUE,
-                       0);
-
-    // Register with the theme provider to set the |app_mode_title_| label
-    // color.
-    theme_provider_ = GtkThemeProvider::GetFrom(
-        browser_window_->browser()->profile());
-    registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                   NotificationService::AllSources());
-    theme_provider_->InitThemesFor(this);
-    UpdateTitleAndIcon();
-  }
-
-  gtk_widget_show_all(container_);
-
-  ActiveWindowWatcherX::AddObserver(this);
-}
-
-BrowserTitlebar::~BrowserTitlebar() {
-  ActiveWindowWatcherX::RemoveObserver(this);
-#if defined(USE_GCONF)
-  GConfTitlebarListener::GetInstance()->RemoveObserver(this);
-#endif
-}
-
-void BrowserTitlebar::BuildButtons(const std::string& button_string) {
-  // Clear out all previous data.
-  close_button_.reset();
-  restore_button_.reset();
-  maximize_button_.reset();
-  minimize_button_.reset();
-  gtk_util::RemoveAllChildren(titlebar_left_buttons_vbox_);
-  gtk_util::RemoveAllChildren(titlebar_right_buttons_vbox_);
-  titlebar_left_buttons_hbox_ = NULL;
-  titlebar_right_buttons_hbox_ = NULL;
-  top_padding_left_ = NULL;
-  top_padding_right_ = NULL;
-
-  bool left_side = true;
-  StringTokenizer tokenizer(button_string, ":,");
-  tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
-  int left_count = 0;
-  int right_count = 0;
-  while (tokenizer.GetNext()) {
-    if (tokenizer.token_is_delim()) {
-      if (*tokenizer.token_begin() == ':')
-        left_side = false;
-    } else {
-      base::StringPiece token = tokenizer.token_piece();
-      if (token == "minimize") {
-        (left_side ? left_count : right_count)++;
-        GtkWidget* parent_box = GetButtonHBox(left_side);
-        minimize_button_.reset(
-            BuildTitlebarButton(IDR_MINIMIZE, IDR_MINIMIZE_P,
-                                IDR_MINIMIZE_H, parent_box,
-                                IDS_XPFRAME_MINIMIZE_TOOLTIP));
-
-        gtk_widget_size_request(minimize_button_->widget(),
-                                &minimize_button_req_);
-      } else if (token == "maximize") {
-        (left_side ? left_count : right_count)++;
-        GtkWidget* parent_box = GetButtonHBox(left_side);
-        restore_button_.reset(
-            BuildTitlebarButton(IDR_RESTORE, IDR_RESTORE_P,
-                                IDR_RESTORE_H, parent_box,
-                                IDS_XPFRAME_RESTORE_TOOLTIP));
-        maximize_button_.reset(
-            BuildTitlebarButton(IDR_MAXIMIZE, IDR_MAXIMIZE_P,
-                                IDR_MAXIMIZE_H, parent_box,
-                                IDS_XPFRAME_MAXIMIZE_TOOLTIP));
-
-        gtk_util::SetButtonClickableByMouseButtons(maximize_button_->widget(),
-                                                   true, true, true);
-        gtk_widget_size_request(restore_button_->widget(),
-                                &restore_button_req_);
-      } else if (token == "close") {
-        (left_side ? left_count : right_count)++;
-        GtkWidget* parent_box = GetButtonHBox(left_side);
-        close_button_.reset(
-            BuildTitlebarButton(IDR_CLOSE, IDR_CLOSE_P,
-                                IDR_CLOSE_H, parent_box,
-                                IDS_XPFRAME_CLOSE_TOOLTIP));
-        close_button_->set_flipped(left_side);
-
-        gtk_widget_size_request(close_button_->widget(), &close_button_req_);
-      }
-      // Ignore any other values like "pin" since we don't have images for
-      // those.
-    }
-  }
-
-  // If we are in incognito mode, add the spy guy to either the end of the left
-  // or the beginning of the right depending on which side has fewer buttons.
-  if (browser_window_->browser()->profile()->IsOffTheRecord() &&
-      browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
-    GtkWidget* spy_guy = gtk_image_new_from_pixbuf(GetOTRAvatar());
-    gtk_misc_set_alignment(GTK_MISC(spy_guy), 0.0, 1.0);
-    gtk_widget_set_size_request(spy_guy, -1, 0);
-    gtk_widget_show(spy_guy);
-
-    // Remove previous state.
-    gtk_util::RemoveAllChildren(titlebar_left_spy_frame_);
-    gtk_util::RemoveAllChildren(titlebar_right_spy_frame_);
-
-    if (right_count > left_count) {
-      gtk_container_add(GTK_CONTAINER(titlebar_left_spy_frame_), spy_guy);
-      gtk_widget_show(titlebar_left_spy_frame_);
-      gtk_widget_hide(titlebar_right_spy_frame_);
-    } else {
-      gtk_container_add(GTK_CONTAINER(titlebar_right_spy_frame_), spy_guy);
-      gtk_widget_show(titlebar_right_spy_frame_);
-      gtk_widget_hide(titlebar_left_spy_frame_);
-    }
-  }
-
-  // Now show the correct widgets in the two hierarchies.
-  if (using_custom_frame_) {
-    gtk_widget_show_all(titlebar_left_buttons_vbox_);
-    gtk_widget_show_all(titlebar_right_buttons_vbox_);
-  }
-  UpdateMaximizeRestoreVisibility();
-}
-
-GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) {
-  if (left_side && titlebar_left_buttons_hbox_)
-    return titlebar_left_buttons_hbox_;
-  else if (!left_side && titlebar_right_buttons_hbox_)
-    return titlebar_right_buttons_hbox_;
-
-  // We put the min/max/restore/close buttons in a vbox so they are top aligned
-  // (up to padding) and don't vertically stretch.
-  GtkWidget* vbox = left_side ? titlebar_left_buttons_vbox_ :
-                    titlebar_right_buttons_vbox_;
-
-  GtkWidget* top_padding = gtk_fixed_new();
-  gtk_widget_set_size_request(top_padding, -1, kButtonOuterPadding);
-  gtk_box_pack_start(GTK_BOX(vbox), top_padding, FALSE, FALSE, 0);
-
-  GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing);
-  gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0);
-
-  if (left_side) {
-    titlebar_left_buttons_hbox_ = buttons_hbox;
-    top_padding_left_ = top_padding;
-  } else {
-    titlebar_right_buttons_hbox_ = buttons_hbox;
-    top_padding_right_ = top_padding;
-  }
-
-  return buttons_hbox;
-}
-
-CustomDrawButton* BrowserTitlebar::BuildTitlebarButton(int image,
-    int image_pressed, int image_hot, GtkWidget* box, int tooltip) {
-  CustomDrawButton* button = new CustomDrawButton(image, image_pressed,
-                                                  image_hot, 0);
-  gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK);
-  g_signal_connect(button->widget(), "clicked",
-                   G_CALLBACK(OnButtonClickedThunk), this);
-  g_signal_connect(button->widget(), "motion-notify-event",
-                   G_CALLBACK(OnMouseMoveEvent), browser_window_);
-  std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip);
-  gtk_widget_set_tooltip_text(button->widget(),
-                              localized_tooltip.c_str());
-  gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0);
-  return button;
-}
-
-void BrowserTitlebar::UpdateCustomFrame(bool use_custom_frame) {
-  using_custom_frame_ = use_custom_frame;
-  if (use_custom_frame) {
-    if (titlebar_left_buttons_vbox_)
-      gtk_widget_show_all(titlebar_left_buttons_vbox_);
-    if (titlebar_right_buttons_vbox_)
-      gtk_widget_show_all(titlebar_right_buttons_vbox_);
-  } else {
-    if (titlebar_left_buttons_vbox_)
-      gtk_widget_hide(titlebar_left_buttons_vbox_);
-    if (titlebar_right_buttons_vbox_)
-      gtk_widget_hide(titlebar_right_buttons_vbox_);
-  }
-  UpdateTitlebarAlignment();
-}
-
-void BrowserTitlebar::UpdateTitleAndIcon() {
-  if (!app_mode_title_)
-    return;
-
-  // Get the page title and elide it to the available space.
-  string16 title = browser_window_->browser()->GetWindowTitleForCurrentTab();
-  gtk_label_set_text(GTK_LABEL(app_mode_title_), UTF16ToUTF8(title).c_str());
-
-  // Note: this isn't browser_window_->browser()->type() & Browser::TYPE_APP
-  // because we want to exclude Browser::TYPE_APP_POPUP.
-  if (browser_window_->browser()->type() == Browser::TYPE_APP ||
-      browser_window_->browser()->type() == Browser::TYPE_APP_PANEL) {
-    // Update the system app icon.  We don't need to update the icon in the top
-    // left of the custom frame, that will get updated when the throbber is
-    // updated.
-    SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon();
-    if (icon.empty()) {
-      gtk_util::SetWindowIcon(window_);
-    } else {
-      GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
-      gtk_window_set_icon(window_, icon_pixbuf);
-      g_object_unref(icon_pixbuf);
-    }
-  }
-}
-
-void BrowserTitlebar::UpdateThrobber(TabContents* tab_contents) {
-  DCHECK(app_mode_favicon_);
-
-  if (tab_contents && tab_contents->is_loading()) {
-    GdkPixbuf* icon_pixbuf =
-        throbber_.GetNextFrame(tab_contents->waiting_for_response());
-    gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
-  } else {
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-    // Note: this isn't browser_window_->browser()->type() & Browser::TYPE_APP
-    // because we want to exclude Browser::TYPE_APP_POPUP.
-    if (browser_window_->browser()->type() == Browser::TYPE_APP ||
-        browser_window_->browser()->type() == Browser::TYPE_APP_PANEL) {
-      SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon();
-      if (icon.empty()) {
-        // Fallback to the Chromium icon if the page has no icon.
-        gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
-            rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
-      } else {
-        GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
-        gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
-        g_object_unref(icon_pixbuf);
-      }
-    } else {
-      gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
-          rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
-    }
-    throbber_.Reset();
-  }
-}
-
-void BrowserTitlebar::UpdateTitlebarAlignment() {
-  if (browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
-    int top_padding = 0;
-    int side_padding = 0;
-    int vertical_offset = kNormalVerticalOffset;
-
-    if (using_custom_frame_) {
-      if (!browser_window_->IsMaximized()) {
-        top_padding = kTitlebarHeight;
-      } else if (using_custom_frame_ && browser_window_->IsMaximized()) {
-        vertical_offset = 0;
-        side_padding = kMaximizedTabstripPadding;
-      }
-    }
-
-    int right_padding = 0;
-    int left_padding = kTabStripLeftPadding;
-    if (titlebar_right_buttons_hbox_)
-      right_padding = side_padding;
-    if (titlebar_left_buttons_hbox_)
-      left_padding = side_padding;
-
-    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
-                              top_padding, 0,
-                              left_padding, right_padding);
-    browser_window_->tabstrip()->SetVerticalOffset(vertical_offset);
-  } else {
-    if (using_custom_frame_ && !browser_window_->IsFullscreen()) {
-      gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
-          kAppModePaddingTop, kAppModePaddingBottom, kAppModePaddingLeft, 0);
-      gtk_widget_show(titlebar_alignment_);
-    } else {
-      gtk_widget_hide(titlebar_alignment_);
-    }
-  }
-
-  // Resize the buttons so that the clickable area extends all the way to the
-  // edge of the browser window.
-  GtkRequisition close_button_req = close_button_req_;
-  GtkRequisition minimize_button_req = minimize_button_req_;
-  GtkRequisition restore_button_req = restore_button_req_;
-  if (using_custom_frame_ && browser_window_->IsMaximized()) {
-    close_button_req.width += kButtonOuterPadding;
-    close_button_req.height += kButtonOuterPadding;
-    minimize_button_req.height += kButtonOuterPadding;
-    restore_button_req.height += kButtonOuterPadding;
-    if (top_padding_left_)
-      gtk_widget_hide(top_padding_left_);
-    if (top_padding_right_)
-      gtk_widget_hide(top_padding_right_);
-  } else {
-    if (top_padding_left_)
-      gtk_widget_show(top_padding_left_);
-    if (top_padding_right_)
-      gtk_widget_show(top_padding_right_);
-  }
-  if (close_button_.get()) {
-    gtk_widget_set_size_request(close_button_->widget(),
-                                close_button_req.width,
-                                close_button_req.height);
-  }
-  if (minimize_button_.get()) {
-    gtk_widget_set_size_request(minimize_button_->widget(),
-                                minimize_button_req.width,
-                                minimize_button_req.height);
-  }
-  if (maximize_button_.get()) {
-    gtk_widget_set_size_request(restore_button_->widget(),
-                                restore_button_req.width,
-                                restore_button_req.height);
-  }
-}
-
-void BrowserTitlebar::UpdateTextColor() {
-  if (!app_mode_title_)
-    return;
-
-  if (theme_provider_ && theme_provider_->UseGtkTheme()) {
-    // We don't really have any good options here.
-    //
-    // Colors from window manager themes aren't exposed in GTK; the window
-    // manager is a separate component and when there is information sharing
-    // (in the case of metacity), it's one way where the window manager reads
-    // data from the GTK theme (which allows us to do a decent job with
-    // picking the frame color).
-    //
-    // We probably won't match in the majority of cases, but we can at the
-    // very least make things legible. The default metacity and xfwm themes
-    // on ubuntu have white text hardcoded. Determine whether black or white
-    // has more luminosity contrast and then set that color as the text
-    // color.
-    GdkColor frame_color;
-    if (window_has_focus_) {
-      frame_color = theme_provider_->GetGdkColor(
-          BrowserThemeProvider::COLOR_FRAME);
-    } else {
-      frame_color = theme_provider_->GetGdkColor(
-          BrowserThemeProvider::COLOR_FRAME_INACTIVE);
-    }
-    GdkColor text_color = PickLuminosityContrastingColor(
-        &frame_color, &gtk_util::kGdkWhite, &gtk_util::kGdkBlack);
-    gtk_util::SetLabelColor(app_mode_title_, &text_color);
-  } else {
-    gtk_util::SetLabelColor(app_mode_title_, &gtk_util::kGdkWhite);
-  }
-}
-
-void BrowserTitlebar::ShowFaviconMenu(GdkEventButton* event) {
-  if (!favicon_menu_model_.get()) {
-    favicon_menu_model_.reset(
-        new PopupPageMenuModel(this, browser_window_->browser()));
-
-    favicon_menu_.reset(new MenuGtk(NULL, favicon_menu_model_.get()));
-  }
-
-  favicon_menu_->Popup(app_mode_favicon_, reinterpret_cast<GdkEvent*>(event));
-}
-
-void BrowserTitlebar::MaximizeButtonClicked() {
-  GdkEvent* event = gtk_get_current_event();
-  if (event->button.button == 1) {
-    gtk_window_maximize(window_);
-  } else {
-    GtkWidget* widget = GTK_WIDGET(window_);
-    GdkScreen* screen = gtk_widget_get_screen(widget);
-    gint monitor = gdk_screen_get_monitor_at_window(screen, widget->window);
-    GdkRectangle screen_rect;
-    gdk_screen_get_monitor_geometry(screen, monitor, &screen_rect);
-
-    gint x, y;
-    gtk_window_get_position(window_, &x, &y);
-    gint width = widget->allocation.width;
-    gint height = widget->allocation.height;
-
-    if (event->button.button == 3) {
-      x = 0;
-      width = screen_rect.width;
-    } else if (event->button.button == 2) {
-      y = 0;
-      height = screen_rect.height;
-    }
-
-    browser_window_->SetBounds(gfx::Rect(x, y, width, height));
-  }
-  gdk_event_free(event);
-}
-
-void BrowserTitlebar::UpdateMaximizeRestoreVisibility() {
-  if (maximize_button_.get()) {
-    if (browser_window_->IsMaximized()) {
-      gtk_widget_hide(maximize_button_->widget());
-      gtk_widget_show(restore_button_->widget());
-    } else {
-      gtk_widget_hide(restore_button_->widget());
-      gtk_widget_show(maximize_button_->widget());
-    }
-  }
-}
-
-gboolean BrowserTitlebar::OnWindowStateChanged(GtkWindow* window,
-                                               GdkEventWindowState* event) {
-  UpdateMaximizeRestoreVisibility();
-  UpdateTitlebarAlignment();
-  UpdateTextColor();
-  return FALSE;
-}
-
-gboolean BrowserTitlebar::OnScroll(GtkWidget* widget, GdkEventScroll* event) {
-  TabStripModel* tabstrip_model = browser_window_->browser()->tabstrip_model();
-  int index = tabstrip_model->selected_index();
-  if (event->direction == GDK_SCROLL_LEFT ||
-      event->direction == GDK_SCROLL_UP) {
-    if (index != 0)
-      tabstrip_model->SelectPreviousTab();
-  } else if (index + 1 < tabstrip_model->count()) {
-    tabstrip_model->SelectNextTab();
-  }
-  return TRUE;
-}
-
-// static
-void BrowserTitlebar::OnButtonClicked(GtkWidget* button) {
-  if (close_button_.get() && close_button_->widget() == button) {
-    browser_window_->Close();
-  } else if (restore_button_.get() && restore_button_->widget() == button) {
-    browser_window_->UnMaximize();
-  } else if (maximize_button_.get() && maximize_button_->widget() == button) {
-    MaximizeButtonClicked();
-  } else if (minimize_button_.get() && minimize_button_->widget() == button) {
-    gtk_window_iconify(window_);
-  }
-}
-
-gboolean BrowserTitlebar::OnButtonPressed(GtkWidget* widget,
-                                          GdkEventButton* event) {
-  if (event->button != 1)
-    return FALSE;
-
-  ShowFaviconMenu(event);
-  return TRUE;
-}
-
-void BrowserTitlebar::ShowContextMenu() {
-  if (!context_menu_.get()) {
-    context_menu_model_.reset(new ContextMenuModel(this));
-    context_menu_.reset(new MenuGtk(NULL, context_menu_model_.get()));
-  }
-
-  context_menu_->PopupAsContext(gtk_get_current_event_time());
-}
-
-bool BrowserTitlebar::IsCommandIdEnabled(int command_id) const {
-  if (command_id == kShowWindowDecorationsCommand)
-    return true;
-
-  return browser_window_->browser()->command_updater()->
-      IsCommandEnabled(command_id);
-}
-
-bool BrowserTitlebar::IsCommandIdChecked(int command_id) const {
-  if (command_id == kShowWindowDecorationsCommand) {
-    PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
-    return !prefs->GetBoolean(prefs::kUseCustomChromeFrame);
-  }
-
-  EncodingMenuController controller;
-  if (controller.DoesCommandBelongToEncodingMenu(command_id)) {
-    TabContents* tab_contents =
-        browser_window_->browser()->GetSelectedTabContents();
-    if (tab_contents) {
-      return controller.IsItemChecked(browser_window_->browser()->profile(),
-                                      tab_contents->encoding(),
-                                      command_id);
-    }
-    return false;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-void BrowserTitlebar::ExecuteCommand(int command_id) {
-  if (command_id == kShowWindowDecorationsCommand) {
-    PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
-    prefs->SetBoolean(prefs::kUseCustomChromeFrame,
-                  !prefs->GetBoolean(prefs::kUseCustomChromeFrame));
-    return;
-  }
-
-  browser_window_->browser()->ExecuteCommand(command_id);
-}
-
-bool BrowserTitlebar::GetAcceleratorForCommandId(
-    int command_id, menus::Accelerator* accelerator) {
-  const menus::AcceleratorGtk* accelerator_gtk =
-      AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(
-          command_id);
-  if (accelerator_gtk)
-    *accelerator = *accelerator_gtk;
-  return accelerator_gtk;
-}
-
-void BrowserTitlebar::Observe(NotificationType type,
-                              const NotificationSource& source,
-                              const NotificationDetails& details) {
-  switch (type.value) {
-    case NotificationType::BROWSER_THEME_CHANGED:
-      UpdateTextColor();
-      break;
-
-    default:
-      NOTREACHED();
-  }
-}
-
-void BrowserTitlebar::ActiveWindowChanged(GdkWindow* active_window) {
-  // Can be called during shutdown; BrowserWindowGtk will set our |window_|
-  // to NULL during that time.
-  if (!window_)
-    return;
-
-  window_has_focus_ = GTK_WIDGET(window_)->window == active_window;
-  UpdateTextColor();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// BrowserTitlebar::Throbber implementation
-// TODO(tc): Handle anti-clockwise spinning when waiting for a connection.
-
-// We don't bother to clean up these or the pixbufs they contain when we exit.
-static std::vector<GdkPixbuf*>* g_throbber_frames = NULL;
-static std::vector<GdkPixbuf*>* g_throbber_waiting_frames = NULL;
-
-// Load |resource_id| from the ResourceBundle and split it into a series of
-// square GdkPixbufs that get stored in |frames|.
-static void MakeThrobberFrames(int resource_id,
-                               std::vector<GdkPixbuf*>* frames) {
-  ResourceBundle &rb = ResourceBundle::GetSharedInstance();
-  SkBitmap* frame_strip = rb.GetBitmapNamed(resource_id);
-
-  // Each frame of the animation is a square, so we use the height as the
-  // frame size.
-  int frame_size = frame_strip->height();
-  size_t num_frames = frame_strip->width() / frame_size;
-
-  // Make a separate GdkPixbuf for each frame of the animation.
-  for (size_t i = 0; i < num_frames; ++i) {
-    SkBitmap frame = SkBitmapOperations::CreateTiledBitmap(*frame_strip,
-        i * frame_size, 0, frame_size, frame_size);
-    frames->push_back(gfx::GdkPixbufFromSkBitmap(&frame));
-  }
-}
-
-GdkPixbuf* BrowserTitlebar::Throbber::GetNextFrame(bool is_waiting) {
-  Throbber::InitFrames();
-  if (is_waiting) {
-    return (*g_throbber_waiting_frames)[current_waiting_frame_++ %
-        g_throbber_waiting_frames->size()];
-  } else {
-    return (*g_throbber_frames)[current_frame_++ % g_throbber_frames->size()];
-  }
-}
-
-void BrowserTitlebar::Throbber::Reset() {
-  current_frame_ = 0;
-  current_waiting_frame_ = 0;
-}
-
-// static
-void BrowserTitlebar::Throbber::InitFrames() {
-  if (g_throbber_frames)
-    return;
-
-  // We load the light version of the throbber since it'll be in the titlebar.
-  g_throbber_frames = new std::vector<GdkPixbuf*>;
-  MakeThrobberFrames(IDR_THROBBER_LIGHT, g_throbber_frames);
-
-  g_throbber_waiting_frames = new std::vector<GdkPixbuf*>;
-  MakeThrobberFrames(IDR_THROBBER_WAITING_LIGHT, g_throbber_waiting_frames);
-}
-
-BrowserTitlebar::ContextMenuModel::ContextMenuModel(
-    menus::SimpleMenuModel::Delegate* delegate)
-    : SimpleMenuModel(delegate) {
-  AddItemWithStringId(IDC_NEW_TAB, IDS_TAB_CXMENU_NEWTAB);
-  AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
-  AddSeparator();
-  AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
-  AddSeparator();
-  AddCheckItemWithStringId(kShowWindowDecorationsCommand,
-                           IDS_SHOW_WINDOW_DECORATIONS_MENU);
-}
diff --git a/chrome/browser/gtk/browser_titlebar.h b/chrome/browser/gtk/browser_titlebar.h
deleted file mode 100644
index 5cd30e6..0000000
--- a/chrome/browser/gtk/browser_titlebar.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// A helper class that contains the gtk widgets that make up the titlebar.  The
-// titlebar consists of the tabstrip and if the custom chrome frame is turned
-// on, it includes the taller titlebar and minimize, restore, maximize, and
-// close buttons.
-
-#ifndef CHROME_BROWSER_GTK_BROWSER_TITLEBAR_H_
-#define CHROME_BROWSER_GTK_BROWSER_TITLEBAR_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/active_window_watcher_x.h"
-#include "app/menus/simple_menu_model.h"
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class BrowserWindowGtk;
-class CustomDrawButton;
-class GtkThemeProvider;
-class MenuGtk;
-class PopupPageMenuModel;
-class TabContents;
-
-class BrowserTitlebar : public NotificationObserver,
-                        public ActiveWindowWatcherX::Observer,
-                        public menus::SimpleMenuModel::Delegate {
- public:
-  // A default button order string for when we aren't asking gconf for the
-  // metacity configuration.
-  static const char kDefaultButtonString[];
-
-  BrowserTitlebar(BrowserWindowGtk* browser_window, GtkWindow* window);
-  virtual ~BrowserTitlebar();
-
-  GtkWidget* widget() {
-    return container_;
-  }
-
-  void set_window(GtkWindow* window) { window_ = window; }
-
-  // Builds the buttons based on the metacity |button_string|.
-  void BuildButtons(const std::string& button_string);
-
-  // Update the appearance of the title bar based on whether we're showing a
-  // custom frame or not.  If |use_custom_frame| is true, we show an extra
-  // tall titlebar and the min/max/close buttons.
-  void UpdateCustomFrame(bool use_custom_frame);
-
-  // Updates the title and icon when in app or popup mode (no tabstrip).
-  void UpdateTitleAndIcon();
-
-  // Called by the browser asking us to update the loading throbber.
-  // |tab_contents| is the tab that is associated with the window throbber.
-  // |tab_contents| can be null.
-  void UpdateThrobber(TabContents* tab_contents);
-
-  // On Windows, right clicking in the titlebar background brings up the system
-  // menu.  There's no such thing on linux, so we just show the menu items we
-  // add to the menu.
-  void ShowContextMenu();
-
- private:
-  // A helper class to keep track of which frame of the throbber animation
-  // we're showing.
-  class Throbber {
-   public:
-    Throbber() : current_frame_(0), current_waiting_frame_(0) {}
-
-    // Get the next frame in the animation. The image is owned by the throbber
-    // so the caller doesn't need to unref.  |is_waiting| is true if we're
-    // still waiting for a response.
-    GdkPixbuf* GetNextFrame(bool is_waiting);
-
-    // Reset back to the first frame.
-    void Reset();
-   private:
-    // Make sure the frames are loaded.
-    static void InitFrames();
-
-    int current_frame_;
-    int current_waiting_frame_;
-  };
-
-  class ContextMenuModel : public menus::SimpleMenuModel {
-   public:
-    explicit ContextMenuModel(menus::SimpleMenuModel::Delegate* delegate);
-  };
-
-  // Build the titlebar, the space above the tab
-  // strip, and (maybe) the min, max, close buttons.  |container| is the gtk
-  // continer that we put the widget into.
-  void Init();
-
-  // Lazily builds and returns |titlebar_{left,right}_buttons_vbox_| and their
-  // subtrees. We do this lazily because in most situations, only one of them
-  // is allocated (though the user can (and do) manually mess with their gconf
-  // settings to get absolutely horrid combinations of buttons on both sides.
-  GtkWidget* GetButtonHBox(bool left_side);
-
-  // Constructs a CustomDraw button given 3 image ids (IDR_), the box to place
-  // the button into, and a tooltip id (IDS_).
-  CustomDrawButton* BuildTitlebarButton(int image, int image_pressed,
-                                        int image_hot, GtkWidget* box,
-                                        int tooltip);
-
-  // Update the titlebar spacing based on the custom frame and maximized state.
-  void UpdateTitlebarAlignment();
-
-  // Updates the color of the title bar. Called whenever we have a state
-  // change in the window.
-  void UpdateTextColor();
-
-  // Show the menu that the user gets from left-clicking the favicon.
-  void ShowFaviconMenu(GdkEventButton* event);
-
-  // The maximize button was clicked, take an action depending on which mouse
-  // button the user pressed.
-  void MaximizeButtonClicked();
-
-  // Updates the visibility of the maximize and restore buttons; only one can
-  // be visible at a time.
-  void UpdateMaximizeRestoreVisibility();
-
-  // Callback for changes to window state.  This includes
-  // maximizing/restoring/minimizing the window.
-  CHROMEG_CALLBACK_1(BrowserTitlebar, gboolean, OnWindowStateChanged,
-                     GtkWindow*, GdkEventWindowState*);
-
-  // Callback for mousewheel events.
-  CHROMEGTK_CALLBACK_1(BrowserTitlebar, gboolean, OnScroll,
-                       GdkEventScroll*);
-
-  // Callback for min/max/close buttons.
-  CHROMEGTK_CALLBACK_0(BrowserTitlebar, void, OnButtonClicked);
-
-  // Callback for favicon.
-  CHROMEGTK_CALLBACK_1(BrowserTitlebar, gboolean, OnButtonPressed,
-                       GdkEventButton*);
-
-  // -- Context Menu -----------------------------------------------------------
-
-  // SimpleMenuModel::Delegate implementation:
-  virtual bool IsCommandIdEnabled(int command_id) const;
-  virtual bool IsCommandIdChecked(int command_id) const;
-  virtual void ExecuteCommand(int command_id);
-  virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Overriden from ActiveWindowWatcher::Observer.
-  virtual void ActiveWindowChanged(GdkWindow* active_window);
-
-  // Pointers to the browser window that owns us and it's GtkWindow.
-  BrowserWindowGtk* browser_window_;
-  GtkWindow* window_;
-
-  // The container widget the holds the hbox which contains the whole titlebar.
-  GtkWidget* container_;
-
-  // The hbox that contains the whole titlebar.
-  GtkWidget* container_hbox_;
-
-  // VBoxes that holds the min/max/close buttons box and an optional padding
-  // that defines the skyline if the user turns off window manager decorations.
-  // There is a left and right version of this box since we try to integrate
-  // with the recent Ubuntu theme changes which put the buttons on the left.
-  GtkWidget* titlebar_left_buttons_vbox_;
-  GtkWidget* titlebar_right_buttons_vbox_;
-
-  // HBoxes that contains the actual min/max/close buttons.
-  GtkWidget* titlebar_left_buttons_hbox_;
-  GtkWidget* titlebar_right_buttons_hbox_;
-
-  // Spy frame. One of these frames holds the spy guy in incognito mode. It's
-  // the side with the least buttons. These are NULL when we aren't in
-  // incognito mode.
-  GtkWidget* titlebar_left_spy_frame_;
-  GtkWidget* titlebar_right_spy_frame_;
-
-  // Padding between the titlebar buttons and the top of the screen. Only show
-  // when not maximized.
-  GtkWidget* top_padding_left_;
-  GtkWidget* top_padding_right_;
-
-  // Gtk alignment that contains the tab strip.  If the user turns off window
-  // manager decorations, we draw this taller.
-  GtkWidget* titlebar_alignment_;
-
-  // The favicon and page title used when in app mode or popup mode.
-  GtkWidget* app_mode_favicon_;
-  GtkWidget* app_mode_title_;
-
-  // Whether we are using a custom frame.
-  bool using_custom_frame_;
-
-  // Whether we have focus (gtk_window_is_active() sometimes returns the wrong
-  // value, so manually track the focus-in and focus-out events.)
-  bool window_has_focus_;
-
-  // We change the size of these three buttons when the window is maximized, so
-  // we use these structs to keep track of their original size.
-  GtkRequisition close_button_req_;
-  GtkRequisition minimize_button_req_;
-  GtkRequisition restore_button_req_;
-
-  // Maximize and restore widgets in the titlebar.
-  scoped_ptr<CustomDrawButton> minimize_button_;
-  scoped_ptr<CustomDrawButton> maximize_button_;
-  scoped_ptr<CustomDrawButton> restore_button_;
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  // The context menu view and model.
-  scoped_ptr<MenuGtk> context_menu_;
-  scoped_ptr<ContextMenuModel> context_menu_model_;
-
-  // The favicon menu view and model.
-  scoped_ptr<MenuGtk> favicon_menu_;
-  scoped_ptr<PopupPageMenuModel> favicon_menu_model_;
-
-  // The throbber used when the window is in app mode or popup window mode.
-  Throbber throbber_;
-
-  // Theme provider for building buttons.
-  GtkThemeProvider* theme_provider_;
-
-  NotificationRegistrar registrar_;
-};
-
-#endif  // CHROME_BROWSER_GTK_BROWSER_TITLEBAR_H_
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
deleted file mode 100644
index 3af9c38..0000000
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ /dev/null
@@ -1,660 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/browser_toolbar_gtk.h"
-
-#include <X11/XF86keysym.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include "app/gtk_dnd_util.h"
-#include "app/l10n_util.h"
-#include "app/menus/accelerator_gtk.h"
-#include "base/base_paths.h"
-#include "base/command_line.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/singleton.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/background_page_tracker.h"
-#include "chrome/browser/gtk/accelerators_gtk.h"
-#include "chrome/browser/gtk/back_forward_button_gtk.h"
-#include "chrome/browser/gtk/browser_actions_toolbar_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-#include "chrome/browser/gtk/reload_button_gtk.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
-#include "chrome/browser/upgrade_detector.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/gtk_util.h"
-#include "gfx/skbitmap_operations.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// Padding on left and right of the left toolbar buttons (back, forward, reload,
-// etc.).
-const int kToolbarLeftAreaPadding = 4;
-
-// Height of the toolbar in pixels (not counting padding).
-const int kToolbarHeight = 29;
-
-// Padding within the toolbar above the buttons and location bar.
-const int kTopBottomPadding = 3;
-
-// Height of the toolbar in pixels when we only show the location bar.
-const int kToolbarHeightLocationBarOnly = kToolbarHeight - 2;
-
-// Interior spacing between toolbar widgets.
-const int kToolbarWidgetSpacing = 1;
-
-// Amount of rounding on top corners of toolbar. Only used in Gtk theme mode.
-const int kToolbarCornerSize = 3;
-
-void SetWidgetHeightRequest(GtkWidget* widget, gpointer user_data) {
-  gtk_widget_set_size_request(widget, -1, GPOINTER_TO_INT(user_data));
-}
-
-}  // namespace
-
-// BrowserToolbarGtk, public ---------------------------------------------------
-
-BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window)
-    : toolbar_(NULL),
-      location_bar_(new LocationBarViewGtk(browser)),
-      model_(browser->toolbar_model()),
-      wrench_menu_model_(this, browser),
-      browser_(browser),
-      window_(window),
-      profile_(NULL) {
-  browser_->command_updater()->AddCommandObserver(IDC_BACK, this);
-  browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
-  browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
-  browser_->command_updater()->AddCommandObserver(IDC_BOOKMARK_PAGE, this);
-
-  registrar_.Add(this,
-                 NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  registrar_.Add(this,
-                 NotificationType::UPGRADE_RECOMMENDED,
-                 NotificationService::AllSources());
-  registrar_.Add(this,
-                 NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED,
-                 NotificationService::AllSources());
-}
-
-BrowserToolbarGtk::~BrowserToolbarGtk() {
-  browser_->command_updater()->RemoveCommandObserver(IDC_BACK, this);
-  browser_->command_updater()->RemoveCommandObserver(IDC_FORWARD, this);
-  browser_->command_updater()->RemoveCommandObserver(IDC_HOME, this);
-  browser_->command_updater()->RemoveCommandObserver(IDC_BOOKMARK_PAGE, this);
-
-  offscreen_entry_.Destroy();
-
-  wrench_menu_.reset();
-}
-
-void BrowserToolbarGtk::Init(Profile* profile,
-                             GtkWindow* top_level_window) {
-  // Make sure to tell the location bar the profile before calling its Init.
-  SetProfile(profile);
-
-  theme_provider_ = GtkThemeProvider::GetFrom(profile);
-  offscreen_entry_.Own(gtk_entry_new());
-
-  show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this);
-  home_page_.Init(prefs::kHomePage, profile->GetPrefs(), this);
-  home_page_is_new_tab_page_.Init(prefs::kHomePageIsNewTabPage,
-                                  profile->GetPrefs(), this);
-
-  event_box_ = gtk_event_box_new();
-  // Make the event box transparent so themes can use transparent toolbar
-  // backgrounds.
-  if (!theme_provider_->UseGtkTheme())
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
-
-  toolbar_ = gtk_hbox_new(FALSE, 0);
-  alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  UpdateForBookmarkBarVisibility(false);
-  g_signal_connect(alignment_, "expose-event",
-                   G_CALLBACK(&OnAlignmentExposeThunk), this);
-  gtk_container_add(GTK_CONTAINER(event_box_), alignment_);
-  gtk_container_add(GTK_CONTAINER(alignment_), toolbar_);
-
-  toolbar_left_ = gtk_hbox_new(FALSE, kToolbarWidgetSpacing);
-
-  back_.reset(new BackForwardButtonGtk(browser_, false));
-  g_signal_connect(back_->widget(), "clicked",
-                   G_CALLBACK(OnButtonClickThunk), this);
-  gtk_box_pack_start(GTK_BOX(toolbar_left_), back_->widget(), FALSE,
-                     FALSE, 0);
-
-  forward_.reset(new BackForwardButtonGtk(browser_, true));
-  g_signal_connect(forward_->widget(), "clicked",
-                   G_CALLBACK(OnButtonClickThunk), this);
-  gtk_box_pack_start(GTK_BOX(toolbar_left_), forward_->widget(), FALSE,
-                     FALSE, 0);
-
-  reload_.reset(new ReloadButtonGtk(location_bar_.get(), browser_));
-  gtk_box_pack_start(GTK_BOX(toolbar_left_), reload_->widget(), FALSE, FALSE,
-                     0);
-
-  home_.reset(new CustomDrawButton(GtkThemeProvider::GetFrom(profile_),
-      IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0, GTK_STOCK_HOME,
-      GTK_ICON_SIZE_SMALL_TOOLBAR));
-  gtk_widget_set_tooltip_text(home_->widget(),
-      l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME).c_str());
-  g_signal_connect(home_->widget(), "clicked",
-                   G_CALLBACK(OnButtonClickThunk), this);
-  gtk_box_pack_start(GTK_BOX(toolbar_left_), home_->widget(), FALSE, FALSE,
-                     kToolbarWidgetSpacing);
-  gtk_util::SetButtonTriggersNavigation(home_->widget());
-
-  gtk_box_pack_start(GTK_BOX(toolbar_), toolbar_left_, FALSE, FALSE,
-                     kToolbarLeftAreaPadding);
-
-  location_hbox_ = gtk_hbox_new(FALSE, 0);
-  location_bar_->Init(ShouldOnlyShowLocation());
-  gtk_box_pack_start(GTK_BOX(location_hbox_), location_bar_->widget(), TRUE,
-                     TRUE, 0);
-
-  g_signal_connect(location_hbox_, "expose-event",
-                   G_CALLBACK(OnLocationHboxExposeThunk), this);
-  gtk_box_pack_start(GTK_BOX(toolbar_), location_hbox_, TRUE, TRUE,
-      ShouldOnlyShowLocation() ? 1 : 0);
-
-  if (!ShouldOnlyShowLocation()) {
-    actions_toolbar_.reset(new BrowserActionsToolbarGtk(browser_));
-    gtk_box_pack_start(GTK_BOX(toolbar_), actions_toolbar_->widget(),
-                       FALSE, FALSE, 0);
-  }
-
-  wrench_menu_image_ = gtk_image_new_from_pixbuf(
-      theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS));
-  wrench_menu_button_.reset(new CustomDrawButton(
-      GtkThemeProvider::GetFrom(profile_),
-      IDR_TOOLS, IDR_TOOLS_P, IDR_TOOLS_H, 0,
-      wrench_menu_image_));
-  GtkWidget* wrench_button = wrench_menu_button_->widget();
-
-  gtk_widget_set_tooltip_text(
-      wrench_button,
-      l10n_util::GetStringFUTF8(IDS_APPMENU_TOOLTIP,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
-  g_signal_connect(wrench_button, "button-press-event",
-                   G_CALLBACK(OnMenuButtonPressEventThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(wrench_button, GTK_CAN_FOCUS);
-
-  // Put the wrench button in a box so that we can paint the update notification
-  // over it.
-  GtkWidget* wrench_box = gtk_alignment_new(0, 0, 1, 1);
-  g_signal_connect_after(wrench_box, "expose-event",
-                         G_CALLBACK(OnWrenchMenuButtonExposeThunk), this);
-  gtk_container_add(GTK_CONTAINER(wrench_box), wrench_button);
-  gtk_box_pack_start(GTK_BOX(toolbar_), wrench_box, FALSE, FALSE, 4);
-
-  wrench_menu_.reset(new MenuGtk(this, &wrench_menu_model_));
-  registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
-                 Source<Profile>(browser_->profile()));
-
-  if (ShouldOnlyShowLocation()) {
-    gtk_widget_show(event_box_);
-    gtk_widget_show(alignment_);
-    gtk_widget_show(toolbar_);
-    gtk_widget_show_all(location_hbox_);
-    gtk_widget_hide(reload_->widget());
-  } else {
-    gtk_widget_show_all(event_box_);
-    if (actions_toolbar_->button_count() == 0)
-      gtk_widget_hide(actions_toolbar_->widget());
-  }
-  // Initialize pref-dependent UI state.
-  NotifyPrefChanged(NULL);
-
-  // Because the above does a recursive show all on all widgets we need to
-  // update the icon visibility to hide them.
-  location_bar_->UpdateContentSettingsIcons();
-
-  SetViewIDs();
-  theme_provider_->InitThemesFor(this);
-}
-
-void BrowserToolbarGtk::SetViewIDs() {
-  ViewIDUtil::SetID(widget(), VIEW_ID_TOOLBAR);
-  ViewIDUtil::SetID(back_->widget(), VIEW_ID_BACK_BUTTON);
-  ViewIDUtil::SetID(forward_->widget(), VIEW_ID_FORWARD_BUTTON);
-  ViewIDUtil::SetID(reload_->widget(), VIEW_ID_RELOAD_BUTTON);
-  ViewIDUtil::SetID(home_->widget(), VIEW_ID_HOME_BUTTON);
-  ViewIDUtil::SetID(location_bar_->widget(), VIEW_ID_LOCATION_BAR);
-  ViewIDUtil::SetID(wrench_menu_button_->widget(), VIEW_ID_APP_MENU);
-}
-
-void BrowserToolbarGtk::Show() {
-  gtk_widget_show(toolbar_);
-}
-
-void BrowserToolbarGtk::Hide() {
-  gtk_widget_hide(toolbar_);
-}
-
-LocationBar* BrowserToolbarGtk::GetLocationBar() const {
-  return location_bar_.get();
-}
-
-void BrowserToolbarGtk::UpdateForBookmarkBarVisibility(
-    bool show_bottom_padding) {
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_),
-      ShouldOnlyShowLocation() ? 0 : kTopBottomPadding,
-      !show_bottom_padding || ShouldOnlyShowLocation() ? 0 : kTopBottomPadding,
-      0, 0);
-}
-
-void BrowserToolbarGtk::ShowAppMenu() {
-  wrench_menu_->Cancel();
-  wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE);
-  wrench_menu_->PopupAsFromKeyEvent(wrench_menu_button_->widget());
-}
-
-// CommandUpdater::CommandObserver ---------------------------------------------
-
-void BrowserToolbarGtk::EnabledStateChangedForCommand(int id, bool enabled) {
-  GtkWidget* widget = NULL;
-  switch (id) {
-    case IDC_BACK:
-      widget = back_->widget();
-      break;
-    case IDC_FORWARD:
-      widget = forward_->widget();
-      break;
-    case IDC_HOME:
-      if (home_.get())
-        widget = home_->widget();
-      break;
-  }
-  if (widget) {
-    if (!enabled && GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) {
-      // If we're disabling a widget, GTK will helpfully restore it to its
-      // previous state when we re-enable it, even if that previous state
-      // is the prelight.  This looks bad.  See the bug for a simple repro.
-      // http://code.google.com/p/chromium/issues/detail?id=13729
-      gtk_widget_set_state(widget, GTK_STATE_NORMAL);
-    }
-    gtk_widget_set_sensitive(widget, enabled);
-  }
-}
-
-// MenuGtk::Delegate -----------------------------------------------------------
-
-void BrowserToolbarGtk::StoppedShowing() {
-  // Without these calls, the hover state can get stuck since the leave-notify
-  // event is not sent when clicking a button brings up the menu.
-  gtk_chrome_button_set_hover_state(
-      GTK_CHROME_BUTTON(wrench_menu_button_->widget()), 0.0);
-  wrench_menu_button_->UnsetPaintOverride();
-
-  // Stop showing the BG page badge when we close the wrench menu.
-  BackgroundPageTracker::GetInstance()->AcknowledgeBackgroundPages();
-}
-
-GtkIconSet* BrowserToolbarGtk::GetIconSetForId(int idr) {
-  return theme_provider_->GetIconSetForId(idr);
-}
-
-// Always show images because we desire that some icons always show
-// regardless of the system setting.
-bool BrowserToolbarGtk::AlwaysShowIconForCmd(int command_id) const {
-  return command_id == IDC_UPGRADE_DIALOG ||
-         command_id == IDC_VIEW_BACKGROUND_PAGES;
-}
-
-// menus::AcceleratorProvider
-
-bool BrowserToolbarGtk::GetAcceleratorForCommandId(
-    int id,
-    menus::Accelerator* accelerator) {
-  const menus::AcceleratorGtk* accelerator_gtk =
-      AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(id);
-  if (accelerator_gtk)
-    *accelerator = *accelerator_gtk;
-  return !!accelerator_gtk;
-}
-
-// NotificationObserver --------------------------------------------------------
-
-void BrowserToolbarGtk::Observe(NotificationType type,
-                                const NotificationSource& source,
-                                const NotificationDetails& details) {
-  if (type == NotificationType::PREF_CHANGED) {
-    NotifyPrefChanged(Details<std::string>(details).ptr());
-  } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    // Update the spacing around the menu buttons
-    bool use_gtk = theme_provider_->UseGtkTheme();
-    int border = use_gtk ? 0 : 2;
-    gtk_container_set_border_width(
-        GTK_CONTAINER(wrench_menu_button_->widget()), border);
-
-    // Force the height of the toolbar so we get the right amount of padding
-    // above and below the location bar. We always force the size of the widgets
-    // to either side of the location box, but we only force the location box
-    // size in chrome-theme mode because that's the only time we try to control
-    // the font size.
-    int toolbar_height = ShouldOnlyShowLocation() ?
-                         kToolbarHeightLocationBarOnly : kToolbarHeight;
-    gtk_container_foreach(GTK_CONTAINER(toolbar_), SetWidgetHeightRequest,
-                          GINT_TO_POINTER(toolbar_height));
-    gtk_widget_set_size_request(location_hbox_, -1,
-                                use_gtk ? -1 : toolbar_height);
-
-    // When using the GTK+ theme, we need to have the event box be visible so
-    // buttons don't get a halo color from the background.  When using Chromium
-    // themes, we want to let the background show through the toolbar.
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), use_gtk);
-
-    if (use_gtk) {
-      // We need to manually update the icon if we are in GTK mode. (Note that
-      // we set the initial value in Init()).
-      gtk_image_set_from_pixbuf(
-          GTK_IMAGE(wrench_menu_image_),
-          theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS));
-    }
-
-    UpdateRoundedness();
-  } else if (type == NotificationType::UPGRADE_RECOMMENDED ||
-             type == NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED) {
-    // Redraw the wrench menu to update the badge.
-    gtk_widget_queue_draw(wrench_menu_button_->widget());
-  } else if (type == NotificationType::ZOOM_LEVEL_CHANGED) {
-    // If our zoom level changed, we need to tell the menu to update its state,
-    // since the menu could still be open.
-    wrench_menu_->UpdateMenu();
-  } else {
-    NOTREACHED();
-  }
-}
-
-// BrowserToolbarGtk, public ---------------------------------------------------
-
-void BrowserToolbarGtk::SetProfile(Profile* profile) {
-  if (profile == profile_)
-    return;
-
-  profile_ = profile;
-  location_bar_->SetProfile(profile);
-}
-
-void BrowserToolbarGtk::UpdateTabContents(TabContents* contents,
-                                          bool should_restore_state) {
-  location_bar_->Update(should_restore_state ? contents : NULL);
-
-  if (actions_toolbar_.get())
-    actions_toolbar_->Update();
-}
-
-// BrowserToolbarGtk, private --------------------------------------------------
-
-void BrowserToolbarGtk::SetUpDragForHomeButton(bool enable) {
-  if (enable) {
-    gtk_drag_dest_set(home_->widget(), GTK_DEST_DEFAULT_ALL,
-                      NULL, 0, GDK_ACTION_COPY);
-    static const int targets[] = { gtk_dnd_util::TEXT_PLAIN,
-                                   gtk_dnd_util::TEXT_URI_LIST, -1 };
-    gtk_dnd_util::SetDestTargetList(home_->widget(), targets);
-
-    drop_handler_.reset(new GtkSignalRegistrar());
-    drop_handler_->Connect(home_->widget(), "drag-data-received",
-                           G_CALLBACK(OnDragDataReceivedThunk), this);
-  } else {
-    gtk_drag_dest_unset(home_->widget());
-    drop_handler_.reset(NULL);
-  }
-}
-
-bool BrowserToolbarGtk::UpdateRoundedness() {
-  // We still round the corners if we are in chrome theme mode, but we do it by
-  // drawing theme resources rather than changing the physical shape of the
-  // widget.
-  bool should_be_rounded = theme_provider_->UseGtkTheme() &&
-      window_->ShouldDrawContentDropShadow();
-
-  if (should_be_rounded == gtk_util::IsActingAsRoundedWindow(alignment_))
-    return false;
-
-  if (should_be_rounded) {
-    gtk_util::ActAsRoundedWindow(alignment_, GdkColor(), kToolbarCornerSize,
-                                 gtk_util::ROUNDED_TOP,
-                                 gtk_util::BORDER_NONE);
-  } else {
-    gtk_util::StopActingAsRoundedWindow(alignment_);
-  }
-
-  return true;
-}
-
-gboolean BrowserToolbarGtk::OnAlignmentExpose(GtkWidget* widget,
-                                              GdkEventExpose* e) {
-  // We may need to update the roundedness of the toolbar's top corners. In
-  // this case, don't draw; we'll be called again soon enough.
-  if (UpdateRoundedness())
-    return TRUE;
-
-  // We don't need to render the toolbar image in GTK mode.
-  if (theme_provider_->UseGtkTheme())
-    return FALSE;
-
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-  gdk_cairo_rectangle(cr, &e->area);
-  cairo_clip(cr);
-
-  gfx::Point tabstrip_origin =
-      window_->tabstrip()->GetTabStripOriginForWidget(widget);
-  // Fill the entire region with the toolbar color.
-  GdkColor color = theme_provider_->GetGdkColor(
-      BrowserThemeProvider::COLOR_TOOLBAR);
-  gdk_cairo_set_source_color(cr, &color);
-  cairo_fill(cr);
-
-  // The horizontal size of the top left and right corner images.
-  const int kCornerWidth = 4;
-  // The thickness of the shadow outside the toolbar's bounds; the offset
-  // between the edge of the toolbar and where we anchor the corner images.
-  const int kShadowThickness = 2;
-
-  gfx::Rect area(e->area);
-  gfx::Rect right(widget->allocation.x + widget->allocation.width -
-                      kCornerWidth,
-                  widget->allocation.y - kShadowThickness,
-                  kCornerWidth,
-                  widget->allocation.height + kShadowThickness);
-  gfx::Rect left(widget->allocation.x - kShadowThickness,
-                 widget->allocation.y - kShadowThickness,
-                 kCornerWidth,
-                 widget->allocation.height + kShadowThickness);
-
-  if (window_->ShouldDrawContentDropShadow()) {
-    // Leave room to draw rounded corners.
-    area = area.Subtract(right).Subtract(left);
-  }
-
-  CairoCachedSurface* background = theme_provider_->GetSurfaceNamed(
-      IDR_THEME_TOOLBAR, widget);
-  background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
-  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-  cairo_rectangle(cr, area.x(), area.y(), area.width(), area.height());
-  cairo_fill(cr);
-
-  if (!window_->ShouldDrawContentDropShadow()) {
-    // The rest of this function is for rounded corners. Our work is done here.
-    cairo_destroy(cr);
-    return FALSE;
-  }
-
-  bool draw_left_corner = left.Intersects(gfx::Rect(e->area));
-  bool draw_right_corner = right.Intersects(gfx::Rect(e->area));
-
-  if (draw_left_corner || draw_right_corner) {
-    // Create a mask which is composed of the left and/or right corners.
-    cairo_surface_t* target = cairo_surface_create_similar(
-        cairo_get_target(cr),
-        CAIRO_CONTENT_COLOR_ALPHA,
-        widget->allocation.x + widget->allocation.width,
-        widget->allocation.y + widget->allocation.height);
-    cairo_t* copy_cr = cairo_create(target);
-
-    cairo_set_operator(copy_cr, CAIRO_OPERATOR_SOURCE);
-    if (draw_left_corner) {
-      CairoCachedSurface* left_corner = theme_provider_->GetSurfaceNamed(
-          IDR_CONTENT_TOP_LEFT_CORNER_MASK, widget);
-      left_corner->SetSource(copy_cr, left.x(), left.y());
-      cairo_paint(copy_cr);
-    }
-    if (draw_right_corner) {
-      CairoCachedSurface* right_corner = theme_provider_->GetSurfaceNamed(
-          IDR_CONTENT_TOP_RIGHT_CORNER_MASK, widget);
-      right_corner->SetSource(copy_cr, right.x(), right.y());
-      // We fill a path rather than just painting because we don't want to
-      // overwrite the left corner.
-      cairo_rectangle(copy_cr, right.x(), right.y(),
-                      right.width(), right.height());
-      cairo_fill(copy_cr);
-    }
-
-    // Draw the background. CAIRO_OPERATOR_IN uses the existing pixel data as
-    // an alpha mask.
-    background->SetSource(copy_cr, tabstrip_origin.x(), tabstrip_origin.y());
-    cairo_set_operator(copy_cr, CAIRO_OPERATOR_IN);
-    cairo_pattern_set_extend(cairo_get_source(copy_cr), CAIRO_EXTEND_REPEAT);
-    cairo_paint(copy_cr);
-    cairo_destroy(copy_cr);
-
-    // Copy the temporary surface to the screen.
-    cairo_set_source_surface(cr, target, 0, 0);
-    cairo_paint(cr);
-    cairo_surface_destroy(target);
-  }
-
-  cairo_destroy(cr);
-
-  return FALSE;  // Allow subwidgets to paint.
-}
-
-gboolean BrowserToolbarGtk::OnLocationHboxExpose(GtkWidget* location_hbox,
-                                                 GdkEventExpose* e) {
-  if (theme_provider_->UseGtkTheme()) {
-    gtk_util::DrawTextEntryBackground(offscreen_entry_.get(),
-                                      location_hbox, &e->area,
-                                      &location_hbox->allocation);
-  }
-
-  return FALSE;
-}
-
-void BrowserToolbarGtk::OnButtonClick(GtkWidget* button) {
-  if ((button == back_->widget()) || (button == forward_->widget())) {
-    if (gtk_util::DispositionForCurrentButtonPressEvent() == CURRENT_TAB)
-      location_bar_->Revert();
-    return;
-  }
-
-  DCHECK(home_.get() && button == home_->widget()) <<
-      "Unexpected button click callback";
-  browser_->Home(gtk_util::DispositionForCurrentButtonPressEvent());
-}
-
-gboolean BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button,
-                                                   GdkEventButton* event) {
-  if (event->button != 1)
-    return FALSE;
-
-  wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE);
-  wrench_menu_->Popup(button, reinterpret_cast<GdkEvent*>(event));
-
-  return TRUE;
-}
-
-void BrowserToolbarGtk::OnDragDataReceived(GtkWidget* widget,
-    GdkDragContext* drag_context, gint x, gint y,
-    GtkSelectionData* data, guint info, guint time) {
-  if (info != gtk_dnd_util::TEXT_PLAIN) {
-    NOTIMPLEMENTED() << "Only support plain text drops for now, sorry!";
-    return;
-  }
-
-  GURL url(reinterpret_cast<char*>(data->data));
-  if (!url.is_valid())
-    return;
-
-  bool url_is_newtab = url.spec() == chrome::kChromeUINewTabURL;
-  home_page_is_new_tab_page_.SetValue(url_is_newtab);
-  if (!url_is_newtab)
-    home_page_.SetValue(url.spec());
-}
-
-void BrowserToolbarGtk::NotifyPrefChanged(const std::string* pref) {
-  if (!pref || *pref == prefs::kShowHomeButton) {
-    if (show_home_button_.GetValue() && !ShouldOnlyShowLocation()) {
-      gtk_widget_show(home_->widget());
-    } else {
-      gtk_widget_hide(home_->widget());
-    }
-  }
-
-  if (!pref ||
-      *pref == prefs::kHomePage ||
-      *pref == prefs::kHomePageIsNewTabPage)
-    SetUpDragForHomeButton(!home_page_.IsManaged() &&
-                           !home_page_is_new_tab_page_.IsManaged());
-}
-
-bool BrowserToolbarGtk::ShouldOnlyShowLocation() const {
-  // If we're a popup window, only show the location bar (omnibox).
-  return browser_->type() != Browser::TYPE_NORMAL;
-}
-
-gboolean BrowserToolbarGtk::OnWrenchMenuButtonExpose(GtkWidget* sender,
-                                                     GdkEventExpose* expose) {
-  const SkBitmap* badge = NULL;
-  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
-    badge = theme_provider_->GetBitmapNamed(IDR_UPDATE_BADGE);
-  } else if (BackgroundPageTracker::GetInstance()->
-             GetUnacknowledgedBackgroundPageCount()) {
-    badge = theme_provider_->GetBitmapNamed(IDR_BACKGROUND_BADGE);
-  } else {
-    return FALSE;
-  }
-
-  // Draw the chrome app menu icon onto the canvas.
-  gfx::CanvasSkiaPaint canvas(expose, false);
-  int x_offset = base::i18n::IsRTL() ? 0 :
-      sender->allocation.width - badge->width();
-  int y_offset = 0;
-  canvas.DrawBitmapInt(
-      *badge,
-      sender->allocation.x + x_offset,
-      sender->allocation.y + y_offset);
-
-  return FALSE;
-}
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h
deleted file mode 100644
index 431c573..0000000
--- a/chrome/browser/gtk/browser_toolbar_gtk.h
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BROWSER_TOOLBAR_GTK_H_
-#define CHROME_BROWSER_GTK_BROWSER_TOOLBAR_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <string>
-
-#include "app/active_window_watcher_x.h"
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "app/menus/accelerator.h"
-#include "app/menus/simple_menu_model.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/command_updater.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class BackForwardButtonGtk;
-class Browser;
-class BrowserActionsToolbarGtk;
-class BrowserWindowGtk;
-class CustomDrawButton;
-class GtkThemeProvider;
-class LocationBar;
-class LocationBarViewGtk;
-class Profile;
-class ReloadButtonGtk;
-class TabContents;
-class ToolbarModel;
-
-// View class that displays the GTK version of the toolbar and routes gtk
-// events back to the Browser.
-class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
-                          public menus::AcceleratorProvider,
-                          public MenuGtk::Delegate,
-                          public NotificationObserver {
- public:
-  explicit BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window);
-  virtual ~BrowserToolbarGtk();
-
-  // Create the contents of the toolbar. |top_level_window| is the GtkWindow
-  // to which we attach our accelerators.
-  void Init(Profile* profile, GtkWindow* top_level_window);
-
-  // Set the various widgets' ViewIDs.
-  void SetViewIDs();
-
-  void Show();
-  void Hide();
-
-  // Getter for the containing widget.
-  GtkWidget* widget() {
-    return event_box_;
-  }
-
-  // Getter for associated browser object.
-  Browser* browser() {
-    return browser_;
-  }
-
-  virtual LocationBar* GetLocationBar() const;
-
-  ReloadButtonGtk* GetReloadButton() { return reload_.get(); }
-
-  GtkWidget* GetAppMenuButton() { return wrench_menu_button_->widget(); }
-
-  BrowserActionsToolbarGtk* GetBrowserActionsToolbar() {
-    return actions_toolbar_.get();
-  }
-
-  LocationBarViewGtk* GetLocationBarView() { return location_bar_.get(); }
-
-  // We have to show padding on the bottom of the toolbar when the bookmark
-  // is in floating mode. Otherwise the bookmark bar will paint it for us.
-  void UpdateForBookmarkBarVisibility(bool show_bottom_padding);
-
-  void ShowAppMenu();
-
-  // Overridden from CommandUpdater::CommandObserver:
-  virtual void EnabledStateChangedForCommand(int id, bool enabled);
-
-  // Overridden from MenuGtk::Delegate:
-  virtual void StoppedShowing();
-  virtual GtkIconSet* GetIconSetForId(int idr);
-  virtual bool AlwaysShowIconForCmd(int command_id) const;
-
-  // Overridden from menus::AcceleratorProvider:
-  virtual bool GetAcceleratorForCommandId(int id,
-                                          menus::Accelerator* accelerator);
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  Profile* profile() { return profile_; }
-  void SetProfile(Profile* profile);
-
-  // Message that we should react to a state change.
-  void UpdateTabContents(TabContents* contents, bool should_restore_state);
-
- private:
-  // Connect/Disconnect signals for dragging a url onto the home button.
-  void SetUpDragForHomeButton(bool enable);
-
-  // Sets the top corners of the toolbar to rounded, or sets them to normal,
-  // depending on the state of the browser window. Returns false if no action
-  // was taken (the roundedness was already correct), true otherwise.
-  bool UpdateRoundedness();
-
-  // Gtk callback for the "expose-event" signal.
-  // The alignment contains the toolbar.
-  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnAlignmentExpose,
-                       GdkEventExpose*);
-  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnLocationHboxExpose,
-                       GdkEventExpose*);
-
-  // Gtk callback for the "clicked" signal.
-  CHROMEGTK_CALLBACK_0(BrowserToolbarGtk, void, OnButtonClick);
-
-  // Gtk callback to intercept mouse clicks to the menu buttons.
-  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnMenuButtonPressEvent,
-                       GdkEventButton*);
-
-  // Used for drags onto home button.
-  CHROMEGTK_CALLBACK_6(BrowserToolbarGtk, void, OnDragDataReceived,
-                       GdkDragContext*, gint, gint, GtkSelectionData*,
-                       guint, guint);
-
-  // Used to draw the upgrade notification badge.
-  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnWrenchMenuButtonExpose,
-                       GdkEventExpose*);
-
-  // Updates preference-dependent state.
-  void NotifyPrefChanged(const std::string* pref);
-
-  static void SetSyncMenuLabel(GtkWidget* widget, gpointer userdata);
-
-  // Sometimes we only want to show the location w/o the toolbar buttons (e.g.,
-  // in a popup window).
-  bool ShouldOnlyShowLocation() const;
-
-  // An event box that holds |toolbar_|. We need the toolbar to have its own
-  // GdkWindow when we use the GTK drawing because otherwise the color from our
-  // parent GdkWindow will leak through with some theme engines (such as
-  // Clearlooks).
-  GtkWidget* event_box_;
-
-  // This widget handles padding around the outside of the toolbar.
-  GtkWidget* alignment_;
-
-  // Gtk widgets. The toolbar is an hbox with each of the other pieces of the
-  // toolbar placed side by side.
-  GtkWidget* toolbar_;
-
-  // All widgets to the left or right of the |location_hbox_|. We put the
-  // widgets on either side of location_hbox_ in their own toolbar so we can
-  // set their minimum sizes independently of |location_hbox_| which needs to
-  // grow/shrink in GTK+ mode.
-  GtkWidget* toolbar_left_;
-
-  // Contains all the widgets of the location bar.
-  GtkWidget* location_hbox_;
-
-  // The location bar view.
-  scoped_ptr<LocationBarViewGtk> location_bar_;
-
-  // All the buttons in the toolbar.
-  scoped_ptr<BackForwardButtonGtk> back_, forward_;
-  scoped_ptr<CustomDrawButton> home_;
-  scoped_ptr<ReloadButtonGtk> reload_;
-  scoped_ptr<BrowserActionsToolbarGtk> actions_toolbar_;
-  scoped_ptr<CustomDrawButton> wrench_menu_button_;
-
-  // The image shown in GTK+ mode in the wrench button.
-  GtkWidget* wrench_menu_image_;
-
-  // The model that contains the security level, text, icon to display...
-  ToolbarModel* model_;
-
-  GtkThemeProvider* theme_provider_;
-
-  scoped_ptr<MenuGtk> wrench_menu_;
-
-  WrenchMenuModel wrench_menu_model_;
-
-  Browser* browser_;
-  BrowserWindowGtk* window_;
-  Profile* profile_;
-
-  // Controls whether or not a home button should be shown on the toolbar.
-  BooleanPrefMember show_home_button_;
-
-  // Preferences controlling the configured home page.
-  StringPrefMember home_page_;
-  BooleanPrefMember home_page_is_new_tab_page_;
-
-  NotificationRegistrar registrar_;
-
-  // A GtkEntry that isn't part of the hierarchy. We keep this for native
-  // rendering.
-  OwnedWidgetGtk offscreen_entry_;
-
-  // Manages the home button drop signal handler.
-  scoped_ptr<GtkSignalRegistrar> drop_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserToolbarGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BROWSER_TOOLBAR_GTK_H_
diff --git a/chrome/browser/gtk/browser_window_factory_gtk.cc b/chrome/browser/gtk/browser_window_factory_gtk.cc
deleted file mode 100644
index 054a0df..0000000
--- a/chrome/browser/gtk/browser_window_factory_gtk.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/browser_window.h"
-
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/find_bar_gtk.h"
-#include "chrome/browser/ui/browser.h"
-
-BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) {
-  return new BrowserWindowGtk(browser);
-}
-
-FindBar* BrowserWindow::CreateFindBar(Browser* browser) {
-  return new FindBarGtk(browser);
-}
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
deleted file mode 100644
index ec300a1..0000000
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ /dev/null
@@ -1,2249 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/browser_window_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-
-#include <string>
-
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "base/base_paths.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/scoped_ptr.h"
-#include "base/singleton.h"
-#include "base/string_util.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/debugger/devtools_window.h"
-#include "chrome/browser/dom_ui/bug_report_ui.h"
-#include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/gtk/about_chrome_dialog.h"
-#include "chrome/browser/gtk/accelerators_gtk.h"
-#include "chrome/browser/gtk/bookmark_bar_gtk.h"
-#include "chrome/browser/gtk/browser_titlebar.h"
-#include "chrome/browser/gtk/browser_toolbar_gtk.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h"
-#include "chrome/browser/gtk/collected_cookies_gtk.h"
-#include "chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h"
-#include "chrome/browser/gtk/download_in_progress_dialog_gtk.h"
-#include "chrome/browser/gtk/download_shelf_gtk.h"
-#include "chrome/browser/gtk/edit_search_engine_dialog.h"
-#include "chrome/browser/gtk/find_bar_gtk.h"
-#include "chrome/browser/gtk/fullscreen_exit_bubble_gtk.h"
-#include "chrome/browser/gtk/gtk_floating_container.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/html_dialog_gtk.h"
-#include "chrome/browser/gtk/import_dialog_gtk.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/browser/gtk/infobar_container_gtk.h"
-#include "chrome/browser/gtk/infobar_gtk.h"
-#include "chrome/browser/gtk/keyword_editor_view.h"
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-#include "chrome/browser/gtk/nine_box.h"
-#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
-#include "chrome/browser/gtk/reload_button_gtk.h"
-#include "chrome/browser/gtk/repost_form_warning_gtk.h"
-#include "chrome/browser/gtk/status_bubble_gtk.h"
-#include "chrome/browser/gtk/tab_contents_container_gtk.h"
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/gtk/task_manager_gtk.h"
-#include "chrome/browser/gtk/theme_install_bubble_view_gtk.h"
-#include "chrome/browser/gtk/update_recommended_dialog.h"
-#include "chrome/browser/page_info_window.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/ui/omnibox/location_bar.h"
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/browser/ui/window_sizer.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/native_web_keyboard_event.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/gtk_util.h"
-#include "gfx/rect.h"
-#include "gfx/skia_utils_gtk.h"
-#include "grit/app_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// The number of milliseconds between loading animation frames.
-const int kLoadingAnimationFrameTimeMs = 30;
-
-// Default height of dev tools pane when docked to the browser window.  This
-// matches the value in Views.
-const int kDefaultDevToolsHeight = 200;
-
-const int kMinDevToolsHeight = 50;
-
-const char* kBrowserWindowKey = "__BROWSER_WINDOW_GTK__";
-
-// The frame border is only visible in restored mode and is hardcoded to 4 px
-// on each side regardless of the system window border size.
-const int kFrameBorderThickness = 4;
-// While resize areas on Windows are normally the same size as the window
-// borders, our top area is shrunk by 1 px to make it easier to move the window
-// around with our thinner top grabbable strip.  (Incidentally, our side and
-// bottom resize areas don't match the frame border thickness either -- they
-// span the whole nonclient area, so there's no "dead zone" for the mouse.)
-const int kTopResizeAdjust = 1;
-// In the window corners, the resize areas don't actually expand bigger, but
-// the 16 px at the end of each edge triggers diagonal resizing.
-const int kResizeAreaCornerSize = 16;
-// The thickness of the shadow around the toolbar+web content area.  There are
-// actually a couple pixels more that should overlap the toolbar and web
-// content area, but we don't use those pixels.
-const int kContentShadowThickness = 2;
-// The offset to the background when the custom frame is off.  We want the
-// window background to line up with the tab background regardless of whether
-// we're in custom frame mode or not.  Since themes are designed with the
-// custom frame in mind, we need to offset the background when the custom frame
-// is off.
-const int kCustomFrameBackgroundVerticalOffset = 15;
-
-// The timeout in milliseconds before we'll get the true window position with
-// gtk_window_get_position() after the last GTK configure-event signal.
-const int kDebounceTimeoutMilliseconds = 100;
-
-gboolean MainWindowConfigured(GtkWindow* window, GdkEventConfigure* event,
-                              BrowserWindowGtk* browser_win) {
-  gfx::Rect bounds = gfx::Rect(event->x, event->y, event->width, event->height);
-  browser_win->OnBoundsChanged(bounds);
-  return FALSE;
-}
-
-gboolean MainWindowStateChanged(GtkWindow* window, GdkEventWindowState* event,
-                                BrowserWindowGtk* browser_win) {
-  browser_win->OnStateChanged(event->new_window_state, event->changed_mask);
-  return FALSE;
-}
-
-// Callback for the delete event.  This event is fired when the user tries to
-// close the window (e.g., clicking on the X in the window manager title bar).
-gboolean MainWindowDeleteEvent(GtkWidget* widget, GdkEvent* event,
-                               BrowserWindowGtk* window) {
-  window->Close();
-
-  // Return true to prevent the gtk window from being destroyed.  Close will
-  // destroy it for us.
-  return TRUE;
-}
-
-void MainWindowDestroy(GtkWidget* widget, BrowserWindowGtk* window) {
-  // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the
-  // signal right away, and we will be here (while Close() is still in the
-  // call stack).  In order to not reenter Close(), and to also follow the
-  // expectations of BrowserList, we should run the BrowserWindowGtk destructor
-  // not now, but after the run loop goes back to process messages.  Otherwise
-  // we will remove ourself from BrowserList while it's being iterated.
-  // Additionally, now that we know the window is gone, we need to make sure to
-  // set window_ to NULL, otherwise we will try to close the window again when
-  // we call Close() in the destructor.
-  //
-  // We don't want to use DeleteSoon() here since it won't work on a nested pump
-  // (like in UI tests).
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   new DeleteTask<BrowserWindowGtk>(window));
-}
-
-// Using gtk_window_get_position/size creates a race condition, so only use
-// this to get the initial bounds.  After window creation, we pick up the
-// normal bounds by connecting to the configure-event signal.
-gfx::Rect GetInitialWindowBounds(GtkWindow* window) {
-  gint x, y, width, height;
-  gtk_window_get_position(window, &x, &y);
-  gtk_window_get_size(window, &width, &height);
-  return gfx::Rect(x, y, width, height);
-}
-
-// Get the command ids of the key combinations that are not valid gtk
-// accelerators.
-int GetCustomCommandId(GdkEventKey* event) {
-  // Filter modifier to only include accelerator modifiers.
-  guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
-  switch (event->keyval) {
-    // Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see
-    // gtk_accelerator_valid), so we need to handle these accelerators
-    // manually.
-    // Some X clients (e.g. cygwin, NX client, etc.) also send GDK_KP_Tab when
-    // typing a tab key. We should also handle GDK_KP_Tab for such X clients as
-    // Firefox does.
-    case GDK_Tab:
-    case GDK_ISO_Left_Tab:
-    case GDK_KP_Tab:
-      if (GDK_CONTROL_MASK == modifier) {
-        return IDC_SELECT_NEXT_TAB;
-      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
-        return IDC_SELECT_PREVIOUS_TAB;
-      }
-      break;
-
-    default:
-      break;
-  }
-  return -1;
-}
-
-// Get the command ids of the accelerators that we don't want the native widget
-// to be able to override.
-int GetPreHandleCommandId(GdkEventKey* event) {
-  // Filter modifier to only include accelerator modifiers.
-  guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
-  switch (event->keyval) {
-    case GDK_Page_Down:
-      if (GDK_CONTROL_MASK == modifier) {
-        return IDC_SELECT_NEXT_TAB;
-      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
-        return IDC_MOVE_TAB_NEXT;
-      }
-      break;
-
-    case GDK_Page_Up:
-      if (GDK_CONTROL_MASK == modifier) {
-        return IDC_SELECT_PREVIOUS_TAB;
-      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
-        return IDC_MOVE_TAB_PREVIOUS;
-      }
-      break;
-
-    default:
-      break;
-  }
-  return -1;
-}
-
-GdkCursorType GdkWindowEdgeToGdkCursorType(GdkWindowEdge edge) {
-  switch (edge) {
-    case GDK_WINDOW_EDGE_NORTH_WEST:
-      return GDK_TOP_LEFT_CORNER;
-    case GDK_WINDOW_EDGE_NORTH:
-      return GDK_TOP_SIDE;
-    case GDK_WINDOW_EDGE_NORTH_EAST:
-      return GDK_TOP_RIGHT_CORNER;
-    case GDK_WINDOW_EDGE_WEST:
-      return GDK_LEFT_SIDE;
-    case GDK_WINDOW_EDGE_EAST:
-      return GDK_RIGHT_SIDE;
-    case GDK_WINDOW_EDGE_SOUTH_WEST:
-      return GDK_BOTTOM_LEFT_CORNER;
-    case GDK_WINDOW_EDGE_SOUTH:
-      return GDK_BOTTOM_SIDE;
-    case GDK_WINDOW_EDGE_SOUTH_EAST:
-      return GDK_BOTTOM_RIGHT_CORNER;
-    default:
-      NOTREACHED();
-  }
-  return GDK_LAST_CURSOR;
-}
-
-// A helper method for setting the GtkWindow size that should be used in place
-// of calling gtk_window_resize directly.  This is done to avoid a WM "feature"
-// where setting the window size to the monitor size causes the WM to set the
-// EWMH for full screen mode.
-void SetWindowSize(GtkWindow* window, const gfx::Size& size) {
-  GdkScreen* screen = gtk_window_get_screen(window);
-  gint num_monitors = gdk_screen_get_n_monitors(screen);
-  // Make sure the window doesn't match any monitor size.  We compare against
-  // all monitors because we don't know which monitor the window is going to
-  // open on (the WM decides that).
-  for (gint i = 0; i < num_monitors; ++i) {
-    GdkRectangle monitor_size;
-    gdk_screen_get_monitor_geometry(screen, i, &monitor_size);
-    if (gfx::Size(monitor_size.width, monitor_size.height) == size) {
-      gtk_window_resize(window, size.width(), size.height() - 1);
-      return;
-    }
-  }
-  gtk_window_resize(window, size.width(), size.height());
-}
-
-GQuark GetBrowserWindowQuarkKey() {
-  static GQuark quark = g_quark_from_static_string(kBrowserWindowKey);
-  return quark;
-}
-
-}  // namespace
-
-std::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_;
-
-BrowserWindowGtk::BrowserWindowGtk(Browser* browser)
-    :  browser_(browser),
-       state_(GDK_WINDOW_STATE_WITHDRAWN),
-       bookmark_bar_is_floating_(false),
-       frame_cursor_(NULL),
-       is_active_(true),
-       last_click_time_(0),
-       maximize_after_show_(false),
-       suppress_window_raise_(false),
-       accel_group_(NULL),
-       infobar_arrow_model_(this) {
-  // We register first so that other views like the toolbar can use the
-  // is_active() function in their ActiveWindowChanged() handlers.
-  ActiveWindowWatcherX::AddObserver(this);
-
-  use_custom_frame_pref_.Init(prefs::kUseCustomChromeFrame,
-      browser_->profile()->GetPrefs(), this);
-
-  // In some (older) versions of compiz, raising top-level windows when they
-  // are partially off-screen causes them to get snapped back on screen, not
-  // always even on the current virtual desktop.  If we are running under
-  // compiz, suppress such raises, as they are not necessary in compiz anyway.
-  std::string wm_name;
-  if (x11_util::GetWindowManagerName(&wm_name) && wm_name == "compiz")
-    suppress_window_raise_ = true;
-
-  window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
-  g_object_set_qdata(G_OBJECT(window_), GetBrowserWindowQuarkKey(), this);
-  gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK |
-                                             GDK_POINTER_MOTION_MASK);
-
-  // Add this window to its own unique window group to allow for
-  // window-to-parent modality.
-  gtk_window_group_add_window(gtk_window_group_new(), window_);
-  g_object_unref(gtk_window_get_group(window_));
-
-  // For popups, we initialize widgets then set the window geometry, because
-  // popups need the widgets inited before they can set the window size
-  // properly. For other windows, we set the geometry first to prevent resize
-  // flicker.
-  if (browser_->type() & Browser::TYPE_POPUP) {
-    InitWidgets();
-    SetGeometryHints();
-  } else {
-    SetGeometryHints();
-    InitWidgets();
-  }
-
-  ConnectAccelerators();
-
-  // Set the initial background color of widgets.
-  SetBackgroundColor();
-  HideUnsupportedWindowFeatures();
-
-  registrar_.Add(this, NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
-                 NotificationService::AllSources());
-}
-
-BrowserWindowGtk::~BrowserWindowGtk() {
-  ActiveWindowWatcherX::RemoveObserver(this);
-
-  browser_->tabstrip_model()->RemoveObserver(this);
-}
-
-gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget,
-                                               GdkEventExpose* event) {
-  // Draw the default background.
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-
-  if (UsingCustomPopupFrame()) {
-    DrawPopupFrame(cr, widget, event);
-  } else {
-    DrawCustomFrame(cr, widget, event);
-  }
-
-  DrawContentShadow(cr);
-
-  cairo_destroy(cr);
-
-  if (UseCustomFrame() && !IsMaximized()) {
-    static NineBox custom_frame_border(
-        IDR_WINDOW_TOP_LEFT_CORNER,
-        IDR_WINDOW_TOP_CENTER,
-        IDR_WINDOW_TOP_RIGHT_CORNER,
-        IDR_WINDOW_LEFT_SIDE,
-        0,
-        IDR_WINDOW_RIGHT_SIDE,
-        IDR_WINDOW_BOTTOM_LEFT_CORNER,
-        IDR_WINDOW_BOTTOM_CENTER,
-        IDR_WINDOW_BOTTOM_RIGHT_CORNER);
-
-    custom_frame_border.RenderToWidget(widget);
-  }
-
-  return FALSE;  // Allow subwidgets to paint.
-}
-
-void BrowserWindowGtk::DrawContentShadow(cairo_t* cr) {
-  // Draw the shadow above the toolbar. Tabs on the tabstrip will draw over us.
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
-      browser()->profile());
-  int left_x, top_y;
-  gtk_widget_translate_coordinates(toolbar_->widget(),
-      GTK_WIDGET(window_), 0, 0, &left_x,
-      &top_y);
-  int center_width = window_vbox_->allocation.width;
-
-  CairoCachedSurface* top_center = theme_provider->GetSurfaceNamed(
-      IDR_CONTENT_TOP_CENTER, GTK_WIDGET(window_));
-  CairoCachedSurface* top_right = theme_provider->GetSurfaceNamed(
-      IDR_CONTENT_TOP_RIGHT_CORNER, GTK_WIDGET(window_));
-  CairoCachedSurface* top_left = theme_provider->GetSurfaceNamed(
-      IDR_CONTENT_TOP_LEFT_CORNER, GTK_WIDGET(window_));
-
-  int center_left_x = left_x;
-  if (ShouldDrawContentDropShadow()) {
-    // Don't draw over the corners.
-    center_left_x += top_left->Width() - kContentShadowThickness;
-    center_width -= (top_left->Width() + top_right->Width());
-    center_width += 2 * kContentShadowThickness;
-  }
-
-  top_center->SetSource(cr, center_left_x, top_y - kContentShadowThickness);
-  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-  cairo_rectangle(cr, center_left_x, top_y - kContentShadowThickness,
-                  center_width, top_center->Height());
-  cairo_fill(cr);
-
-  // Only draw the rest of the shadow if the user has the custom frame enabled
-  // and the browser is not maximized.
-  if (!ShouldDrawContentDropShadow())
-    return;
-
-  // The top left corner has a width of 3 pixels. On Windows, the last column
-  // of pixels overlap the toolbar. We just crop it off on Linux.  The top
-  // corners extend to the base of the toolbar (one pixel above the dividing
-  // line).
-  int right_x = center_left_x + center_width;
-  top_left->SetSource(
-      cr, left_x - kContentShadowThickness, top_y - kContentShadowThickness);
-  // The toolbar is shorter in location bar only mode so clip the image to the
-  // height of the toolbar + the amount of shadow above the toolbar.
-  cairo_rectangle(cr,
-      left_x - kContentShadowThickness,
-      top_y - kContentShadowThickness,
-      top_left->Width(),
-      top_left->Height());
-  cairo_fill(cr);
-
-  // Likewise, we crop off the left column of pixels for the top right corner.
-  top_right->SetSource(cr, right_x, top_y - kContentShadowThickness);
-  cairo_rectangle(cr,
-      right_x,
-      top_y - kContentShadowThickness,
-      top_right->Width(),
-      top_right->Height());
-  cairo_fill(cr);
-
-  // Fill in the sides.  As above, we only draw 2 of the 3 columns on Linux.
-  int bottom_y;
-  gtk_widget_translate_coordinates(window_vbox_,
-      GTK_WIDGET(window_),
-      0, window_vbox_->allocation.height,
-      NULL, &bottom_y);
-  // |side_y| is where to start drawing the side shadows.  The top corners draw
-  // the sides down to the bottom of the toolbar.
-  int side_y = top_y - kContentShadowThickness + top_right->Height();
-  // |side_height| is how many pixels to draw for the side borders.  We do one
-  // pixel before the bottom of the web contents because that extra pixel is
-  // drawn by the bottom corners.
-  int side_height = bottom_y - side_y - 1;
-  if (side_height > 0) {
-    CairoCachedSurface* left = theme_provider->GetSurfaceNamed(
-        IDR_CONTENT_LEFT_SIDE, GTK_WIDGET(window_));
-    left->SetSource(cr, left_x - kContentShadowThickness, side_y);
-    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(cr,
-        left_x - kContentShadowThickness,
-        side_y,
-        kContentShadowThickness,
-        side_height);
-    cairo_fill(cr);
-
-    CairoCachedSurface* right = theme_provider->GetSurfaceNamed(
-        IDR_CONTENT_RIGHT_SIDE, GTK_WIDGET(window_));
-    int right_side_x =
-        right_x + top_right->Width() - kContentShadowThickness - 1;
-    right->SetSource(cr, right_side_x, side_y);
-    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(cr,
-        right_side_x,
-        side_y,
-        kContentShadowThickness,
-        side_height);
-    cairo_fill(cr);
-  }
-
-  // Draw the bottom corners.  The bottom corners also draw the bottom row of
-  // pixels of the side shadows.
-  CairoCachedSurface* bottom_left = theme_provider->GetSurfaceNamed(
-      IDR_CONTENT_BOTTOM_LEFT_CORNER, GTK_WIDGET(window_));
-  bottom_left->SetSource(cr, left_x - kContentShadowThickness, bottom_y - 1);
-  cairo_paint(cr);
-
-  CairoCachedSurface* bottom_right = theme_provider->GetSurfaceNamed(
-      IDR_CONTENT_BOTTOM_RIGHT_CORNER, GTK_WIDGET(window_));
-  bottom_right->SetSource(cr, right_x - 1, bottom_y - 1);
-  cairo_paint(cr);
-
-  // Finally, draw the bottom row. Since we don't overlap the contents, we clip
-  // the top row of pixels.
-  CairoCachedSurface* bottom = theme_provider->GetSurfaceNamed(
-      IDR_CONTENT_BOTTOM_CENTER, GTK_WIDGET(window_));
-  bottom->SetSource(cr, left_x + 1, bottom_y - 1);
-  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-  cairo_rectangle(cr,
-      left_x + 1,
-      bottom_y,
-      window_vbox_->allocation.width - 2,
-      kContentShadowThickness);
-  cairo_fill(cr);
-}
-
-void BrowserWindowGtk::DrawPopupFrame(cairo_t* cr,
-                                      GtkWidget* widget,
-                                      GdkEventExpose* event) {
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
-      browser()->profile());
-
-  // Like DrawCustomFrame(), except that we use the unthemed resources to draw
-  // the background. We do this because we can't rely on sane images in the
-  // theme that we can draw text on. (We tried using the tab background, but
-  // that has inverse saturation from what the user usually expects).
-  int image_name = GetThemeFrameResource();
-  CairoCachedSurface* surface = theme_provider->GetUnthemedSurfaceNamed(
-      image_name, widget);
-  surface->SetSource(cr, 0, GetVerticalOffset());
-  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REFLECT);
-  cairo_rectangle(cr, event->area.x, event->area.y,
-                  event->area.width, event->area.height);
-  cairo_fill(cr);
-}
-
-void BrowserWindowGtk::DrawCustomFrame(cairo_t* cr,
-                                       GtkWidget* widget,
-                                       GdkEventExpose* event) {
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
-      browser()->profile());
-
-  int image_name = GetThemeFrameResource();
-
-  CairoCachedSurface* surface = theme_provider->GetSurfaceNamed(
-      image_name, widget);
-  if (event->area.y < surface->Height()) {
-    surface->SetSource(cr, 0, GetVerticalOffset());
-
-    // The frame background isn't tiled vertically.
-    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(cr, event->area.x, event->area.y,
-                    event->area.width, surface->Height() - event->area.y);
-    cairo_fill(cr);
-  }
-
-  if (theme_provider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
-      !browser()->profile()->IsOffTheRecord()) {
-    CairoCachedSurface* theme_overlay = theme_provider->GetSurfaceNamed(
-        IsActive() ? IDR_THEME_FRAME_OVERLAY
-        : IDR_THEME_FRAME_OVERLAY_INACTIVE, widget);
-    theme_overlay->SetSource(cr, 0, GetVerticalOffset());
-    cairo_paint(cr);
-  }
-}
-
-int BrowserWindowGtk::GetVerticalOffset() {
-  return (IsMaximized() || (!UseCustomFrame())) ?
-      -kCustomFrameBackgroundVerticalOffset : 0;
-}
-
-int BrowserWindowGtk::GetThemeFrameResource() {
-  bool off_the_record = browser()->profile()->IsOffTheRecord();
-  int image_name;
-  if (IsActive()) {
-    image_name = off_the_record ? IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
-  } else {
-    image_name = off_the_record ? IDR_THEME_FRAME_INCOGNITO_INACTIVE :
-                 IDR_THEME_FRAME_INACTIVE;
-  }
-
-  return image_name;
-}
-
-void BrowserWindowGtk::Show() {
-  // The Browser associated with this browser window must become the active
-  // browser at the time Show() is called. This is the natural behaviour under
-  // Windows, but gtk_widget_show won't show the widget (and therefore won't
-  // call OnFocusIn()) until we return to the runloop. Therefore any calls to
-  // BrowserList::GetLastActive() (for example, in bookmark_util), will return
-  // the previous browser instead if we don't explicitly set it here.
-  BrowserList::SetLastActive(browser());
-
-  gtk_window_present(window_);
-  if (maximize_after_show_) {
-    gtk_window_maximize(window_);
-    maximize_after_show_ = false;
-  }
-
-  // If we have sized the window by setting a size request for the render
-  // area, then undo it so that the render view can later adjust its own
-  // size.
-  gtk_widget_set_size_request(contents_container_->widget(), -1, -1);
-}
-
-void BrowserWindowGtk::SetBoundsImpl(const gfx::Rect& bounds,
-                                     bool exterior,
-                                     bool move) {
-  gint x = static_cast<gint>(bounds.x());
-  gint y = static_cast<gint>(bounds.y());
-  gint width = static_cast<gint>(bounds.width());
-  gint height = static_cast<gint>(bounds.height());
-
-  if (move)
-    gtk_window_move(window_, x, y);
-
-  if (exterior) {
-    SetWindowSize(window_, gfx::Size(width, height));
-  } else {
-    gtk_widget_set_size_request(contents_container_->widget(),
-                                width, height);
-  }
-}
-
-void BrowserWindowGtk::SetBounds(const gfx::Rect& bounds) {
-  SetBoundsImpl(bounds, true, true);
-}
-
-void BrowserWindowGtk::Close() {
-  // We're already closing.  Do nothing.
-  if (!window_)
-    return;
-
-  if (!CanClose())
-    return;
-
-  // We're going to destroy the window, make sure the tab strip isn't running
-  // any animations which may still reference GtkWidgets.
-  tabstrip_->StopAnimation();
-
-  SaveWindowPosition();
-
-  if (accel_group_) {
-    // Disconnecting the keys we connected to our accelerator group frees the
-    // closures allocated in ConnectAccelerators.
-    AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
-    for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
-         iter != accelerators->end(); ++iter) {
-      gtk_accel_group_disconnect_key(accel_group_,
-          iter->second.GetGdkKeyCode(),
-          static_cast<GdkModifierType>(iter->second.modifiers()));
-    }
-    gtk_window_remove_accel_group(window_, accel_group_);
-    g_object_unref(accel_group_);
-    accel_group_ = NULL;
-  }
-
-  // Cancel any pending callback from the window configure debounce timer.
-  window_configure_debounce_timer_.Stop();
-
-  // Likewise for the loading animation.
-  loading_animation_timer_.Stop();
-
-  GtkWidget* window = GTK_WIDGET(window_);
-  // To help catch bugs in any event handlers that might get fired during the
-  // destruction, set window_ to NULL before any handlers will run.
-  window_ = NULL;
-  titlebar_->set_window(NULL);
-  gtk_widget_destroy(window);
-}
-
-void BrowserWindowGtk::Activate() {
-  gtk_window_present(window_);
-}
-
-void BrowserWindowGtk::Deactivate() {
-  gdk_window_lower(GTK_WIDGET(window_)->window);
-}
-
-bool BrowserWindowGtk::IsActive() const {
-  return is_active_;
-}
-
-void BrowserWindowGtk::FlashFrame() {
-  // May not be respected by all window managers.
-  gtk_window_set_urgency_hint(window_, TRUE);
-}
-
-gfx::NativeWindow BrowserWindowGtk::GetNativeHandle() {
-  return window_;
-}
-
-BrowserWindowTesting* BrowserWindowGtk::GetBrowserWindowTesting() {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-StatusBubble* BrowserWindowGtk::GetStatusBubble() {
-  return status_bubble_.get();
-}
-
-void BrowserWindowGtk::SelectedTabToolbarSizeChanged(bool is_animating) {
-  // On Windows, this is used for a performance optimization.
-  // http://code.google.com/p/chromium/issues/detail?id=12291
-}
-
-void BrowserWindowGtk::UpdateTitleBar() {
-  string16 title = browser_->GetWindowTitleForCurrentTab();
-  gtk_window_set_title(window_, UTF16ToUTF8(title).c_str());
-  if (ShouldShowWindowIcon())
-    titlebar_->UpdateTitleAndIcon();
-}
-
-void BrowserWindowGtk::ShelfVisibilityChanged() {
-  MaybeShowBookmarkBar(false);
-}
-
-void BrowserWindowGtk::UpdateDevTools() {
-  UpdateDevToolsForContents(
-      browser_->GetSelectedTabContents());
-}
-
-void BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) {
-  if (should_animate) {
-    if (!loading_animation_timer_.IsRunning()) {
-      // Loads are happening, and the timer isn't running, so start it.
-      loading_animation_timer_.Start(
-          base::TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
-          &BrowserWindowGtk::LoadingAnimationCallback);
-    }
-  } else {
-    if (loading_animation_timer_.IsRunning()) {
-      loading_animation_timer_.Stop();
-      // Loads are now complete, update the state if a task was scheduled.
-      LoadingAnimationCallback();
-    }
-  }
-}
-
-void BrowserWindowGtk::LoadingAnimationCallback() {
-  if (browser_->type() == Browser::TYPE_NORMAL) {
-    // Loading animations are shown in the tab for tabbed windows.  We check the
-    // browser type instead of calling IsTabStripVisible() because the latter
-    // will return false for fullscreen windows, but we still need to update
-    // their animations (so that when they come out of fullscreen mode they'll
-    // be correct).
-    tabstrip_->UpdateLoadingAnimations();
-  } else if (ShouldShowWindowIcon()) {
-    // ... or in the window icon area for popups and app windows.
-    TabContents* tab_contents = browser_->GetSelectedTabContents();
-    // GetSelectedTabContents can return NULL for example under Purify when
-    // the animations are running slowly and this function is called on
-    // a timer through LoadingAnimationCallback.
-    titlebar_->UpdateThrobber(tab_contents);
-  }
-}
-
-void BrowserWindowGtk::SetStarredState(bool is_starred) {
-  toolbar_->GetLocationBarView()->SetStarred(is_starred);
-}
-
-gfx::Rect BrowserWindowGtk::GetRestoredBounds() const {
-  return restored_bounds_;
-}
-
-bool BrowserWindowGtk::IsMaximized() const {
-  return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
-}
-
-bool BrowserWindowGtk::ShouldDrawContentDropShadow() {
-  return !IsMaximized() && UseCustomFrame();
-}
-
-void BrowserWindowGtk::SetFullscreen(bool fullscreen) {
-  // gtk_window_(un)fullscreen asks the window manager to toggle the EWMH
-  // for fullscreen windows.  Not all window managers support this.
-  if (fullscreen) {
-    gtk_window_fullscreen(window_);
-  } else {
-    // Work around a bug where if we try to unfullscreen, metacity immediately
-    // fullscreens us again.  This is a little flickery and not necessary if
-    // there's a gnome-panel, but it's not easy to detect whether there's a
-    // panel or not.
-    std::string wm_name;
-    bool unmaximize_before_unfullscreen = IsMaximized() &&
-        x11_util::GetWindowManagerName(&wm_name) && wm_name == "Metacity";
-    if (unmaximize_before_unfullscreen)
-      UnMaximize();
-
-    gtk_window_unfullscreen(window_);
-
-    if (unmaximize_before_unfullscreen)
-      gtk_window_maximize(window_);
-  }
-}
-
-bool BrowserWindowGtk::IsFullscreen() const {
-  return (state_ & GDK_WINDOW_STATE_FULLSCREEN);
-}
-
-bool BrowserWindowGtk::IsFullscreenBubbleVisible() const {
-  return fullscreen_exit_bubble_.get() ? true : false;
-}
-
-LocationBar* BrowserWindowGtk::GetLocationBar() const {
-  return toolbar_->GetLocationBar();
-}
-
-void BrowserWindowGtk::SetFocusToLocationBar(bool select_all) {
-  if (!IsFullscreen())
-    GetLocationBar()->FocusLocation(select_all);
-}
-
-void BrowserWindowGtk::UpdateReloadStopState(bool is_loading, bool force) {
-  toolbar_->GetReloadButton()->ChangeMode(
-      is_loading ? ReloadButtonGtk::MODE_STOP : ReloadButtonGtk::MODE_RELOAD,
-      force);
-}
-
-void BrowserWindowGtk::UpdateToolbar(TabContentsWrapper* contents,
-                                     bool should_restore_state) {
-  toolbar_->UpdateTabContents(contents->tab_contents(), should_restore_state);
-}
-
-void BrowserWindowGtk::FocusToolbar() {
-  NOTIMPLEMENTED();
-}
-
-void BrowserWindowGtk::FocusAppMenu() {
-  NOTIMPLEMENTED();
-}
-
-void BrowserWindowGtk::FocusBookmarksToolbar() {
-  NOTIMPLEMENTED();
-}
-
-void BrowserWindowGtk::FocusChromeOSStatus() {
-  NOTIMPLEMENTED();
-}
-
-void BrowserWindowGtk::RotatePaneFocus(bool forwards) {
-  NOTIMPLEMENTED();
-}
-
-bool BrowserWindowGtk::IsBookmarkBarVisible() const {
-  return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR) &&
-      bookmark_bar_.get() &&
-      browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
-}
-
-bool BrowserWindowGtk::IsBookmarkBarAnimating() const {
-  if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
-    return true;
-  return false;
-}
-
-bool BrowserWindowGtk::IsTabStripEditable() const {
-  return !tabstrip()->IsDragSessionActive() &&
-      !tabstrip()->IsActiveDropTarget();
-}
-
-bool BrowserWindowGtk::IsToolbarVisible() const {
-  return IsToolbarSupported();
-}
-
-void BrowserWindowGtk::ConfirmAddSearchProvider(const TemplateURL* template_url,
-                                                Profile* profile) {
-  new EditSearchEngineDialog(window_, template_url, NULL, profile);
-}
-
-void BrowserWindowGtk::ToggleBookmarkBar() {
-  bookmark_utils::ToggleWhenVisible(browser_->profile());
-}
-
-views::Window* BrowserWindowGtk::ShowAboutChromeDialog() {
-  ShowAboutDialogForProfile(window_, browser_->profile());
-  return NULL;
-}
-
-void BrowserWindowGtk::ShowUpdateChromeDialog() {
-  UpdateRecommendedDialog::Show(window_);
-}
-
-void BrowserWindowGtk::ShowTaskManager() {
-  TaskManagerGtk::Show();
-}
-
-void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
-                                          bool already_bookmarked) {
-  toolbar_->GetLocationBarView()->ShowStarBubble(url, !already_bookmarked);
-}
-
-bool BrowserWindowGtk::IsDownloadShelfVisible() const {
-  return download_shelf_.get() && download_shelf_->IsShowing();
-}
-
-DownloadShelf* BrowserWindowGtk::GetDownloadShelf() {
-  if (!download_shelf_.get())
-    download_shelf_.reset(new DownloadShelfGtk(browser_.get(),
-                                               render_area_vbox_));
-  return download_shelf_.get();
-}
-
-void BrowserWindowGtk::ShowReportBugDialog() {
-  browser::ShowHtmlBugReportView(window_, bounds_, browser_.get());
-}
-
-void BrowserWindowGtk::ShowClearBrowsingDataDialog() {
-  ClearBrowsingDataDialogGtk::Show(window_, browser_->profile());
-}
-
-void BrowserWindowGtk::ShowImportDialog() {
-  ImportDialogGtk::Show(window_, browser_->profile(), ALL);
-}
-
-void BrowserWindowGtk::ShowSearchEnginesDialog() {
-  KeywordEditorView::Show(browser_->profile());
-}
-
-void BrowserWindowGtk::ShowPasswordManager() {
-  NOTIMPLEMENTED();
-}
-
-void BrowserWindowGtk::ShowRepostFormWarningDialog(TabContents* tab_contents) {
-  new RepostFormWarningGtk(GetNativeHandle(), tab_contents);
-}
-
-void BrowserWindowGtk::ShowContentSettingsWindow(
-    ContentSettingsType content_type,
-    Profile* profile) {
-  ContentSettingsWindowGtk::Show(GetNativeHandle(), content_type, profile);
-}
-
-void BrowserWindowGtk::ShowCollectedCookiesDialog(TabContents* tab_contents) {
-  // Deletes itself on close.
-  new CollectedCookiesGtk(GetNativeHandle(), tab_contents);
-}
-
-void BrowserWindowGtk::ShowProfileErrorDialog(int message_id) {
-  std::string title = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
-  std::string message = l10n_util::GetStringUTF8(message_id);
-  GtkWidget* dialog = gtk_message_dialog_new(window_,
-      static_cast<GtkDialogFlags>(0), GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
-      "%s", message.c_str());
-  gtk_util::ApplyMessageDialogQuirks(dialog);
-  gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
-  g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
-  gtk_widget_show_all(dialog);
-}
-
-void BrowserWindowGtk::ShowThemeInstallBubble() {
-  ThemeInstallBubbleViewGtk::Show(window_);
-}
-
-void BrowserWindowGtk::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
-                                      gfx::NativeWindow parent_window) {
-  HtmlDialogGtk::ShowHtmlDialogGtk(browser_.get(), delegate, parent_window);
-}
-
-void BrowserWindowGtk::UserChangedTheme() {
-  SetBackgroundColor();
-  gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
-      &GTK_WIDGET(window_)->allocation, TRUE);
-  UpdateWindowShape(bounds_.width(), bounds_.height());
-}
-
-int BrowserWindowGtk::GetExtraRenderViewHeight() const {
-  int sum = infobar_container_->TotalHeightOfAnimatingBars();
-  if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
-    sum += bookmark_bar_->GetHeight();
-  if (download_shelf_.get() && download_shelf_->IsClosing())
-    sum += download_shelf_->GetHeight();
-  return sum;
-}
-
-void BrowserWindowGtk::TabContentsFocused(TabContents* tab_contents) {
-  NOTIMPLEMENTED();
-}
-
-void BrowserWindowGtk::ShowPageInfo(Profile* profile,
-                                    const GURL& url,
-                                    const NavigationEntry::SSLStatus& ssl,
-                                    bool show_history) {
-  browser::ShowPageInfoBubble(window_, profile, url, ssl, show_history);
-}
-
-void BrowserWindowGtk::ShowAppMenu() {
-  toolbar_->ShowAppMenu();
-}
-
-bool BrowserWindowGtk::PreHandleKeyboardEvent(
-    const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
-  GdkEventKey* os_event = event.os_event;
-
-  if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown)
-    return false;
-
-  // We first find out the browser command associated to the |event|.
-  // Then if the command is a reserved one, and should be processed immediately
-  // according to the |event|, the command will be executed immediately.
-  // Otherwise we just set |*is_keyboard_shortcut| properly and return false.
-
-  // First check if it's a custom accelerator.
-  int id = GetCustomCommandId(os_event);
-
-  // Then check if it's a predefined accelerator bound to the window.
-  if (id == -1) {
-    // This piece of code is based on the fact that calling
-    // gtk_window_activate_key() method against |window_| may only trigger a
-    // browser command execution, by matching a global accelerator
-    // defined in above |kAcceleratorMap|.
-    //
-    // Here we need to retrieve the command id (if any) associated to the
-    // keyboard event. Instead of looking up the command id in above
-    // |kAcceleratorMap| table by ourselves, we block the command execution of
-    // the |browser_| object then send the keyboard event to the |window_| by
-    // calling gtk_window_activate_key() method, as if we are activating an
-    // accelerator key. Then we can retrieve the command id from the
-    // |browser_| object.
-    //
-    // Pros of this approach:
-    // 1. We don't need to care about keyboard layout problem, as
-    //    gtk_window_activate_key() method handles it for us.
-    //
-    // Cons:
-    // 1. The logic is a little complicated.
-    // 2. We should be careful not to introduce any accelerators that trigger
-    //    customized code instead of browser commands.
-    browser_->SetBlockCommandExecution(true);
-    gtk_window_activate_key(window_, os_event);
-    // We don't need to care about the WindowOpenDisposition value,
-    // because all commands executed in this path use the default value.
-    id = browser_->GetLastBlockedCommand(NULL);
-    browser_->SetBlockCommandExecution(false);
-  }
-
-  if (id == -1)
-    return false;
-
-  // Executing the command may cause |this| object to be destroyed.
-  if (browser_->IsReservedCommand(id) && !event.match_edit_command)
-    return browser_->ExecuteCommandIfEnabled(id);
-
-  // The |event| is a keyboard shortcut.
-  DCHECK(is_keyboard_shortcut != NULL);
-  *is_keyboard_shortcut = true;
-
-  return false;
-}
-
-void BrowserWindowGtk::HandleKeyboardEvent(
-    const NativeWebKeyboardEvent& event) {
-  GdkEventKey* os_event = event.os_event;
-
-  if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown)
-    return;
-
-  // Handles a key event in following sequence:
-  // 1. Our special key accelerators, such as ctrl-tab, etc.
-  // 2. Gtk accelerators.
-  // This sequence matches the default key press handler of GtkWindow.
-  //
-  // It's not necessary to care about the keyboard layout, as
-  // gtk_window_activate_key() takes care of it automatically.
-  int id = GetCustomCommandId(os_event);
-  if (id != -1)
-    browser_->ExecuteCommandIfEnabled(id);
-  else
-    gtk_window_activate_key(window_, os_event);
-}
-
-void BrowserWindowGtk::ShowCreateWebAppShortcutsDialog(
-    TabContents* tab_contents) {
-  CreateWebApplicationShortcutsDialogGtk::Show(window_, tab_contents);
-}
-
-void BrowserWindowGtk::ShowCreateChromeAppShortcutsDialog(
-    Profile* profile, const Extension* app) {
-  CreateChromeApplicationShortcutsDialogGtk::Show(window_, app);
-}
-
-void BrowserWindowGtk::Cut() {
-  gtk_util::DoCut(this);
-}
-
-void BrowserWindowGtk::Copy() {
-  gtk_util::DoCopy(this);
-}
-
-void BrowserWindowGtk::Paste() {
-  gtk_util::DoPaste(this);
-}
-
-void BrowserWindowGtk::PrepareForInstant() {
-  TabContents* contents = contents_container_->GetTabContents();
-  if (contents)
-    contents->FadeForInstant(true);
-}
-
-void BrowserWindowGtk::ShowInstant(TabContents* preview_contents) {
-  contents_container_->SetPreviewContents(preview_contents);
-  MaybeShowBookmarkBar(false);
-
-  TabContents* contents = contents_container_->GetTabContents();
-  if (contents)
-    contents->CancelInstantFade();
-}
-
-void BrowserWindowGtk::HideInstant(bool instant_is_active) {
-  contents_container_->PopPreviewContents();
-  MaybeShowBookmarkBar(false);
-
-  TabContents* contents = contents_container_->GetTabContents();
-  if (contents) {
-    if (instant_is_active)
-      contents->FadeForInstant(false);
-    else
-      contents->CancelInstantFade();
-  }
-}
-
-gfx::Rect BrowserWindowGtk::GetInstantBounds() {
-  return gtk_util::GetWidgetScreenBounds(contents_container_->widget());
-}
-
-void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
-  new DownloadInProgressDialogGtk(browser());
-}
-
-void BrowserWindowGtk::Observe(NotificationType type,
-                               const NotificationSource& source,
-                               const NotificationDetails& details) {
-  switch (type.value) {
-    case NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED:
-      MaybeShowBookmarkBar(true);
-      break;
-
-    case NotificationType::PREF_CHANGED: {
-      std::string* pref_name = Details<std::string>(details).ptr();
-      if (*pref_name == prefs::kUseCustomChromeFrame) {
-        UpdateCustomFrame();
-      } else {
-        NOTREACHED() << "Got pref change notification we didn't register for!";
-      }
-      break;
-    }
-
-    default:
-      NOTREACHED() << "Got a notification we didn't register for!";
-  }
-}
-
-void BrowserWindowGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
-  // We use index here rather than comparing |contents| because by this time
-  // the model has already removed |contents| from its list, so
-  // browser_->GetSelectedTabContents() will return NULL or something else.
-  if (index == browser_->tabstrip_model()->selected_index())
-    infobar_container_->ChangeTabContents(NULL);
-  contents_container_->DetachTabContents(contents->tab_contents());
-  UpdateDevToolsForContents(NULL);
-}
-
-void BrowserWindowGtk::TabSelectedAt(TabContentsWrapper* old_contents,
-                                     TabContentsWrapper* new_contents,
-                                     int index,
-                                     bool user_gesture) {
-  DCHECK(old_contents != new_contents);
-
-  if (old_contents && !old_contents->tab_contents()->is_being_destroyed())
-    old_contents->view()->StoreFocus();
-
-  // Update various elements that are interested in knowing the current
-  // TabContents.
-  infobar_container_->ChangeTabContents(new_contents->tab_contents());
-  contents_container_->SetTabContents(new_contents->tab_contents());
-  UpdateDevToolsForContents(new_contents->tab_contents());
-
-  new_contents->tab_contents()->DidBecomeSelected();
-  // TODO(estade): after we manage browser activation, add a check to make sure
-  // we are the active browser before calling RestoreFocus().
-  if (!browser_->tabstrip_model()->closing_all()) {
-    new_contents->view()->RestoreFocus();
-    if (new_contents->tab_contents()->find_ui_active())
-      browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
-  }
-
-  // Update all the UI bits.
-  UpdateTitleBar();
-  UpdateToolbar(new_contents, true);
-  MaybeShowBookmarkBar(false);
-}
-
-void BrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
-  // Do nothing if we're in the process of closing the browser window.
-  if (!window_)
-    return;
-
-  bool is_active = (GTK_WIDGET(window_)->window == active_window);
-  bool changed = (is_active != is_active_);
-
-  if (is_active && changed) {
-    // If there's an app modal dialog (e.g., JS alert), try to redirect
-    // the user's attention to the window owning the dialog.
-    if (AppModalDialogQueue::GetInstance()->HasActiveDialog()) {
-      AppModalDialogQueue::GetInstance()->ActivateModalDialog();
-      return;
-    }
-  }
-
-  is_active_ = is_active;
-  if (changed) {
-    SetBackgroundColor();
-    gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
-                               &GTK_WIDGET(window_)->allocation, TRUE);
-    // For some reason, the above two calls cause the window shape to be
-    // lost so reset it.
-    UpdateWindowShape(bounds_.width(), bounds_.height());
-  }
-}
-
-void BrowserWindowGtk::MaybeShowBookmarkBar(bool animate) {
-  if (!IsBookmarkBarSupported())
-    return;
-
-  TabContents* contents = GetDisplayedTabContents();
-  bool show_bar = false;
-
-  if (IsBookmarkBarSupported() && contents) {
-    bookmark_bar_->SetProfile(contents->profile());
-    bookmark_bar_->SetPageNavigator(contents);
-    show_bar = true;
-  }
-
-  if (show_bar && contents && !contents->ShouldShowBookmarkBar()) {
-    PrefService* prefs = contents->profile()->GetPrefs();
-    show_bar = prefs->GetBoolean(prefs::kShowBookmarkBar) && !IsFullscreen();
-  }
-
-  if (show_bar) {
-    bookmark_bar_->Show(animate);
-  } else if (IsFullscreen()) {
-    bookmark_bar_->EnterFullscreen();
-  } else {
-    bookmark_bar_->Hide(animate);
-  }
-}
-
-void BrowserWindowGtk::UpdateDevToolsForContents(TabContents* contents) {
-  TabContents* old_devtools = devtools_container_->GetTabContents();
-  TabContents* devtools_contents = contents ?
-      DevToolsWindow::GetDevToolsContents(contents) : NULL;
-  if (old_devtools == devtools_contents)
-    return;
-
-  if (old_devtools)
-    devtools_container_->DetachTabContents(old_devtools);
-
-  devtools_container_->SetTabContents(devtools_contents);
-  if (devtools_contents) {
-    // TabContentsViewGtk::WasShown is not called when tab contents is shown by
-    // anything other than user selecting a Tab.
-    // See TabContentsViewWin::OnWindowPosChanged for reference on how it should
-    // be implemented.
-    devtools_contents->ShowContents();
-  }
-
-  bool should_show = old_devtools == NULL && devtools_contents != NULL;
-  bool should_hide = old_devtools != NULL && devtools_contents == NULL;
-  if (should_show) {
-    gtk_widget_show(devtools_container_->widget());
-  } else if (should_hide) {
-    // Store split offset when hiding devtools window only.
-    gint divider_offset = gtk_paned_get_position(GTK_PANED(contents_split_));
-    g_browser_process->local_state()->SetInteger(
-        prefs::kDevToolsSplitLocation, divider_offset);
-    gtk_widget_hide(devtools_container_->widget());
-  }
-}
-
-void BrowserWindowGtk::DestroyBrowser() {
-  browser_.reset();
-}
-
-void BrowserWindowGtk::OnBoundsChanged(const gfx::Rect& bounds) {
-  GetLocationBar()->location_entry()->ClosePopup();
-
-  TabContents* tab_contents = GetDisplayedTabContents();
-  if (tab_contents)
-    tab_contents->WindowMoveOrResizeStarted();
-
-  if (bounds_.size() != bounds.size())
-    OnSizeChanged(bounds.width(), bounds.height());
-
-  // We update |bounds_| but not |restored_bounds_| here.  The latter needs
-  // to be updated conditionally when the window is non-maximized and non-
-  // fullscreen, but whether those state updates have been processed yet is
-  // window-manager specific.  We update |restored_bounds_| in the debounced
-  // handler below, after the window state has been updated.
-  bounds_ = bounds;
-
-  // When a window is moved or resized, GTK will call MainWindowConfigured()
-  // above.  The GdkEventConfigure* that it gets doesn't have quite the right
-  // coordinates though (they're relative to the drawable window area, rather
-  // than any window manager decorations, if enabled), so we need to call
-  // gtk_window_get_position() to get the right values.  (Otherwise session
-  // restore, if enabled, will restore windows to incorrect positions.)  That's
-  // a round trip to the X server though, so we set a debounce timer and only
-  // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a
-  // reconfigure event in a short while.
-  // We don't use Reset() because the timer may not yet be running.
-  // (In that case Stop() is a no-op.)
-  window_configure_debounce_timer_.Stop();
-  window_configure_debounce_timer_.Start(base::TimeDelta::FromMilliseconds(
-      kDebounceTimeoutMilliseconds), this,
-      &BrowserWindowGtk::OnDebouncedBoundsChanged);
-}
-
-void BrowserWindowGtk::OnDebouncedBoundsChanged() {
-  gint x, y;
-  gtk_window_get_position(window_, &x, &y);
-  gfx::Point origin(x, y);
-  bounds_.set_origin(origin);
-  if (!IsFullscreen() && !IsMaximized())
-    restored_bounds_ = bounds_;
-  SaveWindowPosition();
-}
-
-void BrowserWindowGtk::OnStateChanged(GdkWindowState state,
-                                      GdkWindowState changed_mask) {
-  state_ = state;
-
-  if (changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
-    bool is_fullscreen = state & GDK_WINDOW_STATE_FULLSCREEN;
-    browser_->UpdateCommandsForFullscreenMode(is_fullscreen);
-    if (is_fullscreen) {
-      UpdateCustomFrame();
-      toolbar_->Hide();
-      tabstrip_->Hide();
-      if (IsBookmarkBarSupported())
-        bookmark_bar_->EnterFullscreen();
-      bool is_kiosk =
-          CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
-      if (!is_kiosk) {
-        fullscreen_exit_bubble_.reset(new FullscreenExitBubbleGtk(
-            GTK_FLOATING_CONTAINER(render_area_floating_container_)));
-      }
-      gtk_widget_hide(toolbar_border_);
-    } else {
-      fullscreen_exit_bubble_.reset();
-      UpdateCustomFrame();
-      ShowSupportedWindowFeatures();
-    }
-  }
-
-  UpdateWindowShape(bounds_.width(), bounds_.height());
-  SaveWindowPosition();
-}
-
-void BrowserWindowGtk::UnMaximize() {
-  gtk_window_unmaximize(window_);
-
-  // It can happen that you end up with a window whose restore size is the same
-  // as the size of the screen, so unmaximizing it merely remaximizes it due to
-  // the same WM feature that SetWindowSize() works around.  We try to detect
-  // this and resize the window to work around the issue.
-  if (bounds_.size() == restored_bounds_.size())
-    gtk_window_resize(window_, bounds_.width(), bounds_.height() - 1);
-}
-
-bool BrowserWindowGtk::CanClose() const {
-  // You cannot close a frame for which there is an active originating drag
-  // session.
-  if (tabstrip_->IsDragSessionActive())
-    return false;
-
-  // Give beforeunload handlers the chance to cancel the close before we hide
-  // the window below.
-  if (!browser_->ShouldCloseWindow())
-    return false;
-
-  if (!browser_->tabstrip_model()->empty()) {
-    // Tab strip isn't empty.  Hide the window (so it appears to have closed
-    // immediately) and close all the tabs, allowing the renderers to shut
-    // down. When the tab strip is empty we'll be called back again.
-    gtk_widget_hide(GTK_WIDGET(window_));
-    browser_->OnWindowClosing();
-    return false;
-  }
-
-  // Empty TabStripModel, it's now safe to allow the Window to be closed.
-  NotificationService::current()->Notify(
-      NotificationType::WINDOW_CLOSED,
-      Source<GtkWindow>(window_),
-      NotificationService::NoDetails());
-  return true;
-}
-
-bool BrowserWindowGtk::ShouldShowWindowIcon() const {
-  return browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
-}
-
-void BrowserWindowGtk::AddFindBar(FindBarGtk* findbar) {
-  gtk_floating_container_add_floating(
-      GTK_FLOATING_CONTAINER(render_area_floating_container_),
-      findbar->widget());
-}
-
-void BrowserWindowGtk::ResetCustomFrameCursor() {
-  if (!frame_cursor_)
-    return;
-
-  frame_cursor_ = NULL;
-  gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL);
-}
-
-// static
-BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow(
-    gfx::NativeWindow window) {
-  if (window) {
-    return static_cast<BrowserWindowGtk*>(
-        g_object_get_qdata(G_OBJECT(window), GetBrowserWindowQuarkKey()));
-  }
-
-  return NULL;
-}
-
-// static
-GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) {
-  std::map<XID, GtkWindow*>::iterator iter =
-      BrowserWindowGtk::xid_map_.find(xid);
-  return (iter != BrowserWindowGtk::xid_map_.end()) ? iter->second : NULL;
-}
-
-// static
-void BrowserWindowGtk::RegisterUserPrefs(PrefService* prefs) {
-  bool custom_frame_default = false;
-  // Avoid checking the window manager if we're not connected to an X server (as
-  // is the case in Valgrind tests).
-  if (x11_util::XDisplayExists() &&
-      !prefs->HasPrefPath(prefs::kUseCustomChromeFrame)) {
-    custom_frame_default = GetCustomFramePrefDefault();
-  }
-  prefs->RegisterBooleanPref(
-      prefs::kUseCustomChromeFrame, custom_frame_default);
-}
-
-void BrowserWindowGtk::BookmarkBarIsFloating(bool is_floating) {
-  bookmark_bar_is_floating_ = is_floating;
-  toolbar_->UpdateForBookmarkBarVisibility(is_floating);
-
-  // This can be NULL during initialization of the bookmark bar.
-  if (bookmark_bar_.get())
-    PlaceBookmarkBar(is_floating);
-}
-
-TabContents* BrowserWindowGtk::GetDisplayedTabContents() {
-  return contents_container_->GetVisibleTabContents();
-}
-
-void BrowserWindowGtk::QueueToolbarRedraw() {
-  gtk_widget_queue_draw(toolbar_->widget());
-}
-
-void BrowserWindowGtk::SetGeometryHints() {
-  // If we call gtk_window_maximize followed by gtk_window_present, compiz gets
-  // confused and maximizes the window, but doesn't set the
-  // GDK_WINDOW_STATE_MAXIMIZED bit.  So instead, we keep track of whether to
-  // maximize and call it after gtk_window_present.
-  maximize_after_show_ = browser_->GetSavedMaximizedState();
-
-  gfx::Rect bounds = browser_->GetSavedWindowBounds();
-  // We don't blindly call SetBounds here: that sets a forced position
-  // on the window and we intentionally *don't* do that for normal
-  // windows.  Most programs do not restore their window position on
-  // Linux, instead letting the window manager choose a position.
-  //
-  // However, in cases like dropping a tab where the bounds are
-  // specifically set, we do want to position explicitly.  We also
-  // force the position as part of session restore, as applications
-  // that restore other, similar state (for instance GIMP, audacity,
-  // pidgin, dia, and gkrellm) do tend to restore their positions.
-  //
-  // For popup windows, we assume that if x == y == 0, the opening page
-  // did not specify a position.  Let the WM position the popup instead.
-  bool is_popup = browser_->type() & Browser::TYPE_POPUP;
-  bool popup_without_position = is_popup &&
-      bounds.x() == 0 && bounds.y() == 0;
-  bool move = browser_->bounds_overridden() && !popup_without_position;
-  SetBoundsImpl(bounds, !is_popup, move);
-}
-
-void BrowserWindowGtk::ConnectHandlersToSignals() {
-  g_signal_connect(window_, "delete-event",
-                   G_CALLBACK(MainWindowDeleteEvent), this);
-  g_signal_connect(window_, "destroy",
-                   G_CALLBACK(MainWindowDestroy), this);
-  g_signal_connect(window_, "configure-event",
-                   G_CALLBACK(MainWindowConfigured), this);
-  g_signal_connect(window_, "window-state-event",
-                   G_CALLBACK(MainWindowStateChanged), this);
-  g_signal_connect(window_, "map",
-                   G_CALLBACK(MainWindowMapped), NULL);
-  g_signal_connect(window_, "unmap",
-                   G_CALLBACK(MainWindowUnMapped), NULL);
-  g_signal_connect(window_, "key-press-event",
-                   G_CALLBACK(OnKeyPressThunk), this);
-  g_signal_connect(window_, "motion-notify-event",
-                   G_CALLBACK(OnMouseMoveEventThunk), this);
-  g_signal_connect(window_, "button-press-event",
-                   G_CALLBACK(OnButtonPressEventThunk), this);
-  g_signal_connect(window_, "focus-in-event",
-                   G_CALLBACK(OnFocusInThunk), this);
-  g_signal_connect(window_, "focus-out-event",
-                   G_CALLBACK(OnFocusOutThunk), this);
-}
-
-void BrowserWindowGtk::InitWidgets() {
-  ConnectHandlersToSignals();
-  bounds_ = restored_bounds_ = GetInitialWindowBounds(window_);
-
-  // This vbox encompasses all of the widgets within the browser.  This is
-  // everything except the custom frame border.
-  window_vbox_ = gtk_vbox_new(FALSE, 0);
-  gtk_widget_show(window_vbox_);
-
-  // The window container draws the custom browser frame.
-  window_container_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_widget_set_name(window_container_, "chrome-custom-frame-border");
-  gtk_widget_set_app_paintable(window_container_, TRUE);
-  gtk_widget_set_double_buffered(window_container_, FALSE);
-  gtk_widget_set_redraw_on_allocate(window_container_, TRUE);
-  g_signal_connect(window_container_, "expose-event",
-                   G_CALLBACK(OnCustomFrameExposeThunk), this);
-  gtk_container_add(GTK_CONTAINER(window_container_), window_vbox_);
-
-  tabstrip_.reset(new TabStripGtk(browser_->tabstrip_model(), this));
-  tabstrip_->Init();
-
-  // Build the titlebar (tabstrip + header space + min/max/close buttons).
-  titlebar_.reset(new BrowserTitlebar(this, window_));
-
-  // Insert the tabstrip into the window.
-  gtk_box_pack_start(GTK_BOX(window_vbox_), titlebar_->widget(), FALSE, FALSE,
-                     0);
-
-  toolbar_.reset(new BrowserToolbarGtk(browser_.get(), this));
-  toolbar_->Init(browser_->profile(), window_);
-  gtk_box_pack_start(GTK_BOX(window_vbox_), toolbar_->widget(),
-                     FALSE, FALSE, 0);
-  g_signal_connect_after(toolbar_->widget(), "expose-event",
-                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
-  // This vbox surrounds the render area: find bar, info bars and render view.
-  // The reason is that this area as a whole needs to be grouped in its own
-  // GdkWindow hierarchy so that animations originating inside it (infobar,
-  // download shelf, find bar) are all clipped to that area. This is why
-  // |render_area_vbox_| is packed in |render_area_event_box_|.
-  render_area_vbox_ = gtk_vbox_new(FALSE, 0);
-  gtk_widget_set_name(render_area_vbox_, "chrome-render-area-vbox");
-  render_area_floating_container_ = gtk_floating_container_new();
-  gtk_container_add(GTK_CONTAINER(render_area_floating_container_),
-                    render_area_vbox_);
-
-  GtkWidget* location_icon = toolbar_->GetLocationBarView()->
-      location_icon_widget();
-  g_signal_connect(location_icon, "size-allocate",
-                   G_CALLBACK(OnLocationIconSizeAllocateThunk), this);
-  g_signal_connect_after(location_icon, "expose-event",
-                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
-
-  toolbar_border_ = gtk_event_box_new();
-  gtk_box_pack_start(GTK_BOX(render_area_vbox_),
-                     toolbar_border_, FALSE, FALSE, 0);
-  gtk_widget_set_size_request(toolbar_border_, -1, 1);
-  gtk_widget_set_no_show_all(toolbar_border_, TRUE);
-  g_signal_connect_after(toolbar_border_, "expose-event",
-                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
-
-  if (IsToolbarSupported())
-    gtk_widget_show(toolbar_border_);
-
-  infobar_container_.reset(new InfoBarContainerGtk(browser_->profile()));
-  gtk_box_pack_start(GTK_BOX(render_area_vbox_),
-                     infobar_container_->widget(),
-                     FALSE, FALSE, 0);
-
-  status_bubble_.reset(new StatusBubbleGtk(browser_->profile()));
-
-  contents_container_.reset(new TabContentsContainerGtk(status_bubble_.get()));
-  devtools_container_.reset(new TabContentsContainerGtk(NULL));
-  ViewIDUtil::SetID(devtools_container_->widget(), VIEW_ID_DEV_TOOLS_DOCKED);
-  contents_split_ = gtk_vpaned_new();
-  gtk_paned_pack1(GTK_PANED(contents_split_), contents_container_->widget(),
-                  TRUE, TRUE);
-  gtk_paned_pack2(GTK_PANED(contents_split_), devtools_container_->widget(),
-                  FALSE, TRUE);
-  gtk_box_pack_end(GTK_BOX(render_area_vbox_), contents_split_, TRUE, TRUE, 0);
-  // Restore split offset.
-  int split_offset = g_browser_process->local_state()->GetInteger(
-      prefs::kDevToolsSplitLocation);
-  if (split_offset != -1) {
-    if (split_offset < kMinDevToolsHeight)
-      split_offset = kMinDevToolsHeight;
-    gtk_paned_set_position(GTK_PANED(contents_split_), split_offset);
-  } else {
-    gtk_widget_set_size_request(devtools_container_->widget(), -1,
-                                kDefaultDevToolsHeight);
-  }
-  gtk_widget_show_all(render_area_floating_container_);
-  gtk_widget_hide(devtools_container_->widget());
-  render_area_event_box_ = gtk_event_box_new();
-  // Set a white background so during startup the user sees white in the
-  // content area before we get a TabContents in place.
-  gtk_widget_modify_bg(render_area_event_box_, GTK_STATE_NORMAL,
-                       &gtk_util::kGdkWhite);
-  gtk_container_add(GTK_CONTAINER(render_area_event_box_),
-                    render_area_floating_container_);
-  gtk_widget_show(render_area_event_box_);
-  gtk_box_pack_end(GTK_BOX(window_vbox_), render_area_event_box_,
-                   TRUE, TRUE, 0);
-
-  if (IsBookmarkBarSupported()) {
-    bookmark_bar_.reset(new BookmarkBarGtk(this,
-                                           browser_->profile(),
-                                           browser_.get(),
-                                           tabstrip_.get()));
-    PlaceBookmarkBar(false);
-    gtk_widget_show(bookmark_bar_->widget());
-
-    g_signal_connect_after(bookmark_bar_->widget(), "expose-event",
-                           G_CALLBACK(OnBookmarkBarExposeThunk), this);
-    g_signal_connect(bookmark_bar_->widget(), "size-allocate",
-                     G_CALLBACK(OnBookmarkBarSizeAllocateThunk), this);
-  }
-
-  // We have to realize the window before we try to apply a window shape mask.
-  gtk_widget_realize(GTK_WIDGET(window_));
-  state_ = gdk_window_get_state(GTK_WIDGET(window_)->window);
-  // Note that calling this the first time is necessary to get the
-  // proper control layout.
-  UpdateCustomFrame();
-
-  gtk_container_add(GTK_CONTAINER(window_), window_container_);
-  gtk_widget_show(window_container_);
-  browser_->tabstrip_model()->AddObserver(this);
-}
-
-void BrowserWindowGtk::SetBackgroundColor() {
-  Profile* profile = browser()->profile();
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(profile);
-  int frame_color_id;
-  if (UsingCustomPopupFrame()) {
-    frame_color_id = BrowserThemeProvider::COLOR_TOOLBAR;
-  } else if (IsActive()) {
-    frame_color_id = browser()->profile()->IsOffTheRecord()
-       ? BrowserThemeProvider::COLOR_FRAME_INCOGNITO
-       : BrowserThemeProvider::COLOR_FRAME;
-  } else {
-    frame_color_id = browser()->profile()->IsOffTheRecord()
-       ? BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE
-       : BrowserThemeProvider::COLOR_FRAME_INACTIVE;
-  }
-
-  SkColor frame_color = theme_provider->GetColor(frame_color_id);
-
-  // Paint the frame color on the left, right and bottom.
-  GdkColor frame_color_gdk = gfx::SkColorToGdkColor(frame_color);
-  gtk_widget_modify_bg(GTK_WIDGET(window_), GTK_STATE_NORMAL,
-                       &frame_color_gdk);
-
-  // Set the color of the dev tools divider.
-  gtk_widget_modify_bg(contents_split_, GTK_STATE_NORMAL, &frame_color_gdk);
-
-  // When the cursor is over the divider, GTK+ normally lightens the background
-  // color by 1.3 (see LIGHTNESS_MULT in gtkstyle.c).  Since we're setting the
-  // color, override the prelight also.
-  color_utils::HSL hsl = { -1, 0.5, 0.65 };
-  SkColor frame_prelight_color = color_utils::HSLShift(frame_color, hsl);
-  GdkColor frame_prelight_color_gdk =
-      gfx::SkColorToGdkColor(frame_prelight_color);
-  gtk_widget_modify_bg(contents_split_, GTK_STATE_PRELIGHT,
-      &frame_prelight_color_gdk);
-
-  GdkColor border_color = theme_provider->GetBorderColor();
-  gtk_widget_modify_bg(toolbar_border_, GTK_STATE_NORMAL, &border_color);
-}
-
-void BrowserWindowGtk::OnSizeChanged(int width, int height) {
-  UpdateWindowShape(width, height);
-}
-
-void BrowserWindowGtk::UpdateWindowShape(int width, int height) {
-  if (UseCustomFrame() && !IsFullscreen() && !IsMaximized()) {
-    // Make the corners rounded.  We set a mask that includes most of the
-    // window except for a few pixels in each corner.
-    GdkRectangle top_top_rect = { 3, 0, width - 6, 1 };
-    GdkRectangle top_mid_rect = { 1, 1, width - 2, 2 };
-    GdkRectangle mid_rect = { 0, 3, width, height - 6 };
-    // The bottom two rects are mirror images of the top two rects.
-    GdkRectangle bot_mid_rect = top_mid_rect;
-    bot_mid_rect.y = height - 3;
-    GdkRectangle bot_bot_rect = top_top_rect;
-    bot_bot_rect.y = height - 1;
-    GdkRegion* mask = gdk_region_rectangle(&top_top_rect);
-    gdk_region_union_with_rect(mask, &top_mid_rect);
-    gdk_region_union_with_rect(mask, &mid_rect);
-    gdk_region_union_with_rect(mask, &bot_mid_rect);
-    gdk_region_union_with_rect(mask, &bot_bot_rect);
-    gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, mask, 0, 0);
-    gdk_region_destroy(mask);
-    gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 1,
-        kFrameBorderThickness, kFrameBorderThickness, kFrameBorderThickness);
-  } else {
-    // XFCE disables the system decorations if there's an xshape set.
-    if (UseCustomFrame()) {
-      // Disable rounded corners.  Simply passing in a NULL region doesn't
-      // seem to work on KWin, so manually set the shape to the whole window.
-      GdkRectangle rect = { 0, 0, width, height };
-      GdkRegion* mask = gdk_region_rectangle(&rect);
-      gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, mask, 0, 0);
-      gdk_region_destroy(mask);
-    } else {
-      gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, NULL, 0, 0);
-    }
-    gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 0, 0, 0, 0);
-  }
-}
-
-void BrowserWindowGtk::ConnectAccelerators() {
-  accel_group_ = gtk_accel_group_new();
-  gtk_window_add_accel_group(window_, accel_group_);
-
-  AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
-  for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
-       iter != accelerators->end(); ++iter) {
-    gtk_accel_group_connect(
-        accel_group_,
-        iter->second.GetGdkKeyCode(),
-        static_cast<GdkModifierType>(iter->second.modifiers()),
-        GtkAccelFlags(0),
-        g_cclosure_new(G_CALLBACK(OnGtkAccelerator),
-                       GINT_TO_POINTER(iter->first), NULL));
-  }
-}
-
-void BrowserWindowGtk::UpdateCustomFrame() {
-  gtk_window_set_decorated(window_, !UseCustomFrame());
-  titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen());
-  UpdateWindowShape(bounds_.width(), bounds_.height());
-}
-
-void BrowserWindowGtk::SaveWindowPosition() {
-  // Browser::SaveWindowPlacement is used for session restore.
-  if (browser_->ShouldSaveWindowPlacement())
-    browser_->SaveWindowPlacement(restored_bounds_, IsMaximized());
-
-  // We also need to save the placement for startup.
-  // This is a web of calls between views and delegates on Windows, but the
-  // crux of the logic follows.  See also cocoa/browser_window_controller.mm.
-  if (!g_browser_process->local_state())
-    return;
-
-  std::string window_name = browser_->GetWindowPlacementKey();
-  DictionaryValue* window_preferences =
-      g_browser_process->local_state()->GetMutableDictionary(
-          window_name.c_str());
-  // Note that we store left/top for consistency with Windows, but that we
-  // *don't* obey them; we only use them for computing width/height.  See
-  // comments in SetGeometryHints().
-  window_preferences->SetInteger("left", restored_bounds_.x());
-  window_preferences->SetInteger("top", restored_bounds_.y());
-  window_preferences->SetInteger("right", restored_bounds_.right());
-  window_preferences->SetInteger("bottom", restored_bounds_.bottom());
-  window_preferences->SetBoolean("maximized", IsMaximized());
-
-  scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_info_provider(
-      WindowSizer::CreateDefaultMonitorInfoProvider());
-  gfx::Rect work_area(
-      monitor_info_provider->GetMonitorWorkAreaMatching(restored_bounds_));
-  window_preferences->SetInteger("work_area_left", work_area.x());
-  window_preferences->SetInteger("work_area_top", work_area.y());
-  window_preferences->SetInteger("work_area_right", work_area.right());
-  window_preferences->SetInteger("work_area_bottom", work_area.bottom());
-}
-
-void BrowserWindowGtk::SetInfoBarShowing(InfoBar* bar, bool animate) {
-  infobar_arrow_model_.ShowArrowFor(bar, animate);
-}
-
-void BrowserWindowGtk::PaintStateChanged() {
-  InvalidateInfoBarBits();
-}
-
-void BrowserWindowGtk::InvalidateInfoBarBits() {
-  gtk_widget_queue_draw(toolbar_border_);
-  gtk_widget_queue_draw(toolbar_->widget());
-  if (bookmark_bar_.get() && !bookmark_bar_is_floating_)
-    gtk_widget_queue_draw(bookmark_bar_->widget());
-}
-
-int BrowserWindowGtk::GetXPositionOfLocationIcon(GtkWidget* relative_to) {
-  GtkWidget* location_icon = toolbar_->GetLocationBarView()->
-      location_icon_widget();
-  int x = 0;
-  gtk_widget_translate_coordinates(
-      location_icon, relative_to,
-      (location_icon->allocation.width + 1) / 2,
-      0, &x, NULL);
-
-  if (GTK_WIDGET_NO_WINDOW(relative_to))
-    x += relative_to->allocation.x;
-
-  return x;
-}
-
-void BrowserWindowGtk::OnLocationIconSizeAllocate(GtkWidget* sender,
-                                                  GtkAllocation* allocation) {
-  // The position of the arrow may have changed, so we'll have to redraw it.
-  InvalidateInfoBarBits();
-}
-
-gboolean BrowserWindowGtk::OnExposeDrawInfobarBits(GtkWidget* sender,
-                                                   GdkEventExpose* expose) {
-  if (!infobar_arrow_model_.NeedToDrawInfoBarArrow())
-    return FALSE;
-
-  int x = GetXPositionOfLocationIcon(sender);
-
-  gfx::Rect toolbar_border(toolbar_border_->allocation);
-  int y = 0;
-  gtk_widget_translate_coordinates(toolbar_border_, sender,
-                                   0, toolbar_border.bottom(),
-                                   NULL, &y);
-  if (GTK_WIDGET_NO_WINDOW(sender))
-    y += sender->allocation.y;
-
-  Profile* profile = browser()->profile();
-  infobar_arrow_model_.Paint(
-      sender, expose, gfx::Point(x, y),
-      GtkThemeProvider::GetFrom(profile)->GetBorderColor());
-  return FALSE;
-}
-
-gboolean BrowserWindowGtk::OnBookmarkBarExpose(GtkWidget* sender,
-                                               GdkEventExpose* expose) {
-  if (!infobar_arrow_model_.NeedToDrawInfoBarArrow())
-    return FALSE;
-
-  if (bookmark_bar_is_floating_)
-    return FALSE;
-
-  return OnExposeDrawInfobarBits(sender, expose);
-}
-
-void BrowserWindowGtk::OnBookmarkBarSizeAllocate(GtkWidget* sender,
-                                                 GtkAllocation* allocation) {
-  // The size of the bookmark bar affects how the infobar arrow is drawn on
-  // the toolbar.
-  if (infobar_arrow_model_.NeedToDrawInfoBarArrow())
-    gtk_widget_queue_draw(toolbar_->widget());
-}
-
-// static
-gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
-                                            GObject* acceleratable,
-                                            guint keyval,
-                                            GdkModifierType modifier,
-                                            void* user_data) {
-  int command_id = GPOINTER_TO_INT(user_data);
-  BrowserWindowGtk* browser_window =
-      GetBrowserWindowForNativeWindow(GTK_WINDOW(acceleratable));
-  DCHECK(browser_window != NULL);
-  return browser_window->browser()->ExecuteCommandIfEnabled(command_id);
-}
-
-// Let the focused widget have first crack at the key event so we don't
-// override their accelerators.
-gboolean BrowserWindowGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
-  // If a widget besides the native view is focused, we have to try to handle
-  // the custom accelerators before letting it handle them.
-  TabContents* current_tab_contents =
-      browser()->GetSelectedTabContents();
-  // The current tab might not have a render view if it crashed.
-  if (!current_tab_contents || !current_tab_contents->GetContentNativeView() ||
-      !gtk_widget_is_focus(current_tab_contents->GetContentNativeView())) {
-    int command_id = GetCustomCommandId(event);
-    if (command_id == -1)
-      command_id = GetPreHandleCommandId(event);
-
-    if (command_id != -1 && browser_->ExecuteCommandIfEnabled(command_id))
-      return TRUE;
-
-    // Propagate the key event to child widget first, so we don't override their
-    // accelerators.
-    if (!gtk_window_propagate_key_event(GTK_WINDOW(widget), event)) {
-      if (!gtk_window_activate_key(GTK_WINDOW(widget), event)) {
-        gtk_bindings_activate_event(GTK_OBJECT(widget), event);
-      }
-    }
-  } else {
-    bool rv = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
-    DCHECK(rv);
-  }
-
-  // Prevents the default handler from handling this event.
-  return TRUE;
-}
-
-gboolean BrowserWindowGtk::OnMouseMoveEvent(GtkWidget* widget,
-                                            GdkEventMotion* event) {
-  // This method is used to update the mouse cursor when over the edge of the
-  // custom frame.  If the custom frame is off or we're over some other widget,
-  // do nothing.
-  if (!UseCustomFrame() || event->window != widget->window) {
-    // Reset the cursor.
-    if (frame_cursor_) {
-      frame_cursor_ = NULL;
-      gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL);
-    }
-    return FALSE;
-  }
-
-  // Update the cursor if we're on the custom frame border.
-  GdkWindowEdge edge;
-  bool has_hit_edge = GetWindowEdge(static_cast<int>(event->x),
-                                    static_cast<int>(event->y), &edge);
-  GdkCursorType new_cursor = GDK_LAST_CURSOR;
-  if (has_hit_edge)
-    new_cursor = GdkWindowEdgeToGdkCursorType(edge);
-
-  GdkCursorType last_cursor = GDK_LAST_CURSOR;
-  if (frame_cursor_)
-    last_cursor = frame_cursor_->type;
-
-  if (last_cursor != new_cursor) {
-    if (has_hit_edge) {
-      frame_cursor_ = gfx::GetCursor(new_cursor);
-    } else {
-      frame_cursor_ = NULL;
-    }
-    gdk_window_set_cursor(GTK_WIDGET(window_)->window, frame_cursor_);
-  }
-  return FALSE;
-}
-
-gboolean BrowserWindowGtk::OnButtonPressEvent(GtkWidget* widget,
-                                              GdkEventButton* event) {
-  // Handle back/forward.
-  if (event->type == GDK_BUTTON_PRESS) {
-    if (event->button == 8) {
-      browser_->GoBack(CURRENT_TAB);
-      return TRUE;
-    } else if (event->button == 9) {
-      browser_->GoForward(CURRENT_TAB);
-      return TRUE;
-    }
-  }
-
-  // Handle left, middle and right clicks.  In particular, we care about clicks
-  // in the custom frame border and clicks in the titlebar.
-
-  // Make the button press coordinate relative to the browser window.
-  int win_x, win_y;
-  gdk_window_get_origin(GTK_WIDGET(window_)->window, &win_x, &win_y);
-
-  GdkWindowEdge edge;
-  gfx::Point point(static_cast<int>(event->x_root - win_x),
-                   static_cast<int>(event->y_root - win_y));
-  bool has_hit_edge = GetWindowEdge(point.x(), point.y(), &edge);
-
-  // Ignore clicks that are in/below the browser toolbar.
-  GtkWidget* toolbar = toolbar_->widget();
-  if (!GTK_WIDGET_VISIBLE(toolbar)) {
-    // If the toolbar is not showing, use the location of web contents as the
-    // boundary of where to ignore clicks.
-    toolbar = render_area_vbox_;
-  }
-  gint toolbar_y;
-  gtk_widget_get_pointer(toolbar, NULL, &toolbar_y);
-  bool has_hit_titlebar = !IsFullscreen() && (toolbar_y < 0)
-                          && !has_hit_edge;
-  if (event->button == 1) {
-    if (GDK_BUTTON_PRESS == event->type) {
-      guint32 last_click_time = last_click_time_;
-      gfx::Point last_click_position = last_click_position_;
-      last_click_time_ = event->time;
-      last_click_position_ = gfx::Point(static_cast<int>(event->x),
-                                        static_cast<int>(event->y));
-
-      // Raise the window after a click on either the titlebar or the border to
-      // match the behavior of most window managers, unless that behavior has
-      // been suppressed.
-      if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_)
-        gdk_window_raise(GTK_WIDGET(window_)->window);
-
-      if (has_hit_titlebar) {
-        // We want to start a move when the user single clicks, but not start a
-        // move when the user double clicks.  However, a double click sends the
-        // following GDK events: GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE,
-        // GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE.  If we
-        // start a gtk_window_begin_move_drag on the second GDK_BUTTON_PRESS,
-        // the call to gtk_window_maximize fails.  To work around this, we
-        // keep track of the last click and if it's going to be a double click,
-        // we don't call gtk_window_begin_move_drag.
-        static GtkSettings* settings = gtk_settings_get_default();
-        gint double_click_time = 250;
-        gint double_click_distance = 5;
-        g_object_get(G_OBJECT(settings),
-                     "gtk-double-click-time", &double_click_time,
-                     "gtk-double-click-distance", &double_click_distance,
-                     NULL);
-
-        guint32 click_time = event->time - last_click_time;
-        int click_move_x = abs(event->x - last_click_position.x());
-        int click_move_y = abs(event->y - last_click_position.y());
-
-        if (click_time > static_cast<guint32>(double_click_time) ||
-            click_move_x > double_click_distance ||
-            click_move_y > double_click_distance) {
-          // Ignore drag requests if the window is the size of the screen.
-          // We do this to avoid triggering fullscreen mode in metacity
-          // (without the --no-force-fullscreen flag) and in compiz (with
-          // Legacy Fullscreen Mode enabled).
-          if (!BoundsMatchMonitorSize()) {
-            gtk_window_begin_move_drag(window_, event->button,
-                                       static_cast<gint>(event->x_root),
-                                       static_cast<gint>(event->y_root),
-                                       event->time);
-          }
-          return TRUE;
-        }
-      } else if (has_hit_edge) {
-        gtk_window_begin_resize_drag(window_, edge, event->button,
-                                     static_cast<gint>(event->x_root),
-                                     static_cast<gint>(event->y_root),
-                                     event->time);
-        return TRUE;
-      }
-    } else if (GDK_2BUTTON_PRESS == event->type) {
-      if (has_hit_titlebar) {
-        // Maximize/restore on double click.
-        if (IsMaximized()) {
-          UnMaximize();
-        } else {
-          gtk_window_maximize(window_);
-        }
-        return TRUE;
-      }
-    }
-  } else if (event->button == 2) {
-    if (has_hit_titlebar || has_hit_edge) {
-      gdk_window_lower(GTK_WIDGET(window_)->window);
-    }
-    return TRUE;
-  } else if (event->button == 3) {
-    if (has_hit_titlebar) {
-      titlebar_->ShowContextMenu();
-      return TRUE;
-    }
-  }
-
-  return FALSE;  // Continue to propagate the event.
-}
-
-// static
-void BrowserWindowGtk::MainWindowMapped(GtkWidget* widget) {
-  // Map the X Window ID of the window to our window.
-  XID xid = x11_util::GetX11WindowFromGtkWidget(widget);
-  BrowserWindowGtk::xid_map_.insert(
-      std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget)));
-}
-
-// static
-void BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget) {
-  // Unmap the X Window ID.
-  XID xid = x11_util::GetX11WindowFromGtkWidget(widget);
-  BrowserWindowGtk::xid_map_.erase(xid);
-}
-
-gboolean BrowserWindowGtk::OnFocusIn(GtkWidget* widget,
-                                     GdkEventFocus* event) {
-  BrowserList::SetLastActive(browser_.get());
-  return FALSE;
-}
-
-gboolean BrowserWindowGtk::OnFocusOut(GtkWidget* widget,
-                                      GdkEventFocus* event) {
-  return FALSE;
-}
-
-void BrowserWindowGtk::ShowSupportedWindowFeatures() {
-  if (IsTabStripSupported())
-    tabstrip_->Show();
-
-  if (IsToolbarSupported()) {
-    toolbar_->Show();
-    gtk_widget_show(toolbar_border_);
-    gdk_window_lower(toolbar_border_->window);
-  }
-
-  if (IsBookmarkBarSupported())
-    MaybeShowBookmarkBar(false);
-}
-
-void BrowserWindowGtk::HideUnsupportedWindowFeatures() {
-  if (!IsTabStripSupported())
-    tabstrip_->Hide();
-
-  if (!IsToolbarSupported())
-    toolbar_->Hide();
-
-  // If the bookmark bar shelf is unsupported, then we never create it.
-}
-
-bool BrowserWindowGtk::IsTabStripSupported() const {
-  return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
-}
-
-bool BrowserWindowGtk::IsToolbarSupported() const {
-  return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
-         browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
-}
-
-bool BrowserWindowGtk::IsBookmarkBarSupported() const {
-  return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR);
-}
-
-bool BrowserWindowGtk::UsingCustomPopupFrame() const {
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
-      browser()->profile());
-  return !theme_provider->UseGtkTheme() &&
-      browser()->type() & Browser::TYPE_POPUP;
-}
-
-bool BrowserWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
-  if (!UseCustomFrame())
-    return false;
-
-  if (IsMaximized() || IsFullscreen())
-    return false;
-
-  if (x < kFrameBorderThickness) {
-    // Left edge.
-    if (y < kResizeAreaCornerSize - kTopResizeAdjust) {
-      *edge = GDK_WINDOW_EDGE_NORTH_WEST;
-    } else if (y < bounds_.height() - kResizeAreaCornerSize) {
-      *edge = GDK_WINDOW_EDGE_WEST;
-    } else {
-      *edge = GDK_WINDOW_EDGE_SOUTH_WEST;
-    }
-    return true;
-  } else if (x < bounds_.width() - kFrameBorderThickness) {
-    if (y < kFrameBorderThickness - kTopResizeAdjust) {
-      // Top edge.
-      if (x < kResizeAreaCornerSize) {
-        *edge = GDK_WINDOW_EDGE_NORTH_WEST;
-      } else if (x < bounds_.width() - kResizeAreaCornerSize) {
-        *edge = GDK_WINDOW_EDGE_NORTH;
-      } else {
-        *edge = GDK_WINDOW_EDGE_NORTH_EAST;
-      }
-    } else if (y < bounds_.height() - kFrameBorderThickness) {
-      // Ignore the middle content area.
-      return false;
-    } else {
-      // Bottom edge.
-      if (x < kResizeAreaCornerSize) {
-        *edge = GDK_WINDOW_EDGE_SOUTH_WEST;
-      } else if (x < bounds_.width() - kResizeAreaCornerSize) {
-        *edge = GDK_WINDOW_EDGE_SOUTH;
-      } else {
-        *edge = GDK_WINDOW_EDGE_SOUTH_EAST;
-      }
-    }
-    return true;
-  } else {
-    // Right edge.
-    if (y < kResizeAreaCornerSize - kTopResizeAdjust) {
-      *edge = GDK_WINDOW_EDGE_NORTH_EAST;
-    } else if (y < bounds_.height() - kResizeAreaCornerSize) {
-      *edge = GDK_WINDOW_EDGE_EAST;
-    } else {
-      *edge = GDK_WINDOW_EDGE_SOUTH_EAST;
-    }
-    return true;
-  }
-  NOTREACHED();
-}
-
-bool BrowserWindowGtk::UseCustomFrame() {
-  // We don't use the custom frame for app mode windows or app window popups.
-  return use_custom_frame_pref_.GetValue() &&
-      browser_->type() != Browser::TYPE_APP &&
-      browser_->type() != Browser::TYPE_APP_POPUP;
-}
-
-bool BrowserWindowGtk::BoundsMatchMonitorSize() {
-  // A screen can be composed of multiple monitors.
-  GdkScreen* screen = gtk_window_get_screen(window_);
-  gint monitor_num = gdk_screen_get_monitor_at_window(screen,
-      GTK_WIDGET(window_)->window);
-
-  GdkRectangle monitor_size;
-  gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor_size);
-  return bounds_.size() == gfx::Size(monitor_size.width, monitor_size.height);
-}
-
-void BrowserWindowGtk::PlaceBookmarkBar(bool is_floating) {
-  GtkWidget* parent = gtk_widget_get_parent(bookmark_bar_->widget());
-  if (parent)
-    gtk_container_remove(GTK_CONTAINER(parent), bookmark_bar_->widget());
-
-  if (!is_floating) {
-    // Place the bookmark bar at the end of |window_vbox_|; this happens after
-    // we have placed the render area at the end of |window_vbox_| so we will
-    // be above the render area.
-    gtk_box_pack_end(GTK_BOX(window_vbox_), bookmark_bar_->widget(),
-                     FALSE, FALSE, 0);
-  } else {
-    // Place the bookmark bar at the end of the render area; this happens after
-    // the tab contents container has been placed there so we will be
-    // above the webpage (in terms of y).
-    gtk_box_pack_end(GTK_BOX(render_area_vbox_), bookmark_bar_->widget(),
-                     FALSE, FALSE, 0);
-  }
-}
-
-// static
-bool BrowserWindowGtk::GetCustomFramePrefDefault() {
-  std::string wm_name;
-  if (!x11_util::GetWindowManagerName(&wm_name))
-    return false;
-
-  // Ideally, we'd use the custom frame by default and just fall back on using
-  // system decorations for the few (?) tiling window managers where the custom
-  // frame doesn't make sense (e.g. awesome, ion3, ratpoison, xmonad, etc.) or
-  // other WMs where it has issues (e.g. Fluxbox -- see issue 19130).  The EWMH
-  // _NET_SUPPORTING_WM property makes it easy to look up a name for the current
-  // WM, but at least some of the WMs in the latter group don't set it.
-  // Instead, we default to using system decorations for all WMs and
-  // special-case the ones where the custom frame should be used.  These names
-  // are taken from the WMs' source code.
-  return (wm_name == "Blackbox" ||
-          wm_name == "compiz" ||
-          wm_name == "e16" ||  // Enlightenment DR16
-          wm_name == "Metacity" ||
-          wm_name == "Mutter" ||
-          wm_name == "Openbox" ||
-          wm_name == "Xfwm4");
-}
diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h
deleted file mode 100644
index ad2fa40..0000000
--- a/chrome/browser/gtk/browser_window_gtk.h
+++ /dev/null
@@ -1,494 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_
-#define CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <map>
-
-#include "app/active_window_watcher_x.h"
-#include "app/gtk_signal.h"
-#include "app/x11_util.h"
-#include "base/scoped_ptr.h"
-#include "base/timer.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/gtk/infobar_arrow_model.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/tabs/tab_strip_model_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
-
-class BookmarkBarGtk;
-class Browser;
-class BrowserTitlebar;
-class BrowserToolbarGtk;
-class CustomDrawButton;
-class DownloadShelfGtk;
-class FindBarGtk;
-class FullscreenExitBubbleGtk;
-class InfoBarContainerGtk;
-class LocationBar;
-class StatusBubbleGtk;
-class TabContentsContainerGtk;
-class TabStripGtk;
-
-// An implementation of BrowserWindow for GTK.
-// Cross-platform code will interact with this object when
-// it needs to manipulate the window.
-
-class BrowserWindowGtk : public BrowserWindow,
-                         public NotificationObserver,
-                         public TabStripModelObserver,
-                         public ActiveWindowWatcherX::Observer,
-                         public InfoBarArrowModel::Observer {
- public:
-  explicit BrowserWindowGtk(Browser* browser);
-  virtual ~BrowserWindowGtk();
-
-  // Overridden from BrowserWindow
-  virtual void Show();
-  virtual void SetBounds(const gfx::Rect& bounds);
-  virtual void Close();
-  virtual void Activate();
-  virtual void Deactivate();
-  virtual bool IsActive() const;
-  virtual void FlashFrame();
-  virtual gfx::NativeWindow GetNativeHandle();
-  virtual BrowserWindowTesting* GetBrowserWindowTesting();
-  virtual StatusBubble* GetStatusBubble();
-  virtual void SelectedTabToolbarSizeChanged(bool is_animating);
-  virtual void UpdateTitleBar();
-  virtual void ShelfVisibilityChanged();
-  virtual void UpdateDevTools();
-  virtual void UpdateLoadingAnimations(bool should_animate);
-  virtual void SetStarredState(bool is_starred);
-  virtual gfx::Rect GetRestoredBounds() const;
-  virtual bool IsMaximized() const;
-  virtual void SetFullscreen(bool fullscreen);
-  virtual bool IsFullscreen() const;
-  virtual bool IsFullscreenBubbleVisible() const;
-  virtual LocationBar* GetLocationBar() const;
-  virtual void SetFocusToLocationBar(bool select_all);
-  virtual void UpdateReloadStopState(bool is_loading, bool force);
-  virtual void UpdateToolbar(TabContentsWrapper* contents,
-                             bool should_restore_state);
-  virtual void FocusToolbar();
-  virtual void FocusAppMenu();
-  virtual void FocusBookmarksToolbar();
-  virtual void FocusChromeOSStatus();
-  virtual void RotatePaneFocus(bool forwards);
-  virtual bool IsBookmarkBarVisible() const;
-  virtual bool IsBookmarkBarAnimating() const;
-  virtual bool IsTabStripEditable() const;
-  virtual bool IsToolbarVisible() const;
-  virtual void ConfirmAddSearchProvider(const TemplateURL* template_url,
-                                        Profile* profile);
-  virtual void ToggleBookmarkBar();
-  virtual views::Window* ShowAboutChromeDialog();
-  virtual void ShowUpdateChromeDialog();
-  virtual void ShowTaskManager();
-  virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
-  virtual bool IsDownloadShelfVisible() const;
-  virtual DownloadShelf* GetDownloadShelf();
-  virtual void ShowReportBugDialog();
-  virtual void ShowClearBrowsingDataDialog();
-  virtual void ShowImportDialog();
-  virtual void ShowSearchEnginesDialog();
-  virtual void ShowPasswordManager();
-  virtual void ShowRepostFormWarningDialog(TabContents* tab_contents);
-  virtual void ShowContentSettingsWindow(ContentSettingsType content_type,
-                                         Profile* profile);
-  virtual void ShowCollectedCookiesDialog(TabContents* tab_contents);
-  virtual void ShowProfileErrorDialog(int message_id);
-  virtual void ShowThemeInstallBubble();
-  virtual void ConfirmBrowserCloseWithPendingDownloads();
-  virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
-                              gfx::NativeWindow parent_window);
-  virtual void UserChangedTheme();
-  virtual int GetExtraRenderViewHeight() const;
-  virtual void TabContentsFocused(TabContents* tab_contents);
-  virtual void ShowPageInfo(Profile* profile,
-                            const GURL& url,
-                            const NavigationEntry::SSLStatus& ssl,
-                            bool show_history);
-  virtual void ShowAppMenu();
-  virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
-                                      bool* is_keyboard_shortcut);
-  virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
-  virtual void ShowCreateWebAppShortcutsDialog(TabContents*  tab_contents);
-  virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile,
-                                                  const Extension* app);
-  virtual void Cut();
-  virtual void Copy();
-  virtual void Paste();
-  virtual void ToggleTabStripMode() {}
-  virtual void PrepareForInstant();
-  virtual void ShowInstant(TabContents* preview_contents);
-  virtual void HideInstant(bool instant_is_active);
-  virtual gfx::Rect GetInstantBounds();
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Overridden from TabStripModelObserver:
-  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
-  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* new_contents,
-                             int index,
-                             bool user_gesture);
-
-  // Overridden from ActiveWindowWatcher::Observer.
-  virtual void ActiveWindowChanged(GdkWindow* active_window);
-
-  // Overridden from InfoBarArrowModel::Observer.
-  virtual void PaintStateChanged();
-
-  // Accessor for the tab strip.
-  TabStripGtk* tabstrip() const { return tabstrip_.get(); }
-
-  void UpdateDevToolsForContents(TabContents* contents);
-
-  void OnBoundsChanged(const gfx::Rect& bounds);
-  void OnDebouncedBoundsChanged();
-  void OnStateChanged(GdkWindowState state, GdkWindowState changed_mask);
-
-  // Request the underlying window to unmaximize.  Also tries to work around
-  // a window manager "feature" that can prevent this in some edge cases.
-  void UnMaximize();
-
-  // Returns false if we're not ready to close yet.  E.g., a tab may have an
-  // onbeforeunload handler that prevents us from closing.
-  bool CanClose() const;
-
-  bool ShouldShowWindowIcon() const;
-
-  // Add the find bar widget to the window hierarchy.
-  void AddFindBar(FindBarGtk* findbar);
-
-  // Reset the mouse cursor to the default cursor if it was set to something
-  // else for the custom frame.
-  void ResetCustomFrameCursor();
-
-  // Toggles whether an infobar is showing.
-  // |animate| controls whether we animate to the new state set by |bar|.
-  void SetInfoBarShowing(InfoBar* bar, bool animate);
-
-  // Returns the BrowserWindowGtk registered with |window|.
-  static BrowserWindowGtk* GetBrowserWindowForNativeWindow(
-      gfx::NativeWindow window);
-
-  // Retrieves the GtkWindow associated with |xid|, which is the X Window
-  // ID of the top-level X window of this object.
-  static GtkWindow* GetBrowserWindowForXID(XID xid);
-
-  Browser* browser() const { return browser_.get(); }
-
-  GtkWindow* window() const { return window_; }
-
-  BrowserToolbarGtk* GetToolbar() { return toolbar_.get(); }
-
-  gfx::Rect bounds() const { return bounds_; }
-
-  // Make changes necessary when the floating state of the bookmark bar changes.
-  // This should only be called by the bookmark bar itself.
-  void BookmarkBarIsFloating(bool is_floating);
-
-  // Returns the tab contents we're currently displaying in the tab contents
-  // container.
-  TabContents* GetDisplayedTabContents();
-
-  static void RegisterUserPrefs(PrefService* prefs);
-
-  // Returns whether to draw the content drop shadow on the sides and bottom
-  // of the browser window. When false, we still draw a shadow on the top of
-  // the toolbar (under the tab strip), but do not round the top corners.
-  bool ShouldDrawContentDropShadow();
-
-  // Tells GTK that the toolbar area is invalidated and needs redrawing. We
-  // have this method as a hack because GTK doesn't queue the toolbar area for
-  // redraw when it should.
-  void QueueToolbarRedraw();
-
-  // Get the position where the infobar arrow should be anchored in
-  // |relative_to| coordinates. This is the middle of the omnibox location icon.
-  int GetXPositionOfLocationIcon(GtkWidget* relative_to);
-
- protected:
-  virtual void DestroyBrowser();
-  // Top level window.
-  GtkWindow* window_;
-  // GtkAlignment that holds the interior components of the chromium window.
-  // This is used to draw the custom frame border and content shadow.
-  GtkWidget* window_container_;
-  // VBox that holds everything (tabs, toolbar, bookmarks bar, tab contents).
-  GtkWidget* window_vbox_;
-  // VBox that holds everything below the toolbar.
-  GtkWidget* render_area_vbox_;
-  // Floating container that holds the render area. It is needed to position
-  // the findbar.
-  GtkWidget* render_area_floating_container_;
-  // EventBox that holds render_area_floating_container_.
-  GtkWidget* render_area_event_box_;
-  // Border between toolbar and render area.
-  GtkWidget* toolbar_border_;
-
-  scoped_ptr<Browser> browser_;
-
-  // The download shelf view (view at the bottom of the page).
-  scoped_ptr<DownloadShelfGtk> download_shelf_;
-
- private:
-  // Show or hide the bookmark bar.
-  void MaybeShowBookmarkBar(bool animate);
-
-  // Sets the default size for the window and the the way the user is allowed to
-  // resize it.
-  void SetGeometryHints();
-
-  // Connect to signals on |window_|.
-  void ConnectHandlersToSignals();
-
-  // Create the various UI components.
-  void InitWidgets();
-
-  // Set up background color of the window (depends on if we're incognito or
-  // not).
-  void SetBackgroundColor();
-
-  // Called when the window size changed.
-  void OnSizeChanged(int width, int height);
-
-  // Applies the window shape to if we're in custom drawing mode.
-  void UpdateWindowShape(int width, int height);
-
-  // Connect accelerators that aren't connected to menu items (like ctrl-o,
-  // ctrl-l, etc.).
-  void ConnectAccelerators();
-
-  // Change whether we're showing the custom blue frame.
-  // Must be called once at startup.
-  // Triggers relayout of the content.
-  void UpdateCustomFrame();
-
-  // Save the window position in the prefs.
-  void SaveWindowPosition();
-
-  // Set the bounds of the current window. If |exterior| is true, set the size
-  // of the window itself, otherwise set the bounds of the web contents.
-  // If |move| is true, set the position of the window, otherwise leave the
-  // position to the WM.
-  void SetBoundsImpl(const gfx::Rect& bounds, bool exterior, bool move);
-
-  // Callback for when the custom frame alignment needs to be redrawn.
-  // The content area includes the toolbar and web page but not the tab strip.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnCustomFrameExpose,
-                       GdkEventExpose*);
-
-  // A helper method that draws the shadow above the toolbar and in the frame
-  // border during an expose.
-  void DrawContentShadow(cairo_t* cr);
-
-  // Draws the tab image as the frame so we can write legible text.
-  void DrawPopupFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
-
-  // Draws the normal custom frame using theme_frame.
-  void DrawCustomFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
-
-  // The background frame image needs to be offset by the size of the top of
-  // the window to the top of the tabs when the full skyline isn't displayed
-  // for some reason.
-  int GetVerticalOffset();
-
-  // Returns which frame image we should use based on the window's current
-  // activation state / incognito state.
-  int GetThemeFrameResource();
-
-  // Invalidate all the widgets that need to redraw when the infobar draw state
-  // has changed.
-  void InvalidateInfoBarBits();
-
-  // When the location icon moves, we have to redraw the arrow.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, void, OnLocationIconSizeAllocate,
-                       GtkAllocation*);
-
-  // Used to draw the infobar arrow and drop shadow. This is connected to
-  // multiple widgets' expose events because it overlaps several widgets.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnExposeDrawInfobarBits,
-                       GdkEventExpose*);
-
-  // Used to draw the infobar bits for the bookmark bar. When the bookmark
-  // bar is in floating mode, it has to draw a drop shadow only; otherwise
-  // it is responsible for its portion of the arrow as well as some shadowing.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnBookmarkBarExpose,
-                       GdkEventExpose*);
-
-  // Callback for "size-allocate" signal on bookmark bar; this is relevant
-  // because when the bookmark bar changes dimensions, the infobar arrow has to
-  // change its shape, and we need to queue appropriate redraws.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, void, OnBookmarkBarSizeAllocate,
-                       GtkAllocation*);
-
-  // Callback for accelerator activation. |user_data| stores the command id
-  // of the matched accelerator.
-  static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group,
-                                   GObject* acceleratable,
-                                   guint keyval,
-                                   GdkModifierType modifier,
-                                   void* user_data);
-
-  // Key press event callback.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnKeyPress, GdkEventKey*);
-
-  // Mouse move and mouse button press callbacks.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnMouseMoveEvent,
-                       GdkEventMotion*);
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnButtonPressEvent,
-                       GdkEventButton*);
-
-  // Maps and Unmaps the xid of |widget| to |window|.
-  static void MainWindowMapped(GtkWidget* widget);
-  static void MainWindowUnMapped(GtkWidget* widget);
-
-  // Tracks focus state of browser.
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnFocusIn,
-                       GdkEventFocus*);
-  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnFocusOut,
-                       GdkEventFocus*);
-
-  // Callback for the loading animation(s) associated with this window.
-  void LoadingAnimationCallback();
-
-  // Shows UI elements for supported window features.
-  void ShowSupportedWindowFeatures();
-
-  // Hides UI elements for unsupported window features.
-  void HideUnsupportedWindowFeatures();
-
-  // Helper functions that query |browser_| concerning support for UI features
-  // in this window. (For example, a popup window might not support a tabstrip).
-  bool IsTabStripSupported() const;
-  bool IsToolbarSupported() const;
-  bool IsBookmarkBarSupported() const;
-
-  // Whether we should draw the tab background instead of the theme_frame
-  // background because this window is a popup.
-  bool UsingCustomPopupFrame() const;
-
-  // Checks to see if the mouse pointer at |x|, |y| is over the border of the
-  // custom frame (a spot that should trigger a window resize). Returns true if
-  // it should and sets |edge|.
-  bool GetWindowEdge(int x, int y, GdkWindowEdge* edge);
-
-  // Returns |true| if we should use the custom frame.
-  bool UseCustomFrame();
-
-  // Returns |true| if the window bounds match the monitor size.
-  bool BoundsMatchMonitorSize();
-
-  // Put the bookmark bar where it belongs.
-  void PlaceBookmarkBar(bool is_floating);
-
-  // Determine whether we use should default to native decorations or the custom
-  // frame based on the currently-running window manager.
-  static bool GetCustomFramePrefDefault();
-
-  NotificationRegistrar registrar_;
-
-  // The position and size of the current window.
-  gfx::Rect bounds_;
-
-  // The position and size of the non-maximized, non-fullscreen window.
-  gfx::Rect restored_bounds_;
-
-  GdkWindowState state_;
-
-  // The container for the titlebar + tab strip.
-  scoped_ptr<BrowserTitlebar> titlebar_;
-
-  // The object that manages all of the widgets in the toolbar.
-  scoped_ptr<BrowserToolbarGtk> toolbar_;
-
-  // The object that manages the bookmark bar. This will be NULL if the
-  // bookmark bar is not supported.
-  scoped_ptr<BookmarkBarGtk> bookmark_bar_;
-
-  // Caches the hover state of the bookmark bar.
-  bool bookmark_bar_is_floating_;
-
-  // The status bubble manager.  Always non-NULL.
-  scoped_ptr<StatusBubbleGtk> status_bubble_;
-
-  // A container that manages the GtkWidget*s that are the webpage display
-  // (along with associated infobars, shelves, and other things that are part
-  // of the content area).
-  scoped_ptr<TabContentsContainerGtk> contents_container_;
-
-  // A container that manages the GtkWidget*s of developer tools for the
-  // selected tab contents.
-  scoped_ptr<TabContentsContainerGtk> devtools_container_;
-
-  // Split pane containing the contents_container_ and the devtools_container_.
-  GtkWidget* contents_split_;
-
-  // The tab strip.  Always non-NULL.
-  scoped_ptr<TabStripGtk> tabstrip_;
-
-  // The container for info bars. Always non-NULL.
-  scoped_ptr<InfoBarContainerGtk> infobar_container_;
-
-  // The timer used to update frames for the Loading Animation.
-  base::RepeatingTimer<BrowserWindowGtk> loading_animation_timer_;
-
-  // The timer used to save the window position for session restore.
-  base::OneShotTimer<BrowserWindowGtk> window_configure_debounce_timer_;
-
-  // Whether the custom chrome frame pref is set.  Normally you want to use
-  // UseCustomFrame() above to determine whether to use the custom frame or
-  // not.
-  BooleanPrefMember use_custom_frame_pref_;
-
-  // A map which translates an X Window ID into its respective GtkWindow.
-  static std::map<XID, GtkWindow*> xid_map_;
-
-  // The current window cursor.  We set it to a resize cursor when over the
-  // custom frame border.  We set it to NULL if we want the default cursor.
-  GdkCursor* frame_cursor_;
-
-  // True if the window manager thinks the window is active.  Not all window
-  // managers keep track of this state (_NET_ACTIVE_WINDOW), in which case
-  // this will always be true.
-  bool is_active_;
-
-  // Keep track of the last click time and the last click position so we can
-  // filter out extra GDK_BUTTON_PRESS events when a double click happens.
-  guint32 last_click_time_;
-  gfx::Point last_click_position_;
-
-  // If true, maximize the window after we call BrowserWindow::Show for the
-  // first time.  This is to work around a compiz bug.
-  bool maximize_after_show_;
-
-  // If true, don't call gdk_window_raise() when we get a click in the title
-  // bar or window border.  This is to work around a compiz bug.
-  bool suppress_window_raise_;
-
-  // The accelerator group used to handle accelerators, owned by this object.
-  GtkAccelGroup* accel_group_;
-
-  scoped_ptr<FullscreenExitBubbleGtk> fullscreen_exit_bubble_;
-
-  // The model that tracks the paint state of the arrow for the infobar
-  // directly below the toolbar.
-  InfoBarArrowModel infobar_arrow_model_;
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_
diff --git a/chrome/browser/gtk/cairo_cached_surface.cc b/chrome/browser/gtk/cairo_cached_surface.cc
deleted file mode 100644
index bb5ae41..0000000
--- a/chrome/browser/gtk/cairo_cached_surface.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-
-#include <gtk/gtk.h>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-
-CairoCachedSurface::CairoCachedSurface() : pixbuf_(NULL), surface_(NULL) {
-}
-
-CairoCachedSurface::~CairoCachedSurface() {
-  if (surface_)
-    cairo_surface_destroy(surface_);
-
-  if (pixbuf_)
-    g_object_unref(pixbuf_);
-}
-
-int CairoCachedSurface::Width() const {
-  return pixbuf_ ? gdk_pixbuf_get_width(pixbuf_) : -1;
-}
-
-int CairoCachedSurface::Height() const {
-  return pixbuf_ ? gdk_pixbuf_get_height(pixbuf_) : -1;
-}
-
-void CairoCachedSurface::UsePixbuf(GdkPixbuf* pixbuf) {
-  if (surface_) {
-    cairo_surface_destroy(surface_);
-    surface_ = NULL;
-  }
-
-  if (pixbuf)
-    g_object_ref(pixbuf);
-
-  if (pixbuf_)
-    g_object_unref(pixbuf_);
-
-  pixbuf_ = pixbuf;
-}
-
-void CairoCachedSurface::SetSource(cairo_t* cr, int x, int y) {
-  DCHECK(pixbuf_);
-  DCHECK(cr);
-
-  if (!surface_) {
-    // First time here since last UsePixbuf call. Generate the surface.
-    cairo_surface_t* target = cairo_get_target(cr);
-    surface_ = cairo_surface_create_similar(
-        target,
-        CAIRO_CONTENT_COLOR_ALPHA,
-        gdk_pixbuf_get_width(pixbuf_),
-        gdk_pixbuf_get_height(pixbuf_));
-
-    DCHECK(surface_);
-#if !defined(NDEBUG)
-    int surface_type = cairo_surface_get_type(surface_);
-    DCHECK(surface_type == CAIRO_SURFACE_TYPE_XLIB ||
-           surface_type == CAIRO_SURFACE_TYPE_XCB ||
-           surface_type == CAIRO_SURFACE_TYPE_IMAGE);
-#endif
-
-    cairo_t* copy_cr = cairo_create(surface_);
-    gdk_cairo_set_source_pixbuf(copy_cr, pixbuf_, 0, 0);
-    cairo_paint(copy_cr);
-    cairo_destroy(copy_cr);
-  }
-
-  cairo_set_source_surface(cr, surface_, x, y);
-}
diff --git a/chrome/browser/gtk/cairo_cached_surface.h b/chrome/browser/gtk/cairo_cached_surface.h
deleted file mode 100644
index b257062..0000000
--- a/chrome/browser/gtk/cairo_cached_surface.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CAIRO_CACHED_SURFACE_H_
-#define CHROME_BROWSER_GTK_CAIRO_CACHED_SURFACE_H_
-#pragma once
-
-typedef struct _GdkPixbuf GdkPixbuf;
-typedef struct _cairo cairo_t;
-typedef struct _cairo_surface cairo_surface_t;
-
-// A helper class that takes a GdkPixbuf* and renders it to the screen. Unlike
-// gdk_cairo_set_source_pixbuf(), CairoCachedSurface assumes that the pixbuf is
-// immutable after UsePixbuf() is called and can be sent to the X server
-// once. From then on, that cached version is used so we don't upload the same
-// image each and every time we expose.
-//
-// Most cached surfaces are owned by the GtkThemeProvider, which associates
-// them with a certain XDisplay. Some users of surfaces (CustomDrawButtonBase,
-// for example) own their surfaces instead since they interact with the
-// ResourceBundle instead of the GtkThemeProvider.
-class CairoCachedSurface {
- public:
-  CairoCachedSurface();
-  ~CairoCachedSurface();
-
-  // Whether this CairoCachedSurface owns a GdkPixbuf.
-  bool valid() const {
-    return pixbuf_;
-  }
-
-  // The dimensions of the underlying pixbuf/surface. (or -1 if invalid.)
-  int Width() const;
-  int Height() const;
-
-  // Sets the pixbuf that we pass to cairo. Calling UsePixbuf() only derefs the
-  // current pixbuf and surface (if they exist). Actually transfering data to
-  // the X server occurs at SetSource() time. Calling UsePixbuf() should only
-  // be done once as it clears cached data from the X server.
-  void UsePixbuf(GdkPixbuf* pixbuf);
-
-  // Sets our pixbuf as the active surface starting at (x, y), uploading it in
-  // case we don't have an X backed surface cached.
-  void SetSource(cairo_t* cr, int x, int y);
-
-  // Raw access to the pixbuf. May be NULL. Used for a few gdk operations
-  // regarding window shaping.
-  GdkPixbuf* pixbuf() { return pixbuf_; }
-
- private:
-  // The source pixbuf.
-  GdkPixbuf* pixbuf_;
-
-  // Our cached surface. This should be a xlib surface so the data lives on the
-  // server instead of on the client.
-  cairo_surface_t* surface_;
-};
-
-#endif  // CHROME_BROWSER_GTK_CAIRO_CACHED_SURFACE_H_
diff --git a/chrome/browser/gtk/certificate_dialogs.cc b/chrome/browser/gtk/certificate_dialogs.cc
deleted file mode 100644
index 8709bb4..0000000
--- a/chrome/browser/gtk/certificate_dialogs.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(mattm): this isn't gtk specific, it shouldn't be under the gtk dir
-
-#include "chrome/browser/gtk/certificate_dialogs.h"
-
-
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "base/base64.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/shell_dialogs.h"
-#include "chrome/common/net/x509_certificate_model.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-////////////////////////////////////////////////////////////////////////////////
-// General utility functions.
-
-class Writer : public Task {
- public:
-  Writer(const FilePath& path, const std::string& data)
-      : path_(path), data_(data) {
-  }
-
-  virtual void Run() {
-    int bytes_written = file_util::WriteFile(path_, data_.data(), data_.size());
-    if (bytes_written != static_cast<ssize_t>(data_.size())) {
-      LOG(ERROR) << "Writing " << path_.value() << " ("
-                 << data_.size() << "B) returned " << bytes_written;
-    }
-  }
- private:
-  FilePath path_;
-  std::string data_;
-};
-
-void WriteFileOnFileThread(const FilePath& path, const std::string& data) {
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE, new Writer(path, data));
-}
-
-std::string WrapAt64(const std::string &str) {
-  std::string result;
-  for (size_t i = 0; i < str.size(); i += 64) {
-    result.append(str, i, 64);  // Append clamps the len arg internally.
-    result.append("\r\n");
-  }
-  return result;
-}
-
-std::string GetBase64String(net::X509Certificate::OSCertHandle cert) {
-  std::string base64;
-  if (!base::Base64Encode(
-      x509_certificate_model::GetDerString(cert), &base64)) {
-    LOG(ERROR) << "base64 encoding error";
-    return "";
-  }
-  return "-----BEGIN CERTIFICATE-----\r\n" +
-      WrapAt64(base64) +
-      "-----END CERTIFICATE-----\r\n";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// General utility functions.
-
-class Exporter : public SelectFileDialog::Listener {
- public:
-  Exporter(gfx::NativeWindow parent, net::X509Certificate::OSCertHandle cert);
-  ~Exporter();
-
-  // SelectFileDialog::Listener implemenation.
-  virtual void FileSelected(const FilePath& path,
-                            int index, void* params);
-  virtual void FileSelectionCanceled(void* params);
- private:
-  scoped_refptr<SelectFileDialog> select_file_dialog_;
-
-  // The certificate hierarchy (leaf cert first).
-  net::X509Certificate::OSCertHandles cert_chain_list_;
-};
-
-Exporter::Exporter(gfx::NativeWindow parent,
-                   net::X509Certificate::OSCertHandle cert)
-    : select_file_dialog_(SelectFileDialog::Create(this)) {
-  x509_certificate_model::GetCertChainFromCert(cert, &cert_chain_list_);
-
-  // TODO(mattm): should this default to some directory?
-  // Maybe SavePackage::GetSaveDirPreference? (Except that it's private.)
-  FilePath suggested_path("certificate");
-  std::string cert_title = x509_certificate_model::GetTitle(cert);
-  if (!cert_title.empty())
-    suggested_path = FilePath(cert_title);
-
-  ShowCertSelectFileDialog(select_file_dialog_.get(),
-                           SelectFileDialog::SELECT_SAVEAS_FILE,
-                           suggested_path,
-                           parent,
-                           NULL);
-}
-
-Exporter::~Exporter() {
-  x509_certificate_model::DestroyCertChain(&cert_chain_list_);
-}
-
-void Exporter::FileSelected(const FilePath& path, int index, void* params) {
-  std::string data;
-  switch (index) {
-    case 2:
-      for (size_t i = 0; i < cert_chain_list_.size(); ++i)
-        data += GetBase64String(cert_chain_list_[i]);
-      break;
-    case 3:
-      data = x509_certificate_model::GetDerString(cert_chain_list_[0]);
-      break;
-    case 4:
-      data = x509_certificate_model::GetCMSString(cert_chain_list_, 0, 1);
-      break;
-    case 5:
-      data = x509_certificate_model::GetCMSString(
-          cert_chain_list_, 0, cert_chain_list_.size());
-      break;
-    case 1:
-    default:
-      data = GetBase64String(cert_chain_list_[0]);
-      break;
-  }
-
-  if (!data.empty())
-    WriteFileOnFileThread(path, data);
-
-  delete this;
-}
-
-void Exporter::FileSelectionCanceled(void* params) {
-  delete this;
-}
-
-} // namespace
-
-void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog,
-                              SelectFileDialog::Type type,
-                              const FilePath& suggested_path,
-                              gfx::NativeWindow parent,
-                              void* params) {
-  SelectFileDialog::FileTypeInfo file_type_info;
-  file_type_info.extensions.resize(5);
-  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("pem"));
-  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("crt"));
-  file_type_info.extension_description_overrides.push_back(
-      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64));
-  file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("pem"));
-  file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("crt"));
-  file_type_info.extension_description_overrides.push_back(
-      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64_CHAIN));
-  file_type_info.extensions[2].push_back(FILE_PATH_LITERAL("der"));
-  file_type_info.extension_description_overrides.push_back(
-      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_DER));
-  file_type_info.extensions[3].push_back(FILE_PATH_LITERAL("p7c"));
-  file_type_info.extension_description_overrides.push_back(
-      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7));
-  file_type_info.extensions[4].push_back(FILE_PATH_LITERAL("p7c"));
-  file_type_info.extension_description_overrides.push_back(
-      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7_CHAIN));
-  file_type_info.include_all_files = true;
-  select_file_dialog->SelectFile(
-      type, string16(),
-      suggested_path, &file_type_info, 1,
-      FILE_PATH_LITERAL("crt"), parent,
-      params);
-}
-
-void ShowCertExportDialog(gfx::NativeWindow parent,
-                          net::X509Certificate::OSCertHandle cert) {
-  new Exporter(parent, cert);
-}
diff --git a/chrome/browser/gtk/certificate_dialogs.h b/chrome/browser/gtk/certificate_dialogs.h
deleted file mode 100644
index e982195..0000000
--- a/chrome/browser/gtk/certificate_dialogs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CERTIFICATE_DIALOGS_H_
-#define CHROME_BROWSER_GTK_CERTIFICATE_DIALOGS_H_
-#pragma once
-
-#include "chrome/browser/shell_dialogs.h"
-#include "net/base/x509_certificate.h"
-
-void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog,
-                              SelectFileDialog::Type type,
-                              const FilePath& suggested_path,
-                              gfx::NativeWindow parent,
-                              void* params);
-
-void ShowCertExportDialog(gfx::NativeWindow parent,
-                          net::X509Certificate::OSCertHandle cert);
-
-#endif  // CHROME_BROWSER_GTK_CERTIFICATE_DIALOGS_H_
diff --git a/chrome/browser/gtk/certificate_viewer.cc b/chrome/browser/gtk/certificate_viewer.cc
deleted file mode 100644
index a79507d..0000000
--- a/chrome/browser/gtk/certificate_viewer.cc
+++ /dev/null
@@ -1,694 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/certificate_viewer.h"
-
-#include <gtk/gtk.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "base/i18n/time_formatting.h"
-#include "base/nss_util.h"
-#include "base/scoped_ptr.h"
-#include "base/string_number_conversions.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/certificate_dialogs.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/common/net/x509_certificate_model.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "net/base/x509_certificate.h"
-
-namespace {
-
-const char kDetailsFontFamily[] = "monospace";
-
-////////////////////////////////////////////////////////////////////////////////
-// Gtk utility functions.
-
-void AddTitle(GtkTable* table, int row, const std::string& text) {
-  gtk_table_attach_defaults(table,
-                            gtk_util::CreateBoldLabel(text),
-                            0, 2,
-                            row, row + 1);
-}
-
-void AddKeyValue(GtkTable* table, int row, const std::string& text,
-                 const std::string& value) {
-  gtk_table_attach_defaults(
-      table,
-      gtk_util::IndentWidget(
-          gtk_util::LeftAlignMisc(gtk_label_new(text.c_str()))),
-      0, 1, row, row + 1);
-  gtk_table_attach_defaults(
-      table,
-      gtk_util::LeftAlignMisc(gtk_label_new(value.c_str())),
-      1, 2, row, row + 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CertificateViewer class definition.
-
-class CertificateViewer {
- public:
-  CertificateViewer(gfx::NativeWindow parent,
-                    const net::X509Certificate::OSCertHandles& cert_chain_list);
-  ~CertificateViewer();
-
-  void InitGeneralPage();
-  void InitDetailsPage();
-
-  void Show();
-
- private:
-  // Indices and column count for the certificate chain hierarchy tree store.
-  enum {
-    HIERARCHY_NAME,
-    HIERARCHY_OBJECT,
-    HIERARCHY_INDEX,
-    HIERARCHY_COLUMNS
-  };
-
-  // Indices and column count for the certificate fields tree store.
-  enum {
-    FIELDS_NAME,
-    FIELDS_VALUE,
-    FIELDS_COLUMNS
-  };
-
-  // Fill the tree store with the certificate hierarchy, and set |leaf| to the
-  // iter of the leaf node.
-  void FillHierarchyStore(GtkTreeStore* hierarchy_store,
-                          GtkTreeIter* leaf) const;
-
-  // Fill the tree store with the details of the given certificate.
-  static void FillTreeStoreWithCertFields(
-      GtkTreeStore* store, net::X509Certificate::OSCertHandle cert);
-
-  // Create a tree store filled with the details of the given certificate.
-  static GtkTreeStore* CreateFieldsTreeStore(
-      net::X509Certificate::OSCertHandle cert);
-
-  // Callbacks for user selecting elements in the trees.
-  static void OnHierarchySelectionChanged(GtkTreeSelection* selection,
-                                          CertificateViewer* viewer);
-  static void OnFieldsSelectionChanged(GtkTreeSelection* selection,
-                                       CertificateViewer* viewer);
-
-  // Callback for export button.
-  static void OnExportClicked(GtkButton *button, CertificateViewer* viewer);
-
-  // The certificate hierarchy (leaf cert first).
-  net::X509Certificate::OSCertHandles cert_chain_list_;
-
-  GtkWidget* dialog_;
-  GtkWidget* notebook_;
-  GtkWidget* general_page_vbox_;
-  GtkWidget* details_page_vbox_;
-  GtkTreeSelection* hierarchy_selection_;
-  GtkWidget* fields_tree_;
-  GtkTextBuffer* field_value_buffer_;
-  GtkWidget* export_button_;
-
-  DISALLOW_COPY_AND_ASSIGN(CertificateViewer);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// CertificateViewer implementation.
-
-// Close button callback.
-void OnDialogResponse(GtkDialog* dialog, gint response_id,
-                      gpointer user_data) {
-  // "Close" was clicked.
-  gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-void OnDestroy(GtkDialog* dialog, CertificateViewer* cert_viewer) {
-  delete cert_viewer;
-}
-
-CertificateViewer::CertificateViewer(
-    gfx::NativeWindow parent,
-    const net::X509Certificate::OSCertHandles& cert_chain_list)
-    : cert_chain_list_(cert_chain_list) {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringFUTF8(
-          IDS_CERT_INFO_DIALOG_TITLE,
-          UTF8ToUTF16(
-              x509_certificate_model::GetTitle(
-                  cert_chain_list_.front()))).c_str(),
-      parent,
-      // Non-modal.
-      GTK_DIALOG_NO_SEPARATOR,
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  x509_certificate_model::RegisterDynamicOids();
-  InitGeneralPage();
-  InitDetailsPage();
-
-  notebook_ = gtk_notebook_new();
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      general_page_vbox_,
-      gtk_label_new_with_mnemonic(
-          gfx::ConvertAcceleratorsFromWindowsStyle(
-              l10n_util::GetStringUTF8(
-                  IDS_CERT_INFO_GENERAL_TAB_LABEL)).c_str()));
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      details_page_vbox_,
-      gtk_label_new_with_mnemonic(
-          gfx::ConvertAcceleratorsFromWindowsStyle(
-              l10n_util::GetStringUTF8(
-                  IDS_CERT_INFO_DETAILS_TAB_LABEL)).c_str()));
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponse), NULL);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this);
-}
-
-CertificateViewer::~CertificateViewer() {
-  x509_certificate_model::DestroyCertChain(&cert_chain_list_);
-}
-
-void CertificateViewer::InitGeneralPage() {
-  net::X509Certificate::OSCertHandle cert = cert_chain_list_.front();
-  general_page_vbox_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(general_page_vbox_),
-                                 gtk_util::kContentAreaBorder);
-
-  GtkWidget* uses_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(general_page_vbox_), uses_vbox, FALSE, FALSE, 0);
-  gtk_box_pack_start(
-      GTK_BOX(uses_vbox),
-      gtk_util::CreateBoldLabel(
-          l10n_util::GetStringUTF8(IDS_CERT_INFO_VERIFIED_USAGES_GROUP)),
-      FALSE, FALSE, 0);
-
-  std::vector<std::string> usages;
-  x509_certificate_model::GetUsageStrings(cert, &usages);
-  for (size_t i = 0; i < usages.size(); ++i)
-    gtk_box_pack_start(
-        GTK_BOX(uses_vbox),
-        gtk_util::IndentWidget(gtk_util::LeftAlignMisc(gtk_label_new(
-            usages[i].c_str()))),
-        FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(general_page_vbox_), gtk_hseparator_new(),
-                     FALSE, FALSE, 0);
-
-  const int num_rows = 21;
-  GtkTable* table = GTK_TABLE(gtk_table_new(num_rows, 2, FALSE));
-  gtk_table_set_col_spacing(table, 0, gtk_util::kLabelSpacing);
-  gtk_table_set_row_spacings(table, gtk_util::kControlSpacing);
-
-  gtk_box_pack_start(GTK_BOX(general_page_vbox_), GTK_WIDGET(table),
-                     FALSE, FALSE, 0);
-  int row = 0;
-  const std::string alternative_text =
-      l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT);
-  AddTitle(table, row++,
-           l10n_util::GetStringUTF8(IDS_CERT_INFO_SUBJECT_GROUP));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL),
-              x509_certificate_model::ProcessIDN(
-                  x509_certificate_model::GetSubjectCommonName(
-                      cert, alternative_text)));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATION_LABEL),
-              x509_certificate_model::GetSubjectOrgName(
-                  cert, alternative_text));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL),
-              x509_certificate_model::GetSubjectOrgUnitName(
-                  cert, alternative_text));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_SERIAL_NUMBER_LABEL),
-              x509_certificate_model::GetSerialNumberHexified(
-                  cert, alternative_text));
-
-  row += 2;  // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
-
-  AddTitle(table, row++,
-           l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUER_GROUP));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL),
-              x509_certificate_model::ProcessIDN(
-                  x509_certificate_model::GetIssuerCommonName(
-                      cert, alternative_text)));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATION_LABEL),
-              x509_certificate_model::GetIssuerOrgName(
-                  cert, alternative_text));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL),
-              x509_certificate_model::GetIssuerOrgUnitName(
-                  cert, alternative_text));
-
-  row += 2;  // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
-
-  base::Time issued, expires;
-  std::string issued_str, expires_str;
-  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
-    issued_str = UTF16ToUTF8(
-        base::TimeFormatShortDateNumeric(issued));
-    expires_str = UTF16ToUTF8(
-        base::TimeFormatShortDateNumeric(expires));
-  } else {
-    issued_str = alternative_text;
-    expires_str = alternative_text;
-  }
-  AddTitle(table, row++,
-           l10n_util::GetStringUTF8(IDS_CERT_INFO_VALIDITY_GROUP));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUED_ON_LABEL),
-              issued_str);
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_EXPIRES_ON_LABEL),
-              expires_str);
-
-  row += 2;  // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
-
-  AddTitle(table, row++,
-           l10n_util::GetStringUTF8(IDS_CERT_INFO_FINGERPRINTS_GROUP));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL),
-              x509_certificate_model::HashCertSHA256(cert));
-  AddKeyValue(table, row++,
-              l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL),
-              x509_certificate_model::HashCertSHA1(cert));
-
-  DCHECK_EQ(row, num_rows);
-}
-
-void CertificateViewer::FillHierarchyStore(GtkTreeStore* hierarchy_store,
-                                           GtkTreeIter* leaf) const {
-  GtkTreeIter parent;
-  GtkTreeIter* parent_ptr = NULL;
-  GtkTreeIter iter;
-  gint index = cert_chain_list_.size() - 1;
-  for (net::X509Certificate::OSCertHandles::const_reverse_iterator i =
-          cert_chain_list_.rbegin();
-       i != cert_chain_list_.rend(); ++i, --index) {
-    gtk_tree_store_append(hierarchy_store, &iter, parent_ptr);
-    GtkTreeStore* fields_store = CreateFieldsTreeStore(*i);
-    gtk_tree_store_set(
-        hierarchy_store, &iter,
-        HIERARCHY_NAME, x509_certificate_model::GetTitle(*i).c_str(),
-        HIERARCHY_OBJECT, fields_store,
-        HIERARCHY_INDEX, index,
-        -1);
-    g_object_unref(fields_store);
-    parent = iter;
-    parent_ptr = &parent;
-  }
-  *leaf = iter;
-}
-
-// static
-void CertificateViewer::FillTreeStoreWithCertFields(
-    GtkTreeStore* store, net::X509Certificate::OSCertHandle cert) {
-  GtkTreeIter top;
-  gtk_tree_store_append(store, &top, NULL);
-  gtk_tree_store_set(
-      store, &top,
-      FIELDS_NAME, x509_certificate_model::GetTitle(cert).c_str(),
-      FIELDS_VALUE, "",
-      -1);
-
-  GtkTreeIter cert_iter;
-  gtk_tree_store_append(store, &cert_iter, &top);
-  gtk_tree_store_set(
-      store, &cert_iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE).c_str(),
-      FIELDS_VALUE, "",
-      -1);
-
-  std::string version_str;
-  std::string version = x509_certificate_model::GetVersion(cert);
-  if (!version.empty())
-    version_str = l10n_util::GetStringFUTF8(IDS_CERT_DETAILS_VERSION_FORMAT,
-                                            UTF8ToUTF16(version));
-  GtkTreeIter iter;
-  gtk_tree_store_append(store, &iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VERSION).c_str(),
-      FIELDS_VALUE, version_str.c_str(),
-      -1);
-
-  gtk_tree_store_append(store, &iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SERIAL_NUMBER).c_str(),
-      FIELDS_VALUE,
-      x509_certificate_model::GetSerialNumberHexified(
-          cert,
-          l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT)).c_str(),
-      -1);
-
-  gtk_tree_store_append(store, &iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG).c_str(),
-      FIELDS_VALUE,
-      x509_certificate_model::ProcessSecAlgorithmSignature(cert).c_str(),
-      -1);
-
-  gtk_tree_store_append(store, &iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_ISSUER).c_str(),
-      FIELDS_VALUE, x509_certificate_model::GetIssuerName(cert).c_str(),
-      -1);
-
-  GtkTreeIter validity_iter;
-  gtk_tree_store_append(store, &validity_iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &validity_iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VALIDITY).c_str(),
-      FIELDS_VALUE, "",
-      -1);
-
-  base::Time issued, expires;
-  std::string issued_str, expires_str;
-  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
-    issued_str = UTF16ToUTF8(base::TimeFormatShortDateAndTime(issued));
-    expires_str = UTF16ToUTF8(base::TimeFormatShortDateAndTime(expires));
-  }
-  gtk_tree_store_append(store, &iter, &validity_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_BEFORE).c_str(),
-      FIELDS_VALUE, issued_str.c_str(),
-      -1);
-  gtk_tree_store_append(store, &iter, &validity_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_AFTER).c_str(),
-      FIELDS_VALUE, expires_str.c_str(),
-      -1);
-
-  gtk_tree_store_append(store, &iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT).c_str(),
-      FIELDS_VALUE, x509_certificate_model::GetSubjectName(cert).c_str(),
-      -1);
-
-  GtkTreeIter subject_public_key_iter;
-  gtk_tree_store_append(store, &subject_public_key_iter, &cert_iter);
-  gtk_tree_store_set(
-      store, &subject_public_key_iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_INFO).c_str(),
-      FIELDS_VALUE, "",
-      -1);
-
-  gtk_tree_store_append(store, &iter, &subject_public_key_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_ALG).c_str(),
-      FIELDS_VALUE,
-      x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(cert).c_str(),
-      -1);
-
-  gtk_tree_store_append(store, &iter, &subject_public_key_iter);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY).c_str(),
-      FIELDS_VALUE,
-      x509_certificate_model::ProcessSubjectPublicKeyInfo(cert).c_str(),
-      -1);
-
-  x509_certificate_model::Extensions extensions;
-  x509_certificate_model::GetExtensions(
-      l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL),
-      l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL),
-      cert, &extensions);
-
-  if (!extensions.empty()) {
-    GtkTreeIter extensions_iter;
-    gtk_tree_store_append(store, &extensions_iter, &cert_iter);
-    gtk_tree_store_set(
-        store, &extensions_iter,
-        FIELDS_NAME,
-        l10n_util::GetStringUTF8(IDS_CERT_DETAILS_EXTENSIONS).c_str(),
-        FIELDS_VALUE, "",
-        -1);
-
-    for (x509_certificate_model::Extensions::const_iterator i =
-         extensions.begin(); i != extensions.end(); ++i) {
-      gtk_tree_store_append(store, &iter, &extensions_iter);
-      gtk_tree_store_set(
-          store, &iter,
-          FIELDS_NAME, i->name.c_str(),
-          FIELDS_VALUE, i->value.c_str(),
-          -1);
-    }
-  }
-
-  gtk_tree_store_append(store, &iter, &top);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG).c_str(),
-      FIELDS_VALUE,
-      x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert).c_str(),
-      -1);
-
-  gtk_tree_store_append(store, &iter, &top);
-  gtk_tree_store_set(
-      store, &iter,
-      FIELDS_NAME,
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE).c_str(),
-      FIELDS_VALUE,
-      x509_certificate_model::ProcessRawBitsSignatureWrap(cert).c_str(),
-      -1);
-}
-
-// static
-GtkTreeStore* CertificateViewer::CreateFieldsTreeStore(
-    net::X509Certificate::OSCertHandle cert) {
-  GtkTreeStore* fields_store = gtk_tree_store_new(FIELDS_COLUMNS, G_TYPE_STRING,
-                                                  G_TYPE_STRING);
-  FillTreeStoreWithCertFields(fields_store, cert);
-  return fields_store;
-}
-
-void CertificateViewer::InitDetailsPage() {
-  details_page_vbox_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(details_page_vbox_),
-                                 gtk_util::kContentAreaBorder);
-
-  GtkWidget* hierarchy_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(details_page_vbox_), hierarchy_vbox,
-                     FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(hierarchy_vbox),
-                     gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
-                         IDS_CERT_DETAILS_CERTIFICATE_HIERARCHY_LABEL)),
-                     FALSE, FALSE, 0);
-
-  GtkTreeStore* hierarchy_store = gtk_tree_store_new(HIERARCHY_COLUMNS,
-                                                     G_TYPE_STRING,
-                                                     G_TYPE_OBJECT,
-                                                     G_TYPE_INT);
-  GtkTreeIter hierarchy_leaf_iter;
-  FillHierarchyStore(hierarchy_store, &hierarchy_leaf_iter);
-  GtkWidget* hierarchy_tree = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(hierarchy_store));
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(hierarchy_tree), FALSE);
-  gtk_tree_view_append_column(
-      GTK_TREE_VIEW(hierarchy_tree),
-      gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(),
-                                               "text", HIERARCHY_NAME,
-                                               NULL));
-  gtk_tree_view_expand_all(GTK_TREE_VIEW(hierarchy_tree));
-  hierarchy_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(hierarchy_tree));
-  gtk_tree_selection_set_mode(hierarchy_selection_, GTK_SELECTION_SINGLE);
-  g_signal_connect(hierarchy_selection_, "changed",
-                   G_CALLBACK(OnHierarchySelectionChanged), this);
-  GtkWidget* hierarchy_scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(hierarchy_scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_NEVER);
-  gtk_scrolled_window_set_shadow_type(
-      GTK_SCROLLED_WINDOW(hierarchy_scroll_window), GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(hierarchy_scroll_window), hierarchy_tree);
-  gtk_box_pack_start(GTK_BOX(hierarchy_vbox),
-                     hierarchy_scroll_window, FALSE, FALSE, 0);
-
-  GtkWidget* fields_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(details_page_vbox_), fields_vbox,
-                     TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(fields_vbox),
-                     gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
-                         IDS_CERT_DETAILS_CERTIFICATE_FIELDS_LABEL)),
-                     FALSE, FALSE, 0);
-
-  fields_tree_ = gtk_tree_view_new();
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(fields_tree_), FALSE);
-  gtk_tree_view_append_column(
-      GTK_TREE_VIEW(fields_tree_),
-      gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(),
-                                               "text", FIELDS_NAME,
-                                               NULL));
-  GtkTreeSelection* fields_selection = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(fields_tree_));
-  gtk_tree_selection_set_mode(fields_selection, GTK_SELECTION_SINGLE);
-  g_signal_connect(fields_selection, "changed",
-                   G_CALLBACK(OnFieldsSelectionChanged), this);
-  GtkWidget* fields_scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fields_scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(
-      GTK_SCROLLED_WINDOW(fields_scroll_window), GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(fields_scroll_window), fields_tree_);
-  gtk_box_pack_start(GTK_BOX(fields_vbox),
-                     fields_scroll_window, TRUE, TRUE, 0);
-
-  GtkWidget* value_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(details_page_vbox_), value_vbox,
-                     TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(value_vbox),
-                     gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
-                         IDS_CERT_DETAILS_CERTIFICATE_FIELD_VALUE_LABEL)),
-                     FALSE, FALSE, 0);
-
-  // TODO(mattm): fix text view coloring (should have grey background).
-  GtkWidget* field_value_view = gtk_text_view_new();
-  gtk_text_view_set_editable(GTK_TEXT_VIEW(field_value_view), FALSE);
-  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(field_value_view), GTK_WRAP_NONE);
-  field_value_buffer_ = gtk_text_view_get_buffer(
-      GTK_TEXT_VIEW(field_value_view));
-  GtkWidget* value_scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(value_scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(
-      GTK_SCROLLED_WINDOW(value_scroll_window), GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(value_scroll_window), field_value_view);
-  gtk_box_pack_start(GTK_BOX(value_vbox),
-                     value_scroll_window, TRUE, TRUE, 0);
-
-  gtk_widget_ensure_style(field_value_view);
-  PangoFontDescription* font_desc = pango_font_description_copy(
-      gtk_widget_get_style(field_value_view)->font_desc);
-  pango_font_description_set_family(font_desc, kDetailsFontFamily);
-  gtk_widget_modify_font(field_value_view, font_desc);
-  pango_font_description_free(font_desc);
-
-  GtkWidget* export_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(details_page_vbox_), export_hbox,
-                     FALSE, FALSE, 0);
-  export_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(
-              IDS_CERT_DETAILS_EXPORT_CERTIFICATE)).c_str());
-  g_signal_connect(export_button_, "clicked",
-                   G_CALLBACK(OnExportClicked), this);
-  gtk_box_pack_start(GTK_BOX(export_hbox), export_button_,
-                     FALSE, FALSE, 0);
-
-  // Select the initial certificate in the hierarchy.
-  gtk_tree_selection_select_iter(hierarchy_selection_, &hierarchy_leaf_iter);
-}
-
-// static
-void CertificateViewer::OnHierarchySelectionChanged(
-    GtkTreeSelection* selection, CertificateViewer* viewer) {
-  GtkTreeIter iter;
-  GtkTreeModel* model;
-  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
-    GtkTreeStore* fields_store = NULL;
-    gtk_tree_model_get(model, &iter, HIERARCHY_OBJECT, &fields_store, -1);
-    gtk_tree_view_set_model(GTK_TREE_VIEW(viewer->fields_tree_),
-                            GTK_TREE_MODEL(fields_store));
-    gtk_tree_view_expand_all(GTK_TREE_VIEW(viewer->fields_tree_));
-    gtk_widget_set_sensitive(viewer->export_button_, TRUE);
-  } else {
-    gtk_tree_view_set_model(GTK_TREE_VIEW(viewer->fields_tree_), NULL);
-    gtk_widget_set_sensitive(viewer->export_button_, FALSE);
-  }
-}
-
-// static
-void CertificateViewer::OnFieldsSelectionChanged(GtkTreeSelection* selection,
-                                                 CertificateViewer* viewer) {
-  GtkTreeIter iter;
-  GtkTreeModel* model;
-  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
-    gchar* value_string = NULL;
-    gtk_tree_model_get(model, &iter, FIELDS_VALUE, &value_string, -1);
-    if (value_string) {
-      gtk_text_buffer_set_text(viewer->field_value_buffer_, value_string, -1);
-      g_free(value_string);
-    } else {
-      gtk_text_buffer_set_text(viewer->field_value_buffer_, "", 0);
-    }
-  } else {
-    gtk_text_buffer_set_text(viewer->field_value_buffer_, "", 0);
-  }
-}
-
-// static
-void CertificateViewer::OnExportClicked(GtkButton *button,
-                                        CertificateViewer* viewer) {
-  GtkTreeIter iter;
-  GtkTreeModel* model;
-  if (!gtk_tree_selection_get_selected(viewer->hierarchy_selection_, &model,
-                                       &iter))
-    return;
-  gint cert_index = -1;
-  gtk_tree_model_get(model, &iter, HIERARCHY_INDEX, &cert_index, -1);
-
-  if (cert_index < 0) {
-    NOTREACHED();
-    return;
-  }
-
-  ShowCertExportDialog(GTK_WINDOW(viewer->dialog_),
-                       viewer->cert_chain_list_[cert_index]);
-}
-
-void CertificateViewer::Show() {
-  gtk_util::ShowDialog(dialog_);
-}
-
-} // namespace
-
-void ShowCertificateViewer(gfx::NativeWindow parent,
-                           net::X509Certificate::OSCertHandle cert) {
-  net::X509Certificate::OSCertHandles cert_chain;
-  x509_certificate_model::GetCertChainFromCert(cert, &cert_chain);
-  (new CertificateViewer(parent, cert_chain))->Show();
-}
-
-void ShowCertificateViewer(gfx::NativeWindow parent,
-                           net::X509Certificate* cert) {
-  ShowCertificateViewer(parent, cert->os_cert_handle());
-}
diff --git a/chrome/browser/gtk/certificate_viewer.h b/chrome/browser/gtk/certificate_viewer.h
deleted file mode 100644
index 16ad370..0000000
--- a/chrome/browser/gtk/certificate_viewer.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CERTIFICATE_VIEWER_H_
-#define CHROME_BROWSER_GTK_CERTIFICATE_VIEWER_H_
-#pragma once
-
-#include "chrome/browser/certificate_viewer.h"
-#include "gfx/native_widget_types.h"
-#include "net/base/x509_certificate.h"
-
-void ShowCertificateViewer(gfx::NativeWindow parent,
-                           net::X509Certificate::OSCertHandle);
-
-#endif  // CHROME_BROWSER_GTK_CERTIFICATE_VIEWER_H_
diff --git a/chrome/browser/gtk/chrome_gtk_frame.cc b/chrome/browser/gtk/chrome_gtk_frame.cc
deleted file mode 100644
index 77f28d1..0000000
--- a/chrome/browser/gtk/chrome_gtk_frame.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/chrome_gtk_frame.h"
-
-G_BEGIN_DECLS
-
-// MetaFrames declaration
-G_DEFINE_TYPE(MetaFrames, meta_frames, GTK_TYPE_WINDOW)
-
-static void meta_frames_class_init(MetaFramesClass* frames_class) {
-  // Noop since we don't declare anything.
-}
-
-static void meta_frames_init(MetaFrames* button) {
-}
-
-
-// ChromeGtkFrame declaration
-G_DEFINE_TYPE(ChromeGtkFrame, chrome_gtk_frame, meta_frames_get_type())
-
-static void chrome_gtk_frame_class_init(ChromeGtkFrameClass* frame_class) {
-  GtkWidgetClass* widget_class = reinterpret_cast<GtkWidgetClass*>(frame_class);
-
-  // Frame tints:
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "frame-color",
-          "Frame Color",
-          "The color that the chrome frame will be. (If unspecified, "
-            " Chrome will take ChromeGtkFrame::bg[SELECTED] and slightly darken"
-            " it.)",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "inactive-frame-color",
-          "Inactive Frame Color",
-          "The color that the inactive chrome frame will be. (If"
-            " unspecified, Chrome will take ChromeGtkFrame::bg[INSENSITIVE]"
-            " and slightly darken it.)",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "incognito-frame-color",
-          "Incognito Frame Color",
-          "The color that the incognito frame will be. (If unspecified,"
-            " Chrome will take the frame color and tint it by Chrome's default"
-            " incognito tint.)",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "incognito-inactive-frame-color",
-          "Incognito Inactive Frame Color",
-          "The color that the inactive incognito frame will be. (If"
-            " unspecified, Chrome will take the frame color and tint it by"
-            " Chrome's default incognito tint.)",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-
-  // Frame gradient control:
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_int(
-          "frame-gradient-size",
-          "Chrome Frame Gradient Size",
-          "The size of the gradient on top of the frame image. Specify 0 to"
-            " make the frame a solid color.",
-          0,      // 0 disables the gradient
-          128,    // The frame image is only up to 128 pixels tall.
-          16,     // By default, gradients are 16 pixels high.
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "frame-gradient-color",
-          "Frame Gradient Color",
-          "The top color of the chrome frame gradient. (If unspecified,"
-            " chrome will create a lighter tint of frame-color",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "inactive-frame-gradient-color",
-          "Inactive Frame Gradient Color",
-          "The top color of the inactive chrome frame gradient. (If"
-            " unspecified, chrome will create a lighter tint of frame-color",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "incognito-frame-gradient-color",
-          "Incognito Frame Gradient Color",
-          "The top color of the incognito chrome frame gradient. (If"
-            " unspecified, chrome will create a lighter tint of frame-color",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "incognito-inactive-frame-gradient-color",
-          "Incognito Inactive Frame Gradient Color",
-          "The top color of the incognito inactive chrome frame gradient. (If"
-            " unspecified, chrome will create a lighter tint of frame-color",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-
-  // Scrollbar color properties:
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "scrollbar-slider-prelight-color",
-          "Scrollbar Slider Prelight Color",
-          "The color applied to the mouse is above the tab",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "scrollbar-slider-normal-color",
-          "Scrollbar Slider Normal Color",
-          "The color applied to the slider normally",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-  gtk_widget_class_install_style_property(
-      widget_class,
-      g_param_spec_boxed(
-          "scrollbar-trough-color",
-          "Scrollbar Trough Color",
-          "The background color of the slider track",
-          GDK_TYPE_COLOR,
-          G_PARAM_READABLE));
-}
-
-static void chrome_gtk_frame_init(ChromeGtkFrame* frame) {
-}
-
-GtkWidget* chrome_gtk_frame_new(void) {
-  GtkWindow* window =
-      GTK_WINDOW(g_object_new(chrome_gtk_frame_get_type(), NULL));
-  window->type = GTK_WINDOW_TOPLEVEL;
-  return GTK_WIDGET(window);
-}
-
-
-G_END_DECLS
diff --git a/chrome/browser/gtk/chrome_gtk_frame.h b/chrome/browser/gtk/chrome_gtk_frame.h
deleted file mode 100644
index 0fd7d28..0000000
--- a/chrome/browser/gtk/chrome_gtk_frame.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CHROME_GTK_FRAME_H_
-#define CHROME_BROWSER_GTK_CHROME_GTK_FRAME_H_
-#pragma once
-
-#include <gdk/gdk.h>
-#include <gtk/gtkwindow.h>
-
-G_BEGIN_DECLS
-
-// This file declares two subclasses of GtkWindow for easier gtk+ theme
-// integration.
-//
-// The first is "MetaFrames," which is (was?) the name of a gobject class in
-// the metacity window manager. To actually get at those values, we need to
-// have an object whose gobject class name string matches the definitions in
-// the gtkrc file. MetaFrames derives from GtkWindow.
-//
-// Metaframes can not be instantiated. It has no constructor; instantiate
-// ChromeGtkFrame instead.
-typedef struct _MetaFrames       MetaFrames;
-typedef struct _MetaFramesClass  MetaFramesClass;
-
-struct _MetaFrames {
-  GtkWindow window;
-};
-
-struct _MetaFramesClass {
-  GtkWindowClass parent_class;
-};
-
-
-// The second is ChromeGtkFrame, which defines a number of optional style
-// properties so theme authors can control how chromium appears in gtk-theme
-// mode.  It derives from MetaFrames in chrome so older themes that declare a
-// MetaFrames theme will still work. New themes should target this class.
-typedef struct _ChromeGtkFrame       ChromeGtkFrame;
-typedef struct _ChromeGtkFrameClass  ChromeGtkFrameClass;
-
-struct _ChromeGtkFrame {
-  MetaFrames frames;
-};
-
-struct _ChromeGtkFrameClass {
-  MetaFramesClass frames_class;
-};
-
-// Creates a GtkWindow object the the class name "ChromeGtkFrame".
-GtkWidget* chrome_gtk_frame_new();
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_CHROME_GTK_FRAME_H_
diff --git a/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc b/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc
deleted file mode 100644
index cae4b37..0000000
--- a/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "chrome/browser/browsing_data_remover.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Returns true if the checkbox is checked.
-gboolean IsChecked(GtkWidget* widget) {
-  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-}
-
-}  // namespace
-
-// static
-void ClearBrowsingDataDialogGtk::Show(GtkWindow* parent, Profile* profile) {
-  new ClearBrowsingDataDialogGtk(parent, profile);
-}
-
-ClearBrowsingDataDialogGtk::ClearBrowsingDataDialogGtk(GtkWindow* parent,
-                                                       Profile* profile) :
-    profile_(profile), remover_(NULL) {
-  // Build the dialog.
-  std::string dialog_name = l10n_util::GetStringUTF8(
-      IDS_CLEAR_BROWSING_DATA_TITLE);
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      parent,
-      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      NULL);
-
-  GtkWidget* cancel_button = gtk_dialog_add_button(GTK_DIALOG(dialog_),
-      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
-  gtk_widget_grab_focus(cancel_button);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(dialog_, profile));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(IDS_CLEAR_BROWSING_DATA_COMMIT).c_str(),
-      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
-
-  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(content_area), vbox);
-
-  // Label on top of the checkboxes.
-  GtkWidget* description = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_CLEAR_BROWSING_DATA_LABEL).c_str());
-  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);
-
-  // History checkbox.
-  del_history_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DEL_BROWSING_HISTORY_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), del_history_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_history_checkbox_),
-      profile_->GetPrefs()->GetBoolean(prefs::kDeleteBrowsingHistory));
-  g_signal_connect(del_history_checkbox_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Downloads checkbox.
-  del_downloads_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DEL_DOWNLOAD_HISTORY_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), del_downloads_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_downloads_checkbox_),
-      profile_->GetPrefs()->GetBoolean(prefs::kDeleteDownloadHistory));
-  g_signal_connect(del_downloads_checkbox_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Cache checkbox.
-  del_cache_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DEL_CACHE_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), del_cache_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_cache_checkbox_),
-      profile_->GetPrefs()->GetBoolean(prefs::kDeleteCache));
-  g_signal_connect(del_cache_checkbox_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Cookies checkbox.
-  del_cookies_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DEL_COOKIES_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), del_cookies_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_cookies_checkbox_),
-      profile_->GetPrefs()->GetBoolean(prefs::kDeleteCookies));
-  g_signal_connect(del_cookies_checkbox_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Passwords checkbox.
-  del_passwords_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DEL_PASSWORDS_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), del_passwords_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_passwords_checkbox_),
-      profile_->GetPrefs()->GetBoolean(prefs::kDeletePasswords));
-  g_signal_connect(del_passwords_checkbox_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Form data checkbox.
-  del_form_data_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DEL_FORM_DATA_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), del_form_data_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_form_data_checkbox_),
-      profile_->GetPrefs()->GetBoolean(prefs::kDeleteFormData));
-  g_signal_connect(del_form_data_checkbox_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Create a horizontal layout for the combo box and label.
-  GtkWidget* combo_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  GtkWidget* time_period_label_ = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_CLEAR_BROWSING_DATA_TIME_LABEL).c_str());
-  gtk_box_pack_start(GTK_BOX(combo_hbox), time_period_label_, FALSE, FALSE, 0);
-
-  // Time period combo box items.
-  time_period_combobox_ = gtk_combo_box_new_text();
-  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
-      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_HOUR).c_str());
-  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
-      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_DAY).c_str());
-  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
-      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_WEEK).c_str());
-  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
-      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_4WEEKS).c_str());
-  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
-      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_EVERYTHING).c_str());
-  gtk_combo_box_set_active(GTK_COMBO_BOX(time_period_combobox_),
-      profile_->GetPrefs()->GetInteger(prefs::kDeleteTimePeriod));
-  gtk_box_pack_start(GTK_BOX(combo_hbox),
-                     time_period_combobox_, FALSE, FALSE, 0);
-  g_signal_connect(time_period_combobox_, "changed",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  // Add the combo/label time period box to the vertical layout.
-  gtk_box_pack_start(GTK_BOX(vbox), combo_hbox, FALSE, FALSE, 0);
-
-  // Add widgets for the area below the accept buttons.
-  GtkWidget* flash_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_SETTINGS).c_str());
-  g_signal_connect(G_OBJECT(flash_link), "clicked",
-                   G_CALLBACK(OnFlashLinkClickedThunk), this);
-  GtkWidget* flash_link_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(flash_link_hbox), flash_link, FALSE, FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(content_area), flash_link_hbox, FALSE, FALSE, 0);
-
-  GtkWidget* separator = gtk_hseparator_new();
-  gtk_box_pack_end(GTK_BOX(content_area), separator, FALSE, FALSE, 0);
-
-  // Make sure we can move things around.
-  DCHECK_EQ(GTK_DIALOG(dialog_)->action_area->parent, content_area);
-
-  // Now rearrange those because they're *above* the accept buttons...there's
-  // no way to place them in the correct position with gtk_box_pack_end() so
-  // manually move things into the correct order.
-  gtk_box_reorder_child(GTK_BOX(content_area), flash_link_hbox, -1);
-  gtk_box_reorder_child(GTK_BOX(content_area), separator, -1);
-  gtk_box_reorder_child(GTK_BOX(content_area), GTK_DIALOG(dialog_)->action_area,
-                        -1);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-
-  UpdateDialogButtons();
-
-  gtk_util::ShowModalDialogWithMinLocalizedWidth(dialog_,
-      IDS_CLEARDATA_DIALOG_WIDTH_CHARS);
-}
-
-ClearBrowsingDataDialogGtk::~ClearBrowsingDataDialogGtk() {
-}
-
-void ClearBrowsingDataDialogGtk::OnDialogResponse(GtkWidget* widget,
-                                                  int response) {
-  if (response == GTK_RESPONSE_ACCEPT) {
-    PrefService* prefs = profile_->GetPrefs();
-    prefs->SetBoolean(prefs::kDeleteBrowsingHistory,
-                      IsChecked(del_history_checkbox_));
-    prefs->SetBoolean(prefs::kDeleteDownloadHistory,
-                      IsChecked(del_downloads_checkbox_));
-    prefs->SetBoolean(prefs::kDeleteCache,
-                      IsChecked(del_cache_checkbox_));
-    prefs->SetBoolean(prefs::kDeleteCookies,
-                      IsChecked(del_cookies_checkbox_));
-    prefs->SetBoolean(prefs::kDeletePasswords,
-                      IsChecked(del_passwords_checkbox_));
-    prefs->SetBoolean(prefs::kDeleteFormData,
-                      IsChecked(del_form_data_checkbox_));
-    prefs->SetInteger(prefs::kDeleteTimePeriod,
-        gtk_combo_box_get_active(GTK_COMBO_BOX(time_period_combobox_)));
-
-    int period_selected = gtk_combo_box_get_active(
-        GTK_COMBO_BOX(time_period_combobox_));
-
-    // BrowsingDataRemover deletes itself when done.
-    remover_ = new BrowsingDataRemover(profile_,
-        static_cast<BrowsingDataRemover::TimePeriod>(period_selected),
-        base::Time());
-    remover_->Remove(GetCheckedItems());
-  }
-
-  delete this;
-  gtk_widget_destroy(GTK_WIDGET(widget));
-}
-
-void ClearBrowsingDataDialogGtk::OnDialogWidgetClicked(GtkWidget* widget) {
-  UpdateDialogButtons();
-}
-
-void ClearBrowsingDataDialogGtk::OnFlashLinkClicked(GtkWidget* button) {
-  // We open a new browser window so the Options dialog doesn't get lost
-  // behind other windows.
-  Browser* browser = Browser::Create(profile_);
-  browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)),
-                   GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
-  browser->window()->Show();
-}
-
-void ClearBrowsingDataDialogGtk::UpdateDialogButtons() {
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT,
-                                    GetCheckedItems() != 0);
-}
-
-int ClearBrowsingDataDialogGtk::GetCheckedItems() {
-  int items = 0;
-  if (IsChecked(del_history_checkbox_))
-    items |= BrowsingDataRemover::REMOVE_HISTORY;
-  if (IsChecked(del_downloads_checkbox_))
-    items |= BrowsingDataRemover::REMOVE_DOWNLOADS;
-  if (IsChecked(del_cookies_checkbox_))
-    items |= BrowsingDataRemover::REMOVE_COOKIES;
-  if (IsChecked(del_passwords_checkbox_))
-    items |= BrowsingDataRemover::REMOVE_PASSWORDS;
-  if (IsChecked(del_form_data_checkbox_))
-    items |= BrowsingDataRemover::REMOVE_FORM_DATA;
-  if (IsChecked(del_cache_checkbox_))
-    items |= BrowsingDataRemover::REMOVE_CACHE;
-  return items;
-}
diff --git a/chrome/browser/gtk/clear_browsing_data_dialog_gtk.h b/chrome/browser/gtk/clear_browsing_data_dialog_gtk.h
deleted file mode 100644
index 87a4546..0000000
--- a/chrome/browser/gtk/clear_browsing_data_dialog_gtk.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CLEAR_BROWSING_DATA_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_CLEAR_BROWSING_DATA_DIALOG_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkWindow GtkWindow;
-
-class AccessibleWidgetHelper;
-class BrowsingDataRemover;
-class Profile;
-
-class ClearBrowsingDataDialogGtk {
- public:
-  // Displays the dialog box to clear browsing data from |profile|.
-  static void Show(GtkWindow* parent, Profile* profile);
-
- private:
-  ClearBrowsingDataDialogGtk(GtkWindow* parent, Profile* profile);
-  ~ClearBrowsingDataDialogGtk();
-
-  // Handler to respond to Ok and Cancel responses from the dialog.
-  CHROMEGTK_CALLBACK_1(ClearBrowsingDataDialogGtk, void, OnDialogResponse, int);
-
-  // Handler to respond to widget clicked actions from the dialog.
-  CHROMEGTK_CALLBACK_0(ClearBrowsingDataDialogGtk, void, OnDialogWidgetClicked);
-
-  CHROMEGTK_CALLBACK_0(ClearBrowsingDataDialogGtk, void, OnFlashLinkClicked);
-
-  // Enable or disable the dialog buttons depending on the state of the
-  // checkboxes.
-  void UpdateDialogButtons();
-
-  // Create a bitmask from the checkboxes of the dialog.
-  int GetCheckedItems();
-
-  // The dialog window.
-  GtkWidget* dialog_;
-
-  // UI elements.
-  GtkWidget* del_history_checkbox_;
-  GtkWidget* del_downloads_checkbox_;
-  GtkWidget* del_cache_checkbox_;
-  GtkWidget* del_cookies_checkbox_;
-  GtkWidget* del_passwords_checkbox_;
-  GtkWidget* del_form_data_checkbox_;
-  GtkWidget* time_period_combobox_;
-
-  // Our current profile.
-  Profile* profile_;
-
-  // If non-null it means removal is in progress. BrowsingDataRemover takes care
-  // of deleting itself when done.
-  BrowsingDataRemover* remover_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClearBrowsingDataDialogGtk);
-};
-
-
-#endif  // CHROME_BROWSER_GTK_CLEAR_BROWSING_DATA_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/collected_cookies_gtk.cc b/chrome/browser/gtk/collected_cookies_gtk.cc
deleted file mode 100644
index a64f19e..0000000
--- a/chrome/browser/gtk/collected_cookies_gtk.cc
+++ /dev/null
@@ -1,401 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/collected_cookies_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "chrome/browser/cookies_tree_model.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_source.h"
-#include "grit/generated_resources.h"
-
-namespace {
-// Width and height of the cookie tree view.
-const int kTreeViewWidth = 450;
-const int kTreeViewHeight = 150;
-
-// Padding within the banner box.
-const int kBannerPadding = 3;
-
-// Returns the text to display in the info bar when content settings were
-// created.
-const std::string GetInfobarLabel(ContentSetting setting,
-                                  bool multiple_domains_added,
-                                  const string16& domain_name) {
-  if (multiple_domains_added) {
-    switch (setting) {
-      case CONTENT_SETTING_BLOCK:
-        return l10n_util::GetStringUTF8(
-            IDS_COLLECTED_COOKIES_MULTIPLE_BLOCK_RULES_CREATED);
-
-      case CONTENT_SETTING_ALLOW:
-        return l10n_util::GetStringUTF8(
-            IDS_COLLECTED_COOKIES_MULTIPLE_ALLOW_RULES_CREATED);
-
-      case CONTENT_SETTING_SESSION_ONLY:
-        return l10n_util::GetStringUTF8(
-            IDS_COLLECTED_COOKIES_MULTIPLE_SESSION_RULES_CREATED);
-
-      default:
-        NOTREACHED();
-        return std::string();
-    }
-  }
-
-  switch (setting) {
-    case CONTENT_SETTING_BLOCK:
-      return l10n_util::GetStringFUTF8(
-          IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name);
-
-    case CONTENT_SETTING_ALLOW:
-      return l10n_util::GetStringFUTF8(
-          IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name);
-
-    case CONTENT_SETTING_SESSION_ONLY:
-      return l10n_util::GetStringFUTF8(
-          IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name);
-
-    default:
-      NOTREACHED();
-      return std::string();
-  }
-}
-}  // namespace
-
-CollectedCookiesGtk::CollectedCookiesGtk(GtkWindow* parent,
-                                         TabContents* tab_contents)
-    : tab_contents_(tab_contents) {
-  TabSpecificContentSettings* content_settings =
-      tab_contents->GetTabSpecificContentSettings();
-  registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN,
-                 Source<TabSpecificContentSettings>(content_settings));
-
-  Init();
-}
-
-void CollectedCookiesGtk::Init() {
-  HostContentSettingsMap* host_content_settings_map =
-      tab_contents_->profile()->GetHostContentSettingsMap();
-
-  dialog_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_box_set_spacing(GTK_BOX(dialog_), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_DIALOG_TITLE).c_str());
-  gtk_box_pack_start(GTK_BOX(dialog_), label, TRUE, TRUE, 0);
-
-  // Allowed Cookie list.
-  GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(dialog_), cookie_list_vbox, TRUE, TRUE, 0);
-
-  label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL).
-          c_str());
-  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), label, FALSE, FALSE, 0);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
-
-  TabSpecificContentSettings* content_settings =
-      tab_contents_->GetTabSpecificContentSettings();
-
-  allowed_cookies_tree_model_.reset(
-      content_settings->GetAllowedCookiesTreeModel());
-  allowed_cookies_tree_adapter_.reset(
-      new gtk_tree::TreeAdapter(this, allowed_cookies_tree_model_.get()));
-  allowed_tree_ = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(allowed_cookies_tree_adapter_->tree_store()));
-  gtk_widget_set_size_request(allowed_tree_, kTreeViewWidth, kTreeViewHeight);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(allowed_tree_), FALSE);
-  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(allowed_tree_), TRUE);
-  gtk_container_add(GTK_CONTAINER(scroll_window), allowed_tree_);
-
-  GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
-  GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
-  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
-                                     gtk_tree::TreeAdapter::COL_ICON);
-  GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
-  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
-                                     gtk_tree::TreeAdapter::COL_TITLE);
-  gtk_tree_view_column_set_title(
-      title_column, l10n_util::GetStringUTF8(
-          IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
-  gtk_tree_view_append_column(GTK_TREE_VIEW(allowed_tree_), title_column);
-  g_signal_connect(allowed_tree_, "row-expanded",
-                   G_CALLBACK(OnTreeViewRowExpandedThunk), this);
-  allowed_selection_ =
-      gtk_tree_view_get_selection(GTK_TREE_VIEW(allowed_tree_));
-  gtk_tree_selection_set_mode(allowed_selection_, GTK_SELECTION_MULTIPLE);
-  g_signal_connect(allowed_selection_, "changed",
-                   G_CALLBACK(OnTreeViewSelectionChangeThunk), this);
-
-  GtkWidget* button_box = gtk_hbutton_box_new();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START);
-  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(dialog_), button_box, FALSE, FALSE, 0);
-  block_allowed_cookie_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_BLOCK_BUTTON).c_str());
-  g_signal_connect(block_allowed_cookie_button_, "clicked",
-                   G_CALLBACK(OnBlockAllowedButtonClickedThunk), this);
-  gtk_container_add(GTK_CONTAINER(button_box), block_allowed_cookie_button_);
-
-  GtkWidget* separator = gtk_hseparator_new();
-  gtk_box_pack_start(GTK_BOX(dialog_), separator, TRUE, TRUE, 0);
-
-  // Blocked Cookie list.
-  cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(dialog_), cookie_list_vbox, TRUE, TRUE, 0);
-
-  label = gtk_label_new(
-      l10n_util::GetStringUTF8(
-          host_content_settings_map->BlockThirdPartyCookies() ?
-              IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED :
-              IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL).c_str());
-  gtk_widget_set_size_request(label, kTreeViewWidth, -1);
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), label, TRUE, TRUE, 0);
-
-  scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
-
-  blocked_cookies_tree_model_.reset(
-      content_settings->GetBlockedCookiesTreeModel());
-  blocked_cookies_tree_adapter_.reset(
-      new gtk_tree::TreeAdapter(this, blocked_cookies_tree_model_.get()));
-  blocked_tree_ = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(blocked_cookies_tree_adapter_->tree_store()));
-  gtk_widget_set_size_request(blocked_tree_, kTreeViewWidth, kTreeViewHeight);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(blocked_tree_), FALSE);
-  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(blocked_tree_), TRUE);
-  gtk_container_add(GTK_CONTAINER(scroll_window), blocked_tree_);
-
-  title_column = gtk_tree_view_column_new();
-  pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
-  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
-                                     gtk_tree::TreeAdapter::COL_ICON);
-  title_renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
-  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
-                                     gtk_tree::TreeAdapter::COL_TITLE);
-  gtk_tree_view_column_set_title(
-      title_column, l10n_util::GetStringUTF8(
-          IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
-  gtk_tree_view_append_column(GTK_TREE_VIEW(blocked_tree_), title_column);
-  g_signal_connect(blocked_tree_, "row-expanded",
-                   G_CALLBACK(OnTreeViewRowExpandedThunk), this);
-  blocked_selection_ =
-      gtk_tree_view_get_selection(GTK_TREE_VIEW(blocked_tree_));
-  gtk_tree_selection_set_mode(blocked_selection_, GTK_SELECTION_MULTIPLE);
-  g_signal_connect(blocked_selection_, "changed",
-                   G_CALLBACK(OnTreeViewSelectionChangeThunk), this);
-
-  button_box = gtk_hbutton_box_new();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START);
-  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(dialog_), button_box, FALSE, FALSE, 0);
-  allow_blocked_cookie_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOW_BUTTON).c_str());
-  g_signal_connect(allow_blocked_cookie_button_, "clicked",
-                   G_CALLBACK(OnAllowBlockedButtonClickedThunk), this);
-  gtk_container_add(GTK_CONTAINER(button_box), allow_blocked_cookie_button_);
-  for_session_blocked_cookie_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON).
-          c_str());
-  g_signal_connect(for_session_blocked_cookie_button_, "clicked",
-                   G_CALLBACK(OnForSessionBlockedButtonClickedThunk), this);
-  gtk_container_add(GTK_CONTAINER(button_box),
-                    for_session_blocked_cookie_button_);
-
-  // Infobar.
-  infobar_ = gtk_frame_new(NULL);
-  GtkWidget* infobar_contents = gtk_hbox_new(FALSE, kBannerPadding);
-  gtk_container_set_border_width(GTK_CONTAINER(infobar_contents),
-                                 kBannerPadding);
-  gtk_container_add(GTK_CONTAINER(infobar_), infobar_contents);
-  GtkWidget* info_image =
-      gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,
-                               GTK_ICON_SIZE_SMALL_TOOLBAR);
-  gtk_box_pack_start(GTK_BOX(infobar_contents), info_image, FALSE, FALSE, 0);
-  infobar_label_ = gtk_label_new(NULL);
-  gtk_box_pack_start(
-      GTK_BOX(infobar_contents), infobar_label_, FALSE, FALSE, 0);
-  gtk_widget_show_all(infobar_);
-  gtk_widget_set_no_show_all(infobar_, TRUE);
-  gtk_widget_hide(infobar_);
-  gtk_box_pack_start(GTK_BOX(dialog_), infobar_, TRUE, TRUE, 0);
-
-  // Close button.
-  button_box = gtk_hbutton_box_new();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
-  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
-  gtk_box_pack_end(GTK_BOX(dialog_), button_box, FALSE, TRUE, 0);
-  GtkWidget* close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
-  gtk_button_set_label(GTK_BUTTON(close),
-                       l10n_util::GetStringUTF8(IDS_CLOSE).c_str());
-  g_signal_connect(close, "clicked", G_CALLBACK(OnCloseThunk), this);
-  gtk_box_pack_end(GTK_BOX(button_box), close, FALSE, TRUE, 0);
-
-  // Show the dialog.
-  allowed_cookies_tree_adapter_->Init();
-  blocked_cookies_tree_adapter_->Init();
-  EnableControls();
-  window_ = tab_contents_->CreateConstrainedDialog(this);
-}
-
-CollectedCookiesGtk::~CollectedCookiesGtk() {
-  gtk_widget_destroy(dialog_);
-}
-
-GtkWidget* CollectedCookiesGtk::GetWidgetRoot() {
-  return dialog_;
-}
-
-void CollectedCookiesGtk::DeleteDelegate() {
-  delete this;
-}
-
-bool CollectedCookiesGtk::SelectionContainsOriginNode(
-    GtkTreeSelection* selection, gtk_tree::TreeAdapter* adapter) {
-  // Check whether at least one "origin" node is selected.
-  GtkTreeModel* model;
-  GList* paths =
-      gtk_tree_selection_get_selected_rows(selection, &model);
-  bool contains_origin_node = false;
-  for (GList* item = paths; item; item = item->next) {
-    GtkTreeIter iter;
-    gtk_tree_model_get_iter(
-        model, &iter, reinterpret_cast<GtkTreePath*>(item->data));
-    CookieTreeNode* node =
-        static_cast<CookieTreeNode*>(adapter->GetNode(&iter));
-    if (node->GetDetailedInfo().node_type !=
-        CookieTreeNode::DetailedInfo::TYPE_ORIGIN)
-      continue;
-    CookieTreeOriginNode* origin_node = static_cast<CookieTreeOriginNode*>(
-        node);
-    if (!origin_node->CanCreateContentException())
-      continue;
-    contains_origin_node = true;
-  }
-  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
-  g_list_free(paths);
-  return contains_origin_node;
-}
-
-void CollectedCookiesGtk::EnableControls() {
-  // Update button states.
-  bool enable_for_allowed_cookies =
-      SelectionContainsOriginNode(allowed_selection_,
-                                  allowed_cookies_tree_adapter_.get());
-  gtk_widget_set_sensitive(block_allowed_cookie_button_,
-                           enable_for_allowed_cookies);
-
-  bool enable_for_blocked_cookies =
-      SelectionContainsOriginNode(blocked_selection_,
-                                  blocked_cookies_tree_adapter_.get());
-  gtk_widget_set_sensitive(allow_blocked_cookie_button_,
-                           enable_for_blocked_cookies);
-  gtk_widget_set_sensitive(for_session_blocked_cookie_button_,
-                           enable_for_blocked_cookies);
-}
-
-void CollectedCookiesGtk::Observe(NotificationType type,
-                                  const NotificationSource& source,
-                                  const NotificationDetails& details) {
-  DCHECK(type == NotificationType::COLLECTED_COOKIES_SHOWN);
-  DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(),
-            tab_contents_->GetTabSpecificContentSettings());
-  window_->CloseConstrainedWindow();
-}
-
-void CollectedCookiesGtk::OnClose(GtkWidget* close_button) {
-  window_->CloseConstrainedWindow();
-}
-
-void CollectedCookiesGtk::AddExceptions(GtkTreeSelection* selection,
-                                        gtk_tree::TreeAdapter* adapter,
-                                        ContentSetting setting) {
-  GtkTreeModel* model;
-  GList* paths =
-      gtk_tree_selection_get_selected_rows(selection, &model);
-  string16 last_domain_name;
-  bool multiple_domains_added = false;
-  for (GList* item = paths; item; item = item->next) {
-    GtkTreeIter iter;
-    gtk_tree_model_get_iter(
-        model, &iter, reinterpret_cast<GtkTreePath*>(item->data));
-    CookieTreeNode* node =
-        static_cast<CookieTreeNode*>(adapter->GetNode(&iter));
-    if (node->GetDetailedInfo().node_type !=
-        CookieTreeNode::DetailedInfo::TYPE_ORIGIN)
-      continue;
-    CookieTreeOriginNode* origin_node = static_cast<CookieTreeOriginNode*>(
-        node);
-    if (origin_node->CanCreateContentException()) {
-      if (!last_domain_name.empty())
-        multiple_domains_added = true;
-      last_domain_name = origin_node->GetTitle();
-      origin_node->CreateContentException(
-          tab_contents_->profile()->GetHostContentSettingsMap(), setting);
-    }
-  }
-  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
-  g_list_free(paths);
-  if (last_domain_name.empty()) {
-    gtk_widget_hide(infobar_);
-  } else {
-    gtk_label_set_text(
-        GTK_LABEL(infobar_label_), GetInfobarLabel(
-            setting, multiple_domains_added, last_domain_name).c_str());
-    gtk_widget_show(infobar_);
-  }
-}
-
-void CollectedCookiesGtk::OnBlockAllowedButtonClicked(GtkWidget* button) {
-  AddExceptions(allowed_selection_, allowed_cookies_tree_adapter_.get(),
-                CONTENT_SETTING_BLOCK);
-}
-
-void CollectedCookiesGtk::OnAllowBlockedButtonClicked(GtkWidget* button) {
-  AddExceptions(blocked_selection_, blocked_cookies_tree_adapter_.get(),
-                CONTENT_SETTING_ALLOW);
-}
-
-void CollectedCookiesGtk::OnForSessionBlockedButtonClicked(GtkWidget* button) {
-  AddExceptions(blocked_selection_, blocked_cookies_tree_adapter_.get(),
-                CONTENT_SETTING_SESSION_ONLY);
-}
-
-void CollectedCookiesGtk::OnTreeViewRowExpanded(GtkWidget* tree_view,
-                                        GtkTreeIter* iter,
-                                        GtkTreePath* path) {
-  // When a row in the tree is expanded, expand all the children too.
-  g_signal_handlers_block_by_func(
-      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
-  gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
-  g_signal_handlers_unblock_by_func(
-      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
-}
-
-void CollectedCookiesGtk::OnTreeViewSelectionChange(GtkWidget* selection) {
-  EnableControls();
-}
diff --git a/chrome/browser/gtk/collected_cookies_gtk.h b/chrome/browser/gtk/collected_cookies_gtk.h
deleted file mode 100644
index f4348b2..0000000
--- a/chrome/browser/gtk/collected_cookies_gtk.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This is the Gtk implementation of the collected Cookies dialog.
-
-#ifndef CHROME_BROWSER_GTK_COLLECTED_COOKIES_GTK_H_
-#define CHROME_BROWSER_GTK_COLLECTED_COOKIES_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class CookiesTreeModel;
-
-// CollectedCookiesGtk is a dialog that displays the allowed and blocked
-// cookies of the current tab contents.  To display the dialog, invoke
-// ShowCollectedCookiesDialog() on the delegate of the tab contents.
-
-class CollectedCookiesGtk : public ConstrainedDialogDelegate,
-                                   gtk_tree::TreeAdapter::Delegate,
-                                   NotificationObserver {
- public:
-  CollectedCookiesGtk(GtkWindow* parent, TabContents* tab_contents);
-
-  // ConstrainedDialogDelegate methods.
-  virtual GtkWidget* GetWidgetRoot();
-  virtual void DeleteDelegate();
-
- private:
-  virtual ~CollectedCookiesGtk();
-
-  // Initialize all widgets of this dialog.
-  void Init();
-
-  // True if the selection contains at least one origin node.
-  bool SelectionContainsOriginNode(GtkTreeSelection* selection,
-                                   gtk_tree::TreeAdapter* adapter);
-
-  // Enable the allow/block buttons if at least one origin node is selected.
-  void EnableControls();
-
-  // Add exceptions for all origin nodes within the selection.
-  void AddExceptions(GtkTreeSelection* selection,
-                     gtk_tree::TreeAdapter* adapter,
-                     ContentSetting setting);
-
-  // Notification Observer implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Callbacks.
-  CHROMEGTK_CALLBACK_2(CollectedCookiesGtk, void, OnTreeViewRowExpanded,
-                       GtkTreeIter*, GtkTreePath*);
-  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnTreeViewSelectionChange);
-  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnClose);
-  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnBlockAllowedButtonClicked);
-  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnAllowBlockedButtonClicked);
-  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void,
-                       OnForSessionBlockedButtonClicked);
-
-  NotificationRegistrar registrar_;
-
-  ConstrainedWindow* window_;
-
-  // Widgets of the dialog.
-  GtkWidget* dialog_;
-
-  GtkWidget* allowed_description_label_;
-  GtkWidget* blocked_description_label_;
-
-  GtkWidget* block_allowed_cookie_button_;
-
-  GtkWidget* allow_blocked_cookie_button_;
-  GtkWidget* for_session_blocked_cookie_button_;
-
-  // The table listing the cookies.
-  GtkWidget* allowed_tree_;
-  GtkWidget* blocked_tree_;
-
-  GtkTreeSelection* allowed_selection_;
-  GtkTreeSelection* blocked_selection_;
-
-  // The infobar widget.
-  GtkWidget* infobar_;
-  GtkWidget* infobar_label_;
-
-  // The tab contents.
-  TabContents* tab_contents_;
-
-  // The Cookies Table model.
-  scoped_ptr<CookiesTreeModel> allowed_cookies_tree_model_;
-  scoped_ptr<CookiesTreeModel> blocked_cookies_tree_model_;
-  scoped_ptr<gtk_tree::TreeAdapter> allowed_cookies_tree_adapter_;
-  scoped_ptr<gtk_tree::TreeAdapter> blocked_cookies_tree_adapter_;
-
-  DISALLOW_COPY_AND_ASSIGN(CollectedCookiesGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_COLLECTED_COOKIES_GTK_H_
diff --git a/chrome/browser/gtk/constrained_html_delegate_gtk.cc b/chrome/browser/gtk/constrained_html_delegate_gtk.cc
deleted file mode 100644
index d55393f..0000000
--- a/chrome/browser/gtk/constrained_html_delegate_gtk.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/dom_ui/constrained_html_ui.h"
-
-#include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
-#include "chrome/browser/dom_ui/html_dialog_ui.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/tab_contents_container_gtk.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_source.h"
-#include "gfx/rect.h"
-#include "ipc/ipc_message.h"
-
-class ConstrainedHtmlDelegateGtk : public ConstrainedWindowGtkDelegate,
-                                   public HtmlDialogTabContentsDelegate,
-                                   public ConstrainedHtmlUIDelegate {
- public:
-  ConstrainedHtmlDelegateGtk(Profile* profile,
-                           HtmlDialogUIDelegate* delegate);
-
-  virtual ~ConstrainedHtmlDelegateGtk();
-
-  // ConstrainedWindowGtkDelegate ----------------------------------------------
-  virtual GtkWidget* GetWidgetRoot() {
-    return tab_contents_container_.widget();
-  }
-  virtual void DeleteDelegate() {
-    html_delegate_->OnDialogClosed("");
-    delete this;
-  }
-
-  // ConstrainedHtmlDelegate ---------------------------------------------
-  virtual HtmlDialogUIDelegate* GetHtmlDialogUIDelegate();
-  virtual void OnDialogClose();
-  virtual bool GetBackgroundColor(GdkColor* color) {
-    *color = gtk_util::kGdkWhite;
-    return true;
-  }
-
-  // HtmlDialogTabContentsDelegate ---------------------------------------------
-  void MoveContents(TabContents* source, const gfx::Rect& pos) {}
-  void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
-  void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {}
-
-  void set_window(ConstrainedWindow* window) {
-    window_ = window;
-  }
-
- private:
-  TabContents tab_contents_;
-  TabContentsContainerGtk tab_contents_container_;
-  HtmlDialogUIDelegate* html_delegate_;
-
-  // The constrained window that owns |this|. It's saved here because it needs
-  // to be closed in response to the DOMUI OnDialogClose callback.
-  ConstrainedWindow* window_;
-};
-
-ConstrainedHtmlDelegateGtk::ConstrainedHtmlDelegateGtk(
-    Profile* profile,
-    HtmlDialogUIDelegate* delegate)
-    : HtmlDialogTabContentsDelegate(profile),
-      tab_contents_(profile, NULL, MSG_ROUTING_NONE, NULL, NULL),
-      tab_contents_container_(NULL),
-      html_delegate_(delegate),
-      window_(NULL) {
-  tab_contents_.set_delegate(this);
-
-  // Set |this| as a property on the tab contents so that the ConstrainedHtmlUI
-  // can get a reference to |this|.
-  ConstrainedHtmlUI::GetPropertyAccessor().SetProperty(
-      tab_contents_.property_bag(), this);
-
-  tab_contents_.controller().LoadURL(delegate->GetDialogContentURL(),
-                                     GURL(), PageTransition::START_PAGE);
-  tab_contents_container_.SetTabContents(&tab_contents_);
-
-  gfx::Size dialog_size;
-  delegate->GetDialogSize(&dialog_size);
-  gtk_widget_set_size_request(GTK_WIDGET(tab_contents_container_.widget()),
-                              dialog_size.width(),
-                              dialog_size.height());
-
-  gtk_widget_show_all(GetWidgetRoot());
-}
-
-ConstrainedHtmlDelegateGtk::~ConstrainedHtmlDelegateGtk() {
-}
-
-HtmlDialogUIDelegate*
-    ConstrainedHtmlDelegateGtk::GetHtmlDialogUIDelegate() {
-  return html_delegate_;
-}
-
-void ConstrainedHtmlDelegateGtk::OnDialogClose() {
-  window_->CloseConstrainedWindow();
-}
-
-// static
-void ConstrainedHtmlUI::CreateConstrainedHtmlDialog(
-    Profile* profile,
-    HtmlDialogUIDelegate* delegate,
-    TabContents* overshadowed) {
-  ConstrainedHtmlDelegateGtk* constrained_delegate =
-      new ConstrainedHtmlDelegateGtk(profile, delegate);
-  ConstrainedWindow* constrained_window =
-      overshadowed->CreateConstrainedDialog(constrained_delegate);
-  constrained_delegate->set_window(constrained_window);
-}
diff --git a/chrome/browser/gtk/constrained_window_gtk.cc b/chrome/browser/gtk/constrained_window_gtk.cc
deleted file mode 100644
index 195fb17..0000000
--- a/chrome/browser/gtk/constrained_window_gtk.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-
-#if defined(TOUCH_UI)
-#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"
-#else
-#include "chrome/browser/tab_contents/tab_contents_view_gtk.h"
-#endif
-
-ConstrainedWindowGtkDelegate::~ConstrainedWindowGtkDelegate() {
-}
-
-bool ConstrainedWindowGtkDelegate::GetBackgroundColor(GdkColor* color) {
-  return false;
-}
-
-ConstrainedWindowGtk::ConstrainedWindowGtk(
-    TabContents* owner, ConstrainedWindowGtkDelegate* delegate)
-    : owner_(owner),
-      delegate_(delegate),
-      visible_(false),
-      factory_(this) {
-  DCHECK(owner);
-  DCHECK(delegate);
-  GtkWidget* dialog = delegate->GetWidgetRoot();
-
-  // Unlike other users of CreateBorderBin, we need a dedicated frame around
-  // our "window".
-  GtkWidget* ebox = gtk_event_box_new();
-  GtkWidget* frame = gtk_frame_new(NULL);
-  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
-
-  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
-      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder,
-      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
-  GdkColor background;
-  if (delegate->GetBackgroundColor(&background)) {
-    gtk_widget_modify_base(ebox, GTK_STATE_NORMAL, &background);
-    gtk_widget_modify_fg(ebox, GTK_STATE_NORMAL, &background);
-    gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &background);
-  }
-
-  if (gtk_widget_get_parent(dialog))
-    gtk_widget_reparent(dialog, alignment);
-  else
-    gtk_container_add(GTK_CONTAINER(alignment), dialog);
-
-  gtk_container_add(GTK_CONTAINER(frame), alignment);
-  gtk_container_add(GTK_CONTAINER(ebox), frame);
-  border_.Own(ebox);
-
-  gtk_widget_add_events(widget(), GDK_KEY_PRESS_MASK);
-  g_signal_connect(widget(), "key-press-event", G_CALLBACK(OnKeyPressThunk),
-                   this);
-}
-
-ConstrainedWindowGtk::~ConstrainedWindowGtk() {
-  border_.Destroy();
-}
-
-void ConstrainedWindowGtk::ShowConstrainedWindow() {
-  gtk_widget_show_all(border_.get());
-
-  // We collaborate with TabContentsView and stick ourselves in the
-  // TabContentsView's floating container.
-  ContainingView()->AttachConstrainedWindow(this);
-
-  visible_ = true;
-}
-
-void ConstrainedWindowGtk::CloseConstrainedWindow() {
-  if (visible_)
-    ContainingView()->RemoveConstrainedWindow(this);
-  delegate_->DeleteDelegate();
-  owner_->WillClose(this);
-
-  delete this;
-}
-
-ConstrainedWindowGtk::TabContentsViewType*
-    ConstrainedWindowGtk::ContainingView() {
-  return static_cast<TabContentsViewType*>(owner_->view());
-}
-
-gboolean ConstrainedWindowGtk::OnKeyPress(GtkWidget* sender,
-                                          GdkEventKey* key) {
-  if (key->keyval == GDK_Escape) {
-    // Let the stack unwind so the event handler can release its ref
-    // on widget().
-    MessageLoop::current()->PostTask(FROM_HERE,
-        factory_.NewRunnableMethod(
-            &ConstrainedWindowGtk::CloseConstrainedWindow));
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-// static
-ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
-    TabContents* parent,
-    ConstrainedWindowGtkDelegate* delegate) {
-  return new ConstrainedWindowGtk(parent, delegate);
-}
diff --git a/chrome/browser/gtk/constrained_window_gtk.h b/chrome/browser/gtk/constrained_window_gtk.h
deleted file mode 100644
index 0f57f65..0000000
--- a/chrome/browser/gtk/constrained_window_gtk.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CONSTRAINED_WINDOW_GTK_H_
-#define CHROME_BROWSER_GTK_CONSTRAINED_WINDOW_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/task.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/tab_contents/constrained_window.h"
-
-class TabContents;
-typedef struct _GdkColor GdkColor;
-#if defined(TOUCH_UI)
-class TabContentsViewViews;
-#else
-class TabContentsViewGtk;
-#endif
-
-class ConstrainedWindowGtkDelegate {
- public:
-  // Returns the widget that will be put in the constrained window's container.
-  virtual GtkWidget* GetWidgetRoot() = 0;
-
-  // Tells the delegate to either delete itself or set up a task to delete
-  // itself later.
-  virtual void DeleteDelegate() = 0;
-
-  virtual bool GetBackgroundColor(GdkColor* color);
-
- protected:
-  virtual ~ConstrainedWindowGtkDelegate();
-};
-
-// Constrained window implementation for the GTK port. Unlike the Win32 system,
-// ConstrainedWindowGtk doesn't draw draggable fake windows and instead just
-// centers the dialog. It is thus an order of magnitude simpler.
-class ConstrainedWindowGtk : public ConstrainedWindow {
- public:
-#if defined(TOUCH_UI)
-   typedef TabContentsViewViews TabContentsViewType;
-#else
-   typedef TabContentsViewGtk TabContentsViewType;
-#endif
-
-  virtual ~ConstrainedWindowGtk();
-
-  // Overridden from ConstrainedWindow:
-  virtual void ShowConstrainedWindow();
-  virtual void CloseConstrainedWindow();
-
-  // Returns the TabContents that constrains this Constrained Window.
-  TabContents* owner() const { return owner_; }
-
-  // Returns the toplevel widget that displays this "window".
-  GtkWidget* widget() { return border_.get(); }
-
-  // Returns the View that we collaborate with to position ourselves.
-  TabContentsViewType* ContainingView();
-
- private:
-  friend class ConstrainedWindow;
-
-  ConstrainedWindowGtk(TabContents* owner,
-                       ConstrainedWindowGtkDelegate* delegate);
-
-  // Handler for Escape.
-  CHROMEGTK_CALLBACK_1(ConstrainedWindowGtk, gboolean, OnKeyPress,
-                       GdkEventKey*);
-
-  // The TabContents that owns and constrains this ConstrainedWindow.
-  TabContents* owner_;
-
-  // The top level widget container that exports to our TabContentsView.
-  OwnedWidgetGtk border_;
-
-  // Delegate that provides the contents of this constrained window.
-  ConstrainedWindowGtkDelegate* delegate_;
-
-  // Stores if |ShowConstrainedWindow()| has been called.
-  bool visible_;
-
-  ScopedRunnableMethodFactory<ConstrainedWindowGtk> factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_CONSTRAINED_WINDOW_GTK_H_
diff --git a/chrome/browser/gtk/content_setting_bubble_gtk.cc b/chrome/browser/gtk/content_setting_bubble_gtk.cc
deleted file mode 100644
index f8c36f0..0000000
--- a/chrome/browser/gtk/content_setting_bubble_gtk.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/content_setting_bubble_gtk.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/text_elider.h"
-#include "base/i18n/rtl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/blocked_content_container.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/content_setting_bubble_model.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "webkit/plugins/npapi/plugin_list.h"
-
-namespace {
-
-// Padding between content and edge of info bubble.
-const int kContentBorder = 7;
-
-// The maximum width of a title entry in the content box. We elide anything
-// longer than this.
-const int kMaxLinkPixelSize = 500;
-
-std::string BuildElidedText(const std::string& input) {
-  return UTF16ToUTF8(gfx::ElideText(
-      UTF8ToUTF16(input),
-      gfx::Font(),
-      kMaxLinkPixelSize,
-      false));
-}
-
-}  // namespace
-
-ContentSettingBubbleGtk::ContentSettingBubbleGtk(
-    GtkWidget* anchor,
-    InfoBubbleGtkDelegate* delegate,
-    ContentSettingBubbleModel* content_setting_bubble_model,
-    Profile* profile,
-    TabContents* tab_contents)
-    : anchor_(anchor),
-      profile_(profile),
-      tab_contents_(tab_contents),
-      delegate_(delegate),
-      content_setting_bubble_model_(content_setting_bubble_model),
-      info_bubble_(NULL) {
-  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
-                 Source<TabContents>(tab_contents));
-  BuildBubble();
-}
-
-ContentSettingBubbleGtk::~ContentSettingBubbleGtk() {
-}
-
-void ContentSettingBubbleGtk::Close() {
-  if (info_bubble_)
-    info_bubble_->Close();
-}
-
-void ContentSettingBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                                bool closed_by_escape) {
-  delegate_->InfoBubbleClosing(info_bubble, closed_by_escape);
-  delete this;
-}
-
-void ContentSettingBubbleGtk::Observe(NotificationType type,
-                                      const NotificationSource& source,
-                                      const NotificationDetails& details) {
-  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
-  DCHECK(source == Source<TabContents>(tab_contents_));
-  tab_contents_ = NULL;
-}
-
-void ContentSettingBubbleGtk::BuildBubble() {
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(profile_);
-
-  GtkWidget* bubble_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder);
-
-  const ContentSettingBubbleModel::BubbleContent& content =
-      content_setting_bubble_model_->bubble_content();
-  if (!content.title.empty()) {
-    // Add the content label.
-    GtkWidget* label = gtk_label_new(content.title.c_str());
-    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(bubble_content), label, FALSE, FALSE, 0);
-  }
-
-  const std::set<std::string>& plugins = content.resource_identifiers;
-  if (!plugins.empty()) {
-    GtkWidget* list_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-    for (std::set<std::string>::const_iterator it = plugins.begin();
-        it != plugins.end(); ++it) {
-      std::string name = UTF16ToUTF8(
-          webkit::npapi::PluginList::Singleton()->GetPluginGroupName(*it));
-      if (name.empty())
-        name = *it;
-
-      GtkWidget* label = gtk_label_new(BuildElidedText(name).c_str());
-      GtkWidget* label_box = gtk_hbox_new(FALSE, 0);
-      gtk_box_pack_start(GTK_BOX(label_box), label, FALSE, FALSE, 0);
-
-      gtk_box_pack_start(GTK_BOX(list_content),
-                         label_box,
-                         FALSE, FALSE, 0);
-    }
-    gtk_box_pack_start(GTK_BOX(bubble_content), list_content, FALSE, FALSE,
-                       gtk_util::kControlSpacing);
-  }
-
-  if (content_setting_bubble_model_->content_type() ==
-      CONTENT_SETTINGS_TYPE_POPUPS) {
-    const std::vector<ContentSettingBubbleModel::PopupItem>& popup_items =
-        content.popup_items;
-    GtkWidget* table = gtk_table_new(popup_items.size(), 2, FALSE);
-    int row = 0;
-    for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
-         i(popup_items.begin()); i != popup_items.end(); ++i, ++row) {
-      GtkWidget* image = gtk_image_new();
-      if (!i->bitmap.empty()) {
-        GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&i->bitmap);
-        gtk_image_set_from_pixbuf(GTK_IMAGE(image), icon_pixbuf);
-        g_object_unref(icon_pixbuf);
-
-        // We stuff the image in an event box so we can trap mouse clicks on the
-        // image (and launch the popup).
-        GtkWidget* event_box = gtk_event_box_new();
-        gtk_container_add(GTK_CONTAINER(event_box), image);
-
-        popup_icons_[event_box] = i -popup_items.begin();
-        g_signal_connect(event_box, "button_press_event",
-                         G_CALLBACK(OnPopupIconButtonPressThunk), this);
-        gtk_table_attach(GTK_TABLE(table), event_box, 0, 1, row, row + 1,
-                         GTK_FILL, GTK_FILL, gtk_util::kControlSpacing / 2,
-                         gtk_util::kControlSpacing / 2);
-      }
-
-      GtkWidget* button = gtk_chrome_link_button_new(
-          BuildElidedText(i->title).c_str());
-      popup_links_[button] = i -popup_items.begin();
-      g_signal_connect(button, "clicked", G_CALLBACK(OnPopupLinkClickedThunk),
-                       this);
-      gtk_table_attach(GTK_TABLE(table), button, 1, 2, row, row + 1,
-                       GTK_FILL, GTK_FILL, gtk_util::kControlSpacing / 2,
-                       gtk_util::kControlSpacing / 2);
-    }
-
-    gtk_box_pack_start(GTK_BOX(bubble_content), table, FALSE, FALSE, 0);
-  }
-
-  if (content_setting_bubble_model_->content_type() !=
-      CONTENT_SETTINGS_TYPE_COOKIES) {
-    const ContentSettingBubbleModel::RadioGroup& radio_group =
-        content.radio_group;
-    for (ContentSettingBubbleModel::RadioItems::const_iterator i =
-         radio_group.radio_items.begin();
-         i != radio_group.radio_items.end(); ++i) {
-      std::string elided = BuildElidedText(*i);
-      GtkWidget* radio =
-          radio_group_gtk_.empty() ?
-              gtk_radio_button_new_with_label(NULL, elided.c_str()) :
-              gtk_radio_button_new_with_label_from_widget(
-                  GTK_RADIO_BUTTON(radio_group_gtk_[0]),
-                  elided.c_str());
-      gtk_box_pack_start(GTK_BOX(bubble_content), radio, FALSE, FALSE, 0);
-      if (i - radio_group.radio_items.begin() == radio_group.default_item) {
-        // We must set the default value before we attach the signal handlers
-        // or pain occurs.
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
-      }
-      radio_group_gtk_.push_back(radio);
-    }
-    for (std::vector<GtkWidget*>::const_iterator i = radio_group_gtk_.begin();
-         i != radio_group_gtk_.end(); ++i) {
-      // We can attach signal handlers now that all defaults are set.
-      g_signal_connect(*i, "toggled", G_CALLBACK(OnRadioToggledThunk), this);
-    }
-  }
-
-  for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i =
-       content.domain_lists.begin();
-       i != content.domain_lists.end(); ++i) {
-    // Put each list into its own vbox to allow spacing between lists.
-    GtkWidget* list_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-    GtkWidget* label = gtk_label_new(BuildElidedText(i->title).c_str());
-    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-    GtkWidget* label_box = gtk_hbox_new(FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(label_box), label, FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(list_content), label_box, FALSE, FALSE, 0);
-    for (std::set<std::string>::const_iterator j = i->hosts.begin();
-         j != i->hosts.end(); ++j) {
-      gtk_box_pack_start(GTK_BOX(list_content),
-                         gtk_util::IndentWidget(gtk_util::CreateBoldLabel(*j)),
-                         FALSE, FALSE, 0);
-    }
-    gtk_box_pack_start(GTK_BOX(bubble_content), list_content, FALSE, FALSE,
-                       gtk_util::kControlSpacing);
-  }
-
-  if (!content.custom_link.empty()) {
-    GtkWidget* custom_link_box = gtk_hbox_new(FALSE, 0);
-    GtkWidget* custom_link = NULL;
-    if (content.custom_link_enabled) {
-      custom_link = gtk_chrome_link_button_new(content.custom_link.c_str());
-      g_signal_connect(custom_link, "clicked",
-                       G_CALLBACK(OnCustomLinkClickedThunk), this);
-    } else {
-      custom_link = gtk_label_new(content.custom_link.c_str());
-      gtk_misc_set_alignment(GTK_MISC(custom_link), 0, 0.5);
-    }
-    DCHECK(custom_link);
-    gtk_box_pack_start(GTK_BOX(custom_link_box), custom_link, FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(bubble_content), custom_link_box,
-                       FALSE, FALSE, 0);
-  }
-
-  gtk_box_pack_start(GTK_BOX(bubble_content), gtk_hseparator_new(),
-                     FALSE, FALSE, 0);
-
-  GtkWidget* bottom_box = gtk_hbox_new(FALSE, 0);
-
-  GtkWidget* manage_link =
-      gtk_chrome_link_button_new(content.manage_link.c_str());
-  g_signal_connect(manage_link, "clicked", G_CALLBACK(OnManageLinkClickedThunk),
-                   this);
-  gtk_box_pack_start(GTK_BOX(bottom_box), manage_link, FALSE, FALSE, 0);
-
-  GtkWidget* button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_DONE).c_str());
-  g_signal_connect(button, "clicked", G_CALLBACK(OnCloseButtonClickedThunk),
-                   this);
-  gtk_box_pack_end(GTK_BOX(bottom_box), button, FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(bubble_content), bottom_box, FALSE, FALSE, 0);
-  gtk_widget_grab_focus(bottom_box);
-  gtk_widget_grab_focus(button);
-
-  InfoBubbleGtk::ArrowLocationGtk arrow_location =
-      !base::i18n::IsRTL() ?
-      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
-      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
-  info_bubble_ = InfoBubbleGtk::Show(
-      anchor_,
-      NULL,
-      bubble_content,
-      arrow_location,
-      true,  // match_system_theme
-      true,  // grab_input
-      theme_provider,
-      this);
-}
-
-void ContentSettingBubbleGtk::OnPopupIconButtonPress(
-    GtkWidget* icon_event_box,
-    GdkEventButton* event) {
-  PopupMap::iterator i(popup_icons_.find(icon_event_box));
-  DCHECK(i != popup_icons_.end());
-  content_setting_bubble_model_->OnPopupClicked(i->second);
-  // The views interface implicitly closes because of the launching of a new
-  // window; we need to do that explicitly.
-  Close();
-}
-
-void ContentSettingBubbleGtk::OnPopupLinkClicked(GtkWidget* button) {
-  PopupMap::iterator i(popup_links_.find(button));
-  DCHECK(i != popup_links_.end());
-  content_setting_bubble_model_->OnPopupClicked(i->second);
-  // The views interface implicitly closes because of the launching of a new
-  // window; we need to do that explicitly.
-  Close();
-}
-
-void ContentSettingBubbleGtk::OnRadioToggled(GtkWidget* widget) {
-  for (ContentSettingBubbleGtk::RadioGroupGtk::const_iterator i =
-       radio_group_gtk_.begin();
-       i != radio_group_gtk_.end(); ++i) {
-    if (widget == *i) {
-      content_setting_bubble_model_->OnRadioClicked(
-          i - radio_group_gtk_.begin());
-      return;
-    }
-  }
-  NOTREACHED() << "unknown radio toggled";
-}
-
-void ContentSettingBubbleGtk::OnCloseButtonClicked(GtkWidget *button) {
-  Close();
-}
-
-void ContentSettingBubbleGtk::OnCustomLinkClicked(GtkWidget* button) {
-  content_setting_bubble_model_->OnCustomLinkClicked();
-  Close();
-}
-
-void ContentSettingBubbleGtk::OnManageLinkClicked(GtkWidget* button) {
-  content_setting_bubble_model_->OnManageLinkClicked();
-  Close();
-}
diff --git a/chrome/browser/gtk/content_setting_bubble_gtk.h b/chrome/browser/gtk/content_setting_bubble_gtk.h
deleted file mode 100644
index f003ab6..0000000
--- a/chrome/browser/gtk/content_setting_bubble_gtk.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CONTENT_SETTING_BUBBLE_GTK_H_
-#define CHROME_BROWSER_GTK_CONTENT_SETTING_BUBBLE_GTK_H_
-#pragma once
-
-#include <map>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/common/content_settings_types.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class ContentSettingBubbleModel;
-class Profile;
-class TabContents;
-
-// ContentSettingBubbleGtk is used when the user turns on different kinds of
-// content blocking (e.g. "block images"). An icon appears in the location bar,
-// and when clicked, an instance of this class is created specialized for the
-// type of content being blocked.
-class ContentSettingBubbleGtk : public InfoBubbleGtkDelegate,
-                                public NotificationObserver {
- public:
-   ContentSettingBubbleGtk(
-       GtkWidget* anchor,
-       InfoBubbleGtkDelegate* delegate,
-       ContentSettingBubbleModel* content_setting_bubble_model,
-       Profile* profile, TabContents* tab_contents);
-  virtual ~ContentSettingBubbleGtk();
-
-  // Dismisses the infobubble.
-  void Close();
-
- private:
-  typedef std::map<GtkWidget*, int> PopupMap;
-
-  // InfoBubbleGtkDelegate:
-  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                 bool closed_by_escape);
-
-  // NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Builds the info bubble and all the widgets that it displays.
-  void BuildBubble();
-
-  // Widget callback methods.
-  CHROMEGTK_CALLBACK_1(ContentSettingBubbleGtk, void, OnPopupIconButtonPress,
-                       GdkEventButton*);
-  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnPopupLinkClicked);
-  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnRadioToggled);
-  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnCustomLinkClicked);
-  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnManageLinkClicked);
-  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnCloseButtonClicked);
-
-  // We position the bubble near this widget.
-  GtkWidget* anchor_;
-
-  // The active profile.
-  Profile* profile_;
-
-  // The active tab contents.
-  TabContents* tab_contents_;
-
-  // A registrar for listening for TAB_CONTENTS_DESTROYED notifications.
-  NotificationRegistrar registrar_;
-
-  // Pass on delegate messages to this.
-  InfoBubbleGtkDelegate* delegate_;
-
-  // Provides data for this bubble.
-  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model_;
-
-  // The info bubble.
-  InfoBubbleGtk* info_bubble_;
-
-  // Stored controls so we can figure out what was clicked.
-  PopupMap popup_links_;
-  PopupMap popup_icons_;
-
-  typedef std::vector<GtkWidget*> RadioGroupGtk;
-  RadioGroupGtk radio_group_gtk_;
-};
-
-#endif  // CHROME_BROWSER_GTK_CONTENT_SETTING_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc
deleted file mode 100644
index 2d6b44e..0000000
--- a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/environment.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/shell_integration.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "chrome/browser/web_applications/web_app.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_resource.h"
-#include "gfx/gtk_util.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Size (in pixels) of the icon preview.
-const int kIconPreviewSizePixels = 32;
-
-// Height (in lines) of the shortcut description label.
-const int kDescriptionLabelHeightLines = 3;
-
-}  // namespace
-
-// static
-void CreateWebApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
-                                                  TabContents* tab_contents) {
-  new CreateWebApplicationShortcutsDialogGtk(parent, tab_contents);
-}
-
-void CreateChromeApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
-                                                     const Extension* app) {
-  new CreateChromeApplicationShortcutsDialogGtk(parent, app);
-}
-
-
-CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk(
-    GtkWindow* parent)
-  : parent_(parent),
-    error_dialog_(NULL) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  // Will be balanced by Release later.
-  AddRef();
-}
-
-void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf(
-    const SkBitmap& bitmap) {
-  // Prepare the icon. Try to scale it if it's too small, otherwise it would
-  // look weird.
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&shortcut_info_.favicon);
-  int pixbuf_width = gdk_pixbuf_get_width(pixbuf);
-  int pixbuf_height = gdk_pixbuf_get_height(pixbuf);
-  if (pixbuf_width == pixbuf_height && pixbuf_width < kIconPreviewSizePixels) {
-    // Only scale the pixbuf if it's a square (for simplicity).
-    // Generally it should be square, if it's a favicon or app icon.
-    // Use the highest quality interpolation. The scaling is
-    // going to have low quality anyway, because the initial image
-    // is likely small.
-    favicon_pixbuf_ = gdk_pixbuf_scale_simple(pixbuf,
-                                              kIconPreviewSizePixels,
-                                              kIconPreviewSizePixels,
-                                              GDK_INTERP_HYPER);
-    g_object_unref(pixbuf);
-  } else {
-    favicon_pixbuf_ = pixbuf;
-  }
-}
-
-void CreateApplicationShortcutsDialogGtk::CreateDialogBox(GtkWindow* parent) {
-  // Build the dialog.
-  create_dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_TITLE).c_str(),
-      parent,
-      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_REJECT,
-      NULL);
-  gtk_widget_realize(create_dialog_);
-  gtk_window_set_resizable(GTK_WINDOW(create_dialog_), false);
-  gtk_util::AddButtonToDialog(create_dialog_,
-      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_COMMIT).c_str(),
-      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
-
-  GtkWidget* content_area = GTK_DIALOG(create_dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(content_area), vbox);
-
-  // Create a box containing basic information about the new shortcut: an image
-  // on the left, and a description on the right.
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(hbox),
-                                 gtk_util::kControlSpacing);
-
-  // Put the icon preview in place.
-  GtkWidget* favicon_image = gtk_image_new_from_pixbuf(favicon_pixbuf_);
-  gtk_box_pack_start(GTK_BOX(hbox), favicon_image, FALSE, FALSE, 0);
-
-  // Create the label with application shortcut description.
-  GtkWidget* description_label = gtk_label_new(NULL);
-  gtk_box_pack_start(GTK_BOX(hbox), description_label, FALSE, FALSE, 0);
-  gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
-  gtk_widget_realize(description_label);
-
-  // Set the size request on the label so it knows where to line wrap. The width
-  // is the desired size of the dialog less the space reserved for padding and
-  // the image.
-  int label_width, label_height;
-  gtk_util::GetWidgetSizeFromResources(
-      description_label,
-      IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS, -1, &label_width, NULL);
-  label_width -= gtk_util::kControlSpacing * 3 +
-      gdk_pixbuf_get_width(favicon_pixbuf_);
-  gtk_util::GetWidgetSizeFromCharacters(
-      description_label, -1, kDescriptionLabelHeightLines, NULL, &label_height);
-  gtk_widget_set_size_request(description_label, label_width, label_height);
-  gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5);
-  std::string description(UTF16ToUTF8(shortcut_info_.description));
-  std::string title(UTF16ToUTF8(shortcut_info_.title));
-  gtk_label_set_text(GTK_LABEL(description_label),
-                     (description.empty() ? title : description).c_str());
-
-  // Label on top of the checkboxes.
-  GtkWidget* checkboxes_label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_LABEL).c_str());
-  gtk_misc_set_alignment(GTK_MISC(checkboxes_label), 0, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), checkboxes_label, FALSE, FALSE, 0);
-
-  // Desktop checkbox.
-  desktop_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), desktop_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(desktop_checkbox_), true);
-  g_signal_connect(desktop_checkbox_, "toggled",
-                   G_CALLBACK(OnToggleCheckboxThunk), this);
-
-  // Menu checkbox.
-  menu_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_MENU_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), menu_checkbox_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(menu_checkbox_), false);
-  g_signal_connect(menu_checkbox_, "toggled",
-                   G_CALLBACK(OnToggleCheckboxThunk), this);
-
-  g_signal_connect(create_dialog_, "response",
-                   G_CALLBACK(OnCreateDialogResponseThunk), this);
-  gtk_widget_show_all(create_dialog_);
-}
-
-CreateApplicationShortcutsDialogGtk::~CreateApplicationShortcutsDialogGtk() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  gtk_widget_destroy(create_dialog_);
-
-  if (error_dialog_)
-    gtk_widget_destroy(error_dialog_);
-
-  g_object_unref(favicon_pixbuf_);
-}
-
-void CreateApplicationShortcutsDialogGtk::OnCreateDialogResponse(
-    GtkWidget* widget, int response) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (response == GTK_RESPONSE_ACCEPT) {
-    shortcut_info_.create_on_desktop =
-        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_));
-    shortcut_info_.create_in_applications_menu =
-        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_));
-    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-         NewRunnableMethod(this,
-             &CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut,
-             shortcut_info_));
-
-    OnCreatedShortcut();
-  } else {
-    Release();
-  }
-}
-
-void CreateApplicationShortcutsDialogGtk::OnErrorDialogResponse(
-    GtkWidget* widget, int response) {
-  Release();
-}
-
-void CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut(
-    const ShellIntegration::ShortcutInfo& shortcut_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
-  scoped_ptr<base::Environment> env(base::Environment::Create());
-
-  std::string shortcut_template;
-  if (ShellIntegration::GetDesktopShortcutTemplate(env.get(),
-                                                   &shortcut_template)) {
-    ShellIntegration::CreateDesktopShortcut(shortcut_info,
-                                            shortcut_template);
-    Release();
-  } else {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        NewRunnableMethod(this,
-            &CreateApplicationShortcutsDialogGtk::ShowErrorDialog));
-  }
-}
-
-void CreateApplicationShortcutsDialogGtk::ShowErrorDialog() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  // Hide the create dialog so that the user can no longer interact with it.
-  gtk_widget_hide(create_dialog_);
-
-  error_dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_ERROR_TITLE).c_str(),
-      NULL,
-      (GtkDialogFlags) (GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_OK,
-      GTK_RESPONSE_ACCEPT,
-      NULL);
-  gtk_widget_realize(error_dialog_);
-  gtk_util::SetWindowSizeFromResources(
-      GTK_WINDOW(error_dialog_),
-      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_WIDTH_CHARS,
-      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_HEIGHT_LINES,
-      false);  // resizable
-  GtkWidget* content_area = GTK_DIALOG(error_dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(content_area), vbox);
-
-  // Label on top of the checkboxes.
-  GtkWidget* description = gtk_label_new(
-      l10n_util::GetStringFUTF8(
-          IDS_CREATE_SHORTCUTS_ERROR_LABEL,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(description), TRUE);
-  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);
-
-  g_signal_connect(error_dialog_, "response",
-                   G_CALLBACK(OnErrorDialogResponseThunk), this);
-  gtk_widget_show_all(error_dialog_);
-}
-
-void CreateApplicationShortcutsDialogGtk::OnToggleCheckbox(GtkWidget* sender) {
-  gboolean can_accept = FALSE;
-
-  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_)) ||
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_))) {
-    can_accept = TRUE;
-  }
-
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(create_dialog_),
-                                    GTK_RESPONSE_ACCEPT,
-                                    can_accept);
-}
-
-CreateWebApplicationShortcutsDialogGtk::CreateWebApplicationShortcutsDialogGtk(
-    GtkWindow* parent,
-    TabContents* tab_contents)
-  : CreateApplicationShortcutsDialogGtk(parent),
-    tab_contents_(tab_contents) {
-
-  // Get shortcut information now, it's needed for our UI.
-  web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_);
-  CreateIconPixBuf(shortcut_info_.favicon);
-
-  CreateDialogBox(parent);
-}
-
-void CreateWebApplicationShortcutsDialogGtk::OnCreatedShortcut() {
-  if (tab_contents_->delegate())
-    tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_);
-}
-
-CreateChromeApplicationShortcutsDialogGtk::
-    CreateChromeApplicationShortcutsDialogGtk(
-        GtkWindow* parent,
-        const Extension* app)
-      : CreateApplicationShortcutsDialogGtk(parent),
-        app_(app),
-        ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this))  {
-
-  // Get shortcut information now, it's needed for our UI.
-  shortcut_info_.extension_id = UTF8ToUTF16(app_->id());
-  shortcut_info_.url = GURL(app_->launch_web_url());
-  shortcut_info_.title = UTF8ToUTF16(app_->name());
-  shortcut_info_.description = UTF8ToUTF16(app_->description());
-
-  // Get the icon.
-  const gfx::Size max_size(kIconPreviewSizePixels, kIconPreviewSizePixels);
-  ExtensionResource icon_resource = app_->GetIconResource(
-      kIconPreviewSizePixels, ExtensionIconSet::MATCH_BIGGER);
-
-  // If no icon exists that is the desired size or larger, get the
-  // largest icon available:
-  if (icon_resource.empty())
-    icon_resource = app_->GetIconResource(
-        kIconPreviewSizePixels, ExtensionIconSet::MATCH_SMALLER);
-
-  tracker_.LoadImage(app_,
-                     icon_resource,
-                     max_size,
-                     ImageLoadingTracker::DONT_CACHE);
-}
-
-// Called by tracker_ when the app's icon is loaded.
-void CreateChromeApplicationShortcutsDialogGtk::OnImageLoaded(
-    SkBitmap* image, ExtensionResource resource, int index) {
-  if (image->isNull()) {
-    NOTREACHED() << "Corrupt image in profile?";
-    return;
-  }
-  shortcut_info_.favicon = *image;
-
-  CreateIconPixBuf(*image);
-  CreateDialogBox(parent_);
-}
diff --git a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h b/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h
deleted file mode 100644
index 5570e0c..0000000
--- a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/shell_integration.h"
-#include "googleurl/src/gurl.h"
-
-typedef struct _GdkPixbuf GdkPixbuf;
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkWindow GtkWindow;
-
-class Extension;
-class TabContents;
-
-class CreateApplicationShortcutsDialogGtk
-    : public base::RefCountedThreadSafe<CreateApplicationShortcutsDialogGtk,
-                                        BrowserThread::DeleteOnUIThread> {
- protected:
-  explicit CreateApplicationShortcutsDialogGtk(GtkWindow* parent);
-  virtual ~CreateApplicationShortcutsDialogGtk();
-
-  CHROMEGTK_CALLBACK_1(CreateApplicationShortcutsDialogGtk, void,
-                       OnCreateDialogResponse, int);
-
-  CHROMEGTK_CALLBACK_1(CreateApplicationShortcutsDialogGtk, void,
-                       OnErrorDialogResponse, int);
-
-  CHROMEGTK_CALLBACK_0(CreateApplicationShortcutsDialogGtk, void,
-                       OnToggleCheckbox);
-
-  virtual void CreateDialogBox(GtkWindow* parent);
-  virtual void CreateIconPixBuf(const SkBitmap& bitmap);
-
-  // This method is called after a shortcut is created.
-  // Subclasses can override it to take some action at that time.
-  virtual void OnCreatedShortcut(void) {}
-
-  void CreateDesktopShortcut(
-      const ShellIntegration::ShortcutInfo& shortcut_info);
-  void ShowErrorDialog();
-
-  GtkWindow* parent_;
-
-  // UI elements.
-  GtkWidget* desktop_checkbox_;
-  GtkWidget* menu_checkbox_;
-
-  // ShortcutInfo for the new shortcut.
-  ShellIntegration::ShortcutInfo shortcut_info_;
-
-  // Image associated with the site.
-  GdkPixbuf* favicon_pixbuf_;
-
-  // Dialog box that allows the user to create an application shortcut.
-  GtkWidget* create_dialog_;
-
-  // Dialog box that shows the error message.
-  GtkWidget* error_dialog_;
-
- private:
-  friend class BrowserThread;
-  friend class DeleteTask<CreateApplicationShortcutsDialogGtk>;
-  DISALLOW_COPY_AND_ASSIGN(CreateApplicationShortcutsDialogGtk);
-};
-
-class CreateWebApplicationShortcutsDialogGtk
-    : public CreateApplicationShortcutsDialogGtk {
- public:
-  // Displays the dialog box to create application shortcuts for |tab_contents|.
-  static void Show(GtkWindow* parent, TabContents* tab_contents);
-
-  explicit CreateWebApplicationShortcutsDialogGtk(GtkWindow* parent,
-                                                  TabContents* tab_contents);
-  virtual ~CreateWebApplicationShortcutsDialogGtk() {}
-
-  virtual void OnCreatedShortcut(void);
-
- private:
-
-  // TabContents for which the shortcut will be created.
-  TabContents* tab_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(CreateWebApplicationShortcutsDialogGtk);
-};
-
-class CreateChromeApplicationShortcutsDialogGtk
-  : public CreateApplicationShortcutsDialogGtk,
-    public ImageLoadingTracker::Observer {
- public:
-  // Displays the dialog box to create application shortcuts for |app|.
-  static void Show(GtkWindow* parent, const Extension* app);
-
-  explicit CreateChromeApplicationShortcutsDialogGtk(GtkWindow* parent,
-                                                     const Extension* app);
-  virtual ~CreateChromeApplicationShortcutsDialogGtk() {}
-
-  // Implement ImageLoadingTracker::Observer.  |tracker_| is used to
-  // load the app's icon.  This method recieves the icon, and adds
-  // it to the "Create Shortcut" dailog box.
-  virtual void OnImageLoaded(SkBitmap* image,
-                             ExtensionResource resource,
-                             int index);
-
- private:
-  const Extension* app_;
-  ImageLoadingTracker tracker_;
-  DISALLOW_COPY_AND_ASSIGN(CreateChromeApplicationShortcutsDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/custom_button.cc b/chrome/browser/gtk/custom_button.cc
deleted file mode 100644
index 375452d..0000000
--- a/chrome/browser/gtk/custom_button.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/custom_button.h"
-
-#include "app/resource_bundle.h"
-#include "base/basictypes.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/gtk_util.h"
-#include "gfx/skbitmap_operations.h"
-#include "grit/theme_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-CustomDrawButtonBase::CustomDrawButtonBase(GtkThemeProvider* theme_provider,
-                                           int normal_id,
-                                           int pressed_id,
-                                           int hover_id,
-                                           int disabled_id)
-    : background_image_(NULL),
-      paint_override_(-1),
-      normal_id_(normal_id),
-      pressed_id_(pressed_id),
-      hover_id_(hover_id),
-      disabled_id_(disabled_id),
-      theme_provider_(theme_provider),
-      flipped_(false) {
-  for (int i = 0; i < (GTK_STATE_INSENSITIVE + 1); ++i)
-    surfaces_[i].reset(new CairoCachedSurface);
-  background_image_.reset(new CairoCachedSurface);
-
-  if (theme_provider) {
-    // Load images by pretending that we got a BROWSER_THEME_CHANGED
-    // notification.
-    theme_provider->InitThemesFor(this);
-
-    registrar_.Add(this,
-                   NotificationType::BROWSER_THEME_CHANGED,
-                   NotificationService::AllSources());
-  } else {
-    // Load the button images from the resource bundle.
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    surfaces_[GTK_STATE_NORMAL]->UsePixbuf(
-        normal_id_ ? rb.GetRTLEnabledPixbufNamed(normal_id_) : NULL);
-    surfaces_[GTK_STATE_ACTIVE]->UsePixbuf(
-        pressed_id_ ? rb.GetRTLEnabledPixbufNamed(pressed_id_) : NULL);
-    surfaces_[GTK_STATE_PRELIGHT]->UsePixbuf(
-        hover_id_ ? rb.GetRTLEnabledPixbufNamed(hover_id_) : NULL);
-    surfaces_[GTK_STATE_SELECTED]->UsePixbuf(NULL);
-    surfaces_[GTK_STATE_INSENSITIVE]->UsePixbuf(
-        disabled_id_ ? rb.GetRTLEnabledPixbufNamed(disabled_id_) : NULL);
-  }
-}
-
-CustomDrawButtonBase::~CustomDrawButtonBase() {
-}
-
-int CustomDrawButtonBase::Width() const {
-  return surfaces_[0]->Width();
-}
-
-int CustomDrawButtonBase::Height() const {
-  return surfaces_[0]->Height();
-}
-
-gboolean CustomDrawButtonBase::OnExpose(GtkWidget* widget,
-                                        GdkEventExpose* e,
-                                        gdouble hover_state) {
-  int paint_state = paint_override_ >= 0 ?
-                    paint_override_ : GTK_WIDGET_STATE(widget);
-
-  // If the paint state is PRELIGHT then set it to NORMAL (we will paint the
-  // hover state according to |hover_state_|).
-  if (paint_state == GTK_STATE_PRELIGHT)
-    paint_state = GTK_STATE_NORMAL;
-  bool animating_hover = hover_state > 0.0 &&
-      paint_state == GTK_STATE_NORMAL;
-  CairoCachedSurface* pixbuf = PixbufForState(paint_state);
-  CairoCachedSurface* hover_pixbuf = PixbufForState(GTK_STATE_PRELIGHT);
-
-  if (!pixbuf || !pixbuf->valid())
-    return FALSE;
-  if (animating_hover && (!hover_pixbuf || !hover_pixbuf->valid()))
-    return FALSE;
-
-  cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-  cairo_translate(cairo_context, widget->allocation.x, widget->allocation.y);
-
-  if (flipped_) {
-    // Horizontally flip the image for non-LTR/RTL reasons.
-    cairo_translate(cairo_context, widget->allocation.width, 0.0f);
-    cairo_scale(cairo_context, -1.0f, 1.0f);
-  }
-
-  // The widget might be larger than the pixbuf. Paint the pixbuf flush with the
-  // start of the widget (left for LTR, right for RTL) and its bottom.
-  gfx::Rect bounds = gfx::Rect(0, 0, pixbuf->Width(), 0);
-  int x = gtk_util::MirroredLeftPointForRect(widget, bounds);
-  int y = widget->allocation.height - pixbuf->Height();
-
-  if (background_image_->valid()) {
-    background_image_->SetSource(cairo_context, x, y);
-    cairo_paint(cairo_context);
-  }
-
-  pixbuf->SetSource(cairo_context, x, y);
-  cairo_paint(cairo_context);
-
-  if (animating_hover) {
-    hover_pixbuf->SetSource(cairo_context, x, y);
-    cairo_paint_with_alpha(cairo_context, hover_state);
-  }
-
-  cairo_destroy(cairo_context);
-
-  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
-  if (child)
-    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
-
-  return TRUE;
-}
-
-void CustomDrawButtonBase::SetBackground(SkColor color,
-                                         SkBitmap* image, SkBitmap* mask) {
-  if (!image || !mask) {
-    if (background_image_->valid()) {
-      background_image_->UsePixbuf(NULL);
-    }
-  } else {
-    SkBitmap img =
-        SkBitmapOperations::CreateButtonBackground(color, *image, *mask);
-
-    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&img);
-    background_image_->UsePixbuf(pixbuf);
-    g_object_unref(pixbuf);
-  }
-}
-
-void CustomDrawButtonBase::Observe(NotificationType type,
-    const NotificationSource& source, const NotificationDetails& details) {
-  DCHECK(theme_provider_);
-  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
-
-  surfaces_[GTK_STATE_NORMAL]->UsePixbuf(normal_id_ ?
-      theme_provider_->GetRTLEnabledPixbufNamed(normal_id_) : NULL);
-  surfaces_[GTK_STATE_ACTIVE]->UsePixbuf(pressed_id_ ?
-      theme_provider_->GetRTLEnabledPixbufNamed(pressed_id_) : NULL);
-  surfaces_[GTK_STATE_PRELIGHT]->UsePixbuf(hover_id_ ?
-      theme_provider_->GetRTLEnabledPixbufNamed(hover_id_) : NULL);
-  surfaces_[GTK_STATE_SELECTED]->UsePixbuf(NULL);
-  surfaces_[GTK_STATE_INSENSITIVE]->UsePixbuf(disabled_id_ ?
-      theme_provider_->GetRTLEnabledPixbufNamed(disabled_id_) : NULL);
-}
-
-CairoCachedSurface* CustomDrawButtonBase::PixbufForState(int state) {
-  CairoCachedSurface* pixbuf = surfaces_[state].get();
-
-  // Fall back to the default image if we don't have one for this state.
-  if (!pixbuf || !pixbuf->valid())
-    pixbuf = surfaces_[GTK_STATE_NORMAL].get();
-
-  return pixbuf;
-}
-
-// CustomDrawHoverController ---------------------------------------------------
-
-CustomDrawHoverController::CustomDrawHoverController(GtkWidget* widget)
-    : slide_animation_(this),
-      widget_(NULL) {
-  Init(widget);
-}
-
-CustomDrawHoverController::CustomDrawHoverController()
-    : slide_animation_(this),
-      widget_(NULL) {
-}
-
-CustomDrawHoverController::~CustomDrawHoverController() {
-}
-
-void CustomDrawHoverController::Init(GtkWidget* widget) {
-  DCHECK(widget_ == NULL);
-  widget_ = widget;
-  g_signal_connect(widget_, "enter-notify-event",
-                   G_CALLBACK(OnEnterThunk), this);
-  g_signal_connect(widget_, "leave-notify-event",
-                   G_CALLBACK(OnLeaveThunk), this);
-}
-
-void CustomDrawHoverController::AnimationProgressed(
-    const ui::Animation* animation) {
-  gtk_widget_queue_draw(widget_);
-}
-
-gboolean CustomDrawHoverController::OnEnter(
-    GtkWidget* widget,
-    GdkEventCrossing* event) {
-  slide_animation_.Show();
-  return FALSE;
-}
-
-gboolean CustomDrawHoverController::OnLeave(
-    GtkWidget* widget,
-    GdkEventCrossing* event) {
-  // When the user is holding a mouse button, we don't want to animate.
-  if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))
-    slide_animation_.Reset();
-  else
-    slide_animation_.Hide();
-  return FALSE;
-}
-
-// CustomDrawButton ------------------------------------------------------------
-
-CustomDrawButton::CustomDrawButton(int normal_id,
-                                   int pressed_id,
-                                   int hover_id,
-                                   int disabled_id)
-    : button_base_(NULL, normal_id, pressed_id, hover_id, disabled_id),
-      theme_provider_(NULL) {
-  Init();
-
-  // Initialize the theme stuff with no theme_provider.
-  SetBrowserTheme();
-}
-
-CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider,
-                                   int normal_id,
-                                   int pressed_id,
-                                   int hover_id,
-                                   int disabled_id,
-                                   const char* stock_id,
-                                   GtkIconSize stock_size)
-    : button_base_(theme_provider, normal_id, pressed_id, hover_id,
-                   disabled_id),
-      theme_provider_(theme_provider) {
-  native_widget_.Own(gtk_image_new_from_stock(stock_id, stock_size));
-
-  Init();
-
-  theme_provider_->InitThemesFor(this);
-  registrar_.Add(this,
-                 NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider,
-                                   int normal_id,
-                                   int pressed_id,
-                                   int hover_id,
-                                   int disabled_id,
-                                   GtkWidget* native_widget)
-    : button_base_(theme_provider, normal_id, pressed_id, hover_id,
-                   disabled_id),
-      native_widget_(native_widget),
-      theme_provider_(theme_provider) {
-  Init();
-
-  theme_provider_->InitThemesFor(this);
-  registrar_.Add(this,
-                 NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-CustomDrawButton::~CustomDrawButton() {
-  widget_.Destroy();
-  native_widget_.Destroy();
-}
-
-void CustomDrawButton::Init() {
-  widget_.Own(gtk_chrome_button_new());
-  GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS);
-  g_signal_connect(widget(), "expose-event",
-                   G_CALLBACK(OnCustomExposeThunk), this);
-  hover_controller_.Init(widget());
-}
-
-void CustomDrawButton::Observe(NotificationType type,
-    const NotificationSource& source, const NotificationDetails& details) {
-  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
-  SetBrowserTheme();
-}
-
-void CustomDrawButton::SetPaintOverride(GtkStateType state) {
-  button_base_.set_paint_override(state);
-  gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget()), state);
-  gtk_widget_queue_draw(widget());
-}
-
-void CustomDrawButton::UnsetPaintOverride() {
-  button_base_.set_paint_override(-1);
-  gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget()));
-  gtk_widget_queue_draw(widget());
-}
-
-void CustomDrawButton::SetBackground(SkColor color,
-                                     SkBitmap* image, SkBitmap* mask) {
-  button_base_.SetBackground(color, image, mask);
-}
-
-gboolean CustomDrawButton::OnCustomExpose(GtkWidget* sender,
-                                          GdkEventExpose* e) {
-  if (UseGtkTheme()) {
-    // Continue processing this expose event.
-    return FALSE;
-  } else {
-    double hover_state = hover_controller_.GetCurrentValue();
-    return button_base_.OnExpose(sender, e, hover_state);
-  }
-}
-
-// static
-CustomDrawButton* CustomDrawButton::CloseButton(
-    GtkThemeProvider* theme_provider) {
-  CustomDrawButton* button = new CustomDrawButton(theme_provider, IDR_CLOSE_BAR,
-      IDR_CLOSE_BAR_P, IDR_CLOSE_BAR_H, 0, GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
-  return button;
-}
-
-void CustomDrawButton::SetBrowserTheme() {
-  if (UseGtkTheme()) {
-    if (native_widget_.get())
-      gtk_button_set_image(GTK_BUTTON(widget()), native_widget_.get());
-    gtk_widget_set_size_request(widget(), -1, -1);
-    gtk_widget_set_app_paintable(widget(), FALSE);
-  } else {
-    if (native_widget_.get())
-      gtk_button_set_image(GTK_BUTTON(widget()), NULL);
-    gtk_widget_set_size_request(widget(), button_base_.Width(),
-                                button_base_.Height());
-
-    gtk_widget_set_app_paintable(widget(), TRUE);
-  }
-
-  gtk_chrome_button_set_use_gtk_rendering(
-      GTK_CHROME_BUTTON(widget()), UseGtkTheme());
-}
-
-bool CustomDrawButton::UseGtkTheme() {
-  return theme_provider_ && theme_provider_->UseGtkTheme();
-}
diff --git a/chrome/browser/gtk/custom_button.h b/chrome/browser/gtk/custom_button.h
deleted file mode 100644
index 85f07b1..0000000
--- a/chrome/browser/gtk/custom_button.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CUSTOM_BUTTON_H_
-#define CHROME_BROWSER_GTK_CUSTOM_BUTTON_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-
-class CairoCachedSurface;
-class GtkThemeProvider;
-class SkBitmap;
-
-// These classes implement two kinds of custom-drawn buttons.  They're
-// used on the toolbar and the bookmarks bar.
-
-// CustomDrawButtonBase provides the base for building a custom drawn button.
-// It handles managing the pixbufs containing all the static images used to draw
-// the button.  It also manages painting these pixbufs.
-class CustomDrawButtonBase : public NotificationObserver {
- public:
-  // If the images come from ResourceBundle rather than the theme provider,
-  // pass in NULL for |theme_provider|.
-  CustomDrawButtonBase(GtkThemeProvider* theme_provider,
-                       int normal_id,
-                       int pressed_id,
-                       int hover_id,
-                       int disabled_id);
-
-  ~CustomDrawButtonBase();
-
-  // Flip the image horizontally. Not to be used for RTL/LTR reasons. (In RTL
-  // mode, this will unflip the image.)
-  void set_flipped(bool flipped) { flipped_ = flipped; }
-
-  // Returns the dimensions of the first surface.
-  int Width() const;
-  int Height() const;
-
-  gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e, gdouble hover_state);
-
-  void set_paint_override(int state) { paint_override_ = state; }
-  int paint_override() const { return paint_override_; }
-
-  // Set the background details.
-  void SetBackground(SkColor color, SkBitmap* image, SkBitmap* mask);
-
-  // Provide NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  // Get the CairoCachedSurface from |surfaces_| for |state|.
-  CairoCachedSurface* PixbufForState(int state);
-
-  // We store one surface for each possible state of the button;
-  // INSENSITIVE is the last available state;
-  scoped_ptr<CairoCachedSurface> surfaces_[GTK_STATE_INSENSITIVE + 1];
-
-  // The background image.
-  scoped_ptr<CairoCachedSurface> background_image_;
-
-  // If non-negative, the state to paint the button.
-  int paint_override_;
-
-  // We need to remember the image ids that the user passes in and the theme
-  // provider so we can reload images if the user changes theme.
-  int normal_id_;
-  int pressed_id_;
-  int hover_id_;
-  int disabled_id_;
-  GtkThemeProvider* theme_provider_;
-
-  // Whether the button is flipped horizontally. Not used for RTL (we get
-  // flipped versions from the theme provider). Used for the flipped window
-  // buttons.
-  bool flipped_;
-
-  // Used to listen for theme change notifications.
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(CustomDrawButtonBase);
-};
-
-// CustomDrawHoverController is a convenience class that eases the common task
-// of controlling the hover state of a button. The "hover state" refers to the
-// percent opacity of a button's PRELIGHT. The PRELIGHT is animated such that
-// when a user moves a mouse over a button the PRELIGHT fades in.
-class CustomDrawHoverController : public ui::AnimationDelegate {
- public:
-  explicit CustomDrawHoverController(GtkWidget* widget);
-  CustomDrawHoverController();
-
-  virtual ~CustomDrawHoverController();
-
-  void Init(GtkWidget* widget);
-
-  double GetCurrentValue() {
-    return slide_animation_.GetCurrentValue();
-  }
-
- private:
-  virtual void AnimationProgressed(const ui::Animation* animation);
-
-  CHROMEGTK_CALLBACK_1(CustomDrawHoverController, gboolean, OnEnter,
-                       GdkEventCrossing*);
-  CHROMEGTK_CALLBACK_1(CustomDrawHoverController, gboolean, OnLeave,
-                       GdkEventCrossing*);
-
-  ui::SlideAnimation slide_animation_;
-  GtkWidget* widget_;
-};
-
-// CustomDrawButton is a plain button where all its various states are drawn
-// with static images. In GTK rendering mode, it will show the standard button
-// with GTK |stock_id|.
-class CustomDrawButton : public NotificationObserver {
- public:
-  // The constructor takes 4 resource ids.  If a resource doesn't exist for a
-  // button, pass in 0.
-  CustomDrawButton(int normal_id,
-                   int pressed_id,
-                   int hover_id,
-                   int disabled_id);
-
-  // Same as above, but uses themed (and possibly tinted) images. |stock_id| and
-  // |stock_size| are used for GTK+ theme mode.
-  CustomDrawButton(GtkThemeProvider* theme_provider,
-                   int normal_id,
-                   int pressed_id,
-                   int hover_id,
-                   int disabled_id,
-                   const char* stock_id,
-                   GtkIconSize stock_size);
-
-  // As above, but uses an arbitrary GtkImage rather than a stock icon. This
-  // constructor takes ownership of |native_widget|.
-  CustomDrawButton(GtkThemeProvider* theme_provider,
-                   int normal_id,
-                   int pressed_id,
-                   int hover_id,
-                   int disabled_id,
-                   GtkWidget* native_widget);
-
-  ~CustomDrawButton();
-
-  void Init();
-
-  // Flip the image horizontally. Not to be used for RTL/LTR reasons. (In RTL
-  // mode, this will unflip the image.)
-  void set_flipped(bool flipped) { button_base_.set_flipped(flipped); }
-
-  GtkWidget* widget() const { return widget_.get(); }
-
-  gfx::Rect bounds() const {
-      return gfx::Rect(widget_->allocation.x,
-                       widget_->allocation.y,
-                       widget_->allocation.width,
-                       widget_->allocation.height);
-  }
-
-  int width() const { return widget_->allocation.width; }
-  int height() const { return widget_->allocation.height; }
-
-  // Set the state to draw. We will paint the widget as if it were in this
-  // state.
-  void SetPaintOverride(GtkStateType state);
-
-  // Resume normal drawing of the widget's state.
-  void UnsetPaintOverride();
-
-  // Set the background details.
-  void SetBackground(SkColor color, SkBitmap* image, SkBitmap* mask);
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Returns a standard close button. Pass a |theme_provider| to use Gtk icons
-  // in Gtk rendering mode.
-  static CustomDrawButton* CloseButton(GtkThemeProvider* theme_provider);
-
- private:
-  // Sets the button to themed or not.
-  void SetBrowserTheme();
-
-  // Whether to use the GTK+ theme. For this to be true, we have to be in GTK+
-  // theme mode and we must have a valid stock icon resource.
-  bool UseGtkTheme();
-
-  // Callback for custom button expose, used to draw the custom graphics.
-  CHROMEGTK_CALLBACK_1(CustomDrawButton, gboolean, OnCustomExpose,
-                       GdkEventExpose*);
-
-  // The actual button widget.
-  OwnedWidgetGtk widget_;
-
-  CustomDrawButtonBase button_base_;
-
-  CustomDrawHoverController hover_controller_;
-
-  // The widget to use when we are displaying in GTK+ theme mode.
-  OwnedWidgetGtk native_widget_;
-
-  // Our theme provider.
-  GtkThemeProvider* theme_provider_;
-
-  // Used to listen for theme change notifications.
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(CustomDrawButton);
-};
-
-#endif  // CHROME_BROWSER_GTK_CUSTOM_BUTTON_H_
diff --git a/chrome/browser/gtk/custom_drag.cc b/chrome/browser/gtk/custom_drag.cc
deleted file mode 100644
index 6556e85..0000000
--- a/chrome/browser/gtk/custom_drag.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/custom_drag.h"
-
-#include "app/gtk_dnd_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/download/download_item.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "gfx/gtk_util.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/net_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-const int kDownloadItemCodeMask = gtk_dnd_util::TEXT_URI_LIST |
-                                  gtk_dnd_util::CHROME_NAMED_URL;
-const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY;
-const GdkDragAction kBookmarkDragAction =
-    static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
-void OnDragDataGetForDownloadItem(GtkSelectionData* selection_data,
-                                  guint target_type,
-                                  const DownloadItem* download_item) {
-  GURL url = net::FilePathToFileURL(download_item->full_path());
-  gtk_dnd_util::WriteURLWithName(selection_data, url,
-      UTF8ToUTF16(download_item->GetFileNameToReportUser().value()),
-      target_type);
-}
-
-void OnDragDataGetStandalone(GtkWidget* widget, GdkDragContext* context,
-                             GtkSelectionData* selection_data,
-                             guint target_type, guint time,
-                             const DownloadItem* item) {
-  OnDragDataGetForDownloadItem(selection_data, target_type, item);
-}
-
-}  // namespace
-
-// CustomDrag ------------------------------------------------------------------
-
-CustomDrag::CustomDrag(SkBitmap* icon, int code_mask, GdkDragAction action)
-    : drag_widget_(gtk_invisible_new()),
-      pixbuf_(icon ? gfx::GdkPixbufFromSkBitmap(icon) : NULL) {
-  g_signal_connect(drag_widget_, "drag-data-get",
-                   G_CALLBACK(OnDragDataGetThunk), this);
-  g_signal_connect(drag_widget_, "drag-begin",
-                   G_CALLBACK(OnDragBeginThunk), this);
-  g_signal_connect(drag_widget_, "drag-end",
-                   G_CALLBACK(OnDragEndThunk), this);
-
-  GtkTargetList* list = gtk_dnd_util::GetTargetListFromCodeMask(code_mask);
-  GdkEvent* event = gtk_get_current_event();
-  gtk_drag_begin(drag_widget_, list, action, 1, event);
-  if (event)
-    gdk_event_free(event);
-  gtk_target_list_unref(list);
-}
-
-CustomDrag::~CustomDrag() {
-  if (pixbuf_)
-    g_object_unref(pixbuf_);
-  gtk_widget_destroy(drag_widget_);
-}
-
-void CustomDrag::OnDragBegin(GtkWidget* widget, GdkDragContext* drag_context) {
-  if (pixbuf_)
-    gtk_drag_set_icon_pixbuf(drag_context, pixbuf_, 0, 0);
-}
-
-void CustomDrag::OnDragEnd(GtkWidget* widget, GdkDragContext* drag_context) {
-  delete this;
-}
-
-// DownloadItemDrag ------------------------------------------------------------
-
-DownloadItemDrag::DownloadItemDrag(const DownloadItem* item,
-                                   SkBitmap* icon)
-    : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction),
-      download_item_(item) {
-}
-
-DownloadItemDrag::~DownloadItemDrag() {
-}
-
-void DownloadItemDrag::OnDragDataGet(
-    GtkWidget* widget, GdkDragContext* context,
-    GtkSelectionData* selection_data,
-    guint target_type, guint time) {
-  OnDragDataGetForDownloadItem(selection_data, target_type, download_item_);
-}
-
-// static
-void DownloadItemDrag::SetSource(GtkWidget* widget,
-                                 DownloadItem* item,
-                                 SkBitmap* icon) {
-  gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0,
-                      kDownloadItemDragAction);
-  gtk_dnd_util::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask);
-
-  // Disconnect previous signal handlers, if any.
-  g_signal_handlers_disconnect_by_func(
-      widget,
-      reinterpret_cast<gpointer>(OnDragDataGetStandalone),
-      item);
-  // Connect new signal handlers.
-  g_signal_connect(widget, "drag-data-get",
-                   G_CALLBACK(OnDragDataGetStandalone), item);
-
-  GdkPixbuf* pixbuf = icon ? gfx::GdkPixbufFromSkBitmap(icon) : NULL;
-  if (pixbuf) {
-    gtk_drag_source_set_icon_pixbuf(widget, pixbuf);
-    g_object_unref(pixbuf);
-  }
-}
-
-// static
-void DownloadItemDrag::BeginDrag(const DownloadItem* item, SkBitmap* icon) {
-  new DownloadItemDrag(item, icon);
-}
-
-// BookmarkDrag ----------------------------------------------------------------
-
-BookmarkDrag::BookmarkDrag(Profile* profile,
-                           const std::vector<const BookmarkNode*>& nodes)
-    : CustomDrag(NULL,
-                 bookmark_utils::GetCodeMask(false),
-                 kBookmarkDragAction),
-      profile_(profile),
-      nodes_(nodes) {
-}
-
-BookmarkDrag::~BookmarkDrag() {
-}
-
-void BookmarkDrag::OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
-                                 GtkSelectionData* selection_data,
-                                 guint target_type, guint time) {
-  bookmark_utils::WriteBookmarksToSelection(nodes_, selection_data,
-                                            target_type, profile_);
-}
-
-// static
-void BookmarkDrag::BeginDrag(Profile* profile,
-                             const std::vector<const BookmarkNode*>& nodes) {
-  new BookmarkDrag(profile, nodes);
-}
diff --git a/chrome/browser/gtk/custom_drag.h b/chrome/browser/gtk/custom_drag.h
deleted file mode 100644
index 679fac0..0000000
--- a/chrome/browser/gtk/custom_drag.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_CUSTOM_DRAG_H_
-#define CHROME_BROWSER_GTK_CUSTOM_DRAG_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-
-class BookmarkNode;
-class DownloadItem;
-class Profile;
-class SkBitmap;
-
-// Base class for programatically generated drags.
-class CustomDrag {
- protected:
-  explicit CustomDrag(SkBitmap* icon, int code_mask, GdkDragAction action);
-  virtual ~CustomDrag();
-
-  virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
-                             GtkSelectionData* selection_data,
-                             guint target_type, guint time) = 0;
-
- private:
-  CHROMEGTK_CALLBACK_1(CustomDrag, void, OnDragBegin, GdkDragContext*);
-  CHROMEGTK_CALLBACK_1(CustomDrag, void, OnDragEnd, GdkDragContext*);
-
-  // Since this uses a virtual function, we can't use a macro.
-  static void OnDragDataGetThunk(GtkWidget* widget, GdkDragContext* context,
-                                 GtkSelectionData* selection_data,
-                                 guint target_type, guint time,
-                                 CustomDrag* custom_drag) {
-    return custom_drag->OnDragDataGet(widget, context, selection_data,
-                                      target_type, time);
-  }
-
-  // Can't use a OwnedWidgetGtk because the initialization of GtkInvisible
-  // sinks the reference.
-  GtkWidget* drag_widget_;
-
-  GdkPixbuf* pixbuf_;
-
-  DISALLOW_COPY_AND_ASSIGN(CustomDrag);
-};
-
-// Encapsulates functionality for drags of download items.
-class DownloadItemDrag : public CustomDrag {
- public:
-  // Sets |widget| as a source for drags pertaining to |item|. No
-  // DownloadItemDrag object is created.
-  // It is safe to call this multiple times with different values of |icon|.
-  static void SetSource(GtkWidget* widget, DownloadItem* item, SkBitmap* icon);
-
-  // Creates a new DownloadItemDrag, the lifetime of which is tied to the
-  // system drag.
-  static void BeginDrag(const DownloadItem* item, SkBitmap* icon);
-
- private:
-  DownloadItemDrag(const DownloadItem* item, SkBitmap* icon);
-  virtual ~DownloadItemDrag();
-
-  virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
-                             GtkSelectionData* selection_data,
-                             guint target_type, guint time);
-
-  const DownloadItem* download_item_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloadItemDrag);
-};
-
-// Encapsulates functionality for drags of one or more bookmarks.
-class BookmarkDrag : public CustomDrag {
- public:
-  // Creates a new BookmarkDrag, the lifetime of which is tied to the
-  // system drag.
-  static void BeginDrag(Profile* profile,
-                        const std::vector<const BookmarkNode*>& nodes);
-
- private:
-  BookmarkDrag(Profile* profile,
-               const std::vector<const BookmarkNode*>& nodes);
-  virtual ~BookmarkDrag();
-
-  virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
-                             GtkSelectionData* selection_data,
-                             guint target_type, guint time);
-
-  Profile* profile_;
-  std::vector<const BookmarkNode*> nodes_;
-
-  DISALLOW_COPY_AND_ASSIGN(BookmarkDrag);
-};
-
-#endif  // CHROME_BROWSER_GTK_CUSTOM_DRAG_H_
diff --git a/chrome/browser/gtk/dialogs_gtk.cc b/chrome/browser/gtk/dialogs_gtk.cc
deleted file mode 100644
index 7188620..0000000
--- a/chrome/browser/gtk/dialogs_gtk.cc
+++ /dev/null
@@ -1,587 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-#include <map>
-#include <set>
-
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/mime_util.h"
-#include "base/sys_string_conversions.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/shell_dialogs.h"
-#include "grit/generated_resources.h"
-
-// The size of the preview we display for selected image files. We set height
-// larger than width because generally there is more free space vertically
-// than horiztonally (setting the preview image will alway expand the width of
-// the dialog, but usually not the height). The image's aspect ratio will always
-// be preserved.
-static const int kPreviewWidth = 256;
-static const int kPreviewHeight = 512;
-
-// Implementation of SelectFileDialog that shows a Gtk common dialog for
-// choosing a file or folder. This acts as a modal dialog.
-class SelectFileDialogImpl : public SelectFileDialog {
- public:
-  explicit SelectFileDialogImpl(Listener* listener);
-
-  // BaseShellDialog implementation.
-  virtual bool IsRunning(gfx::NativeWindow parent_window) const;
-  virtual void ListenerDestroyed();
-
-  // SelectFileDialog implementation.
-  // |params| is user data we pass back via the Listener interface.
-  virtual void SelectFile(Type type,
-                          const string16& title,
-                          const FilePath& default_path,
-                          const FileTypeInfo* file_types,
-                          int file_type_index,
-                          const FilePath::StringType& default_extension,
-                          gfx::NativeWindow owning_window,
-                          void* params);
-
- private:
-  virtual ~SelectFileDialogImpl();
-
-  // Add the filters from |file_types_| to |chooser|.
-  void AddFilters(GtkFileChooser* chooser);
-
-  // Notifies the listener that a single file was chosen.
-  void FileSelected(GtkWidget* dialog, const FilePath& path);
-
-  // Notifies the listener that multiple files were chosen.
-  void MultiFilesSelected(GtkWidget* dialog,
-                          const std::vector<FilePath>& files);
-
-  // Notifies the listener that no file was chosen (the action was canceled).
-  // Dialog is passed so we can find that |params| pointer that was passed to
-  // us when we were told to show the dialog.
-  void FileNotSelected(GtkWidget* dialog);
-
-  GtkWidget* CreateSelectFolderDialog(const std::string& title,
-      const FilePath& default_path, gfx::NativeWindow parent);
-
-  GtkWidget* CreateFileOpenDialog(const std::string& title,
-      const FilePath& default_path, gfx::NativeWindow parent);
-
-  GtkWidget* CreateMultiFileOpenDialog(const std::string& title,
-      const FilePath& default_path, gfx::NativeWindow parent);
-
-  GtkWidget* CreateSaveAsDialog(const std::string& title,
-      const FilePath& default_path, gfx::NativeWindow parent);
-
-  // Removes and returns the |params| associated with |dialog| from
-  // |params_map_|.
-  void* PopParamsForDialog(GtkWidget* dialog);
-
-  // Take care of internal data structures when a file dialog is destroyed.
-  void FileDialogDestroyed(GtkWidget* dialog);
-
-  // Check whether response_id corresponds to the user cancelling/closing the
-  // dialog. Used as a helper for the below callbacks.
-  bool IsCancelResponse(gint response_id);
-
-  // Common function for OnSelectSingleFileDialogResponse and
-  // OnSelectSingleFolderDialogResponse.
-  void SelectSingleFileHelper(GtkWidget* dialog,
-                              gint response_id,
-                              bool allow_folder);
-
-  // Common function for CreateFileOpenDialog and CreateMultiFileOpenDialog.
-  GtkWidget* CreateFileOpenHelper(const std::string& title,
-                                  const FilePath& default_path,
-                                  gfx::NativeWindow parent);
-
-  // Wrapper for file_util::DirectoryExists() that allow access on the UI
-  // thread. Use this only in the file dialog functions, where it's ok
-  // because the file dialog has to do many stats anyway. One more won't
-  // hurt too badly and it's likely already cached.
-  bool CallDirectoryExistsOnUIThread(const FilePath& path);
-
-  // Callback for when the user responds to a Save As or Open File dialog.
-  CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
-                       OnSelectSingleFileDialogResponse, gint);
-
-  // Callback for when the user responds to a Select Folder dialog.
-  CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
-                       OnSelectSingleFolderDialogResponse, gint);
-
-  // Callback for when the user responds to a Open Multiple Files dialog.
-  CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
-                       OnSelectMultiFileDialogResponse, gint);
-
-  // Callback for when the file chooser gets destroyed.
-  CHROMEGTK_CALLBACK_0(SelectFileDialogImpl, void, OnFileChooserDestroy);
-
-  // Callback for when we update the preview for the selection.
-  CHROMEGTK_CALLBACK_0(SelectFileDialogImpl, void, OnUpdatePreview);
-
-  // The listener to be notified of selection completion.
-  Listener* listener_;
-
-  // A map from dialog windows to the |params| user data associated with them.
-  std::map<GtkWidget*, void*> params_map_;
-
-  // The file filters.
-  FileTypeInfo file_types_;
-
-  // The index of the default selected file filter.
-  // Note: This starts from 1, not 0.
-  size_t file_type_index_;
-
-  // The set of all parent windows for which we are currently running dialogs.
-  std::set<GtkWindow*> parents_;
-
-  // The type of dialog we are showing the user.
-  Type type_;
-
-  // These two variables track where the user last saved a file or opened a
-  // file so that we can display future dialogs with the same starting path.
-  static FilePath* last_saved_path_;
-  static FilePath* last_opened_path_;
-
-  // The GtkImage widget for showing previews of selected images.
-  GtkWidget* preview_;
-
-  // All our dialogs.
-  std::set<GtkWidget*> dialogs_;
-
-  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
-};
-
-FilePath* SelectFileDialogImpl::last_saved_path_ = NULL;
-FilePath* SelectFileDialogImpl::last_opened_path_ = NULL;
-
-// static
-SelectFileDialog* SelectFileDialog::Create(Listener* listener) {
-  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
-  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  return new SelectFileDialogImpl(listener);
-}
-
-SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener)
-    : listener_(listener),
-      file_type_index_(0),
-      type_(SELECT_NONE),
-      preview_(NULL) {
-  if (!last_saved_path_) {
-    last_saved_path_ = new FilePath();
-    last_opened_path_ = new FilePath();
-  }
-}
-
-SelectFileDialogImpl::~SelectFileDialogImpl() {
-  while (dialogs_.begin() != dialogs_.end()) {
-    gtk_widget_destroy(*(dialogs_.begin()));
-  }
-}
-
-bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
-  return parents_.find(parent_window) != parents_.end();
-}
-
-void SelectFileDialogImpl::ListenerDestroyed() {
-  listener_ = NULL;
-}
-
-// We ignore |default_extension|.
-void SelectFileDialogImpl::SelectFile(
-    Type type,
-    const string16& title,
-    const FilePath& default_path,
-    const FileTypeInfo* file_types,
-    int file_type_index,
-    const FilePath::StringType& default_extension,
-    gfx::NativeWindow owning_window,
-    void* params) {
-  type_ = type;
-  // |owning_window| can be null when user right-clicks on a downloadable item
-  // and chooses 'Open Link in New Tab' when 'Ask where to save each file
-  // before downloading.' preference is turned on. (http://crbug.com/29213)
-  if (owning_window)
-    parents_.insert(owning_window);
-
-  std::string title_string = UTF16ToUTF8(title);
-
-  file_type_index_ = file_type_index;
-  if (file_types)
-    file_types_ = *file_types;
-  else
-    file_types_.include_all_files = true;
-
-  GtkWidget* dialog = NULL;
-  switch (type) {
-    case SELECT_FOLDER:
-      dialog = CreateSelectFolderDialog(title_string, default_path,
-                                        owning_window);
-      break;
-    case SELECT_OPEN_FILE:
-      dialog = CreateFileOpenDialog(title_string, default_path, owning_window);
-      break;
-    case SELECT_OPEN_MULTI_FILE:
-      dialog = CreateMultiFileOpenDialog(title_string, default_path,
-                                         owning_window);
-      break;
-    case SELECT_SAVEAS_FILE:
-      dialog = CreateSaveAsDialog(title_string, default_path, owning_window);
-      break;
-    default:
-      NOTREACHED();
-      return;
-  }
-  dialogs_.insert(dialog);
-
-  preview_ = gtk_image_new();
-  g_signal_connect(dialog, "destroy",
-                   G_CALLBACK(OnFileChooserDestroyThunk), this);
-  g_signal_connect(dialog, "update-preview",
-                   G_CALLBACK(OnUpdatePreviewThunk), this);
-  gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_);
-
-  params_map_[dialog] = params;
-
-  // Set window-to-parent modality by adding the dialog to the same window
-  // group as the parent.
-  gtk_window_group_add_window(gtk_window_get_group(owning_window),
-                              GTK_WINDOW(dialog));
-  gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
-
-  gtk_widget_show_all(dialog);
-}
-
-void SelectFileDialogImpl::AddFilters(GtkFileChooser* chooser) {
-  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
-    GtkFileFilter* filter = NULL;
-    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
-      if (!file_types_.extensions[i][j].empty()) {
-        if (!filter)
-          filter = gtk_file_filter_new();
-        std::string mime_type = mime_util::GetFileMimeType(
-            FilePath("name.").Append(file_types_.extensions[i][j]));
-        gtk_file_filter_add_mime_type(filter, mime_type.c_str());
-      }
-    }
-    // We didn't find any non-empty extensions to filter on.
-    if (!filter)
-      continue;
-
-    // The description vector may be blank, in which case we are supposed to
-    // use some sort of default description based on the filter.
-    if (i < file_types_.extension_description_overrides.size()) {
-      gtk_file_filter_set_name(filter, UTF16ToUTF8(
-          file_types_.extension_description_overrides[i]).c_str());
-    } else {
-      // There is no system default filter description so we use
-      // the MIME type itself if the description is blank.
-      std::string mime_type = mime_util::GetFileMimeType(
-          FilePath("name.").Append(file_types_.extensions[i][0]));
-      gtk_file_filter_set_name(filter, mime_type.c_str());
-    }
-
-    gtk_file_chooser_add_filter(chooser, filter);
-    if (i == file_type_index_ - 1)
-      gtk_file_chooser_set_filter(chooser, filter);
-  }
-
-  // Add the *.* filter, but only if we have added other filters (otherwise it
-  // is implied).
-  if (file_types_.include_all_files && file_types_.extensions.size() > 0) {
-    GtkFileFilter* filter = gtk_file_filter_new();
-    gtk_file_filter_add_pattern(filter, "*");
-    gtk_file_filter_set_name(filter,
-        l10n_util::GetStringUTF8(IDS_SAVEAS_ALL_FILES).c_str());
-    gtk_file_chooser_add_filter(chooser, filter);
-  }
-}
-
-void SelectFileDialogImpl::FileSelected(GtkWidget* dialog,
-                                        const FilePath& path) {
-  if (type_ == SELECT_SAVEAS_FILE)
-    *last_saved_path_ = path.DirName();
-  else if (type_ == SELECT_OPEN_FILE)
-    *last_opened_path_ = path.DirName();
-  else if (type_ == SELECT_FOLDER)
-    *last_opened_path_ = path.DirName().DirName();
-  else
-    NOTREACHED();
-
-  if (listener_) {
-    GtkFileFilter* selected_filter =
-        gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
-    GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog));
-    int idx = g_slist_index(filters, selected_filter);
-    g_slist_free(filters);
-    listener_->FileSelected(path, idx + 1, PopParamsForDialog(dialog));
-  }
-  gtk_widget_destroy(dialog);
-}
-
-void SelectFileDialogImpl::MultiFilesSelected(GtkWidget* dialog,
-    const std::vector<FilePath>& files) {
-  *last_opened_path_ = files[0].DirName();
-
-  if (listener_)
-    listener_->MultiFilesSelected(files, PopParamsForDialog(dialog));
-  gtk_widget_destroy(dialog);
-}
-
-void SelectFileDialogImpl::FileNotSelected(GtkWidget* dialog) {
-  void* params = PopParamsForDialog(dialog);
-  if (listener_)
-    listener_->FileSelectionCanceled(params);
-  gtk_widget_destroy(dialog);
-}
-
-bool SelectFileDialogImpl::CallDirectoryExistsOnUIThread(const FilePath& path) {
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
-  return file_util::DirectoryExists(path);
-}
-
-GtkWidget* SelectFileDialogImpl::CreateFileOpenHelper(
-    const std::string& title,
-    const FilePath& default_path,
-    gfx::NativeWindow parent) {
-  GtkWidget* dialog =
-      gtk_file_chooser_dialog_new(title.c_str(), parent,
-                                  GTK_FILE_CHOOSER_ACTION_OPEN,
-                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                  NULL);
-  AddFilters(GTK_FILE_CHOOSER(dialog));
-
-  if (!default_path.empty()) {
-    if (CallDirectoryExistsOnUIThread(default_path)) {
-      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
-                                          default_path.value().c_str());
-    } else {
-      // If the file doesn't exist, this will just switch to the correct
-      // directory. That's good enough.
-      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
-                                    default_path.value().c_str());
-    }
-  } else if (!last_opened_path_->empty()) {
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
-                                        last_opened_path_->value().c_str());
-  }
-  return dialog;
-}
-
-GtkWidget* SelectFileDialogImpl::CreateSelectFolderDialog(
-    const std::string& title,
-    const FilePath& default_path,
-    gfx::NativeWindow parent) {
-  std::string title_string = !title.empty() ? title :
-        l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE);
-
-  GtkWidget* dialog =
-      gtk_file_chooser_dialog_new(title_string.c_str(), parent,
-                                  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
-                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                  NULL);
-
-  if (!default_path.empty()) {
-    gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
-                                  default_path.value().c_str());
-  } else if (!last_opened_path_->empty()) {
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
-                                        last_opened_path_->value().c_str());
-  }
-  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
-  g_signal_connect(dialog, "response",
-                   G_CALLBACK(OnSelectSingleFolderDialogResponseThunk), this);
-  return dialog;
-}
-
-GtkWidget* SelectFileDialogImpl::CreateFileOpenDialog(
-    const std::string& title,
-    const FilePath& default_path,
-    gfx::NativeWindow parent) {
-  std::string title_string = !title.empty() ? title :
-        l10n_util::GetStringUTF8(IDS_OPEN_FILE_DIALOG_TITLE);
-  GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent);
-  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
-  g_signal_connect(dialog, "response",
-                   G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this);
-  return dialog;
-}
-
-GtkWidget* SelectFileDialogImpl::CreateMultiFileOpenDialog(
-    const std::string& title,
-    const FilePath& default_path,
-    gfx::NativeWindow parent) {
-  std::string title_string = !title.empty() ? title :
-        l10n_util::GetStringUTF8(IDS_OPEN_FILES_DIALOG_TITLE);
-  GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent);
-  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
-  g_signal_connect(dialog, "response",
-                   G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this);
-  return dialog;
-}
-
-GtkWidget* SelectFileDialogImpl::CreateSaveAsDialog(const std::string& title,
-    const FilePath& default_path, gfx::NativeWindow parent) {
-  std::string title_string = !title.empty() ? title :
-        l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE);
-
-  GtkWidget* dialog =
-      gtk_file_chooser_dialog_new(title_string.c_str(), parent,
-                                  GTK_FILE_CHOOSER_ACTION_SAVE,
-                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
-                                  NULL);
-
-  AddFilters(GTK_FILE_CHOOSER(dialog));
-  if (!default_path.empty()) {
-    // Since the file may not already exist, we use
-    // set_current_folder() followed by set_current_name(), as per the
-    // recommendation of the GTK docs.
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
-        default_path.DirName().value().c_str());
-    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
-        default_path.BaseName().value().c_str());
-  } else if (!last_saved_path_->empty()) {
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
-                                        last_saved_path_->value().c_str());
-  }
-  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
-  gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog),
-                                                 TRUE);
-  g_signal_connect(dialog, "response",
-                   G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this);
-  return dialog;
-}
-
-void* SelectFileDialogImpl::PopParamsForDialog(GtkWidget* dialog) {
-  std::map<GtkWidget*, void*>::iterator iter = params_map_.find(dialog);
-  DCHECK(iter != params_map_.end());
-  void* params = iter->second;
-  params_map_.erase(iter);
-  return params;
-}
-
-void SelectFileDialogImpl::FileDialogDestroyed(GtkWidget* dialog) {
-  dialogs_.erase(dialog);
-
-  // Parent may be NULL in a few cases: 1) on shutdown when
-  // AllBrowsersClosed() trigger this handler after all the browser
-  // windows got destroyed, or 2) when the parent tab has been opened by
-  // 'Open Link in New Tab' context menu on a downloadable item and
-  // the tab has no content (see the comment in SelectFile as well).
-  GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog));
-  if (!parent)
-    return;
-  std::set<GtkWindow*>::iterator iter = parents_.find(parent);
-  if (iter != parents_.end())
-    parents_.erase(iter);
-  else
-    NOTREACHED();
-}
-
-bool SelectFileDialogImpl::IsCancelResponse(gint response_id) {
-  bool is_cancel = response_id == GTK_RESPONSE_CANCEL ||
-                   response_id == GTK_RESPONSE_DELETE_EVENT;
-  if (is_cancel)
-    return true;
-
-  DCHECK(response_id == GTK_RESPONSE_ACCEPT);
-  return false;
-}
-
-void SelectFileDialogImpl::SelectSingleFileHelper(GtkWidget* dialog,
-    gint response_id,
-    bool allow_folder) {
-  if (IsCancelResponse(response_id)) {
-    FileNotSelected(dialog);
-    return;
-  }
-
-  gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
-  if (!filename) {
-    FileNotSelected(dialog);
-    return;
-  }
-
-  FilePath path(filename);
-  g_free(filename);
-
-  if (allow_folder) {
-    FileSelected(dialog, path);
-    return;
-  }
-
-  if (CallDirectoryExistsOnUIThread(path))
-    FileNotSelected(dialog);
-  else
-    FileSelected(dialog, path);
-}
-
-void SelectFileDialogImpl::OnSelectSingleFileDialogResponse(
-    GtkWidget* dialog, gint response_id) {
-  return SelectSingleFileHelper(dialog, response_id, false);
-}
-
-void SelectFileDialogImpl::OnSelectSingleFolderDialogResponse(
-    GtkWidget* dialog, gint response_id) {
-  return SelectSingleFileHelper(dialog, response_id, true);
-}
-
-void SelectFileDialogImpl::OnSelectMultiFileDialogResponse(
-    GtkWidget* dialog, gint response_id) {
-  if (IsCancelResponse(response_id)) {
-    FileNotSelected(dialog);
-    return;
-  }
-
-  GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
-  if (!filenames) {
-    FileNotSelected(dialog);
-    return;
-  }
-
-  std::vector<FilePath> filenames_fp;
-  for (GSList* iter = filenames; iter != NULL; iter = g_slist_next(iter)) {
-    FilePath path(static_cast<char*>(iter->data));
-    g_free(iter->data);
-    if (CallDirectoryExistsOnUIThread(path))
-      continue;
-    filenames_fp.push_back(path);
-  }
-  g_slist_free(filenames);
-
-  if (filenames_fp.empty()) {
-    FileNotSelected(dialog);
-    return;
-  }
-  MultiFilesSelected(dialog, filenames_fp);
-}
-
-void SelectFileDialogImpl::OnFileChooserDestroy(GtkWidget* dialog) {
-  FileDialogDestroyed(dialog);
-}
-
-void SelectFileDialogImpl::OnUpdatePreview(GtkWidget* chooser) {
-  gchar* filename = gtk_file_chooser_get_preview_filename(
-      GTK_FILE_CHOOSER(chooser));
-  if (!filename)
-    return;
-  // This will preserve the image's aspect ratio.
-  GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth,
-                                                       kPreviewHeight, NULL);
-  g_free(filename);
-  if (pixbuf) {
-    gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf);
-    g_object_unref(pixbuf);
-  }
-  gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser),
-                                             pixbuf ? TRUE : FALSE);
-}
diff --git a/chrome/browser/gtk/download_in_progress_dialog_gtk.cc b/chrome/browser/gtk/download_in_progress_dialog_gtk.cc
deleted file mode 100644
index 0aa0455..0000000
--- a/chrome/browser/gtk/download_in_progress_dialog_gtk.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/download_in_progress_dialog_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/string_number_conversions.h"
-#include "base/string16.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-DownloadInProgressDialogGtk::DownloadInProgressDialogGtk(Browser* browser)
-    : browser_(browser) {
-  int download_count = browser->profile()->GetDownloadManager()->
-      in_progress_count();
-
-  std::string warning_text;
-  std::string explanation_text;
-  std::string ok_button_text;
-  std::string cancel_button_text;
-  string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
-  if (download_count == 1) {
-    warning_text =
-        l10n_util::GetStringFUTF8(IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_WARNING,
-                                  product_name);
-    explanation_text =
-        l10n_util::GetStringFUTF8(
-            IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_EXPLANATION,
-            product_name);
-    ok_button_text = l10n_util::GetStringUTF8(
-        IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_OK_BUTTON_LABEL);
-    cancel_button_text = l10n_util::GetStringUTF8(
-        IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL);
-  } else {
-    warning_text =
-        l10n_util::GetStringFUTF8(IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_WARNING,
-                                  product_name,
-                                  base::IntToString16(download_count));
-    explanation_text =
-        l10n_util::GetStringFUTF8(
-            IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_EXPLANATION, product_name);
-    ok_button_text = l10n_util::GetStringUTF8(
-        IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_OK_BUTTON_LABEL);
-    cancel_button_text = l10n_util::GetStringUTF8(
-        IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL);
-  }
-
-  GtkWidget* dialog = gtk_message_dialog_new(
-      browser_->window()->GetNativeHandle(),
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
-      GTK_MESSAGE_QUESTION,
-      GTK_BUTTONS_NONE,
-      "%s",
-      warning_text.c_str());
-  gtk_util::AddButtonToDialog(dialog,
-      cancel_button_text.c_str(),
-      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
-  gtk_util::AddButtonToDialog(dialog,
-      ok_button_text.c_str(),
-      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
-
-  gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
-                                           "%s",
-                                           explanation_text.c_str());
-
-  g_signal_connect(dialog, "response", G_CALLBACK(OnResponseThunk), this);
-
-  gtk_widget_show_all(dialog);
-}
-
-void DownloadInProgressDialogGtk::OnResponse(GtkWidget* widget,
-                                             int response) {
-  gtk_widget_destroy(widget);
-  browser_->InProgressDownloadResponse(response == GTK_RESPONSE_ACCEPT);
-  delete this;
-}
diff --git a/chrome/browser/gtk/download_in_progress_dialog_gtk.h b/chrome/browser/gtk/download_in_progress_dialog_gtk.h
deleted file mode 100644
index 86f736a..0000000
--- a/chrome/browser/gtk/download_in_progress_dialog_gtk.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_DOWNLOAD_IN_PROGRESS_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_DOWNLOAD_IN_PROGRESS_DIALOG_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-
-class Browser;
-
-typedef struct _GtkWidget GtkWidget;
-
-class DownloadInProgressDialogGtk {
- public:
-  explicit DownloadInProgressDialogGtk(Browser* browser);
-
- protected:
-  virtual ~DownloadInProgressDialogGtk() {}
-
- private:
-  CHROMEGTK_CALLBACK_1(DownloadInProgressDialogGtk, void, OnResponse, int);
-
-  Browser* browser_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloadInProgressDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_DOWNLOAD_IN_PROGRESS_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc
deleted file mode 100644
index b0acf44..0000000
--- a/chrome/browser/gtk/download_item_gtk.cc
+++ /dev/null
@@ -1,879 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/download_item_gtk.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/metrics/histogram.h"
-#include "base/string_util.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_item.h"
-#include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/download/download_shelf.h"
-#include "chrome/browser/download/download_util.h"
-#include "chrome/browser/gtk/custom_drag.h"
-#include "chrome/browser/gtk/download_shelf_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/nine_box.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/color_utils.h"
-#include "gfx/font.h"
-#include "gfx/skia_utils_gtk.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-// The width of the |menu_button_| widget. It has to be at least as wide as the
-// bitmap that we use to draw it, i.e. 16, but can be more.
-const int kMenuButtonWidth = 16;
-
-// Padding on left and right of items in dangerous download prompt.
-const int kDangerousElementPadding = 3;
-
-// Amount of space we allot to showing the filename. If the filename is too wide
-// it will be elided.
-const int kTextWidth = 140;
-
-// We only cap the size of the tooltip so we don't crash.
-const int kTooltipMaxWidth = 1000;
-
-// The minimum width we will ever draw the download item. Used as a lower bound
-// during animation. This number comes from the width of the images used to
-// make the download item.
-const int kMinDownloadItemWidth = download_util::kSmallProgressIconSize;
-
-// New download item animation speed in milliseconds.
-const int kNewItemAnimationDurationMs = 800;
-
-// How long the 'download complete' animation should last for.
-const int kCompleteAnimationDurationMs = 2500;
-
-// Width of the body area of the download item.
-// TODO(estade): get rid of the fudge factor. http://crbug.com/18692
-const int kBodyWidth = kTextWidth + 50 + download_util::kSmallProgressIconSize;
-
-// The font size of the text, and that size rounded down to the nearest integer
-// for the size of the arrow in GTK theme mode.
-const double kTextSize = 13.4;  // 13.4px == 10pt @ 96dpi
-
-// Darken light-on-dark download status text by 20% before drawing, thus
-// creating a "muted" version of title text for both dark-on-light and
-// light-on-dark themes.
-static const double kDownloadItemLuminanceMod = 0.8;
-
-}  // namespace
-
-// DownloadShelfContextMenuGtk -------------------------------------------------
-
-class DownloadShelfContextMenuGtk : public DownloadShelfContextMenu,
-                                    public MenuGtk::Delegate {
- public:
-  // The constructor creates the menu and immediately pops it up.
-  // |model| is the download item model associated with this context menu,
-  // |widget| is the button that popped up this context menu, and |e| is
-  // the button press event that caused this menu to be created.
-  DownloadShelfContextMenuGtk(BaseDownloadItemModel* model,
-                              DownloadItemGtk* download_item)
-      : DownloadShelfContextMenu(model),
-        download_item_(download_item) {
-  }
-
-  ~DownloadShelfContextMenuGtk() {
-  }
-
-  void Popup(GtkWidget* widget, GdkEvent* event) {
-    // Create the menu if we have not created it yet or we created it for
-    // an in-progress download that has since completed.
-    if (download_->state() == DownloadItem::COMPLETE)
-      menu_.reset(new MenuGtk(this, GetFinishedMenuModel()));
-    else
-      menu_.reset(new MenuGtk(this, GetInProgressMenuModel()));
-    menu_->Popup(widget, event);
-  }
-
-  // MenuGtk::Delegate implementation:
-  virtual void StoppedShowing() {
-    download_item_->menu_showing_ = false;
-    gtk_widget_queue_draw(download_item_->menu_button_);
-  }
-
-  virtual GtkWidget* GetImageForCommandId(int command_id) const {
-    const char* stock = NULL;
-    switch (command_id) {
-      case SHOW_IN_FOLDER:
-      case OPEN_WHEN_COMPLETE:
-        stock = GTK_STOCK_OPEN;
-        break;
-
-      case CANCEL:
-        stock = GTK_STOCK_CANCEL;
-        break;
-
-      case ALWAYS_OPEN_TYPE:
-      case TOGGLE_PAUSE:
-        stock = NULL;
-    }
-
-    return stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU) : NULL;
-  }
-
- private:
-  // The menu we show on Popup(). We keep a pointer to it for a couple reasons:
-  //  * we don't want to have to recreate the menu every time it's popped up.
-  //  * we have to keep it in scope for longer than the duration of Popup(), or
-  //    completing the user-selected action races against the menu's
-  //    destruction.
-  scoped_ptr<MenuGtk> menu_;
-
-  // The download item that created us.
-  DownloadItemGtk* download_item_;
-};
-
-// DownloadItemGtk -------------------------------------------------------------
-
-NineBox* DownloadItemGtk::body_nine_box_normal_ = NULL;
-NineBox* DownloadItemGtk::body_nine_box_prelight_ = NULL;
-NineBox* DownloadItemGtk::body_nine_box_active_ = NULL;
-
-NineBox* DownloadItemGtk::menu_nine_box_normal_ = NULL;
-NineBox* DownloadItemGtk::menu_nine_box_prelight_ = NULL;
-NineBox* DownloadItemGtk::menu_nine_box_active_ = NULL;
-
-NineBox* DownloadItemGtk::dangerous_nine_box_ = NULL;
-
-DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf,
-                                 BaseDownloadItemModel* download_model)
-    : parent_shelf_(parent_shelf),
-      arrow_(NULL),
-      menu_showing_(false),
-      theme_provider_(GtkThemeProvider::GetFrom(
-                          parent_shelf->browser()->profile())),
-      progress_angle_(download_util::kStartAngleDegrees),
-      download_model_(download_model),
-      dangerous_prompt_(NULL),
-      dangerous_label_(NULL),
-      icon_small_(NULL),
-      icon_large_(NULL),
-      creation_time_(base::Time::Now()) {
-  LoadIcon();
-
-  body_.Own(gtk_button_new());
-  gtk_widget_set_app_paintable(body_.get(), TRUE);
-  UpdateTooltip();
-
-  g_signal_connect(body_.get(), "expose-event",
-                   G_CALLBACK(OnExposeThunk), this);
-  g_signal_connect(body_.get(), "clicked",
-                   G_CALLBACK(OnClickThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(body_.get(), GTK_CAN_FOCUS);
-  // Remove internal padding on the button.
-  GtkRcStyle* no_padding_style = gtk_rc_style_new();
-  no_padding_style->xthickness = 0;
-  no_padding_style->ythickness = 0;
-  gtk_widget_modify_style(body_.get(), no_padding_style);
-  g_object_unref(no_padding_style);
-
-  name_label_ = gtk_label_new(NULL);
-
-  UpdateNameLabel();
-
-  status_label_ = gtk_label_new(NULL);
-  g_signal_connect(status_label_, "destroy",
-                   G_CALLBACK(gtk_widget_destroyed), &status_label_);
-  // Left align and vertically center the labels.
-  gtk_misc_set_alignment(GTK_MISC(name_label_), 0, 0.5);
-  gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0.5);
-  // Until we switch to vector graphics, force the font size.
-  gtk_util::ForceFontSizePixels(name_label_, kTextSize);
-  gtk_util::ForceFontSizePixels(status_label_, kTextSize);
-
-  // Stack the labels on top of one another.
-  GtkWidget* text_stack = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(text_stack), name_label_, TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(text_stack), status_label_, FALSE, FALSE, 0);
-
-  // We use a GtkFixed because we don't want it to have its own window.
-  // This choice of widget is not critically important though.
-  progress_area_.Own(gtk_fixed_new());
-  gtk_widget_set_size_request(progress_area_.get(),
-      download_util::kSmallProgressIconSize,
-      download_util::kSmallProgressIconSize);
-  gtk_widget_set_app_paintable(progress_area_.get(), TRUE);
-  g_signal_connect(progress_area_.get(), "expose-event",
-                   G_CALLBACK(OnProgressAreaExposeThunk), this);
-
-  // Put the download progress icon on the left of the labels.
-  GtkWidget* body_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(body_.get()), body_hbox);
-  gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_.get(), FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(body_hbox), text_stack, TRUE, TRUE, 0);
-
-  menu_button_ = gtk_button_new();
-  gtk_widget_set_app_paintable(menu_button_, TRUE);
-  GTK_WIDGET_UNSET_FLAGS(menu_button_, GTK_CAN_FOCUS);
-  g_signal_connect(menu_button_, "expose-event",
-                   G_CALLBACK(OnExposeThunk), this);
-  g_signal_connect(menu_button_, "button-press-event",
-                   G_CALLBACK(OnMenuButtonPressEventThunk), this);
-  g_object_set_data(G_OBJECT(menu_button_), "left-align-popup",
-                    reinterpret_cast<void*>(true));
-
-  GtkWidget* shelf_hbox = parent_shelf->GetHBox();
-  hbox_.Own(gtk_hbox_new(FALSE, 0));
-  g_signal_connect(hbox_.get(), "expose-event",
-                   G_CALLBACK(OnHboxExposeThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), body_.get(), FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), menu_button_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(shelf_hbox), hbox_.get(), FALSE, FALSE, 0);
-  // Insert as the leftmost item.
-  gtk_box_reorder_child(GTK_BOX(shelf_hbox), hbox_.get(), 0);
-
-  get_download()->AddObserver(this);
-
-  new_item_animation_.reset(new ui::SlideAnimation(this));
-  new_item_animation_->SetSlideDuration(kNewItemAnimationDurationMs);
-  gtk_widget_show_all(hbox_.get());
-
-  if (IsDangerous()) {
-    // Hide the download item components for now.
-    gtk_widget_hide(body_.get());
-    gtk_widget_hide(menu_button_);
-
-    // Create an hbox to hold it all.
-    dangerous_hbox_ = gtk_hbox_new(FALSE, kDangerousElementPadding);
-
-    // Add padding at the beginning and end. The hbox will add padding between
-    // the empty labels and the other elements.
-    GtkWidget* empty_label_a = gtk_label_new(NULL);
-    GtkWidget* empty_label_b = gtk_label_new(NULL);
-    gtk_box_pack_start(GTK_BOX(dangerous_hbox_), empty_label_a,
-                       FALSE, FALSE, 0);
-    gtk_box_pack_end(GTK_BOX(dangerous_hbox_), empty_label_b,
-                     FALSE, FALSE, 0);
-
-    // Create the warning icon.
-    dangerous_image_ = gtk_image_new();
-    gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_image_,
-                       FALSE, FALSE, 0);
-
-    dangerous_label_ = gtk_label_new(NULL);
-    // We pass TRUE, TRUE so that the label will condense to less than its
-    // request when the animation is going on.
-    gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_label_,
-                       TRUE, TRUE, 0);
-
-    // Create the nevermind button.
-    GtkWidget* dangerous_decline = gtk_button_new_with_label(
-        l10n_util::GetStringUTF8(IDS_DISCARD_DOWNLOAD).c_str());
-    g_signal_connect(dangerous_decline, "clicked",
-                     G_CALLBACK(OnDangerousDeclineThunk), this);
-    gtk_util::CenterWidgetInHBox(dangerous_hbox_, dangerous_decline, false, 0);
-
-    // Create the ok button.
-    GtkWidget* dangerous_accept = gtk_button_new_with_label(
-        l10n_util::GetStringUTF8(
-            download_model->download()->is_extension_install() ?
-                IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_SAVE_DOWNLOAD).c_str());
-    g_signal_connect(dangerous_accept, "clicked",
-                     G_CALLBACK(OnDangerousAcceptThunk), this);
-    gtk_util::CenterWidgetInHBox(dangerous_hbox_, dangerous_accept, false, 0);
-
-    // Put it in an alignment so that padding will be added on the left and
-    // right.
-    dangerous_prompt_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-    gtk_alignment_set_padding(GTK_ALIGNMENT(dangerous_prompt_),
-        0, 0, kDangerousElementPadding, kDangerousElementPadding);
-    gtk_container_add(GTK_CONTAINER(dangerous_prompt_), dangerous_hbox_);
-    gtk_box_pack_start(GTK_BOX(hbox_.get()), dangerous_prompt_, FALSE, FALSE,
-                       0);
-    gtk_widget_set_app_paintable(dangerous_prompt_, TRUE);
-    gtk_widget_set_redraw_on_allocate(dangerous_prompt_, TRUE);
-    g_signal_connect(dangerous_prompt_, "expose-event",
-                     G_CALLBACK(OnDangerousPromptExposeThunk), this);
-    gtk_widget_show_all(dangerous_prompt_);
-  }
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_->InitThemesFor(this);
-
-  // Set the initial width of the widget to be animated.
-  if (IsDangerous()) {
-    gtk_widget_set_size_request(dangerous_hbox_,
-                                dangerous_hbox_start_width_, -1);
-  } else {
-    gtk_widget_set_size_request(body_.get(), kMinDownloadItemWidth, -1);
-  }
-
-  new_item_animation_->Show();
-}
-
-DownloadItemGtk::~DownloadItemGtk() {
-  icon_consumer_.CancelAllRequests();
-  StopDownloadProgress();
-  get_download()->RemoveObserver(this);
-
-  // We may free some shelf space for showing more download items.
-  parent_shelf_->MaybeShowMoreDownloadItems();
-
-  hbox_.Destroy();
-  progress_area_.Destroy();
-  body_.Destroy();
-
-  // Make sure this widget has been destroyed and the pointer we hold to it
-  // NULLed.
-  DCHECK(!status_label_);
-}
-
-void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) {
-  DCHECK_EQ(download, get_download());
-
-  if (dangerous_prompt_ != NULL &&
-      download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) {
-    // We have been approved.
-    gtk_widget_show_all(hbox_.get());
-    gtk_widget_destroy(dangerous_prompt_);
-    gtk_widget_set_size_request(body_.get(), kBodyWidth, -1);
-    dangerous_prompt_ = NULL;
-
-    // We may free some shelf space for showing more download items.
-    parent_shelf_->MaybeShowMoreDownloadItems();
-  }
-
-  if (download->GetUserVerifiedFilePath() != icon_filepath_) {
-    // Turns out the file path is "unconfirmed %d.crdownload" for dangerous
-    // downloads. When the download is confirmed, the file is renamed on
-    // another thread, so reload the icon if the download filename changes.
-    LoadIcon();
-
-    UpdateTooltip();
-  }
-
-  switch (download->state()) {
-    case DownloadItem::REMOVING:
-      parent_shelf_->RemoveDownloadItem(this);  // This will delete us!
-      return;
-    case DownloadItem::CANCELLED:
-      StopDownloadProgress();
-      gtk_widget_queue_draw(progress_area_.get());
-      break;
-    case DownloadItem::COMPLETE:
-      if (download->auto_opened()) {
-        parent_shelf_->RemoveDownloadItem(this);  // This will delete us!
-        return;
-      }
-      StopDownloadProgress();
-
-      // Set up the widget as a drag source.
-      DownloadItemDrag::SetSource(body_.get(), get_download(), icon_large_);
-
-      complete_animation_.reset(new ui::SlideAnimation(this));
-      complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs);
-      complete_animation_->SetTweenType(ui::Tween::LINEAR);
-      complete_animation_->Show();
-      break;
-    case DownloadItem::IN_PROGRESS:
-      get_download()->is_paused() ?
-          StopDownloadProgress() : StartDownloadProgress();
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  // Now update the status label. We may have already removed it; if so, we
-  // do nothing.
-  if (!status_label_) {
-    return;
-  }
-
-  status_text_ = UTF16ToUTF8(download_model_->GetStatusText());
-  // Remove the status text label.
-  if (status_text_.empty()) {
-    gtk_widget_destroy(status_label_);
-    return;
-  }
-
-  UpdateStatusLabel(status_text_);
-}
-
-void DownloadItemGtk::AnimationProgressed(const ui::Animation* animation) {
-  if (animation == complete_animation_.get()) {
-    gtk_widget_queue_draw(progress_area_.get());
-  } else {
-    if (IsDangerous()) {
-      int progress = static_cast<int>((dangerous_hbox_full_width_ -
-                                       dangerous_hbox_start_width_) *
-                                      new_item_animation_->GetCurrentValue());
-      int showing_width = dangerous_hbox_start_width_ + progress;
-      gtk_widget_set_size_request(dangerous_hbox_, showing_width, -1);
-    } else {
-      DCHECK(animation == new_item_animation_.get());
-      int showing_width = std::max(kMinDownloadItemWidth,
-          static_cast<int>(kBodyWidth *
-                           new_item_animation_->GetCurrentValue()));
-      gtk_widget_set_size_request(body_.get(), showing_width, -1);
-    }
-  }
-}
-
-void DownloadItemGtk::Observe(NotificationType type,
-                              const NotificationSource& source,
-                              const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    // Our GtkArrow is only visible in gtk mode. Otherwise, we let the custom
-    // rendering code do whatever it wants.
-    if (theme_provider_->UseGtkTheme()) {
-      if (!arrow_) {
-        arrow_ = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
-        gtk_widget_set_size_request(arrow_,
-                                    static_cast<int>(kTextSize),
-                                    static_cast<int>(kTextSize));
-        gtk_container_add(GTK_CONTAINER(menu_button_), arrow_);
-      }
-
-      gtk_widget_set_size_request(menu_button_, -1, -1);
-      gtk_widget_show(arrow_);
-    } else {
-      InitNineBoxes();
-
-      gtk_widget_set_size_request(menu_button_, kMenuButtonWidth, 0);
-
-      if (arrow_)
-        gtk_widget_hide(arrow_);
-    }
-
-    UpdateNameLabel();
-    UpdateStatusLabel(status_text_);
-    UpdateDangerWarning();
-  }
-}
-
-DownloadItem* DownloadItemGtk::get_download() {
-  return download_model_->download();
-}
-
-bool DownloadItemGtk::IsDangerous() {
-  return get_download()->safety_state() == DownloadItem::DANGEROUS;
-}
-
-// Download progress animation functions.
-
-void DownloadItemGtk::UpdateDownloadProgress() {
-  progress_angle_ = (progress_angle_ +
-                     download_util::kUnknownIncrementDegrees) %
-                    download_util::kMaxDegrees;
-  gtk_widget_queue_draw(progress_area_.get());
-}
-
-void DownloadItemGtk::StartDownloadProgress() {
-  if (progress_timer_.IsRunning())
-    return;
-  progress_timer_.Start(
-      base::TimeDelta::FromMilliseconds(download_util::kProgressRateMs), this,
-      &DownloadItemGtk::UpdateDownloadProgress);
-}
-
-void DownloadItemGtk::StopDownloadProgress() {
-  progress_timer_.Stop();
-}
-
-// Icon loading functions.
-
-void DownloadItemGtk::OnLoadSmallIconComplete(IconManager::Handle handle,
-                                              SkBitmap* icon_bitmap) {
-  icon_small_ = icon_bitmap;
-  gtk_widget_queue_draw(progress_area_.get());
-}
-
-void DownloadItemGtk::OnLoadLargeIconComplete(IconManager::Handle handle,
-                                              SkBitmap* icon_bitmap) {
-  icon_large_ = icon_bitmap;
-  DownloadItemDrag::SetSource(body_.get(), get_download(), icon_large_);
-}
-
-void DownloadItemGtk::LoadIcon() {
-  icon_consumer_.CancelAllRequests();
-  IconManager* im = g_browser_process->icon_manager();
-  icon_filepath_ = get_download()->GetUserVerifiedFilePath();
-  im->LoadIcon(icon_filepath_,
-               IconLoader::SMALL, &icon_consumer_,
-               NewCallback(this, &DownloadItemGtk::OnLoadSmallIconComplete));
-  im->LoadIcon(icon_filepath_,
-               IconLoader::LARGE, &icon_consumer_,
-               NewCallback(this, &DownloadItemGtk::OnLoadLargeIconComplete));
-}
-
-void DownloadItemGtk::UpdateTooltip() {
-  string16 elided_filename = gfx::ElideFilename(
-      get_download()->GetFileNameToReportUser(),
-      gfx::Font(), kTooltipMaxWidth);
-  gtk_widget_set_tooltip_text(body_.get(),
-                              UTF16ToUTF8(elided_filename).c_str());
-}
-
-void DownloadItemGtk::UpdateNameLabel() {
-  // TODO(estade): This is at best an educated guess, since we don't actually
-  // use gfx::Font() to draw the text. This is why we need to add so
-  // much padding when we set the size request. We need to either use gfx::Font
-  // or somehow extend TextElider.
-  string16 elided_filename = gfx::ElideFilename(
-      get_download()->GetFileNameToReportUser(),
-      gfx::Font(), kTextWidth);
-
-  GdkColor color = theme_provider_->GetGdkColor(
-      BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-  gtk_util::SetLabelColor(name_label_, theme_provider_->UseGtkTheme() ?
-                                       NULL : &color);
-  gtk_label_set_text(GTK_LABEL(name_label_),
-                     UTF16ToUTF8(elided_filename).c_str());
-}
-
-void DownloadItemGtk::UpdateStatusLabel(const std::string& status_text) {
-  if (!status_label_)
-    return;
-
-  GdkColor text_color;
-  if (!theme_provider_->UseGtkTheme()) {
-    SkColor color = theme_provider_->GetColor(
-        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-    if (color_utils::RelativeLuminance(color) > 0.5) {
-      color = SkColorSetRGB(
-          static_cast<int>(kDownloadItemLuminanceMod *
-                           SkColorGetR(color)),
-          static_cast<int>(kDownloadItemLuminanceMod *
-                           SkColorGetG(color)),
-          static_cast<int>(kDownloadItemLuminanceMod *
-                           SkColorGetB(color)));
-    }
-
-    // Lighten the color by blending it with the download item body color. These
-    // values are taken from IDR_DOWNLOAD_BUTTON.
-    SkColor blend_color = SkColorSetRGB(241, 245, 250);
-    text_color = gfx::SkColorToGdkColor(
-        color_utils::AlphaBlend(blend_color, color, 77));
-  }
-
-  gtk_util::SetLabelColor(status_label_, theme_provider_->UseGtkTheme() ?
-                                        NULL : &text_color);
-  gtk_label_set_text(GTK_LABEL(status_label_), status_text.c_str());
-}
-
-void DownloadItemGtk::UpdateDangerWarning() {
-  if (dangerous_prompt_) {
-    // We create |dangerous_warning| as a wide string so we can more easily
-    // calculate its length in characters.
-    string16 dangerous_warning;
-    if (get_download()->is_extension_install()) {
-      dangerous_warning =
-          l10n_util::GetStringUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
-    } else {
-      string16 elided_filename = gfx::ElideFilename(
-          get_download()->target_name(), gfx::Font(), kTextWidth);
-
-      dangerous_warning =
-          l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
-                                     elided_filename);
-    }
-
-    if (theme_provider_->UseGtkTheme()) {
-      gtk_image_set_from_stock(GTK_IMAGE(dangerous_image_),
-          GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
-
-      gtk_util::SetLabelColor(dangerous_label_, NULL);
-    } else {
-      // Set the warning icon.
-      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-      GdkPixbuf* download_pixbuf = rb.GetPixbufNamed(IDR_WARNING);
-      gtk_image_set_from_pixbuf(GTK_IMAGE(dangerous_image_), download_pixbuf);
-
-      GdkColor color = theme_provider_->GetGdkColor(
-          BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-      gtk_util::SetLabelColor(dangerous_label_, &color);
-    }
-
-    gtk_label_set_text(GTK_LABEL(dangerous_label_),
-                       UTF16ToUTF8(dangerous_warning).c_str());
-
-    // Until we switch to vector graphics, force the font size.
-    gtk_util::ForceFontSizePixels(dangerous_label_, kTextSize);
-
-    // Get the label width when displaying in one line, and reduce it to 60% to
-    // wrap the label into two lines.
-    gtk_widget_set_size_request(dangerous_label_, -1, -1);
-    gtk_label_set_line_wrap(GTK_LABEL(dangerous_label_), FALSE);
-
-    GtkRequisition req;
-    gtk_widget_size_request(dangerous_label_, &req);
-
-    gint label_width = req.width * 6 / 10;
-    gtk_label_set_line_wrap(GTK_LABEL(dangerous_label_), TRUE);
-    gtk_widget_set_size_request(dangerous_label_, label_width, -1);
-
-    // The width will depend on the text. We must do this each time we possibly
-    // change the label above.
-    gtk_widget_size_request(dangerous_hbox_, &req);
-    dangerous_hbox_full_width_ = req.width;
-    dangerous_hbox_start_width_ = dangerous_hbox_full_width_ - label_width;
-  }
-}
-
-// static
-void DownloadItemGtk::InitNineBoxes() {
-  if (body_nine_box_normal_)
-    return;
-
-  body_nine_box_normal_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_LEFT_TOP,
-      IDR_DOWNLOAD_BUTTON_CENTER_TOP,
-      IDR_DOWNLOAD_BUTTON_RIGHT_TOP,
-      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE,
-      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE,
-      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE,
-      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM,
-      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM,
-      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM);
-
-  body_nine_box_prelight_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_LEFT_TOP_H,
-      IDR_DOWNLOAD_BUTTON_CENTER_TOP_H,
-      IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H,
-      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_H,
-      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_H,
-      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_H,
-      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_H,
-      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H,
-      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_H);
-
-  body_nine_box_active_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_LEFT_TOP_P,
-      IDR_DOWNLOAD_BUTTON_CENTER_TOP_P,
-      IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P,
-      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_P,
-      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_P,
-      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_P,
-      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_P,
-      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P,
-      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_P);
-
-  menu_nine_box_normal_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_MENU_TOP, 0, 0,
-      IDR_DOWNLOAD_BUTTON_MENU_MIDDLE, 0, 0,
-      IDR_DOWNLOAD_BUTTON_MENU_BOTTOM, 0, 0);
-
-  menu_nine_box_prelight_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_MENU_TOP_H, 0, 0,
-      IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_H, 0, 0,
-      IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_H, 0, 0);
-
-  menu_nine_box_active_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_MENU_TOP_P, 0, 0,
-      IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P, 0, 0,
-      IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P, 0, 0);
-
-  dangerous_nine_box_ = new NineBox(
-      IDR_DOWNLOAD_BUTTON_LEFT_TOP,
-      IDR_DOWNLOAD_BUTTON_CENTER_TOP,
-      IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD,
-      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE,
-      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE,
-      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD,
-      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM,
-      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM,
-      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD);
-}
-
-gboolean DownloadItemGtk::OnHboxExpose(GtkWidget* widget, GdkEventExpose* e) {
-  if (theme_provider_->UseGtkTheme()) {
-    int border_width = GTK_CONTAINER(widget)->border_width;
-    int x = widget->allocation.x + border_width;
-    int y = widget->allocation.y + border_width;
-    int width = widget->allocation.width - border_width * 2;
-    int height = widget->allocation.height - border_width * 2;
-
-    if (IsDangerous()) {
-      // Draw a simple frame around the area when we're displaying the warning.
-      gtk_paint_shadow(widget->style, widget->window,
-                       static_cast<GtkStateType>(widget->state),
-                       static_cast<GtkShadowType>(GTK_SHADOW_OUT),
-                       &e->area, widget, "frame",
-                       x, y, width, height);
-    } else {
-      // Manually draw the GTK button border around the download item. We draw
-      // the left part of the button (the file), a divider, and then the right
-      // part of the button (the menu). We can't draw a button on top of each
-      // other (*cough*Clearlooks*cough*) so instead, to draw the left part of
-      // the button, we instruct GTK to draw the entire button...with a
-      // doctored clip rectangle to the left part of the button sans
-      // separator. We then repeat this for the right button.
-      GtkStyle* style = body_.get()->style;
-
-      GtkAllocation left_allocation = body_.get()->allocation;
-      GdkRectangle left_clip = {
-        left_allocation.x, left_allocation.y,
-        left_allocation.width, left_allocation.height
-      };
-
-      GtkAllocation right_allocation = menu_button_->allocation;
-      GdkRectangle right_clip = {
-        right_allocation.x, right_allocation.y,
-        right_allocation.width, right_allocation.height
-      };
-
-      GtkShadowType body_shadow =
-          GTK_BUTTON(body_.get())->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
-      gtk_paint_box(style, widget->window,
-                    static_cast<GtkStateType>(GTK_WIDGET_STATE(body_.get())),
-                    body_shadow,
-                    &left_clip, widget, "button",
-                    x, y, width, height);
-
-      GtkShadowType menu_shadow =
-          GTK_BUTTON(menu_button_)->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
-      gtk_paint_box(style, widget->window,
-                    static_cast<GtkStateType>(GTK_WIDGET_STATE(menu_button_)),
-                    menu_shadow,
-                    &right_clip, widget, "button",
-                    x, y, width, height);
-
-      // Doing the math to reverse engineer where we should be drawing our line
-      // is hard and relies on copying GTK internals, so instead steal the
-      // allocation of the gtk arrow which is close enough (and will error on
-      // the conservative side).
-      GtkAllocation arrow_allocation = arrow_->allocation;
-      gtk_paint_vline(style, widget->window,
-                      static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
-                      &e->area, widget, "button",
-                      arrow_allocation.y,
-                      arrow_allocation.y + arrow_allocation.height,
-                      left_allocation.x + left_allocation.width);
-    }
-  }
-  return FALSE;
-}
-
-gboolean DownloadItemGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e) {
-  if (!theme_provider_->UseGtkTheme()) {
-    bool is_body = widget == body_.get();
-
-    NineBox* nine_box = NULL;
-    // If true, this widget is |body_|, otherwise it is |menu_button_|.
-    if (GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT)
-      nine_box = is_body ? body_nine_box_prelight_ : menu_nine_box_prelight_;
-    else if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE)
-      nine_box = is_body ? body_nine_box_active_ : menu_nine_box_active_;
-    else
-      nine_box = is_body ? body_nine_box_normal_ : menu_nine_box_normal_;
-
-    // When the button is showing, we want to draw it as active. We have to do
-    // this explicitly because the button's state will be NORMAL while the menu
-    // has focus.
-    if (!is_body && menu_showing_)
-      nine_box = menu_nine_box_active_;
-
-    nine_box->RenderToWidget(widget);
-  }
-
-  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
-  if (child)
-    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
-
-  return TRUE;
-}
-
-void DownloadItemGtk::OnClick(GtkWidget* widget) {
-  UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
-                           base::Time::Now() - creation_time_);
-  get_download()->OpenDownload();
-}
-
-gboolean DownloadItemGtk::OnProgressAreaExpose(GtkWidget* widget,
-                                               GdkEventExpose* event) {
-  // Create a transparent canvas.
-  gfx::CanvasSkiaPaint canvas(event, false);
-  if (complete_animation_.get()) {
-    if (complete_animation_->is_animating()) {
-      download_util::PaintDownloadComplete(&canvas,
-          widget->allocation.x, widget->allocation.y,
-          complete_animation_->GetCurrentValue(),
-          download_util::SMALL);
-    }
-  } else if (get_download()->state() !=
-             DownloadItem::CANCELLED) {
-    download_util::PaintDownloadProgress(&canvas,
-        widget->allocation.x, widget->allocation.y,
-        progress_angle_,
-        get_download()->PercentComplete(),
-        download_util::SMALL);
-  }
-
-  // |icon_small_| may be NULL if it is still loading. If the file is an
-  // unrecognized type then we will get back a generic system icon. Hence
-  // there is no need to use the chromium-specific default download item icon.
-  if (icon_small_) {
-    const int offset = download_util::kSmallProgressIconOffset;
-    canvas.DrawBitmapInt(*icon_small_,
-        widget->allocation.x + offset, widget->allocation.y + offset);
-  }
-
-  return TRUE;
-}
-
-gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button,
-                                                 GdkEvent* event) {
-  // Stop any completion animation.
-  if (complete_animation_.get() && complete_animation_->is_animating())
-    complete_animation_->End();
-
-  if (event->type == GDK_BUTTON_PRESS) {
-    GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
-    if (event_button->button == 1) {
-      if (menu_.get() == NULL) {
-        menu_.reset(new DownloadShelfContextMenuGtk(
-            download_model_.get(), this));
-      }
-      menu_->Popup(button, event);
-      menu_showing_ = true;
-      gtk_widget_queue_draw(button);
-    }
-  }
-
-  return FALSE;
-}
-
-gboolean DownloadItemGtk::OnDangerousPromptExpose(GtkWidget* widget,
-                                                  GdkEventExpose* event) {
-  if (!theme_provider_->UseGtkTheme()) {
-    // The hbox renderer will take care of the border when in GTK mode.
-    dangerous_nine_box_->RenderToWidget(widget);
-  }
-  return FALSE;  // Continue propagation.
-}
-
-void DownloadItemGtk::OnDangerousAccept(GtkWidget* button) {
-  UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download",
-                           base::Time::Now() - creation_time_);
-  get_download()->DangerousDownloadValidated();
-}
-
-void DownloadItemGtk::OnDangerousDecline(GtkWidget* button) {
-  UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download",
-                           base::Time::Now() - creation_time_);
-  if (get_download()->state() == DownloadItem::IN_PROGRESS)
-    get_download()->Cancel(true);
-  get_download()->Remove(true);
-}
diff --git a/chrome/browser/gtk/download_item_gtk.h b/chrome/browser/gtk/download_item_gtk.h
deleted file mode 100644
index 56a0890..0000000
--- a/chrome/browser/gtk/download_item_gtk.h
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_DOWNLOAD_ITEM_GTK_H_
-#define CHROME_BROWSER_GTK_DOWNLOAD_ITEM_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "base/time.h"
-#include "chrome/browser/download/download_item.h"
-#include "chrome/browser/icon_manager.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "ui/base/animation/animation_delegate.h"
-
-class BaseDownloadItemModel;
-class DownloadShelfContextMenuGtk;
-class DownloadShelfGtk;
-class GtkThemeProvider;
-class NineBox;
-class SkBitmap;
-
-namespace ui {
-class SlideAnimation;
-}
-
-class DownloadItemGtk : public DownloadItem::Observer,
-                        public ui::AnimationDelegate,
-                        public NotificationObserver {
- public:
-  // DownloadItemGtk takes ownership of |download_item_model|.
-  DownloadItemGtk(DownloadShelfGtk* parent_shelf,
-                  BaseDownloadItemModel* download_item_model);
-
-  // Destroys all widgets belonging to this DownloadItemGtk.
-  ~DownloadItemGtk();
-
-  // DownloadItem::Observer implementation.
-  virtual void OnDownloadUpdated(DownloadItem* download);
-  virtual void OnDownloadFileCompleted(DownloadItem* download) { }
-  virtual void OnDownloadOpened(DownloadItem* download) { }
-
-  // ui::AnimationDelegate implementation.
-  virtual void AnimationProgressed(const ui::Animation* animation);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Called when the icon manager has finished loading the icon. We take
-  // ownership of |icon_bitmap|.
-  void OnLoadSmallIconComplete(IconManager::Handle handle,
-                               SkBitmap* icon_bitmap);
-  void OnLoadLargeIconComplete(IconManager::Handle handle,
-                               SkBitmap* icon_bitmap);
-
-  // Returns the DownloadItem model object belonging to this item.
-  DownloadItem* get_download();
-
- private:
-  friend class DownloadShelfContextMenuGtk;
-
-  // Returns true IFF the download is dangerous and unconfirmed.
-  bool IsDangerous();
-
-  // Functions for controlling the progress animation.
-  // Repaint the download progress.
-  void UpdateDownloadProgress();
-
-  // Starts a repeating timer for UpdateDownloadProgress.
-  void StartDownloadProgress();
-
-  // Stops the repeating timer.
-  void StopDownloadProgress();
-
-  // Ask the icon manager to asynchronously start loading the icon for the file.
-  void LoadIcon();
-
-  // Sets the tooltip on the download button.
-  void UpdateTooltip();
-
-  // Sets the name label to the correct color.
-  void UpdateNameLabel();
-
-  // Sets the text of |status_label_| with the correct color.
-  void UpdateStatusLabel(const std::string& status_text);
-
-  // Sets the components of the danger warning.
-  void UpdateDangerWarning();
-
-  static void InitNineBoxes();
-
-  // Draws everything in GTK rendering mode.
-  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnHboxExpose,
-                       GdkEventExpose*);
-
-  // Used for the download item's body and menu button in chrome theme mode.
-  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnExpose, GdkEventExpose*);
-
-  // Called when |body_| is clicked.
-  CHROMEGTK_CALLBACK_0(DownloadItemGtk, void, OnClick);
-
-  // Used for the download icon.
-  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnProgressAreaExpose,
-                       GdkEventExpose*);
-
-  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnMenuButtonPressEvent,
-                       GdkEvent*);
-
-  // Dangerous download related. -----------------------------------------------
-  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnDangerousPromptExpose,
-                       GdkEventExpose*);
-  CHROMEGTK_CALLBACK_0(DownloadItemGtk, void, OnDangerousAccept);
-  CHROMEGTK_CALLBACK_0(DownloadItemGtk, void, OnDangerousDecline);
-
-  // Nineboxes for the body area.
-  static NineBox* body_nine_box_normal_;
-  static NineBox* body_nine_box_prelight_;
-  static NineBox* body_nine_box_active_;
-
-  // Nineboxes for the menu button.
-  static NineBox* menu_nine_box_normal_;
-  static NineBox* menu_nine_box_prelight_;
-  static NineBox* menu_nine_box_active_;
-
-  // Ninebox for the background of the dangerous download prompt.
-  static NineBox* dangerous_nine_box_;
-
-  // The shelf on which we are displayed.
-  DownloadShelfGtk* parent_shelf_;
-
-  // The widget that contains the body and menu dropdown.
-  OwnedWidgetGtk hbox_;
-
-  // The widget that contains the name of the download and the progress
-  // animation.
-  OwnedWidgetGtk body_;
-
-  // The GtkLabel that holds the download title text.
-  GtkWidget* name_label_;
-
-  // The GtkLabel that holds the status text.
-  GtkWidget* status_label_;
-
-  // The current text of status label
-  std::string status_text_;
-
-  // The widget that creates a dropdown menu when pressed.
-  GtkWidget* menu_button_;
-
-  // A gtk arrow pointing downward displayed in |menu_button_|. Only displayed
-  // in GTK mode.
-  GtkWidget* arrow_;
-
-  // Whether the menu is currently showing for |menu_button_|. Affects how we
-  // draw the button.
-  bool menu_showing_;
-
-  // Whether we should use the GTK text color
-  GtkThemeProvider* theme_provider_;
-
-  // The widget that contains the animation progress and the file's icon
-  // (as well as the complete animation).
-  OwnedWidgetGtk progress_area_;
-
-  // In degrees. Only used for downloads with no known total size.
-  int progress_angle_;
-
-  // The menu that pops down when the user presses |menu_button_|. We do not
-  // create this until the first time we actually need it.
-  scoped_ptr<DownloadShelfContextMenuGtk> menu_;
-
-  // The download item model we represent.
-  scoped_ptr<BaseDownloadItemModel> download_model_;
-
-  // The dangerous download dialog. This will be null for safe downloads.
-  GtkWidget* dangerous_prompt_;
-  GtkWidget* dangerous_image_;
-  GtkWidget* dangerous_label_;
-
-  // An hbox for holding components of the dangerous download dialog.
-  GtkWidget* dangerous_hbox_;
-  int dangerous_hbox_start_width_;
-  int dangerous_hbox_full_width_;
-
-  // The animation when this item is first added to the shelf.
-  scoped_ptr<ui::SlideAnimation> new_item_animation_;
-
-  // Progress animation.
-  base::RepeatingTimer<DownloadItemGtk> progress_timer_;
-
-  // Animation for download complete.
-  scoped_ptr<ui::SlideAnimation> complete_animation_;
-
-  // The file icon for the download. May be null. The small version is used
-  // for display in the shelf; the large version is for use as a drag icon.
-  SkBitmap* icon_small_;
-  SkBitmap* icon_large_;
-
-  // The last download file path for which we requested an icon.
-  FilePath icon_filepath_;
-
-  NotificationRegistrar registrar_;
-
-  // The time at which we were insantiated.
-  base::Time creation_time_;
-
-  // For canceling an in progress icon request.
-  CancelableRequestConsumerT<int, 0> icon_consumer_;
-};
-
-#endif  // CHROME_BROWSER_GTK_DOWNLOAD_ITEM_GTK_H_
diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc
deleted file mode 100644
index d9b5109..0000000
--- a/chrome/browser/gtk/download_shelf_gtk.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/download_shelf_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "chrome/browser/download/download_item.h"
-#include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_util.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/download_item_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// The height of the download items.
-const int kDownloadItemHeight = download_util::kSmallProgressIconSize;
-
-// Padding between the download widgets.
-const int kDownloadItemPadding = 10;
-
-// Padding between the top/bottom of the download widgets and the edge of the
-// shelf.
-const int kTopBottomPadding = 4;
-
-// Padding between the left side of the shelf and the first download item.
-const int kLeftPadding = 2;
-
-// Padding between the right side of the shelf and the close button.
-const int kRightPadding = 10;
-
-// Speed of the shelf show/hide animation.
-const int kShelfAnimationDurationMs = 120;
-
-}  // namespace
-
-DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent)
-    : browser_(browser),
-      is_showing_(false),
-      theme_provider_(GtkThemeProvider::GetFrom(browser->profile())) {
-  // Logically, the shelf is a vbox that contains two children: a one pixel
-  // tall event box, which serves as the top border, and an hbox, which holds
-  // the download items and other shelf widgets (close button, show-all-
-  // downloads link).
-  // To make things pretty, we have to add a few more widgets. To get padding
-  // right, we stick the hbox in an alignment. We put that alignment in an
-  // event box so we can color the background.
-
-  // Create the top border.
-  top_border_ = gtk_event_box_new();
-  gtk_widget_set_size_request(GTK_WIDGET(top_border_), 0, 1);
-
-  // Create |items_hbox_|. We use GtkChromeShrinkableHBox, so that download
-  // items can be hid automatically when there is no enough space to show them.
-  items_hbox_.Own(gtk_chrome_shrinkable_hbox_new(
-      TRUE, FALSE, kDownloadItemPadding));
-  // We want the download shelf to be horizontally shrinkable, so that the
-  // Chrome window can be resized freely even with many download items.
-  gtk_widget_set_size_request(items_hbox_.get(), 0, kDownloadItemHeight);
-
-  // Create a hbox that holds |items_hbox_| and other shelf widgets.
-  GtkWidget* outer_hbox = gtk_hbox_new(FALSE, kDownloadItemPadding);
-
-  // Pack the |items_hbox_| in the outer hbox.
-  gtk_box_pack_start(GTK_BOX(outer_hbox), items_hbox_.get(), TRUE, TRUE, 0);
-
-  // Get the padding and background color for |outer_hbox| right.
-  GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
-  // Subtract 1 from top spacing to account for top border.
-  gtk_alignment_set_padding(GTK_ALIGNMENT(padding),
-      kTopBottomPadding - 1, kTopBottomPadding, kLeftPadding, kRightPadding);
-  padding_bg_ = gtk_event_box_new();
-  gtk_container_add(GTK_CONTAINER(padding_bg_), padding);
-  gtk_container_add(GTK_CONTAINER(padding), outer_hbox);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), top_border_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), padding_bg_, FALSE, FALSE, 0);
-
-  // Put the shelf in an event box so it gets its own window, which makes it
-  // easier to get z-ordering right.
-  shelf_.Own(gtk_event_box_new());
-  gtk_container_add(GTK_CONTAINER(shelf_.get()), vbox);
-
-  // Create and pack the close button.
-  close_button_.reset(CustomDrawButton::CloseButton(theme_provider_));
-  gtk_util::CenterWidgetInHBox(outer_hbox, close_button_->widget(), true, 0);
-  g_signal_connect(close_button_->widget(), "clicked",
-                   G_CALLBACK(OnButtonClickThunk), this);
-
-  // Create the "Show all downloads..." link and connect to the click event.
-  std::string link_text =
-      l10n_util::GetStringUTF8(IDS_SHOW_ALL_DOWNLOADS);
-  link_button_ = gtk_chrome_link_button_new(link_text.c_str());
-  g_signal_connect(link_button_, "clicked",
-                   G_CALLBACK(OnButtonClickThunk), this);
-  gtk_util::SetButtonTriggersNavigation(link_button_);
-  // Until we switch to vector graphics, force the font size.
-  // 13.4px == 10pt @ 96dpi
-  gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link_button_)->label,
-                                13.4);
-
-  // Make the download arrow icon.
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  GdkPixbuf* download_pixbuf = rb.GetPixbufNamed(IDR_DOWNLOADS_FAVICON);
-  GtkWidget* download_image = gtk_image_new_from_pixbuf(download_pixbuf);
-
-  // Pack the link and the icon in outer hbox.
-  gtk_util::CenterWidgetInHBox(outer_hbox, link_button_, true, 0);
-  gtk_util::CenterWidgetInHBox(outer_hbox, download_image, true, 0);
-
-  slide_widget_.reset(new SlideAnimatorGtk(shelf_.get(),
-                                           SlideAnimatorGtk::UP,
-                                           kShelfAnimationDurationMs,
-                                           false, true, this));
-
-  theme_provider_->InitThemesFor(this);
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-
-  gtk_widget_show_all(shelf_.get());
-
-  // Stick ourselves at the bottom of the parent browser.
-  gtk_box_pack_end(GTK_BOX(parent), slide_widget_->widget(),
-                   FALSE, FALSE, 0);
-  // Make sure we are at the very end.
-  gtk_box_reorder_child(GTK_BOX(parent), slide_widget_->widget(), 0);
-  Show();
-}
-
-DownloadShelfGtk::~DownloadShelfGtk() {
-  for (std::vector<DownloadItemGtk*>::iterator iter = download_items_.begin();
-       iter != download_items_.end(); ++iter) {
-    delete *iter;
-  }
-
-  shelf_.Destroy();
-  items_hbox_.Destroy();
-}
-
-void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) {
-  download_items_.push_back(new DownloadItemGtk(this, download_model_));
-  Show();
-}
-
-bool DownloadShelfGtk::IsShowing() const {
-  return slide_widget_->IsShowing();
-}
-
-bool DownloadShelfGtk::IsClosing() const {
-  return slide_widget_->IsClosing();
-}
-
-void DownloadShelfGtk::Show() {
-  slide_widget_->Open();
-  browser_->UpdateDownloadShelfVisibility(true);
-}
-
-void DownloadShelfGtk::Close() {
-  // When we are closing, we can vertically overlap the render view. Make sure
-  // we are on top.
-  gdk_window_raise(shelf_.get()->window);
-  slide_widget_->Close();
-  browser_->UpdateDownloadShelfVisibility(false);
-}
-
-Browser* DownloadShelfGtk::browser() const {
-  return browser_;
-}
-
-void DownloadShelfGtk::Closed() {
-  // When the close animation is complete, remove all completed downloads.
-  size_t i = 0;
-  while (i < download_items_.size()) {
-    DownloadItem* download = download_items_[i]->get_download();
-    bool is_transfer_done = download->state() == DownloadItem::COMPLETE ||
-                            download->state() == DownloadItem::CANCELLED;
-    if (is_transfer_done &&
-        download->safety_state() != DownloadItem::DANGEROUS) {
-      RemoveDownloadItem(download_items_[i]);
-    } else {
-      ++i;
-    }
-  }
-}
-
-void DownloadShelfGtk::Observe(NotificationType type,
-                               const NotificationSource& source,
-                               const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    GdkColor color = theme_provider_->GetGdkColor(
-        BrowserThemeProvider::COLOR_TOOLBAR);
-    gtk_widget_modify_bg(padding_bg_, GTK_STATE_NORMAL, &color);
-
-    color = theme_provider_->GetBorderColor();
-    gtk_widget_modify_bg(top_border_, GTK_STATE_NORMAL, &color);
-
-    gtk_chrome_link_button_set_use_gtk_theme(
-        GTK_CHROME_LINK_BUTTON(link_button_), theme_provider_->UseGtkTheme());
-
-    // When using a non-standard, non-gtk theme, we make the link color match
-    // the bookmark text color. Otherwise, standard link blue can look very
-    // bad for some dark themes.
-    bool use_default_color = theme_provider_->GetColor(
-        BrowserThemeProvider::COLOR_BOOKMARK_TEXT) ==
-        BrowserThemeProvider::GetDefaultColor(
-            BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-    GdkColor bookmark_color = theme_provider_->GetGdkColor(
-        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-    gtk_chrome_link_button_set_normal_color(
-        GTK_CHROME_LINK_BUTTON(link_button_),
-        use_default_color ? NULL : &bookmark_color);
-
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    close_button_->SetBackground(
-        theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT),
-        rb.GetBitmapNamed(IDR_CLOSE_BAR),
-        rb.GetBitmapNamed(IDR_CLOSE_BAR_MASK));
-  }
-}
-
-int DownloadShelfGtk::GetHeight() const {
-  return slide_widget_->widget()->allocation.height;
-}
-
-void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) {
-  DCHECK(download_item);
-  std::vector<DownloadItemGtk*>::iterator i =
-      find(download_items_.begin(), download_items_.end(), download_item);
-  DCHECK(i != download_items_.end());
-  download_items_.erase(i);
-  delete download_item;
-  if (download_items_.empty()) {
-    slide_widget_->CloseWithoutAnimation();
-    browser_->UpdateDownloadShelfVisibility(false);
-  }
-}
-
-GtkWidget* DownloadShelfGtk::GetHBox() const {
-  return items_hbox_.get();
-}
-
-void DownloadShelfGtk::MaybeShowMoreDownloadItems() {
-  // Show all existing download items. It'll trigger "size-allocate" signal,
-  // which will hide download items that don't have enough space to show.
-  gtk_widget_show_all(items_hbox_.get());
-}
-
-void DownloadShelfGtk::OnButtonClick(GtkWidget* button) {
-  if (button == close_button_->widget()) {
-    Close();
-  } else {
-    // The link button was clicked.
-    browser_->ShowDownloadsTab();
-  }
-}
diff --git a/chrome/browser/gtk/download_shelf_gtk.h b/chrome/browser/gtk/download_shelf_gtk.h
deleted file mode 100644
index 9c6cceb..0000000
--- a/chrome/browser/gtk/download_shelf_gtk.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_DOWNLOAD_SHELF_GTK_H_
-#define CHROME_BROWSER_GTK_DOWNLOAD_SHELF_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/download/download_shelf.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
-
-class BaseDownloadItemModel;
-class Browser;
-class CustomDrawButton;
-class DownloadItemGtk;
-class GtkThemeProvider;
-class SlideAnimatorGtk;
-
-class DownloadShelfGtk : public DownloadShelf,
-                         public NotificationObserver,
-                         public SlideAnimatorGtk::Delegate {
- public:
-  explicit DownloadShelfGtk(Browser* browser, gfx::NativeView view);
-
-  ~DownloadShelfGtk();
-
-  // DownloadShelf implementation.
-  virtual void AddDownload(BaseDownloadItemModel* download_model);
-  virtual bool IsShowing() const;
-  virtual bool IsClosing() const;
-  virtual void Show();
-  virtual void Close();
-  virtual Browser* browser() const;
-
-  // SlideAnimatorGtk::Delegate implementation.
-  virtual void Closed();
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Returns the current height of the shelf.
-  int GetHeight() const;
-
- private:
-  // Remove |download_item| from the download shelf and delete it.
-  void RemoveDownloadItem(DownloadItemGtk* download_item);
-
-  // Get the hbox download items ought to pack themselves into.
-  GtkWidget* GetHBox() const;
-
-  // Show more hidden download items if there is enough space in the shelf.
-  // It's called when a download item is removed from the shelf or an item's
-  // size is changed.
-  void MaybeShowMoreDownloadItems();
-
-  CHROMEGTK_CALLBACK_0(DownloadShelfGtk, void, OnButtonClick);
-
-  // The browser that owns this download shelf.
-  Browser* browser_;
-
-  // The top level widget of the shelf.
-  scoped_ptr<SlideAnimatorGtk> slide_widget_;
-
-  // |items_hbox_| holds the download items.
-  OwnedWidgetGtk items_hbox_;
-
-  // |shelf_| is the second highest level widget. See the constructor
-  // for an explanation of the widget layout.
-  OwnedWidgetGtk shelf_;
-
-  // Top level event box which draws the one pixel border.
-  GtkWidget* top_border_;
-
-  // A GtkEventBox which we color.
-  GtkWidget* padding_bg_;
-
-  // The "Show all downloads..." link.
-  GtkWidget* link_button_;
-
-  // The 'x' that the user can press to hide the download shelf.
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  // Keeps track of our current hide/show state.
-  bool is_showing_;
-
-  // The download items we have added to our shelf.
-  std::vector<DownloadItemGtk*> download_items_;
-
-  // Gives us our colors and theme information.
-  GtkThemeProvider* theme_provider_;
-
-  NotificationRegistrar registrar_;
-
-  friend class DownloadItemGtk;
-};
-
-#endif  // CHROME_BROWSER_GTK_DOWNLOAD_SHELF_GTK_H_
diff --git a/chrome/browser/gtk/download_started_animation_gtk.cc b/chrome/browser/gtk/download_started_animation_gtk.cc
deleted file mode 100644
index e54e1a7..0000000
--- a/chrome/browser/gtk/download_started_animation_gtk.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/download/download_started_animation.h"
-
-#include <gtk/gtk.h>
-
-#include "app/resource_bundle.h"
-#include "base/message_loop.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_source.h"
-#include "gfx/rect.h"
-#include "grit/theme_resources.h"
-#include "ui/base/animation/linear_animation.h"
-
-namespace {
-
-// How long to spend moving downwards and fading out after waiting.
-const int kMoveTimeMs = 600;
-
-// The animation framerate.
-const int kFrameRateHz = 60;
-
-// What fraction of the frame height to move downward from the frame center.
-// Note that setting this greater than 0.5 will mean moving past the bottom of
-// the frame.
-const double kMoveFraction = 1.0 / 3.0;
-
-class DownloadStartedAnimationGtk : public ui::LinearAnimation,
-                                    public NotificationObserver {
- public:
-  explicit DownloadStartedAnimationGtk(TabContents* tab_contents);
-
-  // DownloadStartedAnimation will delete itself, but this is public so
-  // that we can use DeleteSoon().
-  virtual ~DownloadStartedAnimationGtk();
-
- private:
-  // Move the arrow to wherever it should currently be.
-  void Reposition();
-
-  // Shut down cleanly.
-  void Close();
-
-  // Animation implementation.
-  virtual void AnimateToState(double state);
-
-  // NotificationObserver
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // The top level window that floats over the browser and displays the
-  // image.
-  GtkWidget* popup_;
-
-  // Dimensions of the image.
-  int width_;
-  int height_;
-
-  // The content area holding us.
-  TabContents* tab_contents_;
-
-  // The content area at the start of the animation. We store this so that the
-  // download shelf's resizing of the content area doesn't cause the animation
-  // to move around. This means that once started, the animation won't move
-  // with the parent window, but it's so fast that this shouldn't cause too
-  // much heartbreak.
-  gfx::Rect tab_contents_bounds_;
-
-  // A scoped container for notification registries.
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloadStartedAnimationGtk);
-};
-
-DownloadStartedAnimationGtk::DownloadStartedAnimationGtk(
-    TabContents* tab_contents)
-    : ui::LinearAnimation(kMoveTimeMs, kFrameRateHz, NULL),
-      tab_contents_(tab_contents) {
-  static GdkPixbuf* kDownloadImage = NULL;
-  if (!kDownloadImage) {
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    kDownloadImage = rb.GetPixbufNamed(IDR_DOWNLOAD_ANIMATION_BEGIN);
-  }
-
-  width_ = gdk_pixbuf_get_width(kDownloadImage);
-  height_ = gdk_pixbuf_get_height(kDownloadImage);
-
-  // If we're too small to show the download image, then don't bother -
-  // the shelf will be enough.
-  tab_contents_->GetContainerBounds(&tab_contents_bounds_);
-  if (tab_contents_bounds_.height() < height_)
-    return;
-
-  registrar_.Add(
-      this,
-      NotificationType::TAB_CONTENTS_HIDDEN,
-      Source<TabContents>(tab_contents_));
-  registrar_.Add(
-      this,
-      NotificationType::TAB_CONTENTS_DESTROYED,
-      Source<TabContents>(tab_contents_));
-
-  // TODO(estade): don't show up on the wrong virtual desktop.
-
-  popup_ = gtk_window_new(GTK_WINDOW_POPUP);
-  GtkWidget* image = gtk_image_new_from_pixbuf(kDownloadImage);
-  gtk_container_add(GTK_CONTAINER(popup_), image);
-
-  // Set the shape of the window to that of the arrow. Areas with
-  // opacity less than 0xff (i.e. <100% opacity) will be transparent.
-  GdkBitmap* mask = gdk_pixmap_new(NULL, width_, height_, 1);
-  gdk_pixbuf_render_threshold_alpha(kDownloadImage, mask,
-                                    0, 0,
-                                    0, 0, -1, -1,
-                                    0xff);
-  gtk_widget_shape_combine_mask(popup_, mask, 0, 0);
-  g_object_unref(mask);
-
-  Reposition();
-  gtk_widget_show_all(popup_);
-  // Make sure our window has focus, is brought to the top, etc.
-  gtk_window_present(GTK_WINDOW(popup_));
-
-  Start();
-}
-
-DownloadStartedAnimationGtk::~DownloadStartedAnimationGtk() {
-}
-
-void DownloadStartedAnimationGtk::Reposition() {
-  if (!tab_contents_)
-    return;
-
-  // Align the image with the bottom left of the web contents (so that it
-  // points to the newly created download).
-  gtk_window_move(GTK_WINDOW(popup_),
-      tab_contents_bounds_.x(),
-      static_cast<int>(tab_contents_bounds_.bottom() -
-          height_ - height_ * (1 - GetCurrentValue())));
-}
-
-void DownloadStartedAnimationGtk::Close() {
-  if (!tab_contents_)
-    return;
-
-  registrar_.Remove(
-      this,
-      NotificationType::TAB_CONTENTS_HIDDEN,
-      Source<TabContents>(tab_contents_));
-  registrar_.Remove(
-      this,
-      NotificationType::TAB_CONTENTS_DESTROYED,
-      Source<TabContents>(tab_contents_));
-
-  tab_contents_ = NULL;
-  gtk_widget_destroy(popup_);
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void DownloadStartedAnimationGtk::AnimateToState(double state) {
-  if (!tab_contents_)
-    return;
-
-  if (state >= 1.0) {
-    Close();
-  } else {
-    Reposition();
-
-    // Start at zero, peak halfway and end at zero.
-    double opacity = std::min(1.0 - pow(GetCurrentValue() - 0.5, 2) * 4.0,
-                              static_cast<double>(1.0));
-
-    // This only works when there's a compositing manager running. Oh well.
-    gtk_window_set_opacity(GTK_WINDOW(popup_), opacity);
-  }
-}
-
-void DownloadStartedAnimationGtk::Observe(NotificationType type,
-                                          const NotificationSource& source,
-                                          const NotificationDetails& details) {
-  Close();
-}
-
-}  // namespace
-
-// static
-void DownloadStartedAnimation::Show(TabContents* tab_contents) {
-  // The animation will delete itself.
-  new DownloadStartedAnimationGtk(tab_contents);
-}
diff --git a/chrome/browser/gtk/edit_search_engine_dialog.cc b/chrome/browser/gtk/edit_search_engine_dialog.cc
deleted file mode 100644
index a3fa339..0000000
--- a/chrome/browser/gtk/edit_search_engine_dialog.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/edit_search_engine_dialog.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/i18n/rtl.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/edit_search_engine_controller.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "googleurl/src/gurl.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-std::string GetDisplayURL(const TemplateURL& turl) {
-  return turl.url() ? WideToUTF8(turl.url()->DisplayURL()) : std::string();
-}
-
-// Forces text to lowercase when connected to an editable's "insert-text"
-// signal.  (Like views Textfield::STYLE_LOWERCASE.)
-void LowercaseInsertTextHandler(GtkEditable *editable, const gchar *text,
-                                gint length, gint *position, gpointer data) {
-  string16 original_text = UTF8ToUTF16(text);
-  string16 lower_text = l10n_util::ToLower(original_text);
-  if (lower_text != original_text) {
-    std::string result = UTF16ToUTF8(lower_text);
-    // Prevent ourselves getting called recursively about our own edit.
-    g_signal_handlers_block_by_func(G_OBJECT(editable),
-        reinterpret_cast<gpointer>(LowercaseInsertTextHandler), data);
-    gtk_editable_insert_text(editable, result.c_str(), result.size(), position);
-    g_signal_handlers_unblock_by_func(G_OBJECT(editable),
-        reinterpret_cast<gpointer>(LowercaseInsertTextHandler), data);
-    // We've inserted our modified version, stop the defalut handler from
-    // inserting the original.
-    g_signal_stop_emission_by_name(G_OBJECT(editable), "insert_text");
-  }
-}
-
-void SetWidgetStyle(GtkWidget* entry, GtkStyle* label_style,
-                    GtkStyle* dialog_style) {
-  gtk_widget_modify_fg(entry, GTK_STATE_NORMAL,
-                       &label_style->fg[GTK_STATE_NORMAL]);
-  gtk_widget_modify_fg(entry, GTK_STATE_INSENSITIVE,
-                       &label_style->fg[GTK_STATE_INSENSITIVE]);
-  // GTK_NO_WINDOW widgets like GtkLabel don't draw their own background, so we
-  // combine the normal or insensitive foreground of the label style with the
-  // normal background of the window style to achieve the "normal label" and
-  // "insensitive label" colors.
-  gtk_widget_modify_base(entry, GTK_STATE_NORMAL,
-                         &dialog_style->bg[GTK_STATE_NORMAL]);
-  gtk_widget_modify_base(entry, GTK_STATE_INSENSITIVE,
-                         &dialog_style->bg[GTK_STATE_NORMAL]);
-}
-
-}  // namespace
-
-EditSearchEngineDialog::EditSearchEngineDialog(
-    GtkWindow* parent_window,
-    const TemplateURL* template_url,
-    EditSearchEngineControllerDelegate* delegate,
-    Profile* profile)
-    : controller_(new EditSearchEngineController(template_url, delegate,
-                                                 profile)) {
-  Init(parent_window, profile);
-}
-
-EditSearchEngineDialog::~EditSearchEngineDialog() {}
-
-void EditSearchEngineDialog::Init(GtkWindow* parent_window, Profile* profile) {
-  std::string dialog_name = l10n_util::GetStringUTF8(
-      controller_->template_url() ?
-      IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE :
-      IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE);
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      parent_window,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_CANCEL,
-      NULL);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  ok_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
-                                     controller_->template_url() ?
-                                     GTK_STOCK_SAVE :
-                                     GTK_STOCK_ADD,
-                                     GTK_RESPONSE_OK);
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
-
-  // The dialog layout hierarchy looks like this:
-  //
-  // \ GtkVBox |dialog_->vbox|
-  // +-\ GtkTable |controls|
-  // | +-\ row 0
-  // | | +- GtkLabel
-  // | | +-\ GtkHBox
-  // | |   +- GtkEntry |title_entry_|
-  // | |   +- GtkImage |title_image_|
-  // | +-\ row 1
-  // | | +- GtkLabel
-  // | | +-\ GtkHBox
-  // | |   +- GtkEntry |keyword_entry_|
-  // | |   +- GtkImage |keyword_image_|
-  // | +-\ row 2
-  // |   +- GtkLabel
-  // |   +-\ GtkHBox
-  // |     +- GtkEntry |url_entry_|
-  // |     +- GtkImage |url_image_|
-  // +- GtkLabel |description_label|
-
-  title_entry_ = gtk_entry_new();
-  gtk_entry_set_activates_default(GTK_ENTRY(title_entry_), TRUE);
-  g_signal_connect(title_entry_, "changed",
-                   G_CALLBACK(OnEntryChangedThunk), this);
-  accessible_widget_helper_->SetWidgetName(
-      title_entry_,
-      IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL);
-
-  keyword_entry_ = gtk_entry_new();
-  gtk_entry_set_activates_default(GTK_ENTRY(keyword_entry_), TRUE);
-  g_signal_connect(keyword_entry_, "changed",
-                   G_CALLBACK(OnEntryChangedThunk), this);
-  g_signal_connect(keyword_entry_, "insert-text",
-                   G_CALLBACK(LowercaseInsertTextHandler), NULL);
-  accessible_widget_helper_->SetWidgetName(
-      keyword_entry_,
-      IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL);
-
-  url_entry_ = gtk_entry_new();
-  gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
-  g_signal_connect(url_entry_, "changed",
-                   G_CALLBACK(OnEntryChangedThunk), this);
-  accessible_widget_helper_->SetWidgetName(
-      url_entry_,
-      IDS_SEARCH_ENGINES_EDITOR_URL_LABEL);
-
-  title_image_ = gtk_image_new_from_pixbuf(NULL);
-  keyword_image_ = gtk_image_new_from_pixbuf(NULL);
-  url_image_ = gtk_image_new_from_pixbuf(NULL);
-
-  if (controller_->template_url()) {
-    gtk_entry_set_text(
-        GTK_ENTRY(title_entry_),
-        WideToUTF8(controller_->template_url()->short_name()).c_str());
-    gtk_entry_set_text(
-        GTK_ENTRY(keyword_entry_),
-        WideToUTF8(controller_->template_url()->keyword()).c_str());
-    gtk_entry_set_text(
-        GTK_ENTRY(url_entry_),
-        GetDisplayURL(*controller_->template_url()).c_str());
-    // We don't allow users to edit prepopulated URLs.
-    gtk_editable_set_editable(
-        GTK_EDITABLE(url_entry_),
-        controller_->template_url()->prepopulate_id() == 0);
-
-    if (controller_->template_url()->prepopulate_id() != 0) {
-      GtkWidget* fake_label = gtk_label_new("Fake label");
-      gtk_widget_set_sensitive(fake_label,
-          controller_->template_url()->prepopulate_id() == 0);
-      GtkStyle* label_style = gtk_widget_get_style(fake_label);
-      GtkStyle* dialog_style = gtk_widget_get_style(dialog_);
-      SetWidgetStyle(url_entry_, label_style, dialog_style);
-      gtk_widget_destroy(fake_label);
-    }
-  }
-
-  GtkWidget* controls = gtk_util::CreateLabeledControlsGroup(NULL,
-      l10n_util::GetStringUTF8(
-          IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL).c_str(),
-      gtk_util::CreateEntryImageHBox(title_entry_, title_image_),
-      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL).c_str(),
-      gtk_util::CreateEntryImageHBox(keyword_entry_, keyword_image_),
-      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_URL_LABEL).c_str(),
-      gtk_util::CreateEntryImageHBox(url_entry_, url_image_),
-      NULL);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), controls,
-                     FALSE, FALSE, 0);
-
-  // On RTL UIs (such as Arabic and Hebrew) the description text is not
-  // displayed correctly since it contains the substring "%s". This substring
-  // is not interpreted by the Unicode BiDi algorithm as an LTR string and
-  // therefore the end result is that the following right to left text is
-  // displayed: ".three two s% one" (where 'one', 'two', etc. are words in
-  // Hebrew).
-  //
-  // In order to fix this problem we transform the substring "%s" so that it
-  // is displayed correctly when rendered in an RTL context.
-  std::string description =
-      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_URL_DESCRIPTION_LABEL);
-  if (base::i18n::IsRTL()) {
-    const std::string reversed_percent("s%");
-    std::string::size_type percent_index = description.find("%s");
-    if (percent_index != std::string::npos) {
-      description.replace(percent_index,
-                          reversed_percent.length(),
-                          reversed_percent);
-    }
-  }
-
-  GtkWidget* description_label = gtk_label_new(description.c_str());
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), description_label,
-                     FALSE, FALSE, 0);
-
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  EnableControls();
-
-  gtk_util::ShowDialog(dialog_);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-string16 EditSearchEngineDialog::GetTitleInput() const {
-  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(title_entry_)));
-}
-
-string16 EditSearchEngineDialog::GetKeywordInput() const {
-  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(keyword_entry_)));
-}
-
-std::string EditSearchEngineDialog::GetURLInput() const {
-  return gtk_entry_get_text(GTK_ENTRY(url_entry_));
-}
-
-void EditSearchEngineDialog::EnableControls() {
-  gtk_widget_set_sensitive(ok_button_,
-                           controller_->IsKeywordValid(GetKeywordInput()) &&
-                           controller_->IsTitleValid(GetTitleInput()) &&
-                           controller_->IsURLValid(GetURLInput()));
-  UpdateImage(keyword_image_, controller_->IsKeywordValid(GetKeywordInput()),
-              IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT);
-  UpdateImage(url_image_, controller_->IsURLValid(GetURLInput()),
-              IDS_SEARCH_ENGINES_INVALID_URL_TT);
-  UpdateImage(title_image_, controller_->IsTitleValid(GetTitleInput()),
-              IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
-}
-
-void EditSearchEngineDialog::UpdateImage(GtkWidget* image,
-                                         bool is_valid,
-                                         int invalid_message_id) {
-  if (is_valid) {
-    gtk_widget_set_has_tooltip(image, FALSE);
-    gtk_image_set_from_pixbuf(GTK_IMAGE(image),
-        ResourceBundle::GetSharedInstance().GetPixbufNamed(
-            IDR_INPUT_GOOD));
-  } else {
-    gtk_widget_set_tooltip_text(
-        image, l10n_util::GetStringUTF8(invalid_message_id).c_str());
-    gtk_image_set_from_pixbuf(GTK_IMAGE(image),
-        ResourceBundle::GetSharedInstance().GetPixbufNamed(
-            IDR_INPUT_ALERT));
-  }
-}
-
-void EditSearchEngineDialog::OnEntryChanged(GtkEditable* editable) {
-  EnableControls();
-}
-
-void EditSearchEngineDialog::OnResponse(GtkDialog* dialog, int response_id) {
-  if (response_id == GTK_RESPONSE_OK) {
-    controller_->AcceptAddOrEdit(GetTitleInput(),
-                                 GetKeywordInput(),
-                                 GetURLInput());
-  } else {
-    controller_->CleanUpCancelledAdd();
-  }
-  gtk_widget_destroy(dialog_);
-}
-
-void EditSearchEngineDialog::OnWindowDestroy(GtkWidget* widget) {
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
diff --git a/chrome/browser/gtk/edit_search_engine_dialog.h b/chrome/browser/gtk/edit_search_engine_dialog.h
deleted file mode 100644
index df5f308..0000000
--- a/chrome/browser/gtk/edit_search_engine_dialog.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_EDIT_SEARCH_ENGINE_DIALOG_H_
-#define CHROME_BROWSER_GTK_EDIT_SEARCH_ENGINE_DIALOG_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "base/string16.h"
-
-class AccessibleWidgetHelper;
-class EditSearchEngineController;
-class EditSearchEngineControllerDelegate;
-class Profile;
-class TemplateURL;
-
-class EditSearchEngineDialog {
- public:
-  EditSearchEngineDialog(GtkWindow* parent_window,
-                         const TemplateURL* template_url,
-                         EditSearchEngineControllerDelegate* delegate,
-                         Profile* profile);
-  virtual ~EditSearchEngineDialog();
-
- private:
-  // Create and show the window.
-  void Init(GtkWindow* parent_window, Profile* profile);
-
-  // Retrieve the user input in the various fields.
-  string16 GetTitleInput() const;
-  string16 GetKeywordInput() const;
-  std::string GetURLInput() const;
-
-  // Set sensitivity of buttons based on entry state.
-  void EnableControls();
-
-  // Updates the tooltip and image of the image view based on is_valid. If
-  // is_valid is false the tooltip of the image view is set to the message with
-  // id invalid_message_id, otherwise the tooltip is set to the empty text.
-  void UpdateImage(GtkWidget* image, bool is_valid, int invalid_message_id);
-
-  // Callback for entry changes.
-  CHROMEG_CALLBACK_0(EditSearchEngineDialog, void, OnEntryChanged,
-                     GtkEditable*);
-
-  // Callback for dialog buttons.
-  CHROMEG_CALLBACK_1(EditSearchEngineDialog, void, OnResponse, GtkDialog*, int);
-
-  // Callback for window destruction.
-  CHROMEGTK_CALLBACK_0(EditSearchEngineDialog, void, OnWindowDestroy);
-
-  // The dialog window.
-  GtkWidget* dialog_;
-
-  // Text entries for each field.
-  GtkWidget* title_entry_;
-  GtkWidget* keyword_entry_;
-  GtkWidget* url_entry_;
-
-  // Images showing whether each entry is okay or has errors.
-  GtkWidget* title_image_;
-  GtkWidget* keyword_image_;
-  GtkWidget* url_image_;
-
-  // The ok button (we need a reference to it so we can de-activate it when the
-  // entries are not all filled in.)
-  GtkWidget* ok_button_;
-
-  scoped_ptr<EditSearchEngineController> controller_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(EditSearchEngineDialog);
-};
-
-#endif  // CHROME_BROWSER_GTK_EDIT_SEARCH_ENGINE_DIALOG_H_
diff --git a/chrome/browser/gtk/extension_infobar_gtk.cc b/chrome/browser/gtk/extension_infobar_gtk.cc
deleted file mode 100644
index bd40795..0000000
--- a/chrome/browser/gtk/extension_infobar_gtk.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/extension_infobar_gtk.h"
-
-#include "app/resource_bundle.h"
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_icon_set.h"
-#include "chrome/common/extensions/extension_resource.h"
-#include "gfx/gtk_util.h"
-#include "grit/theme_resources.h"
-
-ExtensionInfoBarGtk::ExtensionInfoBarGtk(ExtensionInfoBarDelegate* delegate)
-    : InfoBar(delegate),
-      tracker_(this),
-      delegate_(delegate),
-      view_(NULL) {
-  delegate_->extension_host()->view()->SetContainer(this);
-  BuildWidgets();
-}
-
-ExtensionInfoBarGtk::~ExtensionInfoBarGtk() {
-  // This view is not owned by us, so unparent.
-  gtk_widget_unparent(view_->native_view());
-}
-
-void ExtensionInfoBarGtk::OnImageLoaded(
-    SkBitmap* image, ExtensionResource resource, int index) {
-  if (!delegate_)
-    return;  // The delegate can go away while we asynchronously load images.
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  SkBitmap* icon;
-  if (!image || image->empty())
-    icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
-  else
-    icon = image;
-
-  // TODO(finnur): We now have the icon for the menu button, show the menu
-  // button and layout.
-}
-
-void ExtensionInfoBarGtk::BuildWidgets() {
-  // Start loading the image for the menu button.
-  const Extension* extension = delegate_->extension_host()->extension();
-  ExtensionResource icon_resource = extension->GetIconResource(
-      Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY);
-  if (!icon_resource.relative_path().empty()) {
-    // Create a tracker to load the image. It will report back on OnImageLoaded.
-    tracker_.LoadImage(extension, icon_resource,
-                       gfx::Size(Extension::EXTENSION_ICON_BITTY,
-                                 Extension::EXTENSION_ICON_BITTY),
-                       ImageLoadingTracker::DONT_CACHE);
-  } else {
-    OnImageLoaded(NULL, icon_resource, 0);  // |image|, |index|.
-  }
-
-  ExtensionHost* extension_host = delegate_->extension_host();
-  view_ = extension_host->view();
-  if (gtk_widget_get_parent(view_->native_view())) {
-    gtk_widget_reparent(view_->native_view(), hbox_);
-    gtk_box_set_child_packing(GTK_BOX(hbox_), view_->native_view(),
-                              TRUE, TRUE, 0, GTK_PACK_START);
-  } else {
-    gtk_box_pack_start(GTK_BOX(hbox_), view_->native_view(), TRUE, TRUE, 0);
-  }
-
-  g_signal_connect(view_->native_view(), "size_allocate",
-                   G_CALLBACK(&OnSizeAllocateThunk), this);
-}
-
-void ExtensionInfoBarGtk::OnSizeAllocate(GtkWidget* widget,
-                                         GtkAllocation* allocation) {
-  gfx::Size new_size(allocation->width, allocation->height);
-
-  delegate_->extension_host()->view()->render_view_host()->view()
-      ->SetSize(new_size);
-}
-
-void ExtensionInfoBarGtk::OnExtensionPreferredSizeChanged(
-    ExtensionViewGtk* view,
-    const gfx::Size& new_size) {
-  // TODO(rafaelw) - Size the InfobarGtk vertically based on the preferred size
-  // of the content.
-}
-
-InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() {
-  return new ExtensionInfoBarGtk(this);
-}
diff --git a/chrome/browser/gtk/extension_infobar_gtk.h b/chrome/browser/gtk/extension_infobar_gtk.h
deleted file mode 100644
index b204bfc..0000000
--- a/chrome/browser/gtk/extension_infobar_gtk.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_EXTENSION_INFOBAR_GTK_H_
-#define CHROME_BROWSER_GTK_EXTENSION_INFOBAR_GTK_H_
-#pragma once
-
-#include "chrome/browser/gtk/extension_view_gtk.h"
-#include "chrome/browser/gtk/infobar_gtk.h"
-#include "chrome/browser/extensions/extension_infobar_delegate.h"
-#include "chrome/browser/extensions/image_loading_tracker.h"
-#include "gfx/gtk_util.h"
-
-class ExtensionInfobarDelegate;
-class ExtensionResource;
-class ExtensionViewGtk;
-
-class ExtensionInfoBarGtk : public InfoBar,
-                            public ImageLoadingTracker::Observer,
-                            public ExtensionViewGtk::Container {
- public:
-  explicit ExtensionInfoBarGtk(ExtensionInfoBarDelegate* delegate);
-  virtual ~ExtensionInfoBarGtk();
-
-  // Overridden from ImageLoadingTracker::Observer:
-  virtual void OnImageLoaded(
-      SkBitmap* image, ExtensionResource resource, int index);
-
-  // ExtensionViewGtk::Container implementation
-  virtual void OnExtensionPreferredSizeChanged(ExtensionViewGtk* view,
-                                               const gfx::Size& new_size);
-
- private:
-  // Build the widgets of the Infobar.
-  void BuildWidgets();
-
-  CHROMEGTK_CALLBACK_1(ExtensionInfoBarGtk, void, OnSizeAllocate,
-                       GtkAllocation*);
-
-  ImageLoadingTracker tracker_;
-
-  ExtensionInfoBarDelegate* delegate_;
-
-  ExtensionViewGtk* view_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionInfoBarGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_EXTENSION_INFOBAR_GTK_H_
diff --git a/chrome/browser/gtk/extension_install_prompt2_gtk.cc b/chrome/browser/gtk/extension_install_prompt2_gtk.cc
deleted file mode 100644
index 10ee4e4..0000000
--- a/chrome/browser/gtk/extension_install_prompt2_gtk.cc
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/extensions/extension_install_ui.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/common/extensions/extension.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "skia/ext/image_operations.h"
-
-class Profile;
-
-namespace {
-
-const int kRightColumnMinWidth = 290;
-
-const int kImageSize = 69;
-
-// Padding on all sides of each permission in the permissions list.
-const int kPermissionsPadding = 8;
-
-// Make a GtkLabel with |str| as its text, using the formatting in |format|.
-GtkWidget* MakeMarkupLabel(const char* format, const std::string& str) {
-  GtkWidget* label = gtk_label_new(NULL);
-  char* markup = g_markup_printf_escaped(format, str.c_str());
-  gtk_label_set_markup(GTK_LABEL(label), markup);
-  g_free(markup);
-
-  // Left align it.
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
-  return label;
-}
-
-void OnDialogResponse(GtkDialog* dialog, int response_id,
-                      ExtensionInstallUI::Delegate* delegate) {
-  if (response_id == GTK_RESPONSE_ACCEPT) {
-    delegate->InstallUIProceed();
-  } else {
-    delegate->InstallUIAbort();
-  }
-
-  gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-void ShowInstallPromptDialog2(GtkWindow* parent, SkBitmap* skia_icon,
-                              const Extension* extension,
-                              ExtensionInstallUI::Delegate *delegate,
-                              const std::vector<string16>& permissions) {
-  // Build the dialog.
-  GtkWidget* dialog = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALL_PROMPT_TITLE).c_str(),
-      parent,
-      GTK_DIALOG_MODAL,
-      NULL);
-  GtkWidget* close_button = gtk_dialog_add_button(GTK_DIALOG(dialog),
-      GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE);
-  gtk_dialog_add_button(GTK_DIALOG(dialog),
-      l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_INSTALL_BUTTON).c_str(),
-      GTK_RESPONSE_ACCEPT);
-  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
-
-  // Create a two column layout.
-  GtkWidget* content_area = GTK_DIALOG(dialog)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* icon_hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_box_pack_start(GTK_BOX(content_area), icon_hbox, TRUE, TRUE, 0);
-
-  // Resize the icon if necessary.
-  SkBitmap scaled_icon = *skia_icon;
-  if (scaled_icon.width() > kImageSize || scaled_icon.height() > kImageSize) {
-    scaled_icon = skia::ImageOperations::Resize(scaled_icon,
-        skia::ImageOperations::RESIZE_LANCZOS3,
-        kImageSize, kImageSize);
-  }
-
-  // Put Icon in the left column.
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&scaled_icon);
-  GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf);
-  g_object_unref(pixbuf);
-  gtk_box_pack_start(GTK_BOX(icon_hbox), icon, FALSE, FALSE, 0);
-  // Top justify the image.
-  gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
-
-  // Create a new vbox for the right column.
-  GtkWidget* right_column_area = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(icon_hbox), right_column_area, TRUE, TRUE, 0);
-
-  std::string heading_text = l10n_util::GetStringFUTF8(
-      IDS_EXTENSION_INSTALL_PROMPT_HEADING, UTF8ToUTF16(extension->name()));
-  GtkWidget* heading_label = MakeMarkupLabel("<span weight=\"bold\">%s</span>",
-                                             heading_text);
-  gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5);
-  bool show_permissions = !permissions.empty();
-  // If we are not going to show the permissions, vertically center the title.
-  gtk_box_pack_start(GTK_BOX(right_column_area), heading_label,
-                     !show_permissions, !show_permissions, 0);
-
-  if (show_permissions) {
-    GtkWidget* warning_label = gtk_label_new(l10n_util::GetStringUTF8(
-        IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO).c_str());
-    gtk_misc_set_alignment(GTK_MISC(warning_label), 0.0, 0.5);
-    gtk_util::SetLabelWidth(warning_label, kRightColumnMinWidth);
-
-    gtk_box_pack_start(GTK_BOX(right_column_area), warning_label,
-                       FALSE, FALSE, 0);
-
-    GtkWidget* frame = gtk_frame_new(NULL);
-    gtk_box_pack_start(GTK_BOX(right_column_area), frame, FALSE, FALSE, 0);
-
-    GtkWidget* text_view = gtk_text_view_new();
-    gtk_container_add(GTK_CONTAINER(frame), text_view);
-    gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), FALSE);
-    gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_view),
-                                  kPermissionsPadding);
-    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text_view),
-                                   kPermissionsPadding);
-    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD);
-    GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
-    GtkTextTagTable* tag_table = gtk_text_buffer_get_tag_table(buffer);
-
-    GtkTextTag* padding_below_tag = gtk_text_tag_new(NULL);
-    g_object_set(G_OBJECT(padding_below_tag), "pixels-below-lines",
-                 kPermissionsPadding, NULL);
-    g_object_set(G_OBJECT(padding_below_tag), "pixels-below-lines-set",
-                 TRUE, NULL);
-    gtk_text_tag_table_add(tag_table, padding_below_tag);
-    g_object_unref(padding_below_tag);
-    GtkTextTag* padding_above_tag = gtk_text_tag_new(NULL);
-    g_object_set(G_OBJECT(padding_above_tag), "pixels-above-lines",
-                 kPermissionsPadding, NULL);
-    g_object_set(G_OBJECT(padding_above_tag), "pixels-above-lines-set",
-                 TRUE, NULL);
-    gtk_text_tag_table_add(tag_table, padding_above_tag);
-    g_object_unref(padding_above_tag);
-
-    GtkTextIter end_iter;
-    gtk_text_buffer_get_end_iter(buffer, &end_iter);
-    for (std::vector<string16>::const_iterator iter = permissions.begin();
-         iter != permissions.end(); ++iter) {
-      if (iter != permissions.begin())
-        gtk_text_buffer_insert(buffer, &end_iter, "\n", -1);
-      gtk_text_buffer_insert_with_tags(
-          buffer, &end_iter, UTF16ToUTF8(*iter).c_str(), -1,
-          padding_below_tag,
-          iter == permissions.begin() ? padding_above_tag : NULL,
-          NULL);
-    }
-  }
-
-  g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), delegate);
-  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
-  gtk_widget_show_all(dialog);
-  gtk_widget_grab_focus(close_button);
-}
-
-}  // namespace
-
-void ExtensionInstallUI::ShowExtensionInstallUIPrompt2Impl(
-    Profile* profile,
-    Delegate* delegate,
-    const Extension* extension,
-    SkBitmap* icon,
-    const std::vector<string16>& permissions) {
-  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
-  if (!browser) {
-    delegate->InstallUIAbort();
-    return;
-  }
-
-  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
-      browser->window());
-  if (!browser_window) {
-    delegate->InstallUIAbort();
-    return;
-  }
-
-  ShowInstallPromptDialog2(browser_window->window(), icon, extension,
-      delegate, permissions);
-}
diff --git a/chrome/browser/gtk/extension_install_prompt_gtk.cc b/chrome/browser/gtk/extension_install_prompt_gtk.cc
deleted file mode 100644
index a1166d0..0000000
--- a/chrome/browser/gtk/extension_install_prompt_gtk.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Currently this file is only used for the uninstall prompt. The install prompt
-// code is in extension_install_prompt2_gtk.cc.
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/extensions/extension_install_ui.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/common/extensions/extension.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-
-class Profile;
-
-namespace {
-
-// Left or right margin.
-const int kPanelHorizMargin = 13;
-
-void OnDialogResponse(GtkDialog* dialog, int response_id,
-                      ExtensionInstallUI::Delegate* delegate) {
-  if (response_id == GTK_RESPONSE_ACCEPT) {
-    delegate->InstallUIProceed();
-  } else {
-    delegate->InstallUIAbort();
-  }
-
-  gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-void ShowInstallPromptDialog(GtkWindow* parent, SkBitmap* skia_icon,
-                             const Extension* extension,
-                             ExtensionInstallUI::Delegate *delegate,
-                             ExtensionInstallUI::PromptType type) {
-  // Build the dialog.
-  int title_id = ExtensionInstallUI::kTitleIds[type];
-  int button_id = ExtensionInstallUI::kButtonIds[type];
-  GtkWidget* dialog = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(title_id).c_str(),
-      parent,
-      GTK_DIALOG_MODAL,
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_CLOSE,
-      l10n_util::GetStringUTF8(button_id).c_str(),
-      GTK_RESPONSE_ACCEPT,
-      NULL);
-  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
-
-  // Create a two column layout.
-  GtkWidget* content_area = GTK_DIALOG(dialog)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* icon_hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_box_pack_start(GTK_BOX(content_area), icon_hbox, TRUE, TRUE, 0);
-
-  // Put Icon in the left column.
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(skia_icon);
-  GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf);
-  g_object_unref(pixbuf);
-  gtk_box_pack_start(GTK_BOX(icon_hbox), icon, TRUE, TRUE, 0);
-
-  // Create a new vbox for the right column.
-  GtkWidget* right_column_area = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(icon_hbox), right_column_area, TRUE, TRUE, 0);
-
-  int heading_id = ExtensionInstallUI::kHeadingIds[type];
-  std::string heading_text = l10n_util::GetStringFUTF8(
-      heading_id, UTF8ToUTF16(extension->name()));
-  GtkWidget* heading_label = gtk_label_new(heading_text.c_str());
-  gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5);
-  gtk_box_pack_start(GTK_BOX(right_column_area), heading_label, TRUE, TRUE, 0);
-
-  g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), delegate);
-  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-  gtk_widget_show_all(dialog);
-}
-
-}  // namespace
-
-void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl(
-    Profile* profile,
-    Delegate* delegate,
-    const Extension* extension,
-    SkBitmap* icon,
-    ExtensionInstallUI::PromptType type) {
-  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
-  if (!browser) {
-    delegate->InstallUIAbort();
-    return;
-  }
-
-  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
-      browser->window());
-  if (!browser_window) {
-    delegate->InstallUIAbort();
-    return;
-  }
-
-  ShowInstallPromptDialog(browser_window->window(), icon, extension, delegate,
-                          type);
-}
diff --git a/chrome/browser/gtk/extension_installed_bubble_gtk.cc b/chrome/browser/gtk/extension_installed_bubble_gtk.cc
deleted file mode 100644
index 9ca5854..0000000
--- a/chrome/browser/gtk/extension_installed_bubble_gtk.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/extension_installed_bubble_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/i18n/rtl.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/browser_actions_toolbar_gtk.h"
-#include "chrome/browser/gtk/browser_toolbar_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_action.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-const int kHorizontalColumnSpacing = 10;
-const int kIconPadding = 3;
-const int kIconSize = 43;
-const int kTextColumnVerticalSpacing = 7;
-const int kTextColumnWidth = 350;
-
-// When showing the bubble for a new browser action, we may have to wait for
-// the toolbar to finish animating to know where the item's final position
-// will be.
-const int kAnimationWaitRetries = 10;
-const int kAnimationWaitMS = 50;
-
-// Padding between content and edge of info bubble.
-const int kContentBorder = 7;
-
-}  // namespace
-
-void ExtensionInstalledBubbleGtk::Show(const Extension* extension,
-                                       Browser* browser,
-                                       SkBitmap icon) {
-  new ExtensionInstalledBubbleGtk(extension, browser, icon);
-}
-
-ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk(
-    const Extension* extension, Browser *browser, SkBitmap icon)
-    : extension_(extension),
-      browser_(browser),
-      icon_(icon),
-      animation_wait_retries_(kAnimationWaitRetries) {
-  AddRef();  // Balanced in Close().
-
-  if (!extension_->omnibox_keyword().empty()) {
-    type_ = OMNIBOX_KEYWORD;
-  } else if (extension_->browser_action()) {
-    type_ = BROWSER_ACTION;
-  } else if (extension->page_action() &&
-             !extension->page_action()->default_icon_path().empty()) {
-    type_ = PAGE_ACTION;
-  } else {
-    type_ = GENERIC;
-  }
-
-  // |extension| has been initialized but not loaded at this point. We need
-  // to wait on showing the Bubble until not only the EXTENSION_LOADED gets
-  // fired, but all of the EXTENSION_LOADED Observers have run. Only then can we
-  // be sure that a browser action or page action has had views created which we
-  // can inspect for the purpose of pointing to them.
-  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
-      Source<Profile>(browser->profile()));
-  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
-      Source<Profile>(browser->profile()));
-}
-
-ExtensionInstalledBubbleGtk::~ExtensionInstalledBubbleGtk() {}
-
-void ExtensionInstalledBubbleGtk::Observe(NotificationType type,
-                                          const NotificationSource& source,
-                                          const NotificationDetails& details) {
-  if (type == NotificationType::EXTENSION_LOADED) {
-    const Extension* extension = Details<const Extension>(details).ptr();
-    if (extension == extension_) {
-      // PostTask to ourself to allow all EXTENSION_LOADED Observers to run.
-      MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
-          &ExtensionInstalledBubbleGtk::ShowInternal));
-    }
-  } else if (type == NotificationType::EXTENSION_UNLOADED) {
-    const Extension* extension =
-        Details<UnloadedExtensionInfo>(details)->extension;
-    if (extension == extension_)
-      extension_ = NULL;
-  } else {
-    NOTREACHED() << L"Received unexpected notification";
-  }
-}
-
-void ExtensionInstalledBubbleGtk::ShowInternal() {
-  BrowserWindowGtk* browser_window =
-      BrowserWindowGtk::GetBrowserWindowForNativeWindow(
-          browser_->window()->GetNativeHandle());
-
-  GtkWidget* reference_widget = NULL;
-
-  if (type_ == BROWSER_ACTION) {
-    BrowserActionsToolbarGtk* toolbar =
-        browser_window->GetToolbar()->GetBrowserActionsToolbar();
-
-    if (toolbar->animating() && animation_wait_retries_-- > 0) {
-      MessageLoopForUI::current()->PostDelayedTask(
-          FROM_HERE,
-          NewRunnableMethod(this, &ExtensionInstalledBubbleGtk::ShowInternal),
-          kAnimationWaitMS);
-      return;
-    }
-
-    reference_widget = toolbar->GetBrowserActionWidget(extension_);
-    // glib delays recalculating layout, but we need reference_widget to know
-    // its coordinates, so we force a check_resize here.
-    gtk_container_check_resize(GTK_CONTAINER(
-        browser_window->GetToolbar()->widget()));
-    // If the widget is not visible then browser_window could be incognito
-    // with this extension disabled. Try showing it on the chevron.
-    // If that fails, fall back to default position.
-    if (reference_widget && !GTK_WIDGET_VISIBLE(reference_widget)) {
-      reference_widget = GTK_WIDGET_VISIBLE(toolbar->chevron()) ?
-          toolbar->chevron() : NULL;
-    }
-  } else if (type_ == PAGE_ACTION) {
-    LocationBarViewGtk* location_bar_view =
-        browser_window->GetToolbar()->GetLocationBarView();
-    location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(),
-                                                   true);  // preview_enabled
-    reference_widget = location_bar_view->GetPageActionWidget(
-        extension_->page_action());
-    // glib delays recalculating layout, but we need reference_widget to know
-    // it's coordinates, so we force a check_resize here.
-    gtk_container_check_resize(GTK_CONTAINER(
-        browser_window->GetToolbar()->widget()));
-    DCHECK(reference_widget);
-  } else if (type_ == OMNIBOX_KEYWORD) {
-    LocationBarViewGtk* location_bar_view =
-        browser_window->GetToolbar()->GetLocationBarView();
-    reference_widget = location_bar_view->location_entry_widget();
-    DCHECK(reference_widget);
-  }
-
-  // Default case.
-  if (reference_widget == NULL)
-    reference_widget = browser_window->GetToolbar()->GetAppMenuButton();
-
-  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
-      browser_->profile());
-
-  // Setup the InfoBubble content.
-  GtkWidget* bubble_content = gtk_hbox_new(FALSE, kHorizontalColumnSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder);
-
-  if (!icon_.isNull()) {
-    // Scale icon down to 43x43, but allow smaller icons (don't scale up).
-    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon_);
-    gfx::Size size(icon_.width(), icon_.height());
-    if (size.width() > kIconSize || size.height() > kIconSize) {
-      if (size.width() > size.height()) {
-        size.set_height(size.height() * kIconSize / size.width());
-        size.set_width(kIconSize);
-      } else {
-        size.set_width(size.width() * kIconSize / size.height());
-        size.set_height(kIconSize);
-      }
-
-      GdkPixbuf* old = pixbuf;
-      pixbuf = gdk_pixbuf_scale_simple(pixbuf, size.width(), size.height(),
-                                       GDK_INTERP_BILINEAR);
-      g_object_unref(old);
-    }
-
-    // Put Icon in top of the left column.
-    GtkWidget* icon_column = gtk_vbox_new(FALSE, 0);
-    // Use 3 pixel padding to get visual balance with InfoBubble border on the
-    // left.
-    gtk_box_pack_start(GTK_BOX(bubble_content), icon_column, FALSE, FALSE,
-                       kIconPadding);
-    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
-    g_object_unref(pixbuf);
-    gtk_box_pack_start(GTK_BOX(icon_column), image, FALSE, FALSE, 0);
-  }
-
-  // Center text column.
-  GtkWidget* text_column = gtk_vbox_new(FALSE, kTextColumnVerticalSpacing);
-  gtk_box_pack_start(GTK_BOX(bubble_content), text_column, FALSE, FALSE, 0);
-
-  // Heading label
-  GtkWidget* heading_label = gtk_label_new(NULL);
-  string16 extension_name = UTF8ToUTF16(extension_->name());
-  base::i18n::AdjustStringForLocaleDirection(&extension_name);
-  std::string heading_text = l10n_util::GetStringFUTF8(
-      IDS_EXTENSION_INSTALLED_HEADING, extension_name);
-  char* markup = g_markup_printf_escaped("<span size=\"larger\">%s</span>",
-      heading_text.c_str());
-  gtk_label_set_markup(GTK_LABEL(heading_label), markup);
-  g_free(markup);
-
-  gtk_label_set_line_wrap(GTK_LABEL(heading_label), TRUE);
-  gtk_widget_set_size_request(heading_label, kTextColumnWidth, -1);
-  gtk_box_pack_start(GTK_BOX(text_column), heading_label, FALSE, FALSE, 0);
-
-  // Page action label
-  if (type_ == PAGE_ACTION) {
-    GtkWidget* info_label = gtk_label_new(l10n_util::GetStringUTF8(
-        IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO).c_str());
-    gtk_label_set_line_wrap(GTK_LABEL(info_label), TRUE);
-    gtk_widget_set_size_request(info_label, kTextColumnWidth, -1);
-    gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
-  }
-
-  // Omnibox keyword label
-  if (type_ == OMNIBOX_KEYWORD) {
-    GtkWidget* info_label = gtk_label_new(l10n_util::GetStringFUTF8(
-        IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
-        UTF8ToUTF16(extension_->omnibox_keyword())).c_str());
-    gtk_label_set_line_wrap(GTK_LABEL(info_label), TRUE);
-    gtk_widget_set_size_request(info_label, kTextColumnWidth, -1);
-    gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
-  }
-
-  // Manage label
-  GtkWidget* manage_label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALLED_MANAGE_INFO).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(manage_label), TRUE);
-  gtk_widget_set_size_request(manage_label, kTextColumnWidth, -1);
-  gtk_box_pack_start(GTK_BOX(text_column), manage_label, FALSE, FALSE, 0);
-
-  // Create and pack the close button.
-  GtkWidget* close_column = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(bubble_content), close_column, FALSE, FALSE, 0);
-  close_button_.reset(CustomDrawButton::CloseButton(theme_provider));
-  g_signal_connect(close_button_->widget(), "clicked",
-                   G_CALLBACK(OnButtonClick), this);
-  gtk_box_pack_start(GTK_BOX(close_column), close_button_->widget(),
-      FALSE, FALSE, 0);
-
-  InfoBubbleGtk::ArrowLocationGtk arrow_location =
-      !base::i18n::IsRTL() ?
-      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
-      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
-
-  gfx::Rect bounds = gtk_util::WidgetBounds(reference_widget);
-  if (type_ == OMNIBOX_KEYWORD) {
-    // Reverse the arrow for omnibox keywords, since the bubble will be on the
-    // other side of the window. We also clear the width to avoid centering
-    // the popup on the URL bar.
-    arrow_location =
-        !base::i18n::IsRTL() ?
-        InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
-        InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
-    if (base::i18n::IsRTL())
-      bounds.Offset(bounds.width(), 0);
-    bounds.set_width(0);
-  }
-
-  info_bubble_ = InfoBubbleGtk::Show(reference_widget,
-      &bounds,
-      bubble_content,
-      arrow_location,
-      true,  // match_system_theme
-      true,  // grab_input
-      theme_provider,
-      this);
-}
-
-// static
-void ExtensionInstalledBubbleGtk::OnButtonClick(GtkWidget* button,
-    ExtensionInstalledBubbleGtk* bubble) {
-  if (button == bubble->close_button_->widget()) {
-    bubble->info_bubble_->Close();
-  } else {
-    NOTREACHED();
-  }
-}
-// InfoBubbleDelegate
-void ExtensionInstalledBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                                    bool closed_by_escape) {
-  if (extension_ && type_ == PAGE_ACTION) {
-    // Turn the page action preview off.
-    BrowserWindowGtk* browser_window =
-          BrowserWindowGtk::GetBrowserWindowForNativeWindow(
-              browser_->window()->GetNativeHandle());
-    LocationBarViewGtk* location_bar_view =
-        browser_window->GetToolbar()->GetLocationBarView();
-    location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(),
-                                                   false);  // preview_enabled
-  }
-
-  // We need to allow the info bubble to close and remove the widgets from
-  // the window before we call Release() because close_button_ depends
-  // on all references being cleared before it is destroyed.
-  MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
-      &ExtensionInstalledBubbleGtk::Close));
-}
-
-void ExtensionInstalledBubbleGtk::Close() {
-  Release();  // Balanced in ctor.
-  info_bubble_ = NULL;
-}
diff --git a/chrome/browser/gtk/extension_installed_bubble_gtk.h b/chrome/browser/gtk/extension_installed_bubble_gtk.h
deleted file mode 100644
index 0613283..0000000
--- a/chrome/browser/gtk/extension_installed_bubble_gtk.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_EXTENSION_INSTALLED_BUBBLE_GTK_H_
-#define CHROME_BROWSER_GTK_EXTENSION_INSTALLED_BUBBLE_GTK_H_
-#pragma once
-
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-class Browser;
-class BrowserWindowGtk;
-class Extension;
-class SkBitmap;
-
-// Provides feedback to the user upon successful installation of an
-// extension. Depending on the type of extension, the InfoBubble will
-// point to:
-//    OMNIBOX_KEYWORD-> The omnibox.
-//    BROWSER_ACTION -> The browserAction icon in the toolbar.
-//    PAGE_ACTION    -> A preview of the page action icon in the location
-//                      bar which is shown while the InfoBubble is shown.
-//    GENERIC        -> The wrench menu. This case includes page actions that
-//                      don't specify a default icon.
-//
-// ExtensionInstallBubble manages its own lifetime.
-class ExtensionInstalledBubbleGtk
-    : public InfoBubbleGtkDelegate,
-      public NotificationObserver,
-      public base::RefCountedThreadSafe<ExtensionInstalledBubbleGtk> {
- public:
-  // The behavior and content of this InfoBubble comes in three varieties.
-  enum BubbleType {
-    OMNIBOX_KEYWORD,
-    BROWSER_ACTION,
-    PAGE_ACTION,
-    GENERIC
-  };
-
-  // Creates the ExtensionInstalledBubble and schedules it to be shown once
-  // the extension has loaded. |extension| is the installed extension. |browser|
-  // is the browser window which will host the bubble. |icon| is the install
-  // icon of the extension.
-  static void Show(const Extension* extension, Browser *browser, SkBitmap icon);
-
- private:
-  friend class base::RefCountedThreadSafe<ExtensionInstalledBubbleGtk>;
-
-  // Private ctor. Registers a listener for EXTENSION_LOADED.
-  ExtensionInstalledBubbleGtk(const Extension* extension, Browser *browser,
-                              SkBitmap icon);
-
-  virtual ~ExtensionInstalledBubbleGtk();
-
-  // Shows the bubble. Called internally via PostTask.
-  void ShowInternal();
-
-  // NotificationObserver
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // InfoBubbleDelegate
-  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                 bool closed_by_escape);
-
-  // Calls Release() internally. Called internally via PostTask.
-  void Close();
-
-  static void OnButtonClick(GtkWidget* button,
-                            ExtensionInstalledBubbleGtk* toolbar);
-
-  const Extension* extension_;
-  Browser *browser_;
-  SkBitmap icon_;
-  NotificationRegistrar registrar_;
-  BubbleType type_;
-
-  // The number of times to retry showing the bubble if the browser action
-  // toolbar is animating.
-  int animation_wait_retries_;
-
-  // The 'x' that the user can press to hide the info bubble shelf.
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  InfoBubbleGtk* info_bubble_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_EXTENSION_INSTALLED_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/extension_popup_gtk.cc b/chrome/browser/gtk/extension_popup_gtk.cc
deleted file mode 100644
index f1faf37..0000000
--- a/chrome/browser/gtk/extension_popup_gtk.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/extension_popup_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <algorithm>
-
-#include "base/i18n/rtl.h"
-#include "base/message_loop.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/debugger/devtools_manager.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_process_manager.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "googleurl/src/gurl.h"
-
-ExtensionPopupGtk* ExtensionPopupGtk::current_extension_popup_ = NULL;
-
-// The minimum/maximum dimensions of the extension popup.
-// The minimum is just a little larger than the size of a browser action button.
-// The maximum is an arbitrary number that should be smaller than most screens.
-const int ExtensionPopupGtk::kMinWidth = 25;
-const int ExtensionPopupGtk::kMinHeight = 25;
-const int ExtensionPopupGtk::kMaxWidth = 800;
-const int ExtensionPopupGtk::kMaxHeight = 600;
-
-ExtensionPopupGtk::ExtensionPopupGtk(Browser* browser,
-                                     ExtensionHost* host,
-                                     GtkWidget* anchor,
-                                     bool inspect)
-    : browser_(browser),
-      bubble_(NULL),
-      host_(host),
-      anchor_(anchor),
-      being_inspected_(inspect),
-      method_factory_(this) {
-  host_->view()->SetContainer(this);
-
-  // If the host had somehow finished loading, then we'd miss the notification
-  // and not show.  This seems to happen in single-process mode.
-  if (host->did_stop_loading()) {
-    ShowPopup();
-  } else {
-    registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING,
-                   Source<Profile>(host->profile()));
-  }
-
-  registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
-                 Source<Profile>(host->profile()));
-}
-
-ExtensionPopupGtk::~ExtensionPopupGtk() {
-}
-
-void ExtensionPopupGtk::Observe(NotificationType type,
-                                const NotificationSource& source,
-                                const NotificationDetails& details) {
-  switch (type.value) {
-    case NotificationType::EXTENSION_HOST_DID_STOP_LOADING:
-      if (Details<ExtensionHost>(host_.get()) == details)
-        ShowPopup();
-      break;
-    case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE:
-      if (Details<ExtensionHost>(host_.get()) == details)
-        DestroyPopup();
-      break;
-    case NotificationType::DEVTOOLS_WINDOW_CLOSING:
-      // Make sure its the devtools window that inspecting our popup.
-      if (Details<RenderViewHost>(host_->render_view_host()) != details)
-        break;
-
-      // If the devtools window is closing, we post a task to ourselves to
-      // close the popup. This gives the devtools window a chance to finish
-      // detaching from the inspected RenderViewHost.
-      MessageLoop::current()->PostTask(FROM_HERE,
-          method_factory_.NewRunnableMethod(&ExtensionPopupGtk::DestroyPopup));
-      break;
-    default:
-      NOTREACHED() << "Received unexpected notification";
-  }
-}
-
-void ExtensionPopupGtk::ShowPopup() {
-  if (bubble_) {
-    NOTREACHED();
-    return;
-  }
-
-  if (being_inspected_) {
-    DevToolsManager::GetInstance()->OpenDevToolsWindow(
-        host_->render_view_host());
-    // Listen for the the devtools window closing.
-    registrar_.Add(this, NotificationType::DEVTOOLS_WINDOW_CLOSING,
-        Source<Profile>(host_->profile()));
-  }
-
-  // Only one instance should be showing at a time. Get rid of the old one, if
-  // any. Typically, |current_extension_popup_| will be NULL, but it can be
-  // non-NULL if a browser action button is clicked while another extension
-  // popup's extension host is still loading.
-  if (current_extension_popup_)
-    current_extension_popup_->DestroyPopup();
-  current_extension_popup_ = this;
-
-  // We'll be in the upper-right corner of the window for LTR languages, so we
-  // want to put the arrow at the upper-right corner of the bubble to match the
-  // page and app menus.
-  InfoBubbleGtk::ArrowLocationGtk arrow_location =
-      !base::i18n::IsRTL() ?
-      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
-      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
-  bubble_ = InfoBubbleGtk::Show(anchor_,
-                                NULL,
-                                host_->view()->native_view(),
-                                arrow_location,
-                                false,  // match_system_theme
-                                !being_inspected_,  // grab_input
-                                GtkThemeProvider::GetFrom(browser_->profile()),
-                                this);
-}
-
-bool ExtensionPopupGtk::DestroyPopup() {
-  if (!bubble_) {
-    NOTREACHED();
-    return false;
-  }
-
-  bubble_->Close();
-  return true;
-}
-
-void ExtensionPopupGtk::InfoBubbleClosing(InfoBubbleGtk* bubble,
-                                          bool closed_by_escape) {
-  current_extension_popup_ = NULL;
-  delete this;
-}
-
-void ExtensionPopupGtk::OnExtensionPreferredSizeChanged(
-    ExtensionViewGtk* view,
-    const gfx::Size& new_size) {
-  int width = std::max(kMinWidth, std::min(kMaxWidth, new_size.width()));
-  int height = std::max(kMinHeight, std::min(kMaxHeight, new_size.height()));
-
-  view->render_view_host()->view()->SetSize(gfx::Size(width, height));
-  gtk_widget_set_size_request(view->native_view(), width, height);
-}
-
-// static
-void ExtensionPopupGtk::Show(const GURL& url, Browser* browser,
-    GtkWidget* anchor, bool inspect) {
-  ExtensionProcessManager* manager =
-      browser->profile()->GetExtensionProcessManager();
-  DCHECK(manager);
-  if (!manager)
-    return;
-
-  ExtensionHost* host = manager->CreatePopup(url, browser);
-  // This object will delete itself when the info bubble is closed.
-  new ExtensionPopupGtk(browser, host, anchor, inspect);
-}
-
-gfx::Rect ExtensionPopupGtk::GetViewBounds() {
-  return gfx::Rect(host_->view()->native_view()->allocation);
-}
diff --git a/chrome/browser/gtk/extension_popup_gtk.h b/chrome/browser/gtk/extension_popup_gtk.h
deleted file mode 100644
index df983de..0000000
--- a/chrome/browser/gtk/extension_popup_gtk.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_EXTENSION_POPUP_GTK_H_
-#define CHROME_BROWSER_GTK_EXTENSION_POPUP_GTK_H_
-#pragma once
-
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "chrome/browser/gtk/extension_view_gtk.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
-
-class Browser;
-class ExtensionHost;
-class GURL;
-
-class ExtensionPopupGtk : public NotificationObserver,
-                          public InfoBubbleGtkDelegate,
-                          public ExtensionViewGtk::Container {
- public:
-  ExtensionPopupGtk(Browser* browser,
-                    ExtensionHost* host,
-                    GtkWidget* anchor,
-                    bool inspect);
-  virtual ~ExtensionPopupGtk();
-
-  static void Show(const GURL& url,
-                   Browser* browser,
-                   GtkWidget* anchor,
-                   bool inspect);
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // InfoBubbleGtkDelegate implementation.
-  virtual void InfoBubbleClosing(InfoBubbleGtk* bubble,
-                                 bool closed_by_escape);
-
-  // ExtensionViewGtk::Container implementation
-  virtual void OnExtensionPreferredSizeChanged(ExtensionViewGtk* view,
-                                               const gfx::Size& new_size);
-
-  // Destroys the popup widget. This will in turn destroy us since we delete
-  // ourselves when the info bubble closes. Returns true if we successfully
-  // closed the bubble.
-  bool DestroyPopup();
-
-  // Get the currently showing extension popup, or NULL.
-  static ExtensionPopupGtk* get_current_extension_popup() {
-    return current_extension_popup_;
-  }
-
-  bool being_inspected() const {
-    return being_inspected_;
-  }
-
-  // Declared here for testing.
-  static const int kMinWidth;
-  static const int kMinHeight;
-  static const int kMaxWidth;
-  static const int kMaxHeight;
-
- private:
-  // Shows the popup widget. Called after loading completes.
-  void ShowPopup();
-
-  Browser* browser_;
-
-  InfoBubbleGtk* bubble_;
-
-  // We take ownership of the popup ExtensionHost.
-  scoped_ptr<ExtensionHost> host_;
-
-  // The widget for anchoring the position of the info bubble.
-  GtkWidget* anchor_;
-
-  NotificationRegistrar registrar_;
-
-  static ExtensionPopupGtk* current_extension_popup_;
-
-  // Whether a devtools window is attached to this bubble.
-  bool being_inspected_;
-
-  ScopedRunnableMethodFactory<ExtensionPopupGtk> method_factory_;
-
-  // Used for testing. ---------------------------------------------------------
-  gfx::Rect GetViewBounds();
-
-  friend class BrowserActionTestUtil;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionPopupGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_EXTENSION_POPUP_GTK_H_
diff --git a/chrome/browser/gtk/extension_view_gtk.cc b/chrome/browser/gtk/extension_view_gtk.cc
deleted file mode 100644
index f2e49c3..0000000
--- a/chrome/browser/gtk/extension_view_gtk.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/extension_view_gtk.h"
-
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/gtk/extension_popup_gtk.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
-
-ExtensionViewGtk::ExtensionViewGtk(ExtensionHost* extension_host,
-                                   Browser* browser)
-    : browser_(browser),
-      extension_host_(extension_host),
-      render_widget_host_view_(NULL),
-      container_(NULL) {
-}
-
-void ExtensionViewGtk::Init() {
-  CreateWidgetHostView();
-}
-
-gfx::NativeView ExtensionViewGtk::native_view() {
-  return render_widget_host_view_->native_view();
-}
-
-RenderViewHost* ExtensionViewGtk::render_view_host() const {
-  return extension_host_->render_view_host();
-}
-
-void ExtensionViewGtk::SetBackground(const SkBitmap& background) {
-  if (render_view_host()->IsRenderViewLive()) {
-    render_widget_host_view_->SetBackground(background);
-  } else {
-    pending_background_ = background;
-  }
-}
-
-void ExtensionViewGtk::UpdatePreferredSize(const gfx::Size& new_size) {
-  if (container_)
-    container_->OnExtensionPreferredSizeChanged(this, new_size);
-}
-
-void ExtensionViewGtk::CreateWidgetHostView() {
-  DCHECK(!render_widget_host_view_);
-  render_widget_host_view_ = new RenderWidgetHostViewGtk(render_view_host());
-  render_widget_host_view_->InitAsChild();
-
-  extension_host_->CreateRenderViewSoon(render_widget_host_view_);
-}
-
-void ExtensionViewGtk::RenderViewCreated() {
-  if (!pending_background_.empty() && render_view_host()->view()) {
-    render_widget_host_view_->SetBackground(pending_background_);
-    pending_background_.reset();
-  }
-
-  // Tell the renderer not to draw scrollbars in popups unless the
-  // popups are at the maximum allowed size.
-  gfx::Size largest_popup_size(ExtensionPopupGtk::kMaxWidth,
-                               ExtensionPopupGtk::kMaxHeight);
-  extension_host_->DisableScrollbarsForSmallWindows(largest_popup_size);
-}
diff --git a/chrome/browser/gtk/extension_view_gtk.h b/chrome/browser/gtk/extension_view_gtk.h
deleted file mode 100644
index 5e5f436..0000000
--- a/chrome/browser/gtk/extension_view_gtk.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_EXTENSION_VIEW_GTK_H_
-#define CHROME_BROWSER_GTK_EXTENSION_VIEW_GTK_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/size.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-class Browser;
-class ExtensionHost;
-class RenderViewHost;
-class RenderWidgetHostViewGtk;
-class SkBitmap;
-
-class ExtensionViewGtk {
- public:
-  ExtensionViewGtk(ExtensionHost* extension_host, Browser* browser);
-
-  class Container {
-   public:
-    virtual ~Container() {}
-    virtual void OnExtensionPreferredSizeChanged(ExtensionViewGtk* view,
-                                                 const gfx::Size& new_size) {}
-  };
-
-  void Init();
-
-  gfx::NativeView native_view();
-  Browser* browser() const { return browser_; }
-
-  void SetBackground(const SkBitmap& background);
-
-  // Sets the container for this view.
-  void SetContainer(Container* container) { container_ = container; }
-
-  // Method for the ExtensionHost to notify us about the correct size for
-  // extension contents.
-  void UpdatePreferredSize(const gfx::Size& new_size);
-
-  // Method for the ExtensionHost to notify us when the RenderViewHost has a
-  // connection.
-  void RenderViewCreated();
-
-  RenderViewHost* render_view_host() const;
-
- private:
-  void CreateWidgetHostView();
-
-  Browser* browser_;
-
-  ExtensionHost* extension_host_;
-
-  RenderWidgetHostViewGtk* render_widget_host_view_;
-
-  // The background the view should have once it is initialized. This is set
-  // when the view has a custom background, but hasn't been initialized yet.
-  SkBitmap pending_background_;
-
-  // This view's container.
-  Container* container_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionViewGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_EXTENSION_VIEW_GTK_H_
diff --git a/chrome/browser/gtk/external_protocol_dialog_gtk.cc b/chrome/browser/gtk/external_protocol_dialog_gtk.cc
deleted file mode 100644
index 34c2f78..0000000
--- a/chrome/browser/gtk/external_protocol_dialog_gtk.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/external_protocol_dialog_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "app/text_elider.h"
-#include "base/metrics/histogram.h"
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/external_protocol_handler.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/tab_contents/tab_util.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-const int kMessageWidth = 400;
-
-}  // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// ExternalProtocolHandler
-
-// static
-void ExternalProtocolHandler::RunExternalProtocolDialog(
-    const GURL& url, int render_process_host_id, int routing_id) {
-  new ExternalProtocolDialogGtk(url);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// ExternalProtocolDialogGtk
-
-ExternalProtocolDialogGtk::ExternalProtocolDialogGtk(const GURL& url)
-    : url_(url),
-      creation_time_(base::TimeTicks::Now()) {
-  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_TITLE).c_str(),
-      NULL,
-      GTK_DIALOG_NO_SEPARATOR,
-      NULL);
-
-  // Add the response buttons.
-  gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(
-          IDS_EXTERNAL_PROTOCOL_CANCEL_BUTTON_TEXT).c_str(),
-      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
-  gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT).c_str(),
-      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
-
-  // Construct the message text.
-  const int kMaxUrlWithoutSchemeSize = 256;
-  const int kMaxCommandSize = 256;
-  std::wstring elided_url_without_scheme;
-  std::wstring elided_command;
-  gfx::ElideString(ASCIIToWide(url.possibly_invalid_spec()),
-      kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
-  gfx::ElideString(ASCIIToWide(std::string("xdg-open ") + url.spec()),
-      kMaxCommandSize, &elided_command);
-
-  std::string message_text = l10n_util::GetStringFUTF8(
-      IDS_EXTERNAL_PROTOCOL_INFORMATION,
-      ASCIIToUTF16(url.scheme() + ":"),
-      WideToUTF16(elided_url_without_scheme)) + "\n\n";
-
-  message_text += l10n_util::GetStringFUTF8(
-      IDS_EXTERNAL_PROTOCOL_APPLICATION_TO_LAUNCH,
-      WideToUTF16(elided_command)) + "\n\n";
-
-  message_text += l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_WARNING);
-
-  // Create the content-holding vbox.
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox),
-                                 gtk_util::kContentAreaBorder);
-
-  // Add the message text.
-  GtkWidget* label = gtk_label_new(message_text.c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  gtk_widget_set_size_request(label, kMessageWidth, -1);
-  gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
-
-  // Add the checkbox.
-  checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), checkbox_,
-                     FALSE, FALSE, 0);
-
-  // Add our vbox to the dialog.
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), vbox,
-                     FALSE, FALSE, 0);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-
-  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
-  gtk_widget_show_all(dialog_);
-}
-
-void ExternalProtocolDialogGtk::OnDialogResponse(GtkWidget* widget,
-                                                 int response) {
-  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox_))) {
-    if (response == GTK_RESPONSE_ACCEPT) {
-      ExternalProtocolHandler::SetBlockState(
-          url_.scheme(), ExternalProtocolHandler::DONT_BLOCK);
-    } else if (response == GTK_RESPONSE_REJECT) {
-      ExternalProtocolHandler::SetBlockState(
-          url_.scheme(), ExternalProtocolHandler::BLOCK);
-    }
-    // If the response is GTK_RESPONSE_DELETE, triggered by the user closing
-    // the dialog, do nothing.
-  }
-
-  if (response == GTK_RESPONSE_ACCEPT) {
-    UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url",
-                             base::TimeTicks::Now() - creation_time_);
-
-    ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_);
-  }
-
-  gtk_widget_destroy(dialog_);
-  delete this;
-}
diff --git a/chrome/browser/gtk/external_protocol_dialog_gtk.h b/chrome/browser/gtk/external_protocol_dialog_gtk.h
deleted file mode 100644
index 0703bc8..0000000
--- a/chrome/browser/gtk/external_protocol_dialog_gtk.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/time.h"
-#include "googleurl/src/gurl.h"
-
-class TabContents;
-
-typedef struct _GtkWidget GtkWidget;
-
-class ExternalProtocolDialogGtk {
- public:
-  explicit ExternalProtocolDialogGtk(const GURL& url);
-
- protected:
-  virtual ~ExternalProtocolDialogGtk() {}
-
- private:
-  CHROMEGTK_CALLBACK_1(ExternalProtocolDialogGtk, void, OnDialogResponse, int);
-
-  GtkWidget* dialog_;
-  GtkWidget* checkbox_;
-  GURL url_;
-  base::TimeTicks creation_time_;
-};
-
-#endif  // CHROME_BROWSER_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/find_bar_gtk.cc b/chrome/browser/gtk/find_bar_gtk.cc
deleted file mode 100644
index ddd9955..0000000
--- a/chrome/browser/gtk/find_bar_gtk.cc
+++ /dev/null
@@ -1,992 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/find_bar_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/i18n/rtl.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_floating_container.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/nine_box.h"
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-#include "chrome/browser/gtk/tab_contents_container_gtk.h"
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/ui/find_bar/find_bar_state.h"
-#include "chrome/common/native_web_keyboard_event.h"
-#include "chrome/common/notification_service.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// Used as the color of the text in the entry box and the text for the results
-// label for failure searches.
-const GdkColor kEntryTextColor = gtk_util::kGdkBlack;
-
-// Used as the color of the background of the entry box and the background of
-// the find label for successful searches.
-const GdkColor kEntryBackgroundColor = gtk_util::kGdkWhite;
-const GdkColor kFindFailureBackgroundColor = GDK_COLOR_RGB(255, 102, 102);
-const GdkColor kFindSuccessTextColor = GDK_COLOR_RGB(178, 178, 178);
-
-// Padding around the container.
-const int kBarPaddingTopBottom = 4;
-const int kEntryPaddingLeft = 6;
-const int kCloseButtonPaddingLeft = 3;
-const int kBarPaddingRight = 4;
-
-// The height of the findbar dialog, as dictated by the size of the background
-// images.
-const int kFindBarHeight = 32;
-
-// The width of the text entry field.
-const int kTextEntryWidth = 220;
-
-// The size of the "rounded" corners.
-const int kCornerSize = 3;
-
-enum FrameType {
-  FRAME_MASK,
-  FRAME_STROKE,
-};
-
-// Returns a list of points that either form the outline of the status bubble
-// (|type| == FRAME_MASK) or form the inner border around the inner edge
-// (|type| == FRAME_STROKE).
-std::vector<GdkPoint> MakeFramePolygonPoints(int width,
-                                             int height,
-                                             FrameType type) {
-  using gtk_util::MakeBidiGdkPoint;
-  std::vector<GdkPoint> points;
-
-  bool ltr = !base::i18n::IsRTL();
-  // If we have a stroke, we have to offset some of our points by 1 pixel.
-  // We have to inset by 1 pixel when we draw horizontal lines that are on the
-  // bottom or when we draw vertical lines that are closer to the end (end is
-  // right for ltr).
-  int y_off = (type == FRAME_MASK) ? 0 : -1;
-  // We use this one for LTR.
-  int x_off_l = ltr ? y_off : 0;
-  // We use this one for RTL.
-  int x_off_r = !ltr ? -y_off : 0;
-
-  // Top left corner
-  points.push_back(MakeBidiGdkPoint(x_off_r, 0, width, ltr));
-  points.push_back(MakeBidiGdkPoint(
-      kCornerSize + x_off_r, kCornerSize, width, ltr));
-
-  // Bottom left corner
-  points.push_back(MakeBidiGdkPoint(
-      kCornerSize + x_off_r, height - kCornerSize, width, ltr));
-  points.push_back(MakeBidiGdkPoint(
-      (2 * kCornerSize) + x_off_l, height + y_off,
-      width, ltr));
-
-  // Bottom right corner
-  points.push_back(MakeBidiGdkPoint(
-      width - (2 * kCornerSize) + x_off_r, height + y_off,
-      width, ltr));
-  points.push_back(MakeBidiGdkPoint(
-      width - kCornerSize + x_off_l, height - kCornerSize, width, ltr));
-
-  // Top right corner
-  points.push_back(MakeBidiGdkPoint(
-      width - kCornerSize + x_off_l, kCornerSize, width, ltr));
-  points.push_back(MakeBidiGdkPoint(width + x_off_l, 0, width, ltr));
-
-  return points;
-}
-
-// Give the findbar dialog its unique shape using images.
-void SetDialogShape(GtkWidget* widget) {
-  static NineBox* dialog_shape = NULL;
-  if (!dialog_shape) {
-    dialog_shape = new NineBox(
-      IDR_FIND_DLG_LEFT_BACKGROUND,
-      IDR_FIND_DLG_MIDDLE_BACKGROUND,
-      IDR_FIND_DLG_RIGHT_BACKGROUND,
-      0, 0, 0, 0, 0, 0);
-    dialog_shape->ChangeWhiteToTransparent();
-  }
-
-  dialog_shape->ContourWidget(widget);
-}
-
-// Return a ninebox that will paint the border of the findbar dialog. This is
-// shared across all instances of the findbar. Do not free the returned pointer.
-const NineBox* GetDialogBorder() {
-  static NineBox* dialog_border = NULL;
-  if (!dialog_border) {
-    dialog_border = new NineBox(
-      IDR_FIND_DIALOG_LEFT,
-      IDR_FIND_DIALOG_MIDDLE,
-      IDR_FIND_DIALOG_RIGHT,
-      0, 0, 0, 0, 0, 0);
-  }
-
-  return dialog_border;
-}
-
-// Like gtk_util::CreateGtkBorderBin, but allows control over the alignment and
-// returns both the event box and the alignment so we can modify it during its
-// lifetime (i.e. during a theme change).
-void BuildBorder(GtkWidget* child,
-                 bool center,
-                 int padding_top, int padding_bottom, int padding_left,
-                 int padding_right,
-                 GtkWidget** ebox, GtkWidget** alignment) {
-  *ebox = gtk_event_box_new();
-  if (center)
-    *alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
-  else
-    *alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(*alignment),
-                            padding_top, padding_bottom, padding_left,
-                            padding_right);
-  gtk_container_add(GTK_CONTAINER(*alignment), child);
-  gtk_container_add(GTK_CONTAINER(*ebox), *alignment);
-}
-
-}  // namespace
-
-FindBarGtk::FindBarGtk(Browser* browser)
-    : browser_(browser),
-      window_(static_cast<BrowserWindowGtk*>(browser->window())),
-      theme_provider_(GtkThemeProvider::GetFrom(browser->profile())),
-      container_width_(-1),
-      container_height_(-1),
-      match_label_failure_(false),
-      ignore_changed_signal_(false) {
-  InitWidgets();
-  ViewIDUtil::SetID(text_entry_, VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
-
-  // Insert the widget into the browser gtk hierarchy.
-  window_->AddFindBar(this);
-
-  // Hook up signals after the widget has been added to the hierarchy so the
-  // widget will be realized.
-  g_signal_connect(text_entry_, "changed",
-                   G_CALLBACK(OnChanged), this);
-  g_signal_connect_after(text_entry_, "key-press-event",
-                         G_CALLBACK(OnKeyPressEvent), this);
-  g_signal_connect_after(text_entry_, "key-release-event",
-                         G_CALLBACK(OnKeyReleaseEvent), this);
-  // When the user tabs to us or clicks on us, save where the focus used to
-  // be.
-  g_signal_connect(text_entry_, "focus",
-                   G_CALLBACK(OnFocus), this);
-  gtk_widget_add_events(text_entry_, GDK_BUTTON_PRESS_MASK);
-  g_signal_connect(text_entry_, "button-press-event",
-                   G_CALLBACK(OnButtonPress), this);
-  g_signal_connect(text_entry_, "move-cursor", G_CALLBACK(OnMoveCursor), this);
-  g_signal_connect(text_entry_, "activate", G_CALLBACK(OnActivate), this);
-  g_signal_connect(text_entry_, "direction-changed",
-                   G_CALLBACK(OnWidgetDirectionChanged), this);
-  g_signal_connect(text_entry_, "focus-in-event",
-                   G_CALLBACK(OnFocusIn), this);
-  g_signal_connect(text_entry_, "focus-out-event",
-                   G_CALLBACK(OnFocusOut), this);
-  g_signal_connect(container_, "expose-event",
-                   G_CALLBACK(OnExpose), this);
-}
-
-FindBarGtk::~FindBarGtk() {
-}
-
-void FindBarGtk::InitWidgets() {
-  // The find bar is basically an hbox with a gtkentry (text box) followed by 3
-  // buttons (previous result, next result, close).  We wrap the hbox in a gtk
-  // alignment and a gtk event box to get the padding and light blue
-  // background. We put that event box in a fixed in order to control its
-  // lateral position. We put that fixed in a SlideAnimatorGtk in order to get
-  // the slide effect.
-  GtkWidget* hbox = gtk_hbox_new(false, 0);
-  container_ = gtk_util::CreateGtkBorderBin(hbox, NULL,
-      kBarPaddingTopBottom, kBarPaddingTopBottom,
-      kEntryPaddingLeft, kBarPaddingRight);
-  ViewIDUtil::SetID(container_, VIEW_ID_FIND_IN_PAGE);
-  gtk_widget_set_app_paintable(container_, TRUE);
-
-  slide_widget_.reset(new SlideAnimatorGtk(container_,
-                                           SlideAnimatorGtk::DOWN,
-                                           0, false, false, NULL));
-
-  close_button_.reset(CustomDrawButton::CloseButton(theme_provider_));
-  gtk_util::CenterWidgetInHBox(hbox, close_button_->widget(), true,
-                               kCloseButtonPaddingLeft);
-  g_signal_connect(close_button_->widget(), "clicked",
-                   G_CALLBACK(OnClicked), this);
-  gtk_widget_set_tooltip_text(close_button_->widget(),
-      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_CLOSE_TOOLTIP).c_str());
-
-  find_next_button_.reset(new CustomDrawButton(theme_provider_,
-      IDR_FINDINPAGE_NEXT, IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_H,
-      IDR_FINDINPAGE_NEXT_P, GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU));
-  g_signal_connect(find_next_button_->widget(), "clicked",
-                   G_CALLBACK(OnClicked), this);
-  gtk_widget_set_tooltip_text(find_next_button_->widget(),
-      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_NEXT_TOOLTIP).c_str());
-  gtk_box_pack_end(GTK_BOX(hbox), find_next_button_->widget(),
-                   FALSE, FALSE, 0);
-
-  find_previous_button_.reset(new CustomDrawButton(theme_provider_,
-      IDR_FINDINPAGE_PREV, IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_H,
-      IDR_FINDINPAGE_PREV_P, GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU));
-  g_signal_connect(find_previous_button_->widget(), "clicked",
-                   G_CALLBACK(OnClicked), this);
-  gtk_widget_set_tooltip_text(find_previous_button_->widget(),
-      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP).c_str());
-  gtk_box_pack_end(GTK_BOX(hbox), find_previous_button_->widget(),
-                   FALSE, FALSE, 0);
-
-  // Make a box for the edit and match count widgets. This is fixed size since
-  // we want the widgets inside to resize themselves rather than making the
-  // dialog bigger.
-  GtkWidget* content_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_widget_set_size_request(content_hbox, kTextEntryWidth, -1);
-
-  text_entry_ = gtk_entry_new();
-  gtk_entry_set_has_frame(GTK_ENTRY(text_entry_), FALSE);
-
-  match_count_label_ = gtk_label_new(NULL);
-  // This line adds padding on the sides so that the label has even padding on
-  // all edges.
-  gtk_misc_set_padding(GTK_MISC(match_count_label_), 2, 0);
-  match_count_event_box_ = gtk_event_box_new();
-  GtkWidget* match_count_centerer = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(match_count_centerer), match_count_event_box_,
-                     TRUE, TRUE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(match_count_centerer), 1);
-  gtk_container_add(GTK_CONTAINER(match_count_event_box_), match_count_label_);
-
-  gtk_box_pack_end(GTK_BOX(content_hbox), match_count_centerer,
-                   FALSE, FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(content_hbox), text_entry_, TRUE, TRUE, 0);
-
-  // This event box is necessary to color in the area above and below the match
-  // count label, and is where we draw the entry background onto in GTK mode.
-  BuildBorder(content_hbox, true, 0, 0, 0, 0,
-              &content_event_box_, &content_alignment_);
-  gtk_widget_set_app_paintable(content_event_box_, TRUE);
-  g_signal_connect(content_event_box_, "expose-event",
-                   G_CALLBACK(OnContentEventBoxExpose), this);
-
-  // This alignment isn't centered and is used for spacing in chrome theme
-  // mode. (It's also used in GTK mode for padding because left padding doesn't
-  // equal bottom padding naturally.)
-  BuildBorder(content_event_box_, false, 2, 2, 2, 0,
-              &border_bin_, &border_bin_alignment_);
-  gtk_util::CenterWidgetInHBox(hbox, border_bin_, true, 0);
-
-  theme_provider_->InitThemesFor(this);
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-
-  g_signal_connect(widget(), "parent-set", G_CALLBACK(OnParentSet), this);
-
-  // We take care to avoid showing the slide animator widget.
-  gtk_widget_show_all(container_);
-  gtk_widget_show(widget());
-}
-
-FindBarController* FindBarGtk::GetFindBarController() const {
-  return find_bar_controller_;
-}
-
-void FindBarGtk::SetFindBarController(FindBarController* find_bar_controller) {
-  find_bar_controller_ = find_bar_controller;
-}
-
-void FindBarGtk::Show(bool animate) {
-  if (animate) {
-    slide_widget_->Open();
-    selection_rect_ = gfx::Rect();
-    Reposition();
-    if (container_->window)
-      gdk_window_raise(container_->window);
-  } else {
-    slide_widget_->OpenWithoutAnimation();
-  }
-}
-
-void FindBarGtk::Hide(bool animate) {
-  if (animate)
-    slide_widget_->Close();
-  else
-    slide_widget_->CloseWithoutAnimation();
-}
-
-void FindBarGtk::SetFocusAndSelection() {
-  StoreOutsideFocus();
-  gtk_widget_grab_focus(text_entry_);
-  // Select all the text.
-  gtk_entry_select_region(GTK_ENTRY(text_entry_), 0, -1);
-}
-
-void FindBarGtk::ClearResults(const FindNotificationDetails& results) {
-  UpdateUIForFindResult(results, string16());
-}
-
-void FindBarGtk::StopAnimation() {
-  slide_widget_->End();
-}
-
-void FindBarGtk::MoveWindowIfNecessary(const gfx::Rect& selection_rect,
-                                       bool no_redraw) {
-  // Not moving the window on demand, so do nothing.
-}
-
-void FindBarGtk::SetFindText(const string16& find_text) {
-  std::string find_text_utf8 = UTF16ToUTF8(find_text);
-
-  // Ignore the "changed" signal handler because programatically setting the
-  // text should not fire a "changed" event.
-  ignore_changed_signal_ = true;
-  gtk_entry_set_text(GTK_ENTRY(text_entry_), find_text_utf8.c_str());
-  ignore_changed_signal_ = false;
-}
-
-void FindBarGtk::UpdateUIForFindResult(const FindNotificationDetails& result,
-                                       const string16& find_text) {
-  if (!result.selection_rect().IsEmpty()) {
-    selection_rect_ = result.selection_rect();
-    int xposition = GetDialogPosition(result.selection_rect()).x();
-    if (xposition != widget()->allocation.x)
-      Reposition();
-  }
-
-  // Once we find a match we no longer want to keep track of what had
-  // focus. EndFindSession will then set the focus to the page content.
-  if (result.number_of_matches() > 0)
-    focus_store_.Store(NULL);
-
-  std::string find_text_utf8 = UTF16ToUTF8(find_text);
-  bool have_valid_range =
-      result.number_of_matches() != -1 && result.active_match_ordinal() != -1;
-
-  std::string entry_text(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
-  if (entry_text != find_text_utf8) {
-    SetFindText(find_text);
-    gtk_entry_select_region(GTK_ENTRY(text_entry_), 0, -1);
-  }
-
-  if (!find_text.empty() && have_valid_range) {
-    gtk_label_set_text(GTK_LABEL(match_count_label_),
-        l10n_util::GetStringFUTF8(IDS_FIND_IN_PAGE_COUNT,
-            base::IntToString16(result.active_match_ordinal()),
-            base::IntToString16(result.number_of_matches())).c_str());
-    UpdateMatchLabelAppearance(result.number_of_matches() == 0 &&
-                               result.final_update());
-  } else {
-    // If there was no text entered, we don't show anything in the result count
-    // area.
-    gtk_label_set_text(GTK_LABEL(match_count_label_), "");
-    UpdateMatchLabelAppearance(false);
-  }
-}
-
-void FindBarGtk::AudibleAlert() {
-  // This call causes a lot of weird bugs, especially when using the custom
-  // frame. TODO(estade): if people complain, re-enable it. See
-  // http://crbug.com/27635 and others.
-  //
-  //   gtk_widget_error_bell(widget());
-}
-
-gfx::Rect FindBarGtk::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
-  bool ltr = !base::i18n::IsRTL();
-  // 15 is the size of the scrollbar, copied from ScrollbarThemeChromium.
-  // The height is not used.
-  // At very low browser widths we can wind up with a negative |dialog_bounds|
-  // width, so clamp it to 0.
-  gfx::Rect dialog_bounds = gfx::Rect(ltr ? 0 : 15, 0,
-      std::max(0, widget()->parent->allocation.width - (ltr ? 15 : 0)), 0);
-
-  GtkRequisition req;
-  gtk_widget_size_request(container_, &req);
-  gfx::Size prefsize(req.width, req.height);
-
-  gfx::Rect view_location(
-      ltr ? dialog_bounds.width() - prefsize.width() : dialog_bounds.x(),
-      dialog_bounds.y(), prefsize.width(), prefsize.height());
-  gfx::Rect new_pos = FindBarController::GetLocationForFindbarView(
-      view_location, dialog_bounds, avoid_overlapping_rect);
-
-  return new_pos;
-}
-
-bool FindBarGtk::IsFindBarVisible() {
-  return GTK_WIDGET_VISIBLE(widget());
-}
-
-void FindBarGtk::RestoreSavedFocus() {
-  // This function sometimes gets called when we don't have focus. We should do
-  // nothing in this case.
-  if (!gtk_widget_is_focus(text_entry_))
-    return;
-
-  if (focus_store_.widget())
-    gtk_widget_grab_focus(focus_store_.widget());
-  else
-    find_bar_controller_->tab_contents()->Focus();
-}
-
-FindBarTesting* FindBarGtk::GetFindBarTesting() {
-  return this;
-}
-
-void FindBarGtk::Observe(NotificationType type,
-                         const NotificationSource& source,
-                         const NotificationDetails& details) {
-  DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED);
-
-  // Force reshapings of the find bar window.
-  container_width_ = -1;
-  container_height_ = -1;
-
-  if (theme_provider_->UseGtkTheme()) {
-    gtk_widget_modify_cursor(text_entry_, NULL, NULL);
-    gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL, NULL);
-    gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL, NULL);
-
-    // Prevent forced font sizes because it causes the jump up and down
-    // character movement (http://crbug.com/22614), and because it will
-    // prevent centering of the text entry.
-    gtk_util::UndoForceFontSize(text_entry_);
-    gtk_util::UndoForceFontSize(match_count_label_);
-
-    gtk_widget_set_size_request(content_event_box_, -1, -1);
-    gtk_widget_modify_bg(content_event_box_, GTK_STATE_NORMAL, NULL);
-
-    // Replicate the normal GtkEntry behaviour by drawing the entry
-    // background. We set the fake alignment to be the frame thickness.
-    GtkStyle* style = gtk_rc_get_style(text_entry_);
-    gint xborder = style->xthickness;
-    gint yborder = style->ythickness;
-    gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment_),
-                              yborder, yborder, xborder, xborder);
-
-    // We leave left padding on the left, even in GTK mode, as it's required
-    // for the left margin to be equivalent to the bottom margin.
-    gtk_alignment_set_padding(GTK_ALIGNMENT(border_bin_alignment_),
-                              0, 0, 1, 0);
-
-    // We need this event box to have its own window in GTK mode for doing the
-    // hacky widget rendering.
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(border_bin_), TRUE);
-    gtk_widget_set_app_paintable(border_bin_, TRUE);
-
-    gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 0.5);
-  } else {
-    gtk_widget_modify_cursor(
-        text_entry_, &gtk_util::kGdkBlack, &gtk_util::kGdkGray);
-    gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL,
-                           &kEntryBackgroundColor);
-    gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL,
-                           &kEntryTextColor);
-
-    // Until we switch to vector graphics, force the font size.
-    gtk_util::ForceFontSizePixels(text_entry_, 13.4);  // 13.4px == 10pt @ 96dpi
-    gtk_util::ForceFontSizePixels(match_count_label_, 13.4);
-
-    // Force the text widget height so it lines up with the buttons regardless
-    // of font size.
-    gtk_widget_set_size_request(content_event_box_, -1, 20);
-    gtk_widget_modify_bg(content_event_box_, GTK_STATE_NORMAL,
-                         &kEntryBackgroundColor);
-
-    gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment_),
-                              0.0, 0.0, 0.0, 0.0);
-
-    gtk_alignment_set_padding(GTK_ALIGNMENT(border_bin_alignment_),
-                              2, 2, 3, 0);
-
-    // We need this event box to be invisible because we're only going to draw
-    // on the background (but we can't take it out of the heiarchy entirely
-    // because we also need it to take up space).
-    gtk_event_box_set_visible_window(GTK_EVENT_BOX(border_bin_), FALSE);
-    gtk_widget_set_app_paintable(border_bin_, FALSE);
-
-    gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 1.0);
-
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    close_button_->SetBackground(
-        theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT),
-        rb.GetBitmapNamed(IDR_CLOSE_BAR),
-        rb.GetBitmapNamed(IDR_CLOSE_BAR_MASK));
-  }
-
-  UpdateMatchLabelAppearance(match_label_failure_);
-}
-
-bool FindBarGtk::GetFindBarWindowInfo(gfx::Point* position,
-                                      bool* fully_visible) {
-  if (position)
-    *position = GetPosition();
-
-  if (fully_visible) {
-    *fully_visible = !slide_widget_->IsAnimating() &&
-                     slide_widget_->IsShowing();
-  }
-  return true;
-}
-
-string16 FindBarGtk::GetFindText() {
-  std::string contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
-  return UTF8ToUTF16(contents);
-}
-
-string16 FindBarGtk::GetFindSelectedText() {
-  gint cursor_pos;
-  gint selection_bound;
-  g_object_get(G_OBJECT(text_entry_), "cursor-position", &cursor_pos,
-               NULL);
-  g_object_get(G_OBJECT(text_entry_), "selection-bound", &selection_bound,
-               NULL);
-  std::string contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
-  return UTF8ToUTF16(contents.substr(cursor_pos, selection_bound));
-}
-
-string16 FindBarGtk::GetMatchCountText() {
-  std::string contents(gtk_label_get_text(GTK_LABEL(match_count_label_)));
-  return UTF8ToUTF16(contents);
-}
-
-void FindBarGtk::FindEntryTextInContents(bool forward_search) {
-  TabContents* tab_contents = find_bar_controller_->tab_contents();
-  if (!tab_contents)
-    return;
-
-  std::string new_contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
-
-  if (new_contents.length() > 0) {
-    tab_contents->StartFinding(UTF8ToUTF16(new_contents), forward_search,
-                               false);  // Not case sensitive.
-  } else {
-    // The textbox is empty so we reset.
-    tab_contents->StopFinding(FindBarController::kClearSelection);
-    UpdateUIForFindResult(find_bar_controller_->tab_contents()->find_result(),
-                          string16());
-
-    // Clearing the text box should also clear the prepopulate state so that
-    // when we close and reopen the Find box it doesn't show the search we
-    // just deleted.
-    FindBarState* find_bar_state = browser_->profile()->GetFindBarState();
-    find_bar_state->set_last_prepopulate_text(string16());
-  }
-}
-
-void FindBarGtk::UpdateMatchLabelAppearance(bool failure) {
-  match_label_failure_ = failure;
-  bool use_gtk = theme_provider_->UseGtkTheme();
-
-  if (use_gtk) {
-    GtkStyle* style = gtk_rc_get_style(text_entry_);
-    GdkColor normal_bg = style->base[GTK_STATE_NORMAL];
-    GdkColor normal_text = gtk_util::AverageColors(
-        style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
-
-    gtk_widget_modify_bg(match_count_event_box_, GTK_STATE_NORMAL,
-                         failure ? &kFindFailureBackgroundColor :
-                         &normal_bg);
-    gtk_widget_modify_fg(match_count_label_, GTK_STATE_NORMAL,
-                         failure ? &kEntryTextColor : &normal_text);
-  } else {
-    gtk_widget_modify_bg(match_count_event_box_, GTK_STATE_NORMAL,
-                         failure ? &kFindFailureBackgroundColor :
-                         &kEntryBackgroundColor);
-    gtk_widget_modify_fg(match_count_label_, GTK_STATE_NORMAL,
-                         failure ? &kEntryTextColor : &kFindSuccessTextColor);
-  }
-}
-
-void FindBarGtk::Reposition() {
-  if (!IsFindBarVisible())
-    return;
-
-  // This will trigger an allocate, which allows us to reposition.
-  if (widget()->parent)
-    gtk_widget_queue_resize(widget()->parent);
-}
-
-void FindBarGtk::StoreOutsideFocus() {
-  // |text_entry_| is the only widget in the find bar that can be focused,
-  // so it's the only one we have to check.
-  // TODO(estade): when we make the find bar buttons focusable, we'll have
-  // to change this (same above in RestoreSavedFocus).
-  if (!gtk_widget_is_focus(text_entry_))
-    focus_store_.Store(text_entry_);
-}
-
-bool FindBarGtk::MaybeForwardKeyEventToRenderer(GdkEventKey* event) {
-  switch (event->keyval) {
-    case GDK_Down:
-    case GDK_Up:
-    case GDK_Page_Up:
-    case GDK_Page_Down:
-      break;
-    case GDK_Home:
-    case GDK_End:
-      if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
-          GDK_CONTROL_MASK) {
-        break;
-      }
-    // Fall through.
-    default:
-      return false;
-  }
-
-  TabContents* contents = find_bar_controller_->tab_contents();
-  if (!contents)
-    return false;
-
-  RenderViewHost* render_view_host = contents->render_view_host();
-
-  // Make sure we don't have a text field element interfering with keyboard
-  // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
-  render_view_host->ClearFocusedNode();
-
-  NativeWebKeyboardEvent wke(event);
-  render_view_host->ForwardKeyboardEvent(wke);
-  return true;
-}
-
-void FindBarGtk::AdjustTextAlignment() {
-  PangoDirection content_dir =
-      pango_find_base_dir(gtk_entry_get_text(GTK_ENTRY(text_entry_)), -1);
-
-  GtkTextDirection widget_dir = gtk_widget_get_direction(text_entry_);
-
-  // Use keymap or widget direction if content does not have strong direction.
-  // It matches the behavior of GtkEntry.
-  if (content_dir == PANGO_DIRECTION_NEUTRAL) {
-    if (GTK_WIDGET_HAS_FOCUS(text_entry_)) {
-      content_dir = gdk_keymap_get_direction(
-        gdk_keymap_get_for_display(gtk_widget_get_display(text_entry_)));
-    } else {
-      if (widget_dir == GTK_TEXT_DIR_RTL)
-        content_dir = PANGO_DIRECTION_RTL;
-      else
-        content_dir = PANGO_DIRECTION_LTR;
-    }
-  }
-
-  if ((widget_dir == GTK_TEXT_DIR_RTL && content_dir == PANGO_DIRECTION_LTR) ||
-      (widget_dir == GTK_TEXT_DIR_LTR && content_dir == PANGO_DIRECTION_RTL)) {
-    gtk_entry_set_alignment(GTK_ENTRY(text_entry_), 1.0);
-  } else {
-    gtk_entry_set_alignment(GTK_ENTRY(text_entry_), 0.0);
-  }
-}
-
-gfx::Point FindBarGtk::GetPosition() {
-  gfx::Point point;
-
-  GValue value = { 0, };
-  g_value_init(&value, G_TYPE_INT);
-  gtk_container_child_get_property(GTK_CONTAINER(widget()->parent),
-                                   widget(), "x", &value);
-  point.set_x(g_value_get_int(&value));
-
-  gtk_container_child_get_property(GTK_CONTAINER(widget()->parent),
-                                   widget(), "y", &value);
-  point.set_y(g_value_get_int(&value));
-
-  g_value_unset(&value);
-
-  return point;
-}
-
-// static
-void FindBarGtk::OnParentSet(GtkWidget* widget, GtkObject* old_parent,
-                             FindBarGtk* find_bar) {
-  if (!widget->parent)
-    return;
-
-  g_signal_connect(widget->parent, "set-floating-position",
-                   G_CALLBACK(OnSetFloatingPosition), find_bar);
-}
-
-// static
-void FindBarGtk::OnSetFloatingPosition(
-    GtkFloatingContainer* floating_container,
-    GtkAllocation* allocation,
-    FindBarGtk* find_bar) {
-  GtkWidget* findbar = find_bar->widget();
-
-  int xposition = find_bar->GetDialogPosition(find_bar->selection_rect_).x();
-
-  GValue value = { 0, };
-  g_value_init(&value, G_TYPE_INT);
-  g_value_set_int(&value, xposition);
-  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
-                                   findbar, "x", &value);
-
-  g_value_set_int(&value, 0);
-  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
-                                   findbar, "y", &value);
-  g_value_unset(&value);
-}
-
-// static
-gboolean FindBarGtk::OnChanged(GtkWindow* window, FindBarGtk* find_bar) {
-  find_bar->AdjustTextAlignment();
-
-  if (!find_bar->ignore_changed_signal_)
-    find_bar->FindEntryTextInContents(true);
-
-  return FALSE;
-}
-
-// static
-gboolean FindBarGtk::OnKeyPressEvent(GtkWidget* widget, GdkEventKey* event,
-                                     FindBarGtk* find_bar) {
-  if (find_bar->MaybeForwardKeyEventToRenderer(event)) {
-    return TRUE;
-  } else if (GDK_Escape == event->keyval) {
-    find_bar->find_bar_controller_->EndFindSession(
-        FindBarController::kKeepSelection);
-    return TRUE;
-  } else if (GDK_Return == event->keyval ||
-             GDK_KP_Enter == event->keyval) {
-    if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
-        GDK_CONTROL_MASK) {
-      find_bar->find_bar_controller_->EndFindSession(
-          FindBarController::kActivateSelection);
-      return TRUE;
-    }
-
-    bool forward = (event->state & gtk_accelerator_get_default_mod_mask()) !=
-                   GDK_SHIFT_MASK;
-    find_bar->FindEntryTextInContents(forward);
-    return TRUE;
-  }
-  return FALSE;
-}
-
-// static
-gboolean FindBarGtk::OnKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event,
-                                       FindBarGtk* find_bar) {
-  return find_bar->MaybeForwardKeyEventToRenderer(event);
-}
-
-// static
-void FindBarGtk::OnClicked(GtkWidget* button, FindBarGtk* find_bar) {
-  if (button == find_bar->close_button_->widget()) {
-    find_bar->find_bar_controller_->EndFindSession(
-        FindBarController::kKeepSelection);
-  } else if (button == find_bar->find_previous_button_->widget() ||
-             button == find_bar->find_next_button_->widget()) {
-    find_bar->FindEntryTextInContents(
-        button == find_bar->find_next_button_->widget());
-  } else {
-    NOTREACHED();
-  }
-}
-
-// static
-gboolean FindBarGtk::OnContentEventBoxExpose(GtkWidget* widget,
-                                             GdkEventExpose* event,
-                                             FindBarGtk* bar) {
-  if (bar->theme_provider_->UseGtkTheme()) {
-    // Draw the text entry background around where we input stuff. Note the
-    // decrement to |width|. We do this because some theme engines
-    // (*cough*Clearlooks*cough*) don't do any blending and use thickness to
-    // make sure that widgets never overlap.
-    int padding = gtk_widget_get_style(widget)->xthickness;
-    GdkRectangle rec = {
-      widget->allocation.x,
-      widget->allocation.y,
-      widget->allocation.width - padding,
-      widget->allocation.height
-    };
-
-    gtk_util::DrawTextEntryBackground(bar->text_entry_, widget,
-                                      &event->area, &rec);
-  }
-
-  return FALSE;
-}
-
-// Used to handle custom painting of |container_|.
-gboolean FindBarGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e,
-                              FindBarGtk* bar) {
-  GtkRequisition req;
-  gtk_widget_size_request(widget, &req);
-  gtk_widget_set_size_request(bar->widget(), req.width, -1);
-
-  if (bar->theme_provider_->UseGtkTheme()) {
-    if (bar->container_width_ != widget->allocation.width ||
-        bar->container_height_ != widget->allocation.height) {
-      std::vector<GdkPoint> mask_points = MakeFramePolygonPoints(
-          widget->allocation.width, widget->allocation.height, FRAME_MASK);
-      GdkRegion* mask_region = gdk_region_polygon(&mask_points[0],
-                                                  mask_points.size(),
-                                                  GDK_EVEN_ODD_RULE);
-      // Reset the shape.
-      gdk_window_shape_combine_region(widget->window, NULL, 0, 0);
-      gdk_window_shape_combine_region(widget->window, mask_region, 0, 0);
-      gdk_region_destroy(mask_region);
-
-      bar->container_width_ = widget->allocation.width;
-      bar->container_height_ = widget->allocation.height;
-    }
-
-    GdkDrawable* drawable = GDK_DRAWABLE(e->window);
-    GdkGC* gc = gdk_gc_new(drawable);
-    gdk_gc_set_clip_rectangle(gc, &e->area);
-    GdkColor color = bar->theme_provider_->GetBorderColor();
-    gdk_gc_set_rgb_fg_color(gc, &color);
-
-    // Stroke the frame border.
-    std::vector<GdkPoint> points = MakeFramePolygonPoints(
-        widget->allocation.width, widget->allocation.height, FRAME_STROKE);
-    gdk_draw_lines(drawable, gc, &points[0], points.size());
-
-    g_object_unref(gc);
-  } else {
-    if (bar->container_width_ != widget->allocation.width ||
-        bar->container_height_ != widget->allocation.height) {
-      // Reset the shape.
-      gdk_window_shape_combine_region(widget->window, NULL, 0, 0);
-      SetDialogShape(bar->container_);
-
-      bar->container_width_ = widget->allocation.width;
-      bar->container_height_ = widget->allocation.height;
-    }
-
-    cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-    gdk_cairo_rectangle(cr, &e->area);
-    cairo_clip(cr);
-
-    gfx::Point tabstrip_origin =
-        bar->window_->tabstrip()->GetTabStripOriginForWidget(widget);
-
-    gtk_util::DrawThemedToolbarBackground(widget, cr, e, tabstrip_origin,
-                                          bar->theme_provider_);
-
-    // During chrome theme mode, we need to draw the border around content_hbox
-    // now instead of when we render |border_bin_|. We don't use stacked event
-    // boxes to simulate the effect because we need to blend them with this
-    // background.
-    GtkAllocation border_allocation = bar->border_bin_->allocation;
-
-    // Blit the left part of the background image once on the left.
-    CairoCachedSurface* background_left =
-        bar->theme_provider_->GetRTLEnabledSurfaceNamed(
-        IDR_FIND_BOX_BACKGROUND_LEFT, widget);
-    background_left->SetSource(cr, border_allocation.x, border_allocation.y);
-    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(cr, border_allocation.x, border_allocation.y,
-                    background_left->Width(), background_left->Height());
-    cairo_fill(cr);
-
-    // Blit the center part of the background image in all the space between.
-    CairoCachedSurface* background = bar->theme_provider_->GetSurfaceNamed(
-        IDR_FIND_BOX_BACKGROUND, widget);
-    background->SetSource(cr,
-                          border_allocation.x + background_left->Width(),
-                          border_allocation.y);
-    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(cr,
-                    border_allocation.x + background_left->Width(),
-                    border_allocation.y,
-                    border_allocation.width - background_left->Width(),
-                    background->Height());
-    cairo_fill(cr);
-
-    cairo_destroy(cr);
-
-    // Draw the border.
-    GetDialogBorder()->RenderToWidget(widget);
-  }
-
-  // Propagate to the container's child.
-  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
-  if (child)
-    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
-  return TRUE;
-}
-
-// static
-gboolean FindBarGtk::OnFocus(GtkWidget* text_entry, GtkDirectionType focus,
-                             FindBarGtk* find_bar) {
-  find_bar->StoreOutsideFocus();
-
-  // Continue propagating the event.
-  return FALSE;
-}
-
-// static
-gboolean FindBarGtk::OnButtonPress(GtkWidget* text_entry, GdkEventButton* e,
-                                   FindBarGtk* find_bar) {
-  find_bar->StoreOutsideFocus();
-
-  // Continue propagating the event.
-  return FALSE;
-}
-
-// static
-void FindBarGtk::OnMoveCursor(GtkEntry* entry, GtkMovementStep step, gint count,
-                              gboolean selection, FindBarGtk* bar) {
-  static guint signal_id = g_signal_lookup("move-cursor", GTK_TYPE_ENTRY);
-
-  GdkEvent* event = gtk_get_current_event();
-  if (event) {
-    if ((event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE) &&
-        bar->MaybeForwardKeyEventToRenderer(&(event->key))) {
-      g_signal_stop_emission(entry, signal_id, 0);
-    }
-
-    gdk_event_free(event);
-  }
-}
-
-// static
-void FindBarGtk::OnActivate(GtkEntry* entry, FindBarGtk* bar) {
-  bar->FindEntryTextInContents(true);
-}
-
-// static
-gboolean FindBarGtk::OnFocusIn(GtkWidget* entry, GdkEventFocus* event,
-                               FindBarGtk* find_bar) {
-  g_signal_connect(
-      gdk_keymap_get_for_display(gtk_widget_get_display(entry)),
-      "direction-changed",
-      G_CALLBACK(&OnKeymapDirectionChanged), find_bar);
-
-  find_bar->AdjustTextAlignment();
-
-  return FALSE;  // Continue propagation.
-}
-
-// static
-gboolean FindBarGtk::OnFocusOut(GtkWidget* entry, GdkEventFocus* event,
-                                FindBarGtk* find_bar) {
-  g_signal_handlers_disconnect_by_func(
-      gdk_keymap_get_for_display(gtk_widget_get_display(entry)),
-      reinterpret_cast<gpointer>(&OnKeymapDirectionChanged), find_bar);
-
-  return FALSE;  // Continue propagation.
-}
diff --git a/chrome/browser/gtk/find_bar_gtk.h b/chrome/browser/gtk/find_bar_gtk.h
deleted file mode 100644
index 527644a..0000000
--- a/chrome/browser/gtk/find_bar_gtk.h
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_FIND_BAR_GTK_H_
-#define CHROME_BROWSER_GTK_FIND_BAR_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/focus_store_gtk.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-#include "chrome/browser/ui/find_bar/find_bar.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/point.h"
-
-class Browser;
-class BrowserWindowGtk;
-class CustomDrawButton;
-class FindBarController;
-class GtkThemeProvider;
-class NineBox;
-class SlideAnimatorGtk;
-class TabContentsContainerGtk;
-
-typedef struct _GtkFloatingContainer GtkFloatingContainer;
-
-// Currently this class contains both a model and a view.  We may want to
-// eventually pull out the model specific bits and share with Windows.
-class FindBarGtk : public FindBar,
-                   public FindBarTesting,
-                   public NotificationObserver {
- public:
-  explicit FindBarGtk(Browser* browser);
-  virtual ~FindBarGtk();
-
-  GtkWidget* widget() const { return slide_widget_->widget(); }
-
-  // Methods from FindBar.
-  virtual FindBarController* GetFindBarController() const;
-  virtual void SetFindBarController(FindBarController* find_bar_controller);
-  virtual void Show(bool animate);
-  virtual void Hide(bool animate);
-  virtual void SetFocusAndSelection();
-  virtual void ClearResults(const FindNotificationDetails& results);
-  virtual void StopAnimation();
-  virtual void MoveWindowIfNecessary(const gfx::Rect& selection_rect,
-                                     bool no_redraw);
-  virtual void SetFindText(const string16& find_text);
-  virtual void UpdateUIForFindResult(const FindNotificationDetails& result,
-                                     const string16& find_text);
-  virtual void AudibleAlert();
-  virtual bool IsFindBarVisible();
-  virtual void RestoreSavedFocus();
-  virtual FindBarTesting* GetFindBarTesting();
-
-  // Methods from FindBarTesting.
-  virtual bool GetFindBarWindowInfo(gfx::Point* position,
-                                    bool* fully_visible);
-  virtual string16 GetFindText();
-  virtual string16 GetFindSelectedText();
-  virtual string16 GetMatchCountText();
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  void InitWidgets();
-
-  // Store the currently focused widget if it is not in the find bar.
-  // This should always be called before we claim focus.
-  void StoreOutsideFocus();
-
-  // For certain keystrokes, such as up or down, we want to forward the event
-  // to the renderer rather than handling it ourselves. Returns true if the
-  // key event was forwarded.
-  // See similar function in FindBarWin.
-  bool MaybeForwardKeyEventToRenderer(GdkEventKey* event);
-
-  // Searches for another occurrence of the entry text, moving forward if
-  // |forward_search| is true.
-  void FindEntryTextInContents(bool forward_search);
-
-  void UpdateMatchLabelAppearance(bool failure);
-
-  // Asynchronously repositions the dialog.
-  void Reposition();
-
-  // Returns the rectangle representing where to position the find bar. If
-  // |avoid_overlapping_rect| is specified, the return value will be a rectangle
-  // located immediately to the left of |avoid_overlapping_rect|, as long as
-  // there is enough room for the dialog to draw within the bounds. If not, the
-  // dialog position returned will overlap |avoid_overlapping_rect|.
-  // Note: |avoid_overlapping_rect| is expected to use coordinates relative to
-  // the top of the page area, (it will be converted to coordinates relative to
-  // the top of the browser window, when comparing against the dialog
-  // coordinates). The returned value is relative to the browser window.
-  gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect);
-
-  // Adjust the text alignment according to the text direction of the widget
-  // and |text_entry_|'s content, to make sure the real text alignment is
-  // always in sync with the UI language direction.
-  void AdjustTextAlignment();
-
-  // Get the position of the findbar within the floating container.
-  gfx::Point GetPosition();
-
-  static void OnParentSet(GtkWidget* widget, GtkObject* old_parent,
-                          FindBarGtk* find_bar);
-
-  static void OnSetFloatingPosition(GtkFloatingContainer* floating_container,
-                                    GtkAllocation* allocation,
-                                    FindBarGtk* find_bar);
-
-  // Callback when the entry text changes.
-  static gboolean OnChanged(GtkWindow* window, FindBarGtk* find_bar);
-
-  static gboolean OnKeyPressEvent(GtkWidget* widget, GdkEventKey* event,
-                                  FindBarGtk* find_bar);
-  static gboolean OnKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event,
-                                    FindBarGtk* find_bar);
-
-  // Callback for previous, next, and close button.
-  static void OnClicked(GtkWidget* button, FindBarGtk* find_bar);
-
-  // Handles shapping and drawing the find bar background.
-  static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* event,
-                           FindBarGtk* bar);
-
-  // Expose that draws the text entry background in GTK mode.
-  static gboolean OnContentEventBoxExpose(GtkWidget* widget,
-                                          GdkEventExpose* event,
-                                          FindBarGtk* bar);
-
-  // These are both used for focus management.
-  static gboolean OnFocus(GtkWidget* text_entry, GtkDirectionType focus,
-                          FindBarGtk* find_bar);
-  static gboolean OnButtonPress(GtkWidget* text_entry, GdkEventButton* e,
-                                FindBarGtk* find_bar);
-
-  // Forwards ctrl-Home/End key bindings to the renderer.
-  static void OnMoveCursor(GtkEntry* entry, GtkMovementStep step, gint count,
-                           gboolean selection, FindBarGtk* bar);
-
-  // Handles Enter key.
-  static void OnActivate(GtkEntry* entry, FindBarGtk* bar);
-
-  static void OnWidgetDirectionChanged(GtkWidget* widget,
-                                       GtkTextDirection previous_direction,
-                                       FindBarGtk* find_bar) {
-    find_bar->AdjustTextAlignment();
-  }
-
-  static void OnKeymapDirectionChanged(GdkKeymap* keymap,
-                                       FindBarGtk* find_bar) {
-    find_bar->AdjustTextAlignment();
-  }
-
-  static gboolean OnFocusIn(GtkWidget* entry, GdkEventFocus* event,
-                            FindBarGtk* find_bar);
-
-  static gboolean OnFocusOut(GtkWidget* entry, GdkEventFocus* event,
-                             FindBarGtk* find_bar);
-
-  Browser* browser_;
-  BrowserWindowGtk* window_;
-
-  // Provides colors and information about GTK.
-  GtkThemeProvider* theme_provider_;
-
-  // The widget that animates the slide-in and -out of the findbar.
-  scoped_ptr<SlideAnimatorGtk> slide_widget_;
-
-  // A GtkAlignment that is the child of |slide_widget_|.
-  GtkWidget* container_;
-
-  // Cached allocation of |container_|. We keep this on hand so that we can
-  // reset the widget's shape when the width/height change.
-  int container_width_;
-  int container_height_;
-
-  // The widget where text is entered.
-  GtkWidget* text_entry_;
-
-  // An event box and alignment that wrap the entry area and the count label.
-  GtkWidget* content_event_box_;
-  GtkWidget* content_alignment_;
-
-  // The border around the text entry area.
-  GtkWidget* border_bin_;
-  GtkWidget* border_bin_alignment_;
-
-  // The next and previous match buttons.
-  scoped_ptr<CustomDrawButton> find_previous_button_;
-  scoped_ptr<CustomDrawButton> find_next_button_;
-
-  // The GtkLabel listing how many results were found.
-  GtkWidget* match_count_label_;
-  GtkWidget* match_count_event_box_;
-  // Cache whether the match count label is showing failure or not so that
-  // we can update its appearance without changing its semantics.
-  bool match_label_failure_;
-
-  // The X to close the find bar.
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  // The last matchcount number we reported to the user.
-  int last_reported_matchcount_;
-
-  // Pointer back to the owning controller.
-  FindBarController* find_bar_controller_;
-
-  // Saves where the focus used to be whenever we get it.
-  FocusStoreGtk focus_store_;
-
-  // If true, the change signal for the text entry is ignored.
-  bool ignore_changed_signal_;
-
-  // This is the width of widget(). We cache it so we can recognize whether
-  // allocate signals have changed it, and if so take appropriate actions.
-  int current_fixed_width_;
-
-  scoped_ptr<NineBox> dialog_background_;
-
-  // The selection rect we are currently showing. We cache it to avoid covering
-  // it up.
-  gfx::Rect selection_rect_;
-
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(FindBarGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_FIND_BAR_GTK_H_
diff --git a/chrome/browser/gtk/first_run_bubble.cc b/chrome/browser/gtk/first_run_bubble.cc
deleted file mode 100644
index 119166b..0000000
--- a/chrome/browser/gtk/first_run_bubble.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/first_run_bubble.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "base/i18n/rtl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/search_engines/util.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_service.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-// Markup for the text of the Omnibox search label
-const char kSearchLabelMarkup[] = "<big><b>%s</b></big>";
-
-// Padding for the buttons on first run bubble.
-const int kButtonPadding = 4;
-
-// Padding between content and edge of info bubble.
-const int kContentBorder = 7;
-
-// Vertical spacing between labels.
-const int kInterLineSpacing = 5;
-
-}  // namespace
-
-// static
-void FirstRunBubble::Show(Profile* profile,
-                          GtkWidget* anchor,
-                          const gfx::Rect& rect,
-                          FirstRun::BubbleType bubble_type) {
-  new FirstRunBubble(profile, anchor, rect, bubble_type);
-}
-
-void FirstRunBubble::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                       bool closed_by_escape) {
-  // TODO(port): Enable parent window
-}
-
-bool FirstRunBubble::CloseOnEscape() {
-  return true;
-}
-
-void FirstRunBubble::Observe(NotificationType type,
-                             const NotificationSource& source,
-                             const NotificationDetails& details) {
-  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
-
-  if (theme_provider_->UseGtkTheme()) {
-    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
-         it != labels_.end(); ++it) {
-      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
-    }
-  } else {
-    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
-         it != labels_.end(); ++it) {
-      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-    }
-  }
-}
-
-FirstRunBubble::FirstRunBubble(Profile* profile,
-                               GtkWidget* anchor,
-                               const gfx::Rect& rect,
-                               FirstRun::BubbleType bubble_type)
-    : profile_(profile),
-      theme_provider_(GtkThemeProvider::GetFrom(profile_)),
-      anchor_(anchor),
-      content_(NULL),
-      bubble_(NULL) {
-  content_ = gtk_vbox_new(FALSE, kInterLineSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(content_), kContentBorder);
-  g_signal_connect(content_, "destroy",
-                   G_CALLBACK(&HandleDestroyThunk), this);
-
-  int width_resource = 0;
-  if (bubble_type == FirstRun::LARGE_BUBBLE) {
-    width_resource = IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS;
-    InitializeContentForLarge();
-  } else if (bubble_type == FirstRun::OEM_BUBBLE) {
-    width_resource = IDS_FIRSTRUNOEMBUBBLE_DIALOG_WIDTH_CHARS;
-    InitializeContentForOEM();
-  } else if (bubble_type == FirstRun::MINIMAL_BUBBLE) {
-    width_resource = IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_WIDTH_CHARS;
-    InitializeContentForMinimal();
-  } else {
-    NOTREACHED();
-  }
-
-  InitializeLabels(width_resource);
-
-  InfoBubbleGtk::ArrowLocationGtk arrow_location =
-      !base::i18n::IsRTL() ?
-      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
-      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
-  bubble_ = InfoBubbleGtk::Show(anchor_,
-                                &rect,
-                                content_,
-                                arrow_location,
-                                true,  // match_system_theme
-                                true,  // grab_input
-                                theme_provider_,
-                                this);  // delegate
-  if (!bubble_) {
-    NOTREACHED();
-    return;
-  }
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_->InitThemesFor(this);
-}
-
-FirstRunBubble::~FirstRunBubble() {
-}
-
-void FirstRunBubble::InitializeContentForLarge() {
-  GtkWidget* label1 = gtk_label_new(NULL);
-  labels_.push_back(label1);
-  char* markup = g_markup_printf_escaped(kSearchLabelMarkup,
-      l10n_util::GetStringUTF8(IDS_FR_BUBBLE_TITLE).c_str());
-  gtk_label_set_markup(GTK_LABEL(label1), markup);
-  g_free(markup);
-
-  GtkWidget* label2 = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_FR_BUBBLE_SUBTEXT).c_str());
-  labels_.push_back(label2);
-
-  string16 search_engine = GetDefaultSearchEngineName(profile_);
-  GtkWidget* label3 = gtk_label_new(
-      l10n_util::GetStringFUTF8(IDS_FR_BUBBLE_QUESTION, search_engine).c_str());
-  labels_.push_back(label3);
-
-  GtkWidget* keep_button = gtk_button_new_with_label(
-      l10n_util::GetStringFUTF8(IDS_FR_BUBBLE_OK, search_engine).c_str());
-  GtkWidget* change_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_FR_BUBBLE_CHANGE).c_str());
-
-  gtk_box_pack_start(GTK_BOX(content_), label1, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(content_), label2, FALSE, FALSE, 0);
-  // Leave an empty line.
-  gtk_box_pack_start(GTK_BOX(content_), gtk_label_new(NULL), FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(content_), label3, FALSE, FALSE, 0);
-
-  GtkWidget* bottom = gtk_hbox_new(FALSE, 0);
-  // We want the buttons on the right, so just use an expanding label to fill
-  // all of the extra space on the left.
-  gtk_box_pack_start(GTK_BOX(bottom), gtk_label_new(NULL), TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(bottom), keep_button, FALSE, FALSE,
-                     kButtonPadding);
-  gtk_box_pack_start(GTK_BOX(bottom), change_button, FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(content_), bottom, FALSE, FALSE, 0);
-  // We want the focus to start on the keep entry, not on the change button.
-  gtk_widget_grab_focus(keep_button);
-
-  g_signal_connect(keep_button, "clicked",
-                   G_CALLBACK(&HandleKeepButtonThunk), this);
-  g_signal_connect(change_button, "clicked",
-                   G_CALLBACK(&HandleChangeButtonThunk), this);
-}
-
-void FirstRunBubble::InitializeContentForOEM() {
-  NOTIMPLEMENTED() << "Falling back to minimal bubble";
-  InitializeContentForMinimal();
-}
-
-void FirstRunBubble::InitializeContentForMinimal() {
-  GtkWidget* label1 = gtk_label_new(NULL);
-  labels_.push_back(label1);
-  char* markup = g_markup_printf_escaped(kSearchLabelMarkup,
-      l10n_util::GetStringFUTF8(
-          IDS_FR_SE_BUBBLE_TITLE,
-          GetDefaultSearchEngineName(profile_)).c_str());
-  gtk_label_set_markup(GTK_LABEL(label1), markup);
-  g_free(markup);
-
-  GtkWidget* label2 =
-      gtk_label_new(l10n_util::GetStringUTF8(IDS_FR_BUBBLE_SUBTEXT).c_str());
-  labels_.push_back(label2);
-
-  gtk_box_pack_start(GTK_BOX(content_), label1, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(content_), label2, FALSE, FALSE, 0);
-}
-
-void FirstRunBubble::InitializeLabels(int width_resource) {
-  int width = -1;
-
-  gtk_util::GetWidgetSizeFromResources(
-      anchor_, width_resource, 0, &width, NULL);
-
-  for (size_t i = 0; i < labels_.size(); ++i) {
-    // Resize the labels so that they don't wrap more than necessary.  We leave
-    // |content_| unsized so that it'll expand as needed to hold the other
-    // widgets -- the buttons may be wider than |width| on high-DPI displays.
-    gtk_util::SetLabelWidth(labels_[i], width);
-    gtk_misc_set_alignment(GTK_MISC(labels_[i]), 0, 0.5);
-  }
-}
-
-void FirstRunBubble::HandleDestroy(GtkWidget* sender) {
-  content_ = NULL;
-  delete this;
-}
-
-void FirstRunBubble::HandleKeepButton(GtkWidget* sender) {
-  bubble_->Close();
-}
-
-void FirstRunBubble::HandleChangeButton(GtkWidget* sender) {
-  bubble_->Close();
-  Browser* browser = BrowserList::GetLastActive();
-  DCHECK(browser);
-  browser->OpenSearchEngineOptionsDialog();
-}
diff --git a/chrome/browser/gtk/first_run_bubble.h b/chrome/browser/gtk/first_run_bubble.h
deleted file mode 100644
index 220c4f6..0000000
--- a/chrome/browser/gtk/first_run_bubble.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This is the GTK implementation of the First Run bubble, the dialog box
-// presented on first run of Chromium. There can only ever be a single
-// bubble open, so the class presents only static methods.
-
-#ifndef CHROME_BROWSER_GTK_FIRST_RUN_BUBBLE_H_
-#define CHROME_BROWSER_GTK_FIRST_RUN_BUBBLE_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class Profile;
-
-class FirstRunBubble : public InfoBubbleGtkDelegate,
-                       public NotificationObserver {
- public:
-  // Shows the first run bubble, pointing at |rect|.
-  static void Show(Profile* profile,
-                   GtkWidget* anchor,
-                   const gfx::Rect& rect,
-                   FirstRun::BubbleType bubble_type);
-
-  // Implements the InfoBubbleGtkDelegate.  We are notified when the bubble
-  // is about to be closed.
-  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                 bool closed_by_escape);
-  virtual bool CloseOnEscape();
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  FirstRunBubble(Profile* profile,
-                 GtkWidget* anchor,
-                 const gfx::Rect& rect,
-                 FirstRun::BubbleType bubble_type);
-  virtual ~FirstRunBubble();
-
-  // Create and pack widgets for different bubble types.
-  void InitializeContentForLarge();
-  void InitializeContentForOEM();
-  void InitializeContentForMinimal();
-
-  // Contains some common set up for the labels in the bubble. |width| is a
-  // resource that holds the desired width for the labels.
-  void InitializeLabels(int width_resource);
-
-  CHROMEGTK_CALLBACK_0(FirstRunBubble, void, HandleDestroy);
-  CHROMEGTK_CALLBACK_0(FirstRunBubble, void, HandleKeepButton);
-  CHROMEGTK_CALLBACK_0(FirstRunBubble, void, HandleChangeButton);
-
-  // Our current profile.
-  Profile* profile_;
-
-  // Provides colors and stuff.
-  GtkThemeProvider* theme_provider_;
-
-  // The widget we anchor to, and a descendant of the toplevel window we
-  // are transient for.
-  GtkWidget* anchor_;
-
-  // We let the InfoBubble own our content, and then we delete ourself
-  // when the widget is destroyed (when the InfoBubble is destroyed).
-  GtkWidget* content_;
-
-  // The various labels in the interface. We keep track of them for theme
-  // changes.
-  std::vector<GtkWidget*> labels_;
-
-  InfoBubbleGtk* bubble_;
-
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(FirstRunBubble);
-};
-
-#endif  // CHROME_BROWSER_GTK_FIRST_RUN_BUBBLE_H_
diff --git a/chrome/browser/gtk/first_run_dialog.cc b/chrome/browser/gtk/first_run_dialog.cc
deleted file mode 100644
index 0074d28..0000000
--- a/chrome/browser/gtk/first_run_dialog.cc
+++ /dev/null
@@ -1,426 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/first_run_dialog.h"
-
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/i18n/rtl.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_floating_container.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/process_singleton.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/shell_integration.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-
-#if defined(USE_LINUX_BREAKPAD)
-#include "chrome/app/breakpad_linux.h"
-#endif
-
-#if defined(GOOGLE_CHROME_BUILD)
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/prefs/pref_service.h"
-#endif
-
-namespace {
-
-const gchar* kSearchEngineKey = "template-url-search-engine";
-
-// Height of the label that displays the search engine's logo (in lieu of the
-// actual logo) in chromium.
-const int kLogoLabelHeight = 100;
-
-// Size of the small logo (for when we show 4 search engines).
-const int kLogoLabelWidthSmall = 132;
-const int kLogoLabelHeightSmall = 88;
-
-// The number of search engine options we normally show. It may be less than
-// this number if there are not enough search engines for the current locale,
-// or more if the user's imported default is not one of the top search engines
-// for the current locale.
-const size_t kNormalBallotSize = 3;
-
-// The width of the explanatory label. The 180 is the width of the large images.
-const int kExplanationWidth = kNormalBallotSize * 180;
-
-// Horizontal spacing between search engine choices.
-const int kSearchEngineSpacing = 6;
-
-// Set the (x, y) coordinates of the welcome message (which floats on top of
-// the omnibox image at the top of the first run dialog).
-void SetWelcomePosition(GtkFloatingContainer* container,
-                        GtkAllocation* allocation,
-                        GtkWidget* label) {
-  GValue value = { 0, };
-  g_value_init(&value, G_TYPE_INT);
-
-  GtkRequisition req;
-  gtk_widget_size_request(label, &req);
-
-  int x = base::i18n::IsRTL() ?
-      allocation->width - req.width - gtk_util::kContentAreaSpacing :
-      gtk_util::kContentAreaSpacing;
-  g_value_set_int(&value, x);
-  gtk_container_child_set_property(GTK_CONTAINER(container),
-                                   label, "x", &value);
-
-  int y = allocation->height / 2 - req.height / 2;
-  g_value_set_int(&value, y);
-  gtk_container_child_set_property(GTK_CONTAINER(container),
-                                   label, "y", &value);
-  g_value_unset(&value);
-}
-
-}  // namespace
-
-// static
-bool FirstRunDialog::Show(Profile* profile,
-                          bool randomize_search_engine_order) {
-  // Figure out which dialogs we will show.
-  // If the default search is managed via policy, we won't ask.
-  const TemplateURLModel* search_engines_model = profile->GetTemplateURLModel();
-  bool show_search_engines_dialog = search_engines_model &&
-      !search_engines_model->is_default_search_managed();
-
-#if defined(GOOGLE_CHROME_BUILD)
-  // If the metrics reporting is managed, we won't ask.
-  const PrefService::Preference* metrics_reporting_pref =
-      g_browser_process->local_state()->FindPreference(
-          prefs::kMetricsReportingEnabled);
-  bool show_reporting_dialog = !metrics_reporting_pref ||
-      !metrics_reporting_pref->IsManaged();
-#else
-  bool show_reporting_dialog = false;
-#endif
-
-  if (!show_search_engines_dialog && !show_reporting_dialog)
-    return true;  // Nothing to do
-
-  int response = -1;
-  // Object deletes itself.
-  new FirstRunDialog(profile,
-                     show_reporting_dialog,
-                     show_search_engines_dialog,
-                     &response);
-
-  // TODO(port): it should be sufficient to just run the dialog:
-  // int response = gtk_dialog_run(GTK_DIALOG(dialog));
-  // but that spins a nested message loop and hoses us.  :(
-  // http://code.google.com/p/chromium/issues/detail?id=12552
-  // Instead, run a loop and extract the response manually.
-  MessageLoop::current()->Run();
-
-  return (response == GTK_RESPONSE_ACCEPT);
-}
-
-FirstRunDialog::FirstRunDialog(Profile* profile,
-                               bool show_reporting_dialog,
-                               bool show_search_engines_dialog,
-                               int* response)
-    : search_engine_window_(NULL),
-      dialog_(NULL),
-      report_crashes_(NULL),
-      make_default_(NULL),
-      profile_(profile),
-      chosen_search_engine_(NULL),
-      show_reporting_dialog_(show_reporting_dialog),
-      response_(response) {
-  if (!show_search_engines_dialog) {
-    ShowReportingDialog();
-    return;
-  }
-  search_engines_model_ = profile_->GetTemplateURLModel();
-
-  ShowSearchEngineWindow();
-
-  search_engines_model_->AddObserver(this);
-  if (search_engines_model_->loaded())
-    OnTemplateURLModelChanged();
-  else
-    search_engines_model_->Load();
-}
-
-FirstRunDialog::~FirstRunDialog() {
-}
-
-void FirstRunDialog::ShowSearchEngineWindow() {
-  search_engine_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-  gtk_window_set_deletable(GTK_WINDOW(search_engine_window_), FALSE);
-  gtk_window_set_title(
-      GTK_WINDOW(search_engine_window_),
-      l10n_util::GetStringUTF8(IDS_FIRSTRUN_DLG_TITLE).c_str());
-  gtk_window_set_resizable(GTK_WINDOW(search_engine_window_), FALSE);
-  g_signal_connect(search_engine_window_, "destroy",
-                   G_CALLBACK(OnSearchEngineWindowDestroyThunk), this);
-  GtkWidget* content_area = gtk_vbox_new(FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(search_engine_window_), content_area);
-
-  GdkPixbuf* pixbuf =
-      ResourceBundle::GetSharedInstance().GetRTLEnabledPixbufNamed(
-          IDR_SEARCH_ENGINE_DIALOG_TOP);
-  GtkWidget* top_image = gtk_image_new_from_pixbuf(pixbuf);
-  // Right align the image.
-  gtk_misc_set_alignment(GTK_MISC(top_image), 1, 0);
-  gtk_widget_set_size_request(top_image, 0, -1);
-
-  GtkWidget* welcome_message = gtk_util::CreateBoldLabel(
-      l10n_util::GetStringUTF8(IDS_FR_SEARCH_MAIN_LABEL));
-  // Force the font size to make sure the label doesn't overlap the image.
-  // 13.4px == 10pt @ 96dpi
-  gtk_util::ForceFontSizePixels(welcome_message, 13.4);
-
-  GtkWidget* top_area = gtk_floating_container_new();
-  gtk_container_add(GTK_CONTAINER(top_area), top_image);
-  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(top_area),
-                                      welcome_message);
-  g_signal_connect(top_area, "set-floating-position",
-                   G_CALLBACK(SetWelcomePosition), welcome_message);
-
-  gtk_box_pack_start(GTK_BOX(content_area), top_area,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* bubble_area_background = gtk_event_box_new();
-  gtk_widget_modify_bg(bubble_area_background,
-                       GTK_STATE_NORMAL, &gtk_util::kGdkWhite);
-
-  GtkWidget* bubble_area_box = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(bubble_area_box),
-                                 gtk_util::kContentAreaSpacing);
-  gtk_container_add(GTK_CONTAINER(bubble_area_background),
-                    bubble_area_box);
-
-  GtkWidget* explanation = gtk_label_new(
-      l10n_util::GetStringFUTF8(IDS_FR_SEARCH_TEXT,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
-  gtk_misc_set_alignment(GTK_MISC(explanation), 0, 0.5);
-  gtk_util::SetLabelColor(explanation, &gtk_util::kGdkBlack);
-  gtk_util::SetLabelWidth(explanation, kExplanationWidth);
-  gtk_box_pack_start(GTK_BOX(bubble_area_box), explanation, FALSE, FALSE, 0);
-
-  // We will fill this in after the TemplateURLModel has loaded.
-  // GtkHButtonBox because we want all children to have the same size.
-  search_engine_hbox_ = gtk_hbutton_box_new();
-  gtk_box_set_spacing(GTK_BOX(search_engine_hbox_), kSearchEngineSpacing);
-  gtk_box_pack_start(GTK_BOX(bubble_area_box), search_engine_hbox_,
-                     FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(content_area), bubble_area_background,
-                     TRUE, TRUE, 0);
-
-  gtk_widget_show_all(content_area);
-  gtk_window_present(GTK_WINDOW(search_engine_window_));
-}
-
-void FirstRunDialog::ShowReportingDialog() {
-  // The purpose of the dialog is to ask the user to enable stats and crash
-  // reporting. This setting may be controlled through configuration management
-  // in enterprise scenarios. If that is the case, skip the dialog entirely,
-  // it's not worth bothering the user for only the default browser question
-  // (which is likely to be forced in enterprise deployments anyway).
-  if (!show_reporting_dialog_) {
-    OnResponseDialog(NULL, GTK_RESPONSE_ACCEPT);
-    return;
-  }
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_FIRSTRUN_DLG_TITLE).c_str(),
-      NULL,  // No parent
-      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      NULL);
-  gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(IDS_FIRSTRUN_DLG_OK).c_str(),
-      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
-  gtk_window_set_deletable(GTK_WINDOW(dialog_), FALSE);
-
-  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
-
-  g_signal_connect(dialog_, "delete-event",
-                   G_CALLBACK(gtk_widget_hide_on_delete), NULL);
-
-  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
-
-  make_default_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_FR_CUSTOMIZE_DEFAULT_BROWSER).c_str());
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(make_default_), TRUE);
-  gtk_box_pack_start(GTK_BOX(content_area), make_default_, FALSE, FALSE, 0);
-
-  report_crashes_ = gtk_check_button_new();
-  GtkWidget* check_label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ENABLE_LOGGING).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(check_label), TRUE);
-  gtk_container_add(GTK_CONTAINER(report_crashes_), check_label);
-  GtkWidget* learn_more_vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(learn_more_vbox), report_crashes_,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
-  gtk_button_set_alignment(GTK_BUTTON(learn_more_link), 0.0, 0.5);
-  gtk_box_pack_start(GTK_BOX(learn_more_vbox),
-                     gtk_util::IndentWidget(learn_more_link),
-                     FALSE, FALSE, 0);
-  g_signal_connect(learn_more_link, "clicked",
-                   G_CALLBACK(OnLearnMoreLinkClickedThunk), this);
-
-  gtk_box_pack_start(GTK_BOX(content_area), learn_more_vbox, FALSE, FALSE, 0);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnResponseDialogThunk), this);
-  gtk_widget_show_all(dialog_);
-}
-
-void FirstRunDialog::OnTemplateURLModelChanged() {
-  // We only watch the search engine model change once, on load.  Remove
-  // observer so we don't try to redraw if engines change under us.
-  search_engines_model_->RemoveObserver(this);
-
-  // Add search engines in |search_engines_model_| to buttons list.
-  std::vector<const TemplateURL*> ballot_engines =
-      search_engines_model_->GetTemplateURLs();
-  // Drop any not in the first 3.
-  if (ballot_engines.size() > kNormalBallotSize)
-    ballot_engines.resize(kNormalBallotSize);
-
-  const TemplateURL* default_search_engine =
-      search_engines_model_->GetDefaultSearchProvider();
-  if (std::find(ballot_engines.begin(),
-                ballot_engines.end(),
-                default_search_engine) ==
-      ballot_engines.end()) {
-    ballot_engines.push_back(default_search_engine);
-  }
-
-  std::string choose_text = l10n_util::GetStringUTF8(IDS_FR_SEARCH_CHOOSE);
-  for (std::vector<const TemplateURL*>::iterator search_engine_iter =
-           ballot_engines.begin();
-       search_engine_iter < ballot_engines.end();
-       ++search_engine_iter) {
-    // Create a container for the search engine widgets.
-    GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-    // We show text on Chromium and images on Google Chrome.
-    bool show_images = false;
-#if defined(GOOGLE_CHROME_BUILD)
-    show_images = true;
-#endif
-
-    // Create the image (maybe).
-    int logo_id = (*search_engine_iter)->logo_id();
-    if (show_images && logo_id > 0) {
-      GdkPixbuf* pixbuf =
-          ResourceBundle::GetSharedInstance().GetPixbufNamed(logo_id);
-      if (ballot_engines.size() > kNormalBallotSize) {
-        pixbuf = gdk_pixbuf_scale_simple(pixbuf,
-                                         kLogoLabelWidthSmall,
-                                         kLogoLabelHeightSmall,
-                                         GDK_INTERP_HYPER);
-      } else {
-        g_object_ref(pixbuf);
-      }
-
-      GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
-      gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
-      g_object_unref(pixbuf);
-    } else {
-      GtkWidget* logo_label = gtk_label_new(NULL);
-      char* markup = g_markup_printf_escaped(
-          "<span weight='bold' size='x-large' color='black'>%s</span>",
-          WideToUTF8((*search_engine_iter)->short_name()).c_str());
-      gtk_label_set_markup(GTK_LABEL(logo_label), markup);
-      g_free(markup);
-      gtk_widget_set_size_request(logo_label, -1,
-          ballot_engines.size() > kNormalBallotSize ? kLogoLabelHeightSmall :
-                                                      kLogoLabelHeight);
-      gtk_box_pack_start(GTK_BOX(vbox), logo_label, FALSE, FALSE, 0);
-    }
-
-    // Create the button.
-    GtkWidget* button = gtk_button_new_with_label(choose_text.c_str());
-    g_signal_connect(button, "clicked",
-                     G_CALLBACK(OnSearchEngineButtonClickedThunk), this);
-    g_object_set_data(G_OBJECT(button), kSearchEngineKey,
-                      const_cast<TemplateURL*>(*search_engine_iter));
-
-    GtkWidget* button_centerer = gtk_hbox_new(FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(button_centerer), button, TRUE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), button_centerer, FALSE, FALSE, 0);
-
-    gtk_container_add(GTK_CONTAINER(search_engine_hbox_), vbox);
-    gtk_widget_show_all(search_engine_hbox_);
-  }
-}
-
-void FirstRunDialog::OnSearchEngineButtonClicked(GtkWidget* sender) {
-  chosen_search_engine_ = static_cast<TemplateURL*>(
-      g_object_get_data(G_OBJECT(sender), kSearchEngineKey));
-  gtk_widget_destroy(search_engine_window_);
-}
-
-void FirstRunDialog::OnSearchEngineWindowDestroy(GtkWidget* sender) {
-  search_engine_window_ = NULL;
-  if (chosen_search_engine_) {
-    search_engines_model_->SetDefaultSearchProvider(chosen_search_engine_);
-    ShowReportingDialog();
-  } else {
-    FirstRunDone();
-  }
-}
-
-void FirstRunDialog::OnResponseDialog(GtkWidget* widget, int response) {
-  if (dialog_)
-    gtk_widget_hide_all(dialog_);
-  *response_ = response;
-
-  // Mark that first run has ran.
-  FirstRun::CreateSentinel();
-
-  // Check if user has opted into reporting.
-  if (report_crashes_ &&
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(report_crashes_))) {
-#if defined(USE_LINUX_BREAKPAD)
-    if (GoogleUpdateSettings::SetCollectStatsConsent(true))
-      InitCrashReporter();
-#endif
-  } else {
-    GoogleUpdateSettings::SetCollectStatsConsent(false);
-  }
-
-  // If selected set as default browser.
-  if (make_default_ &&
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(make_default_))) {
-    ShellIntegration::SetAsDefaultBrowser();
-  }
-
-  FirstRunDone();
-}
-
-void FirstRunDialog::OnLearnMoreLinkClicked(GtkButton* button) {
-  platform_util::OpenExternal(google_util::AppendGoogleLocaleParam(
-      GURL(chrome::kLearnMoreReportingURL)));
-}
-
-void FirstRunDialog::FirstRunDone() {
-  FirstRun::SetShowWelcomePagePref();
-
-  if (dialog_)
-    gtk_widget_destroy(dialog_);
-  MessageLoop::current()->Quit();
-  delete this;
-}
diff --git a/chrome/browser/gtk/first_run_dialog.h b/chrome/browser/gtk/first_run_dialog.h
deleted file mode 100644
index 234a64b..0000000
--- a/chrome/browser/gtk/first_run_dialog.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_FIRST_RUN_DIALOG_H_
-#define CHROME_BROWSER_GTK_FIRST_RUN_DIALOG_H_
-#pragma once
-
-typedef struct _GtkButton GtkButton;
-typedef struct _GtkWidget GtkWidget;
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/search_engines/template_url_model_observer.h"
-
-class TemplateURL;
-class TemplateURLModel;
-
-class FirstRunDialog : public TemplateURLModelObserver {
- public:
-  // Displays the first run UI for reporting opt-in, import data etc.
-  static bool Show(Profile* profile, bool randomize_search_engine_order);
-
-  virtual void OnTemplateURLModelChanged();
-
- private:
-  FirstRunDialog(Profile* profile,
-                 bool show_reporting_dialog,
-                 bool show_search_engines_dialog,
-                 int* response);
-  virtual ~FirstRunDialog();
-
-  CHROMEGTK_CALLBACK_1(FirstRunDialog, void, OnResponseDialog, int);
-  CHROMEGTK_CALLBACK_0(FirstRunDialog, void, OnSearchEngineButtonClicked);
-  CHROMEGTK_CALLBACK_0(FirstRunDialog, void, OnSearchEngineWindowDestroy);
-  CHROMEG_CALLBACK_0(FirstRunDialog, void, OnLearnMoreLinkClicked, GtkButton*);
-
-  void ShowSearchEngineWindow();
-  void ShowReportingDialog();
-
-  // This method closes the first run window and quits the message loop so that
-  // the Chrome startup can continue. This should be called when all the
-  // first run tasks are done.
-  void FirstRunDone();
-
-  // The search engine choice window. This is created and shown before
-  // |dialog_|.
-  GtkWidget* search_engine_window_;
-
-  // Dialog that holds the bug reporting and default browser checkboxes.
-  GtkWidget* dialog_;
-
-  // Container for the search engine choices.
-  GtkWidget* search_engine_hbox_;
-
-  // Crash reporting checkbox
-  GtkWidget* report_crashes_;
-
-  // Make browser default checkbox
-  GtkWidget* make_default_;
-
-  // Our current profile
-  Profile* profile_;
-
-  // Owned by the profile_.
-  TemplateURLModel* search_engines_model_;
-
-  // The search engine the user chose, or NULL if the user has not chosen a
-  // search engine.
-  TemplateURL* chosen_search_engine_;
-
-  // Whether we should show the dialog asking the user whether to report
-  // crashes and usage stats.
-  bool show_reporting_dialog_;
-
-  // User response (accept or cancel) is returned through this.
-  int* response_;
-
-  DISALLOW_COPY_AND_ASSIGN(FirstRunDialog);
-};
-
-#endif  // CHROME_BROWSER_GTK_FIRST_RUN_DIALOG_H_
diff --git a/chrome/browser/gtk/focus_store_gtk.cc b/chrome/browser/gtk/focus_store_gtk.cc
deleted file mode 100644
index e882e2b..0000000
--- a/chrome/browser/gtk/focus_store_gtk.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/focus_store_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/platform_util.h"
-
-FocusStoreGtk::FocusStoreGtk()
-    : widget_(NULL),
-      destroy_handler_id_(0) {
-}
-
-FocusStoreGtk::~FocusStoreGtk() {
-  DisconnectDestroyHandler();
-}
-
-void FocusStoreGtk::Store(GtkWidget* widget) {
-  GtkWidget* focus_widget = NULL;
-  if (widget) {
-    GtkWindow* window = platform_util::GetTopLevel(widget);
-    if (window)
-      focus_widget = window->focus_widget;
-  }
-
-  SetWidget(focus_widget);
-}
-
-void FocusStoreGtk::SetWidget(GtkWidget* widget) {
-  DisconnectDestroyHandler();
-
-  // We don't add a ref. The signal handler below effectively gives us a weak
-  // reference.
-  widget_ = widget;
-  if (widget_) {
-    // When invoked, |gtk_widget_destroyed| will set |widget_| to NULL.
-    destroy_handler_id_ = g_signal_connect(widget_, "destroy",
-                                           G_CALLBACK(gtk_widget_destroyed),
-                                           &widget_);
-  }
-}
-
-void FocusStoreGtk::DisconnectDestroyHandler() {
-  if (widget_) {
-    g_signal_handler_disconnect(widget_, destroy_handler_id_);
-    widget_ = NULL;
-  }
-}
diff --git a/chrome/browser/gtk/focus_store_gtk.h b/chrome/browser/gtk/focus_store_gtk.h
deleted file mode 100644
index 2159f1e..0000000
--- a/chrome/browser/gtk/focus_store_gtk.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_FOCUS_STORE_GTK_H_
-#define CHROME_BROWSER_GTK_FOCUS_STORE_GTK_H_
-#pragma once
-
-#include "base/basictypes.h"
-
-typedef struct _GtkWidget GtkWidget;
-
-class FocusStoreGtk {
- public:
-  FocusStoreGtk();
-
-  virtual ~FocusStoreGtk();
-
-  GtkWidget* widget() const { return widget_; }
-
-  // Save the widget that is currently focused for |widget|'s toplevel (NOT
-  // |widget|).
-  void Store(GtkWidget* widget);
-
-  // Save |widget| as the focus widget. Call with NULL to clear |widget_|.
-  void SetWidget(GtkWidget* widget);
-
- private:
-  // Disconnect the previous destroy handler (if any).
-  void DisconnectDestroyHandler();
-
-  // The widget which last had focus.
-  GtkWidget* widget_;
-
-  // The widget for which we've stored focus might be destroyed by the time we
-  // want to restore focus. Thus we connect to the "destroy" signal on that
-  // widget. This is the ID for the destroy handler.
-  unsigned int destroy_handler_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(FocusStoreGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_FOCUS_STORE_GTK_H_
diff --git a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc b/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc
deleted file mode 100644
index ee452b8..0000000
--- a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/fullscreen_exit_bubble_gtk.h"
-
-#include "app/l10n_util.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_floating_container.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "grit/app_strings.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Padding around the link text.
-const int kPaddingPixels = 8;
-
-// Time before the link slides away. This is a bit longer than the Windows
-// timeout because we don't yet support reshowing when the mouse moves to the
-// of the screen.
-const int kInitialDelayMs = 3000;
-
-// How long the slide up animation takes when hiding the bubble.
-const int kSlideOutDurationMs = 700;
-
-}
-
-FullscreenExitBubbleGtk::FullscreenExitBubbleGtk(
-    GtkFloatingContainer* container)
-    : container_(container) {
-  InitWidgets();
-}
-
-FullscreenExitBubbleGtk::~FullscreenExitBubbleGtk() {
-}
-
-void FullscreenExitBubbleGtk::InitWidgets() {
-  // The exit bubble is a gtk_chrome_link_button inside a gtk event box and gtk
-  // alignment (these provide the background color).  This is then made rounded
-  // and put into a slide widget.
-
-  // The Windows code actually looks up the accelerator key in the accelerator
-  // table and then converts the key to a string (in a switch statement).
-  std::string exit_text_utf8("<span color=\"white\" size=\"large\">");
-  exit_text_utf8.append(l10n_util::GetStringFUTF8(
-      IDS_EXIT_FULLSCREEN_MODE, l10n_util::GetStringUTF16(IDS_APP_F11_KEY)));
-  exit_text_utf8.append("</span>");
-  GtkWidget* link = gtk_chrome_link_button_new_with_markup(
-      exit_text_utf8.c_str());
-  gtk_chrome_link_button_set_use_gtk_theme(GTK_CHROME_LINK_BUTTON(link),
-                                           FALSE);
-  signals_.Connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
-
-  GtkWidget* container = gtk_util::CreateGtkBorderBin(
-      link, &gtk_util::kGdkBlack,
-      kPaddingPixels, kPaddingPixels, kPaddingPixels, kPaddingPixels);
-  gtk_util::ActAsRoundedWindow(container, gtk_util::kGdkGreen, kPaddingPixels,
-      gtk_util::ROUNDED_BOTTOM_LEFT | gtk_util::ROUNDED_BOTTOM_RIGHT,
-      gtk_util::BORDER_NONE);
-
-  slide_widget_.reset(new SlideAnimatorGtk(container,
-      SlideAnimatorGtk::DOWN, kSlideOutDurationMs, false, false, NULL));
-  gtk_widget_set_name(widget(), "exit-fullscreen-bubble");
-  gtk_widget_show_all(container);
-  gtk_widget_show(widget());
-  slide_widget_->OpenWithoutAnimation();
-
-  // TODO(tc): Implement the more complex logic in the windows version for
-  // when to show/hide the exit bubble.
-  initial_delay_.Start(base::TimeDelta::FromMilliseconds(kInitialDelayMs), this,
-                       &FullscreenExitBubbleGtk::Hide);
-
-  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(container_),
-                                      widget());
-  signals_.Connect(container_, "set-floating-position",
-                   G_CALLBACK(OnSetFloatingPositionThunk), this);
-}
-
-void FullscreenExitBubbleGtk::Hide() {
-  slide_widget_->Close();
-}
-
-void FullscreenExitBubbleGtk::OnSetFloatingPosition(
-    GtkWidget* floating_container,
-    GtkAllocation* allocation) {
-  GtkRequisition bubble_size;
-  gtk_widget_size_request(widget(), &bubble_size);
-
-  // Position the bubble at the top center of the screen.
-  GValue value = { 0, };
-  g_value_init(&value, G_TYPE_INT);
-  g_value_set_int(&value, (allocation->width - bubble_size.width) / 2);
-  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
-                                   widget(), "x", &value);
-
-  g_value_set_int(&value, 0);
-  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
-                                   widget(), "y", &value);
-  g_value_unset(&value);
-}
-
-void FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link) {
-  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(widget()));
-  gtk_window_unfullscreen(window);
-}
diff --git a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h b/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h
deleted file mode 100644
index 91be3ef..0000000
--- a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_
-#define CHROME_BROWSER_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "base/timer.h"
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-
-typedef struct _GtkFloatingContainer GtkFloatingContainer;
-typedef struct _GtkWidget GtkWidget;
-
-// FullscreenExitBubbleGTK is responsible for showing a bubble atop the screen
-// in fullscreen mode, telling users how to exit and providing a click target.
-class FullscreenExitBubbleGtk {
- public:
-  // We place the bubble in |container|.
-  explicit FullscreenExitBubbleGtk(GtkFloatingContainer* container);
-  virtual ~FullscreenExitBubbleGtk();
-
-  void InitWidgets();
-
- private:
-  GtkWidget* widget() const {
-    return slide_widget_->widget();
-  }
-
-  // Hide the exit bubble.
-  void Hide();
-
-  CHROMEGTK_CALLBACK_1(FullscreenExitBubbleGtk, void, OnSetFloatingPosition,
-                       GtkAllocation*);
-  CHROMEGTK_CALLBACK_0(FullscreenExitBubbleGtk, void, OnLinkClicked);
-
-  // A pointer to the floating container that is our parent.
-  GtkFloatingContainer* container_;
-
-  // The widget that animates the slide-out of fullscreen exit bubble.
-  scoped_ptr<SlideAnimatorGtk> slide_widget_;
-
-  // The timer that does the initial hiding of the exit bubble.
-  base::OneShotTimer<FullscreenExitBubbleGtk> initial_delay_;
-
-  GtkSignalRegistrar signals_;
-};
-
-#endif  // CHROME_BROWSER_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/gconf_titlebar_listener.cc b/chrome/browser/gtk/gconf_titlebar_listener.cc
deleted file mode 100644
index ae89f1a..0000000
--- a/chrome/browser/gtk/gconf_titlebar_listener.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gconf_titlebar_listener.h"
-
-#include <gtk/gtk.h>
-
-#include "base/scoped_ptr.h"
-#include "base/singleton.h"
-#include "base/environment.h"
-#include "base/nix/xdg_util.h"
-#include "chrome/browser/gtk/browser_titlebar.h"
-
-namespace {
-
-// The GConf key we read for the button placement string. Even through the key
-// has "metacity" in it, it's shared between metacity and compiz.
-const char* kButtonLayoutKey = "/apps/metacity/general/button_layout";
-
-// GConf requires us to subscribe to a parent directory before we can subscribe
-// to changes in an individual key in that directory.
-const char* kMetacityGeneral = "/apps/metacity/general";
-
-}  // namespace
-
-// Public interface:
-
-// static
-GConfTitlebarListener* GConfTitlebarListener::GetInstance() {
-  return Singleton<GConfTitlebarListener>::get();
-}
-
-void GConfTitlebarListener::SetTitlebarButtons(BrowserTitlebar* titlebar) {
-  if (client_) {
-    titlebar->BuildButtons(current_value_);
-    titlebars_.insert(titlebar);
-  } else {
-    titlebar->BuildButtons(BrowserTitlebar::kDefaultButtonString);
-  }
-}
-
-void GConfTitlebarListener::RemoveObserver(BrowserTitlebar* titlebar) {
-  titlebars_.erase(titlebar);
-}
-
-// Protected:
-
-GConfTitlebarListener::~GConfTitlebarListener() {}
-
-// Private:
-
-GConfTitlebarListener::GConfTitlebarListener() : client_(NULL) {
-  scoped_ptr<base::Environment> env(base::Environment::Create());
-  if (base::nix::GetDesktopEnvironment(env.get()) ==
-      base::nix::DESKTOP_ENVIRONMENT_GNOME) {
-    client_ = gconf_client_get_default();
-    // If we fail to get a context, that's OK, since we'll just fallback on
-    // not receiving gconf keys.
-    if (client_) {
-      // Get the initial value of the key.
-      GError* error = NULL;
-      GConfValue* gconf_value = gconf_client_get(client_, kButtonLayoutKey,
-                                                 &error);
-      if (HandleGError(error, kButtonLayoutKey))
-        return;
-      ParseAndStoreValue(gconf_value);
-      if (gconf_value)
-        gconf_value_free(gconf_value);
-
-      // Register that we're interested in the values of this directory.
-      gconf_client_add_dir(client_, kMetacityGeneral,
-                           GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
-      if (HandleGError(error, kMetacityGeneral))
-        return;
-
-      // Register to get notifies about changes to this key.
-      gconf_client_notify_add(
-          client_, kButtonLayoutKey,
-          reinterpret_cast<void (*)(GConfClient*, guint, GConfEntry*, void*)>(
-              OnChangeNotificationThunk),
-          this, NULL, &error);
-      if (HandleGError(error, kButtonLayoutKey))
-        return;
-    }
-  }
-}
-
-void GConfTitlebarListener::OnChangeNotification(GConfClient* client,
-                                                 guint cnxn_id,
-                                                 GConfEntry* entry) {
-  if (strcmp(gconf_entry_get_key(entry), kButtonLayoutKey) == 0) {
-    GConfValue* gconf_value = gconf_entry_get_value(entry);
-    ParseAndStoreValue(gconf_value);
-
-    // Broadcast the new configuration to all windows:
-    for (std::set<BrowserTitlebar*>::const_iterator it = titlebars_.begin();
-         it != titlebars_.end(); ++it) {
-      (*it)->BuildButtons(current_value_);
-    }
-  }
-}
-
-bool GConfTitlebarListener::HandleGError(GError* error, const char* key) {
-  if (error != NULL) {
-    LOG(ERROR) << "Error with gconf key '" << key << "': " << error->message;
-    g_error_free(error);
-    g_object_unref(client_);
-    client_ = NULL;
-    return true;
-  }
-  return false;
-}
-
-void GConfTitlebarListener::ParseAndStoreValue(GConfValue* gconf_value) {
-  if (gconf_value) {
-    const char* value = gconf_value_get_string(gconf_value);
-    current_value_ = value ? value : BrowserTitlebar::kDefaultButtonString;
-  } else {
-    current_value_ = BrowserTitlebar::kDefaultButtonString;
-  }
-}
diff --git a/chrome/browser/gtk/gconf_titlebar_listener.h b/chrome/browser/gtk/gconf_titlebar_listener.h
deleted file mode 100644
index b96b759..0000000
--- a/chrome/browser/gtk/gconf_titlebar_listener.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GCONF_TITLEBAR_LISTENER_H_
-#define CHROME_BROWSER_GTK_GCONF_TITLEBAR_LISTENER_H_
-#pragma once
-
-#include <gconf/gconf-client.h>
-#include <gtk/gtk.h>
-
-#include <set>
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-
-class BrowserTitlebar;
-template <typename T> struct DefaultSingletonTraits;
-
-// On GNOME desktops, subscribes to the gconf key which controlls button order.
-// Everywhere else, SetTiltebarButtons() just calls back into BrowserTitlebar
-// with the default ordering.
-//
-// Meant to be used as a Singleton through base/singleton.h's interface.
-class GConfTitlebarListener {
- public:
-  // Returns the singleton instance.
-  static GConfTitlebarListener* GetInstance();
-
-  // Sets the current titlebar button order. On GNOME desktops, also subscribes
-  // to further notifications when this changes.
-  void SetTitlebarButtons(BrowserTitlebar* titlebar);
-
-  // Removes |titlebar| from the list of objects observing button order change
-  // notifications.
-  void RemoveObserver(BrowserTitlebar* titlebar);
-
- protected:
-  virtual ~GConfTitlebarListener();
-
- private:
-  // Private constructor to enforce singleton access.
-  GConfTitlebarListener();
-
-  // Called whenever the metacity key changes.
-  CHROMEG_CALLBACK_2(GConfTitlebarListener, void, OnChangeNotification,
-                     GConfClient*, guint, GConfEntry*);
-
-  // Checks |error|. On error, prints out a message and closes the connection
-  // to GConf and reverts to default mode.
-  bool HandleGError(GError* error, const char* key);
-
-  // Parses the return data structure from GConf, falling back to the default
-  // value on any error.
-  void ParseAndStoreValue(GConfValue* gconf_value);
-
-  // Pointer to our gconf context. NULL if we aren't on a desktop that uses
-  // gconf.
-  GConfClient* client_;
-
-  // The current button ordering as heard from gconf.
-  std::string current_value_;
-
-  // BrowserTitlebar objects which have subscribed to updates.
-  std::set<BrowserTitlebar*> titlebars_;
-
-  friend struct DefaultSingletonTraits<GConfTitlebarListener>;
-  DISALLOW_COPY_AND_ASSIGN(GConfTitlebarListener);
-};
-
-#endif  // CHROME_BROWSER_GTK_GCONF_TITLEBAR_LISTENER_H_
diff --git a/chrome/browser/gtk/gtk_chrome_button.cc b/chrome/browser/gtk/gtk_chrome_button.cc
deleted file mode 100644
index 20310a5..0000000
--- a/chrome/browser/gtk/gtk_chrome_button.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-
-#include "base/basictypes.h"
-#include "chrome/browser/gtk/nine_box.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-
-namespace {
-
-// The theme graphics for when the mouse is over the button.
-NineBox* g_nine_box_prelight;
-// The theme graphics for when the button is clicked.
-NineBox* g_nine_box_active;
-
-}  // namespace
-
-G_BEGIN_DECLS
-
-#define GTK_CHROME_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),\
-                                          GTK_TYPE_CHROME_BUTTON,\
-                                          GtkChromeButtonPrivate))
-typedef struct _GtkChromeButtonPrivate GtkChromeButtonPrivate;
-
-struct _GtkChromeButtonPrivate {
-  int paint_state;
-
-  // If true, we use images provided by the theme instead of GTK's default
-  // button rendering.
-  gboolean use_gtk_rendering;
-
-  gdouble hover_state;
-};
-
-G_DEFINE_TYPE(GtkChromeButton, gtk_chrome_button, GTK_TYPE_BUTTON)
-static gboolean gtk_chrome_button_expose(GtkWidget* widget,
-                                         GdkEventExpose* event);
-
-static void gtk_chrome_button_class_init(GtkChromeButtonClass* button_class) {
-  gtk_rc_parse_string(
-      "style \"chrome-button\" {"
-      "  xthickness = 2 "
-      "  GtkButton::child-displacement-x = 0"
-      "  GtkButton::child-displacement-y = 0"
-      "  GtkButton::inner-border = { 0, 0, 0, 0 }"
-      "}"
-      "widget_class \"*.<GtkChromeButton>\" style \"chrome-button\"");
-
-  GtkWidgetClass* widget_class =
-      reinterpret_cast<GtkWidgetClass*>(button_class);
-  widget_class->expose_event = gtk_chrome_button_expose;
-
-  g_nine_box_prelight = new NineBox(
-      IDR_TEXTBUTTON_TOP_LEFT_H,
-      IDR_TEXTBUTTON_TOP_H,
-      IDR_TEXTBUTTON_TOP_RIGHT_H,
-      IDR_TEXTBUTTON_LEFT_H,
-      IDR_TEXTBUTTON_CENTER_H,
-      IDR_TEXTBUTTON_RIGHT_H,
-      IDR_TEXTBUTTON_BOTTOM_LEFT_H,
-      IDR_TEXTBUTTON_BOTTOM_H,
-      IDR_TEXTBUTTON_BOTTOM_RIGHT_H);
-
-  g_nine_box_active = new NineBox(
-      IDR_TEXTBUTTON_TOP_LEFT_P,
-      IDR_TEXTBUTTON_TOP_P,
-      IDR_TEXTBUTTON_TOP_RIGHT_P,
-      IDR_TEXTBUTTON_LEFT_P,
-      IDR_TEXTBUTTON_CENTER_P,
-      IDR_TEXTBUTTON_RIGHT_P,
-      IDR_TEXTBUTTON_BOTTOM_LEFT_P,
-      IDR_TEXTBUTTON_BOTTOM_P,
-      IDR_TEXTBUTTON_BOTTOM_RIGHT_P);
-
-  GObjectClass* gobject_class = G_OBJECT_CLASS(button_class);
-  g_type_class_add_private(gobject_class, sizeof(GtkChromeButtonPrivate));
-}
-
-static void gtk_chrome_button_init(GtkChromeButton* button) {
-  GtkChromeButtonPrivate* priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
-  priv->paint_state = -1;
-  priv->use_gtk_rendering = FALSE;
-  priv->hover_state = -1.0;
-
-  GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
-}
-
-static gboolean gtk_chrome_button_expose(GtkWidget* widget,
-                                         GdkEventExpose* event) {
-  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(widget);
-  int paint_state = priv->paint_state < 0 ?
-                    GTK_WIDGET_STATE(widget) : priv->paint_state;
-
-  if (priv->use_gtk_rendering) {
-    // We have the superclass handle this expose when we aren't using custom
-    // rendering AND we're in either the prelight or active state so that we
-    // get the button border for the current GTK theme drawn.
-    if (paint_state == GTK_STATE_PRELIGHT || paint_state == GTK_STATE_ACTIVE) {
-      // Set the state of button->depressed so we paint pressed even if the
-      // actual state of the button is something else.
-      GTK_BUTTON(widget)->depressed = (paint_state == GTK_STATE_ACTIVE);
-      return GTK_WIDGET_CLASS(gtk_chrome_button_parent_class)->expose_event
-          (widget, event);
-    }
-  } else {
-    double effective_hover_state = paint_state == GTK_STATE_PRELIGHT ?
-                                   1.0 : 0.0;
-    // |paint_state| overrides |hover_state|.
-    if (priv->hover_state >= 0.0 && priv->paint_state < 0)
-      effective_hover_state = priv->hover_state;
-
-    if (paint_state == GTK_STATE_ACTIVE) {
-      g_nine_box_active->RenderToWidget(widget);
-    } else {
-      g_nine_box_prelight->RenderToWidgetWithOpacity(widget,
-                                                     effective_hover_state);
-    }
-  }
-
-  // If we have a child widget, draw it.
-  if (gtk_bin_get_child(GTK_BIN(widget))) {
-    gtk_container_propagate_expose(GTK_CONTAINER(widget),
-                                   gtk_bin_get_child(GTK_BIN(widget)),
-                                   event);
-  }
-
-  return FALSE;
-}
-
-GtkWidget* gtk_chrome_button_new(void) {
-  return GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_BUTTON, NULL));
-}
-
-void gtk_chrome_button_set_paint_state(GtkChromeButton* button,
-                                       GtkStateType state) {
-  g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
-
-  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
-  priv->paint_state = state;
-
-  gtk_widget_queue_draw(GTK_WIDGET(button));
-}
-
-void gtk_chrome_button_unset_paint_state(GtkChromeButton* button) {
-  g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
-
-  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
-  priv->paint_state = -1;
-
-  gtk_widget_queue_draw(GTK_WIDGET(button));
-}
-
-void gtk_chrome_button_set_use_gtk_rendering(GtkChromeButton* button,
-                                             gboolean value) {
-  g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
-  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
-  priv->use_gtk_rendering = value;
-}
-
-void gtk_chrome_button_set_hover_state(GtkChromeButton* button,
-                                       gdouble state) {
-  GtkChromeButtonPrivate* priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
-  if (state >= 0.0 && state <= 1.0)
-    priv->hover_state = state;
-  else
-    priv->hover_state = -1.0;
-  gtk_widget_queue_draw(GTK_WIDGET(button));
-}
-
-G_END_DECLS
diff --git a/chrome/browser/gtk/gtk_chrome_button.h b/chrome/browser/gtk/gtk_chrome_button.h
deleted file mode 100644
index e64c00b..0000000
--- a/chrome/browser/gtk/gtk_chrome_button.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_CHROME_BUTTON_H_
-#define CHROME_BROWSER_GTK_GTK_CHROME_BUTTON_H_
-#pragma once
-
-#include <gdk/gdk.h>
-#include <gtk/gtkbutton.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CHROME_BUTTON        (gtk_chrome_button_get_type ())
-#define GTK_CHROME_BUTTON(obj)                              \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CHROME_BUTTON, GtkChromeButton))
-#define GTK_CHROME_BUTTON_CLASS(klass)                      \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CHROME_BUTTON, \
-                           GtkChromeButtonClass))
-#define GTK_IS_CHROME_BUTTON(obj)                           \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHROME_BUTTON))
-#define GTK_IS_CHROME_BUTTON_CLASS(klass)                   \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHROME_BUTTON))
-#define GTK_CHROME_BUTTON_GET_CLASS(obj)                    \
-  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHROME_BUTTON, GtkChromeButton))
-
-typedef struct _GtkChromeButton        GtkChromeButton;
-typedef struct _GtkChromeButtonClass   GtkChromeButtonClass;
-
-struct _GtkChromeButton {
-  GtkButton button;
-};
-
-struct _GtkChromeButtonClass {
-  GtkButtonClass parent_class;
-};
-
-GtkWidget* gtk_chrome_button_new();
-
-GType gtk_chrome_button_get_type();
-
-// Set the paint state to |state|. This overrides the widget's current state.
-void gtk_chrome_button_set_paint_state(GtkChromeButton* button,
-                                       GtkStateType state);
-
-// Revert to using the widget's current state for painting.
-void gtk_chrome_button_unset_paint_state(GtkChromeButton* button);
-
-// Whether we should use custom theme images or let GTK take care of it.
-void gtk_chrome_button_set_use_gtk_rendering(GtkChromeButton* button,
-                                             gboolean value);
-
-// Sets the partial hover state of the button. The acceptable range is 0.0 to
-// 1.0. If |state| is outside of that range, then revert the button to normal
-// hovering. This can be overridden by gtk_chrome_button_set_paint_state.
-void gtk_chrome_button_set_hover_state(GtkChromeButton* button,
-                                       gdouble state);
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_CHROME_BUTTON_H_
diff --git a/chrome/browser/gtk/gtk_chrome_cookie_view.cc b/chrome/browser/gtk/gtk_chrome_cookie_view.cc
deleted file mode 100644
index a0e3c62..0000000
--- a/chrome/browser/gtk/gtk_chrome_cookie_view.cc
+++ /dev/null
@@ -1,675 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_chrome_cookie_view.h"
-
-#include "app/l10n_util.h"
-#include "base/i18n/time_formatting.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-void InitBrowserDetailStyle(GtkWidget* entry, GtkStyle* label_style,
-                            GtkStyle* dialog_style) {
-  gtk_widget_modify_fg(entry, GTK_STATE_NORMAL,
-                       &label_style->fg[GTK_STATE_NORMAL]);
-  gtk_widget_modify_fg(entry, GTK_STATE_INSENSITIVE,
-                       &label_style->fg[GTK_STATE_INSENSITIVE]);
-  // GTK_NO_WINDOW widgets like GtkLabel don't draw their own background, so we
-  // combine the normal or insensitive foreground of the label style with the
-  // normal background of the window style to achieve the "normal label" and
-  // "insensitive label" colors.
-  gtk_widget_modify_base(entry, GTK_STATE_NORMAL,
-                         &dialog_style->bg[GTK_STATE_NORMAL]);
-  gtk_widget_modify_base(entry, GTK_STATE_INSENSITIVE,
-                         &dialog_style->bg[GTK_STATE_NORMAL]);
-}
-
-GtkWidget* InitRowLabel(int row, int label_id, GtkWidget* details_table) {
-  GtkWidget* name_label = gtk_label_new(
-      l10n_util::GetStringUTF8(label_id).c_str());
-  gtk_misc_set_alignment(GTK_MISC(name_label), 1, 0.5);
-  gtk_table_attach(GTK_TABLE(details_table), name_label,
-                   0, 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
-
-  return name_label;
-}
-
-GtkWidget* InitDetailRow(int row, int label_id,
-                         GtkWidget* details_table, GtkWidget** entry) {
-  GtkWidget* name_label = InitRowLabel(row, label_id, details_table);
-
-  *entry = gtk_entry_new();
-  gtk_entry_set_editable(GTK_ENTRY(*entry), FALSE);
-  gtk_entry_set_has_frame(GTK_ENTRY(*entry), FALSE);
-  gtk_table_attach_defaults(GTK_TABLE(details_table), *entry,
-                            1, 2, row, row + 1);
-
-  return name_label;
-}
-
-GtkWidget* InitComboboxRow(int row, int label_id,
-                           GtkWidget* details_table,
-                           GtkWidget** combobox,
-                           GtkListStore** store) {
-  GtkWidget* name_label = InitRowLabel(row, label_id, details_table);
-
-  *store = gtk_list_store_new(1, G_TYPE_STRING);
-  *combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(*store));
-  g_object_unref(*store);
-
-  GtkCellRenderer* cell = gtk_cell_renderer_text_new();
-  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(*combobox), cell, TRUE);
-  gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(*combobox), cell,
-                                  "text", 0, NULL);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), *combobox, FALSE, FALSE, 0);
-
-  gtk_table_attach_defaults(GTK_TABLE(details_table), hbox,
-                            1, 2, row, row + 1);
-
-  return name_label;
-}
-
-void InitStyles(GtkChromeCookieView *self) {
-  GtkStyle* label_style = gtk_widget_get_style(self->first_label_);
-  GtkStyle* dialog_style = gtk_widget_get_style(GTK_WIDGET(self));
-
-  // Cookie details.
-  InitBrowserDetailStyle(self->cookie_name_entry_, label_style, dialog_style);
-  InitBrowserDetailStyle(self->cookie_content_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->cookie_domain_entry_, label_style, dialog_style);
-  InitBrowserDetailStyle(self->cookie_path_entry_, label_style, dialog_style);
-  InitBrowserDetailStyle(self->cookie_send_for_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->cookie_created_entry_, label_style,
-                         dialog_style);
-  if (self->cookie_expires_entry_) {
-    InitBrowserDetailStyle(self->cookie_expires_entry_, label_style,
-                           dialog_style);
-  }
-
-  // Database details.
-  InitBrowserDetailStyle(self->database_name_entry_, label_style, dialog_style);
-  InitBrowserDetailStyle(self->database_description_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->database_size_entry_, label_style, dialog_style);
-  InitBrowserDetailStyle(self->database_last_modified_entry_, label_style,
-                         dialog_style);
-
-  // Local storage details.
-  InitBrowserDetailStyle(self->local_storage_origin_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->local_storage_size_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->local_storage_last_modified_entry_, label_style,
-                         dialog_style);
-
-  // AppCache details.
-  InitBrowserDetailStyle(self->appcache_manifest_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->appcache_size_entry_, label_style, dialog_style);
-  InitBrowserDetailStyle(self->appcache_created_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->appcache_last_accessed_entry_, label_style,
-                         dialog_style);
-
-  // Local storage item.
-  InitBrowserDetailStyle(self->local_storage_item_origin_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->local_storage_item_key_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->local_storage_item_value_entry_, label_style,
-                         dialog_style);
-
-  // Database accessed item.
-  InitBrowserDetailStyle(self->database_accessed_origin_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->database_accessed_name_entry_, label_style,
-                         dialog_style);
-  InitBrowserDetailStyle(self->database_accessed_description_entry_,
-                         label_style, dialog_style);
-  InitBrowserDetailStyle(self->database_accessed_size_entry_, label_style,
-                         dialog_style);
-
-  // AppCache created item.
-  InitBrowserDetailStyle(self->appcache_created_manifest_entry_, label_style,
-                         dialog_style);
-}
-
-void SetCookieDetailsSensitivity(GtkChromeCookieView *self,
-                                 gboolean enabled) {
-  gtk_widget_set_sensitive(self->cookie_name_entry_, enabled);
-  gtk_widget_set_sensitive(self->cookie_content_entry_, enabled);
-  gtk_widget_set_sensitive(self->cookie_domain_entry_, enabled);
-  gtk_widget_set_sensitive(self->cookie_path_entry_, enabled);
-  gtk_widget_set_sensitive(self->cookie_send_for_entry_, enabled);
-  gtk_widget_set_sensitive(self->cookie_created_entry_, enabled);
-  if (self->cookie_expires_entry_)
-    gtk_widget_set_sensitive(self->cookie_expires_entry_, enabled);
-  else
-    gtk_widget_set_sensitive(self->cookie_expires_combobox_, enabled);
-}
-
-void SetDatabaseDetailsSensitivity(GtkChromeCookieView *self,
-                                   gboolean enabled) {
-  gtk_widget_set_sensitive(self->database_name_entry_, enabled);
-  gtk_widget_set_sensitive(self->database_description_entry_, enabled);
-  gtk_widget_set_sensitive(self->database_size_entry_, enabled);
-  gtk_widget_set_sensitive(self->database_last_modified_entry_, enabled);
-}
-
-void SetLocalStorageDetailsSensitivity(GtkChromeCookieView *self,
-                                       gboolean enabled) {
-  gtk_widget_set_sensitive(self->local_storage_origin_entry_, enabled);
-  gtk_widget_set_sensitive(self->local_storage_size_entry_, enabled);
-  gtk_widget_set_sensitive(self->local_storage_last_modified_entry_, enabled);
-}
-
-void SetAppCacheDetailsSensitivity(GtkChromeCookieView *self,
-                                   gboolean enabled) {
-  gtk_widget_set_sensitive(self->appcache_manifest_entry_, enabled);
-  gtk_widget_set_sensitive(self->appcache_size_entry_, enabled);
-  gtk_widget_set_sensitive(self->appcache_created_entry_, enabled);
-  gtk_widget_set_sensitive(self->appcache_last_accessed_entry_, enabled);
-}
-
-void SetIndexedDBDetailsSensitivity(GtkChromeCookieView *self,
-                                    gboolean enabled) {
-  gtk_widget_set_sensitive(self->indexed_db_origin_entry_, enabled);
-  gtk_widget_set_sensitive(self->indexed_db_size_entry_, enabled);
-  gtk_widget_set_sensitive(self->indexed_db_last_modified_entry_, enabled);
-}
-
-void SetLocalStorageItemSensitivity(GtkChromeCookieView* self,
-                                    gboolean enabled) {
-  gtk_widget_set_sensitive(self->local_storage_item_origin_entry_, enabled);
-  gtk_widget_set_sensitive(self->local_storage_item_key_entry_, enabled);
-  gtk_widget_set_sensitive(self->local_storage_item_value_entry_, enabled);
-}
-
-void SetDatabaseAccessedSensitivity(GtkChromeCookieView* self,
-                                    gboolean enabled) {
-  gtk_widget_set_sensitive(self->database_accessed_origin_entry_, enabled);
-  gtk_widget_set_sensitive(self->database_accessed_name_entry_, enabled);
-  gtk_widget_set_sensitive(self->database_accessed_description_entry_, enabled);
-  gtk_widget_set_sensitive(self->database_accessed_size_entry_, enabled);
-}
-
-void SetAppCacheCreatedSensitivity(GtkChromeCookieView* self,
-                                   gboolean enabled) {
-  gtk_widget_set_sensitive(self->appcache_created_manifest_entry_, enabled);
-}
-
-void ClearCookieDetails(GtkChromeCookieView *self) {
-  std::string no_cookie =
-      l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_NONESELECTED);
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_name_entry_),
-                     no_cookie.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_content_entry_),
-                     no_cookie.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_domain_entry_),
-                     no_cookie.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_path_entry_),
-                     no_cookie.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_created_entry_),
-                     no_cookie.c_str());
-  if (self->cookie_expires_entry_) {
-    gtk_entry_set_text(GTK_ENTRY(self->cookie_expires_entry_),
-                       no_cookie.c_str());
-  } else {
-    GtkListStore* store = self->cookie_expires_combobox_store_;
-    GtkTreeIter iter;
-    gtk_list_store_clear(store);
-
-    gtk_list_store_append(store, &iter);
-    gtk_list_store_set(store, &iter, 0, no_cookie.c_str(), -1);
-
-    gtk_combo_box_set_active(GTK_COMBO_BOX(self->cookie_expires_combobox_),
-                             0);
-  }
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_send_for_entry_),
-                     no_cookie.c_str());
-  SetCookieDetailsSensitivity(self, FALSE);
-}
-
-void UpdateVisibleDetailedInfo(GtkChromeCookieView *self, GtkWidget* table) {
-  SetCookieDetailsSensitivity(self, table == self->cookie_details_table_);
-  SetDatabaseDetailsSensitivity(self, table == self->database_details_table_);
-  SetLocalStorageDetailsSensitivity(self,
-      table == self->local_storage_details_table_);
-  SetAppCacheDetailsSensitivity(self, table == self->appcache_details_table_);
-  SetIndexedDBDetailsSensitivity(self,
-      table == self->indexed_db_details_table_);
-  SetLocalStorageItemSensitivity(self,
-      table == self->local_storage_item_table_);
-  SetDatabaseAccessedSensitivity(self,
-      table == self->database_accessed_table_);
-  SetAppCacheCreatedSensitivity(self,
-      table == self->appcache_created_table_);
-
-  // Display everything
-  gtk_widget_show(self->table_box_);
-  gtk_widget_show_all(table);
-  // Hide everything that isn't us.
-  if (table != self->cookie_details_table_)
-    gtk_widget_hide(self->cookie_details_table_);
-  if (table != self->database_details_table_)
-    gtk_widget_hide(self->database_details_table_);
-  if (table != self->local_storage_details_table_)
-    gtk_widget_hide(self->local_storage_details_table_);
-  if (table != self->appcache_details_table_)
-    gtk_widget_hide(self->appcache_details_table_);
-  if (table != self->indexed_db_details_table_)
-    gtk_widget_hide(self->indexed_db_details_table_);
-  if (table != self->local_storage_item_table_)
-    gtk_widget_hide(self->local_storage_item_table_);
-  if (table != self->database_accessed_table_)
-    gtk_widget_hide(self->database_accessed_table_);
-  if (table != self->appcache_created_table_)
-    gtk_widget_hide(self->appcache_created_table_);
-}
-
-}  // namespace
-
-G_DEFINE_TYPE(GtkChromeCookieView, gtk_chrome_cookie_view, GTK_TYPE_FRAME)
-
-static void gtk_chrome_cookie_view_class_init(GtkChromeCookieViewClass *klass) {
-}
-
-static void gtk_chrome_cookie_view_init(GtkChromeCookieView *self) {
-}
-
-void BuildWidgets(GtkChromeCookieView *self, gboolean editable_expiration) {
-  self->table_box_ = gtk_vbox_new(FALSE, 0);
-  gtk_widget_set_no_show_all(self->table_box_, TRUE);
-
-  // Cookie details.
-  self->cookie_details_table_ = gtk_table_new(7, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->cookie_details_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->cookie_details_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  int row = 0;
-  self->first_label_ = InitDetailRow(row++, IDS_COOKIES_COOKIE_NAME_LABEL,
-                self->cookie_details_table_, &self->cookie_name_entry_);
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_CONTENT_LABEL,
-                self->cookie_details_table_, &self->cookie_content_entry_);
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
-                self->cookie_details_table_, &self->cookie_domain_entry_);
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_PATH_LABEL,
-                self->cookie_details_table_, &self->cookie_path_entry_);
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_SENDFOR_LABEL,
-                self->cookie_details_table_, &self->cookie_send_for_entry_);
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_CREATED_LABEL,
-                self->cookie_details_table_, &self->cookie_created_entry_);
-  if (editable_expiration) {
-    InitComboboxRow(row++, IDS_COOKIES_COOKIE_EXPIRES_LABEL,
-                    self->cookie_details_table_,
-                    &self->cookie_expires_combobox_,
-                    &self->cookie_expires_combobox_store_);
-  } else {
-    InitDetailRow(row++, IDS_COOKIES_COOKIE_EXPIRES_LABEL,
-                  self->cookie_details_table_, &self->cookie_expires_entry_);
-  }
-
-  // Database details.
-  self->database_details_table_ = gtk_table_new(4, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->database_details_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->database_details_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_NAME_LABEL,
-                self->database_details_table_, &self->database_name_entry_);
-  InitDetailRow(row++, IDS_COOKIES_WEB_DATABASE_DESCRIPTION_LABEL,
-                self->database_details_table_,
-                &self->database_description_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
-                self->database_details_table_, &self->database_size_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
-                self->database_details_table_,
-                &self->database_last_modified_entry_);
-
-  // Local storage details.
-  self->local_storage_details_table_ = gtk_table_new(3, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->local_storage_details_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->local_storage_details_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  row = 0;
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL,
-                self->local_storage_details_table_,
-                &self->local_storage_origin_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
-                self->local_storage_details_table_,
-                &self->local_storage_size_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
-                self->local_storage_details_table_,
-                &self->local_storage_last_modified_entry_);
-
-  // AppCache details.
-  self->appcache_details_table_ = gtk_table_new(4, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->appcache_details_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->appcache_details_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  row = 0;
-  InitDetailRow(row++, IDS_COOKIES_APPLICATION_CACHE_MANIFEST_LABEL,
-                self->appcache_details_table_,
-                &self->appcache_manifest_entry_);
-  InitDetailRow(row++, IDS_COOKIES_SIZE_LABEL,
-                self->appcache_details_table_, &self->appcache_size_entry_);
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_CREATED_LABEL,
-                self->appcache_details_table_, &self->appcache_created_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LAST_ACCESSED_LABEL,
-                self->appcache_details_table_,
-                &self->appcache_last_accessed_entry_);
-
-  // IndexedDB details.
-  self->indexed_db_details_table_ = gtk_table_new(4, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->indexed_db_details_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->indexed_db_details_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  row = 0;
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL,
-                self->indexed_db_details_table_,
-                &self->indexed_db_origin_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
-                self->indexed_db_details_table_, &self->indexed_db_size_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
-                self->indexed_db_details_table_,
-                &self->indexed_db_last_modified_entry_);
-
-  // Local storage item.
-  self->local_storage_item_table_ = gtk_table_new(3, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->local_storage_item_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->local_storage_item_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  row = 0;
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
-                self->local_storage_item_table_,
-                &self->local_storage_item_origin_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_KEY_LABEL,
-                self->local_storage_item_table_,
-                &self->local_storage_item_key_entry_);
-  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_VALUE_LABEL,
-                self->local_storage_item_table_,
-                &self->local_storage_item_value_entry_);
-
-  // Database accessed prompt.
-  self->database_accessed_table_ = gtk_table_new(2, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->database_accessed_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->local_storage_item_table_), 0,
-                            gtk_util::kLabelSpacing);
-
-  row = 0;
-  InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
-                self->database_accessed_table_,
-                &self->database_accessed_origin_entry_);
-  InitDetailRow(row++, IDS_COOKIES_WEB_DATABASE_NAME,
-                self->database_accessed_table_,
-                &self->database_accessed_name_entry_);
-  InitDetailRow(row++, IDS_COOKIES_WEB_DATABASE_DESCRIPTION_LABEL,
-                self->database_accessed_table_,
-                &self->database_accessed_description_entry_);
-  InitDetailRow(row++, IDS_COOKIES_SIZE_LABEL,
-                self->database_accessed_table_,
-                &self->database_accessed_size_entry_);
-
-  // AppCache created prompt.
-  self->appcache_created_table_ = gtk_table_new(1, 2, FALSE);
-  gtk_container_add(GTK_CONTAINER(self->table_box_),
-                    self->appcache_created_table_);
-  gtk_table_set_col_spacing(GTK_TABLE(self->appcache_created_table_), 0,
-                            gtk_util::kLabelSpacing);
-  row = 0;
-  InitDetailRow(row++, IDS_COOKIES_APPLICATION_CACHE_MANIFEST_LABEL,
-                self->appcache_created_table_,
-                &self->appcache_created_manifest_entry_);
-
-  gtk_frame_set_shadow_type(GTK_FRAME(self), GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(self), self->table_box_);
-}
-
-GtkWidget* gtk_chrome_cookie_view_new(gboolean editable_expiration) {
-  GtkChromeCookieView* view = GTK_CHROME_COOKIE_VIEW(
-      g_object_new(GTK_TYPE_CHROME_COOKIE_VIEW, NULL));
-  BuildWidgets(view, editable_expiration);
-  g_signal_connect(view, "realize", G_CALLBACK(InitStyles), NULL);
-  return GTK_WIDGET(view);
-}
-
-void gtk_chrome_cookie_view_clear(GtkChromeCookieView* self) {
-  UpdateVisibleDetailedInfo(self, self->cookie_details_table_);
-  ClearCookieDetails(self);
-}
-
-// Switches the display to showing the passed in cookie.
-void gtk_chrome_cookie_view_display_cookie(
-    GtkChromeCookieView* self,
-    const std::string& domain,
-    const net::CookieMonster::CanonicalCookie& cookie) {
-  UpdateVisibleDetailedInfo(self, self->cookie_details_table_);
-
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_name_entry_),
-                     cookie.Name().c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_content_entry_),
-                     cookie.Value().c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_domain_entry_),
-                     domain.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_path_entry_),
-                     cookie.Path().c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->cookie_created_entry_),
-                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                         cookie.CreationDate())).c_str());
-
-  std::string expire_text = cookie.DoesExpire() ?
-      UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate())) :
-      l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION);
-
-  if (self->cookie_expires_entry_) {
-    gtk_entry_set_text(GTK_ENTRY(self->cookie_expires_entry_),
-                       expire_text.c_str());
-  } else {
-    GtkListStore* store = self->cookie_expires_combobox_store_;
-    GtkTreeIter iter;
-    gtk_list_store_clear(store);
-
-    if (cookie.DoesExpire()) {
-      gtk_list_store_append(store, &iter);
-      gtk_list_store_set(store, &iter, 0, expire_text.c_str(), -1);
-    }
-
-    gtk_list_store_append(store, &iter);
-    gtk_list_store_set(
-        store, &iter, 0,
-        l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION).c_str(),
-        -1);
-
-    gtk_combo_box_set_active(GTK_COMBO_BOX(self->cookie_expires_combobox_),
-                             0);
-  }
-
-  gtk_entry_set_text(
-      GTK_ENTRY(self->cookie_send_for_entry_),
-      l10n_util::GetStringUTF8(cookie.IsSecure() ?
-                               IDS_COOKIES_COOKIE_SENDFOR_SECURE :
-                               IDS_COOKIES_COOKIE_SENDFOR_ANY).c_str());
-  SetCookieDetailsSensitivity(self, TRUE);
-}
-
-void gtk_chrome_cookie_view_display_cookie_string(
-    GtkChromeCookieView* self,
-    const GURL& url,
-    const std::string& cookie_line) {
-  net::CookieMonster::ParsedCookie pc(cookie_line);
-  net::CookieMonster::CanonicalCookie cookie(url, pc);
-
-  gtk_chrome_cookie_view_display_cookie(
-      self,
-      pc.HasDomain() ? pc.Domain() : url.host(),
-      cookie);
-}
-
-// Switches the display to showing the passed in database.
-void gtk_chrome_cookie_view_display_database(
-    GtkChromeCookieView* self,
-    const BrowsingDataDatabaseHelper::DatabaseInfo& database_info) {
-  UpdateVisibleDetailedInfo(self, self->database_details_table_);
-
-  gtk_entry_set_text(
-      GTK_ENTRY(self->database_name_entry_),
-      database_info.database_name.empty() ?
-          l10n_util::GetStringUTF8(
-              IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME).c_str() :
-          database_info.database_name.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->database_description_entry_),
-                     database_info.description.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->database_size_entry_),
-                     UTF16ToUTF8(FormatBytes(
-                         database_info.size,
-                         GetByteDisplayUnits(database_info.size),
-                         true)).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->database_last_modified_entry_),
-                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                         database_info.last_modified)).c_str());
-  SetDatabaseDetailsSensitivity(self, TRUE);
-}
-
-// Switches the display to showing the passed in local storage data.
-void gtk_chrome_cookie_view_display_local_storage(
-    GtkChromeCookieView* self,
-    const BrowsingDataLocalStorageHelper::LocalStorageInfo&
-    local_storage_info) {
-  UpdateVisibleDetailedInfo(self, self->local_storage_details_table_);
-
-  gtk_entry_set_text(GTK_ENTRY(self->local_storage_origin_entry_),
-                     local_storage_info.origin.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->local_storage_size_entry_),
-                     UTF16ToUTF8(FormatBytes(
-                         local_storage_info.size,
-                         GetByteDisplayUnits(local_storage_info.size),
-                         true)).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->local_storage_last_modified_entry_),
-                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                         local_storage_info.last_modified)).c_str());
-  SetLocalStorageDetailsSensitivity(self, TRUE);
-}
-
-// Switches the display to showing the passed in app cache.
-void gtk_chrome_cookie_view_display_app_cache(
-    GtkChromeCookieView* self,
-    const appcache::AppCacheInfo& info) {
-  UpdateVisibleDetailedInfo(self, self->appcache_details_table_);
-
-  gtk_entry_set_text(GTK_ENTRY(self->appcache_manifest_entry_),
-                     info.manifest_url.spec().c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->appcache_size_entry_),
-                     UTF16ToUTF8(FormatBytes(
-                         info.size,
-                         GetByteDisplayUnits(info.size),
-                         true)).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->appcache_created_entry_),
-                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                         info.creation_time)).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->appcache_last_accessed_entry_),
-                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                         info.last_access_time)).c_str());
-  SetAppCacheDetailsSensitivity(self, TRUE);
-}
-
-// Switches the display to showing the passed in IndexedDB data.
-void gtk_chrome_cookie_view_display_indexed_db(
-    GtkChromeCookieView* self,
-    const BrowsingDataIndexedDBHelper::IndexedDBInfo& indexed_db_info) {
-  UpdateVisibleDetailedInfo(self, self->indexed_db_details_table_);
-
-  gtk_entry_set_text(GTK_ENTRY(self->indexed_db_origin_entry_),
-                     indexed_db_info.origin.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->indexed_db_size_entry_),
-                     UTF16ToUTF8(FormatBytes(
-                         indexed_db_info.size,
-                         GetByteDisplayUnits(indexed_db_info.size),
-                         true)).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->indexed_db_last_modified_entry_),
-                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                         indexed_db_info.last_modified)).c_str());
-  SetLocalStorageDetailsSensitivity(self, TRUE);
-}
-
-void gtk_chrome_cookie_view_display_local_storage_item(
-    GtkChromeCookieView* self,
-    const std::string& host,
-    const string16& key,
-    const string16& value) {
-  UpdateVisibleDetailedInfo(self, self->local_storage_item_table_);
-
-  gtk_entry_set_text(GTK_ENTRY(self->local_storage_item_origin_entry_),
-                     host.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->local_storage_item_key_entry_),
-                     UTF16ToUTF8(key).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->local_storage_item_value_entry_),
-                     UTF16ToUTF8(value).c_str());
-  SetLocalStorageItemSensitivity(self, TRUE);
-}
-
-void gtk_chrome_cookie_view_display_database_accessed(
-    GtkChromeCookieView* self,
-    const std::string& host,
-    const string16& database_name,
-    const string16& display_name,
-    unsigned long estimated_size) {
-  UpdateVisibleDetailedInfo(self, self->database_accessed_table_);
-
-  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_origin_entry_),
-                     host.c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_name_entry_),
-                     UTF16ToUTF8(database_name).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_description_entry_),
-                     UTF16ToUTF8(display_name).c_str());
-  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_size_entry_),
-                     UTF16ToUTF8(FormatBytes(
-                         estimated_size,
-                         GetByteDisplayUnits(estimated_size),
-                         true)).c_str());
-  SetDatabaseAccessedSensitivity(self, TRUE);
-}
-
-void gtk_chrome_cookie_view_display_appcache_created(
-    GtkChromeCookieView* self,
-    const GURL& manifest_url) {
-  UpdateVisibleDetailedInfo(self, self->appcache_created_table_);
-  gtk_entry_set_text(GTK_ENTRY(self->appcache_created_manifest_entry_),
-                     manifest_url.spec().c_str());
-  SetAppCacheCreatedSensitivity(self, TRUE);
-}
-
-bool gtk_chrome_cookie_view_session_expires(GtkChromeCookieView* self) {
-  if (self->cookie_expires_entry_)
-    return false;
-
-  GtkListStore* store = self->cookie_expires_combobox_store_;
-  int store_size = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
-  if (store_size == 1)
-    return false;
-
-  DCHECK_EQ(2, store_size);
-
-  int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(
-      self->cookie_expires_combobox_));
-  return selected == 1;
-}
diff --git a/chrome/browser/gtk/gtk_chrome_cookie_view.h b/chrome/browser/gtk/gtk_chrome_cookie_view.h
deleted file mode 100644
index 93bc96c..0000000
--- a/chrome/browser/gtk/gtk_chrome_cookie_view.h
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_CHROME_COOKIE_VIEW_H_
-#define CHROME_BROWSER_GTK_GTK_CHROME_COOKIE_VIEW_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "chrome/browser/browsing_data_appcache_helper.h"
-#include "chrome/browser/browsing_data_database_helper.h"
-#include "chrome/browser/browsing_data_indexed_db_helper.h"
-#include "chrome/browser/browsing_data_local_storage_helper.h"
-#include "net/base/cookie_monster.h"
-
-class GURL;
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CHROME_COOKIE_VIEW gtk_chrome_cookie_view_get_type()
-
-#define GTK_CHROME_COOKIE_VIEW(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), \
-  GTK_TYPE_CHROME_COOKIE_VIEW, GtkChromeCookieView))
-
-#define GTK_CHROME_COOKIE_VIEW_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), \
-  GTK_TYPE_CHROME_COOKIE_VIEW, GtkChromeCookieViewClass))
-
-#define GTK_IS_CHROME_COOKIE_VIEW(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
-  GTK_TYPE_CHROME_COOKIE_VIEW))
-
-#define GTK_IS_CHROME_COOKIE_VIEW_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), \
-  GTK_TYPE_CHROME_COOKIE_VIEW))
-
-#define GTK_CHROME_COOKIE_VIEW_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS((obj), \
-  GTK_TYPE_CHROME_COOKIE_VIEW, GtkChromeCookieViewClass))
-
-// TODO(erg): Refactor the following class. It's continuously grown as more
-// things have been added to it and should probably become a general key/value
-// table. The problem is that any implementation for that would be much more
-// complicated and would require changing a whole lot of code.
-typedef struct {
-  GtkFrame parent;
-
-  // All public for testing since I don't think there's a "friend" mechanism in
-  // gobject.
-
-  GtkWidget* table_box_;
-
-  // A label we keep around so we can access its GtkStyle* once it is realized.
-  GtkWidget* first_label_;
-
-  // The cookie details widgets.
-  GtkWidget* cookie_details_table_;
-  GtkWidget* cookie_name_entry_;
-  GtkWidget* cookie_content_entry_;
-  GtkWidget* cookie_domain_entry_;
-  GtkWidget* cookie_path_entry_;
-  GtkWidget* cookie_send_for_entry_;
-  GtkWidget* cookie_created_entry_;
-
-  // Note: These two widgets are mutually exclusive based on what
-  // |editable_expiration| was when the cookie view was created. One of these
-  // variables will be NULL.
-  GtkWidget* cookie_expires_entry_;
-  GtkWidget* cookie_expires_combobox_;
-
-  GtkListStore* cookie_expires_combobox_store_;
-
-  // The database details widgets.
-  GtkWidget* database_details_table_;
-  GtkWidget* database_name_entry_;
-  GtkWidget* database_description_entry_;
-  GtkWidget* database_size_entry_;
-  GtkWidget* database_last_modified_entry_;
-
-  // The local storage details widgets.
-  GtkWidget* local_storage_details_table_;
-  GtkWidget* local_storage_origin_entry_;
-  GtkWidget* local_storage_size_entry_;
-  GtkWidget* local_storage_last_modified_entry_;
-
-  // The appcache details widgets.
-  GtkWidget* appcache_details_table_;
-  GtkWidget* appcache_manifest_entry_;
-  GtkWidget* appcache_size_entry_;
-  GtkWidget* appcache_created_entry_;
-  GtkWidget* appcache_last_accessed_entry_;
-
-  // The IndexedDB details widgets.
-  GtkWidget* indexed_db_details_table_;
-  GtkWidget* indexed_db_origin_entry_;
-  GtkWidget* indexed_db_size_entry_;
-  GtkWidget* indexed_db_last_modified_entry_;
-
-  // The local storage item widgets.
-  GtkWidget* local_storage_item_table_;
-  GtkWidget* local_storage_item_origin_entry_;
-  GtkWidget* local_storage_item_key_entry_;
-  GtkWidget* local_storage_item_value_entry_;
-
-  // The database accessed widgets.
-  GtkWidget* database_accessed_table_;
-  GtkWidget* database_accessed_origin_entry_;
-  GtkWidget* database_accessed_name_entry_;
-  GtkWidget* database_accessed_description_entry_;
-  GtkWidget* database_accessed_size_entry_;
-
-  // The appcache created widgets.
-  GtkWidget* appcache_created_table_;
-  GtkWidget* appcache_created_manifest_entry_;
-} GtkChromeCookieView;
-
-typedef struct {
-  GtkFrameClass parent_class;
-} GtkChromeCookieViewClass;
-
-GType gtk_chrome_cookie_view_get_type();
-
-// Builds a new cookie view.
-GtkWidget* gtk_chrome_cookie_view_new(gboolean editable_expiration);
-
-// Clears the cookie view.
-void gtk_chrome_cookie_view_clear(GtkChromeCookieView* widget);
-
-// NOTE: The G_END_DECLS ends here instead of at the end of the document
-// because we want to define some methods on GtkChromeCookieView that take C++
-// objects.
-G_END_DECLS
-// NOTE: ^^^^^^^^^^^^^^^^^^^^^^^
-
-// Switches the display to showing the passed in cookie.
-void gtk_chrome_cookie_view_display_cookie(
-    GtkChromeCookieView* widget,
-    const std::string& domain,
-    const net::CookieMonster::CanonicalCookie& cookie);
-
-// Looks up the cookie_line in CookieMonster and displays that.
-void gtk_chrome_cookie_view_display_cookie_string(
-    GtkChromeCookieView* widget,
-    const GURL& url,
-    const std::string& cookie_line);
-
-// Switches the display to showing the passed in database.
-void gtk_chrome_cookie_view_display_database(
-    GtkChromeCookieView* widget,
-    const BrowsingDataDatabaseHelper::DatabaseInfo& database_info);
-
-// Switches the display to showing the passed in local storage data.
-void gtk_chrome_cookie_view_display_local_storage(
-    GtkChromeCookieView* widget,
-    const BrowsingDataLocalStorageHelper::LocalStorageInfo&
-    local_storage_info);
-
-// Switches the display to showing the passed in app cache.
-void gtk_chrome_cookie_view_display_app_cache(
-    GtkChromeCookieView* widget,
-    const appcache::AppCacheInfo& info);
-
-// Switches the display to showing the passed in IndexedDB data.
-void gtk_chrome_cookie_view_display_indexed_db(
-    GtkChromeCookieView* widget,
-    const BrowsingDataIndexedDBHelper::IndexedDBInfo& info);
-
-// Switches the display to an individual storage item.
-void gtk_chrome_cookie_view_display_local_storage_item(
-    GtkChromeCookieView* widget,
-    const std::string& host,
-    const string16& key,
-    const string16& value);
-
-void gtk_chrome_cookie_view_display_database_accessed(
-    GtkChromeCookieView* self,
-    const std::string& host,
-    const string16& database_name,
-    const string16& display_name,
-    unsigned long estimated_size);
-
-void gtk_chrome_cookie_view_display_appcache_created(
-    GtkChromeCookieView* self,
-    const GURL& manifest_url);
-
-// If |editable_expiration| was true at construction time, returns the value of
-// the combo box. Otherwise, returns false.
-bool gtk_chrome_cookie_view_session_expires(GtkChromeCookieView* self);
-
-#endif  // CHROME_BROWSER_GTK_GTK_CHROME_COOKIE_VIEW_H_
diff --git a/chrome/browser/gtk/gtk_chrome_link_button.cc b/chrome/browser/gtk/gtk_chrome_link_button.cc
deleted file mode 100644
index 0da375f..0000000
--- a/chrome/browser/gtk/gtk_chrome_link_button.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-
-#include <stdlib.h>
-
-#include "chrome/browser/gtk/gtk_util.h"
-#include "gfx/gtk_util.h"
-
-static const gchar* kLinkMarkup = "<u><span color=\"%s\">%s</span></u>";
-
-namespace {
-
-// Set the GTK style on our custom link button. We don't want any border around
-// the link text.
-void SetLinkButtonStyle() {
-  static bool style_was_set = false;
-
-  if (style_was_set)
-    return;
-  style_was_set = true;
-
-  gtk_rc_parse_string(
-      "style \"chrome-link-button\" {"
-      "  GtkButton::inner-border = {0, 0, 0, 0}"
-      "  GtkButton::child-displacement-x = 0"
-      "  GtkButton::child-displacement-y = 0"
-      "  xthickness = 0"
-      "  ythickness = 0"
-      "}"
-      "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\"");
-}
-
-static void gtk_chrome_link_button_destroy_text_resources(
-    GtkChromeLinkButton* button) {
-  g_free(button->native_markup);
-  button->native_markup = NULL;
-  g_free(button->normal_markup);
-  button->normal_markup = NULL;
-  g_free(button->pressed_markup);
-  button->pressed_markup = NULL;
-
-  g_free(button->text);
-  button->text = NULL;
-}
-
-}  // namespace
-
-G_BEGIN_DECLS
-G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)
-
-static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
-  // If we were called before we were realized, abort. We'll be called for
-  // real when |button| is realized.
-  if (!GTK_WIDGET_REALIZED(button))
-    return;
-
-  g_free(button->native_markup);
-  button->native_markup = NULL;
-  g_free(button->normal_markup);
-  button->normal_markup = NULL;
-  g_free(button->pressed_markup);
-  button->pressed_markup = NULL;
-
-  gchar* text = button->text;
-  gboolean uses_markup = button->uses_markup;
-
-  if (!uses_markup) {
-    button->normal_markup = g_markup_printf_escaped(kLinkMarkup,
-                                                    button->normal_color,
-                                                    text);
-    button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
-  } else {
-    button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color,
-                                            text);
-
-    button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text);
-  }
-
-  // Get the current GTK theme's link button text color.
-  GdkColor* native_color = NULL;
-  gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);
-
-  if (native_color) {
-    gchar color_spec[9];
-    snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257,
-             native_color->green / 257, native_color->blue / 257);
-    gdk_color_free(native_color);
-
-    if (!uses_markup) {
-      button->native_markup = g_markup_printf_escaped(kLinkMarkup,
-          color_spec, text);
-    } else {
-      button->native_markup = g_strdup_printf(kLinkMarkup, color_spec, text);
-    }
-  } else {
-    // If the theme doesn't have a link color, just use blue. This matches the
-    // default for GtkLinkButton.
-    button->native_markup = g_strdup(button->normal_markup);
-  }
-
-  gtk_label_set_markup(GTK_LABEL(button->label),
-      button->using_native_theme ? button->native_markup :
-      button->normal_markup);
-}
-
-static void gtk_chrome_link_button_style_changed(GtkChromeLinkButton* button) {
-  // Regenerate the link with the possibly new colors after the user has
-  // changed his GTK style.
-  gtk_chrome_link_button_set_text(button);
-
-  if (GTK_WIDGET_VISIBLE(button))
-    gtk_widget_queue_draw(GTK_WIDGET(button));
-}
-
-static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
-                                              GdkEventExpose* event) {
-  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
-  GtkWidget* label = button->label;
-
-  if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_normal) {
-    gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup);
-    button->is_normal = FALSE;
-  } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE &&
-             !button->is_normal) {
-    gtk_label_set_markup(GTK_LABEL(label),
-        button->using_native_theme ? button->native_markup :
-                                     button->normal_markup);
-    button->is_normal = TRUE;
-  }
-
-  // Draw the link inside the button.
-  gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);
-
-  // Draw the focus rectangle.
-  if (GTK_WIDGET_HAS_FOCUS(widget)) {
-    gtk_paint_focus(widget->style, widget->window,
-                    static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
-                    &event->area, widget, NULL,
-                    widget->allocation.x, widget->allocation.y,
-                    widget->allocation.width, widget->allocation.height);
-  }
-
-  return TRUE;
-}
-
-static void gtk_chrome_link_button_enter(GtkButton* button) {
-  GtkWidget* widget = GTK_WIDGET(button);
-  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
-  gdk_window_set_cursor(widget->window, link_button->hand_cursor);
-}
-
-static void gtk_chrome_link_button_leave(GtkButton* button) {
-  GtkWidget* widget = GTK_WIDGET(button);
-  gdk_window_set_cursor(widget->window, NULL);
-}
-
-static void gtk_chrome_link_button_destroy(GtkObject* object) {
-  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
-
-  gtk_chrome_link_button_destroy_text_resources(button);
-
-  button->hand_cursor = NULL;
-
-  GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
-}
-
-static void gtk_chrome_link_button_class_init(
-    GtkChromeLinkButtonClass* link_button_class) {
-  GtkWidgetClass* widget_class =
-      reinterpret_cast<GtkWidgetClass*>(link_button_class);
-  GtkButtonClass* button_class =
-      reinterpret_cast<GtkButtonClass*>(link_button_class);
-  GtkObjectClass* object_class =
-      reinterpret_cast<GtkObjectClass*>(link_button_class);
-  widget_class->expose_event = &gtk_chrome_link_button_expose;
-  button_class->enter = &gtk_chrome_link_button_enter;
-  button_class->leave = &gtk_chrome_link_button_leave;
-  object_class->destroy = &gtk_chrome_link_button_destroy;
-}
-
-static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
-  SetLinkButtonStyle();
-
-  // We put a label in a button so we can connect to the click event. We don't
-  // let the button draw itself; catch all expose events to the button and pass
-  // them through to the label.
-  button->label = gtk_label_new(NULL);
-  button->normal_markup = NULL;
-  button->pressed_markup = NULL;
-  button->is_normal = TRUE;
-  strncpy(button->normal_color, "blue", 9);
-  button->native_markup = NULL;
-  button->using_native_theme = TRUE;
-  button->hand_cursor = gfx::GetCursor(GDK_HAND2);
-  button->text = NULL;
-
-  gtk_container_add(GTK_CONTAINER(button), button->label);
-  gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
-  g_signal_connect(button, "realize",
-                   G_CALLBACK(gtk_chrome_link_button_set_text), NULL);
-  g_signal_connect(button, "style-set",
-                   G_CALLBACK(gtk_chrome_link_button_style_changed), NULL);
-}
-
-GtkWidget* gtk_chrome_link_button_new(const char* text) {
-  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
-  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(text);
-  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;
-
-  return lb;
-}
-
-GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
-  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
-  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(markup);
-  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;
-
-  return lb;
-}
-
-void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
-                                              gboolean use_gtk) {
-  if (use_gtk != button->using_native_theme) {
-    button->using_native_theme = use_gtk;
-    if (GTK_WIDGET_VISIBLE(button))
-      gtk_widget_queue_draw(GTK_WIDGET(button));
-  }
-}
-
-void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
-                                      const char* text) {
-  g_free(button->text);
-  button->text = g_strdup(text);
-
-  gtk_chrome_link_button_set_text(button);
-
-  if (GTK_WIDGET_VISIBLE(button))
-    gtk_widget_queue_draw(GTK_WIDGET(button));
-}
-
-void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
-                                             const GdkColor* color) {
-  if (color) {
-    snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257,
-             color->green / 257, color->blue / 257);
-  } else {
-    strncpy(button->normal_color, "blue", 9);
-  }
-
-  gtk_chrome_link_button_set_text(button);
-
-  if (GTK_WIDGET_VISIBLE(button))
-    gtk_widget_queue_draw(GTK_WIDGET(button));
-}
-
-G_END_DECLS
diff --git a/chrome/browser/gtk/gtk_chrome_link_button.h b/chrome/browser/gtk/gtk_chrome_link_button.h
deleted file mode 100644
index 4cde366..0000000
--- a/chrome/browser/gtk/gtk_chrome_link_button.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Creates a link button that shows |text| in blue and underlined. The cursor
-// changes to a hand when over the link.  This is like the GTK LinkButton, but
-// it doesn't call the global URI link handler, etc.  It is a button subclass,
-// so you can just handle the clicked signal.
-
-#ifndef CHROME_BROWSER_GTK_GTK_CHROME_LINK_BUTTON_H_
-#define CHROME_BROWSER_GTK_GTK_CHROME_LINK_BUTTON_H_
-#pragma once
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CHROME_LINK_BUTTON        (gtk_chrome_link_button_get_type ())
-#define GTK_CHROME_LINK_BUTTON(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), \
-                                            GTK_TYPE_CHROME_LINK_BUTTON, \
-                                            GtkChromeLinkButton))
-#define GTK_CHROME_LINK_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
-                                             GTK_TYPE_CHROME_LINK_BUTTON, \
-                                             GtkChromeLinkButtonClass))
-#define GTK_IS_CHROME_LINK_BUTTON(obj)                           \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHROME_LINK_BUTTON))
-#define GTK_IS_CHROME_LINK_BUTTON_CLASS(klass)                   \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHROME_LINK_BUTTON))
-#define GTK_CHROME_LINK_BUTTON_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHROME_LINK_BUTTON, \
-                             GtkChromeLinkButton))
-
-typedef struct _GtkChromeLinkButton        GtkChromeLinkButton;
-typedef struct _GtkChromeLinkButtonClass   GtkChromeLinkButtonClass;
-
-struct _GtkChromeLinkButton {
-  GtkButton button;
-  GtkWidget* label;
-  gchar* normal_markup;
-  gchar* pressed_markup;
-  gboolean is_normal;
-  gchar normal_color[9];
-  gchar* native_markup;
-  gboolean using_native_theme;
-  GdkCursor* hand_cursor;
-  gchar* text;
-  gboolean uses_markup;
-};
-
-struct _GtkChromeLinkButtonClass {
-  GtkButtonClass parent_class;
-};
-
-// Make a link button with display text |text|.
-GtkWidget* gtk_chrome_link_button_new(const char* text);
-
-// As above, but don't escape markup in the text.
-GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup);
-
-// Set whether the link button draws natively (using "link-color"). The default
-// is TRUE.
-void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
-                                              gboolean use_gtk);
-
-// Set the label text of the link.
-void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
-                                      const char* text);
-
-// Set the color when the link is in a normal state (i.e. not pressed).
-// If not set, or called NULL |color|, the color will be blue.
-void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
-                                             const GdkColor* color);
-
-GType gtk_chrome_link_button_get_type();
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_CHROME_LINK_BUTTON_H_
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc
deleted file mode 100644
index 3ce83d0..0000000
--- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
-
-#include <gtk/gtk.h>
-#include <algorithm>
-
-namespace {
-
-enum {
-  PROP_0,
-  PROP_HIDE_CHILD_DIRECTLY
-};
-
-struct SizeAllocateData {
-  GtkChromeShrinkableHBox* box;
-  GtkAllocation* allocation;
-  GtkTextDirection direction;
-  bool homogeneous;
-  int border_width;
-
-  // Maximum child width when |homogeneous| is TRUE.
-  int homogeneous_child_width;
-};
-
-void CountVisibleChildren(GtkWidget* child, gpointer userdata) {
-  if (GTK_WIDGET_VISIBLE(child))
-    ++(*reinterpret_cast<int*>(userdata));
-}
-
-void SumChildrenWidthRequisition(GtkWidget* child, gpointer userdata) {
-  if (GTK_WIDGET_VISIBLE(child)) {
-    GtkRequisition req;
-    gtk_widget_get_child_requisition(child, &req);
-    (*reinterpret_cast<int*>(userdata)) += std::max(req.width, 0);
-  }
-}
-
-void ShowInvisibleChildren(GtkWidget* child, gpointer userdata) {
-  if (!GTK_WIDGET_VISIBLE(child)) {
-    gtk_widget_show(child);
-    ++(*reinterpret_cast<int*>(userdata));
-  }
-}
-
-void ChildSizeAllocate(GtkWidget* child, gpointer userdata) {
-  if (!GTK_WIDGET_VISIBLE(child))
-    return;
-
-  SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata);
-  GtkAllocation child_allocation = child->allocation;
-
-  if (data->homogeneous) {
-    // Make sure the child is not overlapped with others' boundary.
-    if (child_allocation.width > data->homogeneous_child_width) {
-      child_allocation.x +=
-          (child_allocation.width - data->homogeneous_child_width) / 2;
-      child_allocation.width = data->homogeneous_child_width;
-    }
-  } else {
-    guint padding;
-    GtkPackType pack_type;
-    gtk_box_query_child_packing(GTK_BOX(data->box), child, NULL, NULL,
-                                &padding, &pack_type);
-
-    if ((data->direction == GTK_TEXT_DIR_RTL && pack_type == GTK_PACK_START) ||
-        (data->direction != GTK_TEXT_DIR_RTL && pack_type == GTK_PACK_END)) {
-      // All children are right aligned, so make sure the child won't overflow
-      // its parent's left edge.
-      int overflow = (data->allocation->x + data->border_width + padding -
-                      child_allocation.x);
-      if (overflow > 0) {
-        child_allocation.width -= overflow;
-        child_allocation.x += overflow;
-      }
-    } else {
-      // All children are left aligned, so make sure the child won't overflow
-      // its parent's right edge.
-      int overflow = (child_allocation.x + child_allocation.width + padding -
-          (data->allocation->x + data->allocation->width - data->border_width));
-      if (overflow > 0)
-        child_allocation.width -= overflow;
-    }
-  }
-
-  if (child_allocation.width != child->allocation.width) {
-    if (data->box->hide_child_directly || child_allocation.width <= 1)
-      gtk_widget_hide(child);
-    else
-      gtk_widget_size_allocate(child, &child_allocation);
-  }
-}
-
-}  // namespace
-
-G_BEGIN_DECLS
-
-static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
-                                             guint prop_id,
-                                             const GValue* value,
-                                             GParamSpec* pspec);
-static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
-                                             guint prop_id,
-                                             GValue* value,
-                                             GParamSpec* pspec);
-static void gtk_chrome_shrinkable_hbox_size_allocate(GtkWidget* widget,
-                                              GtkAllocation* allocation);
-
-G_DEFINE_TYPE(GtkChromeShrinkableHBox, gtk_chrome_shrinkable_hbox,
-              GTK_TYPE_HBOX)
-
-static void gtk_chrome_shrinkable_hbox_class_init(
-    GtkChromeShrinkableHBoxClass *klass) {
-  GObjectClass* object_class = G_OBJECT_CLASS(klass);
-  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
-
-  object_class->set_property = gtk_chrome_shrinkable_hbox_set_property;
-  object_class->get_property = gtk_chrome_shrinkable_hbox_get_property;
-
-  widget_class->size_allocate = gtk_chrome_shrinkable_hbox_size_allocate;
-
-  g_object_class_install_property(object_class, PROP_HIDE_CHILD_DIRECTLY,
-      g_param_spec_boolean("hide-child-directly",
-                           "Hide child directly",
-                           "Whether the children should be hid directly, "
-                           "if there is no enough space in its parent",
-                           FALSE,
-                           static_cast<GParamFlags>(
-                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
-}
-
-static void gtk_chrome_shrinkable_hbox_init(GtkChromeShrinkableHBox* box) {
-  box->hide_child_directly = FALSE;
-  box->children_width_requisition = 0;
-}
-
-static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
-                                                    guint prop_id,
-                                                    const GValue* value,
-                                                    GParamSpec* pspec) {
-  GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(object);
-
-  switch (prop_id) {
-    case PROP_HIDE_CHILD_DIRECTLY:
-      gtk_chrome_shrinkable_hbox_set_hide_child_directly(
-          box, g_value_get_boolean(value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-      break;
-  }
-}
-
-static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
-                                                    guint prop_id,
-                                                    GValue* value,
-                                                    GParamSpec* pspec) {
-  GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(object);
-
-  switch (prop_id) {
-    case PROP_HIDE_CHILD_DIRECTLY:
-      g_value_set_boolean(value, box->hide_child_directly);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-      break;
-  }
-}
-
-static void gtk_chrome_shrinkable_hbox_size_allocate(
-    GtkWidget* widget, GtkAllocation* allocation) {
-  GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(widget);
-  gint children_width_requisition = 0;
-  gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
-                        &children_width_requisition);
-
-  // If we are allocated to more width or some children are removed or shrunk,
-  // then we need to show all invisible children before calling parent class's
-  // size_allocate method, because the new width may be enough to show those
-  // hidden children.
-  if (widget->allocation.width < allocation->width ||
-      box->children_width_requisition > children_width_requisition) {
-    gtk_container_foreach(GTK_CONTAINER(widget),
-                          reinterpret_cast<GtkCallback>(gtk_widget_show), NULL);
-
-    // If there were any invisible children, showing them will trigger another
-    // allocate. But we still need to go through the size allocate process
-    // in this iteration, otherwise before the next allocate iteration, the
-    // children may be redrawn on the screen with incorrect size allocation.
-  }
-
-  // Let the parent class do size allocation first. After that all children will
-  // be allocated with reasonable position and size according to their size
-  // request.
-  (GTK_WIDGET_CLASS(gtk_chrome_shrinkable_hbox_parent_class)->size_allocate)
-      (widget, allocation);
-
-  gint visible_children_count =
-      gtk_chrome_shrinkable_hbox_get_visible_child_count(
-          GTK_CHROME_SHRINKABLE_HBOX(widget));
-
-  box->children_width_requisition = 0;
-  if (visible_children_count == 0)
-    return;
-
-  SizeAllocateData data;
-  data.box = GTK_CHROME_SHRINKABLE_HBOX(widget);
-  data.allocation = allocation;
-  data.direction = gtk_widget_get_direction(widget);
-  data.homogeneous = gtk_box_get_homogeneous(GTK_BOX(widget));
-  data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
-  data.homogeneous_child_width =
-      (allocation->width - data.border_width * 2 -
-       (visible_children_count - 1) * gtk_box_get_spacing(GTK_BOX(widget))) /
-      visible_children_count;
-
-  // Shrink or hide children if necessary.
-  gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data);
-
-  // Record current width requisition of visible children, so we can know if
-  // it's necessary to show invisible children next time.
-  gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
-                        &box->children_width_requisition);
-}
-
-GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly,
-                                          gboolean homogeneous,
-                                          gint spacing) {
-  return GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_SHRINKABLE_HBOX,
-                                 "hide-child-directly", hide_child_directly,
-                                 "homogeneous", homogeneous,
-                                 "spacing", spacing,
-                                 NULL));
-}
-
-void gtk_chrome_shrinkable_hbox_set_hide_child_directly(
-    GtkChromeShrinkableHBox* box, gboolean hide_child_directly) {
-  g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
-
-  if (hide_child_directly != box->hide_child_directly) {
-    box->hide_child_directly = hide_child_directly;
-    g_object_notify(G_OBJECT(box), "hide-child-directly");
-    gtk_widget_queue_resize(GTK_WIDGET(box));
-  }
-}
-
-gboolean gtk_chrome_shrinkable_hbox_get_hide_child_directly(
-    GtkChromeShrinkableHBox* box) {
-  g_return_val_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box), FALSE);
-
-  return box->hide_child_directly;
-}
-
-void gtk_chrome_shrinkable_hbox_pack_start(GtkChromeShrinkableHBox* box,
-                                           GtkWidget* child,
-                                           guint padding) {
-  g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
-  g_return_if_fail(GTK_IS_WIDGET(child));
-
-  gtk_box_pack_start(GTK_BOX(box), child, FALSE, FALSE, 0);
-}
-
-void gtk_chrome_shrinkable_hbox_pack_end(GtkChromeShrinkableHBox* box,
-                                         GtkWidget* child,
-                                         guint padding) {
-  g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
-  g_return_if_fail(GTK_IS_WIDGET(child));
-
-  gtk_box_pack_end(GTK_BOX(box), child, FALSE, FALSE, 0);
-}
-
-gint gtk_chrome_shrinkable_hbox_get_visible_child_count(
-    GtkChromeShrinkableHBox* box) {
-  gint visible_children_count = 0;
-  gtk_container_foreach(GTK_CONTAINER(box), CountVisibleChildren,
-                        &visible_children_count);
-  return visible_children_count;
-}
-
-G_END_DECLS
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h
deleted file mode 100644
index 9793548..0000000
--- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_CHROME_SHRINKABLE_HBOX_H_
-#define CHROME_BROWSER_GTK_GTK_CHROME_SHRINKABLE_HBOX_H_
-#pragma once
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-// A specialized container derived from GtkHBox, which can shrink or hide its
-// children one by one to fit into its width.
-//
-// Limitations of this container:
-// - All children should have the same pack type, otherwise they may be
-//   overlapped with each other.
-// - All children must be packed with expand == false and fill == false,
-//   otherwise they may be overlapped with each other.
-// - The visibility of a child is adjusted automatically according to the
-//   container's width. The child may not show or hide itself.
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CHROME_SHRINKABLE_HBOX                                 \
-    (gtk_chrome_shrinkable_hbox_get_type())
-#define GTK_CHROME_SHRINKABLE_HBOX(obj)                                 \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CHROME_SHRINKABLE_HBOX, \
-                                GtkChromeShrinkableHBox))
-#define GTK_CHROME_SHRINKABLE_HBOX_CLASS(klass)                         \
-    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CHROME_SHRINKABLE_HBOX,  \
-                             GtkChromeShrinkableHBoxClass))
-#define GTK_IS_CHROME_SHRINKABLE_HBOX(obj)                              \
-    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHROME_SHRINKABLE_HBOX))
-#define GTK_IS_CHROME_SHRINKABLE_HBOX_CLASS(klass)                      \
-    (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHROME_SHRINKABLE_HBOX))
-#define GTK_CHROME_SHRINKABLE_HBOX_GET_CLASS(obj)                       \
-    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHROME_SHRINKABLE_HBOX,  \
-                               GtkChromeShrinkableHBoxClass))
-
-typedef struct _GtkChromeShrinkableHBox GtkChromeShrinkableHBox;
-typedef struct _GtkChromeShrinkableHBoxClass GtkChromeShrinkableHBoxClass;
-
-struct _GtkChromeShrinkableHBox {
-  // Parent class.
-  GtkHBox hbox;
-
-  gboolean hide_child_directly;
-
-  // Private
-  int children_width_requisition;
-};
-
-struct _GtkChromeShrinkableHBoxClass {
-  GtkHBoxClass parent_class;
-};
-
-GType gtk_chrome_shrinkable_hbox_get_type() G_GNUC_CONST;
-
-// Creates a new shrinkable hbox.
-// If |hide_child_directly| is true then its child widgets will be hid directly
-// if they are too wide to be fit into the hbox's width. Otherwise they will be
-// shrunk first before being hid completely.
-GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly,
-                                          gboolean homogeneous,
-                                          gint spacing);
-
-void gtk_chrome_shrinkable_hbox_set_hide_child_directly(
-    GtkChromeShrinkableHBox* box, gboolean hide_child_directly);
-
-gboolean gtk_chrome_shrinkable_hbox_get_hide_child_directly(
-    GtkChromeShrinkableHBox* box);
-
-void gtk_chrome_shrinkable_hbox_pack_start(GtkChromeShrinkableHBox* box,
-                                           GtkWidget* child,
-                                           guint padding);
-
-void gtk_chrome_shrinkable_hbox_pack_end(GtkChromeShrinkableHBox* box,
-                                         GtkWidget* child,
-                                         guint padding);
-
-gint gtk_chrome_shrinkable_hbox_get_visible_child_count(
-    GtkChromeShrinkableHBox* box);
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_CHROME_SHRINKABLE_HBOX_H_
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
deleted file mode 100644
index db9981f..0000000
--- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
-
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-const int kSpacing = 3;
-const int kBorderWidth = 5;
-
-}  // namespace
-
-class GtkChromeShrinkableHBoxTest : public testing::Test {
- protected:
-  GtkChromeShrinkableHBoxTest()
-      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
-        box_(gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, kSpacing)) {
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
-    gtk_window_set_default_size(GTK_WINDOW(window_), 200, 200);
-    gtk_container_add(GTK_CONTAINER(window_), box_);
-    gtk_container_set_border_width(GTK_CONTAINER(box_), kBorderWidth);
-  }
-
-  ~GtkChromeShrinkableHBoxTest() {
-    gtk_widget_destroy(window_);
-  }
-
-  // Add some children widgets with arbitrary width and padding.
-  void AddChildren(bool pack_start) {
-    static struct {
-      int width;
-      int padding;
-    } kChildrenData[] = {
-      { 60, 2 },
-      { 70, 3 },
-      { 80, 5 },
-      { 50, 7 },
-      { 40, 11 },
-      { 60, 0 },
-      { 0, 0 }
-    };
-
-    for (size_t i = 0; kChildrenData[i].width; ++i) {
-      GtkWidget* child = gtk_fixed_new();
-      gtk_widget_set_size_request(child, kChildrenData[i].width, -1);
-      if (pack_start) {
-        gtk_chrome_shrinkable_hbox_pack_start(
-            GTK_CHROME_SHRINKABLE_HBOX(box_), child, kChildrenData[i].padding);
-      } else {
-        gtk_chrome_shrinkable_hbox_pack_end(
-            GTK_CHROME_SHRINKABLE_HBOX(box_), child, kChildrenData[i].padding);
-      }
-    }
-  }
-
-  // Check if all children's size allocation are inside the |box_|'s boundary.
-  void Validate(bool pack_start) {
-    std::vector<ChildData> children_data;
-    gtk_container_foreach(GTK_CONTAINER(box_), CollectChildData,
-                          &children_data);
-
-    size_t children_count = children_data.size();
-    size_t visible_children_count = 0;
-    for (size_t i = 0; i < children_count; ++i) {
-      if (children_data[i].visible)
-        ++visible_children_count;
-    }
-
-    if (visible_children_count == 0)
-      return;
-
-    int border_width = gtk_container_get_border_width(GTK_CONTAINER(box_));
-    int x = box_->allocation.x + border_width;
-    int width = box_->allocation.width - border_width * 2;
-    int spacing = gtk_box_get_spacing(GTK_BOX(box_));
-    bool homogeneous = gtk_box_get_homogeneous(GTK_BOX(box_));
-
-    if (homogeneous) {
-      // If the |box_| is in homogeneous mode, then check if the visible
-      // children are not overlapped with each other.
-      int homogeneous_child_width =
-          (width - (visible_children_count - 1) * spacing) /
-          visible_children_count;
-
-      for (size_t i = 0; i < children_count; ++i) {
-        SCOPED_TRACE(testing::Message() << "Validate homogeneous child " << i
-                     << " visible: " << children_data[i].visible
-                     << " padding: " << children_data[i].padding
-                     << " x: " << children_data[i].x
-                     << " width: " << children_data[i].width);
-
-        if (children_data[i].visible)
-          ASSERT_LE(children_data[i].width, homogeneous_child_width);
-      }
-    } else {
-      // If the |box_| is not in homogeneous mode, then just check if all
-      // visible children are inside the |box_|'s boundary. And for those
-      // hidden children which are out of the boundary, they should only
-      // be hidden one by one from the end of the |box_|.
-      bool last_visible = pack_start;
-      bool visibility_changed = false;
-      for (size_t i = 0; i < children_count; ++i) {
-        SCOPED_TRACE(testing::Message() << "Validate child " << i
-                     << " visible: " << children_data[i].visible
-                     << " padding: " << children_data[i].padding
-                     << " x: " << children_data[i].x
-                     << " width: " << children_data[i].width);
-
-        if (last_visible != children_data[i].visible) {
-          ASSERT_FALSE(visibility_changed);
-          visibility_changed = true;
-          last_visible = children_data[i].visible;
-        }
-        if (children_data[i].visible) {
-          ASSERT_GE(children_data[i].x,
-                    x + children_data[i].padding);
-          ASSERT_LE(children_data[i].x + children_data[i].width,
-                    x + width - children_data[i].padding);
-        }
-      }
-    }
-  }
-
-  void Test(bool pack_start) {
-    gtk_widget_show_all(window_);
-    GtkAllocation allocation = { 0, 0, 0, 200 };
-    gtk_chrome_shrinkable_hbox_set_hide_child_directly(
-        GTK_CHROME_SHRINKABLE_HBOX(box_), FALSE);
-    for (int width = 500; width > kBorderWidth * 2; --width) {
-      SCOPED_TRACE(testing::Message() << "Shrink hide_child_directly = FALSE,"
-                   << " width = " << width);
-
-      allocation.width = width;
-      // Reducing the width may cause some children to be hidden, which will
-      // cause queue resize, so it's necessary to do another size allocation to
-      // emulate the queue resize.
-      gtk_widget_size_allocate(box_, &allocation);
-      gtk_widget_size_allocate(box_, &allocation);
-      ASSERT_NO_FATAL_FAILURE(Validate(pack_start)) << "width = " << width;
-    }
-
-    for (int width = kBorderWidth * 2; width <= 500; ++width) {
-      SCOPED_TRACE(testing::Message() << "Expand hide_child_directly = FALSE,"
-                   << " width = " << width);
-
-      allocation.width = width;
-      // Expanding the width may cause some invisible children to be shown,
-      // which will cause queue resize, so it's necessary to do another size
-      // allocation to emulate the queue resize.
-      gtk_widget_size_allocate(box_, &allocation);
-      gtk_widget_size_allocate(box_, &allocation);
-      ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
-    }
-
-    gtk_chrome_shrinkable_hbox_set_hide_child_directly(
-        GTK_CHROME_SHRINKABLE_HBOX(box_), TRUE);
-    for (int width = 500; width > kBorderWidth * 2; --width) {
-      SCOPED_TRACE(testing::Message() << "Shrink hide_child_directly = TRUE,"
-                   << " width = " << width);
-
-      allocation.width = width;
-      gtk_widget_size_allocate(box_, &allocation);
-      gtk_widget_size_allocate(box_, &allocation);
-      ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
-    }
-
-    for (int width = kBorderWidth * 2; width <= 500; ++width) {
-      SCOPED_TRACE(testing::Message() << "Expand hide_child_directly = TRUE,"
-                   << " width = " << width);
-
-      allocation.width = width;
-      gtk_widget_size_allocate(box_, &allocation);
-      gtk_widget_size_allocate(box_, &allocation);
-      ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
-    }
-  }
-
- protected:
-  GtkWidget* window_;
-  GtkWidget* box_;
-
- private:
-  struct ChildData {
-    bool visible;
-    int padding;
-    int x;
-    int width;
-  };
-
-  static void CollectChildData(GtkWidget* child, gpointer userdata) {
-    guint padding;
-    gtk_box_query_child_packing(GTK_BOX(gtk_widget_get_parent(child)), child,
-                                NULL, NULL, &padding, NULL);
-
-    ChildData data;
-    data.visible = GTK_WIDGET_VISIBLE(child);
-    data.padding = padding;
-    data.x = child->allocation.x;
-    data.width = child->allocation.width;
-
-    reinterpret_cast<std::vector<ChildData>*>(userdata)->push_back(data);
-  }
-};
-
-TEST_F(GtkChromeShrinkableHBoxTest, PackStart) {
-  AddChildren(true);
-
-  {
-    SCOPED_TRACE("Test LTR");
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
-    EXPECT_NO_FATAL_FAILURE(Test(true));
-  }
-  {
-    SCOPED_TRACE("Test RTL");
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
-    EXPECT_NO_FATAL_FAILURE(Test(true));
-  }
-}
-
-TEST_F(GtkChromeShrinkableHBoxTest, PackEnd) {
-  AddChildren(false);
-
-  {
-    SCOPED_TRACE("Test LTR");
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
-    EXPECT_NO_FATAL_FAILURE(Test(false));
-  }
-  {
-    SCOPED_TRACE("Test RTL");
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
-    EXPECT_NO_FATAL_FAILURE(Test(false));
-  }
-}
-
-TEST_F(GtkChromeShrinkableHBoxTest, Homogeneous) {
-  AddChildren(true);
-  gtk_box_set_homogeneous(GTK_BOX(box_), true);
-
-  {
-    SCOPED_TRACE("Test LTR");
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
-    EXPECT_NO_FATAL_FAILURE(Test(true));
-  }
-  {
-    SCOPED_TRACE("Test RTL");
-    gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
-    EXPECT_NO_FATAL_FAILURE(Test(true));
-  }
-}
diff --git a/chrome/browser/gtk/gtk_custom_menu.cc b/chrome/browser/gtk/gtk_custom_menu.cc
deleted file mode 100644
index 15eeb5a..0000000
--- a/chrome/browser/gtk/gtk_custom_menu.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_custom_menu.h"
-
-#include "chrome/browser/gtk/gtk_custom_menu_item.h"
-
-G_DEFINE_TYPE(GtkCustomMenu, gtk_custom_menu, GTK_TYPE_MENU)
-
-// Stolen directly from gtkmenushell.c. I'd love to call the library version
-// instead, but it's static and isn't exported. :(
-static gint gtk_menu_shell_is_item(GtkMenuShell* menu_shell,
-                                   GtkWidget* child) {
-  GtkWidget *parent;
-
-  g_return_val_if_fail(GTK_IS_MENU_SHELL(menu_shell), FALSE);
-  g_return_val_if_fail(child != NULL, FALSE);
-
-  parent = child->parent;
-  while (GTK_IS_MENU_SHELL(parent)) {
-    if (parent == reinterpret_cast<GtkWidget*>(menu_shell))
-      return TRUE;
-    parent = GTK_MENU_SHELL(parent)->parent_menu_shell;
-  }
-
-  return FALSE;
-}
-
-// Stolen directly from gtkmenushell.c. I'd love to call the library version
-// instead, but it's static and isn't exported. :(
-static GtkWidget* gtk_menu_shell_get_item(GtkMenuShell* menu_shell,
-                                          GdkEvent* event) {
-  GtkWidget* menu_item = gtk_get_event_widget(event);
-
-  while (menu_item && !GTK_IS_MENU_ITEM(menu_item))
-    menu_item = menu_item->parent;
-
-  if (menu_item && gtk_menu_shell_is_item(menu_shell, menu_item))
-    return menu_item;
-  else
-    return NULL;
-}
-
-// When processing a button event, abort processing if the cursor isn't in a
-// clickable region.
-static gboolean gtk_custom_menu_button_press(GtkWidget* widget,
-                                             GdkEventButton* event) {
-  GtkWidget* menu_item = gtk_menu_shell_get_item(
-      GTK_MENU_SHELL(widget), reinterpret_cast<GdkEvent*>(event));
-  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
-    if (!gtk_custom_menu_item_is_in_clickable_region(
-            GTK_CUSTOM_MENU_ITEM(menu_item))) {
-      return TRUE;
-    }
-  }
-
-  return GTK_WIDGET_CLASS(gtk_custom_menu_parent_class)->
-      button_press_event(widget, event);
-}
-
-// When processing a button event, abort processing if the cursor isn't in a
-// clickable region. If it's in a button that doesn't dismiss the menu, fire
-// that event and abort having the normal GtkMenu code run.
-static gboolean gtk_custom_menu_button_release(GtkWidget* widget,
-                                               GdkEventButton* event) {
-  GtkWidget* menu_item = gtk_menu_shell_get_item(
-      GTK_MENU_SHELL(widget), reinterpret_cast<GdkEvent*>(event));
-  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
-    if (!gtk_custom_menu_item_is_in_clickable_region(
-            GTK_CUSTOM_MENU_ITEM(menu_item))) {
-      // Stop processing this event. This isn't a clickable region.
-      return TRUE;
-    }
-
-    if (gtk_custom_menu_item_try_no_dismiss_command(
-            GTK_CUSTOM_MENU_ITEM(menu_item))) {
-      return TRUE;
-    }
-  }
-
-  return GTK_WIDGET_CLASS(gtk_custom_menu_parent_class)->
-      button_release_event(widget, event);
-}
-
-// Manually forward button press events to the menu item (and then do what we'd
-// do normally).
-static gboolean gtk_custom_menu_motion_notify(GtkWidget* widget,
-                                              GdkEventMotion* event) {
-  GtkWidget* menu_item = gtk_menu_shell_get_item(
-      GTK_MENU_SHELL(widget), (GdkEvent*)event);
-  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
-    gtk_custom_menu_item_receive_motion_event(GTK_CUSTOM_MENU_ITEM(menu_item),
-                                              event->x, event->y);
-  }
-
-  return GTK_WIDGET_CLASS(gtk_custom_menu_parent_class)->
-      motion_notify_event(widget, event);
-}
-
-static void gtk_custom_menu_move_current(GtkMenuShell* menu_shell,
-                                         GtkMenuDirectionType direction) {
-  // If the currently selected item is custom, we give it first chance to catch
-  // up/down events.
-
-  // TODO(erg): We are breaking a GSEAL by directly accessing this. We'll need
-  // to fix this by the time gtk3 comes out.
-  GtkWidget* menu_item = GTK_MENU_SHELL(menu_shell)->active_menu_item;
-  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
-    switch (direction) {
-      case GTK_MENU_DIR_PREV:
-      case GTK_MENU_DIR_NEXT:
-        if (gtk_custom_menu_item_handle_move(GTK_CUSTOM_MENU_ITEM(menu_item),
-                                             direction))
-          return;
-        break;
-      default:
-        break;
-    }
-  }
-
-  GTK_MENU_SHELL_CLASS(gtk_custom_menu_parent_class)->
-      move_current(menu_shell, direction);
-
-  // In the case of hitting PREV and transitioning to a custom menu, we want to
-  // make sure we're selecting the final item in the list, not the first one.
-  menu_item = GTK_MENU_SHELL(menu_shell)->active_menu_item;
-  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
-    gtk_custom_menu_item_select_item_by_direction(
-        GTK_CUSTOM_MENU_ITEM(menu_item), direction);
-  }
-}
-
-static void gtk_custom_menu_init(GtkCustomMenu* menu) {
-}
-
-static void gtk_custom_menu_class_init(GtkCustomMenuClass* klass) {
-  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
-  GtkMenuShellClass* menu_shell_class = GTK_MENU_SHELL_CLASS(klass);
-
-  widget_class->button_press_event = gtk_custom_menu_button_press;
-  widget_class->button_release_event = gtk_custom_menu_button_release;
-  widget_class->motion_notify_event = gtk_custom_menu_motion_notify;
-
-  menu_shell_class->move_current = gtk_custom_menu_move_current;
-}
-
-GtkWidget* gtk_custom_menu_new() {
-  return GTK_WIDGET(g_object_new(GTK_TYPE_CUSTOM_MENU, NULL));
-}
diff --git a/chrome/browser/gtk/gtk_custom_menu.h b/chrome/browser/gtk/gtk_custom_menu.h
deleted file mode 100644
index 1faa730..0000000
--- a/chrome/browser/gtk/gtk_custom_menu.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_H_
-#define CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_H_
-#pragma once
-
-// GtkCustomMenu is a GtkMenu subclass that can contain, and collaborates with,
-// GtkCustomMenuItem instances. GtkCustomMenuItem is a GtkMenuItem that can
-// have buttons and other normal widgets embeded in it. GtkCustomMenu exists
-// only to override most of the button/motion/move callback functions so
-// that the normal GtkMenu implementation doesn't handle events related to
-// GtkCustomMenuItem items.
-//
-// For a more through overview of this system, see the comments in
-// gtk_custom_menu_item.h.
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-#include <gtk/gtkmenuitem.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CUSTOM_MENU                                            \
-  (gtk_custom_menu_get_type())
-#define GTK_CUSTOM_MENU(obj)                                            \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CUSTOM_MENU, GtkCustomMenu))
-#define GTK_CUSTOM_MENU_CLASS(klass)                                    \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CUSTOM_MENU, GtkCustomMenuClass))
-#define GTK_IS_CUSTOM_MENU(obj)                                         \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CUSTOM_MENU))
-#define GTK_IS_CUSTOM_MENU_CLASS(klass)                                 \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CUSTOM_MENU))
-#define GTK_CUSTOM_MENU_GET_CLASS(obj)                                  \
-  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CUSTOM_MENU, GtkCustomMenuClass))
-
-typedef struct _GtkCustomMenu GtkCustomMenu;
-typedef struct _GtkCustomMenuClass GtkCustomMenuClass;
-
-struct _GtkCustomMenu {
-  GtkMenu menu;
-};
-
-struct _GtkCustomMenuClass {
-  GtkMenuClass parent_class;
-};
-
-GType gtk_custom_menu_get_type(void) G_GNUC_CONST;
-GtkWidget* gtk_custom_menu_new();
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_H_
diff --git a/chrome/browser/gtk/gtk_custom_menu_item.cc b/chrome/browser/gtk/gtk_custom_menu_item.cc
deleted file mode 100644
index a3d62d4..0000000
--- a/chrome/browser/gtk/gtk_custom_menu_item.cc
+++ /dev/null
@@ -1,434 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_custom_menu_item.h"
-
-#include "base/i18n/rtl.h"
-#include "chrome/browser/gtk/gtk_custom_menu.h"
-
-enum {
-  BUTTON_PUSHED,
-  TRY_BUTTON_PUSHED,
-  LAST_SIGNAL
-};
-
-static guint custom_menu_item_signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE(GtkCustomMenuItem, gtk_custom_menu_item, GTK_TYPE_MENU_ITEM)
-
-static void set_selected(GtkCustomMenuItem* item, GtkWidget* selected) {
-  if (selected != item->currently_selected_button) {
-    if (item->currently_selected_button) {
-      gtk_widget_set_state(item->currently_selected_button, GTK_STATE_NORMAL);
-      gtk_widget_set_state(
-          gtk_bin_get_child(GTK_BIN(item->currently_selected_button)),
-          GTK_STATE_NORMAL);
-    }
-
-    item->currently_selected_button = selected;
-    if (item->currently_selected_button) {
-      gtk_widget_set_state(item->currently_selected_button, GTK_STATE_SELECTED);
-      gtk_widget_set_state(
-          gtk_bin_get_child(GTK_BIN(item->currently_selected_button)),
-          GTK_STATE_PRELIGHT);
-    }
-  }
-}
-
-// When GtkButtons set the label text, they rebuild the widget hierarchy each
-// and every time. Therefore, we can't just fish out the label from the button
-// and set some properties; we have to create this callback function that
-// listens on the button's "notify" signal, which is emitted right after the
-// label has been (re)created. (Label values can change dynamically.)
-static void on_button_label_set(GObject* object) {
-  GtkButton* button = GTK_BUTTON(object);
-  gtk_widget_set_sensitive(GTK_BIN(button)->child, FALSE);
-  gtk_misc_set_padding(GTK_MISC(GTK_BIN(button)->child), 2, 0);
-}
-
-static void gtk_custom_menu_item_finalize(GObject *object);
-static gint gtk_custom_menu_item_expose(GtkWidget* widget,
-                                        GdkEventExpose* event);
-static gboolean gtk_custom_menu_item_hbox_expose(GtkWidget* widget,
-                                                 GdkEventExpose* event,
-                                                 GtkCustomMenuItem* menu_item);
-static void gtk_custom_menu_item_select(GtkItem *item);
-static void gtk_custom_menu_item_deselect(GtkItem *item);
-static void gtk_custom_menu_item_activate(GtkMenuItem* menu_item);
-
-static void gtk_custom_menu_item_init(GtkCustomMenuItem* item) {
-  item->all_widgets = NULL;
-  item->button_widgets = NULL;
-  item->currently_selected_button = NULL;
-  item->previously_selected_button = NULL;
-
-  GtkWidget* menu_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(item), menu_hbox);
-
-  item->label = gtk_label_new(NULL);
-  gtk_misc_set_alignment(GTK_MISC(item->label), 0.0, 0.5);
-  gtk_box_pack_start(GTK_BOX(menu_hbox), item->label, TRUE, TRUE, 0);
-
-  item->hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(menu_hbox), item->hbox, FALSE, FALSE, 0);
-
-  g_signal_connect(item->hbox, "expose-event",
-                   G_CALLBACK(gtk_custom_menu_item_hbox_expose),
-                   item);
-
-  gtk_widget_show_all(menu_hbox);
-}
-
-static void gtk_custom_menu_item_class_init(GtkCustomMenuItemClass* klass) {
-  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
-  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
-  GtkItemClass* item_class = GTK_ITEM_CLASS(klass);
-  GtkMenuItemClass* menu_item_class = GTK_MENU_ITEM_CLASS(klass);
-
-  gobject_class->finalize = gtk_custom_menu_item_finalize;
-
-  widget_class->expose_event = gtk_custom_menu_item_expose;
-
-  item_class->select = gtk_custom_menu_item_select;
-  item_class->deselect = gtk_custom_menu_item_deselect;
-
-  menu_item_class->activate = gtk_custom_menu_item_activate;
-
-  custom_menu_item_signals[BUTTON_PUSHED] =
-      g_signal_new("button-pushed",
-                   G_OBJECT_CLASS_TYPE(gobject_class),
-                   G_SIGNAL_RUN_FIRST,
-                   0,
-                   NULL, NULL,
-                   gtk_marshal_NONE__INT,
-                   G_TYPE_NONE, 1, GTK_TYPE_INT);
-  // TODO(erg): Change from BOOL__POINTER to BOOLEAN__INTEGER when we get to
-  // use a modern GTK+.
-  custom_menu_item_signals[TRY_BUTTON_PUSHED] =
-      g_signal_new("try-button-pushed",
-                   G_OBJECT_CLASS_TYPE(gobject_class),
-                   G_SIGNAL_RUN_LAST,
-                   0,
-                   NULL, NULL,
-                   gtk_marshal_BOOL__POINTER,
-                   G_TYPE_BOOLEAN, 1, GTK_TYPE_INT);
-}
-
-static void gtk_custom_menu_item_finalize(GObject *object) {
-  GtkCustomMenuItem* item = GTK_CUSTOM_MENU_ITEM(object);
-  g_list_free(item->all_widgets);
-  g_list_free(item->button_widgets);
-
-  G_OBJECT_CLASS(gtk_custom_menu_item_parent_class)->finalize(object);
-}
-
-static gint gtk_custom_menu_item_expose(GtkWidget* widget,
-                                        GdkEventExpose* event) {
-  if (GTK_WIDGET_VISIBLE(widget) &&
-      GTK_WIDGET_MAPPED(widget) &&
-      gtk_bin_get_child(GTK_BIN(widget))) {
-    // We skip the drawing in the GtkMenuItem class it draws the highlighted
-    // background and we don't want that.
-    gtk_container_propagate_expose(GTK_CONTAINER(widget),
-                                   gtk_bin_get_child(GTK_BIN(widget)),
-                                   event);
-  }
-
-  return FALSE;
-}
-
-static void gtk_custom_menu_item_expose_button(GtkWidget* hbox,
-                                               GdkEventExpose* event,
-                                               GList* button_item) {
-  // We search backwards to find the leftmost and rightmost buttons. The
-  // current button may be that button.
-  GtkWidget* current_button = GTK_WIDGET(button_item->data);
-  GtkWidget* first_button = current_button;
-  for (GList* i = button_item; i && GTK_IS_BUTTON(i->data);
-       i = g_list_previous(i)) {
-    first_button = GTK_WIDGET(i->data);
-  }
-
-  GtkWidget* last_button = current_button;
-  for (GList* i = button_item; i && GTK_IS_BUTTON(i->data);
-       i = g_list_next(i)) {
-    last_button = GTK_WIDGET(i->data);
-  }
-
-  if (base::i18n::IsRTL())
-    std::swap(first_button, last_button);
-
-  int x = first_button->allocation.x;
-  int y = first_button->allocation.y;
-  int width = last_button->allocation.width + last_button->allocation.x -
-              first_button->allocation.x;
-  int height = last_button->allocation.height;
-
-  gtk_paint_box(hbox->style, hbox->window,
-                static_cast<GtkStateType>(
-                    GTK_WIDGET_STATE(current_button)),
-                GTK_SHADOW_OUT,
-                &current_button->allocation, hbox, "button",
-                x, y, width, height);
-
-  // Propagate to the button's children.
-  gtk_container_propagate_expose(
-      GTK_CONTAINER(current_button),
-      gtk_bin_get_child(GTK_BIN(current_button)),
-      event);
-}
-
-static gboolean gtk_custom_menu_item_hbox_expose(GtkWidget* widget,
-                                                 GdkEventExpose* event,
-                                                 GtkCustomMenuItem* menu_item) {
-  // First render all the buttons that aren't the currently selected item.
-  for (GList* current_item = menu_item->all_widgets;
-       current_item != NULL; current_item = g_list_next(current_item)) {
-    if (GTK_IS_BUTTON(current_item->data)) {
-      if (GTK_WIDGET(current_item->data) !=
-          menu_item->currently_selected_button) {
-        gtk_custom_menu_item_expose_button(widget, event, current_item);
-      }
-    }
-  }
-
-  // As a separate pass, draw the buton separators above. We need to draw the
-  // separators in a separate pass because we are drawing on top of the
-  // buttons. Otherwise, the vlines are overwritten by the next button.
-  for (GList* current_item = menu_item->all_widgets;
-       current_item != NULL; current_item = g_list_next(current_item)) {
-    if (GTK_IS_BUTTON(current_item->data)) {
-      // Check to see if this is the last button in a run.
-      GList* next_item = g_list_next(current_item);
-      if (next_item && GTK_IS_BUTTON(next_item->data)) {
-        GtkWidget* current_button = GTK_WIDGET(current_item->data);
-        GtkAllocation child_alloc =
-            gtk_bin_get_child(GTK_BIN(current_button))->allocation;
-        int half_offset = widget->style->xthickness / 2;
-        gtk_paint_vline(widget->style, widget->window,
-                        static_cast<GtkStateType>(
-                            GTK_WIDGET_STATE(current_button)),
-                        &event->area, widget, "button",
-                        child_alloc.y,
-                        child_alloc.y + child_alloc.height,
-                        current_button->allocation.x +
-                        current_button->allocation.width - half_offset);
-      }
-    }
-  }
-
-  // Finally, draw the selected item on top of the separators so there are no
-  // artifacts inside the button area.
-  GList* selected = g_list_find(menu_item->all_widgets,
-                                menu_item->currently_selected_button);
-  if (selected) {
-    gtk_custom_menu_item_expose_button(widget, event, selected);
-  }
-
-  return TRUE;
-}
-
-static void gtk_custom_menu_item_select(GtkItem* item) {
-  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(item);
-
-  // When we are selected, the only thing we do is clear information from
-  // previous selections. Actual selection of a button is done either in the
-  // "mouse-motion-event" or is manually set from GtkCustomMenu's overridden
-  // "move-current" handler.
-  custom_item->previously_selected_button = NULL;
-
-  gtk_widget_queue_draw(GTK_WIDGET(item));
-}
-
-static void gtk_custom_menu_item_deselect(GtkItem* item) {
-  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(item);
-
-  // When we are deselected, we store the item that was currently selected so
-  // that it can be acted on. Menu items are first deselected before they are
-  // activated.
-  custom_item->previously_selected_button =
-      custom_item->currently_selected_button;
-  if (custom_item->currently_selected_button)
-    set_selected(custom_item, NULL);
-
-  gtk_widget_queue_draw(GTK_WIDGET(item));
-}
-
-static void gtk_custom_menu_item_activate(GtkMenuItem* menu_item) {
-  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(menu_item);
-
-  // We look at |previously_selected_button| because by the time we've been
-  // activated, we've already gone through our deselect handler.
-  if (custom_item->previously_selected_button) {
-    gpointer id_ptr = g_object_get_data(
-        G_OBJECT(custom_item->previously_selected_button), "command-id");
-    if (id_ptr != NULL) {
-      int command_id = GPOINTER_TO_INT(id_ptr);
-      g_signal_emit(custom_item, custom_menu_item_signals[BUTTON_PUSHED], 0,
-                    command_id);
-      set_selected(custom_item, NULL);
-    }
-  }
-}
-
-GtkWidget* gtk_custom_menu_item_new(const char* title) {
-  GtkCustomMenuItem* item = GTK_CUSTOM_MENU_ITEM(
-      g_object_new(GTK_TYPE_CUSTOM_MENU_ITEM, NULL));
-  gtk_label_set_text(GTK_LABEL(item->label), title);
-  return GTK_WIDGET(item);
-}
-
-GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item,
-                                           int command_id) {
-  GtkWidget* button = gtk_button_new();
-  g_object_set_data(G_OBJECT(button), "command-id",
-                    GINT_TO_POINTER(command_id));
-  gtk_box_pack_start(GTK_BOX(menu_item->hbox), button, FALSE, FALSE, 0);
-  gtk_widget_show(button);
-
-  menu_item->all_widgets = g_list_append(menu_item->all_widgets, button);
-  menu_item->button_widgets = g_list_append(menu_item->button_widgets, button);
-
-  return button;
-}
-
-GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item,
-                                                 int command_id) {
-  GtkWidget* button = gtk_button_new_with_label("");
-  g_object_set_data(G_OBJECT(button), "command-id",
-                    GINT_TO_POINTER(command_id));
-  gtk_box_pack_start(GTK_BOX(menu_item->hbox), button, FALSE, FALSE, 0);
-  g_signal_connect(button, "notify::label",
-                   G_CALLBACK(on_button_label_set), NULL);
-  gtk_widget_show(button);
-
-  menu_item->all_widgets = g_list_append(menu_item->all_widgets, button);
-
-  return button;
-}
-
-void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item) {
-  GtkWidget* fixed = gtk_fixed_new();
-  gtk_widget_set_size_request(fixed, 5, -1);
-
-  gtk_box_pack_start(GTK_BOX(menu_item->hbox), fixed, FALSE, FALSE, 0);
-  gtk_widget_show(fixed);
-
-  menu_item->all_widgets = g_list_append(menu_item->all_widgets, fixed);
-}
-
-void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item,
-                                               gdouble x, gdouble y) {
-  GtkWidget* new_selected_widget = NULL;
-  GList* current = menu_item->button_widgets;
-  for (; current != NULL; current = current->next) {
-    GtkWidget* current_widget = GTK_WIDGET(current->data);
-    GtkAllocation alloc = current_widget->allocation;
-    int offset_x, offset_y;
-    gtk_widget_translate_coordinates(current_widget, GTK_WIDGET(menu_item),
-                                     0, 0, &offset_x, &offset_y);
-    if (x >= offset_x && x < (offset_x + alloc.width) &&
-        y >= offset_y && y < (offset_y + alloc.height)) {
-      new_selected_widget = current_widget;
-      break;
-    }
-  }
-
-  set_selected(menu_item, new_selected_widget);
-}
-
-gboolean gtk_custom_menu_item_handle_move(GtkCustomMenuItem* menu_item,
-                                          GtkMenuDirectionType direction) {
-  GtkWidget* current = menu_item->currently_selected_button;
-  if (menu_item->button_widgets && current) {
-    switch (direction) {
-      case GTK_MENU_DIR_PREV: {
-        if (g_list_first(menu_item->button_widgets)->data == current)
-          return FALSE;
-
-        set_selected(menu_item, GTK_WIDGET(g_list_previous(g_list_find(
-            menu_item->button_widgets, current))->data));
-        break;
-      }
-      case GTK_MENU_DIR_NEXT: {
-        if (g_list_last(menu_item->button_widgets)->data == current)
-          return FALSE;
-
-        set_selected(menu_item, GTK_WIDGET(g_list_next(g_list_find(
-            menu_item->button_widgets, current))->data));
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  return TRUE;
-}
-
-void gtk_custom_menu_item_select_item_by_direction(
-    GtkCustomMenuItem* menu_item, GtkMenuDirectionType direction) {
-  menu_item->previously_selected_button = NULL;
-
-  // If we're just told to be selected by the menu system, select the first
-  // item.
-  if (menu_item->button_widgets) {
-    switch (direction) {
-      case GTK_MENU_DIR_PREV: {
-        GtkWidget* last_button =
-            GTK_WIDGET(g_list_last(menu_item->button_widgets)->data);
-        if (last_button)
-          set_selected(menu_item, last_button);
-        break;
-      }
-      case GTK_MENU_DIR_NEXT: {
-        GtkWidget* first_button =
-            GTK_WIDGET(g_list_first(menu_item->button_widgets)->data);
-        if (first_button)
-          set_selected(menu_item, first_button);
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  gtk_widget_queue_draw(GTK_WIDGET(menu_item));
-}
-
-gboolean gtk_custom_menu_item_is_in_clickable_region(
-    GtkCustomMenuItem* menu_item) {
-  return menu_item->currently_selected_button != NULL;
-}
-
-gboolean gtk_custom_menu_item_try_no_dismiss_command(
-    GtkCustomMenuItem* menu_item) {
-  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(menu_item);
-  gboolean activated = TRUE;
-
-  // We work with |currently_selected_button| instead of
-  // |previously_selected_button| since we haven't been "deselect"ed yet.
-  gpointer id_ptr = g_object_get_data(
-      G_OBJECT(custom_item->currently_selected_button), "command-id");
-  if (id_ptr != NULL) {
-    int command_id = GPOINTER_TO_INT(id_ptr);
-    g_signal_emit(custom_item, custom_menu_item_signals[TRY_BUTTON_PUSHED], 0,
-                  command_id, &activated);
-  }
-
-  return activated;
-}
-
-void gtk_custom_menu_item_foreach_button(GtkCustomMenuItem* menu_item,
-                                         GtkCallback callback,
-                                         gpointer callback_data) {
-  // Even though we're filtering |all_widgets| on GTK_IS_BUTTON(), this isn't
-  // equivalent to |button_widgets| because we also want the button-labels.
-  for (GList* i = menu_item->all_widgets; i && GTK_IS_BUTTON(i->data);
-       i = g_list_next(i)) {
-    if (GTK_IS_BUTTON(i->data)) {
-      callback(GTK_WIDGET(i->data), callback_data);
-    }
-  }
-}
diff --git a/chrome/browser/gtk/gtk_custom_menu_item.h b/chrome/browser/gtk/gtk_custom_menu_item.h
deleted file mode 100644
index 76e8c9a..0000000
--- a/chrome/browser/gtk/gtk_custom_menu_item.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_ITEM_H_
-#define CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_ITEM_H_
-#pragma once
-
-// GtkCustomMenuItem is a GtkMenuItem subclass that has buttons in it and acts
-// to support this. GtkCustomMenuItems only render properly when put in a
-// GtkCustomMenu; there's a lot of collaboration between these two classes
-// necessary to work around how gtk normally does menus.
-//
-// We can't rely on the normal event infrastructure. While a menu is up, the
-// GtkMenu has a grab on all events. Instead of trying to pump events through
-// the normal channels, we have the GtkCustomMenu selectively forward mouse
-// motion through a back channel. The GtkCustomMenu only listens for button
-// press information so it can block the effects of the click if the cursor
-// isn't in a button in the menu item.
-//
-// A GtkCustomMenuItem doesn't try to take these signals and forward them to
-// the buttons it owns. The GtkCustomMenu class keeps track of which button is
-// selected (due to key events and mouse movement) and otherwise acts like a
-// normal GtkItem. The buttons are only for sizing and rendering; they don't
-// respond to events. Instead, when the GtkCustomMenuItem is activated by the
-// GtkMenu, it uses which button was selected as a signal of what to do.
-//
-// Users should connect to the "button-pushed" signal to be notified when a
-// button was pushed. We don't go through the normal "activate" signal because
-// we need to communicate additional information, namely which button was
-// activated.
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CUSTOM_MENU_ITEM                                       \
-  (gtk_custom_menu_item_get_type())
-#define GTK_CUSTOM_MENU_ITEM(obj)                                       \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CUSTOM_MENU_ITEM,         \
-                              GtkCustomMenuItem))
-#define GTK_CUSTOM_MENU_ITEM_CLASS(klass)                               \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CUSTOM_MENU_ITEM,          \
-                           GtkCustomMenuItemClass))
-#define GTK_IS_CUSTOM_MENU_ITEM(obj)                                    \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CUSTOM_MENU_ITEM))
-#define GTK_IS_CUSTOM_MENU_ITEM_CLASS(klass)                            \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CUSTOM_MENU_ITEM))
-#define GTK_CUSTOM_MENU_ITEM_GET_CLASS(obj)                             \
-  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CUSTOM_MENU_ITEM,          \
-                             GtkCustomMenuItemClass))
-
-typedef struct _GtkCustomMenuItem GtkCustomMenuItem;
-typedef struct _GtkCustomMenuItemClass GtkCustomMenuItemClass;
-
-struct _GtkCustomMenuItem {
-  GtkMenuItem menu_item;
-
-  // Container for button widgets.
-  GtkWidget* hbox;
-
-  // Label on left side of menu item.
-  GtkWidget* label;
-
-  // List of all widgets we added. Used to find the leftmost and rightmost
-  // continuous buttons.
-  GList* all_widgets;
-
-  // Possible button widgets. Used for keyboard navigation.
-  GList* button_widgets;
-
-  // The widget that currently has highlight.
-  GtkWidget* currently_selected_button;
-
-  // The widget that was selected *before* |currently_selected_button|. Why do
-  // we hang on to this? Because the menu system sends us a deselect signal
-  // right before activating us. We need to listen to deselect since that's
-  // what we receive when the mouse cursor leaves us entirely.
-  GtkWidget* previously_selected_button;
-};
-
-struct _GtkCustomMenuItemClass {
-  GtkMenuItemClass parent_class;
-};
-
-GType gtk_custom_menu_item_get_type(void) G_GNUC_CONST;
-GtkWidget* gtk_custom_menu_item_new(const char* title);
-
-// Adds a button to our list of items in the |hbox|.
-GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item,
-                                           int command_id);
-
-// Adds a button to our list of items in the |hbox|, but that isn't part of
-// |button_widgets| to prevent it from being activatable.
-GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item,
-                                                 int command_id);
-
-// Adds a vertical space in the |hbox|.
-void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item);
-
-// Receives a motion event from the GtkCustomMenu that contains us. We can't
-// just subscribe to motion-event or the individual widget enter/leave events
-// because the top level GtkMenu has an event grab.
-void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item,
-                                               gdouble x, gdouble y);
-
-// Notification that the menu got a cursor key event. Used to move up/down
-// within the menu buttons. Returns TRUE to stop the default signal handler
-// from running.
-gboolean gtk_custom_menu_item_handle_move(GtkCustomMenuItem* menu_item,
-                                          GtkMenuDirectionType direction);
-
-// Because we only get a generic "selected" signal when we've changed, we need
-// to have a way for the GtkCustomMenu to tell us that we were just
-// selected.
-void gtk_custom_menu_item_select_item_by_direction(
-    GtkCustomMenuItem* menu_item, GtkMenuDirectionType direction);
-
-// Whether we are currently hovering over a clickable region on the menu
-// item. Used by GtkCustomMenu to determine whether it should discard click
-// events.
-gboolean gtk_custom_menu_item_is_in_clickable_region(
-    GtkCustomMenuItem* menu_item);
-
-// If the button is released while the |currently_selected_button| isn't
-// supposed to dismiss the menu, this signals to our listeners that we want to
-// run this command if it doesn't dismiss the menu.  Returns TRUE if we acted
-// on this button click (and should prevent the normal GtkMenu machinery from
-// firing an "activate" signal).
-gboolean gtk_custom_menu_item_try_no_dismiss_command(
-    GtkCustomMenuItem* menu_item);
-
-// Calls |callback| with every button and button-label in the container.
-void gtk_custom_menu_item_foreach_button(GtkCustomMenuItem* menu_item,
-                                         GtkCallback callback,
-                                         gpointer callback_data);
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_ITEM_H_
diff --git a/chrome/browser/gtk/gtk_expanded_container.cc b/chrome/browser/gtk/gtk_expanded_container.cc
deleted file mode 100644
index 4e5daad..0000000
--- a/chrome/browser/gtk/gtk_expanded_container.cc
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_expanded_container.h"
-
-#include <gtk/gtk.h>
-#include <algorithm>
-
-namespace {
-
-enum {
-  CHILD_SIZE_REQUEST,
-  LAST_SIGNAL
-};
-
-guint expanded_container_signals[LAST_SIGNAL] = { 0 };
-
-struct SizeAllocateData {
-  GtkWidget* container;
-  GtkAllocation* allocation;
-  int border_width;
-};
-
-void GetChildPosition(GtkWidget* container, GtkWidget* child, int* x, int* y) {
-  GValue v = { 0 };
-  g_value_init(&v, G_TYPE_INT);
-  gtk_container_child_get_property(GTK_CONTAINER(container), child, "x", &v);
-  *x = g_value_get_int(&v);
-  gtk_container_child_get_property(GTK_CONTAINER(container), child, "y", &v);
-  *y = g_value_get_int(&v);
-  g_value_unset(&v);
-}
-
-void ChildSizeAllocate(GtkWidget* child, gpointer userdata) {
-  if (!GTK_WIDGET_VISIBLE(child))
-    return;
-
-  SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata);
-
-  GtkRequisition child_requisition;
-  child_requisition.width = data->allocation->width - data->border_width * 2;
-  child_requisition.height = data->allocation->height - data->border_width * 2;
-
-  // We need to give whoever is pulling our strings a chance to adjust the
-  // size of our children.
-  g_signal_emit(data->container,
-                expanded_container_signals[CHILD_SIZE_REQUEST], 0,
-                child, &child_requisition);
-
-  GtkAllocation child_allocation;
-  child_allocation.width = child_requisition.width;
-  child_allocation.height = child_requisition.height;
-  if (child_allocation.width < 0 || child_allocation.height < 0) {
-    gtk_widget_get_child_requisition(child, &child_requisition);
-    if (child_allocation.width < 0)
-      child_allocation.width = child_requisition.width;
-    if (child_allocation.height < 0)
-      child_allocation.height = child_requisition.height;
-  }
-
-  int x, y;
-  GetChildPosition(data->container, child, &x, &y);
-
-  child_allocation.x = x + data->border_width;
-  child_allocation.y = y + data->border_width;
-
-  if (GTK_WIDGET_NO_WINDOW(data->container)) {
-    child_allocation.x += data->allocation->x;
-    child_allocation.y += data->allocation->y;
-  }
-  gtk_widget_size_allocate(child, &child_allocation);
-}
-
-void Marshal_VOID__OBJECT_BOXED(GClosure* closure,
-                                GValue* return_value G_GNUC_UNUSED,
-                                guint n_param_values,
-                                const GValue* param_values,
-                                gpointer invocation_hint G_GNUC_UNUSED,
-                                gpointer marshal_data) {
-  typedef void (*GMarshalFunc_VOID__OBJECT_BOXED) (gpointer data1,
-                                                   gpointer arg_1,
-                                                   gpointer arg_2,
-                                                   gpointer data2);
-  register GMarshalFunc_VOID__OBJECT_BOXED callback;
-  register GCClosure *cc = reinterpret_cast<GCClosure*>(closure);
-  register gpointer data1, data2;
-
-  g_return_if_fail(n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA(closure)) {
-    data1 = closure->data;
-    data2 = g_value_peek_pointer(param_values + 0);
-  } else {
-    data1 = g_value_peek_pointer(param_values + 0);
-    data2 = closure->data;
-  }
-
-  callback = reinterpret_cast<GMarshalFunc_VOID__OBJECT_BOXED>(
-      marshal_data ? marshal_data : cc->callback);
-
-  callback(data1,
-           g_value_get_object(param_values + 1),
-           g_value_get_boxed(param_values + 2),
-           data2);
-}
-
-}  // namespace
-
-G_BEGIN_DECLS
-
-static void gtk_expanded_container_size_allocate(GtkWidget* widget,
-                                                 GtkAllocation* allocation);
-
-G_DEFINE_TYPE(GtkExpandedContainer, gtk_expanded_container, GTK_TYPE_FIXED)
-
-static void gtk_expanded_container_class_init(
-    GtkExpandedContainerClass *klass) {
-  GtkObjectClass* object_class =
-      reinterpret_cast<GtkObjectClass*>(klass);
-
-  GtkWidgetClass* widget_class =
-      reinterpret_cast<GtkWidgetClass*>(klass);
-  widget_class->size_allocate = gtk_expanded_container_size_allocate;
-
-  expanded_container_signals[CHILD_SIZE_REQUEST] =
-      g_signal_new("child-size-request",
-                   G_OBJECT_CLASS_TYPE(object_class),
-                   static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST),
-                   0,
-                   NULL, NULL,
-                   Marshal_VOID__OBJECT_BOXED,
-                   G_TYPE_NONE, 2,
-                   GTK_TYPE_WIDGET,
-                   GTK_TYPE_REQUISITION | G_SIGNAL_TYPE_STATIC_SCOPE);
-}
-
-static void gtk_expanded_container_init(GtkExpandedContainer* container) {
-}
-
-static void gtk_expanded_container_size_allocate(GtkWidget* widget,
-                                                 GtkAllocation* allocation) {
-  widget->allocation = *allocation;
-
-  if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
-    gdk_window_move_resize(widget->window,
-                           allocation->x,
-                           allocation->y,
-                           allocation->width,
-                           allocation->height);
-  }
-
-  SizeAllocateData data;
-  data.container = widget;
-  data.allocation = allocation;
-  data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
-
-  gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data);
-}
-
-GtkWidget* gtk_expanded_container_new() {
-  return GTK_WIDGET(g_object_new(GTK_TYPE_EXPANDED_CONTAINER, NULL));
-}
-
-void gtk_expanded_container_put(GtkExpandedContainer* container,
-                                GtkWidget* widget, gint x, gint y) {
-  g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container));
-  g_return_if_fail(GTK_IS_WIDGET(widget));
-  gtk_fixed_put(GTK_FIXED(container), widget, x, y);
-}
-
-void gtk_expanded_container_move(GtkExpandedContainer* container,
-                                 GtkWidget* widget, gint x, gint y) {
-  g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container));
-  g_return_if_fail(GTK_IS_WIDGET(widget));
-  gtk_fixed_move(GTK_FIXED(container), widget, x, y);
-}
-
-void gtk_expanded_container_set_has_window(GtkExpandedContainer* container,
-                                           gboolean has_window) {
-  g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container));
-  g_return_if_fail(!GTK_WIDGET_REALIZED(container));
-  gtk_fixed_set_has_window(GTK_FIXED(container), has_window);
-}
-
-gboolean gtk_expanded_container_get_has_window(
-    GtkExpandedContainer* container) {
-  g_return_val_if_fail(GTK_IS_EXPANDED_CONTAINER(container), FALSE);
-  return gtk_fixed_get_has_window(GTK_FIXED(container));
-}
-
-G_END_DECLS
diff --git a/chrome/browser/gtk/gtk_expanded_container.h b/chrome/browser/gtk/gtk_expanded_container.h
deleted file mode 100644
index 0870bbc..0000000
--- a/chrome/browser/gtk/gtk_expanded_container.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_EXPANDED_CONTAINER_H_
-#define CHROME_BROWSER_GTK_GTK_EXPANDED_CONTAINER_H_
-#pragma once
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-// A specialized container derived from GtkFixed, which expands the size of its
-// children to fill the container, in one or both directions. The usage of this
-// container is similar to GtkFixed.
-//
-// The "child-size-request" signal is optional, if you want to expand child
-// widgets to customized size other than the container's size. It should have
-// the following signature:
-//
-//   void (*child_size_request)(GtkExpandedContainer* container,
-//                              GtkWidget* child,
-//                              GtkRequisition* requisition);
-//
-// This signal is emitted for each child with the requisition set to the size of
-// the container. Your handler may adjust the value of the requisition. If the
-// width or height is set to -1, then that direction will not be expanded, and
-// the original size request of the child will be used.
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_EXPANDED_CONTAINER                                 \
-    (gtk_expanded_container_get_type())
-#define GTK_EXPANDED_CONTAINER(obj)                                 \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_EXPANDED_CONTAINER, \
-                                GtkExpandedContainer))
-#define GTK_EXPANDED_CONTAINER_CLASS(klass)                         \
-    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_EXPANDED_CONTAINER,  \
-                             GtkExpandedContainerClass))
-#define GTK_IS_EXPANDED_CONTAINER(obj)                              \
-    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_EXPANDED_CONTAINER))
-#define GTK_IS_EXPANDED_CONTAINER_CLASS(klass)                      \
-    (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_EXPANDED_CONTAINER))
-#define GTK_EXPANDED_CONTAINER_GET_CLASS(obj)                       \
-    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_EXPANDED_CONTAINER,  \
-                               GtkExpandedContainerClass))
-
-typedef struct _GtkExpandedContainer GtkExpandedContainer;
-typedef struct _GtkExpandedContainerClass GtkExpandedContainerClass;
-
-struct _GtkExpandedContainer {
-  // Parent class.
-  GtkFixed fixed;
-};
-
-struct _GtkExpandedContainerClass {
-  GtkFixedClass parent_class;
-};
-
-GType gtk_expanded_container_get_type() G_GNUC_CONST;
-GtkWidget* gtk_expanded_container_new();
-void gtk_expanded_container_put(GtkExpandedContainer* container,
-                                GtkWidget* widget, gint x, gint y);
-void gtk_expanded_container_move(GtkExpandedContainer* container,
-                                 GtkWidget* widget, gint x, gint y);
-void gtk_expanded_container_set_has_window(GtkExpandedContainer* container,
-                                           gboolean has_window);
-gboolean gtk_expanded_container_get_has_window(GtkExpandedContainer* container);
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_EXPANDED_CONTAINER_H_
diff --git a/chrome/browser/gtk/gtk_expanded_container_unittest.cc b/chrome/browser/gtk/gtk_expanded_container_unittest.cc
deleted file mode 100644
index d400bb1..0000000
--- a/chrome/browser/gtk/gtk_expanded_container_unittest.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_expanded_container.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-class GtkExpandedContainerTest : public testing::Test {
- protected:
-  GtkExpandedContainerTest()
-      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
-        expanded_(gtk_expanded_container_new()) {
-    gtk_window_set_default_size(GTK_WINDOW(window_), 200, 200);
-    gtk_container_add(GTK_CONTAINER(window_), expanded_);
-  }
-  ~GtkExpandedContainerTest() {
-    gtk_widget_destroy(window_);
-  }
-
-  bool FindChild(GtkWidget* widget) {
-    GList* children = gtk_container_get_children(GTK_CONTAINER(expanded_));
-    for (GList* child = children; child; child = child->next) {
-      if (GTK_WIDGET(child->data) == widget) {
-        g_list_free(children);
-        return true;
-      }
-    }
-    g_list_free(children);
-    return false;
-  }
-
-  int GetChildX(GtkWidget* widget) {
-    GValue x = { 0 };
-    g_value_init(&x, G_TYPE_INT);
-    gtk_container_child_get_property(GTK_CONTAINER(expanded_), widget, "x", &x);
-    return g_value_get_int(&x);
-  }
-
-  int GetChildY(GtkWidget* widget) {
-    GValue y = { 0 };
-    g_value_init(&y, G_TYPE_INT);
-    gtk_container_child_get_property(GTK_CONTAINER(expanded_), widget, "y", &y);
-    return g_value_get_int(&y);
-  }
-
- protected:
-  GtkWidget* window_;
-  GtkWidget* expanded_;
-};
-
-TEST_F(GtkExpandedContainerTest, AddRemove) {
-  GtkWidget* child1 = gtk_fixed_new();
-  GtkWidget* child2 = gtk_fixed_new();
-  gtk_container_add(GTK_CONTAINER(expanded_), child1);
-  ASSERT_TRUE(FindChild(child1));
-
-  gtk_container_add(GTK_CONTAINER(expanded_), child2);
-  ASSERT_TRUE(FindChild(child2));
-  ASSERT_TRUE(FindChild(child1));
-
-  gtk_container_remove(GTK_CONTAINER(expanded_), child1);
-  ASSERT_FALSE(FindChild(child1));
-  ASSERT_TRUE(FindChild(child2));
-
-  gtk_container_remove(GTK_CONTAINER(expanded_), child2);
-  ASSERT_FALSE(FindChild(child2));
-}
-
-TEST_F(GtkExpandedContainerTest, Expand) {
-  GtkWidget* child1 = gtk_fixed_new();
-  GtkWidget* child2 = gtk_fixed_new();
-  gtk_container_add(GTK_CONTAINER(expanded_), child1);
-  gtk_expanded_container_put(GTK_EXPANDED_CONTAINER(expanded_),
-                             child2, 10, 20);
-  gtk_widget_show_all(window_);
-
-  GtkAllocation allocation = { 0, 0, 50, 100 };
-  gtk_widget_size_allocate(expanded_, &allocation);
-
-  EXPECT_EQ(0, child1->allocation.x);
-  EXPECT_EQ(0, child1->allocation.y);
-  EXPECT_EQ(50, child1->allocation.width);
-  EXPECT_EQ(100, child1->allocation.height);
-
-  EXPECT_EQ(10, child2->allocation.x);
-  EXPECT_EQ(20, child2->allocation.y);
-  EXPECT_EQ(50, child2->allocation.width);
-  EXPECT_EQ(100, child2->allocation.height);
-
-  allocation.x = 10;
-  allocation.y = 20;
-  gtk_widget_size_allocate(expanded_, &allocation);
-
-  EXPECT_EQ(10, child1->allocation.x);
-  EXPECT_EQ(20, child1->allocation.y);
-  EXPECT_EQ(20, child2->allocation.x);
-  EXPECT_EQ(40, child2->allocation.y);
-}
-
-// Test if the size allocation for children still works when using own
-// GdkWindow. In this case, the children's origin starts from (0, 0) rather
-// than the container's origin.
-TEST_F(GtkExpandedContainerTest, HasWindow) {
-  GtkWidget* child = gtk_fixed_new();
-  gtk_container_add(GTK_CONTAINER(expanded_), child);
-  gtk_expanded_container_set_has_window(GTK_EXPANDED_CONTAINER(expanded_),
-                                        TRUE);
-  gtk_widget_show_all(window_);
-
-  GtkAllocation allocation = { 10, 10, 50, 100 };
-  gtk_widget_size_allocate(expanded_, &allocation);
-
-  EXPECT_EQ(0, child->allocation.x);
-  EXPECT_EQ(0, child->allocation.y);
-  EXPECT_EQ(50, child->allocation.width);
-  EXPECT_EQ(100, child->allocation.height);
-}
-
-static void OnChildSizeRequest(GtkExpandedContainer* container,
-                               GtkWidget* child,
-                               GtkRequisition* requisition,
-                               gpointer userdata) {
-  ASSERT_EQ(child, GTK_WIDGET(userdata));
-  requisition->width = 250;
-  requisition->height = -1;
-}
-
-TEST_F(GtkExpandedContainerTest, ChildSizeRequest) {
-  GtkWidget* child = gtk_fixed_new();
-  gtk_widget_set_size_request(child, 10, 25);
-  g_signal_connect(expanded_, "child-size-request",
-                   G_CALLBACK(OnChildSizeRequest), child);
-  gtk_container_add(GTK_CONTAINER(expanded_), child);
-  gtk_widget_show_all(window_);
-
-  GtkAllocation allocation = { 0, 0, 300, 100 };
-  gtk_widget_size_allocate(expanded_, &allocation);
-
-  EXPECT_EQ(0, child->allocation.x);
-  EXPECT_EQ(0, child->allocation.y);
-  EXPECT_EQ(250, child->allocation.width);
-  EXPECT_EQ(25, child->allocation.height);
-}
-
-TEST_F(GtkExpandedContainerTest, ChildPosition) {
-  GtkWidget* child = gtk_fixed_new();
-  gtk_expanded_container_put(GTK_EXPANDED_CONTAINER(expanded_),
-                             child, 10, 20);
-  gtk_widget_show_all(window_);
-
-  EXPECT_EQ(10, GetChildX(child));
-  EXPECT_EQ(20, GetChildY(child));
-
-  gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(expanded_),
-                              child, 40, 50);
-  EXPECT_EQ(40, GetChildX(child));
-  EXPECT_EQ(50, GetChildY(child));
-}
diff --git a/chrome/browser/gtk/gtk_floating_container.cc b/chrome/browser/gtk/gtk_floating_container.cc
deleted file mode 100644
index ab8a49e..0000000
--- a/chrome/browser/gtk/gtk_floating_container.cc
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_floating_container.h"
-
-#include <gtk/gtk.h>
-#include <gtk/gtkprivate.h>
-#include <gtk/gtkmarshal.h>
-
-#include <algorithm>
-
-namespace {
-
-enum {
-  SET_FLOATING_POSITION,
-  LAST_SIGNAL
-};
-
-enum {
-  CHILD_PROP_0,
-  CHILD_PROP_X,
-  CHILD_PROP_Y
-};
-
-// Returns the GtkFloatingContainerChild associated with |widget| (or NULL if
-// |widget| not found).
-GtkFloatingContainerChild* GetChild(GtkFloatingContainer* container,
-                                    GtkWidget* widget) {
-  for (GList* floating_children = container->floating_children;
-       floating_children; floating_children = g_list_next(floating_children)) {
-    GtkFloatingContainerChild* child =
-        reinterpret_cast<GtkFloatingContainerChild*>(floating_children->data);
-
-    if (child->widget == widget)
-      return child;
-  }
-
-  return NULL;
-}
-
-}  // namespace
-
-G_BEGIN_DECLS
-
-static void gtk_floating_container_remove(GtkContainer* container,
-                                          GtkWidget* widget);
-static void gtk_floating_container_forall(GtkContainer* container,
-                                          gboolean include_internals,
-                                          GtkCallback callback,
-                                          gpointer callback_data);
-static void gtk_floating_container_size_request(GtkWidget* widget,
-                                                GtkRequisition* requisition);
-static void gtk_floating_container_size_allocate(GtkWidget* widget,
-                                                 GtkAllocation* allocation);
-static void gtk_floating_container_set_child_property(GtkContainer* container,
-                                                      GtkWidget* child,
-                                                      guint property_id,
-                                                      const GValue* value,
-                                                      GParamSpec* pspec);
-static void gtk_floating_container_get_child_property(GtkContainer* container,
-                                                      GtkWidget* child,
-                                                      guint property_id,
-                                                      GValue* value,
-                                                      GParamSpec* pspec);
-
-static guint floating_container_signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE(GtkFloatingContainer, gtk_floating_container, GTK_TYPE_BIN)
-
-static void gtk_floating_container_class_init(
-    GtkFloatingContainerClass *klass) {
-  GtkObjectClass* object_class =
-      reinterpret_cast<GtkObjectClass*>(klass);
-
-  GtkWidgetClass* widget_class =
-      reinterpret_cast<GtkWidgetClass*>(klass);
-  widget_class->size_request = gtk_floating_container_size_request;
-  widget_class->size_allocate = gtk_floating_container_size_allocate;
-
-  GtkContainerClass* container_class =
-      reinterpret_cast<GtkContainerClass*>(klass);
-  container_class->remove = gtk_floating_container_remove;
-  container_class->forall = gtk_floating_container_forall;
-
-  container_class->set_child_property =
-      gtk_floating_container_set_child_property;
-  container_class->get_child_property =
-      gtk_floating_container_get_child_property;
-
-  gtk_container_class_install_child_property(
-      container_class,
-      CHILD_PROP_X,
-      g_param_spec_int("x",
-                       "X position",
-                       "X position of child widget",
-                       G_MININT,
-                       G_MAXINT,
-                       0,
-                       static_cast<GParamFlags>(GTK_PARAM_READWRITE)));
-
-  gtk_container_class_install_child_property(
-      container_class,
-      CHILD_PROP_Y,
-      g_param_spec_int("y",
-                       "Y position",
-                       "Y position of child widget",
-                       G_MININT,
-                       G_MAXINT,
-                       0,
-                       static_cast<GParamFlags>(GTK_PARAM_READWRITE)));
-
-  floating_container_signals[SET_FLOATING_POSITION] =
-      g_signal_new("set-floating-position",
-                   G_OBJECT_CLASS_TYPE(object_class),
-                   static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST |
-                                             G_SIGNAL_ACTION),
-                   0,
-                   NULL, NULL,
-                   gtk_marshal_VOID__BOXED,
-                   G_TYPE_NONE, 1,
-                   GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
-}
-
-static void gtk_floating_container_init(GtkFloatingContainer* container) {
-  GTK_WIDGET_SET_FLAGS(container, GTK_NO_WINDOW);
-
-  container->floating_children = NULL;
-}
-
-static void gtk_floating_container_remove(GtkContainer* container,
-                                          GtkWidget* widget) {
-  g_return_if_fail(GTK_IS_WIDGET(widget));
-
-  GtkBin* bin = GTK_BIN(container);
-  if (bin->child == widget) {
-    ((GTK_CONTAINER_CLASS(gtk_floating_container_parent_class))->remove)
-        (container, widget);
-  } else {
-    // Handle the other case where it's in our |floating_children| list.
-    GtkFloatingContainer* floating = GTK_FLOATING_CONTAINER(container);
-    GList* children = floating->floating_children;
-    gboolean removed_child = false;
-    while (children) {
-      GtkFloatingContainerChild* child =
-          reinterpret_cast<GtkFloatingContainerChild*>(children->data);
-
-      if (child->widget == widget) {
-        removed_child = true;
-        gboolean was_visible = GTK_WIDGET_VISIBLE(widget);
-
-        gtk_widget_unparent(widget);
-
-        floating->floating_children =
-            g_list_remove_link(floating->floating_children, children);
-        g_list_free(children);
-        g_free(child);
-
-        if (was_visible && GTK_WIDGET_VISIBLE(container))
-          gtk_widget_queue_resize(GTK_WIDGET(container));
-
-        break;
-      }
-      children = children->next;
-    }
-
-    g_return_if_fail(removed_child);
-  }
-}
-
-static void gtk_floating_container_forall(GtkContainer* container,
-                                          gboolean include_internals,
-                                          GtkCallback callback,
-                                          gpointer callback_data) {
-  g_return_if_fail(container != NULL);
-  g_return_if_fail(callback != NULL);
-
-  // Let GtkBin do its part of the forall.
-  ((GTK_CONTAINER_CLASS(gtk_floating_container_parent_class))->forall)
-      (container, include_internals, callback, callback_data);
-
-  GtkFloatingContainer* floating = GTK_FLOATING_CONTAINER(container);
-  GList* children = floating->floating_children;
-  while (children) {
-    GtkFloatingContainerChild* child =
-        reinterpret_cast<GtkFloatingContainerChild*>(children->data);
-    children = children->next;
-
-    (*callback)(child->widget, callback_data);
-  }
-}
-
-static void gtk_floating_container_size_request(GtkWidget* widget,
-                                                GtkRequisition* requisition) {
-  GtkBin* bin = GTK_BIN(widget);
-  if (bin && bin->child) {
-    gtk_widget_size_request(bin->child, requisition);
-  } else {
-    requisition->width = 0;
-    requisition->height = 0;
-  }
-}
-
-static void gtk_floating_container_size_allocate(GtkWidget* widget,
-                                                 GtkAllocation* allocation) {
-  widget->allocation = *allocation;
-
-  if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
-    gdk_window_move_resize(widget->window,
-                           allocation->x,
-                           allocation->y,
-                           allocation->width,
-                           allocation->height);
-  }
-
-  // Give the same allocation to our GtkBin component.
-  GtkBin* bin = GTK_BIN(widget);
-  if (bin->child) {
-    gtk_widget_size_allocate(bin->child, allocation);
-  }
-
-  // We need to give whoever is pulling our strings a chance to set the "x" and
-  // "y" properties on all of our children.
-  g_signal_emit(widget, floating_container_signals[SET_FLOATING_POSITION], 0,
-                allocation);
-
-  // Our allocation has been set. We've asked our controller to place the other
-  // widgets. Pass out allocations to all our children based on where they want
-  // to be.
-  GtkFloatingContainer* container = GTK_FLOATING_CONTAINER(widget);
-  GList* children = container->floating_children;
-  GtkAllocation child_allocation;
-  GtkRequisition child_requisition;
-  while (children) {
-    GtkFloatingContainerChild* child =
-        reinterpret_cast<GtkFloatingContainerChild*>(children->data);
-    children = children->next;
-
-    if (GTK_WIDGET_VISIBLE(child->widget)) {
-      gtk_widget_size_request(child->widget, &child_requisition);
-      child_allocation.x = allocation->x + child->x;
-      child_allocation.y = allocation->y + child->y;
-      child_allocation.width = std::max(1, std::min(child_requisition.width,
-                                                    allocation->width));
-      child_allocation.height = std::max(1, std::min(child_requisition.height,
-                                                     allocation->height));
-      gtk_widget_size_allocate(child->widget, &child_allocation);
-    }
-  }
-}
-
-static void gtk_floating_container_set_child_property(GtkContainer* container,
-                                                      GtkWidget* child,
-                                                      guint property_id,
-                                                      const GValue* value,
-                                                      GParamSpec* pspec) {
-  GtkFloatingContainerChild* floating_child =
-      GetChild(GTK_FLOATING_CONTAINER(container), child);
-  g_return_if_fail(floating_child);
-
-  switch (property_id) {
-    case CHILD_PROP_X:
-      floating_child->x = g_value_get_int(value);
-      gtk_widget_child_notify(child, "x");
-      break;
-    case CHILD_PROP_Y:
-      floating_child->y = g_value_get_int(value);
-      gtk_widget_child_notify(child, "y");
-      break;
-    default:
-      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID(
-          container, property_id, pspec);
-      break;
-  };
-}
-
-static void gtk_floating_container_get_child_property(GtkContainer* container,
-                                                      GtkWidget* child,
-                                                      guint property_id,
-                                                      GValue* value,
-                                                      GParamSpec* pspec) {
-  GtkFloatingContainerChild* floating_child =
-      GetChild(GTK_FLOATING_CONTAINER(container), child);
-  g_return_if_fail(floating_child);
-
-  switch (property_id) {
-    case CHILD_PROP_X:
-      g_value_set_int(value, floating_child->x);
-      break;
-    case CHILD_PROP_Y:
-      g_value_set_int(value, floating_child->y);
-      break;
-    default:
-      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID(
-          container, property_id, pspec);
-      break;
-  };
-}
-
-GtkWidget* gtk_floating_container_new() {
-  return GTK_WIDGET(g_object_new(GTK_TYPE_FLOATING_CONTAINER, NULL));
-}
-
-void gtk_floating_container_add_floating(GtkFloatingContainer* container,
-                                         GtkWidget* widget) {
-  g_return_if_fail(GTK_IS_FLOATING_CONTAINER(container));
-  g_return_if_fail(GTK_IS_WIDGET(widget));
-
-  GtkFloatingContainerChild* child_info = g_new(GtkFloatingContainerChild, 1);
-  child_info->widget = widget;
-  child_info->x = 0;
-  child_info->y = 0;
-
-  gtk_widget_set_parent(widget, GTK_WIDGET(container));
-
-  container->floating_children =
-      g_list_append(container->floating_children, child_info);
-}
-
-G_END_DECLS
diff --git a/chrome/browser/gtk/gtk_floating_container.h b/chrome/browser/gtk/gtk_floating_container.h
deleted file mode 100644
index b0eed46..0000000
--- a/chrome/browser/gtk/gtk_floating_container.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_FLOATING_CONTAINER_H_
-#define CHROME_BROWSER_GTK_GTK_FLOATING_CONTAINER_H_
-#pragma once
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-// A specialized container, which is a cross between a GtkBin and a
-// GtkFixed. This container dervies from GtkBin and the implementation of
-// gtk_container_add() is the same: only one GtkWidget can be added through
-// that interface. The GtkBin portion contains normal content and is given the
-// same allocation that this container has.
-//
-// In addition, any number of widgets can be added through the
-// gtk_floating_container_add_floating() method, which provides functionality
-// similar to a GtkFixed. Unlike a GtkFixed, coordinates are not set when you
-// gtk_fixed_put(). The location of the floating widgets is determined while
-// running the "set-floating-position" signal, which is emitted during this
-// container's "size-allocate" handler.
-//
-// The "set-floating-position" signal is (semi-)mandatory if you want widgets
-// placed anywhere other than the origin and should have the following
-// signature:
-//
-//   void (*set_floating_position)(GtkFloatingContainer* container,
-//                                 GtkAllocation* allocation,
-//                                 gpointer userdata);
-//
-// Your handler should, for each floating widget, set the "x" and "y" child
-// properties.
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_FLOATING_CONTAINER                                 \
-    (gtk_floating_container_get_type())
-#define GTK_FLOATING_CONTAINER(obj)                                 \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_FLOATING_CONTAINER, \
-                                GtkFloatingContainer))
-#define GTK_FLOATING_CONTAINER_CLASS(klass)                         \
-    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_FLOATING_CONTAINER,  \
-                             GtkFloatingContainerClass))
-#define GTK_IS_FLOATING_CONTAINER(obj)                              \
-    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_FLOATING_CONTAINER))
-#define GTK_IS_FLOATING_CONTAINER_CLASS(klass)                      \
-    (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_FLOATING_CONTAINER))
-#define GTK_FLOATING_CONTAINER_GET_CLASS(obj)                       \
-    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_FLOATING_CONTAINER,  \
-                               GtkFloatingContainerClass))
-
-typedef struct _GtkFloatingContainer GtkFloatingContainer;
-typedef struct _GtkFloatingContainerClass GtkFloatingContainerClass;
-typedef struct _GtkFloatingContainerChild GtkFloatingContainerChild;
-
-struct _GtkFloatingContainer {
-  // Parent class.
-  GtkBin bin;
-
-  // A GList of all our floating children, in GtkFloatingContainerChild
-  // structs. Owned by the GtkFloatingContainer.
-  GList* floating_children;
-};
-
-struct _GtkFloatingContainerClass {
-  GtkBinClass parent_class;
-};
-
-// Internal structure used to associate a widget and its x/y child properties.
-struct _GtkFloatingContainerChild {
-  GtkWidget* widget;
-  gint x;
-  gint y;
-};
-
-GType      gtk_floating_container_get_type() G_GNUC_CONST;
-GtkWidget* gtk_floating_container_new();
-void       gtk_floating_container_add_floating(GtkFloatingContainer* container,
-                                               GtkWidget* widget);
-// Use gtk_container_remove to remove all widgets; both widgets added with
-// gtk_container_add() and gtk_floating_container_add_floating().
-
-G_END_DECLS
-
-#endif  // CHROME_BROWSER_GTK_GTK_FLOATING_CONTAINER_H_
diff --git a/chrome/browser/gtk/gtk_theme_provider.cc b/chrome/browser/gtk/gtk_theme_provider.cc
deleted file mode 100644
index 84c44b3..0000000
--- a/chrome/browser/gtk/gtk_theme_provider.cc
+++ /dev/null
@@ -1,1132 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-
-#include <gtk/gtk.h>
-
-#include <set>
-
-#include "app/gtk_signal_registrar.h"
-#include "app/resource_bundle.h"
-#include "base/environment.h"
-#include "base/stl_util-inl.h"
-#include "base/nix/xdg_util.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/chrome_gtk_frame.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/hover_controller_gtk.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
-#include "gfx/gtk_util.h"
-#include "gfx/skbitmap_operations.h"
-#include "gfx/skia_util.h"
-#include "gfx/skia_utils_gtk.h"
-#include "grit/app_resources.h"
-#include "grit/theme_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkShader.h"
-
-namespace {
-
-// The size of the rendered toolbar image.
-const int kToolbarImageWidth = 64;
-const int kToolbarImageHeight = 128;
-
-// How much to tint the GTK+ color lighter at the top of the window.
-const color_utils::HSL kGtkFrameShift = { -1, -1, 0.58 };
-
-// How much to tint the GTK+ color when an explicit frame color hasn't been
-// specified.
-const color_utils::HSL kDefaultFrameShift = { -1, -1, 0.4 };
-
-// Values used as the new luminance and saturation values in the inactive tab
-// text color.
-const double kDarkInactiveLuminance = 0.85;
-const double kLightInactiveLuminance = 0.15;
-const double kHeavyInactiveSaturation = 0.7;
-const double kLightInactiveSaturation = 0.3;
-
-// Number of times that the background color should be counted when trying to
-// calculate the border color in GTK theme mode.
-const int kBgWeight = 3;
-
-// Padding to left, top and bottom of vertical separators.
-const int kSeparatorPadding = 2;
-
-// Default color for links on the NTP when the GTK+ theme doesn't define a
-// link color. Constant taken from gtklinkbutton.c.
-const GdkColor kDefaultLinkColor = { 0, 0, 0, 0xeeee };
-
-// Middle color of the separator gradient.
-const double kMidSeparatorColor[] =
-    { 194.0 / 255.0, 205.0 / 255.0, 212.0 / 212.0 };
-// Top color of the separator gradient.
-const double kTopSeparatorColor[] =
-    { 222.0 / 255.0, 234.0 / 255.0, 248.0 / 255.0 };
-
-// Converts a GdkColor to a SkColor.
-SkColor GdkToSkColor(const GdkColor* color) {
-  return SkColorSetRGB(color->red >> 8,
-                       color->green >> 8,
-                       color->blue >> 8);
-}
-
-// A list of images that we provide while in gtk mode.
-const int kThemeImages[] = {
-  IDR_THEME_TOOLBAR,
-  IDR_THEME_TAB_BACKGROUND,
-  IDR_THEME_TAB_BACKGROUND_INCOGNITO,
-  IDR_THEME_FRAME,
-  IDR_THEME_FRAME_INACTIVE,
-  IDR_THEME_FRAME_INCOGNITO,
-  IDR_THEME_FRAME_INCOGNITO_INACTIVE,
-};
-
-// A list of icons used in the autocomplete view that should be tinted to the
-// current gtk theme selection color so they stand out against the GtkEntry's
-// base color.
-const int kAutocompleteImages[] = {
-  IDR_OMNIBOX_HTTP,
-  IDR_OMNIBOX_HTTP_DARK,
-  IDR_OMNIBOX_HISTORY,
-  IDR_OMNIBOX_HISTORY_DARK,
-  IDR_OMNIBOX_SEARCH,
-  IDR_OMNIBOX_SEARCH_DARK,
-  IDR_OMNIBOX_MORE,
-  IDR_OMNIBOX_MORE_DARK,
-  IDR_OMNIBOX_STAR,
-  IDR_OMNIBOX_STAR_DARK,
-  IDR_GEOLOCATION_ALLOWED_LOCATIONBAR_ICON,
-  IDR_GEOLOCATION_DENIED_LOCATIONBAR_ICON
-};
-
-bool IsOverridableImage(int id) {
-  static std::set<int> images;
-  if (images.empty()) {
-    images.insert(kThemeImages, kThemeImages + arraysize(kThemeImages));
-    images.insert(kAutocompleteImages,
-                  kAutocompleteImages + arraysize(kAutocompleteImages));
-
-    const std::set<int>& buttons =
-        BrowserThemeProvider::GetTintableToolbarButtons();
-    images.insert(buttons.begin(), buttons.end());
-  }
-
-  return images.count(id) > 0;
-}
-
-// Picks a button tint from a set of background colors. While
-// |accent_gdk_color| will usually be the same color through a theme, this
-// function will get called with the normal GtkLabel |text_color|/GtkWindow
-// |background_color| pair and the GtkEntry |text_color|/|background_color|
-// pair. While 3/4 of the time the resulting tint will be the same, themes that
-// have a dark window background (with light text) and a light text entry (with
-// dark text) will get better icons with this separated out.
-void PickButtonTintFromColors(const GdkColor& accent_gdk_color,
-                              const GdkColor& text_color,
-                              const GdkColor& background_color,
-                              color_utils::HSL* tint) {
-  SkColor accent_color = GdkToSkColor(&accent_gdk_color);
-  color_utils::HSL accent_tint;
-  color_utils::SkColorToHSL(accent_color, &accent_tint);
-
-  color_utils::HSL text_tint;
-  color_utils::SkColorToHSL(GdkToSkColor(&text_color), &text_tint);
-
-  color_utils::HSL background_tint;
-  color_utils::SkColorToHSL(GdkToSkColor(&background_color), &background_tint);
-
-  // If the accent color is gray, then our normal HSL tomfoolery will bring out
-  // whatever color is oddly dominant (for example, in rgb space [125, 128,
-  // 125] will tint green instead of gray). Slight differences (+/-10 (4%) to
-  // all color components) should be interpreted as this color being gray and
-  // we should switch into a special grayscale mode.
-  int rb_diff = abs(SkColorGetR(accent_color) - SkColorGetB(accent_color));
-  int rg_diff = abs(SkColorGetR(accent_color) - SkColorGetG(accent_color));
-  int bg_diff = abs(SkColorGetB(accent_color) - SkColorGetG(accent_color));
-  if (rb_diff < 10 && rg_diff < 10 && bg_diff < 10) {
-    // Our accent is white/gray/black. Only the luminance of the accent color
-    // matters.
-    tint->h = -1;
-
-    // Use the saturation of the text.
-    tint->s = text_tint.s;
-
-    // Use the luminance of the accent color UNLESS there isn't enough
-    // luminance contrast between the accent color and the base color.
-    if (fabs(accent_tint.l - background_tint.l) > 0.3)
-      tint->l = accent_tint.l;
-    else
-      tint->l = text_tint.l;
-  } else {
-    // Our accent is a color.
-    tint->h = accent_tint.h;
-
-    // Don't modify the saturation; the amount of color doesn't matter.
-    tint->s = -1;
-
-    // If the text wants us to darken the icon, don't change the luminance (the
-    // icons are already dark enough). Otherwise, lighten the icon by no more
-    // than 0.9 since we don't want a pure-white icon even if the text is pure
-    // white.
-    if (text_tint.l < 0.5)
-      tint->l = -1;
-    else if (text_tint.l <= 0.9)
-      tint->l = text_tint.l;
-    else
-      tint->l = 0.9;
-  }
-}
-
-
-// Builds and tints the image with |id| to the GtkStateType |state| and
-// places the result in |icon_set|.
-void BuildIconFromIDRWithColor(int id,
-                               GtkStyle* style,
-                               GtkStateType state,
-                               GtkIconSet* icon_set) {
-  SkColor color = GdkToSkColor(&style->fg[state]);
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  SkBitmap original = *rb.GetBitmapNamed(id);
-
-  SkBitmap fill_color;
-  fill_color.setConfig(SkBitmap::kARGB_8888_Config,
-                       original.width(), original.height(), 0);
-  fill_color.allocPixels();
-  fill_color.eraseColor(color);
-  SkBitmap masked = SkBitmapOperations::CreateMaskedBitmap(
-      fill_color, original);
-
-  GtkIconSource* icon = gtk_icon_source_new();
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&masked);
-  gtk_icon_source_set_pixbuf(icon, pixbuf);
-  g_object_unref(pixbuf);
-
-  gtk_icon_source_set_direction_wildcarded(icon, TRUE);
-  gtk_icon_source_set_size_wildcarded(icon, TRUE);
-
-  gtk_icon_source_set_state(icon, state);
-  // All fields default to wildcarding being on and setting a property doesn't
-  // turn off wildcarding. You need to do this yourself. This is stated once in
-  // the documentation in the gtk_icon_source_new() function, and no where else.
-  gtk_icon_source_set_state_wildcarded(
-      icon, state == GTK_STATE_NORMAL);
-
-  gtk_icon_set_add_source(icon_set, icon);
-  gtk_icon_source_free(icon);
-}
-
-// Applies an HSL shift to a GdkColor (instead of an SkColor)
-void GdkColorHSLShift(const color_utils::HSL& shift, GdkColor* frame_color) {
-  SkColor shifted = color_utils::HSLShift(GdkToSkColor(frame_color), shift);
-  frame_color->pixel = 0;
-  frame_color->red = SkColorGetR(shifted) * kSkiaToGDKMultiplier;
-  frame_color->green = SkColorGetG(shifted) * kSkiaToGDKMultiplier;
-  frame_color->blue = SkColorGetB(shifted) * kSkiaToGDKMultiplier;
-}
-
-}  // namespace
-
-GtkWidget* GtkThemeProvider::icon_widget_ = NULL;
-GdkPixbuf* GtkThemeProvider::default_folder_icon_ = NULL;
-GdkPixbuf* GtkThemeProvider::default_bookmark_icon_ = NULL;
-
-// static
-GtkThemeProvider* GtkThemeProvider::GetFrom(Profile* profile) {
-  return static_cast<GtkThemeProvider*>(profile->GetThemeProvider());
-}
-
-GtkThemeProvider::GtkThemeProvider()
-    : BrowserThemeProvider(),
-      fake_window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
-      fake_frame_(chrome_gtk_frame_new()),
-      signals_(new GtkSignalRegistrar),
-      fullscreen_icon_set_(NULL) {
-  fake_label_.Own(gtk_label_new(""));
-  fake_entry_.Own(gtk_entry_new());
-  fake_menu_item_.Own(gtk_menu_item_new());
-
-  // Only realized widgets receive style-set notifications, which we need to
-  // broadcast new theme images and colors. Only realized widgets have style
-  // properties, too, which we query for some colors.
-  gtk_widget_realize(fake_frame_);
-  gtk_widget_realize(fake_window_);
-  signals_->Connect(fake_frame_, "style-set",
-                    G_CALLBACK(&OnStyleSetThunk), this);
-}
-
-GtkThemeProvider::~GtkThemeProvider() {
-  gtk_widget_destroy(fake_window_);
-  gtk_widget_destroy(fake_frame_);
-  fake_label_.Destroy();
-  fake_entry_.Destroy();
-  fake_menu_item_.Destroy();
-
-  FreeIconSets();
-
-  // We have to call this because FreePlatformCached() in ~BrowserThemeProvider
-  // doesn't call the right virutal FreePlatformCaches.
-  FreePlatformCaches();
-}
-
-void GtkThemeProvider::Init(Profile* profile) {
-  registrar_.Init(profile->GetPrefs());
-  registrar_.Add(prefs::kUsesSystemTheme, this);
-  use_gtk_ = profile->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
-
-  BrowserThemeProvider::Init(profile);
-}
-
-SkBitmap* GtkThemeProvider::GetBitmapNamed(int id) const {
-  // Try to get our cached version:
-  ImageCache::const_iterator it = gtk_images_.find(id);
-  if (it != gtk_images_.end())
-    return it->second;
-
-  if (use_gtk_ && IsOverridableImage(id)) {
-    // We haven't built this image yet:
-    SkBitmap* bitmap = GenerateGtkThemeBitmap(id);
-    gtk_images_[id] = bitmap;
-    return bitmap;
-  }
-
-  return BrowserThemeProvider::GetBitmapNamed(id);
-}
-
-SkColor GtkThemeProvider::GetColor(int id) const {
-  if (use_gtk_) {
-    ColorMap::const_iterator it = colors_.find(id);
-    if (it != colors_.end())
-      return it->second;
-  }
-
-  return BrowserThemeProvider::GetColor(id);
-}
-
-bool GtkThemeProvider::HasCustomImage(int id) const {
-  if (use_gtk_)
-    return IsOverridableImage(id);
-
-  return BrowserThemeProvider::HasCustomImage(id);
-}
-
-void GtkThemeProvider::InitThemesFor(NotificationObserver* observer) {
-  observer->Observe(NotificationType::BROWSER_THEME_CHANGED,
-                    Source<ThemeProvider>(this),
-                    NotificationService::NoDetails());
-}
-
-void GtkThemeProvider::SetTheme(const Extension* extension) {
-  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
-  LoadDefaultValues();
-  BrowserThemeProvider::SetTheme(extension);
-}
-
-void GtkThemeProvider::UseDefaultTheme() {
-  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
-  LoadDefaultValues();
-  BrowserThemeProvider::UseDefaultTheme();
-}
-
-void GtkThemeProvider::SetNativeTheme() {
-  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, true);
-  ClearAllThemeData();
-  LoadGtkValues();
-  NotifyThemeChanged(NULL);
-}
-
-bool GtkThemeProvider::UsingDefaultTheme() {
-  return !use_gtk_ && BrowserThemeProvider::UsingDefaultTheme();
-}
-
-void GtkThemeProvider::Observe(NotificationType type,
-                               const NotificationSource& source,
-                               const NotificationDetails& details) {
-  if ((type == NotificationType::PREF_CHANGED) &&
-      (*Details<std::string>(details).ptr() == prefs::kUsesSystemTheme))
-    use_gtk_ = profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
-}
-
-GtkWidget* GtkThemeProvider::BuildChromeButton() {
-  GtkWidget* button = HoverControllerGtk::CreateChromeButton();
-  gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(button), use_gtk_);
-  chrome_buttons_.push_back(button);
-
-  signals_->Connect(button, "destroy", G_CALLBACK(OnDestroyChromeButtonThunk),
-                    this);
-  return button;
-}
-
-GtkWidget* GtkThemeProvider::CreateToolbarSeparator() {
-  GtkWidget* separator = gtk_vseparator_new();
-  GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
-      kSeparatorPadding, kSeparatorPadding, kSeparatorPadding, 0);
-  gtk_container_add(GTK_CONTAINER(alignment), separator);
-
-  signals_->Connect(separator, "expose-event",
-                    G_CALLBACK(OnSeparatorExposeThunk), this);
-  return alignment;
-}
-
-bool GtkThemeProvider::UseGtkTheme() const {
-  return use_gtk_;
-}
-
-GdkColor GtkThemeProvider::GetGdkColor(int id) const {
-  return gfx::SkColorToGdkColor(GetColor(id));
-}
-
-GdkColor GtkThemeProvider::GetBorderColor() const {
-  GtkStyle* style = gtk_rc_get_style(fake_window_);
-
-  GdkColor text;
-  GdkColor bg;
-  if (use_gtk_) {
-    text = style->text[GTK_STATE_NORMAL];
-    bg = style->bg[GTK_STATE_NORMAL];
-  } else {
-    text = GetGdkColor(COLOR_BOOKMARK_TEXT);
-    bg = GetGdkColor(COLOR_TOOLBAR);
-  }
-
-  // Creates a weighted average between the text and base color where
-  // the base color counts more than once.
-  GdkColor color;
-  color.pixel = 0;
-  color.red = (text.red + (bg.red * kBgWeight)) / (1 + kBgWeight);
-  color.green = (text.green + (bg.green * kBgWeight)) / (1 + kBgWeight);
-  color.blue = (text.blue + (bg.blue * kBgWeight)) / (1 + kBgWeight);
-
-  return color;
-}
-
-GtkIconSet* GtkThemeProvider::GetIconSetForId(int id) const {
-  if (id == IDR_FULLSCREEN_MENU_BUTTON)
-    return fullscreen_icon_set_;
-
-  return NULL;
-}
-
-void GtkThemeProvider::GetScrollbarColors(GdkColor* thumb_active_color,
-                                          GdkColor* thumb_inactive_color,
-                                          GdkColor* track_color) {
-  const GdkColor* theme_thumb_active = NULL;
-  const GdkColor* theme_thumb_inactive = NULL;
-  const GdkColor* theme_trough_color = NULL;
-  gtk_widget_style_get(GTK_WIDGET(fake_frame_),
-                       "scrollbar-slider-prelight-color", &theme_thumb_active,
-                       "scrollbar-slider-normal-color", &theme_thumb_inactive,
-                       "scrollbar-trough-color", &theme_trough_color,
-                       NULL);
-
-  // Ask the theme if the theme specifies all the scrollbar colors and short
-  // circuit the expensive painting/compositing if we have all of them.
-  if (theme_thumb_active && theme_thumb_inactive && theme_trough_color) {
-    *thumb_active_color = *theme_thumb_active;
-    *thumb_inactive_color = *theme_thumb_inactive;
-    *track_color = *theme_trough_color;
-    return;
-  }
-
-  // Create window containing scrollbar elements
-  GtkWidget* window    = gtk_window_new(GTK_WINDOW_POPUP);
-  GtkWidget* fixed     = gtk_fixed_new();
-  GtkWidget* scrollbar = gtk_hscrollbar_new(NULL);
-  gtk_container_add(GTK_CONTAINER(window), fixed);
-  gtk_container_add(GTK_CONTAINER(fixed),  scrollbar);
-  gtk_widget_realize(window);
-  gtk_widget_realize(scrollbar);
-
-  // Draw scrollbar thumb part and track into offscreen image
-  const int kWidth  = 100;
-  const int kHeight = 20;
-  GtkStyle*  style  = gtk_rc_get_style(scrollbar);
-  GdkPixmap* pm     = gdk_pixmap_new(window->window, kWidth, kHeight, -1);
-  GdkRectangle rect = { 0, 0, kWidth, kHeight };
-  unsigned char data[3 * kWidth * kHeight];
-  for (int i = 0; i < 3; ++i) {
-    if (i < 2) {
-      // Thumb part
-      gtk_paint_slider(style, pm,
-                       i == 0 ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
-                       GTK_SHADOW_OUT, &rect, scrollbar, "slider", 0, 0,
-                       kWidth, kHeight, GTK_ORIENTATION_HORIZONTAL);
-    } else {
-      // Track
-      gtk_paint_box(style, pm, GTK_STATE_ACTIVE, GTK_SHADOW_IN, &rect,
-                    scrollbar, "trough-upper", 0, 0, kWidth, kHeight);
-    }
-    GdkPixbuf* pb = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB,
-                                             FALSE, 8, kWidth, kHeight,
-                                             3 * kWidth, 0, 0);
-    gdk_pixbuf_get_from_drawable(pb, pm, NULL, 0, 0, 0, 0, kWidth, kHeight);
-
-    // Sample pixels
-    int components[3] = { 0 };
-    for (int y = 2; y < kHeight - 2; ++y) {
-      for (int c = 0; c < 3; ++c) {
-        // Sample a vertical slice of pixels at about one-thirds from the
-        // left edge. This allows us to avoid any fixed graphics that might be
-        // located at the edges or in the center of the scrollbar.
-        // Each pixel is made up of a red, green, and blue component; taking up
-        // a total of three bytes.
-        components[c] += data[3 * (kWidth / 3 + y * kWidth) + c];
-      }
-    }
-    GdkColor* color = i == 0 ? thumb_active_color :
-                      i == 1 ? thumb_inactive_color :
-                               track_color;
-    color->pixel = 0;
-    // We sampled pixels across the full height of the image, ignoring a two
-    // pixel border. In some themes, the border has a completely different
-    // color which we do not want to factor into our average color computation.
-    //
-    // We now need to scale the colors from the 0..255 range, to the wider
-    // 0..65535 range, and we need to actually compute the average color; so,
-    // we divide by the total number of pixels in the sample.
-    color->red   = components[0] * 65535 / (255 * (kHeight - 4));
-    color->green = components[1] * 65535 / (255 * (kHeight - 4));
-    color->blue  = components[2] * 65535 / (255 * (kHeight - 4));
-
-    g_object_unref(pb);
-  }
-  g_object_unref(pm);
-
-  gtk_widget_destroy(window);
-
-  // Override any of the default colors with ones that were specified by the
-  // theme.
-  if (theme_thumb_active)
-    *thumb_active_color = *theme_thumb_active;
-
-  if (theme_thumb_inactive)
-    *thumb_inactive_color = *theme_thumb_inactive;
-
-  if (theme_trough_color)
-    *track_color = *theme_trough_color;
-}
-
-CairoCachedSurface* GtkThemeProvider::GetSurfaceNamed(
-    int id,
-    GtkWidget* widget_on_display) {
-  return GetSurfaceNamedImpl(id,
-                             &per_display_surfaces_,
-                             GetPixbufNamed(id),
-                             widget_on_display);
-}
-
-CairoCachedSurface* GtkThemeProvider::GetRTLEnabledSurfaceNamed(
-    int id,
-    GtkWidget* widget_on_display) {
-  // We flip the sign of |id| when passing it to GetSurfaceNamedImpl() for the
-  // same reason that BrowserThemeProvider::GetPixbufImpl() does: so that if one
-  // location calls this function with a resource ID, and another place calls
-  // GetSurfaceNamed() with the same ID, they'll correctly get different
-  // surfaces in RTL mode.
-  return GetSurfaceNamedImpl(-id,
-                             &per_display_surfaces_,
-                             GetRTLEnabledPixbufNamed(id),
-                             widget_on_display);
-}
-
-CairoCachedSurface* GtkThemeProvider::GetUnthemedSurfaceNamed(
-    int id,
-    GtkWidget* widget_on_display) {
-  return GetSurfaceNamedImpl(id,
-      &per_display_unthemed_surfaces_,
-      ResourceBundle::GetSharedInstance().GetPixbufNamed(id),
-      widget_on_display);
-}
-
-// static
-GdkPixbuf* GtkThemeProvider::GetFolderIcon(bool native) {
-  if (native) {
-    if (!icon_widget_)
-      icon_widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-    // We never release our ref, so we will leak this on program shutdown.
-    if (!default_folder_icon_) {
-      default_folder_icon_ =
-          gtk_widget_render_icon(icon_widget_, GTK_STOCK_DIRECTORY,
-                                 GTK_ICON_SIZE_MENU, NULL);
-    }
-    if (default_folder_icon_)
-      return default_folder_icon_;
-  }
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  static GdkPixbuf* default_folder_icon_ = rb.GetPixbufNamed(
-      IDR_BOOKMARK_BAR_FOLDER);
-  return default_folder_icon_;
-}
-
-// static
-GdkPixbuf* GtkThemeProvider::GetDefaultFavicon(bool native) {
-  if (native) {
-    if (!icon_widget_)
-      icon_widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-    // We never release our ref, so we will leak this on program shutdown.
-    if (!default_bookmark_icon_) {
-      default_bookmark_icon_ =
-          gtk_widget_render_icon(icon_widget_, GTK_STOCK_FILE,
-                                 GTK_ICON_SIZE_MENU, NULL);
-    }
-    if (default_bookmark_icon_)
-      return default_bookmark_icon_;
-  }
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  static GdkPixbuf* default_bookmark_icon_ = rb.GetPixbufNamed(
-      IDR_DEFAULT_FAVICON);
-  return default_bookmark_icon_;
-}
-
-// static
-bool GtkThemeProvider::DefaultUsesSystemTheme() {
-  scoped_ptr<base::Environment> env(base::Environment::Create());
-
-  switch (base::nix::GetDesktopEnvironment(env.get())) {
-    case base::nix::DESKTOP_ENVIRONMENT_GNOME:
-    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
-      return true;
-    default:
-      return false;
-  }
-}
-
-void GtkThemeProvider::ClearAllThemeData() {
-  colors_.clear();
-  tints_.clear();
-
-  BrowserThemeProvider::ClearAllThemeData();
-}
-
-void GtkThemeProvider::LoadThemePrefs() {
-  if (use_gtk_) {
-    LoadGtkValues();
-  } else {
-    LoadDefaultValues();
-    BrowserThemeProvider::LoadThemePrefs();
-  }
-
-  RebuildMenuIconSets();
-}
-
-void GtkThemeProvider::NotifyThemeChanged(const Extension* extension) {
-  BrowserThemeProvider::NotifyThemeChanged(extension);
-
-  // Notify all GtkChromeButtons of their new rendering mode:
-  for (std::vector<GtkWidget*>::iterator it = chrome_buttons_.begin();
-       it != chrome_buttons_.end(); ++it) {
-    gtk_chrome_button_set_use_gtk_rendering(
-        GTK_CHROME_BUTTON(*it), use_gtk_);
-  }
-}
-
-void GtkThemeProvider::FreePlatformCaches() {
-  BrowserThemeProvider::FreePlatformCaches();
-  FreePerDisplaySurfaces(&per_display_surfaces_);
-  FreePerDisplaySurfaces(&per_display_unthemed_surfaces_);
-  STLDeleteValues(&gtk_images_);
-}
-
-void GtkThemeProvider::OnStyleSet(GtkWidget* widget,
-                                  GtkStyle* previous_style) {
-  GdkPixbuf* default_folder_icon = default_folder_icon_;
-  GdkPixbuf* default_bookmark_icon = default_bookmark_icon_;
-  default_folder_icon_ = NULL;
-  default_bookmark_icon_ = NULL;
-
-  if (profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme)) {
-    ClearAllThemeData();
-    LoadGtkValues();
-    NotifyThemeChanged(NULL);
-  }
-
-  RebuildMenuIconSets();
-
-  // Free the old icons only after the theme change notification has gone
-  // through.
-  if (default_folder_icon)
-    g_object_unref(default_folder_icon);
-  if (default_bookmark_icon)
-    g_object_unref(default_bookmark_icon);
-}
-
-void GtkThemeProvider::LoadGtkValues() {
-  // Before we start setting images and values, we have to clear out old, stale
-  // values. (If we don't do this, we'll regress startup time in the case where
-  // someone installs a heavyweight theme, then goes back to GTK.)
-  DictionaryValue* pref_images =
-      profile()->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages);
-  pref_images->Clear();
-
-  GtkStyle* frame_style = gtk_rc_get_style(fake_frame_);
-
-  GtkStyle* window_style = gtk_rc_get_style(fake_window_);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_CONTROL_BACKGROUND,
-                       &window_style->bg[GTK_STATE_NORMAL]);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND,
-                       &window_style->bg[GTK_STATE_NORMAL]);
-
-  GdkColor toolbar_color = window_style->bg[GTK_STATE_NORMAL];
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TOOLBAR, &toolbar_color);
-
-  GdkColor button_color = window_style->bg[GTK_STATE_SELECTED];
-  SetThemeTintFromGtk(BrowserThemeProvider::TINT_BUTTONS, &button_color);
-
-  GtkStyle* label_style = gtk_rc_get_style(fake_label_.get());
-  GdkColor label_color = label_style->fg[GTK_STATE_NORMAL];
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TAB_TEXT, &label_color);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, &label_color);
-
-  // Build the various icon tints.
-  GetNormalButtonTintHSL(&button_tint_);
-  GetNormalEntryForegroundHSL(&entry_tint_);
-  GetSelectedEntryForegroundHSL(&selected_entry_tint_);
-  GdkColor frame_color = BuildFrameColors(frame_style);
-
-  // The inactive frame color never occurs naturally in the theme, as it is a
-  // tinted version of |frame_color|. We generate another color based on the
-  // background tab color, with the lightness and saturation moved in the
-  // opposite direction. (We don't touch the hue, since there should be subtle
-  // hints of the color in the text.)
-  color_utils::HSL inactive_tab_text_hsl = tints_[TINT_BACKGROUND_TAB];
-  if (inactive_tab_text_hsl.l < 0.5)
-    inactive_tab_text_hsl.l = kDarkInactiveLuminance;
-  else
-    inactive_tab_text_hsl.l = kLightInactiveLuminance;
-
-  if (inactive_tab_text_hsl.s < 0.5)
-    inactive_tab_text_hsl.s = kHeavyInactiveSaturation;
-  else
-    inactive_tab_text_hsl.s = kLightInactiveSaturation;
-
-  colors_[BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT] =
-      color_utils::HSLToSkColor(inactive_tab_text_hsl, 255);
-
-  // We pick the text and background colors for the NTP out of the colors for a
-  // GtkEntry. We do this because GtkEntries background color is never the same
-  // as |toolbar_color|, is usually a white, and when it isn't a white,
-  // provides sufficient contrast to |toolbar_color|. Try this out with
-  // Darklooks, HighContrastInverse or ThinIce.
-  GtkStyle* entry_style = gtk_rc_get_style(fake_entry_.get());
-  GdkColor ntp_background = entry_style->base[GTK_STATE_NORMAL];
-  GdkColor ntp_foreground = entry_style->text[GTK_STATE_NORMAL];
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_BACKGROUND,
-                       &ntp_background);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_TEXT,
-                       &ntp_foreground);
-
-  // The NTP header is the color that surrounds the current active thumbnail on
-  // the NTP, and acts as the border of the "Recent Links" box. It would be
-  // awesome if they were separated so we could use GetBorderColor() for the
-  // border around the "Recent Links" section, but matching the frame color is
-  // more important.
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_HEADER,
-                       &frame_color);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION,
-                       &toolbar_color);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION_TEXT,
-                       &label_color);
-
-  // Override the link color if the theme provides it.
-  const GdkColor* link_color = NULL;
-  gtk_widget_style_get(GTK_WIDGET(fake_window_),
-                       "link-color", &link_color, NULL);
-  if (!link_color)
-    link_color = &kDefaultLinkColor;
-
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_LINK,
-                       link_color);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE,
-                       link_color);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION_LINK,
-                       link_color);
-  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE,
-                       link_color);
-
-  // Generate the colors that we pass to WebKit.
-  focus_ring_color_ = GdkToSkColor(&frame_color);
-  GdkColor thumb_active_color, thumb_inactive_color, track_color;
-  GtkThemeProvider::GetScrollbarColors(&thumb_active_color,
-                                       &thumb_inactive_color,
-                                       &track_color);
-  thumb_active_color_ = GdkToSkColor(&thumb_active_color);
-  thumb_inactive_color_ = GdkToSkColor(&thumb_inactive_color);
-  track_color_ = GdkToSkColor(&track_color);
-
-  // Some GTK themes only define the text selection colors on the GtkEntry
-  // class, so we need to use that for getting selection colors.
-  active_selection_bg_color_ =
-      GdkToSkColor(&entry_style->base[GTK_STATE_SELECTED]);
-  active_selection_fg_color_ =
-      GdkToSkColor(&entry_style->text[GTK_STATE_SELECTED]);
-  inactive_selection_bg_color_ =
-      GdkToSkColor(&entry_style->base[GTK_STATE_ACTIVE]);
-  inactive_selection_fg_color_ =
-      GdkToSkColor(&entry_style->text[GTK_STATE_ACTIVE]);
-}
-
-GdkColor GtkThemeProvider::BuildFrameColors(GtkStyle* frame_style) {
-  const GdkColor* theme_frame = NULL;
-  const GdkColor* theme_inactive_frame = NULL;
-  const GdkColor* theme_incognito_frame = NULL;
-  const GdkColor* theme_incognito_inactive_frame = NULL;
-  gtk_widget_style_get(GTK_WIDGET(fake_frame_),
-                       "frame-color", &theme_frame,
-                       "inactive-frame-color", &theme_inactive_frame,
-                       "incognito-frame-color", &theme_incognito_frame,
-                       "incognito-inactive-frame-color",
-                       &theme_incognito_inactive_frame,
-                       NULL);
-
-  GdkColor frame_color = BuildAndSetFrameColor(
-      &frame_style->bg[GTK_STATE_SELECTED],
-      theme_frame,
-      kDefaultFrameShift,
-      BrowserThemeProvider::COLOR_FRAME,
-      BrowserThemeProvider::TINT_FRAME);
-  SetThemeTintFromGtk(BrowserThemeProvider::TINT_BACKGROUND_TAB, &frame_color);
-
-  BuildAndSetFrameColor(
-      &frame_style->bg[GTK_STATE_INSENSITIVE],
-      theme_inactive_frame,
-      kDefaultFrameShift,
-      BrowserThemeProvider::COLOR_FRAME_INACTIVE,
-      BrowserThemeProvider::TINT_FRAME_INACTIVE);
-
-  BuildAndSetFrameColor(
-      &frame_color,
-      theme_incognito_frame,
-      GetDefaultTint(BrowserThemeProvider::TINT_FRAME_INCOGNITO),
-      BrowserThemeProvider::COLOR_FRAME_INCOGNITO,
-      BrowserThemeProvider::TINT_FRAME_INCOGNITO);
-
-  BuildAndSetFrameColor(
-      &frame_color,
-      theme_incognito_inactive_frame,
-      GetDefaultTint(BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE),
-      BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE,
-      BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE);
-
-  return frame_color;
-}
-
-void GtkThemeProvider::LoadDefaultValues() {
-  focus_ring_color_ = SkColorSetARGB(255, 229, 151, 0);
-  thumb_active_color_ = SkColorSetRGB(244, 244, 244);
-  thumb_inactive_color_ = SkColorSetRGB(234, 234, 234);
-  track_color_ = SkColorSetRGB(211, 211, 211);
-
-  active_selection_bg_color_ = SkColorSetRGB(30, 144, 255);
-  active_selection_fg_color_ = SK_ColorWHITE;
-  inactive_selection_bg_color_ = SkColorSetRGB(200, 200, 200);
-  inactive_selection_fg_color_ = SkColorSetRGB(50, 50, 50);
-}
-
-void GtkThemeProvider::RebuildMenuIconSets() {
-  FreeIconSets();
-
-  GtkStyle* style = gtk_rc_get_style(fake_menu_item_.get());
-
-  fullscreen_icon_set_ = gtk_icon_set_new();
-  BuildIconFromIDRWithColor(IDR_FULLSCREEN_MENU_BUTTON,
-                            style,
-                            GTK_STATE_PRELIGHT,
-                            fullscreen_icon_set_);
-  BuildIconFromIDRWithColor(IDR_FULLSCREEN_MENU_BUTTON,
-                            style,
-                            GTK_STATE_NORMAL,
-                            fullscreen_icon_set_);
-}
-
-void GtkThemeProvider::SetThemeColorFromGtk(int id, const GdkColor* color) {
-  colors_[id] = GdkToSkColor(color);
-}
-
-void GtkThemeProvider::SetThemeTintFromGtk(int id, const GdkColor* color) {
-  color_utils::HSL default_tint = GetDefaultTint(id);
-  color_utils::HSL hsl;
-  color_utils::SkColorToHSL(GdkToSkColor(color), &hsl);
-
-  if (default_tint.s != -1)
-    hsl.s = default_tint.s;
-
-  if (default_tint.l != -1)
-    hsl.l = default_tint.l;
-
-  tints_[id] = hsl;
-}
-
-GdkColor GtkThemeProvider::BuildAndSetFrameColor(const GdkColor* base,
-                                                 const GdkColor* gtk_base,
-                                                 const color_utils::HSL& tint,
-                                                 int color_id,
-                                                 int tint_id) {
-  GdkColor out_color = *base;
-  if (gtk_base) {
-    // The theme author specified a color to use, use it without modification.
-    out_color = *gtk_base;
-  } else {
-    // Tint the basic color since this is a heuristic color instead of one
-    // specified by the theme author.
-    GdkColorHSLShift(tint, &out_color);
-  }
-  SetThemeColorFromGtk(color_id, &out_color);
-  SetThemeTintFromGtk(tint_id, &out_color);
-
-  return out_color;
-}
-
-void GtkThemeProvider::FreePerDisplaySurfaces(
-    PerDisplaySurfaceMap* per_display_map) {
-  for (PerDisplaySurfaceMap::iterator it = per_display_map->begin();
-       it != per_display_map->end(); ++it) {
-    for (CairoCachedSurfaceMap::iterator jt = it->second.begin();
-         jt != it->second.end(); ++jt) {
-      delete jt->second;
-    }
-  }
-  per_display_map->clear();
-}
-
-void GtkThemeProvider::FreeIconSets() {
-  if (fullscreen_icon_set_) {
-    gtk_icon_set_unref(fullscreen_icon_set_);
-    fullscreen_icon_set_ = NULL;
-  }
-}
-
-SkBitmap* GtkThemeProvider::GenerateGtkThemeBitmap(int id) const {
-  switch (id) {
-    case IDR_THEME_TOOLBAR: {
-      GtkStyle* style = gtk_rc_get_style(fake_window_);
-      GdkColor* color = &style->bg[GTK_STATE_NORMAL];
-      SkBitmap* bitmap = new SkBitmap;
-      bitmap->setConfig(SkBitmap::kARGB_8888_Config,
-                        kToolbarImageWidth, kToolbarImageHeight);
-      bitmap->allocPixels();
-      bitmap->eraseRGB(color->red >> 8, color->green >> 8, color->blue >> 8);
-      return bitmap;
-    }
-    case IDR_THEME_TAB_BACKGROUND:
-      return GenerateTabImage(IDR_THEME_FRAME);
-    case IDR_THEME_TAB_BACKGROUND_INCOGNITO:
-      return GenerateTabImage(IDR_THEME_FRAME_INCOGNITO);
-    case IDR_THEME_FRAME:
-      return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME,
-                                "frame-gradient-color");
-    case IDR_THEME_FRAME_INACTIVE:
-      return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME_INACTIVE,
-                                "inactive-frame-gradient-color");
-    case IDR_THEME_FRAME_INCOGNITO:
-      return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME_INCOGNITO,
-                                "incognito-frame-gradient-color");
-    case IDR_THEME_FRAME_INCOGNITO_INACTIVE: {
-      return GenerateFrameImage(
-          BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE,
-          "incognito-inactive-frame-gradient-color");
-    }
-    // Icons that sit inside the omnibox shouldn't receive TINT_BUTTONS and
-    // instead should tint based on the foreground text entry color in GTK+
-    // mode because some themes that try to be dark *and* light have very
-    // different colors between the omnibox and the normal background area.
-    case IDR_OMNIBOX_HISTORY:
-    case IDR_OMNIBOX_HTTP:
-    case IDR_OMNIBOX_MORE:
-    case IDR_OMNIBOX_SEARCH:
-    case IDR_OMNIBOX_STAR:
-    case IDR_GEOLOCATION_ALLOWED_LOCATIONBAR_ICON:
-    case IDR_GEOLOCATION_DENIED_LOCATIONBAR_ICON: {
-      return GenerateTintedIcon(id, entry_tint_);
-    }
-    // In GTK mode, the dark versions of the omnibox icons only ever appear in
-    // the autocomplete popup and only against the current theme's GtkEntry
-    // base[GTK_STATE_SELECTED] color, so tint the icons so they won't collide
-    // with the selected color.
-    case IDR_OMNIBOX_HISTORY_DARK:
-    case IDR_OMNIBOX_HTTP_DARK:
-    case IDR_OMNIBOX_MORE_DARK:
-    case IDR_OMNIBOX_SEARCH_DARK:
-    case IDR_OMNIBOX_STAR_DARK: {
-      return GenerateTintedIcon(id, selected_entry_tint_);
-    }
-    default: {
-      return GenerateTintedIcon(id, button_tint_);
-    }
-  }
-}
-
-SkBitmap* GtkThemeProvider::GenerateFrameImage(
-    int color_id,
-    const char* gradient_name) const {
-  // We use two colors: the main color (passed in) and a lightened version of
-  // that color (which is supposed to match the light gradient at the top of
-  // several GTK+ themes, such as Ambiance, Clearlooks or Bluebird).
-  ColorMap::const_iterator it = colors_.find(color_id);
-  DCHECK(it != colors_.end());
-  SkColor base = it->second;
-
-  gfx::CanvasSkia canvas(kToolbarImageWidth, kToolbarImageHeight, true);
-
-  int gradient_size;
-  const GdkColor* gradient_top_color = NULL;
-  gtk_widget_style_get(GTK_WIDGET(fake_frame_),
-                       "frame-gradient-size", &gradient_size,
-                       gradient_name, &gradient_top_color,
-                       NULL);
-  if (gradient_size) {
-    SkColor lighter = gradient_top_color ? GdkToSkColor(gradient_top_color)
-                      : color_utils::HSLShift(base, kGtkFrameShift);
-    SkShader* shader = gfx::CreateGradientShader(
-        0, gradient_size, lighter, base);
-    SkPaint paint;
-    paint.setStyle(SkPaint::kFill_Style);
-    paint.setAntiAlias(true);
-    paint.setShader(shader);
-    shader->unref();
-
-    canvas.DrawRectInt(0, 0, kToolbarImageWidth, gradient_size, paint);
-  }
-
-  canvas.FillRectInt(base, 0, gradient_size,
-                     kToolbarImageWidth,
-                     kToolbarImageHeight - gradient_size);
-  return new SkBitmap(canvas.ExtractBitmap());
-}
-
-SkBitmap* GtkThemeProvider::GenerateTabImage(int base_id) const {
-  SkBitmap* base_image = GetBitmapNamed(base_id);
-  SkBitmap bg_tint = SkBitmapOperations::CreateHSLShiftedBitmap(
-      *base_image, GetTint(BrowserThemeProvider::TINT_BACKGROUND_TAB));
-  return new SkBitmap(SkBitmapOperations::CreateTiledBitmap(
-      bg_tint, 0, 0, bg_tint.width(), bg_tint.height()));
-}
-
-SkBitmap* GtkThemeProvider::GenerateTintedIcon(int base_id,
-                                               color_utils::HSL tint) const {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  scoped_ptr<SkBitmap> button(new SkBitmap(*rb.GetBitmapNamed(base_id)));
-  return new SkBitmap(SkBitmapOperations::CreateHSLShiftedBitmap(
-      *button, tint));
-}
-
-void GtkThemeProvider::GetNormalButtonTintHSL(
-    color_utils::HSL* tint) const {
-  GtkStyle* window_style = gtk_rc_get_style(fake_window_);
-  const GdkColor accent_gdk_color = window_style->bg[GTK_STATE_SELECTED];
-  const GdkColor base_color = window_style->base[GTK_STATE_NORMAL];
-
-  GtkStyle* label_style = gtk_rc_get_style(fake_label_.get());
-  const GdkColor text_color = label_style->fg[GTK_STATE_NORMAL];
-
-  PickButtonTintFromColors(accent_gdk_color, text_color, base_color, tint);
-}
-
-void GtkThemeProvider::GetNormalEntryForegroundHSL(
-    color_utils::HSL* tint) const {
-  GtkStyle* window_style = gtk_rc_get_style(fake_window_);
-  const GdkColor accent_gdk_color = window_style->bg[GTK_STATE_SELECTED];
-
-  GtkStyle* style = gtk_rc_get_style(fake_entry_.get());
-  const GdkColor text_color = style->text[GTK_STATE_NORMAL];
-  const GdkColor base_color = style->base[GTK_STATE_NORMAL];
-
-  PickButtonTintFromColors(accent_gdk_color, text_color, base_color, tint);
-}
-
-void GtkThemeProvider::GetSelectedEntryForegroundHSL(
-    color_utils::HSL* tint) const {
-  // The simplest of all the tints. We just use the selected text in the entry
-  // since the icons tinted this way will only be displayed against
-  // base[GTK_STATE_SELECTED].
-  GtkStyle* style = gtk_rc_get_style(fake_entry_.get());
-  const GdkColor color = style->text[GTK_STATE_SELECTED];
-  color_utils::SkColorToHSL(GdkToSkColor(&color), tint);
-}
-
-CairoCachedSurface* GtkThemeProvider::GetSurfaceNamedImpl(
-    int id,
-    PerDisplaySurfaceMap* display_surface_map,
-    GdkPixbuf* pixbuf,
-    GtkWidget* widget_on_display) {
-  GdkDisplay* display = gtk_widget_get_display(widget_on_display);
-  CairoCachedSurfaceMap& surface_map = (*display_surface_map)[display];
-
-  // Check to see if we already have the pixbuf in the cache.
-  CairoCachedSurfaceMap::const_iterator found = surface_map.find(id);
-  if (found != surface_map.end())
-    return found->second;
-
-  CairoCachedSurface* surface = new CairoCachedSurface;
-  surface->UsePixbuf(pixbuf);
-
-  surface_map[id] = surface;
-
-  return surface;
-}
-
-void GtkThemeProvider::OnDestroyChromeButton(GtkWidget* button) {
-  std::vector<GtkWidget*>::iterator it =
-      find(chrome_buttons_.begin(), chrome_buttons_.end(), button);
-  if (it != chrome_buttons_.end())
-    chrome_buttons_.erase(it);
-}
-
-gboolean GtkThemeProvider::OnSeparatorExpose(GtkWidget* widget,
-                                             GdkEventExpose* event) {
-  if (UseGtkTheme())
-    return FALSE;
-
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-
-  GdkColor bottom_color = GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
-  double bottom_color_rgb[] = {
-      static_cast<double>(bottom_color.red / 257) / 255.0,
-      static_cast<double>(bottom_color.green / 257) / 255.0,
-      static_cast<double>(bottom_color.blue / 257) / 255.0, };
-
-  cairo_pattern_t* pattern =
-      cairo_pattern_create_linear(widget->allocation.x, widget->allocation.y,
-                                  widget->allocation.x,
-                                  widget->allocation.y +
-                                  widget->allocation.height);
-  cairo_pattern_add_color_stop_rgb(
-      pattern, 0.0,
-      kTopSeparatorColor[0], kTopSeparatorColor[1], kTopSeparatorColor[2]);
-  cairo_pattern_add_color_stop_rgb(
-      pattern, 0.5,
-      kMidSeparatorColor[0], kMidSeparatorColor[1], kMidSeparatorColor[2]);
-  cairo_pattern_add_color_stop_rgb(
-      pattern, 1.0,
-      bottom_color_rgb[0], bottom_color_rgb[1], bottom_color_rgb[2]);
-  cairo_set_source(cr, pattern);
-
-  double start_x = 0.5 + widget->allocation.x;
-  cairo_new_path(cr);
-  cairo_set_line_width(cr, 1.0);
-  cairo_move_to(cr, start_x, widget->allocation.y);
-  cairo_line_to(cr, start_x,
-                    widget->allocation.y + widget->allocation.height);
-  cairo_stroke(cr);
-  cairo_destroy(cr);
-  cairo_pattern_destroy(pattern);
-
-  return TRUE;
-}
diff --git a/chrome/browser/gtk/gtk_theme_provider.h b/chrome/browser/gtk/gtk_theme_provider.h
deleted file mode 100644
index 39233a3..0000000
--- a/chrome/browser/gtk/gtk_theme_provider.h
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_THEME_PROVIDER_H_
-#define CHROME_BROWSER_GTK_GTK_THEME_PROVIDER_H_
-#pragma once
-
-#include <map>
-#include <vector>
-
-#include "app/gtk_integers.h"
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/prefs/pref_change_registrar.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/common/notification_observer.h"
-#include "gfx/color_utils.h"
-
-class CairoCachedSurface;
-class GtkSignalRegistrar;
-class Profile;
-
-typedef struct _GdkDisplay GdkDisplay;
-typedef struct _GdkEventExpose GdkEventExpose;
-typedef struct _GdkPixbuf GdkPixbuf;
-typedef struct _GtkIconSet GtkIconSet;
-typedef struct _GtkStyle GtkStyle;
-typedef struct _GtkWidget GtkWidget;
-
-// Specialization of BrowserThemeProvider which supplies system colors.
-class GtkThemeProvider : public BrowserThemeProvider,
-                         public NotificationObserver {
- public:
-  // Returns GtkThemeProvider, casted from our superclass.
-  static GtkThemeProvider* GetFrom(Profile* profile);
-
-  GtkThemeProvider();
-  virtual ~GtkThemeProvider();
-
-  // Calls |observer|.Observe() for the browser theme with this provider as the
-  // source.
-  void InitThemesFor(NotificationObserver* observer);
-
-  // Overridden from BrowserThemeProvider:
-  //
-  // Sets that we aren't using the system theme, then calls
-  // BrowserThemeProvider's implementation.
-  virtual void Init(Profile* profile);
-  virtual SkBitmap* GetBitmapNamed(int id) const;
-  virtual SkColor GetColor(int id) const;
-  virtual bool HasCustomImage(int id) const;
-  virtual void SetTheme(const Extension* extension);
-  virtual void UseDefaultTheme();
-  virtual void SetNativeTheme();
-  virtual bool UsingDefaultTheme();
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Creates a GtkChromeButton instance, registered with this theme provider,
-  // with a "destroy" signal to remove it from our internal list when it goes
-  // away.
-  GtkWidget* BuildChromeButton();
-
-  // Creates a theme-aware vertical separator widget.
-  GtkWidget* CreateToolbarSeparator();
-
-  // Whether we should use the GTK system theme.
-  bool UseGtkTheme() const;
-
-  // A wrapper around ThemeProvider::GetColor, transforming the result to a
-  // GdkColor.
-  GdkColor GetGdkColor(int id) const;
-
-  // A weighted average between the text color and the background color of a
-  // label. Used for borders between GTK stuff and the webcontent.
-  GdkColor GetBorderColor() const;
-
-  // Returns a set of icons tinted for different GtkStateTypes based on the
-  // label colors for the IDR resource |id|.
-  GtkIconSet* GetIconSetForId(int id) const;
-
-  // This method returns the colors webkit will use for the scrollbars. When no
-  // colors are specified by the GTK+ theme, this function averages of the
-  // thumb part and of the track colors.
-  void GetScrollbarColors(GdkColor* thumb_active_color,
-                          GdkColor* thumb_inactive_color,
-                          GdkColor* track_color);
-
-  // Expose the inner label. Only used for testing.
-  GtkWidget* fake_label() { return fake_label_.get(); }
-
-  // Returns a CairoCachedSurface for a particular Display. CairoCachedSurfaces
-  // (hopefully) live on the X server, instead of the client so we don't have
-  // to send the image to the server on each expose.
-  CairoCachedSurface* GetSurfaceNamed(int id, GtkWidget* widget_on_display);
-
-  // Same as above, but auto-mirrors the underlying pixbuf in RTL mode.
-  CairoCachedSurface* GetRTLEnabledSurfaceNamed(int id,
-                                                GtkWidget* widget_on_display);
-
-  // Same as above, but gets the resource from the ResourceBundle instead of the
-  // BrowserThemeProvider.
-  // NOTE: Never call this with resource IDs that are ever passed to the above
-  // two functions!  Depending on which call comes first, all callers will
-  // either get the themed or the unthemed version.
-  CairoCachedSurface* GetUnthemedSurfaceNamed(int id,
-                                              GtkWidget* widget_on_display);
-
-  // Returns colors that we pass to webkit to match the system theme.
-  const SkColor& get_focus_ring_color() const { return focus_ring_color_; }
-  const SkColor& get_thumb_active_color() const { return thumb_active_color_; }
-  const SkColor& get_thumb_inactive_color() const {
-    return thumb_inactive_color_;
-  }
-  const SkColor& get_track_color() const { return track_color_; }
-  const SkColor& get_active_selection_bg_color() const {
-    return active_selection_bg_color_;
-  }
-  const SkColor& get_active_selection_fg_color() const {
-    return active_selection_fg_color_;
-  }
-  const SkColor& get_inactive_selection_bg_color() const {
-    return inactive_selection_bg_color_;
-  }
-  const SkColor& get_inactive_selection_fg_color() const {
-    return inactive_selection_fg_color_;
-  }
-
-  // These functions do not add a ref to the returned pixbuf, and it should not
-  // be unreffed.  If |native| is true, get the GTK_STOCK version of the icon.
-  static GdkPixbuf* GetFolderIcon(bool native);
-  static GdkPixbuf* GetDefaultFavicon(bool native);
-
-  // Whether we use the GTK theme by default in the current desktop
-  // environment. Returns true when we GTK defaults to on.
-  static bool DefaultUsesSystemTheme();
-
- private:
-  typedef std::map<int, SkColor> ColorMap;
-  typedef std::map<int, color_utils::HSL> TintMap;
-  typedef std::map<int, SkBitmap*> ImageCache;
-  typedef std::map<int, CairoCachedSurface*> CairoCachedSurfaceMap;
-  typedef std::map<GdkDisplay*, CairoCachedSurfaceMap> PerDisplaySurfaceMap;
-
-  // Clears all the GTK color overrides.
-  virtual void ClearAllThemeData();
-
-  // Load theme data from preferences, possibly picking colors from GTK.
-  virtual void LoadThemePrefs();
-
-  // Let all the browser views know that themes have changed.
-  virtual void NotifyThemeChanged(const Extension* extension);
-
-  // Additionally frees the CairoCachedSurfaces.
-  virtual void FreePlatformCaches();
-
-  // Extracts colors and tints from the GTK theme, both for the
-  // BrowserThemeProvider interface and the colors we send to webkit.
-  void LoadGtkValues();
-
-  // Reads in explicit theme frame colors from the ChromeGtkFrame style class
-  // or generates them per our fallback algorithm.
-  GdkColor BuildFrameColors(GtkStyle* frame_style);
-
-  // Sets the values that we send to webkit to safe defaults.
-  void LoadDefaultValues();
-
-  // Builds all of the tinted menus images needed for custom buttons. This is
-  // always called on style-set even if we aren't using the gtk-theme because
-  // the menus are always rendered with gtk colors.
-  void RebuildMenuIconSets();
-
-  // Sets the underlying theme colors/tints from a GTK color.
-  void SetThemeColorFromGtk(int id, const GdkColor* color);
-  void SetThemeTintFromGtk(int id, const GdkColor* color);
-
-  // Creates and returns a frame color, either using |gtk_base| verbatim if
-  // non-NULL, or tinting |base| with |tint|. Also sets |color_id| and
-  // |tint_id| to the returned color.
-  GdkColor BuildAndSetFrameColor(const GdkColor* base,
-                                 const GdkColor* gtk_base,
-                                 const color_utils::HSL& tint,
-                                 int color_id,
-                                 int tint_id);
-
-  // Split out from FreePlatformCaches so it can be called in our destructor;
-  // FreePlatformCaches() is called from the BrowserThemeProvider's destructor,
-  // but by the time ~BrowserThemeProvider() is run, the vtable no longer
-  // points to GtkThemeProvider's version.
-  void FreePerDisplaySurfaces(PerDisplaySurfaceMap* per_display_map);
-
-  // Frees all the created GtkIconSets we use for the chrome menu.
-  void FreeIconSets();
-
-  // Lazily generates each bitmap used in the gtk theme.
-  SkBitmap* GenerateGtkThemeBitmap(int id) const;
-
-  // Creates a GTK+ version of IDR_THEME_FRAME. Instead of tinting, this
-  // creates a theme configurable gradient ending with |color_id| at the
-  // bottom, and |gradient_name| at the top if that color is specified in the
-  // theme.
-  SkBitmap* GenerateFrameImage(int color_id,
-                               const char* gradient_name) const;
-
-  // Takes the base frame image |base_id| and tints it with |tint_id|.
-  SkBitmap* GenerateTabImage(int base_id) const;
-
-  // Tints an icon based on tint.
-  SkBitmap* GenerateTintedIcon(int base_id, color_utils::HSL tint) const;
-
-  // Returns the tint for buttons that contrasts with the normal window
-  // background color.
-  void GetNormalButtonTintHSL(color_utils::HSL* tint) const;
-
-  // Returns a tint that's the color of the current normal text in an entry.
-  void GetNormalEntryForegroundHSL(color_utils::HSL* tint) const;
-
-  // Returns a tint that's the color of the current highlighted text in an
-  // entry.
-  void GetSelectedEntryForegroundHSL(color_utils::HSL* tint) const;
-
-  // Implements GetXXXSurfaceNamed(), given the appropriate pixbuf to use.
-  CairoCachedSurface* GetSurfaceNamedImpl(int id,
-                                          PerDisplaySurfaceMap* surface_map,
-                                          GdkPixbuf* pixbuf,
-                                          GtkWidget* widget_on_display);
-
-  // Handles signal from GTK that our theme has been changed.
-  CHROMEGTK_CALLBACK_1(GtkThemeProvider, void, OnStyleSet, GtkStyle*);
-
-  // A notification from the GtkChromeButton GObject destructor that we should
-  // remove it from our internal list.
-  CHROMEGTK_CALLBACK_0(GtkThemeProvider, void, OnDestroyChromeButton);
-
-  CHROMEGTK_CALLBACK_1(GtkThemeProvider, gboolean, OnSeparatorExpose,
-                       GdkEventExpose*);
-
-  // Whether we should be using gtk rendering.
-  bool use_gtk_;
-
-  // GtkWidgets that exist only so we can look at their properties (and take
-  // their colors).
-  GtkWidget* fake_window_;
-  GtkWidget* fake_frame_;
-  OwnedWidgetGtk fake_label_;
-  OwnedWidgetGtk fake_entry_;
-  OwnedWidgetGtk fake_menu_item_;
-
-  // A list of all GtkChromeButton instances. We hold on to these to notify
-  // them of theme changes.
-  std::vector<GtkWidget*> chrome_buttons_;
-
-  // Tracks all the signals we have connected to on various widgets.
-  scoped_ptr<GtkSignalRegistrar> signals_;
-
-  // Tints and colors calculated by LoadGtkValues() that are given to the
-  // caller while |use_gtk_| is true.
-  ColorMap colors_;
-  TintMap tints_;
-
-  // Colors used to tint certain icons.
-  color_utils::HSL button_tint_;
-  color_utils::HSL entry_tint_;
-  color_utils::HSL selected_entry_tint_;
-
-  // Colors that we pass to WebKit. These are generated each time the theme
-  // changes.
-  SkColor focus_ring_color_;
-  SkColor thumb_active_color_;
-  SkColor thumb_inactive_color_;
-  SkColor track_color_;
-  SkColor active_selection_bg_color_;
-  SkColor active_selection_fg_color_;
-  SkColor inactive_selection_bg_color_;
-  SkColor inactive_selection_fg_color_;
-
-  // A GtkIconSet that has the tinted icons for the NORMAL and PRELIGHT states
-  // of the IDR_FULLSCREEN_MENU_BUTTON tinted to the respective menu item label
-  // colors.
-  GtkIconSet* fullscreen_icon_set_;
-
-  // Image cache of lazily created images, created when requested by
-  // GetBitmapNamed().
-  mutable ImageCache gtk_images_;
-
-  // Cairo surfaces for each GdkDisplay.
-  PerDisplaySurfaceMap per_display_surfaces_;
-  PerDisplaySurfaceMap per_display_unthemed_surfaces_;
-
-  PrefChangeRegistrar registrar_;
-
-  // This is a dummy widget that only exists so we have something to pass to
-  // gtk_widget_render_icon().
-  static GtkWidget* icon_widget_;
-
-  // The default folder icon and default bookmark icon for the GTK theme.
-  // These are static because the system can only have one theme at a time.
-  // They are cached when they are requested the first time, and cleared when
-  // the system theme changes.
-  static GdkPixbuf* default_folder_icon_;
-  static GdkPixbuf* default_bookmark_icon_;
-};
-
-#endif  // CHROME_BROWSER_GTK_GTK_THEME_PROVIDER_H_
diff --git a/chrome/browser/gtk/gtk_theme_provider_unittest.cc b/chrome/browser/gtk/gtk_theme_provider_unittest.cc
deleted file mode 100644
index e2a7272..0000000
--- a/chrome/browser/gtk/gtk_theme_provider_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/testing_profile.h"
-#include "grit/theme_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Converts a GdkColor to a SkColor.
-SkColor GdkToSkColor(GdkColor* color) {
-  return SkColorSetRGB(color->red >> 8,
-                       color->green >> 8,
-                       color->blue >> 8);
-}
-
-}  // namespace
-
-class GtkThemeProviderTest : public testing::Test {
- public:
-  GtkThemeProviderTest() : provider_(NULL) {}
-
-  void SetUseGtkTheme(bool use_gtk_theme) {
-    profile_.GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, use_gtk_theme);
-  }
-
-  void BuildProvider() {
-    profile_.InitThemes();
-    provider_ = GtkThemeProvider::GetFrom(&profile_);
-  }
-
- protected:
-  TestingProfile profile_;
-
-  GtkThemeProvider* provider_;
-};
-
-TEST_F(GtkThemeProviderTest, DefaultValues) {
-  SetUseGtkTheme(false);
-  BuildProvider();
-
-  // Test that we get the default theme colors back when in normal mode.
-  for (int i = BrowserThemeProvider::COLOR_FRAME;
-       i <= BrowserThemeProvider::COLOR_BUTTON_BACKGROUND; ++i) {
-    EXPECT_EQ(provider_->GetColor(i), BrowserThemeProvider::GetDefaultColor(i))
-        << "Wrong default color for " << i;
-  }
-}
-
-TEST_F(GtkThemeProviderTest, UsingGtkValues) {
-  SetUseGtkTheme(true);
-  BuildProvider();
-
-  // This test only verifies that we're using GTK values. Because of Gtk's
-  // large, implied global state, it would take some IN_PROCESS_BROWSER_TESTS
-  // to write an equivalent of DefaultValues above in a way that wouldn't make
-  // other tests flaky. kColorTabText is the only simple path where there's no
-  // weird calculations for edge cases so use that as a simple test.
-  GtkWidget* fake_label = provider_->fake_label();
-  GtkStyle* label_style = gtk_rc_get_style(fake_label);
-  GdkColor label_color = label_style->fg[GTK_STATE_NORMAL];
-  EXPECT_EQ(provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT),
-            GdkToSkColor(&label_color));
-}
diff --git a/chrome/browser/gtk/gtk_tree.cc b/chrome/browser/gtk/gtk_tree.cc
deleted file mode 100644
index 46307da..0000000
--- a/chrome/browser/gtk/gtk_tree.cc
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_tree.h"
-
-#include "app/table_model.h"
-#include "base/logging.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "gfx/gtk_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace gtk_tree {
-
-gint GetRowNumForPath(GtkTreePath* path) {
-  gint* indices = gtk_tree_path_get_indices(path);
-  if (!indices) {
-    NOTREACHED();
-    return -1;
-  }
-  return indices[0];
-}
-
-gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) {
-  GtkTreePath* path = gtk_tree_model_get_path(model, iter);
-  int row = GetRowNumForPath(path);
-  gtk_tree_path_free(path);
-  return row;
-}
-
-gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
-                                   GtkTreePath* sort_path) {
-  GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path(
-      GTK_TREE_MODEL_SORT(sort_model), sort_path);
-  int row = GetRowNumForPath(child_path);
-  gtk_tree_path_free(child_path);
-  return row;
-}
-
-void SelectAndFocusRowNum(int row, GtkTreeView* tree_view) {
-  GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
-  if (!model) {
-    NOTREACHED();
-    return;
-  }
-  GtkTreeIter iter;
-  if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) {
-    NOTREACHED();
-    return;
-  }
-  GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
-  gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE);
-  gtk_tree_path_free(path);
-}
-
-bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter) {
-  GtkTreeIter child;
-  if (gtk_tree_model_iter_children(GTK_TREE_MODEL(tree_store), &child, iter)) {
-    while (true) {
-      if (!RemoveRecursively(tree_store, &child))
-        break;
-    }
-  }
-  return gtk_tree_store_remove(tree_store, iter);
-}
-
-void GetSelectedIndices(GtkTreeSelection* selection, std::set<int>* out) {
-  GList* list = gtk_tree_selection_get_selected_rows(
-      selection, NULL);
-  GList* node;
-  for (node = list; node != NULL; node = node->next) {
-    out->insert(
-        gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(node->data)));
-  }
-  g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
-  g_list_free(list);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//  TableAdapter
-
-TableAdapter::TableAdapter(Delegate* delegate, GtkListStore* list_store,
-                           TableModel* table_model)
-    : delegate_(delegate), list_store_(list_store), table_model_(table_model) {
-  if (table_model)
-    table_model->SetObserver(this);
-}
-
-void TableAdapter::SetModel(TableModel* table_model) {
-  table_model_ = table_model;
-  table_model_->SetObserver(this);
-}
-
-bool TableAdapter::IsGroupRow(GtkTreeIter* iter) const {
-  if (!table_model_->HasGroups())
-    return false;
-  gboolean is_header = false;
-  gboolean is_separator = false;
-  gtk_tree_model_get(GTK_TREE_MODEL(list_store_),
-                     iter,
-                     COL_IS_HEADER,
-                     &is_header,
-                     COL_IS_SEPARATOR,
-                     &is_separator,
-                     -1);
-  return is_header || is_separator;
-}
-
-static int OffsetForGroupIndex(size_t group_index) {
-  // Every group consists of a header and a separator row, and there is a blank
-  // row between groups.
-  return 3 * group_index + 2;
-}
-
-void TableAdapter::MapListStoreIndicesToModelRows(
-    const std::set<int>& list_store_indices,
-    RemoveRowsTableModel::Rows* model_rows) {
-  if (!table_model_->HasGroups()) {
-    for (std::set<int>::const_iterator it = list_store_indices.begin();
-         it != list_store_indices.end();
-         ++it) {
-      model_rows->insert(*it);
-    }
-    return;
-  }
-
-  const TableModel::Groups& groups = table_model_->GetGroups();
-  TableModel::Groups::const_iterator group_it = groups.begin();
-  for (std::set<int>::const_iterator list_store_it = list_store_indices.begin();
-       list_store_it != list_store_indices.end();
-       ++list_store_it) {
-    int list_store_index = *list_store_it;
-    GtkTreeIter iter;
-    bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
-                                       &iter,
-                                       NULL,
-                                       list_store_index);
-    if (!rv) {
-      NOTREACHED();
-      return;
-    }
-    int group = -1;
-    gtk_tree_model_get(GTK_TREE_MODEL(list_store_),
-                       &iter,
-                       COL_GROUP_ID,
-                       &group,
-                       -1);
-    while (group_it->id != group) {
-      ++group_it;
-      if (group_it == groups.end()) {
-        NOTREACHED();
-        return;
-      }
-    }
-    int offset = OffsetForGroupIndex(group_it - groups.begin());
-    model_rows->insert(list_store_index - offset);
-  }
-}
-
-int TableAdapter::GetListStoreIndexForModelRow(int model_row) const {
-  if (!table_model_->HasGroups())
-    return model_row;
-  int group = table_model_->GetGroupID(model_row);
-  const TableModel::Groups& groups = table_model_->GetGroups();
-  for (TableModel::Groups::const_iterator it = groups.begin();
-       it != groups.end(); ++it) {
-    if (it->id == group) {
-      return model_row + OffsetForGroupIndex(it - groups.begin());
-    }
-  }
-  NOTREACHED();
-  return -1;
-}
-
-void TableAdapter::AddNodeToList(int row) {
-  GtkTreeIter iter;
-  int list_store_index = GetListStoreIndexForModelRow(row);
-  if (list_store_index == 0) {
-    gtk_list_store_prepend(list_store_, &iter);
-  } else {
-    GtkTreeIter sibling;
-    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling, NULL,
-                                  list_store_index - 1);
-    gtk_list_store_insert_after(list_store_, &iter, &sibling);
-  }
-
-  if (table_model_->HasGroups()) {
-    gtk_list_store_set(list_store_,
-                       &iter,
-                       COL_WEIGHT, PANGO_WEIGHT_NORMAL,
-                       COL_WEIGHT_SET, TRUE,
-                       COL_GROUP_ID, table_model_->GetGroupID(row),
-                       -1);
-  }
-  delegate_->SetColumnValues(row, &iter);
-}
-
-void TableAdapter::OnModelChanged() {
-  delegate_->OnAnyModelUpdateStart();
-  gtk_list_store_clear(list_store_);
-  delegate_->OnModelChanged();
-
-  if (table_model_->HasGroups()) {
-    const TableModel::Groups& groups = table_model_->GetGroups();
-    for (TableModel::Groups::const_iterator it = groups.begin();
-         it != groups.end(); ++it) {
-      GtkTreeIter iter;
-      if (it != groups.begin()) {
-        // Blank row between groups.
-        gtk_list_store_append(list_store_, &iter);
-        gtk_list_store_set(list_store_, &iter, COL_IS_HEADER, TRUE, -1);
-      }
-      // Group title.
-      gtk_list_store_append(list_store_, &iter);
-      gtk_list_store_set(list_store_,
-                         &iter,
-                         COL_WEIGHT,
-                         PANGO_WEIGHT_BOLD,
-                         COL_WEIGHT_SET,
-                         TRUE,
-                         COL_TITLE,
-                         UTF16ToUTF8(it->title).c_str(),
-                         COL_IS_HEADER,
-                         TRUE,
-                         -1);
-      // Group separator.
-      gtk_list_store_append(list_store_, &iter);
-      gtk_list_store_set(list_store_,
-                         &iter,
-                         COL_IS_HEADER,
-                         TRUE,
-                         COL_IS_SEPARATOR,
-                         TRUE,
-                         -1);
-    }
-  }
-
-  for (int i = 0; i < table_model_->RowCount(); ++i)
-    AddNodeToList(i);
-  delegate_->OnAnyModelUpdate();
-}
-
-void TableAdapter::OnItemsChanged(int start, int length) {
-  if (length == 0)
-    return;
-  delegate_->OnAnyModelUpdateStart();
-  int list_store_index = GetListStoreIndexForModelRow(start);
-  GtkTreeIter iter;
-  bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
-                                          &iter,
-                                          NULL,
-                                          list_store_index);
-  for (int i = 0; i < length; ++i) {
-    if (!rv) {
-      NOTREACHED();
-      return;
-    }
-    while (IsGroupRow(&iter)) {
-      rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
-      if (!rv) {
-        NOTREACHED();
-        return;
-      }
-    }
-    delegate_->SetColumnValues(start + i, &iter);
-    rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
-  }
-  delegate_->OnAnyModelUpdate();
-}
-
-void TableAdapter::OnItemsAdded(int start, int length) {
-  delegate_->OnAnyModelUpdateStart();
-  for (int i = 0; i < length; ++i) {
-    AddNodeToList(start + i);
-  }
-  delegate_->OnAnyModelUpdate();
-}
-
-void TableAdapter::OnItemsRemoved(int start, int length) {
-  if (length == 0)
-    return;
-  delegate_->OnAnyModelUpdateStart();
-  // When this method is called, the model has already removed the items, so
-  // accessing items in the model from |start| on may not be possible anymore.
-  // Therefore we use the item right before that, if it exists.
-  int list_store_index = 0;
-  if (start > 0)
-    list_store_index = GetListStoreIndexForModelRow(start - 1) + 1;
-  GtkTreeIter iter;
-  bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
-                                          &iter,
-                                          NULL,
-                                          list_store_index);
-  if (!rv) {
-    NOTREACHED();
-    return;
-  }
-  for (int i = 0; i < length; ++i) {
-    while (IsGroupRow(&iter)) {
-      rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
-      if (!rv) {
-        NOTREACHED();
-        return;
-      }
-    }
-    gtk_list_store_remove(list_store_, &iter);
-  }
-  delegate_->OnAnyModelUpdate();
-}
-
-// static
-gboolean TableAdapter::OnCheckRowIsSeparator(GtkTreeModel* model,
-                                             GtkTreeIter* iter,
-                                             gpointer user_data) {
-  gboolean is_separator;
-  gtk_tree_model_get(model,
-                     iter,
-                     COL_IS_SEPARATOR,
-                     &is_separator,
-                     -1);
-  return is_separator;
-}
-
-// static
-gboolean TableAdapter::OnSelectionFilter(GtkTreeSelection* selection,
-                                         GtkTreeModel* model,
-                                         GtkTreePath* path,
-                                         gboolean path_currently_selected,
-                                         gpointer user_data) {
-  GtkTreeIter iter;
-  if (!gtk_tree_model_get_iter(model, &iter, path)) {
-    NOTREACHED();
-    return TRUE;
-  }
-  gboolean is_header;
-  gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1);
-  return !is_header;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//  TreeAdapter
-
-TreeAdapter::TreeAdapter(Delegate* delegate, TreeModel* tree_model)
-    : delegate_(delegate),
-      tree_model_(tree_model) {
-  tree_store_ = gtk_tree_store_new(COL_COUNT,
-                                   GDK_TYPE_PIXBUF,
-                                   G_TYPE_STRING,
-                                   G_TYPE_POINTER);
-  tree_model->AddObserver(this);
-
-  std::vector<SkBitmap> icons;
-  tree_model->GetIcons(&icons);
-  for (size_t i = 0; i < icons.size(); ++i) {
-    pixbufs_.push_back(gfx::GdkPixbufFromSkBitmap(&icons[i]));
-  }
-}
-
-TreeAdapter::~TreeAdapter() {
-  g_object_unref(tree_store_);
-  for (size_t i = 0; i < pixbufs_.size(); ++i)
-    g_object_unref(pixbufs_[i]);
-}
-
-void TreeAdapter::Init() {
-  gtk_tree_store_clear(tree_store_);
-  Fill(NULL, tree_model_->GetRoot());
-}
-
-
-TreeModelNode* TreeAdapter::GetNode(GtkTreeIter* iter) {
-  TreeModelNode* node;
-  gtk_tree_model_get(GTK_TREE_MODEL(tree_store_), iter,
-                     COL_NODE_PTR, &node,
-                     -1);
-  return node;
-}
-
-void TreeAdapter::FillRow(GtkTreeIter* iter, TreeModelNode* node) {
-  GdkPixbuf* pixbuf = NULL;
-  int icon_index = tree_model_->GetIconIndex(node);
-  if (icon_index >= 0 && icon_index < static_cast<int>(pixbufs_.size()))
-    pixbuf = pixbufs_[icon_index];
-  else
-    pixbuf = GtkThemeProvider::GetFolderIcon(true);
-  gtk_tree_store_set(tree_store_, iter,
-                     COL_ICON, pixbuf,
-                     COL_TITLE, UTF16ToUTF8(node->GetTitle()).c_str(),
-                     COL_NODE_PTR, node,
-                     -1);
-}
-
-void TreeAdapter::Fill(GtkTreeIter* parent_iter, TreeModelNode* parent_node) {
-  if (parent_iter)
-    FillRow(parent_iter, parent_node);
-  GtkTreeIter iter;
-  int child_count = tree_model_->GetChildCount(parent_node);
-  for (int i = 0; i < child_count; ++i) {
-    TreeModelNode* node = tree_model_->GetChild(parent_node, i);
-    gtk_tree_store_append(tree_store_, &iter, parent_iter);
-    Fill(&iter, node);
-  }
-}
-
-GtkTreePath* TreeAdapter::GetTreePath(TreeModelNode* node) {
-  GtkTreePath* path = gtk_tree_path_new();
-  TreeModelNode* parent = node;
-  while (parent) {
-    parent = tree_model_->GetParent(parent);
-    if (parent) {
-      int idx = tree_model_->IndexOfChild(parent, node);
-      gtk_tree_path_prepend_index(path, idx);
-      node = parent;
-    }
-  }
-  return path;
-}
-
-bool TreeAdapter::GetTreeIter(TreeModelNode* node, GtkTreeIter* iter) {
-  GtkTreePath* path = GetTreePath(node);
-  bool rv = false;
-  // Check the path ourselves since gtk_tree_model_get_iter prints a warning if
-  // given an empty path.  The path will be empty when it points to the root
-  // node and we are using SetRootShown(false).
-  if (gtk_tree_path_get_depth(path) > 0)
-    rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), iter, path);
-  gtk_tree_path_free(path);
-  return rv;
-}
-
-void TreeAdapter::TreeNodesAdded(TreeModel* model,
-                                 TreeModelNode* parent,
-                                 int start,
-                                 int count) {
-  delegate_->OnAnyModelUpdateStart();
-  GtkTreeIter parent_iter;
-  GtkTreeIter* parent_iter_ptr = NULL;
-  GtkTreeIter iter;
-  if (GetTreeIter(parent, &parent_iter))
-    parent_iter_ptr = &parent_iter;
-  for (int i = 0; i < count; ++i) {
-    gtk_tree_store_insert(tree_store_, &iter, parent_iter_ptr, start + i);
-    Fill(&iter, tree_model_->GetChild(parent, start + i));
-  }
-  delegate_->OnAnyModelUpdate();
-}
-
-void TreeAdapter::TreeNodesRemoved(TreeModel* model,
-                                   TreeModelNode* parent,
-                                   int start,
-                                   int count) {
-  delegate_->OnAnyModelUpdateStart();
-  GtkTreeIter iter;
-  GtkTreePath* path = GetTreePath(parent);
-  gtk_tree_path_append_index(path, start);
-  gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), &iter, path);
-  gtk_tree_path_free(path);
-  for (int i = 0; i < count; ++i) {
-    RemoveRecursively(tree_store_, &iter);
-  }
-  delegate_->OnAnyModelUpdate();
-}
-
-void TreeAdapter::TreeNodeChanged(TreeModel* model, TreeModelNode* node) {
-  delegate_->OnAnyModelUpdateStart();
-  GtkTreeIter iter;
-  if (GetTreeIter(node, &iter))
-    FillRow(&iter, node);
-  delegate_->OnAnyModelUpdate();
-}
-
-}  // namespace gtk_tree
diff --git a/chrome/browser/gtk/gtk_tree.h b/chrome/browser/gtk/gtk_tree.h
deleted file mode 100644
index ce4feee..0000000
--- a/chrome/browser/gtk/gtk_tree.h
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_TREE_H_
-#define CHROME_BROWSER_GTK_GTK_TREE_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <set>
-#include <vector>
-
-#include "app/table_model_observer.h"
-#include "app/tree_model.h"
-#include "base/basictypes.h"
-#include "chrome/browser/remove_rows_table_model.h"
-
-class TableModel;
-
-namespace gtk_tree {
-
-// Get the row number corresponding to |path|.
-gint GetRowNumForPath(GtkTreePath* path);
-
-// Get the row number corresponding to |iter|.
-gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter);
-
-// Get the row number in the child tree model corresponding to |sort_path| in
-// the parent tree model.
-gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
-                                   GtkTreePath* sort_path);
-
-// Select the given row by number.
-void SelectAndFocusRowNum(int row, GtkTreeView* tree_view);
-
-// Remove the row and all its children from the |tree_store|.  If there is a
-// following row, |iter| will be updated to point to the it and the return value
-// will be true, otherwise the return will be false and |iter| is no longer
-// valid.
-bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter);
-
-// Writes all the indexes of selected rows into |out|.
-void GetSelectedIndices(GtkTreeSelection* selection, std::set<int>* out);
-
-// A helper class for populating a GtkListStore from a TableModel.
-class TableAdapter : public TableModelObserver {
- public:
-
-  enum ColumnID {
-    COL_TITLE = 0,
-    COL_IS_HEADER,
-    COL_IS_SEPARATOR,
-    COL_GROUP_ID,
-    COL_WEIGHT,
-    COL_WEIGHT_SET,
-    COL_LAST_ID
-  };
-
-  class Delegate {
-   public:
-    // Should fill in the column and row.
-    virtual void SetColumnValues(int row, GtkTreeIter* iter) = 0;
-
-    // Called after any change to the TableModel but before the corresponding
-    // change to the GtkListStore.
-    virtual void OnAnyModelUpdateStart() {}
-
-    // Called after any change to the TableModel.
-    virtual void OnAnyModelUpdate() {}
-
-    // When the TableModel has been completely changed, called by OnModelChanged
-    // after clearing the list store.  Can be overriden by the delegate if it
-    // needs to do extra initialization before the list store is populated.
-    virtual void OnModelChanged() {}
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  // |table_model| may be NULL.
-  TableAdapter(Delegate* delegate,
-               GtkListStore* list_store,
-               TableModel* table_model);
-  virtual ~TableAdapter() {}
-
-  // Replace the TableModel with a different one.  If the list store currenty
-  // has items this would cause weirdness, so this should generally only be
-  // called during the Delegate's OnModelChanged call, or if the adapter was
-  // created with a NULL |table_model|.
-  void SetModel(TableModel* table_model);
-
-  // Add all model rows corresponding to the given list store indices to |rows|.
-  void MapListStoreIndicesToModelRows(const std::set<int>& list_store_indices,
-                                      RemoveRowsTableModel::Rows* model_rows);
-
-  // GtkTreeModel callbacks:
-  // Callback checking whether a row should be drawn as a separator.
-  static gboolean OnCheckRowIsSeparator(GtkTreeModel* model,
-                                        GtkTreeIter* iter,
-                                        gpointer user_data);
-
-  // Callback checking whether a row may be selected.  We use some rows in the
-  // table as headers/separators for the groups, which should not be selectable.
-  static gboolean OnSelectionFilter(GtkTreeSelection* selection,
-                                    GtkTreeModel* model,
-                                    GtkTreePath* path,
-                                    gboolean path_currently_selected,
-                                    gpointer user_data);
-
-  // TableModelObserver implementation.
-  virtual void OnModelChanged();
-  virtual void OnItemsChanged(int start, int length);
-  virtual void OnItemsAdded(int start, int length);
-  virtual void OnItemsRemoved(int start, int length);
-
- private:
-  // Return whether the row pointed to by |iter| is a group row, i.e. a group
-  // header, or a separator.
-  bool IsGroupRow(GtkTreeIter* iter) const;
-
-  // Return the index into the list store for the given model row.
-  int GetListStoreIndexForModelRow(int model_row) const;
-
-  // Add the values from |row| of the TableModel.
-  void AddNodeToList(int row);
-
-  Delegate* delegate_;
-  GtkListStore* list_store_;
-  TableModel* table_model_;
-
-  DISALLOW_COPY_AND_ASSIGN(TableAdapter);
-};
-
-// A helper class for populating a GtkTreeStore from a TreeModel.
-// TODO(mattm): support SetRootShown(true)
-class TreeAdapter : public TreeModelObserver {
- public:
-  // Column ids for |tree_store_|.
-  enum {
-    COL_ICON,
-    COL_TITLE,
-    COL_NODE_PTR,
-    COL_COUNT,
-  };
-
-  class Delegate {
-   public:
-    // Called after any change to the TreeModel but before the corresponding
-    // change to the GtkTreeStore.
-    virtual void OnAnyModelUpdateStart() {}
-
-    // Called after any change to the GtkTreeStore.
-    virtual void OnAnyModelUpdate() {}
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  TreeAdapter(Delegate* delegate, TreeModel* tree_model);
-  virtual ~TreeAdapter();
-
-  // Populate the tree store from the |tree_model_|.
-  void Init();
-
-  // Return the tree store.
-  GtkTreeStore* tree_store() { return tree_store_; }
-
-  // Get the TreeModelNode corresponding to iter in the tree store.
-  TreeModelNode* GetNode(GtkTreeIter* iter);
-
-  // Begin TreeModelObserver implementation.
-  virtual void TreeNodesAdded(TreeModel* model,
-                              TreeModelNode* parent,
-                              int start,
-                              int count);
-  virtual void TreeNodesRemoved(TreeModel* model,
-                                TreeModelNode* parent,
-                                int start,
-                                int count);
-  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node);
-  // End TreeModelObserver implementation.
-
- private:
-  // Fill the tree store values for a given node.
-  void FillRow(GtkTreeIter* iter, TreeModelNode* node);
-
-  // Fill the tree store for a row and all its descendants.
-  void Fill(GtkTreeIter* parent_iter, TreeModelNode* parent_node);
-
-  // Get the GtkTreePath in the tree store for the given node.
-  // The returned path should be freed with gtk_tree_path_free.
-  GtkTreePath* GetTreePath(TreeModelNode* node);
-
-  // Get the GtkTreeIter in the tree store for the given node.
-  bool GetTreeIter(TreeModelNode* node, GtkTreeIter* iter);
-
-  Delegate* delegate_;
-  GtkTreeStore* tree_store_;
-  TreeModel* tree_model_;
-  std::vector<GdkPixbuf*> pixbufs_;
-
-  DISALLOW_COPY_AND_ASSIGN(TreeAdapter);
-};
-
-}  // namespace gtk_tree
-
-#endif  // CHROME_BROWSER_GTK_GTK_TREE_H_
diff --git a/chrome/browser/gtk/gtk_util.cc b/chrome/browser/gtk/gtk_util.cc
deleted file mode 100644
index bf7ba63..0000000
--- a/chrome/browser/gtk/gtk_util.cc
+++ /dev/null
@@ -1,1250 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/gtk_util.h"
-
-#include <cairo/cairo.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-
-#include <cstdarg>
-#include <map>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/x11_util.h"
-#include "base/environment.h"
-#include "base/i18n/rtl.h"
-#include "base/linux_util.h"
-#include "base/logging.h"
-#include "base/nix/xdg_util.h"
-#include "base/string_number_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/autocomplete/autocomplete.h"
-#include "chrome/browser/autocomplete/autocomplete_classifier.h"
-#include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/renderer_preferences.h"
-#include "gfx/gtk_util.h"
-#include "googleurl/src/gurl.h"
-#include "grit/theme_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/frame/browser_view.h"
-#include "chrome/browser/chromeos/native_dialog_window.h"
-#include "chrome/browser/chromeos/options/options_window_view.h"
-#include "views/window/window.h"
-#else
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#endif
-
-using WebKit::WebDragOperationsMask;
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationNone;
-using WebKit::WebDragOperationCopy;
-using WebKit::WebDragOperationLink;
-using WebKit::WebDragOperationMove;
-
-namespace {
-
-const char kBoldLabelMarkup[] = "<span weight='bold'>%s</span>";
-
-// Callback used in RemoveAllChildren.
-void RemoveWidget(GtkWidget* widget, gpointer container) {
-  gtk_container_remove(GTK_CONTAINER(container), widget);
-}
-
-// These two functions are copped almost directly from gtk core. The only
-// difference is that they accept middle clicks.
-gboolean OnMouseButtonPressed(GtkWidget* widget, GdkEventButton* event,
-                              gpointer userdata) {
-  if (event->type == GDK_BUTTON_PRESS) {
-    if (gtk_button_get_focus_on_click(GTK_BUTTON(widget)) &&
-        !GTK_WIDGET_HAS_FOCUS(widget)) {
-      gtk_widget_grab_focus(widget);
-    }
-
-    gint button_mask = GPOINTER_TO_INT(userdata);
-    if (button_mask & (1 << event->button))
-      gtk_button_pressed(GTK_BUTTON(widget));
-  }
-
-  return TRUE;
-}
-
-gboolean OnMouseButtonReleased(GtkWidget* widget, GdkEventButton* event,
-                               gpointer userdata) {
-  gint button_mask = GPOINTER_TO_INT(userdata);
-  if (button_mask && (1 << event->button))
-    gtk_button_released(GTK_BUTTON(widget));
-
-  return TRUE;
-}
-
-// Returns the approximate number of characters that can horizontally fit in
-// |pixel_width| pixels.
-int GetCharacterWidthForPixels(GtkWidget* widget, int pixel_width) {
-  DCHECK(GTK_WIDGET_REALIZED(widget))
-      << " widget must be realized to compute font metrics correctly";
-
-  PangoContext* context = gtk_widget_create_pango_context(widget);
-  PangoFontMetrics* metrics = pango_context_get_metrics(context,
-      widget->style->font_desc, pango_context_get_language(context));
-
-  // This technique (max of char and digit widths) matches the code in
-  // gtklabel.c.
-  int char_width = pixel_width * PANGO_SCALE /
-      std::max(pango_font_metrics_get_approximate_char_width(metrics),
-               pango_font_metrics_get_approximate_digit_width(metrics));
-
-  pango_font_metrics_unref(metrics);
-  g_object_unref(context);
-
-  return char_width;
-}
-
-void OnLabelRealize(GtkWidget* label, gpointer pixel_width) {
-  gtk_label_set_width_chars(
-      GTK_LABEL(label),
-      GetCharacterWidthForPixels(label,GPOINTER_TO_INT(pixel_width)));
-}
-
-// Ownership of |icon_list| is passed to the caller.
-GList* GetIconList() {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  GList* icon_list = NULL;
-  icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_ICON_32));
-  icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
-  return icon_list;
-}
-
-// Expose event handler for a container that simply suppresses the default
-// drawing and propagates the expose event to the container's children.
-gboolean PaintNoBackground(GtkWidget* widget,
-                           GdkEventExpose* event,
-                           gpointer unused) {
-  GList* children = gtk_container_get_children(GTK_CONTAINER(widget));
-  for (GList* item = children; item; item = item->next) {
-    gtk_container_propagate_expose(GTK_CONTAINER(widget),
-                                   GTK_WIDGET(item->data),
-                                   event);
-  }
-  g_list_free(children);
-
-  return TRUE;
-}
-
-#if defined(OS_CHROMEOS)
-
-TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
-  chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
-      window);
-  return browser_view->GetSelectedTabContents();
-}
-
-GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
-  gfx::NativeView widget = gtk_window_get_focus(window->GetNativeHandle());
-
-  if (widget == NULL) {
-    chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
-        window);
-    widget = browser_view->saved_focused_widget();
-  }
-
-  return widget;
-}
-
-#else
-
-TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
-  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
-      window);
-  return browser_window->browser()->GetSelectedTabContents();
-}
-
-GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
-  return gtk_window_get_focus(window->GetNativeHandle());
-}
-
-#endif
-
-}  // namespace
-
-namespace event_utils {
-
-WindowOpenDisposition DispositionFromEventFlags(guint event_flags) {
-  if ((event_flags & GDK_BUTTON2_MASK) || (event_flags & GDK_CONTROL_MASK)) {
-    return (event_flags & GDK_SHIFT_MASK) ?
-        NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
-  }
-
-  if (event_flags & GDK_SHIFT_MASK)
-    return NEW_WINDOW;
-  return false /*event.IsAltDown()*/ ? SAVE_TO_DISK : CURRENT_TAB;
-}
-
-}  // namespace event_utils
-
-namespace gtk_util {
-
-const GdkColor kGdkWhite = GDK_COLOR_RGB(0xff, 0xff, 0xff);
-const GdkColor kGdkGray  = GDK_COLOR_RGB(0x7f, 0x7f, 0x7f);
-const GdkColor kGdkBlack = GDK_COLOR_RGB(0x00, 0x00, 0x00);
-const GdkColor kGdkGreen = GDK_COLOR_RGB(0x00, 0xff, 0x00);
-
-GtkWidget* CreateLabeledControlsGroup(std::vector<GtkWidget*>* labels,
-                                      const char* text, ...) {
-  va_list ap;
-  va_start(ap, text);
-  GtkWidget* table = gtk_table_new(0, 2, FALSE);
-  gtk_table_set_col_spacing(GTK_TABLE(table), 0, kLabelSpacing);
-  gtk_table_set_row_spacings(GTK_TABLE(table), kControlSpacing);
-
-  for (guint row = 0; text; ++row) {
-    gtk_table_resize(GTK_TABLE(table), row + 1, 2);
-    GtkWidget* control = va_arg(ap, GtkWidget*);
-    GtkWidget* label = gtk_label_new(text);
-    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-    if (labels)
-      labels->push_back(label);
-
-    gtk_table_attach(GTK_TABLE(table), label,
-                 0, 1, row, row + 1,
-                 GTK_FILL, GTK_FILL,
-                 0, 0);
-    gtk_table_attach_defaults(GTK_TABLE(table), control,
-                              1, 2, row, row + 1);
-    text = va_arg(ap, const char*);
-  }
-  va_end(ap);
-
-  return table;
-}
-
-GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
-                              int top, int bottom, int left, int right) {
-  // Use a GtkEventBox to get the background painted.  However, we can't just
-  // use a container border, since it won't paint there.  Use an alignment
-  // inside to get the sizes exactly of how we want the border painted.
-  GtkWidget* ebox = gtk_event_box_new();
-  if (color)
-    gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, color);
-  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), top, bottom, left, right);
-  gtk_container_add(GTK_CONTAINER(alignment), child);
-  gtk_container_add(GTK_CONTAINER(ebox), alignment);
-  return ebox;
-}
-
-GtkWidget* LeftAlignMisc(GtkWidget* misc) {
-  gtk_misc_set_alignment(GTK_MISC(misc), 0, 0.5);
-  return misc;
-}
-
-GtkWidget* CreateBoldLabel(const std::string& text) {
-  GtkWidget* label = gtk_label_new(NULL);
-  char* markup = g_markup_printf_escaped(kBoldLabelMarkup, text.c_str());
-  gtk_label_set_markup(GTK_LABEL(label), markup);
-  g_free(markup);
-
-  return LeftAlignMisc(label);
-}
-
-void GetWidgetSizeFromCharacters(
-    GtkWidget* widget, double width_chars, double height_lines,
-    int* width, int* height) {
-  DCHECK(GTK_WIDGET_REALIZED(widget))
-      << " widget must be realized to compute font metrics correctly";
-  PangoContext* context = gtk_widget_create_pango_context(widget);
-  PangoFontMetrics* metrics = pango_context_get_metrics(context,
-      widget->style->font_desc, pango_context_get_language(context));
-  if (width) {
-    *width = static_cast<int>(
-        pango_font_metrics_get_approximate_char_width(metrics) *
-        width_chars / PANGO_SCALE);
-  }
-  if (height) {
-    *height = static_cast<int>(
-        (pango_font_metrics_get_ascent(metrics) +
-        pango_font_metrics_get_descent(metrics)) *
-        height_lines / PANGO_SCALE);
-  }
-  pango_font_metrics_unref(metrics);
-  g_object_unref(context);
-}
-
-void GetWidgetSizeFromResources(
-    GtkWidget* widget, int width_chars, int height_lines,
-    int* width, int* height) {
-  DCHECK(GTK_WIDGET_REALIZED(widget))
-      << " widget must be realized to compute font metrics correctly";
-
-  double chars = 0;
-  if (width)
-    base::StringToDouble(l10n_util::GetStringUTF8(width_chars), &chars);
-
-  double lines = 0;
-  if (height)
-    base::StringToDouble(l10n_util::GetStringUTF8(height_lines), &lines);
-
-  GetWidgetSizeFromCharacters(widget, chars, lines, width, height);
-}
-
-void SetWindowSizeFromResources(GtkWindow* window,
-                                int width_id, int height_id, bool resizable) {
-  int width = -1;
-  int height = -1;
-  gtk_util::GetWidgetSizeFromResources(GTK_WIDGET(window), width_id, height_id,
-                                       (width_id != -1) ? &width : NULL,
-                                       (height_id != -1) ? &height : NULL);
-
-  if (resizable) {
-    gtk_window_set_default_size(window, width, height);
-  } else {
-    // For a non-resizable window, GTK tries to snap the window size
-    // to the minimum size around the content.  We use the sizes in
-    // the resources to set *minimum* window size to allow windows
-    // with long titles to be wide enough to display their titles.
-    //
-    // But if GTK wants to make the window *wider* due to very wide
-    // controls, we should allow that too, so be careful to pick the
-    // wider of the resources size and the natural window size.
-
-    gtk_widget_show_all(GTK_BIN(window)->child);
-    GtkRequisition requisition;
-    gtk_widget_size_request(GTK_WIDGET(window), &requisition);
-    gtk_widget_set_size_request(
-        GTK_WIDGET(window),
-        width == -1 ? -1 : std::max(width, requisition.width),
-        height == -1 ? -1 : std::max(height, requisition.height));
-  }
-  gtk_window_set_resizable(window, resizable ? TRUE : FALSE);
-}
-
-void CenterOverWindow(GtkWindow* window, GtkWindow* parent) {
-  gfx::Rect frame_bounds = gtk_util::GetWidgetScreenBounds(GTK_WIDGET(parent));
-  gfx::Point origin = frame_bounds.origin();
-  gfx::Size size = gtk_util::GetWidgetSize(GTK_WIDGET(window));
-  origin.Offset(
-      (frame_bounds.width() - size.width()) / 2,
-      (frame_bounds.height() - size.height()) / 2);
-
-  // Prevent moving window out of monitor bounds.
-  GdkScreen* screen = gtk_window_get_screen(parent);
-  if (screen) {
-    // It would be better to check against workarea for given monitor
-    // but getting workarea for particular monitor is tricky.
-    gint monitor = gdk_screen_get_monitor_at_window(screen,
-        GTK_WIDGET(parent)->window);
-    GdkRectangle rect;
-    gdk_screen_get_monitor_geometry(screen, monitor, &rect);
-
-    // Check the right bottom corner.
-    if (origin.x() > rect.x + rect.width - size.width())
-      origin.set_x(rect.x + rect.width - size.width());
-    if (origin.y() > rect.y + rect.height - size.height())
-      origin.set_y(rect.y + rect.height - size.height());
-
-    // Check the left top corner.
-    if (origin.x() < rect.x)
-      origin.set_x(rect.x);
-    if (origin.y() < rect.y)
-      origin.set_y(rect.y);
-  }
-
-  gtk_window_move(window, origin.x(), origin.y());
-
-  // Move to user expected desktop if window is already visible.
-  if (GTK_WIDGET(window)->window) {
-    x11_util::ChangeWindowDesktop(
-        x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(window)),
-        x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(parent)));
-  }
-}
-
-void MakeAppModalWindowGroup() {
-#if GTK_CHECK_VERSION(2, 14, 0)
-  // Older versions of GTK+ don't give us gtk_window_group_list() which is what
-  // we need to add current non-browser modal dialogs to the list. If
-  // we have 2.14+ we can do things the correct way.
-  GtkWindowGroup* window_group = gtk_window_group_new();
-  for (BrowserList::const_iterator it = BrowserList::begin();
-       it != BrowserList::end(); ++it) {
-    // List all windows in this current group
-    GtkWindowGroup* old_group =
-        gtk_window_get_group((*it)->window()->GetNativeHandle());
-
-    GList* all_windows = gtk_window_group_list_windows(old_group);
-    for (GList* window = all_windows; window; window = window->next) {
-      gtk_window_group_add_window(window_group, GTK_WINDOW(window->data));
-    }
-    g_list_free(all_windows);
-  }
-  g_object_unref(window_group);
-#else
-  // Otherwise just grab all browser windows and be slightly broken.
-  GtkWindowGroup* window_group = gtk_window_group_new();
-  for (BrowserList::const_iterator it = BrowserList::begin();
-       it != BrowserList::end(); ++it) {
-    gtk_window_group_add_window(window_group,
-                                (*it)->window()->GetNativeHandle());
-  }
-  g_object_unref(window_group);
-#endif
-}
-
-void AppModalDismissedUngroupWindows() {
-#if GTK_CHECK_VERSION(2, 14, 0)
-  if (BrowserList::begin() != BrowserList::end()) {
-    std::vector<GtkWindow*> transient_windows;
-
-    // All windows should be part of one big modal group right now.
-    GtkWindowGroup* window_group = gtk_window_get_group(
-        (*BrowserList::begin())->window()->GetNativeHandle());
-    GList* windows = gtk_window_group_list_windows(window_group);
-
-    for (GList* item = windows; item; item = item->next) {
-      GtkWindow* window = GTK_WINDOW(item->data);
-      GtkWindow* transient_for = gtk_window_get_transient_for(window);
-      if (transient_for) {
-        transient_windows.push_back(window);
-      } else {
-        GtkWindowGroup* window_group = gtk_window_group_new();
-        gtk_window_group_add_window(window_group, window);
-        g_object_unref(window_group);
-      }
-    }
-
-    // Put each transient window in the same group as its transient parent.
-    for (std::vector<GtkWindow*>::iterator it = transient_windows.begin();
-         it != transient_windows.end(); ++it) {
-      GtkWindow* transient_parent = gtk_window_get_transient_for(*it);
-      GtkWindowGroup* group = gtk_window_get_group(transient_parent);
-      gtk_window_group_add_window(group, *it);
-    }
-  }
-#else
-  // This is slightly broken in the case where a different window had a dialog,
-  // but its the best we can do since we don't have newer gtk stuff.
-  for (BrowserList::const_iterator it = BrowserList::begin();
-       it != BrowserList::end(); ++it) {
-    GtkWindowGroup* window_group = gtk_window_group_new();
-    gtk_window_group_add_window(window_group,
-                                (*it)->window()->GetNativeHandle());
-    g_object_unref(window_group);
-  }
-#endif
-}
-
-void RemoveAllChildren(GtkWidget* container) {
-  gtk_container_foreach(GTK_CONTAINER(container), RemoveWidget, container);
-}
-
-void ForceFontSizePixels(GtkWidget* widget, double size_pixels) {
-  GtkStyle* style = widget->style;
-  PangoFontDescription* font_desc = style->font_desc;
-  // pango_font_description_set_absolute_size sets the font size in device
-  // units, which for us is pixels.
-  pango_font_description_set_absolute_size(font_desc,
-                                           PANGO_SCALE * size_pixels);
-  gtk_widget_modify_font(widget, font_desc);
-}
-
-void UndoForceFontSize(GtkWidget* widget) {
-  gtk_widget_modify_font(widget, NULL);
-}
-
-gfx::Point GetWidgetScreenPosition(GtkWidget* widget) {
-  if (!widget->window) {
-    NOTREACHED() << "Must only be called on realized widgets.";
-    return gfx::Point(0, 0);
-  }
-
-  gint x, y;
-  gdk_window_get_origin(widget->window, &x, &y);
-
-  if (!GTK_IS_WINDOW(widget)) {
-    x += widget->allocation.x;
-    y += widget->allocation.y;
-  }
-
-  return gfx::Point(x, y);
-}
-
-gfx::Rect GetWidgetScreenBounds(GtkWidget* widget) {
-  gfx::Point position = GetWidgetScreenPosition(widget);
-  return gfx::Rect(position.x(), position.y(),
-                   widget->allocation.width, widget->allocation.height);
-}
-
-gfx::Size GetWidgetSize(GtkWidget* widget) {
-  GtkRequisition size;
-  gtk_widget_size_request(widget, &size);
-  return gfx::Size(size.width, size.height);
-}
-
-void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p) {
-  DCHECK(widget);
-  DCHECK(p);
-
-  gfx::Point position = GetWidgetScreenPosition(widget);
-  p->SetPoint(p->x() + position.x(), p->y() + position.y());
-}
-
-void InitRCStyles() {
-  static const char kRCText[] =
-      // Make our dialogs styled like the GNOME HIG.
-      //
-      // TODO(evanm): content-area-spacing was introduced in a later
-      // version of GTK, so we need to set that manually on all dialogs.
-      // Perhaps it would make sense to have a shared FixupDialog() function.
-      "style \"gnome-dialog\" {\n"
-      "  xthickness = 12\n"
-      "  GtkDialog::action-area-border = 0\n"
-      "  GtkDialog::button-spacing = 6\n"
-      "  GtkDialog::content-area-spacing = 18\n"
-      "  GtkDialog::content-area-border = 12\n"
-      "}\n"
-      // Note we set it at the "application" priority, so users can override.
-      "widget \"GtkDialog\" style : application \"gnome-dialog\"\n"
-
-      // Make our about dialog special, so the image is flush with the edge.
-      "style \"about-dialog\" {\n"
-      "  GtkDialog::action-area-border = 12\n"
-      "  GtkDialog::button-spacing = 6\n"
-      "  GtkDialog::content-area-spacing = 18\n"
-      "  GtkDialog::content-area-border = 0\n"
-      "}\n"
-      "widget \"about-dialog\" style : application \"about-dialog\"\n";
-
-  gtk_rc_parse_string(kRCText);
-}
-
-GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
-                              bool pack_at_end, int padding) {
-  GtkWidget* centering_vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(centering_vbox), widget, TRUE, FALSE, 0);
-  if (pack_at_end)
-    gtk_box_pack_end(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
-  else
-    gtk_box_pack_start(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
-
-  return centering_vbox;
-}
-
-bool IsScreenComposited() {
-  GdkScreen* screen = gdk_screen_get_default();
-  return gdk_screen_is_composited(screen) == TRUE;
-}
-
-void EnumerateTopLevelWindows(x11_util::EnumerateWindowsDelegate* delegate) {
-  std::vector<XID> stack;
-  if (!x11_util::GetXWindowStack(&stack)) {
-    // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
-    // to old school enumeration of all X windows.  Some WMs parent 'top-level'
-    // windows in unnamed actual top-level windows (ion WM), so extend the
-    // search depth to all children of top-level windows.
-    const int kMaxSearchDepth = 1;
-    x11_util::EnumerateAllWindows(delegate, kMaxSearchDepth);
-    return;
-  }
-
-  std::vector<XID>::iterator iter;
-  for (iter = stack.begin(); iter != stack.end(); iter++) {
-    if (delegate->ShouldStopIterating(*iter))
-      return;
-  }
-}
-
-void SetButtonClickableByMouseButtons(GtkWidget* button,
-                                      bool left, bool middle, bool right) {
-  gint button_mask = 0;
-  if (left)
-    button_mask |= 1 << 1;
-  if (middle)
-    button_mask |= 1 << 2;
-  if (right)
-    button_mask |= 1 << 3;
-  void* userdata = GINT_TO_POINTER(button_mask);
-
-  g_signal_connect(button, "button-press-event",
-                   G_CALLBACK(OnMouseButtonPressed), userdata);
-  g_signal_connect(button, "button-release-event",
-                   G_CALLBACK(OnMouseButtonReleased), userdata);
-}
-
-void SetButtonTriggersNavigation(GtkWidget* button) {
-  SetButtonClickableByMouseButtons(button, true, true, false);
-}
-
-int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds) {
-  if (!base::i18n::IsRTL())
-    return bounds.x();
-  return widget->allocation.width - bounds.x() - bounds.width();
-}
-
-int MirroredXCoordinate(GtkWidget* widget, int x) {
-  if (base::i18n::IsRTL())
-    return widget->allocation.width - x;
-  return x;
-}
-
-bool WidgetContainsCursor(GtkWidget* widget) {
-  gint x = 0;
-  gint y = 0;
-  gtk_widget_get_pointer(widget, &x, &y);
-  return WidgetBounds(widget).Contains(x, y);
-}
-
-void SetWindowIcon(GtkWindow* window) {
-  GList* icon_list = GetIconList();
-  gtk_window_set_icon_list(window, icon_list);
-  g_list_free(icon_list);
-}
-
-void SetDefaultWindowIcon() {
-  GList* icon_list = GetIconList();
-  gtk_window_set_default_icon_list(icon_list);
-  g_list_free(icon_list);
-}
-
-GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
-                             const gchar* stock_id, gint response_id) {
-  GtkWidget* button = gtk_button_new_with_label(text);
-  gtk_button_set_image(GTK_BUTTON(button),
-                       gtk_image_new_from_stock(stock_id,
-                                                GTK_ICON_SIZE_BUTTON));
-  gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button,
-                               response_id);
-  return button;
-}
-
-GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
-                             const gchar* stock_id) {
-  GtkWidget* button = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(ids_id)).c_str());
-  gtk_button_set_image(GTK_BUTTON(button),
-                       gtk_image_new_from_stock(stock_id,
-                                                GTK_ICON_SIZE_BUTTON));
-  return button;
-}
-
-GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image) {
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-  return hbox;
-}
-
-void SetLabelColor(GtkWidget* label, const GdkColor* color) {
-  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, color);
-  gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, color);
-  gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, color);
-  gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, color);
-}
-
-GtkWidget* IndentWidget(GtkWidget* content) {
-  GtkWidget* content_alignment = gtk_alignment_new(0.0, 0.5, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment), 0, 0,
-                            gtk_util::kGroupIndent, 0);
-  gtk_container_add(GTK_CONTAINER(content_alignment), content);
-  return content_alignment;
-}
-
-void UpdateGtkFontSettings(RendererPreferences* prefs) {
-  DCHECK(prefs);
-
-  // From http://library.gnome.org/devel/gtk/unstable/GtkSettings.html, this is
-  // the default value for gtk-cursor-blink-time.
-  static const gint kGtkDefaultCursorBlinkTime = 1200;
-
-  gint cursor_blink_time = kGtkDefaultCursorBlinkTime;
-  gboolean cursor_blink = TRUE;
-  gint antialias = 0;
-  gint hinting = 0;
-  gchar* hint_style = NULL;
-  gchar* rgba_style = NULL;
-  g_object_get(gtk_settings_get_default(),
-               "gtk-cursor-blink-time", &cursor_blink_time,
-               "gtk-cursor-blink", &cursor_blink,
-               "gtk-xft-antialias", &antialias,
-               "gtk-xft-hinting", &hinting,
-               "gtk-xft-hintstyle", &hint_style,
-               "gtk-xft-rgba", &rgba_style,
-               NULL);
-
-  // Set some reasonable defaults.
-  prefs->should_antialias_text = true;
-  prefs->hinting = RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT;
-  prefs->subpixel_rendering =
-      RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT;
-
-  if (cursor_blink) {
-    // Dividing by 2*1000ms follows the WebKit GTK port and makes the blink
-    // frequency appear similar to the omnibox.  Without this the blink is too
-    // slow.
-    prefs->caret_blink_interval = cursor_blink_time / 2000.;
-  } else {
-    prefs->caret_blink_interval = 0;
-  }
-
-  // g_object_get() doesn't tell us whether the properties were present or not,
-  // but if they aren't (because gnome-settings-daemon isn't running), we'll get
-  // NULL values for the strings.
-  if (hint_style && rgba_style) {
-    prefs->should_antialias_text = antialias;
-
-    if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) {
-      prefs->hinting = RENDERER_PREFERENCES_HINTING_NONE;
-    } else if (strcmp(hint_style, "hintslight") == 0) {
-      prefs->hinting = RENDERER_PREFERENCES_HINTING_SLIGHT;
-    } else if (strcmp(hint_style, "hintmedium") == 0) {
-      prefs->hinting = RENDERER_PREFERENCES_HINTING_MEDIUM;
-    } else if (strcmp(hint_style, "hintfull") == 0) {
-      prefs->hinting = RENDERER_PREFERENCES_HINTING_FULL;
-    }
-
-    if (strcmp(rgba_style, "none") == 0) {
-      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE;
-    } else if (strcmp(rgba_style, "rgb") == 0) {
-      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB;
-    } else if (strcmp(rgba_style, "bgr") == 0) {
-      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR;
-    } else if (strcmp(rgba_style, "vrgb") == 0) {
-      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB;
-    } else if (strcmp(rgba_style, "vbgr") == 0) {
-      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR;
-    }
-  }
-
-  if (hint_style)
-    g_free(hint_style);
-  if (rgba_style)
-    g_free(rgba_style);
-}
-
-gfx::Point ScreenPoint(GtkWidget* widget) {
-  int x, y;
-  gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y,
-                          NULL);
-  return gfx::Point(x, y);
-}
-
-gfx::Point ClientPoint(GtkWidget* widget) {
-  int x, y;
-  gtk_widget_get_pointer(widget, &x, &y);
-  return gfx::Point(x, y);
-}
-
-GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) {
-  GdkPoint point = {ltr ? x : width - x, y};
-  return point;
-}
-
-void DrawTextEntryBackground(GtkWidget* offscreen_entry,
-                             GtkWidget* widget_to_draw_on,
-                             GdkRectangle* dirty_rec,
-                             GdkRectangle* rec) {
-  GtkStyle* gtk_owned_style = gtk_rc_get_style(offscreen_entry);
-  // GTK owns the above and we're going to have to make our own copy of it
-  // that we can edit.
-  GtkStyle* our_style = gtk_style_copy(gtk_owned_style);
-  our_style = gtk_style_attach(our_style, widget_to_draw_on->window);
-
-  // TODO(erg): Draw the focus ring if appropriate...
-
-  // We're using GTK rendering; draw a GTK entry widget onto the background.
-  gtk_paint_shadow(our_style, widget_to_draw_on->window,
-                   GTK_STATE_NORMAL, GTK_SHADOW_IN, dirty_rec,
-                   widget_to_draw_on, "entry",
-                   rec->x, rec->y, rec->width, rec->height);
-
-  // Draw the interior background (not all themes draw the entry background
-  // above; this is a noop on themes that do).
-  gint xborder = our_style->xthickness;
-  gint yborder = our_style->ythickness;
-  gint width = rec->width - 2 * xborder;
-  gint height = rec->height - 2 * yborder;
-  if (width > 0 && height > 0) {
-    gtk_paint_flat_box(our_style, widget_to_draw_on->window,
-                       GTK_STATE_NORMAL, GTK_SHADOW_NONE, dirty_rec,
-                       widget_to_draw_on, "entry_bg",
-                       rec->x + xborder, rec->y + yborder,
-                       width, height);
-  }
-
-  gtk_style_detach(our_style);
-  g_object_unref(our_style);
-}
-
-void DrawThemedToolbarBackground(GtkWidget* widget,
-                                 cairo_t* cr,
-                                 GdkEventExpose* event,
-                                 const gfx::Point& tabstrip_origin,
-                                 GtkThemeProvider* theme_provider) {
-  // Fill the entire region with the toolbar color.
-  GdkColor color = theme_provider->GetGdkColor(
-      BrowserThemeProvider::COLOR_TOOLBAR);
-  gdk_cairo_set_source_color(cr, &color);
-  cairo_fill(cr);
-
-  // The toolbar is supposed to blend in with the active tab, so we have to pass
-  // coordinates for the IDR_THEME_TOOLBAR bitmap relative to the top of the
-  // tab strip.
-  CairoCachedSurface* background = theme_provider->GetSurfaceNamed(
-      IDR_THEME_TOOLBAR, widget);
-  background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
-  // We tile the toolbar background in both directions.
-  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-  cairo_rectangle(cr,
-                  tabstrip_origin.x(),
-                  tabstrip_origin.y(),
-                  event->area.x + event->area.width - tabstrip_origin.x(),
-                  event->area.y + event->area.height - tabstrip_origin.y());
-  cairo_fill(cr);
-}
-
-GdkColor AverageColors(GdkColor color_one, GdkColor color_two) {
-  GdkColor average_color;
-  average_color.pixel = 0;
-  average_color.red = (color_one.red + color_two.red) / 2;
-  average_color.green = (color_one.green + color_two.green) / 2;
-  average_color.blue = (color_one.blue + color_two.blue) / 2;
-  return average_color;
-}
-
-void SetAlwaysShowImage(GtkWidget* image_menu_item) {
-  // Compile time check: if it's available, just use the API.
-  // GTK_CHECK_VERSION is TRUE if the passed version is compatible.
-#if GTK_CHECK_VERSION(2, 16, 1)
-  gtk_image_menu_item_set_always_show_image(
-      GTK_IMAGE_MENU_ITEM(image_menu_item), TRUE);
-#else
-  // Run time check: if the API is not available, set the property manually.
-  // This will still only work with GTK 2.16+ as the property doesn't exist
-  // in earlier versions.
-  // gtk_check_version() returns NULL if the passed version is compatible.
-  if (!gtk_check_version(2, 16, 1)) {
-    GValue true_value = { 0 };
-    g_value_init(&true_value, G_TYPE_BOOLEAN);
-    g_value_set_boolean(&true_value, TRUE);
-    g_object_set_property(G_OBJECT(image_menu_item), "always-show-image",
-                          &true_value);
-  }
-#endif
-}
-
-void StackPopupWindow(GtkWidget* popup, GtkWidget* toplevel) {
-  DCHECK(GTK_IS_WINDOW(popup) && GTK_WIDGET_TOPLEVEL(popup) &&
-         GTK_WIDGET_REALIZED(popup));
-  DCHECK(GTK_IS_WINDOW(toplevel) && GTK_WIDGET_TOPLEVEL(toplevel) &&
-         GTK_WIDGET_REALIZED(toplevel));
-
-  // Stack the |popup| window directly above the |toplevel| window.
-  // The popup window is a direct child of the root window, so we need to
-  // find a similar ancestor for the toplevel window (which might have been
-  // reparented by a window manager).  We grab the server while we're doing
-  // this -- otherwise, we'll get an error if the window manager reparents the
-  // toplevel window right after we call GetHighestAncestorWindow().
-  gdk_x11_display_grab(gtk_widget_get_display(toplevel));
-  XID toplevel_window_base = x11_util::GetHighestAncestorWindow(
-      x11_util::GetX11WindowFromGtkWidget(toplevel),
-      x11_util::GetX11RootWindow());
-  if (toplevel_window_base) {
-    XID window_xid = x11_util::GetX11WindowFromGtkWidget(popup);
-    XID window_parent = x11_util::GetParentWindow(window_xid);
-    if (window_parent == x11_util::GetX11RootWindow()) {
-      x11_util::RestackWindow(window_xid, toplevel_window_base, true);
-    } else {
-      // The window manager shouldn't reparent override-redirect windows.
-      DLOG(ERROR) << "override-redirect window " << window_xid
-                  << "'s parent is " << window_parent
-                  << ", rather than root window "
-                  << x11_util::GetX11RootWindow();
-    }
-  }
-  gdk_x11_display_ungrab(gtk_widget_get_display(toplevel));
-}
-
-gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget) {
-  DCHECK(GTK_WIDGET_REALIZED(widget));
-
-  GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
-  DCHECK(toplevel);
-  DCHECK(GTK_WIDGET_REALIZED(toplevel));
-
-  gint x = 0, y = 0;
-  gtk_widget_translate_coordinates(widget,
-                                   toplevel,
-                                   0, 0,
-                                   &x, &y);
-  return gfx::Rect(x, y, widget->allocation.width, widget->allocation.height);
-}
-
-void SuppressDefaultPainting(GtkWidget* container) {
-  g_signal_connect(container, "expose-event",
-                   G_CALLBACK(PaintNoBackground), NULL);
-}
-
-WindowOpenDisposition DispositionForCurrentButtonPressEvent() {
-  GdkEvent* event = gtk_get_current_event();
-  if (!event) {
-    NOTREACHED();
-    return NEW_FOREGROUND_TAB;
-  }
-
-  guint state = event->button.state;
-  gdk_event_free(event);
-  return event_utils::DispositionFromEventFlags(state);
-}
-
-bool GrabAllInput(GtkWidget* widget) {
-  guint time = gtk_get_current_event_time();
-
-  if (!GTK_WIDGET_VISIBLE(widget))
-    return false;
-
-  if (!gdk_pointer_grab(widget->window, TRUE,
-                        GdkEventMask(GDK_BUTTON_PRESS_MASK |
-                                     GDK_BUTTON_RELEASE_MASK |
-                                     GDK_ENTER_NOTIFY_MASK |
-                                     GDK_LEAVE_NOTIFY_MASK |
-                                     GDK_POINTER_MOTION_MASK),
-                        NULL, NULL, time) == 0) {
-    return false;
-  }
-
-  if (!gdk_keyboard_grab(widget->window, TRUE, time) == 0) {
-    gdk_display_pointer_ungrab(gdk_drawable_get_display(widget->window), time);
-    return false;
-  }
-
-  gtk_grab_add(widget);
-  return true;
-}
-
-gfx::Rect WidgetBounds(GtkWidget* widget) {
-  // To quote the gtk docs:
-  //
-  //   Widget coordinates are a bit odd; for historical reasons, they are
-  //   defined as widget->window coordinates for widgets that are not
-  //   GTK_NO_WINDOW widgets, and are relative to widget->allocation.x,
-  //   widget->allocation.y for widgets that are GTK_NO_WINDOW widgets.
-  //
-  // So the base is always (0,0).
-  return gfx::Rect(0, 0, widget->allocation.width, widget->allocation.height);
-}
-
-void SetWMLastUserActionTime(GtkWindow* window) {
-  gdk_x11_window_set_user_time(GTK_WIDGET(window)->window, XTimeNow());
-}
-
-guint32 XTimeNow() {
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
-}
-
-bool URLFromPrimarySelection(Profile* profile, GURL* url) {
-  GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
-  DCHECK(clipboard);
-  gchar* selection_text = gtk_clipboard_wait_for_text(clipboard);
-  if (!selection_text)
-    return false;
-
-  // Use autocomplete to clean up the text, going so far as to turn it into
-  // a search query if necessary.
-  AutocompleteMatch match;
-  profile->GetAutocompleteClassifier()->Classify(UTF8ToWide(selection_text),
-      std::wstring(), false, &match, NULL);
-  g_free(selection_text);
-  if (!match.destination_url.is_valid())
-    return false;
-
-  *url = match.destination_url;
-  return true;
-}
-
-bool AddWindowAlphaChannel(GtkWidget* window) {
-  GdkScreen* screen = gtk_widget_get_screen(window);
-  GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen);
-  if (rgba)
-    gtk_widget_set_colormap(window, rgba);
-
-  return rgba;
-}
-
-void GetTextColors(GdkColor* normal_base,
-                   GdkColor* selected_base,
-                   GdkColor* normal_text,
-                   GdkColor* selected_text) {
-  GtkWidget* fake_entry = gtk_entry_new();
-  GtkStyle* style = gtk_rc_get_style(fake_entry);
-
-  if (normal_base)
-    *normal_base = style->base[GTK_STATE_NORMAL];
-  if (selected_base)
-    *selected_base = style->base[GTK_STATE_SELECTED];
-  if (normal_text)
-    *normal_text = style->text[GTK_STATE_NORMAL];
-  if (selected_text)
-    *selected_text = style->text[GTK_STATE_SELECTED];
-
-  g_object_ref_sink(fake_entry);
-  g_object_unref(fake_entry);
-}
-
-#if defined(OS_CHROMEOS)
-
-GtkWindow* GetDialogTransientParent(GtkWindow* dialog) {
-  GtkWindow* parent = gtk_window_get_transient_for(dialog);
-  if (!parent)
-    parent = chromeos::GetOptionsViewParent();
-
-  return parent;
-}
-
-void ShowDialog(GtkWidget* dialog) {
-  // Make sure all controls are visible so that we get correct size.
-  gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
-
-  // Get dialog window size.
-  gint width = 0;
-  gint height = 0;
-  gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
-
-  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
-      dialog,
-      gtk_window_get_resizable(GTK_WINDOW(dialog)) ?
-          chromeos::DIALOG_FLAG_RESIZEABLE :
-          chromeos::DIALOG_FLAG_DEFAULT,
-      gfx::Size(width, height),
-      gfx::Size());
-}
-
-void ShowDialogWithLocalizedSize(GtkWidget* dialog,
-                                 int width_id,
-                                 int height_id,
-                                 bool resizeable) {
-  int width = (width_id == -1) ? 0 :
-      views::Window::GetLocalizedContentsWidth(width_id);
-  int height = (height_id == -1) ? 0 :
-      views::Window::GetLocalizedContentsHeight(height_id);
-
-  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
-      dialog,
-      resizeable ? chromeos::DIALOG_FLAG_RESIZEABLE :
-                   chromeos::DIALOG_FLAG_DEFAULT,
-      gfx::Size(width, height),
-      gfx::Size());
-}
-
-void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
-                                          int width_id) {
-  int width = (width_id == -1) ? 0 :
-      views::Window::GetLocalizedContentsWidth(width_id);
-
-  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
-      dialog,
-      chromeos::DIALOG_FLAG_MODAL,
-      gfx::Size(),
-      gfx::Size(width, 0));
-}
-
-void PresentWindow(GtkWidget* window, int timestamp) {
-  GtkWindow* host_window = chromeos::GetNativeDialogWindow(window);
-  if (!host_window)
-      host_window = GTK_WINDOW(window);
-  if (timestamp)
-    gtk_window_present_with_time(host_window, timestamp);
-  else
-    gtk_window_present(host_window);
-}
-
-GtkWindow* GetDialogWindow(GtkWidget* dialog) {
-  return chromeos::GetNativeDialogWindow(dialog);
-}
-
-gfx::Rect GetDialogBounds(GtkWidget* dialog) {
-  return chromeos::GetNativeDialogContentsBounds(dialog);
-}
-
-#else
-
-void ShowDialog(GtkWidget* dialog) {
-  gtk_widget_show_all(dialog);
-}
-
-void ShowDialogWithLocalizedSize(GtkWidget* dialog,
-                                 int width_id,
-                                 int height_id,
-                                 bool resizeable) {
-  gtk_widget_realize(dialog);
-  SetWindowSizeFromResources(GTK_WINDOW(dialog),
-                             width_id,
-                             height_id,
-                             resizeable);
-  gtk_widget_show_all(dialog);
-}
-
-void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
-                                          int width_id) {
-  gtk_widget_show_all(dialog);
-
-  // Suggest a minimum size.
-  gint width;
-  GtkRequisition req;
-  gtk_widget_size_request(dialog, &req);
-  gtk_util::GetWidgetSizeFromResources(dialog, width_id, 0, &width, NULL);
-  if (width > req.width)
-    gtk_widget_set_size_request(dialog, width, -1);
-}
-
-void PresentWindow(GtkWidget* window, int timestamp) {
-  if (timestamp)
-    gtk_window_present_with_time(GTK_WINDOW(window), timestamp);
-  else
-    gtk_window_present(GTK_WINDOW(window));
-}
-
-GtkWindow* GetDialogWindow(GtkWidget* dialog) {
-  return GTK_WINDOW(dialog);
-}
-
-gfx::Rect GetDialogBounds(GtkWidget* dialog) {
-  gint x = 0, y = 0, width = 1, height = 1;
-  gtk_window_get_position(GTK_WINDOW(dialog), &x, &y);
-  gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
-
-  return gfx::Rect(x, y, width, height);
-}
-
-#endif
-
-string16 GetStockPreferencesMenuLabel() {
-  GtkStockItem stock_item;
-  string16 preferences;
-  if (gtk_stock_lookup(GTK_STOCK_PREFERENCES, &stock_item)) {
-    const char16 kUnderscore[] = { '_', 0 };
-    RemoveChars(UTF8ToUTF16(stock_item.label), kUnderscore, &preferences);
-  }
-  return preferences;
-}
-
-bool IsWidgetAncestryVisible(GtkWidget* widget) {
-  GtkWidget* parent = widget;
-  while (parent && GTK_WIDGET_VISIBLE(parent))
-    parent = parent->parent;
-  return !parent;
-}
-
-void SetGtkFont(const std::string& font_name) {
-  g_object_set(gtk_settings_get_default(),
-               "gtk-font-name", font_name.c_str(), NULL);
-}
-
-void SetLabelWidth(GtkWidget* label, int pixel_width) {
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-
-  // Do the simple thing in LTR because the bug only affects right-aligned
-  // text. Also, when using the workaround, the label tries to maintain
-  // uniform line-length, which we don't really want.
-  if (gtk_widget_get_direction(label) == GTK_TEXT_DIR_LTR) {
-    gtk_widget_set_size_request(label, pixel_width, -1);
-  } else {
-    // The label has to be realized before we can adjust its width.
-    if (GTK_WIDGET_REALIZED(label)) {
-      OnLabelRealize(label, GINT_TO_POINTER(pixel_width));
-    } else {
-      g_signal_connect(label, "realize", G_CALLBACK(OnLabelRealize),
-                       GINT_TO_POINTER(pixel_width));
-    }
-  }
-}
-
-void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label) {
-  GtkRequisition size;
-  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
-  gtk_widget_set_size_request(label, -1, -1);
-  gtk_widget_size_request(label, &size);
-  gtk_widget_set_size_request(label, size.width, size.height);
-  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
-}
-
-GdkDragAction WebDragOpToGdkDragAction(WebDragOperationsMask op) {
-  GdkDragAction action = static_cast<GdkDragAction>(0);
-  if (op & WebDragOperationCopy)
-    action = static_cast<GdkDragAction>(action | GDK_ACTION_COPY);
-  if (op & WebDragOperationLink)
-    action = static_cast<GdkDragAction>(action | GDK_ACTION_LINK);
-  if (op & WebDragOperationMove)
-    action = static_cast<GdkDragAction>(action | GDK_ACTION_MOVE);
-  return action;
-}
-
-WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action) {
-  WebDragOperationsMask op = WebDragOperationNone;
-  if (action & GDK_ACTION_COPY)
-    op = static_cast<WebDragOperationsMask>(op | WebDragOperationCopy);
-  if (action & GDK_ACTION_LINK)
-    op = static_cast<WebDragOperationsMask>(op | WebDragOperationLink);
-  if (action & GDK_ACTION_MOVE)
-    op = static_cast<WebDragOperationsMask>(op | WebDragOperationMove);
-  return op;
-}
-
-void ApplyMessageDialogQuirks(GtkWidget* dialog) {
-  if (gtk_window_get_modal(GTK_WINDOW(dialog))) {
-    // Work around a KDE 3 window manager bug.
-    scoped_ptr<base::Environment> env(base::Environment::Create());
-    if (base::nix::DESKTOP_ENVIRONMENT_KDE3 ==
-        base::nix::GetDesktopEnvironment(env.get()))
-      gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
-  }
-}
-
-// Performs Cut/Copy/Paste operation on the |window|.
-// If the current render view is focused, then just call the specified |method|
-// against the current render view host, otherwise emit the specified |signal|
-// against the focused widget.
-// TODO(suzhe): This approach does not work for plugins.
-void DoCutCopyPaste(BrowserWindow* window,
-                    void (RenderViewHost::*method)(),
-                    const char* signal) {
-  GtkWidget* widget = GetBrowserWindowFocusedWidget(window);
-  if (widget == NULL)
-    return;  // Do nothing if no focused widget.
-
-  TabContents* current_tab = GetBrowserWindowSelectedTabContents(window);
-  if (current_tab && widget == current_tab->GetContentNativeView()) {
-    (current_tab->render_view_host()->*method)();
-  } else {
-    guint id;
-    if ((id = g_signal_lookup(signal, G_OBJECT_TYPE(widget))) != 0)
-      g_signal_emit(widget, id, 0);
-  }
-}
-
-void DoCut(BrowserWindow* window) {
-  DoCutCopyPaste(window, &RenderViewHost::Cut, "cut-clipboard");
-}
-
-void DoCopy(BrowserWindow* window) {
-  DoCutCopyPaste(window, &RenderViewHost::Copy, "copy-clipboard");
-}
-
-void DoPaste(BrowserWindow* window) {
-  DoCutCopyPaste(window, &RenderViewHost::Paste, "paste-clipboard");
-}
-
-}  // namespace gtk_util
diff --git a/chrome/browser/gtk/gtk_util.h b/chrome/browser/gtk/gtk_util.h
deleted file mode 100644
index 894abc6..0000000
--- a/chrome/browser/gtk/gtk_util.h
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_GTK_UTIL_H_
-#define CHROME_BROWSER_GTK_GTK_UTIL_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <string>
-#include <vector>
-
-#include "app/x11_util.h"
-#include "base/string16.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
-#include "webkit/glue/window_open_disposition.h"
-
-typedef struct _cairo cairo_t;
-typedef struct _GdkColor GdkColor;
-typedef struct _GtkWidget GtkWidget;
-
-class BrowserWindow;
-class GtkThemeProvider;
-class GURL;
-class Profile;
-struct RendererPreferences;  // from common/renderer_preferences.h
-
-const int kSkiaToGDKMultiplier = 257;
-
-// Define a macro for creating GdkColors from RGB values.  This is a macro to
-// allow static construction of literals, etc.  Use this like:
-//   GdkColor white = GDK_COLOR_RGB(0xff, 0xff, 0xff);
-#define GDK_COLOR_RGB(r, g, b) {0, r * kSkiaToGDKMultiplier, \
-        g * kSkiaToGDKMultiplier, b * kSkiaToGDKMultiplier}
-
-namespace event_utils {
-
-// Translates event flags into what kind of disposition they represent.
-// For example, a middle click would mean to open a background tab.
-// event_flags are the state in the GdkEvent structure.
-WindowOpenDisposition DispositionFromEventFlags(guint state);
-
-}  // namespace event_utils
-
-namespace gtk_util {
-
-extern const GdkColor kGdkWhite;
-extern const GdkColor kGdkGray;
-extern const GdkColor kGdkBlack;
-extern const GdkColor kGdkGreen;
-
-// Constants relating to the layout of dialog windows:
-// (See http://library.gnome.org/devel/hig-book/stable/design-window.html.en)
-
-// Spacing between controls of the same group.
-const int kControlSpacing = 6;
-
-// Horizontal spacing between a label and its control.
-const int kLabelSpacing = 12;
-
-// Indent of the controls within each group.
-const int kGroupIndent = 12;
-
-// Space around the outside of a dialog's contents.
-const int kContentAreaBorder = 12;
-
-// Spacing between groups of controls.
-const int kContentAreaSpacing = 18;
-
-// Horizontal Spacing between controls in a form.
-const int kFormControlSpacing = 10;
-
-// Create a table of labeled controls, using proper spacing and alignment.
-// Arguments should be pairs of const char*, GtkWidget*, concluding with a
-// NULL.  The first argument is a vector in which to place all labels
-// produced. It can be NULL if you don't need to keep track of the label
-// widgets. The second argument is a color to force the label text to. It can
-// be NULL to get the system default.
-//
-// For example:
-// controls = CreateLabeledControlsGroup(NULL,
-//                                       "Name:", title_entry_,
-//                                       "Folder:", folder_combobox_,
-//                                       NULL);
-GtkWidget* CreateLabeledControlsGroup(
-    std::vector<GtkWidget*>* labels,
-    const char* text, ...);
-
-// Create a GtkBin with |child| as its child widget.  This bin will paint a
-// border of color |color| with the sizes specified in pixels.
-GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
-                              int top, int bottom, int left, int right);
-
-// Left-align the given GtkMisc and return the same pointer.
-GtkWidget* LeftAlignMisc(GtkWidget* misc);
-
-// Create a left-aligned label with the given text in bold.
-GtkWidget* CreateBoldLabel(const std::string& text);
-
-// As above, but uses number of characters/lines directly rather than looking up
-// a resource.
-void GetWidgetSizeFromCharacters(GtkWidget* widget,
-                                 double width_chars, double height_lines,
-                                 int* width, int* height);
-
-// Calculates the size of given widget based on the size specified in number of
-// characters/lines (in locale specific resource file) and font metrics.
-// NOTE: Make sure to realize |widget| before using this method, or a default
-// font size will be used instead of the actual font size.
-void GetWidgetSizeFromResources(GtkWidget* widget,
-                                int width_chars, int height_lines,
-                                int* width, int* height);
-
-// As above, but a convenience method for configuring dialog size.
-// |width_id| and |height_id| are resource IDs for the size.  If either of these
-// are set to -1, the respective size will be set to the widget default.
-// |resizable| also controls whether the dialog will be resizable
-// (this info is also necessary for getting the width-setting code
-// right).
-void SetWindowSizeFromResources(GtkWindow* window,
-                                int width_id, int height_id, bool resizable);
-
-// Places |window| approximately over center of |parent|, it also moves window
-// to parent's desktop. Use this only for non-modal dialogs, such as the
-// options window and content settings window; otherwise you should be using
-// transient_for.
-void CenterOverWindow(GtkWindow* window, GtkWindow* parent);
-
-// Puts all browser windows in one window group; this will make any dialog
-// spawned app modal.
-void MakeAppModalWindowGroup();
-
-// Called after an app modal dialog that used MakeAppModalWindowGroup() was
-// dismissed. Returns each browser window to its own window group.
-void AppModalDismissedUngroupWindows();
-
-// Remove all children from this container.
-void RemoveAllChildren(GtkWidget* container);
-
-// Force the font size of the widget to |size_pixels|.
-void ForceFontSizePixels(GtkWidget* widget, double size_pixels);
-
-// Undoes the effects of a previous ForceFontSizePixels() call. Safe to call
-// even if ForceFontSizePixels() was never called.
-void UndoForceFontSize(GtkWidget* widget);
-
-// Gets the position of a gtk widget in screen coordinates.
-gfx::Point GetWidgetScreenPosition(GtkWidget* widget);
-
-// Returns the bounds of the specified widget in screen coordinates.
-gfx::Rect GetWidgetScreenBounds(GtkWidget* widget);
-
-// Retuns size of the |widget| without window manager decorations.
-gfx::Size GetWidgetSize(GtkWidget* widget);
-
-// Converts a point in a widget to screen coordinates.  The point |p| is
-// relative to the widget's top-left origin.
-void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p);
-
-// Initialize some GTK settings so that our dialogs are consistent.
-void InitRCStyles();
-
-// Stick the widget in the given hbox without expanding vertically. The widget
-// is packed at the start of the hbox. This is useful for widgets that would
-// otherwise expand to fill the vertical space of the hbox
-// (e.g. buttons). Returns the vbox that widget was packed in.
-GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
-                              bool pack_at_end, int padding);
-
-// Returns true if the screen is composited, false otherwise.
-bool IsScreenComposited();
-
-// Enumerates the top-level gdk windows of the current display.
-void EnumerateTopLevelWindows(x11_util::EnumerateWindowsDelegate* delegate);
-
-// Set that clicking the button with the given mouse buttons will cause a click
-// event.
-// NOTE: If you need to connect to the button-press-event or
-// button-release-event signals, do so before calling this function.
-void SetButtonClickableByMouseButtons(GtkWidget* button,
-                                      bool left, bool middle, bool right);
-
-// Set that a button causes a page navigation. In particular, it will accept
-// middle clicks. Warning: only call this *after* you have connected your
-// own handlers for button-press and button-release events, or you will not get
-// those events.
-void SetButtonTriggersNavigation(GtkWidget* button);
-
-// Returns the mirrored x value for |bounds| if the layout is RTL; otherwise,
-// the original value is returned unchanged.
-int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds);
-
-// Returns the mirrored x value for the point |x| if the layout is RTL;
-// otherwise, the original value is returned unchanged.
-int MirroredXCoordinate(GtkWidget* widget, int x);
-
-// Returns true if the pointer is currently inside the widget.
-bool WidgetContainsCursor(GtkWidget* widget);
-
-// Sets the icon of |window| to the product icon (potentially used in window
-// border or alt-tab list).
-void SetWindowIcon(GtkWindow* window);
-
-// Sets the default window icon for windows created in this app.
-void SetDefaultWindowIcon();
-
-// Adds an action button with the given text to the dialog. Only useful when you
-// want a stock icon but not the stock text to go with it. Returns the button.
-GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
-                             const gchar* stock_id, gint response_id);
-
-GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
-                             const gchar* stock_id);
-
-GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image);
-
-// Sets all the foreground color states of |label| to |color|.
-void SetLabelColor(GtkWidget* label, const GdkColor* color);
-
-// Adds the given widget to an alignment identing it by |kGroupIndent|.
-GtkWidget* IndentWidget(GtkWidget* content);
-
-// Sets (or resets) the font settings in |prefs| (used when creating new
-// renderers) based on GtkSettings (which itself comes from XSETTINGS).
-void UpdateGtkFontSettings(RendererPreferences* prefs);
-
-// Get the current location of the mouse cursor relative to the screen.
-gfx::Point ScreenPoint(GtkWidget* widget);
-
-// Get the current location of the mouse cursor relative to the widget.
-gfx::Point ClientPoint(GtkWidget* widget);
-
-// Reverses a point in RTL mode. Used in making vectors of GdkPoints for window
-// shapes.
-GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr);
-
-// Draws a GTK text entry with the style parameters of GtkEntry
-// |offscreen_entry| onto |widget_to_draw_on| in the rectangle |rec|. Drawing
-// is only done in the clip rectangle |dirty_rec|.
-void DrawTextEntryBackground(GtkWidget* offscreen_entry,
-                             GtkWidget* widget_to_draw_on,
-                             GdkRectangle* dirty_rec,
-                             GdkRectangle* rec);
-
-// Draws the background of the toolbar area subject to the expose rectangle
-// |event| and starting image tiling from |tabstrip_origin|.
-void DrawThemedToolbarBackground(GtkWidget* widget,
-                                 cairo_t* cr,
-                                 GdkEventExpose* event,
-                                 const gfx::Point& tabstrip_origin,
-                                 GtkThemeProvider* provider);
-
-// Returns the two colors averaged together.
-GdkColor AverageColors(GdkColor color_one, GdkColor color_two);
-
-// Show the image for the given menu item, even if the user's default is to not
-// show images. Only to be used for favicons or other menus where the image is
-// crucial to its functionality.
-void SetAlwaysShowImage(GtkWidget* image_menu_item);
-
-// Stacks a |popup| window directly on top of a |toplevel| window.
-void StackPopupWindow(GtkWidget* popup, GtkWidget* toplevel);
-
-// Get a rectangle corresponding to a widget's allocation relative to its
-// toplevel window's origin.
-gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget);
-
-// Don't allow the widget to paint anything, and instead propagate the expose
-// to its children. This is similar to calling
-//
-//   gtk_widget_set_app_paintable(container, TRUE);
-//
-// except that it will always work, and it should be called after any custom
-// expose events are connected.
-void SuppressDefaultPainting(GtkWidget* container);
-
-// Get the window open disposition from the state in gtk_get_current_event().
-// This is designed to be called inside a "clicked" event handler. It is an
-// error to call it when gtk_get_current_event() won't return a GdkEventButton*.
-WindowOpenDisposition DispositionForCurrentButtonPressEvent();
-
-// Safely grabs all input (with X grabs and an application grab), returning true
-// for success.
-bool GrabAllInput(GtkWidget* widget);
-
-// Returns a rectangle that represents the widget's bounds. The rectangle it
-// returns is the same as widget->allocation, but anchored at (0, 0).
-gfx::Rect WidgetBounds(GtkWidget* widget);
-
-// Update the timestamp for the given window. This is usually the time of the
-// last user event, but on rare occasions we wish to update it despite not
-// receiving a user event.
-void SetWMLastUserActionTime(GtkWindow* window);
-
-// The current system time, using the format expected by the X server, but not
-// retrieved from the X server. NOTE: You should almost never need to use this
-// function, instead using the timestamp from the latest GDK event.
-guint32 XTimeNow();
-
-// Uses the autocomplete controller for |profile| to convert the contents of the
-// PRIMARY selection to a parsed URL. Returns true and sets |url| on success,
-// otherwise returns false.
-bool URLFromPrimarySelection(Profile* profile, GURL* url);
-
-// Set the colormap of the given window to rgba to allow transparency.
-bool AddWindowAlphaChannel(GtkWidget* window);
-
-// Get the default colors for a text entry.  Parameters may be NULL.
-void GetTextColors(GdkColor* normal_base,
-                   GdkColor* selected_base,
-                   GdkColor* normal_text,
-                   GdkColor* selected_text);
-
-// Wrappers to show a GtkDialog. On Linux, it merely calls gtk_widget_show_all.
-// On ChromeOs, it calls ShowNativeDialog which hosts the its vbox
-// in a view based Window.
-void ShowDialog(GtkWidget* dialog);
-void ShowDialogWithLocalizedSize(GtkWidget* dialog,
-                                 int width_id,
-                                 int height_id,
-                                 bool resizeable);
-void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
-                                          int width_id);
-
-// Wrapper to present a window. On Linux, it just calls gtk_window_present or
-// gtk_window_present_with_time for non-zero timestamp. For ChromeOS, it first
-// finds the host window of the dialog contents and then present it.
-void PresentWindow(GtkWidget* window, int timestamp);
-
-// Get real window for given dialog. On ChromeOS, this gives the native dialog
-// host window. On Linux, it merely returns the passed in dialog.
-GtkWindow* GetDialogWindow(GtkWidget* dialog);
-
-// Gets dialog window bounds.
-gfx::Rect GetDialogBounds(GtkWidget* dialog);
-
-// Returns the stock menu item label for the "preferences" item - returns an
-// empty string if no stock item found.
-string16 GetStockPreferencesMenuLabel();
-
-// Checks whether a widget is actually visible, i.e. whether it and all its
-// ancestors up to its toplevel are visible.
-bool IsWidgetAncestryVisible(GtkWidget* widget);
-
-// Sets the GTK font from the given font name (ex. "Arial Black, 10").
-void SetGtkFont(const std::string& font_name);
-
-// Sets the given label's size request to |pixel_width|. This will cause the
-// label to wrap if it needs to. The reason for this function is that some
-// versions of GTK mis-align labels that have a size request and line wrapping,
-// and this function hides the complexity of the workaround.
-void SetLabelWidth(GtkWidget* label, int pixel_width);
-
-// Make the |label| shrinkable within a GthChromeShrinkableHBox
-// It calculates the real size request of a label and set its ellipsize mode to
-// PANGO_ELLIPSIZE_END.
-// It must be done when the label is mapped (become visible on the screen),
-// to make sure the pango can get correct font information for the calculation.
-void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label);
-
-// Convenience methods for converting between web drag operations and the GDK
-// equivalent.
-GdkDragAction WebDragOpToGdkDragAction(WebKit::WebDragOperationsMask op);
-WebKit::WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action);
-
-// A helper function for gtk_message_dialog_new() to work around a few KDE 3
-// window manager bugs. You should always call it after creating a dialog with
-// gtk_message_dialog_new.
-void ApplyMessageDialogQuirks(GtkWidget* dialog);
-
-// Performs Cut/Copy/Paste operation on the |window|.
-void DoCut(BrowserWindow* window);
-void DoCopy(BrowserWindow* window);
-void DoPaste(BrowserWindow* window);
-
-}  // namespace gtk_util
-
-#endif  // CHROME_BROWSER_GTK_GTK_UTIL_H_
diff --git a/chrome/browser/gtk/hover_controller_gtk.cc b/chrome/browser/gtk/hover_controller_gtk.cc
deleted file mode 100644
index f7fe91a..0000000
--- a/chrome/browser/gtk/hover_controller_gtk.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/hover_controller_gtk.h"
-
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-
-static const gchar* kHoverControllerGtkKey = "__HOVER_CONTROLLER_GTK__";
-
-HoverControllerGtk::HoverControllerGtk(GtkWidget* button)
-    : throb_animation_(this),
-      hover_animation_(this),
-      button_(button) {
-  g_object_ref(button_);
-  gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0);
-
-  signals_.Connect(button_, "enter-notify-event",
-                   G_CALLBACK(OnEnterThunk), this);
-  signals_.Connect(button_, "leave-notify-event",
-                   G_CALLBACK(OnLeaveThunk), this);
-  signals_.Connect(button_, "destroy",
-                   G_CALLBACK(OnDestroyThunk), this);
-  signals_.Connect(button_, "hierarchy-changed",
-                   G_CALLBACK(OnHierarchyChangedThunk), this);
-
-#ifndef NDEBUG
-  if (g_object_get_data(G_OBJECT(button_), kHoverControllerGtkKey))
-    NOTREACHED();
-#endif  // !NDEBUG
-
-  g_object_set_data(G_OBJECT(button), kHoverControllerGtkKey, this);
-}
-
-HoverControllerGtk::~HoverControllerGtk() {
-}
-
-void HoverControllerGtk::StartThrobbing(int cycles) {
-  throb_animation_.StartThrobbing(cycles);
-}
-
-// static
-GtkWidget* HoverControllerGtk::CreateChromeButton() {
-  GtkWidget* widget = gtk_chrome_button_new();
-  new HoverControllerGtk(widget);
-  return widget;
-}
-
-// static
-HoverControllerGtk* HoverControllerGtk::GetHoverControllerGtk(
-    GtkWidget* button) {
-  return reinterpret_cast<HoverControllerGtk*>(
-      g_object_get_data(G_OBJECT(button), kHoverControllerGtkKey));
-}
-
-void HoverControllerGtk::Destroy() {
-  gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), -1.0);
-
-  g_object_set_data(G_OBJECT(button_), kHoverControllerGtkKey, NULL);
-  g_object_unref(button_);
-  button_ = NULL;
-
-  delete this;
-}
-
-void HoverControllerGtk::AnimationProgressed(const ui::Animation* animation) {
-  if (!button_)
-    return;
-
-  // Ignore the hover animation if we are throbbing.
-  if (animation == &hover_animation_ && throb_animation_.is_animating())
-    return;
-
-  gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_),
-                                    animation->GetCurrentValue());
-}
-
-void HoverControllerGtk::AnimationEnded(const ui::Animation* animation) {
-  if (!button_)
-    return;
-  if (animation != &throb_animation_)
-    return;
-
-  if (throb_animation_.cycles_remaining() <= 1)
-    gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0);
-}
-
-void HoverControllerGtk::AnimationCanceled(const ui::Animation* animation) {
-  AnimationEnded(animation);
-}
-
-gboolean HoverControllerGtk::OnEnter(GtkWidget* widget,
-                                     GdkEventCrossing* event) {
-  hover_animation_.Show();
-
-  return FALSE;
-}
-
-gboolean HoverControllerGtk::OnLeave(GtkWidget* widget,
-                                     GdkEventCrossing* event) {
-  // When the user is holding a mouse button, we don't want to animate.
-  if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) {
-    hover_animation_.Reset();
-    gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0);
-  } else {
-    hover_animation_.Hide();
-  }
-
-  return FALSE;
-}
-
-void HoverControllerGtk::OnHierarchyChanged(GtkWidget* widget,
-                                            GtkWidget* previous_toplevel) {
-  // GTK+ does not emit leave-notify-event signals when a widget
-  // becomes unanchored, so manually unset the hover states.
-  if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget))) {
-    gtk_widget_set_state(button_, GTK_STATE_NORMAL);
-    hover_animation_.Reset();
-    gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0.0);
-  }
-}
-
-void HoverControllerGtk::OnDestroy(GtkWidget* widget) {
-  Destroy();
-}
diff --git a/chrome/browser/gtk/hover_controller_gtk.h b/chrome/browser/gtk/hover_controller_gtk.h
deleted file mode 100644
index 9172167..0000000
--- a/chrome/browser/gtk/hover_controller_gtk.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_HOVER_CONTROLLER_GTK_H_
-#define CHROME_BROWSER_GTK_HOVER_CONTROLLER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-#include "ui/base/animation/throb_animation.h"
-
-// This class handles the "throbbing" of a GtkChromeButton. The visual effect
-// of throbbing is created by painting partially transparent hover effects. It
-// only works in non-gtk theme mode. This class mainly exists to glue an
-// AnimationDelegate (C++ class) to a GtkChromeButton* (GTK/c object).
-class HoverControllerGtk : public ui::AnimationDelegate {
- public:
-  virtual ~HoverControllerGtk();
-
-  GtkWidget* button() { return button_; }
-
-  // Throb for |cycles| cycles. This will override the current remaining
-  // number of cycles. Note that a "cycle" is (somewhat unintuitively) half of
-  // a complete throb revolution.
-  void StartThrobbing(int cycles);
-
-  // Get the HoverControllerGtk for a given GtkChromeButton*. It is an error
-  // to call this on a widget that is not a GtkChromeButton*.
-  static HoverControllerGtk* GetHoverControllerGtk(GtkWidget* button);
-
-  // Creates a GtkChromeButton and adds a HoverControllerGtk for it.
-  static GtkWidget* CreateChromeButton();
-
-  // Stop throbbing and delete |this|.
-  void Destroy();
-
- private:
-  explicit HoverControllerGtk(GtkWidget* button);
-
-  // Overridden from ui::AnimationDelegate.
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-  virtual void AnimationCanceled(const ui::Animation* animation);
-
-  CHROMEGTK_CALLBACK_1(HoverControllerGtk, gboolean, OnEnter,
-                       GdkEventCrossing*);
-  CHROMEGTK_CALLBACK_1(HoverControllerGtk, gboolean, OnLeave,
-                       GdkEventCrossing*);
-  CHROMEGTK_CALLBACK_1(HoverControllerGtk, void, OnHierarchyChanged,
-                       GtkWidget*);
-  CHROMEGTK_CALLBACK_0(HoverControllerGtk, void, OnDestroy);
-
-  ui::ThrobAnimation throb_animation_;
-  ui::SlideAnimation hover_animation_;
-  GtkWidget* button_;
-
-  GtkSignalRegistrar signals_;
-
-  DISALLOW_COPY_AND_ASSIGN(HoverControllerGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_HOVER_CONTROLLER_GTK_H_
diff --git a/chrome/browser/gtk/html_dialog_gtk.cc b/chrome/browser/gtk/html_dialog_gtk.cc
deleted file mode 100644
index d0d18b2..0000000
--- a/chrome/browser/gtk/html_dialog_gtk.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/html_dialog_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/dom_ui/html_dialog_ui.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/tab_contents_container_gtk.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/native_web_keyboard_event.h"
-#include "ipc/ipc_message.h"
-
-// static
-void HtmlDialogGtk::ShowHtmlDialogGtk(Browser* browser,
-                                      HtmlDialogUIDelegate* delegate,
-                                      gfx::NativeWindow parent_window) {
-  HtmlDialogGtk* html_dialog =
-      new HtmlDialogGtk(browser->profile(), delegate, parent_window);
-  html_dialog->InitDialog();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// HtmlDialogGtk, public:
-
-HtmlDialogGtk::HtmlDialogGtk(Profile* profile,
-                             HtmlDialogUIDelegate* delegate,
-                             gfx::NativeWindow parent_window)
-    : HtmlDialogTabContentsDelegate(profile),
-      delegate_(delegate),
-      parent_window_(parent_window),
-      dialog_(NULL) {
-}
-
-HtmlDialogGtk::~HtmlDialogGtk() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// HtmlDialogUIDelegate implementation:
-
-bool HtmlDialogGtk::IsDialogModal() const {
-  return delegate_ ? delegate_->IsDialogModal() : false;
-}
-
-std::wstring HtmlDialogGtk::GetDialogTitle() const {
-  return delegate_ ? delegate_->GetDialogTitle() : L"";
-}
-
-GURL HtmlDialogGtk::GetDialogContentURL() const {
-  if (delegate_)
-    return delegate_->GetDialogContentURL();
-  else
-    return GURL();
-}
-
-void HtmlDialogGtk::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
-  if (delegate_)
-    delegate_->GetDOMMessageHandlers(handlers);
-  else
-    handlers->clear();
-}
-
-void HtmlDialogGtk::GetDialogSize(gfx::Size* size) const {
-  if (delegate_)
-    delegate_->GetDialogSize(size);
-  else
-    *size = gfx::Size();
-}
-
-std::string HtmlDialogGtk::GetDialogArgs() const {
-  if (delegate_)
-    return delegate_->GetDialogArgs();
-  else
-    return std::string();
-}
-
-void HtmlDialogGtk::OnDialogClosed(const std::string& json_retval) {
-  DCHECK(dialog_);
-
-  Detach();
-  if (delegate_) {
-    HtmlDialogUIDelegate* dialog_delegate = delegate_;
-    delegate_ = NULL;  // We will not communicate further with the delegate.
-    dialog_delegate->OnDialogClosed(json_retval);
-  }
-  gtk_widget_destroy(dialog_);
-  delete this;
-}
-
-bool HtmlDialogGtk::ShouldShowDialogTitle() const {
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabContentsDelegate implementation:
-
-void HtmlDialogGtk::MoveContents(TabContents* source, const gfx::Rect& pos) {
-  // The contained web page wishes to resize itself. We let it do this because
-  // if it's a dialog we know about, we trust it not to be mean to the user.
-}
-
-void HtmlDialogGtk::ToolbarSizeChanged(TabContents* source,
-                                       bool is_animating) {
-  // Ignored.
-}
-
-// A simplified version of BrowserWindowGtk::HandleKeyboardEvent().
-// We don't handle global keyboard shortcuts here, but that's fine since
-// they're all browser-specific. (This may change in the future.)
-void HtmlDialogGtk::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
-  GdkEventKey* os_event = event.os_event;
-  if (!os_event || event.type == WebKit::WebInputEvent::Char)
-    return;
-
-  // To make sure the default key bindings can still work, such as Escape to
-  // close the dialog.
-  gtk_bindings_activate_event(GTK_OBJECT(dialog_), os_event);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// HtmlDialogGtk:
-
-void HtmlDialogGtk::InitDialog() {
-  tab_contents_.reset(
-      new TabContents(profile(), NULL, MSG_ROUTING_NONE, NULL, NULL));
-  tab_contents_->set_delegate(this);
-
-  // This must be done before loading the page; see the comments in
-  // HtmlDialogUI.
-  HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
-                                                  this);
-
-  tab_contents_->controller().LoadURL(GetDialogContentURL(),
-                                      GURL(), PageTransition::START_PAGE);
-  GtkDialogFlags flags = GTK_DIALOG_NO_SEPARATOR;
-  if (delegate_->IsDialogModal())
-    flags = static_cast<GtkDialogFlags>(flags | GTK_DIALOG_MODAL);
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      WideToUTF8(delegate_->GetDialogTitle()).c_str(),
-      parent_window_,
-      flags,
-      NULL);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-
-  tab_contents_container_.reset(new TabContentsContainerGtk(NULL));
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                     tab_contents_container_->widget(), TRUE, TRUE, 0);
-
-  tab_contents_container_->SetTabContents(tab_contents_.get());
-
-  gfx::Size dialog_size;
-  delegate_->GetDialogSize(&dialog_size);
-
-  gtk_widget_set_size_request(GTK_WIDGET(tab_contents_container_->widget()),
-                              dialog_size.width(),
-                              dialog_size.height());
-
-  gtk_widget_show_all(dialog_);
-}
-
-void HtmlDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
-  OnDialogClosed(std::string());
-}
diff --git a/chrome/browser/gtk/html_dialog_gtk.h b/chrome/browser/gtk/html_dialog_gtk.h
deleted file mode 100644
index 6b4ddda..0000000
--- a/chrome/browser/gtk/html_dialog_gtk.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_HTML_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_HTML_DIALOG_GTK_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/dom_ui/html_dialog_ui.h"
-#include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/size.h"
-
-typedef struct _GtkWidget GtkWidget;
-
-class Browser;
-class Profile;
-class TabContents;
-class TabContentsContainerGtk;
-
-class HtmlDialogGtk : public HtmlDialogTabContentsDelegate,
-                      public HtmlDialogUIDelegate {
- public:
-  HtmlDialogGtk(Profile* profile, HtmlDialogUIDelegate* delegate,
-                gfx::NativeWindow parent_window);
-  virtual ~HtmlDialogGtk();
-
-  static void ShowHtmlDialogGtk(Browser* browser,
-                                HtmlDialogUIDelegate* delegate,
-                                gfx::NativeWindow parent_window);
-  // Initializes the contents of the dialog (the DOMView and the callbacks).
-  void InitDialog();
-
-  // Overridden from HtmlDialogUI::Delegate:
-  virtual bool IsDialogModal() const;
-  virtual std::wstring GetDialogTitle() const;
-  virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
-  virtual void GetDialogSize(gfx::Size* size) const;
-  virtual std::string GetDialogArgs() const;
-  virtual void OnDialogClosed(const std::string& json_retval);
-  virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) { }
-  virtual bool ShouldShowDialogTitle() const;
-
-  // Overridden from TabContentsDelegate:
-  virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
-  virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
-  virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
-
- private:
-  CHROMEGTK_CALLBACK_1(HtmlDialogGtk, void, OnResponse, int);
-
-  // This view is a delegate to the HTML content since it needs to get notified
-  // about when the dialog is closing. For all other actions (besides dialog
-  // closing) we delegate to the creator of this view, which we keep track of
-  // using this variable.
-  HtmlDialogUIDelegate* delegate_;
-
-  gfx::NativeWindow parent_window_;
-
-  GtkWidget* dialog_;
-
-  scoped_ptr<TabContents> tab_contents_;
-  scoped_ptr<TabContentsContainerGtk> tab_contents_container_;
-
-  DISALLOW_COPY_AND_ASSIGN(HtmlDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_HTML_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/hung_renderer_dialog_gtk.cc b/chrome/browser/gtk/hung_renderer_dialog_gtk.cc
deleted file mode 100644
index 5dbed52..0000000
--- a/chrome/browser/gtk/hung_renderer_dialog_gtk.cc
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/hung_renderer_dialog.h"
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/process_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/renderer_host/render_process_host.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/logging_chrome.h"
-#include "chrome/common/result_codes.h"
-#include "gfx/gtk_util.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// A wrapper class that represents the Gtk dialog.
-class HungRendererDialogGtk {
- public:
-  HungRendererDialogGtk();
-  void ShowForTabContents(TabContents* hung_contents);
-  void EndForTabContents(TabContents* hung_contents);
-
- private:
-  // The GtkTreeView column ids.
-  enum {
-    COL_FAVICON,
-    COL_TITLE,
-    COL_COUNT,
-  };
-
-  // Create the gtk dialog and add the widgets.
-  void Init();
-
-  CHROMEGTK_CALLBACK_1(HungRendererDialogGtk, void, OnDialogResponse, gint);
-
-  GtkDialog* dialog_;
-  GtkListStore* model_;
-  TabContents* contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(HungRendererDialogGtk);
-};
-
-// We only support showing one of these at a time per app.
-HungRendererDialogGtk* g_instance = NULL;
-
-// The response ID for the "Kill pages" button.  Anything positive should be
-// fine (the built in GtkResponseTypes are negative numbers).
-const int kKillPagesButtonResponse = 1;
-
-HungRendererDialogGtk::HungRendererDialogGtk()
-    : dialog_(NULL), model_(NULL), contents_(NULL) {
-  Init();
-}
-
-void HungRendererDialogGtk::Init() {
-  dialog_ = GTK_DIALOG(gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE).c_str(),
-      NULL,  // No parent because tabs can span multiple windows.
-      GTK_DIALOG_NO_SEPARATOR,
-      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_END).c_str(),
-      kKillPagesButtonResponse,
-      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT).c_str(),
-      GTK_RESPONSE_OK,
-      NULL));
-  gtk_dialog_set_default_response(dialog_, GTK_RESPONSE_OK);
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-
-  // We have an hbox with the frozen icon on the left.  On the right,
-  // we have a vbox with the unresponsive text on top and a table of
-  // tabs on bottom.
-  // ·-----------------------------------·
-  // |·---------------------------------·|
-  // ||·----·|·------------------------·||
-  // |||icon|||                        |||
-  // ||·----·|| The folowing page(s).. |||
-  // ||      ||                        |||
-  // ||      ||------------------------|||
-  // ||      || table of tabs          |||
-  // ||      |·------------------------·||
-  // |·---------------------------------·|
-  // |                                   |
-  // |         kill button    wait button|
-  // ·-----------------------------------·
-  GtkWidget* contents_vbox = dialog_->vbox;
-  gtk_box_set_spacing(GTK_BOX(contents_vbox), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 12);
-  gtk_box_pack_start(GTK_BOX(contents_vbox), hbox, TRUE, TRUE, 0);
-
-  // Wrap the icon in a vbox so it stays top aligned.
-  GtkWidget* icon_vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), icon_vbox, FALSE, FALSE, 0);
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  GdkPixbuf* icon_pixbuf = rb.GetPixbufNamed(IDR_FROZEN_TAB_ICON);
-  GtkWidget* icon = gtk_image_new_from_pixbuf(icon_pixbuf);
-  gtk_box_pack_start(GTK_BOX(icon_vbox), icon, FALSE, FALSE, 0);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
-
-  GtkWidget* text = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(text), TRUE);
-  gtk_box_pack_start(GTK_BOX(vbox), text, FALSE, FALSE, 0);
-
-  GtkWidget* scroll_list = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_list),
-      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_list),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_box_pack_start(GTK_BOX(vbox), scroll_list, TRUE, TRUE, 0);
-
-  // The list of hung tabs is GtkTreeView with a GtkListStore as the model.
-  model_ = gtk_list_store_new(COL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING);
-  GtkWidget* tree_view = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(model_));
-  g_object_unref(model_);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
-  GtkTreeViewColumn* column = gtk_tree_view_column_new();
-  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(column, renderer, FALSE);
-  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
-  renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(column, renderer, TRUE);
-  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);
-
-  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
-  gtk_container_add(GTK_CONTAINER(scroll_list), tree_view);
-}
-
-void HungRendererDialogGtk::ShowForTabContents(TabContents* hung_contents) {
-  DCHECK(hung_contents && dialog_);
-  contents_ = hung_contents;
-  gtk_list_store_clear(model_);
-
-  GtkTreeIter tree_iter;
-  for (TabContentsIterator it; !it.done(); ++it) {
-    if (it->GetRenderProcessHost() == hung_contents->GetRenderProcessHost()) {
-      gtk_list_store_append(model_, &tree_iter);
-      std::string title = UTF16ToUTF8(it->GetTitle());
-      if (title.empty())
-        title = UTF16ToUTF8(TabContents::GetDefaultTitle());
-      SkBitmap favicon = it->GetFavIcon();
-
-      GdkPixbuf* pixbuf = NULL;
-      if (favicon.width() > 0)
-        pixbuf = gfx::GdkPixbufFromSkBitmap(&favicon);
-      gtk_list_store_set(model_, &tree_iter,
-          COL_FAVICON, pixbuf,
-          COL_TITLE, title.c_str(),
-          -1);
-      if (pixbuf)
-        g_object_unref(pixbuf);
-    }
-  }
-  gtk_util::ShowDialog(GTK_WIDGET(dialog_));
-}
-
-void HungRendererDialogGtk::EndForTabContents(TabContents* contents) {
-  DCHECK(contents);
-  if (contents_ && contents_->GetRenderProcessHost() ==
-      contents->GetRenderProcessHost()) {
-    gtk_widget_hide(GTK_WIDGET(dialog_));
-    // Since we're closing, we no longer need this TabContents.
-    contents_ = NULL;
-  }
-}
-
-// When the user clicks a button on the dialog or closes the dialog, this
-// callback is called.
-void HungRendererDialogGtk::OnDialogResponse(GtkWidget* widget,
-                                             gint response_id) {
-  DCHECK(g_instance == this);
-  switch (response_id) {
-    case kKillPagesButtonResponse:
-      // Kill the process.
-      if (contents_ && contents_->GetRenderProcessHost()) {
-        base::KillProcess(contents_->GetRenderProcessHost()->GetHandle(),
-                          ResultCodes::HUNG, false);
-      }
-      break;
-
-    case GTK_RESPONSE_OK:
-    case GTK_RESPONSE_DELETE_EVENT:
-      // Start waiting again for responsiveness.
-      if (contents_ && contents_->render_view_host())
-        contents_->render_view_host()->RestartHangMonitorTimeout();
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  gtk_widget_destroy(GTK_WIDGET(dialog_));
-  delete g_instance;
-  g_instance = NULL;
-}
-
-}  // namespace
-
-namespace hung_renderer_dialog {
-
-void ShowForTabContents(TabContents* contents) {
-  if (!logging::DialogsAreSuppressed()) {
-    if (!g_instance)
-      g_instance = new HungRendererDialogGtk();
-    g_instance->ShowForTabContents(contents);
-  }
-}
-
-// static
-void HideForTabContents(TabContents* contents) {
-  if (!logging::DialogsAreSuppressed() && g_instance)
-    g_instance->EndForTabContents(contents);
-}
-
-}  // namespace hung_renderer_dialog
diff --git a/chrome/browser/gtk/import_dialog_gtk.cc b/chrome/browser/gtk/import_dialog_gtk.cc
deleted file mode 100644
index d1f828a..0000000
--- a/chrome/browser/gtk/import_dialog_gtk.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/import_dialog_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Returns true if the checkbox is checked.
-gboolean IsChecked(GtkWidget* widget) {
-  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-}
-
-}   // namespace
-
-// static
-void ImportDialogGtk::Show(GtkWindow* parent, Profile* profile,
-                           int initial_state) {
-  new ImportDialogGtk(parent, profile, initial_state);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ImportObserver implementation:
-void ImportDialogGtk::ImportCanceled() {
-  ImportComplete();
-}
-
-void ImportDialogGtk::ImportComplete() {
-  gtk_widget_destroy(dialog_);
-  delete this;
-}
-
-ImportDialogGtk::ImportDialogGtk(GtkWindow* parent, Profile* profile,
-                                 int initial_state)
-    : parent_(parent),
-      profile_(profile),
-      importer_host_(new ImporterHost(this)),
-      initial_state_(initial_state) {
-  // Build the dialog.
-  std::string dialog_name = l10n_util::GetStringUTF8(
-      IDS_IMPORT_SETTINGS_TITLE);
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      parent,
-      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_REJECT,
-      NULL);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  importer_host_->set_parent_window(GTK_WINDOW(dialog_));
-
-  // Add import button separately as we might need to disable it, if
-  // no supported browsers found.
-  import_button_ = gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(IDS_IMPORT_COMMIT).c_str(),
-      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
-  GTK_WIDGET_SET_FLAGS(import_button_, GTK_CAN_DEFAULT);
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
-
-  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* combo_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  GtkWidget* from = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_LABEL).c_str());
-  gtk_box_pack_start(GTK_BOX(combo_hbox), from, FALSE, FALSE, 0);
-
-  combo_ = gtk_combo_box_new_text();
-  gtk_box_pack_start(GTK_BOX(combo_hbox), combo_, TRUE, TRUE, 0);
-
-  gtk_box_pack_start(GTK_BOX(content_area), combo_hbox, FALSE, FALSE, 0);
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GtkWidget* description = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_IMPORT_ITEMS_LABEL).c_str());
-  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);
-
-  bookmarks_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_IMPORT_FAVORITES_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), bookmarks_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bookmarks_),
-      (initial_state_ & importer::FAVORITES) != 0);
-  g_signal_connect(bookmarks_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  search_engines_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_IMPORT_SEARCH_ENGINES_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), search_engines_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(search_engines_),
-      (initial_state_ & importer::SEARCH_ENGINES) != 0);
-  g_signal_connect(search_engines_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  passwords_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_IMPORT_PASSWORDS_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), passwords_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(passwords_),
-      (initial_state_ & importer::PASSWORDS) != 0);
-  g_signal_connect(passwords_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  history_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_IMPORT_HISTORY_CHKBOX).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), history_, FALSE, FALSE, 0);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(history_),
-      (initial_state_ & importer::HISTORY) !=0);
-  g_signal_connect(history_, "toggled",
-                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
-
-  gtk_box_pack_start(GTK_BOX(content_area), vbox, FALSE, FALSE, 0);
-
-  // Let the user know profiles are being loaded.
-  gtk_combo_box_append_text(GTK_COMBO_BOX(combo_),
-      l10n_util::GetStringUTF8(IDS_IMPORT_LOADING_PROFILES).c_str());
-  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_), 0);
-
-  // Disable controls until source profiles are loaded.
-  SetDialogControlsSensitive(false);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-
-  UpdateDialogButtons();
-
-  gtk_util::ShowDialogWithLocalizedSize(dialog_,
-                                        IDS_IMPORT_DIALOG_WIDTH_CHARS,
-                                        -1,  // height
-                                        false);  // resizable
-}
-
-ImportDialogGtk::~ImportDialogGtk() {
-}
-
-void ImportDialogGtk::SourceProfilesLoaded() {
-  // Detect any supported browsers that we can import from and fill
-  // up the combo box. If none found, disable all controls except cancel.
-  int profiles_count = importer_host_->GetAvailableProfileCount();
-  SetDialogControlsSensitive(profiles_count != 0);
-  gtk_combo_box_remove_text(GTK_COMBO_BOX(combo_), 0);
-  if (profiles_count > 0) {
-    for (int i = 0; i < profiles_count; i++) {
-      std::wstring profile = importer_host_->GetSourceProfileNameAt(i);
-      gtk_combo_box_append_text(GTK_COMBO_BOX(combo_),
-                                WideToUTF8(profile).c_str());
-    }
-    gtk_widget_grab_focus(import_button_);
-  } else {
-    gtk_combo_box_append_text(GTK_COMBO_BOX(combo_),
-      l10n_util::GetStringUTF8(IDS_IMPORT_NO_PROFILE_FOUND).c_str());
-  }
-  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_), 0);
-}
-
-void ImportDialogGtk::OnDialogResponse(GtkWidget* widget, int response) {
-  gtk_widget_hide_all(dialog_);
-  if (response == GTK_RESPONSE_ACCEPT) {
-    uint16 items = GetCheckedItems();
-    if (items == 0) {
-      ImportComplete();
-    } else {
-      const ProfileInfo& source_profile =
-          importer_host_->GetSourceProfileInfoAt(
-          gtk_combo_box_get_active(GTK_COMBO_BOX(combo_)));
-      StartImportingWithUI(parent_, items, importer_host_.get(),
-                           source_profile, profile_, this, false);
-    }
-  } else {
-    ImportCanceled();
-  }
-}
-
-void ImportDialogGtk::OnDialogWidgetClicked(GtkWidget* widget) {
-  UpdateDialogButtons();
-}
-
-void ImportDialogGtk::UpdateDialogButtons() {
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT,
-                                    GetCheckedItems() != 0);
-}
-
-void ImportDialogGtk::SetDialogControlsSensitive(bool sensitive) {
-  gtk_widget_set_sensitive(bookmarks_, sensitive);
-  gtk_widget_set_sensitive(search_engines_, sensitive);
-  gtk_widget_set_sensitive(passwords_, sensitive);
-  gtk_widget_set_sensitive(history_, sensitive);
-  gtk_widget_set_sensitive(import_button_, sensitive);
-}
-
-uint16 ImportDialogGtk::GetCheckedItems() {
-  uint16 items = importer::NONE;
-  if (IsChecked(bookmarks_))
-    items |= importer::FAVORITES;
-  if (IsChecked(search_engines_))
-    items |= importer::SEARCH_ENGINES;
-  if (IsChecked(passwords_))
-    items |= importer::PASSWORDS;
-  if (IsChecked(history_))
-    items |= importer::HISTORY;
-  return items;
-}
diff --git a/chrome/browser/gtk/import_dialog_gtk.h b/chrome/browser/gtk/import_dialog_gtk.h
deleted file mode 100644
index f52b845..0000000
--- a/chrome/browser/gtk/import_dialog_gtk.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_IMPORT_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_IMPORT_DIALOG_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/importer/importer.h"
-
-class AccessibleWidgetHelper;
-class Profile;
-
-class ImportDialogGtk : public ImportObserver,
-                        public ImporterList::Observer {
- public:
-  // Displays the import box to import data from another browser into |profile|
-  // |initial_state| is a bitmask of ImportItems. Each checkbox for the bits in
-  // is checked.
-  static void Show(GtkWindow* parent, Profile* profile, int initial_state);
-
-  // ImportObserver implementation.
-  virtual void ImportCanceled();
-  virtual void ImportComplete();
-
- private:
-  ImportDialogGtk(GtkWindow* parent, Profile* profile, int initial_state);
-  ~ImportDialogGtk();
-
-  // ImporterList::Observer implementation.
-  virtual void SourceProfilesLoaded();
-
-  // Handler to respond to OK or Cancel responses from the dialog.
-  CHROMEGTK_CALLBACK_1(ImportDialogGtk, void, OnDialogResponse, int);
-
-  // Handler to respond to widget clicked actions from the dialog.
-  CHROMEGTK_CALLBACK_0(ImportDialogGtk, void, OnDialogWidgetClicked);
-
-  // Enable or disable the dialog buttons depending on the state of the
-  // checkboxes.
-  void UpdateDialogButtons();
-
-  // Sets the sensitivity of all controls on the dialog except the cancel
-  // button.
-  void SetDialogControlsSensitive(bool sensitive);
-
-  // Create a bitmask from the checkboxes of the dialog.
-  uint16 GetCheckedItems();
-
-  // Parent window
-  GtkWindow* parent_;
-
-  // Import Dialog
-  GtkWidget* dialog_;
-
-  // Combo box that displays list of profiles from which we can import.
-  GtkWidget* combo_;
-
-  // Bookmarks/Favorites checkbox
-  GtkWidget* bookmarks_;
-
-  // Search Engines checkbox
-  GtkWidget* search_engines_;
-
-  // Passwords checkbox
-  GtkWidget* passwords_;
-
-  // History checkbox
-  GtkWidget* history_;
-
-  // Import button.
-  GtkWidget* import_button_;
-
-  // Our current profile
-  Profile* profile_;
-
-  // Utility class that does the actual import.
-  scoped_refptr<ImporterHost> importer_host_;
-
-  int initial_state_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImportDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_IMPORT_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/import_lock_dialog_gtk.cc b/chrome/browser/gtk/import_lock_dialog_gtk.cc
deleted file mode 100644
index 8fcaefe..0000000
--- a/chrome/browser/gtk/import_lock_dialog_gtk.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/import_lock_dialog_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/importer/importer.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-// static
-void ImportLockDialogGtk::Show(GtkWindow* parent, ImporterHost* importer_host) {
-  new ImportLockDialogGtk(parent, importer_host);
-}
-
-ImportLockDialogGtk::ImportLockDialogGtk(GtkWindow* parent,
-    ImporterHost* importer_host) : importer_host_(importer_host) {
-  // Build the dialog.
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_TITLE).c_str(),
-      parent,
-      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      NULL);
-
-  gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_CANCEL).c_str(),
-      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
-  gtk_util::AddButtonToDialog(dialog_,
-      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_OK).c_str(),
-      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
-
-  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_TEXT).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, FALSE, 0);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
-  gtk_widget_show_all(dialog_);
-}
-
-ImportLockDialogGtk::~ImportLockDialogGtk() {}
-
-void ImportLockDialogGtk::OnDialogResponse(GtkWidget* widget, int response) {
-  if (response == GTK_RESPONSE_ACCEPT) {
-    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-        importer_host_.get(), &ImporterHost::OnLockViewEnd, true));
-  } else {
-    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-        importer_host_.get(), &ImporterHost::OnLockViewEnd, false));
-  }
-  gtk_widget_destroy(dialog_);
-  delete this;
-}
diff --git a/chrome/browser/gtk/import_lock_dialog_gtk.h b/chrome/browser/gtk/import_lock_dialog_gtk.h
deleted file mode 100644
index e22e823..0000000
--- a/chrome/browser/gtk/import_lock_dialog_gtk.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_IMPORT_LOCK_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_IMPORT_LOCK_DIALOG_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-
-class ImporterHost;
-
-class ImportLockDialogGtk {
- public:
-  // Displays the Firefox profile locked warning
-  static void Show(GtkWindow* parent, ImporterHost* importer_host);
-
- private:
-  ImportLockDialogGtk(GtkWindow* parent, ImporterHost* importer_host);
-  ~ImportLockDialogGtk();
-
-  CHROMEGTK_CALLBACK_1(ImportLockDialogGtk, void, OnDialogResponse, int);
-
-  // Dialog box
-  GtkWidget* dialog_;
-
-  // Utility class that does the actual import.
-  scoped_refptr<ImporterHost> importer_host_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImportLockDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_IMPORT_LOCK_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/import_progress_dialog_gtk.cc b/chrome/browser/gtk/import_progress_dialog_gtk.cc
deleted file mode 100644
index c70561b..0000000
--- a/chrome/browser/gtk/import_progress_dialog_gtk.cc
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/import_progress_dialog_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-using importer::ALL;
-using importer::BOOKMARKS_HTML;
-using importer::FAVORITES;
-using importer::HISTORY;
-using importer::HOME_PAGE;
-using importer::ImportItem;
-using importer::PASSWORDS;
-using importer::ProfileInfo;
-using importer::SEARCH_ENGINES;
-
-namespace {
-
-void SetItemImportStatus(GtkWidget* label, int res_id, bool is_done) {
-  std::string status = l10n_util::GetStringUTF8(res_id);
-  // Windows version of this has fancy throbbers to indicate progress. Here
-  // we rely on text until we can have something equivalent on Linux.
-  if (is_done)
-    status = "\xE2\x9C\x94 " + status;  // U+2714 HEAVY CHECK MARK
-  else
-    status.append(" ...");
-  gtk_label_set_text(GTK_LABEL(label), status.c_str());
-}
-
-}  // namespace
-
-// static
-void ImportProgressDialogGtk::StartImport(GtkWindow* parent,
-                                          int16 items,
-                                          ImporterHost* importer_host,
-                                          const ProfileInfo& browser_profile,
-                                          Profile* profile,
-                                          ImportObserver* observer,
-                                          bool first_run) {
-  ImportProgressDialogGtk* v = new ImportProgressDialogGtk(
-      WideToUTF16(browser_profile.description), items, importer_host, observer,
-      parent, browser_profile.browser_type == BOOKMARKS_HTML);
-
-  // In headless mode it means that we don't show the progress window, but it
-  // still need it to exist. No user interaction will be required.
-  if (!importer_host->is_headless())
-    v->ShowDialog();
-
-  importer_host->StartImportSettings(browser_profile, profile, items,
-                                     new ProfileWriter(profile),
-                                     first_run);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ImporterHost::Observer implementation:
-void ImportProgressDialogGtk::ImportItemStarted(importer::ImportItem item) {
-  DCHECK(items_ & item);
-  switch (item) {
-    case FAVORITES:
-      SetItemImportStatus(bookmarks_,
-                          IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS, false);
-      break;
-    case SEARCH_ENGINES:
-      SetItemImportStatus(search_engines_,
-                          IDS_IMPORT_PROGRESS_STATUS_SEARCH, false);
-      break;
-    case PASSWORDS:
-      SetItemImportStatus(passwords_,
-                          IDS_IMPORT_PROGRESS_STATUS_PASSWORDS, false);
-      break;
-    case HISTORY:
-      SetItemImportStatus(history_,
-                          IDS_IMPORT_PROGRESS_STATUS_HISTORY, false);
-      break;
-    default:
-      break;
-  }
-}
-
-void ImportProgressDialogGtk::ImportItemEnded(importer::ImportItem item) {
-  DCHECK(items_ & item);
-  switch (item) {
-    case FAVORITES:
-      SetItemImportStatus(bookmarks_,
-                          IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS, true);
-      break;
-    case SEARCH_ENGINES:
-      SetItemImportStatus(search_engines_,
-                          IDS_IMPORT_PROGRESS_STATUS_SEARCH, true);
-      break;
-    case PASSWORDS:
-      SetItemImportStatus(passwords_,
-                          IDS_IMPORT_PROGRESS_STATUS_PASSWORDS, true);
-      break;
-    case HISTORY:
-      SetItemImportStatus(history_,
-                          IDS_IMPORT_PROGRESS_STATUS_HISTORY, true);
-      break;
-    default:
-      break;
-  }
-}
-
-void ImportProgressDialogGtk::ImportStarted() {
-  importing_ = true;
-}
-
-void ImportProgressDialogGtk::ImportEnded() {
-  importing_ = false;
-  importer_host_->SetObserver(NULL);
-  if (observer_)
-    observer_->ImportComplete();
-  CloseDialog();
-}
-
-ImportProgressDialogGtk::ImportProgressDialogGtk(const string16& source_profile,
-    int16 items, ImporterHost* importer_host, ImportObserver* observer,
-    GtkWindow* parent, bool bookmarks_import) :
-    parent_(parent), importing_(true), observer_(observer),
-    items_(items), importer_host_(importer_host) {
-  importer_host_->SetObserver(this);
-
-  // Build the dialog.
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_TITLE).c_str(),
-      parent_,
-      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_REJECT,
-      NULL);
-  importer_host_->set_parent_window(GTK_WINDOW(dialog_));
-
-  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
-  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
-
-  GtkWidget* control_group = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GtkWidget* import_info = gtk_label_new(
-      l10n_util::GetStringFUTF8(IDS_IMPORT_PROGRESS_INFO,
-                                source_profile).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(import_info), TRUE);
-  gtk_widget_set_size_request(import_info, 350, -1);
-  gtk_box_pack_start(GTK_BOX(control_group), import_info, FALSE, FALSE, 0);
-
-  GtkWidget* item_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  if (items_ & HISTORY) {
-    history_ = gtk_label_new(
-        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_HISTORY).c_str());
-    gtk_misc_set_alignment(GTK_MISC(history_), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(item_box), history_, FALSE, FALSE, 0);
-  }
-
-  if (items_ & FAVORITES) {
-    bookmarks_ = gtk_label_new(
-        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS).c_str());
-    gtk_misc_set_alignment(GTK_MISC(bookmarks_), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(item_box), bookmarks_, FALSE, FALSE, 0);
-  }
-
-  if (items_ & SEARCH_ENGINES) {
-    search_engines_ = gtk_label_new(
-        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_SEARCH).c_str());
-    gtk_misc_set_alignment(GTK_MISC(search_engines_), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(item_box), search_engines_, FALSE, FALSE, 0);
-  }
-
-  if (items_ & PASSWORDS) {
-    passwords_ = gtk_label_new(
-        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_PASSWORDS).c_str());
-    gtk_misc_set_alignment(GTK_MISC(passwords_), 0, 0.5);
-    gtk_box_pack_start(GTK_BOX(item_box), passwords_, FALSE, FALSE, 0);
-  }
-
-  gtk_box_pack_start(GTK_BOX(control_group), gtk_util::IndentWidget(item_box),
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(content_area), control_group, FALSE, FALSE, 0);
-
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(HandleOnResponseDialog), this);
-  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
-}
-
-ImportProgressDialogGtk::~ImportProgressDialogGtk() {}
-
-void ImportProgressDialogGtk::CloseDialog() {
-  gtk_widget_destroy(dialog_);
-  dialog_ = NULL;
-  delete this;
-}
-
-void ImportProgressDialogGtk::OnDialogResponse(GtkWidget* widget,
-                                               int response) {
-  if (!importing_) {
-    CloseDialog();
-    return;
-  }
-
-  // Only response to the dialog is to close it so we hide immediately.
-  gtk_widget_hide_all(dialog_);
-  if (response == GTK_RESPONSE_REJECT)
-    importer_host_->Cancel();
-}
-
-void ImportProgressDialogGtk::ShowDialog() {
-  gtk_widget_show_all(dialog_);
-}
-
-
-void StartImportingWithUI(GtkWindow* parent,
-                          uint16 items,
-                          ImporterHost* importer_host,
-                          const ProfileInfo& browser_profile,
-                          Profile* profile,
-                          ImportObserver* observer,
-                          bool first_run) {
-  DCHECK_NE(0, items);
-  ImportProgressDialogGtk::StartImport(parent, items, importer_host,
-                                       browser_profile, profile, observer,
-                                       first_run);
-}
diff --git a/chrome/browser/gtk/import_progress_dialog_gtk.h b/chrome/browser/gtk/import_progress_dialog_gtk.h
deleted file mode 100644
index 360b0de..0000000
--- a/chrome/browser/gtk/import_progress_dialog_gtk.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_IMPORT_PROGRESS_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_IMPORT_PROGRESS_DIALOG_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/importer/importer.h"
-#include "chrome/browser/importer/importer_data_types.h"
-
-class Profile;
-
-class ImportProgressDialogGtk : public ImporterHost::Observer {
- public:
-  // Displays the import progress dialog box and starts the import
-  static void StartImport(GtkWindow* parent, int16 items,
-                          ImporterHost* importer_host,
-                          const ProfileInfo& browser_profile,
-                          Profile* profile,
-                          ImportObserver* observer, bool first_run);
-
-  // Overridden from ImporterHost::Observer:
-  virtual void ImportItemStarted(importer::ImportItem item);
-  virtual void ImportItemEnded(importer::ImportItem item);
-  virtual void ImportStarted();
-  virtual void ImportEnded();
-
- private:
-  ImportProgressDialogGtk(const string16& source_profile, int16 items,
-      ImporterHost* importer_host, ImportObserver* observer,
-      GtkWindow* parent, bool bookmarks_import);
-  virtual ~ImportProgressDialogGtk();
-
-  static void HandleOnResponseDialog(GtkWidget* widget,
-                                     int response,
-                                     gpointer user_data) {
-    reinterpret_cast<ImportProgressDialogGtk*>(user_data)->OnDialogResponse(
-        widget, response);
-  }
-
-  void CloseDialog();
-
-  void OnDialogResponse(GtkWidget* widget, int response);
-
-  void ShowDialog();
-
-  // Parent window
-  GtkWindow* parent_;
-
-  // Import progress dialog
-  GtkWidget* dialog_;
-
-  // Bookmarks/Favorites checkbox
-  GtkWidget* bookmarks_;
-
-  // Search Engines checkbox
-  GtkWidget* search_engines_;
-
-  // Passwords checkbox
-  GtkWidget* passwords_;
-
-  // History checkbox
-  GtkWidget* history_;
-
-  // Boolean that tells whether we are currently in the mid of import process
-  bool importing_;
-
-  // Observer that we need to notify about import events
-  ImportObserver* observer_;
-
-  // Items to import from the other browser.
-  int16 items_;
-
-  // Utility class that does the actual import.
-  scoped_refptr<ImporterHost> importer_host_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImportProgressDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_IMPORT_PROGRESS_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/info_bubble_accelerators_gtk.cc b/chrome/browser/gtk/info_bubble_accelerators_gtk.cc
deleted file mode 100644
index ba04846..0000000
--- a/chrome/browser/gtk/info_bubble_accelerators_gtk.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/info_bubble_accelerators_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-#include <glib.h>
-
-namespace {
-// Listing of the accelerators that are either handled or forwarded by
-// info bubbles. Any accelerators that are not explicitly listed here
-// are ignored and silently dropped. This table is expected to change
-// after discussion over which accelerators should be addressed in
-// info bubbles. For a complete listing of accelerators that are used
-// in chrome consult accelerators_gtk.cc
-struct InfoBubbleAcceleratorGtk InfoBubbleAcceleratorGtkTable[] = {
-  // Tab/window controls.
-  { GDK_w, GDK_CONTROL_MASK},
-
-  // Navigation / toolbar buttons.
-  { GDK_Escape, GdkModifierType(0)}
-};
-
-}  // namespace
-
-InfoBubbleAcceleratorGtkList InfoBubbleAcceleratorsGtk::GetList() {
-  InfoBubbleAcceleratorGtkList accelerators;
-  for (size_t i = 0; i < arraysize(InfoBubbleAcceleratorGtkTable); ++i) {
-    accelerators.push_back(InfoBubbleAcceleratorGtkTable[i]);
-  }
-
-  return accelerators;
-}
diff --git a/chrome/browser/gtk/info_bubble_accelerators_gtk.h b/chrome/browser/gtk/info_bubble_accelerators_gtk.h
deleted file mode 100644
index e208ee3..0000000
--- a/chrome/browser/gtk/info_bubble_accelerators_gtk.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_INFO_BUBBLE_ACCELERATORS_GTK_H_
-#define CHROME_BROWSER_GTK_INFO_BUBBLE_ACCELERATORS_GTK_H_
-#pragma once
-
-#include <gdk/gdktypes.h>
-#include <glib.h>
-#include <vector>
-
-#include "base/basictypes.h"
-
-struct InfoBubbleAcceleratorGtk {
-  guint keyval;
-  GdkModifierType modifier_type;
-};
-
-typedef std::vector<struct InfoBubbleAcceleratorGtk>
-    InfoBubbleAcceleratorGtkList;
-
-// This class contains a list of accelerators that an InfoBubbleGtk
-// is expected to either catch and respond to or catch and forward to the
-// root browser window. This list is expected to be a subset of the
-// accelerators that are handled by the root browser window, but the
-// specific accelerators to be handled has not yet been fully specified. The
-// common use case for this class has code that uses it needing the entire
-// list and not needing extra processing, so the only get method gives you the
-// entire list.
-class InfoBubbleAcceleratorsGtk {
- public:
-  static InfoBubbleAcceleratorGtkList GetList();
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(InfoBubbleAcceleratorsGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_INFO_BUBBLE_ACCELERATORS_GTK_H_
diff --git a/chrome/browser/gtk/info_bubble_gtk.cc b/chrome/browser/gtk/info_bubble_gtk.cc
deleted file mode 100644
index 42dc0d1..0000000
--- a/chrome/browser/gtk/info_bubble_gtk.cc
+++ /dev/null
@@ -1,535 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/info_bubble_accelerators_gtk.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/gtk_util.h"
-#include "gfx/path.h"
-#include "gfx/rect.h"
-
-namespace {
-
-// The height of the arrow, and the width will be about twice the height.
-const int kArrowSize = 8;
-
-// Number of pixels to the middle of the arrow from the close edge of the
-// window.
-const int kArrowX = 18;
-
-// Number of pixels between the tip of the arrow and the region we're
-// pointing to.
-const int kArrowToContentPadding = -4;
-
-// We draw flat diagonal corners, each corner is an NxN square.
-const int kCornerSize = 3;
-
-// Margins around the content.
-const int kTopMargin = kArrowSize + kCornerSize - 1;
-const int kBottomMargin = kCornerSize - 1;
-const int kLeftMargin = kCornerSize - 1;
-const int kRightMargin = kCornerSize - 1;
-
-const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff);
-const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63);
-
-}  // namespace
-
-// static
-InfoBubbleGtk* InfoBubbleGtk::Show(GtkWidget* anchor_widget,
-                                   const gfx::Rect* rect,
-                                   GtkWidget* content,
-                                   ArrowLocationGtk arrow_location,
-                                   bool match_system_theme,
-                                   bool grab_input,
-                                   GtkThemeProvider* provider,
-                                   InfoBubbleGtkDelegate* delegate) {
-  InfoBubbleGtk* bubble = new InfoBubbleGtk(provider, match_system_theme);
-  bubble->Init(anchor_widget, rect, content, arrow_location, grab_input);
-  bubble->set_delegate(delegate);
-  return bubble;
-}
-
-InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider,
-                             bool match_system_theme)
-    : delegate_(NULL),
-      window_(NULL),
-      theme_provider_(provider),
-      accel_group_(gtk_accel_group_new()),
-      toplevel_window_(NULL),
-      anchor_widget_(NULL),
-      mask_region_(NULL),
-      preferred_arrow_location_(ARROW_LOCATION_TOP_LEFT),
-      current_arrow_location_(ARROW_LOCATION_TOP_LEFT),
-      match_system_theme_(match_system_theme),
-      grab_input_(true),
-      closed_by_escape_(false) {
-}
-
-InfoBubbleGtk::~InfoBubbleGtk() {
-  // Notify the delegate that we're about to close.  This gives the chance
-  // to save state / etc from the hosted widget before it's destroyed.
-  if (delegate_)
-    delegate_->InfoBubbleClosing(this, closed_by_escape_);
-
-  g_object_unref(accel_group_);
-  if (mask_region_)
-    gdk_region_destroy(mask_region_);
-}
-
-void InfoBubbleGtk::Init(GtkWidget* anchor_widget,
-                         const gfx::Rect* rect,
-                         GtkWidget* content,
-                         ArrowLocationGtk arrow_location,
-                         bool grab_input) {
-  // If there is a current grab widget (menu, other info bubble, etc.), hide it.
-  GtkWidget* current_grab_widget = gtk_grab_get_current();
-  if (current_grab_widget)
-    gtk_widget_hide(current_grab_widget);
-
-  DCHECK(!window_);
-  anchor_widget_ = anchor_widget;
-  toplevel_window_ = GTK_WINDOW(gtk_widget_get_toplevel(anchor_widget_));
-  DCHECK(GTK_WIDGET_TOPLEVEL(toplevel_window_));
-  rect_ = rect ? *rect : gtk_util::WidgetBounds(anchor_widget);
-  preferred_arrow_location_ = arrow_location;
-
-  grab_input_ = grab_input;
-  // Using a TOPLEVEL window may cause placement issues with certain WMs but it
-  // is necessary to be able to focus the window.
-  window_ = gtk_window_new(grab_input ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
-
-  gtk_widget_set_app_paintable(window_, TRUE);
-  // Resizing is handled by the program, not user.
-  gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
-
-  // Attach all of the accelerators to the bubble.
-  InfoBubbleAcceleratorGtkList acceleratorList =
-      InfoBubbleAcceleratorsGtk::GetList();
-  for (InfoBubbleAcceleratorGtkList::const_iterator iter =
-           acceleratorList.begin();
-       iter != acceleratorList.end();
-       ++iter) {
-    gtk_accel_group_connect(accel_group_,
-                            iter->keyval,
-                            iter->modifier_type,
-                            GtkAccelFlags(0),
-                            g_cclosure_new(G_CALLBACK(&OnGtkAcceleratorThunk),
-                                           this,
-                                           NULL));
-  }
-
-  gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_);
-
-  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
-                            kTopMargin, kBottomMargin,
-                            kLeftMargin, kRightMargin);
-
-  gtk_container_add(GTK_CONTAINER(alignment), content);
-  gtk_container_add(GTK_CONTAINER(window_), alignment);
-
-  // GtkWidget only exposes the bitmap mask interface.  Use GDK to more
-  // efficently mask a GdkRegion.  Make sure the window is realized during
-  // OnSizeAllocate, so the mask can be applied to the GdkWindow.
-  gtk_widget_realize(window_);
-
-  UpdateArrowLocation(true);  // Force move and reshape.
-  StackWindow();
-
-  gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK);
-
-  signals_.Connect(window_, "expose-event", G_CALLBACK(OnExposeThunk), this);
-  signals_.Connect(window_, "size-allocate", G_CALLBACK(OnSizeAllocateThunk),
-                   this);
-  signals_.Connect(window_, "button-press-event",
-                   G_CALLBACK(OnButtonPressThunk), this);
-  signals_.Connect(window_, "destroy", G_CALLBACK(OnDestroyThunk), this);
-  signals_.Connect(window_, "hide", G_CALLBACK(OnHideThunk), this);
-
-  // If the toplevel window is being used as the anchor, then the signals below
-  // are enough to keep us positioned correctly.
-  if (anchor_widget_ != GTK_WIDGET(toplevel_window_)) {
-    signals_.Connect(anchor_widget_, "size-allocate",
-                     G_CALLBACK(OnAnchorAllocateThunk), this);
-    signals_.Connect(anchor_widget_, "destroy",
-                     G_CALLBACK(gtk_widget_destroyed), &anchor_widget_);
-  }
-
-  signals_.Connect(toplevel_window_, "configure-event",
-                   G_CALLBACK(OnToplevelConfigureThunk), this);
-  signals_.Connect(toplevel_window_, "unmap-event",
-                   G_CALLBACK(OnToplevelUnmapThunk), this);
-  // Set |toplevel_window_| to NULL if it gets destroyed.
-  signals_.Connect(toplevel_window_, "destroy",
-                   G_CALLBACK(gtk_widget_destroyed), &toplevel_window_);
-
-  gtk_widget_show_all(window_);
-
-  if (grab_input_) {
-    gtk_grab_add(window_);
-    GrabPointerAndKeyboard();
-  }
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_->InitThemesFor(this);
-}
-
-// NOTE: This seems a bit overcomplicated, but it requires a bunch of careful
-// fudging to get the pixels rasterized exactly where we want them, the arrow to
-// have a 1 pixel point, etc.
-// TODO(deanm): Windows draws with Skia and uses some PNG images for the
-// corners.  This is a lot more work, but they get anti-aliasing.
-// static
-std::vector<GdkPoint> InfoBubbleGtk::MakeFramePolygonPoints(
-    ArrowLocationGtk arrow_location,
-    int width,
-    int height,
-    FrameType type) {
-  using gtk_util::MakeBidiGdkPoint;
-  std::vector<GdkPoint> points;
-
-  bool on_left = (arrow_location == ARROW_LOCATION_TOP_LEFT);
-
-  // If we're stroking the frame, we need to offset some of our points by 1
-  // pixel.  We do this when we draw horizontal lines that are on the bottom or
-  // when we draw vertical lines that are closer to the end (where "end" is the
-  // right side for ARROW_LOCATION_TOP_LEFT).
-  int y_off = (type == FRAME_MASK) ? 0 : -1;
-  // We use this one for arrows located on the left.
-  int x_off_l = on_left ? y_off : 0;
-  // We use this one for RTL.
-  int x_off_r = !on_left ? -y_off : 0;
-
-  // Top left corner.
-  points.push_back(MakeBidiGdkPoint(
-      x_off_r, kArrowSize + kCornerSize - 1, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      kCornerSize + x_off_r - 1, kArrowSize, width, on_left));
-
-  // The arrow.
-  points.push_back(MakeBidiGdkPoint(
-      kArrowX - kArrowSize + x_off_r, kArrowSize, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      kArrowX + x_off_r, 0, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      kArrowX + 1 + x_off_l, 0, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      kArrowX + kArrowSize + 1 + x_off_l, kArrowSize, width, on_left));
-
-  // Top right corner.
-  points.push_back(MakeBidiGdkPoint(
-      width - kCornerSize + 1 + x_off_l, kArrowSize, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      width + x_off_l, kArrowSize + kCornerSize - 1, width, on_left));
-
-  // Bottom right corner.
-  points.push_back(MakeBidiGdkPoint(
-      width + x_off_l, height - kCornerSize, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      width - kCornerSize + x_off_r, height + y_off, width, on_left));
-
-  // Bottom left corner.
-  points.push_back(MakeBidiGdkPoint(
-      kCornerSize + x_off_l, height + y_off, width, on_left));
-  points.push_back(MakeBidiGdkPoint(
-      x_off_r, height - kCornerSize, width, on_left));
-
-  return points;
-}
-
-InfoBubbleGtk::ArrowLocationGtk InfoBubbleGtk::GetArrowLocation(
-    ArrowLocationGtk preferred_location, int arrow_x, int width) {
-  bool wants_left = (preferred_location == ARROW_LOCATION_TOP_LEFT);
-  int screen_width = gdk_screen_get_width(gdk_screen_get_default());
-
-  bool left_is_onscreen = (arrow_x - kArrowX + width < screen_width);
-  bool right_is_onscreen = (arrow_x + kArrowX - width >= 0);
-
-  // Use the requested location if it fits onscreen, use whatever fits
-  // otherwise, and use the requested location if neither fits.
-  if (left_is_onscreen && (wants_left || !right_is_onscreen))
-    return ARROW_LOCATION_TOP_LEFT;
-  if (right_is_onscreen && (!wants_left || !left_is_onscreen))
-    return ARROW_LOCATION_TOP_RIGHT;
-  return (wants_left ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT);
-}
-
-bool InfoBubbleGtk::UpdateArrowLocation(bool force_move_and_reshape) {
-  if (!toplevel_window_ || !anchor_widget_)
-    return false;
-
-  gint toplevel_x = 0, toplevel_y = 0;
-  gdk_window_get_position(
-      GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y);
-  int offset_x, offset_y;
-  gtk_widget_translate_coordinates(anchor_widget_, GTK_WIDGET(toplevel_window_),
-                                   rect_.x(), rect_.y(), &offset_x, &offset_y);
-
-  ArrowLocationGtk old_location = current_arrow_location_;
-  current_arrow_location_ = GetArrowLocation(
-      preferred_arrow_location_,
-      toplevel_x + offset_x + (rect_.width() / 2),  // arrow_x
-      window_->allocation.width);
-
-  if (force_move_and_reshape || current_arrow_location_ != old_location) {
-    UpdateWindowShape();
-    MoveWindow();
-    // We need to redraw the entire window to repaint its border.
-    gtk_widget_queue_draw(window_);
-    return true;
-  }
-  return false;
-}
-
-void InfoBubbleGtk::UpdateWindowShape() {
-  if (mask_region_) {
-    gdk_region_destroy(mask_region_);
-    mask_region_ = NULL;
-  }
-  std::vector<GdkPoint> points = MakeFramePolygonPoints(
-      current_arrow_location_,
-      window_->allocation.width, window_->allocation.height,
-      FRAME_MASK);
-  mask_region_ = gdk_region_polygon(&points[0],
-                                    points.size(),
-                                    GDK_EVEN_ODD_RULE);
-  gdk_window_shape_combine_region(window_->window, NULL, 0, 0);
-  gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0);
-}
-
-void InfoBubbleGtk::MoveWindow() {
-  if (!toplevel_window_ || !anchor_widget_)
-    return;
-
-  gint toplevel_x = 0, toplevel_y = 0;
-  gdk_window_get_position(
-      GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y);
-
-  int offset_x, offset_y;
-  gtk_widget_translate_coordinates(anchor_widget_, GTK_WIDGET(toplevel_window_),
-                                   rect_.x(), rect_.y(), &offset_x, &offset_y);
-
-  gint screen_x = 0;
-  if (current_arrow_location_ == ARROW_LOCATION_TOP_LEFT) {
-    screen_x = toplevel_x + offset_x + (rect_.width() / 2) - kArrowX;
-  } else if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT) {
-    screen_x = toplevel_x + offset_x + (rect_.width() / 2) -
-               window_->allocation.width + kArrowX;
-  } else {
-    NOTREACHED();
-  }
-
-  gint screen_y = toplevel_y + offset_y + rect_.height() +
-                  kArrowToContentPadding;
-
-  gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y);
-}
-
-void InfoBubbleGtk::StackWindow() {
-  // Stack our window directly above the toplevel window.
-  if (toplevel_window_)
-    gtk_util::StackPopupWindow(window_, GTK_WIDGET(toplevel_window_));
-}
-
-void InfoBubbleGtk::Observe(NotificationType type,
-                            const NotificationSource& source,
-                            const NotificationDetails& details) {
-  DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED);
-  if (theme_provider_->UseGtkTheme() && match_system_theme_) {
-    gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL);
-  } else {
-    // Set the background color, so we don't need to paint it manually.
-    gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor);
-  }
-}
-
-void InfoBubbleGtk::HandlePointerAndKeyboardUngrabbedByContent() {
-  if (grab_input_)
-    GrabPointerAndKeyboard();
-}
-
-void InfoBubbleGtk::Close() {
-  // We don't need to ungrab the pointer or keyboard here; the X server will
-  // automatically do that when we destroy our window.
-  DCHECK(window_);
-  gtk_widget_destroy(window_);
-  // |this| has been deleted, see OnDestroy.
-}
-
-void InfoBubbleGtk::GrabPointerAndKeyboard() {
-  // Install X pointer and keyboard grabs to make sure that we have the focus
-  // and get all mouse and keyboard events until we're closed.
-  GdkGrabStatus pointer_grab_status =
-      gdk_pointer_grab(window_->window,
-                       TRUE,                   // owner_events
-                       GDK_BUTTON_PRESS_MASK,  // event_mask
-                       NULL,                   // confine_to
-                       NULL,                   // cursor
-                       GDK_CURRENT_TIME);
-  if (pointer_grab_status != GDK_GRAB_SUCCESS) {
-    // This will fail if someone else already has the pointer grabbed, but
-    // there's not really anything we can do about that.
-    DLOG(ERROR) << "Unable to grab pointer (status="
-                << pointer_grab_status << ")";
-  }
-  GdkGrabStatus keyboard_grab_status =
-      gdk_keyboard_grab(window_->window,
-                        FALSE,  // owner_events
-                        GDK_CURRENT_TIME);
-  if (keyboard_grab_status != GDK_GRAB_SUCCESS) {
-    DLOG(ERROR) << "Unable to grab keyboard (status="
-                << keyboard_grab_status << ")";
-  }
-}
-
-gboolean InfoBubbleGtk::OnGtkAccelerator(GtkAccelGroup* group,
-                                         GObject* acceleratable,
-                                         guint keyval,
-                                         GdkModifierType modifier) {
-  GdkEventKey msg;
-  GdkKeymapKey* keys;
-  gint n_keys;
-
-  switch (keyval) {
-    case GDK_Escape:
-      // Close on Esc and trap the accelerator
-      closed_by_escape_ = true;
-      Close();
-      return TRUE;
-    case GDK_w:
-      // Close on C-w and forward the accelerator
-      if (modifier & GDK_CONTROL_MASK) {
-        Close();
-      }
-      break;
-    default:
-      return FALSE;
-  }
-
-  gdk_keymap_get_entries_for_keyval(NULL,
-                                    keyval,
-                                    &keys,
-                                    &n_keys);
-  if (n_keys) {
-    // Forward the accelerator to root window the bubble is anchored
-    // to for further processing
-    msg.type = GDK_KEY_PRESS;
-    msg.window = GTK_WIDGET(toplevel_window_)->window;
-    msg.send_event = TRUE;
-    msg.time = GDK_CURRENT_TIME;
-    msg.state = modifier | GDK_MOD2_MASK;
-    msg.keyval = keyval;
-    // length and string are deprecated and thus zeroed out
-    msg.length = 0;
-    msg.string = NULL;
-    msg.hardware_keycode = keys[0].keycode;
-    msg.group = keys[0].group;
-    msg.is_modifier = 0;
-
-    g_free(keys);
-
-    gtk_main_do_event(reinterpret_cast<GdkEvent*>(&msg));
-  } else {
-    // This means that there isn't a h/w code for the keyval in the
-    // current keymap, which is weird but possible if the keymap just
-    // changed. This isn't a critical error, but might be indicative
-    // of something off if it happens regularly.
-    DLOG(WARNING) << "Found no keys for value " << keyval;
-  }
-  return TRUE;
-}
-
-gboolean InfoBubbleGtk::OnExpose(GtkWidget* widget, GdkEventExpose* expose) {
-  GdkDrawable* drawable = GDK_DRAWABLE(window_->window);
-  GdkGC* gc = gdk_gc_new(drawable);
-  gdk_gc_set_rgb_fg_color(gc, &kFrameColor);
-
-  // Stroke the frame border.
-  std::vector<GdkPoint> points = MakeFramePolygonPoints(
-      current_arrow_location_,
-      window_->allocation.width, window_->allocation.height,
-      FRAME_STROKE);
-  gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
-
-  g_object_unref(gc);
-  return FALSE;  // Propagate so our children paint, etc.
-}
-
-// When our size is initially allocated or changed, we need to recompute
-// and apply our shape mask region.
-void InfoBubbleGtk::OnSizeAllocate(GtkWidget* widget,
-                                   GtkAllocation* allocation) {
-  if (!UpdateArrowLocation(false)) {
-    UpdateWindowShape();
-    if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT)
-      MoveWindow();
-  }
-}
-
-gboolean InfoBubbleGtk::OnButtonPress(GtkWidget* widget,
-                                      GdkEventButton* event) {
-  // If we got a click in our own window, that's okay (we need to additionally
-  // check that it falls within our bounds, since we've grabbed the pointer and
-  // some events that actually occurred in other windows will be reported with
-  // respect to our window).
-  if (event->window == window_->window &&
-      (mask_region_ && gdk_region_point_in(mask_region_, event->x, event->y))) {
-    return FALSE;  // Propagate.
-  }
-
-  // Our content widget got a click.
-  if (event->window != window_->window &&
-      gdk_window_get_toplevel(event->window) == window_->window) {
-    return FALSE;
-  }
-
-  if (grab_input_) {
-    // Otherwise we had a click outside of our window, close ourself.
-    Close();
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-gboolean InfoBubbleGtk::OnDestroy(GtkWidget* widget) {
-  // We are self deleting, we have a destroy signal setup to catch when we
-  // destroy the widget manually, or the window was closed via X.  This will
-  // delete the InfoBubbleGtk object.
-  delete this;
-  return FALSE;  // Propagate.
-}
-
-void InfoBubbleGtk::OnHide(GtkWidget* widget) {
-  gtk_widget_destroy(widget);
-}
-
-gboolean InfoBubbleGtk::OnToplevelConfigure(GtkWidget* widget,
-                                            GdkEventConfigure* event) {
-  if (!UpdateArrowLocation(false))
-    MoveWindow();
-  StackWindow();
-  return FALSE;
-}
-
-gboolean InfoBubbleGtk::OnToplevelUnmap(GtkWidget* widget, GdkEvent* event) {
-  Close();
-  return FALSE;
-}
-
-void InfoBubbleGtk::OnAnchorAllocate(GtkWidget* widget,
-                                     GtkAllocation* allocation) {
-  if (!UpdateArrowLocation(false))
-    MoveWindow();
-}
diff --git a/chrome/browser/gtk/info_bubble_gtk.h b/chrome/browser/gtk/info_bubble_gtk.h
deleted file mode 100644
index ead0b18..0000000
--- a/chrome/browser/gtk/info_bubble_gtk.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This is the GTK implementation of InfoBubbles.  InfoBubbles are like
-// dialogs, but they point to a given element on the screen.  You should call
-// InfoBubbleGtk::Show, which will create and display a bubble.  The object is
-// self deleting, when the bubble is closed, you will be notified via
-// InfoBubbleGtkDelegate::InfoBubbleClosing().  Then the widgets and the
-// underlying object will be destroyed.  You can also close and destroy the
-// bubble by calling Close().
-
-#ifndef CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_
-#define CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "base/basictypes.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-
-class GtkThemeProvider;
-class InfoBubbleGtk;
-namespace gfx {
-class Rect;
-}
-
-class InfoBubbleGtkDelegate {
- public:
-  // Called when the InfoBubble is closing and is about to be deleted.
-  // |closed_by_escape| is true if the close is the result of pressing escape.
-  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                 bool closed_by_escape) = 0;
-
-  // NOTE: The Views interface has CloseOnEscape, except I can't find a place
-  // where it ever returns false, so we always allow you to close via escape.
-
- protected:
-  virtual ~InfoBubbleGtkDelegate() {}
-};
-
-class InfoBubbleGtk : public NotificationObserver {
- public:
-  // Where should the arrow be placed relative to the bubble?
-  enum ArrowLocationGtk {
-    // TODO(derat): Support placing arrows on the bottoms of the bubbles.
-    ARROW_LOCATION_TOP_LEFT,
-    ARROW_LOCATION_TOP_RIGHT,
-  };
-
-  // Show an InfoBubble, pointing at the area |rect| (in coordinates relative to
-  // |anchor_widget|'s origin).  An info bubble will try to fit on the screen,
-  // so it can point to any edge of |rect|.  If |rect| is NULL, the widget's
-  // entire area will be used. The bubble will host the |content|
-  // widget.  Its arrow will be drawn at |arrow_location| if possible.  The
-  // |delegate| will be notified when the bubble is closed.  The bubble will
-  // perform an X grab of the pointer and keyboard, and will close itself if a
-  // click is received outside of the bubble.
-  static InfoBubbleGtk* Show(GtkWidget* anchor_widget,
-                             const gfx::Rect* rect,
-                             GtkWidget* content,
-                             ArrowLocationGtk arrow_location,
-                             bool match_system_theme,
-                             bool grab_input,
-                             GtkThemeProvider* provider,
-                             InfoBubbleGtkDelegate* delegate);
-
-  // Close the bubble if it's open.  This will delete the widgets and object,
-  // so you shouldn't hold a InfoBubbleGtk pointer after calling Close().
-  void Close();
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // If the content contains widgets that can steal our pointer and keyboard
-  // grabs (e.g. GtkComboBox), this method should be called after a widget
-  // releases the grabs so we can reacquire them.  Note that this causes a race
-  // condition; another client could grab them before we do (ideally, GDK would
-  // transfer the grabs back to us when the widget releases them).  The window
-  // is small, though, and the worst-case scenario for this seems to just be
-  // that the content's widgets will appear inactive even after the user clicks
-  // in them.
-  void HandlePointerAndKeyboardUngrabbedByContent();
-
- private:
-  enum FrameType {
-    FRAME_MASK,
-    FRAME_STROKE,
-  };
-
-  explicit InfoBubbleGtk(GtkThemeProvider* provider, bool match_system_theme);
-  virtual ~InfoBubbleGtk();
-
-  // Creates the InfoBubble.
-  void Init(GtkWidget* anchor_widget,
-            const gfx::Rect* rect,
-            GtkWidget* content,
-            ArrowLocationGtk arrow_location,
-            bool grab_input);
-
-  // Make the points for our polygon frame, either for fill (the mask), or for
-  // when we stroke the border.
-  static std::vector<GdkPoint> MakeFramePolygonPoints(
-      ArrowLocationGtk arrow_location,
-      int width,
-      int height,
-      FrameType type);
-
-  // Get the location where the arrow should be placed (which is a function of
-  // the preferred location and of the direction that the bubble should be
-  // facing to fit onscreen).  |arrow_x| is the X component in screen
-  // coordinates of the point at which the bubble's arrow should be aimed, and
-  // |width| is the bubble's width.
-  static ArrowLocationGtk GetArrowLocation(
-      ArrowLocationGtk preferred_location, int arrow_x, int width);
-
-  // Updates |arrow_location_| based on the toplevel window's current position
-  // and the bubble's size.  If the |force_move_and_reshape| is true or the
-  // location changes, moves and reshapes the window and returns true.
-  bool UpdateArrowLocation(bool force_move_and_reshape);
-
-  // Reshapes the window and updates |mask_region_|.
-  void UpdateWindowShape();
-
-  // Calculate the current screen position for the bubble's window (per
-  // |toplevel_window_|'s position as of its most-recent ConfigureNotify event
-  // and |rect_|) and move it there.
-  void MoveWindow();
-
-  // Restack the bubble's window directly above |toplevel_window_|.
-  void StackWindow();
-
-  // Sets the delegate.
-  void set_delegate(InfoBubbleGtkDelegate* delegate) { delegate_ = delegate; }
-
-  // Grab (in the X sense) the pointer and keyboard.  This is needed to make
-  // sure that we have the input focus.
-  void GrabPointerAndKeyboard();
-
-  CHROMEG_CALLBACK_3(InfoBubbleGtk, gboolean, OnGtkAccelerator, GtkAccelGroup*,
-                     GObject*, guint, GdkModifierType);
-
-  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnExpose, GdkEventExpose*);
-  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, void, OnSizeAllocate, GtkAllocation*);
-  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnButtonPress, GdkEventButton*);
-  CHROMEGTK_CALLBACK_0(InfoBubbleGtk, gboolean, OnDestroy);
-  CHROMEGTK_CALLBACK_0(InfoBubbleGtk, void, OnHide);
-  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnToplevelConfigure,
-                       GdkEventConfigure*);
-  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnToplevelUnmap, GdkEvent*);
-  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, void, OnAnchorAllocate, GtkAllocation*);
-
-  // The caller supplied delegate, can be NULL.
-  InfoBubbleGtkDelegate* delegate_;
-
-  // Our GtkWindow popup window, we don't technically "own" the widget, since
-  // it deletes us when it is destroyed.
-  GtkWidget* window_;
-
-  // Provides colors and stuff.
-  GtkThemeProvider* theme_provider_;
-
-  // The accel group attached to |window_|, to handle closing with escape.
-  GtkAccelGroup* accel_group_;
-
-  // The window for which we're being shown (and to which |rect_| is relative).
-  // Note that it's possible for |toplevel_window_| to be NULL if the
-  // window is destroyed before this object is destroyed, so it's important
-  // to check for that case.
-  GtkWindow* toplevel_window_;
-
-  // The widget that we use to relatively position the popup window.
-  GtkWidget* anchor_widget_;
-
-  // Provides an offset from |anchor_widget_|'s origin for MoveWindow() to
-  // use.
-  gfx::Rect rect_;
-
-  // The current shape of |window_| (used to test whether clicks fall in it or
-  // not).
-  GdkRegion* mask_region_;
-
-  // Where would we prefer for the arrow be drawn relative to the bubble, and
-  // where is it currently drawn?
-  ArrowLocationGtk preferred_arrow_location_;
-  ArrowLocationGtk current_arrow_location_;
-
-  // Whether the background should match the system theme, when the system theme
-  // is being used. For example, the bookmark bubble does, but extension popups
-  // do not.
-  bool match_system_theme_;
-
-  // If true, the popup owns all X input for the duration of its existence.
-  // This will usually be true, the exception being when inspecting extension
-  // popups with dev tools.
-  bool grab_input_;
-
-  bool closed_by_escape_;
-
-  NotificationRegistrar registrar_;
-
-  GtkSignalRegistrar signals_;
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBubbleGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_INFO_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/infobar_arrow_model.cc b/chrome/browser/gtk/infobar_arrow_model.cc
deleted file mode 100644
index fc2f889..0000000
--- a/chrome/browser/gtk/infobar_arrow_model.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/infobar_arrow_model.h"
-
-#include "chrome/browser/gtk/infobar_gtk.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/color_utils.h"
-#include "gfx/point.h"
-#include "gfx/skia_utils_gtk.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
-
-InfoBarArrowModel::InfoBarArrowModel(Observer* observer)
-    : observer_(observer),
-      animation_(this) {
-  animation_.SetTweenType(ui::Tween::LINEAR);
-  animation_.Reset(1.0);
-  target_colors_.top = target_colors_.bottom = SkColorSetARGB(0, 0, 0, 0);
-  previous_colors_ = target_colors_;
-}
-
-InfoBarArrowModel::~InfoBarArrowModel() {
-}
-
-InfoBarArrowModel::InfoBarColors InfoBarArrowModel::CurrentInfoBarColors() {
-  double alpha = animation_.GetCurrentValue();
-  InfoBarColors colors = {
-      color_utils::AlphaBlend(target_colors_.top,
-                              previous_colors_.top,
-                              alpha * 0xff),
-      color_utils::AlphaBlend(target_colors_.bottom,
-                              previous_colors_.bottom,
-                              alpha * 0xff)};
-  return colors;
-}
-
-bool InfoBarArrowModel::NeedToDrawInfoBarArrow() {
-  return SkColorGetA(CurrentInfoBarColors().top) != 0;
-}
-
-void InfoBarArrowModel::ShowArrowFor(InfoBar* bar, bool animate) {
-  scoped_ptr<std::pair<SkColor, SkColor> > colors;
-
-  previous_colors_ = CurrentInfoBarColors();
-
-  if (bar) {
-    double r, g, b;
-    bar->GetTopColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
-    target_colors_.top = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
-    bar->GetBottomColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
-    target_colors_.bottom = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
-  } else {
-    target_colors_.bottom = target_colors_.top = SkColorSetARGB(0, 0, 0, 0);
-  }
-
-  if (animate) {
-    // Fade from the current color to the target color.
-    animation_.Reset();
-    animation_.Show();
-  } else {
-    // Skip straight to showing the target color.
-    animation_.Reset(1.0);
-  }
-
-  observer_->PaintStateChanged();
-}
-
-void InfoBarArrowModel::Paint(GtkWidget* widget,
-                              GdkEventExpose* expose,
-                              const gfx::Point& origin,
-                              const GdkColor& border_color) {
-  if (!NeedToDrawInfoBarArrow())
-    return;
-
-  // The size of the arrow (its height; also half its width).
-  const int kArrowSize = 10;
-
-  SkPath path;
-  path.moveTo(SkPoint::Make(origin.x() - kArrowSize, origin.y()));
-  path.rLineTo(kArrowSize, -kArrowSize);
-  path.rLineTo(kArrowSize, kArrowSize);
-  path.close();
-
-  SkPaint paint;
-  paint.setStrokeWidth(1);
-  paint.setStyle(SkPaint::kFill_Style);
-
-  SkPoint grad_points[2];
-  grad_points[0].set(SkIntToScalar(0), SkIntToScalar(origin.y()));
-  grad_points[1].set(SkIntToScalar(0),
-                     SkIntToScalar(origin.y() + InfoBar::kInfoBarHeight));
-
-  InfoBarColors colors = CurrentInfoBarColors();
-  SkColor grad_colors[2];
-  grad_colors[0] = colors.top;
-  grad_colors[1] = colors.bottom;
-
-  SkShader* gradient_shader = SkGradientShader::CreateLinear(
-      grad_points, grad_colors, NULL, 2, SkShader::kMirror_TileMode);
-  paint.setShader(gradient_shader);
-  gradient_shader->unref();
-
-  gfx::CanvasSkiaPaint canvas(expose, false);
-  canvas.drawPath(path, paint);
-
-  paint.setShader(NULL);
-  paint.setColor(SkColorSetA(gfx::GdkColorToSkColor(border_color),
-                             SkColorGetA(colors.top)));
-  paint.setStyle(SkPaint::kStroke_Style);
-  canvas.drawPath(path, paint);
-}
-
-void InfoBarArrowModel::AnimationEnded(const ui::Animation* animation) {
-  observer_->PaintStateChanged();
-}
-
-void InfoBarArrowModel::AnimationProgressed(const ui::Animation* animation) {
-  observer_->PaintStateChanged();
-}
-
-void InfoBarArrowModel::AnimationCanceled(const ui::Animation* animation) {
-  observer_->PaintStateChanged();
-}
diff --git a/chrome/browser/gtk/infobar_arrow_model.h b/chrome/browser/gtk/infobar_arrow_model.h
deleted file mode 100644
index 331089b..0000000
--- a/chrome/browser/gtk/infobar_arrow_model.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_INFOBAR_ARROW_MODEL_H_
-#define CHROME_BROWSER_GTK_INFOBAR_ARROW_MODEL_H_
-
-#include <gtk/gtk.h>
-
-#include "third_party/skia/include/core/SkPaint.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace gfx {
-class Point;
-}
-
-class InfoBar;
-
-// A helper class that tracks the state of an infobar arrow and provides a
-// utility to draw it.
-class InfoBarArrowModel : public ui::AnimationDelegate {
- public:
-  class Observer {
-   public:
-    // The arrow has changed states; relevant widgets need to be repainted.
-    virtual void PaintStateChanged() = 0;
-  };
-
-  explicit InfoBarArrowModel(Observer* observer);
-  virtual ~InfoBarArrowModel();
-
-  // An infobar has been added or removed that will affect the state of this
-  // arrow.
-  void ShowArrowFor(InfoBar* bar, bool animate);
-
-  // Returns true if the arrow is showing at all.
-  bool NeedToDrawInfoBarArrow();
-
-  // Paints the arrow on |widget|, in response to |expose|, with the bottom
-  // center of the arrow at |origin|, drawing a border with |border_color|.
-  void Paint(GtkWidget* widget,
-             GdkEventExpose* expose,
-             const gfx::Point& origin,
-             const GdkColor& border_color);
-
-  // Overridden from ui::AnimationDelegate.
-  virtual void AnimationEnded(const ui::Animation* animation);
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationCanceled(const ui::Animation* animation);
-
- private:
-  // A pair of colors used to draw a gradient for an arrow.
-  struct InfoBarColors {
-    SkColor top;
-    SkColor bottom;
-  };
-
-  // Calculates the currently showing arrow color, which is a blend of the new
-  // arrow color and the old arrow color.
-  InfoBarColors CurrentInfoBarColors();
-
-  // The view that owns us.
-  Observer* observer_;
-
-  // An animation that tracks the progress of the transition from the last color
-  // to the new color.
-  ui::SlideAnimation animation_;
-
-  // The color we are animating towards.
-  InfoBarColors target_colors_;
-  // The last color we showed (the one we are animating away from).
-  InfoBarColors previous_colors_;
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBarArrowModel);
-};
-
-#endif  // CHROME_BROWSER_GTK_INFOBAR_ARROW_MODEL_H_
diff --git a/chrome/browser/gtk/infobar_container_gtk.cc b/chrome/browser/gtk/infobar_container_gtk.cc
deleted file mode 100644
index 76ba36a..0000000
--- a/chrome/browser/gtk/infobar_container_gtk.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/infobar_container_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/infobar_gtk.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "third_party/skia/include/core/SkPaint.h"
-
-namespace {
-
-static const char* kInfoBar = "info-bar";
-
-// If |infobar_widget| matches |info_bar_delegate|, then close the infobar.
-void AnimateClosingForDelegate(GtkWidget* infobar_widget,
-                               gpointer info_bar_delegate) {
-  InfoBarDelegate* delegate =
-      static_cast<InfoBarDelegate*>(info_bar_delegate);
-  InfoBar* infobar = reinterpret_cast<InfoBar*>(
-      g_object_get_data(G_OBJECT(infobar_widget), kInfoBar));
-
-  if (!infobar) {
-    NOTREACHED();
-    return;
-  }
-
-  if (delegate == infobar->delegate())
-    infobar->AnimateClose();
-}
-
-// If |infobar_widget| matches |info_bar_delegate|, then close the infobar w/o
-// an animation.
-void ClosingForDelegate(GtkWidget* infobar_widget, gpointer info_bar_delegate) {
-  InfoBarDelegate* delegate =
-      static_cast<InfoBarDelegate*>(info_bar_delegate);
-  InfoBar* infobar = reinterpret_cast<InfoBar*>(
-      g_object_get_data(G_OBJECT(infobar_widget), kInfoBar));
-
-  if (!infobar) {
-    NOTREACHED();
-    return;
-  }
-
-  if (delegate == infobar->delegate())
-    infobar->Close();
-}
-
-// Get the height of the widget and add it to |userdata|, but only if it is in
-// the process of animating.
-void SumAnimatingBarHeight(GtkWidget* widget, gpointer userdata) {
-  int* height_sum = static_cast<int*>(userdata);
-  InfoBar* infobar = reinterpret_cast<InfoBar*>(
-      g_object_get_data(G_OBJECT(widget), kInfoBar));
-  if (infobar->IsAnimating())
-    *height_sum += widget->allocation.height;
-}
-
-}  // namespace
-
-// InfoBarContainerGtk, public: ------------------------------------------------
-
-InfoBarContainerGtk::InfoBarContainerGtk(Profile* profile)
-    : profile_(profile),
-      tab_contents_(NULL),
-      container_(gtk_vbox_new(FALSE, 0)) {
-  gtk_widget_show(widget());
-}
-
-InfoBarContainerGtk::~InfoBarContainerGtk() {
-  ChangeTabContents(NULL);
-
-  container_.Destroy();
-}
-
-void InfoBarContainerGtk::ChangeTabContents(TabContents* contents) {
-  if (tab_contents_)
-    registrar_.RemoveAll();
-
-  gtk_util::RemoveAllChildren(widget());
-  UpdateToolbarInfoBarState(NULL, false);
-
-  tab_contents_ = contents;
-  if (tab_contents_) {
-    UpdateInfoBars();
-    Source<TabContents> source(tab_contents_);
-    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source);
-    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
-                   source);
-    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED,
-                   source);
-  }
-}
-
-void InfoBarContainerGtk::RemoveDelegate(InfoBarDelegate* delegate) {
-  tab_contents_->RemoveInfoBar(delegate);
-}
-
-int InfoBarContainerGtk::TotalHeightOfAnimatingBars() const {
-  int sum = 0;
-  gtk_container_foreach(GTK_CONTAINER(widget()), SumAnimatingBarHeight, &sum);
-  return sum;
-}
-
-// InfoBarContainerGtk, NotificationObserver implementation: -------------------
-
-void InfoBarContainerGtk::Observe(NotificationType type,
-                                  const NotificationSource& source,
-                                  const NotificationDetails& details) {
-  if (type == NotificationType::TAB_CONTENTS_INFOBAR_ADDED) {
-    AddInfoBar(Details<InfoBarDelegate>(details).ptr(), true);
-  } else if (type == NotificationType::TAB_CONTENTS_INFOBAR_REMOVED) {
-    RemoveInfoBar(Details<InfoBarDelegate>(details).ptr(), true);
-  } else if (type == NotificationType::TAB_CONTENTS_INFOBAR_REPLACED) {
-    std::pair<InfoBarDelegate*, InfoBarDelegate*>* delegates =
-        Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details).ptr();
-
-    // By not animating the removal/addition, this appears to be a replace.
-    RemoveInfoBar(delegates->first, false);
-    AddInfoBar(delegates->second, false);
-  } else {
-    NOTREACHED();
-  }
-}
-
-// InfoBarContainerGtk, private: -----------------------------------------------
-
-void InfoBarContainerGtk::UpdateInfoBars() {
-  for (int i = 0; i < tab_contents_->infobar_delegate_count(); ++i) {
-    InfoBarDelegate* delegate = tab_contents_->GetInfoBarDelegateAt(i);
-    AddInfoBar(delegate, false);
-  }
-}
-
-void InfoBarContainerGtk::ShowArrowForDelegate(InfoBarDelegate* delegate,
-                                               bool animate) {
-  GList* children = gtk_container_get_children(GTK_CONTAINER(widget()));
-  if (!children)
-    return;
-
-  // Iterate through the infobars and find the last one that isn't closing.
-  InfoBar* last_bar = NULL;
-  InfoBar* this_bar = NULL;
-  for (GList* iter = children; iter != NULL; iter = iter->next) {
-    this_bar = reinterpret_cast<InfoBar*>(
-        g_object_get_data(G_OBJECT(iter->data), kInfoBar));
-
-    if (this_bar->delegate() == delegate)
-      break;
-
-    if (!this_bar->IsClosing())
-      last_bar = this_bar;
-
-    this_bar = NULL;
-  }
-
-  if (last_bar)
-    last_bar->ShowArrowFor(this_bar, animate);
-  else
-    UpdateToolbarInfoBarState(this_bar, animate);
-
-  g_list_free(children);
-}
-
-void InfoBarContainerGtk::AddInfoBar(InfoBarDelegate* delegate, bool animate) {
-  InfoBar* infobar = delegate->CreateInfoBar();
-  infobar->set_container(this);
-  infobar->SetThemeProvider(GtkThemeProvider::GetFrom(profile_));
-  gtk_box_pack_start(GTK_BOX(widget()), infobar->widget(),
-                     FALSE, FALSE, 0);
-
-  if (animate)
-    infobar->AnimateOpen();
-  else
-    infobar->Open();
-
-  ShowArrowForDelegate(delegate, animate);
-}
-
-void InfoBarContainerGtk::RemoveInfoBar(InfoBarDelegate* delegate,
-                                        bool animate) {
-  if (animate) {
-    gtk_container_foreach(GTK_CONTAINER(widget()),
-                          AnimateClosingForDelegate, delegate);
-  } else {
-    gtk_container_foreach(GTK_CONTAINER(widget()), ClosingForDelegate,
-                          delegate);
-  }
-
-  InfoBarDelegate* next_delegate = NULL;
-  for (int i = 1; i < tab_contents_->infobar_delegate_count(); ++i) {
-    if (tab_contents_->GetInfoBarDelegateAt(i - 1) == delegate) {
-      next_delegate = tab_contents_->GetInfoBarDelegateAt(i);
-      break;
-    }
-  }
-
-  ShowArrowForDelegate(next_delegate, animate);
-}
-
-void InfoBarContainerGtk::UpdateToolbarInfoBarState(
-    InfoBar* infobar, bool animate) {
-  GtkWindow* parent = platform_util::GetTopLevel(widget());
-  BrowserWindowGtk* browser_window =
-      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
-  if (browser_window)
-    browser_window->SetInfoBarShowing(infobar, animate);
-}
diff --git a/chrome/browser/gtk/infobar_container_gtk.h b/chrome/browser/gtk/infobar_container_gtk.h
deleted file mode 100644
index ba676a9..0000000
--- a/chrome/browser/gtk/infobar_container_gtk.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_INFOBAR_CONTAINER_GTK_H_
-#define CHROME_BROWSER_GTK_INFOBAR_CONTAINER_GTK_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class InfoBar;
-class InfoBarDelegate;
-class Profile;
-class TabContents;
-
-typedef struct _GtkWidget GtkWidget;
-
-class InfoBarContainerGtk : public NotificationObserver {
- public:
-  explicit InfoBarContainerGtk(Profile* profile);
-  virtual ~InfoBarContainerGtk();
-
-  // Get the native widget.
-  GtkWidget* widget() const { return container_.get(); }
-
-  // Changes the TabContents for which this container is showing InfoBars. Can
-  // be NULL, in which case we will simply detach ourselves from the old tab
-  // contents.
-  void ChangeTabContents(TabContents* contents);
-
-  // Remove the specified InfoBarDelegate from the selected TabContents. This
-  // will notify us back and cause us to close the View. This is called from
-  // the InfoBar's close button handler.
-  void RemoveDelegate(InfoBarDelegate* delegate);
-
-  // Returns the total pixel height of all infobars in this container that
-  // are currently animating.
-  int TotalHeightOfAnimatingBars() const;
-
- private:
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Constructs the InfoBars needed to reflect the state of the current
-  // TabContents associated with this container. No animations are run during
-  // this process.
-  void UpdateInfoBars();
-
-  // Makes the calls to show an arrow for |delegate| (either on the browser
-  // toolbar or on the next infobar up).
-  void ShowArrowForDelegate(InfoBarDelegate* delegate, bool animate);
-
-  // Adds an InfoBar for the specified delegate, in response to a notification
-  // from the selected TabContents.
-  void AddInfoBar(InfoBarDelegate* delegate, bool animate);
-
-  // Removes an InfoBar for the specified delegate, in response to a
-  // notification from the selected TabContents. The InfoBar's disappearance
-  // will be animated.
-  void RemoveInfoBar(InfoBarDelegate* delegate, bool animate);
-
-  // Tells the browser window about our state so it can draw the arrow
-  // appropriately.
-  void UpdateToolbarInfoBarState(InfoBar* infobar, bool animate);
-
-  NotificationRegistrar registrar_;
-
-  // The profile for the browser that hosts this InfoBarContainer.
-  Profile* profile_;
-
-  // The TabContents for which we are currently showing InfoBars.
-  TabContents* tab_contents_;
-
-  // VBox that holds the info bars.
-  OwnedWidgetGtk container_;
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBarContainerGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_INFOBAR_CONTAINER_GTK_H_
diff --git a/chrome/browser/gtk/infobar_gtk.cc b/chrome/browser/gtk/infobar_gtk.cc
deleted file mode 100644
index 5a061d0..0000000
--- a/chrome/browser/gtk/infobar_gtk.cc
+++ /dev/null
@@ -1,453 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/infobar_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/infobar_container_gtk.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/gtk_util.h"
-
-extern const int InfoBar::kInfoBarHeight = 37;
-
-namespace {
-
-// Spacing after message (and before buttons).
-const int kEndOfLabelSpacing = 6;
-// Spacing between buttons.
-const int kButtonButtonSpacing = 3;
-
-// Pixels between infobar elements.
-const int kElementPadding = 5;
-
-// Extra padding on either end of info bar.
-const int kLeftPadding = 5;
-const int kRightPadding = 5;
-
-}  // namespace
-
-InfoBar::InfoBar(InfoBarDelegate* delegate)
-    : container_(NULL),
-      delegate_(delegate),
-      theme_provider_(NULL),
-      arrow_model_(this) {
-  // Create |hbox_| and pad the sides.
-  hbox_ = gtk_hbox_new(FALSE, kElementPadding);
-
-  // Make the whole infor bar horizontally shrinkable.
-  gtk_widget_set_size_request(hbox_, 0, -1);
-
-  GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(padding),
-      0, 0, kLeftPadding, kRightPadding);
-
-  bg_box_ = gtk_event_box_new();
-  gtk_widget_set_app_paintable(bg_box_, TRUE);
-  g_signal_connect(bg_box_, "expose-event",
-                   G_CALLBACK(OnBackgroundExposeThunk), this);
-  gtk_container_add(GTK_CONTAINER(padding), hbox_);
-  gtk_container_add(GTK_CONTAINER(bg_box_), padding);
-  gtk_widget_set_size_request(bg_box_, -1, kInfoBarHeight);
-
-  // Add the icon on the left, if any.
-  SkBitmap* icon = delegate->GetIcon();
-  if (icon) {
-    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(icon);
-    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
-    g_object_unref(pixbuf);
-    gtk_box_pack_start(GTK_BOX(hbox_), image, FALSE, FALSE, 0);
-  }
-
-  close_button_.reset(CustomDrawButton::CloseButton(NULL));
-  gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0);
-  g_signal_connect(close_button_->widget(), "clicked",
-                   G_CALLBACK(OnCloseButtonThunk), this);
-
-  slide_widget_.reset(new SlideAnimatorGtk(bg_box_,
-                                           SlideAnimatorGtk::DOWN,
-                                           0, true, true, this));
-  // We store a pointer back to |this| so we can refer to it from the infobar
-  // container.
-  g_object_set_data(G_OBJECT(slide_widget_->widget()), "info-bar", this);
-}
-
-InfoBar::~InfoBar() {
-}
-
-GtkWidget* InfoBar::widget() {
-  return slide_widget_->widget();
-}
-
-void InfoBar::AnimateOpen() {
-  slide_widget_->Open();
-
-  gtk_widget_show_all(bg_box_);
-  if (bg_box_->window)
-    gdk_window_lower(bg_box_->window);
-}
-
-void InfoBar::Open() {
-  slide_widget_->OpenWithoutAnimation();
-
-  gtk_widget_show_all(bg_box_);
-  if (bg_box_->window)
-    gdk_window_lower(bg_box_->window);
-}
-
-void InfoBar::AnimateClose() {
-  slide_widget_->Close();
-}
-
-void InfoBar::Close() {
-  if (delegate_) {
-    delegate_->InfoBarClosed();
-    delegate_ = NULL;
-  }
-  delete this;
-}
-
-bool InfoBar::IsAnimating() {
-  return slide_widget_->IsAnimating();
-}
-
-bool InfoBar::IsClosing() {
-  return slide_widget_->IsClosing();
-}
-
-void InfoBar::ShowArrowFor(InfoBar* other, bool animate) {
-  arrow_model_.ShowArrowFor(other, animate);
-}
-
-void InfoBar::PaintStateChanged() {
-  gtk_widget_queue_draw(widget());
-}
-
-void InfoBar::RemoveInfoBar() const {
-  container_->RemoveDelegate(delegate_);
-}
-
-void InfoBar::Closed() {
-  Close();
-}
-
-void InfoBar::SetThemeProvider(GtkThemeProvider* theme_provider) {
-  if (theme_provider_) {
-    NOTREACHED();
-    return;
-  }
-
-  theme_provider_ = theme_provider;
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  UpdateBorderColor();
-}
-
-void InfoBar::Observe(NotificationType type,
-                      const NotificationSource& source,
-                      const NotificationDetails& details) {
-  UpdateBorderColor();
-}
-
-void InfoBar::AddLabelWithInlineLink(const string16& display_text,
-                                     const string16& link_text,
-                                     size_t link_offset,
-                                     GCallback callback) {
-  GtkWidget* link_button = gtk_chrome_link_button_new(
-      UTF16ToUTF8(link_text).c_str());
-  gtk_chrome_link_button_set_use_gtk_theme(
-      GTK_CHROME_LINK_BUTTON(link_button), FALSE);
-  gtk_util::ForceFontSizePixels(
-      GTK_CHROME_LINK_BUTTON(link_button)->label, 13.4);
-  DCHECK(callback);
-  g_signal_connect(link_button, "clicked", callback, this);
-  gtk_util::SetButtonTriggersNavigation(link_button);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-  // We want the link to be horizontally shrinkable, so that the Chrome
-  // window can be resized freely even with a very long link.
-  gtk_widget_set_size_request(hbox, 0, -1);
-  gtk_box_pack_start(GTK_BOX(hbox_), hbox, TRUE, TRUE, 0);
-
-  // Need to insert the link inside the display text.
-  GtkWidget* initial_label = gtk_label_new(
-      UTF16ToUTF8(display_text.substr(0, link_offset)).c_str());
-  GtkWidget* trailing_label = gtk_label_new(
-      UTF16ToUTF8(display_text.substr(link_offset)).c_str());
-
-  gtk_util::ForceFontSizePixels(initial_label, 13.4);
-  gtk_util::ForceFontSizePixels(trailing_label, 13.4);
-
-  // TODO(joth): Unlike the AddLabelAndLink below, none of the label widgets
-  // are set as shrinkable here, meaning the text will run under the close
-  // button etc. when the width is restricted, rather than eliding.
-  gtk_widget_modify_fg(initial_label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-  gtk_widget_modify_fg(trailing_label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-
-  // We don't want any spacing between the elements, so we pack them into
-  // this hbox that doesn't use kElementPadding.
-  gtk_box_pack_start(GTK_BOX(hbox), initial_label, FALSE, FALSE, 0);
-  gtk_util::CenterWidgetInHBox(hbox, link_button, false, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), trailing_label, FALSE, FALSE, 0);
-}
-
-// TODO(joth): This method factors out some common functionality between the
-// various derived infobar classes, however the class hierarchy itself could
-// use refactoring to reduce this duplication. http://crbug.com/38924
-void InfoBar::AddLabelAndLink(const string16& display_text,
-                              const string16& link_text,
-                              GCallback callback) {
-  GtkWidget* link_button = NULL;
-  if (!link_text.empty()) {
-    // If we have some link text, create the link button.
-    link_button = gtk_chrome_link_button_new(UTF16ToUTF8(link_text).c_str());
-    gtk_chrome_link_button_set_use_gtk_theme(
-        GTK_CHROME_LINK_BUTTON(link_button), FALSE);
-    DCHECK(callback);
-    g_signal_connect(link_button, "clicked", callback, this);
-    gtk_util::SetButtonTriggersNavigation(link_button);
-  }
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-  // We want the link to be horizontally shrinkable, so that the Chrome
-  // window can be resized freely even with a very long link.
-  gtk_widget_set_size_request(hbox, 0, -1);
-  gtk_box_pack_start(GTK_BOX(hbox_), hbox, TRUE, TRUE, 0);
-
-  if (link_button)
-    gtk_box_pack_end(GTK_BOX(hbox), link_button, FALSE, FALSE, 0);
-  GtkWidget* label = gtk_label_new(UTF16ToUTF8(display_text).c_str());
-  gtk_util::ForceFontSizePixels(label, 13.4);
-  // In order to avoid the link_button and the label overlapping with each
-  // other, we make the label shrinkable.
-  gtk_widget_set_size_request(label, 0, -1);
-  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
-  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-}
-
-void InfoBar::GetTopColor(InfoBarDelegate::Type type,
-                          double* r, double* g, double *b) {
-  // These constants are copied from corresponding skia constants from
-  // browser/views/infobars/infobars.cc, and then changed into 0-1 ranged
-  // values for cairo.
-  switch (type) {
-    case InfoBarDelegate::WARNING_TYPE:
-      *r = 255.0 / 255.0;
-      *g = 242.0 / 255.0;
-      *b = 183.0 / 255.0;
-      break;
-    case InfoBarDelegate::PAGE_ACTION_TYPE:
-      *r = 218.0 / 255.0;
-      *g = 231.0 / 255.0;
-      *b = 249.0 / 255.0;
-      break;
-  }
-}
-
-void InfoBar::GetBottomColor(InfoBarDelegate::Type type,
-                             double* r, double* g, double *b) {
-  switch (type) {
-    case InfoBarDelegate::WARNING_TYPE:
-      *r = 250.0 / 255.0;
-      *g = 230.0 / 255.0;
-      *b = 145.0 / 255.0;
-      break;
-    case InfoBarDelegate::PAGE_ACTION_TYPE:
-      *r = 179.0 / 255.0;
-      *g = 202.0 / 255.0;
-      *b = 231.0 / 255.0;
-      break;
-  }
-}
-
-void InfoBar::UpdateBorderColor() {
-  gtk_widget_queue_draw(widget());
-}
-
-void InfoBar::OnCloseButton(GtkWidget* button) {
-  if (delegate_)
-    delegate_->InfoBarDismissed();
-  RemoveInfoBar();
-}
-
-gboolean InfoBar::OnBackgroundExpose(GtkWidget* sender,
-                                     GdkEventExpose* event) {
-  const int height = sender->allocation.height;
-
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-
-  cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height);
-
-  double top_r, top_g, top_b;
-  GetTopColor(delegate_->GetInfoBarType(), &top_r, &top_g, &top_b);
-  cairo_pattern_add_color_stop_rgb(pattern, 0.0, top_r, top_g, top_b);
-
-  double bottom_r, bottom_g, bottom_b;
-  GetBottomColor(delegate_->GetInfoBarType(), &bottom_r, &bottom_g, &bottom_b);
-  cairo_pattern_add_color_stop_rgb(
-      pattern, 1.0, bottom_r, bottom_g, bottom_b);
-  cairo_set_source(cr, pattern);
-  cairo_paint(cr);
-  cairo_pattern_destroy(pattern);
-
-  // Draw the bottom border.
-  GdkColor border_color = theme_provider_->GetBorderColor();
-  cairo_set_source_rgb(cr, border_color.red / 65535.0,
-                           border_color.green / 65535.0,
-                           border_color.blue / 65535.0);
-  cairo_set_line_width(cr, 1.0);
-  int y = sender->allocation.height;
-  cairo_move_to(cr, 0, y - 0.5);
-  cairo_rel_line_to(cr, sender->allocation.width, 0);
-  cairo_stroke(cr);
-
-  cairo_destroy(cr);
-
-  if (!arrow_model_.NeedToDrawInfoBarArrow())
-    return FALSE;
-
-  GtkWindow* parent = platform_util::GetTopLevel(widget());
-  BrowserWindowGtk* browser_window =
-      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
-  int x = browser_window ?
-      browser_window->GetXPositionOfLocationIcon(sender) : 0;
-
-  arrow_model_.Paint(sender, event, gfx::Point(x, y), border_color);
-
-  return FALSE;
-}
-
-// AlertInfoBar ----------------------------------------------------------------
-
-class AlertInfoBar : public InfoBar {
- public:
-  explicit AlertInfoBar(AlertInfoBarDelegate* delegate)
-      : InfoBar(delegate) {
-    AddLabelAndLink(delegate->GetMessageText(), string16(), NULL);
-  }
-};
-
-// LinkInfoBar -----------------------------------------------------------------
-
-class LinkInfoBar : public InfoBar {
- public:
-  explicit LinkInfoBar(LinkInfoBarDelegate* delegate)
-      : InfoBar(delegate) {
-    size_t link_offset;
-    string16 display_text = delegate->GetMessageTextWithOffset(&link_offset);
-    string16 link_text = delegate->GetLinkText();
-    AddLabelWithInlineLink(display_text, link_text, link_offset,
-                           G_CALLBACK(OnLinkClick));
-  }
-
- private:
-  static void OnLinkClick(GtkWidget* button, LinkInfoBar* link_info_bar) {
-    if (link_info_bar->delegate_->AsLinkInfoBarDelegate()->
-        LinkClicked(gtk_util::DispositionForCurrentButtonPressEvent())) {
-      link_info_bar->RemoveInfoBar();
-    }
-  }
-};
-
-// ConfirmInfoBar --------------------------------------------------------------
-
-class ConfirmInfoBar : public InfoBar {
- public:
-  explicit ConfirmInfoBar(ConfirmInfoBarDelegate* delegate);
-
- private:
-  // Adds a button to the info bar by type. It will do nothing if the delegate
-  // doesn't specify a button of the given type.
-  void AddButton(ConfirmInfoBarDelegate::InfoBarButton type);
-
-  CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnOkButton);
-  CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnCancelButton);
-  CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnLinkClicked);
-
-  GtkWidget* confirm_hbox_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
-};
-
-ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
-    : InfoBar(delegate) {
-  confirm_hbox_ = gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox_), confirm_hbox_, TRUE, TRUE, 0);
-  gtk_widget_set_size_request(confirm_hbox_, 0, -1);
-
-  std::string label_text = UTF16ToUTF8(delegate->GetMessageText());
-  GtkWidget* label = gtk_label_new(label_text.c_str());
-  gtk_util::ForceFontSizePixels(label, 13.4);
-  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-  gtk_util::CenterWidgetInHBox(confirm_hbox_, label, false, kEndOfLabelSpacing);
-  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-  g_signal_connect(label, "map",
-                   G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
-                   NULL);
-
-  AddButton(ConfirmInfoBarDelegate::BUTTON_CANCEL);
-  AddButton(ConfirmInfoBarDelegate::BUTTON_OK);
-
-  std::string link_text = UTF16ToUTF8(delegate->GetLinkText());
-  GtkWidget* link = gtk_chrome_link_button_new(link_text.c_str());
-  gtk_misc_set_alignment(GTK_MISC(GTK_CHROME_LINK_BUTTON(link)->label), 0, 0.5);
-  g_signal_connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
-  gtk_util::SetButtonTriggersNavigation(link);
-  // Until we switch to vector graphics, force the font size.
-  // 13.4px == 10pt @ 96dpi
-  gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link)->label, 13.4);
-  gtk_util::CenterWidgetInHBox(hbox_, link, true, kEndOfLabelSpacing);
-}
-
-void ConfirmInfoBar::AddButton(ConfirmInfoBarDelegate::InfoBarButton type) {
-  if (delegate_->AsConfirmInfoBarDelegate()->GetButtons() & type) {
-    GtkWidget* button = gtk_button_new_with_label(UTF16ToUTF8(
-        delegate_->AsConfirmInfoBarDelegate()->GetButtonLabel(type)).c_str());
-    gtk_util::CenterWidgetInHBox(confirm_hbox_, button, false,
-                                 kButtonButtonSpacing);
-    g_signal_connect(button, "clicked",
-                     G_CALLBACK(type == ConfirmInfoBarDelegate::BUTTON_OK ?
-                                OnOkButtonThunk : OnCancelButtonThunk),
-                     this);
-  }
-}
-
-void ConfirmInfoBar::OnCancelButton(GtkWidget* widget) {
-  if (delegate_->AsConfirmInfoBarDelegate()->Cancel())
-    RemoveInfoBar();
-}
-
-void ConfirmInfoBar::OnOkButton(GtkWidget* widget) {
-  if (delegate_->AsConfirmInfoBarDelegate()->Accept())
-    RemoveInfoBar();
-}
-
-void ConfirmInfoBar::OnLinkClicked(GtkWidget* widget) {
-  if (delegate_->AsConfirmInfoBarDelegate()->LinkClicked(
-          gtk_util::DispositionForCurrentButtonPressEvent())) {
-    RemoveInfoBar();
-  }
-}
-
-InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
-  return new AlertInfoBar(this);
-}
-InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
-  return new LinkInfoBar(this);
-}
-InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
-  return new ConfirmInfoBar(this);
-}
diff --git a/chrome/browser/gtk/infobar_gtk.h b/chrome/browser/gtk/infobar_gtk.h
deleted file mode 100644
index d0dd542..0000000
--- a/chrome/browser/gtk/infobar_gtk.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_INFOBAR_GTK_H_
-#define CHROME_BROWSER_GTK_INFOBAR_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/infobar_arrow_model.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "third_party/skia/include/core/SkPaint.h"
-
-class CustomDrawButton;
-class GtkThemeProvider;
-class InfoBarContainerGtk;
-class InfoBarDelegate;
-
-class InfoBar : public SlideAnimatorGtk::Delegate,
-                public NotificationObserver,
-                public InfoBarArrowModel::Observer {
- public:
-  explicit InfoBar(InfoBarDelegate* delegate);
-  virtual ~InfoBar();
-
-  InfoBarDelegate* delegate() const { return delegate_; }
-
-  // Get the top level native GTK widget for this infobar.
-  GtkWidget* widget();
-
-  // Set a link to the parent InfoBarContainer. This must be set before the
-  // InfoBar is added to the view hierarchy.
-  void set_container(InfoBarContainerGtk* container) { container_ = container; }
-
-  // Starts animating the InfoBar open.
-  void AnimateOpen();
-
-  // Opens the InfoBar immediately.
-  void Open();
-
-  // Starts animating the InfoBar closed. It will not be closed until the
-  // animation has completed, when |Close| will be called.
-  void AnimateClose();
-
-  // Closes the InfoBar immediately and removes it from its container. Notifies
-  // the delegate that it has closed. The InfoBar is deleted after this function
-  // is called.
-  void Close();
-
-  // Returns true if the infobar is showing the its open or close animation.
-  bool IsAnimating();
-
-  // Returns true if the infobar is showing the close animation.
-  bool IsClosing();
-
-  void SetThemeProvider(GtkThemeProvider* theme_provider);
-
-  // Show an arrow that originates from another infobar (i.e. a bar was added
-  // below this one). If |other| is NULL, stop showing the arrow.
-  void ShowArrowFor(InfoBar* other, bool animate);
-
-  // InfoBarArrowModel::Observer implementation.
-  virtual void PaintStateChanged();
-
-  // SlideAnimatorGtk::Delegate implementation.
-  virtual void Closed();
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Retrieves the component colors for the infobar's background
-  // gradient. (This varies by infobars and can be animated to change).
-  virtual void GetTopColor(InfoBarDelegate::Type type,
-                           double* r, double* g, double *b);
-  virtual void GetBottomColor(InfoBarDelegate::Type type,
-                              double* r, double* g, double *b);
-
-  // The total height of the info bar.
-  static const int kInfoBarHeight;
-
- protected:
-  // Removes our associated InfoBarDelegate from the associated TabContents.
-  // (Will lead to this InfoBar being closed).
-  void RemoveInfoBar() const;
-
-  // Adds |display_text| to the infobar. If |link_text| is not empty, it is
-  // rendered as a hyperlink and inserted into |display_text| at |link_offset|,
-  // or right aligned in the infobar if |link_offset| is |npos|. If a link is
-  // supplied, |link_callback| must not be null. It will be invoked on click.
-  void AddLabelWithInlineLink(const string16& display_text,
-                              const string16& link_text,
-                              size_t link_offset,
-                              GCallback callback);
-
-  // Adds |display_text| to the infobar. If |link_text| is not empty, it is
-  // right aligned in the infobar.
-  void AddLabelAndLink(const string16& display_text,
-                       const string16& link_text,
-                       GCallback callback);
-  // The top level widget of the infobar.
-  scoped_ptr<SlideAnimatorGtk> slide_widget_;
-
-  // The second highest widget in the hierarchy (after the slide widget).
-  GtkWidget* bg_box_;
-
-  // The hbox that holds infobar elements (button, text, icon, etc.).
-  GtkWidget* hbox_;
-
-  // The x that closes the bar.
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  // The InfoBar's container
-  InfoBarContainerGtk* container_;
-
-  // The InfoBar's delegate.
-  InfoBarDelegate* delegate_;
-
-  // The theme provider, used for getting border colors.
-  GtkThemeProvider* theme_provider_;
-
-  // The model that tracks the paint state of the arrow for the infobar
-  // below this one (if it exists).
-  InfoBarArrowModel arrow_model_;
-
-  NotificationRegistrar registrar_;
-
- private:
-  CHROMEGTK_CALLBACK_0(InfoBar, void, OnCloseButton);
-  CHROMEGTK_CALLBACK_1(InfoBar, gboolean, OnBackgroundExpose, GdkEventExpose*);
-
-  void UpdateBorderColor();
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBar);
-};
-
-#endif  // CHROME_BROWSER_GTK_INFOBAR_GTK_H_
diff --git a/chrome/browser/gtk/instant_confirm_dialog_gtk.cc b/chrome/browser/gtk/instant_confirm_dialog_gtk.cc
deleted file mode 100644
index 1e7725c..0000000
--- a/chrome/browser/gtk/instant_confirm_dialog_gtk.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/instant_confirm_dialog_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/instant/instant_confirm_dialog.h"
-#include "chrome/browser/instant/instant_controller.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "googleurl/src/gurl.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-namespace browser {
-
-void ShowInstantConfirmDialog(GtkWindow* parent, Profile* profile) {
-  new InstantConfirmDialogGtk(parent, profile);
-}
-
-}  // namespace browser
-
-InstantConfirmDialogGtk::InstantConfirmDialogGtk(
-    GtkWindow* parent, Profile* profile) : profile_(profile) {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_INSTANT_OPT_IN_TITLE).c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
-      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-      NULL);
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-
-  GtkBox* vbox = GTK_BOX(GTK_DIALOG(dialog_)->vbox);
-  gtk_box_set_spacing(vbox, gtk_util::kControlSpacing);
-
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_INSTANT_OPT_IN_MESSAGE).c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  gtk_box_pack_start(vbox, label, FALSE, FALSE, 0);
-
-  GtkWidget* link_button = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_LEARN_MORE_LABEL).c_str());
-  g_signal_connect(link_button, "clicked",
-                   G_CALLBACK(OnLinkButtonClickedThunk), this);
-
-  GtkWidget* action_area = GTK_DIALOG(dialog_)->action_area;
-  gtk_container_add(GTK_CONTAINER(action_area), link_button);
-  gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(action_area),
-                                     link_button,
-                                     TRUE);
-
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
-  gtk_widget_show_all(dialog_);
-}
-
-InstantConfirmDialogGtk::~InstantConfirmDialogGtk() {
-  gtk_widget_destroy(dialog_);
-}
-
-void InstantConfirmDialogGtk::OnDialogResponse(GtkWidget* dialog,
-                                               int response) {
-  if (response == GTK_RESPONSE_ACCEPT)
-    InstantController::Enable(profile_);
-
-  delete this;
-}
-
-void InstantConfirmDialogGtk::OnLinkButtonClicked(GtkWidget* button) {
-  browser::ShowOptionsURL(profile_, browser::InstantLearnMoreURL());
-}
diff --git a/chrome/browser/gtk/instant_confirm_dialog_gtk.h b/chrome/browser/gtk/instant_confirm_dialog_gtk.h
deleted file mode 100644
index 29a184e..0000000
--- a/chrome/browser/gtk/instant_confirm_dialog_gtk.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_INSTANT_CONFIRM_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_INSTANT_CONFIRM_DIALOG_GTK_H_
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-
-class Profile;
-typedef struct _GtkWindow GtkWindow;
-
-// A dialog that explains some of the privacy implications surrounding instant.
-// Shown when the user enables instant for the first time.
-class InstantConfirmDialogGtk {
- public:
-  InstantConfirmDialogGtk(GtkWindow* parent, Profile* profile);
-  ~InstantConfirmDialogGtk();
-
- private:
-  CHROMEGTK_CALLBACK_1(InstantConfirmDialogGtk, void, OnDialogResponse, int);
-  CHROMEGTK_CALLBACK_0(InstantConfirmDialogGtk, void, OnLinkButtonClicked);
-
-  GtkWidget* dialog_;
-  Profile* profile_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstantConfirmDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_INSTANT_CONFIRM_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/js_modal_dialog_gtk.cc b/chrome/browser/gtk/js_modal_dialog_gtk.cc
deleted file mode 100644
index 27888d4..0000000
--- a/chrome/browser/gtk/js_modal_dialog_gtk.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/js_modal_dialog_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
-#include "base/logging.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// We stash pointers to widgets on the gtk_dialog so we can refer to them
-// after dialog creation.
-const char kPromptTextId[] = "chrome_prompt_text";
-const char kSuppressCheckboxId[] = "chrome_suppress_checkbox";
-
-// If there's a text entry in the dialog, get the text from the first one and
-// return it.
-std::wstring GetPromptText(GtkDialog* dialog) {
-  GtkWidget* widget = static_cast<GtkWidget*>(
-      g_object_get_data(G_OBJECT(dialog), kPromptTextId));
-  if (widget)
-    return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(widget)));
-  return std::wstring();
-}
-
-// If there's a toggle button in the dialog, return the toggled state.
-// Otherwise, return false.
-bool ShouldSuppressJSDialogs(GtkDialog* dialog) {
-  GtkWidget* widget = static_cast<GtkWidget*>(
-      g_object_get_data(G_OBJECT(dialog), kSuppressCheckboxId));
-  if (widget)
-    return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  return false;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// JSModalDialogGtk, public:
-
-JSModalDialogGtk::JSModalDialogGtk(JavaScriptAppModalDialog* dialog,
-                                   gfx::NativeWindow parent_window)
-    : dialog_(dialog) {
-  GtkButtonsType buttons = GTK_BUTTONS_NONE;
-  GtkMessageType message_type = GTK_MESSAGE_OTHER;
-
-  // We add in the OK button manually later because we want to focus it
-  // explicitly.
-  switch (dialog_->dialog_flags()) {
-    case MessageBoxFlags::kIsJavascriptAlert:
-      buttons = GTK_BUTTONS_NONE;
-      message_type = GTK_MESSAGE_WARNING;
-      break;
-
-    case MessageBoxFlags::kIsJavascriptConfirm:
-      if (dialog_->is_before_unload_dialog()) {
-        // onbeforeunload also uses a confirm prompt, it just has custom
-        // buttons.  We add the buttons using gtk_dialog_add_button below.
-        buttons = GTK_BUTTONS_NONE;
-      } else {
-        buttons = GTK_BUTTONS_CANCEL;
-      }
-      message_type = GTK_MESSAGE_QUESTION;
-      break;
-
-    case MessageBoxFlags::kIsJavascriptPrompt:
-      buttons = GTK_BUTTONS_CANCEL;
-      message_type = GTK_MESSAGE_QUESTION;
-      break;
-
-    default:
-      NOTREACHED();
-  }
-
-  // We want the alert to be app modal so put all the browser windows into the
-  // same window group.
-  gtk_util::MakeAppModalWindowGroup();
-
-  gtk_dialog_ = gtk_message_dialog_new(parent_window,
-      GTK_DIALOG_MODAL, message_type, buttons, "%s",
-      WideToUTF8(dialog_->message_text()).c_str());
-  gtk_util::ApplyMessageDialogQuirks(gtk_dialog_);
-  gtk_window_set_title(GTK_WINDOW(gtk_dialog_),
-                       WideToUTF8(dialog_->title()).c_str());
-
-  // Adjust content area as needed.  Set up the prompt text entry or
-  // suppression check box.
-  if (MessageBoxFlags::kIsJavascriptPrompt == dialog_->dialog_flags()) {
-    // TODO(tc): Replace with gtk_dialog_get_content_area() when using GTK 2.14+
-    GtkWidget* contents_vbox = GTK_DIALOG(gtk_dialog_)->vbox;
-    GtkWidget* text_box = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(text_box),
-        WideToUTF8(dialog_->default_prompt_text()).c_str());
-    gtk_box_pack_start(GTK_BOX(contents_vbox), text_box, TRUE, TRUE, 0);
-    g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
-    gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
-  }
-
-  if (dialog_->display_suppress_checkbox()) {
-    GtkWidget* contents_vbox = GTK_DIALOG(gtk_dialog_)->vbox;
-    GtkWidget* check_box = gtk_check_button_new_with_label(
-        l10n_util::GetStringUTF8(
-        IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION).c_str());
-    gtk_box_pack_start(GTK_BOX(contents_vbox), check_box, TRUE, TRUE, 0);
-    g_object_set_data(G_OBJECT(gtk_dialog_), kSuppressCheckboxId, check_box);
-  }
-
-  // Adjust buttons/action area as needed.
-  if (dialog_->is_before_unload_dialog()) {
-    std::string button_text = l10n_util::GetStringUTF8(
-      IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL);
-    gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), button_text.c_str(),
-        GTK_RESPONSE_OK);
-
-    button_text = l10n_util::GetStringUTF8(
-        IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL);
-    gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), button_text.c_str(),
-        GTK_RESPONSE_CANCEL);
-  } else {
-    // Add the OK button and focus it.
-    GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
-        GTK_STOCK_OK, GTK_RESPONSE_OK);
-    if (MessageBoxFlags::kIsJavascriptPrompt != dialog_->dialog_flags())
-      gtk_widget_grab_focus(ok_button);
-  }
-
-  gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
-  g_signal_connect(gtk_dialog_, "response",
-                   G_CALLBACK(OnDialogResponseThunk), this);
-}
-
-JSModalDialogGtk::~JSModalDialogGtk() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// JSModalDialogGtk, NativeAppModalDialog implementation:
-
-int JSModalDialogGtk::GetAppModalDialogButtons() const {
-  switch (dialog_->dialog_flags()) {
-    case MessageBoxFlags::kIsJavascriptAlert:
-      return MessageBoxFlags::DIALOGBUTTON_OK;
-
-    case MessageBoxFlags::kIsJavascriptConfirm:
-      return MessageBoxFlags::DIALOGBUTTON_OK |
-        MessageBoxFlags::DIALOGBUTTON_CANCEL;
-
-    case MessageBoxFlags::kIsJavascriptPrompt:
-      return MessageBoxFlags::DIALOGBUTTON_OK;
-
-    default:
-      NOTREACHED();
-      return 0;
-  }
-}
-
-void JSModalDialogGtk::ShowAppModalDialog() {
-  gtk_util::ShowModalDialogWithMinLocalizedWidth(GTK_WIDGET(gtk_dialog_),
-      IDS_ALERT_DIALOG_WIDTH_CHARS);
-}
-
-void JSModalDialogGtk::ActivateAppModalDialog() {
-  DCHECK(gtk_dialog_);
-  gtk_window_present(GTK_WINDOW(gtk_dialog_));}
-
-void JSModalDialogGtk::CloseAppModalDialog() {
-  DCHECK(gtk_dialog_);
-  OnDialogResponse(gtk_dialog_, GTK_RESPONSE_DELETE_EVENT);
-}
-
-void JSModalDialogGtk::AcceptAppModalDialog() {
-  OnDialogResponse(gtk_dialog_, GTK_RESPONSE_OK);
-}
-
-void JSModalDialogGtk::CancelAppModalDialog() {
-  OnDialogResponse(gtk_dialog_, GTK_RESPONSE_CANCEL);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// JSModalDialogGtk, private:
-
-void JSModalDialogGtk::OnDialogResponse(GtkWidget* dialog,
-                                        int response_id) {
-  switch (response_id) {
-    case GTK_RESPONSE_OK:
-      // The first arg is the prompt text and the second is true if we want to
-      // suppress additional popups from the page.
-      dialog_->OnAccept(GetPromptText(GTK_DIALOG(dialog)),
-                        ShouldSuppressJSDialogs(GTK_DIALOG(dialog)));
-      break;
-
-    case GTK_RESPONSE_CANCEL:
-    case GTK_RESPONSE_DELETE_EVENT:   // User hit the X on the dialog.
-      dialog_->OnCancel(ShouldSuppressJSDialogs(GTK_DIALOG(dialog)));
-      break;
-
-    default:
-      NOTREACHED();
-  }
-  gtk_widget_destroy(GTK_WIDGET(dialog));
-
-  // Now that the dialog is gone, we can put all the  windows into separate
-  // window groups so other dialogs are no longer app modal.
-  gtk_util::AppModalDismissedUngroupWindows();
-  delete this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeAppModalDialog, public:
-
-// static
-NativeAppModalDialog* NativeAppModalDialog::CreateNativeJavaScriptPrompt(
-    JavaScriptAppModalDialog* dialog,
-    gfx::NativeWindow parent_window) {
-  return new JSModalDialogGtk(dialog, parent_window);
-}
diff --git a/chrome/browser/gtk/js_modal_dialog_gtk.h b/chrome/browser/gtk/js_modal_dialog_gtk.h
deleted file mode 100644
index a6a132b..0000000
--- a/chrome/browser/gtk/js_modal_dialog_gtk.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_JS_MODAL_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_JS_MODAL_DIALOG_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
-#include "gfx/native_widget_types.h"
-
-typedef struct _GtkWidget GtkWidget;
-
-class JavaScriptAppModalDialog;
-
-class JSModalDialogGtk : public NativeAppModalDialog {
- public:
-  JSModalDialogGtk(JavaScriptAppModalDialog* dialog,
-                   gfx::NativeWindow parent_window);
-  virtual ~JSModalDialogGtk();
-
-  // Overridden from NativeAppModalDialog:
-  virtual int GetAppModalDialogButtons() const;
-  virtual void ShowAppModalDialog();
-  virtual void ActivateAppModalDialog();
-  virtual void CloseAppModalDialog();
-  virtual void AcceptAppModalDialog();
-  virtual void CancelAppModalDialog();
-
- private:
-  CHROMEGTK_CALLBACK_1(JSModalDialogGtk, void, OnDialogResponse, int);
-
-  scoped_ptr<JavaScriptAppModalDialog> dialog_;
-  GtkWidget* gtk_dialog_;
-
-  DISALLOW_COPY_AND_ASSIGN(JSModalDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_JS_MODAL_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/keyword_editor_view.cc b/chrome/browser/gtk/keyword_editor_view.cc
deleted file mode 100644
index 63931b9..0000000
--- a/chrome/browser/gtk/keyword_editor_view.cc
+++ /dev/null
@@ -1,502 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/keyword_editor_view.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/edit_search_engine_dialog.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/keyword_editor_controller.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/search_engines/template_url_table_model.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-// How many rows should be added to an index into the |table_model_| to get the
-// corresponding row in |list_store_|
-const int kFirstGroupRowOffset = 2;
-const int kSecondGroupRowOffset = 5;
-
-KeywordEditorView* instance_ = NULL;
-
-}  // namespace
-
-// static
-void KeywordEditorView::Show(Profile* profile) {
-  DCHECK(profile);
-  // If this panel is opened from an Incognito window, closing that window can
-  // leave this with a stale pointer. Use the original profile instead.
-  // See http://crbug.com/23359.
-  profile = profile->GetOriginalProfile();
-  if (!profile->GetTemplateURLModel())
-    return;
-
-  // If there's already an existing editor window, activate it.
-  if (instance_) {
-    gtk_util::PresentWindow(instance_->dialog_, 0);
-  } else {
-    instance_ = new KeywordEditorView(profile);
-    gtk_util::ShowDialogWithLocalizedSize(instance_->dialog_,
-        IDS_SEARCHENGINES_DIALOG_WIDTH_CHARS,
-        IDS_SEARCHENGINES_DIALOG_HEIGHT_LINES,
-        true);
-  }
-}
-
-void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url,
-                                        const string16& title,
-                                        const string16& keyword,
-                                        const std::string& url) {
-  if (template_url) {
-    controller_->ModifyTemplateURL(template_url, title, keyword, url);
-
-    // Force the make default button to update.
-    EnableControls();
-  } else {
-    SelectModelRow(controller_->AddTemplateURL(title, keyword, url));
-  }
-}
-
-KeywordEditorView::~KeywordEditorView() {
-  controller_->url_model()->RemoveObserver(this);
-}
-
-KeywordEditorView::KeywordEditorView(Profile* profile)
-    : profile_(profile),
-      controller_(new KeywordEditorController(profile)),
-      table_model_(controller_->table_model()) {
-  Init();
-}
-
-void KeywordEditorView::Init() {
-  std::string dialog_name =
-      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE);
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      NULL,
-      // Non-modal.
-      GTK_DIALOG_NO_SEPARATOR,
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile_));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_box_pack_start(GTK_BOX(hbox), scroll_window, TRUE, TRUE, 0);
-
-  list_store_ = gtk_list_store_new(COL_COUNT,
-                                   GDK_TYPE_PIXBUF,
-                                   G_TYPE_STRING,
-                                   G_TYPE_STRING,
-                                   G_TYPE_BOOLEAN,
-                                   G_TYPE_BOOLEAN,
-                                   G_TYPE_INT,
-                                   G_TYPE_BOOLEAN);
-  tree_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_));
-  g_object_unref(list_store_);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), TRUE);
-  gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(tree_),
-                                       OnCheckRowIsSeparator,
-                                       NULL, NULL);
-  g_signal_connect(tree_, "row-activated",
-                   G_CALLBACK(OnRowActivated), this);
-  gtk_container_add(GTK_CONTAINER(scroll_window), tree_);
-
-  GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
-  GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
-  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
-                                     COL_FAVICON);
-  GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
-  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
-                                     COL_TITLE);
-  gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight",
-                                     COL_WEIGHT);
-  gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight-set",
-                                     COL_WEIGHT_SET);
-  gtk_tree_view_column_set_title(
-      title_column, l10n_util::GetStringUTF8(
-          IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN).c_str());
-  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), title_column);
-
-  GtkTreeViewColumn* keyword_column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(
-          IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_KEYWORD,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), keyword_column);
-
-  selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_));
-  gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE);
-  gtk_tree_selection_set_select_function(selection_, OnSelectionFilter,
-                                         NULL, NULL);
-  g_signal_connect(selection_, "changed",
-                   G_CALLBACK(OnSelectionChanged), this);
-
-  GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0);
-
-  add_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(
-              IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON)).c_str());
-  g_signal_connect(add_button_, "clicked",
-                   G_CALLBACK(OnAddButtonClicked), this);
-  gtk_box_pack_start(GTK_BOX(button_box), add_button_, FALSE, FALSE, 0);
-
-  edit_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON).c_str());
-  g_signal_connect(edit_button_, "clicked",
-                   G_CALLBACK(OnEditButtonClicked), this);
-  gtk_box_pack_start(GTK_BOX(button_box), edit_button_, FALSE, FALSE, 0);
-
-  remove_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(
-              IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON)).c_str());
-  g_signal_connect(remove_button_, "clicked",
-                   G_CALLBACK(OnRemoveButtonClicked), this);
-  gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0);
-
-  make_default_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(
-          IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON).c_str());
-  g_signal_connect(make_default_button_, "clicked",
-                   G_CALLBACK(OnMakeDefaultButtonClicked), this);
-  gtk_box_pack_start(GTK_BOX(button_box), make_default_button_, FALSE, FALSE,
-                     0);
-
-  controller_->url_model()->AddObserver(this);
-  table_model_->SetObserver(this);
-  table_model_->Reload();
-
-  EnableControls();
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
-}
-
-void KeywordEditorView::EnableControls() {
-  bool can_edit = false;
-  bool can_make_default = false;
-  bool can_remove = false;
-  int model_row = GetSelectedModelRow();
-  if (model_row != -1) {
-    const TemplateURL* selected_url = controller_->GetTemplateURL(model_row);
-    can_edit = controller_->CanEdit(selected_url);
-    can_make_default = controller_->CanMakeDefault(selected_url);
-    can_remove = controller_->CanRemove(selected_url);
-  }
-  gtk_widget_set_sensitive(add_button_, controller_->loaded());
-  gtk_widget_set_sensitive(edit_button_, can_edit);
-  gtk_widget_set_sensitive(remove_button_, can_remove);
-  gtk_widget_set_sensitive(make_default_button_, can_make_default);
-}
-
-void KeywordEditorView::SetColumnValues(int model_row, GtkTreeIter* iter) {
-  SkBitmap bitmap = table_model_->GetIcon(model_row);
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
-  gtk_list_store_set(
-      list_store_, iter,
-      COL_FAVICON, pixbuf,
-      // Dunno why, even with COL_WEIGHT_SET to FALSE here, the weight still
-      // has an effect.  So we just set it to normal.
-      COL_WEIGHT, PANGO_WEIGHT_NORMAL,
-      COL_WEIGHT_SET, TRUE,
-      COL_TITLE, UTF16ToUTF8(table_model_->GetText(
-          model_row, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)).c_str(),
-      COL_KEYWORD, UTF16ToUTF8(table_model_->GetText(
-          model_row, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN)).c_str(),
-      -1);
-  g_object_unref(pixbuf);
-}
-
-int KeywordEditorView::GetListStoreRowForModelRow(int model_row) const {
-  if (model_row < model_second_group_index_)
-    return model_row + kFirstGroupRowOffset;
-  else
-    return model_row + kSecondGroupRowOffset;
-}
-
-int KeywordEditorView::GetModelRowForPath(GtkTreePath* path) const {
-  gint* indices = gtk_tree_path_get_indices(path);
-  if (!indices) {
-    NOTREACHED();
-    return -1;
-  }
-  if (indices[0] >= model_second_group_index_ + kSecondGroupRowOffset)
-    return indices[0] - kSecondGroupRowOffset;
-  return indices[0] - kFirstGroupRowOffset;
-}
-
-int KeywordEditorView::GetModelRowForIter(GtkTreeIter* iter) const {
-  GtkTreePath* path = gtk_tree_model_get_path(GTK_TREE_MODEL(list_store_),
-                                              iter);
-  int model_row = GetModelRowForPath(path);
-  gtk_tree_path_free(path);
-  return model_row;
-}
-
-int KeywordEditorView::GetSelectedModelRow() const {
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(selection_, NULL, &iter))
-    return -1;
-  return GetModelRowForIter(&iter);
-}
-
-void KeywordEditorView::SelectModelRow(int model_row) {
-  int row = GetListStoreRowForModelRow(model_row);
-  gtk_tree::SelectAndFocusRowNum(row, GTK_TREE_VIEW(tree_));
-}
-
-void KeywordEditorView::AddNodeToList(int model_row) {
-  GtkTreeIter iter;
-  int row = GetListStoreRowForModelRow(model_row);
-  if (row == 0) {
-    gtk_list_store_prepend(list_store_, &iter);
-  } else {
-    GtkTreeIter sibling;
-    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling,
-                                  NULL, row - 1);
-    gtk_list_store_insert_after(list_store_, &iter, &sibling);
-  }
-
-  SetColumnValues(model_row, &iter);
-}
-
-void KeywordEditorView::OnModelChanged() {
-  model_second_group_index_ = table_model_->last_search_engine_index();
-  gtk_list_store_clear(list_store_);
-
-  TableModel::Groups groups(table_model_->GetGroups());
-  if (groups.size() != 2) {
-    NOTREACHED();
-    return;
-  }
-
-  GtkTreeIter iter;
-  // First group title.
-  gtk_list_store_append(list_store_, &iter);
-  gtk_list_store_set(
-      list_store_, &iter,
-      COL_WEIGHT, PANGO_WEIGHT_BOLD,
-      COL_WEIGHT_SET, TRUE,
-      COL_TITLE, UTF16ToUTF8(groups[0].title).c_str(),
-      COL_IS_HEADER, TRUE,
-      -1);
-  // First group separator.
-  gtk_list_store_append(list_store_, &iter);
-  gtk_list_store_set(
-      list_store_, &iter,
-      COL_IS_HEADER, TRUE,
-      COL_IS_SEPARATOR, TRUE,
-      -1);
-
-  // Blank row between groups.
-  gtk_list_store_append(list_store_, &iter);
-  gtk_list_store_set(
-      list_store_, &iter,
-      COL_IS_HEADER, TRUE,
-      -1);
-  // Second group title.
-  gtk_list_store_append(list_store_, &iter);
-  gtk_list_store_set(
-      list_store_, &iter,
-      COL_WEIGHT, PANGO_WEIGHT_BOLD,
-      COL_WEIGHT_SET, TRUE,
-      COL_TITLE, UTF16ToUTF8(groups[1].title).c_str(),
-      COL_IS_HEADER, TRUE,
-      -1);
-  // Second group separator.
-  gtk_list_store_append(list_store_, &iter);
-  gtk_list_store_set(
-      list_store_, &iter,
-      COL_IS_HEADER, TRUE,
-      COL_IS_SEPARATOR, TRUE,
-      -1);
-
-  for (int i = 0; i < table_model_->RowCount(); ++i)
-    AddNodeToList(i);
-}
-
-void KeywordEditorView::OnItemsChanged(int start, int length) {
-  DCHECK(model_second_group_index_ == table_model_->last_search_engine_index());
-  GtkTreeIter iter;
-  for (int i = 0; i < length; ++i) {
-    int row = GetListStoreRowForModelRow(start + i);
-    bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
-        &iter, NULL, row);
-    if (!rv) {
-      NOTREACHED();
-      return;
-    }
-    SetColumnValues(start + i, &iter);
-    rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
-  }
-}
-
-void KeywordEditorView::OnItemsAdded(int start, int length) {
-  model_second_group_index_ = table_model_->last_search_engine_index();
-  for (int i = 0; i < length; ++i) {
-    AddNodeToList(start + i);
-  }
-}
-
-void KeywordEditorView::OnItemsRemoved(int start, int length) {
-  // This is quite likely not correct with removing multiple in one call, but
-  // that shouldn't happen since we only can select and modify/remove one at a
-  // time.
-  DCHECK_EQ(length, 1);
-  for (int i = 0; i < length; ++i) {
-    int row = GetListStoreRowForModelRow(start + i);
-    GtkTreeIter iter;
-    if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter,
-                                       NULL, row)) {
-      NOTREACHED();
-      return;
-    }
-    gtk_list_store_remove(list_store_, &iter);
-  }
-  model_second_group_index_ = table_model_->last_search_engine_index();
-}
-
-void KeywordEditorView::OnTemplateURLModelChanged() {
-  EnableControls();
-}
-
-// static
-void KeywordEditorView::OnWindowDestroy(GtkWidget* widget,
-                                        KeywordEditorView* window) {
-  instance_ = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
-}
-
-// static
-void KeywordEditorView::OnResponse(GtkDialog* dialog, int response_id,
-                                   KeywordEditorView* window) {
-  gtk_widget_destroy(window->dialog_);
-}
-
-// static
-gboolean KeywordEditorView::OnCheckRowIsSeparator(GtkTreeModel* model,
-                                                  GtkTreeIter* iter,
-                                                  gpointer user_data) {
-  gboolean is_separator;
-  gtk_tree_model_get(model, iter, COL_IS_SEPARATOR, &is_separator, -1);
-  return is_separator;
-}
-
-// static
-gboolean KeywordEditorView::OnSelectionFilter(GtkTreeSelection* selection,
-                                              GtkTreeModel* model,
-                                              GtkTreePath* path,
-                                              gboolean path_currently_selected,
-                                              gpointer user_data) {
-  GtkTreeIter iter;
-  if (!gtk_tree_model_get_iter(model, &iter, path)) {
-    NOTREACHED();
-    return TRUE;
-  }
-  gboolean is_header;
-  gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1);
-  return !is_header;
-}
-
-// static
-void KeywordEditorView::OnSelectionChanged(
-    GtkTreeSelection* selection, KeywordEditorView* editor) {
-  editor->EnableControls();
-}
-
-// static
-void KeywordEditorView::OnRowActivated(GtkTreeView* tree_view,
-                                       GtkTreePath* path,
-                                       GtkTreeViewColumn* column,
-                                       KeywordEditorView* editor) {
-  OnEditButtonClicked(NULL, editor);
-}
-
-// static
-void KeywordEditorView::OnAddButtonClicked(GtkButton* button,
-                                           KeywordEditorView* editor) {
-  new EditSearchEngineDialog(
-      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(
-          gtk_util::GetDialogWindow(editor->dialog_)))),
-      NULL,
-      editor,
-      editor->profile_);
-}
-
-// static
-void KeywordEditorView::OnEditButtonClicked(GtkButton* button,
-                                            KeywordEditorView* editor) {
-  int model_row = editor->GetSelectedModelRow();
-  if (model_row == -1)
-    return;
-
-  new EditSearchEngineDialog(
-      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(
-          gtk_util::GetDialogWindow(editor->dialog_)))),
-      editor->controller_->GetTemplateURL(model_row),
-      editor,
-      editor->profile_);
-}
-
-// static
-void KeywordEditorView::OnRemoveButtonClicked(GtkButton* button,
-                                              KeywordEditorView* editor) {
-  int model_row = editor->GetSelectedModelRow();
-  if (model_row == -1) {
-    NOTREACHED();
-    return;
-  }
-  editor->controller_->RemoveTemplateURL(model_row);
-  if (model_row >= editor->table_model_->RowCount())
-    model_row = editor->table_model_->RowCount() - 1;
-  if (model_row >= 0)
-    editor->SelectModelRow(model_row);
-}
-
-// static
-void KeywordEditorView::OnMakeDefaultButtonClicked(GtkButton* button,
-                                                   KeywordEditorView* editor) {
-  int model_row = editor->GetSelectedModelRow();
-  if (model_row == -1) {
-    NOTREACHED();
-    return;
-  }
-  int new_index = editor->controller_->MakeDefaultTemplateURL(model_row);
-  if (new_index > 0) {
-    editor->SelectModelRow(new_index);
-  }
-}
diff --git a/chrome/browser/gtk/keyword_editor_view.h b/chrome/browser/gtk/keyword_editor_view.h
deleted file mode 100644
index 451d635..0000000
--- a/chrome/browser/gtk/keyword_editor_view.h
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_KEYWORD_EDITOR_VIEW_H_
-#define CHROME_BROWSER_GTK_KEYWORD_EDITOR_VIEW_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/table_model_observer.h"
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/scoped_ptr.h"
-#include "base/string16.h"
-#include "chrome/browser/search_engines/edit_search_engine_controller.h"
-#include "chrome/browser/search_engines/template_url_model_observer.h"
-
-class AccessibleWidgetHelper;
-class KeywordEditorController;
-class Profile;
-class TemplateURLTableModel;
-
-class KeywordEditorView : public TableModelObserver,
-                          public TemplateURLModelObserver,
-                          public EditSearchEngineControllerDelegate {
- public:
-  virtual ~KeywordEditorView();
-
-  // Create (if necessary) and show the keyword editor window.
-  static void Show(Profile* profile);
-
-  // Overriden from EditSearchEngineControllerDelegate.
-  virtual void OnEditedKeyword(const TemplateURL* template_url,
-                               const string16& title,
-                               const string16& keyword,
-                               const std::string& url);
- private:
-  // Column ids for |list_store_|.
-  enum {
-    COL_FAVICON,
-    COL_TITLE,
-    COL_KEYWORD,
-    COL_IS_HEADER,
-    COL_IS_SEPARATOR,
-    COL_WEIGHT,
-    COL_WEIGHT_SET,
-    COL_COUNT,
-  };
-
-  explicit KeywordEditorView(Profile* profile);
-  void Init();
-
-  // Enable buttons based on selection state.
-  void EnableControls();
-
-  // Set the column values for |row| of |table_model_| in the |list_store_| at
-  // |iter|.
-  void SetColumnValues(int row, GtkTreeIter* iter);
-
-  // Get the row number in the GtkListStore corresponding to |model_row|.
-  int GetListStoreRowForModelRow(int model_row) const;
-
-  // Get the row number in the TemplateURLTableModel corresponding to |path|.
-  int GetModelRowForPath(GtkTreePath* path) const;
-
-  // Get the row number in the TemplateURLTableModel corresponding to |iter|.
-  int GetModelRowForIter(GtkTreeIter* iter) const;
-
-  // Get the row number in the TemplateURLTableModel of the current selection,
-  // or -1 if no row is selected.
-  int GetSelectedModelRow() const;
-
-  // Select the row in the |tree_| corresponding to |model_row|.
-  void SelectModelRow(int model_row);
-
-  // Add the values from |row| of |table_model_|.
-  void AddNodeToList(int row);
-
-  // TableModelObserver implementation.
-  virtual void OnModelChanged();
-  virtual void OnItemsChanged(int start, int length);
-  virtual void OnItemsAdded(int start, int length);
-  virtual void OnItemsRemoved(int start, int length);
-
-  // TemplateURLModelObserver notification.
-  virtual void OnTemplateURLModelChanged();
-
-  // Callback for window destruction.
-  static void OnWindowDestroy(GtkWidget* widget, KeywordEditorView* window);
-
-  // Callback for dialog buttons.
-  static void OnResponse(GtkDialog* dialog, int response_id,
-                         KeywordEditorView* window);
-
-  // Callback checking whether a row should be drawn as a separator.
-  static gboolean OnCheckRowIsSeparator(GtkTreeModel* model,
-                                        GtkTreeIter* iter,
-                                        gpointer user_data);
-
-  // Callback checking whether a row may be selected.  We use some rows in the
-  // table as headers/separators for the groups, which should not be selectable.
-  static gboolean OnSelectionFilter(GtkTreeSelection* selection,
-                                    GtkTreeModel* model,
-                                    GtkTreePath* path,
-                                    gboolean path_currently_selected,
-                                    gpointer user_data);
-
-  // Callback for when user selects something.
-  static void OnSelectionChanged(GtkTreeSelection* selection,
-                                 KeywordEditorView* editor);
-
-  // Callbacks for user actions modifying the table.
-  static void OnRowActivated(GtkTreeView* tree_view,
-                             GtkTreePath* path,
-                             GtkTreeViewColumn* column,
-                             KeywordEditorView* editor);
-  static void OnAddButtonClicked(GtkButton* button,
-                                 KeywordEditorView* editor);
-  static void OnEditButtonClicked(GtkButton* button,
-                                  KeywordEditorView* editor);
-  static void OnRemoveButtonClicked(GtkButton* button,
-                                    KeywordEditorView* editor);
-  static void OnMakeDefaultButtonClicked(GtkButton* button,
-                                         KeywordEditorView* editor);
-
-  // The table listing the search engines.
-  GtkWidget* tree_;
-  GtkListStore* list_store_;
-  GtkTreeSelection* selection_;
-
-  // Buttons for acting on the table.
-  GtkWidget* add_button_;
-  GtkWidget* edit_button_;
-  GtkWidget* remove_button_;
-  GtkWidget* make_default_button_;
-
-  // The containing dialog.
-  GtkWidget* dialog_;
-
-  // The profile.
-  Profile* profile_;
-
-  scoped_ptr<KeywordEditorController> controller_;
-
-  TemplateURLTableModel* table_model_;
-
-  // We store our own index of the start of the second group within the model,
-  // as when OnItemsRemoved is called the value in the model is already updated
-  // but we need the old value to know which row to remove from the
-  // |list_store_|.
-  int model_second_group_index_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  friend class KeywordEditorViewTest;
-  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Empty);
-  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Add);
-  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, MakeDefault);
-  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Remove);
-  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Edit);
-
-  DISALLOW_COPY_AND_ASSIGN(KeywordEditorView);
-};
-
-#endif  // CHROME_BROWSER_GTK_KEYWORD_EDITOR_VIEW_H_
diff --git a/chrome/browser/gtk/keyword_editor_view_unittest.cc b/chrome/browser/gtk/keyword_editor_view_unittest.cc
deleted file mode 100644
index 1f06fb8..0000000
--- a/chrome/browser/gtk/keyword_editor_view_unittest.cc
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/keyword_editor_view.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "base/string16.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/search_engines/template_url_table_model.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class KeywordEditorViewTest : public testing::Test {
- public:
-  virtual void SetUp() {
-    profile_.reset(new TestingProfile());
-    profile_->CreateTemplateURLModel();
-  }
-
-  TemplateURL* AddToModel(const std::string& name,
-                          const std::string& keyword,
-                          bool make_default) {
-    TemplateURL* template_url = new TemplateURL();
-    template_url->set_short_name(UTF8ToWide(name));
-    template_url->set_keyword(UTF8ToWide(keyword));
-    template_url->SetURL("http://example.com/{searchTerms}", 0, 0);
-    profile_->GetTemplateURLModel()->Add(template_url);
-    if (make_default)
-      profile_->GetTemplateURLModel()->SetDefaultSearchProvider(template_url);
-    return template_url;
-  }
-
-  int GetSelectedRowNum(const KeywordEditorView& editor) {
-    GtkTreeIter iter;
-    if (!gtk_tree_selection_get_selected(editor.selection_, NULL, &iter))
-      return -1;
-    return gtk_tree::GetRowNumForIter(GTK_TREE_MODEL(editor.list_store_),
-                                      &iter);
-  }
-
-  // Get the search engines displayed in the dialog in the order they are
-  // displayed, as a comma seperated string.
-  // The headers are included as "!,_" for the first group header and "_,@,_"
-  // for the second group header (This allows the tests to ensure the headers
-  // aren't accidentally misplaced/moved.)
-  // Ex: EXPECT_STREQ("!,_,A (Default),_,@,_,B",
-  //                  GetDisplayedEngines(editor).c_str());
-  std::string GetDisplayedEngines(const KeywordEditorView& editor) {
-    TableModel::Groups groups(editor.table_model_->GetGroups());
-    std::vector<std::string> parts;
-    GtkTreeModel* tree_model = GTK_TREE_MODEL(editor.list_store_);
-    GtkTreeIter iter;
-    if (!gtk_tree_model_get_iter_first(tree_model, &iter))
-      return std::string();
-    while (true) {
-      gchar* name;
-      gboolean is_header;
-      gtk_tree_model_get(tree_model, &iter,
-                         KeywordEditorView::COL_TITLE, &name,
-                         KeywordEditorView::COL_IS_HEADER, &is_header,
-                         -1);
-      if (name && UTF16ToUTF8(groups[0].title) == name)
-        parts.push_back("!");
-      else if (name && UTF16ToUTF8(groups[1].title) == name)
-        parts.push_back("@");
-      else if (is_header)
-        parts.push_back("_");
-      else if (name)
-        parts.push_back(name);
-      else
-        parts.push_back("???");
-      if (name)
-        g_free(name);
-      if (!gtk_tree_model_iter_next(tree_model, &iter))
-        break;
-    }
-    return JoinString(parts, ',');
-  }
-
- protected:
-  MessageLoopForUI message_loop_;
-  scoped_ptr<TestingProfile> profile_;
-};
-
-TEST_F(KeywordEditorViewTest, Empty) {
-  KeywordEditorView editor(profile_.get());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,_,@,_", GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(-1, GetSelectedRowNum(editor));
-}
-
-TEST_F(KeywordEditorViewTest, Add) {
-  AddToModel("A1", "k1", true);
-  KeywordEditorView editor(profile_.get());
-  EXPECT_STREQ("!,_,A1 (Default),_,@,_", GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(-1, GetSelectedRowNum(editor));
-
-  editor.OnEditedKeyword(NULL, ASCIIToUTF16("B"), ASCIIToUTF16("b"),
-                         "example.com");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A1 (Default),_,@,_,B", GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(6, GetSelectedRowNum(editor));
-
-  editor.OnEditedKeyword(NULL, ASCIIToUTF16("C"), ASCIIToUTF16("c"),
-                         "example.com/{searchTerms}");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A1 (Default),_,@,_,B,C",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(7, GetSelectedRowNum(editor));
-
-  editor.OnEditedKeyword(NULL, ASCIIToUTF16("D"), ASCIIToUTF16("d"),
-                         "example.com");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A1 (Default),_,@,_,B,C,D",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(8, GetSelectedRowNum(editor));
-}
-
-TEST_F(KeywordEditorViewTest, MakeDefault) {
-  AddToModel("A", "a", true);
-  AddToModel("B", "b", false);
-  AddToModel("C", "c", false);
-  AddToModel("D", "d", false);
-  KeywordEditorView editor(profile_.get());
-  EXPECT_STREQ("!,_,A (Default),_,@,_,B,C,D",
-               GetDisplayedEngines(editor).c_str());
-
-  GtkTreeIter iter;
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
-                                &iter, NULL, 6);
-  gtk_tree_selection_select_iter(editor.selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-
-  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A,B (Default),_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(3, GetSelectedRowNum(editor));
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
-                                &iter, NULL, 8);
-  gtk_tree_selection_select_iter(editor.selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-
-  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A,B,D (Default),_,@,_,C",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(4, GetSelectedRowNum(editor));
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
-                                &iter, NULL, 2);
-  gtk_tree_selection_select_iter(editor.selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-
-  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A (Default),B,D,_,@,_,C",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(2, GetSelectedRowNum(editor));
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
-                                &iter, NULL, 4);
-  gtk_tree_selection_select_iter(editor.selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-
-  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
-  EXPECT_STREQ("!,_,A,B,D (Default),_,@,_,C",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(4, GetSelectedRowNum(editor));
-}
-
-TEST_F(KeywordEditorViewTest, Remove) {
-  AddToModel("A", "a", true);
-  AddToModel("B", "b", true);
-  AddToModel("C", "c", false);
-  AddToModel("D", "d", false);
-  KeywordEditorView editor(profile_.get());
-  EXPECT_STREQ("!,_,A,B (Default),_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-
-  GtkTreeIter iter;
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
-                                &iter, NULL, 2);
-  gtk_tree_selection_select_iter(editor.selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(editor.remove_button_));
-  EXPECT_STREQ("!,_,B (Default),_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(2, GetSelectedRowNum(editor));
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
-                                &iter, NULL, 6);
-  gtk_tree_selection_select_iter(editor.selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(editor.remove_button_));
-  EXPECT_STREQ("!,_,B (Default),_,@,_,D",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(6, GetSelectedRowNum(editor));
-
-  gtk_button_clicked(GTK_BUTTON(editor.remove_button_));
-  EXPECT_STREQ("!,_,B (Default),_,@,_",
-               GetDisplayedEngines(editor).c_str());
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
-  EXPECT_EQ(2, GetSelectedRowNum(editor));
-}
-
-TEST_F(KeywordEditorViewTest, Edit) {
-  TemplateURL* a = AddToModel("A", "a", true);
-  TemplateURL* b = AddToModel("B", "b", true);
-  TemplateURL* c = AddToModel("C", "c", false);
-  TemplateURL* d = AddToModel("D", "d", false);
-  KeywordEditorView editor(profile_.get());
-  EXPECT_STREQ("!,_,A,B (Default),_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-
-  editor.OnEditedKeyword(a, ASCIIToUTF16("AA"), ASCIIToUTF16("a"),
-                         "example.com/{searchTerms}");
-  EXPECT_STREQ("!,_,AA,B (Default),_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-
-  editor.OnEditedKeyword(b, ASCIIToUTF16("BB"), ASCIIToUTF16("b"),
-                         "foo.example.com/{searchTerms}");
-  EXPECT_STREQ("!,_,AA,BB (Default),_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-
-  editor.OnEditedKeyword(b, ASCIIToUTF16("BBB"), ASCIIToUTF16("b"),
-                         "example.com");
-  EXPECT_STREQ("!,_,AA,BBB,_,@,_,C,D",
-               GetDisplayedEngines(editor).c_str());
-
-  editor.OnEditedKeyword(d, ASCIIToUTF16("DD"), ASCIIToUTF16("d"),
-                         "example.com");
-  EXPECT_STREQ("!,_,AA,BBB,_,@,_,C,DD",
-               GetDisplayedEngines(editor).c_str());
-
-  editor.OnEditedKeyword(c, ASCIIToUTF16("CC"), ASCIIToUTF16("cc"),
-                         "example.com");
-  EXPECT_STREQ("!,_,AA,BBB,_,@,_,CC,DD",
-               GetDisplayedEngines(editor).c_str());
-}
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
deleted file mode 100644
index 6bc7513..0000000
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ /dev/null
@@ -1,1546 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-
-#include <string>
-
-#include "app/gtk_dnd_util.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/basictypes.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/accessibility_events.h"
-#include "chrome/browser/alternate_nav_url_fetcher.h"
-#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
-#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/command_updater.h"
-#include "chrome/browser/content_setting_bubble_model.h"
-#include "chrome/browser/content_setting_image_model.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/extensions/extension_browser_event_router.h"
-#include "chrome/browser/extensions/extension_tabs_module.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/gtk/bookmark_bubble_gtk.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/cairo_cached_surface.h"
-#include "chrome/browser/gtk/content_setting_bubble_gtk.h"
-#include "chrome/browser/gtk/extension_popup_gtk.h"
-#include "chrome/browser/gtk/first_run_bubble.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/nine_box.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/instant/instant_controller.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/omnibox/location_bar_util.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_action.h"
-#include "chrome/common/extensions/extension_resource.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/page_transition_types.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/font.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "net/base/net_util.h"
-#include "webkit/glue/window_open_disposition.h"
-
-namespace {
-
-// We are positioned with a little bit of extra space that we don't use now.
-const int kTopMargin = 1;
-const int kBottomMargin = 1;
-const int kLeftMargin = 1;
-const int kRightMargin = 1;
-// We draw a border on the top and bottom (but not on left or right).
-const int kBorderThickness = 1;
-
-// Left margin of first run bubble.
-const int kFirstRunBubbleLeftMargin = 8;
-// Extra vertical spacing for first run bubble.
-const int kFirstRunBubbleTopMargin = 5;
-
-// The padding around the top, bottom, and sides of the location bar hbox.
-// We don't want to edit control's text to be right against the edge,
-// as well the tab to search box and other widgets need to have the padding on
-// top and bottom to avoid drawing larger than the location bar space.
-const int kHboxBorder = 2;
-
-// Padding between the elements in the bar.
-const int kInnerPadding = 2;
-
-// Padding between the right of the star and the edge of the URL entry.
-const int kStarRightPadding = 2;
-
-// Colors used to draw the EV certificate rounded bubble.
-const GdkColor kEvSecureTextColor = GDK_COLOR_RGB(0x07, 0x95, 0x00);
-const GdkColor kEvSecureBackgroundColor = GDK_COLOR_RGB(0xef, 0xfc, 0xef);
-const GdkColor kEvSecureBorderColor = GDK_COLOR_RGB(0x90, 0xc3, 0x90);
-
-// Colors used to draw the Tab to Search rounded bubble.
-const GdkColor kKeywordBackgroundColor = GDK_COLOR_RGB(0xf0, 0xf4, 0xfa);
-const GdkColor kKeywordBorderColor = GDK_COLOR_RGB(0xcb, 0xde, 0xf7);
-
-// Use weak gray for showing search and keyword hint text.
-const GdkColor kHintTextColor = GDK_COLOR_RGB(0x75, 0x75, 0x75);
-
-// Size of the rounding of the "Search site for:" box.
-const int kCornerSize = 3;
-
-// If widget is visible, increment the int pointed to by count.
-// Suitible for use with gtk_container_foreach.
-void CountVisibleWidgets(GtkWidget* widget, gpointer count) {
-  if (GTK_WIDGET_VISIBLE(widget))
-    *static_cast<int*>(count) += 1;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// LocationBarViewGtk
-
-// static
-const GdkColor LocationBarViewGtk::kBackgroundColor =
-    GDK_COLOR_RGB(255, 255, 255);
-
-LocationBarViewGtk::LocationBarViewGtk(Browser* browser)
-    : star_image_(NULL),
-      starred_(false),
-      site_type_alignment_(NULL),
-      site_type_event_box_(NULL),
-      location_icon_image_(NULL),
-      drag_icon_(NULL),
-      enable_location_drag_(false),
-      security_info_label_(NULL),
-      tab_to_search_box_(NULL),
-      tab_to_search_full_label_(NULL),
-      tab_to_search_partial_label_(NULL),
-      tab_to_search_hint_(NULL),
-      tab_to_search_hint_leading_label_(NULL),
-      tab_to_search_hint_icon_(NULL),
-      tab_to_search_hint_trailing_label_(NULL),
-      profile_(NULL),
-      command_updater_(browser->command_updater()),
-      toolbar_model_(browser->toolbar_model()),
-      browser_(browser),
-      disposition_(CURRENT_TAB),
-      transition_(PageTransition::TYPED),
-      first_run_bubble_(this),
-      popup_window_mode_(false),
-      theme_provider_(NULL),
-      hbox_width_(0),
-      entry_box_width_(0),
-      show_selected_keyword_(false),
-      show_keyword_hint_(false),
-      update_instant_(true) {
-}
-
-LocationBarViewGtk::~LocationBarViewGtk() {
-  // All of our widgets should have be children of / owned by the alignment.
-  star_.Destroy();
-  hbox_.Destroy();
-  content_setting_hbox_.Destroy();
-  page_action_hbox_.Destroy();
-}
-
-void LocationBarViewGtk::Init(bool popup_window_mode) {
-  popup_window_mode_ = popup_window_mode;
-
-  // Create the widget first, so we can pass it to the AutocompleteEditViewGtk.
-  hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
-  gtk_container_set_border_width(GTK_CONTAINER(hbox_.get()), kHboxBorder);
-  // We will paint for the alignment, to paint the background and border.
-  gtk_widget_set_app_paintable(hbox_.get(), TRUE);
-  // Redraw the whole location bar when it changes size (e.g., when toggling
-  // the home button on/off.
-  gtk_widget_set_redraw_on_allocate(hbox_.get(), TRUE);
-
-  // Now initialize the AutocompleteEditViewGtk.
-  location_entry_.reset(new AutocompleteEditViewGtk(this,
-                                                    toolbar_model_,
-                                                    profile_,
-                                                    command_updater_,
-                                                    popup_window_mode_,
-                                                    hbox_.get()));
-  location_entry_->Init();
-
-  g_signal_connect(hbox_.get(), "expose-event",
-                   G_CALLBACK(&HandleExposeThunk), this);
-
-  BuildSiteTypeArea();
-
-  // Put |tab_to_search_box_|, |location_entry_|, and |tab_to_search_hint_| into
-  // a sub hbox, so that we can make this part horizontally shrinkable without
-  // affecting other elements in the location bar.
-  entry_box_ = gtk_hbox_new(FALSE, kInnerPadding);
-  gtk_widget_show(entry_box_);
-  gtk_widget_set_size_request(entry_box_, 0, -1);
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), entry_box_, TRUE, TRUE, 0);
-
-  // We need to adjust the visibility of the search hint widgets according to
-  // the horizontal space in the |entry_box_|.
-  g_signal_connect(entry_box_, "size-allocate",
-                   G_CALLBACK(&OnEntryBoxSizeAllocateThunk), this);
-
-  // Tab to search (the keyword box on the left hand side).
-  tab_to_search_full_label_ = gtk_label_new(NULL);
-  tab_to_search_partial_label_ = gtk_label_new(NULL);
-  GtkWidget* tab_to_search_label_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox),
-                     tab_to_search_full_label_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox),
-                     tab_to_search_partial_label_, FALSE, FALSE, 0);
-  GtkWidget* tab_to_search_hbox = gtk_hbox_new(FALSE, 0);
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  tab_to_search_magnifier_ = gtk_image_new_from_pixbuf(
-      rb.GetPixbufNamed(IDR_KEYWORD_SEARCH_MAGNIFIER));
-  gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_magnifier_,
-                     FALSE, FALSE, 0);
-  gtk_util::CenterWidgetInHBox(tab_to_search_hbox, tab_to_search_label_hbox,
-                               false, 0);
-
-  // This creates a box around the keyword text with a border, background color,
-  // and padding around the text.
-  tab_to_search_box_ = gtk_util::CreateGtkBorderBin(
-      tab_to_search_hbox, NULL, 1, 1, 1, 3);
-  gtk_widget_set_name(tab_to_search_box_, "chrome-tab-to-search-box");
-  gtk_util::ActAsRoundedWindow(tab_to_search_box_, kKeywordBorderColor,
-                               kCornerSize,
-                               gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
-  // Show all children widgets of |tab_to_search_box_| initially, except
-  // |tab_to_search_partial_label_|.
-  gtk_widget_show_all(tab_to_search_box_);
-  gtk_widget_hide(tab_to_search_box_);
-  gtk_widget_hide(tab_to_search_partial_label_);
-  gtk_box_pack_start(GTK_BOX(entry_box_), tab_to_search_box_, FALSE, FALSE, 0);
-
-  location_entry_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_container_add(GTK_CONTAINER(location_entry_alignment_),
-                    location_entry_->GetNativeView());
-  gtk_box_pack_start(GTK_BOX(entry_box_), location_entry_alignment_,
-                     TRUE, TRUE, 0);
-
-  // Tab to search notification (the hint on the right hand side).
-  tab_to_search_hint_ = gtk_hbox_new(FALSE, 0);
-  gtk_widget_set_name(tab_to_search_hint_, "chrome-tab-to-search-hint");
-  tab_to_search_hint_leading_label_ = gtk_label_new(NULL);
-  gtk_widget_set_sensitive(tab_to_search_hint_leading_label_, FALSE);
-  tab_to_search_hint_icon_ = gtk_image_new_from_pixbuf(
-      rb.GetPixbufNamed(IDR_LOCATION_BAR_KEYWORD_HINT_TAB));
-  tab_to_search_hint_trailing_label_ = gtk_label_new(NULL);
-  gtk_widget_set_sensitive(tab_to_search_hint_trailing_label_, FALSE);
-  gtk_box_pack_start(GTK_BOX(tab_to_search_hint_),
-                     tab_to_search_hint_leading_label_,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tab_to_search_hint_),
-                     tab_to_search_hint_icon_,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(tab_to_search_hint_),
-                     tab_to_search_hint_trailing_label_,
-                     FALSE, FALSE, 0);
-  // Show all children widgets of |tab_to_search_hint_| initially.
-  gtk_widget_show_all(tab_to_search_hint_);
-  gtk_widget_hide(tab_to_search_hint_);
-  // tab_to_search_hint_ gets hidden initially in OnChanged.  Hiding it here
-  // doesn't work, someone is probably calling show_all on our parent box.
-  gtk_box_pack_end(GTK_BOX(entry_box_), tab_to_search_hint_, FALSE, FALSE, 0);
-
-  // We don't show the star in popups, app windows, etc.
-  if (browser_defaults::bookmarks_enabled && !ShouldOnlyShowLocation()) {
-    CreateStarButton();
-    gtk_box_pack_end(GTK_BOX(hbox_.get()), star_.get(), FALSE, FALSE, 0);
-  }
-
-  content_setting_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding + 1));
-  gtk_widget_set_name(content_setting_hbox_.get(),
-                      "chrome-content-setting-hbox");
-  gtk_box_pack_end(GTK_BOX(hbox_.get()), content_setting_hbox_.get(),
-                   FALSE, FALSE, 1);
-
-  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
-    ContentSettingImageViewGtk* content_setting_view =
-        new ContentSettingImageViewGtk(
-            static_cast<ContentSettingsType>(i), this, profile_);
-    content_setting_views_.push_back(content_setting_view);
-    gtk_box_pack_end(GTK_BOX(content_setting_hbox_.get()),
-                     content_setting_view->widget(), FALSE, FALSE, 0);
-  }
-
-  page_action_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
-  gtk_widget_set_name(page_action_hbox_.get(),
-                      "chrome-page-action-hbox");
-  gtk_box_pack_end(GTK_BOX(hbox_.get()), page_action_hbox_.get(),
-                   FALSE, FALSE, 0);
-
-  // Now that we've created the widget hierarchy, connect to the main |hbox_|'s
-  // size-allocate so we can do proper resizing and eliding on
-  // |security_info_label_|.
-  g_signal_connect(hbox_.get(), "size-allocate",
-                   G_CALLBACK(&OnHboxSizeAllocateThunk), this);
-
-  registrar_.Add(this,
-                 NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  theme_provider_ = GtkThemeProvider::GetFrom(profile_);
-  theme_provider_->InitThemesFor(this);
-}
-
-void LocationBarViewGtk::BuildSiteTypeArea() {
-  location_icon_image_ = gtk_image_new();
-  gtk_widget_set_name(location_icon_image_, "chrome-location-icon");
-
-  GtkWidget* icon_alignment = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(icon_alignment), 0, 0, 2, 0);
-  gtk_container_add(GTK_CONTAINER(icon_alignment), location_icon_image_);
-  gtk_widget_show_all(icon_alignment);
-
-  security_info_label_ = gtk_label_new(NULL);
-  gtk_label_set_ellipsize(GTK_LABEL(security_info_label_),
-                          PANGO_ELLIPSIZE_MIDDLE);
-  gtk_widget_modify_fg(GTK_WIDGET(security_info_label_), GTK_STATE_NORMAL,
-                       &kEvSecureTextColor);
-  gtk_widget_set_name(security_info_label_,
-                      "chrome-location-bar-security-info-label");
-
-  GtkWidget* site_type_hbox = gtk_hbox_new(FALSE, 1);
-  gtk_box_pack_start(GTK_BOX(site_type_hbox), icon_alignment,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(site_type_hbox), security_info_label_,
-                     FALSE, FALSE, 2);
-
-  site_type_event_box_ = gtk_event_box_new();
-  gtk_widget_modify_bg(site_type_event_box_, GTK_STATE_NORMAL,
-                       &kEvSecureBackgroundColor);
-  g_signal_connect(site_type_event_box_, "drag-data-get",
-                   G_CALLBACK(&OnIconDragDataThunk), this);
-  g_signal_connect(site_type_event_box_, "drag-begin",
-                   G_CALLBACK(&OnIconDragBeginThunk), this);
-  g_signal_connect(site_type_event_box_, "drag-end",
-                   G_CALLBACK(&OnIconDragEndThunk), this);
-
-  // Make the event box not visible so it does not paint a background.
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
-                                   FALSE);
-  gtk_widget_set_name(site_type_event_box_,
-                      "chrome-location-icon-eventbox");
-  gtk_container_add(GTK_CONTAINER(site_type_event_box_),
-                    site_type_hbox);
-
-  // Put the event box in an alignment to get the padding correct.
-  site_type_alignment_ = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_),
-                            1, 1, 0, 0);
-  gtk_container_add(GTK_CONTAINER(site_type_alignment_),
-                    site_type_event_box_);
-  gtk_box_pack_start(GTK_BOX(hbox_.get()), site_type_alignment_,
-                     FALSE, FALSE, 0);
-
-  g_signal_connect(site_type_event_box_, "button-release-event",
-                   G_CALLBACK(&OnIconReleasedThunk), this);
-}
-
-void LocationBarViewGtk::SetSiteTypeDragSource() {
-  bool enable = !location_entry()->IsEditingOrEmpty();
-  if (enable_location_drag_ == enable)
-    return;
-  enable_location_drag_ = enable;
-
-  if (!enable) {
-    gtk_drag_source_unset(site_type_event_box_);
-    return;
-  }
-
-  gtk_drag_source_set(site_type_event_box_, GDK_BUTTON1_MASK,
-                      NULL, 0, GDK_ACTION_COPY);
-  gtk_dnd_util::SetSourceTargetListFromCodeMask(site_type_event_box_,
-                                                gtk_dnd_util::TEXT_PLAIN |
-                                                gtk_dnd_util::TEXT_URI_LIST |
-                                                gtk_dnd_util::CHROME_NAMED_URL);
-}
-
-void LocationBarViewGtk::SetProfile(Profile* profile) {
-  profile_ = profile;
-}
-
-TabContents* LocationBarViewGtk::GetTabContents() const {
-  return browser_->GetSelectedTabContents();
-}
-
-void LocationBarViewGtk::SetPreviewEnabledPageAction(
-    ExtensionAction *page_action,
-    bool preview_enabled) {
-  DCHECK(page_action);
-  UpdatePageActions();
-  for (ScopedVector<PageActionViewGtk>::iterator iter =
-       page_action_views_.begin(); iter != page_action_views_.end();
-       ++iter) {
-    if ((*iter)->page_action() == page_action) {
-      (*iter)->set_preview_enabled(preview_enabled);
-      UpdatePageActions();
-      return;
-    }
-  }
-}
-
-GtkWidget* LocationBarViewGtk::GetPageActionWidget(
-    ExtensionAction *page_action) {
-  DCHECK(page_action);
-  for (ScopedVector<PageActionViewGtk>::iterator iter =
-           page_action_views_.begin();
-       iter != page_action_views_.end();
-       ++iter) {
-    if ((*iter)->page_action() == page_action)
-      return (*iter)->widget();
-  }
-  return NULL;
-}
-
-void LocationBarViewGtk::Update(const TabContents* contents) {
-  bool star_enabled = star_.get() && !toolbar_model_->input_in_progress();
-  command_updater_->UpdateCommandEnabled(IDC_BOOKMARK_PAGE, star_enabled);
-  if (star_.get()) {
-    if (star_enabled)
-      gtk_widget_show_all(star_.get());
-    else
-      gtk_widget_hide_all(star_.get());
-  }
-  UpdateSiteTypeArea();
-  UpdateContentSettingsIcons();
-  UpdatePageActions();
-  location_entry_->Update(contents);
-  // The security level (background color) could have changed, etc.
-  if (theme_provider_->UseGtkTheme()) {
-    // In GTK mode, we need our parent to redraw, as it draws the text entry
-    // border.
-    gtk_widget_queue_draw(widget()->parent);
-  } else {
-    gtk_widget_queue_draw(widget());
-  }
-}
-
-void LocationBarViewGtk::OnAutocompleteWillClosePopup() {
-  if (!update_instant_)
-    return;
-
-  InstantController* instant = browser_->instant();
-  if (instant && !instant->commit_on_mouse_up())
-    instant->DestroyPreviewContents();
-}
-
-void LocationBarViewGtk::OnAutocompleteLosingFocus(
-    gfx::NativeView view_gaining_focus) {
-  SetSuggestedText(string16());
-
-  InstantController* instant = browser_->instant();
-  if (instant)
-    instant->OnAutocompleteLostFocus(view_gaining_focus);
-}
-
-void LocationBarViewGtk::OnAutocompleteWillAccept() {
-  update_instant_ = false;
-}
-
-bool LocationBarViewGtk::OnCommitSuggestedText(
-    const std::wstring& typed_text) {
-  InstantController* instant = browser_->instant();
-  if (!instant)
-    return false;
-
-  return location_entry_->CommitInstantSuggestion();
-}
-
-bool LocationBarViewGtk::AcceptCurrentInstantPreview() {
-  return InstantController::CommitIfCurrent(browser_->instant());
-}
-
-void LocationBarViewGtk::OnSetSuggestedSearchText(
-    const string16& suggested_text) {
-  SetSuggestedText(suggested_text);
-}
-
-void LocationBarViewGtk::OnPopupBoundsChanged(const gfx::Rect& bounds) {
-  InstantController* instant = browser_->instant();
-  if (instant)
-    instant->SetOmniboxBounds(bounds);
-}
-
-void LocationBarViewGtk::OnAutocompleteAccept(const GURL& url,
-    WindowOpenDisposition disposition,
-    PageTransition::Type transition,
-    const GURL& alternate_nav_url) {
-  if (url.is_valid()) {
-    location_input_ = UTF8ToWide(url.spec());
-    disposition_ = disposition;
-    transition_ = transition;
-
-    if (command_updater_) {
-      if (!alternate_nav_url.is_valid()) {
-        command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
-      } else {
-        AlternateNavURLFetcher* fetcher =
-            new AlternateNavURLFetcher(alternate_nav_url);
-        // The AlternateNavURLFetcher will listen for the pending navigation
-        // notification that will be issued as a result of the "open URL." It
-        // will automatically install itself into that navigation controller.
-        command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
-        if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
-          // I'm not sure this should be reachable, but I'm not also sure enough
-          // that it shouldn't to stick in a NOTREACHED().  In any case, this is
-          // harmless.
-          delete fetcher;
-        } else {
-          // The navigation controller will delete the fetcher.
-        }
-      }
-    }
-  }
-
-  if (browser_->instant() && !location_entry_->model()->popup_model()->IsOpen())
-    browser_->instant()->DestroyPreviewContents();
-
-  update_instant_ = true;
-}
-
-void LocationBarViewGtk::OnChanged() {
-  UpdateSiteTypeArea();
-
-  const std::wstring keyword(location_entry_->model()->keyword());
-  const bool is_keyword_hint = location_entry_->model()->is_keyword_hint();
-  show_selected_keyword_ = !keyword.empty() && !is_keyword_hint;
-  show_keyword_hint_ = !keyword.empty() && is_keyword_hint;
-
-  if (show_selected_keyword_)
-    SetKeywordLabel(keyword);
-
-  if (show_keyword_hint_)
-    SetKeywordHintLabel(keyword);
-
-  AdjustChildrenVisibility();
-
-  InstantController* instant = browser_->instant();
-  string16 suggested_text;
-  if (update_instant_ && instant && GetTabContents()) {
-    if (location_entry_->model()->user_input_in_progress() &&
-        location_entry_->model()->popup_model()->IsOpen()) {
-      instant->Update(
-          browser_->GetSelectedTabContentsWrapper(),
-          location_entry_->model()->CurrentMatch(),
-          WideToUTF16(location_entry_->GetText()),
-          location_entry_->model()->UseVerbatimInstant(),
-          &suggested_text);
-      if (!instant->MightSupportInstant()) {
-        location_entry_->model()->FinalizeInstantQuery(std::wstring(),
-                                                       std::wstring());
-      }
-    } else {
-      instant->DestroyPreviewContents();
-      location_entry_->model()->FinalizeInstantQuery(std::wstring(),
-                                                     std::wstring());
-    }
-  }
-
-  SetSuggestedText(suggested_text);
-}
-
-void LocationBarViewGtk::OnSelectionBoundsChanged() {
-  NOTIMPLEMENTED();
-}
-
-void LocationBarViewGtk::CreateStarButton() {
-  star_image_ = gtk_image_new();
-
-  GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
-                            0, kStarRightPadding);
-  gtk_container_add(GTK_CONTAINER(alignment), star_image_);
-
-  star_.Own(gtk_event_box_new());
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(star_.get()), FALSE);
-  gtk_container_add(GTK_CONTAINER(star_.get()), alignment);
-  gtk_widget_show_all(star_.get());
-  ViewIDUtil::SetID(star_.get(), VIEW_ID_STAR_BUTTON);
-
-  gtk_widget_set_tooltip_text(star_.get(),
-      l10n_util::GetStringUTF8(IDS_TOOLTIP_STAR).c_str());
-  g_signal_connect(star_.get(), "button-press-event",
-                   G_CALLBACK(OnStarButtonPressThunk), this);
-}
-
-void LocationBarViewGtk::OnInputInProgress(bool in_progress) {
-  // This is identical to the Windows code, except that we don't proxy the call
-  // back through the Toolbar, and just access the model here.
-  // The edit should make sure we're only notified when something changes.
-  DCHECK(toolbar_model_->input_in_progress() != in_progress);
-
-  toolbar_model_->set_input_in_progress(in_progress);
-  Update(NULL);
-}
-
-void LocationBarViewGtk::OnKillFocus() {
-}
-
-void LocationBarViewGtk::OnSetFocus() {
-  AccessibilityTextBoxInfo info(
-      profile_,
-      l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION).c_str(),
-      false);
-  NotificationService::current()->Notify(
-      NotificationType::ACCESSIBILITY_CONTROL_FOCUSED,
-      Source<Profile>(profile_),
-      Details<AccessibilityTextBoxInfo>(&info));
-
-  // Update the keyword and search hint states.
-  OnChanged();
-}
-
-SkBitmap LocationBarViewGtk::GetFavIcon() const {
-  return GetTabContents()->GetFavIcon();
-}
-
-std::wstring LocationBarViewGtk::GetTitle() const {
-  return UTF16ToWideHack(GetTabContents()->GetTitle());
-}
-
-void LocationBarViewGtk::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {
-  // We need the browser window to be shown before we can show the bubble, but
-  // we get called before that's happened.
-  Task* task = first_run_bubble_.NewRunnableMethod(
-      &LocationBarViewGtk::ShowFirstRunBubbleInternal, bubble_type);
-  MessageLoop::current()->PostTask(FROM_HERE, task);
-}
-
-void LocationBarViewGtk::SetSuggestedText(const string16& text) {
-  location_entry_->SetInstantSuggestion(UTF16ToUTF8(text));
-}
-
-std::wstring LocationBarViewGtk::GetInputString() const {
-  return location_input_;
-}
-
-WindowOpenDisposition LocationBarViewGtk::GetWindowOpenDisposition() const {
-  return disposition_;
-}
-
-PageTransition::Type LocationBarViewGtk::GetPageTransition() const {
-  return transition_;
-}
-
-void LocationBarViewGtk::AcceptInput() {
-  location_entry_->model()->AcceptInput(CURRENT_TAB, false);
-}
-
-void LocationBarViewGtk::FocusLocation(bool select_all) {
-  location_entry_->SetFocus();
-  if (select_all)
-    location_entry_->SelectAll(true);
-}
-
-void LocationBarViewGtk::FocusSearch() {
-  location_entry_->SetFocus();
-  location_entry_->SetForcedQuery();
-}
-
-void LocationBarViewGtk::UpdateContentSettingsIcons() {
-  TabContents* tab_contents = GetTabContents();
-  bool any_visible = false;
-  for (ScopedVector<ContentSettingImageViewGtk>::iterator i(
-           content_setting_views_.begin());
-       i != content_setting_views_.end(); ++i) {
-    (*i)->UpdateFromTabContents(
-        toolbar_model_->input_in_progress() ? NULL : tab_contents);
-    any_visible = (*i)->IsVisible() || any_visible;
-  }
-
-  // If there are no visible content things, hide the top level box so it
-  // doesn't mess with padding.
-  if (any_visible)
-    gtk_widget_show(content_setting_hbox_.get());
-  else
-    gtk_widget_hide(content_setting_hbox_.get());
-}
-
-void LocationBarViewGtk::UpdatePageActions() {
-  std::vector<ExtensionAction*> page_actions;
-  ExtensionService* service = profile_->GetExtensionService();
-  if (!service)
-    return;
-
-  // Find all the page actions.
-  for (size_t i = 0; i < service->extensions()->size(); ++i) {
-    if (service->extensions()->at(i)->page_action())
-      page_actions.push_back(service->extensions()->at(i)->page_action());
-  }
-
-  // Initialize on the first call, or re-inialize if more extensions have been
-  // loaded or added after startup.
-  if (page_actions.size() != page_action_views_.size()) {
-    page_action_views_.reset();  // Delete the old views (if any).
-
-    for (size_t i = 0; i < page_actions.size(); ++i) {
-      page_action_views_.push_back(
-          new PageActionViewGtk(this, profile_, page_actions[i]));
-      gtk_box_pack_end(GTK_BOX(page_action_hbox_.get()),
-                       page_action_views_[i]->widget(), FALSE, FALSE, 0);
-    }
-    NotificationService::current()->Notify(
-        NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
-        Source<LocationBar>(this),
-        NotificationService::NoDetails());
-  }
-
-  TabContents* contents = GetTabContents();
-  if (!page_action_views_.empty() && contents) {
-    GURL url = GURL(WideToUTF8(toolbar_model_->GetText()));
-
-    for (size_t i = 0; i < page_action_views_.size(); i++) {
-      page_action_views_[i]->UpdateVisibility(
-          toolbar_model_->input_in_progress() ? NULL : contents, url);
-    }
-  }
-
-  // If there are no visible page actions, hide the hbox too, so that it does
-  // not affect the padding in the location bar.
-  if (PageActionVisibleCount() && !ShouldOnlyShowLocation())
-    gtk_widget_show(page_action_hbox_.get());
-  else
-    gtk_widget_hide(page_action_hbox_.get());
-}
-
-void LocationBarViewGtk::InvalidatePageActions() {
-  size_t count_before = page_action_views_.size();
-  page_action_views_.reset();
-  if (page_action_views_.size() != count_before) {
-    NotificationService::current()->Notify(
-        NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
-        Source<LocationBar>(this),
-        NotificationService::NoDetails());
-  }
-}
-
-void LocationBarViewGtk::SaveStateToContents(TabContents* contents) {
-  location_entry_->SaveStateToTab(contents);
-}
-
-void LocationBarViewGtk::Revert() {
-  location_entry_->RevertAll();
-}
-
-const AutocompleteEditView* LocationBarViewGtk::location_entry() const {
-  return location_entry_.get();
-}
-
-AutocompleteEditView* LocationBarViewGtk::location_entry() {
-  return location_entry_.get();
-}
-
-LocationBarTesting* LocationBarViewGtk::GetLocationBarForTesting() {
-  return this;
-}
-
-int LocationBarViewGtk::PageActionCount() {
-  return page_action_views_.size();
-}
-
-int LocationBarViewGtk::PageActionVisibleCount() {
-  int count = 0;
-  gtk_container_foreach(GTK_CONTAINER(page_action_hbox_.get()),
-                        CountVisibleWidgets, &count);
-  return count;
-}
-
-ExtensionAction* LocationBarViewGtk::GetPageAction(size_t index) {
-  if (index >= page_action_views_.size()) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return page_action_views_[index]->page_action();
-}
-
-ExtensionAction* LocationBarViewGtk::GetVisiblePageAction(size_t index) {
-  size_t visible_index = 0;
-  for (size_t i = 0; i < page_action_views_.size(); ++i) {
-    if (page_action_views_[i]->IsVisible()) {
-      if (index == visible_index++)
-        return page_action_views_[i]->page_action();
-    }
-  }
-
-  NOTREACHED();
-  return NULL;
-}
-
-void LocationBarViewGtk::TestPageActionPressed(size_t index) {
-  if (index >= page_action_views_.size()) {
-    NOTREACHED();
-    return;
-  }
-
-  page_action_views_[index]->TestActivatePageAction();
-}
-
-void LocationBarViewGtk::Observe(NotificationType type,
-                                 const NotificationSource& source,
-                                 const NotificationDetails& details) {
-  DCHECK_EQ(type.value,  NotificationType::BROWSER_THEME_CHANGED);
-
-  if (theme_provider_->UseGtkTheme()) {
-    gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL, NULL);
-
-    GdkColor border_color = theme_provider_->GetGdkColor(
-        BrowserThemeProvider::COLOR_FRAME);
-    gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_, border_color);
-
-    gtk_util::SetLabelColor(tab_to_search_full_label_, NULL);
-    gtk_util::SetLabelColor(tab_to_search_partial_label_, NULL);
-    gtk_util::SetLabelColor(tab_to_search_hint_leading_label_, NULL);
-    gtk_util::SetLabelColor(tab_to_search_hint_trailing_label_, NULL);
-
-    gtk_util::UndoForceFontSize(security_info_label_);
-    gtk_util::UndoForceFontSize(tab_to_search_full_label_);
-    gtk_util::UndoForceFontSize(tab_to_search_partial_label_);
-    gtk_util::UndoForceFontSize(tab_to_search_hint_leading_label_);
-    gtk_util::UndoForceFontSize(tab_to_search_hint_trailing_label_);
-
-    gtk_alignment_set_padding(GTK_ALIGNMENT(location_entry_alignment_),
-                              0, 0, 0, 0);
-  } else {
-    gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL,
-                         &kKeywordBackgroundColor);
-    gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_,
-                                          kKeywordBorderColor);
-
-    gtk_util::SetLabelColor(tab_to_search_full_label_, &gtk_util::kGdkBlack);
-    gtk_util::SetLabelColor(tab_to_search_partial_label_, &gtk_util::kGdkBlack);
-    gtk_util::SetLabelColor(tab_to_search_hint_leading_label_,
-                            &kHintTextColor);
-    gtk_util::SetLabelColor(tab_to_search_hint_trailing_label_,
-                            &kHintTextColor);
-
-    // Until we switch to vector graphics, force the font size of labels.
-    // 12.1px = 9pt @ 96dpi
-    gtk_util::ForceFontSizePixels(security_info_label_, 12.1);
-    gtk_util::ForceFontSizePixels(tab_to_search_full_label_,
-        browser_defaults::kAutocompleteEditFontPixelSize);
-    gtk_util::ForceFontSizePixels(tab_to_search_partial_label_,
-        browser_defaults::kAutocompleteEditFontPixelSize);
-    gtk_util::ForceFontSizePixels(tab_to_search_hint_leading_label_,
-        browser_defaults::kAutocompleteEditFontPixelSize);
-    gtk_util::ForceFontSizePixels(tab_to_search_hint_trailing_label_,
-        browser_defaults::kAutocompleteEditFontPixelSize);
-
-    if (popup_window_mode_) {
-      gtk_alignment_set_padding(GTK_ALIGNMENT(location_entry_alignment_),
-                                kTopMargin + kBorderThickness,
-                                kBottomMargin + kBorderThickness,
-                                kBorderThickness,
-                                kBorderThickness);
-    } else {
-      gtk_alignment_set_padding(GTK_ALIGNMENT(location_entry_alignment_),
-                                kTopMargin + kBorderThickness,
-                                kBottomMargin + kBorderThickness,
-                                0, 0);
-    }
-  }
-
-  UpdateStarIcon();
-  UpdateSiteTypeArea();
-  UpdateContentSettingsIcons();
-}
-
-gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
-                                          GdkEventExpose* event) {
-  // If we're not using GTK theming, draw our own border over the edge pixels
-  // of the background.
-  if (!profile_ ||
-      !GtkThemeProvider::GetFrom(profile_)->UseGtkTheme()) {
-    int left, center, right;
-    if (popup_window_mode_) {
-      left = right = IDR_LOCATIONBG_POPUPMODE_EDGE;
-      center = IDR_LOCATIONBG_POPUPMODE_CENTER;
-    } else {
-      left = IDR_LOCATIONBG_L;
-      center = IDR_LOCATIONBG_C;
-      right = IDR_LOCATIONBG_R;
-    }
-
-    NineBox background(left, center, right,
-                       0, 0, 0, 0, 0, 0);
-    background.RenderToWidget(widget);
-  }
-
-  return FALSE;  // Continue propagating the expose.
-}
-
-void LocationBarViewGtk::UpdateSiteTypeArea() {
-  // The icon is always visible except when the |tab_to_search_box_| is visible.
-  if (!location_entry_->model()->keyword().empty() &&
-      !location_entry_->model()->is_keyword_hint()) {
-    gtk_widget_hide(site_type_area());
-    return;
-  }
-
-  int resource_id = location_entry_->GetIcon();
-  gtk_image_set_from_pixbuf(GTK_IMAGE(location_icon_image_),
-                            theme_provider_->GetPixbufNamed(resource_id));
-
-  if (toolbar_model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
-    if (!gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) {
-      // Fun fact: If wee try to make |site_type_event_box_| act as a
-      // rounded window while it doesn't have a visible window, GTK interprets
-      // this as a sign that it should paint the skyline texture into the
-      // omnibox.
-      gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
-                                       TRUE);
-
-      gtk_util::ActAsRoundedWindow(site_type_event_box_,
-                                   kEvSecureBorderColor,
-                                   kCornerSize,
-                                   gtk_util::ROUNDED_ALL,
-                                   gtk_util::BORDER_ALL);
-    }
-
-    std::wstring info_text = toolbar_model_->GetEVCertName();
-    gtk_label_set_text(GTK_LABEL(security_info_label_),
-                       WideToUTF8(info_text).c_str());
-
-    UpdateEVCertificateLabelSize();
-
-    gtk_widget_show(GTK_WIDGET(security_info_label_));
-  } else {
-    if (gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) {
-      gtk_util::StopActingAsRoundedWindow(site_type_event_box_);
-
-      gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
-                                       FALSE);
-    }
-
-    gtk_widget_hide(GTK_WIDGET(security_info_label_));
-  }
-
-  gtk_widget_show(site_type_area());
-
-  SetSiteTypeDragSource();
-}
-
-void LocationBarViewGtk::UpdateEVCertificateLabelSize() {
-  // Figure out the width of the average character.
-  PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(security_info_label_));
-  PangoContext* context = pango_layout_get_context(layout);
-  PangoFontMetrics* metrics = pango_context_get_metrics(
-      context,
-      gtk_widget_get_style(security_info_label_)->font_desc,
-      pango_context_get_language(context));
-  int char_width =
-      pango_font_metrics_get_approximate_char_width(metrics) / PANGO_SCALE;
-
-  // The EV label should never take up more than half the hbox. We try to
-  // correct our inaccurate measurement units ("the average character width")
-  // by dividing more than an even 2.
-  int text_area = security_info_label_->allocation.width +
-                  entry_box_->allocation.width;
-  int max_chars = static_cast<int>(static_cast<float>(text_area) /
-                                   static_cast<float>(char_width) / 2.75);
-  // Don't let the label be smaller than 10 characters so that the country
-  // code is always visible.
-  gtk_label_set_max_width_chars(GTK_LABEL(security_info_label_),
-                                std::max(10, max_chars));
-
-  pango_font_metrics_unref(metrics);
-}
-
-void LocationBarViewGtk::SetKeywordLabel(const std::wstring& keyword) {
-  if (keyword.empty())
-    return;
-
-  DCHECK(profile_);
-  if (!profile_->GetTemplateURLModel())
-    return;
-
-  bool is_extension_keyword;
-  const std::wstring short_name = profile_->GetTemplateURLModel()->
-      GetKeywordShortName(keyword, &is_extension_keyword);
-  int message_id = is_extension_keyword ?
-      IDS_OMNIBOX_EXTENSION_KEYWORD_TEXT : IDS_OMNIBOX_KEYWORD_TEXT;
-  string16 full_name = l10n_util::GetStringFUTF16(message_id,
-                                                  WideToUTF16Hack(short_name));
-  string16 partial_name = l10n_util::GetStringFUTF16(
-      message_id,
-      WideToUTF16Hack(location_bar_util::CalculateMinString(short_name)));
-  gtk_label_set_text(GTK_LABEL(tab_to_search_full_label_),
-                     UTF16ToUTF8(full_name).c_str());
-  gtk_label_set_text(GTK_LABEL(tab_to_search_partial_label_),
-                     UTF16ToUTF8(partial_name).c_str());
-
-  if (last_keyword_ != keyword) {
-    last_keyword_ = keyword;
-
-    if (is_extension_keyword) {
-      const TemplateURL* template_url =
-          profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
-      const SkBitmap& bitmap = profile_->GetExtensionService()->
-          GetOmniboxIcon(template_url->GetExtensionId());
-      GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
-      gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_), pixbuf);
-      g_object_unref(pixbuf);
-    } else {
-      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-      gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_),
-                                rb.GetPixbufNamed(IDR_OMNIBOX_SEARCH));
-    }
-  }
-}
-
-void LocationBarViewGtk::SetKeywordHintLabel(const std::wstring& keyword) {
-  if (keyword.empty())
-    return;
-
-  DCHECK(profile_);
-  if (!profile_->GetTemplateURLModel())
-    return;
-
-  bool is_extension_keyword;
-  const std::wstring short_name = profile_->GetTemplateURLModel()->
-      GetKeywordShortName(keyword, &is_extension_keyword);
-  int message_id = is_extension_keyword ?
-      IDS_OMNIBOX_EXTENSION_KEYWORD_HINT : IDS_OMNIBOX_KEYWORD_HINT;
-  std::vector<size_t> content_param_offsets;
-  const string16 keyword_hint = l10n_util::GetStringFUTF16(
-      message_id,
-      string16(),
-      WideToUTF16Hack(short_name),
-      &content_param_offsets);
-  if (content_param_offsets.size() != 2) {
-    // See comments on an identical NOTREACHED() in search_provider.cc.
-    NOTREACHED();
-    return;
-  }
-
-  std::string leading(UTF16ToUTF8(
-      keyword_hint.substr(0, content_param_offsets.front())));
-  std::string trailing(UTF16ToUTF8(
-      keyword_hint.substr(content_param_offsets.front())));
-  gtk_label_set_text(GTK_LABEL(tab_to_search_hint_leading_label_),
-                     leading.c_str());
-  gtk_label_set_text(GTK_LABEL(tab_to_search_hint_trailing_label_),
-                     trailing.c_str());
-}
-
-void LocationBarViewGtk::ShowFirstRunBubbleInternal(
-    FirstRun::BubbleType bubble_type) {
-  if (!location_entry_.get() || !widget()->window)
-    return;
-
-  GtkWidget* anchor = location_entry_->GetNativeView();
-
-  // The bubble needs to be just below the Omnibox and slightly to the right
-  // of star button, so shift x and y co-ordinates.
-  int y_offset = anchor->allocation.height + kFirstRunBubbleTopMargin;
-  int x_offset = 0;
-  if (!base::i18n::IsRTL())
-    x_offset = kFirstRunBubbleLeftMargin;
-  else
-    x_offset = anchor->allocation.width - kFirstRunBubbleLeftMargin;
-  gfx::Rect rect(x_offset, y_offset, 0, 0);
-
-  FirstRunBubble::Show(profile_, anchor, rect, bubble_type);
-}
-
-gboolean LocationBarViewGtk::OnIconReleased(GtkWidget* sender,
-                                            GdkEventButton* event) {
-  TabContents* tab = GetTabContents();
-
-  if (event->button == 1) {
-    // Do not show page info if the user has been editing the location
-    // bar, or the location bar is at the NTP.
-    if (location_entry()->IsEditingOrEmpty())
-      return FALSE;
-
-    // (0,0) event coordinates indicates that the release came at the end of
-    // a drag.
-    if (event->x == 0 && event->y == 0)
-      return FALSE;
-
-    NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
-    if (!nav_entry) {
-      NOTREACHED();
-      return FALSE;
-    }
-    tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
-    return TRUE;
-  } else if (event->button == 2) {
-    // When the user middle clicks on the location icon, try to open the
-    // contents of the PRIMARY selection in the current tab.
-    // If the click was outside our bounds, do nothing.
-    if (!gtk_util::WidgetBounds(sender).Contains(
-            gfx::Point(event->x, event->y))) {
-      return FALSE;
-    }
-
-    GURL url;
-    if (!gtk_util::URLFromPrimarySelection(profile_, &url))
-      return FALSE;
-
-    tab->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-void LocationBarViewGtk::OnIconDragData(GtkWidget* sender,
-                                        GdkDragContext* context,
-                                        GtkSelectionData* data,
-                                        guint info, guint time) {
-  TabContents* tab = GetTabContents();
-  if (!tab)
-    return;
-  gtk_dnd_util::WriteURLWithName(data, tab->GetURL(), tab->GetTitle(), info);
-}
-
-void LocationBarViewGtk::OnIconDragBegin(GtkWidget* sender,
-                                         GdkDragContext* context) {
-  SkBitmap favicon = GetFavIcon();
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&favicon);
-  if (!pixbuf)
-    return;
-  drag_icon_ = bookmark_utils::GetDragRepresentation(pixbuf,
-      WideToUTF16(GetTitle()), theme_provider_);
-  g_object_unref(pixbuf);
-  gtk_drag_set_icon_widget(context, drag_icon_, 0, 0);
-}
-
-void LocationBarViewGtk::OnIconDragEnd(GtkWidget* sender,
-                                       GdkDragContext* context) {
-  DCHECK(drag_icon_);
-  gtk_widget_destroy(drag_icon_);
-  drag_icon_ = NULL;
-}
-
-void LocationBarViewGtk::OnHboxSizeAllocate(GtkWidget* sender,
-                                            GtkAllocation* allocation) {
-  if (hbox_width_ != allocation->width) {
-    hbox_width_ = allocation->width;
-    UpdateEVCertificateLabelSize();
-  }
-}
-
-void LocationBarViewGtk::OnEntryBoxSizeAllocate(GtkWidget* sender,
-                                                GtkAllocation* allocation) {
-  if (entry_box_width_ != allocation->width) {
-    entry_box_width_ = allocation->width;
-    AdjustChildrenVisibility();
-  }
-}
-
-gboolean LocationBarViewGtk::OnStarButtonPress(GtkWidget* widget,
-                                               GdkEventButton* event) {
-  browser_->ExecuteCommand(IDC_BOOKMARK_PAGE);
-  return FALSE;
-}
-
-void LocationBarViewGtk::ShowStarBubble(const GURL& url,
-                                        bool newly_bookmarked) {
-  if (!star_.get())
-    return;
-
-  BookmarkBubbleGtk::Show(star_.get(), profile_, url, newly_bookmarked);
-}
-
-void LocationBarViewGtk::SetStarred(bool starred) {
-  if (starred == starred_)
-    return;
-
-  starred_ = starred;
-  UpdateStarIcon();
-}
-
-void LocationBarViewGtk::UpdateStarIcon() {
-  if (!star_.get())
-    return;
-
-  gtk_image_set_from_pixbuf(GTK_IMAGE(star_image_),
-      theme_provider_->GetPixbufNamed(
-          starred_ ? IDR_STAR_LIT : IDR_STAR));
-}
-
-bool LocationBarViewGtk::ShouldOnlyShowLocation() {
-  return browser_->type() != Browser::TYPE_NORMAL;
-}
-
-void LocationBarViewGtk::AdjustChildrenVisibility() {
-  int text_width = location_entry_->TextWidth();
-  int available_width = entry_box_width_ - text_width - kInnerPadding;
-
-  // Only one of |tab_to_search_box_| and |tab_to_search_hint_| can be visible
-  // at the same time.
-  if (!show_selected_keyword_ && GTK_WIDGET_VISIBLE(tab_to_search_box_)) {
-    gtk_widget_hide(tab_to_search_box_);
-  } else if (!show_keyword_hint_ && GTK_WIDGET_VISIBLE(tab_to_search_hint_)) {
-    gtk_widget_hide(tab_to_search_hint_);
-    location_entry_->set_enable_tab_to_search(false);
-  }
-
-  if (show_selected_keyword_) {
-    GtkRequisition box, full_label, partial_label;
-    gtk_widget_size_request(tab_to_search_box_, &box);
-    gtk_widget_size_request(tab_to_search_full_label_, &full_label);
-    gtk_widget_size_request(tab_to_search_partial_label_, &partial_label);
-    int full_partial_width_diff = full_label.width - partial_label.width;
-    int full_box_width;
-    int partial_box_width;
-    if (GTK_WIDGET_VISIBLE(tab_to_search_full_label_)) {
-      full_box_width = box.width;
-      partial_box_width = full_box_width - full_partial_width_diff;
-    } else {
-      partial_box_width = box.width;
-      full_box_width = partial_box_width + full_partial_width_diff;
-    }
-
-    if (partial_box_width >= entry_box_width_ - kInnerPadding) {
-      gtk_widget_hide(tab_to_search_box_);
-    } else if (full_box_width >= available_width) {
-      gtk_widget_hide(tab_to_search_full_label_);
-      gtk_widget_show(tab_to_search_partial_label_);
-      gtk_widget_show(tab_to_search_box_);
-    } else if (full_box_width < available_width) {
-      gtk_widget_hide(tab_to_search_partial_label_);
-      gtk_widget_show(tab_to_search_full_label_);
-      gtk_widget_show(tab_to_search_box_);
-    }
-  } else if (show_keyword_hint_) {
-    GtkRequisition leading, icon, trailing;
-    gtk_widget_size_request(tab_to_search_hint_leading_label_, &leading);
-    gtk_widget_size_request(tab_to_search_hint_icon_, &icon);
-    gtk_widget_size_request(tab_to_search_hint_trailing_label_, &trailing);
-    int full_width = leading.width + icon.width + trailing.width;
-
-    if (icon.width >= entry_box_width_ - kInnerPadding) {
-      gtk_widget_hide(tab_to_search_hint_);
-      location_entry_->set_enable_tab_to_search(false);
-    } else if (full_width >= available_width) {
-      gtk_widget_hide(tab_to_search_hint_leading_label_);
-      gtk_widget_hide(tab_to_search_hint_trailing_label_);
-      gtk_widget_show(tab_to_search_hint_);
-      location_entry_->set_enable_tab_to_search(true);
-    } else if (full_width < available_width) {
-      gtk_widget_show(tab_to_search_hint_leading_label_);
-      gtk_widget_show(tab_to_search_hint_trailing_label_);
-      gtk_widget_show(tab_to_search_hint_);
-      location_entry_->set_enable_tab_to_search(true);
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// LocationBarViewGtk::ContentSettingImageViewGtk
-LocationBarViewGtk::ContentSettingImageViewGtk::ContentSettingImageViewGtk(
-    ContentSettingsType content_type,
-    const LocationBarViewGtk* parent,
-    Profile* profile)
-    : content_setting_image_model_(
-          ContentSettingImageModel::CreateContentSettingImageModel(
-              content_type)),
-      parent_(parent),
-      profile_(profile),
-      info_bubble_(NULL) {
-  event_box_.Own(gtk_event_box_new());
-
-  // Make the event box not visible so it does not paint a background.
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
-  g_signal_connect(event_box_.get(), "button-press-event",
-                   G_CALLBACK(&OnButtonPressedThunk), this);
-
-  image_.Own(gtk_image_new());
-  gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get());
-  gtk_widget_hide(widget());
-}
-
-LocationBarViewGtk::ContentSettingImageViewGtk::~ContentSettingImageViewGtk() {
-  image_.Destroy();
-  event_box_.Destroy();
-
-  if (info_bubble_)
-    info_bubble_->Close();
-}
-
-void LocationBarViewGtk::ContentSettingImageViewGtk::UpdateFromTabContents(
-    TabContents* tab_contents) {
-  content_setting_image_model_->UpdateFromTabContents(tab_contents);
-  if (content_setting_image_model_->is_visible()) {
-    gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
-          GtkThemeProvider::GetFrom(profile_)->GetPixbufNamed(
-              content_setting_image_model_->get_icon()));
-
-    gtk_widget_set_tooltip_text(widget(),
-        content_setting_image_model_->get_tooltip().c_str());
-    gtk_widget_show(widget());
-  } else {
-    gtk_widget_hide(widget());
-  }
-}
-
-gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnButtonPressed(
-    GtkWidget* sender, GdkEvent* event) {
-  TabContents* tab_contents = parent_->GetTabContents();
-  if (!tab_contents)
-    return true;
-  GURL url = tab_contents->GetURL();
-  std::wstring display_host;
-  net::AppendFormattedHost(url,
-      UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
-      &display_host,
-      NULL, NULL);
-
-  info_bubble_ = new ContentSettingBubbleGtk(
-      sender, this,
-      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
-          tab_contents, profile_,
-          content_setting_image_model_->get_content_settings_type()),
-      profile_, tab_contents);
-  return TRUE;
-}
-
-void LocationBarViewGtk::ContentSettingImageViewGtk::InfoBubbleClosing(
-    InfoBubbleGtk* info_bubble,
-    bool closed_by_escape) {
-  info_bubble_ = NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// LocationBarViewGtk::PageActionViewGtk
-
-LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk(
-    LocationBarViewGtk* owner, Profile* profile,
-    ExtensionAction* page_action)
-    : owner_(NULL),
-      profile_(profile),
-      page_action_(page_action),
-      last_icon_pixbuf_(NULL),
-      tracker_(this),
-      preview_enabled_(false) {
-  event_box_.Own(gtk_event_box_new());
-  gtk_widget_set_size_request(event_box_.get(),
-                              Extension::kPageActionIconMaxSize,
-                              Extension::kPageActionIconMaxSize);
-
-  // Make the event box not visible so it does not paint a background.
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
-  g_signal_connect(event_box_.get(), "button-press-event",
-                   G_CALLBACK(&OnButtonPressedThunk), this);
-  g_signal_connect_after(event_box_.get(), "expose-event",
-                         G_CALLBACK(OnExposeEventThunk), this);
-
-  image_.Own(gtk_image_new());
-  gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get());
-
-  const Extension* extension = profile->GetExtensionService()->
-      GetExtensionById(page_action->extension_id(), false);
-  DCHECK(extension);
-
-  // Load all the icons declared in the manifest. This is the contents of the
-  // icons array, plus the default_icon property, if any.
-  std::vector<std::string> icon_paths(*page_action->icon_paths());
-  if (!page_action_->default_icon_path().empty())
-    icon_paths.push_back(page_action_->default_icon_path());
-
-  for (std::vector<std::string>::iterator iter = icon_paths.begin();
-       iter != icon_paths.end(); ++iter) {
-    tracker_.LoadImage(extension, extension->GetResource(*iter),
-                       gfx::Size(Extension::kPageActionIconMaxSize,
-                                 Extension::kPageActionIconMaxSize),
-                       ImageLoadingTracker::DONT_CACHE);
-  }
-
-  // We set the owner last of all so that we can determine whether we are in
-  // the process of initializing this class or not.
-  owner_ = owner;
-}
-
-LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() {
-  image_.Destroy();
-  event_box_.Destroy();
-  for (PixbufMap::iterator iter = pixbufs_.begin(); iter != pixbufs_.end();
-       ++iter) {
-    g_object_unref(iter->second);
-  }
-  if (last_icon_pixbuf_)
-    g_object_unref(last_icon_pixbuf_);
-}
-
-void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility(
-    TabContents* contents, GURL url) {
-  // Save this off so we can pass it back to the extension when the action gets
-  // executed. See PageActionImageView::OnMousePressed.
-  current_tab_id_ = contents ? ExtensionTabUtil::GetTabId(contents) : -1;
-  current_url_ = url;
-
-  bool visible = contents &&
-      (preview_enabled_ || page_action_->GetIsVisible(current_tab_id_));
-  if (visible) {
-    // Set the tooltip.
-    gtk_widget_set_tooltip_text(event_box_.get(),
-        page_action_->GetTitle(current_tab_id_).c_str());
-
-    // Set the image.
-    // It can come from three places. In descending order of priority:
-    // - The developer can set it dynamically by path or bitmap. It will be in
-    //   page_action_->GetIcon().
-    // - The developer can set it dyanmically by index. It will be in
-    //   page_action_->GetIconIndex().
-    // - It can be set in the manifest by path. It will be in page_action_->
-    //   default_icon_path().
-
-    // First look for a dynamically set bitmap.
-    SkBitmap icon = page_action_->GetIcon(current_tab_id_);
-    GdkPixbuf* pixbuf = NULL;
-    if (!icon.isNull()) {
-      if (icon.pixelRef() != last_icon_skbitmap_.pixelRef()) {
-        if (last_icon_pixbuf_)
-          g_object_unref(last_icon_pixbuf_);
-        last_icon_skbitmap_ = icon;
-        last_icon_pixbuf_ = gfx::GdkPixbufFromSkBitmap(&icon);
-      }
-      DCHECK(last_icon_pixbuf_);
-      pixbuf = last_icon_pixbuf_;
-    } else {
-      // Otherwise look for a dynamically set index, or fall back to the
-      // default path.
-      int icon_index = page_action_->GetIconIndex(current_tab_id_);
-      std::string icon_path = (icon_index < 0) ?
-          page_action_->default_icon_path() :
-          page_action_->icon_paths()->at(icon_index);
-      if (!icon_path.empty()) {
-        PixbufMap::iterator iter = pixbufs_.find(icon_path);
-        if (iter != pixbufs_.end())
-          pixbuf = iter->second;
-      }
-    }
-    // The pixbuf might not be loaded yet.
-    if (pixbuf)
-      gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()), pixbuf);
-  }
-
-  bool old_visible = IsVisible();
-  if (visible)
-    gtk_widget_show_all(event_box_.get());
-  else
-    gtk_widget_hide_all(event_box_.get());
-
-  if (visible != old_visible) {
-    NotificationService::current()->Notify(
-        NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
-        Source<ExtensionAction>(page_action_),
-        Details<TabContents>(contents));
-  }
-}
-
-void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded(
-    SkBitmap* image, ExtensionResource resource, int index) {
-  // We loaded icons()->size() icons, plus one extra if the page action had
-  // a default icon.
-  int total_icons = static_cast<int>(page_action_->icon_paths()->size());
-  if (!page_action_->default_icon_path().empty())
-    total_icons++;
-  DCHECK(index < total_icons);
-
-  // Map the index of the loaded image back to its name. If we ever get an
-  // index greater than the number of icons, it must be the default icon.
-  if (image) {
-    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(image);
-    if (index < static_cast<int>(page_action_->icon_paths()->size()))
-      pixbufs_[page_action_->icon_paths()->at(index)] = pixbuf;
-    else
-      pixbufs_[page_action_->default_icon_path()] = pixbuf;
-  }
-
-  // If we have no owner, that means this class is still being constructed and
-  // we should not UpdatePageActions, since it leads to the PageActions being
-  // destroyed again and new ones recreated (causing an infinite loop).
-  if (owner_)
-    owner_->UpdatePageActions();
-}
-
-void LocationBarViewGtk::PageActionViewGtk::TestActivatePageAction() {
-  GdkEvent event;
-  event.button.button = 1;
-  OnButtonPressed(widget(), &event);
-}
-
-void LocationBarViewGtk::PageActionViewGtk::InspectPopup(
-    ExtensionAction* action) {
-  ShowPopup(true);
-}
-
-bool LocationBarViewGtk::PageActionViewGtk::ShowPopup(bool devtools) {
-  if (!page_action_->HasPopup(current_tab_id_))
-    return false;
-
-  ExtensionPopupGtk::Show(
-      page_action_->GetPopupUrl(current_tab_id_),
-      owner_->browser_,
-      event_box_.get(),
-      devtools);
-  return true;
-}
-
-gboolean LocationBarViewGtk::PageActionViewGtk::OnButtonPressed(
-    GtkWidget* sender,
-    GdkEvent* event) {
-  if (event->button.button != 3) {
-    if (!ShowPopup(false)) {
-      ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
-          profile_,
-          page_action_->extension_id(),
-          page_action_->id(),
-          current_tab_id_,
-          current_url_.spec(),
-          event->button.button);
-    }
-  } else {
-    const Extension* extension = profile_->GetExtensionService()->
-        GetExtensionById(page_action()->extension_id(), false);
-
-    context_menu_model_ =
-        new ExtensionContextMenuModel(extension, owner_->browser_, this);
-    context_menu_.reset(
-        new MenuGtk(NULL, context_menu_model_.get()));
-    context_menu_->Popup(sender, event);
-  }
-
-  return TRUE;
-}
-
-gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent(
-    GtkWidget* widget, GdkEventExpose* event) {
-  TabContents* contents = owner_->GetTabContents();
-  if (!contents)
-    return FALSE;
-
-  int tab_id = ExtensionTabUtil::GetTabId(contents);
-  if (tab_id < 0)
-    return FALSE;
-
-  std::string badge_text = page_action_->GetBadgeText(tab_id);
-  if (badge_text.empty())
-    return FALSE;
-
-  gfx::CanvasSkiaPaint canvas(event, false);
-  gfx::Rect bounding_rect(widget->allocation);
-  page_action_->PaintBadge(&canvas, bounding_rect, tab_id);
-  return FALSE;
-}
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
deleted file mode 100644
index f1b1534..0000000
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_LOCATION_BAR_VIEW_GTK_H_
-#define CHROME_BROWSER_GTK_LOCATION_BAR_VIEW_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <map>
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "base/scoped_vector.h"
-#include "chrome/browser/autocomplete/autocomplete_edit.h"
-#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
-#include "chrome/browser/extensions/extension_context_menu_model.h"
-#include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/ui/omnibox/location_bar.h"
-#include "chrome/common/content_settings_types.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/page_transition_types.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "webkit/glue/window_open_disposition.h"
-
-class AutocompleteEditViewGtk;
-class Browser;
-class CommandUpdater;
-class ContentSettingImageModel;
-class ContentSettingBubbleGtk;
-class ExtensionAction;
-class GtkThemeProvider;
-class Profile;
-class SkBitmap;
-class TabContents;
-class ToolbarModel;
-
-class LocationBarViewGtk : public AutocompleteEditController,
-                           public LocationBar,
-                           public LocationBarTesting,
-                           public NotificationObserver {
- public:
-  explicit LocationBarViewGtk(Browser* browser);
-  virtual ~LocationBarViewGtk();
-
-  void Init(bool popup_window_mode);
-
-  void SetProfile(Profile* profile);
-
-  // Returns the widget the caller should host.  You must call Init() first.
-  GtkWidget* widget() { return hbox_.get(); }
-
-  // Returns the widget the page info bubble should point to.
-  GtkWidget* location_icon_widget() const { return location_icon_image_; }
-
-  // Returns the widget the extension installed bubble should point to.
-  GtkWidget* location_entry_widget() const { return entry_box_; }
-
-  // Returns the current TabContents.
-  TabContents* GetTabContents() const;
-
-  // Sets |preview_enabled| for the PageActionViewGtk associated with this
-  // |page_action|. If |preview_enabled| is true, the view will display the
-  // page action's icon even though it has not been activated by the extension.
-  // This is used by the ExtensionInstalledBubbleGtk to preview what the icon
-  // will look like for the user upon installation of the extension.
-  void SetPreviewEnabledPageAction(ExtensionAction *page_action,
-                                   bool preview_enabled);
-
-  // Retrieves the GtkWidget which is associated with PageActionView
-  // corresponding to |page_action|.
-  GtkWidget* GetPageActionWidget(ExtensionAction* page_action);
-
-  // Updates the location bar.  We also reset the bar's permanent text and
-  // security style, and, if |tab_for_state_restoring| is non-NULL, also
-  // restore saved state that the tab holds.
-  void Update(const TabContents* tab_for_state_restoring);
-
-  // Show the bookmark bubble.
-  void ShowStarBubble(const GURL& url, bool newly_boomkarked);
-
-  // Set the starred state of the bookmark star.
-  void SetStarred(bool starred);
-
-  // Implement the AutocompleteEditController interface.
-  virtual void OnAutocompleteWillClosePopup();
-  virtual void OnAutocompleteLosingFocus(gfx::NativeView view_gaining_focus);
-  virtual void OnAutocompleteWillAccept();
-  // For this implementation, the parameter is ignored.
-  virtual bool OnCommitSuggestedText(const std::wstring& typed_text);
-  virtual bool AcceptCurrentInstantPreview();
-  virtual void OnSetSuggestedSearchText(const string16& suggested_text);
-  virtual void OnPopupBoundsChanged(const gfx::Rect& bounds);
-  virtual void OnAutocompleteAccept(const GURL& url,
-      WindowOpenDisposition disposition,
-      PageTransition::Type transition,
-      const GURL& alternate_nav_url);
-  virtual void OnChanged();
-  virtual void OnSelectionBoundsChanged();
-  virtual void OnKillFocus();
-  virtual void OnSetFocus();
-  virtual void OnInputInProgress(bool in_progress);
-  virtual SkBitmap GetFavIcon() const;
-  virtual std::wstring GetTitle() const;
-
-  // Implement the LocationBar interface.
-  virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type);
-  virtual void SetSuggestedText(const string16& text);
-  virtual std::wstring GetInputString() const;
-  virtual WindowOpenDisposition GetWindowOpenDisposition() const;
-  virtual PageTransition::Type GetPageTransition() const;
-  virtual void AcceptInput();
-  virtual void FocusLocation(bool select_all);
-  virtual void FocusSearch();
-  virtual void UpdateContentSettingsIcons();
-  virtual void UpdatePageActions();
-  virtual void InvalidatePageActions();
-  virtual void SaveStateToContents(TabContents* contents);
-  virtual void Revert();
-  virtual const AutocompleteEditView* location_entry() const;
-  virtual AutocompleteEditView* location_entry();
-  virtual LocationBarTesting* GetLocationBarForTesting();
-
-  // Implement the LocationBarTesting interface.
-  virtual int PageActionCount();
-  virtual int PageActionVisibleCount();
-  virtual ExtensionAction* GetPageAction(size_t index);
-  virtual ExtensionAction* GetVisiblePageAction(size_t index);
-  virtual void TestPageActionPressed(size_t index);
-
-  // Implement the NotificationObserver interface.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Edit background color.
-  static const GdkColor kBackgroundColor;
-
- private:
-  class ContentSettingImageViewGtk : public InfoBubbleGtkDelegate {
-   public:
-    ContentSettingImageViewGtk(ContentSettingsType content_type,
-                               const LocationBarViewGtk* parent,
-                               Profile* profile);
-    virtual ~ContentSettingImageViewGtk();
-
-    GtkWidget* widget() { return event_box_.get(); }
-
-    void set_profile(Profile* profile) { profile_ = profile; }
-
-    bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); }
-    void UpdateFromTabContents(TabContents* tab_contents);
-
-   private:
-    CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnButtonPressed,
-                         GdkEvent*);
-
-    // InfoBubbleDelegate overrides:
-    virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                   bool closed_by_escape);
-
-    scoped_ptr<ContentSettingImageModel> content_setting_image_model_;
-
-    // The widgets for this content settings view.
-    OwnedWidgetGtk event_box_;
-    OwnedWidgetGtk image_;
-
-    // The owning LocationBarViewGtk.
-    const LocationBarViewGtk* parent_;
-
-    // The currently active profile.
-    Profile* profile_;
-
-    // The currently shown info bubble if any.
-    ContentSettingBubbleGtk* info_bubble_;
-
-    DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk);
-  };
-
-  class PageActionViewGtk : public ImageLoadingTracker::Observer,
-                            public ExtensionContextMenuModel::PopupDelegate {
-   public:
-    PageActionViewGtk(
-        LocationBarViewGtk* owner, Profile* profile,
-        ExtensionAction* page_action);
-    virtual ~PageActionViewGtk();
-
-    GtkWidget* widget() { return event_box_.get(); }
-
-    ExtensionAction* page_action() { return page_action_; }
-
-    void set_preview_enabled(bool preview_enabled) {
-      preview_enabled_ = preview_enabled;
-    }
-
-    bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); }
-
-    // Called to notify the PageAction that it should determine whether to be
-    // visible or hidden. |contents| is the TabContents that is active, |url|
-    // is the current page URL.
-    void UpdateVisibility(TabContents* contents, GURL url);
-
-    // A callback from ImageLoadingTracker for when the image has loaded.
-    virtual void OnImageLoaded(
-        SkBitmap* image, ExtensionResource resource, int index);
-
-    // Simulate left mouse click on the page action button.
-    void TestActivatePageAction();
-
-    // Overridden from ExtensionContextMenuModel::PopupDelegate:
-    virtual void InspectPopup(ExtensionAction* action);
-
-   private:
-    // Show the popup for this page action. If |devtools| is true, show it
-    // with a debugger window attached. Returns true if a popup was shown.
-    bool ShowPopup(bool devtools);
-
-    CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed,
-                         GdkEvent*);
-    CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent,
-                         GdkEventExpose*);
-
-    // The location bar view that owns us.
-    LocationBarViewGtk* owner_;
-
-    // The current profile (not owned by us).
-    Profile* profile_;
-
-    // The PageAction that this view represents. The PageAction is not owned by
-    // us, it resides in the extension of this particular profile.
-    ExtensionAction* page_action_;
-
-    // A cache of all the different icon paths associated with this page action.
-    typedef std::map<std::string, GdkPixbuf*> PixbufMap;
-    PixbufMap pixbufs_;
-
-    // A cache of the last dynamically generated bitmap and the pixbuf that
-    // corresponds to it. We keep track of both so we can free old pixbufs as
-    // their icons are replaced.
-    SkBitmap last_icon_skbitmap_;
-    GdkPixbuf* last_icon_pixbuf_;
-
-    // The object that is waiting for the image loading to complete
-    // asynchronously.
-    ImageLoadingTracker tracker_;
-
-    // The widgets for this page action.
-    OwnedWidgetGtk event_box_;
-    OwnedWidgetGtk image_;
-
-    // The tab id we are currently showing the icon for.
-    int current_tab_id_;
-
-    // The URL we are currently showing the icon for.
-    GURL current_url_;
-
-    // This is used for post-install visual feedback. The page_action icon
-    // is briefly shown even if it hasn't been enabled by its extension.
-    bool preview_enabled_;
-
-    // The context menu view and model for this extension action.
-    scoped_ptr<MenuGtk> context_menu_;
-    scoped_refptr<ExtensionContextMenuModel> context_menu_model_;
-
-    DISALLOW_COPY_AND_ASSIGN(PageActionViewGtk);
-  };
-  friend class PageActionViewGtk;
-
-  // Creates, initializes, and packs the location icon, EV certificate name,
-  // and optional border.
-  void BuildSiteTypeArea();
-
-  // Enable or disable the location icon/EV certificate as a drag source for
-  // the URL.
-  void SetSiteTypeDragSource();
-
-  GtkWidget* site_type_area() { return site_type_alignment_; }
-
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, HandleExpose,
-                       GdkEventExpose*);
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnIconReleased,
-                       GdkEventButton*);
-  CHROMEGTK_CALLBACK_4(LocationBarViewGtk, void, OnIconDragData,
-                       GdkDragContext*, GtkSelectionData*, guint, guint);
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragBegin,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragEnd,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnHboxSizeAllocate,
-                       GtkAllocation*);
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnEntryBoxSizeAllocate,
-                       GtkAllocation*);
-  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnStarButtonPress,
-                       GdkEventButton*);
-
-  // Updates the site type area: changes the icon and shows/hides the EV
-  // certificate information.
-  void UpdateSiteTypeArea();
-
-  // Updates the maximum size of the EV certificate label.
-  void UpdateEVCertificateLabelSize();
-
-  // Sets the text that should be displayed in the info label and its associated
-  // tooltip text.  Call with an empty string if the info label should be
-  // hidden.
-  void SetInfoText();
-
-  // Set the keyword text for the Search BLAH: keyword box.
-  void SetKeywordLabel(const std::wstring& keyword);
-
-  // Set the keyword text for the "Press tab to search BLAH" hint box.
-  void SetKeywordHintLabel(const std::wstring& keyword);
-
-  void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type);
-
-  // Show or hide |tab_to_search_box_| and |tab_to_search_hint_| according to
-  // the value of |show_selected_keyword_|, |show_keyword_hint_|, and the
-  // available horizontal space in the location bar.
-  void AdjustChildrenVisibility();
-
-  // Build the star icon.
-  void CreateStarButton();
-
-  // Update the star icon after it is toggled or the theme changes.
-  void UpdateStarIcon();
-
-  // Returns true if we should only show the URL and none of the extras like
-  // the star button or page actions.
-  bool ShouldOnlyShowLocation();
-
-  // The outermost widget we want to be hosted.
-  OwnedWidgetGtk hbox_;
-
-  // Star button.
-  OwnedWidgetGtk star_;
-  GtkWidget* star_image_;
-  bool starred_;
-
-  // An icon to the left of the address bar.
-  GtkWidget* site_type_alignment_;
-  GtkWidget* site_type_event_box_;
-  GtkWidget* location_icon_image_;
-  GtkWidget* drag_icon_;
-  bool enable_location_drag_;
-  // TODO(pkasting): Split this label off and move the rest of the items to the
-  // left of the address bar.
-  GtkWidget* security_info_label_;
-
-  // Content setting icons.
-  OwnedWidgetGtk content_setting_hbox_;
-  ScopedVector<ContentSettingImageViewGtk> content_setting_views_;
-
-  // Extension page action icons.
-  OwnedWidgetGtk page_action_hbox_;
-  ScopedVector<PageActionViewGtk> page_action_views_;
-
-  // The widget that contains our tab hints and the location bar.
-  GtkWidget* entry_box_;
-
-  // Area on the left shown when in tab to search mode.
-  GtkWidget* tab_to_search_box_;
-  GtkWidget* tab_to_search_magnifier_;
-  GtkWidget* tab_to_search_full_label_;
-  GtkWidget* tab_to_search_partial_label_;
-
-  // Hint to user that they can tab-to-search by hitting tab.
-  GtkWidget* tab_to_search_hint_;
-  GtkWidget* tab_to_search_hint_leading_label_;
-  GtkWidget* tab_to_search_hint_icon_;
-  GtkWidget* tab_to_search_hint_trailing_label_;
-
-  scoped_ptr<AutocompleteEditViewGtk> location_entry_;
-
-  // Alignment used to wrap |location_entry_|.
-  GtkWidget* location_entry_alignment_;
-
-  Profile* profile_;
-  CommandUpdater* command_updater_;
-  ToolbarModel* toolbar_model_;
-  Browser* browser_;
-
-  // When we get an OnAutocompleteAccept notification from the autocomplete
-  // edit, we save the input string so we can give it back to the browser on
-  // the LocationBar interface via GetInputString().
-  std::wstring location_input_;
-
-  // The user's desired disposition for how their input should be opened.
-  WindowOpenDisposition disposition_;
-
-  // The transition type to use for the navigation.
-  PageTransition::Type transition_;
-
-  // Used to schedule a task for the first run info bubble.
-  ScopedRunnableMethodFactory<LocationBarViewGtk> first_run_bubble_;
-
-  // When true, the location bar view is read only and also is has a slightly
-  // different presentation (font size / color). This is used for popups.
-  bool popup_window_mode_;
-
-  // Provides colors and rendering mode.
-  GtkThemeProvider* theme_provider_;
-
-  NotificationRegistrar registrar_;
-
-  // Width of the main |hbox_|. Used to properly elide the EV certificate.
-  int hbox_width_;
-
-  // Width of the hbox that holds |tab_to_search_box_|, |location_entry_| and
-  // |tab_to_search_hint_|.
-  int entry_box_width_;
-
-  // Indicate if |tab_to_search_box_| should be shown.
-  bool show_selected_keyword_;
-
-  // Indicate if |tab_to_search_hint_| should be shown.
-  bool show_keyword_hint_;
-
-  // The last search keyword that was shown via the |tab_to_search_box_|.
-  std::wstring last_keyword_;
-
-  // True if we should update the instant controller when the edit text changes.
-  bool update_instant_;
-
-  DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_LOCATION_BAR_VIEW_GTK_H_
diff --git a/chrome/browser/gtk/menu_bar_helper.cc b/chrome/browser/gtk/menu_bar_helper.cc
deleted file mode 100644
index 7d8fa8d..0000000
--- a/chrome/browser/gtk/menu_bar_helper.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/menu_bar_helper.h"
-
-#include <algorithm>
-
-#include "app/gtk_signal_registrar.h"
-#include "base/logging.h"
-#include "chrome/browser/gtk/gtk_util.h"
-
-namespace {
-
-// Recursively find all the GtkMenus that are attached to menu item |child|
-// and add them to |data|, which is a vector of GtkWidgets.
-void PopulateSubmenus(GtkWidget* child, gpointer data) {
-  std::vector<GtkWidget*>* submenus =
-      static_cast<std::vector<GtkWidget*>*>(data);
-  GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(child));
-  if (submenu) {
-    submenus->push_back(submenu);
-    gtk_container_foreach(GTK_CONTAINER(submenu), PopulateSubmenus, submenus);
-  }
-}
-
-// Is the cursor over |menu| or one of its parent menus?
-bool MotionIsOverMenu(GtkWidget* menu, GdkEventMotion* motion) {
-  if (motion->x >= 0 && motion->y >= 0 &&
-      motion->x < menu->allocation.width &&
-      motion->y < menu->allocation.height) {
-    return true;
-  }
-
-  while (menu) {
-    GtkWidget* menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu));
-    if (!menu_item)
-      return false;
-    GtkWidget* parent = gtk_widget_get_parent(menu_item);
-
-    if (gtk_util::WidgetContainsCursor(parent))
-      return true;
-    menu = parent;
-  }
-
-  return false;
-}
-
-}  // namespace
-
-MenuBarHelper::MenuBarHelper(Delegate* delegate)
-    : button_showing_menu_(NULL),
-      showing_menu_(NULL),
-      delegate_(delegate) {
-  DCHECK(delegate_);
-}
-
-MenuBarHelper::~MenuBarHelper() {
-}
-
-void MenuBarHelper::Add(GtkWidget* button) {
-  buttons_.push_back(button);
-}
-
-void MenuBarHelper::Remove(GtkWidget* button) {
-  std::vector<GtkWidget*>::iterator iter =
-      find(buttons_.begin(), buttons_.end(), button);
-  if (iter == buttons_.end()) {
-    NOTREACHED();
-    return;
-  }
-  buttons_.erase(iter);
-}
-
-void MenuBarHelper::Clear() {
-  buttons_.clear();
-}
-
-void MenuBarHelper::MenuStartedShowing(GtkWidget* button, GtkWidget* menu) {
-  DCHECK(GTK_IS_MENU(menu));
-  button_showing_menu_ = button;
-  showing_menu_ = menu;
-
-  signal_handlers_.reset(new GtkSignalRegistrar());
-  signal_handlers_->Connect(menu, "destroy",
-                            G_CALLBACK(OnMenuHiddenOrDestroyedThunk), this);
-  signal_handlers_->Connect(menu, "hide",
-                            G_CALLBACK(OnMenuHiddenOrDestroyedThunk), this);
-  signal_handlers_->Connect(menu, "motion-notify-event",
-                            G_CALLBACK(OnMenuMotionNotifyThunk), this);
-  signal_handlers_->Connect(menu, "move-current",
-                            G_CALLBACK(OnMenuMoveCurrentThunk), this);
-  gtk_container_foreach(GTK_CONTAINER(menu), PopulateSubmenus, &submenus_);
-
-  for (size_t i = 0; i < submenus_.size(); ++i) {
-    signal_handlers_->Connect(submenus_[i], "motion-notify-event",
-                              G_CALLBACK(OnMenuMotionNotifyThunk), this);
-  }
-}
-
-gboolean MenuBarHelper::OnMenuMotionNotify(GtkWidget* menu,
-                                           GdkEventMotion* motion) {
-  // Don't do anything if pointer is in the menu.
-  if (MotionIsOverMenu(menu, motion))
-    return FALSE;
-  if (buttons_.empty())
-    return FALSE;
-
-  gint x = 0;
-  gint y = 0;
-  GtkWidget* last_button = NULL;
-
-  for (size_t i = 0; i < buttons_.size(); ++i) {
-    GtkWidget* button = buttons_[i];
-    // Figure out coordinates relative to this button. Avoid using
-    // gtk_widget_get_pointer() unnecessarily.
-    if (i == 0) {
-      // We have to make this call because the menu is a popup window, so it
-      // doesn't share a toplevel with the buttons and we can't just use
-      // gtk_widget_translate_coordinates().
-      gtk_widget_get_pointer(buttons_[0], &x, &y);
-    } else {
-      gint last_x = x;
-      gint last_y = y;
-      if (!gtk_widget_translate_coordinates(
-          last_button, button, last_x, last_y, &x, &y)) {
-        // |button| may not be realized.
-        continue;
-      }
-    }
-
-    last_button = button;
-
-    if (x >= 0 && y >= 0 && x < button->allocation.width &&
-        y < button->allocation.height) {
-      if (button != button_showing_menu_)
-        delegate_->PopupForButton(button);
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-void MenuBarHelper::OnMenuHiddenOrDestroyed(GtkWidget* menu) {
-  DCHECK_EQ(showing_menu_, menu);
-
-  signal_handlers_.reset();
-  showing_menu_ = NULL;
-  button_showing_menu_ = NULL;
-  submenus_.clear();
-}
-
-void MenuBarHelper::OnMenuMoveCurrent(GtkWidget* menu,
-                                      GtkMenuDirectionType dir) {
-  // The menu directions are triggered by the arrow keys as follows
-  //
-  //   PARENT   left
-  //   CHILD    right
-  //   NEXT     down
-  //   PREV     up
-  //
-  // We only care about left and right. Note that for RTL, they are swapped.
-  switch (dir) {
-    case GTK_MENU_DIR_CHILD: {
-      GtkWidget* active_item = GTK_MENU_SHELL(menu)->active_menu_item;
-      // The move is going to open a submenu; don't override default behavior.
-      if (active_item && gtk_menu_item_get_submenu(GTK_MENU_ITEM(active_item)))
-        return;
-      // Fall through.
-    }
-    case GTK_MENU_DIR_PARENT: {
-      delegate_->PopupForButtonNextTo(button_showing_menu_, dir);
-      break;
-    }
-    default:
-      return;
-  }
-
-  // This signal doesn't have a return value; we have to manually stop its
-  // propagation.
-  g_signal_stop_emission_by_name(menu, "move-current");
-}
diff --git a/chrome/browser/gtk/menu_bar_helper.h b/chrome/browser/gtk/menu_bar_helper.h
deleted file mode 100644
index e6f0ef4..0000000
--- a/chrome/browser/gtk/menu_bar_helper.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This class replicates some menubar behaviors that are tricky to get right.
-// It is used to create a more native feel for the bookmark bar.
-
-#ifndef CHROME_BROWSER_GTK_MENU_BAR_HELPER_H_
-#define CHROME_BROWSER_GTK_MENU_BAR_HELPER_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-
-class GtkSignalRegistrar;
-
-class MenuBarHelper {
- public:
-  class Delegate {
-   public:
-    virtual ~Delegate() {}
-
-    // Called when a the menu for a button ought to be triggered.
-    virtual void PopupForButton(GtkWidget* button) = 0;
-    virtual void PopupForButtonNextTo(GtkWidget* button,
-                                      GtkMenuDirectionType dir) = 0;
-  };
-
-  // |delegate| cannot be null.
-  explicit MenuBarHelper(Delegate* delegate);
-  virtual ~MenuBarHelper();
-
-  // Must be called whenever a button's menu starts showing. It triggers the
-  // MenuBarHelper to start listening for certain events.
-  void MenuStartedShowing(GtkWidget* button, GtkWidget* menu);
-
-  // Add |button| to the set of buttons we care about.
-  void Add(GtkWidget* button);
-
-  // Remove |button| from the set of buttons we care about.
-  void Remove(GtkWidget* button);
-
-  // Clear all buttons from the set.
-  void Clear();
-
- private:
-  CHROMEGTK_CALLBACK_0(MenuBarHelper, void, OnMenuHiddenOrDestroyed);
-  CHROMEGTK_CALLBACK_1(MenuBarHelper, gboolean, OnMenuMotionNotify,
-                       GdkEventMotion*);
-  CHROMEGTK_CALLBACK_1(MenuBarHelper, void, OnMenuMoveCurrent,
-                       GtkMenuDirectionType);
-
-  // The buttons for which we pop up menus. We do not own these, or even add
-  // refs to them.
-  std::vector<GtkWidget*> buttons_;
-
-  // The button that is currently showing a menu, or NULL.
-  GtkWidget* button_showing_menu_;
-
-  // The highest level menu that is currently showing, or NULL.
-  GtkWidget* showing_menu_;
-
-  // All the submenus of |showing_menu_|. We connect to motion events on all
-  // of them.
-  std::vector<GtkWidget*> submenus_;
-
-  // Signal handlers that are attached only between the "show" and "hide" events
-  // for the menu.
-  scoped_ptr<GtkSignalRegistrar> signal_handlers_;
-
-  Delegate* delegate_;
-};
-
-#endif  // CHROME_BROWSER_GTK_MENU_BAR_HELPER_H_
diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc
deleted file mode 100644
index 52b9c12..0000000
--- a/chrome/browser/gtk/menu_gtk.cc
+++ /dev/null
@@ -1,840 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/menu_gtk.h"
-
-#include <map>
-
-#include "app/menus/accelerator_gtk.h"
-#include "app/menus/button_menu_item_model.h"
-#include "app/menus/menu_model.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gtk/gtk_custom_menu.h"
-#include "chrome/browser/gtk/gtk_custom_menu_item.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "gfx/gtk_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "webkit/glue/window_open_disposition.h"
-
-bool MenuGtk::block_activation_ = false;
-
-namespace {
-
-// Sets the ID of a menu item.
-void SetMenuItemID(GtkWidget* menu_item, int menu_id) {
-  DCHECK_GE(menu_id, 0);
-
-  // Add 1 to the menu_id to avoid setting zero (null) to "menu-id".
-  g_object_set_data(G_OBJECT(menu_item), "menu-id",
-                    GINT_TO_POINTER(menu_id + 1));
-}
-
-// Gets the ID of a menu item.
-// Returns true if the menu item has an ID.
-bool GetMenuItemID(GtkWidget* menu_item, int* menu_id) {
-  gpointer id_ptr = g_object_get_data(G_OBJECT(menu_item), "menu-id");
-  if (id_ptr != NULL) {
-    *menu_id = GPOINTER_TO_INT(id_ptr) - 1;
-    return true;
-  }
-
-  return false;
-}
-
-menus::MenuModel* ModelForMenuItem(GtkMenuItem* menu_item) {
-  return reinterpret_cast<menus::MenuModel*>(
-      g_object_get_data(G_OBJECT(menu_item), "model"));
-}
-
-void SetupButtonShowHandler(GtkWidget* button,
-                            menus::ButtonMenuItemModel* model,
-                            int index) {
-  g_object_set_data(G_OBJECT(button), "button-model",
-                    model);
-  g_object_set_data(G_OBJECT(button), "button-model-id",
-                    GINT_TO_POINTER(index));
-}
-
-void OnSubmenuShowButtonImage(GtkWidget* widget, GtkButton* button) {
-  MenuGtk::Delegate* delegate = reinterpret_cast<MenuGtk::Delegate*>(
-      g_object_get_data(G_OBJECT(button), "menu-gtk-delegate"));
-  int icon_idr = GPOINTER_TO_INT(g_object_get_data(
-      G_OBJECT(button), "button-image-idr"));
-
-  GtkIconSet* icon_set = delegate->GetIconSetForId(icon_idr);
-  if (icon_set) {
-    gtk_button_set_image(
-        button, gtk_image_new_from_icon_set(icon_set,
-                                            GTK_ICON_SIZE_MENU));
-  }
-}
-
-void SetupImageIcon(GtkWidget* button,
-                    GtkWidget* menu,
-                    int icon_idr,
-                    MenuGtk::Delegate* menu_gtk_delegate) {
-  g_object_set_data(G_OBJECT(button), "button-image-idr",
-                    GINT_TO_POINTER(icon_idr));
-  g_object_set_data(G_OBJECT(button), "menu-gtk-delegate",
-                    menu_gtk_delegate);
-
-  g_signal_connect(menu, "show", G_CALLBACK(OnSubmenuShowButtonImage), button);
-}
-
-// Popup menus may get squished if they open up too close to the bottom of the
-// screen. This function takes the size of the screen, the size of the menu,
-// an optional widget, the Y position of the mouse click, and adjusts the popup
-// menu's Y position to make it fit if it's possible to do so.
-// Returns the new Y position of the popup menu.
-int CalculateMenuYPosition(const GdkRectangle* screen_rect,
-                           const GtkRequisition* menu_req,
-                           const GtkWidget* widget, const int y) {
-  CHECK(screen_rect);
-  CHECK(menu_req);
-  // If the menu would run off the bottom of the screen, and there is enough
-  // screen space upwards to accommodate the menu, then pop upwards. If there
-  // is a widget, then also move the anchor point to the top of the widget
-  // rather than the bottom.
-  const int screen_top = screen_rect->y;
-  const int screen_bottom = screen_rect->y + screen_rect->height;
-  const int menu_bottom = y + menu_req->height;
-  int alternate_y = y - menu_req->height;
-  if (widget)
-    alternate_y -= widget->allocation.height;
-  if (menu_bottom >= screen_bottom && alternate_y >= screen_top)
-    return alternate_y;
-  return y;
-}
-
-}  // namespace
-
-GtkWidget* MenuGtk::Delegate::GetDefaultImageForCommandId(int command_id) {
-  const char* stock;
-  switch (command_id) {
-    case IDC_NEW_TAB:
-    case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB:
-    case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB:
-    case IDC_CONTENT_CONTEXT_OPENAVNEWTAB:
-      stock = GTK_STOCK_NEW;
-      break;
-
-    case IDC_CLOSE_TAB:
-      stock = GTK_STOCK_CLOSE;
-      break;
-
-    case IDC_CONTENT_CONTEXT_SAVEIMAGEAS:
-    case IDC_CONTENT_CONTEXT_SAVEAVAS:
-    case IDC_CONTENT_CONTEXT_SAVELINKAS:
-      stock = GTK_STOCK_SAVE_AS;
-      break;
-
-    case IDC_SAVE_PAGE:
-      stock = GTK_STOCK_SAVE;
-      break;
-
-    case IDC_COPY:
-    case IDC_COPY_URL:
-    case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION:
-    case IDC_CONTENT_CONTEXT_COPYLINKLOCATION:
-    case IDC_CONTENT_CONTEXT_COPYAVLOCATION:
-    case IDC_CONTENT_CONTEXT_COPYEMAILADDRESS:
-    case IDC_CONTENT_CONTEXT_COPY:
-      stock = GTK_STOCK_COPY;
-      break;
-
-    case IDC_CUT:
-    case IDC_CONTENT_CONTEXT_CUT:
-      stock = GTK_STOCK_CUT;
-      break;
-
-    case IDC_PASTE:
-    case IDC_CONTENT_CONTEXT_PASTE:
-      stock = GTK_STOCK_PASTE;
-      break;
-
-    case IDC_CONTENT_CONTEXT_DELETE:
-    case IDC_BOOKMARK_BAR_REMOVE:
-      stock = GTK_STOCK_DELETE;
-      break;
-
-    case IDC_CONTENT_CONTEXT_UNDO:
-      stock = GTK_STOCK_UNDO;
-      break;
-
-    case IDC_CONTENT_CONTEXT_REDO:
-      stock = GTK_STOCK_REDO;
-      break;
-
-    case IDC_SEARCH:
-    case IDC_FIND:
-    case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
-      stock = GTK_STOCK_FIND;
-      break;
-
-    case IDC_CONTENT_CONTEXT_SELECTALL:
-      stock = GTK_STOCK_SELECT_ALL;
-      break;
-
-    case IDC_CLEAR_BROWSING_DATA:
-      stock = GTK_STOCK_CLEAR;
-      break;
-
-    case IDC_BACK:
-      stock = GTK_STOCK_GO_BACK;
-      break;
-
-    case IDC_RELOAD:
-      stock = GTK_STOCK_REFRESH;
-      break;
-
-    case IDC_FORWARD:
-      stock = GTK_STOCK_GO_FORWARD;
-      break;
-
-    case IDC_PRINT:
-      stock = GTK_STOCK_PRINT;
-      break;
-
-    case IDC_CONTENT_CONTEXT_VIEWPAGEINFO:
-      stock = GTK_STOCK_INFO;
-      break;
-
-    case IDC_SPELLCHECK_MENU:
-      stock = GTK_STOCK_SPELL_CHECK;
-      break;
-
-    case IDC_RESTORE_TAB:
-      stock = GTK_STOCK_UNDELETE;
-      break;
-
-    case IDC_HOME:
-      stock = GTK_STOCK_HOME;
-      break;
-
-    case IDC_STOP:
-      stock = GTK_STOCK_STOP;
-      break;
-
-    case IDC_ABOUT:
-      stock = GTK_STOCK_ABOUT;
-      break;
-
-    case IDC_EXIT:
-      stock = GTK_STOCK_QUIT;
-      break;
-
-    case IDC_HELP_PAGE:
-      stock = GTK_STOCK_HELP;
-      break;
-
-    case IDC_OPTIONS:
-      stock = GTK_STOCK_PREFERENCES;
-      break;
-
-    case IDC_CONTENT_CONTEXT_GOTOURL:
-      stock = GTK_STOCK_JUMP_TO;
-      break;
-
-    case IDC_DEV_TOOLS_INSPECT:
-    case IDC_CONTENT_CONTEXT_INSPECTELEMENT:
-      stock = GTK_STOCK_PROPERTIES;
-      break;
-
-    case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK:
-      stock = GTK_STOCK_ADD;
-      break;
-
-    case IDC_BOOKMARK_BAR_RENAME_FOLDER:
-    case IDC_BOOKMARK_BAR_EDIT:
-      stock = GTK_STOCK_EDIT;
-      break;
-
-    case IDC_BOOKMARK_BAR_NEW_FOLDER:
-      stock = GTK_STOCK_DIRECTORY;
-      break;
-
-    case IDC_BOOKMARK_BAR_OPEN_ALL:
-      stock = GTK_STOCK_OPEN;
-      break;
-
-    default:
-      stock = NULL;
-  }
-
-  return stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU) : NULL;
-}
-
-GtkWidget* MenuGtk::Delegate::GetImageForCommandId(int command_id) const {
-  return GetDefaultImageForCommandId(command_id);
-}
-
-MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
-                 menus::MenuModel* model)
-    : delegate_(delegate),
-      model_(model),
-      dummy_accel_group_(gtk_accel_group_new()),
-      menu_(gtk_custom_menu_new()),
-      factory_(this) {
-  DCHECK(model);
-  g_object_ref_sink(menu_);
-  ConnectSignalHandlers();
-  BuildMenuFromModel();
-}
-
-MenuGtk::~MenuGtk() {
-  Cancel();
-
-  gtk_widget_destroy(menu_);
-  g_object_unref(menu_);
-
-  STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end());
-  g_object_unref(dummy_accel_group_);
-}
-
-void MenuGtk::ConnectSignalHandlers() {
-  // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may
-  // take a long time or even start a nested message loop.
-  g_signal_connect(menu_, "show", G_CALLBACK(OnMenuShowThunk), this);
-  g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this);
-}
-
-GtkWidget* MenuGtk::AppendMenuItemWithLabel(int command_id,
-                                            const std::string& label) {
-  std::string converted_label = gfx::ConvertAcceleratorsFromWindowsStyle(label);
-  GtkWidget* menu_item = BuildMenuItemWithLabel(label, command_id);
-  return AppendMenuItem(command_id, menu_item);
-}
-
-GtkWidget* MenuGtk::AppendMenuItemWithIcon(int command_id,
-                                           const std::string& label,
-                                           const SkBitmap& icon) {
-  std::string converted_label = gfx::ConvertAcceleratorsFromWindowsStyle(label);
-  GtkWidget* menu_item = BuildMenuItemWithImage(converted_label, icon);
-  return AppendMenuItem(command_id, menu_item);
-}
-
-GtkWidget* MenuGtk::AppendCheckMenuItemWithLabel(int command_id,
-                                                 const std::string& label) {
-  std::string converted_label = gfx::ConvertAcceleratorsFromWindowsStyle(label);
-  GtkWidget* menu_item =
-      gtk_check_menu_item_new_with_mnemonic(converted_label.c_str());
-  return AppendMenuItem(command_id, menu_item);
-}
-
-GtkWidget* MenuGtk::AppendSeparator() {
-  GtkWidget* menu_item = gtk_separator_menu_item_new();
-  gtk_widget_show(menu_item);
-  gtk_menu_shell_append(GTK_MENU_SHELL(menu_), menu_item);
-  return menu_item;
-}
-
-GtkWidget* MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) {
-  if (delegate_ && delegate_->AlwaysShowIconForCmd(command_id) &&
-      GTK_IS_IMAGE_MENU_ITEM(menu_item))
-    gtk_util::SetAlwaysShowImage(menu_item);
-
-  return AppendMenuItemToMenu(command_id, NULL, menu_item, menu_, true);
-}
-
-GtkWidget* MenuGtk::AppendMenuItemToMenu(int index,
-                                         menus::MenuModel* model,
-                                         GtkWidget* menu_item,
-                                         GtkWidget* menu,
-                                         bool connect_to_activate) {
-  SetMenuItemID(menu_item, index);
-
-  // Native menu items do their own thing, so only selectively listen for the
-  // activate signal.
-  if (connect_to_activate) {
-    g_signal_connect(menu_item, "activate",
-                     G_CALLBACK(OnMenuItemActivatedThunk), this);
-  }
-
-  // AppendMenuItemToMenu is used both internally when we control menu creation
-  // from a model (where the model can choose to hide certain menu items), and
-  // with immediate commands which don't provide the option.
-  if (model) {
-    if (model->IsVisibleAt(index))
-      gtk_widget_show(menu_item);
-  } else {
-    gtk_widget_show(menu_item);
-  }
-  gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-  return menu_item;
-}
-
-void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) {
-  DCHECK(event->type == GDK_BUTTON_PRESS)
-      << "Non-button press event sent to RunMenuAt";
-
-  Popup(widget, event->button.button, event->button.time);
-}
-
-void MenuGtk::Popup(GtkWidget* widget, gint button_type, guint32 timestamp) {
-  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
-                 WidgetMenuPositionFunc,
-                 widget,
-                 button_type, timestamp);
-}
-
-void MenuGtk::PopupAsContext(guint32 event_time) {
-  // TODO(estade): |button| value of 3 (6th argument) is not strictly true,
-  // but does it matter?
-  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, NULL, NULL, 3, event_time);
-}
-
-void MenuGtk::PopupAsContextAt(guint32 event_time, gfx::Point point) {
-  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
-                 PointMenuPositionFunc, &point, 3, event_time);
-}
-
-void MenuGtk::PopupAsContextForStatusIcon(guint32 event_time, guint32 button,
-                                          GtkStatusIcon* icon) {
-  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, gtk_status_icon_position_menu,
-                 icon, button, event_time);
-}
-
-void MenuGtk::PopupAsFromKeyEvent(GtkWidget* widget) {
-  Popup(widget, 0, gtk_get_current_event_time());
-  gtk_menu_shell_select_first(GTK_MENU_SHELL(menu_), FALSE);
-}
-
-void MenuGtk::Cancel() {
-  gtk_menu_popdown(GTK_MENU(menu_));
-}
-
-void MenuGtk::UpdateMenu() {
-  gtk_container_foreach(GTK_CONTAINER(menu_), SetMenuItemInfo, this);
-}
-
-GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
-                                  GtkWidget* image) {
-  GtkWidget* menu_item =
-      gtk_image_menu_item_new_with_mnemonic(label.c_str());
-  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
-  return menu_item;
-}
-
-GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
-                                           const SkBitmap& icon) {
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
-  GtkWidget* menu_item = BuildMenuItemWithImage(label,
-      gtk_image_new_from_pixbuf(pixbuf));
-  g_object_unref(pixbuf);
-  return menu_item;
-}
-
-GtkWidget* MenuGtk::BuildMenuItemWithLabel(const std::string& label,
-                                           int command_id) {
-  GtkWidget* img =
-      delegate_ ? delegate_->GetImageForCommandId(command_id) :
-                  MenuGtk::Delegate::GetDefaultImageForCommandId(command_id);
-  return img ? BuildMenuItemWithImage(label, img) :
-               gtk_menu_item_new_with_mnemonic(label.c_str());
-}
-
-void MenuGtk::BuildMenuFromModel() {
-  BuildSubmenuFromModel(model_, menu_);
-}
-
-void MenuGtk::BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu) {
-  std::map<int, GtkWidget*> radio_groups;
-  GtkWidget* menu_item = NULL;
-  for (int i = 0; i < model->GetItemCount(); ++i) {
-    SkBitmap icon;
-    std::string label =
-        gfx::ConvertAcceleratorsFromWindowsStyle(
-            UTF16ToUTF8(model->GetLabelAt(i)));
-    bool connect_to_activate = true;
-
-    switch (model->GetTypeAt(i)) {
-      case menus::MenuModel::TYPE_SEPARATOR:
-        menu_item = gtk_separator_menu_item_new();
-        break;
-
-      case menus::MenuModel::TYPE_CHECK:
-        menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
-        break;
-
-      case menus::MenuModel::TYPE_RADIO: {
-        std::map<int, GtkWidget*>::iterator iter =
-            radio_groups.find(model->GetGroupIdAt(i));
-
-        if (iter == radio_groups.end()) {
-          menu_item = gtk_radio_menu_item_new_with_mnemonic(
-              NULL, label.c_str());
-          radio_groups[model->GetGroupIdAt(i)] = menu_item;
-        } else {
-          menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
-              GTK_RADIO_MENU_ITEM(iter->second), label.c_str());
-        }
-        break;
-      }
-      case menus::MenuModel::TYPE_BUTTON_ITEM: {
-        menus::ButtonMenuItemModel* button_menu_item_model =
-            model->GetButtonMenuItemAt(i);
-        menu_item = BuildButtomMenuItem(button_menu_item_model, menu);
-        connect_to_activate = false;
-        break;
-      }
-      case menus::MenuModel::TYPE_SUBMENU:
-      case menus::MenuModel::TYPE_COMMAND: {
-        int command_id = model->GetCommandIdAt(i);
-        if (model->GetIconAt(i, &icon))
-          menu_item = BuildMenuItemWithImage(label, icon);
-        else
-          menu_item = BuildMenuItemWithLabel(label, command_id);
-        if (delegate_ && delegate_->AlwaysShowIconForCmd(command_id) &&
-            GTK_IS_IMAGE_MENU_ITEM(menu_item))
-          gtk_util::SetAlwaysShowImage(menu_item);
-        break;
-      }
-
-      default:
-        NOTREACHED();
-    }
-
-    if (model->GetTypeAt(i) == menus::MenuModel::TYPE_SUBMENU) {
-      GtkWidget* submenu = gtk_menu_new();
-      BuildSubmenuFromModel(model->GetSubmenuModelAt(i), submenu);
-      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
-    }
-
-    menus::AcceleratorGtk accelerator;
-    if (model->GetAcceleratorAt(i, &accelerator)) {
-      gtk_widget_add_accelerator(menu_item,
-                                 "activate",
-                                 dummy_accel_group_,
-                                 accelerator.GetGdkKeyCode(),
-                                 accelerator.gdk_modifier_type(),
-                                 GTK_ACCEL_VISIBLE);
-    }
-
-    g_object_set_data(G_OBJECT(menu_item), "model", model);
-    AppendMenuItemToMenu(i, model, menu_item, menu, connect_to_activate);
-
-    menu_item = NULL;
-  }
-}
-
-GtkWidget* MenuGtk::BuildButtomMenuItem(menus::ButtonMenuItemModel* model,
-                                        GtkWidget* menu) {
-  GtkWidget* menu_item = gtk_custom_menu_item_new(
-      gfx::RemoveWindowsStyleAccelerators(UTF16ToUTF8(model->label())).c_str());
-
-  // Set up the callback to the model for when it is clicked.
-  g_object_set_data(G_OBJECT(menu_item), "button-model", model);
-  g_signal_connect(menu_item, "button-pushed",
-                   G_CALLBACK(OnMenuButtonPressedThunk), this);
-  g_signal_connect(menu_item, "try-button-pushed",
-                   G_CALLBACK(OnMenuTryButtonPressedThunk), this);
-
-  GtkSizeGroup* group = NULL;
-  for (int i = 0; i < model->GetItemCount(); ++i) {
-    GtkWidget* button = NULL;
-
-    switch (model->GetTypeAt(i)) {
-      case menus::ButtonMenuItemModel::TYPE_SPACE: {
-        gtk_custom_menu_item_add_space(GTK_CUSTOM_MENU_ITEM(menu_item));
-        break;
-      }
-      case menus::ButtonMenuItemModel::TYPE_BUTTON: {
-        button = gtk_custom_menu_item_add_button(
-            GTK_CUSTOM_MENU_ITEM(menu_item),
-            model->GetCommandIdAt(i));
-
-        int icon_idr;
-        if (model->GetIconAt(i, &icon_idr)) {
-          SetupImageIcon(button, menu, icon_idr, delegate_);
-        } else {
-          gtk_button_set_label(
-              GTK_BUTTON(button),
-              gfx::RemoveWindowsStyleAccelerators(
-                  UTF16ToUTF8(model->GetLabelAt(i))).c_str());
-        }
-
-        SetupButtonShowHandler(button, model, i);
-        break;
-      }
-      case menus::ButtonMenuItemModel::TYPE_BUTTON_LABEL: {
-        button = gtk_custom_menu_item_add_button_label(
-            GTK_CUSTOM_MENU_ITEM(menu_item),
-            model->GetCommandIdAt(i));
-        gtk_button_set_label(
-            GTK_BUTTON(button),
-            gfx::RemoveWindowsStyleAccelerators(
-                UTF16ToUTF8(model->GetLabelAt(i))).c_str());
-        SetupButtonShowHandler(button, model, i);
-        break;
-      }
-    }
-
-    if (button && model->PartOfGroup(i)) {
-      if (!group)
-        group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-      gtk_size_group_add_widget(group, button);
-    }
-  }
-
-  if (group) {
-    g_object_unref(group);
-  }
-
-  return menu_item;
-}
-
-void MenuGtk::OnMenuItemActivated(GtkWidget* menuitem) {
-  if (block_activation_)
-    return;
-
-  // We receive activation messages when highlighting a menu that has a
-  // submenu. Ignore them.
-  if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuitem)))
-    return;
-
-  // The activate signal is sent to radio items as they get deselected;
-  // ignore it in this case.
-  if (GTK_IS_RADIO_MENU_ITEM(menuitem) &&
-      !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
-    return;
-  }
-
-  int id;
-  if (!GetMenuItemID(menuitem, &id))
-    return;
-
-  menus::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menuitem));
-
-  // The menu item can still be activated by hotkeys even if it is disabled.
-  if (model->IsEnabledAt(id))
-    ExecuteCommand(model, id);
-}
-
-void MenuGtk::OnMenuButtonPressed(GtkWidget* menu_item, int command_id) {
-  menus::ButtonMenuItemModel* model =
-      reinterpret_cast<menus::ButtonMenuItemModel*>(
-          g_object_get_data(G_OBJECT(menu_item), "button-model"));
-  if (model && model->IsCommandIdEnabled(command_id)) {
-    if (delegate_)
-      delegate_->CommandWillBeExecuted();
-
-    model->ActivatedCommand(command_id);
-  }
-}
-
-gboolean MenuGtk::OnMenuTryButtonPressed(GtkWidget* menu_item,
-                                         int command_id) {
-  gboolean pressed = FALSE;
-  menus::ButtonMenuItemModel* model =
-      reinterpret_cast<menus::ButtonMenuItemModel*>(
-          g_object_get_data(G_OBJECT(menu_item), "button-model"));
-  if (model &&
-      model->IsCommandIdEnabled(command_id) &&
-      !model->DoesCommandIdDismissMenu(command_id)) {
-    if (delegate_)
-      delegate_->CommandWillBeExecuted();
-
-    model->ActivatedCommand(command_id);
-    pressed = TRUE;
-  }
-
-  return pressed;
-}
-
-// static
-void MenuGtk::WidgetMenuPositionFunc(GtkMenu* menu,
-                                     int* x,
-                                     int* y,
-                                     gboolean* push_in,
-                                     void* void_widget) {
-  GtkWidget* widget = GTK_WIDGET(void_widget);
-  GtkRequisition menu_req;
-
-  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
-
-  gdk_window_get_origin(widget->window, x, y);
-  GdkScreen *screen = gtk_widget_get_screen(widget);
-  gint monitor = gdk_screen_get_monitor_at_point(screen, *x, *y);
-
-  GdkRectangle screen_rect;
-  gdk_screen_get_monitor_geometry(screen, monitor,
-                                  &screen_rect);
-
-  if (GTK_WIDGET_NO_WINDOW(widget)) {
-    *x += widget->allocation.x;
-    *y += widget->allocation.y;
-  }
-  *y += widget->allocation.height;
-
-  bool start_align =
-    !!g_object_get_data(G_OBJECT(widget), "left-align-popup");
-  if (base::i18n::IsRTL())
-    start_align = !start_align;
-
-  if (!start_align)
-    *x += widget->allocation.width - menu_req.width;
-
-  *y = CalculateMenuYPosition(&screen_rect, &menu_req, widget, *y);
-
-  *push_in = FALSE;
-}
-
-// static
-void MenuGtk::PointMenuPositionFunc(GtkMenu* menu,
-                                    int* x,
-                                    int* y,
-                                    gboolean* push_in,
-                                    gpointer userdata) {
-  *push_in = TRUE;
-
-  gfx::Point* point = reinterpret_cast<gfx::Point*>(userdata);
-  *x = point->x();
-  *y = point->y();
-
-  GtkRequisition menu_req;
-  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
-  GdkScreen* screen;
-  gdk_display_get_pointer(gdk_display_get_default(), &screen, NULL, NULL, NULL);
-  gint monitor = gdk_screen_get_monitor_at_point(screen, *x, *y);
-
-  GdkRectangle screen_rect;
-  gdk_screen_get_monitor_geometry(screen, monitor, &screen_rect);
-
-  *y = CalculateMenuYPosition(&screen_rect, &menu_req, NULL, *y);
-}
-
-void MenuGtk::ExecuteCommand(menus::MenuModel* model, int id) {
-  if (delegate_)
-    delegate_->CommandWillBeExecuted();
-
-  GdkEvent* event = gtk_get_current_event();
-  if (event && event->type == GDK_BUTTON_RELEASE) {
-    model->ActivatedAtWithDisposition(
-        id, event_utils::DispositionFromEventFlags(event->button.state));
-  } else {
-    model->ActivatedAt(id);
-  }
-
-  if (event)
-    gdk_event_free(event);
-}
-
-void MenuGtk::OnMenuShow(GtkWidget* widget) {
-  MessageLoop::current()->PostTask(FROM_HERE,
-      factory_.NewRunnableMethod(&MenuGtk::UpdateMenu));
-}
-
-void MenuGtk::OnMenuHidden(GtkWidget* widget) {
-  if (delegate_)
-    delegate_->StoppedShowing();
-}
-
-// static
-void MenuGtk::SetButtonItemInfo(GtkWidget* button, gpointer userdata) {
-  menus::ButtonMenuItemModel* model =
-      reinterpret_cast<menus::ButtonMenuItemModel*>(
-          g_object_get_data(G_OBJECT(button), "button-model"));
-  int index = GPOINTER_TO_INT(g_object_get_data(
-      G_OBJECT(button), "button-model-id"));
-
-  if (model->IsItemDynamicAt(index)) {
-    std::string label =
-        gfx::ConvertAcceleratorsFromWindowsStyle(
-            UTF16ToUTF8(model->GetLabelAt(index)));
-    gtk_button_set_label(GTK_BUTTON(button), label.c_str());
-  }
-
-  gtk_widget_set_sensitive(GTK_WIDGET(button), model->IsEnabledAt(index));
-}
-
-// static
-void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
-  if (GTK_IS_SEPARATOR_MENU_ITEM(widget)) {
-    // We need to explicitly handle this case because otherwise we'll ask the
-    // menu delegate about something with an invalid id.
-    return;
-  }
-
-  int id;
-  if (!GetMenuItemID(widget, &id))
-    return;
-
-  menus::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(widget));
-  if (!model) {
-    // If we're not providing the sub menu, then there's no model.  For
-    // example, the IME submenu doesn't have a model.
-    return;
-  }
-
-  if (GTK_IS_CHECK_MENU_ITEM(widget)) {
-    GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget);
-
-    // gtk_check_menu_item_set_active() will send the activate signal. Touching
-    // the underlying "active" property will also call the "activate" handler
-    // for this menu item. So we prevent the "activate" handler from
-    // being called while we set the checkbox.
-    // Why not use one of the glib signal-blocking functions?  Because when we
-    // toggle a radio button, it will deactivate one of the other radio buttons,
-    // which we don't have a pointer to.
-    // Wny not make this a member variable?  Because "menu" is a pointer to the
-    // root of the MenuGtk and we want to disable *all* MenuGtks, including
-    // submenus.
-    block_activation_ = true;
-    gtk_check_menu_item_set_active(item, model->IsItemCheckedAt(id));
-    block_activation_ = false;
-  }
-
-  if (GTK_IS_CUSTOM_MENU_ITEM(widget)) {
-    // Iterate across all the buttons to update their visible properties.
-    gtk_custom_menu_item_foreach_button(GTK_CUSTOM_MENU_ITEM(widget),
-                                        SetButtonItemInfo,
-                                        userdata);
-  }
-
-  if (GTK_IS_MENU_ITEM(widget)) {
-    gtk_widget_set_sensitive(widget, model->IsEnabledAt(id));
-
-    if (model->IsVisibleAt(id)) {
-      // Update the menu item label if it is dynamic.
-      if (model->IsItemDynamicAt(id)) {
-        std::string label =
-            gfx::ConvertAcceleratorsFromWindowsStyle(
-                UTF16ToUTF8(model->GetLabelAt(id)));
-
-#if GTK_CHECK_VERSION(2, 16, 0)
-        gtk_menu_item_set_label(GTK_MENU_ITEM(widget), label.c_str());
-#else
-        gtk_label_set_label(GTK_LABEL(GTK_BIN(widget)->child), label.c_str());
-#endif
-        if (GTK_IS_IMAGE_MENU_ITEM(widget)) {
-          SkBitmap icon;
-          if (model->GetIconAt(id, &icon)) {
-            GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
-            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget),
-                                          gtk_image_new_from_pixbuf(pixbuf));
-            g_object_unref(pixbuf);
-          } else {
-            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), NULL);
-          }
-        }
-      }
-
-      gtk_widget_show(widget);
-    } else {
-      gtk_widget_hide(widget);
-    }
-
-    GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
-    if (submenu) {
-      gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
-                            userdata);
-    }
-  }
-}
diff --git a/chrome/browser/gtk/menu_gtk.h b/chrome/browser/gtk/menu_gtk.h
deleted file mode 100644
index 7e4185b..0000000
--- a/chrome/browser/gtk/menu_gtk.h
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_MENU_GTK_H_
-#define CHROME_BROWSER_GTK_MENU_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/task.h"
-#include "gfx/point.h"
-
-class SkBitmap;
-
-namespace menus {
-class ButtonMenuItemModel;
-class MenuModel;
-}
-
-class MenuGtk {
- public:
-  // Delegate class that lets another class control the status of the menu.
-  class Delegate {
-   public:
-    virtual ~Delegate() { }
-
-    // Called before a command is executed. This exists for the case where a
-    // model is handling the actual execution of commands, but the delegate
-    // still needs to know that some command got executed. This is called before
-    // and not after the command is executed because its execution may delete
-    // the menu and/or the delegate.
-    virtual void CommandWillBeExecuted() {}
-
-    // Called when the menu stops showing. This will be called before
-    // ExecuteCommand if the user clicks an item, but will also be called when
-    // the user clicks away from the menu.
-    virtual void StoppedShowing() {}
-
-    // Return true if we should override the "gtk-menu-images" system setting
-    // when showing image menu items for this menu.
-    virtual bool AlwaysShowIconForCmd(int command_id) const { return false; }
-
-    // Returns a tinted image used in button in a menu.
-    virtual GtkIconSet* GetIconSetForId(int idr) { return NULL; }
-
-    // Returns an icon for the menu item, if available.
-    virtual GtkWidget* GetImageForCommandId(int command_id) const;
-
-    static GtkWidget* GetDefaultImageForCommandId(int command_id);
-  };
-
-  MenuGtk(MenuGtk::Delegate* delegate, menus::MenuModel* model);
-  ~MenuGtk();
-
-  // Initialize GTK signal handlers.
-  void ConnectSignalHandlers();
-
-  // These methods are used to build the menu dynamically. The return value
-  // is the new menu item.
-  GtkWidget* AppendMenuItemWithLabel(int command_id, const std::string& label);
-  GtkWidget* AppendMenuItemWithIcon(int command_id, const std::string& label,
-                                    const SkBitmap& icon);
-  GtkWidget* AppendCheckMenuItemWithLabel(int command_id,
-                                          const std::string& label);
-  GtkWidget* AppendSeparator();
-  GtkWidget* AppendMenuItem(int command_id, GtkWidget* menu_item);
-  GtkWidget* AppendMenuItemToMenu(int index,
-                                  menus::MenuModel* model,
-                                  GtkWidget* menu_item,
-                                  GtkWidget* menu,
-                                  bool connect_to_activate);
-
-  // Displays the menu. |timestamp| is the time of activation. The popup is
-  // statically positioned at |widget|.
-  void Popup(GtkWidget* widget, gint button_type, guint32 timestamp);
-
-  // Displays the menu using the button type and timestamp of |event|. The popup
-  // is statically positioned at |widget|.
-  void Popup(GtkWidget* widget, GdkEvent* event);
-
-  // Displays the menu as a context menu, i.e. at the current cursor location.
-  // |event_time| is the time of the event that triggered the menu's display.
-  void PopupAsContext(guint32 event_time);
-
-  // Displays the menu at the given coords. |point| is intentionally not const.
-  void PopupAsContextAt(guint32 event_time, gfx::Point point);
-
-  // Displays the menu as a context menu for the passed status icon.
-  void PopupAsContextForStatusIcon(guint32 event_time, guint32 button,
-                                   GtkStatusIcon* icon);
-
-  // Displays the menu following a keyboard event (such as selecting |widget|
-  // and pressing "enter").
-  void PopupAsFromKeyEvent(GtkWidget* widget);
-
-  // Closes the menu.
-  void Cancel();
-
-  // Repositions the menu to be right under the button.  Alignment is set as
-  // object data on |void_widget| with the tag "left_align".  If "left_align"
-  // is true, it aligns the left side of the menu with the left side of the
-  // button. Otherwise it aligns the right side of the menu with the right side
-  // of the button. Public since some menus have odd requirements that don't
-  // belong in a public class.
-  static void WidgetMenuPositionFunc(GtkMenu* menu,
-                                     int* x,
-                                     int* y,
-                                     gboolean* push_in,
-                                     void* void_widget);
-
-  // Positions the menu to appear at the gfx::Point represented by |userdata|.
-  static void PointMenuPositionFunc(GtkMenu* menu,
-                                    int* x,
-                                    int* y,
-                                    gboolean* push_in,
-                                    gpointer userdata);
-
-  GtkWidget* widget() const { return menu_; }
-
-  // Updates all the enabled/checked states and the dynamic labels.
-  void UpdateMenu();
-
- private:
-  // Builds a GtkImageMenuItem.
-  GtkWidget* BuildMenuItemWithImage(const std::string& label,
-                                    const SkBitmap& icon);
-
-  GtkWidget* BuildMenuItemWithImage(const std::string& label,
-                                    GtkWidget* image);
-
-  GtkWidget* BuildMenuItemWithLabel(const std::string& label,
-                                    int command_id);
-
-  // A function that creates a GtkMenu from |model_|.
-  void BuildMenuFromModel();
-  // Implementation of the above; called recursively.
-  void BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu);
-  // Builds a menu item with buttons in it from the data in the model.
-  GtkWidget* BuildButtomMenuItem(menus::ButtonMenuItemModel* model,
-                                 GtkWidget* menu);
-
-  void ExecuteCommand(menus::MenuModel* model, int id);
-
-  // Callback for when a menu item is clicked.
-  CHROMEGTK_CALLBACK_0(MenuGtk, void, OnMenuItemActivated);
-
-  // Called when one of the buttons are pressed.
-  CHROMEGTK_CALLBACK_1(MenuGtk, void, OnMenuButtonPressed, int);
-
-  // Called to maybe activate a button if that button isn't supposed to dismiss
-  // the menu.
-  CHROMEGTK_CALLBACK_1(MenuGtk, gboolean, OnMenuTryButtonPressed, int);
-
-  // Updates all the menu items' state.
-  CHROMEGTK_CALLBACK_0(MenuGtk, void, OnMenuShow);
-
-  // Sets the activating widget back to a normal appearance.
-  CHROMEGTK_CALLBACK_0(MenuGtk, void, OnMenuHidden);
-
-  // Sets the enable/disabled state and dynamic labels on our menu items.
-  static void SetButtonItemInfo(GtkWidget* button, gpointer userdata);
-
-  // Sets the check mark, enabled/disabled state and dynamic labels on our menu
-  // items.
-  static void SetMenuItemInfo(GtkWidget* widget, void* raw_menu);
-
-  // Queries this object about the menu state.
-  MenuGtk::Delegate* delegate_;
-
-  // If non-NULL, the MenuModel that we use to populate and control the GTK
-  // menu (overriding the delegate as a controller).
-  menus::MenuModel* model_;
-
-  // For some menu items, we want to show the accelerator, but not actually
-  // explicitly handle it. To this end we connect those menu items' accelerators
-  // to this group, but don't attach this group to any top level window.
-  GtkAccelGroup* dummy_accel_group_;
-
-  // gtk_menu_popup() does not appear to take ownership of popup menus, so
-  // MenuGtk explicitly manages the lifetime of the menu.
-  GtkWidget* menu_;
-
-  // True when we should ignore "activate" signals.  Used to prevent
-  // menu items from getting activated when we are setting up the
-  // menu.
-  static bool block_activation_;
-
-  // We must free these at shutdown.
-  std::vector<MenuGtk*> submenus_we_own_;
-
-  ScopedRunnableMethodFactory<MenuGtk> factory_;
-};
-
-#endif  // CHROME_BROWSER_GTK_MENU_GTK_H_
diff --git a/chrome/browser/gtk/nine_box.cc b/chrome/browser/gtk/nine_box.cc
deleted file mode 100644
index 9d65387..0000000
--- a/chrome/browser/gtk/nine_box.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/nine_box.h"
-
-#include "app/resource_bundle.h"
-#include "base/basictypes.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "gfx/gtk_util.h"
-#include "gfx/point.h"
-
-namespace {
-
-// Draw pixbuf |src| into |dst| at position (x, y).
-void DrawPixbuf(cairo_t* cr, GdkPixbuf* src, int x, int y, double alpha) {
-  gdk_cairo_set_source_pixbuf(cr, src, x, y);
-  cairo_paint_with_alpha(cr, alpha);
-}
-
-// Tile pixbuf |src| across |cr| at |x|, |y| for |width| and |height|.
-void TileImage(cairo_t* cr, GdkPixbuf* src,
-               int x, int y, int width, int height, double alpha) {
-  if (alpha == 1.0) {
-    gdk_cairo_set_source_pixbuf(cr, src, x, y);
-    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(cr, x, y, width, height);
-    cairo_fill(cr);
-  } else {
-    // Since there is no easy way to apply a mask to a fill operation, we create
-    // a secondary surface and tile into that, then paint it with |alpha|.
-    cairo_surface_t* surface = cairo_image_surface_create(
-        CAIRO_FORMAT_ARGB32, width, height);
-    cairo_t* tiled = cairo_create(surface);
-    gdk_cairo_set_source_pixbuf(tiled, src, 0, 0);
-    cairo_pattern_set_extend(cairo_get_source(tiled), CAIRO_EXTEND_REPEAT);
-    cairo_rectangle(tiled, 0, 0, width, height);
-    cairo_fill(tiled);
-
-    cairo_set_source_surface(cr, surface, x, y);
-    cairo_paint_with_alpha(cr, alpha);
-
-    cairo_destroy(tiled);
-    cairo_surface_destroy(surface);
-  }
-}
-
-}  // namespace
-
-NineBox::NineBox(int top_left, int top, int top_right, int left, int center,
-                 int right, int bottom_left, int bottom, int bottom_right)
-    : unref_pixbufs_on_destroy_(false) {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  images_[0] = top_left ? rb.GetPixbufNamed(top_left) : NULL;
-  images_[1] = top ? rb.GetPixbufNamed(top) : NULL;
-  images_[2] = top_right ? rb.GetPixbufNamed(top_right) : NULL;
-  images_[3] = left ? rb.GetPixbufNamed(left) : NULL;
-  images_[4] = center ? rb.GetPixbufNamed(center) : NULL;
-  images_[5] = right ? rb.GetPixbufNamed(right) : NULL;
-  images_[6] = bottom_left ? rb.GetPixbufNamed(bottom_left) : NULL;
-  images_[7] = bottom ? rb.GetPixbufNamed(bottom) : NULL;
-  images_[8] = bottom_right ? rb.GetPixbufNamed(bottom_right) : NULL;
-}
-
-NineBox::NineBox(int image, int top_margin, int bottom_margin, int left_margin,
-                 int right_margin)
-    : unref_pixbufs_on_destroy_(true) {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  GdkPixbuf* pixbuf = rb.GetPixbufNamed(image);
-  int width = gdk_pixbuf_get_width(pixbuf);
-  int height = gdk_pixbuf_get_height(pixbuf);
-  int inset_width = left_margin + right_margin;
-  int inset_height = top_margin + bottom_margin;
-
-  images_[0] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, 0, left_margin, top_margin);
-  images_[1] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, 0,
-                                        width - inset_width, top_margin);
-  images_[2] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin, 0,
-                                        right_margin, top_margin);
-  images_[3] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, top_margin,
-                                        left_margin, height - inset_height);
-  images_[4] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, top_margin,
-                                        width - inset_width,
-                                        height - inset_height);
-  images_[5] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin,
-                                        top_margin, right_margin,
-                                        height - inset_height);
-  images_[6] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, height - bottom_margin,
-                                        left_margin, bottom_margin);
-  images_[7] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin,
-                                        height - bottom_margin,
-                                        width - inset_width, bottom_margin);
-  images_[8] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin,
-                                        height - bottom_margin,
-                                        right_margin, bottom_margin);
-}
-
-NineBox::~NineBox() {
-  if (unref_pixbufs_on_destroy_) {
-    for (int i = 0; i < 9; i++) {
-      g_object_unref(images_[i]);
-    }
-  }
-}
-
-void NineBox::RenderToWidget(GtkWidget* dst) const {
-  RenderToWidgetWithOpacity(dst, 1.0);
-}
-
-void NineBox::RenderToWidgetWithOpacity(GtkWidget* dst, double opacity) const {
-  int dst_width = dst->allocation.width;
-  int dst_height = dst->allocation.height;
-
-  // The upper-left and lower-right corners of the center square in the
-  // rendering of the ninebox.
-  int x1 = gdk_pixbuf_get_width(images_[0]);
-  int y1 = gdk_pixbuf_get_height(images_[0]);
-  int x2 = images_[2] ? dst_width - gdk_pixbuf_get_width(images_[2]) : x1;
-  int y2 = images_[6] ? dst_height - gdk_pixbuf_get_height(images_[6]) : y1;
-  // Paint nothing if there's not enough room.
-  if (x2 < x1 || y2 < y1)
-    return;
-
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(dst->window));
-  // For widgets that have their own window, the allocation (x,y) coordinates
-  // are GdkWindow relative. For other widgets, the coordinates are relative
-  // to their container.
-  if (GTK_WIDGET_NO_WINDOW(dst)) {
-    // Transform our cairo from window to widget coordinates.
-    cairo_translate(cr, dst->allocation.x, dst->allocation.y);
-  }
-
-  if (base::i18n::IsRTL()) {
-    cairo_translate(cr, dst_width, 0.0f);
-    cairo_scale(cr, -1.0f, 1.0f);
-  }
-
-  // Top row, center image is horizontally tiled.
-  if (images_[0])
-    DrawPixbuf(cr, images_[0], 0, 0, opacity);
-  if (images_[1])
-    TileImage(cr, images_[1], x1, 0, x2 - x1, y1, opacity);
-  if (images_[2])
-    DrawPixbuf(cr, images_[2], x2, 0, opacity);
-
-  // Center row, all images are vertically tiled, center is horizontally tiled.
-  if (images_[3])
-    TileImage(cr, images_[3], 0, y1, x1, y2 - y1, opacity);
-  if (images_[4])
-    TileImage(cr, images_[4], x1, y1, x2 - x1, y2 - y1, opacity);
-  if (images_[5])
-    TileImage(cr, images_[5], x2, y1, dst_width - x2, y2 - y1, opacity);
-
-  // Bottom row, center image is horizontally tiled.
-  if (images_[6])
-    DrawPixbuf(cr, images_[6], 0, y2, opacity);
-  if (images_[7])
-    TileImage(cr, images_[7], x1, y2, x2 - x1, dst_height - y2, opacity);
-  if (images_[8])
-    DrawPixbuf(cr, images_[8], x2, y2, opacity);
-
-  cairo_destroy(cr);
-}
-
-void NineBox::RenderTopCenterStrip(cairo_t* cr, int x, int y,
-                                   int width) const {
-  const int height = gdk_pixbuf_get_height(images_[1]);
-  TileImage(cr, images_[1], x, y, width, height, 1.0);
-}
-
-void NineBox::ChangeWhiteToTransparent() {
-  for (int image_idx = 0; image_idx < 9; ++image_idx) {
-    GdkPixbuf* pixbuf = images_[image_idx];
-    if (!pixbuf)
-      continue;
-
-    if (!gdk_pixbuf_get_has_alpha(pixbuf))
-      continue;
-
-    guchar* pixels = gdk_pixbuf_get_pixels(pixbuf);
-    int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
-    int width = gdk_pixbuf_get_width(pixbuf);
-    int height = gdk_pixbuf_get_height(pixbuf);
-
-    if (width * 4 > rowstride) {
-      NOTREACHED();
-      continue;
-    }
-
-    for (int i = 0; i < height; ++i) {
-      for (int j = 0; j < width; ++j) {
-         guchar* pixel = &pixels[i * rowstride + j * 4];
-         if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) {
-           pixel[3] = 0;
-         }
-      }
-    }
-  }
-}
-
-void NineBox::ContourWidget(GtkWidget* widget) const {
-  int width = widget->allocation.width;
-  int height = widget->allocation.height;
-  int x1 = gdk_pixbuf_get_width(images_[0]);
-  int x2 = width - gdk_pixbuf_get_width(images_[2]);
-
-  // Paint the left and right sides.
-  GdkBitmap* mask = gdk_pixmap_new(NULL, width, height, 1);
-  gdk_pixbuf_render_threshold_alpha(images_[0], mask,
-                                    0, 0,
-                                    0, 0, -1, -1,
-                                    1);
-  gdk_pixbuf_render_threshold_alpha(images_[2], mask,
-                                    0, 0,
-                                    x2, 0, -1, -1,
-                                    1);
-
-  // Assume no transparency in the middle rectangle.
-  cairo_t* cr = gdk_cairo_create(mask);
-  cairo_rectangle(cr, x1, 0, x2 - x1, height);
-  cairo_fill(cr);
-  cairo_destroy(cr);
-
-  // Mask the widget's window's shape.
-  if (!base::i18n::IsRTL()) {
-    gtk_widget_shape_combine_mask(widget, mask, 0, 0);
-  } else {
-    GdkBitmap* flipped_mask = gdk_pixmap_new(NULL, width, height, 1);
-    cairo_t* flipped_cr = gdk_cairo_create(flipped_mask);
-
-    // Clear the target bitmap.
-    cairo_set_operator(flipped_cr, CAIRO_OPERATOR_CLEAR);
-    cairo_paint(flipped_cr);
-
-    // Apply flipping transformation.
-    cairo_translate(flipped_cr, width, 0.0f);
-    cairo_scale(flipped_cr, -1.0f, 1.0f);
-
-    // Paint the source bitmap onto the target.
-    cairo_set_operator(flipped_cr, CAIRO_OPERATOR_SOURCE);
-    gdk_cairo_set_source_pixmap(flipped_cr, mask, 0, 0);
-    cairo_paint(flipped_cr);
-    cairo_destroy(flipped_cr);
-
-    // Mask the widget.
-    gtk_widget_shape_combine_mask(widget, flipped_mask, 0, 0);
-    g_object_unref(flipped_mask);
-  }
-
-  g_object_unref(mask);
-}
diff --git a/chrome/browser/gtk/nine_box.h b/chrome/browser/gtk/nine_box.h
deleted file mode 100644
index ecdf44a..0000000
--- a/chrome/browser/gtk/nine_box.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_NINE_BOX_H_
-#define CHROME_BROWSER_GTK_NINE_BOX_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-// A NineBox manages a set of source images representing a 3x3 grid, where
-// non-corner images can be tiled to make a larger image.  It's used to
-// use bitmaps for constructing image-based resizable widgets like buttons.
-//
-// If you want just a vertical image that stretches in height but is fixed
-// in width, only pass in images for the left column (leave others NULL).
-// Similarly, for a horizontal image that stretches in width but is fixed in
-// height, only pass in images for the top row.
-//
-// TODO(port): add support for caching server-side pixmaps of prerendered
-// nineboxes.
-class NineBox {
- public:
-  // Construct a NineBox with nine images.  Images are specified using resource
-  // ids that will be passed to the resource bundle.  Use 0 for no image.
-  NineBox(int top_left, int top, int top_right, int left, int center, int right,
-          int bottom_left, int bottom, int bottom_right);
-
-  // Construct a NineBox from a single image and insets indicating the sizes
-  // of the edges and corners.
-  NineBox(int image, int top_margin, int bottom_margin, int left_margin,
-          int right_margin);
-  ~NineBox();
-
-  // Render the NineBox to |dst|.
-  // The images will be tiled to fit into the widget.
-  void RenderToWidget(GtkWidget* dst) const;
-
-  // As above, but rendered partially transparent.
-  void RenderToWidgetWithOpacity(GtkWidget* dst, double opacity) const;
-
-  // Render the top row of images to |dst| between |x1| and |x1| + |width|.
-  // This is split from RenderToWidget so the toolbar can use it.
-  void RenderTopCenterStrip(cairo_t* cr, int x, int y, int width) const;
-
-  // Change all pixels that are white in |images_| to have 0 opacity.
-  void ChangeWhiteToTransparent();
-
-  // Set the shape of |widget| to match that of the ninebox. Note that |widget|
-  // must have its own window and be allocated. Also, currently only the top
-  // three images are used.
-  // TODO(estade): extend this function to use all 9 images (if it's ever
-  // needed).
-  void ContourWidget(GtkWidget* widget) const;
-
- private:
-  GdkPixbuf* images_[9];
-  bool unref_pixbufs_on_destroy_;
-};
-
-#endif  // CHROME_BROWSER_GTK_NINE_BOX_H_
diff --git a/chrome/browser/gtk/notifications/balloon_view_gtk.cc b/chrome/browser/gtk/notifications/balloon_view_gtk.cc
deleted file mode 100644
index edb475e..0000000
--- a/chrome/browser/gtk/notifications/balloon_view_gtk.cc
+++ /dev/null
@@ -1,427 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/notifications/balloon_view_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_process_manager.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/notifications/balloon_view_host_gtk.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "chrome/browser/notifications/balloon.h"
-#include "chrome/browser/notifications/desktop_notification_service.h"
-#include "chrome/browser/notifications/notification.h"
-#include "chrome/browser/notifications/notification_options_menu_model.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "gfx/canvas.h"
-#include "gfx/insets.h"
-#include "gfx/native_widget_types.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-// Margin, in pixels, between the notification frame and the contents
-// of the notification.
-const int kTopMargin = 0;
-const int kBottomMargin = 1;
-const int kLeftMargin = 1;
-const int kRightMargin = 1;
-
-// How many pixels of overlap there is between the shelf top and the
-// balloon bottom.
-const int kShelfBorderTopOverlap = 0;
-
-// Properties of the origin label.
-const int kLeftLabelMargin = 8;
-
-// TODO(johnnyg): Add a shadow for the frame.
-const int kLeftShadowWidth = 0;
-const int kRightShadowWidth = 0;
-const int kTopShadowWidth = 0;
-const int kBottomShadowWidth = 0;
-
-// Space in pixels between text and icon on the buttons.
-const int kButtonSpacing = 4;
-
-// Number of characters to show in the origin label before ellipsis.
-const int kOriginLabelCharacters = 18;
-
-// The shelf height for the system default font size.  It is scaled
-// with changes in the default font size.
-const int kDefaultShelfHeight = 21;
-const int kShelfVerticalMargin = 4;
-
-// The amount that the bubble collections class offsets from the side of the
-// screen.
-const int kScreenBorder = 5;
-
-// Colors specified in various ways for different parts of the UI.
-// These match the windows colors in balloon_view.cc
-const char* kLabelColor = "#7D7D7D";
-const double kShelfBackgroundColorR = 245.0 / 255.0;
-const double kShelfBackgroundColorG = 245.0 / 255.0;
-const double kShelfBackgroundColorB = 245.0 / 255.0;
-const double kDividerLineColorR = 180.0 / 255.0;
-const double kDividerLineColorG = 180.0 / 255.0;
-const double kDividerLineColorB = 180.0 / 255.0;
-
-// Makes the website label relatively smaller to the base text size.
-const char* kLabelMarkup = "<span size=\"small\" color=\"%s\">%s</span>";
-
-}  // namespace
-
-BalloonViewImpl::BalloonViewImpl(BalloonCollection* collection)
-    : balloon_(NULL),
-      frame_container_(NULL),
-      html_container_(NULL),
-      method_factory_(this),
-      close_button_(NULL),
-      animation_(NULL) {
-}
-
-BalloonViewImpl::~BalloonViewImpl() {
-}
-
-void BalloonViewImpl::Close(bool by_user) {
-  MessageLoop::current()->PostTask(FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &BalloonViewImpl::DelayedClose, by_user));
-}
-
-gfx::Size BalloonViewImpl::GetSize() const {
-  // BalloonView has no size if it hasn't been shown yet (which is when
-  // balloon_ is set).
-  if (!balloon_)
-    return gfx::Size();
-
-  // Although this may not be the instantaneous size of the balloon if
-  // called in the middle of an animation, it is the effective size that
-  // will result from the animation.
-  return gfx::Size(GetDesiredTotalWidth(), GetDesiredTotalHeight());
-}
-
-BalloonHost* BalloonViewImpl::GetHost() const {
-  return html_contents_.get();
-}
-
-void BalloonViewImpl::DelayedClose(bool by_user) {
-  html_contents_->Shutdown();
-  if (frame_container_) {
-    // It's possible that |frame_container_| was destroyed before the
-    // BalloonViewImpl if our related browser window was closed first.
-    gtk_widget_hide(frame_container_);
-  }
-  balloon_->OnClose(by_user);
-}
-
-void BalloonViewImpl::RepositionToBalloon() {
-  if (!frame_container_) {
-    // No need to create a slide animation when this balloon is fading out.
-    return;
-  }
-
-  DCHECK(balloon_);
-
-  // Create an amination from the current position to the desired one.
-  int start_x;
-  int start_y;
-  int start_w;
-  int start_h;
-  gtk_window_get_position(GTK_WINDOW(frame_container_), &start_x, &start_y);
-  gtk_window_get_size(GTK_WINDOW(frame_container_), &start_w, &start_h);
-
-  int end_x = balloon_->GetPosition().x();
-  int end_y = balloon_->GetPosition().y();
-  int end_w = GetDesiredTotalWidth();
-  int end_h = GetDesiredTotalHeight();
-
-  anim_frame_start_ = gfx::Rect(start_x, start_y, start_w, start_h);
-  anim_frame_end_ = gfx::Rect(end_x, end_y, end_w, end_h);
-  animation_.reset(new ui::SlideAnimation(this));
-  animation_->Show();
-}
-
-void BalloonViewImpl::AnimationProgressed(const ui::Animation* animation) {
-  DCHECK_EQ(animation, animation_.get());
-
-  // Linear interpolation from start to end position.
-  double end = animation->GetCurrentValue();
-  double start = 1.0 - end;
-
-  gfx::Rect frame_position(
-      static_cast<int>(start * anim_frame_start_.x() +
-                       end * anim_frame_end_.x()),
-      static_cast<int>(start * anim_frame_start_.y() +
-                       end * anim_frame_end_.y()),
-      static_cast<int>(start * anim_frame_start_.width() +
-                       end * anim_frame_end_.width()),
-      static_cast<int>(start * anim_frame_start_.height() +
-                       end * anim_frame_end_.height()));
-  gtk_window_resize(GTK_WINDOW(frame_container_),
-                    frame_position.width(), frame_position.height());
-  gtk_window_move(GTK_WINDOW(frame_container_),
-                  frame_position.x(), frame_position.y());
-
-  gfx::Rect contents_rect = GetContentsRectangle();
-  html_contents_->UpdateActualSize(contents_rect.size());
-}
-
-void BalloonViewImpl::Show(Balloon* balloon) {
-  theme_provider_ = GtkThemeProvider::GetFrom(balloon->profile());
-
-  const std::string source_label_text = l10n_util::GetStringFUTF8(
-      IDS_NOTIFICATION_BALLOON_SOURCE_LABEL,
-      balloon->notification().display_source());
-  const std::string options_text =
-      l10n_util::GetStringUTF8(IDS_NOTIFICATION_OPTIONS_MENU_LABEL);
-  const std::string dismiss_text =
-      l10n_util::GetStringUTF8(IDS_NOTIFICATION_BALLOON_DISMISS_LABEL);
-
-  balloon_ = balloon;
-  frame_container_ = gtk_window_new(GTK_WINDOW_POPUP);
-
-  // Construct the options menu.
-  options_menu_model_.reset(new NotificationOptionsMenuModel(balloon_));
-  options_menu_.reset(new MenuGtk(this, options_menu_model_.get()));
-
-  // Create a BalloonViewHost to host the HTML contents of this balloon.
-  html_contents_.reset(new BalloonViewHost(balloon));
-  html_contents_->Init();
-  gfx::NativeView contents = html_contents_->native_view();
-
-  // Divide the frame vertically into the shelf and the content area.
-  GtkWidget* vbox = gtk_vbox_new(0, 0);
-  gtk_container_add(GTK_CONTAINER(frame_container_), vbox);
-
-  shelf_ = gtk_hbox_new(0, 0);
-  gtk_container_add(GTK_CONTAINER(vbox), shelf_);
-
-  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(
-      GTK_ALIGNMENT(alignment),
-      kTopMargin, kBottomMargin, kLeftMargin, kRightMargin);
-  gtk_widget_show_all(alignment);
-  gtk_container_add(GTK_CONTAINER(alignment), contents);
-  gtk_container_add(GTK_CONTAINER(vbox), alignment);
-
-  // Create a toolbar and add it to the shelf.
-  hbox_ = gtk_hbox_new(FALSE, 0);
-  gtk_widget_set_size_request(GTK_WIDGET(hbox_), -1, GetShelfHeight());
-  gtk_container_add(GTK_CONTAINER(shelf_), hbox_);
-  gtk_widget_show_all(vbox);
-
-  g_signal_connect(frame_container_, "expose-event",
-                   G_CALLBACK(OnExposeThunk), this);
-  g_signal_connect(frame_container_, "destroy",
-                   G_CALLBACK(OnDestroyThunk), this);
-
-  // Create a label for the source of the notification and add it to the
-  // toolbar.
-  GtkWidget* source_label_ = gtk_label_new(NULL);
-  char* markup = g_markup_printf_escaped(kLabelMarkup,
-                                         kLabelColor,
-                                         source_label_text.c_str());
-  gtk_label_set_markup(GTK_LABEL(source_label_), markup);
-  g_free(markup);
-  gtk_label_set_max_width_chars(GTK_LABEL(source_label_),
-                                kOriginLabelCharacters);
-  gtk_label_set_ellipsize(GTK_LABEL(source_label_), PANGO_ELLIPSIZE_END);
-  GtkWidget* label_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(label_alignment),
-                            kShelfVerticalMargin, kShelfVerticalMargin,
-                            kLeftLabelMargin, 0);
-  gtk_container_add(GTK_CONTAINER(label_alignment), source_label_);
-  gtk_box_pack_start(GTK_BOX(hbox_), label_alignment, FALSE, FALSE, 0);
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  // Create a button to dismiss the balloon and add it to the toolbar.
-  close_button_.reset(new CustomDrawButton(IDR_TAB_CLOSE,
-                                           IDR_TAB_CLOSE_P,
-                                           IDR_TAB_CLOSE_H,
-                                           IDR_TAB_CLOSE));
-  close_button_->SetBackground(SK_ColorBLACK,
-                               rb.GetBitmapNamed(IDR_TAB_CLOSE),
-                               rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
-  gtk_widget_set_tooltip_text(close_button_->widget(), dismiss_text.c_str());
-  g_signal_connect(close_button_->widget(), "clicked",
-                   G_CALLBACK(OnCloseButtonThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(close_button_->widget(), GTK_CAN_FOCUS);
-  GtkWidget* close_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(close_alignment),
-                            kShelfVerticalMargin, kShelfVerticalMargin,
-                            0, kButtonSpacing);
-  gtk_container_add(GTK_CONTAINER(close_alignment), close_button_->widget());
-  gtk_box_pack_end(GTK_BOX(hbox_), close_alignment, FALSE, FALSE, 0);
-
-  // Create a button for showing the options menu, and add it to the toolbar.
-  options_menu_button_.reset(new CustomDrawButton(IDR_BALLOON_WRENCH,
-                                                  IDR_BALLOON_WRENCH_P,
-                                                  IDR_BALLOON_WRENCH_H,
-                                                  0));
-  gtk_widget_set_tooltip_text(options_menu_button_->widget(),
-                              options_text.c_str());
-  g_signal_connect(options_menu_button_->widget(), "clicked",
-                   G_CALLBACK(OnOptionsMenuButtonThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(options_menu_button_->widget(), GTK_CAN_FOCUS);
-  GtkWidget* options_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(options_alignment),
-                            kShelfVerticalMargin, kShelfVerticalMargin,
-                            0, kButtonSpacing);
-  gtk_container_add(GTK_CONTAINER(options_alignment),
-                    options_menu_button_->widget());
-  gtk_box_pack_end(GTK_BOX(hbox_), options_alignment, FALSE, FALSE, 0);
-
-  notification_registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                              NotificationService::AllSources());
-
-  // We don't do InitThemesFor() because it just forces a redraw.
-  gtk_util::ActAsRoundedWindow(frame_container_, gtk_util::kGdkBlack, 3,
-                               gtk_util::ROUNDED_ALL,
-                               gtk_util::BORDER_ALL);
-
-  // Realize the frame container so we can do size calculations.
-  gtk_widget_realize(frame_container_);
-
-  // Update to make sure we have everything sized properly and then move our
-  // window offscreen for its initial animation.
-  html_contents_->UpdateActualSize(balloon_->content_size());
-  int window_width;
-  gtk_window_get_size(GTK_WINDOW(frame_container_), &window_width, NULL);
-
-  int pos_x = gdk_screen_width() - window_width - kScreenBorder;
-  int pos_y = gdk_screen_height();
-  gtk_window_move(GTK_WINDOW(frame_container_), pos_x, pos_y);
-  balloon_->SetPosition(gfx::Point(pos_x, pos_y), false);
-  gtk_widget_show_all(frame_container_);
-
-  notification_registrar_.Add(this,
-      NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon));
-}
-
-void BalloonViewImpl::Update() {
-  DCHECK(html_contents_.get()) << "BalloonView::Update called before Show";
-  if (html_contents_->render_view_host())
-    html_contents_->render_view_host()->NavigateToURL(
-        balloon_->notification().content_url());
-}
-
-gfx::Point BalloonViewImpl::GetContentsOffset() const {
-  return gfx::Point(kLeftShadowWidth + kLeftMargin,
-                    GetShelfHeight() + kTopShadowWidth + kTopMargin);
-}
-
-int BalloonViewImpl::GetShelfHeight() const {
-  // TODO(johnnyg): add scaling here.
-  return kDefaultShelfHeight;
-}
-
-int BalloonViewImpl::GetDesiredTotalWidth() const {
-  return balloon_->content_size().width() +
-      kLeftMargin + kRightMargin + kLeftShadowWidth + kRightShadowWidth;
-}
-
-int BalloonViewImpl::GetDesiredTotalHeight() const {
-  return balloon_->content_size().height() +
-      kTopMargin + kBottomMargin + kTopShadowWidth + kBottomShadowWidth +
-      GetShelfHeight();
-}
-
-gfx::Rect BalloonViewImpl::GetContentsRectangle() const {
-  if (!frame_container_)
-    return gfx::Rect();
-
-  gfx::Size content_size = balloon_->content_size();
-  gfx::Point offset = GetContentsOffset();
-  int x = 0, y = 0;
-  gtk_window_get_position(GTK_WINDOW(frame_container_), &x, &y);
-  return gfx::Rect(x + offset.x(), y + offset.y(),
-                   content_size.width(), content_size.height());
-}
-
-void BalloonViewImpl::Observe(NotificationType type,
-                              const NotificationSource& source,
-                              const NotificationDetails& details) {
-  if (type == NotificationType::NOTIFY_BALLOON_DISCONNECTED) {
-    // If the renderer process attached to this balloon is disconnected
-    // (e.g., because of a crash), we want to close the balloon.
-    notification_registrar_.Remove(this,
-        NotificationType::NOTIFY_BALLOON_DISCONNECTED,
-        Source<Balloon>(balloon_));
-    Close(false);
-  } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    // Since all the buttons change their own properties, and our expose does
-    // all the real differences, we'll need a redraw.
-    gtk_widget_queue_draw(frame_container_);
-  } else {
-    NOTREACHED();
-  }
-}
-
-void BalloonViewImpl::OnCloseButton(GtkWidget* widget) {
-  Close(true);
-}
-
-gboolean BalloonViewImpl::OnExpose(GtkWidget* sender, GdkEventExpose* event) {
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-
-  gfx::Size content_size = balloon_->content_size();
-  gfx::Point offset = GetContentsOffset();
-
-  // Draw a background color behind the shelf.
-  cairo_set_source_rgb(cr, kShelfBackgroundColorR,
-                       kShelfBackgroundColorG, kShelfBackgroundColorB);
-  cairo_rectangle(cr, kLeftMargin, kTopMargin + 0.5,
-                  content_size.width() - 0.5, GetShelfHeight());
-  cairo_fill(cr);
-
-  // Now draw a one pixel line between content and shelf.
-  cairo_move_to(cr, offset.x(), offset.y() - 1);
-  cairo_line_to(cr, offset.x() + content_size.width(), offset.y() - 1);
-  cairo_set_line_width(cr, 0.5);
-  cairo_set_source_rgb(cr, kDividerLineColorR,
-                       kDividerLineColorG, kDividerLineColorB);
-  cairo_stroke(cr);
-
-  cairo_destroy(cr);
-
-  return FALSE;
-}
-
-void BalloonViewImpl::OnOptionsMenuButton(GtkWidget* widget) {
-  options_menu_->PopupAsContext(gtk_get_current_event_time());
-}
-
-gboolean BalloonViewImpl::OnDestroy(GtkWidget* widget) {
-  frame_container_ = NULL;
-  Close(false);
-  return FALSE;  // Propagate.
-}
diff --git a/chrome/browser/gtk/notifications/balloon_view_gtk.h b/chrome/browser/gtk/notifications/balloon_view_gtk.h
deleted file mode 100644
index 0db221b..0000000
--- a/chrome/browser/gtk/notifications/balloon_view_gtk.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Draws the view for the balloons.
-
-#ifndef CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_
-#define CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/gtk/notifications/balloon_view_host_gtk.h"
-#include "chrome/browser/notifications/balloon.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
-#include "ui/base/animation/animation_delegate.h"
-
-class BalloonCollection;
-class CustomDrawButton;
-class GtkThemeProvider;
-class MenuGtk;
-class NotificationDetails;
-class NotificationOptionsMenuModel;
-class NotificationSource;
-
-namespace ui {
-class SlideAnimation;
-}
-
-// A balloon view is the UI component for desktop notification toasts.
-// It draws a border, and within the border an HTML renderer.
-class BalloonViewImpl : public BalloonView,
-                        public MenuGtk::Delegate,
-                        public NotificationObserver,
-                        public ui::AnimationDelegate {
- public:
-  explicit BalloonViewImpl(BalloonCollection* collection);
-  ~BalloonViewImpl();
-
-  // BalloonView interface.
-  virtual void Show(Balloon* balloon);
-  virtual void Update();
-  virtual void RepositionToBalloon();
-  virtual void Close(bool by_user);
-  virtual gfx::Size GetSize() const;
-  virtual BalloonHost* GetHost() const;
-
- private:
-  // NotificationObserver interface.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // ui::AnimationDelegate interface.
-  virtual void AnimationProgressed(const ui::Animation* animation);
-
-  // Do the delayed close work.
-  void DelayedClose(bool by_user);
-
-  // The height of the balloon's shelf.
-  // The shelf is where is close button is located.
-  int GetShelfHeight() const;
-
-  // The width and height that the frame should be.  If the balloon inside
-  // changes size, this will not be the same as the actual frame size until
-  // RepositionToBalloon() has been called and the animation completes.
-  int GetDesiredTotalWidth() const;
-  int GetDesiredTotalHeight() const;
-
-  // Where the balloon contents should be placed with respect to the top left
-  // of the frame.
-  gfx::Point GetContentsOffset() const;
-
-  // Where the balloon contents should be in screen coordinates.
-  gfx::Rect GetContentsRectangle() const;
-
-  CHROMEGTK_CALLBACK_0(BalloonViewImpl, void, OnCloseButton);
-  CHROMEGTK_CALLBACK_1(BalloonViewImpl, gboolean, OnExpose, GdkEventExpose*);
-  CHROMEGTK_CALLBACK_0(BalloonViewImpl, void, OnOptionsMenuButton);
-  CHROMEGTK_CALLBACK_0(BalloonViewImpl, gboolean, OnDestroy);
-
-  // Non-owned pointer to the balloon which owns this object.
-  Balloon* balloon_;
-
-  GtkThemeProvider* theme_provider_;
-
-  // The window that contains the frame of the notification.
-  GtkWidget* frame_container_;
-
-  // The widget that contains the shelf.
-  GtkWidget* shelf_;
-
-  // The hbox within the shelf that contains the buttons.
-  GtkWidget* hbox_;
-
-  // The window that contains the contents of the notification.
-  GtkWidget* html_container_;
-
-  // The renderer of the HTML contents.
-  scoped_ptr<BalloonViewHost> html_contents_;
-
-  // The following factory is used to call methods at a later time.
-  ScopedRunnableMethodFactory<BalloonViewImpl> method_factory_;
-
-  // Close button.
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  // An animation to move the balloon on the screen as its position changes.
-  scoped_ptr<ui::SlideAnimation> animation_;
-  gfx::Rect anim_frame_start_;
-  gfx::Rect anim_frame_end_;
-
-  // The options menu.
-  scoped_ptr<MenuGtk> options_menu_;
-  scoped_ptr<NotificationOptionsMenuModel> options_menu_model_;
-  // The button to open the options menu.
-  scoped_ptr<CustomDrawButton> options_menu_button_;
-
-  NotificationRegistrar notification_registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(BalloonViewImpl);
-};
-
-#endif  // CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_
diff --git a/chrome/browser/gtk/notifications/balloon_view_host_gtk.cc b/chrome/browser/gtk/notifications/balloon_view_host_gtk.cc
deleted file mode 100644
index 4bd7482..0000000
--- a/chrome/browser/gtk/notifications/balloon_view_host_gtk.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/notifications/balloon_view_host_gtk.h"
-
-#include "chrome/browser/notifications/balloon.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
-
-BalloonViewHost::BalloonViewHost(Balloon* balloon)
-    : BalloonHost(balloon),
-      render_widget_host_view_(NULL) {
-}
-
-void BalloonViewHost::UpdateActualSize(const gfx::Size& new_size) {
-  render_widget_host_view_->SetSize(new_size);
-  gtk_widget_set_size_request(
-      native_view(), new_size.width(), new_size.height());
-}
-
-gfx::NativeView BalloonViewHost::native_view() const {
-  return render_widget_host_view_->native_view();
-}
-
-void BalloonViewHost::InitRenderWidgetHostView() {
-  DCHECK(render_view_host_);
-  render_widget_host_view_ = new RenderWidgetHostViewGtk(render_view_host_);
-  render_widget_host_view_->InitAsChild();
-}
-
-RenderWidgetHostView* BalloonViewHost::render_widget_host_view() const {
-  return render_widget_host_view_;
-}
diff --git a/chrome/browser/gtk/notifications/balloon_view_host_gtk.h b/chrome/browser/gtk/notifications/balloon_view_host_gtk.h
deleted file mode 100644
index 75dfb92..0000000
--- a/chrome/browser/gtk/notifications/balloon_view_host_gtk.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_HOST_GTK_H_
-#define CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_HOST_GTK_H_
-#pragma once
-
-#include "chrome/browser/notifications/balloon_host.h"
-#include "gfx/native_widget_types.h"
-
-class RenderWidgetHostViewGtk;
-
-// BalloonViewHost class is a delegate to the renderer host for the HTML
-// notification.  When initialized it creates a new RenderViewHost and loads
-// the contents of the toast into it.  It also handles links within the toast,
-// loading them into a new tab.
-class BalloonViewHost : public BalloonHost {
- public:
-  explicit BalloonViewHost(Balloon* balloon);
-
-  ~BalloonViewHost() {
-    Shutdown();
-  }
-
-  // Changes the size of the balloon.
-  void UpdateActualSize(const gfx::Size& new_size);
-
-  // Accessors.
-  gfx::NativeView native_view() const;
-
- protected:
-  virtual void InitRenderWidgetHostView();
-  virtual RenderWidgetHostView* render_widget_host_view() const;
-
- private:
-  // The GTK-specific widget host view.  Owned by its native view.
-  RenderWidgetHostViewGtk* render_widget_host_view_;
-
-  DISALLOW_COPY_AND_ASSIGN(BalloonViewHost);
-};
-
-#endif  // CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_HOST_GTK_H_
diff --git a/chrome/browser/gtk/options/advanced_contents_gtk.cc b/chrome/browser/gtk/options/advanced_contents_gtk.cc
deleted file mode 100644
index 5ffdee5..0000000
--- a/chrome/browser/gtk/options/advanced_contents_gtk.cc
+++ /dev/null
@@ -1,1236 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/advanced_contents_gtk.h"
-
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/process_util.h"
-#include "base/string_tokenizer.h"
-#include "base/nix/xdg_util.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/download/download_prefs.h"
-#include "chrome/browser/fonts_languages_window.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
-#include "chrome/browser/gtk/options/options_layout_gtk.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/prefs/pref_set_observer.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-#include "chrome/browser/ui/options/options_util.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/process_watcher.h"
-#include "chrome/common/url_constants.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Command used to configure GNOME proxy settings. The command was renamed
-// in January 2009, so both are used to work on both old and new systems.
-const char* kOldGNOMEProxyConfigCommand[] = {"gnome-network-preferences", NULL};
-const char* kGNOMEProxyConfigCommand[] = {"gnome-network-properties", NULL};
-// KDE3 and KDE4 are only slightly different, but incompatible. Go figure.
-const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL};
-const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL};
-
-// The URL for Linux ssl certificate configuration help.
-const char* const kLinuxCertificatesConfigUrl =
-    "http://code.google.com/p/chromium/wiki/LinuxCertManagement";
-
-// The URL for Linux proxy configuration help when not running under a
-// supported desktop environment.
-const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config";
-
-// The pixel width we wrap labels at.
-// TODO(evanm): make the labels wrap at the appropriate width.
-#if defined(OS_CHROMEOS)
-// ChromeOS uses IDS_OPTIONS_DIALOG_WIDTH_CHARS for options dialog width, which
-// is slightly smaller than the Gtk options dialog's 500px.
-const int kWrapWidth = 445;
-#else
-const int kWrapWidth = 475;
-#endif
-
-GtkWidget* CreateWrappedLabel(int string_id) {
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(string_id).c_str());
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-  gtk_util::SetLabelWidth(label, kWrapWidth);
-  return label;
-}
-
-GtkWidget* CreateCheckButtonWithWrappedLabel(int string_id) {
-  GtkWidget* checkbox = gtk_check_button_new();
-  gtk_container_add(GTK_CONTAINER(checkbox),
-                    CreateWrappedLabel(string_id));
-  return checkbox;
-}
-
-GtkWidget* AddCheckButtonWithWrappedLabel(int string_id,
-                                          GtkWidget* container,
-                                          GCallback handler,
-                                          gpointer data) {
-  GtkWidget* checkbox = CreateCheckButtonWithWrappedLabel(string_id);
-  gtk_box_pack_start(GTK_BOX(container), checkbox, FALSE, FALSE, 0);
-  g_signal_connect(checkbox, "toggled", handler, data);
-
-  return checkbox;
-}
-
-// Don't let the widget handle scroll events. Instead, pass it on to the
-// parent widget.
-gboolean PassScrollToParent(GtkWidget* widget, GdkEvent* event,
-                            gpointer unused) {
-  if (widget->parent)
-    gtk_propagate_event(widget->parent, event);
-
-  return TRUE;
-}
-
-// Recursively search for a combo box among the children of |widget|.
-void SearchForComboBox(GtkWidget* widget, gpointer data) {
-  if (GTK_IS_COMBO_BOX(widget)) {
-    *reinterpret_cast<GtkWidget**>(data) = widget;
-  } else if (GTK_IS_CONTAINER(widget)) {
-    gtk_container_foreach(GTK_CONTAINER(widget), SearchForComboBox, data);
-  }
-}
-
-// Letting the combo boxes in the advanced options page handle scroll events is
-// annoying because they fight with the scrolled window. Also,
-// GtkFileChooserButton is buggy in that if you scroll on it very quickly it
-// spews Gtk-WARNINGs, which causes us to crash in debug. This function disables
-// scrolling for the combo box in |widget| (the first one it finds in a DFS).
-void DisableScrolling(GtkWidget* widget) {
-  gpointer combo_box_ptr = NULL;
-  SearchForComboBox(widget, &combo_box_ptr);
-
-  if (!combo_box_ptr) {
-    NOTREACHED() << " Did not find a combo box in this widget.";
-    return;
-  }
-
-  g_signal_connect(GTK_WIDGET(combo_box_ptr), "scroll-event",
-                   G_CALLBACK(PassScrollToParent), NULL);
-}
-
-}  // anonymous namespace
-
-
-///////////////////////////////////////////////////////////////////////////////
-// DownloadSection
-
-class DownloadSection : public OptionsPageBase {
- public:
-  explicit DownloadSection(Profile* profile);
-  virtual ~DownloadSection() {}
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  // Callbacks for the widgets.
-  static void OnDownloadLocationChanged(GtkFileChooser* widget,
-                                        DownloadSection* section);
-  static void OnDownloadAskForSaveLocationChanged(GtkWidget* widget,
-                                                  DownloadSection* section);
-  static void OnResetFileHandlersClicked(GtkButton *button,
-                                         DownloadSection* section);
-
-  // The widgets for the download options.
-  GtkWidget* download_location_button_;
-  GtkWidget* download_ask_for_save_location_checkbox_;
-  GtkWidget* reset_file_handlers_label_;
-  GtkWidget* reset_file_handlers_button_;
-
-  // The widget containing the options for this section.
-  GtkWidget* page_;
-
-  // Pref members.
-  FilePathPrefMember default_download_location_;
-  BooleanPrefMember ask_for_save_location_;
-  StringPrefMember auto_open_files_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool pref_changing_;
-
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloadSection);
-};
-
-DownloadSection::DownloadSection(Profile* profile)
-    : OptionsPageBase(profile),
-      pref_changing_(true) {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      page_, profile));
-
-  // Download location options.
-  download_location_button_ = gtk_file_chooser_button_new(
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE).c_str(),
-      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-  g_signal_connect(download_location_button_, "selection-changed",
-                   G_CALLBACK(OnDownloadLocationChanged), this);
-  DisableScrolling(download_location_button_);
-
-  // Add the default download path to the list of shortcuts in the selector.
-  FilePath default_download_path;
-  if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
-                        &default_download_path)) {
-    NOTREACHED();
-  } else {
-    if (!gtk_file_chooser_add_shortcut_folder(
-        GTK_FILE_CHOOSER(download_location_button_),
-        default_download_path.value().c_str(),
-        NULL)) {
-      NOTREACHED();
-    }
-  }
-
-  GtkWidget* download_location_control = gtk_util::CreateLabeledControlsGroup(
-      NULL,
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE).c_str(),
-      download_location_button_,
-      NULL);
-  gtk_box_pack_start(GTK_BOX(page_), download_location_control,
-                     FALSE, FALSE, 0);
-
-  download_ask_for_save_location_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION);
-  gtk_box_pack_start(GTK_BOX(page_), download_ask_for_save_location_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(download_ask_for_save_location_checkbox_, "clicked",
-                   G_CALLBACK(OnDownloadAskForSaveLocationChanged), this);
-  accessible_widget_helper_->SetWidgetName(
-      download_ask_for_save_location_checkbox_,
-      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION);
-
-  // Option for resetting file handlers.
-  reset_file_handlers_label_ = CreateWrappedLabel(
-      IDS_OPTIONS_AUTOOPENFILETYPES_INFO);
-  gtk_misc_set_alignment(GTK_MISC(reset_file_handlers_label_), 0, 0);
-  gtk_box_pack_start(GTK_BOX(page_), reset_file_handlers_label_,
-                     FALSE, FALSE, 0);
-
-  reset_file_handlers_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT).c_str());
-  g_signal_connect(reset_file_handlers_button_, "clicked",
-                   G_CALLBACK(OnResetFileHandlersClicked), this);
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(button_hbox),
-                     reset_file_handlers_button_,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(page_),
-                     gtk_util::IndentWidget(button_hbox),
-                     FALSE, FALSE, 0);
-
-  // Init prefs watchers.
-  default_download_location_.Init(prefs::kDownloadDefaultDirectory,
-                                  profile->GetPrefs(), this);
-  ask_for_save_location_.Init(prefs::kPromptForDownload,
-                              profile->GetPrefs(), this);
-  auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, profile->GetPrefs(),
-                        this);
-
-  NotifyPrefChanged(NULL);
-}
-
-void DownloadSection::NotifyPrefChanged(const std::string* pref_name) {
-  pref_changing_ = true;
-  if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) {
-    gtk_file_chooser_set_current_folder(
-        GTK_FILE_CHOOSER(download_location_button_),
-            default_download_location_.GetValue().value().c_str());
-  }
-
-  if (!pref_name || *pref_name == prefs::kPromptForDownload) {
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(download_ask_for_save_location_checkbox_),
-        ask_for_save_location_.GetValue());
-  }
-
-  if (!pref_name || *pref_name == prefs::kDownloadExtensionsToOpen) {
-    DownloadPrefs* prefs = profile()->GetDownloadManager()->download_prefs();
-    bool enabled = prefs->IsAutoOpenUsed();
-    gtk_widget_set_sensitive(reset_file_handlers_label_, enabled);
-    gtk_widget_set_sensitive(reset_file_handlers_button_, enabled);
-  }
-  pref_changing_ = false;
-}
-
-// static
-void DownloadSection::OnDownloadLocationChanged(GtkFileChooser* widget,
-                                                DownloadSection* section) {
-  if (section->pref_changing_)
-    return;
-
-  gchar* folder = gtk_file_chooser_get_filename(widget);
-  FilePath path(folder);
-  g_free(folder);
-  // Gtk seems to call this signal multiple times, so we only set the pref and
-  // metric if something actually changed.
-  if (path != section->default_download_location_.GetValue()) {
-    section->default_download_location_.SetValue(path);
-    section->UserMetricsRecordAction(
-        UserMetricsAction("Options_SetDownloadDirectory"),
-        section->profile()->GetPrefs());
-  }
-}
-
-// static
-void DownloadSection::OnDownloadAskForSaveLocationChanged(
-    GtkWidget* widget, DownloadSection* section) {
-  if (section->pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  if (enabled) {
-    section->UserMetricsRecordAction(
-        UserMetricsAction("Options_AskForSaveLocation_Enable"),
-        section->profile()->GetPrefs());
-  } else {
-    section->UserMetricsRecordAction(
-        UserMetricsAction("Options_AskForSaveLocation_Disable"),
-        section->profile()->GetPrefs());
-  }
-  section->ask_for_save_location_.SetValue(enabled);
-}
-
-// static
-void DownloadSection::OnResetFileHandlersClicked(GtkButton *button,
-                                                 DownloadSection* section) {
-  section->profile()->GetDownloadManager()->download_prefs()->ResetAutoOpen();
-  section->UserMetricsRecordAction(
-      UserMetricsAction("Options_ResetAutoOpenFiles"),
-      section->profile()->GetPrefs());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NetworkSection
-
-class NetworkSection : public OptionsPageBase {
- public:
-  explicit NetworkSection(Profile* profile);
-  virtual ~NetworkSection() {}
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  struct ProxyConfigCommand {
-    std::string binary;
-    const char** argv;
-  };
-  // The callback functions for invoking the proxy config dialog.
-  static void OnChangeProxiesButtonClicked(GtkButton *button,
-                                           NetworkSection* section);
-  // Detect, and if possible, start the appropriate proxy config utility. On
-  // failure to do so, show the Linux proxy config URL in a new tab instead.
-  static void DetectAndStartProxyConfigUtil(Profile* profile);
-  // Show the proxy config URL in a new tab.
-  static void ShowLinuxProxyConfigUrl(Profile* profile);
-  // Search $PATH to find one of the commands. Store the full path to
-  // it in the |binary| field and the command array index in in |index|.
-  static bool SearchPATH(ProxyConfigCommand* commands, size_t ncommands,
-                         size_t* index);
-  // Start the given proxy configuration utility.
-  static void StartProxyConfigUtil(Profile* profile,
-                                   const ProxyConfigCommand& command);
-
-  // Tracks the state of proxy preferences.
-  scoped_ptr<PrefSetObserver> proxy_prefs_;
-
-  // The widget containing the options for this section.
-  GtkWidget* page_;
-
-  // The proxy configuration button.
-  GtkWidget* change_proxies_button_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkSection);
-};
-
-NetworkSection::NetworkSection(Profile* profile)
-    : OptionsPageBase(profile) {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GtkWidget* proxy_description_label = CreateWrappedLabel(
-      IDS_OPTIONS_PROXIES_LABEL);
-  gtk_misc_set_alignment(GTK_MISC(proxy_description_label), 0, 0);
-  gtk_box_pack_start(GTK_BOX(page_), proxy_description_label,
-                     FALSE, FALSE, 0);
-
-  change_proxies_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON).c_str());
-  g_signal_connect(change_proxies_button_, "clicked",
-                   G_CALLBACK(OnChangeProxiesButtonClicked), this);
-
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(button_hbox),
-                     change_proxies_button_,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(page_),
-                     gtk_util::IndentWidget(button_hbox),
-                     FALSE, FALSE, 0);
-
-  proxy_prefs_.reset(PrefSetObserver::CreateProxyPrefSetObserver(
-      profile->GetPrefs(), this));
-  NotifyPrefChanged(NULL);
-}
-
-void NetworkSection::NotifyPrefChanged(const std::string* pref_name) {
-  if (!pref_name || proxy_prefs_->IsObserved(*pref_name))
-    gtk_widget_set_sensitive(change_proxies_button_,
-                             !proxy_prefs_->IsManaged());
-}
-
-// static
-void NetworkSection::DetectAndStartProxyConfigUtil(Profile* profile) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  scoped_ptr<base::Environment> env(base::Environment::Create());
-
-  ProxyConfigCommand command;
-  bool found_command = false;
-  switch (base::nix::GetDesktopEnvironment(env.get())) {
-    case base::nix::DESKTOP_ENVIRONMENT_GNOME: {
-      size_t index;
-      ProxyConfigCommand commands[2];
-      commands[0].argv = kGNOMEProxyConfigCommand;
-      commands[1].argv = kOldGNOMEProxyConfigCommand;
-      found_command = SearchPATH(commands, 2, &index);
-      if (found_command)
-        command = commands[index];
-      break;
-    }
-
-    case base::nix::DESKTOP_ENVIRONMENT_KDE3:
-      command.argv = kKDE3ProxyConfigCommand;
-      found_command = SearchPATH(&command, 1, NULL);
-      break;
-
-    case base::nix::DESKTOP_ENVIRONMENT_KDE4:
-      command.argv = kKDE4ProxyConfigCommand;
-      found_command = SearchPATH(&command, 1, NULL);
-      break;
-
-    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
-    case base::nix::DESKTOP_ENVIRONMENT_OTHER:
-      break;
-  }
-
-  if (found_command) {
-    StartProxyConfigUtil(profile, command);
-  } else {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        NewRunnableFunction(&NetworkSection::ShowLinuxProxyConfigUrl, profile));
-  }
-}
-
-// static
-void NetworkSection::ShowLinuxProxyConfigUrl(Profile* profile) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  scoped_ptr<base::Environment> env(base::Environment::Create());
-  const char* name = base::nix::GetDesktopEnvironmentName(env.get());
-  if (name)
-    LOG(ERROR) << "Could not find " << name << " network settings in $PATH";
-  browser::ShowOptionsURL(profile, GURL(kLinuxProxyConfigUrl));
-}
-
-// static
-void NetworkSection::OnChangeProxiesButtonClicked(GtkButton *button,
-                                                  NetworkSection* section) {
-  section->UserMetricsRecordAction(UserMetricsAction("Options_ChangeProxies"),
-                                   NULL);
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-      NewRunnableFunction(&NetworkSection::DetectAndStartProxyConfigUtil,
-                          section->profile()));
-}
-
-// static
-bool NetworkSection::SearchPATH(ProxyConfigCommand* commands, size_t ncommands,
-                                size_t* index) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  const char* path = getenv("PATH");
-  if (!path)
-    return false;
-  FilePath bin_path;
-  CStringTokenizer tk(path, path + strlen(path), ":");
-  // Search $PATH looking for the commands in order.
-  while (tk.GetNext()) {
-    for (size_t i = 0; i < ncommands; i++) {
-      bin_path = FilePath(tk.token()).Append(commands[i].argv[0]);
-      if (file_util::PathExists(bin_path)) {
-        commands[i].binary = bin_path.value();
-        if (index)
-          *index = i;
-        return true;
-      }
-    }
-  }
-  // Did not find any of the binaries in $PATH.
-  return false;
-}
-
-// static
-void NetworkSection::StartProxyConfigUtil(Profile* profile,
-                                          const ProxyConfigCommand& command) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  std::vector<std::string> argv;
-  argv.push_back(command.binary);
-  for (size_t i = 1; command.argv[i]; i++)
-    argv.push_back(command.argv[i]);
-  base::file_handle_mapping_vector no_files;
-  base::ProcessHandle handle;
-  if (!base::LaunchApp(argv, no_files, false, &handle)) {
-    LOG(ERROR) << "StartProxyConfigUtil failed to start " << command.binary;
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        NewRunnableFunction(&NetworkSection::ShowLinuxProxyConfigUrl, profile));
-    return;
-  }
-  ProcessWatcher::EnsureProcessGetsReaped(handle);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TranslateSection
-
-class TranslateSection : public OptionsPageBase {
- public:
-  explicit TranslateSection(Profile* profile);
-  virtual ~TranslateSection() {}
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  CHROMEGTK_CALLBACK_0(TranslateSection, void, OnTranslateClicked);
-
-  // Preferences for this section:
-  BooleanPrefMember enable_translate_;
-
-  // The widget containing the options for this section.
-  GtkWidget* page_;
-
-  // The checkbox.
-  GtkWidget* translate_checkbox_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool pref_changing_;
-
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(TranslateSection);
-};
-
-TranslateSection::TranslateSection(Profile* profile)
-    : OptionsPageBase(profile),
-      pref_changing_(true) {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      page_, profile));
-
-  translate_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
-  gtk_box_pack_start(GTK_BOX(page_), translate_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(translate_checkbox_, "clicked",
-                   G_CALLBACK(OnTranslateClickedThunk), this);
-  accessible_widget_helper_->SetWidgetName(
-      translate_checkbox_,
-      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
-
-  // Init member prefs so we can update the controls if prefs change.
-  enable_translate_.Init(prefs::kEnableTranslate, profile->GetPrefs(), this);
-
-  NotifyPrefChanged(NULL);
-}
-
-void TranslateSection::NotifyPrefChanged(const std::string* pref_name) {
-  pref_changing_ = true;
-  if (!pref_name || *pref_name == prefs::kEnableTranslate) {
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(translate_checkbox_), enable_translate_.GetValue());
-  }
-  pref_changing_ = false;
-}
-
-void TranslateSection::OnTranslateClicked(GtkWidget* widget) {
-  if (pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  UserMetricsRecordAction(
-      enabled ?
-      UserMetricsAction("Options_Translate_Enable") :
-      UserMetricsAction("Options_Translate_Disable"),
-      profile()->GetPrefs());
-  enable_translate_.SetValue(enabled);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PrivacySection
-
-class PrivacySection : public OptionsPageBase {
- public:
-  explicit PrivacySection(Profile* profile);
-  virtual ~PrivacySection() {}
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  // Try to make the the crash stats consent and the metrics upload
-  // permission match the |reporting_enabled_checkbox_|.
-  void ResolveMetricsReportingEnabled();
-
-  // The callback functions for the options widgets.
-  static void OnContentSettingsClicked(GtkButton* button,
-                                       PrivacySection* privacy_section);
-  static void OnClearBrowsingDataButtonClicked(GtkButton* widget,
-                                               PrivacySection* page);
-  static void OnLearnMoreLinkClicked(GtkButton *button,
-                                     PrivacySection* privacy_section);
-  static void OnEnableLinkDoctorChange(GtkWidget* widget,
-                                       PrivacySection* options_window);
-  static void OnEnableSuggestChange(GtkWidget* widget,
-                                    PrivacySection* options_window);
-  static void OnDNSPrefetchingChange(GtkWidget* widget,
-                                     PrivacySection* options_window);
-  static void OnSafeBrowsingChange(GtkWidget* widget,
-                                   PrivacySection* options_window);
-  static void OnLoggingChange(GtkWidget* widget,
-                              PrivacySection* options_window);
-
-  // The widget containing the options for this section.
-  GtkWidget* page_;
-
-  // The widgets for the privacy options.
-  GtkWidget* enable_link_doctor_checkbox_;
-  GtkWidget* enable_suggest_checkbox_;
-  GtkWidget* enable_dns_prefetching_checkbox_;
-  GtkWidget* enable_safe_browsing_checkbox_;
-#if defined(GOOGLE_CHROME_BUILD)
-  GtkWidget* reporting_enabled_checkbox_;
-#endif
-
-  // Preferences for this section:
-  BooleanPrefMember alternate_error_pages_;
-  BooleanPrefMember use_suggest_;
-  BooleanPrefMember dns_prefetch_enabled_;
-  BooleanPrefMember safe_browsing_;
-  BooleanPrefMember enable_metrics_recording_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool pref_changing_;
-
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrivacySection);
-};
-
-PrivacySection::PrivacySection(Profile* profile)
-    : OptionsPageBase(profile),
-      pref_changing_(true) {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      page_, profile));
-
-  GtkWidget* content_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON).c_str());
-  g_signal_connect(content_button, "clicked",
-                   G_CALLBACK(OnContentSettingsClicked), this);
-
-  GtkWidget* clear_data_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON).c_str());
-  g_signal_connect(clear_data_button, "clicked",
-                   G_CALLBACK(OnClearBrowsingDataButtonClicked), this);
-
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(button_hbox), content_button, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(button_hbox), clear_data_button, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(page_), gtk_util::IndentWidget(button_hbox),
-                     FALSE, FALSE, 0);
-
-  GtkWidget* section_description_label = CreateWrappedLabel(
-      IDS_OPTIONS_DISABLE_SERVICES);
-  gtk_misc_set_alignment(GTK_MISC(section_description_label), 0, 0);
-  gtk_box_pack_start(GTK_BOX(page_), section_description_label,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  GtkWidget* learn_more_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(learn_more_hbox), learn_more_link,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(page_), learn_more_hbox,
-                     FALSE, FALSE, 0);
-  g_signal_connect(learn_more_link, "clicked",
-                   G_CALLBACK(OnLearnMoreLinkClicked), this);
-
-  enable_link_doctor_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_LINKDOCTOR_PREF);
-  gtk_box_pack_start(GTK_BOX(page_), enable_link_doctor_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(enable_link_doctor_checkbox_, "clicked",
-                   G_CALLBACK(OnEnableLinkDoctorChange), this);
-  accessible_widget_helper_->SetWidgetName(
-      enable_link_doctor_checkbox_, IDS_OPTIONS_LINKDOCTOR_PREF);
-
-  enable_suggest_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_SUGGEST_PREF);
-  gtk_box_pack_start(GTK_BOX(page_), enable_suggest_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(enable_suggest_checkbox_, "clicked",
-                   G_CALLBACK(OnEnableSuggestChange), this);
-  accessible_widget_helper_->SetWidgetName(
-      enable_suggest_checkbox_, IDS_OPTIONS_SUGGEST_PREF);
-
-  enable_dns_prefetching_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION);
-  gtk_box_pack_start(GTK_BOX(page_), enable_dns_prefetching_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(enable_dns_prefetching_checkbox_, "clicked",
-                   G_CALLBACK(OnDNSPrefetchingChange), this);
-  accessible_widget_helper_->SetWidgetName(
-      enable_dns_prefetching_checkbox_,
-      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION);
-
-  enable_safe_browsing_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION);
-  gtk_box_pack_start(GTK_BOX(page_), enable_safe_browsing_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(enable_safe_browsing_checkbox_, "clicked",
-                   G_CALLBACK(OnSafeBrowsingChange), this);
-  accessible_widget_helper_->SetWidgetName(
-      enable_safe_browsing_checkbox_,
-      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION);
-
-#if defined(GOOGLE_CHROME_BUILD)
-  reporting_enabled_checkbox_ = CreateCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_ENABLE_LOGGING);
-  gtk_box_pack_start(GTK_BOX(page_), reporting_enabled_checkbox_,
-                     FALSE, FALSE, 0);
-  g_signal_connect(reporting_enabled_checkbox_, "clicked",
-                   G_CALLBACK(OnLoggingChange), this);
-  accessible_widget_helper_->SetWidgetName(
-      reporting_enabled_checkbox_, IDS_OPTIONS_ENABLE_LOGGING);
-#endif
-
-  // Init member prefs so we can update the controls if prefs change.
-  alternate_error_pages_.Init(prefs::kAlternateErrorPagesEnabled,
-                              profile->GetPrefs(), this);
-  use_suggest_.Init(prefs::kSearchSuggestEnabled,
-                    profile->GetPrefs(), this);
-  dns_prefetch_enabled_.Init(prefs::kDnsPrefetchingEnabled,
-                             profile->GetPrefs(), this);
-  safe_browsing_.Init(prefs::kSafeBrowsingEnabled, profile->GetPrefs(), this);
-  enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled,
-                                 g_browser_process->local_state(), this);
-  NotifyPrefChanged(NULL);
-}
-
-// static
-void PrivacySection::OnContentSettingsClicked(GtkButton* button,
-                                              PrivacySection* privacy_section) {
-  ContentSettingsWindowGtk::Show(
-      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
-      CONTENT_SETTINGS_TYPE_DEFAULT,
-      privacy_section->profile());
-}
-
-// static
-void PrivacySection::OnClearBrowsingDataButtonClicked(GtkButton* widget,
-                                                      PrivacySection* section) {
-  ClearBrowsingDataDialogGtk::Show(
-      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))),
-      section->profile());
-}
-
-// static
-void PrivacySection::OnLearnMoreLinkClicked(GtkButton *button,
-                                            PrivacySection* privacy_section) {
-  GURL url = google_util::AppendGoogleLocaleParam(
-      GURL(chrome::kPrivacyLearnMoreURL));
-  browser::ShowOptionsURL(privacy_section->profile(), url);
-}
-
-// static
-void PrivacySection::OnEnableLinkDoctorChange(GtkWidget* widget,
-                                              PrivacySection* privacy_section) {
-  if (privacy_section->pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  privacy_section->UserMetricsRecordAction(
-      enabled ?
-          UserMetricsAction("Options_LinkDoctorCheckbox_Enable") :
-          UserMetricsAction("Options_LinkDoctorCheckbox_Disable"),
-      privacy_section->profile()->GetPrefs());
-  privacy_section->alternate_error_pages_.SetValue(enabled);
-}
-
-// static
-void PrivacySection::OnEnableSuggestChange(GtkWidget* widget,
-                                           PrivacySection* privacy_section) {
-  if (privacy_section->pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  privacy_section->UserMetricsRecordAction(
-      enabled ?
-          UserMetricsAction("Options_UseSuggestCheckbox_Enable") :
-          UserMetricsAction("Options_UseSuggestCheckbox_Disable"),
-      privacy_section->profile()->GetPrefs());
-  privacy_section->use_suggest_.SetValue(enabled);
-}
-
-// static
-void PrivacySection::OnDNSPrefetchingChange(GtkWidget* widget,
-                                           PrivacySection* privacy_section) {
-  if (privacy_section->pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  privacy_section->UserMetricsRecordAction(
-      enabled ?
-          UserMetricsAction("Options_DnsPrefetchCheckbox_Enable") :
-          UserMetricsAction("Options_DnsPrefetchCheckbox_Disable"),
-      privacy_section->profile()->GetPrefs());
-  privacy_section->dns_prefetch_enabled_.SetValue(enabled);
-}
-
-// static
-void PrivacySection::OnSafeBrowsingChange(GtkWidget* widget,
-                                          PrivacySection* privacy_section) {
-  if (privacy_section->pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  privacy_section->UserMetricsRecordAction(
-      enabled ?
-          UserMetricsAction("Options_SafeBrowsingCheckbox_Enable") :
-          UserMetricsAction("Options_SafeBrowsingCheckbox_Disable"),
-      privacy_section->profile()->GetPrefs());
-  privacy_section->safe_browsing_.SetValue(enabled);
-  SafeBrowsingService* safe_browsing_service =
-      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      safe_browsing_service, &SafeBrowsingService::OnEnable, enabled));
-}
-
-// static
-void PrivacySection::OnLoggingChange(GtkWidget* widget,
-                                     PrivacySection* privacy_section) {
-  if (privacy_section->pref_changing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-  privacy_section->UserMetricsRecordAction(
-      enabled ?
-          UserMetricsAction("Options_MetricsReportingCheckbox_Enable") :
-          UserMetricsAction("Options_MetricsReportingCheckbox_Disable"),
-      privacy_section->profile()->GetPrefs());
-  // Prevent us from being called again by ResolveMetricsReportingEnabled
-  // resetting the checkbox if there was a problem.
-  g_signal_handlers_block_by_func(widget,
-                                  reinterpret_cast<gpointer>(OnLoggingChange),
-                                  privacy_section);
-  privacy_section->ResolveMetricsReportingEnabled();
-  g_signal_handlers_unblock_by_func(widget,
-                                    reinterpret_cast<gpointer>(OnLoggingChange),
-                                    privacy_section);
-  privacy_section->enable_metrics_recording_.SetValue(enabled);
-}
-
-void PrivacySection::NotifyPrefChanged(const std::string* pref_name) {
-  pref_changing_ = true;
-  if (!pref_name || *pref_name == prefs::kAlternateErrorPagesEnabled) {
-    gtk_widget_set_sensitive(
-        GTK_WIDGET(enable_link_doctor_checkbox_),
-        !alternate_error_pages_.IsManaged());
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(enable_link_doctor_checkbox_),
-        alternate_error_pages_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kSearchSuggestEnabled) {
-    gtk_widget_set_sensitive(
-        GTK_WIDGET(enable_suggest_checkbox_),
-        !use_suggest_.IsManaged());
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(enable_suggest_checkbox_),
-        use_suggest_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kDnsPrefetchingEnabled) {
-    gtk_widget_set_sensitive(
-        GTK_WIDGET(enable_dns_prefetching_checkbox_),
-        !dns_prefetch_enabled_.IsManaged());
-    bool enabled = dns_prefetch_enabled_.GetValue();
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(enable_dns_prefetching_checkbox_), enabled);
-  }
-  if (!pref_name || *pref_name == prefs::kSafeBrowsingEnabled) {
-    gtk_widget_set_sensitive(
-        GTK_WIDGET(enable_safe_browsing_checkbox_),
-        !safe_browsing_.IsManaged());
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(enable_safe_browsing_checkbox_),
-        safe_browsing_.GetValue());
-  }
-#if defined(GOOGLE_CHROME_BUILD)
-  if (!pref_name || *pref_name == prefs::kMetricsReportingEnabled) {
-    gtk_widget_set_sensitive(
-        GTK_WIDGET(reporting_enabled_checkbox_),
-        !enable_metrics_recording_.IsManaged());
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_),
-        enable_metrics_recording_.GetValue());
-    ResolveMetricsReportingEnabled();
-  }
-#endif
-  pref_changing_ = false;
-}
-
-void PrivacySection::ResolveMetricsReportingEnabled() {
-#if defined(GOOGLE_CHROME_BUILD)
-  bool enabled = gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_));
-
-  enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled);
-
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_),
-                               enabled);
-#endif
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// SecuritySection
-
-class SecuritySection : public OptionsPageBase {
- public:
-  explicit SecuritySection(Profile* profile);
-  virtual ~SecuritySection() {}
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  // The callback functions for the options widgets.
-  static void OnManageCertificatesClicked(GtkButton* button,
-                                          SecuritySection* section);
-  static void OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton,
-                                          SecuritySection* section);
-  static void OnSSL3EnabledToggled(GtkToggleButton* togglebutton,
-                                   SecuritySection* section);
-  static void OnTLS1EnabledToggled(GtkToggleButton* togglebutton,
-                                   SecuritySection* section);
-
-  // The widget containing the options for this section.
-  GtkWidget* page_;
-  GtkWidget* rev_checking_enabled_checkbox_;
-  GtkWidget* ssl3_enabled_checkbox_;
-  GtkWidget* tls1_enabled_checkbox_;
-
-  // SSLConfigService prefs.
-  BooleanPrefMember rev_checking_enabled_;
-  BooleanPrefMember ssl3_enabled_;
-  BooleanPrefMember tls1_enabled_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool pref_changing_;
-
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(SecuritySection);
-};
-
-SecuritySection::SecuritySection(Profile* profile)
-    : OptionsPageBase(profile),
-      pref_changing_(true) {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      page_, profile));
-
-  GtkWidget* manage_certificates_label = CreateWrappedLabel(
-      IDS_OPTIONS_CERTIFICATES_LABEL);
-  gtk_misc_set_alignment(GTK_MISC(manage_certificates_label), 0, 0);
-  gtk_box_pack_start(GTK_BOX(page_), manage_certificates_label,
-                     FALSE, FALSE, 0);
-
-  // TODO(mattm): change this to a button to launch the system certificate
-  // manager, when one exists.
-  GtkWidget* manage_certificates_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON).c_str());
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  GtkWidget* manage_certificates_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(manage_certificates_hbox),
-                     manage_certificates_link, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(page_),
-                     gtk_util::IndentWidget(manage_certificates_hbox),
-                     FALSE, FALSE, 0);
-  g_signal_connect(manage_certificates_link, "clicked",
-                   G_CALLBACK(OnManageCertificatesClicked), this);
-
-  // TODO(mattm): should have a description label here and have the checkboxes
-  // indented, but IDS_OPTIONS_SSL_GROUP_DESCRIPTION isn't appropriate and
-  // didn't think of adding a Linux specific one before the string freeze.
-  rev_checking_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_SSL_CHECKREVOCATION, page_,
-      G_CALLBACK(OnRevCheckingEnabledToggled), this);
-  accessible_widget_helper_->SetWidgetName(
-      rev_checking_enabled_checkbox_, IDS_OPTIONS_SSL_CHECKREVOCATION);
-  ssl3_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_SSL_USESSL3, page_, G_CALLBACK(OnSSL3EnabledToggled), this);
-  accessible_widget_helper_->SetWidgetName(
-      ssl3_enabled_checkbox_, IDS_OPTIONS_SSL_USESSL3);
-  tls1_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
-      IDS_OPTIONS_SSL_USETLS1, page_, G_CALLBACK(OnTLS1EnabledToggled), this);
-  accessible_widget_helper_->SetWidgetName(
-      tls1_enabled_checkbox_, IDS_OPTIONS_SSL_USETLS1);
-
-  rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled,
-                             profile->GetPrefs(), this);
-  ssl3_enabled_.Init(prefs::kSSL3Enabled, profile->GetPrefs(), this);
-  tls1_enabled_.Init(prefs::kTLS1Enabled, profile->GetPrefs(), this);
-
-  NotifyPrefChanged(NULL);
-}
-
-void SecuritySection::NotifyPrefChanged(const std::string* pref_name) {
-  pref_changing_ = true;
-  if (!pref_name || *pref_name == prefs::kCertRevocationCheckingEnabled) {
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(rev_checking_enabled_checkbox_),
-        rev_checking_enabled_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kSSL3Enabled) {
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl3_enabled_checkbox_),
-                                 ssl3_enabled_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kTLS1Enabled) {
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tls1_enabled_checkbox_),
-                                 tls1_enabled_.GetValue());
-  }
-  pref_changing_ = false;
-}
-
-
-// static
-void SecuritySection::OnManageCertificatesClicked(GtkButton* button,
-                                                  SecuritySection* section) {
-  browser::ShowOptionsURL(section->profile(),
-                          GURL(kLinuxCertificatesConfigUrl));
-}
-
-// static
-void SecuritySection::OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton,
-                                                  SecuritySection* section) {
-  if (section->pref_changing_)
-    return;
-
-  bool enabled = gtk_toggle_button_get_active(togglebutton);
-  if (enabled) {
-    section->UserMetricsRecordAction(
-        UserMetricsAction("Options_CheckCertRevocation_Enable"),
-        NULL);
-  } else {
-    section->UserMetricsRecordAction(
-        UserMetricsAction("Options_CheckCertRevocation_Disable"),
-        NULL);
-  }
-  section->rev_checking_enabled_.SetValue(enabled);
-}
-
-// static
-void SecuritySection::OnSSL3EnabledToggled(GtkToggleButton* togglebutton,
-                                           SecuritySection* section) {
-  if (section->pref_changing_)
-    return;
-
-  bool enabled = gtk_toggle_button_get_active(togglebutton);
-  if (enabled) {
-    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Enable"),
-                                     NULL);
-  } else {
-    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Disable"),
-                                     NULL);
-  }
-  section->ssl3_enabled_.SetValue(enabled);
-}
-
-// static
-void SecuritySection::OnTLS1EnabledToggled(GtkToggleButton* togglebutton,
-                                           SecuritySection* section) {
-  if (section->pref_changing_)
-    return;
-
-  bool enabled = gtk_toggle_button_get_active(togglebutton);
-  if (enabled) {
-    section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Enable"),
-                                     NULL);
-  } else {
-    section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Disable"),
-                                     NULL);
-  }
-  section->tls1_enabled_.SetValue(enabled);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// WebContentSection
-
-class WebContentSection : public OptionsPageBase {
- public:
-  explicit WebContentSection(Profile* profile);
-  virtual ~WebContentSection() {}
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // The callback functions for the options widgets.
-  static void OnFontsAndLanguagesButtonClicked(GtkButton *button,
-                                               WebContentSection* section);
-
-  // The widget containing the options for this section.
-  GtkWidget* page_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebContentSection);
-};
-
-WebContentSection::WebContentSection(Profile* profile)
-    : OptionsPageBase(profile) {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GtkWidget* fonts_and_languages_label = CreateWrappedLabel(
-      IDS_OPTIONS_FONTSETTINGS_INFO);
-  gtk_misc_set_alignment(GTK_MISC(fonts_and_languages_label), 0, 0);
-  gtk_box_pack_start(GTK_BOX(page_), fonts_and_languages_label,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* fonts_and_languages_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON).c_str());
-  g_signal_connect(fonts_and_languages_button, "clicked",
-                   G_CALLBACK(OnFontsAndLanguagesButtonClicked), this);
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(button_hbox),
-                     fonts_and_languages_button,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(page_),
-                     gtk_util::IndentWidget(button_hbox),
-                     FALSE, FALSE, 0);
-
-  // TODO(mattm): gears options would go here if we supported gears
-}
-
-// static
-void WebContentSection::OnFontsAndLanguagesButtonClicked(
-    GtkButton *button, WebContentSection* section) {
-  ShowFontsLanguagesWindow(GTK_WINDOW(gtk_widget_get_toplevel(section->page_)),
-                           FONTS_ENCODING_PAGE,
-                           section->profile());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// AdvancedContentsGtk
-
-AdvancedContentsGtk::AdvancedContentsGtk(Profile* profile)
-    : profile_(profile) {
-  Init();
-}
-
-AdvancedContentsGtk::~AdvancedContentsGtk() {
-}
-
-void AdvancedContentsGtk::Init() {
-  scoped_ptr<OptionsLayoutBuilderGtk>
-    options_builder(OptionsLayoutBuilderGtk::Create());
-
-  privacy_section_.reset(new PrivacySection(profile_));
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY),
-      privacy_section_->get_page_widget(), false);
-
-  network_section_.reset(new NetworkSection(profile_));
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK),
-      network_section_->get_page_widget(), false);
-
-  translate_section_.reset(new TranslateSection(profile_));
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE),
-      translate_section_->get_page_widget(), false);
-
-  download_section_.reset(new DownloadSection(profile_));
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME),
-      download_section_->get_page_widget(), false);
-
-  web_content_section_.reset(new WebContentSection(profile_));
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT),
-      web_content_section_->get_page_widget(), false);
-
-  security_section_.reset(new SecuritySection(profile_));
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY),
-      security_section_->get_page_widget(), false);
-
-  page_ = options_builder->get_page_widget();
-}
diff --git a/chrome/browser/gtk/options/advanced_contents_gtk.h b/chrome/browser/gtk/options/advanced_contents_gtk.h
deleted file mode 100644
index 28eb3bd..0000000
--- a/chrome/browser/gtk/options/advanced_contents_gtk.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_ADVANCED_CONTENTS_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_ADVANCED_CONTENTS_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-
-class Profile;
-class DownloadSection;
-class NetworkSection;
-class PrivacySection;
-class SecuritySection;
-class TranslateSection;
-class WebContentSection;
-
-class AdvancedContentsGtk {
- public:
-  explicit AdvancedContentsGtk(Profile* profile);
-  virtual ~AdvancedContentsGtk();
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  void Init();
-
-  // The profile.
-  Profile* profile_;
-
-  // The sections of the page.
-  scoped_ptr<DownloadSection> download_section_;
-  scoped_ptr<NetworkSection> network_section_;
-  scoped_ptr<TranslateSection> translate_section_;
-  scoped_ptr<PrivacySection> privacy_section_;
-  scoped_ptr<SecuritySection> security_section_;
-  scoped_ptr<WebContentSection> web_content_section_;
-
-  // The widget containing the advanced options sections.
-  GtkWidget* page_;
-
-  DISALLOW_COPY_AND_ASSIGN(AdvancedContentsGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_ADVANCED_CONTENTS_GTK_H_
diff --git a/chrome/browser/gtk/options/advanced_page_gtk.cc b/chrome/browser/gtk/options/advanced_page_gtk.cc
deleted file mode 100644
index 1bab4b4..0000000
--- a/chrome/browser/gtk/options/advanced_page_gtk.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/advanced_page_gtk.h"
-
-#include "app/l10n_util.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/options/options_util.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-AdvancedPageGtk::AdvancedPageGtk(Profile* profile)
-    : OptionsPageBase(profile),
-      advanced_contents_(profile),
-      managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_ADVANCED) {
-  Init();
-}
-
-AdvancedPageGtk::~AdvancedPageGtk() {
-}
-
-void AdvancedPageGtk::Init() {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(page_),
-                                 gtk_util::kContentAreaBorder);
-
-  gtk_box_pack_start(GTK_BOX(page_), managed_prefs_banner_.banner_widget(),
-                     false, false, 0);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_container_add(GTK_CONTAINER(page_), scroll_window);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_NEVER,
-                                 GTK_POLICY_AUTOMATIC);
-  // Note that typically we call gtk_scrolled_window_set_shadow_type right
-  // here, but the add_with_viewport method of GtkScrolledWindow already adds
-  // its own shadow.
-  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll_window),
-                                        advanced_contents_.get_page_widget());
-
-  GtkWidget* button_box = gtk_hbutton_box_new();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
-  GtkWidget* reset_button = gtk_button_new_with_label(
-        l10n_util::GetStringUTF8(IDS_OPTIONS_RESET).c_str());
-  g_signal_connect(reset_button, "clicked",
-                   G_CALLBACK(OnResetToDefaultsClickedThunk), this);
-  gtk_container_add(GTK_CONTAINER(button_box), reset_button);
-  gtk_box_pack_start(GTK_BOX(page_), button_box, FALSE, FALSE, 0);
-}
-
-void AdvancedPageGtk::OnResetToDefaultsClicked(GtkWidget* button) {
-  UserMetricsRecordAction(UserMetricsAction("Options_ResetToDefaults"), NULL);
-  GtkWidget* dialog_ = gtk_message_dialog_new(
-      GTK_WINDOW(gtk_widget_get_toplevel(page_)),
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
-      GTK_MESSAGE_QUESTION,
-      GTK_BUTTONS_NONE,
-      "%s",
-      l10n_util::GetStringUTF8(IDS_OPTIONS_RESET_MESSAGE).c_str());
-  gtk_util::ApplyMessageDialogQuirks(dialog_);
-  gtk_dialog_add_buttons(
-      GTK_DIALOG(dialog_),
-      l10n_util::GetStringUTF8(IDS_OPTIONS_RESET_CANCELLABEL).c_str(),
-      GTK_RESPONSE_CANCEL,
-      l10n_util::GetStringUTF8(IDS_OPTIONS_RESET_OKLABEL).c_str(),
-      GTK_RESPONSE_OK,
-      NULL);
-  gtk_window_set_title(GTK_WINDOW(dialog_),
-      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str());
-  g_signal_connect(dialog_, "response",
-                   G_CALLBACK(OnResetToDefaultsResponseThunk), this);
-
-  gtk_util::ShowDialog(dialog_);
-}
-
-void AdvancedPageGtk::OnResetToDefaultsResponse(GtkWidget* dialog,
-                                                int response_id) {
-  if (response_id == GTK_RESPONSE_OK) {
-    OptionsUtil::ResetToDefaults(profile());
-  }
-  gtk_widget_destroy(dialog);
-}
diff --git a/chrome/browser/gtk/options/advanced_page_gtk.h b/chrome/browser/gtk/options/advanced_page_gtk.h
deleted file mode 100644
index f1345c8..0000000
--- a/chrome/browser/gtk/options/advanced_page_gtk.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_ADVANCED_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_ADVANCED_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/gtk/options/advanced_contents_gtk.h"
-#include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-
-class Profile;
-
-class AdvancedPageGtk : public OptionsPageBase {
- public:
-  explicit AdvancedPageGtk(Profile* profile);
-  virtual ~AdvancedPageGtk();
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  void Init();
-
-  // Callback for reset to default button.
-  CHROMEGTK_CALLBACK_0(AdvancedPageGtk, void, OnResetToDefaultsClicked);
-
-  // Callback for reset to default confirmation dialog.
-  CHROMEGTK_CALLBACK_1(AdvancedPageGtk, void, OnResetToDefaultsResponse, int);
-
-  // The contents of the scroll box.
-  AdvancedContentsGtk advanced_contents_;
-
-  // The widget containing the options for this page.
-  GtkWidget* page_;
-
-  // Tracks managed preference warning banner state.
-  ManagedPrefsBannerGtk managed_prefs_banner_;
-
-  DISALLOW_COPY_AND_ASSIGN(AdvancedPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_ADVANCED_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/content_exception_editor.cc b/chrome/browser/gtk/options/content_exception_editor.cc
deleted file mode 100644
index 5f8aa69..0000000
--- a/chrome/browser/gtk/options/content_exception_editor.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/content_exception_editor.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/content_exceptions_table_model.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-ContentExceptionEditor::ContentExceptionEditor(
-    GtkWindow* parent,
-    ContentExceptionEditor::Delegate* delegate,
-    ContentExceptionsTableModel* model,
-    bool allow_off_the_record,
-    int index,
-    const ContentSettingsPattern& pattern,
-    ContentSetting setting,
-    bool is_off_the_record)
-    : delegate_(delegate),
-      model_(model),
-      cb_model_(model->content_type()),
-      index_(index),
-      pattern_(pattern),
-      setting_(setting) {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(is_new() ?
-                               IDS_EXCEPTION_EDITOR_NEW_TITLE :
-                               IDS_EXCEPTION_EDITOR_TITLE).c_str(),
-      parent,
-      // Non-modal.
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_CANCEL,
-      GTK_STOCK_OK,
-      GTK_RESPONSE_OK,
-      NULL);
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
-
-  entry_ = gtk_entry_new();
-  gtk_entry_set_text(GTK_ENTRY(entry_), pattern_.AsString().c_str());
-  g_signal_connect(entry_, "changed", G_CALLBACK(OnEntryChangedThunk), this);
-  gtk_entry_set_activates_default(GTK_ENTRY(entry_), TRUE);
-
-  pattern_image_ = gtk_image_new_from_pixbuf(NULL);
-
-  action_combo_ = gtk_combo_box_new_text();
-  for (int i = 0; i < cb_model_.GetItemCount(); ++i) {
-    gtk_combo_box_append_text(GTK_COMBO_BOX(action_combo_),
-        UTF16ToUTF8(cb_model_.GetItemAt(i)).c_str());
-  }
-  gtk_combo_box_set_active(GTK_COMBO_BOX(action_combo_),
-                           cb_model_.IndexForSetting(setting_));
-
-  otr_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_OTR_TITLE).c_str());
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(otr_checkbox_),
-                               is_off_the_record);
-
-  GtkWidget* table = gtk_util::CreateLabeledControlsGroup(
-      NULL,
-      l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_PATTERN_TITLE).c_str(),
-      gtk_util::CreateEntryImageHBox(entry_, pattern_image_),
-      l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_ACTION_TITLE).c_str(),
-      action_combo_,
-      NULL);
-  if (allow_off_the_record) {
-    gtk_table_attach(GTK_TABLE(table), otr_checkbox_,
-                     0, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
-  }
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), table,
-                     FALSE, FALSE, 0);
-
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  // Prime the state of the buttons.
-  OnEntryChanged(entry_);
-
-  gtk_util::ShowDialog(dialog_);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-bool ContentExceptionEditor::IsPatternValid(
-    const ContentSettingsPattern& pattern,
-    bool is_off_the_record) const {
-  bool is_valid_pattern = pattern.IsValid() &&
-      (model_->IndexOfExceptionByPattern(pattern, is_off_the_record) == -1);
-
-  return is_new() ? is_valid_pattern : (!pattern.AsString().empty() &&
-      ((pattern_ == pattern) || is_valid_pattern));
-}
-
-void ContentExceptionEditor::UpdateImage(GtkWidget* image, bool is_valid) {
-  return gtk_image_set_from_pixbuf(GTK_IMAGE(image),
-      ResourceBundle::GetSharedInstance().GetPixbufNamed(
-          is_valid ? IDR_INPUT_GOOD : IDR_INPUT_ALERT));
-}
-
-void ContentExceptionEditor::OnEntryChanged(GtkWidget* entry) {
-  ContentSettingsPattern new_pattern(gtk_entry_get_text(GTK_ENTRY(entry)));
-  bool is_off_the_record =
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(otr_checkbox_));
-  bool is_valid = IsPatternValid(new_pattern, is_off_the_record);
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
-                                    GTK_RESPONSE_OK, is_valid);
-  UpdateImage(pattern_image_, is_valid);
-}
-
-void ContentExceptionEditor::OnResponse(GtkWidget* sender, int response_id) {
-  if (response_id == GTK_RESPONSE_OK) {
-    // Notify our delegate to update everything.
-    ContentSettingsPattern new_pattern(gtk_entry_get_text(GTK_ENTRY(entry_)));
-    ContentSetting setting = cb_model_.SettingForIndex(
-        gtk_combo_box_get_active(GTK_COMBO_BOX(action_combo_)));
-    bool is_off_the_record =
-        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(otr_checkbox_));
-    delegate_->AcceptExceptionEdit(
-        new_pattern, setting, is_off_the_record, index_, is_new());
-  }
-
-  gtk_widget_destroy(dialog_);
-}
-
-void ContentExceptionEditor::OnWindowDestroy(GtkWidget* widget) {
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
diff --git a/chrome/browser/gtk/options/content_exception_editor.h b/chrome/browser/gtk/options/content_exception_editor.h
deleted file mode 100644
index 4ed5ad3..0000000
--- a/chrome/browser/gtk/options/content_exception_editor.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_CONTENT_EXCEPTION_EDITOR_H_
-#define CHROME_BROWSER_GTK_OPTIONS_CONTENT_EXCEPTION_EDITOR_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/content_exceptions_table_model.h"
-#include "chrome/browser/content_setting_combo_model.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/content_settings_types.h"
-
-// An editor which lets the user create or edit an individual exception to the
-// current content setting policy. (i.e. let www.google.com always show
-// images). Modal to parent.
-class ContentExceptionEditor {
- public:
-  class Delegate {
-   public:
-    // Invoked when the user accepts the edit.
-    virtual void AcceptExceptionEdit(
-        const ContentSettingsPattern& pattern,
-        ContentSetting setting,
-        bool is_off_the_record,
-        int index,
-        bool is_new) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  ContentExceptionEditor(GtkWindow* parent,
-                         Delegate* delegate,
-                         ContentExceptionsTableModel* model,
-                         bool allow_off_the_record,
-                         int index,
-                         const ContentSettingsPattern& pattern,
-                         ContentSetting setting,
-                         bool is_off_the_record);
-  virtual ~ContentExceptionEditor() {}
-
- private:
-  // Returns true if we're adding a new item.
-  bool is_new() const { return index_ == -1; }
-
-  bool IsPatternValid(const ContentSettingsPattern& pattern,
-                      bool is_off_the_record) const;
-
-  void UpdateImage(GtkWidget* image, bool is_valid);
-
-  // GTK callbacks
-  CHROMEGTK_CALLBACK_0(ContentExceptionEditor, void, OnEntryChanged);
-  CHROMEGTK_CALLBACK_1(ContentExceptionEditor, void, OnResponse, int);
-  CHROMEGTK_CALLBACK_0(ContentExceptionEditor, void, OnWindowDestroy);
-
-  Delegate* delegate_;
-  ContentExceptionsTableModel* model_;
-
-  // The model for Combobox widget.
-  ContentSettingComboModel cb_model_;
-
-  // Index of the item being edited. If -1, indicates this is a new entry.
-  const int index_;
-  const ContentSettingsPattern pattern_;
-  const ContentSetting setting_;
-
-  // UI widgets.
-  GtkWidget* dialog_;
-  GtkWidget* entry_;
-  GtkWidget* pattern_image_;
-  GtkWidget* action_combo_;
-  GtkWidget* otr_checkbox_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentExceptionEditor);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_CONTENT_EXCEPTION_EDITOR_H_
diff --git a/chrome/browser/gtk/options/content_exceptions_window_gtk.cc b/chrome/browser/gtk/options/content_exceptions_window_gtk.cc
deleted file mode 100644
index 1189096..0000000
--- a/chrome/browser/gtk/options/content_exceptions_window_gtk.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/content_exceptions_window_gtk.h"
-
-#include <set>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/content_exception_editor.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Singletons for each possible exception window.
-ContentExceptionsWindowGtk* instances[CONTENT_SETTINGS_NUM_TYPES] = { NULL };
-
-}  // namespace
-
-// static
-void ContentExceptionsWindowGtk::ShowExceptionsWindow(
-    GtkWindow* parent,
-    HostContentSettingsMap* map,
-    HostContentSettingsMap* off_the_record_map,
-    ContentSettingsType type) {
-  DCHECK(map);
-  DCHECK(type < CONTENT_SETTINGS_NUM_TYPES);
-  // Geolocation exceptions are handled by SimpleContentExceptionsWindow.
-  DCHECK_NE(type, CONTENT_SETTINGS_TYPE_GEOLOCATION);
-  // Notification exceptions are handled by SimpleContentExceptionsWindow.
-  DCHECK_NE(type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
-
-  if (!instances[type]) {
-    // Create the options window.
-    instances[type] =
-        new ContentExceptionsWindowGtk(parent, map, off_the_record_map, type);
-  } else {
-    gtk_util::PresentWindow(instances[type]->dialog_, 0);
-  }
-}
-
-ContentExceptionsWindowGtk::~ContentExceptionsWindowGtk() {
-}
-
-ContentExceptionsWindowGtk::ContentExceptionsWindowGtk(
-    GtkWindow* parent,
-    HostContentSettingsMap* map,
-    HostContentSettingsMap* off_the_record_map,
-    ContentSettingsType type)
-    : allow_off_the_record_(off_the_record_map) {
-  // Build the list backing that GTK uses, along with an adapter which will
-  // sort stuff without changing the underlying backing store.
-  list_store_ = gtk_list_store_new(COL_COUNT, G_TYPE_STRING, G_TYPE_STRING,
-                                   PANGO_TYPE_STYLE);
-  sort_list_store_ = gtk_tree_model_sort_new_with_model(
-      GTK_TREE_MODEL(list_store_));
-  treeview_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(sort_list_store_));
-  g_object_unref(list_store_);
-  g_object_unref(sort_list_store_);
-
-  // Set up the properties of the treeview
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview_), TRUE);
-  g_signal_connect(treeview_, "row-activated",
-                   G_CALLBACK(OnTreeViewRowActivateThunk), this);
-
-  GtkTreeViewColumn* pattern_column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_PATTERN_HEADER).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_PATTERN,
-      "style", COL_OTR,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), pattern_column);
-  gtk_tree_view_column_set_sort_column_id(pattern_column, COL_PATTERN);
-
-  GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_ACTION,
-      "style", COL_OTR,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), action_column);
-  gtk_tree_view_column_set_sort_column_id(action_column, COL_ACTION);
-
-  treeview_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(treeview_));
-  gtk_tree_selection_set_mode(treeview_selection_, GTK_SELECTION_MULTIPLE);
-  g_signal_connect(treeview_selection_, "changed",
-                   G_CALLBACK(OnTreeSelectionChangedThunk), this);
-
-  // Bind |list_store_| to our C++ model.
-  model_.reset(new ContentExceptionsTableModel(map, off_the_record_map, type));
-  model_adapter_.reset(new gtk_tree::TableAdapter(this, list_store_,
-                                                  model_.get()));
-  // Force a reload of everything to copy data into |list_store_|.
-  model_adapter_->OnModelChanged();
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      GetWindowTitle().c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
-  // Allow browser windows to go in front of the options dialog in metacity.
-  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox);
-
-  GtkWidget* treeview_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  // Create a scrolled window to wrap the treeview widget.
-  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
-                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
-  gtk_box_pack_start(GTK_BOX(treeview_box), scrolled, TRUE, TRUE, 0);
-
-  // If we also have an OTR profile, inform the user that OTR exceptions are
-  // displayed in italics.
-  if (allow_off_the_record_) {
-    GtkWidget* incognito_label = gtk_label_new(
-        l10n_util::GetStringUTF8(IDS_EXCEPTIONS_OTR_IN_ITALICS).c_str());
-    PangoAttrList* attributes = pango_attr_list_new();
-    pango_attr_list_insert(attributes,
-                           pango_attr_style_new(PANGO_STYLE_ITALIC));
-    gtk_label_set_attributes(GTK_LABEL(incognito_label), attributes);
-    pango_attr_list_unref(attributes);
-    gtk_misc_set_alignment(GTK_MISC(incognito_label), 0, 0);
-    gtk_box_pack_start(GTK_BOX(treeview_box), incognito_label, FALSE, FALSE, 0);
-  }
-
-  gtk_box_pack_start(GTK_BOX(hbox), treeview_box, TRUE, TRUE, 0);
-
-  GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GtkWidget* add_button = gtk_util::BuildDialogButton(dialog_,
-                                                      IDS_EXCEPTIONS_ADD_BUTTON,
-                                                      GTK_STOCK_ADD);
-  g_signal_connect(add_button, "clicked", G_CALLBACK(AddThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0);
-
-  edit_button_ = gtk_util::BuildDialogButton(dialog_,
-                                             IDS_EXCEPTIONS_EDIT_BUTTON,
-                                             GTK_STOCK_EDIT);
-  g_signal_connect(edit_button_, "clicked", G_CALLBACK(EditThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_box), edit_button_, FALSE, FALSE, 0);
-
-  remove_button_ = gtk_util::BuildDialogButton(dialog_,
-                                               IDS_EXCEPTIONS_REMOVE_BUTTON,
-                                               GTK_STOCK_REMOVE);
-  g_signal_connect(remove_button_, "clicked", G_CALLBACK(RemoveThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0);
-
-  remove_all_button_ = gtk_util::BuildDialogButton(
-      dialog_,
-      IDS_EXCEPTIONS_REMOVEALL_BUTTON,
-      GTK_STOCK_CLEAR);
-  g_signal_connect(remove_all_button_, "clicked", G_CALLBACK(RemoveAllThunk),
-                   this);
-  gtk_box_pack_start(GTK_BOX(button_box), remove_all_button_, FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0);
-
-  UpdateButtonState();
-
-  gtk_util::ShowDialogWithLocalizedSize(dialog_,
-      IDS_CONTENT_EXCEPTION_DIALOG_WIDTH_CHARS,
-      -1,
-      true);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-void ContentExceptionsWindowGtk::SetColumnValues(int row, GtkTreeIter* iter) {
-  string16 pattern = model_->GetText(row, IDS_EXCEPTIONS_PATTERN_HEADER);
-  gtk_list_store_set(list_store_, iter, COL_PATTERN,
-                     UTF16ToUTF8(pattern).c_str(), -1);
-
-  string16 action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER);
-  gtk_list_store_set(list_store_, iter, COL_ACTION,
-                     UTF16ToUTF8(action).c_str(), -1);
-
-  bool is_off_the_record = model_->entry_is_off_the_record(row);
-  PangoStyle style =
-      is_off_the_record ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
-  gtk_list_store_set(list_store_, iter, COL_OTR, style, -1);
-}
-
-void ContentExceptionsWindowGtk::AcceptExceptionEdit(
-    const ContentSettingsPattern& pattern,
-    ContentSetting setting,
-    bool is_off_the_record,
-    int index,
-    bool is_new) {
-  DCHECK(!is_off_the_record || allow_off_the_record_);
-
-  if (!is_new)
-    model_->RemoveException(index);
-
-  model_->AddException(pattern, setting, is_off_the_record);
-
-  int new_index = model_->IndexOfExceptionByPattern(pattern, is_off_the_record);
-  DCHECK_NE(-1, new_index);
-
-  gtk_tree::SelectAndFocusRowNum(new_index, GTK_TREE_VIEW(treeview_));
-
-  UpdateButtonState();
-}
-
-void ContentExceptionsWindowGtk::UpdateButtonState() {
-  int num_selected = gtk_tree_selection_count_selected_rows(
-      treeview_selection_);
-  int row_count = gtk_tree_model_iter_n_children(
-      GTK_TREE_MODEL(sort_list_store_), NULL);
-
-  // TODO(erg): http://crbug.com/34177 , support editing of more than one entry
-  // at a time.
-  gtk_widget_set_sensitive(edit_button_, num_selected == 1);
-  gtk_widget_set_sensitive(remove_button_, num_selected >= 1);
-  gtk_widget_set_sensitive(remove_all_button_, row_count > 0);
-}
-
-void ContentExceptionsWindowGtk::Add(GtkWidget* widget) {
-  new ContentExceptionEditor(GTK_WINDOW(dialog_),
-                             this, model_.get(), allow_off_the_record_, -1,
-                             ContentSettingsPattern(),
-                             CONTENT_SETTING_BLOCK, false);
-}
-
-void ContentExceptionsWindowGtk::Edit(GtkWidget* widget) {
-  std::set<std::pair<int, int> > indices;
-  GetSelectedModelIndices(&indices);
-  DCHECK_GT(indices.size(), 0u);
-  int index = indices.begin()->first;
-  const HostContentSettingsMap::PatternSettingPair& entry =
-      model_->entry_at(index);
-  new ContentExceptionEditor(GTK_WINDOW(dialog_), this, model_.get(),
-                             allow_off_the_record_, index,
-                             entry.first, entry.second,
-                             model_->entry_is_off_the_record(index));
-}
-
-void ContentExceptionsWindowGtk::Remove(GtkWidget* widget) {
-  std::set<std::pair<int, int> > model_selected_indices;
-  GetSelectedModelIndices(&model_selected_indices);
-
-  int selected_row = gtk_tree_model_iter_n_children(
-      GTK_TREE_MODEL(sort_list_store_), NULL);
-  for (std::set<std::pair<int, int> >::reverse_iterator i =
-           model_selected_indices.rbegin();
-       i != model_selected_indices.rend(); ++i) {
-    model_->RemoveException(i->first);
-    selected_row = std::min(selected_row, i->second);
-  }
-
-  int row_count = model_->RowCount();
-  if (row_count <= 0)
-    return;
-  if (selected_row >= row_count)
-    selected_row = row_count - 1;
-  gtk_tree::SelectAndFocusRowNum(selected_row,
-                                 GTK_TREE_VIEW(treeview_));
-
-  UpdateButtonState();
-}
-
-void ContentExceptionsWindowGtk::RemoveAll(GtkWidget* widget) {
-  model_->RemoveAll();
-  UpdateButtonState();
-}
-
-std::string ContentExceptionsWindowGtk::GetWindowTitle() const {
-  switch (model_->content_type()) {
-    case CONTENT_SETTINGS_TYPE_COOKIES:
-      return l10n_util::GetStringUTF8(IDS_COOKIE_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_IMAGES:
-      return l10n_util::GetStringUTF8(IDS_IMAGES_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
-      return l10n_util::GetStringUTF8(IDS_JS_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_PLUGINS:
-      return l10n_util::GetStringUTF8(IDS_PLUGINS_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_POPUPS:
-      return l10n_util::GetStringUTF8(IDS_POPUP_EXCEPTION_TITLE);
-    default:
-      NOTREACHED();
-  }
-  return std::string();
-}
-
-void ContentExceptionsWindowGtk::GetSelectedModelIndices(
-    std::set<std::pair<int, int> >* indices) {
-  GtkTreeModel* model;
-  GList* paths = gtk_tree_selection_get_selected_rows(treeview_selection_,
-                                                      &model);
-  for (GList* item = paths; item; item = item->next) {
-    GtkTreePath* sorted_path = reinterpret_cast<GtkTreePath*>(item->data);
-    int sorted_row = gtk_tree::GetRowNumForPath(sorted_path);
-    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
-        GTK_TREE_MODEL_SORT(sort_list_store_), sorted_path);
-    int row = gtk_tree::GetRowNumForPath(path);
-    gtk_tree_path_free(path);
-    indices->insert(std::make_pair(row, sorted_row));
-  }
-
-  g_list_foreach(paths, (GFunc)gtk_tree_path_free, NULL);
-  g_list_free(paths);
-}
-
-void ContentExceptionsWindowGtk::OnTreeViewRowActivate(
-    GtkWidget* sender,
-    GtkTreePath* path,
-    GtkTreeViewColumn* column) {
-  Edit(sender);
-}
-
-void ContentExceptionsWindowGtk::OnWindowDestroy(GtkWidget* widget) {
-  instances[model_->content_type()] = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void ContentExceptionsWindowGtk::OnTreeSelectionChanged(
-    GtkWidget* selection) {
-  UpdateButtonState();
-}
diff --git a/chrome/browser/gtk/options/content_exceptions_window_gtk.h b/chrome/browser/gtk/options/content_exceptions_window_gtk.h
deleted file mode 100644
index 0f70c90..0000000
--- a/chrome/browser/gtk/options/content_exceptions_window_gtk.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_CONTENT_EXCEPTIONS_WINDOW_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_CONTENT_EXCEPTIONS_WINDOW_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/content_exceptions_table_model.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/options/content_exception_editor.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/content_settings_types.h"
-
-class HostContentSettingsMap;
-
-// Dialog that lists each of the exceptions to the current content policy, and
-// has options for adding/editing/removing entries. Modal to parrent.
-class ContentExceptionsWindowGtk : public gtk_tree::TableAdapter::Delegate,
-                                   public ContentExceptionEditor::Delegate {
- public:
-  static void ShowExceptionsWindow(GtkWindow* window,
-                                   HostContentSettingsMap* map,
-                                   HostContentSettingsMap* off_the_record_map,
-                                   ContentSettingsType content_type);
-
-  ~ContentExceptionsWindowGtk();
-
-  // gtk_tree::TableAdapter::Delegate implementation:
-  virtual void SetColumnValues(int row, GtkTreeIter* iter);
-
-  // ContentExceptionEditor::Delegate implementation:
-  virtual void AcceptExceptionEdit(
-      const ContentSettingsPattern& pattern,
-      ContentSetting setting,
-      bool is_off_the_record,
-      int index,
-      bool is_new);
-
- private:
-  // Column ids for |list_store_|.
-  enum {
-    COL_PATTERN,
-    COL_ACTION,
-    COL_OTR,
-    COL_COUNT
-  };
-
-  ContentExceptionsWindowGtk(GtkWindow* parent,
-                             HostContentSettingsMap* map,
-                             HostContentSettingsMap* off_the_record_map,
-                             ContentSettingsType type);
-
-  // Updates which buttons are enabled.
-  void UpdateButtonState();
-
-  // Callbacks for the buttons.
-  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, Add);
-  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, Edit);
-  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, Remove);
-  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, RemoveAll);
-
-  // Returns the title of the window (changes based on what ContentSettingsType
-  // was set to in the constructor).
-  std::string GetWindowTitle() const;
-
-  // Gets the selected indicies in the two list stores. Indicies are returned
-  // in <list_store_, sort_list_store_> order.
-  void GetSelectedModelIndices(std::set<std::pair<int, int> >* indices);
-
-  // GTK Callbacks
-  CHROMEGTK_CALLBACK_2(ContentExceptionsWindowGtk, void,
-                       OnTreeViewRowActivate, GtkTreePath*, GtkTreeViewColumn*);
-  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, OnWindowDestroy);
-  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void,
-                       OnTreeSelectionChanged);
-
-  // The list presented in |treeview_|. Separate from |list_store_|, the list
-  // that backs |sort_model_|. This separation comes so the user can sort the
-  // data on screen without changing the underlying |list_store_|.
-  GtkTreeModel* sort_list_store_;
-
-  // The backing to |sort_list_store_|. Doesn't change when sorted.
-  GtkListStore* list_store_;
-
-  // The C++, views-ish, cross-platform model class that actually contains the
-  // gold standard data.
-  scoped_ptr<ContentExceptionsTableModel> model_;
-
-  // True if we also show exceptions from an OTR profile.
-  bool allow_off_the_record_;
-
-  // The adapter that ferries data back and forth between |model_| and
-  // |list_store_| whenever either of them change.
-  scoped_ptr<gtk_tree::TableAdapter> model_adapter_;
-
-  // The exception window.
-  GtkWidget* dialog_;
-
-  // The treeview that presents the site/action pairs.
-  GtkWidget* treeview_;
-
-  // The current user selection from |treeview_|.
-  GtkTreeSelection* treeview_selection_;
-
-  // Buttons.
-  GtkWidget* edit_button_;
-  GtkWidget* remove_button_;
-  GtkWidget* remove_all_button_;
-
-  friend class ContentExceptionsWindowGtkUnittest;
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_CONTENT_EXCEPTIONS_WINDOW_GTK_H_
diff --git a/chrome/browser/gtk/options/content_exceptions_window_gtk_unittest.cc b/chrome/browser/gtk/options/content_exceptions_window_gtk_unittest.cc
deleted file mode 100644
index 8af7c55..0000000
--- a/chrome/browser/gtk/options/content_exceptions_window_gtk_unittest.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/content_exceptions_window_gtk.h"
-
-#include "chrome/test/testing_profile.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-
-class ContentExceptionsWindowGtkUnittest : public testing::Test {
- public:
-  ContentExceptionsWindowGtkUnittest()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        host_content_settings_map_(profile_.GetHostContentSettingsMap()),
-        window_(NULL) {
-  }
-
-  ~ContentExceptionsWindowGtkUnittest() {
-    // This will delete window_ too.
-    gtk_widget_destroy(window_->dialog_);
-    message_loop_.RunAllPending();
-  }
-
-  void AddException(const std::string& pattern, ContentSetting value) {
-    host_content_settings_map_->SetContentSetting(
-        ContentSettingsPattern(pattern),
-        CONTENT_SETTINGS_TYPE_JAVASCRIPT,
-        "",
-        value);
-  }
-
-  void BuildWindow() {
-    window_ = new ContentExceptionsWindowGtk(
-        NULL,
-        host_content_settings_map_,
-        NULL,
-        CONTENT_SETTINGS_TYPE_JAVASCRIPT);
-  }
-
-  // Actions:
-  void SelectRows(const std::vector<int>& rows) {
-    gtk_tree_selection_unselect_all(window_->treeview_selection_);
-
-    for (std::vector<int>::const_iterator it = rows.begin(); it != rows.end();
-         ++it) {
-      GtkTreeIter iter;
-      if (!gtk_tree_model_iter_nth_child(window_->sort_list_store_,
-                                         &iter, NULL, *it)) {
-        NOTREACHED();
-        return;
-      }
-
-      gtk_tree_selection_select_iter(window_->treeview_selection_, &iter);
-    }
-  }
-
-  void Remove() {
-    window_->Remove(window_->remove_button_);
-  }
-
-  // Getters:
-
-  void GetSelectedRows(std::set<std::pair<int, int> >* selected) {
-    window_->GetSelectedModelIndices(selected);
-  }
-
-  int StoreListStoreCount() {
-    return gtk_tree_model_iter_n_children(
-        GTK_TREE_MODEL(window_->sort_list_store_), NULL);
-  }
-
-  int ListStoreCount() {
-    return gtk_tree_model_iter_n_children(
-        GTK_TREE_MODEL(window_->list_store_), NULL);
-  }
-
-  std::set<std::string> Paths() {
-    std::set<std::string> paths;
-    GtkTreeIter iter;
-    bool valid = gtk_tree_model_get_iter_first(
-        GTK_TREE_MODEL(window_->sort_list_store_), &iter);
-
-    while (valid) {
-      gchar* str = NULL;
-      gtk_tree_model_get(GTK_TREE_MODEL(window_->sort_list_store_), &iter,
-                         0, &str, -1);
-      paths.insert(str);
-      g_free(str);
-
-      valid = gtk_tree_model_iter_next(
-          GTK_TREE_MODEL(window_->sort_list_store_), &iter);
-    }
-
-    return paths;
-  }
-
-  // Whether certain widgets are enabled:
-  bool EditButtonSensitive() {
-    return GTK_WIDGET_SENSITIVE(window_->edit_button_);
-  }
-
-  bool RemoveButtonSensitive() {
-    return GTK_WIDGET_SENSITIVE(window_->remove_button_);
-  }
-
-  bool RemoveAllSensitive() {
-    return GTK_WIDGET_SENSITIVE(window_->remove_all_button_);
-  }
-
- private:
-  MessageLoop message_loop_;
-  BrowserThread ui_thread_;
-
-  TestingProfile profile_;
-  HostContentSettingsMap* host_content_settings_map_;
-
-  ContentExceptionsWindowGtk* window_;
-};
-
-TEST_F(ContentExceptionsWindowGtkUnittest, TestEmptyDisplay) {
-  BuildWindow();
-
-  EXPECT_EQ(0, StoreListStoreCount());
-  EXPECT_EQ(0, ListStoreCount());
-
-  EXPECT_FALSE(RemoveAllSensitive());
-}
-
-TEST_F(ContentExceptionsWindowGtkUnittest, TestDisplay) {
-  AddException("a", CONTENT_SETTING_BLOCK);
-  AddException("b", CONTENT_SETTING_ALLOW);
-
-  BuildWindow();
-
-  EXPECT_EQ(2, StoreListStoreCount());
-  EXPECT_EQ(2, ListStoreCount());
-
-  EXPECT_TRUE(RemoveAllSensitive());
-}
-
-TEST_F(ContentExceptionsWindowGtkUnittest, TestSelection) {
-  AddException("a", CONTENT_SETTING_BLOCK);
-
-  BuildWindow();
-
-  EXPECT_FALSE(EditButtonSensitive());
-  EXPECT_FALSE(RemoveButtonSensitive());
-
-  std::vector<int> rows;
-  rows.push_back(0);
-  SelectRows(rows);
-
-  EXPECT_TRUE(EditButtonSensitive());
-  EXPECT_TRUE(RemoveButtonSensitive());
-}
-
-TEST_F(ContentExceptionsWindowGtkUnittest, TestSimpleRemoval) {
-  AddException("a", CONTENT_SETTING_BLOCK);
-  AddException("b", CONTENT_SETTING_ALLOW);
-  AddException("c", CONTENT_SETTING_BLOCK);
-  AddException("d", CONTENT_SETTING_ALLOW);
-
-  BuildWindow();
-
-  std::vector<int> rows;
-  rows.push_back(1);
-  SelectRows(rows);
-
-  Remove();
-
-  EXPECT_EQ(3, StoreListStoreCount());
-  EXPECT_EQ(3, ListStoreCount());
-  EXPECT_TRUE(EditButtonSensitive());
-  EXPECT_TRUE(RemoveButtonSensitive());
-
-  std::set<std::pair<int, int> > selected;
-  GetSelectedRows(&selected);
-
-  ASSERT_EQ(1u, selected.size());
-  EXPECT_EQ(1, selected.begin()->first);
-  EXPECT_EQ(1, selected.begin()->second);
-  EXPECT_THAT(Paths(), ElementsAre("a", "c", "d"));
-}
-
-TEST_F(ContentExceptionsWindowGtkUnittest, TestComplexRemoval) {
-  AddException("a", CONTENT_SETTING_BLOCK);
-  AddException("b", CONTENT_SETTING_ALLOW);
-  AddException("c", CONTENT_SETTING_BLOCK);
-  AddException("d", CONTENT_SETTING_ALLOW);
-  AddException("e", CONTENT_SETTING_BLOCK);
-
-  BuildWindow();
-
-  std::vector<int> rows;
-  rows.push_back(1);
-  rows.push_back(3);
-  SelectRows(rows);
-
-  Remove();
-
-  std::set<std::pair<int, int> > selected;
-  GetSelectedRows(&selected);
-
-  ASSERT_EQ(1u, selected.size());
-  EXPECT_EQ(1, selected.begin()->first);
-  EXPECT_EQ(1, selected.begin()->second);
-  EXPECT_THAT(Paths(), ElementsAre("a", "c", "e"));
-}
diff --git a/chrome/browser/gtk/options/content_filter_page_gtk.cc b/chrome/browser/gtk/options/content_filter_page_gtk.cc
deleted file mode 100644
index 13aeb05..0000000
--- a/chrome/browser/gtk/options/content_filter_page_gtk.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/content_filter_page_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "chrome/browser/content_settings/content_settings_details.h"
-#include "chrome/browser/content_settings/content_settings_pattern.h"
-#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
-#include "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
-#include "chrome/browser/plugin_exceptions_table_model.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/content_exceptions_window_gtk.h"
-#include "chrome/browser/gtk/options/simple_content_exceptions_window.h"
-#include "chrome/browser/notifications/desktop_notification_service.h"
-#include "chrome/browser/notifications/notification_exceptions_table_model.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/url_constants.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-ContentFilterPageGtk::ContentFilterPageGtk(Profile* profile,
-                                           ContentSettingsType content_type)
-    : OptionsPageBase(profile),
-      content_type_(content_type),
-      ask_radio_(NULL),
-      ignore_toggle_(false) {
-  static const int kTitleIDs[] = {
-    0,  // This dialog isn't used for cookies.
-    IDS_IMAGES_SETTING_LABEL,
-    IDS_JS_SETTING_LABEL,
-    IDS_PLUGIN_SETTING_LABEL,
-    IDS_POPUP_SETTING_LABEL,
-    IDS_GEOLOCATION_SETTING_LABEL,
-    IDS_NOTIFICATIONS_SETTING_LABEL,
-  };
-  COMPILE_ASSERT(arraysize(kTitleIDs) == CONTENT_SETTINGS_NUM_TYPES,
-                 kTitleIDs_IncorrectSize);
-
-  GtkWidget* title_label = gtk_util::CreateBoldLabel(
-      l10n_util::GetStringUTF8(kTitleIDs[content_type_]));
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(page_), title_label, FALSE, FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(page_), InitGroup());
-}
-
-ContentFilterPageGtk::~ContentFilterPageGtk() {
-}
-
-
-GtkWidget* ContentFilterPageGtk::InitGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  static const int kAllowIDs[] = {
-    0,  // This dialog isn't used for cookies.
-    IDS_IMAGES_LOAD_RADIO,
-    IDS_JS_ALLOW_RADIO,
-    IDS_PLUGIN_LOAD_RADIO,
-    IDS_POPUP_ALLOW_RADIO,
-    IDS_GEOLOCATION_ALLOW_RADIO,
-    IDS_NOTIFICATIONS_ALLOW_RADIO,
-  };
-  COMPILE_ASSERT(arraysize(kAllowIDs) == CONTENT_SETTINGS_NUM_TYPES,
-                 kAllowIDs_IncorrectSize);
-  allow_radio_ = gtk_radio_button_new_with_label(NULL,
-      l10n_util::GetStringUTF8(kAllowIDs[content_type_]).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), allow_radio_, FALSE, FALSE, 0);
-
-  static const int kAskIDs[] = {
-     0,  // This dialog isn't used for cookies.
-     0,
-     0,
-     IDS_PLUGIN_ASK_RADIO,
-     0,
-     IDS_GEOLOCATION_ASK_RADIO,
-     IDS_NOTIFICATIONS_ASK_RADIO,
-  };
-  COMPILE_ASSERT(arraysize(kAskIDs) == CONTENT_SETTINGS_NUM_TYPES,
-                 kAskIDs_IncorrectSize);
-  int askID = kAskIDs[content_type_];
-  if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS &&
-      !CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableClickToPlay)) {
-    askID = 0;
-  }
-
-  if (askID) {
-    ask_radio_ = gtk_radio_button_new_with_label_from_widget(
-        GTK_RADIO_BUTTON(allow_radio_),
-        l10n_util::GetStringUTF8(askID).c_str());
-    gtk_box_pack_start(GTK_BOX(vbox), ask_radio_, FALSE, FALSE, 0);
-  }
-
-  static const int kBlockIDs[] = {
-    0,  // This dialog isn't used for cookies.
-    IDS_IMAGES_NOLOAD_RADIO,
-    IDS_JS_DONOTALLOW_RADIO,
-    IDS_PLUGIN_NOLOAD_RADIO,
-    IDS_POPUP_BLOCK_RADIO,
-    IDS_GEOLOCATION_BLOCK_RADIO,
-    IDS_NOTIFICATIONS_BLOCK_RADIO,
-  };
-  COMPILE_ASSERT(arraysize(kBlockIDs) == CONTENT_SETTINGS_NUM_TYPES,
-                 kBlockIDs_IncorrectSize);
-  block_radio_ = gtk_radio_button_new_with_label_from_widget(
-      GTK_RADIO_BUTTON(allow_radio_),
-      l10n_util::GetStringUTF8(kBlockIDs[content_type_]).c_str());
-  gtk_box_pack_start(GTK_BOX(vbox), block_radio_, FALSE, FALSE, 0);
-
-  exceptions_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str());
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), exceptions_button_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-  g_signal_connect(G_OBJECT(allow_radio_), "toggled",
-                   G_CALLBACK(OnAllowToggledThunk), this);
-  if (ask_radio_) {
-    g_signal_connect(G_OBJECT(ask_radio_), "toggled",
-                     G_CALLBACK(OnAllowToggledThunk), this);
-  }
-  g_signal_connect(G_OBJECT(block_radio_), "toggled",
-                   G_CALLBACK(OnAllowToggledThunk), this);
-
-  g_signal_connect(G_OBJECT(exceptions_button_), "clicked",
-                   G_CALLBACK(OnExceptionsClickedThunk), this);
-
-  // Add the "Disable individual plug-ins..." link on the plug-ins page.
-  if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) {
-    GtkWidget* plugins_page_link = gtk_chrome_link_button_new(
-        l10n_util::GetStringUTF8(IDS_PLUGIN_SELECTIVE_DISABLE).c_str());
-    g_signal_connect(G_OBJECT(plugins_page_link), "clicked",
-                     G_CALLBACK(OnPluginsPageLinkClickedThunk), this);
-
-    hbox = gtk_hbox_new(FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(hbox), plugins_page_link, FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-  }
-
-  // Now that the buttons have been added to the view hierarchy, it's safe to
-  // call SetChecked() on them. So Update the Buttons.
-  ignore_toggle_ = true;
-  UpdateButtonsState();
-  ignore_toggle_ = false;
-
-  // Register for CONTENT_SETTINGS_CHANGED notifications to update the UI
-  // aften content settings change.
-  registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
-                 NotificationService::AllSources());
-  registrar_.Add(this, NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED,
-                 NotificationService::AllSources());
-  registrar_.Add(this, NotificationType::GEOLOCATION_SETTINGS_CHANGED,
-                 NotificationService::AllSources());
-
-  return vbox;
-}
-
-void ContentFilterPageGtk::UpdateButtonsState() {
-  // Get default_setting.
-  ContentSetting default_setting;
-  // If the content setting is managed, sensitive is set to false and the radio
-  // buttons will be disabled.
-  bool sensitive = true;
-  if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    default_setting = profile()->GetGeolocationContentSettingsMap()->
-        GetDefaultContentSetting();
-    sensitive = !profile()->GetGeolocationContentSettingsMap()->
-        IsDefaultContentSettingManaged();
-  } else if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-    default_setting = profile()->GetDesktopNotificationService()->
-        GetDefaultContentSetting();
-    sensitive = !profile()->GetDesktopNotificationService()->
-        IsDefaultContentSettingManaged();
-  } else {
-    default_setting = profile()->GetHostContentSettingsMap()->
-        GetDefaultContentSetting(content_type_);
-    sensitive = !profile()->GetHostContentSettingsMap()->
-        IsDefaultContentSettingManaged(content_type_);
-  }
-  // Set UI state.
-  if (default_setting == CONTENT_SETTING_ALLOW) {
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE);
-  } else if (default_setting == CONTENT_SETTING_ASK) {
-    DCHECK(ask_radio_);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ask_radio_), TRUE);
-  } else {
-    DCHECK(default_setting == CONTENT_SETTING_BLOCK);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE);
-  }
-
-  // Disable the UI if the default content setting is managed.
-  gtk_widget_set_sensitive(allow_radio_, sensitive);
-  gtk_widget_set_sensitive(block_radio_, sensitive);
-  if (ask_radio_)
-    gtk_widget_set_sensitive(ask_radio_, sensitive);
-  gtk_widget_set_sensitive(exceptions_button_, sensitive);
-}
-
-void ContentFilterPageGtk::OnAllowToggled(GtkWidget* toggle_button) {
-  if (ignore_toggle_)
-    return;
-
-  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
-    // When selecting a radio button, we get two signals (one for the old radio
-    // being toggled off, one for the new one being toggled on.)  Ignore the
-    // signal for toggling off the old button.
-    return;
-  }
-
-  DCHECK((toggle_button == allow_radio_) ||
-         (toggle_button == ask_radio_) ||
-         (toggle_button == block_radio_));
-
-  ContentSetting default_setting =
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(allow_radio_)) ?
-          CONTENT_SETTING_ALLOW :
-          gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(block_radio_)) ?
-              CONTENT_SETTING_BLOCK : CONTENT_SETTING_ASK;
-
-  DCHECK(ask_radio_ || default_setting != CONTENT_SETTING_ASK);
-  if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    profile()->GetGeolocationContentSettingsMap()->SetDefaultContentSetting(
-        default_setting);
-  } else if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-    profile()->GetDesktopNotificationService()->SetDefaultContentSetting(
-        default_setting);
-  } else {
-    profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
-        content_type_, default_setting);
-  }
-}
-
-void ContentFilterPageGtk::OnExceptionsClicked(GtkWidget* button) {
-  if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
-    SimpleContentExceptionsWindow::ShowExceptionsWindow(
-        GTK_WINDOW(gtk_widget_get_toplevel(button)),
-        new GeolocationExceptionsTableModel(
-            profile()->GetGeolocationContentSettingsMap()),
-        IDS_GEOLOCATION_EXCEPTION_TITLE);
-    return;
-  }
-  if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-    SimpleContentExceptionsWindow::ShowExceptionsWindow(
-        GTK_WINDOW(gtk_widget_get_toplevel(button)),
-        new NotificationExceptionsTableModel(
-            profile()->GetDesktopNotificationService()),
-        IDS_NOTIFICATIONS_EXCEPTION_TITLE);
-    return;
-  }
-  HostContentSettingsMap* settings_map =
-      profile()->GetHostContentSettingsMap();
-  HostContentSettingsMap* otr_settings_map =
-      profile()->HasOffTheRecordProfile() ?
-          profile()->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
-          NULL;
-  if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS &&
-      CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableResourceContentSettings)) {
-    PluginExceptionsTableModel* model =
-        new PluginExceptionsTableModel(settings_map, otr_settings_map);
-    model->LoadSettings();
-    SimpleContentExceptionsWindow::ShowExceptionsWindow(
-        GTK_WINDOW(gtk_widget_get_toplevel(button)),
-        model,
-        IDS_PLUGINS_EXCEPTION_TITLE);
-    return;
-  }
-  ContentExceptionsWindowGtk::ShowExceptionsWindow(
-      GTK_WINDOW(gtk_widget_get_toplevel(button)),
-      settings_map, otr_settings_map, content_type_);
-}
-
-void ContentFilterPageGtk::OnPluginsPageLinkClicked(GtkWidget* button) {
-  browser::ShowOptionsURL(profile(), GURL(chrome::kChromeUIPluginsURL));
-}
-
-void ContentFilterPageGtk::Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-  if (type == NotificationType::CONTENT_SETTINGS_CHANGED) {
-    NotifyContentSettingsChanged(
-        Details<const ContentSettingsDetails>(details).ptr());
-  } else if (type == NotificationType::GEOLOCATION_SETTINGS_CHANGED) {
-    NotifyContentSettingsChanged(
-        Details<const ContentSettingsDetails>(details).ptr());
-  } else if (type == NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED) {
-    ContentSettingsDetails content_settings_details(
-        ContentSettingsPattern(),
-        CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
-        "");
-    NotifyContentSettingsChanged(&content_settings_details);
-  } else {
-    OptionsPageBase::Observe(type, source, details);
-  }
-}
-
-void ContentFilterPageGtk::NotifyContentSettingsChanged(
-    const ContentSettingsDetails *details) {
-  if (details->type() == CONTENT_SETTINGS_TYPE_DEFAULT ||
-      details->type() == content_type_) {
-    ignore_toggle_ = true;
-    UpdateButtonsState();
-    ignore_toggle_ = false;
-  }
-}
diff --git a/chrome/browser/gtk/options/content_filter_page_gtk.h b/chrome/browser/gtk/options/content_filter_page_gtk.h
deleted file mode 100644
index d5d3de2..0000000
--- a/chrome/browser/gtk/options/content_filter_page_gtk.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_CONTENT_FILTER_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_CONTENT_FILTER_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/content_settings_types.h"
-#include "chrome/common/notification_registrar.h"
-
-class ContentSettingsDetails;
-
-// A page in the content settings window. Used for everything but the Cookies
-// page (which has a much more complex dialog). A |content_type| is passed into
-// the constructor and the correct strings and settings are used.
-class ContentFilterPageGtk : public OptionsPageBase {
- public:
-  ContentFilterPageGtk(Profile* profile, ContentSettingsType content_type);
-  virtual ~ContentFilterPageGtk();
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  // This method is called during initialization to set the initial state of the
-  // buttons and called after a default content setting change (either value
-  // change or "is managed" state).
-  virtual void UpdateButtonsState();
-
-  virtual void NotifyContentSettingsChanged(
-      const ContentSettingsDetails* details);
-
-  // Builds the content of the dialog.
-  GtkWidget* InitGroup();
-
-  CHROMEGTK_CALLBACK_0(ContentFilterPageGtk, void, OnAllowToggled);
-  CHROMEGTK_CALLBACK_0(ContentFilterPageGtk, void, OnExceptionsClicked);
-  CHROMEGTK_CALLBACK_0(ContentFilterPageGtk, void, OnPluginsPageLinkClicked);
-
-  ContentSettingsType content_type_;
-
-  GtkWidget* page_;
-
-  // Controls for the content filter tab page.
-  GtkWidget* allow_radio_;
-  GtkWidget* ask_radio_;
-  GtkWidget* block_radio_;
-
-  GtkWidget* exceptions_button_;
-
-  NotificationRegistrar registrar_;
-
-  // If state of the UI is not changed by a user-action we need to ignore
-  // "toggled" events.
-  bool ignore_toggle_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentFilterPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_CONTENT_FILTER_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc
deleted file mode 100644
index 0981456..0000000
--- a/chrome/browser/gtk/options/content_page_gtk.cc
+++ /dev/null
@@ -1,621 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/content_page_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/import_dialog_gtk.h"
-#include "chrome/browser/gtk/options/options_layout_gtk.h"
-#include "chrome/browser/gtk/options/passwords_exceptions_window_gtk.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/options/options_window_view.h"
-#endif  // defined(OS_CHROMEOS)
-
-namespace {
-
-// Background color for the status label when it's showing an error.
-static const GdkColor kSyncLabelErrorBgColor = GDK_COLOR_RGB(0xff, 0x9a, 0x9a);
-
-// Helper for WrapLabelAtAllocationHack.
-void OnLabelAllocate(GtkWidget* label, GtkAllocation* allocation) {
-  gtk_util::SetLabelWidth(label, allocation->width);
-
-  // Disconnect ourselves.  Repeatedly resizing based on allocation causes
-  // the dialog to become unshrinkable.
-  g_signal_handlers_disconnect_by_func(
-      label, reinterpret_cast<gpointer>(OnLabelAllocate), NULL);
-}
-
-// Set the label to use a request size equal to its initial allocation
-// size.  This causes the label to wrap at the width of the container
-// it is in, instead of at the default width.  This is called a hack
-// because GTK doesn't really work when a widget to make its size
-// request depend on its allocation.  It does, however, have the
-// intended effect of wrapping the label at the proper width.
-void WrapLabelAtAllocationHack(GtkWidget* label) {
-  g_signal_connect(label, "size-allocate",
-                   G_CALLBACK(OnLabelAllocate), NULL);
-}
-
-}  // anonymous namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// ContentPageGtk, public:
-
-ContentPageGtk::ContentPageGtk(Profile* profile)
-    : OptionsPageBase(profile),
-      sync_status_label_background_(NULL),
-      sync_status_label_(NULL),
-#if !defined(OS_CHROMEOS)
-      sync_action_link_background_(NULL),
-      sync_action_link_(NULL),
-#endif
-      sync_start_stop_button_(NULL),
-      sync_customize_button_(NULL),
-      privacy_dashboard_link_(NULL),
-      initializing_(true),
-      sync_service_(NULL),
-      managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_CONTENT) {
-  if (profile->GetProfileSyncService()) {
-    sync_service_ = profile->GetProfileSyncService();
-    sync_service_->AddObserver(this);
-  }
-
-  // Prepare the group options layout.
-  scoped_ptr<OptionsLayoutBuilderGtk>
-    options_builder(OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout());
-  options_builder->AddWidget(managed_prefs_banner_.banner_widget(), false);
-  if (sync_service_) {
-    options_builder->AddOptionGroup(
-        l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_GROUP_NAME),
-        InitSyncGroup(), false);
-    UpdateSyncControls();
-  }
-
-  // Add preferences observers.
-  ask_to_save_passwords_.Init(prefs::kPasswordManagerEnabled,
-                              profile->GetPrefs(), this);
-  form_autofill_enabled_.Init(prefs::kAutoFillEnabled,
-                              profile->GetPrefs(), this);
-  if (browser_defaults::kCanToggleSystemTitleBar) {
-    use_custom_chrome_frame_.Init(prefs::kUseCustomChromeFrame,
-                                  profile->GetPrefs(), this);
-  }
-
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_GROUP_NAME),
-      InitPasswordSavingGroup(), false);
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_AUTOFILL_SETTING_WINDOWS_GROUP_NAME),
-      InitFormAutoFillGroup(), false);
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_BROWSING_DATA_GROUP_NAME),
-      InitBrowsingDataGroup(), false);
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_APPEARANCE_GROUP_NAME),
-      InitThemesGroup(), false);
-  page_ = options_builder->get_page_widget();
-
-  // Load initial values.
-  NotifyPrefChanged(NULL);
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  ObserveThemeChanged();
-}
-
-ContentPageGtk::~ContentPageGtk() {
-  if (sync_service_)
-    sync_service_->RemoveObserver(this);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// ContentsPageView, ProfileSyncServiceObserver implementation:
-
-void ContentPageGtk::OnStateChanged() {
-  // If the UI controls are not yet initialized, then don't do anything. This
-  // can happen if the Options dialog is up, but the Content tab is not yet
-  // clicked.
-  if (!initializing_)
-    UpdateSyncControls();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// ContentPageGtk, private:
-
-// If |pref_name| is NULL, set the state of all the widgets. (This is used
-// in ContentPageGtk() above to initialize the dialog.) Otherwise, reset the
-// state of the widget for the given preference name, as it has changed.
-void ContentPageGtk::NotifyPrefChanged(const std::string* pref_name) {
-  initializing_ = true;
-  if (!pref_name || *pref_name == prefs::kPasswordManagerEnabled) {
-    if (ask_to_save_passwords_.GetValue()) {
-      gtk_toggle_button_set_active(
-          GTK_TOGGLE_BUTTON(passwords_asktosave_radio_), TRUE);
-    } else {
-      gtk_toggle_button_set_active(
-          GTK_TOGGLE_BUTTON(passwords_neversave_radio_), TRUE);
-    }
-    bool isPasswordManagerEnabled = !ask_to_save_passwords_.IsManaged();
-    gtk_widget_set_sensitive(passwords_asktosave_radio_,
-                             isPasswordManagerEnabled);
-    gtk_widget_set_sensitive(passwords_neversave_radio_,
-                             isPasswordManagerEnabled);
-    gtk_widget_set_sensitive(show_passwords_button_,
-                             isPasswordManagerEnabled ||
-                             ask_to_save_passwords_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kAutoFillEnabled) {
-    bool disabled_by_policy = form_autofill_enabled_.IsManaged() &&
-        !form_autofill_enabled_.GetValue();
-    gtk_widget_set_sensitive(autofill_button_, !disabled_by_policy);
-  }
-  if (browser_defaults::kCanToggleSystemTitleBar &&
-      (!pref_name || *pref_name == prefs::kUseCustomChromeFrame)) {
-    if (use_custom_chrome_frame_.GetValue()) {
-      gtk_toggle_button_set_active(
-          GTK_TOGGLE_BUTTON(system_title_bar_hide_radio_), TRUE);
-    } else {
-      gtk_toggle_button_set_active(
-          GTK_TOGGLE_BUTTON(system_title_bar_show_radio_), TRUE);
-    }
-  }
-  initializing_ = false;
-}
-
-void ContentPageGtk::Observe(NotificationType type,
-                             const NotificationSource& source,
-                             const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED)
-    ObserveThemeChanged();
-  else
-    OptionsPageBase::Observe(type, source, details);
-}
-
-void ContentPageGtk::ObserveThemeChanged() {
-#if defined(TOOLKIT_GTK)
-  GtkThemeProvider* provider = GtkThemeProvider::GetFrom(profile());
-  bool is_gtk_theme = provider->UseGtkTheme();
-  gtk_widget_set_sensitive(gtk_theme_button_, !is_gtk_theme);
-#else
-  BrowserThemeProvider* provider =
-      reinterpret_cast<BrowserThemeProvider*>(profile()->GetThemeProvider());
-  bool is_gtk_theme = false;
-#endif
-
-  bool is_classic_theme = !is_gtk_theme && provider->GetThemeID().empty();
-  gtk_widget_set_sensitive(themes_reset_button_, !is_classic_theme);
-}
-
-GtkWidget* ContentPageGtk::InitPasswordSavingGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  // Ask to save radio button.
-  passwords_asktosave_radio_ = gtk_radio_button_new_with_label(NULL,
-      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_ASKTOSAVE).c_str());
-  g_signal_connect(passwords_asktosave_radio_, "toggled",
-                   G_CALLBACK(OnPasswordRadioToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), passwords_asktosave_radio_, FALSE,
-                     FALSE, 0);
-
-  // Never save radio button.
-  passwords_neversave_radio_ = gtk_radio_button_new_with_label_from_widget(
-      GTK_RADIO_BUTTON(passwords_asktosave_radio_),
-      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_NEVERSAVE).c_str());
-  g_signal_connect(passwords_neversave_radio_, "toggled",
-                   G_CALLBACK(OnPasswordRadioToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), passwords_neversave_radio_, FALSE,
-                     FALSE, 0);
-
-  // Add the show passwords button into its own horizontal box so it does not
-  // depend on the spacing above.
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  gtk_container_add(GTK_CONTAINER(vbox), button_hbox);
-  show_passwords_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_SHOWPASSWORDS).c_str());
-  g_signal_connect(show_passwords_button_, "clicked",
-                   G_CALLBACK(OnShowPasswordsButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_hbox), show_passwords_button_, FALSE,
-                     FALSE, 0);
-
-  return vbox;
-}
-
-GtkWidget* ContentPageGtk::InitFormAutoFillGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(vbox), button_hbox);
-
-  // AutoFill button.
-  autofill_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_AUTOFILL_OPTIONS).c_str());
-
-  g_signal_connect(G_OBJECT(autofill_button_), "clicked",
-                   G_CALLBACK(OnAutoFillButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_hbox), autofill_button_, FALSE, FALSE, 0);
-
-  return vbox;
-}
-
-GtkWidget* ContentPageGtk::InitBrowsingDataGroup() {
-  GtkWidget* button_box = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-
-  // Import button.
-  GtkWidget* import_button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_IMPORT_DATA_BUTTON).c_str());
-  g_signal_connect(import_button, "clicked",
-                   G_CALLBACK(OnImportButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_box), import_button, FALSE, FALSE, 0);
-
-  return button_box;
-}
-
-GtkWidget* ContentPageGtk::InitThemesGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-
-#if defined(TOOLKIT_GTK)
-  // GTK theme button.
-  gtk_theme_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_THEMES_GTK_BUTTON).c_str());
-  g_signal_connect(gtk_theme_button_, "clicked",
-                   G_CALLBACK(OnGtkThemeButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), gtk_theme_button_, FALSE, FALSE, 0);
-#endif
-
-  // Reset theme button.
-  themes_reset_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_THEMES_SET_CLASSIC).c_str());
-  g_signal_connect(themes_reset_button_, "clicked",
-                   G_CALLBACK(OnResetDefaultThemeButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), themes_reset_button_, FALSE, FALSE, 0);
-
-  // Get themes button.
-  GtkWidget* themes_gallery_button = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_BUTTON).c_str());
-  g_signal_connect(themes_gallery_button, "clicked",
-                   G_CALLBACK(OnGetThemesButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), themes_gallery_button, FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-  // "Use system title bar and borders" radio buttons.
-  if (browser_defaults::kCanToggleSystemTitleBar) {
-    // Use system title bar and borders
-    system_title_bar_show_radio_ = gtk_radio_button_new_with_label(NULL,
-        l10n_util::GetStringUTF8(IDS_SHOW_WINDOW_DECORATIONS_RADIO).c_str());
-    g_signal_connect(system_title_bar_show_radio_, "toggled",
-                     G_CALLBACK(OnSystemTitleBarRadioToggledThunk), this);
-    gtk_box_pack_start(GTK_BOX(vbox), system_title_bar_show_radio_, FALSE,
-                       FALSE, 0);
-
-    // Hide system title bar and use custom borders
-    system_title_bar_hide_radio_ = gtk_radio_button_new_with_label_from_widget(
-        GTK_RADIO_BUTTON(system_title_bar_show_radio_),
-        l10n_util::GetStringUTF8(IDS_HIDE_WINDOW_DECORATIONS_RADIO).c_str());
-    g_signal_connect(system_title_bar_hide_radio_, "toggled",
-                     G_CALLBACK(OnSystemTitleBarRadioToggledThunk), this);
-    gtk_box_pack_start(GTK_BOX(vbox), system_title_bar_hide_radio_, FALSE,
-                       FALSE, 0);
-  }
-
-  return vbox;
-}
-
-GtkWidget* ContentPageGtk::InitSyncGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  // Sync label.
-  sync_status_label_background_ = gtk_event_box_new();
-  sync_status_label_ = gtk_label_new("");
-  WrapLabelAtAllocationHack(sync_status_label_);
-
-  gtk_misc_set_alignment(GTK_MISC(sync_status_label_), 0, 0.5);
-  gtk_box_pack_start(GTK_BOX(vbox), sync_status_label_background_, FALSE,
-                     FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(sync_status_label_background_),
-                    sync_status_label_);
-
-#if !defined(OS_CHROMEOS)
-  // Sync action link.
-  GtkWidget* link_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  sync_action_link_background_ = gtk_event_box_new();
-  sync_action_link_ = gtk_chrome_link_button_new("");
-  g_signal_connect(sync_action_link_, "clicked",
-                   G_CALLBACK(OnSyncActionLinkClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), link_hbox, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(link_hbox), sync_action_link_background_, FALSE,
-                     FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(sync_action_link_background_),
-                    sync_action_link_);
-  gtk_widget_hide(sync_action_link_background_);
-#endif
-
-  // Add the sync button into its own horizontal box so it does not
-  // depend on the spacing above.
-  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  gtk_container_add(GTK_CONTAINER(vbox), button_hbox);
-  sync_start_stop_button_ = gtk_button_new_with_label("");
-  g_signal_connect(sync_start_stop_button_, "clicked",
-                   G_CALLBACK(OnSyncStartStopButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_hbox), sync_start_stop_button_, FALSE,
-                     FALSE, 0);
-  sync_customize_button_ = gtk_button_new_with_label("");
-  g_signal_connect(sync_customize_button_, "clicked",
-                   G_CALLBACK(OnSyncCustomizeButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_hbox), sync_customize_button_, FALSE,
-                     FALSE, 0);
-
-  // Add the privacy dashboard link.
-  GtkWidget* dashboard_link_hbox =
-      gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  GtkWidget* dashboard_link_background = gtk_event_box_new();
-  std::string dashboard_link_label =
-      l10n_util::GetStringUTF8(IDS_SYNC_PRIVACY_DASHBOARD_LINK_LABEL);
-  privacy_dashboard_link_ =
-      gtk_chrome_link_button_new(dashboard_link_label.c_str());
-  g_signal_connect(privacy_dashboard_link_, "clicked",
-                   G_CALLBACK(OnPrivacyDashboardLinkClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), dashboard_link_hbox, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(dashboard_link_hbox),
-                     dashboard_link_background, FALSE, FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(dashboard_link_background),
-                    privacy_dashboard_link_);
-
-
-  return vbox;
-}
-
-void ContentPageGtk::UpdateSyncControls() {
-  DCHECK(sync_service_);
-  string16 status_label;
-  string16 link_label;
-  std::string customize_button_label;
-  bool managed = sync_service_->IsManaged();
-  bool sync_setup_completed = sync_service_->HasSyncSetupCompleted();
-  bool status_has_error = sync_ui_util::GetStatusLabels(sync_service_,
-      &status_label, &link_label) == sync_ui_util::SYNC_ERROR;
-  customize_button_label =
-    l10n_util::GetStringUTF8(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL);
-
-  std::string start_stop_button_label;
-  bool is_start_stop_button_visible = false;
-  bool is_start_stop_button_sensitive = false;
-  if (sync_setup_completed) {
-    start_stop_button_label =
-        l10n_util::GetStringUTF8(IDS_SYNC_STOP_SYNCING_BUTTON_LABEL);
-#if defined(OS_CHROMEOS)
-    is_start_stop_button_visible = false;
-#else
-    is_start_stop_button_visible = true;
-#endif
-    is_start_stop_button_sensitive = !managed;
-  } else if (sync_service_->SetupInProgress()) {
-    start_stop_button_label =
-        l10n_util::GetStringUTF8(IDS_SYNC_NTP_SETUP_IN_PROGRESS);
-    is_start_stop_button_visible = true;
-    is_start_stop_button_sensitive = false;
-  } else {
-    start_stop_button_label =
-        l10n_util::GetStringUTF8(IDS_SYNC_START_SYNC_BUTTON_LABEL);
-    is_start_stop_button_visible = true;
-    is_start_stop_button_sensitive = !managed;
-  }
-  gtk_widget_set_no_show_all(sync_start_stop_button_,
-                             !is_start_stop_button_visible);
-  if (is_start_stop_button_visible)
-    gtk_widget_show(sync_start_stop_button_);
-  else
-    gtk_widget_hide(sync_start_stop_button_);
-  gtk_widget_set_sensitive(sync_start_stop_button_,
-                           is_start_stop_button_sensitive);
-  gtk_button_set_label(GTK_BUTTON(sync_start_stop_button_),
-                       start_stop_button_label.c_str());
-
-  gtk_label_set_label(GTK_LABEL(sync_status_label_),
-                      UTF16ToUTF8(status_label).c_str());
-
-  gtk_widget_set_child_visible(sync_customize_button_,
-      sync_setup_completed && !status_has_error);
-  gtk_button_set_label(GTK_BUTTON(sync_customize_button_),
-                       customize_button_label.c_str());
-  gtk_widget_set_sensitive(sync_customize_button_, !managed);
-#if !defined(OS_CHROMEOS)
-  gtk_chrome_link_button_set_label(GTK_CHROME_LINK_BUTTON(sync_action_link_),
-                                   UTF16ToUTF8(link_label).c_str());
-  if (link_label.empty()) {
-    gtk_widget_set_no_show_all(sync_action_link_background_, TRUE);
-    gtk_widget_hide(sync_action_link_background_);
-  } else {
-    gtk_widget_set_no_show_all(sync_action_link_background_, FALSE);
-    gtk_widget_show(sync_action_link_background_);
-  }
-  gtk_widget_set_sensitive(sync_action_link_, !managed);
-#endif
-  if (status_has_error) {
-    gtk_widget_modify_bg(sync_status_label_background_, GTK_STATE_NORMAL,
-                         &kSyncLabelErrorBgColor);
-#if !defined(OS_CHROMEOS)
-    gtk_widget_modify_bg(sync_action_link_background_, GTK_STATE_NORMAL,
-                         &kSyncLabelErrorBgColor);
-#endif
-  } else {
-    gtk_widget_modify_bg(sync_status_label_background_, GTK_STATE_NORMAL, NULL);
-#if !defined(OS_CHROMEOS)
-    gtk_widget_modify_bg(sync_action_link_background_, GTK_STATE_NORMAL, NULL);
-#endif
-  }
-}
-
-void ContentPageGtk::OnAutoFillButtonClicked(GtkWidget* widget) {
-  ShowAutoFillDialog(NULL, profile()->GetPersonalDataManager(), profile());
-}
-
-void ContentPageGtk::OnImportButtonClicked(GtkWidget* widget) {
-  ImportDialogGtk::Show(
-      GTK_WINDOW(gtk_widget_get_toplevel(widget)),
-      profile(), importer::ALL);
-}
-
-void ContentPageGtk::OnGtkThemeButtonClicked(GtkWidget* widget) {
-  UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet"),
-                          profile()->GetPrefs());
-  profile()->SetNativeTheme();
-}
-
-void ContentPageGtk::OnResetDefaultThemeButtonClicked(GtkWidget* widget) {
-  UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset"),
-                          profile()->GetPrefs());
-  profile()->ClearTheme();
-}
-
-void ContentPageGtk::OnGetThemesButtonClicked(GtkWidget* widget) {
-  UserMetricsRecordAction(UserMetricsAction("Options_ThemesGallery"),
-                          profile()->GetPrefs());
-#if defined(OS_CHROMEOS)
-  // Close options dialog for ChromeOS becuase it is always stacked on top
-  // of browser window and blocks user's view.
-  chromeos::CloseOptionsWindow();
-#endif  // defined(OS_CHROMEOS)
-
-  BrowserList::GetLastActive()->OpenThemeGalleryTabAndActivate();
-}
-
-void ContentPageGtk::OnSystemTitleBarRadioToggled(GtkWidget* widget) {
-  DCHECK(browser_defaults::kCanToggleSystemTitleBar);
-  if (initializing_)
-    return;
-
-  // We get two signals when selecting a radio button, one for the old radio
-  // being toggled off and one for the new one being toggled on. Ignore the
-  // signal for the toggling off the old button.
-  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
-    return;
-
-  bool use_custom = gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(system_title_bar_hide_radio_));
-  if (use_custom) {
-    UserMetricsRecordAction(UserMetricsAction("Options_CustomFrame_Enable"),
-                            profile()->GetPrefs());
-  } else {
-    UserMetricsRecordAction(UserMetricsAction("Options_CustomFrame_Disable"),
-                            profile()->GetPrefs());
-  }
-
-  use_custom_chrome_frame_.SetValue(use_custom);
-}
-
-void ContentPageGtk::OnShowPasswordsButtonClicked(GtkWidget* widget) {
-  ShowPasswordsExceptionsWindow(profile());
-}
-
-void ContentPageGtk::OnPasswordRadioToggled(GtkWidget* widget) {
-  if (initializing_)
-    return;
-
-  // We get two signals when selecting a radio button, one for the old radio
-  // being toggled off and one for the new one being toggled on. Ignore the
-  // signal for the toggling off the old button.
-  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
-    return;
-
-  bool enabled = gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(passwords_asktosave_radio_));
-  if (enabled) {
-    UserMetricsRecordAction(UserMetricsAction("Options_PasswordManager_Enable"),
-                            profile()->GetPrefs());
-  } else {
-    UserMetricsRecordAction(
-        UserMetricsAction("Options_PasswordManager_Disable"),
-        profile()->GetPrefs());
-  }
-  ask_to_save_passwords_.SetValue(enabled);
-}
-
-void ContentPageGtk::OnSyncStartStopButtonClicked(GtkWidget* widget) {
-  DCHECK(sync_service_ && !sync_service_->IsManaged());
-
-  if (sync_service_->HasSyncSetupCompleted()) {
-    GtkWidget* dialog = gtk_message_dialog_new(
-        GTK_WINDOW(gtk_widget_get_toplevel(widget)),
-        static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
-        GTK_MESSAGE_WARNING,
-        GTK_BUTTONS_NONE,
-        "%s",
-        l10n_util::GetStringFUTF8(
-            IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL,
-            l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
-    gtk_util::ApplyMessageDialogQuirks(dialog);
-    gtk_window_set_title(GTK_WINDOW(dialog),
-                         l10n_util::GetStringUTF8(
-                             IDS_SYNC_STOP_SYNCING_DIALOG_TITLE).c_str());
-    gtk_dialog_add_buttons(
-        GTK_DIALOG(dialog),
-        l10n_util::GetStringUTF8(IDS_CANCEL).c_str(),
-        GTK_RESPONSE_REJECT,
-        l10n_util::GetStringUTF8(
-            IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL).c_str(),
-        GTK_RESPONSE_ACCEPT,
-        NULL);
-
-    g_signal_connect(dialog, "response",
-                     G_CALLBACK(OnStopSyncDialogResponseThunk), this);
-
-    gtk_util::ShowDialog(dialog);
-    return;
-  } else {
-    sync_service_->ShowLoginDialog(NULL);
-    ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
-  }
-}
-
-void ContentPageGtk::OnSyncCustomizeButtonClicked(GtkWidget* widget) {
-  // sync_customize_button_ should be invisible if sync is not yet set up.
-  DCHECK(sync_service_ && !sync_service_->IsManaged() &&
-         sync_service_->HasSyncSetupCompleted());
-  sync_service_->ShowConfigure(NULL);
-}
-
-void ContentPageGtk::OnSyncActionLinkClicked(GtkWidget* widget) {
-  DCHECK(sync_service_ && !sync_service_->IsManaged());
-  sync_service_->ShowConfigure(NULL);
-}
-
-void ContentPageGtk::OnStopSyncDialogResponse(GtkWidget* widget, int response) {
-  if (response == GTK_RESPONSE_ACCEPT) {
-    sync_service_->DisableForUser();
-    ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
-  }
-  gtk_widget_destroy(widget);
-}
-
-void ContentPageGtk::OnPrivacyDashboardLinkClicked(GtkWidget* widget) {
-  BrowserList::GetLastActive()->OpenPrivacyDashboardTabAndActivate();
-}
diff --git a/chrome/browser/gtk/options/content_page_gtk.h b/chrome/browser/gtk/options/content_page_gtk.h
deleted file mode 100644
index eb840b9..0000000
--- a/chrome/browser/gtk/options/content_page_gtk.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_CONTENT_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_CONTENT_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-
-class Profile;
-
-class ContentPageGtk : public OptionsPageBase,
-                       public ProfileSyncServiceObserver {
- public:
-  explicit ContentPageGtk(Profile* profile);
-  ~ContentPageGtk();
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
-  // ProfileSyncServiceObserver method.
-  virtual void OnStateChanged();
-
- private:
-  // Updates various sync controls based on the current sync state.
-  void UpdateSyncControls();
-
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  // Overridden from OptionsPageBase.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Update content area after a theme changed.
-  void ObserveThemeChanged();
-
-  // Initialize the option group widgets, return their container.
-  GtkWidget* InitPasswordSavingGroup();
-  GtkWidget* InitFormAutoFillGroup();
-  GtkWidget* InitBrowsingDataGroup();
-  GtkWidget* InitThemesGroup();
-  GtkWidget* InitSyncGroup();
-
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnImportButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnGtkThemeButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnResetDefaultThemeButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnGetThemesButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSystemTitleBarRadioToggled);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnShowPasswordsButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnPasswordRadioToggled);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnAutoFillButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSyncStartStopButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSyncCustomizeButtonClicked);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSyncActionLinkClicked);
-  CHROMEGTK_CALLBACK_1(ContentPageGtk, void, OnStopSyncDialogResponse, int);
-  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnPrivacyDashboardLinkClicked);
-
-  // Widgets for the Password saving group.
-  GtkWidget* passwords_asktosave_radio_;
-  GtkWidget* passwords_neversave_radio_;
-  GtkWidget* show_passwords_button_;
-
-  // Widgets for the AutoFill group.
-  GtkWidget* autofill_button_;
-
-  // Widgets for the Appearance group.
-  GtkWidget* system_title_bar_show_radio_;
-  GtkWidget* system_title_bar_hide_radio_;
-  GtkWidget* themes_reset_button_;
-#if defined(TOOLKIT_GTK)
-  GtkWidget* gtk_theme_button_;
-#endif
-
-  // Widgets for the Sync group.
-  GtkWidget* sync_status_label_background_;
-  GtkWidget* sync_status_label_;
-  GtkWidget* sync_action_link_background_;
-  GtkWidget* sync_action_link_;
-  GtkWidget* sync_start_stop_button_;
-  GtkWidget* sync_customize_button_;
-  GtkWidget* privacy_dashboard_link_;
-
-  // The parent GtkTable widget
-  GtkWidget* page_;
-
-  // Pref members.
-  BooleanPrefMember ask_to_save_passwords_;
-  BooleanPrefMember form_autofill_enabled_;
-  BooleanPrefMember use_custom_chrome_frame_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool initializing_;
-
-  NotificationRegistrar registrar_;
-
-  // Cached pointer to ProfileSyncService, if it exists. Kept up to date
-  // and NULL-ed out on destruction.
-  ProfileSyncService* sync_service_;
-
-  // Tracks managed preference warning banner state.
-  ManagedPrefsBannerGtk managed_prefs_banner_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_CONTENT_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/content_settings_window_gtk.cc b/chrome/browser/gtk/options/content_settings_window_gtk.cc
deleted file mode 100644
index 91b0019..0000000
--- a/chrome/browser/gtk/options/content_settings_window_gtk.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/content_settings_types.h"
-#include "chrome/common/pref_names.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// The singleton options window object.
-ContentSettingsWindowGtk* settings_window = NULL;
-
-}  // namespace
-
-// static
-void ContentSettingsWindowGtk::Show(GtkWindow* parent,
-                                    ContentSettingsType page,
-                                    Profile* profile) {
-  DCHECK(profile);
-
-  if (!settings_window) {
-    // Creating and initializing a bunch of controls generates a bunch of
-    // spurious events as control values change. Temporarily suppress
-    // accessibility events until the window is created.
-    profile->PauseAccessibilityEvents();
-
-    // Create the options window.
-    settings_window = new ContentSettingsWindowGtk(parent, profile);
-
-    // Resume accessibility events.
-    profile->ResumeAccessibilityEvents();
-  }
-  settings_window->ShowContentSettingsTab(page);
-}
-
-ContentSettingsWindowGtk::ContentSettingsWindowGtk(GtkWindow* parent,
-                                                   Profile* profile)
-    : profile_(profile),
-      cookie_page_(profile),
-      image_page_(profile, CONTENT_SETTINGS_TYPE_IMAGES),
-      javascript_page_(profile, CONTENT_SETTINGS_TYPE_JAVASCRIPT),
-      plugin_page_(profile, CONTENT_SETTINGS_TYPE_PLUGINS),
-      popup_page_(profile, CONTENT_SETTINGS_TYPE_POPUPS),
-      geolocation_page_(profile, CONTENT_SETTINGS_TYPE_GEOLOCATION),
-      notifications_page_(profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
-  const struct {
-    int message_id;
-    GtkWidget* widget;
-  } kNotebookPages[] = {
-    { IDS_COOKIES_TAB_LABEL, cookie_page_.get_page_widget() },
-    { IDS_IMAGES_TAB_LABEL, image_page_.get_page_widget() },
-    { IDS_JAVASCRIPT_TAB_LABEL, javascript_page_.get_page_widget() },
-    { IDS_PLUGIN_TAB_LABEL, plugin_page_.get_page_widget() },
-    { IDS_POPUP_TAB_LABEL, popup_page_.get_page_widget() },
-    { IDS_GEOLOCATION_TAB_LABEL, geolocation_page_.get_page_widget() },
-    { IDS_NOTIFICATIONS_TAB_LABEL, notifications_page_.get_page_widget() },
-  };
-
-  // We don't need to observe changes in this value.
-  last_selected_page_.Init(prefs::kContentSettingsWindowLastTabIndex,
-                           profile->GetPrefs(), NULL);
-
-  std::string dialog_name = l10n_util::GetStringUTF8(
-      IDS_CONTENT_SETTINGS_TITLE);
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-  gtk_window_set_policy(GTK_WINDOW(dialog_), FALSE, FALSE, TRUE);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile_));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
-  // Allow browser windows to go in front of the options dialog in metacity.
-  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-  gtk_util::SetWindowIcon(GTK_WINDOW(dialog_));
-
-  // Create hbox with list view and notebook.
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);
-
-  list_ = gtk_tree_view_new();
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list_), FALSE);
-
-  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
-  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
-      "List Item", renderer, "text", 0, NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(list_), column);
-
-  const int kColumnCount = 1;
-  GtkListStore* store = gtk_list_store_new(kColumnCount, G_TYPE_STRING);
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNotebookPages); ++i) {
-    GtkTreeIter iter;
-    gtk_list_store_append(store, &iter);
-    std::string label = l10n_util::GetStringUTF8(kNotebookPages[i].message_id);
-    gtk_list_store_set(store, &iter, 0, label.c_str(), -1);
-  }
-  gtk_tree_view_set_model(GTK_TREE_VIEW(list_), GTK_TREE_MODEL(store));
-  g_object_unref(store);
-
-  // Needs to happen after the model is all set up.
-  GtkTreeSelection* selection = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(list_));
-  gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
-
-  // Wrap the list widget in a scrolled window in order to have a frame.
-  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
-                                 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
-  gtk_container_add(GTK_CONTAINER(scrolled), list_);
-  gtk_box_pack_start(GTK_BOX(hbox), scrolled, FALSE, FALSE, 0);
-
-  notebook_ = gtk_notebook_new();
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNotebookPages); ++i) {
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook_),
-                             kNotebookPages[i].widget,
-                             NULL);
-  }
-  gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook_), FALSE);
-  gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook_), FALSE);
-  gtk_box_pack_start(GTK_BOX(hbox), notebook_, FALSE, FALSE, 0);
-  DCHECK_EQ(gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)),
-            CONTENT_SETTINGS_NUM_TYPES);
-
-  // Create vbox with "Features:" text and hbox below.
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_CONTENT_SETTINGS_FEATURES_LABEL).c_str());
-  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), vbox);
-
-  // Need to show the notebook before connecting switch-page signal, otherwise
-  // we'll immediately get a signal switching to page 0 and overwrite our
-  // last_selected_page_ value.
-  gtk_util::ShowDialogWithLocalizedSize(dialog_, -1, -1, true);
-
-  g_signal_connect(notebook_, "switch-page",
-                   G_CALLBACK(OnSwitchPageThunk), this);
-  g_signal_connect(selection, "changed",
-                   G_CALLBACK(OnListSelectionChangedThunk), this);
-
-  // We only have one button and don't do any special handling, so just hook it
-  // directly to gtk_widget_destroy.
-  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
-
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-ContentSettingsWindowGtk::~ContentSettingsWindowGtk() {
-}
-
-void ContentSettingsWindowGtk::ShowContentSettingsTab(
-    ContentSettingsType page) {
-  // Bring options window to front if it already existed and isn't already
-  // in front
-  gtk_util::PresentWindow(dialog_,  gtk_get_current_event_time());
-
-  if (page == CONTENT_SETTINGS_TYPE_DEFAULT) {
-    // Remember the last visited page from local state.
-    page = static_cast<ContentSettingsType>(last_selected_page_.GetValue());
-    if (page == CONTENT_SETTINGS_TYPE_DEFAULT)
-      page = CONTENT_SETTINGS_TYPE_COOKIES;
-  }
-  // If the page number is out of bounds, reset to the first tab.
-  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
-    page = CONTENT_SETTINGS_TYPE_COOKIES;
-
-  gtk_tree::SelectAndFocusRowNum(page, GTK_TREE_VIEW(list_));
-}
-
-void ContentSettingsWindowGtk::OnSwitchPage(
-    GtkWidget* notebook,
-    GtkNotebookPage* page,
-    guint page_num) {
-  int index = page_num;
-  DCHECK(index > CONTENT_SETTINGS_TYPE_DEFAULT &&
-         index < CONTENT_SETTINGS_NUM_TYPES);
-
-  // Keep list in sync.
-  GtkTreeModel* model;
-  GtkTreeIter iter;
-  if (gtk_tree_selection_get_selected(
-      gtk_tree_view_get_selection(GTK_TREE_VIEW(list_)), &model, &iter)) {
-    gint row_index = gtk_tree::GetRowNumForIter(model, &iter);
-    if (row_index == index)
-      return;
-  }
-  gtk_tree::SelectAndFocusRowNum(index, GTK_TREE_VIEW(list_));
-}
-
-void ContentSettingsWindowGtk::OnWindowDestroy(GtkWidget* widget) {
-  settings_window = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void ContentSettingsWindowGtk::OnListSelectionChanged(
-    GtkTreeSelection* selection) {
-  GtkTreeModel* model;
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
-    NOTREACHED();
-    return;
-  }
-  gint row_index = gtk_tree::GetRowNumForIter(model, &iter);
-  DCHECK(row_index > CONTENT_SETTINGS_TYPE_DEFAULT &&
-         row_index < CONTENT_SETTINGS_NUM_TYPES);
-
-  last_selected_page_.SetValue(row_index);
-
-  if (row_index != gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_)))
-    gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), row_index);
-}
diff --git a/chrome/browser/gtk/options/content_settings_window_gtk.h b/chrome/browser/gtk/options/content_settings_window_gtk.h
deleted file mode 100644
index 6e32f4a..0000000
--- a/chrome/browser/gtk/options/content_settings_window_gtk.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_CONTENT_SETTINGS_WINDOW_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_CONTENT_SETTINGS_WINDOW_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/options/cookie_filter_page_gtk.h"
-#include "chrome/browser/gtk/options/content_filter_page_gtk.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/common/content_settings_types.h"
-
-class AccessibleWidgetHelper;
-
-// A window that presents options to the user for blocking various kinds of
-// content in webpages (cookies, javascript, images, popups).
-class ContentSettingsWindowGtk {
- public:
-  // Shows the current content settings page, opening a new one if it doesn't
-  // exist.
-  static void Show(GtkWindow* parent, ContentSettingsType page,
-                   Profile* profile);
-  static void RegisterUserPrefs(PrefService* prefs);
-
-  explicit ContentSettingsWindowGtk(GtkWindow* parent, Profile* profile);
-  virtual ~ContentSettingsWindowGtk();
-
- private:
-  // Shows the Tab corresponding to the specified Content Settings page.
-  void ShowContentSettingsTab(ContentSettingsType page);
-
-  CHROMEGTK_CALLBACK_2(ContentSettingsWindowGtk, void, OnSwitchPage,
-                       GtkNotebookPage*, guint);
-  CHROMEGTK_CALLBACK_0(ContentSettingsWindowGtk, void, OnWindowDestroy);
-  CHROMEG_CALLBACK_0(ContentSettingsWindowGtk, void, OnListSelectionChanged,
-                     GtkTreeSelection*);
-
-  // The options dialog.
-  GtkWidget* dialog_;
-
-  // The container of the option pages.
-  GtkWidget* notebook_;
-  GtkWidget* list_;
-
-  // The Profile associated with these options.
-  Profile* profile_;
-
-  // The last page the user was on when they opened the ContentSettings window.
-  IntegerPrefMember last_selected_page_;
-
-  // The individual page implementations. Note that we have a specialized one
-  // for cookies (which have more complex rules) and use the same basic page
-  // layout for each other type.
-  CookieFilterPageGtk cookie_page_;
-  ContentFilterPageGtk image_page_;
-  ContentFilterPageGtk javascript_page_;
-  ContentFilterPageGtk plugin_page_;
-  ContentFilterPageGtk popup_page_;
-  ContentFilterPageGtk geolocation_page_;
-  ContentFilterPageGtk notifications_page_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentSettingsWindowGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_CONTENT_SETTINGS_WINDOW_GTK_H_
diff --git a/chrome/browser/gtk/options/cookie_filter_page_gtk.cc b/chrome/browser/gtk/options/cookie_filter_page_gtk.cc
deleted file mode 100644
index d2fa259..0000000
--- a/chrome/browser/gtk/options/cookie_filter_page_gtk.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/cookie_filter_page_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "chrome/browser/browsing_data_local_storage_helper.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/content_exceptions_window_gtk.h"
-#include "chrome/browser/gtk/options/cookies_view.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Stick small widgets in an hbox so it doesn't expand to the whole width.
-GtkWidget* WrapInHBox(GtkWidget* widget) {
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
-  return hbox;
-}
-
-}  // namespace
-
-CookieFilterPageGtk::CookieFilterPageGtk(Profile* profile)
-    : OptionsPageBase(profile),
-      ignore_toggle_(false) {
-  // The pref members must be initialized first since the pref values are read
-  // afterwards when we initialize the cookie storing group.
-  clear_site_data_on_exit_.Init(prefs::kClearSiteDataOnExit,
-                                profile->GetPrefs(), this);
-
-  block_third_party_cookies_.Init(prefs::kBlockThirdPartyCookies,
-                                  profile->GetPrefs(), this);
-
-  managed_default_cookies_setting_.Init(prefs::kManagedDefaultCookiesSetting,
-                                        profile->GetPrefs(), this);
-
-  GtkWidget* title_label = gtk_util::CreateBoldLabel(
-      l10n_util::GetStringUTF8(IDS_MODIFY_COOKIE_STORING_LABEL));
-  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(page_), title_label, FALSE, FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(page_), InitCookieStoringGroup());
-}
-
-CookieFilterPageGtk::~CookieFilterPageGtk() {
-}
-
-void CookieFilterPageGtk::NotifyPrefChanged(const std::string* pref_name) {
-  AutoReset<bool> toggle_guard(&ignore_toggle_, true);
-
-  if (!pref_name || *pref_name == prefs::kClearSiteDataOnExit) {
-    UpdateUiState();
-  }
-  if (!pref_name || *pref_name == prefs::kManagedDefaultCookiesSetting) {
-    UpdateUiState();
-  }
-  if (!pref_name || *pref_name == prefs::kBlockThirdPartyCookies) {
-    UpdateUiState();
-  }
-}
-
-void CookieFilterPageGtk::HighlightGroup(OptionsGroup highlight_group) {
-  // TODO(erg): implement group highlighting
-}
-
-GtkWidget* CookieFilterPageGtk::InitCookieStoringGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  allow_radio_ = gtk_radio_button_new_with_label(NULL,
-      l10n_util::GetStringUTF8(IDS_COOKIES_ALLOW_RADIO).c_str());
-  g_signal_connect(G_OBJECT(allow_radio_), "toggled",
-                   G_CALLBACK(OnCookiesAllowToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), allow_radio_, FALSE, FALSE, 0);
-
-  block_radio_ = gtk_radio_button_new_with_label_from_widget(
-      GTK_RADIO_BUTTON(allow_radio_),
-      l10n_util::GetStringUTF8(IDS_COOKIES_BLOCK_RADIO).c_str());
-  g_signal_connect(G_OBJECT(block_radio_), "toggled",
-                   G_CALLBACK(OnCookiesAllowToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), block_radio_, FALSE, FALSE, 0);
-
-  exceptions_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str());
-  g_signal_connect(G_OBJECT(exceptions_button_), "clicked",
-                   G_CALLBACK(OnExceptionsClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(exceptions_button_),
-                     FALSE, FALSE, 0);
-
-  block_3rdparty_check_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX).c_str());
-  g_signal_connect(G_OBJECT(block_3rdparty_check_), "toggled",
-                   G_CALLBACK(OnBlockThirdPartyToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), block_3rdparty_check_, FALSE, FALSE, 0);
-
-  clear_on_close_check_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX).c_str());
-  g_signal_connect(G_OBJECT(clear_on_close_check_), "toggled",
-                   G_CALLBACK(OnClearOnCloseToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), clear_on_close_check_, FALSE, FALSE, 0);
-
-  show_cookies_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_COOKIES_SHOW_COOKIES_BUTTON).c_str());
-  g_signal_connect(G_OBJECT(show_cookies_button_), "clicked",
-                   G_CALLBACK(OnShowCookiesClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(show_cookies_button_),
-                     FALSE, FALSE, 0);
-
-  GtkWidget* flash_settings_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_SETTINGS).c_str());
-  g_signal_connect(G_OBJECT(flash_settings_link), "clicked",
-                   G_CALLBACK(OnFlashLinkClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(flash_settings_link),
-                     FALSE, FALSE, 0);
-
-  ignore_toggle_ = true;
-  UpdateUiState();
-  ignore_toggle_ = false;
-
-  return vbox;
-};
-
-void CookieFilterPageGtk::UpdateUiState() {
-  // Get default_setting.
-  ContentSetting default_setting;
-  default_setting = profile()->GetHostContentSettingsMap()->
-      GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
-
-  // Set UI state.
-  if (default_setting == CONTENT_SETTING_ALLOW) {
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE);
-  } else {
-    DCHECK(default_setting == CONTENT_SETTING_BLOCK);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE);
-  }
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(clear_on_close_check_),
-                               clear_site_data_on_exit_.GetValue());
-  gtk_toggle_button_set_active(
-      GTK_TOGGLE_BUTTON(block_3rdparty_check_),
-      block_third_party_cookies_.GetValue());
-
-  // Disable the UI if the default content setting is managed.
-  gtk_widget_set_sensitive(block_3rdparty_check_,
-                           !block_third_party_cookies_.IsManaged());
-  bool sensitive = true;
-  if (profile()->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
-      CONTENT_SETTINGS_TYPE_COOKIES)) {
-    sensitive = false;
-  }
-  gtk_widget_set_sensitive(allow_radio_, sensitive);
-  gtk_widget_set_sensitive(block_radio_, sensitive);
-  gtk_widget_set_sensitive(exceptions_button_, sensitive);
-}
-
-void CookieFilterPageGtk::OnCookiesAllowToggled(GtkWidget* toggle_button) {
-  if (ignore_toggle_)
-    return;
-
-  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
-    // When selecting a radio button, we get two signals (one for the old radio
-    // being toggled off, one for the new one being toggled on.)  Ignore the
-    // signal for toggling off the old button.
-    return;
-  }
-
-  ContentSetting setting = CONTENT_SETTING_ALLOW;
-  if (toggle_button == allow_radio_)
-    setting = CONTENT_SETTING_ALLOW;
-  else if (toggle_button == block_radio_)
-    setting = CONTENT_SETTING_BLOCK;
-
-  profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_COOKIES, setting);
-}
-
-void CookieFilterPageGtk::OnExceptionsClicked(GtkWidget* button) {
-  HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap();
-  HostContentSettingsMap* otr_settings_map =
-      profile()->HasOffTheRecordProfile() ?
-          profile()->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
-          NULL;
-  ContentExceptionsWindowGtk::ShowExceptionsWindow(
-      GTK_WINDOW(gtk_widget_get_toplevel(button)),
-      settings_map, otr_settings_map, CONTENT_SETTINGS_TYPE_COOKIES);
-}
-
-void CookieFilterPageGtk::OnBlockThirdPartyToggled(GtkWidget* toggle_button) {
-  if (ignore_toggle_)
-    return;
-
-  HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap();
-  settings_map->SetBlockThirdPartyCookies(
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
-}
-
-void CookieFilterPageGtk::OnClearOnCloseToggled(GtkWidget* toggle_button) {
-  if (ignore_toggle_)
-    return;
-
-  clear_site_data_on_exit_.SetValue(
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
-}
-
-void CookieFilterPageGtk::OnShowCookiesClicked(GtkWidget* button) {
-  UserMetricsRecordAction(UserMetricsAction("Options_ShowCookies"), NULL);
-  CookiesView::Show(GTK_WINDOW(gtk_widget_get_toplevel(button)),
-                    profile(),
-                    new BrowsingDataDatabaseHelper(profile()),
-                    new BrowsingDataLocalStorageHelper(profile()),
-                    new BrowsingDataAppCacheHelper(profile()),
-                    BrowsingDataIndexedDBHelper::Create(profile()));
-}
-
-void CookieFilterPageGtk::OnFlashLinkClicked(GtkWidget* button) {
-  browser::ShowOptionsURL(
-      profile(), GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)));
-}
diff --git a/chrome/browser/gtk/options/cookie_filter_page_gtk.h b/chrome/browser/gtk/options/cookie_filter_page_gtk.h
deleted file mode 100644
index f07cbdb..0000000
--- a/chrome/browser/gtk/options/cookie_filter_page_gtk.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_COOKIE_FILTER_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_COOKIE_FILTER_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-
-class Profile;
-
-// A page in the content settings window for cookie options. This dialog has
-// more options as is more complicated then all the other pages implemented
-// with ContentPageGtk.
-class CookieFilterPageGtk : public OptionsPageBase {
- public:
-  explicit CookieFilterPageGtk(Profile* profile);
-  virtual ~CookieFilterPageGtk();
-
-  GtkWidget* get_page_widget() const {
-    return page_;
-  }
-
- private:
-  // Updates the UI state.
-  virtual void UpdateUiState();
-
-  // Overridden from OptionsPageBase
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-  virtual void HighlightGroup(OptionsGroup highlight_group);
-
-  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnCookiesAllowToggled);
-  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnExceptionsClicked);
-  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnBlockThirdPartyToggled);
-  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnClearOnCloseToggled);
-  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnShowCookiesClicked);
-  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnFlashLinkClicked);
-
-  GtkWidget* InitCookieStoringGroup();
-
-  // Widgets of the cookie storing group
-  GtkWidget* allow_radio_;
-  GtkWidget* block_radio_;
-
-  GtkWidget* exceptions_button_;
-  GtkWidget* block_3rdparty_check_;
-  GtkWidget* clear_on_close_check_;
-  GtkWidget* show_cookies_button_;
-
-  // The parent GtkTable widget
-  GtkWidget* page_;
-
-  // If state of the UI is not changed by a user-action we need to ignore
-  // "toggled" events.
-  bool ignore_toggle_;
-
-  // Clear locally stored site data on exit pref.
-  BooleanPrefMember clear_site_data_on_exit_;
-
-  // Block third-party-cookies.
-  BooleanPrefMember block_third_party_cookies_;
-
-  // Managed default-cookies-setting.
-  IntegerPrefMember managed_default_cookies_setting_;
-
-  DISALLOW_COPY_AND_ASSIGN(CookieFilterPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_COOKIE_FILTER_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/cookies_view.cc b/chrome/browser/gtk/options/cookies_view.cc
deleted file mode 100644
index 9b4cedd..0000000
--- a/chrome/browser/gtk/options/cookies_view.cc
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/cookies_view.h"
-
-#include <gdk/gdkkeysyms.h>
-#include <set>
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "chrome/browser/cookies_tree_model.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Initial size for dialog.
-const int kDialogDefaultWidth = 550;
-const int kDialogDefaultHeight = 550;
-
-// Delay after entering filter text before filtering occurs.
-const int kSearchFilterDelayMs = 500;
-
-// Response ids for our custom buttons.
-enum {
-  RESPONSE_REMOVE = 1,
-  RESPONSE_REMOVE_ALL
-};
-
-// The currently open cookie manager, if any.
-CookiesView* instance_ = NULL;
-
-}  // namespace
-
-CookiesView::~CookiesView() {
-  if (destroy_dialog_in_destructor_)
-    gtk_widget_destroy(dialog_);
-}
-
-// static
-void CookiesView::Show(
-    GtkWindow* parent,
-    Profile* profile,
-    BrowsingDataDatabaseHelper* browsing_data_database_helper,
-    BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
-    BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
-    BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper) {
-  DCHECK(profile);
-  DCHECK(browsing_data_database_helper);
-  DCHECK(browsing_data_local_storage_helper);
-  DCHECK(browsing_data_appcache_helper);
-  DCHECK(browsing_data_indexed_db_helper);
-
-  // If there's already an existing editor window, activate it.
-  if (instance_) {
-    gtk_util::PresentWindow(instance_->dialog_, 0);
-  } else {
-    instance_ = new CookiesView(parent,
-                                profile,
-                                browsing_data_database_helper,
-                                browsing_data_local_storage_helper,
-                                browsing_data_appcache_helper,
-                                browsing_data_indexed_db_helper);
-  }
-}
-
-CookiesView::CookiesView(
-    GtkWindow* parent,
-    Profile* profile,
-    BrowsingDataDatabaseHelper* browsing_data_database_helper,
-    BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
-    BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
-    BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper)
-    : profile_(profile),
-      browsing_data_database_helper_(browsing_data_database_helper),
-      browsing_data_local_storage_helper_(browsing_data_local_storage_helper),
-      browsing_data_appcache_helper_(browsing_data_appcache_helper),
-      browsing_data_indexed_db_helper_(browsing_data_indexed_db_helper),
-      filter_update_factory_(this),
-      destroy_dialog_in_destructor_(false) {
-  Init(parent);
-
-  gtk_util::ShowDialogWithLocalizedSize(dialog_,
-      IDS_COOKIES_DIALOG_WIDTH_CHARS,
-      -1,
-      true);
-
-  gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_display_));
-}
-
-void CookiesView::TestDestroySynchronously() {
-  g_signal_handler_disconnect(dialog_, destroy_handler_);
-  destroy_dialog_in_destructor_ = true;
-}
-
-void CookiesView::Init(GtkWindow* parent) {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(
-          IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE).c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-  // Allow browser windows to go in front of the options dialog in metacity.
-  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
-  gtk_util::SetWindowIcon(GTK_WINDOW(dialog_));
-
-  remove_button_ = gtk_util::AddButtonToDialog(
-      dialog_,
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-        l10n_util::GetStringUTF8(IDS_COOKIES_REMOVE_LABEL)).c_str(),
-      GTK_STOCK_REMOVE,
-      RESPONSE_REMOVE);
-  gtk_button_set_use_underline(GTK_BUTTON(remove_button_), TRUE);
-  gtk_button_box_set_child_secondary(
-      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area),
-      remove_button_,
-      TRUE);
-
-  remove_all_button_ = gtk_util::AddButtonToDialog(
-      dialog_,
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(IDS_COOKIES_REMOVE_ALL_LABEL)).c_str(),
-      GTK_STOCK_CLEAR,
-      RESPONSE_REMOVE_ALL);
-  gtk_button_set_use_underline(GTK_BUTTON(remove_all_button_), TRUE);
-  gtk_button_box_set_child_secondary(
-      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area),
-      remove_all_button_,
-      TRUE);
-
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_CLOSE);
-  gtk_window_set_default_size(GTK_WINDOW(dialog_), kDialogDefaultWidth,
-                              kDialogDefaultHeight);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-  destroy_handler_ = g_signal_connect(dialog_, "destroy",
-                                      G_CALLBACK(OnWindowDestroyThunk), this);
-
-  // Filtering controls.
-  GtkWidget* filter_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  filter_entry_ = gtk_entry_new();
-  g_signal_connect(filter_entry_, "activate",
-                   G_CALLBACK(OnFilterEntryActivatedThunk), this);
-  g_signal_connect(filter_entry_, "changed",
-                   G_CALLBACK(OnFilterEntryChangedThunk), this);
-  gtk_box_pack_start(GTK_BOX(filter_hbox), filter_entry_,
-                     TRUE, TRUE, 0);
-  filter_clear_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(IDS_COOKIES_CLEAR_SEARCH_LABEL)).c_str());
-  g_signal_connect(filter_clear_button_, "clicked",
-                   G_CALLBACK(OnFilterClearButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(filter_hbox), filter_clear_button_,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* filter_controls = gtk_util::CreateLabeledControlsGroup(NULL,
-      l10n_util::GetStringUTF8(IDS_COOKIES_SEARCH_LABEL).c_str(), filter_hbox,
-      NULL);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), filter_controls,
-                     FALSE, FALSE, 0);
-
-  // Cookie list.
-  GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), cookie_list_vbox,
-                     TRUE, TRUE, 0);
-
-  description_label_ = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_COOKIES_INFO_LABEL).c_str());
-  gtk_misc_set_alignment(GTK_MISC(description_label_), 0, 0.5);
-  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), description_label_,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
-
-  cookies_tree_model_.reset(new CookiesTreeModel(
-      profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(),
-      browsing_data_database_helper_,
-      browsing_data_local_storage_helper_,
-      NULL,
-      browsing_data_appcache_helper_,
-      browsing_data_indexed_db_helper_));
-  cookies_tree_adapter_.reset(
-      new gtk_tree::TreeAdapter(this, cookies_tree_model_.get()));
-  tree_ = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(cookies_tree_adapter_->tree_store()));
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), FALSE);
-  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(tree_), TRUE);
-  gtk_container_add(GTK_CONTAINER(scroll_window), tree_);
-
-  GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
-  GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
-  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
-                                     gtk_tree::TreeAdapter::COL_ICON);
-  GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
-  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
-                                     gtk_tree::TreeAdapter::COL_TITLE);
-  gtk_tree_view_column_set_title(
-      title_column, l10n_util::GetStringUTF8(
-          IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
-  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), title_column);
-  g_signal_connect(tree_, "key-press-event",
-                   G_CALLBACK(OnTreeViewKeyPressThunk), this);
-  g_signal_connect(tree_, "row-expanded",
-                   G_CALLBACK(OnTreeViewRowExpandedThunk), this);
-
-  selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_));
-  gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE);
-  g_signal_connect(selection_, "changed",
-                   G_CALLBACK(OnTreeViewSelectionChangeThunk), this);
-
-  cookie_display_ = gtk_chrome_cookie_view_new(FALSE);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                     cookie_display_, FALSE, FALSE, 0);
-
-  // Populate the view.
-  cookies_tree_adapter_->Init();
-  SetInitialTreeState();
-  EnableControls();
-}
-
-void CookiesView::SetInitialTreeState() {
-  if (cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot()))
-    gtk_tree::SelectAndFocusRowNum(0, GTK_TREE_VIEW(tree_));
-}
-
-void CookiesView::EnableControls() {
-  GtkTreeIter iter;
-  bool selected = gtk_tree_selection_get_selected(selection_, NULL, &iter);
-  gtk_widget_set_sensitive(remove_button_, selected);
-  gtk_widget_set_sensitive(
-      remove_all_button_,
-      cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot()));
-
-  const gchar* filter_text = gtk_entry_get_text(GTK_ENTRY(filter_entry_));
-  gtk_widget_set_sensitive(filter_clear_button_, filter_text && *filter_text);
-
-  if (selected) {
-    CookieTreeNode::DetailedInfo detailed_info =
-        static_cast<CookieTreeNode*>(
-            cookies_tree_adapter_->GetNode(&iter))->GetDetailedInfo();
-    if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
-      gtk_chrome_cookie_view_display_cookie(
-          GTK_CHROME_COOKIE_VIEW(cookie_display_),
-          detailed_info.cookie->Domain(),
-          *detailed_info.cookie);
-    } else if (detailed_info.node_type ==
-               CookieTreeNode::DetailedInfo::TYPE_DATABASE) {
-      gtk_chrome_cookie_view_display_database(
-          GTK_CHROME_COOKIE_VIEW(cookie_display_),
-          *detailed_info.database_info);
-    } else if (detailed_info.node_type ==
-               CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE) {
-      gtk_chrome_cookie_view_display_local_storage(
-          GTK_CHROME_COOKIE_VIEW(cookie_display_),
-          *detailed_info.local_storage_info);
-    } else if (detailed_info.node_type ==
-               CookieTreeNode::DetailedInfo::TYPE_APPCACHE) {
-      gtk_chrome_cookie_view_display_app_cache(
-          GTK_CHROME_COOKIE_VIEW(cookie_display_),
-          *detailed_info.appcache_info);
-    } else if (detailed_info.node_type ==
-               CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB) {
-      gtk_chrome_cookie_view_display_indexed_db(
-          GTK_CHROME_COOKIE_VIEW(cookie_display_),
-          *detailed_info.indexed_db_info);
-    } else {
-      gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_display_));
-    }
-  } else {
-    gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_display_));
-  }
-}
-
-void CookiesView::RemoveSelectedItems() {
-  GtkTreeIter iter;
-  bool selected = gtk_tree_selection_get_selected(selection_, NULL, &iter);
-  if (selected) {
-    GtkTreePath* path = gtk_tree_model_get_path(
-        GTK_TREE_MODEL(cookies_tree_adapter_->tree_store()),
-        &iter);
-    CookieTreeNode* node = static_cast<CookieTreeNode*>(
-        cookies_tree_adapter_->GetNode(&iter));
-    cookies_tree_model_->DeleteCookieNode(node);
-    // After removing a node, try to select the "next" node.
-    // We call gtk_tree_model_get_iter to check if there is still a node at the
-    // pointed to by path.  If not, we try to select the previous node in that
-    // subtree.  If that subtree is empty, we then try to select the parent.
-    if (gtk_tree_model_get_iter(
-        GTK_TREE_MODEL(cookies_tree_adapter_->tree_store()),
-        &iter,
-        path)) {
-      gtk_tree_selection_select_iter(selection_, &iter);
-    } else if (gtk_tree_path_prev(path)) {
-      gtk_tree_selection_select_path(selection_, path);
-    } else if (gtk_tree_path_up(path)) {
-      gtk_tree_selection_select_path(selection_, path);
-    }
-    gtk_tree_path_free(path);
-  }
-}
-
-void CookiesView::OnAnyModelUpdateStart() {
-  g_signal_handlers_block_by_func(
-      selection_, reinterpret_cast<gpointer>(OnTreeViewSelectionChangeThunk),
-      this);
-}
-
-void CookiesView::OnAnyModelUpdate() {
-  g_signal_handlers_unblock_by_func(
-      selection_, reinterpret_cast<gpointer>(OnTreeViewSelectionChangeThunk),
-      this);
-  EnableControls();
-}
-
-void CookiesView::OnResponse(GtkWidget* dialog, int response_id) {
-  if (response_id == RESPONSE_REMOVE) {
-    RemoveSelectedItems();
-  } else if (response_id == RESPONSE_REMOVE_ALL) {
-    cookies_tree_model_->DeleteAllStoredObjects();
-  } else {
-    gtk_widget_destroy(dialog);
-  }
-}
-
-void CookiesView::OnWindowDestroy(GtkWidget* widget) {
-  instance_ = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void CookiesView::OnTreeViewSelectionChange(GtkWidget* selection) {
-  EnableControls();
-}
-
-gboolean CookiesView::OnTreeViewKeyPress(GtkWidget* tree_view,
-                                         GdkEventKey* key) {
-  if (key->keyval == GDK_Delete) {
-    RemoveSelectedItems();
-    return TRUE;
-  }
-  return FALSE;
-}
-
-void CookiesView::OnTreeViewRowExpanded(GtkWidget* tree_view,
-                                        GtkTreeIter* iter,
-                                        GtkTreePath* path) {
-  // When a row in the tree is expanded, expand all the children too.
-  g_signal_handlers_block_by_func(
-      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
-  gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
-  g_signal_handlers_unblock_by_func(
-      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
-}
-
-void CookiesView::UpdateFilterResults() {
-  const gchar* text = gtk_entry_get_text(GTK_ENTRY(filter_entry_));
-  if (text) {
-    cookies_tree_model_->UpdateSearchResults(UTF8ToWide(text));
-    SetInitialTreeState();
-  }
-}
-
-void CookiesView::OnFilterEntryActivated(GtkWidget* entry) {
-  filter_update_factory_.RevokeAll();
-  UpdateFilterResults();
-}
-
-void CookiesView::OnFilterEntryChanged(GtkWidget* editable) {
-  filter_update_factory_.RevokeAll();
-  MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      filter_update_factory_.NewRunnableMethod(
-          &CookiesView::UpdateFilterResults), kSearchFilterDelayMs);
-  EnableControls();
-}
-
-void CookiesView::OnFilterClearButtonClicked(GtkWidget* button) {
-  gtk_entry_set_text(GTK_ENTRY(filter_entry_), "");
-  filter_update_factory_.RevokeAll();
-  UpdateFilterResults();
-}
diff --git a/chrome/browser/gtk/options/cookies_view.h b/chrome/browser/gtk/options/cookies_view.h
deleted file mode 100644
index 27c0e0f..0000000
--- a/chrome/browser/gtk/options/cookies_view.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This is the Gtk implementation of the Cookie Manager dialog.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_COOKIES_VIEW_H_
-#define CHROME_BROWSER_GTK_OPTIONS_COOKIES_VIEW_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "chrome/browser/browsing_data_appcache_helper.h"
-#include "chrome/browser/browsing_data_database_helper.h"
-#include "chrome/browser/browsing_data_indexed_db_helper.h"
-#include "chrome/browser/browsing_data_local_storage_helper.h"
-#include "chrome/browser/gtk/gtk_chrome_cookie_view.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "net/base/cookie_monster.h"
-
-class CookieDisplayGtk;
-class CookiesTreeModel;
-class CookiesViewTest;
-class Profile;
-
-// CookiesView is thread-hostile, and should only be called on the UI thread.
-// Usage:
-//   CookiesView::Show(profile);
-// Once the CookiesView is shown, it is responsible for deleting itself when the
-// user closes the dialog.
-
-class CookiesView : public gtk_tree::TreeAdapter::Delegate {
- public:
-  virtual ~CookiesView();
-
-  // Create (if necessary) and show the cookie manager window.
-  static void Show(
-      GtkWindow* parent,
-      Profile* profile,
-      BrowsingDataDatabaseHelper* browsing_data_database_helper,
-      BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
-      BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
-      BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper);
-
-  // gtk_tree::TreeAdapter::Delegate implementation.
-  virtual void OnAnyModelUpdateStart();
-  virtual void OnAnyModelUpdate();
-
- private:
-  CookiesView(
-      GtkWindow* parent,
-      Profile* profile,
-      BrowsingDataDatabaseHelper* browsing_data_database_helper,
-      BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
-      BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
-      BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper);
-
-  // A method only used in unit tests that sets a bit inside this class that
-  // lets it be stack allocated.
-  void TestDestroySynchronously();
-
-  // Initialize the dialog contents and layout.
-  void Init(GtkWindow* parent);
-
-  // Set the initial selection and tree expanded state.
-  void SetInitialTreeState();
-
-  // Set sensitivity of buttons based on selection and filter state.
-  void EnableControls();
-
-  // Remove any cookies that are currently selected.
-  void RemoveSelectedItems();
-
-  CHROMEGTK_CALLBACK_1(CookiesView, void, OnResponse, int);
-  CHROMEGTK_CALLBACK_0(CookiesView, void, OnWindowDestroy);
-  // Callback for the table.
-  CHROMEGTK_CALLBACK_0(CookiesView, void, OnTreeViewSelectionChange);
-  CHROMEGTK_CALLBACK_1(CookiesView, gboolean, OnTreeViewKeyPress,
-                       GdkEventKey*);
-  CHROMEGTK_CALLBACK_2(CookiesView, void, OnTreeViewRowExpanded,
-                       GtkTreeIter*, GtkTreePath*);
-  // Callbacks for user actions filtering the list.
-  CHROMEGTK_CALLBACK_0(CookiesView, void, OnFilterEntryActivated);
-  CHROMEGTK_CALLBACK_0(CookiesView, void, OnFilterEntryChanged);
-  CHROMEGTK_CALLBACK_0(CookiesView, void, OnFilterClearButtonClicked);
-
-  // Filter the list against the text in |filter_entry_|.
-  void UpdateFilterResults();
-
-
-  // The parent widget.
-  GtkWidget* dialog_;
-
-  // Widgets of the dialog.
-  GtkWidget* description_label_;
-  GtkWidget* filter_entry_;
-  GtkWidget* filter_clear_button_;
-  GtkWidget* remove_button_;
-  GtkWidget* remove_all_button_;
-
-  // The table listing the cookies.
-  GtkWidget* tree_;
-  GtkTreeSelection* selection_;
-
-  GtkWidget* cookie_display_;
-
-  // The profile and related helpers.
-  Profile* profile_;
-  scoped_refptr<BrowsingDataDatabaseHelper> browsing_data_database_helper_;
-  scoped_refptr<BrowsingDataLocalStorageHelper>
-      browsing_data_local_storage_helper_;
-  scoped_refptr<BrowsingDataAppCacheHelper> browsing_data_appcache_helper_;
-  scoped_refptr<BrowsingDataIndexedDBHelper> browsing_data_indexed_db_helper_;
-
-  // A factory to construct Runnable Methods so that we can be called back to
-  // re-evaluate the model after the search query string changes.
-  ScopedRunnableMethodFactory<CookiesView> filter_update_factory_;
-
-  // The Cookies Table model.
-  scoped_ptr<CookiesTreeModel> cookies_tree_model_;
-  scoped_ptr<gtk_tree::TreeAdapter> cookies_tree_adapter_;
-
-  // A reference to the "destroy" signal handler for this object. We disconnect
-  // from this signal if we need to be destroyed synchronously.
-  gulong destroy_handler_;
-
-  // Whether we own |dialog_| or the other way around.
-  bool destroy_dialog_in_destructor_;
-
-  friend class CookiesViewTest;
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Empty);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Noop);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveAll);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveAllWithDefaultSelected);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Remove);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveCookiesByType);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveByDomain);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveDefaultSelection);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Filter);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, FilterRemoveAll);
-  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, FilterRemove);
-
-  DISALLOW_COPY_AND_ASSIGN(CookiesView);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_COOKIES_VIEW_H_
diff --git a/chrome/browser/gtk/options/cookies_view_unittest.cc b/chrome/browser/gtk/options/cookies_view_unittest.cc
deleted file mode 100644
index 8087cf8..0000000
--- a/chrome/browser/gtk/options/cookies_view_unittest.cc
+++ /dev/null
@@ -1,1202 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/cookies_view.h"
-
-#include <string>
-#include <vector>
-
-#include <gtk/gtk.h>
-
-#include "base/string_util.h"
-#include "chrome/browser/mock_browsing_data_appcache_helper.h"
-#include "chrome/browser/mock_browsing_data_database_helper.h"
-#include "chrome/browser/mock_browsing_data_indexed_db_helper.h"
-#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
-#include "chrome/browser/gtk/gtk_chrome_cookie_view.h"
-#include "chrome/common/net/url_request_context_getter.h"
-#include "chrome/test/testing_profile.h"
-#include "net/url_request/url_request_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class CookiesViewTest : public testing::Test {
- public:
-  CookiesViewTest() : io_thread_(BrowserThread::IO, &message_loop_) {
-  }
-
-  virtual ~CookiesViewTest() {
-  }
-
-  virtual void SetUp() {
-    profile_.reset(new TestingProfile());
-    profile_->CreateRequestContext();
-    mock_browsing_data_database_helper_ =
-        new MockBrowsingDataDatabaseHelper(profile_.get());
-    mock_browsing_data_local_storage_helper_ =
-        new MockBrowsingDataLocalStorageHelper(profile_.get());
-    mock_browsing_data_appcache_helper_ =
-        new MockBrowsingDataAppCacheHelper(profile_.get());
-    mock_browsing_data_indexed_db_helper_ =
-        new MockBrowsingDataIndexedDBHelper(profile_.get());
-  }
-
-  void CheckDetailsSensitivity(gboolean expected_cookies,
-                               gboolean expected_database,
-                               gboolean expected_local_storage,
-                               gboolean expected_appcache,
-                               gboolean expected_indexed_db,
-                               const CookiesView& cookies_view) {
-    GtkChromeCookieView* display = GTK_CHROME_COOKIE_VIEW(
-        cookies_view.cookie_display_);
-
-    // Cookies
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_name_entry_));
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_content_entry_));
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_domain_entry_));
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_path_entry_));
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_send_for_entry_));
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_created_entry_));
-    EXPECT_EQ(expected_cookies,
-              GTK_WIDGET_SENSITIVE(display->cookie_expires_entry_));
-    // Database
-    EXPECT_EQ(expected_database,
-              GTK_WIDGET_SENSITIVE(display->database_description_entry_));
-    EXPECT_EQ(expected_database,
-              GTK_WIDGET_SENSITIVE(display->database_size_entry_));
-    EXPECT_EQ(expected_database,
-              GTK_WIDGET_SENSITIVE(display->database_last_modified_entry_));
-    // Local Storage
-    EXPECT_EQ(expected_local_storage,
-              GTK_WIDGET_SENSITIVE(display->local_storage_origin_entry_));
-    EXPECT_EQ(expected_local_storage,
-              GTK_WIDGET_SENSITIVE(display->local_storage_size_entry_));
-    EXPECT_EQ(expected_local_storage, GTK_WIDGET_SENSITIVE(
-        display->local_storage_last_modified_entry_));
-    // AppCache
-    EXPECT_EQ(expected_appcache,
-              GTK_WIDGET_SENSITIVE(display->appcache_manifest_entry_));
-    EXPECT_EQ(expected_appcache,
-              GTK_WIDGET_SENSITIVE(display->appcache_size_entry_));
-    EXPECT_EQ(expected_appcache,
-              GTK_WIDGET_SENSITIVE(display->appcache_created_entry_));
-    EXPECT_EQ(expected_appcache,
-              GTK_WIDGET_SENSITIVE(display->appcache_last_accessed_entry_));
-    // IndexedDB
-    EXPECT_EQ(expected_indexed_db,
-              GTK_WIDGET_SENSITIVE(display->indexed_db_origin_entry_));
-    EXPECT_EQ(expected_indexed_db,
-              GTK_WIDGET_SENSITIVE(display->indexed_db_size_entry_));
-    EXPECT_EQ(expected_indexed_db,
-              GTK_WIDGET_SENSITIVE(display->indexed_db_last_modified_entry_));
-  }
-
-  // Get the cookie names in the cookie list, as a comma seperated string.
-  // (Note that the CookieMonster cookie list is sorted by domain.)
-  // Ex:
-  //   monster->SetCookie(GURL("http://b"), "X=1")
-  //   monster->SetCookie(GURL("http://a"), "Y=1")
-  //   EXPECT_STREQ("Y,X", GetMonsterCookies(monster).c_str());
-  std::string GetMonsterCookies(net::CookieMonster* monster) {
-    std::vector<std::string> parts;
-    net::CookieList cookie_list = monster->GetAllCookies();
-    for (size_t i = 0; i < cookie_list.size(); ++i)
-      parts.push_back(cookie_list[i].Name());
-    return JoinString(parts, ',');
-  }
-
-  typedef std::pair<std::vector<std::string>*, GtkTreeView*>
-      DisplayedCookiesData;
-
-  static gboolean GetDisplayedCookiesHelper(GtkTreeModel *model,
-                                            GtkTreePath *path,
-                                            GtkTreeIter *iter,
-                                            gpointer user_data) {
-    DisplayedCookiesData* data =
-        reinterpret_cast<DisplayedCookiesData*>(user_data);
-    gchar* title;
-    gtk_tree_model_get(model, iter,
-                       gtk_tree::TreeAdapter::COL_TITLE, &title,
-                       -1);
-    std::string str;
-    if (gtk_tree_path_get_depth(path) > 1) {
-      // There isn't a function to check if a row is visible, instead we have to
-      // check whether the parent is expanded.
-      GtkTreePath* parent_path = gtk_tree_path_copy(path);
-      gtk_tree_path_up(parent_path);
-      str.append(
-          gtk_tree_path_get_depth(parent_path),
-          gtk_tree_view_row_expanded(data->second, parent_path) ? '+' : '_');
-      gtk_tree_path_free(parent_path);
-    }
-    str += title;
-    g_free(title);
-    data->first->push_back(str);
-    return FALSE;
-  }
-
-  // Get the cookie names displayed in the dialog in the order they are
-  // displayed, as a comma seperated string.
-  // Items are prefixed with _ or + up to their indent level.
-  // _ when hidden (parent is closed) and + when visible (parent is expanded).
-  // Ex: EXPECT_STREQ("a,+Cookies,++Y,b,_Cookies,__X",
-  //                  GetDisplayedCookies(cookies_view).c_str());
-  std::string GetDisplayedCookies(const CookiesView& cookies_view) {
-    GtkTreeStore* tree_store = cookies_view.cookies_tree_adapter_->tree_store();
-    std::vector<std::string> parts;
-    DisplayedCookiesData helper_data(&parts, GTK_TREE_VIEW(cookies_view.tree_));
-    gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store),
-                           GetDisplayedCookiesHelper, &helper_data);
-    return JoinString(parts, ',');
-  }
-
-  bool ExpandByPath(const CookiesView& cookies_view, const char* path_str) {
-    GtkTreePath* path = gtk_tree_path_new_from_string(path_str);
-    if (!path)
-      return false;
-    bool rv = gtk_tree_view_expand_row(GTK_TREE_VIEW(cookies_view.tree_), path,
-                                       FALSE);
-    gtk_tree_path_free(path);
-    return rv;
-  }
-
-  bool SelectByPath(const CookiesView& cookies_view, const char* path_str) {
-    GtkTreePath* path = gtk_tree_path_new_from_string(path_str);
-    if (!path)
-      return false;
-    gtk_tree_selection_select_path(cookies_view.selection_, path);
-    bool rv = gtk_tree_selection_path_is_selected(cookies_view.selection_,
-                                                  path);
-    gtk_tree_path_free(path);
-    return rv;
-  }
-
-  std::string GetSelectedPath(const CookiesView& cookies_view) {
-    std::string result;
-    GtkTreeIter iter;
-    bool selected = gtk_tree_selection_get_selected(cookies_view.selection_,
-                                                    NULL, &iter);
-    if (selected) {
-      gchar* path_str = gtk_tree_model_get_string_from_iter(
-          GTK_TREE_MODEL(cookies_view.cookies_tree_adapter_->tree_store()),
-          &iter);
-      if (path_str) {
-        result = path_str;
-        g_free(path_str);
-      }
-    }
-    return result;
-  }
-
- protected:
-  MessageLoop message_loop_;
-  BrowserThread io_thread_;
-
-  scoped_ptr<TestingProfile> profile_;
-  scoped_refptr<MockBrowsingDataDatabaseHelper>
-      mock_browsing_data_database_helper_;
-  scoped_refptr<MockBrowsingDataLocalStorageHelper>
-      mock_browsing_data_local_storage_helper_;
-  scoped_refptr<MockBrowsingDataAppCacheHelper>
-      mock_browsing_data_appcache_helper_;
-  scoped_refptr<MockBrowsingDataIndexedDBHelper>
-      mock_browsing_data_indexed_db_helper_;
-};
-
-TEST_F(CookiesViewTest, Empty) {
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
-}
-
-TEST_F(CookiesViewTest, Noop) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://foo0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://foo1"), "A=1");
-  monster->SetCookie(GURL("http://foo1"), "E=1");
-  monster->SetCookie(GURL("http://foo2"), "G=1");
-  monster->SetCookie(GURL("http://foo2"), "X=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo1,_Cookies,__A,__B,__E,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-}
-
-TEST_F(CookiesViewTest, RemoveAll) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo"), "A=1");
-  monster->SetCookie(GURL("http://foo2"), "B=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  // Reset the selection of the first row.
-  gtk_tree_selection_unselect_all(cookies_view.selection_);
-
-  {
-    SCOPED_TRACE("Before removing");
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B,"
-                 "gdbhost1,_Web Databases,__db1,"
-                 "gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-  }
-
-  mock_browsing_data_database_helper_->Reset();
-  mock_browsing_data_local_storage_helper_->Reset();
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_));
-  {
-    SCOPED_TRACE("After removing");
-    EXPECT_EQ(0u, monster->GetAllCookies().size());
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_TRUE(mock_browsing_data_database_helper_->AllDeleted());
-    EXPECT_TRUE(mock_browsing_data_local_storage_helper_->AllDeleted());
-  }
-}
-
-TEST_F(CookiesViewTest, RemoveAllWithDefaultSelected) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo"), "A=1");
-  monster->SetCookie(GURL("http://foo2"), "B=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
-  EXPECT_EQ(1, gtk_tree_selection_count_selected_rows(cookies_view.selection_));
-  {
-    SCOPED_TRACE("Before removing");
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B,"
-                 "gdbhost1,_Web Databases,__db1,"
-                 "gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-  }
-
-  mock_browsing_data_database_helper_->Reset();
-  mock_browsing_data_local_storage_helper_->Reset();
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_));
-  {
-    SCOPED_TRACE("After removing");
-    EXPECT_EQ(0u, monster->GetAllCookies().size());
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(0,
-              gtk_tree_selection_count_selected_rows(cookies_view.selection_));
-    EXPECT_TRUE(mock_browsing_data_database_helper_->AllDeleted());
-    EXPECT_TRUE(mock_browsing_data_local_storage_helper_->AllDeleted());
-  }
-}
-
-TEST_F(CookiesViewTest, Remove) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo1"), "A=1");
-  monster->SetCookie(GURL("http://foo2"), "B=1");
-  monster->SetCookie(GURL("http://foo2"), "C=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
-  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
-
-  {
-    SCOPED_TRACE("First selection");
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++B,++C,"
-                 "gdbhost1,_Web Databases,__db1,"
-                 "gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-  }
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("First selection removed");
-    EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
-    EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++C,"
-                 "gdbhost1,_Web Databases,__db1,"
-                 "gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str());
-    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("Second selection");
-    EXPECT_STREQ("A", GetMonsterCookies(monster).c_str());
-    EXPECT_STREQ("foo1,_Cookies,__A,"
-                 "gdbhost1,_Web Databases,__db1,"
-                 "gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    EXPECT_STREQ("", GetSelectedPath(cookies_view).c_str());
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
-  EXPECT_STREQ("foo1,+Cookies,++A,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("Second selection removed");
-    EXPECT_EQ(0u, monster->GetAllCookies().size());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-                 "gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-  }
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
-  EXPECT_STREQ("gdbhost1,+Web Databases,++db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("Third selection removed");
-    EXPECT_EQ(0u, monster->GetAllCookies().size());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
-                "http_gdbhost1_1");
-    EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
-                "db1");
-  }
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
-  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-               "host1,+Local Storage,++http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("Fourth selection removed");
-    EXPECT_EQ(0u, monster->GetAllCookies().size());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
-                FilePath(FILE_PATH_LITERAL("file1")));
-  }
-}
-
-TEST_F(CookiesViewTest, RemoveCookiesByType) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://foo0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://foo1"), "A=1");
-  monster->SetCookie(GURL("http://foo1"), "E=1");
-  monster->SetCookie(GURL("http://foo2"), "G=1");
-  monster->SetCookie(GURL("http://foo2"), "X=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo1,_Cookies,__A,__B,__E,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo1,+Cookies,++A,++B,++E,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "1:0"));
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("C,D,G,X", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
-  EXPECT_STREQ("foo0,+Cookies,++C,++D,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
-  EXPECT_STREQ("foo2,+Cookies,++G,++X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
-  EXPECT_STREQ("gdbhost1,+Web Databases,++db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
-              "http_gdbhost1_1");
-  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
-              "db1");
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
-  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-               "host1,+Local Storage,++http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "1:0"));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
-              FilePath(FILE_PATH_LITERAL("file1")));
-}
-
-TEST_F(CookiesViewTest, RemoveByDomain) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://foo0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://foo1"), "A=1");
-  monster->SetCookie(GURL("http://foo1"), "E=1");
-  monster->SetCookie(GURL("http://foo2"), "G=1");
-  monster->SetCookie(GURL("http://foo2"), "X=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo1,_Cookies,__A,__B,__E,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  ASSERT_TRUE(SelectByPath(cookies_view, "1"));
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("C,D,G,X", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_STREQ("1", GetSelectedPath(cookies_view).c_str());
-
-  ASSERT_TRUE(SelectByPath(cookies_view, "0"));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
-              "http_gdbhost1_1");
-  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
-              "db1");
-  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
-              "http_gdbhost2_2");
-  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
-              "db2");
-  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
-        FilePath(FILE_PATH_LITERAL("file1")));
-  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
-        FilePath(FILE_PATH_LITERAL("file2")));
-
-  EXPECT_EQ(0, gtk_tree_selection_count_selected_rows(cookies_view.selection_));
-}
-
-TEST_F(CookiesViewTest, RemoveDefaultSelection) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://foo0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://foo1"), "A=1");
-  monster->SetCookie(GURL("http://foo1"), "E=1");
-  monster->SetCookie(GURL("http://foo2"), "G=1");
-  monster->SetCookie(GURL("http://foo2"), "X=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
-               "foo1,_Cookies,__A,__B,__E,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("B,A,E,G,X", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("foo1,_Cookies,__A,__B,__E,"
-               "foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("foo2,_Cookies,__G,__X,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
-  EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-}
-
-TEST_F(CookiesViewTest, Filter) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://bar0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://bar1"), "A=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-
-  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  // Entering text doesn't immediately filter the results.
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  // Results are filtered immediately if you activate (hit enter in the entry).
-  gtk_widget_activate(cookies_view.filter_entry_);
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "hos");
-  gtk_widget_activate(cookies_view.filter_entry_);
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-}
-
-TEST_F(CookiesViewTest, FilterRemoveAll) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://bar0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://bar1"), "A=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-
-  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  // Entering text doesn't immediately filter the results.
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  // Results are filtered immediately if you activate (hit enter in the entry).
-  gtk_widget_activate(cookies_view.filter_entry_);
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_));
-
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-  EXPECT_STREQ("",
-               GetDisplayedCookies(cookies_view).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
-  EXPECT_STREQ("foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-}
-
-TEST_F(CookiesViewTest, FilterRemove) {
-  net::CookieMonster* monster = profile_->GetCookieMonster();
-  monster->SetCookie(GURL("http://foo0"), "C=1");
-  monster->SetCookie(GURL("http://bar0"), "D=1");
-  monster->SetCookie(GURL("http://foo1"), "B=1");
-  monster->SetCookie(GURL("http://bar1"), "A=1");
-  monster->SetCookie(GURL("http://bar1"), "E=1");
-  CookiesView cookies_view(NULL,
-                           profile_.get(),
-                           mock_browsing_data_database_helper_,
-                           mock_browsing_data_local_storage_helper_,
-                           mock_browsing_data_appcache_helper_,
-                           mock_browsing_data_indexed_db_helper_);
-  cookies_view.TestDestroySynchronously();
-  mock_browsing_data_database_helper_->AddDatabaseSamples();
-  mock_browsing_data_database_helper_->Notify();
-  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
-  mock_browsing_data_local_storage_helper_->Notify();
-
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,__E,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  // All default paths; order will be creation time.
-  EXPECT_STREQ("C,D,B,A,E", GetMonsterCookies(monster).c_str());
-
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-
-  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  // Entering text doesn't immediately filter the results.
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,__E,"
-               "foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  // Results are filtered immediately if you activate (hit enter in the entry).
-  gtk_widget_activate(cookies_view.filter_entry_);
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,_Cookies,__A,__E",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
-  EXPECT_STREQ("bar0,_Cookies,__D,"
-               "bar1,+Cookies,++A,++E",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
-
-  {
-    SCOPED_TRACE("First selection");
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("First selection removed");
-    EXPECT_STREQ("C,D,B,E", GetMonsterCookies(monster).c_str());
-    EXPECT_STREQ("bar0,_Cookies,__D,"
-                 "bar1,+Cookies,++E",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str());
-    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("Second selection");
-    EXPECT_STREQ("C,D,B", GetMonsterCookies(monster).c_str());
-    EXPECT_STREQ("bar0,_Cookies,__D",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
-  ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("Second selection removed");
-    EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-    EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
-  }
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
-  EXPECT_STREQ("foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "hos");
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
-  // Entering text doesn't immediately filter the results.
-  EXPECT_STREQ("foo0,_Cookies,__C,"
-               "foo1,_Cookies,__B,"
-               "gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  // Results are filtered immediately if you activate (hit enter in the entry).
-  gtk_widget_activate(cookies_view.filter_entry_);
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,_Web Databases,__db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "gdbhost2,+Web Databases,++db2,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,_Local Storage,__http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
-
-  {
-    SCOPED_TRACE("First selection");
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, TRUE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("First selection removed");
-    EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
-    EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-                 "host1,_Local Storage,__http://host1:1/,"
-                 "host2,_Local Storage,__http://host2:2/",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-
-  ASSERT_TRUE(ExpandByPath(cookies_view, "2"));
-  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-               "host1,_Local Storage,__http://host1:1/,"
-               "host2,+Local Storage,++http://host2:2/",
-               GetDisplayedCookies(cookies_view).c_str());
-  ASSERT_TRUE(SelectByPath(cookies_view, "2:0:0"));
-
-  {
-    SCOPED_TRACE("First selection");
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, TRUE, FALSE, FALSE, cookies_view);
-  }
-
-  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
-
-  {
-    SCOPED_TRACE("First selection removed");
-    EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
-    EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
-                 "host1,_Local Storage,__http://host1:1/",
-                 GetDisplayedCookies(cookies_view).c_str());
-    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
-    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
-    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
-  }
-}
diff --git a/chrome/browser/gtk/options/fonts_languages_window_gtk.cc b/chrome/browser/gtk/options/fonts_languages_window_gtk.cc
deleted file mode 100644
index e37cb1c..0000000
--- a/chrome/browser/gtk/options/fonts_languages_window_gtk.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/fonts_languages_window.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/gtk/options/fonts_page_gtk.h"
-#include "chrome/browser/gtk/options/languages_page_gtk.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// FontsLanguagesWindowGtk
-//
-// The contents of the Options dialog window.
-
-class FontsLanguagesWindowGtk {
- public:
-  explicit FontsLanguagesWindowGtk(Profile* profile);
-  ~FontsLanguagesWindowGtk();
-
-  // Shows the tab corresponding to the specified |page|.
-  void ShowTabPage(gfx::NativeWindow window, FontsLanguagesPage page);
-
- private:
-  static void OnWindowDestroy(GtkWidget* widget,
-                              FontsLanguagesWindowGtk* window);
-
-  // The fonts and languages dialog.
-  GtkWidget *dialog_;
-
-  // The container of the option pages.
-  GtkWidget *notebook_;
-
-  // The Profile associated with these options.
-  Profile* profile_;
-
-  // The fonts page.
-  FontsPageGtk fonts_page_;
-
-  // The languages page.
-  LanguagesPageGtk languages_page_;
-
-  DISALLOW_COPY_AND_ASSIGN(FontsLanguagesWindowGtk);
-};
-
-static FontsLanguagesWindowGtk* instance_ = NULL;
-
-///////////////////////////////////////////////////////////////////////////////
-// FontsLanguagesWindowGtk, public:
-
-FontsLanguagesWindowGtk::FontsLanguagesWindowGtk(Profile* profile)
-      // Always show preferences for the original profile. Most state when off
-      // the record comes from the original profile, but we explicitly use
-      // the original profile to avoid potential problems.
-    : profile_(profile->GetOriginalProfile()),
-      fonts_page_(profile_),
-      languages_page_(profile_) {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_FONT_LANGUAGE_SETTING_WINDOWS_TITLE).c_str(),
-      // Prefs window is shared between all browser windows.
-      NULL,
-      // Non-modal.
-      GTK_DIALOG_NO_SEPARATOR,
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-
-  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  notebook_ = gtk_notebook_new();
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
-
-  // Fonts and Encoding tab.
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      fonts_page_.get_page_widget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(
-              IDS_FONT_LANGUAGE_SETTING_FONT_TAB_TITLE).c_str()));
-
-  // Langauges tab.
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      languages_page_.get_page_widget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(
-              IDS_FONT_LANGUAGE_SETTING_LANGUAGES_TAB_TITLE).c_str()));
-
-  // Show the notebook.
-  gtk_util::ShowDialogWithLocalizedSize(dialog_, -1, -1, false);
-
-  // We only have one button and don't do any special handling, so just hook it
-  // directly to gtk_widget_destroy.
-  g_signal_connect_swapped(dialog_, "response", G_CALLBACK(gtk_widget_destroy),
-                           dialog_);
-
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
-}
-
-FontsLanguagesWindowGtk::~FontsLanguagesWindowGtk() {
-}
-
-void FontsLanguagesWindowGtk::ShowTabPage(gfx::NativeWindow window,
-                                          FontsLanguagesPage page) {
-  // Center our dialog over whoever displayed us.
-  gtk_util::CenterOverWindow(GTK_WINDOW(dialog_), window);
-
-  // Bring options window to front if it already existed and isn't already
-  // in front.
-  gtk_util::PresentWindow(dialog_, 0);
-
-  // If the page is out of bounds, reset to the first tab.
-  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
-    page = FONTS_ENCODING_PAGE;
-
-  // Switch the tab to the selected |page|.
-  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// FontsLanguagesWindowGtk, private:
-
-// static
-void FontsLanguagesWindowGtk::OnWindowDestroy(GtkWidget* widget,
-    FontsLanguagesWindowGtk* window) {
-  instance_ = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
-}
-
-void ShowFontsLanguagesWindow(gfx::NativeWindow window,
-                              FontsLanguagesPage page,
-                              Profile* profile) {
-  DCHECK(profile);
-  // If there's already an existing fonts and language window, activate it and
-  // switch to the specified page.
-  if (!instance_)
-    instance_ = new FontsLanguagesWindowGtk(profile);
-
-  instance_->ShowTabPage(window, page);
-}
diff --git a/chrome/browser/gtk/options/fonts_page_gtk.cc b/chrome/browser/gtk/options/fonts_page_gtk.cc
deleted file mode 100644
index a3c2d4e..0000000
--- a/chrome/browser/gtk/options/fonts_page_gtk.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/fonts_page_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/stringprintf.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/default_encoding_combo_model.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/options_layout_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/font.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Make a Gtk font name string from a font family name and pixel size.
-std::string MakeFontName(std::string family_name, int pixel_size) {
-  // The given font might not be available (the default fonts we use are not
-  // installed by default on some distros).  So figure out which font we are
-  // actually falling back to and display that.  (See crbug.com/31381.)
-  std::wstring actual_family_name = gfx::Font(
-      UTF8ToWide(family_name), pixel_size).GetFontName();
-  std::string fontname;
-  // TODO(mattm): We can pass in the size in pixels (px), and the font button
-  // actually honors it, but when you open the selector it interprets it as
-  // points.  See crbug.com/17857
-  base::SStringPrintf(&fontname, "%s, %dpx",
-                      WideToUTF8(actual_family_name).c_str(), pixel_size);
-  return fontname;
-}
-
-}  // namespace
-
-FontsPageGtk::FontsPageGtk(Profile* profile) : OptionsPageBase(profile) {
-  Init();
-}
-
-FontsPageGtk::~FontsPageGtk() {
-}
-
-void FontsPageGtk::Init() {
-  scoped_ptr<OptionsLayoutBuilderGtk>
-    options_builder(OptionsLayoutBuilderGtk::Create());
-  serif_font_button_ = gtk_font_button_new();
-  gtk_font_button_set_use_font(GTK_FONT_BUTTON(serif_font_button_), TRUE);
-  gtk_font_button_set_use_size(GTK_FONT_BUTTON(serif_font_button_), TRUE);
-  g_signal_connect(serif_font_button_, "font-set",
-                   G_CALLBACK(OnSerifFontSetThunk), this);
-
-  sans_font_button_ = gtk_font_button_new();
-  gtk_font_button_set_use_font(GTK_FONT_BUTTON(sans_font_button_), TRUE);
-  gtk_font_button_set_use_size(GTK_FONT_BUTTON(sans_font_button_), TRUE);
-  g_signal_connect(sans_font_button_, "font-set",
-                   G_CALLBACK(OnSansFontSetThunk), this);
-
-  fixed_font_button_ = gtk_font_button_new();
-  gtk_font_button_set_use_font(GTK_FONT_BUTTON(fixed_font_button_), TRUE);
-  gtk_font_button_set_use_size(GTK_FONT_BUTTON(fixed_font_button_), TRUE);
-  g_signal_connect(fixed_font_button_, "font-set",
-                   G_CALLBACK(OnFixedFontSetThunk), this);
-
-  GtkWidget* font_controls = gtk_util::CreateLabeledControlsGroup(NULL,
-      l10n_util::GetStringUTF8(
-          IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SERIF_LABEL).c_str(),
-      serif_font_button_,
-      l10n_util::GetStringUTF8(
-        IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SANS_SERIF_LABEL).c_str(),
-      sans_font_button_,
-      l10n_util::GetStringUTF8(
-        IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_FIXED_WIDTH_LABEL).c_str(),
-      fixed_font_button_,
-      NULL);
-
-  options_builder->AddOptionGroup(l10n_util::GetStringUTF8(
-        IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_FONT_TITLE),
-      font_controls, false);
-
-  InitDefaultEncodingComboBox();
-  std::string encoding_group_description = l10n_util::GetStringUTF8(
-      IDS_FONT_LANGUAGE_SETTING_FONT_DEFAULT_ENCODING_SELECTOR_LABEL);
-  GtkWidget* encoding_controls = gtk_util::CreateLabeledControlsGroup(NULL,
-      encoding_group_description.c_str(),
-      default_encoding_combobox_,
-      NULL);
-  options_builder->AddOptionGroup(l10n_util::GetStringUTF8(
-        IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_ENCODING_TITLE),
-      encoding_controls, false);
-
-  page_ = options_builder->get_page_widget();
-
-  serif_name_.Init(prefs::kWebKitSerifFontFamily, profile()->GetPrefs(), this);
-  sans_serif_name_.Init(prefs::kWebKitSansSerifFontFamily,
-                        profile()->GetPrefs(), this);
-  variable_width_size_.Init(prefs::kWebKitDefaultFontSize,
-                            profile()->GetPrefs(), this);
-
-  fixed_width_name_.Init(prefs::kWebKitFixedFontFamily, profile()->GetPrefs(),
-                         this);
-  fixed_width_size_.Init(prefs::kWebKitDefaultFixedFontSize,
-                         profile()->GetPrefs(), this);
-
-  default_encoding_.Init(prefs::kDefaultCharset, profile()->GetPrefs(), this);
-
-  NotifyPrefChanged(NULL);
-}
-
-void FontsPageGtk::InitDefaultEncodingComboBox() {
-  default_encoding_combobox_ = gtk_combo_box_new_text();
-  g_signal_connect(default_encoding_combobox_, "changed",
-                   G_CALLBACK(OnDefaultEncodingChangedThunk), this);
-  default_encoding_combobox_model_.reset(new DefaultEncodingComboboxModel);
-  for (int i = 0; i < default_encoding_combobox_model_->GetItemCount(); ++i) {
-    gtk_combo_box_append_text(
-        GTK_COMBO_BOX(default_encoding_combobox_),
-        UTF16ToUTF8(default_encoding_combobox_model_->GetItemAt(i)).c_str());
-  }
-}
-
-void FontsPageGtk::NotifyPrefChanged(const std::string* pref_name) {
-  if (!pref_name || *pref_name == prefs::kWebKitSerifFontFamily ||
-      *pref_name == prefs::kWebKitDefaultFontSize) {
-    gtk_font_button_set_font_name(GTK_FONT_BUTTON(serif_font_button_),
-        MakeFontName(serif_name_.GetValue(),
-          variable_width_size_.GetValue()).c_str());
-  }
-  if (!pref_name || *pref_name == prefs::kWebKitSansSerifFontFamily ||
-      *pref_name == prefs::kWebKitDefaultFontSize) {
-    gtk_font_button_set_font_name(GTK_FONT_BUTTON(sans_font_button_),
-        MakeFontName(sans_serif_name_.GetValue(),
-          variable_width_size_.GetValue()).c_str());
-  }
-  if (!pref_name || *pref_name == prefs::kWebKitFixedFontFamily ||
-      *pref_name == prefs::kWebKitDefaultFixedFontSize) {
-    gtk_font_button_set_font_name(GTK_FONT_BUTTON(fixed_font_button_),
-        MakeFontName(fixed_width_name_.GetValue(),
-          fixed_width_size_.GetValue()).c_str());
-  }
-  if (!pref_name || *pref_name == prefs::kDefaultCharset) {
-    gtk_combo_box_set_active(
-        GTK_COMBO_BOX(default_encoding_combobox_),
-        default_encoding_combobox_model_->GetSelectedEncodingIndex(profile()));
-  }
-}
-
-void FontsPageGtk::SetFontsFromButton(StringPrefMember* name_pref,
-                                      IntegerPrefMember* size_pref,
-                                      GtkWidget* font_button) {
-  PangoFontDescription* desc = pango_font_description_from_string(
-      gtk_font_button_get_font_name(GTK_FONT_BUTTON(font_button)));
-  int size = pango_font_description_get_size(desc);
-  name_pref->SetValue(pango_font_description_get_family(desc));
-  size_pref->SetValue(size / PANGO_SCALE);
-  pango_font_description_free(desc);
-  // Reset the button font in px, since the chooser will have set it in points.
-  // Also, both sans and serif share the same size so we need to update them
-  // both.
-  NotifyPrefChanged(NULL);
-}
-
-void FontsPageGtk::OnSerifFontSet(GtkWidget* font_button) {
-  SetFontsFromButton(&serif_name_,
-                     &variable_width_size_,
-                     font_button);
-}
-
-void FontsPageGtk::OnSansFontSet(GtkWidget* font_button) {
-  SetFontsFromButton(&sans_serif_name_,
-                     &variable_width_size_,
-                     font_button);
-}
-
-void FontsPageGtk::OnFixedFontSet(GtkWidget* font_button) {
-  SetFontsFromButton(&fixed_width_name_,
-                     &fixed_width_size_,
-                     font_button);
-}
-
-void FontsPageGtk::OnDefaultEncodingChanged(GtkWidget* combo_box) {
-  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_box));
-  default_encoding_.SetValue(default_encoding_combobox_model_->
-      GetEncodingCharsetByIndex(index));
-}
diff --git a/chrome/browser/gtk/options/fonts_page_gtk.h b/chrome/browser/gtk/options/fonts_page_gtk.h
deleted file mode 100644
index 3dbdf5a..0000000
--- a/chrome/browser/gtk/options/fonts_page_gtk.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The fonts page of the fonts & languages options dialog, which contains font
-// family and size settings, as well as the default encoding option.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_FONTS_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_FONTS_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/character_encoding.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-
-class DefaultEncodingComboboxModel;
-
-class FontsPageGtk : public OptionsPageBase {
- public:
-  explicit FontsPageGtk(Profile* profile);
-  virtual ~FontsPageGtk();
-
-  GtkWidget* get_page_widget() const { return page_; }
-
- private:
-  void Init();
-  void InitDefaultEncodingComboBox();
-
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  // Retrieve the font selection from the button and save it to the prefs.  Also
-  // ensure the button(s) are displayed in the proper size, as the
-  // GtkFontSelector returns the value in points not pixels.
-  void SetFontsFromButton(StringPrefMember* name_pref,
-                          IntegerPrefMember* size_pref,
-                          GtkWidget* font_button);
-
-  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnSerifFontSet);
-  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnSansFontSet);
-  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnFixedFontSet);
-  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnDefaultEncodingChanged);
-
-  // The font chooser widgets
-  GtkWidget* serif_font_button_;
-  GtkWidget* sans_font_button_;
-  GtkWidget* fixed_font_button_;
-
-  // The default encoding combobox widget.
-  GtkWidget* default_encoding_combobox_;
-  scoped_ptr<DefaultEncodingComboboxModel> default_encoding_combobox_model_;
-
-  // The widget containing the options for this page.
-  GtkWidget* page_;
-
-  // Font name preferences.
-  StringPrefMember serif_name_;
-  StringPrefMember sans_serif_name_;
-  StringPrefMember fixed_width_name_;
-
-  // Font size preferences, in pixels.
-  IntegerPrefMember variable_width_size_;
-  IntegerPrefMember fixed_width_size_;
-
-  // Default encoding preference.
-  StringPrefMember default_encoding_;
-
-  DISALLOW_COPY_AND_ASSIGN(FontsPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_FONTS_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/general_page_gtk.cc b/chrome/browser/gtk/options/general_page_gtk.cc
deleted file mode 100644
index 1df3769..0000000
--- a/chrome/browser/gtk/options/general_page_gtk.cc
+++ /dev/null
@@ -1,806 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/general_page_gtk.h"
-
-#include <set>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/custom_home_pages_table_model.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/keyword_editor_view.h"
-#include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h"
-#include "chrome/browser/gtk/options/options_layout_gtk.h"
-#include "chrome/browser/gtk/options/url_picker_dialog_gtk.h"
-#include "chrome/browser/instant/instant_confirm_dialog.h"
-#include "chrome/browser/instant/instant_controller.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/gtk_util.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Markup for the text showing the current state of the default browser
-const char kDefaultBrowserLabelMarkup[] = "<span color='#%s'>%s</span>";
-
-// Color of the default browser text when Chromium is the default browser
-const char kDefaultBrowserLabelColor[] = "008700";
-
-// Color of the default browser text when Chromium is not the default browser
-const char kNotDefaultBrowserLabelColor[] = "870000";
-
-// Column ids for |startup_custom_pages_store_|.
-enum {
-  COL_FAVICON,
-  COL_URL,
-  COL_TOOLTIP,
-  COL_COUNT,
-};
-
-// Column ids for |default_search_engines_model_|.
-enum {
-  SEARCH_ENGINES_COL_INDEX,
-  SEARCH_ENGINES_COL_TITLE,
-  SEARCH_ENGINES_COL_COUNT,
-};
-
-bool IsNewTabUIURLString(const GURL& url) {
-  return url == GURL(chrome::kChromeUINewTabURL);
-}
-
-}  // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// GeneralPageGtk, public:
-
-GeneralPageGtk::GeneralPageGtk(Profile* profile)
-    : OptionsPageBase(profile),
-      template_url_model_(NULL),
-      instant_checkbox_(NULL),
-      default_search_initializing_(true),
-      initializing_(true),
-      default_browser_worker_(
-          new ShellIntegration::DefaultBrowserWorker(this)),
-      managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_GENERAL) {
-  scoped_ptr<OptionsLayoutBuilderGtk>
-    options_builder(OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout());
-  page_ = options_builder->get_page_widget();
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(page_, profile));
-
-  options_builder->AddWidget(managed_prefs_banner_.banner_widget(), false);
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_GROUP_NAME),
-      InitStartupGroup(), true);
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_GROUP_NAME),
-      InitHomepageGroup(), false);
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME),
-      InitDefaultSearchGroup(), false);
-#if !defined(OS_CHROMEOS)
-  options_builder->AddOptionGroup(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME),
-      InitDefaultBrowserGroup(), false);
-#endif
-
-  registrar_.Init(profile->GetPrefs());
-  registrar_.Add(prefs::kRestoreOnStartup, this);
-  registrar_.Add(prefs::kURLsToRestoreOnStartup, this);
-
-  new_tab_page_is_home_page_.Init(prefs::kHomePageIsNewTabPage,
-      profile->GetPrefs(), this);
-  homepage_.Init(prefs::kHomePage, profile->GetPrefs(), this);
-  show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this);
-
-  instant_.Init(prefs::kInstantEnabled, profile->GetPrefs(), this);
-
-  // Load initial values
-  NotifyPrefChanged(NULL);
-}
-
-GeneralPageGtk::~GeneralPageGtk() {
-  if (template_url_model_)
-    template_url_model_->RemoveObserver(this);
-
-  default_browser_worker_->ObserverDestroyed();
-}
-
-GtkWindow* GeneralPageGtk::GetWindow() {
-  return GTK_WINDOW(gtk_widget_get_toplevel(page_));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// GeneralPageGtk, OptionsPageBase overrides:
-
-void GeneralPageGtk::NotifyPrefChanged(const std::string* pref_name) {
-  initializing_ = true;
-  PrefService* prefs = profile()->GetPrefs();
-  if (!pref_name ||
-      *pref_name == prefs::kRestoreOnStartup ||
-      *pref_name == prefs::kURLsToRestoreOnStartup) {
-    const SessionStartupPref startup_pref =
-        SessionStartupPref::GetStartupPref(prefs);
-    bool radio_buttons_enabled = !SessionStartupPref::TypeIsManaged(prefs);
-    bool restore_urls_enabled = !SessionStartupPref::URLsAreManaged(prefs);
-    switch (startup_pref.type) {
-    case SessionStartupPref::DEFAULT:
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startup_homepage_radio_),
-                                   TRUE);
-      restore_urls_enabled = false;
-      break;
-
-    case SessionStartupPref::LAST:
-      gtk_toggle_button_set_active(
-          GTK_TOGGLE_BUTTON(startup_last_session_radio_), TRUE);
-      restore_urls_enabled = false;
-      break;
-
-    case SessionStartupPref::URLS:
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startup_custom_radio_),
-                                   TRUE);
-      break;
-    }
-    gtk_widget_set_sensitive(startup_homepage_radio_, radio_buttons_enabled);
-    gtk_widget_set_sensitive(startup_last_session_radio_,
-                             radio_buttons_enabled);
-    gtk_widget_set_sensitive(startup_custom_radio_, radio_buttons_enabled);
-    EnableCustomHomepagesControls(restore_urls_enabled);
-    startup_custom_pages_table_model_->SetURLs(startup_pref.urls);
-  }
-
-  if (!pref_name ||
-      *pref_name == prefs::kHomePageIsNewTabPage ||
-      *pref_name == prefs::kHomePage) {
-    bool new_tab_page_is_home_page_managed =
-        new_tab_page_is_home_page_.IsManaged();
-    bool homepage_managed = homepage_.IsManaged();
-    bool homepage_url_is_new_tab =
-        IsNewTabUIURLString(GURL(homepage_.GetValue()));
-    bool homepage_is_new_tab = homepage_url_is_new_tab ||
-        new_tab_page_is_home_page_.GetValue();
-    // If HomepageIsNewTab is managed or
-    // Homepage is 'chrome://newtab' and managed, disable the radios.
-    bool disable_homepage_choice_buttons =
-        new_tab_page_is_home_page_managed ||
-        (homepage_managed && homepage_url_is_new_tab);
-    if (!homepage_url_is_new_tab) {
-      gtk_entry_set_text(GTK_ENTRY(homepage_use_url_entry_),
-                         homepage_.GetValue().c_str());
-    }
-    UpdateHomepageIsNewTabRadio(
-        homepage_is_new_tab, !disable_homepage_choice_buttons);
-    EnableHomepageURLField(!homepage_is_new_tab);
-  }
-
-  if (!pref_name || *pref_name == prefs::kShowHomeButton) {
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(homepage_show_home_button_checkbox_),
-        show_home_button_.GetValue());
-    gtk_widget_set_sensitive(
-        homepage_show_home_button_checkbox_,
-        !show_home_button_.IsManaged());
-  }
-
-  if ((!pref_name || *pref_name == prefs::kInstantEnabled) &&
-      instant_checkbox_) {
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(instant_checkbox_), instant_.GetValue());
-  }
-
-  initializing_ = false;
-}
-
-void GeneralPageGtk::HighlightGroup(OptionsGroup highlight_group) {
-  // TODO(mattm): implement group highlighting
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// GeneralPageGtk, private:
-
-GtkWidget* GeneralPageGtk::InitStartupGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  startup_homepage_radio_ = gtk_radio_button_new_with_label(NULL,
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB).c_str());
-  g_signal_connect(startup_homepage_radio_, "toggled",
-                   G_CALLBACK(OnStartupRadioToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), startup_homepage_radio_, FALSE, FALSE, 0);
-
-  startup_last_session_radio_ = gtk_radio_button_new_with_label_from_widget(
-      GTK_RADIO_BUTTON(startup_homepage_radio_),
-      l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION).c_str());
-  g_signal_connect(startup_last_session_radio_, "toggled",
-                   G_CALLBACK(OnStartupRadioToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), startup_last_session_radio_,
-                     FALSE, FALSE, 0);
-
-  startup_custom_radio_ = gtk_radio_button_new_with_label_from_widget(
-      GTK_RADIO_BUTTON(startup_homepage_radio_),
-      l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_SHOW_PAGES).c_str());
-  g_signal_connect(startup_custom_radio_, "toggled",
-                   G_CALLBACK(OnStartupRadioToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(vbox), startup_custom_radio_, FALSE, FALSE, 0);
-
-  GtkWidget* url_list_container = gtk_hbox_new(FALSE,
-                                               gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(vbox), url_list_container, TRUE, TRUE, 0);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(url_list_container),
-                    scroll_window);
-  startup_custom_pages_store_ = gtk_list_store_new(COL_COUNT,
-                                                   GDK_TYPE_PIXBUF,
-                                                   G_TYPE_STRING,
-                                                   G_TYPE_STRING);
-  startup_custom_pages_tree_ = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(startup_custom_pages_store_));
-  gtk_container_add(GTK_CONTAINER(scroll_window), startup_custom_pages_tree_);
-
-  // Release |startup_custom_pages_store_| so that |startup_custom_pages_tree_|
-  // owns the model.
-  g_object_unref(startup_custom_pages_store_);
-
-  gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(startup_custom_pages_tree_),
-                                   COL_TOOLTIP);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(startup_custom_pages_tree_),
-                                    FALSE);
-  GtkTreeViewColumn* column = gtk_tree_view_column_new();
-  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(column, renderer, FALSE);
-  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
-  renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(column, renderer, TRUE);
-  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_URL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(startup_custom_pages_tree_),
-                              column);
-  startup_custom_pages_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(startup_custom_pages_tree_));
-  gtk_tree_selection_set_mode(startup_custom_pages_selection_,
-                              GTK_SELECTION_MULTIPLE);
-  g_signal_connect(startup_custom_pages_selection_, "changed",
-                   G_CALLBACK(OnStartupPagesSelectionChangedThunk), this);
-
-  startup_custom_pages_table_model_.reset(
-      new CustomHomePagesTableModel(profile()));
-  startup_custom_pages_table_adapter_.reset(
-      new gtk_tree::TableAdapter(this, startup_custom_pages_store_,
-                                 startup_custom_pages_table_model_.get()));
-
-  GtkWidget* url_list_buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_end(GTK_BOX(url_list_container), url_list_buttons,
-                   FALSE, FALSE, 0);
-
-  startup_add_custom_page_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_ADD_BUTTON)).c_str());
-  g_signal_connect(startup_add_custom_page_button_, "clicked",
-                   G_CALLBACK(OnStartupAddCustomPageClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(url_list_buttons), startup_add_custom_page_button_,
-                     FALSE, FALSE, 0);
-  startup_remove_custom_page_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-        l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_REMOVE_BUTTON)).c_str());
-  g_signal_connect(startup_remove_custom_page_button_, "clicked",
-                   G_CALLBACK(OnStartupRemoveCustomPageClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(url_list_buttons),
-                     startup_remove_custom_page_button_, FALSE, FALSE, 0);
-  startup_use_current_page_button_ = gtk_button_new_with_mnemonic(
-      gfx::ConvertAcceleratorsFromWindowsStyle(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_USE_CURRENT)).c_str());
-  g_signal_connect(startup_use_current_page_button_, "clicked",
-                   G_CALLBACK(OnStartupUseCurrentPageClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(url_list_buttons),
-                     startup_use_current_page_button_, FALSE, FALSE, 0);
-
-  return vbox;
-}
-
-GtkWidget* GeneralPageGtk::InitHomepageGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  homepage_use_newtab_radio_ = gtk_radio_button_new_with_label(NULL,
-      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_USE_NEWTAB).c_str());
-  g_signal_connect(homepage_use_newtab_radio_, "toggled",
-                   G_CALLBACK(OnNewTabIsHomePageToggledThunk), this);
-  gtk_container_add(GTK_CONTAINER(vbox), homepage_use_newtab_radio_);
-
-  GtkWidget* homepage_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  gtk_container_add(GTK_CONTAINER(vbox), homepage_hbox);
-
-  homepage_use_url_radio_ = gtk_radio_button_new_with_label_from_widget(
-      GTK_RADIO_BUTTON(homepage_use_newtab_radio_),
-      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_USE_URL).c_str());
-  g_signal_connect(homepage_use_url_radio_, "toggled",
-                   G_CALLBACK(OnNewTabIsHomePageToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(homepage_hbox), homepage_use_url_radio_,
-                     FALSE, FALSE, 0);
-
-  homepage_use_url_entry_ = gtk_entry_new();
-  g_signal_connect(homepage_use_url_entry_, "changed",
-                   G_CALLBACK(OnHomepageUseUrlEntryChangedThunk), this);
-  gtk_box_pack_start(GTK_BOX(homepage_hbox), homepage_use_url_entry_,
-                     TRUE, TRUE, 0);
-
-  homepage_show_home_button_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_SHOW_BUTTON).c_str());
-  g_signal_connect(homepage_show_home_button_checkbox_, "toggled",
-                   G_CALLBACK(OnShowHomeButtonToggledThunk), this);
-  gtk_container_add(GTK_CONTAINER(vbox), homepage_show_home_button_checkbox_);
-
-  return vbox;
-}
-
-GtkWidget* GeneralPageGtk::InitDefaultSearchGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  GtkWidget* search_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(vbox), search_hbox, FALSE, FALSE, 0);
-
-  default_search_engines_model_ = gtk_list_store_new(SEARCH_ENGINES_COL_COUNT,
-                                                     G_TYPE_UINT,
-                                                     G_TYPE_STRING);
-  default_search_engine_combobox_ = gtk_combo_box_new_with_model(
-      GTK_TREE_MODEL(default_search_engines_model_));
-  g_object_unref(default_search_engines_model_);
-  g_signal_connect(default_search_engine_combobox_, "changed",
-                   G_CALLBACK(OnDefaultSearchEngineChangedThunk), this);
-  gtk_container_add(GTK_CONTAINER(search_hbox),
-                    default_search_engine_combobox_);
-  accessible_widget_helper_->SetWidgetName(
-      default_search_engine_combobox_, IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME);
-
-  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
-  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(default_search_engine_combobox_),
-                             renderer, TRUE);
-  gtk_cell_layout_set_attributes(
-      GTK_CELL_LAYOUT(default_search_engine_combobox_), renderer,
-      "text", SEARCH_ENGINES_COL_TITLE,
-      NULL);
-
-  template_url_model_ = profile()->GetTemplateURLModel();
-  if (template_url_model_) {
-    template_url_model_->Load();
-    template_url_model_->AddObserver(this);
-  }
-  OnTemplateURLModelChanged();
-
-  default_search_manage_engines_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(
-          IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES_LINK).c_str());
-  g_signal_connect(default_search_manage_engines_button_, "clicked",
-                   G_CALLBACK(OnDefaultSearchManageEnginesClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(search_hbox),
-                     default_search_manage_engines_button_, FALSE, FALSE, 0);
-
-  // When the instant lab is on, add some options for instant. We want the
-  // warning text and link to align with the pref's checkbox's label.
-  // Need a new vbox as we don't want any spacing between these labels.
-  GtkWidget* instant_vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), instant_vbox, FALSE, FALSE, 0);
-
-  instant_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_INSTANT_PREF).c_str());
-  g_signal_connect(instant_checkbox_, "toggled",
-                   G_CALLBACK(OnInstantToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(instant_vbox), instant_checkbox_, FALSE, FALSE, 0);
-
-  // Relies on knowledge of GTK+ internals to find the checkbox's label child
-  // and then make the indent below match its vertical spacing.
-  GtkWidget* instant_label = gtk_bin_get_child(GTK_BIN(instant_checkbox_));
-  if (instant_label && GTK_IS_LABEL(instant_label)) {
-    g_signal_connect(instant_label, "size-allocate",
-                     G_CALLBACK(OnInstantLabelSizeAllocateThunk), this);
-  }
-
-  instant_indent_ = gtk_fixed_new();
-  GtkWidget* explanation_box = gtk_hbox_new(FALSE, 0);
-  GtkWidget* explanation = gtk_label_new((
-      l10n_util::GetStringUTF8(IDS_INSTANT_PREF_WARNING) + " ").c_str());
-  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
-  g_signal_connect(learn_more_link, "clicked",
-                   G_CALLBACK(OnSearchLearnMoreClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(explanation_box), instant_indent_,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(explanation_box), explanation,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(explanation_box), learn_more_link,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(instant_vbox), explanation_box, FALSE, FALSE, 0);
-
-  return vbox;
-}
-
-GtkWidget* GeneralPageGtk::InitDefaultBrowserGroup() {
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  // TODO(mattm): the label should be created with a text like "checking for
-  // default" to be displayed while we wait for the check to complete.
-  default_browser_status_label_ = gtk_label_new(NULL);
-  gtk_box_pack_start(GTK_BOX(vbox), default_browser_status_label_,
-                     FALSE, FALSE, 0);
-
-  default_browser_use_as_default_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
-  g_signal_connect(default_browser_use_as_default_button_, "clicked",
-                   G_CALLBACK(OnBrowserUseAsDefaultClickedThunk), this);
-
-  gtk_box_pack_start(GTK_BOX(vbox), default_browser_use_as_default_button_,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* vbox_alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
-  gtk_container_add(GTK_CONTAINER(vbox_alignment), vbox);
-
-  default_browser_worker_->StartCheckDefaultBrowser();
-
-  return vbox_alignment;
-}
-
-void GeneralPageGtk::OnStartupRadioToggled(GtkWidget* toggle_button) {
-  if (initializing_)
-    return;
-
-  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
-    // When selecting a radio button, we get two signals (one for the old radio
-    // being toggled off, one for the new one being toggled on.)  Ignore the
-    // signal for toggling off the old button.
-    return;
-  }
-  SaveStartupPref();
-  if (toggle_button == startup_homepage_radio_) {
-    UserMetricsRecordAction(UserMetricsAction("Options_Startup_Homepage"),
-                            profile()->GetPrefs());
-  } else if (toggle_button == startup_last_session_radio_) {
-    UserMetricsRecordAction(UserMetricsAction("Options_Startup_LastSession"),
-                            profile()->GetPrefs());
-  } else if (toggle_button == startup_custom_radio_) {
-    UserMetricsRecordAction(UserMetricsAction("Options_Startup_Custom"),
-                            profile()->GetPrefs());
-  }
-}
-
-void GeneralPageGtk::OnStartupAddCustomPageClicked(GtkWidget* button) {
-  new UrlPickerDialogGtk(
-      NewCallback(this, &GeneralPageGtk::OnAddCustomUrl),
-      profile(),
-      GetWindow());
-}
-
-void GeneralPageGtk::OnStartupRemoveCustomPageClicked(GtkWidget* button) {
-  RemoveSelectedCustomUrls();
-}
-
-void GeneralPageGtk::OnStartupUseCurrentPageClicked(GtkWidget* button) {
-  SetCustomUrlListFromCurrentPages();
-}
-
-void GeneralPageGtk::OnStartupPagesSelectionChanged(
-    GtkTreeSelection* selection) {
-  EnableCustomHomepagesControls(true);
-}
-
-void GeneralPageGtk::OnNewTabIsHomePageToggled(GtkWidget* toggle_button) {
-  if (initializing_)
-    return;
-  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
-    // Ignore the signal for toggling off the old button.
-    return;
-  }
-  if (toggle_button == homepage_use_newtab_radio_) {
-    UserMetricsRecordAction(UserMetricsAction("Options_Homepage_UseNewTab"),
-                            profile()->GetPrefs());
-    UpdateHomepagePrefs();
-    EnableHomepageURLField(false);
-  } else if (toggle_button == homepage_use_url_radio_) {
-    UserMetricsRecordAction(UserMetricsAction("Options_Homepage_UseURL"),
-                            profile()->GetPrefs());
-    UpdateHomepagePrefs();
-    EnableHomepageURLField(true);
-  }
-}
-
-void GeneralPageGtk::OnHomepageUseUrlEntryChanged(GtkWidget* editable) {
-  if (initializing_)
-    return;
-  UpdateHomepagePrefs();
-}
-
-void GeneralPageGtk::OnShowHomeButtonToggled(GtkWidget* toggle_button) {
-  if (initializing_)
-    return;
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button));
-  show_home_button_.SetValue(enabled);
-  if (enabled) {
-    UserMetricsRecordAction(
-        UserMetricsAction("Options_Homepage_ShowHomeButton"),
-        profile()->GetPrefs());
-  } else {
-    UserMetricsRecordAction(
-        UserMetricsAction("Options_Homepage_HideHomeButton"),
-        profile()->GetPrefs());
-  }
-}
-
-void GeneralPageGtk::OnInstantToggled(GtkWidget* toggle_button) {
-  if (initializing_)
-    return;
-
-  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button));
-
-  if (enabled) {
-    if (!instant_.GetValue())
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(instant_checkbox_), false);
-    browser::ShowInstantConfirmDialogIfNecessary(GetWindow(), profile());
-  } else {
-    InstantController::Disable(profile());
-  }
-
-  // TODO(estade): UMA?
-}
-
-void GeneralPageGtk::OnDefaultSearchEngineChanged(GtkWidget* combo_box) {
-  if (default_search_initializing_)
-    return;
-  SetDefaultSearchEngineFromComboBox();
-}
-
-void GeneralPageGtk::OnDefaultSearchManageEnginesClicked(GtkWidget* button) {
-  KeywordEditorView::Show(profile());
-}
-
-void GeneralPageGtk::OnBrowserUseAsDefaultClicked(GtkWidget* button) {
-  default_browser_worker_->StartSetAsDefaultBrowser();
-  // If the user made Chrome the default browser, then he/she arguably wants
-  // to be notified when that changes.
-  profile()->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, true);
-  UserMetricsRecordAction(UserMetricsAction("Options_SetAsDefaultBrowser"),
-                          profile()->GetPrefs());
-}
-
-void GeneralPageGtk::SaveStartupPref() {
-  SessionStartupPref pref;
-
-  if (gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(startup_last_session_radio_))) {
-    pref.type = SessionStartupPref::LAST;
-  } else if (gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(startup_custom_radio_))) {
-    pref.type = SessionStartupPref::URLS;
-  }
-
-  pref.urls = startup_custom_pages_table_model_->GetURLs();
-
-  SessionStartupPref::SetStartupPref(profile()->GetPrefs(), pref);
-}
-
-void GeneralPageGtk::SetColumnValues(int row, GtkTreeIter* iter) {
-  SkBitmap bitmap = startup_custom_pages_table_model_->GetIcon(row);
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
-  string16 text = startup_custom_pages_table_model_->GetText(row, 0);
-  std::string tooltip =
-      UTF16ToUTF8(startup_custom_pages_table_model_->GetTooltip(row));
-  gchar* escaped_tooltip = g_markup_escape_text(tooltip.c_str(),
-                                                tooltip.size());
-  gtk_list_store_set(startup_custom_pages_store_, iter,
-                     COL_FAVICON, pixbuf,
-                     COL_URL, UTF16ToUTF8(text).c_str(),
-                     COL_TOOLTIP, escaped_tooltip,
-                     -1);
-  g_object_unref(pixbuf);
-  g_free(escaped_tooltip);
-}
-
-void GeneralPageGtk::SetCustomUrlListFromCurrentPages() {
-  startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
-
-  SaveStartupPref();
-}
-
-void GeneralPageGtk::OnAddCustomUrl(const GURL& url) {
-  // The restore URLs policy might have become managed while the dialog is
-  // displayed.  While the model makes sure that no changes are made in this
-  // condition, we should still avoid the rest of the method otherwise
-  // graphic elements will become enabled.
-  if (SessionStartupPref::URLsAreManaged(profile()->GetPrefs()))
-    return;
-  std::set<int> indices;
-  gtk_tree::GetSelectedIndices(startup_custom_pages_selection_, &indices);
-  int index;
-  if (indices.empty())
-    index = startup_custom_pages_table_model_->RowCount();
-  else
-    index = *indices.begin() + 1;
-  startup_custom_pages_table_model_->Add(index, url);
-
-  SaveStartupPref();
-
-  gtk_tree::SelectAndFocusRowNum(index,
-                                 GTK_TREE_VIEW(startup_custom_pages_tree_));
-}
-
-void GeneralPageGtk::RemoveSelectedCustomUrls() {
-  std::set<int> indices;
-  gtk_tree::GetSelectedIndices(startup_custom_pages_selection_, &indices);
-
-  int selected_row = 0;
-  for (std::set<int>::reverse_iterator i = indices.rbegin();
-       i != indices.rend(); ++i) {
-    startup_custom_pages_table_model_->Remove(*i);
-    selected_row = *i;
-  }
-
-  SaveStartupPref();
-
-  // Select the next row after the last row deleted, or the above item if the
-  // latest item was deleted or nothing when the table doesn't have any items.
-  int row_count = startup_custom_pages_table_model_->RowCount();
-  if (selected_row >= row_count)
-    selected_row = row_count - 1;
-  if (selected_row >= 0) {
-    gtk_tree::SelectAndFocusRowNum(selected_row,
-                                   GTK_TREE_VIEW(startup_custom_pages_tree_));
-  }
-}
-
-void GeneralPageGtk::OnTemplateURLModelChanged() {
-  if (!template_url_model_ || !template_url_model_->loaded()) {
-    EnableDefaultSearchEngineComboBox(false);
-    return;
-  }
-  default_search_initializing_ = true;
-  gtk_list_store_clear(default_search_engines_model_);
-  const TemplateURL* default_search_provider =
-      template_url_model_->GetDefaultSearchProvider();
-  std::vector<const TemplateURL*> model_urls =
-      template_url_model_->GetTemplateURLs();
-  bool populated = false;
-  for (size_t i = 0; i < model_urls.size(); ++i) {
-    if (!model_urls[i]->ShowInDefaultList())
-      continue;
-    populated = true;
-    GtkTreeIter iter;
-    gtk_list_store_append(default_search_engines_model_, &iter);
-    gtk_list_store_set(
-        default_search_engines_model_, &iter,
-        SEARCH_ENGINES_COL_INDEX, i,
-        SEARCH_ENGINES_COL_TITLE,
-        WideToUTF8(model_urls[i]->short_name()).c_str(),
-        -1);
-    if (model_urls[i] == default_search_provider) {
-      gtk_combo_box_set_active_iter(
-          GTK_COMBO_BOX(default_search_engine_combobox_), &iter);
-    }
-  }
-  EnableDefaultSearchEngineComboBox(populated &&
-      !template_url_model_->is_default_search_managed());
-  default_search_initializing_ = false;
-}
-
-void GeneralPageGtk::SetDefaultSearchEngineFromComboBox() {
-  GtkTreeIter iter;
-  if (!gtk_combo_box_get_active_iter(
-      GTK_COMBO_BOX(default_search_engine_combobox_), &iter)) {
-    return;
-  }
-  guint index;
-  gtk_tree_model_get(GTK_TREE_MODEL(default_search_engines_model_), &iter,
-                     SEARCH_ENGINES_COL_INDEX, &index,
-                     -1);
-  std::vector<const TemplateURL*> model_urls =
-      template_url_model_->GetTemplateURLs();
-  if (index < model_urls.size())
-    template_url_model_->SetDefaultSearchProvider(model_urls[index]);
-  else
-    NOTREACHED();
-}
-
-void GeneralPageGtk::EnableDefaultSearchEngineComboBox(bool enable) {
-  gtk_widget_set_sensitive(default_search_engine_combobox_, enable);
-}
-
-void GeneralPageGtk::UpdateHomepagePrefs() {
-  const GURL& homepage = URLFixerUpper::FixupURL(
-      gtk_entry_get_text(GTK_ENTRY(homepage_use_url_entry_)), std::string());
-  bool new_tab_page_is_home_page =
-    gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(homepage_use_newtab_radio_));
-  if (IsNewTabUIURLString(homepage)) {
-    new_tab_page_is_home_page = true;
-    homepage_.SetValueIfNotManaged(std::string());
-  } else if (!homepage.is_valid()) {
-    new_tab_page_is_home_page = true;
-    if (!homepage.has_host())
-      homepage_.SetValueIfNotManaged(std::string());
-  } else {
-    homepage_.SetValueIfNotManaged(homepage.spec());
-  }
-  new_tab_page_is_home_page_.SetValueIfNotManaged(new_tab_page_is_home_page);
-}
-
-void GeneralPageGtk::UpdateHomepageIsNewTabRadio(bool homepage_is_new_tab,
-                                                 bool enabled) {
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(homepage_use_newtab_radio_),
-                               homepage_is_new_tab);
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(homepage_use_url_radio_),
-                               !homepage_is_new_tab);
-  gtk_widget_set_sensitive(homepage_use_newtab_radio_, enabled);
-  gtk_widget_set_sensitive(homepage_use_url_radio_, enabled);
-}
-
-void GeneralPageGtk::EnableHomepageURLField(bool enabled) {
-  if (homepage_.IsManaged())
-    enabled = false;
-  gtk_widget_set_sensitive(homepage_use_url_entry_, enabled);
-}
-
-void GeneralPageGtk::EnableCustomHomepagesControls(bool enable) {
-  gtk_widget_set_sensitive(startup_add_custom_page_button_, enable);
-  gtk_widget_set_sensitive(startup_remove_custom_page_button_,
-      enable &&
-      gtk_tree_selection_count_selected_rows(startup_custom_pages_selection_));
-  gtk_widget_set_sensitive(startup_use_current_page_button_, enable);
-  gtk_widget_set_sensitive(startup_custom_pages_tree_, enable);
-}
-
-void GeneralPageGtk::SetDefaultBrowserUIState(
-    ShellIntegration::DefaultBrowserUIState state) {
-  const char* color = NULL;
-  std::string text;
-  if (state == ShellIntegration::STATE_IS_DEFAULT) {
-    color = kDefaultBrowserLabelColor;
-    text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_DEFAULT,
-        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  } else if (state == ShellIntegration::STATE_NOT_DEFAULT) {
-    color = kNotDefaultBrowserLabelColor;
-    text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT,
-        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  } else if (state == ShellIntegration::STATE_UNKNOWN) {
-    color = kNotDefaultBrowserLabelColor;
-    text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
-        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  }
-  if (color) {
-    char* markup = g_markup_printf_escaped(kDefaultBrowserLabelMarkup,
-                                           color, text.c_str());
-    gtk_label_set_markup(GTK_LABEL(default_browser_status_label_), markup);
-    g_free(markup);
-  }
-
-  gtk_widget_set_sensitive(default_browser_use_as_default_button_,
-                           state == ShellIntegration::STATE_NOT_DEFAULT);
-}
-
-void GeneralPageGtk::OnInstantLabelSizeAllocate(GtkWidget* sender,
-                                                GtkAllocation* allocation) {
-  int desired_width = allocation->x - sender->parent->allocation.x;
-  GtkRequisition req;
-  gtk_widget_size_request(instant_indent_, &req);
-  if (req.width != desired_width)
-    gtk_widget_set_size_request(instant_indent_, desired_width, -1);
-}
-
-void GeneralPageGtk::OnSearchLearnMoreClicked(GtkWidget* sender) {
-  browser::ShowOptionsURL(profile(), browser::InstantLearnMoreURL());
-}
diff --git a/chrome/browser/gtk/options/general_page_gtk.h b/chrome/browser/gtk/options/general_page_gtk.h
deleted file mode 100644
index 05dac88..0000000
--- a/chrome/browser/gtk/options/general_page_gtk.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_GENERAL_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_GENERAL_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h"
-#include "chrome/browser/prefs/pref_change_registrar.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/search_engines/template_url_model_observer.h"
-#include "chrome/browser/shell_integration.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-#include "googleurl/src/gurl.h"
-
-class AccessibleWidgetHelper;
-class CustomHomePagesTableModel;
-class Profile;
-class TemplateURLModel;
-
-class GeneralPageGtk : public OptionsPageBase,
-                       public TemplateURLModelObserver,
-                       public ShellIntegration::DefaultBrowserObserver,
-                       public gtk_tree::TableAdapter::Delegate {
- public:
-  explicit GeneralPageGtk(Profile* profile);
-  ~GeneralPageGtk();
-
-  GtkWidget* get_page_widget() const { return page_; }
-
- private:
-  GtkWindow* GetWindow();
-
-  // Overridden from OptionsPageBase
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-  virtual void HighlightGroup(OptionsGroup highlight_group);
-
-  // Initialize the option group widgets, return their container
-  GtkWidget* InitStartupGroup();
-  GtkWidget* InitHomepageGroup();
-  GtkWidget* InitDefaultSearchGroup();
-  GtkWidget* InitDefaultBrowserGroup();
-
-  // Saves the startup preference from the values in the ui
-  void SaveStartupPref();
-
-  // Set the custom url list using the pages currently open
-  void SetCustomUrlListFromCurrentPages();
-
-  // Callback from UrlPickerDialogGtk, for adding custom urls manually.
-  // If a single row in the list is selected, the new url will be inserted
-  // before that row.  Otherwise the new row will be added to the end.
-  void OnAddCustomUrl(const GURL& url);
-
-  // Removes urls that are currently selected
-  void RemoveSelectedCustomUrls();
-
-  // Overridden from TemplateURLModelObserver.
-  // Populates the default search engine combobox from the model.
-  virtual void OnTemplateURLModelChanged();
-
-  // Set the default search engine pref to the combo box active item.
-  void SetDefaultSearchEngineFromComboBox();
-
-  // Set the default search engine combo box state.
-  void EnableDefaultSearchEngineComboBox(bool enable);
-
-  // Copies the home page preferences from the gui controls to
-  // kNewTabPageIsHomePage and kHomePage. If an empty or null-host
-  // URL is specified, then we revert to using NewTab page as the Homepage.
-  void UpdateHomepagePrefs();
-
-  // Enables or disables the field for entering a custom homepage URL.
-  void EnableHomepageURLField(bool enabled);
-
-  // Sets the state and enables/disables the radio buttons that control
-  // if the home page is the new tab page.
-  void UpdateHomepageIsNewTabRadio(bool homepage_is_new_tab, bool enabled);
-
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupRadioToggled);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupAddCustomPageClicked);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupRemoveCustomPageClicked);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupUseCurrentPageClicked);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnNewTabIsHomePageToggled);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnHomepageUseUrlEntryChanged);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnShowHomeButtonToggled);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnDefaultSearchEngineChanged);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void,
-                       OnDefaultSearchManageEnginesClicked);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnInstantToggled);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnBrowserUseAsDefaultClicked);
-  CHROMEGTK_CALLBACK_1(GeneralPageGtk, void, OnInstantLabelSizeAllocate,
-                       GtkAllocation*);
-  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnSearchLearnMoreClicked);
-
-  CHROMEG_CALLBACK_0(GeneralPageGtk, void, OnStartupPagesSelectionChanged,
-                     GtkTreeSelection*);
-
-  // Enables/Disables the controls associated with the custom start pages
-  // option if that preference is not selected.
-  void EnableCustomHomepagesControls(bool enable);
-
-  // ShellIntegration::DefaultBrowserObserver implementation.
-  virtual void SetDefaultBrowserUIState(
-      ShellIntegration::DefaultBrowserUIState state);
-
-  // gtk_tree::TableAdapter::Delegate implementation.
-  virtual void SetColumnValues(int row, GtkTreeIter* iter);
-
-  // Widgets of the startup group
-  GtkWidget* startup_homepage_radio_;
-  GtkWidget* startup_last_session_radio_;
-  GtkWidget* startup_custom_radio_;
-  GtkWidget* startup_custom_pages_tree_;
-  GtkListStore* startup_custom_pages_store_;
-  GtkTreeSelection* startup_custom_pages_selection_;
-  GtkWidget* startup_add_custom_page_button_;
-  GtkWidget* startup_remove_custom_page_button_;
-  GtkWidget* startup_use_current_page_button_;
-
-  // The model for |startup_custom_pages_store_|.
-  scoped_ptr<CustomHomePagesTableModel> startup_custom_pages_table_model_;
-  scoped_ptr<gtk_tree::TableAdapter> startup_custom_pages_table_adapter_;
-
-  // Widgets and prefs of the homepage group
-  GtkWidget* homepage_use_newtab_radio_;
-  GtkWidget* homepage_use_url_radio_;
-  GtkWidget* homepage_use_url_entry_;
-  GtkWidget* homepage_show_home_button_checkbox_;
-  BooleanPrefMember new_tab_page_is_home_page_;
-  StringPrefMember homepage_;
-  BooleanPrefMember show_home_button_;
-
-  // Widgets and data of the default search group
-  GtkWidget* default_search_engine_combobox_;
-  GtkListStore* default_search_engines_model_;
-  GtkWidget* default_search_manage_engines_button_;
-  TemplateURLModel* template_url_model_;
-  GtkWidget* instant_checkbox_;
-  // This widget acts as the indent for the instant warning label.
-  GtkWidget* instant_indent_;
-  BooleanPrefMember instant_;
-
-  // Widgets of the default browser group
-  GtkWidget* default_browser_status_label_;
-  GtkWidget* default_browser_use_as_default_button_;
-
-  // The parent GtkTable widget
-  GtkWidget* page_;
-
-  // Flag to ignore gtk callbacks while we are populating default search urls.
-  bool default_search_initializing_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool initializing_;
-
-  // The helper object that performs default browser set/check tasks.
-  scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  // Tracks managed preference warning banner state.
-  ManagedPrefsBannerGtk managed_prefs_banner_;
-
-  PrefChangeRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(GeneralPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_GENERAL_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/languages_page_gtk.cc b/chrome/browser/gtk/options/languages_page_gtk.cc
deleted file mode 100644
index 6a400db..0000000
--- a/chrome/browser/gtk/options/languages_page_gtk.cc
+++ /dev/null
@@ -1,451 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/languages_page_gtk.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/language_combobox_model.h"
-#include "chrome/browser/language_order_table_model.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/spellcheck_common.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-const int kWrapWidth = 475;
-
-GtkWidget* NewComboboxFromModel(ComboboxModel* model) {
-  GtkWidget* combobox = gtk_combo_box_new_text();
-  int count = model->GetItemCount();
-  for (int i = 0; i < count; ++i)
-    gtk_combo_box_append_text(GTK_COMBO_BOX(combobox),
-                              UTF16ToUTF8(model->GetItemAt(i)).c_str());
-  return combobox;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// AddLanguageDialog
-
-class AddLanguageDialog {
- public:
-  AddLanguageDialog(Profile* profile, LanguagesPageGtk* delegate);
-  virtual ~AddLanguageDialog() {}
-
- private:
-  // Callback for dialog buttons.
-  CHROMEGTK_CALLBACK_1(AddLanguageDialog, void, OnResponse, int);
-
-  // Callback for window destruction.
-  CHROMEGTK_CALLBACK_0(AddLanguageDialog, void, OnWindowDestroy);
-
-  // The dialog window.
-  GtkWidget* dialog_;
-
-  // The language chooser combobox.
-  GtkWidget* combobox_;
-  scoped_ptr<LanguageComboboxModel> accept_language_combobox_model_;
-
-  // Used for call back to LanguagePageGtk that language has been selected.
-  LanguagesPageGtk* language_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(AddLanguageDialog);
-};
-
-AddLanguageDialog::AddLanguageDialog(Profile* profile,
-                                     LanguagesPageGtk* delegate)
-    : language_delegate_(delegate) {
-  GtkWindow* parent = GTK_WINDOW(
-      gtk_widget_get_toplevel(delegate->get_page_widget()));
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(
-          IDS_FONT_LANGUAGE_SETTING_LANGUAGES_TAB_TITLE).c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_CANCEL,
-      GTK_STOCK_ADD,
-      GTK_RESPONSE_OK,
-      NULL);
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  const std::string app_locale = g_browser_process->GetApplicationLocale();
-  std::vector<std::string> locale_codes;
-  l10n_util::GetAcceptLanguagesForLocale(app_locale, &locale_codes);
-  accept_language_combobox_model_.reset(
-      new LanguageComboboxModel(profile, locale_codes));
-  combobox_ = NewComboboxFromModel(accept_language_combobox_model_.get());
-  gtk_combo_box_set_active(GTK_COMBO_BOX(combobox_), 0);
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), combobox_);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-
-  gtk_util::ShowDialog(dialog_);
-}
-
-void AddLanguageDialog::OnResponse(GtkWidget* dialog, int response_id) {
-  if (response_id == GTK_RESPONSE_OK) {
-    int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox_));
-    language_delegate_->OnAddLanguage(
-        accept_language_combobox_model_->GetLocaleFromIndex(selected));
-  }
-  gtk_widget_destroy(dialog_);
-}
-
-void AddLanguageDialog::OnWindowDestroy(GtkWidget* widget) {
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// LanguagesPageGtk
-
-LanguagesPageGtk::LanguagesPageGtk(Profile* profile)
-    : OptionsPageBase(profile),
-      enable_autospellcorrect_checkbox_(NULL),
-      initializing_(true) {
-  Init();
-}
-
-LanguagesPageGtk::~LanguagesPageGtk() {
-}
-
-void LanguagesPageGtk::Init() {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(page_),
-                                 gtk_util::kContentAreaBorder);
-
-  // Languages order controls.
-  GtkWidget* languages_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(page_), languages_vbox,
-                     TRUE, TRUE, 0);
-
-  GtkWidget* languages_instructions_label = gtk_label_new(
-      l10n_util::GetStringUTF8(
-          IDS_FONT_LANGUAGE_SETTING_LANGUAGES_INSTRUCTIONS).c_str());
-  gtk_misc_set_alignment(GTK_MISC(languages_instructions_label), 0, .5);
-  gtk_util::SetLabelWidth(languages_instructions_label, kWrapWidth);
-  gtk_box_pack_start(GTK_BOX(languages_vbox), languages_instructions_label,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* languages_list_hbox = gtk_hbox_new(FALSE,
-                                                gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(languages_vbox), languages_list_hbox,
-                     TRUE, TRUE, 0);
-
-  // Languages order tree.
-  language_order_store_ = gtk_list_store_new(COL_COUNT,
-                                             G_TYPE_STRING);
-  language_order_tree_ = gtk_tree_view_new_with_model(
-      GTK_TREE_MODEL(language_order_store_));
-  g_object_unref(language_order_store_);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(language_order_tree_), FALSE);
-  GtkTreeViewColumn* lang_column = gtk_tree_view_column_new_with_attributes(
-      "",
-      gtk_cell_renderer_text_new(),
-      "text", COL_LANG,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(language_order_tree_), lang_column);
-  language_order_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(language_order_tree_));
-  gtk_tree_selection_set_mode(language_order_selection_,
-                              GTK_SELECTION_MULTIPLE);
-  g_signal_connect(language_order_selection_, "changed",
-                   G_CALLBACK(OnSelectionChangedThunk), this);
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(scroll_window), language_order_tree_);
-  gtk_box_pack_start(GTK_BOX(languages_list_hbox), scroll_window,
-                     TRUE, TRUE, 0);
-
-  language_order_table_model_.reset(new LanguageOrderTableModel);
-  language_order_table_adapter_.reset(
-      new gtk_tree::TableAdapter(this, language_order_store_,
-                                 language_order_table_model_.get()));
-
-  // Languages order buttons.
-  GtkWidget* languages_buttons_vbox = gtk_vbox_new(FALSE,
-                                                   gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(languages_list_hbox), languages_buttons_vbox,
-                     FALSE, FALSE, 0);
-
-  add_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
-      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_ADD_BUTTON_LABEL).c_str());
-  g_signal_connect(add_button_, "clicked",
-                   G_CALLBACK(OnAddButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), add_button_,
-                     FALSE, FALSE, 0);
-
-  std::string remove_button_text  = l10n_util::GetStringUTF8(
-      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_REMOVE_BUTTON_LABEL);
-  remove_button_ = gtk_button_new_with_label(remove_button_text.c_str());
-  g_signal_connect(remove_button_, "clicked",
-                   G_CALLBACK(OnRemoveButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), remove_button_,
-                     FALSE, FALSE, 0);
-
-  std::string move_up_button_text  = l10n_util::GetStringUTF8(
-      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_MOVEUP_BUTTON_LABEL);
-  move_up_button_ = gtk_button_new_with_label(move_up_button_text.c_str());
-  g_signal_connect(move_up_button_, "clicked",
-                   G_CALLBACK(OnMoveUpButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), move_up_button_,
-                     FALSE, FALSE, 0);
-
-  std::string move_down_button_text  = l10n_util::GetStringUTF8(
-      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_MOVEDOWN_BUTTON_LABEL);
-  move_down_button_ = gtk_button_new_with_label(move_down_button_text.c_str());
-  g_signal_connect(move_down_button_, "clicked",
-                   G_CALLBACK(OnMoveDownButtonClickedThunk), this);
-  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), move_down_button_,
-                     FALSE, FALSE, 0);
-
-  // Spell checker controls.
-  GtkWidget* spellchecker_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(page_), spellchecker_vbox,
-                     FALSE, FALSE, 0);
-
-  enable_spellchecking_checkbox_ = gtk_check_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_OPTIONS_ENABLE_SPELLCHECK).c_str());
-  g_signal_connect(enable_spellchecking_checkbox_, "toggled",
-                   G_CALLBACK(OnEnableSpellCheckingToggledThunk), this);
-  gtk_box_pack_start(GTK_BOX(spellchecker_vbox), enable_spellchecking_checkbox_,
-                     FALSE, FALSE, 0);
-
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures)) {
-    enable_autospellcorrect_checkbox_ = gtk_check_button_new_with_label(
-        l10n_util::GetStringUTF8(
-            IDS_OPTIONS_ENABLE_AUTO_SPELL_CORRECTION).c_str());
-    g_signal_connect(enable_autospellcorrect_checkbox_, "toggled",
-                     G_CALLBACK(OnEnableAutoSpellCheckingToggledThunk), this);
-    gtk_box_pack_start(GTK_BOX(spellchecker_vbox),
-                       enable_autospellcorrect_checkbox_, FALSE, FALSE, 0);
-  }
-
-  std::vector<std::string> spell_check_languages;
-  SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
-  dictionary_language_model_.reset(new LanguageComboboxModel(profile(),
-      spell_check_languages));
-  dictionary_language_combobox_ = NewComboboxFromModel(
-      dictionary_language_model_.get());
-  g_signal_connect(dictionary_language_combobox_, "changed",
-                   G_CALLBACK(OnDictionaryLanguageChangedThunk), this);
-  GtkWidget* dictionary_language_control =
-      gtk_util::CreateLabeledControlsGroup(NULL,
-          l10n_util::GetStringUTF8(
-              IDS_OPTIONS_CHROME_DICTIONARY_LANGUAGE).c_str(),
-          dictionary_language_combobox_,
-          NULL);
-  gtk_box_pack_start(GTK_BOX(spellchecker_vbox), dictionary_language_control,
-                     FALSE, FALSE, 0);
-
-  // Initialize.
-  accept_languages_.Init(prefs::kAcceptLanguages,
-                         profile()->GetPrefs(), this);
-  dictionary_language_.Init(prefs::kSpellCheckDictionary,
-                            profile()->GetPrefs(), this);
-  enable_spellcheck_.Init(prefs::kEnableSpellCheck,
-                          profile()->GetPrefs(), this);
-  enable_autospellcorrect_.Init(prefs::kEnableAutoSpellCorrect,
-                                profile()->GetPrefs(), this);
-  NotifyPrefChanged(NULL);
-  EnableControls();
-}
-
-void LanguagesPageGtk::SetColumnValues(int row, GtkTreeIter* iter) {
-  string16 lang = language_order_table_model_->GetText(row, 0);
-  gtk_list_store_set(language_order_store_, iter,
-                     COL_LANG, UTF16ToUTF8(lang).c_str(),
-                     -1);
-}
-
-void LanguagesPageGtk::OnAnyModelUpdate() {
-  if (!initializing_)
-    accept_languages_.SetValue(language_order_table_model_->GetLanguageList());
-  EnableControls();
-}
-
-void LanguagesPageGtk::EnableControls() {
-  int num_selected = gtk_tree_selection_count_selected_rows(
-      language_order_selection_);
-  int row_count = gtk_tree_model_iter_n_children(
-      GTK_TREE_MODEL(language_order_store_), NULL);
-  gtk_widget_set_sensitive(move_up_button_,
-                           num_selected == 1 && FirstSelectedRowNum() > 0);
-  gtk_widget_set_sensitive(move_down_button_,
-                           num_selected == 1 &&
-                           FirstSelectedRowNum() < row_count - 1);
-  gtk_widget_set_sensitive(remove_button_, num_selected > 0);
-}
-
-int LanguagesPageGtk::FirstSelectedRowNum() {
-  int row_num = -1;
-  GList* list = gtk_tree_selection_get_selected_rows(language_order_selection_,
-                                                     NULL);
-  if (list) {
-    row_num = gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(list->data));
-    g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
-    g_list_free(list);
-  }
-  return row_num;
-}
-
-void LanguagesPageGtk::NotifyPrefChanged(const std::string* pref_name) {
-  initializing_ = true;
-  if (!pref_name || *pref_name == prefs::kAcceptLanguages) {
-    language_order_table_model_->SetAcceptLanguagesString(
-        accept_languages_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kSpellCheckDictionary) {
-    int index = dictionary_language_model_->GetSelectedLanguageIndex(
-        prefs::kSpellCheckDictionary);
-
-    // If not found, fall back from "language-region" to "language".
-    if (index < 0) {
-      const std::string& lang_region = dictionary_language_.GetValue();
-      dictionary_language_.SetValue(
-          SpellCheckCommon::GetLanguageFromLanguageRegion(lang_region));
-      index = dictionary_language_model_->GetSelectedLanguageIndex(
-          prefs::kSpellCheckDictionary);
-    }
-
-    gtk_combo_box_set_active(GTK_COMBO_BOX(dictionary_language_combobox_),
-                             index);
-  }
-  if (!pref_name || *pref_name == prefs::kEnableSpellCheck) {
-    gtk_toggle_button_set_active(
-        GTK_TOGGLE_BUTTON(enable_spellchecking_checkbox_),
-        enable_spellcheck_.GetValue());
-  }
-  if (!pref_name || *pref_name == prefs::kEnableAutoSpellCorrect) {
-    if (enable_autospellcorrect_checkbox_) {
-      gtk_toggle_button_set_active(
-          GTK_TOGGLE_BUTTON(enable_autospellcorrect_checkbox_),
-          enable_autospellcorrect_.GetValue());
-    }
-  }
-  initializing_ = false;
-}
-
-void LanguagesPageGtk::OnAddLanguage(const std::string& new_language) {
-  if (language_order_table_model_->Add(new_language))
-    gtk_tree::SelectAndFocusRowNum(language_order_table_model_->RowCount() - 1,
-                                   GTK_TREE_VIEW(language_order_tree_));
-}
-
-void LanguagesPageGtk::OnSelectionChanged(GtkTreeSelection* selection) {
-  EnableControls();
-}
-
-void LanguagesPageGtk::OnAddButtonClicked(GtkWidget* button) {
-  new AddLanguageDialog(profile(), this);
-}
-
-void LanguagesPageGtk::OnRemoveButtonClicked(GtkWidget* button) {
-  std::set<int> selected_rows;
-  gtk_tree::GetSelectedIndices(language_order_selection_,
-                               &selected_rows);
-
-  int selected_row = 0;
-  for (std::set<int>::reverse_iterator selected = selected_rows.rbegin();
-       selected != selected_rows.rend(); ++selected) {
-    language_order_table_model_->Remove(*selected);
-    selected_row = *selected;
-  }
-  int row_count = language_order_table_model_->RowCount();
-  if (row_count <= 0)
-    return;
-  if (selected_row >= row_count)
-    selected_row = row_count - 1;
-  gtk_tree::SelectAndFocusRowNum(selected_row,
-      GTK_TREE_VIEW(language_order_tree_));
-}
-
-void LanguagesPageGtk::OnMoveUpButtonClicked(GtkWidget* button) {
-  int item_selected = FirstSelectedRowNum();
-  language_order_table_model_->MoveUp(item_selected);
-  gtk_tree::SelectAndFocusRowNum(
-      item_selected - 1, GTK_TREE_VIEW(language_order_tree_));
-}
-
-void LanguagesPageGtk::OnMoveDownButtonClicked(GtkWidget* button) {
-  int item_selected = FirstSelectedRowNum();
-  language_order_table_model_->MoveDown(item_selected);
-  gtk_tree::SelectAndFocusRowNum(
-      item_selected + 1, GTK_TREE_VIEW(language_order_tree_));
-}
-
-void LanguagesPageGtk::OnEnableSpellCheckingToggled(GtkWidget* toggle_button) {
-  if (initializing_)
-    return;
-  enable_spellcheck_.SetValue(
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
-}
-
-void LanguagesPageGtk::OnEnableAutoSpellCheckingToggled(
-    GtkWidget* toggle_button) {
-  if (initializing_)
-    return;
-  enable_autospellcorrect_.SetValue(
-      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
-}
-
-void LanguagesPageGtk::OnDictionaryLanguageChanged(GtkWidget* widget) {
-  if (initializing_)
-    return;
-  int new_index = gtk_combo_box_get_active(
-      GTK_COMBO_BOX(dictionary_language_combobox_));
-
-  if (new_index < 0 ||
-      new_index >= dictionary_language_model_->GetItemCount()) {
-    NOTREACHED();
-    return;
-  }
-
-  // Remove the previously added spell check language to the accept list.
-  if (!spellcheck_language_added_.empty()) {
-    int old_index = language_order_table_model_->GetIndex(
-        spellcheck_language_added_);
-    if (old_index > -1)
-      language_order_table_model_->Remove(old_index);
-  }
-
-  // Add this new spell check language only if it is not already in the
-  // accept language list.
-  std::string language =
-      dictionary_language_model_->GetLocaleFromIndex(new_index);
-  int index = language_order_table_model_->GetIndex(language);
-  if (index == -1) {
-    // Add the new language.
-    OnAddLanguage(language);
-    spellcheck_language_added_ = language;
-  } else {
-    spellcheck_language_added_ = "";
-  }
-
-  UserMetricsRecordAction(UserMetricsAction("Options_DictionaryLanguage"),
-                          profile()->GetPrefs());
-  dictionary_language_.SetValue(language);
-}
diff --git a/chrome/browser/gtk/options/languages_page_gtk.h b/chrome/browser/gtk/options/languages_page_gtk.h
deleted file mode 100644
index 5fb41bb..0000000
--- a/chrome/browser/gtk/options/languages_page_gtk.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The languages page of the Languages & languages options dialog, which
-// contains accept-languages and spellchecker language options.
-//
-// Note that we intentionally do not implement the application locale setting,
-// as it does not make sense on Linux, where locale is set through the LANG and
-// LC_* environment variables.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/gtest_prod_util.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/ui/options/options_page_base.h"
-
-class LanguageComboboxModel;
-class LanguageOrderTableModel;
-
-class LanguagesPageGtk
-    : public OptionsPageBase,
-      public gtk_tree::TableAdapter::Delegate {
- public:
-  explicit LanguagesPageGtk(Profile* profile);
-  virtual ~LanguagesPageGtk();
-
-  GtkWidget* get_page_widget() const { return page_; }
-
-  // gtk_tree::TableAdapter::Delegate implementation.
-  virtual void OnAnyModelUpdate();
-  virtual void SetColumnValues(int row, GtkTreeIter* iter);
-
-  // Callback from AddLanguageDialog.
-  void OnAddLanguage(const std::string& new_language);
-
- private:
-  // Column ids for |language_order_store_|.
-  enum {
-    COL_LANG,
-    COL_COUNT,
-  };
-
-  void Init();
-
-  // Enable buttons based on selection state.
-  void EnableControls();
-
-  // Get the row number of the first selected row or -1 if no row is selected.
-  int FirstSelectedRowNum();
-
-  // Overridden from OptionsPageBase.
-  virtual void NotifyPrefChanged(const std::string* pref_name);
-
-  // Callbacks for accept languages widgets.
-  CHROMEG_CALLBACK_0(LanguagesPageGtk, void, OnSelectionChanged,
-                     GtkTreeSelection*);
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnAddButtonClicked);
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnRemoveButtonClicked);
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnMoveUpButtonClicked);
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnMoveDownButtonClicked);
-
-  // Callbacks for spellchecker option widgets.
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnEnableSpellCheckingToggled);
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void,
-                       OnEnableAutoSpellCheckingToggled);
-  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnDictionaryLanguageChanged);
-
-  // The accept languages widgets.
-  GtkListStore* language_order_store_;
-  GtkWidget* language_order_tree_;
-  GtkTreeSelection* language_order_selection_;
-  GtkWidget* move_up_button_;
-  GtkWidget* move_down_button_;
-  GtkWidget* add_button_;
-  GtkWidget* remove_button_;
-
-  // The spell checking widgets.
-  GtkWidget* dictionary_language_combobox_;
-  GtkWidget* enable_autospellcorrect_checkbox_;
-  GtkWidget* enable_spellchecking_checkbox_;
-
-  // The widget containing the options for this page.
-  GtkWidget* page_;
-
-  // The model for |language_order_store_|.
-  scoped_ptr<LanguageOrderTableModel> language_order_table_model_;
-  scoped_ptr<gtk_tree::TableAdapter> language_order_table_adapter_;
-
-  // Accept languages pref.
-  StringPrefMember accept_languages_;
-
-  // The spellchecker "dictionary language" pref and model.
-  StringPrefMember dictionary_language_;
-  scoped_ptr<LanguageComboboxModel> dictionary_language_model_;
-
-  // If a language was auto-added to accept_languages_ due to being selected as
-  // the dictionary language, it is saved in this string, so that it can be
-  // removed if the dictionary language is changed again.
-  std::string spellcheck_language_added_;
-
-  // SpellChecker enable pref.
-  BooleanPrefMember enable_spellcheck_;
-
-  // Auto spell correction pref.
-  BooleanPrefMember enable_autospellcorrect_;
-
-  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
-  // then turning around and saving them again.
-  bool initializing_;
-
-  friend class LanguagesPageGtkTest;
-  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, RemoveAcceptLang);
-  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, RemoveMultipleAcceptLang);
-  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, MoveAcceptLang);
-  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, AddAcceptLang);
-  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, EnableSpellChecking);
-  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, DictionaryLanguage);
-
-  DISALLOW_COPY_AND_ASSIGN(LanguagesPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/languages_page_gtk_unittest.cc b/chrome/browser/gtk/options/languages_page_gtk_unittest.cc
deleted file mode 100644
index d861c35..0000000
--- a/chrome/browser/gtk/options/languages_page_gtk_unittest.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/languages_page_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "chrome/browser/language_combobox_model.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class LanguagesPageGtkTest : public testing::Test {
- public:
-  virtual void SetUp() {
-    profile_.reset(new TestingProfile());
-  }
-
-  // Get the accept languages displayed in the dialog in the order they are
-  // displayed, as a comma seperated string.
-  // Ex: EXPECT_STREQ("en,ja", GetDisplayedLangs(page).c_str());
-  std::string GetDisplayedLangs(const LanguagesPageGtk& page) {
-    std::vector<std::string> parts;
-    GtkTreeModel* tree_model = GTK_TREE_MODEL(page.language_order_store_);
-    GtkTreeIter iter;
-    if (!gtk_tree_model_get_iter_first(tree_model, &iter))
-      return std::string();
-    while (true) {
-      gchar* name;
-      gtk_tree_model_get(tree_model, &iter, LanguagesPageGtk::COL_LANG, &name,
-                         -1);
-      parts.push_back(name);
-      g_free(name);
-      if (!gtk_tree_model_iter_next(tree_model, &iter))
-        break;
-    }
-    return JoinString(parts, ',');
-  }
-
-  std::string GetDisplayedSpellCheckerLang(const LanguagesPageGtk& page) {
-    gchar* text = gtk_combo_box_get_active_text(
-        GTK_COMBO_BOX(page.dictionary_language_combobox_));
-    std::string result = text;
-    g_free(text);
-    int space_pos = result.find(' ');
-    if (space_pos)
-      result = result.substr(0, space_pos);
-    return result;
-  }
-
- protected:
-  MessageLoopForUI message_loop_;
-  scoped_ptr<TestingProfile> profile_;
-};
-
-TEST_F(LanguagesPageGtkTest, RemoveAcceptLang) {
-  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en,ja,es");
-  LanguagesPageGtk page(profile_.get());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  GtkTreeIter iter;
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 1);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
-  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(1, page.FirstSelectedRowNum());
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 1);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
-  EXPECT_STREQ("English", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(0, page.FirstSelectedRowNum());
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 0);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
-  EXPECT_STREQ("", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(-1, page.FirstSelectedRowNum());
-}
-
-TEST_F(LanguagesPageGtkTest, RemoveMultipleAcceptLang) {
-  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en,ja,es,fr,it");
-  LanguagesPageGtk page(profile_.get());
-  GtkTreeIter iter;
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 1);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 3);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 4);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
-  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(1, page.FirstSelectedRowNum());
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 1);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 0);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
-  EXPECT_STREQ("", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(-1, page.FirstSelectedRowNum());
-}
-
-TEST_F(LanguagesPageGtkTest, MoveAcceptLang) {
-  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en,ja,es");
-  LanguagesPageGtk page(profile_.get());
-  EXPECT_STREQ("English,Japanese,Spanish", GetDisplayedLangs(page).c_str());
-  GtkTreeIter iter;
-
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
-                                &iter, NULL, 0);
-  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-
-  gtk_button_clicked(GTK_BUTTON(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_STREQ("Japanese,English,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("ja,en,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_STREQ("Japanese,Spanish,English", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("ja,es,en",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(page.move_up_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_STREQ("Japanese,English,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("ja,en,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-
-  gtk_button_clicked(GTK_BUTTON(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_STREQ("English,Japanese,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en,ja,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-}
-
-TEST_F(LanguagesPageGtkTest, AddAcceptLang) {
-  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "");
-  LanguagesPageGtk page(profile_.get());
-  EXPECT_STREQ("", GetDisplayedLangs(page).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-
-  page.OnAddLanguage("en");
-  EXPECT_STREQ("English", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(0, page.FirstSelectedRowNum());
-
-  page.OnAddLanguage("es");
-  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(1, page.FirstSelectedRowNum());
-
-  // Duplicates should be ignored and selection should not be changed.
-  gtk_tree_selection_unselect_all(page.language_order_selection_);
-  page.OnAddLanguage("en");
-  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("en,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
-  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
-  EXPECT_EQ(0, gtk_tree_selection_count_selected_rows(
-      page.language_order_selection_));
-}
-
-TEST_F(LanguagesPageGtkTest, EnableSpellChecking) {
-  profile_->GetPrefs()->SetBoolean(prefs::kEnableSpellCheck, false);
-  LanguagesPageGtk page(profile_.get());
-  EXPECT_EQ(FALSE, gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
-
-  profile_->GetPrefs()->SetBoolean(prefs::kEnableSpellCheck, true);
-  EXPECT_EQ(TRUE, gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
-
-  gtk_button_clicked(GTK_BUTTON(page.enable_spellchecking_checkbox_));
-  EXPECT_EQ(FALSE, gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
-  EXPECT_EQ(false, profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck));
-
-  gtk_button_clicked(GTK_BUTTON(page.enable_spellchecking_checkbox_));
-  EXPECT_EQ(TRUE, gtk_toggle_button_get_active(
-      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
-  EXPECT_EQ(true, profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck));
-}
-
-// TODO(mattm): add EnableAutoSpellChecking test
-
-TEST_F(LanguagesPageGtkTest, DictionaryLanguage) {
-  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "it");
-  profile_->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "es");
-  LanguagesPageGtk page(profile_.get());
-  EXPECT_STREQ("Italian", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("it",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_STREQ("Spanish", GetDisplayedSpellCheckerLang(page).c_str());
-  int spanish_index = gtk_combo_box_get_active(
-        GTK_COMBO_BOX(page.dictionary_language_combobox_));
-
-  profile_->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "fr");
-  EXPECT_STREQ("Italian", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("it",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_STREQ("French", GetDisplayedSpellCheckerLang(page).c_str());
-  int french_index = gtk_combo_box_get_active(
-        GTK_COMBO_BOX(page.dictionary_language_combobox_));
-
-  gtk_combo_box_set_active(
-        GTK_COMBO_BOX(page.dictionary_language_combobox_), spanish_index);
-  EXPECT_STREQ("Italian,Spanish", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("it,es",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_STREQ("Spanish", GetDisplayedSpellCheckerLang(page).c_str());
-
-  gtk_combo_box_set_active(
-        GTK_COMBO_BOX(page.dictionary_language_combobox_), french_index);
-  EXPECT_STREQ("Italian,French", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("it,fr",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_STREQ("French", GetDisplayedSpellCheckerLang(page).c_str());
-
-  gtk_combo_box_set_active(
-        GTK_COMBO_BOX(page.dictionary_language_combobox_),
-        page.dictionary_language_model_->GetIndexFromLocale("it"));
-  EXPECT_STREQ("Italian", GetDisplayedLangs(page).c_str());
-  EXPECT_STREQ("it",
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
-  EXPECT_STREQ("Italian", GetDisplayedSpellCheckerLang(page).c_str());
-}
diff --git a/chrome/browser/gtk/options/managed_prefs_banner_gtk.cc b/chrome/browser/gtk/options/managed_prefs_banner_gtk.cc
deleted file mode 100644
index a402656..0000000
--- a/chrome/browser/gtk/options/managed_prefs_banner_gtk.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h"
-
-#include "app/l10n_util.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Padding within the banner box.
-const int kBannerPadding = 3;
-
-}
-
-ManagedPrefsBannerGtk::ManagedPrefsBannerGtk(PrefService* prefs,
-                                             OptionsPage page)
-    : policy::ManagedPrefsBannerBase(prefs, page),
-      banner_widget_(NULL) {
-  InitWidget();
-  OnUpdateVisibility();
-}
-
-void ManagedPrefsBannerGtk::InitWidget() {
-  banner_widget_ = gtk_frame_new(NULL);
-  GtkWidget* contents = gtk_hbox_new(FALSE, kBannerPadding);
-  gtk_container_set_border_width(GTK_CONTAINER(contents), kBannerPadding);
-  gtk_container_add(GTK_CONTAINER(banner_widget_), contents);
-  GtkWidget* warning_image =
-      gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
-                               GTK_ICON_SIZE_SMALL_TOOLBAR);
-  gtk_box_pack_start(GTK_BOX(contents), warning_image, FALSE, FALSE, 0);
-  std::string info_text(l10n_util::GetStringUTF8(IDS_OPTIONS_MANAGED_PREFS));
-  GtkWidget* info_label = gtk_label_new(info_text.c_str());
-  gtk_box_pack_start(GTK_BOX(contents), info_label, FALSE, FALSE, 0);
-  gtk_widget_show_all(banner_widget_);
-  gtk_widget_set_no_show_all(GTK_WIDGET(banner_widget_), TRUE);
-}
-
-void ManagedPrefsBannerGtk::OnUpdateVisibility() {
-  DCHECK(banner_widget_);
-  if (DetermineVisibility())
-    gtk_widget_show(banner_widget_);
-  else
-    gtk_widget_hide(banner_widget_);
-}
diff --git a/chrome/browser/gtk/options/managed_prefs_banner_gtk.h b/chrome/browser/gtk/options/managed_prefs_banner_gtk.h
deleted file mode 100644
index cd7f9c6..0000000
--- a/chrome/browser/gtk/options/managed_prefs_banner_gtk.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_MANAGED_PREFS_BANNER_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_MANAGED_PREFS_BANNER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/policy/managed_prefs_banner_base.h"
-
-// Constructs and maintains a GTK widget displaying a warning banner. The banner
-// is displayed on the preferences dialog whenever there are options that are
-// not settable by the user due to policy.
-class ManagedPrefsBannerGtk : public policy::ManagedPrefsBannerBase {
- public:
-  ManagedPrefsBannerGtk(PrefService* prefs, OptionsPage page);
-  virtual ~ManagedPrefsBannerGtk() { }
-
-  GtkWidget* banner_widget() { return banner_widget_; }
-
- protected:
-  // Update widget visibility.
-  virtual void OnUpdateVisibility();
-
- private:
-  // Construct the widget.
-  void InitWidget();
-
-  GtkWidget* banner_widget_;
-
-  DISALLOW_COPY_AND_ASSIGN(ManagedPrefsBannerGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_MANAGED_PREFS_BANNER_GTK_H_
diff --git a/chrome/browser/gtk/options/options_layout_gtk.cc b/chrome/browser/gtk/options/options_layout_gtk.cc
deleted file mode 100644
index d0ae714..0000000
--- a/chrome/browser/gtk/options/options_layout_gtk.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/options_layout_gtk.h"
-
-#include "chrome/browser/gtk/gtk_util.h"
-
-// If the height of screen is equal or shorter than this, we will use
-// a more compact option layout.
-const int kCompactScreenHeight = 600;
-
-// Default option layout builder follows GNOME HIG, which uses header and
-// spacing to group options.
-class DefaultOptionsLayoutBuilderGtk : public OptionsLayoutBuilderGtk {
- public:
-  explicit DefaultOptionsLayoutBuilderGtk();
-
-  void AddOptionGroup(const std::string& title, GtkWidget* content,
-                      bool expandable);
-  void AddWidget(GtkWidget* content, bool expandable);
- private:
-  DISALLOW_COPY_AND_ASSIGN(DefaultOptionsLayoutBuilderGtk);
-};
-
-DefaultOptionsLayoutBuilderGtk::DefaultOptionsLayoutBuilderGtk() {
-  page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(page_),
-                                 gtk_util::kContentAreaBorder);
-}
-
-void DefaultOptionsLayoutBuilderGtk::AddOptionGroup(const std::string& title,
-                                                    GtkWidget* content,
-                                                    bool expandable) {
-  GtkWidget* title_label = gtk_util::CreateBoldLabel(title);
-
-  GtkWidget* group = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(group), title_label, FALSE, FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(group), gtk_util::IndentWidget(content));
-
-  AddWidget(group, expandable);
-}
-
-void DefaultOptionsLayoutBuilderGtk::AddWidget(GtkWidget* content,
-                                               bool expandable) {
-  gtk_box_pack_start(GTK_BOX(page_), content, expandable, expandable, 0);
-}
-
-// Compact layout builder uses table to layout label and content horizontally.
-class CompactOptionsLayoutBuilderGtk : public OptionsLayoutBuilderGtk {
- public:
-  explicit CompactOptionsLayoutBuilderGtk();
-
-  void AddOptionGroup(const std::string& title, GtkWidget* content,
-                      bool expandable);
-  void AddWidget(GtkWidget* content, bool expandable);
- private:
-  GtkWidget *table_;
-  guint row_;
-
-  DISALLOW_COPY_AND_ASSIGN(CompactOptionsLayoutBuilderGtk);
-};
-
-CompactOptionsLayoutBuilderGtk::CompactOptionsLayoutBuilderGtk() {
-  row_ = 0;
-  table_ = NULL;
-
-  page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(page_),
-                                 gtk_util::kContentAreaBorder);
-}
-
-void CompactOptionsLayoutBuilderGtk::AddOptionGroup(const std::string& title,
-                                             GtkWidget* content,
-                                             bool expandable) {
-  if (!table_) {
-    // Create a new table to contain option groups
-    table_ = gtk_table_new(0, 2, FALSE);
-    gtk_table_set_col_spacing(GTK_TABLE(table_), 0, gtk_util::kLabelSpacing);
-    gtk_table_set_row_spacings(GTK_TABLE(table_),
-                               gtk_util::kContentAreaSpacing);
-
-    gtk_container_set_border_width(GTK_CONTAINER(table_),
-                                   gtk_util::kContentAreaBorder);
-    gtk_box_pack_start(GTK_BOX(page_), table_, TRUE, TRUE, 0);
-  }
-
-  GtkWidget* title_label = gtk_util::CreateBoldLabel(title);
-
-  gtk_table_resize(GTK_TABLE(table_), row_ + 1, 2);
-  gtk_misc_set_alignment(GTK_MISC(title_label), 1, 0);
-
-  gtk_table_attach(GTK_TABLE(table_), title_label,
-                   0, 1, row_, row_ + 1,
-                   GTK_FILL, GTK_FILL,
-                   0, 0);
-  gtk_table_attach(GTK_TABLE(table_), content,
-                   1, 2, row_, row_ + 1,
-                   expandable ?
-                   GTK_FILL : GtkAttachOptions(GTK_FILL | GTK_EXPAND),
-                   GTK_FILL,
-                   0, 0);
-  row_++;
-}
-
-void CompactOptionsLayoutBuilderGtk::AddWidget(GtkWidget* content,
-                                               bool expandable) {
-  gtk_box_pack_start(GTK_BOX(page_), content, expandable, expandable, 0);
-
-  // Let AddOptionGroup create a new table and append after this widget
-  table_ = NULL;
-}
-
-OptionsLayoutBuilderGtk* OptionsLayoutBuilderGtk::Create() {
-    return new DefaultOptionsLayoutBuilderGtk();
-}
-
-OptionsLayoutBuilderGtk*
-OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout() {
-  gint screen_height = gdk_screen_get_height(gdk_screen_get_default());
-  if (screen_height <= kCompactScreenHeight)
-    return new CompactOptionsLayoutBuilderGtk();
-  else
-    return new DefaultOptionsLayoutBuilderGtk();
-}
diff --git a/chrome/browser/gtk/options/options_layout_gtk.h b/chrome/browser/gtk/options/options_layout_gtk.h
deleted file mode 100644
index 5bf2d3e..0000000
--- a/chrome/browser/gtk/options/options_layout_gtk.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_OPTIONS_LAYOUT_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_OPTIONS_LAYOUT_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <string>
-
-#include "base/basictypes.h"
-
-class OptionsLayoutBuilderGtk {
- public:
-  virtual ~OptionsLayoutBuilderGtk() {}
-
-  GtkWidget* get_page_widget() {
-    return page_;
-  }
-
-  // Adds an option group to the table.  Handles layout and the placing of
-  // separators between groups.  If expandable is true, the content widget will
-  // be allowed to expand and fill any extra space when the dialog is resized.
-  virtual void AddOptionGroup(const std::string& title, GtkWidget* content,
-                              bool expandable) = 0;
-
-  // Adds a widget without title or special layout.  If expandable is true, the
-  // content widget will be allowed to expand and fill any extra space when the
-  // dialog is resized.
-  virtual void AddWidget(GtkWidget* content, bool expandable) = 0;
-
-  // Creates a default option layout builder. The default layout builder
-  // follows the GNOME HIG.
-  static OptionsLayoutBuilderGtk* Create();
-
-  // Creates a compact option layout builder, if the screen is compact.
-  // Otherwise, creates a default one.
-  static OptionsLayoutBuilderGtk* CreateOptionallyCompactLayout();
-
- protected:
-  // The parent widget
-  GtkWidget* page_;
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_OPTIONS_LAYOUT_GTK_H_
diff --git a/chrome/browser/gtk/options/options_window_gtk.cc b/chrome/browser/gtk/options/options_window_gtk.cc
deleted file mode 100644
index c2e997e..0000000
--- a/chrome/browser/gtk/options/options_window_gtk.cc
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/accessibility_events.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/advanced_page_gtk.h"
-#include "chrome/browser/gtk/options/content_page_gtk.h"
-#include "chrome/browser/gtk/options/general_page_gtk.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/options/options_window.h"
-#include "chrome/browser/ui/window_sizer.h"
-#include "chrome/common/pref_names.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/options/internet_page_view.h"
-#include "chrome/browser/chromeos/options/system_page_view.h"
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowGtk
-//
-// The contents of the Options dialog window.
-
-class OptionsWindowGtk {
- public:
-  explicit OptionsWindowGtk(Profile* profile);
-  ~OptionsWindowGtk();
-
-  // Shows the Tab corresponding to the specified OptionsPage.
-  void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group);
-
- private:
-  static void OnSwitchPage(GtkNotebook* notebook, GtkNotebookPage* page,
-                           guint page_num, OptionsWindowGtk* window);
-
-  static void OnWindowDestroy(GtkWidget* widget, OptionsWindowGtk* window);
-
-  // The options dialog.
-  GtkWidget* dialog_;
-
-  // The container of the option pages.
-  GtkWidget* notebook_;
-
-  // The Profile associated with these options.
-  Profile* profile_;
-
-  // The general page.
-  GeneralPageGtk general_page_;
-
-  // The content page.
-  ContentPageGtk content_page_;
-
-  // The advanced (user data) page.
-  AdvancedPageGtk advanced_page_;
-
-  // The last page the user was on when they opened the Options window.
-  IntegerPrefMember last_selected_page_;
-
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(OptionsWindowGtk);
-};
-
-// The singleton options window object.
-static OptionsWindowGtk* options_window = NULL;
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowGtk, public:
-
-OptionsWindowGtk::OptionsWindowGtk(Profile* profile)
-      // Always show preferences for the original profile. Most state when off
-      // the record comes from the original profile, but we explicitly use
-      // the original profile to avoid potential problems.
-    : profile_(profile->GetOriginalProfile()),
-      general_page_(profile_),
-      content_page_(profile_),
-      advanced_page_(profile_) {
-
-  // We don't need to observe changes in this value.
-  last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex,
-                           g_browser_process->local_state(), NULL);
-
-  std::string dialog_name =
-      l10n_util::GetStringFUTF8(
-          IDS_PREFERENCES_DIALOG_TITLE,
-          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      // Prefs window is shared between all browser windows.
-      NULL,
-      // Non-modal.
-      GTK_DIALOG_NO_SEPARATOR,
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
-  // Allow browser windows to go in front of the options dialog in metacity.
-  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  notebook_ = gtk_notebook_new();
-
-#if defined(OS_CHROMEOS)
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      (new chromeos::SystemPageView(profile_))->WrapInGtkWidget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_SYSTEM_TAB_LABEL).c_str()));
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      (new chromeos::InternetPageView(profile_))->WrapInGtkWidget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_INTERNET_TAB_LABEL).c_str()));
-#endif
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      general_page_.get_page_widget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_GENERAL_TAB_LABEL).c_str()));
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      content_page_.get_page_widget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_CONTENT_TAB_LABEL).c_str()));
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      advanced_page_.get_page_widget(),
-      gtk_label_new(
-          l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_TAB_LABEL).c_str()));
-
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
-
-  DCHECK_EQ(
-      gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), OPTIONS_PAGE_COUNT);
-
-  // Show the content so that we can compute full dialog size, both
-  // for centering and because we want to show the notebook before
-  // connecting switch-page signal, otherwise we'll immediately get a
-  // signal switching to page 0 and overwrite our last_selected_page_
-  // value.
-  gtk_widget_show_all(gtk_bin_get_child(GTK_BIN(dialog_)));
-
-  if (Browser* b = BrowserList::GetLastActive()) {
-    gtk_util::CenterOverWindow(GTK_WINDOW(dialog_),
-                               b->window()->GetNativeHandle());
-  }
-
-  // Now that we're centered over the browser, we add our dialog to its own
-  // window group. We don't do anything with the response and we don't want the
-  // options window's modal dialogs to be associated with the main browser
-  // window because gtk grabs work on a per window group basis.
-  gtk_window_group_add_window(gtk_window_group_new(), GTK_WINDOW(dialog_));
-  g_object_unref(gtk_window_get_group(GTK_WINDOW(dialog_)));
-
-  g_signal_connect(notebook_, "switch-page", G_CALLBACK(OnSwitchPage), this);
-
-  // We only have one button and don't do any special handling, so just hook it
-  // directly to gtk_widget_destroy.
-  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
-
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
-
-  gtk_widget_show(dialog_);
-}
-
-OptionsWindowGtk::~OptionsWindowGtk() {
-}
-
-void OptionsWindowGtk::ShowOptionsPage(OptionsPage page,
-                                       OptionsGroup highlight_group) {
-  if (Browser* b = BrowserList::GetLastActive()) {
-    gtk_util::CenterOverWindow(GTK_WINDOW(dialog_),
-                               b->window()->GetNativeHandle());
-  }
-
-  // Bring options window to front if it already existed and isn't already
-  // in front
-  gtk_window_present_with_time(GTK_WINDOW(dialog_),
-                               gtk_get_current_event_time());
-
-  if (page == OPTIONS_PAGE_DEFAULT) {
-    // Remember the last visited page from local state.
-    page = static_cast<OptionsPage>(last_selected_page_.GetValue());
-    if (page == OPTIONS_PAGE_DEFAULT)
-      page = OPTIONS_PAGE_GENERAL;
-  }
-  // If the page number is out of bounds, reset to the first tab.
-  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
-    page = OPTIONS_PAGE_GENERAL;
-
-  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page);
-
-  // TODO(mattm): set highlight_group
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// OptionsWindowGtk, private:
-
-// static
-void OptionsWindowGtk::OnSwitchPage(GtkNotebook* notebook,
-                                    GtkNotebookPage* page,
-                                    guint page_num,
-                                    OptionsWindowGtk* window) {
-  int index = page_num;
-  DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT);
-  window->last_selected_page_.SetValue(index);
-}
-
-// static
-void OptionsWindowGtk::OnWindowDestroy(GtkWidget* widget,
-                                       OptionsWindowGtk* window) {
-  options_window = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Factory/finder method:
-
-#if !defined(OS_CHROMEOS)
-// ShowOptionsWindow for non ChromeOS build. For ChromeOS build, see
-// chrome/browser/chromeos/options/options_window_view.h
-void ShowOptionsWindow(OptionsPage page,
-                       OptionsGroup highlight_group,
-                       Profile* profile) {
-  DCHECK(profile);
-
-  // If there's already an existing options window, activate it and switch to
-  // the specified page.
-  if (!options_window) {
-    // Creating and initializing a bunch of controls generates a bunch of
-    // spurious events as control values change. Temporarily suppress
-    // accessibility events until the window is created.
-    profile->PauseAccessibilityEvents();
-
-    // Create the options window.
-    options_window = new OptionsWindowGtk(profile);
-
-    // Resume accessibility events.
-    profile->ResumeAccessibilityEvents();
-  }
-  options_window->ShowOptionsPage(page, highlight_group);
-}
-#endif  // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc b/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc
deleted file mode 100644
index 4146d9f..0000000
--- a/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/passwords_exceptions_page_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/stl_util-inl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "net/base/net_util.h"
-
-namespace {
-
-// Column ids for |exception_list_store_|.
-enum {
-  COL_SITE,
-  COL_COUNT,
-};
-
-}  // anonymous namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsExceptionsPageGtk, public:
-
-PasswordsExceptionsPageGtk::PasswordsExceptionsPageGtk(Profile* profile)
-    : populater(this), profile_(profile) {
-
-  remove_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON).c_str());
-  gtk_widget_set_sensitive(remove_button_, FALSE);
-  g_signal_connect(remove_button_, "clicked",
-                   G_CALLBACK(OnRemoveButtonClickedThunk), this);
-  remove_all_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
-          IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON).c_str());
-  gtk_widget_set_sensitive(remove_all_button_, FALSE);
-  g_signal_connect(remove_all_button_, "clicked",
-                   G_CALLBACK(OnRemoveAllButtonClickedThunk), this);
-
-  GtkWidget* buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(buttons), remove_button_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(buttons), remove_all_button_, FALSE, FALSE, 0);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-
-  // Sets exception_tree_ among other things.
-  InitExceptionTree();
-  gtk_container_add(GTK_CONTAINER(scroll_window), exception_tree_);
-
-  page_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(page_),
-                                 gtk_util::kContentAreaBorder);
-  gtk_box_pack_end(GTK_BOX(page_), buttons, FALSE, FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(page_), scroll_window, TRUE, TRUE, 0);
-}
-
-PasswordsExceptionsPageGtk::~PasswordsExceptionsPageGtk() {
-  STLDeleteElements(&exception_list_);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsExceptionsPageGtk, private:
-
-void PasswordsExceptionsPageGtk::InitExceptionTree() {
-  exception_list_store_ = gtk_list_store_new(COL_COUNT, G_TYPE_STRING);
-  exception_list_sort_ = gtk_tree_model_sort_new_with_model(
-      GTK_TREE_MODEL(exception_list_store_));
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(exception_list_sort_),
-                                  COL_SITE, CompareSite, this, NULL);
-  exception_tree_ = gtk_tree_view_new_with_model(exception_list_sort_);
-  g_object_unref(exception_list_store_);
-  g_object_unref(exception_list_sort_);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(exception_tree_), TRUE);
-
-  exception_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(exception_tree_));
-  gtk_tree_selection_set_mode(exception_selection_,
-                              GTK_SELECTION_SINGLE);
-  g_signal_connect(exception_selection_, "changed",
-                   G_CALLBACK(OnExceptionSelectionChangedThunk), this);
-
-  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_SITE,
-      NULL);
-  gtk_tree_view_column_set_sort_column_id(column, COL_SITE);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(exception_tree_), column);
-
-  populater.populate();
-}
-
-PasswordStore* PasswordsExceptionsPageGtk::GetPasswordStore() {
-    return profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
-}
-
-void PasswordsExceptionsPageGtk::SetExceptionList(
-    const std::vector<webkit_glue::PasswordForm*>& result) {
-  std::string languages =
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
-  gtk_list_store_clear(exception_list_store_);
-  STLDeleteElements(&exception_list_);
-  exception_list_ = result;
-  for (size_t i = 0; i < result.size(); ++i) {
-    GtkTreeIter iter;
-    gtk_list_store_insert_with_values(exception_list_store_, &iter, (gint) i,
-        COL_SITE,
-        UTF16ToUTF8(net::FormatUrl(result[i]->origin, languages)).c_str(), -1);
-  }
-  gtk_widget_set_sensitive(remove_all_button_, result.size() > 0);
-}
-
-void PasswordsExceptionsPageGtk::OnRemoveButtonClicked(GtkWidget* widget) {
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(exception_selection_,
-                                       NULL, &iter)) {
-    NOTREACHED();
-    return;
-  }
-
-  GtkTreePath* path = gtk_tree_model_get_path(
-      GTK_TREE_MODEL(exception_list_sort_), &iter);
-  gint index = gtk_tree::GetTreeSortChildRowNumForPath(
-      exception_list_sort_, path);
-  gtk_tree_path_free(path);
-
-  GtkTreeIter child_iter;
-  gtk_tree_model_sort_convert_iter_to_child_iter(
-      GTK_TREE_MODEL_SORT(exception_list_sort_), &child_iter, &iter);
-
-  // Remove from GTK list, DB, and vector.
-  gtk_list_store_remove(exception_list_store_, &child_iter);
-  GetPasswordStore()->RemoveLogin(*exception_list_[index]);
-  delete exception_list_[index];
-  exception_list_.erase(exception_list_.begin() + index);
-
-  gtk_widget_set_sensitive(remove_all_button_, exception_list_.size() > 0);
-}
-
-void PasswordsExceptionsPageGtk::OnRemoveAllButtonClicked(GtkWidget* widget) {
-  // Remove from GTK list, DB, and vector.
-  PasswordStore* store = GetPasswordStore();
-  gtk_list_store_clear(exception_list_store_);
-  for (size_t i = 0; i < exception_list_.size(); ++i)
-    store->RemoveLogin(*exception_list_[i]);
-  STLDeleteElements(&exception_list_);
-  gtk_widget_set_sensitive(remove_all_button_, FALSE);
-}
-
-void PasswordsExceptionsPageGtk::OnExceptionSelectionChanged(
-    GtkTreeSelection* selection) {
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
-    gtk_widget_set_sensitive(remove_button_, FALSE);
-    return;
-  }
-  gtk_widget_set_sensitive(remove_button_, TRUE);
-}
-
-// static
-gint PasswordsExceptionsPageGtk::CompareSite(GtkTreeModel* model,
-                                   GtkTreeIter* a, GtkTreeIter* b,
-                                   gpointer window) {
-  int row1 = gtk_tree::GetRowNumForIter(model, a);
-  int row2 = gtk_tree::GetRowNumForIter(model, b);
-  PasswordsExceptionsPageGtk* page =
-      reinterpret_cast<PasswordsExceptionsPageGtk*>(window);
-  return page->exception_list_[row1]->origin.spec().compare(
-         page->exception_list_[row2]->origin.spec());
-}
-
-void PasswordsExceptionsPageGtk::ExceptionListPopulater::populate() {
-  DCHECK(!pending_login_query_);
-  PasswordStore* store = page_->GetPasswordStore();
-  if (store != NULL)
-    pending_login_query_ = store->GetBlacklistLogins(this);
-  else
-    LOG(ERROR) << "No password store! Cannot display exceptions.";
-}
-
-void
-PasswordsExceptionsPageGtk::ExceptionListPopulater::OnPasswordStoreRequestDone(
-    int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
-  DCHECK_EQ(pending_login_query_, handle);
-  pending_login_query_ = 0;
-  page_->SetExceptionList(result);
-}
diff --git a/chrome/browser/gtk/options/passwords_exceptions_page_gtk.h b/chrome/browser/gtk/options/passwords_exceptions_page_gtk.h
deleted file mode 100644
index 0179501..0000000
--- a/chrome/browser/gtk/options/passwords_exceptions_page_gtk.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/password_manager/password_store.h"
-
-class Profile;
-
-// A page in the show saved passwords dialog that lists what sites we never
-// show passwords for, with controls for the user to add/remove sites from that
-// list.
-class PasswordsExceptionsPageGtk {
- public:
-  explicit PasswordsExceptionsPageGtk(Profile* profile);
-  virtual ~PasswordsExceptionsPageGtk();
-
-  GtkWidget* get_page_widget() const { return page_; }
-
- private:
-  // Initialize the exception tree widget, setting the member variables.
-  void InitExceptionTree();
-
-  // The password store associated with the currently active profile.
-  PasswordStore* GetPasswordStore();
-
-  // Sets the exception list contents to the given data. We take ownership of
-  // the PasswordForms in the vector.
-  void SetExceptionList(const std::vector<webkit_glue::PasswordForm*>& result);
-
-  CHROMEGTK_CALLBACK_0(PasswordsExceptionsPageGtk, void, OnRemoveButtonClicked);
-  CHROMEGTK_CALLBACK_0(PasswordsExceptionsPageGtk, void,
-                       OnRemoveAllButtonClicked);
-
-  CHROMEG_CALLBACK_0(PasswordsExceptionsPageGtk, void,
-                     OnExceptionSelectionChanged, GtkTreeSelection*);
-
-  // Sorting function.
-  static gint CompareSite(GtkTreeModel* model,
-                          GtkTreeIter* a, GtkTreeIter* b,
-                          gpointer window);
-
-  // A short class to mediate requests to the password store.
-  class ExceptionListPopulater : public PasswordStoreConsumer {
-   public:
-    explicit ExceptionListPopulater(PasswordsExceptionsPageGtk* page)
-        : page_(page),
-          pending_login_query_(0) {
-    }
-
-    // Send a query to the password store to populate an
-    // PasswordsExceptionsPageGtk.
-    void populate();
-
-    // PasswordStoreConsumer implementation.
-    // Send the password store's reply back to the PasswordsExceptionsPageGtk.
-    virtual void OnPasswordStoreRequestDone(
-        int handle, const std::vector<webkit_glue::PasswordForm*>& result);
-
-   private:
-    PasswordsExceptionsPageGtk* page_;
-    int pending_login_query_;
-  };
-
-  // Password store consumer for populating the exception list.
-  ExceptionListPopulater populater;
-
-  // Widgets for the buttons.
-  GtkWidget* remove_button_;
-  GtkWidget* remove_all_button_;
-
-  // Widgets for the exception table.
-  GtkWidget* exception_tree_;
-  GtkListStore* exception_list_store_;
-  GtkTreeModel* exception_list_sort_;
-  GtkTreeSelection* exception_selection_;
-
-  // The parent GtkHBox widget.
-  GtkWidget* page_;
-
-  Profile* profile_;
-  std::vector<webkit_glue::PasswordForm*> exception_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(PasswordsExceptionsPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/passwords_exceptions_window_gtk.cc b/chrome/browser/gtk/options/passwords_exceptions_window_gtk.cc
deleted file mode 100644
index d516f58..0000000
--- a/chrome/browser/gtk/options/passwords_exceptions_window_gtk.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/passwords_exceptions_window_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/passwords_exceptions_page_gtk.h"
-#include "chrome/browser/gtk/options/passwords_page_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/options/options_window.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsExceptionsWindowGtk
-//
-// The contents of the Passwords and Exceptions dialog window.
-
-class PasswordsExceptionsWindowGtk {
- public:
-  explicit PasswordsExceptionsWindowGtk(Profile* profile);
-  ~PasswordsExceptionsWindowGtk();
-
-  void Show();
-
- private:
-  static void OnWindowDestroy(GtkWidget* widget,
-                              PasswordsExceptionsWindowGtk* window);
-
-  // The passwords and exceptions dialog.
-  GtkWidget *dialog_;
-
-  // The container of the password and exception pages.
-  GtkWidget *notebook_;
-
-  // The Profile associated with these passwords and exceptions.
-  Profile* profile_;
-
-  // The passwords page.
-  PasswordsPageGtk passwords_page_;
-
-  // The exceptions page.
-  PasswordsExceptionsPageGtk exceptions_page_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(PasswordsExceptionsWindowGtk);
-};
-
-// The singleton passwords and exceptions window object.
-static PasswordsExceptionsWindowGtk* passwords_exceptions_window = NULL;
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsExceptionsWindowGtk, public:
-
-PasswordsExceptionsWindowGtk::PasswordsExceptionsWindowGtk(Profile* profile)
-    : profile_(profile),
-      passwords_page_(profile_),
-      exceptions_page_(profile_) {
-  std::string dialog_name = l10n_util::GetStringUTF8(
-      IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      // Passwords and exceptions window is shared between all browser windows.
-      NULL,
-      // Non-modal.
-      GTK_DIALOG_NO_SEPARATOR,
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  notebook_ = gtk_notebook_new();
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      passwords_page_.get_page_widget(),
-      gtk_label_new(l10n_util::GetStringUTF8(
-              IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE).c_str()));
-
-  gtk_notebook_append_page(
-      GTK_NOTEBOOK(notebook_),
-      exceptions_page_.get_page_widget(),
-      gtk_label_new(l10n_util::GetStringUTF8(
-              IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE).c_str()));
-
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
-
-  // We only have one button and don't do any special handling, so just hook it
-  // directly to gtk_widget_destroy.
-  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
-
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
-
-  gtk_util::ShowDialogWithLocalizedSize(dialog_,
-      IDS_PASSWORDS_DIALOG_WIDTH_CHARS,
-      IDS_PASSWORDS_DIALOG_HEIGHT_LINES,
-      true);
-}
-
-PasswordsExceptionsWindowGtk::~PasswordsExceptionsWindowGtk() {
-}
-
-void PasswordsExceptionsWindowGtk::Show() {
-  // Bring options window to front if it already existed and isn't already
-  // in front
-  gtk_util::PresentWindow(dialog_, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsExceptionsWindowGtk, private:
-
-// static
-void PasswordsExceptionsWindowGtk::OnWindowDestroy(GtkWidget* widget,
-    PasswordsExceptionsWindowGtk* window) {
-  passwords_exceptions_window = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Factory/finder method:
-
-void ShowPasswordsExceptionsWindow(Profile* profile) {
-  DCHECK(profile);
-  // If there's already an existing passwords and exceptions window, use it.
-  if (!passwords_exceptions_window) {
-    passwords_exceptions_window = new PasswordsExceptionsWindowGtk(profile);
-  }
-  passwords_exceptions_window->Show();
-}
diff --git a/chrome/browser/gtk/options/passwords_exceptions_window_gtk.h b/chrome/browser/gtk/options/passwords_exceptions_window_gtk.h
deleted file mode 100644
index 1e5be39..0000000
--- a/chrome/browser/gtk/options/passwords_exceptions_window_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_GTK_H_
-#pragma once
-
-class Profile;
-
-void ShowPasswordsExceptionsWindow(Profile* profile);
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_GTK_H_
diff --git a/chrome/browser/gtk/options/passwords_page_gtk.cc b/chrome/browser/gtk/options/passwords_page_gtk.cc
deleted file mode 100644
index 7a58f15..0000000
--- a/chrome/browser/gtk/options/passwords_page_gtk.cc
+++ /dev/null
@@ -1,367 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/passwords_page_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "base/stl_util-inl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "net/base/net_util.h"
-
-namespace {
-
-// Initial width of the first column.
-const int kSiteColumnInitialSize = 265;
-
-// Column ids for |password_list_store_|.
-enum {
-  COL_SITE,
-  COL_USERNAME,
-  COL_COUNT,
-};
-
-}  // anonymous namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsPageGtk, public:
-
-PasswordsPageGtk::PasswordsPageGtk(Profile* profile)
-    : populater(this), password_showing_(false), profile_(profile) {
-  allow_show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords,
-                             profile->GetPrefs(),
-                             this);
-
-  remove_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON).c_str());
-  gtk_widget_set_sensitive(remove_button_, FALSE);
-  g_signal_connect(remove_button_, "clicked",
-                   G_CALLBACK(OnRemoveButtonClickedThunk), this);
-  remove_all_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
-          IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON).c_str());
-  gtk_widget_set_sensitive(remove_all_button_, FALSE);
-  g_signal_connect(remove_all_button_, "clicked",
-                   G_CALLBACK(OnRemoveAllButtonClickedThunk), this);
-
-  // We start with the "hide password" text but change it in the realize event.
-  show_password_button_ = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON).c_str());
-  gtk_widget_set_no_show_all(show_password_button_, true);
-  gtk_widget_set_sensitive(show_password_button_, FALSE);
-  g_signal_connect(show_password_button_, "clicked",
-                   G_CALLBACK(OnShowPasswordButtonClickedThunk), this);
-  g_signal_connect(show_password_button_, "realize",
-                   G_CALLBACK(OnShowPasswordButtonRealizedThunk), this);
-
-  password_ = gtk_label_new("");
-  gtk_label_set_selectable(GTK_LABEL(password_), TRUE);
-  gtk_widget_set_no_show_all(password_, true);
-
-  GtkWidget* buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(buttons), remove_button_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(buttons), remove_all_button_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(buttons), show_password_button_, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(buttons), password_, FALSE, FALSE, 0);
-
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-
-  // Sets password_tree_ among other things.
-  InitPasswordTree();
-  gtk_container_add(GTK_CONTAINER(scroll_window), password_tree_);
-
-  page_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_set_border_width(GTK_CONTAINER(page_),
-                                 gtk_util::kContentAreaBorder);
-  gtk_box_pack_end(GTK_BOX(page_), buttons, FALSE, FALSE, 0);
-  gtk_box_pack_end(GTK_BOX(page_), scroll_window, TRUE, TRUE, 0);
-
-  // Initialize UI state based on current preference values.
-  OnPrefChanged(prefs::kPasswordManagerAllowShowPasswords);
-}
-
-PasswordsPageGtk::~PasswordsPageGtk() {
-  STLDeleteElements(&password_list_);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PasswordsPageGtk, private:
-
-void PasswordsPageGtk::InitPasswordTree() {
-  password_list_store_ = gtk_list_store_new(COL_COUNT,
-                                            G_TYPE_STRING,
-                                            G_TYPE_STRING);
-  password_list_sort_ = gtk_tree_model_sort_new_with_model(
-      GTK_TREE_MODEL(password_list_store_));
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(password_list_sort_),
-                                  COL_SITE, CompareSite, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(password_list_sort_),
-                                  COL_USERNAME, CompareUsername, this, NULL);
-  password_tree_ = gtk_tree_view_new_with_model(password_list_sort_);
-  g_object_unref(password_list_store_);
-  g_object_unref(password_list_sort_);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(password_tree_), TRUE);
-
-  password_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(password_tree_));
-  gtk_tree_selection_set_mode(password_selection_,
-                              GTK_SELECTION_SINGLE);
-  g_signal_connect(password_selection_, "changed",
-                   G_CALLBACK(OnPasswordSelectionChangedThunk), this);
-
-  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_SITE,
-      NULL);
-  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-  gtk_tree_view_column_set_resizable(column, TRUE);
-  gtk_tree_view_column_set_fixed_width(column, kSiteColumnInitialSize);
-  gtk_tree_view_column_set_sort_column_id(column, COL_SITE);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(password_tree_), column);
-
-  column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_USERNAME,
-      NULL);
-  gtk_tree_view_column_set_sort_column_id(column, COL_USERNAME);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(password_tree_), column);
-  populater.populate();
-}
-
-PasswordStore* PasswordsPageGtk::GetPasswordStore() {
-    return profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
-}
-
-void PasswordsPageGtk::SetPasswordList(
-    const std::vector<webkit_glue::PasswordForm*>& result) {
-  std::string languages =
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
-  gtk_list_store_clear(password_list_store_);
-  STLDeleteElements(&password_list_);
-  password_list_ = result;
-  for (size_t i = 0; i < result.size(); ++i) {
-    GtkTreeIter iter;
-    gtk_list_store_insert_with_values(password_list_store_, &iter, (gint) i,
-        COL_SITE,
-        UTF16ToUTF8(net::FormatUrl(result[i]->origin, languages)).c_str(),
-        COL_USERNAME, UTF16ToUTF8(result[i]->username_value).c_str(), -1);
-  }
-  gtk_widget_set_sensitive(remove_all_button_, result.size() > 0);
-}
-
-void PasswordsPageGtk::HidePassword() {
-  password_showing_ = false;
-  gtk_label_set_text(GTK_LABEL(password_), "");
-  gtk_button_set_label(GTK_BUTTON(show_password_button_),
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON).c_str());
-}
-
-void PasswordsPageGtk::Observe(NotificationType type,
-                               const NotificationSource& source,
-                               const NotificationDetails& details) {
-  DCHECK_EQ(NotificationType::PREF_CHANGED, type.value);
-  const std::string* pref_name = Details<std::string>(details).ptr();
-  OnPrefChanged(*pref_name);
-}
-
-void PasswordsPageGtk::OnPrefChanged(const std::string& pref_name) {
-  if (pref_name == prefs::kPasswordManagerAllowShowPasswords) {
-    if (allow_show_passwords_.GetValue()) {
-      gtk_widget_show(show_password_button_);
-      gtk_widget_show(password_);
-    } else {
-      HidePassword();
-      gtk_widget_hide(show_password_button_);
-      gtk_widget_hide(password_);
-    }
-  } else {
-    NOTREACHED();
-  }
-}
-
-void PasswordsPageGtk::OnRemoveButtonClicked(GtkWidget* widget) {
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(password_selection_,
-                                       NULL, &iter)) {
-    NOTREACHED();
-    return;
-  }
-
-  GtkTreePath* path = gtk_tree_model_get_path(
-      GTK_TREE_MODEL(password_list_sort_), &iter);
-  gint index = gtk_tree::GetTreeSortChildRowNumForPath(
-      password_list_sort_, path);
-  gtk_tree_path_free(path);
-
-  GtkTreeIter child_iter;
-  gtk_tree_model_sort_convert_iter_to_child_iter(
-      GTK_TREE_MODEL_SORT(password_list_sort_), &child_iter, &iter);
-
-  // Remove from GTK list, DB, and vector.
-  gtk_list_store_remove(password_list_store_, &child_iter);
-  GetPasswordStore()->RemoveLogin(*password_list_[index]);
-  delete password_list_[index];
-  password_list_.erase(password_list_.begin() + index);
-
-  gtk_widget_set_sensitive(remove_all_button_, password_list_.size() > 0);
-}
-
-void PasswordsPageGtk::OnRemoveAllButtonClicked(GtkWidget* widget) {
-  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(page_));
-  GtkWidget* confirm = gtk_message_dialog_new(
-      window,
-      static_cast<GtkDialogFlags>(
-          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
-      GTK_MESSAGE_QUESTION,
-      GTK_BUTTONS_YES_NO,
-      "%s",
-      l10n_util::GetStringUTF8(
-          IDS_PASSWORDS_PAGE_VIEW_TEXT_DELETE_ALL_PASSWORDS).c_str());
-  gtk_util::ApplyMessageDialogQuirks(confirm);
-  gtk_window_set_title(GTK_WINDOW(confirm), l10n_util::GetStringUTF8(
-          IDS_PASSWORDS_PAGE_VIEW_CAPTION_DELETE_ALL_PASSWORDS).c_str());
-  g_signal_connect(confirm, "response",
-                   G_CALLBACK(OnRemoveAllConfirmResponseThunk), this);
-  gtk_widget_show_all(confirm);
-}
-
-void PasswordsPageGtk::OnRemoveAllConfirmResponse(GtkWidget* confirm,
-                                                  gint response) {
-  bool confirmed = false;
-  switch (response) {
-    case GTK_RESPONSE_YES:
-      confirmed = true;
-      break;
-    default:
-      break;
-  }
-  gtk_widget_destroy(confirm);
-  if (!confirmed)
-    return;
-
-  // Remove from GTK list, DB, and vector.
-  PasswordStore* store = GetPasswordStore();
-  gtk_list_store_clear(password_list_store_);
-  for (size_t i = 0; i < password_list_.size(); ++i)
-    store->RemoveLogin(*password_list_[i]);
-  STLDeleteElements(&password_list_);
-  gtk_widget_set_sensitive(remove_all_button_, FALSE);
-}
-
-void PasswordsPageGtk::OnShowPasswordButtonClicked(GtkWidget* widget) {
-  if (password_showing_ || !allow_show_passwords_.GetValue()) {
-    // Hide the password.
-    HidePassword();
-    return;
-  }
-  // Show the password.
-  password_showing_ = true;
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(password_selection_,
-                                       NULL, &iter)) {
-    NOTREACHED();
-    return;
-  }
-  GtkTreePath* path = gtk_tree_model_get_path(
-      GTK_TREE_MODEL(password_list_sort_), &iter);
-  gint index = gtk_tree::GetTreeSortChildRowNumForPath(
-      password_list_sort_, path);
-  gtk_tree_path_free(path);
-  std::string pass = UTF16ToUTF8(password_list_[index]->password_value);
-  gtk_label_set_text(GTK_LABEL(password_), pass.c_str());
-  gtk_button_set_label(GTK_BUTTON(show_password_button_),
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON).c_str());
-}
-
-void PasswordsPageGtk::OnShowPasswordButtonRealized(GtkWidget* widget) {
-  // We have just realized the "show password" button, so we can now accurately
-  // find out how big it needs to be in order to accomodate both the "show" and
-  // "hide" labels. (This requires font information to work correctly.) The
-  // button starts with the "hide" label so we only have to change it once.
-  GtkRequisition hide_size, show_size;
-  // Get the size request of the button with the "hide password" text.
-  gtk_widget_size_request(show_password_button_, &hide_size);
-  gtk_button_set_label(GTK_BUTTON(show_password_button_),
-      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON).c_str());
-  // Get the size request of the button with the "show password" text.
-  gtk_widget_size_request(show_password_button_, &show_size);
-  // Determine the maximum width and height.
-  if (hide_size.width > show_size.width)
-    show_size.width = hide_size.width;
-  if (hide_size.height > show_size.height)
-    show_size.height = hide_size.height;
-  // Force the button to be large enough for both labels.
-  gtk_widget_set_size_request(show_password_button_, show_size.width,
-                              show_size.height);
-}
-
-void PasswordsPageGtk::OnPasswordSelectionChanged(GtkTreeSelection* selection) {
-  // No matter how the selection changed, we want to hide the old password.
-  HidePassword();
-
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
-    gtk_widget_set_sensitive(show_password_button_, FALSE);
-    gtk_widget_set_sensitive(remove_button_, FALSE);
-    return;
-  }
-  gtk_widget_set_sensitive(show_password_button_, TRUE);
-  gtk_widget_set_sensitive(remove_button_, TRUE);
-}
-
-// static
-gint PasswordsPageGtk::CompareSite(GtkTreeModel* model,
-                                   GtkTreeIter* a, GtkTreeIter* b,
-                                   gpointer window) {
-  int row1 = gtk_tree::GetRowNumForIter(model, a);
-  int row2 = gtk_tree::GetRowNumForIter(model, b);
-  PasswordsPageGtk* page = reinterpret_cast<PasswordsPageGtk*>(window);
-  return page->password_list_[row1]->origin.spec().compare(
-         page->password_list_[row2]->origin.spec());
-}
-
-// static
-gint PasswordsPageGtk::CompareUsername(GtkTreeModel* model,
-                                       GtkTreeIter* a, GtkTreeIter* b,
-                                       gpointer window) {
-  int row1 = gtk_tree::GetRowNumForIter(model, a);
-  int row2 = gtk_tree::GetRowNumForIter(model, b);
-  PasswordsPageGtk* page = reinterpret_cast<PasswordsPageGtk*>(window);
-  return page->password_list_[row1]->username_value.compare(
-         page->password_list_[row2]->username_value);
-}
-
-void PasswordsPageGtk::PasswordListPopulater::populate() {
-  DCHECK(!pending_login_query_);
-  PasswordStore* store = page_->GetPasswordStore();
-  if (store != NULL)
-    pending_login_query_ = store->GetAutofillableLogins(this);
-  else
-    LOG(ERROR) << "No password store! Cannot display passwords.";
-}
-
-void PasswordsPageGtk::PasswordListPopulater::OnPasswordStoreRequestDone(
-    int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
-  DCHECK_EQ(pending_login_query_, handle);
-  pending_login_query_ = 0;
-  page_->SetPasswordList(result);
-}
diff --git a/chrome/browser/gtk/options/passwords_page_gtk.h b/chrome/browser/gtk/options/passwords_page_gtk.h
deleted file mode 100644
index d2f9ddf..0000000
--- a/chrome/browser/gtk/options/passwords_page_gtk.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_PAGE_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_PAGE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/password_manager/password_store.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/common/notification_observer.h"
-
-class Profile;
-
-class PasswordsPageGtk : public NotificationObserver {
- public:
-  explicit PasswordsPageGtk(Profile* profile);
-  virtual ~PasswordsPageGtk();
-
-  GtkWidget* get_page_widget() const { return page_; }
-
- private:
-  // Initialize the password tree widget, setting the member variables.
-  void InitPasswordTree();
-
-  // The password store associated with the currently active profile.
-  PasswordStore* GetPasswordStore();
-
-  // Sets the password list contents to the given data. We take ownership of
-  // the PasswordForms in the vector.
-  void SetPasswordList(const std::vector<webkit_glue::PasswordForm*>& result);
-
-  // Helper that hides the password.
-  void HidePassword();
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Handles changes to the observed preferences and updates the UI.
-  void OnPrefChanged(const std::string& pref_name);
-
-  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnRemoveButtonClicked);
-  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnRemoveAllButtonClicked);
-  CHROMEGTK_CALLBACK_1(PasswordsPageGtk, void, OnRemoveAllConfirmResponse, int);
-  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnShowPasswordButtonClicked);
-  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnShowPasswordButtonRealized);
-
-  CHROMEG_CALLBACK_0(PasswordsPageGtk, void, OnPasswordSelectionChanged,
-                     GtkTreeSelection*);
-
-  // Sorting functions.
-  static gint CompareSite(GtkTreeModel* model,
-                          GtkTreeIter* a, GtkTreeIter* b,
-                          gpointer window);
-  static gint CompareUsername(GtkTreeModel* model,
-                              GtkTreeIter* a, GtkTreeIter* b,
-                              gpointer window);
-
-  // A short class to mediate requests to the password store.
-  class PasswordListPopulater : public PasswordStoreConsumer {
-   public:
-    explicit PasswordListPopulater(PasswordsPageGtk* page)
-        : page_(page),
-          pending_login_query_(0) {
-    }
-
-    // Send a query to the password store to populate a PasswordsPageGtk.
-    void populate();
-
-    // Send the password store's reply back to the PasswordsPageGtk.
-    virtual void OnPasswordStoreRequestDone(
-        int handle, const std::vector<webkit_glue::PasswordForm*>& result);
-
-   private:
-    PasswordsPageGtk* page_;
-    int pending_login_query_;
-  };
-
-  // Password store consumer for populating the password list.
-  PasswordListPopulater populater;
-
-  // Widgets for the buttons.
-  GtkWidget* remove_button_;
-  GtkWidget* remove_all_button_;
-  GtkWidget* show_password_button_;
-
-  // Widget for the shown password
-  GtkWidget* password_;
-  bool password_showing_;
-
-  // Widgets for the password table.
-  GtkWidget* password_tree_;
-  GtkListStore* password_list_store_;
-  GtkTreeModel* password_list_sort_;
-  GtkTreeSelection* password_selection_;
-
-  // The parent GtkHBox widget and GtkWindow window.
-  GtkWidget* page_;
-
-  Profile* profile_;
-  BooleanPrefMember allow_show_passwords_;
-  std::vector<webkit_glue::PasswordForm*> password_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(PasswordsPageGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_PASSWORDS_PAGE_GTK_H_
diff --git a/chrome/browser/gtk/options/simple_content_exceptions_window.cc b/chrome/browser/gtk/options/simple_content_exceptions_window.cc
deleted file mode 100644
index 58676f3..0000000
--- a/chrome/browser/gtk/options/simple_content_exceptions_window.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/options/simple_content_exceptions_window.h"
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "gfx/gtk_util.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-namespace {
-
-// Singleton for exception window.
-SimpleContentExceptionsWindow* instance = NULL;
-
-enum {
-  COL_ACTION = gtk_tree::TableAdapter::COL_LAST_ID,
-  COL_COUNT
-};
-
-}  // namespace
-
-// static
-void SimpleContentExceptionsWindow::ShowExceptionsWindow(
-    GtkWindow* parent, RemoveRowsTableModel* model, int title_message_id) {
-  DCHECK(model);
-  scoped_ptr<RemoveRowsTableModel> owned_model(model);
-
-  if (!instance) {
-    instance = new SimpleContentExceptionsWindow(
-        parent, owned_model.release(), title_message_id);
-  } else {
-    gtk_util::PresentWindow(instance->dialog_, 0);
-  }
-}
-
-SimpleContentExceptionsWindow::SimpleContentExceptionsWindow(
-    GtkWindow* parent,
-    RemoveRowsTableModel* model,
-    int title_message_id)
-      : ignore_selection_changes_(false) {
-  // Build the model adapters that translate views and TableModels into
-  // something GTK can use.
-  list_store_ = gtk_list_store_new(COL_COUNT,
-                                   G_TYPE_STRING,
-                                   G_TYPE_BOOLEAN,
-                                   G_TYPE_BOOLEAN,
-                                   G_TYPE_INT,
-                                   G_TYPE_INT,
-                                   G_TYPE_BOOLEAN,
-                                   G_TYPE_STRING);
-  treeview_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_));
-  g_object_unref(list_store_);
-
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview_), TRUE);
-  gtk_tree_view_set_row_separator_func(
-      GTK_TREE_VIEW(treeview_),
-      gtk_tree::TableAdapter::OnCheckRowIsSeparator,
-      NULL,
-      NULL);
-
-  // Set up the properties of the treeview
-  GtkTreeViewColumn* hostname_column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_HOSTNAME_HEADER).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", gtk_tree::TableAdapter::COL_TITLE,
-      "weight", gtk_tree::TableAdapter::COL_WEIGHT,
-      "weight-set", gtk_tree::TableAdapter::COL_WEIGHT_SET,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), hostname_column);
-
-  GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_ACTION,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), action_column);
-
-  treeview_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(treeview_));
-  gtk_tree_selection_set_mode(treeview_selection_, GTK_SELECTION_MULTIPLE);
-  gtk_tree_selection_set_select_function(
-      treeview_selection_,
-      gtk_tree::TableAdapter::OnSelectionFilter,
-      NULL,
-      NULL);
-  g_signal_connect(treeview_selection_, "changed",
-                   G_CALLBACK(OnTreeSelectionChangedThunk), this);
-
-  // Bind |list_store_| to our C++ model.
-  model_.reset(model);
-  model_adapter_.reset(new gtk_tree::TableAdapter(this, list_store_,
-                                                  model_.get()));
-  // Force a reload of everything to copy data into |list_store_|.
-  model_adapter_->OnModelChanged();
-
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(title_message_id).c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CLOSE,
-      GTK_RESPONSE_CLOSE,
-      NULL);
-  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, 400);
-  // Allow browser windows to go in front of the options dialog in metacity.
-  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox);
-
-  // Create a scrolled window to wrap the treeview widget.
-  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
-                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
-  gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0);
-
-  GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-
-  remove_button_ = gtk_util::BuildDialogButton(dialog_,
-                                               IDS_EXCEPTIONS_REMOVE_BUTTON,
-                                               GTK_STOCK_REMOVE);
-
-  g_signal_connect(remove_button_, "clicked", G_CALLBACK(RemoveThunk), this);
-  gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0);
-
-  remove_all_button_ = gtk_util::BuildDialogButton(
-      dialog_,
-      IDS_EXCEPTIONS_REMOVEALL_BUTTON,
-      GTK_STOCK_CLEAR);
-  g_signal_connect(remove_all_button_, "clicked", G_CALLBACK(RemoveAllThunk),
-                   this);
-  gtk_box_pack_start(GTK_BOX(button_box), remove_all_button_, FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0);
-
-  UpdateButtonState();
-
-  gtk_util::ShowDialogWithLocalizedSize(dialog_,
-      IDS_SIMPLE_CONTENT_EXCEPTION_DIALOG_WIDTH_CHARS,
-      IDS_SIMPLE_CONTENT_EXCEPTION_DIALOG_HEIGHT_LINES,
-      true);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-SimpleContentExceptionsWindow::~SimpleContentExceptionsWindow() {}
-
-void SimpleContentExceptionsWindow::SetColumnValues(int row,
-                                                    GtkTreeIter* iter) {
-  string16 hostname = model_->GetText(row, IDS_EXCEPTIONS_HOSTNAME_HEADER);
-  gtk_list_store_set(list_store_, iter, gtk_tree::TableAdapter::COL_TITLE,
-                     UTF16ToUTF8(hostname).c_str(), -1);
-
-  string16 action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER);
-  gtk_list_store_set(list_store_, iter, COL_ACTION,
-                     UTF16ToUTF8(action).c_str(), -1);
-}
-
-void SimpleContentExceptionsWindow::OnAnyModelUpdateStart() {
-  ignore_selection_changes_ = true;
-}
-
-void SimpleContentExceptionsWindow::OnAnyModelUpdate() {
-  ignore_selection_changes_ = false;
-}
-
-void SimpleContentExceptionsWindow::UpdateButtonState() {
-  int row_count = gtk_tree_model_iter_n_children(
-      GTK_TREE_MODEL(list_store_), NULL);
-
-  RemoveRowsTableModel::Rows rows;
-  std::set<int> indices;
-  gtk_tree::GetSelectedIndices(treeview_selection_, &indices);
-  model_adapter_->MapListStoreIndicesToModelRows(indices, &rows);
-  gtk_widget_set_sensitive(remove_button_, model_->CanRemoveRows(rows));
-  gtk_widget_set_sensitive(remove_all_button_, row_count > 0);
-}
-
-void SimpleContentExceptionsWindow::Remove(GtkWidget* widget) {
-  RemoveRowsTableModel::Rows rows;
-  std::set<int> indices;
-  gtk_tree::GetSelectedIndices(treeview_selection_, &indices);
-  model_adapter_->MapListStoreIndicesToModelRows(indices, &rows);
-  model_->RemoveRows(rows);
-  UpdateButtonState();
-}
-
-void SimpleContentExceptionsWindow::RemoveAll(GtkWidget* widget) {
-  model_->RemoveAll();
-  UpdateButtonState();
-}
-
-void SimpleContentExceptionsWindow::OnWindowDestroy(GtkWidget* widget) {
-  instance = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void SimpleContentExceptionsWindow::OnTreeSelectionChanged(
-    GtkWidget* selection) {
-  if (!ignore_selection_changes_)
-    UpdateButtonState();
-}
diff --git a/chrome/browser/gtk/options/simple_content_exceptions_window.h b/chrome/browser/gtk/options/simple_content_exceptions_window.h
deleted file mode 100644
index 2d3b068..0000000
--- a/chrome/browser/gtk/options/simple_content_exceptions_window.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_WINDOW_H_
-#define CHROME_BROWSER_GTK_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_WINDOW_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/remove_rows_table_model.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/content_settings_types.h"
-
-class SimpleContentExceptionsWindow
-    : public gtk_tree::TableAdapter::Delegate {
- public:
-  // Takes ownership of |model|.
-  static void ShowExceptionsWindow(GtkWindow* parent,
-                                   RemoveRowsTableModel* model,
-                                   int tile_message_id);
-
-  virtual ~SimpleContentExceptionsWindow();
-
-  // gtk_tree::TableAdapter::Delegate implementation:
-  virtual void SetColumnValues(int row, GtkTreeIter* iter);
-  virtual void OnAnyModelUpdateStart();
-  virtual void OnAnyModelUpdate();
-
- private:
-  // Takes ownership of |model|.
-  SimpleContentExceptionsWindow(GtkWindow* parent,
-                                RemoveRowsTableModel* model,
-                                int title_message_id);
-
-  // Updates which buttons are enabled.
-  void UpdateButtonState();
-
-  // Callbacks for the buttons.
-  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void, Remove);
-  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void, RemoveAll);
-
-  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void,
-                       OnWindowDestroy);
-  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void,
-                       OnTreeSelectionChanged);
-
-  // The list presented in |treeview_|; a gobject instead of a C++ object.
-  GtkListStore* list_store_;
-
-  // The C++, views-ish, cross-platform model class that actually contains the
-  // gold standard data.
-  scoped_ptr<RemoveRowsTableModel> model_;
-
-  // The adapter that ferries data back and forth between |model_| and
-  // |list_store_| whenever either of them change.
-  scoped_ptr<gtk_tree::TableAdapter> model_adapter_;
-
-  // The exception window.
-  GtkWidget* dialog_;
-
-  // The treeview that presents the site/action pairs.
-  GtkWidget* treeview_;
-
-  // The current user selection from |treeview_|.
-  GtkTreeSelection* treeview_selection_;
-
-  // Whether to ignore selection changes. This is set during model updates,
-  // when the list store may be inconsistent with the table model.
-  bool ignore_selection_changes_;
-
-  // Buttons.
-  GtkWidget* remove_button_;
-  GtkWidget* remove_all_button_;
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_WINDOW_H_
diff --git a/chrome/browser/gtk/options/url_picker_dialog_gtk.cc b/chrome/browser/gtk/options/url_picker_dialog_gtk.cc
deleted file mode 100644
index 9f7ed06..0000000
--- a/chrome/browser/gtk/options/url_picker_dialog_gtk.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/options/url_picker_dialog_gtk.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/possible_url_model.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/gtk_util.h"
-#include "googleurl/src/gurl.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "net/base/net_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-// Column ids for |history_list_store_|.
-enum {
-  COL_FAVICON,
-  COL_TITLE,
-  COL_DISPLAY_URL,
-  COL_COUNT,
-};
-
-}  // anonymous namespace
-
-UrlPickerDialogGtk::UrlPickerDialogGtk(UrlPickerCallback* callback,
-                                       Profile* profile,
-                                       GtkWindow* parent)
-    : profile_(profile),
-      callback_(callback) {
-  std::string dialog_name = l10n_util::GetStringUTF8(IDS_ASI_ADD_TITLE);
-  dialog_ = gtk_dialog_new_with_buttons(
-      dialog_name.c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      GTK_STOCK_CANCEL,
-      GTK_RESPONSE_CANCEL,
-      NULL);
-  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
-      dialog_, profile));
-  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
-
-  add_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
-                                      GTK_STOCK_ADD, GTK_RESPONSE_OK);
-  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  // URL entry.
-  GtkWidget* url_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
-  GtkWidget* url_label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_ASI_URL).c_str());
-  gtk_box_pack_start(GTK_BOX(url_hbox), url_label,
-                     FALSE, FALSE, 0);
-  url_entry_ = gtk_entry_new();
-  accessible_widget_helper_->SetWidgetName(url_entry_, IDS_ASI_URL);
-  gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
-  g_signal_connect(url_entry_, "changed",
-                   G_CALLBACK(OnUrlEntryChangedThunk), this);
-  gtk_box_pack_start(GTK_BOX(url_hbox), url_entry_,
-                     TRUE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), url_hbox,
-                     FALSE, FALSE, 0);
-
-  // Recent history description label.
-  GtkWidget* history_vbox = gtk_vbox_new(FALSE, gtk_util::kLabelSpacing);
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), history_vbox);
-  GtkWidget* history_label = gtk_util::CreateBoldLabel(
-      l10n_util::GetStringUTF8(IDS_ASI_DESCRIPTION));
-  gtk_box_pack_start(GTK_BOX(history_vbox), history_label, FALSE, FALSE, 0);
-
-  // Recent history list.
-  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(history_vbox), scroll_window);
-
-  history_list_store_ = gtk_list_store_new(COL_COUNT,
-                                           GDK_TYPE_PIXBUF,
-                                           G_TYPE_STRING,
-                                           G_TYPE_STRING);
-  history_list_sort_ = gtk_tree_model_sort_new_with_model(
-      GTK_TREE_MODEL(history_list_store_));
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
-                                  COL_TITLE, CompareTitle, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
-                                  COL_DISPLAY_URL, CompareURL, this, NULL);
-  history_tree_ = gtk_tree_view_new_with_model(history_list_sort_);
-  accessible_widget_helper_->SetWidgetName(
-      history_tree_, IDS_ASI_DESCRIPTION);
-  g_object_unref(history_list_store_);
-  g_object_unref(history_list_sort_);
-  gtk_container_add(GTK_CONTAINER(scroll_window), history_tree_);
-  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(history_tree_),
-                                    TRUE);
-  g_signal_connect(history_tree_, "row-activated",
-                   G_CALLBACK(OnHistoryRowActivatedThunk), this);
-
-  history_selection_ = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(history_tree_));
-  gtk_tree_selection_set_mode(history_selection_,
-                              GTK_SELECTION_SINGLE);
-  g_signal_connect(history_selection_, "changed",
-                   G_CALLBACK(OnHistorySelectionChangedThunk), this);
-
-  // History list columns.
-  GtkTreeViewColumn* column = gtk_tree_view_column_new();
-  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(column, renderer, FALSE);
-  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
-  renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(column, renderer, TRUE);
-  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_),
-                              column);
-  gtk_tree_view_column_set_title(
-      column, l10n_util::GetStringUTF8(IDS_ASI_PAGE_COLUMN).c_str());
-  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-  gtk_tree_view_column_set_resizable(column, TRUE);
-  gtk_tree_view_column_set_sort_column_id(column, COL_TITLE);
-
-  GtkTreeViewColumn* url_column = gtk_tree_view_column_new_with_attributes(
-      l10n_util::GetStringUTF8(IDS_ASI_URL_COLUMN).c_str(),
-      gtk_cell_renderer_text_new(),
-      "text", COL_DISPLAY_URL,
-      NULL);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_), url_column);
-  gtk_tree_view_column_set_sort_column_id(url_column, COL_DISPLAY_URL);
-
-  // Loading data, showing dialog.
-  url_table_model_.reset(new PossibleURLModel());
-  url_table_adapter_.reset(new gtk_tree::TableAdapter(this, history_list_store_,
-                                                      url_table_model_.get()));
-  url_table_model_->Reload(profile_);
-
-  EnableControls();
-
-  // Set the size of the dialog.
-  gtk_widget_realize(dialog_);
-  gtk_util::SetWindowSizeFromResources(GTK_WINDOW(dialog_),
-                                       IDS_URLPICKER_DIALOG_WIDTH_CHARS,
-                                       IDS_URLPICKER_DIALOG_HEIGHT_LINES,
-                                       true);
-
-  // Set the width of the first column as well.
-  int width;
-  gtk_util::GetWidgetSizeFromResources(
-      dialog_,
-      IDS_URLPICKER_DIALOG_LEFT_COLUMN_WIDTH_CHARS, 0,
-      &width, NULL);
-  gtk_tree_view_column_set_fixed_width(column, width);
-
-  gtk_util::ShowDialogWithLocalizedSize(dialog_,
-      IDS_URLPICKER_DIALOG_WIDTH_CHARS,
-      IDS_URLPICKER_DIALOG_HEIGHT_LINES,
-      false);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
-}
-
-UrlPickerDialogGtk::~UrlPickerDialogGtk() {
-  delete callback_;
-}
-
-void UrlPickerDialogGtk::AddURL() {
-  callback_->Run(URLFixerUpper::FixupURL(
-      gtk_entry_get_text(GTK_ENTRY(url_entry_)), std::string()));
-}
-
-void UrlPickerDialogGtk::EnableControls() {
-  const gchar* text = gtk_entry_get_text(GTK_ENTRY(url_entry_));
-  gtk_widget_set_sensitive(add_button_, text && *text);
-}
-
-std::string UrlPickerDialogGtk::GetURLForPath(GtkTreePath* path) const {
-  gint row = gtk_tree::GetTreeSortChildRowNumForPath(history_list_sort_, path);
-  if (row < 0) {
-    NOTREACHED();
-    return std::string();
-  }
-  std::string languages =
-      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
-  // Because this gets parsed by FixupURL(), it's safe to omit the scheme or
-  // trailing slash, and unescape most characters, but we need to not drop any
-  // username/password, or unescape anything that changes the meaning.
-  return UTF16ToUTF8(net::FormatUrl(url_table_model_->GetURL(row),
-      languages, net::kFormatUrlOmitAll & ~net::kFormatUrlOmitUsernamePassword,
-      UnescapeRule::SPACES, NULL, NULL, NULL));
-}
-
-void UrlPickerDialogGtk::SetColumnValues(int row, GtkTreeIter* iter) {
-  SkBitmap bitmap = url_table_model_->GetIcon(row);
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
-  string16 title = url_table_model_->GetText(row, IDS_ASI_PAGE_COLUMN);
-  string16 url = url_table_model_->GetText(row, IDS_ASI_URL_COLUMN);
-  gtk_list_store_set(history_list_store_, iter,
-                     COL_FAVICON, pixbuf,
-                     COL_TITLE, UTF16ToUTF8(title).c_str(),
-                     COL_DISPLAY_URL, UTF16ToUTF8(url).c_str(),
-                     -1);
-  g_object_unref(pixbuf);
-}
-
-// static
-gint UrlPickerDialogGtk::CompareTitle(GtkTreeModel* model,
-                                      GtkTreeIter* a,
-                                      GtkTreeIter* b,
-                                      gpointer window) {
-  int row1 = gtk_tree::GetRowNumForIter(model, a);
-  int row2 = gtk_tree::GetRowNumForIter(model, b);
-  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
-      CompareValues(row1, row2, IDS_ASI_PAGE_COLUMN);
-}
-
-// static
-gint UrlPickerDialogGtk::CompareURL(GtkTreeModel* model,
-                                    GtkTreeIter* a,
-                                    GtkTreeIter* b,
-                                    gpointer window) {
-  int row1 = gtk_tree::GetRowNumForIter(model, a);
-  int row2 = gtk_tree::GetRowNumForIter(model, b);
-  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
-      CompareValues(row1, row2, IDS_ASI_URL_COLUMN);
-}
-
-void UrlPickerDialogGtk::OnUrlEntryChanged(GtkWidget* editable) {
-  EnableControls();
-}
-
-void UrlPickerDialogGtk::OnHistorySelectionChanged(
-    GtkTreeSelection* selection) {
-  GtkTreeIter iter;
-  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
-    // The user has unselected the history element, nothing to do.
-    return;
-  }
-  GtkTreePath* path = gtk_tree_model_get_path(
-      GTK_TREE_MODEL(history_list_sort_), &iter);
-  gtk_entry_set_text(GTK_ENTRY(url_entry_),
-                     GetURLForPath(path).c_str());
-  gtk_tree_path_free(path);
-}
-
-void UrlPickerDialogGtk::OnHistoryRowActivated(GtkWidget* tree_view,
-                                               GtkTreePath* path,
-                                               GtkTreeViewColumn* column) {
-  callback_->Run(URLFixerUpper::FixupURL(GetURLForPath(path), std::string()));
-  gtk_widget_destroy(dialog_);
-}
-
-void UrlPickerDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
-  if (response_id == GTK_RESPONSE_OK)
-    AddURL();
-  gtk_widget_destroy(dialog_);
-}
-
-void UrlPickerDialogGtk::OnWindowDestroy(GtkWidget* widget) {
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
diff --git a/chrome/browser/gtk/options/url_picker_dialog_gtk.h b/chrome/browser/gtk/options/url_picker_dialog_gtk.h
deleted file mode 100644
index 6c4429b..0000000
--- a/chrome/browser/gtk/options/url_picker_dialog_gtk.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OPTIONS_URL_PICKER_DIALOG_GTK_H_
-#define CHROME_BROWSER_GTK_OPTIONS_URL_PICKER_DIALOG_GTK_H_
-#pragma once
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/history/history.h"
-
-class AccessibleWidgetHelper;
-class GURL;
-class Profile;
-class PossibleURLModel;
-
-class UrlPickerDialogGtk : public gtk_tree::TableAdapter::Delegate {
- public:
-  typedef Callback1<const GURL&>::Type UrlPickerCallback;
-
-  UrlPickerDialogGtk(UrlPickerCallback* callback,
-                     Profile* profile,
-                     GtkWindow* parent);
-
-  ~UrlPickerDialogGtk();
-
-  // gtk_tree::TableAdapter::Delegate implementation.
-  virtual void SetColumnValues(int row, GtkTreeIter* iter);
-
- private:
-  // Call the callback based on url entry.
-  void AddURL();
-
-  // Set sensitivity of buttons based on url entry state.
-  void EnableControls();
-
-  // Return the entry-formatted url for path in the sorted model.
-  std::string GetURLForPath(GtkTreePath* path) const;
-
-  // GTK sorting callbacks.
-  static gint CompareTitle(GtkTreeModel* model, GtkTreeIter* a, GtkTreeIter* b,
-                           gpointer window);
-  static gint CompareURL(GtkTreeModel* model, GtkTreeIter* a, GtkTreeIter* b,
-                         gpointer window);
-
-  CHROMEGTK_CALLBACK_0(UrlPickerDialogGtk, void, OnUrlEntryChanged);
-  CHROMEGTK_CALLBACK_2(UrlPickerDialogGtk, void, OnHistoryRowActivated,
-                       GtkTreePath*, GtkTreeViewColumn*);
-  CHROMEGTK_CALLBACK_1(UrlPickerDialogGtk, void, OnResponse, int);
-  CHROMEGTK_CALLBACK_0(UrlPickerDialogGtk, void, OnWindowDestroy);
-
-  // Callback for user selecting rows in recent history list.
-  CHROMEG_CALLBACK_0(UrlPickerDialogGtk, void, OnHistorySelectionChanged,
-                     GtkTreeSelection*)
-
-  // The dialog window.
-  GtkWidget* dialog_;
-
-  // The text entry for manually adding an URL.
-  GtkWidget* url_entry_;
-
-  // The add button (we need a reference to it so we can de-activate it when the
-  // |url_entry_| is empty.)
-  GtkWidget* add_button_;
-
-  // The recent history list.
-  GtkWidget* history_tree_;
-  GtkListStore* history_list_store_;
-  GtkTreeModel* history_list_sort_;
-  GtkTreeSelection* history_selection_;
-
-  // Profile.
-  Profile* profile_;
-
-  // The table model.
-  scoped_ptr<PossibleURLModel> url_table_model_;
-  scoped_ptr<gtk_tree::TableAdapter> url_table_adapter_;
-
-  // Called if the user selects an url.
-  UrlPickerCallback* callback_;
-
-  // Helper object to manage accessibility metadata.
-  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(UrlPickerDialogGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OPTIONS_URL_PICKER_DIALOG_GTK_H_
diff --git a/chrome/browser/gtk/overflow_button.cc b/chrome/browser/gtk/overflow_button.cc
deleted file mode 100644
index 9397799..0000000
--- a/chrome/browser/gtk/overflow_button.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/overflow_button.h"
-
-#include <gtk/gtk.h>
-
-#include "app/resource_bundle.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "grit/theme_resources.h"
-
-OverflowButton::OverflowButton(Profile* profile) : profile_(profile) {
-  widget_.Own(GtkThemeProvider::GetFrom(profile)->BuildChromeButton());
-  gtk_widget_set_no_show_all(widget_.get(), TRUE);
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-  GtkThemeProvider::GetFrom(profile)->InitThemesFor(this);
-}
-
-OverflowButton::~OverflowButton() {
-  widget_.Destroy();
-}
-
-void OverflowButton::Observe(NotificationType type,
-                             const NotificationSource& source,
-                             const NotificationDetails& details) {
-  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(widget()));
-  if (former_child)
-    gtk_widget_destroy(former_child);
-
-  GtkWidget* new_child =
-      GtkThemeProvider::GetFrom(profile_)->UseGtkTheme() ?
-      gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE) :
-      gtk_image_new_from_pixbuf(ResourceBundle::GetSharedInstance().
-          GetRTLEnabledPixbufNamed(IDR_BOOKMARK_BAR_CHEVRONS));
-
-  gtk_container_add(GTK_CONTAINER(widget()), new_child);
-  gtk_widget_show(new_child);
-}
diff --git a/chrome/browser/gtk/overflow_button.h b/chrome/browser/gtk/overflow_button.h
deleted file mode 100644
index 66724f4..0000000
--- a/chrome/browser/gtk/overflow_button.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_OVERFLOW_BUTTON_H_
-#define CHROME_BROWSER_GTK_OVERFLOW_BUTTON_H_
-#pragma once
-
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-typedef struct _GtkWidget GtkWidget;
-class Profile;
-
-// An overflow chevron button. The button itself is a plain gtk_chrome_button,
-// and this class handles theming it.
-class OverflowButton : public NotificationObserver {
- public:
-  explicit OverflowButton(Profile* profile);
-  virtual ~OverflowButton();
-
-  GtkWidget* widget() { return widget_.get(); }
-
- private:
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  OwnedWidgetGtk widget_;
-
-  Profile* profile_;
-
-  NotificationRegistrar registrar_;
-};
-
-#endif  // CHROME_BROWSER_GTK_OVERFLOW_BUTTON_H_
diff --git a/chrome/browser/gtk/owned_widget_gtk.cc b/chrome/browser/gtk/owned_widget_gtk.cc
deleted file mode 100644
index 2315371..0000000
--- a/chrome/browser/gtk/owned_widget_gtk.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include "base/logging.h"
-
-OwnedWidgetGtk::~OwnedWidgetGtk() {
-  DCHECK(!widget_) << "You must explicitly call OwnerWidgetGtk::Destroy().";
-}
-
-void OwnedWidgetGtk::Own(GtkWidget* widget) {
-  if (!widget)
-    return;
-
-  DCHECK(!widget_);
-  // We want to make sure that Own() was called properly, right after the
-  // widget was created. There should be a floating reference.
-  DCHECK(g_object_is_floating(widget));
-
-  // Sink the floating reference, we should now own this reference.
-  g_object_ref_sink(widget);
-  widget_ = widget;
-}
-
-void OwnedWidgetGtk::Destroy() {
-  if (!widget_)
-    return;
-
-  GtkWidget* widget = widget_;
-  widget_ = NULL;
-  gtk_widget_destroy(widget);
-
-  DCHECK(!g_object_is_floating(widget));
-  // NOTE: Assumes some implementation details about glib internals.
-  DCHECK_EQ(G_OBJECT(widget)->ref_count, 1U);
-  g_object_unref(widget);
-}
diff --git a/chrome/browser/gtk/owned_widget_gtk.h b/chrome/browser/gtk/owned_widget_gtk.h
deleted file mode 100644
index b5299c9..0000000
--- a/chrome/browser/gtk/owned_widget_gtk.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This class assists you in dealing with a specific situation when managing
-// ownership between a C++ object and a GTK widget.  It is common to have a
-// C++ object which encapsulates a GtkWidget, and that widget is exposed from
-// the object for use outside of the class.  In this situation, you commonly
-// want the GtkWidget's lifetime to match its C++ object's lifetime.  Using an
-// OwnedWigetGtk will take ownership over the initial reference of the
-// GtkWidget, so that it is "owned" by the C++ object.  Example usage:
-//
-// class FooViewGtk() {
-//  public:
-//   FooViewGtk() { }
-//   ~FooViewGtk() { widget_.Destroy(); }
-//   void Init() { vbox_.Own(gtk_vbox_new()); }
-//   GtkWidget* widget() { return vbox_.get() };  // Host my widget!
-//  private:
-//   OwnedWidgetGtk vbox_;
-// };
-//
-// This design will ensure that the widget stays alive from the call to Own()
-// until the call to Destroy().
-//
-// - Details of the problem and OwnedWidgetGtk's solution:
-// In order to make passing ownership more convenient for newly created
-// widgets, GTK has a concept of a "floating" reference.  All GtkObjects (and
-// thus GtkWidgets) inherit from GInitiallyUnowned.  When they are created, the
-// object starts with a reference count of 1, but has its floating flag set.
-// When it is put into a container for the first time, that container will
-// "sink" the floating reference, and the count will still be 1.  Now the
-// container owns the widget, and if we remove the widget from the container,
-// the widget is destroyed.  This style of ownership often causes problems when
-// you have an object encapsulating the widget.  If we just use a raw
-// GtkObject* with no specific ownership management, we push the widget's
-// ownership onto the user of the class.  Now the C++ object can't depend on
-// the widget being valid, since it doesn't manage its lifetime.  If the widget
-// was removed from a container, removing its only reference, it would be
-// destroyed (from the C++ object's perspective) unexpectantly destroyed.  The
-// solution is fairly simple, make sure that the C++ object owns the widget,
-// and thus it is also responsible for destroying it.  This boils down to:
-//   GtkWidget* widget = gtk_widget_new();
-//   g_object_ref_sink(widget);  // Claim the initial floating reference.
-//   ...
-//   gtk_destroy_widget(widget);  // Ask all code to destroy their references.
-//   g_object_unref(widget);  // Destroy the initial reference we had claimed.
-
-#ifndef CHROME_BROWSER_GTK_OWNED_WIDGET_GTK_H_
-#define CHROME_BROWSER_GTK_OWNED_WIDGET_GTK_H_
-#pragma once
-
-#include "base/basictypes.h"
-
-typedef struct _GtkWidget GtkWidget;
-
-class OwnedWidgetGtk {
- public:
-  // Create an instance that isn't managing any ownership.
-  OwnedWidgetGtk() : widget_(NULL) { }
-  // Create an instance that owns |widget|.
-  explicit OwnedWidgetGtk(GtkWidget* widget) : widget_(NULL) { Own(widget); }
-
-  ~OwnedWidgetGtk();
-
-  // Return the currently owned widget, or NULL if no widget is owned.
-  GtkWidget* get() const { return widget_; }
-  GtkWidget* operator->() const { return widget_; }
-
-  // Takes ownership of a widget, by taking the initial floating reference of
-  // the GtkWidget.  It is expected that Own() is called right after the widget
-  // has been created, and before any other references to the widget might have
-  // been added.  It is valid to never call Own(), in which case Destroy() will
-  // do nothing.  If Own() has been called, you must explicitly call Destroy().
-  void Own(GtkWidget* widget);
-
-  // You must call Destroy() after you have called Own().  Calling Destroy()
-  // will call gtk_widget_destroy(), and drop our reference to the widget.
-  // After a call to Destroy(), you may call Own() again.  NOTE: It is expected
-  // that after gtk_widget_destroy we will be holding the only reference left
-  // on the object.  We assert this in debug mode to help catch any leaks.
-  void Destroy();
-
- private:
-  GtkWidget* widget_;
-
-  DISALLOW_COPY_AND_ASSIGN(OwnedWidgetGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_OWNED_WIDGET_GTK_H_
diff --git a/chrome/browser/gtk/page_info_bubble_gtk.cc b/chrome/browser/gtk/page_info_bubble_gtk.cc
deleted file mode 100644
index 6bfa77c..0000000
--- a/chrome/browser/gtk/page_info_bubble_gtk.cc
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "build/build_config.h"
-
-#include "app/l10n_util.h"
-#include "base/i18n/rtl.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/certificate_viewer.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/gtk/browser_toolbar_gtk.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-#include "chrome/browser/page_info_model.h"
-#include "chrome/browser/page_info_window.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-
-class Profile;
-
-namespace {
-
-class PageInfoBubbleGtk : public PageInfoModel::PageInfoModelObserver,
-                          public InfoBubbleGtkDelegate,
-                          public NotificationObserver {
- public:
-  PageInfoBubbleGtk(gfx::NativeWindow parent,
-                    Profile* profile,
-                    const GURL& url,
-                    const NavigationEntry::SSLStatus& ssl,
-                    bool show_history);
-  virtual ~PageInfoBubbleGtk();
-
-  // PageInfoModelObserver implementation:
-  virtual void ModelChanged();
-
-  // NotificationObserver implementation:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // InfoBubbleGtkDelegate implementation:
-  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                 bool closed_by_escape);
-
- private:
-  // Layouts the different sections retrieved from the model.
-  void InitContents();
-
-  // Returns a widget that contains the UI for the passed |section|.
-  GtkWidget* CreateSection(const PageInfoModel::SectionInfo& section);
-
-  // Link button callbacks.
-  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnViewCertLinkClicked);
-  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnHelpLinkClicked);
-
-  // The model containing the different sections to display.
-  PageInfoModel model_;
-
-  // The url for this dialog. Should be unique among active dialogs.
-  GURL url_;
-
-  // The id of the certificate for this page.
-  int cert_id_;
-
-  // Parent window.
-  GtkWindow* parent_;
-
-  // The virtual box containing the sections.
-  GtkWidget* contents_;
-
-  // The widget relative to which we are positioned.
-  GtkWidget* anchor_;
-
-  // Provides colors and stuff.
-  GtkThemeProvider* theme_provider_;
-
-  // The various elements in the interface we keep track of for theme changes.
-  std::vector<GtkWidget*> labels_;
-  std::vector<GtkWidget*> links_;
-
-  InfoBubbleGtk* bubble_;
-
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleGtk);
-};
-
-PageInfoBubbleGtk::PageInfoBubbleGtk(gfx::NativeWindow parent,
-                                     Profile* profile,
-                                     const GURL& url,
-                                     const NavigationEntry::SSLStatus& ssl,
-                                     bool show_history)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
-                                            show_history, this)),
-      url_(url),
-      cert_id_(ssl.cert_id()),
-      parent_(parent),
-      contents_(NULL),
-      theme_provider_(GtkThemeProvider::GetFrom(profile)) {
-  BrowserWindowGtk* browser_window =
-      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
-
-  anchor_ = browser_window->
-      GetToolbar()->GetLocationBarView()->location_icon_widget();
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-
-  InitContents();
-
-  InfoBubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ?
-      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
-      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
-  bubble_ = InfoBubbleGtk::Show(anchor_,
-                                NULL,  // |rect|
-                                contents_,
-                                arrow_location,
-                                true,  // |match_system_theme|
-                                true,  // |grab_input|
-                                theme_provider_,
-                                this);  // |delegate|
-  if (!bubble_) {
-    NOTREACHED();
-    return;
-  }
-}
-
-PageInfoBubbleGtk::~PageInfoBubbleGtk() {
-}
-
-void PageInfoBubbleGtk::ModelChanged() {
-  InitContents();
-}
-
-void PageInfoBubbleGtk::Observe(NotificationType type,
-                                const NotificationSource& source,
-                                const NotificationDetails& details) {
-  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
-
-  for (std::vector<GtkWidget*>::iterator it = links_.begin();
-       it != links_.end(); ++it) {
-    gtk_chrome_link_button_set_use_gtk_theme(
-        GTK_CHROME_LINK_BUTTON(*it),
-        theme_provider_->UseGtkTheme());
-  }
-
-  if (theme_provider_->UseGtkTheme()) {
-    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
-         it != labels_.end(); ++it) {
-      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
-    }
-  } else {
-    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
-         it != labels_.end(); ++it) {
-      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-    }
-  }
-}
-
-void PageInfoBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
-                                          bool closed_by_escape) {
-  delete this;
-}
-
-void PageInfoBubbleGtk::InitContents() {
-  if (!contents_) {
-    contents_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
-    gtk_container_set_border_width(GTK_CONTAINER(contents_),
-                                   gtk_util::kContentAreaBorder);
-  } else {
-    labels_.clear();
-    links_.clear();
-    gtk_util::RemoveAllChildren(contents_);
-  }
-
-  for (int i = 0; i < model_.GetSectionCount(); i++) {
-    gtk_box_pack_start(GTK_BOX(contents_),
-                       CreateSection(model_.GetSectionInfo(i)),
-                       FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(contents_),
-                       gtk_hseparator_new(),
-                       FALSE, FALSE, 0);
-  }
-
-  GtkWidget* help_link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK).c_str());
-  links_.push_back(help_link);
-  GtkWidget* help_link_hbox = gtk_hbox_new(FALSE, 0);
-  // Stick it in an hbox so it doesn't expand to the whole width.
-  gtk_box_pack_start(GTK_BOX(help_link_hbox), help_link, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(contents_), help_link_hbox, FALSE, FALSE, 0);
-  g_signal_connect(help_link, "clicked",
-                   G_CALLBACK(OnHelpLinkClickedThunk), this);
-
-  theme_provider_->InitThemesFor(this);
-  gtk_widget_show_all(contents_);
-}
-
-GtkWidget* PageInfoBubbleGtk::CreateSection(
-    const PageInfoModel::SectionInfo& section) {
-  GtkWidget* section_box = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-
-  GdkPixbuf* pixbuf = model_.GetIconImage(section.icon_id);
-  if (pixbuf) {
-    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
-    gtk_box_pack_start(GTK_BOX(section_box), image, FALSE, FALSE, 0);
-    gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
-  }
-
-  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(section_box), vbox, TRUE, TRUE, 0);
-
-  if (!section.headline.empty()) {
-    GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.headline).c_str());
-    labels_.push_back(label);
-    PangoAttrList* attributes = pango_attr_list_new();
-    pango_attr_list_insert(attributes,
-                           pango_attr_weight_new(PANGO_WEIGHT_BOLD));
-    gtk_label_set_attributes(GTK_LABEL(label), attributes);
-    pango_attr_list_unref(attributes);
-    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-    // Allow linebreaking in the middle of words if necessary, so that extremely
-    // long hostnames (longer than one line) will still be completely shown.
-    gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
-    gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-    gtk_widget_set_size_request(label, 400, -1);
-  }
-  GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.description).c_str());
-  labels_.push_back(label);
-  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  // Allow linebreaking in the middle of words if necessary, so that extremely
-  // long hostnames (longer than one line) will still be completely shown.
-  gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-  gtk_widget_set_size_request(label, 400, -1);
-
-  if (section.type == PageInfoModel::SECTION_INFO_IDENTITY && cert_id_ > 0) {
-    GtkWidget* view_cert_link = gtk_chrome_link_button_new(
-        l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
-    links_.push_back(view_cert_link);
-    GtkWidget* cert_link_hbox = gtk_hbox_new(FALSE, 0);
-    // Stick it in an hbox so it doesn't expand to the whole width.
-    gtk_box_pack_start(GTK_BOX(cert_link_hbox), view_cert_link,
-                       FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), cert_link_hbox, FALSE, FALSE, 0);
-    g_signal_connect(view_cert_link, "clicked",
-                     G_CALLBACK(OnViewCertLinkClickedThunk), this);
-  }
-
-  return section_box;
-}
-
-void PageInfoBubbleGtk::OnViewCertLinkClicked(GtkWidget* widget) {
-  ShowCertificateViewerByID(GTK_WINDOW(parent_), cert_id_);
-  bubble_->Close();
-}
-
-void PageInfoBubbleGtk::OnHelpLinkClicked(GtkWidget* widget) {
-  GURL url = google_util::AppendGoogleLocaleParam(
-      GURL(chrome::kPageInfoHelpCenterURL));
-  Browser* browser = BrowserList::GetLastActive();
-  browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
-  bubble_->Close();
-}
-
-}  // namespace
-
-namespace browser {
-
-void ShowPageInfoBubble(gfx::NativeWindow parent,
-                        Profile* profile,
-                        const GURL& url,
-                        const NavigationEntry::SSLStatus& ssl,
-                        bool show_history) {
-  new PageInfoBubbleGtk(parent, profile, url, ssl, show_history);
-}
-
-}  // namespace browser
diff --git a/chrome/browser/gtk/process_singleton_dialog.cc b/chrome/browser/gtk/process_singleton_dialog.cc
deleted file mode 100644
index 26fc1b4..0000000
--- a/chrome/browser/gtk/process_singleton_dialog.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/process_singleton_dialog.h"
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "grit/chromium_strings.h"
-
-// static
-void ProcessSingletonDialog::ShowAndRun(const std::string& message) {
-  ProcessSingletonDialog dialog(message);
-}
-
-ProcessSingletonDialog::ProcessSingletonDialog(const std::string& message) {
-  dialog_ = gtk_message_dialog_new(
-      NULL,
-      static_cast<GtkDialogFlags>(0),
-      GTK_MESSAGE_ERROR,
-      GTK_BUTTONS_NONE,
-      "%s",
-      message.c_str());
-  gtk_util::ApplyMessageDialogQuirks(dialog_);
-  gtk_window_set_title(GTK_WINDOW(dialog_),
-                       l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str());
-  gtk_dialog_add_button(GTK_DIALOG(dialog_), GTK_STOCK_QUIT,
-                        GTK_RESPONSE_REJECT);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
-
-  gtk_widget_show_all(dialog_);
-  MessageLoop::current()->Run();
-}
-
-// static
-void ProcessSingletonDialog::OnResponse(GtkWidget* widget, int response,
-                                        ProcessSingletonDialog* dialog) {
-  gtk_widget_destroy(dialog->dialog_);
-  MessageLoop::current()->Quit();
-}
diff --git a/chrome/browser/gtk/process_singleton_dialog.h b/chrome/browser/gtk/process_singleton_dialog.h
deleted file mode 100644
index ec9641e..0000000
--- a/chrome/browser/gtk/process_singleton_dialog.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_PROCESS_SINGLETON_DIALOG_H_
-#define CHROME_BROWSER_GTK_PROCESS_SINGLETON_DIALOG_H_
-#pragma once
-
-#include <string>
-
-#include <gtk/gtk.h>
-
-#include "base/basictypes.h"
-
-// Displays an error to the user when the ProcessSingleton cannot acquire the
-// lock.  This runs the message loop itself as the browser message loop has not
-// started by that point in the startup process.
-class ProcessSingletonDialog {
- public:
-  // Shows the dialog, and returns once the dialog has been closed.
-  static void ShowAndRun(const std::string& message);
-
- private:
-  explicit ProcessSingletonDialog(const std::string& message);
-
-  static void OnResponse(GtkWidget* widget,
-                         int response,
-                         ProcessSingletonDialog* dialog);
-
-  GtkWidget* dialog_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProcessSingletonDialog);
-};
-
-#endif  // CHROME_BROWSER_GTK_PROCESS_SINGLETON_DIALOG_H_
diff --git a/chrome/browser/gtk/reload_button_gtk.cc b/chrome/browser/gtk/reload_button_gtk.cc
deleted file mode 100644
index 9ee0e29..0000000
--- a/chrome/browser/gtk/reload_button_gtk.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/reload_button_gtk.h"
-
-#include <algorithm>
-
-#include "app/l10n_util.h"
-#include "base/logging.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/location_bar_view_gtk.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_source.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-// The width of this button in GTK+ theme mode. The Stop and Refresh stock icons
-// can be different sizes; this variable is used to make sure that the button
-// doesn't change sizes when switching between the two.
-static int GtkButtonWidth = 0;
-
-////////////////////////////////////////////////////////////////////////////////
-// ReloadButton, public:
-
-ReloadButtonGtk::ReloadButtonGtk(LocationBarViewGtk* location_bar,
-                                 Browser* browser)
-    : location_bar_(location_bar),
-      browser_(browser),
-      intended_mode_(MODE_RELOAD),
-      visible_mode_(MODE_RELOAD),
-      theme_provider_(browser ?
-                      GtkThemeProvider::GetFrom(browser->profile()) : NULL),
-      reload_(theme_provider_, IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0),
-      stop_(theme_provider_, IDR_STOP, IDR_STOP_P, IDR_STOP_H, IDR_STOP_D),
-      widget_(gtk_chrome_button_new()),
-      stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)),
-      testing_mouse_hovered_(false),
-      testing_reload_count_(0) {
-  gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height());
-
-  gtk_widget_set_app_paintable(widget(), TRUE);
-
-  g_signal_connect(widget(), "clicked", G_CALLBACK(OnClickedThunk), this);
-  g_signal_connect(widget(), "expose-event", G_CALLBACK(OnExposeThunk), this);
-  g_signal_connect(widget(), "leave-notify-event",
-                   G_CALLBACK(OnLeaveNotifyThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS);
-
-  gtk_widget_set_has_tooltip(widget(), TRUE);
-  g_signal_connect(widget(), "query-tooltip", G_CALLBACK(OnQueryTooltipThunk),
-                   this);
-
-  hover_controller_.Init(widget());
-  gtk_util::SetButtonTriggersNavigation(widget());
-
-  if (theme_provider_) {
-    theme_provider_->InitThemesFor(this);
-    registrar_.Add(this,
-                   NotificationType::BROWSER_THEME_CHANGED,
-                   Source<GtkThemeProvider>(theme_provider_));
-  }
-
-  // Set the default double-click timer delay to the system double-click time.
-  int timer_delay_ms;
-  GtkSettings* settings = gtk_settings_get_default();
-  g_object_get(G_OBJECT(settings), "gtk-double-click-time", &timer_delay_ms,
-               NULL);
-  double_click_timer_delay_ = base::TimeDelta::FromMilliseconds(timer_delay_ms);
-}
-
-ReloadButtonGtk::~ReloadButtonGtk() {
-  widget_.Destroy();
-}
-
-void ReloadButtonGtk::ChangeMode(Mode mode, bool force) {
-  intended_mode_ = mode;
-
-  // If the change is forced, or the user isn't hovering the icon, or it's safe
-  // to change it to the other image type, make the change immediately;
-  // otherwise we'll let it happen later.
-  if (force || ((GTK_WIDGET_STATE(widget()) == GTK_STATE_NORMAL) &&
-      !testing_mouse_hovered_) || ((mode == MODE_STOP) ?
-          !double_click_timer_.IsRunning() : (visible_mode_ != MODE_STOP))) {
-    double_click_timer_.Stop();
-    stop_to_reload_timer_.Stop();
-    visible_mode_ = mode;
-
-    stop_.set_paint_override(-1);
-    gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget_.get()));
-
-    UpdateThemeButtons();
-    gtk_widget_queue_draw(widget());
-  } else if (visible_mode_ != MODE_RELOAD) {
-    // If you read the views implementation of reload_button.cc, you'll see
-    // that instead of screwing with paint states, the views implementation
-    // just changes whether the view is enabled. We can't do that here because
-    // changing the widget state to GTK_STATE_INSENSITIVE will cause a cascade
-    // of messages on all its children and will also trigger a synthesized
-    // leave notification and prevent the real leave notification from turning
-    // the button back to normal. So instead, override the stop_ paint state
-    // for chrome-theme mode, and use this as a flag to discard click events.
-    stop_.set_paint_override(GTK_STATE_INSENSITIVE);
-
-    // Also set the gtk_chrome_button paint state to insensitive to hide
-    // the border drawn around the stop icon.
-    gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget_.get()),
-                                      GTK_STATE_INSENSITIVE);
-
-    // If we're in GTK theme mode, we need to also render the correct icon for
-    // the stop/insensitive since we won't be using |stop_| to render the icon.
-    UpdateThemeButtons();
-
-    // Go ahead and change to reload after a bit, which allows repeated reloads
-    // without moving the mouse.
-    if (!stop_to_reload_timer_.IsRunning()) {
-      stop_to_reload_timer_.Start(stop_to_reload_timer_delay_, this,
-                                  &ReloadButtonGtk::OnStopToReloadTimer);
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ReloadButtonGtk, NotificationObserver implementation:
-
-void ReloadButtonGtk::Observe(NotificationType type,
-                              const NotificationSource& source,
-                              const NotificationDetails& /* details */) {
-  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
-
-  GtkThemeProvider* provider = static_cast<GtkThemeProvider*>(
-      Source<GtkThemeProvider>(source).ptr());
-  DCHECK_EQ(provider, theme_provider_);
-  GtkButtonWidth = 0;
-  UpdateThemeButtons();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ReloadButtonGtk, private:
-
-void ReloadButtonGtk::OnClicked(GtkWidget* /* sender */) {
-  if (visible_mode_ == MODE_STOP) {
-    // Do nothing if Stop was disabled due to an attempt to change back to
-    // RELOAD mode while hovered.
-    if (stop_.paint_override() == GTK_STATE_INSENSITIVE)
-      return;
-
-    if (browser_)
-      browser_->Stop();
-
-    // The user has clicked, so we can feel free to update the button,
-    // even if the mouse is still hovering.
-    ChangeMode(MODE_RELOAD, true);
-  } else if (!double_click_timer_.IsRunning()) {
-    // Shift-clicking or Ctrl-clicking the reload button means we should ignore
-    // any cached content.
-    int command;
-    GdkModifierType modifier_state;
-    gtk_get_current_event_state(&modifier_state);
-    guint modifier_state_uint = modifier_state;
-    if (modifier_state_uint & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
-      command = IDC_RELOAD_IGNORING_CACHE;
-      // Mask off Shift and Control so they don't affect the disposition below.
-      modifier_state_uint &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
-    } else {
-      command = IDC_RELOAD;
-    }
-
-    WindowOpenDisposition disposition =
-        event_utils::DispositionFromEventFlags(modifier_state_uint);
-    if ((disposition == CURRENT_TAB) && location_bar_) {
-      // Forcibly reset the location bar, since otherwise it won't discard any
-      // ongoing user edits, since it doesn't realize this is a user-initiated
-      // action.
-      location_bar_->Revert();
-    }
-
-    // Start a timer - while this timer is running, the reload button cannot be
-    // changed to a stop button.  We do not set |intended_mode_| to MODE_STOP
-    // here as the browser will do that when it actually starts loading (which
-    // may happen synchronously, thus the need to do this before telling the
-    // browser to execute the reload command).
-    double_click_timer_.Start(double_click_timer_delay_, this,
-                              &ReloadButtonGtk::OnDoubleClickTimer);
-
-    if (browser_)
-      browser_->ExecuteCommandWithDisposition(command, disposition);
-    ++testing_reload_count_;
-  }
-}
-
-gboolean ReloadButtonGtk::OnExpose(GtkWidget* widget,
-                                   GdkEventExpose* e) {
-  if (theme_provider_ && theme_provider_->UseGtkTheme())
-    return FALSE;
-  return ((visible_mode_ == MODE_RELOAD) ? reload_ : stop_).OnExpose(
-      widget, e, hover_controller_.GetCurrentValue());
-}
-
-gboolean ReloadButtonGtk::OnLeaveNotify(GtkWidget* /* widget */,
-                                        GdkEventCrossing* /* event */) {
-  ChangeMode(intended_mode_, true);
-  return FALSE;
-}
-
-gboolean ReloadButtonGtk::OnQueryTooltip(GtkWidget* /* sender */,
-                                         gint /* x */,
-                                         gint /* y */,
-                                         gboolean /* keyboard_mode */,
-                                         GtkTooltip* tooltip) {
-  // |location_bar_| can be NULL in tests.
-  if (!location_bar_)
-    return FALSE;
-
-  gtk_tooltip_set_text(tooltip, l10n_util::GetStringUTF8(
-      (visible_mode_ == MODE_RELOAD) ?
-      IDS_TOOLTIP_RELOAD : IDS_TOOLTIP_STOP).c_str());
-  return TRUE;
-}
-
-void ReloadButtonGtk::UpdateThemeButtons() {
-  bool use_gtk = theme_provider_ && theme_provider_->UseGtkTheme();
-
-  if (use_gtk) {
-    gtk_widget_ensure_style(widget());
-    GtkIconSet* icon_set = gtk_style_lookup_icon_set(
-        widget()->style,
-        (visible_mode_ == MODE_RELOAD) ? GTK_STOCK_REFRESH : GTK_STOCK_STOP);
-    if (icon_set) {
-      GtkStateType state = static_cast<GtkStateType>(
-          GTK_WIDGET_STATE(widget()));
-      if (visible_mode_ == MODE_STOP && stop_.paint_override() != -1)
-        state = static_cast<GtkStateType>(stop_.paint_override());
-
-      GdkPixbuf* pixbuf = gtk_icon_set_render_icon(
-          icon_set,
-          widget()->style,
-          gtk_widget_get_direction(widget()),
-          state,
-          GTK_ICON_SIZE_SMALL_TOOLBAR,
-          widget(),
-          NULL);
-
-      gtk_button_set_image(GTK_BUTTON(widget()),
-                           gtk_image_new_from_pixbuf(pixbuf));
-      g_object_unref(pixbuf);
-    }
-
-    gtk_widget_set_size_request(widget(), -1, -1);
-    GtkRequisition req;
-    gtk_widget_size_request(widget(), &req);
-    GtkButtonWidth = std::max(GtkButtonWidth, req.width);
-    gtk_widget_set_size_request(widget(), GtkButtonWidth, -1);
-
-    gtk_widget_set_app_paintable(widget(), FALSE);
-    gtk_widget_set_double_buffered(widget(), TRUE);
-  } else {
-    gtk_button_set_image(GTK_BUTTON(widget()), NULL);
-
-    gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height());
-
-    gtk_widget_set_app_paintable(widget(), TRUE);
-    // We effectively double-buffer by virtue of having only one image...
-    gtk_widget_set_double_buffered(widget(), FALSE);
-  }
-
-  gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(widget()), use_gtk);
-}
-
-void ReloadButtonGtk::OnDoubleClickTimer() {
-  ChangeMode(intended_mode_, false);
-}
-
-void ReloadButtonGtk::OnStopToReloadTimer() {
-  ChangeMode(intended_mode_, true);
-}
diff --git a/chrome/browser/gtk/reload_button_gtk.h b/chrome/browser/gtk/reload_button_gtk.h
deleted file mode 100644
index b641a13..0000000
--- a/chrome/browser/gtk/reload_button_gtk.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_RELOAD_BUTTON_GTK_H_
-#define CHROME_BROWSER_GTK_RELOAD_BUTTON_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/timer.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class Browser;
-class GtkThemeProvider;
-class LocationBarViewGtk;
-class Task;
-
-class ReloadButtonGtk : public NotificationObserver {
- public:
-  enum Mode { MODE_RELOAD = 0, MODE_STOP };
-
-  ReloadButtonGtk(LocationBarViewGtk* location_bar, Browser* browser);
-  ~ReloadButtonGtk();
-
-  GtkWidget* widget() const { return widget_.get(); }
-
-  // Ask for a specified button state.  If |force| is true this will be applied
-  // immediately.
-  void ChangeMode(Mode mode, bool force);
-
-  // Provide NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& /* details */);
-
- private:
-  friend class ReloadButtonGtkTest;
-
-  CHROMEGTK_CALLBACK_0(ReloadButtonGtk, void, OnClicked);
-  CHROMEGTK_CALLBACK_1(ReloadButtonGtk, gboolean, OnExpose, GdkEventExpose*);
-  CHROMEGTK_CALLBACK_1(ReloadButtonGtk,
-                       gboolean,
-                       OnLeaveNotify,
-                       GdkEventCrossing*);
-  CHROMEGTK_CALLBACK_4(ReloadButtonGtk,
-                       gboolean,
-                       OnQueryTooltip,
-                       gint,
-                       gint,
-                       gboolean,
-                       GtkTooltip*);
-
-  void UpdateThemeButtons();
-
-  void OnDoubleClickTimer();
-  void OnStopToReloadTimer();
-
-  base::OneShotTimer<ReloadButtonGtk> double_click_timer_;
-  base::OneShotTimer<ReloadButtonGtk> stop_to_reload_timer_;
-
-  // These may be NULL when testing.
-  LocationBarViewGtk* const location_bar_;
-  Browser* const browser_;
-
-  // The mode we should be in assuming no timers are running.
-  Mode intended_mode_;
-
-  // The currently-visible mode - this may differ from the intended mode.
-  Mode visible_mode_;
-
-  // Used to listen for theme change notifications.
-  NotificationRegistrar registrar_;
-
-  GtkThemeProvider* theme_provider_;
-
-  CustomDrawButtonBase reload_;
-  CustomDrawButtonBase stop_;
-  CustomDrawHoverController hover_controller_;
-
-  OwnedWidgetGtk widget_;
-
-  // The delay times for the timers.  These are members so that tests can modify
-  // them.
-  base::TimeDelta double_click_timer_delay_;
-  base::TimeDelta stop_to_reload_timer_delay_;
-
-  // TESTING ONLY
-  // True if we should pretend the button is hovered.
-  bool testing_mouse_hovered_;
-  // Increments when we would tell the browser to "reload", so
-  // test code can tell whether we did so (as there may be no |browser_|).
-  int testing_reload_count_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ReloadButtonGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_RELOAD_BUTTON_GTK_H_
diff --git a/chrome/browser/gtk/reload_button_gtk_unittest.cc b/chrome/browser/gtk/reload_button_gtk_unittest.cc
deleted file mode 100644
index fddb358..0000000
--- a/chrome/browser/gtk/reload_button_gtk_unittest.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/reload_button_gtk.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class ReloadButtonGtkTest : public testing::Test {
- public:
-  ReloadButtonGtkTest();
-
-  void CheckState(bool enabled,
-                  ReloadButtonGtk::Mode intended_mode,
-                  ReloadButtonGtk::Mode visible_mode,
-                  bool double_click_timer_running,
-                  bool stop_to_reload_timer_running);
-
-  // These accessors eliminate the need to declare each testcase as a friend.
-  void set_mouse_hovered(bool hovered) {
-    reload_.testing_mouse_hovered_ = hovered;
-  }
-  int reload_count() { return reload_.testing_reload_count_; }
-  void fake_mouse_leave() { reload_.OnLeaveNotify(reload_.widget(), NULL); }
-
- protected:
-  // We need a message loop for the timers to post events.
-  MessageLoop loop_;
-
-  ReloadButtonGtk reload_;
-};
-
-ReloadButtonGtkTest::ReloadButtonGtkTest() : reload_(NULL, NULL) {
-  // Set the timer delays to 0 so that timers will fire as soon as we tell the
-  // message loop to run pending tasks.
-  reload_.double_click_timer_delay_ = base::TimeDelta();
-  reload_.stop_to_reload_timer_delay_ = base::TimeDelta();
-}
-
-void ReloadButtonGtkTest::CheckState(bool enabled,
-                                     ReloadButtonGtk::Mode intended_mode,
-                                     ReloadButtonGtk::Mode visible_mode,
-                                     bool double_click_timer_running,
-                                     bool stop_to_reload_timer_running) {
-  EXPECT_NE(enabled, reload_.stop_.paint_override() == GTK_STATE_INSENSITIVE);
-  EXPECT_EQ(intended_mode, reload_.intended_mode_);
-  EXPECT_EQ(visible_mode, reload_.visible_mode_);
-  EXPECT_EQ(double_click_timer_running,
-            reload_.double_click_timer_.IsRunning());
-  EXPECT_EQ(stop_to_reload_timer_running,
-            reload_.stop_to_reload_timer_.IsRunning());
-}
-
-TEST_F(ReloadButtonGtkTest, Basic) {
-  // The stop/reload button starts in the "enabled reload" state with no timers
-  // running.
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             false, false);
-
-  // Press the button.  This should start the double-click timer.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             true, false);
-
-  // Now change the mode (as if the browser had started loading the page).  This
-  // should cancel the double-click timer since the button is not hovered.
-  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
-  CheckState(true, ReloadButtonGtk::MODE_STOP, ReloadButtonGtk::MODE_STOP,
-             false, false);
-
-  // Press the button again.  This should change back to reload.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             false, false);
-}
-
-TEST_F(ReloadButtonGtkTest, DoubleClickTimer) {
-  // Start by pressing the button.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-
-  // Try to press the button again.  This should do nothing because the timer is
-  // running.
-  int original_reload_count = reload_count();
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             true, false);
-  EXPECT_EQ(original_reload_count, reload_count());
-
-  // Hover the button, and change mode.  The visible mode should not change,
-  // again because the timer is running.
-  set_mouse_hovered(true);
-  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
-  CheckState(true, ReloadButtonGtk::MODE_STOP, ReloadButtonGtk::MODE_RELOAD,
-             true, false);
-
-  // Now fire the timer.  This should complete the mode change.
-  loop_.RunAllPending();
-  CheckState(true, ReloadButtonGtk::MODE_STOP, ReloadButtonGtk::MODE_STOP,
-             false, false);
-}
-
-TEST_F(ReloadButtonGtkTest, DisableOnHover) {
-  // Change to stop and hover.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
-  set_mouse_hovered(true);
-
-  // Now change back to reload.  This should result in a disabled stop button
-  // due to the hover.
-  reload_.ChangeMode(ReloadButtonGtk::MODE_RELOAD, false);
-  CheckState(false, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_STOP,
-             false, true);
-
-  // Un-hover the button, which should allow it to reset.
-  set_mouse_hovered(false);
-  fake_mouse_leave();
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             false, false);
-}
-
-TEST_F(ReloadButtonGtkTest, ResetOnClick) {
-  // Change to stop and hover.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
-  set_mouse_hovered(true);
-
-  // Press the button.  This should change back to reload despite the hover,
-  // because it's a direct user action.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             false, false);
-}
-
-TEST_F(ReloadButtonGtkTest, ResetOnTimer) {
-  // Change to stop, hover, and change back to reload.
-  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
-  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
-  set_mouse_hovered(true);
-  reload_.ChangeMode(ReloadButtonGtk::MODE_RELOAD, false);
-
-  // Now fire the stop-to-reload timer.  This should reset the button.
-  loop_.RunAllPending();
-  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
-             false, false);
-}
diff --git a/chrome/browser/gtk/repost_form_warning_gtk.cc b/chrome/browser/gtk/repost_form_warning_gtk.cc
deleted file mode 100644
index 1740b29..0000000
--- a/chrome/browser/gtk/repost_form_warning_gtk.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/repost_form_warning_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/repost_form_warning_controller.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_type.h"
-#include "grit/generated_resources.h"
-
-RepostFormWarningGtk::RepostFormWarningGtk(GtkWindow* parent,
-                                           TabContents* tab_contents)
-    : controller_(new RepostFormWarningController(tab_contents)) {
-  dialog_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaBorder);
-  gtk_box_set_spacing(GTK_BOX(dialog_), gtk_util::kContentAreaSpacing);
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_HTTP_POST_WARNING).c_str());
-  GtkWidget* image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,
-                                              GTK_ICON_SIZE_DIALOG);
-  gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0);
-
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  gtk_label_set_selectable(GTK_LABEL(label), TRUE);
-
-  GtkWidget *hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-
-  gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-
-  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-
-  gtk_box_pack_start(GTK_BOX(dialog_), hbox, FALSE, FALSE, 0);
-
-  GtkWidget* buttonBox = gtk_hbutton_box_new();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END);
-  gtk_box_set_spacing(GTK_BOX(buttonBox), gtk_util::kControlSpacing);
-  gtk_box_pack_end(GTK_BOX(dialog_), buttonBox, FALSE, TRUE, 0);
-
-  cancel_ = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
-  gtk_button_set_label(GTK_BUTTON(cancel_),
-                       l10n_util::GetStringUTF8(IDS_CANCEL).c_str());
-  g_signal_connect(cancel_, "clicked", G_CALLBACK(OnCancelThunk), this);
-  gtk_box_pack_end(GTK_BOX(buttonBox), cancel_, FALSE, TRUE, 0);
-
-  ok_ = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
-  gtk_button_set_label(
-      GTK_BUTTON(ok_),
-      l10n_util::GetStringUTF8(IDS_HTTP_POST_WARNING_RESEND).c_str());
-  g_signal_connect(ok_, "clicked", G_CALLBACK(OnRefreshThunk), this);
-  gtk_box_pack_end(GTK_BOX(buttonBox), ok_, FALSE, TRUE, 0);
-
-  g_signal_connect(cancel_, "hierarchy-changed",
-                   G_CALLBACK(OnHierarchyChangedThunk), this);
-
-  controller_->Show(this);
-}
-
-GtkWidget* RepostFormWarningGtk::GetWidgetRoot() {
-  return dialog_;
-}
-
-void RepostFormWarningGtk::DeleteDelegate() {
-  delete this;
-}
-
-RepostFormWarningGtk::~RepostFormWarningGtk() {
-  gtk_widget_destroy(dialog_);
-}
-
-void RepostFormWarningGtk::OnRefresh(GtkWidget* widget) {
-  controller_->Continue();
-}
-
-void RepostFormWarningGtk::OnCancel(GtkWidget* widget) {
-  controller_->Cancel();
-}
-
-void RepostFormWarningGtk::OnHierarchyChanged(GtkWidget* root,
-                                              GtkWidget* previous_toplevel) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(cancel_))) {
-    return;
-  }
-  gtk_widget_grab_focus(cancel_);
-}
diff --git a/chrome/browser/gtk/repost_form_warning_gtk.h b/chrome/browser/gtk/repost_form_warning_gtk.h
deleted file mode 100644
index 6b0f982..0000000
--- a/chrome/browser/gtk/repost_form_warning_gtk.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_REPOST_FORM_WARNING_GTK_H_
-#define CHROME_BROWSER_GTK_REPOST_FORM_WARNING_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-
-class RepostFormWarningController;
-
-// Displays a dialog that warns the user that they are about to resubmit
-// a form.
-// To display the dialog, allocate this object on the heap. It will open the
-// dialog from its constructor and then delete itself when the user dismisses
-// the dialog.
-class RepostFormWarningGtk : public ConstrainedDialogDelegate {
- public:
-  RepostFormWarningGtk(GtkWindow* parent, TabContents* tab_contents);
-
-  // ConstrainedDialogDelegate methods
-  virtual GtkWidget* GetWidgetRoot();
-
-  virtual void DeleteDelegate();
-
- private:
-  virtual ~RepostFormWarningGtk();
-
-  // Callbacks
-  CHROMEGTK_CALLBACK_0(RepostFormWarningGtk, void, OnRefresh);
-  CHROMEGTK_CALLBACK_0(RepostFormWarningGtk, void, OnCancel);
-  CHROMEGTK_CALLBACK_1(RepostFormWarningGtk,
-                       void,
-                       OnHierarchyChanged,
-                       GtkWidget*);
-
-  scoped_ptr<RepostFormWarningController> controller_;
-
-  GtkWidget* dialog_;
-  GtkWidget* ok_;
-  GtkWidget* cancel_;
-
-  DISALLOW_COPY_AND_ASSIGN(RepostFormWarningGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_REPOST_FORM_WARNING_GTK_H_
diff --git a/chrome/browser/gtk/rounded_window.cc b/chrome/browser/gtk/rounded_window.cc
deleted file mode 100644
index f0d827d..0000000
--- a/chrome/browser/gtk/rounded_window.cc
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/rounded_window.h"
-
-#include <gtk/gtk.h>
-#include <math.h>
-
-#include "app/gtk_signal_registrar.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "chrome/browser/gtk/gtk_util.h"
-
-namespace gtk_util {
-
-namespace {
-
-const char* kRoundedData = "rounded-window-data";
-
-// If the border radius is less than |kMinRoundedBorderSize|, we don't actually
-// round the corners, we just truncate the corner.
-const int kMinRoundedBorderSize = 8;
-
-struct RoundedWindowData {
-  // Expected window size. Used to detect when we need to reshape the window.
-  int expected_width;
-  int expected_height;
-
-  // Color of the border.
-  GdkColor border_color;
-
-  // Radius of the edges in pixels.
-  int corner_size;
-
-  // Which corners should be rounded?
-  int rounded_edges;
-
-  // Which sides of the window should have an internal border?
-  int drawn_borders;
-
-  // Keeps track of attached signal handlers.
-  GtkSignalRegistrar signals;
-};
-
-// Callback from GTK to release allocated memory.
-void FreeRoundedWindowData(gpointer data) {
-  delete static_cast<RoundedWindowData*>(data);
-}
-
-enum FrameType {
-  FRAME_MASK,
-  FRAME_STROKE,
-};
-
-// Returns a list of points that either form the outline of the status bubble
-// (|type| == FRAME_MASK) or form the inner border around the inner edge
-// (|type| == FRAME_STROKE).
-std::vector<GdkPoint> MakeFramePolygonPoints(RoundedWindowData* data,
-                                             FrameType type) {
-  using gtk_util::MakeBidiGdkPoint;
-  int width = data->expected_width;
-  int height = data->expected_height;
-  int corner_size = data->corner_size;
-
-  std::vector<GdkPoint> points;
-
-  bool ltr = !base::i18n::IsRTL();
-  // If we have a stroke, we have to offset some of our points by 1 pixel.
-  // We have to inset by 1 pixel when we draw horizontal lines that are on the
-  // bottom or when we draw vertical lines that are closer to the end (end is
-  // right for ltr).
-  int y_off = (type == FRAME_MASK) ? 0 : -1;
-  // We use this one for LTR.
-  int x_off_l = ltr ? y_off : 0;
-  // We use this one for RTL.
-  int x_off_r = !ltr ? -y_off : 0;
-
-  // Build up points starting with the bottom left corner and continuing
-  // clockwise.
-
-  // Bottom left corner.
-  if (type == FRAME_MASK ||
-      (data->drawn_borders & (BORDER_LEFT | BORDER_BOTTOM))) {
-    if (data->rounded_edges & ROUNDED_BOTTOM_LEFT) {
-      if (corner_size >= kMinRoundedBorderSize) {
-        // We are careful to only add points that are horizontal or vertically
-        // offset from the previous point (not both).  This avoids rounding
-        // differences when two points are connected.
-        for (int x = 0; x <= corner_size; ++x) {
-          int y = static_cast<int>(sqrt(static_cast<double>(
-              (corner_size * corner_size) - (x * x))));
-          if (x > 0) {
-            points.push_back(MakeBidiGdkPoint(
-                corner_size - x + x_off_r + 1,
-                height - (corner_size - y) + y_off, width, ltr));
-          }
-          points.push_back(MakeBidiGdkPoint(
-              corner_size - x + x_off_r,
-              height - (corner_size - y) + y_off, width, ltr));
-        }
-      } else {
-        points.push_back(MakeBidiGdkPoint(
-            corner_size + x_off_l, height + y_off, width, ltr));
-        points.push_back(MakeBidiGdkPoint(
-            x_off_r, height - corner_size, width, ltr));
-      }
-    } else {
-      points.push_back(MakeBidiGdkPoint(x_off_r, height + y_off, width, ltr));
-    }
-  }
-
-  // Top left corner.
-  if (type == FRAME_MASK ||
-      (data->drawn_borders & (BORDER_LEFT | BORDER_TOP))) {
-    if (data->rounded_edges & ROUNDED_TOP_LEFT) {
-      if (corner_size >= kMinRoundedBorderSize) {
-        for (int x = corner_size; x >= 0; --x) {
-          int y = static_cast<int>(sqrt(static_cast<double>(
-              (corner_size * corner_size) - (x * x))));
-          points.push_back(MakeBidiGdkPoint(corner_size - x + x_off_r,
-              corner_size - y, width, ltr));
-          if (x > 0) {
-            points.push_back(MakeBidiGdkPoint(corner_size - x + 1 + x_off_r,
-                corner_size - y, width, ltr));
-          }
-        }
-      } else {
-        points.push_back(MakeBidiGdkPoint(
-            x_off_r, corner_size - 1, width, ltr));
-        points.push_back(MakeBidiGdkPoint(
-            corner_size + x_off_r - 1, 0, width, ltr));
-      }
-    } else {
-      points.push_back(MakeBidiGdkPoint(x_off_r, 0, width, ltr));
-    }
-  }
-
-  // Top right corner.
-  if (type == FRAME_MASK ||
-      (data->drawn_borders & (BORDER_TOP | BORDER_RIGHT))) {
-    if (data->rounded_edges & ROUNDED_TOP_RIGHT) {
-      if (corner_size >= kMinRoundedBorderSize) {
-        for (int x = 0; x <= corner_size; ++x) {
-          int y = static_cast<int>(sqrt(static_cast<double>(
-              (corner_size * corner_size) - (x * x))));
-          if (x > 0) {
-            points.push_back(MakeBidiGdkPoint(
-                width - (corner_size - x) + x_off_l - 1,
-                corner_size - y, width, ltr));
-          }
-          points.push_back(MakeBidiGdkPoint(
-              width - (corner_size - x) + x_off_l,
-              corner_size - y, width, ltr));
-        }
-      } else {
-        points.push_back(MakeBidiGdkPoint(
-            width - corner_size + 1 + x_off_l, 0, width, ltr));
-        points.push_back(MakeBidiGdkPoint(
-            width + x_off_l, corner_size - 1, width, ltr));
-      }
-    } else {
-      points.push_back(MakeBidiGdkPoint(
-          width + x_off_l, 0, width, ltr));
-    }
-  }
-
-  // Bottom right corner.
-  if (type == FRAME_MASK ||
-      (data->drawn_borders & (BORDER_RIGHT | BORDER_BOTTOM))) {
-    if (data->rounded_edges & ROUNDED_BOTTOM_RIGHT) {
-      if (corner_size >= kMinRoundedBorderSize) {
-        for (int x = corner_size; x >= 0; --x) {
-          int y = static_cast<int>(sqrt(static_cast<double>(
-              (corner_size * corner_size) - (x * x))));
-          points.push_back(MakeBidiGdkPoint(
-              width - (corner_size - x) + x_off_l,
-              height - (corner_size - y) + y_off, width, ltr));
-          if (x > 0) {
-            points.push_back(MakeBidiGdkPoint(
-                width - (corner_size - x) + x_off_l - 1,
-                height - (corner_size - y) + y_off, width, ltr));
-          }
-        }
-      } else {
-        points.push_back(MakeBidiGdkPoint(
-            width + x_off_l, height - corner_size, width, ltr));
-        points.push_back(MakeBidiGdkPoint(
-            width - corner_size + x_off_r, height + y_off, width, ltr));
-      }
-    } else {
-      points.push_back(MakeBidiGdkPoint(
-          width + x_off_l, height + y_off, width, ltr));
-    }
-  }
-
-  return points;
-}
-
-// Set the window shape in needed, lets our owner do some drawing (if it wants
-// to), and finally draw the border.
-gboolean OnRoundedWindowExpose(GtkWidget* widget,
-                               GdkEventExpose* event) {
-  RoundedWindowData* data = static_cast<RoundedWindowData*>(
-      g_object_get_data(G_OBJECT(widget), kRoundedData));
-
-  if (data->expected_width != widget->allocation.width ||
-      data->expected_height != widget->allocation.height) {
-    data->expected_width = widget->allocation.width;
-    data->expected_height = widget->allocation.height;
-
-    // We need to update the shape of the status bubble whenever our GDK
-    // window changes shape.
-    std::vector<GdkPoint> mask_points = MakeFramePolygonPoints(
-        data, FRAME_MASK);
-    GdkRegion* mask_region = gdk_region_polygon(&mask_points[0],
-                                                mask_points.size(),
-                                                GDK_EVEN_ODD_RULE);
-    gdk_window_shape_combine_region(widget->window, mask_region, 0, 0);
-    gdk_region_destroy(mask_region);
-  }
-
-  GdkDrawable* drawable = GDK_DRAWABLE(event->window);
-  GdkGC* gc = gdk_gc_new(drawable);
-  gdk_gc_set_clip_rectangle(gc, &event->area);
-  gdk_gc_set_rgb_fg_color(gc, &data->border_color);
-
-  // Stroke the frame border.
-  std::vector<GdkPoint> points = MakeFramePolygonPoints(
-      data, FRAME_STROKE);
-  if (data->drawn_borders == BORDER_ALL) {
-    // If we want to have borders everywhere, we need to draw a polygon instead
-    // of a set of lines.
-    gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
-  } else if (points.size() > 0) {
-    gdk_draw_lines(drawable, gc, &points[0], points.size());
-  }
-
-  g_object_unref(gc);
-  return FALSE;  // Propagate so our children paint, etc.
-}
-
-// On theme changes, window shapes are reset, but we detect whether we need to
-// reshape a window by whether its allocation has changed so force it to reset
-// the window shape on next expose.
-void OnStyleSet(GtkWidget* widget, GtkStyle* previous_style) {
-  DCHECK(widget);
-  RoundedWindowData* data = static_cast<RoundedWindowData*>(
-      g_object_get_data(G_OBJECT(widget), kRoundedData));
-  DCHECK(data);
-  data->expected_width = -1;
-  data->expected_height = -1;
-}
-
-}  // namespace
-
-void ActAsRoundedWindow(
-    GtkWidget* widget, const GdkColor& color, int corner_size,
-    int rounded_edges, int drawn_borders) {
-  DCHECK(widget);
-  DCHECK(!g_object_get_data(G_OBJECT(widget), kRoundedData));
-
-  gtk_widget_set_app_paintable(widget, TRUE);
-
-  RoundedWindowData* data = new RoundedWindowData;
-  data->signals.Connect(widget, "expose-event",
-                        G_CALLBACK(OnRoundedWindowExpose), NULL);
-  data->signals.Connect(widget, "style-set", G_CALLBACK(OnStyleSet), NULL);
-
-  data->expected_width = -1;
-  data->expected_height = -1;
-
-  data->border_color = color;
-  data->corner_size = corner_size;
-
-  data->rounded_edges = rounded_edges;
-  data->drawn_borders = drawn_borders;
-
-  g_object_set_data_full(G_OBJECT(widget), kRoundedData,
-                         data, FreeRoundedWindowData);
-
-  if (GTK_WIDGET_VISIBLE(widget))
-    gtk_widget_queue_draw(widget);
-}
-
-void StopActingAsRoundedWindow(GtkWidget* widget) {
-  g_object_set_data(G_OBJECT(widget), kRoundedData, NULL);
-
-  if (GTK_WIDGET_REALIZED(widget))
-    gdk_window_shape_combine_mask(widget->window, NULL, 0, 0);
-
-  if (GTK_WIDGET_VISIBLE(widget))
-    gtk_widget_queue_draw(widget);
-}
-
-bool IsActingAsRoundedWindow(GtkWidget* widget) {
-  return g_object_get_data(G_OBJECT(widget), kRoundedData) != NULL;
-}
-
-void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
-                                     int corner_size,
-                                     int rounded_edges,
-                                     int drawn_borders) {
-  DCHECK(widget);
-  RoundedWindowData* data = static_cast<RoundedWindowData*>(
-      g_object_get_data(G_OBJECT(widget), kRoundedData));
-  DCHECK(data);
-  data->corner_size = corner_size;
-  data->rounded_edges = rounded_edges;
-  data->drawn_borders = drawn_borders;
-}
-
-void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color) {
-  DCHECK(widget);
-  RoundedWindowData* data = static_cast<RoundedWindowData*>(
-      g_object_get_data(G_OBJECT(widget), kRoundedData));
-  DCHECK(data);
-  data->border_color = color;
-}
-
-}  // namespace gtk_util
diff --git a/chrome/browser/gtk/rounded_window.h b/chrome/browser/gtk/rounded_window.h
deleted file mode 100644
index d1788f8..0000000
--- a/chrome/browser/gtk/rounded_window.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_ROUNDED_WINDOW_H_
-#define CHROME_BROWSER_GTK_ROUNDED_WINDOW_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-namespace gtk_util {
-
-// Symbolic names for arguments to |rounded_edges| in ActAsRoundedWindow().
-enum RoundedBorders {
-  ROUNDED_NONE = 0,
-  ROUNDED_BOTTOM_LEFT = 1 << 0,
-  ROUNDED_TOP_LEFT = 1 << 1,
-  ROUNDED_TOP_RIGHT = 1 << 2,
-  ROUNDED_TOP = (1 << 1) | (1 << 2),
-  ROUNDED_BOTTOM_RIGHT = 1 << 3,
-  ROUNDED_ALL = 0xF
-};
-
-// Symbolic names for arguments to |drawn_borders| in ActAsRoundedWindow().
-enum BorderEdge {
-  BORDER_NONE = 0,
-  BORDER_LEFT = 1 << 0,
-  BORDER_TOP = 1 << 1,
-  BORDER_RIGHT = 1 << 2,
-  BORDER_BOTTOM = 1 << 3,
-  BORDER_ALL = 0xF
-};
-
-// Sets up the passed in widget that has its own GdkWindow with an expose
-// handler that forces the window shape into roundness. Caller should not set
-// an "expose-event" handler on |widget|; if caller needs to do custom
-// rendering, use SetRoundedWindowExposeFunction() instead. |rounded_edges|
-// control which corners are rounded. |drawn_borders| border control which
-// sides have a visible border drawn in |color|.
-void ActAsRoundedWindow(
-    GtkWidget* widget, const GdkColor& color, int corner_size,
-    int rounded_edges, int drawn_borders);
-
-// Undoes most of the actions of ActAsRoundedWindow().
-void StopActingAsRoundedWindow(GtkWidget* widget);
-
-// Returns true if the window is rounded.
-bool IsActingAsRoundedWindow(GtkWidget* widget);
-
-// Sets edge and border properties on a widget that has already been configured
-// with ActAsRoundedWindow().
-void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
-                                     int corner_size,
-                                     int rounded_edges,
-                                     int drawn_borders);
-
-// Sets the color of the border on a widget that has already been configured
-// with ActAsRoundedWindow().
-void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color);
-
-
-}  // namespace gtk_util
-
-#endif  // CHROME_BROWSER_GTK_ROUNDED_WINDOW_H_
diff --git a/chrome/browser/gtk/sad_tab_gtk.cc b/chrome/browser/gtk/sad_tab_gtk.cc
deleted file mode 100644
index 80612f7..0000000
--- a/chrome/browser/gtk/sad_tab_gtk.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/sad_tab_gtk.h"
-
-#include <string>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/url_constants.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// Background color of the content (a grayish blue).
-const GdkColor kBackgroundColor = GDK_COLOR_RGB(35, 48, 64);
-
-// Construct a centered GtkLabel with a white foreground.
-// |format| is a printf-style format containing a %s;
-// |str| is substituted into the format.
-GtkWidget* MakeWhiteMarkupLabel(const char* format, const std::string& str) {
-  GtkWidget* label = gtk_label_new(NULL);
-  char* markup = g_markup_printf_escaped(format, str.c_str());
-  gtk_label_set_markup(GTK_LABEL(label), markup);
-  g_free(markup);
-
-  // Center align and justify it.
-  gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
-  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
-
-  // Set text to white.
-  GdkColor white = gtk_util::kGdkWhite;
-  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &white);
-
-  return label;
-}
-
-}  // namespace
-
-SadTabGtk::SadTabGtk(TabContents* tab_contents)
-  : tab_contents_(tab_contents) {
-  DCHECK(tab_contents_);
-
-  // Use an event box to get the background painting correctly.
-  event_box_.Own(gtk_event_box_new());
-  gtk_widget_modify_bg(event_box_.get(), GTK_STATE_NORMAL, &kBackgroundColor);
-  // Allow ourselves to be resized arbitrarily small.
-  gtk_widget_set_size_request(event_box_.get(), 0, 0);
-
-  GtkWidget* centering = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
-  gtk_container_add(GTK_CONTAINER(event_box_.get()), centering);
-
-  // Use a vertical box to contain icon, title, message and link.
-  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_add(GTK_CONTAINER(centering), vbox);
-
-  // Add center-aligned image.
-  GtkWidget* image = gtk_image_new_from_pixbuf(
-      ResourceBundle::GetSharedInstance().GetPixbufNamed(IDR_SAD_TAB));
-  gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5);
-  gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
-
-  // Add spacer between image and title.
-  GtkWidget* spacer = gtk_label_new(NULL);
-  gtk_label_set_markup(GTK_LABEL(spacer), "<span size=\"larger\"> </span>");
-  gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
-
-  // Add center-aligned title.
-  GtkWidget* title = MakeWhiteMarkupLabel(
-      "<span size=\"larger\" style=\"normal\"><b>%s</b></span>",
-      l10n_util::GetStringUTF8(IDS_SAD_TAB_TITLE));
-  gtk_box_pack_start(GTK_BOX(vbox), title, FALSE, FALSE, 0);
-
-  // Add spacer between title and message.
-  spacer = gtk_label_new(" ");
-  gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
-
-  // Add center-aligned message.
-  GtkWidget* message =
-      MakeWhiteMarkupLabel("<span style=\"normal\">%s</span>",
-                           l10n_util::GetStringUTF8(IDS_SAD_TAB_MESSAGE));
-  gtk_label_set_line_wrap(GTK_LABEL(message), TRUE);
-  gtk_box_pack_start(GTK_BOX(vbox), message, FALSE, FALSE, 0);
-
-  // Add spacer between message and link.
-  spacer = gtk_label_new(" ");
-  gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
-
-  if (tab_contents_ != NULL) {
-    // Add the learn-more link and center-align it in an alignment.
-    GtkWidget* link = gtk_chrome_link_button_new(
-        l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
-    gtk_chrome_link_button_set_normal_color(GTK_CHROME_LINK_BUTTON(link),
-                                            &gtk_util::kGdkWhite);
-    g_signal_connect(link, "clicked", G_CALLBACK(OnLinkButtonClickThunk), this);
-    GtkWidget* link_alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
-    gtk_container_add(GTK_CONTAINER(link_alignment), link);
-    gtk_box_pack_start(GTK_BOX(vbox), link_alignment, FALSE, FALSE, 0);
-  }
-
-  gtk_widget_show_all(event_box_.get());
-}
-
-SadTabGtk::~SadTabGtk() {
-  event_box_.Destroy();
-}
-
-void SadTabGtk::OnLinkButtonClick(GtkWidget* sender) {
-  if (tab_contents_ != NULL) {
-    GURL help_url =
-        google_util::AppendGoogleLocaleParam(GURL(chrome::kCrashReasonURL));
-    tab_contents_->OpenURL(help_url, GURL(), CURRENT_TAB, PageTransition::LINK);
-  }
-}
diff --git a/chrome/browser/gtk/sad_tab_gtk.h b/chrome/browser/gtk/sad_tab_gtk.h
deleted file mode 100644
index 9c5489b..0000000
--- a/chrome/browser/gtk/sad_tab_gtk.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_SAD_TAB_GTK_H_
-#define CHROME_BROWSER_GTK_SAD_TAB_GTK_H_
-#pragma once
-
-typedef struct _GtkWidget GtkWidget;
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-
-class TabContents;
-
-class SadTabGtk {
- public:
-  explicit SadTabGtk(TabContents* tab_contents);
-  virtual ~SadTabGtk();
-
-  GtkWidget* widget() const { return event_box_.get(); }
-
- private:
-  CHROMEGTK_CALLBACK_0(SadTabGtk, void, OnLinkButtonClick);
-
-  void OnLinkButtonClick();
-
-  TabContents* tab_contents_;
-  OwnedWidgetGtk event_box_;
-
-  DISALLOW_COPY_AND_ASSIGN(SadTabGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_SAD_TAB_GTK_H_
diff --git a/chrome/browser/gtk/slide_animator_gtk.cc b/chrome/browser/gtk/slide_animator_gtk.cc
deleted file mode 100644
index a3ae9cc..0000000
--- a/chrome/browser/gtk/slide_animator_gtk.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-
-#include "chrome/browser/gtk/gtk_expanded_container.h"
-#include "ui/base/animation/animation.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-void OnChildSizeRequest(GtkWidget* expanded,
-                        GtkWidget* child,
-                        GtkRequisition* requisition,
-                        gpointer control_child_size) {
-  // If |control_child_size| is true, then we want |child_| to match the width
-  // of the |widget_|, but the height of |child_| should not change.
-  if (!GPOINTER_TO_INT(control_child_size)) {
-    requisition->width = -1;
-  }
-  requisition->height = -1;
-}
-
-}  // namespace
-
-bool SlideAnimatorGtk::animations_enabled_ = true;
-
-SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget* child,
-                                   Direction direction,
-                                   int duration,
-                                   bool linear,
-                                   bool control_child_size,
-                                   Delegate* delegate)
-    : child_(child),
-      direction_(direction),
-      delegate_(delegate) {
-  widget_.Own(gtk_expanded_container_new());
-  gtk_container_add(GTK_CONTAINER(widget_.get()), child);
-  gtk_widget_set_size_request(widget_.get(), -1, 0);
-
-  // If the child requests it, we will manually set the size request for
-  // |child_| every time the |widget_| changes sizes. This is mainly useful
-  // for bars, where we want the child to expand to fill all available space.
-  g_signal_connect(widget_.get(), "child-size-request",
-                   G_CALLBACK(OnChildSizeRequest),
-                   GINT_TO_POINTER(control_child_size));
-
-  // We connect to this signal to set an initial position for our child widget.
-  // The reason we connect to this signal rather than setting the initial
-  // position here is that the widget is currently unallocated and may not
-  // even have a size request.
-  g_signal_connect(child, "size-allocate",
-                   G_CALLBACK(OnChildSizeAllocate), this);
-
-  child_needs_move_ = (direction == DOWN);
-
-  animation_.reset(new ui::SlideAnimation(this));
-  // Default tween type is EASE_OUT.
-  if (linear)
-    animation_->SetTweenType(ui::Tween::LINEAR);
-  if (duration != 0)
-    animation_->SetSlideDuration(duration);
-}
-
-SlideAnimatorGtk::~SlideAnimatorGtk() {
-  widget_.Destroy();
-}
-
-void SlideAnimatorGtk::Open() {
-  if (!animations_enabled_)
-    return OpenWithoutAnimation();
-
-  gtk_widget_show(widget_.get());
-  animation_->Show();
-}
-
-void SlideAnimatorGtk::OpenWithoutAnimation() {
-  gtk_widget_show(widget_.get());
-  animation_->Reset(1.0);
-  animation_->Show();
-  AnimationProgressed(animation_.get());
-}
-
-void SlideAnimatorGtk::Close() {
-  if (!animations_enabled_)
-    return CloseWithoutAnimation();
-
-  animation_->Hide();
-}
-
-void SlideAnimatorGtk::End() {
-  animation_->End();
-}
-
-void SlideAnimatorGtk::CloseWithoutAnimation() {
-  animation_->Reset(0.0);
-  animation_->Hide();
-  AnimationProgressed(animation_.get());
-  gtk_widget_hide(widget_.get());
-}
-
-bool SlideAnimatorGtk::IsShowing() {
-  return animation_->IsShowing();
-}
-
-bool SlideAnimatorGtk::IsClosing() {
-  return animation_->IsClosing();
-}
-
-bool SlideAnimatorGtk::IsAnimating() {
-  return animation_->is_animating();
-}
-
-void SlideAnimatorGtk::AnimationProgressed(const ui::Animation* animation) {
-  GtkRequisition req;
-  gtk_widget_size_request(child_, &req);
-
-  int showing_height = static_cast<int>(req.height *
-                                        animation_->GetCurrentValue());
-  if (direction_ == DOWN) {
-    gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()),
-                                child_, 0, showing_height - req.height);
-    child_needs_move_ = false;
-  }
-  gtk_widget_set_size_request(widget_.get(), -1, showing_height);
-}
-
-void SlideAnimatorGtk::AnimationEnded(const ui::Animation* animation) {
-  if (!animation_->IsShowing()) {
-    gtk_widget_hide(widget_.get());
-    if (delegate_)
-      delegate_->Closed();
-  }
-}
-
-// static
-void SlideAnimatorGtk::SetAnimationsForTesting(bool enable) {
-  animations_enabled_ = enable;
-}
-
-// static
-void SlideAnimatorGtk::OnChildSizeAllocate(GtkWidget* child,
-                                           GtkAllocation* allocation,
-                                           SlideAnimatorGtk* slider) {
-  if (slider->child_needs_move_) {
-    gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(slider->widget()),
-                                child, 0, -allocation->height);
-    slider->child_needs_move_ = false;
-  }
-}
diff --git a/chrome/browser/gtk/slide_animator_gtk.h b/chrome/browser/gtk/slide_animator_gtk.h
deleted file mode 100644
index b0f5c73..0000000
--- a/chrome/browser/gtk/slide_animator_gtk.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// A helper class for animating the display of native widget content.
-// Currently only handle vertical sliding, but could be extended to handle
-// horizontal slides or other types of animations.
-//
-// NOTE: This does not handle clipping. If you are not careful, you will
-// wind up with visibly overlapping widgets. If you need clipping, you can
-// extend the constructor to take an option to give |fixed| its own GdkWindow
-// (via gtk_fixed_set_has_window).
-
-#ifndef CHROME_BROWSER_GTK_SLIDE_ANIMATOR_GTK_H_
-#define CHROME_BROWSER_GTK_SLIDE_ANIMATOR_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "ui/base/animation/animation_delegate.h"
-
-namespace ui {
-class SlideAnimation;
-}
-
-class SlideAnimatorGtk : public ui::AnimationDelegate {
- public:
-  class Delegate {
-   public:
-    // Called when a call to Close() finishes animating.
-    virtual void Closed() = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  enum Direction {
-    DOWN,
-    UP
-  };
-
-  // |child| is the widget we pack into |widget_|.
-  // |direction| indicates which side the contents will appear to come from.
-  // |duration| is the duration of the slide in milliseconds, or 0 for default.
-  // |linear| controls how the animation progresses. If true, the
-  // velocity of the slide is constant over time, otherwise it goes a bit faster
-  // at the beginning and slows to a halt.
-  // |delegate| may be NULL.
-  SlideAnimatorGtk(GtkWidget* child,
-                   Direction direction,
-                   int duration,
-                   bool linear,
-                   bool control_child_size,
-                   Delegate* delegate);
-
-  virtual ~SlideAnimatorGtk();
-
-  GtkWidget* widget() { return widget_.get(); }
-
-  // Slide open.
-  void Open();
-
-  // Immediately show the widget.
-  void OpenWithoutAnimation();
-
-  // Slide shut.
-  void Close();
-
-  // End the current animation.
-  void End();
-
-  // Immediately hide the widget.
-  void CloseWithoutAnimation();
-
-  // Returns whether the widget is visible.
-  bool IsShowing();
-
-  // Returns whether the widget is currently showing the close animation.
-  bool IsClosing();
-
-  // Returns whether the widget is currently showing the open or close
-  // animation.
-  bool IsAnimating();
-
-  // ui::AnimationDelegate implementation.
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-
-  // Used during testing; disable or enable animations (default is enabled).
-  static void SetAnimationsForTesting(bool enable);
-
- private:
-  static void OnChildSizeAllocate(GtkWidget* child,
-                                  GtkAllocation* allocation,
-                                  SlideAnimatorGtk* slider);
-
-  scoped_ptr<ui::SlideAnimation> animation_;
-
-  // The top level widget of the SlideAnimatorGtk. It is a GtkFixed.
-  OwnedWidgetGtk widget_;
-
-  // The widget passed to us at construction time, and the only direct child of
-  // |widget_|.
-  GtkWidget* child_;
-
-  // The direction of the slide.
-  Direction direction_;
-
-  // The object to inform about certain events. It may be NULL.
-  Delegate* delegate_;
-
-  // We need to move the child widget to (0, -height), but we don't know its
-  // height until it has been allocated. This variable will be true until the
-  // child widget has been allocated, at which point we will move it, and then
-  // set this variable to false to indicate it should not be moved again.
-  bool child_needs_move_;
-
-  static bool animations_enabled_;
-};
-
-#endif  // CHROME_BROWSER_GTK_SLIDE_ANIMATOR_GTK_H_
diff --git a/chrome/browser/gtk/ssl_client_certificate_selector.cc b/chrome/browser/gtk/ssl_client_certificate_selector.cc
deleted file mode 100644
index edf560a..0000000
--- a/chrome/browser/gtk/ssl_client_certificate_selector.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ssl_client_certificate_selector.h"
-
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "app/l10n_util.h"
-#include "base/i18n/time_formatting.h"
-#include "base/logging.h"
-#include "base/nss_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/certificate_viewer.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/ssl/ssl_client_auth_handler.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/net/x509_certificate_model.h"
-#include "gfx/native_widget_types.h"
-#include "grit/generated_resources.h"
-#include "net/base/x509_certificate.h"
-
-namespace {
-
-enum {
-  RESPONSE_SHOW_CERT_INFO = 1,
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// SSLClientCertificateSelector
-
-class SSLClientCertificateSelector : public ConstrainedDialogDelegate {
- public:
-  explicit SSLClientCertificateSelector(
-      TabContents* parent,
-      net::SSLCertRequestInfo* cert_request_info,
-      SSLClientAuthHandler* delegate);
-  ~SSLClientCertificateSelector();
-
-  void Show();
-
-  // ConstrainedDialogDelegate implementation:
-  virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); }
-  virtual void DeleteDelegate();
-
- private:
-  void PopulateCerts();
-
-  net::X509Certificate* GetSelectedCert();
-
-  static std::string FormatComboBoxText(
-      net::X509Certificate::OSCertHandle cert,
-      const std::string& nickname);
-  static std::string FormatDetailsText(
-      net::X509Certificate::OSCertHandle cert);
-
-  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged);
-  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked);
-  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked);
-  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked);
-  CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown,
-                       GtkWidget*);
-
-  scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
-
-  std::vector<std::string> details_strings_;
-
-  GtkWidget* cert_combo_box_;
-  GtkTextBuffer* cert_details_buffer_;
-
-  scoped_refptr<SSLClientAuthHandler> delegate_;
-
-  OwnedWidgetGtk root_widget_;
-  // Hold on to the select button to focus it.
-  GtkWidget* select_button_;
-
-  TabContents* parent_;
-  ConstrainedWindow* window_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLClientCertificateSelector);
-};
-
-SSLClientCertificateSelector::SSLClientCertificateSelector(
-    TabContents* parent,
-    net::SSLCertRequestInfo* cert_request_info,
-    SSLClientAuthHandler* delegate)
-    : cert_request_info_(cert_request_info),
-      delegate_(delegate),
-      parent_(parent),
-      window_(NULL) {
-  root_widget_.Own(gtk_vbox_new(FALSE, gtk_util::kControlSpacing));
-
-  GtkWidget* site_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(root_widget_.get()), site_vbox,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* site_description_label = gtk_util::CreateBoldLabel(
-      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_SITE_DESCRIPTION_LABEL));
-  gtk_box_pack_start(GTK_BOX(site_vbox), site_description_label,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* site_label = gtk_label_new(
-      cert_request_info->host_and_port.c_str());
-  gtk_util::LeftAlignMisc(site_label);
-  gtk_box_pack_start(GTK_BOX(site_vbox), site_label, FALSE, FALSE, 0);
-
-  GtkWidget* selector_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_box_pack_start(GTK_BOX(root_widget_.get()), selector_vbox,
-                     TRUE, TRUE, 0);
-
-  GtkWidget* choose_description_label = gtk_util::CreateBoldLabel(
-      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CHOOSE_DESCRIPTION_LABEL));
-  gtk_box_pack_start(GTK_BOX(selector_vbox), choose_description_label,
-                     FALSE, FALSE, 0);
-
-
-  cert_combo_box_ = gtk_combo_box_new_text();
-  g_signal_connect(cert_combo_box_, "changed",
-                   G_CALLBACK(OnComboBoxChangedThunk), this);
-  gtk_box_pack_start(GTK_BOX(selector_vbox), cert_combo_box_,
-                     FALSE, FALSE, 0);
-
-  GtkWidget* details_label = gtk_label_new(l10n_util::GetStringUTF8(
-      IDS_CERT_SELECTOR_DETAILS_DESCRIPTION_LABEL).c_str());
-  gtk_util::LeftAlignMisc(details_label);
-  gtk_box_pack_start(GTK_BOX(selector_vbox), details_label, FALSE, FALSE, 0);
-
-  // TODO(mattm): fix text view coloring (should have grey background).
-  GtkWidget* cert_details_view = gtk_text_view_new();
-  gtk_text_view_set_editable(GTK_TEXT_VIEW(cert_details_view), FALSE);
-  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(cert_details_view), GTK_WRAP_WORD);
-  cert_details_buffer_ = gtk_text_view_get_buffer(
-      GTK_TEXT_VIEW(cert_details_view));
-  // We put the details in a frame instead of a scrolled window so that the
-  // entirety will be visible without requiring scrolling or expanding the
-  // dialog.  This does however mean the dialog will grow itself if you switch
-  // to different cert that has longer details text.
-  GtkWidget* details_frame = gtk_frame_new(NULL);
-  gtk_frame_set_shadow_type(GTK_FRAME(details_frame), GTK_SHADOW_ETCHED_IN);
-  gtk_container_add(GTK_CONTAINER(details_frame), cert_details_view);
-  gtk_box_pack_start(GTK_BOX(selector_vbox), details_frame, TRUE, TRUE, 0);
-
-  // And then create a set of buttons like a GtkDialog would.
-  GtkWidget* button_box = gtk_hbutton_box_new();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
-  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
-  gtk_box_pack_end(GTK_BOX(root_widget_.get()), button_box, FALSE, FALSE, 0);
-
-  GtkWidget* view_button = gtk_button_new_with_mnemonic(
-      l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
-  gtk_box_pack_start(GTK_BOX(button_box), view_button, FALSE, FALSE, 0);
-  g_signal_connect(view_button, "clicked",
-                   G_CALLBACK(OnViewClickedThunk), this);
-
-  GtkWidget* cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
-  gtk_box_pack_end(GTK_BOX(button_box), cancel_button, FALSE, FALSE, 0);
-  g_signal_connect(cancel_button, "clicked",
-                   G_CALLBACK(OnCancelClickedThunk), this);
-
-  GtkWidget* select_button = gtk_button_new_from_stock(GTK_STOCK_OK);
-  gtk_box_pack_end(GTK_BOX(button_box), select_button, FALSE, FALSE, 0);
-  g_signal_connect(select_button, "clicked",
-                   G_CALLBACK(OnOkClickedThunk), this);
-
-  // When we are attached to a window, focus the select button.
-  select_button_ = select_button;
-  g_signal_connect(root_widget_.get(), "hierarchy-changed",
-                   G_CALLBACK(OnPromptShownThunk), this);
-  PopulateCerts();
-
-  gtk_widget_show_all(root_widget_.get());
-}
-
-SSLClientCertificateSelector::~SSLClientCertificateSelector() {
-  root_widget_.Destroy();
-}
-
-void SSLClientCertificateSelector::Show() {
-  DCHECK(!window_);
-  window_ = parent_->CreateConstrainedDialog(this);
-}
-
-void SSLClientCertificateSelector::DeleteDelegate() {
-  if (delegate_) {
-    // The dialog was closed by escape key.
-    delegate_->CertificateSelected(NULL);
-  }
-  delete this;
-}
-
-void SSLClientCertificateSelector::PopulateCerts() {
-  std::vector<std::string> nicknames;
-  x509_certificate_model::GetNicknameStringsFromCertList(
-      cert_request_info_->client_certs,
-      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_EXPIRED),
-      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_NOT_YET_VALID),
-      &nicknames);
-
-  DCHECK_EQ(nicknames.size(),
-            cert_request_info_->client_certs.size());
-
-  for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) {
-    net::X509Certificate::OSCertHandle cert =
-        cert_request_info_->client_certs[i]->os_cert_handle();
-
-    details_strings_.push_back(FormatDetailsText(cert));
-
-    gtk_combo_box_append_text(
-        GTK_COMBO_BOX(cert_combo_box_),
-        FormatComboBoxText(cert, nicknames[i]).c_str());
-  }
-
-  // Auto-select the first cert.
-  gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0);
-}
-
-net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() {
-  int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_));
-  if (selected >= 0 &&
-      selected < static_cast<int>(
-          cert_request_info_->client_certs.size()))
-    return cert_request_info_->client_certs[selected];
-  return NULL;
-}
-
-// static
-std::string SSLClientCertificateSelector::FormatComboBoxText(
-    net::X509Certificate::OSCertHandle cert, const std::string& nickname) {
-  std::string rv(nickname);
-  rv += " [";
-  rv += x509_certificate_model::GetSerialNumberHexified(cert, "");
-  rv += ']';
-  return rv;
-}
-
-// static
-std::string SSLClientCertificateSelector::FormatDetailsText(
-    net::X509Certificate::OSCertHandle cert) {
-  std::string rv;
-
-  rv += l10n_util::GetStringFUTF8(
-      IDS_CERT_SUBJECTNAME_FORMAT,
-      UTF8ToUTF16(x509_certificate_model::GetSubjectName(cert)));
-
-  rv += "\n  ";
-  rv += l10n_util::GetStringFUTF8(
-      IDS_CERT_SERIAL_NUMBER_FORMAT,
-      UTF8ToUTF16(
-          x509_certificate_model::GetSerialNumberHexified(cert, "")));
-
-  base::Time issued, expires;
-  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
-    string16 issued_str = base::TimeFormatShortDateAndTime(issued);
-    string16 expires_str = base::TimeFormatShortDateAndTime(expires);
-    rv += "\n  ";
-    rv += l10n_util::GetStringFUTF8(IDS_CERT_VALIDITY_RANGE_FORMAT,
-                                    issued_str, expires_str);
-  }
-
-  std::vector<std::string> usages;
-  x509_certificate_model::GetUsageStrings(cert, &usages);
-  if (usages.size()) {
-    rv += "\n  ";
-    rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_EXTENDED_KEY_USAGE_FORMAT,
-                                    UTF8ToUTF16(JoinString(usages, ',')));
-  }
-
-  std::string key_usage_str = x509_certificate_model::GetKeyUsageString(cert);
-  if (!key_usage_str.empty()) {
-    rv += "\n  ";
-    rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_KEY_USAGE_FORMAT,
-                                    UTF8ToUTF16(key_usage_str));
-  }
-
-  std::vector<std::string> email_addresses;
-  x509_certificate_model::GetEmailAddresses(cert, &email_addresses);
-  if (email_addresses.size()) {
-    rv += "\n  ";
-    rv += l10n_util::GetStringFUTF8(
-        IDS_CERT_EMAIL_ADDRESSES_FORMAT,
-        UTF8ToUTF16(JoinString(email_addresses, ',')));
-  }
-
-  rv += '\n';
-  rv += l10n_util::GetStringFUTF8(
-      IDS_CERT_ISSUERNAME_FORMAT,
-      UTF8ToUTF16(x509_certificate_model::GetIssuerName(cert)));
-
-  string16 token(UTF8ToUTF16(x509_certificate_model::GetTokenName(cert)));
-  if (!token.empty()) {
-    rv += '\n';
-    rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token);
-  }
-
-  return rv;
-}
-
-void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) {
-  int selected = gtk_combo_box_get_active(
-      GTK_COMBO_BOX(cert_combo_box_));
-  if (selected < 0)
-    return;
-  gtk_text_buffer_set_text(cert_details_buffer_,
-                           details_strings_[selected].c_str(),
-                           details_strings_[selected].size());
-}
-
-void SSLClientCertificateSelector::OnViewClicked(GtkWidget* button) {
-  net::X509Certificate* cert = GetSelectedCert();
-  if (cert) {
-    GtkWidget* toplevel = gtk_widget_get_toplevel(root_widget_.get());
-    ShowCertificateViewer(GTK_WINDOW(toplevel), cert);
-  }
-}
-
-void SSLClientCertificateSelector::OnCancelClicked(GtkWidget* button) {
-  delegate_->CertificateSelected(NULL);
-  delegate_ = NULL;
-  DCHECK(window_);
-  window_->CloseConstrainedWindow();
-}
-
-void SSLClientCertificateSelector::OnOkClicked(GtkWidget* button) {
-  net::X509Certificate* cert = GetSelectedCert();
-  delegate_->CertificateSelected(cert);
-  delegate_ = NULL;
-  DCHECK(window_);
-  window_->CloseConstrainedWindow();
-}
-
-void SSLClientCertificateSelector::OnPromptShown(GtkWidget* widget,
-                                                 GtkWidget* previous_toplevel) {
-  if (!root_widget_.get() ||
-      !GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(root_widget_.get())))
-    return;
-  GTK_WIDGET_SET_FLAGS(select_button_, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(select_button_);
-  gtk_widget_grab_focus(select_button_);
-}
-
-}  // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// SSLClientAuthHandler platform specific implementation:
-
-namespace browser {
-
-void ShowSSLClientCertificateSelector(
-    TabContents* parent,
-    net::SSLCertRequestInfo* cert_request_info,
-    SSLClientAuthHandler* delegate) {
-  (new SSLClientCertificateSelector(parent,
-                                    cert_request_info,
-                                    delegate))->Show();
-}
-
-}  // namespace browser
diff --git a/chrome/browser/gtk/status_bubble_gtk.cc b/chrome/browser/gtk/status_bubble_gtk.cc
deleted file mode 100644
index 06c33d0..0000000
--- a/chrome/browser/gtk/status_bubble_gtk.cc
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/status_bubble_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <algorithm>
-
-#include "app/text_elider.h"
-#include "base/i18n/rtl.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "chrome/browser/gtk/slide_animator_gtk.h"
-#include "chrome/common/notification_service.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-// Inner padding between the border and the text label.
-const int kInternalTopBottomPadding = 1;
-const int kInternalLeftRightPadding = 2;
-
-// The radius of the edges of our bubble.
-const int kCornerSize = 3;
-
-// Milliseconds before we hide the status bubble widget when you mouseout.
-const int kHideDelay = 250;
-
-// How close the mouse can get to the infobubble before it starts sliding
-// off-screen.
-const int kMousePadding = 20;
-
-}  // namespace
-
-StatusBubbleGtk::StatusBubbleGtk(Profile* profile)
-    : theme_provider_(GtkThemeProvider::GetFrom(profile)),
-      padding_(NULL),
-      label_(NULL),
-      flip_horizontally_(false),
-      y_offset_(0),
-      download_shelf_is_visible_(false),
-      last_mouse_location_(0, 0),
-      last_mouse_left_content_(false),
-      ignore_next_left_content_(false) {
-  InitWidgets();
-
-  theme_provider_->InitThemesFor(this);
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-StatusBubbleGtk::~StatusBubbleGtk() {
-  container_.Destroy();
-}
-
-void StatusBubbleGtk::SetStatus(const string16& status_text_wide) {
-  std::string status_text = UTF16ToUTF8(status_text_wide);
-  if (status_text_ == status_text)
-    return;
-
-  status_text_ = status_text;
-  if (!status_text_.empty())
-    SetStatusTextTo(status_text_);
-  else if (!url_text_.empty())
-    SetStatusTextTo(url_text_);
-  else
-    SetStatusTextTo(std::string());
-}
-
-void StatusBubbleGtk::SetURL(const GURL& url, const string16& languages) {
-  url_ = url;
-  languages_ = languages;
-
-  // If we want to clear a displayed URL but there is a status still to
-  // display, display that status instead.
-  if (url.is_empty() && !status_text_.empty()) {
-    url_text_ = std::string();
-    SetStatusTextTo(status_text_);
-    return;
-  }
-
-  SetStatusTextToURL();
-}
-
-void StatusBubbleGtk::SetStatusTextToURL() {
-  GtkWidget* parent = gtk_widget_get_parent(container_.get());
-
-  // It appears that parent can be NULL (probably only during shutdown).
-  if (!parent || !GTK_WIDGET_REALIZED(parent))
-    return;
-
-  int desired_width = parent->allocation.width;
-  if (!expanded()) {
-    expand_timer_.Stop();
-    expand_timer_.Start(base::TimeDelta::FromMilliseconds(kExpandHoverDelay),
-                        this, &StatusBubbleGtk::ExpandURL);
-    // When not expanded, we limit the size to one third the browser's
-    // width.
-    desired_width /= 3;
-  }
-
-  // TODO(tc): We don't actually use gfx::Font as the font in the status
-  // bubble.  We should extend gfx::ElideUrl to take some sort of pango font.
-  url_text_ = UTF16ToUTF8(gfx::ElideUrl(url_, gfx::Font(), desired_width,
-                          UTF16ToWideHack(languages_)));
-  SetStatusTextTo(url_text_);
-}
-
-void StatusBubbleGtk::Show() {
-  // If we were going to hide, stop.
-  hide_timer_.Stop();
-
-  gtk_widget_show_all(container_.get());
-  if (container_->window)
-    gdk_window_raise(container_->window);
-}
-
-void StatusBubbleGtk::Hide() {
-  // If we were going to expand the bubble, stop.
-  expand_timer_.Stop();
-  expand_animation_.reset();
-
-  gtk_widget_hide_all(container_.get());
-}
-
-void StatusBubbleGtk::SetStatusTextTo(const std::string& status_utf8) {
-  if (status_utf8.empty()) {
-    hide_timer_.Stop();
-    hide_timer_.Start(base::TimeDelta::FromMilliseconds(kHideDelay),
-                      this, &StatusBubbleGtk::Hide);
-  } else {
-    gtk_label_set_text(GTK_LABEL(label_), status_utf8.c_str());
-    GtkRequisition req;
-    gtk_widget_size_request(label_, &req);
-    desired_width_ = req.width;
-
-    UpdateLabelSizeRequest();
-
-    if (!last_mouse_left_content_) {
-      // Show the padding and label to update our requisition and then
-      // re-process the last mouse event -- if the label was empty before or the
-      // text changed, our size will have changed and we may need to move
-      // ourselves away from the pointer now.
-      gtk_widget_show_all(padding_);
-      MouseMoved(last_mouse_location_, false);
-    }
-    Show();
-  }
-}
-
-void StatusBubbleGtk::MouseMoved(
-    const gfx::Point& location, bool left_content) {
-  if (left_content && ignore_next_left_content_) {
-    ignore_next_left_content_ = false;
-    return;
-  }
-
-  last_mouse_location_ = location;
-  last_mouse_left_content_ = left_content;
-
-  if (!GTK_WIDGET_REALIZED(container_.get()))
-    return;
-
-  GtkWidget* parent = gtk_widget_get_parent(container_.get());
-  if (!parent || !GTK_WIDGET_REALIZED(parent))
-    return;
-
-  int old_y_offset = y_offset_;
-  bool old_flip_horizontally = flip_horizontally_;
-
-  if (left_content) {
-    SetFlipHorizontally(false);
-    y_offset_ = 0;
-  } else {
-    GtkWidget* toplevel = gtk_widget_get_toplevel(container_.get());
-    if (!toplevel || !GTK_WIDGET_REALIZED(toplevel))
-      return;
-
-    bool ltr = !base::i18n::IsRTL();
-
-    GtkRequisition requisition;
-    gtk_widget_size_request(container_.get(), &requisition);
-
-    // Get our base position (that is, not including the current offset)
-    // relative to the origin of the root window.
-    gint toplevel_x = 0, toplevel_y = 0;
-    gdk_window_get_position(toplevel->window, &toplevel_x, &toplevel_y);
-    gfx::Rect parent_rect =
-        gtk_util::GetWidgetRectRelativeToToplevel(parent);
-    gfx::Rect bubble_rect(
-        toplevel_x + parent_rect.x() +
-            (ltr ? 0 : parent->allocation.width - requisition.width),
-        toplevel_y + parent_rect.y() +
-            parent->allocation.height - requisition.height,
-        requisition.width,
-        requisition.height);
-
-    int left_threshold =
-        bubble_rect.x() - bubble_rect.height() - kMousePadding;
-    int right_threshold =
-        bubble_rect.right() + bubble_rect.height() + kMousePadding;
-    int top_threshold = bubble_rect.y() - kMousePadding;
-
-    if (((ltr && location.x() < right_threshold) ||
-         (!ltr && location.x() > left_threshold)) &&
-        location.y() > top_threshold) {
-      if (download_shelf_is_visible_) {
-        SetFlipHorizontally(true);
-        y_offset_ = 0;
-      } else {
-        SetFlipHorizontally(false);
-        int distance = std::max(ltr ?
-                                    location.x() - right_threshold :
-                                    left_threshold - location.x(),
-                                top_threshold - location.y());
-        y_offset_ = std::min(-1 * distance, requisition.height);
-      }
-    } else {
-      SetFlipHorizontally(false);
-      y_offset_ = 0;
-    }
-  }
-
-  if (y_offset_ != old_y_offset || flip_horizontally_ != old_flip_horizontally)
-    gtk_widget_queue_resize_no_redraw(parent);
-}
-
-void StatusBubbleGtk::UpdateDownloadShelfVisibility(bool visible) {
-  download_shelf_is_visible_ = visible;
-}
-
-void StatusBubbleGtk::Observe(NotificationType type,
-                              const NotificationSource& source,
-                              const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    UserChangedTheme();
-  }
-}
-
-void StatusBubbleGtk::InitWidgets() {
-  bool ltr = !base::i18n::IsRTL();
-
-  label_ = gtk_label_new(NULL);
-
-  padding_ = gtk_alignment_new(0, 0, 1, 1);
-  gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
-      kInternalTopBottomPadding, kInternalTopBottomPadding,
-      kInternalLeftRightPadding + (ltr ? 0 : kCornerSize),
-      kInternalLeftRightPadding + (ltr ? kCornerSize : 0));
-  gtk_container_add(GTK_CONTAINER(padding_), label_);
-
-  container_.Own(gtk_event_box_new());
-  gtk_util::ActAsRoundedWindow(
-      container_.get(), gtk_util::kGdkWhite, kCornerSize,
-      gtk_util::ROUNDED_TOP_RIGHT,
-      gtk_util::BORDER_TOP | gtk_util::BORDER_RIGHT);
-  gtk_widget_set_name(container_.get(), "status-bubble");
-  gtk_container_add(GTK_CONTAINER(container_.get()), padding_);
-
-  // We need to listen for mouse motion events, since a fast-moving pointer may
-  // enter our window without us getting any motion events on the browser near
-  // enough for us to run away.
-  gtk_widget_add_events(container_.get(), GDK_POINTER_MOTION_MASK |
-                                          GDK_ENTER_NOTIFY_MASK);
-  g_signal_connect(container_.get(), "motion-notify-event",
-                   G_CALLBACK(HandleMotionNotifyThunk), this);
-  g_signal_connect(container_.get(), "enter-notify-event",
-                   G_CALLBACK(HandleEnterNotifyThunk), this);
-
-  UserChangedTheme();
-}
-
-void StatusBubbleGtk::UserChangedTheme() {
-  if (theme_provider_->UseGtkTheme()) {
-    gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, NULL);
-    gtk_widget_modify_bg(container_.get(), GTK_STATE_NORMAL, NULL);
-  } else {
-    // TODO(erg): This is the closest to "text that will look good on a
-    // toolbar" that I can find. Maybe in later iterations of the theme system,
-    // there will be a better color to pick.
-    GdkColor bookmark_text =
-        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
-    gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, &bookmark_text);
-
-    GdkColor toolbar_color =
-        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
-    gtk_widget_modify_bg(container_.get(), GTK_STATE_NORMAL, &toolbar_color);
-  }
-
-  gtk_util::SetRoundedWindowBorderColor(container_.get(),
-                                        theme_provider_->GetBorderColor());
-}
-
-void StatusBubbleGtk::SetFlipHorizontally(bool flip_horizontally) {
-  if (flip_horizontally == flip_horizontally_)
-    return;
-
-  flip_horizontally_ = flip_horizontally;
-
-  bool ltr = !base::i18n::IsRTL();
-  bool on_left = (ltr && !flip_horizontally) || (!ltr && flip_horizontally);
-
-  gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
-      kInternalTopBottomPadding, kInternalTopBottomPadding,
-      kInternalLeftRightPadding + (on_left ? 0 : kCornerSize),
-      kInternalLeftRightPadding + (on_left ? kCornerSize : 0));
-  // The rounded window code flips these arguments if we're RTL.
-  gtk_util::SetRoundedWindowEdgesAndBorders(
-      container_.get(),
-      kCornerSize,
-      flip_horizontally ?
-          gtk_util::ROUNDED_TOP_LEFT :
-          gtk_util::ROUNDED_TOP_RIGHT,
-      gtk_util::BORDER_TOP |
-          (flip_horizontally ? gtk_util::BORDER_LEFT : gtk_util::BORDER_RIGHT));
-  gtk_widget_queue_draw(container_.get());
-}
-
-void StatusBubbleGtk::ExpandURL() {
-  start_width_ = label_->allocation.width;
-  expand_animation_.reset(new ui::SlideAnimation(this));
-  expand_animation_->SetTweenType(ui::Tween::LINEAR);
-  expand_animation_->Show();
-
-  SetStatusTextToURL();
-}
-
-void StatusBubbleGtk::UpdateLabelSizeRequest() {
-  if (!expanded() || !expand_animation_->is_animating()) {
-    gtk_widget_set_size_request(label_, -1, -1);
-    return;
-  }
-
-  int new_width = start_width_ +
-      (desired_width_ - start_width_) * expand_animation_->GetCurrentValue();
-  gtk_widget_set_size_request(label_, new_width, -1);
-}
-
-// See http://crbug.com/68897 for why we have to handle this event.
-gboolean StatusBubbleGtk::HandleEnterNotify(GtkWidget* sender,
-                                            GdkEventCrossing* event) {
-  ignore_next_left_content_ = true;
-  MouseMoved(gfx::Point(event->x_root, event->y_root), false);
-  return FALSE;
-}
-
-gboolean StatusBubbleGtk::HandleMotionNotify(GtkWidget* sender,
-                                             GdkEventMotion* event) {
-  MouseMoved(gfx::Point(event->x_root, event->y_root), false);
-  return FALSE;
-}
-
-void StatusBubbleGtk::AnimationEnded(const ui::Animation* animation) {
-  UpdateLabelSizeRequest();
-}
-
-void StatusBubbleGtk::AnimationProgressed(const ui::Animation* animation) {
-  UpdateLabelSizeRequest();
-}
diff --git a/chrome/browser/gtk/status_bubble_gtk.h b/chrome/browser/gtk/status_bubble_gtk.h
deleted file mode 100644
index fcbf7a0..0000000
--- a/chrome/browser/gtk/status_bubble_gtk.h
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_STATUS_BUBBLE_GTK_H_
-#define CHROME_BROWSER_GTK_STATUS_BUBBLE_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "base/timer.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/ui/status_bubble.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/point.h"
-#include "googleurl/src/gurl.h"
-#include "ui/base/animation/animation_delegate.h"
-
-class GtkThemeProvider;
-class Profile;
-
-namespace ui {
-class SlideAnimation;
-}
-
-// GTK implementation of StatusBubble. Unlike Windows, our status bubble
-// doesn't have the nice leave-the-window effect since we can't rely on the
-// window manager to not try to be "helpful" and center our popups, etc.
-// We therefore position it absolutely in a GtkFixed, that we don't own.
-class StatusBubbleGtk : public StatusBubble,
-                        public NotificationObserver,
-                        public ui::AnimationDelegate {
- public:
-  explicit StatusBubbleGtk(Profile* profile);
-  virtual ~StatusBubbleGtk();
-
-  bool flip_horizontally() const { return flip_horizontally_; }
-  int y_offset() const { return y_offset_; }
-
-  // StatusBubble implementation.
-  virtual void SetStatus(const string16& status);
-  virtual void SetURL(const GURL& url, const string16& languages);
-  virtual void Hide();
-  virtual void MouseMoved(const gfx::Point& location, bool left_content);
-
-  // ui::AnimationDelegate implementation.
-  virtual void AnimationEnded(const ui::Animation* animation);
-  virtual void AnimationProgressed(const ui::Animation* animation);
-
-  // Called when the download shelf becomes visible or invisible.
-  // This is used by to ensure that the status bubble does not obscure
-  // the download shelf, when it is visible.
-  virtual void UpdateDownloadShelfVisibility(bool visible);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Top of the widget hierarchy for a StatusBubble. This top level widget is
-  // guarenteed to have its gtk_widget_name set to "status-bubble" for
-  // identification.
-  GtkWidget* widget() { return container_.get(); }
-
- private:
-  // Sets the text of the label widget and controls visibility. (As contrasted
-  // with setting the current status or URL text, which may be ignored for now).
-  void SetStatusTextTo(const std::string& status_utf8);
-
-  // Sets the status text to the current value of |url_|, eliding it as
-  // necessary.
-  void SetStatusTextToURL();
-
-  // Sets the status bubble's location in the parent GtkFixed, shows the widget
-  // and makes sure that the status bubble has the highest z-order.
-  void Show();
-
-  // Builds the widgets, containers, etc.
-  void InitWidgets();
-
-  // Notification from the window that we should retheme ourself.
-  void UserChangedTheme();
-
-  // Sets whether the bubble should be flipped horizontally and displayed on the
-  // opposite side of the tab contents.  Reshapes the container and queues a
-  // redraw if necessary.
-  void SetFlipHorizontally(bool flip_horizontally);
-
-  // Expand the bubble up to the full width of the browser, so that the entire
-  // URL may be seen. Called after the user hovers over a link for sufficient
-  // time.
-  void ExpandURL();
-
-  // Adjust the actual size of the bubble by changing the label's size request.
-  void UpdateLabelSizeRequest();
-
-  // Returns true if the status bubble is in the expand-state (i.e., is
-  // currently expanded or in the process of expanding).
-  bool expanded() {
-    return expand_animation_.get();
-  }
-
-  CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleMotionNotify,
-                       GdkEventMotion*);
-
-  CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleEnterNotify,
-                       GdkEventCrossing*);
-
-  NotificationRegistrar registrar_;
-
-  // Provides colors.
-  GtkThemeProvider* theme_provider_;
-
-  // The toplevel event box.
-  OwnedWidgetGtk container_;
-
-  // The GtkAlignment holding |label_|.
-  GtkWidget* padding_;
-
-  // The GtkLabel holding the text.
-  GtkWidget* label_;
-
-  // The status text we want to display when there are no URLs to display.
-  std::string status_text_;
-
-  // The URL we are displaying for.
-  GURL url_;
-
-  // The possibly elided url text we want to display.
-  std::string url_text_;
-
-  // Used to determine the character set that the user can read (for eliding
-  // the url text).
-  string16 languages_;
-
-  // A timer that hides our window after a delay.
-  base::OneShotTimer<StatusBubbleGtk> hide_timer_;
-
-  // A timer that expands our window after a delay.
-  base::OneShotTimer<StatusBubbleGtk> expand_timer_;
-
-  // The animation for resizing the status bubble on long hovers.
-  scoped_ptr<ui::SlideAnimation> expand_animation_;
-
-  // The start and end width of the current resize animation.
-  int start_width_;
-  int desired_width_;
-
-  // Should the bubble be flipped horizontally (e.g. displayed on the right for
-  // an LTR language)?  We move the bubble to the other side of the tab contents
-  // rather than sliding it down when the download shelf is visible.
-  bool flip_horizontally_;
-
-  // Vertical offset used to hide the status bubble as the pointer nears it.
-  int y_offset_;
-
-  // If the download shelf is visible, do not obscure it.
-  bool download_shelf_is_visible_;
-
-  // 'location' and 'left_content' values from the last invocation of
-  // MouseMoved().  We hang onto these so we can move the bubble if necessary
-  // when its text changes, triggering a size change.
-  gfx::Point last_mouse_location_;
-  bool last_mouse_left_content_;
-
-  // Shortly after the cursor enters the status bubble, we'll get a message
-  // that the cursor left the content area. This lets us ignore that.
-  bool ignore_next_left_content_;
-};
-
-#endif  // CHROME_BROWSER_GTK_STATUS_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/status_icons/status_icon_gtk.cc b/chrome/browser/gtk/status_icons/status_icon_gtk.cc
deleted file mode 100644
index 7268b00..0000000
--- a/chrome/browser/gtk/status_icons/status_icon_gtk.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/status_icons/status_icon_gtk.h"
-
-#include "base/string16.h"
-#include "base/logging.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "gfx/gtk_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-StatusIconGtk::StatusIconGtk() {
-  icon_ = gtk_status_icon_new();
-  gtk_status_icon_set_visible(icon_, TRUE);
-
-  g_signal_connect(icon_, "activate",
-                   G_CALLBACK(OnClickThunk), this);
-  g_signal_connect(icon_, "popup-menu",
-                   G_CALLBACK(OnPopupMenuThunk), this);
-}
-
-StatusIconGtk::~StatusIconGtk() {
-  g_object_unref(icon_);
-}
-
-void StatusIconGtk::SetImage(const SkBitmap& image) {
-  if (image.isNull())
-    return;
-
-  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&image);
-  gtk_status_icon_set_from_pixbuf(icon_, pixbuf);
-  g_object_unref(pixbuf);
-}
-
-void StatusIconGtk::SetPressedImage(const SkBitmap& image) {
-  // Ignore pressed images, since the standard on Linux is to not highlight
-  // pressed status icons.
-}
-
-void StatusIconGtk::SetToolTip(const string16& tool_tip) {
-  gtk_status_icon_set_tooltip(icon_, UTF16ToUTF8(tool_tip).c_str());
-}
-
-void StatusIconGtk::OnClick(GtkWidget* widget) {
-  DispatchClickEvent();
-}
-
-void StatusIconGtk::UpdatePlatformContextMenu(menus::MenuModel* model) {
-  if (!model)
-    menu_.reset();
-  else
-    menu_.reset(new MenuGtk(NULL, model));
-}
-
-void StatusIconGtk::OnPopupMenu(GtkWidget* widget, guint button, guint time) {
-  // If we have a menu - display it.
-  if (menu_.get())
-    menu_->PopupAsContextForStatusIcon(time, button, icon_);
-}
diff --git a/chrome/browser/gtk/status_icons/status_icon_gtk.h b/chrome/browser/gtk/status_icons/status_icon_gtk.h
deleted file mode 100644
index 7053ed5..0000000
--- a/chrome/browser/gtk/status_icons/status_icon_gtk.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_STATUS_ICONS_STATUS_ICON_GTK_H_
-#define CHROME_BROWSER_GTK_STATUS_ICONS_STATUS_ICON_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "chrome/browser/status_icons/status_icon.h"
-
-class MenuGtk;
-class SkBitmap;
-
-class StatusIconGtk : public StatusIcon {
- public:
-  StatusIconGtk();
-  virtual ~StatusIconGtk();
-
-  // Overridden from StatusIcon:
-  virtual void SetImage(const SkBitmap& image);
-  virtual void SetPressedImage(const SkBitmap& image);
-  virtual void SetToolTip(const string16& tool_tip);
-
-  // Exposed for testing.
-  CHROMEGTK_CALLBACK_0(StatusIconGtk, void, OnClick);
-
- protected:
-  // Overridden from StatusIcon.
-  virtual void UpdatePlatformContextMenu(menus::MenuModel* menu);
-
- private:
-  // Callback invoked when user right-clicks on the status icon.
-  CHROMEGTK_CALLBACK_2(StatusIconGtk, void, OnPopupMenu, guint, guint);
-
-  // The currently-displayed icon for the window.
-  GtkStatusIcon* icon_;
-
-  // The context menu for this icon (if any).
-  scoped_ptr<MenuGtk> menu_;
-
-  DISALLOW_COPY_AND_ASSIGN(StatusIconGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_STATUS_ICONS_STATUS_ICON_GTK_H_
diff --git a/chrome/browser/gtk/status_icons/status_tray_gtk.cc b/chrome/browser/gtk/status_icons/status_tray_gtk.cc
deleted file mode 100644
index 98cf98c..0000000
--- a/chrome/browser/gtk/status_icons/status_tray_gtk.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/status_icons/status_tray_gtk.h"
-
-#include "chrome/browser/gtk/status_icons/status_icon_gtk.h"
-
-StatusTrayGtk::StatusTrayGtk() {
-}
-
-StatusTrayGtk::~StatusTrayGtk() {
-}
-
-StatusIcon* StatusTrayGtk::CreatePlatformStatusIcon() {
-  return new StatusIconGtk();
-}
-
-StatusTray* StatusTray::Create() {
-  return new StatusTrayGtk();
-}
diff --git a/chrome/browser/gtk/status_icons/status_tray_gtk.h b/chrome/browser/gtk/status_icons/status_tray_gtk.h
deleted file mode 100644
index 5e0241b..0000000
--- a/chrome/browser/gtk/status_icons/status_tray_gtk.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_STATUS_ICONS_STATUS_TRAY_GTK_H_
-#define CHROME_BROWSER_GTK_STATUS_ICONS_STATUS_TRAY_GTK_H_
-#pragma once
-
-#include "chrome/browser/status_icons/status_tray.h"
-
-class StatusTrayGtk : public StatusTray {
- public:
-  StatusTrayGtk();
-  ~StatusTrayGtk();
-
- protected:
-  // Overriden from StatusTray:
-  virtual StatusIcon* CreatePlatformStatusIcon();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(StatusTrayGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_STATUS_ICONS_STATUS_TRAY_GTK_H_
diff --git a/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc b/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc
deleted file mode 100644
index 0e28e9e..0000000
--- a/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/menus/simple_menu_model.h"
-#include "app/resource_bundle.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/status_icons/status_icon_gtk.h"
-#include "chrome/browser/gtk/status_icons/status_tray_gtk.h"
-#include "grit/browser_resources.h"
-#include "grit/theme_resources.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class MockStatusIconObserver : public StatusIcon::Observer {
- public:
-  MOCK_METHOD0(OnClicked, void());
-};
-
-TEST(StatusTrayGtkTest, CreateTray) {
-  // Just tests creation/destruction.
-  StatusTrayGtk tray;
-}
-
-TEST(StatusTrayGtkTest, CreateIcon) {
-  // Create an icon, set the images and tooltip, then shut it down.
-  StatusTrayGtk tray;
-  StatusIcon* icon = tray.CreateStatusIcon();
-  SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed(
-      IDR_STATUS_TRAY_ICON);
-  icon->SetImage(*bitmap);
-  icon->SetPressedImage(*bitmap);
-  icon->SetToolTip(ASCIIToUTF16("tool tip"));
-  menus::SimpleMenuModel* menu = new menus::SimpleMenuModel(NULL);
-  menu->AddItem(0, ASCIIToUTF16("foo"));
-  icon->SetContextMenu(menu);
-}
-
-TEST(StatusTrayGtkTest, ClickOnIcon) {
-  // Create an icon, send a fake click event, make sure observer is called.
-  StatusTrayGtk tray;
-  StatusIconGtk* icon = static_cast<StatusIconGtk*>(tray.CreateStatusIcon());
-  MockStatusIconObserver observer;
-  icon->AddObserver(&observer);
-  EXPECT_CALL(observer, OnClicked());
-  // Mimic a click.
-  icon->OnClick(NULL);
-  icon->RemoveObserver(&observer);
-}
-
-}  // namespace
diff --git a/chrome/browser/gtk/tab_contents_container_gtk.cc b/chrome/browser/gtk/tab_contents_container_gtk.cc
deleted file mode 100644
index b189e81..0000000
--- a/chrome/browser/gtk/tab_contents_container_gtk.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tab_contents_container_gtk.h"
-
-#include <algorithm>
-
-#include "base/i18n/rtl.h"
-#include "chrome/browser/gtk/gtk_expanded_container.h"
-#include "chrome/browser/gtk/gtk_floating_container.h"
-#include "chrome/browser/gtk/status_bubble_gtk.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
-#include "chrome/common/notification_source.h"
-#include "gfx/native_widget_types.h"
-
-TabContentsContainerGtk::TabContentsContainerGtk(StatusBubbleGtk* status_bubble)
-    : tab_contents_(NULL),
-      preview_contents_(NULL),
-      status_bubble_(status_bubble) {
-  Init();
-}
-
-TabContentsContainerGtk::~TabContentsContainerGtk() {
-  floating_.Destroy();
-}
-
-void TabContentsContainerGtk::Init() {
-  // A high level overview of the TabContentsContainer:
-  //
-  // +- GtkFloatingContainer |floating_| -------------------------------+
-  // |+- GtkExpandedContainer |expanded_| -----------------------------+|
-  // ||                                                                ||
-  // ||                                                                ||
-  // ||                                                                ||
-  // ||                                                                ||
-  // |+- (StatusBubble) ------+                                        ||
-  // |+                       +                                        ||
-  // |+-----------------------+----------------------------------------+|
-  // +------------------------------------------------------------------+
-
-  floating_.Own(gtk_floating_container_new());
-  gtk_widget_set_name(floating_.get(), "chrome-tab-contents-container");
-  g_signal_connect(floating_.get(), "focus", G_CALLBACK(OnFocusThunk), this);
-
-  expanded_ = gtk_expanded_container_new();
-  gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_);
-
-  if (status_bubble_) {
-    gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
-                                        status_bubble_->widget());
-    g_signal_connect(floating_.get(), "set-floating-position",
-                     G_CALLBACK(OnSetFloatingPosition), this);
-  }
-
-  gtk_widget_show(expanded_);
-  gtk_widget_show(floating_.get());
-
-  ViewIDUtil::SetDelegateForWidget(widget(), this);
-}
-
-void TabContentsContainerGtk::SetTabContents(TabContents* tab_contents) {
-  HideTabContents(tab_contents_);
-  if (tab_contents_) {
-    registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
-                      Source<TabContents>(tab_contents_));
-  }
-
-  tab_contents_ = tab_contents;
-
-  if (tab_contents_ == preview_contents_) {
-    // If the preview contents is becoming the new permanent tab contents, we
-    // just reassign some pointers.
-    preview_contents_ = NULL;
-  } else if (tab_contents_) {
-    // Otherwise we actually have to add it to the widget hierarchy.
-    PackTabContents(tab_contents);
-    registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
-                   Source<TabContents>(tab_contents_));
-  }
-}
-
-TabContents* TabContentsContainerGtk::GetVisibleTabContents() {
-  return preview_contents_ ? preview_contents_ : tab_contents_;
-}
-
-void TabContentsContainerGtk::SetPreviewContents(TabContents* preview) {
-  if (preview_contents_)
-    RemovePreviewContents();
-  else
-    HideTabContents(tab_contents_);
-
-  preview_contents_ = preview;
-
-  PackTabContents(preview);
-  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
-                 Source<TabContents>(preview_contents_));
-}
-
-void TabContentsContainerGtk::RemovePreviewContents() {
-  if (!preview_contents_)
-    return;
-
-  HideTabContents(preview_contents_);
-
-  GtkWidget* preview_widget = preview_contents_->GetNativeView();
-  if (preview_widget)
-    gtk_container_remove(GTK_CONTAINER(expanded_), preview_widget);
-
-  registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
-                    Source<TabContents>(preview_contents_));
-  preview_contents_ = NULL;
-}
-
-void TabContentsContainerGtk::PopPreviewContents() {
-  if (!preview_contents_)
-    return;
-
-  RemovePreviewContents();
-
-  PackTabContents(tab_contents_);
-}
-
-void TabContentsContainerGtk::PackTabContents(TabContents* contents) {
-  if (!contents)
-    return;
-
-  gfx::NativeView widget = contents->GetNativeView();
-  if (widget) {
-    if (widget->parent != expanded_)
-      gtk_container_add(GTK_CONTAINER(expanded_), widget);
-    gtk_widget_show(widget);
-  }
-
-  // We need to make sure that we are below the findbar.
-  // Sometimes the content native view will be null.
-  if (contents->GetContentNativeView()) {
-    GdkWindow* content_gdk_window =
-        contents->GetContentNativeView()->window;
-    if (content_gdk_window)
-      gdk_window_lower(content_gdk_window);
-  }
-
-  contents->ShowContents();
-}
-
-void TabContentsContainerGtk::HideTabContents(TabContents* contents) {
-  if (!contents)
-    return;
-
-  gfx::NativeView widget = contents->GetNativeView();
-  if (widget)
-    gtk_widget_hide(widget);
-
-  contents->WasHidden();
-}
-
-void TabContentsContainerGtk::DetachTabContents(TabContents* tab_contents) {
-  gfx::NativeView widget = tab_contents->GetNativeView();
-
-  // It is possible to detach an unrealized, unparented TabContents if you
-  // slow things down enough in valgrind. Might happen in the real world, too.
-  if (widget && widget->parent) {
-    DCHECK_EQ(widget->parent, expanded_);
-    gtk_container_remove(GTK_CONTAINER(expanded_), widget);
-  }
-}
-
-void TabContentsContainerGtk::Observe(NotificationType type,
-                                      const NotificationSource& source,
-                                      const NotificationDetails& details) {
-  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
-
-  TabContentsDestroyed(Source<TabContents>(source).ptr());
-}
-
-void TabContentsContainerGtk::TabContentsDestroyed(TabContents* contents) {
-  // Sometimes, a TabContents is destroyed before we know about it. This allows
-  // us to clean up our state in case this happens.
-  if (contents == preview_contents_)
-    PopPreviewContents();
-  else if (contents == tab_contents_)
-    SetTabContents(NULL);
-  else
-    NOTREACHED();
-}
-
-// Prevent |preview_contents_| from getting focus via the tab key. If
-// |tab_contents_| exists, try to focus that. Otherwise, do nothing, but stop
-// event propagation. See bug http://crbug.com/63365
-gboolean TabContentsContainerGtk::OnFocus(GtkWidget* widget,
-                                          GtkDirectionType focus) {
-  if (preview_contents_) {
-    gtk_widget_child_focus(tab_contents_->GetContentNativeView(), focus);
-    return TRUE;
-  }
-
-  // No preview contents; let the default handler run.
-  return FALSE;
-}
-
-// -----------------------------------------------------------------------------
-// ViewIDUtil::Delegate implementation
-
-GtkWidget* TabContentsContainerGtk::GetWidgetForViewID(ViewID view_id) {
-  if (view_id == VIEW_ID_TAB_CONTAINER ||
-      view_id == VIEW_ID_TAB_CONTAINER_FOCUS_VIEW) {
-    return widget();
-  }
-
-  return NULL;
-}
-
-// -----------------------------------------------------------------------------
-
-// static
-void TabContentsContainerGtk::OnSetFloatingPosition(
-    GtkFloatingContainer* floating_container, GtkAllocation* allocation,
-    TabContentsContainerGtk* tab_contents_container) {
-  StatusBubbleGtk* status = tab_contents_container->status_bubble_;
-
-  // Look at the size request of the status bubble and tell the
-  // GtkFloatingContainer where we want it positioned.
-  GtkRequisition requisition;
-  gtk_widget_size_request(status->widget(), &requisition);
-
-  bool ltr = !base::i18n::IsRTL();
-
-  GValue value = { 0, };
-  g_value_init(&value, G_TYPE_INT);
-  if (ltr ^ status->flip_horizontally())  // Is it on the left?
-    g_value_set_int(&value, 0);
-  else
-    g_value_set_int(&value, allocation->width - requisition.width);
-  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
-                                   status->widget(), "x", &value);
-
-  int child_y = std::max(allocation->height - requisition.height, 0);
-  g_value_set_int(&value, child_y + status->y_offset());
-  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
-                                   status->widget(), "y", &value);
-  g_value_unset(&value);
-}
diff --git a/chrome/browser/gtk/tab_contents_container_gtk.h b/chrome/browser/gtk/tab_contents_container_gtk.h
deleted file mode 100644
index 13d6bf0..0000000
--- a/chrome/browser/gtk/tab_contents_container_gtk.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H_
-#define CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class RenderViewHost;
-class StatusBubbleGtk;
-class TabContents;
-
-typedef struct _GtkFloatingContainer GtkFloatingContainer;
-
-class TabContentsContainerGtk : public NotificationObserver,
-                                public ViewIDUtil::Delegate {
- public:
-  explicit TabContentsContainerGtk(StatusBubbleGtk* status_bubble);
-  ~TabContentsContainerGtk();
-
-  void Init();
-
-  // Make the specified tab visible.
-  void SetTabContents(TabContents* tab_contents);
-  TabContents* GetTabContents() const { return tab_contents_; }
-
-  // Gets the tab contents currently being displayed (either |tab_contents_| or
-  // |preview_contents_|).
-  TabContents* GetVisibleTabContents();
-
-  void SetPreviewContents(TabContents* preview);
-  void PopPreviewContents();
-
-  // Remove the tab from the hierarchy.
-  void DetachTabContents(TabContents* tab_contents);
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  GtkWidget* widget() { return floating_.get(); }
-
-  // ViewIDUtil::Delegate implementation ---------------------------------------
-  virtual GtkWidget* GetWidgetForViewID(ViewID id);
-
- private:
-  // Called when a TabContents is destroyed. This gives us a chance to clean
-  // up our internal state if the TabContents is somehow destroyed before we
-  // get notified.
-  void TabContentsDestroyed(TabContents* contents);
-
-  // Handler for |floating_|'s "set-floating-position" signal. During this
-  // callback, we manually set the position of the status bubble.
-  static void OnSetFloatingPosition(
-      GtkFloatingContainer* container, GtkAllocation* allocation,
-      TabContentsContainerGtk* tab_contents_container);
-
-  // Add |contents| to the container and start showing it.
-  void PackTabContents(TabContents* contents);
-
-  // Stop showing |contents|.
-  void HideTabContents(TabContents* contents);
-
-  // Removes |preview_contents_|.
-  void RemovePreviewContents();
-
-  // Handle focus traversal on the tab contents container. Focus should not
-  // traverse to the preview contents.
-  CHROMEGTK_CALLBACK_1(TabContentsContainerGtk, gboolean, OnFocus,
-                       GtkDirectionType);
-
-  NotificationRegistrar registrar_;
-
-  // The TabContents for the currently selected tab. This will be showing unless
-  // there is a preview contents.
-  TabContents* tab_contents_;
-
-  // The current preview contents (for instant). If non-NULL, it will be
-  // visible.
-  TabContents* preview_contents_;
-
-  // The status bubble manager.  Always non-NULL.
-  StatusBubbleGtk* status_bubble_;
-
-  // Top of the TabContentsContainerGtk widget hierarchy. A cross between a
-  // GtkBin and a GtkFixed, |floating_| has |expanded_| as its one "real" child,
-  // and the various things that hang off the bottom (status bubble, etc) have
-  // their positions manually set in OnSetFloatingPosition.
-  OwnedWidgetGtk floating_;
-
-  // We insert and remove TabContents GtkWidgets into this expanded_. This
-  // should not be a GtkVBox since there were errors with timing where the vbox
-  // was horizontally split with the top half displaying the current TabContents
-  // and bottom half displaying the loading page.
-  GtkWidget* expanded_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabContentsContainerGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H_
diff --git a/chrome/browser/gtk/tab_contents_drag_source.cc b/chrome/browser/gtk/tab_contents_drag_source.cc
deleted file mode 100644
index 13e2196..0000000
--- a/chrome/browser/gtk/tab_contents_drag_source.cc
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tab_contents_drag_source.h"
-
-#include <string>
-
-#include "app/gtk_dnd_util.h"
-#include "base/file_util.h"
-#include "base/mime_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/download/download_util.h"
-#include "chrome/browser/download/drag_download_file.h"
-#include "chrome/browser/download/drag_download_util.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "gfx/gtk_util.h"
-#include "net/base/file_stream.h"
-#include "net/base/net_util.h"
-#include "webkit/glue/webdropdata.h"
-
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
-using WebKit::WebDragOperationNone;
-
-TabContentsDragSource::TabContentsDragSource(
-    TabContentsView* tab_contents_view)
-    : tab_contents_view_(tab_contents_view),
-      drag_pixbuf_(NULL),
-      drag_failed_(false),
-      drag_widget_(gtk_invisible_new()),
-      drag_icon_(gtk_window_new(GTK_WINDOW_POPUP)) {
-  signals_.Connect(drag_widget_, "drag-failed",
-                   G_CALLBACK(OnDragFailedThunk), this);
-  signals_.Connect(drag_widget_, "drag-begin",
-                   G_CALLBACK(OnDragBeginThunk),
-                   this);
-  signals_.Connect(drag_widget_, "drag-end",
-                   G_CALLBACK(OnDragEndThunk), this);
-  signals_.Connect(drag_widget_, "drag-data-get",
-                   G_CALLBACK(OnDragDataGetThunk), this);
-
-  signals_.Connect(drag_icon_, "expose-event",
-                   G_CALLBACK(OnDragIconExposeThunk), this);
-}
-
-TabContentsDragSource::~TabContentsDragSource() {
-  // Break the current drag, if any.
-  if (drop_data_.get()) {
-    gtk_grab_add(drag_widget_);
-    gtk_grab_remove(drag_widget_);
-    MessageLoopForUI::current()->RemoveObserver(this);
-    drop_data_.reset();
-  }
-
-  gtk_widget_destroy(drag_widget_);
-  gtk_widget_destroy(drag_icon_);
-}
-
-TabContents* TabContentsDragSource::tab_contents() const {
-  return tab_contents_view_->tab_contents();
-}
-
-void TabContentsDragSource::StartDragging(const WebDropData& drop_data,
-                                          WebDragOperationsMask allowed_ops,
-                                          GdkEventButton* last_mouse_down,
-                                          const SkBitmap& image,
-                                          const gfx::Point& image_offset) {
-  int targets_mask = 0;
-
-  if (!drop_data.plain_text.empty())
-    targets_mask |= gtk_dnd_util::TEXT_PLAIN;
-  if (drop_data.url.is_valid()) {
-    targets_mask |= gtk_dnd_util::TEXT_URI_LIST;
-    targets_mask |= gtk_dnd_util::CHROME_NAMED_URL;
-    targets_mask |= gtk_dnd_util::NETSCAPE_URL;
-  }
-  if (!drop_data.text_html.empty())
-    targets_mask |= gtk_dnd_util::TEXT_HTML;
-  if (!drop_data.file_contents.empty())
-    targets_mask |= gtk_dnd_util::CHROME_WEBDROP_FILE_CONTENTS;
-  if (!drop_data.download_metadata.empty() &&
-      drag_download_util::ParseDownloadMetadata(drop_data.download_metadata,
-                                                &wide_download_mime_type_,
-                                                &download_file_name_,
-                                                &download_url_)) {
-    targets_mask |= gtk_dnd_util::DIRECT_SAVE_FILE;
-  }
-
-  if (targets_mask == 0) {
-    NOTIMPLEMENTED();
-    if (tab_contents()->render_view_host())
-      tab_contents()->render_view_host()->DragSourceSystemDragEnded();
-  }
-
-  drop_data_.reset(new WebDropData(drop_data));
-
-  // The image we get from WebKit makes heavy use of alpha-shading. This looks
-  // bad on non-compositing WMs. Fall back to the default drag icon.
-  if (!image.isNull() && gtk_util::IsScreenComposited())
-    drag_pixbuf_ = gfx::GdkPixbufFromSkBitmap(&image);
-  image_offset_ = image_offset;
-
-  GtkTargetList* list = gtk_dnd_util::GetTargetListFromCodeMask(targets_mask);
-  if (targets_mask & gtk_dnd_util::CHROME_WEBDROP_FILE_CONTENTS) {
-    drag_file_mime_type_ = gdk_atom_intern(
-        mime_util::GetDataMimeType(drop_data.file_contents).c_str(), FALSE);
-    gtk_target_list_add(list, drag_file_mime_type_,
-                        0, gtk_dnd_util::CHROME_WEBDROP_FILE_CONTENTS);
-  }
-
-  drag_failed_ = false;
-  // If we don't pass an event, GDK won't know what event time to start grabbing
-  // mouse events. Technically it's the mouse motion event and not the mouse
-  // down event that causes the drag, but there's no reliable way to know
-  // *which* motion event initiated the drag, so this will have to do.
-  // TODO(estade): This can sometimes be very far off, e.g. if the user clicks
-  // and holds and doesn't start dragging for a long time. I doubt it matters
-  // much, but we should probably look into the possibility of getting the
-  // initiating event from webkit.
-  GdkDragContext* context = gtk_drag_begin(
-      drag_widget_, list,
-      gtk_util::WebDragOpToGdkDragAction(allowed_ops),
-      1,  // Drags are always initiated by the left button.
-      reinterpret_cast<GdkEvent*>(last_mouse_down));
-  // The drag adds a ref; let it own the list.
-  gtk_target_list_unref(list);
-
-  // Sometimes the drag fails to start; |context| will be NULL and we won't
-  // get a drag-end signal.
-  if (!context) {
-    drop_data_.reset();
-    if (tab_contents()->render_view_host())
-      tab_contents()->render_view_host()->DragSourceSystemDragEnded();
-    return;
-  }
-
-  MessageLoopForUI::current()->AddObserver(this);
-}
-
-void TabContentsDragSource::WillProcessEvent(GdkEvent* event) {
-  // No-op.
-}
-
-void TabContentsDragSource::DidProcessEvent(GdkEvent* event) {
-  if (event->type != GDK_MOTION_NOTIFY)
-    return;
-
-  GdkEventMotion* event_motion = reinterpret_cast<GdkEventMotion*>(event);
-  gfx::Point client = gtk_util::ClientPoint(GetContentNativeView());
-
-  if (tab_contents()->render_view_host()) {
-    tab_contents()->render_view_host()->DragSourceMovedTo(
-        client.x(), client.y(),
-        static_cast<int>(event_motion->x_root),
-        static_cast<int>(event_motion->y_root));
-  }
-}
-
-void TabContentsDragSource::OnDragDataGet(GtkWidget* sender,
-    GdkDragContext* context, GtkSelectionData* selection_data,
-    guint target_type, guint time) {
-  const int kBitsPerByte = 8;
-
-  switch (target_type) {
-    case gtk_dnd_util::TEXT_PLAIN: {
-      std::string utf8_text = UTF16ToUTF8(drop_data_->plain_text);
-      gtk_selection_data_set_text(selection_data, utf8_text.c_str(),
-                                  utf8_text.length());
-      break;
-    }
-
-    case gtk_dnd_util::TEXT_HTML: {
-      // TODO(estade): change relative links to be absolute using
-      // |html_base_url|.
-      std::string utf8_text = UTF16ToUTF8(drop_data_->text_html);
-      gtk_selection_data_set(selection_data,
-                             gtk_dnd_util::GetAtomForTarget(
-                                 gtk_dnd_util::TEXT_HTML),
-                             kBitsPerByte,
-                             reinterpret_cast<const guchar*>(utf8_text.c_str()),
-                             utf8_text.length());
-      break;
-    }
-
-    case gtk_dnd_util::TEXT_URI_LIST:
-    case gtk_dnd_util::CHROME_NAMED_URL:
-    case gtk_dnd_util::NETSCAPE_URL: {
-      gtk_dnd_util::WriteURLWithName(selection_data, drop_data_->url,
-                                   drop_data_->url_title, target_type);
-      break;
-    }
-
-    case gtk_dnd_util::CHROME_WEBDROP_FILE_CONTENTS: {
-      gtk_selection_data_set(
-          selection_data,
-          drag_file_mime_type_, kBitsPerByte,
-          reinterpret_cast<const guchar*>(drop_data_->file_contents.data()),
-          drop_data_->file_contents.length());
-      break;
-    }
-
-    case gtk_dnd_util::DIRECT_SAVE_FILE: {
-      char status_code = 'E';
-
-      // Retrieves the full file path (in file URL format) provided by the
-      // drop target by reading from the source window's XdndDirectSave0
-      // property.
-      gint file_url_len = 0;
-      guchar* file_url_value = NULL;
-      if (gdk_property_get(context->source_window,
-                           gtk_dnd_util::GetAtomForTarget(
-                              gtk_dnd_util::DIRECT_SAVE_FILE),
-                           gtk_dnd_util::GetAtomForTarget(
-                              gtk_dnd_util::TEXT_PLAIN_NO_CHARSET),
-                           0,
-                           1024,
-                           FALSE,
-                           NULL,
-                           NULL,
-                           &file_url_len,
-                           &file_url_value) &&
-          file_url_value) {
-        // Convert from the file url to the file path.
-        GURL file_url(std::string(reinterpret_cast<char*>(file_url_value),
-                                  file_url_len));
-        g_free(file_url_value);
-        FilePath file_path;
-        if (net::FileURLToFilePath(file_url, &file_path)) {
-          // Open the file as a stream.
-          net::FileStream* file_stream =
-              drag_download_util::CreateFileStreamForDrop(&file_path);
-          if (file_stream) {
-              // Start downloading the file to the stream.
-              TabContents* tab_contents = tab_contents_view_->tab_contents();
-              scoped_refptr<DragDownloadFile> drag_file_downloader =
-                  new DragDownloadFile(file_path,
-                                       linked_ptr<net::FileStream>(file_stream),
-                                       download_url_,
-                                       tab_contents->GetURL(),
-                                       tab_contents->encoding(),
-                                       tab_contents);
-              drag_file_downloader->Start(
-                  new drag_download_util::PromiseFileFinalizer(
-                      drag_file_downloader));
-
-              // Set the status code to success.
-              status_code = 'S';
-          }
-        }
-
-        // Return the status code to the file manager.
-        gtk_selection_data_set(selection_data,
-                               selection_data->target,
-                               8,
-                               reinterpret_cast<guchar*>(&status_code),
-                               1);
-      }
-      break;
-    }
-
-    default:
-      NOTREACHED();
-  }
-}
-
-gboolean TabContentsDragSource::OnDragFailed(GtkWidget* sender,
-                                             GdkDragContext* context,
-                                             GtkDragResult result) {
-  drag_failed_ = true;
-
-  gfx::Point root = gtk_util::ScreenPoint(GetContentNativeView());
-  gfx::Point client = gtk_util::ClientPoint(GetContentNativeView());
-
-  if (tab_contents()->render_view_host()) {
-    tab_contents()->render_view_host()->DragSourceEndedAt(
-        client.x(), client.y(), root.x(), root.y(),
-        WebDragOperationNone);
-  }
-
-  // Let the native failure animation run.
-  return FALSE;
-}
-
-void TabContentsDragSource::OnDragBegin(GtkWidget* sender,
-                                        GdkDragContext* drag_context) {
-  if (!download_url_.is_empty()) {
-    // Generate the file name based on both mime type and proposed file name.
-    std::string download_mime_type = UTF16ToUTF8(wide_download_mime_type_);
-    std::string content_disposition("attachment; filename=");
-    content_disposition += download_file_name_.value();
-    FilePath generated_download_file_name;
-    download_util::GenerateFileName(download_url_,
-                                    content_disposition,
-                                    std::string(),
-                                    download_mime_type,
-                                    &generated_download_file_name);
-
-    // Pass the file name to the drop target by setting the source window's
-    // XdndDirectSave0 property.
-    gdk_property_change(drag_context->source_window,
-                        gtk_dnd_util::GetAtomForTarget(
-                            gtk_dnd_util::DIRECT_SAVE_FILE),
-                        gtk_dnd_util::GetAtomForTarget(
-                            gtk_dnd_util::TEXT_PLAIN_NO_CHARSET),
-                        8,
-                        GDK_PROP_MODE_REPLACE,
-                        reinterpret_cast<const guchar*>(
-                            generated_download_file_name.value().c_str()),
-                        generated_download_file_name.value().length());
-  }
-
-  if (drag_pixbuf_) {
-    gtk_widget_set_size_request(drag_icon_,
-                                gdk_pixbuf_get_width(drag_pixbuf_),
-                                gdk_pixbuf_get_height(drag_pixbuf_));
-
-    // We only need to do this once.
-    if (!GTK_WIDGET_REALIZED(drag_icon_)) {
-      GdkScreen* screen = gtk_widget_get_screen(drag_icon_);
-      GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen);
-      if (rgba)
-        gtk_widget_set_colormap(drag_icon_, rgba);
-    }
-
-    gtk_drag_set_icon_widget(drag_context, drag_icon_,
-                             image_offset_.x(), image_offset_.y());
-  }
-}
-
-void TabContentsDragSource::OnDragEnd(GtkWidget* sender,
-                                      GdkDragContext* drag_context) {
-  if (drag_pixbuf_) {
-    g_object_unref(drag_pixbuf_);
-    drag_pixbuf_ = NULL;
-  }
-
-  MessageLoopForUI::current()->RemoveObserver(this);
-
-  if (!download_url_.is_empty()) {
-    gdk_property_delete(drag_context->source_window,
-                        gtk_dnd_util::GetAtomForTarget(
-                            gtk_dnd_util::DIRECT_SAVE_FILE));
-  }
-
-  if (!drag_failed_) {
-    gfx::Point root = gtk_util::ScreenPoint(GetContentNativeView());
-    gfx::Point client = gtk_util::ClientPoint(GetContentNativeView());
-
-    if (tab_contents()->render_view_host()) {
-      tab_contents()->render_view_host()->DragSourceEndedAt(
-          client.x(), client.y(), root.x(), root.y(),
-          gtk_util::GdkDragActionToWebDragOp(drag_context->action));
-    }
-  }
-
-  if (tab_contents()->render_view_host())
-    tab_contents()->render_view_host()->DragSourceSystemDragEnded();
-
-  drop_data_.reset();
-}
-
-gfx::NativeView TabContentsDragSource::GetContentNativeView() const {
-  return tab_contents_view_->GetContentNativeView();
-}
-
-gboolean TabContentsDragSource::OnDragIconExpose(GtkWidget* sender,
-                                                 GdkEventExpose* event) {
-  cairo_t* cr = gdk_cairo_create(event->window);
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-  gdk_cairo_set_source_pixbuf(cr, drag_pixbuf_, 0, 0);
-  cairo_paint(cr);
-  cairo_destroy(cr);
-
-  return TRUE;
-}
diff --git a/chrome/browser/gtk/tab_contents_drag_source.h b/chrome/browser/gtk/tab_contents_drag_source.h
deleted file mode 100644
index 261c677..0000000
--- a/chrome/browser/gtk/tab_contents_drag_source.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TAB_CONTENTS_DRAG_SOURCE_H_
-#define CHROME_BROWSER_GTK_TAB_CONTENTS_DRAG_SOURCE_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "app/gtk_signal_registrar.h"
-#include "base/basictypes.h"
-#include "base/file_path.h"
-#include "base/message_loop.h"
-#include "base/string16.h"
-#include "gfx/point.h"
-#include "gfx/native_widget_types.h"
-#include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
-
-class SkBitmap;
-class TabContents;
-class TabContentsView;
-struct WebDropData;
-
-// TabContentsDragSource takes care of managing the drag from a TabContents
-// with Gtk.
-class TabContentsDragSource : public MessageLoopForUI::Observer {
- public:
-  explicit TabContentsDragSource(TabContentsView* tab_contents_view);
-  ~TabContentsDragSource();
-
-  TabContents* tab_contents() const;
-
-  // Starts a drag for the tab contents this TabContentsDragSource was
-  // created for.
-  void StartDragging(const WebDropData& drop_data,
-                     WebKit::WebDragOperationsMask allowed_ops,
-                     GdkEventButton* last_mouse_down,
-                     const SkBitmap& image,
-                     const gfx::Point& image_offset);
-
-  // MessageLoop::Observer implementation:
-  virtual void WillProcessEvent(GdkEvent* event);
-  virtual void DidProcessEvent(GdkEvent* event);
-
- private:
-  CHROMEGTK_CALLBACK_2(TabContentsDragSource, gboolean, OnDragFailed,
-                       GdkDragContext*, GtkDragResult);
-  CHROMEGTK_CALLBACK_1(TabContentsDragSource, void, OnDragBegin,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_1(TabContentsDragSource, void, OnDragEnd,
-                       GdkDragContext*);
-  CHROMEGTK_CALLBACK_4(TabContentsDragSource, void, OnDragDataGet,
-                       GdkDragContext*, GtkSelectionData*, guint, guint);
-  CHROMEGTK_CALLBACK_1(TabContentsDragSource, gboolean, OnDragIconExpose,
-                       GdkEventExpose*);
-
-  gfx::NativeView GetContentNativeView() const;
-
-  // The view we're manging the drag for.
-  TabContentsView* tab_contents_view_;
-
-  // The drop data for the current drag (for drags that originate in the render
-  // view). Non-NULL iff there is a current drag.
-  scoped_ptr<WebDropData> drop_data_;
-
-  // The image used for depicting the drag, and the offset between the cursor
-  // and the top left pixel.
-  GdkPixbuf* drag_pixbuf_;
-  gfx::Point image_offset_;
-
-  // The mime type for the file contents of the current drag (if any).
-  GdkAtom drag_file_mime_type_;
-
-  // Whether the current drag has failed. Meaningless if we are not the source
-  // for a current drag.
-  bool drag_failed_;
-
-  // This is the widget we use to initiate drags. Since we don't use the
-  // renderer widget, we can persist drags even when our contents is switched
-  // out. We can't use an OwnedWidgetGtk because the GtkInvisible widget
-  // initialization code sinks the reference.
-  GtkWidget* drag_widget_;
-
-  // The file mime type for a drag-out download.
-  string16 wide_download_mime_type_;
-
-  // The file name to be saved to for a drag-out download.
-  FilePath download_file_name_;
-
-  // The URL to download from for a drag-out download.
-  GURL download_url_;
-
-  // The widget that provides visual feedback for the drag. We can't use
-  // an OwnedWidgetGtk because the GtkWindow initialization code sinks
-  // the reference.
-  GtkWidget* drag_icon_;
-
-  GtkSignalRegistrar signals_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabContentsDragSource);
-};
-
-#endif  // CHROME_BROWSER_GTK_TAB_CONTENTS_DRAG_SOURCE_H_
diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc
deleted file mode 100644
index a204b29..0000000
--- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc
+++ /dev/null
@@ -1,790 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h"
-
-#include <algorithm>
-
-#include "base/callback.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/tabs/dragged_tab_gtk.h"
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/notification_source.h"
-
-namespace {
-
-// Delay, in ms, during dragging before we bring a window to front.
-const int kBringToFrontDelay = 750;
-
-// Used to determine how far a tab must obscure another tab in order to swap
-// their indexes.
-const int kHorizontalMoveThreshold = 16;  // pixels
-
-// How far a drag must pull a tab out of the tabstrip in order to detach it.
-const int kVerticalDetachMagnetism = 15;  // pixels
-
-}  // namespace
-
-DraggedTabControllerGtk::DraggedTabControllerGtk(TabGtk* source_tab,
-                                                 TabStripGtk* source_tabstrip)
-    : dragged_contents_(NULL),
-      original_delegate_(NULL),
-      source_tab_(source_tab),
-      source_tabstrip_(source_tabstrip),
-      source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)),
-      attached_tabstrip_(source_tabstrip),
-      in_destructor_(false),
-      last_move_screen_x_(0),
-      mini_(source_tabstrip->model()->IsMiniTab(source_model_index_)),
-      pinned_(source_tabstrip->model()->IsTabPinned(source_model_index_)) {
-  SetDraggedContents(
-      source_tabstrip_->model()->GetTabContentsAt(source_model_index_));
-}
-
-DraggedTabControllerGtk::~DraggedTabControllerGtk() {
-  in_destructor_ = true;
-  CleanUpSourceTab();
-  // Need to delete the dragged tab here manually _before_ we reset the dragged
-  // contents to NULL, otherwise if the view is animating to its destination
-  // bounds, it won't be able to clean up properly since its cleanup routine
-  // uses GetIndexForDraggedContents, which will be invalid.
-  dragged_tab_.reset();
-  SetDraggedContents(NULL);
-}
-
-void DraggedTabControllerGtk::CaptureDragInfo(const gfx::Point& mouse_offset) {
-  start_screen_point_ = GetCursorScreenPoint();
-  mouse_offset_ = mouse_offset;
-}
-
-void DraggedTabControllerGtk::Drag() {
-  if (!source_tab_ || !dragged_contents_)
-    return;
-
-  bring_to_front_timer_.Stop();
-
-  EnsureDraggedTab();
-
-  // Before we get to dragging anywhere, ensure that we consider ourselves
-  // attached to the source tabstrip.
-  if (source_tab_->IsVisible()) {
-    Attach(source_tabstrip_, gfx::Point());
-  }
-
-  if (!source_tab_->IsVisible()) {
-    // TODO(jhawkins): Save focus.
-    ContinueDragging();
-  }
-}
-
-bool DraggedTabControllerGtk::EndDrag(bool canceled) {
-  return EndDragImpl(canceled ? CANCELED : NORMAL);
-}
-
-TabGtk* DraggedTabControllerGtk::GetDragSourceTabForContents(
-    TabContents* contents) const {
-  if (attached_tabstrip_ == source_tabstrip_)
-    return contents == dragged_contents_->tab_contents() ? source_tab_ : NULL;
-  return NULL;
-}
-
-bool DraggedTabControllerGtk::IsDragSourceTab(const TabGtk* tab) const {
-  return source_tab_ == tab;
-}
-
-bool DraggedTabControllerGtk::IsTabDetached(const TabGtk* tab) const {
-  if (!IsDragSourceTab(tab))
-    return false;
-  return (attached_tabstrip_ == NULL);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabControllerGtk, TabContentsDelegate implementation:
-
-void DraggedTabControllerGtk::OpenURLFromTab(TabContents* source,
-                                             const GURL& url,
-                                             const GURL& referrer,
-                                             WindowOpenDisposition disposition,
-                                             PageTransition::Type transition) {
-  if (original_delegate_) {
-    if (disposition == CURRENT_TAB)
-      disposition = NEW_WINDOW;
-
-    original_delegate_->OpenURLFromTab(source, url, referrer,
-                                       disposition, transition);
-  }
-}
-
-void DraggedTabControllerGtk::NavigationStateChanged(const TabContents* source,
-                                                     unsigned changed_flags) {
-  if (dragged_tab_.get())
-    dragged_tab_->Update();
-}
-
-void DraggedTabControllerGtk::AddNewContents(TabContents* source,
-                                             TabContents* new_contents,
-                                             WindowOpenDisposition disposition,
-                                             const gfx::Rect& initial_pos,
-                                             bool user_gesture) {
-  DCHECK(disposition != CURRENT_TAB);
-
-  // Theoretically could be called while dragging if the page tries to
-  // spawn a window. Route this message back to the browser in most cases.
-  if (original_delegate_) {
-    original_delegate_->AddNewContents(source, new_contents, disposition,
-                                       initial_pos, user_gesture);
-  }
-}
-
-void DraggedTabControllerGtk::ActivateContents(TabContents* contents) {
-  // Ignored.
-}
-
-void DraggedTabControllerGtk::DeactivateContents(TabContents* contents) {
-  // Ignored.
-}
-
-void DraggedTabControllerGtk::LoadingStateChanged(TabContents* source) {
-  // TODO(jhawkins): It would be nice to respond to this message by changing the
-  // screen shot in the dragged tab.
-  if (dragged_tab_.get())
-    dragged_tab_->Update();
-}
-
-void DraggedTabControllerGtk::CloseContents(TabContents* source) {
-  // Theoretically could be called by a window. Should be ignored
-  // because window.close() is ignored (usually, even though this
-  // method gets called.)
-}
-
-void DraggedTabControllerGtk::MoveContents(TabContents* source,
-                                        const gfx::Rect& pos) {
-  // Theoretically could be called by a web page trying to move its
-  // own window. Should be ignored since we're moving the window...
-}
-
-bool DraggedTabControllerGtk::IsPopup(TabContents* source) {
-  return false;
-}
-
-void DraggedTabControllerGtk::ToolbarSizeChanged(TabContents* source,
-                                                 bool finished) {
-  // Dragged tabs don't care about this.
-}
-
-void DraggedTabControllerGtk::URLStarredChanged(TabContents* source,
-                                                bool starred) {
-  // Ignored.
-}
-
-void DraggedTabControllerGtk::UpdateTargetURL(TabContents* source,
-                                              const GURL& url) {
-  // Ignored.
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabControllerGtk, NotificationObserver implementation:
-
-void DraggedTabControllerGtk::Observe(NotificationType type,
-                                   const NotificationSource& source,
-                                   const NotificationDetails& details) {
-  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
-  DCHECK(Source<TabContentsWrapper>(source).ptr() == dragged_contents_);
-  EndDragImpl(TAB_DESTROYED);
-}
-
-void DraggedTabControllerGtk::InitWindowCreatePoint() {
-  window_create_point_.SetPoint(mouse_offset_.x(), mouse_offset_.y());
-}
-
-gfx::Point DraggedTabControllerGtk::GetWindowCreatePoint() const {
-  gfx::Point cursor_point = GetCursorScreenPoint();
-  return gfx::Point(cursor_point.x() - window_create_point_.x(),
-                    cursor_point.y() - window_create_point_.y());
-}
-
-void DraggedTabControllerGtk::SetDraggedContents(
-    TabContentsWrapper* new_contents) {
-  if (dragged_contents_) {
-    registrar_.Remove(this,
-                      NotificationType::TAB_CONTENTS_DESTROYED,
-                      Source<TabContentsWrapper>(dragged_contents_));
-    if (original_delegate_)
-      dragged_contents_->set_delegate(original_delegate_);
-  }
-  original_delegate_ = NULL;
-  dragged_contents_ = new_contents;
-  if (dragged_contents_) {
-    registrar_.Add(this,
-                   NotificationType::TAB_CONTENTS_DESTROYED,
-                   Source<TabContentsWrapper>(dragged_contents_));
-
-    // We need to be the delegate so we receive messages about stuff,
-    // otherwise our dragged_contents() may be replaced and subsequently
-    // collected/destroyed while the drag is in process, leading to
-    // nasty crashes.
-    original_delegate_ = dragged_contents_->delegate();
-    dragged_contents_->set_delegate(this);
-  }
-}
-
-void DraggedTabControllerGtk::ContinueDragging() {
-  // TODO(jhawkins): We don't handle the situation where the last tab is dragged
-  // out of a window, so we'll just go with the way Windows handles dragging for
-  // now.
-  gfx::Point screen_point = GetCursorScreenPoint();
-
-  // Determine whether or not we have dragged over a compatible TabStrip in
-  // another browser window. If we have, we should attach to it and start
-  // dragging within it.
-#if defined(OS_CHROMEOS)
-  // We don't allow detaching on chrome os.
-  TabStripGtk* target_tabstrip = source_tabstrip_;
-#else
-  TabStripGtk* target_tabstrip = GetTabStripForPoint(screen_point);
-#endif
-  if (target_tabstrip != attached_tabstrip_) {
-    // Make sure we're fully detached from whatever TabStrip we're attached to
-    // (if any).
-    if (attached_tabstrip_)
-      Detach();
-
-    if (target_tabstrip)
-      Attach(target_tabstrip, screen_point);
-  }
-
-  if (!target_tabstrip) {
-    bring_to_front_timer_.Start(
-        base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this,
-        &DraggedTabControllerGtk::BringWindowUnderMouseToFront);
-  }
-
-  MoveTab(screen_point);
-}
-
-void DraggedTabControllerGtk::MoveTab(const gfx::Point& screen_point) {
-  gfx::Point dragged_tab_point = GetDraggedTabPoint(screen_point);
-
-  if (attached_tabstrip_) {
-    TabStripModel* attached_model = attached_tabstrip_->model();
-    int from_index = attached_model->GetIndexOfTabContents(dragged_contents_);
-
-    // Determine the horizontal move threshold. This is dependent on the width
-    // of tabs. The smaller the tabs compared to the standard size, the smaller
-    // the threshold.
-    double unselected, selected;
-    attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected);
-    double ratio = unselected / TabGtk::GetStandardSize().width();
-    int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold);
-
-    // Update the model, moving the TabContents from one index to another. Do
-    // this only if we have moved a minimum distance since the last reorder (to
-    // prevent jitter).
-    if (abs(screen_point.x() - last_move_screen_x_) > threshold) {
-      gfx::Rect bounds = GetDraggedTabTabStripBounds(dragged_tab_point);
-      int to_index = GetInsertionIndexForDraggedBounds(bounds, true);
-      to_index = NormalizeIndexToAttachedTabStrip(to_index);
-      if (from_index != to_index) {
-        last_move_screen_x_ = screen_point.x();
-        attached_model->MoveTabContentsAt(from_index, to_index, true);
-      }
-    }
-  }
-
-  // Move the dragged tab. There are no changes to the model if we're detached.
-  dragged_tab_->MoveTo(dragged_tab_point);
-}
-
-TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint(
-    const gfx::Point& screen_point) {
-  GtkWidget* dragged_window = dragged_tab_->widget();
-  dock_windows_.insert(dragged_window);
-  gfx::NativeWindow local_window =
-      DockInfo::GetLocalProcessWindowAtPoint(screen_point, dock_windows_);
-  dock_windows_.erase(dragged_window);
-  if (!local_window)
-    return NULL;
-
-  BrowserWindowGtk* browser =
-      BrowserWindowGtk::GetBrowserWindowForNativeWindow(local_window);
-  if (!browser)
-    return NULL;
-
-  TabStripGtk* other_tabstrip = browser->tabstrip();
-  if (!other_tabstrip->IsCompatibleWith(source_tabstrip_))
-    return NULL;
-
-  return GetTabStripIfItContains(other_tabstrip, screen_point);
-}
-
-TabStripGtk* DraggedTabControllerGtk::GetTabStripIfItContains(
-    TabStripGtk* tabstrip, const gfx::Point& screen_point) const {
-  // Make sure the specified screen point is actually within the bounds of the
-  // specified tabstrip...
-  gfx::Rect tabstrip_bounds =
-      gtk_util::GetWidgetScreenBounds(tabstrip->tabstrip_.get());
-  if (screen_point.x() < tabstrip_bounds.right() &&
-      screen_point.x() >= tabstrip_bounds.x()) {
-    // TODO(beng): make this be relative to the start position of the mouse for
-    // the source TabStrip.
-    int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism;
-    int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism;
-    if (screen_point.y() >= lower_threshold &&
-        screen_point.y() <= upper_threshold) {
-      return tabstrip;
-    }
-  }
-
-  return NULL;
-}
-
-void DraggedTabControllerGtk::Attach(TabStripGtk* attached_tabstrip,
-                                     const gfx::Point& screen_point) {
-  attached_tabstrip_ = attached_tabstrip;
-  InitWindowCreatePoint();
-  attached_tabstrip_->GenerateIdealBounds();
-
-  TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
-
-  // Update the tab first, so we can ask it for its bounds and determine
-  // where to insert the hidden tab.
-
-  // If this is the first time Attach is called for this drag, we're attaching
-  // to the source tabstrip, and we should assume the tab count already
-  // includes this tab since we haven't been detached yet. If we don't do this,
-  // the dragged representation will be a different size to others in the
-  // tabstrip.
-  int tab_count = attached_tabstrip_->GetTabCount();
-  int mini_tab_count = attached_tabstrip_->GetMiniTabCount();
-  if (!tab)
-    ++tab_count;
-  double unselected_width = 0, selected_width = 0;
-  attached_tabstrip_->GetDesiredTabWidths(tab_count, mini_tab_count,
-                                          &unselected_width, &selected_width);
-  int dragged_tab_width =
-      mini_ ? TabGtk::GetMiniWidth() : static_cast<int>(selected_width);
-  dragged_tab_->Attach(dragged_tab_width);
-
-  if (!tab) {
-    // There is no tab in |attached_tabstrip| that corresponds to the dragged
-    // TabContents. We must now create one.
-
-    // Remove ourselves as the delegate now that the dragged TabContents is
-    // being inserted back into a Browser.
-    dragged_contents_->set_delegate(NULL);
-    original_delegate_ = NULL;
-
-    // Return the TabContents' to normalcy.
-    dragged_contents_->tab_contents()->set_capturing_contents(false);
-
-    // We need to ask the tabstrip we're attached to ensure that the ideal
-    // bounds for all its tabs are correctly generated, because the calculation
-    // in GetInsertionIndexForDraggedBounds needs them to be to figure out the
-    // appropriate insertion index.
-    attached_tabstrip_->GenerateIdealBounds();
-
-    // Inserting counts as a move. We don't want the tabs to jitter when the
-    // user moves the tab immediately after attaching it.
-    last_move_screen_x_ = screen_point.x();
-
-    // Figure out where to insert the tab based on the bounds of the dragged
-    // representation and the ideal bounds of the other tabs already in the
-    // strip. ("ideal bounds" are stable even if the tabs' actual bounds are
-    // changing due to animation).
-    gfx::Rect bounds = GetDraggedTabTabStripBounds(screen_point);
-    int index = GetInsertionIndexForDraggedBounds(bounds, false);
-    attached_tabstrip_->model()->InsertTabContentsAt(
-        index, dragged_contents_,
-        TabStripModel::ADD_SELECTED |
-            (pinned_ ? TabStripModel::ADD_PINNED : 0));
-
-    tab = GetTabMatchingDraggedContents(attached_tabstrip_);
-  }
-  DCHECK(tab);  // We should now have a tab.
-  tab->SetVisible(false);
-  tab->set_dragging(true);
-
-  // TODO(jhawkins): Move the corresponding window to the front.
-}
-
-void DraggedTabControllerGtk::Detach() {
-  // Update the Model.
-  TabStripModel* attached_model = attached_tabstrip_->model();
-  int index = attached_model->GetIndexOfTabContents(dragged_contents_);
-  if (index >= 0 && index < attached_model->count()) {
-    // Sometimes, DetachTabContentsAt has consequences that result in
-    // attached_tabstrip_ being set to NULL, so we need to save it first.
-    TabStripGtk* attached_tabstrip = attached_tabstrip_;
-    attached_model->DetachTabContentsAt(index);
-    attached_tabstrip->SchedulePaint();
-  }
-
-  // If we've removed the last tab from the tabstrip, hide the frame now.
-  if (attached_model->empty())
-    HideWindow();
-
-  // Update the dragged tab. This NULL check is necessary apparently in some
-  // conditions during automation where the view_ is destroyed inside a
-  // function call preceding this point but after it is created.
-  if (dragged_tab_.get()) {
-    dragged_tab_->Detach();
-  }
-
-  // Detaching resets the delegate, but we still want to be the delegate.
-  dragged_contents_->set_delegate(this);
-
-  attached_tabstrip_ = NULL;
-}
-
-gfx::Point DraggedTabControllerGtk::ConvertScreenPointToTabStripPoint(
-    TabStripGtk* tabstrip, const gfx::Point& screen_point) {
-  gfx::Point tabstrip_screen_point =
-      gtk_util::GetWidgetScreenPosition(tabstrip->tabstrip_.get());
-  return screen_point.Subtract(tabstrip_screen_point);
-}
-
-gfx::Rect DraggedTabControllerGtk::GetDraggedTabTabStripBounds(
-    const gfx::Point& screen_point) {
-  gfx::Point client_point =
-      ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point);
-  gfx::Size tab_size = dragged_tab_->attached_tab_size();
-  return gfx::Rect(client_point.x(), client_point.y(),
-                   tab_size.width(), tab_size.height());
-}
-
-int DraggedTabControllerGtk::GetInsertionIndexForDraggedBounds(
-    const gfx::Rect& dragged_bounds,
-    bool is_tab_attached) const {
-  int right_tab_x = 0;
-
-  // TODO(jhawkins): Handle RTL layout.
-
-  // Divides each tab into two halves to see if the dragged tab has crossed
-  // the halfway boundary necessary to move past the next tab.
-  int index = -1;
-  for (int i = 0; i < attached_tabstrip_->GetTabCount(); i++) {
-    gfx::Rect ideal_bounds = attached_tabstrip_->GetIdealBounds(i);
-
-    gfx::Rect left_half = ideal_bounds;
-    left_half.set_width(left_half.width() / 2);
-
-    gfx::Rect right_half = ideal_bounds;
-    right_half.set_width(ideal_bounds.width() - left_half.width());
-    right_half.set_x(left_half.right());
-
-    right_tab_x = right_half.right();
-
-    if (dragged_bounds.x() >= right_half.x() &&
-        dragged_bounds.x() < right_half.right()) {
-      index = i + 1;
-      break;
-    } else if (dragged_bounds.x() >= left_half.x() &&
-               dragged_bounds.x() < left_half.right()) {
-      index = i;
-      break;
-    }
-  }
-
-  if (index == -1) {
-    if (dragged_bounds.right() > right_tab_x)
-      index = attached_tabstrip_->model()->count();
-    else
-      index = 0;
-  }
-
-  index = attached_tabstrip_->model()->ConstrainInsertionIndex(index, mini_);
-  if (is_tab_attached && mini_ &&
-      index == attached_tabstrip_->model()->IndexOfFirstNonMiniTab()) {
-    index--;
-  }
-
-  return index;
-}
-
-gfx::Point DraggedTabControllerGtk::GetDraggedTabPoint(
-    const gfx::Point& screen_point) {
-  int x = screen_point.x() - mouse_offset_.x();
-  int y = screen_point.y() - mouse_offset_.y();
-
-  // If we're not attached, we just use x and y from above.
-  if (attached_tabstrip_) {
-    gfx::Rect tabstrip_bounds =
-        gtk_util::GetWidgetScreenBounds(attached_tabstrip_->tabstrip_.get());
-    // Snap the dragged tab to the tabstrip if we are attached, detaching
-    // only when the mouse position (screen_point) exceeds the screen bounds
-    // of the tabstrip.
-    if (x < tabstrip_bounds.x() && screen_point.x() >= tabstrip_bounds.x())
-      x = tabstrip_bounds.x();
-
-    gfx::Size tab_size = dragged_tab_->attached_tab_size();
-    int vertical_drag_magnetism = tab_size.height() * 2;
-    int vertical_detach_point = tabstrip_bounds.y() - vertical_drag_magnetism;
-    if (y < tabstrip_bounds.y() && screen_point.y() >= vertical_detach_point)
-      y = tabstrip_bounds.y();
-
-    // Make sure the tab can't be dragged off the right side of the tabstrip
-    // unless the mouse pointer passes outside the bounds of the strip by
-    // clamping the position of the dragged window to the tabstrip width less
-    // the width of one tab until the mouse pointer (screen_point) exceeds the
-    // screen bounds of the tabstrip.
-    int max_x = tabstrip_bounds.right() - tab_size.width();
-    int max_y = tabstrip_bounds.bottom() - tab_size.height();
-    if (x > max_x && screen_point.x() <= tabstrip_bounds.right())
-      x = max_x;
-    if (y > max_y && screen_point.y() <=
-        (tabstrip_bounds.bottom() + vertical_drag_magnetism)) {
-      y = max_y;
-    }
-#if defined(OS_CHROMEOS)
-    // We don't allow detaching on chromeos. This restricts dragging to the
-    // source window.
-    x = std::min(std::max(x, tabstrip_bounds.x()), max_x);
-    y = tabstrip_bounds.y();
-#endif
-  }
-  return gfx::Point(x, y);
-}
-
-int DraggedTabControllerGtk::NormalizeIndexToAttachedTabStrip(int index) const {
-  if (index >= attached_tabstrip_->model_->count())
-    return attached_tabstrip_->model_->count() - 1;
-  if (index == TabStripModel::kNoTab)
-    return 0;
-  return index;
-}
-
-TabGtk* DraggedTabControllerGtk::GetTabMatchingDraggedContents(
-    TabStripGtk* tabstrip) const {
-  int index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_);
-  return index == TabStripModel::kNoTab ? NULL : tabstrip->GetTabAt(index);
-}
-
-bool DraggedTabControllerGtk::EndDragImpl(EndDragType type) {
-  bring_to_front_timer_.Stop();
-
-  // WARNING: this may be invoked multiple times. In particular, if deletion
-  // occurs after a delay (as it does when the tab is released in the original
-  // tab strip) and the navigation controller/tab contents is deleted before
-  // the animation finishes, this is invoked twice. The second time through
-  // type == TAB_DESTROYED.
-
-  bool destroy_now = true;
-  if (type == TAB_DESTROYED) {
-    // If we get here it means the NavigationController is going down. Don't
-    // attempt to do any cleanup other than resetting the delegate (if we're
-    // still the delegate).
-    if (dragged_contents_ && dragged_contents_->delegate() == this)
-      dragged_contents_->set_delegate(NULL);
-    dragged_contents_ = NULL;
-  } else {
-    // If we never received a drag-motion event, the drag will never have
-    // started in the sense that |dragged_tab_| will be NULL. We don't need to
-    // revert or complete the drag in that case.
-    if (dragged_tab_.get()) {
-      if (type == CANCELED) {
-        RevertDrag();
-      } else {
-        destroy_now = CompleteDrag();
-      }
-    }
-
-    if (dragged_contents_ && dragged_contents_->delegate() == this)
-      dragged_contents_->set_delegate(original_delegate_);
-  }
-
-  // The delegate of the dragged contents should have been reset. Unset the
-  // original delegate so that we don't attempt to reset the delegate when
-  // deleted.
-  DCHECK(!dragged_contents_ || dragged_contents_->delegate() != this);
-  original_delegate_ = NULL;
-
-  // If we're not destroyed now, we'll be destroyed asynchronously later.
-  if (destroy_now)
-    source_tabstrip_->DestroyDragController();
-
-  return destroy_now;
-}
-
-void DraggedTabControllerGtk::RevertDrag() {
-  // We save this here because code below will modify |attached_tabstrip_|.
-  bool restore_window = attached_tabstrip_ != source_tabstrip_;
-  if (attached_tabstrip_) {
-    int index = attached_tabstrip_->model()->GetIndexOfTabContents(
-        dragged_contents_);
-    if (attached_tabstrip_ != source_tabstrip_) {
-      // The tab was inserted into another tabstrip. We need to put it back
-      // into the original one.
-      attached_tabstrip_->model()->DetachTabContentsAt(index);
-      // TODO(beng): (Cleanup) seems like we should use Attach() for this
-      //             somehow.
-      attached_tabstrip_ = source_tabstrip_;
-      source_tabstrip_->model()->InsertTabContentsAt(
-          source_model_index_, dragged_contents_,
-          TabStripModel::ADD_SELECTED |
-              (pinned_ ? TabStripModel::ADD_PINNED : 0));
-    } else {
-      // The tab was moved within the tabstrip where the drag was initiated.
-      // Move it back to the starting location.
-      source_tabstrip_->model()->MoveTabContentsAt(index, source_model_index_,
-          true);
-    }
-  } else {
-    // TODO(beng): (Cleanup) seems like we should use Attach() for this
-    //             somehow.
-    attached_tabstrip_ = source_tabstrip_;
-    // The tab was detached from the tabstrip where the drag began, and has not
-    // been attached to any other tabstrip. We need to put it back into the
-    // source tabstrip.
-    source_tabstrip_->model()->InsertTabContentsAt(
-        source_model_index_, dragged_contents_,
-        TabStripModel::ADD_SELECTED |
-            (pinned_ ? TabStripModel::ADD_PINNED : 0));
-  }
-
-  // If we're not attached to any tab strip, or attached to some other tab
-  // strip, we need to restore the bounds of the original tab strip's frame, in
-  // case it has been hidden.
-  if (restore_window)
-    ShowWindow();
-
-  source_tab_->SetVisible(true);
-  source_tab_->set_dragging(false);
-}
-
-bool DraggedTabControllerGtk::CompleteDrag() {
-  bool destroy_immediately = true;
-  if (attached_tabstrip_) {
-    // We don't need to do anything other than make the tab visible again,
-    // since the dragged tab is going away.
-    TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
-    gfx::Rect rect = GetTabScreenBounds(tab);
-    dragged_tab_->AnimateToBounds(GetTabScreenBounds(tab),
-        NewCallback(this, &DraggedTabControllerGtk::OnAnimateToBoundsComplete));
-    destroy_immediately = false;
-  } else {
-    // Compel the model to construct a new window for the detached TabContents.
-    BrowserWindowGtk* window = source_tabstrip_->window();
-    gfx::Rect window_bounds = window->GetRestoredBounds();
-    window_bounds.set_origin(GetWindowCreatePoint());
-    Browser* new_browser =
-        source_tabstrip_->model()->delegate()->CreateNewStripWithContents(
-        dragged_contents_, window_bounds, dock_info_, window->IsMaximized());
-    TabStripModel* new_model = new_browser->tabstrip_model();
-    new_model->SetTabPinned(new_model->GetIndexOfTabContents(dragged_contents_),
-                            pinned_);
-    new_browser->window()->Show();
-    CleanUpHiddenFrame();
-  }
-
-  return destroy_immediately;
-}
-
-void DraggedTabControllerGtk::EnsureDraggedTab() {
-  if (!dragged_tab_.get()) {
-    gfx::Rect rect;
-    dragged_contents_->tab_contents()->GetContainerBounds(&rect);
-
-    dragged_tab_.reset(new DraggedTabGtk(dragged_contents_->tab_contents(),
-                                         mouse_offset_, rect.size(), mini_));
-  }
-}
-
-gfx::Point DraggedTabControllerGtk::GetCursorScreenPoint() const {
-  // Get default display and screen.
-  GdkDisplay* display = gdk_display_get_default();
-
-  // Get cursor position.
-  int x, y;
-  gdk_display_get_pointer(display, NULL, &x, &y, NULL);
-
-  return gfx::Point(x, y);
-}
-
-// static
-gfx::Rect DraggedTabControllerGtk::GetTabScreenBounds(TabGtk* tab) {
-  // A hidden widget moved with gtk_fixed_move in a GtkFixed container doesn't
-  // update its allocation until after the widget is shown, so we have to use
-  // the tab bounds we keep track of.
-  //
-  // We use the requested bounds instead of the allocation because the
-  // allocation is relative to the first windowed widget ancestor of the tab.
-  // Because of this, we can't use the tabs allocation to get the screen bounds.
-  gfx::Rect bounds = tab->GetRequisition();
-  GtkWidget* widget = tab->widget();
-  GtkWidget* parent = gtk_widget_get_parent(widget);
-  gfx::Point point = gtk_util::GetWidgetScreenPosition(parent);
-  bounds.Offset(point);
-
-  return gfx::Rect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
-}
-
-void DraggedTabControllerGtk::HideWindow() {
-  GtkWidget* tabstrip = source_tabstrip_->widget();
-  GtkWindow* window = platform_util::GetTopLevel(tabstrip);
-  gtk_widget_hide(GTK_WIDGET(window));
-}
-
-void DraggedTabControllerGtk::ShowWindow() {
-  GtkWidget* tabstrip = source_tabstrip_->widget();
-  GtkWindow* window = platform_util::GetTopLevel(tabstrip);
-  gtk_window_present(window);
-}
-
-void DraggedTabControllerGtk::CleanUpHiddenFrame() {
-  // If the model we started dragging from is now empty, we must ask the
-  // delegate to close the frame.
-  if (source_tabstrip_->model()->empty())
-    source_tabstrip_->model()->delegate()->CloseFrameAfterDragSession();
-}
-
-void DraggedTabControllerGtk::CleanUpSourceTab() {
-  // If we were attached to the source tabstrip, source tab will be in use
-  // as the tab. If we were detached or attached to another tabstrip, we can
-  // safely remove this item and delete it now.
-  if (attached_tabstrip_ != source_tabstrip_) {
-    source_tabstrip_->DestroyDraggedSourceTab(source_tab_);
-    source_tab_ = NULL;
-  }
-}
-
-void DraggedTabControllerGtk::OnAnimateToBoundsComplete() {
-  // Sometimes, for some reason, in automation we can be called back on a
-  // detach even though we aren't attached to a tabstrip. Guard against that.
-  if (attached_tabstrip_) {
-    TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
-    if (tab) {
-      tab->SetVisible(true);
-      tab->set_dragging(false);
-      // Paint the tab now, otherwise there may be slight flicker between the
-      // time the dragged tab window is destroyed and we paint.
-      tab->SchedulePaint();
-    }
-  }
-
-  CleanUpHiddenFrame();
-
-  if (!in_destructor_)
-    source_tabstrip_->DestroyDragController();
-}
-
-void DraggedTabControllerGtk::BringWindowUnderMouseToFront() {
-  // If we're going to dock to another window, bring it to the front.
-  gfx::NativeWindow window = dock_info_.window();
-  if (!window) {
-    gfx::NativeView dragged_tab = dragged_tab_->widget();
-    dock_windows_.insert(dragged_tab);
-    window = DockInfo::GetLocalProcessWindowAtPoint(GetCursorScreenPoint(),
-                                                    dock_windows_);
-    dock_windows_.erase(dragged_tab);
-  }
-
-  if (window)
-    gtk_window_present(GTK_WINDOW(window));
-}
diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h
deleted file mode 100644
index c421d69..0000000
--- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
-#define CHROME_BROWSER_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <set>
-
-#include "app/x11_util.h"
-#include "base/scoped_ptr.h"
-#include "base/timer.h"
-#include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "chrome/browser/ui/tabs/dock_info.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class DraggedTabGtk;
-class TabGtk;
-class TabStripGtk;
-class TabContentsWrapper;
-
-class DraggedTabControllerGtk : public NotificationObserver,
-                                public TabContentsDelegate {
- public:
-  DraggedTabControllerGtk(TabGtk* source_tab, TabStripGtk* source_tabstrip);
-  virtual ~DraggedTabControllerGtk();
-
-  // Capture information needed to be used during a drag session for this
-  // controller's associated source Tab and TabStrip. |mouse_offset| is the
-  // distance of the mouse pointer from the Tab's origin.
-  void CaptureDragInfo(const gfx::Point& mouse_offset);
-
-  // Responds to drag events subsequent to StartDrag. If the mouse moves a
-  // sufficient distance before the mouse is released, a drag session is
-  // initiated.
-  void Drag();
-
-  // Complete the current drag session. If the drag session was canceled
-  // because the user pressed Escape or something interrupted it, |canceled|
-  // is true so the helper can revert the state to the world before the drag
-  // begun. Returns whether the tab has been destroyed.
-  bool EndDrag(bool canceled);
-
-  // Retrieve the source tab if the TabContents specified matches the one being
-  // dragged by this controller, or NULL if the specified TabContents is not
-  // the same as the one being dragged.
-  TabGtk* GetDragSourceTabForContents(TabContents* contents) const;
-
-  // Returns true if the specified tab matches the tab being dragged.
-  bool IsDragSourceTab(const TabGtk* tab) const;
-
-  // Returns true if the specified tab is detached.
-  bool IsTabDetached(const TabGtk* tab) const;
-
- private:
-  // Enumeration of the ways a drag session can end.
-  enum EndDragType {
-    // Drag session exited normally: the user released the mouse.
-    NORMAL,
-
-    // The drag session was canceled (alt-tab during drag, escape ...)
-    CANCELED,
-
-    // The tab (NavigationController) was destroyed during the drag.
-    TAB_DESTROYED
-  };
-
-  // Overridden from TabContentsDelegate:
-  virtual void OpenURLFromTab(TabContents* source,
-                              const GURL& url,
-                              const GURL& referrer,
-                              WindowOpenDisposition disposition,
-                              PageTransition::Type transition);
-  virtual void NavigationStateChanged(const TabContents* source,
-                                      unsigned changed_flags);
-  virtual void AddNewContents(TabContents* source,
-                              TabContents* new_contents,
-                              WindowOpenDisposition disposition,
-                              const gfx::Rect& initial_pos,
-                              bool user_gesture);
-  virtual void ActivateContents(TabContents* contents);
-  virtual void DeactivateContents(TabContents* contents);
-  virtual void LoadingStateChanged(TabContents* source);
-  virtual void CloseContents(TabContents* source);
-  virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
-  virtual bool IsPopup(TabContents* source);
-  virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
-  virtual void URLStarredChanged(TabContents* source, bool starred);
-  virtual void UpdateTargetURL(TabContents* source, const GURL& url);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Initialize the offset used to calculate the position to create windows
-  // in |GetWindowCreatePoint|.
-  void InitWindowCreatePoint();
-
-  // Returns the point where a detached window should be created given the
-  // current mouse position.
-  gfx::Point GetWindowCreatePoint() const;
-
-  // Sets the TabContents being dragged with the specified |new_contents|.
-  void SetDraggedContents(TabContentsWrapper* new_contents);
-
-  // Move the DraggedTabView according to the current mouse screen position,
-  // potentially updating the source and other TabStrips.
-  void ContinueDragging();
-
-  // Handles moving the Tab within a TabStrip as well as updating the View.
-  void MoveTab(const gfx::Point& screen_point);
-
-  // Returns the compatible TabStrip that is under the specified point (screen
-  // coordinates), or NULL if there is none.
-  TabStripGtk* GetTabStripForPoint(const gfx::Point& screen_point);
-
-  // Returns the specified |tabstrip| if it contains the specified point
-  // (screen coordinates), NULL if it does not.
-  TabStripGtk* GetTabStripIfItContains(TabStripGtk* tabstrip,
-                                       const gfx::Point& screen_point) const;
-
-  // Attach the dragged Tab to the specified TabStrip.
-  void Attach(TabStripGtk* attached_tabstrip, const gfx::Point& screen_point);
-
-  // Detach the dragged Tab from the current TabStrip.
-  void Detach();
-
-  // Converts a screen point to a point relative to the tab strip.
-  gfx::Point ConvertScreenPointToTabStripPoint(TabStripGtk* tabstrip,
-                                               const gfx::Point& screen_point);
-
-  // Retrieve the bounds of the DraggedTabGtk, relative to the attached
-  // TabStrip, given location of the dragged tab in screen coordinates.
-  gfx::Rect GetDraggedTabTabStripBounds(const gfx::Point& screen_point);
-
-  // Returns the index where the dragged TabContents should be inserted into
-  // the attached TabStripModel given the DraggedTabView's bounds
-  // |dragged_bounds| in coordinates relative to the attached TabStrip.
-  // |is_tab_attached| is true if the tab has already been added.
-  int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds,
-                                        bool is_tab_attached) const;
-
-  // Get the position of the dragged tab relative to the attached tab strip.
-  gfx::Point GetDraggedTabPoint(const gfx::Point& screen_point);
-
-  // Finds the Tab within the specified TabStrip that corresponds to the
-  // dragged TabContents.
-  TabGtk* GetTabMatchingDraggedContents(TabStripGtk* tabstrip) const;
-
-  // Does the work for EndDrag. Returns whether the tab has been destroyed.
-  bool EndDragImpl(EndDragType how_end);
-
-  // If the drag was aborted for some reason, this function is called to un-do
-  // the changes made during the drag operation.
-  void RevertDrag();
-
-  // Finishes the drag operation. Returns true if the drag controller should
-  // be destroyed immediately, false otherwise.
-  bool CompleteDrag();
-
-  // Create the DraggedTabGtk if it does not yet exist.
-  void EnsureDraggedTab();
-
-  // Utility for getting the mouse position in screen coordinates.
-  gfx::Point GetCursorScreenPoint() const;
-
-  // Gets the screen bounds of a tab.
-  static gfx::Rect GetTabScreenBounds(TabGtk* tab);
-
-  // Utility to convert the specified TabStripModel index to something valid
-  // for the attached TabStrip.
-  int NormalizeIndexToAttachedTabStrip(int index) const;
-
-  // Hides the window that contains the tab strip the current drag session was
-  // initiated from.
-  void HideWindow();
-
-  // Presents the window that was hidden by HideWindow.
-  void ShowWindow();
-
-  // Closes a hidden frame at the end of a drag session.
-  void CleanUpHiddenFrame();
-
-  // Cleans up a source tab that is no longer used.
-  void CleanUpSourceTab();
-
-  // Completes the drag session after the view has animated to its final
-  // position.
-  void OnAnimateToBoundsComplete();
-
-  // Activates whichever window is under the mouse.
-  void BringWindowUnderMouseToFront();
-
-  // Handles registering for notifications.
-  NotificationRegistrar registrar_;
-
-  // The TabContents being dragged.
-  TabContentsWrapper* dragged_contents_;
-
-  // The original TabContentsDelegate of |dragged_contents_|, before it was
-  // detached from the browser window. We store this so that we can forward
-  // certain delegate notifications back to it if we can't handle them locally.
-  TabContentsDelegate* original_delegate_;
-
-  // The tab that initiated the drag session.
-  TabGtk* source_tab_;
-
-  // The tab strip |source_tab_| originated from.
-  TabStripGtk* source_tabstrip_;
-
-  // This is the index of the |source_tab_| in |source_tabstrip_| when the drag
-  // began. This is used to restore the previous state if the drag is aborted.
-  int source_model_index_;
-
-  // The TabStrip the dragged Tab is currently attached to, or NULL if the
-  // dragged Tab is detached.
-  TabStripGtk* attached_tabstrip_;
-
-  // The visual representation of the dragged Tab.
-  scoped_ptr<DraggedTabGtk> dragged_tab_;
-
-  // The position of the mouse (in screen coordinates) at the start of the drag
-  // operation. This is used to calculate minimum elasticity before a
-  // DraggedTabView is constructed.
-  gfx::Point start_screen_point_;
-
-  // This is the offset of the mouse from the top left of the Tab where
-  // dragging begun. This is used to ensure that the dragged view is always
-  // positioned at the correct location during the drag, and to ensure that the
-  // detached window is created at the right location.
-  gfx::Point mouse_offset_;
-
-  // A hint to use when positioning new windows created by detaching Tabs. This
-  // is the distance of the mouse from the top left of the dragged tab as if it
-  // were the distance of the mouse from the top left of the first tab in the
-  // attached TabStrip from the top left of the window.
-  gfx::Point window_create_point_;
-
-  // Whether we're in the destructor or not.  Makes sure we don't destroy the
-  // drag controller more than once.
-  bool in_destructor_;
-
-  // The horizontal position of the mouse cursor in screen coordinates at the
-  // time of the last re-order event.
-  int last_move_screen_x_;
-
-  // DockInfo for the tabstrip.
-  DockInfo dock_info_;
-
-  typedef std::set<GtkWidget*> DockWindows;
-  DockWindows dock_windows_;
-
-  // Is the tab mini?
-  const bool mini_;
-
-  // Is the tab pinned?
-  const bool pinned_;
-
-  // Timer used to bring the window under the cursor to front. If the user
-  // stops moving the mouse for a brief time over a browser window, it is
-  // brought to front.
-  base::OneShotTimer<DraggedTabControllerGtk> bring_to_front_timer_;
-
-  DISALLOW_COPY_AND_ASSIGN(DraggedTabControllerGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
deleted file mode 100644
index 299f183..0000000
--- a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tabs/dragged_tab_gtk.h"
-
-#include <gdk/gdk.h>
-
-#include <algorithm>
-
-#include "app/x11_util.h"
-#include "base/i18n/rtl.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/backing_store_x.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "gfx/gtk_util.h"
-#include "third_party/skia/include/core/SkShader.h"
-
-namespace {
-
-// The size of the dragged window frame.
-const int kDragFrameBorderSize = 1;
-const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize;
-
-// Used to scale the dragged window sizes.
-const float kScalingFactor = 0.5;
-
-const int kAnimateToBoundsDurationMs = 150;
-
-const gdouble kTransparentAlpha = (200.0f / 255.0f);
-const gdouble kOpaqueAlpha = 1.0f;
-const double kDraggedTabBorderColor[] = { 103.0 / 0xff,
-                                          129.0 / 0xff,
-                                          162.0 / 0xff };
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabGtk, public:
-
-DraggedTabGtk::DraggedTabGtk(TabContents* datasource,
-                             const gfx::Point& mouse_tab_offset,
-                             const gfx::Size& contents_size,
-                             bool mini)
-    : data_source_(datasource),
-      renderer_(new TabRendererGtk(datasource->profile()->GetThemeProvider())),
-      attached_(false),
-      mouse_tab_offset_(mouse_tab_offset),
-      attached_tab_size_(TabRendererGtk::GetMinimumSelectedSize()),
-      contents_size_(contents_size),
-      close_animation_(this) {
-  renderer_->UpdateData(datasource,
-                        datasource->is_app(),
-                        false); // loading_only
-  renderer_->set_mini(mini);
-
-  container_ = gtk_window_new(GTK_WINDOW_POPUP);
-  SetContainerColorMap();
-  gtk_widget_set_app_paintable(container_, TRUE);
-  g_signal_connect(container_, "expose-event",
-                   G_CALLBACK(OnExposeEvent), this);
-  gtk_widget_add_events(container_, GDK_STRUCTURE_MASK);
-
-  // We contain the tab renderer in a GtkFixed in order to maintain the
-  // requested size.  Otherwise, the widget will fill the entire window and
-  // cause a crash when rendering because the bounds don't match our images.
-  fixed_ = gtk_fixed_new();
-  gtk_fixed_put(GTK_FIXED(fixed_), renderer_->widget(), 0, 0);
-  gtk_container_add(GTK_CONTAINER(container_), fixed_);
-  gtk_widget_show_all(container_);
-}
-
-DraggedTabGtk::~DraggedTabGtk() {
-  gtk_widget_destroy(container_);
-}
-
-void DraggedTabGtk::MoveTo(const gfx::Point& screen_point) {
-  int x = screen_point.x() + mouse_tab_offset_.x() -
-      ScaleValue(mouse_tab_offset_.x());
-  int y = screen_point.y() + mouse_tab_offset_.y() -
-      ScaleValue(mouse_tab_offset_.y());
-
-  gtk_window_move(GTK_WINDOW(container_), x, y);
-}
-
-void DraggedTabGtk::Attach(int selected_width) {
-  attached_ = true;
-  Resize(selected_width);
-
-  if (gtk_util::IsScreenComposited())
-    gdk_window_set_opacity(container_->window, kOpaqueAlpha);
-}
-
-void DraggedTabGtk::Resize(int width) {
-  attached_tab_size_.set_width(width);
-  ResizeContainer();
-}
-
-void DraggedTabGtk::Detach() {
-  attached_ = false;
-  ResizeContainer();
-
-  if (gtk_util::IsScreenComposited())
-    gdk_window_set_opacity(container_->window, kTransparentAlpha);
-}
-
-void DraggedTabGtk::Update() {
-  gtk_widget_queue_draw(container_);
-}
-
-void DraggedTabGtk::AnimateToBounds(const gfx::Rect& bounds,
-                                    AnimateToBoundsCallback* callback) {
-  animation_callback_.reset(callback);
-
-  gint x, y, width, height;
-  gdk_window_get_origin(container_->window, &x, &y);
-  gdk_window_get_geometry(container_->window, NULL, NULL,
-                          &width, &height, NULL);
-
-  animation_start_bounds_ = gfx::Rect(x, y, width, height);
-  animation_end_bounds_ = bounds;
-
-  close_animation_.SetSlideDuration(kAnimateToBoundsDurationMs);
-  close_animation_.SetTweenType(ui::Tween::EASE_OUT);
-  if (!close_animation_.IsShowing()) {
-    close_animation_.Reset();
-    close_animation_.Show();
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabGtk, ui::AnimationDelegate implementation:
-
-void DraggedTabGtk::AnimationProgressed(const ui::Animation* animation) {
-  int delta_x = (animation_end_bounds_.x() - animation_start_bounds_.x());
-  int x = animation_start_bounds_.x() +
-      static_cast<int>(delta_x * animation->GetCurrentValue());
-  int y = animation_end_bounds_.y();
-  gdk_window_move(container_->window, x, y);
-}
-
-void DraggedTabGtk::AnimationEnded(const ui::Animation* animation) {
-  animation_callback_->Run();
-}
-
-void DraggedTabGtk::AnimationCanceled(const ui::Animation* animation) {
-  AnimationEnded(animation);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabGtk, private:
-
-void DraggedTabGtk::Layout() {
-  if (attached_) {
-    renderer_->SetBounds(gfx::Rect(GetPreferredSize()));
-  } else {
-    int left = 0;
-    if (base::i18n::IsRTL())
-      left = GetPreferredSize().width() - attached_tab_size_.width();
-
-    // The renderer_'s width should be attached_tab_size_.width() in both LTR
-    // and RTL locales. Wrong width will cause the wrong positioning of the tab
-    // view in dragging. Please refer to http://crbug.com/6223 for details.
-    renderer_->SetBounds(gfx::Rect(left, 0, attached_tab_size_.width(),
-                         attached_tab_size_.height()));
-  }
-}
-
-gfx::Size DraggedTabGtk::GetPreferredSize() {
-  if (attached_)
-    return attached_tab_size_;
-
-  int width = std::max(attached_tab_size_.width(), contents_size_.width()) +
-      kTwiceDragFrameBorderSize;
-  int height = attached_tab_size_.height() + kDragFrameBorderSize +
-      contents_size_.height();
-  return gfx::Size(width, height);
-}
-
-void DraggedTabGtk::ResizeContainer() {
-  gfx::Size size = GetPreferredSize();
-  gtk_window_resize(GTK_WINDOW(container_),
-                    ScaleValue(size.width()), ScaleValue(size.height()));
-  Layout();
-}
-
-int DraggedTabGtk::ScaleValue(int value) {
-  return attached_ ? value : static_cast<int>(value * kScalingFactor);
-}
-
-gfx::Rect DraggedTabGtk::bounds() const {
-  gint x, y, width, height;
-  gtk_window_get_position(GTK_WINDOW(container_), &x, &y);
-  gtk_window_get_size(GTK_WINDOW(container_), &width, &height);
-  return gfx::Rect(x, y, width, height);
-}
-
-void DraggedTabGtk::SetContainerColorMap() {
-  GdkScreen* screen = gtk_widget_get_screen(container_);
-  GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
-
-  // If rgba is not available, use rgb instead.
-  if (!colormap)
-    colormap = gdk_screen_get_rgb_colormap(screen);
-
-  gtk_widget_set_colormap(container_, colormap);
-}
-
-void DraggedTabGtk::SetContainerTransparency() {
-  cairo_t* cairo_context = gdk_cairo_create(container_->window);
-  if (!cairo_context)
-    return;
-
-  // Make the background of the dragged tab window fully transparent.  All of
-  // the content of the window (child widgets) will be completely opaque.
-  gfx::Size size = bounds().size();
-  cairo_scale(cairo_context, static_cast<double>(size.width()),
-              static_cast<double>(size.height()));
-  cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
-  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
-  cairo_paint(cairo_context);
-  cairo_destroy(cairo_context);
-}
-
-void DraggedTabGtk::SetContainerShapeMask(cairo_surface_t* surface) {
-  // Create a 1bpp bitmap the size of |container_|.
-  gfx::Size size = bounds().size();
-  GdkPixmap* pixmap = gdk_pixmap_new(NULL, size.width(), size.height(), 1);
-  cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(pixmap));
-
-  // Set the transparency.
-  cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
-
-  // Blit the rendered bitmap into a pixmap.  Any pixel set in the pixmap will
-  // be opaque in the container window.
-  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
-  if (!attached_)
-    cairo_scale(cairo_context, kScalingFactor, kScalingFactor);
-  cairo_set_source_surface(cairo_context, surface, 0, 0);
-  cairo_paint(cairo_context);
-
-  if (!attached_) {
-    // Make the render area depiction opaque (leaving enough room for the
-    // border).
-    cairo_identity_matrix(cairo_context);
-    // On Lucid running VNC, the X server will reject RGBA (1,1,1,1) as an
-    // invalid value below in gdk_window_shape_combine_mask(). Using (0,0,0,1)
-    // instead. The value doesn't really matter, as long as the alpha is not 0.
-    cairo_set_source_rgba(cairo_context, 0.0f, 0.0f, 0.0f, 1.0f);
-    int tab_height = static_cast<int>(kScalingFactor *
-                                      renderer_->height() -
-                                      kDragFrameBorderSize);
-    cairo_rectangle(cairo_context,
-                    0, tab_height,
-                    size.width(), size.height() - tab_height);
-    cairo_fill(cairo_context);
-  }
-
-  cairo_destroy(cairo_context);
-
-  // Set the shape mask.
-  gdk_window_shape_combine_mask(container_->window, pixmap, 0, 0);
-  g_object_unref(pixmap);
-}
-
-// static
-gboolean DraggedTabGtk::OnExposeEvent(GtkWidget* widget,
-                                      GdkEventExpose* event,
-                                      DraggedTabGtk* dragged_tab) {
-  cairo_surface_t* surface = dragged_tab->renderer_->PaintToSurface();
-  if (gtk_util::IsScreenComposited()) {
-    dragged_tab->SetContainerTransparency();
-  } else {
-    dragged_tab->SetContainerShapeMask(surface);
-  }
-
-  // Only used when not attached.
-  int tab_width = static_cast<int>(kScalingFactor *
-      dragged_tab->renderer_->width());
-  int tab_height = static_cast<int>(kScalingFactor *
-      dragged_tab->renderer_->height());
-
-  // Draw the render area.
-  BackingStore* backing_store =
-      dragged_tab->data_source_->render_view_host()->GetBackingStore(false);
-  if (backing_store && !dragged_tab->attached_) {
-    // This leaves room for the border.
-    static_cast<BackingStoreX*>(backing_store)->PaintToRect(
-        gfx::Rect(kDragFrameBorderSize, tab_height,
-                  widget->allocation.width - kTwiceDragFrameBorderSize,
-                  widget->allocation.height - tab_height -
-                  kDragFrameBorderSize),
-        GDK_DRAWABLE(widget->window));
-  }
-
-  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
-  // Draw the border.
-  if (!dragged_tab->attached_) {
-    cairo_set_line_width(cr, kDragFrameBorderSize);
-    cairo_set_source_rgb(cr, kDraggedTabBorderColor[0],
-                             kDraggedTabBorderColor[1],
-                             kDraggedTabBorderColor[2]);
-    // |offset| is the distance from the edge of the image to the middle of
-    // the border line.
-    double offset = kDragFrameBorderSize / 2.0 - 0.5;
-    double left_x = offset;
-    double top_y = tab_height - kDragFrameBorderSize + offset;
-    double right_x = widget->allocation.width - offset;
-    double bottom_y = widget->allocation.height - offset;
-    double middle_x = tab_width + offset;
-
-    // We don't use cairo_rectangle() because we don't want to draw the border
-    // under the tab itself.
-    cairo_move_to(cr, left_x, top_y);
-    cairo_line_to(cr, left_x, bottom_y);
-    cairo_line_to(cr, right_x, bottom_y);
-    cairo_line_to(cr, right_x, top_y);
-    cairo_line_to(cr, middle_x, top_y);
-    cairo_stroke(cr);
-  }
-
-  // Draw the tab.
-  if (!dragged_tab->attached_)
-    cairo_scale(cr, kScalingFactor, kScalingFactor);
-  cairo_set_source_surface(cr, surface, 0, 0);
-  cairo_paint(cr);
-
-  cairo_destroy(cr);
-
-  cairo_surface_destroy(surface);
-
-  // We've already drawn the tab, so don't propagate the expose-event signal.
-  return TRUE;
-}
diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_gtk.h
deleted file mode 100644
index ae4c0f1..0000000
--- a/chrome/browser/gtk/tabs/dragged_tab_gtk.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TABS_DRAGGED_TAB_GTK_H_
-#define CHROME_BROWSER_GTK_TABS_DRAGGED_TAB_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "base/callback.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "gfx/canvas.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-
-class TabContents;
-class TabRendererGtk;
-
-class DraggedTabGtk : public ui::AnimationDelegate {
- public:
-  DraggedTabGtk(TabContents* datasource,
-                const gfx::Point& mouse_tab_offset,
-                const gfx::Size& contents_size,
-                bool mini);
-  virtual ~DraggedTabGtk();
-
-  // Moves the dragged tab to the appropriate location given the mouse
-  // pointer at |screen_point|.
-  void MoveTo(const gfx::Point& screen_point);
-
-  // Sets the offset of the mouse from the upper left corner of the tab.
-  void set_mouse_tab_offset(const gfx::Point& offset) {
-    mouse_tab_offset_ = offset;
-  }
-
-  // Notifies the dragged tab that it has become attached to a tabstrip.
-  void Attach(int selected_width);
-
-  // Resizes the dragged tab to a width of |width|.
-  void Resize(int width);
-
-  // Notifies the dragged tab that it has been detached from a tabstrip.
-  void Detach();
-
-  // Notifies the dragged tab that it should update itself.
-  void Update();
-
-  // Animates the dragged tab to the specified bounds, then calls back to
-  // |callback|.
-  typedef Callback0::Type AnimateToBoundsCallback;
-  void AnimateToBounds(const gfx::Rect& bounds,
-                       AnimateToBoundsCallback* callback);
-
-  // Returns the size of the dragged tab. Used when attaching to a tabstrip
-  // to determine where to place the tab in the attached tabstrip.
-  const gfx::Size& attached_tab_size() const { return attached_tab_size_; }
-
-  GtkWidget* widget() const { return container_; }
-
- private:
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-  virtual void AnimationCanceled(const ui::Animation* animation);
-
-  // Arranges the contents of the dragged tab.
-  void Layout();
-
-  // Gets the preferred size of the dragged tab.
-  gfx::Size GetPreferredSize();
-
-  // Resizes the container to fit the content for the current attachment mode.
-  void ResizeContainer();
-
-  // Utility for scaling a size by the current scaling factor.
-  int ScaleValue(int value);
-
-  // Returns the bounds of the container window.
-  gfx::Rect bounds() const;
-
-  // Sets the color map of the container window to allow the window to be
-  // transparent.
-  void SetContainerColorMap();
-
-  // Sets full transparency for the container window.  This is used if
-  // compositing is available for the screen.
-  void SetContainerTransparency();
-
-  // Sets the shape mask for the container window to emulate a transparent
-  // container window.  This is used if compositing is not available for the
-  // screen.
-  // |surface| represents the tab only (not the render view).
-  void SetContainerShapeMask(cairo_surface_t* surface);
-
-  // expose-event handler that notifies when the tab needs to be redrawn.
-  static gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event,
-                                DraggedTabGtk* dragged_tab);
-
-  // The tab contents that the dragged tab contains.
-  TabContents* data_source_;
-
-  // The window that contains the dragged tab or tab contents.
-  GtkWidget* container_;
-
-  // The fixed widget that we use to contain the tab renderer so that the
-  // tab widget won't be resized.
-  GtkWidget* fixed_;
-
-  // The renderer that paints the dragged tab.
-  scoped_ptr<TabRendererGtk> renderer_;
-
-  // True if the view is currently attached to a tabstrip. Controls rendering
-  // and sizing modes.
-  bool attached_;
-
-  // The unscaled offset of the mouse from the top left of the dragged tab.
-  // This is used to maintain an appropriate offset for the mouse pointer when
-  // dragging scaled and unscaled representations, and also to calculate the
-  // position of detached windows.
-  gfx::Point mouse_tab_offset_;
-
-  // The size of the tab renderer when the dragged tab is attached to a
-  // tabstrip.
-  gfx::Size attached_tab_size_;
-
-  // The dimensions of the TabContents being dragged.
-  gfx::Size contents_size_;
-
-  // The animation used to slide the attached tab to its final location.
-  ui::SlideAnimation close_animation_;
-
-  // A callback notified when the animation is complete.
-  scoped_ptr<Callback0::Type> animation_callback_;
-
-  // The start and end bounds of the animation sequence.
-  gfx::Rect animation_start_bounds_;
-  gfx::Rect animation_end_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(DraggedTabGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TABS_DRAGGED_TAB_GTK_H_
diff --git a/chrome/browser/gtk/tabs/tab_gtk.cc b/chrome/browser/gtk/tabs/tab_gtk.cc
deleted file mode 100644
index c0f8e82..0000000
--- a/chrome/browser/gtk/tabs/tab_gtk.cc
+++ /dev/null
@@ -1,398 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tabs/tab_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-
-#include "app/gtk_dnd_util.h"
-#include "app/menus/accelerator_gtk.h"
-#include "base/singleton.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gtk/accelerators_gtk.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "chrome/browser/ui/tabs/tab_menu_model.h"
-#include "gfx/path.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// Returns the width of the title for the current font, in pixels.
-int GetTitleWidth(gfx::Font* font, string16 title) {
-  DCHECK(font);
-  if (title.empty())
-    return 0;
-
-  return font->GetStringWidth(title);
-}
-
-}  // namespace
-
-class TabGtk::ContextMenuController : public menus::SimpleMenuModel::Delegate,
-                                      public MenuGtk::Delegate {
- public:
-  explicit ContextMenuController(TabGtk* tab)
-      : tab_(tab),
-        model_(this, tab->delegate()->IsTabPinned(tab)) {
-    menu_.reset(new MenuGtk(this, &model_));
-  }
-
-  virtual ~ContextMenuController() {}
-
-  void RunMenu() {
-    menu_->PopupAsContext(gtk_get_current_event_time());
-  }
-
-  void Cancel() {
-    tab_ = NULL;
-    menu_->Cancel();
-  }
-
- private:
-  // Overridden from menus::SimpleMenuModel::Delegate:
-  virtual bool IsCommandIdChecked(int command_id) const {
-    return false;
-  }
-  virtual bool IsCommandIdEnabled(int command_id) const {
-    return tab_ && tab_->delegate()->IsCommandEnabledForTab(
-        static_cast<TabStripModel::ContextMenuCommand>(command_id),
-        tab_);
-  }
-  virtual bool GetAcceleratorForCommandId(
-      int command_id,
-      menus::Accelerator* accelerator) {
-    int browser_command;
-    if (!TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
-                                                           &browser_command))
-      return false;
-    const menus::AcceleratorGtk* accelerator_gtk =
-        AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(
-            browser_command);
-    if (accelerator_gtk)
-      *accelerator = *accelerator_gtk;
-    return !!accelerator_gtk;
-  }
-
-  virtual void ExecuteCommand(int command_id) {
-    if (!tab_)
-      return;
-    tab_->delegate()->ExecuteCommandForTab(
-        static_cast<TabStripModel::ContextMenuCommand>(command_id), tab_);
-  }
-
-  GtkWidget* GetImageForCommandId(int command_id) const {
-    int browser_cmd_id;
-    return TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
-                                                             &browser_cmd_id) ?
-        MenuGtk::Delegate::GetDefaultImageForCommandId(browser_cmd_id) :
-        NULL;
-  }
-
-  // The context menu.
-  scoped_ptr<MenuGtk> menu_;
-
-  // The Tab the context menu was brought up for. Set to NULL when the menu
-  // is canceled.
-  TabGtk* tab_;
-
-  // The model.
-  TabMenuModel model_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
-};
-
-class TabGtk::TabGtkObserverHelper {
- public:
-  explicit TabGtkObserverHelper(TabGtk* tab)
-      : tab_(tab) {
-    MessageLoopForUI::current()->AddObserver(tab_);
-  }
-
-  ~TabGtkObserverHelper() {
-    MessageLoopForUI::current()->RemoveObserver(tab_);
-  }
-
- private:
-  TabGtk* tab_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabGtkObserverHelper);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// TabGtk, public:
-
-TabGtk::TabGtk(TabDelegate* delegate)
-    : TabRendererGtk(delegate->GetThemeProvider()),
-      delegate_(delegate),
-      closing_(false),
-      dragging_(false),
-      last_mouse_down_(NULL),
-      drag_widget_(NULL),
-      title_width_(0),
-      ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)),
-      ALLOW_THIS_IN_INITIALIZER_LIST(drag_end_factory_(this)) {
-  event_box_ = gtk_event_box_new();
-  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
-  g_signal_connect(event_box_, "button-press-event",
-                   G_CALLBACK(OnButtonPressEventThunk), this);
-  g_signal_connect(event_box_, "button-release-event",
-                   G_CALLBACK(OnButtonReleaseEventThunk), this);
-  g_signal_connect(event_box_, "enter-notify-event",
-                   G_CALLBACK(OnEnterNotifyEventThunk), this);
-  g_signal_connect(event_box_, "leave-notify-event",
-                   G_CALLBACK(OnLeaveNotifyEventThunk), this);
-  gtk_widget_add_events(event_box_,
-        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-        GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
-  gtk_container_add(GTK_CONTAINER(event_box_), TabRendererGtk::widget());
-  gtk_widget_show_all(event_box_);
-}
-
-TabGtk::~TabGtk() {
-  if (drag_widget_) {
-    // Shadow the drag grab so the grab terminates. We could do this using any
-    // widget, |drag_widget_| is just convenient.
-    gtk_grab_add(drag_widget_);
-    gtk_grab_remove(drag_widget_);
-    DestroyDragWidget();
-  }
-
-  if (menu_controller_.get()) {
-    // The menu is showing. Close the menu.
-    menu_controller_->Cancel();
-
-    // Invoke this so that we hide the highlight.
-    ContextMenuClosed();
-  }
-}
-
-gboolean TabGtk::OnButtonPressEvent(GtkWidget* widget, GdkEventButton* event) {
-  // Every button press ensures either a button-release-event or a drag-fail
-  // signal for |widget|.
-  if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
-    // Store whether or not we were selected just now... we only want to be
-    // able to drag foreground tabs, so we don't start dragging the tab if
-    // it was in the background.
-    bool just_selected = !IsSelected();
-    if (just_selected) {
-      delegate_->SelectTab(this);
-    }
-
-    // Hook into the message loop to handle dragging.
-    observer_.reset(new TabGtkObserverHelper(this));
-
-    // Store the button press event, used to initiate a drag.
-    last_mouse_down_ = gdk_event_copy(reinterpret_cast<GdkEvent*>(event));
-  } else if (event->button == 3) {
-    // Only show the context menu if the left mouse button isn't down (i.e.,
-    // the user might want to drag instead).
-    if (!last_mouse_down_)
-      ShowContextMenu();
-  }
-
-  return TRUE;
-}
-
-gboolean TabGtk::OnButtonReleaseEvent(GtkWidget* widget,
-                                      GdkEventButton* event) {
-  if (event->button == 1) {
-    observer_.reset();
-
-    if (last_mouse_down_) {
-      gdk_event_free(last_mouse_down_);
-      last_mouse_down_ = NULL;
-    }
-  }
-
-  // Middle mouse up means close the tab, but only if the mouse is over it
-  // (like a button).
-  if (event->button == 2 &&
-      event->x >= 0 && event->y >= 0 &&
-      event->x < widget->allocation.width &&
-      event->y < widget->allocation.height) {
-    // If the user is currently holding the left mouse button down but hasn't
-    // moved the mouse yet, a drag hasn't started yet.  In that case, clean up
-    // some state before closing the tab to avoid a crash.  Once the drag has
-    // started, we don't get the middle mouse click here.
-    if (last_mouse_down_) {
-      DCHECK(!drag_widget_);
-      observer_.reset();
-      gdk_event_free(last_mouse_down_);
-      last_mouse_down_ = NULL;
-    }
-    delegate_->CloseTab(this);
-  }
-
-  return TRUE;
-}
-
-gboolean TabGtk::OnDragFailed(GtkWidget* widget, GdkDragContext* context,
-                              GtkDragResult result) {
-  bool canceled = (result == GTK_DRAG_RESULT_USER_CANCELLED);
-  EndDrag(canceled);
-  return TRUE;
-}
-
-gboolean TabGtk::OnDragButtonReleased(GtkWidget* widget,
-                                      GdkEventButton* button) {
-  // We always get this event when gtk is releasing the grab and ending the
-  // drag.  However, if the user ended the drag with space or enter, we don't
-  // get a follow up event to tell us the drag has finished (either a
-  // drag-failed or a drag-end).  So we post a task to manually end the drag.
-  // If GTK+ does send the drag-failed or drag-end event, we cancel the task.
-  MessageLoop::current()->PostTask(FROM_HERE,
-      drag_end_factory_.NewRunnableMethod(&TabGtk::EndDrag, false));
-  return TRUE;
-}
-
-void TabGtk::OnDragBegin(GtkWidget* widget, GdkDragContext* context) {
-  GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
-  gtk_drag_set_icon_pixbuf(context, pixbuf, 0, 0);
-  g_object_unref(pixbuf);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabGtk, MessageLoop::Observer implementation:
-
-void TabGtk::WillProcessEvent(GdkEvent* event) {
-  // Nothing to do.
-}
-
-void TabGtk::DidProcessEvent(GdkEvent* event) {
-  if (!(event->type == GDK_MOTION_NOTIFY || event->type == GDK_LEAVE_NOTIFY ||
-        event->type == GDK_ENTER_NOTIFY)) {
-    return;
-  }
-
-  if (drag_widget_) {
-    delegate_->ContinueDrag(NULL);
-    return;
-  }
-
-  gint old_x = static_cast<gint>(last_mouse_down_->button.x_root);
-  gint old_y = static_cast<gint>(last_mouse_down_->button.y_root);
-  gdouble new_x;
-  gdouble new_y;
-  gdk_event_get_root_coords(event, &new_x, &new_y);
-
-  if (gtk_drag_check_threshold(widget(), old_x, old_y,
-      static_cast<gint>(new_x), static_cast<gint>(new_y))) {
-    StartDragging(gfx::Point(
-        static_cast<int>(last_mouse_down_->button.x),
-        static_cast<int>(last_mouse_down_->button.y)));
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabGtk, TabRendererGtk overrides:
-
-bool TabGtk::IsSelected() const {
-  return delegate_->IsTabSelected(this);
-}
-
-bool TabGtk::IsVisible() const {
-  return GTK_WIDGET_FLAGS(event_box_) & GTK_VISIBLE;
-}
-
-void TabGtk::SetVisible(bool visible) const {
-  if (visible) {
-    gtk_widget_show(event_box_);
-  } else {
-    gtk_widget_hide(event_box_);
-  }
-}
-
-void TabGtk::CloseButtonClicked() {
-  delegate_->CloseTab(this);
-}
-
-void TabGtk::UpdateData(TabContents* contents, bool app, bool loading_only) {
-  TabRendererGtk::UpdateData(contents, app, loading_only);
-  // Cache the title width so we don't recalculate it every time the tab is
-  // resized.
-  title_width_ = GetTitleWidth(title_font(), GetTitle());
-  UpdateTooltipState();
-}
-
-void TabGtk::SetBounds(const gfx::Rect& bounds) {
-  TabRendererGtk::SetBounds(bounds);
-  UpdateTooltipState();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabGtk, private:
-
-void TabGtk::ShowContextMenu() {
-  menu_controller_.reset(new ContextMenuController(this));
-  menu_controller_->RunMenu();
-}
-
-void TabGtk::ContextMenuClosed() {
-  delegate()->StopAllHighlighting();
-  menu_controller_.reset();
-}
-
-void TabGtk::UpdateTooltipState() {
-  // Only show the tooltip if the title is truncated.
-  if (title_width_ > title_bounds().width()) {
-    gtk_widget_set_tooltip_text(widget(), UTF16ToUTF8(GetTitle()).c_str());
-  } else {
-    gtk_widget_set_has_tooltip(widget(), FALSE);
-  }
-}
-
-void TabGtk::CreateDragWidget() {
-  DCHECK(!drag_widget_);
-  drag_widget_ = gtk_invisible_new();
-  g_signal_connect(drag_widget_, "drag-failed",
-                   G_CALLBACK(OnDragFailedThunk), this);
-  g_signal_connect(drag_widget_, "button-release-event",
-                   G_CALLBACK(OnDragButtonReleasedThunk), this);
-  g_signal_connect_after(drag_widget_, "drag-begin",
-                         G_CALLBACK(OnDragBeginThunk), this);
-}
-
-void TabGtk::DestroyDragWidget() {
-  if (drag_widget_) {
-    gtk_widget_destroy(drag_widget_);
-    drag_widget_ = NULL;
-  }
-}
-
-void TabGtk::StartDragging(gfx::Point drag_offset) {
-  CreateDragWidget();
-
-  GtkTargetList* list = gtk_dnd_util::GetTargetListFromCodeMask(
-      gtk_dnd_util::CHROME_TAB);
-  gtk_drag_begin(drag_widget_, list, GDK_ACTION_MOVE,
-                 1,  // Drags are always initiated by the left button.
-                 last_mouse_down_);
-
-  delegate_->MaybeStartDrag(this, drag_offset);
-}
-
-void TabGtk::EndDrag(bool canceled) {
-  // Make sure we only run EndDrag once by canceling any tasks that want
-  // to call EndDrag.
-  drag_end_factory_.RevokeAll();
-
-  // We must let gtk clean up after we handle the drag operation, otherwise
-  // there will be outstanding references to the drag widget when we try to
-  // destroy it.
-  MessageLoop::current()->PostTask(FROM_HERE,
-      destroy_factory_.NewRunnableMethod(&TabGtk::DestroyDragWidget));
-
-  if (last_mouse_down_) {
-    gdk_event_free(last_mouse_down_);
-    last_mouse_down_ = NULL;
-  }
-
-  // Notify the drag helper that we're done with any potential drag operations.
-  // Clean up the drag helper, which is re-created on the next mouse press.
-  delegate_->EndDrag(canceled);
-
-  observer_.reset();
-}
diff --git a/chrome/browser/gtk/tabs/tab_gtk.h b/chrome/browser/gtk/tabs/tab_gtk.h
deleted file mode 100644
index 804656e..0000000
--- a/chrome/browser/gtk/tabs/tab_gtk.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TABS_TAB_GTK_H_
-#define CHROME_BROWSER_GTK_TABS_TAB_GTK_H_
-#pragma once
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-
-namespace gfx {
-class Path;
-}
-
-class ThemeProvider;
-
-class TabGtk : public TabRendererGtk,
-               public MessageLoopForUI::Observer {
- public:
-  // An interface implemented by an object that can help this Tab complete
-  // various actions. The index parameter is the index of this Tab in the
-  // TabRenderer::Model.
-  class TabDelegate {
-   public:
-    // Returns true if the specified Tab is selected.
-    virtual bool IsTabSelected(const TabGtk* tab) const = 0;
-
-    // Returns true if the specified Tab is pinned.
-    virtual bool IsTabPinned(const TabGtk* tab) const = 0;
-
-    // Returns true if the specified Tab is detached.
-    virtual bool IsTabDetached(const TabGtk* tab) const = 0;
-
-    // Selects the specified Tab.
-    virtual void SelectTab(TabGtk* tab) = 0;
-
-    // Closes the specified Tab.
-    virtual void CloseTab(TabGtk* tab) = 0;
-
-    // Returns true if the specified command is enabled for the specified Tab.
-    virtual bool IsCommandEnabledForTab(
-        TabStripModel::ContextMenuCommand command_id,
-        const TabGtk* tab) const = 0;
-
-    // Executes the specified command for the specified Tab.
-    virtual void ExecuteCommandForTab(
-        TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
-
-    // Starts/Stops highlighting the tabs that will be affected by the
-    // specified command for the specified Tab.
-    virtual void StartHighlightTabsForCommand(
-        TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
-    virtual void StopHighlightTabsForCommand(
-        TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
-    virtual void StopAllHighlighting() = 0;
-
-    // Potentially starts a drag for the specified Tab.
-    virtual void MaybeStartDrag(TabGtk* tab, const gfx::Point& point) = 0;
-
-    // Continues dragging a Tab.
-    virtual void ContinueDrag(GdkDragContext* context) = 0;
-
-    // Ends dragging a Tab. |canceled| is true if the drag was aborted in a way
-    // other than the user releasing the mouse. Returns whether the tab has been
-    // destroyed.
-    virtual bool EndDrag(bool canceled) = 0;
-
-    // Returns true if the associated TabStrip's delegate supports tab moving or
-    // detaching. Used by the Frame to determine if dragging on the Tab
-    // itself should move the window in cases where there's only one
-    // non drag-able Tab.
-    virtual bool HasAvailableDragActions() const = 0;
-
-    // Returns the theme provider for icons and colors.
-    virtual ThemeProvider* GetThemeProvider() = 0;
-
-   protected:
-    virtual ~TabDelegate() {}
-  };
-
-  explicit TabGtk(TabDelegate* delegate);
-  virtual ~TabGtk();
-
-  // Access the delegate.
-  TabDelegate* delegate() const { return delegate_; }
-
-  GtkWidget* widget() const { return event_box_; }
-
-  // Used to set/check whether this Tab is being animated closed.
-  void set_closing(bool closing) { closing_ = closing; }
-  bool closing() const { return closing_; }
-
-  // Used to set/check whether this Tab is being dragged.
-  void set_dragging(bool dragging) { dragging_ = dragging; }
-  bool dragging() const { return dragging_; }
-
-  // TabRendererGtk overrides:
-  virtual bool IsSelected() const;
-  virtual bool IsVisible() const;
-  virtual void SetVisible(bool visible) const;
-  virtual void CloseButtonClicked();
-  virtual void UpdateData(TabContents* contents, bool app, bool loading_only);
-  virtual void SetBounds(const gfx::Rect& bounds);
-
- private:
-  class ContextMenuController;
-  class TabGtkObserverHelper;
-  friend class ContextMenuController;
-
-  // MessageLoop::Observer implementation:
-  virtual void WillProcessEvent(GdkEvent* event);
-  virtual void DidProcessEvent(GdkEvent* event);
-
-  // button-press-event handler that handles mouse clicks.
-  CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnButtonPressEvent, GdkEventButton*);
-
-  // button-release-event handler that handles mouse click releases.
-  CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnButtonReleaseEvent, GdkEventButton*);
-
-  // drag-begin is emitted when the drag is started. We connect so that we can
-  // set the drag icon to a transparent pixbuf.
-  CHROMEGTK_CALLBACK_1(TabGtk, void, OnDragBegin, GdkDragContext*);
-
-  // drag-failed is emitted when the drag is finished.  In our case the signal
-  // does not imply failure as we don't use the drag-n-drop API to transfer drop
-  // data.
-  CHROMEGTK_CALLBACK_2(TabGtk, gboolean, OnDragFailed, GdkDragContext*,
-                       GtkDragResult);
-
-  // When a drag is ending, a fake button release event is passed to the drag
-  // widget to fake letting go of the mouse button.  We need a callback for
-  // this event because it is the only way to catch drag end events when the
-  // user presses space or return.
-  CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnDragButtonReleased, GdkEventButton*);
-
-  // Shows the context menu.
-  void ShowContextMenu();
-
-  // Invoked when the context menu closes.
-  void ContextMenuClosed();
-
-  // Sets whether the tooltip should be shown or not, depending on the size of
-  // the tab.
-  void UpdateTooltipState();
-
-  // Creates the drag widget used to track a drag operation.
-  void CreateDragWidget();
-
-  // Destroys the drag widget.
-  void DestroyDragWidget();
-
-  // Starts the dragging operation.  |drag_offset| is the offset inside the tab
-  // bounds where the grab occurred.
-  void StartDragging(gfx::Point drag_offset);
-
-  // Ends the dragging operations.  |canceled| is true if the operation was
-  // canceled.
-  void EndDrag(bool canceled);
-
-  // An instance of a delegate object that can perform various actions based on
-  // user gestures.
-  TabDelegate* delegate_;
-
-  // True if the tab is being animated closed.
-  bool closing_;
-
-  // True if the tab is being dragged.
-  bool dragging_;
-
-  // The context menu controller.
-  scoped_ptr<ContextMenuController> menu_controller_;
-
-  // The windowless widget used to collect input events for the tab.  We can't
-  // use an OwnedWidgetGtk because of the way the dragged tab controller
-  // destroys the source tab.  The source tab is destroyed when the drag ends
-  // before we let gtk handle the end of the drag.  This results in the widget
-  // having an extra reference, which will cause OwnedWidgetGtk.Destroy to
-  // DCHECK.
-  GtkWidget* event_box_;
-
-  // A copy of the last button press event, used to initiate a drag.
-  GdkEvent* last_mouse_down_;
-
-  // A GtkInivisible used to track the drag event.  GtkInvisibles are of the
-  // type GInitiallyUnowned, but the widget initialization code sinks the
-  // reference, so we can't used an OwnedWidgetGtk here.
-  GtkWidget* drag_widget_;
-
-  // The cached width of the title in pixels, updated whenever the title
-  // changes.
-  int title_width_;
-
-  // Keep track of whether or not we have an observer.
-  scoped_ptr<TabGtkObserverHelper> observer_;
-
-  // Used to destroy the drag widget after a return to the message loop.
-  ScopedRunnableMethodFactory<TabGtk> destroy_factory_;
-
-  // Due to a bug in GTK+, we need to force the end of a drag when we get a
-  // mouse release event on the the dragged widget, otherwise, we don't know
-  // when the drag has ended when the user presses space or enter.  We queue
-  // a task to end the drag and only run it if GTK+ didn't send us the
-  // drag-failed event.
-  ScopedRunnableMethodFactory<TabGtk> drag_end_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TABS_TAB_GTK_H_
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
deleted file mode 100644
index b3f1c91..0000000
--- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
+++ /dev/null
@@ -1,1085 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/favicon_size.h"
-#include "gfx/platform_font_gtk.h"
-#include "gfx/skbitmap_operations.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/animation/slide_animation.h"
-#include "ui/base/animation/throb_animation.h"
-
-namespace {
-
-const int kLeftPadding = 16;
-const int kTopPadding = 6;
-const int kRightPadding = 15;
-const int kBottomPadding = 5;
-const int kDropShadowHeight = 2;
-const int kFavIconTitleSpacing = 4;
-const int kTitleCloseButtonSpacing = 5;
-const int kStandardTitleWidth = 175;
-const int kDropShadowOffset = 2;
-const int kInactiveTabBackgroundOffsetY = 15;
-
-// When a non-mini-tab becomes a mini-tab the width of the tab animates. If
-// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab
-// is rendered as a normal tab. This is done to avoid having the title
-// immediately disappear when transitioning a tab from normal to mini-tab.
-const int kMiniTabRendererAsNormalTabWidth =
-    browser_defaults::kMiniTabWidth + 30;
-
-// The tab images are designed to overlap the toolbar by 1 pixel. For now we
-// don't actually overlap the toolbar, so this is used to know how many pixels
-// at the bottom of the tab images are to be ignored.
-const int kToolbarOverlap = 1;
-
-// How long the hover state takes.
-const int kHoverDurationMs = 90;
-
-// How opaque to make the hover state (out of 1).
-const double kHoverOpacity = 0.33;
-
-// Max opacity for the mini-tab title change animation.
-const double kMiniTitleChangeThrobOpacity = 0.75;
-
-// Duration for when the title of an inactive mini-tab changes.
-const int kMiniTitleChangeThrobDuration = 1000;
-
-const SkScalar kTabCapWidth = 15;
-const SkScalar kTabTopCurveWidth = 4;
-const SkScalar kTabBottomCurveWidth = 3;
-
-// The vertical and horizontal offset used to position the close button
-// in the tab. TODO(jhawkins): Ask pkasting what the Fuzz is about.
-const int kCloseButtonVertFuzz = 0;
-const int kCloseButtonHorzFuzz = 5;
-
-SkBitmap* crashed_fav_icon = NULL;
-
-// Gets the bounds of |widget| relative to |parent|.
-gfx::Rect GetWidgetBoundsRelativeToParent(GtkWidget* parent,
-                                          GtkWidget* widget) {
-  gfx::Point parent_pos = gtk_util::GetWidgetScreenPosition(parent);
-  gfx::Point widget_pos = gtk_util::GetWidgetScreenPosition(widget);
-  return gfx::Rect(widget_pos.x() - parent_pos.x(),
-                   widget_pos.y() - parent_pos.y(),
-                   widget->allocation.width, widget->allocation.height);
-}
-
-}  // namespace
-
-TabRendererGtk::LoadingAnimation::Data::Data(ThemeProvider* theme_provider) {
-  // The loading animation image is a strip of states. Each state must be
-  // square, so the height must divide the width evenly.
-  loading_animation_frames = theme_provider->GetBitmapNamed(IDR_THROBBER);
-  DCHECK(loading_animation_frames);
-  DCHECK_EQ(loading_animation_frames->width() %
-            loading_animation_frames->height(), 0);
-  loading_animation_frame_count =
-      loading_animation_frames->width() /
-      loading_animation_frames->height();
-
-  waiting_animation_frames =
-      theme_provider->GetBitmapNamed(IDR_THROBBER_WAITING);
-  DCHECK(waiting_animation_frames);
-  DCHECK_EQ(waiting_animation_frames->width() %
-            waiting_animation_frames->height(), 0);
-  waiting_animation_frame_count =
-      waiting_animation_frames->width() /
-      waiting_animation_frames->height();
-
-  waiting_to_loading_frame_count_ratio =
-      waiting_animation_frame_count /
-      loading_animation_frame_count;
-  // TODO(beng): eventually remove this when we have a proper themeing system.
-  //             themes not supporting IDR_THROBBER_WAITING are causing this
-  //             value to be 0 which causes DIV0 crashes. The value of 5
-  //             matches the current bitmaps in our source.
-  if (waiting_to_loading_frame_count_ratio == 0)
-    waiting_to_loading_frame_count_ratio = 5;
-}
-
-TabRendererGtk::LoadingAnimation::Data::Data(
-    int loading, int waiting, int waiting_to_loading)
-    : waiting_animation_frames(NULL),
-      loading_animation_frames(NULL),
-      loading_animation_frame_count(loading),
-      waiting_animation_frame_count(waiting),
-      waiting_to_loading_frame_count_ratio(waiting_to_loading) {
-}
-
-bool TabRendererGtk::initialized_ = false;
-TabRendererGtk::TabImage TabRendererGtk::tab_active_ = {0};
-TabRendererGtk::TabImage TabRendererGtk::tab_inactive_ = {0};
-TabRendererGtk::TabImage TabRendererGtk::tab_alpha_ = {0};
-gfx::Font* TabRendererGtk::title_font_ = NULL;
-int TabRendererGtk::title_font_height_ = 0;
-int TabRendererGtk::close_button_width_ = 0;
-int TabRendererGtk::close_button_height_ = 0;
-SkColor TabRendererGtk::selected_title_color_ = SK_ColorBLACK;
-SkColor TabRendererGtk::unselected_title_color_ = SkColorSetRGB(64, 64, 64);
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRendererGtk::LoadingAnimation, public:
-//
-TabRendererGtk::LoadingAnimation::LoadingAnimation(
-    ThemeProvider* theme_provider)
-    : data_(new Data(theme_provider)),
-      theme_provider_(theme_provider),
-      animation_state_(ANIMATION_NONE),
-      animation_frame_(0) {
-  registrar_.Add(this,
-                 NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-TabRendererGtk::LoadingAnimation::LoadingAnimation(
-    const LoadingAnimation::Data& data)
-    : data_(new Data(data)),
-      theme_provider_(NULL),
-      animation_state_(ANIMATION_NONE),
-      animation_frame_(0) {
-}
-
-TabRendererGtk::LoadingAnimation::~LoadingAnimation() {}
-
-bool TabRendererGtk::LoadingAnimation::ValidateLoadingAnimation(
-    AnimationState animation_state) {
-  bool has_changed = false;
-  if (animation_state_ != animation_state) {
-    // The waiting animation is the reverse of the loading animation, but at a
-    // different rate - the following reverses and scales the animation_frame_
-    // so that the frame is at an equivalent position when going from one
-    // animation to the other.
-    if (animation_state_ == ANIMATION_WAITING &&
-        animation_state == ANIMATION_LOADING) {
-      animation_frame_ = data_->loading_animation_frame_count -
-          (animation_frame_ / data_->waiting_to_loading_frame_count_ratio);
-    }
-    animation_state_ = animation_state;
-    has_changed = true;
-  }
-
-  if (animation_state_ != ANIMATION_NONE) {
-    animation_frame_ = (animation_frame_ + 1) %
-                       ((animation_state_ == ANIMATION_WAITING) ?
-                         data_->waiting_animation_frame_count :
-                         data_->loading_animation_frame_count);
-    has_changed = true;
-  } else {
-    animation_frame_ = 0;
-  }
-  return has_changed;
-}
-
-void TabRendererGtk::LoadingAnimation::Observe(
-    NotificationType type,
-    const NotificationSource& source,
-    const NotificationDetails& details) {
-  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
-  data_.reset(new Data(theme_provider_));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FaviconCrashAnimation
-//
-//  A custom animation subclass to manage the favicon crash animation.
-class TabRendererGtk::FavIconCrashAnimation : public ui::LinearAnimation,
-                                              public ui::AnimationDelegate {
- public:
-  explicit FavIconCrashAnimation(TabRendererGtk* target)
-      : ALLOW_THIS_IN_INITIALIZER_LIST(ui::LinearAnimation(1000, 25, this)),
-        target_(target) {
-  }
-  virtual ~FavIconCrashAnimation() {}
-
-  // ui::Animation overrides:
-  virtual void AnimateToState(double state) {
-    const double kHidingOffset = 27;
-
-    if (state < .5) {
-      target_->SetFavIconHidingOffset(
-          static_cast<int>(floor(kHidingOffset * 2.0 * state)));
-    } else {
-      target_->DisplayCrashedFavIcon();
-      target_->SetFavIconHidingOffset(
-          static_cast<int>(
-              floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset))));
-    }
-  }
-
-  // ui::AnimationDelegate overrides:
-  virtual void AnimationCanceled(const ui::Animation* animation) {
-    target_->SetFavIconHidingOffset(0);
-  }
-
- private:
-  TabRendererGtk* target_;
-
-  DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRendererGtk, public:
-
-TabRendererGtk::TabRendererGtk(ThemeProvider* theme_provider)
-    : showing_icon_(false),
-      showing_close_button_(false),
-      fav_icon_hiding_offset_(0),
-      should_display_crashed_favicon_(false),
-      loading_animation_(theme_provider),
-      background_offset_x_(0),
-      background_offset_y_(kInactiveTabBackgroundOffsetY),
-      close_button_color_(0) {
-  InitResources();
-
-  tab_.Own(gtk_fixed_new());
-  gtk_widget_set_app_paintable(tab_.get(), TRUE);
-  g_signal_connect(tab_.get(), "expose-event",
-                   G_CALLBACK(OnExposeEventThunk), this);
-  g_signal_connect(tab_.get(), "size-allocate",
-                   G_CALLBACK(OnSizeAllocateThunk), this);
-  close_button_.reset(MakeCloseButton());
-  gtk_widget_show(tab_.get());
-
-  hover_animation_.reset(new ui::SlideAnimation(this));
-  hover_animation_->SetSlideDuration(kHoverDurationMs);
-
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-TabRendererGtk::~TabRendererGtk() {
-  tab_.Destroy();
-  for (BitmapCache::iterator it = cached_bitmaps_.begin();
-       it != cached_bitmaps_.end(); ++it) {
-    delete it->second.bitmap;
-  }
-}
-
-void TabRendererGtk::UpdateData(TabContents* contents,
-                                bool app,
-                                bool loading_only) {
-  DCHECK(contents);
-  theme_provider_ = GtkThemeProvider::GetFrom(contents->profile());
-
-  if (!loading_only) {
-    data_.title = contents->GetTitle();
-    data_.off_the_record = contents->profile()->IsOffTheRecord();
-    data_.crashed = contents->is_crashed();
-
-    SkBitmap* app_icon = contents->GetExtensionAppIcon();
-    if (app_icon)
-      data_.favicon = *app_icon;
-    else
-      data_.favicon = contents->GetFavIcon();
-
-    data_.app = app;
-    // This is kind of a hacky way to determine whether our icon is the default
-    // favicon. But the plumbing that would be necessary to do it right would
-    // be a good bit of work and would sully code for other platforms which
-    // don't care to custom-theme the favicon. Hopefully the default favicon
-    // will eventually be chromium-themable and this code will go away.
-    data_.is_default_favicon =
-        (data_.favicon.pixelRef() ==
-        ResourceBundle::GetSharedInstance().GetBitmapNamed(
-            IDR_DEFAULT_FAVICON)->pixelRef());
-  }
-
-  // Loading state also involves whether we show the favicon, since that's where
-  // we display the throbber.
-  data_.loading = contents->is_loading();
-  data_.show_icon = contents->ShouldDisplayFavIcon();
-}
-
-void TabRendererGtk::UpdateFromModel() {
-  // Force a layout, since the tab may have grown a favicon.
-  Layout();
-  SchedulePaint();
-
-  if (data_.crashed) {
-    if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation())
-      StartCrashAnimation();
-  } else {
-    if (IsPerformingCrashAnimation())
-      StopCrashAnimation();
-    ResetCrashedFavIcon();
-  }
-}
-
-void TabRendererGtk::SetBlocked(bool blocked) {
-  if (data_.blocked == blocked)
-    return;
-  data_.blocked = blocked;
-  // TODO(zelidrag) bug 32399: Make tabs pulse on Linux as well.
-}
-
-bool TabRendererGtk::is_blocked() const {
-  return data_.blocked;
-}
-
-bool TabRendererGtk::IsSelected() const {
-  return true;
-}
-
-bool TabRendererGtk::IsVisible() const {
-  return GTK_WIDGET_FLAGS(tab_.get()) & GTK_VISIBLE;
-}
-
-void TabRendererGtk::SetVisible(bool visible) const {
-  if (visible) {
-    gtk_widget_show(tab_.get());
-    if (data_.mini)
-      gtk_widget_show(close_button_->widget());
-  } else {
-    gtk_widget_hide_all(tab_.get());
-  }
-}
-
-bool TabRendererGtk::ValidateLoadingAnimation(AnimationState animation_state) {
-  return loading_animation_.ValidateLoadingAnimation(animation_state);
-}
-
-void TabRendererGtk::PaintFavIconArea(GdkEventExpose* event) {
-  DCHECK(ShouldShowIcon());
-
-  // The paint area is the favicon bounds, but we're painting into the gdk
-  // window belonging to the tabstrip.  So the coordinates are relative to the
-  // top left of the tab strip.
-  event->area.x = x() + favicon_bounds_.x();
-  event->area.y = y() + favicon_bounds_.y();
-  event->area.width = favicon_bounds_.width();
-  event->area.height = favicon_bounds_.height();
-  gfx::CanvasSkiaPaint canvas(event, false);
-
-  // The actual paint methods expect 0, 0 to be the tab top left (see
-  // PaintTab).
-  canvas.TranslateInt(x(), y());
-
-  // Paint the background behind the favicon.
-  int theme_id;
-  int offset_y = 0;
-  if (IsSelected()) {
-    theme_id = IDR_THEME_TOOLBAR;
-  } else {
-    if (!data_.off_the_record) {
-      theme_id = IDR_THEME_TAB_BACKGROUND;
-    } else {
-      theme_id = IDR_THEME_TAB_BACKGROUND_INCOGNITO;
-    }
-    if (!theme_provider_->HasCustomImage(theme_id))
-      offset_y = background_offset_y_;
-  }
-  SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(theme_id);
-  canvas.TileImageInt(*tab_bg,
-      x() + favicon_bounds_.x(), offset_y + favicon_bounds_.y(),
-      favicon_bounds_.x(), favicon_bounds_.y(),
-      favicon_bounds_.width(), favicon_bounds_.height());
-
-  if (!IsSelected()) {
-    double throb_value = GetThrobValue();
-    if (throb_value > 0) {
-      SkRect bounds;
-      bounds.set(favicon_bounds_.x(), favicon_bounds_.y(),
-          favicon_bounds_.right(), favicon_bounds_.bottom());
-      canvas.saveLayerAlpha(&bounds, static_cast<int>(throb_value * 0xff),
-                            SkCanvas::kARGB_ClipLayer_SaveFlag);
-      canvas.drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
-      SkBitmap* active_bg = theme_provider_->GetBitmapNamed(IDR_THEME_TOOLBAR);
-      canvas.TileImageInt(*active_bg,
-          x() + favicon_bounds_.x(), favicon_bounds_.y(),
-          favicon_bounds_.x(), favicon_bounds_.y(),
-          favicon_bounds_.width(), favicon_bounds_.height());
-      canvas.restore();
-    }
-  }
-
-  // Now paint the icon.
-  PaintIcon(&canvas);
-}
-
-bool TabRendererGtk::ShouldShowIcon() const {
-  if (mini() && height() >= GetMinimumUnselectedSize().height()) {
-    return true;
-  } else if (!data_.show_icon) {
-    return false;
-  } else if (IsSelected()) {
-    // The selected tab clips favicon before close button.
-    return IconCapacity() >= 2;
-  }
-  // Non-selected tabs clip close button before favicon.
-  return IconCapacity() >= 1;
-}
-
-// static
-gfx::Size TabRendererGtk::GetMinimumUnselectedSize() {
-  InitResources();
-
-  gfx::Size minimum_size;
-  minimum_size.set_width(kLeftPadding + kRightPadding);
-  // Since we use bitmap images, the real minimum height of the image is
-  // defined most accurately by the height of the end cap images.
-  minimum_size.set_height(tab_active_.image_l->height() - kToolbarOverlap);
-  return minimum_size;
-}
-
-// static
-gfx::Size TabRendererGtk::GetMinimumSelectedSize() {
-  gfx::Size minimum_size = GetMinimumUnselectedSize();
-  minimum_size.set_width(kLeftPadding + kFavIconSize + kRightPadding);
-  return minimum_size;
-}
-
-// static
-gfx::Size TabRendererGtk::GetStandardSize() {
-  gfx::Size standard_size = GetMinimumUnselectedSize();
-  standard_size.Enlarge(kFavIconTitleSpacing + kStandardTitleWidth, 0);
-  return standard_size;
-}
-
-// static
-int TabRendererGtk::GetMiniWidth() {
-  return browser_defaults::kMiniTabWidth;
-}
-
-// static
-int TabRendererGtk::GetContentHeight() {
-  // The height of the content of the Tab is the largest of the favicon,
-  // the title text and the close button graphic.
-  int content_height = std::max(kFavIconSize, title_font_height_);
-  return std::max(content_height, close_button_height_);
-}
-
-// static
-void TabRendererGtk::LoadTabImages() {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  tab_alpha_.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
-  tab_alpha_.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
-
-  tab_active_.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
-  tab_active_.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
-  tab_active_.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
-  tab_active_.l_width = tab_active_.image_l->width();
-  tab_active_.r_width = tab_active_.image_r->width();
-
-  tab_inactive_.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
-  tab_inactive_.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
-  tab_inactive_.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
-  tab_inactive_.l_width = tab_inactive_.image_l->width();
-  tab_inactive_.r_width = tab_inactive_.image_r->width();
-
-  close_button_width_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->width();
-  close_button_height_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->height();
-}
-
-// static
-void TabRendererGtk::SetSelectedTitleColor(SkColor color) {
-  selected_title_color_ = color;
-}
-
-// static
-void TabRendererGtk::SetUnselectedTitleColor(SkColor color) {
-  unselected_title_color_ = color;
-}
-
-gfx::Rect TabRendererGtk::GetNonMirroredBounds(GtkWidget* parent) const {
-  // The tabstrip widget is a windowless widget so the tab widget's allocation
-  // is relative to the browser titlebar.  We need the bounds relative to the
-  // tabstrip.
-  gfx::Rect bounds = GetWidgetBoundsRelativeToParent(parent, widget());
-  bounds.set_x(gtk_util::MirroredLeftPointForRect(parent, bounds));
-  return bounds;
-}
-
-gfx::Rect TabRendererGtk::GetRequisition() const {
-  return gfx::Rect(requisition_.x(), requisition_.y(),
-                   requisition_.width(), requisition_.height());
-}
-
-void TabRendererGtk::StartMiniTabTitleAnimation() {
-  if (!mini_title_animation_.get()) {
-    mini_title_animation_.reset(new ui::ThrobAnimation(this));
-    mini_title_animation_->SetThrobDuration(kMiniTitleChangeThrobDuration);
-  }
-
-  if (!mini_title_animation_->is_animating()) {
-    mini_title_animation_->StartThrobbing(2);
-  } else if (mini_title_animation_->cycles_remaining() <= 2) {
-    // The title changed while we're already animating. Add at most one more
-    // cycle. This is done in an attempt to smooth out pages that continuously
-    // change the title.
-    mini_title_animation_->set_cycles_remaining(
-        mini_title_animation_->cycles_remaining() + 2);
-  }
-}
-
-void TabRendererGtk::StopMiniTabTitleAnimation() {
-  if (mini_title_animation_.get())
-    mini_title_animation_->Stop();
-}
-
-void TabRendererGtk::SetBounds(const gfx::Rect& bounds) {
-  requisition_ = bounds;
-  gtk_widget_set_size_request(tab_.get(), bounds.width(), bounds.height());
-}
-
-void TabRendererGtk::Observe(NotificationType type,
-                             const NotificationSource& source,
-                             const NotificationDetails& details) {
-  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
-
-  // Clear our cache when we receive a theme change notification because it
-  // contains cached bitmaps based off the previous theme.
-  for (BitmapCache::iterator it = cached_bitmaps_.begin();
-       it != cached_bitmaps_.end(); ++it) {
-    delete it->second.bitmap;
-  }
-  cached_bitmaps_.clear();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRendererGtk, protected:
-
-string16 TabRendererGtk::GetTitle() const {
-  return data_.title;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabRendererGtk, ui::AnimationDelegate implementation:
-
-void TabRendererGtk::AnimationProgressed(const ui::Animation* animation) {
-  gtk_widget_queue_draw(tab_.get());
-}
-
-void TabRendererGtk::AnimationCanceled(const ui::Animation* animation) {
-  AnimationEnded(animation);
-}
-
-void TabRendererGtk::AnimationEnded(const ui::Animation* animation) {
-  gtk_widget_queue_draw(tab_.get());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRendererGtk, private:
-
-void TabRendererGtk::StartCrashAnimation() {
-  if (!crash_animation_.get())
-    crash_animation_.reset(new FavIconCrashAnimation(this));
-  crash_animation_->Stop();
-  crash_animation_->Start();
-}
-
-void TabRendererGtk::StopCrashAnimation() {
-  if (!crash_animation_.get())
-    return;
-  crash_animation_->Stop();
-}
-
-bool TabRendererGtk::IsPerformingCrashAnimation() const {
-  return crash_animation_.get() && crash_animation_->is_animating();
-}
-
-void TabRendererGtk::SetFavIconHidingOffset(int offset) {
-  fav_icon_hiding_offset_ = offset;
-  SchedulePaint();
-}
-
-void TabRendererGtk::DisplayCrashedFavIcon() {
-  should_display_crashed_favicon_ = true;
-}
-
-void TabRendererGtk::ResetCrashedFavIcon() {
-  should_display_crashed_favicon_ = false;
-}
-
-void TabRendererGtk::Paint(gfx::Canvas* canvas) {
-  // Don't paint if we're narrower than we can render correctly. (This should
-  // only happen during animations).
-  if (width() < GetMinimumUnselectedSize().width() && !mini())
-    return;
-
-  // See if the model changes whether the icons should be painted.
-  const bool show_icon = ShouldShowIcon();
-  const bool show_close_button = ShouldShowCloseBox();
-  if (show_icon != showing_icon_ ||
-      show_close_button != showing_close_button_)
-    Layout();
-
-  PaintTabBackground(canvas);
-
-  if (!mini() || width() > kMiniTabRendererAsNormalTabWidth)
-    PaintTitle(canvas);
-
-  if (show_icon)
-    PaintIcon(canvas);
-}
-
-SkBitmap TabRendererGtk::PaintBitmap() {
-  gfx::CanvasSkia canvas(width(), height(), false);
-  Paint(&canvas);
-  return canvas.ExtractBitmap();
-}
-
-cairo_surface_t* TabRendererGtk::PaintToSurface() {
-  gfx::CanvasSkia canvas(width(), height(), false);
-  Paint(&canvas);
-  return cairo_surface_reference(cairo_get_target(canvas.beginPlatformPaint()));
-}
-
-void TabRendererGtk::SchedulePaint() {
-  gtk_widget_queue_draw(tab_.get());
-}
-
-gfx::Rect TabRendererGtk::GetLocalBounds() {
-  return gfx::Rect(0, 0, bounds_.width(), bounds_.height());
-}
-
-void TabRendererGtk::Layout() {
-  gfx::Rect local_bounds = GetLocalBounds();
-  if (local_bounds.IsEmpty())
-    return;
-  local_bounds.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding);
-
-  // Figure out who is tallest.
-  int content_height = GetContentHeight();
-
-  // Size the Favicon.
-  showing_icon_ = ShouldShowIcon();
-  if (showing_icon_) {
-    int favicon_top = kTopPadding + (content_height - kFavIconSize) / 2;
-    favicon_bounds_.SetRect(local_bounds.x(), favicon_top,
-                            kFavIconSize, kFavIconSize);
-    if ((mini() || data_.animating_mini_change) &&
-        bounds_.width() < kMiniTabRendererAsNormalTabWidth) {
-      int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth();
-      int ideal_delta = bounds_.width() - GetMiniWidth();
-      if (ideal_delta < mini_delta) {
-        int ideal_x = (GetMiniWidth() - kFavIconSize) / 2;
-        int x = favicon_bounds_.x() + static_cast<int>(
-            (1 - static_cast<float>(ideal_delta) /
-             static_cast<float>(mini_delta)) *
-            (ideal_x - favicon_bounds_.x()));
-        favicon_bounds_.set_x(x);
-      }
-    }
-  } else {
-    favicon_bounds_.SetRect(local_bounds.x(), local_bounds.y(), 0, 0);
-  }
-
-  // Size the Close button.
-  showing_close_button_ = ShouldShowCloseBox();
-  if (showing_close_button_) {
-    int close_button_top =
-        kTopPadding + kCloseButtonVertFuzz +
-        (content_height - close_button_height_) / 2;
-    close_button_bounds_.SetRect(local_bounds.width() + kCloseButtonHorzFuzz,
-                                 close_button_top, close_button_width_,
-                                 close_button_height_);
-
-    // If the close button color has changed, generate a new one.
-    if (theme_provider_) {
-      SkColor tab_text_color =
-        theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT);
-      if (!close_button_color_ || tab_text_color != close_button_color_) {
-        close_button_color_ = tab_text_color;
-        ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-        close_button_->SetBackground(close_button_color_,
-            rb.GetBitmapNamed(IDR_TAB_CLOSE),
-            rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
-      }
-    }
-  } else {
-    close_button_bounds_.SetRect(0, 0, 0, 0);
-  }
-
-  if (!mini() || width() >= kMiniTabRendererAsNormalTabWidth) {
-    // Size the Title text to fill the remaining space.
-    int title_left = favicon_bounds_.right() + kFavIconTitleSpacing;
-    int title_top = kTopPadding;
-
-    // If the user has big fonts, the title will appear rendered too far down
-    // on the y-axis if we use the regular top padding, so we need to adjust it
-    // so that the text appears centered.
-    gfx::Size minimum_size = GetMinimumUnselectedSize();
-    int text_height = title_top + title_font_height_ + kBottomPadding;
-    if (text_height > minimum_size.height())
-      title_top -= (text_height - minimum_size.height()) / 2;
-
-    int title_width;
-    if (close_button_bounds_.width() && close_button_bounds_.height()) {
-      title_width = std::max(close_button_bounds_.x() -
-                             kTitleCloseButtonSpacing - title_left, 0);
-    } else {
-      title_width = std::max(local_bounds.width() - title_left, 0);
-    }
-    title_bounds_.SetRect(title_left, title_top, title_width, content_height);
-  }
-
-  favicon_bounds_.set_x(
-      gtk_util::MirroredLeftPointForRect(tab_.get(), favicon_bounds_));
-  close_button_bounds_.set_x(
-      gtk_util::MirroredLeftPointForRect(tab_.get(), close_button_bounds_));
-  title_bounds_.set_x(
-      gtk_util::MirroredLeftPointForRect(tab_.get(), title_bounds_));
-
-  MoveCloseButtonWidget();
-}
-
-void TabRendererGtk::MoveCloseButtonWidget() {
-  if (!close_button_bounds_.IsEmpty()) {
-    gtk_fixed_move(GTK_FIXED(tab_.get()), close_button_->widget(),
-                   close_button_bounds_.x(), close_button_bounds_.y());
-    gtk_widget_show(close_button_->widget());
-  } else {
-    gtk_widget_hide(close_button_->widget());
-  }
-}
-
-SkBitmap* TabRendererGtk::GetMaskedBitmap(const SkBitmap* mask,
-    const SkBitmap* background, int bg_offset_x, int bg_offset_y) {
-  // We store a bitmap for each mask + background pair (4 total bitmaps).  We
-  // replace the cached image if the tab has moved relative to the background.
-  BitmapCache::iterator it = cached_bitmaps_.find(std::make_pair(mask,
-                                                                 background));
-  if (it != cached_bitmaps_.end()) {
-    if (it->second.bg_offset_x == bg_offset_x &&
-        it->second.bg_offset_y == bg_offset_y) {
-      return it->second.bitmap;
-    }
-    // The background offset changed so we should re-render with the new
-    // offsets.
-    delete it->second.bitmap;
-  }
-  SkBitmap image = SkBitmapOperations::CreateTiledBitmap(
-      *background, bg_offset_x, bg_offset_y, mask->width(),
-      height() + kToolbarOverlap);
-  CachedBitmap bitmap = {
-    bg_offset_x,
-    bg_offset_y,
-    new SkBitmap(SkBitmapOperations::CreateMaskedBitmap(image, *mask))
-  };
-  cached_bitmaps_[std::make_pair(mask, background)] = bitmap;
-  return bitmap.bitmap;
-}
-
-void TabRendererGtk::PaintTab(GdkEventExpose* event) {
-  gfx::CanvasSkiaPaint canvas(event, false);
-  if (canvas.is_empty())
-    return;
-
-  // The tab is rendered into a windowless widget whose offset is at the
-  // coordinate event->area.  Translate by these offsets so we can render at
-  // (0,0) to match Windows' rendering metrics.
-  canvas.TranslateInt(event->area.x, event->area.y);
-
-  // Save the original x offset so we can position background images properly.
-  background_offset_x_ = event->area.x;
-
-  Paint(&canvas);
-}
-
-void TabRendererGtk::PaintTitle(gfx::Canvas* canvas) {
-  // Paint the Title.
-  string16 title = data_.title;
-  if (title.empty()) {
-    title = data_.loading ?
-        l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) :
-        TabContents::GetDefaultTitle();
-  } else {
-    Browser::FormatTitleForDisplay(&title);
-  }
-
-  SkColor title_color = IsSelected() ? selected_title_color_
-                                     : unselected_title_color_;
-  canvas->DrawStringInt(UTF16ToWideHack(title), *title_font_, title_color,
-                        title_bounds_.x(), title_bounds_.y(),
-                        title_bounds_.width(), title_bounds_.height());
-}
-
-void TabRendererGtk::PaintIcon(gfx::Canvas* canvas) {
-  if (loading_animation_.animation_state() != ANIMATION_NONE) {
-    PaintLoadingAnimation(canvas);
-  } else {
-    canvas->Save();
-    canvas->ClipRectInt(0, 0, width(), height() - kFavIconTitleSpacing);
-    if (should_display_crashed_favicon_) {
-      canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0,
-                            crashed_fav_icon->width(),
-                            crashed_fav_icon->height(),
-                            favicon_bounds_.x(),
-                            favicon_bounds_.y() + fav_icon_hiding_offset_,
-                            kFavIconSize, kFavIconSize,
-                            true);
-    } else {
-      if (!data_.favicon.isNull()) {
-        if (data_.is_default_favicon && theme_provider_->UseGtkTheme()) {
-          GdkPixbuf* favicon = GtkThemeProvider::GetDefaultFavicon(true);
-          canvas->AsCanvasSkia()->DrawGdkPixbuf(
-              favicon, favicon_bounds_.x(),
-              favicon_bounds_.y() + fav_icon_hiding_offset_);
-        } else {
-          // If the favicon is an app icon, it is allowed to be drawn slightly
-          // larger than the standard favicon.
-          int favIconHeightOffset = data_.app ? -2 : 0;
-          int favIconWidthDelta = data_.app ?
-              data_.favicon.width() - kFavIconSize : 0;
-          int favIconHeightDelta = data_.app ?
-              data_.favicon.height() - kFavIconSize : 0;
-
-          // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch
-          // to using that class to render the favicon).
-          canvas->DrawBitmapInt(data_.favicon, 0, 0,
-                                data_.favicon.width(),
-                                data_.favicon.height(),
-                                favicon_bounds_.x() - favIconWidthDelta/2,
-                                favicon_bounds_.y() + favIconHeightOffset
-                                    - favIconHeightDelta/2
-                                    + fav_icon_hiding_offset_,
-                                kFavIconSize + favIconWidthDelta,
-                                kFavIconSize + favIconHeightDelta,
-                                true);
-        }
-      }
-    }
-    canvas->Restore();
-  }
-}
-
-void TabRendererGtk::PaintTabBackground(gfx::Canvas* canvas) {
-  if (IsSelected()) {
-    PaintActiveTabBackground(canvas);
-  } else {
-    PaintInactiveTabBackground(canvas);
-
-    double throb_value = GetThrobValue();
-    if (throb_value > 0) {
-      canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff),
-                             gfx::Rect(width(), height()));
-      canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255,
-                                       SkXfermode::kClear_Mode);
-      PaintActiveTabBackground(canvas);
-      canvas->Restore();
-    }
-  }
-}
-
-void TabRendererGtk::PaintInactiveTabBackground(gfx::Canvas* canvas) {
-  bool is_otr = data_.off_the_record;
-
-  // The tab image needs to be lined up with the background image
-  // so that it feels partially transparent.
-  int offset_x = background_offset_x_;
-
-  int tab_id = is_otr ?
-      IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND;
-
-  SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(tab_id);
-
-  // If the theme is providing a custom background image, then its top edge
-  // should be at the top of the tab. Otherwise, we assume that the background
-  // image is a composited foreground + frame image.
-  int offset_y = theme_provider_->HasCustomImage(tab_id) ?
-      0 : background_offset_y_;
-
-  // Draw left edge.
-  SkBitmap* theme_l = GetMaskedBitmap(tab_alpha_.image_l, tab_bg, offset_x,
-                                      offset_y);
-  canvas->DrawBitmapInt(*theme_l, 0, 0);
-
-  // Draw right edge.
-  SkBitmap* theme_r = GetMaskedBitmap(tab_alpha_.image_r, tab_bg,
-      offset_x + width() - tab_active_.r_width, offset_y);
-
-  canvas->DrawBitmapInt(*theme_r, width() - theme_r->width(), 0);
-
-  // Draw center.
-  canvas->TileImageInt(*tab_bg,
-      offset_x + tab_active_.l_width, kDropShadowOffset + offset_y,
-      tab_active_.l_width, 2,
-      width() - tab_active_.l_width - tab_active_.r_width, height() - 2);
-
-  canvas->DrawBitmapInt(*tab_inactive_.image_l, 0, 0);
-  canvas->TileImageInt(*tab_inactive_.image_c, tab_inactive_.l_width, 0,
-      width() - tab_inactive_.l_width - tab_inactive_.r_width, height());
-  canvas->DrawBitmapInt(*tab_inactive_.image_r,
-      width() - tab_inactive_.r_width, 0);
-}
-
-void TabRendererGtk::PaintActiveTabBackground(gfx::Canvas* canvas) {
-  int offset_x = background_offset_x_;
-
-  SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(IDR_THEME_TOOLBAR);
-
-  // Draw left edge.
-  SkBitmap* theme_l = GetMaskedBitmap(tab_alpha_.image_l, tab_bg, offset_x, 0);
-  canvas->DrawBitmapInt(*theme_l, 0, 0);
-
-  // Draw right edge.
-  SkBitmap* theme_r = GetMaskedBitmap(tab_alpha_.image_r, tab_bg,
-      offset_x + width() - tab_active_.r_width, 0);
-  canvas->DrawBitmapInt(*theme_r, width() - tab_active_.r_width, 0);
-
-  // Draw center.
-  canvas->TileImageInt(*tab_bg,
-      offset_x + tab_active_.l_width, kDropShadowHeight,
-      tab_active_.l_width, kDropShadowHeight,
-      width() - tab_active_.l_width - tab_active_.r_width,
-      height() - kDropShadowHeight);
-
-  canvas->DrawBitmapInt(*tab_active_.image_l, 0, 0);
-  canvas->TileImageInt(*tab_active_.image_c, tab_active_.l_width, 0,
-      width() - tab_active_.l_width - tab_active_.r_width, height());
-  canvas->DrawBitmapInt(*tab_active_.image_r, width() - tab_active_.r_width, 0);
-}
-
-void TabRendererGtk::PaintLoadingAnimation(gfx::Canvas* canvas) {
-  const SkBitmap* frames =
-      (loading_animation_.animation_state() == ANIMATION_WAITING) ?
-      loading_animation_.waiting_animation_frames() :
-      loading_animation_.loading_animation_frames();
-  const int image_size = frames->height();
-  const int image_offset = loading_animation_.animation_frame() * image_size;
-  DCHECK(image_size == favicon_bounds_.height());
-  DCHECK(image_size == favicon_bounds_.width());
-
-  canvas->DrawBitmapInt(*frames, image_offset, 0, image_size, image_size,
-      favicon_bounds_.x(), favicon_bounds_.y(), image_size, image_size,
-      false);
-}
-
-int TabRendererGtk::IconCapacity() const {
-  if (height() < GetMinimumUnselectedSize().height())
-    return 0;
-  return (width() - kLeftPadding - kRightPadding) / kFavIconSize;
-}
-
-bool TabRendererGtk::ShouldShowCloseBox() const {
-  // The selected tab never clips close button.
-  return !mini() && (IsSelected() || IconCapacity() >= 3);
-}
-
-CustomDrawButton* TabRendererGtk::MakeCloseButton() {
-  CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE,
-      IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE);
-
-  gtk_widget_set_tooltip_text(button->widget(),
-      l10n_util::GetStringUTF8(IDS_TOOLTIP_CLOSE_TAB).c_str());
-
-  g_signal_connect(button->widget(), "clicked",
-                   G_CALLBACK(OnCloseButtonClickedThunk), this);
-  g_signal_connect(button->widget(), "button-release-event",
-                   G_CALLBACK(OnCloseButtonMouseReleaseThunk), this);
-  g_signal_connect(button->widget(), "enter-notify-event",
-                   G_CALLBACK(OnEnterNotifyEventThunk), this);
-  g_signal_connect(button->widget(), "leave-notify-event",
-                   G_CALLBACK(OnLeaveNotifyEventThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS);
-  gtk_fixed_put(GTK_FIXED(tab_.get()), button->widget(), 0, 0);
-
-  return button;
-}
-
-double TabRendererGtk::GetThrobValue() {
-  if (mini_title_animation_.get() && mini_title_animation_->is_animating()) {
-    return mini_title_animation_->GetCurrentValue() *
-        kMiniTitleChangeThrobOpacity;
-  }
-  return hover_animation_.get() ?
-      kHoverOpacity * hover_animation_->GetCurrentValue() : 0;
-}
-
-void TabRendererGtk::CloseButtonClicked() {
-  // Nothing to do.
-}
-
-void TabRendererGtk::OnCloseButtonClicked(GtkWidget* widget) {
-  CloseButtonClicked();
-}
-
-gboolean TabRendererGtk::OnCloseButtonMouseRelease(GtkWidget* widget,
-                                                   GdkEventButton* event) {
-  if (event->button == 2) {
-    CloseButtonClicked();
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-gboolean TabRendererGtk::OnExposeEvent(GtkWidget* widget,
-                                       GdkEventExpose* event) {
-  PaintTab(event);
-  gtk_container_propagate_expose(GTK_CONTAINER(tab_.get()),
-                                 close_button_->widget(), event);
-  return TRUE;
-}
-
-void TabRendererGtk::OnSizeAllocate(GtkWidget* widget,
-                                    GtkAllocation* allocation) {
-  gfx::Rect bounds = gfx::Rect(allocation->x, allocation->y,
-                               allocation->width, allocation->height);
-
-  // Nothing to do if the bounds are the same.  If we don't catch this, we'll
-  // get an infinite loop of size-allocate signals.
-  if (bounds_ == bounds)
-    return;
-
-  bounds_ = bounds;
-  Layout();
-}
-
-gboolean TabRendererGtk::OnEnterNotifyEvent(GtkWidget* widget,
-                                            GdkEventCrossing* event) {
-  hover_animation_->SetTweenType(ui::Tween::EASE_OUT);
-  hover_animation_->Show();
-  return FALSE;
-}
-
-gboolean TabRendererGtk::OnLeaveNotifyEvent(GtkWidget* widget,
-                                            GdkEventCrossing* event) {
-  hover_animation_->SetTweenType(ui::Tween::EASE_IN);
-  hover_animation_->Hide();
-  return FALSE;
-}
-
-// static
-void TabRendererGtk::InitResources() {
-  if (initialized_)
-    return;
-
-  LoadTabImages();
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
-  // Dividing by the pango scale factor maintains an absolute pixel size across
-  // all DPIs.
-  int size = static_cast<int>(13 / gfx::PlatformFontGtk::GetPangoScaleFactor());
-  title_font_ = new gfx::Font(base_font.GetFontName(), size);
-  title_font_height_ = title_font_->GetHeight();
-
-  crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON);
-
-  initialized_ = true;
-}
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h
deleted file mode 100644
index 0593e68..0000000
--- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h
+++ /dev/null
@@ -1,456 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TABS_TAB_RENDERER_GTK_H_
-#define CHROME_BROWSER_GTK_TABS_TAB_RENDERER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <map>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "base/string16.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
-#include "gfx/rect.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/animation/animation_delegate.h"
-
-namespace gfx {
-class Size;
-}  // namespace gfx
-
-class CustomDrawButton;
-class GtkThemeProvider;
-class TabContents;
-class ThemeProvider;
-
-namespace ui {
-class SlideAnimation;
-class ThrobAnimation;
-}
-
-class TabRendererGtk : public ui::AnimationDelegate,
-                       public NotificationObserver {
- public:
-  // Possible animation states.
-  enum AnimationState {
-    ANIMATION_NONE,
-    ANIMATION_WAITING,
-    ANIMATION_LOADING
-  };
-
-  class LoadingAnimation : public NotificationObserver {
-   public:
-    struct Data {
-      explicit Data(ThemeProvider* theme_provider);
-      Data(int loading, int waiting, int waiting_to_loading);
-
-      SkBitmap* waiting_animation_frames;
-      SkBitmap* loading_animation_frames;
-      int loading_animation_frame_count;
-      int waiting_animation_frame_count;
-      int waiting_to_loading_frame_count_ratio;
-    };
-
-    explicit LoadingAnimation(ThemeProvider* theme_provider);
-
-    // Used in unit tests to inject specific data.
-    explicit LoadingAnimation(const LoadingAnimation::Data& data);
-
-    virtual ~LoadingAnimation();
-
-    // Advance the loading animation to the next frame, or hide the animation if
-    // the tab isn't loading. Returns |true| if the icon area needs to be
-    // repainted.
-    bool ValidateLoadingAnimation(AnimationState animation_state);
-
-    AnimationState animation_state() const { return animation_state_; }
-    int animation_frame() const { return animation_frame_; }
-
-    const SkBitmap* waiting_animation_frames() const {
-      return data_->waiting_animation_frames;
-    }
-    const SkBitmap* loading_animation_frames() const {
-      return data_->loading_animation_frames;
-    }
-
-    // Provide NotificationObserver implementation.
-    virtual void Observe(NotificationType type,
-                         const NotificationSource& source,
-                         const NotificationDetails& details);
-
-   private:
-    scoped_ptr<Data> data_;
-
-    // Used to listen for theme change notifications.
-    NotificationRegistrar registrar_;
-
-    // Gives us our throbber images.
-    ThemeProvider* theme_provider_;
-
-    // Current state of the animation.
-    AnimationState animation_state_;
-
-    // The current index into the Animation image strip.
-    int animation_frame_;
-
-    DISALLOW_COPY_AND_ASSIGN(LoadingAnimation);
-  };
-
-  explicit TabRendererGtk(ThemeProvider* theme_provider);
-  virtual ~TabRendererGtk();
-
-  // TabContents. If only the loading state was updated, the loading_only flag
-  // should be specified. If other things change, set this flag to false to
-  // update everything.
-  virtual void UpdateData(TabContents* contents, bool app, bool loading_only);
-
-  // Sets the blocked state of the tab.
-  void SetBlocked(bool pinned);
-  bool is_blocked() const;
-
-  // Sets the mini-state of the tab.
-  void set_mini(bool mini) { data_.mini = mini; }
-  bool mini() const { return data_.mini; }
-
-  // Sets the app state of the tab.
-  void set_app(bool app) { data_.app = app; }
-  bool app() const { return data_.app; }
-
-  // Are we in the process of animating a mini tab state change on this tab?
-  void set_animating_mini_change(bool value) {
-    data_.animating_mini_change = value;
-  }
-
-  // Updates the display to reflect the contents of this TabRenderer's model.
-  void UpdateFromModel();
-
-  // Returns true if the Tab is selected, false otherwise.
-  virtual bool IsSelected() const;
-
-  // Returns true if the Tab is visible, false otherwise.
-  virtual bool IsVisible() const;
-
-  // Sets the visibility of the Tab.
-  virtual void SetVisible(bool visible) const;
-
-  // Paints the tab into |canvas|.
-  virtual void Paint(gfx::Canvas* canvas);
-
-  // Paints the tab into a SkBitmap.
-  virtual SkBitmap PaintBitmap();
-
-  // Paints the tab, and keeps the result server-side. The returned surface must
-  // be freed with cairo_surface_destroy().
-  virtual cairo_surface_t* PaintToSurface();
-
-  // There is no PaintNow available, so the fastest we can do is schedule a
-  // paint with the windowing system.
-  virtual void SchedulePaint();
-
-  // Notifies the Tab that the close button has been clicked.
-  virtual void CloseButtonClicked();
-
-  // Sets the bounds of the tab.
-  virtual void SetBounds(const gfx::Rect& bounds);
-
-  // Provide NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Advance the loading animation to the next frame, or hide the animation if
-  // the tab isn't loading.  Returns |true| if the icon area needs to be
-  // repainted.
-  bool ValidateLoadingAnimation(AnimationState animation_state);
-
-  // Repaint only the area of the tab that contains the favicon.
-  void PaintFavIconArea(GdkEventExpose* event);
-
-  // Returns whether the Tab should display a favicon.
-  bool ShouldShowIcon() const;
-
-  // Returns the minimum possible size of a single unselected Tab.
-  static gfx::Size GetMinimumUnselectedSize();
-  // Returns the minimum possible size of a selected Tab. Selected tabs must
-  // always show a close button and have a larger minimum size than unselected
-  // tabs.
-  static gfx::Size GetMinimumSelectedSize();
-  // Returns the preferred size of a single Tab, assuming space is
-  // available.
-  static gfx::Size GetStandardSize();
-
-  // Returns the width for mini-tabs. Mini-tabs always have this width.
-  static int GetMiniWidth();
-
-  // Loads the images to be used for the tab background.
-  static void LoadTabImages();
-
-  // Sets the colors used for painting text on the tabs.
-  static void SetSelectedTitleColor(SkColor color);
-  static void SetUnselectedTitleColor(SkColor color);
-
-  static gfx::Font* title_font() { return title_font_; }
-
-  // Returns the bounds of the Tab.
-  int x() const { return bounds_.x(); }
-  int y() const { return bounds_.y(); }
-  int width() const { return bounds_.width(); }
-  int height() const { return bounds_.height(); }
-
-  gfx::Rect bounds() const { return bounds_; }
-
-  gfx::Rect favicon_bounds() const { return favicon_bounds_; }
-
-  // Returns the non-mirrored (LTR) bounds of this tab.
-  gfx::Rect GetNonMirroredBounds(GtkWidget* parent) const;
-
-  // Returns the requested bounds of the tab.
-  gfx::Rect GetRequisition() const;
-
-  GtkWidget* widget() const { return tab_.get(); }
-
-  // Start/stop the mini-tab title animation.
-  void StartMiniTabTitleAnimation();
-  void StopMiniTabTitleAnimation();
-
-  void set_vertical_offset(int offset) { background_offset_y_ = offset; }
-
- protected:
-  const gfx::Rect& title_bounds() const { return title_bounds_; }
-  const gfx::Rect& close_button_bounds() const { return close_button_bounds_; }
-
-  // Returns the title of the Tab.
-  string16 GetTitle() const;
-
-  // enter-notify-event handler that signals when the mouse enters the tab.
-  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnEnterNotifyEvent,
-                       GdkEventCrossing*);
-
-  // leave-notify-event handler that signals when the mouse enters the tab.
-  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnLeaveNotifyEvent,
-                       GdkEventCrossing*);
-
- private:
-  class FavIconCrashAnimation;
-
-  // The data structure used to hold cached bitmaps.  We need to manually free
-  // the bitmap in CachedBitmap when we remove it from |cached_bitmaps_|.  We
-  // handle this when we replace images in the map and in the destructor.
-  struct CachedBitmap {
-    int bg_offset_x;
-    int bg_offset_y;
-    SkBitmap* bitmap;
-  };
-  typedef std::map<std::pair<const SkBitmap*, const SkBitmap*>, CachedBitmap>
-      BitmapCache;
-
-  // Model data. We store this here so that we don't need to ask the underlying
-  // model, which is tricky since instances of this object can outlive the
-  // corresponding objects in the underlying model.
-  struct TabData {
-    TabData()
-        : is_default_favicon(false),
-          loading(false),
-          crashed(false),
-          off_the_record(false),
-          show_icon(true),
-          mini(false),
-          blocked(false),
-          animating_mini_change(false),
-          app(false) {
-    }
-
-    SkBitmap favicon;
-    bool is_default_favicon;
-    string16 title;
-    bool loading;
-    bool crashed;
-    bool off_the_record;
-    bool show_icon;
-    bool mini;
-    bool blocked;
-    bool animating_mini_change;
-    bool app;
-  };
-
-  // TODO(jhawkins): Move into TabResources class.
-  struct TabImage {
-    SkBitmap* image_l;
-    SkBitmap* image_c;
-    SkBitmap* image_r;
-    int l_width;
-    int r_width;
-    int y_offset;
-  };
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationCanceled(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-
-  // Starts/Stops the crash animation.
-  void StartCrashAnimation();
-  void StopCrashAnimation();
-
-  // Return true if the crash animation is currently running.
-  bool IsPerformingCrashAnimation() const;
-
-  // Set the temporary offset for the favicon. This is used during animation.
-  void SetFavIconHidingOffset(int offset);
-
-  void DisplayCrashedFavIcon();
-  void ResetCrashedFavIcon();
-
-  // Generates the bounds for the interior items of the tab.
-  void Layout();
-
-  // Returns the local bounds of the tab.  This returns the rect
-  // {0, 0, width(), height()} for now, as we don't yet support borders.
-  gfx::Rect GetLocalBounds();
-
-  // Moves the close button widget within the GtkFixed container.
-  void MoveCloseButtonWidget();
-
-  // Returns the largest of the favicon, title text, and the close button.
-  static int GetContentHeight();
-
-  // A helper method for generating the masked bitmaps used to draw the curved
-  // edges of tabs.  We cache the generated bitmaps because they can take a
-  // long time to compute.
-  SkBitmap* GetMaskedBitmap(const SkBitmap* mask,
-                            const SkBitmap* background,
-                            int bg_offset_x,
-                            int bg_offset_y);
-  BitmapCache cached_bitmaps_;
-
-  // Paints the tab, minus the close button.
-  void PaintTab(GdkEventExpose* event);
-
-  // Paint various portions of the Tab
-  void PaintTitle(gfx::Canvas* canvas);
-  void PaintIcon(gfx::Canvas* canvas);
-  void PaintTabBackground(gfx::Canvas* canvas);
-  void PaintInactiveTabBackground(gfx::Canvas* canvas);
-  void PaintActiveTabBackground(gfx::Canvas* canvas);
-  void PaintLoadingAnimation(gfx::Canvas* canvas);
-
-  // Returns the number of favicon-size elements that can fit in the tab's
-  // current size.
-  int IconCapacity() const;
-
-
-  // Returns whether the Tab should display a close button.
-  bool ShouldShowCloseBox() const;
-
-  CustomDrawButton* MakeCloseButton();
-
-  // Gets the throb value for the tab. When a tab is not selected the
-  // active background is drawn at |GetThrobValue()|%. This is used for hover
-  // and mini-tab title change effects.
-  double GetThrobValue();
-
-  // Handles the clicked signal for the close button.
-  CHROMEGTK_CALLBACK_0(TabRendererGtk, void, OnCloseButtonClicked);
-
-  // Handles middle clicking the close button.
-  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnCloseButtonMouseRelease,
-                       GdkEventButton*);
-
-  // expose-event handler that redraws the tab.
-  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnExposeEvent,
-                       GdkEventExpose*);
-
-  // size-allocate handler used to update the current bounds of the tab.
-  CHROMEGTK_CALLBACK_1(TabRendererGtk, void, OnSizeAllocate, GtkAllocation*);
-
-  // TODO(jhawkins): Move to TabResources.
-  static void InitResources();
-  static bool initialized_;
-
-  // The bounds of various sections of the display.
-  gfx::Rect favicon_bounds_;
-  gfx::Rect title_bounds_;
-  gfx::Rect close_button_bounds_;
-
-  TabData data_;
-
-  static TabImage tab_active_;
-  static TabImage tab_inactive_;
-  static TabImage tab_alpha_;
-
-  static gfx::Font* title_font_;
-  static int title_font_height_;
-
-  static int close_button_width_;
-  static int close_button_height_;
-
-  static SkColor selected_title_color_;
-  static SkColor unselected_title_color_;
-
-  // The GtkDrawingArea we draw the tab on.
-  OwnedWidgetGtk tab_;
-
-  // Whether we're showing the icon. It is cached so that we can detect when it
-  // changes and layout appropriately.
-  bool showing_icon_;
-
-  // Whether we are showing the close button. It is cached so that we can
-  // detect when it changes and layout appropriately.
-  bool showing_close_button_;
-
-  // The offset used to animate the favicon location.
-  int fav_icon_hiding_offset_;
-
-  // The animation object used to swap the favicon with the sad tab icon.
-  scoped_ptr<FavIconCrashAnimation> crash_animation_;
-
-  // Set when the crashed favicon should be displayed.
-  bool should_display_crashed_favicon_;
-
-  // The bounds of this Tab.
-  gfx::Rect bounds_;
-
-  // The requested bounds of this tab.  These bounds are relative to the
-  // tabstrip.
-  gfx::Rect requisition_;
-
-  // Hover animation.
-  scoped_ptr<ui::SlideAnimation> hover_animation_;
-
-  // Animation used when the title of an inactive mini-tab changes.
-  scoped_ptr<ui::ThrobAnimation> mini_title_animation_;
-
-  // Contains the loading animation state.
-  LoadingAnimation loading_animation_;
-
-  // The offset used to paint the tab theme images.
-  int background_offset_x_;
-
-  // The vertical offset used to paint the tab theme images. Controlled by the
-  // tabstrip and plumbed here to offset the theme image by the size of the
-  // alignment in the BrowserTitlebar.
-  int background_offset_y_;
-
-  GtkThemeProvider* theme_provider_;
-
-  // The close button.
-  scoped_ptr<CustomDrawButton> close_button_;
-
-  // The current color of the close button.
-  SkColor close_button_color_;
-
-  // Used to listen for theme change notifications.
-  NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabRendererGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TABS_TAB_RENDERER_GTK_H_
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc
deleted file mode 100644
index 10189da..0000000
--- a/chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-typedef TabRendererGtk::LoadingAnimation LoadingAnimation;
-
-const int kTestLoadingAnimationFrameCount = 10;
-const int kTestWaitingAnimationFrameCount = 40;
-const int kTestWaitingToLoadingFrameCountRatio = 4;
-
-const LoadingAnimation::Data kMockAnimationData =
-    LoadingAnimation::Data(kTestLoadingAnimationFrameCount,
-                           kTestWaitingAnimationFrameCount,
-                           kTestWaitingToLoadingFrameCountRatio);
-
-TEST(LoadingAnimationTest, InitialState) {
-  LoadingAnimation loading_animation(kMockAnimationData);
-  EXPECT_EQ(TabRendererGtk::ANIMATION_NONE,
-            loading_animation.animation_state());
-  EXPECT_EQ(0, loading_animation.animation_frame());
-}
-
-TEST(LoadingAnimationTest, AdvanceWaitingFrames) {
-  LoadingAnimation loading_animation(kMockAnimationData);
-  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
-  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
-            loading_animation.animation_state());
-  EXPECT_EQ(1, loading_animation.animation_frame());
-  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
-  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
-            loading_animation.animation_state());
-  EXPECT_EQ(2, loading_animation.animation_frame());
-
-  for (int i = 2; i < kTestWaitingAnimationFrameCount - 1; ++i) {
-    loading_animation.ValidateLoadingAnimation(
-        TabRendererGtk::ANIMATION_WAITING);
-  }
-  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
-            loading_animation.animation_state());
-  EXPECT_EQ(kTestWaitingAnimationFrameCount - 1,
-            loading_animation.animation_frame());
-
-  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
-  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
-            loading_animation.animation_state());
-  EXPECT_EQ(0, loading_animation.animation_frame()) <<
-            "The animation frame should have wrapped around to 0.";
-}
-
-TEST(LoadingAnimationTest, AdvanceFromWaitingToLoading) {
-  LoadingAnimation loading_animation(kMockAnimationData);
-  for (int i = 0; i < 2 * kTestWaitingToLoadingFrameCountRatio; ++i) {
-    loading_animation.ValidateLoadingAnimation(
-        TabRendererGtk::ANIMATION_WAITING);
-  }
-  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
-            loading_animation.animation_state());
-  EXPECT_EQ(2 * kTestWaitingToLoadingFrameCountRatio,
-            loading_animation.animation_frame());
-
-  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_LOADING);
-  EXPECT_EQ(TabRendererGtk::ANIMATION_LOADING,
-            loading_animation.animation_state());
-  EXPECT_EQ(kTestLoadingAnimationFrameCount - 1,
-            loading_animation.animation_frame());
-}
-
-}  // namespace
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
deleted file mode 100644
index 8cadca9..0000000
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc
+++ /dev/null
@@ -1,2062 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-
-#include <algorithm>
-
-#include "app/gtk_dnd_util.h"
-#include "app/resource_bundle.h"
-#include "base/i18n/rtl.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/autocomplete/autocomplete.h"
-#include "chrome/browser/autocomplete/autocomplete_classifier.h"
-#include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tabs/tab_strip_model_delegate.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "gfx/gtk_util.h"
-#include "gfx/point.h"
-#include "grit/app_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-const int kDefaultAnimationDurationMs = 100;
-const int kResizeLayoutAnimationDurationMs = 166;
-const int kReorderAnimationDurationMs = 166;
-const int kAnimateToBoundsDurationMs = 150;
-const int kMiniTabAnimationDurationMs = 150;
-
-const int kNewTabButtonHOffset = -5;
-const int kNewTabButtonVOffset = 5;
-
-// The delay between when the mouse leaves the tabstrip and the resize animation
-// is started.
-const int kResizeTabsTimeMs = 300;
-
-// The range outside of the tabstrip where the pointer must enter/leave to
-// start/stop the resize animation.
-const int kTabStripAnimationVSlop = 40;
-
-const int kHorizontalMoveThreshold = 16;  // pixels
-
-// The horizontal offset from one tab to the next, which results in overlapping
-// tabs.
-const int kTabHOffset = -16;
-
-// A linux specific menu item for toggling window decorations.
-const int kShowWindowDecorationsCommand = 200;
-
-// Size of the drop indicator.
-static int drop_indicator_width;
-static int drop_indicator_height;
-
-inline int Round(double x) {
-  return static_cast<int>(x + 0.5);
-}
-
-// widget->allocation is not guaranteed to be set.  After window creation,
-// we pick up the normal bounds by connecting to the configure-event signal.
-gfx::Rect GetInitialWidgetBounds(GtkWidget* widget) {
-  GtkRequisition request;
-  gtk_widget_size_request(widget, &request);
-  return gfx::Rect(0, 0, request.width, request.height);
-}
-
-// Sort rectangles based on their x position.  We don't care about y position
-// so we don't bother breaking ties.
-int CompareGdkRectangles(const void* p1, const void* p2) {
-  int p1_x = static_cast<const GdkRectangle*>(p1)->x;
-  int p2_x = static_cast<const GdkRectangle*>(p2)->x;
-  if (p1_x < p2_x)
-    return -1;
-  else if (p1_x == p2_x)
-    return 0;
-  return 1;
-}
-
-bool GdkRectMatchesTabFavIconBounds(const GdkRectangle& gdk_rect, TabGtk* tab) {
-  gfx::Rect favicon_bounds = tab->favicon_bounds();
-  return gdk_rect.x == favicon_bounds.x() + tab->x() &&
-      gdk_rect.y == favicon_bounds.y() + tab->y() &&
-      gdk_rect.width == favicon_bounds.width() &&
-      gdk_rect.height == favicon_bounds.height();
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// TabAnimation
-//
-//  A base class for all TabStrip animations.
-//
-class TabStripGtk::TabAnimation : public ui::AnimationDelegate {
- public:
-  friend class TabStripGtk;
-
-  // Possible types of animation.
-  enum Type {
-    INSERT,
-    REMOVE,
-    MOVE,
-    RESIZE,
-    MINI,
-    MINI_MOVE
-  };
-
-  TabAnimation(TabStripGtk* tabstrip, Type type)
-      : tabstrip_(tabstrip),
-        animation_(this),
-        start_selected_width_(0),
-        start_unselected_width_(0),
-        end_selected_width_(0),
-        end_unselected_width_(0),
-        layout_on_completion_(false),
-        type_(type) {
-  }
-  virtual ~TabAnimation() {}
-
-  Type type() const { return type_; }
-
-  void Start() {
-    animation_.SetSlideDuration(GetDuration());
-    animation_.SetTweenType(ui::Tween::EASE_OUT);
-    if (!animation_.IsShowing()) {
-      animation_.Reset();
-      animation_.Show();
-    }
-  }
-
-  void Stop() {
-    animation_.Stop();
-  }
-
-  void set_layout_on_completion(bool layout_on_completion) {
-    layout_on_completion_ = layout_on_completion;
-  }
-
-  // Retrieves the width for the Tab at the specified index if an animation is
-  // active.
-  static double GetCurrentTabWidth(TabStripGtk* tabstrip,
-                                   TabStripGtk::TabAnimation* animation,
-                                   int index) {
-    TabGtk* tab = tabstrip->GetTabAt(index);
-    double tab_width;
-    if (tab->mini()) {
-      tab_width = TabGtk::GetMiniWidth();
-    } else {
-      double unselected, selected;
-      tabstrip->GetCurrentTabWidths(&unselected, &selected);
-      tab_width = tab->IsSelected() ? selected : unselected;
-    }
-
-    if (animation) {
-      double specified_tab_width = animation->GetWidthForTab(index);
-      if (specified_tab_width != -1)
-        tab_width = specified_tab_width;
-    }
-
-    return tab_width;
-  }
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation) {
-    tabstrip_->AnimationLayout(end_unselected_width_);
-  }
-
-  virtual void AnimationEnded(const ui::Animation* animation) {
-    tabstrip_->FinishAnimation(this, layout_on_completion_);
-    // This object is destroyed now, so we can't do anything else after this.
-  }
-
-  virtual void AnimationCanceled(const ui::Animation* animation) {
-    AnimationEnded(animation);
-  }
-
-  // Returns the gap before the tab at the specified index. Subclass if during
-  // an animation you need to insert a gap before a tab.
-  virtual double GetGapWidth(int index) {
-    return 0;
-  }
-
- protected:
-  // Returns the duration of the animation.
-  virtual int GetDuration() const {
-    return kDefaultAnimationDurationMs;
-  }
-
-  // Subclasses override to return the width of the Tab at the specified index
-  // at the current animation frame. -1 indicates the default width should be
-  // used for the Tab.
-  virtual double GetWidthForTab(int index) const {
-    return -1;  // Use default.
-  }
-
-  // Figure out the desired start and end widths for the specified pre- and
-  // post- animation tab counts.
-  void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count,
-                                 int start_mini_count,
-                                 int end_mini_count) {
-    tabstrip_->GetDesiredTabWidths(start_tab_count, start_mini_count,
-                                   &start_unselected_width_,
-                                   &start_selected_width_);
-    double standard_tab_width =
-        static_cast<double>(TabRendererGtk::GetStandardSize().width());
-
-    if ((end_tab_count - start_tab_count) > 0 &&
-        start_unselected_width_ < standard_tab_width) {
-      double minimum_tab_width = static_cast<double>(
-          TabRendererGtk::GetMinimumUnselectedSize().width());
-      start_unselected_width_ -= minimum_tab_width / start_tab_count;
-    }
-
-    tabstrip_->GenerateIdealBounds();
-    tabstrip_->GetDesiredTabWidths(end_tab_count, end_mini_count,
-                                   &end_unselected_width_,
-                                   &end_selected_width_);
-  }
-
-  TabStripGtk* tabstrip_;
-  ui::SlideAnimation animation_;
-
-  double start_selected_width_;
-  double start_unselected_width_;
-  double end_selected_width_;
-  double end_unselected_width_;
-
- private:
-  // True if a complete re-layout is required upon completion of the animation.
-  // Subclasses set this if they don't perform a complete layout
-  // themselves and canceling the animation may leave the strip in an
-  // inconsistent state.
-  bool layout_on_completion_;
-
-  const Type type_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Handles insertion of a Tab at |index|.
-class InsertTabAnimation : public TabStripGtk::TabAnimation {
- public:
-  explicit InsertTabAnimation(TabStripGtk* tabstrip, int index)
-      : TabAnimation(tabstrip, INSERT),
-        index_(index) {
-    int tab_count = tabstrip->GetTabCount();
-    int end_mini_count = tabstrip->GetMiniTabCount();
-    int start_mini_count = end_mini_count;
-    if (index < end_mini_count)
-      start_mini_count--;
-    GenerateStartAndEndWidths(tab_count - 1, tab_count, start_mini_count,
-                              end_mini_count);
-  }
-  virtual ~InsertTabAnimation() {}
-
- protected:
-  // Overridden from TabStripGtk::TabAnimation:
-  virtual double GetWidthForTab(int index) const {
-    if (index == index_) {
-      bool is_selected = tabstrip_->model()->selected_index() == index;
-      double start_width, target_width;
-      if (index < tabstrip_->GetMiniTabCount()) {
-        start_width = TabGtk::GetMinimumSelectedSize().width();
-        target_width = TabGtk::GetMiniWidth();
-      } else {
-        target_width =
-            is_selected ? end_unselected_width_ : end_selected_width_;
-        start_width =
-            is_selected ? TabGtk::GetMinimumSelectedSize().width() :
-                          TabGtk::GetMinimumUnselectedSize().width();
-      }
-
-      double delta = target_width - start_width;
-      if (delta > 0)
-        return start_width + (delta * animation_.GetCurrentValue());
-
-      return start_width;
-    }
-
-    if (tabstrip_->GetTabAt(index)->mini())
-      return TabGtk::GetMiniWidth();
-
-    if (tabstrip_->GetTabAt(index)->IsSelected()) {
-      double delta = end_selected_width_ - start_selected_width_;
-      return start_selected_width_ + (delta * animation_.GetCurrentValue());
-    }
-
-    double delta = end_unselected_width_ - start_unselected_width_;
-    return start_unselected_width_ + (delta * animation_.GetCurrentValue());
-  }
-
- private:
-  int index_;
-
-  DISALLOW_COPY_AND_ASSIGN(InsertTabAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Handles removal of a Tab from |index|
-class RemoveTabAnimation : public TabStripGtk::TabAnimation {
- public:
-  RemoveTabAnimation(TabStripGtk* tabstrip, int index, TabContents* contents)
-      : TabAnimation(tabstrip, REMOVE),
-        index_(index) {
-    int tab_count = tabstrip->GetTabCount();
-    int start_mini_count = tabstrip->GetMiniTabCount();
-    int end_mini_count = start_mini_count;
-    if (index < start_mini_count)
-      end_mini_count--;
-    GenerateStartAndEndWidths(tab_count, tab_count - 1, start_mini_count,
-                              end_mini_count);
-    // If the last non-mini-tab is being removed we force a layout on
-    // completion. This is necessary as the value returned by GetTabHOffset
-    // changes once the tab is actually removed (which happens at the end of
-    // the animation), and unless we layout GetTabHOffset won't be called after
-    // the removal.
-    // We do the same when the last mini-tab is being removed for the same
-    // reason.
-    set_layout_on_completion(start_mini_count > 0 &&
-                             (end_mini_count == 0 ||
-                              (start_mini_count == end_mini_count &&
-                               tab_count == start_mini_count + 1)));
-  }
-
-  virtual ~RemoveTabAnimation() {}
-
-  // Returns the index of the tab being removed.
-  int index() const { return index_; }
-
- protected:
-  // Overridden from TabStripGtk::TabAnimation:
-  virtual double GetWidthForTab(int index) const {
-    TabGtk* tab = tabstrip_->GetTabAt(index);
-
-    if (index == index_) {
-      // The tab(s) being removed are gradually shrunken depending on the state
-      // of the animation.
-      if (tab->mini()) {
-        return animation_.CurrentValueBetween(TabGtk::GetMiniWidth(),
-                                              -kTabHOffset);
-      }
-
-      // Removed animated Tabs are never selected.
-      double start_width = start_unselected_width_;
-      // Make sure target_width is at least abs(kTabHOffset), otherwise if
-      // less than kTabHOffset during layout tabs get negatively offset.
-      double target_width =
-          std::max(abs(kTabHOffset),
-                   TabGtk::GetMinimumUnselectedSize().width() + kTabHOffset);
-      return animation_.CurrentValueBetween(start_width, target_width);
-    }
-
-    if (tab->mini())
-      return TabGtk::GetMiniWidth();
-
-    if (tabstrip_->available_width_for_tabs_ != -1 &&
-        index_ != tabstrip_->GetTabCount() - 1) {
-      return TabStripGtk::TabAnimation::GetWidthForTab(index);
-    }
-
-    // All other tabs are sized according to the start/end widths specified at
-    // the start of the animation.
-    if (tab->IsSelected()) {
-      double delta = end_selected_width_ - start_selected_width_;
-      return start_selected_width_ + (delta * animation_.GetCurrentValue());
-    }
-
-    double delta = end_unselected_width_ - start_unselected_width_;
-    return start_unselected_width_ + (delta * animation_.GetCurrentValue());
-  }
-
-  virtual void AnimationEnded(const ui::Animation* animation) {
-    tabstrip_->RemoveTabAt(index_);
-    TabStripGtk::TabAnimation::AnimationEnded(animation);
-  }
-
- private:
-  int index_;
-
-  DISALLOW_COPY_AND_ASSIGN(RemoveTabAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Handles the movement of a Tab from one position to another.
-class MoveTabAnimation : public TabStripGtk::TabAnimation {
- public:
-  MoveTabAnimation(TabStripGtk* tabstrip, int tab_a_index, int tab_b_index)
-      : TabAnimation(tabstrip, MOVE),
-        start_tab_a_bounds_(tabstrip_->GetIdealBounds(tab_b_index)),
-        start_tab_b_bounds_(tabstrip_->GetIdealBounds(tab_a_index)) {
-    tab_a_ = tabstrip_->GetTabAt(tab_a_index);
-    tab_b_ = tabstrip_->GetTabAt(tab_b_index);
-
-    // Since we don't do a full TabStrip re-layout, we need to force a full
-    // layout upon completion since we're not guaranteed to be in a good state
-    // if for example the animation is canceled.
-    set_layout_on_completion(true);
-  }
-  virtual ~MoveTabAnimation() {}
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation) {
-    // Position Tab A
-    double distance = start_tab_b_bounds_.x() - start_tab_a_bounds_.x();
-    double delta = distance * animation_.GetCurrentValue();
-    double new_x = start_tab_a_bounds_.x() + delta;
-    gfx::Rect bounds(Round(new_x), start_tab_a_bounds_.y(), tab_a_->width(),
-        tab_a_->height());
-    tabstrip_->SetTabBounds(tab_a_, bounds);
-
-    // Position Tab B
-    distance = start_tab_a_bounds_.x() - start_tab_b_bounds_.x();
-    delta = distance * animation_.GetCurrentValue();
-    new_x = start_tab_b_bounds_.x() + delta;
-    bounds = gfx::Rect(Round(new_x), start_tab_b_bounds_.y(), tab_b_->width(),
-        tab_b_->height());
-    tabstrip_->SetTabBounds(tab_b_, bounds);
-  }
-
- protected:
-  // Overridden from TabStripGtk::TabAnimation:
-  virtual int GetDuration() const { return kReorderAnimationDurationMs; }
-
- private:
-  // The two tabs being exchanged.
-  TabGtk* tab_a_;
-  TabGtk* tab_b_;
-
-  // ...and their bounds.
-  gfx::Rect start_tab_a_bounds_;
-  gfx::Rect start_tab_b_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(MoveTabAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Handles the animated resize layout of the entire TabStrip from one width
-// to another.
-class ResizeLayoutAnimation : public TabStripGtk::TabAnimation {
- public:
-  explicit ResizeLayoutAnimation(TabStripGtk* tabstrip)
-      : TabAnimation(tabstrip, RESIZE) {
-    int tab_count = tabstrip->GetTabCount();
-    int mini_tab_count = tabstrip->GetMiniTabCount();
-    GenerateStartAndEndWidths(tab_count, tab_count, mini_tab_count,
-                              mini_tab_count);
-    InitStartState();
-  }
-  virtual ~ResizeLayoutAnimation() {}
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationEnded(const ui::Animation* animation) {
-    tabstrip_->needs_resize_layout_ = false;
-    TabStripGtk::TabAnimation::AnimationEnded(animation);
-  }
-
- protected:
-  // Overridden from TabStripGtk::TabAnimation:
-  virtual int GetDuration() const {
-    return kResizeLayoutAnimationDurationMs;
-  }
-
-  virtual double GetWidthForTab(int index) const {
-    TabGtk* tab = tabstrip_->GetTabAt(index);
-
-    if (tab->mini())
-      return TabGtk::GetMiniWidth();
-
-    if (tab->IsSelected()) {
-      return animation_.CurrentValueBetween(start_selected_width_,
-                                            end_selected_width_);
-    }
-
-    return animation_.CurrentValueBetween(start_unselected_width_,
-                                          end_unselected_width_);
-  }
-
- private:
-  // We need to start from the current widths of the Tabs as they were last
-  // laid out, _not_ the last known good state, which is what'll be done if we
-  // don't measure the Tab sizes here and just go with the default TabAnimation
-  // behavior...
-  void InitStartState() {
-    for (int i = 0; i < tabstrip_->GetTabCount(); ++i) {
-      TabGtk* current_tab = tabstrip_->GetTabAt(i);
-      if (!current_tab->mini()) {
-        if (current_tab->IsSelected()) {
-          start_selected_width_ = current_tab->width();
-        } else {
-          start_unselected_width_ = current_tab->width();
-        }
-      }
-    }
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(ResizeLayoutAnimation);
-};
-
-// Handles a tabs mini-state changing while the tab does not change position
-// in the model.
-class MiniTabAnimation : public TabStripGtk::TabAnimation {
- public:
-  explicit MiniTabAnimation(TabStripGtk* tabstrip, int index)
-      : TabAnimation(tabstrip, MINI),
-        index_(index) {
-    int tab_count = tabstrip->GetTabCount();
-    int start_mini_count = tabstrip->GetMiniTabCount();
-    int end_mini_count = start_mini_count;
-    if (tabstrip->GetTabAt(index)->mini())
-      start_mini_count--;
-    else
-      start_mini_count++;
-    tabstrip_->GetTabAt(index)->set_animating_mini_change(true);
-    GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count,
-                              end_mini_count);
-  }
-
- protected:
-  // Overridden from TabStripGtk::TabAnimation:
-  virtual int GetDuration() const {
-    return kMiniTabAnimationDurationMs;
-  }
-
-  virtual double GetWidthForTab(int index) const {
-    TabGtk* tab = tabstrip_->GetTabAt(index);
-
-    if (index == index_) {
-      if (tab->mini()) {
-        return animation_.CurrentValueBetween(
-            start_selected_width_,
-            static_cast<double>(TabGtk::GetMiniWidth()));
-      } else {
-        return animation_.CurrentValueBetween(
-            static_cast<double>(TabGtk::GetMiniWidth()),
-            end_selected_width_);
-      }
-    } else if (tab->mini()) {
-      return TabGtk::GetMiniWidth();
-    }
-
-    if (tab->IsSelected()) {
-      return animation_.CurrentValueBetween(start_selected_width_,
-                                            end_selected_width_);
-    }
-
-    return animation_.CurrentValueBetween(start_unselected_width_,
-                                          end_unselected_width_);
-  }
-
- private:
-  // Index of the tab whose mini-state changed.
-  int index_;
-
-  DISALLOW_COPY_AND_ASSIGN(MiniTabAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Handles the animation when a tabs mini-state changes and the tab moves as a
-// result.
-class MiniMoveAnimation : public TabStripGtk::TabAnimation {
- public:
-  explicit MiniMoveAnimation(TabStripGtk* tabstrip,
-                             int from_index,
-                             int to_index,
-                             const gfx::Rect& start_bounds)
-      : TabAnimation(tabstrip, MINI_MOVE),
-        tab_(tabstrip->GetTabAt(to_index)),
-        start_bounds_(start_bounds),
-        from_index_(from_index),
-        to_index_(to_index) {
-    int tab_count = tabstrip->GetTabCount();
-    int start_mini_count = tabstrip->GetMiniTabCount();
-    int end_mini_count = start_mini_count;
-    if (tabstrip->GetTabAt(to_index)->mini())
-      start_mini_count--;
-    else
-      start_mini_count++;
-    GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count,
-                              end_mini_count);
-    target_bounds_ = tabstrip->GetIdealBounds(to_index);
-    tab_->set_animating_mini_change(true);
-  }
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation) {
-    // Do the normal layout.
-    TabAnimation::AnimationProgressed(animation);
-
-    // Then special case the position of the tab being moved.
-    int x = animation_.CurrentValueBetween(start_bounds_.x(),
-                                           target_bounds_.x());
-    int width = animation_.CurrentValueBetween(start_bounds_.width(),
-                                               target_bounds_.width());
-    gfx::Rect tab_bounds(x, start_bounds_.y(), width,
-                         start_bounds_.height());
-    tabstrip_->SetTabBounds(tab_, tab_bounds);
-  }
-
-  virtual void AnimationEnded(const ui::Animation* animation) {
-    tabstrip_->needs_resize_layout_ = false;
-    TabStripGtk::TabAnimation::AnimationEnded(animation);
-  }
-
-  virtual double GetGapWidth(int index) {
-    if (to_index_ < from_index_) {
-      // The tab was made mini.
-      if (index == to_index_) {
-        double current_size =
-            animation_.CurrentValueBetween(0, target_bounds_.width());
-        if (current_size < -kTabHOffset)
-          return -(current_size + kTabHOffset);
-      } else if (index == from_index_ + 1) {
-        return animation_.CurrentValueBetween(start_bounds_.width(), 0);
-      }
-    } else {
-      // The tab was was made a normal tab.
-      if (index == from_index_) {
-        return animation_.CurrentValueBetween(
-            TabGtk::GetMiniWidth() + kTabHOffset, 0);
-      }
-    }
-    return 0;
-  }
-
- protected:
-  // Overridden from TabStripGtk::TabAnimation:
-  virtual int GetDuration() const { return kReorderAnimationDurationMs; }
-
-  virtual double GetWidthForTab(int index) const {
-    TabGtk* tab = tabstrip_->GetTabAt(index);
-
-    if (index == to_index_)
-      return animation_.CurrentValueBetween(0, target_bounds_.width());
-
-    if (tab->mini())
-      return TabGtk::GetMiniWidth();
-
-    if (tab->IsSelected()) {
-      return animation_.CurrentValueBetween(start_selected_width_,
-                                            end_selected_width_);
-    }
-
-    return animation_.CurrentValueBetween(start_unselected_width_,
-                                          end_unselected_width_);
-  }
-
- private:
-  // The tab being moved.
-  TabGtk* tab_;
-
-  // Initial bounds of tab_.
-  gfx::Rect start_bounds_;
-
-  // Target bounds.
-  gfx::Rect target_bounds_;
-
-  // Start and end indices of the tab.
-  int from_index_;
-  int to_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(MiniMoveAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// TabStripGtk, public:
-
-// static
-const int TabStripGtk::mini_to_non_mini_gap_ = 3;
-
-TabStripGtk::TabStripGtk(TabStripModel* model, BrowserWindowGtk* window)
-    : current_unselected_width_(TabGtk::GetStandardSize().width()),
-      current_selected_width_(TabGtk::GetStandardSize().width()),
-      available_width_for_tabs_(-1),
-      needs_resize_layout_(false),
-      tab_vertical_offset_(0),
-      model_(model),
-      window_(window),
-      theme_provider_(GtkThemeProvider::GetFrom(model->profile())),
-      resize_layout_factory_(this),
-      added_as_message_loop_observer_(false) {
-  theme_provider_->InitThemesFor(this);
-  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
-                 NotificationService::AllSources());
-}
-
-TabStripGtk::~TabStripGtk() {
-  model_->RemoveObserver(this);
-  tabstrip_.Destroy();
-
-  // Free any remaining tabs.  This is needed to free the very last tab,
-  // because it is not animated on close.  This also happens when all of the
-  // tabs are closed at once.
-  std::vector<TabData>::iterator iterator = tab_data_.begin();
-  for (; iterator < tab_data_.end(); iterator++) {
-    delete iterator->tab;
-  }
-
-  tab_data_.clear();
-
-  // Make sure we unhook ourselves as a message loop observer so that we don't
-  // crash in the case where the user closes the last tab in a window.
-  RemoveMessageLoopObserver();
-}
-
-void TabStripGtk::Init() {
-  model_->AddObserver(this);
-
-  tabstrip_.Own(gtk_fixed_new());
-  ViewIDUtil::SetID(tabstrip_.get(), VIEW_ID_TAB_STRIP);
-  // We want the tab strip to be horizontally shrinkable, so that the Chrome
-  // window can be resized freely.
-  gtk_widget_set_size_request(tabstrip_.get(), 0,
-                              TabGtk::GetMinimumUnselectedSize().height());
-  gtk_widget_set_app_paintable(tabstrip_.get(), TRUE);
-  gtk_drag_dest_set(tabstrip_.get(), GTK_DEST_DEFAULT_ALL,
-                    NULL, 0,
-                    static_cast<GdkDragAction>(
-                        GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK));
-  static const int targets[] = { gtk_dnd_util::TEXT_URI_LIST,
-                                 gtk_dnd_util::NETSCAPE_URL,
-                                 gtk_dnd_util::TEXT_PLAIN,
-                                 -1 };
-  gtk_dnd_util::SetDestTargetList(tabstrip_.get(), targets);
-
-  g_signal_connect(tabstrip_.get(), "expose-event",
-                   G_CALLBACK(OnExposeThunk), this);
-  g_signal_connect(tabstrip_.get(), "size-allocate",
-                   G_CALLBACK(OnSizeAllocateThunk), this);
-  g_signal_connect(tabstrip_.get(), "drag-motion",
-                   G_CALLBACK(OnDragMotionThunk), this);
-  g_signal_connect(tabstrip_.get(), "drag-drop",
-                   G_CALLBACK(OnDragDropThunk), this);
-  g_signal_connect(tabstrip_.get(), "drag-leave",
-                   G_CALLBACK(OnDragLeaveThunk), this);
-  g_signal_connect(tabstrip_.get(), "drag-data-received",
-                   G_CALLBACK(OnDragDataReceivedThunk), this);
-
-  newtab_button_.reset(MakeNewTabButton());
-
-  gtk_widget_show_all(tabstrip_.get());
-
-  bounds_ = GetInitialWidgetBounds(tabstrip_.get());
-
-  if (drop_indicator_width == 0) {
-    // Direction doesn't matter, both images are the same size.
-    GdkPixbuf* drop_image = GetDropArrowImage(true);
-    drop_indicator_width = gdk_pixbuf_get_width(drop_image);
-    drop_indicator_height = gdk_pixbuf_get_height(drop_image);
-  }
-
-  ViewIDUtil::SetDelegateForWidget(widget(), this);
-}
-
-void TabStripGtk::Show() {
-  gtk_widget_show(tabstrip_.get());
-}
-
-void TabStripGtk::Hide() {
-  gtk_widget_hide(tabstrip_.get());
-}
-
-bool TabStripGtk::IsActiveDropTarget() const {
-  for (int i = 0; i < GetTabCount(); ++i) {
-    TabGtk* tab = GetTabAt(i);
-    if (tab->dragging())
-      return true;
-  }
-  return false;
-}
-
-void TabStripGtk::Layout() {
-  // Called from:
-  // - window resize
-  // - animation completion
-  StopAnimation();
-
-  GenerateIdealBounds();
-  int tab_count = GetTabCount();
-  int tab_right = 0;
-  for (int i = 0; i < tab_count; ++i) {
-    const gfx::Rect& bounds = tab_data_.at(i).ideal_bounds;
-    TabGtk* tab = GetTabAt(i);
-    tab->set_animating_mini_change(false);
-    tab->set_vertical_offset(tab_vertical_offset_);
-    SetTabBounds(tab, bounds);
-    tab_right = bounds.right();
-    tab_right += GetTabHOffset(i + 1);
-  }
-
-  LayoutNewTabButton(static_cast<double>(tab_right), current_unselected_width_);
-}
-
-void TabStripGtk::SchedulePaint() {
-  gtk_widget_queue_draw(tabstrip_.get());
-}
-
-void TabStripGtk::SetBounds(const gfx::Rect& bounds) {
-  bounds_ = bounds;
-}
-
-void TabStripGtk::UpdateLoadingAnimations() {
-  for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
-    TabGtk* current_tab = GetTabAt(i);
-    if (current_tab->closing()) {
-      --index;
-    } else {
-      TabRendererGtk::AnimationState state;
-      TabContentsWrapper* contents = model_->GetTabContentsAt(index);
-      if (!contents || !contents->tab_contents()->is_loading()) {
-        state = TabGtk::ANIMATION_NONE;
-      } else if (contents->tab_contents()->waiting_for_response()) {
-        state = TabGtk::ANIMATION_WAITING;
-      } else {
-        state = TabGtk::ANIMATION_LOADING;
-      }
-      if (current_tab->ValidateLoadingAnimation(state)) {
-        // Queue the tab's icon area to be repainted.
-        gfx::Rect favicon_bounds = current_tab->favicon_bounds();
-        gtk_widget_queue_draw_area(tabstrip_.get(),
-            favicon_bounds.x() + current_tab->x(),
-            favicon_bounds.y() + current_tab->y(),
-            favicon_bounds.width(),
-            favicon_bounds.height());
-      }
-    }
-  }
-}
-
-bool TabStripGtk::IsCompatibleWith(TabStripGtk* other) {
-  return model_->profile() == other->model()->profile();
-}
-
-bool TabStripGtk::IsAnimating() const {
-  return active_animation_.get() != NULL;
-}
-
-void TabStripGtk::DestroyDragController() {
-  drag_controller_.reset();
-}
-
-void TabStripGtk::DestroyDraggedSourceTab(TabGtk* tab) {
-  // We could be running an animation that references this Tab.
-  StopAnimation();
-
-  // Make sure we leave the tab_data_ vector in a consistent state, otherwise
-  // we'll be pointing to tabs that have been deleted and removed from the
-  // child view list.
-  std::vector<TabData>::iterator it = tab_data_.begin();
-  for (; it != tab_data_.end(); ++it) {
-    if (it->tab == tab) {
-      if (!model_->closing_all())
-        NOTREACHED() << "Leaving in an inconsistent state!";
-      tab_data_.erase(it);
-      break;
-    }
-  }
-
-  gtk_container_remove(GTK_CONTAINER(tabstrip_.get()), tab->widget());
-  // If we delete the dragged source tab here, the DestroyDragWidget posted
-  // task will be run after the tab is deleted, leading to a crash.
-  MessageLoop::current()->DeleteSoon(FROM_HERE, tab);
-
-  // Force a layout here, because if we've just quickly drag detached a Tab,
-  // the stopping of the active animation above may have left the TabStrip in a
-  // bad (visual) state.
-  Layout();
-}
-
-gfx::Rect TabStripGtk::GetIdealBounds(int index) {
-  DCHECK(index >= 0 && index < GetTabCount());
-  return tab_data_.at(index).ideal_bounds;
-}
-
-void TabStripGtk::SetVerticalOffset(int offset) {
-  tab_vertical_offset_ = offset;
-  Layout();
-}
-
-gfx::Point TabStripGtk::GetTabStripOriginForWidget(GtkWidget* target) {
-  int x, y;
-  if (!gtk_widget_translate_coordinates(widget(), target,
-      -widget()->allocation.x, 0, &x, &y)) {
-    // If the tab strip isn't showing, give the coordinates relative to the
-    // toplevel instead.
-    if (!gtk_widget_translate_coordinates(
-        gtk_widget_get_toplevel(widget()), target, 0, 0, &x, &y)) {
-      NOTREACHED();
-    }
-  }
-  if (GTK_WIDGET_NO_WINDOW(target)) {
-    x += target->allocation.x;
-    y += target->allocation.y;
-  }
-  return gfx::Point(x, y);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ViewIDUtil::Delegate implementation
-
-GtkWidget* TabStripGtk::GetWidgetForViewID(ViewID view_id) {
-  if (GetTabCount() > 0) {
-    if (view_id == VIEW_ID_TAB_LAST) {
-      return GetTabAt(GetTabCount() - 1)->widget();
-    } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) {
-      int index = view_id - VIEW_ID_TAB_0;
-      if (index >= 0 && index < GetTabCount()) {
-        return GetTabAt(index)->widget();
-      } else {
-        return NULL;
-      }
-    }
-  }
-
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabStripGtk, TabStripModelObserver implementation:
-
-void TabStripGtk::TabInsertedAt(TabContentsWrapper* contents,
-                                int index,
-                                bool foreground) {
-  DCHECK(contents);
-  DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index));
-
-  StopAnimation();
-
-  bool contains_tab = false;
-  TabGtk* tab = NULL;
-  // First see if this Tab is one that was dragged out of this TabStrip and is
-  // now being dragged back in. In this case, the DraggedTabController actually
-  // has the Tab already constructed and we can just insert it into our list
-  // again.
-  if (IsDragSessionActive()) {
-    tab = drag_controller_->GetDragSourceTabForContents(
-        contents->tab_contents());
-    if (tab) {
-      // If the Tab was detached, it would have been animated closed but not
-      // removed, so we need to reset this property.
-      tab->set_closing(false);
-      tab->ValidateLoadingAnimation(TabRendererGtk::ANIMATION_NONE);
-      tab->SetVisible(true);
-    }
-
-    // See if we're already in the list. We don't want to add ourselves twice.
-    std::vector<TabData>::const_iterator iter = tab_data_.begin();
-    for (; iter != tab_data_.end() && !contains_tab; ++iter) {
-      if (iter->tab == tab)
-        contains_tab = true;
-    }
-  }
-
-  if (!tab)
-    tab = new TabGtk(this);
-
-  // Only insert if we're not already in the list.
-  if (!contains_tab) {
-    TabData d = { tab, gfx::Rect() };
-    tab_data_.insert(tab_data_.begin() + index, d);
-    tab->UpdateData(contents->tab_contents(), model_->IsAppTab(index), false);
-  }
-  tab->set_mini(model_->IsMiniTab(index));
-  tab->set_app(model_->IsAppTab(index));
-  tab->SetBlocked(model_->IsTabBlocked(index));
-
-  if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get())
-    gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0);
-
-  // Don't animate the first tab; it looks weird.
-  if (GetTabCount() > 1) {
-    StartInsertTabAnimation(index);
-    // We added the tab at 0x0, we need to force an animation step otherwise
-    // if GTK paints before the animation event the tab is painted at 0x0
-    // which is most likely not where it should be positioned.
-    active_animation_->AnimationProgressed(NULL);
-  } else {
-    Layout();
-  }
-}
-
-void TabStripGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
-  GenerateIdealBounds();
-  StartRemoveTabAnimation(index, contents->tab_contents());
-  // Have to do this _after_ calling StartRemoveTabAnimation, so that any
-  // previous remove is completed fully and index is valid in sync with the
-  // model index.
-  GetTabAt(index)->set_closing(true);
-}
-
-void TabStripGtk::TabSelectedAt(TabContentsWrapper* old_contents,
-                                TabContentsWrapper* new_contents,
-                                int index,
-                                bool user_gesture) {
-  DCHECK(index >= 0 && index < static_cast<int>(GetTabCount()));
-
-  // We have "tiny tabs" if the tabs are so tiny that the unselected ones are
-  // a different size to the selected ones.
-  bool tiny_tabs = current_unselected_width_ != current_selected_width_;
-  if (!IsAnimating() && (!needs_resize_layout_ || tiny_tabs))
-    Layout();
-
-  GetTabAt(index)->SchedulePaint();
-
-  int old_index = model_->GetIndexOfTabContents(old_contents);
-  if (old_index >= 0) {
-    GetTabAt(old_index)->SchedulePaint();
-    GetTabAt(old_index)->StopMiniTabTitleAnimation();
-  }
-}
-
-void TabStripGtk::TabMoved(TabContentsWrapper* contents,
-                           int from_index,
-                           int to_index) {
-  gfx::Rect start_bounds = GetIdealBounds(from_index);
-  TabGtk* tab = GetTabAt(from_index);
-  tab_data_.erase(tab_data_.begin() + from_index);
-  TabData data = {tab, gfx::Rect()};
-  tab->set_mini(model_->IsMiniTab(to_index));
-  tab->SetBlocked(model_->IsTabBlocked(to_index));
-  tab_data_.insert(tab_data_.begin() + to_index, data);
-  GenerateIdealBounds();
-  StartMoveTabAnimation(from_index, to_index);
-}
-
-void TabStripGtk::TabChangedAt(TabContentsWrapper* contents, int index,
-                               TabChangeType change_type) {
-  // Index is in terms of the model. Need to make sure we adjust that index in
-  // case we have an animation going.
-  TabGtk* tab = GetTabAtAdjustForAnimation(index);
-  if (change_type == TITLE_NOT_LOADING) {
-    if (tab->mini() && !tab->IsSelected())
-      tab->StartMiniTabTitleAnimation();
-    // We'll receive another notification of the change asynchronously.
-    return;
-  }
-  tab->UpdateData(contents->tab_contents(),
-                  model_->IsAppTab(index),
-                  change_type == LOADING_ONLY);
-  tab->UpdateFromModel();
-}
-
-void TabStripGtk::TabReplacedAt(TabContentsWrapper* old_contents,
-                                TabContentsWrapper* new_contents,
-                                int index) {
-  TabChangedAt(new_contents, index, ALL);
-}
-
-void TabStripGtk::TabMiniStateChanged(TabContentsWrapper* contents, int index) {
-  // Don't do anything if we've already picked up the change from TabMoved.
-  if (GetTabAt(index)->mini() == model_->IsMiniTab(index))
-    return;
-
-  GetTabAt(index)->set_mini(model_->IsMiniTab(index));
-  // Don't animate if the window isn't visible yet. The window won't be visible
-  // when dragging a mini-tab to a new window.
-  if (window_ && window_->window() &&
-      GTK_WIDGET_VISIBLE(GTK_WIDGET(window_->window()))) {
-    StartMiniTabAnimation(index);
-  } else {
-    Layout();
-  }
-}
-
-void TabStripGtk::TabBlockedStateChanged(TabContentsWrapper* contents,
-                                         int index) {
-  GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabStripGtk, TabGtk::TabDelegate implementation:
-
-bool TabStripGtk::IsTabSelected(const TabGtk* tab) const {
-  if (tab->closing())
-    return false;
-
-  return GetIndexOfTab(tab) == model_->selected_index();
-}
-
-bool TabStripGtk::IsTabDetached(const TabGtk* tab) const {
-  if (drag_controller_.get())
-    return drag_controller_->IsTabDetached(tab);
-  return false;
-}
-
-void TabStripGtk::GetCurrentTabWidths(double* unselected_width,
-                                      double* selected_width) const {
-  *unselected_width = current_unselected_width_;
-  *selected_width = current_selected_width_;
-}
-
-bool TabStripGtk::IsTabPinned(const TabGtk* tab) const {
-  if (tab->closing())
-    return false;
-
-  return model_->IsTabPinned(GetIndexOfTab(tab));
-}
-
-void TabStripGtk::SelectTab(TabGtk* tab) {
-  int index = GetIndexOfTab(tab);
-  if (model_->ContainsIndex(index))
-    model_->SelectTabContentsAt(index, true);
-}
-
-void TabStripGtk::CloseTab(TabGtk* tab) {
-  int tab_index = GetIndexOfTab(tab);
-  if (model_->ContainsIndex(tab_index)) {
-    TabGtk* last_tab = GetTabAt(GetTabCount() - 1);
-    // Limit the width available to the TabStrip for laying out Tabs, so that
-    // Tabs are not resized until a later time (when the mouse pointer leaves
-    // the TabStrip).
-    available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
-    needs_resize_layout_ = true;
-    // We hook into the message loop in order to receive mouse move events when
-    // the mouse is outside of the tabstrip.  We unhook once the resize layout
-    // animation is started.
-    AddMessageLoopObserver();
-    model_->CloseTabContentsAt(tab_index,
-                               TabStripModel::CLOSE_USER_GESTURE |
-                               TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
-  }
-}
-
-bool TabStripGtk::IsCommandEnabledForTab(
-    TabStripModel::ContextMenuCommand command_id, const TabGtk* tab) const {
-  int index = GetIndexOfTab(tab);
-  if (model_->ContainsIndex(index))
-    return model_->IsContextMenuCommandEnabled(index, command_id);
-  return false;
-}
-
-void TabStripGtk::ExecuteCommandForTab(
-    TabStripModel::ContextMenuCommand command_id, TabGtk* tab) {
-  int index = GetIndexOfTab(tab);
-  if (model_->ContainsIndex(index))
-    model_->ExecuteContextMenuCommand(index, command_id);
-}
-
-void TabStripGtk::StartHighlightTabsForCommand(
-    TabStripModel::ContextMenuCommand command_id, TabGtk* tab) {
-  if (command_id == TabStripModel::CommandCloseOtherTabs ||
-      command_id == TabStripModel::CommandCloseTabsToRight) {
-    NOTIMPLEMENTED();
-  }
-}
-
-void TabStripGtk::StopHighlightTabsForCommand(
-    TabStripModel::ContextMenuCommand command_id, TabGtk* tab) {
-  if (command_id == TabStripModel::CommandCloseTabsToRight ||
-      command_id == TabStripModel::CommandCloseOtherTabs) {
-    // Just tell all Tabs to stop pulsing - it's safe.
-    StopAllHighlighting();
-  }
-}
-
-void TabStripGtk::StopAllHighlighting() {
-  // TODO(jhawkins): Hook up animations.
-  NOTIMPLEMENTED();
-}
-
-void TabStripGtk::MaybeStartDrag(TabGtk* tab, const gfx::Point& point) {
-  // Don't accidentally start any drag operations during animations if the
-  // mouse is down.
-  if (IsAnimating() || tab->closing() || !HasAvailableDragActions())
-    return;
-
-  drag_controller_.reset(new DraggedTabControllerGtk(tab, this));
-  drag_controller_->CaptureDragInfo(point);
-}
-
-void TabStripGtk::ContinueDrag(GdkDragContext* context) {
-  // We can get called even if |MaybeStartDrag| wasn't called in the event of
-  // a TabStrip animation when the mouse button is down. In this case we should
-  // _not_ continue the drag because it can lead to weird bugs.
-  if (drag_controller_.get())
-    drag_controller_->Drag();
-}
-
-bool TabStripGtk::EndDrag(bool canceled) {
-  return drag_controller_.get() ? drag_controller_->EndDrag(canceled) : false;
-}
-
-bool TabStripGtk::HasAvailableDragActions() const {
-  return model_->delegate()->GetDragActions() != 0;
-}
-
-ThemeProvider* TabStripGtk::GetThemeProvider() {
-  return theme_provider_;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStripGtk, MessageLoop::Observer implementation:
-
-void TabStripGtk::WillProcessEvent(GdkEvent* event) {
-  // Nothing to do.
-}
-
-void TabStripGtk::DidProcessEvent(GdkEvent* event) {
-  switch (event->type) {
-    case GDK_MOTION_NOTIFY:
-    case GDK_LEAVE_NOTIFY:
-      HandleGlobalMouseMoveEvent();
-      break;
-    default:
-      break;
-  }
-}
-
-void TabStripGtk::Observe(NotificationType type,
-                          const NotificationSource& source,
-                          const NotificationDetails& details) {
-  if (type == NotificationType::BROWSER_THEME_CHANGED) {
-    TabRendererGtk::SetSelectedTitleColor(theme_provider_->GetColor(
-        BrowserThemeProvider::COLOR_TAB_TEXT));
-    TabRendererGtk::SetUnselectedTitleColor(theme_provider_->GetColor(
-        BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT));
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabStripGtk, private:
-
-int TabStripGtk::GetTabCount() const {
-  return static_cast<int>(tab_data_.size());
-}
-
-int TabStripGtk::GetMiniTabCount() const {
-  int mini_count = 0;
-  for (size_t i = 0; i < tab_data_.size(); ++i) {
-    if (tab_data_[i].tab->mini())
-      mini_count++;
-    else
-      return mini_count;
-  }
-  return mini_count;
-}
-
-int TabStripGtk::GetAvailableWidthForTabs(TabGtk* last_tab) const {
-  if (!base::i18n::IsRTL())
-    return last_tab->x() - bounds_.x() + last_tab->width();
-  else
-    return bounds_.width() - last_tab->x();
-}
-
-int TabStripGtk::GetIndexOfTab(const TabGtk* tab) const {
-  for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
-    TabGtk* current_tab = GetTabAt(i);
-    if (current_tab->closing()) {
-      --index;
-    } else if (current_tab == tab) {
-      return index;
-    }
-  }
-  return -1;
-}
-
-TabGtk* TabStripGtk::GetTabAt(int index) const {
-  DCHECK_GE(index, 0);
-  DCHECK_LT(index, GetTabCount());
-  return tab_data_.at(index).tab;
-}
-
-TabGtk* TabStripGtk::GetTabAtAdjustForAnimation(int index) const {
-  if (active_animation_.get() &&
-      active_animation_->type() == TabAnimation::REMOVE &&
-      index >=
-      static_cast<RemoveTabAnimation*>(active_animation_.get())->index()) {
-    index++;
-  }
-  return GetTabAt(index);
-}
-
-void TabStripGtk::RemoveTabAt(int index) {
-  TabGtk* removed = tab_data_.at(index).tab;
-
-  // Remove the Tab from the TabStrip's list.
-  tab_data_.erase(tab_data_.begin() + index);
-
-  if (!IsDragSessionActive() || !drag_controller_->IsDragSourceTab(removed)) {
-    gtk_container_remove(GTK_CONTAINER(tabstrip_.get()), removed->widget());
-    delete removed;
-  }
-}
-
-void TabStripGtk::HandleGlobalMouseMoveEvent() {
-  if (!IsCursorInTabStripZone()) {
-    // Mouse moved outside the tab slop zone, start a timer to do a resize
-    // layout after a short while...
-    if (resize_layout_factory_.empty()) {
-      MessageLoop::current()->PostDelayedTask(FROM_HERE,
-          resize_layout_factory_.NewRunnableMethod(
-              &TabStripGtk::ResizeLayoutTabs),
-          kResizeTabsTimeMs);
-    }
-  } else {
-    // Mouse moved quickly out of the tab strip and then into it again, so
-    // cancel the timer so that the strip doesn't move when the mouse moves
-    // back over it.
-    resize_layout_factory_.RevokeAll();
-  }
-}
-
-void TabStripGtk::GenerateIdealBounds() {
-  int tab_count = GetTabCount();
-  double unselected, selected;
-  GetDesiredTabWidths(tab_count, GetMiniTabCount(), &unselected, &selected);
-
-  current_unselected_width_ = unselected;
-  current_selected_width_ = selected;
-
-  // NOTE: This currently assumes a tab's height doesn't differ based on
-  // selected state or the number of tabs in the strip!
-  int tab_height = TabGtk::GetStandardSize().height();
-  double tab_x = tab_start_x();
-  for (int i = 0; i < tab_count; ++i) {
-    TabGtk* tab = GetTabAt(i);
-    double tab_width = unselected;
-    if (tab->mini())
-      tab_width = TabGtk::GetMiniWidth();
-    else if (tab->IsSelected())
-      tab_width = selected;
-    double end_of_tab = tab_x + tab_width;
-    int rounded_tab_x = Round(tab_x);
-    gfx::Rect state(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
-                    tab_height);
-    tab_data_.at(i).ideal_bounds = state;
-    tab_x = end_of_tab + GetTabHOffset(i + 1);
-  }
-}
-
-void TabStripGtk::LayoutNewTabButton(double last_tab_right,
-                                     double unselected_width) {
-  gfx::Rect bounds(0, kNewTabButtonVOffset,
-                   newtab_button_->width(), newtab_button_->height());
-  int delta = abs(Round(unselected_width) - TabGtk::GetStandardSize().width());
-  if (delta > 1 && !needs_resize_layout_) {
-    // We're shrinking tabs, so we need to anchor the New Tab button to the
-    // right edge of the TabStrip's bounds, rather than the right edge of the
-    // right-most Tab, otherwise it'll bounce when animating.
-    bounds.set_x(bounds_.width() - newtab_button_->width());
-  } else {
-    bounds.set_x(Round(last_tab_right - kTabHOffset) + kNewTabButtonHOffset);
-  }
-  bounds.set_x(gtk_util::MirroredLeftPointForRect(tabstrip_.get(), bounds));
-
-  gtk_fixed_move(GTK_FIXED(tabstrip_.get()), newtab_button_->widget(),
-                 bounds.x(), bounds.y());
-}
-
-void TabStripGtk::GetDesiredTabWidths(int tab_count,
-                                      int mini_tab_count,
-                                      double* unselected_width,
-                                      double* selected_width) const {
-  DCHECK(tab_count >= 0 && mini_tab_count >= 0 && mini_tab_count <= tab_count);
-  const double min_unselected_width =
-      TabGtk::GetMinimumUnselectedSize().width();
-  const double min_selected_width =
-      TabGtk::GetMinimumSelectedSize().width();
-
-  *unselected_width = min_unselected_width;
-  *selected_width = min_selected_width;
-
-  if (tab_count == 0) {
-    // Return immediately to avoid divide-by-zero below.
-    return;
-  }
-
-  // Determine how much space we can actually allocate to tabs.
-  int available_width = tabstrip_->allocation.width;
-  if (available_width_for_tabs_ < 0) {
-    available_width = bounds_.width();
-    available_width -=
-        (kNewTabButtonHOffset + newtab_button_->width());
-  } else {
-    // Interesting corner case: if |available_width_for_tabs_| > the result
-    // of the calculation in the conditional arm above, the strip is in
-    // overflow.  We can either use the specified width or the true available
-    // width here; the first preserves the consistent "leave the last tab under
-    // the user's mouse so they can close many tabs" behavior at the cost of
-    // prolonging the glitchy appearance of the overflow state, while the second
-    // gets us out of overflow as soon as possible but forces the user to move
-    // their mouse for a few tabs' worth of closing.  We choose visual
-    // imperfection over behavioral imperfection and select the first option.
-    available_width = available_width_for_tabs_;
-  }
-
-  if (mini_tab_count > 0) {
-    available_width -= mini_tab_count * (TabGtk::GetMiniWidth() + kTabHOffset);
-    tab_count -= mini_tab_count;
-    if (tab_count == 0) {
-      *selected_width = *unselected_width = TabGtk::GetStandardSize().width();
-      return;
-    }
-    // Account for gap between the last mini-tab and first normal tab.
-    available_width -= mini_to_non_mini_gap_;
-  }
-
-  // Calculate the desired tab widths by dividing the available space into equal
-  // portions.  Don't let tabs get larger than the "standard width" or smaller
-  // than the minimum width for each type, respectively.
-  const int total_offset = kTabHOffset * (tab_count - 1);
-  const double desired_tab_width = std::min(
-      (static_cast<double>(available_width - total_offset) /
-       static_cast<double>(tab_count)),
-      static_cast<double>(TabGtk::GetStandardSize().width()));
-
-  *unselected_width = std::max(desired_tab_width, min_unselected_width);
-  *selected_width = std::max(desired_tab_width, min_selected_width);
-
-  // When there are multiple tabs, we'll have one selected and some unselected
-  // tabs.  If the desired width was between the minimum sizes of these types,
-  // try to shrink the tabs with the smaller minimum.  For example, if we have
-  // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5.  If
-  // selected tabs have a minimum width of 4 and unselected tabs have a minimum
-  // width of 1, the above code would set *unselected_width = 2.5,
-  // *selected_width = 4, which results in a total width of 11.5.  Instead, we
-  // want to set *unselected_width = 2, *selected_width = 4, for a total width
-  // of 10.
-  if (tab_count > 1) {
-    if ((min_unselected_width < min_selected_width) &&
-        (desired_tab_width < min_selected_width)) {
-      double calc_width =
-          static_cast<double>(
-              available_width - total_offset - min_selected_width) /
-          static_cast<double>(tab_count - 1);
-      *unselected_width = std::max(calc_width, min_unselected_width);
-    } else if ((min_unselected_width > min_selected_width) &&
-               (desired_tab_width < min_unselected_width)) {
-      *selected_width = std::max(available_width - total_offset -
-          (min_unselected_width * (tab_count - 1)), min_selected_width);
-    }
-  }
-}
-
-int TabStripGtk::GetTabHOffset(int tab_index) {
-  if (tab_index < GetTabCount() && GetTabAt(tab_index - 1)->mini() &&
-      !GetTabAt(tab_index)->mini()) {
-    return mini_to_non_mini_gap_ + kTabHOffset;
-  }
-  return kTabHOffset;
-}
-
-int TabStripGtk::tab_start_x() const {
-  return 0;
-}
-
-bool TabStripGtk::ResizeLayoutTabs() {
-  resize_layout_factory_.RevokeAll();
-
-  // It is critically important that this is unhooked here, otherwise we will
-  // keep spying on messages forever.
-  RemoveMessageLoopObserver();
-
-  available_width_for_tabs_ = -1;
-  int mini_tab_count = GetMiniTabCount();
-  if (mini_tab_count == GetTabCount()) {
-    // Only mini tabs, we know the tab widths won't have changed (all mini-tabs
-    // have the same width), so there is nothing to do.
-    return false;
-  }
-  TabGtk* first_tab = GetTabAt(mini_tab_count);
-  double unselected, selected;
-  GetDesiredTabWidths(GetTabCount(), mini_tab_count, &unselected, &selected);
-  int w = Round(first_tab->IsSelected() ? selected : unselected);
-
-  // We only want to run the animation if we're not already at the desired
-  // size.
-  if (abs(first_tab->width() - w) > 1) {
-    StartResizeLayoutAnimation();
-    return true;
-  }
-
-  return false;
-}
-
-bool TabStripGtk::IsCursorInTabStripZone() const {
-  gfx::Point tabstrip_topleft;
-  gtk_util::ConvertWidgetPointToScreen(tabstrip_.get(), &tabstrip_topleft);
-
-  gfx::Rect bds = bounds();
-  bds.set_origin(tabstrip_topleft);
-  bds.set_height(bds.height() + kTabStripAnimationVSlop);
-
-  GdkScreen* screen = gdk_screen_get_default();
-  GdkDisplay* display = gdk_screen_get_display(screen);
-  gint x, y;
-  gdk_display_get_pointer(display, NULL, &x, &y, NULL);
-  gfx::Point cursor_point(x, y);
-
-  return bds.Contains(cursor_point);
-}
-
-void TabStripGtk::AddMessageLoopObserver() {
-  if (!added_as_message_loop_observer_) {
-    MessageLoopForUI::current()->AddObserver(this);
-    added_as_message_loop_observer_ = true;
-  }
-}
-
-void TabStripGtk::RemoveMessageLoopObserver() {
-  if (added_as_message_loop_observer_) {
-    MessageLoopForUI::current()->RemoveObserver(this);
-    added_as_message_loop_observer_ = false;
-  }
-}
-
-gfx::Rect TabStripGtk::GetDropBounds(int drop_index,
-                                     bool drop_before,
-                                     bool* is_beneath) {
-  DCHECK_NE(drop_index, -1);
-  int center_x;
-  if (drop_index < GetTabCount()) {
-    TabGtk* tab = GetTabAt(drop_index);
-    gfx::Rect bounds = tab->GetNonMirroredBounds(tabstrip_.get());
-    // TODO(sky): update these for pinned tabs.
-    if (drop_before)
-      center_x = bounds.x() - (kTabHOffset / 2);
-    else
-      center_x = bounds.x() + (bounds.width() / 2);
-  } else {
-    TabGtk* last_tab = GetTabAt(drop_index - 1);
-    gfx::Rect bounds = last_tab->GetNonMirroredBounds(tabstrip_.get());
-    center_x = bounds.x() + bounds.width() + (kTabHOffset / 2);
-  }
-
-  center_x = gtk_util::MirroredXCoordinate(tabstrip_.get(), center_x);
-
-  // Determine the screen bounds.
-  gfx::Point drop_loc(center_x - drop_indicator_width / 2,
-                      -drop_indicator_height);
-  gtk_util::ConvertWidgetPointToScreen(tabstrip_.get(), &drop_loc);
-  gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width,
-                        drop_indicator_height);
-
-  // TODO(jhawkins): We always display the arrow underneath the tab because we
-  // don't have custom frame support yet.
-  *is_beneath = true;
-  if (*is_beneath)
-    drop_bounds.Offset(0, drop_bounds.height() + bounds().height());
-
-  return drop_bounds;
-}
-
-void TabStripGtk::UpdateDropIndex(GdkDragContext* context, gint x, gint y) {
-  // If the UI layout is right-to-left, we need to mirror the mouse
-  // coordinates since we calculate the drop index based on the
-  // original (and therefore non-mirrored) positions of the tabs.
-  x = gtk_util::MirroredXCoordinate(tabstrip_.get(), x);
-  // We don't allow replacing the urls of mini-tabs.
-  for (int i = GetMiniTabCount(); i < GetTabCount(); ++i) {
-    TabGtk* tab = GetTabAt(i);
-    gfx::Rect bounds = tab->GetNonMirroredBounds(tabstrip_.get());
-    const int tab_max_x = bounds.x() + bounds.width();
-    const int hot_width = bounds.width() / 3;
-    if (x < tab_max_x) {
-      if (x < bounds.x() + hot_width)
-        SetDropIndex(i, true);
-      else if (x >= tab_max_x - hot_width)
-        SetDropIndex(i + 1, true);
-      else
-        SetDropIndex(i, false);
-      return;
-    }
-  }
-
-  // The drop isn't over a tab, add it to the end.
-  SetDropIndex(GetTabCount(), true);
-}
-
-void TabStripGtk::SetDropIndex(int index, bool drop_before) {
-  bool is_beneath;
-  gfx::Rect drop_bounds = GetDropBounds(index, drop_before, &is_beneath);
-
-  if (!drop_info_.get()) {
-    drop_info_.reset(new DropInfo(index, drop_before, !is_beneath));
-  } else {
-    if (!GTK_IS_WIDGET(drop_info_->container)) {
-      drop_info_->CreateContainer();
-    } else if (drop_info_->drop_index == index &&
-               drop_info_->drop_before == drop_before) {
-      return;
-    }
-
-    drop_info_->drop_index = index;
-    drop_info_->drop_before = drop_before;
-    if (is_beneath == drop_info_->point_down) {
-      drop_info_->point_down = !is_beneath;
-      drop_info_->drop_arrow= GetDropArrowImage(drop_info_->point_down);
-    }
-  }
-
-  gtk_window_move(GTK_WINDOW(drop_info_->container),
-                  drop_bounds.x(), drop_bounds.y());
-  gtk_window_resize(GTK_WINDOW(drop_info_->container),
-                    drop_bounds.width(), drop_bounds.height());
-}
-
-bool TabStripGtk::CompleteDrop(guchar* data, bool is_plain_text) {
-  if (!drop_info_.get())
-    return false;
-
-  const int drop_index = drop_info_->drop_index;
-  const bool drop_before = drop_info_->drop_before;
-
-  // Destroy the drop indicator.
-  drop_info_.reset();
-
-  GURL url;
-  if (is_plain_text) {
-    AutocompleteMatch match;
-    model_->profile()->GetAutocompleteClassifier()->Classify(
-        UTF8ToWide(reinterpret_cast<char*>(data)), std::wstring(), false,
-        &match, NULL);
-    url = match.destination_url;
-  } else {
-    std::string url_string(reinterpret_cast<char*>(data));
-    url = GURL(url_string.substr(0, url_string.find_first_of('\n')));
-  }
-  if (!url.is_valid())
-    return false;
-
-  browser::NavigateParams params(window()->browser(), url,
-                                 PageTransition::LINK);
-  params.tabstrip_index = drop_index;
-
-  if (drop_before) {
-    params.disposition = NEW_FOREGROUND_TAB;
-  } else {
-    params.disposition = CURRENT_TAB;
-    params.source_contents = model_->GetTabContentsAt(drop_index);
-  }
-
-  browser::Navigate(&params);
-
-  return true;
-}
-
-// static
-GdkPixbuf* TabStripGtk::GetDropArrowImage(bool is_down) {
-  return ResourceBundle::GetSharedInstance().GetPixbufNamed(
-      is_down ? IDR_TAB_DROP_DOWN : IDR_TAB_DROP_UP);
-}
-
-// TabStripGtk::DropInfo -------------------------------------------------------
-
-TabStripGtk::DropInfo::DropInfo(int drop_index, bool drop_before,
-                                bool point_down)
-    : drop_index(drop_index),
-      drop_before(drop_before),
-      point_down(point_down) {
-  CreateContainer();
-  drop_arrow = GetDropArrowImage(point_down);
-}
-
-TabStripGtk::DropInfo::~DropInfo() {
-  DestroyContainer();
-}
-
-gboolean TabStripGtk::DropInfo::OnExposeEvent(GtkWidget* widget,
-                                              GdkEventExpose* event) {
-  if (gtk_util::IsScreenComposited()) {
-    SetContainerTransparency();
-  } else {
-    SetContainerShapeMask();
-  }
-
-  gdk_pixbuf_render_to_drawable(drop_arrow,
-                                container->window,
-                                0, 0, 0,
-                                0, 0,
-                                drop_indicator_width,
-                                drop_indicator_height,
-                                GDK_RGB_DITHER_NONE, 0, 0);
-
-  return FALSE;
-}
-
-// Sets the color map of the container window to allow the window to be
-// transparent.
-void TabStripGtk::DropInfo::SetContainerColorMap() {
-  GdkScreen* screen = gtk_widget_get_screen(container);
-  GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
-
-  // If rgba is not available, use rgb instead.
-  if (!colormap)
-    colormap = gdk_screen_get_rgb_colormap(screen);
-
-  gtk_widget_set_colormap(container, colormap);
-}
-
-// Sets full transparency for the container window.  This is used if
-// compositing is available for the screen.
-void TabStripGtk::DropInfo::SetContainerTransparency() {
-  cairo_t* cairo_context = gdk_cairo_create(container->window);
-  if (!cairo_context)
-      return;
-
-  // Make the background of the dragged tab window fully transparent.  All of
-  // the content of the window (child widgets) will be completely opaque.
-
-  cairo_scale(cairo_context, static_cast<double>(drop_indicator_width),
-              static_cast<double>(drop_indicator_height));
-  cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
-  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
-  cairo_paint(cairo_context);
-  cairo_destroy(cairo_context);
-}
-
-// Sets the shape mask for the container window to emulate a transparent
-// container window.  This is used if compositing is not available for the
-// screen.
-void TabStripGtk::DropInfo::SetContainerShapeMask() {
-  // Create a 1bpp bitmap the size of |container|.
-  GdkPixmap* pixmap = gdk_pixmap_new(NULL,
-                                     drop_indicator_width,
-                                     drop_indicator_height, 1);
-  cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(pixmap));
-
-  // Set the transparency.
-  cairo_set_source_rgba(cairo_context, 1, 1, 1, 0);
-
-  // Blit the rendered bitmap into a pixmap.  Any pixel set in the pixmap will
-  // be opaque in the container window.
-  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
-  gdk_cairo_set_source_pixbuf(cairo_context, drop_arrow, 0, 0);
-  cairo_paint(cairo_context);
-  cairo_destroy(cairo_context);
-
-  // Set the shape mask.
-  gdk_window_shape_combine_mask(container->window, pixmap, 0, 0);
-  g_object_unref(pixmap);
-}
-
-void TabStripGtk::DropInfo::CreateContainer() {
-  container = gtk_window_new(GTK_WINDOW_POPUP);
-  SetContainerColorMap();
-  gtk_widget_set_app_paintable(container, TRUE);
-  g_signal_connect(container, "expose-event",
-                   G_CALLBACK(OnExposeEventThunk), this);
-  gtk_widget_add_events(container, GDK_STRUCTURE_MASK);
-  gtk_window_move(GTK_WINDOW(container), 0, 0);
-  gtk_window_resize(GTK_WINDOW(container),
-                    drop_indicator_width, drop_indicator_height);
-  gtk_widget_show_all(container);
-}
-
-void TabStripGtk::DropInfo::DestroyContainer() {
-  if (GTK_IS_WIDGET(container))
-    gtk_widget_destroy(container);
-}
-
-void TabStripGtk::StopAnimation() {
-  if (active_animation_.get())
-    active_animation_->Stop();
-}
-
-// Called from:
-// - animation tick
-void TabStripGtk::AnimationLayout(double unselected_width) {
-  int tab_height = TabGtk::GetStandardSize().height();
-  double tab_x = tab_start_x();
-  for (int i = 0; i < GetTabCount(); ++i) {
-    TabAnimation* animation = active_animation_.get();
-    if (animation)
-      tab_x += animation->GetGapWidth(i);
-    double tab_width = TabAnimation::GetCurrentTabWidth(this, animation, i);
-    double end_of_tab = tab_x + tab_width;
-    int rounded_tab_x = Round(tab_x);
-    TabGtk* tab = GetTabAt(i);
-    gfx::Rect bounds(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
-                     tab_height);
-    SetTabBounds(tab, bounds);
-    tab_x = end_of_tab + GetTabHOffset(i + 1);
-  }
-  LayoutNewTabButton(tab_x, unselected_width);
-}
-
-void TabStripGtk::StartInsertTabAnimation(int index) {
-  // The TabStrip can now use its entire width to lay out Tabs.
-  available_width_for_tabs_ = -1;
-  StopAnimation();
-  active_animation_.reset(new InsertTabAnimation(this, index));
-  active_animation_->Start();
-}
-
-void TabStripGtk::StartRemoveTabAnimation(int index, TabContents* contents) {
-  if (active_animation_.get()) {
-    // Some animations (e.g. MoveTabAnimation) cause there to be a Layout when
-    // they're completed (which includes canceled). Since |tab_data_| is now
-    // inconsistent with TabStripModel, doing this Layout will crash now, so
-    // we ask the MoveTabAnimation to skip its Layout (the state will be
-    // corrected by the RemoveTabAnimation we're about to initiate).
-    active_animation_->set_layout_on_completion(false);
-    active_animation_->Stop();
-  }
-
-  active_animation_.reset(new RemoveTabAnimation(this, index, contents));
-  active_animation_->Start();
-}
-
-void TabStripGtk::StartMoveTabAnimation(int from_index, int to_index) {
-  StopAnimation();
-  active_animation_.reset(new MoveTabAnimation(this, from_index, to_index));
-  active_animation_->Start();
-}
-
-void TabStripGtk::StartResizeLayoutAnimation() {
-  StopAnimation();
-  active_animation_.reset(new ResizeLayoutAnimation(this));
-  active_animation_->Start();
-}
-
-void TabStripGtk::StartMiniTabAnimation(int index) {
-  StopAnimation();
-  active_animation_.reset(new MiniTabAnimation(this, index));
-  active_animation_->Start();
-}
-
-void TabStripGtk::StartMiniMoveTabAnimation(int from_index,
-                                            int to_index,
-                                            const gfx::Rect& start_bounds) {
-  StopAnimation();
-  active_animation_.reset(
-      new MiniMoveAnimation(this, from_index, to_index, start_bounds));
-  active_animation_->Start();
-}
-
-void TabStripGtk::FinishAnimation(TabStripGtk::TabAnimation* animation,
-                                  bool layout) {
-  active_animation_.reset(NULL);
-
-  // Reset the animation state of each tab.
-  for (int i = 0, count = GetTabCount(); i < count; ++i)
-    GetTabAt(i)->set_animating_mini_change(false);
-
-  if (layout)
-    Layout();
-}
-
-gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event) {
-  if (gdk_region_empty(event->region))
-    return TRUE;
-
-  // If we're only repainting favicons, optimize the paint path and only draw
-  // the favicons.
-  GdkRectangle* rects;
-  gint num_rects;
-  gdk_region_get_rectangles(event->region, &rects, &num_rects);
-  qsort(rects, num_rects, sizeof(GdkRectangle), CompareGdkRectangles);
-  std::vector<int> tabs_to_repaint;
-  if (!IsDragSessionActive() &&
-      CanPaintOnlyFavIcons(rects, num_rects, &tabs_to_repaint)) {
-    PaintOnlyFavIcons(event, tabs_to_repaint);
-    g_free(rects);
-    return TRUE;
-  }
-  g_free(rects);
-
-  // TODO(jhawkins): Ideally we'd like to only draw what's needed in the damage
-  // rect, but the tab widgets overlap each other, and painting on one widget
-  // will cause an expose-event to be sent to the widgets underneath.  The
-  // underlying widget does not need to be redrawn as we control the order of
-  // expose-events.  Currently we hack it to redraw the entire tabstrip.  We
-  // could change the damage rect to just contain the tabs + the new tab button.
-  event->area.x = 0;
-  event->area.y = 0;
-  event->area.width = bounds_.width();
-  event->area.height = bounds_.height();
-  gdk_region_union_with_rect(event->region, &event->area);
-
-  // Paint the New Tab button.
-  gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()),
-      newtab_button_->widget(), event);
-
-  // Paint the tabs in reverse order, so they stack to the left.
-  TabGtk* selected_tab = NULL;
-  int tab_count = GetTabCount();
-  for (int i = tab_count - 1; i >= 0; --i) {
-    TabGtk* tab = GetTabAt(i);
-    // We must ask the _Tab's_ model, not ourselves, because in some situations
-    // the model will be different to this object, e.g. when a Tab is being
-    // removed after its TabContents has been destroyed.
-    if (!tab->IsSelected()) {
-      gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()),
-                                     tab->widget(), event);
-    } else {
-      selected_tab = tab;
-    }
-  }
-
-  // Paint the selected tab last, so it overlaps all the others.
-  if (selected_tab) {
-    gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()),
-                                   selected_tab->widget(), event);
-  }
-
-  return TRUE;
-}
-
-void TabStripGtk::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) {
-  gfx::Rect bounds = gfx::Rect(allocation->x, allocation->y,
-      allocation->width, allocation->height);
-
-  // Nothing to do if the bounds are the same.  If we don't catch this, we'll
-  // get an infinite loop of size-allocate signals.
-  if (bounds_ == bounds)
-    return;
-
-  SetBounds(bounds);
-
-  // No tabs, nothing to layout.  This happens when a browser window is created
-  // and shown before tabs are added (as in a popup window).
-  if (GetTabCount() == 0)
-    return;
-
-  // When there is only one tab, Layout() so we don't animate it. With more
-  // tabs, do ResizeLayoutTabs(). In RTL(), we will also need to manually
-  // Layout() when ResizeLayoutTabs() is a no-op.
-  if ((GetTabCount() == 1) || (!ResizeLayoutTabs() && base::i18n::IsRTL()))
-    Layout();
-}
-
-gboolean TabStripGtk::OnDragMotion(GtkWidget* widget, GdkDragContext* context,
-                                   gint x, gint y, guint time) {
-  UpdateDropIndex(context, x, y);
-  return TRUE;
-}
-
-gboolean TabStripGtk::OnDragDrop(GtkWidget* widget, GdkDragContext* context,
-                                 gint x, gint y, guint time) {
-  if (!drop_info_.get())
-    return FALSE;
-
-  GdkAtom target = gtk_drag_dest_find_target(widget, context, NULL);
-  if (target != GDK_NONE)
-    gtk_drag_finish(context, FALSE, FALSE, time);
-  else
-    gtk_drag_get_data(widget, context, target, time);
-
-  return TRUE;
-}
-
-gboolean TabStripGtk::OnDragLeave(GtkWidget* widget, GdkDragContext* context,
-                                  guint time) {
-  // Destroy the drop indicator.
-  drop_info_->DestroyContainer();
-  return FALSE;
-}
-
-gboolean TabStripGtk::OnDragDataReceived(GtkWidget* widget,
-                                         GdkDragContext* context,
-                                         gint x, gint y,
-                                         GtkSelectionData* data,
-                                         guint info, guint time) {
-  bool success = false;
-
-  if (info == gtk_dnd_util::TEXT_URI_LIST ||
-      info == gtk_dnd_util::NETSCAPE_URL ||
-      info == gtk_dnd_util::TEXT_PLAIN) {
-    success = CompleteDrop(data->data, info == gtk_dnd_util::TEXT_PLAIN);
-  }
-
-  gtk_drag_finish(context, success, success, time);
-  return TRUE;
-}
-
-void TabStripGtk::OnNewTabClicked(GtkWidget* widget) {
-  GdkEvent* event = gtk_get_current_event();
-  DCHECK_EQ(event->type, GDK_BUTTON_RELEASE);
-  int mouse_button = event->button.button;
-  gdk_event_free(event);
-
-  switch (mouse_button) {
-    case 1:
-      model_->delegate()->AddBlankTab(true);
-      break;
-    case 2: {
-      // On middle-click, try to parse the PRIMARY selection as a URL and load
-      // it instead of creating a blank page.
-      GURL url;
-      if (!gtk_util::URLFromPrimarySelection(model_->profile(), &url))
-        return;
-
-      Browser* browser = window_->browser();
-      DCHECK(browser);
-      browser->AddSelectedTabWithURL(url, PageTransition::TYPED);
-      break;
-    }
-    default:
-      NOTREACHED() << "Got click on new tab button with unhandled mouse "
-                   << "button " << mouse_button;
-  }
-}
-
-void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) {
-  gfx::Rect bds = bounds;
-  bds.set_x(gtk_util::MirroredLeftPointForRect(tabstrip_.get(), bounds));
-  tab->SetBounds(bds);
-  gtk_fixed_move(GTK_FIXED(tabstrip_.get()), tab->widget(),
-                 bds.x(), bds.y());
-}
-
-bool TabStripGtk::CanPaintOnlyFavIcons(const GdkRectangle* rects,
-    int num_rects, std::vector<int>* tabs_to_paint) {
-  // |rects| are sorted so we just need to scan from left to right and compare
-  // it to the tab favicon positions from left to right.
-  int t = 0;
-  for (int r = 0; r < num_rects; ++r) {
-    while (t < GetTabCount()) {
-      TabGtk* tab = GetTabAt(t);
-      if (GdkRectMatchesTabFavIconBounds(rects[r], tab) &&
-          tab->ShouldShowIcon()) {
-        tabs_to_paint->push_back(t);
-        ++t;
-        break;
-      }
-      ++t;
-    }
-  }
-  return static_cast<int>(tabs_to_paint->size()) == num_rects;
-}
-
-void TabStripGtk::PaintOnlyFavIcons(GdkEventExpose* event,
-                                    const std::vector<int>& tabs_to_paint) {
-  for (size_t i = 0; i < tabs_to_paint.size(); ++i)
-    GetTabAt(tabs_to_paint[i])->PaintFavIconArea(event);
-}
-
-CustomDrawButton* TabStripGtk::MakeNewTabButton() {
-  CustomDrawButton* button = new CustomDrawButton(IDR_NEWTAB_BUTTON,
-      IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0);
-
-  // Let the middle mouse button initiate clicks as well.
-  gtk_util::SetButtonTriggersNavigation(button->widget());
-  g_signal_connect(button->widget(), "clicked",
-                   G_CALLBACK(OnNewTabClickedThunk), this);
-  GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS);
-  gtk_fixed_put(GTK_FIXED(tabstrip_.get()), button->widget(), 0, 0);
-
-  return button;
-}
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.h b/chrome/browser/gtk/tabs/tab_strip_gtk.h
deleted file mode 100644
index 20d9ee0..0000000
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.h
+++ /dev/null
@@ -1,465 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TABS_TAB_STRIP_GTK_H_
-#define CHROME_BROWSER_GTK_TABS_TAB_STRIP_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-#include <vector>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "base/task.h"
-#include "base/message_loop.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
-#include "chrome/browser/gtk/tabstrip_origin_provider.h"
-#include "chrome/browser/gtk/tabs/tab_gtk.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/common/notification_observer.h"
-#include "gfx/rect.h"
-
-class BrowserWindowGtk;
-class CustomDrawButton;
-class DraggedTabControllerGtk;
-class GtkThemeProvider;
-
-class TabStripGtk : public TabStripModelObserver,
-                    public TabGtk::TabDelegate,
-                    public MessageLoopForUI::Observer,
-                    public NotificationObserver,
-                    public TabstripOriginProvider,
-                    public ViewIDUtil::Delegate {
- public:
-  class TabAnimation;
-
-  TabStripGtk(TabStripModel* model, BrowserWindowGtk* window);
-  virtual ~TabStripGtk();
-
-  // Initialize and load the TabStrip into a container.
-  // TODO(tc): Pass in theme provider so we can properly theme the tabs.
-  void Init();
-
-  void Show();
-  void Hide();
-
-  TabStripModel* model() const { return model_; }
-
-  BrowserWindowGtk* window() const { return window_; }
-
-  GtkWidget* widget() const { return tabstrip_.get(); }
-
-  // Returns true if there is an active drag session.
-  bool IsDragSessionActive() const { return drag_controller_.get() != NULL; }
-
-  // Returns true if a tab is being dragged into this tabstrip.
-  bool IsActiveDropTarget() const;
-
-  // Sets the bounds of the tabs.
-  void Layout();
-
-  // Queues a draw for the tabstrip widget.
-  void SchedulePaint();
-
-  // Sets the bounds of the tabstrip.
-  void SetBounds(const gfx::Rect& bounds);
-
-  // Returns the bounds of the tabstrip.
-  const gfx::Rect& bounds() const { return bounds_; }
-
-  // Updates loading animations for the TabStrip.
-  void UpdateLoadingAnimations();
-
-  // Return true if this tab strip is compatible with the provided tab strip.
-  // Compatible tab strips can transfer tabs during drag and drop.
-  bool IsCompatibleWith(TabStripGtk* other);
-
-  // Returns true if Tabs in this TabStrip are currently changing size or
-  // position.
-  bool IsAnimating() const;
-
-  // Destroys the active drag controller.
-  void DestroyDragController();
-
-  // Removes the drag source tab from this tabstrip, and deletes it.
-  void DestroyDraggedSourceTab(TabGtk* tab);
-
-  // Retrieve the ideal bounds for the Tab at the specified index.
-  gfx::Rect GetIdealBounds(int index);
-
-  // Sets the vertical offset that each tab will use to offset against the
-  // background image. Passed in from the titlebar and based on the size of the
-  // alignment that sits above the tabstrip.
-  void SetVerticalOffset(int offset);
-
-  // TabstripOriginProvider implementation -------------------------------------
-  virtual gfx::Point GetTabStripOriginForWidget(GtkWidget* widget);
-
-  // ViewIDUtil::Delegate implementation ---------------------------------------
-  virtual GtkWidget* GetWidgetForViewID(ViewID id);
-
- protected:
-  // TabStripModelObserver implementation:
-  virtual void TabInsertedAt(TabContentsWrapper* contents,
-                             int index,
-                             bool foreground);
-  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
-  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* contents,
-                             int index,
-                             bool user_gesture);
-  virtual void TabMoved(TabContentsWrapper* contents,
-                        int from_index,
-                        int to_index);
-  virtual void TabChangedAt(TabContentsWrapper* contents, int index,
-                            TabChangeType change_type);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* new_contents,
-                             int index);
-  virtual void TabMiniStateChanged(TabContentsWrapper* contents, int index);
-  virtual void TabBlockedStateChanged(TabContentsWrapper* contents,
-                                      int index);
-
-  // TabGtk::TabDelegate implementation:
-  virtual bool IsTabSelected(const TabGtk* tab) const;
-  virtual bool IsTabPinned(const TabGtk* tab) const;
-  virtual bool IsTabDetached(const TabGtk* tab) const;
-  virtual void SelectTab(TabGtk* tab);
-  virtual void CloseTab(TabGtk* tab);
-  virtual bool IsCommandEnabledForTab(
-      TabStripModel::ContextMenuCommand command_id, const TabGtk* tab) const;
-  virtual void ExecuteCommandForTab(
-      TabStripModel::ContextMenuCommand command_id, TabGtk* tab);
-  virtual void StartHighlightTabsForCommand(
-      TabStripModel::ContextMenuCommand command_id, TabGtk* tab);
-  virtual void StopHighlightTabsForCommand(
-      TabStripModel::ContextMenuCommand command_id, TabGtk* tab);
-  virtual void StopAllHighlighting();
-  virtual void MaybeStartDrag(TabGtk* tab, const gfx::Point& point);
-  virtual void ContinueDrag(GdkDragContext* context);
-  virtual bool EndDrag(bool canceled);
-  virtual bool HasAvailableDragActions() const;
-  virtual ThemeProvider* GetThemeProvider();
-
-  // MessageLoop::Observer implementation:
-  virtual void WillProcessEvent(GdkEvent* event);
-  virtual void DidProcessEvent(GdkEvent* event);
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Horizontal gap between mini-tabs and normal tabs.
-  static const int mini_to_non_mini_gap_;
-
- private:
-  friend class BrowserWindowGtk;
-  friend class DraggedTabControllerGtk;
-  friend class InsertTabAnimation;
-  friend class MiniMoveAnimation;
-  friend class MiniTabAnimation;
-  friend class MoveTabAnimation;
-  friend class RemoveTabAnimation;
-  friend class ResizeLayoutAnimation;
-  friend class TabAnimation;
-
-  struct TabData {
-    TabGtk* tab;
-    gfx::Rect ideal_bounds;
-  };
-
-  // Used during a drop session of a url. Tracks the position of the drop as
-  // well as a window used to highlight where the drop occurs.
-  class DropInfo {
-   public:
-    DropInfo(int index, bool drop_before, bool point_down);
-    virtual ~DropInfo();
-
-    // TODO(jhawkins): Factor out this code into a TransparentContainer class.
-
-    // expose-event handler that redraws the drop indicator.
-    CHROMEGTK_CALLBACK_1(DropInfo, gboolean, OnExposeEvent, GdkEventExpose*);
-
-    // Sets the color map of the container window to allow the window to be
-    // transparent.
-    void SetContainerColorMap();
-
-    // Sets full transparency for the container window.  This is used if
-    // compositing is available for the screen.
-    void SetContainerTransparency();
-
-    // Sets the shape mask for the container window to emulate a transparent
-    // container window.  This is used if compositing is not available for the
-    // screen.
-    void SetContainerShapeMask();
-
-    // Creates the container widget.
-    void CreateContainer();
-
-    // Destroys the container widget.
-    void DestroyContainer();
-
-    // Index of the tab to drop on. If drop_before is true, the drop should
-    // occur between the tab at drop_index - 1 and drop_index.
-    // WARNING: if drop_before is true it is possible this will == tab_count,
-    // which indicates the drop should create a new tab at the end of the tabs.
-    int drop_index;
-    bool drop_before;
-
-    // Direction the arrow should point in. If true, the arrow is displayed
-    // above the tab and points down. If false, the arrow is displayed beneath
-    // the tab and points up.
-    bool point_down;
-
-    // Transparent container window used to render the drop indicator over the
-    // tabstrip and toolbar.
-    GtkWidget* container;
-
-    // The drop indicator image.
-    GdkPixbuf* drop_arrow;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(DropInfo);
-  };
-
-  // expose-event handler that redraws the tabstrip
-  CHROMEGTK_CALLBACK_1(TabStripGtk, gboolean, OnExpose, GdkEventExpose*);
-
-  // size-allocate handler that gets the new bounds of the tabstrip.
-  CHROMEGTK_CALLBACK_1(TabStripGtk, void, OnSizeAllocate, GtkAllocation*);
-
-  // drag-motion handler that is signaled when the user performs a drag in the
-  // tabstrip bounds.
-  CHROMEGTK_CALLBACK_4(TabStripGtk, gboolean, OnDragMotion, GdkDragContext*,
-                       gint, gint, guint);
-
-  // drag-drop handler that is notified when the user finishes a drag.
-  CHROMEGTK_CALLBACK_4(TabStripGtk, gboolean, OnDragDrop, GdkDragContext*,
-                       gint, gint, guint);
-
-  // drag-leave handler that is signaled when the mouse leaves the tabstrip
-  // during a drag.
-  CHROMEGTK_CALLBACK_2(TabStripGtk, gboolean, OnDragLeave, GdkDragContext*,
-                       guint);
-
-  // drag-data-received handler that receives the data associated with the drag.
-  CHROMEGTK_CALLBACK_6(TabStripGtk, gboolean, OnDragDataReceived,
-                       GdkDragContext*, gint, gint, GtkSelectionData*,
-                       guint, guint);
-
-  // Handles the clicked signal from the new tab button.
-  CHROMEGTK_CALLBACK_0(TabStripGtk, void, OnNewTabClicked);
-
-  // Sets the bounds of the tab and moves the tab widget to those bounds.
-  void SetTabBounds(TabGtk* tab, const gfx::Rect& bounds);
-
-  // Returns true if |rects| are all areas that match up with tab favicons.
-  // |rects| must be sorted from left to right.  |tabs_to_paint| are the tab
-  // positions that match the rects.
-  bool CanPaintOnlyFavIcons(const GdkRectangle* rects,
-                            int num_rects,
-                            std::vector<int>* tabs_to_paint);
-
-  // Paints the tab favicon areas for tabs in |tabs_to_paint|.
-  void PaintOnlyFavIcons(GdkEventExpose* event,
-                         const std::vector<int>& tabs_to_paint);
-
-  // Initializes the new tab button.
-  CustomDrawButton* MakeNewTabButton();
-
-  // Gets the number of Tabs in the collection.
-  int GetTabCount() const;
-
-  // Returns the number of mini-tabs.
-  int GetMiniTabCount() const;
-
-  // Retrieves the Tab at the specified index. Take care in using this, you may
-  // need to use GetTabAtAdjustForAnimation.
-  TabGtk* GetTabAt(int index) const;
-
-  // Returns the tab at the specified index. If a remove animation is on going
-  // and the index is >= the index of the tab being removed, the index is
-  // incremented. While a remove operation is on going the indices of the model
-  // do not line up with the indices of the view. This method adjusts the index
-  // accordingly.
-  //
-  // Use this instead of GetTabAt if the index comes from the model.
-  TabGtk* GetTabAtAdjustForAnimation(int index) const;
-
-  // Returns the exact (unrounded) current width of each tab.
-  void GetCurrentTabWidths(double* unselected_width,
-                           double* selected_width) const;
-
-  // Returns the exact (unrounded) desired width of each tab, based on the
-  // desired strip width and number of tabs.  If
-  // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in
-  // calculating the desired strip width; otherwise we use the current width.
-  // |mini_tab_count| gives the number of mini-tabs, and |tab_count| the
-  // number of mini and non-mini-tabs.
-  void GetDesiredTabWidths(int tab_count,
-                           int mini_tab_count,
-                           double* unselected_width,
-                           double* selected_width) const;
-
-  // Returns the horizontal offset before the tab at |tab_index|.
-  int GetTabHOffset(int tab_index);
-
-  // Returns the x-coordinate tabs start from.
-  int tab_start_x() const;
-
-  // Perform an animated resize-relayout of the TabStrip immediately. The
-  // value returned indicates whether a resize actually took place.
-  bool ResizeLayoutTabs();
-
-  // Returns whether or not the cursor is currently in the "tab strip zone"
-  // which is defined as the region above the TabStrip and a bit below it.
-  bool IsCursorInTabStripZone() const;
-
-  // Ensure that the message loop observer used for event spying is added and
-  // removed appropriately so we can tell when to resize layout the tab strip.
-  void AddMessageLoopObserver();
-  void RemoveMessageLoopObserver();
-
-  // Calculates the available width for tabs, assuming a Tab is to be closed.
-  int GetAvailableWidthForTabs(TabGtk* last_tab) const;
-
-  // Finds the index of the TabContents corresponding to |tab| in our
-  // associated TabStripModel, or -1 if there is none (e.g. the specified |tab|
-  // is being animated closed).
-  int GetIndexOfTab(const TabGtk* tab) const;
-
-  // Cleans up the tab from the TabStrip at the specified |index|.
-  void RemoveTabAt(int index);
-
-  // Called from the message loop observer when a mouse movement has occurred
-  // anywhere over our containing window.
-  void HandleGlobalMouseMoveEvent();
-
-  // Generates the ideal bounds of the TabStrip when all Tabs have finished
-  // animating to their desired position/bounds. This is used by the standard
-  // Layout method and other callers like the DraggedTabController that need
-  // stable representations of Tab positions.
-  void GenerateIdealBounds();
-
-  // Lays out the New Tab button, assuming the right edge of the last Tab on
-  // the TabStrip at |last_tab_right|.  |unselected_width| is the width of
-  // unselected tabs at the moment this function is called.  The value changes
-  // during animations, so we can't use current_unselected_width_.
-  void LayoutNewTabButton(double last_tab_right, double unselected_width);
-
-  // -- Link Drag & Drop ------------------------------------------------------
-
-  // Returns the bounds to render the drop at, in screen coordinates. Sets
-  // |is_beneath| to indicate whether the arrow is beneath the tab, or above
-  // it.
-  gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath);
-
-  // Updates the location of the drop based on the event.
-  void UpdateDropIndex(GdkDragContext* context, gint x, gint y);
-
-  // Sets the location of the drop, repainting as necessary.
-  void SetDropIndex(int index, bool drop_before);
-
-  // Determines whether the data is acceptable by the tabstrip and opens a new
-  // tab with the data as URL if it is.  Returns true if the drop was
-  // successful.
-  bool CompleteDrop(guchar* data, bool is_plain_text);
-
-  // Returns the image to use for indicating a drop on a tab. If is_down is
-  // true, this returns an arrow pointing down.
-  static GdkPixbuf* GetDropArrowImage(bool is_down);
-
-  // -- Animations -------------------------------------------------------------
-
-  // Stops the current animation.
-  void StopAnimation();
-
-  // A generic Layout method for various classes of TabStrip animations,
-  // including Insert, Remove and Resize Layout cases.
-  void AnimationLayout(double unselected_width);
-
-  // Starts various types of TabStrip animations.
-  void StartInsertTabAnimation(int index);
-  void StartRemoveTabAnimation(int index, TabContents* contents);
-  void StartMoveTabAnimation(int from_index, int to_index);
-  void StartMiniTabAnimation(int index);
-  void StartMiniMoveTabAnimation(int from_index,
-                                 int to_index,
-                                 const gfx::Rect& start_bounds);
-  void StartResizeLayoutAnimation();
-
-  // Notifies the TabStrip that the specified TabAnimation has completed.
-  // Optionally a full Layout will be performed, specified by |layout|.
-  void FinishAnimation(TabAnimation* animation, bool layout);
-
-  NotificationRegistrar registrar_;
-
-  // The Tabs we contain, and their last generated "good" bounds.
-  std::vector<TabData> tab_data_;
-
-  // The current widths of various types of tabs.  We save these so that, as
-  // users close tabs while we're holding them at the same size, we can lay out
-  // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving
-  // them all at their existing, rounded widths.
-  double current_unselected_width_;
-  double current_selected_width_;
-
-  // If this value is nonnegative, it is used in GetDesiredTabWidths() to
-  // calculate how much space in the tab strip to use for tabs.  Most of the
-  // time this will be -1, but while we're handling closing a tab via the mouse,
-  // we'll set this to the edge of the last tab before closing, so that if we
-  // are closing the last tab and need to resize immediately, we'll resize only
-  // back to this width, thus once again placing the last tab under the mouse
-  // cursor.
-  int available_width_for_tabs_;
-
-  // True if a resize layout animation should be run a short delay after the
-  // mouse exits the TabStrip.
-  bool needs_resize_layout_;
-
-  // The GtkFixed widget.
-  OwnedWidgetGtk tabstrip_;
-
-  // The bounds of the tabstrip.
-  gfx::Rect bounds_;
-
-  // The amount to offset tab backgrounds when we are using an autogenerated
-  // tab background image.
-  int tab_vertical_offset_;
-
-  // Our model.
-  TabStripModel* model_;
-
-  // The BrowserWindowGtk containing this tab strip.
-  BrowserWindowGtk* window_;
-
-  // Theme resources.
-  GtkThemeProvider* theme_provider_;
-
-  // The currently running animation.
-  scoped_ptr<TabAnimation> active_animation_;
-
-  // The New Tab button.
-  scoped_ptr<CustomDrawButton> newtab_button_;
-
-  // Valid for the lifetime of a drag over us.
-  scoped_ptr<DropInfo> drop_info_;
-
-  // The controller for a drag initiated from a Tab. Valid for the lifetime of
-  // the drag session.
-  scoped_ptr<DraggedTabControllerGtk> drag_controller_;
-
-  // A factory that is used to construct a delayed callback to the
-  // ResizeLayoutTabsNow method.
-  ScopedRunnableMethodFactory<TabStripGtk> resize_layout_factory_;
-
-  // True if the tabstrip has already been added as a MessageLoop observer.
-  bool added_as_message_loop_observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabStripGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TABS_TAB_STRIP_GTK_H_
diff --git a/chrome/browser/gtk/tabstrip_origin_provider.h b/chrome/browser/gtk/tabstrip_origin_provider.h
deleted file mode 100644
index 0904a01..0000000
--- a/chrome/browser/gtk/tabstrip_origin_provider.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TABSTRIP_ORIGIN_PROVIDER_H_
-#define CHROME_BROWSER_GTK_TABSTRIP_ORIGIN_PROVIDER_H_
-#pragma once
-
-namespace gfx{
-class Point;
-}
-
-// Abstract interface that provides an offset of a widget. Many pieces of the
-// UI don't need the full BrowserWindowGtk, but just need information about
-// it's position relative to the tabstrip to draw correctly. This interface
-// exists to make it easier to test piece by piece.
-class TabstripOriginProvider {
- public:
-  virtual ~TabstripOriginProvider() { }
-
-  // Return the origin of the tab strip in coordinates relative to where we
-  // start drawing the background theme image. This is the x coordinate of
-  // the origin of the GdkWindow of widget(), but the y coordinate of the origin
-  // of widget() itself.
-  // Used to help other widgets draw their background relative to the tabstrip.
-  // Should only be called after both the tabstrip and |widget| have been
-  // allocated.
-  virtual gfx::Point GetTabStripOriginForWidget(GtkWidget* widget) = 0;
-};
-
-#endif  // CHROME_BROWSER_GTK_TABSTRIP_ORIGIN_PROVIDER_H_
diff --git a/chrome/browser/gtk/task_manager_gtk.cc b/chrome/browser/gtk/task_manager_gtk.cc
deleted file mode 100644
index ccc5f73..0000000
--- a/chrome/browser/gtk/task_manager_gtk.cc
+++ /dev/null
@@ -1,959 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/task_manager_gtk.h"
-
-#include <gdk/gdkkeysyms.h>
-
-#include <algorithm>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "app/l10n_util.h"
-#include "app/menus/simple_menu_model.h"
-#include "app/resource_bundle.h"
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_tree.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/memory_purger.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/gtk_util.h"
-#include "grit/app_resources.h"
-#include "grit/chromium_strings.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-#if defined(TOOLKIT_VIEWS)
-#include "views/controls/menu/menu_2.h"
-#else
-#include "chrome/browser/gtk/menu_gtk.h"
-#endif
-
-namespace {
-
-// The task manager window default size.
-const int kDefaultWidth = 460;
-const int kDefaultHeight = 270;
-
-// The resource id for the 'End process' button.
-const gint kTaskManagerResponseKill = 1;
-
-// The resource id for the 'Stats for nerds' link button.
-const gint kTaskManagerAboutMemoryLink = 2;
-
-// The resource id for the 'Purge Memory' button
-const gint kTaskManagerPurgeMemory = 3;
-
-enum TaskManagerColumn {
-  kTaskManagerIcon,
-  kTaskManagerPage,
-  kTaskManagerSharedMem,
-  kTaskManagerPrivateMem,
-  kTaskManagerCPU,
-  kTaskManagerNetwork,
-  kTaskManagerProcessID,
-  kTaskManagerJavaScriptMemory,
-  kTaskManagerWebCoreImageCache,
-  kTaskManagerWebCoreScriptsCache,
-  kTaskManagerWebCoreCssCache,
-  kTaskManagerSqliteMemoryUsed,
-  kTaskManagerGoatsTeleported,
-  kTaskManagerColumnCount,
-};
-
-TaskManagerColumn TaskManagerResourceIDToColumnID(int id) {
-  switch (id) {
-    case IDS_TASK_MANAGER_PAGE_COLUMN:
-      return kTaskManagerPage;
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
-      return kTaskManagerSharedMem;
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
-      return kTaskManagerPrivateMem;
-    case IDS_TASK_MANAGER_CPU_COLUMN:
-      return kTaskManagerCPU;
-    case IDS_TASK_MANAGER_NET_COLUMN:
-      return kTaskManagerNetwork;
-    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
-      return kTaskManagerProcessID;
-    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
-      return kTaskManagerJavaScriptMemory;
-    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
-      return kTaskManagerWebCoreImageCache;
-    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
-      return kTaskManagerWebCoreScriptsCache;
-    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
-      return kTaskManagerWebCoreCssCache;
-    case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
-      return kTaskManagerSqliteMemoryUsed;
-    case IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN:
-      return kTaskManagerGoatsTeleported;
-    default:
-      NOTREACHED();
-      return static_cast<TaskManagerColumn>(-1);
-  }
-}
-
-int TaskManagerColumnIDToResourceID(int id) {
-  switch (id) {
-    case kTaskManagerPage:
-      return IDS_TASK_MANAGER_PAGE_COLUMN;
-    case kTaskManagerSharedMem:
-      return IDS_TASK_MANAGER_SHARED_MEM_COLUMN;
-    case kTaskManagerPrivateMem:
-      return IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN;
-    case kTaskManagerCPU:
-      return IDS_TASK_MANAGER_CPU_COLUMN;
-    case kTaskManagerNetwork:
-      return IDS_TASK_MANAGER_NET_COLUMN;
-    case kTaskManagerProcessID:
-      return IDS_TASK_MANAGER_PROCESS_ID_COLUMN;
-    case kTaskManagerJavaScriptMemory:
-      return IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN;
-    case kTaskManagerWebCoreImageCache:
-      return IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN;
-    case kTaskManagerWebCoreScriptsCache:
-      return IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN;
-    case kTaskManagerWebCoreCssCache:
-      return IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN;
-    case kTaskManagerSqliteMemoryUsed:
-      return IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN;
-    case kTaskManagerGoatsTeleported:
-      return IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN;
-    default:
-      NOTREACHED();
-      return -1;
-  }
-}
-
-// Should be used for all gtk_tree_view functions that require a column index on
-// input.
-//
-// We need colid - 1 because the gtk_tree_view function is asking for the
-// column index, not the column id, and both kTaskManagerIcon and
-// kTaskManagerPage are in the same column index, so all column IDs are off by
-// one.
-int TreeViewColumnIndexFromID(TaskManagerColumn colid) {
-  return colid - 1;
-}
-
-// Shows or hides a treeview column.
-void TreeViewColumnSetVisible(GtkWidget* treeview, TaskManagerColumn colid,
-                              bool visible) {
-  GtkTreeViewColumn* column = gtk_tree_view_get_column(
-      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
-  gtk_tree_view_column_set_visible(column, visible);
-}
-
-bool TreeViewColumnIsVisible(GtkWidget* treeview, TaskManagerColumn colid) {
-  GtkTreeViewColumn* column = gtk_tree_view_get_column(
-      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
-  return gtk_tree_view_column_get_visible(column);
-}
-
-void TreeViewInsertColumnWithPixbuf(GtkWidget* treeview, int resid) {
-  int colid = TaskManagerResourceIDToColumnID(resid);
-  GtkTreeViewColumn* column = gtk_tree_view_column_new();
-  gtk_tree_view_column_set_title(column,
-                                 l10n_util::GetStringUTF8(resid).c_str());
-  GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
-  gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
-  gtk_tree_view_column_add_attribute(column, image_renderer,
-                                     "pixbuf", kTaskManagerIcon);
-  GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
-  gtk_tree_view_column_add_attribute(column, text_renderer, "text", colid);
-  gtk_tree_view_column_set_resizable(column, TRUE);
-  // This is temporary: we'll turn expanding off after getting the size.
-  gtk_tree_view_column_set_expand(column, TRUE);
-  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
-  gtk_tree_view_column_set_sort_column_id(column, colid);
-}
-
-// Inserts a column with a column id of |colid| and |name|.
-void TreeViewInsertColumnWithName(GtkWidget* treeview,
-                                  TaskManagerColumn colid, const char* name) {
-  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
-  gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1,
-                                              name, renderer,
-                                              "text", colid,
-                                              NULL);
-  GtkTreeViewColumn* column = gtk_tree_view_get_column(
-      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
-  gtk_tree_view_column_set_resizable(column, TRUE);
-  gtk_tree_view_column_set_sort_column_id(column, colid);
-}
-
-// Loads the column name from |resid| and uses the corresponding
-// TaskManagerColumn value as the column id to insert into the treeview.
-void TreeViewInsertColumn(GtkWidget* treeview, int resid) {
-  TreeViewInsertColumnWithName(treeview, TaskManagerResourceIDToColumnID(resid),
-                               l10n_util::GetStringUTF8(resid).c_str());
-}
-
-// Set the current width of the column without forcing a minimum width as
-// gtk_tree_view_column_set_fixed_width() would. This would basically be
-// gtk_tree_view_column_set_width() except that there is no such function.
-void TreeViewColumnSetWidth(GtkTreeViewColumn* column, gint width) {
-  column->width = width;
-  column->resized_width = width;
-  column->use_resized_width = TRUE;
-  // Needed for use_resized_width to be effective.
-  gtk_widget_queue_resize(column->tree_view);
-}
-
-}  // namespace
-
-class TaskManagerGtk::ContextMenuController
-    : public menus::SimpleMenuModel::Delegate {
- public:
-  explicit ContextMenuController(TaskManagerGtk* task_manager)
-      : task_manager_(task_manager) {
-    menu_model_.reset(new menus::SimpleMenuModel(this));
-    for (int i = kTaskManagerPage; i < kTaskManagerColumnCount; i++) {
-      menu_model_->AddCheckItemWithStringId(
-          i, TaskManagerColumnIDToResourceID(i));
-    }
-#if defined(TOOLKIT_VIEWS)
-    menu_.reset(new views::Menu2(menu_model_.get()));
-#else
-    menu_.reset(new MenuGtk(NULL, menu_model_.get()));
-#endif
-  }
-
-  virtual ~ContextMenuController() {}
-
-#if defined(TOOLKIT_VIEWS)
-  void RunMenu(const gfx::Point& point) {
-    menu_->RunContextMenuAt(point);
-  }
-#else
-  void RunMenu() {
-    menu_->PopupAsContext(gtk_get_current_event_time());
-  }
-#endif
-
-  void Cancel() {
-    task_manager_ = NULL;
-#if defined(TOOLKIT_VIEWS)
-    menu_->CancelMenu();
-#else
-    menu_->Cancel();
-#endif
-  }
-
- private:
-  // menus::SimpleMenuModel::Delegate implementation:
-  virtual bool IsCommandIdEnabled(int command_id) const {
-    if (!task_manager_)
-      return false;
-
-    return true;
-  }
-
-  virtual bool IsCommandIdChecked(int command_id) const {
-    if (!task_manager_)
-      return false;
-
-    TaskManagerColumn colid = static_cast<TaskManagerColumn>(command_id);
-    return TreeViewColumnIsVisible(task_manager_->treeview_, colid);
-  }
-
-  virtual bool GetAcceleratorForCommandId(
-      int command_id,
-      menus::Accelerator* accelerator) {
-    return false;
-  }
-
-  virtual void ExecuteCommand(int command_id) {
-    if (!task_manager_)
-      return;
-
-    TaskManagerColumn colid = static_cast<TaskManagerColumn>(command_id);
-    bool visible = !TreeViewColumnIsVisible(task_manager_->treeview_, colid);
-    TreeViewColumnSetVisible(task_manager_->treeview_, colid, visible);
-  }
-
-  // The model and view for the right click context menu.
-  scoped_ptr<menus::SimpleMenuModel> menu_model_;
-#if defined(TOOLKIT_VIEWS)
-  scoped_ptr<views::Menu2> menu_;
-#else
-  scoped_ptr<MenuGtk> menu_;
-#endif
-
-  // The TaskManager the context menu was brought up for. Set to NULL when the
-  // menu is canceled.
-  TaskManagerGtk* task_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
-};
-
-TaskManagerGtk::TaskManagerGtk()
-  : task_manager_(TaskManager::GetInstance()),
-    model_(TaskManager::GetInstance()->model()),
-    dialog_(NULL),
-    treeview_(NULL),
-    process_list_(NULL),
-    process_count_(0),
-    ignore_selection_changed_(false) {
-  Init();
-}
-
-// static
-TaskManagerGtk* TaskManagerGtk::instance_ = NULL;
-
-TaskManagerGtk::~TaskManagerGtk() {
-  model_->RemoveObserver(this);
-  task_manager_->OnWindowClosed();
-
-  gtk_accel_group_disconnect_key(accel_group_, GDK_w, GDK_CONTROL_MASK);
-  gtk_window_remove_accel_group(GTK_WINDOW(dialog_), accel_group_);
-  g_object_unref(accel_group_);
-  accel_group_ = NULL;
-
-  // Disconnect the destroy signal so it doesn't delete |this|.
-  g_signal_handler_disconnect(G_OBJECT(dialog_), destroy_handler_id_);
-  gtk_widget_destroy(dialog_);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TaskManagerGtk, TaskManagerModelObserver implementation:
-
-void TaskManagerGtk::OnModelChanged() {
-  // Nothing to do.
-}
-
-void TaskManagerGtk::OnItemsChanged(int start, int length) {
-  GtkTreeIter iter;
-  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
-                                NULL, start);
-
-  for (int i = start; i < start + length; i++) {
-    SetRowDataFromModel(i, &iter);
-    gtk_tree_model_iter_next(GTK_TREE_MODEL(process_list_), &iter);
-  }
-}
-
-void TaskManagerGtk::OnItemsAdded(int start, int length) {
-  AutoReset<bool> autoreset(&ignore_selection_changed_, true);
-
-  GtkTreeIter iter;
-  if (start == 0) {
-    gtk_list_store_prepend(process_list_, &iter);
-  } else if (start >= process_count_) {
-    gtk_list_store_append(process_list_, &iter);
-  } else {
-    GtkTreeIter sibling;
-    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &sibling,
-                                  NULL, start);
-    gtk_list_store_insert_before(process_list_, &iter, &sibling);
-  }
-
-  SetRowDataFromModel(start, &iter);
-
-  for (int i = start + 1; i < start + length; i++) {
-    gtk_list_store_insert_after(process_list_, &iter, &iter);
-    SetRowDataFromModel(i, &iter);
-  }
-
-  process_count_ += length;
-}
-
-void TaskManagerGtk::OnItemsRemoved(int start, int length) {
-  {
-    AutoReset<bool> autoreset(&ignore_selection_changed_, true);
-
-    GtkTreeIter iter;
-    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
-                                  NULL, start);
-
-    for (int i = 0; i < length; i++) {
-      // |iter| is moved to the next valid node when the current node is
-      // removed.
-      gtk_list_store_remove(process_list_, &iter);
-    }
-
-    process_count_ -= length;
-  }
-
-  // It is possible that we have removed the current selection; run selection
-  // changed to detect that case.
-  OnSelectionChanged(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_)));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TaskManagerGtk, public:
-
-// static
-void TaskManagerGtk::Show() {
-  if (instance_) {
-    // If there's a Task manager window open already, just activate it.
-    gtk_util::PresentWindow(instance_->dialog_, 0);
-  } else {
-    instance_ = new TaskManagerGtk;
-    instance_->model_->StartUpdating();
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TaskManagerGtk, private:
-
-void TaskManagerGtk::Init() {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_TITLE).c_str(),
-      // Task Manager window is shared between all browsers.
-      NULL,
-      GTK_DIALOG_NO_SEPARATOR,
-      NULL);
-
-  // Allow browser windows to go in front of the task manager dialog in
-  // metacity.
-  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
-
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kPurgeMemoryButton)) {
-    gtk_dialog_add_button(GTK_DIALOG(dialog_),
-        l10n_util::GetStringUTF8(IDS_TASK_MANAGER_PURGE_MEMORY).c_str(),
-        kTaskManagerPurgeMemory);
-  }
-
-  if (browser_defaults::kShowCancelButtonInTaskManager) {
-    gtk_dialog_add_button(GTK_DIALOG(dialog_),
-        l10n_util::GetStringUTF8(IDS_CLOSE).c_str(),
-        GTK_RESPONSE_DELETE_EVENT);
-  }
-
-  gtk_dialog_add_button(GTK_DIALOG(dialog_),
-      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_KILL).c_str(),
-      kTaskManagerResponseKill);
-
-  // The response button should not be sensitive when the dialog is first opened
-  // because the selection is initially empty.
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
-                                    kTaskManagerResponseKill, FALSE);
-
-  GtkWidget* link = gtk_chrome_link_button_new(
-      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK).c_str());
-  gtk_dialog_add_action_widget(GTK_DIALOG(dialog_), link,
-                               kTaskManagerAboutMemoryLink);
-
-  // Setting the link widget to secondary positions the button on the left side
-  // of the action area (vice versa for RTL layout).
-  gtk_button_box_set_child_secondary(
-      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area), link, TRUE);
-
-  ConnectAccelerators();
-
-  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
-                      gtk_util::kContentAreaSpacing);
-
-  destroy_handler_id_ = g_signal_connect(dialog_, "destroy",
-                                         G_CALLBACK(OnDestroyThunk), this);
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-  g_signal_connect(dialog_, "button-release-event",
-                   G_CALLBACK(OnButtonReleaseEventThunk), this);
-  gtk_widget_add_events(dialog_,
-                        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
-
-  // Wrap the treeview widget in a scrolled window in order to have a frame.
-  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
-                                      GTK_SHADOW_ETCHED_IN);
-  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
-                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
-  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), scrolled);
-
-  CreateTaskManagerTreeview();
-  gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(treeview_), TRUE);
-  g_signal_connect(treeview_, "row-activated",
-                   G_CALLBACK(OnRowActivatedThunk), this);
-
-  // |selection| is owned by |treeview_|.
-  GtkTreeSelection* selection = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(treeview_));
-  gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
-  g_signal_connect(selection, "changed",
-                   G_CALLBACK(OnSelectionChangedThunk), this);
-
-  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
-
-  SetInitialDialogSize();
-  gtk_util::ShowDialog(dialog_);
-
-  // If the model already has resources, we need to add them before we start
-  // observing events.
-  if (model_->ResourceCount() > 0)
-    OnItemsAdded(0, model_->ResourceCount());
-
-  model_->AddObserver(this);
-}
-
-void TaskManagerGtk::SetInitialDialogSize() {
-  // Hook up to the realize event so we can size the page column to the
-  // size of the leftover space after packing the other columns.
-  g_signal_connect(treeview_, "realize",
-                   G_CALLBACK(OnTreeViewRealizeThunk), this);
-  // If we previously saved the dialog's bounds, use them.
-  if (g_browser_process->local_state()) {
-    const DictionaryValue* placement_pref =
-        g_browser_process->local_state()->GetDictionary(
-            prefs::kTaskManagerWindowPlacement);
-    int top = 0, left = 0, bottom = 1, right = 1;
-    if (placement_pref &&
-        placement_pref->GetInteger("top", &top) &&
-        placement_pref->GetInteger("left", &left) &&
-        placement_pref->GetInteger("bottom", &bottom) &&
-        placement_pref->GetInteger("right", &right)) {
-      gtk_window_resize(GTK_WINDOW(dialog_),
-                        std::max(1, right - left),
-                        std::max(1, bottom - top));
-      return;
-    }
-  }
-
-  // Otherwise, just set a default size (GTK will override this if it's not
-  // large enough to hold the window's contents).
-  gtk_window_set_default_size(
-      GTK_WINDOW(dialog_), kDefaultWidth, kDefaultHeight);
-}
-
-void TaskManagerGtk::ConnectAccelerators() {
-  accel_group_ = gtk_accel_group_new();
-  gtk_window_add_accel_group(GTK_WINDOW(dialog_), accel_group_);
-
-  gtk_accel_group_connect(accel_group_,
-                          GDK_w, GDK_CONTROL_MASK, GtkAccelFlags(0),
-                          g_cclosure_new(G_CALLBACK(OnGtkAcceleratorThunk),
-                                         this, NULL));
-}
-
-void TaskManagerGtk::CreateTaskManagerTreeview() {
-  process_list_ = gtk_list_store_new(kTaskManagerColumnCount,
-      GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-      G_TYPE_STRING);
-
-  // Support sorting on all columns.
-  process_list_sort_ = gtk_tree_model_sort_new_with_model(
-      GTK_TREE_MODEL(process_list_));
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerPage,
-                                  ComparePage, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerSharedMem,
-                                  CompareSharedMemory, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerPrivateMem,
-                                  ComparePrivateMemory, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerJavaScriptMemory,
-                                  CompareV8Memory, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerCPU,
-                                  CompareCPU, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerNetwork,
-                                  CompareNetwork, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerProcessID,
-                                  CompareProcessID, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerWebCoreImageCache,
-                                  CompareWebCoreImageCache, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerWebCoreScriptsCache,
-                                  CompareWebCoreScriptsCache, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerWebCoreCssCache,
-                                  CompareWebCoreCssCache, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerSqliteMemoryUsed,
-                                  CompareSqliteMemoryUsed, this, NULL);
-  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
-                                  kTaskManagerGoatsTeleported,
-                                  CompareGoatsTeleported, this, NULL);
-  treeview_ = gtk_tree_view_new_with_model(process_list_sort_);
-
-  // Insert all the columns.
-  TreeViewInsertColumnWithPixbuf(treeview_, IDS_TASK_MANAGER_PAGE_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_CPU_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_NET_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
-  TreeViewInsertColumn(treeview_,
-                       IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
-  TreeViewInsertColumn(treeview_,
-                       IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
-  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
-
-  // Hide some columns by default.
-  TreeViewColumnSetVisible(treeview_, kTaskManagerSharedMem, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerProcessID, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerJavaScriptMemory, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreImageCache, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreScriptsCache, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreCssCache, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerSqliteMemoryUsed, false);
-  TreeViewColumnSetVisible(treeview_, kTaskManagerGoatsTeleported, false);
-
-  g_object_unref(process_list_);
-  g_object_unref(process_list_sort_);
-}
-
-bool IsSharedByGroup(int col_id) {
-  switch (col_id) {
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
-    case IDS_TASK_MANAGER_CPU_COLUMN:
-    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
-    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
-    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
-    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
-    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
-      return true;
-    default:
-      return false;
-  }
-}
-
-std::string TaskManagerGtk::GetModelText(int row, int col_id) {
-  if (IsSharedByGroup(col_id) && !model_->IsResourceFirstInGroup(row))
-    return std::string();
-
-  switch (col_id) {
-    case IDS_TASK_MANAGER_PAGE_COLUMN:  // Process
-      return UTF16ToUTF8(model_->GetResourceTitle(row));
-
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:  // Memory
-      return UTF16ToUTF8(model_->GetResourcePrivateMemory(row));
-
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:  // Memory
-      return UTF16ToUTF8(model_->GetResourceSharedMemory(row));
-
-    case IDS_TASK_MANAGER_CPU_COLUMN:  // CPU
-      return UTF16ToUTF8(model_->GetResourceCPUUsage(row));
-
-    case IDS_TASK_MANAGER_NET_COLUMN:  // Net
-      return UTF16ToUTF8(model_->GetResourceNetworkUsage(row));
-
-    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:  // Process ID
-      return UTF16ToUTF8(model_->GetResourceProcessId(row));
-
-    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
-      return UTF16ToUTF8(model_->GetResourceV8MemoryAllocatedSize(row));
-
-    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
-      return UTF16ToUTF8(model_->GetResourceWebCoreImageCacheSize(row));
-
-    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
-      return UTF16ToUTF8(model_->GetResourceWebCoreScriptsCacheSize(row));
-
-    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
-      return UTF16ToUTF8(model_->GetResourceWebCoreCSSCacheSize(row));
-
-    case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
-      return UTF16ToUTF8(model_->GetResourceSqliteMemoryUsed(row));
-
-    case IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN:  // Goats Teleported!
-      return UTF16ToUTF8(model_->GetResourceGoatsTeleported(row));
-
-    default:
-      NOTREACHED();
-      return std::string();
-  }
-}
-
-GdkPixbuf* TaskManagerGtk::GetModelIcon(int row) {
-  SkBitmap icon = model_->GetResourceIcon(row);
-  if (icon.pixelRef() ==
-      ResourceBundle::GetSharedInstance().GetBitmapNamed(
-          IDR_DEFAULT_FAVICON)->pixelRef()) {
-    return static_cast<GdkPixbuf*>(g_object_ref(
-        GtkThemeProvider::GetDefaultFavicon(true)));
-  }
-
-  return gfx::GdkPixbufFromSkBitmap(&icon);
-}
-
-void TaskManagerGtk::SetRowDataFromModel(int row, GtkTreeIter* iter) {
-  GdkPixbuf* icon = GetModelIcon(row);
-  std::string page = GetModelText(row, IDS_TASK_MANAGER_PAGE_COLUMN);
-  std::string shared_mem = GetModelText(
-      row, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
-  std::string priv_mem = GetModelText(row, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
-  std::string cpu = GetModelText(row, IDS_TASK_MANAGER_CPU_COLUMN);
-  std::string net = GetModelText(row, IDS_TASK_MANAGER_NET_COLUMN);
-  std::string procid = GetModelText(row, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
-
-  // Querying the renderer metrics is slow as it has to do IPC, so only do it
-  // when the columns are visible.
-  std::string javascript_memory;
-  if (TreeViewColumnIsVisible(treeview_, kTaskManagerJavaScriptMemory))
-    javascript_memory = GetModelText(
-        row, IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
-  std::string wk_img_cache;
-  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreImageCache))
-    wk_img_cache = GetModelText(
-        row, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
-  std::string wk_scripts_cache;
-  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreScriptsCache))
-    wk_scripts_cache = GetModelText(
-        row, IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
-  std::string wk_css_cache;
-  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreCssCache))
-    wk_css_cache = GetModelText(
-        row, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
-  std::string sqlite_memory;
-  if (TreeViewColumnIsVisible(treeview_, kTaskManagerSqliteMemoryUsed))
-    sqlite_memory = GetModelText(
-        row, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
-
-  std::string goats = GetModelText(
-      row, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
-  gtk_list_store_set(process_list_, iter,
-                     kTaskManagerIcon, icon,
-                     kTaskManagerPage, page.c_str(),
-                     kTaskManagerSharedMem, shared_mem.c_str(),
-                     kTaskManagerPrivateMem, priv_mem.c_str(),
-                     kTaskManagerCPU, cpu.c_str(),
-                     kTaskManagerNetwork, net.c_str(),
-                     kTaskManagerProcessID, procid.c_str(),
-                     kTaskManagerJavaScriptMemory, javascript_memory.c_str(),
-                     kTaskManagerWebCoreImageCache, wk_img_cache.c_str(),
-                     kTaskManagerWebCoreScriptsCache, wk_scripts_cache.c_str(),
-                     kTaskManagerWebCoreCssCache, wk_css_cache.c_str(),
-                     kTaskManagerSqliteMemoryUsed, sqlite_memory.c_str(),
-                     kTaskManagerGoatsTeleported, goats.c_str(),
-                     -1);
-  g_object_unref(icon);
-}
-
-void TaskManagerGtk::KillSelectedProcesses() {
-  GtkTreeSelection* selection = gtk_tree_view_get_selection(
-      GTK_TREE_VIEW(treeview_));
-
-  GtkTreeModel* model;
-  GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
-  for (GList* item = paths; item; item = item->next) {
-    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
-        GTK_TREE_MODEL_SORT(process_list_sort_),
-        reinterpret_cast<GtkTreePath*>(item->data));
-    int row = gtk_tree::GetRowNumForPath(path);
-    gtk_tree_path_free(path);
-    task_manager_->KillProcess(row);
-  }
-  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
-  g_list_free(paths);
-}
-
-#if defined(TOOLKIT_VIEWS)
-void TaskManagerGtk::ShowContextMenu(const gfx::Point& point) {
-  if (!menu_controller_.get())
-    menu_controller_.reset(new ContextMenuController(this));
-
-  menu_controller_->RunMenu(point);
-}
-#else
-void TaskManagerGtk::ShowContextMenu() {
-  if (!menu_controller_.get())
-    menu_controller_.reset(new ContextMenuController(this));
-
-  menu_controller_->RunMenu();
-}
-#endif
-
-void TaskManagerGtk::OnLinkActivated() {
-  task_manager_->OpenAboutMemory();
-}
-
-gint TaskManagerGtk::CompareImpl(GtkTreeModel* model, GtkTreeIter* a,
-                                 GtkTreeIter* b, int id) {
-  int row1 = gtk_tree::GetRowNumForIter(model, b);
-  int row2 = gtk_tree::GetRowNumForIter(model, a);
-
-  // When sorting by non-grouped attributes (e.g., Network), just do a normal
-  // sort.
-  if (!IsSharedByGroup(id))
-    return model_->CompareValues(row1, row2, id);
-
-  // Otherwise, make sure grouped resources are shown together.
-  std::pair<int, int> group_range1 = model_->GetGroupRangeForResource(row1);
-  std::pair<int, int> group_range2 = model_->GetGroupRangeForResource(row2);
-
-  if (group_range1 == group_range2) {
-    // Sort within groups.
-    // We want the first-in-group row at the top, whether we are sorting up or
-    // down.
-    GtkSortType sort_type;
-    gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(process_list_sort_),
-                                         NULL, &sort_type);
-    if (row1 == group_range1.first)
-      return sort_type == GTK_SORT_ASCENDING ? -1 : 1;
-    if (row2 == group_range2.first)
-      return sort_type == GTK_SORT_ASCENDING ? 1 : -1;
-
-    return model_->CompareValues(row1, row2, id);
-  } else {
-    // Sort between groups.
-    // Compare by the first-in-group rows so that the groups will stay together.
-    return model_->CompareValues(group_range1.first, group_range2.first, id);
-  }
-}
-
-void TaskManagerGtk::OnDestroy(GtkWidget* dialog) {
-  instance_ = NULL;
-  delete this;
-}
-
-void TaskManagerGtk::OnResponse(GtkWidget* dialog, gint response_id) {
-  if (response_id == GTK_RESPONSE_DELETE_EVENT) {
-    // Store the dialog's size so we can restore it the next time it's opened.
-    if (g_browser_process->local_state()) {
-      gfx::Rect dialog_bounds = gtk_util::GetDialogBounds(GTK_WIDGET(dialog));
-
-      DictionaryValue* placement_pref =
-          g_browser_process->local_state()->GetMutableDictionary(
-              prefs::kTaskManagerWindowPlacement);
-      // Note that we store left/top for consistency with Windows, but that we
-      // *don't* restore them.
-      placement_pref->SetInteger("left", dialog_bounds.x());
-      placement_pref->SetInteger("top", dialog_bounds.y());
-      placement_pref->SetInteger("right", dialog_bounds.right());
-      placement_pref->SetInteger("bottom", dialog_bounds.bottom());
-      placement_pref->SetBoolean("maximized", false);
-    }
-
-    instance_ = NULL;
-    delete this;
-  } else if (response_id == kTaskManagerResponseKill) {
-    KillSelectedProcesses();
-  } else if (response_id == kTaskManagerAboutMemoryLink) {
-    OnLinkActivated();
-  } else if (response_id == kTaskManagerPurgeMemory) {
-    MemoryPurger::PurgeAll();
-  }
-}
-
-void TaskManagerGtk::OnTreeViewRealize(GtkTreeView* treeview) {
-  // Four columns show by default: the page column, the memory column, the
-  // CPU column, and the network column. Initially we set the page column to
-  // take all the extra space, with the other columns being sized to fit the
-  // column names. Here we turn off the expand property of the first column
-  // (to make the table behave sanely when the user resizes columns) and set
-  // the effective sizes of all four default columns to the automatically
-  // chosen size before any rows are added. This causes them to stay at that
-  // size even if the data would overflow, preventing a horizontal scroll
-  // bar from appearing due to the row data.
-  const TaskManagerColumn dfl_columns[] = {kTaskManagerNetwork, kTaskManagerCPU,
-                                           kTaskManagerPrivateMem};
-  GtkTreeViewColumn* column = NULL;
-  gint width;
-  for (size_t i = 0; i < arraysize(dfl_columns); ++i) {
-    column = gtk_tree_view_get_column(treeview,
-        TreeViewColumnIndexFromID(dfl_columns[i]));
-    width = gtk_tree_view_column_get_width(column);
-    TreeViewColumnSetWidth(column, width);
-  }
-  // Do the page column separately since it's a little different.
-  column = gtk_tree_view_get_column(treeview,
-      TreeViewColumnIndexFromID(kTaskManagerPage));
-  width = gtk_tree_view_column_get_width(column);
-  // Turn expanding back off to make resizing columns behave sanely.
-  gtk_tree_view_column_set_expand(column, FALSE);
-  TreeViewColumnSetWidth(column, width);
-}
-
-void TaskManagerGtk::OnSelectionChanged(GtkTreeSelection* selection) {
-  if (ignore_selection_changed_)
-    return;
-  AutoReset<bool> autoreset(&ignore_selection_changed_, true);
-
-  // The set of groups that should be selected.
-  std::set<std::pair<int, int> > ranges;
-  bool selection_contains_browser_process = false;
-
-  GtkTreeModel* model;
-  GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
-  for (GList* item = paths; item; item = item->next) {
-    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
-        GTK_TREE_MODEL_SORT(process_list_sort_),
-        reinterpret_cast<GtkTreePath*>(item->data));
-    int row = gtk_tree::GetRowNumForPath(path);
-    gtk_tree_path_free(path);
-    if (task_manager_->IsBrowserProcess(row))
-      selection_contains_browser_process = true;
-    ranges.insert(model_->GetGroupRangeForResource(row));
-  }
-  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
-  g_list_free(paths);
-
-  for (std::set<std::pair<int, int> >::iterator iter = ranges.begin();
-       iter != ranges.end(); ++iter) {
-    for (int i = 0; i < iter->second; ++i) {
-      GtkTreePath* child_path = gtk_tree_path_new_from_indices(iter->first + i,
-                                                               -1);
-      GtkTreePath* sort_path = gtk_tree_model_sort_convert_child_path_to_path(
-        GTK_TREE_MODEL_SORT(process_list_sort_), child_path);
-      gtk_tree_selection_select_path(selection, sort_path);
-      gtk_tree_path_free(child_path);
-      gtk_tree_path_free(sort_path);
-    }
-  }
-
-  bool sensitive = (paths != NULL) && !selection_contains_browser_process;
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
-                                    kTaskManagerResponseKill, sensitive);
-}
-
-void TaskManagerGtk::OnRowActivated(GtkWidget* widget,
-                                    GtkTreePath* path,
-                                    GtkTreeViewColumn* column) {
-  GtkTreePath* child_path = gtk_tree_model_sort_convert_path_to_child_path(
-      GTK_TREE_MODEL_SORT(process_list_sort_), path);
-  int row = gtk_tree::GetRowNumForPath(child_path);
-  gtk_tree_path_free(child_path);
-  task_manager_->ActivateProcess(row);
-}
-
-gboolean TaskManagerGtk::OnButtonReleaseEvent(GtkWidget* widget,
-                                              GdkEventButton* event) {
-  if (event->button == 3) {
-#if defined(TOOLKIT_VIEWS)
-    gfx::Point pt(event->x_root, event->y_root);
-    ShowContextMenu(pt);
-#else
-    ShowContextMenu();
-#endif
-  }
-
-  return FALSE;
-}
-
-gboolean TaskManagerGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
-                                          GObject* acceleratable,
-                                          guint keyval,
-                                          GdkModifierType modifier) {
-  if (keyval == GDK_w && modifier == GDK_CONTROL_MASK) {
-    // The GTK_RESPONSE_DELETE_EVENT response must be sent before the widget
-    // is destroyed.  The deleted object will receive gtk signals otherwise.
-    gtk_dialog_response(GTK_DIALOG(dialog_), GTK_RESPONSE_DELETE_EVENT);
-  }
-
-  return TRUE;
-}
diff --git a/chrome/browser/gtk/task_manager_gtk.h b/chrome/browser/gtk/task_manager_gtk.h
deleted file mode 100644
index 5aa5907..0000000
--- a/chrome/browser/gtk/task_manager_gtk.h
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TASK_MANAGER_GTK_H_
-#define CHROME_BROWSER_GTK_TASK_MANAGER_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include <string>
-
-#include "app/gtk_signal.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/task_manager/task_manager.h"
-#include "grit/generated_resources.h"
-
-#if defined(TOOLKIT_VIEWS)
-namespace gfx {
-class Point;
-}
-#endif
-
-class TaskManagerGtk : public TaskManagerModelObserver {
- public:
-  TaskManagerGtk();
-  virtual ~TaskManagerGtk();
-
-  // TaskManagerModelObserver
-  virtual void OnModelChanged();
-  virtual void OnItemsChanged(int start, int length);
-  virtual void OnItemsAdded(int start, int length);
-  virtual void OnItemsRemoved(int start, int length);
-
-  // Creates the task manager if it doesn't exist; otherwise, it activates the
-  // existing task manager window.
-  static void Show();
-
- private:
-  class ContextMenuController;
-  friend class ContextMenuController;
-
-  // Initializes the task manager dialog.
-  void Init();
-
-  // Set |dialog_|'s initial size, using its previous size if that was saved.
-  void SetInitialDialogSize();
-
-  // Connects the ctrl-w accelerator to the dialog.
-  void ConnectAccelerators();
-
-  // Sets up the treeview widget.
-  void CreateTaskManagerTreeview();
-
-  // Returns the model data for a given |row| and |col_id|.
-  std::string GetModelText(int row, int col_id);
-
-  // Retrieves the resource icon from the model for |row|.
-  GdkPixbuf* GetModelIcon(int row);
-
-  // Sets the treeview row data.  |row| is an index into the model and |iter|
-  // is the current position in the treeview.
-  void SetRowDataFromModel(int row, GtkTreeIter* iter);
-
-  // Queries the treeview for the selected rows, and kills those processes.
-  void KillSelectedProcesses();
-
-  // Opens the context menu used to select the task manager columns.
-#if defined(TOOLKIT_VIEWS)
-  void ShowContextMenu(const gfx::Point& point);
-#else
-  void ShowContextMenu();
-#endif
-
-  // Opens about:memory in a new foreground tab.
-  void OnLinkActivated();
-
-  // Compare implementation used for sorting columns.
-  gint CompareImpl(GtkTreeModel* tree_model, GtkTreeIter* a,
-                   GtkTreeIter* b, int id);
-
-  // Response signal handler that notifies us of dialog destruction.
-  CHROMEGTK_CALLBACK_0(TaskManagerGtk, void, OnDestroy);
-
-  // Response signal handler that notifies us of dialog responses.
-  CHROMEGTK_CALLBACK_1(TaskManagerGtk, void, OnResponse, gint);
-
-  // Realize signal handler to set the page column's initial size.
-  CHROMEG_CALLBACK_0(TaskManagerGtk, void, OnTreeViewRealize, GtkTreeView*);
-
-  // Changed signal handler that is sent when the treeview selection changes.
-  CHROMEG_CALLBACK_0(TaskManagerGtk, void, OnSelectionChanged,
-                     GtkTreeSelection*);
-
-  // row-activated handler that foregrounds a process on activation (e.g.,
-  // double-click).
-  CHROMEGTK_CALLBACK_2(TaskManagerGtk, void, OnRowActivated,
-                       GtkTreePath*, GtkTreeViewColumn*);
-
-  // button-release-event handler that opens the right-click context menu.
-  CHROMEGTK_CALLBACK_1(TaskManagerGtk, gboolean, OnButtonReleaseEvent,
-                       GdkEventButton*);
-
-  // Handles an accelerator being pressed.
-  CHROMEG_CALLBACK_3(TaskManagerGtk, gboolean, OnGtkAccelerator,
-                     GtkAccelGroup*, GObject*, guint, GdkModifierType);
-
-  // Page sorting callback.
-  static gint ComparePage(GtkTreeModel* model, GtkTreeIter* a,
-                          GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_PAGE_COLUMN);
-  }
-
-  // Shared memory sorting callback.
-  static gint CompareSharedMemory(GtkTreeModel* model, GtkTreeIter* a,
-                                  GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
-  }
-
-  // Private memory sorting callback.
-  static gint ComparePrivateMemory(GtkTreeModel* model, GtkTreeIter* a,
-                                   GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
-  }
-
-  // Javascript memory sorting callback.
-  static gint CompareV8Memory(GtkTreeModel* model, GtkTreeIter* a,
-                              GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b,
-                    IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
-  }
-
-  // CPU sorting callback.
-  static gint CompareCPU(GtkTreeModel* model, GtkTreeIter* a,
-                         GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_CPU_COLUMN);
-  }
-
-  // Network sorting callback.
-  static gint CompareNetwork(GtkTreeModel* model, GtkTreeIter* a,
-                             GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_NET_COLUMN);
-  }
-
-  // Process ID sorting callback.
-  static gint CompareProcessID(GtkTreeModel* model, GtkTreeIter* a,
-                               GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
-  }
-
-  // WebCore Image Cache sorting callback.
-  static gint CompareWebCoreImageCache(GtkTreeModel* model, GtkTreeIter* a,
-                                       GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
-  }
-
-  // WebCore Scripts Cache sorting callback.
-  static gint CompareWebCoreScriptsCache(GtkTreeModel* model, GtkTreeIter* a,
-                                         GtkTreeIter* b,
-                                         gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
-  }
-
-  // WebCore CSS Cache sorting callback.
-  static gint CompareWebCoreCssCache(GtkTreeModel* model, GtkTreeIter* a,
-                                     GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
-  }
-
-  // Sqlite memory sorting callback.
-  static gint CompareSqliteMemoryUsed(GtkTreeModel* model, GtkTreeIter* a,
-                                      GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
-  }
-
-  // Goats Teleported sorting callback.
-  static gint CompareGoatsTeleported(GtkTreeModel* model, GtkTreeIter* a,
-                                     GtkTreeIter* b, gpointer task_manager) {
-    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
-        CompareImpl(model, a, b, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
-  }
-
-  // The task manager.
-  TaskManager* task_manager_;
-
-  // Our model.
-  TaskManagerModel* model_;
-
-  // The task manager dialog window.
-  GtkWidget* dialog_;
-
-  // The treeview that contains the process list.
-  GtkWidget* treeview_;
-
-  // The list of processes.
-  GtkListStore* process_list_;
-  GtkTreeModel* process_list_sort_;
-
-  // The number of processes in |process_list_|.
-  int process_count_;
-
-  // The id of the |dialog_| destroy signal handler.
-  gulong destroy_handler_id_;
-
-  // The context menu controller.
-  scoped_ptr<ContextMenuController> menu_controller_;
-
-  GtkAccelGroup* accel_group_;
-
-  // An open task manager window. There can only be one open at a time. This
-  // is reset to NULL when the window is closed.
-  static TaskManagerGtk* instance_;
-
-  // We edit the selection in the OnSelectionChanged handler, and we use this
-  // variable to prevent ourselves from handling further changes that we
-  // ourselves caused.
-  bool ignore_selection_changed_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaskManagerGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_TASK_MANAGER_GTK_H_
diff --git a/chrome/browser/gtk/theme_install_bubble_view_gtk.cc b/chrome/browser/gtk/theme_install_bubble_view_gtk.cc
deleted file mode 100644
index a08d393..0000000
--- a/chrome/browser/gtk/theme_install_bubble_view_gtk.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/theme_install_bubble_view_gtk.h"
-
-#include <math.h>
-
-#include "app/l10n_util.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/rounded_window.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "grit/generated_resources.h"
-
-// Roundedness of bubble.
-static const int kBubbleCornerRadius = 4;
-
-// Padding between border of bubble and text.
-static const int kTextPadding = 8;
-
-// The bubble is partially transparent.
-static const double kBubbleOpacity = static_cast<double>(0xcc) / 0xff;
-
-ThemeInstallBubbleViewGtk* ThemeInstallBubbleViewGtk::instance_ = NULL;
-
-// ThemeInstallBubbleViewGtk, public -------------------------------------------
-
-// static
-void ThemeInstallBubbleViewGtk::Show(GtkWindow* parent) {
-  if (instance_)
-    instance_->increment_num_loading();
-  else
-    instance_ = new ThemeInstallBubbleViewGtk(GTK_WIDGET(parent));
-}
-
-void ThemeInstallBubbleViewGtk::Observe(NotificationType type,
-                                        const NotificationSource& source,
-                                        const NotificationDetails& details) {
-  if (--num_loads_extant_ == 0)
-    delete this;
-}
-
-// ThemeInstallBubbleViewGtk, private ------------------------------------------
-
-ThemeInstallBubbleViewGtk::ThemeInstallBubbleViewGtk(GtkWidget* parent)
-    : widget_(NULL),
-      parent_(parent),
-      num_loads_extant_(1) {
-  InitWidgets();
-
-  // Close when theme has been installed.
-  registrar_.Add(
-      this,
-      NotificationType::BROWSER_THEME_CHANGED,
-      NotificationService::AllSources());
-
-  // Close when we are installing an extension, not a theme.
-  registrar_.Add(
-      this,
-      NotificationType::NO_THEME_DETECTED,
-      NotificationService::AllSources());
-  registrar_.Add(
-      this,
-      NotificationType::EXTENSION_INSTALLED,
-      NotificationService::AllSources());
-  registrar_.Add(
-      this,
-      NotificationType::EXTENSION_INSTALL_ERROR,
-      NotificationService::AllSources());
-
-  // Don't let the bubble overlap the confirm dialog.
-  registrar_.Add(
-      this,
-      NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
-      NotificationService::AllSources());
-}
-
-ThemeInstallBubbleViewGtk::~ThemeInstallBubbleViewGtk() {
-  gtk_widget_destroy(widget_);
-  instance_ = NULL;
-}
-
-void ThemeInstallBubbleViewGtk::InitWidgets() {
-  // Widgematically, the bubble is just a label in a popup window.
-  widget_ = gtk_window_new(GTK_WINDOW_POPUP);
-  gtk_container_set_border_width(GTK_CONTAINER(widget_), kTextPadding);
-  GtkWidget* label = gtk_label_new(NULL);
-
-  gchar* markup = g_markup_printf_escaped(
-      "<span size='xx-large'>%s</span>",
-      l10n_util::GetStringUTF8(IDS_THEME_LOADING_TITLE).c_str());
-  gtk_label_set_markup(GTK_LABEL(label), markup);
-  g_free(markup);
-
-  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkWhite);
-  gtk_container_add(GTK_CONTAINER(widget_), label);
-
-  // We need to show the label so we'll know the widget's actual size when we
-  // call MoveWindow().
-  gtk_widget_show_all(label);
-
-  bool composited = false;
-  if (gtk_util::IsScreenComposited()) {
-    composited = true;
-    GdkScreen* screen = gtk_widget_get_screen(widget_);
-    GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
-
-    if (colormap)
-      gtk_widget_set_colormap(widget_, colormap);
-    else
-      composited = false;
-  }
-
-  if (composited) {
-    gtk_widget_set_app_paintable(widget_, TRUE);
-    g_signal_connect(widget_, "expose-event",
-                     G_CALLBACK(OnExposeThunk), this);
-    gtk_widget_realize(widget_);
-  } else {
-    gtk_widget_modify_bg(widget_, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-    GdkColor color;
-    gtk_util::ActAsRoundedWindow(widget_, color, kBubbleCornerRadius,
-                                 gtk_util::ROUNDED_ALL, gtk_util::BORDER_NONE);
-  }
-
-  MoveWindow();
-
-  g_signal_connect(widget_, "unmap-event",
-                   G_CALLBACK(OnUnmapEventThunk), this);
-
-  gtk_widget_show_all(widget_);
-}
-
-void ThemeInstallBubbleViewGtk::MoveWindow() {
-  GtkRequisition req;
-  gtk_widget_size_request(widget_, &req);
-
-  gint parent_x = 0, parent_y = 0;
-  gdk_window_get_position(parent_->window, &parent_x, &parent_y);
-  gint parent_width = parent_->allocation.width;
-  gint parent_height = parent_->allocation.height;
-
-  gint x = parent_x + parent_width / 2 - req.width / 2;
-  gint y = parent_y + parent_height / 2 - req.height / 2;
-
-  gtk_window_move(GTK_WINDOW(widget_), x, y);
-}
-
-gboolean ThemeInstallBubbleViewGtk::OnUnmapEvent(GtkWidget* widget) {
-  delete this;
-  return FALSE;
-}
-
-gboolean ThemeInstallBubbleViewGtk::OnExpose(GtkWidget* widget,
-                                             GdkEventExpose* event) {
-  cairo_t* cr = gdk_cairo_create(event->window);
-  gdk_cairo_rectangle(cr, &event->area);
-  cairo_clip(cr);
-
-  cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
-  cairo_paint(cr);
-  cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-
-  // |inner_rect| has its corners at the centerpoints of the corner arcs.
-  gfx::Rect inner_rect(widget_->allocation);
-  int inset = kBubbleCornerRadius;
-  inner_rect.Inset(inset, inset);
-
-  // The positive y axis is down, so M_PI_2 is down.
-  cairo_arc(cr, inner_rect.x(), inner_rect.y(), inset,
-            M_PI, 3 * M_PI_2);
-  cairo_arc(cr, inner_rect.right(), inner_rect.y(), inset,
-            3 * M_PI_2, 0);
-  cairo_arc(cr, inner_rect.right(), inner_rect.bottom(), inset,
-            0, M_PI_2);
-  cairo_arc(cr, inner_rect.x(), inner_rect.bottom(), inset,
-            M_PI_2, M_PI);
-
-  cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, kBubbleOpacity);
-  cairo_fill(cr);
-  cairo_destroy(cr);
-
-  return FALSE;
-}
diff --git a/chrome/browser/gtk/theme_install_bubble_view_gtk.h b/chrome/browser/gtk/theme_install_bubble_view_gtk.h
deleted file mode 100644
index fe38690..0000000
--- a/chrome/browser/gtk/theme_install_bubble_view_gtk.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_THEME_INSTALL_BUBBLE_VIEW_GTK_H_
-#define CHROME_BROWSER_GTK_THEME_INSTALL_BUBBLE_VIEW_GTK_H_
-#pragma once
-
-#include <gtk/gtk.h>
-
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class ThemeInstallBubbleViewGtk : public NotificationObserver {
- public:
-  static void Show(GtkWindow* parent);
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
- private:
-  explicit ThemeInstallBubbleViewGtk(GtkWidget* parent);
-
-  virtual ~ThemeInstallBubbleViewGtk();
-
-  void increment_num_loading() { num_loads_extant_++; }
-
-  // Create the widget hierarchy.
-  void InitWidgets();
-
-  // Reposition |widget_| to be centered over |parent_|.
-  void MoveWindow();
-
-  // Our parent is going down; self destruct.
-  CHROMEGTK_CALLBACK_0(ThemeInstallBubbleViewGtk, gboolean, OnUnmapEvent);
-
-  // Draw the background. This is only signalled if we are using a compositing
-  // window manager, otherwise we just use ActAsRoundedWindow().
-  CHROMEGTK_CALLBACK_1(ThemeInstallBubbleViewGtk, gboolean,
-                       OnExpose, GdkEventExpose*);
-
-  GtkWidget* widget_;
-
-  // The parent browser window, over which we position ourselves.
-  GtkWidget* parent_;
-
-  // The number of loads we represent. When it reaches 0 we delete ourselves.
-  int num_loads_extant_;
-
-  NotificationRegistrar registrar_;
-
-  // Our one instance. We don't allow more than one to exist at a time.
-  static ThemeInstallBubbleViewGtk* instance_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThemeInstallBubbleViewGtk);
-};
-
-#endif  // CHROME_BROWSER_GTK_THEME_INSTALL_BUBBLE_VIEW_GTK_H_
diff --git a/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc b/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc
deleted file mode 100644
index 3f36ca6..0000000
--- a/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/translate/after_translate_infobar_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "grit/generated_resources.h"
-
-AfterTranslateInfoBar::AfterTranslateInfoBar(
-    TranslateInfoBarDelegate* delegate)
-    : TranslateInfoBarBase(delegate),
-      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
-}
-
-AfterTranslateInfoBar::~AfterTranslateInfoBar() {
-}
-
-void AfterTranslateInfoBar::Init() {
-  TranslateInfoBarBase::Init();
-
-  bool swapped_language_combos = false;
-  std::vector<string16> strings;
-  TranslateInfoBarDelegate::GetAfterTranslateStrings(
-      &strings, &swapped_language_combos);
-  DCHECK(strings.size() == 3U);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_util::CenterWidgetInHBox(hbox_, hbox, false, 0);
-
-  GtkWidget* original_lang_combo =
-      CreateLanguageCombobox(GetDelegate()->original_language_index(),
-                             GetDelegate()->target_language_index());
-  g_signal_connect(original_lang_combo, "changed",
-                   G_CALLBACK(&OnOriginalLanguageModifiedThunk), this);
-  GtkWidget* target_lang_combo =
-      CreateLanguageCombobox(GetDelegate()->target_language_index(),
-                             GetDelegate()->original_language_index());
-  g_signal_connect(target_lang_combo, "changed",
-                   G_CALLBACK(&OnTargetLanguageModifiedThunk), this);
-
-  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(UTF16ToUTF8(strings[0])),
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox),
-                     swapped_language_combos ? target_lang_combo :
-                                               original_lang_combo,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(UTF16ToUTF8(strings[1])),
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox),
-                     swapped_language_combos ? original_lang_combo :
-                                               target_lang_combo,
-                     FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(UTF16ToUTF8(strings[2])),
-                     FALSE, FALSE, 0);
-
-  GtkWidget* button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_REVERT).c_str());
-  g_signal_connect(button, "clicked",G_CALLBACK(&OnRevertPressedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-}
-
-bool AfterTranslateInfoBar::ShowOptionsMenuButton() const {
-  return true;
-}
-
-void AfterTranslateInfoBar::OnOriginalLanguageModified(GtkWidget* sender) {
-  int index = GetLanguageComboboxActiveId(GTK_COMBO_BOX(sender));
-  if (index == GetDelegate()->original_language_index())
-    return;
-
-  // Setting the language will lead to a new translation that is going to close
-  // the infobar.  This is not OK to do this from the signal handler, so we'll
-  // defer it.
-  MessageLoop::current()->PostTask(FROM_HERE, method_factory_.NewRunnableMethod(
-      &AfterTranslateInfoBar::SetOriginalLanguage, index));
-}
-
-void AfterTranslateInfoBar::OnTargetLanguageModified(GtkWidget* sender) {
-  int index = GetLanguageComboboxActiveId(GTK_COMBO_BOX(sender));
-  if (index == GetDelegate()->target_language_index())
-    return;
-
-  // See comment in OnOriginalLanguageModified on why we use a task.
-  MessageLoop::current()->PostTask(FROM_HERE, method_factory_.NewRunnableMethod(
-      &AfterTranslateInfoBar::SetTargetLanguage, index));
-}
-
-void AfterTranslateInfoBar::OnRevertPressed(GtkWidget* sender) {
-  GetDelegate()->RevertTranslation();
-}
-
-void AfterTranslateInfoBar::SetOriginalLanguage(int language_index) {
-  GetDelegate()->SetOriginalLanguage(language_index);
-}
-
-void AfterTranslateInfoBar::SetTargetLanguage(int language_index) {
-  GetDelegate()->SetTargetLanguage(language_index);
-}
diff --git a/chrome/browser/gtk/translate/after_translate_infobar_gtk.h b/chrome/browser/gtk/translate/after_translate_infobar_gtk.h
deleted file mode 100644
index 4f49ffd..0000000
--- a/chrome/browser/gtk/translate/after_translate_infobar_gtk.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TRANSLATE_AFTER_TRANSLATE_INFOBAR_GTK_H_
-#define CHROME_BROWSER_GTK_TRANSLATE_AFTER_TRANSLATE_INFOBAR_GTK_H_
-#pragma once
-
-#include "base/task.h"
-#include "chrome/browser/gtk/translate/translate_infobar_base_gtk.h"
-
-class TranslateInfoBarDelegate;
-
-class AfterTranslateInfoBar : public TranslateInfoBarBase {
- public:
-  explicit AfterTranslateInfoBar(TranslateInfoBarDelegate* delegate);
-  virtual ~AfterTranslateInfoBar();
-
-  // Overridden from TranslateInfoBarBase:
-  virtual void Init();
-
- protected:
-  virtual bool ShowOptionsMenuButton() const;
-
- private:
-  CHROMEGTK_CALLBACK_0(AfterTranslateInfoBar, void, OnOriginalLanguageModified);
-  CHROMEGTK_CALLBACK_0(AfterTranslateInfoBar, void, OnTargetLanguageModified);
-  CHROMEGTK_CALLBACK_0(AfterTranslateInfoBar, void, OnRevertPressed);
-
-  // These methods set the original/target language on the
-  // TranslateInfobarDelegate.
-  void SetOriginalLanguage(int language_index);
-  void SetTargetLanguage(int language_index);
-
-  ScopedRunnableMethodFactory<AfterTranslateInfoBar> method_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(AfterTranslateInfoBar);
-};
-
-#endif  // CHROME_BROWSER_GTK_TRANSLATE_AFTER_TRANSLATE_INFOBAR_GTK_H_
diff --git a/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc b/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc
deleted file mode 100644
index 01a94ff..0000000
--- a/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/translate/before_translate_infobar_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "grit/generated_resources.h"
-
-BeforeTranslateInfoBar::BeforeTranslateInfoBar(
-    TranslateInfoBarDelegate* delegate)
-    : TranslateInfoBarBase(delegate) {
-}
-
-BeforeTranslateInfoBar::~BeforeTranslateInfoBar() {
-}
-
-void BeforeTranslateInfoBar::Init() {
-  TranslateInfoBarBase::Init();
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_util::CenterWidgetInHBox(hbox_, hbox, false, 0);
-  size_t offset = 0;
-  string16 text =
-      l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE,
-                                 string16(), &offset);
-
-  gtk_box_pack_start(GTK_BOX(hbox),
-                     CreateLabel(UTF16ToUTF8(text.substr(0, offset))),
-                     FALSE, FALSE, 0);
-  GtkWidget* combobox =
-      CreateLanguageCombobox(GetDelegate()->original_language_index(),
-                             GetDelegate()->target_language_index());
-  g_signal_connect(combobox, "changed",
-                   G_CALLBACK(&OnLanguageModifiedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), combobox, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox),
-                     CreateLabel(UTF16ToUTF8(text.substr(offset))),
-                     FALSE, FALSE, 0);
-
-  GtkWidget* button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_ACCEPT).c_str());
-  g_signal_connect(button, "clicked",G_CALLBACK(&OnAcceptPressedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
-  button = gtk_button_new_with_label(
-      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_DENY).c_str());
-  g_signal_connect(button, "clicked",G_CALLBACK(&OnDenyPressedThunk), this);
-  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
-  TranslateInfoBarDelegate* delegate = GetDelegate();
-  if (delegate->ShouldShowNeverTranslateButton()) {
-    std::string label =
-        l10n_util::GetStringFUTF8(IDS_TRANSLATE_INFOBAR_NEVER_TRANSLATE,
-                                  delegate->GetLanguageDisplayableNameAt(
-                                      delegate->original_language_index()));
-    button = gtk_button_new_with_label(label.c_str());
-    g_signal_connect(button, "clicked",
-                     G_CALLBACK(&OnNeverTranslatePressedThunk), this);
-    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-  }
-
-  if (delegate->ShouldShowAlwaysTranslateButton()) {
-    std::string label =
-        l10n_util::GetStringFUTF8(IDS_TRANSLATE_INFOBAR_ALWAYS_TRANSLATE,
-                                  delegate->GetLanguageDisplayableNameAt(
-                                      delegate->original_language_index()));
-    button = gtk_button_new_with_label(label.c_str());
-    g_signal_connect(button, "clicked",
-                     G_CALLBACK(&OnAlwaysTranslatePressedThunk), this);
-    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-  }
-}
-
-bool BeforeTranslateInfoBar::ShowOptionsMenuButton() const {
-  return true;
-}
-
-void BeforeTranslateInfoBar::OnLanguageModified(GtkWidget* sender) {
-  int index = GetLanguageComboboxActiveId(GTK_COMBO_BOX(sender));
-  if (index == GetDelegate()->original_language_index())
-    return;
-
-  GetDelegate()->SetOriginalLanguage(index);
-}
-
-void BeforeTranslateInfoBar::OnAcceptPressed(GtkWidget* sender) {
-  GetDelegate()->Translate();
-}
-
-void BeforeTranslateInfoBar::OnDenyPressed(GtkWidget* sender) {
-  GetDelegate()->TranslationDeclined();
-  RemoveInfoBar();
-}
-
-void BeforeTranslateInfoBar::OnNeverTranslatePressed(GtkWidget* sender) {
-  GetDelegate()->NeverTranslatePageLanguage();
-}
-
-void BeforeTranslateInfoBar::OnAlwaysTranslatePressed(GtkWidget* sender) {
-  GetDelegate()->AlwaysTranslatePageLanguage();
-}
diff --git a/chrome/browser/gtk/translate/before_translate_infobar_gtk.h b/chrome/browser/gtk/translate/before_translate_infobar_gtk.h
deleted file mode 100644
index e6ff5a9..0000000
--- a/chrome/browser/gtk/translate/before_translate_infobar_gtk.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_GTK_H_
-#define CHROME_BROWSER_GTK_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_GTK_H_
-#pragma once
-
-#include "chrome/browser/gtk/translate/translate_infobar_base_gtk.h"
-
-class TranslateInfoBarDelegate;
-
-class BeforeTranslateInfoBar : public TranslateInfoBarBase {
- public:
-  explicit BeforeTranslateInfoBar(TranslateInfoBarDelegate* delegate);
-  virtual ~BeforeTranslateInfoBar();
-
-  // Overridden from TranslateInfoBarBase:
-  virtual void Init();
-
- protected:
-  virtual bool ShowOptionsMenuButton() const;
-
- private:
-  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnLanguageModified);
-  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnAcceptPressed);
-  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnDenyPressed);
-  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnNeverTranslatePressed);
-  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnAlwaysTranslatePressed);
-
-  DISALLOW_COPY_AND_ASSIGN(BeforeTranslateInfoBar);
-};
-
-#endif  // CHROME_BROWSER_GTK_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_GTK_H_
diff --git a/chrome/browser/gtk/translate/translate_infobar_base_gtk.cc b/chrome/browser/gtk/translate/translate_infobar_base_gtk.cc
deleted file mode 100644
index 3d78de4..0000000
--- a/chrome/browser/gtk/translate/translate_infobar_base_gtk.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/translate/translate_infobar_base_gtk.h"
-
-#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/translate/options_menu_model.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/gtk/translate/after_translate_infobar_gtk.h"
-#include "chrome/browser/gtk/translate/before_translate_infobar_gtk.h"
-#include "chrome/browser/gtk/translate/translate_message_infobar_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/menu_gtk.h"
-#include "gfx/canvas.h"
-#include "grit/generated_resources.h"
-#include "ui/base/animation/slide_animation.h"
-
-namespace {
-
-// To be able to map from language id <-> entry in the combo box, we
-// store the language id in the combo box data model in addition to the
-// displayed name.
-enum {
-  LANGUAGE_COMBO_COLUMN_ID,
-  LANGUAGE_COMBO_COLUMN_NAME,
-  LANGUAGE_COMBO_COLUMN_COUNT
-};
-
-}  // namespace
-
-TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate)
-    : InfoBar(delegate) {
-  TranslateInfoBarDelegate::BackgroundAnimationType animation =
-      delegate->background_animation_type();
-  if (animation != TranslateInfoBarDelegate::NONE) {
-    background_color_animation_.reset(new ui::SlideAnimation(this));
-    background_color_animation_->SetTweenType(ui::Tween::LINEAR);
-    background_color_animation_->SetSlideDuration(500);
-    if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
-      background_color_animation_->Show();
-    } else {
-      DCHECK_EQ(TranslateInfoBarDelegate::ERROR_TO_NORMAL, animation);
-      // Hide() runs the animation in reverse.
-      background_color_animation_->Reset(1.0);
-      background_color_animation_->Hide();
-    }
-  } else {
-    background_error_percent_ = delegate->IsError() ? 1 : 0;
-  }
-}
-
-TranslateInfoBarBase::~TranslateInfoBarBase() {
-}
-
-void TranslateInfoBarBase::Init() {
-  if (!ShowOptionsMenuButton())
-    return;
-
-  // The options button sits outside the translate_box so that it can be end
-  // packed in hbox_.
-  GtkWidget* options_menu_button = BuildOptionsMenuButton();
-  g_signal_connect(options_menu_button, "clicked",
-                   G_CALLBACK(&OnOptionsClickedThunk), this);
-  gtk_widget_show_all(options_menu_button);
-  gtk_util::CenterWidgetInHBox(hbox_, options_menu_button, true, 0);
-}
-
-void TranslateInfoBarBase::GetTopColor(InfoBarDelegate::Type type,
-                                       double* r, double* g, double *b) {
-  if (background_error_percent_ <= 0) {
-    InfoBar::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b);
-  } else if (background_error_percent_ >= 1) {
-    InfoBar::GetTopColor(InfoBarDelegate::WARNING_TYPE, r, g, b);
-  } else {
-    double normal_r, normal_g, normal_b;
-    InfoBar::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE,
-                         &normal_r, &normal_g, &normal_b);
-
-    double error_r, error_g, error_b;
-    InfoBar::GetTopColor(InfoBarDelegate::WARNING_TYPE,
-                         &error_r, &error_g, &error_b);
-
-    double offset_r = error_r - normal_r;
-    double offset_g = error_g - normal_g;
-    double offset_b = error_b - normal_b;
-
-    *r = normal_r + (background_error_percent_ * offset_r);
-    *g = normal_g + (background_error_percent_ * offset_g);
-    *b = normal_b + (background_error_percent_ * offset_b);
-  }
-}
-
-void TranslateInfoBarBase::GetBottomColor(InfoBarDelegate::Type type,
-                                          double* r, double* g, double *b) {
-  if (background_error_percent_ <= 0) {
-    InfoBar::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b);
-  } else if (background_error_percent_ >= 1) {
-    InfoBar::GetBottomColor(InfoBarDelegate::WARNING_TYPE, r, g, b);
-  } else {
-    double normal_r, normal_g, normal_b;
-    InfoBar::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE,
-                            &normal_r, &normal_g, &normal_b);
-
-    double error_r, error_g, error_b;
-    InfoBar::GetBottomColor(InfoBarDelegate::WARNING_TYPE,
-                            &error_r, &error_g, &error_b);
-
-    double offset_r = error_r - normal_r;
-    double offset_g = error_g - normal_g;
-    double offset_b = error_b - normal_b;
-
-    *r = normal_r + (background_error_percent_ * offset_r);
-    *g = normal_g + (background_error_percent_ * offset_g);
-    *b = normal_b + (background_error_percent_ * offset_b);
-  }
-}
-
-void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
-  DCHECK(animation == background_color_animation_.get());
-  background_error_percent_ = animation->GetCurrentValue();
-  // Queue the info bar widget for redisplay so it repaints its background.
-  gtk_widget_queue_draw(widget());
-}
-
-bool TranslateInfoBarBase::ShowOptionsMenuButton() const {
-  return false;
-}
-
-GtkWidget* TranslateInfoBarBase::CreateLabel(const std::string& text) {
-  GtkWidget* label = gtk_label_new(text.c_str());
-  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
-  return label;
-}
-
-GtkWidget* TranslateInfoBarBase::CreateLanguageCombobox(int selected_language,
-                                                        int exclude_language) {
-  GtkListStore* model = gtk_list_store_new(LANGUAGE_COMBO_COLUMN_COUNT,
-                                           G_TYPE_INT, G_TYPE_STRING);
-  bool set_selection = false;
-  GtkTreeIter selected_iter;
-  TranslateInfoBarDelegate* delegate = GetDelegate();
-  for (int i = 0; i < delegate->GetLanguageCount(); ++i) {
-    if (i == exclude_language)
-      continue;
-    GtkTreeIter tree_iter;
-    const string16& name = delegate->GetLanguageDisplayableNameAt(i);
-
-    gtk_list_store_append(model, &tree_iter);
-    gtk_list_store_set(model, &tree_iter,
-                       LANGUAGE_COMBO_COLUMN_ID, i,
-                       LANGUAGE_COMBO_COLUMN_NAME, UTF16ToUTF8(name).c_str(),
-                       -1);
-    if (i == selected_language) {
-      selected_iter = tree_iter;
-      set_selection = true;
-    }
-  }
-
-  GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
-  if (set_selection)
-    gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combobox), &selected_iter);
-  g_object_unref(model);
-  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
-  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
-  gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer,
-                                 "text", LANGUAGE_COMBO_COLUMN_NAME,
-                                 NULL);
-  return combobox;
-}
-
-// static
-int TranslateInfoBarBase::GetLanguageComboboxActiveId(GtkComboBox* combo) {
-  GtkTreeIter iter;
-  if (!gtk_combo_box_get_active_iter(combo, &iter))
-    return 0;
-
-  gint id = 0;
-  gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter,
-                     LANGUAGE_COMBO_COLUMN_ID, &id,
-                     -1);
-  return id;
-}
-
-TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() const {
-  return static_cast<TranslateInfoBarDelegate*>(delegate());
-}
-
-// static
-GtkWidget* TranslateInfoBarBase::BuildOptionsMenuButton() {
-  GtkWidget* button = gtk_button_new();
-  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
-  if (former_child)
-    gtk_container_remove(GTK_CONTAINER(button), former_child);
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
-
-  GtkWidget* label = gtk_label_new(
-      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS).c_str());
-  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
-  GtkWidget* arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
-  gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);
-
-  gtk_container_add(GTK_CONTAINER(button), hbox);
-
-  return button;
-}
-
-void TranslateInfoBarBase::OnOptionsClicked(GtkWidget* sender) {
-  if (!options_menu_model_.get()) {
-    options_menu_model_.reset(new OptionsMenuModel(GetDelegate()));
-    options_menu_menu_.reset(new MenuGtk(NULL, options_menu_model_.get()));
-  }
-  options_menu_menu_->Popup(sender, 1, gtk_get_current_event_time());
-}
-
-// TranslateInfoBarDelegate specific method:
-InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
-  TranslateInfoBarBase* infobar = NULL;
-  switch (type_) {
-    case BEFORE_TRANSLATE:
-      infobar = new BeforeTranslateInfoBar(this);
-      break;
-    case AFTER_TRANSLATE:
-      infobar = new AfterTranslateInfoBar(this);
-      break;
-    case TRANSLATING:
-    case TRANSLATION_ERROR:
-      infobar = new TranslateMessageInfoBar(this);
-      break;
-    default:
-      NOTREACHED();
-  }
-  infobar->Init();
-  // Set |infobar_view_| so that the model can notify the infobar when it
-  // changes.
-  infobar_view_ = infobar;
-  return infobar;
-}
diff --git a/chrome/browser/gtk/translate/translate_infobar_base_gtk.h b/chrome/browser/gtk/translate/translate_infobar_base_gtk.h
deleted file mode 100644
index 6adf98a..0000000
--- a/chrome/browser/gtk/translate/translate_infobar_base_gtk.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_
-#define CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_
-#pragma once
-
-#include "chrome/browser/translate/translate_infobar_view.h"
-#include "chrome/browser/gtk/infobar_gtk.h"
-#include "ui/base/animation/animation_delegate.h"
-
-class MenuGtk;
-class OptionsMenuModel;
-class TranslateInfoBarDelegate;
-
-// This class contains some of the base functionality that translate infobars
-// use.
-class TranslateInfoBarBase : public TranslateInfoBarView,
-                             public InfoBar,
-                             public ui::AnimationDelegate {
- public:
-  explicit TranslateInfoBarBase(TranslateInfoBarDelegate* delegate);
-  virtual ~TranslateInfoBarBase();
-
-  // Initializes the infobar widgets. Should be called after the object has been
-  // created.
-  virtual void Init();
-
-  // Overridden from InfoBar:
-  virtual void GetTopColor(InfoBarDelegate::Type type,
-                           double* r, double* g, double *b);
-  virtual void GetBottomColor(InfoBarDelegate::Type type,
-                              double* r, double* g, double *b);
-
-  // Overridden from TranslateInfoBarView:
-  virtual void OriginalLanguageChanged() {}
-  virtual void TargetLanguageChanged() {}
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation);
-
- protected:
-  // Sub-classes that want to have the options menu button showing sould
-  // override and return true.
-  virtual bool ShowOptionsMenuButton() const;
-
-  // Creates a label with the appropriate font and color for the translate
-  // infobars.
-  GtkWidget* CreateLabel(const std::string& text);
-
-  // Creates a combobox that displays the languages currently available.
-  // |selected_language| is the language index (as used in the
-  // TranslateInfoDelegate) that should be selected initially.
-  // |exclude_language| is the language index of the language that should not be
-  // included in the list (-1 means no language excluded).
-  GtkWidget* CreateLanguageCombobox(int selected_language,
-                                    int exclude_language);
-
-  // Given an above-constructed combobox, returns the currently selected
-  // language id.
-  static int GetLanguageComboboxActiveId(GtkComboBox* combo);
-
-  // Convenience to retrieve the TranslateInfoBarDelegate for this infobar.
-  TranslateInfoBarDelegate* GetDelegate() const;
-
- private:
-  // Builds a button with an arrow in it to emulate the menu-button style from
-  // the windows version.
-  static GtkWidget* BuildOptionsMenuButton();
-
-  // The menu displayed when the Options button is pressed.
-  scoped_ptr<OptionsMenuModel> options_menu_model_;
-  scoped_ptr<MenuGtk> options_menu_menu_;
-
-  CHROMEGTK_CALLBACK_0(TranslateInfoBarBase, void, OnOptionsClicked);
-
-  // A percentage to average the normal page action background with the error
-  // background. When 0, the infobar background should be pure PAGE_ACTION_TYPE.
-  // When 1, the infobar background should be pure WARNING_TYPE.
-  double background_error_percent_;
-
-  // Changes the color of the background from normal to error color and back.
-  scoped_ptr<ui::SlideAnimation> background_color_animation_;
-
-  DISALLOW_COPY_AND_ASSIGN(TranslateInfoBarBase);
-};
-
-#endif  // CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_
diff --git a/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc b/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc
deleted file mode 100644
index 0f61bca..0000000
--- a/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/translate/translate_message_infobar_gtk.h"
-
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-
-TranslateMessageInfoBar::TranslateMessageInfoBar(
-    TranslateInfoBarDelegate* delegate)
-    : TranslateInfoBarBase(delegate) {
-}
-
-TranslateMessageInfoBar::~TranslateMessageInfoBar() {
-}
-
-void TranslateMessageInfoBar::Init() {
-  TranslateInfoBarBase::Init();
-
-  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
-  gtk_util::CenterWidgetInHBox(hbox_, hbox, false, 0);
-
-  std::string text = UTF16ToUTF8(GetDelegate()->GetMessageInfoBarText());
-  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(text.c_str()), FALSE, FALSE, 0);
-  string16 button_text = GetDelegate()->GetMessageInfoBarButtonText();
-  if (!button_text.empty()) {
-    GtkWidget* button =
-        gtk_button_new_with_label(UTF16ToUTF8(button_text).c_str());
-    g_signal_connect(button, "clicked",G_CALLBACK(&OnButtonPressedThunk), this);
-    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-  }
-}
-
-void TranslateMessageInfoBar::OnButtonPressed(GtkWidget* sender) {
-  GetDelegate()->MessageInfoBarButtonPressed();
-}
diff --git a/chrome/browser/gtk/translate/translate_message_infobar_gtk.h b/chrome/browser/gtk/translate/translate_message_infobar_gtk.h
deleted file mode 100644
index 74db7e3..0000000
--- a/chrome/browser/gtk/translate/translate_message_infobar_gtk.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_MESSAGE_INFOBAR_GTK_H_
-#define CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_MESSAGE_INFOBAR_GTK_H_
-#pragma once
-
-#include "chrome/browser/gtk/translate/translate_infobar_base_gtk.h"
-
-class TranslateInfoBarDelegate;
-
-class TranslateMessageInfoBar : public TranslateInfoBarBase {
- public:
-  explicit TranslateMessageInfoBar(TranslateInfoBarDelegate* delegate);
-  virtual ~TranslateMessageInfoBar();
-
-  // Overridden from TranslateInfoBarBase:
-  virtual void Init();
-
- private:
-  CHROMEGTK_CALLBACK_0(TranslateMessageInfoBar, void, OnButtonPressed);
-
-  DISALLOW_COPY_AND_ASSIGN(TranslateMessageInfoBar);
-};
-
-#endif  // CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_MESSAGE_INFOBAR_GTK_H_
diff --git a/chrome/browser/gtk/update_recommended_dialog.cc b/chrome/browser/gtk/update_recommended_dialog.cc
deleted file mode 100644
index d9b4316..0000000
--- a/chrome/browser/gtk/update_recommended_dialog.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/update_recommended_dialog.h"
-
-#include <gtk/gtk.h>
-
-#include "app/l10n_util.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/pref_names.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-static const int kMessageWidth = 400;
-
-// static
-void UpdateRecommendedDialog::Show(GtkWindow* parent) {
-  new UpdateRecommendedDialog(parent);
-}
-
-UpdateRecommendedDialog::UpdateRecommendedDialog(GtkWindow* parent) {
-  dialog_ = gtk_dialog_new_with_buttons(
-      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str(),
-      parent,
-      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
-      l10n_util::GetStringUTF8(IDS_NOT_NOW).c_str(),
-      GTK_RESPONSE_REJECT,
-      l10n_util::GetStringUTF8(IDS_RESTART_AND_UPDATE).c_str(),
-      GTK_RESPONSE_ACCEPT,
-      NULL);
-
-  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
-
-  // Add the message text.
-  std::string text(
-      l10n_util::GetStringFUTF8(IDS_UPDATE_RECOMMENDED,
-                                l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
-  GtkWidget* label = gtk_label_new(text.c_str());
-  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
-  gtk_widget_set_size_request(label, kMessageWidth, -1);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), label,
-                     FALSE, FALSE, 0);
-
-  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
-
-  gtk_widget_show_all(dialog_);
-}
-
-UpdateRecommendedDialog::~UpdateRecommendedDialog() {
-}
-
-void UpdateRecommendedDialog::OnResponse(GtkWidget* sender, gint response_id) {
-  gtk_widget_destroy(dialog_);
-
-  if (response_id == GTK_RESPONSE_ACCEPT) {
-    // Set the flag to restore the last session on shutdown.
-    PrefService* pref_service = g_browser_process->local_state();
-    pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
-
-    BrowserList::CloseAllBrowsersAndExit();
-  }
-
-  delete this;
-}
diff --git a/chrome/browser/gtk/update_recommended_dialog.h b/chrome/browser/gtk/update_recommended_dialog.h
deleted file mode 100644
index 1105584..0000000
--- a/chrome/browser/gtk/update_recommended_dialog.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_UPDATE_RECOMMENDED_DIALOG_H_
-#define CHROME_BROWSER_GTK_UPDATE_RECOMMENDED_DIALOG_H_
-#pragma once
-
-#include "app/gtk_integers.h"
-#include "app/gtk_signal.h"
-#include "base/basictypes.h"
-
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkWindow GtkWindow;
-
-class UpdateRecommendedDialog {
- public:
-  static void Show(GtkWindow* parent);
-
- private:
-  CHROMEGTK_CALLBACK_1(UpdateRecommendedDialog, void, OnResponse, gint);
-
-  explicit UpdateRecommendedDialog(GtkWindow* parent);
-  ~UpdateRecommendedDialog();
-
-  GtkWidget* dialog_;
-
-  DISALLOW_COPY_AND_ASSIGN(UpdateRecommendedDialog);
-};
-
-#endif  // CHROME_BROWSER_GTK_UPDATE_RECOMMENDED_DIALOG_H_
diff --git a/chrome/browser/gtk/view_id_util.cc b/chrome/browser/gtk/view_id_util.cc
deleted file mode 100644
index 2b8e396..0000000
--- a/chrome/browser/gtk/view_id_util.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/view_id_util.h"
-
-#include <stdint.h>
-#include <string>
-
-#include <gtk/gtk.h>
-
-#include "base/logging.h"
-
-namespace {
-
-const char kViewIDString[] = "__VIEW_ID__";
-const char kViewIDOverrideString[] = "__VIEW_ID_OVERRIDE__";
-
-struct ViewIDSearchStruct {
-  ViewID id;  // Input: the ID we are searching for.
-  GtkWidget* widget;  // Output: the found widget, or NULL.
-};
-
-// Recursively search for the given view ID among the children of |widget|.
-void SearchForWidgetWithViewID(GtkWidget* widget, gpointer data) {
-  ViewIDSearchStruct* search_struct =
-      reinterpret_cast<ViewIDSearchStruct*>(data);
-
-  // The widget has already been found; abort the search.
-  if (search_struct->widget)
-    return;
-
-  // Check if the widget defines its own ID function.
-  ViewIDUtil::Delegate* delegate = reinterpret_cast<ViewIDUtil::Delegate*>(
-      g_object_get_data(G_OBJECT(widget), kViewIDOverrideString));
-  if (delegate) {
-    search_struct->widget = delegate->GetWidgetForViewID(search_struct->id);
-    // If there was success, return.
-    if (search_struct->widget)
-      return;
-  }
-
-  // Otherwise check the g_object data.
-  int widget_id =
-      reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(widget),
-                                 kViewIDString));
-  if (search_struct->id == widget_id) {
-    // Success; set |widget| and return.
-    search_struct->widget = widget;
-    return;
-  }
-
-  // Recurse.
-  if (GTK_IS_CONTAINER(widget)) {
-    gtk_container_foreach(GTK_CONTAINER(widget),
-                          SearchForWidgetWithViewID, data);
-  }
-}
-
-const char* GetNameFromID(ViewID id) {
-  switch (id) {
-    case VIEW_ID_TAB_STRIP:
-      return "chrome-tab-strip";
-
-    case VIEW_ID_TOOLBAR:
-      return "chrome-toolbar";
-
-    case VIEW_ID_BACK_BUTTON:
-      return "chrome-toolbar-back-button";
-
-    case VIEW_ID_FORWARD_BUTTON:
-      return "chrome-toolbar-forward-button";
-
-    case VIEW_ID_RELOAD_BUTTON:
-      return "chrome-toolbar-reload-button";
-
-    case VIEW_ID_HOME_BUTTON:
-      return "chrome-toolbar-home-button";
-
-    case VIEW_ID_STAR_BUTTON:
-      return "chrome-toolbar-star-button";
-
-    case VIEW_ID_LOCATION_BAR:
-      return "chrome-location-bar";
-
-    case VIEW_ID_BROWSER_ACTION_TOOLBAR:
-      return "chrome-toolbar-browser-actions-container";
-
-    case VIEW_ID_APP_MENU:
-      return "chrome-app-menu";
-
-    case VIEW_ID_AUTOCOMPLETE:
-      return "chrome-autocomplete-edit";
-
-    case VIEW_ID_BOOKMARK_BAR:
-      return "chrome-bookmark-bar";
-
-    case VIEW_ID_OTHER_BOOKMARKS:
-      return "chrome-bookmark-bar-other-bookmarks";
-
-    case VIEW_ID_FIND_IN_PAGE_TEXT_FIELD:
-      return "chrome-find-in-page-entry";
-
-    case VIEW_ID_FIND_IN_PAGE:
-      return "chrome-find-in-page";
-
-    case VIEW_ID_DEV_TOOLS_DOCKED:
-      return "chrome-dev-tools-docked";
-
-    // These are never hit because the tab container uses the delegate to
-    // set its ID.
-    case VIEW_ID_TAB_CONTAINER:
-    case VIEW_ID_TAB_CONTAINER_FOCUS_VIEW:
-    default:
-      NOTREACHED() << "If you added a new VIEW_ID, please provide "
-                      "a name for the widget.";
-      return NULL;
-  }
-}
-
-}  // namespace
-
-void ViewIDUtil::SetID(GtkWidget* widget, ViewID id) {
-  const char* name = GetNameFromID(id);
-  if (name)
-    gtk_widget_set_name(widget, name);
-  g_object_set_data(G_OBJECT(widget), kViewIDString,
-                    reinterpret_cast<void*>(id));
-}
-
-GtkWidget* ViewIDUtil::GetWidget(GtkWidget* root, ViewID id) {
-  ViewIDSearchStruct search_struct = { id, NULL };
-  SearchForWidgetWithViewID(root, &search_struct);
-  return search_struct.widget;
-}
-
-void ViewIDUtil::SetDelegateForWidget(GtkWidget* widget, Delegate* delegate) {
-  g_object_set_data(G_OBJECT(widget), kViewIDOverrideString, delegate);
-}
diff --git a/chrome/browser/gtk/view_id_util.h b/chrome/browser/gtk/view_id_util.h
deleted file mode 100644
index 0be817e..0000000
--- a/chrome/browser/gtk/view_id_util.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GTK_VIEW_ID_UTIL_H_
-#define CHROME_BROWSER_GTK_VIEW_ID_UTIL_H_
-#pragma once
-
-#include "chrome/browser/ui/view_ids.h"
-
-typedef struct _GtkWidget GtkWidget;
-
-class ViewIDUtil {
- public:
-  // Use this delegate to override default view id searches.
-  class Delegate {
-   public:
-    virtual GtkWidget* GetWidgetForViewID(ViewID id) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  // If you set the ID via this function, it will also set the name of your
-  // widget to a human-readable value for debugging.
-  static void SetID(GtkWidget* widget, ViewID id);
-
-  static GtkWidget* GetWidget(GtkWidget* root, ViewID id);
-
-  static void SetDelegateForWidget(GtkWidget* widget, Delegate* delegate);
-};
-
-#endif  // CHROME_BROWSER_GTK_VIEW_ID_UTIL_H_
diff --git a/chrome/browser/gtk/view_id_util_browsertest.cc b/chrome/browser/gtk/view_id_util_browsertest.cc
deleted file mode 100644
index 62ab99c..0000000
--- a/chrome/browser/gtk/view_id_util_browsertest.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtk/gtk.h>
-
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/gtk/view_id_util.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/in_process_browser_test.h"
-
-class ViewIDTest : public InProcessBrowserTest {
- public:
-  ViewIDTest() : root_window_(NULL) {}
-
-  void CheckViewID(ViewID id, bool should_have) {
-    if (!root_window_)
-      root_window_ = GTK_WIDGET(browser()->window()->GetNativeHandle());
-
-    ASSERT_TRUE(root_window_);
-    EXPECT_EQ(should_have, !!ViewIDUtil::GetWidget(root_window_, id))
-        << " Failed id=" << id;
-  }
-
- private:
-  GtkWidget* root_window_;
-};
-
-IN_PROC_BROWSER_TEST_F(ViewIDTest, Basic) {
-  // Make sure FindBar is created to test
-  // VIEW_ID_FIND_IN_PAGE_TEXT_FIELD and VIEW_ID_FIND_IN_PAGE.
-  browser()->ShowFindBar();
-
-  for (int i = VIEW_ID_TOOLBAR; i < VIEW_ID_PREDEFINED_COUNT; ++i) {
-    // The following ids are used only in views implementation.
-    if (i == VIEW_ID_CONTENTS_SPLIT ||
-        i == VIEW_ID_INFO_BAR_CONTAINER ||
-        i == VIEW_ID_DOWNLOAD_SHELF ||
-        i == VIEW_ID_BOOKMARK_BAR_ELEMENT ||
-        i == VIEW_ID_TAB ||
-        i == VIEW_ID_SIDE_BAR_CONTAINER ||
-        i == VIEW_ID_SIDE_BAR_SPLIT ||
-        i == VIEW_ID_FEEDBACK_BUTTON) {
-      continue;
-    }
-
-    CheckViewID(static_cast<ViewID>(i), true);
-  }
-
-  CheckViewID(VIEW_ID_PREDEFINED_COUNT, false);
-}
-
-IN_PROC_BROWSER_TEST_F(ViewIDTest, Delegate) {
-  CheckViewID(VIEW_ID_TAB_0, true);
-  CheckViewID(VIEW_ID_TAB_1, false);
-
-  browser()->OpenURL(GURL(chrome::kAboutBlankURL), GURL(),
-                     NEW_BACKGROUND_TAB, PageTransition::TYPED);
-
-  CheckViewID(VIEW_ID_TAB_0, true);
-  CheckViewID(VIEW_ID_TAB_1, true);
-}
diff --git a/chrome/browser/hang_monitor/hung_plugin_action.cc b/chrome/browser/hang_monitor/hung_plugin_action.cc
index 77062b2..b53914d 100644
--- a/chrome/browser/hang_monitor/hung_plugin_action.cc
+++ b/chrome/browser/hang_monitor/hung_plugin_action.cc
@@ -6,11 +6,11 @@
 
 #include "chrome/browser/hang_monitor/hung_plugin_action.h"
 
-#include "app/l10n_util.h"
-#include "app/win/hwnd_util.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/common/logging_chrome.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/win/hwnd_util.h"
 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
 
 HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) {
@@ -132,7 +132,7 @@
 
 // static
 BOOL CALLBACK HungPluginAction::DismissMessageBox(HWND window, LPARAM ignore) {
-  string16 class_name = app::win::GetClassName(window);
+  string16 class_name = ui::GetClassName(window);
   // #32770 is the dialog window class which is the window class of
   // the message box being displayed.
   if (class_name == L"#32770") {
diff --git a/chrome/browser/hang_monitor/hung_window_detector.cc b/chrome/browser/hang_monitor/hung_window_detector.cc
index a9bdead..ea864be 100644
--- a/chrome/browser/hang_monitor/hung_window_detector.cc
+++ b/chrome/browser/hang_monitor/hung_window_detector.cc
@@ -48,7 +48,7 @@
 
 void HungWindowDetector::OnTick() {
   do {
-    AutoLock lock(hang_detection_lock_);
+    base::AutoLock lock(hang_detection_lock_);
     // If we already are checking for hung windows on another thread,
     // don't do this again.
     if (enumerating_) {
diff --git a/chrome/browser/hang_monitor/hung_window_detector.h b/chrome/browser/hang_monitor/hung_window_detector.h
index 0e48739..50ea31f 100644
--- a/chrome/browser/hang_monitor/hung_window_detector.h
+++ b/chrome/browser/hang_monitor/hung_window_detector.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_HANG_MONITOR_HUNG_WINDOW_DETECTOR_H__
 #pragma once
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "chrome/common/worker_thread_ticker.h"
 
 // This class provides the following functionality:
@@ -81,7 +81,7 @@
 
   // How long do we wait before we consider a window hung (in ms)
   int message_response_timeout_;
-  Lock hang_detection_lock_;
+  base::Lock hang_detection_lock_;
   // Indicates if this object is currently enumerating hung windows
   bool enumerating_;
 
diff --git a/chrome/browser/history/download_create_info.h b/chrome/browser/history/download_create_info.h
index 49ac635..0814350 100644
--- a/chrome/browser/history/download_create_info.h
+++ b/chrome/browser/history/download_create_info.h
@@ -36,7 +36,11 @@
 
   // DownloadItem fields
   FilePath path;
+  // The URL from which we are downloading. This is the final URL after any
+  // redirection by the server for |original_url_|.
   GURL url;
+  // The original URL before any redirection by the server for this URL.
+  GURL original_url;
   GURL referrer_url;
   FilePath suggested_path;
   // A number that should be added to the suggested path to make it unique.
diff --git a/chrome/browser/history/expire_history_backend.cc b/chrome/browser/history/expire_history_backend.cc
index 8cafc82..62aa7e5 100644
--- a/chrome/browser/history/expire_history_backend.cc
+++ b/chrome/browser/history/expire_history_backend.cc
@@ -557,7 +557,8 @@
     cur_visit.url_id = main_id_to_archived_id[cur_visit.url_id];
     cur_visit.referring_visit = 0;
     VisitSourceMap::iterator iter = visit_sources.find(visits[i].visit_id);
-    archived_db_->AddVisit(&cur_visit,
+    archived_db_->AddVisit(
+        &cur_visit,
         iter == visit_sources.end() ? SOURCE_BROWSED : iter->second);
     // Ignore failures, we will delete it from the main DB no matter what.
   }
diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc
index 161a086..d71535b 100644
--- a/chrome/browser/history/expire_history_backend_unittest.cc
+++ b/chrome/browser/history/expire_history_backend_unittest.cc
@@ -26,9 +26,9 @@
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/test/testing_profile.h"
 #include "chrome/tools/profiles/thumbnail-inl.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 using base::Time;
 using base::TimeDelta;
diff --git a/chrome/browser/history/history.cc b/chrome/browser/history/history.cc
index 0736fc2..09434e1 100644
--- a/chrome/browser/history/history.cc
+++ b/chrome/browser/history/history.cc
@@ -791,7 +791,7 @@
   NotificationService::current()->Notify(NotificationType::HISTORY_LOADED,
                                          Source<Profile>(profile_),
                                          Details<HistoryService>(this));
-  if (thread_ && profile_ && history::TopSites::IsEnabled()) {
+  if (thread_ && profile_) {
     // We don't want to force creation of TopSites.
     history::TopSites* ts = profile_->GetTopSitesWithoutCreating();
     if (ts)
@@ -801,7 +801,7 @@
 
 void HistoryService::StartTopSitesMigration() {
   needs_top_sites_migration_ = true;
-  if (thread_ && profile_ && history::TopSites::IsEnabled()) {
+  if (thread_ && profile_) {
     // We don't want to force creation of TopSites.
     history::TopSites* ts = profile_->GetTopSitesWithoutCreating();
     if (ts)
diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h
index 3e604e6..6afe318 100644
--- a/chrome/browser/history/history.h
+++ b/chrome/browser/history/history.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_HISTORY_HISTORY_H_
 #pragma once
 
+#include <set>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/favicon_service.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/search_engines/template_url_id.h"
+#include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/page_transition_types.h"
 #include "chrome/common/ref_counted_util.h"
@@ -327,8 +329,8 @@
   typedef Callback4<Handle,
                     bool,        // Were we able to determine the # of visits?
                     int,         // Number of visits.
-                    base::Time>::Type // Time of first visit. Only first bool is
-                                 // true and int is > 0.
+                    base::Time>::Type  // Time of first visit. Only first bool
+                                       // is true and int is > 0.
       GetVisitCountToHostCallback;
 
   // Requests the number of visits to all urls on the scheme/host/post
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index cd0a40b..50f47d5 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -4,7 +4,10 @@
 
 #include "chrome/browser/history/history_backend.h"
 
+#include <list>
+#include <map>
 #include <set>
+#include <vector>
 
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
@@ -24,7 +27,6 @@
 #include "chrome/browser/history/page_usage_data.h"
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
@@ -581,7 +583,7 @@
 
   // Thumbnail database.
   thumbnail_db_.reset(new ThumbnailDatabase());
-  if (history::TopSites::IsEnabled() && !db_->GetNeedsThumbnailMigration()) {
+  if (!db_->GetNeedsThumbnailMigration()) {
     // No convertion needed - use new filename right away.
     thumbnail_name = GetFaviconsFileName();
   }
@@ -596,7 +598,7 @@
     thumbnail_db_.reset();
   }
 
-  if (history::TopSites::IsEnabled() && db_->GetNeedsThumbnailMigration()) {
+  if (db_->GetNeedsThumbnailMigration()) {
     VLOG(1) << "Starting TopSites migration";
     delegate_->StartTopSitesMigration();
   }
@@ -719,6 +721,9 @@
     // Re-enable this.
     // GetMostRecentRedirectsTo(url, &details->redirects);
     BroadcastNotifications(NotificationType::HISTORY_URL_VISITED, details);
+  } else {
+    VLOG(0) << "Failed to build visit insert statement:  "
+            << "url_id = " << url_id;
   }
 
   return std::make_pair(url_id, visit_id);
@@ -1201,10 +1206,18 @@
     const VisitRow visit = visits[i];
 
     // Add a result row for this visit, get the URL info from the DB.
-    if (!url_db->GetURLRow(visit.url_id, &url_result))
+    if (!url_db->GetURLRow(visit.url_id, &url_result)) {
+      VLOG(0) << "Failed to get id " << visit.url_id
+              << " from history.urls.";
       continue;  // DB out of sync and URL doesn't exist, try to recover.
-    if (!url_result.url().is_valid())
+    }
+
+    if (!url_result.url().is_valid()) {
+      VLOG(0) << "Got invalid URL from history.urls with id "
+              << visit.url_id << ":  "
+              << url_result.url().possibly_invalid_spec();
       continue;  // Don't report invalid URLs in case of corruption.
+    }
 
     // The archived database may be out of sync with respect to starring,
     // titles, last visit date, etc. Therefore, we query the main DB if the
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc
index a3b2c86..c930558 100644
--- a/chrome/browser/history/history_backend_unittest.cc
+++ b/chrome/browser/history/history_backend_unittest.cc
@@ -18,17 +18,15 @@
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/in_memory_history_backend.h"
 #include "chrome/browser/history/in_memory_database.h"
-#include "chrome/browser/history/top_sites.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/tools/profiles/thumbnail-inl.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 using base::Time;
 
@@ -416,45 +414,6 @@
       backend_->thumbnail_db_->GetFavIconIDForFavIconURL(favicon_url1));
 }
 
-TEST_F(HistoryBackendTest, GetPageThumbnailAfterRedirects) {
-  ASSERT_TRUE(backend_.get());
-  if (history::TopSites::IsEnabled())
-    return;
-
-  const char* base_url = "http://mail";
-  const char* thumbnail_url = "http://mail.google.com";
-  const char* first_chain[] = {
-    base_url,
-    thumbnail_url,
-    NULL
-  };
-  AddRedirectChain(first_chain, 0);
-
-  // Add a thumbnail for the end of that redirect chain.
-  scoped_ptr<SkBitmap> thumbnail(
-      gfx::JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
-  backend_->SetPageThumbnail(GURL(thumbnail_url), *thumbnail,
-                             ThumbnailScore(0.25, true, true));
-
-  // Write a second URL chain so that if you were to simply check what
-  // "http://mail" redirects to, you wouldn't see the URL that has
-  // contains the thumbnail.
-  const char* second_chain[] = {
-    base_url,
-    "http://mail.google.com/somewhere/else",
-    NULL
-  };
-  AddRedirectChain(second_chain, 1);
-
-  // Now try to get the thumbnail for the base url. It shouldn't be
-  // distracted by the second chain and should return the thumbnail
-  // attached to thumbnail_url_.
-  scoped_refptr<RefCountedBytes> data;
-  backend_->GetPageThumbnailDirectly(GURL(base_url), &data);
-
-  EXPECT_TRUE(data.get());
-}
-
 // Tests a handful of assertions for a navigation with a type of
 // KEYWORD_GENERATED.
 TEST_F(HistoryBackendTest, KeywordGenerated) {
@@ -617,15 +576,6 @@
   ASSERT_EQ(1U, visits.size());
 }
 
-TEST_F(HistoryBackendTest, DeleteThumbnailsDatabaseTest) {
-  if (history::TopSites::IsEnabled())
-    return;
-
-  EXPECT_TRUE(backend_->thumbnail_db_->NeedsMigrationToTopSites());
-  backend_->delegate_->StartTopSitesMigration();
-  EXPECT_FALSE(backend_->thumbnail_db_->NeedsMigrationToTopSites());
-}
-
 TEST_F(HistoryBackendTest, AddPageVisitSource) {
   ASSERT_TRUE(backend_.get());
 
diff --git a/chrome/browser/history/history_browsertest.cc b/chrome/browser/history/history_browsertest.cc
index 7075b16..d5dc39b 100644
--- a/chrome/browser/history/history_browsertest.cc
+++ b/chrome/browser/history/history_browsertest.cc
@@ -17,6 +17,14 @@
 
 namespace {
 
+// Helper to debug intermittent test hangs/timeouts.
+// TODO(phajdan.jr): remove when http://crbug.com/57994 is fixed.
+void Checkpoint(const char* message, const base::TimeTicks& start_time) {
+  LOG(INFO) << message << " : "
+            << (base::TimeTicks::Now() - start_time).InMilliseconds()
+            << " ms" << std::flush;
+}
+
 // Note: WaitableEvent is not used for synchronization between the main thread
 // and history backend thread because the history subsystem posts tasks back
 // to the main thread. Had we tried to Signal an event in such a task
@@ -141,49 +149,50 @@
   }
 }
 
-// Times out on Vista only.  http://crbug.com/57994
-#if defined(OS_WIN)
-#define MAYBE_SavingHistoryDisabled DISABLED_SavingHistoryDisabled
-#else
-#define MAYBE_SavingHistoryDisabled SavingHistoryDisabled
-#endif
-
 // Test that disabling saving browser history really works.
-IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MAYBE_SavingHistoryDisabled) {
+// TODO(phajdan.jr): remove debug code when http://crbug.com/57994 is fixed.
+IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabled) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
+
   GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
 
   EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
   EXPECT_FALSE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));
 
+  Checkpoint("Before waiting for history to load", start_time);
   ui_test_utils::WaitForHistoryToLoad(browser());
+  Checkpoint("After waiting for history to load", start_time);
   ExpectEmptyHistory();
+  Checkpoint("After checking history", start_time);
 
   ui_test_utils::NavigateToURL(browser(), GetTestUrl());
+  Checkpoint("After NavigateToURL", start_time);
   WaitForHistoryBackendToRun();
+  Checkpoint("After waiting for history backend to run", start_time);
   ExpectEmptyHistory();
+  Checkpoint("After second check", start_time);
 }
 
-// Times out on Vista only.  http://crbug.com/57994
-#if defined(OS_WIN)
-#define MAYBE_SavingHistoryEnabledThenDisabled \
-    DISABLED_SavingHistoryEnabledThenDisabled
-#else
-#define MAYBE_SavingHistoryEnabledThenDisabled SavingHistoryEnabledThenDisabled
-#endif
-
 // Test that changing the pref takes effect immediately
 // when the browser is running.
-IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
-    MAYBE_SavingHistoryEnabledThenDisabled) {
+// TODO(phajdan.jr): remove debug code when http://crbug.com/57994 is fixed.
+IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabledThenDisabled) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
+
   EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));
 
+  Checkpoint("Before waiting for history to load", start_time);
   ui_test_utils::WaitForHistoryToLoad(browser());
+  Checkpoint("After waiting for history to load", start_time);
 
   ui_test_utils::NavigateToURL(browser(), GetTestUrl());
+  Checkpoint("After first NavigateToURL", start_time);
   WaitForHistoryBackendToRun();
+  Checkpoint("After waiting for history backend to run", start_time);
 
   {
     std::vector<GURL> urls(GetHistoryContents());
+    Checkpoint("After first GetHistoryContents", start_time);
     ASSERT_EQ(1U, urls.size());
     EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
   }
@@ -191,11 +200,14 @@
   GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);
 
   ui_test_utils::NavigateToURL(browser(), GetTestUrl());
+  Checkpoint("After second NavigateToURL", start_time);
   WaitForHistoryBackendToRun();
+  Checkpoint("After waiting for history backend to run (2nd time)", start_time);
 
   {
     // No additional entries should be present in the history.
     std::vector<GURL> urls(GetHistoryContents());
+    Checkpoint("After second GetHistoryContents", start_time);
     ASSERT_EQ(1U, urls.size());
     EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
   }
diff --git a/chrome/browser/history/history_database.cc b/chrome/browser/history/history_database.cc
index c5478b8..bdd3cb4 100644
--- a/chrome/browser/history/history_database.cc
+++ b/chrome/browser/history/history_database.cc
@@ -14,7 +14,6 @@
 #include "base/rand_util.h"
 #include "base/string_util.h"
 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
-#include "chrome/common/chrome_switches.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
diff --git a/chrome/browser/history/history_types.cc b/chrome/browser/history/history_types.cc
index ecc8314..d3753bf 100644
--- a/chrome/browser/history/history_types.cc
+++ b/chrome/browser/history/history_types.cc
@@ -149,7 +149,7 @@
 URLResult::~URLResult() {
 }
 
-void URLResult::Swap(URLResult* other) {
+void URLResult::SwapResult(URLResult* other) {
   URLRow::Swap(other);
   std::swap(visit_time_, other->visit_time_);
   snippet_.Swap(&other->snippet_);
@@ -192,7 +192,7 @@
 
 void QueryResults::AppendURLBySwapping(URLResult* result) {
   URLResult* new_result = new URLResult;
-  new_result->Swap(result);
+  new_result->SwapResult(result);
 
   results_.push_back(new_result);
   AddURLUsageAtIndex(new_result->url(), results_.size() - 1);
diff --git a/chrome/browser/history/history_types.h b/chrome/browser/history/history_types.h
index 76359fc..320c991 100644
--- a/chrome/browser/history/history_types.h
+++ b/chrome/browser/history/history_types.h
@@ -122,10 +122,10 @@
     favicon_id_ = favicon_id;
   }
 
+ protected:
   // Swaps the contents of this URLRow with another, which allows it to be
   // destructively copied without memory allocations.
-  // (Virtual because it's overridden by URLResult.)
-  virtual void Swap(URLRow* other);
+  void Swap(URLRow* other);
 
  private:
   // This class writes directly into this structure and clears our dirty bits
@@ -359,7 +359,7 @@
     return title_match_positions_;
   }
 
-  virtual void Swap(URLResult* other);
+  void SwapResult(URLResult* other);
 
  private:
   friend class HistoryBackend;
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc
index e139cdd..7bc76da 100644
--- a/chrome/browser/history/history_unittest.cc
+++ b/chrome/browser/history/history_unittest.cc
@@ -45,16 +45,14 @@
 #include "chrome/browser/history/in_memory_database.h"
 #include "chrome/browser/history/in_memory_history_backend.h"
 #include "chrome/browser/history/page_usage_data.h"
-#include "chrome/browser/history/top_sites.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/tools/profiles/thumbnail-inl.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -114,19 +112,6 @@
   ~HistoryTest() {
   }
 
-  // Thumbnail callback: we save the data and exit the message loop so the
-  // unit test can read the data
-  void OnThumbnailDataAvailable(
-      HistoryService::Handle request_handle,
-      scoped_refptr<RefCountedBytes> jpeg_data) {
-    got_thumbnail_callback_ = true;
-    if (jpeg_data.get()) {
-      std::copy(jpeg_data->data.begin(), jpeg_data->data.end(),
-                std::back_inserter(thumbnail_data_));
-    }
-    MessageLoop::current()->Quit();
-  }
-
   // Creates the HistoryBackend and HistoryDatabase on the current thread,
   // assigning the values to backend_ and db_.
   void CreateBackendAndDatabase() {
@@ -683,73 +668,6 @@
   EXPECT_GT(page_usage_data_[0]->GetScore(), 5.0);
 }
 
-// This just tests history system -> thumbnail database integration, the actual
-// thumbnail tests are in its own file.
-TEST_F(HistoryTest, Thumbnails) {
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  scoped_refptr<HistoryService> history(new HistoryService);
-  history_service_ = history;
-  ASSERT_TRUE(history->Init(history_dir_, NULL));
-
-  scoped_ptr<SkBitmap> thumbnail(
-      gfx::JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
-  static const double boringness = 0.25;
-
-  const GURL url("http://www.google.com/thumbnail_test/");
-  // Must be visited before adding a thumbnail.
-  history->AddPage(url, history::SOURCE_BROWSED);
-  history->SetPageThumbnail(url, *thumbnail,
-                            ThumbnailScore(boringness, true, true));
-
-  // Make sure we get the correct thumbnail data.
-  EXPECT_TRUE(history->GetPageThumbnail(url, &consumer_,
-      NewCallback(static_cast<HistoryTest*>(this),
-                  &HistoryTest::OnThumbnailDataAvailable)));
-  thumbnail_data_.clear();
-  MessageLoop::current()->Run();
-  // Make sure we got a valid JPEG back. This isn't equivalent to
-  // being correct, but when we're roundtripping through JPEG
-  // compression and we don't have a similarity measure.
-  EXPECT_TRUE(thumbnail_data_.size());
-  scoped_ptr<SkBitmap> decoded_thumbnail(
-      gfx::JPEGCodec::Decode(&thumbnail_data_[0], thumbnail_data_.size()));
-  EXPECT_TRUE(decoded_thumbnail.get());
-
-  // Request a nonexistent thumbnail and make sure we get
-  // a callback and no data.
-  EXPECT_TRUE(history->GetPageThumbnail(GURL("http://asdfasdf.com/"),
-              &consumer_,
-                  NewCallback(static_cast<HistoryTest*>(this),
-                              &HistoryTest::OnThumbnailDataAvailable)));
-  thumbnail_data_.clear();
-  MessageLoop::current()->Run();
-  EXPECT_EQ(0U, thumbnail_data_.size());
-
-  // Request the thumbnail and cancel the request..
-  got_thumbnail_callback_ = false;
-  thumbnail_data_.clear();
-  HistoryService::Handle handle = history->GetPageThumbnail(url, &consumer_,
-      NewCallback(static_cast<HistoryTest*>(this),
-                  &HistoryTest::OnThumbnailDataAvailable));
-  EXPECT_TRUE(handle);
-
-  history->CancelRequest(handle);
-
-  // We create a task with a timeout so we can make sure we don't get and
-  // data in that time.
-  class QuitMessageLoop : public Task {
-   public:
-    virtual void Run() {
-      MessageLoop::current()->Quit();
-    }
-  };
-  MessageLoop::current()->PostDelayedTask(FROM_HERE, new QuitMessageLoop, 2000);
-  MessageLoop::current()->Run();
-  EXPECT_FALSE(got_thumbnail_callback_);
-}
-
 TEST_F(HistoryTest, MostVisitedURLs) {
   scoped_refptr<HistoryService> history(new HistoryService);
   history_service_ = history;
diff --git a/chrome/browser/history/in_memory_history_backend.cc b/chrome/browser/history/in_memory_history_backend.cc
index 25219f6..cfeb618 100644
--- a/chrome/browser/history/in_memory_history_backend.cc
+++ b/chrome/browser/history/in_memory_history_backend.cc
@@ -16,12 +16,10 @@
 #include "chrome/browser/history/in_memory_database.h"
 #include "chrome/browser/history/in_memory_url_index.h"
 #include "chrome/browser/history/url_database.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "chrome/common/pref_names.h"
 
 namespace history {
 
diff --git a/chrome/browser/history/in_memory_url_index.cc b/chrome/browser/history/in_memory_url_index.cc
index 62a22e6..9d2e925 100644
--- a/chrome/browser/history/in_memory_url_index.cc
+++ b/chrome/browser/history/in_memory_url_index.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/history/in_memory_url_index.h"
 
 #include <algorithm>
+#include <iterator>
 #include <limits>
 
-#include "app/l10n_util.h"
 #include "base/i18n/break_iterator.h"
 #include "base/string_util.h"
 #include "base/time.h"
@@ -16,6 +16,7 @@
 #include "chrome/browser/history/url_database.h"
 #include "net/base/escape.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/utypes.h"  // for int32_t
 
 using base::Time;
diff --git a/chrome/browser/history/query_parser.cc b/chrome/browser/history/query_parser.cc
index 12ecc29..1037b6c 100644
--- a/chrome/browser/history/query_parser.cc
+++ b/chrome/browser/history/query_parser.cc
@@ -6,12 +6,12 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/i18n/break_iterator.h"
 #include "base/logging.h"
 #include "base/scoped_vector.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/uscript.h"
 
 namespace {
diff --git a/chrome/browser/history/redirect_uitest.cc b/chrome/browser/history/redirect_uitest.cc
index 9d2c35a..904ba86 100644
--- a/chrome/browser/history/redirect_uitest.cc
+++ b/chrome/browser/history/redirect_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include "base/scoped_temp_dir.h"
 #include "base/string_util.h"
 #include "base/string16.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/ui/view_ids.h"
@@ -21,7 +22,7 @@
 #include "chrome/test/ui/ui_test.h"
 #include "net/base/net_util.h"
 #include "net/test/test_server.h"
-#include "views/event.h"
+#include "ui/base/events.h"
 
 namespace {
 
@@ -164,9 +165,8 @@
   ASSERT_TRUE(browser->BringToFront());
   ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER, &tab_view_bounds,
                                     true));
-  ASSERT_TRUE(
-      window->SimulateOSClick(tab_view_bounds.CenterPoint(),
-                              views::Event::EF_LEFT_BUTTON_DOWN));
+  ASSERT_TRUE(window->SimulateOSClick(tab_view_bounds.CenterPoint(),
+                                      ui::EF_LEFT_BUTTON_DOWN));
   EXPECT_TRUE(tab_proxy->WaitForNavigation(last_nav_time));
 
   std::vector<GURL> redirects;
@@ -210,7 +210,7 @@
   NavigateToURL(first_url);
 
   for (int i = 0; i < 10; ++i) {
-    base::PlatformThread::Sleep(sleep_timeout_ms());
+    base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
     scoped_refptr<TabProxy> tab_proxy(GetActiveTab());
     ASSERT_TRUE(tab_proxy.get());
     ASSERT_TRUE(tab_proxy->GetRedirectsFrom(first_url, &redirects));
@@ -243,7 +243,9 @@
 // Test that redirect from http:// to file:// :
 // A) does not crash the browser or confuse the redirect chain, see bug 1080873
 // B) does not take place.
-TEST_F(RedirectTest, NoHttpToFile) {
+//
+// Flaky on XP and Vista, http://crbug.com/69390.
+TEST_F(RedirectTest, FLAKY_NoHttpToFile) {
   ASSERT_TRUE(test_server_.Start());
   FilePath test_file(test_data_directory_);
   test_file = test_file.AppendASCII("http_to_file.html");
@@ -316,7 +318,7 @@
   std::wstring final_url_title = UTF8ToWide("Title Of Awesomeness");
   // Wait till the final page has been loaded.
   for (int i = 0; i < 10; ++i) {
-    base::PlatformThread::Sleep(sleep_timeout_ms());
+    base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
     scoped_refptr<TabProxy> tab_proxy(GetActiveTab());
     ASSERT_TRUE(tab_proxy.get());
     ASSERT_TRUE(tab_proxy->GetTabTitle(&tab_title));
diff --git a/chrome/browser/history/starred_url_database.h b/chrome/browser/history/starred_url_database.h
index aab2ae5..aff2d64 100644
--- a/chrome/browser/history/starred_url_database.h
+++ b/chrome/browser/history/starred_url_database.h
@@ -8,12 +8,12 @@
 
 #include <set>
 
-#include "app/tree_node_model.h"
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/string16.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/history/url_database.h"
+#include "ui/base/models/tree_node_model.h"
 
 class FilePath;
 
@@ -115,7 +115,7 @@
   StarID CreateStarredEntry(StarredEntry* entry);
 
   // Used when checking integrity of starred table.
-  typedef TreeNodeWithValue<history::StarredEntry> StarredNode;
+  typedef ui::TreeNodeWithValue<history::StarredEntry> StarredNode;
 
   // Returns the max group id, or 0 if there is an error.
   UIStarID GetMaxGroupID();
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index 7fa8bd1..3f863da 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/history/thumbnail_database.h"
 
+#include <algorithm>
+#include <string>
+
 #include "app/sql/statement.h"
 #include "app/sql/transaction.h"
 #include "base/command_line.h"
@@ -16,10 +19,9 @@
 #include "chrome/browser/history/history_publisher.h"
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/history/url_database.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/thumbnail_score.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
@@ -121,18 +123,7 @@
 
 bool ThumbnailDatabase::InitThumbnailTable() {
   if (!db_.DoesTableExist("thumbnails")) {
-    if (history::TopSites::IsEnabled()) {
-      use_top_sites_ = true;
-      return true;
-    }
-    if (!db_.Execute("CREATE TABLE thumbnails ("
-        "url_id INTEGER PRIMARY KEY,"
-        "boring_score DOUBLE DEFAULT 1.0,"
-        "good_clipping INTEGER DEFAULT 0,"
-        "at_top INTEGER DEFAULT 0,"
-        "last_updated INTEGER DEFAULT 0,"
-        "data BLOB)"))
-      return false;
+    use_top_sites_ = true;
   }
   return true;
 }
diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc
index 23eccef..6483a25 100644
--- a/chrome/browser/history/thumbnail_database_unittest.cc
+++ b/chrome/browser/history/thumbnail_database_unittest.cc
@@ -14,14 +14,12 @@
 #include "base/scoped_temp_dir.h"
 #include "chrome/browser/history/thumbnail_database.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/browser/history/top_sites.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/tools/profiles/thumbnail-inl.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -72,297 +70,6 @@
   FilePath new_file_name_;
 };
 
-TEST_F(ThumbnailDatabaseTest, AddDelete) {
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  ThumbnailDatabase db;
-  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
-
-  // Add one page & verify it got added.
-  ThumbnailScore boring(kBoringness, true, true);
-  Time time;
-  GURL gurl;
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring, time);
-  ThumbnailScore score_output;
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_output));
-  ASSERT_TRUE(boring.Equals(score_output));
-
-  // Verify a random page is not found.
-  int64 page2 = 5678;
-  std::vector<unsigned char> jpeg_data;
-  EXPECT_FALSE(db.GetPageThumbnail(page2, &jpeg_data));
-  EXPECT_FALSE(db.ThumbnailScoreForId(page2, &score_output));
-
-  // Add another page with a better boringness & verify it got added.
-  ThumbnailScore better_boringness(kBetterBoringness, true, true);
-
-  db.SetPageThumbnail(gurl, page2, *google_bitmap_, better_boringness, time);
-  ASSERT_TRUE(db.ThumbnailScoreForId(page2, &score_output));
-  ASSERT_TRUE(better_boringness.Equals(score_output));
-
-  // Delete the thumbnail for the second page.
-  ThumbnailScore worse_boringness(kWorseBoringness, true, true);
-  db.SetPageThumbnail(gurl, page2, SkBitmap(), worse_boringness, time);
-  ASSERT_FALSE(db.GetPageThumbnail(page2, &jpeg_data));
-  ASSERT_FALSE(db.ThumbnailScoreForId(page2, &score_output));
-
-  // Delete the first thumbnail using the explicit delete API.
-  ASSERT_TRUE(db.DeleteThumbnail(kPage1));
-
-  // Make sure it is gone
-  ASSERT_FALSE(db.ThumbnailScoreForId(kPage1, &score_output));
-  ASSERT_FALSE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_FALSE(db.ThumbnailScoreForId(page2, &score_output));
-  ASSERT_FALSE(db.GetPageThumbnail(page2, &jpeg_data));
-}
-
-TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) {
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  ThumbnailDatabase db;
-  Time now = Time::Now();
-  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
-
-  // Add one page & verify it got added.
-  ThumbnailScore boring(kBoringness, true, true);
-
-  Time time;
-  GURL gurl;
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring, time);
-  std::vector<unsigned char> jpeg_data;
-  ThumbnailScore score_out;
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring.Equals(score_out));
-
-  // Attempt to update the first page entry with a thumbnail that
-  // is more boring and verify that it doesn't change.
-  ThumbnailScore more_boring(kWorseBoringness, true, true);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, more_boring, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring.Equals(score_out));
-
-  // Attempt to update the first page entry with a thumbnail that
-  // is less boring and verify that we update it.
-  ThumbnailScore less_boring(kBetterBoringness, true, true);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, less_boring, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(less_boring.Equals(score_out));
-}
-
-TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) {
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  ThumbnailDatabase db;
-  Time now = Time::Now();
-  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
-
-  // Add one page & verify it got added. Note that it doesn't have
-  // |good_clipping| and isn't |at_top|.
-  ThumbnailScore boring_and_bad(kBoringness, false, false);
-
-  Time time;
-  GURL gurl;
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring_and_bad, time);
-  std::vector<unsigned char> jpeg_data;
-  ThumbnailScore score_out;
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring_and_bad.Equals(score_out));
-
-  // A thumbnail that's at the top of the page should replace
-  // thumbnails that are in the middle, for the same boringness.
-  ThumbnailScore boring_but_better(kBoringness, false, true);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring_but_better, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring_but_better.Equals(score_out));
-
-  // The only case where we should replace a thumbnail at the top with
-  // a thumbnail in the middle/bottom is when the current thumbnail is
-  // weirdly stretched and the incoming thumbnail isn't.
-  ThumbnailScore better_boring_bad_framing(kBetterBoringness, false, false);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, better_boring_bad_framing,
-                      time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring_but_better.Equals(score_out));
-
-  ThumbnailScore boring_good_clipping(kBoringness, true, false);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring_good_clipping,
-                      time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring_good_clipping.Equals(score_out));
-
-  // Now that we have a non-stretched, middle of the page thumbnail,
-  // we shouldn't be able to replace it with:
-
-  // 1) A stretched thumbnail in the middle of the page
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_,
-                      ThumbnailScore(kBetterBoringness, false, false, now),
-                      time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring_good_clipping.Equals(score_out));
-
-  // 2) A stretched thumbnail at the top of the page
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_,
-                      ThumbnailScore(kBetterBoringness, false, true, now),
-                      time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(boring_good_clipping.Equals(score_out));
-
-  // But it should be replaced by a thumbnail that's clipped properly
-  // and is at the top
-  ThumbnailScore best_score(kBetterBoringness, true, true);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, best_score, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(best_score.Equals(score_out));
-}
-
-TEST_F(ThumbnailDatabaseTest, ThumbnailTimeDegradation) {
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  ThumbnailDatabase db;
-  const Time kNow = Time::Now();
-  const Time kThreeHoursAgo = kNow - TimeDelta::FromHours(4);
-  const Time kFiveHoursAgo = kNow - TimeDelta::FromHours(6);
-  const double kBaseBoringness = 0.305;
-  const double kWorseBoringness = 0.345;
-
-  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
-
-  // add one page & verify it got added.
-  ThumbnailScore base_boringness(kBaseBoringness, true, true, kFiveHoursAgo);
-
-  Time time;
-  GURL gurl;
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, base_boringness, time);
-  std::vector<unsigned char> jpeg_data;
-  ThumbnailScore score_out;
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(base_boringness.Equals(score_out));
-
-  // Try to add a different thumbnail with a worse score an hour later
-  // (but not enough to trip the boringness degradation threshold).
-  ThumbnailScore hour_later(kWorseBoringness, true, true, kThreeHoursAgo);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, hour_later, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(base_boringness.Equals(score_out));
-
-  // After a full five hours, things should have degraded enough
-  // that we'll allow the same thumbnail with the same (worse)
-  // boringness that we previous rejected.
-  ThumbnailScore five_hours_later(kWorseBoringness, true, true, kNow);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, five_hours_later, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(five_hours_later.Equals(score_out));
-}
-
-TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) {
-  // We enforce a maximum boringness score: even in cases where we
-  // should replace a thumbnail with another because of reasons other
-  // than straight up boringness score, still reject because the
-  // thumbnail is totally boring.
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  ThumbnailDatabase db;
-  Time now = Time::Now();
-  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
-
-  std::vector<unsigned char> jpeg_data;
-  ThumbnailScore score_out;
-  const double kBaseBoringness = 0.50;
-  const Time kNow = Time::Now();
-  const int kSizeOfTable = 4;
-  struct {
-    bool good_scaling;
-    bool at_top;
-  } const heiarchy_table[] = {
-    {false, false},
-    {false, true},
-    {true, false},
-    {true, true}
-  };
-
-  Time time;
-  GURL gurl;
-
-  // Test that for each entry type, all entry types that are better
-  // than it still will reject thumbnails which are totally boring.
-  for (int i = 0; i < kSizeOfTable; ++i) {
-    ThumbnailScore base(kBaseBoringness,
-                        heiarchy_table[i].good_scaling,
-                        heiarchy_table[i].at_top,
-                        kNow);
-
-    db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, base, time);
-    ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-    ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-    ASSERT_TRUE(base.Equals(score_out));
-
-    for (int j = i; j < kSizeOfTable; ++j) {
-      ThumbnailScore shouldnt_replace(
-          kTotallyBoring, heiarchy_table[j].good_scaling,
-          heiarchy_table[j].at_top, kNow);
-
-      db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, shouldnt_replace,
-                          time);
-      ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-      ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-      ASSERT_TRUE(base.Equals(score_out));
-    }
-
-    // Clean up for the next iteration
-    ASSERT_TRUE(db.DeleteThumbnail(kPage1));
-    ASSERT_FALSE(db.GetPageThumbnail(kPage1, &jpeg_data));
-    ASSERT_FALSE(db.ThumbnailScoreForId(kPage1, &score_out));
-  }
-
-  // We should never accept a totally boring thumbnail no matter how
-  // much old the current thumbnail is.
-  ThumbnailScore base_boring(kBaseBoringness, true, true, kNow);
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, base_boring, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(base_boring.Equals(score_out));
-
-  ThumbnailScore totally_boring_in_the_future(
-      kTotallyBoring, true, true, kNow + TimeDelta::FromDays(365));
-  db.SetPageThumbnail(gurl, kPage1, *google_bitmap_,
-                      totally_boring_in_the_future, time);
-  ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data));
-  ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out));
-  ASSERT_TRUE(base_boring.Equals(score_out));
-}
-
-TEST_F(ThumbnailDatabaseTest, NeedsMigrationToTopSites) {
-  if (history::TopSites::IsEnabled())
-    return;  // TopSitesTest replaces this.
-
-  ThumbnailDatabase db;
-  ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
-  db.BeginTransaction();
-  EXPECT_TRUE(db.NeedsMigrationToTopSites());
-  EXPECT_TRUE(db.RenameAndDropThumbnails(file_name_, new_file_name_));
-  EXPECT_FALSE(db.NeedsMigrationToTopSites());
-  EXPECT_FALSE(file_util::PathExists(file_name_));
-  EXPECT_TRUE(file_util::PathExists(new_file_name_));
-}
-
 TEST_F(ThumbnailDatabaseTest, GetFaviconAfterMigrationToTopSites) {
   ThumbnailDatabase db;
   ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
diff --git a/chrome/browser/history/top_sites.cc b/chrome/browser/history/top_sites.cc
index 1635523..155c3fc 100644
--- a/chrome/browser/history/top_sites.cc
+++ b/chrome/browser/history/top_sites.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/md5.h"
@@ -29,11 +28,12 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/thumbnail_score.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 namespace history {
 
@@ -127,7 +127,7 @@
 }  // namespace
 
 TopSites::TopSites(Profile* profile)
-    : backend_(new TopSitesBackend()),
+    : backend_(NULL),
       cache_(new TopSitesCache()),
       thread_safe_cache_(new TopSitesCache()),
       profile_(profile),
@@ -153,15 +153,10 @@
       GetMutableDictionary(prefs::kNTPMostVisitedPinnedURLs);
 }
 
-// static
-bool TopSites::IsEnabled() {
-  std::string switch_value =
-      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kEnableTopSites);
-  return switch_value.empty() || switch_value == "true";
-}
-
 void TopSites::Init(const FilePath& db_name) {
+  // Create the backend here, rather than in the constructor, so that
+  // unit tests that do not need the backend can run without a problem.
+  backend_ = new TopSitesBackend;
   backend_->Init(db_name);
   backend_->GetMostVisitedThumbnails(
       &cancelable_consumer_,
@@ -189,8 +184,8 @@
   }
 
   bool add_temp_thumbnail = false;
-  if (!cache_->IsKnownURL(url)) {
-    if (cache_->top_sites().size() < kTopSitesNumber) {
+  if (!IsKnownURL(url)) {
+    if (!IsFull()) {
       add_temp_thumbnail = true;
     } else {
       return false;  // This URL is not known to us.
@@ -225,7 +220,7 @@
   AddRequest(request, consumer);
   MostVisitedURLList filtered_urls;
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     if (!loaded_) {
       // A request came in before we finished loading. Put the request in
       // pending_callbacks_ and we'll notify it when we finish loading.
@@ -241,10 +236,17 @@
 bool TopSites::GetPageThumbnail(const GURL& url,
                                 scoped_refptr<RefCountedBytes>* bytes) {
   // WARNING: this may be invoked on any thread.
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   return thread_safe_cache_->GetPageThumbnail(url, bytes);
 }
 
+bool TopSites::GetPageThumbnailScore(const GURL& url,
+                                     ThumbnailScore* score) {
+  // WARNING: this may be invoked on any thread.
+  base::AutoLock lock(lock_);
+  return thread_safe_cache_->GetPageThumbnailScore(url, score);
+}
+
 // Returns the index of |url| in |urls|, or -1 if not found.
 static int IndexOf(const MostVisitedURLList& urls, const GURL& url) {
   for (size_t i = 0; i < urls.size(); i++) {
@@ -443,7 +445,7 @@
 CancelableRequestProvider::Handle TopSites::StartQueryForMostVisited() {
   DCHECK(loaded_);
   if (!profile_)
-    return NULL;
+    return 0;
 
   HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
   // |hs| may be null during unit tests.
@@ -454,7 +456,15 @@
         &cancelable_consumer_,
         NewCallback(this, &TopSites::OnTopSitesAvailableFromHistory));
   }
-  return NULL;
+  return 0;
+}
+
+bool TopSites::IsKnownURL(const GURL& url) {
+  return loaded_ && cache_->IsKnownURL(url);
+}
+
+bool TopSites::IsFull() {
+  return loaded_ && cache_->top_sites().size() >= kTopSitesNumber;
 }
 
 TopSites::~TopSites() {
@@ -732,7 +742,7 @@
     }
     StartQueryForMostVisited();
   } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
-    if (cache_->top_sites().size() < kTopSitesNumber) {
+    if (!IsFull()) {
       NavigationController::LoadCommittedDetails* load_details =
           Details<NavigationController::LoadCommittedDetails>(details).ptr();
       if (!load_details)
@@ -808,7 +818,7 @@
   MostVisitedURLList filtered_urls;
   PendingCallbackSet pending_callbacks;
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
 
     if (loaded_)
       return;  // Don't do anything if we're already loaded.
@@ -830,14 +840,14 @@
 }
 
 void TopSites::ResetThreadSafeCache() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   MostVisitedURLList cached;
   ApplyBlacklistAndPinnedURLs(cache_->top_sites(), &cached);
   thread_safe_cache_->SetTopSites(cached);
 }
 
 void TopSites::ResetThreadSafeImageCache() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   thread_safe_cache_->SetThumbnails(cache_->images());
   thread_safe_cache_->RemoveUnreferencedThumbnails();
 }
diff --git a/chrome/browser/history/top_sites.h b/chrome/browser/history/top_sites.h
index 9eeb715..f92b877 100644
--- a/chrome/browser/history/top_sites.h
+++ b/chrome/browser/history/top_sites.h
@@ -13,9 +13,9 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
 #include "base/ref_counted_memory.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "base/timer.h"
 #include "chrome/browser/cancelable_request.h"
@@ -51,9 +51,6 @@
  public:
   explicit TopSites(Profile* profile);
 
-  // Returns whether top sites is enabled.
-  static bool IsEnabled();
-
   // Initializes TopSites.
   void Init(const FilePath& db_name);
 
@@ -82,6 +79,11 @@
   bool GetPageThumbnail(const GURL& url,
                         scoped_refptr<RefCountedBytes>* bytes);
 
+  // Get a thumbnail score for a given page. Returns true iff we have the
+  // thumbnail score.  This may be invoked on any thread. The score will
+  // be copied to |score|.
+  virtual bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score);
+
   // Invoked from History if migration is needed. If this is invoked it will
   // be before HistoryLoaded is invoked.
   void MigrateFromHistory();
@@ -147,6 +149,19 @@
 
   bool loaded() const { return loaded_; }
 
+  // Returns true if the given URL is known to the top sites service.
+  // This function also returns false if TopSites isn't loaded yet.
+  virtual bool IsKnownURL(const GURL& url);
+
+  // Returns true if the top sites list is full (i.e. we already have the
+  // maximum number of top sites).  This function also returns false if
+  // TopSites isn't loaded yet.
+  virtual bool IsFull();
+
+ protected:
+  // For allowing inheritance.
+  virtual ~TopSites();
+
  private:
   friend class base::RefCountedThreadSafe<TopSites>;
   friend class TopSitesTest;
@@ -180,8 +195,6 @@
     TOP_SITES_LOADED
   };
 
-  ~TopSites();
-
   // Sets the thumbnail without writing to the database. Useful when
   // reading last known top sites from the DB.
   // Returns true if the thumbnail was set, false if the existing one is better.
@@ -300,7 +313,7 @@
   Profile* profile_;
 
   // Lock used to access |thread_safe_cache_|.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   CancelableRequestConsumer cancelable_consumer_;
 
diff --git a/chrome/browser/history/top_sites_cache.cc b/chrome/browser/history/top_sites_cache.cc
index 828b701..3be7041 100644
--- a/chrome/browser/history/top_sites_cache.cc
+++ b/chrome/browser/history/top_sites_cache.cc
@@ -47,6 +47,17 @@
   return false;
 }
 
+bool TopSitesCache::GetPageThumbnailScore(const GURL& url,
+                                          ThumbnailScore* score) {
+  std::map<GURL, Images>::const_iterator found =
+      images_.find(GetCanonicalURL(url));
+  if (found != images_.end()) {
+    *score = found->second.thumbnail_score;
+    return true;
+  }
+  return false;
+}
+
 GURL TopSitesCache::GetCanonicalURL(const GURL& url) {
   CanonicalURLs::iterator i = TopSitesCache::GetCanonicalURLsIterator(url);
   return i == canonical_urls_.end() ? url : i->first.first->url;
diff --git a/chrome/browser/history/top_sites_cache.h b/chrome/browser/history/top_sites_cache.h
index 4c5d79a..ca0d7bc 100644
--- a/chrome/browser/history/top_sites_cache.h
+++ b/chrome/browser/history/top_sites_cache.h
@@ -45,6 +45,10 @@
   bool GetPageThumbnail(const GURL& url,
                         scoped_refptr<RefCountedBytes>* bytes);
 
+  // Fetches the thumbnail score for the specified url. Returns true if
+  // there is a thumbnail score for the specified url.
+  bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score);
+
   // Returns the canonical URL for |url|.
   GURL GetCanonicalURL(const GURL& url);
 
diff --git a/chrome/browser/history/top_sites_unittest.cc b/chrome/browser/history/top_sites_unittest.cc
index f908646..b380a57 100644
--- a/chrome/browser/history/top_sites_unittest.cc
+++ b/chrome/browser/history/top_sites_unittest.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
+#include "base/format_macros.h"
 #include "base/path_service.h"
 #include "base/scoped_temp_dir.h"
 #include "base/string_util.h"
@@ -25,13 +25,14 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/testing_profile.h"
 #include "chrome/tools/profiles/thumbnail-inl.h"
-#include "gfx/codec/jpeg_codec.h"
 #include "googleurl/src/gurl.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/jpeg_codec.h"
 
 namespace history {
 
@@ -132,7 +133,6 @@
   }
 
   virtual void SetUp() {
-    CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTopSites);
     profile_.reset(new TestingProfile);
     if (CreateHistoryAndTopSites()) {
       profile_->CreateHistoryService(false, false);
@@ -382,6 +382,16 @@
                   const FilePath& db_path) {
     std::string sql;
     ASSERT_TRUE(file_util::ReadFileToString(sql_path, &sql));
+
+    // Replace the 'last_visit_time', 'visit_time', 'time_slot' values in this
+    // SQL with the current time.
+    int64 now = base::Time::Now().ToInternalValue();
+    std::vector<std::string> sql_time;
+    sql_time.push_back(StringPrintf("%" PRId64, now));  // last_visit_time
+    sql_time.push_back(StringPrintf("%" PRId64, now));  // visit_time
+    sql_time.push_back(StringPrintf("%" PRId64, now));  // time_slot
+    sql = ReplaceStringPlaceholders(sql, sql_time, NULL);
+
     sql::Connection connection;
     ASSERT_TRUE(connection.Open(db_path));
     ASSERT_TRUE(connection.Execute(sql.c_str()));
diff --git a/chrome/browser/history/url_database.cc b/chrome/browser/history/url_database.cc
index dd3346b..24decc6 100644
--- a/chrome/browser/history/url_database.cc
+++ b/chrome/browser/history/url_database.cc
@@ -9,11 +9,11 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "app/sql/statement.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace history {
 
@@ -163,8 +163,11 @@
   statement.BindInt(5, info.hidden() ? 1 : 0);
   statement.BindInt64(6, info.favicon_id());
 
-  if (!statement.Run())
+  if (!statement.Run()) {
+    VLOG(0) << "Failed to add url " << info.url().possibly_invalid_spec()
+            << " to table history.urls.";
     return 0;
+  }
   return GetDB().GetLastInsertRowId();
 }
 
diff --git a/chrome/browser/history/visit_database.cc b/chrome/browser/history/visit_database.cc
index d0156c2..ace5dac 100644
--- a/chrome/browser/history/visit_database.cc
+++ b/chrome/browser/history/visit_database.cc
@@ -111,8 +111,11 @@
       "INSERT INTO visits "
       "(url, visit_time, from_visit, transition, segment_id, is_indexed) "
       "VALUES (?,?,?,?,?,?)"));
-  if (!statement)
+  if (!statement) {
+    VLOG(0) << "Failed to build visit insert statement:  "
+            << "url_id = " << visit->url_id;
     return 0;
+  }
 
   statement.BindInt64(0, visit->url_id);
   statement.BindInt64(1, visit->visit_time.ToInternalValue());
@@ -120,8 +123,12 @@
   statement.BindInt64(3, visit->transition);
   statement.BindInt64(4, visit->segment_id);
   statement.BindInt64(5, visit->is_indexed);
-  if (!statement.Run())
+
+  if (!statement.Run()) {
+    VLOG(0) << "Failed to execute visit insert statement:  "
+            << "url_id = " << visit->url_id;
     return 0;
+  }
 
   visit->visit_id = GetDB().GetLastInsertRowId();
 
@@ -129,13 +136,19 @@
     // Record the source of this visit when it is not browsed.
     sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE,
         "INSERT INTO visit_source (id, source) VALUES (?,?)"));
-    if (!statement1.is_valid())
+    if (!statement1.is_valid()) {
+      VLOG(0) << "Failed to build visit_source insert statement:  "
+              << "url_id = " << visit->visit_id;
       return 0;
+    }
 
     statement1.BindInt64(0, visit->visit_id);
     statement1.BindInt64(1, source);
-    if (!statement1.Run())
+    if (!statement1.Run()) {
+      VLOG(0) << "Failed to execute visit_source insert statement:  "
+              << "url_id = " << visit->visit_id;
       return 0;
+    }
   }
 
   return visit->visit_id;
diff --git a/chrome/browser/host_zoom_map.cc b/chrome/browser/host_zoom_map.cc
index 3e6ce27..3dc257b 100644
--- a/chrome/browser/host_zoom_map.cc
+++ b/chrome/browser/host_zoom_map.cc
@@ -21,7 +21,7 @@
 #include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 
 using WebKit::WebView;
 
@@ -30,7 +30,7 @@
       updating_preferences_(false) {
   Load();
   default_zoom_level_ =
-      profile_->GetPrefs()->GetReal(prefs::kDefaultZoomLevel);
+      profile_->GetPrefs()->GetDouble(prefs::kDefaultZoomLevel);
   registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
                  Source<Profile>(profile));
   // Don't observe pref changes (e.g. from sync) in Incognito; once we create
@@ -51,7 +51,7 @@
   if (!profile_)
     return;
 
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   host_zoom_levels_.clear();
   const DictionaryValue* host_zoom_dictionary =
       profile_->GetPrefs()->GetDictionary(prefs::kPerHostZoomLevels);
@@ -62,7 +62,7 @@
       const std::string& host(*i);
       double zoom_level = 0;
 
-      bool success = host_zoom_dictionary->GetRealWithoutPathExpansion(
+      bool success = host_zoom_dictionary->GetDoubleWithoutPathExpansion(
           host, &zoom_level);
       if (!success) {
         // The data used to be stored as ints, so try that.
@@ -95,7 +95,7 @@
 
 double HostZoomMap::GetZoomLevel(const GURL& url) const {
   std::string host(net::GetHostOrSpecFromURL(url));
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   HostZoomLevels::const_iterator i(host_zoom_levels_.find(host));
   return (i == host_zoom_levels_.end()) ? default_zoom_level_ : i->second;
 }
@@ -108,7 +108,7 @@
   std::string host(net::GetHostOrSpecFromURL(url));
 
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     if (level == default_zoom_level_)
       host_zoom_levels_.erase(host);
     else
@@ -133,7 +133,7 @@
       host_zoom_dictionary->RemoveWithoutPathExpansion(host, NULL);
     } else {
       host_zoom_dictionary->SetWithoutPathExpansion(
-          host, Value::CreateRealValue(level));
+          host, Value::CreateDoubleValue(level));
     }
   }
   updating_preferences_ = false;
@@ -141,7 +141,7 @@
 
 double HostZoomMap::GetTemporaryZoomLevel(int render_process_id,
                                           int render_view_id) const {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   for (size_t i = 0; i < temporary_zoom_levels_.size(); ++i) {
     if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
         temporary_zoom_levels_[i].render_view_id == render_view_id) {
@@ -159,7 +159,7 @@
     return;
 
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     size_t i;
     for (i = 0; i < temporary_zoom_levels_.size(); ++i) {
       if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
@@ -193,7 +193,7 @@
     return;
 
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     host_zoom_levels_.clear();
   }
 
@@ -224,7 +224,7 @@
       Shutdown();
       break;
     case NotificationType::RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW: {
-      AutoLock auto_lock(lock_);
+      base::AutoLock auto_lock(lock_);
       int render_view_id = Source<RenderViewHost>(source)->routing_id();
       int render_process_id = Source<RenderViewHost>(source)->process()->id();
 
@@ -245,7 +245,7 @@
           Load();
         else if (prefs::kDefaultZoomLevel == *name) {
           default_zoom_level_ =
-              profile_->GetPrefs()->GetReal(prefs::kDefaultZoomLevel);
+              profile_->GetPrefs()->GetDouble(prefs::kDefaultZoomLevel);
         }
       }
       break;
diff --git a/chrome/browser/host_zoom_map.h b/chrome/browser/host_zoom_map.h
index 6030f4c..85e02ed 100644
--- a/chrome/browser/host_zoom_map.h
+++ b/chrome/browser/host_zoom_map.h
@@ -14,8 +14,8 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/common/notification_observer.h"
@@ -112,7 +112,7 @@
 
   // Used around accesses to |host_zoom_levels_|, |default_zoom_level_| and
   // |temporary_zoom_levels_| to guarantee thread safety.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   // Whether we are currently updating preferences, this is used to ignore
   // notifications from the preference service that we triggered ourself.
diff --git a/chrome/browser/host_zoom_map_unittest.cc b/chrome/browser/host_zoom_map_unittest.cc
index d99bfbf..82e0e58 100644
--- a/chrome/browser/host_zoom_map_unittest.cc
+++ b/chrome/browser/host_zoom_map_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,6 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer_mock.h"
-#include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
@@ -65,7 +64,7 @@
 TEST_F(HostZoomMapTest, Load) {
   DictionaryValue* dict =
       prefs_->GetMutableDictionary(prefs::kPerHostZoomLevels);
-  dict->SetWithoutPathExpansion(host_, Value::CreateRealValue(kZoomLevel));
+  dict->SetWithoutPathExpansion(host_, Value::CreateDoubleValue(kZoomLevel));
   scoped_refptr<HostZoomMap> map(new HostZoomMap(&profile_));
   EXPECT_EQ(kZoomLevel, map->GetZoomLevel(url_));
 }
@@ -81,7 +80,7 @@
   const DictionaryValue* dict =
       prefs_->GetDictionary(prefs::kPerHostZoomLevels);
   double zoom_level = 0;
-  EXPECT_TRUE(dict->GetRealWithoutPathExpansion(host_, &zoom_level));
+  EXPECT_TRUE(dict->GetDoubleWithoutPathExpansion(host_, &zoom_level));
   EXPECT_EQ(kZoomLevel, zoom_level);
 
   SetPrefObserverExpectation();
@@ -100,7 +99,9 @@
   SetPrefObserverExpectation();
   map->ResetToDefaults();
   EXPECT_EQ(0, map->GetZoomLevel(url_));
-  EXPECT_EQ(NULL, prefs_->GetDictionary(prefs::kPerHostZoomLevels));
+  DictionaryValue empty;
+  EXPECT_TRUE(
+      Value::Equals(&empty, prefs_->GetDictionary(prefs::kPerHostZoomLevels)));
 }
 
 TEST_F(HostZoomMapTest, ReloadOnPrefChange) {
@@ -108,7 +109,7 @@
   map->SetZoomLevel(url_, kZoomLevel);
 
   DictionaryValue dict;
-  dict.SetWithoutPathExpansion(host_, Value::CreateRealValue(0));
+  dict.SetWithoutPathExpansion(host_, Value::CreateDoubleValue(0));
   prefs_->Set(prefs::kPerHostZoomLevels, dict);
   EXPECT_EQ(0, map->GetZoomLevel(url_));
 }
diff --git a/chrome/browser/icon_loader.h b/chrome/browser/icon_loader.h
index 8d055e3..bfd078d 100644
--- a/chrome/browser/icon_loader.h
+++ b/chrome/browser/icon_loader.h
@@ -13,7 +13,7 @@
 #include "base/basictypes.h"
 #include "base/message_loop_proxy.h"
 #include "base/ref_counted.h"
-#include "gfx/scoped_image.h"
+#include "ui/gfx/scoped_image.h"
 
 #if defined(TOOLKIT_USES_GTK)
 #include "base/file_path.h"
diff --git a/chrome/browser/icon_loader_linux.cc b/chrome/browser/icon_loader_linux.cc
index 52f5e2c..29d7f7f 100644
--- a/chrome/browser/icon_loader_linux.cc
+++ b/chrome/browser/icon_loader_linux.cc
@@ -14,9 +14,9 @@
 #include "base/mime_util.h"
 #include "base/threading/thread.h"
 #include "base/string_util.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/gtk_util.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/gtk_util.h"
 
 static int SizeToInt(IconLoader::IconSize size) {
   int pixels = 48;
diff --git a/chrome/browser/icon_loader_win.cc b/chrome/browser/icon_loader_win.cc
index c708fb6..717c15b 100644
--- a/chrome/browser/icon_loader_win.cc
+++ b/chrome/browser/icon_loader_win.cc
@@ -9,8 +9,8 @@
 
 #include "base/message_loop.h"
 #include "base/threading/thread.h"
-#include "gfx/icon_util.h"
-#include "gfx/size.h"
+#include "ui/gfx/icon_util.h"
+#include "ui/gfx/size.h"
 
 void IconLoader::ReadIcon() {
   int size = 0;
diff --git a/chrome/browser/icon_manager_linux.cc b/chrome/browser/icon_manager_linux.cc
index c653d2f..53fd124 100644
--- a/chrome/browser/icon_manager_linux.cc
+++ b/chrome/browser/icon_manager_linux.cc
@@ -5,7 +5,15 @@
 #include "chrome/browser/icon_manager.h"
 
 #include "base/mime_util.h"
+#include "base/threading/thread_restrictions.h"
 
 IconGroupID IconManager::GetGroupIDFromFilepath(const FilePath& filepath) {
+  // It turns out the call to mime_util::GetFileMimeType below does IO, but
+  // callers of GetGroupIDFromFilepath assume it does not do IO (the Windows
+  // and Mac implementations do not). We should fix this by either not doing IO
+  // in this method, or reworking callers to avoid calling it on the UI thread.
+  // See crbug.com/72740.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
   return mime_util::GetFileMimeType(filepath);
 }
diff --git a/chrome/browser/idbbindingutilities_browsertest.cc b/chrome/browser/idbbindingutilities_browsertest.cc
index 3f832b7..581e736 100644
--- a/chrome/browser/idbbindingutilities_browsertest.cc
+++ b/chrome/browser/idbbindingutilities_browsertest.cc
@@ -5,7 +5,6 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/utility_process_host.h"
 #include "chrome/common/indexed_db_key.h"
 #include "chrome/common/serialized_script_value.h"
@@ -13,7 +12,7 @@
 #include "chrome/test/ui_test_utils.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
 #include "webkit/glue/idb_bindings.h"
 #include "webkit/glue/web_io_operators.h"
 
diff --git a/chrome/browser/idle.h b/chrome/browser/idle.h
index 3ea8067..4f99bef 100644
--- a/chrome/browser/idle.h
+++ b/chrome/browser/idle.h
@@ -12,6 +12,13 @@
   IDLE_STATE_LOCKED = 2  // Only available on supported systems.
 };
 
+// For MacOSX, InitIdleMonitor needs to be called first to setup the monitor.
+// StopIdleMonitor should be called if it is not needed any more.
+#if defined(OS_MACOSX)
+void InitIdleMonitor();
+void StopIdleMonitor();
+#endif
+
 IdleState CalculateIdleState(unsigned int idle_threshold);
 
 #endif  // CHROME_BROWSER_IDLE_H_
diff --git a/chrome/browser/idle_linux.cc b/chrome/browser/idle_linux.cc
index 0da7f72..e1cdac2 100644
--- a/chrome/browser/idle_linux.cc
+++ b/chrome/browser/idle_linux.cc
@@ -4,9 +4,74 @@
 
 #include "chrome/browser/idle.h"
 
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <vector>
+
+#include "base/basictypes.h"
 #include "chrome/browser/sync/engine/idle_query_linux.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/x/x11_util.h"
+
+namespace {
+
+class ScreensaverWindowFinder : public ui::EnumerateWindowsDelegate {
+ public:
+  ScreensaverWindowFinder()
+      : exists_(false) {}
+
+  bool exists() const { return exists_; }
+
+ protected:
+  virtual bool ShouldStopIterating(XID window) {
+    if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
+      return false;
+    exists_ = true;
+    return true;
+  }
+
+ private:
+  bool IsScreensaverWindow(XID window) const {
+    // It should occupy the full screen.
+    if (!ui::IsX11WindowFullScreen(window))
+      return false;
+
+    // For xscreensaver, the window should have _SCREENSAVER_VERSION property.
+    if (ui::PropertyExists(window, "_SCREENSAVER_VERSION"))
+      return true;
+
+    // For all others, like gnome-screensaver, the window's WM_CLASS property
+    // should contain "screensaver".
+    std::string value;
+    if (!ui::GetStringProperty(window, "WM_CLASS", &value))
+      return false;
+
+    return value.find("screensaver") != std::string::npos;
+  }
+
+  bool exists_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScreensaverWindowFinder);
+};
+
+bool ScreensaverWindowExists() {
+  ScreensaverWindowFinder finder;
+  gtk_util::EnumerateTopLevelWindows(&finder);
+  return finder.exists();
+}
+
+}
 
 IdleState CalculateIdleState(unsigned int idle_threshold) {
+  // Usually the screensaver is used to lock the screen, so we do not need to
+  // check if the workstation is locked.
+  gdk_error_trap_push();
+  bool result = ScreensaverWindowExists();
+  bool got_error = gdk_error_trap_pop();
+  if (result && !got_error)
+    return IDLE_STATE_LOCKED;
+
   browser_sync::IdleQueryLinux idle_query;
   unsigned int idle_time = idle_query.IdleTime();
   if (idle_time >= idle_threshold)
diff --git a/chrome/browser/idle_mac.cc b/chrome/browser/idle_mac.cc
deleted file mode 100644
index 383e4c7..0000000
--- a/chrome/browser/idle_mac.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/idle.h"
-
-#include <CoreGraphics/CGEventSource.h>
-
-IdleState CalculateIdleState(unsigned int idle_threshold) {
-  unsigned int idle_time = CGEventSourceSecondsSinceLastEventType(
-     kCGEventSourceStateCombinedSessionState,
-     kCGAnyInputEventType);
-  if (idle_time >= idle_threshold)
-    return IDLE_STATE_IDLE;
-  return IDLE_STATE_ACTIVE;
-}
diff --git a/chrome/browser/idle_mac.mm b/chrome/browser/idle_mac.mm
new file mode 100644
index 0000000..4032408
--- /dev/null
+++ b/chrome/browser/idle_mac.mm
@@ -0,0 +1,99 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/idle.h"
+
+#import <Cocoa/Cocoa.h>
+#import <CoreGraphics/CGEventSource.h>
+
+@interface MacScreenMonitor : NSObject {
+ @private
+  BOOL screensaverRunning_;
+  BOOL screenLocked_;
+}
+
+@property (readonly,
+           nonatomic,
+           getter=isScreensaverRunning) BOOL screensaverRunning;
+@property (readonly, nonatomic, getter=isScreenLocked) BOOL screenLocked;
+
+@end
+
+@implementation MacScreenMonitor
+
+@synthesize screensaverRunning = screensaverRunning_;
+@synthesize screenLocked = screenLocked_;
+
+- (id)init {
+  if ((self = [super init])) {
+    NSDistributedNotificationCenter* distCenter =
+          [NSDistributedNotificationCenter defaultCenter];
+    [distCenter addObserver:self
+                   selector:@selector(onScreenSaverStarted:)
+                       name:@"com.apple.screensaver.didstart"
+                     object:nil];
+    [distCenter addObserver:self
+                   selector:@selector(onScreenSaverStopped:)
+                       name:@"com.apple.screensaver.didstop"
+                     object:nil];
+    [distCenter addObserver:self
+                   selector:@selector(onScreenLocked:)
+                       name:@"com.apple.screenIsLocked"
+                     object:nil];
+    [distCenter addObserver:self
+                   selector:@selector(onScreenUnlocked:)
+                       name:@"com.apple.screenIsUnlocked"
+                     object:nil];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSDistributedNotificationCenter defaultCenter] removeObject:self];
+  [super dealloc];
+}
+
+- (void)onScreenSaverStarted:(NSNotification*)notification {
+   screensaverRunning_ = YES;
+}
+
+- (void)onScreenSaverStopped:(NSNotification*)notification {
+   screensaverRunning_ = NO;
+}
+
+- (void)onScreenLocked:(NSNotification*)notification {
+   screenLocked_ = YES;
+}
+
+- (void)onScreenUnlocked:(NSNotification*)notification {
+   screenLocked_ = NO;
+}
+
+@end
+
+static MacScreenMonitor* g_screenMonitor = nil;
+
+void InitIdleMonitor() {
+  if (!g_screenMonitor)
+    g_screenMonitor = [[MacScreenMonitor alloc] init];
+}
+
+void StopIdleMonitor() {
+  [g_screenMonitor release];
+  g_screenMonitor = nil;
+}
+
+IdleState CalculateIdleState(unsigned int idle_threshold) {
+  if ([g_screenMonitor isScreensaverRunning] ||
+      [g_screenMonitor isScreenLocked])
+    return IDLE_STATE_LOCKED;
+
+  CFTimeInterval idle_time = CGEventSourceSecondsSinceLastEventType(
+      kCGEventSourceStateCombinedSessionState,
+      kCGAnyInputEventType);
+  if (idle_time >= idle_threshold)
+    return IDLE_STATE_IDLE;
+
+  return IDLE_STATE_ACTIVE;
+}
diff --git a/chrome/browser/iframe_uitest.cc b/chrome/browser/iframe_uitest.cc
index d255344..bc69358 100644
--- a/chrome/browser/iframe_uitest.cc
+++ b/chrome/browser/iframe_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/chrome/browser/images_uitest.cc b/chrome/browser/images_uitest.cc
index 400ac86..5c36e40 100644
--- a/chrome/browser/images_uitest.cc
+++ b/chrome/browser/images_uitest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
 #include "base/file_path.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "net/base/net_util.h"
 #include "chrome/test/ui/ui_test.h"
@@ -16,7 +17,7 @@
   NavigateToURL(net::FilePathToFileURL(test_file));
 
   // Let the GIFs fully animate.
-  base::PlatformThread::Sleep(sleep_timeout_ms());
+  base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
 
   std::wstring page_title = L"animated gif test";
   EXPECT_EQ(page_title, GetActiveTabTitle());
diff --git a/chrome/browser/ime_input.h b/chrome/browser/ime_input.h
index e446ad3..66526b2 100644
--- a/chrome/browser/ime_input.h
+++ b/chrome/browser/ime_input.h
@@ -12,8 +12,8 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "gfx/rect.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "ui/gfx/rect.h"
 
 // This header file defines a struct and a class used for encapsulating IMM32
 // APIs, controls IMEs attached to a window, and enables the 'on-the-spot'
diff --git a/chrome/browser/importer/firefox2_importer.cc b/chrome/browser/importer/firefox2_importer.cc
index 7783a7c..bf68af0 100644
--- a/chrome/browser/importer/firefox2_importer.cc
+++ b/chrome/browser/importer/firefox2_importer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -140,9 +140,9 @@
   TemplateURL* t_url = new TemplateURL();
   // We set short name by using the title if it exists.
   // Otherwise, we use the shortcut.
-  t_url->set_short_name(!title.empty() ? title : keyword);
-  t_url->set_keyword(keyword);
-  t_url->SetURL(TemplateURLRef::DisplayURLToURLRef(UTF8ToWide(url.spec())),
+  t_url->set_short_name(WideToUTF16Hack(!title.empty() ? title : keyword));
+  t_url->set_keyword(WideToUTF16Hack(keyword));
+  t_url->SetURL(TemplateURLRef::DisplayURLToURLRef(UTF8ToUTF16(url.spec())),
                 0, 0);
   return t_url;
 }
@@ -165,6 +165,8 @@
   std::vector<ProfileWriter::BookmarkEntry> toolbar_bookmarks;
   std::wstring last_folder = first_folder_name;
   bool last_folder_on_toolbar = false;
+  bool last_folder_is_empty = true;
+  Time last_folder_add_date;
   std::vector<std::wstring> path;
   size_t toolbar_folder = 0;
   std::string charset;
@@ -179,7 +181,8 @@
 
     // Get the folder name.
     if (ParseFolderNameFromLine(line, charset, &last_folder,
-                                &last_folder_on_toolbar))
+                                &last_folder_on_toolbar,
+                                &last_folder_add_date))
       continue;
 
     // Get the bookmark entry.
@@ -187,11 +190,18 @@
     GURL url, favicon;
     Time add_date;
     std::wstring post_data;
+    bool is_bookmark;
     // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based
     //                keywords yet.
-    if (ParseBookmarkFromLine(line, charset, &title,
-                              &url, &favicon, &shortcut, &add_date,
-                              &post_data) &&
+    is_bookmark = ParseBookmarkFromLine(line, charset, &title,
+                                        &url, &favicon, &shortcut, &add_date,
+                                        &post_data) ||
+        ParseMinimumBookmarkFromLine(line, charset, &title, &url);
+
+    if (is_bookmark)
+      last_folder_is_empty = false;
+
+    if (is_bookmark &&
         post_data.empty() &&
         CanImportURL(GURL(url)) &&
         default_urls.find(url) == default_urls.end()) {
@@ -235,15 +245,44 @@
     }
 
     // Bookmarks in sub-folder are encapsulated with <DL> tag.
-    if (StartsWithASCII(line, "<DL>", true)) {
+    if (StartsWithASCII(line, "<DL>", false)) {
       path.push_back(last_folder);
       last_folder.clear();
       if (last_folder_on_toolbar && !toolbar_folder)
         toolbar_folder = path.size();
-    } else if (StartsWithASCII(line, "</DL>", true)) {
+
+      // Mark next folder empty as initial state.
+      last_folder_is_empty = true;
+    } else if (StartsWithASCII(line, "</DL>", false)) {
       if (path.empty())
         break;  // Mismatch <DL>.
+
+      std::wstring folder_title = path.back();
       path.pop_back();
+
+      if (last_folder_is_empty) {
+        // Empty folder should be added explicitly.
+        ProfileWriter::BookmarkEntry entry;
+        entry.is_folder = true;
+        entry.creation_time = last_folder_add_date;
+        entry.title = folder_title;
+        if (import_to_bookmark_bar && toolbar_folder) {
+          // Flatten the folder in toolbar.
+          entry.in_toolbar = true;
+          entry.path.assign(path.begin() + toolbar_folder, path.end());
+          toolbar_bookmarks.push_back(entry);
+        } else {
+          // Insert the folder into the "Imported from Firefox" folder.
+          entry.path.assign(path.begin(), path.end());
+          if (import_to_bookmark_bar)
+            entry.path.erase(entry.path.begin());
+          bookmarks->push_back(entry);
+        }
+
+        // Parent folder include current one, so it's not empty.
+        last_folder_is_empty = false;
+      }
+
       if (toolbar_folder > path.size())
         toolbar_folder = 0;
     }
@@ -298,10 +337,8 @@
 void Firefox2Importer::ImportPasswords() {
   // Initializes NSS3.
   NSSDecryptor decryptor;
-  if (!decryptor.Init(source_path_.ToWStringHack(),
-                      source_path_.ToWStringHack()) &&
-      !decryptor.Init(app_path_.ToWStringHack(),
-                      source_path_.ToWStringHack())) {
+  if (!decryptor.Init(source_path_, source_path_) &&
+      !decryptor.Init(app_path_, source_path_)) {
     return;
   }
 
@@ -365,8 +402,9 @@
 bool Firefox2Importer::ParseCharsetFromLine(const std::string& line,
                                             std::string* charset) {
   const char kCharset[] = "charset=";
-  if (StartsWithASCII(line, "<META", true) &&
-      line.find("CONTENT=\"") != std::string::npos) {
+  if (StartsWithASCII(line, "<META", false) &&
+      (line.find("CONTENT=\"") != std::string::npos ||
+          line.find("content=\"") != std::string::npos)) {
     size_t begin = line.find(kCharset);
     if (begin == std::string::npos)
       return false;
@@ -382,10 +420,12 @@
 bool Firefox2Importer::ParseFolderNameFromLine(const std::string& line,
                                                const std::string& charset,
                                                std::wstring* folder_name,
-                                               bool* is_toolbar_folder) {
+                                               bool* is_toolbar_folder,
+                                               Time* add_date) {
   const char kFolderOpen[] = "<DT><H3";
   const char kFolderClose[] = "</H3>";
   const char kToolbarFolderAttribute[] = "PERSONAL_TOOLBAR_FOLDER";
+  const char kAddDateAttribute[] = "ADD_DATE";
 
   if (!StartsWithASCII(line, kFolderOpen, true))
     return false;
@@ -403,6 +443,16 @@
   std::string attribute_list = line.substr(arraysize(kFolderOpen),
       tag_end - arraysize(kFolderOpen) - 1);
   std::string value;
+
+  // Add date
+  if (GetAttribute(attribute_list, kAddDateAttribute, &value)) {
+    int64 time;
+    base::StringToInt64(value, &time);
+    // Upper bound it at 32 bits.
+    if (0 < time && time < (1LL << 32))
+      *add_date = Time::FromTimeT(time);
+  }
+
   if (GetAttribute(attribute_list, kToolbarFolderAttribute, &value) &&
       LowerCaseEqualsASCII(value, "true"))
     *is_toolbar_folder = true;
@@ -503,6 +553,58 @@
 }
 
 // static
+bool Firefox2Importer::ParseMinimumBookmarkFromLine(const std::string& line,
+                                                    const std::string& charset,
+                                                    std::wstring* title,
+                                                    GURL* url) {
+  const char kItemOpen[] = "<DT><A";
+  const char kItemClose[] = "</";
+  const char kHrefAttributeUpper[] = "HREF";
+  const char kHrefAttributeLower[] = "href";
+
+  title->clear();
+  *url = GURL();
+
+  // Case-insensitive check of open tag.
+  if (!StartsWithASCII(line, kItemOpen, false))
+    return false;
+
+  // Find any close tag.
+  size_t end = line.find(kItemClose);
+  size_t tag_end = line.rfind('>', end) + 1;
+  if (end == std::string::npos || tag_end < arraysize(kItemOpen))
+    return false;  // No end tag or start tag is broken.
+
+  std::string attribute_list = line.substr(arraysize(kItemOpen),
+      tag_end - arraysize(kItemOpen) - 1);
+
+  // Title
+  base::CodepageToWide(line.substr(tag_end, end - tag_end), charset.c_str(),
+                       base::OnStringConversionError::SKIP, title);
+  HTMLUnescape(title);
+
+  // URL
+  std::string value;
+  if (GetAttribute(attribute_list, kHrefAttributeUpper, &value) ||
+      GetAttribute(attribute_list, kHrefAttributeLower, &value)) {
+    if (charset.length() != 0) {
+      std::wstring w_url;
+      base::CodepageToWide(value, charset.c_str(),
+                           base::OnStringConversionError::SKIP, &w_url);
+      HTMLUnescape(&w_url);
+
+      string16 url16 = WideToUTF16Hack(w_url);
+
+      *url = GURL(url16);
+    } else {
+      *url = GURL(value);
+    }
+  }
+
+  return true;
+}
+
+// static
 bool Firefox2Importer::GetAttribute(const std::string& attribute_list,
                                     const std::string& attribute,
                                     std::string* value) {
diff --git a/chrome/browser/importer/firefox2_importer.h b/chrome/browser/importer/firefox2_importer.h
index 5264c55..7fef5e6 100644
--- a/chrome/browser/importer/firefox2_importer.h
+++ b/chrome/browser/importer/firefox2_importer.h
@@ -52,6 +52,7 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(FirefoxImporterTest, Firefox2BookmarkParse);
   FRIEND_TEST_ALL_PREFIXES(FirefoxImporterTest, Firefox2CookesParse);
+  FRIEND_TEST_ALL_PREFIXES(FirefoxImporterTest, Firefox2BookmarkFileImport);
 
   virtual ~Firefox2Importer();
 
@@ -84,7 +85,8 @@
   static bool ParseFolderNameFromLine(const std::string& line,
                                       const std::string& charset,
                                       std::wstring* folder_name,
-                                      bool* is_toolbar_folder);
+                                      bool* is_toolbar_folder,
+                                      base::Time* add_date);
   // See above, this will also put the data: URL of the favicon into *favicon
   // if there is a favicon given.  |post_data| is set for POST base keywords to
   // the contents of the actual POST (with %s for the search term).
@@ -96,6 +98,18 @@
                                     std::wstring* shortcut,
                                     base::Time* add_date,
                                     std::wstring* post_data);
+  // Save bookmarks imported from browsers with Firefox2 compatible bookmark
+  // systems such as Epiphany. This bookmark format is the same as that of the
+  // basic Firefox bookmark, but it misses additional properties and uses
+  // lower-case tag:
+  //   ...<h1>Bookmarks</h1><dl>
+  //   <dt><a href="url">name</a></dt>
+  //   <dt><a href="url">name</a></dt>
+  //   </dl>
+  static bool ParseMinimumBookmarkFromLine(const std::string& line,
+                                           const std::string& charset,
+                                           std::wstring* title,
+                                           GURL* url);
 
   // Fetches the given attribute value from the |tag|. Returns true if
   // successful, and |value| will contain the value.
diff --git a/chrome/browser/importer/firefox3_importer.cc b/chrome/browser/importer/firefox3_importer.cc
index 6442c87..38317be 100644
--- a/chrome/browser/importer/firefox3_importer.cc
+++ b/chrome/browser/importer/firefox3_importer.cc
@@ -35,15 +35,25 @@
 using importer::SEARCH_ENGINES;
 using webkit_glue::PasswordForm;
 
+// Original definition is in http://mxr.mozilla.org/firefox/source/toolkit/
+//  components/places/public/nsINavBookmarksService.idl
+enum BookmarkItemType {
+  TYPE_BOOKMARK = 1,
+  TYPE_FOLDER = 2,
+  TYPE_SEPARATOR = 3,
+  TYPE_DYNAMIC_CONTAINER = 4
+};
+
 struct Firefox3Importer::BookmarkItem {
   int parent;
   int id;
   GURL url;
   std::wstring title;
-  int type;
+  BookmarkItemType type;
   std::string keyword;
   base::Time date_added;
   int64 favicon;
+  bool empty_folder;
 };
 
 Firefox3Importer::Firefox3Importer() {
@@ -104,10 +114,8 @@
     return;
 
   sqlite3* sqlite;
-  if (sqlite3_open(WideToUTF8(file.ToWStringHack()).c_str(),
-                   &sqlite) != SQLITE_OK) {
+  if (sqlite_utils::OpenSqliteDb(file, &sqlite) != SQLITE_OK)
     return;
-  }
   sqlite_utils::scoped_sqlite_db_ptr db(sqlite);
 
   SQLStatement s;
@@ -153,10 +161,8 @@
     return;
 
   sqlite3* sqlite;
-  if (sqlite3_open(WideToUTF8(file.ToWStringHack()).c_str(),
-                   &sqlite) != SQLITE_OK) {
+  if (sqlite_utils::OpenSqliteDb(file, &sqlite) != SQLITE_OK)
     return;
-  }
   sqlite_utils::scoped_sqlite_db_ptr db(sqlite);
 
   // Get the bookmark folders that we are interested in.
@@ -180,7 +186,7 @@
   GetTopBookmarkFolder(db.get(), unsorted_folder_id, &list);
   size_t count = list.size();
   for (size_t i = 0; i < count; ++i)
-    GetWholeBookmarkFolder(db.get(), &list, i);
+    GetWholeBookmarkFolder(db.get(), &list, i, NULL);
 
   std::vector<ProfileWriter::BookmarkEntry> bookmarks;
   std::vector<TemplateURL*> template_urls;
@@ -207,13 +213,21 @@
   for (size_t i = 0; i < list.size(); ++i) {
     BookmarkItem* item = list[i];
 
-    // The type of bookmark items is 1.
-    if (item->type != 1)
+    if (item->type == TYPE_FOLDER) {
+      // Folders are added implicitly on adding children,
+      // so now we pass only empty folders to add them explicitly.
+      if (!item->empty_folder)
+        continue;
+    } else if (item->type == TYPE_BOOKMARK) {
+      // Import only valid bookmarks
+      if (!CanImportURL(item->url))
+        continue;
+    } else {
       continue;
+    }
 
     // Skip the default bookmarks and unwanted URLs.
-    if (!CanImportURL(item->url) ||
-        default_urls.find(item->url) != default_urls.end() ||
+    if (default_urls.find(item->url) != default_urls.end() ||
         post_keyword_ids.find(item->id) != post_keyword_ids.end())
       continue;
 
@@ -261,6 +275,7 @@
     entry.url = item->url;
     entry.path = path;
     entry.in_toolbar = is_in_toolbar;
+    entry.is_folder = item->type == TYPE_FOLDER;
 
     bookmarks.push_back(entry);
 
@@ -300,10 +315,8 @@
 void Firefox3Importer::ImportPasswords() {
   // Initializes NSS3.
   NSSDecryptor decryptor;
-  if (!decryptor.Init(source_path_.ToWStringHack(),
-                      source_path_.ToWStringHack()) &&
-      !decryptor.Init(app_path_.ToWStringHack(),
-                      source_path_.ToWStringHack())) {
+  if (!decryptor.Init(source_path_, source_path_) &&
+      !decryptor.Init(app_path_, source_path_)) {
     return;
   }
 
@@ -356,10 +369,8 @@
     return;
 
   sqlite3* sqlite;
-  if (sqlite3_open(WideToUTF8(file.ToWStringHack()).c_str(),
-                   &sqlite) != SQLITE_OK) {
+  if (sqlite_utils::OpenSqliteDb(file, &sqlite) != SQLITE_OK)
     return;
-  }
   sqlite_utils::scoped_sqlite_db_ptr db(sqlite);
 
   SQLStatement s;
@@ -488,14 +499,16 @@
     item->parent = -1;  // The top level folder has no parent.
     item->id = folder_id;
     item->title = s.column_wstring(0);
-    item->type = 2;
+    item->type = TYPE_FOLDER;
     item->favicon = 0;
+    item->empty_folder = true;
     list->push_back(item);
   }
 }
 
 void Firefox3Importer::GetWholeBookmarkFolder(sqlite3* db, BookmarkList* list,
-                                              size_t position) {
+                                              size_t position,
+                                              bool* empty_folder) {
   if (position >= list->size()) {
     NOTREACHED();
     return;
@@ -520,12 +533,15 @@
     item->id = s.column_int(0);
     item->url = GURL(s.column_string(1));
     item->title = s.column_wstring(2);
-    item->type = s.column_int(3);
+    item->type = static_cast<BookmarkItemType>(s.column_int(3));
     item->keyword = s.column_string(4);
     item->date_added = Time::FromTimeT(s.column_int64(5)/1000000);
     item->favicon = s.column_int64(6);
+    item->empty_folder = true;
 
     temp_list.push_back(item);
+    if (empty_folder != NULL)
+      *empty_folder = false;
   }
 
   // Appends all items to the list.
@@ -533,8 +549,8 @@
        i != temp_list.end(); ++i) {
     list->push_back(*i);
     // Recursive add bookmarks in sub-folders.
-    if ((*i)->type == 2)
-      GetWholeBookmarkFolder(db, list, list->size() - 1);
+    if ((*i)->type == TYPE_FOLDER)
+      GetWholeBookmarkFolder(db, list, list->size() - 1, &(*i)->empty_folder);
   }
 }
 
diff --git a/chrome/browser/importer/firefox3_importer.h b/chrome/browser/importer/firefox3_importer.h
index fe3deb7..6530edc 100644
--- a/chrome/browser/importer/firefox3_importer.h
+++ b/chrome/browser/importer/firefox3_importer.h
@@ -62,7 +62,7 @@
 
   // Loads all children of the given folder, and appends them to the |list|.
   void GetWholeBookmarkFolder(sqlite3* db, BookmarkList* list,
-                              size_t position);
+                              size_t position, bool* empty_folder);
 
   // Loads the favicons given in the map from the database, loads the data,
   // and converts it into FaviconUsage structures.
diff --git a/chrome/browser/importer/firefox_importer_unittest.cc b/chrome/browser/importer/firefox_importer_unittest.cc
index 73c70a4..15bdb14 100644
--- a/chrome/browser/importer/firefox_importer_unittest.cc
+++ b/chrome/browser/importer/firefox_importer_unittest.cc
@@ -33,10 +33,9 @@
   db_path = db_path.AppendASCII("firefox2_profile");
 
   FFUnitTestDecryptorProxy decryptor_proxy;
-  ASSERT_TRUE(decryptor_proxy.Setup(nss_path.ToWStringHack()));
+  ASSERT_TRUE(decryptor_proxy.Setup(nss_path));
 
-  EXPECT_TRUE(decryptor_proxy.DecryptorInit(nss_path.ToWStringHack(),
-                                            db_path.ToWStringHack()));
+  EXPECT_TRUE(decryptor_proxy.DecryptorInit(nss_path, db_path));
   EXPECT_EQ(ASCIIToUTF16("hello"),
       decryptor_proxy.Decrypt("MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECBJ"
                               "M63MpT9rtBAjMCm7qo/EhlA=="));
@@ -59,10 +58,9 @@
   db_path = db_path.AppendASCII("firefox3_profile");
 
   FFUnitTestDecryptorProxy decryptor_proxy;
-  ASSERT_TRUE(decryptor_proxy.Setup(nss_path.ToWStringHack()));
+  ASSERT_TRUE(decryptor_proxy.Setup(nss_path));
 
-  EXPECT_TRUE(decryptor_proxy.DecryptorInit(nss_path.ToWStringHack(),
-                                            db_path.ToWStringHack()));
+  EXPECT_TRUE(decryptor_proxy.DecryptorInit(nss_path, db_path));
   EXPECT_EQ(ASCIIToUTF16("hello"),
       decryptor_proxy.Decrypt("MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECKa"
                               "jtRg4qFSHBAhv9luFkXgDJA=="));
@@ -87,18 +85,20 @@
   // Escaped characters in name.
   std::wstring folder_name;
   bool is_toolbar_folder;
+  Time folder_add_date;
   result = Firefox2Importer::ParseFolderNameFromLine(
       "<DT><H3 ADD_DATE=\"1207558707\" >&lt; &gt;"
       " &amp; &quot; &#39; \\ /</H3>",
-      charset, &folder_name, &is_toolbar_folder);
+      charset, &folder_name, &is_toolbar_folder, &folder_add_date);
   EXPECT_TRUE(result);
   EXPECT_EQ(L"< > & \" ' \\ /", folder_name);
   EXPECT_FALSE(is_toolbar_folder);
+  EXPECT_TRUE(Time::FromTimeT(1207558707) == folder_add_date);
 
   // Empty name and toolbar folder attribute.
   result = Firefox2Importer::ParseFolderNameFromLine(
       "<DT><H3 PERSONAL_TOOLBAR_FOLDER=\"true\"></H3>",
-      charset, &folder_name, &is_toolbar_folder);
+      charset, &folder_name, &is_toolbar_folder, &folder_add_date);
   EXPECT_TRUE(result);
   EXPECT_EQ(L"", folder_name);
   EXPECT_TRUE(is_toolbar_folder);
@@ -176,4 +176,125 @@
   EXPECT_EQ(L"", shortcut);
   EXPECT_EQ(L"", post_data);
   EXPECT_TRUE(Time() == add_date);
+
+  // Epiphany format.
+  result = Firefox2Importer::ParseMinimumBookmarkFromLine(
+      "<dt><a href=\"http://www.google.com/\">Google</a></dt>",
+      charset, &title, &url);
+  EXPECT_TRUE(result);
+  EXPECT_EQ(L"Google", title);
+  EXPECT_EQ("http://www.google.com/", url.spec());
+}
+
+TEST(FirefoxImporterTest, Firefox2BookmarkFileImport) {
+  FilePath path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+  path = path.AppendASCII("firefox2_importer");
+
+  // Import all bookmarks from a file which include an empty folder entry.
+  FilePath empty_folder_path = path.AppendASCII("empty_folder.html");
+  std::set<GURL> default_urls;
+  std::wstring first_folder_name;
+  Firefox2Importer* importer = new Firefox2Importer();
+  importer->AddRef();
+  std::vector<ProfileWriter::BookmarkEntry> bookmarks;
+  importer->ImportBookmarksFile(empty_folder_path, default_urls, false,
+                                first_folder_name, importer, &bookmarks,
+                                NULL, NULL);
+  EXPECT_EQ(3, static_cast<int>(bookmarks.size()));
+  std::vector<ProfileWriter::BookmarkEntry>::iterator it;
+  ProfileWriter::BookmarkEntry entry;
+  std::vector<std::wstring>::iterator path_it;
+  if (bookmarks.size() == 3) {
+    it = bookmarks.begin();
+    entry = *it++;
+    EXPECT_EQ(L"Empty", entry.title);
+    EXPECT_TRUE(entry.is_folder);
+    EXPECT_EQ(Time::FromTimeT(1295938143), entry.creation_time);
+    EXPECT_EQ(2, static_cast<int>(entry.path.size()));
+    if (entry.path.size() == 2) {
+      path_it = entry.path.begin();
+      EXPECT_EQ(L"", *path_it++);
+      EXPECT_EQ(L"Empty's Parent", *path_it);
+    }
+
+    entry = *it++;
+    EXPECT_EQ(L"[Tamura Yukari.com]", entry.title);
+    EXPECT_FALSE(entry.is_folder);
+    EXPECT_EQ(Time::FromTimeT(1234567890), entry.creation_time);
+    EXPECT_EQ(2, static_cast<int>(entry.path.size()));
+    if (entry.path.size() == 2) {
+      path_it = entry.path.begin();
+      EXPECT_EQ(L"", *path_it++);
+      EXPECT_EQ(L"Not Empty", *path_it);
+    }
+    EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
+
+    entry = *it++;
+    EXPECT_EQ(L"Google", entry.title);
+    EXPECT_FALSE(entry.is_folder);
+    EXPECT_EQ(Time::FromTimeT(0000000000), entry.creation_time);
+    EXPECT_EQ(2, static_cast<int>(entry.path.size()));
+    if (entry.path.size() == 2) {
+      path_it = entry.path.begin();
+      EXPECT_EQ(L"", *path_it++);
+      EXPECT_EQ(L"Not Empty But Default", *path_it);
+    }
+    EXPECT_EQ("http://www.google.com/", entry.url.spec());
+  }
+
+  // Import non-default bookmarks from a file.
+  bookmarks.clear();
+  default_urls.insert(GURL("http://www.google.com/"));
+  importer->ImportBookmarksFile(empty_folder_path, default_urls, false,
+                                first_folder_name, importer, &bookmarks,
+                                NULL, NULL);
+  EXPECT_EQ(2, static_cast<int>(bookmarks.size()));
+  if (bookmarks.size() == 2) {
+    it = bookmarks.begin();
+    entry = *it++;
+    EXPECT_EQ(L"Empty", entry.title);
+    EXPECT_TRUE(entry.is_folder);
+    EXPECT_EQ(Time::FromTimeT(1295938143), entry.creation_time);
+    EXPECT_EQ(2, static_cast<int>(entry.path.size()));
+    if (entry.path.size() == 2) {
+      path_it = entry.path.begin();
+      EXPECT_EQ(L"", *path_it++);
+      EXPECT_EQ(L"Empty's Parent", *path_it);
+    }
+
+    entry = *it++;
+    EXPECT_EQ(L"[Tamura Yukari.com]", entry.title);
+    EXPECT_FALSE(entry.is_folder);
+    EXPECT_EQ(Time::FromTimeT(1234567890), entry.creation_time);
+    EXPECT_EQ(2, static_cast<int>(entry.path.size()));
+    if (entry.path.size() == 2) {
+      path_it = entry.path.begin();
+      EXPECT_EQ(L"", *path_it++);
+      EXPECT_EQ(L"Not Empty", *path_it);
+    }
+    EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
+  }
+
+  // Import Epiphany bookmarks from a file
+  FilePath epiphany_path = path.AppendASCII("epiphany.html");
+  bookmarks.clear();
+  default_urls.clear();
+  importer->ImportBookmarksFile(epiphany_path, default_urls, false,
+                                first_folder_name, importer, &bookmarks,
+                                NULL, NULL);
+  EXPECT_EQ(2, static_cast<int>(bookmarks.size()));
+  if (bookmarks.size() == 2) {
+    it = bookmarks.begin();
+    entry = *it++;
+    EXPECT_EQ(L"[Tamura Yukari.com]", entry.title);
+    EXPECT_EQ("http://www.tamurayukari.com/", entry.url.spec());
+    EXPECT_EQ(0, static_cast<int>(entry.path.size()));
+    entry = *it++;
+    EXPECT_EQ(L"Google", entry.title);
+    EXPECT_EQ("http://www.google.com/", entry.url.spec());
+    EXPECT_EQ(0, static_cast<int>(entry.path.size()));
+  }
+
+  importer->Release();
 }
diff --git a/chrome/browser/importer/firefox_importer_unittest_messages_internal.h b/chrome/browser/importer/firefox_importer_unittest_messages_internal.h
index fd70f7f..b0e25c2 100644
--- a/chrome/browser/importer/firefox_importer_unittest_messages_internal.h
+++ b/chrome/browser/importer/firefox_importer_unittest_messages_internal.h
@@ -11,8 +11,8 @@
 
 // Server->Child: Initialize the decrytor with the following paramters.
 IPC_MESSAGE_CONTROL2(Msg_Decryptor_Init,
-                     std::wstring /* dll_path */,
-                     std::wstring /* db_path */)
+                     FilePath /* dll_path */,
+                     FilePath /* db_path */)
 // Child->Server: Return paramter from init call.
 IPC_MESSAGE_CONTROL1(Msg_Decryptor_InitReturnCode,
                      bool /* ret */)
diff --git a/chrome/browser/importer/firefox_importer_unittest_utils.h b/chrome/browser/importer/firefox_importer_unittest_utils.h
index 9a1df8d..9001f9a 100644
--- a/chrome/browser/importer/firefox_importer_unittest_utils.h
+++ b/chrome/browser/importer/firefox_importer_unittest_utils.h
@@ -35,10 +35,10 @@
 
   // Initialize a decryptor, returns true if the object was
   // constructed successfully.
-  bool Setup(const std::wstring& nss_path);
+  bool Setup(const FilePath& nss_path);
 
   // This match the parallel functions in NSSDecryptor.
-  bool DecryptorInit(const std::wstring& dll_path, const std::wstring& db_path);
+  bool DecryptorInit(const FilePath& dll_path, const FilePath& db_path);
   string16 Decrypt(const std::string& crypt);
 
  private:
@@ -68,12 +68,12 @@
 FFUnitTestDecryptorProxy::~FFUnitTestDecryptorProxy() {
 }
 
-bool FFUnitTestDecryptorProxy::Setup(const std::wstring& /* nss_path */) {
+bool FFUnitTestDecryptorProxy::Setup(const FilePath& nss_path) {
   return true;
 }
 
-bool FFUnitTestDecryptorProxy::DecryptorInit(const std::wstring& dll_path,
-    const std::wstring& db_path) {
+bool FFUnitTestDecryptorProxy::DecryptorInit(const FilePath& dll_path,
+                                             const FilePath& db_path) {
   return decryptor_.Init(dll_path, db_path);
 }
 
diff --git a/chrome/browser/importer/firefox_importer_unittest_utils_mac.cc b/chrome/browser/importer/firefox_importer_unittest_utils_mac.cc
index f27a53c..dbaf19a 100644
--- a/chrome/browser/importer/firefox_importer_unittest_utils_mac.cc
+++ b/chrome/browser/importer/firefox_importer_unittest_utils_mac.cc
@@ -29,19 +29,18 @@
 // |channel| - IPC Channel to use for communication.
 // |handle| - On return, the process handle to use to communicate with the
 // child.
-bool LaunchNSSDecrypterChildProcess(const std::wstring& nss_path,
+bool LaunchNSSDecrypterChildProcess(const FilePath& nss_path,
     const IPC::Channel& channel, base::ProcessHandle* handle) {
   CommandLine cl(*CommandLine::ForCurrentProcess());
   cl.AppendSwitchASCII(switches::kTestChildProcess, "NSSDecrypterChildProcess");
 
-  FilePath ff_dylib_dir = FilePath::FromWStringHack(nss_path);
   // Set env variable needed for FF encryption libs to load.
   // See "chrome/browser/importer/nss_decryptor_mac.mm" for an explanation of
   // why we need this.
   base::environment_vector env;
   std::pair<std::string, std::string> dyld_override;
   dyld_override.first = "DYLD_FALLBACK_LIBRARY_PATH";
-  dyld_override.second = ff_dylib_dir.value();
+  dyld_override.second = nss_path.value();
   env.push_back(dyld_override);
 
   base::file_handle_mapping_vector fds_to_map;
@@ -123,7 +122,7 @@
     : child_process_(0) {
 }
 
-bool FFUnitTestDecryptorProxy::Setup(const std::wstring& nss_path) {
+bool FFUnitTestDecryptorProxy::Setup(const FilePath& nss_path) {
   // Create a new message loop and spawn the child process.
   message_loop_.reset(new MessageLoopForIO());
 
@@ -185,8 +184,8 @@
   return ret;
 }
 
-bool FFUnitTestDecryptorProxy::DecryptorInit(const std::wstring& dll_path,
-    const std::wstring& db_path) {
+bool FFUnitTestDecryptorProxy::DecryptorInit(const FilePath& dll_path,
+                                             const FilePath& db_path) {
   channel_->Send(new Msg_Decryptor_Init(dll_path, db_path));
   bool ok = WaitForClientResponse();
   if (ok && listener_->got_result) {
@@ -219,7 +218,7 @@
     sender_ = sender;
   }
 
-  void OnDecryptor_Init(std::wstring dll_path, std::wstring db_path) {
+  void OnDecryptor_Init(FilePath dll_path, FilePath db_path) {
     bool ret = decryptor_.Init(dll_path, db_path);
     sender_->Send(new Msg_Decryptor_InitReturnCode(ret));
   }
diff --git a/chrome/browser/importer/firefox_importer_utils.cc b/chrome/browser/importer/firefox_importer_utils.cc
index be606ff..3ff88f2 100644
--- a/chrome/browser/importer/firefox_importer_utils.cc
+++ b/chrome/browser/importer/firefox_importer_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -312,7 +312,7 @@
   int default_se_index = -1;
   for (std::vector<TemplateURL*>::const_iterator iter = search_engines.begin();
        iter != search_engines.end(); ++iter) {
-    if (default_se_name == WideToUTF8((*iter)->short_name())) {
+    if (default_se_name == UTF16ToUTF8((*iter)->short_name())) {
       default_se_index = static_cast<int>(iter - search_engines.begin());
       break;
     }
diff --git a/chrome/browser/importer/firefox_importer_utils_win.cc b/chrome/browser/importer/firefox_importer_utils_win.cc
index 7fc2a41..16696b9 100644
--- a/chrome/browser/importer/firefox_importer_utils_win.cc
+++ b/chrome/browser/importer/firefox_importer_utils_win.cc
@@ -31,9 +31,9 @@
     base::win::RegKey reg_key(kFireFoxRegistryPaths[i],
                               L"Software\\Mozilla\\Mozilla Firefox", KEY_READ);
 
-    bool result = reg_key.ReadValue(L"CurrentVersion", ver_buffer,
+    LONG result = reg_key.ReadValue(L"CurrentVersion", ver_buffer,
                                     &ver_buffer_length, NULL);
-    if (!result)
+    if (result != ERROR_SUCCESS)
       continue;
     highest_version = std::max(highest_version, _wtoi(ver_buffer));
   }
@@ -47,9 +47,9 @@
   DWORD buffer_length = sizeof(buffer);
   base::win::RegKey reg_key(HKEY_LOCAL_MACHINE, registry_path.c_str(),
                             KEY_READ);
-  bool result = reg_key.ReadValue(L"CurrentVersion", buffer,
+  LONG result = reg_key.ReadValue(L"CurrentVersion", buffer,
                                   &buffer_length, NULL);
-  if (!result)
+  if (result != ERROR_SUCCESS)
     return std::wstring();
   registry_path += L"\\" + std::wstring(buffer) + L"\\Main";
   buffer_length = sizeof(buffer);
@@ -57,7 +57,7 @@
                                       registry_path.c_str(), KEY_READ);
   result = reg_key_directory.ReadValue(L"Install Directory", buffer,
                                        &buffer_length, NULL);
-  if (!result)
+  if (result != ERROR_SUCCESS)
     return std::wstring();
   return buffer;
 }
diff --git a/chrome/browser/importer/ie_importer.cc b/chrome/browser/importer/ie_importer.cc
index b26c306..d10453c 100644
--- a/chrome/browser/importer/ie_importer.cc
+++ b/chrome/browser/importer/ie_importer.cc
@@ -15,7 +15,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "app/win/scoped_co_mem.h"
 #include "app/win/scoped_com_initializer.h"
 #include "base/file_path.h"
@@ -40,6 +39,7 @@
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/glue/password_form.h"
 
 using base::Time;
@@ -75,7 +75,7 @@
                              uint16 items,
                              ImporterBridge* bridge) {
   bridge_ = bridge;
-  source_path_ = profile_info.source_path.ToWStringHack();
+  source_path_ = profile_info.source_path.value();
 
   bridge_->NotifyStarted();
 
@@ -263,19 +263,18 @@
   base::win::RegKey key(HKEY_CURRENT_USER, kStorage2Path, KEY_READ);
   base::win::RegistryValueIterator reg_iterator(HKEY_CURRENT_USER,
                                                 kStorage2Path);
+  IE7PasswordInfo password_info;
   while (reg_iterator.Valid() && !cancelled()) {
     // Get the size of the encrypted data.
     DWORD value_len = 0;
-    if (key.ReadValue(reg_iterator.Name(), NULL, &value_len, NULL) &&
-        value_len) {
+    key.ReadValue(reg_iterator.Name(), NULL, &value_len, NULL);
+    if (value_len) {
       // Query the encrypted data.
-      std::vector<unsigned char> value;
-      value.resize(value_len);
-      if (key.ReadValue(reg_iterator.Name(), &value.front(), &value_len,
-                        NULL)) {
-        IE7PasswordInfo password_info;
+      password_info.encrypted_data.resize(value_len);
+      if (key.ReadValue(reg_iterator.Name(),
+                        &password_info.encrypted_data.front(),
+                        &value_len, NULL) == ERROR_SUCCESS) {
         password_info.url_hash = reg_iterator.Name();
-        password_info.encrypted_data = value;
         password_info.date_created = Time::Now();
 
         bridge_->AddIE7PasswordInfo(password_info);
@@ -366,7 +365,8 @@
     base::win::RegKey sub_key(HKEY_CURRENT_USER, sub_key_name.c_str(),
                               KEY_READ);
     std::wstring wide_url;
-    if (!sub_key.ReadValue(L"URL", &wide_url) || wide_url.empty()) {
+    if ((sub_key.ReadValue(L"URL", &wide_url) != ERROR_SUCCESS) ||
+        wide_url.empty()) {
       VLOG(1) << "No URL for IE search engine at " << key_iterator.Name();
       ++key_iterator;
       continue;
@@ -375,9 +375,10 @@
     // non displayable name in DisplayName, and the readable name under the
     // default value).
     std::wstring name;
-    if (!sub_key.ReadValue(NULL, &name) || name.empty()) {
+    if ((sub_key.ReadValue(NULL, &name) != ERROR_SUCCESS) || name.empty()) {
       // Try the displayable name.
-      if (!sub_key.ReadValue(L"DisplayName", &name) || name.empty()) {
+      if ((sub_key.ReadValue(L"DisplayName", &name) != ERROR_SUCCESS) ||
+          name.empty()) {
         VLOG(1) << "No name for IE search engine at " << key_iterator.Name();
         ++key_iterator;
         continue;
@@ -433,7 +434,8 @@
 
   base::win::RegKey key(HKEY_CURRENT_USER, kIESettingsMain, KEY_READ);
   std::wstring homepage_url;
-  if (!key.ReadValue(kIEHomepage, &homepage_url) || homepage_url.empty())
+  if (key.ReadValue(kIEHomepage, &homepage_url) != ERROR_SUCCESS ||
+      homepage_url.empty())
     return;
 
   GURL homepage = GURL(homepage_url);
@@ -443,8 +445,8 @@
   // Check to see if this is the default website and skip import.
   base::win::RegKey keyDefault(HKEY_LOCAL_MACHINE, kIESettingsMain, KEY_READ);
   std::wstring default_homepage_url;
-  if (keyDefault.ReadValue(kIEDefaultHomepage, &default_homepage_url) &&
-      !default_homepage_url.empty()) {
+  LONG result = keyDefault.ReadValue(kIEDefaultHomepage, &default_homepage_url);
+  if (result == ERROR_SUCCESS && !default_homepage_url.empty()) {
     if (homepage.spec() == GURL(default_homepage_url).spec())
       return;
   }
@@ -477,7 +479,8 @@
     DWORD buffer_length = sizeof(buffer);
     base::win::RegKey reg_key(HKEY_CURRENT_USER,
         L"Software\\Microsoft\\Internet Explorer\\Toolbar", KEY_READ);
-    if (!reg_key.ReadValue(L"LinksFolderName", buffer, &buffer_length, NULL))
+    if (reg_key.ReadValue(L"LinksFolderName", buffer,
+                          &buffer_length, NULL) != ERROR_SUCCESS)
       return false;
     info->links_folder = buffer;
   } else {
@@ -587,8 +590,8 @@
     DWORD buffer_length = sizeof(buffer);
     base::win::RegKey reg_key(HKEY_LOCAL_MACHINE,
         L"Software\\Microsoft\\Internet Explorer", KEY_READ);
-    bool result = reg_key.ReadValue(L"Version", buffer, &buffer_length, NULL);
-    version = (result ? _wtoi(buffer) : 0);
+    LONG result = reg_key.ReadValue(L"Version", buffer, &buffer_length, NULL);
+    version = ((result == ERROR_SUCCESS)? _wtoi(buffer) : 0);
   }
   return version;
 }
diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc
index d69aff4..03c72cf 100644
--- a/chrome/browser/importer/importer.cc
+++ b/chrome/browser/importer/importer.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/importer/importer.h"
 
-#include "app/l10n_util.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
@@ -19,24 +18,21 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/favicon_size.h"
 #include "grit/generated_resources.h"
 #include "skia/ext/image_operations.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/favicon_size.h"
 #include "webkit/glue/image_decoder.h"
 
 // TODO(port): Port these files.
 #if defined(OS_WIN)
-#include "app/win/win_util.h"
-#include "chrome/browser/views/importer_lock_view.h"
+#include "ui/base/message_box_win.h"
 #include "views/window/window.h"
-#elif defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/importer_lock_dialog.h"
-#elif defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/import_lock_dialog_gtk.h"
 #endif
 
 using webkit_glue::PasswordForm;
@@ -88,28 +84,13 @@
       installed_bookmark_observer_(false),
       is_source_readable_(true),
       headless_(false),
-      parent_window_(NULL),
-      importer_list_(new ImporterList) {
-  importer_list_->DetectSourceProfilesHack();
-}
-
-ImporterHost::ImporterHost(ImporterList::Observer* observer)
-    : profile_(NULL),
-      observer_(NULL),
-      task_(NULL),
-      importer_(NULL),
-      waiting_for_bookmarkbar_model_(false),
-      installed_bookmark_observer_(false),
-      is_source_readable_(true),
-      headless_(false),
-      parent_window_(NULL),
-      importer_list_(new ImporterList) {
-  importer_list_->DetectSourceProfiles(observer);
+      parent_window_(NULL) {
 }
 
 ImporterHost::~ImporterHost() {
   if (NULL != importer_)
     importer_->Release();
+
   if (installed_bookmark_observer_) {
     DCHECK(profile_);  // Only way for waiting_for_bookmarkbar_model_ to be true
                        // is if we have a profile.
@@ -143,14 +124,7 @@
   if (headless_) {
     OnLockViewEnd(false);
   } else {
-#if defined(OS_WIN)
-    views::Window::CreateChromeWindow(NULL, gfx::Rect(),
-                                      new ImporterLockView(this))->Show();
-#elif defined(TOOLKIT_USES_GTK)
-    ImportLockDialogGtk::Show(parent_window_, this);
-#else
-    ImportLockDialogCocoa::ShowWarning(this);
-#endif
+    browser::ShowImportLockDialog(parent_window_, this);
   }
 }
 
@@ -212,7 +186,7 @@
   // credentials.
   if (profile_info.browser_type == importer::GOOGLE_TOOLBAR5) {
     if (!toolbar_importer_utils::IsGoogleGAIACookieInstalled()) {
-      app::win::MessageBox(
+      ui::MessageBox(
           NULL,
           UTF16ToWide(l10n_util::GetStringUTF16(
               IDS_IMPORTER_GOOGLE_LOGIN_TEXT)).c_str(),
@@ -326,15 +300,6 @@
       import_process_launched_(false) {
 }
 
-ExternalProcessImporterHost::ExternalProcessImporterHost(
-    ImporterList::Observer* observer)
-    : ImporterHost(observer),
-      items_(0),
-      import_to_bookmark_bar_(false),
-      cancelled_(false),
-      import_process_launched_(false) {
-}
-
 void ExternalProcessImporterHost::Loaded(BookmarkModel* model) {
   DCHECK(model->IsLoaded());
   model->RemoveObserver(this);
@@ -410,7 +375,7 @@
       items_(items),
       import_to_bookmark_bar_(import_to_bookmark_bar),
       bridge_(bridge),
-      cancelled_(FALSE) {
+      cancelled_(false) {
   bridge_->AddRef();
   process_importer_host_->ImportStarted();
 }
diff --git a/chrome/browser/importer/importer.h b/chrome/browser/importer/importer.h
index e994036..179d68b 100644
--- a/chrome/browser/importer/importer.h
+++ b/chrome/browser/importer/importer.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -21,7 +21,7 @@
 #include "chrome/browser/profile_import_process_host.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 using importer::ImportItem;
 using importer::ProfileInfo;
@@ -76,15 +76,8 @@
     virtual ~Observer() {}
   };
 
-  // DEPRECATED: Calls the synchronous version of
-  // ImporterList::DetectSourceProfiles.
-  // TODO(jhawkins): Remove this constructor once all callers are fixed.
-  // See http://crbug.com/65633 and http://crbug.com/65638.
   ImporterHost();
 
-  // |observer| must not be NULL.
-  explicit ImporterHost(ImporterList::Observer* observer);
-
   // BookmarkModelObserver implementation.
   virtual void Loaded(BookmarkModel* model);
   virtual void BookmarkNodeMoved(BookmarkModel* model,
@@ -162,33 +155,6 @@
   virtual void ImportItemEnded(importer::ImportItem item);
   virtual void ImportEnded();
 
-  int GetAvailableProfileCount() const {
-    return importer_list_->GetAvailableProfileCount();
-  }
-
-  // Returns the name of the profile at the 'index' slot. The profiles are
-  // ordered such that the profile at index 0 is the likely default browser.
-  std::wstring GetSourceProfileNameAt(int index) const {
-    return importer_list_->GetSourceProfileNameAt(index);
-  }
-
-  // Returns the ProfileInfo at the specified index.  The ProfileInfo should be
-  // passed to StartImportSettings().
-  const importer::ProfileInfo& GetSourceProfileInfoAt(int index) const {
-    return importer_list_->GetSourceProfileInfoAt(index);
-  }
-
-  // Returns the ProfileInfo with the given browser type.
-  const importer::ProfileInfo& GetSourceProfileInfoForBrowserType(
-      int browser_type) const {
-    return importer_list_->GetSourceProfileInfoForBrowserType(browser_type);
-  }
-
-  // Returns true if the source profiles have been loaded.
-  bool source_profiles_loaded() const {
-    return importer_list_->source_profiles_loaded();
-  }
-
  protected:
   friend class base::RefCountedThreadSafe<ImporterHost>;
 
@@ -255,24 +221,15 @@
   // complete.
   virtual void InvokeTaskIfDone();
 
-  // Used to create an importer of the appropriate type.
-  scoped_refptr<ImporterList> importer_list_;
-
   DISALLOW_COPY_AND_ASSIGN(ImporterHost);
 };
 
-// This class manages the import process.  It creates the in-process half of
-// the importer bridge and the external process importer client.
+// This class manages the import process.  It creates the in-process half of the
+// importer bridge and the external process importer client.
 class ExternalProcessImporterHost : public ImporterHost {
  public:
-  // DEPRECATED: Calls the deprecated ImporterHost constructor.
-  // TODO(jhawkins): Remove this constructor once all callers are fixed.
-  // See http://crbug.com/65633 and http://crbug.com/65638.
   ExternalProcessImporterHost();
 
-  // |observer| must not be NULL.
-  explicit ExternalProcessImporterHost(ImporterList::Observer* observer);
-
   // Called when the BookmarkModel has finished loading. Calls InvokeTaskIfDone
   // to start importing.
   virtual void Loaded(BookmarkModel* model);
diff --git a/chrome/browser/importer/importer_bridge.cc b/chrome/browser/importer/importer_bridge.cc
index 588e365..2fb48a7 100644
--- a/chrome/browser/importer/importer_bridge.cc
+++ b/chrome/browser/importer/importer_bridge.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/importer/importer_bridge.h"
 
-#include "app/l10n_util.h"
 #include "base/scoped_ptr.h"
 #include "base/string_number_conversions.h"
 #include "base/string16.h"
@@ -19,6 +18,7 @@
 #include "chrome/common/child_thread.h"
 #include "chrome/browser/importer/importer_messages.h"
 #include "chrome/profile_import/profile_import_thread.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/glue/password_form.h"
 
 ImporterBridge::ImporterBridge() { }
@@ -128,8 +128,7 @@
     : profile_import_thread_(profile_import_thread) {
   // Bridge needs to make its own copy because OS 10.6 autoreleases the
   // localized_strings value that is passed in (see http://crbug.com/46003 ).
-  localized_strings_.reset(
-      static_cast<DictionaryValue*>(localized_strings.DeepCopy()));
+  localized_strings_.reset(localized_strings.DeepCopy());
 }
 
 void ExternalProcessImporterBridge::AddBookmarkEntries(
diff --git a/chrome/browser/importer/importer_list.cc b/chrome/browser/importer/importer_list.cc
index 9574f95..a47e9b4 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/importer/importer_list.h"
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/stl_util-inl.h"
 #include "base/values.h"
@@ -17,6 +16,7 @@
 #include "chrome/browser/importer/toolbar_importer.h"
 #include "chrome/browser/shell_integration.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/importer/ie_importer.h"
@@ -146,6 +146,7 @@
 ImporterList::ImporterList()
     : source_thread_id_(BrowserThread::UI),
       observer_(NULL),
+      is_observed_(false),
       source_profiles_loaded_(false) {
 }
 
@@ -155,6 +156,7 @@
 void ImporterList::DetectSourceProfiles(Observer* observer) {
   DCHECK(observer);
   observer_ = observer;
+  is_observed_ = true;
 
   BrowserThread::GetCurrentThreadIdentifier(&source_thread_id_);
 
@@ -164,6 +166,10 @@
       NewRunnableMethod(this, &ImporterList::DetectSourceProfilesWorker));
 }
 
+void ImporterList::SetObserver(Observer* observer) {
+  observer_ = observer;
+}
+
 void ImporterList::DetectSourceProfilesHack() {
   DetectSourceProfilesWorker();
 }
@@ -205,8 +211,8 @@
 
 void ImporterList::DetectSourceProfilesWorker() {
   // TODO(jhawkins): Remove this condition once DetectSourceProfileHack is
-  // removed. |observer_| is NULL when said method is called.
-  if (observer_)
+  // removed.
+  if (is_observed_)
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   std::vector<importer::ProfileInfo*> profiles;
@@ -236,8 +242,8 @@
 #endif
 
   // TODO(jhawkins): Remove this condition once DetectSourceProfileHack is
-  // removed. |observer_| is NULL when said method is called.
-  if (observer_) {
+  // removed.
+  if (is_observed_) {
     BrowserThread::PostTask(
         source_thread_id_,
         FROM_HERE,
@@ -250,7 +256,9 @@
 
 void ImporterList::SourceProfilesLoaded(
     const std::vector<importer::ProfileInfo*>& profiles) {
-  DCHECK_NE(static_cast<Observer*>(NULL), observer_);
+  // |observer_| may be NULL if it removed itself before being notified.
+  if (!observer_)
+    return;
 
   BrowserThread::ID current_thread_id;
   BrowserThread::GetCurrentThreadIdentifier(&current_thread_id);
@@ -258,7 +266,11 @@
 
   source_profiles_->assign(profiles.begin(), profiles.end());
   source_profiles_loaded_ = true;
+  source_thread_id_ = BrowserThread::UI;
+
   observer_->SourceProfilesLoaded();
   observer_ = NULL;
-  source_thread_id_ = BrowserThread::UI;
+
+  // TODO(jhawkins): Remove once DetectSourceProfileHack is removed.
+  is_observed_ = false;
 }
diff --git a/chrome/browser/importer/importer_list.h b/chrome/browser/importer/importer_list.h
index 513a55f..e82764b 100644
--- a/chrome/browser/importer/importer_list.h
+++ b/chrome/browser/importer/importer_list.h
@@ -41,6 +41,11 @@
   // non-NULL.
   void DetectSourceProfiles(Observer* observer);
 
+  // Sets the observer of this object. When the current observer is destroyed,
+  // this method should be called with a NULL |observer| so it is not notified
+  // after destruction.
+  void SetObserver(Observer* observer);
+
   // DEPRECATED: This method is synchronous and performs file operations which
   // may end up blocking the current thread, which is usually the UI thread.
   void DetectSourceProfilesHack();
@@ -90,6 +95,12 @@
   // SourceProfilesLoaded() has returned.
   Observer* observer_;
 
+  // True if |observer_| is set during the lifetime of source profile detection.
+  // This hack is necessary in order to not use |observer_| != NULL as a method
+  // of determining whether this object is being observed or not.
+  // TODO(jhawkins): Remove once DetectSourceProfilesHack() is removed.
+  bool is_observed_;
+
   // True if source profiles are loaded.
   bool source_profiles_loaded_;
 
diff --git a/chrome/browser/importer/importer_messages.h b/chrome/browser/importer/importer_messages.h
index e05aac8..ac63526 100644
--- a/chrome/browser/importer/importer_messages.h
+++ b/chrome/browser/importer/importer_messages.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -222,7 +222,7 @@
     WriteParam(m, p.url);
   }
   static bool Read(const Message* m, void** iter, param_type* p) {
-    std::wstring type;
+    std::string type;
     int width;
     int height;
     GURL url;
@@ -275,17 +275,17 @@
     WriteParam(m, p.prepopulate_id());
   }
   static bool Read(const Message* m, void** iter, param_type* p) {
-    std::wstring short_name;
-    std::wstring description;
+    string16 short_name;
+    string16 description;
     bool includes_suggestions_url;
     TemplateURLRef suggestions_url;
     TemplateURLRef url;
     GURL originating_url;
-    std::wstring keyword;
+    string16 keyword;
     bool autogenerate_keyword;
     bool show_in_default_list;
     bool safe_for_autoreplace;
-    std::vector<std::wstring> languages;
+    std::vector<string16> languages;
     std::vector<std::string> input_encodings;
     base::Time date_created;
     int usage_count;
@@ -314,7 +314,7 @@
 
     *p = TemplateURL();
     for (size_t i = 0; i < image_refs_size; ++i) {
-      std::wstring type;
+      std::string type;
       int width;
       int height;
       GURL url;
@@ -344,7 +344,7 @@
     p->set_show_in_default_list(show_in_default_list);
     p->set_safe_for_autoreplace(safe_for_autoreplace);
 
-    std::vector<std::wstring>::const_iterator lang_iter;
+    std::vector<string16>::const_iterator lang_iter;
     for (lang_iter = languages.begin();
          lang_iter != languages.end();
          ++lang_iter) {
diff --git a/chrome/browser/importer/importer_unittest.cc b/chrome/browser/importer/importer_unittest.cc
index 595a3d7..cfca4de 100644
--- a/chrome/browser/importer/importer_unittest.cc
+++ b/chrome/browser/importer/importer_unittest.cc
@@ -114,7 +114,7 @@
     profile_info.browser_type = FIREFOX3;
     profile_info.app_path = app_path_;
     profile_info.source_path = profile_path_;
-    scoped_refptr<ImporterHost> host(new ImporterHost());
+    scoped_refptr<ImporterHost> host(new ImporterHost);
     host->SetObserver(observer);
     int items = HISTORY | PASSWORDS | FAVORITES;
     if (import_search_plugins)
@@ -416,7 +416,7 @@
 
   // Starts to import the above settings.
   MessageLoop* loop = MessageLoop::current();
-  scoped_refptr<ImporterHost> host = new ImporterHost();
+  scoped_refptr<ImporterHost> host(new ImporterHost);
 
   TestObserver* observer = new TestObserver();
   host->SetObserver(observer);
@@ -637,9 +637,10 @@
       // The order might not be deterministic, look in the expected list for
       // that template URL.
       bool found = false;
-      std::wstring keyword = template_urls[i]->keyword();
+      string16 keyword = template_urls[i]->keyword();
       for (size_t j = 0; j < arraysize(kFirefox2Keywords); ++j) {
-        if (template_urls[i]->keyword() == kFirefox2Keywords[j].keyword) {
+        if (template_urls[i]->keyword() ==
+            WideToUTF16Hack(kFirefox2Keywords[j].keyword)) {
           EXPECT_EQ(kFirefox2Keywords[j].url, template_urls[i]->url()->url());
           found = true;
           break;
@@ -652,7 +653,7 @@
     if (default_keyword_index != -1) {
       EXPECT_LT(default_keyword_index, static_cast<int>(template_urls.size()));
       TemplateURL* default_turl = template_urls[default_keyword_index];
-      default_keyword_ = default_turl->keyword();
+      default_keyword_ = UTF16ToWideHack(default_turl->keyword());
       default_keyword_url_ = default_turl->url()->url();
     }
 
@@ -695,7 +696,7 @@
   ASSERT_TRUE(file_util::CopyDirectory(data_path, search_engine_path, false));
 
   MessageLoop* loop = MessageLoop::current();
-  scoped_refptr<ImporterHost> host(new ImporterHost());
+  scoped_refptr<ImporterHost> host(new ImporterHost);
   FirefoxObserver* observer = new FirefoxObserver();
   host->SetObserver(observer);
   ProfileInfo profile_info;
@@ -844,9 +845,10 @@
       // The order might not be deterministic, look in the expected list for
       // that template URL.
       bool found = false;
-      std::wstring keyword = template_urls[i]->keyword();
+      string16 keyword = template_urls[i]->keyword();
       for (size_t j = 0; j < arraysize(kFirefox3Keywords); ++j) {
-        if (template_urls[i]->keyword() == kFirefox3Keywords[j].keyword) {
+        if (template_urls[i]->keyword() ==
+            WideToUTF16Hack(kFirefox3Keywords[j].keyword)) {
           EXPECT_EQ(kFirefox3Keywords[j].url, template_urls[i]->url()->url());
           found = true;
           break;
@@ -859,7 +861,7 @@
     if (default_keyword_index != -1) {
       EXPECT_LT(default_keyword_index, static_cast<int>(template_urls.size()));
       TemplateURL* default_turl = template_urls[default_keyword_index];
-      default_keyword_ = default_turl->keyword();
+      default_keyword_ = UTF16ToWideHack(default_turl->keyword());
       default_keyword_url_ = default_turl->url()->url();
     }
 
diff --git a/chrome/browser/importer/nss_decryptor_mac.h b/chrome/browser/importer/nss_decryptor_mac.h
index 5e0eeff..e88fd11 100644
--- a/chrome/browser/importer/nss_decryptor_mac.h
+++ b/chrome/browser/importer/nss_decryptor_mac.h
@@ -120,8 +120,7 @@
   ~NSSDecryptor();
 
   // Initializes NSS if it hasn't already been initialized.
-  bool Init(const std::wstring& /* dll_path */,
-            const std::wstring& /* db_path */);
+  bool Init(const FilePath& dll_path, const FilePath& db_path);
 
   // Decrypts Firefox stored passwords. Before using this method,
   // make sure Init() returns true.
@@ -152,9 +151,6 @@
   PK11SDRDecryptFunc PK11SDR_Decrypt;
   SECITEMFreeItemFunc SECITEM_FreeItem;
 
-  // Libraries necessary for decrypting the passwords.
-  static const wchar_t kNSS3Library[];
-
   // True if NSS_Init() has been called
   bool is_nss_initialized_;
 
diff --git a/chrome/browser/importer/nss_decryptor_mac.mm b/chrome/browser/importer/nss_decryptor_mac.mm
index 988ab56..d9d3d7a 100644
--- a/chrome/browser/importer/nss_decryptor_mac.mm
+++ b/chrome/browser/importer/nss_decryptor_mac.mm
@@ -13,25 +13,20 @@
 #include "chrome/browser/importer/nss_decryptor_mac.h"
 #include "chrome/browser/importer/firefox_importer_utils.h"
 
-// static
-const wchar_t NSSDecryptor::kNSS3Library[] = L"libnss3.dylib";
-
 // Important!! : On OS X the nss3 libraries are compiled with depedencies
 // on one another, referenced using dyld's @executable_path directive.
 // To make a long story short in order to get the libraries to load, dyld's
 // fallback path needs to be set to the directory containing the libraries.
 // To do so, the process this function runs in must have the
 // DYLD_FALLBACK_LIBRARY_PATH set on startup to said directory.
-bool NSSDecryptor::Init(const std::wstring& dll_path,
-                        const std::wstring& db_path) {
+bool NSSDecryptor::Init(const FilePath& dll_path, const FilePath& db_path) {
   if (getenv("DYLD_FALLBACK_LIBRARY_PATH") == NULL) {
     LOG(ERROR) << "DYLD_FALLBACK_LIBRARY_PATH variable not set";
     return false;
   }
-  FilePath dylib_file_path = FilePath::FromWStringHack(dll_path);
-  FilePath nss3_path = dylib_file_path.Append("libnss3.dylib");
+  FilePath nss3_path = dll_path.Append("libnss3.dylib");
 
-  void *nss_3_lib = dlopen(nss3_path.value().c_str(), RTLD_LAZY);
+  void* nss_3_lib = dlopen(nss3_path.value().c_str(), RTLD_LAZY);
   if (!nss_3_lib) {
     LOG(ERROR) << "Failed to load nss3 lib" << dlerror();
     return false;
@@ -56,7 +51,7 @@
     return false;
   }
 
-  SECStatus result = NSS_Init(base::SysWideToNativeMB(db_path).c_str());
+  SECStatus result = NSS_Init(db_path.value().c_str());
 
   if (result != SECSuccess) {
     LOG(ERROR) << "NSS_Init Failed returned: " << result;
diff --git a/chrome/browser/importer/nss_decryptor_null.h b/chrome/browser/importer/nss_decryptor_null.h
index 155f1e0..af725c1 100644
--- a/chrome/browser/importer/nss_decryptor_null.h
+++ b/chrome/browser/importer/nss_decryptor_null.h
@@ -23,8 +23,7 @@
 class NSSDecryptor {
  public:
   NSSDecryptor() {}
-  bool Init(const std::wstring& /* dll_path */,
-            const std::wstring& db_path) { return false; }
+  bool Init(const FilePath& dll_path, const FilePath& db_path) { return false; }
   string16 Decrypt(const std::string& crypt) const { return string16(); }
   void ParseSignons(const std::string& content,
                     std::vector<webkit_glue::PasswordForm>* forms) {}
diff --git a/chrome/browser/importer/nss_decryptor_system_nss.cc b/chrome/browser/importer/nss_decryptor_system_nss.cc
index 06be5da..58ce34e 100644
--- a/chrome/browser/importer/nss_decryptor_system_nss.cc
+++ b/chrome/browser/importer/nss_decryptor_system_nss.cc
@@ -8,6 +8,7 @@
 #include <pk11sdr.h>
 
 #include "base/basictypes.h"
+#include "base/file_path.h"
 #include "base/nss_util.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
@@ -23,13 +24,12 @@
   }
 }
 
-bool NSSDecryptor::Init(const std::wstring& /* dll_path */,
-                        const std::wstring& db_path) {
+bool NSSDecryptor::Init(const FilePath& dll_path, const FilePath& db_path) {
   base::EnsureNSSInit();
   is_nss_initialized_ = true;
   const std::string modspec =
       StringPrintf("configDir='%s' tokenDescription='Firefox NSS database' "
-                   "flags=readOnly", base::SysWideToNativeMB(db_path).c_str());
+                   "flags=readOnly", db_path.value().c_str());
   db_slot_ = SECMOD_OpenUserDB(modspec.c_str());
   return db_slot_ != NULL;
 }
diff --git a/chrome/browser/importer/nss_decryptor_system_nss.h b/chrome/browser/importer/nss_decryptor_system_nss.h
index c08496d..b4087d9 100644
--- a/chrome/browser/importer/nss_decryptor_system_nss.h
+++ b/chrome/browser/importer/nss_decryptor_system_nss.h
@@ -26,8 +26,7 @@
   ~NSSDecryptor();
 
   // Initializes NSS if it hasn't already been initialized.
-  bool Init(const std::wstring& /* dll_path */,
-            const std::wstring& db_path);
+  bool Init(const FilePath& dll_path, const FilePath& db_path);
 
   // Decrypts Firefox stored passwords. Before using this method,
   // make sure Init() returns true.
diff --git a/chrome/browser/importer/nss_decryptor_win.cc b/chrome/browser/importer/nss_decryptor_win.cc
index a7b5592..bb1b2d4 100644
--- a/chrome/browser/importer/nss_decryptor_win.cc
+++ b/chrome/browser/importer/nss_decryptor_win.cc
@@ -37,8 +37,7 @@
 const wchar_t NSSDecryptor::kPLDS4Library[] = L"plds4.dll";
 const wchar_t NSSDecryptor::kNSPR4Library[] = L"nspr4.dll";
 
-bool NSSDecryptor::Init(const std::wstring& dll_path,
-                        const std::wstring& db_path) {
+bool NSSDecryptor::Init(const FilePath& dll_path, const FilePath& db_path) {
   // We call SetDllDirectory to work around a Purify bug (GetModuleHandle
   // fails inside Purify under certain conditions).  SetDllDirectory only
   // exists on Windows XP SP1 or later, so we look up its address at run time.
@@ -50,7 +49,7 @@
   SetDllDirectoryCaller caller;
 
   if (set_dll_directory != NULL) {
-    if (!set_dll_directory(dll_path.c_str()))
+    if (!set_dll_directory(dll_path.value().c_str()))
       return false;
     caller.set_func(set_dll_directory);
     nss3_dll_ = LoadLibrary(kNSS3Library);
@@ -60,7 +59,7 @@
     // Fall back on LoadLibraryEx if SetDllDirectory isn't available.  We
     // actually prefer this method because it doesn't change the DLL search
     // path, which is a process-wide property.
-    FilePath path = FilePath(dll_path).Append(kNSS3Library);
+    FilePath path = dll_path.Append(kNSS3Library);
     nss3_dll_ = LoadLibraryEx(path.value().c_str(), NULL,
                               LOAD_WITH_ALTERED_SEARCH_PATH);
     if (nss3_dll_ == NULL)
@@ -103,7 +102,7 @@
   Free();
 }
 
-bool NSSDecryptor::InitNSS(const std::wstring& db_path,
+bool NSSDecryptor::InitNSS(const FilePath& db_path,
                            base::NativeLibrary plds4_dll,
                            base::NativeLibrary nspr4_dll) {
   // NSPR DLLs are already loaded now.
@@ -142,7 +141,7 @@
     return false;
   }
 
-  SECStatus result = NSS_Init(base::SysWideToNativeMB(db_path).c_str());
+  SECStatus result = NSS_Init(base::SysWideToNativeMB(db_path.value()).c_str());
   if (result != SECSuccess) {
     Free();
     return false;
diff --git a/chrome/browser/importer/nss_decryptor_win.h b/chrome/browser/importer/nss_decryptor_win.h
index 0436323..23e7b1a 100644
--- a/chrome/browser/importer/nss_decryptor_win.h
+++ b/chrome/browser/importer/nss_decryptor_win.h
@@ -117,7 +117,7 @@
   // Loads NSS3 library and returns true if successful.
   // |dll_path| indicates the location of NSS3 DLL files, and |db_path|
   // is the location of the database file that stores the keys.
-  bool Init(const std::wstring& dll_path, const std::wstring& db_path);
+  bool Init(const FilePath& dll_path, const FilePath& db_path);
 
   // Frees the libraries.
   void Free();
@@ -139,8 +139,8 @@
                            std::vector<webkit_glue::PasswordForm>* forms);
 
  private:
-  // Performs tasks common across all platforms to initialize NSS.
-  bool InitNSS(const std::wstring& db_path,
+  // Call NSS initialization funcs.
+  bool InitNSS(const FilePath& db_path,
                base::NativeLibrary plds4_dll,
                base::NativeLibrary nspr4_dll);
 
diff --git a/chrome/browser/importer/profile_writer.cc b/chrome/browser/importer/profile_writer.cc
index 00e8dcf..1ea2c46 100644
--- a/chrome/browser/importer/profile_writer.cc
+++ b/chrome/browser/importer/profile_writer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,7 +19,8 @@
 
 using webkit_glue::PasswordForm;
 
-ProfileWriter::BookmarkEntry::BookmarkEntry() : in_toolbar(false) {}
+ProfileWriter::BookmarkEntry::BookmarkEntry() : in_toolbar(false),
+    is_folder(false) {}
 
 ProfileWriter::BookmarkEntry::~BookmarkEntry() {}
 
@@ -82,7 +83,7 @@
   for (std::vector<BookmarkEntry>::const_iterator it = bookmark.begin();
        it != bookmark.end(); ++it) {
     // Don't insert this url if it isn't valid.
-    if (!it->url.is_valid())
+    if (!it->is_folder && !it->url.is_valid())
       continue;
 
     // We suppose that bookmarks are unique by Title, URL, and Folder.  Since
@@ -119,8 +120,13 @@
       parent = child;
     }
     groups_added_to.insert(parent);
-    model->AddURLWithCreationTime(parent, parent->GetChildCount(),
-        WideToUTF16Hack(it->title), it->url, it->creation_time);
+    if (it->is_folder) {
+      model->AddGroup(parent, parent->GetChildCount(),
+                      WideToUTF16Hack(it->title));
+    } else {
+      model->AddURLWithCreationTime(parent, parent->GetChildCount(),
+          WideToUTF16Hack(it->title), it->url, it->creation_time);
+    }
 
     // If some items are put into toolbar, it looks like the user was using
     // it in their last browser. We turn on the bookmarks toolbar.
@@ -181,8 +187,8 @@
     if (t_url->url()->SupportsReplacement()) {
       return HostPathKeyForURL(GURL(
           t_url->url()->ReplaceSearchTerms(
-          *t_url, L"random string",
-          TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring())));
+          *t_url, ASCIIToUTF16("random string"),
+          TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())));
     }
   }
   return std::string();
diff --git a/chrome/browser/importer/profile_writer.h b/chrome/browser/importer/profile_writer.h
index 5c0e25c..3002b1a 100644
--- a/chrome/browser/importer/profile_writer.h
+++ b/chrome/browser/importer/profile_writer.h
@@ -56,6 +56,7 @@
     ~BookmarkEntry();
 
     bool in_toolbar;
+    bool is_folder;
     GURL url;
     std::vector<std::wstring> path;
     std::wstring title;
diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc
index 57a0a14..da76fa2 100644
--- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc
+++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc
@@ -10,10 +10,10 @@
 #include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h"
 #include "chrome/common/indexed_db_key.h"
 #include "chrome/common/serialized_script_value.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
 #include "webkit/glue/webkit_glue.h"
 
 BrowserWebKitClientImpl::BrowserWebKitClientImpl() {
@@ -147,19 +147,10 @@
   return file_util::Delete(path, false) ? 0 : 1;
 }
 
-void BrowserWebKitClientImpl::idbShutdown() {
-  if (indexed_db_key_utility_client_.get())
-    indexed_db_key_utility_client_->EndUtilityProcess();
-}
-
 void BrowserWebKitClientImpl::createIDBKeysFromSerializedValuesAndKeyPath(
     const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values,
     const WebKit::WebString& keyPath,
     WebKit::WebVector<WebKit::WebIDBKey>& keys) {
-  if (!indexed_db_key_utility_client_.get()) {
-    indexed_db_key_utility_client_ = new IndexedDBKeyUtilityClient();
-    indexed_db_key_utility_client_->StartUtilityProcess();
-  }
 
   std::vector<SerializedScriptValue> std_values;
   size_t size = values.size();
@@ -168,8 +159,9 @@
     std_values.push_back(SerializedScriptValue(values[i]));
 
   std::vector<IndexedDBKey> std_keys;
-  indexed_db_key_utility_client_->CreateIDBKeysFromSerializedValuesAndKeyPath(
-      std_values, keyPath, &std_keys);
+  IndexedDBKeyUtilityClient::
+      CreateIDBKeysFromSerializedValuesAndKeyPath(std_values, keyPath,
+                                                  &std_keys);
 
   keys = std_keys;
 }
diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h
index bc0dd5d..54ada73 100644
--- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h
+++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_IN_PROCESS_WEBKIT_BROWSER_WEBKITCLIENT_IMPL_H_
 #pragma once
 
-#include "base/ref_counted.h"
 #include "webkit/glue/webfileutilities_impl.h"
 #include "webkit/glue/webkitclient_impl.h"
 
@@ -49,7 +48,6 @@
   virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
   virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
                                  bool sync_dir);
-  virtual void idbShutdown();
   virtual void createIDBKeysFromSerializedValuesAndKeyPath(
       const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values,
       const WebKit::WebString& keyPath,
@@ -57,7 +55,6 @@
 
  private:
   webkit_glue::WebFileUtilitiesImpl file_utilities_;
-  scoped_refptr<IndexedDBKeyUtilityClient> indexed_db_key_utility_client_;
 };
 
 #endif  // CHROME_BROWSER_IN_PROCESS_WEBKIT_BROWSER_WEBKITCLIENT_IMPL_H_
diff --git a/chrome/browser/in_process_webkit/dom_storage_area.cc b/chrome/browser/in_process_webkit/dom_storage_area.cc
index fdf2ebc..d2953a2 100644
--- a/chrome/browser/in_process_webkit/dom_storage_area.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_area.cc
@@ -9,10 +9,10 @@
 #include "chrome/browser/in_process_webkit/dom_storage_context.h"
 #include "chrome/browser/in_process_webkit/dom_storage_namespace.h"
 #include "chrome/common/render_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageArea.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebSecurityOrigin;
diff --git a/chrome/browser/in_process_webkit/dom_storage_area.h b/chrome/browser/in_process_webkit/dom_storage_area.h
index cf5a0c7..950a2d2 100644
--- a/chrome/browser/in_process_webkit/dom_storage_area.h
+++ b/chrome/browser/in_process_webkit/dom_storage_area.h
@@ -13,7 +13,7 @@
 #include "base/string16.h"
 #include "chrome/common/dom_storage_common.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageArea.h"
 
 class DOMStorageNamespace;
 class HostContentSettingsMap;
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.cc b/chrome/browser/in_process_webkit/dom_storage_context.cc
index 1d6d627..45eae2a 100644
--- a/chrome/browser/in_process_webkit/dom_storage_context.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_context.cc
@@ -15,8 +15,8 @@
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/common/dom_storage_common.h"
 #include "chrome/common/url_constants.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebSecurityOrigin;
@@ -49,20 +49,6 @@
 const FilePath::CharType DOMStorageContext::kLocalStorageExtension[] =
     FILE_PATH_LITERAL(".localstorage");
 
-static const FilePath::CharType kLocalStorageOldPath[] =
-    FILE_PATH_LITERAL("localStorage");
-
-// TODO(jorlow): Remove after Chrome 4 ships.
-static void MigrateLocalStorageDirectory(const FilePath& data_path) {
-  FilePath new_path = data_path.Append(
-      DOMStorageContext::kLocalStorageDirectory);
-  FilePath old_path = data_path.Append(kLocalStorageOldPath);
-  if (!file_util::DirectoryExists(new_path) &&
-      file_util::DirectoryExists(old_path)) {
-    file_util::Move(old_path, new_path);
-  }
-}
-
 DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context)
     : last_storage_area_id_(0),
       last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId),
@@ -258,10 +244,8 @@
 
 DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() {
   FilePath dir_path;
-  if (!data_path_.empty()) {
-    MigrateLocalStorageDirectory(data_path_);
+  if (!data_path_.empty())
     dir_path = data_path_.Append(kLocalStorageDirectory);
-  }
   DOMStorageNamespace* new_namespace =
       DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
   RegisterStorageNamespace(new_namespace);
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.h b/chrome/browser/in_process_webkit/dom_storage_context.h
index 68993f4..7b88671 100644
--- a/chrome/browser/in_process_webkit/dom_storage_context.h
+++ b/chrome/browser/in_process_webkit/dom_storage_context.h
@@ -30,6 +30,11 @@
   explicit DOMStorageContext(WebKitContext* webkit_context);
   virtual ~DOMStorageContext();
 
+  // Invalid storage id.  No storage session will ever report this value.
+  // Used in DOMStorageMessageFilter::OnStorageAreaId when coping with
+  // interactions with non-existent storage sessions.
+  static const int64 kInvalidStorageId = -1;
+
   // Allocate a new storage area id.  Only call on the WebKit thread.
   int64 AllocateStorageAreaId();
 
diff --git a/chrome/browser/in_process_webkit/dom_storage_message_filter.cc b/chrome/browser/in_process_webkit/dom_storage_message_filter.cc
index 8b91c4c..eaaff5c 100644
--- a/chrome/browser/in_process_webkit/dom_storage_message_filter.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_message_filter.cc
@@ -102,9 +102,8 @@
   return handled;
 }
 
-void DOMStorageMessageFilter::BadMessageReceived() {
-  UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_DSMF"));
-  BrowserMessageFilter::BadMessageReceived();
+void DOMStorageMessageFilter::OnDestruct() const {
+  BrowserThread::DeleteOnIOThread::Destruct(this);
 }
 
 void DOMStorageMessageFilter::OverrideThreadForMessage(
@@ -122,7 +121,7 @@
   DOMStorageNamespace* storage_namespace =
       Context()->GetStorageNamespace(namespace_id, true);
   if (!storage_namespace) {
-    BadMessageReceived();
+    *storage_area_id = DOMStorageContext::kInvalidStorageId;
     return;
   }
   DOMStorageArea* storage_area = storage_namespace->GetStorageArea(
@@ -135,10 +134,10 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DOMStorageArea* storage_area = Context()->GetStorageArea(storage_area_id);
   if (!storage_area) {
-    BadMessageReceived();
-    return;
+    *length = 0;
+  } else {
+    *length = storage_area->Length();
   }
-  *length = storage_area->Length();
 }
 
 void DOMStorageMessageFilter::OnKey(int64 storage_area_id, unsigned index,
@@ -146,10 +145,10 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DOMStorageArea* storage_area = Context()->GetStorageArea(storage_area_id);
   if (!storage_area) {
-    BadMessageReceived();
-    return;
+    *key = NullableString16(true);
+  } else {
+    *key = storage_area->Key(index);
   }
-  *key = storage_area->Key(index);
 }
 
 void DOMStorageMessageFilter::OnGetItem(int64 storage_area_id,
@@ -158,10 +157,10 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DOMStorageArea* storage_area = Context()->GetStorageArea(storage_area_id);
   if (!storage_area) {
-    BadMessageReceived();
-    return;
+    *value = NullableString16(true);
+  } else {
+    *value = storage_area->GetItem(key);
   }
-  *value = storage_area->GetItem(key);
 }
 
 void DOMStorageMessageFilter::OnSetItem(
@@ -171,7 +170,8 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DOMStorageArea* storage_area = Context()->GetStorageArea(storage_area_id);
   if (!storage_area) {
-    BadMessageReceived();
+    *old_value = NullableString16(true);
+    *result = WebKit::WebStorageArea::ResultOK;
     return;
   }
 
@@ -196,7 +196,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DOMStorageArea* storage_area = Context()->GetStorageArea(storage_area_id);
   if (!storage_area) {
-    BadMessageReceived();
+    *old_value = NullableString16(true);
     return;
   }
 
@@ -209,7 +209,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DOMStorageArea* storage_area = Context()->GetStorageArea(storage_area_id);
   if (!storage_area) {
-    BadMessageReceived();
+    *something_cleared = false;
     return;
   }
 
diff --git a/chrome/browser/in_process_webkit/dom_storage_message_filter.h b/chrome/browser/in_process_webkit/dom_storage_message_filter.h
index bf56c04..a8e9368 100644
--- a/chrome/browser/in_process_webkit/dom_storage_message_filter.h
+++ b/chrome/browser/in_process_webkit/dom_storage_message_filter.h
@@ -35,6 +35,7 @@
                                         BrowserThread::ID* thread);
   virtual bool OnMessageReceived(const IPC::Message& message,
                                  bool* message_was_ok);
+  virtual void OnDestruct() const;
 
   // Only call on the WebKit thread.
   static void DispatchStorageEvent(const NullableString16& key,
@@ -42,12 +43,10 @@
       const string16& origin, const GURL& url, bool is_local_storage);
 
  private:
-  friend class base::RefCountedThreadSafe<DOMStorageMessageFilter>;
+  friend class BrowserThread;
+  friend class DeleteTask<DOMStorageMessageFilter>;
   ~DOMStorageMessageFilter();
 
-  // BrowserMessageFilter override.
-  virtual void BadMessageReceived();
-
   // Message Handlers.
   void OnStorageAreaId(int64 namespace_id, const string16& origin,
                        int64* storage_area_id);
diff --git a/chrome/browser/in_process_webkit/dom_storage_namespace.cc b/chrome/browser/in_process_webkit/dom_storage_namespace.cc
index a663a05..8097405 100644
--- a/chrome/browser/in_process_webkit/dom_storage_namespace.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_namespace.cc
@@ -8,8 +8,8 @@
 #include "chrome/browser/in_process_webkit/dom_storage_area.h"
 #include "chrome/browser/in_process_webkit/dom_storage_context.h"
 #include "chrome/browser/in_process_webkit/dom_storage_message_filter.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebStorageNamespace.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageArea.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageNamespace.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebStorageArea;
diff --git a/chrome/browser/in_process_webkit/dom_storage_namespace.h b/chrome/browser/in_process_webkit/dom_storage_namespace.h
index be38e34..79fc0db 100644
--- a/chrome/browser/in_process_webkit/dom_storage_namespace.h
+++ b/chrome/browser/in_process_webkit/dom_storage_namespace.h
@@ -10,7 +10,7 @@
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
 #include "chrome/common/dom_storage_common.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 class DOMStorageArea;
 class DOMStorageContext;
diff --git a/chrome/browser/in_process_webkit/dom_storage_uitest.cc b/chrome/browser/in_process_webkit/dom_storage_uitest.cc
index 460d411..ac82728 100644
--- a/chrome/browser/in_process_webkit/dom_storage_uitest.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_uitest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/file_path.h"
 #include "base/file_util.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_layout_test.h"
@@ -78,7 +79,8 @@
     ASSERT_TRUE(tab->SetCookie(url, ""));
     ASSERT_TRUE(tab->NavigateToURL(url));
 
-    WaitUntilCookieNonEmpty(tab.get(), url, "cleared", action_max_timeout_ms());
+    WaitUntilCookieNonEmpty(tab.get(), url, "cleared",
+                            TestTimeouts::action_max_timeout_ms());
   }
 
   // Runs each test in an array of strings until it hits a NULL.
diff --git a/chrome/browser/in_process_webkit/indexed_db_browsertest.cc b/chrome/browser/in_process_webkit/indexed_db_browsertest.cc
index fea58e0..c0320f7 100644
--- a/chrome/browser/in_process_webkit/indexed_db_browsertest.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_browsertest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/testing_profile.h"
 #include "chrome/test/thread_test_helper.h"
@@ -49,39 +48,39 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_CursorTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
 }
 
-// TODO(hans): Keep an eye out for these tests going flaky. See crbug.com/63675.
-// Crashy, http://crbug.com/67422.
+// http://code.google.com/p/chromium/issues/detail?id=70773
 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_IndexTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
 }
 
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, KeyPathTest) {
+// http://code.google.com/p/chromium/issues/detail?id=70773
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_KeyPathTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
 }
 
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionGetTest) {
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_TransactionGetTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
 }
 
-// Crashy, http://crbug.com/68446.
+// http://code.google.com/p/chromium/issues/detail?id=70773
 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ObjectStoreTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
 }
 
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DatabaseTest) {
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_DatabaseTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
 }
 
-// Crashy, http://crbug.com/67422.
+// http://code.google.com/p/chromium/issues/detail?id=70773
 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_TransactionTest) {
   SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
 }
 
-// Crashy, http://crbug.com/66394.
+// http://code.google.com/p/chromium/issues/detail?id=70773
 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_DoesntHangTest) {
   SimpleTest(testUrl(FilePath(
       FILE_PATH_LITERAL("transaction_run_forever.html"))));
@@ -91,7 +90,7 @@
 
 // In proc browser test is needed here because ClearLocalState indirectly calls
 // WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) {
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ClearLocalState) {
   // Create test files.
   ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/chrome/browser/in_process_webkit/indexed_db_callbacks.cc b/chrome/browser/in_process_webkit/indexed_db_callbacks.cc
index 41ac4ed..c4584c6 100644
--- a/chrome/browser/in_process_webkit/indexed_db_callbacks.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_callbacks.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/in_process_webkit/indexed_db_callbacks.h"
 
+#include "chrome/common/indexed_db_messages.h"
+
 IndexedDBCallbacksBase::IndexedDBCallbacksBase(
     IndexedDBDispatcherHost* dispatcher_host,
     int32 response_id)
@@ -27,6 +29,10 @@
       response_id_, error.code(), error.message()));
 }
 
+void IndexedDBCallbacksBase::onBlocked() {
+  dispatcher_host_->Send(new IndexedDBMsg_CallbacksBlocked(response_id_));
+}
+
 void IndexedDBTransactionCallbacks::onAbort() {
   dispatcher_host_->Send(
       new IndexedDBMsg_TransactionCallbacksAbort(transaction_id_));
@@ -41,3 +47,31 @@
   dispatcher_host_->Send(
       new IndexedDBMsg_TransactionCallbacksTimeout(transaction_id_));
 }
+
+void IndexedDBCallbacks<WebKit::WebIDBCursor>::onSuccess(
+    WebKit::WebIDBCursor* idb_object) {
+  int32 object_id = dispatcher_host()->Add(idb_object);
+  dispatcher_host()->Send(
+      new IndexedDBMsg_CallbacksSuccessIDBCursor(response_id(), object_id));
+}
+
+void IndexedDBCallbacks<WebKit::WebIDBCursor>::onSuccess(
+    const WebKit::WebSerializedScriptValue& value) {
+  dispatcher_host()->Send(
+      new IndexedDBMsg_CallbacksSuccessSerializedScriptValue(
+          response_id(), SerializedScriptValue(value)));
+}
+
+void IndexedDBCallbacks<WebKit::WebIDBKey>::onSuccess(
+    const WebKit::WebIDBKey& value) {
+  dispatcher_host()->Send(
+      new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
+          response_id(), IndexedDBKey(value)));
+}
+
+void IndexedDBCallbacks<WebKit::WebSerializedScriptValue>::onSuccess(
+    const WebKit::WebSerializedScriptValue& value) {
+  dispatcher_host()->Send(
+      new IndexedDBMsg_CallbacksSuccessSerializedScriptValue(
+          response_id(), SerializedScriptValue(value)));
+}
diff --git a/chrome/browser/in_process_webkit/indexed_db_callbacks.h b/chrome/browser/in_process_webkit/indexed_db_callbacks.h
index 55bc77e..b900d15 100644
--- a/chrome/browser/in_process_webkit/indexed_db_callbacks.h
+++ b/chrome/browser/in_process_webkit/indexed_db_callbacks.h
@@ -9,12 +9,16 @@
 #include "base/basictypes.h"
 #include "base/ref_counted.h"
 #include "chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h"
-#include "chrome/common/indexed_db_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBCallbacks.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBCursor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBDatabaseError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBTransaction.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBTransactionCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBTransaction.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBTransactionCallbacks.h"
+
+class IndexedDBMsg_CallbacksSuccessIDBDatabase;
+class IndexedDBMsg_CallbacksSuccessIDBIndex;
+class IndexedDBMsg_CallbacksSuccessIDBObjectStore;
+class IndexedDBMsg_CallbacksSuccessIDBTransaction;
 
 // Template magic to figure out what message to send to the renderer based on
 // which (overloaded) onSuccess method we expect to be called.
@@ -41,6 +45,7 @@
   virtual ~IndexedDBCallbacksBase();
 
   virtual void onError(const WebKit::WebIDBDatabaseError& error);
+  virtual void onBlocked();
 
  protected:
   IndexedDBDispatcherHost* dispatcher_host() const {
@@ -85,16 +90,8 @@
       IndexedDBDispatcherHost* dispatcher_host, int32 response_id)
       : IndexedDBCallbacksBase(dispatcher_host, response_id) { }
 
-  virtual void onSuccess(WebKit::WebIDBCursor* idb_object) {
-    int32 object_id = dispatcher_host()->Add(idb_object);
-    dispatcher_host()->Send(
-        new IndexedDBMsg_CallbacksSuccessIDBCursor(response_id(), object_id));
-  }
-
-  virtual void onSuccess() {
-    dispatcher_host()->Send(new IndexedDBMsg_CallbacksSuccessNull(
-        response_id()));
-  }
+  virtual void onSuccess(WebKit::WebIDBCursor* idb_object);
+  virtual void onSuccess(const WebKit::WebSerializedScriptValue& value);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBCallbacks);
@@ -111,11 +108,7 @@
       IndexedDBDispatcherHost* dispatcher_host, int32 response_id)
       : IndexedDBCallbacksBase(dispatcher_host, response_id) { }
 
-  virtual void onSuccess(const WebKit::WebIDBKey& value) {
-    dispatcher_host()->Send(
-        new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
-            response_id(), IndexedDBKey(value)));
-  }
+  virtual void onSuccess(const WebKit::WebIDBKey& value);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBCallbacks);
@@ -132,28 +125,7 @@
       IndexedDBDispatcherHost* dispatcher_host, int32 response_id)
       : IndexedDBCallbacksBase(dispatcher_host, response_id) { }
 
-  virtual void onSuccess(const WebKit::WebSerializedScriptValue& value) {
-    dispatcher_host()->Send(
-        new IndexedDBMsg_CallbacksSuccessSerializedScriptValue(
-            response_id(), SerializedScriptValue(value)));
-  }
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBCallbacks);
-};
-
-// A WebIDBCallbacks implementation that doesn't return a result.
-template <>
-class IndexedDBCallbacks<void> : public IndexedDBCallbacksBase {
- public:
-  IndexedDBCallbacks(
-      IndexedDBDispatcherHost* dispatcher_host, int32 response_id)
-      : IndexedDBCallbacksBase(dispatcher_host, response_id) { }
-
-  virtual void onSuccess() {
-    dispatcher_host()->Send(
-        new IndexedDBMsg_CallbacksSuccessNull(response_id()));
-  }
+  virtual void onSuccess(const WebKit::WebSerializedScriptValue& value);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBCallbacks);
diff --git a/chrome/browser/in_process_webkit/indexed_db_context.cc b/chrome/browser/in_process_webkit/indexed_db_context.cc
index 86aa5fd..e2872a4 100644
--- a/chrome/browser/in_process_webkit/indexed_db_context.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_context.cc
@@ -11,11 +11,11 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/common/url_constants.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBDatabase.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBFactory.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebIDBDatabase;
diff --git a/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.cc b/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.cc
index 1463ab5..fad4720 100644
--- a/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.cc
@@ -18,17 +18,17 @@
 #include "chrome/common/indexed_db_messages.h"
 #include "chrome/common/result_codes.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDOMStringList.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBCursor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBDatabase.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBDatabaseError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBKeyRange.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBIndex.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBFactory.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBObjectStore.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBTransaction.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMStringList.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyRange.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBIndex.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBObjectStore.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBTransaction.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebDOMStringList;
@@ -131,26 +131,46 @@
 }
 
 int32 IndexedDBDispatcherHost::Add(WebIDBCursor* idb_cursor) {
+  if (!cursor_dispatcher_host_.get()) {
+    delete idb_cursor;
+    return 0;
+  }
   return cursor_dispatcher_host_->map_.Add(idb_cursor);
 }
 
 int32 IndexedDBDispatcherHost::Add(WebIDBDatabase* idb_database) {
+  if (!database_dispatcher_host_.get()) {
+    delete idb_database;
+    return 0;
+  }
   return database_dispatcher_host_->map_.Add(idb_database);
 }
 
 int32 IndexedDBDispatcherHost::Add(WebIDBIndex* idb_index) {
+  if (!index_dispatcher_host_.get())  {
+    delete idb_index;
+    return 0;
+  }
   if (!idb_index)
     return 0;
   return index_dispatcher_host_->map_.Add(idb_index);
 }
 
 int32 IndexedDBDispatcherHost::Add(WebIDBObjectStore* idb_object_store) {
+  if (!object_store_dispatcher_host_.get()) {
+    delete idb_object_store;
+    return 0;
+  }
   if (!idb_object_store)
     return 0;
   return object_store_dispatcher_host_->map_.Add(idb_object_store);
 }
 
 int32 IndexedDBDispatcherHost::Add(WebIDBTransaction* idb_transaction) {
+  if (!transaction_dispatcher_host_.get()) {
+    delete idb_transaction;
+    return 0;
+  }
   int32 id = transaction_dispatcher_host_->map_.Add(idb_transaction);
   idb_transaction->setCallbacks(new IndexedDBTransactionCallbacks(this, id));
   return id;
@@ -267,6 +287,7 @@
                         OnDeleteObjectStore)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetVersion, OnSetVersion)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseTransaction, OnTransaction)
+    IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
@@ -380,7 +401,14 @@
   *idb_transaction_id = *ec ? 0 : parent_->Add(transaction);
 }
 
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed(
+void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
+    int32 idb_database_id) {
+  WebIDBDatabase* database = parent_->GetOrTerminateProcess(
+      &map_, idb_database_id);
+  database->close();
+}
+
+ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed(
     int32 object_id) {
   parent_->DestroyObject(&map_, object_id);
 }
@@ -556,6 +584,7 @@
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStoreGet, OnGet)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStorePut, OnPut)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStoreDelete, OnDelete)
+    IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStoreClear, OnClear)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStoreCreateIndex, OnCreateIndex)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStoreIndex, OnIndex)
     IPC_MESSAGE_HANDLER(IndexedDBHostMsg_ObjectStoreDeleteIndex, OnDeleteIndex)
@@ -630,7 +659,7 @@
   *ec = 0;
   scoped_ptr<WebIDBCallbacks> callbacks(
       new IndexedDBCallbacks<WebIDBKey>(parent_, params.response_id));
-  idb_object_store->put(params.serialized_value, params.key, params.add_only,
+  idb_object_store->put(params.serialized_value, params.key, params.put_mode,
                         callbacks.release(), *idb_transaction, *ec);
 }
 
@@ -650,11 +679,30 @@
 
   *ec = 0;
   scoped_ptr<WebIDBCallbacks> callbacks(
-      new IndexedDBCallbacks<void>(parent_, response_id));
+      new IndexedDBCallbacks<WebSerializedScriptValue>(parent_, response_id));
   idb_object_store->deleteFunction(
       key, callbacks.release(), *idb_transaction, *ec);
 }
 
+void IndexedDBDispatcherHost::ObjectStoreDispatcherHost::OnClear(
+    int idb_object_store_id,
+    int32 response_id,
+    int32 transaction_id,
+    WebKit::WebExceptionCode* ec) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
+  WebIDBObjectStore* idb_object_store = parent_->GetOrTerminateProcess(
+      &map_, idb_object_store_id);
+  WebIDBTransaction* idb_transaction = parent_->GetOrTerminateProcess(
+      &parent_->transaction_dispatcher_host_->map_, transaction_id);
+  if (!idb_transaction || !idb_object_store)
+    return;
+
+  *ec = 0;
+  scoped_ptr<WebIDBCallbacks> callbacks(
+      new IndexedDBCallbacks<WebSerializedScriptValue>(parent_, response_id));
+  idb_object_store->clear(callbacks.release(), *idb_transaction, *ec);
+}
+
 void IndexedDBDispatcherHost::ObjectStoreDispatcherHost::OnCreateIndex(
    const IndexedDBHostMsg_ObjectStoreCreateIndex_Params& params,
    int32* index_id, WebKit::WebExceptionCode* ec) {
@@ -812,7 +860,7 @@
 
   *ec = 0;
   idb_cursor->update(
-      value, new IndexedDBCallbacks<void>(parent_, response_id), *ec);
+      value, new IndexedDBCallbacks<WebIDBKey>(parent_, response_id), *ec);
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
@@ -841,7 +889,8 @@
 
   *ec = 0;
   // TODO(jorlow): This should be delete.
-  idb_cursor->remove(new IndexedDBCallbacks<void>(parent_, response_id), *ec);
+  idb_cursor->remove(
+      new IndexedDBCallbacks<WebSerializedScriptValue>(parent_, response_id), *ec);
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(
diff --git a/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h b/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h
index ff21529..0d83c69 100644
--- a/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h
+++ b/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h
@@ -10,7 +10,7 @@
 #include "base/id_map.h"
 #include "chrome/browser/browser_message_filter.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebExceptionCode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h"
 
 class HostContentSettingsMap;
 class IndexedDBKey;
@@ -105,6 +105,7 @@
                        int32 mode, int32 timeout,
                        int32* idb_transaction_id,
                        WebKit::WebExceptionCode* ec);
+    void OnClose(int32 idb_database_id);
     void OnDestroyed(int32 idb_database_id);
 
     IndexedDBDispatcherHost* parent_;
@@ -168,6 +169,10 @@
                   const IndexedDBKey& key,
                   int32 transaction_id,
                   WebKit::WebExceptionCode* ec);
+    void OnClear(int idb_object_store_id,
+                 int32 response_id,
+                 int32 transaction_id,
+                 WebKit::WebExceptionCode* ec);
     void OnCreateIndex(
         const IndexedDBHostMsg_ObjectStoreCreateIndex_Params& params,
         int32* index_id,
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
index f708b43..e70b2a3 100644
--- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
@@ -4,25 +4,155 @@
 
 #include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h"
 
-#include <vector>
-
+#include "base/lazy_instance.h"
+#include "base/synchronization/waitable_event.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/utility_process_host.h"
 #include "chrome/common/indexed_db_key.h"
 #include "chrome/common/serialized_script_value.h"
 
+// This class is used to obtain IndexedDBKeys from SerializedScriptValues
+// given an IDBKeyPath. It uses UtilityProcess to do this inside a sandbox
+// (a V8 lock is required there). At this level, all methods are synchronous
+// as required by the caller. The public API is used on WEBKIT thread,
+// but internally it moves around to UI and IO as needed.
+class KeyUtilityClientImpl
+    : public base::RefCountedThreadSafe<KeyUtilityClientImpl> {
+ public:
+  KeyUtilityClientImpl();
+
+  // Starts the UtilityProcess. Must be called before any other method.
+  void StartUtilityProcess();
+
+  // Stops the UtilityProcess. No further keys can be created after this.
+  void Shutdown();
+
+  // Synchronously obtain the |keys| from |values| for the given |key_path|.
+  void CreateIDBKeysFromSerializedValuesAndKeyPath(
+      const std::vector<SerializedScriptValue>& values,
+      const string16& key_path,
+      std::vector<IndexedDBKey>* keys);
+
+ private:
+  class Client : public UtilityProcessHost::Client {
+   public:
+    explicit Client(KeyUtilityClientImpl* parent);
+
+    // UtilityProcessHost::Client
+    virtual void OnProcessCrashed(int exit_code);
+    virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
+        int id, const std::vector<IndexedDBKey>& keys);
+    virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id);
+
+   private:
+    KeyUtilityClientImpl* parent_;
+
+    DISALLOW_COPY_AND_ASSIGN(Client);
+  };
+
+  friend class base::RefCountedThreadSafe<KeyUtilityClientImpl>;
+  ~KeyUtilityClientImpl();
+
+  void GetRDHAndStartUtilityProcess();
+  void StartUtilityProcessInternal(ResourceDispatcherHost* rdh);
+  void EndUtilityProcessInternal();
+  void CallStartIDBKeyFromValueAndKeyPathFromIOThread(
+      const std::vector<SerializedScriptValue>& values,
+      const string16& key_path);
+
+  void SetKeys(const std::vector<IndexedDBKey>& keys);
+  void FinishCreatingKeys();
+
+  base::WaitableEvent waitable_event_;
+
+  // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e.,
+  // these members are only set / read when the other thread is blocked.
+  enum State {
+    STATE_UNINITIALIZED,
+    STATE_INITIALIZED,
+    STATE_CREATING_KEYS,
+    STATE_SHUTDOWN,
+  };
+  State state_;
+  std::vector<IndexedDBKey> keys_;
+
+  // Used in the IO thread.
+  UtilityProcessHost* utility_process_host_;
+  scoped_refptr<Client> client_;
+
+  DISALLOW_COPY_AND_ASSIGN(KeyUtilityClientImpl);
+};
+
+// IndexedDBKeyUtilityClient definitions.
+
+static base::LazyInstance<IndexedDBKeyUtilityClient> client_instance(
+    base::LINKER_INITIALIZED);
+
 IndexedDBKeyUtilityClient::IndexedDBKeyUtilityClient()
+    : is_shutdown_(false) {
+  // Note that creating the impl_ object is deferred until it is first needed,
+  // as this class can be constructed even though it never gets used.
+}
+
+IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() {
+  DCHECK(!impl_ || is_shutdown_);
+}
+
+//  static
+void IndexedDBKeyUtilityClient::Shutdown() {
+  IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
+  if (!instance->impl_)
+    return;
+
+  instance->is_shutdown_ = true;
+  instance->impl_->Shutdown();
+}
+
+//  static
+void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
+      const std::vector<SerializedScriptValue>& values,
+      const string16& key_path,
+      std::vector<IndexedDBKey>* keys) {
+  IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
+
+  if (instance->is_shutdown_) {
+    keys->clear();
+    return;
+  }
+
+  if (!instance->impl_) {
+    instance->impl_ = new KeyUtilityClientImpl();
+    instance->impl_->StartUtilityProcess();
+  }
+
+  instance->impl_->CreateIDBKeysFromSerializedValuesAndKeyPath(values, key_path,
+                                                               keys);
+}
+
+// KeyUtilityClientImpl definitions.
+
+void KeyUtilityClientImpl::Shutdown() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  utility_process_host_->EndBatchMode();
+  utility_process_host_ = NULL;
+  client_ = NULL;
+  state_ = STATE_SHUTDOWN;
+}
+
+KeyUtilityClientImpl::KeyUtilityClientImpl()
     : waitable_event_(false, false),
       state_(STATE_UNINITIALIZED),
       utility_process_host_(NULL) {
 }
 
-IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() {
+KeyUtilityClientImpl::~KeyUtilityClientImpl() {
   DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_SHUTDOWN);
   DCHECK(!utility_process_host_);
   DCHECK(!client_.get());
 }
 
-void IndexedDBKeyUtilityClient::StartUtilityProcess() {
+void KeyUtilityClientImpl::StartUtilityProcess() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
   DCHECK(state_ == STATE_UNINITIALIZED);
 
@@ -32,21 +162,16 @@
   DCHECK(ret && state_ == STATE_INITIALIZED);
 }
 
-void IndexedDBKeyUtilityClient::EndUtilityProcess() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
-  DCHECK(state_ == STATE_INITIALIZED);
-
-  EndUtilityProcessInternal();
-  bool ret = waitable_event_.Wait();
-
-  DCHECK(ret && state_ == STATE_SHUTDOWN);
-}
-
-void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
+void KeyUtilityClientImpl::CreateIDBKeysFromSerializedValuesAndKeyPath(
     const std::vector<SerializedScriptValue>& values,
     const string16& key_path,
     std::vector<IndexedDBKey>* keys) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
+  if (state_ == STATE_SHUTDOWN) {
+    keys->clear();
+    return;
+  }
+
   DCHECK(state_ == STATE_INITIALIZED);
 
   state_ = STATE_CREATING_KEYS;
@@ -57,7 +182,7 @@
   *keys = keys_;
 }
 
-void IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess() {
+void KeyUtilityClientImpl::GetRDHAndStartUtilityProcess() {
   // In order to start the UtilityProcess, we need to grab
   // a pointer to the ResourceDispatcherHost. This can only
   // be done on the UI thread. See the comment at the top of
@@ -67,14 +192,14 @@
         BrowserThread::UI, FROM_HERE,
         NewRunnableMethod(
             this,
-            &IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess));
+            &KeyUtilityClientImpl::GetRDHAndStartUtilityProcess));
     return;
   }
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   StartUtilityProcessInternal(g_browser_process->resource_dispatcher_host());
 }
 
-void IndexedDBKeyUtilityClient::StartUtilityProcessInternal(
+void KeyUtilityClientImpl::StartUtilityProcessInternal(
     ResourceDispatcherHost* rdh) {
   DCHECK(rdh);
   // The ResourceDispatcherHost can only be used on the IO thread.
@@ -84,14 +209,14 @@
         BrowserThread::IO, FROM_HERE,
         NewRunnableMethod(
             this,
-            &IndexedDBKeyUtilityClient::StartUtilityProcessInternal,
+            &KeyUtilityClientImpl::StartUtilityProcessInternal,
             rdh));
     return;
   }
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(state_ == STATE_UNINITIALIZED);
 
-  client_ = new IndexedDBKeyUtilityClient::Client(this);
+  client_ = new KeyUtilityClientImpl::Client(this);
   utility_process_host_ = new UtilityProcessHost(
       rdh, client_.get(), BrowserThread::IO);
   utility_process_host_->StartBatchMode();
@@ -99,13 +224,13 @@
   waitable_event_.Signal();
 }
 
-void IndexedDBKeyUtilityClient::EndUtilityProcessInternal() {
+void KeyUtilityClientImpl::EndUtilityProcessInternal() {
   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         NewRunnableMethod(
             this,
-            &IndexedDBKeyUtilityClient::EndUtilityProcessInternal));
+            &KeyUtilityClientImpl::EndUtilityProcessInternal));
     return;
   }
 
@@ -116,14 +241,14 @@
   waitable_event_.Signal();
 }
 
-void IndexedDBKeyUtilityClient::CallStartIDBKeyFromValueAndKeyPathFromIOThread(
+void KeyUtilityClientImpl::CallStartIDBKeyFromValueAndKeyPathFromIOThread(
     const std::vector<SerializedScriptValue>& values,
     const string16& key_path) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         NewRunnableMethod(this,
-            &IndexedDBKeyUtilityClient::
+            &KeyUtilityClientImpl::
                 CallStartIDBKeyFromValueAndKeyPathFromIOThread,
             values, key_path));
     return;
@@ -134,33 +259,33 @@
       0, values, key_path);
 }
 
-void IndexedDBKeyUtilityClient::SetKeys(const std::vector<IndexedDBKey>& keys) {
+void KeyUtilityClientImpl::SetKeys(const std::vector<IndexedDBKey>& keys) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   keys_ = keys;
 }
 
-void IndexedDBKeyUtilityClient::FinishCreatingKeys() {
+void KeyUtilityClientImpl::FinishCreatingKeys() {
   DCHECK(state_ == STATE_CREATING_KEYS);
   state_ = STATE_INITIALIZED;
   waitable_event_.Signal();
 }
 
-IndexedDBKeyUtilityClient::Client::Client(IndexedDBKeyUtilityClient* parent)
+KeyUtilityClientImpl::Client::Client(KeyUtilityClientImpl* parent)
     : parent_(parent) {
 }
 
-void IndexedDBKeyUtilityClient::Client::OnProcessCrashed(int exit_code) {
+void KeyUtilityClientImpl::Client::OnProcessCrashed(int exit_code) {
   if (parent_->state_ == STATE_CREATING_KEYS)
     parent_->FinishCreatingKeys();
 }
 
-void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathSucceeded(
+void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathSucceeded(
     int id, const std::vector<IndexedDBKey>& keys) {
   parent_->SetKeys(keys);
   parent_->FinishCreatingKeys();
 }
 
-void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathFailed(
+void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathFailed(
     int id) {
   parent_->FinishCreatingKeys();
 }
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
index 3a79c28..b36aafa 100644
--- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
@@ -6,87 +6,43 @@
 #define CHROME_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_KEY_UTILITY_CLIENT_H_
 #pragma once
 
+#include <vector>
+
 #include "base/ref_counted.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/utility_process_host.h"
+#include "base/string16.h"
 
 class IndexedDBKey;
 class SerializedScriptValue;
+class KeyUtilityClientImpl;
 
-// This class is responsible to obtain IndexedDBKeys from the
-// SerializedScriptValues given an IDBKeyPath. It uses UtilityProcess to do this
-// inside a sandbox (a V8 lock is required there). At this level, all methods
-// are synchronous as required by the caller. The public API is used on
-// WEBKIT thread, but internally it moves around to UI and IO as needed.
-class IndexedDBKeyUtilityClient
-    : public base::RefCountedThreadSafe<IndexedDBKeyUtilityClient> {
+namespace base {
+template <typename T>
+struct DefaultLazyInstanceTraits;
+}  // namespace base
+
+// Class for obtaining IndexedDBKeys from the SerializedScriptValues given
+// an IDBKeyPath. This class is a thin singleton wrapper around the
+// KeyUtilityClientImpl, which does the real work.
+class IndexedDBKeyUtilityClient {
  public:
-  IndexedDBKeyUtilityClient();
-
-  // Starts the UtilityProcess. Must be called before any other method.
-  void StartUtilityProcess();
-
-  // Ends the UtilityProcess. Must be called after StartUtilityProcess() and
-  // before destruction.
-  // TODO(bulach): figure out an appropriate hook so that we can keep the
-  // UtilityProcess running for a longer period of time and avoid spinning it
-  // on every IDBObjectStore::Put call.
-  void EndUtilityProcess();
-
   // Synchronously obtain the |keys| from |values| for the given |key_path|.
-  void CreateIDBKeysFromSerializedValuesAndKeyPath(
+  static void CreateIDBKeysFromSerializedValuesAndKeyPath(
       const std::vector<SerializedScriptValue>& values,
       const string16& key_path,
       std::vector<IndexedDBKey>* keys);
 
+  // Shut down the underlying implementation. Must be called on the IO thread.
+  static void Shutdown();
+
  private:
-  class Client : public UtilityProcessHost::Client {
-   public:
-    explicit Client(IndexedDBKeyUtilityClient* parent);
-
-    // UtilityProcessHost::Client
-    virtual void OnProcessCrashed(int exit_code);
-    virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
-        int id, const std::vector<IndexedDBKey>& keys);
-    virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id);
-
-   private:
-    IndexedDBKeyUtilityClient* parent_;
-
-    DISALLOW_COPY_AND_ASSIGN(Client);
-  };
-
-  friend class base::RefCountedThreadSafe<IndexedDBKeyUtilityClient>;
+  friend struct base::DefaultLazyInstanceTraits<IndexedDBKeyUtilityClient>;
+  IndexedDBKeyUtilityClient();
   ~IndexedDBKeyUtilityClient();
 
-  void GetRDHAndStartUtilityProcess();
-  void StartUtilityProcessInternal(ResourceDispatcherHost* rdh);
-  void EndUtilityProcessInternal();
-  void CallStartIDBKeyFromValueAndKeyPathFromIOThread(
-      const std::vector<SerializedScriptValue>& values,
-      const string16& key_path);
+  bool is_shutdown_;
 
-  void SetKeys(const std::vector<IndexedDBKey>& keys);
-  void FinishCreatingKeys();
-
-  base::WaitableEvent waitable_event_;
-
-  // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e.,
-  // these members are only set / read when the other thread is blocked.
-  enum State {
-    STATE_UNINITIALIZED,
-    STATE_INITIALIZED,
-    STATE_CREATING_KEYS,
-    STATE_SHUTDOWN,
-  };
-  State state_;
-  std::vector<IndexedDBKey> keys_;
-
-  // Used in the IO thread.
-  UtilityProcessHost* utility_process_host_;
-  scoped_refptr<Client> client_;
-
-  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyUtilityClient);
+  // The real client; laziliy instantiated.
+  scoped_refptr<KeyUtilityClientImpl> impl_;
 };
 
 #endif  // CHROME_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_KEY_UTILITY_CLIENT_H_
diff --git a/chrome/browser/in_process_webkit/webkit_context.cc b/chrome/browser/in_process_webkit/webkit_context.cc
index 5022ad5..0c72346 100644
--- a/chrome/browser/in_process_webkit/webkit_context.cc
+++ b/chrome/browser/in_process_webkit/webkit_context.cc
@@ -7,7 +7,6 @@
 #include "base/command_line.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_switches.h"
 
 WebKitContext::WebKitContext(Profile* profile, bool clear_local_state_on_exit)
     : data_path_(profile->IsOffTheRecord() ? FilePath() : profile->GetPath()),
diff --git a/chrome/browser/in_process_webkit/webkit_thread.cc b/chrome/browser/in_process_webkit/webkit_thread.cc
index 8ff8174..b2b469b 100644
--- a/chrome/browser/in_process_webkit/webkit_thread.cc
+++ b/chrome/browser/in_process_webkit/webkit_thread.cc
@@ -7,7 +7,7 @@
 #include "base/command_line.h"
 #include "chrome/browser/in_process_webkit/browser_webkitclient_impl.h"
 #include "chrome/common/chrome_switches.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
 
 WebKitThread::WebKitThread() {
 }
diff --git a/chrome/browser/in_process_webkit/webkit_thread.h b/chrome/browser/in_process_webkit/webkit_thread.h
index 856007c..ed17434 100644
--- a/chrome/browser/in_process_webkit/webkit_thread.h
+++ b/chrome/browser/in_process_webkit/webkit_thread.h
@@ -7,7 +7,6 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
 #include "base/threading/thread.h"
 #include "chrome/browser/browser_thread.h"
diff --git a/chrome/browser/instant/instant_browsertest.cc b/chrome/browser/instant/instant_browsertest.cc
index 6eaca52..e9424b4 100644
--- a/chrome/browser/instant/instant_browsertest.cc
+++ b/chrome/browser/instant/instant_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,8 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_loader_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
@@ -18,10 +20,12 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 
+#define EXPECT_STR_EQ(ascii, utf16) \
+  EXPECT_EQ(ASCIIToWide(ascii), UTF16ToWide(utf16))
+
 class InstantTest : public InProcessBrowserTest {
  public:
   InstantTest()
@@ -31,6 +35,10 @@
     EnableDOMAutomation();
   }
 
+  void EnableInstant() {
+    InstantController::Enable(browser()->profile());
+  }
+
   void SetupInstantProvider(const std::string& page) {
     TemplateURLModel* model = browser()->profile()->GetTemplateURLModel();
     ASSERT_TRUE(model);
@@ -53,8 +61,8 @@
         page.c_str());
     template_url->SetURL(url, 0, 0);
     template_url->SetInstantURL(url, 0, 0);
-    template_url->set_keyword(UTF8ToWide("foo"));
-    template_url->set_short_name(UTF8ToWide("foo"));
+    template_url->set_keyword(ASCIIToUTF16("foo"));
+    template_url->set_short_name(ASCIIToUTF16("foo"));
 
     model->Add(template_url);
     model->SetDefaultSearchProvider(template_url);
@@ -74,7 +82,7 @@
   // Type a character to get instant to trigger.
   void SetupLocationBar() {
     FindLocationBar();
-    location_bar_->location_entry()->SetUserText(L"a");
+    location_bar_->location_entry()->SetUserText(ASCIIToUTF16("a"));
   }
 
   // Waits for preview to be shown.
@@ -100,22 +108,37 @@
 
     // When the page loads, the initial searchBox values are set and only a
     // resize will have been sent.
-    ASSERT_EQ("true 0 0 0 1 a false a false",
-        GetSearchStateAsString(preview_));
+    ASSERT_EQ("true 0 0 0 1 a false a false 1 1",
+              GetSearchStateAsString(preview_));
   }
 
   void SetLocationBarText(const std::wstring& text) {
     ASSERT_NO_FATAL_FAILURE(FindLocationBar());
-    location_bar_->location_entry()->SetUserText(text);
+    location_bar_->location_entry()->SetUserText(WideToUTF16Hack(text));
     ui_test_utils::WaitForNotification(
         NotificationType::INSTANT_CONTROLLER_SHOWN);
   }
 
-  void SendKey(app::KeyboardCode key) {
+  const string16& GetSuggestion() const {
+    return browser()->instant()->loader_manager_->
+        current_loader()->complete_suggested_text_;
+  }
+
+  void SendKey(ui::KeyboardCode key) {
     ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
         browser(), key, false, false, false, false));
   }
 
+  void SetSuggestionsJavascriptArgument(TabContents* tab_contents,
+                                        const std::string& argument) {
+    std::string script = StringPrintf(
+        "window.setSuggestionsArgument = %s;", argument.c_str());
+    ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
+        tab_contents->render_view_host(),
+        std::wstring(),
+        UTF8ToWide(script)));
+  }
+
   bool GetStringFromJavascript(TabContents* tab_contents,
                                const std::string& function,
                                std::string* result) {
@@ -157,6 +180,8 @@
   // window.beforeLoadSearchBox.verbatim
   // window.chrome.searchBox.value
   // window.chrome.searchBox.verbatim
+  // window.chrome.searchBox.selectionStart
+  // window.chrome.searchBox.selectionEnd
   // If determining any of the values fails, the value is 'fail'.
   std::string GetSearchStateAsString(TabContents* tab_contents) {
     bool sv = false;
@@ -164,6 +189,8 @@
     int oncancelcalls = 0;
     int onchangecalls = 0;
     int onresizecalls = 0;
+    int selection_start = 0;
+    int selection_end = 0;
     std::string before_load_value;
     bool before_load_verbatim = false;
     std::string value;
@@ -187,11 +214,17 @@
         !GetStringFromJavascript(tab_contents, "window.chrome.searchBox.value",
                                  &value) ||
         !GetBoolFromJavascript(tab_contents, "window.chrome.searchBox.verbatim",
-                               &verbatim)) {
+                               &verbatim) ||
+        !GetIntFromJavascript(tab_contents,
+                              "window.chrome.searchBox.selectionStart",
+                              &selection_start) ||
+        !GetIntFromJavascript(tab_contents,
+                              "window.chrome.searchBox.selectionEnd",
+                              &selection_end)) {
       return "fail";
     }
 
-    return StringPrintf("%s %d %d %d %d %s %s %s %s",
+    return StringPrintf("%s %d %d %d %d %s %s %s %s %d %d",
                         sv ? "true" : "false",
                         onsubmitcalls,
                         oncancelcalls,
@@ -200,7 +233,9 @@
                         before_load_value.c_str(),
                         before_load_verbatim ? "true" : "false",
                         value.c_str(),
-                        verbatim ? "true" : "false");
+                        verbatim ? "true" : "false",
+                        selection_start,
+                        selection_end);
   }
 
   void CheckStringValueFromJavascript(
@@ -238,37 +273,134 @@
   }
 
  protected:
-  virtual void SetUpCommandLine(CommandLine* command_line) {
-    command_line->AppendSwitch(switches::kEnablePredictiveInstant);
-  }
-
   LocationBar* location_bar_;
   TabContents* preview_;
 };
 
 // TODO(tonyg): Add the following tests:
-// 1. Test that setSuggestions() works.
-// 2. Test that the search box API is not populated for pages other than the
-//    default search provider.
-// 3. Test resize events.
+// - Test that the search box API is not populated for pages other than the
+//   default search provider.
+// - Test resize events.
 
 // Verify that the onchange event is dispatched upon typing in the box.
 IN_PROC_BROWSER_TEST_F(InstantTest, OnChangeEvent) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
   ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
   ASSERT_NO_FATAL_FAILURE(SetupPreview());
 
   ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
 
+  ASSERT_EQ(ASCIIToUTF16("abcdef"), location_bar_->location_entry()->GetText());
+
+  // Make sure the url that will get committed when we press enter matches that
+  // of the default search provider.
+  const TemplateURL* default_turl =
+      browser()->profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
+  ASSERT_TRUE(default_turl);
+  ASSERT_TRUE(default_turl->url());
+  EXPECT_EQ(default_turl->url()->ReplaceSearchTerms(
+                *default_turl, ASCIIToUTF16("abcdef"), 0, string16()),
+            browser()->instant()->GetCurrentURL().spec());
+
   // Check that the value is reflected and onchange is called.
-  EXPECT_EQ("true 0 0 1 1 a false abc false",
-      GetSearchStateAsString(preview_));
+  EXPECT_EQ("true 0 0 1 2 a false abc false 3 3",
+            GetSearchStateAsString(preview_));
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsArrayOfStrings) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(preview_, "['abcde', 'unused']");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("abcde", GetSuggestion());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptyArray) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(preview_, "[]");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("", GetSuggestion());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsValidJson) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(
+      preview_,
+      "{suggestions:[{value:'abcdefg'},{value:'unused'}]}");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("abcdefg", GetSuggestion());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsInvalidSuggestions) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(
+      preview_,
+      "{suggestions:{value:'abcdefg'}}");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("", GetSuggestion());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptyJson) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(preview_, "{}");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("", GetSuggestion());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptySuggestions) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(preview_, "{suggestions:[]}");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("", GetSuggestion());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptySuggestion) {
+  ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
+  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
+  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
+  ASSERT_NO_FATAL_FAILURE(SetupPreview());
+
+  SetSuggestionsJavascriptArgument(preview_, "{suggestions:[{}]}");
+  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
+  EXPECT_STR_EQ("", GetSuggestion());
 }
 
 // Verify instant preview is shown correctly for a non-search query.
 IN_PROC_BROWSER_TEST_F(InstantTest, ShowPreviewNonSearch) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   GURL url(test_server()->GetURL("files/instant/empty.html"));
   ASSERT_NO_FATAL_FAILURE(SetLocationBarText(UTF8ToWide(url.spec())));
   // The preview should be active and showing.
@@ -287,6 +419,7 @@
 // correctly.
 IN_PROC_BROWSER_TEST_F(InstantTest, NonSearchToSearch) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   GURL url(test_server()->GetURL("files/instant/empty.html"));
   ASSERT_NO_FATAL_FAILURE(SetLocationBarText(UTF8ToWide(url.spec())));
   // The preview should be active and showing.
@@ -301,7 +434,7 @@
 
   // Now type in some search text.
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
-  location_bar_->location_entry()->SetUserText(L"abc");
+  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("abc"));
 
   // Wait for the preview to navigate.
   ASSERT_NO_FATAL_FAILURE(WaitForPreviewToNavigate(false));
@@ -333,7 +466,7 @@
 
   // Reset the user text so that the page is told the text changed. We should be
   // able to nuke this once 66104 is fixed.
-  location_bar_->location_entry()->SetUserText(L"abcd");
+  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("abcd"));
 
   // Wait for the renderer to process it.
   ASSERT_NO_FATAL_FAILURE(
@@ -356,11 +489,21 @@
 
 // Makes sure that if the server doesn't support the instant API we don't show
 // anything.
-IN_PROC_BROWSER_TEST_F(InstantTest, SearchServerDoesntSupportInstant) {
+#if defined(OS_MACOSX) || defined(OS_LINUX)
+// Showing as flaky on Mac and Linux.
+// http://crbug.com/70860
+#define MAYBE_SearchServerDoesntSupportInstant \
+    DISABLED_SearchServerDoesntSupportInstant
+#else
+#define MAYBE_SearchServerDoesntSupportInstant \
+    SearchServerDoesntSupportInstant
+#endif
+IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_SearchServerDoesntSupportInstant) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("empty.html"));
   ASSERT_NO_FATAL_FAILURE(FindLocationBar());
-  location_bar_->location_entry()->SetUserText(L"a");
+  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("a"));
   ASSERT_TRUE(browser()->instant());
   // Because we typed in a search string we should think we're showing instant
   // results.
@@ -383,8 +526,19 @@
 // Verifies transitioning from loading a non-search string to a search string
 // with the provider not supporting instant works (meaning we don't display
 // anything).
-IN_PROC_BROWSER_TEST_F(InstantTest, NonSearchToSearchDoesntSupportInstant) {
+#if defined(OS_MACOSX) || defined(OS_LINUX)
+// Showing as flaky on Mac and linux (chrome os)
+// http://crbug.com/70810
+#define MAYBE_NonSearchToSearchDoesntSupportInstant \
+    DISABLED_NonSearchToSearchDoesntSupportInstant
+#else
+#define MAYBE_NonSearchToSearchDoesntSupportInstant \
+    NonSearchToSearchDoesntSupportInstant
+#endif
+IN_PROC_BROWSER_TEST_F(InstantTest,
+                       MAYBE_NonSearchToSearchDoesntSupportInstant) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("empty.html"));
   GURL url(test_server()->GetURL("files/instant/empty.html"));
   ASSERT_NO_FATAL_FAILURE(SetLocationBarText(UTF8ToWide(url.spec())));
@@ -399,7 +553,7 @@
   ASSERT_TRUE(rwhv->IsShowing());
 
   // Now type in some search text.
-  location_bar_->location_entry()->SetUserText(L"a");
+  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("a"));
 
   // Instant should still be live.
   ASSERT_TRUE(browser()->instant()->is_displayable());
@@ -422,6 +576,7 @@
 // Verifies the page was told a non-zero height.
 IN_PROC_BROWSER_TEST_F(InstantTest, ValidHeight) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
   ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
   ASSERT_NO_FATAL_FAILURE(SetupPreview());
@@ -447,9 +602,10 @@
 // query the host again.
 IN_PROC_BROWSER_TEST_F(InstantTest, HideOn403) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   GURL url(test_server()->GetURL("files/instant/403.html"));
   ASSERT_NO_FATAL_FAILURE(FindLocationBar());
-  location_bar_->location_entry()->SetUserText(UTF8ToWide(url.spec()));
+  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
   // The preview shouldn't be showing, but it should be loading.
   ASSERT_TRUE(browser()->instant()->GetPreviewContents());
   ASSERT_TRUE(browser()->instant()->is_active());
@@ -464,7 +620,7 @@
   // Try loading another url on the server. Instant shouldn't create a new tab
   // as the server returned 403.
   GURL url2(test_server()->GetURL("files/instant/empty.html"));
-  location_bar_->location_entry()->SetUserText(UTF8ToWide(url2.spec()));
+  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url2.spec()));
   ASSERT_FALSE(browser()->instant()->GetPreviewContents());
   ASSERT_TRUE(browser()->instant()->is_active());
   ASSERT_FALSE(browser()->instant()->is_displayable());
@@ -473,6 +629,7 @@
 // Verify that the onsubmit event is dispatched upon pressing enter.
 IN_PROC_BROWSER_TEST_F(InstantTest, OnSubmitEvent) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
@@ -480,7 +637,7 @@
   ASSERT_NO_FATAL_FAILURE(SetupPreview());
 
   ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_RETURN));
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));
 
   // Check that the preview contents have been committed.
   ASSERT_FALSE(browser()->instant()->GetPreviewContents());
@@ -489,13 +646,14 @@
   ASSERT_TRUE(contents);
 
   // Check that the value is reflected and onsubmit is called.
-  EXPECT_EQ("true 1 0 1 1 a false abc true",
-      GetSearchStateAsString(preview_));
+  EXPECT_EQ("true 1 0 1 2 a false abcdef true 3 3",
+            GetSearchStateAsString(preview_));
 }
 
 // Verify that the oncancel event is dispatched upon losing focus.
 IN_PROC_BROWSER_TEST_F(InstantTest, OnCancelEvent) {
   ASSERT_TRUE(test_server()->Start());
+  EnableInstant();
   ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
 
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
@@ -513,44 +671,6 @@
   ASSERT_TRUE(contents);
 
   // Check that the value is reflected and oncancel is called.
-  EXPECT_EQ("true 0 1 1 1 a false abc false",
-      GetSearchStateAsString(preview_));
-}
-
-#if !defined(OS_MACOSX)
-// Only passes on Mac.  http://crbug.com/66850
-#define MAYBE_TabKey FAILS_TabKey
-#else
-#define MAYBE_TabKey TabKey
-#endif
-IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_TabKey) {
-  ASSERT_TRUE(test_server()->Start());
-  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
-
-  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
-  ASSERT_NO_FATAL_FAILURE(SetupPreview());
-
-  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(L"abc"));
-
-  // Pressing tab to convert instant suggest into inline autocomplete.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_TAB));
-
-  ASSERT_EQ(L"abcdef", location_bar_->location_entry()->GetText());
-
-  EXPECT_EQ("true 0 0 2 2 a false abcdef false",
-      GetSearchStateAsString(preview_));
-
-  // Pressing tab again to accept the current instant preview.
-  ASSERT_NO_FATAL_FAILURE(SendKey(app::VKEY_TAB));
-
-  // Check that the preview contents have been committed.
-  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
-  ASSERT_FALSE(browser()->instant()->is_active());
-  TabContents* contents = browser()->GetSelectedTabContents();
-  ASSERT_TRUE(contents);
-
-  // Check that the value is reflected and onsubmit is called.
-  EXPECT_EQ("true 1 0 2 2 a false abcdef true",
-      GetSearchStateAsString(preview_));
+  EXPECT_EQ("true 0 1 1 2 a false abc false 3 3",
+            GetSearchStateAsString(preview_));
 }
diff --git a/chrome/browser/instant/instant_confirm_dialog.cc b/chrome/browser/instant/instant_confirm_dialog.cc
index e56a822..5ef3d87 100644
--- a/chrome/browser/instant/instant_confirm_dialog.cc
+++ b/chrome/browser/instant/instant_confirm_dialog.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/instant/instant_confirm_dialog.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/instant/instant_controller.h"
 #include "chrome/browser/instant/promo_counter.h"
 #include "chrome/browser/prefs/pref_service.h"
@@ -12,6 +11,7 @@
 #include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace browser {
 
diff --git a/chrome/browser/instant/instant_confirm_dialog.h b/chrome/browser/instant/instant_confirm_dialog.h
index f8cfe21..e815265 100644
--- a/chrome/browser/instant/instant_confirm_dialog.h
+++ b/chrome/browser/instant/instant_confirm_dialog.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_INSTANT_INSTANT_CONFIRM_DIALOG_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class GURL;
 class Profile;
diff --git a/chrome/browser/instant/instant_controller.cc b/chrome/browser/instant/instant_controller.cc
index fffe5db..e255509 100644
--- a/chrome/browser/instant/instant_controller.cc
+++ b/chrome/browser/instant/instant_controller.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,6 @@
 #include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
-#include "base/rand_util.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/instant/instant_delegate.h"
 #include "chrome/browser/instant/instant_loader.h"
@@ -41,10 +40,7 @@
       is_displayable_(false),
       commit_on_mouse_up_(false),
       last_transition_type_(PageTransition::LINK),
-      ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)),
-      type_(FIRST_TYPE) {
-  bool enabled = GetType(profile, &type_);
-  DCHECK(enabled);
+      ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)) {
   PrefService* service = profile->GetPrefs();
   if (service) {
     // kInstantWasEnabledOnce was added after instant, set it now to make sure
@@ -79,27 +75,17 @@
     } else {
       base::TimeDelta delta =
           base::Time::Now() - base::Time::FromInternalValue(enable_time);
-      std::string name = "Instant.EnabledTime. " + GetTypeString(profile);
-      // Can't use histogram macros as name isn't constant.
       // Histogram from 1 hour to 30 days.
-      scoped_refptr<base::Histogram> counter =
-          base::Histogram::FactoryGet(name, 1, 30 * 24, 50,
-              base::Histogram::kUmaTargetedHistogramFlag);
-      counter->Add(delta.InHours());
+      UMA_HISTOGRAM_CUSTOM_COUNTS("Instant.EnabledTime.Predictive",
+                                  delta.InHours(), 1, 30 * 24, 50);
     }
   }
 }
 
 // static
 bool InstantController::IsEnabled(Profile* profile) {
-  Type type;
-  return GetType(profile, &type);
-}
-
-// static
-bool InstantController::IsEnabled(Profile* profile, Type type) {
-  Type enabled_type;
-  return GetType(profile, &enabled_type) && type == enabled_type;
+  PrefService* prefs = profile->GetPrefs();
+  return prefs->GetBoolean(prefs::kInstantEnabled);
 }
 
 // static
@@ -129,13 +115,9 @@
   if (enable_time) {
     base::TimeDelta delta =
         base::Time::Now() - base::Time::FromInternalValue(enable_time);
-    std::string name = "Instant.TimeToDisable." + GetTypeString(profile);
-    // Can't use histogram macros as name isn't constant.
     // Histogram from 1 minute to 10 days.
-    scoped_refptr<base::Histogram> counter =
-       base::Histogram::FactoryGet(name, 1, 60 * 24 * 10, 50,
-                                   base::Histogram::kUmaTargetedHistogramFlag);
-    counter->Add(delta.InMinutes());
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Instant.TimeToDisable.Predictive",
+                                delta.InMinutes(), 1, 60 * 24 * 10, 50);
   }
 
   service->SetBoolean(prefs::kInstantEnabled, false);
@@ -352,6 +334,11 @@
       loader_manager_->active_loader()->is_showing_instant();
 }
 
+GURL InstantController::GetCurrentURL() {
+  return loader_manager_.get() && loader_manager_->active_loader() ?
+      loader_manager_->active_loader()->url() : GURL();
+}
+
 void InstantController::ShowInstantLoader(InstantLoader* loader) {
   DCHECK(loader_manager_.get());
   if (loader_manager_->current_loader() == loader) {
@@ -586,16 +573,6 @@
 
 const TemplateURL* InstantController::GetTemplateURL(
     const AutocompleteMatch& match) {
-  if (type_ == VERBATIM_TYPE) {
-    // When using VERBATIM_TYPE we don't want to attempt to use the instant
-    // JavaScript API, otherwise the page would show predictive results. By
-    // returning NULL here we ensure we don't attempt to use the instant API.
-    //
-    // TODO: when the full search box API is in place we can lift this
-    // restriction and force the page to show verbatim results always.
-    return NULL;
-  }
-
   const TemplateURL* template_url = match.template_url;
   if (match.type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED ||
       match.type == AutocompleteMatch::SEARCH_HISTORY ||
@@ -605,51 +582,3 @@
   }
   return template_url;
 }
-
-// static
-bool InstantController::GetType(Profile* profile, Type* type) {
-  *type = FIRST_TYPE;
-  // CommandLine takes precedence.
-  CommandLine* cl = CommandLine::ForCurrentProcess();
-  if (cl->HasSwitch(switches::kEnablePredictiveInstant)) {
-    *type = PREDICTIVE_TYPE;
-    return true;
-  }
-  if (cl->HasSwitch(switches::kEnableVerbatimInstant)) {
-    *type = VERBATIM_TYPE;
-    return true;
-  }
-  if (cl->HasSwitch(switches::kEnablePredictiveNoAutoCompleteInstant)) {
-    *type = PREDICTIVE_NO_AUTO_COMPLETE_TYPE;
-    return true;
-  }
-
-  // Then prefs.
-  PrefService* prefs = profile->GetPrefs();
-  if (!prefs->GetBoolean(prefs::kInstantEnabled))
-    return false;
-
-  // PREDICTIVE_TYPE is the default if enabled via preferences.
-  *type = PREDICTIVE_TYPE;
-  return true;
-}
-
-// static
-std::string InstantController::GetTypeString(Profile* profile) {
-  Type type;
-  if (!GetType(profile, &type)) {
-    NOTREACHED();
-    return std::string();
-  }
-  switch (type) {
-    case PREDICTIVE_TYPE:
-      return "Predictive";
-    case VERBATIM_TYPE:
-      return "Verbatim";
-    case PREDICTIVE_NO_AUTO_COMPLETE_TYPE:
-      return "PredictiveNoAutoComplete";
-    default:
-      NOTREACHED();
-      return std::string();
-  }
-}
diff --git a/chrome/browser/instant/instant_controller.h b/chrome/browser/instant/instant_controller.h
index 018101d..8b005d8 100644
--- a/chrome/browser/instant/instant_controller.h
+++ b/chrome/browser/instant/instant_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,9 +19,9 @@
 #include "chrome/browser/instant/instant_loader_delegate.h"
 #include "chrome/browser/search_engines/template_url_id.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 
 struct AutocompleteMatch;
 class InstantDelegate;
@@ -44,27 +44,6 @@
 // being invoked on the delegate.
 class InstantController : public InstantLoaderDelegate {
  public:
-  // Variations of instant support.
-  // TODO(sky): nuke these when we decide the default behavior.
-  enum Type {
-    // NOTE: these values are persisted to prefs. Don't change them!
-
-    FIRST_TYPE = 0,
-
-    // Search results are shown for the best guess of what we think the user was
-    // planning on typing.
-    PREDICTIVE_TYPE = 0,
-
-    // Search results are shown for exactly what was typed.
-    VERBATIM_TYPE,
-
-    // Variant of predictive that does not auto-complete after a delay.
-    PREDICTIVE_NO_AUTO_COMPLETE_TYPE,
-
-    LAST_TYPE = PREDICTIVE_NO_AUTO_COMPLETE_TYPE
-  };
-
-
   // Amount of time to wait before starting the instant animation.
   static const int kAutoCommitPauseTimeMS = 1000;
   // Duration of the instant animation in which the colors change.
@@ -79,12 +58,9 @@
   // Records instant metrics.
   static void RecordMetrics(Profile* profile);
 
-  // Returns true if either type of instant is enabled.
+  // Returns true if instant is enabled.
   static bool IsEnabled(Profile* profile);
 
-  // Returns true if the specified type of instant is enabled.
-  static bool IsEnabled(Profile* profile, Type type);
-
   // Enables instant.
   static void Enable(Profile* profile);
 
@@ -188,6 +164,10 @@
   // (until the search provider loads, then both return true).
   bool MightSupportInstant();
 
+  // Returns the URL currently being loaded or shown if everything has finished
+  // loading.
+  GURL GetCurrentURL();
+
   // InstantLoaderDelegate
   virtual void ShowInstantLoader(InstantLoader* loader);
   virtual void SetSuggestedTextFor(InstantLoader* loader,
@@ -257,14 +237,6 @@
   // NULL if there is no TemplateURL for |match|.
   const TemplateURL* GetTemplateURL(const AutocompleteMatch& match);
 
-  // If instant is enabled for the specified profile the type of instant is set
-  // in |type| and true is returned. Otherwise returns false.
-  static bool GetType(Profile* profile, Type* type);
-
-  // Returns a string description for the currently enabled type. This is used
-  // for histograms.
-  static std::string GetTypeString(Profile* profile);
-
   InstantDelegate* delegate_;
 
   // The TabContents last passed to |Update|.
@@ -302,8 +274,6 @@
   // URL last pased to ScheduleUpdate.
   GURL scheduled_url_;
 
-  Type type_;
-
   // List of InstantLoaders to destroy. See ScheduleForDestroy for details.
   ScopedVector<InstantLoader> loaders_to_destroy_;
 
diff --git a/chrome/browser/instant/instant_loader.cc b/chrome/browser/instant/instant_loader.cc
index 3d8189d..7e2b6f0 100644
--- a/chrome/browser/instant/instant_loader.cc
+++ b/chrome/browser/instant/instant_loader.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/string_number_conversions.h"
 #include "base/timer.h"
@@ -33,14 +32,16 @@
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/page_transition_types.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/renderer_preferences.h"
-#include "gfx/codec/png_codec.h"
 #include "ipc/ipc_message.h"
 #include "net/http/http_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace {
 
@@ -95,8 +96,10 @@
           return;
         }
         loader_->SendBoundsToPage(true);
+        // TODO: support real cursor position.
+        int text_length = static_cast<int>(text_.size());
         tab_contents_->render_view_host()->DetermineIfPageSupportsInstant(
-            text_, verbatim_);
+            text_, verbatim_, text_length, text_length);
         break;
       }
       default:
@@ -126,46 +129,13 @@
   DISALLOW_COPY_AND_ASSIGN(FrameLoadObserver);
 };
 
-// PaintObserver implementation. When the RenderWidgetHost paints itself this
-// notifies the TabContentsDelegateImpl which ultimately notifies InstantLoader
-// and shows the preview.
-// The ownership of this class is tricky. It's created and
-// tracked by TabContentsDelegateImpl, but owned by RenderWidgetHost. When
-// deleted this notifies the TabContentsDelegateImpl so that it can clean
-// up appropriately.
-class InstantLoader::PaintObserverImpl
-    : public RenderWidgetHost::PaintObserver {
- public:
-  PaintObserverImpl(TabContentsDelegateImpl* delegate,
-                    RenderWidgetHost* rwh)
-      : delegate_(delegate),
-        rwh_(rwh) {
-    rwh_->set_paint_observer(this);
-  }
-
-  ~PaintObserverImpl();
-
-  // Deletes this object by resetting the PaintObserver on the RenderWidgetHost.
-  void Destroy() {
-    rwh_->set_paint_observer(NULL);
-  }
-
-  virtual void RenderWidgetHostWillPaint(RenderWidgetHost* rwh) {}
-
-  virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh);
-
- private:
-  TabContentsDelegateImpl* delegate_;
-  RenderWidgetHost* rwh_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintObserverImpl);
-};
-
-class InstantLoader::TabContentsDelegateImpl : public TabContentsDelegate {
+class InstantLoader::TabContentsDelegateImpl
+    : public TabContentsDelegate,
+      public NotificationObserver {
  public:
   explicit TabContentsDelegateImpl(InstantLoader* loader)
       : loader_(loader),
-        paint_observer_(NULL),
+        registered_render_widget_host_(NULL),
         waiting_for_new_page_(true),
         is_mouse_down_from_activate_(false),
         user_typed_before_load_(false) {
@@ -176,14 +146,14 @@
     user_typed_before_load_ = false;
     waiting_for_new_page_ = true;
     add_page_vector_.clear();
-    DestroyPaintObserver();
+    UnregisterForPaintNotifications();
   }
 
   // Invoked when removed as the delegate. Gives a chance to do any necessary
   // cleanup.
   void Reset() {
     is_mouse_down_from_activate_ = false;
-    DestroyPaintObserver();
+    UnregisterForPaintNotifications();
   }
 
   // Invoked when the preview paints. Invokes PreviewPainted on the loader.
@@ -191,12 +161,6 @@
     loader_->PreviewPainted();
   }
 
-  // Invoked when the PaintObserverImpl is deleted.
-  void PaintObserverDestroyed(PaintObserverImpl* observer) {
-    if (observer == paint_observer_)
-      paint_observer_ = NULL;
-  }
-
   bool is_mouse_down_from_activate() const {
     return is_mouse_down_from_activate_;
   }
@@ -262,20 +226,56 @@
     }
   }
 
+  void RegisterForPaintNotifications(RenderWidgetHost* render_widget_host) {
+    DCHECK(registered_render_widget_host_ == NULL);
+    registered_render_widget_host_ = render_widget_host;
+    Source<RenderWidgetHost> source =
+        Source<RenderWidgetHost>(registered_render_widget_host_);
+    registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
+        source);
+    registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
+        source);
+  }
+
+  void UnregisterForPaintNotifications() {
+    if (registered_render_widget_host_) {
+      Source<RenderWidgetHost> source =
+          Source<RenderWidgetHost>(registered_render_widget_host_);
+      registrar_.Remove(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
+          source);
+      registrar_.Remove(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
+          source);
+      registered_render_widget_host_ = NULL;
+    }
+  }
+
+  virtual void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    if (type == NotificationType::RENDER_WIDGET_HOST_DID_PAINT) {
+      UnregisterForPaintNotifications();
+      PreviewPainted();
+    } else if (type == NotificationType::RENDER_WIDGET_HOST_DESTROYED) {
+      UnregisterForPaintNotifications();
+    } else {
+      NOTREACHED() << "Got a notification we didn't register for.";
+    }
+  }
+
   virtual void OpenURLFromTab(TabContents* source,
                               const GURL& url, const GURL& referrer,
                               WindowOpenDisposition disposition,
                               PageTransition::Type transition) {}
   virtual void NavigationStateChanged(const TabContents* source,
                                       unsigned changed_flags) {
-    if (!loader_->ready() && !paint_observer_ &&
+    if (!loader_->ready() && !registered_render_widget_host_ &&
         source->controller().entry_count()) {
       // The load has been committed. Install an observer that waits for the
       // first paint then makes the preview active. We wait for the load to be
       // committed before waiting on paint as there is always an initial paint
       // when a new renderer is created from the resize so that if we showed the
       // preview after the first paint we would end up with a white rect.
-      paint_observer_ = new PaintObserverImpl(this,
+      RegisterForPaintNotifications(
           source->GetRenderWidgetHostView()->GetRenderWidgetHost());
     }
   }
@@ -306,12 +306,11 @@
     if (!loader_->ready()) {
       // A constrained window shown for an auth may not paint. Show the preview
       // contents.
-      DestroyPaintObserver();
+      UnregisterForPaintNotifications();
       loader_->ShowPreview();
     }
   }
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
   virtual bool ShouldSuppressDialogs() {
     // Any message shown during instant cancels instant, so we suppress them.
@@ -325,6 +324,12 @@
   virtual void LostCapture() {
     CommitFromMouseReleaseIfNecessary();
   }
+  // If the user drags, we won't get a mouse up (at least on Linux). Commit the
+  // instant result when the drag ends, so that during the drag the page won't
+  // move around.
+  virtual void DragEnded() {
+    CommitFromMouseReleaseIfNecessary();
+  }
   virtual bool CanDownload(int request_id) { return false; }
   virtual void HandleMouseUp() {
     CommitFromMouseReleaseIfNecessary();
@@ -373,6 +378,13 @@
       loader_->PageDoesntSupportInstant(user_typed_before_load_);
   }
 
+  virtual bool ShouldShowHungRendererDialog() {
+    // If we allow the hung renderer dialog to be shown it'll gain focus,
+    // stealing focus from the omnibox causing instant to be cancelled. Return
+    // false so that doesn't happen.
+    return false;
+  }
+
  private:
   typedef std::vector<scoped_refptr<history::HistoryAddPageArgs> >
       AddPageVector;
@@ -384,22 +396,13 @@
       loader_->CommitInstantLoader();
   }
 
-  // If the PaintObserver is non-null Destroy is invoked on it.
-  void DestroyPaintObserver() {
-    if (paint_observer_) {
-      paint_observer_->Destroy();
-      // Destroy should result in invoking PaintObserverDestroyed and NULLing
-      // out paint_observer_.
-      DCHECK(!paint_observer_);
-    }
-  }
-
   InstantLoader* loader_;
 
-  // Used to listen for paint so that we know when to show the preview. See
-  // comment in NavigationStateChanged for details on this.
-  // Ownership of this is tricky, see comment above PaintObserverImpl class.
-  PaintObserverImpl* paint_observer_;
+  NotificationRegistrar registrar_;
+
+  // If we are registered for paint notifications on a RenderWidgetHost this
+  // will contain a pointer to it.
+  RenderWidgetHost* registered_render_widget_host_;
 
   // Used to cache data that needs to be added to history. Normally entries are
   // added to history as the user types, but for instant we only want to add the
@@ -420,22 +423,6 @@
   DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl);
 };
 
-InstantLoader::PaintObserverImpl::~PaintObserverImpl() {
-  delegate_->PaintObserverDestroyed(this);
-}
-
-void InstantLoader::PaintObserverImpl::RenderWidgetHostDidPaint(
-    RenderWidgetHost* rwh) {
-  TabContentsDelegateImpl* delegate = delegate_;
-  // Set the paint observer to NULL, which deletes us. Showing the preview may
-  // reset the paint observer, and delete us. By resetting the delegate first we
-  // know we've been deleted and can deal correctly.
-  rwh->set_paint_observer(NULL);
-  // WARNING: we've been deleted.
-  if (delegate)
-    delegate->PreviewPainted();
-}
-
 InstantLoader::InstantLoader(InstantLoaderDelegate* delegate, TemplateURLID id)
     : delegate_(delegate),
       template_url_id_(id),
@@ -461,6 +448,8 @@
                            const string16& user_text,
                            bool verbatim,
                            string16* suggested_text) {
+  DCHECK(!url.is_empty() && url.is_valid());
+
   // Strip leading ?.
   string16 new_user_text =
       !user_text.empty() && (UTF16ToWide(user_text)[0] == L'?') ?
@@ -470,22 +459,25 @@
   // showing the url.
   last_transition_type_ = transition_type;
 
-  // If state hasn't changed, just reuse the last suggestion. If the user
-  // modifies the text of the omnibox in anyway the URL changes. We also need to
-  // update if verbatim changes and we're showing instant results. We have to be
-  // careful in checking user_text as in some situations InstantController
-  // passes in an empty string (when it knows the user_text won't matter). In
-  // these cases, we don't worry about whether the new user text matches the old
-  // user text.
-  if ((url_ == url) &&
-      (new_user_text.empty() || user_text_ == new_user_text) &&
-      (!template_url || verbatim == verbatim_)) {
+  // If state hasn't changed, reuse the last suggestion. There are two cases:
+  // 1. If no template url (not using instant API), then we only care if the url
+  //    changes.
+  // 2. Template url (using instant API) then the important part is if the
+  //    user_text changes.
+  //    We have to be careful in checking user_text as in some situations
+  //    InstantController passes in an empty string (when it knows the user_text
+  //    won't matter).
+  if ((!template_url_id_ && url_ == url) ||
+      (template_url_id_ &&
+       (new_user_text.empty() || user_text_ == new_user_text))) {
     suggested_text->assign(last_suggestion_);
+    // Track the url even if we're not going to update. This is important as
+    // when we get the suggest text we set user_text_ to the new suggest text,
+    // but yet the url is much different.
+    url_ = url;
     return;
   }
 
-  DCHECK(!url.is_empty() && url.is_valid());
-
   url_ = url;
   user_text_ = new_user_text;
   verbatim_ = verbatim;
@@ -505,8 +497,10 @@
         preview_tab_contents_delegate_->set_user_typed_before_load();
         return;
       }
+      // TODO: support real cursor position.
+      int text_length = static_cast<int>(user_text_.size());
       preview_contents_->render_view_host()->SearchBoxChange(
-          user_text_, verbatim, 0, 0);
+          user_text_, verbatim, text_length, text_length);
 
       string16 complete_suggested_text_lower = l10n_util::ToLower(
           complete_suggested_text_);
@@ -531,7 +525,7 @@
       // TODO(sky): having to use a replaceable url is a bit of a hack here.
       GURL instant_url(
           template_url->instant_url()->ReplaceSearchTerms(
-              *template_url, std::wstring(), -1, std::wstring()));
+              *template_url, string16(), -1, string16()));
       CommandLine* cl = CommandLine::ForCurrentProcess();
       if (cl->HasSwitch(switches::kInstantURL))
         instant_url = GURL(cl->GetSwitchValueASCII(switches::kInstantURL));
@@ -557,6 +551,10 @@
   if (omnibox_bounds_ == bounds)
     return;
 
+  // Don't update the page while the mouse is down. http://crbug.com/71952
+  if (IsMouseDownFromActivate())
+    return;
+
   omnibox_bounds_ = bounds;
   if (preview_contents_.get() && is_showing_instant() &&
       !is_waiting_for_load()) {
@@ -611,11 +609,7 @@
       }
       preview_tab_contents_delegate_->CommitHistory(template_url_id_ != 0);
     }
-    // Destroy the paint observer.
-    // RenderWidgetHostView may be null during shutdown.
     if (preview_contents_->tab_contents()->GetRenderWidgetHostView()) {
-      preview_contents_->tab_contents()->GetRenderWidgetHostView()->
-          GetRenderWidgetHost()->set_paint_observer(NULL);
 #if defined(OS_MACOSX)
       preview_contents_->tab_contents()->GetRenderWidgetHostView()->
           SetTakesFocusOnlyOnMouseDown(false);
@@ -667,8 +661,13 @@
   }
 
   complete_suggested_text_ = complete_suggested_text;
-  last_suggestion_ = complete_suggested_text_.substr(user_text_.size());
-  delegate_->SetSuggestedTextFor(this, last_suggestion_);
+  // We are effectively showing complete_suggested_text_ now. Update user_text_
+  // so we don't notify the page again if Update happens to be invoked (which is
+  // more than likely if this callback completes before the omnibox is done).
+  string16 suggestion = complete_suggested_text_.substr(user_text_.size());
+  user_text_ = complete_suggested_text_;
+  last_suggestion_.clear();
+  delegate_->SetSuggestedTextFor(this, suggestion);
 }
 
 void InstantLoader::PreviewPainted() {
diff --git a/chrome/browser/instant/instant_loader.h b/chrome/browser/instant/instant_loader.h
index 8be48af..1da643a 100644
--- a/chrome/browser/instant/instant_loader.h
+++ b/chrome/browser/instant/instant_loader.h
@@ -15,8 +15,8 @@
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/rect.h"
 
 class InstantLoaderDelegate;
 class InstantLoaderManagerTest;
@@ -94,6 +94,7 @@
 
  private:
   friend class InstantLoaderManagerTest;
+  friend class InstantTest;
   class FrameLoadObserver;
   class PaintObserverImpl;
   class TabContentsDelegateImpl;
diff --git a/chrome/browser/instant/instant_unload_handler.cc b/chrome/browser/instant/instant_unload_handler.cc
index 811bde2..c58ee98 100644
--- a/chrome/browser/instant/instant_unload_handler.cc
+++ b/chrome/browser/instant/instant_unload_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -69,7 +69,6 @@
   virtual void LoadingStateChanged(TabContents* source) {}
   virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
 
  private:
diff --git a/chrome/browser/intranet_redirect_detector.cc b/chrome/browser/intranet_redirect_detector.cc
index 78c4089..8be4d5e 100644
--- a/chrome/browser/intranet_redirect_detector.cc
+++ b/chrome/browser/intranet_redirect_detector.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -107,7 +107,7 @@
 void IntranetRedirectDetector::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 7af736c..c6b8c7b 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,13 +17,13 @@
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/gpu_process_host.h"
+#include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h"
 #include "chrome/browser/net/chrome_net_log.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/connect_interceptor.h"
 #include "chrome/browser/net/passive_log_collector.h"
 #include "chrome/browser/net/predictor_api.h"
 #include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prerender/prerender_interceptor.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/net/raw_host_resolver_proc.h"
 #include "chrome/common/net/url_fetcher.h"
@@ -38,12 +38,11 @@
 #include "net/http/http_auth_filter.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
 #if defined(USE_NSS)
 #include "net/ocsp/nss_ocsp.h"
 #endif  // defined(USE_NSS)
 #include "net/proxy/proxy_script_fetcher_impl.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/spdy/spdy_session_pool.h"
 
 namespace {
 
@@ -71,8 +70,11 @@
     // For each option (i.e., non-default), we have a fixed probability.
     base::FieldTrial::Probability kProbabilityPerGroup = 100;  // 10%.
 
+    // After June 30, 2011 builds, it will always be in default group
+    // (parallel_default).
     scoped_refptr<base::FieldTrial> trial(
-        new base::FieldTrial("DnsParallelism", kDivisor));
+        new base::FieldTrial(
+            "DnsParallelism", kDivisor, "parallel_default", 2011, 6, 30));
 
     // List options with different counts.
     // Firefox limits total to 8 in parallel, and default is currently 50.
@@ -84,9 +86,6 @@
     int parallel_14 = trial->AppendGroup("parallel_14", kProbabilityPerGroup);
     int parallel_20 = trial->AppendGroup("parallel_20", kProbabilityPerGroup);
 
-    trial->AppendGroup("parallel_default",
-                        base::FieldTrial::kAllRemainingProbability);
-
     if (trial->group() == parallel_6)
       parallelism = 6;
     else if (trial->group() == parallel_7)
@@ -177,10 +176,10 @@
   DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver);
 };
 
-scoped_refptr<URLRequestContext>
+scoped_refptr<net::URLRequestContext>
 ConstructProxyScriptFetcherContext(IOThread::Globals* globals,
                                    net::NetLog* net_log) {
-  scoped_refptr<URLRequestContext> context(new URLRequestContext);
+  scoped_refptr<net::URLRequestContext> context(new net::URLRequestContext);
   context->set_net_log(net_log);
   context->set_host_resolver(globals->host_resolver.get());
   context->set_cert_verifier(globals->cert_verifier.get());
@@ -192,6 +191,7 @@
       globals->proxy_script_fetcher_http_transaction_factory.get());
   // In-memory cookie store.
   context->set_cookie_store(new net::CookieMonster(NULL, NULL));
+  // TODO(mpcomplete): give it a SystemNetworkDelegate.
   return context;
 }
 
@@ -295,12 +295,9 @@
 }
 
 void IOThread::Init() {
-#if !defined(OS_CHROMEOS)
-  // TODO(evan): test and enable this on all platforms.
   // Though this thread is called the "IO" thread, it actually just routes
   // messages around; it shouldn't be allowed to perform any blocking disk I/O.
   base::ThreadRestrictions::SetIOAllowed(false);
-#endif
 
   BrowserProcessSubThread::Init();
 
@@ -319,8 +316,6 @@
   network_change_observer_.reset(
       new LoggingNetworkChangeObserver(net_log_));
 
-  globals_->client_socket_factory =
-      net::ClientSocketFactory::GetDefaultFactory();
   globals_->host_resolver.reset(
       CreateGlobalHostResolver(net_log_));
   globals_->cert_verifier.reset(new net::CertVerifier);
@@ -333,34 +328,29 @@
   // For the ProxyScriptFetcher, we use a direct ProxyService.
   globals_->proxy_script_fetcher_proxy_service =
       net::ProxyService::CreateDirectWithNetLog(net_log_);
+  net::HttpNetworkSession::Params session_params;
+  session_params.host_resolver = globals_->host_resolver.get();
+  session_params.cert_verifier = globals_->cert_verifier.get();
+  session_params.proxy_service =
+      globals_->proxy_script_fetcher_proxy_service.get();
+  session_params.http_auth_handler_factory =
+      globals_->http_auth_handler_factory.get();
+  session_params.network_delegate = &globals_->network_delegate;
+  session_params.net_log = net_log_;
+  session_params.ssl_config_service = globals_->ssl_config_service;
+  scoped_refptr<net::HttpNetworkSession> network_session(
+      new net::HttpNetworkSession(session_params));
   globals_->proxy_script_fetcher_http_transaction_factory.reset(
-      new net::HttpNetworkLayer(
-          globals_->client_socket_factory,
-          globals_->host_resolver.get(),
-          globals_->cert_verifier.get(),
-          globals_->dnsrr_resolver.get(),
-          NULL /* dns_cert_checker */,
-          NULL /* ssl_host_info_factory */,
-          globals_->proxy_script_fetcher_proxy_service.get(),
-          globals_->ssl_config_service.get(),
-          new net::SpdySessionPool(globals_->ssl_config_service.get()),
-          globals_->http_auth_handler_factory.get(),
-          &globals_->network_delegate,
-          net_log_));
+      new net::HttpNetworkLayer(network_session));
 
-  scoped_refptr<URLRequestContext> proxy_script_fetcher_context =
+  scoped_refptr<net::URLRequestContext> proxy_script_fetcher_context =
       ConstructProxyScriptFetcherContext(globals_, net_log_);
   globals_->proxy_script_fetcher_context = proxy_script_fetcher_context;
-
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnablePagePrerender)) {
-    prerender_interceptor_.reset(new PrerenderInterceptor());
-  }
 }
 
 void IOThread::CleanUp() {
   // Step 1: Kill all things that might be holding onto
-  // net::URLRequest/URLRequestContexts.
+  // net::URLRequest/net::URLRequestContexts.
 
 #if defined(USE_NSS)
   net::ShutdownOCSP();
@@ -369,6 +359,8 @@
   // Destroy all URLRequests started by URLFetchers.
   URLFetcher::CancelAll();
 
+  IndexedDBKeyUtilityClient::Shutdown();
+
   // If any child processes are still running, terminate them and
   // and delete the BrowserChildProcessHost instances to release whatever
   // IO thread only resources they are referencing.
@@ -388,8 +380,8 @@
     getter->ReleaseURLRequestContext();
   }
 
-  // Step 2: Release objects that the URLRequestContext could have been pointing
-  // to.
+  // Step 2: Release objects that the net::URLRequestContext could have been
+  // pointing to.
 
   // This must be reset before the ChromeNetLog is destroyed.
   network_change_observer_.reset();
@@ -409,8 +401,6 @@
   delete speculative_interceptor_;
   speculative_interceptor_ = NULL;
 
-  prerender_interceptor_.reset();
-
   // TODO(eroman): hack for http://crbug.com/15513
   if (globals_->host_resolver->GetAsHostResolverImpl()) {
     globals_->host_resolver.get()->GetAsHostResolverImpl()->Shutdown();
@@ -510,14 +500,21 @@
 
   // Clear the host cache to avoid showing entries from the OTR session
   // in about:net-internals.
+  ClearHostCache();
+
+  // Clear all of the passively logged data.
+  // TODO(eroman): this is a bit heavy handed, really all we need to do is
+  //               clear the data pertaining to off the record context.
+  net_log_->ClearAllPassivelyCapturedEvents();
+}
+
+void IOThread::ClearHostCache() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
   if (globals_->host_resolver->GetAsHostResolverImpl()) {
     net::HostCache* host_cache =
         globals_->host_resolver.get()->GetAsHostResolverImpl()->cache();
     if (host_cache)
       host_cache->clear();
   }
-  // Clear all of the passively logged data.
-  // TODO(eroman): this is a bit heavy handed, really all we need to do is
-  //               clear the data pertaining to off the record context.
-  net_log_->ClearAllPassivelyCapturedEvents();
 }
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 3d34538..f912765 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -20,7 +20,6 @@
 class ChromeURLRequestContextGetter;
 class ListValue;
 class PrefService;
-class PrerenderInterceptor;
 
 namespace chrome_browser_net {
 class ConnectInterceptor;
@@ -29,7 +28,6 @@
 
 namespace net {
 class CertVerifier;
-class ClientSocketFactory;
 class DnsRRResolver;
 class HostResolver;
 class HttpAuthHandlerFactory;
@@ -47,7 +45,6 @@
     Globals();
     ~Globals();
 
-    net::ClientSocketFactory* client_socket_factory;
     scoped_ptr<net::HostResolver> host_resolver;
     scoped_ptr<net::CertVerifier> cert_verifier;
     scoped_ptr<net::DnsRRResolver> dnsrr_resolver;
@@ -98,10 +95,15 @@
   void UnregisterURLRequestContextGetter(
       ChromeURLRequestContextGetter* url_request_context_getter);
 
-  // Handles changing to On The Record mode.  Posts a task for this onto the
+  // Handles changing to On The Record mode.  Post a task for this onto the
   // IOThread's message loop.
   void ChangedToOnTheRecord();
 
+  // Clears the host cache.  Intended to be used to prevent exposing recently
+  // visited sites on about:net-internals/#dns and about:dns pages.  Must be
+  // called on the IO thread.
+  void ClearHostCache();
+
  protected:
   virtual void Init();
   virtual void CleanUp();
@@ -157,7 +159,6 @@
   // down.
   chrome_browser_net::ConnectInterceptor* speculative_interceptor_;
   chrome_browser_net::Predictor* predictor_;
-  scoped_ptr<PrerenderInterceptor> prerender_interceptor_;
 
   // Keeps track of all live ChromeURLRequestContextGetters, so the
   // ChromeURLRequestContexts can be released during
diff --git a/chrome/browser/jankometer.cc b/chrome/browser/jankometer.cc
index ea1cf27..29986ea 100644
--- a/chrome/browser/jankometer.cc
+++ b/chrome/browser/jankometer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,8 +13,8 @@
 #include "base/metrics/stats_counters.h"
 #include "base/ref_counted.h"
 #include "base/string_util.h"
-#include "base/threading/watchdog.h"
 #include "base/threading/thread.h"
+#include "base/threading/watchdog.h"
 #include "base/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
@@ -22,7 +22,7 @@
 #include "chrome/common/chrome_switches.h"
 
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #endif
 
 using base::TimeDelta;
diff --git a/chrome/browser/jumplist_win.cc b/chrome/browser/jumplist_win.cc
index b953795..438c9e7 100644
--- a/chrome/browser/jumplist_win.cc
+++ b/chrome/browser/jumplist_win.cc
@@ -12,7 +12,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -33,13 +32,14 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/icon_util.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/icon_util.h"
+
 
 namespace {
 
diff --git a/chrome/browser/language_combobox_model.cc b/chrome/browser/language_combobox_model.cc
index 6366d59..54e67e1 100644
--- a/chrome/browser/language_combobox_model.cc
+++ b/chrome/browser/language_combobox_model.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/language_combobox_model.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
 #include "base/string_split.h"
 #include "base/stringprintf.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/uloc.h"
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/language_combobox_model.h b/chrome/browser/language_combobox_model.h
index 7844311..a88b380 100644
--- a/chrome/browser/language_combobox_model.h
+++ b/chrome/browser/language_combobox_model.h
@@ -10,9 +10,9 @@
 #include <string>
 #include <vector>
 
-#include "app/combobox_model.h"
 #include "base/basictypes.h"
 #include "base/string16.h"
+#include "ui/base/models/combobox_model.h"
 
 class Profile;
 
@@ -68,7 +68,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 // LanguageComboboxModel
 //  The combobox model implementation.
-class LanguageComboboxModel : public LanguageList, public ComboboxModel {
+class LanguageComboboxModel : public LanguageList, public ui::ComboboxModel {
  public:
   LanguageComboboxModel();
 
diff --git a/chrome/browser/language_order_table_model.cc b/chrome/browser/language_order_table_model.cc
index 90501d8..7f4c42a 100644
--- a/chrome/browser/language_order_table_model.cc
+++ b/chrome/browser/language_order_table_model.cc
@@ -6,11 +6,11 @@
 
 #include <set>
 
-#include "app/l10n_util.h"
-#include "app/table_model_observer.h"
 #include "base/string_split.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
 
 LanguageOrderTableModel::LanguageOrderTableModel()
     : observer_(NULL) {
@@ -35,7 +35,7 @@
     observer_->OnModelChanged();
 }
 
-void LanguageOrderTableModel::SetObserver(TableModelObserver* observer) {
+void LanguageOrderTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
diff --git a/chrome/browser/language_order_table_model.h b/chrome/browser/language_order_table_model.h
index d23f638..a3aa8a3 100644
--- a/chrome/browser/language_order_table_model.h
+++ b/chrome/browser/language_order_table_model.h
@@ -9,13 +9,15 @@
 #include <string>
 #include <vector>
 
-#include "app/table_model.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "ui/base/models/table_model.h"
 
+namespace ui {
 class TableModelObserver;
+}
 
-class LanguageOrderTableModel : public TableModel {
+class LanguageOrderTableModel : public ui::TableModel {
  public:
   LanguageOrderTableModel();
 
@@ -46,14 +48,14 @@
   // TableModel overrides:
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
  private:
   // Set of entries we're showing.
   std::vector<std::string> languages_;
   std::string comma_separated_language_list_;
 
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(LanguageOrderTableModel);
 };
diff --git a/chrome/browser/load_from_memory_cache_details.cc b/chrome/browser/load_from_memory_cache_details.cc
new file mode 100644
index 0000000..2791020
--- /dev/null
+++ b/chrome/browser/load_from_memory_cache_details.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/load_from_memory_cache_details.h"
+
+LoadFromMemoryCacheDetails::LoadFromMemoryCacheDetails(
+    const GURL& url,
+    const std::string& frame_origin,
+    const std::string& main_frame_origin,
+    int pid,
+    int cert_id,
+    int cert_status)
+    : url_(url),
+      frame_origin_(frame_origin),
+      main_frame_origin_(main_frame_origin),
+      pid_(pid),
+      cert_id_(cert_id),
+      cert_status_(cert_status) {
+}
+
+LoadFromMemoryCacheDetails::~LoadFromMemoryCacheDetails() {
+}
diff --git a/chrome/browser/load_from_memory_cache_details.h b/chrome/browser/load_from_memory_cache_details.h
index d46684d..d5ffd1e 100644
--- a/chrome/browser/load_from_memory_cache_details.h
+++ b/chrome/browser/load_from_memory_cache_details.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,16 +17,8 @@
        const std::string& main_frame_origin,
        int pid,
        int cert_id,
-       int cert_status)
-       : url_(url),
-         frame_origin_(frame_origin),
-         main_frame_origin_(main_frame_origin),
-         pid_(pid),
-         cert_id_(cert_id),
-         cert_status_(cert_status)
-  { }
-
-  ~LoadFromMemoryCacheDetails() { }
+       int cert_status);
+  ~LoadFromMemoryCacheDetails();
 
   const GURL& url() const { return url_; }
   const std::string& frame_origin() const { return frame_origin_; }
diff --git a/chrome/browser/mach_broker_mac.cc b/chrome/browser/mach_broker_mac.cc
index 4ea2069..03932ad 100644
--- a/chrome/browser/mach_broker_mac.cc
+++ b/chrome/browser/mach_broker_mac.cc
@@ -91,7 +91,7 @@
       // leaking MachBroker map entries in this case, lock around both these
       // calls.  If the child dies, the death notification will be processed
       // after the call to FinalizePid(), ensuring proper cleanup.
-      AutoLock lock(broker_->GetLock());
+      base::AutoLock lock(broker_->GetLock());
 
       int pid;
       err = pid_for_task(child_task, &pid);
@@ -170,7 +170,7 @@
 
 // Removes all mappings belonging to |pid| from the broker.
 void MachBroker::InvalidatePid(base::ProcessHandle pid) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   MachBroker::MachMap::iterator it = mach_map_.find(pid);
   if (it == mach_map_.end())
     return;
@@ -183,13 +183,13 @@
   mach_map_.erase(it);
 }
 
-Lock& MachBroker::GetLock() {
+base::Lock& MachBroker::GetLock() {
   return lock_;
 }
 
 // Returns the mach task belonging to |pid|.
 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
   if (it == mach_map_.end())
     return MACH_PORT_NULL;
diff --git a/chrome/browser/mach_broker_mac.h b/chrome/browser/mach_broker_mac.h
index 2007055..0d4baa8 100644
--- a/chrome/browser/mach_broker_mac.h
+++ b/chrome/browser/mach_broker_mac.h
@@ -11,10 +11,10 @@
 
 #include <mach/mach.h>
 
-#include "base/lock.h"
 #include "base/process.h"
 #include "base/process_util.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
@@ -70,7 +70,7 @@
 
   // The lock that protects this MachBroker object.  Clients MUST acquire and
   // release this lock around calls to PlaceholderForPid() and FinalizePid().
-  Lock& GetLock();
+  base::Lock& GetLock();
 
   // Returns the Mach port name to use when sending or receiving messages.
   // Does the Right Thing in the browser and in child processes.
@@ -99,7 +99,7 @@
   MachMap mach_map_;
 
   // Mutex that guards |mach_map_|.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   friend class MachBrokerTest;
   friend class RegisterNotificationTask;
diff --git a/chrome/browser/mach_broker_mac_unittest.cc b/chrome/browser/mach_broker_mac_unittest.cc
index b0e5b05..5ed6652 100644
--- a/chrome/browser/mach_broker_mac_unittest.cc
+++ b/chrome/browser/mach_broker_mac_unittest.cc
@@ -4,21 +4,21 @@
 
 #include "chrome/browser/mach_broker_mac.h"
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class MachBrokerTest : public testing::Test {
  public:
   // Helper function to acquire/release locks and call |PlaceholderForPid()|.
   void AddPlaceholderForPid(base::ProcessHandle pid) {
-    AutoLock lock(broker_.GetLock());
+    base::AutoLock lock(broker_.GetLock());
     broker_.AddPlaceholderForPid(pid);
   }
 
   // Helper function to acquire/release locks and call |FinalizePid()|.
   void FinalizePid(base::ProcessHandle pid,
                    const MachBroker::MachInfo& mach_info) {
-    AutoLock lock(broker_.GetLock());
+    base::AutoLock lock(broker_.GetLock());
     broker_.FinalizePid(pid, mach_info);
   }
 
@@ -28,7 +28,7 @@
 
 TEST_F(MachBrokerTest, Locks) {
   // Acquire and release the locks.  Nothing bad should happen.
-  AutoLock lock(broker_.GetLock());
+  base::AutoLock lock(broker_.GetLock());
 }
 
 TEST_F(MachBrokerTest, AddPlaceholderAndFinalize) {
diff --git a/chrome/browser/media_uitest.cc b/chrome/browser/media_uitest.cc
index 0d1bc26..865b1e2 100644
--- a/chrome/browser/media_uitest.cc
+++ b/chrome/browser/media_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 #include "base/basictypes.h"
 #include "base/file_path.h"
 #include "base/string_util.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/test_launcher_utils.h"
@@ -46,7 +47,7 @@
     const std::wstring kFailed = L"FAILED";
     const std::wstring kError = L"ERROR";
     for (int i = 0; i < 10; ++i) {
-      base::PlatformThread::Sleep(sleep_timeout_ms());
+      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
       const std::wstring& title = GetActiveTabTitle();
       if (title == kPlaying || title == kFailed ||
           StartsWith(title, kError, true))
@@ -65,13 +66,6 @@
   }
 };
 
-#if defined(OS_LINUX) || defined(OS_WIN)
-// Test appears to be fine on linux, but let's first change to flaky and
-// see how that goes.
-// http://crbug.com/56364
-#define MediaUILayoutTest FLAKY_MediaUILayoutTest
-#endif
-
 TEST_F(MediaTest, VideoBearTheora) {
   PlayVideo("bear.ogv");
 }
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc
index 233f444..fbf431c 100644
--- a/chrome/browser/memory_details.cc
+++ b/chrome/browser/memory_details.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/memory_details.h"
 
-#include "app/l10n_util.h"
 #include "base/file_version_info.h"
 #include "base/metrics/histogram.h"
 #include "base/process_util.h"
@@ -24,6 +23,7 @@
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_LINUX)
 #include "chrome/browser/zygote_host_linux.h"
@@ -158,7 +158,7 @@
         RenderViewHostDelegate* host_delegate = host->delegate();
         GURL url = host_delegate->GetURL();
         ViewType::Type type = host_delegate->GetRenderViewType();
-        if (host->enabled_bindings() & BindingsPolicy::DOM_UI) {
+        if (host->enabled_bindings() & BindingsPolicy::WEB_UI) {
           // TODO(erikkay) the type for devtools doesn't actually appear to
           // be set.
           if (type == ViewType::DEV_TOOLS_UI)
diff --git a/chrome/browser/memory_details_mac.cc b/chrome/browser/memory_details_mac.cc
index fbc4d98..d4d14fd 100644
--- a/chrome/browser/memory_details_mac.cc
+++ b/chrome/browser/memory_details_mac.cc
@@ -7,7 +7,6 @@
 #include <set>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/file_path.h"
 #include "base/file_version_info.h"
@@ -26,6 +25,7 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // TODO(viettrungluu): Many of the TODOs below are subsumed by a general need to
 // refactor the about:memory code (not just on Mac, but probably on other
diff --git a/chrome/browser/memory_details_win.cc b/chrome/browser/memory_details_win.cc
index 4684fd0..697f608 100644
--- a/chrome/browser/memory_details_win.cc
+++ b/chrome/browser/memory_details_win.cc
@@ -6,7 +6,6 @@
 
 #include <psapi.h>
 
-#include "app/l10n_util.h"
 #include "base/file_path.h"
 #include "base/file_version_info.h"
 #include "base/string_util.h"
@@ -20,6 +19,7 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // Known browsers which we collect details for.
 enum {
diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc
index bf54134..d8a36c0 100644
--- a/chrome/browser/metrics/metrics_log.cc
+++ b/chrome/browser/metrics/metrics_log.cc
@@ -109,10 +109,9 @@
   }
 }
 
-void MetricsLog::WriteStabilityElement() {
+void MetricsLog::WriteStabilityElement(PrefService* pref) {
   DCHECK(!locked_);
 
-  PrefService* pref = g_browser_process->local_state();
   DCHECK(pref);
 
   // Get stability attributes out of Local State, zeroing out stored values.
@@ -232,6 +231,38 @@
     pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
   }
 
+#if defined(OS_CHROMEOS)
+  count = pref->GetInteger(prefs::kStabilityOtherUserCrashCount);
+  if (count) {
+    // TODO(kmixter): Write attribute once log server supports it
+    // and remove warning log.
+    // WriteIntAttribute("otherusercrashcount", count);
+    LOG(WARNING) << "Not yet able to send otherusercrashcount="
+                 << count;
+    pref->SetInteger(prefs::kStabilityOtherUserCrashCount, 0);
+  }
+
+  count = pref->GetInteger(prefs::kStabilityKernelCrashCount);
+  if (count) {
+    // TODO(kmixter): Write attribute once log server supports it
+    // and remove warning log.
+    // WriteIntAttribute("kernelcrashcount", count);
+    LOG(WARNING) << "Not yet able to send kernelcrashcount="
+                 << count;
+    pref->SetInteger(prefs::kStabilityKernelCrashCount, 0);
+  }
+
+  count = pref->GetInteger(prefs::kStabilitySystemUncleanShutdownCount);
+  if (count) {
+    // TODO(kmixter): Write attribute once log server supports it
+    // and remove warning log.
+    // WriteIntAttribute("systemuncleanshutdowns", count);
+    LOG(WARNING) << "Not yet able to send systemuncleanshutdowns="
+                 << count;
+    pref->SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 0);
+  }
+#endif  // OS_CHROMEOS
+
   int64 recent_duration = GetIncrementalUptime(pref);
   if (recent_duration)
     WriteInt64Attribute("uptimesec", recent_duration);
@@ -251,8 +282,13 @@
     // Plugin name and filename are hashed for the privacy of those
     // testing unreleased new extensions.
     WriteAttribute("name", CreateBase64Hash(UTF16ToUTF8(iter->name)));
-    WriteAttribute("filename",
-        CreateBase64Hash(WideToUTF8(iter->path.BaseName().ToWStringHack())));
+    std::string filename_bytes =
+#if defined(OS_WIN)
+        UTF16ToUTF8(iter->path.BaseName().value());
+#else
+        iter->path.BaseName().value();
+#endif
+    WriteAttribute("filename", CreateBase64Hash(filename_bytes));
     WriteAttribute("version", UTF16ToUTF8(iter->version));
   }
 }
@@ -277,7 +313,7 @@
 
   WritePluginList(plugin_list);
 
-  WriteStabilityElement();
+  WriteStabilityElement(pref);
 
   {
     OPEN_ELEMENT_FOR_SCOPE("cpu");
diff --git a/chrome/browser/metrics/metrics_log.h b/chrome/browser/metrics/metrics_log.h
index 0cb8b29..8a19bd3 100644
--- a/chrome/browser/metrics/metrics_log.h
+++ b/chrome/browser/metrics/metrics_log.h
@@ -64,6 +64,8 @@
   virtual MetricsLog* AsMetricsLog();
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(MetricsLogTest, ChromeOSStabilityData);
+
   // Returns the date at which the current metrics client ID was created as
   // a string containing milliseconds since the epoch, or "0" if none was found.
   std::string GetInstallDate() const;
@@ -71,7 +73,7 @@
 
   // Writes application stability metrics (as part of the profile log).
   // NOTE: Has the side-effect of clearing those counts.
-  void WriteStabilityElement();
+  void WriteStabilityElement(PrefService* pref);
 
   // Within stability group, write plugin crash stats.
   void WritePluginStabilityElements(PrefService* pref);
diff --git a/chrome/browser/metrics/metrics_log_unittest.cc b/chrome/browser/metrics/metrics_log_unittest.cc
index 184500d..63a304f 100644
--- a/chrome/browser/metrics/metrics_log_unittest.cc
+++ b/chrome/browser/metrics/metrics_log_unittest.cc
@@ -7,6 +7,9 @@
 #include "base/string_util.h"
 #include "base/time.h"
 #include "chrome/browser/metrics/metrics_log.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_profile.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -24,10 +27,10 @@
   std::string prefix = "buildtime=\"";
   const char postfix = '\"';
   size_t offset = xml_encoded->find(prefix);
-  ASSERT_GT(offset, 0u);
+  ASSERT_NE(std::string::npos, offset);
   offset += prefix.size();
   size_t postfix_position = xml_encoded->find(postfix, offset);
-  ASSERT_GT(postfix_position, offset);
+  ASSERT_NE(std::string::npos, postfix_position);
   for (size_t i = offset; i < postfix_position; ++i) {
     char digit = xml_encoded->at(i);
     ASSERT_GE(digit, '0');
@@ -192,6 +195,52 @@
 
   ASSERT_EQ(expected_output, encoded);
 }
+
+TEST(MetricsLogTest, ChromeOSStabilityData) {
+  NoTimeMetricsLog log("bogus client ID", 0);
+  TestingProfile profile;
+  PrefService* pref = profile.GetPrefs();
+
+  pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 10);
+  pref->SetInteger(prefs::kStabilityOtherUserCrashCount, 11);
+  pref->SetInteger(prefs::kStabilityKernelCrashCount, 12);
+  pref->SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 13);
+  std::string expected_output = StringPrintf(
+      "<log clientid=\"bogus client ID\" buildtime=\"123456789\" "
+          "appversion=\"%s\">\n"
+      "<stability stuff>\n", MetricsLog::GetVersionString().c_str());
+  // Expect 3 warnings about not yet being able to send the
+  // Chrome OS stability stats.
+  log.WriteStabilityElement(profile.GetPrefs());
+  log.CloseLog();
+
+  int size = log.GetEncodedLogSize();
+  ASSERT_GT(size, 0);
+
+  EXPECT_EQ(0, pref->GetInteger(prefs::kStabilityChildProcessCrashCount));
+  EXPECT_EQ(0, pref->GetInteger(prefs::kStabilityOtherUserCrashCount));
+  EXPECT_EQ(0, pref->GetInteger(prefs::kStabilityKernelCrashCount));
+  EXPECT_EQ(0, pref->GetInteger(prefs::kStabilitySystemUncleanShutdownCount));
+
+  std::string encoded;
+  // Leave room for the NUL terminator.
+  bool encoding_result = log.GetEncodedLog(
+      WriteInto(&encoded, size + 1), size);
+  ASSERT_TRUE(encoding_result);
+
+  // Check that we can find childprocesscrashcount, but not
+  // any of the ChromeOS ones that we are not emitting until log
+  // servers can handle them.
+  EXPECT_NE(std::string::npos,
+            encoded.find(" childprocesscrashcount=\"10\""));
+  EXPECT_EQ(std::string::npos,
+            encoded.find(" otherusercrashcount="));
+  EXPECT_EQ(std::string::npos,
+            encoded.find(" kernelcrashcount="));
+  EXPECT_EQ(std::string::npos,
+            encoded.find(" systemuncleanshutdowns="));
+}
+
 #endif  // OS_CHROMEOS
 
 // Make sure our ID hashes are the same as what we see on the server side.
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index a5394c0..9f044fd 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -400,6 +400,12 @@
                                    0);
   local_state->RegisterIntegerPref(prefs::kStabilityDebuggerPresent, 0);
   local_state->RegisterIntegerPref(prefs::kStabilityDebuggerNotPresent, 0);
+#if defined(OS_CHROMEOS)
+  local_state->RegisterIntegerPref(prefs::kStabilityOtherUserCrashCount, 0);
+  local_state->RegisterIntegerPref(prefs::kStabilityKernelCrashCount, 0);
+  local_state->RegisterIntegerPref(prefs::kStabilitySystemUncleanShutdownCount,
+                                   0);
+#endif  // OS_CHROMEOS
 
   local_state->RegisterDictionaryPref(prefs::kProfileMetrics);
   local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0);
@@ -865,9 +871,7 @@
   if (!current_log_)
     return;
 
-  MetricsLog* current_log = current_log_->AsMetricsLog();
-  DCHECK(current_log);
-  current_log->set_hardware_class(hardware_class_);  // Adds to ongoing logs.
+  current_log_->set_hardware_class(hardware_class_);  // Adds to ongoing logs.
 
   // TODO(jar): Integrate bounds on log recording more consistently, so that we
   // can stop recording logs that are too big much sooner.
@@ -884,13 +888,17 @@
   // end of all log transmissions (initial log handles this separately).
   // Don't bother if we're going to discard current_log_.
   if (log) {
+    // RecordIncrementalStabilityElements only exists on the derived
+    // MetricsLog class.
+    MetricsLog* current_log = current_log_->AsMetricsLog();
+    DCHECK(current_log);
     current_log->RecordIncrementalStabilityElements();
     RecordCurrentHistograms();
   }
 
   current_log_->CloseLog();
   if (log)
-    *log = current_log;
+    *log = current_log_;
   else
     delete current_log_;
   current_log_ = NULL;
@@ -1332,21 +1340,21 @@
   current_fetch_->set_upload_data(kMetricsType, compressed_log_);
 }
 
-static const char* StatusToString(const URLRequestStatus& status) {
+static const char* StatusToString(const net::URLRequestStatus& status) {
   switch (status.status()) {
-    case URLRequestStatus::SUCCESS:
+    case net::URLRequestStatus::SUCCESS:
       return "SUCCESS";
 
-    case URLRequestStatus::IO_PENDING:
+    case net::URLRequestStatus::IO_PENDING:
       return "IO_PENDING";
 
-    case URLRequestStatus::HANDLED_EXTERNALLY:
+    case net::URLRequestStatus::HANDLED_EXTERNALLY:
       return "HANDLED_EXTERNALLY";
 
-    case URLRequestStatus::CANCELED:
+    case net::URLRequestStatus::CANCELED:
       return "CANCELED";
 
-    case URLRequestStatus::FAILED:
+    case net::URLRequestStatus::FAILED:
       return "FAILED";
 
     default:
@@ -1357,7 +1365,7 @@
 
 void MetricsService::OnURLFetchComplete(const URLFetcher* source,
                                         const GURL& url,
-                                        const URLRequestStatus& status,
+                                        const net::URLRequestStatus& status,
                                         int response_code,
                                         const ResponseCookies& cookies,
                                         const std::string& data) {
@@ -1715,6 +1723,22 @@
   IncrementPrefValue(prefs::kStabilityRendererHangCount);
 }
 
+#if defined(OS_CHROMEOS)
+void MetricsService::LogChromeOSCrash(const std::string &crash_type) {
+  if (crash_type == "user")
+    IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
+  else if (crash_type == "kernel")
+    IncrementPrefValue(prefs::kStabilityKernelCrashCount);
+  else if (crash_type == "uncleanshutdown")
+    IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
+  else
+    NOTREACHED() << "Unexpected Chrome OS crash type " << crash_type;
+  // Wake up metrics logs sending if necessary now that new
+  // log data is available.
+  HandleIdleSinceLastTransmission(false);
+}
+#endif  // OS_CHROMEOS
+
 void MetricsService::LogChildProcessChange(
     NotificationType type,
     const NotificationSource& source,
diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h
index a4bee94..ec3fd70 100644
--- a/chrome/browser/metrics/metrics_service.h
+++ b/chrome/browser/metrics/metrics_service.h
@@ -125,17 +125,12 @@
   void StoreUnsentLogs();
 
 #if defined(OS_CHROMEOS)
-  // Returns the hardware class of the Chrome OS device (e.g.,
-  // hardware qualification ID), or "unknown" if the hardware class is
-  // not available.  The hardware class identifies the configured
-  // system components such us CPU, WiFi adapter, etc.  Note that this
-  // routine invokes an external utility to determine the hardware
-  // class.
-  static std::string GetHardwareClass();
-
   // Start the external metrics service, which collects metrics from Chrome OS
   // and passes them to UMA.
   void StartExternalMetrics();
+
+  // Records a Chrome OS crash.
+  void LogChromeOSCrash(const std::string &crash_type);
 #endif
 
   bool recording_active() const;
diff --git a/chrome/browser/metrics/metrics_service_uitest.cc b/chrome/browser/metrics/metrics_service_uitest.cc
index 24ea726..3d3b0d2 100644
--- a/chrome/browser/metrics/metrics_service_uitest.cc
+++ b/chrome/browser/metrics/metrics_service_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,6 +10,7 @@
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/pref_service_mock_builder.h"
@@ -99,7 +100,7 @@
   }
 
   // Give the browser a chance to notice the crashed tab.
-  base::PlatformThread::Sleep(sleep_timeout_ms());
+  base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
 
   QuitBrowser();
 
diff --git a/chrome/browser/mock_plugin_exceptions_table_model.cc b/chrome/browser/mock_plugin_exceptions_table_model.cc
index 1c88524..281777b 100644
--- a/chrome/browser/mock_plugin_exceptions_table_model.cc
+++ b/chrome/browser/mock_plugin_exceptions_table_model.cc
@@ -4,6 +4,13 @@
 
 #include "chrome/browser/mock_plugin_exceptions_table_model.h"
 
+MockPluginExceptionsTableModel::MockPluginExceptionsTableModel(
+    HostContentSettingsMap* map,
+    HostContentSettingsMap* otr_map)
+    : PluginExceptionsTableModel(map, otr_map) {}
+
+MockPluginExceptionsTableModel::~MockPluginExceptionsTableModel() {}
+
 void MockPluginExceptionsTableModel::set_plugins(
     std::vector<webkit::npapi::PluginGroup>& plugins) {
   plugins_ = plugins;
diff --git a/chrome/browser/mock_plugin_exceptions_table_model.h b/chrome/browser/mock_plugin_exceptions_table_model.h
index c63d67f..1fae316 100644
--- a/chrome/browser/mock_plugin_exceptions_table_model.h
+++ b/chrome/browser/mock_plugin_exceptions_table_model.h
@@ -13,9 +13,8 @@
 class MockPluginExceptionsTableModel : public PluginExceptionsTableModel {
  public:
   MockPluginExceptionsTableModel(HostContentSettingsMap* map,
-                                 HostContentSettingsMap* otr_map)
-      : PluginExceptionsTableModel(map, otr_map) {}
-  virtual ~MockPluginExceptionsTableModel() {}
+                                 HostContentSettingsMap* otr_map);
+  virtual ~MockPluginExceptionsTableModel();
 
   void set_plugins(std::vector<webkit::npapi::PluginGroup>& plugins);
 
diff --git a/chrome/browser/modal_html_dialog_delegate.cc b/chrome/browser/modal_html_dialog_delegate.cc
index bae474d..5999d3d 100644
--- a/chrome/browser/modal_html_dialog_delegate.cc
+++ b/chrome/browser/modal_html_dialog_delegate.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 ModalHtmlDialogDelegate::ModalHtmlDialogDelegate(
     const GURL& url, int width, int height, const std::string& json_arguments,
diff --git a/chrome/browser/modal_html_dialog_delegate.h b/chrome/browser/modal_html_dialog_delegate.h
index dbdd812..02116a1 100644
--- a/chrome/browser/modal_html_dialog_delegate.h
+++ b/chrome/browser/modal_html_dialog_delegate.h
@@ -41,8 +41,8 @@
   virtual bool IsDialogModal() const;
   virtual std::wstring GetDialogTitle() const;
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const { }
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const { }
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
diff --git a/chrome/browser/nacl_host/nacl_broker_service_win.cc b/chrome/browser/nacl_host/nacl_broker_service_win.cc
index 602f98e..a89e082 100644
--- a/chrome/browser/nacl_host/nacl_broker_service_win.cc
+++ b/chrome/browser/nacl_host/nacl_broker_service_win.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/nacl_host/nacl_broker_service_win.h"
 
 #include "chrome/browser/nacl_host/nacl_process_host.h"
-#include "chrome/common/chrome_switches.h"
 
 NaClBrokerService* NaClBrokerService::GetInstance() {
   return Singleton<NaClBrokerService>::get();
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index a009702..18b727e 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -140,6 +140,8 @@
 
   cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
 
+  SetCrashReporterCommandLine(cmd_line);
+
   // On Windows we might need to start the broker process to launch a new loader
 #if defined(OS_WIN)
   if (running_on_wow64_) {
diff --git a/chrome/browser/net/OWNERS b/chrome/browser/net/OWNERS
new file mode 100644
index 0000000..b621119
--- /dev/null
+++ b/chrome/browser/net/OWNERS
@@ -0,0 +1,4 @@
+eroman@chromium.org
+jar@chromium.org
+mmenke@chromium.org
+willchan@chromium.org
diff --git a/chrome/browser/net/browser_url_util.cc b/chrome/browser/net/browser_url_util.cc
index 786ab7d..8471140 100644
--- a/chrome/browser/net/browser_url_util.cc
+++ b/chrome/browser/net/browser_url_util.cc
@@ -4,18 +4,18 @@
 
 #include "chrome/browser/net/browser_url_util.h"
 
-#include "app/clipboard/scoped_clipboard_writer.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
 
 namespace chrome_browser_net {
 
 void WriteURLToClipboard(const GURL& url,
                          const std::string& languages,
-                         Clipboard *clipboard) {
+                         ui::Clipboard *clipboard) {
   if (url.is_empty() || !url.is_valid() || !clipboard)
     return;
 
@@ -26,7 +26,7 @@
       net::FormatUrl(url, languages, net::kFormatUrlOmitNothing,
                      UnescapeRule::NONE, NULL, NULL, NULL);
 
-  ScopedClipboardWriter scw(clipboard);
+  ui::ScopedClipboardWriter scw(clipboard);
   scw.WriteURL(text);
 }
 
diff --git a/chrome/browser/net/browser_url_util.h b/chrome/browser/net/browser_url_util.h
index 043725f..2199d36 100644
--- a/chrome/browser/net/browser_url_util.h
+++ b/chrome/browser/net/browser_url_util.h
@@ -8,15 +8,18 @@
 
 #include <string>
 
-class Clipboard;
 class GURL;
 
+namespace ui {
+class Clipboard;
+}
+
 namespace chrome_browser_net {
 
 // Writes a string representation of |url| to the system clipboard.
 void WriteURLToClipboard(const GURL& url,
                          const std::string& languages,
-                         Clipboard *clipboard);
+                         ui::Clipboard *clipboard);
 
 }  // namespace chrome_browser_net
 
diff --git a/chrome/browser/net/chrome_cookie_policy.cc b/chrome/browser/net/chrome_cookie_policy.cc
index 88ff606..dbd74d4 100644
--- a/chrome/browser/net/chrome_cookie_policy.cc
+++ b/chrome/browser/net/chrome_cookie_policy.cc
@@ -4,10 +4,12 @@
 
 #include "chrome/browser/net/chrome_cookie_policy.h"
 
+#include "base/command_line.h"
 #include "base/string_util.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/common/chrome_switches.h"
 #include "net/base/net_errors.h"
 #include "net/base/static_cookie_policy.h"
 
@@ -20,6 +22,8 @@
 
 ChromeCookiePolicy::ChromeCookiePolicy(HostContentSettingsMap* map)
     : host_content_settings_map_(map) {
+  strict_third_party_blocking_ = CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kBlockReadingThirdPartyCookies);
 }
 
 ChromeCookiePolicy::~ChromeCookiePolicy() {
@@ -32,8 +36,9 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   if (host_content_settings_map_->BlockThirdPartyCookies()) {
-    net::StaticCookiePolicy policy(
-        net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES);
+    net::StaticCookiePolicy policy(strict_third_party_blocking_ ?
+        net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
+        net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
     int rv = policy.CanGetCookies(url, first_party, NULL);
     if (rv != net::OK)
       return rv;
@@ -69,8 +74,9 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   if (host_content_settings_map_->BlockThirdPartyCookies()) {
-    net::StaticCookiePolicy policy(
-        net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES);
+    net::StaticCookiePolicy policy(strict_third_party_blocking_ ?
+        net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
+        net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
     int rv = policy.CanSetCookie(url, first_party, cookie_line, NULL);
     if (rv != net::OK)
       return rv;
diff --git a/chrome/browser/net/chrome_cookie_policy.h b/chrome/browser/net/chrome_cookie_policy.h
index ea63e6b..0e53d65 100644
--- a/chrome/browser/net/chrome_cookie_policy.h
+++ b/chrome/browser/net/chrome_cookie_policy.h
@@ -28,7 +28,7 @@
       public net::CookiePolicy {
  public:
   explicit ChromeCookiePolicy(HostContentSettingsMap* map);
-  ~ChromeCookiePolicy();
+  virtual ~ChromeCookiePolicy();
 
   // CookiePolicy methods:
   virtual int CanGetCookies(const GURL& url, const GURL& first_party,
@@ -70,6 +70,11 @@
   HostCompletionsMap host_completions_map_;
 
   scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
+
+  // True if blocking third-party cookies also applies to reading them.
+  bool strict_third_party_blocking_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeCookiePolicy);
 };
 
 #endif  // CHROME_BROWSER_NET_CHROME_COOKIE_POLICY_H_
diff --git a/chrome/browser/net/chrome_dns_cert_provenance_checker.cc b/chrome/browser/net/chrome_dns_cert_provenance_checker.cc
index fe0ca9d..c7ecb6e 100644
--- a/chrome/browser/net/chrome_dns_cert_provenance_checker.cc
+++ b/chrome/browser/net/chrome_dns_cert_provenance_checker.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -79,7 +79,7 @@
 
     // Delegate implementation
     void OnResponseStarted(net::URLRequest* request) {
-      const URLRequestStatus& status(request->status());
+      const net::URLRequestStatus& status(request->status());
       if (!status.is_success()) {
         LOG(WARNING) << "Certificate upload failed"
                      << " status:" << status.status()
diff --git a/chrome/browser/net/chrome_net_log.cc b/chrome/browser/net/chrome_net_log.cc
index 6cfc893..39ebe79 100644
--- a/chrome/browser/net/chrome_net_log.cc
+++ b/chrome/browser/net/chrome_net_log.cc
@@ -36,7 +36,7 @@
 void ChromeNetLog::ThreadSafeObserver::SetLogLevel(
     net::NetLog::LogLevel log_level) {
   DCHECK(net_log_);
-  AutoLock lock(net_log_->lock_);
+  base::AutoLock lock(net_log_->lock_);
   log_level_ = log_level;
   net_log_->UpdateLogLevel_();
 }
@@ -67,7 +67,8 @@
 
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kLogNetLog)) {
-    net_log_logger_.reset(new NetLogLogger());
+    net_log_logger_.reset(new NetLogLogger(
+            command_line.GetSwitchValuePath(switches::kLogNetLog)));
     AddObserver(net_log_logger_.get());
   }
 }
@@ -85,7 +86,7 @@
                             const Source& source,
                             EventPhase phase,
                             EventParameters* params) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   // Notify all of the log observers.
   FOR_EACH_OBSERVER(ThreadSafeObserver, observers_,
@@ -102,12 +103,12 @@
 }
 
 void ChromeNetLog::AddObserver(ThreadSafeObserver* observer) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   AddObserverWhileLockHeld(observer);
 }
 
 void ChromeNetLog::RemoveObserver(ThreadSafeObserver* observer) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK_EQ(observer->net_log_, this);
   observer->net_log_ = NULL;
   observers_.RemoveObserver(observer);
@@ -116,18 +117,18 @@
 
 void ChromeNetLog::AddObserverAndGetAllPassivelyCapturedEvents(
     ThreadSafeObserver* observer, EntryList* passive_entries) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   AddObserverWhileLockHeld(observer);
   passive_collector_->GetAllCapturedEvents(passive_entries);
 }
 
 void ChromeNetLog::GetAllPassivelyCapturedEvents(EntryList* passive_entries) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   passive_collector_->GetAllCapturedEvents(passive_entries);
 }
 
 void ChromeNetLog::ClearAllPassivelyCapturedEvents() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   passive_collector_->Clear();
 }
 
diff --git a/chrome/browser/net/chrome_net_log.h b/chrome/browser/net/chrome_net_log.h
index 12daee8..9b2c480 100644
--- a/chrome/browser/net/chrome_net_log.h
+++ b/chrome/browser/net/chrome_net_log.h
@@ -9,9 +9,9 @@
 #include <vector>
 
 #include "base/atomicops.h"
-#include "base/lock.h"
 #include "base/observer_list.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "net/base/net_log.h"
 
@@ -142,7 +142,7 @@
 
   // |lock_| protects access to |observers_| and, indirectly, to
   // |passive_collector_|.  Should not be acquired by observers.
-  Lock lock_;
+  base::Lock lock_;
 
   // Last assigned source ID.  Incremented to get the next one.
   base::subtle::Atomic32 last_id_;
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index a657b26..0c92721 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -5,11 +5,32 @@
 #include "chrome/browser/net/chrome_network_delegate.h"
 
 #include "base/logging.h"
+#include "chrome/browser/extensions/extension_webrequest_api.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
 #include "net/http/http_request_headers.h"
+#include "net/url_request/url_request.h"
+
+namespace {
+
+// Get the event router from the request context. Currently only
+// ChromeURLRequestContexts use a network delegate, so the cast is guaranteed to
+// work.
+const ExtensionIOEventRouter* GetIOEventRouter(
+    net::URLRequestContext* context) {
+  return static_cast<ChromeURLRequestContext*>(context)->
+      extension_io_event_router();
+}
+
+}  // namespace
 
 ChromeNetworkDelegate::ChromeNetworkDelegate() {}
 ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
 
+void ChromeNetworkDelegate::OnBeforeURLRequest(net::URLRequest* request) {
+  ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
+      GetIOEventRouter(request->context()), request->url(), request->method());
+}
+
 void ChromeNetworkDelegate::OnSendHttpRequest(
     net::HttpRequestHeaders* headers) {
   DCHECK(headers);
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h
index 55336d6..8bff160 100644
--- a/chrome/browser/net/chrome_network_delegate.h
+++ b/chrome/browser/net/chrome_network_delegate.h
@@ -10,15 +10,14 @@
 #include "net/http/http_network_delegate.h"
 
 // ChromeNetworkDelegate is the central point from within the chrome code to
-// add hooks into the network stack.  In the future, we can use this for
-// extensions to register hooks for the network stack.
+// add hooks into the network stack.
 class ChromeNetworkDelegate : public net::HttpNetworkDelegate {
  public:
   ChromeNetworkDelegate();
   ~ChromeNetworkDelegate();
 
   // net::HttpNetworkDelegate methods:
-
+  virtual void OnBeforeURLRequest(net::URLRequest* request);
   virtual void OnSendHttpRequest(net::HttpRequestHeaders* headers);
 
   // TODO(willchan): Add functions for consumers to register ways to
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index d06d806..573ffdc 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 #include "base/string_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager_backend.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/user_script_master.h"
 #include "chrome/browser/io_thread.h"
@@ -21,6 +22,7 @@
 #include "chrome/browser/net/predictor_api.h"
 #include "chrome/browser/net/pref_proxy_config_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
@@ -43,6 +45,8 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/libcros_service_library.h"
 #include "chrome/browser/chromeos/proxy_config_service.h"
 #endif  // defined(OS_CHROMEOS)
 
@@ -93,7 +97,7 @@
 // Create a proxy service according to the options on command line.
 net::ProxyService* CreateProxyService(
     net::NetLog* net_log,
-    URLRequestContext* context,
+    net::URLRequestContext* context,
     net::ProxyConfigService* proxy_config_service,
     const CommandLine& command_line) {
   CheckCurrentlyOnIOThread();
@@ -122,19 +126,29 @@
     }
   }
 
+  net::ProxyService* proxy_service;
   if (use_v8) {
-    return net::ProxyService::CreateUsingV8ProxyResolver(
+    proxy_service = net::ProxyService::CreateUsingV8ProxyResolver(
         proxy_config_service,
         num_pac_threads,
         new net::ProxyScriptFetcherImpl(context),
         context->host_resolver(),
         net_log);
+  } else {
+    proxy_service = net::ProxyService::CreateUsingSystemProxyResolver(
+        proxy_config_service,
+        num_pac_threads,
+        net_log);
   }
 
-  return net::ProxyService::CreateUsingSystemProxyResolver(
-      proxy_config_service,
-      num_pac_threads,
-      net_log);
+#if defined(OS_CHROMEOS)
+  if (chromeos::CrosLibrary::Get()->EnsureLoaded()) {
+    chromeos::CrosLibrary::Get()->GetLibCrosServiceLibrary()->
+        RegisterNetworkProxyHandler(proxy_service);
+  }
+#endif  // defined(OS_CHROMEOS)
+
+  return proxy_service;
 }
 
 // ----------------------------------------------------------------------------
@@ -230,41 +244,29 @@
 class FactoryForOriginal : public ChromeURLRequestContextFactory {
  public:
   FactoryForOriginal(Profile* profile,
-                     const FilePath& cookie_store_path,
-                     const FilePath& disk_cache_path,
-                     int cache_size)
+                     const ProfileIOData* profile_io_data)
       : ChromeURLRequestContextFactory(profile),
-        cookie_store_path_(cookie_store_path),
-        disk_cache_path_(disk_cache_path),
-        cache_size_(cache_size),
+        profile_io_data_(profile_io_data),
         // We need to initialize the ProxyConfigService from the UI thread
         // because on linux it relies on initializing things through gconf,
         // and needs to be on the main thread.
         proxy_config_service_(CreateProxyConfigService(profile)) {
   }
 
-  virtual ChromeURLRequestContext* Create();
+  virtual scoped_refptr<ChromeURLRequestContext> Create();
 
  private:
-  FilePath cookie_store_path_;
-  FilePath disk_cache_path_;
-  int cache_size_;
-
+  const scoped_refptr<const ProfileIOData> profile_io_data_;
   scoped_ptr<net::ProxyConfigService> proxy_config_service_;
 };
 
-ChromeURLRequestContext* FactoryForOriginal::Create() {
-  ChromeURLRequestContext* context = new ChromeURLRequestContext;
+scoped_refptr<ChromeURLRequestContext> FactoryForOriginal::Create() {
+  scoped_refptr<ChromeURLRequestContext> context =
+      profile_io_data_->GetMainRequestContext();
   ApplyProfileParametersToContext(context);
 
   IOThread::Globals* io_thread_globals = io_thread()->globals();
-
-  // Global host resolver for the context.
-  context->set_host_resolver(io_thread_globals->host_resolver.get());
-  context->set_cert_verifier(io_thread_globals->cert_verifier.get());
-  context->set_dnsrr_resolver(io_thread_globals->dnsrr_resolver.get());
-  context->set_http_auth_handler_factory(
-      io_thread_globals->http_auth_handler_factory.get());
+  const ProfileIOData::LazyParams& params = profile_io_data_->lazy_params();
 
   context->set_dns_cert_checker(
       CreateDnsCertProvenanceChecker(io_thread_globals->dnsrr_resolver.get(),
@@ -279,19 +281,19 @@
                          command_line));
 
   net::HttpCache::DefaultBackend* backend = new net::HttpCache::DefaultBackend(
-      net::DISK_CACHE, disk_cache_path_, cache_size_,
+      net::DISK_CACHE, params.cache_path, params.cache_max_size,
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
-  net::HttpCache* cache =
-      new net::HttpCache(context->host_resolver(),
-                         context->cert_verifier(),
-                         context->dnsrr_resolver(),
-                         context->dns_cert_checker(),
-                         context->proxy_service(),
-                         context->ssl_config_service(),
-                         context->http_auth_handler_factory(),
-                         &io_thread_globals->network_delegate,
-                         io_thread()->net_log(),
-                         backend);
+  net::HttpCache* cache = new net::HttpCache(
+      context->host_resolver(),
+      context->cert_verifier(),
+      context->dnsrr_resolver(),
+      context->dns_cert_checker(),
+      context->proxy_service(),
+      context->ssl_config_service(),
+      context->http_auth_handler_factory(),
+      &io_thread_globals->network_delegate,
+      io_thread()->net_log(),
+      backend);
 
   bool record_mode = chrome::kRecordModeEnabled &&
                      command_line.HasSwitch(switches::kRecordMode);
@@ -311,10 +313,10 @@
 
   // setup cookie store
   if (!context->cookie_store()) {
-    DCHECK(!cookie_store_path_.empty());
+    DCHECK(!params.cookie_path.empty());
 
     scoped_refptr<SQLitePersistentCookieStore> cookie_db =
-        new SQLitePersistentCookieStore(cookie_store_path_);
+        new SQLitePersistentCookieStore(params.cookie_path);
     cookie_db->SetClearLocalStateOnExit(clear_local_state_on_exit_);
     context->set_cookie_store(new net::CookieMonster(cookie_db.get(),
         cookie_monster_delegate_));
@@ -324,30 +326,33 @@
       new ChromeCookiePolicy(host_content_settings_map_));
 
   appcache_service_->set_request_context(context);
-
-  context->set_net_log(io_thread()->net_log());
   return context;
 }
 
 // Factory that creates the ChromeURLRequestContext for extensions.
 class FactoryForExtensions : public ChromeURLRequestContextFactory {
  public:
-  FactoryForExtensions(Profile* profile, const FilePath& cookie_store_path,
+  FactoryForExtensions(Profile* profile, const ProfileIOData* profile_io_data,
                        bool incognito)
       : ChromeURLRequestContextFactory(profile),
-        cookie_store_path_(cookie_store_path),
+        profile_io_data_(profile_io_data),
         incognito_(incognito) {
+    DCHECK(incognito || profile_io_data);
   }
 
-  virtual ChromeURLRequestContext* Create();
+  virtual scoped_refptr<ChromeURLRequestContext> Create();
 
  private:
-  FilePath cookie_store_path_;
-  bool incognito_;
+  const scoped_refptr<const ProfileIOData> profile_io_data_;
+  const bool incognito_;
 };
 
-ChromeURLRequestContext* FactoryForExtensions::Create() {
-  ChromeURLRequestContext* context = new ChromeURLRequestContext;
+scoped_refptr<ChromeURLRequestContext> FactoryForExtensions::Create() {
+  scoped_refptr<ChromeURLRequestContext> context = NULL;
+  if (incognito_)
+    context = new ChromeURLRequestContext;
+  else
+    context = profile_io_data_->GetExtensionsRequestContext();
   ApplyProfileParametersToContext(context);
 
   IOThread::Globals* io_thread_globals = io_thread()->globals();
@@ -356,8 +361,10 @@
   // use a non-persistent cookie store.
   scoped_refptr<SQLitePersistentCookieStore> cookie_db = NULL;
   if (!incognito_) {
-    DCHECK(!cookie_store_path_.empty());
-    cookie_db = new SQLitePersistentCookieStore(cookie_store_path_);
+    const FilePath& cookie_store_path =
+        profile_io_data_->lazy_params().extensions_cookie_path;
+    DCHECK(!cookie_store_path.empty());
+    cookie_db = new SQLitePersistentCookieStore(cookie_store_path);
   }
 
   net::CookieMonster* cookie_monster =
@@ -368,6 +375,7 @@
                            chrome::kExtensionScheme};
   cookie_monster->SetCookieableSchemes(schemes, 2);
   context->set_cookie_store(cookie_monster);
+  context->set_network_delegate(&io_thread_globals->network_delegate);
   // TODO(cbentzel): How should extensions handle HTTP Authentication?
   context->set_http_auth_handler_factory(
       io_thread_globals->http_auth_handler_factory.get());
@@ -380,45 +388,48 @@
  public:
   explicit FactoryForOffTheRecord(Profile* profile)
       : ChromeURLRequestContextFactory(profile),
+        proxy_config_service_(CreateProxyConfigService(profile)),
         original_context_getter_(
             static_cast<ChromeURLRequestContextGetter*>(
                 profile->GetOriginalProfile()->GetRequestContext())) {
   }
 
-  virtual ChromeURLRequestContext* Create();
+  virtual scoped_refptr<ChromeURLRequestContext> Create();
 
  private:
+  scoped_ptr<net::ProxyConfigService> proxy_config_service_;
   scoped_refptr<ChromeURLRequestContextGetter> original_context_getter_;
 };
 
-ChromeURLRequestContext* FactoryForOffTheRecord::Create() {
-  ChromeURLRequestContext* context = new ChromeURLRequestContext;
+scoped_refptr<ChromeURLRequestContext> FactoryForOffTheRecord::Create() {
+  scoped_refptr<ChromeURLRequestContext> context = new ChromeURLRequestContext;
   ApplyProfileParametersToContext(context);
 
-  ChromeURLRequestContext* original_context =
-      original_context_getter_->GetIOContext();
-
   IOThread::Globals* io_thread_globals = io_thread()->globals();
-
-  // Share the same proxy service, host resolver, cert verifier,
-  // and http_auth_handler_factory as the original profile.
-  context->set_host_resolver(original_context->host_resolver());
-  context->set_cert_verifier(original_context->cert_verifier());
-  context->set_proxy_service(original_context->proxy_service());
+  context->set_host_resolver(io_thread_globals->host_resolver.get());
+  context->set_cert_verifier(io_thread_globals->cert_verifier.get());
   context->set_http_auth_handler_factory(
-      original_context->http_auth_handler_factory());
+      io_thread_globals->http_auth_handler_factory.get());
+  context->set_network_delegate(&io_thread_globals->network_delegate);
+
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  context->set_proxy_service(
+      CreateProxyService(io_thread()->net_log(),
+                         io_thread_globals->proxy_script_fetcher_context.get(),
+                         proxy_config_service_.release(),
+                         command_line));
 
   net::HttpCache::BackendFactory* backend =
       net::HttpCache::DefaultBackend::InMemory(0);
 
   net::HttpCache* cache =
-      new net::HttpCache(context->host_resolver(),
-                         context->cert_verifier(),
+      new net::HttpCache(io_thread_globals->host_resolver.get(),
+                         io_thread_globals->cert_verifier.get(),
                          context->dnsrr_resolver(),
                          NULL /* dns_cert_checker */,
                          context->proxy_service(),
                          context->ssl_config_service(),
-                         context->http_auth_handler_factory(),
+                         io_thread_globals->http_auth_handler_factory.get(),
                          &io_thread_globals->network_delegate,
                          io_thread()->net_log(),
                          backend);
@@ -441,41 +452,33 @@
 class FactoryForMedia : public ChromeURLRequestContextFactory {
  public:
   FactoryForMedia(Profile* profile,
-                  const FilePath& disk_cache_path,
-                  int cache_size,
-                  bool off_the_record)
+                  const ProfileIOData* profile_io_data)
       : ChromeURLRequestContextFactory(profile),
         main_context_getter_(
             static_cast<ChromeURLRequestContextGetter*>(
                 profile->GetRequestContext())),
-        disk_cache_path_(disk_cache_path),
-        cache_size_(cache_size) {
-    is_media_ = true;
-    is_off_the_record_ = off_the_record;
+        profile_io_data_(profile_io_data) {
   }
 
-  virtual ChromeURLRequestContext* Create();
+  virtual scoped_refptr<ChromeURLRequestContext> Create();
 
  private:
   scoped_refptr<ChromeURLRequestContextGetter> main_context_getter_;
-
-  FilePath disk_cache_path_;
-  int cache_size_;
+  const scoped_refptr<const ProfileIOData> profile_io_data_;
 };
 
-ChromeURLRequestContext* FactoryForMedia::Create() {
-  ChromeURLRequestContext* context = new ChromeURLRequestContext;
+scoped_refptr<ChromeURLRequestContext> FactoryForMedia::Create() {
+  scoped_refptr<ChromeURLRequestContext> context =
+      profile_io_data_->GetMediaRequestContext();
   ApplyProfileParametersToContext(context);
 
-  ChromeURLRequestContext* main_context =
-      main_context_getter_->GetIOContext();
+  ChromeURLRequestContext* main_context = main_context_getter_->GetIOContext();
 
-  IOThread::Globals* io_thread_globals = io_thread()->globals();
+  const ProfileIOData::LazyParams& params = profile_io_data_->lazy_params();
 
-  // Share the same proxy service of the common profile.
+  // TODO(willchan): Make a global ProxyService available in IOThread::Globals.
   context->set_proxy_service(main_context->proxy_service());
-  context->set_http_auth_handler_factory(
-      main_context->http_auth_handler_factory());
+  context->set_network_delegate(main_context->network_delegate());
 
   // Also share the cookie store of the common profile.
   context->set_cookie_store(main_context->cookie_store());
@@ -485,39 +488,13 @@
   // Create a media cache with default size.
   // TODO(hclam): make the maximum size of media cache configurable.
   net::HttpCache::DefaultBackend* backend = new net::HttpCache::DefaultBackend(
-      net::MEDIA_CACHE, disk_cache_path_, cache_size_,
+      net::MEDIA_CACHE, params.media_cache_path, params.media_cache_max_size,
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
 
   net::HttpCache* main_cache =
       main_context->http_transaction_factory()->GetCache();
-  net::HttpCache* cache;
-  if (main_cache) {
-    // Try to reuse HttpNetworkSession in the main context, assuming that
-    // HttpTransactionFactory (network_layer()) of HttpCache is implemented
-    // by HttpNetworkLayer so we can reuse HttpNetworkSession within it. This
-    // assumption will be invalid if the original HttpCache is constructed with
-    // HttpCache(HttpTransactionFactory*, BackendFactory*) constructor.
-    net::HttpNetworkLayer* main_network_layer =
-        static_cast<net::HttpNetworkLayer*>(main_cache->network_layer());
-    cache = new net::HttpCache(main_network_layer->GetSession(), backend);
-    // TODO(eroman): Since this is poaching the session from the main
-    // context, it should hold a reference to that context preventing the
-    // session from getting deleted.
-  } else {
-    // If original HttpCache doesn't exist, simply construct one with a whole
-    // new set of network stack.
-    cache = new net::HttpCache(main_context->host_resolver(),
-                               main_context->cert_verifier(),
-                               main_context->dnsrr_resolver(),
-                               NULL /* dns_cert_checker */,
-                               main_context->proxy_service(),
-                               main_context->ssl_config_service(),
-                               main_context->http_auth_handler_factory(),
-                               &io_thread_globals->network_delegate,
-                               io_thread()->net_log(),
-                               backend);
-  }
-
+  net::HttpNetworkSession* network_session = main_cache->GetSession();
+  net::HttpCache* cache = new net::HttpCache(network_session, backend);
   context->set_http_transaction_factory(cache);
   context->set_net_log(io_thread()->net_log());
 
@@ -548,7 +525,7 @@
 
   DCHECK(registrar_.IsEmpty()) << "Probably didn't call CleanupOnUIThread";
 
-  // Either we already transformed the factory into a URLRequestContext, or
+  // Either we already transformed the factory into a net::URLRequestContext, or
   // we still have a pending factory.
   DCHECK((factory_.get() && !url_request_context_.get()) ||
          (!factory_.get() && url_request_context_.get()));
@@ -561,7 +538,7 @@
 }
 
 // Lazily create a ChromeURLRequestContext using our factory.
-URLRequestContext* ChromeURLRequestContextGetter::GetURLRequestContext() {
+net::URLRequestContext* ChromeURLRequestContextGetter::GetURLRequestContext() {
   CheckCurrentlyOnIOThread();
 
   if (!url_request_context_) {
@@ -570,7 +547,8 @@
     if (is_main()) {
       url_request_context_->set_is_main(true);
 #if defined(USE_NSS)
-      // TODO(ukai): find a better way to set the URLRequestContext for OCSP.
+      // TODO(ukai): find a better way to set the net::URLRequestContext for
+      // OCSP.
       net::SetURLRequestContextForOCSP(url_request_context_);
 #endif
     }
@@ -618,34 +596,32 @@
 
 // static
 ChromeURLRequestContextGetter* ChromeURLRequestContextGetter::CreateOriginal(
-    Profile* profile, const FilePath& cookie_store_path,
-    const FilePath& disk_cache_path, int cache_size) {
+    Profile* profile,
+    const ProfileIOData* profile_io_data) {
   DCHECK(!profile->IsOffTheRecord());
   return new ChromeURLRequestContextGetter(
       profile,
-      new FactoryForOriginal(profile,
-                             cookie_store_path,
-                             disk_cache_path,
-                             cache_size));
+      new FactoryForOriginal(profile, profile_io_data));
 }
 
 // static
 ChromeURLRequestContextGetter*
 ChromeURLRequestContextGetter::CreateOriginalForMedia(
-    Profile* profile, const FilePath& disk_cache_path, int cache_size) {
+    Profile* profile, const ProfileIOData* profile_io_data) {
   DCHECK(!profile->IsOffTheRecord());
-  return CreateRequestContextForMedia(profile, disk_cache_path, cache_size,
-                                      false);
+  return new ChromeURLRequestContextGetter(
+      profile,
+      new FactoryForMedia(profile, profile_io_data));
 }
 
 // static
 ChromeURLRequestContextGetter*
 ChromeURLRequestContextGetter::CreateOriginalForExtensions(
-    Profile* profile, const FilePath& cookie_store_path) {
+    Profile* profile, const ProfileIOData* profile_io_data) {
   DCHECK(!profile->IsOffTheRecord());
   return new ChromeURLRequestContextGetter(
       profile,
-      new FactoryForExtensions(profile, cookie_store_path, false));
+      new FactoryForExtensions(profile, profile_io_data, false));
 }
 
 // static
@@ -662,7 +638,7 @@
     Profile* profile) {
   DCHECK(profile->IsOffTheRecord());
   return new ChromeURLRequestContextGetter(
-      profile, new FactoryForExtensions(profile, FilePath(), true));
+      profile, new FactoryForExtensions(profile, NULL, true));
 }
 
 void ChromeURLRequestContextGetter::CleanupOnUIThread() {
@@ -724,19 +700,6 @@
   registrar_.Add(prefs::kClearSiteDataOnExit, this);
 }
 
-// static
-ChromeURLRequestContextGetter*
-ChromeURLRequestContextGetter::CreateRequestContextForMedia(
-    Profile* profile, const FilePath& disk_cache_path, int cache_size,
-    bool off_the_record) {
-  return new ChromeURLRequestContextGetter(
-      profile,
-      new FactoryForMedia(profile,
-                          disk_cache_path,
-                          cache_size,
-                          off_the_record));
-}
-
 void ChromeURLRequestContextGetter::OnAcceptLanguageChange(
     const std::string& accept_language) {
   GetIOContext()->OnAcceptLanguageChange(accept_language);
@@ -766,11 +729,17 @@
 // ----------------------------------------------------------------------------
 
 ChromeURLRequestContext::ChromeURLRequestContext()
-    : is_media_(false),
-      is_off_the_record_(false) {
+    : is_off_the_record_(false) {
   CheckCurrentlyOnIOThread();
 }
 
+ChromeURLDataManagerBackend*
+    ChromeURLRequestContext::GetChromeURLDataManagerBackend() {
+  if (!chrome_url_data_manager_backend_.get())
+    chrome_url_data_manager_backend_.reset(new ChromeURLDataManagerBackend());
+  return chrome_url_data_manager_backend_.get();
+}
+
 ChromeURLRequestContext::~ChromeURLRequestContext() {
   CheckCurrentlyOnIOThread();
 
@@ -786,10 +755,10 @@
 
 #if defined(USE_NSS)
   if (is_main()) {
-    URLRequestContext* ocsp_context = net::GetURLRequestContextForOCSP();
+    net::URLRequestContext* ocsp_context = net::GetURLRequestContextForOCSP();
     if (ocsp_context) {
       DCHECK_EQ(this, ocsp_context);
-      // We are releasing the URLRequestContext used by OCSP handlers.
+      // We are releasing the net::URLRequestContext used by OCSP handlers.
       net::SetURLRequestContextForOCSP(NULL);
     }
   }
@@ -797,7 +766,7 @@
 
   NotificationService::current()->Notify(
       NotificationType::URL_REQUEST_CONTEXT_RELEASED,
-      Source<URLRequestContext>(this),
+      Source<net::URLRequestContext>(this),
       NotificationService::NoDetails());
 
   delete ftp_transaction_factory_;
@@ -805,7 +774,7 @@
 
   // cookie_policy_'s lifetime is auto-managed by chrome_cookie_policy_.  We
   // null this out here to avoid a dangling reference to chrome_cookie_policy_
-  // when ~URLRequestContext runs.
+  // when ~net::URLRequestContext runs.
   cookie_policy_ = NULL;
 }
 
@@ -814,10 +783,6 @@
   return webkit_glue::GetUserAgent(url);
 }
 
-bool ChromeURLRequestContext::IsExternal() const {
-  return false;
-}
-
 void ChromeURLRequestContext::OnAcceptLanguageChange(
     const std::string& accept_language) {
   CheckCurrentlyOnIOThread();
@@ -842,8 +807,7 @@
 // ChromeURLRequestContext on the IO thread (see
 // ApplyProfileParametersToContext() which reverses this).
 ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile)
-    : is_media_(false),
-      is_off_the_record_(profile->IsOffTheRecord()),
+    : is_off_the_record_(profile->IsOffTheRecord()),
       io_thread_(g_browser_process->io_thread()) {
   CheckCurrentlyOnMainThread();
   PrefService* prefs = profile->GetPrefs();
@@ -885,6 +849,8 @@
   blob_storage_context_ = profile->GetBlobStorageContext();
   file_system_context_ = profile->GetFileSystemContext();
   extension_info_map_ = profile->GetExtensionInfoMap();
+  extension_io_event_router_ = profile->GetExtensionIOEventRouter();
+  prerender_manager_ = profile->GetPrerenderManager();
 }
 
 ChromeURLRequestContextFactory::~ChromeURLRequestContextFactory() {
@@ -895,7 +861,6 @@
     ChromeURLRequestContext* context) {
   // Apply all the parameters. NOTE: keep this in sync with
   // ChromeURLRequestContextFactory(Profile*).
-  context->set_is_media(is_media_);
   context->set_is_off_the_record(is_off_the_record_);
   context->set_accept_language(accept_language_);
   context->set_accept_charset(accept_charset_);
@@ -911,4 +876,6 @@
   context->set_blob_storage_context(blob_storage_context_);
   context->set_file_system_context(file_system_context_);
   context->set_extension_info_map(extension_info_map_);
+  context->set_extension_io_event_router(extension_io_event_router_);
+  context->set_prerender_manager(prerender_manager_);
 }
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 93f0e37..494bf50 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -14,34 +14,38 @@
 #include "chrome/browser/chrome_blob_storage_context.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/extensions/extension_info_map.h"
+#include "chrome/browser/extensions/extension_io_event_router.h"
+#include "chrome/browser/extensions/extension_webrequest_api.h"
 #include "chrome/browser/host_zoom_map.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/net/chrome_cookie_policy.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/net/url_request_context_getter.h"
-#include "chrome/common/notification_registrar.h"
 #include "net/base/cookie_monster.h"
 #include "net/base/cookie_policy.h"
 #include "net/url_request/url_request_context.h"
 #include "webkit/database/database_tracker.h"
-#include "webkit/fileapi/sandboxed_file_system_context.h"
+#include "webkit/fileapi/file_system_context.h"
 
 class CommandLine;
 class PrefService;
 class Profile;
+class ProfileIOData;
 
 namespace net {
 class DnsCertProvenanceChecker;
 class NetworkDelegate;
 }
 
+class ChromeURLDataManagerBackend;
 class ChromeURLRequestContext;
 class ChromeURLRequestContextFactory;
 
-// Subclass of URLRequestContext which can be used to store extra information
-// for requests.
+// Subclass of net::URLRequestContext which can be used to store extra
+// information for requests.
 //
 // All methods of this class must be called from the IO thread,
 // including the constructor and destructor.
@@ -71,16 +75,13 @@
   }
 
   // Gets the file system host context with this context's profile.
-  fileapi::SandboxedFileSystemContext* file_system_context() const {
+  fileapi::FileSystemContext* file_system_context() const {
     return file_system_context_.get();
   }
 
   bool is_off_the_record() const {
     return is_off_the_record_;
   }
-  bool is_media() const {
-    return is_media_;
-  }
 
   virtual const std::string& GetUserAgent(const GURL& url) const;
 
@@ -94,9 +95,15 @@
     return extension_info_map_;
   }
 
-  // Returns true if this context is an external request context, like
-  // ChromeFrame.
-  virtual bool IsExternal() const;
+  const ExtensionIOEventRouter* extension_io_event_router() const {
+    return extension_io_event_router_;
+  }
+
+  PrerenderManager* prerender_manager() {
+    return prerender_manager_.get();
+  }
+
+  ChromeURLDataManagerBackend* GetChromeURLDataManagerBackend();
 
  protected:
   virtual ~ChromeURLRequestContext();
@@ -136,9 +143,6 @@
   void set_is_off_the_record(bool is_off_the_record) {
     is_off_the_record_ = is_off_the_record;
   }
-  void set_is_media(bool is_media) {
-    is_media_ = is_media;
-  }
   void set_host_content_settings_map(
       HostContentSettingsMap* host_content_settings_map) {
     host_content_settings_map_ = host_content_settings_map;
@@ -155,15 +159,17 @@
   void set_blob_storage_context(ChromeBlobStorageContext* context) {
     blob_storage_context_ = context;
   }
-  void set_file_system_context(fileapi::SandboxedFileSystemContext* context) {
+  void set_file_system_context(fileapi::FileSystemContext* context) {
     file_system_context_ = context;
   }
   void set_extension_info_map(ExtensionInfoMap* map) {
     extension_info_map_ = map;
   }
-  void set_network_delegate(
-      net::HttpNetworkDelegate* network_delegate) {
-    network_delegate_ = network_delegate;
+  void set_extension_io_event_router(ExtensionIOEventRouter* router) {
+    extension_io_event_router_ = router;
+  }
+  void set_prerender_manager(PrerenderManager* prerender_manager) {
+    prerender_manager_ = prerender_manager;
   }
 
   // Callback for when the accept language changes.
@@ -176,16 +182,20 @@
   // Path to the directory user scripts are stored in.
   FilePath user_script_dir_path_;
 
+  // TODO(willchan): Make these non-refcounted.
   scoped_refptr<ChromeAppCacheService> appcache_service_;
   scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
   scoped_refptr<ChromeCookiePolicy> chrome_cookie_policy_;
   scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
   scoped_refptr<HostZoomMap> host_zoom_map_;
   scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
-  scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+  scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+  // TODO(aa): This should use chrome/common/extensions/extension_set.h.
   scoped_refptr<ExtensionInfoMap> extension_info_map_;
+  scoped_refptr<ExtensionIOEventRouter> extension_io_event_router_;
+  scoped_refptr<PrerenderManager> prerender_manager_;
+  scoped_ptr<ChromeURLDataManagerBackend> chrome_url_data_manager_backend_;
 
-  bool is_media_;
   bool is_off_the_record_;
 
  private:
@@ -193,8 +203,8 @@
 };
 
 // A URLRequestContextGetter subclass used by the browser. This returns a
-// subclass of URLRequestContext which can be used to store extra information
-// about requests.
+// subclass of net::URLRequestContext which can be used to store extra
+// information about requests.
 //
 // Most methods are expected to be called on the UI thread, except for
 // the destructor and GetURLRequestContext().
@@ -223,7 +233,7 @@
   void ReleaseURLRequestContext();
 
   // Convenience overload of GetURLRequestContext() that returns a
-  // ChromeURLRequestContext* rather than a URLRequestContext*.
+  // ChromeURLRequestContext* rather than a net::URLRequestContext*.
   ChromeURLRequestContext* GetIOContext() {
     return reinterpret_cast<ChromeURLRequestContext*>(GetURLRequestContext());
   }
@@ -231,19 +241,18 @@
   // Create an instance for use with an 'original' (non-OTR) profile. This is
   // expected to get called on the UI thread.
   static ChromeURLRequestContextGetter* CreateOriginal(
-      Profile* profile, const FilePath& cookie_store_path,
-      const FilePath& disk_cache_path, int cache_size);
+      Profile* profile, const ProfileIOData* profile_io_data);
 
   // Create an instance for an original profile for media. This is expected to
   // get called on UI thread. This method takes a profile and reuses the
-  // 'original' URLRequestContext for common files.
+  // 'original' net::URLRequestContext for common files.
   static ChromeURLRequestContextGetter* CreateOriginalForMedia(
-      Profile* profile, const FilePath& disk_cache_path, int cache_size);
+      Profile* profile, const ProfileIOData* profile_io_data);
 
   // Create an instance for an original profile for extensions. This is expected
   // to get called on UI thread.
   static ChromeURLRequestContextGetter* CreateOriginalForExtensions(
-      Profile* profile, const FilePath& cookie_store_path);
+      Profile* profile, const ProfileIOData* profile_io_data);
 
   // Create an instance for use with an OTR profile. This is expected to get
   // called on the UI thread.
@@ -271,13 +280,6 @@
   // to update the context when the default language and charset change.
   void RegisterPrefsObserver(Profile* profile);
 
-  // Creates a request context for media resources from a regular request
-  // context. This helper method is called from CreateOriginalForMedia and
-  // CreateOffTheRecordForMedia.
-  static ChromeURLRequestContextGetter* CreateRequestContextForMedia(
-      Profile* profile, const FilePath& disk_cache_path, int cache_size,
-      bool off_the_record);
-
   // These methods simply forward to the corresponding method on
   // ChromeURLRequestContext.
   void OnAcceptLanguageChange(const std::string& accept_language);
@@ -298,7 +300,7 @@
   // Access only from the IO thread.
   scoped_ptr<ChromeURLRequestContextFactory> factory_;
 
-  // NULL if not yet initialized. Otherwise, it is the URLRequestContext
+  // NULL if not yet initialized. Otherwise, it is the net::URLRequestContext
   // instance that was lazilly created by GetURLRequestContext.
   // Access only from the IO thread.
   scoped_refptr<net::URLRequestContext> url_request_context_;
@@ -321,7 +323,7 @@
   virtual ~ChromeURLRequestContextFactory();
 
   // Called to create a new instance (will only be called once).
-  virtual ChromeURLRequestContext* Create() = 0;
+  virtual scoped_refptr<ChromeURLRequestContext> Create() = 0;
 
  protected:
   IOThread* io_thread() { return io_thread_; }
@@ -333,7 +335,6 @@
   //
   // NOTE: If you add any parameters here, keep it in sync with
   // ApplyProfileParametersToContext().
-  bool is_media_;
   bool is_off_the_record_;
   bool clear_local_state_on_exit_;
   std::string accept_language_;
@@ -342,6 +343,7 @@
 
   // TODO(aa): I think this can go away now as we no longer support standalone
   // user scripts.
+  // TODO(willchan): Make these non-refcounted.
   FilePath user_script_dir_path_;
   scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
   scoped_refptr<ChromeAppCacheService> appcache_service_;
@@ -351,8 +353,10 @@
   scoped_refptr<net::SSLConfigService> ssl_config_service_;
   scoped_refptr<net::CookieMonster::Delegate> cookie_monster_delegate_;
   scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
-  scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+  scoped_refptr<fileapi::FileSystemContext> file_system_context_;
   scoped_refptr<ExtensionInfoMap> extension_info_map_;
+  scoped_refptr<ExtensionIOEventRouter> extension_io_event_router_;
+  scoped_refptr<PrerenderManager> prerender_manager_;
 
   FilePath profile_dir_path_;
 
diff --git a/chrome/browser/net/connect_interceptor.cc b/chrome/browser/net/connect_interceptor.cc
index 3809da2..56ecbc9 100644
--- a/chrome/browser/net/connect_interceptor.cc
+++ b/chrome/browser/net/connect_interceptor.cc
@@ -49,19 +49,15 @@
     }
   } else {
     GURL referring_scheme_host = GURL(request->referrer()).GetWithEmptyPath();
-    if (referring_scheme_host == request_scheme_host) {
-      // There is nothing to learn about preconnections when the referrer is
-      // already the site needed in the request URL.  Similarly, we've already
-      // made any/all predictions when we navigated to the referring host, so we
-      // can bail out here. This will also avoid useless boosting of the number
-      // of times we navigated to this site, which was already accounted for by
-      // the navigation to the referrering_url.
-      return NULL;
-    }
     bool is_subresource = !(request->load_flags() & net::LOAD_MAIN_FRAME);
     // Learn about our referring URL, for use in the future.
     if (is_subresource)
       LearnFromNavigation(referring_scheme_host, request_scheme_host);
+    if (referring_scheme_host == request_scheme_host) {
+      // We've already made any/all predictions when we navigated to the
+      // referring host, so we can bail out here.
+      return NULL;
+    }
   }
 
   // Subresources for main frames usually get predicted when we detected the
diff --git a/chrome/browser/net/connection_tester.cc b/chrome/browser/net/connection_tester.cc
index f23d619..d0a7c95 100644
--- a/chrome/browser/net/connection_tester.cc
+++ b/chrome/browser/net/connection_tester.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
+#include "base/task.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/importer/firefox_proxy_settings.h"
@@ -25,7 +26,7 @@
 #include "net/ftp/ftp_network_layer.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_cache.h"
-#include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/proxy/proxy_script_fetcher_impl.h"
 #include "net/url_request/url_request.h"
@@ -38,9 +39,10 @@
 // An instance of ExperimentURLRequestContext is created for each experiment
 // run by ConnectionTester. The class initializes network dependencies according
 // to the specified "experiment".
-class ExperimentURLRequestContext : public URLRequestContext {
+class ExperimentURLRequestContext : public net::URLRequestContext {
  public:
-  explicit ExperimentURLRequestContext(URLRequestContext* proxy_request_context)
+  explicit ExperimentURLRequestContext(
+      net::URLRequestContext* proxy_request_context)
       : proxy_request_context_(proxy_request_context) {}
 
   int Init(const ConnectionTester::Experiment& experiment) {
@@ -66,12 +68,18 @@
     ssl_config_service_ = new net::SSLConfigServiceDefaults;
     http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
         host_resolver_);
+
+    net::HttpNetworkSession::Params session_params;
+    session_params.host_resolver = host_resolver_;
+    session_params.dnsrr_resolver = dnsrr_resolver_;
+    session_params.cert_verifier = cert_verifier_;
+    session_params.proxy_service = proxy_service_;
+    session_params.http_auth_handler_factory = http_auth_handler_factory_;
+    session_params.ssl_config_service = ssl_config_service_;
+    scoped_refptr<net::HttpNetworkSession> network_session(
+        new net::HttpNetworkSession(session_params));
     http_transaction_factory_ = new net::HttpCache(
-        net::HttpNetworkLayer::CreateFactory(host_resolver_, cert_verifier_,
-            dnsrr_resolver_, NULL /* dns_cert_checker */,
-            NULL /* ssl_host_info_factory */, proxy_service_,
-            ssl_config_service_, http_auth_handler_factory_, NULL, NULL),
-        NULL /* net_log */,
+        network_session,
         net::HttpCache::DefaultBackend::InMemory(0));
     // In-memory cookie store.
     cookie_store_ = new net::CookieMonster(NULL, NULL);
@@ -223,7 +231,7 @@
     return net::ERR_FAILED;
   }
 
-  const scoped_refptr<URLRequestContext> proxy_request_context_;
+  const scoped_refptr<net::URLRequestContext> proxy_request_context_;
 };
 
 }  // namespace
@@ -236,7 +244,9 @@
  public:
   // |tester| must remain alive throughout the TestRunner's lifetime.
   // |tester| will be notified of completion.
-  explicit TestRunner(ConnectionTester* tester) : tester_(tester) {}
+  explicit TestRunner(ConnectionTester* tester)
+      : tester_(tester),
+        ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}
 
   // Starts running |experiment|. Notifies tester->OnExperimentCompleted() when
   // it is done.
@@ -257,10 +267,13 @@
 
   // Called when the request has completed (for both success and failure).
   void OnResponseCompleted(net::URLRequest* request);
+  void OnExperimentCompletedWithResult(int result);
 
   ConnectionTester* tester_;
   scoped_ptr<net::URLRequest> request_;
 
+  ScopedRunnableMethodFactory<TestRunner> method_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(TestRunner);
 };
 
@@ -305,11 +318,22 @@
     DCHECK_NE(net::ERR_IO_PENDING, request->status().os_error());
     result = request->status().os_error();
   }
+
+  // Post a task to notify the parent rather than handling it right away,
+  // to avoid re-entrancy problems with URLRequest. (Don't want the caller
+  // to end up deleting the URLRequest while in the middle of processing).
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &TestRunner::OnExperimentCompletedWithResult, result));
+}
+
+void ConnectionTester::TestRunner::OnExperimentCompletedWithResult(int result) {
   tester_->OnExperimentCompleted(result);
 }
 
 void ConnectionTester::TestRunner::Run(const Experiment& experiment) {
-  // Try to create a URLRequestContext for this experiment.
+  // Try to create a net::URLRequestContext for this experiment.
   scoped_refptr<ExperimentURLRequestContext> context(
       new ExperimentURLRequestContext(tester_->proxy_request_context_));
   int rv = context->Init(experiment);
@@ -327,8 +351,9 @@
 
 // ConnectionTester ----------------------------------------------------------
 
-ConnectionTester::ConnectionTester(Delegate* delegate,
-                                   URLRequestContext* proxy_request_context)
+ConnectionTester::ConnectionTester(
+    Delegate* delegate,
+    net::URLRequestContext* proxy_request_context)
     : delegate_(delegate), proxy_request_context_(proxy_request_context) {
   DCHECK(delegate);
   DCHECK(proxy_request_context);
diff --git a/chrome/browser/net/connection_tester_unittest.cc b/chrome/browser/net/connection_tester_unittest.cc
index 6735599..0bb5f50 100644
--- a/chrome/browser/net/connection_tester_unittest.cc
+++ b/chrome/browser/net/connection_tester_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,9 +14,8 @@
 #include "net/ftp/ftp_network_layer.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
 #include "net/proxy/proxy_config_service_fixed.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/spdy/spdy_session_pool.h"
 #include "net/test/test_server.h"
 #include "net/url_request/url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -87,8 +86,7 @@
   ConnectionTesterTest()
       : test_server_(net::TestServer::TYPE_HTTP,
             FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))),
-        client_socket_factory_(net::ClientSocketFactory::GetDefaultFactory()),
-        proxy_script_fetcher_context_(new URLRequestContext),
+        proxy_script_fetcher_context_(new net::URLRequestContext),
         message_loop_(MessageLoop::TYPE_IO),
         io_thread_(BrowserThread::IO, &message_loop_) {
     InitializeRequestContext();
@@ -97,7 +95,6 @@
  protected:
   net::TestServer test_server_;
   ConnectionTesterDelegate test_delegate_;
-  net::ClientSocketFactory* const client_socket_factory_;
   net::MockHostResolver host_resolver_;
   net::CertVerifier cert_verifier_;
   net::DnsRRResolver dnsrr_resolver_;
@@ -105,7 +102,7 @@
   scoped_refptr<net::SSLConfigService> ssl_config_service_;
   scoped_ptr<net::HttpTransactionFactory> http_transaction_factory_;
   net::HttpAuthHandlerRegistryFactory http_auth_handler_factory_;
-  scoped_refptr<URLRequestContext> proxy_script_fetcher_context_;
+  scoped_refptr<net::URLRequestContext> proxy_script_fetcher_context_;
 
  private:
   void InitializeRequestContext() {
@@ -117,20 +114,17 @@
     proxy_service_ = net::ProxyService::CreateDirect();
     proxy_script_fetcher_context_->set_proxy_service(proxy_service_);
     ssl_config_service_ = net::SSLConfigService::CreateSystemSSLConfigService();
+    net::HttpNetworkSession::Params session_params;
+    session_params.host_resolver = &host_resolver_;
+    session_params.cert_verifier = &cert_verifier_;
+    session_params.dnsrr_resolver = &dnsrr_resolver_;
+    session_params.http_auth_handler_factory = &http_auth_handler_factory_;
+    session_params.ssl_config_service = ssl_config_service_;
+    session_params.proxy_service = proxy_service_;
+    scoped_refptr<net::HttpNetworkSession> network_session(
+        new net::HttpNetworkSession(session_params));
     http_transaction_factory_.reset(
-        new net::HttpNetworkLayer(
-            client_socket_factory_,
-            &host_resolver_,
-            &cert_verifier_,
-            &dnsrr_resolver_,
-            NULL /* DNS cert provenance checker */,
-            NULL /* ssl_host_info_factory */,
-            proxy_service_.get(),
-            ssl_config_service_,
-            new net::SpdySessionPool(ssl_config_service_),
-            &http_auth_handler_factory_,
-            NULL /* NetworkDelegate */,
-            NULL /* NetLog */));
+        new net::HttpNetworkLayer(network_session));
     proxy_script_fetcher_context_->set_http_transaction_factory(
         http_transaction_factory_.get());
     // In-memory cookie store.
diff --git a/chrome/browser/net/file_system_url_request_job_factory.cc b/chrome/browser/net/file_system_url_request_job_factory.cc
new file mode 100644
index 0000000..c3356cd
--- /dev/null
+++ b/chrome/browser/net/file_system_url_request_job_factory.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/file_system_url_request_job_factory.h"
+
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/common/url_constants.h"
+#include "net/url_request/url_request.h"
+#include "webkit/fileapi/file_system_url_request_job.h"
+#include "webkit/fileapi/file_system_dir_url_request_job.h"
+
+namespace {
+
+net::URLRequestJob* FileSystemURLRequestJobFactory(net::URLRequest* request,
+                                                   const std::string& scheme) {
+  fileapi::FileSystemPathManager* path_manager =
+      static_cast<ChromeURLRequestContext*>(request->context())
+          ->file_system_context()->path_manager();
+  const std::string path = request->url().path();
+
+  // If the path ends with a /, we know it's a directory. If the path refers
+  // to a directory and gets dispatched to FileSystemURLRequestJob, that class
+  // redirects back here, by adding a / to the URL.
+  if (!path.empty() && path[path.size() - 1] == '/') {
+    return new fileapi::FileSystemDirURLRequestJob(request, path_manager,
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
+  }
+  return new fileapi::FileSystemURLRequestJob(request, path_manager,
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
+}
+
+}  // anonymous namespace
+
+void RegisterFileSystemURLRequestJobFactory() {
+  net::URLRequest::RegisterProtocolFactory(chrome::kFileSystemScheme,
+                                           &FileSystemURLRequestJobFactory);
+}
diff --git a/chrome/browser/net/file_system_url_request_job_factory.h b/chrome/browser/net/file_system_url_request_job_factory.h
new file mode 100644
index 0000000..57345d2
--- /dev/null
+++ b/chrome/browser/net/file_system_url_request_job_factory.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_NET_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_
+#define CHROME_BROWSER_NET_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_
+
+void RegisterFileSystemURLRequestJobFactory();
+
+#endif  // CHROME_BROWSER_NET_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_
diff --git a/chrome/browser/net/gaia/token_service_unittest.cc b/chrome/browser/net/gaia/token_service_unittest.cc
index d06956f..e3560b6 100644
--- a/chrome/browser/net/gaia/token_service_unittest.cc
+++ b/chrome/browser/net/gaia/token_service_unittest.cc
@@ -7,11 +7,69 @@
 #include "chrome/browser/net/gaia/token_service_unittest.h"
 
 #include "base/command_line.h"
+#include "base/synchronization/waitable_event.h"
+#include "chrome/browser/password_manager/encryptor.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h"
 #include "chrome/common/net/gaia/gaia_constants.h"
 #include "chrome/common/net/test_url_fetcher_factory.h"
 
+TokenServiceTestHarness::TokenServiceTestHarness()
+    : ui_thread_(BrowserThread::UI, &message_loop_),
+      db_thread_(BrowserThread::DB) {
+}
+
+TokenServiceTestHarness::~TokenServiceTestHarness() {}
+
+void TokenServiceTestHarness::SetUp() {
+#if defined(OS_MACOSX)
+  Encryptor::UseMockKeychain(true);
+#endif
+  credentials_.sid = "sid";
+  credentials_.lsid = "lsid";
+  credentials_.token = "token";
+  credentials_.data = "data";
+
+  ASSERT_TRUE(db_thread_.Start());
+
+  profile_.reset(new TestingProfile());
+  profile_->CreateWebDataService(false);
+  WaitForDBLoadCompletion();
+
+  success_tracker_.ListenFor(NotificationType::TOKEN_AVAILABLE,
+                             Source<TokenService>(&service_));
+  failure_tracker_.ListenFor(NotificationType::TOKEN_REQUEST_FAILED,
+                             Source<TokenService>(&service_));
+
+  service_.Initialize("test", profile_.get());
+
+  URLFetcher::set_factory(NULL);
+}
+
+void TokenServiceTestHarness::TearDown() {
+  // You have to destroy the profile before the db_thread_ stops.
+  if (profile_.get()) {
+    profile_.reset(NULL);
+  }
+
+  db_thread_.Stop();
+  MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+  MessageLoop::current()->Run();
+}
+
+void TokenServiceTestHarness::WaitForDBLoadCompletion() {
+  // The WebDB does all work on the DB thread. This will add an event
+  // to the end of the DB thread, so when we reach this task, all DB
+  // operations should be complete.
+  base::WaitableEvent done(false, false);
+  BrowserThread::PostTask(
+      BrowserThread::DB, FROM_HERE, new SignalingTask(&done));
+  done.Wait();
+
+  // Notifications should be returned from the DB thread onto the UI thread.
+  message_loop_.RunAllPending();
+}
+
 class TokenServiceTest : public TokenServiceTestHarness {
  public:
   virtual void SetUp() {
diff --git a/chrome/browser/net/gaia/token_service_unittest.h b/chrome/browser/net/gaia/token_service_unittest.h
index 46cffb0..8f48e78 100644
--- a/chrome/browser/net/gaia/token_service_unittest.h
+++ b/chrome/browser/net/gaia/token_service_unittest.h
@@ -8,8 +8,8 @@
 #define CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_UNITTEST_H_
 #pragma once
 
+#include "base/synchronization/waitable_event.h"
 #include "chrome/browser/net/gaia/token_service.h"
-#include "chrome/browser/password_manager/encryptor.h"
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/common/net/gaia/gaia_auth_consumer.h"
 #include "chrome/common/notification_details.h"
@@ -64,59 +64,14 @@
 
 class TokenServiceTestHarness : public testing::Test {
  public:
-  TokenServiceTestHarness()
-      : ui_thread_(BrowserThread::UI, &message_loop_),
-        db_thread_(BrowserThread::DB) {
-  }
+  TokenServiceTestHarness();
+  virtual ~TokenServiceTestHarness();
 
-  virtual void SetUp() {
-#if defined(OS_MACOSX)
-    Encryptor::UseMockKeychain(true);
-#endif
-    credentials_.sid = "sid";
-    credentials_.lsid = "lsid";
-    credentials_.token = "token";
-    credentials_.data = "data";
+  virtual void SetUp();
 
-    ASSERT_TRUE(db_thread_.Start());
+  virtual void TearDown();
 
-    profile_.reset(new TestingProfile());
-    profile_->CreateWebDataService(false);
-    WaitForDBLoadCompletion();
-
-    success_tracker_.ListenFor(NotificationType::TOKEN_AVAILABLE,
-                               Source<TokenService>(&service_));
-    failure_tracker_.ListenFor(NotificationType::TOKEN_REQUEST_FAILED,
-                               Source<TokenService>(&service_));
-
-    service_.Initialize("test", profile_.get());
-
-    URLFetcher::set_factory(NULL);
-  }
-
-  virtual void TearDown() {
-    // You have to destroy the profile before the db_thread_ stops.
-    if (profile_.get()) {
-      profile_.reset(NULL);
-    }
-
-    db_thread_.Stop();
-    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
-    MessageLoop::current()->Run();
-  }
-
-  void WaitForDBLoadCompletion() {
-    // The WebDB does all work on the DB thread. This will add an event
-    // to the end of the DB thread, so when we reach this task, all DB
-    // operations should be complete.
-    WaitableEvent done(false, false);
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE, new SignalingTask(&done));
-    done.Wait();
-
-    // Notifications should be returned from the DB thread onto the UI thread.
-    message_loop_.RunAllPending();
-  }
+  void WaitForDBLoadCompletion();
 
   MessageLoopForUI message_loop_;
   BrowserThread ui_thread_;  // Mostly so DCHECKS pass.
diff --git a/chrome/browser/net/net_log_logger.cc b/chrome/browser/net/net_log_logger.cc
index bba75ca..1468e6f 100644
--- a/chrome/browser/net/net_log_logger.cc
+++ b/chrome/browser/net/net_log_logger.cc
@@ -4,11 +4,19 @@
 
 #include "chrome/browser/net/net_log_logger.h"
 
+#include <stdio.h>
+
+#include "base/file_util.h"
 #include "base/json/json_writer.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 
-NetLogLogger::NetLogLogger()
+NetLogLogger::NetLogLogger(const FilePath &log_path)
     : ThreadSafeObserver(net::NetLog::LOG_ALL_BUT_BYTES) {
+  if (!log_path.empty()) {
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    file_.Set(file_util::OpenFile(log_path, "w"));
+  }
 }
 
 NetLogLogger::~NetLogLogger() {}
@@ -21,8 +29,16 @@
   scoped_ptr<Value> value(net::NetLog::EntryToDictionaryValue(type, time,
                                                               source, phase,
                                                               params, true));
+  // Don't pretty print, so each JSON value occupies a single line, with no
+  // breaks (Line breaks in any text field will be escaped).  Using strings
+  // instead of integer identifiers allows logs from older versions to be
+  // loaded, though a little extra parsing has to be done when loading a log.
   std::string json;
-  base::JSONWriter::Write(value.get(), true, &json);
-  VLOG(1) << json;
+  base::JSONWriter::Write(value.get(), false, &json);
+  if (!file_.get()) {
+    VLOG(1) << json;
+  } else {
+    fprintf(file_.get(), "%s\n", json.c_str());
+  }
 }
 
diff --git a/chrome/browser/net/net_log_logger.h b/chrome/browser/net/net_log_logger.h
index 564f232..2cb88c6 100644
--- a/chrome/browser/net/net_log_logger.h
+++ b/chrome/browser/net/net_log_logger.h
@@ -6,14 +6,23 @@
 #define CHROME_BROWSER_NET_NET_LOG_LOGGER_H_
 #pragma once
 
+#include "base/scoped_handle.h"
 #include "chrome/browser/net/chrome_net_log.h"
 
+class FilePath;
+
 // NetLogLogger watches the NetLog event stream, and sends all entries to
-// VLOG(1).  This is to debug errors that prevent getting to the
-// about:net-internals page.
+// VLOG(1) or a path specified on creation.  This is to debug errors that
+// prevent getting to the about:net-internals page.
+//
+// Relies on ChromeNetLog only calling an Observer once at a time for
+// thread-safety.
 class NetLogLogger : public ChromeNetLog::ThreadSafeObserver {
  public:
-  NetLogLogger();
+  // If |log_path| is empty or file creation fails, writes to VLOG(1).
+  // Otherwise, writes to |log_path|.  Uses one line per entry, for
+  // easy parsing.
+  explicit NetLogLogger(const FilePath &log_path);
   ~NetLogLogger();
 
   // ThreadSafeObserver implementation:
@@ -24,6 +33,8 @@
                           net::NetLog::EventParameters* params);
 
  private:
+  ScopedStdioHandle file_;
+
   DISALLOW_COPY_AND_ASSIGN(NetLogLogger);
 };
 
diff --git a/chrome/browser/net/passive_log_collector.cc b/chrome/browser/net/passive_log_collector.cc
index 21e2935..8ac8e53 100644
--- a/chrome/browser/net/passive_log_collector.cc
+++ b/chrome/browser/net/passive_log_collector.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/compiler_specific.h"
-#include "base/lock.h"
 #include "base/string_util.h"
 #include "base/format_macros.h"
 #include "net/url_request/url_request_netlog_params.h"
diff --git a/chrome/browser/net/preconnect.cc b/chrome/browser/net/preconnect.cc
index 972e302..c35bc0e 100644
--- a/chrome/browser/net/preconnect.cc
+++ b/chrome/browser/net/preconnect.cc
@@ -56,7 +56,7 @@
   UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation_,
                             UrlInfo::MAX_MOTIVATED);
 
-  URLRequestContext* context = getter->GetURLRequestContext();
+  net::URLRequestContext* context = getter->GetURLRequestContext();
   net::HttpTransactionFactory* factory = context->http_transaction_factory();
   net::HttpNetworkSession* session = factory->GetSession();
 
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc
index 46dcf1f..327d709 100644
--- a/chrome/browser/net/predictor.cc
+++ b/chrome/browser/net/predictor.cc
@@ -133,7 +133,6 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(referring_url == referring_url.GetWithEmptyPath());
   DCHECK(target_url == target_url.GetWithEmptyPath());
-  DCHECK(target_url != referring_url);
   if (referring_url.has_host()) {
     referrers_[referring_url].SuggestHost(target_url);
   }
@@ -258,6 +257,8 @@
       evalution = PRECONNECTION;
       future_url->second.IncrementPreconnectionCount();
       int count = static_cast<int>(std::ceil(connection_expectation));
+      if (url.host() == future_url->first.host())
+        ++count;
       Preconnect::PreconnectOnIOThread(future_url->first, motivation, count);
     } else if (connection_expectation > kDNSPreresolutionWorthyExpectedValue) {
       evalution = PRERESOLUTION;
diff --git a/chrome/browser/net/predictor_api.cc b/chrome/browser/net/predictor_api.cc
index 9296cfa..52a1497 100644
--- a/chrome/browser/net/predictor_api.cc
+++ b/chrome/browser/net/predictor_api.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/net/preconnect.h"
 #include "chrome/browser/net/referrer.h"
 #include "chrome/browser/net/url_info.h"
+#include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
@@ -246,7 +247,7 @@
     return;
 
   if (url.SchemeIs("http") || url.SchemeIs("https")) {
-    const GURL url_without_path(url.GetWithEmptyPath());
+    const GURL url_without_path(Predictor::CanonicalizeUrl(url));
     if (first_navigations_.find(url_without_path) == first_navigations_.end())
       first_navigations_[url_without_path] = base::TimeTicks::Now();
   }
@@ -394,16 +395,15 @@
           prefs::kDnsPrefetchingHostReferralList)->DeepCopy());
 
   // Remove obsolete preferences from local state if necessary.
-  int dns_prefs_version =
-      user_prefs->GetInteger(prefs::kMultipleProfilePrefMigration);
-  if (dns_prefs_version < 1) {
-    // These prefs only need to be registered if they need to be cleared from
-    // local state.
+  int current_version =
+      local_state->GetInteger(prefs::kMultipleProfilePrefMigration);
+  if ((current_version & browser::DNS_PREFS) == 0) {
     local_state->RegisterListPref(prefs::kDnsStartupPrefetchList);
     local_state->RegisterListPref(prefs::kDnsHostReferralList);
     local_state->ClearPref(prefs::kDnsStartupPrefetchList);
     local_state->ClearPref(prefs::kDnsHostReferralList);
-    user_prefs->SetInteger(prefs::kMultipleProfilePrefMigration, 1);
+    local_state->SetInteger(prefs::kMultipleProfilePrefMigration,
+        current_version | browser::DNS_PREFS);
   }
 
   g_browser_process->io_thread()->InitNetworkPredictor(
@@ -551,13 +551,15 @@
   // For each option (i.e., non-default), we have a fixed probability.
   base::FieldTrial::Probability kProbabilityPerGroup = 100;  // 10% probability.
 
-  trial_ = new base::FieldTrial("DnsImpact", kDivisor);
+  // After June 30, 2011 builds, it will always be in default group
+  // (default_enabled_prefetch).
+  trial_ = new base::FieldTrial("DnsImpact", kDivisor,
+                                "default_enabled_prefetch", 2011, 6, 30);
 
   // First option is to disable prefetching completely.
   int disabled_prefetch = trial_->AppendGroup("disabled_prefetch",
                                               kProbabilityPerGroup);
 
-
   // We're running two experiments at the same time.  The first set of trials
   // modulates the delay-time until we declare a congestion event (and purge
   // our queue).  The second modulates the number of concurrent resolutions
@@ -586,9 +588,6 @@
   int max_6_concurrent_prefetch = trial_->AppendGroup(
       "max_6 concurrent_prefetch", kProbabilityPerGroup);
 
-  trial_->AppendGroup("default_enabled_prefetch",
-      base::FieldTrial::kAllRemainingProbability);
-
   // We will register the incognito observer regardless of whether prefetching
   // is enabled, as it is also used to clear the host cache.
   g_off_the_record_observer.Get().Register();
diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc
index bbc798e..2dbcc4e 100644
--- a/chrome/browser/net/predictor_unittest.cc
+++ b/chrome/browser/net/predictor_unittest.cc
@@ -339,7 +339,7 @@
   for (size_t i = 0; i < subresource_list->GetSize();) {
     std::string url_spec;
     EXPECT_TRUE(subresource_list->GetString(i++, &url_spec));
-    EXPECT_TRUE(subresource_list->GetReal(i++, use_rate));
+    EXPECT_TRUE(subresource_list->GetDouble(i++, use_rate));
     if (subresource == GURL(url_spec)) {
       return true;
     }
diff --git a/chrome/browser/net/pref_proxy_config_service.cc b/chrome/browser/net/pref_proxy_config_service.cc
index 2b10104..a31dc9f 100644
--- a/chrome/browser/net/pref_proxy_config_service.cc
+++ b/chrome/browser/net/pref_proxy_config_service.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/pref_set_observer.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
@@ -86,9 +86,10 @@
   // Clear the configuration.
   *config = net::ProxyConfig();
 
+  ProxyConfigDictionary proxy_dict(pref_service_->GetDictionary(prefs::kProxy));
+
   ProxyPrefs::ProxyMode mode;
-  int proxy_mode = pref_service_->GetInteger(prefs::kProxyMode);
-  if (!ProxyPrefs::IntToProxyMode(proxy_mode, &mode)) {
+  if (!proxy_dict.GetMode(&mode)) {
     // Fall back to system settings if the mode preference is invalid.
     return false;
   }
@@ -105,12 +106,12 @@
       config->set_auto_detect(true);
       return true;
     case ProxyPrefs::MODE_PAC_SCRIPT: {
-      if (!pref_service_->HasPrefPath(prefs::kProxyPacUrl)) {
+      std::string proxy_pac;
+      if (!proxy_dict.GetPacUrl(&proxy_pac)) {
         LOG(ERROR) << "Proxy settings request PAC script but do not specify "
                    << "its URL. Falling back to direct connection.";
         return true;
       }
-      std::string proxy_pac = pref_service_->GetString(prefs::kProxyPacUrl);
       GURL proxy_pac_url(proxy_pac);
       if (!proxy_pac_url.is_valid()) {
         LOG(ERROR) << "Invalid proxy PAC url: " << proxy_pac;
@@ -120,18 +121,16 @@
       return true;
     }
     case ProxyPrefs::MODE_FIXED_SERVERS: {
-      if (!pref_service_->HasPrefPath(prefs::kProxyServer)) {
+      std::string proxy_server;
+      if (!proxy_dict.GetProxyServer(&proxy_server)) {
         LOG(ERROR) << "Proxy settings request fixed proxy servers but do not "
                    << "specify their URLs. Falling back to direct connection.";
         return true;
       }
-      std::string proxy_server =
-          pref_service_->GetString(prefs::kProxyServer);
       config->proxy_rules().ParseFromString(proxy_server);
 
-      if (pref_service_->HasPrefPath(prefs::kProxyBypassList)) {
-        std::string proxy_bypass =
-            pref_service_->GetString(prefs::kProxyBypassList);
+      std::string proxy_bypass;
+      if (proxy_dict.GetBypassList(&proxy_bypass)) {
         config->proxy_rules().bypass_rules.ParseFromString(proxy_bypass);
       }
       return true;
@@ -229,8 +228,6 @@
 // static
 void PrefProxyConfigService::RegisterUserPrefs(
     PrefService* pref_service) {
-  pref_service->RegisterIntegerPref(prefs::kProxyMode, ProxyPrefs::MODE_SYSTEM);
-  pref_service->RegisterStringPref(prefs::kProxyServer, "");
-  pref_service->RegisterStringPref(prefs::kProxyPacUrl, "");
-  pref_service->RegisterStringPref(prefs::kProxyBypassList, "");
+  DictionaryValue* default_settings = ProxyConfigDictionary::CreateSystem();
+  pref_service->RegisterDictionaryPref(prefs::kProxy, default_settings);
 }
diff --git a/chrome/browser/net/pref_proxy_config_service_unittest.cc b/chrome/browser/net/pref_proxy_config_service_unittest.cc
index dad5c53..d25abaa 100644
--- a/chrome/browser/net/pref_proxy_config_service_unittest.cc
+++ b/chrome/browser/net/pref_proxy_config_service_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/file_path.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/prefs/pref_service_mock_builder.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/testing_pref_service.h"
@@ -114,10 +114,8 @@
 
 TEST_F(PrefProxyConfigServiceTest, DynamicPrefOverrides) {
   pref_service_->SetManagedPref(
-      prefs::kProxyServer, Value::CreateStringValue("http://example.com:3128"));
-  pref_service_->SetManagedPref(
-      prefs::kProxyMode,
-      Value::CreateIntegerValue(ProxyPrefs::MODE_FIXED_SERVERS));
+      prefs::kProxy,
+      ProxyConfigDictionary::CreateFixedServers("http://example.com:3128", ""));
   loop_.RunAllPending();
 
   net::ProxyConfig actual_config;
@@ -129,9 +127,8 @@
             net::ProxyServer::FromURI("http://example.com:3128",
                                       net::ProxyServer::SCHEME_HTTP));
 
-  pref_service_->SetManagedPref(
-      prefs::kProxyMode,
-      Value::CreateIntegerValue(ProxyPrefs::MODE_AUTO_DETECT));
+  pref_service_->SetManagedPref(prefs::kProxy,
+                                ProxyConfigDictionary::CreateAutoDetect());
   loop_.RunAllPending();
 
   proxy_config_service_->GetLatestProxyConfig(&actual_config);
@@ -164,17 +161,9 @@
 
   EXPECT_CALL(observer,
               OnProxyConfigChanged(ProxyConfigMatches(pref_config))).Times(1);
-
-  pref_service_->SetManagedPref(prefs::kProxyPacUrl,
-                                Value::CreateStringValue(kFixedPacUrl));
-  // The above does not trigger a notification, because PrefProxyConfig still
-  // sees the mode as the default (ProxyPrefs::SYSTEM), so that it doesn't claim
-  // to have proxy config.
-  // TODO(battre): Remove this comment when http://crbug.com/65732 is
-  // resolved.
   pref_service_->SetManagedPref(
-      prefs::kProxyMode,
-      Value::CreateIntegerValue(ProxyPrefs::MODE_PAC_SCRIPT));
+      prefs::kProxy,
+      ProxyConfigDictionary::CreatePacScript(kFixedPacUrl));
   loop_.RunAllPending();
   Mock::VerifyAndClearExpectations(&observer);
 
@@ -190,12 +179,7 @@
   // Clear the override should switch back to the fixed configuration.
   EXPECT_CALL(observer,
               OnProxyConfigChanged(ProxyConfigMatches(config3))).Times(1);
-  pref_service_->RemoveManagedPref(prefs::kProxyMode);
-  // The above switches the mode to the default (ProxyPrefs::SYSTEM), so the
-  // next removal won't bother PrefProxyConfigService.
-  // TODO(battre): Remove this comment when http://crbug.com/65732 is
-  // completed.
-  pref_service_->RemoveManagedPref(prefs::kProxyPacUrl);
+  pref_service_->RemoveManagedPref(prefs::kProxy);
   loop_.RunAllPending();
   Mock::VerifyAndClearExpectations(&observer);
 
diff --git a/chrome/browser/net/referrer.cc b/chrome/browser/net/referrer.cc
index 0b884d6..8f16067 100644
--- a/chrome/browser/net/referrer.cc
+++ b/chrome/browser/net/referrer.cc
@@ -124,7 +124,7 @@
     if (!subresource_list->GetString(index++, &url_spec))
       return;
     double rate;
-    if (!subresource_list->GetReal(index++, &rate))
+    if (!subresource_list->GetDouble(index++, &rate))
       return;
 
     GURL url(url_spec);
diff --git a/chrome/browser/net/sdch_dictionary_fetcher.cc b/chrome/browser/net/sdch_dictionary_fetcher.cc
index 696d311..2db03ed 100644
--- a/chrome/browser/net/sdch_dictionary_fetcher.cc
+++ b/chrome/browser/net/sdch_dictionary_fetcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,18 +16,23 @@
 SdchDictionaryFetcher::~SdchDictionaryFetcher() {
 }
 
+// static
+void SdchDictionaryFetcher::Shutdown() {
+  net::SdchManager::Shutdown();
+}
+
 void SdchDictionaryFetcher::Schedule(const GURL& dictionary_url) {
   // Avoid pushing duplicate copy onto queue.  We may fetch this url again later
   // and get a different dictionary, but there is no reason to have it in the
   // queue twice at one time.
   if (!fetch_queue_.empty() && fetch_queue_.back() == dictionary_url) {
-    SdchManager::SdchErrorRecovery(
-        SdchManager::DICTIONARY_ALREADY_SCHEDULED_TO_DOWNLOAD);
+    net::SdchManager::SdchErrorRecovery(
+        net::SdchManager::DICTIONARY_ALREADY_SCHEDULED_TO_DOWNLOAD);
     return;
   }
   if (attempted_load_.find(dictionary_url) != attempted_load_.end()) {
-    SdchManager::SdchErrorRecovery(
-        SdchManager::DICTIONARY_ALREADY_TRIED_TO_DOWNLOAD);
+    net::SdchManager::SdchErrorRecovery(
+        net::SdchManager::DICTIONARY_ALREADY_TRIED_TO_DOWNLOAD);
     return;
   }
   attempted_load_.insert(dictionary_url);
@@ -64,14 +69,16 @@
   current_fetch_->Start();
 }
 
-void SdchDictionaryFetcher::OnURLFetchComplete(const URLFetcher* source,
-                                               const GURL& url,
-                                               const URLRequestStatus& status,
-                                               int response_code,
-                                               const ResponseCookies& cookies,
-                                               const std::string& data) {
-  if ((200 == response_code) && (status.status() == URLRequestStatus::SUCCESS))
-    SdchManager::Global()->AddSdchDictionary(data, url);
+void SdchDictionaryFetcher::OnURLFetchComplete(
+    const URLFetcher* source,
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
+    const std::string& data) {
+  if ((200 == response_code) &&
+      (status.status() == net::URLRequestStatus::SUCCESS))
+    net::SdchManager::Global()->AddSdchDictionary(data, url);
   current_fetch_.reset(NULL);
   ScheduleDelayedRun();
 }
diff --git a/chrome/browser/net/sdch_dictionary_fetcher.h b/chrome/browser/net/sdch_dictionary_fetcher.h
index 0240245..0919d62 100644
--- a/chrome/browser/net/sdch_dictionary_fetcher.h
+++ b/chrome/browser/net/sdch_dictionary_fetcher.h
@@ -20,20 +20,20 @@
 #include "net/base/sdch_manager.h"
 
 class SdchDictionaryFetcher : public URLFetcher::Delegate,
-                              public SdchFetcher {
+                              public net::SdchFetcher {
  public:
   SdchDictionaryFetcher();
   virtual ~SdchDictionaryFetcher();
 
+  // Stop fetching dictionaries, and abandon any current URLFetcheer operations
+  // so that the IO thread can be stopped.
+  static void Shutdown();
+
   // Implementation of SdchFetcher class.
   // This method gets the requested dictionary, and then calls back into the
   // SdchManager class with the dictionary's text.
   virtual void Schedule(const GURL& dictionary_url);
 
-  // Stop fetching dictionaries, and abandon any current URLFetcheer operations
-  // so that the IO thread can be stopped.
-  static void Shutdown() { SdchManager::Shutdown(); }
-
  private:
   // Delay in ms between Schedule and actual download.
   // This leaves the URL in a queue, which is de-duped, so that there is less
diff --git a/chrome/browser/net/sqlite_persistent_cookie_store.cc b/chrome/browser/net/sqlite_persistent_cookie_store.cc
index 58f4b91..d2ecf69 100644
--- a/chrome/browser/net/sqlite_persistent_cookie_store.cc
+++ b/chrome/browser/net/sqlite_persistent_cookie_store.cc
@@ -145,7 +145,7 @@
   // True if the persistent store should be deleted upon destruction.
   bool clear_local_state_on_exit_;
   // Guard |pending_|, |num_pending_| and |clear_local_state_on_exit_|.
-  Lock lock_;
+  base::Lock lock_;
 
 #if defined(ANDROID)
   // Number of cookies that have actually been saved. Updated during Commit().
@@ -379,7 +379,7 @@
 
   PendingOperationsList::size_type num_pending;
   {
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     pending_.push_back(po.release());
     num_pending = ++num_pending_;
   }
@@ -429,7 +429,7 @@
 
   PendingOperationsList ops;
   {
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     pending_.swap(ops);
     num_pending_ = 0;
   }
@@ -592,7 +592,7 @@
 
 void SQLitePersistentCookieStore::Backend::SetClearLocalStateOnExit(
     bool clear_local_state) {
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
   clear_local_state_on_exit_ = clear_local_state;
 }
 SQLitePersistentCookieStore::SQLitePersistentCookieStore(const FilePath& path)
diff --git a/chrome/browser/net/url_fixer_upper.cc b/chrome/browser/net/url_fixer_upper.cc
index 4c36368..07881a4 100644
--- a/chrome/browser/net/url_fixer_upper.cc
+++ b/chrome/browser/net/url_fixer_upper.cc
@@ -72,6 +72,50 @@
   parts->ref =
       UTF8ComponentToWideComponent(text_utf8, parts_utf8.ref);
 }
+#if defined(WCHAR_T_IS_UTF32)
+url_parse::Component UTF8ComponentToUTF16Component(
+    const std::string& text_utf8,
+    const url_parse::Component& component_utf8) {
+  if (component_utf8.len == -1)
+    return url_parse::Component();
+
+  std::string before_component_string =
+      text_utf8.substr(0, component_utf8.begin);
+  std::string component_string = text_utf8.substr(component_utf8.begin,
+                                                  component_utf8.len);
+  string16 before_component_string_16 = UTF8ToUTF16(before_component_string);
+  string16 component_string_16 = UTF8ToUTF16(component_string);
+  url_parse::Component component_16(before_component_string_16.length(),
+                                    component_string_16.length());
+  return component_16;
+}
+
+void UTF8PartsToUTF16Parts(const std::string& text_utf8,
+                           const url_parse::Parsed& parts_utf8,
+                           url_parse::Parsed* parts) {
+  if (IsStringASCII(text_utf8)) {
+    *parts = parts_utf8;
+    return;
+  }
+
+  parts->scheme =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.scheme);
+  parts ->username =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.username);
+  parts->password =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.password);
+  parts->host =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.host);
+  parts->port =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.port);
+  parts->path =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.path);
+  parts->query =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.query);
+  parts->ref =
+      UTF8ComponentToUTF16Component(text_utf8, parts_utf8.ref);
+}
+#endif
 
 TrimPositions TrimWhitespaceUTF8(const std::string& input,
                                  TrimPositions positions,
@@ -581,6 +625,16 @@
   UTF8PartsToWideParts(text_utf8, parts_utf8, parts);
   return UTF8ToWide(scheme_utf8);
 }
+#if defined(WCHAR_T_IS_UTF32)
+string16 URLFixerUpper::SegmentURL(const string16& text,
+                                   url_parse::Parsed* parts) {
+  std::string text_utf8 = UTF16ToUTF8(text);
+  url_parse::Parsed parts_utf8;
+  std::string scheme_utf8 = SegmentURL(text_utf8, &parts_utf8);
+  UTF8PartsToUTF16Parts(text_utf8, parts_utf8, parts);
+  return UTF8ToUTF16(scheme_utf8);
+}
+#endif
 GURL URLFixerUpper::FixupRelativeFile(const std::wstring& base_dir,
                                       const std::wstring& text) {
   return FixupRelativeFile(FilePath::FromWStringHack(base_dir),
diff --git a/chrome/browser/net/url_fixer_upper.h b/chrome/browser/net/url_fixer_upper.h
index 9f5beb5..fa5ba1b 100644
--- a/chrome/browser/net/url_fixer_upper.h
+++ b/chrome/browser/net/url_fixer_upper.h
@@ -8,6 +8,7 @@
 
 #include <string>
 
+#include "base/string16.h"
 #include "googleurl/src/gurl.h"
 
 namespace url_parse {
@@ -29,8 +30,11 @@
   // Returns the canonicalized scheme, or the empty string when |text| is only
   // whitespace.
   std::string SegmentURL(const std::string& text, url_parse::Parsed* parts);
-  // Deprecated temporary compatibility function.
+  // Deprecated temporary compatibility functions.
   std::wstring SegmentURL(const std::wstring& text, url_parse::Parsed* parts);
+#if defined(WCHAR_T_IS_UTF32)
+  string16 SegmentURL(const string16& text, url_parse::Parsed* parts);
+#endif
 
   // Converts |text| to a fixed-up URL and returns it. Attempts to make
   // some "smart" adjustments to obviously-invalid input where possible.
diff --git a/chrome/browser/net/url_request_failed_dns_job.cc b/chrome/browser/net/url_request_failed_dns_job.cc
index 3481ee7..d6224c3 100644
--- a/chrome/browser/net/url_request_failed_dns_job.cc
+++ b/chrome/browser/net/url_request_failed_dns_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -41,6 +41,6 @@
 }
 
 void URLRequestFailedDnsJob::StartAsync() {
-  NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
+  NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
                                     net::ERR_NAME_NOT_RESOLVED));
 }
diff --git a/chrome/browser/net/url_request_mock_net_error_job.cc b/chrome/browser/net/url_request_mock_net_error_job.cc
index b88b160..0cf0df3 100644
--- a/chrome/browser/net/url_request_mock_net_error_job.cc
+++ b/chrome/browser/net/url_request_mock_net_error_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -109,7 +109,8 @@
       request_->delegate()->OnSSLCertificateError(request_, error,
                                                   ssl_cert_.get());
     } else {
-      NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
+      NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                             error));
     }
   }
 }
diff --git a/chrome/browser/net/url_request_slow_download_job.cc b/chrome/browser/net/url_request_slow_download_job.cc
index d4b2007..79c2676 100644
--- a/chrome/browser/net/url_request_slow_download_job.cc
+++ b/chrome/browser/net/url_request_slow_download_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -115,7 +115,7 @@
 
   // If we make it here, the first chunk has been sent and we need to wait
   // until a request is made for kFinishDownloadUrl.
-  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+  SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
   MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(
       this, &URLRequestSlowDownloadJob::CheckDoneStatus), 100);
   AddRef();
@@ -127,7 +127,7 @@
 void URLRequestSlowDownloadJob::CheckDoneStatus() {
   if (should_finish_download_) {
     should_send_second_chunk_ = true;
-    SetStatus(URLRequestStatus());
+    SetStatus(net::URLRequestStatus());
     NotifyReadComplete(kSecondDownloadSize);
     Release();
   } else {
diff --git a/chrome/browser/net/url_request_tracking.cc b/chrome/browser/net/url_request_tracking.cc
index a931856..020aad1 100644
--- a/chrome/browser/net/url_request_tracking.cc
+++ b/chrome/browser/net/url_request_tracking.cc
@@ -11,37 +11,37 @@
 
 // The value is not important, this address is used as the unique key for the
 // PID.
-const void* kOriginProcessUniqueIDKey = 0;
+const void* kOriginPidKey = 0;
 
-class UniqueIDData : public net::URLRequest::UserData {
+class OriginPidData : public net::URLRequest::UserData {
  public:
-  explicit UniqueIDData(int id) : id_(id) {}
-  virtual ~UniqueIDData() {}
+  explicit OriginPidData(int pid) : pid_(pid) {}
+  virtual ~OriginPidData() {}
 
-  int id() const { return id_; }
-  void set_id(int id) { id_ = id; }
+  int pid() const { return pid_; }
+  void set_pid(int pid) { pid_ = pid; }
 
  private:
-  int id_;
+  int pid_;
 
-  DISALLOW_COPY_AND_ASSIGN(UniqueIDData);
+  DISALLOW_COPY_AND_ASSIGN(OriginPidData);
 };
 
 }  // namespace
 
 namespace chrome_browser_net {
 
-void SetOriginProcessUniqueIDForRequest(int id, net::URLRequest* request) {
+void SetOriginPIDForRequest(int pid, net::URLRequest* request) {
   // The request will take ownership.
-  request->SetUserData(&kOriginProcessUniqueIDKey, new UniqueIDData(id));
+  request->SetUserData(&kOriginPidKey, new OriginPidData(pid));
 }
 
-int GetOriginProcessUniqueIDForRequest(const net::URLRequest* request) {
-  const UniqueIDData* data = static_cast<const UniqueIDData*>(
-      request->GetUserData(&kOriginProcessUniqueIDKey));
+int GetOriginPIDForRequest(const net::URLRequest* request) {
+  const OriginPidData* data = static_cast<const OriginPidData*>(
+      request->GetUserData(&kOriginPidKey));
   if (!data)
-    return -1;
-  return data->id();
+    return 0;
+  return data->pid();
 }
 
 }  // namespace chrome_browser_net
diff --git a/chrome/browser/net/url_request_tracking.h b/chrome/browser/net/url_request_tracking.h
index 0e7a715..497dfb2 100644
--- a/chrome/browser/net/url_request_tracking.h
+++ b/chrome/browser/net/url_request_tracking.h
@@ -18,20 +18,19 @@
 // place allows us to do more general things, such as assigning traffic for the
 // network view in the task manager.
 //
-// If you make a request on behalf of a child process, please call this
-// function. The default value will be -1 which will be interprepreted as
-// originating from the browser itself.
+// If you make a request on behalf of a child process other than a renderer,
+// please call this function to store its PID (NOT its browser-assigned unique
+// child ID).  For requests originating in a renderer or the browser itself,
+// set a PID of zero (the default).
 //
-// The ID is the child process' unique ID (not a PID) of the process originating
-// the request. This is normally the renderer corresponding to the load. If a
-// plugin process does a request through a renderer process this will be the
-// plugin (the originator of the request).
-void SetOriginProcessUniqueIDForRequest(int id, net::URLRequest* request);
+// TODO(wez): Get rid of the zero-PID hack & enforce that one is always set.
+void SetOriginPIDForRequest(int pid, net::URLRequest* request);
 
-// Returns the child process' unique ID that has been previously set by
-// SetOriginProcessUniqueIDForRequest. If no ID has been set, the return
-// value is -1. We use this to identify requests made by the browser process.
-int GetOriginProcessUniqueIDForRequest(const net::URLRequest* request);
+// Returns the process ID of the request's originator, previously stored with
+// SetOriginProcessIDForRequest, or zero if no PID has been set.  A PID of zero
+// should be interpreted as meaning the request originated from a renderer
+// process, or within the browser itself.
+int GetOriginPIDForRequest(const net::URLRequest* request);
 
 }  // namespace chrome_browser_net
 
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
index fd5088b..270700a 100644
--- a/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
@@ -28,12 +28,13 @@
 void WebSocketExperimentRunner::Start() {
   DCHECK(!runner.get());
 
+  // After June 30, 2011 builds, it will always be in default group.
   scoped_refptr<base::FieldTrial> trial(
-      new base::FieldTrial("WebSocketExperiment", 1000));
-  trial->AppendGroup("active", 5);  // 0.5% in active group.
+      new base::FieldTrial(
+          "WebSocketExperiment", 1000, "default", 2011, 6, 30));
+  int active = trial->AppendGroup("active", 5);  // 0.5% in active group.
 
-  bool run_experiment =
-      (trial->group() != base::FieldTrial::kNotParticipating);
+  bool run_experiment = (trial->group() == active);
 #ifndef NDEBUG
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   std::string experiment_host = command_line.GetSwitchValueASCII(
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc b/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
index 09cccc7..6929365 100644
--- a/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -114,6 +114,8 @@
       websocket_close_deadline_ms(kWebSocketCloseDeadlineSec * 1000) {
 }
 
+WebSocketExperimentTask::Config::~Config() {}
+
 WebSocketExperimentTask::WebSocketExperimentTask(
     const Config& config,
     net::CompletionCallback* callback)
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_task.h b/chrome/browser/net/websocket_experiment/websocket_experiment_task.h
index b23c0a0..8996eeb 100644
--- a/chrome/browser/net/websocket_experiment/websocket_experiment_task.h
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_task.h
@@ -73,9 +73,11 @@
     STATE_WEBSOCKET_CLOSE_COMPLETE,
     NUM_STATES,
   };
+
   class Config {
    public:
     Config();
+    ~Config();
 
     GURL url;
     std::string ws_protocol;
@@ -95,6 +97,7 @@
     int64 websocket_bye_deadline_ms;
     int64 websocket_close_deadline_ms;
   };
+
   class Context {
    public:
     Context() {}
@@ -108,6 +111,7 @@
    private:
     DISALLOW_COPY_AND_ASSIGN(Context);
   };
+
   class Result {
    public:
     Result()
diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS
new file mode 100644
index 0000000..967c65c
--- /dev/null
+++ b/chrome/browser/notifications/OWNERS
@@ -0,0 +1 @@
+johnnyg@chromium.org
diff --git a/chrome/browser/notifications/balloon.cc b/chrome/browser/notifications/balloon.cc
index d9f9111..115e1ee 100644
--- a/chrome/browser/notifications/balloon.cc
+++ b/chrome/browser/notifications/balloon.cc
@@ -8,8 +8,8 @@
 #include "chrome/browser/notifications/balloon_collection.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/renderer_host/site_instance.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 Balloon::Balloon(const Notification& notification, Profile* profile,
                  BalloonCollection* collection)
diff --git a/chrome/browser/notifications/balloon.h b/chrome/browser/notifications/balloon.h
index 5b86508..48c22e1 100644
--- a/chrome/browser/notifications/balloon.h
+++ b/chrome/browser/notifications/balloon.h
@@ -10,9 +10,9 @@
 
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 class Balloon;
 class BalloonCollection;
diff --git a/chrome/browser/notifications/balloon_collection.cc b/chrome/browser/notifications/balloon_collection.cc
index 60c9f2d..48059f5 100644
--- a/chrome/browser/notifications/balloon_collection.cc
+++ b/chrome/browser/notifications/balloon_collection.cc
@@ -1,344 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/notifications/balloon_collection_impl.h"
+#include "chrome/browser/notifications/balloon_collection.h"
 
-#include "base/logging.h"
-#include "base/stl_util-inl.h"
-#include "chrome/browser/notifications/balloon.h"
-#include "chrome/browser/notifications/balloon_host.h"
-#include "chrome/browser/notifications/notification.h"
-#include "chrome/browser/ui/window_sizer.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
-
-namespace {
-
-// Portion of the screen allotted for notifications. When notification balloons
-// extend over this, no new notifications are shown until some are closed.
-const double kPercentBalloonFillFactor = 0.7;
-
-// Allow at least this number of balloons on the screen.
-const int kMinAllowedBalloonCount = 2;
-
-// Delay from the mouse leaving the balloon collection before
-// there is a relayout, in milliseconds.
-const int kRepositionDelay = 300;
-
-}  // namespace
-
-BalloonCollectionImpl::BalloonCollectionImpl()
-#if USE_OFFSETS
-    : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)),
-      added_as_message_loop_observer_(false)
-#endif
-{
-
-  SetPositionPreference(BalloonCollection::DEFAULT_POSITION);
+BalloonCollection::BalloonCollection()
+    : space_change_listener_(NULL) {
 }
 
-BalloonCollectionImpl::~BalloonCollectionImpl() {
-}
-
-void BalloonCollectionImpl::Add(const Notification& notification,
-                                Profile* profile) {
-  Balloon* new_balloon = MakeBalloon(notification, profile);
-  // The +1 on width is necessary because width is fixed on notifications,
-  // so since we always have the max size, we would always hit the scrollbar
-  // condition.  We are only interested in comparing height to maximum.
-  new_balloon->set_min_scrollbar_size(gfx::Size(1 + layout_.max_balloon_width(),
-                                                layout_.max_balloon_height()));
-  new_balloon->SetPosition(layout_.OffScreenLocation(), false);
-  new_balloon->Show();
-#if USE_OFFSETS
-  int count = base_.count();
-  if (count > 0)
-    new_balloon->set_offset(base_.balloons()[count - 1]->offset());
-#endif
-  base_.Add(new_balloon);
-  PositionBalloons(false);
-
-  // There may be no listener in a unit test.
-  if (space_change_listener_)
-    space_change_listener_->OnBalloonSpaceChanged();
-
-  // This is used only for testing.
-  if (on_collection_changed_callback_.get())
-    on_collection_changed_callback_->Run();
-}
-
-bool BalloonCollectionImpl::RemoveById(const std::string& id) {
-  return base_.CloseById(id);
-}
-
-bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) {
-  return base_.CloseAllBySourceOrigin(origin);
-}
-
-void BalloonCollectionImpl::RemoveAll() {
-  base_.CloseAll();
-}
-
-bool BalloonCollectionImpl::HasSpace() const {
-  int count = base_.count();
-  if (count < kMinAllowedBalloonCount)
-    return true;
-
-  int max_balloon_size = 0;
-  int total_size = 0;
-  layout_.GetMaxLinearSize(&max_balloon_size, &total_size);
-
-  int current_max_size = max_balloon_size * count;
-  int max_allowed_size = static_cast<int>(total_size *
-                                          kPercentBalloonFillFactor);
-  return current_max_size < max_allowed_size - max_balloon_size;
-}
-
-void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon,
-                                          const gfx::Size& size) {
-  balloon->set_content_size(Layout::ConstrainToSizeLimits(size));
-  PositionBalloons(true);
-}
-
-void BalloonCollectionImpl::DisplayChanged() {
-  layout_.RefreshSystemMetrics();
-  PositionBalloons(true);
-}
-
-void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
-  // We want to free the balloon when finished.
-  const Balloons& balloons = base_.balloons();
-  Balloons::const_iterator it = balloons.begin();
-
-#if USE_OFFSETS
-  gfx::Point offset;
-  bool apply_offset = false;
-  while (it != balloons.end()) {
-    if (*it == source) {
-      ++it;
-      if (it != balloons.end()) {
-        apply_offset = true;
-        offset.set_y((source)->offset().y() - (*it)->offset().y() +
-            (*it)->content_size().height() - source->content_size().height());
-      }
-    } else {
-      if (apply_offset)
-        (*it)->add_offset(offset);
-      ++it;
-    }
-  }
-  // Start listening for UI events so we cancel the offset when the mouse
-  // leaves the balloon area.
-  if (apply_offset)
-    AddMessageLoopObserver();
-#endif
-
-  base_.Remove(source);
-  PositionBalloons(true);
-
-  // There may be no listener in a unit test.
-  if (space_change_listener_)
-    space_change_listener_->OnBalloonSpaceChanged();
-
-  // This is used only for testing.
-  if (on_collection_changed_callback_.get())
-    on_collection_changed_callback_->Run();
-}
-
-void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) {
-  const Balloons& balloons = base_.balloons();
-
-  layout_.RefreshSystemMetrics();
-  gfx::Point origin = layout_.GetLayoutOrigin();
-  for (Balloons::const_iterator it = balloons.begin();
-       it != balloons.end();
-       ++it) {
-    gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin);
-    (*it)->SetPosition(upper_left, reposition);
-  }
-}
-
-#if USE_OFFSETS
-void BalloonCollectionImpl::AddMessageLoopObserver() {
-  if (!added_as_message_loop_observer_) {
-    MessageLoopForUI::current()->AddObserver(this);
-    added_as_message_loop_observer_ = true;
-  }
-}
-
-void BalloonCollectionImpl::RemoveMessageLoopObserver() {
-  if (added_as_message_loop_observer_) {
-    MessageLoopForUI::current()->RemoveObserver(this);
-    added_as_message_loop_observer_ = false;
-  }
-}
-
-void BalloonCollectionImpl::CancelOffsets() {
-  reposition_factory_.RevokeAll();
-
-  // Unhook from listening to all UI events.
-  RemoveMessageLoopObserver();
-
-  const Balloons& balloons = base_.balloons();
-  for (Balloons::const_iterator it = balloons.begin();
-       it != balloons.end();
-       ++it)
-    (*it)->set_offset(gfx::Point(0, 0));
-
-  PositionBalloons(true);
-}
-
-void BalloonCollectionImpl::HandleMouseMoveEvent() {
-  if (!IsCursorInBalloonCollection()) {
-    // Mouse has left the region.  Schedule a reposition after
-    // a short delay.
-    if (reposition_factory_.empty()) {
-      MessageLoop::current()->PostDelayedTask(
-          FROM_HERE,
-          reposition_factory_.NewRunnableMethod(
-              &BalloonCollectionImpl::CancelOffsets),
-          kRepositionDelay);
-    }
-  } else {
-    // Mouse moved back into the region.  Cancel the reposition.
-    reposition_factory_.RevokeAll();
-  }
-}
-#endif
-
-BalloonCollectionImpl::Layout::Layout() {
-  RefreshSystemMetrics();
-}
-
-void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size,
-                                                     int* total_size) const {
-  DCHECK(max_balloon_size && total_size);
-
-  // All placement schemes are vertical, so we only care about height.
-  *total_size = work_area_.height();
-  *max_balloon_size = max_balloon_height();
-}
-
-gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const {
-  int x = 0;
-  int y = 0;
-  switch (placement_) {
-    case VERTICALLY_FROM_TOP_LEFT:
-      x = work_area_.x() + HorizontalEdgeMargin();
-      y = work_area_.y() + VerticalEdgeMargin();
-      break;
-    case VERTICALLY_FROM_TOP_RIGHT:
-      x = work_area_.right() - HorizontalEdgeMargin();
-      y = work_area_.y() + VerticalEdgeMargin();
-      break;
-    case VERTICALLY_FROM_BOTTOM_LEFT:
-      x = work_area_.x() + HorizontalEdgeMargin();
-      y = work_area_.bottom() - VerticalEdgeMargin();
-      break;
-    case VERTICALLY_FROM_BOTTOM_RIGHT:
-      x = work_area_.right() - HorizontalEdgeMargin();
-      y = work_area_.bottom() - VerticalEdgeMargin();
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  return gfx::Point(x, y);
-}
-
-gfx::Point BalloonCollectionImpl::Layout::NextPosition(
-    const gfx::Size& balloon_size,
-    gfx::Point* position_iterator) const {
-  DCHECK(position_iterator);
-
-  int x = 0;
-  int y = 0;
-  switch (placement_) {
-    case VERTICALLY_FROM_TOP_LEFT:
-      x = position_iterator->x();
-      y = position_iterator->y();
-      position_iterator->set_y(position_iterator->y() + balloon_size.height() +
-                               InterBalloonMargin());
-      break;
-    case VERTICALLY_FROM_TOP_RIGHT:
-      x = position_iterator->x() - balloon_size.width();
-      y = position_iterator->y();
-      position_iterator->set_y(position_iterator->y() + balloon_size.height() +
-                               InterBalloonMargin());
-      break;
-    case VERTICALLY_FROM_BOTTOM_LEFT:
-      position_iterator->set_y(position_iterator->y() - balloon_size.height() -
-                               InterBalloonMargin());
-      x = position_iterator->x();
-      y = position_iterator->y();
-      break;
-    case VERTICALLY_FROM_BOTTOM_RIGHT:
-      position_iterator->set_y(position_iterator->y() - balloon_size.height() -
-                               InterBalloonMargin());
-      x = position_iterator->x() - balloon_size.width();
-      y = position_iterator->y();
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  return gfx::Point(x, y);
-}
-
-gfx::Point BalloonCollectionImpl::Layout::OffScreenLocation() const {
-  int x = 0;
-  int y = 0;
-  switch (placement_) {
-    case VERTICALLY_FROM_TOP_LEFT:
-      x = work_area_.x() + HorizontalEdgeMargin();
-      y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin();
-      break;
-    case VERTICALLY_FROM_TOP_RIGHT:
-      x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin();
-      y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin();
-      break;
-    case VERTICALLY_FROM_BOTTOM_LEFT:
-      x = work_area_.x() + HorizontalEdgeMargin();
-      y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin();
-      break;
-    case VERTICALLY_FROM_BOTTOM_RIGHT:
-      x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin();
-      y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin();
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  return gfx::Point(x, y);
-}
-
-// static
-gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits(
-    const gfx::Size& size) {
-  // restrict to the min & max sizes
-  return gfx::Size(
-      std::max(min_balloon_width(),
-               std::min(max_balloon_width(), size.width())),
-      std::max(min_balloon_height(),
-               std::min(max_balloon_height(), size.height())));
-}
-
-bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() {
-  bool changed = false;
-
-#if defined(OS_MACOSX)
-  gfx::Rect new_work_area = GetMacWorkArea();
-#else
-  scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
-      WindowSizer::CreateDefaultMonitorInfoProvider());
-  gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea();
-#endif
-  if (!work_area_.Equals(new_work_area)) {
-    work_area_.SetRect(new_work_area.x(), new_work_area.y(),
-                       new_work_area.width(), new_work_area.height());
-    changed = true;
-  }
-
-  return changed;
+BalloonCollection::~BalloonCollection() {
 }
diff --git a/chrome/browser/notifications/balloon_collection.h b/chrome/browser/notifications/balloon_collection.h
index 6909759..4cae909 100644
--- a/chrome/browser/notifications/balloon_collection.h
+++ b/chrome/browser/notifications/balloon_collection.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -48,11 +48,9 @@
 
   static BalloonCollection* Create();
 
-  BalloonCollection()
-      : space_change_listener_(NULL) {
-  }
+  BalloonCollection();
 
-  virtual ~BalloonCollection() {}
+  virtual ~BalloonCollection();
 
   // Adds a new balloon for the specified notification.
   virtual void Add(const Notification& notification,
diff --git a/chrome/browser/notifications/balloon_collection_impl.cc b/chrome/browser/notifications/balloon_collection_impl.cc
new file mode 100644
index 0000000..f133de3
--- /dev/null
+++ b/chrome/browser/notifications/balloon_collection_impl.cc
@@ -0,0 +1,382 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/balloon_collection_impl.h"
+
+#include "base/logging.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/balloon_host.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/ui/window_sizer.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+namespace {
+
+// Portion of the screen allotted for notifications. When notification balloons
+// extend over this, no new notifications are shown until some are closed.
+const double kPercentBalloonFillFactor = 0.7;
+
+// Allow at least this number of balloons on the screen.
+const int kMinAllowedBalloonCount = 2;
+
+// Delay from the mouse leaving the balloon collection before
+// there is a relayout, in milliseconds.
+const int kRepositionDelay = 300;
+
+}  // namespace
+
+BalloonCollectionImpl::BalloonCollectionImpl()
+#if USE_OFFSETS
+    : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)),
+      added_as_message_loop_observer_(false)
+#endif
+{
+
+  SetPositionPreference(BalloonCollection::DEFAULT_POSITION);
+}
+
+BalloonCollectionImpl::~BalloonCollectionImpl() {
+}
+
+void BalloonCollectionImpl::Add(const Notification& notification,
+                                Profile* profile) {
+  Balloon* new_balloon = MakeBalloon(notification, profile);
+  // The +1 on width is necessary because width is fixed on notifications,
+  // so since we always have the max size, we would always hit the scrollbar
+  // condition.  We are only interested in comparing height to maximum.
+  new_balloon->set_min_scrollbar_size(gfx::Size(1 + layout_.max_balloon_width(),
+                                                layout_.max_balloon_height()));
+  new_balloon->SetPosition(layout_.OffScreenLocation(), false);
+  new_balloon->Show();
+#if USE_OFFSETS
+  int count = base_.count();
+  if (count > 0 && layout_.RequiresOffsets())
+    new_balloon->set_offset(base_.balloons()[count - 1]->offset());
+#endif
+  base_.Add(new_balloon);
+  PositionBalloons(false);
+
+  // There may be no listener in a unit test.
+  if (space_change_listener_)
+    space_change_listener_->OnBalloonSpaceChanged();
+
+  // This is used only for testing.
+  if (on_collection_changed_callback_.get())
+    on_collection_changed_callback_->Run();
+}
+
+bool BalloonCollectionImpl::RemoveById(const std::string& id) {
+  return base_.CloseById(id);
+}
+
+bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) {
+  return base_.CloseAllBySourceOrigin(origin);
+}
+
+void BalloonCollectionImpl::RemoveAll() {
+  base_.CloseAll();
+}
+
+bool BalloonCollectionImpl::HasSpace() const {
+  int count = base_.count();
+  if (count < kMinAllowedBalloonCount)
+    return true;
+
+  int max_balloon_size = 0;
+  int total_size = 0;
+  layout_.GetMaxLinearSize(&max_balloon_size, &total_size);
+
+  int current_max_size = max_balloon_size * count;
+  int max_allowed_size = static_cast<int>(total_size *
+                                          kPercentBalloonFillFactor);
+  return current_max_size < max_allowed_size - max_balloon_size;
+}
+
+void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon,
+                                          const gfx::Size& size) {
+  balloon->set_content_size(Layout::ConstrainToSizeLimits(size));
+  PositionBalloons(true);
+}
+
+void BalloonCollectionImpl::DisplayChanged() {
+  layout_.RefreshSystemMetrics();
+  PositionBalloons(true);
+}
+
+void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
+  // We want to free the balloon when finished.
+  const Balloons& balloons = base_.balloons();
+  Balloons::const_iterator it = balloons.begin();
+
+#if USE_OFFSETS
+  if (layout_.RequiresOffsets()) {
+    gfx::Point offset;
+    bool apply_offset = false;
+    while (it != balloons.end()) {
+      if (*it == source) {
+        ++it;
+        if (it != balloons.end()) {
+          apply_offset = true;
+          offset.set_y((source)->offset().y() - (*it)->offset().y() +
+              (*it)->content_size().height() - source->content_size().height());
+        }
+      } else {
+        if (apply_offset)
+          (*it)->add_offset(offset);
+        ++it;
+      }
+    }
+    // Start listening for UI events so we cancel the offset when the mouse
+    // leaves the balloon area.
+    if (apply_offset)
+      AddMessageLoopObserver();
+  }
+#endif
+
+  base_.Remove(source);
+  PositionBalloons(true);
+
+  // There may be no listener in a unit test.
+  if (space_change_listener_)
+    space_change_listener_->OnBalloonSpaceChanged();
+
+  // This is used only for testing.
+  if (on_collection_changed_callback_.get())
+    on_collection_changed_callback_->Run();
+}
+
+const BalloonCollection::Balloons& BalloonCollectionImpl::GetActiveBalloons() {
+  return base_.balloons();
+}
+
+void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) {
+  const Balloons& balloons = base_.balloons();
+
+  layout_.RefreshSystemMetrics();
+  gfx::Point origin = layout_.GetLayoutOrigin();
+  for (Balloons::const_iterator it = balloons.begin();
+       it != balloons.end();
+       ++it) {
+    gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin);
+    (*it)->SetPosition(upper_left, reposition);
+  }
+}
+
+gfx::Rect BalloonCollectionImpl::GetBalloonsBoundingBox() const {
+  // Start from the layout origin.
+  gfx::Rect bounds = gfx::Rect(layout_.GetLayoutOrigin(), gfx::Size(0, 0));
+
+  // For each balloon, extend the rectangle.  This approach is indifferent to
+  // the orientation of the balloons.
+  const Balloons& balloons = base_.balloons();
+  Balloons::const_iterator iter;
+  for (iter = balloons.begin(); iter != balloons.end(); ++iter) {
+    gfx::Rect balloon_box = gfx::Rect((*iter)->GetPosition(),
+                                      (*iter)->GetViewSize());
+    bounds = bounds.Union(balloon_box);
+  }
+
+  return bounds;
+}
+
+#if USE_OFFSETS
+void BalloonCollectionImpl::AddMessageLoopObserver() {
+  if (!added_as_message_loop_observer_) {
+    MessageLoopForUI::current()->AddObserver(this);
+    added_as_message_loop_observer_ = true;
+  }
+}
+
+void BalloonCollectionImpl::RemoveMessageLoopObserver() {
+  if (added_as_message_loop_observer_) {
+    MessageLoopForUI::current()->RemoveObserver(this);
+    added_as_message_loop_observer_ = false;
+  }
+}
+
+void BalloonCollectionImpl::CancelOffsets() {
+  reposition_factory_.RevokeAll();
+
+  // Unhook from listening to all UI events.
+  RemoveMessageLoopObserver();
+
+  const Balloons& balloons = base_.balloons();
+  for (Balloons::const_iterator it = balloons.begin();
+       it != balloons.end();
+       ++it)
+    (*it)->set_offset(gfx::Point(0, 0));
+
+  PositionBalloons(true);
+}
+
+void BalloonCollectionImpl::HandleMouseMoveEvent() {
+  if (!IsCursorInBalloonCollection()) {
+    // Mouse has left the region.  Schedule a reposition after
+    // a short delay.
+    if (reposition_factory_.empty()) {
+      MessageLoop::current()->PostDelayedTask(
+          FROM_HERE,
+          reposition_factory_.NewRunnableMethod(
+              &BalloonCollectionImpl::CancelOffsets),
+          kRepositionDelay);
+    }
+  } else {
+    // Mouse moved back into the region.  Cancel the reposition.
+    reposition_factory_.RevokeAll();
+  }
+}
+#endif
+
+BalloonCollectionImpl::Layout::Layout() {
+  RefreshSystemMetrics();
+}
+
+void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size,
+                                                     int* total_size) const {
+  DCHECK(max_balloon_size && total_size);
+
+  // All placement schemes are vertical, so we only care about height.
+  *total_size = work_area_.height();
+  *max_balloon_size = max_balloon_height();
+}
+
+gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const {
+  int x = 0;
+  int y = 0;
+  switch (placement_) {
+    case VERTICALLY_FROM_TOP_LEFT:
+      x = work_area_.x() + HorizontalEdgeMargin();
+      y = work_area_.y() + VerticalEdgeMargin();
+      break;
+    case VERTICALLY_FROM_TOP_RIGHT:
+      x = work_area_.right() - HorizontalEdgeMargin();
+      y = work_area_.y() + VerticalEdgeMargin();
+      break;
+    case VERTICALLY_FROM_BOTTOM_LEFT:
+      x = work_area_.x() + HorizontalEdgeMargin();
+      y = work_area_.bottom() - VerticalEdgeMargin();
+      break;
+    case VERTICALLY_FROM_BOTTOM_RIGHT:
+      x = work_area_.right() - HorizontalEdgeMargin();
+      y = work_area_.bottom() - VerticalEdgeMargin();
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  return gfx::Point(x, y);
+}
+
+gfx::Point BalloonCollectionImpl::Layout::NextPosition(
+    const gfx::Size& balloon_size,
+    gfx::Point* position_iterator) const {
+  DCHECK(position_iterator);
+
+  int x = 0;
+  int y = 0;
+  switch (placement_) {
+    case VERTICALLY_FROM_TOP_LEFT:
+      x = position_iterator->x();
+      y = position_iterator->y();
+      position_iterator->set_y(position_iterator->y() + balloon_size.height() +
+                               InterBalloonMargin());
+      break;
+    case VERTICALLY_FROM_TOP_RIGHT:
+      x = position_iterator->x() - balloon_size.width();
+      y = position_iterator->y();
+      position_iterator->set_y(position_iterator->y() + balloon_size.height() +
+                               InterBalloonMargin());
+      break;
+    case VERTICALLY_FROM_BOTTOM_LEFT:
+      position_iterator->set_y(position_iterator->y() - balloon_size.height() -
+                               InterBalloonMargin());
+      x = position_iterator->x();
+      y = position_iterator->y();
+      break;
+    case VERTICALLY_FROM_BOTTOM_RIGHT:
+      position_iterator->set_y(position_iterator->y() - balloon_size.height() -
+                               InterBalloonMargin());
+      x = position_iterator->x() - balloon_size.width();
+      y = position_iterator->y();
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  return gfx::Point(x, y);
+}
+
+gfx::Point BalloonCollectionImpl::Layout::OffScreenLocation() const {
+  int x = 0;
+  int y = 0;
+  switch (placement_) {
+    case VERTICALLY_FROM_TOP_LEFT:
+      x = work_area_.x() + HorizontalEdgeMargin();
+      y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin();
+      break;
+    case VERTICALLY_FROM_TOP_RIGHT:
+      x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin();
+      y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin();
+      break;
+    case VERTICALLY_FROM_BOTTOM_LEFT:
+      x = work_area_.x() + HorizontalEdgeMargin();
+      y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin();
+      break;
+    case VERTICALLY_FROM_BOTTOM_RIGHT:
+      x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin();
+      y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin();
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  return gfx::Point(x, y);
+}
+
+bool BalloonCollectionImpl::Layout::RequiresOffsets() const {
+  // Layout schemes that grow up from the bottom require offsets;
+  // schemes that grow down do not require offsets.
+  bool offsets = (placement_ == VERTICALLY_FROM_BOTTOM_LEFT ||
+                  placement_ == VERTICALLY_FROM_BOTTOM_RIGHT);
+
+#if defined(OS_MACOSX)
+  // These schemes are in screen-coordinates, and top and bottom
+  // are inverted on Mac.
+  offsets = !offsets;
+#endif
+
+  return offsets;
+}
+
+// static
+gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits(
+    const gfx::Size& size) {
+  // restrict to the min & max sizes
+  return gfx::Size(
+      std::max(min_balloon_width(),
+               std::min(max_balloon_width(), size.width())),
+      std::max(min_balloon_height(),
+               std::min(max_balloon_height(), size.height())));
+}
+
+bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() {
+  bool changed = false;
+
+#if defined(OS_MACOSX)
+  gfx::Rect new_work_area = GetMacWorkArea();
+#else
+  scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
+      WindowSizer::CreateDefaultMonitorInfoProvider());
+  gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea();
+#endif
+  if (!work_area_.Equals(new_work_area)) {
+    work_area_.SetRect(new_work_area.x(), new_work_area.y(),
+                       new_work_area.width(), new_work_area.height());
+    changed = true;
+  }
+
+  return changed;
+}
diff --git a/chrome/browser/notifications/balloon_collection_impl.h b/chrome/browser/notifications/balloon_collection_impl.h
index d123717..fdabcb5 100644
--- a/chrome/browser/notifications/balloon_collection_impl.h
+++ b/chrome/browser/notifications/balloon_collection_impl.h
@@ -14,8 +14,8 @@
 #include "base/message_loop.h"
 #include "chrome/browser/notifications/balloon_collection.h"
 #include "chrome/browser/notifications/balloon_collection_base.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 
 // Mac balloons grow from the top down and have close buttons on top, so
 // offsetting is not necessary for easy multiple-closing.  Other platforms grow
@@ -50,7 +50,7 @@
   virtual void SetPositionPreference(PositionPreference position);
   virtual void DisplayChanged();
   virtual void OnBalloonClosed(Balloon* source);
-  virtual const Balloons& GetActiveBalloons() { return base_.balloons(); }
+  virtual const Balloons& GetActiveBalloons();
 
   // MessageLoopForUI::Observer interface.
 #if defined(OS_WIN)
@@ -120,6 +120,10 @@
     // to be used as the initial position for an animation into view.
     gfx::Point OffScreenLocation() const;
 
+    // Returns true if the layout requires offsetting for keeping the close
+    // buttons under the cursor during rapid-close interaction.
+    bool RequiresOffsets() const;
+
    private:
     // Layout parameters
     int VerticalEdgeMargin() const;
@@ -142,6 +146,9 @@
   virtual Balloon* MakeBalloon(const Notification& notification,
                                Profile* profile);
 
+  // Gets a bounding box for all the current balloons in screen coordinates.
+  gfx::Rect GetBalloonsBoundingBox() const;
+
  private:
   // Adjusts the positions of the balloons (e.g., when one is closed).
   // Implemented by each platform for specific UI requirements.
diff --git a/chrome/browser/notifications/balloon_collection_linux.cc b/chrome/browser/notifications/balloon_collection_linux.cc
index 099193c..0255ae8 100644
--- a/chrome/browser/notifications/balloon_collection_linux.cc
+++ b/chrome/browser/notifications/balloon_collection_linux.cc
@@ -1,12 +1,17 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/notifications/balloon_collection_impl.h"
 
 #include "chrome/browser/notifications/balloon.h"
-#include "chrome/browser/views/notifications/balloon_view.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/ui/views/notifications/balloon_view.h"
+#else
+#include "chrome/browser/ui/gtk/notifications/balloon_view_gtk.h"
+#endif
 
 Balloon* BalloonCollectionImpl::MakeBalloon(const Notification& notification,
                                             Profile* profile) {
@@ -46,25 +51,13 @@
 }
 
 bool BalloonCollectionImpl::IsCursorInBalloonCollection() const {
-  const Balloons& balloons = base_.balloons();
-  if (balloons.empty())
-    return false;
-
-  gfx::Point upper_left = balloons[balloons.size() - 1]->GetPosition();
-  gfx::Point lower_right = layout_.GetLayoutOrigin();
-
-  gfx::Rect bounds = gfx::Rect(upper_left.x(),
-                               upper_left.y(),
-                               lower_right.x() - upper_left.x(),
-                               lower_right.y() - upper_left.y());
-
   GdkScreen* screen = gdk_screen_get_default();
   GdkDisplay* display = gdk_screen_get_display(screen);
   gint x, y;
   gdk_display_get_pointer(display, NULL, &x, &y, NULL);
   gfx::Point cursor(x, y);
 
-  return bounds.Contains(cursor);
+  return GetBalloonsBoundingBox().Contains(cursor);
 }
 
 void BalloonCollectionImpl::SetPositionPreference(
diff --git a/chrome/browser/notifications/balloon_collection_win.cc b/chrome/browser/notifications/balloon_collection_win.cc
index 742872b..821b5f4 100644
--- a/chrome/browser/notifications/balloon_collection_win.cc
+++ b/chrome/browser/notifications/balloon_collection_win.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/notifications/balloon_collection_impl.h"
 
 #include "chrome/browser/notifications/balloon.h"
-#include "chrome/browser/views/notifications/balloon_view.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/views/notifications/balloon_view.h"
+#include "ui/gfx/rect.h"
 
 Balloon* BalloonCollectionImpl::MakeBalloon(const Notification& notification,
                                             Profile* profile) {
@@ -44,22 +44,9 @@
 }
 
 bool BalloonCollectionImpl::IsCursorInBalloonCollection() const {
-  const Balloons& balloons = base_.balloons();
-  if (balloons.empty())
-    return false;
-
-  gfx::Point upper_left = balloons[balloons.size() - 1]->GetPosition();
-  gfx::Point lower_right = layout_.GetLayoutOrigin();
-
-  gfx::Rect bounds = gfx::Rect(upper_left.x(),
-                               upper_left.y(),
-                               lower_right.x() - upper_left.x(),
-                               lower_right.y() - upper_left.y());
-
   DWORD pos = GetMessagePos();
   gfx::Point cursor(pos);
-
-  return bounds.Contains(cursor);
+  return GetBalloonsBoundingBox().Contains(cursor);
 }
 
 void BalloonCollectionImpl::SetPositionPreference(
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index d24f3d7..6cf4ba1 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,42 +14,20 @@
 #include "chrome/browser/renderer_preferences_util.h"
 #include "chrome/common/bindings_policy.h"
 #include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/render_messages.h"
+#include "chrome/common/render_messages_params.h"
 #include "chrome/common/renderer_preferences.h"
 #include "chrome/common/url_constants.h"
 #include "webkit/glue/webpreferences.h"
 
-namespace {
-class BalloonPaintObserver : public RenderWidgetHost::PaintObserver {
- public:
-  explicit BalloonPaintObserver(BalloonHost* balloon_host)
-      : balloon_host_(balloon_host) {
-  }
-
-  virtual void RenderWidgetHostWillPaint(RenderWidgetHost* rhw) {}
-  virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh);
-
- private:
-  BalloonHost* balloon_host_;
-
-  DISALLOW_COPY_AND_ASSIGN(BalloonPaintObserver);
-};
-
-void BalloonPaintObserver::RenderWidgetHostDidPaint(RenderWidgetHost* rwh) {
-  balloon_host_->RenderWidgetHostDidPaint();
-  // WARNING: we may have been deleted (if the balloon host cleared the paint
-  // observer).
-}
-
-}  // namespace
-
 BalloonHost::BalloonHost(Balloon* balloon)
     : render_view_host_(NULL),
       balloon_(balloon),
       initialized_(false),
       should_notify_on_disconnect_(false),
-      enable_dom_ui_(false) {
+      enable_web_ui_(false) {
   DCHECK(balloon_);
 
   // If the notification is for an extension URL, make sure to use the extension
@@ -73,7 +51,7 @@
   }
 }
 
-Browser* BalloonHost::GetBrowser() const {
+Browser* BalloonHost::GetBrowser() {
   // Notifications aren't associated with a particular browser.
   return NULL;
 }
@@ -92,7 +70,7 @@
 WebPreferences BalloonHost::GetWebkitPrefs() {
   WebPreferences web_prefs =
       RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(),
-                                                   enable_dom_ui_);
+                                                   enable_web_ui_);
   web_prefs.allow_scripts_to_close_windows = true;
   return web_prefs;
 }
@@ -151,7 +129,7 @@
   return this;
 }
 
-void BalloonHost::ProcessDOMUIMessage(
+void BalloonHost::ProcessWebUIMessage(
     const ViewHostMsg_DomMessage_Params& params) {
   if (extension_function_dispatcher_.get()) {
     extension_function_dispatcher_->HandleRequest(params);
@@ -162,17 +140,16 @@
 // open pages in new tabs.
 void BalloonHost::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   delegate_view_helper_.CreateNewWindow(
       route_id,
       balloon_->profile(),
       site_instance_.get(),
-      DOMUIFactory::GetDOMUIType(balloon_->profile(),
+      WebUIFactory::GetWebUIType(balloon_->profile(),
           balloon_->notification().content_url()),
       this,
-      window_container_type,
-      frame_name);
+      params.window_container_type,
+      params.frame_name);
 }
 
 void BalloonHost::ShowCreatedWindow(int route_id,
@@ -224,8 +201,8 @@
   if (extension_function_dispatcher_.get()) {
     rvh->AllowBindings(BindingsPolicy::EXTENSION);
     rvh->set_is_extension_process(true);
-  } else if (enable_dom_ui_) {
-    rvh->AllowBindings(BindingsPolicy::DOM_UI);
+  } else if (enable_web_ui_) {
+    rvh->AllowBindings(BindingsPolicy::WEB_UI);
   }
 
   // Do platform-specific initialization.
@@ -236,17 +213,18 @@
   rvh->set_view(render_widget_host_view());
   rvh->CreateRenderView(string16());
 #if defined(OS_MACOSX)
-  rvh->set_paint_observer(new BalloonPaintObserver(this));
+  registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
+      Source<RenderWidgetHost>(render_view_host_));
 #endif
   rvh->NavigateToURL(balloon_->notification().content_url());
 
   initialized_ = true;
 }
 
-void BalloonHost::EnableDOMUI() {
+void BalloonHost::EnableWebUI() {
   DCHECK(render_view_host_ == NULL) <<
-      "EnableDOMUI has to be called before a renderer is created.";
-  enable_dom_ui_ = true;
+      "EnableWebUI has to be called before a renderer is created.";
+  enable_web_ui_ = true;
 }
 
 void BalloonHost::UpdateInspectorSetting(const std::string& key,
@@ -259,10 +237,14 @@
   RenderViewHostDelegateHelper::ClearInspectorSettings(GetProfile());
 }
 
-void BalloonHost::RenderWidgetHostDidPaint() {
-  render_view_host_->set_paint_observer(NULL);
-  render_view_host_->EnablePreferredSizeChangedMode(
-      kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
+void BalloonHost::Observe(NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  if (type == NotificationType::RENDER_WIDGET_HOST_DID_PAINT) {
+    registrar_.RemoveAll();
+    render_view_host_->EnablePreferredSizeChangedMode(
+        kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
+  }
 }
 
 BalloonHost::~BalloonHost() {
diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index 358cb61..afb3eb1 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,8 @@
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
 
 class Balloon;
 class Browser;
@@ -22,7 +24,8 @@
 
 class BalloonHost : public RenderViewHostDelegate,
                     public RenderViewHostDelegate::View,
-                    public ExtensionFunctionDispatcher::Delegate {
+                    public ExtensionFunctionDispatcher::Delegate,
+                    public NotificationObserver {
  public:
   explicit BalloonHost(Balloon* balloon);
 
@@ -33,7 +36,7 @@
   void Shutdown();
 
   // ExtensionFunctionDispatcher::Delegate overrides.
-  virtual Browser* GetBrowser() const;
+  virtual Browser* GetBrowser();
   virtual gfx::NativeView GetNativeViewOfHost();
   virtual TabContents* associated_tab_contents() const;
 
@@ -57,17 +60,21 @@
   virtual int GetBrowserWindowID() const;
   virtual ViewType::Type GetRenderViewType() const;
   virtual RenderViewHostDelegate::View* GetViewDelegate();
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
+
+  // NotificationObserver override.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
 
   // RenderViewHostDelegate::View methods. Only the ones for opening new
   // windows are currently implemented.
   virtual void CreateNewWindow(
       int route_id,
-      WindowContainerType window_container_type,
-      const string16& frame_name);
+      const ViewHostMsg_CreateWindow_Params& params);
   virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type) {}
-  virtual void CreateNewFullscreenWidget(
-      int route_id, WebKit::WebPopupType popup_type) {}
+  virtual void CreateNewFullscreenWidget(int route_id) {}
   virtual void ShowCreatedWindow(int route_id,
                                  WindowOpenDisposition disposition,
                                  const gfx::Rect& initial_pos,
@@ -105,16 +112,13 @@
   virtual void UpdatePreferredSize(const gfx::Size& pref_size);
   virtual RendererPreferences GetRendererPrefs(Profile* profile) const;
 
-  // Enable DOM UI. This has to be called before renderer is created.
-  void EnableDOMUI();
+  // Enable Web UI. This has to be called before renderer is created.
+  void EnableWebUI();
 
   virtual void UpdateInspectorSetting(const std::string& key,
                                       const std::string& value);
   virtual void ClearInspectorSettings();
 
-  // Called when the render view has painted.
-  void RenderWidgetHostDidPaint();
-
  protected:
   virtual ~BalloonHost();
   // Must override in platform specific implementations.
@@ -150,8 +154,10 @@
   // rendering a page from an extension.
   scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_;
 
-  // A flag to enable DOM UI.
-  bool enable_dom_ui_;
+  // A flag to enable Web UI.
+  bool enable_web_ui_;
+
+  NotificationRegistrar registrar_;
 };
 
 #endif  // CHROME_BROWSER_NOTIFICATIONS_BALLOON_HOST_H_
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index a1eaeb3..0f837f9 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/notifications/desktop_notification_service.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/metrics/histogram.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
@@ -36,13 +34,171 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/escape.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 using WebKit::WebNotificationPresenter;
 using WebKit::WebTextDirection;
 
 const ContentSetting kDefaultSetting = CONTENT_SETTING_ASK;
 
+// NotificationPermissionCallbackTask -----------------------------------------
+
+// A task object which calls the renderer to inform the web page that the
+// permission request has completed.
+class NotificationPermissionCallbackTask : public Task {
+ public:
+  NotificationPermissionCallbackTask(int process_id,
+                                     int route_id,
+                                     int request_id);
+  virtual ~NotificationPermissionCallbackTask();
+
+ private:
+  virtual void Run();
+
+  int process_id_;
+  int route_id_;
+  int request_id_;
+};
+
+NotificationPermissionCallbackTask::NotificationPermissionCallbackTask(
+    int process_id,
+    int route_id,
+    int request_id)
+    : process_id_(process_id),
+      route_id_(route_id),
+      request_id_(request_id) {
+}
+
+NotificationPermissionCallbackTask::~NotificationPermissionCallbackTask() {
+}
+
+void NotificationPermissionCallbackTask::Run() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
+  if (host)
+    host->Send(new ViewMsg_PermissionRequestDone(route_id_, request_id_));
+}
+
+
+// NotificationPermissionInfoBarDelegate --------------------------------------
+
+// The delegate for the infobar shown when an origin requests notification
+// permissions.
+class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  NotificationPermissionInfoBarDelegate(TabContents* contents,
+                                        const GURL& origin,
+                                        const string16& display_name,
+                                        int process_id,
+                                        int route_id,
+                                        int callback_context);
+
+ private:
+  virtual ~NotificationPermissionInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+
+  // The origin we are asking for permissions on.
+  GURL origin_;
+
+  // The display name for the origin to be displayed.  Will be different from
+  // origin_ for extensions.
+  string16 display_name_;
+
+  // The Profile that we restore sessions from.
+  Profile* profile_;
+
+  // The callback information that tells us how to respond to javascript via
+  // the correct RenderView.
+  int process_id_;
+  int route_id_;
+  int callback_context_;
+
+  // Whether the user clicked one of the buttons.
+  bool action_taken_;
+
+  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
+};
+
+NotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate(
+    TabContents* contents,
+    const GURL& origin,
+    const string16& display_name,
+    int process_id,
+    int route_id,
+    int callback_context)
+    : ConfirmInfoBarDelegate(contents),
+      origin_(origin),
+      display_name_(display_name),
+      profile_(contents->profile()),
+      process_id_(process_id),
+      route_id_(route_id),
+      callback_context_(callback_context),
+      action_taken_(false) {
+}
+
+NotificationPermissionInfoBarDelegate::
+    ~NotificationPermissionInfoBarDelegate() {
+}
+
+void NotificationPermissionInfoBarDelegate::InfoBarClosed() {
+  if (!action_taken_)
+    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
+
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+      new NotificationPermissionCallbackTask(process_id_, route_id_,
+                                             callback_context_));
+
+  delete this;
+}
+
+SkBitmap* NotificationPermissionInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+     IDR_PRODUCT_ICON_32);
+}
+
+InfoBarDelegate::Type
+    NotificationPermissionInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+string16 NotificationPermissionInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
+                                    display_name_);
+}
+
+string16 NotificationPermissionInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_NOTIFICATION_PERMISSION_YES : IDS_NOTIFICATION_PERMISSION_NO);
+}
+
+bool NotificationPermissionInfoBarDelegate::Accept() {
+  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
+  profile_->GetDesktopNotificationService()->GrantPermission(origin_);
+  action_taken_ = true;
+  return true;
+}
+
+bool NotificationPermissionInfoBarDelegate::Cancel() {
+  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
+  profile_->GetDesktopNotificationService()->DenyPermission(origin_);
+  action_taken_ = true;
+  return true;
+}
+
+
+// DesktopNotificationService -------------------------------------------------
+
 // static
 string16 DesktopNotificationService::CreateDataUrl(
     const GURL& icon_url, const string16& title, const string16& body,
@@ -94,123 +250,6 @@
                       EscapeQueryParamValue(data, false));
 }
 
-// A task object which calls the renderer to inform the web page that the
-// permission request has completed.
-class NotificationPermissionCallbackTask : public Task {
- public:
-  NotificationPermissionCallbackTask(int process_id, int route_id,
-      int request_id)
-      : process_id_(process_id),
-        route_id_(route_id),
-        request_id_(request_id) {
-  }
-
-  virtual void Run() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
-    if (host)
-      host->Send(new ViewMsg_PermissionRequestDone(route_id_, request_id_));
-  }
-
- private:
-  int process_id_;
-  int route_id_;
-  int request_id_;
-};
-
-// The delegate for the infobar shown when an origin requests notification
-// permissions.
-class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
- public:
-  NotificationPermissionInfoBarDelegate(TabContents* contents,
-                                        const GURL& origin,
-                                        const string16& display_name,
-                                        int process_id,
-                                        int route_id,
-                                        int callback_context)
-      : ConfirmInfoBarDelegate(contents),
-        origin_(origin),
-        display_name_(display_name),
-        profile_(contents->profile()),
-        process_id_(process_id),
-        route_id_(route_id),
-        callback_context_(callback_context),
-        action_taken_(false) {
-  }
-
-  // Overridden from ConfirmInfoBarDelegate:
-  virtual void InfoBarClosed() {
-    if (!action_taken_)
-      UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
-
-    BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      new NotificationPermissionCallbackTask(
-          process_id_, route_id_, callback_context_));
-
-    delete this;
-  }
-
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
-                                      display_name_);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-       IDR_PRODUCT_ICON_32);
-  }
-
-  virtual int GetButtons() const {
-    return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    return button == BUTTON_OK ?
-        l10n_util::GetStringUTF16(IDS_NOTIFICATION_PERMISSION_YES) :
-        l10n_util::GetStringUTF16(IDS_NOTIFICATION_PERMISSION_NO);
-  }
-
-  virtual bool Accept() {
-    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
-    profile_->GetDesktopNotificationService()->GrantPermission(origin_);
-    action_taken_ = true;
-    return true;
-  }
-
-  virtual bool Cancel() {
-    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
-    profile_->GetDesktopNotificationService()->DenyPermission(origin_);
-    action_taken_ = true;
-    return true;
-  }
-
-  // Overridden from InfoBarDelegate:
-  virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
-
- private:
-  // The origin we are asking for permissions on.
-  GURL origin_;
-
-  // The display name for the origin to be displayed.  Will be different from
-  // origin_ for extensions.
-  string16 display_name_;
-
-  // The Profile that we restore sessions from.
-  Profile* profile_;
-
-  // The callback information that tells us how to respond to javascript via
-  // the correct RenderView.
-  int process_id_;
-  int route_id_;
-  int callback_context_;
-
-  // Whether the user clicked one of the buttons.
-  bool action_taken_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
-};
-
 DesktopNotificationService::DesktopNotificationService(Profile* profile,
     NotificationUIManager* ui_manager)
     : profile_(profile),
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index bb6691b..e208be3 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -17,7 +17,7 @@
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
 
 class Notification;
 class NotificationUIManager;
diff --git a/chrome/browser/notifications/desktop_notification_service_unittest.cc b/chrome/browser/notifications/desktop_notification_service_unittest.cc
index 64ad3fc..05a3dd5 100644
--- a/chrome/browser/notifications/desktop_notification_service_unittest.cc
+++ b/chrome/browser/notifications/desktop_notification_service_unittest.cc
@@ -16,7 +16,7 @@
 #include "chrome/test/testing_profile.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
 
 namespace {
 
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.cc b/chrome/browser/notifications/desktop_notifications_unittest.cc
index 762990f..6effdf1 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/notifications/desktop_notifications_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/test/testing_pref_service.h"
 
@@ -16,6 +17,10 @@
 // static
 std::string DesktopNotificationsTest::log_output_;
 
+MockBalloonCollection::MockBalloonCollection() {}
+
+MockBalloonCollection::~MockBalloonCollection() {}
+
 void MockBalloonCollection::Add(const Notification& notification,
                                 Profile* profile) {
   // Swap in a logging proxy for the purpose of logging calls that
@@ -324,6 +329,39 @@
   EXPECT_EQ(std::string::npos, data_url.spec().find("%3ci%3e"));
 }
 
+TEST_F(DesktopNotificationsTest, TestBoundingBox) {
+  // Create some notifications.
+  ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
+  for (int id = 0; id <= 3; ++id) {
+    params.notification_id = id;
+    EXPECT_TRUE(service_->ShowDesktopNotification(
+        params, 0, 0, DesktopNotificationService::PageNotification));
+  }
+
+  gfx::Rect box = balloon_collection_->GetBalloonsBoundingBox();
+
+  // Try this for all positions.
+  BalloonCollection::PositionPreference pref;
+  for (pref = BalloonCollection::UPPER_RIGHT;
+       pref <= BalloonCollection::LOWER_LEFT;
+       pref = static_cast<BalloonCollection::PositionPreference>(pref + 1)) {
+    // Make sure each balloon's 4 corners are inside the box.
+    std::deque<Balloon*>& balloons = balloon_collection_->balloons();
+    std::deque<Balloon*>::iterator iter;
+    for (iter = balloons.begin(); iter != balloons.end(); ++iter) {
+      int min_x = (*iter)->GetPosition().x();
+      int max_x = min_x + (*iter)->GetViewSize().width() - 1;
+      int min_y = (*iter)->GetPosition().y();
+      int max_y = min_y + (*iter)->GetViewSize().height() - 1;
+
+      EXPECT_TRUE(box.Contains(gfx::Point(min_x, min_y)));
+      EXPECT_TRUE(box.Contains(gfx::Point(min_x, max_y)));
+      EXPECT_TRUE(box.Contains(gfx::Point(max_x, min_y)));
+      EXPECT_TRUE(box.Contains(gfx::Point(max_x, max_y)));
+    }
+  }
+}
+
 TEST_F(DesktopNotificationsTest, TestPositionPreference) {
   // Set position preference to lower right.
   profile_->GetPrefs()->SetInteger(prefs::kDesktopNotificationPosition,
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.h b/chrome/browser/notifications/desktop_notifications_unittest.h
index 9f556e4..25e5270 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.h
+++ b/chrome/browser/notifications/desktop_notifications_unittest.h
@@ -17,7 +17,6 @@
 #include "chrome/browser/notifications/notification_test_util.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/notifications/notifications_prefs_cache.h"
-#include "chrome/common/render_messages.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -29,7 +28,8 @@
 // of notifications that are added to it.
 class MockBalloonCollection : public BalloonCollectionImpl {
  public:
-  MockBalloonCollection() {}
+  MockBalloonCollection();
+  virtual ~MockBalloonCollection();
 
   // Our mock collection has an area large enough for a fixed number
   // of balloons.
@@ -59,6 +59,11 @@
   int MinHeight() { return Layout::min_balloon_height(); }
   int MaxHeight() { return Layout::max_balloon_height(); }
 
+  // Returns the bounding box.
+  gfx::Rect GetBalloonsBoundingBox() {
+    return BalloonCollectionImpl::GetBalloonsBoundingBox();
+  }
+
  private:
   std::deque<Balloon*> balloons_;
 };
@@ -66,7 +71,7 @@
 class DesktopNotificationsTest : public testing::Test {
  public:
   DesktopNotificationsTest();
-  ~DesktopNotificationsTest();
+  virtual ~DesktopNotificationsTest();
 
   static void log(const std::string& message) {
     log_output_.append(message);
diff --git a/chrome/browser/notifications/notification_exceptions_table_model.cc b/chrome/browser/notifications/notification_exceptions_table_model.cc
index e70536c..7a70875 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model.cc
+++ b/chrome/browser/notifications/notification_exceptions_table_model.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/notifications/notification_exceptions_table_model.h"
 
-#include "app/l10n_util.h"
-#include "app/table_model_observer.h"
 #include "base/auto_reset.h"
 #include "chrome/common/content_settings.h"
 #include "chrome/common/content_settings_helper.h"
@@ -14,6 +12,8 @@
 #include "chrome/common/notification_type.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
 
 struct NotificationExceptionsTableModel::Entry {
   Entry(const GURL& origin, ContentSetting setting);
@@ -93,7 +93,7 @@
 }
 
 void NotificationExceptionsTableModel::SetObserver(
-    TableModelObserver* observer) {
+    ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
diff --git a/chrome/browser/notifications/notification_exceptions_table_model.h b/chrome/browser/notifications/notification_exceptions_table_model.h
index de19963..c9e2100 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model.h
+++ b/chrome/browser/notifications/notification_exceptions_table_model.h
@@ -28,7 +28,7 @@
   // Overridden from TableModel:
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
   // Overridden from NotificationObserver:
   virtual void Observe(NotificationType type,
@@ -48,7 +48,7 @@
   // that we ourselves caused.
   bool updates_disabled_;
   NotificationRegistrar registrar_;
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(NotificationExceptionsTableModel);
 };
diff --git a/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc b/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc
index 4fdcb24..693f1ec 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc
+++ b/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/notifications/notification_exceptions_table_model.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
 #include "chrome/test/testing_profile.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 class NotificationExceptionsTableModelTest : public RenderViewHostTestHarness {
  public:
diff --git a/chrome/browser/notifications/notification_options_menu_model.cc b/chrome/browser/notifications/notification_options_menu_model.cc
index fb05bda..c524643 100644
--- a/chrome/browser/notifications/notification_options_menu_model.cc
+++ b/chrome/browser/notifications/notification_options_menu_model.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/notifications/notification_options_menu_model.h"
 
-#include "app/l10n_util.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
@@ -22,6 +21,7 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/ui/views/browser_dialogs.h"
@@ -41,7 +41,7 @@
 const int kCornerDefault = 20;
 
 CornerSelectionMenuModel::CornerSelectionMenuModel(Balloon* balloon)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       balloon_(balloon) {
   AddRadioItem(kCornerDefault,
                l10n_util::GetStringUTF16(IDS_NOTIFICATION_POSITION_DEFAULT),
@@ -91,7 +91,7 @@
 }
 
 bool CornerSelectionMenuModel::GetAcceleratorForCommandId(
-    int command_id, menus::Accelerator* accelerator) {
+    int command_id, ui::Accelerator* accelerator) {
   // Currently no accelerators.
   return false;
 }
@@ -116,7 +116,7 @@
 }
 
 NotificationOptionsMenuModel::NotificationOptionsMenuModel(Balloon* balloon)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       balloon_(balloon) {
 
   const Notification& notification = balloon->notification();
@@ -205,7 +205,7 @@
 }
 
 bool NotificationOptionsMenuModel::GetAcceleratorForCommandId(
-    int /* command_id */, menus::Accelerator* /* accelerator */) {
+    int /* command_id */, ui::Accelerator* /* accelerator */) {
   // Currently no accelerators.
   return false;
 }
diff --git a/chrome/browser/notifications/notification_options_menu_model.h b/chrome/browser/notifications/notification_options_menu_model.h
index 022b7e0..033f360 100644
--- a/chrome/browser/notifications/notification_options_menu_model.h
+++ b/chrome/browser/notifications/notification_options_menu_model.h
@@ -6,21 +6,21 @@
 #define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_OPTIONS_MENU_MODEL_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
 #include "chrome/browser/notifications/balloon.h"
+#include "ui/base/models/simple_menu_model.h"
 
 // Model for the corner-selection submenu.
-class CornerSelectionMenuModel : public menus::SimpleMenuModel,
-                                 public menus::SimpleMenuModel::Delegate {
+class CornerSelectionMenuModel : public ui::SimpleMenuModel,
+                                 public ui::SimpleMenuModel::Delegate {
  public:
   explicit CornerSelectionMenuModel(Balloon* balloon);
   virtual ~CornerSelectionMenuModel();
 
-  // Overridden from menus::SimpleMenuModel::Delegate:
+  // Overridden from ui::SimpleMenuModel::Delegate:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
  private:
@@ -31,21 +31,21 @@
 };
 
 // Model for the notification options menu itself.
-class NotificationOptionsMenuModel : public menus::SimpleMenuModel,
-                                     public menus::SimpleMenuModel::Delegate {
+class NotificationOptionsMenuModel : public ui::SimpleMenuModel,
+                                     public ui::SimpleMenuModel::Delegate {
  public:
   explicit NotificationOptionsMenuModel(Balloon* balloon);
   virtual ~NotificationOptionsMenuModel();
 
-  // Overridden from menus::SimpleMenuModel:
+  // Overridden from ui::SimpleMenuModel:
   virtual bool IsItemForCommandIdDynamic(int command_id) const;
   virtual string16 GetLabelForCommandId(int command_id) const;
 
-  // Overridden from menus::SimpleMenuModel::Delegate:
+  // Overridden from ui::SimpleMenuModel::Delegate:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
  private:
diff --git a/chrome/browser/notifications/notification_test_util.h b/chrome/browser/notifications/notification_test_util.h
index fbaec4e..38863cf 100644
--- a/chrome/browser/notifications/notification_test_util.h
+++ b/chrome/browser/notifications/notification_test_util.h
@@ -10,7 +10,7 @@
 
 #include "chrome/browser/notifications/notification_object_proxy.h"
 #include "chrome/browser/notifications/balloon.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 // NotificationDelegate which does nothing, useful for testing when
 // the notification events are not important.
diff --git a/chrome/browser/notifications/notification_ui_manager.cc b/chrome/browser/notifications/notification_ui_manager.cc
index 950bd6c..51a2c66 100644
--- a/chrome/browser/notifications/notification_ui_manager.cc
+++ b/chrome/browser/notifications/notification_ui_manager.cc
@@ -8,6 +8,8 @@
 #include "base/scoped_ptr.h"
 #include "base/stl_util-inl.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/fullscreen.h"
+#include "chrome/browser/idle.h"
 #include "chrome/browser/notifications/balloon_collection.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/prefs/pref_service.h"
@@ -16,6 +18,10 @@
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 
+namespace {
+const int kUserStatePollingIntervalSeconds = 1;
+}
+
 // A class which represents a notification waiting to be shown.
 class QueuedNotification {
  public:
@@ -42,14 +48,21 @@
 };
 
 NotificationUIManager::NotificationUIManager(PrefService* local_state)
-    : balloon_collection_(NULL) {
+    : balloon_collection_(NULL),
+      is_user_active_(true) {
   registrar_.Add(this, NotificationType::APP_TERMINATING,
                  NotificationService::AllSources());
   position_pref_.Init(prefs::kDesktopNotificationPosition, local_state, this);
+#if defined(OS_MACOSX)
+  InitFullScreenMonitor();
+#endif
 }
 
 NotificationUIManager::~NotificationUIManager() {
   STLDeleteElements(&show_queue_);
+#if defined(OS_MACOSX)
+  StopFullScreenMonitor();
+#endif
 }
 
 // static
@@ -126,8 +139,29 @@
 }
 
 void NotificationUIManager::CheckAndShowNotifications() {
-  // TODO(johnnyg): http://crbug.com/25061 - Check for user idle/presentation.
-  ShowNotifications();
+  CheckUserState();
+  if (is_user_active_)
+    ShowNotifications();
+}
+
+void NotificationUIManager::CheckUserState() {
+  bool is_user_active_previously = is_user_active_;
+  is_user_active_ = CalculateIdleState(0) != IDLE_STATE_LOCKED &&
+                    !IsFullScreenMode();
+  if (is_user_active_ == is_user_active_previously)
+    return;
+
+  if (is_user_active_) {
+    user_state_check_timer_.Stop();
+    // We need to show any postponed nofications when the user becomes active
+    // again.
+    ShowNotifications();
+  } else if (!user_state_check_timer_.IsRunning()) {
+    // Start a timer to detect the moment at which the user becomes active.
+    user_state_check_timer_.Start(
+        base::TimeDelta::FromSeconds(kUserStatePollingIntervalSeconds), this,
+        &NotificationUIManager::CheckUserState);
+  }
 }
 
 void NotificationUIManager::ShowNotifications() {
diff --git a/chrome/browser/notifications/notification_ui_manager.h b/chrome/browser/notifications/notification_ui_manager.h
index 3a0125c..7ac63a2 100644
--- a/chrome/browser/notifications/notification_ui_manager.h
+++ b/chrome/browser/notifications/notification_ui_manager.h
@@ -11,6 +11,7 @@
 
 #include "base/id_map.h"
 #include "base/scoped_ptr.h"
+#include "base/timer.h"
 #include "chrome/browser/notifications/balloon.h"
 #include "chrome/browser/notifications/balloon_collection.h"
 #include "chrome/browser/prefs/pref_member.h"
@@ -73,12 +74,12 @@
   // be placed on the screen.
   void SetPositionPreference(BalloonCollection::PositionPreference preference);
 
-  // NotificationObserver interface (the event signaling kind of notifications)
+ private:
+  // NotificationObserver override.
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
- private:
   // Attempts to display notifications from the show_queue if the user
   // is active.
   void CheckAndShowNotifications();
@@ -93,6 +94,9 @@
   // returns true if the replacement happened.
   bool TryReplacement(const Notification& notification);
 
+  // Checks the user state to decide if we want to show the notification.
+  void CheckUserState();
+
   // An owned pointer to the collection of active balloons.
   scoped_ptr<BalloonCollection> balloon_collection_;
 
@@ -106,6 +110,10 @@
   // Prefs listener for the position preference.
   IntegerPrefMember position_pref_;
 
+  // Used by screen-saver and full-screen handling support.
+  bool is_user_active_;
+  base::RepeatingTimer<NotificationUIManager> user_state_check_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(NotificationUIManager);
 };
 
diff --git a/chrome/browser/notifications/notifications_interactive_uitest.cc b/chrome/browser/notifications/notifications_interactive_uitest.cc
index 43d905f..d2ace68 100644
--- a/chrome/browser/notifications/notifications_interactive_uitest.cc
+++ b/chrome/browser/notifications/notifications_interactive_uitest.cc
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/automation/browser_proxy.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_test.h"
@@ -62,7 +61,7 @@
                 "files/notifications/notifications_request_inline.html")));
   WaitUntilTabCount(1);
 
-  int info_bar_count;
+  size_t info_bar_count;
   ASSERT_TRUE(tab->GetInfoBarCount(&info_bar_count));
-  EXPECT_EQ(0, info_bar_count);
+  EXPECT_EQ(0U, info_bar_count);
 }
diff --git a/chrome/browser/notifications/notifications_prefs_cache.cc b/chrome/browser/notifications/notifications_prefs_cache.cc
index b1dbe2e..b7cd5f5 100644
--- a/chrome/browser/notifications/notifications_prefs_cache.cc
+++ b/chrome/browser/notifications/notifications_prefs_cache.cc
@@ -4,11 +4,13 @@
 
 #include "chrome/browser/notifications/notifications_prefs_cache.h"
 
+#include <string>
+
 #include "base/string_util.h"
+#include "base/values.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
 
 NotificationsPrefsCache::NotificationsPrefsCache()
         : default_content_setting_(CONTENT_SETTING_DEFAULT),
diff --git a/chrome/browser/notifications/notifications_prefs_cache_unittest.cc b/chrome/browser/notifications/notifications_prefs_cache_unittest.cc
index d3bbf7d..a6dcea9 100644
--- a/chrome/browser/notifications/notifications_prefs_cache_unittest.cc
+++ b/chrome/browser/notifications/notifications_prefs_cache_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/message_loop.h"
 #include "chrome/browser/browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
 
 TEST(NotificationsPrefsCacheTest, CanCreate) {
   scoped_refptr<NotificationsPrefsCache> cache(new NotificationsPrefsCache());
diff --git a/chrome/browser/ntp_background_util.cc b/chrome/browser/ntp_background_util.cc
index b3926d5..5cd3f95 100644
--- a/chrome/browser/ntp_background_util.cc
+++ b/chrome/browser/ntp_background_util.cc
@@ -6,11 +6,11 @@
 
 #include "base/logging.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "gfx/canvas.h"
-#include "gfx/rect.h"
-#include "gfx/skia_util.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/skia_util.h"
 
 namespace {
 
@@ -57,7 +57,7 @@
 
 // static
 void NtpBackgroundUtil::PaintBackgroundDetachedMode(
-    ThemeProvider* tp, gfx::Canvas* canvas, const gfx::Rect& area,
+    ui::ThemeProvider* tp, gfx::Canvas* canvas, const gfx::Rect& area,
     int tab_contents_height) {
   // Draw the background to match the new tab page.
   canvas->FillRectInt(tp->GetColor(BrowserThemeProvider::COLOR_NTP_BACKGROUND),
diff --git a/chrome/browser/ntp_background_util.h b/chrome/browser/ntp_background_util.h
index a4fa544..a9558ec 100644
--- a/chrome/browser/ntp_background_util.h
+++ b/chrome/browser/ntp_background_util.h
@@ -6,13 +6,15 @@
 #define CHROME_BROWSER_NTP_BACKGROUND_UTIL_H_
 #pragma once
 
-class ThemeProvider;
-
 namespace gfx {
 class Canvas;
 class Rect;
 }
 
+namespace ui {
+class ThemeProvider;
+}
+
 class NtpBackgroundUtil {
  public:
   // Paints the NTP background on |canvas|. |area| is the area of the canvas
@@ -20,7 +22,7 @@
   // aligned images). |tab_contents_height| is necessary for correctly painting
   // bottom-aligned images since then the origin is the bottom of the web page.
   static void PaintBackgroundDetachedMode(
-      ThemeProvider* tp, gfx::Canvas* canvas,
+      ui::ThemeProvider* tp, gfx::Canvas* canvas,
       const gfx::Rect& area, int tab_contents_height);
 
  private:
diff --git a/chrome/browser/omnibox_search_hint.cc b/chrome/browser/omnibox_search_hint.cc
index 4822cc8..eed1a48 100644
--- a/chrome/browser/omnibox_search_hint.cc
+++ b/chrome/browser/omnibox_search_hint.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/omnibox_search_hint.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/metrics/histogram.h"
 #include "base/task.h"
@@ -31,6 +29,8 @@
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // The URLs of search engines for which we want to trigger the infobar.
 const char* kSearchEngineURLs[] = {
@@ -42,73 +42,30 @@
     "http://www.wolframalpha.com/",
 };
 
+
+// HintInfoBar ----------------------------------------------------------------
+
 class HintInfoBar : public ConfirmInfoBarDelegate {
  public:
-  explicit HintInfoBar(OmniboxSearchHint* omnibox_hint)
-      : ConfirmInfoBarDelegate(omnibox_hint->tab()),
-        omnibox_hint_(omnibox_hint),
-        action_taken_(false),
-        should_expire_(false),
-        ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
-    // We want the info-bar to stick-around for few seconds and then be hidden
-    // on the next navigation after that.
-    MessageLoop::current()->PostDelayedTask(FROM_HERE,
-        method_factory_.NewRunnableMethod(&HintInfoBar::Expire),
-        8000);  // 8 seconds.
-  }
-
-  virtual bool ShouldExpire(
-      const NavigationController::LoadCommittedDetails& details) const {
-    return should_expire_;
-  }
-
-  // Overridden from ConfirmInfoBarDelegate:
-  virtual void InfoBarClosed() {
-    if (!action_taken_)
-      UMA_HISTOGRAM_COUNTS("OmniboxSearchHint.Ignored", 1);
-    delete this;
-  }
-
-  virtual void InfoBarDismissed() {
-    action_taken_ = true;
-    UMA_HISTOGRAM_COUNTS("OmniboxSearchHint.Closed", 1);
-    // User closed the infobar, let's not bug him again with this in the future.
-    omnibox_hint_->DisableHint();
-  }
-
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringUTF16(IDS_OMNIBOX_SEARCH_HINT_INFOBAR_TEXT);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-       IDR_INFOBAR_QUESTION_MARK);
-  }
-
-  virtual int GetButtons() const {
-    return BUTTON_OK;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    return l10n_util::GetStringUTF16(
-        IDS_OMNIBOX_SEARCH_HINT_INFOBAR_BUTTON_LABEL);
-  }
-
-  virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
-
-  virtual bool Accept() {
-    action_taken_ = true;
-    UMA_HISTOGRAM_COUNTS("OmniboxSearchHint.ShowMe", 1);
-    omnibox_hint_->DisableHint();
-    omnibox_hint_->ShowEnteringQuery();
-    return true;
-  }
-
-  void Expire() {
-    should_expire_ = true;
-  }
+  explicit HintInfoBar(OmniboxSearchHint* omnibox_hint);
 
  private:
+  virtual ~HintInfoBar();
+
+  void AllowExpiry() { should_expire_ = true; }
+
+  // ConfirmInfoBarDelegate:
+  virtual bool ShouldExpire(
+      const NavigationController::LoadCommittedDetails& details) const;
+  virtual void InfoBarDismissed();
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+
   // The omnibox hint that shows us.
   OmniboxSearchHint* omnibox_hint_;
 
@@ -124,6 +81,74 @@
   DISALLOW_COPY_AND_ASSIGN(HintInfoBar);
 };
 
+HintInfoBar::HintInfoBar(OmniboxSearchHint* omnibox_hint)
+    : ConfirmInfoBarDelegate(omnibox_hint->tab()),
+      omnibox_hint_(omnibox_hint),
+      action_taken_(false),
+      should_expire_(false),
+      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+  // We want the info-bar to stick-around for few seconds and then be hidden
+  // on the next navigation after that.
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(&HintInfoBar::AllowExpiry),
+      8000);  // 8 seconds.
+}
+
+HintInfoBar::~HintInfoBar() {
+}
+
+bool HintInfoBar::ShouldExpire(
+    const NavigationController::LoadCommittedDetails& details) const {
+  return should_expire_;
+}
+
+void HintInfoBar::InfoBarDismissed() {
+  action_taken_ = true;
+  UMA_HISTOGRAM_COUNTS("OmniboxSearchHint.Closed", 1);
+  // User closed the infobar, let's not bug him again with this in the future.
+  omnibox_hint_->DisableHint();
+}
+
+void HintInfoBar::InfoBarClosed() {
+  if (!action_taken_)
+    UMA_HISTOGRAM_COUNTS("OmniboxSearchHint.Ignored", 1);
+  delete this;
+}
+
+SkBitmap* HintInfoBar::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+     IDR_INFOBAR_QUESTION_MARK);
+}
+
+InfoBarDelegate::Type HintInfoBar::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+string16 HintInfoBar::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_OMNIBOX_SEARCH_HINT_INFOBAR_TEXT);
+}
+
+int HintInfoBar::GetButtons() const {
+  return BUTTON_OK;
+}
+
+string16 HintInfoBar::GetButtonLabel(InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(
+      IDS_OMNIBOX_SEARCH_HINT_INFOBAR_BUTTON_LABEL);
+}
+
+bool HintInfoBar::Accept() {
+  action_taken_ = true;
+  UMA_HISTOGRAM_COUNTS("OmniboxSearchHint.ShowMe", 1);
+  omnibox_hint_->DisableHint();
+  omnibox_hint_->ShowEnteringQuery();
+  return true;
+}
+
+
+// OmniboxSearchHint ----------------------------------------------------------
+
 OmniboxSearchHint::OmniboxSearchHint(TabContents* tab) : tab_(tab) {
   NavigationController* controller = &(tab->controller());
   notification_registrar_.Add(this,
@@ -185,8 +210,8 @@
       GetLocationBar();
   AutocompleteEditView*  edit_view = location_bar->location_entry();
   location_bar->FocusLocation(true);
-  edit_view->SetUserText(UTF16ToWideHack(
-      l10n_util::GetStringUTF16(IDS_OMNIBOX_SEARCH_HINT_OMNIBOX_TEXT)));
+  edit_view->SetUserText(
+      l10n_util::GetStringUTF16(IDS_OMNIBOX_SEARCH_HINT_OMNIBOX_TEXT));
   edit_view->SelectAll(false);
   // Entering text in the autocomplete edit view triggers the suggestion popup
   // that we don't want to show in this case.
diff --git a/chrome/browser/page_info_model.cc b/chrome/browser/page_info_model.cc
index 471962e..365852f 100644
--- a/chrome/browser/page_info_model.cc
+++ b/chrome/browser/page_info_model.cc
@@ -6,24 +6,22 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/i18n/time_formatting.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/cert_store.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ssl/ssl_error_info.h"
 #include "chrome/browser/ssl/ssl_manager.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/cert_status_flags.h"
 #include "net/base/ssl_connection_status_flags.h"
 #include "net/base/ssl_cipher_suite_names.h"
 #include "net/base/x509_certificate.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
@@ -142,6 +140,15 @@
     icon_id = ssl.security_style() == SECURITY_STYLE_UNAUTHENTICATED ?
         ICON_STATE_WARNING_MAJOR : ICON_STATE_ERROR;
 
+    const string16 bullet = UTF8ToUTF16("\n • ");
+    std::vector<SSLErrorInfo> errors;
+    SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id(), ssl.cert_status(),
+                                         url, &errors);
+    for (size_t i = 0; i < errors.size(); ++i) {
+      description += bullet;
+      description += errors[i].short_description();
+    }
+
     if (ssl.cert_status() & net::CERT_STATUS_NON_UNIQUE_NAME) {
       description += ASCIIToUTF16("\n\n");
       description += l10n_util::GetStringUTF16(
diff --git a/chrome/browser/page_info_model.h b/chrome/browser/page_info_model.h
index f58556d..9edabc5 100644
--- a/chrome/browser/page_info_model.h
+++ b/chrome/browser/page_info_model.h
@@ -8,12 +8,12 @@
 
 #include <vector>
 
-#include "gfx/native_widget_types.h"
 #include "base/string16.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/native_widget_types.h"
 
 class PrefService;
 class Profile;
diff --git a/chrome/browser/page_info_window.h b/chrome/browser/page_info_window.h
index 117510b..17e28d4 100644
--- a/chrome/browser/page_info_window.h
+++ b/chrome/browser/page_info_window.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "chrome/browser/tab_contents/navigation_entry.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Profile;
 class GURL;
diff --git a/chrome/browser/password_manager/encryptor_password_mac.mm b/chrome/browser/password_manager/encryptor_password_mac.mm
index a92fdcd..5488f4c 100644
--- a/chrome/browser/password_manager/encryptor_password_mac.mm
+++ b/chrome/browser/password_manager/encryptor_password_mac.mm
@@ -6,10 +6,10 @@
 
 #import <Security/Security.h>
 
-#include "app/l10n_util.h"
 #include "chrome/browser/keychain_mac.h"
 #include "chrome/browser/sync/util/crypto_helpers.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc
index 576cd89..265448f 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -169,7 +169,6 @@
   bool date_ok = base::StringToInt64(string_attr_map["date_created"],
                                      &date_created);
   DCHECK(date_ok);
-  DCHECK_NE(date_created, 0);
   form->date_created = base::Time::FromTimeT(date_created);
   form->blacklisted_by_user = uint_attr_map["blacklisted_by_user"];
   form->scheme = static_cast<PasswordForm::Scheme>(uint_attr_map["scheme"]);
@@ -189,7 +188,11 @@
 
     PasswordForm* form = FormFromAttributes(attrs);
     if (form) {
-      form->password_value = UTF8ToUTF16(data->secret);
+      if (data->secret) {
+        form->password_value = UTF8ToUTF16(data->secret);
+      } else {
+        LOG(WARNING) << "Unable to access password from list element!";
+      }
       forms->push_back(form);
     } else {
       LOG(WARNING) << "Could not initialize PasswordForm from attributes!";
@@ -305,6 +308,11 @@
 
 void GKRMethod::AddLogin(const PasswordForm& form) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  time_t date_created = form.date_created.ToTimeT();
+  // If we are asked to save a password with 0 date, use the current time.
+  // We don't want to actually save passwords as though on January 1, 1970.
+  if (!date_created)
+    date_created = time(NULL);
   gnome_keyring_store_password(
       &kGnomeSchema,
       NULL,  // Default keyring.
@@ -322,7 +330,7 @@
       "signon_realm", form.signon_realm.c_str(),
       "ssl_valid", form.ssl_valid,
       "preferred", form.preferred,
-      "date_created", base::Int64ToString(form.date_created.ToTimeT()).c_str(),
+      "date_created", base::Int64ToString(date_created).c_str(),
       "blacklisted_by_user", form.blacklisted_by_user,
       "scheme", form.scheme,
       "application", GNOME_KEYRING_APPLICATION_CHROME,
@@ -521,10 +529,14 @@
   // |info| will be freed after this callback returns, so use it now.
   if (result == GNOME_KEYRING_RESULT_OK) {
     char* secret = gnome_keyring_item_info_get_secret(info);
-    method->password_ = UTF8ToUTF16(secret);
-    // gnome_keyring_item_info_get_secret() allocates and returns a new copy
-    // of the secret, so we have to free it afterward.
-    free(secret);
+    if (secret) {
+      method->password_ = UTF8ToUTF16(secret);
+      // gnome_keyring_item_info_get_secret() allocates and returns a new copy
+      // of the secret, so we have to free it afterward.
+      free(secret);
+    } else {
+      LOG(WARNING) << "Unable to access password from item info!";
+    }
   }
   method->event_.Signal();
 }
@@ -775,7 +787,7 @@
   for (size_t i = 0; i < item_ids.size(); ++i) {
     result = methods[i].WaitResult(&all_forms[i]);
     if (result != GNOME_KEYRING_RESULT_OK) {
-      LOG(ERROR) << "Keyring get item attributes failed:"
+      LOG(ERROR) << "Keyring get item attributes failed: "
                  << gnome_keyring_result_to_message(result);
       // We explicitly do not break out here. We must wait on all the other
       // methods first, and we may have already posted new methods. So, we just
@@ -796,7 +808,7 @@
       continue;
     result = methods[i].WaitResult(&all_forms[i]->password_value);
     if (result != GNOME_KEYRING_RESULT_OK) {
-      LOG(ERROR) << "Keyring get item info failed:"
+      LOG(ERROR) << "Keyring get item info failed: "
                  << gnome_keyring_result_to_message(result);
       delete all_forms[i];
       all_forms[i] = NULL;
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.cc b/chrome/browser/password_manager/native_backend_kwallet_x.cc
index 31dc154..8754cd9 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x.cc
+++ b/chrome/browser/password_manager/native_backend_kwallet_x.cc
@@ -534,7 +534,11 @@
 void NativeBackendKWallet::ReadGURL(const Pickle& pickle, void** iter,
                                     GURL* url) {
   string url_string;
-  pickle.ReadString(iter, &url_string);
+  if (!pickle.ReadString(iter, &url_string)) {
+    LOG(ERROR) << "Failed to read url string";
+    *url = GURL();
+    return;
+  }
   *url = GURL(url_string);
 }
 
diff --git a/chrome/browser/password_manager/password_manager.cc b/chrome/browser/password_manager/password_manager.cc
index a96492a..a847958 100644
--- a/chrome/browser/password_manager/password_manager.cc
+++ b/chrome/browser/password_manager/password_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
 #include "chrome/browser/password_manager/password_manager_delegate.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_registrar.h"
+#include "chrome/common/autofill_messages.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages_params.h"
 #include "grit/generated_resources.h"
@@ -158,7 +158,19 @@
     ProvisionallySavePassword(params.password_form);
 }
 
-void PasswordManager::PasswordFormsFound(
+bool PasswordManager::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(PasswordManager, message)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_PasswordFormsFound,
+                        OnPasswordFormsFound)
+    IPC_MESSAGE_HANDLER(AutoFillHostMsg_PasswordFormsVisible,
+                        OnPasswordFormsVisible)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void PasswordManager::OnPasswordFormsFound(
     const std::vector<PasswordForm>& forms) {
   if (!delegate_->GetProfileForPasswordManager())
     return;
@@ -179,7 +191,7 @@
   }
 }
 
-void PasswordManager::PasswordFormsVisible(
+void PasswordManager::OnPasswordFormsVisible(
     const std::vector<PasswordForm>& visible_forms) {
   if (!provisional_save_manager_.get())
     return;
diff --git a/chrome/browser/password_manager/password_manager.h b/chrome/browser/password_manager/password_manager.h
index 23f8ca3..547f1f3 100644
--- a/chrome/browser/password_manager/password_manager.h
+++ b/chrome/browser/password_manager/password_manager.h
@@ -10,7 +10,7 @@
 #include "base/stl_util-inl.h"
 #include "chrome/browser/password_manager/password_form_manager.h"
 #include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/tab_contents/web_navigation_observer.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
 #include "chrome/browser/ui/login/login_model.h"
 #include "webkit/glue/password_form.h"
 #include "webkit/glue/password_form_dom_manager.h"
@@ -25,7 +25,7 @@
 // database through the WebDataService. The PasswordManager is a LoginModel
 // for purposes of supporting HTTP authentication dialogs.
 class PasswordManager : public LoginModel,
-                        public WebNavigationObserver {
+                        public TabContentsObserver {
  public:
   static void RegisterUserPrefs(PrefService* prefs);
 
@@ -48,14 +48,16 @@
   // of 2 (see SavePassword).
   void ProvisionallySavePassword(webkit_glue::PasswordForm form);
 
-  // WebNavigationObserver overrides.
+  // TabContentsObserver overrides.
   virtual void DidStopLoading();
   virtual void DidNavigateAnyFramePostCommit(
       const NavigationController::LoadCommittedDetails& details,
       const ViewHostMsg_FrameNavigate_Params& params);
-  virtual void PasswordFormsFound(
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+  void OnPasswordFormsFound(
       const std::vector<webkit_glue::PasswordForm>& forms);
-  virtual void PasswordFormsVisible(
+  void OnPasswordFormsVisible(
       const std::vector<webkit_glue::PasswordForm>& visible_forms);
 
  private:
diff --git a/chrome/browser/password_manager/password_manager_unittest.cc b/chrome/browser/password_manager/password_manager_unittest.cc
index 78eae4a..d0b7f4f 100644
--- a/chrome/browser/password_manager/password_manager_unittest.cc
+++ b/chrome/browser/password_manager/password_manager_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -9,7 +11,6 @@
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/browser/password_manager/password_manager_delegate.h"
 #include "chrome/browser/password_manager/password_store.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -136,8 +137,8 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
-  manager()->PasswordFormsFound(observed);  // The initial load.
-  manager()->PasswordFormsVisible(observed);  // The initial layout.
+  manager()->OnPasswordFormsFound(observed);  // The initial load.
+  manager()->OnPasswordFormsVisible(observed);  // The initial layout.
 
   // And the form submit contract is to call ProvisionallySavePassword.
   manager()->ProvisionallySavePassword(form);
@@ -171,8 +172,8 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
-  manager()->PasswordFormsFound(observed);  // The initial load.
-  manager()->PasswordFormsVisible(observed);  // The initial layout.
+  manager()->OnPasswordFormsFound(observed);  // The initial load.
+  manager()->OnPasswordFormsVisible(observed);  // The initial layout.
   manager()->ProvisionallySavePassword(form);
 
   // We still expect an add, since we didn't have a good match.
@@ -195,8 +196,8 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
-  manager()->PasswordFormsFound(observed);  // The initial load.
-  manager()->PasswordFormsVisible(observed);  // The initial layout.
+  manager()->OnPasswordFormsFound(observed);  // The initial load.
+  manager()->OnPasswordFormsVisible(observed);  // The initial layout.
 
   manager()->DidNavigate();
 
@@ -212,14 +213,14 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
-  manager()->PasswordFormsFound(observed);  // The initial load.
-  manager()->PasswordFormsVisible(observed);  // The initial layout.
+  manager()->OnPasswordFormsFound(observed);  // The initial load.
+  manager()->OnPasswordFormsVisible(observed);  // The initial layout.
 
   manager()->ProvisionallySavePassword(form);
 
   // The form reappears, and is visible in the layout:
-  manager()->PasswordFormsFound(observed);
-  manager()->PasswordFormsVisible(observed);
+  manager()->OnPasswordFormsFound(observed);
+  manager()->OnPasswordFormsVisible(observed);
 
   // No expected calls to the PasswordStore...
   manager()->DidStopLoading();
@@ -235,13 +236,13 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
-  manager()->PasswordFormsFound(observed);  // The initial load.
-  manager()->PasswordFormsVisible(observed);  // The initial layout.
+  manager()->OnPasswordFormsFound(observed);  // The initial load.
+  manager()->OnPasswordFormsVisible(observed);  // The initial layout.
 
   manager()->ProvisionallySavePassword(form);
 
   // The form reappears, but is not visible in the layout:
-  manager()->PasswordFormsFound(observed);
+  manager()->OnPasswordFormsFound(observed);
   // No call to PasswordFormsVisible.
 
   // Expect info bar to appear:
@@ -268,7 +269,7 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
-  manager()->PasswordFormsFound(observed);  // The initial load.
+  manager()->OnPasswordFormsFound(observed);  // The initial load.
   // PasswordFormsVisible is not called.
 
   manager()->DidStopLoading();
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc
index 92d536d..0248066 100644
--- a/chrome/browser/password_manager/password_store_mac_unittest.cc
+++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -852,7 +852,7 @@
   ASSERT_EQ(3U, merged_forms.size());
   EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[0]->password_value);
   EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[1]->password_value);
-  EXPECT_EQ(true, merged_forms[2]->blacklisted_by_user);
+  EXPECT_TRUE(merged_forms[2]->blacklisted_by_user);
 
   STLDeleteElements(&database_forms);
   STLDeleteElements(&merged_forms);
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc
index 9c692b6..c965d65 100644
--- a/chrome/browser/password_manager/password_store_win_unittest.cc
+++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -144,7 +144,8 @@
       arg)->GetValue().empty();
 }
 
-TEST_F(PasswordStoreWinTest, ConvertIE7Login) {
+// Hangs flakily, http://crbug.com/71385.
+TEST_F(PasswordStoreWinTest, DISABLED_ConvertIE7Login) {
   IE7PasswordInfo password_info;
   ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
                                     base::Time::FromDoubleT(1),
diff --git a/chrome/browser/password_manager_delegate_impl.cc b/chrome/browser/password_manager_delegate_impl.cc
index 466ee34..7a96746 100644
--- a/chrome/browser/password_manager_delegate_impl.cc
+++ b/chrome/browser/password_manager_delegate_impl.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/password_manager_delegate_impl.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/metrics/histogram.h"
 #include "base/singleton.h"
 #include "chrome/browser/password_manager/password_form_manager.h"
@@ -13,9 +11,12 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/autofill_messages.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/glue/password_form.h"
 
 // After a successful *new* login attempt, we take the PasswordFormManager in
@@ -27,81 +28,94 @@
 class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   SavePasswordInfoBarDelegate(TabContents* tab_contents,
-                              PasswordFormManager* form_to_save)
-      : ConfirmInfoBarDelegate(tab_contents),
-        form_to_save_(form_to_save),
-        infobar_response_(NO_RESPONSE) {}
-
-  virtual ~SavePasswordInfoBarDelegate() {}
-
-  // Begin ConfirmInfoBarDelegate implementation.
-  virtual void InfoBarClosed() {
-    UMA_HISTOGRAM_ENUMERATION("PasswordManager.InfoBarResponse",
-                              infobar_response_, NUM_RESPONSE_TYPES);
-    delete this;
-  }
-
-  virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
-
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-        IDR_INFOBAR_SAVE_PASSWORD);
-  }
-
-  virtual int GetButtons() const {
-    return BUTTON_OK | BUTTON_CANCEL;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    if (button == BUTTON_OK)
-      return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON);
-    if (button == BUTTON_CANCEL)
-      return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON);
-    NOTREACHED();
-    return string16();
-  }
-
-  virtual bool Accept() {
-    DCHECK(form_to_save_.get());
-    form_to_save_->Save();
-    infobar_response_ = REMEMBER_PASSWORD;
-    return true;
-  }
-
-  virtual bool Cancel() {
-    DCHECK(form_to_save_.get());
-    form_to_save_->PermanentlyBlacklist();
-    infobar_response_ = DONT_REMEMBER_PASSWORD;
-    return true;
-  }
-  // End ConfirmInfoBarDelegate implementation.
+                              PasswordFormManager* form_to_save);
 
  private:
-  // The PasswordFormManager managing the form we're asking the user about,
-  // and should update as per her decision.
-  scoped_ptr<PasswordFormManager> form_to_save_;
-
-  // Used to track the results we get from the info bar.
   enum ResponseType {
     NO_RESPONSE = 0,
     REMEMBER_PASSWORD,
     DONT_REMEMBER_PASSWORD,
     NUM_RESPONSE_TYPES,
   };
+
+  virtual ~SavePasswordInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+
+  // The PasswordFormManager managing the form we're asking the user about,
+  // and should update as per her decision.
+  scoped_ptr<PasswordFormManager> form_to_save_;
+
+  // Used to track the results we get from the info bar.
   ResponseType infobar_response_;
 
   DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate);
 };
 
-//----------------------------------------------------------------------------
+SavePasswordInfoBarDelegate::SavePasswordInfoBarDelegate(
+    TabContents* tab_contents,
+    PasswordFormManager* form_to_save)
+    : ConfirmInfoBarDelegate(tab_contents),
+      form_to_save_(form_to_save),
+      infobar_response_(NO_RESPONSE) {
+}
+
+SavePasswordInfoBarDelegate::~SavePasswordInfoBarDelegate() {
+}
+
+void SavePasswordInfoBarDelegate::InfoBarClosed() {
+  UMA_HISTOGRAM_ENUMERATION("PasswordManager.InfoBarResponse",
+                            infobar_response_, NUM_RESPONSE_TYPES);
+  delete this;
+}
+
+SkBitmap* SavePasswordInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_SAVE_PASSWORD);
+}
+
+InfoBarDelegate::Type SavePasswordInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+string16 SavePasswordInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
+}
+
+string16 SavePasswordInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_PASSWORD_MANAGER_SAVE_BUTTON : IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON);
+}
+
+bool SavePasswordInfoBarDelegate::Accept() {
+  DCHECK(form_to_save_.get());
+  form_to_save_->Save();
+  infobar_response_ = REMEMBER_PASSWORD;
+  return true;
+}
+
+bool SavePasswordInfoBarDelegate::Cancel() {
+  DCHECK(form_to_save_.get());
+  form_to_save_->PermanentlyBlacklist();
+  infobar_response_ = DONT_REMEMBER_PASSWORD;
+  return true;
+}
+
+
+// PasswordManagerDelegateImpl ------------------------------------------------
 
 void PasswordManagerDelegateImpl::FillPasswordForm(
     const webkit_glue::PasswordFormFillData& form_data) {
-  tab_contents_->render_view_host()->FillPasswordForm(form_data);
+  tab_contents_->render_view_host()->Send(new AutoFillMsg_FillPasswordForm(
+      tab_contents_->render_view_host()->routing_id(), form_data));
 }
 
 void PasswordManagerDelegateImpl::AddSavePasswordInfoBar(
diff --git a/chrome/browser/pdf_unsupported_feature.cc b/chrome/browser/pdf_unsupported_feature.cc
new file mode 100644
index 0000000..bd598af
--- /dev/null
+++ b/chrome/browser/pdf_unsupported_feature.cc
@@ -0,0 +1,391 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/pdf_unsupported_feature.h"
+
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/plugin_service.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/interstitial_page.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/pepper_plugin_registry.h"
+#include "chrome/common/pref_names.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "webkit/plugins/npapi/plugin_group.h"
+#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/npapi/webplugininfo.h"
+
+using webkit::npapi::PluginGroup;
+using webkit::npapi::PluginList;
+using webkit::npapi::WebPluginInfo;
+
+// Only launch Adobe Reader X or later.
+static const uint16 kMinReaderVersionToUse = 10;
+
+namespace {
+
+// The info bar delegate used to ask the user if they want to use Adobe Reader
+// by default.  We want the infobar to have [No][Yes], so we swap the text on
+// the buttons, and the meaning of the delegate callbacks.
+class PDFEnableAdobeReaderConfirmInfoBarDelegate
+    : public ConfirmInfoBarDelegate {
+ public:
+  PDFEnableAdobeReaderConfirmInfoBarDelegate(
+      TabContents* tab_contents)
+      : ConfirmInfoBarDelegate(tab_contents),
+        tab_contents_(tab_contents) {
+    UserMetrics::RecordAction(
+        UserMetricsAction("PDF_EnableReaderInfoBarShown"));
+  }
+
+  // ConfirmInfoBarDelegate
+  virtual void InfoBarClosed() {
+    delete this;
+  }
+
+  virtual void InfoBarDismissed() {
+    OnNo();
+  }
+
+  virtual Type GetInfoBarType() const {
+    return PAGE_ACTION_TYPE;
+  }
+
+  virtual bool Accept() {
+    tab_contents_->profile()->GetPrefs()->SetBoolean(
+        prefs::kPluginsShowSetReaderDefaultInfobar, false);
+    return OnNo();
+  }
+
+  virtual bool Cancel() {
+    return OnYes();
+  }
+
+  virtual int GetButtons() const {
+    return BUTTON_OK | BUTTON_CANCEL;
+  }
+
+  virtual string16 GetButtonLabel(InfoBarButton button) const {
+    switch (button) {
+      case BUTTON_OK:
+        return l10n_util::GetStringUTF16(
+            IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
+      case BUTTON_CANCEL:
+        return l10n_util::GetStringUTF16(
+            IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
+      default:
+        // All buttons are labeled above.
+        NOTREACHED() << "Bad button id " << button;
+        return string16();
+    }
+  }
+
+  virtual string16 GetMessageText() const {
+    return l10n_util::GetStringUTF16(
+        IDS_PDF_INFOBAR_QUESTION_ALWAYS_USE_READER);
+  }
+
+ private:
+  bool OnYes() {
+    UserMetrics::RecordAction(
+        UserMetricsAction("PDF_EnableReaderInfoBarOK"));
+    webkit::npapi::PluginList::Singleton()->EnableGroup(
+        false, ASCIIToUTF16(PepperPluginRegistry::kPDFPluginName));
+    webkit::npapi::PluginList::Singleton()->EnableGroup(
+        true, ASCIIToUTF16(webkit::npapi::PluginGroup::kAdobeReaderGroupName));
+    return true;
+  }
+
+  bool OnNo() {
+    UserMetrics::RecordAction(
+        UserMetricsAction("PDF_EnableReaderInfoBarCancel"));
+    return true;
+  }
+
+  TabContents* tab_contents_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PDFEnableAdobeReaderConfirmInfoBarDelegate);
+};
+
+// Launch the url to get the latest Adbobe Reader installer.
+void OpenReaderUpdateURL(TabContents* tab) {
+  tab->OpenURL(GURL(PluginGroup::kAdobeReaderUpdateURL), GURL(), CURRENT_TAB,
+               PageTransition::LINK);
+}
+
+// Opens the PDF using Adobe Reader.
+void OpenUsingReader(TabContents* tab,
+                     const WebPluginInfo& reader_plugin,
+                     InfoBarDelegate* old_delegate,
+                     InfoBarDelegate* new_delegate) {
+  PluginService::OverriddenPlugin plugin;
+  plugin.render_process_id = tab->GetRenderProcessHost()->id();
+  plugin.render_view_id = tab->render_view_host()->routing_id();
+  plugin.url = tab->GetURL();
+  plugin.plugin = reader_plugin;
+  // The plugin is disabled, so enable it to get around the renderer check.
+  // Also give it a new version so that the renderer doesn't show the blocked
+  // plugin UI if it's vulnerable, since we already went through the
+  // interstitial.
+  plugin.plugin.enabled = WebPluginInfo::USER_ENABLED;
+  plugin.plugin.version = ASCIIToUTF16("11.0.0.0");
+
+  PluginService::GetInstance()->OverridePluginForTab(plugin);
+  tab->render_view_host()->ReloadFrame();
+
+  if (new_delegate) {
+    if (old_delegate) {
+      tab->ReplaceInfoBar(old_delegate, new_delegate);
+    } else {
+      tab->AddInfoBar(new_delegate);
+    }
+  }
+}
+
+// An interstitial to be used when the user chooses to open a PDF using Adobe
+// Reader, but it is out of date.
+class PDFUnsupportedFeatureInterstitial : public InterstitialPage {
+ public:
+  PDFUnsupportedFeatureInterstitial(
+      TabContents* tab,
+      const WebPluginInfo& reader_webplugininfo)
+      : InterstitialPage(tab, false, tab->GetURL()),
+        reader_webplugininfo_(reader_webplugininfo) {
+    UserMetrics::RecordAction(UserMetricsAction("PDF_ReaderInterstitialShown"));
+  }
+
+ protected:
+  // InterstitialPage implementation.
+  virtual std::string GetHTMLContents() {
+    DictionaryValue strings;
+    strings.SetString(
+        "title",
+        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE));
+    strings.SetString(
+        "headLine",
+        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_BODY));
+    strings.SetString(
+        "update",
+        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_UPDATE));
+    strings.SetString(
+        "open_with_reader",
+        l10n_util::GetStringUTF16(
+            IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_PROCEED));
+    strings.SetString(
+        "ok",
+        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_OK));
+    strings.SetString(
+        "cancel",
+        l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_CANCEL));
+
+    base::StringPiece html(ResourceBundle::GetSharedInstance().
+        GetRawDataResource(IDR_READER_OUT_OF_DATE_HTML));
+
+    return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
+  }
+
+  virtual void CommandReceived(const std::string& command) {
+    if (command == "0") {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_ReaderInterstitialCancel"));
+      DontProceed();
+      return;
+    }
+
+    if (command == "1") {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_ReaderInterstitialUpdate"));
+      OpenReaderUpdateURL(tab());
+    } else if (command == "2") {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_ReaderInterstitialIgnore"));
+      OpenUsingReader(tab(), reader_webplugininfo_, NULL, NULL);
+    } else {
+      NOTREACHED();
+    }
+    Proceed();
+  }
+
+ private:
+  WebPluginInfo reader_webplugininfo_;
+
+  DISALLOW_COPY_AND_ASSIGN(PDFUnsupportedFeatureInterstitial);
+};
+
+// The info bar delegate used to inform the user that we don't support a feature
+// in the PDF.  See the comment about how we swap buttons for
+// PDFEnableAdobeReaderConfirmInfoBarDelegate.
+class PDFUnsupportedFeatureConfirmInfoBarDelegate
+    : public ConfirmInfoBarDelegate {
+ public:
+  PDFUnsupportedFeatureConfirmInfoBarDelegate(
+      TabContents* tab_contents,
+      PluginGroup* reader_group)  // NULL if Adobe Reader isn't installed.
+      : ConfirmInfoBarDelegate(tab_contents),
+        tab_contents_(tab_contents),
+        reader_installed_(!!reader_group),
+        reader_vulnerable_(false) {
+    if (reader_installed_) {
+      UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarShown"));
+      std::vector<WebPluginInfo> plugins = reader_group->web_plugin_infos();
+      DCHECK_EQ(plugins.size(), 1u);
+      reader_webplugininfo_ = plugins[0];
+
+      reader_vulnerable_ = reader_group->IsVulnerable();
+      if (!reader_vulnerable_) {
+        scoped_ptr<Version> version(PluginGroup::CreateVersionFromString(
+            reader_webplugininfo_.version));
+        if (version.get()) {
+          if (version->components()[0] < kMinReaderVersionToUse)
+            reader_vulnerable_ = true;
+        }
+      }
+    } else {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_InstallReaderInfoBarShown"));
+    }
+  }
+
+  // ConfirmInfoBarDelegate
+  virtual void InfoBarClosed() {
+    delete this;
+  }
+
+  virtual void InfoBarDismissed() {
+    OnNo();
+  }
+
+  virtual Type GetInfoBarType() const {
+    return PAGE_ACTION_TYPE;
+  }
+
+  virtual bool Accept() {
+    return OnNo();
+  }
+
+  virtual bool Cancel() {
+    return OnYes();
+  }
+
+  virtual int GetButtons() const {
+    return BUTTON_OK | BUTTON_CANCEL;
+  }
+
+  virtual string16 GetButtonLabel(InfoBarButton button) const {
+    switch (button) {
+      case BUTTON_OK:
+        return l10n_util::GetStringUTF16(
+            IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
+      case BUTTON_CANCEL:
+        return l10n_util::GetStringUTF16(
+            IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
+      default:
+        // All buttons are labeled above.
+        NOTREACHED() << "Bad button id " << button;
+        return string16();
+    }
+  }
+
+  virtual string16 GetMessageText() const {
+    return l10n_util::GetStringUTF16(reader_installed_ ?
+        IDS_PDF_INFOBAR_QUESTION_READER_INSTALLED :
+        IDS_PDF_INFOBAR_QUESTION_READER_NOT_INSTALLED);
+  }
+
+ private:
+  bool OnYes() {
+   if (!reader_installed_) {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_InstallReaderInfoBarOK"));
+      OpenReaderUpdateURL(tab_contents_);
+      return true;
+    }
+
+    UserMetrics::RecordAction(
+        UserMetricsAction("PDF_UseReaderInfoBarOK"));
+
+    if (reader_vulnerable_) {
+      PDFUnsupportedFeatureInterstitial* interstitial = new
+          PDFUnsupportedFeatureInterstitial(
+              tab_contents_, reader_webplugininfo_);
+      interstitial->Show();
+      return true;
+    }
+
+    InfoBarDelegate* bar = NULL;
+    // Don't show the enable Reader by default info bar for now.
+    /*
+    if (tab_contents_->profile()->GetPrefs()->GetBoolean(
+            prefs::kPluginsShowSetReaderDefaultInfobar)) {
+      bar = new PDFEnableAdobeReaderConfirmInfoBarDelegate(tab_contents_);
+    }
+    */
+
+    if (bar) {
+      OpenUsingReader(tab_contents_, reader_webplugininfo_, this, bar);
+      return false;
+    } else {
+      OpenUsingReader(tab_contents_, reader_webplugininfo_, NULL, NULL);
+      return true;
+    }
+  }
+
+  bool OnNo() {
+    if (reader_installed_) {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_UseReaderInfoBarCancel"));
+    } else {
+      UserMetrics::RecordAction(
+          UserMetricsAction("PDF_InstallReaderInfoBarCancel"));
+    }
+    return true;
+  }
+
+  TabContents* tab_contents_;
+  bool reader_installed_;
+  bool reader_vulnerable_;
+  WebPluginInfo reader_webplugininfo_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeatureConfirmInfoBarDelegate);
+};
+
+}  // namespace
+
+void PDFHasUnsupportedFeature(TabContents* tab) {
+#if !defined(OS_WIN)
+  // Only works for Windows for now.  For Mac, we'll have to launch the file
+  // externally since Adobe Reader doesn't work inside Chrome.
+  return;
+#endif
+  string16 reader_group_name(ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));
+
+  // If the Reader plugin is disabled by policy, don't prompt them.
+  if (PluginGroup::IsPluginNameDisabledByPolicy(reader_group_name))
+    return;
+
+  PluginGroup* reader_group = NULL;
+  std::vector<PluginGroup> plugin_groups;
+  PluginList::Singleton()->GetPluginGroups(
+      false, &plugin_groups);
+  for (size_t i = 0; i < plugin_groups.size(); ++i) {
+    if (plugin_groups[i].GetGroupName() == reader_group_name) {
+      reader_group = &plugin_groups[i];
+      break;
+    }
+  }
+
+  tab->AddInfoBar(new PDFUnsupportedFeatureConfirmInfoBarDelegate(
+      tab, reader_group));
+}
diff --git a/chrome/browser/pdf_unsupported_feature.h b/chrome/browser/pdf_unsupported_feature.h
new file mode 100644
index 0000000..e6e4f64
--- /dev/null
+++ b/chrome/browser/pdf_unsupported_feature.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PDF_UNSUPPORTED_FEATURE_H_
+#define CHROME_BROWSER_PDF_UNSUPPORTED_FEATURE_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+class TabContents;
+
+// Call this when a tab encounters a PDF that has features which our internal
+// viewer doesn't support.  Will take care of puting up an infobar to inform the
+// user and launch Reader if they choose.  If Reader is out of date, it will put
+// up an interstitial.
+void PDFHasUnsupportedFeature(TabContents* tab);
+
+#endif  // CHROME_BROWSER_PDF_UNSUPPORTED_FEATURE_H_
diff --git a/chrome/browser/platform_util.h b/chrome/browser/platform_util.h
index 3738aa8..37d5171 100644
--- a/chrome/browser/platform_util.h
+++ b/chrome/browser/platform_util.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/string16.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class FilePath;
 class GURL;
diff --git a/chrome/browser/platform_util_chromeos.cc b/chrome/browser/platform_util_chromeos.cc
index f059385..cbca7c8 100644
--- a/chrome/browser/platform_util_chromeos.cc
+++ b/chrome/browser/platform_util_chromeos.cc
@@ -6,7 +6,6 @@
 
 #include <gtk/gtk.h>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/process_util.h"
 #include "base/task.h"
@@ -19,6 +18,7 @@
 #include "chrome/common/process_watcher.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 class Profile;
 
diff --git a/chrome/browser/platform_util_common_linux.cc b/chrome/browser/platform_util_common_linux.cc
index 062a2b8..faf8a9f 100644
--- a/chrome/browser/platform_util_common_linux.cc
+++ b/chrome/browser/platform_util_common_linux.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,10 +11,10 @@
 #include "base/process_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/process_watcher.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace {
 
diff --git a/chrome/browser/platform_util_mac.mm b/chrome/browser/platform_util_mac.mm
index 5306598..abc72ab 100644
--- a/chrome/browser/platform_util_mac.mm
+++ b/chrome/browser/platform_util_mac.mm
@@ -8,14 +8,14 @@
 #import <Cocoa/Cocoa.h>
 #import <CoreServices/CoreServices.h>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/file_path.h"
 #include "base/logging.h"
 #include "base/mac/scoped_aedesc.h"
 #include "base/sys_string_conversions.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace platform_util {
 
diff --git a/chrome/browser/platform_util_win.cc b/chrome/browser/platform_util_win.cc
index f03f653..1bd8dbe 100644
--- a/chrome/browser/platform_util_win.cc
+++ b/chrome/browser/platform_util_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,6 @@
 
 #include "app/win/scoped_co_mem.h"
 #include "app/win/shell.h"
-#include "app/win/win_util.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
@@ -23,8 +22,9 @@
 #include "chrome/installer/util/google_update_settings.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/util/install_util.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
+#include "ui/base/message_box_win.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace platform_util {
 
@@ -52,7 +52,7 @@
     // the process.
     HMODULE shell32_base = GetModuleHandle(L"shell32.dll");
     if (!shell32_base) {
-      NOTREACHED();
+      NOTREACHED() << " " << __FUNCTION__ << "(): Can't open shell32.dll";
       return;
     }
     open_folder_and_select_itemsPtr =
@@ -60,7 +60,7 @@
             (GetProcAddress(shell32_base, "SHOpenFolderAndSelectItems"));
   }
   if (!open_folder_and_select_itemsPtr) {
-    ShellExecute(NULL, _T("open"), dir.value().c_str(), NULL, NULL, SW_SHOW);
+    ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
     return;
   }
 
@@ -86,8 +86,30 @@
   const ITEMIDLIST* highlight[] = {
     {file_item},
   };
-  (*open_folder_and_select_itemsPtr)(dir_item, arraysize(highlight),
-                                     highlight, NULL);
+
+  hr = (*open_folder_and_select_itemsPtr)(dir_item, arraysize(highlight),
+                                          highlight, NULL);
+
+  if (FAILED(hr)) {
+    // On some systems, the above call mysteriously fails with "file not
+    // found" even though the file is there.  In these cases, ShellExecute()
+    // seems to work as a fallback (although it won't select the file).
+    if (hr == ERROR_FILE_NOT_FOUND) {
+      ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
+    } else {
+      LPTSTR message = NULL;
+      DWORD message_length = FormatMessage(
+          FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+          0, hr, 0, reinterpret_cast<LPTSTR>(&message), 0, NULL);
+      LOG(WARNING) << " " << __FUNCTION__
+                   << "(): Can't open full_path = \""
+                   << full_path.value() << "\""
+                   << " hr = " << hr
+                   << " " << reinterpret_cast<LPTSTR>(&message);
+      if (message)
+        LocalFree(message);
+    }
+  }
 }
 
 void OpenItem(const FilePath& full_path) {
@@ -162,13 +184,13 @@
 void SimpleErrorBox(gfx::NativeWindow parent,
                     const string16& title,
                     const string16& message) {
-  app::win::MessageBox(parent, message, title, MB_OK | MB_SETFOREGROUND);
+  ui::MessageBox(parent, message, title, MB_OK | MB_SETFOREGROUND);
 }
 
 bool SimpleYesNoBox(gfx::NativeWindow parent,
                     const string16& title,
                     const string16& message) {
-  return app::win::MessageBox(parent, message.c_str(), title.c_str(),
+  return ui::MessageBox(parent, message.c_str(), title.c_str(),
       MB_YESNO | MB_ICONWARNING | MB_SETFOREGROUND) == IDYES;
 }
 
diff --git a/chrome/browser/plugin_carbon_interpose_mac.cc b/chrome/browser/plugin_carbon_interpose_mac.cc
index 2b60d66..56d840f 100644
--- a/chrome/browser/plugin_carbon_interpose_mac.cc
+++ b/chrome/browser/plugin_carbon_interpose_mac.cc
@@ -7,7 +7,7 @@
 #include <Carbon/Carbon.h>
 
 #include "chrome/plugin/plugin_interpose_util_mac.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 #include "webkit/plugins/npapi/carbon_plugin_window_tracker_mac.h"
 
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
diff --git a/chrome/browser/plugin_data_remover.cc b/chrome/browser/plugin_data_remover.cc
index 2baf0d0..a32e12b 100644
--- a/chrome/browser/plugin_data_remover.cc
+++ b/chrome/browser/plugin_data_remover.cc
@@ -1,14 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/plugin_data_remover.h"
 
+#include "base/command_line.h"
 #include "base/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
 #include "base/version.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/plugin_service.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/plugin_messages.h"
 #include "webkit/plugins/npapi/plugin_group.h"
 #include "webkit/plugins/npapi/plugin_list.h"
@@ -18,15 +20,18 @@
 #endif
 
 namespace {
-const char* g_flash_mime_type = "application/x-shockwave-flash";
+const char* kFlashMimeType = "application/x-shockwave-flash";
 // TODO(bauerb): Update minimum required Flash version as soon as there is one
 // implementing the API.
-const char* g_min_flash_version = "100";
-const int64 g_timeout_ms = 10000;
+const char* kMinFlashVersion = "100";
+const int64 kRemovalTimeoutMs = 10000;
+const uint64 kClearAllData = 0;
 }  // namespace
 
 PluginDataRemover::PluginDataRemover()
-    : is_removing_(false),
+    : mime_type_(kFlashMimeType),
+      is_removing_(false),
+      event_(new base::WaitableEvent(true, false)),
       channel_(NULL) { }
 
 PluginDataRemover::~PluginDataRemover() {
@@ -35,25 +40,37 @@
     BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
 }
 
-void PluginDataRemover::StartRemoving(base::Time begin_time, Task* done_task) {
-  DCHECK(!done_task_.get());
+base::WaitableEvent* PluginDataRemover::StartRemoving(
+    const base::Time& begin_time) {
   DCHECK(!is_removing_);
   remove_start_time_ = base::Time::Now();
   begin_time_ = begin_time;
 
-  message_loop_ = base::MessageLoopProxy::CreateForCurrentThread();
-  done_task_.reset(done_task);
   is_removing_ = true;
 
   AddRef();
-  PluginService::GetInstance()->OpenChannelToPlugin(
-      GURL(), g_flash_mime_type, this);
+  PluginService::GetInstance()->OpenChannelToNpapiPlugin(
+      0, 0, GURL(), mime_type_, this);
 
   BrowserThread::PostDelayedTask(
       BrowserThread::IO,
       FROM_HERE,
       NewRunnableMethod(this, &PluginDataRemover::OnTimeout),
-      g_timeout_ms);
+      kRemovalTimeoutMs);
+
+  return event_.get();
+}
+
+void PluginDataRemover::Wait() {
+  base::Time start_time(base::Time::Now());
+  bool result = true;
+  if (is_removing_)
+    result = event_->Wait();
+  UMA_HISTOGRAM_TIMES("ClearPluginData.wait_at_shutdown",
+                      base::Time::Now() - start_time);
+  UMA_HISTOGRAM_TIMES("ClearPluginData.time_at_shutdown",
+                      base::Time::Now() - remove_start_time_);
+  DCHECK(result) << "Error waiting for plugin process";
 }
 
 int PluginDataRemover::ID() {
@@ -84,34 +101,36 @@
   DCHECK(!channel_);
   channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this);
   if (!channel_->Connect()) {
-    LOG(DFATAL) << "Couldn't connect to plugin";
+    NOTREACHED() << "Couldn't connect to plugin";
     SignalDone();
     return;
   }
 
   if (!channel_->Send(
-          new PluginMsg_ClearSiteData(0, std::string(), begin_time_))) {
-    LOG(DFATAL) << "Couldn't send ClearSiteData message";
+          new PluginMsg_ClearSiteData(std::string(),
+                                      kClearAllData,
+                                      begin_time_))) {
+    NOTREACHED() << "Couldn't send ClearSiteData message";
     SignalDone();
+    return;
   }
 }
 
 void PluginDataRemover::OnError() {
-  NOTREACHED() << "Couldn't open plugin channel";
+  LOG(DFATAL) << "Couldn't open plugin channel";
   SignalDone();
   Release();
 }
 
 void PluginDataRemover::OnClearSiteDataResult(bool success) {
-  if (!success)
-    LOG(DFATAL) << "ClearSiteData returned error";
+  LOG_IF(DFATAL, !success) << "ClearSiteData returned error";
   UMA_HISTOGRAM_TIMES("ClearPluginData.time",
                       base::Time::Now() - remove_start_time_);
   SignalDone();
 }
 
 void PluginDataRemover::OnTimeout() {
-  NOTREACHED() << "Timed out";
+  LOG_IF(DFATAL, is_removing_) << "Timed out";
   SignalDone();
 }
 
@@ -126,8 +145,10 @@
 }
 
 void PluginDataRemover::OnChannelError() {
-  LOG(DFATAL) << "Channel error";
-  SignalDone();
+  if (is_removing_) {
+    NOTREACHED() << "Channel error";
+    SignalDone();
+  }
 }
 
 void PluginDataRemover::SignalDone() {
@@ -135,10 +156,7 @@
   if (!is_removing_)
     return;
   is_removing_ = false;
-  if (done_task_.get()) {
-    message_loop_->PostTask(FROM_HERE, done_task_.release());
-    message_loop_ = NULL;
-  }
+  event_->Signal();
 }
 
 // static
@@ -147,17 +165,18 @@
   bool allow_wildcard = false;
   webkit::npapi::WebPluginInfo plugin;
   std::string mime_type;
-  if (!webkit::npapi::PluginList::Singleton()->GetPluginInfo(GURL(),
-                                                             g_flash_mime_type,
-                                                             allow_wildcard,
-                                                             &plugin,
-                                                             &mime_type))
+  if (!webkit::npapi::PluginList::Singleton()->GetPluginInfo(
+          GURL(), kFlashMimeType, allow_wildcard, &plugin, &mime_type)) {
     return false;
+  }
   scoped_ptr<Version> version(
       webkit::npapi::PluginGroup::CreateVersionFromString(plugin.version));
-  scoped_ptr<Version> min_version(
-      Version::GetVersionFromString(g_min_flash_version));
-  return plugin.enabled &&
+  scoped_ptr<Version> min_version(Version::GetVersionFromString(
+      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kMinClearSiteDataFlashVersion)));
+  if (!min_version.get())
+    min_version.reset(Version::GetVersionFromString(kMinFlashVersion));
+  return webkit::npapi::IsPluginEnabled(plugin) &&
          version.get() &&
          min_version->CompareTo(*version) == -1;
 }
diff --git a/chrome/browser/plugin_data_remover.h b/chrome/browser/plugin_data_remover.h
index 77f7f58..b9842b1 100644
--- a/chrome/browser/plugin_data_remover.h
+++ b/chrome/browser/plugin_data_remover.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,6 +15,7 @@
 
 namespace base {
 class MessageLoopProxy;
+class WaitableEvent;
 }
 
 class PluginDataRemover : public base::RefCountedThreadSafe<PluginDataRemover>,
@@ -23,9 +24,11 @@
  public:
   PluginDataRemover();
 
-  // Starts removing plug-in data stored since |begin_time|. If |done_task| is
-  // not NULL, it is run on the current thread when removing has finished.
-  void StartRemoving(base::Time begin_time, Task* done_task);
+  // Used in tests to call a different plugin.
+  void set_mime_type(const std::string& mime_type) { mime_type_ = mime_type; }
+
+  // Starts removing plug-in data stored since |begin_time|.
+  base::WaitableEvent* StartRemoving(const base::Time& begin_time);
 
   // Returns whether there is a plug-in installed that supports removing
   // LSO data. Because this method possibly has to load the plug-in list, it
@@ -34,9 +37,10 @@
 
   bool is_removing() const { return is_removing_; }
 
-  // Sets the task to run when removing has finished. Takes ownership of
-  // the passed task.
-  void set_done_task(Task* task) { done_task_.reset(task); }
+  // Wait until removing has finished. When the browser is still running (i.e.
+  // not during shutdown), you should use a WaitableEventWatcher in combination
+  // with the WaitableEvent returned by StartRemoving.
+  void Wait();
 
   // PluginProcessHost::Client methods
   virtual int ID();
@@ -51,6 +55,7 @@
 
  private:
   friend class base::RefCountedThreadSafe<PluginDataRemover>;
+  friend class PluginDataRemoverTest;
   ~PluginDataRemover();
 
   void SignalDone();
@@ -58,13 +63,13 @@
   void OnClearSiteDataResult(bool success);
   void OnTimeout();
 
-  scoped_refptr<base::MessageLoopProxy> message_loop_;
+  std::string mime_type_;
   bool is_removing_;
-  scoped_ptr<Task> done_task_;
   // The point in time when we start removing data.
   base::Time remove_start_time_;
   // The point in time from which on we remove data.
   base::Time begin_time_;
+  scoped_ptr<base::WaitableEvent> event_;
   // We own the channel, but it's used on the IO thread, so it needs to be
   // deleted there as well.
   IPC::Channel* channel_;
diff --git a/chrome/browser/plugin_data_remover_browsertest.cc b/chrome/browser/plugin_data_remover_browsertest.cc
new file mode 100644
index 0000000..3fbaf75
--- /dev/null
+++ b/chrome/browser/plugin_data_remover_browsertest.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/plugin_data_remover.h"
+
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "base/synchronization/waitable_event_watcher.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+
+namespace {
+const char* kNPAPITestPluginMimeType = "application/vnd.npapi-test";
+}
+
+class PluginDataRemoverTest : public InProcessBrowserTest,
+                              public base::WaitableEventWatcher::Delegate {
+ public:
+  PluginDataRemoverTest() : InProcessBrowserTest() { }
+
+  virtual void SetUpOnMainThread() {
+    old_plugin_data_remover_mime_type_ =
+        g_browser_process->plugin_data_remover_mime_type();
+    g_browser_process->set_plugin_data_remover_mime_type(
+        kNPAPITestPluginMimeType);
+  }
+
+  virtual void TearDownOnMainThread() {
+    g_browser_process->set_plugin_data_remover_mime_type(
+        old_plugin_data_remover_mime_type_);
+  }
+
+  virtual void OnWaitableEventSignaled(base::WaitableEvent* waitable_event) {
+    MessageLoop::current()->Quit();
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) {
+#ifdef OS_MACOSX
+    FilePath browser_directory;
+    PathService::Get(chrome::DIR_APP, &browser_directory);
+    command_line->AppendSwitchPath(switches::kExtraPluginDir,
+                                   browser_directory.AppendASCII("plugins"));
+#endif
+
+//    command_line->AppendSwitch(switches::kPluginStartupDialog);
+  }
+
+ private:
+  std::string old_plugin_data_remover_mime_type_;
+};
+
+IN_PROC_BROWSER_TEST_F(PluginDataRemoverTest, RemoveData) {
+  scoped_refptr<PluginDataRemover> plugin_data_remover(new PluginDataRemover());
+  plugin_data_remover->set_mime_type(kNPAPITestPluginMimeType);
+  base::WaitableEventWatcher watcher;
+  base::WaitableEvent* event =
+      plugin_data_remover->StartRemoving(base::Time());
+  watcher.StartWatching(event, this);
+  ui_test_utils::RunMessageLoop();
+}
+
+IN_PROC_BROWSER_TEST_F(PluginDataRemoverTest, AtShutdown) {
+  browser()->profile()->GetPrefs()->SetBoolean(
+      prefs::kClearSiteDataOnExit, true);
+  g_browser_process->local_state()->SetBoolean(
+      prefs::kClearPluginLSODataEnabled, true);
+}
diff --git a/chrome/browser/plugin_data_remover_helper.cc b/chrome/browser/plugin_data_remover_helper.cc
index 43eb4f6..7b05fc3 100644
--- a/chrome/browser/plugin_data_remover_helper.cc
+++ b/chrome/browser/plugin_data_remover_helper.cc
@@ -4,11 +4,12 @@
 
 #include "chrome/browser/plugin_data_remover_helper.h"
 
+#include <string>
+
 #include "base/ref_counted.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/plugin_data_remover.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 
diff --git a/chrome/browser/plugin_download_helper.cc b/chrome/browser/plugin_download_helper.cc
index e9d306c..09a44a1 100644
--- a/chrome/browser/plugin_download_helper.cc
+++ b/chrome/browser/plugin_download_helper.cc
@@ -36,7 +36,7 @@
 void PluginDownloadUrlHelper::InitiateDownload(
     net::URLRequestContext* request_context) {
   download_file_request_ = new net::URLRequest(GURL(download_url_), this);
-  chrome_browser_net::SetOriginProcessUniqueIDForRequest(
+  chrome_browser_net::SetOriginPIDForRequest(
       download_source_child_unique_id_, download_file_request_);
   download_file_request_->set_context(request_context);
   download_file_request_->Start();
@@ -184,7 +184,3 @@
 }
 
 #endif  // OS_WIN
-
-
-
-
diff --git a/chrome/browser/plugin_download_helper.h b/chrome/browser/plugin_download_helper.h
index 63b24be..2bb87ee 100644
--- a/chrome/browser/plugin_download_helper.h
+++ b/chrome/browser/plugin_download_helper.h
@@ -11,9 +11,9 @@
 
 #if defined(OS_WIN)
 #include "base/file_path.h"
-#include "gfx/native_widget_types.h"
 #include "net/base/file_stream.h"
 #include "net/url_request/url_request.h"
+#include "ui/gfx/native_widget_types.h"
 
 // The PluginDownloadUrlHelper is used to handle one download URL request
 // from the plugin. Each download request is handled by a new instance
diff --git a/chrome/browser/plugin_exceptions_table_model.cc b/chrome/browser/plugin_exceptions_table_model.cc
index a8cc464..99169ac 100644
--- a/chrome/browser/plugin_exceptions_table_model.cc
+++ b/chrome/browser/plugin_exceptions_table_model.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/plugin_exceptions_table_model.h"
 
-#include "app/l10n_util.h"
-#include "app/table_model_observer.h"
 #include "base/auto_reset.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
 
 PluginExceptionsTableModel::PluginExceptionsTableModel(
     HostContentSettingsMap* content_settings_map,
@@ -106,11 +106,11 @@
   return true;
 }
 
-void PluginExceptionsTableModel::SetObserver(TableModelObserver* observer) {
+void PluginExceptionsTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
-TableModel::Groups PluginExceptionsTableModel::GetGroups() {
+ui::TableModel::Groups PluginExceptionsTableModel::GetGroups() {
   return groups_;
 }
 
diff --git a/chrome/browser/plugin_exceptions_table_model.h b/chrome/browser/plugin_exceptions_table_model.h
index 009ab35..620a173 100644
--- a/chrome/browser/plugin_exceptions_table_model.h
+++ b/chrome/browser/plugin_exceptions_table_model.h
@@ -37,7 +37,7 @@
   // TableModel methods:
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
   virtual bool HasGroups() OVERRIDE;
   virtual Groups GetGroups() OVERRIDE;
   virtual int GetGroupID(int row) OVERRIDE;
@@ -75,7 +75,7 @@
 
   NotificationRegistrar registrar_;
   bool updates_disabled_;
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(PluginExceptionsTableModel);
 };
diff --git a/chrome/browser/plugin_exceptions_table_model_unittest.cc b/chrome/browser/plugin_exceptions_table_model_unittest.cc
index e7efcca..cdfd537 100644
--- a/chrome/browser/plugin_exceptions_table_model_unittest.cc
+++ b/chrome/browser/plugin_exceptions_table_model_unittest.cc
@@ -2,17 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/table_model_observer.h"
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/mock_plugin_exceptions_table_model.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/testing_pref_service.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/models/table_model_observer.h"
 #include "webkit/plugins/npapi/plugin_group.h"
 #include "webkit/plugins/npapi/webplugininfo.h"
 
@@ -23,9 +22,9 @@
 using ::testing::_;
 using ::testing::Invoke;
 
-class MockTableModelObserver : public TableModelObserver {
+class MockTableModelObserver : public ui::TableModelObserver {
  public:
-  explicit MockTableModelObserver(TableModel* model)
+   explicit MockTableModelObserver(ui::TableModel* model)
       : model_(model) {
     ON_CALL(*this, OnItemsRemoved(_, _))
         .WillByDefault(
@@ -46,7 +45,7 @@
     EXPECT_LT(start, model_->RowCount() + 1);
   }
 
-  TableModel* model_;
+  ui::TableModel* model_;
 };
 
 }  // namespace plugin_test_internal
@@ -89,7 +88,8 @@
     webkit::npapi::WebPluginInfo foo_plugin;
     foo_plugin.path = FilePath(FILE_PATH_LITERAL("a-foo"));
     foo_plugin.name = ASCIIToUTF16("FooPlugin");
-    foo_plugin.enabled = true;
+    foo_plugin.enabled =
+        webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
     scoped_ptr<webkit::npapi::PluginGroup> foo_group(
         webkit::npapi::PluginGroup::FromWebPluginInfo(foo_plugin));
     plugins.push_back(*foo_group);
@@ -97,7 +97,8 @@
     webkit::npapi::WebPluginInfo bar_plugin;
     bar_plugin.path = FilePath(FILE_PATH_LITERAL("b-bar"));
     bar_plugin.name = ASCIIToUTF16("BarPlugin");
-    bar_plugin.enabled = true;
+    bar_plugin.enabled =
+        webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
     scoped_ptr<webkit::npapi::PluginGroup> bar_group(
         webkit::npapi::PluginGroup::FromWebPluginInfo(bar_plugin));
     plugins.push_back(*bar_group);
@@ -112,7 +113,7 @@
     Entries& settings = table_model_->settings_;
     std::deque<int>& row_counts = table_model_->row_counts_;
     std::deque<std::string>& resources = table_model_->resources_;
-    TableModel::Groups& groups = table_model_->groups_;
+    ui::TableModel::Groups& groups = table_model_->groups_;
 
     EXPECT_EQ(groups.size(), row_counts.size());
     EXPECT_EQ(groups.size(), resources.size());
diff --git a/chrome/browser/plugin_installer.cc b/chrome/browser/plugin_installer.cc
deleted file mode 100644
index 8d63679..0000000
--- a/chrome/browser/plugin_installer.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/plugin_installer.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/string_util.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-#include "webkit/plugins/npapi/default_plugin_shared.h"
-
-// The URL for the "Problems installing" page for the Plugins infobar.
-static const char kLearnMorePluginInstallerUrl[] =
-    "http://www.google.com/support/chrome/bin/answer.py?answer=95697&amp;topic=14687";
-
-PluginInstaller::PluginInstaller(TabContents* tab_contents)
-    : ConfirmInfoBarDelegate(tab_contents),
-      tab_contents_(tab_contents) {
-}
-
-PluginInstaller::~PluginInstaller() {
-  // Remove any InfoBars we may be showing.
-  tab_contents_->RemoveInfoBar(this);
-}
-
-void PluginInstaller::OnMissingPluginStatus(int status) {
-  switch (status) {
-    case webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE: {
-      tab_contents_->AddInfoBar(this);
-      break;
-    }
-    case webkit::npapi::default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD: {
-      // Hide the InfoBar if user already started download/install of the
-      // missing plugin.
-      tab_contents_->RemoveInfoBar(this);
-      break;
-    }
-    default: {
-      NOTREACHED();
-      break;
-    }
-  }
-}
-
-string16 PluginInstaller::GetMessageText() const {
-  return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT);
-}
-
-SkBitmap* PluginInstaller::GetIcon() const {
-  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-      IDR_INFOBAR_PLUGIN_INSTALL);
-}
-
-int PluginInstaller::GetButtons() const {
-  return BUTTON_OK;
-}
-
-string16 PluginInstaller::GetButtonLabel(InfoBarButton button) const {
-  if (button == BUTTON_OK)
-    return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON);
-  return ConfirmInfoBarDelegate::GetButtonLabel(button);
-}
-
-bool PluginInstaller::Accept() {
-  tab_contents_->render_view_host()->InstallMissingPlugin();
-  return true;
-}
-
-string16 PluginInstaller::GetLinkText() {
-  return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_PROBLEMSINSTALLING);
-}
-
-bool PluginInstaller::LinkClicked(WindowOpenDisposition disposition) {
-  // Ignore the click dispostion and always open in a new top level tab.
-  tab_contents_->OpenURL(GURL(kLearnMorePluginInstallerUrl), GURL(),
-                         NEW_FOREGROUND_TAB, PageTransition::LINK);
-  return false;  // Do not dismiss the info bar.
-}
diff --git a/chrome/browser/plugin_installer.h b/chrome/browser/plugin_installer.h
deleted file mode 100644
index b56034d..0000000
--- a/chrome/browser/plugin_installer.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PLUGIN_INSTALLER_H_
-#define CHROME_BROWSER_PLUGIN_INSTALLER_H_
-#pragma once
-
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-
-class TabContents;
-
-// The main purpose for this class is to popup/close the infobar when there is
-// a missing plugin.
-class PluginInstaller : public ConfirmInfoBarDelegate {
- public:
-  explicit PluginInstaller(TabContents* tab_contents);
-  ~PluginInstaller();
-
-  void OnMissingPluginStatus(int status);
-  // A new page starts loading. This is the perfect time to close the info bar.
-  void OnStartLoading();
-
- private:
-  // Overridden from ConfirmInfoBarDelegate:
-  virtual string16 GetMessageText() const;
-  virtual SkBitmap* GetIcon() const;
-  virtual int GetButtons() const;
-  virtual string16 GetButtonLabel(InfoBarButton button) const;
-  virtual bool Accept();
-  virtual string16 GetLinkText();
-  virtual bool LinkClicked(WindowOpenDisposition disposition);
-
-  // The containing TabContents
-  TabContents* tab_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(PluginInstaller);
-};
-
-#endif  // CHROME_BROWSER_PLUGIN_INSTALLER_H_
diff --git a/chrome/browser/plugin_installer_infobar_delegate.cc b/chrome/browser/plugin_installer_infobar_delegate.cc
new file mode 100644
index 0000000..3898e0c
--- /dev/null
+++ b/chrome/browser/plugin_installer_infobar_delegate.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/plugin_installer_infobar_delegate.h"
+
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
+    TabContents* tab_contents)
+    : ConfirmInfoBarDelegate(tab_contents),
+      tab_contents_(tab_contents) {
+}
+
+PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() {
+}
+
+SkBitmap* PluginInstallerInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_PLUGIN_INSTALL);
+}
+
+PluginInstallerInfoBarDelegate*
+    PluginInstallerInfoBarDelegate::AsPluginInstallerInfoBarDelegate() {
+  return this;
+}
+
+string16 PluginInstallerInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_MISSINGPLUGIN_PROMPT);
+}
+
+int PluginInstallerInfoBarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
+
+string16 PluginInstallerInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON);
+}
+
+bool PluginInstallerInfoBarDelegate::Accept() {
+  tab_contents_->render_view_host()->InstallMissingPlugin();
+  return true;
+}
+
+string16 PluginInstallerInfoBarDelegate::GetLinkText() {
+  return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_PROBLEMSINSTALLING);
+}
+
+bool PluginInstallerInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  // Ignore the click dispostion and always open in a new top level tab.
+  static const char kLearnMorePluginInstallerUrl[] = "http://www.google.com/"
+      "support/chrome/bin/answer.py?answer=95697&amp;topic=14687";
+  tab_contents_->OpenURL(GURL(kLearnMorePluginInstallerUrl), GURL(),
+                         NEW_FOREGROUND_TAB, PageTransition::LINK);
+  return false;
+}
diff --git a/chrome/browser/plugin_installer_infobar_delegate.h b/chrome/browser/plugin_installer_infobar_delegate.h
new file mode 100644
index 0000000..631831b
--- /dev/null
+++ b/chrome/browser/plugin_installer_infobar_delegate.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PLUGIN_INSTALLER_INFOBAR_DELEGATE_H_
+#define CHROME_BROWSER_PLUGIN_INSTALLER_INFOBAR_DELEGATE_H_
+#pragma once
+
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+
+class TabContents;
+
+// The main purpose for this class is to popup/close the infobar when there is
+// a missing plugin.
+class PluginInstallerInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  explicit PluginInstallerInfoBarDelegate(TabContents* tab_contents);
+
+ private:
+  virtual ~PluginInstallerInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual SkBitmap* GetIcon() const;
+  virtual PluginInstallerInfoBarDelegate* AsPluginInstallerInfoBarDelegate();
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual string16 GetLinkText();
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
+  // The containing TabContents
+  TabContents* tab_contents_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginInstallerInfoBarDelegate);
+};
+
+#endif  // CHROME_BROWSER_PLUGIN_INSTALLER_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/plugin_observer.cc b/chrome/browser/plugin_observer.cc
new file mode 100644
index 0000000..0d0831c
--- /dev/null
+++ b/chrome/browser/plugin_observer.cc
@@ -0,0 +1,324 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/plugin_observer.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/plugin_installer_infobar_delegate.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/url_constants.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "webkit/plugins/npapi/default_plugin_shared.h"
+#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/npapi/webplugininfo.h"
+
+namespace {
+
+// PluginInfoBarDelegate ------------------------------------------------------
+
+class PluginInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  PluginInfoBarDelegate(TabContents* tab_contents, const string16& name);
+
+ protected:
+  virtual ~PluginInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual bool Cancel();
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
+  string16 name_;
+  TabContents* tab_contents_;
+
+ private:
+  // ConfirmInfoBarDelegate:
+  virtual SkBitmap* GetIcon() const;
+  virtual string16 GetLinkText();
+
+  DISALLOW_COPY_AND_ASSIGN(PluginInfoBarDelegate);
+};
+
+PluginInfoBarDelegate::PluginInfoBarDelegate(TabContents* tab_contents,
+                                             const string16& name)
+    : ConfirmInfoBarDelegate(tab_contents),
+      name_(name),
+      tab_contents_(tab_contents) {
+}
+
+PluginInfoBarDelegate::~PluginInfoBarDelegate() {
+}
+
+void PluginInfoBarDelegate::InfoBarClosed() {
+  delete this;
+}
+
+bool PluginInfoBarDelegate::Cancel() {
+  tab_contents_->render_view_host()->LoadBlockedPlugins();
+  return true;
+}
+
+bool PluginInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
+  GURL url = google_util::AppendGoogleLocaleParam(
+      GURL(chrome::kOutdatedPluginLearnMoreURL));
+  tab_contents_->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+  return false;
+}
+
+SkBitmap* PluginInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_PLUGIN_INSTALL);
+}
+
+string16 PluginInfoBarDelegate::GetLinkText() {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+
+// BlockedPluginInfoBarDelegate -----------------------------------------------
+
+class BlockedPluginInfoBarDelegate : public PluginInfoBarDelegate {
+ public:
+  BlockedPluginInfoBarDelegate(TabContents* tab_contents,
+                               const string16& name);
+
+ private:
+  virtual ~BlockedPluginInfoBarDelegate();
+
+  // PluginInfoBarDelegate:
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+  virtual void InfoBarClosed();
+  virtual void InfoBarDismissed();
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
+  DISALLOW_COPY_AND_ASSIGN(BlockedPluginInfoBarDelegate);
+};
+
+BlockedPluginInfoBarDelegate::BlockedPluginInfoBarDelegate(
+    TabContents* tab_contents,
+    const string16& name)
+    : PluginInfoBarDelegate(tab_contents, name) {
+  UserMetrics::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown"));
+}
+
+BlockedPluginInfoBarDelegate::~BlockedPluginInfoBarDelegate() {
+}
+
+string16 BlockedPluginInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, name_);
+}
+
+string16 BlockedPluginInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_PLUGIN_ENABLE_ALWAYS : IDS_PLUGIN_ENABLE_TEMPORARILY);
+}
+
+bool BlockedPluginInfoBarDelegate::Accept() {
+  UserMetrics::RecordAction(
+      UserMetricsAction("BlockedPluginInfobar.AlwaysAllow"));
+  tab_contents_->profile()->GetHostContentSettingsMap()->AddExceptionForURL(
+      tab_contents_->GetURL(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string(),
+      CONTENT_SETTING_ALLOW);
+  tab_contents_->render_view_host()->LoadBlockedPlugins();
+  return true;
+}
+
+bool BlockedPluginInfoBarDelegate::Cancel() {
+  UserMetrics::RecordAction(
+      UserMetricsAction("BlockedPluginInfobar.AllowThisTime"));
+  return PluginInfoBarDelegate::Cancel();
+}
+
+void BlockedPluginInfoBarDelegate::InfoBarDismissed() {
+  UserMetrics::RecordAction(
+      UserMetricsAction("BlockedPluginInfobar.Dismissed"));
+}
+
+void BlockedPluginInfoBarDelegate::InfoBarClosed() {
+  UserMetrics::RecordAction(UserMetricsAction("BlockedPluginInfobar.Closed"));
+  PluginInfoBarDelegate::InfoBarClosed();
+}
+
+bool BlockedPluginInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  UserMetrics::RecordAction(
+      UserMetricsAction("BlockedPluginInfobar.LearnMore"));
+  return PluginInfoBarDelegate::LinkClicked(disposition);
+}
+
+// OutdatedPluginInfoBarDelegate ----------------------------------------------
+
+class OutdatedPluginInfoBarDelegate : public PluginInfoBarDelegate {
+ public:
+  OutdatedPluginInfoBarDelegate(TabContents* tab_contents,
+                                const string16& name,
+                                const GURL& update_url);
+
+ private:
+  virtual ~OutdatedPluginInfoBarDelegate();
+
+  // PluginInfoBarDelegate:
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+  virtual void InfoBarClosed();
+  virtual void InfoBarDismissed();
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
+  GURL update_url_;
+
+  DISALLOW_COPY_AND_ASSIGN(OutdatedPluginInfoBarDelegate);
+};
+
+OutdatedPluginInfoBarDelegate::OutdatedPluginInfoBarDelegate(
+    TabContents* tab_contents,
+    const string16& name,
+    const GURL& update_url)
+    : PluginInfoBarDelegate(tab_contents, name),
+      update_url_(update_url) {
+  UserMetrics::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Shown"));
+}
+
+OutdatedPluginInfoBarDelegate::~OutdatedPluginInfoBarDelegate() {
+}
+
+string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED_PROMPT, name_);
+}
+
+string16 OutdatedPluginInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_PLUGIN_UPDATE : IDS_PLUGIN_ENABLE_TEMPORARILY);
+}
+
+bool OutdatedPluginInfoBarDelegate::Accept() {
+  UserMetrics::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Update"));
+  tab_contents_->OpenURL(update_url_, GURL(), NEW_FOREGROUND_TAB,
+                         PageTransition::LINK);
+  return false;
+}
+
+bool OutdatedPluginInfoBarDelegate::Cancel() {
+  UserMetrics::RecordAction(
+      UserMetricsAction("OutdatedPluginInfobar.AllowThisTime"));
+  return PluginInfoBarDelegate::Cancel();
+}
+
+void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
+  UserMetrics::RecordAction(
+      UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
+}
+
+void OutdatedPluginInfoBarDelegate::InfoBarClosed() {
+  UserMetrics::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Closed"));
+  PluginInfoBarDelegate::InfoBarClosed();
+}
+
+bool OutdatedPluginInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  UserMetrics::RecordAction(
+      UserMetricsAction("OutdatedPluginInfobar.LearnMore"));
+  return PluginInfoBarDelegate::LinkClicked(disposition);
+}
+
+}  // namespace
+
+
+// PluginObserver -------------------------------------------------------------
+
+PluginObserver::PluginObserver(TabContents* tab_contents)
+    : tab_contents_(tab_contents) {
+}
+
+PluginObserver::~PluginObserver() {
+}
+
+bool PluginObserver::OnMessageReceived(const IPC::Message& message) {
+  IPC_BEGIN_MESSAGE_MAP(PluginObserver, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_MissingPluginStatus, OnMissingPluginStatus)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_BlockedOutdatedPlugin,
+                        OnBlockedOutdatedPlugin)
+    IPC_MESSAGE_UNHANDLED(return false)
+  IPC_END_MESSAGE_MAP()
+
+  return true;
+}
+
+PluginInstallerInfoBarDelegate* PluginObserver::GetPluginInstaller() {
+  if (plugin_installer_ == NULL)
+    plugin_installer_.reset(new PluginInstallerInfoBarDelegate(tab_contents_));
+  return plugin_installer_->AsPluginInstallerInfoBarDelegate();
+}
+
+void PluginObserver::OnMissingPluginStatus(int status) {
+  // TODO(PORT): pull in when plug-ins work
+#if defined(OS_WIN)
+  if (status == webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE) {
+    tab_contents_->AddInfoBar(
+        new PluginInstallerInfoBarDelegate(tab_contents_));
+    return;
+  }
+
+  DCHECK_EQ(webkit::npapi::default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD,
+            status);
+  for (size_t i = 0; i < tab_contents_->infobar_count(); ++i) {
+    InfoBarDelegate* delegate = tab_contents_->GetInfoBarDelegateAt(i);
+    if (delegate->AsPluginInstallerInfoBarDelegate() != NULL) {
+      tab_contents_->RemoveInfoBar(delegate);
+      return;
+    }
+  }
+#endif
+}
+
+void PluginObserver::OnCrashedPlugin(const FilePath& plugin_path) {
+  DCHECK(!plugin_path.value().empty());
+
+  string16 plugin_name = plugin_path.LossyDisplayName();
+  webkit::npapi::WebPluginInfo plugin_info;
+  if (webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath(
+          plugin_path, &plugin_info) &&
+      !plugin_info.name.empty()) {
+    plugin_name = plugin_info.name;
+#if defined(OS_MACOSX)
+    // Many plugins on the Mac have .plugin in the actual name, which looks
+    // terrible, so look for that and strip it off if present.
+    const std::string kPluginExtension = ".plugin";
+    if (EndsWith(plugin_name, ASCIIToUTF16(kPluginExtension), true))
+      plugin_name.erase(plugin_name.length() - kPluginExtension.length());
+#endif  // OS_MACOSX
+  }
+  SkBitmap* crash_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_PLUGIN_CRASHED);
+  tab_contents_->AddInfoBar(new SimpleAlertInfoBarDelegate(tab_contents_,
+      crash_icon,
+      l10n_util::GetStringFUTF16(IDS_PLUGIN_CRASHED_PROMPT, plugin_name),
+      true));
+}
+
+void PluginObserver::OnBlockedOutdatedPlugin(const string16& name,
+                                             const GURL& update_url) {
+  tab_contents_->AddInfoBar(update_url.is_empty() ?
+      static_cast<InfoBarDelegate*>(new BlockedPluginInfoBarDelegate(
+          tab_contents_, name)) :
+      new OutdatedPluginInfoBarDelegate(tab_contents_, name, update_url));
+}
+
diff --git a/chrome/browser/plugin_observer.h b/chrome/browser/plugin_observer.h
new file mode 100644
index 0000000..9f7a6be
--- /dev/null
+++ b/chrome/browser/plugin_observer.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PLUGIN_OBSERVER_H_
+#define CHROME_BROWSER_PLUGIN_OBSERVER_H_
+#pragma once
+
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+
+class FilePath;
+class GURL;
+class InfoBarDelegate;
+class PluginInstallerInfoBarDelegate;
+class TabContents;
+
+class PluginObserver : public TabContentsObserver {
+ public:
+  explicit PluginObserver(TabContents* tab_contents);
+  ~PluginObserver();
+
+  // IPC::Channel::Listener implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+ private:
+  // Returns the PluginInstallerInfoBarDelegate, creating it if necessary.
+  PluginInstallerInfoBarDelegate* GetPluginInstaller();
+
+  void OnMissingPluginStatus(int status);
+  void OnCrashedPlugin(const FilePath& plugin_path);
+  void OnBlockedOutdatedPlugin(const string16& name, const GURL& update_url);
+
+  TabContents* tab_contents_;  // Weak, owns us.
+  scoped_ptr<InfoBarDelegate> plugin_installer_;  // Lazily created.
+
+  DISALLOW_COPY_AND_ASSIGN(PluginObserver);
+};
+
+#endif  // CHROME_BROWSER_PLUGIN_OBSERVER_H_
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc
index 7bbb5a7..c15b030 100644
--- a/chrome/browser/plugin_process_host.cc
+++ b/chrome/browser/plugin_process_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -36,21 +36,23 @@
 #include "chrome/common/net/url_request_context_getter.h"
 #include "chrome/common/plugin_messages.h"
 #include "chrome/common/render_messages.h"
-#include "gfx/native_widget_types.h"
+#include "chrome/common/render_messages_params.h"
 #include "ipc/ipc_switches.h"
 #include "net/base/cookie_store.h"
 #include "net/base/io_buffer.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/gfx/native_widget_types.h"
 
 #if defined(USE_X11)
-#include "gfx/gtk_native_view_id_manager.h"
+#include "ui/gfx/gtk_native_view_id_manager.h"
 #endif
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
 #include "chrome/common/plugin_carbon_interpose_constants_mac.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 #endif
 
 static const char kDefaultPluginFinderURL[] =
@@ -59,17 +61,17 @@
 namespace {
 
 // Helper class that we pass to ResourceMessageFilter so that it can find the
-// right URLRequestContext for a request.
+// right net::URLRequestContext for a request.
 class PluginURLRequestContextOverride
     : public ResourceMessageFilter::URLRequestContextOverride {
  public:
   PluginURLRequestContextOverride() {
   }
 
-  virtual URLRequestContext* GetRequestContext(
-      uint32 request_id, ResourceType::Type resource_type) {
+  virtual net::URLRequestContext* GetRequestContext(
+      const ViewHostMsg_Resource_Request& resource_request) {
     return CPBrowsingContextManager::GetInstance()->ToURLRequestContext(
-        request_id);
+        resource_request.request_context);
   }
 
  private:
@@ -380,7 +382,7 @@
 void PluginProcessHost::OnGetCookies(uint32 request_context,
                                      const GURL& url,
                                      std::string* cookies) {
-  URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
+  net::URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
         ToURLRequestContext(request_context);
   // TODO(mpcomplete): remove fallback case when Gears support is prevalent.
   if (!context)
diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h
index d30a77a..754768f 100644
--- a/chrome/browser/plugin_process_host.h
+++ b/chrome/browser/plugin_process_host.h
@@ -17,7 +17,7 @@
 #include "base/ref_counted.h"
 #include "chrome/browser/browser_child_process_host.h"
 #include "chrome/browser/net/resolve_proxy_msg_helper.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/plugins/npapi/webplugininfo.h"
 
 namespace gfx {
diff --git a/chrome/browser/plugin_process_host_mac.cc b/chrome/browser/plugin_process_host_mac.cc
index d976369..18616fd 100644
--- a/chrome/browser/plugin_process_host_mac.cc
+++ b/chrome/browser/plugin_process_host_mac.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/plugin_process_host.h"
 #include "chrome/common/plugin_messages.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 void PluginProcessHost::OnPluginSelectWindow(uint32 window_id,
                                              gfx::Rect window_rect,
diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc
index 0c8ee4c..a65bea6 100644
--- a/chrome/browser/plugin_service.cc
+++ b/chrome/browser/plugin_service.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "build/build_config.h"
-
 #include "chrome/browser/plugin_service.h"
 
+#include <vector>
+
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
@@ -18,9 +18,10 @@
 #include "chrome/browser/chrome_plugin_host.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/plugin_updater.h"
-#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ppapi_plugin_process_host.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/common/chrome_plugin_lib.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -32,16 +33,11 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pepper_plugin_registry.h"
 #include "chrome/common/plugin_messages.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "webkit/plugins/npapi/plugin_constants_win.h"
 #include "webkit/plugins/npapi/plugin_list.h"
 #include "webkit/plugins/npapi/webplugininfo.h"
 
-#ifndef DISABLE_NACL
-#include "native_client/src/trusted/plugin/nacl_entry_points.h"
-#endif
-
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/plugin_selection_policy.h"
 #endif
@@ -58,6 +54,29 @@
 }
 #endif
 
+static void PurgePluginListCache(bool reload_pages) {
+  for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
+       !it.IsAtEnd(); it.Advance()) {
+    it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
+  }
+}
+
+#if defined(OS_LINUX)
+// Delegate class for monitoring directories.
+class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
+  virtual void OnFilePathChanged(const FilePath& path) {
+    VLOG(1) << "Watched path changed: " << path.value();
+    // Make the plugin list update itself
+    webkit::npapi::PluginList::Singleton()->RefreshPlugins();
+  }
+  virtual void OnError() {
+    // TODO(pastarmovj): Add some sensible error handling. Maybe silently
+    // stopping the watcher would be enough. Or possibly restart it.
+    NOTREACHED();
+  }
+};
+#endif
+
 // static
 bool PluginService::enable_chrome_plugins_ = true;
 
@@ -109,12 +128,6 @@
     webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
   }
 
-#ifndef DISABLE_NACL
-  if (command_line->HasSwitch(switches::kInternalNaCl)) {
-    RegisterInternalNaClPlugin();
-  }
-#endif
-
 #if defined(OS_CHROMEOS)
   plugin_selection_policy_ = new chromeos::PluginSelectionPolicy;
   plugin_selection_policy_->StartInit();
@@ -122,17 +135,20 @@
 
   chrome::RegisterInternalGPUPlugin();
 
+  // Start watching for changes in the plugin list. This means watching
+  // for changes in the Windows registry keys and on both Windows and POSIX
+  // watch for changes in the paths that are expected to contain plugins.
 #if defined(OS_WIN)
   hkcu_key_.Create(
       HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
   hklm_key_.Create(
       HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
-  if (hkcu_key_.StartWatching()) {
+  if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
     hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
     hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
   }
 
-  if (hklm_key_.StartWatching()) {
+  if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
     hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
     hklm_watcher_.StartWatching(hklm_event_.get(), this);
   }
@@ -145,7 +161,36 @@
         user_data_dir.Append("Plugins"));
   }
 #endif
+// The FilePathWatcher produces too many false positives on MacOS (access time
+// updates?) which will lead to enforcing updates of the plugins way too often.
+// On ChromeOS the user can't install plugins anyway and on Windows all
+// important plugins register themselves in the registry so no need to do that.
+#if defined(OS_LINUX)
+  file_watcher_delegate_ = new PluginDirWatcherDelegate();
+  // Get the list of all paths for registering the FilePathWatchers
+  // that will track and if needed reload the list of plugins on runtime.
+  std::vector<FilePath> plugin_dirs;
+  webkit::npapi::PluginList::Singleton()->GetPluginDirectories(
+      &plugin_dirs);
 
+  for (size_t i = 0; i < plugin_dirs.size(); ++i) {
+    FilePathWatcher* watcher = new FilePathWatcher();
+    // FilePathWatcher can not handle non-absolute paths under windows.
+    // We don't watch for file changes in windows now but if this should ever
+    // be extended to Windows these lines might save some time of debugging.
+#if defined(OS_WIN)
+    if (!plugin_dirs[i].IsAbsolute())
+      continue;
+#endif
+    VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
+    BrowserThread::PostTask(
+        BrowserThread::FILE, FROM_HERE,
+        NewRunnableFunction(
+            &PluginService::RegisterFilePathWatcher,
+            watcher, plugin_dirs[i], file_watcher_delegate_));
+    file_watchers_.push_back(watcher);
+  }
+#endif
   registrar_.Add(this, NotificationType::EXTENSION_LOADED,
                  NotificationService::AllSources());
   registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
@@ -158,6 +203,9 @@
 #endif
   registrar_.Add(this, NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
                  NotificationService::AllSources());
+  registrar_.Add(this,
+                 NotificationType::RENDERER_PROCESS_CLOSED,
+                 NotificationService::AllSources());
 }
 
 PluginService::~PluginService() {
@@ -165,8 +213,10 @@
   // Release the events since they're owned by RegKey, not WaitableEvent.
   hkcu_watcher_.StopWatching();
   hklm_watcher_.StopWatching();
-  hkcu_event_->Release();
-  hklm_event_->Release();
+  if (hkcu_event_.get())
+    hkcu_event_->Release();
+  if (hklm_event_.get())
+    hklm_event_->Release();
 #endif
 }
 
@@ -191,7 +241,7 @@
   return ui_locale_;
 }
 
-PluginProcessHost* PluginService::FindPluginProcess(
+PluginProcessHost* PluginService::FindNpapiPluginProcess(
     const FilePath& plugin_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
@@ -205,11 +255,27 @@
   return NULL;
 }
 
-PluginProcessHost* PluginService::FindOrStartPluginProcess(
+PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess(
     const FilePath& plugin_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  PluginProcessHost* plugin_host = FindPluginProcess(plugin_path);
+  for (BrowserChildProcessHost::Iterator iter(
+           ChildProcessInfo::PPAPI_PLUGIN_PROCESS);
+       !iter.Done(); ++iter) {
+    PpapiPluginProcessHost* plugin =
+        static_cast<PpapiPluginProcessHost*>(*iter);
+    if (plugin->plugin_path() == plugin_path)
+      return plugin;
+  }
+
+  return NULL;
+}
+
+PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess(
+    const FilePath& plugin_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
   if (plugin_host)
     return plugin_host;
 
@@ -222,14 +288,44 @@
   // This plugin isn't loaded by any plugin process, so create a new process.
   scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
   if (!new_host->Init(info, ui_locale_)) {
-    NOTREACHED();  // Init is not expected to fail
+    NOTREACHED();  // Init is not expected to fail.
     return NULL;
   }
-
   return new_host.release();
 }
 
-void PluginService::OpenChannelToPlugin(
+PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess(
+    const FilePath& plugin_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
+  if (plugin_host)
+    return plugin_host;
+
+  // Validate that the plugin is actually registered. There should generally
+  // be very few plugins so a brute-force search is fine.
+  PepperPluginInfo* info = NULL;
+  for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
+    if (ppapi_plugins_[i].path == plugin_path) {
+      info = &ppapi_plugins_[i];
+      break;
+    }
+  }
+  if (!info)
+    return NULL;
+
+  // This plugin isn't loaded by any plugin process, so create a new process.
+  scoped_ptr<PpapiPluginProcessHost> new_host(new PpapiPluginProcessHost);
+  if (!new_host->Init(plugin_path)) {
+    NOTREACHED();  // Init is not expected to fail.
+    return NULL;
+  }
+  return new_host.release();
+}
+
+void PluginService::OpenChannelToNpapiPlugin(
+    int render_process_id,
+    int render_view_id,
     const GURL& url,
     const std::string& mime_type,
     PluginProcessHost::Client* client) {
@@ -239,18 +335,31 @@
       BrowserThread::FILE, FROM_HERE,
       NewRunnableMethod(
           this, &PluginService::GetAllowedPluginForOpenChannelToPlugin,
-          url, mime_type, client));
+          render_process_id, render_view_id, url, mime_type, client));
+}
+
+void PluginService::OpenChannelToPpapiPlugin(
+    const FilePath& path,
+    PpapiPluginProcessHost::Client* client) {
+  PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(path);
+  if (plugin_host)
+    plugin_host->OpenChannelToPlugin(client);
+  else  // Send error.
+    client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
 }
 
 void PluginService::GetAllowedPluginForOpenChannelToPlugin(
+    int render_process_id,
+    int render_view_id,
     const GURL& url,
     const std::string& mime_type,
     PluginProcessHost::Client* client) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   webkit::npapi::WebPluginInfo info;
-  bool found = GetFirstAllowedPluginInfo(url, mime_type, &info, NULL);
+  bool found = GetFirstAllowedPluginInfo(
+      render_process_id, render_view_id, url, mime_type, &info, NULL);
   FilePath plugin_path;
-  if (found && info.enabled)
+  if (found && webkit::npapi::IsPluginEnabled(info))
     plugin_path = FilePath(info.path);
 
   // Now we jump back to the IO thread to finish opening the channel.
@@ -266,7 +375,7 @@
     PluginProcessHost::Client* client) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  PluginProcessHost* plugin_host = FindOrStartPluginProcess(plugin_path);
+  PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
   if (plugin_host)
     plugin_host->OpenChannelToPlugin(client);
   else
@@ -274,6 +383,8 @@
 }
 
 bool PluginService::GetFirstAllowedPluginInfo(
+    int render_process_id,
+    int render_view_id,
     const GURL& url,
     const std::string& mime_type,
     webkit::npapi::WebPluginInfo* info,
@@ -299,18 +410,24 @@
   }
   return false;
 #else
+  {
+    base::AutoLock auto_lock(overridden_plugins_lock_);
+    for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
+      if (overridden_plugins_[i].render_process_id == render_process_id &&
+          overridden_plugins_[i].render_view_id == render_view_id &&
+          overridden_plugins_[i].url == url) {
+        if (actual_mime_type)
+          *actual_mime_type = mime_type;
+        *info = overridden_plugins_[i].plugin;
+        return true;
+      }
+    }
+  }
   return webkit::npapi::PluginList::Singleton()->GetPluginInfo(
       url, mime_type, allow_wildcard, info, actual_mime_type);
 #endif
 }
 
-static void PurgePluginListCache(bool reload_pages) {
-  for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
-       !it.IsAtEnd(); it.Advance()) {
-    it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
-  }
-}
-
 void PluginService::OnWaitableEventSignaled(
     base::WaitableEvent* waitable_event) {
 #if defined(OS_WIN)
@@ -322,12 +439,15 @@
 
   webkit::npapi::PluginList::Singleton()->RefreshPlugins();
   PurgePluginListCache(true);
+#else
+  // This event should only get signaled on a Windows machine.
+  NOTREACHED();
 #endif  // defined(OS_WIN)
 }
 
 static void ForceShutdownPlugin(const FilePath& plugin_path) {
   PluginProcessHost* plugin =
-      PluginService::GetInstance()->FindPluginProcess(plugin_path);
+      PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path);
   if (plugin)
     plugin->ForceShutdown();
 }
@@ -382,11 +502,24 @@
 #endif
 
     case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: {
+      webkit::npapi::PluginList::Singleton()->RefreshPlugins();
       PurgePluginListCache(false);
       break;
     }
+    case NotificationType::RENDERER_PROCESS_CLOSED: {
+      int render_process_id = Source<RenderProcessHost>(source).ptr()->id();
+
+      base::AutoLock auto_lock(overridden_plugins_lock_);
+      for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
+        if (overridden_plugins_[i].render_process_id == render_process_id) {
+          overridden_plugins_.erase(overridden_plugins_.begin() + i);
+          break;
+        }
+      }
+      break;
+    }
     default:
-      DCHECK(false);
+      NOTREACHED();
   }
 }
 
@@ -406,25 +539,45 @@
           url.host() == required_url.host());
 }
 
-void PluginService::RegisterPepperPlugins() {
-  std::vector<PepperPluginInfo> plugins;
-  PepperPluginRegistry::GetList(&plugins);
-  for (size_t i = 0; i < plugins.size(); ++i) {
-    webkit::npapi::PluginVersionInfo info;
-    info.path = plugins[i].path;
-    info.product_name = plugins[i].name.empty() ?
-        plugins[i].path.BaseName().ToWStringHack() :
-        ASCIIToWide(plugins[i].name);
-    info.file_description = ASCIIToWide(plugins[i].description);
-    info.file_extensions = ASCIIToWide(plugins[i].file_extensions);
-    info.file_description = ASCIIToWide(plugins[i].type_descriptions);
-    info.mime_types = ASCIIToWide(JoinString(plugins[i].mime_types, '|'));
+void PluginService::OverridePluginForTab(OverriddenPlugin plugin) {
+  base::AutoLock auto_lock(overridden_plugins_lock_);
+  overridden_plugins_.push_back(plugin);
+}
 
-    // These NPAPI entry points will never be called.  TODO(darin): Come up
-    // with a cleaner way to register pepper plugins with the NPAPI PluginList,
-    // or perhaps refactor the PluginList to be less specific to NPAPI.
-    memset(&info.entry_points, 0, sizeof(info.entry_points));
+void PluginService::RegisterPepperPlugins() {
+  PepperPluginRegistry::ComputeList(&ppapi_plugins_);
+  for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
+    webkit::npapi::WebPluginInfo info;
+    info.path = ppapi_plugins_[i].path;
+    info.name = ppapi_plugins_[i].name.empty() ?
+        ppapi_plugins_[i].path.BaseName().LossyDisplayName() :
+        ASCIIToUTF16(ppapi_plugins_[i].name);
+    info.desc = ASCIIToUTF16(ppapi_plugins_[i].description);
+    info.enabled = webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
+
+    // TODO(evan): Pepper shouldn't require us to parse strings to get
+    // the list of mime types out.
+    if (!webkit::npapi::PluginList::ParseMimeTypes(
+            JoinString(ppapi_plugins_[i].mime_types, '|'),
+            ppapi_plugins_[i].file_extensions,
+            ASCIIToUTF16(ppapi_plugins_[i].type_descriptions),
+            &info.mime_types)) {
+      LOG(ERROR) << "Error parsing mime types for "
+                 << ppapi_plugins_[i].path.LossyDisplayName();
+      return;
+    }
 
     webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);
   }
 }
+
+#if defined(OS_LINUX)
+// static
+void PluginService::RegisterFilePathWatcher(
+    FilePathWatcher *watcher,
+    const FilePath& path,
+    FilePathWatcher::Delegate* delegate) {
+  bool result = watcher->Watch(path, delegate);
+  DCHECK(result);
+}
+#endif
diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h
index d24c4e2..1c0af96 100644
--- a/chrome/browser/plugin_service.h
+++ b/chrome/browser/plugin_service.h
@@ -14,19 +14,28 @@
 #include "base/basictypes.h"
 #include "base/file_path.h"
 #include "base/hash_tables.h"
+#include "base/scoped_vector.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event_watcher.h"
+#include "build/build_config.h"
 #include "chrome/browser/plugin_process_host.h"
+#include "chrome/browser/ppapi_plugin_process_host.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_channel_handle.h"
+#include "webkit/plugins/npapi/webplugininfo.h"
 
 #if defined(OS_WIN)
 #include "base/scoped_ptr.h"
 #include "base/win/registry.h"
 #endif
 
+#if defined(OS_LINUX)
+#include "chrome/browser/file_path_watcher/file_path_watcher.h"
+#endif
+
 #if defined(OS_CHROMEOS)
 namespace chromeos {
 class PluginSelectionPolicy;
@@ -38,6 +47,8 @@
 }
 
 class MessageLoop;
+struct PepperPluginInfo;
+class PluginDirWatcherDelegate;
 class Profile;
 class ResourceDispatcherHost;
 
@@ -45,18 +56,19 @@
 class URLRequestContext;
 }  // namespace net
 
-namespace webkit {
-namespace npapi {
-struct WebPluginInfo;
-}
-}
-
 // This must be created on the main thread but it's only called on the IO/file
 // thread.
 class PluginService
     : public base::WaitableEventWatcher::Delegate,
       public NotificationObserver {
  public:
+  struct OverriddenPlugin {
+    int render_process_id;
+    int render_view_id;
+    GURL url;
+    webkit::npapi::WebPluginInfo plugin;
+  };
+
   // Initializes the global instance; should be called on startup from the main
   // thread.
   static void InitGlobalInstance(Profile* profile);
@@ -79,24 +91,34 @@
   // Returns the plugin process host corresponding to the plugin process that
   // has been started by this service. Returns NULL if no process has been
   // started.
-  PluginProcessHost* FindPluginProcess(const FilePath& plugin_path);
+  PluginProcessHost* FindNpapiPluginProcess(const FilePath& plugin_path);
+  PpapiPluginProcessHost* FindPpapiPluginProcess(const FilePath& plugin_path);
 
   // Returns the plugin process host corresponding to the plugin process that
   // has been started by this service. This will start a process to host the
   // 'plugin_path' if needed. If the process fails to start, the return value
   // is NULL. Must be called on the IO thread.
-  PluginProcessHost* FindOrStartPluginProcess(const FilePath& plugin_path);
+  PluginProcessHost* FindOrStartNpapiPluginProcess(
+      const FilePath& plugin_path);
+  PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
+      const FilePath& plugin_path);
 
   // Opens a channel to a plugin process for the given mime type, starting
   // a new plugin process if necessary.  This must be called on the IO thread
   // or else a deadlock can occur.
-  void OpenChannelToPlugin(const GURL& url,
-                           const std::string& mime_type,
-                           PluginProcessHost::Client* client);
+  void OpenChannelToNpapiPlugin(int render_process_id,
+                                int render_view_id,
+                                const GURL& url,
+                                const std::string& mime_type,
+                                PluginProcessHost::Client* client);
+  void OpenChannelToPpapiPlugin(const FilePath& path,
+                                PpapiPluginProcessHost::Client* client);
 
   // Gets the first allowed plugin in the list of plugins that matches
   // the given url and mime type.  Must be called on the FILE thread.
-  bool GetFirstAllowedPluginInfo(const GURL& url,
+  bool GetFirstAllowedPluginInfo(int render_process_id,
+                                 int render_view_id,
+                                 const GURL& url,
                                  const std::string& mime_type,
                                  webkit::npapi::WebPluginInfo* info,
                                  std::string* actual_mime_type);
@@ -105,6 +127,9 @@
   // the given URL.
   bool PrivatePluginAllowedForURL(const FilePath& plugin_path, const GURL& url);
 
+  // Safe to be called from any thread.
+  void OverridePluginForTab(OverriddenPlugin plugin);
+
   // The UI thread's message loop
   MessageLoop* main_message_loop() { return main_message_loop_; }
 
@@ -133,6 +158,8 @@
 
   // Helper so we can do the plugin lookup on the FILE thread.
   void GetAllowedPluginForOpenChannelToPlugin(
+      int render_process_id,
+      int render_view_id,
       const GURL& url,
       const std::string& mime_type,
       PluginProcessHost::Client* client);
@@ -143,9 +170,13 @@
       const FilePath& plugin_path,
       PluginProcessHost::Client* client);
 
-  // mapping between plugin path and PluginProcessHost
-  typedef base::hash_map<FilePath, PluginProcessHost*> PluginMap;
-  PluginMap plugin_hosts_;
+#if defined(OS_LINUX)
+  // Registers a new FilePathWatcher for a given path.
+  static void RegisterFilePathWatcher(
+      FilePathWatcher* watcher,
+      const FilePath& path,
+      FilePathWatcher::Delegate* delegate);
+#endif
 
   // The main thread's message loop.
   MessageLoop* main_message_loop_;
@@ -180,9 +211,19 @@
   base::WaitableEventWatcher hklm_watcher_;
 #endif
 
+#if defined(OS_LINUX)
+  ScopedVector<FilePathWatcher> file_watchers_;
+  scoped_refptr<PluginDirWatcherDelegate> file_watcher_delegate_;
+#endif
+
+  std::vector<PepperPluginInfo> ppapi_plugins_;
+
   // Set to true if chrome plugins are enabled. Defaults to true.
   static bool enable_chrome_plugins_;
 
+  std::vector<OverriddenPlugin> overridden_plugins_;
+  base::Lock overridden_plugins_lock_;
+
   DISALLOW_COPY_AND_ASSIGN(PluginService);
 };
 
diff --git a/chrome/browser/plugin_service_browsertest.cc b/chrome/browser/plugin_service_browsertest.cc
index 5fed897..ee1be0c 100644
--- a/chrome/browser/plugin_service_browsertest.cc
+++ b/chrome/browser/plugin_service_browsertest.cc
@@ -72,19 +72,19 @@
   // Try to load the default plugin and if this is successful consecutive
   // calls to FindPluginProcess should return non-zero values.
   PluginProcessHost* default_plugin_process_host =
-      plugin_service_->FindOrStartPluginProcess(
+      plugin_service_->FindOrStartNpapiPluginProcess(
           FilePath(webkit::npapi::kDefaultPluginLibraryName));
 
-  EXPECT_EQ(default_plugin_process_host, plugin_service_->FindPluginProcess(
-      FilePath(webkit::npapi::kDefaultPluginLibraryName)));
+  EXPECT_EQ(default_plugin_process_host,
+            plugin_service_->FindNpapiPluginProcess(
+                FilePath(webkit::npapi::kDefaultPluginLibraryName)));
 }
 
 IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) {
   MockPluginProcessHostClient mock_client;
   EXPECT_CALL(mock_client, SetPluginInfo(testing::_)).Times(1);
-  plugin_service_->OpenChannelToPlugin(GURL("http://google.com/"),
-                                       "audio/mp3",
-                                       &mock_client);
+  plugin_service_->OpenChannelToNpapiPlugin(0, 0, GURL("http://google.com/"),
+                                            "audio/mp3", &mock_client);
   message_loop_.RunAllPending();
 }
 
@@ -97,7 +97,7 @@
   // supports all mime types.
   webkit::npapi::WebPluginInfo plugin_info;
   std::string plugin_mime_type;
-  plugin_service_->GetFirstAllowedPluginInfo(GURL("http://google.com/"),
+  plugin_service_->GetFirstAllowedPluginInfo(0, 0, GURL("http://google.com/"),
                                              "application/pdf",
                                              &plugin_info,
                                              &plugin_mime_type);
diff --git a/chrome/browser/plugin_updater.cc b/chrome/browser/plugin_updater.cc
index d994efd..8ba253d 100644
--- a/chrome/browser/plugin_updater.cc
+++ b/chrome/browser/plugin_updater.cc
@@ -7,7 +7,6 @@
 #include <set>
 #include <string>
 
-#include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/scoped_ptr.h"
@@ -18,7 +17,6 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pepper_plugin_registry.h"
 #include "chrome/common/pref_names.h"
@@ -30,8 +28,7 @@
 #define kPluginUpdateDelayMs (60 * 1000)
 
 PluginUpdater::PluginUpdater()
-    : enable_internal_pdf_(true),
-      notify_pending_(false) {
+    : notify_pending_(false) {
 }
 
 DictionaryValue* PluginUpdater::CreatePluginFileSummary(
@@ -40,7 +37,7 @@
   data->SetString("path", plugin.path.value());
   data->SetString("name", plugin.name);
   data->SetString("version", plugin.version);
-  data->SetBoolean("enabled", plugin.enabled);
+  data->SetBoolean("enabled", webkit::npapi::IsPluginEnabled(plugin));
   return data;
 }
 
@@ -58,17 +55,14 @@
 }
 
 void PluginUpdater::EnablePluginGroup(bool enable, const string16& group_name) {
-  if (webkit::npapi::PluginGroup::IsPluginNameDisabledByPolicy(group_name))
-    enable = false;
   webkit::npapi::PluginList::Singleton()->EnableGroup(enable, group_name);
   NotifyPluginStatusChanged();
 }
 
-void PluginUpdater::EnablePluginFile(bool enable,
-                                     const FilePath::StringType& path) {
+void PluginUpdater::EnablePlugin(bool enable,
+                                 const FilePath::StringType& path) {
   FilePath file_path(path);
-  if (enable &&
-      !webkit::npapi::PluginGroup::IsPluginPathDisabledByPolicy(file_path))
+  if (enable)
     webkit::npapi::PluginList::Singleton()->EnablePlugin(file_path);
   else
     webkit::npapi::PluginList::Singleton()->DisablePlugin(file_path);
@@ -125,24 +119,13 @@
         prefs::kPluginsLastInternalDirectory, cur_internal_dir);
   }
 
-  if (!enable_internal_pdf_) {
-    // This DCHECK guards against us disabling/enabling the pdf plugin more than
-    // once without renaming the flag that tells us whether we can enable it
-    // automatically.  Each time we disable the plugin by default after it was
-    // enabled by default, we need to rename that flag.
-    DCHECK(!profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF));
-  }
-
-  bool found_internal_pdf = false;
   bool force_enable_internal_pdf = false;
+  bool internal_pdf_enabled = false;
   string16 pdf_group_name = ASCIIToUTF16(PepperPluginRegistry::kPDFPluginName);
-  bool force_internal_pdf_for_this_run = CommandLine::ForCurrentProcess()->
-      HasSwitch(switches::kForceInternalPDFPlugin);
   FilePath pdf_path;
   PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
   FilePath::StringType pdf_path_str = pdf_path.value();
-  if (enable_internal_pdf_ &&
-      !profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
+  if (!profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
     // We switched to the internal pdf plugin being on by default, and so we
     // need to force it to be enabled.  We only want to do it this once though,
     // i.e. we don't want to enable it again if the user disables it afterwards.
@@ -182,16 +165,14 @@
         }
 
         if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) {
-          found_internal_pdf = true;
-          if (!enabled) {
-            if (force_enable_internal_pdf) {
-              enabled = true;
-              plugin->SetBoolean("enabled", true);
-            } else if (force_internal_pdf_for_this_run) {
-              enabled = true;
-            }
+          if (!enabled && force_enable_internal_pdf) {
+            enabled = true;
+            plugin->SetBoolean("enabled", true);
           }
+
+          internal_pdf_enabled = enabled;
         }
+
         if (!enabled)
           webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_path);
       } else if (!enabled && plugin->GetString("name", &group_name)) {
@@ -212,19 +193,13 @@
       profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist);
   DisablePluginsFromPolicy(plugin_blacklist);
 
-  if ((!enable_internal_pdf_ && !found_internal_pdf) &&
-      !force_internal_pdf_for_this_run) {
-    // The internal PDF plugin is disabled by default, and the user hasn't
-    // overridden the default.
-    webkit::npapi::PluginList::Singleton()->DisablePlugin(pdf_path);
-    EnablePluginGroup(false, pdf_group_name);
-  }
-
-  if (force_enable_internal_pdf) {
+  if (force_enable_internal_pdf || internal_pdf_enabled) {
     // See http://crbug.com/50105 for background.
     EnablePluginGroup(false, ASCIIToUTF16(
         webkit::npapi::PluginGroup::kAdobeReaderGroupName));
+  }
 
+  if (force_enable_internal_pdf) {
     // We want to save this, but doing so requires loading the list of plugins,
     // so do it after a minute as to not impact startup performance.  Note that
     // plugins are loaded after 30s by the metrics service.
@@ -250,9 +225,9 @@
   BrowserThread::PostTask(
     BrowserThread::UI,
     FROM_HERE,
-    NewRunnableFunction(
-        &PluginUpdater::OnUpdatePreferences,
-        static_cast<Profile*>(profile), plugins, groups));
+    NewRunnableFunction(&PluginUpdater::OnUpdatePreferences,
+                        static_cast<Profile*>(profile),
+                        plugins, groups));
 }
 
 void PluginUpdater::OnUpdatePreferences(
@@ -269,16 +244,29 @@
                                      internal_dir);
 
   // Add the plugin files.
-  for (std::vector<webkit::npapi::WebPluginInfo>::const_iterator it =
-           plugins.begin();
-       it != plugins.end();
-       ++it) {
-    plugins_list->Append(CreatePluginFileSummary(*it));
+  for (size_t i = 0; i < plugins.size(); ++i) {
+    DictionaryValue* summary = CreatePluginFileSummary(plugins[i]);
+    // If the plugin is disabled only by policy don't store this state in the
+    // user pref store.
+    if (plugins[i].enabled ==
+        webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_DISABLED) {
+      summary->SetBoolean("enabled", true);
+    }
+    bool enabled_val;
+    summary->GetBoolean("enabled", &enabled_val);
+    plugins_list->Append(summary);
   }
 
   // Add the groups as well.
   for (size_t i = 0; i < groups.size(); ++i) {
-    plugins_list->Append(groups[i].GetSummary());
+      DictionaryValue* summary = groups[i].GetSummary();
+      // If the plugin is disabled only by policy don't store this state in the
+      // user pref store.
+      if (!groups[i].Enabled() &&
+          webkit::npapi::PluginGroup::IsPluginNameDisabledByPolicy(
+              groups[i].GetGroupName()))
+        summary->SetBoolean("enabled", true);
+      plugins_list->Append(summary);
   }
 }
 
diff --git a/chrome/browser/plugin_updater.h b/chrome/browser/plugin_updater.h
index dc18595..b30418e 100644
--- a/chrome/browser/plugin_updater.h
+++ b/chrome/browser/plugin_updater.h
@@ -36,7 +36,7 @@
   void EnablePluginGroup(bool enable, const string16& group_name);
 
   // Enable or disable a specific plugin file.
-  void EnablePluginFile(bool enable, const FilePath::StringType& file_path);
+  void EnablePlugin(bool enable, const FilePath::StringType& file_path);
 
   // Disable all plugin groups as defined by the user's preference file.
   void DisablePluginGroupsFromPrefs(Profile* profile);
@@ -82,10 +82,6 @@
   // Needed to allow singleton instantiation using private constructor.
   friend struct DefaultSingletonTraits<PluginUpdater>;
 
-  // Note: if you change this to false from true, you must update
-  // kPluginsEnabledInternalPDF to be a new name (i.e. add 2, 3, 4...) at end.
-  bool enable_internal_pdf_;
-
   bool notify_pending_;
 
   DISALLOW_COPY_AND_ASSIGN(PluginUpdater);
diff --git a/chrome/browser/policy/asynchronous_policy_loader_unittest.cc b/chrome/browser/policy/asynchronous_policy_loader_unittest.cc
index 44ab3c2..b3e4534 100644
--- a/chrome/browser/policy/asynchronous_policy_loader_unittest.cc
+++ b/chrome/browser/policy/asynchronous_policy_loader_unittest.cc
@@ -6,6 +6,7 @@
 #include "chrome/browser/policy/asynchronous_policy_provider.h"
 #include "chrome/browser/policy/asynchronous_policy_test_base.h"
 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 using ::testing::_;
diff --git a/chrome/browser/policy/asynchronous_policy_provider_unittest.cc b/chrome/browser/policy/asynchronous_policy_provider_unittest.cc
index c6aee70..9d186b8 100644
--- a/chrome/browser/policy/asynchronous_policy_provider_unittest.cc
+++ b/chrome/browser/policy/asynchronous_policy_provider_unittest.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/policy/asynchronous_policy_test_base.h"
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/policy/mock_configuration_policy_store.h"
-#include "chrome/common/policy_constants.h"
+#include "policy/policy_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/policy/asynchronous_policy_test_base.cc b/chrome/browser/policy/asynchronous_policy_test_base.cc
new file mode 100644
index 0000000..eadf41f
--- /dev/null
+++ b/chrome/browser/policy/asynchronous_policy_test_base.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/asynchronous_policy_test_base.h"
+
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
+
+namespace policy {
+
+ProviderDelegateMock::ProviderDelegateMock()
+    : AsynchronousPolicyProvider::Delegate() {}
+
+ProviderDelegateMock::~ProviderDelegateMock() {}
+
+AsynchronousPolicyTestBase::AsynchronousPolicyTestBase()
+    : ui_thread_(BrowserThread::UI, &loop_),
+      file_thread_(BrowserThread::FILE, &loop_) {}
+
+AsynchronousPolicyTestBase::~AsynchronousPolicyTestBase() {}
+
+void AsynchronousPolicyTestBase::SetUp() {
+  delegate_.reset(new ProviderDelegateMock());
+  store_.reset(new MockConfigurationPolicyStore);
+}
+
+void AsynchronousPolicyTestBase::TearDown() {
+  loop_.RunAllPending();
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/asynchronous_policy_test_base.h b/chrome/browser/policy/asynchronous_policy_test_base.h
index 0281afd..f567f63 100644
--- a/chrome/browser/policy/asynchronous_policy_test_base.h
+++ b/chrome/browser/policy/asynchronous_policy_test_base.h
@@ -9,17 +9,18 @@
 #include "base/message_loop.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/policy/asynchronous_policy_provider.h"
-#include "chrome/browser/policy/mock_configuration_policy_store.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
 
+class MockConfigurationPolicyStore;
+
 // A delegate for testing that can feed arbitrary information to the loader.
 class ProviderDelegateMock : public AsynchronousPolicyProvider::Delegate {
  public:
-  ProviderDelegateMock() : AsynchronousPolicyProvider::Delegate() {}
-  virtual ~ProviderDelegateMock() {}
+  ProviderDelegateMock();
+  virtual ~ProviderDelegateMock();
 
   MOCK_METHOD0(Load, DictionaryValue*());
 
@@ -29,20 +30,12 @@
 
 class AsynchronousPolicyTestBase : public testing::Test {
  public:
-  AsynchronousPolicyTestBase()
-      : ui_thread_(BrowserThread::UI, &loop_),
-        file_thread_(BrowserThread::FILE, &loop_) {}
+  AsynchronousPolicyTestBase();
+  virtual ~AsynchronousPolicyTestBase();
 
-  virtual ~AsynchronousPolicyTestBase() {}
-
-  virtual void SetUp() {
-    delegate_.reset(new ProviderDelegateMock());
-    store_.reset(new MockConfigurationPolicyStore);
-  }
-
-  virtual void TearDown() {
-    loop_.RunAllPending();
-  }
+  // testing::Test:
+  virtual void SetUp();
+  virtual void TearDown();
 
  protected:
   MessageLoop loop_;
diff --git a/chrome/browser/policy/config_dir_policy_provider_unittest.cc b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
index 8b7e9a0..9a31e55 100644
--- a/chrome/browser/policy/config_dir_policy_provider_unittest.cc
+++ b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,7 @@
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/policy/mock_configuration_policy_store.h"
 #include "chrome/common/json_value_serializer.h"
-#include "chrome/common/policy_constants.h"
+#include "policy/policy_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -226,7 +226,7 @@
     ConfigDirPolicyProviderValueTest,
     testing::Values(
         ValueTestParams::ForStringPolicy(
-            kPolicyHomePage,
+            kPolicyHomepageLocation,
             key::kHomepageLocation),
         ValueTestParams::ForBooleanPolicy(
             kPolicyHomepageIsNewTabPage,
@@ -235,8 +235,8 @@
             kPolicyRestoreOnStartup,
             key::kRestoreOnStartup),
         ValueTestParams::ForListPolicy(
-            kPolicyURLsToRestoreOnStartup,
-            key::kURLsToRestoreOnStartup),
+            kPolicyRestoreOnStartupURLs,
+            key::kRestoreOnStartupURLs),
         ValueTestParams::ForBooleanPolicy(
             kPolicyDefaultSearchProviderEnabled,
             key::kDefaultSearchProviderEnabled),
@@ -253,14 +253,20 @@
             kPolicyDefaultSearchProviderSuggestURL,
             key::kDefaultSearchProviderSuggestURL),
         ValueTestParams::ForStringPolicy(
+            kPolicyDefaultSearchProviderInstantURL,
+            key::kDefaultSearchProviderInstantURL),
+        ValueTestParams::ForStringPolicy(
             kPolicyDefaultSearchProviderIconURL,
             key::kDefaultSearchProviderIconURL),
         ValueTestParams::ForStringPolicy(
             kPolicyDefaultSearchProviderEncodings,
             key::kDefaultSearchProviderEncodings),
-        ValueTestParams::ForIntegerPolicy(
+        ValueTestParams::ForStringPolicy(
             kPolicyProxyMode,
             key::kProxyMode),
+        ValueTestParams::ForIntegerPolicy(
+            kPolicyProxyServerMode,
+            key::kProxyServerMode),
         ValueTestParams::ForStringPolicy(
             kPolicyProxyServer,
             key::kProxyServer),
@@ -298,22 +304,34 @@
             kPolicyAutoFillEnabled,
             key::kAutoFillEnabled),
         ValueTestParams::ForStringPolicy(
-            kPolicyApplicationLocale,
+            kPolicyApplicationLocaleValue,
             key::kApplicationLocaleValue),
         ValueTestParams::ForBooleanPolicy(
             kPolicySyncDisabled,
             key::kSyncDisabled),
         ValueTestParams::ForListPolicy(
-            kPolicyExtensionInstallAllowList,
-            key::kExtensionInstallAllowList),
+            kPolicyExtensionInstallWhitelist,
+            key::kExtensionInstallWhitelist),
         ValueTestParams::ForListPolicy(
-            kPolicyExtensionInstallDenyList,
-            key::kExtensionInstallDenyList),
+            kPolicyExtensionInstallBlacklist,
+            key::kExtensionInstallBlacklist),
         ValueTestParams::ForBooleanPolicy(
             kPolicyShowHomeButton,
             key::kShowHomeButton),
         ValueTestParams::ForBooleanPolicy(
             kPolicyPrintingEnabled,
-            key::kPrintingEnabled)));
+            key::kPrintingEnabled),
+        ValueTestParams::ForIntegerPolicy(
+            kPolicyPolicyRefreshRate,
+            key::kPolicyRefreshRate),
+        ValueTestParams::ForBooleanPolicy(
+            kPolicyInstantEnabled,
+            key::kInstantEnabled),
+        ValueTestParams::ForBooleanPolicy(
+            kPolicyIncognitoEnabled,
+            key::kIncognitoEnabled),
+        ValueTestParams::ForBooleanPolicy(
+            kPolicyCloudPrintProxyEnabled,
+            key::kCloudPrintProxyEnabled)));
 
 }  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_loader_win.cc b/chrome/browser/policy/configuration_policy_loader_win.cc
index 68ccf80..7ad6863 100644
--- a/chrome/browser/policy/configuration_policy_loader_win.cc
+++ b/chrome/browser/policy/configuration_policy_loader_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -31,13 +31,11 @@
 void ConfigurationPolicyLoaderWin::InitOnFileThread() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   AsynchronousPolicyLoader::InitOnFileThread();
-  MessageLoop::current()->AddDestructionObserver(this);
   SetupWatches();
 }
 
 void ConfigurationPolicyLoaderWin::StopOnFileThread() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  MessageLoop::current()->RemoveDestructionObserver(this);
   user_policy_watcher_.StopWatching();
   machine_policy_watcher_.StopWatching();
   AsynchronousPolicyLoader::StopOnFileThread();
@@ -81,10 +79,4 @@
   Reload();
 }
 
-void ConfigurationPolicyLoaderWin::
-    WillDestroyCurrentMessageLoop() {
-  CancelReloadTask();
-  MessageLoop::current()->RemoveDestructionObserver(this);
-}
-
 }  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_loader_win.h b/chrome/browser/policy/configuration_policy_loader_win.h
index 5fa804d..713a460 100644
--- a/chrome/browser/policy/configuration_policy_loader_win.h
+++ b/chrome/browser/policy/configuration_policy_loader_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,8 +16,7 @@
 // reload when Group Policy changes.
 class ConfigurationPolicyLoaderWin
     : public AsynchronousPolicyLoader,
-      public base::win::ObjectWatcher::Delegate,
-      public MessageLoop::DestructionObserver {
+      public base::win::ObjectWatcher::Delegate {
  public:
   ConfigurationPolicyLoaderWin(
       AsynchronousPolicyProvider::Delegate* delegate,
@@ -39,9 +38,6 @@
   // ObjectWatcher::Delegate overrides:
   virtual void OnObjectSignaled(HANDLE object);
 
-  // MessageLoop::DestructionObserver overrides:
-  virtual void WillDestroyCurrentMessageLoop();
-
   base::WaitableEvent user_policy_changed_event_;
   base::WaitableEvent machine_policy_changed_event_;
   base::win::ObjectWatcher user_policy_watcher_;
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index a942bfc..2f37588 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -23,14 +23,13 @@
 #include "chrome/browser/policy/device_management_policy_provider.h"
 #include "chrome/browser/policy/profile_policy_context.h"
 #include "chrome/browser/prefs/pref_value_map.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/policy_constants.h"
 #include "chrome/common/pref_names.h"
+#include "policy/policy_constants.h"
 
 namespace policy {
 
@@ -107,8 +106,9 @@
   // respective values in |prefs_|.
   void FinalizeProxyPolicySettings();
 
-  // Returns true if the policy values stored in proxy_* represent a valid
-  // proxy configuration.
+  // Returns true if the policy values stored in proxy_* represent a valid proxy
+  // configuration, including the case in which there is no configuration at
+  // all.
   bool CheckProxySettings();
 
   // Assumes CheckProxySettings returns true and applies the values stored
@@ -150,12 +150,12 @@
 
 const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
     ConfigurationPolicyPrefKeeper::kSimplePolicyMap[] = {
-  { Value::TYPE_STRING, kPolicyHomePage,  prefs::kHomePage },
+  { Value::TYPE_STRING, kPolicyHomepageLocation,  prefs::kHomePage },
   { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
     prefs::kHomePageIsNewTabPage },
   { Value::TYPE_INTEGER, kPolicyRestoreOnStartup,
     prefs::kRestoreOnStartup},
-  { Value::TYPE_LIST, kPolicyURLsToRestoreOnStartup,
+  { Value::TYPE_LIST, kPolicyRestoreOnStartupURLs,
     prefs::kURLsToRestoreOnStartup },
   { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
     prefs::kAlternateErrorPagesEnabled },
@@ -175,13 +175,13 @@
     prefs::kPrintingEnabled },
   { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
     prefs::kMetricsReportingEnabled },
-  { Value::TYPE_STRING, kPolicyApplicationLocale,
+  { Value::TYPE_STRING, kPolicyApplicationLocaleValue,
     prefs::kApplicationLocale},
-  { Value::TYPE_LIST, kPolicyExtensionInstallAllowList,
+  { Value::TYPE_LIST, kPolicyExtensionInstallWhitelist,
     prefs::kExtensionInstallAllowList},
-  { Value::TYPE_LIST, kPolicyExtensionInstallDenyList,
+  { Value::TYPE_LIST, kPolicyExtensionInstallBlacklist,
     prefs::kExtensionInstallDenyList},
-  { Value::TYPE_LIST, kPolicyExtensionInstallForceList,
+  { Value::TYPE_LIST, kPolicyExtensionInstallForcelist,
     prefs::kExtensionInstallForceList},
   { Value::TYPE_LIST, kPolicyDisabledPlugins,
     prefs::kPluginsPluginsBlacklist},
@@ -189,6 +189,8 @@
     prefs::kShowHomeButton },
   { Value::TYPE_BOOLEAN, kPolicyJavascriptEnabled,
     prefs::kWebKitJavascriptEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyIncognitoEnabled,
+    prefs::kIncognitoEnabled },
   { Value::TYPE_BOOLEAN, kPolicySavingBrowserHistoryDisabled,
     prefs::kSavingBrowserHistoryDisabled },
   { Value::TYPE_BOOLEAN, kPolicyDeveloperToolsDisabled,
@@ -223,6 +225,13 @@
     prefs::kGSSAPILibraryName },
   { Value::TYPE_BOOLEAN, kPolicyDisable3DAPIs,
     prefs::kDisable3DAPIs },
+  { Value::TYPE_INTEGER, kPolicyPolicyRefreshRate,
+    prefs::kPolicyRefreshRate },
+  { Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled,
+    prefs::kDefaultBrowserSettingEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyCloudPrintProxyEnabled,
+    prefs::kCloudPrintProxyEnabled },
 
 #if defined(OS_CHROMEOS)
   { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend,
@@ -248,13 +257,6 @@
     prefs::kDefaultSearchProviderEncodings },
 };
 
-const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
-    ConfigurationPolicyPrefKeeper::kProxyPolicyMap[] = {
-  { Value::TYPE_STRING, kPolicyProxyServer, prefs::kProxyServer },
-  { Value::TYPE_STRING, kPolicyProxyPacUrl, prefs::kProxyPacUrl },
-  { Value::TYPE_STRING, kPolicyProxyBypassList, prefs::kProxyBypassList }
-};
-
 ConfigurationPolicyPrefKeeper::ConfigurationPolicyPrefKeeper(
     ConfigurationPolicyProvider* provider)
   : lower_priority_proxy_settings_overridden_(false),
@@ -364,6 +366,7 @@
   // FinalizeProxyPolicySettings() is called to determine whether the presented
   // values were correct and apply them in that case.
   if (policy == kPolicyProxyMode ||
+      policy == kPolicyProxyServerMode ||
       policy == kPolicyProxyServer ||
       policy == kPolicyProxyPacUrl ||
       policy == kPolicyProxyBypassList) {
@@ -423,8 +426,8 @@
     return "en";
   }
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
-  virtual std::wstring GetRlzParameterValue() const {
-    return std::wstring();
+  virtual string16 GetRlzParameterValue() const {
+    return string16();
   }
 #endif
  private:
@@ -444,6 +447,7 @@
     prefs_.SetString(prefs::kDefaultSearchProviderIconURL, std::string());
     prefs_.SetString(prefs::kDefaultSearchProviderEncodings, std::string());
     prefs_.SetString(prefs::kDefaultSearchProviderKeyword, std::string());
+    prefs_.SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
     return;
   }
   std::string search_url;
@@ -460,6 +464,7 @@
       EnsureStringPrefExists(prefs::kDefaultSearchProviderIconURL);
       EnsureStringPrefExists(prefs::kDefaultSearchProviderEncodings);
       EnsureStringPrefExists(prefs::kDefaultSearchProviderKeyword);
+      EnsureStringPrefExists(prefs::kDefaultSearchProviderInstantURL);
 
       // For the name, default to the host if not specified.
       std::string name;
@@ -491,118 +496,184 @@
 
 bool ConfigurationPolicyPrefKeeper::CheckProxySettings() {
   bool mode = HasProxyPolicy(kPolicyProxyMode);
+  bool server_mode = HasProxyPolicy(kPolicyProxyServerMode);  // deprecated
   bool server = HasProxyPolicy(kPolicyProxyServer);
   bool pac_url = HasProxyPolicy(kPolicyProxyPacUrl);
   bool bypass_list = HasProxyPolicy(kPolicyProxyBypassList);
 
-  if ((server || pac_url || bypass_list) && !mode) {
+  if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
     LOG(WARNING) << "A centrally-administered policy defines proxy setting"
                  << " details without setting a proxy mode.";
     return false;
   }
 
-  if (!mode)
-    return true;
+  // If there's a server mode, convert it into a mode.
+  std::string mode_value;
+  if (mode) {
+    if (server_mode)
+      LOG(WARNING) << "Both ProxyMode and ProxyServerMode policies defined, "
+                   << "ignoring ProxyMode.";
+    if (!proxy_policies_[kPolicyProxyMode]->GetAsString(&mode_value)) {
+      LOG(WARNING) << "Invalid ProxyMode value.";
+      return false;
+    }
+  } else if (server_mode) {
+    int server_mode_value;
+    if (!proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(
+        &server_mode_value)) {
+      LOG(WARNING) << "Invalid ProxyServerMode value.";
+      return false;
+    }
 
-  int mode_value;
-  if (!proxy_policies_[kPolicyProxyMode]->GetAsInteger(&mode_value)) {
-    LOG(WARNING) << "Invalid proxy mode value.";
-    return false;
+    switch (server_mode_value) {
+      case kPolicyNoProxyServerMode:
+        mode_value = ProxyPrefs::kDirectProxyModeName;
+        break;
+      case kPolicyAutoDetectProxyServerMode:
+        mode_value = ProxyPrefs::kAutoDetectProxyModeName;
+        break;
+      case kPolicyManuallyConfiguredProxyServerMode:
+        if (server && pac_url) {
+          LOG(WARNING) << "A centrally-administered policy dictates that"
+                       << " both fixed proxy servers and a .pac url. should"
+                       << " be used for proxy configuration.";
+          return false;
+        }
+        if (!server && !pac_url) {
+          LOG(WARNING) << "A centrally-administered policy dictates that the"
+                       << " proxy settings should use either fixed proxy"
+                       << " servers or a .pac url, but specifies neither.";
+          return false;
+        }
+        if (pac_url)
+          mode_value = ProxyPrefs::kPacScriptProxyModeName;
+        else
+          mode_value = ProxyPrefs::kFixedServersProxyModeName;
+        break;
+      case kPolicyUseSystemProxyServerMode:
+        mode_value = ProxyPrefs::kSystemProxyModeName;
+        break;
+      default:
+        LOG(WARNING) << "Invalid proxy mode " << server_mode_value;
+        return false;
+    }
   }
 
-  switch (mode_value) {
-    case kPolicyNoProxyServerMode:
-      if (server || pac_url || bypass_list) {
-        LOG(WARNING) << "A centrally-administered policy disables the use of"
-                     << " a proxy but also specifies an explicit proxy"
-                     << " configuration.";
-        return false;
-      }
-      break;
-    case kPolicyAutoDetectProxyMode:
-      if (server || bypass_list || pac_url) {
-        LOG(WARNING) << "A centrally-administered policy dictates that a proxy"
-                     << " shall be auto configured but specifies fixed proxy"
-                     << " servers, a by-pass list or a .pac script URL.";
-        return false;
-      }
-      break;
-    case kPolicyManuallyConfiguredProxyMode:
-      if (server && pac_url) {
-        LOG(WARNING) << "A centrally-administered policy dictates that the"
-                     << " system proxy settings should use both a fixed"
-                     << " proxy server and a .pac url.";
-        return false;
-      }
-      if (!server && !pac_url) {
-        LOG(WARNING) << "A centrally-administered policy dictates that the"
-                     << " system proxy settings should use either a fixed"
-                     << " proxy server or a .pac url, but specifies neither.";
-        return false;
-      }
-      break;
-    case kPolicyUseSystemProxyMode:
-      if (server || pac_url || bypass_list) {
-        LOG(WARNING) << "A centrally-administered policy dictates that the"
-                     << " system proxy settings should be used but also "
-                     << " specifies an explicit proxy configuration.";
-        return false;
-      }
-      break;
-    default:
-      LOG(WARNING) << "Invalid proxy mode " << mode_value;
+  // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
+  // empty and the proxy shouldn't be configured at all.
+  if (mode_value.empty())
+    return true;
+
+  if (mode_value == ProxyPrefs::kDirectProxyModeName) {
+    if (server || pac_url || bypass_list) {
+      LOG(WARNING) << "A centrally-administered policy disables the use of"
+                   << " a proxy but also specifies an explicit proxy"
+                   << " configuration.";
       return false;
+    }
+  } else if (mode_value == ProxyPrefs::kAutoDetectProxyModeName) {
+    if (server || bypass_list || pac_url) {
+      LOG(WARNING) << "A centrally-administered policy dictates that a proxy"
+                   << " shall be auto configured but specifies fixed proxy"
+                   << " servers, a by-pass list or a .pac script URL.";
+      return false;
+    }
+  } else if (mode_value == ProxyPrefs::kPacScriptProxyModeName) {
+    if (server || bypass_list) {
+      LOG(WARNING) << "A centrally-administered policy dictates that a .pac"
+                   << " script URL should be used for proxy configuration but"
+                   << " also specifies policies required only for fixed"
+                   << " proxy servers.";
+      return false;
+    }
+  } else if (mode_value == ProxyPrefs::kFixedServersProxyModeName) {
+    if (pac_url) {
+      LOG(WARNING) << "A centrally-administered policy dictates that"
+                   << " fixed proxy servers should be used but also"
+                   << " specifies a .pac script URL.";
+      return false;
+    }
+  } else if (mode_value == ProxyPrefs::kSystemProxyModeName) {
+    if (server || pac_url || bypass_list) {
+      LOG(WARNING) << "A centrally-administered policy dictates that the"
+                   << " system proxy settings should be used but also "
+                   << " specifies an explicit proxy configuration.";
+      return false;
+    }
+  } else {
+    LOG(WARNING) << "Invalid proxy mode " << mode_value;
+    return false;
   }
   return true;
 }
 
 void ConfigurationPolicyPrefKeeper::ApplyProxySettings() {
-  if (!HasProxyPolicy(kPolicyProxyMode))
-    return;
-
-  int int_mode;
-  CHECK(proxy_policies_[kPolicyProxyMode]->GetAsInteger(&int_mode));
   ProxyPrefs::ProxyMode mode;
-  switch (int_mode) {
-    case kPolicyNoProxyServerMode:
-      mode = ProxyPrefs::MODE_DIRECT;
+  if (HasProxyPolicy(kPolicyProxyMode)) {
+    std::string string_mode;
+    CHECK(proxy_policies_[kPolicyProxyMode]->GetAsString(&string_mode));
+    if (!ProxyPrefs::StringToProxyMode(string_mode, &mode)) {
+      LOG(WARNING) << "A centrally-administered policy specifies a value for"
+                   << "the ProxyMode policy that isn't recognized.";
+      return;
+    }
+  } else if (HasProxyPolicy(kPolicyProxyServerMode)) {
+    int int_mode = 0;
+    CHECK(proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(&int_mode));
+    switch (int_mode) {
+      case kPolicyNoProxyServerMode:
+        mode = ProxyPrefs::MODE_DIRECT;
+        break;
+      case kPolicyAutoDetectProxyServerMode:
+        mode = ProxyPrefs::MODE_AUTO_DETECT;
+        break;
+      case kPolicyManuallyConfiguredProxyServerMode:
+        mode = ProxyPrefs::MODE_FIXED_SERVERS;
+        if (HasProxyPolicy(kPolicyProxyPacUrl))
+          mode = ProxyPrefs::MODE_PAC_SCRIPT;
+        break;
+      case kPolicyUseSystemProxyServerMode:
+        mode = ProxyPrefs::MODE_SYSTEM;
+        break;
+      default:
+        mode = ProxyPrefs::MODE_DIRECT;
+        NOTREACHED();
+    }
+  } else {
+    return;
+  }
+  switch (mode) {
+    case ProxyPrefs::MODE_DIRECT:
+      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
       break;
-    case kPolicyAutoDetectProxyMode:
-      mode = ProxyPrefs::MODE_AUTO_DETECT;
+    case ProxyPrefs::MODE_AUTO_DETECT:
+      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
       break;
-    case kPolicyManuallyConfiguredProxyMode:
-      mode = ProxyPrefs::MODE_FIXED_SERVERS;
-      if (HasProxyPolicy(kPolicyProxyPacUrl))
-        mode = ProxyPrefs::MODE_PAC_SCRIPT;
+    case ProxyPrefs::MODE_PAC_SCRIPT: {
+      std::string pac_url;
+      proxy_policies_[kPolicyProxyPacUrl]->GetAsString(&pac_url);
+      prefs_.SetValue(prefs::kProxy,
+                      ProxyConfigDictionary::CreatePacScript(pac_url));
       break;
-    case kPolicyUseSystemProxyMode:
-      mode = ProxyPrefs::MODE_SYSTEM;
+    }
+    case ProxyPrefs::MODE_FIXED_SERVERS: {
+      std::string proxy_server;
+      proxy_policies_[kPolicyProxyServer]->GetAsString(&proxy_server);
+      std::string bypass_list;
+      if (HasProxyPolicy(kPolicyProxyBypassList))
+        proxy_policies_[kPolicyProxyBypassList]->GetAsString(&bypass_list);
+      prefs_.SetValue(prefs::kProxy,
+                      ProxyConfigDictionary::CreateFixedServers(proxy_server,
+                                                                bypass_list));
       break;
-    default:
-      mode = ProxyPrefs::MODE_DIRECT;
+    }
+    case ProxyPrefs::MODE_SYSTEM:
+      prefs_.SetValue(prefs::kProxy,
+                      ProxyConfigDictionary::CreateSystem());
+      break;
+    case ProxyPrefs::kModeCount:
       NOTREACHED();
   }
-  prefs_.SetValue(prefs::kProxyMode, Value::CreateIntegerValue(mode));
-
-  if (HasProxyPolicy(kPolicyProxyServer)) {
-    prefs_.SetValue(prefs::kProxyServer, proxy_policies_[kPolicyProxyServer]);
-    proxy_policies_[kPolicyProxyServer] = NULL;
-  } else {
-    prefs_.SetValue(prefs::kProxyServer, Value::CreateNullValue());
-  }
-  if (HasProxyPolicy(kPolicyProxyPacUrl)) {
-    prefs_.SetValue(prefs::kProxyPacUrl, proxy_policies_[kPolicyProxyPacUrl]);
-    proxy_policies_[kPolicyProxyPacUrl] = NULL;
-  } else {
-    prefs_.SetValue(prefs::kProxyPacUrl, Value::CreateNullValue());
-  }
-  if (HasProxyPolicy(kPolicyProxyBypassList)) {
-    prefs_.SetValue(prefs::kProxyBypassList,
-                proxy_policies_[kPolicyProxyBypassList]);
-    proxy_policies_[kPolicyProxyBypassList] = NULL;
-  } else {
-    prefs_.SetValue(prefs::kProxyBypassList, Value::CreateNullValue());
-  }
 }
 
 bool ConfigurationPolicyPrefKeeper::HasProxyPolicy(
@@ -616,11 +687,15 @@
 ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
     ConfigurationPolicyProvider* provider)
     : provider_(provider),
-      initialization_complete_(provider->IsInitializationComplete()) {
-  // Read initial policy.
-  policy_keeper_.reset(new ConfigurationPolicyPrefKeeper(provider));
-
-  registrar_.Init(provider_, this);
+      initialization_complete_(false) {
+  if (provider_) {
+    // Read initial policy.
+    policy_keeper_.reset(new ConfigurationPolicyPrefKeeper(provider));
+    registrar_.Init(provider_, this);
+    initialization_complete_ = provider->IsInitializationComplete();
+  } else {
+    initialization_complete_ = true;
+  }
 }
 
 ConfigurationPolicyPrefStore::~ConfigurationPolicyPrefStore() {
@@ -642,7 +717,10 @@
 PrefStore::ReadResult
 ConfigurationPolicyPrefStore::GetValue(const std::string& key,
                                        Value** value) const {
-  return policy_keeper_->GetValue(key, value);
+  if (policy_keeper_.get())
+    return policy_keeper_->GetValue(key, value);
+
+  return PrefStore::READ_NO_VALUE;
 }
 
 void ConfigurationPolicyPrefStore::OnUpdatePolicy() {
@@ -663,36 +741,40 @@
 
 // static
 ConfigurationPolicyPrefStore*
-ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
+ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(
     Profile* profile) {
-  ConfigurationPolicyProviderKeeper* keeper =
-      g_browser_process->configuration_policy_provider_keeper();
-  ConfigurationPolicyProvider* provider = NULL;
-  if (profile)
-    provider = profile->GetPolicyContext()->GetDeviceManagementPolicyProvider();
-  if (!provider)
-    provider = keeper->device_management_provider();
-  return new ConfigurationPolicyPrefStore(provider);
+  if (profile) {
+    return new ConfigurationPolicyPrefStore(
+        profile->GetPolicyContext()->GetDeviceManagementPolicyProvider());
+  }
+  return new ConfigurationPolicyPrefStore(NULL);
 }
 
 // static
 ConfigurationPolicyPrefStore*
-ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore() {
+ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() {
   ConfigurationPolicyProviderKeeper* keeper =
       g_browser_process->configuration_policy_provider_keeper();
   return new ConfigurationPolicyPrefStore(keeper->recommended_provider());
 }
 
+// static
+ConfigurationPolicyPrefStore*
+ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
+    Profile* profile) {
+  return new ConfigurationPolicyPrefStore(NULL);
+}
+
 /* static */
 const ConfigurationPolicyProvider::PolicyDefinitionList*
 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() {
   static ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[] = {
-    { kPolicyHomePage, Value::TYPE_STRING, key::kHomepageLocation },
+    { kPolicyHomepageLocation, Value::TYPE_STRING, key::kHomepageLocation },
     { kPolicyHomepageIsNewTabPage, Value::TYPE_BOOLEAN,
       key::kHomepageIsNewTabPage },
     { kPolicyRestoreOnStartup, Value::TYPE_INTEGER, key::kRestoreOnStartup },
-    { kPolicyURLsToRestoreOnStartup, Value::TYPE_LIST,
-      key::kURLsToRestoreOnStartup },
+    { kPolicyRestoreOnStartupURLs, Value::TYPE_LIST,
+      key::kRestoreOnStartupURLs },
     { kPolicyDefaultSearchProviderEnabled, Value::TYPE_BOOLEAN,
       key::kDefaultSearchProviderEnabled },
     { kPolicyDefaultSearchProviderName, Value::TYPE_STRING,
@@ -703,11 +785,14 @@
       key::kDefaultSearchProviderSearchURL },
     { kPolicyDefaultSearchProviderSuggestURL, Value::TYPE_STRING,
       key::kDefaultSearchProviderSuggestURL },
+    { kPolicyDefaultSearchProviderInstantURL, Value::TYPE_STRING,
+      key::kDefaultSearchProviderInstantURL },
     { kPolicyDefaultSearchProviderIconURL, Value::TYPE_STRING,
       key::kDefaultSearchProviderIconURL },
     { kPolicyDefaultSearchProviderEncodings, Value::TYPE_STRING,
       key::kDefaultSearchProviderEncodings },
-    { kPolicyProxyMode, Value::TYPE_INTEGER, key::kProxyMode },
+    { kPolicyProxyMode, Value::TYPE_STRING, key::kProxyMode },
+    { kPolicyProxyServerMode, Value::TYPE_INTEGER, key::kProxyServerMode },
     { kPolicyProxyServer, Value::TYPE_STRING, key::kProxyServer },
     { kPolicyProxyPacUrl, Value::TYPE_STRING, key::kProxyPacUrl },
     { kPolicyProxyBypassList, Value::TYPE_STRING, key::kProxyBypassList },
@@ -728,18 +813,19 @@
       key::kPasswordManagerAllowShowPasswords },
     { kPolicyAutoFillEnabled, Value::TYPE_BOOLEAN, key::kAutoFillEnabled },
     { kPolicyDisabledPlugins, Value::TYPE_LIST, key::kDisabledPlugins },
-    { kPolicyApplicationLocale, Value::TYPE_STRING,
+    { kPolicyApplicationLocaleValue, Value::TYPE_STRING,
       key::kApplicationLocaleValue },
     { kPolicySyncDisabled, Value::TYPE_BOOLEAN, key::kSyncDisabled },
-    { kPolicyExtensionInstallAllowList, Value::TYPE_LIST,
-      key::kExtensionInstallAllowList },
-    { kPolicyExtensionInstallDenyList, Value::TYPE_LIST,
-      key::kExtensionInstallDenyList },
-    { kPolicyExtensionInstallForceList, Value::TYPE_LIST,
-      key::kExtensionInstallForceList },
+    { kPolicyExtensionInstallWhitelist, Value::TYPE_LIST,
+      key::kExtensionInstallWhitelist },
+    { kPolicyExtensionInstallBlacklist, Value::TYPE_LIST,
+      key::kExtensionInstallBlacklist },
+    { kPolicyExtensionInstallForcelist, Value::TYPE_LIST,
+      key::kExtensionInstallForcelist },
     { kPolicyShowHomeButton, Value::TYPE_BOOLEAN, key::kShowHomeButton },
     { kPolicyPrintingEnabled, Value::TYPE_BOOLEAN, key::kPrintingEnabled },
     { kPolicyJavascriptEnabled, Value::TYPE_BOOLEAN, key::kJavascriptEnabled },
+    { kPolicyIncognitoEnabled, Value::TYPE_BOOLEAN, key::kIncognitoEnabled },
     { kPolicySavingBrowserHistoryDisabled, Value::TYPE_BOOLEAN,
       key::kSavingBrowserHistoryDisabled },
     { kPolicyDeveloperToolsDisabled, Value::TYPE_BOOLEAN,
@@ -773,6 +859,13 @@
       key::kGSSAPILibraryName },
     { kPolicyDisable3DAPIs, Value::TYPE_BOOLEAN,
       key::kDisable3DAPIs },
+    { kPolicyPolicyRefreshRate, Value::TYPE_INTEGER,
+      key::kPolicyRefreshRate },
+    { kPolicyInstantEnabled, Value::TYPE_BOOLEAN, key::kInstantEnabled },
+    { kPolicyDefaultBrowserSettingEnabled, Value::TYPE_BOOLEAN,
+      key::kDefaultBrowserSettingEnabled },
+    { kPolicyCloudPrintProxyEnabled, Value::TYPE_BOOLEAN,
+      key::kCloudPrintProxyEnabled },
 
 #if defined(OS_CHROMEOS)
     { kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN,
diff --git a/chrome/browser/policy/configuration_policy_pref_store.h b/chrome/browser/policy/configuration_policy_pref_store.h
index 93b2a4a..bd1a990 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.h
+++ b/chrome/browser/policy/configuration_policy_pref_store.h
@@ -47,13 +47,18 @@
   // Creates a ConfigurationPolicyPrefStore that reads managed platform policy.
   static ConfigurationPolicyPrefStore* CreateManagedPlatformPolicyPrefStore();
 
-  // Creates a ConfigurationPolicyPrefStore that supplies policy from
-  // the device management server.
-  static ConfigurationPolicyPrefStore* CreateDeviceManagementPolicyPrefStore(
+  // Creates a ConfigurationPolicyPrefStore that reads managed cloud policy.
+  static ConfigurationPolicyPrefStore* CreateManagedCloudPolicyPrefStore(
       Profile* profile);
 
-  // Creates a ConfigurationPolicyPrefStore that reads recommended policy.
-  static ConfigurationPolicyPrefStore* CreateRecommendedPolicyPrefStore();
+  // Creates a ConfigurationPolicyPrefStore that reads recommended platform
+  // policy.
+  static ConfigurationPolicyPrefStore*
+      CreateRecommendedPlatformPolicyPrefStore();
+
+  // Creates a ConfigurationPolicyPrefStore that reads recommended cloud policy.
+  static ConfigurationPolicyPrefStore* CreateRecommendedCloudPolicyPrefStore(
+      Profile* profile);
 
   // Returns the default policy definition list for Chrome.
   static const ConfigurationPolicyProvider::PolicyDefinitionList*
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index 100c774..be89d98 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/file_path.h"
+#include "base/ref_counted.h"
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/pref_store_observer_mock.h"
@@ -38,10 +38,10 @@
  protected:
   ConfigurationPolicyPrefStoreTestBase()
       : provider_(),
-        store_(&provider_) {}
+        store_(new ConfigurationPolicyPrefStore(&provider_)) {}
 
   MockConfigurationPolicyProvider provider_;
-  ConfigurationPolicyPrefStore store_;
+  scoped_refptr<ConfigurationPolicyPrefStore> store_;
 };
 
 // Test cases for list-valued policy settings.
@@ -52,7 +52,7 @@
 
 TEST_P(ConfigurationPolicyPrefStoreListTest, GetDefault) {
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(GetParam().pref_name(), NULL));
+            store_->GetValue(GetParam().pref_name(), NULL));
 }
 
 TEST_P(ConfigurationPolicyPrefStoreListTest, SetValue) {
@@ -60,10 +60,10 @@
   in_value->Append(Value::CreateStringValue("test1"));
   in_value->Append(Value::CreateStringValue("test2,"));
   provider_.AddPolicy(GetParam().type(), in_value);
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Value* value;
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(GetParam().pref_name(), &value));
+            store_->GetValue(GetParam().pref_name(), &value));
   EXPECT_TRUE(in_value->Equals(value));
 }
 
@@ -71,11 +71,11 @@
     ConfigurationPolicyPrefStoreListTestInstance,
     ConfigurationPolicyPrefStoreListTest,
     testing::Values(
-        TypeAndName(kPolicyURLsToRestoreOnStartup,
+        TypeAndName(kPolicyRestoreOnStartupURLs,
                     prefs::kURLsToRestoreOnStartup),
-        TypeAndName(kPolicyExtensionInstallAllowList,
+        TypeAndName(kPolicyExtensionInstallWhitelist,
                     prefs::kExtensionInstallAllowList),
-        TypeAndName(kPolicyExtensionInstallDenyList,
+        TypeAndName(kPolicyExtensionInstallBlacklist,
                     prefs::kExtensionInstallDenyList),
         TypeAndName(kPolicyDisabledPlugins,
                     prefs::kPluginsPluginsBlacklist)));
@@ -88,16 +88,16 @@
 
 TEST_P(ConfigurationPolicyPrefStoreStringTest, GetDefault) {
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(GetParam().pref_name(), NULL));
+            store_->GetValue(GetParam().pref_name(), NULL));
 }
 
 TEST_P(ConfigurationPolicyPrefStoreStringTest, SetValue) {
   provider_.AddPolicy(GetParam().type(),
                       Value::CreateStringValue("http://chromium.org"));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Value* value;
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(GetParam().pref_name(), &value));
+            store_->GetValue(GetParam().pref_name(), &value));
   EXPECT_TRUE(StringValue("http://chromium.org").Equals(value));
 }
 
@@ -105,11 +105,11 @@
     ConfigurationPolicyPrefStoreStringTestInstance,
     ConfigurationPolicyPrefStoreStringTest,
     testing::Values(
-        TypeAndName(kPolicyHomePage,
+        TypeAndName(kPolicyHomepageLocation,
                     prefs::kHomePage),
-        TypeAndName(kPolicyApplicationLocale,
+        TypeAndName(kPolicyApplicationLocaleValue,
                     prefs::kApplicationLocale),
-        TypeAndName(kPolicyApplicationLocale,
+        TypeAndName(kPolicyApplicationLocaleValue,
                     prefs::kApplicationLocale),
         TypeAndName(kPolicyAuthSchemes,
                     prefs::kAuthSchemes),
@@ -128,23 +128,23 @@
 
 TEST_P(ConfigurationPolicyPrefStoreBooleanTest, GetDefault) {
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(GetParam().pref_name(), NULL));
+            store_->GetValue(GetParam().pref_name(), NULL));
 }
 
 TEST_P(ConfigurationPolicyPrefStoreBooleanTest, SetValue) {
   provider_.AddPolicy(GetParam().type(), Value::CreateBooleanValue(false));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Value* value;
   bool result = true;
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(GetParam().pref_name(), &value));
+            store_->GetValue(GetParam().pref_name(), &value));
   EXPECT_TRUE(FundamentalValue(false).Equals(value));
 
   provider_.AddPolicy(GetParam().type(), Value::CreateBooleanValue(true));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   result = false;
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(GetParam().pref_name(), &value));
+            store_->GetValue(GetParam().pref_name(), &value));
   EXPECT_TRUE(FundamentalValue(true).Equals(value));
 }
 
@@ -176,6 +176,10 @@
                     prefs::kPrintingEnabled),
         TypeAndName(kPolicyJavascriptEnabled,
                     prefs::kWebKitJavascriptEnabled),
+        TypeAndName(kPolicyIncognitoEnabled,
+                    prefs::kIncognitoEnabled),
+        TypeAndName(kPolicyCloudPrintProxyEnabled,
+                    prefs::kCloudPrintProxyEnabled),
         TypeAndName(kPolicySavingBrowserHistoryDisabled,
                     prefs::kSavingBrowserHistoryDisabled),
         TypeAndName(kPolicySavingBrowserHistoryDisabled,
@@ -184,6 +188,8 @@
                     prefs::kDisableAuthNegotiateCnameLookup),
         TypeAndName(kPolicyEnableAuthNegotiatePort,
                     prefs::kEnableAuthNegotiatePort),
+        TypeAndName(kPolicyInstantEnabled,
+                    prefs::kInstantEnabled),
         TypeAndName(kPolicyDisable3DAPIs,
                     prefs::kDisable3DAPIs)));
 
@@ -204,15 +210,15 @@
 
 TEST_P(ConfigurationPolicyPrefStoreIntegerTest, GetDefault) {
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(GetParam().pref_name(), NULL));
+            store_->GetValue(GetParam().pref_name(), NULL));
 }
 
 TEST_P(ConfigurationPolicyPrefStoreIntegerTest, SetValue) {
   provider_.AddPolicy(GetParam().type(), Value::CreateIntegerValue(2));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Value* value = NULL;
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(GetParam().pref_name(), &value));
+            store_->GetValue(GetParam().pref_name(), &value));
   EXPECT_TRUE(FundamentalValue(2).Equals(value));
 }
 
@@ -221,7 +227,9 @@
     ConfigurationPolicyPrefStoreIntegerTest,
     testing::Values(
         TypeAndName(kPolicyRestoreOnStartup,
-                    prefs::kRestoreOnStartup)));
+                    prefs::kRestoreOnStartup),
+        TypeAndName(kPolicyPolicyRefreshRate,
+                    prefs::kPolicyRefreshRate)));
 
 // Test cases for the proxy policy settings.
 class ConfigurationPolicyPrefStoreProxyTest : public testing::Test {
@@ -234,33 +242,32 @@
       const std::string& expected_proxy_bypass_list,
       const ProxyPrefs::ProxyMode& expected_proxy_mode) {
     Value* value = NULL;
-
+    ASSERT_EQ(PrefStore::READ_OK,
+              store.GetValue(prefs::kProxy, &value));
+    ASSERT_EQ(Value::TYPE_DICTIONARY, value->GetType());
+    ProxyConfigDictionary dict(static_cast<DictionaryValue*>(value));
+    std::string s;
     if (expected_proxy_server.empty()) {
-      EXPECT_EQ(PrefStore::READ_USE_DEFAULT,
-                store.GetValue(prefs::kProxyServer, NULL));
+      EXPECT_FALSE(dict.GetProxyServer(&s));
     } else {
-      EXPECT_EQ(PrefStore::READ_OK,
-                store.GetValue(prefs::kProxyServer, &value));
-      EXPECT_TRUE(StringValue(expected_proxy_server).Equals(value));
+      ASSERT_TRUE(dict.GetProxyServer(&s));
+      EXPECT_EQ(expected_proxy_server, s);
     }
     if (expected_proxy_pac_url.empty()) {
-      EXPECT_EQ(PrefStore::READ_USE_DEFAULT,
-                store.GetValue(prefs::kProxyPacUrl, NULL));
+      EXPECT_FALSE(dict.GetPacUrl(&s));
     } else {
-      EXPECT_EQ(PrefStore::READ_OK,
-                store.GetValue(prefs::kProxyPacUrl, &value));
-      EXPECT_TRUE(StringValue(expected_proxy_pac_url).Equals(value));
+      ASSERT_TRUE(dict.GetPacUrl(&s));
+      EXPECT_EQ(expected_proxy_pac_url, s);
     }
     if (expected_proxy_bypass_list.empty()) {
-      EXPECT_EQ(PrefStore::READ_USE_DEFAULT,
-                store.GetValue(prefs::kProxyBypassList, NULL));
+      EXPECT_FALSE(dict.GetBypassList(&s));
     } else {
-      EXPECT_EQ(PrefStore::READ_OK,
-                store.GetValue(prefs::kProxyBypassList, &value));
-      EXPECT_TRUE(StringValue(expected_proxy_bypass_list).Equals(value));
+      ASSERT_TRUE(dict.GetBypassList(&s));
+      EXPECT_EQ(expected_proxy_bypass_list, s);
     }
-    EXPECT_EQ(PrefStore::READ_OK, store.GetValue(prefs::kProxyMode, &value));
-    EXPECT_TRUE(FundamentalValue(expected_proxy_mode).Equals(value));
+    ProxyPrefs::ProxyMode mode;
+    ASSERT_TRUE(dict.GetMode(&mode));
+    EXPECT_EQ(expected_proxy_mode, mode);
   }
 };
 
@@ -270,76 +277,130 @@
                      Value::CreateStringValue("http://chromium.org/override"));
   provider.AddPolicy(kPolicyProxyServer,
                      Value::CreateStringValue("chromium.org"));
-  provider.AddPolicy(kPolicyProxyMode,
+  provider.AddPolicy(kPolicyProxyServerMode,
                      Value::CreateIntegerValue(
-                         kPolicyManuallyConfiguredProxyMode));
+                         kPolicyManuallyConfiguredProxyServerMode));
 
-  ConfigurationPolicyPrefStore store(&provider);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
   VerifyProxyPrefs(
-      store, "chromium.org", "", "http://chromium.org/override",
+      *store, "chromium.org", "", "http://chromium.org/override",
       ProxyPrefs::MODE_FIXED_SERVERS);
 }
 
 TEST_F(ConfigurationPolicyPrefStoreProxyTest, ManualOptionsReversedApplyOrder) {
   MockConfigurationPolicyProvider provider;
-  provider.AddPolicy(kPolicyProxyMode,
+  provider.AddPolicy(kPolicyProxyServerMode,
                      Value::CreateIntegerValue(
-                         kPolicyManuallyConfiguredProxyMode));
+                         kPolicyManuallyConfiguredProxyServerMode));
   provider.AddPolicy(kPolicyProxyBypassList,
                      Value::CreateStringValue("http://chromium.org/override"));
   provider.AddPolicy(kPolicyProxyServer,
                      Value::CreateStringValue("chromium.org"));
-
-  ConfigurationPolicyPrefStore store(&provider);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
   VerifyProxyPrefs(
-      store, "chromium.org", "", "http://chromium.org/override",
+      *store, "chromium.org", "", "http://chromium.org/override",
       ProxyPrefs::MODE_FIXED_SERVERS);
 }
 
-TEST_F(ConfigurationPolicyPrefStoreProxyTest, NoProxy) {
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, NoProxyServerMode) {
   MockConfigurationPolicyProvider provider;
-  provider.AddPolicy(kPolicyProxyMode,
+  provider.AddPolicy(kPolicyProxyServerMode,
                      Value::CreateIntegerValue(kPolicyNoProxyServerMode));
 
-  ConfigurationPolicyPrefStore store(&provider);
-  VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_DIRECT);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_DIRECT);
 }
 
-TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetect) {
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, NoProxyModeName) {
   MockConfigurationPolicyProvider provider;
-  provider.AddPolicy(kPolicyProxyMode,
-                     Value::CreateIntegerValue(kPolicyAutoDetectProxyMode));
+  provider.AddPolicy(
+      kPolicyProxyMode,
+      Value::CreateStringValue(ProxyPrefs::kDirectProxyModeName));
 
-  ConfigurationPolicyPrefStore store(&provider);
-  VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_DIRECT);
 }
 
-TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectPac) {
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectProxyServerMode) {
+  MockConfigurationPolicyProvider provider;
+  provider.AddPolicy(
+      kPolicyProxyServerMode,
+      Value::CreateIntegerValue(kPolicyAutoDetectProxyServerMode));
+
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectProxyModeName) {
+  MockConfigurationPolicyProvider provider;
+  provider.AddPolicy(
+      kPolicyProxyMode,
+      Value::CreateStringValue(ProxyPrefs::kAutoDetectProxyModeName));
+
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, PacScriptProxyMode) {
   MockConfigurationPolicyProvider provider;
   provider.AddPolicy(kPolicyProxyPacUrl,
                      Value::CreateStringValue("http://short.org/proxy.pac"));
   provider.AddPolicy(
       kPolicyProxyMode,
-      Value::CreateIntegerValue(kPolicyManuallyConfiguredProxyMode));
+      Value::CreateStringValue(ProxyPrefs::kPacScriptProxyModeName));
 
-  ConfigurationPolicyPrefStore store(&provider);
-  VerifyProxyPrefs(
-      store, "", "http://short.org/proxy.pac", "", ProxyPrefs::MODE_PAC_SCRIPT);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "http://short.org/proxy.pac", "",
+                   ProxyPrefs::MODE_PAC_SCRIPT);
 }
 
-TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystem) {
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystemProxyServerMode) {
   MockConfigurationPolicyProvider provider;
-  provider.AddPolicy(kPolicyProxyMode,
-                     Value::CreateIntegerValue(kPolicyUseSystemProxyMode));
+  provider.AddPolicy(
+      kPolicyProxyServerMode,
+      Value::CreateIntegerValue(kPolicyUseSystemProxyServerMode));
 
-  ConfigurationPolicyPrefStore store(&provider);
-  VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_SYSTEM);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_SYSTEM);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystemProxyMode) {
+  MockConfigurationPolicyProvider provider;
+  provider.AddPolicy(
+      kPolicyProxyMode,
+      Value::CreateStringValue(ProxyPrefs::kSystemProxyModeName));
+
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_SYSTEM);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreProxyTest,
+       ProxyModeOverridesProxyServerMode) {
+  MockConfigurationPolicyProvider provider;
+  provider.AddPolicy(kPolicyProxyServerMode,
+                     Value::CreateIntegerValue(kPolicyNoProxyServerMode));
+  provider.AddPolicy(
+      kPolicyProxyMode,
+      Value::CreateStringValue(ProxyPrefs::kAutoDetectProxyModeName));
+
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
+  VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
 }
 
 TEST_F(ConfigurationPolicyPrefStoreProxyTest, ProxyInvalid) {
   for (int i = 0; i < MODE_COUNT; ++i) {
     MockConfigurationPolicyProvider provider;
-    provider.AddPolicy(kPolicyProxyMode, Value::CreateIntegerValue(i));
+    provider.AddPolicy(kPolicyProxyServerMode, Value::CreateIntegerValue(i));
     // No mode expects all three parameters being set.
     provider.AddPolicy(kPolicyProxyPacUrl,
                        Value::CreateStringValue("http://short.org/proxy.pac"));
@@ -349,9 +410,11 @@
     provider.AddPolicy(kPolicyProxyServer,
                        Value::CreateStringValue("chromium.org"));
 
-    ConfigurationPolicyPrefStore store(&provider);
+    scoped_refptr<ConfigurationPolicyPrefStore> store(
+        new ConfigurationPolicyPrefStore(&provider));
+    Value* value = NULL;
     EXPECT_EQ(PrefStore::READ_NO_VALUE,
-              store.GetValue(prefs::kProxyMode, NULL));
+              store->GetValue(prefs::kProxy, &value));
   }
 }
 
@@ -368,31 +431,36 @@
   provider.AddPolicy(kPolicyDefaultSearchProviderSearchURL,
                      Value::CreateStringValue(search_url));
 
-  ConfigurationPolicyPrefStore store(&provider);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
 
   Value* value = NULL;
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
+            store->GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
   EXPECT_TRUE(StringValue(search_url).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderName, &value));
+            store->GetValue(prefs::kDefaultSearchProviderName, &value));
   EXPECT_TRUE(StringValue("test.com").Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderKeyword, &value));
+            store->GetValue(prefs::kDefaultSearchProviderKeyword, &value));
   EXPECT_TRUE(StringValue(std::string()).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
+            store->GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
   EXPECT_TRUE(StringValue(std::string()).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderIconURL, &value));
+            store->GetValue(prefs::kDefaultSearchProviderIconURL, &value));
   EXPECT_TRUE(StringValue(std::string()).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderEncodings, &value));
+            store->GetValue(prefs::kDefaultSearchProviderEncodings, &value));
+  EXPECT_TRUE(StringValue(std::string()).Equals(value));
+
+  EXPECT_EQ(PrefStore::READ_OK,
+            store->GetValue(prefs::kDefaultSearchProviderInstantURL, &value));
   EXPECT_TRUE(StringValue(std::string()).Equals(value));
 }
 
@@ -421,31 +489,32 @@
   provider.AddPolicy(kPolicyDefaultSearchProviderEncodings,
                      Value::CreateStringValue(encodings));
 
-  ConfigurationPolicyPrefStore store(&provider);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
 
   Value* value = NULL;
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
+            store->GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
   EXPECT_TRUE(StringValue(search_url).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderName, &value));
+            store->GetValue(prefs::kDefaultSearchProviderName, &value));
   EXPECT_TRUE(StringValue(name).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderKeyword, &value));
+            store->GetValue(prefs::kDefaultSearchProviderKeyword, &value));
   EXPECT_TRUE(StringValue(keyword).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
+            store->GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
   EXPECT_TRUE(StringValue(suggest_url).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderIconURL, &value));
+            store->GetValue(prefs::kDefaultSearchProviderIconURL, &value));
   EXPECT_TRUE(StringValue(icon_url).Equals(value));
 
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kDefaultSearchProviderEncodings, &value));
+            store->GetValue(prefs::kDefaultSearchProviderEncodings, &value));
   EXPECT_TRUE(StringValue(encodings).Equals(value));
 }
 
@@ -471,20 +540,21 @@
   provider.AddPolicy(kPolicyDefaultSearchProviderEncodings,
                      Value::CreateStringValue(encodings));
 
-  ConfigurationPolicyPrefStore store(&provider);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
 
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderName, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderName, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
 }
 
 // Checks that if the default search policy is invalid, that no elements of the
@@ -512,20 +582,21 @@
   provider.AddPolicy(kPolicyDefaultSearchProviderEncodings,
                      Value::CreateStringValue(encodings));
 
-  ConfigurationPolicyPrefStore store(&provider);
+  scoped_refptr<ConfigurationPolicyPrefStore> store(
+      new ConfigurationPolicyPrefStore(&provider));
 
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderName, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderName, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store.GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
+            store->GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
 }
 
 // Test cases for the Sync policy setting.
@@ -535,23 +606,23 @@
 
 TEST_F(ConfigurationPolicyPrefStoreSyncTest, Default) {
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(prefs::kSyncManaged, NULL));
+            store_->GetValue(prefs::kSyncManaged, NULL));
 }
 
 TEST_F(ConfigurationPolicyPrefStoreSyncTest, Enabled) {
   provider_.AddPolicy(kPolicySyncDisabled, Value::CreateBooleanValue(false));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   // Enabling Sync should not set the pref.
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(prefs::kSyncManaged, NULL));
+            store_->GetValue(prefs::kSyncManaged, NULL));
 }
 
 TEST_F(ConfigurationPolicyPrefStoreSyncTest, Disabled) {
   provider_.AddPolicy(kPolicySyncDisabled, Value::CreateBooleanValue(true));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   // Sync should be flagged as managed.
   Value* value = NULL;
-  EXPECT_EQ(PrefStore::READ_OK, store_.GetValue(prefs::kSyncManaged, &value));
+  EXPECT_EQ(PrefStore::READ_OK, store_->GetValue(prefs::kSyncManaged, &value));
   ASSERT_TRUE(value != NULL);
   EXPECT_TRUE(FundamentalValue(true).Equals(value));
 }
@@ -563,24 +634,24 @@
 
 TEST_F(ConfigurationPolicyPrefStoreAutoFillTest, Default) {
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(prefs::kSyncManaged, NULL));
+            store_->GetValue(prefs::kSyncManaged, NULL));
 }
 
 TEST_F(ConfigurationPolicyPrefStoreAutoFillTest, Enabled) {
   provider_.AddPolicy(kPolicyAutoFillEnabled, Value::CreateBooleanValue(true));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   // Enabling AutoFill should not set the pref.
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(prefs::kSyncManaged, NULL));
+            store_->GetValue(prefs::kSyncManaged, NULL));
 }
 
 TEST_F(ConfigurationPolicyPrefStoreAutoFillTest, Disabled) {
   provider_.AddPolicy(kPolicyAutoFillEnabled, Value::CreateBooleanValue(false));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   // Disabling AutoFill should switch the pref to managed.
   Value* value = NULL;
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(prefs::kAutoFillEnabled, &value));
+            store_->GetValue(prefs::kAutoFillEnabled, &value));
   EXPECT_TRUE(FundamentalValue(false).Equals(value));
 }
 
@@ -589,11 +660,11 @@
     : public ConfigurationPolicyPrefStoreTestBase<testing::Test> {
  protected:
   virtual void SetUp() {
-    store_.AddObserver(&observer_);
+    store_->AddObserver(&observer_);
   }
 
   virtual void TearDown() {
-    store_.RemoveObserver(&observer_);
+    store_->RemoveObserver(&observer_);
   }
 
   PrefStoreObserverMock observer_;
@@ -602,40 +673,40 @@
 TEST_F(ConfigurationPolicyPrefStoreRefreshTest, Refresh) {
   Value* value = NULL;
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(prefs::kHomePage, NULL));
+            store_->GetValue(prefs::kHomePage, NULL));
 
   EXPECT_CALL(observer_, OnPrefValueChanged(prefs::kHomePage)).Times(1);
-  provider_.AddPolicy(kPolicyHomePage,
+  provider_.AddPolicy(kPolicyHomepageLocation,
                       Value::CreateStringValue("http://www.chromium.org"));
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Mock::VerifyAndClearExpectations(&observer_);
   EXPECT_EQ(PrefStore::READ_OK,
-            store_.GetValue(prefs::kHomePage, &value));
+            store_->GetValue(prefs::kHomePage, &value));
   EXPECT_TRUE(StringValue("http://www.chromium.org").Equals(value));
 
   EXPECT_CALL(observer_, OnPrefValueChanged(_)).Times(0);
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Mock::VerifyAndClearExpectations(&observer_);
 
   EXPECT_CALL(observer_, OnPrefValueChanged(prefs::kHomePage)).Times(1);
-  provider_.RemovePolicy(kPolicyHomePage);
-  store_.OnUpdatePolicy();
+  provider_.RemovePolicy(kPolicyHomepageLocation);
+  store_->OnUpdatePolicy();
   Mock::VerifyAndClearExpectations(&observer_);
   EXPECT_EQ(PrefStore::READ_NO_VALUE,
-            store_.GetValue(prefs::kHomePage, NULL));
+            store_->GetValue(prefs::kHomePage, NULL));
 }
 
 TEST_F(ConfigurationPolicyPrefStoreRefreshTest, Initialization) {
-  EXPECT_FALSE(store_.IsInitializationComplete());
+  EXPECT_FALSE(store_->IsInitializationComplete());
 
   EXPECT_CALL(observer_, OnInitializationCompleted()).Times(1);
 
   provider_.SetInitializationComplete(true);
-  EXPECT_FALSE(store_.IsInitializationComplete());
+  EXPECT_FALSE(store_->IsInitializationComplete());
 
-  store_.OnUpdatePolicy();
+  store_->OnUpdatePolicy();
   Mock::VerifyAndClearExpectations(&observer_);
-  EXPECT_TRUE(store_.IsInitializationComplete());
+  EXPECT_TRUE(store_->IsInitializationComplete());
 }
 
 }  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_provider.cc b/chrome/browser/policy/configuration_policy_provider.cc
index 3b82134..82ca864 100644
--- a/chrome/browser/policy/configuration_policy_provider.cc
+++ b/chrome/browser/policy/configuration_policy_provider.cc
@@ -17,6 +17,10 @@
 
 ConfigurationPolicyProvider::~ConfigurationPolicyProvider() {}
 
+bool ConfigurationPolicyProvider::IsInitializationComplete() const {
+  return true;
+}
+
 void ConfigurationPolicyProvider::DecodePolicyValueTree(
     const DictionaryValue* policies,
     ConfigurationPolicyStoreInterface* store) {
@@ -34,7 +38,9 @@
 
 // Class ConfigurationPolicyObserverRegistrar.
 
-ConfigurationPolicyObserverRegistrar::ConfigurationPolicyObserverRegistrar() {}
+ConfigurationPolicyObserverRegistrar::ConfigurationPolicyObserverRegistrar()
+  : provider_(NULL),
+    observer_(NULL) {}
 
 ConfigurationPolicyObserverRegistrar::~ConfigurationPolicyObserverRegistrar() {
   if (provider_)
diff --git a/chrome/browser/policy/configuration_policy_provider.h b/chrome/browser/policy/configuration_policy_provider.h
index 81c1813..af2cddf 100644
--- a/chrome/browser/policy/configuration_policy_provider.h
+++ b/chrome/browser/policy/configuration_policy_provider.h
@@ -55,7 +55,7 @@
   // Check whether this provider has completed initialization. This is used to
   // detect whether initialization is done in case providers implementations
   // need to do asynchronous operations for initialization.
-  virtual bool IsInitializationComplete() const { return true; }
+  virtual bool IsInitializationComplete() const;
 
  protected:
   // Decodes the value tree and writes the configuration to the given |store|.
diff --git a/chrome/browser/policy/configuration_policy_provider_delegate_win.cc b/chrome/browser/policy/configuration_policy_provider_delegate_win.cc
index 68947de..7e93486 100644
--- a/chrome/browser/policy/configuration_policy_provider_delegate_win.cc
+++ b/chrome/browser/policy/configuration_policy_provider_delegate_win.cc
@@ -7,7 +7,7 @@
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/win/registry.h"
-#include "chrome/common/policy_constants.h"
+#include "policy/policy_constants.h"
 
 using base::win::RegKey;
 
@@ -19,7 +19,7 @@
   DWORD key_type = 0;
   scoped_array<uint8> buffer;
 
-  if (!key->ReadValue(name.c_str(), 0, &value_size, &key_type))
+  if (key->ReadValue(name.c_str(), 0, &value_size, &key_type) != ERROR_SUCCESS)
     return false;
   if (key_type != REG_SZ)
     return false;
@@ -89,16 +89,14 @@
 
 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyString(
     const string16& name, string16* result) const {
-  string16 path = string16(kRegistrySubKey);
-  RegKey policy_key;
+  RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
   // First try the global policy.
-  if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
-    if (ReadRegistryStringValue(&policy_key, name, result))
-      return true;
-    policy_key.Close();
-  }
+  if (ReadRegistryStringValue(&policy_key, name, result))
+    return true;
+
   // Fall back on user-specific policy.
-  if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
+  if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey,
+                      KEY_READ) != ERROR_SUCCESS)
     return false;
   return ReadRegistryStringValue(&policy_key, name, result);
 }
@@ -108,10 +106,11 @@
   string16 path = string16(kRegistrySubKey);
   path += ASCIIToUTF16("\\") + key;
   RegKey policy_key;
-  if (!policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
-    policy_key.Close();
+  if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ) !=
+      ERROR_SUCCESS) {
     // Fall back on user-specific policy.
-    if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
+    if (policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ) !=
+        ERROR_SUCCESS)
       return false;
   }
   string16 policy_string;
@@ -125,34 +124,28 @@
 
 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyBoolean(
     const string16& value_name, bool* result) const {
-  DWORD value;
-  RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
-  if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
-    *result = value != 0;
-    return true;
-  }
-
-  RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
-  if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
-    *result = value != 0;
-    return true;
-  }
-  return false;
+  uint32 local_result = 0;
+  bool ret = GetRegistryPolicyInteger(value_name, &local_result);
+  if (ret)
+    *result = local_result != 0;
+  return ret;
 }
 
 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyInteger(
     const string16& value_name, uint32* result) const {
-  DWORD value;
-  RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
-  if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
+  DWORD value = 0;
+  RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
+  if (policy_key.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) {
     *result = value;
     return true;
   }
 
-  RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
-  if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
-    *result = value;
-    return true;
+  if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
+      ERROR_SUCCESS) {
+    if (policy_key.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) {
+      *result = value;
+      return true;
+    }
   }
   return false;
 }
diff --git a/chrome/browser/policy/configuration_policy_provider_keeper.cc b/chrome/browser/policy/configuration_policy_provider_keeper.cc
index 768bb93..9959f74 100644
--- a/chrome/browser/policy/configuration_policy_provider_keeper.cc
+++ b/chrome/browser/policy/configuration_policy_provider_keeper.cc
@@ -34,6 +34,8 @@
       recommended_provider_(recommended_provider) {
 }
 
+ConfigurationPolicyProviderKeeper::~ConfigurationPolicyProviderKeeper() {}
+
 ConfigurationPolicyProvider*
     ConfigurationPolicyProviderKeeper::managed_platform_provider() const {
   return managed_platform_provider_.get();
diff --git a/chrome/browser/policy/configuration_policy_provider_keeper.h b/chrome/browser/policy/configuration_policy_provider_keeper.h
index 6994de4..1156cb4 100644
--- a/chrome/browser/policy/configuration_policy_provider_keeper.h
+++ b/chrome/browser/policy/configuration_policy_provider_keeper.h
@@ -21,7 +21,7 @@
       ConfigurationPolicyProvider* managed_platform_provider,
       ConfigurationPolicyProvider* device_management_provider,
       ConfigurationPolicyProvider* recommended_provider);
-  virtual ~ConfigurationPolicyProviderKeeper() {}
+  virtual ~ConfigurationPolicyProviderKeeper();
 
   ConfigurationPolicyProvider* managed_platform_provider() const;
 
diff --git a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
index 345a3f6..fae2597 100644
--- a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,7 @@
 #include "chrome/browser/policy/configuration_policy_provider_mac.h"
 #include "chrome/browser/policy/mock_configuration_policy_store.h"
 #include "chrome/browser/preferences_mock_mac.h"
-#include "chrome/common/policy_constants.h"
+#include "policy/policy_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -200,7 +200,7 @@
     ConfigurationPolicyProviderMacTest,
     testing::Values(
         PolicyTestParams::ForStringPolicy(
-            kPolicyHomePage,
+            kPolicyHomepageLocation,
             key::kHomepageLocation),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyHomepageIsNewTabPage,
@@ -209,8 +209,8 @@
             kPolicyRestoreOnStartup,
             key::kRestoreOnStartup),
         PolicyTestParams::ForListPolicy(
-            kPolicyURLsToRestoreOnStartup,
-            key::kURLsToRestoreOnStartup),
+            kPolicyRestoreOnStartupURLs,
+            key::kRestoreOnStartupURLs),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyDefaultSearchProviderEnabled,
             key::kDefaultSearchProviderEnabled),
@@ -227,14 +227,20 @@
             kPolicyDefaultSearchProviderSuggestURL,
             key::kDefaultSearchProviderSuggestURL),
         PolicyTestParams::ForStringPolicy(
+            kPolicyDefaultSearchProviderInstantURL,
+            key::kDefaultSearchProviderInstantURL),
+        PolicyTestParams::ForStringPolicy(
             kPolicyDefaultSearchProviderIconURL,
             key::kDefaultSearchProviderIconURL),
         PolicyTestParams::ForStringPolicy(
             kPolicyDefaultSearchProviderEncodings,
             key::kDefaultSearchProviderEncodings),
-        PolicyTestParams::ForIntegerPolicy(
+        PolicyTestParams::ForStringPolicy(
             kPolicyProxyMode,
             key::kProxyMode),
+        PolicyTestParams::ForIntegerPolicy(
+            kPolicyProxyServerMode,
+            key::kProxyServerMode),
         PolicyTestParams::ForStringPolicy(
             kPolicyProxyServer,
             key::kProxyServer),
@@ -272,22 +278,31 @@
             kPolicyAutoFillEnabled,
             key::kAutoFillEnabled),
         PolicyTestParams::ForStringPolicy(
-            kPolicyApplicationLocale,
+            kPolicyApplicationLocaleValue,
             key::kApplicationLocaleValue),
         PolicyTestParams::ForBooleanPolicy(
             kPolicySyncDisabled,
             key::kSyncDisabled),
         PolicyTestParams::ForListPolicy(
-            kPolicyExtensionInstallAllowList,
-            key::kExtensionInstallAllowList),
+            kPolicyExtensionInstallWhitelist,
+            key::kExtensionInstallWhitelist),
         PolicyTestParams::ForListPolicy(
-            kPolicyExtensionInstallDenyList,
-            key::kExtensionInstallDenyList),
+            kPolicyExtensionInstallBlacklist,
+            key::kExtensionInstallBlacklist),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyShowHomeButton,
             key::kShowHomeButton),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyPrintingEnabled,
-            key::kPrintingEnabled)));
+            key::kPrintingEnabled),
+        PolicyTestParams::ForBooleanPolicy(
+            kPolicyInstantEnabled,
+            key::kInstantEnabled),
+        PolicyTestParams::ForIntegerPolicy(
+            kPolicyPolicyRefreshRate,
+            key::kPolicyRefreshRate),
+        PolicyTestParams::ForBooleanPolicy(
+            kPolicyCloudPrintProxyEnabled,
+            key::kCloudPrintProxyEnabled)));
 
 }  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
index beed450..b929e4a 100644
--- a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,8 +17,8 @@
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/policy/configuration_policy_provider_win.h"
 #include "chrome/browser/policy/mock_configuration_policy_store.h"
-#include "chrome/common/policy_constants.h"
 #include "chrome/common/pref_names.h"
+#include "policy/policy_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::win::RegKey;
@@ -358,7 +358,7 @@
     ConfigurationPolicyProviderWinTest,
     testing::Values(
         PolicyTestParams::ForStringPolicy(
-            kPolicyHomePage,
+            kPolicyHomepageLocation,
             key::kHomepageLocation),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyHomepageIsNewTabPage,
@@ -367,8 +367,8 @@
             kPolicyRestoreOnStartup,
             key::kRestoreOnStartup),
         PolicyTestParams::ForListPolicy(
-            kPolicyURLsToRestoreOnStartup,
-            key::kURLsToRestoreOnStartup),
+            kPolicyRestoreOnStartupURLs,
+            key::kRestoreOnStartupURLs),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyDefaultSearchProviderEnabled,
             key::kDefaultSearchProviderEnabled),
@@ -385,14 +385,20 @@
             kPolicyDefaultSearchProviderSuggestURL,
             key::kDefaultSearchProviderSuggestURL),
         PolicyTestParams::ForStringPolicy(
+            kPolicyDefaultSearchProviderInstantURL,
+            key::kDefaultSearchProviderInstantURL),
+        PolicyTestParams::ForStringPolicy(
             kPolicyDefaultSearchProviderIconURL,
             key::kDefaultSearchProviderIconURL),
         PolicyTestParams::ForStringPolicy(
             kPolicyDefaultSearchProviderEncodings,
             key::kDefaultSearchProviderEncodings),
-        PolicyTestParams::ForIntegerPolicy(
+        PolicyTestParams::ForStringPolicy(
             kPolicyProxyMode,
             key::kProxyMode),
+        PolicyTestParams::ForIntegerPolicy(
+            kPolicyProxyServerMode,
+            key::kProxyServerMode),
         PolicyTestParams::ForStringPolicy(
             kPolicyProxyServer,
             key::kProxyServer),
@@ -430,19 +436,31 @@
             kPolicySyncDisabled,
             key::kSyncDisabled),
         PolicyTestParams::ForStringPolicy(
-            kPolicyApplicationLocale,
+            kPolicyApplicationLocaleValue,
             key::kApplicationLocaleValue),
         PolicyTestParams::ForListPolicy(
-            kPolicyExtensionInstallAllowList,
-            key::kExtensionInstallAllowList),
+            kPolicyExtensionInstallWhitelist,
+            key::kExtensionInstallWhitelist),
         PolicyTestParams::ForListPolicy(
-            kPolicyExtensionInstallDenyList,
-            key::kExtensionInstallDenyList),
+            kPolicyExtensionInstallBlacklist,
+            key::kExtensionInstallBlacklist),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyShowHomeButton,
             key::kShowHomeButton),
         PolicyTestParams::ForBooleanPolicy(
             kPolicyPrintingEnabled,
-            key::kPrintingEnabled)));
+            key::kPrintingEnabled),
+        PolicyTestParams::ForIntegerPolicy(
+            kPolicyPolicyRefreshRate,
+            key::kPolicyRefreshRate),
+        PolicyTestParams::ForBooleanPolicy(
+            kPolicyInstantEnabled,
+            key::kInstantEnabled),
+        PolicyTestParams::ForBooleanPolicy(
+            kPolicyIncognitoEnabled,
+            key::kIncognitoEnabled),
+        PolicyTestParams::ForBooleanPolicy(
+            kPolicyCloudPrintProxyEnabled,
+            key::kCloudPrintProxyEnabled)));
 
 }  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_store_interface.h b/chrome/browser/policy/configuration_policy_store_interface.h
index b6d1f3b..d3261a3 100644
--- a/chrome/browser/policy/configuration_policy_store_interface.h
+++ b/chrome/browser/policy/configuration_policy_store_interface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,69 +7,14 @@
 #pragma once
 
 #include "base/basictypes.h"
+// configuration_policy_type.h is generated. See policy_template.json for
+// policy definitions.
+#include "policy/configuration_policy_type.h"
 
 class Value;
 
 namespace policy {
 
-enum ConfigurationPolicyType {
-  kPolicyHomePage,
-  kPolicyHomepageIsNewTabPage,
-  kPolicyRestoreOnStartup,
-  kPolicyURLsToRestoreOnStartup,
-  kPolicyDefaultSearchProviderEnabled,
-  kPolicyDefaultSearchProviderName,
-  kPolicyDefaultSearchProviderKeyword,
-  kPolicyDefaultSearchProviderSearchURL,
-  kPolicyDefaultSearchProviderSuggestURL,
-  kPolicyDefaultSearchProviderIconURL,
-  kPolicyDefaultSearchProviderEncodings,
-  kPolicyDisableSpdy,
-  kPolicyProxyMode,
-  kPolicyProxyServer,
-  kPolicyProxyPacUrl,
-  kPolicyProxyBypassList,
-  kPolicyAlternateErrorPagesEnabled,
-  kPolicySearchSuggestEnabled,
-  kPolicyDnsPrefetchingEnabled,
-  kPolicySafeBrowsingEnabled,
-  kPolicyMetricsReportingEnabled,
-  kPolicyPasswordManagerEnabled,
-  kPolicyPasswordManagerAllowShowPasswords,
-  kPolicyAutoFillEnabled,
-  kPolicySyncDisabled,
-  kPolicyApplicationLocale,
-  kPolicyExtensionInstallAllowList,
-  kPolicyExtensionInstallDenyList,
-  kPolicyShowHomeButton,
-  kPolicyDisabledPlugins,
-  kPolicyPrintingEnabled,
-  kPolicyChromeFrameRendererSettings,
-  kPolicyRenderInChromeFrameList,
-  kPolicyRenderInHostList,
-  kPolicyJavascriptEnabled,
-  kPolicySavingBrowserHistoryDisabled,
-  kPolicyDeveloperToolsDisabled,
-  kPolicyBlockThirdPartyCookies,
-  kPolicyDefaultCookiesSetting,
-  kPolicyDefaultImagesSetting,
-  kPolicyDefaultJavaScriptSetting,
-  kPolicyDefaultPluginsSetting,
-  kPolicyDefaultPopupsSetting,
-  kPolicyDefaultNotificationSetting,
-  kPolicyDefaultGeolocationSetting,
-  kPolicyExtensionInstallForceList,
-  kPolicyChromeOsLockOnIdleSuspend,
-  kPolicyAuthSchemes,
-  kPolicyDisableAuthNegotiateCnameLookup,
-  kPolicyEnableAuthNegotiatePort,
-  kPolicyAuthServerWhitelist,
-  kPolicyAuthNegotiateDelegateWhitelist,
-  kPolicyGSSAPILibraryName,
-  kPolicyDisable3DAPIs
-};
-
-
 // Constants for the "Proxy Server Mode" defined in the policies.
 // Note that these diverge from internal presentation defined in
 // ProxyPrefs::ProxyMode for legacy reasons. The following four
@@ -79,11 +24,11 @@
   // Disable Proxy, connect directly.
   kPolicyNoProxyServerMode = 0,
   // Auto detect proxy or use specific PAC script if given.
-  kPolicyAutoDetectProxyMode = 1,
+  kPolicyAutoDetectProxyServerMode = 1,
   // Use manually configured proxy servers (fixed servers).
-  kPolicyManuallyConfiguredProxyMode = 2,
+  kPolicyManuallyConfiguredProxyServerMode = 2,
   // Use system proxy server.
-  kPolicyUseSystemProxyMode = 3,
+  kPolicyUseSystemProxyServerMode = 3,
 
   MODE_COUNT
 };
diff --git a/chrome/browser/policy/device_management_backend_impl.cc b/chrome/browser/policy/device_management_backend_impl.cc
index d479c80..ed75f3f 100644
--- a/chrome/browser/policy/device_management_backend_impl.cc
+++ b/chrome/browser/policy/device_management_backend_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -39,6 +39,8 @@
 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth=";
 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token=";
 
+}  // namespace
+
 // Helper class for URL query parameter encoding/decoding.
 class URLQueryParameters {
  public:
@@ -77,8 +79,6 @@
   return result;
 }
 
-}  // namespace
-
 // A base class containing the common code for the jobs created by the backend
 // implementation. Subclasses provide custom code for handling actual register,
 // unregister, and policy jobs.
@@ -90,7 +90,7 @@
   }
 
   // DeviceManagementJob overrides:
-  virtual void HandleResponse(const URLRequestStatus& status,
+  virtual void HandleResponse(const net::URLRequestStatus& status,
                               int response_code,
                               const ResponseCookies& cookies,
                               const std::string& data);
@@ -156,14 +156,15 @@
   DISALLOW_COPY_AND_ASSIGN(DeviceManagementJobBase);
 };
 
-void DeviceManagementJobBase::HandleResponse(const URLRequestStatus& status,
-                                             int response_code,
-                                             const ResponseCookies& cookies,
-                                             const std::string& data) {
+void DeviceManagementJobBase::HandleResponse(
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
+    const std::string& data) {
   // Delete ourselves when this is done.
   scoped_ptr<DeviceManagementJob> scoped_killer(this);
 
-  if (status.status() != URLRequestStatus::SUCCESS) {
+  if (status.status() != net::URLRequestStatus::SUCCESS) {
     OnError(DeviceManagementBackend::kErrorRequestFailed);
     return;
   }
diff --git a/chrome/browser/policy/device_management_policy_cache.cc b/chrome/browser/policy/device_management_policy_cache.cc
index ab5dd15..ef8e6e1 100644
--- a/chrome/browser/policy/device_management_policy_cache.cc
+++ b/chrome/browser/policy/device_management_policy_cache.cc
@@ -104,7 +104,7 @@
   // Decode and swap in the new policy information.
   scoped_ptr<DictionaryValue> value(DecodePolicy(cached_policy.policy()));
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     if (!fresh_policy_)
       policy_.reset(value.release());
     last_policy_refresh_time_ = timestamp;
@@ -118,7 +118,7 @@
   const bool new_policy_differs = !(value->Equals(policy_.get()));
   base::Time now(base::Time::NowFromSystemTime());
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     policy_.reset(value);
     fresh_policy_ = true;
     last_policy_refresh_time_ = now;
@@ -134,30 +134,22 @@
 }
 
 DictionaryValue* DeviceManagementPolicyCache::GetPolicy() {
-  AutoLock lock(lock_);
-  return static_cast<DictionaryValue*>(policy_->DeepCopy());
+  base::AutoLock lock(lock_);
+  return policy_->DeepCopy();
 }
 
-void DeviceManagementPolicyCache::SetDeviceUnmanaged(bool is_device_unmanaged) {
-  if (is_device_unmanaged_ == is_device_unmanaged)
-    return;
-
-  is_device_unmanaged_ = is_device_unmanaged;
+void DeviceManagementPolicyCache::SetDeviceUnmanaged() {
+  is_device_unmanaged_ = true;
   base::Time now(base::Time::NowFromSystemTime());
-  DictionaryValue* empty = new DictionaryValue();
   {
-    AutoLock lock(lock_);
-    policy_.reset(empty);
+    base::AutoLock lock(lock_);
+    policy_.reset(new DictionaryValue);
     last_policy_refresh_time_ = now;
   }
   BrowserThread::PostTask(
       BrowserThread::FILE,
       FROM_HERE,
-      new PersistPolicyTask(backing_file_path_,
-                            (is_device_unmanaged ? NULL
-                                : new em::DevicePolicyResponse()),
-                            now,
-                            is_device_unmanaged_));
+      new PersistPolicyTask(backing_file_path_, NULL, now, true));
 }
 
 // static
@@ -193,7 +185,7 @@
       return NULL;
     case em::GenericValue::VALUE_TYPE_DOUBLE:
       if (value.has_double_value())
-        return Value::CreateRealValue(value.double_value());
+        return Value::CreateDoubleValue(value.double_value());
       return NULL;
     case em::GenericValue::VALUE_TYPE_BYTES:
       if (value.has_bytes_value()) {
@@ -232,7 +224,7 @@
       RepeatedField<double>::const_iterator i;
       for (i = value.double_array().begin();
            i != value.double_array().end(); ++i)
-        list->Append(Value::CreateRealValue(*i));
+        list->Append(Value::CreateDoubleValue(*i));
       return list;
     }
     default:
diff --git a/chrome/browser/policy/device_management_policy_cache.h b/chrome/browser/policy/device_management_policy_cache.h
index 9c09a07..50441eb 100644
--- a/chrome/browser/policy/device_management_policy_cache.h
+++ b/chrome/browser/policy/device_management_policy_cache.h
@@ -7,9 +7,9 @@
 
 #include "base/file_path.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
 
@@ -42,7 +42,7 @@
   // to the caller.
   DictionaryValue* GetPolicy();
 
-  void SetDeviceUnmanaged(bool is_device_unmanaged);
+  void SetDeviceUnmanaged();
   bool is_device_unmanaged() const {
     return is_device_unmanaged_;
   }
@@ -74,7 +74,7 @@
   const FilePath backing_file_path_;
 
   // Protects |policy_|.
-  Lock lock_;
+  base::Lock lock_;
 
   // Policy key-value information.
   scoped_ptr<DictionaryValue> policy_;
diff --git a/chrome/browser/policy/device_management_policy_cache_unittest.cc b/chrome/browser/policy/device_management_policy_cache_unittest.cc
index e1482f1..1fe98c8 100644
--- a/chrome/browser/policy/device_management_policy_cache_unittest.cc
+++ b/chrome/browser/policy/device_management_policy_cache_unittest.cc
@@ -257,7 +257,7 @@
 TEST_F(DeviceManagementPolicyCacheDecodeTest, Double) {
   value_.set_value_type(em::GenericValue::VALUE_TYPE_DOUBLE);
   value_.set_double_value(0.42L);
-  DecodeAndCheck(Value::CreateRealValue(0.42L));
+  DecodeAndCheck(Value::CreateDoubleValue(0.42L));
 }
 
 TEST_F(DeviceManagementPolicyCacheDecodeTest, Bytes) {
@@ -303,8 +303,8 @@
   value_.add_double_array(0.42L);
   value_.add_double_array(0.17L);
   ListValue* list = new ListValue;
-  list->Append(Value::CreateRealValue(0.42L));
-  list->Append(Value::CreateRealValue(0.17L));
+  list->Append(Value::CreateDoubleValue(0.42L));
+  list->Append(Value::CreateDoubleValue(0.17L));
   DecodeAndCheck(list);
 }
 
diff --git a/chrome/browser/policy/device_management_policy_provider.cc b/chrome/browser/policy/device_management_policy_provider.cc
index 8b9d9b4..315a6d2 100644
--- a/chrome/browser/policy/device_management_policy_provider.cc
+++ b/chrome/browser/policy/device_management_policy_provider.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/policy/device_management_backend.h"
 #include "chrome/browser/policy/device_management_policy_cache.h"
+#include "chrome/browser/policy/profile_policy_context.h"
 #include "chrome/browser/policy/proto/device_management_constants.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
@@ -23,8 +24,13 @@
 
 namespace em = enterprise_management;
 
-const int64 kPolicyRefreshRateInMilliseconds = 3 * 60 * 60 * 1000;  // 3 hours
-const int64 kPolicyRefreshMaxEarlierInMilliseconds = 20 * 60 * 1000;  // 20 mins
+// The maximum ratio in percent of the policy refresh rate we use for adjusting
+// the policy refresh time instant. The rationale is to avoid load spikes from
+// many devices that were set up in sync for some reason.
+const int kPolicyRefreshDeviationFactorPercent = 10;
+// Maximum deviation we are willing to accept.
+const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000;
+
 // These are the base values for delays before retrying after an error. They
 // will be doubled each time they are used.
 const int64 kPolicyRefreshErrorDelayInMilliseconds = 3 * 1000;  // 3 seconds
@@ -35,44 +41,25 @@
 const FilePath::StringType kDeviceTokenFilename = FILE_PATH_LITERAL("Token");
 const FilePath::StringType kPolicyFilename = FILE_PATH_LITERAL("Policy");
 
-// Ensures that the portion of the policy provider implementation that requires
-// the IOThread is deferred until the IOThread is fully initialized. The policy
-// provider posts this task on the UI thread during its constructor, thereby
-// guaranteeing that the code won't get executed until after the UI and IO
-// threads are fully constructed.
-class DeviceManagementPolicyProvider::InitializeAfterIOThreadExistsTask
-    : public Task {
+// Calls back into the provider to refresh policy.
+class DeviceManagementPolicyProvider::RefreshTask : public CancelableTask {
  public:
-  explicit InitializeAfterIOThreadExistsTask(
-      base::WeakPtr<DeviceManagementPolicyProvider> provider)
-      : provider_(provider) {
-  }
-
-  // Task implementation:
-  virtual void Run() {
-    DeviceManagementPolicyProvider* provider = provider_.get();
-    if (provider)
-      provider->InitializeAfterIOThreadExists();
-  }
-
- private:
-  base::WeakPtr<DeviceManagementPolicyProvider> provider_;
-};
-
-class DeviceManagementPolicyProvider::RefreshTask : public Task {
- public:
-  explicit RefreshTask(base::WeakPtr<DeviceManagementPolicyProvider> provider)
+  explicit RefreshTask(DeviceManagementPolicyProvider* provider)
       : provider_(provider) {}
 
   // Task implementation:
   virtual void Run() {
-    DeviceManagementPolicyProvider* provider = provider_.get();
-    if (provider)
-      provider->RefreshTaskExecute();
+    if (provider_)
+      provider_->RefreshTaskExecute();
+  }
+
+  // CancelableTask implementation:
+  virtual void Cancel() {
+    provider_ = NULL;
   }
 
  private:
-  base::WeakPtr<DeviceManagementPolicyProvider> provider_;
+  DeviceManagementPolicyProvider* provider_;
 };
 
 DeviceManagementPolicyProvider::DeviceManagementPolicyProvider(
@@ -82,36 +69,19 @@
     : ConfigurationPolicyProvider(policy_list) {
   Initialize(backend,
              profile,
-             kPolicyRefreshRateInMilliseconds,
-             kPolicyRefreshMaxEarlierInMilliseconds,
+             ProfilePolicyContext::kDefaultPolicyRefreshRateInMilliseconds,
+             kPolicyRefreshDeviationFactorPercent,
+             kPolicyRefreshDeviationMaxInMilliseconds,
              kPolicyRefreshErrorDelayInMilliseconds,
              kDeviceTokenRefreshErrorDelayInMilliseconds,
              kPolicyRefreshUnmanagedDeviceInMilliseconds);
 }
 
-DeviceManagementPolicyProvider::DeviceManagementPolicyProvider(
-    const PolicyDefinitionList* policy_list,
-    DeviceManagementBackend* backend,
-    Profile* profile,
-    int64 policy_refresh_rate_ms,
-    int64 policy_refresh_max_earlier_ms,
-    int64 policy_refresh_error_delay_ms,
-    int64 token_fetch_error_delay_ms,
-    int64 unmanaged_device_refresh_rate_ms)
-    : ConfigurationPolicyProvider(policy_list) {
-  Initialize(backend,
-             profile,
-             policy_refresh_rate_ms,
-             policy_refresh_max_earlier_ms,
-             policy_refresh_error_delay_ms,
-             token_fetch_error_delay_ms,
-             unmanaged_device_refresh_rate_ms);
-}
-
 DeviceManagementPolicyProvider::~DeviceManagementPolicyProvider() {
   FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
                     observer_list_,
                     OnProviderGoingAway());
+  CancelRefreshTask();
 }
 
 bool DeviceManagementPolicyProvider::Provide(
@@ -122,69 +92,127 @@
 }
 
 bool DeviceManagementPolicyProvider::IsInitializationComplete() const {
-  return !waiting_for_initial_policies_;
+  return !cache_->last_policy_refresh_time().is_null();
 }
 
 void DeviceManagementPolicyProvider::HandlePolicyResponse(
     const em::DevicePolicyResponse& response) {
-  if (cache_->SetPolicy(response))
+  DCHECK(TokenAvailable());
+  if (cache_->SetPolicy(response)) {
+    initial_fetch_done_ = true;
     NotifyCloudPolicyUpdate();
-  policy_request_pending_ = false;
-  // Reset the error delay since policy fetching succeeded this time.
-  policy_refresh_error_delay_ms_ = kPolicyRefreshErrorDelayInMilliseconds;
-  ScheduleRefreshTask(GetRefreshTaskDelay());
-  // Update this provider's internal waiting state, but don't notify anyone
-  // else yet (that's done by the PrefValueStore that receives the policy).
-  waiting_for_initial_policies_ = false;
+  }
+  SetState(STATE_POLICY_VALID);
 }
 
 void DeviceManagementPolicyProvider::OnError(
     DeviceManagementBackend::ErrorCode code) {
-  policy_request_pending_ = false;
+  DCHECK(TokenAvailable());
   if (code == DeviceManagementBackend::kErrorServiceDeviceNotFound ||
       code == DeviceManagementBackend::kErrorServiceManagementTokenInvalid) {
     LOG(WARNING) << "The device token was either invalid or unknown to the "
                  << "device manager, re-registering device.";
-    token_fetcher_->Restart();
+    SetState(STATE_TOKEN_RESET);
   } else if (code ==
              DeviceManagementBackend::kErrorServiceManagementNotSupported) {
     VLOG(1) << "The device is no longer managed, resetting device token.";
-    token_fetcher_->Restart();
+    SetState(STATE_TOKEN_RESET);
   } else {
     LOG(WARNING) << "Could not provide policy from the device manager (error = "
                  << code << "), will retry in "
-                 << (policy_refresh_error_delay_ms_/1000) << " seconds.";
-    ScheduleRefreshTask(policy_refresh_error_delay_ms_);
-    policy_refresh_error_delay_ms_ *= 2;
-    if (policy_refresh_rate_ms_ &&
-        policy_refresh_rate_ms_ < policy_refresh_error_delay_ms_) {
-      policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
-    }
+                 << (effective_policy_refresh_error_delay_ms_ / 1000)
+                 << " seconds.";
+    SetState(STATE_POLICY_ERROR);
   }
-  StopWaitingForInitialPolicies();
 }
 
 void DeviceManagementPolicyProvider::OnTokenSuccess() {
-  if (policy_request_pending_)
-    return;
-  cache_->SetDeviceUnmanaged(false);
-  SendPolicyRequest();
+  DCHECK(!TokenAvailable());
+  SetState(STATE_TOKEN_VALID);
 }
 
 void DeviceManagementPolicyProvider::OnTokenError() {
+  DCHECK(!TokenAvailable());
   LOG(WARNING) << "Could not retrieve device token.";
-  ScheduleRefreshTask(token_fetch_error_delay_ms_);
-  token_fetch_error_delay_ms_ *= 2;
-  if (token_fetch_error_delay_ms_ > policy_refresh_rate_ms_)
-    token_fetch_error_delay_ms_ = policy_refresh_rate_ms_;
-  StopWaitingForInitialPolicies();
+  SetState(STATE_TOKEN_ERROR);
 }
 
 void DeviceManagementPolicyProvider::OnNotManaged() {
+  DCHECK(!TokenAvailable());
   VLOG(1) << "This device is not managed.";
-  cache_->SetDeviceUnmanaged(true);
-  ScheduleRefreshTask(unmanaged_device_refresh_rate_ms_);
-  StopWaitingForInitialPolicies();
+  cache_->SetDeviceUnmanaged();
+  SetState(STATE_UNMANAGED);
+}
+
+void DeviceManagementPolicyProvider::SetRefreshRate(
+    int64 refresh_rate_milliseconds) {
+  policy_refresh_rate_ms_ = refresh_rate_milliseconds;
+
+  // Reschedule the refresh task if necessary.
+  if (state_ == STATE_POLICY_VALID)
+    SetState(STATE_POLICY_VALID);
+}
+
+DeviceManagementPolicyProvider::DeviceManagementPolicyProvider(
+    const PolicyDefinitionList* policy_list,
+    DeviceManagementBackend* backend,
+    Profile* profile,
+    int64 policy_refresh_rate_ms,
+    int policy_refresh_deviation_factor_percent,
+    int64 policy_refresh_deviation_max_ms,
+    int64 policy_refresh_error_delay_ms,
+    int64 token_fetch_error_delay_ms,
+    int64 unmanaged_device_refresh_rate_ms)
+    : ConfigurationPolicyProvider(policy_list) {
+  Initialize(backend,
+             profile,
+             policy_refresh_rate_ms,
+             policy_refresh_deviation_factor_percent,
+             policy_refresh_deviation_max_ms,
+             policy_refresh_error_delay_ms,
+             token_fetch_error_delay_ms,
+             unmanaged_device_refresh_rate_ms);
+}
+
+void DeviceManagementPolicyProvider::Initialize(
+    DeviceManagementBackend* backend,
+    Profile* profile,
+    int64 policy_refresh_rate_ms,
+    int policy_refresh_deviation_factor_percent,
+    int64 policy_refresh_deviation_max_ms,
+    int64 policy_refresh_error_delay_ms,
+    int64 token_fetch_error_delay_ms,
+    int64 unmanaged_device_refresh_rate_ms) {
+  DCHECK(profile);
+  backend_.reset(backend);
+  profile_ = profile;
+  storage_dir_ = GetOrCreateDeviceManagementDir(profile_->GetPath());
+  state_ = STATE_INITIALIZING;
+  initial_fetch_done_ = false;
+  refresh_task_ = NULL;
+  policy_refresh_rate_ms_ = policy_refresh_rate_ms;
+  policy_refresh_deviation_factor_percent_ =
+      policy_refresh_deviation_factor_percent;
+  policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms;
+  policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
+  effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
+  token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
+  effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
+  unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
+
+  const FilePath policy_path = storage_dir_.Append(kPolicyFilename);
+  cache_.reset(new DeviceManagementPolicyCache(policy_path));
+  cache_->LoadPolicyFromFile();
+
+  SetDeviceTokenFetcher(new DeviceTokenFetcher(backend_.get(), profile,
+                                               GetTokenPath()));
+
+  if (cache_->is_device_unmanaged()) {
+    // This is a non-first login on an unmanaged device.
+    SetState(STATE_UNMANAGED);
+  } else {
+    SetState(STATE_INITIALIZING);
+  }
 }
 
 void DeviceManagementPolicyProvider::AddObserver(
@@ -197,81 +225,7 @@
   observer_list_.RemoveObserver(observer);
 }
 
-void DeviceManagementPolicyProvider::NotifyCloudPolicyUpdate() {
-  FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
-                    observer_list_,
-                    OnUpdatePolicy());
-}
-
-void DeviceManagementPolicyProvider::Initialize(
-    DeviceManagementBackend* backend,
-    Profile* profile,
-    int64 policy_refresh_rate_ms,
-    int64 policy_refresh_max_earlier_ms,
-    int64 policy_refresh_error_delay_ms,
-    int64 token_fetch_error_delay_ms,
-    int64 unmanaged_device_refresh_rate_ms) {
-  backend_.reset(backend);
-  profile_ = profile;
-  storage_dir_ = GetOrCreateDeviceManagementDir(profile_->GetPath());
-  policy_request_pending_ = false;
-  refresh_task_pending_ = false;
-  waiting_for_initial_policies_ = true;
-  policy_refresh_rate_ms_ = policy_refresh_rate_ms;
-  policy_refresh_max_earlier_ms_ = policy_refresh_max_earlier_ms;
-  policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
-  token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
-  unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
-
-  const FilePath policy_path = storage_dir_.Append(kPolicyFilename);
-  cache_.reset(new DeviceManagementPolicyCache(policy_path));
-  cache_->LoadPolicyFromFile();
-
-  if (cache_->is_device_unmanaged()) {
-    // This is a non-first login on an unmanaged device.
-    waiting_for_initial_policies_ = false;
-    // Defer token_fetcher_ initialization until this device should ask for
-    // a device token again.
-    base::Time unmanaged_timestamp = cache_->last_policy_refresh_time();
-    int64 delay = unmanaged_device_refresh_rate_ms_ -
-        (base::Time::NowFromSystemTime().ToInternalValue() -
-            unmanaged_timestamp.ToInternalValue());
-    if (delay < 0)
-      delay = 0;
-    BrowserThread::PostDelayedTask(
-        BrowserThread::UI, FROM_HERE,
-        new InitializeAfterIOThreadExistsTask(AsWeakPtr()),
-        delay);
-  } else {
-    if (file_util::PathExists(
-        storage_dir_.Append(kDeviceTokenFilename))) {
-      // This is a non-first login on a managed device.
-      waiting_for_initial_policies_ = false;
-    }
-    // Defer initialization that requires the IOThread until after the IOThread
-    // has been initialized.
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            new InitializeAfterIOThreadExistsTask(AsWeakPtr()));
-  }
-}
-
-void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() {
-  if (profile_) {
-    if (!token_fetcher_) {
-      token_fetcher_ = new DeviceTokenFetcher(
-          backend_.get(), profile_, GetTokenPath());
-    }
-    registrar_.Init(token_fetcher_);
-    registrar_.AddObserver(this);
-    token_fetcher_->StartFetching();
-  }
-}
-
 void DeviceManagementPolicyProvider::SendPolicyRequest() {
-  if (policy_request_pending_)
-    return;
-
-  policy_request_pending_ = true;
   em::DevicePolicyRequest policy_request;
   policy_request.set_policy_scope(kChromePolicyScope);
   em::DevicePolicySettingRequest* setting =
@@ -284,40 +238,39 @@
 }
 
 void DeviceManagementPolicyProvider::RefreshTaskExecute() {
-  DCHECK(refresh_task_pending_);
-  refresh_task_pending_ = false;
-  // If there is no valid device token, the token_fetcher_ apparently failed,
-  // so it must be restarted.
-  if (!token_fetcher_->IsTokenValid()) {
-    if (token_fetcher_->IsTokenPending()) {
-      NOTREACHED();
+  DCHECK(refresh_task_);
+  refresh_task_ = NULL;
+
+  switch (state_) {
+    case STATE_INITIALIZING:
+      token_fetcher_->StartFetching();
       return;
-    }
-    token_fetcher_->Restart();
-    return;
+    case STATE_TOKEN_VALID:
+    case STATE_POLICY_VALID:
+    case STATE_POLICY_ERROR:
+      SendPolicyRequest();
+      return;
+    case STATE_UNMANAGED:
+    case STATE_TOKEN_ERROR:
+    case STATE_TOKEN_RESET:
+      token_fetcher_->Restart();
+      return;
   }
-  // If there is a device token, just refresh policies.
-  SendPolicyRequest();
+
+  NOTREACHED() << "Unhandled state";
 }
 
-void DeviceManagementPolicyProvider::ScheduleRefreshTask(
-    int64 delay_in_milliseconds) {
-  // This check is simply a safeguard, the situation currently cannot happen.
-  if (refresh_task_pending_) {
-    NOTREACHED();
-    return;
+void DeviceManagementPolicyProvider::CancelRefreshTask() {
+  if (refresh_task_) {
+    refresh_task_->Cancel();
+    refresh_task_ = NULL;
   }
-  refresh_task_pending_ = true;
-  BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
-                                 new RefreshTask(AsWeakPtr()),
-                                 delay_in_milliseconds);
 }
 
-int64 DeviceManagementPolicyProvider::GetRefreshTaskDelay() {
-  int64 delay = policy_refresh_rate_ms_;
-  if (policy_refresh_max_earlier_ms_)
-    delay -= base::RandGenerator(policy_refresh_max_earlier_ms_);
-  return delay;
+void DeviceManagementPolicyProvider::NotifyCloudPolicyUpdate() {
+  FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
+                    observer_list_,
+                    OnUpdatePolicy());
 }
 
 FilePath DeviceManagementPolicyProvider::GetTokenPath() {
@@ -326,14 +279,88 @@
 
 void DeviceManagementPolicyProvider::SetDeviceTokenFetcher(
     DeviceTokenFetcher* token_fetcher) {
-  DCHECK(!token_fetcher_);
+  registrar_.Init(token_fetcher);
+  registrar_.AddObserver(this);
   token_fetcher_ = token_fetcher;
 }
 
-void DeviceManagementPolicyProvider::StopWaitingForInitialPolicies() {
-  waiting_for_initial_policies_ = false;
-  // Notify observers that initial policy fetch is complete.
-  NotifyCloudPolicyUpdate();
+void DeviceManagementPolicyProvider::SetState(
+    DeviceManagementPolicyProvider::ProviderState new_state) {
+  state_ = new_state;
+
+  // If this state transition completes the initial policy fetch, let the
+  // observers now.
+  if (!initial_fetch_done_ &&
+      new_state != STATE_INITIALIZING &&
+      new_state != STATE_TOKEN_VALID) {
+    initial_fetch_done_ = true;
+    NotifyCloudPolicyUpdate();
+  }
+
+  base::Time now(base::Time::NowFromSystemTime());
+  base::Time refresh_at;
+  base::Time last_refresh(cache_->last_policy_refresh_time());
+  if (last_refresh.is_null())
+    last_refresh = now;
+
+  // Determine when to take the next step.
+  switch (state_) {
+    case STATE_INITIALIZING:
+      refresh_at = now;
+      break;
+    case STATE_TOKEN_VALID:
+      effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;
+      refresh_at = now;
+      break;
+    case STATE_TOKEN_RESET:
+      refresh_at = now;
+      break;
+    case STATE_UNMANAGED:
+      refresh_at = last_refresh +
+          base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
+      break;
+    case STATE_POLICY_VALID:
+      effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
+      refresh_at =
+          last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay());
+      break;
+    case STATE_TOKEN_ERROR:
+      refresh_at = now + base::TimeDelta::FromMilliseconds(
+                             effective_token_fetch_error_delay_ms_);
+      effective_token_fetch_error_delay_ms_ *= 2;
+      if (effective_token_fetch_error_delay_ms_ > policy_refresh_rate_ms_)
+        effective_token_fetch_error_delay_ms_ = policy_refresh_rate_ms_;
+      break;
+    case STATE_POLICY_ERROR:
+      refresh_at = now + base::TimeDelta::FromMilliseconds(
+                             effective_policy_refresh_error_delay_ms_);
+      effective_policy_refresh_error_delay_ms_ *= 2;
+      if (effective_policy_refresh_error_delay_ms_ > policy_refresh_rate_ms_)
+        effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
+      break;
+  }
+
+  // Update the refresh task.
+  CancelRefreshTask();
+  if (!refresh_at.is_null()) {
+    refresh_task_ = new RefreshTask(this);
+    int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0);
+    BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, refresh_task_,
+                                   delay);
+  }
+}
+
+int64 DeviceManagementPolicyProvider::GetRefreshDelay() {
+  int64 deviation = (policy_refresh_deviation_factor_percent_ *
+                     policy_refresh_rate_ms_) / 100;
+  deviation = std::min(deviation, policy_refresh_deviation_max_ms_);
+  return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1);
+}
+
+bool DeviceManagementPolicyProvider::TokenAvailable() const {
+  return state_ == STATE_TOKEN_VALID ||
+         state_ == STATE_POLICY_VALID ||
+         state_ == STATE_POLICY_ERROR;
 }
 
 // static
diff --git a/chrome/browser/policy/device_management_policy_provider.h b/chrome/browser/policy/device_management_policy_provider.h
index fd18bc3..592df9b 100644
--- a/chrome/browser/policy/device_management_policy_provider.h
+++ b/chrome/browser/policy/device_management_policy_provider.h
@@ -12,7 +12,6 @@
 #include "base/observer_list.h"
 #include "base/scoped_ptr.h"
 #include "base/time.h"
-#include "base/weak_ptr.h"
 #include "chrome/browser/policy/configuration_policy_provider.h"
 #include "chrome/browser/policy/device_management_backend.h"
 #include "chrome/browser/policy/device_token_fetcher.h"
@@ -31,7 +30,6 @@
 class DeviceManagementPolicyProvider
     :  public ConfigurationPolicyProvider,
        public DeviceManagementBackend::DevicePolicyResponseDelegate,
-       public base::SupportsWeakPtr<DeviceManagementPolicyProvider>,
        public DeviceTokenFetcher::Observer {
  public:
   DeviceManagementPolicyProvider(const PolicyDefinitionList* policy_list,
@@ -54,8 +52,28 @@
   virtual void OnTokenError();
   virtual void OnNotManaged();
 
+  // Sets the refresh rate at which to re-fetch policy information.
+  void SetRefreshRate(int64 refresh_rate_milliseconds);
+
  private:
-  class InitializeAfterIOThreadExistsTask;
+  // Indicates the current state the provider is in.
+  enum ProviderState {
+    // The provider is initializing, policy information not yet available.
+    STATE_INITIALIZING,
+    // This device is not managed through policy.
+    STATE_UNMANAGED,
+    // The token is valid, but policy is yet to be fetched.
+    STATE_TOKEN_VALID,
+    // Policy information is available and valid.
+    STATE_POLICY_VALID,
+    // The token was found to be invalid and needs to be obtained again.
+    STATE_TOKEN_RESET,
+    // There has been an error fetching the token, retry later.
+    STATE_TOKEN_ERROR,
+    // The service returned an error when requesting policy, ask again later.
+    STATE_POLICY_ERROR,
+  };
+
   class RefreshTask;
 
   friend class DeviceManagementPolicyProviderTest;
@@ -65,7 +83,8 @@
                                  DeviceManagementBackend* backend,
                                  Profile* profile,
                                  int64 policy_refresh_rate_ms,
-                                 int64 policy_refresh_max_earlier_ms,
+                                 int policy_refresh_deviation_factor_percent,
+                                 int64 policy_refresh_deviation_max_ms,
                                  int64 policy_refresh_error_delay_ms,
                                  int64 token_fetch_error_delay_ms,
                                  int64 unmanaged_device_refresh_rate_ms);
@@ -77,15 +96,12 @@
   void Initialize(DeviceManagementBackend* backend,
                   Profile* profile,
                   int64 policy_refresh_rate_ms,
-                  int64 policy_refresh_max_earlier_ms,
+                  int policy_refresh_deviation_factor_percent,
+                  int64 policy_refresh_deviation_max_ms,
                   int64 policy_refresh_error_delay_ms,
                   int64 token_fetch_error_delay_ms,
                   int64 unmanaged_device_refresh_rate_ms);
 
-  // Called by a deferred task posted to the UI thread to complete the portion
-  // of initialization that requires the IOThread.
-  void InitializeAfterIOThreadExists();
-
   // ConfigurationPolicyProvider overrides:
   virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer);
   virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer);
@@ -98,13 +114,8 @@
   // as necessary.
   void RefreshTaskExecute();
 
-  // Schedules a new RefreshTask.
-  void ScheduleRefreshTask(int64 delay_in_milliseconds);
-
-  // Calculates when the next RefreshTask shall be executed.
-  int64 GetRefreshTaskDelay();
-
-  void StopWaitingForInitialPolicies();
+  // Cancels the refresh task.
+  void CancelRefreshTask();
 
   // Notify observers about a policy update.
   void NotifyCloudPolicyUpdate();
@@ -115,6 +126,15 @@
   // Used only by tests.
   void SetDeviceTokenFetcher(DeviceTokenFetcher* token_fetcher);
 
+  // Switches to a new state and triggers any appropriate actions.
+  void SetState(ProviderState new_state);
+
+  // Check whether the current state is one in which the token is available.
+  bool TokenAvailable() const;
+
+  // Computes the refresh delay to use.
+  int64 GetRefreshDelay();
+
   // Provides the URL at which requests are sent to from the device management
   // backend.
   static std::string GetDeviceManagementURL();
@@ -131,13 +151,16 @@
   DeviceTokenFetcher::ObserverRegistrar registrar_;
   ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_;
   FilePath storage_dir_;
-  bool policy_request_pending_;
-  bool refresh_task_pending_;
-  bool waiting_for_initial_policies_;
+  ProviderState state_;
+  bool initial_fetch_done_;
+  RefreshTask* refresh_task_;
   int64 policy_refresh_rate_ms_;
-  int64 policy_refresh_max_earlier_ms_;
+  int policy_refresh_deviation_factor_percent_;
+  int64 policy_refresh_deviation_max_ms_;
   int64 policy_refresh_error_delay_ms_;
+  int64 effective_policy_refresh_error_delay_ms_;
   int64 token_fetch_error_delay_ms_;
+  int64 effective_token_fetch_error_delay_ms_;
   int64 unmanaged_device_refresh_rate_ms_;
 
   DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyProvider);
diff --git a/chrome/browser/policy/device_management_policy_provider_unittest.cc b/chrome/browser/policy/device_management_policy_provider_unittest.cc
index eac2c5b..d0a0eaa 100644
--- a/chrome/browser/policy/device_management_policy_provider_unittest.cc
+++ b/chrome/browser/policy/device_management_policy_provider_unittest.cc
@@ -16,9 +16,9 @@
 #include "chrome/common/net/gaia/gaia_constants.h"
 #include "chrome/common/notification_observer_mock.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/policy_constants.h"
 #include "chrome/test/testing_device_token_fetcher.h"
 #include "chrome/test/testing_profile.h"
+#include "policy/policy_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -27,6 +27,7 @@
 namespace policy {
 
 using ::testing::_;
+using ::testing::AtLeast;
 using ::testing::InSequence;
 using ::testing::Mock;
 
@@ -65,7 +66,8 @@
   }
 
   void CreateNewProvider(int64 policy_refresh_rate_ms,
-                         int64 policy_refresh_max_earlier_ms,
+                         int policy_refresh_fuzz_factor_percent,
+                         int64 policy_refresh_fuzz_max,
                          int64 policy_refresh_error_delay_ms,
                          int64 token_fetch_error_delay_ms,
                          int64 unmanaged_device_refresh_rate_ms) {
@@ -75,7 +77,8 @@
         backend_,
         profile_.get(),
         policy_refresh_rate_ms,
-        policy_refresh_max_earlier_ms,
+        policy_refresh_fuzz_factor_percent,
+        policy_refresh_fuzz_max,
         policy_refresh_error_delay_ms,
         token_fetch_error_delay_ms,
         unmanaged_device_refresh_rate_ms));
@@ -90,6 +93,12 @@
   }
 
   void SimulateSuccessfulLoginAndRunPending() {
+    // Make sure the notification for the initial policy fetch is generated.
+    MockConfigurationPolicyObserver observer;
+    ConfigurationPolicyObserverRegistrar registrar;
+    registrar.Init(provider_.get(), &observer);
+    EXPECT_CALL(observer, OnUpdatePolicy()).Times(AtLeast(1));
+
     loop_.RunAllPending();
     profile_->GetTokenService()->IssueAuthTokenForTest(
         GaiaConstants::kDeviceManagementService, kTestToken);
@@ -117,11 +126,12 @@
   }
 
   virtual void TearDown() {
+    provider_.reset();
     loop_.RunAllPending();
   }
 
   bool waiting_for_initial_policies() const {
-    return provider_->waiting_for_initial_policies_;
+    return !provider_->IsInitializationComplete();
   }
 
   MockDeviceManagementBackend* backend_;  // weak
@@ -196,7 +206,6 @@
   EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
       MockDeviceManagementBackendFailPolicy(
           DeviceManagementBackend::kErrorRequestFailed));
-  loop_.RunAllPending();
   SimulateSuccessfulLoginAndRunPending();
   EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(1);
   provider_->Provide(&store);
@@ -214,90 +223,108 @@
 }
 
 TEST_F(DeviceManagementPolicyProviderTest, ErrorCausesNewRequest) {
-  InSequence s;
-  CreateNewProvider(1000 * 1000, 0, 0, 0, 0);
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailRegister(
-          DeviceManagementBackend::kErrorRequestFailed));
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailPolicy(
-          DeviceManagementBackend::kErrorRequestFailed));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailPolicy(
-          DeviceManagementBackend::kErrorRequestFailed));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    CreateNewProvider(1000 * 1000, 0, 0, 0, 0, 0);
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailRegister(
+            DeviceManagementBackend::kErrorRequestFailed));
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailPolicy(
+            DeviceManagementBackend::kErrorRequestFailed));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailPolicy(
+            DeviceManagementBackend::kErrorRequestFailed));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+  }
   SimulateSuccessfulLoginAndRunPending();
 }
 
 TEST_F(DeviceManagementPolicyProviderTest, RefreshPolicies) {
-  InSequence s;
-  CreateNewProvider(0, 0, 1000 * 1000, 1000, 0);
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailPolicy(
-          DeviceManagementBackend::kErrorRequestFailed));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    CreateNewProvider(0, 0, 0, 1000 * 1000, 1000, 0);
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailPolicy(
+            DeviceManagementBackend::kErrorRequestFailed));
+  }
   SimulateSuccessfulLoginAndRunPending();
 }
 
 // The client should try to re-register the device if the device server reports
 // back that it doesn't recognize the device token on a policy request.
 TEST_F(DeviceManagementPolicyProviderTest, DeviceNotFound) {
-  InSequence s;
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailPolicy(
-          DeviceManagementBackend::kErrorServiceDeviceNotFound));
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailPolicy(
+            DeviceManagementBackend::kErrorServiceDeviceNotFound));
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+  }
   SimulateSuccessfulLoginAndRunPending();
 }
 
 // The client should try to re-register the device if the device server reports
 // back that the device token is invalid on a policy request.
 TEST_F(DeviceManagementPolicyProviderTest, InvalidTokenOnPolicyRequest) {
-  InSequence s;
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailPolicy(
-          DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailPolicy(
+            DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+  }
   SimulateSuccessfulLoginAndRunPending();
 }
 
 // If the client is successfully managed, but the admin stops managing the
 // device, the client should notice and throw away the device token and id.
 TEST_F(DeviceManagementPolicyProviderTest, DeviceNoLongerManaged) {
-  InSequence s;
-  CreateNewProvider(0, 0, 0, 0, 1000 * 1000);
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailPolicy(
-          DeviceManagementBackend::kErrorServiceManagementNotSupported));
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailRegister(
-          DeviceManagementBackend::kErrorServiceManagementNotSupported));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    CreateNewProvider(0, 0, 0, 0, 0, 1000 * 1000);
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailPolicy(
+            DeviceManagementBackend::kErrorServiceManagementNotSupported));
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailRegister(
+            DeviceManagementBackend::kErrorServiceManagementNotSupported));
+  }
   SimulateSuccessfulLoginAndRunPending();
   FilePath token_path(GetTokenPath());
   EXPECT_FALSE(file_util::PathExists(token_path));
@@ -305,22 +332,28 @@
 
 // This test tests three things (see numbered comments below):
 TEST_F(DeviceManagementPolicyProviderTest, UnmanagedDevice) {
-  InSequence s;
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendFailRegister(
-          DeviceManagementBackend::kErrorServiceManagementNotSupported));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendFailRegister(
+            DeviceManagementBackend::kErrorServiceManagementNotSupported));
+  }
   SimulateSuccessfulLoginAndRunPending();
   // (1) The provider's DMPolicyCache should know that the device is not
   // managed.
   EXPECT_TRUE(cache(provider_.get())->is_device_unmanaged());
   // (2) On restart, the provider should detect that this is not the first
   // login.
-  CreateNewProvider(1000*1000, 0, 0, 0, 0);
+  CreateNewProvider(1000 * 1000, 0, 0, 0, 0, 0);
   EXPECT_FALSE(waiting_for_initial_policies());
-  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedRegister());
-  EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
-      MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy, true));
+  { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
+    InSequence s;
+    EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedRegister());
+    EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+        MockDeviceManagementBackendSucceedBooleanPolicy(key::kDisableSpdy,
+                                                        true));
+  }
   SimulateSuccessfulLoginAndRunPending();
   // (3) Since the backend call this time returned a device id, the "unmanaged"
   // marker should have been deleted.
diff --git a/chrome/browser/policy/device_management_service.cc b/chrome/browser/policy/device_management_service.cc
index 689c947..965a42c 100644
--- a/chrome/browser/policy/device_management_service.cc
+++ b/chrome/browser/policy/device_management_service.cc
@@ -1,10 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/policy/device_management_service.h"
 
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/io_thread.h"
+#include "chrome/browser/net/chrome_net_log.h"
+#include "chrome/browser/policy/device_management_backend_impl.h"
+#include "chrome/common/net/url_request_context_getter.h"
 #include "net/base/cookie_monster.h"
 #include "net/base/host_resolver.h"
 #include "net/base/load_flags.h"
@@ -14,10 +18,6 @@
 #include "net/proxy/proxy_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
-#include "chrome/browser/io_thread.h"
-#include "chrome/browser/net/chrome_net_log.h"
-#include "chrome/browser/policy/device_management_backend_impl.h"
-#include "chrome/common/net/url_request_context_getter.h"
 #include "webkit/glue/webkit_glue.h"
 
 namespace policy {
@@ -27,18 +27,18 @@
 // Custom request context implementation that allows to override the user agent,
 // amongst others. Wraps a baseline request context from which we reuse the
 // networking components.
-class DeviceManagementRequestContext : public URLRequestContext {
+class DeviceManagementRequestContext : public net::URLRequestContext {
  public:
-  explicit DeviceManagementRequestContext(URLRequestContext* base_context);
+  explicit DeviceManagementRequestContext(net::URLRequestContext* base_context);
   virtual ~DeviceManagementRequestContext();
 
  private:
-  // Overriden from URLRequestContext.
+  // Overridden from net::URLRequestContext:
   virtual const std::string& GetUserAgent(const GURL& url) const;
 };
 
 DeviceManagementRequestContext::DeviceManagementRequestContext(
-    URLRequestContext* base_context) {
+    net::URLRequestContext* base_context) {
   // Share resolver, proxy service and ssl bits with the baseline context. This
   // is important so we don't make redundant requests (e.g. when resolving proxy
   // auto configuration).
@@ -48,8 +48,9 @@
   ssl_config_service_ = base_context->ssl_config_service();
 
   // Share the http session.
-  http_transaction_factory_ = net::HttpNetworkLayer::CreateFactory(
-      base_context->http_transaction_factory()->GetSession());
+  http_transaction_factory_ =
+      new net::HttpNetworkLayer(
+          base_context->http_transaction_factory()->GetSession());
 
   // No cookies, please.
   cookie_store_ = new net::CookieMonster(NULL, NULL);
@@ -76,17 +77,17 @@
       URLRequestContextGetter* base_context_getter)
       : base_context_getter_(base_context_getter) {}
 
-  // URLRequestContextGetter overrides.
-  virtual URLRequestContext* GetURLRequestContext();
+  // Overridden from URLRequestContextGetter:
+  virtual net::URLRequestContext* GetURLRequestContext();
   virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const;
 
  private:
-  scoped_refptr<URLRequestContext> context_;
+  scoped_refptr<net::URLRequestContext> context_;
   scoped_refptr<URLRequestContextGetter> base_context_getter_;
 };
 
 
-URLRequestContext*
+net::URLRequestContext*
 DeviceManagementRequestContextGetter::GetURLRequestContext() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   if (!context_) {
@@ -133,6 +134,7 @@
     delete job->first;
     queued_jobs_.push_back(job->second);
   }
+  pending_jobs_.clear();
 }
 
 DeviceManagementService::DeviceManagementService(
@@ -154,9 +156,14 @@
     if (entry->second == job) {
       delete entry->first;
       pending_jobs_.erase(entry);
-      break;
+      return;
     }
   }
+
+  const JobQueue::iterator elem =
+      std::find(queued_jobs_.begin(), queued_jobs_.end(), job);
+  if (elem != queued_jobs_.end())
+    queued_jobs_.erase(elem);
 }
 
 void DeviceManagementService::StartJob(DeviceManagementJob* job) {
@@ -174,7 +181,7 @@
 void DeviceManagementService::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
diff --git a/chrome/browser/policy/device_management_service_browsertest.cc b/chrome/browser/policy/device_management_service_browsertest.cc
index feed86f..b8ad273 100644
--- a/chrome/browser/policy/device_management_service_browsertest.cc
+++ b/chrome/browser/policy/device_management_service_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -60,10 +60,10 @@
   virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request) {
     if (request->url().GetOrigin() == service_url_.GetOrigin() &&
         request->url().path() == service_url_.path()) {
-      return new URLRequestTestJob(request,
-                                   URLRequestTestJob::test_headers(),
-                                   response_data_,
-                                   true);
+      return new net::URLRequestTestJob(request,
+                                        net::URLRequestTestJob::test_headers(),
+                                        response_data_,
+                                        true);
     }
 
     return NULL;
diff --git a/chrome/browser/policy/device_management_service_unittest.cc b/chrome/browser/policy/device_management_service_unittest.cc
index 1a11424..6570db8 100644
--- a/chrome/browser/policy/device_management_service_unittest.cc
+++ b/chrome/browser/policy/device_management_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,9 +15,9 @@
 #include "chrome/test/test_url_request_context_getter.h"
 #include "net/base/escape.h"
 #include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_unittest.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
 
@@ -82,7 +82,7 @@
 
 struct FailedRequestParams {
   FailedRequestParams(DeviceManagementBackend::ErrorCode expected_error,
-                      URLRequestStatus::Status request_status,
+                      net::URLRequestStatus::Status request_status,
                       int http_status,
                       const std::string& response)
       : expected_error_(expected_error),
@@ -91,7 +91,7 @@
         response_(response) {}
 
   DeviceManagementBackend::ErrorCode expected_error_;
-  URLRequestStatus request_status_;
+  net::URLRequestStatus request_status_;
   int http_status_;
   std::string response_;
 };
@@ -161,37 +161,37 @@
     testing::Values(
         FailedRequestParams(
             DeviceManagementBackend::kErrorRequestFailed,
-            URLRequestStatus::FAILED,
+            net::URLRequestStatus::FAILED,
             200,
             PROTO_STRING(kResponseEmpty)),
         FailedRequestParams(
             DeviceManagementBackend::kErrorHttpStatus,
-            URLRequestStatus::SUCCESS,
+            net::URLRequestStatus::SUCCESS,
             500,
             PROTO_STRING(kResponseEmpty)),
         FailedRequestParams(
             DeviceManagementBackend::kErrorResponseDecoding,
-            URLRequestStatus::SUCCESS,
+            net::URLRequestStatus::SUCCESS,
             200,
             PROTO_STRING("Not a protobuf.")),
         FailedRequestParams(
             DeviceManagementBackend::kErrorServiceManagementNotSupported,
-            URLRequestStatus::SUCCESS,
+            net::URLRequestStatus::SUCCESS,
             200,
             PROTO_STRING(kResponseErrorManagementNotSupported)),
         FailedRequestParams(
             DeviceManagementBackend::kErrorServiceDeviceNotFound,
-            URLRequestStatus::SUCCESS,
+            net::URLRequestStatus::SUCCESS,
             200,
             PROTO_STRING(kResponseErrorDeviceNotFound)),
         FailedRequestParams(
             DeviceManagementBackend::kErrorServiceManagementTokenInvalid,
-            URLRequestStatus::SUCCESS,
+            net::URLRequestStatus::SUCCESS,
             200,
             PROTO_STRING(kResponseErrorManagementTokenInvalid)),
         FailedRequestParams(
             DeviceManagementBackend::kErrorServiceActivationPending,
-            URLRequestStatus::SUCCESS,
+            net::URLRequestStatus::SUCCESS,
             200,
             PROTO_STRING(kResponseErrorActivationPending))));
 
@@ -299,7 +299,7 @@
   response_wrapper.set_error(em::DeviceManagementResponse::SUCCESS);
   response_wrapper.mutable_register_response()->CopyFrom(expected_response);
   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   fetcher->delegate()->OnURLFetchComplete(fetcher,
                                           GURL(kServiceUrl),
                                           status,
@@ -342,7 +342,7 @@
   response_wrapper.set_error(em::DeviceManagementResponse::SUCCESS);
   response_wrapper.mutable_unregister_response()->CopyFrom(expected_response);
   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   fetcher->delegate()->OnURLFetchComplete(fetcher,
                                           GURL(kServiceUrl),
                                           status,
@@ -397,7 +397,7 @@
   response_wrapper.set_error(em::DeviceManagementResponse::SUCCESS);
   response_wrapper.mutable_policy_response()->CopyFrom(expected_response);
   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   fetcher->delegate()->OnURLFetchComplete(fetcher,
                                           GURL(kServiceUrl),
                                           status,
@@ -473,7 +473,7 @@
   response_wrapper.set_error(em::DeviceManagementResponse::SUCCESS);
   response_wrapper.mutable_register_response()->CopyFrom(expected_response);
   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   fetcher->delegate()->OnURLFetchComplete(fetcher,
                                           GURL(kServiceUrl),
                                           status,
@@ -482,4 +482,22 @@
                                           response_data);
 }
 
+TEST_F(DeviceManagementServiceTest, CancelRequestAfterShutdown) {
+  DevicePolicyResponseDelegateMock mock;
+  EXPECT_CALL(mock, HandlePolicyResponse(_)).Times(0);
+  em::DevicePolicyRequest request;
+  request.set_policy_scope(kChromePolicyScope);
+  em::DevicePolicySettingRequest* setting_request =
+      request.add_setting_request();
+  setting_request->set_key(kChromeDevicePolicySettingKey);
+  setting_request->set_watermark("stale");
+  backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
+  TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
+  ASSERT_TRUE(fetcher);
+
+  // Shutdown the service and cancel the job afterwards.
+  service_->Shutdown();
+  backend_.reset();
+}
+
 }  // namespace policy
diff --git a/chrome/browser/policy/device_token_fetcher.cc b/chrome/browser/policy/device_token_fetcher.cc
index 2d514b6..3f977c1 100644
--- a/chrome/browser/policy/device_token_fetcher.cc
+++ b/chrome/browser/policy/device_token_fetcher.cc
@@ -65,6 +65,7 @@
 
 void DeviceTokenFetcher::ObserverRegistrar::Init(
     DeviceTokenFetcher* token_fetcher) {
+  RemoveAll();
   token_fetcher_ = token_fetcher;
 }
 
@@ -192,7 +193,11 @@
 }
 
 void DeviceTokenFetcher::Restart() {
-  DCHECK(!IsTokenPending());
+  // Complain if there's currently an asynchronous operation going on.
+  DCHECK(state_ == kStateNotStarted ||
+         state_ == kStateHasDeviceToken ||
+         state_ == kStateFailure ||
+         state_ == kStateNotManaged);
   device_token_.clear();
   device_token_load_complete_event_.Reset();
   MakeReadyToRequestDeviceToken();
diff --git a/chrome/browser/policy/device_token_fetcher_unittest.cc b/chrome/browser/policy/device_token_fetcher_unittest.cc
index f4a7e23..28d11b0 100644
--- a/chrome/browser/policy/device_token_fetcher_unittest.cc
+++ b/chrome/browser/policy/device_token_fetcher_unittest.cc
@@ -224,4 +224,28 @@
   ASSERT_FALSE(fetcher_->IsTokenValid());
 }
 
+TEST_F(DeviceTokenFetcherTest, RestartImmediately) {
+  // Create a token.
+  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+      MockDeviceManagementBackendSucceedRegister());
+  SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
+  ASSERT_FALSE(fetcher_->IsTokenPending());
+  std::string device_token = fetcher_->GetDeviceToken();
+
+  // Restart a new fetcher immediately without calling StartFetching(). The
+  // existing token should not be loaded, but rather a new token generated.
+  FilePath token_path;
+  GetDeviceTokenPath(fetcher_, &token_path);
+  scoped_refptr<TestingDeviceTokenFetcher> fetcher2(
+      new TestingDeviceTokenFetcher(
+          backend_.get(), profile_.get(), token_path));
+  fetcher2->Restart();
+  EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+      MockDeviceManagementBackendSucceedRegister());
+  fetcher2->SimulateLogin(kTestManagedDomainUsername);
+  loop_.RunAllPending();
+  ASSERT_FALSE(fetcher2->IsTokenPending());
+  ASSERT_NE(device_token, fetcher2->GetDeviceToken());
+}
+
 }  // namespace policy
diff --git a/chrome/browser/policy/file_based_policy_provider_unittest.cc b/chrome/browser/policy/file_based_policy_provider_unittest.cc
index 1bb2185..d5d0811 100644
--- a/chrome/browser/policy/file_based_policy_provider_unittest.cc
+++ b/chrome/browser/policy/file_based_policy_provider_unittest.cc
@@ -7,7 +7,8 @@
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/policy/configuration_policy_store_interface.h"
 #include "chrome/browser/policy/file_based_policy_provider.h"
-#include "chrome/common/policy_constants.h"
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
+#include "policy/policy_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/policy/managed_prefs_banner_base.cc b/chrome/browser/policy/managed_prefs_banner_base.cc
index 7c20a09..39fdf73 100644
--- a/chrome/browser/policy/managed_prefs_banner_base.cc
+++ b/chrome/browser/policy/managed_prefs_banner_base.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -62,10 +62,13 @@
       AddUserPref(prefs::kDefaultSearchProviderEnabled);
       AddUserPref(prefs::kDefaultSearchProviderName);
       AddUserPref(prefs::kDefaultSearchProviderKeyword);
+      AddUserPref(prefs::kDefaultSearchProviderInstantURL);
       AddUserPref(prefs::kDefaultSearchProviderSearchURL);
       AddUserPref(prefs::kDefaultSearchProviderSuggestURL);
       AddUserPref(prefs::kDefaultSearchProviderIconURL);
       AddUserPref(prefs::kDefaultSearchProviderEncodings);
+      AddUserPref(prefs::kInstantEnabled);
+      AddLocalStatePref(prefs::kDefaultBrowserSettingEnabled);
       break;
     case OPTIONS_PAGE_CONTENT:
       AddUserPref(prefs::kSyncManaged);
@@ -84,10 +87,8 @@
 #if defined(GOOGLE_CHROME_BUILD)
       AddLocalStatePref(prefs::kMetricsReportingEnabled);
 #endif
-      AddUserPref(prefs::kProxyMode);
-      AddUserPref(prefs::kProxyServer);
-      AddUserPref(prefs::kProxyPacUrl);
-      AddUserPref(prefs::kProxyBypassList);
+      AddUserPref(prefs::kProxy);
+      AddUserPref(prefs::kCloudPrintProxyEnabled);
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/policy/mock_device_management_backend.cc b/chrome/browser/policy/mock_device_management_backend.cc
new file mode 100644
index 0000000..c817c60
--- /dev/null
+++ b/chrome/browser/policy/mock_device_management_backend.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/policy/mock_device_management_backend.h"
+
+namespace policy {
+
+MockDeviceManagementBackend::MockDeviceManagementBackend() {}
+
+MockDeviceManagementBackend::~MockDeviceManagementBackend() {}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/mock_device_management_backend.h b/chrome/browser/policy/mock_device_management_backend.h
index 83323de..a684e4f 100644
--- a/chrome/browser/policy/mock_device_management_backend.h
+++ b/chrome/browser/policy/mock_device_management_backend.h
@@ -22,11 +22,10 @@
 // Useful for unit testing when a server-based backend isn't
 // available. Simulates both successful and failed requests to the device
 // management server.
-class MockDeviceManagementBackend
-    : public DeviceManagementBackend {
+class MockDeviceManagementBackend : public DeviceManagementBackend {
  public:
-  MockDeviceManagementBackend() {}
-  virtual ~MockDeviceManagementBackend() {}
+  MockDeviceManagementBackend();
+  virtual ~MockDeviceManagementBackend();
 
   // DeviceManagementBackend method overrides:
   MOCK_METHOD4(ProcessRegisterRequest, void(
diff --git a/chrome/browser/policy/profile_policy_context.cc b/chrome/browser/policy/profile_policy_context.cc
index c221529..7adffd3 100644
--- a/chrome/browser/policy/profile_policy_context.cc
+++ b/chrome/browser/policy/profile_policy_context.cc
@@ -7,8 +7,20 @@
 #include "chrome/browser/policy/device_management_policy_provider.h"
 #include "chrome/browser/policy/device_management_service.h"
 #include "chrome/browser/policy/profile_policy_context.h"
+#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/pref_names.h"
+
+namespace {
+
+// Refresh rate sanity interval bounds.
+const int64 kPolicyRefreshRateMinMs = 30 * 60 * 1000;  // 30 minutes
+const int64 kPolicyRefreshRateMaxMs = 24 * 60 * 60 * 1000;  // 1 day
+
+}
 
 namespace policy {
 
@@ -34,6 +46,10 @@
 void ProfilePolicyContext::Initialize() {
   if (device_management_service_.get())
     device_management_service_->Initialize(profile_->GetRequestContext());
+
+  policy_refresh_rate_.Init(prefs::kPolicyRefreshRate, profile_->GetPrefs(),
+                            this);
+  UpdatePolicyRefreshRate();
 }
 
 void ProfilePolicyContext::Shutdown() {
@@ -46,4 +62,32 @@
   return device_management_policy_provider_.get();
 }
 
+// static
+void ProfilePolicyContext::RegisterUserPrefs(PrefService* user_prefs) {
+  user_prefs->RegisterIntegerPref(prefs::kPolicyRefreshRate,
+                                  kDefaultPolicyRefreshRateInMilliseconds);
+}
+
+void ProfilePolicyContext::UpdatePolicyRefreshRate() {
+  if (device_management_policy_provider_.get()) {
+    // Clamp to sane values.
+    int64 refresh_rate = policy_refresh_rate_.GetValue();
+    refresh_rate = std::max(kPolicyRefreshRateMinMs, refresh_rate);
+    refresh_rate = std::min(kPolicyRefreshRateMaxMs, refresh_rate);
+    device_management_policy_provider_->SetRefreshRate(refresh_rate);
+  }
+}
+
+void ProfilePolicyContext::Observe(NotificationType type,
+                                   const NotificationSource& source,
+                                   const NotificationDetails& details) {
+  if (type == NotificationType::PREF_CHANGED &&
+      prefs::kPolicyRefreshRate == *(Details<std::string>(details).ptr()) &&
+      profile_->GetPrefs() == Source<PrefService>(source).ptr()) {
+    UpdatePolicyRefreshRate();
+  } else {
+    NOTREACHED();
+  }
+}
+
 }  // namespace policy
diff --git a/chrome/browser/policy/profile_policy_context.h b/chrome/browser/policy/profile_policy_context.h
index b343e15..8650ec5 100644
--- a/chrome/browser/policy/profile_policy_context.h
+++ b/chrome/browser/policy/profile_policy_context.h
@@ -7,6 +7,8 @@
 #pragma once
 
 #include "base/scoped_ptr.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/common/notification_observer.h"
 
 class Profile;
 
@@ -19,7 +21,7 @@
 // profile. Since the context owns the policy provider, it's vital that it gets
 // initialized before the profile's prefs and destroyed after the prefs are
 // gone.
-class ProfilePolicyContext {
+class ProfilePolicyContext : public NotificationObserver {
  public:
   explicit ProfilePolicyContext(Profile* profile);
   ~ProfilePolicyContext();
@@ -35,10 +37,27 @@
   // Get the policy provider.
   DeviceManagementPolicyProvider* GetDeviceManagementPolicyProvider();
 
+  // Register preferences.
+  static void RegisterUserPrefs(PrefService* user_prefs);
+
+  static const int kDefaultPolicyRefreshRateInMilliseconds =
+      3 * 60 * 60 * 1000; // 3 hours.
+
  private:
+  // Updates the policy provider with a new refresh rate value.
+  void UpdatePolicyRefreshRate();
+
+  // NotificationObserver overrides.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
   // The profile this context is associated with.
   Profile* profile_;
 
+  // Tracks the pref value for the policy refresh rate.
+  IntegerPrefMember policy_refresh_rate_;
+
   // The device management service.
   scoped_ptr<DeviceManagementService> device_management_service_;
 
diff --git a/chrome/browser/policy/proto/cloud_policy.proto b/chrome/browser/policy/proto/cloud_policy.proto
new file mode 100644
index 0000000..82a1135
--- /dev/null
+++ b/chrome/browser/policy/proto/cloud_policy.proto
@@ -0,0 +1,221 @@
+//
+// DO NOT MODIFY THIS FILE DIRECTLY!
+// ITS IS GENERATED BY generate_policy_source.py
+// FROM policy_templates.json
+//
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package enterprise_management;
+
+// PBs for individual settings.
+
+message PolicyOptions {
+  enum PolicyMode {
+    // The user may choose to override the given settings.
+    RECOMMENDED = 1;
+    // The given settings are applied regardless of user choice.
+    MANDATORY = 2;
+  }
+  optional PolicyMode mode = 1;
+}
+
+message HomepageProto {
+  optional PolicyOptions policy_options = 1;
+  optional string HomepageLocation = 2;
+  optional bool HomepageIsNewTabPage = 3;
+}
+
+message ApplicationLocaleValueProto {
+  optional PolicyOptions policy_options = 1;
+  optional string ApplicationLocaleValue = 2;
+}
+
+message AlternateErrorPagesEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool AlternateErrorPagesEnabled = 2;
+}
+
+message SearchSuggestEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool SearchSuggestEnabled = 2;
+}
+
+message DnsPrefetchingEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool DnsPrefetchingEnabled = 2;
+}
+
+message DisableSpdyProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool DisableSpdy = 2;
+}
+
+message JavascriptEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool JavascriptEnabled = 2;
+}
+
+message SavingBrowserHistoryDisabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool SavingBrowserHistoryDisabled = 2;
+}
+
+message PrintingEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool PrintingEnabled = 2;
+}
+
+message SafeBrowsingEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool SafeBrowsingEnabled = 2;
+}
+
+message MetricsReportingEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool MetricsReportingEnabled = 2;
+}
+
+message PasswordManagerProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool PasswordManagerEnabled = 2;
+  optional bool PasswordManagerAllowShowPasswords = 3;
+}
+
+message AutoFillEnabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool AutoFillEnabled = 2;
+}
+
+message DisabledPluginsProto {
+  optional PolicyOptions policy_options = 1;
+  repeated string DisabledPlugins = 2;
+}
+
+message SyncDisabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool SyncDisabled = 2;
+}
+
+message ProxyProto {
+  optional PolicyOptions policy_options = 1;
+  optional string ProxyMode = 2;
+  optional int64 ProxyServerMode = 3;
+  optional string ProxyServer = 4;
+  optional string ProxyPacUrl = 5;
+  optional string ProxyBypassList = 6;
+}
+
+message HTTPAuthenticationProto {
+  optional PolicyOptions policy_options = 1;
+  optional string AuthSchemes = 2;
+  optional bool DisableAuthNegotiateCnameLookup = 3;
+  optional bool EnableAuthNegotiatePort = 4;
+  optional string AuthServerWhitelist = 5;
+  optional string AuthNegotiateDelegateWhitelist = 6;
+  optional string GSSAPILibraryName = 7;
+}
+
+message ExtensionsProto {
+  optional PolicyOptions policy_options = 1;
+  repeated string ExtensionInstallBlacklist = 2;
+  repeated string ExtensionInstallWhitelist = 3;
+  repeated string ExtensionInstallForcelist = 4;
+}
+
+message ShowHomeButtonProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool ShowHomeButton = 2;
+}
+
+message DeveloperToolsDisabledProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool DeveloperToolsDisabled = 2;
+}
+
+message RestoreOnStartupGroupProto {
+  optional PolicyOptions policy_options = 1;
+  optional int64 RestoreOnStartup = 2;
+  repeated string RestoreOnStartupURLs = 3;
+}
+
+message DefaultSearchProviderProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool DefaultSearchProviderEnabled = 2;
+  optional string DefaultSearchProviderName = 3;
+  optional string DefaultSearchProviderKeyword = 4;
+  optional string DefaultSearchProviderSearchURL = 5;
+  optional string DefaultSearchProviderSuggestURL = 6;
+  optional string DefaultSearchProviderInstantURL = 7;
+  optional string DefaultSearchProviderIconURL = 8;
+  repeated string DefaultSearchProviderEncodings = 9;
+}
+
+message ContentSettingsProto {
+  optional PolicyOptions policy_options = 1;
+  optional int64 DefaultCookiesSetting = 2;
+  optional int64 DefaultImagesSetting = 3;
+  optional int64 DefaultJavaScriptSetting = 4;
+  optional int64 DefaultPluginsSetting = 5;
+  optional int64 DefaultPopupsSetting = 6;
+  optional int64 DefaultNotificationSetting = 7;
+  optional int64 DefaultGeolocationSetting = 8;
+}
+
+message Disable3DAPIsProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool Disable3DAPIs = 2;
+}
+
+message ChromeFrameRendererSettingsProto {
+  optional PolicyOptions policy_options = 1;
+  optional int64 ChromeFrameRendererSettings = 2;
+  repeated string RenderInChromeFrameList = 3;
+  repeated string RenderInHostList = 4;
+}
+
+message ChromeFrameContentTypesProto {
+  optional PolicyOptions policy_options = 1;
+  repeated string ChromeFrameContentTypes = 2;
+}
+
+message ChromeOsLockOnIdleSuspendProto {
+  optional PolicyOptions policy_options = 1;
+  optional bool ChromeOsLockOnIdleSuspend = 2;
+}
+
+
+// --------------------------------------------------
+// Wrapper PB for DMServer -> ChromeOS communication.
+
+message CloudPolicySettings {
+  optional HomepageProto Homepage = 1;
+  optional ApplicationLocaleValueProto ApplicationLocaleValue = 2;
+  optional AlternateErrorPagesEnabledProto AlternateErrorPagesEnabled = 3;
+  optional SearchSuggestEnabledProto SearchSuggestEnabled = 4;
+  optional DnsPrefetchingEnabledProto DnsPrefetchingEnabled = 5;
+  optional DisableSpdyProto DisableSpdy = 6;
+  optional JavascriptEnabledProto JavascriptEnabled = 7;
+  optional SavingBrowserHistoryDisabledProto SavingBrowserHistoryDisabled = 8;
+  optional PrintingEnabledProto PrintingEnabled = 9;
+  optional SafeBrowsingEnabledProto SafeBrowsingEnabled = 10;
+  optional MetricsReportingEnabledProto MetricsReportingEnabled = 11;
+  optional PasswordManagerProto PasswordManager = 12;
+  optional AutoFillEnabledProto AutoFillEnabled = 13;
+  optional DisabledPluginsProto DisabledPlugins = 14;
+  optional SyncDisabledProto SyncDisabled = 15;
+  optional ProxyProto Proxy = 16;
+  optional HTTPAuthenticationProto HTTPAuthentication = 17;
+  optional ExtensionsProto Extensions = 18;
+  optional ShowHomeButtonProto ShowHomeButton = 19;
+  optional DeveloperToolsDisabledProto DeveloperToolsDisabled = 20;
+  optional RestoreOnStartupGroupProto RestoreOnStartupGroup = 21;
+  optional DefaultSearchProviderProto DefaultSearchProvider = 22;
+  optional ContentSettingsProto ContentSettings = 23;
+  optional Disable3DAPIsProto Disable3DAPIs = 24;
+  optional ChromeFrameRendererSettingsProto ChromeFrameRendererSettings = 25;
+  optional ChromeFrameContentTypesProto ChromeFrameContentTypes = 26;
+  optional ChromeOsLockOnIdleSuspendProto ChromeOsLockOnIdleSuspend = 27;
+}
diff --git a/chrome/browser/policy/proto/device_management_backend.proto b/chrome/browser/policy/proto/device_management_backend.proto
index 0f2451b..3187f6b 100644
--- a/chrome/browser/policy/proto/device_management_backend.proto
+++ b/chrome/browser/policy/proto/device_management_backend.proto
@@ -1,13 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 syntax = "proto2";
 
+import "cloud_policy.proto";
+
 option optimize_for = LITE_RUNTIME;
 
 package enterprise_management;
 
+// Protocol buffers for the obsolete protocol:
+// -------------------------------------------
+//    GenericValue, GenericNamedValue, GenericSetting, DevicePolicySetting,
+//    DevicePolicySettingRequest, DevicePolicyRequest, DevicePolicyResponse
+// TODO(gfeher): Remove these when both Chrome and DMServer is switched to
+// using the new protocol.
+
 // Generic value container.
 message GenericValue {
   enum ValueType {
@@ -57,27 +66,6 @@
   optional string watermark = 3;
 }
 
-// Request from device to server to register device.
-message DeviceRegisterRequest {
-  // reregister device without erasing server state.
-  // it can be used to refresh dmtoken etc.
-  optional bool reregister = 1;
-}
-
-// Response from server to device register request.
-message DeviceRegisterResponse {
-  // device mangement toke for this registration.
-  required string device_management_token = 1;
-}
-
-// Request from device to server to unregister device.
-message DeviceUnregisterRequest {
-}
-
-// Response from server to device unregister request.
-message DeviceUnregisterResponse {
-}
-
 // Request for a setting or with optional watermark on client side.
 message DevicePolicySettingRequest {
   // setting key
@@ -100,26 +88,117 @@
   repeated DevicePolicySetting setting = 1;
 }
 
+// Protocol buffers for the new protocol:
+// --------------------------------------
+
+// Request from device to server to query if the authenticated user is in a
+// managed domain.
+message ManagedCheckRequest {
+}
+
+// Response from server to device indicating if the authenticated user is in a 
+// managed domain.
+message ManagedCheckResponse {
+  enum Mode {
+    // The device must be enrolled for policies.
+    MANAGED = 1;
+    // The device is not automatically enrolled for policies, but the user
+    // may choose to try to enroll it.
+    UNMANAGED = 2;
+  }
+
+  optional Mode mode = 1; 
+}
+
+// Request from device to server to register device.
+message DeviceRegisterRequest {
+  // reregister device without erasing server state.
+  // it can be used to refresh dmtoken etc.
+  optional bool reregister = 1;
+}
+
+// Response from server to device register request.
+message DeviceRegisterResponse {
+  // device mangement toke for this registration.
+  required string device_management_token = 1;
+
+  // The name of the device, assigned by the server.
+  optional string device_name = 2;
+}
+
+// Request from device to server to unregister device.
+message DeviceUnregisterRequest {
+}
+
+// Response from server to device unregister request.
+message DeviceUnregisterResponse {
+}
+
+message CloudPolicyRequest {
+  // Identify request scope: chromeos/device for device policies, chromeos/user
+  // for user policies.
+  optional string policy_scope = 1;
+  // The device token of the owner of the device sending the request. In cases
+  // the request was sent by the device owner or device policies were
+  // requested, this is the same as the token used for authentication.
+  // Otherwise (if the user policy is requested for someone else than the device
+  // owner) this token is different from the token used for authentication.
+  optional string device_token = 2;
+}
+
+// Response from server to device for reading policies.
+message CloudPolicyResponse {
+  // Serialized SignedCloudPolicyResponse.
+  optional bytes signed_response = 1;
+  // RSA signature of the SHA1 hash of the above data.
+  optional bytes signature = 2;
+  // The chain of DER-encoded X.509 certificates of the server's signing key.
+  // The first element should be the certificate whose private key was used
+  // for signing the response, and each of the following certificates signs the
+  // previous one.
+  repeated bytes certificate_chain = 3;
+}
+message SignedCloudPolicyResponse {
+  // The following two are necessary against replay attacks.
+  // |timestamp| is a unix timestamp (seconds since 1970).
+  optional int64 timestamp = 1;
+  // The token that was used for the request.
+  optional string request_token = 2;
+  // The name of the device, assigned by the server.
+  optional string device_name = 3;
+  // CloudPolicySettings is defined in cloud_policy.proto (which is
+  // auto-generated from chrome/app/policy_templates.json).
+  optional CloudPolicySettings settings = 4;
+}
+
 // Request from the DMAgent on the device to the DMServer.
 // This is container for all requests from client.
 //
+// Http Query parameters:
+// Query parameters contain the following information in each request:
+//   request: register/unregister/policy/cloud_policy/managed_check etc.
+//   devicetype: CrOS/Android/Iphone etc.
+//   apptype: CrOS/AndroidDM etc.
+//   deviceid: unique id that identify the device.
+//   agent: identify agent on device.
+//
 // Authorization:
-// 1. If request is register_request, client must pass in GoogleLogin auth
+// 1. If request is managed_check, client must pass in GoogleLogin auth 
+//    cookie in Authorization header:
+//      Authorization: GoogleLogin auth=<auth cookie>
+//    This is the only case when the deviceid query parameter is set to empty.
+//    The response will contain a flag indicating if the user is in a managed
+//    domain or not. (We don't want to expose device ids of users not in
+//    managed domains.)
+// 2. If request is register_request, client must pass in GoogleLogin auth
 //    cookie in Authorization header:
 //      Authorization: GoogleLogin auth=<auth cookie>
 //    The response will contain an unique DMToken for future requests.
 //    Depending on domain policy, the request may need admin approval before
 //    DMToken is issued.
-// 2. For other requests, client must pass in DMToken in Authorization header:
+// 3. For other requests, client must pass in DMToken in Authorization header:
 //    Authorization: GoogleDMToken token=<google dm token>
 //
-// Http Query parameters:
-// Query parameters contain the following information in each request:
-//   request: register/unregister/policy etc.
-//   devicetype: CrOS/Android/Iphone etc.
-//   apptype: CrOS/AndroidDM etc.
-//   deviceid: unique id that identify the device.
-//   agent: identify agent on device.
 message DeviceManagementRequest {
   // Register request.
   optional DeviceRegisterRequest register_request = 1;
@@ -129,6 +208,12 @@
 
   // Data request.
   optional DevicePolicyRequest policy_request = 3;
+
+  // Data request (new protocol).
+  optional CloudPolicyRequest cloud_policy_request = 4;
+
+  // Request to check if a user is managed or not.
+  optional ManagedCheckRequest managed_check_request = 5;
 }
 
 // Response from server to device.
@@ -164,4 +249,10 @@
 
   // Policy response.
   optional DevicePolicyResponse policy_response = 5;
-}
+
+  // Policy response (new protocol).
+  optional CloudPolicyResponse cloud_policy_response  = 6;
+
+  // Response to managed check request.
+  optional ManagedCheckResponse managed_check_response = 7;
+}
\ No newline at end of file
diff --git a/chrome/browser/policy/proto/device_management_proto.gyp b/chrome/browser/policy/proto/device_management_proto.gyp
index 0fc6f82..ede0251 100644
--- a/chrome/browser/policy/proto/device_management_proto.gyp
+++ b/chrome/browser/policy/proto/device_management_proto.gyp
@@ -13,6 +13,7 @@
       'target_name': 'device_management_proto',
       'type': 'none',
       'sources': [
+        'cloud_policy.proto',
         'device_management_backend.proto',
         'device_management_local.proto',
       ],
diff --git a/chrome/browser/popup_blocker_browsertest.cc b/chrome/browser/popup_blocker_browsertest.cc
index 890eff4..1bcb4ea 100644
--- a/chrome/browser/popup_blocker_browsertest.cc
+++ b/chrome/browser/popup_blocker_browsertest.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -41,4 +40,3 @@
 }
 
 }  // namespace
-
diff --git a/chrome/browser/possible_url_model.cc b/chrome/browser/possible_url_model.cc
index 31bfd2b..ca6276d 100644
--- a/chrome/browser/possible_url_model.cc
+++ b/chrome/browser/possible_url_model.cc
@@ -4,9 +4,6 @@
 
 #include "chrome/browser/possible_url_model.h"
 
-#include "app/resource_bundle.h"
-#include "app/table_model_observer.h"
-#include "app/text_elider.h"
 #include "base/callback.h"
 #include "base/i18n/rtl.h"
 #include "base/string_util.h"
@@ -16,10 +13,13 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/models/table_model_observer.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/codec/png_codec.h"
 
 using base::Time;
 using base::TimeDelta;
@@ -43,7 +43,7 @@
   // fav_icon_map_ to lookup the favicon for the url, as well as the index
   // into results_ when the favicon is received.
   size_t index;
-  gfx::SortedDisplayURL display_url;
+  ui::SortedDisplayURL display_url;
   std::wstring title;
 };
 
@@ -87,7 +87,7 @@
     results_[i].url = (*result)[i].url();
     results_[i].index = i;
     results_[i].display_url =
-        gfx::SortedDisplayURL((*result)[i].url(), languages);
+        ui::SortedDisplayURL((*result)[i].url(), languages);
     results_[i].title = UTF16ToWide((*result)[i].title());
   }
 
@@ -180,7 +180,7 @@
     return results_[row1].display_url.Compare(
         results_[row2].display_url, GetCollator());
   }
-  return TableModel::CompareValues(row1, row2, column_id);
+  return ui::TableModel::CompareValues(row1, row2, column_id);
 }
 
 void PossibleURLModel::OnFavIconAvailable(
@@ -205,6 +205,6 @@
   }
 }
 
-void PossibleURLModel::SetObserver(TableModelObserver* observer) {
+void PossibleURLModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
diff --git a/chrome/browser/possible_url_model.h b/chrome/browser/possible_url_model.h
index 8bd61c6..338a4e2 100644
--- a/chrome/browser/possible_url_model.h
+++ b/chrome/browser/possible_url_model.h
@@ -10,9 +10,9 @@
 #include <string>
 #include <vector>
 
-#include "app/table_model.h"
 #include "base/compiler_specific.h"
 #include "chrome/browser/history/history.h"
+#include "ui/base/models/table_model.h"
 
 class SkBitmap;
 
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-class PossibleURLModel : public TableModel {
+class PossibleURLModel : public ui::TableModel {
  public:
   PossibleURLModel();
   virtual ~PossibleURLModel();
@@ -47,14 +47,14 @@
   virtual string16 GetText(int row, int col_id) OVERRIDE;
   virtual SkBitmap GetIcon(int row) OVERRIDE;
   virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
  private:
   // The current profile.
   Profile* profile_;
 
   // Our observer.
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   // Our consumer for favicon requests.
   CancelableRequestConsumerT<size_t, NULL> consumer_;
diff --git a/chrome/browser/ppapi_plugin_process_host.cc b/chrome/browser/ppapi_plugin_process_host.cc
index c90d1f4..c319dd0 100644
--- a/chrome/browser/ppapi_plugin_process_host.cc
+++ b/chrome/browser/ppapi_plugin_process_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,40 +7,36 @@
 #include "base/command_line.h"
 #include "base/file_path.h"
 #include "base/process_util.h"
+#include "chrome/browser/plugin_service.h"
 #include "chrome/browser/renderer_host/render_message_filter.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/render_messages.h"
 #include "ipc/ipc_switches.h"
 #include "ppapi/proxy/ppapi_messages.h"
 
-PpapiPluginProcessHost::PpapiPluginProcessHost(RenderMessageFilter* filter)
-    : BrowserChildProcessHost(ChildProcessInfo::PPAPI_PLUGIN_PROCESS,
-                              filter->resource_dispatcher_host()),
-      filter_(filter) {
+PpapiPluginProcessHost::PpapiPluginProcessHost()
+    : BrowserChildProcessHost(
+          ChildProcessInfo::PPAPI_PLUGIN_PROCESS,
+          PluginService::GetInstance()->resource_dispatcher_host()) {
 }
 
 PpapiPluginProcessHost::~PpapiPluginProcessHost() {
+  CancelRequests();
 }
 
-void PpapiPluginProcessHost::Init(const FilePath& path,
-                                  IPC::Message* reply_msg) {
+bool PpapiPluginProcessHost::Init(const FilePath& path) {
   plugin_path_ = path;
-  reply_msg_.reset(reply_msg);
 
-  if (!CreateChannel()) {
-    ReplyToRenderer(NULL, IPC::ChannelHandle());
-    return;
-  }
+  if (!CreateChannel())
+    return false;
 
   const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
   CommandLine::StringType plugin_launcher =
       browser_command_line.GetSwitchValueNative(switches::kPpapiPluginLauncher);
 
   FilePath exe_path = ChildProcessHost::GetChildPath(plugin_launcher.empty());
-  if (exe_path.empty()) {
-    ReplyToRenderer(NULL, IPC::ChannelHandle());
-    return;
-  }
+  if (exe_path.empty())
+    return false;
 
   CommandLine* cmd_line = new CommandLine(exe_path);
   cmd_line->AppendSwitchASCII(switches::kProcessType,
@@ -60,6 +56,36 @@
       base::environment_vector(),
 #endif
       cmd_line);
+  return true;
+}
+
+void PpapiPluginProcessHost::OpenChannelToPlugin(Client* client) {
+  if (opening_channel()) {
+    // The channel is already in the process of being opened.  Put
+    // this "open channel" request into a queue of requests that will
+    // be run once the channel is open.
+    pending_requests_.push_back(client);
+    return;
+  }
+
+  // We already have an open channel, send a request right away to plugin.
+  RequestPluginChannel(client);
+}
+
+void PpapiPluginProcessHost::RequestPluginChannel(Client* client) {
+  base::ProcessHandle process_handle;
+  int renderer_id;
+  client->GetChannelInfo(&process_handle, &renderer_id);
+
+  // We can't send any sync messages from the browser because it might lead to
+  // a hang. See the similar code in PluginProcessHost for more description.
+  PpapiMsg_CreateChannel* msg = new PpapiMsg_CreateChannel(process_handle,
+                                                           renderer_id);
+  msg->set_unblock(true);
+  if (Send(msg))
+    sent_requests_.push(client);
+  else
+    client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
 }
 
 bool PpapiPluginProcessHost::CanShutdown() {
@@ -72,56 +98,77 @@
 bool PpapiPluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(PpapiPluginProcessHost, msg)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PluginLoaded, OnPluginLoaded)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated,
+                        OnRendererPluginChannelCreated)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   DCHECK(handled);
   return handled;
 }
 
+// Called when the browser <--> plugin channel has been established.
 void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) {
-#if defined(OS_WIN)
-  base::ProcessHandle plugins_renderer_handle = NULL;
-  ::DuplicateHandle(::GetCurrentProcess(), filter_->peer_handle(),
-                    GetChildProcessHandle(), &plugins_renderer_handle,
-                    0, FALSE, DUPLICATE_SAME_ACCESS);
-#elif defined(OS_POSIX)
-  base::ProcessHandle plugins_renderer_handle = filter_->peer_handle();
-#endif
+  // This will actually load the plugin. Errors will actually not be reported
+  // back at this point. Instead, the plugin will fail to establish the
+  // connections when we request them on behalf of the renderer(s).
+  Send(new PpapiMsg_LoadPlugin(plugin_path_));
 
-  PpapiMsg_LoadPlugin* msg = new PpapiMsg_LoadPlugin(
-      plugins_renderer_handle, plugin_path_, filter_->render_process_id());
-  if (!Send(msg))  // Just send an empty handle on failure.
-    ReplyToRenderer(NULL, IPC::ChannelHandle());
-  // This function will result in OnChannelCreated getting called to finish.
+  // Process all pending channel requests from the renderers.
+  for (size_t i = 0; i < pending_requests_.size(); i++)
+    RequestPluginChannel(pending_requests_[i]);
+  pending_requests_.clear();
 }
 
+// Called when the browser <--> plugin channel has an error. This normally
+// means the plugin has crashed.
 void PpapiPluginProcessHost::OnChannelError() {
-  if (reply_msg_.get())
-    ReplyToRenderer(NULL, IPC::ChannelHandle());
+  // We don't need to notify the renderers that were communicating with the
+  // plugin since they have their own channels which will go into the error
+  // state at the same time. Instead, we just need to notify any renderers
+  // that have requested a connection but have not yet received one.
+  CancelRequests();
 }
 
-void PpapiPluginProcessHost::OnPluginLoaded(
+void PpapiPluginProcessHost::CancelRequests() {
+  for (size_t i = 0; i < pending_requests_.size(); i++) {
+    pending_requests_[i]->OnChannelOpened(base::kNullProcessHandle,
+                                          IPC::ChannelHandle());
+  }
+  pending_requests_.clear();
+
+  while (!sent_requests_.empty()) {
+    sent_requests_.front()->OnChannelOpened(base::kNullProcessHandle,
+                                            IPC::ChannelHandle());
+    sent_requests_.pop();
+  }
+}
+
+// Called when a new plugin <--> renderer channel has been created.
+void PpapiPluginProcessHost::OnRendererPluginChannelCreated(
     const IPC::ChannelHandle& channel_handle) {
+  if (sent_requests_.empty())
+    return;
+
+  // All requests should be processed FIFO, so the next item in the
+  // sent_requests_ queue should be the one that the plugin just created.
+  Client* client = sent_requests_.front();
+  sent_requests_.pop();
+
+  // Prepare the handle to send to the renderer.
   base::ProcessHandle plugin_process = GetChildProcessHandle();
 #if defined(OS_WIN)
+  base::ProcessHandle renderer_process;
+  int renderer_id;
+  client->GetChannelInfo(&renderer_process, &renderer_id);
+
   base::ProcessHandle renderers_plugin_handle = NULL;
   ::DuplicateHandle(::GetCurrentProcess(), plugin_process,
-                    filter_->peer_handle(), &renderers_plugin_handle,
+                    renderer_process, &renderers_plugin_handle,
                     0, FALSE, DUPLICATE_SAME_ACCESS);
 #elif defined(OS_POSIX)
   // Don't need to duplicate anything on POSIX since it's just a PID.
   base::ProcessHandle renderers_plugin_handle = plugin_process;
 #endif
-  ReplyToRenderer(renderers_plugin_handle, channel_handle);
-}
 
-void PpapiPluginProcessHost::ReplyToRenderer(
-    base::ProcessHandle plugin_handle,
-    const IPC::ChannelHandle& channel_handle) {
-  DCHECK(reply_msg_.get());
-  ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(reply_msg_.get(),
-                                                          plugin_handle,
-                                                          channel_handle);
-  filter_->Send(reply_msg_.release());
+  client->OnChannelOpened(renderers_plugin_handle, channel_handle);
 }
diff --git a/chrome/browser/ppapi_plugin_process_host.h b/chrome/browser/ppapi_plugin_process_host.h
index 227cf31..945195d 100644
--- a/chrome/browser/ppapi_plugin_process_host.h
+++ b/chrome/browser/ppapi_plugin_process_host.h
@@ -6,20 +6,48 @@
 #define CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_
 #pragma once
 
+#include <queue>
+
 #include "base/basictypes.h"
 #include "base/file_path.h"
 #include "chrome/browser/browser_child_process_host.h"
 
-class RenderMessageFilter;
-
 class PpapiPluginProcessHost : public BrowserChildProcessHost {
  public:
-  explicit PpapiPluginProcessHost(RenderMessageFilter* filter);
+  class Client {
+   public:
+    // Gets the information about the renderer that's requesting the channel.
+    virtual void GetChannelInfo(base::ProcessHandle* renderer_handle,
+                                int* renderer_id) = 0;
+
+    // Called when the channel is asynchronously opened to the plugin or on
+    // error. On error, the parameters should be:
+    //   base::kNullProcessHandle
+    //   IPC::ChannelHandle()
+    virtual void OnChannelOpened(base::ProcessHandle plugin_process_handle,
+                                 const IPC::ChannelHandle& channel_handle) = 0;
+  };
+
+  // You must call init before doing anything else.
+  explicit PpapiPluginProcessHost();
   virtual ~PpapiPluginProcessHost();
 
-  void Init(const FilePath& path, IPC::Message* reply_msg);
+  // Actually launches the process with the given plugin path. Returns true
+  // on success (the process was spawned).
+  bool Init(const FilePath& path);
+
+  // Opens a new channel to the plugin. The client will be notified when the
+  // channel is ready or if there's an error.
+  void OpenChannelToPlugin(Client* client);
+
+  const FilePath& plugin_path() const { return plugin_path_; }
+
+  // The client pointer must remain valid until its callback is issued.
 
  private:
+
+  void RequestPluginChannel(Client* client);
+
   virtual bool CanShutdown();
   virtual void OnProcessLaunched();
 
@@ -27,22 +55,22 @@
   virtual void OnChannelConnected(int32 peer_pid);
   virtual void OnChannelError();
 
+  void CancelRequests();
+
   // IPC message handlers.
-  void OnPluginLoaded(const IPC::ChannelHandle& handle);
+  void OnRendererPluginChannelCreated(const IPC::ChannelHandle& handle);
 
-  // Sends the reply_msg_ to the renderer with the given channel info.
-  void ReplyToRenderer(base::ProcessHandle plugin_handle,
-                       const IPC::ChannelHandle& channel_handle);
+  // Channel requests that we are waiting to send to the plugin process once
+  // the channel is opened.
+  std::vector<Client*> pending_requests_;
 
-  RenderMessageFilter* filter_;
+  // Channel requests that we have already sent to the plugin process, but
+  // haven't heard back about yet.
+  std::queue<Client*> sent_requests_;
 
   // Path to the plugin library.
   FilePath plugin_path_;
 
-  // When we're waiting for initialization of the plugin, this contains the
-  // reply message for the renderer to tell it that it can continue.
-  scoped_ptr<IPC::Message> reply_msg_;
-
   DISALLOW_COPY_AND_ASSIGN(PpapiPluginProcessHost);
 };
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 1aa3c9e..ba65eb9 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,32 +12,31 @@
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/content_settings/policy_content_settings_provider.h"
-#include "chrome/browser/content_settings/pref_content_settings_provider.h"
 #include "chrome/browser/debugger/devtools_manager.h"
 #include "chrome/browser/dom_ui/flags_ui.h"
 #include "chrome/browser/dom_ui/new_tab_ui.h"
 #include "chrome/browser/dom_ui/plugins_ui.h"
 #include "chrome/browser/download/download_prefs.h"
-#include "chrome/browser/extensions/extension_dom_ui.h"
 #include "chrome/browser/extensions/extension_prefs.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/extensions/extensions_ui.h"
 #include "chrome/browser/external_protocol_handler.h"
 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
 #include "chrome/browser/geolocation/geolocation_prefs.h"
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/browser/host_zoom_map.h"
-#include "chrome/browser/intranet_redirect_detector.h"
 #include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/intranet_redirect_detector.h"
 #include "chrome/browser/metrics/metrics_log.h"
 #include "chrome/browser/metrics/metrics_service.h"
+#include "chrome/browser/net/net_pref_observer.h"
 #include "chrome/browser/net/predictor_api.h"
 #include "chrome/browser/net/pref_proxy_config_service.h"
-#include "chrome/browser/net/net_pref_observer.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/page_info_model.h"
 #include "chrome/browser/password_manager/password_manager.h"
+#include "chrome/browser/policy/profile_policy_context.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile_impl.h"
 #include "chrome/browser/renderer_host/browser_render_process_host.h"
@@ -54,23 +53,25 @@
 #include "chrome/browser/translate/translate_prefs.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/upgrade_detector.h"
+#include "chrome/common/pref_names.h"
 
 #if defined(TOOLKIT_VIEWS)  // TODO(port): whittle this down as we port
-#include "chrome/browser/views/browser_actions_container.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/browser_actions_container.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #endif
 
 #if defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/audio_mixer_alsa.h"
 #include "chrome/browser/chromeos/login/apply_services_customization.h"
 #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/preferences.h"
-#include "chrome/browser/chromeos/status/input_method_menu_button.h"
+#include "chrome/browser/chromeos/status/input_method_menu.h"
 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
 #endif
 
@@ -84,6 +85,7 @@
 void RegisterLocalState(PrefService* local_state) {
   // Prefs in Local State
   Browser::RegisterPrefs(local_state);
+  FlagsUI::RegisterPrefs(local_state);
   WebCacheManager::RegisterPrefs(local_state);
   ExternalProtocolHandler::RegisterPrefs(local_state);
   GoogleURLTracker::RegisterPrefs(local_state);
@@ -103,10 +105,11 @@
   BackgroundPageTracker::RegisterPrefs(local_state);
   NotificationUIManager::RegisterPrefs(local_state);
 #if defined(OS_CHROMEOS)
+  chromeos::AudioMixerAlsa::RegisterPrefs(local_state);
   chromeos::UserManager::RegisterPrefs(local_state);
   chromeos::UserCrosSettingsProvider::RegisterPrefs(local_state);
   WizardController::RegisterPrefs(local_state);
-  chromeos::InputMethodMenuButton::RegisterPrefs(local_state);
+  chromeos::InputMethodMenu::RegisterPrefs(local_state);
   chromeos::ApplyServicesCustomization::RegisterPrefs(local_state);
   chromeos::SignedSettingsTempStorage::RegisterPrefs(local_state);
 #endif
@@ -123,15 +126,12 @@
   bookmark_utils::RegisterUserPrefs(user_prefs);
   TabContents::RegisterUserPrefs(user_prefs);
   TemplateURLPrepopulateData::RegisterUserPrefs(user_prefs);
-  ExtensionDOMUI::RegisterUserPrefs(user_prefs);
+  ExtensionWebUI::RegisterUserPrefs(user_prefs);
   ExtensionsUI::RegisterUserPrefs(user_prefs);
-  FlagsUI::RegisterUserPrefs(user_prefs);
   NewTabUI::RegisterUserPrefs(user_prefs);
   PluginsUI::RegisterUserPrefs(user_prefs);
   ProfileImpl::RegisterUserPrefs(user_prefs);
   HostContentSettingsMap::RegisterUserPrefs(user_prefs);
-  PolicyContentSettingsProvider::RegisterUserPrefs(user_prefs);
-  PrefContentSettingsProvider::RegisterUserPrefs(user_prefs);
   HostZoomMap::RegisterUserPrefs(user_prefs);
   DevToolsManager::RegisterUserPrefs(user_prefs);
   PinnedTabCodec::RegisterUserPrefs(user_prefs);
@@ -153,6 +153,38 @@
   TemplateURLModel::RegisterUserPrefs(user_prefs);
   InstantController::RegisterUserPrefs(user_prefs);
   NetPrefObserver::RegisterPrefs(user_prefs);
+  policy::ProfilePolicyContext::RegisterUserPrefs(user_prefs);
+}
+
+void MigrateBrowserPrefs(PrefService* user_prefs, PrefService* local_state) {
+  // Copy pref values which have been migrated to user_prefs from local_state,
+  // or remove them from local_state outright, if copying is not required.
+  int current_version =
+      local_state->GetInteger(prefs::kMultipleProfilePrefMigration);
+
+  if ((current_version & WINDOWS_PREFS) == 0) {
+    // Migrate the devtools split location preference.
+    local_state->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
+    DCHECK(user_prefs->FindPreference(prefs::kDevToolsSplitLocation));
+    if (local_state->HasPrefPath(prefs::kDevToolsSplitLocation)) {
+      user_prefs->SetInteger(prefs::kDevToolsSplitLocation,
+          local_state->GetInteger(prefs::kDevToolsSplitLocation));
+    }
+    local_state->ClearPref(prefs::kDevToolsSplitLocation);
+
+    // Migrate the browser window placement preference.
+    local_state->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
+    DCHECK(user_prefs->FindPreference(prefs::kBrowserWindowPlacement));
+    if (local_state->HasPrefPath(prefs::kBrowserWindowPlacement)) {
+      user_prefs->Set(prefs::kBrowserWindowPlacement,
+          *(local_state->FindPreference(prefs::kBrowserWindowPlacement)->
+              GetValue()));
+    }
+    local_state->ClearPref(prefs::kBrowserWindowPlacement);
+
+    local_state->SetInteger(prefs::kMultipleProfilePrefMigration,
+                            current_version | WINDOWS_PREFS);
+  }
 }
 
 }  // namespace browser
diff --git a/chrome/browser/prefs/browser_prefs.h b/chrome/browser/prefs/browser_prefs.h
index ef109a4..4df26c1 100644
--- a/chrome/browser/prefs/browser_prefs.h
+++ b/chrome/browser/prefs/browser_prefs.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,11 +10,19 @@
 
 namespace browser {
 
+// Bitmask for kMultipleProfilePrefMigration.
+enum MigratedPreferences {
+  NO_PREFS = 0,
+  DNS_PREFS = 1 << 0,
+  WINDOWS_PREFS = 1 << 1,
+};
+
 // Makes the PrefService objects aware of all the prefs.
 void RegisterAllPrefs(PrefService* user_prefs, PrefService* local_state);
 void RegisterLocalState(PrefService* local_state);
 void RegisterUserPrefs(PrefService* user_prefs);
-
+// Migrate prefs from local_state to user_prefs.
+void MigrateBrowserPrefs(PrefService* user_prefs, PrefService* local_state);
 } // namespace browser
 
 #endif  // CHROME_BROWSER_PREFS_BROWSER_PREFS_H__
diff --git a/chrome/browser/prefs/command_line_pref_store.cc b/chrome/browser/prefs/command_line_pref_store.cc
index 4a386d6..97e0d39 100644
--- a/chrome/browser/prefs/command_line_pref_store.cc
+++ b/chrome/browser/prefs/command_line_pref_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,16 +7,14 @@
 #include "app/app_switches.h"
 #include "base/logging.h"
 #include "base/values.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
+#include "ui/base/ui_base_switches.h"
 
 const CommandLinePrefStore::StringSwitchToPreferenceMapEntry
     CommandLinePrefStore::string_switch_map_[] = {
       { switches::kLang, prefs::kApplicationLocale },
-      { switches::kProxyServer, prefs::kProxyServer },
-      { switches::kProxyPacUrl, prefs::kProxyPacUrl },
-      { switches::kProxyBypassList, prefs::kProxyBypassList },
       { switches::kAuthSchemes, prefs::kAuthSchemes },
       { switches::kAuthServerWhitelist, prefs::kAuthServerWhitelist },
       { switches::kAuthNegotiateDelegateWhitelist,
@@ -31,6 +29,8 @@
       { switches::kEnableAuthNegotiatePort, prefs::kEnableAuthNegotiatePort,
           true },
       { switches::kDisable3DAPIs, prefs::kDisable3DAPIs, true },
+      { switches::kEnableCloudPrintProxy, prefs::kCloudPrintProxyEnabled,
+          true },
 };
 
 CommandLinePrefStore::CommandLinePrefStore(const CommandLine* command_line)
@@ -76,16 +76,23 @@
 
 void CommandLinePrefStore::ApplyProxyMode() {
   if (command_line_->HasSwitch(switches::kNoProxyServer)) {
-    SetValue(prefs::kProxyMode,
-             Value::CreateIntegerValue(ProxyPrefs::MODE_DIRECT));
+    SetValue(prefs::kProxy,
+             ProxyConfigDictionary::CreateDirect());
   } else if (command_line_->HasSwitch(switches::kProxyPacUrl)) {
-    SetValue(prefs::kProxyMode,
-             Value::CreateIntegerValue(ProxyPrefs::MODE_PAC_SCRIPT));
+    std::string pac_script_url =
+        command_line_->GetSwitchValueASCII(switches::kProxyPacUrl);
+    SetValue(prefs::kProxy,
+             ProxyConfigDictionary::CreatePacScript(pac_script_url));
   } else if (command_line_->HasSwitch(switches::kProxyAutoDetect)) {
-    SetValue(prefs::kProxyMode,
-             Value::CreateIntegerValue(ProxyPrefs::MODE_AUTO_DETECT));
+    SetValue(prefs::kProxy,
+             ProxyConfigDictionary::CreateAutoDetect());
   } else if (command_line_->HasSwitch(switches::kProxyServer)) {
-    SetValue(prefs::kProxyMode,
-             Value::CreateIntegerValue(ProxyPrefs::MODE_FIXED_SERVERS));
+    std::string proxy_server =
+        command_line_->GetSwitchValueASCII(switches::kProxyServer);
+    std::string bypass_list =
+        command_line_->GetSwitchValueASCII(switches::kProxyBypassList);
+    SetValue(prefs::kProxy,
+             ProxyConfigDictionary::CreateFixedServers(proxy_server,
+                                                       bypass_list));
   }
 }
diff --git a/chrome/browser/prefs/command_line_pref_store_unittest.cc b/chrome/browser/prefs/command_line_pref_store_unittest.cc
index 1be9c0a..edc88d9 100644
--- a/chrome/browser/prefs/command_line_pref_store_unittest.cc
+++ b/chrome/browser/prefs/command_line_pref_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,14 @@
 
 #include "app/app_switches.h"
 #include "base/command_line.h"
+#include "base/ref_counted.h"
 #include "base/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/prefs/command_line_pref_store.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
+#include "ui/base/ui_base_switches.h"
 
 namespace {
 
@@ -24,10 +26,14 @@
     return ValidateProxySwitches();
   }
 
-  void VerifyIntPref(const std::string& path, int expected_value) {
-    Value* actual = NULL;
-    ASSERT_EQ(PrefStore::READ_OK, GetValue(path, &actual));
-    EXPECT_TRUE(FundamentalValue(expected_value).Equals(actual));
+  void VerifyProxyMode(ProxyPrefs::ProxyMode expected_mode) {
+    Value* value = NULL;
+    ASSERT_EQ(PrefStore::READ_OK, GetValue(prefs::kProxy, &value));
+    ASSERT_EQ(Value::TYPE_DICTIONARY, value->GetType());
+    ProxyConfigDictionary dict(static_cast<DictionaryValue*>(value));
+    ProxyPrefs::ProxyMode actual_mode;
+    ASSERT_TRUE(dict.GetMode(&actual_mode));
+    EXPECT_EQ(expected_mode, actual_mode);
   }
 };
 
@@ -40,11 +46,11 @@
 TEST(CommandLinePrefStoreTest, SimpleStringPref) {
   CommandLine cl(CommandLine::NO_PROGRAM);
   cl.AppendSwitchASCII(switches::kLang, "hi-MOM");
-  CommandLinePrefStore store(&cl);
+  scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl);
 
   Value* actual = NULL;
   EXPECT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kApplicationLocale, &actual));
+            store->GetValue(prefs::kApplicationLocale, &actual));
   std::string result;
   EXPECT_TRUE(actual->GetAsString(&result));
   EXPECT_EQ("hi-MOM", result);
@@ -54,9 +60,10 @@
 TEST(CommandLinePrefStoreTest, SimpleBooleanPref) {
   CommandLine cl(CommandLine::NO_PROGRAM);
   cl.AppendSwitch(switches::kNoProxyServer);
-  TestCommandLinePrefStore store(&cl);
+  scoped_refptr<TestCommandLinePrefStore> store =
+      new TestCommandLinePrefStore(&cl);
 
-  store.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_DIRECT);
+  store->VerifyProxyMode(ProxyPrefs::MODE_DIRECT);
 }
 
 // Tests a command line with no recognized prefs.
@@ -64,35 +71,40 @@
   CommandLine cl(CommandLine::NO_PROGRAM);
   cl.AppendSwitch(unknown_string);
   cl.AppendSwitchASCII(unknown_bool, "a value");
-  CommandLinePrefStore store(&cl);
+  scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl);
 
   Value* actual = NULL;
-  EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_bool, &actual));
-  EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_string, &actual));
+  EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_bool, &actual));
+  EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_string, &actual));
 }
 
 // Tests a complex command line with multiple known and unknown switches.
 TEST(CommandLinePrefStoreTest, MultipleSwitches) {
   CommandLine cl(CommandLine::NO_PROGRAM);
   cl.AppendSwitch(unknown_string);
-  cl.AppendSwitch(switches::kProxyAutoDetect);
   cl.AppendSwitchASCII(switches::kProxyServer, "proxy");
   cl.AppendSwitchASCII(switches::kProxyBypassList, "list");
   cl.AppendSwitchASCII(unknown_bool, "a value");
-  TestCommandLinePrefStore store(&cl);
+  scoped_refptr<TestCommandLinePrefStore> store =
+      new TestCommandLinePrefStore(&cl);
 
   Value* actual = NULL;
-  EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_bool, &actual));
-  store.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_AUTO_DETECT);
+  EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_bool, &actual));
+  EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_string, &actual));
 
-  EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_string, &actual));
+  store->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS);
+
+  Value* value = NULL;
+  ASSERT_EQ(PrefStore::READ_OK, store->GetValue(prefs::kProxy, &value));
+  ASSERT_EQ(Value::TYPE_DICTIONARY, value->GetType());
+  ProxyConfigDictionary dict(static_cast<DictionaryValue*>(value));
+
   std::string string_result = "";
-  ASSERT_EQ(PrefStore::READ_OK, store.GetValue(prefs::kProxyServer, &actual));
-  EXPECT_TRUE(actual->GetAsString(&string_result));
+
+  ASSERT_TRUE(dict.GetProxyServer(&string_result));
   EXPECT_EQ("proxy", string_result);
-  ASSERT_EQ(PrefStore::READ_OK,
-            store.GetValue(prefs::kProxyBypassList, &actual));
-  EXPECT_TRUE(actual->GetAsString(&string_result));
+
+  ASSERT_TRUE(dict.GetBypassList(&string_result));
   EXPECT_EQ("list", string_result);
 }
 
@@ -101,18 +113,21 @@
   CommandLine cl(CommandLine::NO_PROGRAM);
 
   // No switches.
-  TestCommandLinePrefStore store(&cl);
-  EXPECT_TRUE(store.ProxySwitchesAreValid());
+  scoped_refptr<TestCommandLinePrefStore> store =
+      new TestCommandLinePrefStore(&cl);
+  EXPECT_TRUE(store->ProxySwitchesAreValid());
 
   // Only no-proxy.
   cl.AppendSwitch(switches::kNoProxyServer);
-  TestCommandLinePrefStore store2(&cl);
-  EXPECT_TRUE(store2.ProxySwitchesAreValid());
+  scoped_refptr<TestCommandLinePrefStore> store2 =
+      new TestCommandLinePrefStore(&cl);
+  EXPECT_TRUE(store2->ProxySwitchesAreValid());
 
   // Another proxy switch too.
   cl.AppendSwitch(switches::kProxyAutoDetect);
-  TestCommandLinePrefStore store3(&cl);
-  EXPECT_FALSE(store3.ProxySwitchesAreValid());
+  scoped_refptr<TestCommandLinePrefStore> store3 =
+      new TestCommandLinePrefStore(&cl);
+  EXPECT_FALSE(store3->ProxySwitchesAreValid());
 
   // All proxy switches except no-proxy.
   CommandLine cl2(CommandLine::NO_PROGRAM);
@@ -120,19 +135,28 @@
   cl2.AppendSwitchASCII(switches::kProxyServer, "server");
   cl2.AppendSwitchASCII(switches::kProxyPacUrl, "url");
   cl2.AppendSwitchASCII(switches::kProxyBypassList, "list");
-  TestCommandLinePrefStore store4(&cl2);
-  EXPECT_TRUE(store4.ProxySwitchesAreValid());
+  scoped_refptr<TestCommandLinePrefStore> store4 =
+      new TestCommandLinePrefStore(&cl2);
+  EXPECT_TRUE(store4->ProxySwitchesAreValid());
 }
 
 TEST(CommandLinePrefStoreTest, ManualProxyModeInference) {
   CommandLine cl1(CommandLine::NO_PROGRAM);
   cl1.AppendSwitch(unknown_string);
   cl1.AppendSwitchASCII(switches::kProxyServer, "proxy");
-  TestCommandLinePrefStore store1(&cl1);
-  store1.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_FIXED_SERVERS);
+  scoped_refptr<TestCommandLinePrefStore> store1 =
+      new TestCommandLinePrefStore(&cl1);
+  store1->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS);
 
   CommandLine cl2(CommandLine::NO_PROGRAM);
   cl2.AppendSwitchASCII(switches::kProxyPacUrl, "proxy");
-  TestCommandLinePrefStore store2(&cl2);
-  store2.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_PAC_SCRIPT);
+  scoped_refptr<TestCommandLinePrefStore> store2 =
+        new TestCommandLinePrefStore(&cl2);
+  store2->VerifyProxyMode(ProxyPrefs::MODE_PAC_SCRIPT);
+
+  CommandLine cl3(CommandLine::NO_PROGRAM);
+  cl3.AppendSwitchASCII(switches::kProxyServer, "");
+  scoped_refptr<TestCommandLinePrefStore> store3 =
+        new TestCommandLinePrefStore(&cl3);
+  store3->VerifyProxyMode(ProxyPrefs::MODE_DIRECT);
 }
diff --git a/chrome/browser/prefs/default_pref_store.cc b/chrome/browser/prefs/default_pref_store.cc
new file mode 100644
index 0000000..cacc833
--- /dev/null
+++ b/chrome/browser/prefs/default_pref_store.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/default_pref_store.h"
+
+DefaultPrefStore::DefaultPrefStore() {}
+
+DefaultPrefStore::~DefaultPrefStore() {}
+
+void DefaultPrefStore::SetDefaultValue(const std::string& key, Value* value) {
+  CHECK(GetValue(key, NULL) == READ_NO_VALUE);
+  SetValue(key, value);
+}
+
+Value::ValueType DefaultPrefStore::GetType(const std::string& key) const {
+  Value* value;
+  return GetValue(key, &value) == READ_OK ? value->GetType()
+                                          : Value::TYPE_NULL;
+}
diff --git a/chrome/browser/prefs/default_pref_store.h b/chrome/browser/prefs/default_pref_store.h
index 9e2e715..79a6a0e 100644
--- a/chrome/browser/prefs/default_pref_store.h
+++ b/chrome/browser/prefs/default_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,22 +6,24 @@
 #define CHROME_BROWSER_PREFS_DEFAULT_PREF_STORE_H_
 #pragma once
 
-#include <map>
+#include <string>
 
-#include "base/basictypes.h"
+#include "base/values.h"
 #include "chrome/browser/prefs/value_map_pref_store.h"
 
 // This PrefStore keeps track of default preference values set when a
 // preference is registered with the PrefService.
 class DefaultPrefStore : public ValueMapPrefStore {
  public:
-  DefaultPrefStore() {}
-  virtual ~DefaultPrefStore() {}
+  DefaultPrefStore();
+  virtual ~DefaultPrefStore();
 
   // Stores a new |value| for |key|. Assumes ownership of |value|.
-  void SetDefaultValue(const std::string& key, Value* value) {
-    SetValue(key, value);
-  }
+  void SetDefaultValue(const std::string& key, Value* value);
+
+  // Returns the registered type for |key| or Value::TYPE_NULL if the |key|
+  // has not been registered.
+  Value::ValueType GetType(const std::string& key) const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DefaultPrefStore);
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.cc b/chrome/browser/prefs/overlay_persistent_pref_store.cc
new file mode 100644
index 0000000..16c082a
--- /dev/null
+++ b/chrome/browser/prefs/overlay_persistent_pref_store.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/prefs/overlay_persistent_pref_store.h"
+
+OverlayPersistentPrefStore::OverlayPersistentPrefStore(
+    PersistentPrefStore* underlay)
+    : underlay_(underlay) {
+  underlay_->AddObserver(this);
+}
+OverlayPersistentPrefStore::~OverlayPersistentPrefStore() {
+  underlay_->RemoveObserver(this);
+}
+
+void OverlayPersistentPrefStore::AddObserver(PrefStore::Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void OverlayPersistentPrefStore::RemoveObserver(PrefStore::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+bool OverlayPersistentPrefStore::IsInitializationComplete() const {
+  return underlay_->IsInitializationComplete();
+}
+
+PrefStore::ReadResult OverlayPersistentPrefStore::GetValue(
+    const std::string& key, Value** result) const {
+  if (overlay_.GetValue(key, result))
+    return READ_OK;
+  return underlay_->GetValue(key, result);
+}
+
+void OverlayPersistentPrefStore::SetValue(const std::string& key,
+                                          Value* value) {
+  if (overlay_.SetValue(key, value))
+    FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
+}
+
+void OverlayPersistentPrefStore::SetValueSilently(const std::string& key,
+                                                  Value* value) {
+  overlay_.SetValue(key, value);
+}
+
+void OverlayPersistentPrefStore::RemoveValue(const std::string& key) {
+  if (overlay_.RemoveValue(key))
+    FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
+}
+
+bool OverlayPersistentPrefStore::ReadOnly() const {
+  return false;
+}
+
+PersistentPrefStore::PrefReadError OverlayPersistentPrefStore::ReadPrefs() {
+  // We do not read intentionally.
+  return PersistentPrefStore::PREF_READ_ERROR_NONE;
+}
+
+bool OverlayPersistentPrefStore::WritePrefs() {
+  // We do not write intentionally.
+  return true;
+}
+
+void OverlayPersistentPrefStore::ScheduleWritePrefs() {
+  // We do not write intentionally.
+}
+
+void OverlayPersistentPrefStore::OnPrefValueChanged(const std::string& key) {
+  if (!overlay_.GetValue(key, NULL))
+    FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
+}
+
+void OverlayPersistentPrefStore::OnInitializationCompleted() {
+  FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
+                    OnInitializationCompleted());
+}
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.h b/chrome/browser/prefs/overlay_persistent_pref_store.h
new file mode 100644
index 0000000..dcc3161
--- /dev/null
+++ b/chrome/browser/prefs/overlay_persistent_pref_store.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_PREFS_OVERLAY_PERSISTENT_PREF_STORE_H_
+#define CHROME_BROWSER_PREFS_OVERLAY_PERSISTENT_PREF_STORE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/prefs/pref_value_map.h"
+#include "chrome/common/persistent_pref_store.h"
+
+// PersistentPrefStore that directs all write operations into a in-memory
+// PrefValueMap. Read operations are first answered by the PrefValueMap.
+// If the PrefValueMap does not contain a value for the requested key,
+// the look-up is passed on to an underlying PersistentPrefStore |underlay_|.
+class OverlayPersistentPrefStore : public PersistentPrefStore,
+                                   public PrefStore::Observer {
+ public:
+  explicit OverlayPersistentPrefStore(PersistentPrefStore* underlay);
+  virtual ~OverlayPersistentPrefStore();
+
+  // Methods of PrefStore.
+  virtual void AddObserver(PrefStore::Observer* observer);
+  virtual void RemoveObserver(PrefStore::Observer* observer);
+  virtual bool IsInitializationComplete() const;
+  virtual ReadResult GetValue(const std::string& key, Value** result) const;
+
+  // Methods of PersistentPrefStore.
+  virtual void SetValue(const std::string& key, Value* value);
+  virtual void SetValueSilently(const std::string& key, Value* value);
+  virtual void RemoveValue(const std::string& key);
+  virtual bool ReadOnly() const;
+  virtual PrefReadError ReadPrefs();
+  virtual bool WritePrefs();
+  virtual void ScheduleWritePrefs();
+
+ private:
+  // Methods of PrefStore::Observer.
+  virtual void OnPrefValueChanged(const std::string& key);
+  virtual void OnInitializationCompleted();
+
+  ObserverList<PrefStore::Observer, true> observers_;
+  PrefValueMap overlay_;
+  scoped_refptr<PersistentPrefStore> underlay_;
+
+  DISALLOW_COPY_AND_ASSIGN(OverlayPersistentPrefStore);
+};
+
+#endif  // CHROME_BROWSER_PREFS_OVERLAY_PERSISTENT_PREF_STORE_H_
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc b/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc
new file mode 100644
index 0000000..7e2e0a2
--- /dev/null
+++ b/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/values.h"
+#include "chrome/browser/prefs/overlay_persistent_pref_store.h"
+#include "chrome/browser/prefs/testing_pref_store.h"
+#include "chrome/common/pref_store_observer_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Mock;
+using ::testing::StrEq;
+
+const char key[] = "test.key";
+
+class OverlayPersistentPrefStoreTest : public testing::Test {
+ public:
+  OverlayPersistentPrefStoreTest()
+      : underlay_(new TestingPrefStore()),
+        overlay_(new OverlayPersistentPrefStore(underlay_.get())) {
+  }
+
+  scoped_refptr<TestingPrefStore> underlay_;
+  scoped_refptr<OverlayPersistentPrefStore> overlay_;
+};
+
+TEST_F(OverlayPersistentPrefStoreTest, Observer) {
+  PrefStoreObserverMock obs;
+  overlay_->AddObserver(&obs);
+
+  // Check that underlay first value is reported.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+  underlay_->SetValue(key, Value::CreateIntegerValue(42));
+  Mock::VerifyAndClearExpectations(&obs);
+
+  // Check that underlay overwriting is reported.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+  underlay_->SetValue(key, Value::CreateIntegerValue(43));
+  Mock::VerifyAndClearExpectations(&obs);
+
+  // Check that overwriting change in overlay is reported.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+  overlay_->SetValue(key, Value::CreateIntegerValue(44));
+  Mock::VerifyAndClearExpectations(&obs);
+
+  // Check that hidden underlay change is not reported.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(0);
+  underlay_->SetValue(key, Value::CreateIntegerValue(45));
+  Mock::VerifyAndClearExpectations(&obs);
+
+  // Check that overlay remove is reported.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+  overlay_->RemoveValue(key);
+  Mock::VerifyAndClearExpectations(&obs);
+
+  // Check that underlay remove is reported.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+  underlay_->RemoveValue(key);
+  Mock::VerifyAndClearExpectations(&obs);
+
+  // Check respecting of silence.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(0);
+  overlay_->SetValueSilently(key, Value::CreateIntegerValue(46));
+  Mock::VerifyAndClearExpectations(&obs);
+
+  overlay_->RemoveObserver(&obs);
+
+  // Check successful unsubscription.
+  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(0);
+  underlay_->SetValue(key, Value::CreateIntegerValue(47));
+  overlay_->SetValue(key, Value::CreateIntegerValue(48));
+  Mock::VerifyAndClearExpectations(&obs);
+}
+
+TEST_F(OverlayPersistentPrefStoreTest, GetAndSet) {
+  Value* value = NULL;
+  int i = -1;
+  EXPECT_EQ(PrefStore::READ_NO_VALUE, overlay_->GetValue(key, &value));
+  EXPECT_EQ(PrefStore::READ_NO_VALUE, underlay_->GetValue(key, &value));
+
+  underlay_->SetValue(key, Value::CreateIntegerValue(42));
+
+  // Value shines through:
+  EXPECT_EQ(PrefStore::READ_OK, overlay_->GetValue(key, &value));
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetAsInteger(&i));
+  EXPECT_EQ(42, i);
+
+  EXPECT_EQ(PrefStore::READ_OK, underlay_->GetValue(key, &value));
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetAsInteger(&i));
+  EXPECT_EQ(42, i);
+
+  overlay_->SetValue(key, Value::CreateIntegerValue(43));
+
+  EXPECT_EQ(PrefStore::READ_OK, overlay_->GetValue(key, &value));
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetAsInteger(&i));
+  EXPECT_EQ(43, i);
+
+  EXPECT_EQ(PrefStore::READ_OK, underlay_->GetValue(key, &value));
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetAsInteger(&i));
+  EXPECT_EQ(42, i);
+
+  overlay_->RemoveValue(key);
+
+  // Value shines through:
+  EXPECT_EQ(PrefStore::READ_OK, overlay_->GetValue(key, &value));
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetAsInteger(&i));
+  EXPECT_EQ(42, i);
+
+  EXPECT_EQ(PrefStore::READ_OK, underlay_->GetValue(key, &value));
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetAsInteger(&i));
+  EXPECT_EQ(42, i);
+}
diff --git a/chrome/browser/prefs/pref_change_registrar.cc b/chrome/browser/prefs/pref_change_registrar.cc
index 5655a8e..64c6096 100644
--- a/chrome/browser/prefs/pref_change_registrar.cc
+++ b/chrome/browser/prefs/pref_change_registrar.cc
@@ -10,6 +10,10 @@
 PrefChangeRegistrar::PrefChangeRegistrar() : service_(NULL) {}
 
 PrefChangeRegistrar::~PrefChangeRegistrar() {
+  // If you see an invalid memory access in this destructor, this
+  // PrefChangeRegistrar might be subscribed to an OffTheRecordProfileImpl that
+  // has been destroyed. This should not happen any more but be warned.
+  // Feel free to contact battre@chromium.org in case this happens.
   RemoveAll();
 }
 
diff --git a/chrome/browser/prefs/pref_change_registrar_unittest.cc b/chrome/browser/prefs/pref_change_registrar_unittest.cc
index 2e4cd0e..3ad036f 100644
--- a/chrome/browser/prefs/pref_change_registrar_unittest.cc
+++ b/chrome/browser/prefs/pref_change_registrar_unittest.cc
@@ -7,7 +7,6 @@
 #include "chrome/common/notification_observer_mock.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/testing_pref_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -21,7 +20,7 @@
 class MockPrefService : public TestingPrefService {
  public:
   MockPrefService() {}
-  virtual ~MockPrefService() {};
+  virtual ~MockPrefService() {}
 
   MOCK_METHOD2(AddPrefObserver, void(const char*, NotificationObserver*));
   MOCK_METHOD2(RemovePrefObserver, void(const char*, NotificationObserver*));
diff --git a/chrome/browser/prefs/pref_member.cc b/chrome/browser/prefs/pref_member.cc
index cc14384..5ff0f0d 100644
--- a/chrome/browser/prefs/pref_member.cc
+++ b/chrome/browser/prefs/pref_member.cc
@@ -18,7 +18,7 @@
 }
 
 PrefMemberBase::~PrefMemberBase() {
-  if (!pref_name_.empty())
+  if (prefs_ && !pref_name_.empty())
     prefs_->RemovePrefObserver(pref_name_.c_str(), this);
 }
 
@@ -37,6 +37,13 @@
   prefs_->AddPrefObserver(pref_name, this);
 }
 
+void PrefMemberBase::Destroy() {
+  if (prefs_) {
+    prefs_->RemovePrefObserver(pref_name_.c_str(), this);
+    prefs_ = NULL;
+  }
+}
+
 bool PrefMemberBase::IsManaged() const {
   DCHECK(!pref_name_.empty());
   const PrefService::Preference* pref =
@@ -89,18 +96,18 @@
   prefs()->SetInteger(pref_name().c_str(), value);
 }
 
-RealPrefMember::RealPrefMember() : PrefMember<double>() {
+DoublePrefMember::DoublePrefMember() : PrefMember<double>() {
 }
 
-RealPrefMember::~RealPrefMember() {
+DoublePrefMember::~DoublePrefMember() {
 }
 
-void RealPrefMember::UpdateValueFromPref() const {
-  value_ = prefs()->GetReal(pref_name().c_str());
+void DoublePrefMember::UpdateValueFromPref() const {
+  value_ = prefs()->GetDouble(pref_name().c_str());
 }
 
-void RealPrefMember::UpdatePref(const double& value) {
-  prefs()->SetReal(pref_name().c_str(), value);
+void DoublePrefMember::UpdatePref(const double& value) {
+  prefs()->SetDouble(pref_name().c_str(), value);
 }
 
 StringPrefMember::StringPrefMember() : PrefMember<std::string>() {
diff --git a/chrome/browser/prefs/pref_member.h b/chrome/browser/prefs/pref_member.h
index 6d1ab5a..082ec6e 100644
--- a/chrome/browser/prefs/pref_member.h
+++ b/chrome/browser/prefs/pref_member.h
@@ -45,6 +45,9 @@
             NotificationObserver* observer);
 
   // See PrefMember<> for description.
+  void Destroy();
+
+  // See PrefMember<> for description.
   bool IsManaged() const;
 
   // NotificationObserver
@@ -92,6 +95,12 @@
     subtle::PrefMemberBase::Init(pref_name, prefs, observer);
   }
 
+  // Unsubscribes the PrefMember from the PrefService. After calling this
+  // function, the PrefMember may not be used any more.
+  void Destroy() {
+    subtle::PrefMemberBase::Destroy();
+  }
+
   // Check whether the pref is managed, i.e. controlled externally through
   // enterprise configuration management (e.g. windows group policy). Returns
   // false for unknown prefs.
@@ -169,17 +178,17 @@
   DISALLOW_COPY_AND_ASSIGN(IntegerPrefMember);
 };
 
-class RealPrefMember : public PrefMember<double> {
+class DoublePrefMember : public PrefMember<double> {
  public:
-  RealPrefMember();
-  virtual ~RealPrefMember();
+  DoublePrefMember();
+  virtual ~DoublePrefMember();
 
  protected:
   virtual void UpdateValueFromPref() const;
   virtual void UpdatePref(const double& value);
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(RealPrefMember);
+  DISALLOW_COPY_AND_ASSIGN(DoublePrefMember);
 };
 
 class StringPrefMember : public PrefMember<std::string> {
diff --git a/chrome/browser/prefs/pref_member_unittest.cc b/chrome/browser/prefs/pref_member_unittest.cc
index 3f786afb..f0bf181 100644
--- a/chrome/browser/prefs/pref_member_unittest.cc
+++ b/chrome/browser/prefs/pref_member_unittest.cc
@@ -14,13 +14,13 @@
 
 static const char kBoolPref[] = "bool";
 static const char kIntPref[] = "int";
-static const char kRealPref[] = "real";
+static const char kDoublePref[] = "double";
 static const char kStringPref[] = "string";
 
 void RegisterTestPrefs(PrefService* prefs) {
   prefs->RegisterBooleanPref(kBoolPref, false);
   prefs->RegisterIntegerPref(kIntPref, 0);
-  prefs->RegisterRealPref(kRealPref, 0.0);
+  prefs->RegisterDoublePref(kDoublePref, 0.0);
   prefs->RegisterStringPref(kStringPref, "default");
 }
 
@@ -98,26 +98,26 @@
   EXPECT_EQ(2, integer.GetValue());
   EXPECT_EQ(2, *integer);
 
-  // Test real (double)
-  RealPrefMember real;
-  real.Init(kRealPref, &prefs, NULL);
+  // Test double
+  DoublePrefMember double_member;
+  double_member.Init(kDoublePref, &prefs, NULL);
 
   // Check the defaults
-  EXPECT_EQ(0.0, prefs.GetReal(kRealPref));
-  EXPECT_EQ(0.0, real.GetValue());
-  EXPECT_EQ(0.0, *real);
+  EXPECT_EQ(0.0, prefs.GetDouble(kDoublePref));
+  EXPECT_EQ(0.0, double_member.GetValue());
+  EXPECT_EQ(0.0, *double_member);
 
   // Try changing through the member variable.
-  real.SetValue(1.0);
-  EXPECT_EQ(1.0, real.GetValue());
-  EXPECT_EQ(1.0, prefs.GetReal(kRealPref));
-  EXPECT_EQ(1.0, *real);
+  double_member.SetValue(1.0);
+  EXPECT_EQ(1.0, double_member.GetValue());
+  EXPECT_EQ(1.0, prefs.GetDouble(kDoublePref));
+  EXPECT_EQ(1.0, *double_member);
 
   // Try changing back through the pref.
-  prefs.SetReal(kRealPref, 3.0);
-  EXPECT_EQ(3.0, prefs.GetReal(kRealPref));
-  EXPECT_EQ(3.0, real.GetValue());
-  EXPECT_EQ(3.0, *real);
+  prefs.SetDouble(kDoublePref, 3.0);
+  EXPECT_EQ(3.0, prefs.GetDouble(kDoublePref));
+  EXPECT_EQ(3.0, double_member.GetValue());
+  EXPECT_EQ(3.0, *double_member);
 
   // Test string
   StringPrefMember string;
@@ -142,14 +142,14 @@
 }
 
 TEST(PrefMemberTest, TwoPrefs) {
-  // Make sure two RealPrefMembers stay in sync.
+  // Make sure two DoublePrefMembers stay in sync.
   TestingPrefService prefs;
   RegisterTestPrefs(&prefs);
 
-  RealPrefMember pref1;
-  pref1.Init(kRealPref, &prefs, NULL);
-  RealPrefMember pref2;
-  pref2.Init(kRealPref, &prefs, NULL);
+  DoublePrefMember pref1;
+  pref1.Init(kDoublePref, &prefs, NULL);
+  DoublePrefMember pref2;
+  pref2.Init(kDoublePref, &prefs, NULL);
 
   pref1.SetValue(2.3);
   EXPECT_EQ(2.3, *pref2);
@@ -157,7 +157,7 @@
   pref2.SetValue(3.5);
   EXPECT_EQ(3.5, *pref1);
 
-  prefs.SetReal(kRealPref, 4.2);
+  prefs.SetDouble(kDoublePref, 4.2);
   EXPECT_EQ(4.2, *pref1);
   EXPECT_EQ(4.2, *pref2);
 }
diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc
index 23ca06a..cbfa4bb 100644
--- a/chrome/browser/prefs/pref_service.cc
+++ b/chrome/browser/prefs/pref_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,8 +7,11 @@
 #include <algorithm>
 #include <string>
 
+<<<<<<< HEAD
 #include "app/l10n_util.h"
 #ifndef ANDROID
+=======
+>>>>>>> chromium.org at r11.0.672.0
 #include "base/command_line.h"
 #endif
 #include "base/file_path.h"
@@ -23,9 +26,11 @@
 #include "base/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/extension_pref_store.h"
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/prefs/command_line_pref_store.h"
 #include "chrome/browser/prefs/default_pref_store.h"
+#include "chrome/browser/prefs/overlay_persistent_pref_store.h"
 #include "chrome/browser/prefs/pref_notifier_impl.h"
 #include "chrome/browser/prefs/pref_value_store.h"
 #include "chrome/common/json_pref_store.h"
@@ -35,7 +40,11 @@
 #include "chrome/common/notification_service.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+<<<<<<< HEAD
 #endif
+=======
+#include "ui/base/l10n/l10n_util.h"
+>>>>>>> chromium.org at r11.0.672.0
 
 namespace {
 
@@ -61,10 +70,10 @@
       return Value::CreateIntegerValue(val);
     }
 
-    case Value::TYPE_REAL: {
+    case Value::TYPE_DOUBLE: {
       double val;
       base::StringToDouble(resource_string, &val);
-      return Value::CreateRealValue(val);
+      return Value::CreateDoubleValue(val);
     }
 
     case Value::TYPE_STRING: {
@@ -112,32 +121,51 @@
   }
 #endif
 
+<<<<<<< HEAD
 #ifdef ANDROID
   return new PrefService(NULL, NULL, NULL, NULL, NULL, NULL);
 #else
   ConfigurationPolicyPrefStore* managed =
+=======
+  ConfigurationPolicyPrefStore* managed_platform =
+>>>>>>> chromium.org at r11.0.672.0
       ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore();
-  ConfigurationPolicyPrefStore* device_management =
-      ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
-          profile);
+  ConfigurationPolicyPrefStore* managed_cloud =
+      ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(profile);
   CommandLinePrefStore* command_line =
       new CommandLinePrefStore(CommandLine::ForCurrentProcess());
   JsonPrefStore* user = new JsonPrefStore(
       pref_filename,
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
-  ConfigurationPolicyPrefStore* recommended =
-      ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore();
+  ConfigurationPolicyPrefStore* recommended_platform =
+      ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore();
+  ConfigurationPolicyPrefStore* recommended_cloud =
+      ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
+          profile);
+  DefaultPrefStore* default_pref_store = new DefaultPrefStore();
 
+  return new PrefService(managed_platform, managed_cloud, extension_prefs,
+                         command_line, user, recommended_platform,
+                         recommended_cloud, default_pref_store);
+}
+
+<<<<<<< HEAD
   return new PrefService(managed, device_management, extension_prefs,
                          command_line, user, recommended);
 #endif
+=======
+PrefService* PrefService::CreateIncognitoPrefService(
+    PrefStore* incognito_extension_prefs) {
+  return new PrefService(*this, incognito_extension_prefs);
+>>>>>>> chromium.org at r11.0.672.0
 }
 
 PrefService::PrefService(PrefStore* managed_platform_prefs,
-                         PrefStore* device_management_prefs,
+                         PrefStore* managed_cloud_prefs,
                          PrefStore* extension_prefs,
                          PrefStore* command_line_prefs,
                          PersistentPrefStore* user_prefs,
+<<<<<<< HEAD
                          PrefStore* recommended_prefs)
     : user_pref_store_(user_prefs) {
 #ifndef ANDROID
@@ -145,11 +173,21 @@
 #endif
   default_store_ = new DefaultPrefStore();
   pref_value_store_ =
+=======
+                         PrefStore* recommended_platform_prefs,
+                         PrefStore* recommended_cloud_prefs,
+                         DefaultPrefStore* default_store)
+    : user_pref_store_(user_prefs),
+      default_store_(default_store) {
+  pref_notifier_.reset(new PrefNotifierImpl(this));
+  pref_value_store_.reset(
+>>>>>>> chromium.org at r11.0.672.0
       new PrefValueStore(managed_platform_prefs,
-                         device_management_prefs,
+                         managed_cloud_prefs,
                          extension_prefs,
                          command_line_prefs,
                          user_pref_store_,
+<<<<<<< HEAD
                          recommended_prefs,
                          default_store_,
 #ifdef ANDROID
@@ -157,6 +195,31 @@
 #else
                          pref_notifier_.get());
 #endif
+=======
+                         recommended_platform_prefs,
+                         recommended_cloud_prefs,
+                         default_store,
+                         pref_notifier_.get()));
+  InitFromStorage();
+}
+
+PrefService::PrefService(const PrefService& original,
+                         PrefStore* incognito_extension_prefs)
+      : user_pref_store_(
+            new OverlayPersistentPrefStore(original.user_pref_store_.get())),
+        default_store_(original.default_store_.get()){
+  pref_notifier_.reset(new PrefNotifierImpl(this));
+  pref_value_store_.reset(original.pref_value_store_->CloneAndSpecialize(
+      NULL, // managed_platform_prefs
+      NULL, // managed_cloud_prefs
+      incognito_extension_prefs,
+      NULL, // command_line_prefs
+      user_pref_store_.get(),
+      NULL, // recommended_platform_prefs
+      NULL, // recommended_cloud_prefs
+      default_store_.get(),
+      pref_notifier_.get()));
+>>>>>>> chromium.org at r11.0.672.0
   InitFromStorage();
 }
 
@@ -164,6 +227,11 @@
   DCHECK(CalledOnValidThread());
   STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
   prefs_.clear();
+
+  // Reset pointers so accesses after destruction reliably crash.
+  pref_value_store_.reset();
+  user_pref_store_ = NULL;
+  default_store_ = NULL;
 }
 
 void PrefService::InitFromStorage() {
@@ -217,8 +285,8 @@
   RegisterPreference(path, Value::CreateIntegerValue(default_value));
 }
 
-void PrefService::RegisterRealPref(const char* path, double default_value) {
-  RegisterPreference(path, Value::CreateRealValue(default_value));
+void PrefService::RegisterDoublePref(const char* path, double default_value) {
+  RegisterPreference(path, Value::CreateDoubleValue(default_value));
 }
 
 void PrefService::RegisterStringPref(const char* path,
@@ -235,10 +303,19 @@
   RegisterPreference(path, new ListValue());
 }
 
+void PrefService::RegisterListPref(const char* path, ListValue* default_value) {
+  RegisterPreference(path, default_value);
+}
+
 void PrefService::RegisterDictionaryPref(const char* path) {
   RegisterPreference(path, new DictionaryValue());
 }
 
+void PrefService::RegisterDictionaryPref(const char* path,
+                                         DictionaryValue* default_value) {
+  RegisterPreference(path, default_value);
+}
+
 void PrefService::RegisterLocalizedBooleanPref(const char* path,
                                                int locale_default_message_id) {
   RegisterPreference(
@@ -253,11 +330,11 @@
       CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
 }
 
-void PrefService::RegisterLocalizedRealPref(const char* path,
-                                            int locale_default_message_id) {
+void PrefService::RegisterLocalizedDoublePref(const char* path,
+                                              int locale_default_message_id) {
   RegisterPreference(
       path,
-      CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id));
+      CreateLocaleDefaultValue(Value::TYPE_DOUBLE, locale_default_message_id));
 }
 
 void PrefService::RegisterLocalizedStringPref(const char* path,
@@ -297,7 +374,7 @@
   return result;
 }
 
-double PrefService::GetReal(const char* path) const {
+double PrefService::GetDouble(const char* path) const {
   DCHECK(CalledOnValidThread());
 
   double result = 0.0;
@@ -307,7 +384,7 @@
     NOTREACHED() << "Trying to read an unregistered pref: " << path;
     return result;
   }
-  bool rv = pref->GetValue()->GetAsReal(&result);
+  bool rv = pref->GetValue()->GetAsDouble(&result);
   DCHECK(rv);
   return result;
 }
@@ -347,15 +424,34 @@
 }
 
 bool PrefService::HasPrefPath(const char* path) const {
-  return pref_value_store_->HasPrefPath(path);
+  const Preference* pref = FindPreference(path);
+  return pref && !pref->IsDefaultValue();
+}
+
+DictionaryValue* PrefService::GetPreferenceValues() const {
+  DCHECK(CalledOnValidThread());
+  DictionaryValue* out = new DictionaryValue;
+  DefaultPrefStore::const_iterator i = default_store_->begin();
+  for (; i != default_store_->end(); ++i) {
+    const Value* value = FindPreference(i->first.c_str())->GetValue();
+    out->Set(i->first, value->DeepCopy());
+  }
+  return out;
 }
 
 const PrefService::Preference* PrefService::FindPreference(
     const char* pref_name) const {
   DCHECK(CalledOnValidThread());
-  Preference p(this, pref_name);
+  Preference p(this, pref_name, Value::TYPE_NULL);
   PreferenceSet::const_iterator it = prefs_.find(&p);
-  return it == prefs_.end() ? NULL : *it;
+  if (it != prefs_.end())
+    return *it;
+  const Value::ValueType type = default_store_->GetType(pref_name);
+  if (type == Value::TYPE_NULL)
+    return NULL;
+  Preference* new_pref = new Preference(this, pref_name, type);
+  prefs_.insert(new_pref);
+  return new_pref;
 }
 
 bool PrefService::ReadOnly() const {
@@ -372,10 +468,7 @@
 
 bool PrefService::IsManagedPreference(const char* pref_name) const {
   const Preference* pref = FindPreference(pref_name);
-  if (pref && pref->IsManaged()) {
-    return true;
-  }
-  return false;
+  return pref && pref->IsManaged();
 }
 
 const DictionaryValue* PrefService::GetDictionary(const char* path) const {
@@ -387,8 +480,10 @@
     return NULL;
   }
   const Value* value = pref->GetValue();
-  if (value->GetType() == Value::TYPE_NULL)
+  if (value->GetType() != Value::TYPE_DICTIONARY) {
+    NOTREACHED();
     return NULL;
+  }
   return static_cast<const DictionaryValue*>(value);
 }
 
@@ -401,8 +496,10 @@
     return NULL;
   }
   const Value* value = pref->GetValue();
-  if (value->GetType() == Value::TYPE_NULL)
+  if (value->GetType() != Value::TYPE_LIST) {
+    NOTREACHED();
     return NULL;
+  }
   return static_cast<const ListValue*>(value);
 }
 
@@ -433,18 +530,8 @@
   DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
          "invalid preference type: " << orig_type;
 
-  // We set the default value of dictionaries and lists to be null so it's
-  // easier for callers to check for empty dict/list prefs. The PrefValueStore
-  // accepts ownership of the value (null or default_value).
-  if (Value::TYPE_LIST == orig_type || Value::TYPE_DICTIONARY == orig_type) {
-    default_store_->SetDefaultValue(path, Value::CreateNullValue());
-  } else {
-    // Hand off ownership.
-    default_store_->SetDefaultValue(path, scoped_value.release());
-  }
-
-  pref_value_store_->RegisterPreferenceType(path, orig_type);
-  prefs_.insert(new Preference(this, path));
+  // Hand off ownership.
+  default_store_->SetDefaultValue(path, scoped_value.release());
 }
 
 void PrefService::ClearPref(const char* path) {
@@ -469,13 +556,7 @@
     return;
   }
 
-  // Allow dictionary and list types to be set to null, which removes their
-  // user values.
-  if (value.GetType() == Value::TYPE_NULL &&
-      (pref->GetType() == Value::TYPE_DICTIONARY ||
-       pref->GetType() == Value::TYPE_LIST)) {
-    user_pref_store_->RemoveValue(path);
-  } else if (pref->GetType() != value.GetType()) {
+  if (pref->GetType() != value.GetType()) {
     NOTREACHED() << "Trying to set pref " << path
                  << " of type " << pref->GetType()
                  << " to value of type " << value.GetType();
@@ -492,8 +573,8 @@
   SetUserPrefValue(path, Value::CreateIntegerValue(value));
 }
 
-void PrefService::SetReal(const char* path, double value) {
-  SetUserPrefValue(path, Value::CreateRealValue(value));
+void PrefService::SetDouble(const char* path, double value) {
+  SetUserPrefValue(path, Value::CreateDoubleValue(value));
 }
 
 void PrefService::SetString(const char* path, const std::string& value) {
@@ -541,6 +622,8 @@
 
 DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
   DCHECK(CalledOnValidThread());
+  DLOG_IF(WARNING, IsManagedPreference(path)) <<
+      "Attempt to change managed preference " << path;
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -569,6 +652,8 @@
 
 ListValue* PrefService::GetMutableList(const char* path) {
   DCHECK(CalledOnValidThread());
+  DLOG_IF(WARNING, IsManagedPreference(path)) <<
+      "Attempt to change managed preference " << path;
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -597,6 +682,8 @@
 
 void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
   DCHECK(CalledOnValidThread());
+  DLOG_IF(WARNING, IsManagedPreference(path)) <<
+      "Attempt to change managed preference " << path;
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -619,15 +706,17 @@
 // PrefService::Preference
 
 PrefService::Preference::Preference(const PrefService* service,
-                                    const char* name)
+                                    const char* name,
+                                    Value::ValueType type)
       : name_(name),
+        type_(type),
         pref_service_(service) {
   DCHECK(name);
   DCHECK(service);
 }
 
 Value::ValueType PrefService::Preference::GetType() const {
-  return pref_service_->pref_value_store_->GetRegisteredType(name_);
+  return type_;
 }
 
 const Value* PrefService::Preference::GetValue() const {
@@ -635,8 +724,10 @@
       "Must register pref before getting its value";
 
   Value* found_value = NULL;
-  if (pref_service_->pref_value_store_->GetValue(name_, &found_value))
+  if (pref_value_store()->GetValue(name_, type_, &found_value)) {
+    DCHECK(found_value->IsType(type_));
     return found_value;
+  }
 
   // Every registered preference has at least a default value.
   NOTREACHED() << "no valid value found for registered pref " << name_;
@@ -644,37 +735,29 @@
 }
 
 bool PrefService::Preference::IsManaged() const {
-  PrefValueStore* pref_value_store = pref_service_->pref_value_store_;
-  return pref_value_store->PrefValueInManagedPlatformStore(name_.c_str()) ||
-      pref_value_store->PrefValueInDeviceManagementStore(name_.c_str());
+  return pref_value_store()->PrefValueInManagedStore(name_.c_str());
 }
 
 bool PrefService::Preference::HasExtensionSetting() const {
-  return pref_service_->pref_value_store_->
-      PrefValueInExtensionStore(name_.c_str());
+  return pref_value_store()->PrefValueInExtensionStore(name_.c_str());
 }
 
 bool PrefService::Preference::HasUserSetting() const {
-  return pref_service_->pref_value_store_->
-      PrefValueInUserStore(name_.c_str());
+  return pref_value_store()->PrefValueInUserStore(name_.c_str());
 }
 
 bool PrefService::Preference::IsExtensionControlled() const {
-  return pref_service_->pref_value_store_->
-      PrefValueFromExtensionStore(name_.c_str());
+  return pref_value_store()->PrefValueFromExtensionStore(name_.c_str());
 }
 
 bool PrefService::Preference::IsUserControlled() const {
-  return pref_service_->pref_value_store_->
-      PrefValueFromUserStore(name_.c_str());
+  return pref_value_store()->PrefValueFromUserStore(name_.c_str());
 }
 
 bool PrefService::Preference::IsDefaultValue() const {
-  return pref_service_->pref_value_store_->
-      PrefValueFromDefaultStore(name_.c_str());
+  return pref_value_store()->PrefValueFromDefaultStore(name_.c_str());
 }
 
 bool PrefService::Preference::IsUserModifiable() const {
-  return pref_service_->pref_value_store_->
-      PrefValueUserModifiable(name_.c_str());
+  return pref_value_store()->PrefValueUserModifiable(name_.c_str());
 }
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index 9e1bd33..2c28d6a 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -38,11 +38,12 @@
    public:
 
     // The type of the preference is determined by the type with which it is
-    // registered. This type needs to be a boolean, integer, real, string,
+    // registered. This type needs to be a boolean, integer, double, string,
     // dictionary (a branch), or list.  You shouldn't need to construct this on
     // your own; use the PrefService::Register*Pref methods instead.
     Preference(const PrefService* service,
-               const char* name);
+               const char* name,
+               Value::ValueType type);
     ~Preference() {}
 
     // Returns the name of the Preference (i.e., the key, e.g.,
@@ -90,8 +91,14 @@
    private:
     friend class PrefService;
 
+    PrefValueStore* pref_value_store() const {
+      return pref_service_->pref_value_store_.get();
+    }
+
     std::string name_;
 
+    Value::ValueType type_;
+
     // Reference to the PrefService in which this pref was created.
     const PrefService* pref_service_;
 
@@ -109,6 +116,12 @@
                                         PrefStore* extension_pref_store,
                                         Profile* profile);
 
+  // Creates an incognito copy of the pref service that shares most pref stores
+  // but uses a fresh non-persistent overlay for the user pref store and an
+  // individual extension pref store (to cache the effective extension prefs for
+  // incognito windows).
+  PrefService* CreateIncognitoPrefService(PrefStore* incognito_extension_prefs);
+
   virtual ~PrefService();
 
   // Reloads the data from file. This should only be called when the importer
@@ -133,19 +146,22 @@
   // Make the PrefService aware of a pref.
   void RegisterBooleanPref(const char* path, bool default_value);
   void RegisterIntegerPref(const char* path, int default_value);
-  void RegisterRealPref(const char* path, double default_value);
+  void RegisterDoublePref(const char* path, double default_value);
   void RegisterStringPref(const char* path, const std::string& default_value);
   void RegisterFilePathPref(const char* path, const FilePath& default_value);
   void RegisterListPref(const char* path);
   void RegisterDictionaryPref(const char* path);
+  // These take ownership of the default_value:
+  void RegisterListPref(const char* path, ListValue* default_value);
+  void RegisterDictionaryPref(const char* path, DictionaryValue* default_value);
 
   // These variants use a default value from the locale dll instead.
   void RegisterLocalizedBooleanPref(const char* path,
                                     int locale_default_message_id);
   void RegisterLocalizedIntegerPref(const char* path,
                                     int locale_default_message_id);
-  void RegisterLocalizedRealPref(const char* path,
-                                 int locale_default_message_id);
+  void RegisterLocalizedDoublePref(const char* path,
+                                   int locale_default_message_id);
   void RegisterLocalizedStringPref(const char* path,
                                    int locale_default_message_id);
 
@@ -154,12 +170,13 @@
   // value (set when the pref was registered) will be returned.
   bool GetBoolean(const char* path) const;
   int GetInteger(const char* path) const;
-  double GetReal(const char* path) const;
+  double GetDouble(const char* path) const;
   std::string GetString(const char* path) const;
   FilePath GetFilePath(const char* path) const;
 
-  // Returns the branch if it exists.  If it's not a branch or the branch does
-  // not exist, returns NULL.
+  // Returns the branch if it exists, or the registered default value otherwise.
+  // Note that |path| must point to a registered preference. In that case, these
+  // functions will never return NULL.
   const DictionaryValue* GetDictionary(const char* path) const;
   const ListValue* GetList(const char* path) const;
 
@@ -173,7 +190,7 @@
   void Set(const char* path, const Value& value);
   void SetBoolean(const char* path, bool value);
   void SetInteger(const char* path, int value);
-  void SetReal(const char* path, double value);
+  void SetDouble(const char* path, double value);
   void SetString(const char* path, const std::string& value);
   void SetFilePath(const char* path, const FilePath& value);
 
@@ -202,14 +219,9 @@
   // this checks if a value exists for the path.
   bool HasPrefPath(const char* path) const;
 
-  class PreferencePathComparator {
-   public:
-    bool operator() (Preference* lhs, Preference* rhs) const {
-      return lhs->name() < rhs->name();
-    }
-  };
-  typedef std::set<Preference*, PreferencePathComparator> PreferenceSet;
-  const PreferenceSet& preference_set() const { return prefs_; }
+  // Returns a dictionary with effective preference values. The ownership
+  // is passed to the caller.
+  DictionaryValue* GetPreferenceValues() const;
 
   // A helper method to quickly look up a preference.  Returns NULL if the
   // preference is not registered.
@@ -230,11 +242,13 @@
   // PrefStore pointers. This constructor is what CreatePrefService() ends up
   // calling. It's also used for unit tests.
   PrefService(PrefStore* managed_platform_prefs,
-              PrefStore* device_management_prefs,
+              PrefStore* managed_cloud_prefs,
               PrefStore* extension_prefs,
               PrefStore* command_line_prefs,
               PersistentPrefStore* user_prefs,
-              PrefStore* recommended_prefs);
+              PrefStore* recommended_platform_prefs,
+              PrefStore* recommended_cloud_prefs,
+              DefaultPrefStore* default_store);
 
 #ifndef ANDROID
   // The PrefNotifier handles registering and notifying preference observers.
@@ -244,6 +258,14 @@
 #endif
 
  private:
+  class PreferencePathComparator {
+   public:
+    bool operator() (Preference* lhs, Preference* rhs) const {
+      return lhs->name() < rhs->name();
+    }
+  };
+  typedef std::set<Preference*, PreferencePathComparator> PreferenceSet;
+
   friend class PrefServiceMockBuilder;
 
   // Registration of pref change observers must be done using the
@@ -255,7 +277,15 @@
   friend class PrefChangeRegistrar;
   friend class subtle::PrefMemberBase;
 
+<<<<<<< HEAD
 #ifndef ANDROID
+=======
+  // Construct an incognito version of the pref service. Use
+  // CreateIncognitoPrefService() instead of calling this constructor directly.
+  PrefService(const PrefService& original,
+              PrefStore* incognito_extension_prefs);
+
+>>>>>>> chromium.org at r11.0.672.0
   // If the pref at the given path changes, we call the observer's Observe
   // method with PREF_CHANGED. Note that observers should not call these methods
   // directly but rather use a PrefChangeRegistrar to make sure the observer
@@ -264,8 +294,10 @@
   virtual void RemovePrefObserver(const char* path, NotificationObserver* obs);
 #endif
 
-  // Add a preference to the PreferenceMap.  If the pref already exists, return
-  // false.  This method takes ownership of |default_value|.
+  // Registers a new preference at |path|. The |default_value| must not be
+  // NULL as it determines the preference value's type.
+  // RegisterPreference must not be called twice for the same path.
+  // This method takes ownership of |default_value|.
   void RegisterPreference(const char* path, Value* default_value);
 
   // Sets the value for this pref path in the user pref store and informs the
@@ -278,16 +310,16 @@
 
   // The PrefValueStore provides prioritized preference values. It is created
   // and owned by this PrefService. Subclasses may access it for unit testing.
-  scoped_refptr<PrefValueStore> pref_value_store_;
+  scoped_ptr<PrefValueStore> pref_value_store_;
 
-  // The persistent pref store used for actual user data.
-  PersistentPrefStore* user_pref_store_;
+  // Pref Stores and profile that we passed to the PrefValueStore.
+  scoped_refptr<PersistentPrefStore> user_pref_store_;
+  scoped_refptr<DefaultPrefStore> default_store_;
 
-  // Points to the default pref store we passed to the PrefValueStore.
-  DefaultPrefStore* default_store_;
-
-  // A set of all the registered Preference objects.
-  PreferenceSet prefs_;
+  // Local cache of registered Preference objects. The default_store_
+  // is authoritative with respect to what the types and default values
+  // of registered preferences are.
+  mutable PreferenceSet prefs_;
 
   DISALLOW_COPY_AND_ASSIGN(PrefService);
 };
diff --git a/chrome/browser/prefs/pref_service_mock_builder.cc b/chrome/browser/prefs/pref_service_mock_builder.cc
index b02a334..e714451 100644
--- a/chrome/browser/prefs/pref_service_mock_builder.cc
+++ b/chrome/browser/prefs/pref_service_mock_builder.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 #include "chrome/browser/prefs/command_line_pref_store.h"
+#include "chrome/browser/prefs/default_pref_store.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/testing_pref_store.h"
 #include "chrome/common/json_pref_store.h"
@@ -19,87 +20,107 @@
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithManagedPlatformPrefs(PrefStore* store) {
-  managed_platform_prefs_.reset(store);
+  managed_platform_prefs_ = store;
   return *this;
 }
 
 PrefServiceMockBuilder&
-PrefServiceMockBuilder::WithDeviceManagementPrefs(PrefStore* store) {
-  device_management_prefs_.reset(store);
+PrefServiceMockBuilder::WithManagedCloudPrefs(PrefStore* store) {
+  managed_cloud_prefs_ = store;
   return *this;
 }
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithExtensionPrefs(PrefStore* store) {
-  extension_prefs_.reset(store);
+  extension_prefs_ = store;
   return *this;
 }
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithCommandLinePrefs(PrefStore* store) {
-  command_line_prefs_.reset(store);
+  command_line_prefs_ = store;
   return *this;
 }
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithUserPrefs(PersistentPrefStore* store) {
-  user_prefs_.reset(store);
+  user_prefs_ = store;
   return *this;
 }
 
 PrefServiceMockBuilder&
-PrefServiceMockBuilder::WithRecommendedPrefs(PrefStore* store) {
-  recommended_prefs_.reset(store);
+PrefServiceMockBuilder::WithRecommendedPlatformPrefs(PrefStore* store) {
+  recommended_platform_prefs_ = store;
+  return *this;
+}
+
+PrefServiceMockBuilder&
+PrefServiceMockBuilder::WithRecommendedCloudPrefs(PrefStore* store) {
+  recommended_cloud_prefs_ = store;
   return *this;
 }
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithManagedPlatformProvider(
     policy::ConfigurationPolicyProvider* provider) {
-  managed_platform_prefs_.reset(
-      new policy::ConfigurationPolicyPrefStore(provider));
+  managed_platform_prefs_ = new policy::ConfigurationPolicyPrefStore(provider);
   return *this;
 }
 
 PrefServiceMockBuilder&
-PrefServiceMockBuilder::WithDeviceManagementProvider(
+PrefServiceMockBuilder::WithManagedCloudProvider(
     policy::ConfigurationPolicyProvider* provider) {
-  device_management_prefs_.reset(
-      new policy::ConfigurationPolicyPrefStore(provider));
+  managed_cloud_prefs_ = new policy::ConfigurationPolicyPrefStore(provider);
   return *this;
 }
 
 PrefServiceMockBuilder&
-PrefServiceMockBuilder::WithRecommendedProvider(
+PrefServiceMockBuilder::WithRecommendedPlatformProvider(
     policy::ConfigurationPolicyProvider* provider) {
-  recommended_prefs_.reset(
-      new policy::ConfigurationPolicyPrefStore(provider));
+  recommended_platform_prefs_ =
+      new policy::ConfigurationPolicyPrefStore(provider);
+  return *this;
+}
+
+PrefServiceMockBuilder&
+PrefServiceMockBuilder::WithRecommendedCloudProvider(
+    policy::ConfigurationPolicyProvider* provider) {
+  recommended_cloud_prefs_ = new policy::ConfigurationPolicyPrefStore(provider);
   return *this;
 }
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithCommandLine(CommandLine* command_line) {
-  command_line_prefs_.reset(new CommandLinePrefStore(command_line));
+  command_line_prefs_ = new CommandLinePrefStore(command_line);
   return *this;
 }
 
 PrefServiceMockBuilder&
 PrefServiceMockBuilder::WithUserFilePrefs(const FilePath& prefs_file) {
-  user_prefs_.reset(
+  user_prefs_ =
       new JsonPrefStore(prefs_file,
                         BrowserThread::GetMessageLoopProxyForThread(
-                            BrowserThread::FILE)));
+                            BrowserThread::FILE));
   return *this;
 }
 
 PrefService* PrefServiceMockBuilder::Create() {
   PrefService* pref_service =
-      new PrefService(managed_platform_prefs_.release(),
-                      device_management_prefs_.release(),
-                      extension_prefs_.release(),
-                      command_line_prefs_.release(),
-                      user_prefs_.release(),
-                      recommended_prefs_.release());
-  user_prefs_.reset(new TestingPrefStore);
+      new PrefService(managed_platform_prefs_.get(),
+                      managed_cloud_prefs_.get(),
+                      extension_prefs_.get(),
+                      command_line_prefs_.get(),
+                      user_prefs_.get(),
+                      recommended_platform_prefs_.get(),
+                      recommended_cloud_prefs_.get(),
+                      new DefaultPrefStore());
+  managed_platform_prefs_ = NULL;
+  managed_cloud_prefs_ = NULL;
+  extension_prefs_ = NULL;
+  command_line_prefs_ = NULL;
+  user_prefs_ = NULL;
+  recommended_platform_prefs_ = NULL;
+  recommended_cloud_prefs_ = NULL;
+  user_prefs_ = new TestingPrefStore;
   return pref_service;
 }
diff --git a/chrome/browser/prefs/pref_service_mock_builder.h b/chrome/browser/prefs/pref_service_mock_builder.h
index 9cc4fcc..3e4d1e0 100644
--- a/chrome/browser/prefs/pref_service_mock_builder.h
+++ b/chrome/browser/prefs/pref_service_mock_builder.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "base/scoped_ptr.h"
+#include "base/ref_counted.h"
 #include "chrome/common/persistent_pref_store.h"
 #include "chrome/common/pref_store.h"
 
@@ -29,18 +29,21 @@
   // Functions for setting the various parameters of the PrefService to build.
   // These take ownership of the |store| parameter.
   PrefServiceMockBuilder& WithManagedPlatformPrefs(PrefStore* store);
-  PrefServiceMockBuilder& WithDeviceManagementPrefs(PrefStore* store);
+  PrefServiceMockBuilder& WithManagedCloudPrefs(PrefStore* store);
   PrefServiceMockBuilder& WithExtensionPrefs(PrefStore* store);
   PrefServiceMockBuilder& WithCommandLinePrefs(PrefStore* store);
   PrefServiceMockBuilder& WithUserPrefs(PersistentPrefStore* store);
-  PrefServiceMockBuilder& WithRecommendedPrefs(PrefStore* store);
+  PrefServiceMockBuilder& WithRecommendedPlatformPrefs(PrefStore* store);
+  PrefServiceMockBuilder& WithRecommendedCloudPrefs(PrefStore* store);
 
   // Set up policy pref stores using the given policy provider.
   PrefServiceMockBuilder& WithManagedPlatformProvider(
       policy::ConfigurationPolicyProvider* provider);
-  PrefServiceMockBuilder& WithDeviceManagementProvider(
+  PrefServiceMockBuilder& WithManagedCloudProvider(
       policy::ConfigurationPolicyProvider* provider);
-  PrefServiceMockBuilder& WithRecommendedProvider(
+  PrefServiceMockBuilder& WithRecommendedPlatformProvider(
+      policy::ConfigurationPolicyProvider* provider);
+  PrefServiceMockBuilder& WithRecommendedCloudProvider(
       policy::ConfigurationPolicyProvider* provider);
 
   // Specifies to use an actual command-line backed command-line pref store.
@@ -49,19 +52,17 @@
   // Specifies to use an actual file-backed user pref store.
   PrefServiceMockBuilder& WithUserFilePrefs(const FilePath& prefs_file);
 
-  // Sets the profile to pass to the PrefService.
-  PrefServiceMockBuilder& WithRecommendedPrefs(Profile* profile);
-
   // Creates the PrefService, invalidating the entire builder configuration.
   PrefService* Create();
 
  private:
-  scoped_ptr<PrefStore> managed_platform_prefs_;
-  scoped_ptr<PrefStore> device_management_prefs_;
-  scoped_ptr<PrefStore> extension_prefs_;
-  scoped_ptr<PrefStore> command_line_prefs_;
-  scoped_ptr<PersistentPrefStore> user_prefs_;
-  scoped_ptr<PrefStore> recommended_prefs_;
+  scoped_refptr<PrefStore> managed_platform_prefs_;
+  scoped_refptr<PrefStore> managed_cloud_prefs_;
+  scoped_refptr<PrefStore> extension_prefs_;
+  scoped_refptr<PrefStore> command_line_prefs_;
+  scoped_refptr<PersistentPrefStore> user_prefs_;
+  scoped_refptr<PrefStore> recommended_platform_prefs_;
+  scoped_refptr<PrefStore> recommended_cloud_prefs_;
 
   DISALLOW_COPY_AND_ASSIGN(PrefServiceMockBuilder);
 };
diff --git a/chrome/browser/prefs/pref_service_uitest.cc b/chrome/browser/prefs/pref_service_uitest.cc
index 9712481..fe2a79a 100644
--- a/chrome/browser/prefs/pref_service_uitest.cc
+++ b/chrome/browser/prefs/pref_service_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,7 +17,7 @@
 #include "chrome/test/automation/browser_proxy.h"
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class PreferenceServiceTest : public UITest {
  public:
@@ -29,17 +29,27 @@
     file_util::Delete(tmp_profile_, true);
     file_util::CreateDirectory(tmp_profile_);
 
-    FilePath reference_pref_file =
-        test_data_directory_
+    FilePath reference_pref_file;
+    if (new_profile_) {
+      reference_pref_file = test_data_directory_
+          .AppendASCII("profiles")
+          .AppendASCII("window_placement")
+          .AppendASCII("Default")
+          .Append(chrome::kPreferencesFilename);
+      tmp_pref_file_ = tmp_profile_.AppendASCII("Default");
+      ASSERT_TRUE(file_util::CreateDirectory(tmp_pref_file_));
+      tmp_pref_file_ = tmp_pref_file_.Append(chrome::kPreferencesFilename);
+    } else {
+      reference_pref_file = test_data_directory_
             .AppendASCII("profiles")
             .AppendASCII("window_placement")
             .Append(chrome::kLocalStateFilename);
-
-    tmp_pref_file_ = tmp_profile_.Append(chrome::kLocalStateFilename);
+      tmp_pref_file_ = tmp_profile_.Append(chrome::kLocalStateFilename);
+    }
 
     ASSERT_TRUE(file_util::PathExists(reference_pref_file));
-
-    // Copy only the Local State file, the rest will be automatically created
+    // Copy only the Preferences file if |new_profile_|, or Local State if not,
+    // and the rest will be automatically created.
     ASSERT_TRUE(file_util::CopyFile(reference_pref_file, tmp_pref_file_));
 
 #if defined(OS_WIN)
@@ -66,20 +76,21 @@
   }
 
  public:
+  bool new_profile_;
   FilePath tmp_pref_file_;
   FilePath tmp_profile_;
 };
 
-#if defined(OS_WIN)
+#if !defined(OS_LINUX)
 // This test verifies that the window position from the prefs file is restored
 // when the app restores.  This doesn't really make sense on Linux, where
 // the window manager might fight with you over positioning.  However, we
 // might be able to make this work on buildbots.
-// Also, not sure what should happen on the mac.  In any case, the code below
-// (minus the Windows bits) compiles fine on my Linux box now.
 // TODO(port): revisit this.
 TEST_F(PreferenceServiceTest, PreservedWindowPlacementIsLoaded) {
-  // The window should open with the reference profile
+  // The window should open with the new reference profile, with window
+  // placement values stored in the user data directory.
+  new_profile_ = true;
   ASSERT_TRUE(LaunchAppWithProfile());
 
   ASSERT_TRUE(file_util::PathExists(tmp_pref_file_));
@@ -132,3 +143,66 @@
   EXPECT_EQ(is_maximized, is_window_maximized);
 }
 #endif
+
+#if !defined(OS_LINUX)
+TEST_F(PreferenceServiceTest, PreservedWindowPlacementIsMigrated) {
+  // The window should open with the old reference profile, with window
+  // placement values stored in Local State.
+  new_profile_ = false;
+  ASSERT_TRUE(LaunchAppWithProfile());
+
+  ASSERT_TRUE(file_util::PathExists(tmp_pref_file_));
+
+  JSONFileValueSerializer deserializer(tmp_pref_file_);
+  scoped_ptr<Value> root(deserializer.Deserialize(NULL, NULL));
+
+  ASSERT_TRUE(root.get());
+  ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
+
+  // Retrieve the screen rect for the launched window
+  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+  ASSERT_TRUE(browser.get());
+  scoped_refptr<WindowProxy> window(browser->GetWindow());
+  ASSERT_TRUE(window.get());
+
+  gfx::Rect bounds;
+  ASSERT_TRUE(window->GetBounds(&bounds));
+
+  // Values from old reference profile in Local State should have been
+  // correctly migrated to the user's Preferences -- if so, the window
+  // should be set to values taken from the user's Local State.
+  DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
+
+  // Retrieve the expected rect values from User Preferences, where they
+  // should have been migrated from Local State.
+  int bottom = 0;
+  std::string kBrowserWindowPlacement(prefs::kBrowserWindowPlacement);
+  EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".bottom",
+      &bottom));
+  EXPECT_EQ(bottom, bounds.y() + bounds.height());
+
+  int top = 0;
+  EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".top",
+      &top));
+  EXPECT_EQ(top, bounds.y());
+
+  int left = 0;
+  EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".left",
+      &left));
+  EXPECT_EQ(left, bounds.x());
+
+  int right = 0;
+  EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".right",
+      &right));
+  EXPECT_EQ(right, bounds.x() + bounds.width());
+
+  // Find if launched window is maximized.
+  bool is_window_maximized = false;
+  ASSERT_TRUE(window->IsMaximized(&is_window_maximized));
+  bool is_maximized = false;
+  EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + ".maximized",
+      &is_maximized));
+  EXPECT_EQ(is_maximized, is_window_maximized);
+}
+#endif
+
diff --git a/chrome/browser/prefs/pref_service_unittest.cc b/chrome/browser/prefs/pref_service_unittest.cc
index 1a79708..90a1882 100644
--- a/chrome/browser/prefs/pref_service_unittest.cc
+++ b/chrome/browser/prefs/pref_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
 #include "chrome/browser/prefs/pref_observer_mock.h"
 #include "chrome/browser/prefs/pref_service_mock_builder.h"
 #include "chrome/browser/prefs/pref_value_store.h"
-#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
 #include "chrome/browser/prefs/testing_pref_store.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -148,15 +148,84 @@
   Mock::VerifyAndClearExpectations(&obs2);
 }
 
+// Make sure that if a preference changes type, so the wrong type is stored in
+// the user pref file, it uses the correct fallback value instead.
+TEST(PrefServiceTest, GetValueChangedType) {
+  const int kTestValue = 10;
+  TestingPrefService prefs;
+  prefs.RegisterIntegerPref(prefs::kStabilityLaunchCount, kTestValue);
+
+  // Check falling back to a recommended value.
+  prefs.SetUserPref(prefs::kStabilityLaunchCount,
+                    Value::CreateStringValue("not an integer"));
+  const PrefService::Preference* pref =
+      prefs.FindPreference(prefs::kStabilityLaunchCount);
+  ASSERT_TRUE(pref);
+  const Value* value = pref->GetValue();
+  ASSERT_TRUE(value);
+  EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+  int actual_int_value = -1;
+  EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+  EXPECT_EQ(kTestValue, actual_int_value);
+}
+
+void assertProxyMode(const ProxyConfigDictionary& dict,
+                     ProxyPrefs::ProxyMode expected_mode) {
+  ProxyPrefs::ProxyMode actual_mode;
+  ASSERT_TRUE(dict.GetMode(&actual_mode));
+  EXPECT_EQ(expected_mode, actual_mode);
+}
+
+void assertProxyServer(const ProxyConfigDictionary& dict,
+                       const std::string& expected) {
+  std::string actual;
+  if (!expected.empty()) {
+    ASSERT_TRUE(dict.GetProxyServer(&actual));
+    EXPECT_EQ(expected, actual);
+  } else {
+    EXPECT_FALSE(dict.GetProxyServer(&actual));
+  }
+}
+
+void assertPacUrl(const ProxyConfigDictionary& dict,
+                  const std::string& expected) {
+  std::string actual;
+  if (!expected.empty()) {
+    ASSERT_TRUE(dict.GetPacUrl(&actual));
+    EXPECT_EQ(expected, actual);
+  } else {
+    EXPECT_FALSE(dict.GetPacUrl(&actual));
+  }
+}
+
+void assertBypassList(const ProxyConfigDictionary& dict,
+                      const std::string& expected) {
+  std::string actual;
+  if (!expected.empty()) {
+    ASSERT_TRUE(dict.GetBypassList(&actual));
+    EXPECT_EQ(expected, actual);
+  } else {
+    EXPECT_FALSE(dict.GetBypassList(&actual));
+  }
+}
+
+void assertProxyModeWithoutParams(const ProxyConfigDictionary& dict,
+                                  ProxyPrefs::ProxyMode proxy_mode) {
+  assertProxyMode(dict, proxy_mode);
+  assertProxyServer(dict, "");
+  assertPacUrl(dict, "");
+  assertBypassList(dict, "");
+}
+
 TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineOptions) {
   CommandLine command_line(CommandLine::NO_PROGRAM);
   command_line.AppendSwitchASCII(switches::kProxyBypassList, "123");
   command_line.AppendSwitchASCII(switches::kProxyServer, "789");
   scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
       new policy::MockConfigurationPolicyProvider());
-  Value* mode_value = Value::CreateIntegerValue(
-      policy::kPolicyManuallyConfiguredProxyMode);
-  provider->AddPolicy(policy::kPolicyProxyMode, mode_value);
+  Value* mode_name = Value::CreateStringValue(
+      ProxyPrefs::kFixedServersProxyModeName);
+  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
   provider->AddPolicy(policy::kPolicyProxyBypassList,
                       Value::CreateStringValue("abc"));
   provider->AddPolicy(policy::kPolicyProxyServer,
@@ -168,11 +237,11 @@
   builder.WithCommandLine(&command_line);
   scoped_ptr<PrefService> prefs(builder.Create());
   browser::RegisterUserPrefs(prefs.get());
-  EXPECT_EQ(ProxyPrefs::MODE_FIXED_SERVERS,
-            prefs->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ("789", prefs->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ("123", prefs->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
+  assertProxyMode(dict, ProxyPrefs::MODE_FIXED_SERVERS);
+  assertProxyServer(dict, "789");
+  assertPacUrl(dict, "");
+  assertBypassList(dict, "123");
 
   // Try a second time time with the managed PrefStore in place, the
   // manual proxy policy should have removed all traces of the command
@@ -181,11 +250,11 @@
   builder.WithManagedPlatformProvider(provider.get());
   scoped_ptr<PrefService> prefs2(builder.Create());
   browser::RegisterUserPrefs(prefs2.get());
-  EXPECT_EQ(ProxyPrefs::MODE_FIXED_SERVERS,
-            prefs2->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ("ghi", prefs2->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ("abc", prefs2->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
+  assertProxyMode(dict2, ProxyPrefs::MODE_FIXED_SERVERS);
+  assertProxyServer(dict2, "ghi");
+  assertPacUrl(dict2, "");
+  assertBypassList(dict2, "abc");
 }
 
 TEST(PrefServiceTest, ProxyPolicyOverridesUnrelatedCommandLineOptions) {
@@ -194,9 +263,9 @@
   command_line.AppendSwitchASCII(switches::kProxyServer, "789");
   scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
       new policy::MockConfigurationPolicyProvider());
-  Value* mode_value = Value::CreateIntegerValue(
-      policy::kPolicyAutoDetectProxyMode);
-  provider->AddPolicy(policy::kPolicyProxyMode, mode_value);
+  Value* mode_name = Value::CreateStringValue(
+      ProxyPrefs::kAutoDetectProxyModeName);
+  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
 
   // First verify that command-line options are set correctly when
   // there is no policy in effect.
@@ -204,10 +273,11 @@
   builder.WithCommandLine(&command_line);
   scoped_ptr<PrefService> prefs(builder.Create());
   browser::RegisterUserPrefs(prefs.get());
-  EXPECT_EQ(ProxyPrefs::MODE_FIXED_SERVERS,
-            prefs->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ("789", prefs->GetString(prefs::kProxyServer));
-  EXPECT_EQ("123", prefs->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
+  assertProxyMode(dict, ProxyPrefs::MODE_FIXED_SERVERS);
+  assertProxyServer(dict, "789");
+  assertPacUrl(dict, "");
+  assertBypassList(dict, "123");
 
   // Try a second time time with the managed PrefStore in place, the
   // no proxy policy should have removed all traces of the command
@@ -217,11 +287,8 @@
   builder.WithManagedPlatformProvider(provider.get());
   scoped_ptr<PrefService> prefs2(builder.Create());
   browser::RegisterUserPrefs(prefs2.get());
-  EXPECT_EQ(ProxyPrefs::MODE_AUTO_DETECT,
-      prefs2->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
+  assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_AUTO_DETECT);
 }
 
 TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineNoProxy) {
@@ -229,9 +296,9 @@
   command_line.AppendSwitch(switches::kNoProxyServer);
   scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
       new policy::MockConfigurationPolicyProvider());
-  Value* mode_value = Value::CreateIntegerValue(
-      policy::kPolicyAutoDetectProxyMode);
-  provider->AddPolicy(policy::kPolicyProxyMode, mode_value);
+  Value* mode_name = Value::CreateStringValue(
+      ProxyPrefs::kAutoDetectProxyModeName);
+  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
 
   // First verify that command-line options are set correctly when
   // there is no policy in effect.
@@ -239,10 +306,8 @@
   builder.WithCommandLine(&command_line);
   scoped_ptr<PrefService> prefs(builder.Create());
   browser::RegisterUserPrefs(prefs.get());
-  EXPECT_EQ(ProxyPrefs::MODE_DIRECT, prefs->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
+  assertProxyModeWithoutParams(dict, ProxyPrefs::MODE_DIRECT);
 
   // Try a second time time with the managed PrefStore in place, the
   // auto-detect should be overridden. The default pref store must be
@@ -251,11 +316,8 @@
   builder.WithManagedPlatformProvider(provider.get());
   scoped_ptr<PrefService> prefs2(builder.Create());
   browser::RegisterUserPrefs(prefs2.get());
-  EXPECT_EQ(ProxyPrefs::MODE_AUTO_DETECT,
-      prefs2->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
+  assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_AUTO_DETECT);
 }
 
 TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineAutoDetect) {
@@ -263,9 +325,9 @@
   command_line.AppendSwitch(switches::kProxyAutoDetect);
   scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
       new policy::MockConfigurationPolicyProvider());
-  Value* mode_value = Value::CreateIntegerValue(
-      policy::kPolicyNoProxyServerMode);
-  provider->AddPolicy(policy::kPolicyProxyMode, mode_value);
+  Value* mode_name = Value::CreateStringValue(
+      ProxyPrefs::kDirectProxyModeName);
+  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
 
   // First verify that the auto-detect is set if there is no managed
   // PrefStore.
@@ -273,10 +335,8 @@
   builder.WithCommandLine(&command_line);
   scoped_ptr<PrefService> prefs(builder.Create());
   browser::RegisterUserPrefs(prefs.get());
-  EXPECT_EQ(ProxyPrefs::MODE_AUTO_DETECT, prefs->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ(std::string(), prefs->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
+  assertProxyModeWithoutParams(dict, ProxyPrefs::MODE_AUTO_DETECT);
 
   // Try a second time time with the managed PrefStore in place, the
   // auto-detect should be overridden. The default pref store must be
@@ -285,10 +345,8 @@
   builder.WithManagedPlatformProvider(provider.get());
   scoped_ptr<PrefService> prefs2(builder.Create());
   browser::RegisterUserPrefs(prefs2.get());
-  EXPECT_EQ(ProxyPrefs::MODE_DIRECT, prefs2->GetInteger(prefs::kProxyMode));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyServer));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyPacUrl));
-  EXPECT_EQ(std::string(), prefs2->GetString(prefs::kProxyBypassList));
+  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
+  assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_DIRECT);
 }
 
 class PrefServiceSetValueTest : public testing::Test {
@@ -296,11 +354,7 @@
   static const char kName[];
   static const char kValue[];
 
-  PrefServiceSetValueTest()
-      : null_value_(Value::CreateNullValue()) {}
-
   TestingPrefService prefs_;
-  scoped_ptr<Value> null_value_;
   PrefObserverMock observer_;
 };
 
@@ -337,10 +391,8 @@
   registrar.Init(&prefs_);
   registrar.Add(kName, &observer_);
 
-  // Dictionary values are special: setting one to NULL is the same as clearing
-  // the user value, allowing the NULL default to take (or keep) control.
   EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
-  prefs_.Set(kName, *null_value_);
+  prefs_.RemoveUserPref(kName);
   Mock::VerifyAndClearExpectations(&observer_);
 
   DictionaryValue new_value;
@@ -353,8 +405,9 @@
   prefs_.Set(kName, new_value);
   Mock::VerifyAndClearExpectations(&observer_);
 
-  observer_.Expect(&prefs_, kName, null_value_.get());
-  prefs_.Set(kName, *null_value_);
+  DictionaryValue empty;
+  observer_.Expect(&prefs_, kName, &empty);
+  prefs_.Set(kName, empty);
   Mock::VerifyAndClearExpectations(&observer_);
 }
 
@@ -364,10 +417,8 @@
   registrar.Init(&prefs_);
   registrar.Add(kName, &observer_);
 
-  // List values are special: setting one to NULL is the same as clearing the
-  // user value, allowing the NULL default to take (or keep) control.
   EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
-  prefs_.Set(kName, *null_value_);
+  prefs_.RemoveUserPref(kName);
   Mock::VerifyAndClearExpectations(&observer_);
 
   ListValue new_value;
@@ -380,7 +431,8 @@
   prefs_.Set(kName, new_value);
   Mock::VerifyAndClearExpectations(&observer_);
 
-  observer_.Expect(&prefs_, kName, null_value_.get());
-  prefs_.Set(kName, *null_value_);
+  ListValue empty;
+  observer_.Expect(&prefs_, kName, &empty);
+  prefs_.Set(kName, empty);
   Mock::VerifyAndClearExpectations(&observer_);
 }
diff --git a/chrome/browser/prefs/pref_set_observer.cc b/chrome/browser/prefs/pref_set_observer.cc
index 133b219..117937e 100644
--- a/chrome/browser/prefs/pref_set_observer.cc
+++ b/chrome/browser/prefs/pref_set_observer.cc
@@ -47,10 +47,7 @@
     PrefService* pref_service,
     NotificationObserver* observer) {
   PrefSetObserver* pref_set = new PrefSetObserver(pref_service, observer);
-  pref_set->AddPref(prefs::kProxyMode);
-  pref_set->AddPref(prefs::kProxyServer);
-  pref_set->AddPref(prefs::kProxyPacUrl);
-  pref_set->AddPref(prefs::kProxyBypassList);
+  pref_set->AddPref(prefs::kProxy);
 
   return pref_set;
 }
@@ -66,6 +63,7 @@
   pref_set->AddPref(prefs::kDefaultSearchProviderSearchURL);
   pref_set->AddPref(prefs::kDefaultSearchProviderSuggestURL);
   pref_set->AddPref(prefs::kDefaultSearchProviderIconURL);
+  pref_set->AddPref(prefs::kDefaultSearchProviderInstantURL);
   pref_set->AddPref(prefs::kDefaultSearchProviderEncodings);
 
   return pref_set;
diff --git a/chrome/browser/prefs/pref_value_map.cc b/chrome/browser/prefs/pref_value_map.cc
index 6e7bf79..0857f6d 100644
--- a/chrome/browser/prefs/pref_value_map.cc
+++ b/chrome/browser/prefs/pref_value_map.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -58,6 +58,22 @@
   prefs_.clear();
 }
 
+PrefValueMap::iterator PrefValueMap::begin() {
+  return prefs_.begin();
+}
+
+PrefValueMap::iterator PrefValueMap::end() {
+  return prefs_.end();
+}
+
+PrefValueMap::const_iterator PrefValueMap::begin() const {
+  return prefs_.begin();
+}
+
+PrefValueMap::const_iterator PrefValueMap::end() const {
+  return prefs_.end();
+}
+
 bool PrefValueMap::GetBoolean(const std::string& key,
                               bool* value) const {
   Value* stored_value = NULL;
diff --git a/chrome/browser/prefs/pref_value_map.h b/chrome/browser/prefs/pref_value_map.h
index 0e99920..19aeb05 100644
--- a/chrome/browser/prefs/pref_value_map.h
+++ b/chrome/browser/prefs/pref_value_map.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,6 +17,9 @@
 // A generic string to value map used by the PrefStore implementations.
 class PrefValueMap {
  public:
+  typedef std::map<std::string, Value*>::iterator iterator;
+  typedef std::map<std::string, Value*>::const_iterator const_iterator;
+
   PrefValueMap();
   virtual ~PrefValueMap();
 
@@ -36,6 +39,11 @@
   // Clears the map.
   void Clear();
 
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
   // Gets a boolean value for |key| and stores it in |value|. Returns true if
   // the value was found and of the proper type.
   bool GetBoolean(const std::string& key, bool* value) const;
diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc
index bfe00b4..d3cf044 100644
--- a/chrome/browser/prefs/pref_value_store.cc
+++ b/chrome/browser/prefs/pref_value_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,8 +13,11 @@
 }
 
 PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
-  if (pref_store_.get())
+  if (pref_store_.get()) {
     pref_store_->RemoveObserver(this);
+    pref_store_ = NULL;
+  }
+  pref_value_store_ = NULL;
 }
 
 void PrefValueStore::PrefStoreKeeper::Initialize(
@@ -25,7 +28,7 @@
     pref_store_->RemoveObserver(this);
   type_ = type;
   pref_value_store_ = store;
-  pref_store_.reset(pref_store);
+  pref_store_ = pref_store;
   if (pref_store_.get())
     pref_store_->AddObserver(this);
 }
@@ -40,20 +43,22 @@
 }
 
 PrefValueStore::PrefValueStore(PrefStore* managed_platform_prefs,
-                               PrefStore* device_management_prefs,
+                               PrefStore* managed_cloud_prefs,
                                PrefStore* extension_prefs,
                                PrefStore* command_line_prefs,
                                PrefStore* user_prefs,
-                               PrefStore* recommended_prefs,
+                               PrefStore* recommended_platform_prefs,
+                               PrefStore* recommended_cloud_prefs,
                                PrefStore* default_prefs,
                                PrefNotifier* pref_notifier)
     : pref_notifier_(pref_notifier) {
   InitPrefStore(MANAGED_PLATFORM_STORE, managed_platform_prefs);
-  InitPrefStore(DEVICE_MANAGEMENT_STORE, device_management_prefs);
+  InitPrefStore(MANAGED_CLOUD_STORE, managed_cloud_prefs);
   InitPrefStore(EXTENSION_STORE, extension_prefs);
   InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
   InitPrefStore(USER_STORE, user_prefs);
-  InitPrefStore(RECOMMENDED_STORE, recommended_prefs);
+  InitPrefStore(RECOMMENDED_PLATFORM_STORE, recommended_platform_prefs);
+  InitPrefStore(RECOMMENDED_CLOUD_STORE, recommended_cloud_prefs);
   InitPrefStore(DEFAULT_STORE, default_prefs);
 
   CheckInitializationCompleted();
@@ -61,45 +66,68 @@
 
 PrefValueStore::~PrefValueStore() {}
 
+PrefValueStore* PrefValueStore::CloneAndSpecialize(
+    PrefStore* managed_platform_prefs,
+    PrefStore* managed_cloud_prefs,
+    PrefStore* extension_prefs,
+    PrefStore* command_line_prefs,
+    PrefStore* user_prefs,
+    PrefStore* recommended_platform_prefs,
+    PrefStore* recommended_cloud_prefs,
+    PrefStore* default_prefs,
+    PrefNotifier* pref_notifier) {
+  DCHECK(pref_notifier);
+  if (!managed_platform_prefs)
+    managed_platform_prefs = GetPrefStore(MANAGED_PLATFORM_STORE);
+  if (!managed_cloud_prefs)
+    managed_cloud_prefs = GetPrefStore(MANAGED_CLOUD_STORE);
+  if (!extension_prefs)
+    extension_prefs = GetPrefStore(EXTENSION_STORE);
+  if (!command_line_prefs)
+    command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
+  if (!user_prefs)
+    user_prefs = GetPrefStore(USER_STORE);
+  if (!recommended_platform_prefs)
+    recommended_platform_prefs = GetPrefStore(RECOMMENDED_PLATFORM_STORE);
+  if (!recommended_cloud_prefs)
+    recommended_cloud_prefs = GetPrefStore(RECOMMENDED_CLOUD_STORE);
+  if (!default_prefs)
+    default_prefs = GetPrefStore(DEFAULT_STORE);
+
+  return new PrefValueStore(
+      managed_platform_prefs, managed_cloud_prefs, extension_prefs,
+      command_line_prefs, user_prefs, recommended_platform_prefs,
+      recommended_cloud_prefs, default_prefs,
+      pref_notifier);
+}
+
 bool PrefValueStore::GetValue(const std::string& name,
+                              Value::ValueType type,
                               Value** out_value) const {
+  *out_value = NULL;
   // Check the |PrefStore|s in order of their priority from highest to lowest
   // to find the value of the preference described by the given preference name.
   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
     if (GetValueFromStore(name.c_str(), static_cast<PrefStoreType>(i),
-                          out_value))
+                          out_value)) {
+      if (!(*out_value)->IsType(type)) {
+        LOG(WARNING) << "Expected type for " << name << " is " << type
+                     << " but got " << (*out_value)->GetType()
+                     << " in store " << i;
+        continue;
+      }
       return true;
+    }
   }
   return false;
 }
 
-void PrefValueStore::RegisterPreferenceType(const std::string& name,
-                                            Value::ValueType type) {
-  pref_types_[name] = type;
-}
-
-Value::ValueType PrefValueStore::GetRegisteredType(
-    const std::string& name) const {
-  PrefTypeMap::const_iterator found = pref_types_.find(name);
-  if (found == pref_types_.end())
-    return Value::TYPE_NULL;
-  return found->second;
-}
-
-bool PrefValueStore::HasPrefPath(const char* path) const {
-  Value* tmp_value = NULL;
-  const std::string name(path);
-  bool rv = GetValue(name, &tmp_value);
-  // Merely registering a pref doesn't count as "having" it: we require a
-  // non-default value set.
-  return rv && !PrefValueFromDefaultStore(path);
-}
-
 void PrefValueStore::NotifyPrefChanged(
     const char* path,
     PrefValueStore::PrefStoreType new_store) {
   DCHECK(new_store != INVALID_STORE);
 
+<<<<<<< HEAD
   // If this pref is not registered, just discard the notification.
   if (!pref_types_.count(path))
     return;
@@ -120,16 +148,19 @@
 
 #ifndef ANDROID
   if (changed)
+=======
+  // If the pref is controlled by a higher-priority store, its effective value
+  // cannot have changed.
+  PrefStoreType controller = ControllingPrefStoreForPref(path);
+  if (controller == INVALID_STORE || controller >= new_store)
+>>>>>>> chromium.org at r11.0.672.0
     pref_notifier_->OnPreferenceChanged(path);
 #endif
 }
 
-bool PrefValueStore::PrefValueInManagedPlatformStore(const char* name) const {
-  return PrefValueInStore(name, MANAGED_PLATFORM_STORE);
-}
-
-bool PrefValueStore::PrefValueInDeviceManagementStore(const char* name) const {
-  return PrefValueInStore(name, DEVICE_MANAGEMENT_STORE);
+bool PrefValueStore::PrefValueInManagedStore(const char* name) const {
+  return PrefValueInStore(name, MANAGED_PLATFORM_STORE) ||
+         PrefValueInStore(name, MANAGED_CLOUD_STORE);
 }
 
 bool PrefValueStore::PrefValueInExtensionStore(const char* name) const {
@@ -158,24 +189,6 @@
          effective_store == INVALID_STORE;
 }
 
-// Returns true if the actual value is a valid type for the expected type when
-// found in the given store.
-bool PrefValueStore::IsValidType(Value::ValueType expected,
-                                 Value::ValueType actual,
-                                 PrefValueStore::PrefStoreType store) {
-  if (expected == actual)
-    return true;
-
-  // Dictionaries and lists are allowed to hold TYPE_NULL values too, but only
-  // in the default pref store.
-  if (store == DEFAULT_STORE &&
-      actual == Value::TYPE_NULL &&
-      (expected == Value::TYPE_DICTIONARY || expected == Value::TYPE_LIST)) {
-    return true;
-  }
-  return false;
-}
-
 bool PrefValueStore::PrefValueInStore(
     const char* name,
     PrefValueStore::PrefStoreType store) const {
@@ -227,12 +240,7 @@
         }
         // Fall through...
       case PrefStore::READ_OK:
-        if (IsValidType(GetRegisteredType(name),
-                        (*out_value)->GetType(),
-                        store_type)) {
-          return true;
-        }
-        break;
+        return true;
       case PrefStore::READ_NO_VALUE:
         break;
     }
@@ -260,7 +268,8 @@
 
 void PrefValueStore::CheckInitializationCompleted() {
   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
-    PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i));
+    scoped_refptr<PrefStore> store =
+        GetPrefStore(static_cast<PrefStoreType>(i));
     if (store && !store->IsInitializationComplete())
       return;
   }
diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h
index 8b6ba0c..0592989 100644
--- a/chrome/browser/prefs/pref_value_store.h
+++ b/chrome/browser/prefs/pref_value_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,6 @@
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
 #include "base/values.h"
 #ifndef ANDROID
 #include "chrome/browser/browser_thread.h"
@@ -23,7 +22,6 @@
 class FilePath;
 class PrefNotifier;
 class PrefStore;
-class Profile;
 
 // The PrefValueStore manages various sources of values for Preferences
 // (e.g., configuration policies, extensions, and user settings). It returns
@@ -32,65 +30,62 @@
 //
 // Unless otherwise explicitly noted, all of the methods of this class must
 // be called on the UI thread.
-class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
+class PrefValueStore {
  public:
   // In decreasing order of precedence:
   //   |managed_platform_prefs| contains all managed platform (non-cloud policy)
   //        preference values.
-  //   |device_management_prefs| contains all device management (cloud policy)
-  //        preference values.
+  //   |managed_cloud_prefs| contains all managed cloud policy preference
+  //        values.
   //   |extension_prefs| contains preference values set by extensions.
   //   |command_line_prefs| contains preference values set by command-line
   //        switches.
   //   |user_prefs| contains all user-set preference values.
-  //   |recommended_prefs| contains all recommended (policy) preference values.
+  //   |recommended_platform_prefs| contains all recommended platform policy
+  //        preference values.
+  //   |recommended_cloud_prefs| contains all recommended cloud policy
+  //        preference values.
   //   |default_prefs| contains application-default preference values. It must
   //        be non-null if any preferences are to be registered.
   //
   // |pref_notifier| facilitates broadcasting preference change notifications
   // to the world.
-  //
-  // The |profile| parameter is used to construct a replacement device
-  // management pref store. This is done after policy refresh when we swap out
-  // the policy pref stores for new ones, so the |profile| pointer needs to be
-  // kept around for then. It is safe to pass a NULL pointer for local state
-  // preferences.
   PrefValueStore(PrefStore* managed_platform_prefs,
-                 PrefStore* device_management_prefs,
+                 PrefStore* managed_cloud_prefs,
                  PrefStore* extension_prefs,
                  PrefStore* command_line_prefs,
                  PrefStore* user_prefs,
-                 PrefStore* recommended_prefs,
+                 PrefStore* recommended_platform_prefs,
+                 PrefStore* recommended_cloud_prefs,
                  PrefStore* default_prefs,
                  PrefNotifier* pref_notifier);
   virtual ~PrefValueStore();
 
-  // Gets the value for the given preference name that has a valid value type;
-  // that is, the same type the preference was registered with, or NULL for
-  // default values of Dictionaries and Lists. Returns true if a valid value
+  // Creates a clone of this PrefValueStore with PrefStores overwritten
+  // by the parameters passed, if unequal NULL.
+  PrefValueStore* CloneAndSpecialize(PrefStore* managed_platform_prefs,
+                                     PrefStore* managed_cloud_prefs,
+                                     PrefStore* extension_prefs,
+                                     PrefStore* command_line_prefs,
+                                     PrefStore* user_prefs,
+                                     PrefStore* recommended_platform_prefs,
+                                     PrefStore* recommended_cloud_prefs,
+                                     PrefStore* default_prefs,
+                                     PrefNotifier* pref_notifier);
+
+  // Gets the value for the given preference name that has the specified value
+  // type. Values stored in a PrefStore that have the matching |name| but
+  // a non-matching |type| are silently skipped. Returns true if a valid value
   // was found in any of the available PrefStores. Most callers should use
   // Preference::GetValue() instead of calling this method directly.
-  bool GetValue(const std::string& name, Value** out_value) const;
-
-  // Adds a preference to the mapping of names to types.
-  void RegisterPreferenceType(const std::string& name, Value::ValueType type);
-
-  // Gets the registered value type for the given preference name. Returns
-  // Value::TYPE_NULL if the preference has never been registered.
-  Value::ValueType GetRegisteredType(const std::string& name) const;
-
-  // Returns true if the PrefValueStore contains the given preference (i.e.,
-  // it's been registered), and a value with the correct type has been actively
-  // set in some pref store. The application default specified when the pref was
-  // registered does not count as an "actively set" value, but another pref
-  // store setting a value that happens to be equal to the default does.
-  bool HasPrefPath(const char* name) const;
+  bool GetValue(const std::string& name,
+                Value::ValueType type,
+                Value** out_value) const;
 
   // These methods return true if a preference with the given name is in the
   // indicated pref store, even if that value is currently being overridden by
   // a higher-priority source.
-  bool PrefValueInManagedPlatformStore(const char* name) const;
-  bool PrefValueInDeviceManagementStore(const char* name) const;
+  bool PrefValueInManagedStore(const char* name) const;
   bool PrefValueInExtensionStore(const char* name) const;
   bool PrefValueInUserStore(const char* name) const;
 
@@ -122,11 +117,12 @@
     // an invalid marker, e.g. as a return value.
     INVALID_STORE = -1,
     MANAGED_PLATFORM_STORE = 0,
-    DEVICE_MANAGEMENT_STORE,
+    MANAGED_CLOUD_STORE,
     EXTENSION_STORE,
     COMMAND_LINE_STORE,
     USER_STORE,
-    RECOMMENDED_STORE,
+    RECOMMENDED_PLATFORM_STORE,
+    RECOMMENDED_CLOUD_STORE,
     DEFAULT_STORE,
     PREF_STORE_TYPE_MAX = DEFAULT_STORE
   };
@@ -157,7 +153,7 @@
     PrefValueStore* pref_value_store_;
 
     // The PrefStore managed by this keeper.
-    scoped_ptr<PrefStore> pref_store_;
+    scoped_refptr<PrefStore> pref_store_;
 
     // Type of the pref store.
     PrefStoreType type_;
@@ -174,12 +170,6 @@
   FRIEND_TEST_ALL_PREFIXES(PrefValueStorePolicyRefreshTest,
                            TestConcurrentPolicyRefresh);
 
-  // Returns true if the actual type is a valid type for the expected type when
-  // found in the given store.
-  static bool IsValidType(Value::ValueType expected,
-                          Value::ValueType actual,
-                          PrefStoreType store);
-
   // Returns true if the preference with the given name has a value in the
   // given PrefStoreType, of the same value type as the preference was
   // registered with.
diff --git a/chrome/browser/prefs/pref_value_store_unittest.cc b/chrome/browser/prefs/pref_value_store_unittest.cc
index 5c0fa53..e67de56 100644
--- a/chrome/browser/prefs/pref_value_store_unittest.cc
+++ b/chrome/browser/prefs/pref_value_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -33,58 +33,80 @@
 
 }  // namespace
 
-// Names of the preferences used in this test program.
+// Names of the preferences used in this test.
 namespace prefs {
+const char kManagedPlatformPref[] = "this.pref.managed_platform";
+const char kManagedCloudPref[] = "this.pref.managed_cloud";
+const char kCommandLinePref[] = "this.pref.command_line";
+const char kExtensionPref[] = "this.pref.extension";
+const char kUserPref[] = "this.pref.user";
+const char kRecommendedPlatformPref[] = "this.pref.recommended_platform";
+const char kRecommendedCloudPref[] = "this.pref.recommended_cloud";
+const char kDefaultPref[] = "this.pref.default";
 const char kMissingPref[] = "this.pref.does_not_exist";
-const char kRecommendedPref[] = "this.pref.recommended_value_only";
-const char kSampleDict[] = "sample.dict";
-const char kSampleList[] = "sample.list";
-const char kDefaultPref[] = "default.pref";
 }
 
 // Potentially expected values of all preferences used in this test program.
 namespace managed_platform_pref {
-const std::string kHomepageValue = "http://www.topeka.com";
+const char kManagedPlatformValue[] = "managed_platform:managed_platform";
 }
 
-namespace device_management_pref {
-const std::string kSearchProviderNameValue = "Chromium";
-const char kHomepageValue[] = "http://www.wandering-around.org";
+namespace managed_cloud_pref {
+const char kManagedPlatformValue[] = "managed_cloud:managed_platform";
+const char kManagedCloudValue[] = "managed_cloud:managed_cloud";
 }
 
 namespace extension_pref {
-const char kCurrentThemeIDValue[] = "set by extension";
-const char kHomepageValue[] = "http://www.chromium.org";
-const std::string kSearchProviderNameValue = "AreYouFeelingALittleLucky";
+const char kManagedPlatformValue[] = "extension:managed_platform";
+const char kManagedCloudValue[] = "extension:managed_cloud";
+const char kExtensionValue[] = "extension:extension";
 }
 
 namespace command_line_pref {
-const char kApplicationLocaleValue[] = "hi-MOM";
-const char kCurrentThemeIDValue[] = "zyxwvut";
-const char kHomepageValue[] = "http://www.ferretcentral.org";
-const std::string kSearchProviderNameValue = "AreYouFeelingPrettyLucky";
+const char kManagedPlatformValue[] = "command_line:managed_platform";
+const char kManagedCloudValue[] = "command_line:managed_cloud";
+const char kExtensionValue[] = "command_line:extension";
+const char kCommandLineValue[] = "command_line:command_line";
 }
 
-// The "user" namespace is defined globally in an ARM system header, so we need
-// something different here.
 namespace user_pref {
-const int kStabilityLaunchCountValue = 31;
-const bool kDeleteCacheValue = true;
-const char kCurrentThemeIDValue[] = "abcdefg";
-const char kHomepageValue[] = "http://www.google.com";
-const char kApplicationLocaleValue[] = "is-WRONG";
-const std::string kSearchProviderNameValue = "AreYouFeelingVeryLucky";
+const char kManagedPlatformValue[] = "user:managed_platform";
+const char kManagedCloudValue[] = "user:managed_cloud";
+const char kExtensionValue[] = "user:extension";
+const char kCommandLineValue[] = "user:command_line";
+const char kUserValue[] = "user:user";
 }
 
-namespace recommended_pref {
-const int kStabilityLaunchCountValue = 10;
-const bool kRecommendedPrefValue = true;
+namespace recommended_platform_pref {
+const char kManagedPlatformValue[] = "recommended_platform:managed_platform";
+const char kManagedCloudValue[] = "recommended_platform:managed_cloud";
+const char kExtensionValue[] = "recommended_platform:extension";
+const char kCommandLineValue[] = "recommended_platform:command_line";
+const char kUserValue[] = "recommended_platform:user";
+const char kRecommendedPlatformValue[] =
+    "recommended_platform:recommended_platform";
+}
+
+namespace recommended_cloud_pref {
+const char kManagedPlatformValue[] = "recommended_cloud:managed_platform";
+const char kManagedCloudValue[] = "recommended_cloud:managed_cloud";
+const char kExtensionValue[] = "recommended_cloud:extension";
+const char kCommandLineValue[] = "recommended_cloud:command_line";
+const char kUserValue[] = "recommended_cloud:user";
+const char kRecommendedPlatformValue[] =
+    "recommended_cloud:recommended_platform";
+const char kRecommendedCloudValue[] = "recommended_cloud:recommended_cloud";
 }
 
 namespace default_pref {
-const int kDefaultValue = 7;
-const char kHomepageValue[] = "default homepage";
-const std::string kSearchProviderNameValue = "AreYouFeelingExtraLucky";
+const char kManagedPlatformValue[] = "default:managed_platform";
+const char kManagedCloudValue[] = "default:managed_cloud";
+const char kExtensionValue[] = "default:extension";
+const char kCommandLineValue[] = "default:command_line";
+const char kUserValue[] = "default:user";
+const char kRecommendedPlatformValue[] = "default:recommended_platform";
+const char kRecommendedCloudValue[] = "default:recommended_cloud";
+const char kDefaultValue[] = "default:default";
 }
 
 class PrefValueStoreTest : public testing::Test {
@@ -92,328 +114,350 @@
   virtual void SetUp() {
     // Create TestingPrefStores.
     CreateManagedPlatformPrefs();
-    CreateDeviceManagementPrefs();
+    CreateManagedCloudPrefs();
     CreateExtensionPrefs();
     CreateCommandLinePrefs();
     CreateUserPrefs();
-    CreateRecommendedPrefs();
+    CreateRecommendedPlatformPrefs();
+    CreateRecommendedCloudPrefs();
     CreateDefaultPrefs();
 
     // Create a fresh PrefValueStore.
-    pref_value_store_ = new PrefValueStore(
+    pref_value_store_.reset(new PrefValueStore(
         managed_platform_pref_store_,
-        device_management_pref_store_,
+        managed_cloud_pref_store_,
         extension_pref_store_,
         command_line_pref_store_,
         user_pref_store_,
-        recommended_pref_store_,
+        recommended_platform_pref_store_,
+        recommended_cloud_pref_store_,
         default_pref_store_,
-        &pref_notifier_);
-
-    // Register prefs with the PrefValueStore.
-    pref_value_store_->RegisterPreferenceType(prefs::kApplicationLocale,
-                                              Value::TYPE_STRING);
-    pref_value_store_->RegisterPreferenceType(prefs::kCurrentThemeID,
-                                              Value::TYPE_STRING);
-    pref_value_store_->RegisterPreferenceType(
-        prefs::kDefaultSearchProviderName,
-        Value::TYPE_STRING);
-    pref_value_store_->RegisterPreferenceType(prefs::kDeleteCache,
-                                              Value::TYPE_BOOLEAN);
-    pref_value_store_->RegisterPreferenceType(prefs::kHomePage,
-                                              Value::TYPE_STRING);
-    pref_value_store_->RegisterPreferenceType(prefs::kStabilityLaunchCount,
-                                              Value::TYPE_INTEGER);
-    pref_value_store_->RegisterPreferenceType(prefs::kRecommendedPref,
-                                              Value::TYPE_BOOLEAN);
-    pref_value_store_->RegisterPreferenceType(prefs::kSampleDict,
-                                              Value::TYPE_DICTIONARY);
-    pref_value_store_->RegisterPreferenceType(prefs::kSampleList,
-                                              Value::TYPE_LIST);
-    pref_value_store_->RegisterPreferenceType(prefs::kDefaultPref,
-                                              Value::TYPE_INTEGER);
-    pref_value_store_->RegisterPreferenceType(prefs::kProxyMode,
-                                              Value::TYPE_INTEGER);
-  }
-
-  // Creates a new dictionary and stores some sample user preferences
-  // in it.
-  void CreateUserPrefs() {
-    user_pref_store_ = new TestingPrefStore;
-    user_pref_store_->SetBoolean(prefs::kDeleteCache,
-        user_pref::kDeleteCacheValue);
-    user_pref_store_->SetInteger(prefs::kStabilityLaunchCount,
-        user_pref::kStabilityLaunchCountValue);
-    user_pref_store_->SetString(prefs::kCurrentThemeID,
-        user_pref::kCurrentThemeIDValue);
-    user_pref_store_->SetString(prefs::kApplicationLocale,
-        user_pref::kApplicationLocaleValue);
-    user_pref_store_->SetString(prefs::kDefaultSearchProviderName,
-        user_pref::kSearchProviderNameValue);
-    user_pref_store_->SetString(prefs::kHomePage,
-        user_pref::kHomepageValue);
+        &pref_notifier_));
   }
 
   void CreateManagedPlatformPrefs() {
     managed_platform_pref_store_ = new TestingPrefStore;
-    managed_platform_pref_store_->SetString(prefs::kHomePage,
-        managed_platform_pref::kHomepageValue);
+    managed_platform_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        managed_platform_pref::kManagedPlatformValue);
   }
 
-  void CreateDeviceManagementPrefs() {
-    device_management_pref_store_ = new TestingPrefStore;
-    device_management_pref_store_->SetString(prefs::kDefaultSearchProviderName,
-        device_management_pref::kSearchProviderNameValue);
-    device_management_pref_store_->SetString(prefs::kHomePage,
-        device_management_pref::kHomepageValue);
+  void CreateManagedCloudPrefs() {
+    managed_cloud_pref_store_ = new TestingPrefStore;
+    managed_cloud_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        managed_cloud_pref::kManagedPlatformValue);
+    managed_cloud_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        managed_cloud_pref::kManagedCloudValue);
   }
 
   void CreateExtensionPrefs() {
     extension_pref_store_ = new TestingPrefStore;
-    extension_pref_store_->SetString(prefs::kCurrentThemeID,
-        extension_pref::kCurrentThemeIDValue);
-    extension_pref_store_->SetString(prefs::kHomePage,
-        extension_pref::kHomepageValue);
-    extension_pref_store_->SetString(prefs::kDefaultSearchProviderName,
-        extension_pref::kSearchProviderNameValue);
+    extension_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        extension_pref::kManagedPlatformValue);
+    extension_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        extension_pref::kManagedCloudValue);
+    extension_pref_store_->SetString(
+        prefs::kExtensionPref,
+        extension_pref::kExtensionValue);
   }
 
   void CreateCommandLinePrefs() {
     command_line_pref_store_ = new TestingPrefStore;
-    command_line_pref_store_->SetString(prefs::kCurrentThemeID,
-        command_line_pref::kCurrentThemeIDValue);
-    command_line_pref_store_->SetString(prefs::kApplicationLocale,
-        command_line_pref::kApplicationLocaleValue);
-    command_line_pref_store_->SetString(prefs::kHomePage,
-        command_line_pref::kHomepageValue);
-    command_line_pref_store_->SetString(prefs::kDefaultSearchProviderName,
-        command_line_pref::kSearchProviderNameValue);
+    command_line_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        command_line_pref::kManagedPlatformValue);
+    command_line_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        command_line_pref::kManagedCloudValue);
+    command_line_pref_store_->SetString(
+        prefs::kExtensionPref,
+        command_line_pref::kExtensionValue);
+    command_line_pref_store_->SetString(
+        prefs::kCommandLinePref,
+        command_line_pref::kCommandLineValue);
   }
 
-  void CreateRecommendedPrefs() {
-    recommended_pref_store_ = new TestingPrefStore;
-    recommended_pref_store_->SetInteger(prefs::kStabilityLaunchCount,
-        recommended_pref::kStabilityLaunchCountValue);
-    recommended_pref_store_->SetBoolean(prefs::kRecommendedPref,
-        recommended_pref::kRecommendedPrefValue);
+  void CreateUserPrefs() {
+    user_pref_store_ = new TestingPrefStore;
+    user_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        user_pref::kManagedPlatformValue);
+    user_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        user_pref::kManagedCloudValue);
+    user_pref_store_->SetString(
+        prefs::kCommandLinePref,
+        user_pref::kCommandLineValue);
+    user_pref_store_->SetString(
+        prefs::kExtensionPref,
+        user_pref::kExtensionValue);
+    user_pref_store_->SetString(
+        prefs::kUserPref,
+        user_pref::kUserValue);
+  }
+
+  void CreateRecommendedPlatformPrefs() {
+    recommended_platform_pref_store_ = new TestingPrefStore;
+    recommended_platform_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        recommended_platform_pref::kManagedPlatformValue);
+    recommended_platform_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        recommended_platform_pref::kManagedCloudValue);
+    recommended_platform_pref_store_->SetString(
+        prefs::kCommandLinePref,
+        recommended_platform_pref::kCommandLineValue);
+    recommended_platform_pref_store_->SetString(
+        prefs::kExtensionPref,
+        recommended_platform_pref::kExtensionValue);
+    recommended_platform_pref_store_->SetString(
+        prefs::kUserPref,
+        recommended_platform_pref::kUserValue);
+    recommended_platform_pref_store_->SetString(
+        prefs::kRecommendedPlatformPref,
+        recommended_platform_pref::kRecommendedPlatformValue);
+  }
+
+  void CreateRecommendedCloudPrefs() {
+    recommended_cloud_pref_store_ = new TestingPrefStore;
+    recommended_cloud_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        recommended_cloud_pref::kManagedPlatformValue);
+    recommended_cloud_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        recommended_cloud_pref::kManagedCloudValue);
+    recommended_cloud_pref_store_->SetString(
+        prefs::kCommandLinePref,
+        recommended_cloud_pref::kCommandLineValue);
+    recommended_cloud_pref_store_->SetString(
+        prefs::kExtensionPref,
+        recommended_cloud_pref::kExtensionValue);
+    recommended_cloud_pref_store_->SetString(
+        prefs::kUserPref,
+        recommended_cloud_pref::kUserValue);
+    recommended_cloud_pref_store_->SetString(
+        prefs::kRecommendedPlatformPref,
+        recommended_cloud_pref::kRecommendedPlatformValue);
+    recommended_cloud_pref_store_->SetString(
+        prefs::kRecommendedCloudPref,
+        recommended_cloud_pref::kRecommendedCloudValue);
   }
 
   void CreateDefaultPrefs() {
     default_pref_store_ = new TestingPrefStore;
-    default_pref_store_->SetInteger(prefs::kDefaultPref,
-                                    default_pref::kDefaultValue);
-  }
-
-  DictionaryValue* CreateSampleDictValue() {
-    DictionaryValue* sample_dict = new DictionaryValue();
-    sample_dict->SetBoolean("issample", true);
-    sample_dict->SetInteger("value", 4);
-    sample_dict->SetString("descr", "Sample Test Dictionary");
-    return sample_dict;
-  }
-
-  ListValue* CreateSampleListValue() {
-    ListValue* sample_list = new ListValue();
-    sample_list->Set(0, Value::CreateIntegerValue(0));
-    sample_list->Set(1, Value::CreateIntegerValue(1));
-    sample_list->Set(2, Value::CreateIntegerValue(2));
-    sample_list->Set(3, Value::CreateIntegerValue(3));
-    return sample_list;
+    default_pref_store_->SetString(
+        prefs::kManagedPlatformPref,
+        default_pref::kManagedPlatformValue);
+    default_pref_store_->SetString(
+        prefs::kManagedCloudPref,
+        default_pref::kManagedCloudValue);
+    default_pref_store_->SetString(
+        prefs::kCommandLinePref,
+        default_pref::kCommandLineValue);
+    default_pref_store_->SetString(
+        prefs::kExtensionPref,
+        default_pref::kExtensionValue);
+    default_pref_store_->SetString(
+        prefs::kUserPref,
+        default_pref::kUserValue);
+    default_pref_store_->SetString(
+        prefs::kRecommendedPlatformPref,
+        default_pref::kRecommendedPlatformValue);
+    default_pref_store_->SetString(
+        prefs::kRecommendedCloudPref,
+        default_pref::kRecommendedCloudValue);
+    default_pref_store_->SetString(
+        prefs::kDefaultPref,
+        default_pref::kDefaultValue);
   }
 
   MockPrefNotifier pref_notifier_;
-  scoped_refptr<PrefValueStore> pref_value_store_;
+  scoped_ptr<PrefValueStore> pref_value_store_;
 
-  // |PrefStore|s are owned by the |PrefValueStore|.
-  TestingPrefStore* managed_platform_pref_store_;
-  TestingPrefStore* device_management_pref_store_;
-  TestingPrefStore* extension_pref_store_;
-  TestingPrefStore* command_line_pref_store_;
-  TestingPrefStore* user_pref_store_;
-  TestingPrefStore* recommended_pref_store_;
-  TestingPrefStore* default_pref_store_;
+  scoped_refptr<TestingPrefStore> managed_platform_pref_store_;
+  scoped_refptr<TestingPrefStore> managed_cloud_pref_store_;
+  scoped_refptr<TestingPrefStore> extension_pref_store_;
+  scoped_refptr<TestingPrefStore> command_line_pref_store_;
+  scoped_refptr<TestingPrefStore> user_pref_store_;
+  scoped_refptr<TestingPrefStore> recommended_platform_pref_store_;
+  scoped_refptr<TestingPrefStore> recommended_cloud_pref_store_;
+  scoped_refptr<TestingPrefStore> default_pref_store_;
 };
 
 TEST_F(PrefValueStoreTest, GetValue) {
   Value* value;
 
-  // Test getting a managed platform value overwriting a user-defined and
-  // extension-defined value.
+  // The following tests read a value from the PrefService. The preferences are
+  // set in a way such that all lower-priority stores have a value and we can
+  // test whether overrides work correctly.
+
+  // Test getting a managed platform value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, &value));
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kManagedPlatformPref,
+                                          Value::TYPE_STRING, &value));
   std::string actual_str_value;
   EXPECT_TRUE(value->GetAsString(&actual_str_value));
-  EXPECT_EQ(managed_platform_pref::kHomepageValue, actual_str_value);
+  EXPECT_EQ(managed_platform_pref::kManagedPlatformValue, actual_str_value);
 
-  // Test getting a managed platform value overwriting a user-defined value.
+  // Test getting a managed cloud value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultSearchProviderName,
-                                          &value));
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kManagedCloudPref,
+                                          Value::TYPE_STRING, &value));
   EXPECT_TRUE(value->GetAsString(&actual_str_value));
-  EXPECT_EQ(device_management_pref::kSearchProviderNameValue,
-            actual_str_value);
+  EXPECT_EQ(managed_cloud_pref::kManagedCloudValue, actual_str_value);
 
-  // Test getting an extension value overwriting a user-defined and
-  // command-line-defined value.
+  // Test getting an extension value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kCurrentThemeID, &value));
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kExtensionPref,
+                                          Value::TYPE_STRING, &value));
   EXPECT_TRUE(value->GetAsString(&actual_str_value));
-  EXPECT_EQ(extension_pref::kCurrentThemeIDValue, actual_str_value);
+  EXPECT_EQ(extension_pref::kExtensionValue, actual_str_value);
 
-  // Test getting a command-line value overwriting a user-defined value.
+  // Test getting a command-line value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kApplicationLocale, &value));
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kCommandLinePref,
+                                          Value::TYPE_STRING, &value));
   EXPECT_TRUE(value->GetAsString(&actual_str_value));
-  EXPECT_EQ(command_line_pref::kApplicationLocaleValue, actual_str_value);
+  EXPECT_EQ(command_line_pref::kCommandLineValue, actual_str_value);
 
   // Test getting a user-set value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDeleteCache, &value));
-  bool actual_bool_value = false;
-  EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
-  EXPECT_EQ(user_pref::kDeleteCacheValue, actual_bool_value);
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kUserPref,
+                                          Value::TYPE_STRING, &value));
+  EXPECT_TRUE(value->GetAsString(&actual_str_value));
+  EXPECT_EQ(user_pref::kUserValue, actual_str_value);
 
   // Test getting a user set value overwriting a recommended value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kStabilityLaunchCount,
-                                          &value));
-  int actual_int_value = -1;
-  EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
-  EXPECT_EQ(user_pref::kStabilityLaunchCountValue, actual_int_value);
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kRecommendedPlatformPref,
+                                          Value::TYPE_STRING, &value));
+  EXPECT_TRUE(value->GetAsString(&actual_str_value));
+  EXPECT_EQ(recommended_platform_pref::kRecommendedPlatformValue,
+            actual_str_value);
 
   // Test getting a recommended value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kRecommendedPref, &value));
-  actual_bool_value = false;
-  EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
-  EXPECT_EQ(recommended_pref::kRecommendedPrefValue, actual_bool_value);
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kRecommendedCloudPref,
+                                          Value::TYPE_STRING, &value));
+  EXPECT_TRUE(value->GetAsString(&actual_str_value));
+  EXPECT_EQ(recommended_cloud_pref::kRecommendedCloudValue, actual_str_value);
 
   // Test getting a default value.
   value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultPref, &value));
-  actual_int_value = -1;
-  EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
-  EXPECT_EQ(default_pref::kDefaultValue, actual_int_value);
+  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultPref,
+                                          Value::TYPE_STRING, &value));
+  EXPECT_TRUE(value->GetAsString(&actual_str_value));
+  EXPECT_EQ(default_pref::kDefaultValue, actual_str_value);
 
   // Test getting a preference value that the |PrefValueStore|
   // does not contain.
   FundamentalValue tmp_dummy_value(true);
-  Value* v_null = &tmp_dummy_value;
-  ASSERT_FALSE(pref_value_store_->GetValue(prefs::kMissingPref, &v_null));
-  ASSERT_TRUE(v_null == NULL);
-}
-
-// Make sure that if a preference changes type, so the wrong type is stored in
-// the user pref file, it uses the correct fallback value instead.
-TEST_F(PrefValueStoreTest, GetValueChangedType) {
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(_)).Times(AnyNumber());
-
-  // Check falling back to a recommended value.
-  user_pref_store_->SetString(prefs::kStabilityLaunchCount,
-                                       "not an integer");
-  Value* value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kStabilityLaunchCount,
-                                          &value));
-  ASSERT_TRUE(value != NULL);
-  ASSERT_EQ(Value::TYPE_INTEGER, value->GetType());
-  int actual_int_value = -1;
-  EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
-  EXPECT_EQ(recommended_pref::kStabilityLaunchCountValue, actual_int_value);
-
-  // Check falling back multiple times, to a default string.
-  default_pref_store_->SetString(prefs::kHomePage,
-                                 default_pref::kHomepageValue);
-  managed_platform_pref_store_->SetInteger(prefs::kHomePage, 1);
-  device_management_pref_store_->SetInteger(prefs::kHomePage, 1);
-  extension_pref_store_->SetInteger(prefs::kHomePage, 1);
-  command_line_pref_store_->SetInteger(prefs::kHomePage, 1);
-  user_pref_store_->SetInteger(prefs::kHomePage, 1);
-  recommended_pref_store_->SetInteger(prefs::kHomePage, 1);
-
-  value = NULL;
-  ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, &value));
-  ASSERT_TRUE(value != NULL);
-  ASSERT_EQ(Value::TYPE_STRING, value->GetType());
-  std::string actual_str_value;
-  EXPECT_TRUE(value->GetAsString(&actual_str_value));
-  EXPECT_EQ(default_pref::kHomepageValue, actual_str_value);
-}
-
-TEST_F(PrefValueStoreTest, HasPrefPath) {
-  // Managed Platform preference
-  EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
-  // Device management preference
-  EXPECT_TRUE(pref_value_store_->HasPrefPath(
-      prefs::kDefaultSearchProviderName));
-  // Extension preference
-  EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
-  // User preference
-  EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kDeleteCache));
-  // Recommended preference
-  EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
-  // Default preference
-  EXPECT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
-  // Unknown preference
-  EXPECT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
+  value = &tmp_dummy_value;
+  ASSERT_FALSE(pref_value_store_->GetValue(prefs::kMissingPref,
+                                           Value::TYPE_STRING, &value));
+  ASSERT_TRUE(value == NULL);
 }
 
 TEST_F(PrefValueStoreTest, PrefChanges) {
-  // Setup.
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(_)).Times(AnyNumber());
-  const char managed_platform_pref_path[] = "managed_platform_pref";
-  pref_value_store_->RegisterPreferenceType(managed_platform_pref_path,
-                                            Value::TYPE_STRING);
-  managed_platform_pref_store_->SetString(managed_platform_pref_path,
-                                                   "managed value");
-  const char user_pref_path[] = "user_pref";
-  pref_value_store_->RegisterPreferenceType(user_pref_path, Value::TYPE_STRING);
-  user_pref_store_->SetString(user_pref_path, "user value");
-  const char default_pref_path[] = "default_pref";
-  pref_value_store_->RegisterPreferenceType(default_pref_path,
-                                            Value::TYPE_STRING);
-  default_pref_store_->SetString(default_pref_path, "default value");
-  Mock::VerifyAndClearExpectations(&pref_notifier_);
-
   // Check pref controlled by highest-priority store.
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(managed_platform_pref_path));
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kManagedPlatformPref));
   managed_platform_pref_store_->NotifyPrefValueChanged(
-      managed_platform_pref_path);
+      prefs::kManagedPlatformPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
   EXPECT_CALL(pref_notifier_, OnPreferenceChanged(_)).Times(0);
-  user_pref_store_->NotifyPrefValueChanged(managed_platform_pref_path);
+  managed_cloud_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
+  extension_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
+  command_line_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
+  user_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
+  recommended_platform_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
+  recommended_cloud_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
+  default_pref_store_->NotifyPrefValueChanged(
+      prefs::kManagedPlatformPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
   // Check pref controlled by user store.
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(user_pref_path));
-  managed_platform_pref_store_->NotifyPrefValueChanged(user_pref_path);
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kUserPref));
+  managed_platform_pref_store_->NotifyPrefValueChanged(prefs::kUserPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(user_pref_path));
-  user_pref_store_->NotifyPrefValueChanged(user_pref_path);
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kUserPref));
+  managed_cloud_pref_store_->NotifyPrefValueChanged(prefs::kUserPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kUserPref));
+  extension_pref_store_->NotifyPrefValueChanged(prefs::kUserPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kUserPref));
+  command_line_pref_store_->NotifyPrefValueChanged(prefs::kUserPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kUserPref));
+  user_pref_store_->NotifyPrefValueChanged(prefs::kUserPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
   EXPECT_CALL(pref_notifier_, OnPreferenceChanged(_)).Times(0);
-  default_pref_store_->NotifyPrefValueChanged(user_pref_path);
+  recommended_platform_pref_store_->NotifyPrefValueChanged(
+      prefs::kUserPref);
+  recommended_cloud_pref_store_->NotifyPrefValueChanged(
+      prefs::kUserPref);
+  default_pref_store_->NotifyPrefValueChanged(
+      prefs::kUserPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
   // Check pref controlled by default-pref store.
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(default_pref_path));
-  user_pref_store_->NotifyPrefValueChanged(default_pref_path);
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  managed_platform_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
-  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(default_pref_path));
-  default_pref_store_->NotifyPrefValueChanged(default_pref_path);
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  managed_cloud_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  extension_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  command_line_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  user_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  recommended_platform_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  recommended_cloud_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
+  Mock::VerifyAndClearExpectations(&pref_notifier_);
+
+  EXPECT_CALL(pref_notifier_, OnPreferenceChanged(prefs::kDefaultPref));
+  default_pref_store_->NotifyPrefValueChanged(prefs::kDefaultPref);
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 }
 
 TEST_F(PrefValueStoreTest, OnInitializationCompleted) {
   EXPECT_CALL(pref_notifier_, OnInitializationCompleted()).Times(0);
   managed_platform_pref_store_->SetInitializationCompleted();
-  device_management_pref_store_->SetInitializationCompleted();
+  managed_cloud_pref_store_->SetInitializationCompleted();
   extension_pref_store_->SetInitializationCompleted();
   command_line_pref_store_->SetInitializationCompleted();
-  recommended_pref_store_->SetInitializationCompleted();
+  recommended_platform_pref_store_->SetInitializationCompleted();
+  recommended_cloud_pref_store_->SetInitializationCompleted();
   default_pref_store_->SetInitializationCompleted();
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
@@ -423,198 +467,149 @@
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 }
 
-TEST_F(PrefValueStoreTest, PrefValueInManagedPlatformStore) {
-  // Test a managed platform preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
-  EXPECT_TRUE(pref_value_store_->PrefValueInManagedPlatformStore(
-      prefs::kHomePage));
-
-  // Test a device management preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(
-      prefs::kDefaultSearchProviderName));
-  EXPECT_TRUE(pref_value_store_->PrefValueInDeviceManagementStore(
-      prefs::kDefaultSearchProviderName));
-
-  // Test an extension preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
-  EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
-      prefs::kCurrentThemeID));
-
-  // Test a command-line preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
-  EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
-      prefs::kApplicationLocale));
-
-  // Test a user preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
-  EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
-      prefs::kStabilityLaunchCount));
-
-  // Test a preference from the recommended pref store.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
-      prefs::kRecommendedPref));
-
-  // Test a preference from the default pref store.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
+TEST_F(PrefValueStoreTest, PrefValueInManagedStore) {
+  EXPECT_TRUE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kManagedPlatformPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kManagedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kExtensionPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kCommandLinePref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kUserPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kRecommendedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
+      prefs::kRecommendedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
       prefs::kDefaultPref));
-
-  // Test a preference for which the PrefValueStore does not contain a value.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
+  EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(
       prefs::kMissingPref));
 }
 
 TEST_F(PrefValueStoreTest, PrefValueInExtensionStore) {
-  // Test a managed platform preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
-  EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(prefs::kHomePage));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kHomePage));
-
-  // Test a device management preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(
-      prefs::kDefaultSearchProviderName));
   EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(
-      prefs::kDefaultSearchProviderName));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kDefaultSearchProviderName));
-
-  // Test an extension preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
+      prefs::kManagedPlatformPref));
   EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(
-      prefs::kCurrentThemeID));
-  EXPECT_TRUE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kCurrentThemeID));
-
-  // Test a command-line preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
+      prefs::kManagedCloudPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(
+      prefs::kExtensionPref));
   EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
-      prefs::kApplicationLocale));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kApplicationLocale));
-
-  // Test a user preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
+      prefs::kCommandLinePref));
   EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
-      prefs::kStabilityLaunchCount));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kStabilityLaunchCount));
-
-  // Test a preference from the recommended pref store.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
+      prefs::kUserPref));
   EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
-      prefs::kRecommendedPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kRecommendedPref));
-
-  // Test a preference from the default pref store.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
+      prefs::kRecommendedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
+      prefs::kRecommendedCloudPref));
   EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
       prefs::kDefaultPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kDefaultPref));
-
-  // Test a preference for which the PrefValueStore does not contain a value.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
   EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
       prefs::kMissingPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
-      prefs::kMissingPref));
 }
 
 TEST_F(PrefValueStoreTest, PrefValueInUserStore) {
-  // Test a managed platform preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
-  EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(prefs::kHomePage));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kHomePage));
-
-  // Test a device management preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(
-      prefs::kDefaultSearchProviderName));
   EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
-      prefs::kDefaultSearchProviderName));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
-      prefs::kDefaultSearchProviderName));
-
-  // Test an extension preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
+      prefs::kManagedPlatformPref));
   EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
-      prefs::kCurrentThemeID));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
-      prefs::kCurrentThemeID));
-
-  // Test a command-line preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
+      prefs::kManagedCloudPref));
   EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
-      prefs::kApplicationLocale));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
-      prefs::kApplicationLocale));
-
-  // Test a user preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
+      prefs::kExtensionPref));
   EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
-      prefs::kStabilityLaunchCount));
-  EXPECT_TRUE(pref_value_store_->PrefValueFromUserStore(
-      prefs::kStabilityLaunchCount));
-
-  // Test a preference from the recommended pref store.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
+      prefs::kCommandLinePref));
+  EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
+      prefs::kUserPref));
   EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(
-      prefs::kRecommendedPref));
+      prefs::kRecommendedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(
+      prefs::kRecommendedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(
+      prefs::kDefaultPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(
+      prefs::kMissingPref));
+}
+
+TEST_F(PrefValueStoreTest, PrefValueFromExtensionStore) {
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kManagedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kManagedCloudPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kExtensionPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kCommandLinePref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kUserPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kRecommendedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kRecommendedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kDefaultPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
+      prefs::kMissingPref));
+}
+
+TEST_F(PrefValueStoreTest, PrefValueFromUserStore) {
   EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
-      prefs::kRecommendedPref));
-
-  // Test a preference from the default pref store.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(prefs::kDefaultPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kDefaultPref));
-
-  // Test a preference for which the PrefValueStore does not contain a value.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(prefs::kMissingPref));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kMissingPref));
+      prefs::kManagedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kManagedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kExtensionPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kCommandLinePref));
+  EXPECT_TRUE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kUserPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kRecommendedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kRecommendedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kDefaultPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
+      prefs::kMissingPref));
 }
 
 TEST_F(PrefValueStoreTest, PrefValueFromDefaultStore) {
-  // Test a managed platform preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
-  EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(prefs::kHomePage));
-
-  // Test a device management preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(
-      prefs::kDefaultSearchProviderName));
   EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
-      prefs::kDefaultSearchProviderName));
-
-  // Test an extension preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
+      prefs::kManagedPlatformPref));
   EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
-      prefs::kCurrentThemeID));
-
-  // Test a command-line preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
+      prefs::kManagedCloudPref));
   EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
-      prefs::kApplicationLocale));
-
-  // Test a user preference.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
+      prefs::kExtensionPref));
   EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
-      prefs::kStabilityLaunchCount));
-
-  // Test a preference from the recommended pref store.
-  ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
+      prefs::kCommandLinePref));
   EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
-      prefs::kRecommendedPref));
+      prefs::kUserPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
+      prefs::kRecommendedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
+      prefs::kRecommendedCloudPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueFromDefaultStore(
+      prefs::kDefaultPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
+      prefs::kMissingPref));
+}
 
-  // Test a preference from the default pref store.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
-  EXPECT_TRUE(
-      pref_value_store_->PrefValueFromDefaultStore(prefs::kDefaultPref));
-
-  // Test a preference for which the PrefValueStore does not contain a value.
-  ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
-  EXPECT_FALSE(
-      pref_value_store_->PrefValueFromDefaultStore(prefs::kMissingPref));
+TEST_F(PrefValueStoreTest, PrefValueUserModifiable) {
+  EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kManagedPlatformPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kManagedCloudPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kExtensionPref));
+  EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kCommandLinePref));
+  EXPECT_TRUE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kUserPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kRecommendedPlatformPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kRecommendedCloudPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kDefaultPref));
+  EXPECT_TRUE(pref_value_store_->PrefValueUserModifiable(
+      prefs::kMissingPref));
 }
diff --git a/chrome/browser/prefs/proxy_config_dictionary.cc b/chrome/browser/prefs/proxy_config_dictionary.cc
new file mode 100644
index 0000000..0c063cd
--- /dev/null
+++ b/chrome/browser/prefs/proxy_config_dictionary.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/prefs/proxy_config_dictionary.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/values.h"
+
+namespace {
+
+// Integer to specify the type of proxy settings.
+// See ProxyPrefs for possible values and interactions with the other proxy
+// preferences.
+const char kProxyMode[] = "mode";
+// String specifying the proxy server. For a specification of the expected
+// syntax see net::ProxyConfig::ProxyRules::ParseFromString().
+const char kProxyServer[] = "server";
+// URL to the proxy .pac file.
+const char kProxyPacUrl[] = "pac_url";
+// String containing proxy bypass rules. For a specification of the
+// expected syntax see net::ProxyBypassRules::ParseFromString().
+const char kProxyBypassList[] = "bypass_list";
+
+}  // namespace
+
+ProxyConfigDictionary::ProxyConfigDictionary(const DictionaryValue* dict)
+    : dict_(dict->DeepCopy()) {
+}
+
+ProxyConfigDictionary::~ProxyConfigDictionary() {}
+
+bool ProxyConfigDictionary::GetMode(ProxyPrefs::ProxyMode* out) const {
+  std::string mode_str;
+  return dict_->GetString(kProxyMode, &mode_str)
+      && StringToProxyMode(mode_str, out);
+}
+
+bool ProxyConfigDictionary::GetPacUrl(std::string* out) const {
+  return dict_->GetString(kProxyPacUrl, out);
+}
+
+bool ProxyConfigDictionary::GetProxyServer(std::string* out) const {
+  return dict_->GetString(kProxyServer, out);
+}
+
+bool ProxyConfigDictionary::GetBypassList(std::string* out) const {
+  return dict_->GetString(kProxyBypassList, out);
+}
+
+bool ProxyConfigDictionary::HasBypassList() const {
+  return dict_->HasKey(kProxyBypassList);
+}
+
+// static
+DictionaryValue* ProxyConfigDictionary::CreateDirect() {
+  return CreateDictionary(ProxyPrefs::MODE_DIRECT, "", "", "");
+}
+
+// static
+DictionaryValue* ProxyConfigDictionary::CreateAutoDetect() {
+  return CreateDictionary(ProxyPrefs::MODE_AUTO_DETECT, "", "", "");
+}
+
+// static
+DictionaryValue* ProxyConfigDictionary::CreatePacScript(
+    const std::string& pac_url) {
+  return CreateDictionary(ProxyPrefs::MODE_PAC_SCRIPT, pac_url, "", "");
+}
+
+// static
+DictionaryValue* ProxyConfigDictionary::CreateFixedServers(
+    const std::string& proxy_server,
+    const std::string& bypass_list) {
+  if (!proxy_server.empty()) {
+    return CreateDictionary(
+        ProxyPrefs::MODE_FIXED_SERVERS, "", proxy_server, bypass_list);
+  } else {
+    return CreateDirect();
+  }
+}
+
+// static
+DictionaryValue* ProxyConfigDictionary::CreateSystem() {
+  return CreateDictionary(ProxyPrefs::MODE_SYSTEM, "", "", "");
+}
+
+// static
+DictionaryValue* ProxyConfigDictionary::CreateDictionary(
+    ProxyPrefs::ProxyMode mode,
+    const std::string& pac_url,
+    const std::string& proxy_server,
+    const std::string& bypass_list) {
+  DictionaryValue* dict = new DictionaryValue();
+  dict->SetString(kProxyMode, ProxyModeToString(mode));
+  if (!pac_url.empty())
+    dict->SetString(kProxyPacUrl, pac_url);
+  if (!proxy_server.empty())
+    dict->SetString(kProxyServer, proxy_server);
+  if (!bypass_list.empty())
+    dict->SetString(kProxyBypassList, bypass_list);
+  return dict;
+}
diff --git a/chrome/browser/prefs/proxy_config_dictionary.h b/chrome/browser/prefs/proxy_config_dictionary.h
new file mode 100644
index 0000000..7af2e27
--- /dev/null
+++ b/chrome/browser/prefs/proxy_config_dictionary.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_PREFS_PROXY_CONFIG_DICTIONARY_H_
+#define CHROME_BROWSER_PREFS_PROXY_CONFIG_DICTIONARY_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/prefs/proxy_prefs.h"
+
+class DictionaryValue;
+
+// Factory and wrapper for proxy config dictionaries that are stored
+// in the user preferences. The dictionary has the following structure:
+// {
+//   mode: string,
+//   server: string,
+//   pac_url: string,
+//   bypass_list: string
+// }
+// See proxy_config_dictionary.cc for the structure of the respective strings.
+class ProxyConfigDictionary {
+ public:
+  // Creates a deep copy of |dict| and leaves ownership to caller.
+  explicit ProxyConfigDictionary(const DictionaryValue* dict);
+  ~ProxyConfigDictionary();
+
+  bool GetMode(ProxyPrefs::ProxyMode* out) const;
+  bool GetPacUrl(std::string* out) const;
+  bool GetProxyServer(std::string* out) const;
+  bool GetBypassList(std::string* out) const;
+  bool HasBypassList() const;
+
+  static DictionaryValue* CreateDirect();
+  static DictionaryValue* CreateAutoDetect();
+  static DictionaryValue* CreatePacScript(const std::string& pac_url);
+  static DictionaryValue* CreateFixedServers(
+      const std::string& proxy_server,
+      const std::string& bypass_list);
+  static DictionaryValue* CreateSystem();
+ private:
+  static DictionaryValue* CreateDictionary(ProxyPrefs::ProxyMode mode,
+                                           const std::string& pac_url,
+                                           const std::string& proxy_server,
+                                           const std::string& bypass_list);
+
+  scoped_ptr<DictionaryValue> dict_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProxyConfigDictionary);
+};
+
+#endif  // CHROME_BROWSER_PREFS_PROXY_CONFIG_DICTIONARY_H_
diff --git a/chrome/browser/prefs/proxy_config_dictionary_unittest.cc b/chrome/browser/prefs/proxy_config_dictionary_unittest.cc
new file mode 100644
index 0000000..07c6743
--- /dev/null
+++ b/chrome/browser/prefs/proxy_config_dictionary_unittest.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+struct ProxyConfigHolder {
+  ProxyPrefs::ProxyMode mode;
+  std::string pac_url;
+  std::string proxy_server;
+  std::string bypass_list;
+};
+
+TEST(ProxyConfigDictionaryTest, CreateDirect) {
+  scoped_ptr<DictionaryValue> dict_value(ProxyConfigDictionary::CreateDirect());
+  ProxyConfigDictionary dict(dict_value.get());
+  ProxyConfigHolder h;
+
+  ASSERT_TRUE(dict.GetMode(&h.mode));
+  EXPECT_EQ(ProxyPrefs::MODE_DIRECT, h.mode);
+  ASSERT_FALSE(dict.GetPacUrl(&h.bypass_list));
+  ASSERT_FALSE(dict.GetProxyServer(&h.proxy_server));
+  ASSERT_FALSE(dict.GetBypassList(&h.bypass_list));
+}
+
+TEST(ProxyConfigDictionaryTest, CreateAutoDetect) {
+  scoped_ptr<DictionaryValue> dict_value(
+      ProxyConfigDictionary::CreateAutoDetect());
+  ProxyConfigDictionary dict(dict_value.get());
+  ProxyConfigHolder h;
+
+  ASSERT_TRUE(dict.GetMode(&h.mode));
+  EXPECT_EQ(ProxyPrefs::MODE_AUTO_DETECT, h.mode);
+  ASSERT_FALSE(dict.GetPacUrl(&h.bypass_list));
+  ASSERT_FALSE(dict.GetProxyServer(&h.proxy_server));
+  ASSERT_FALSE(dict.GetBypassList(&h.bypass_list));
+}
+
+TEST(ProxyConfigDictionaryTest, CreatePacScript) {
+  scoped_ptr<DictionaryValue> dict_value(
+      ProxyConfigDictionary::CreatePacScript("pac"));
+  ProxyConfigDictionary dict(dict_value.get());
+  ProxyConfigHolder h;
+
+  ASSERT_TRUE(dict.GetMode(&h.mode));
+  EXPECT_EQ(ProxyPrefs::MODE_PAC_SCRIPT, h.mode);
+  ASSERT_TRUE(dict.GetPacUrl(&h.bypass_list));
+  EXPECT_EQ("pac", h.bypass_list);
+  ASSERT_FALSE(dict.GetProxyServer(&h.proxy_server));
+  ASSERT_FALSE(dict.GetBypassList(&h.bypass_list));
+}
+
+TEST(ProxyConfigDictionaryTest, CreateFixedServers) {
+  scoped_ptr<DictionaryValue> dict_value(
+      ProxyConfigDictionary::CreateFixedServers("http://1.2.3.4",
+                                                "http://foo"));
+  ProxyConfigDictionary dict(dict_value.get());
+  ProxyConfigHolder h;
+
+  ASSERT_TRUE(dict.GetMode(&h.mode));
+  EXPECT_EQ(ProxyPrefs::MODE_FIXED_SERVERS, h.mode);
+  ASSERT_FALSE(dict.GetPacUrl(&h.bypass_list));
+  ASSERT_TRUE(dict.GetProxyServer(&h.proxy_server));
+  EXPECT_EQ("http://1.2.3.4", h.proxy_server);
+  ASSERT_TRUE(dict.GetBypassList(&h.bypass_list));
+  EXPECT_EQ("http://foo", h.bypass_list);
+}
+
+TEST(ProxyConfigDictionaryTest, CreateSystem) {
+  scoped_ptr<DictionaryValue> dict_value(ProxyConfigDictionary::CreateSystem());
+  ProxyConfigDictionary dict(dict_value.get());
+  ProxyConfigHolder h;
+
+  ASSERT_TRUE(dict.GetMode(&h.mode));
+  EXPECT_EQ(ProxyPrefs::MODE_SYSTEM, h.mode);
+  ASSERT_FALSE(dict.GetPacUrl(&h.bypass_list));
+  ASSERT_FALSE(dict.GetProxyServer(&h.proxy_server));
+  ASSERT_FALSE(dict.GetBypassList(&h.bypass_list));
+}
diff --git a/chrome/browser/prefs/proxy_prefs.cc b/chrome/browser/prefs/proxy_prefs.cc
index 7eb504c..4d7b550 100644
--- a/chrome/browser/prefs/proxy_prefs.cc
+++ b/chrome/browser/prefs/proxy_prefs.cc
@@ -7,15 +7,25 @@
 #include "base/basictypes.h"
 #include "base/logging.h"
 
+namespace ProxyPrefs {
+
+const char kDirectProxyModeName[] = "direct";
+const char kAutoDetectProxyModeName[] = "auto_detect";
+const char kPacScriptProxyModeName[] = "pac_script";
+const char kFixedServersProxyModeName[] = "fixed_servers";
+const char kSystemProxyModeName[] = "system";
+
+}
+
 namespace {
 
 // These names are exposed to the proxy extension API. They must be in sync
 // with the constants of ProxyPrefs.
-const char* kProxyModeNames[] = { "direct",
-                                  "auto_detect",
-                                  "pac_script",
-                                  "fixed_servers",
-                                  "system" };
+const char* kProxyModeNames[] = { ProxyPrefs::kDirectProxyModeName,
+                                  ProxyPrefs::kAutoDetectProxyModeName,
+                                  ProxyPrefs::kPacScriptProxyModeName,
+                                  ProxyPrefs::kFixedServersProxyModeName,
+                                  ProxyPrefs::kSystemProxyModeName };
 
 }  // namespace
 
@@ -42,4 +52,8 @@
   return false;
 }
 
+const char* ProxyModeToString(ProxyMode mode) {
+  return kProxyModeNames[mode];
+}
+
 }  // namespace
diff --git a/chrome/browser/prefs/proxy_prefs.h b/chrome/browser/prefs/proxy_prefs.h
index bbeb44d..46be759 100644
--- a/chrome/browser/prefs/proxy_prefs.h
+++ b/chrome/browser/prefs/proxy_prefs.h
@@ -36,9 +36,19 @@
   kModeCount
 };
 
+// Constants for string values used to specify the proxy mode through externally
+// visible APIs, e.g. through policy or the proxy extension API.
+extern const char kDirectProxyModeName[];
+extern const char kAutoDetectProxyModeName[];
+extern const char kPacScriptProxyModeName[];
+extern const char kFixedServersProxyModeName[];
+extern const char kSystemProxyModeName[];
+
 bool IntToProxyMode(int in_value, ProxyMode* out_value);
 bool StringToProxyMode(const std::string& in_value,
                        ProxyMode* out_value);
+// Ownership of the return value is NOT passed to the caller.
+const char* ProxyModeToString(ProxyMode mode);
 
 }  // namespace ProxyPrefs
 
diff --git a/chrome/browser/prefs/proxy_prefs_unittest.cc b/chrome/browser/prefs/proxy_prefs_unittest.cc
index 72aa0f1..63b8ea3 100644
--- a/chrome/browser/prefs/proxy_prefs_unittest.cc
+++ b/chrome/browser/prefs/proxy_prefs_unittest.cc
@@ -1,12 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <string>
 
-#include "base/logging.h"
 #include "base/values.h"
-#include "base/version.h"
 #include "chrome/browser/prefs/proxy_prefs.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/prefs/testing_pref_store.cc b/chrome/browser/prefs/testing_pref_store.cc
index 39c20f2..89394bd 100644
--- a/chrome/browser/prefs/testing_pref_store.cc
+++ b/chrome/browser/prefs/testing_pref_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,9 @@
 TestingPrefStore::TestingPrefStore()
     : read_only_(true),
       prefs_written_(false),
-      init_complete_(false) { }
+      init_complete_(false) {}
+
+TestingPrefStore::~TestingPrefStore() {}
 
 PrefStore::ReadResult TestingPrefStore::GetValue(const std::string& key,
                                                  Value** value) const {
@@ -24,6 +26,10 @@
   observers_.RemoveObserver(observer);
 }
 
+bool TestingPrefStore::IsInitializationComplete() const {
+  return init_complete_;
+}
+
 void TestingPrefStore::SetValue(const std::string& key, Value* value) {
   if (prefs_.SetValue(key, value))
     NotifyPrefValueChanged(key);
@@ -38,6 +44,10 @@
     NotifyPrefValueChanged(key);
 }
 
+bool TestingPrefStore::ReadOnly() const {
+  return read_only_;
+}
+
 PersistentPrefStore::PrefReadError TestingPrefStore::ReadPrefs() {
   prefs_.Clear();
   return PersistentPrefStore::PREF_READ_ERROR_NONE;
@@ -98,3 +108,15 @@
 
   return stored_value->GetAsBoolean(value);
 }
+
+void TestingPrefStore::set_read_only(bool read_only) {
+  read_only_ = read_only;
+}
+
+void TestingPrefStore::set_prefs_written(bool status) {
+  prefs_written_ = status;
+}
+
+bool TestingPrefStore::get_prefs_written() {
+  return prefs_written_;
+}
diff --git a/chrome/browser/prefs/testing_pref_store.h b/chrome/browser/prefs/testing_pref_store.h
index 555ee69..5502ad2 100644
--- a/chrome/browser/prefs/testing_pref_store.h
+++ b/chrome/browser/prefs/testing_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -20,19 +20,19 @@
 class TestingPrefStore : public PersistentPrefStore {
  public:
   TestingPrefStore();
-  virtual ~TestingPrefStore() {}
+  virtual ~TestingPrefStore();
 
   // Overriden from PrefStore.
   virtual ReadResult GetValue(const std::string& key, Value** result) const;
   virtual void AddObserver(PrefStore::Observer* observer);
   virtual void RemoveObserver(PrefStore::Observer* observer);
-  virtual bool IsInitializationComplete() const { return init_complete_; }
+  virtual bool IsInitializationComplete() const;
 
   // PersistentPrefStore overrides:
   virtual void SetValue(const std::string& key, Value* value);
   virtual void SetValueSilently(const std::string& key, Value* value);
   virtual void RemoveValue(const std::string& key);
-  virtual bool ReadOnly() const { return read_only_; }
+  virtual bool ReadOnly() const;
   virtual PersistentPrefStore::PrefReadError ReadPrefs();
   virtual bool WritePrefs();
   virtual void ScheduleWritePrefs() {}
@@ -55,9 +55,9 @@
 
   // Getter and Setter methods for setting and getting the state of the
   // |TestingPrefStore|.
-  virtual void set_read_only(bool read_only) { read_only_ = read_only; }
-  virtual void set_prefs_written(bool status) { prefs_written_ = status; }
-  virtual bool get_prefs_written() { return prefs_written_; }
+  virtual void set_read_only(bool read_only);
+  virtual void set_prefs_written(bool status);
+  virtual bool get_prefs_written();
 
  private:
   // Stores the preference values.
diff --git a/chrome/browser/prefs/value_map_pref_store.cc b/chrome/browser/prefs/value_map_pref_store.cc
index 705c958..58c4016 100644
--- a/chrome/browser/prefs/value_map_pref_store.cc
+++ b/chrome/browser/prefs/value_map_pref_store.cc
@@ -39,3 +39,19 @@
 void ValueMapPrefStore::NotifyInitializationCompleted() {
   FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted());
 }
+
+ValueMapPrefStore::iterator ValueMapPrefStore::begin() {
+  return prefs_.begin();
+}
+
+ValueMapPrefStore::iterator ValueMapPrefStore::end() {
+  return prefs_.end();
+}
+
+ValueMapPrefStore::const_iterator ValueMapPrefStore::begin() const {
+  return prefs_.begin();
+}
+
+ValueMapPrefStore::const_iterator ValueMapPrefStore::end() const {
+  return prefs_.end();
+}
diff --git a/chrome/browser/prefs/value_map_pref_store.h b/chrome/browser/prefs/value_map_pref_store.h
index 20bf290..a8b66c4 100644
--- a/chrome/browser/prefs/value_map_pref_store.h
+++ b/chrome/browser/prefs/value_map_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 #define CHROME_BROWSER_PREFS_VALUE_MAP_PREF_STORE_H_
 #pragma once
 
-#include <map>
-
 #include "base/basictypes.h"
 #include "base/observer_list.h"
 #include "chrome/browser/prefs/pref_value_map.h"
@@ -17,6 +15,9 @@
 // storing the preference values.
 class ValueMapPrefStore : public PrefStore {
  public:
+  typedef std::map<std::string, Value*>::iterator iterator;
+  typedef std::map<std::string, Value*>::const_iterator const_iterator;
+
   ValueMapPrefStore();
   virtual ~ValueMapPrefStore();
 
@@ -25,6 +26,11 @@
   virtual void AddObserver(PrefStore::Observer* observer);
   virtual void RemoveObserver(PrefStore::Observer* observer);
 
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
  protected:
   // Store a |value| for |key| in the store. Also generates an notification if
   // the value changed. Assumes ownership of |value|, which must be non-NULL.
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
new file mode 100644
index 0000000..c31817e
--- /dev/null
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -0,0 +1,252 @@
+// Copyright (c) 2011 The Chromium 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/command_line.h"
+#include "base/path_service.h"
+#include "chrome/browser/prerender/prerender_contents.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "net/url_request/url_request_context.h"
+
+// Prerender tests work as follows:
+//
+// A page with a prefetch link to the test page is loaded.  Once prerendered,
+// its Javascript function DidPrerenderPass() is called, which returns true if
+// the page behaves as expected when prerendered.
+//
+// The prerendered page is then displayed on a tab.  The Javascript function
+// DidDisplayPass() is called, and returns true if the page behaved as it
+// should while being displayed.
+
+namespace {
+
+// PrerenderContents that stops the UI message loop on DidStopLoading().
+class TestPrerenderContents : public PrerenderContents {
+ public:
+  TestPrerenderContents(
+      PrerenderManager* prerender_manager, Profile* profile, const GURL& url,
+      const std::vector<GURL>& alias_urls,
+      PrerenderContents::FinalStatus expected_final_status)
+      : PrerenderContents(prerender_manager, profile, url, alias_urls),
+        did_finish_loading_(false),
+        expected_final_status_(expected_final_status) {
+  }
+
+  virtual ~TestPrerenderContents() {
+    EXPECT_EQ(expected_final_status_, final_status());
+    // In the event we are destroyed, say if the prerender was canceled, quit
+    // the UI message loop.
+    if (!did_finish_loading_)
+      MessageLoopForUI::current()->Quit();
+  }
+
+  virtual void DidStopLoading() {
+    PrerenderContents::DidStopLoading();
+    did_finish_loading_ = true;
+    MessageLoopForUI::current()->Quit();
+  }
+
+  bool did_finish_loading() const { return did_finish_loading_; }
+  void set_did_finish_loading(bool did_finish_loading) {
+    did_finish_loading_ = did_finish_loading;
+  }
+
+ private:
+  bool did_finish_loading_;
+  PrerenderContents::FinalStatus expected_final_status_;
+};
+
+// PrerenderManager that uses TestPrerenderContents.
+class WaitForLoadPrerenderContentsFactory : public PrerenderContents::Factory {
+ public:
+  explicit WaitForLoadPrerenderContentsFactory(
+      PrerenderContents::FinalStatus expected_final_status)
+      : expected_final_status_(expected_final_status) {
+  }
+
+  virtual PrerenderContents* CreatePrerenderContents(
+      PrerenderManager* prerender_manager, Profile* profile, const GURL& url,
+      const std::vector<GURL>& alias_urls) {
+    return new TestPrerenderContents(prerender_manager, profile, url,
+                                     alias_urls, expected_final_status_);
+  }
+
+ private:
+  PrerenderContents::FinalStatus expected_final_status_;
+};
+
+}  // namespace
+
+class PrerenderBrowserTest : public InProcessBrowserTest {
+ public:
+  PrerenderBrowserTest() {
+    EnableDOMAutomation();
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) {
+    command_line->AppendSwitchASCII(switches::kPrerender,
+                                    switches::kPrerenderSwitchValueEnabled);
+#if defined(OS_MACOSX)
+    // The plugins directory isn't read by default on the Mac, so it needs to be
+    // explicitly registered.
+    FilePath app_dir;
+    PathService::Get(chrome::DIR_APP, &app_dir);
+    command_line->AppendSwitchPath(
+        switches::kExtraPluginDir,
+        app_dir.Append(FILE_PATH_LITERAL("plugins")));
+#endif
+  }
+
+  void PrerenderTestURL(const std::string& html_file,
+                        PrerenderContents::FinalStatus expected_final_status,
+                        int total_navigations) {
+    ASSERT_TRUE(test_server()->Start());
+
+    std::string src_path = "files/prerender/prerender_loader.html?";
+    src_path.append(html_file);
+    std::string dest_path = "files/prerender/";
+    dest_path.append(html_file);
+
+    GURL src_url = test_server()->GetURL(src_path);
+    dest_url_ = test_server()->GetURL(dest_path);
+
+    Profile* profile = browser()->GetSelectedTabContents()->profile();
+    PrerenderManager* prerender_manager = profile->GetPrerenderManager();
+    ASSERT_TRUE(prerender_manager);
+
+    // This is needed to exit the event loop once the prerendered page has
+    // stopped loading or was cancelled.
+    prerender_manager->SetPrerenderContentsFactory(
+        new WaitForLoadPrerenderContentsFactory(expected_final_status));
+
+    // ui_test_utils::NavigateToURL uses its own observer and message loop.
+    // Since the test needs to wait until the prerendered page has stopped
+    // loading, rathather than the page directly navigated to, need to
+    // handle browser navigation directly.
+    browser()->OpenURL(src_url, GURL(), CURRENT_TAB, PageTransition::TYPED);
+
+    TestPrerenderContents* prerender_contents = NULL;
+    int navigations = 0;
+    while (true) {
+      ui_test_utils::RunMessageLoop();
+      ++navigations;
+
+      prerender_contents =
+          static_cast<TestPrerenderContents*>(
+              prerender_manager->FindEntry(dest_url_));
+      if (prerender_contents == NULL ||
+          !prerender_contents->did_finish_loading() ||
+          navigations >= total_navigations) {
+        EXPECT_EQ(navigations, total_navigations);
+        break;
+      }
+      prerender_contents->set_did_finish_loading(false);
+    }
+
+    switch (expected_final_status) {
+      case PrerenderContents::FINAL_STATUS_USED: {
+        ASSERT_TRUE(prerender_contents != NULL);
+        ASSERT_TRUE(prerender_contents->did_finish_loading());
+
+        // Check if page behaves as expected while in prerendered state.
+        bool prerender_test_result = false;
+        ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+            prerender_contents->render_view_host(), L"",
+            L"window.domAutomationController.send(DidPrerenderPass())",
+            &prerender_test_result));
+        EXPECT_TRUE(prerender_test_result);
+        break;
+      }
+      default:
+        // In the failure case, we should have removed dest_url_ from the
+        // prerender_manager.
+        EXPECT_TRUE(prerender_contents == NULL);
+        break;
+    }
+  }
+
+  void NavigateToDestURL() const {
+    ui_test_utils::NavigateToURL(browser(), dest_url_);
+
+    Profile* profile = browser()->GetSelectedTabContents()->profile();
+    PrerenderManager* prerender_manager = profile->GetPrerenderManager();
+    ASSERT_TRUE(prerender_manager);
+
+    // Make sure the PrerenderContents found earlier was used or removed
+    EXPECT_TRUE(prerender_manager->FindEntry(dest_url_) == NULL);
+
+    // Check if page behaved as expected when actually displayed.
+    bool display_test_result = false;
+    ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+        browser()->GetSelectedTabContents()->render_view_host(), L"",
+        L"window.domAutomationController.send(DidDisplayPass())",
+        &display_test_result));
+    EXPECT_TRUE(display_test_result);
+  }
+
+ private:
+  GURL dest_url_;
+};
+
+// Checks that a page is correctly prerendered in the case of a
+// <link rel=prefetch> tag and then loaded into a tab in response to a
+// navigation.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) {
+  PrerenderTestURL("prerender_page.html",
+                   PrerenderContents::FINAL_STATUS_USED, 1);
+  NavigateToDestURL();
+}
+
+// Checks that the prerendering of a page is canceled correctly when a
+// Javascript alert is called.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) {
+  PrerenderTestURL(
+      "prerender_alert_before_onload.html",
+      PrerenderContents::FINAL_STATUS_JAVASCRIPT_ALERT, 1);
+}
+
+// Checks that the prerendering of a page is canceled correctly when a
+// Javascript alert is called.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) {
+  PrerenderTestURL(
+      "prerender_alert_after_onload.html",
+      PrerenderContents::FINAL_STATUS_JAVASCRIPT_ALERT, 1);
+}
+
+// Checks that plugins are not loaded while a page is being preloaded, but
+// are loaded when the page is displayed.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDelayLoadPlugin) {
+  PrerenderTestURL("plugin_delay_load.html",
+                   PrerenderContents::FINAL_STATUS_USED, 1);
+  NavigateToDestURL();
+}
+
+// Renders a page that contains a prerender link to a page that contains an
+// iframe with a source that requires http authentication. This should not
+// prerender successfully.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttpAuthentication) {
+  PrerenderTestURL("prerender_http_auth_container.html",
+                   PrerenderContents::FINAL_STATUS_AUTH_NEEDED, 1);
+}
+
+// Checks that redirects work with prerendering.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRedirect) {
+  PrerenderTestURL("prerender_redirect.html",
+                   PrerenderContents::FINAL_STATUS_USED, 2);
+  NavigateToDestURL();
+}
+
+// Checks that popups on a prerendered page cause cancellation.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPopup) {
+  PrerenderTestURL("prerender_popup.html",
+                   PrerenderContents::FINAL_STATUS_CREATE_NEW_WINDOW, 1);
+}
+
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 4970739..ac7555f 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/prerender/prerender_contents.h"
 
+#include "base/metrics/histogram.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/background_contents_service.h"
 #include "chrome/browser/browsing_instance.h"
@@ -12,22 +13,47 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/site_instance.h"
 #include "chrome/browser/renderer_preferences_util.h"
+#include "chrome/browser/ui/login/login_prompt.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/view_types.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
+
+class PrerenderContentsFactoryImpl : public PrerenderContents::Factory {
+ public:
+  virtual PrerenderContents* CreatePrerenderContents(
+      PrerenderManager* prerender_manager, Profile* profile, const GURL& url,
+      const std::vector<GURL>& alias_urls) {
+    return new PrerenderContents(prerender_manager, profile, url, alias_urls);
+  }
+};
 
 PrerenderContents::PrerenderContents(PrerenderManager* prerender_manager,
                                      Profile* profile,
-                                     const GURL& url)
+                                     const GURL& url,
+                                     const std::vector<GURL>& alias_urls)
     : prerender_manager_(prerender_manager),
       render_view_host_(NULL),
       prerender_url_(url),
       profile_(profile),
-      page_id_(0) {
+      page_id_(0),
+      has_stopped_loading_(false),
+      final_status_(FINAL_STATUS_MAX) {
   DCHECK(prerender_manager != NULL);
+  AddAliasURL(prerender_url_);
+  for (std::vector<GURL>::const_iterator it = alias_urls.begin();
+       it != alias_urls.end();
+       ++it) {
+    AddAliasURL(*it);
+  }
+}
+
+// static
+PrerenderContents::Factory* PrerenderContents::CreateFactory() {
+  return new PrerenderContentsFactoryImpl();
 }
 
 void PrerenderContents::StartPrerendering() {
@@ -48,10 +74,40 @@
   registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
                  Source<Profile>(profile_));
   render_view_host_->CreateRenderView(string16());
-  render_view_host_->NavigateToURL(prerender_url_);
+
+  // Register to cancel if Authentication is required.
+  registrar_.Add(this, NotificationType::AUTH_NEEDED,
+                 NotificationService::AllSources());
+
+  registrar_.Add(this, NotificationType::AUTH_CANCELLED,
+                 NotificationService::AllSources());
+
+  DCHECK(load_start_time_.is_null());
+  load_start_time_ = base::TimeTicks::Now();
+
+  ViewMsg_Navigate_Params params;
+  params.url = prerender_url_;
+  params.transition = PageTransition::LINK;
+  params.navigation_type = ViewMsg_Navigate_Params::PRERENDER;
+  render_view_host_->Navigate(params);
+}
+
+void PrerenderContents::set_final_status(FinalStatus final_status) {
+  DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX);
+  DCHECK_EQ(FINAL_STATUS_MAX, final_status_);
+  final_status_ = final_status;
+}
+
+PrerenderContents::FinalStatus PrerenderContents::final_status() const {
+  return final_status_;
 }
 
 PrerenderContents::~PrerenderContents() {
+  DCHECK(final_status_ != FINAL_STATUS_MAX);
+  UMA_HISTOGRAM_ENUMERATION("Prerender.FinalStatus",
+                            final_status_,
+                            FINAL_STATUS_MAX);
+
   if (!render_view_host_)   // Will be null for unit tests.
     return;
 
@@ -87,6 +143,8 @@
   navigate_params_.reset(p);
 
   url_ = params.url;
+
+  AddAliasURL(url_);
 }
 
 void PrerenderContents::UpdateTitle(RenderViewHost* render_view_host,
@@ -107,7 +165,12 @@
     const int flags,
     IPC::Message* reply_msg,
     bool* did_suppress_message) {
+  // Always suppress JavaScript messages if they're triggered by a page being
+  // prerendered.
   *did_suppress_message = true;
+  // We still want to show the user the message when they navigate to this
+  // page, so cancel this prerender.
+  Destroy(FINAL_STATUS_JAVASCRIPT_ALERT);
 }
 
 bool PrerenderContents::PreHandleKeyboardEvent(
@@ -121,10 +184,28 @@
                                 const NotificationDetails& details) {
   switch (type.value) {
     case NotificationType::PROFILE_DESTROYED:
-    case NotificationType::APP_TERMINATING: {
-      prerender_manager_->RemoveEntry(this);
+      Destroy(FINAL_STATUS_PROFILE_DESTROYED);
+      return;
+    case NotificationType::APP_TERMINATING:
+      Destroy(FINAL_STATUS_APP_TERMINATING);
+      return;
+
+    case NotificationType::AUTH_NEEDED:
+    case NotificationType::AUTH_CANCELLED: {
+      // Prerendered pages have a NULL controller and the login handler should
+      // be referencing us as the render view host delegate.
+      NavigationController* controller =
+          Source<NavigationController>(source).ptr();
+      LoginNotificationDetails* details_ptr =
+          Details<LoginNotificationDetails>(details).ptr();
+      LoginHandler* handler = details_ptr->handler();
+      DCHECK(handler != NULL);
+      RenderViewHostDelegate* delegate = handler->GetRenderViewHostDelegate();
+      if (controller == NULL && delegate == this)
+        Destroy(FINAL_STATUS_AUTH_NEEDED);
       break;
     }
+
     default:
       NOTREACHED() << "Unexpected notification sent.";
       break;
@@ -160,7 +241,7 @@
 }
 
 void PrerenderContents::Close(RenderViewHost* render_view_host) {
-  prerender_manager_->RemoveEntry(this);
+  Destroy(FINAL_STATUS_CLOSED);
 }
 
 RendererPreferences PrerenderContents::GetRendererPrefs(
@@ -175,18 +256,17 @@
                                                       false);  // is_dom_ui
 }
 
-void PrerenderContents::ProcessDOMUIMessage(
+void PrerenderContents::ProcessWebUIMessage(
     const ViewHostMsg_DomMessage_Params& params) {
   render_view_host_->BlockExtensionRequest(params.request_id);
 }
 
 void PrerenderContents::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   // Since we don't want to permit child windows that would have a
   // window.opener property, terminate prerendering.
-  prerender_manager_->RemoveEntry(this);
+  Destroy(FINAL_STATUS_CREATE_NEW_WINDOW);
 }
 
 void PrerenderContents::CreateNewWidget(int route_id,
@@ -194,8 +274,7 @@
   NOTREACHED();
 }
 
-void PrerenderContents::CreateNewFullscreenWidget(
-    int route_id, WebKit::WebPopupType popup_type) {
+void PrerenderContents::CreateNewFullscreenWidget(int route_id) {
   NOTREACHED();
 }
 
@@ -215,3 +294,55 @@
 void PrerenderContents::ShowCreatedFullscreenWidget(int route_id) {
   NOTIMPLEMENTED();
 }
+
+bool PrerenderContents::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  bool message_is_ok = true;
+  IPC_BEGIN_MESSAGE_MAP_EX(PrerenderContents, message, message_is_ok)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
+                        OnDidStartProvisionalLoadForFrame)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
+                        OnDidRedirectProvisionalLoad)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFavIconURL, OnUpdateFavIconURL)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP_EX()
+
+  return handled;
+}
+
+void PrerenderContents::OnDidStartProvisionalLoadForFrame(int64 frame_id,
+                                                          bool is_main_frame,
+                                                          const GURL& url) {
+  if (is_main_frame)
+    AddAliasURL(url);
+}
+
+void PrerenderContents::OnDidRedirectProvisionalLoad(int32 page_id,
+                                                     const GURL& source_url,
+                                                     const GURL& target_url) {
+  AddAliasURL(target_url);
+}
+
+void PrerenderContents::OnUpdateFavIconURL(int32 page_id,
+                                           const GURL& icon_url) {
+  icon_url_ = icon_url;
+}
+
+void PrerenderContents::AddAliasURL(const GURL& url) {
+  alias_urls_.push_back(url);
+}
+
+bool PrerenderContents::MatchesURL(const GURL& url) const {
+  return std::find(alias_urls_.begin(), alias_urls_.end(), url)
+      != alias_urls_.end();
+}
+
+void PrerenderContents::DidStopLoading() {
+  has_stopped_loading_ = true;
+}
+
+void PrerenderContents::Destroy(FinalStatus final_status) {
+  prerender_manager_->RemoveEntry(this);
+  set_final_status(final_status);
+  delete this;
+}
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index bf2963f..40b34dc 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/time.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
@@ -36,9 +37,41 @@
                           public NotificationObserver,
                           public JavaScriptAppModalDialogDelegate {
  public:
-  PrerenderContents(PrerenderManager* prerender_manager, Profile* profile,
-                    const GURL& url);
+  // FinalStatus indicates whether |this| was used, or why it was cancelled.
+  // NOTE: New values need to be appended, since they are used in histograms.
+  enum FinalStatus {
+    FINAL_STATUS_USED,
+    FINAL_STATUS_TIMED_OUT,
+    FINAL_STATUS_EVICTED,
+    FINAL_STATUS_MANAGER_SHUTDOWN,
+    FINAL_STATUS_CLOSED,
+    FINAL_STATUS_CREATE_NEW_WINDOW,
+    FINAL_STATUS_PROFILE_DESTROYED,
+    FINAL_STATUS_APP_TERMINATING,
+    FINAL_STATUS_JAVASCRIPT_ALERT,
+    FINAL_STATUS_AUTH_NEEDED,
+    FINAL_STATUS_MAX,
+  };
+
+  // PrerenderContents::Create uses the currently registered Factory to create
+  // the PrerenderContents. Factory is intended for testing.
+  class Factory {
+   public:
+    Factory() {}
+    virtual ~Factory() {}
+
+    virtual PrerenderContents* CreatePrerenderContents(
+        PrerenderManager* prerender_manager, Profile* profile, const GURL& url,
+        const std::vector<GURL>& alias_urls) = 0;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Factory);
+  };
+
   virtual ~PrerenderContents();
+
+  static Factory* CreateFactory();
+
   virtual void StartPrerendering();
 
   RenderViewHost* render_view_host() { return render_view_host_; }
@@ -51,6 +84,20 @@
   }
   string16 title() const { return title_; }
   int32 page_id() const { return page_id_; }
+  GURL icon_url() const { return icon_url_; }
+  bool has_stopped_loading() const { return has_stopped_loading_; }
+
+  // Set the final status for how the PrerenderContents was used. This
+  // should only be called once, and should be called before the prerender
+  // contents are destroyed.
+  void set_final_status(FinalStatus final_status);
+  FinalStatus final_status() const;
+
+  base::TimeTicks load_start_time() const { return load_start_time_; }
+
+  // Indicates whether this prerendered page can be used for the provided
+  // URL, i.e. whether there is a match.
+  bool MatchesURL(const GURL& url) const;
 
   // RenderViewHostDelegate implementation.
   virtual RenderViewHostDelegate::View* GetViewDelegate();
@@ -63,7 +110,7 @@
                            int32 page_id,
                            const std::wstring& title);
   virtual WebPreferences GetWebkitPrefs();
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
   virtual void RunJavaScriptMessage(const std::wstring& message,
                                     const std::wstring& default_prompt,
                                     const GURL& frame_url,
@@ -71,16 +118,15 @@
                                     IPC::Message* reply_msg,
                                     bool* did_suppress_message);
   virtual void Close(RenderViewHost* render_view_host);
+  virtual void DidStopLoading();
   virtual RendererPreferences GetRendererPrefs(Profile* profile) const;
 
   // RenderViewHostDelegate::View
   virtual void CreateNewWindow(
       int route_id,
-      WindowContainerType window_container_type,
-      const string16& frame_name);
+      const ViewHostMsg_CreateWindow_Params& params);
   virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
-  virtual void CreateNewFullscreenWidget(
-      int route_id, WebKit::WebPopupType popup_type);
+  virtual void CreateNewFullscreenWidget(int route_id);
   virtual void ShowCreatedWindow(int route_id,
                                  WindowOpenDisposition disposition,
                                  const gfx::Rect& initial_pos,
@@ -133,7 +179,33 @@
                                       const std::string& value);
   virtual void ClearInspectorSettings();
 
+ protected:
+  PrerenderContents(PrerenderManager* prerender_manager, Profile* profile,
+                    const GURL& url, const std::vector<GURL>& alias_urls);
+
+  // from RenderViewHostDelegate.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
  private:
+  // Needs to be able to call the constructor.
+  friend class PrerenderContentsFactoryImpl;
+
+  // Message handlers.
+  void OnDidStartProvisionalLoadForFrame(int64 frame_id,
+                                         bool main_frame,
+                                         const GURL& url);
+  void OnDidRedirectProvisionalLoad(int32 page_id,
+                                    const GURL& source_url,
+                                    const GURL& target_url);
+
+  void OnUpdateFavIconURL(int32 page_id, const GURL& icon_url);
+
+  void AddAliasURL(const GURL& url);
+
+  // Remove |this| from the PrerenderManager, set a final status, and
+  // delete |this|.
+  void Destroy(FinalStatus reason);
+
   // The prerender manager owning this object.
   PrerenderManager* prerender_manager_;
 
@@ -160,8 +232,23 @@
   string16 title_;
   int32 page_id_;
   GURL url_;
+  GURL icon_url_;
   NotificationRegistrar registrar_;
 
+  // A vector of URLs that this prerendered page matches against.
+  // This array can contain more than element as a result of redirects,
+  // such as HTTP redirects or javascript redirects.
+  std::vector<GURL> alias_urls_;
+
+  bool has_stopped_loading_;
+
+  FinalStatus final_status_;
+
+  // Time at which we started to load the URL.  This is used to compute
+  // the time elapsed from initiating a prerender until the time the
+  // (potentially only partially) prerendered page is shown to the user.
+  base::TimeTicks load_start_time_;
+
   DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
 };
 
diff --git a/chrome/browser/prerender/prerender_interceptor.cc b/chrome/browser/prerender/prerender_interceptor.cc
deleted file mode 100644
index 831cfff..0000000
--- a/chrome/browser/prerender/prerender_interceptor.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/prerender/prerender_interceptor.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/io_thread.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/load_flags.h"
-
-DISABLE_RUNNABLE_METHOD_REFCOUNT(PrerenderInterceptor);
-
-PrerenderInterceptor::PrerenderInterceptor()
-    : ALLOW_THIS_IN_INITIALIZER_LIST(
-        callback_(NewCallback(this,
-                              &PrerenderInterceptor::PrerenderDispatch))) {
-  net::URLRequest::RegisterRequestInterceptor(this);
-}
-
-PrerenderInterceptor::PrerenderInterceptor(
-    PrerenderInterceptorCallback* callback)
-  : callback_(callback) {
-    net::URLRequest::RegisterRequestInterceptor(this);
-}
-
-PrerenderInterceptor::~PrerenderInterceptor() {
-  net::URLRequest::UnregisterRequestInterceptor(this);
-}
-
-net::URLRequestJob* PrerenderInterceptor::MaybeIntercept(
-    net::URLRequest* request) {
-  return NULL;
-}
-
-net::URLRequestJob* PrerenderInterceptor::MaybeInterceptResponse(
-  net::URLRequest* request) {
-  // TODO(gavinp): unfortunately, we can't figure out the origin
-  // of this request here on systems where the referrer is blocked by
-  // configuration.
-
-  // TODO(gavinp): note that the response still might be intercepted
-  // by a later interceptor.  Should we write an interposing delegate
-  // and only prerender dispatch on requests that aren't intercepted?
-  // Or is this a slippery slope?
-
-  if (request->load_flags() & net::LOAD_PREFETCH) {
-    std::string mime_type;
-    request->GetMimeType(&mime_type);
-    if (mime_type == "text/html")
-      BrowserThread::PostTask(
-          BrowserThread::UI,
-          FROM_HERE,
-          NewRunnableMethod(this,
-                            &PrerenderInterceptor::RunCallbackFromUIThread,
-                            request->url()));
-  }
-  return NULL;
-}
-
-void PrerenderInterceptor::RunCallbackFromUIThread(const GURL& url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  callback_->Run(url);
-}
-
-void PrerenderInterceptor::PrerenderDispatch(
-    const GURL& url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DVLOG(2) << "PrerenderDispatchOnUIThread: url=" << url;
-}
-
diff --git a/chrome/browser/prerender/prerender_interceptor.h b/chrome/browser/prerender/prerender_interceptor.h
deleted file mode 100644
index 8a0fe32..0000000
--- a/chrome/browser/prerender/prerender_interceptor.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_INTERCEPTOR_H_
-#define CHROME_BROWSER_PRERENDER_PRERENDER_INTERCEPTOR_H_
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "net/url_request/url_request.h"
-
-class GURL;
-
-// The PrerenderInterceptor watches prefetch requests, and when
-// they are for type text/html, notifies the prerendering
-// system about the fetch so it may consider the URL.
-class PrerenderInterceptor : public net::URLRequest::Interceptor {
- public:
-  PrerenderInterceptor();
-  virtual ~PrerenderInterceptor();
-
-  // URLRequest::Interceptor overrides.  We only care about
-  // MaybeInterceptResponse, but must capture MaybeIntercept since
-  // it is pure virtual.
-  virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request);
-  virtual net::URLRequestJob* MaybeInterceptResponse(net::URLRequest* request);
-
- private:
-  friend class PrerenderInterceptorTest;
-
-  typedef Callback1<const GURL&>::Type PrerenderInterceptorCallback;
-
-  // This constructor is provided for the unit test only, to provide
-  // an an alternative dispatch target for the test only.  The callback
-  // parameter is owned and deleted by this object.
-  explicit PrerenderInterceptor(PrerenderInterceptorCallback* callback);
-
-  void RunCallbackFromUIThread(const GURL& url);
-  void PrerenderDispatch(const GURL& url);
-
-  scoped_ptr<PrerenderInterceptorCallback> callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrerenderInterceptor);
-};
-
-#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_INTERCEPTOR_H_
-
diff --git a/chrome/browser/prerender/prerender_interceptor_unittest.cc b/chrome/browser/prerender/prerender_interceptor_unittest.cc
deleted file mode 100644
index 2fc236f..0000000
--- a/chrome/browser/prerender/prerender_interceptor_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/prerender/prerender_interceptor.h"
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/file_path.h"
-#include "base/message_loop_proxy.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/browser_thread.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/load_flags.h"
-#include "net/test/test_server.h"
-#include "net/url_request/url_request_unittest.h"
-
-class PrerenderInterceptorTest : public testing::Test {
- protected:
-  PrerenderInterceptorTest();
-
-  void MakeTestUrl(const std::string& base);
-  virtual void SetUp();
-
-  net::TestServer test_server_;
-  GURL gurl_;
-  GURL last_intercepted_gurl_;
-  scoped_ptr<net::URLRequest> req_;
-
- private:
-  void SetLastInterceptedGurl(const GURL& url);
-
-  PrerenderInterceptor prerender_interceptor_;
-  MessageLoopForIO io_loop_;
-  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
-  BrowserThread ui_thread_;
-  TestDelegate delegate_for_req_;
-};
-
-PrerenderInterceptorTest::PrerenderInterceptorTest()
-    : test_server_(net::TestServer::TYPE_HTTP,
-                   FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
-      last_intercepted_gurl_("http://not.initialized/"),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          prerender_interceptor_(
-              NewCallback(this,
-                          &PrerenderInterceptorTest::SetLastInterceptedGurl))),
-      ui_thread_(BrowserThread::UI, &io_loop_) {
-}
-
-void PrerenderInterceptorTest::SetUp() {
-  testing::Test::SetUp();
-  last_intercepted_gurl_ = GURL("http://nothing.intercepted/");
-
-  io_message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
-  ASSERT_TRUE(test_server_.Start());
-}
-
-void PrerenderInterceptorTest::MakeTestUrl(const std::string& base) {
-  gurl_ = test_server_.GetURL(base);
-  req_.reset(new TestURLRequest(gurl_, &delegate_for_req_));
-}
-
-void PrerenderInterceptorTest::SetLastInterceptedGurl(const GURL& url) {
-  last_intercepted_gurl_ = url;
-}
-
-namespace {
-
-TEST_F(PrerenderInterceptorTest, Interception) {
-  MakeTestUrl("files/prerender/doc1.html");
-  req_->set_load_flags(req_->load_flags() | net::LOAD_PREFETCH);
-  req_->Start();
-
-  MessageLoop::current()->Run();
-  EXPECT_EQ(URLRequestStatus::SUCCESS, req_->status().status());
-  EXPECT_EQ(gurl_, last_intercepted_gurl_);
-}
-
-TEST_F(PrerenderInterceptorTest, NotAPrefetch) {
-  MakeTestUrl("files/prerender/doc2.html");
-  req_->set_load_flags(req_->load_flags() & ~net::LOAD_PREFETCH);
-  req_->Start();
-
-  MessageLoop::current()->Run();
-  EXPECT_EQ(URLRequestStatus::SUCCESS, req_->status().status());
-  EXPECT_NE(gurl_, last_intercepted_gurl_);
-}
-
-TEST_F(PrerenderInterceptorTest, WrongMimeType) {
-  MakeTestUrl("files/prerender/image.jpeg");
-  req_->set_load_flags(req_->load_flags() | net::LOAD_PREFETCH);
-  req_->Start();
-
-  MessageLoop::current()->Run();
-  EXPECT_EQ(URLRequestStatus::SUCCESS, req_->status().status());
-  EXPECT_NE(gurl_, last_intercepted_gurl_);
-}
-
-}  // namespace
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 0135880..6e28a2c 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -1,15 +1,44 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/prerender/prerender_manager.h"
 
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/fav_icon_helper.h"
 #include "chrome/browser/prerender/prerender_contents.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/render_view_host_manager.h"
+#include "chrome/common/render_messages.h"
+
+// static
+base::TimeTicks PrerenderManager::last_prefetch_seen_time_;
+
+// static
+PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ =
+    PRERENDER_MODE_ENABLED;
+
+// static
+PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() {
+  return mode_;
+}
+
+// static
+void PrerenderManager::SetMode(PrerenderManagerMode mode) {
+  mode_ = mode;
+}
+
+// static
+bool PrerenderManager::IsPrerenderingEnabled() {
+  return
+      GetMode() == PRERENDER_MODE_ENABLED ||
+      GetMode() == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP;
+}
 
 struct PrerenderManager::PrerenderContentsData {
   PrerenderContents* contents_;
@@ -28,19 +57,28 @@
     : profile_(profile),
       max_prerender_age_(base::TimeDelta::FromSeconds(
           kDefaultMaxPrerenderAgeSeconds)),
-      max_elements_(kDefaultMaxPrerenderElements) {
+      max_elements_(kDefaultMaxPrerenderElements),
+      prerender_contents_factory_(PrerenderContents::CreateFactory()) {
 }
 
 PrerenderManager::~PrerenderManager() {
   while (prerender_list_.size() > 0) {
     PrerenderContentsData data = prerender_list_.front();
     prerender_list_.pop_front();
+    data.contents_->set_final_status(
+        PrerenderContents::FINAL_STATUS_MANAGER_SHUTDOWN);
     delete data.contents_;
   }
 }
 
-void PrerenderManager::AddPreload(const GURL& url) {
-  DCHECK(CalledOnValidThread());
+void PrerenderManager::SetPrerenderContentsFactory(
+    PrerenderContents::Factory* prerender_contents_factory) {
+  prerender_contents_factory_.reset(prerender_contents_factory);
+}
+
+void PrerenderManager::AddPreload(const GURL& url,
+                                  const std::vector<GURL>& alias_urls) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DeleteOldEntries();
   // If the URL already exists in the set of preloaded URLs, don't do anything.
   for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
@@ -49,13 +87,14 @@
     if (it->url_ == url)
       return;
   }
-  PrerenderContentsData data(CreatePrerenderContents(url),
+  PrerenderContentsData data(CreatePrerenderContents(url, alias_urls),
                              GetCurrentTime(), url);
   prerender_list_.push_back(data);
   data.contents_->StartPrerendering();
   while (prerender_list_.size() > max_elements_) {
     data = prerender_list_.front();
     prerender_list_.pop_front();
+    data.contents_->set_final_status(PrerenderContents::FINAL_STATUS_EVICTED);
     delete data.contents_;
   }
 }
@@ -66,6 +105,7 @@
     if (IsPrerenderElementFresh(data.start_time_))
       return;
     prerender_list_.pop_front();
+    data.contents_->set_final_status(PrerenderContents::FINAL_STATUS_TIMED_OUT);
     delete data.contents_;
   }
 }
@@ -75,7 +115,8 @@
   for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
        it != prerender_list_.end();
        ++it) {
-    if (it->url_ == url) {
+    PrerenderContents* pc = it->contents_;
+    if (pc->MatchesURL(url)) {
       PrerenderContents* pc = it->contents_;
       prerender_list_.erase(it);
       return pc;
@@ -86,13 +127,18 @@
 }
 
 bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tc, const GURL& url) {
-  DCHECK(CalledOnValidThread());
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   scoped_ptr<PrerenderContents> pc(GetEntry(url));
   if (pc.get() == NULL)
     return false;
 
+  if (!pc->load_start_time().is_null())
+    RecordTimeUntilUsed(base::TimeTicks::Now() - pc->load_start_time());
+  pc->set_final_status(PrerenderContents::FINAL_STATUS_USED);
+
   RenderViewHost* rvh = pc->render_view_host();
   pc->set_render_view_host(NULL);
+  rvh->Send(new ViewMsg_DisplayPrerenderedPage(rvh->routing_id()));
   tc->SwapInRenderViewHost(rvh);
 
   ViewHostMsg_FrameNavigate_Params* p = pc->navigate_params();
@@ -103,11 +149,18 @@
   if (!title.empty())
     tc->UpdateTitle(rvh, pc->page_id(), UTF16ToWideHack(title));
 
+  GURL icon_url = pc->icon_url();
+  if (!icon_url.is_empty())
+    tc->fav_icon_helper().OnUpdateFavIconURL(pc->page_id(), icon_url);
+
+  if (pc->has_stopped_loading())
+    tc->DidStopLoading();
+
   return true;
 }
 
 void PrerenderManager::RemoveEntry(PrerenderContents* entry) {
-  DCHECK(CalledOnValidThread());
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
        it != prerender_list_.end();
        ++it) {
@@ -116,7 +169,6 @@
       break;
     }
   }
-  delete entry;
   DeleteOldEntries();
 }
 
@@ -129,6 +181,81 @@
   return (now - start < max_prerender_age_);
 }
 
-PrerenderContents* PrerenderManager::CreatePrerenderContents(const GURL& url) {
-  return new PrerenderContents(this, profile_, url);
+PrerenderContents* PrerenderManager::CreatePrerenderContents(
+    const GURL& url,
+    const std::vector<GURL>& alias_urls) {
+  return prerender_contents_factory_->CreatePrerenderContents(
+      this, profile_, url, alias_urls);
+}
+
+void PrerenderManager::RecordPerceivedPageLoadTime(base::TimeDelta pplt) {
+  bool record_windowed_pplt = ShouldRecordWindowedPPLT();
+  switch (mode_) {
+    case PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP:
+      UMA_HISTOGRAM_TIMES("Prerender.PerceivedPageLoadTime_Control", pplt);
+      if (record_windowed_pplt) {
+        UMA_HISTOGRAM_TIMES("Prerender.PerceivedPageLoadTime_WindowControl",
+                            pplt);
+      }
+      break;
+    case PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP:
+      UMA_HISTOGRAM_TIMES("Prerender.PerceivedPageLoadTime_Treatment", pplt);
+      if (record_windowed_pplt) {
+        UMA_HISTOGRAM_TIMES("Prerender.PerceivedPageLoadTime_WindowTreatment",
+                            pplt);
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+void PrerenderManager::RecordTimeUntilUsed(base::TimeDelta time_until_used) {
+  if (mode_ == PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP) {
+    UMA_HISTOGRAM_TIMES("Prerender.TimeUntilUsed", time_until_used);
+  }
+}
+
+PrerenderContents* PrerenderManager::FindEntry(const GURL& url) {
+  for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
+       it != prerender_list_.end();
+       ++it) {
+    if (it->contents_->MatchesURL(url))
+      return it->contents_;
+  }
+  // Entry not found.
+  return NULL;
+}
+
+void PrerenderManager::RecordPrefetchTagObserved() {
+  // Ensure that we are in the UI thread, and post to the UI thread if
+  // necessary.
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    BrowserThread::PostTask(
+        BrowserThread::UI,
+        FROM_HERE,
+        NewRunnableFunction(
+            &PrerenderManager::RecordPrefetchTagObservedOnUIThread));
+  } else {
+    RecordPrefetchTagObservedOnUIThread();
+  }
+}
+
+void PrerenderManager::RecordPrefetchTagObservedOnUIThread() {
+  // Once we get here, we have to be on the UI thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // If we observe multiple tags within the 30 second window, we will still
+  // reset the window to begin at the most recent occurrence, so that we will
+  // always be in a window in the 30 seconds from each occurrence.
+  last_prefetch_seen_time_ = base::TimeTicks::Now();
+}
+
+bool PrerenderManager::ShouldRecordWindowedPPLT() const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (last_prefetch_seen_time_.is_null())
+    return false;
+  base::TimeDelta elapsed_time =
+      base::TimeTicks::Now() - last_prefetch_seen_time_;
+  return elapsed_time <= base::TimeDelta::FromSeconds(kWindowedPPLTSeconds);
 }
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 2c49e68..6a62915 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,26 +7,37 @@
 #pragma once
 
 #include <list>
+#include <vector>
 
+#include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time.h"
+#include "chrome/browser/prerender/prerender_contents.h"
 #include "googleurl/src/gurl.h"
 
-class PrerenderContents;
 class Profile;
 class TabContents;
 
 // PrerenderManager is responsible for initiating and keeping prerendered
 // views of webpages.
-class PrerenderManager : base::NonThreadSafe {
+class PrerenderManager : public base::RefCounted<PrerenderManager> {
  public:
+  // PrerenderManagerMode is used in a UMA_HISTOGRAM, so please do not
+  // add in the middle.
+  enum PrerenderManagerMode {
+    PRERENDER_MODE_DISABLED,
+    PRERENDER_MODE_ENABLED,
+    PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP,
+    PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP,
+    PRERENDER_MODE_MAX
+  };
+
   // Owned by a Profile object for the lifetime of the profile.
   explicit PrerenderManager(Profile* profile);
-  virtual ~PrerenderManager();
 
-  // Preloads the URL supplied.
-  void AddPreload(const GURL& url);
+  // Preloads the URL supplied.  alias_urls indicates URLs that redirect
+  // to the same URL to be preloaded.
+  void AddPreload(const GURL& url, const std::vector<GURL>& alias_urls);
 
   // For a given TabContents that wants to navigate to the URL supplied,
   // determines whether a preloaded version of the URL can be used,
@@ -35,7 +46,7 @@
   bool MaybeUsePreloadedPage(TabContents* tc, const GURL& url);
 
   // Allows PrerenderContents to remove itself when prerendering should
-  // be cancelled.  Also deletes the entry.
+  // be cancelled.
   void RemoveEntry(PrerenderContents* entry);
 
   // Retrieves the PrerenderContents object for the specified URL, if it
@@ -44,22 +55,51 @@
   // Returns NULL if the specified URL has not been prerendered.
   PrerenderContents* GetEntry(const GURL& url);
 
+  // The following two methods should only be called from the UI thread.
+  void RecordPerceivedPageLoadTime(base::TimeDelta pplt);
+  void RecordTimeUntilUsed(base::TimeDelta time_until_used);
+
   base::TimeDelta max_prerender_age() const { return max_prerender_age_; }
   void set_max_prerender_age(base::TimeDelta td) { max_prerender_age_ = td; }
   unsigned int max_elements() const { return max_elements_; }
   void set_max_elements(unsigned int num) { max_elements_ = num; }
 
+  static PrerenderManagerMode GetMode();
+  static void SetMode(PrerenderManagerMode mode);
+  static bool IsPrerenderingEnabled();
+
+  // The following static method can be called from any thread, but will result
+  // in posting a task to the UI thread if we are not in the UI thread.
+  static void RecordPrefetchTagObserved();
+
  protected:
-  // The following methods exist explicitly rather than just inlined to
-  // facilitate testing.
-  virtual base::Time GetCurrentTime() const;
-  virtual PrerenderContents* CreatePrerenderContents(const GURL& url);
+  virtual ~PrerenderManager();
+
+  void SetPrerenderContentsFactory(
+      PrerenderContents::Factory* prerender_contents_factory);
 
  private:
+  // Test that needs needs access to internal functions.
+  friend class PrerenderBrowserTest;
+
+  friend class base::RefCounted<PrerenderManager>;
   struct PrerenderContentsData;
 
   bool IsPrerenderElementFresh(const base::Time start) const;
   void DeleteOldEntries();
+  virtual base::Time GetCurrentTime() const;
+  virtual PrerenderContents* CreatePrerenderContents(
+      const GURL& url,
+      const std::vector<GURL>& alias_urls);
+
+  // Finds the specified PrerenderContents and returns it, if it exists.
+  // Returns NULL otherwise.  Unlike GetEntry, the PrerenderManager maintains
+  // ownership of the PrerenderContents.
+  PrerenderContents* FindEntry(const GURL& url);
+
+  bool ShouldRecordWindowedPPLT() const;
+
+  static void RecordPrefetchTagObservedOnUIThread();
 
   Profile* profile_;
 
@@ -75,6 +115,20 @@
   // Default maximum age a prerendered element may have, in seconds.
   static const int kDefaultMaxPrerenderAgeSeconds = 20;
 
+  // Time window for which we will record windowed PLT's from the last
+  // observed link rel=prefetch tag.
+  static const int kWindowedPPLTSeconds = 30;
+
+  scoped_ptr<PrerenderContents::Factory> prerender_contents_factory_;
+
+  static PrerenderManagerMode mode_;
+
+  // The time when we last saw a prefetch request coming from a renderer.
+  // This is used to record perceived PLT's for a certain amount of time
+  // from the point that we last saw a <link rel=prefetch> tag.
+  // This static variable should only be modified on the UI thread.
+  static base::TimeTicks last_prefetch_seen_time_;
+
   DISALLOW_COPY_AND_ASSIGN(PrerenderManager);
 };
 
diff --git a/chrome/browser/prerender/prerender_manager_unittest.cc b/chrome/browser/prerender/prerender_manager_unittest.cc
index b5cb65b..10f7a00 100644
--- a/chrome/browser/prerender/prerender_manager_unittest.cc
+++ b/chrome/browser/prerender/prerender_manager_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/time.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "googleurl/src/gurl.h"
@@ -12,9 +13,26 @@
 
 class DummyPrerenderContents : public PrerenderContents {
  public:
-  DummyPrerenderContents(PrerenderManager* prerender_manager, const GURL& url)
-      : PrerenderContents(prerender_manager, NULL, url),
-        has_started_(false) {
+  DummyPrerenderContents(PrerenderManager* prerender_manager,
+                         const GURL& url,
+                         FinalStatus expected_final_status)
+      : PrerenderContents(prerender_manager, NULL, url,
+                          std::vector<GURL>()),
+        has_started_(false),
+        expected_final_status_(expected_final_status) {
+  }
+
+  DummyPrerenderContents(PrerenderManager* prerender_manager,
+                         const GURL& url,
+                         const std::vector<GURL> alias_urls,
+                         FinalStatus expected_final_status)
+      : PrerenderContents(prerender_manager, NULL, url, alias_urls),
+        has_started_(false),
+        expected_final_status_(expected_final_status) {
+  }
+
+  virtual ~DummyPrerenderContents() {
+    EXPECT_EQ(expected_final_status_, final_status());
   }
 
   virtual void StartPrerendering() {
@@ -25,6 +43,7 @@
 
  private:
   bool has_started_;
+  FinalStatus expected_final_status_;
 };
 
 class TestPrerenderManager : public PrerenderManager {
@@ -43,18 +62,32 @@
     next_pc_.reset(pc);
   }
 
+  // Shorthand to add a simple preload with no aliases.
+  void AddSimplePreload(const GURL& url) {
+    AddPreload(url, std::vector<GURL>());
+  }
+
   PrerenderContents* next_pc() { return next_pc_.get(); }
 
  protected:
+  virtual ~TestPrerenderManager() {
+    if (next_pc()) {
+      next_pc()->set_final_status(
+          PrerenderContents::FINAL_STATUS_MANAGER_SHUTDOWN);
+    }
+  }
+
+ private:
   virtual base::Time GetCurrentTime() const {
     return time_;
   }
 
-  virtual PrerenderContents* CreatePrerenderContents(const GURL& url) {
+  virtual PrerenderContents* CreatePrerenderContents(
+      const GURL& url,
+      const std::vector<GURL>& alias_urls) {
     return next_pc_.release();
   }
 
- private:
   base::Time time_;
   scoped_ptr<PrerenderContents> next_pc_;
 };
@@ -63,11 +96,17 @@
 
 class PrerenderManagerTest : public testing::Test {
  public:
-  PrerenderManagerTest() : prerender_manager_(new TestPrerenderManager()) {
+  PrerenderManagerTest() : prerender_manager_(new TestPrerenderManager()),
+                           ui_thread_(BrowserThread::UI, &message_loop_) {
   }
 
  protected:
-  scoped_ptr<TestPrerenderManager> prerender_manager_;
+  scoped_refptr<TestPrerenderManager> prerender_manager_;
+
+ private:
+  // Needed to pass PrerenderManager's DCHECKs.
+  MessageLoop message_loop_;
+  BrowserThread ui_thread_;
 };
 
 TEST_F(PrerenderManagerTest, EmptyTest) {
@@ -78,11 +117,14 @@
 TEST_F(PrerenderManagerTest, FoundTest) {
   GURL url("http://www.google.com/");
   DummyPrerenderContents* pc =
-      new DummyPrerenderContents(prerender_manager_.get(), url);
+      new DummyPrerenderContents(prerender_manager_.get(),
+                                 url,
+                                 PrerenderContents::FINAL_STATUS_USED);
   prerender_manager_->SetNextPrerenderContents(pc);
-  prerender_manager_->AddPreload(url);
+  prerender_manager_->AddSimplePreload(url);
   EXPECT_TRUE(pc->has_started());
   EXPECT_EQ(pc, prerender_manager_->GetEntry(url));
+  pc->set_final_status(PrerenderContents::FINAL_STATUS_USED);
   delete pc;
 }
 
@@ -91,19 +133,23 @@
 TEST_F(PrerenderManagerTest, DropSecondRequestTest) {
   GURL url("http://www.google.com/");
   DummyPrerenderContents* pc =
-      new DummyPrerenderContents(prerender_manager_.get(), url);
+      new DummyPrerenderContents(prerender_manager_.get(), url,
+                                 PrerenderContents::FINAL_STATUS_USED);
   DummyPrerenderContents* null = NULL;
   prerender_manager_->SetNextPrerenderContents(pc);
-  prerender_manager_->AddPreload(url);
+  prerender_manager_->AddSimplePreload(url);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc->has_started());
   DummyPrerenderContents* pc1 =
-      new DummyPrerenderContents(prerender_manager_.get(), url);
+      new DummyPrerenderContents(
+          prerender_manager_.get(), url,
+          PrerenderContents::FINAL_STATUS_MANAGER_SHUTDOWN);
   prerender_manager_->SetNextPrerenderContents(pc1);
-  prerender_manager_->AddPreload(url);
+  prerender_manager_->AddSimplePreload(url);
   EXPECT_EQ(pc1, prerender_manager_->next_pc());
   EXPECT_FALSE(pc1->has_started());
   EXPECT_EQ(pc, prerender_manager_->GetEntry(url));
+  pc->set_final_status(PrerenderContents::FINAL_STATUS_USED);
   delete pc;
 }
 
@@ -111,10 +157,11 @@
 TEST_F(PrerenderManagerTest, ExpireTest) {
   GURL url("http://www.google.com/");
   DummyPrerenderContents* pc =
-      new DummyPrerenderContents(prerender_manager_.get(), url);
+      new DummyPrerenderContents(prerender_manager_.get(), url,
+                                 PrerenderContents::FINAL_STATUS_TIMED_OUT);
   DummyPrerenderContents* null = NULL;
   prerender_manager_->SetNextPrerenderContents(pc);
-  prerender_manager_->AddPreload(url);
+  prerender_manager_->AddSimplePreload(url);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc->has_started());
   prerender_manager_->AdvanceTime(prerender_manager_->max_prerender_age()
@@ -127,21 +174,24 @@
 TEST_F(PrerenderManagerTest, DropOldestRequestTest) {
   GURL url("http://www.google.com/");
   DummyPrerenderContents* pc =
-      new DummyPrerenderContents(prerender_manager_.get(), url);
+      new DummyPrerenderContents(prerender_manager_.get(), url,
+                                 PrerenderContents::FINAL_STATUS_EVICTED);
   DummyPrerenderContents* null = NULL;
   prerender_manager_->SetNextPrerenderContents(pc);
-  prerender_manager_->AddPreload(url);
+  prerender_manager_->AddSimplePreload(url);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc->has_started());
   GURL url1("http://news.google.com/");
   DummyPrerenderContents* pc1 =
-      new DummyPrerenderContents(prerender_manager_.get(), url1);
+      new DummyPrerenderContents(prerender_manager_.get(), url1,
+                                 PrerenderContents::FINAL_STATUS_USED);
   prerender_manager_->SetNextPrerenderContents(pc1);
-  prerender_manager_->AddPreload(url1);
+  prerender_manager_->AddSimplePreload(url1);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc1->has_started());
   EXPECT_EQ(null, prerender_manager_->GetEntry(url));
   EXPECT_EQ(pc1, prerender_manager_->GetEntry(url1));
+  pc1->set_final_status(PrerenderContents::FINAL_STATUS_USED);
   delete pc1;
 }
 
@@ -151,29 +201,59 @@
   prerender_manager_->set_max_elements(2);
   GURL url("http://www.google.com/");
   DummyPrerenderContents* pc =
-      new DummyPrerenderContents(prerender_manager_.get(), url);
+      new DummyPrerenderContents(prerender_manager_.get(), url,
+                                 PrerenderContents::FINAL_STATUS_EVICTED);
   DummyPrerenderContents* null = NULL;
   prerender_manager_->SetNextPrerenderContents(pc);
-  prerender_manager_->AddPreload(url);
+  prerender_manager_->AddSimplePreload(url);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc->has_started());
   GURL url1("http://news.google.com/");
   DummyPrerenderContents* pc1 =
-      new DummyPrerenderContents(prerender_manager_.get(),  url1);
+      new DummyPrerenderContents(prerender_manager_.get(),  url1,
+                                 PrerenderContents::FINAL_STATUS_USED);
   prerender_manager_->SetNextPrerenderContents(pc1);
-  prerender_manager_->AddPreload(url1);
+  prerender_manager_->AddSimplePreload(url1);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc1->has_started());
   GURL url2("http://images.google.com/");
   DummyPrerenderContents* pc2 =
-      new DummyPrerenderContents(prerender_manager_.get(), url2);
+      new DummyPrerenderContents(prerender_manager_.get(), url2,
+                                 PrerenderContents::FINAL_STATUS_USED);
   prerender_manager_->SetNextPrerenderContents(pc2);
-  prerender_manager_->AddPreload(url2);
+  prerender_manager_->AddSimplePreload(url2);
   EXPECT_EQ(null, prerender_manager_->next_pc());
   EXPECT_TRUE(pc2->has_started());
   EXPECT_EQ(null, prerender_manager_->GetEntry(url));
   EXPECT_EQ(pc1, prerender_manager_->GetEntry(url1));
   EXPECT_EQ(pc2, prerender_manager_->GetEntry(url2));
+  pc1->set_final_status(PrerenderContents::FINAL_STATUS_USED);
   delete pc1;
+  pc2->set_final_status(PrerenderContents::FINAL_STATUS_USED);
   delete pc2;
 }
+
+TEST_F(PrerenderManagerTest, AliasURLTest) {
+  GURL url("http://www.google.com/");
+  GURL alias_url1("http://www.google.com/index.html");
+  GURL alias_url2("http://google.com/");
+  GURL not_an_alias_url("http://google.com/index.html");
+  std::vector<GURL> alias_urls;
+  alias_urls.push_back(alias_url1);
+  alias_urls.push_back(alias_url2);
+  DummyPrerenderContents* pc =
+      new DummyPrerenderContents(prerender_manager_.get(), url, alias_urls,
+                                 PrerenderContents::FINAL_STATUS_USED);
+  prerender_manager_->SetNextPrerenderContents(pc);
+  prerender_manager_->AddSimplePreload(url);
+  EXPECT_EQ(NULL, prerender_manager_->GetEntry(not_an_alias_url));
+  EXPECT_EQ(pc, prerender_manager_->GetEntry(alias_url1));
+  prerender_manager_->SetNextPrerenderContents(pc);
+  prerender_manager_->AddSimplePreload(url);
+  EXPECT_EQ(pc, prerender_manager_->GetEntry(alias_url2));
+  prerender_manager_->SetNextPrerenderContents(pc);
+  prerender_manager_->AddSimplePreload(url);
+  EXPECT_EQ(pc, prerender_manager_->GetEntry(url));
+  pc->set_final_status(PrerenderContents::FINAL_STATUS_USED);
+  delete pc;
+}
diff --git a/chrome/browser/prerender/prerender_plt_recorder.cc b/chrome/browser/prerender/prerender_plt_recorder.cc
new file mode 100644
index 0000000..60b5da9
--- /dev/null
+++ b/chrome/browser/prerender/prerender_plt_recorder.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prerender/prerender_plt_recorder.h"
+
+#include "base/time.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/render_messages.h"
+
+PrerenderPLTRecorder::PrerenderPLTRecorder(TabContents* tab_contents)
+    : tab_contents_(tab_contents),
+      pplt_load_start_() {
+
+}
+
+PrerenderPLTRecorder::~PrerenderPLTRecorder() {
+}
+
+bool PrerenderPLTRecorder::OnMessageReceived(const IPC::Message& message) {
+  IPC_BEGIN_MESSAGE_MAP(PrerenderPLTRecorder, message)
+      IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
+                          OnDidStartProvisionalLoadForFrame)
+  IPC_END_MESSAGE_MAP()
+  return false;
+}
+
+void PrerenderPLTRecorder::OnDidStartProvisionalLoadForFrame(int64 frame_id,
+                                                             bool is_main_frame,
+                                                             const GURL& url) {
+  if (is_main_frame) {
+    // Record the beginning of a new PPLT navigation.
+    pplt_load_start_ = base::TimeTicks::Now();
+  }
+}
+
+void PrerenderPLTRecorder::DidStopLoading() {
+  // Compute the PPLT metric and report it in a histogram, if needed.
+  PrerenderManager* pm = tab_contents_->profile()->GetPrerenderManager();
+  if (pm != NULL && !pplt_load_start_.is_null())
+    pm->RecordPerceivedPageLoadTime(base::TimeTicks::Now() - pplt_load_start_);
+
+  // Reset the PPLT metric.
+  pplt_load_start_ = base::TimeTicks();
+}
diff --git a/chrome/browser/prerender/prerender_plt_recorder.h b/chrome/browser/prerender/prerender_plt_recorder.h
new file mode 100644
index 0000000..206fdf1
--- /dev/null
+++ b/chrome/browser/prerender/prerender_plt_recorder.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_PRERENDER_PRERENDER_PLT_RECORDER_H_
+#define CHROME_BROWSER_PRERENDER_PRERENDER_PLT_RECORDER_H_
+#pragma once
+
+#include <list>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+#include "googleurl/src/gurl.h"
+
+class PrerenderContents;
+class Profile;
+class TabContents;
+
+// PrerenderPLTRecorder is responsible for recording perceived pageload times
+// to compare PLT's with prerendering enabled and disabled.
+class PrerenderPLTRecorder : public TabContentsObserver {
+ public:
+  explicit PrerenderPLTRecorder(TabContents* tab_contents);
+  virtual ~PrerenderPLTRecorder();
+
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+  // Message handler.
+  void OnDidStartProvisionalLoadForFrame(int64 frame_id,
+                                         bool main_frame,
+                                         const GURL& url);
+
+  virtual void DidStopLoading();
+
+ private:
+  TabContents* tab_contents_;
+
+  // System time at which the current load was started for the purpose of
+  // the perceived page load time (PPLT).
+  base::TimeTicks pplt_load_start_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrerenderPLTRecorder);
+};
+
+#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_PLT_RECORDER_H_
diff --git a/chrome/browser/prerender/prerender_resource_handler.cc b/chrome/browser/prerender/prerender_resource_handler.cc
new file mode 100644
index 0000000..64b5184
--- /dev/null
+++ b/chrome/browser/prerender/prerender_resource_handler.cc
@@ -0,0 +1,153 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/prerender/prerender_resource_handler.h"
+
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/common/resource_response.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+
+namespace {
+
+bool ShouldPrerender(const GURL& url, const ResourceResponse* response) {
+  if (!response)
+    return false;
+  const ResourceResponseHead& rrh = response->response_head;
+  if (!url.is_valid())
+    return false;
+  if (!rrh.headers)
+    return false;
+  if (!(url.SchemeIs("http") || url.SchemeIs("https")))
+    return false;
+  if (rrh.mime_type != "text/html")
+    return false;
+  if (rrh.headers->response_code() != 200)
+    return false;
+  return true;
+}
+
+}  // namespace
+
+PrerenderResourceHandler* PrerenderResourceHandler::MaybeCreate(
+    const net::URLRequest& request,
+    ChromeURLRequestContext* context,
+    ResourceHandler* next_handler) {
+  if (!context || !context->prerender_manager())
+    return NULL;
+  if (!(request.load_flags() & net::LOAD_PREFETCH))
+    return NULL;
+  if (request.method() != "GET")
+    return NULL;
+  return new PrerenderResourceHandler(next_handler,
+                                      context->prerender_manager());
+}
+
+PrerenderResourceHandler::PrerenderResourceHandler(
+    ResourceHandler* next_handler,
+    PrerenderManager* prerender_manager)
+    : next_handler_(next_handler),
+      prerender_manager_(prerender_manager),
+      ALLOW_THIS_IN_INITIALIZER_LIST(
+          prerender_callback_(NewCallback(
+              this, &PrerenderResourceHandler::StartPrerender))) {
+  DCHECK(next_handler);
+  DCHECK(prerender_manager);
+}
+
+// This constructor is only used from unit tests.
+PrerenderResourceHandler::PrerenderResourceHandler(
+    ResourceHandler* next_handler,
+    PrerenderCallback* callback)
+    : next_handler_(next_handler),
+      prerender_callback_(callback) {
+  DCHECK(next_handler);
+  DCHECK(callback);
+}
+
+PrerenderResourceHandler::~PrerenderResourceHandler() {
+}
+
+bool PrerenderResourceHandler::OnUploadProgress(int request_id,
+                                                uint64 position,
+                                                uint64 size) {
+  return next_handler_->OnUploadProgress(request_id, position, size);
+}
+
+bool PrerenderResourceHandler::OnRequestRedirected(int request_id,
+                                                   const GURL& url,
+                                                   ResourceResponse* response,
+                                                   bool* defer) {
+  bool will_redirect = next_handler_->OnRequestRedirected(
+      request_id, url, response, defer);
+  if (will_redirect) {
+    alias_urls_.push_back(url);
+    url_ = url;
+  }
+  return will_redirect;
+}
+
+bool PrerenderResourceHandler::OnResponseStarted(int request_id,
+                                                 ResourceResponse* response) {
+  if (ShouldPrerender(url_, response)) {
+    BrowserThread::PostTask(
+        BrowserThread::UI,
+        FROM_HERE,
+        NewRunnableMethod(
+            this,
+            &PrerenderResourceHandler::RunCallbackFromUIThread,
+            url_,
+            alias_urls_));
+  }
+  return next_handler_->OnResponseStarted(request_id, response);
+}
+
+bool PrerenderResourceHandler::OnWillStart(int request_id,
+                                           const GURL& url,
+                                           bool* defer) {
+  bool will_start = next_handler_->OnWillStart(request_id, url, defer);
+  if (will_start) {
+    alias_urls_.push_back(url);
+    url_ = url;
+  }
+  return will_start;
+}
+
+bool PrerenderResourceHandler::OnWillRead(int request_id,
+                                          net::IOBuffer** buf,
+                                          int* buf_size,
+                                          int min_size) {
+  return next_handler_->OnWillRead(request_id, buf, buf_size, min_size);
+}
+
+bool PrerenderResourceHandler::OnReadCompleted(int request_id,
+                                               int* bytes_read) {
+  return next_handler_->OnReadCompleted(request_id, bytes_read);
+}
+
+bool PrerenderResourceHandler::OnResponseCompleted(
+    int request_id,
+    const net::URLRequestStatus& status,
+    const std::string& security_info) {
+  return next_handler_->OnResponseCompleted(request_id, status, security_info);
+}
+
+void PrerenderResourceHandler::OnRequestClosed() {
+  next_handler_->OnRequestClosed();
+}
+
+void PrerenderResourceHandler::RunCallbackFromUIThread(const GURL& url,
+                                                       const std::vector<GURL>&
+                                                       alias_urls) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  prerender_callback_->Run(url, alias_urls);
+}
+
+void PrerenderResourceHandler::StartPrerender(const GURL& url,
+                                              const std::vector<GURL>&
+                                              alias_urls) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  prerender_manager_->AddPreload(url, alias_urls);
+}
diff --git a/chrome/browser/prerender/prerender_resource_handler.h b/chrome/browser/prerender/prerender_resource_handler.h
new file mode 100644
index 0000000..b4f191e
--- /dev/null
+++ b/chrome/browser/prerender/prerender_resource_handler.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_RESOURCE_HANDLER_H_
+#define CHROME_BROWSER_PRERENDER_PRERENDER_RESOURCE_HANDLER_H_
+#pragma once
+
+#include <string>
+
+#include "base/callback.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/renderer_host/resource_handler.h"
+
+class ChromeURLRequestContext;
+namespace net {
+class URLRequest;
+}
+
+// The PrerenderResourceHandler initiates prerendering of web pages
+// under the following conditions:
+//   - The profile which initiated the request allows prerendering.
+//   - The initial request is a GET for a PREFETCH resource type.
+//   - The final URL (after redirects) has a scheme of http or https.
+//   - The response status code is a 200.
+//   - The MIME type of the response (sniffed or explicit) is text/html.
+class PrerenderResourceHandler : public ResourceHandler {
+ public:
+  // Creates a new PrerenderResourceHandler if appropriate for the
+  // given |request| and |context|, otherwise NULL is returned. The
+  // caller is resposible for deleting the returned handler.
+  //
+  // |next_handler| is the backup handler that this handler delegates to
+  // for the majority of the commands, and must be non-NULL.
+  static PrerenderResourceHandler* MaybeCreate(
+      const net::URLRequest& request,
+      ChromeURLRequestContext* context,
+      ResourceHandler* next_handler);
+
+  // OnResponseStarted will ask the |prerender_manager_| to start
+  // prerendering the requested resource if it is of an appropriate
+  // content type. The next handler is still invoked.
+  virtual bool OnResponseStarted(int request_id,
+                                 ResourceResponse* response);
+
+  // The following methods simply delegate to the next_handler.
+  virtual bool OnUploadProgress(int request_id,
+                                uint64 position,
+                                uint64 size);
+  virtual bool OnRequestRedirected(int request_id, const GURL& url,
+                                   ResourceResponse* response,
+                                   bool* defer);
+  virtual bool OnWillStart(int request_id, const GURL& url, bool* defer);
+
+  virtual bool OnWillRead(int request_id,
+                          net::IOBuffer** buf,
+                          int* buf_size,
+                          int min_size);
+
+  virtual bool OnReadCompleted(int request_id, int* bytes_read);
+
+  virtual bool OnResponseCompleted(int request_id,
+                                   const net::URLRequestStatus& status,
+                                   const std::string& security_info);
+
+  virtual void OnRequestClosed();
+
+ private:
+  friend class PrerenderResourceHandlerTest;
+  typedef Callback2<const GURL&, const std::vector<GURL>&>::Type
+      PrerenderCallback;
+
+  PrerenderResourceHandler(ResourceHandler* next_handler,
+                           PrerenderManager* prerender_manager);
+  PrerenderResourceHandler(ResourceHandler* next_handler,
+                           PrerenderCallback* callback);
+  virtual ~PrerenderResourceHandler();
+
+  void RunCallbackFromUIThread(const GURL& url,
+                               const std::vector<GURL>& alias_urls);
+  void StartPrerender(const GURL& url,
+                      const std::vector<GURL>& alias_urls);
+
+  // The set of URLs that are aliases to the URL to be prerendered,
+  // as a result of redirects.
+  std::vector<GURL> alias_urls_;
+  GURL url_;
+  scoped_refptr<ResourceHandler> next_handler_;
+  scoped_refptr<PrerenderManager> prerender_manager_;
+  scoped_ptr<PrerenderCallback> prerender_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrerenderResourceHandler);
+};
+
+#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_RESOURCE_HANDLER_H_
diff --git a/chrome/browser/prerender/prerender_resource_handler_unittest.cc b/chrome/browser/prerender/prerender_resource_handler_unittest.cc
new file mode 100644
index 0000000..6bc4c13
--- /dev/null
+++ b/chrome/browser/prerender/prerender_resource_handler_unittest.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/prerender/prerender_resource_handler.h"
+#include "chrome/common/resource_response.h"
+#include "net/http/http_response_headers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MockResourceHandler : public ResourceHandler {
+ public:
+  MockResourceHandler() {}
+
+  virtual bool OnUploadProgress(int request_id,
+                                uint64 position,
+                                uint64 size) {
+    return true;
+  }
+
+  virtual bool OnRequestRedirected(int request_id, const GURL& url,
+                                   ResourceResponse* response,
+                                   bool* defer) {
+    *defer = false;
+    return true;
+  }
+
+  virtual bool OnResponseStarted(int request_id,
+                                 ResourceResponse* response) {
+    return true;
+  }
+
+  virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) {
+    *defer = false;
+    return true;
+  }
+
+  virtual bool OnWillRead(int request_id,
+                          net::IOBuffer** buf,
+                          int* buf_size,
+                          int min_size) {
+    return true;
+  }
+
+  virtual bool OnReadCompleted(int request_id, int* bytes_read) {
+    return true;
+  }
+
+  virtual bool OnResponseCompleted(int request_id,
+                                   const net::URLRequestStatus& status,
+                                   const std::string& security_info) {
+    return true;
+  }
+
+  virtual void OnRequestClosed() {
+  }
+
+  virtual void OnDataDownloaded(int request_id, int bytes_downloaded) {}
+};
+
+// HttpResponseHeaders expects the raw input for it's constructor
+// to be a NUL ('\0') separated string for each line. This is a little
+// difficult to do for string literals, so this helper function accepts
+// newline-separated string literals and does the substitution. The
+// returned object is expected to be deleted by the caller.
+net::HttpResponseHeaders* CreateResponseHeaders(
+    const char* newline_separated_headers) {
+  std::string headers(newline_separated_headers);
+  std::string::iterator i = headers.begin();
+  std::string::iterator end = headers.end();
+  while (i != end) {
+    if (*i == '\n')
+      *i = '\0';
+    ++i;
+  }
+  return new net::HttpResponseHeaders(headers);
+}
+
+}  // namespace
+
+class PrerenderResourceHandlerTest : public testing::Test {
+ protected:
+  PrerenderResourceHandlerTest()
+      : ALLOW_THIS_IN_INITIALIZER_LIST(
+            pre_handler_(new PrerenderResourceHandler(
+                new MockResourceHandler(),
+                NewCallback(
+                    this,
+                    &PrerenderResourceHandlerTest::SetLastHandledURL)))),
+        ui_thread_(BrowserThread::UI, &loop_),
+        io_thread_(BrowserThread::IO, &loop_),
+        default_url_("http://www.prerender.com") {
+  }
+
+  virtual ~PrerenderResourceHandlerTest() {
+    // When a ResourceHandler's reference count drops to 0, it is not
+    // deleted immediately. Instead, a task is posted to the IO thread's
+    // message loop to delete it.
+    // So, drop the reference count to 0 and run the message loop once
+    // to ensure that all resources are cleaned up before the test exits.
+    pre_handler_ = NULL;
+    loop_.RunAllPending();
+  }
+
+  void SetLastHandledURL(const GURL& url, const std::vector<GURL>& alias_urls) {
+    last_handled_url_ = url;
+    alias_urls_ = alias_urls;
+  }
+
+  // Common logic shared by many of the tests
+  void StartPrerendering(const std::string& mime_type,
+                         const char* headers) {
+    int request_id = 1;
+    bool defer = false;
+    EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer));
+    EXPECT_FALSE(defer);
+    scoped_refptr<ResourceResponse> response(new ResourceResponse);
+    response->response_head.mime_type = mime_type;
+    response->response_head.headers = CreateResponseHeaders(headers);
+    EXPECT_TRUE(last_handled_url_.is_empty());
+
+    // Start the response. If it is able to prerender, a task will
+    // be posted to the UI thread and |SetLastHandledURL| will be called.
+    EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response));
+    loop_.RunAllPending();
+  }
+
+  // Test whether a given URL is part of alias_urls_.
+  bool ContainsAliasURL(const GURL& url) {
+    return std::find(alias_urls_.begin(), alias_urls_.end(), url)
+        != alias_urls_.end();
+  }
+
+  scoped_refptr<PrerenderResourceHandler> pre_handler_;
+  MessageLoop loop_;
+  BrowserThread ui_thread_;
+  BrowserThread io_thread_;
+  GURL last_handled_url_;
+  GURL default_url_;
+  std::vector<GURL> alias_urls_;
+};
+
+namespace {
+
+TEST_F(PrerenderResourceHandlerTest, NoOp) {
+}
+
+// Tests that a valid HTML resource will correctly get diverted
+// to the PrerenderManager.
+TEST_F(PrerenderResourceHandlerTest, Prerender) {
+  StartPrerendering("text/html",
+                    "HTTP/1.1 200 OK\n");
+  EXPECT_EQ(default_url_, last_handled_url_);
+}
+
+// Tests that the final request in a redirect chain will
+// get diverted to the PrerenderManager.
+TEST_F(PrerenderResourceHandlerTest, PrerenderRedirect) {
+  int request_id = 1;
+  GURL url_redirect("http://www.redirect.com");
+  bool defer = false;
+  EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer));
+  EXPECT_FALSE(defer);
+  EXPECT_TRUE(pre_handler_->OnRequestRedirected(request_id,
+                                                url_redirect,
+                                                NULL,
+                                                &defer));
+  EXPECT_FALSE(defer);
+  scoped_refptr<ResourceResponse> response(new ResourceResponse);
+  response->response_head.mime_type = "text/html";
+  response->response_head.headers = CreateResponseHeaders(
+      "HTTP/1.1 200 OK\n");
+  EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response));
+  EXPECT_TRUE(last_handled_url_.is_empty());
+  loop_.RunAllPending();
+  EXPECT_EQ(url_redirect, last_handled_url_);
+  EXPECT_EQ(true, ContainsAliasURL(url_redirect));
+  EXPECT_EQ(true, ContainsAliasURL(default_url_));
+  EXPECT_EQ(2, static_cast<int>(alias_urls_.size()));
+}
+
+}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
index cafad5a..73f5559 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
@@ -7,7 +7,6 @@
 #include <stack>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_process.h"
@@ -22,6 +21,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/service_messages.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // TODO(sanjeevr): Localize the product name?
 const char kCloudPrintProductName[] = "Google Cloud Print";
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
index d34d939..a290c96 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
 
-#include "app/gfx/font_util.h"
 #include "base/json/json_writer.h"
 #include "base/singleton.h"
 #include "base/string_util.h"
@@ -13,10 +12,7 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
-#if defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/html_dialog_gtk.h"
-#endif  // defined(TOOLKIT_GTK)
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
@@ -29,19 +25,17 @@
 #include "chrome/browser/service/service_process_control_manager.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_window.h"
-#if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/browser_dialogs.h"
-#endif  // defined(TOOLKIT_GTK)
 #include "chrome/common/net/gaia/gaia_auth_fetcher.h"
 #include "chrome/common/net/gaia/gaia_constants.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/service_messages.h"
-#include "gfx/font.h"
-
 #include "grit/chromium_strings.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_font_util.h"
+#include "ui/gfx/font.h"
 
 static const wchar_t kGaiaLoginIFrameXPath[] = L"//iframe[@id='gaialogin']";
 static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='setupdone']";
@@ -73,19 +67,13 @@
   // invoked in the context of a "token expired" notfication. If we don't have
   // a brower, use the underlying dialog system to show the dialog without
   // using a browser.
-  Browser* browser = BrowserList::GetLastActive();
-  if (browser) {
-    browser->BrowserShowHtmlDialog(flow, parent_window);
-  } else {
-#if defined(TOOLKIT_VIEWS)
-    browser::ShowHtmlDialogView(parent_window, profile, flow);
-#elif defined(TOOLKIT_GTK)
-    HtmlDialogGtk* html_dialog =
-        new HtmlDialogGtk(profile, flow, parent_window);
-    html_dialog->InitDialog();
-#endif  // defined(TOOLKIT_VIEWS)
-  // TODO(sanjeevr): Implement the "no browser" scenario for the Mac.
+  if (!parent_window) {
+    Browser* browser = BrowserList::GetLastActive();
+    if (browser && browser->window())
+      parent_window = browser->window()->GetNativeHandle();
   }
+  DCHECK(profile);
+  browser::ShowHtmlDialog(parent_window, profile, flow);
   return flow;
 }
 
@@ -93,18 +81,15 @@
                                          Profile* profile,
                                          Delegate* delegate,
                                          bool setup_done)
-    : dom_ui_(NULL),
+    : web_ui_(NULL),
       dialog_start_args_(args),
       setup_done_(setup_done),
       process_control_(NULL),
       delegate_(delegate) {
   // TODO(hclam): The data source should be added once.
   profile_ = profile;
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(new CloudPrintSetupSource())));
+  profile->GetChromeURLDataManager()->AddDataSource(
+      new CloudPrintSetupSource());
 }
 
 CloudPrintSetupFlow::~CloudPrintSetupFlow() {
@@ -121,8 +106,8 @@
   return GURL("chrome://cloudprintsetup/setupflow");
 }
 
-void CloudPrintSetupFlow::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void CloudPrintSetupFlow::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   // Create the message handler only after we are asked, the caller is
   // responsible for deleting the objects.
   handlers->push_back(
@@ -133,16 +118,16 @@
 void CloudPrintSetupFlow::GetDialogSize(gfx::Size* size) const {
   PrefService* prefs = profile_->GetPrefs();
   gfx::Font approximate_web_font(
-      UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
+      UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
       prefs->GetInteger(prefs::kWebKitDefaultFontSize));
 
   if (setup_done_) {
-    *size = gfx::GetLocalizedContentsSizeForFont(
+    *size = ui::GetLocalizedContentsSizeForFont(
         IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS,
         IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES,
         approximate_web_font);
   } else {
-    *size = gfx::GetLocalizedContentsSizeForFont(
+    *size = ui::GetLocalizedContentsSizeForFont(
         IDS_CLOUD_PRINT_SETUP_WIZARD_WIDTH_CHARS,
         IDS_CLOUD_PRINT_SETUP_WIZARD_HEIGHT_LINES,
         approximate_web_font);
@@ -208,8 +193,8 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 // Methods called by CloudPrintSetupMessageHandler
-void CloudPrintSetupFlow::Attach(DOMUI* dom_ui) {
-  dom_ui_ = dom_ui;
+void CloudPrintSetupFlow::Attach(WebUI* web_ui) {
+  web_ui_ = web_ui;
 }
 
 void CloudPrintSetupFlow::OnUserSubmittedAuth(const std::string& user,
@@ -230,22 +215,22 @@
 }
 
 void CloudPrintSetupFlow::OnUserClickedLearnMore() {
-  dom_ui_->tab_contents()->OpenURL(CloudPrintURL::GetCloudPrintLearnMoreURL(),
+  web_ui_->tab_contents()->OpenURL(CloudPrintURL::GetCloudPrintLearnMoreURL(),
                                    GURL(), NEW_FOREGROUND_TAB,
                                    PageTransition::LINK);
 }
 
 void CloudPrintSetupFlow::OnUserClickedPrintTestPage() {
-  dom_ui_->tab_contents()->OpenURL(CloudPrintURL::GetCloudPrintTestPageURL(),
+  web_ui_->tab_contents()->OpenURL(CloudPrintURL::GetCloudPrintTestPageURL(),
                                    GURL(), NEW_FOREGROUND_TAB,
                                    PageTransition::LINK);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Helper methods for showing contents of the DOM UI
+// Helper methods for showing contents of the Web UI
 void CloudPrintSetupFlow::ShowGaiaLogin(const DictionaryValue& args) {
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"cloudprint.showSetupLogin");
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"cloudprint.showSetupLogin");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
@@ -279,19 +264,19 @@
   std::wstring javascript = L"cloudprint.setMessage('" + message + L"');";
   ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
 
-  if (dom_ui_) {
+  if (web_ui_) {
     PrefService* prefs = profile_->GetPrefs();
     gfx::Font approximate_web_font(
-        UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
+        UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
         prefs->GetInteger(prefs::kWebKitDefaultFontSize));
-    gfx::Size done_size = gfx::GetLocalizedContentsSizeForFont(
+    gfx::Size done_size = ui::GetLocalizedContentsSizeForFont(
         IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS,
         IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES,
         approximate_web_font);
 
     FundamentalValue new_width(done_size.width());
     FundamentalValue new_height(done_size.height());
-    dom_ui_->CallJavascriptFunction(L"cloudprint.showSetupDone",
+    web_ui_->CallJavascriptFunction(L"cloudprint.showSetupDone",
                                     new_width, new_height);
   }
 
@@ -301,8 +286,9 @@
 void CloudPrintSetupFlow::ExecuteJavascriptInIFrame(
     const std::wstring& iframe_xpath,
     const std::wstring& js) {
-  if (dom_ui_) {
-    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
-    rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
+  if (web_ui_) {
+    RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
+    rvh->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath),
+                                     WideToUTF16Hack(js));
   }
 }
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
index 86077ab..032fa59 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,13 +8,13 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/time.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/common/net/gaia/gaia_auth_consumer.h"
 #include "chrome/common/net/gaia/gaia_auth_fetcher.h"
-#include "gfx/native_widget_types.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/native_widget_types.h"
 
 class GaiaAuthFetcher;
 class CloudPrintServiceProcessHelper;
@@ -31,14 +31,14 @@
 // 1. Showing the setup dialog.
 // 2. Providing the URL for the content of the dialog.
 // 3. Providing a data source to provide the content HTML files.
-// 4. Providing a message handler to handle user actions in the DOM UI.
+// 4. Providing a message handler to handle user actions in the Web UI.
 // 5. Responding to actions received in the message handler.
 //
-// The architecture for DOMUI is designed such that only the message handler
-// can access the DOMUI. This splits the flow control across the message
+// The architecture for WebUI is designed such that only the message handler
+// can access the WebUI. This splits the flow control across the message
 // handler and this class. In order to centralize all the flow control and
-// content in the DOMUI, the DOMUI object is given to this object by the
-// message handler through the Attach(DOMUI*) method.
+// content in the WebUI, the WebUI object is given to this object by the
+// message handler through the Attach(WebUI*) method.
 class CloudPrintSetupFlow : public HtmlDialogUIDelegate,
                             public GaiaAuthConsumer {
  public:
@@ -62,8 +62,8 @@
 
   // HtmlDialogUIDelegate implementation.
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
@@ -88,8 +88,8 @@
 
   // Called CloudPrintSetupMessageHandler when a DOM is attached. This method
   // is called when the HTML page is fully loaded. We then operate on this
-  // DOMUI object directly.
-  void Attach(DOMUI* dom_ui);
+  // WebUI object directly.
+  void Attach(WebUI* web_ui);
 
   // Called by CloudPrintSetupMessageHandler when user authentication is
   // registered.
@@ -110,9 +110,9 @@
   void ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath,
                                  const std::wstring& js);
 
-  // Pointer to the DOM UI. This is provided by CloudPrintSetupMessageHandler
+  // Pointer to the Web UI. This is provided by CloudPrintSetupMessageHandler
   // when attached.
-  DOMUI* dom_ui_;
+  WebUI* web_ui_;
 
   // The args to pass to the initial page.
   std::string dialog_start_args_;
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
index 0bbd25d..fb933e7 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,26 +7,26 @@
 #include "base/scoped_ptr.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
 
-DOMMessageHandler* CloudPrintSetupMessageHandler::Attach(DOMUI* dom_ui) {
-  // Pass the DOMUI object to the setup flow.
-  flow_->Attach(dom_ui);
-  return DOMMessageHandler::Attach(dom_ui);
+WebUIMessageHandler* CloudPrintSetupMessageHandler::Attach(WebUI* web_ui) {
+  // Pass the WebUI object to the setup flow.
+  flow_->Attach(web_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void CloudPrintSetupMessageHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("SubmitAuth",
+  web_ui_->RegisterMessageCallback("SubmitAuth",
       NewCallback(this, &CloudPrintSetupMessageHandler::HandleSubmitAuth));
-  dom_ui_->RegisterMessageCallback("PrintTestPage",
+  web_ui_->RegisterMessageCallback("PrintTestPage",
       NewCallback(this, &CloudPrintSetupMessageHandler::HandlePrintTestPage));
-  dom_ui_->RegisterMessageCallback("LearnMore",
+  web_ui_->RegisterMessageCallback("LearnMore",
       NewCallback(this, &CloudPrintSetupMessageHandler::HandleLearnMore));
 }
 
 void CloudPrintSetupMessageHandler::HandleSubmitAuth(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
   std::string username, password, captcha;
   if (json.empty())
     return;
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
index 958f537..1dabefe 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,17 +13,17 @@
 class CloudPrintSetupFlow;
 
 // This class is used to handle DOM messages from the setup dialog.
-class CloudPrintSetupMessageHandler : public DOMMessageHandler {
+class CloudPrintSetupMessageHandler : public WebUIMessageHandler {
  public:
   explicit CloudPrintSetupMessageHandler(CloudPrintSetupFlow* flow)
     : flow_(flow) {}
   virtual ~CloudPrintSetupMessageHandler() {}
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
 
  protected:
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callbacks from the page.
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
index 972f088..1159dbb 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
@@ -6,13 +6,10 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/google/google_util.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "googleurl/src/gurl.h"
 #include "grit/app_resources.h"
@@ -20,6 +17,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Define the values of standard URLs.
 const char CloudPrintSetupSource::kInvalidPasswordHelpUrl[] =
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
index 10dcd8a..5fe7637 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
@@ -1,47 +1,47 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-#include "app/l10n_util.h"

-#include "grit/app_resources.h"

-#include "grit/browser_resources.h"

-#include "grit/chromium_strings.h"

-#include "grit/generated_resources.h"

-#include "grit/locale_settings.h"

-#include "testing/gtest/include/gtest/gtest.h"

-#include "testing/gmock/include/gmock/gmock.h"

-

-using testing::HasSubstr;

-using testing::Not;

-

-void TestStringStillOkForCloudPrint(int resource_id) {

-  std::string resource_string = l10n_util::GetStringUTF8(resource_id);

-  EXPECT_THAT(resource_string, Not(HasSubstr("Sync")));

-  EXPECT_THAT(resource_string, Not(HasSubstr("sync")));

-}

-

-// This set of strings to test was generated from

-// CloudPrintSetupSource::StartDataRequest.  If any of these trip, notify the

-// cloud printing team and we'll split the strings.

-TEST(CloudPrintResources, SharedStringsCheck) {

-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SIGNIN_PREFIX);

-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SIGNIN_SUFFIX);

-  TestStringStillOkForCloudPrint(IDS_SYNC_CANNOT_BE_BLANK);

-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_EMAIL);

-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_PASSWORD);

-  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_USER_CREDENTIALS);

-  TestStringStillOkForCloudPrint(IDS_SYNC_SIGNIN);

-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_COULD_NOT_CONNECT);

-  TestStringStillOkForCloudPrint(IDS_SYNC_CANNOT_ACCESS_ACCOUNT);

-  TestStringStillOkForCloudPrint(IDS_SYNC_CREATE_ACCOUNT);

-  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SETTING_UP);

-  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);

-  TestStringStillOkForCloudPrint(IDS_SYNC_ERROR_SIGNING_IN);

-  TestStringStillOkForCloudPrint(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS);

-  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_ACCESS_CODE_LABEL);

-  TestStringStillOkForCloudPrint(IDS_SYNC_ENTER_ACCESS_CODE_LABEL);

-  TestStringStillOkForCloudPrint(IDS_SYNC_ACCESS_CODE_HELP_LABEL);

-  TestStringStillOkForCloudPrint(IDS_SYNC_GET_ACCESS_CODE_URL);

-  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);

-  TestStringStillOkForCloudPrint(IDS_SYNC_SETUP_OK_BUTTON_LABEL);

-}

+// Copyright (c) 2011 The Chromium 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 "grit/app_resources.h"
+#include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using testing::HasSubstr;
+using testing::Not;
+
+void TestStringStillOkForCloudPrint(int resource_id) {
+  std::string resource_string = l10n_util::GetStringUTF8(resource_id);
+  EXPECT_THAT(resource_string, Not(HasSubstr("Sync")));
+  EXPECT_THAT(resource_string, Not(HasSubstr("sync")));
+}
+
+// This set of strings to test was generated from
+// CloudPrintSetupSource::StartDataRequest.  If any of these trip, notify the
+// cloud printing team and we'll split the strings.
+TEST(CloudPrintResources, SharedStringsCheck) {
+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SIGNIN_PREFIX);
+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SIGNIN_SUFFIX);
+  TestStringStillOkForCloudPrint(IDS_SYNC_CANNOT_BE_BLANK);
+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_EMAIL);
+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_PASSWORD);
+  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_USER_CREDENTIALS);
+  TestStringStillOkForCloudPrint(IDS_SYNC_SIGNIN);
+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_COULD_NOT_CONNECT);
+  TestStringStillOkForCloudPrint(IDS_SYNC_CANNOT_ACCESS_ACCOUNT);
+  TestStringStillOkForCloudPrint(IDS_SYNC_CREATE_ACCOUNT);
+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SETTING_UP);
+  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);
+  TestStringStillOkForCloudPrint(IDS_SYNC_ERROR_SIGNING_IN);
+  TestStringStillOkForCloudPrint(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS);
+  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_ACCESS_CODE_LABEL);
+  TestStringStillOkForCloudPrint(IDS_SYNC_ENTER_ACCESS_CODE_LABEL);
+  TestStringStillOkForCloudPrint(IDS_SYNC_ACCESS_CODE_HELP_LABEL);
+  TestStringStillOkForCloudPrint(IDS_SYNC_GET_ACCESS_CODE_URL);
+  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);
+  TestStringStillOkForCloudPrint(IDS_SYNC_SETUP_OK_BUTTON_LABEL);
+}
diff --git a/chrome/browser/printing/print_dialog_cloud.cc b/chrome/browser/printing/print_dialog_cloud.cc
index 95248a9..5869ff7 100644
--- a/chrome/browser/printing/print_dialog_cloud.cc
+++ b/chrome/browser/printing/print_dialog_cloud.cc
@@ -1,11 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/printing/print_dialog_cloud.h"
 #include "chrome/browser/printing/print_dialog_cloud_internal.h"
 
-#include "app/l10n_util.h"
 #include "base/base64.h"
 #include "base/file_util.h"
 #include "base/json/json_reader.h"
@@ -13,21 +12,23 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/debugger/devtools_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/common/notification_observer.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/common/url_constants.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/glue/webpreferences.h"
 
 #include "grit/generated_resources.h"
@@ -44,7 +45,7 @@
 // PrintDialogCloud::CreatePrintDialogForPdf is called from
 // resource_message_filter_gtk.cc once the renderer has informed the
 // renderer host that PDF generation into the renderer host provided
-// temp file has been completed.  That call is on the IO thread.
+// temp file has been completed.  That call is on the FILE thread.
 // That, in turn, hops over to the UI thread to create an instance of
 // PrintDialogCloud.
 
@@ -52,7 +53,7 @@
 // CloudPrintHtmlDialogDelegate and asks the current active browser to
 // show an HTML dialog using that class as the delegate. That class
 // hands in the kCloudPrintResourcesURL as the URL to visit.  That is
-// recognized by the GetDOMUIFactoryFunction as a signal to create an
+// recognized by the GetWebUIFactoryFunction as a signal to create an
 // ExternalHtmlDialogUI.
 
 // CloudPrintHtmlDialogDelegate also temporarily owns a
@@ -61,13 +62,13 @@
 // print data and getting any page setup parameters that the dialog
 // contents provides.  As part of bringing up the dialog,
 // HtmlDialogUI::RenderViewCreated is called (an override of
-// DOMUI::RenderViewCreated).  That routine, in turn, calls the
-// delegate's GetDOMMessageHandlers routine, at which point the
+// WebUI::RenderViewCreated).  That routine, in turn, calls the
+// delegate's GetWebUIMessageHandlers routine, at which point the
 // ownership of the CloudPrintFlowHandler is handed over.  A pointer
 // to the flow handler is kept to facilitate communication back and
 // forth between the two classes.
 
-// The DOMUI continues dialog bring-up, calling
+// The WebUI continues dialog bring-up, calling
 // CloudPrintFlowHandler::RegisterMessages.  This is where the
 // additional object model capabilities are registered for the dialog
 // contents to use.  It is also at this time that capabilities for the
@@ -97,10 +98,10 @@
 
 namespace internal_cloud_print_helpers {
 
-bool GetRealOrInt(const DictionaryValue& dictionary,
-                  const std::string& path,
-                  double* out_value) {
-  if (!dictionary.GetReal(path, out_value)) {
+bool GetDoubleOrInt(const DictionaryValue& dictionary,
+                    const std::string& path,
+                    double* out_value) {
+  if (!dictionary.GetDouble(path, out_value)) {
     int int_value = 0;
     if (!dictionary.GetInteger(path, &int_value))
       return false;
@@ -122,33 +123,33 @@
 
   bool result = true;
   DictionaryValue* params = static_cast<DictionaryValue*>(parsed_value.get());
-  result &= GetRealOrInt(*params, "dpi", &parameters.dpi);
-  result &= GetRealOrInt(*params, "min_shrink", &parameters.min_shrink);
-  result &= GetRealOrInt(*params, "max_shrink", &parameters.max_shrink);
+  result &= GetDoubleOrInt(*params, "dpi", &parameters.dpi);
+  result &= GetDoubleOrInt(*params, "min_shrink", &parameters.min_shrink);
+  result &= GetDoubleOrInt(*params, "max_shrink", &parameters.max_shrink);
   result &= params->GetBoolean("selection_only", &parameters.selection_only);
   return result;
 }
 
 void CloudPrintDataSenderHelper::CallJavascriptFunction(
     const std::wstring& function_name) {
-  dom_ui_->CallJavascriptFunction(function_name);
+  web_ui_->CallJavascriptFunction(function_name);
 }
 
 void CloudPrintDataSenderHelper::CallJavascriptFunction(
     const std::wstring& function_name, const Value& arg) {
-  dom_ui_->CallJavascriptFunction(function_name, arg);
+  web_ui_->CallJavascriptFunction(function_name, arg);
 }
 
 void CloudPrintDataSenderHelper::CallJavascriptFunction(
     const std::wstring& function_name, const Value& arg1, const Value& arg2) {
-  dom_ui_->CallJavascriptFunction(function_name, arg1, arg2);
+  web_ui_->CallJavascriptFunction(function_name, arg1, arg2);
 }
 
 // Clears out the pointer we're using to communicate.  Either routine is
 // potentially expensive enough that stopping whatever is in progress
 // is worth it.
 void CloudPrintDataSender::CancelPrintDataFile() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   // We don't own helper, it was passed in to us, so no need to
   // delete, just let it go.
   helper_ = NULL;
@@ -202,7 +203,7 @@
 // needed. - 4/1/2010
 void CloudPrintDataSender::SendPrintDataFile() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (helper_ && print_data_.get()) {
     StringValue title(print_job_title_);
 
@@ -229,7 +230,7 @@
 
 void CloudPrintFlowHandler::SetDialogDelegate(
     CloudPrintHtmlDialogDelegate* delegate) {
-  // Even if setting a new dom_ui, it means any previous task needs
+  // Even if setting a new WebUI, it means any previous task needs
   // to be cancelled, it's now invalid.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   CancelAnyRunningTask();
@@ -248,28 +249,28 @@
 }
 
 void CloudPrintFlowHandler::RegisterMessages() {
-  if (!dom_ui_)
+  if (!web_ui_)
     return;
 
   // TODO(scottbyer) - This is where we will register messages for the
   // UI JS to use.  Needed: Call to update page setup parameters.
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "ShowDebugger",
       NewCallback(this, &CloudPrintFlowHandler::HandleShowDebugger));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "SendPrintData",
       NewCallback(this, &CloudPrintFlowHandler::HandleSendPrintData));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "SetPageParameters",
       NewCallback(this, &CloudPrintFlowHandler::HandleSetPageParameters));
 
-  if (dom_ui_->tab_contents()) {
+  if (web_ui_->tab_contents()) {
     // Also, take the opportunity to set some (minimal) additional
     // script permissions required for the web UI.
 
     // TODO(scottbyer): learn how to make sure we're talking to the
     // right web site first.
-    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
+    RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
     if (rvh && rvh->delegate()) {
       WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
       webkit_prefs.allow_scripts_to_close_windows = true;
@@ -279,11 +280,11 @@
     // Register for appropriate notifications, and re-direct the URL
     // to the real server URL, now that we've gotten an HTML dialog
     // going.
-    NavigationController* controller = &dom_ui_->tab_contents()->controller();
+    NavigationController* controller = &web_ui_->tab_contents()->controller();
     NavigationEntry* pending_entry = controller->pending_entry();
     if (pending_entry)
       pending_entry->set_url(CloudPrintURL(
-          dom_ui_->GetProfile()).GetCloudPrintServiceDialogURL());
+          web_ui_->GetProfile()).GetCloudPrintServiceDialogURL());
     registrar_.Add(this, NotificationType::LOAD_STOP,
                    Source<NavigationController>(controller));
   }
@@ -308,8 +309,8 @@
 }
 
 void CloudPrintFlowHandler::ShowDebugger() {
-  if (dom_ui_) {
-    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
+  if (web_ui_) {
+    RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
     if (rvh)
       DevToolsManager::GetInstance()->OpenDevToolsWindow(rvh);
   }
@@ -317,8 +318,8 @@
 
 scoped_refptr<CloudPrintDataSender>
 CloudPrintFlowHandler::CreateCloudPrintDataSender() {
-  DCHECK(dom_ui_);
-  print_data_helper_.reset(new CloudPrintDataSenderHelper(dom_ui_));
+  DCHECK(web_ui_);
+  print_data_helper_.reset(new CloudPrintDataSenderHelper(web_ui_));
   return new CloudPrintDataSender(print_data_helper_.get(), print_job_title_);
 }
 
@@ -329,7 +330,7 @@
   // setup parameters becomes asynchronous and may be set while some
   // data is in flight).  Then we can clear out the print data.
   CancelAnyRunningTask();
-  if (dom_ui_) {
+  if (web_ui_) {
     print_data_sender_ = CreateCloudPrintDataSender();
     BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                             NewRunnableMethod(
@@ -340,7 +341,7 @@
 }
 
 void CloudPrintFlowHandler::HandleSetPageParameters(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
   if (json.empty())
     return;
 
@@ -380,11 +381,11 @@
 }
 
 void CloudPrintFlowHandler::StoreDialogClientSize() const {
-  if (dom_ui_ && dom_ui_->tab_contents() && dom_ui_->tab_contents()->view()) {
-    gfx::Size size = dom_ui_->tab_contents()->view()->GetContainerSize();
-    dom_ui_->GetProfile()->GetPrefs()->SetInteger(
+  if (web_ui_ && web_ui_->tab_contents() && web_ui_->tab_contents()->view()) {
+    gfx::Size size = web_ui_->tab_contents()->view()->GetContainerSize();
+    web_ui_->GetProfile()->GetPrefs()->SetInteger(
         prefs::kCloudPrintDialogWidth, size.width());
-    dom_ui_->GetProfile()->GetPrefs()->SetInteger(
+    web_ui_->GetProfile()->GetPrefs()->SetInteger(
         prefs::kCloudPrintDialogHeight, size.height());
   }
 }
@@ -393,32 +394,40 @@
     const FilePath& path_to_pdf,
     int width, int height,
     const std::string& json_arguments,
-    const string16& print_job_title)
+    const string16& print_job_title,
+    bool modal)
     : flow_handler_(new CloudPrintFlowHandler(path_to_pdf, print_job_title)),
+      modal_(modal),
       owns_flow_handler_(true) {
   Init(width, height, json_arguments);
 }
 
+// For unit testing.
 CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
     CloudPrintFlowHandler* flow_handler,
     int width, int height,
-    const std::string& json_arguments)
+    const std::string& json_arguments,
+    bool modal)
     : flow_handler_(flow_handler),
+      modal_(modal),
       owns_flow_handler_(true) {
   Init(width, height, json_arguments);
 }
 
-void CloudPrintHtmlDialogDelegate::Init(
-    int width, int height, const std::string& json_arguments) {
+void CloudPrintHtmlDialogDelegate::Init(int width, int height,
+                                        const std::string& json_arguments) {
   // This information is needed to show the dialog HTML content.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  std::string cloud_print_url(chrome::kCloudPrintResourcesURL);
-  params_.url = GURL(cloud_print_url);
+  params_.url = GURL(chrome::kCloudPrintResourcesURL);
   params_.height = height;
   params_.width = width;
   params_.json_input = json_arguments;
 
   flow_handler_->SetDialogDelegate(this);
+  // If we're not modal we can show the dialog with no browser.
+  // We need this to keep Chrome alive while our dialog is up.
+  if (!modal_)
+    BrowserList::StartKeepAlive();
 }
 
 CloudPrintHtmlDialogDelegate::~CloudPrintHtmlDialogDelegate() {
@@ -432,7 +441,7 @@
 }
 
 bool CloudPrintHtmlDialogDelegate::IsDialogModal() const {
-  return true;
+    return modal_;
 }
 
 std::wstring CloudPrintHtmlDialogDelegate::GetDialogTitle() const {
@@ -443,8 +452,8 @@
   return params_.url;
 }
 
-void CloudPrintHtmlDialogDelegate::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void CloudPrintHtmlDialogDelegate::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   handlers->push_back(flow_handler_);
   // We don't own flow_handler_ anymore, but it sticks around until at
   // least right after OnDialogClosed() is called (and this object is
@@ -465,6 +474,10 @@
     const std::string& json_retval) {
   // Get the final dialog size and store it.
   flow_handler_->StoreDialogClientSize();
+  // If we're modal we can show the dialog with no browser.
+  // End the keep-alive so that Chrome can exit.
+  if (!modal_)
+    BrowserList::EndKeepAlive();
   delete this;
 }
 
@@ -478,7 +491,7 @@
   return false;
 }
 
-}  // end of namespace internal_cloud_print_helpers
+}  // namespace internal_cloud_print_helpers
 
 // static, called on the IO thread.  This is the main entry point into
 // creating the dialog.
@@ -486,34 +499,58 @@
 // TODO(scottbyer): The signature here will need to change as the
 // workflow through the printing code changes to allow for dynamically
 // changing page setup parameters while the dialog is active.
-void PrintDialogCloud::CreatePrintDialogForPdf(const FilePath& path_to_pdf) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+void PrintDialogCloud::CreatePrintDialogForPdf(const FilePath& path_to_pdf,
+                                               const string16& print_job_title,
+                                               bool modal) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE) ||
+         BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      NewRunnableFunction(&PrintDialogCloud::CreateDialogImpl, path_to_pdf));
+      NewRunnableFunction(&PrintDialogCloud::CreateDialogImpl,
+                          path_to_pdf,
+                          print_job_title,
+                          modal));
 }
 
 // static, called from the UI thread.
-void PrintDialogCloud::CreateDialogImpl(const FilePath& path_to_pdf) {
+void PrintDialogCloud::CreateDialogImpl(const FilePath& path_to_pdf,
+                                        const string16& print_job_title,
+                                        bool modal) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  new PrintDialogCloud(path_to_pdf);
+  new PrintDialogCloud(path_to_pdf, print_job_title, modal);
 }
 
 // Initialize the print dialog.  Called on the UI thread.
-PrintDialogCloud::PrintDialogCloud(const FilePath& path_to_pdf)
+PrintDialogCloud::PrintDialogCloud(const FilePath& path_to_pdf,
+                                   const string16& print_job_title,
+                                   bool modal)
     : browser_(BrowserList::GetLastActive()) {
+  Init(path_to_pdf, print_job_title, modal);
+}
 
+PrintDialogCloud::~PrintDialogCloud() {
+}
+
+void PrintDialogCloud::Init(const FilePath& path_to_pdf,
+                            const string16& print_job_title,
+                            bool modal) {
   // TODO(scottbyer): Verify GAIA login valid, execute GAIA login if not (should
   // be distilled out of bookmark sync.)
-  string16 print_job_title;
-  if (browser_ && browser_->GetSelectedTabContents())
-    print_job_title = browser_->GetSelectedTabContents()->GetTitle();
-
   const int kDefaultWidth = 497;
   const int kDefaultHeight = 332;
-
-  PrefService* pref_service = browser_->GetProfile()->GetPrefs();
+  string16 job_title = print_job_title;
+  Profile* profile = NULL;
+  if (modal) {
+    DCHECK(browser_);
+    if (job_title.empty() && browser_->GetSelectedTabContents())
+      job_title = browser_->GetSelectedTabContents()->GetTitle();
+    profile = browser_->GetProfile();
+  } else {
+    profile = ProfileManager::GetDefaultProfile();
+  }
+  DCHECK(profile);
+  PrefService* pref_service = profile->GetPrefs();
   DCHECK(pref_service);
   if (!pref_service->FindPreference(prefs::kCloudPrintDialogWidth)) {
     pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogWidth,
@@ -526,11 +563,14 @@
 
   int width = pref_service->GetInteger(prefs::kCloudPrintDialogWidth);
   int height = pref_service->GetInteger(prefs::kCloudPrintDialogHeight);
+
   HtmlDialogUIDelegate* dialog_delegate =
       new internal_cloud_print_helpers::CloudPrintHtmlDialogDelegate(
-          path_to_pdf, width, height, std::string(), print_job_title);
-  browser_->BrowserShowHtmlDialog(dialog_delegate, NULL);
-}
-
-PrintDialogCloud::~PrintDialogCloud() {
+          path_to_pdf, width, height, std::string(), job_title, modal);
+  if (modal) {
+    DCHECK(browser_);
+    browser_->BrowserShowHtmlDialog(dialog_delegate, NULL);
+  } else {
+    browser::ShowHtmlDialog(NULL, profile, dialog_delegate);
+  }
 }
diff --git a/chrome/browser/printing/print_dialog_cloud.h b/chrome/browser/printing/print_dialog_cloud.h
index 28b2663..01fc5c9 100644
--- a/chrome/browser/printing/print_dialog_cloud.h
+++ b/chrome/browser/printing/print_dialog_cloud.h
@@ -7,28 +7,39 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
+#include "base/string16.h"
 
 class Browser;
 class FilePath;
+
 namespace IPC {
 class Message;
 }
 
 class PrintDialogCloud {
  public:
-  // Called on the IO thread.
-  static void CreatePrintDialogForPdf(const FilePath& path_to_pdf);
+  // Called on the IO or UI thread.
+  static void CreatePrintDialogForPdf(const FilePath& path_to_pdf,
+                                      const string16& print_job_title,
+                                      bool modal);
 
  private:
   friend class PrintDialogCloudTest;
 
-  explicit PrintDialogCloud(const FilePath& path_to_pdf);
+  explicit PrintDialogCloud(const FilePath& path_to_pdf,
+                            const string16& print_job_title,
+                            bool modal);
   ~PrintDialogCloud();
 
+  void Init(const FilePath& path_to_pdf,
+            const string16& print_job_title,
+            bool modal);
+
   // Called as a task from the UI thread, creates an object instance
   // to run the HTML/JS based print dialog for printing through the cloud.
-  static void CreateDialogImpl(const FilePath& path_to_pdf);
+  static void CreateDialogImpl(const FilePath& path_to_pdf,
+                               const string16& print_job_title,
+                               bool modal);
 
   Browser* browser_;
 
diff --git a/chrome/browser/printing/print_dialog_cloud_internal.h b/chrome/browser/printing/print_dialog_cloud_internal.h
index 9c83154..927bf2a 100644
--- a/chrome/browser/printing/print_dialog_cloud_internal.h
+++ b/chrome/browser/printing/print_dialog_cloud_internal.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,10 +10,10 @@
 #include <vector>
 
 #include "base/file_path.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
@@ -26,10 +26,10 @@
 // Small class to virtualize a few functions to aid with unit testing.
 class CloudPrintDataSenderHelper {
  public:
-  explicit CloudPrintDataSenderHelper(DOMUI* dom_ui) : dom_ui_(dom_ui) {}
+  explicit CloudPrintDataSenderHelper(WebUI* web_ui) : web_ui_(web_ui) {}
   virtual ~CloudPrintDataSenderHelper() {}
 
-  // Virtualize the overrides of these three functions from DOMUI to
+  // Virtualize the overrides of these three functions from WebUI to
   // facilitate unit testing.
   virtual void CallJavascriptFunction(const std::wstring& function_name);
   virtual void CallJavascriptFunction(const std::wstring& function_name,
@@ -39,7 +39,7 @@
                                       const Value& arg2);
 
  private:
-  DOMUI* dom_ui_;
+  WebUI* web_ui_;
 
   DISALLOW_COPY_AND_ASSIGN(CloudPrintDataSenderHelper);
 };
@@ -70,7 +70,7 @@
   friend class base::RefCountedThreadSafe<CloudPrintDataSender>;
   virtual ~CloudPrintDataSender();
 
-  Lock lock_;
+  base::Lock lock_;
   CloudPrintDataSenderHelper* volatile helper_;
   scoped_ptr<StringValue> print_data_;
   string16 print_job_title_;
@@ -81,20 +81,20 @@
 class CloudPrintHtmlDialogDelegate;
 
 // The CloudPrintFlowHandler connects the state machine (the UI delegate)
-// to the dialog backing HTML and JS by providing DOMMessageHandler
+// to the dialog backing HTML and JS by providing WebUIMessageHandler
 // functions for the JS to use.  This include refreshing the page
 // setup parameters (which will cause a re-generation of the PDF in
 // the renderer process - do we want a progress throbber shown?
 // Probably..), and packing up the PDF and job parameters and sending
 // them to the cloud.
-class CloudPrintFlowHandler : public DOMMessageHandler,
+class CloudPrintFlowHandler : public WebUIMessageHandler,
                               public NotificationObserver {
  public:
   explicit CloudPrintFlowHandler(const FilePath& path_to_pdf,
                                  const string16& print_job_title);
   virtual ~CloudPrintFlowHandler();
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // NotificationObserver implementation.
@@ -107,18 +107,18 @@
   void HandleSendPrintData(const ListValue* args);
   void HandleSetPageParameters(const ListValue* args);
 
+  virtual void SetDialogDelegate(CloudPrintHtmlDialogDelegate *delegate);
+  void StoreDialogClientSize() const;
+
+ private:
+  virtual scoped_refptr<CloudPrintDataSender> CreateCloudPrintDataSender();
+
   // Call to get the debugger loaded on our hosted dialog page
   // specifically.  Since we're not in an official browser tab, only
   // way to get the debugger going.
   void ShowDebugger();
 
-  virtual void SetDialogDelegate(CloudPrintHtmlDialogDelegate *delegate);
   void CancelAnyRunningTask();
-  void StoreDialogClientSize() const;
-
- private:
-  // For unit testing.
-  virtual scoped_refptr<CloudPrintDataSender> CreateCloudPrintDataSender();
 
   CloudPrintHtmlDialogDelegate* dialog_delegate_;
   NotificationRegistrar registrar_;
@@ -138,15 +138,16 @@
   CloudPrintHtmlDialogDelegate(const FilePath& path_to_pdf,
                                int width, int height,
                                const std::string& json_arguments,
-                               const string16& print_job_title);
+                               const string16& print_job_title,
+                               bool modal);
   virtual ~CloudPrintHtmlDialogDelegate();
 
   // HTMLDialogUIDelegate implementation:
   virtual bool IsDialogModal() const;
   virtual std::wstring GetDialogTitle() const;
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
@@ -156,12 +157,15 @@
  private:
   friend class ::CloudPrintHtmlDialogDelegateTest;
 
+  // For unit testing.
   CloudPrintHtmlDialogDelegate(CloudPrintFlowHandler* flow_handler,
                                int width, int height,
-                               const std::string& json_arguments);
+                               const std::string& json_arguments,
+                               bool modal);
   void Init(int width, int height, const std::string& json_arguments);
 
   CloudPrintFlowHandler* flow_handler_;
+  bool modal_;
   mutable bool owns_flow_handler_;
 
   // The parameters needed to display a modal HTML dialog.
diff --git a/chrome/browser/printing/print_dialog_cloud_uitest.cc b/chrome/browser/printing/print_dialog_cloud_uitest.cc
index aee03ee..caced65 100644
--- a/chrome/browser/printing/print_dialog_cloud_uitest.cc
+++ b/chrome/browser/printing/print_dialog_cloud_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include "base/path_service.h"
 #include "base/singleton.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_thread.h"
@@ -25,7 +26,7 @@
 #include "chrome/test/ui_test_utils.h"
 #include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_test_job.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 
 namespace {
 
@@ -59,14 +60,14 @@
 
 // A simple test net::URLRequestJob. We don't care what it does, only that
 // whether it starts and finishes.
-class SimpleTestJob : public URLRequestTestJob {
+class SimpleTestJob : public net::URLRequestTestJob {
  public:
   explicit SimpleTestJob(net::URLRequest* request)
-      : URLRequestTestJob(request, test_headers(),
-                          TestData::GetInstance()->GetTestData(), true) {}
+      : net::URLRequestTestJob(request, test_headers(),
+                               TestData::GetInstance()->GetTestData(), true) {}
 
   virtual void GetResponseInfo(net::HttpResponseInfo* info) {
-    URLRequestTestJob::GetResponseInfo(info);
+    net::URLRequestTestJob::GetResponseInfo(info);
     if (request_->url().SchemeIsSecure()) {
       // Make up a fake certificate for this response since we don't have
       // access to the real SSL info.
@@ -198,7 +199,10 @@
         test_data_directory_.AppendASCII("printing/cloud_print_uitest.pdf");
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        NewRunnableFunction(&PrintDialogCloud::CreateDialogImpl, path_to_pdf));
+        NewRunnableFunction(&PrintDialogCloud::CreateDialogImpl,
+                            path_to_pdf,
+                            string16(),
+                            true));
   }
 
   bool handler_added_;
@@ -246,9 +250,9 @@
   ASSERT_TRUE(browser()->GetSelectedTabContents());
   ASSERT_TRUE(browser()->GetSelectedTabContents()->render_view_host());
 
-  std::wstring window_print(L"window.print()");
+  string16 window_print = ASCIIToUTF16("window.print()");
   browser()->GetSelectedTabContents()->render_view_host()->
-      ExecuteJavascriptInWebFrame(std::wstring(), window_print);
+      ExecuteJavascriptInWebFrame(string16(), window_print);
 
   ui_test_utils::RunMessageLoop();
 
diff --git a/chrome/browser/printing/print_dialog_cloud_unittest.cc b/chrome/browser/printing/print_dialog_cloud_unittest.cc
index ef9fe33..cdb34ee 100644
--- a/chrome/browser/printing/print_dialog_cloud_unittest.cc
+++ b/chrome/browser/printing/print_dialog_cloud_unittest.cc
@@ -1,10 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/printing/print_dialog_cloud.h"
 #include "chrome/browser/printing/print_dialog_cloud_internal.h"
 
+#include <string>
+#include <vector>
+
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
@@ -16,8 +19,6 @@
 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/notification_details.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/url_constants.h"
@@ -103,8 +104,8 @@
       std::wstring());
   MOCK_CONST_METHOD0(GetDialogContentURL,
       GURL());
-  MOCK_CONST_METHOD1(GetDOMMessageHandlers,
-      void(std::vector<DOMMessageHandler*>* handlers));
+  MOCK_CONST_METHOD1(GetWebUIMessageHandlers,
+      void(std::vector<WebUIMessageHandler*>* handlers));
   MOCK_CONST_METHOD1(GetDialogSize,
       void(gfx::Size* size));
   MOCK_CONST_METHOD0(GetDialogArgs,
@@ -204,7 +205,7 @@
   EXPECT_TRUE(test_page_url.has_query());
 }
 
-// Testing for CloudPrintDataSender needs a mock DOMUI.
+// Testing for CloudPrintDataSender needs a mock WebUI.
 class CloudPrintDataSenderTest : public testing::Test {
  public:
   CloudPrintDataSenderTest()
@@ -274,7 +275,7 @@
 
 // Testing for CloudPrintFlowHandler needs a mock
 // CloudPrintHtmlDialogDelegate, mock CloudPrintDataSender, and a mock
-// DOMUI.
+// WebUI.
 
 // Testing for CloudPrintHtmlDialogDelegate needs a mock
 // CloudPrintFlowHandler.
@@ -297,7 +298,7 @@
     EXPECT_CALL(*mock_flow_handler_.get(), SetDialogDelegate(_));
     EXPECT_CALL(*mock_flow_handler_.get(), SetDialogDelegate(NULL));
     delegate_.reset(new CloudPrintHtmlDialogDelegate(
-        mock_flow_handler_.get(), 100, 100, std::string()));
+        mock_flow_handler_.get(), 100, 100, std::string(), true));
   }
 
   virtual void TearDown() {
@@ -329,8 +330,8 @@
 }
 
 TEST_F(CloudPrintHtmlDialogDelegateTest, UnownedFlowLetGo) {
-  std::vector<DOMMessageHandler*> handlers;
-  delegate_->GetDOMMessageHandlers(&handlers);
+  std::vector<WebUIMessageHandler*> handlers;
+  delegate_->GetWebUIMessageHandlers(&handlers);
   delegate_.reset();
   EXPECT_THAT(mock_flow_handler_.get(), NotNull());
 }
diff --git a/chrome/browser/printing/print_dialog_gtk.cc b/chrome/browser/printing/print_dialog_gtk.cc
index eac9bbe..b51056a 100644
--- a/chrome/browser/printing/print_dialog_gtk.cc
+++ b/chrome/browser/printing/print_dialog_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,8 +11,8 @@
 #include "base/file_util.h"
 #include "base/file_util_proxy.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/logging.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
@@ -26,8 +26,8 @@
 PrintDialogGtk* g_print_dialog = NULL;
 
 // Used to make accesses to the above thread safe.
-Lock& DialogLock() {
-  static base::LazyInstance<Lock> dialog_lock(base::LINKER_INITIALIZED);
+base::Lock& DialogLock() {
+  static base::LazyInstance<base::Lock> dialog_lock(base::LINKER_INITIALIZED);
   return dialog_lock.Get();
 }
 
@@ -53,7 +53,7 @@
     return UTF8ToUTF16("here");
   }
 
-  virtual Type GetInfoBarType() { return WARNING_TYPE; }
+  virtual Type GetInfoBarType() const { return WARNING_TYPE; }
 
   virtual bool LinkClicked(WindowOpenDisposition disposition) {
     browser_->OpenURL(
@@ -77,7 +77,7 @@
 
 // static
 bool PrintDialogGtk::DialogShowing() {
-  AutoLock lock(DialogLock());
+  base::AutoLock lock(DialogLock());
   return !!g_print_dialog;
 }
 
@@ -87,9 +87,14 @@
   // locking up the system with
   //
   //   while(true){print();}
-  AutoLock lock(DialogLock());
-  if (g_print_dialog)
+  base::AutoLock lock(DialogLock());
+  if (g_print_dialog) {
+    // Clean up the temporary file.
+    base::FileUtilProxy::Delete(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
+        path, false, NULL);
     return;
+  }
 
   g_print_dialog = new PrintDialogGtk(path);
 }
@@ -107,7 +112,7 @@
 }
 
 PrintDialogGtk::~PrintDialogGtk() {
-  AutoLock lock(DialogLock());
+  base::AutoLock lock(DialogLock());
   DCHECK_EQ(this, g_print_dialog);
   g_print_dialog = NULL;
 }
@@ -120,6 +125,8 @@
       GtkPrinter* printer =
           gtk_print_unix_dialog_get_selected_printer(
               GTK_PRINT_UNIX_DIALOG(dialog_));
+      // Attempt to track down bug 70166.
+      CHECK(printer != NULL);
       if (!gtk_printer_accepts_pdf(printer)) {
         browser_->GetSelectedTabContents()->AddInfoBar(
             new PdfUnsupportedInfoBarDelegate(browser_));
diff --git a/chrome/browser/printing/print_dialog_gtk.h b/chrome/browser/printing/print_dialog_gtk.h
index faeada9..4e610b3 100644
--- a/chrome/browser/printing/print_dialog_gtk.h
+++ b/chrome/browser/printing/print_dialog_gtk.h
@@ -8,9 +8,9 @@
 
 #include <gtk/gtk.h>
 
-#include "app/gtk_signal.h"
 #include "base/basictypes.h"
 #include "base/file_path.h"
+#include "ui/base/gtk/gtk_signal.h"
 
 class Browser;
 
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc
index 493d317..dc14abb 100644
--- a/chrome/browser/printing/print_job.cc
+++ b/chrome/browser/printing/print_job.cc
@@ -22,7 +22,6 @@
       worker_(),
       settings_(),
       is_job_pending_(false),
-      is_print_dialog_box_shown_(false),
       is_canceling_(false) {
   DCHECK(ui_message_loop_);
   // This is normally a UI message loop, but in unit tests, the message loop is
@@ -36,7 +35,6 @@
   ui_message_loop_->RemoveDestructionObserver(this);
   // The job should be finished (or at least canceled) when it is destroyed.
   DCHECK(!is_job_pending_);
-  DCHECK(!is_print_dialog_box_shown_);
   DCHECK(!is_canceling_);
   if (worker_.get())
     DCHECK(worker_->message_loop() == NULL);
@@ -44,18 +42,21 @@
 }
 
 void PrintJob::Initialize(PrintJobWorkerOwner* job,
-                          PrintedPagesSource* source) {
+                          PrintedPagesSource* source,
+                          int page_count) {
   DCHECK(!source_);
   DCHECK(!worker_.get());
   DCHECK(!is_job_pending_);
-  DCHECK(!is_print_dialog_box_shown_);
   DCHECK(!is_canceling_);
   DCHECK(!document_.get());
   source_ = source;
   worker_.reset(job->DetachWorker(this));
   settings_ = job->settings();
 
-  UpdatePrintedDocument(new PrintedDocument(settings_, source_, job->cookie()));
+  PrintedDocument* new_doc =
+      new PrintedDocument(settings_, source_, job->cookie());
+  new_doc->set_page_count(page_count);
+  UpdatePrintedDocument(new_doc);
 
   // Don't forget to register to our own messages.
   registrar_.Add(this, NotificationType::PRINT_JOB_EVENT,
@@ -110,7 +111,6 @@
   DCHECK_EQ(ui_message_loop_, MessageLoop::current());
   DCHECK(worker_->message_loop());
   DCHECK(!is_job_pending_);
-  DCHECK(!is_print_dialog_box_shown_);
   if (!worker_->message_loop() || is_job_pending_)
     return;
 
@@ -137,13 +137,6 @@
 
   MessageLoop* worker_loop = worker_->message_loop();
   if (worker_loop) {
-    if (is_print_dialog_box_shown_) {
-      // Make sure there is no Print... dialog box.
-      worker_loop->PostTask(FROM_HERE, NewRunnableMethod(
-          worker_.get(), &PrintJobWorker::DismissDialog));
-      is_print_dialog_box_shown_ = false;
-    }
-
     ControlledWorkerShutdown();
 
     is_job_pending_ = false;
@@ -212,10 +205,6 @@
   return is_job_pending_;
 }
 
-bool PrintJob::is_print_dialog_box_shown() const {
-  return is_print_dialog_box_shown_;
-}
-
 PrintedDocument* PrintJob::document() const {
   return document_.get();
 }
@@ -242,8 +231,6 @@
   switch (event_details.type()) {
     case JobEventDetails::FAILED: {
       settings_.Clear();
-      // Update internal state.
-      is_print_dialog_box_shown_ = false;
       // No need to cancel since the worker already canceled itself.
       Stop();
       break;
diff --git a/chrome/browser/printing/print_job.h b/chrome/browser/printing/print_job.h
index 03aacda..9191208 100644
--- a/chrome/browser/printing/print_job.h
+++ b/chrome/browser/printing/print_job.h
@@ -42,8 +42,9 @@
   PrintJob();
 
   // Grabs the ownership of the PrintJobWorker from another job, which is
-  // usually a PrinterQuery.
-  void Initialize(PrintJobWorkerOwner* job, PrintedPagesSource* source);
+  // usually a PrinterQuery. Set the expected page count of the print job.
+  void Initialize(PrintJobWorkerOwner* job, PrintedPagesSource* source,
+                  int page_count);
 
   // NotificationObserver
   virtual void Observe(NotificationType type,
@@ -87,9 +88,6 @@
   // and the end of the spooling.
   bool is_job_pending() const;
 
-  // Returns true if the Print... dialog box is currently displayed.
-  bool is_print_dialog_box_shown() const;
-
   // Access the current printed document. Warning: may be NULL.
   PrintedDocument* document() const;
 
@@ -135,9 +133,6 @@
   // Is the worker thread printing.
   bool is_job_pending_;
 
-  // Is the Print... dialog box currently shown.
-  bool is_print_dialog_box_shown_;
-
   // Is Canceling? If so, try to not cause recursion if on FAILED notification,
   // the notified calls Cancel() again.
   bool is_canceling_;
diff --git a/chrome/browser/printing/print_job_manager.cc b/chrome/browser/printing/print_job_manager.cc
index 25f4791..fd01d62 100644
--- a/chrome/browser/printing/print_job_manager.cc
+++ b/chrome/browser/printing/print_job_manager.cc
@@ -21,7 +21,7 @@
 }
 
 PrintJobManager::~PrintJobManager() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   queued_queries_.clear();
 }
 
@@ -59,7 +59,7 @@
 }
 
 void PrintJobManager::QueuePrinterQuery(PrinterQuery* job) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK(job);
   queued_queries_.push_back(make_scoped_refptr(job));
   DCHECK(job->is_valid());
@@ -67,7 +67,7 @@
 
 void PrintJobManager::PopPrinterQuery(int document_cookie,
                                       scoped_refptr<PrinterQuery>* job) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   for (PrinterQueries::iterator itr = queued_queries_.begin();
        itr != queued_queries_.end();
        ++itr) {
@@ -162,12 +162,12 @@
 }
 
 bool PrintJobManager::printing_enabled() {
-  AutoLock lock(enabled_lock_);
+  base::AutoLock lock(enabled_lock_);
   return printing_enabled_;
 }
 
 void PrintJobManager::set_printing_enabled(bool printing_enabled) {
-  AutoLock lock(enabled_lock_);
+  base::AutoLock lock(enabled_lock_);
   printing_enabled_ = printing_enabled;
 }
 
diff --git a/chrome/browser/printing/print_job_manager.h b/chrome/browser/printing/print_job_manager.h
index 228f7ad..a030303 100644
--- a/chrome/browser/printing/print_job_manager.h
+++ b/chrome/browser/printing/print_job_manager.h
@@ -8,8 +8,8 @@
 
 #include <vector>
 
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
@@ -62,10 +62,10 @@
   NotificationRegistrar registrar_;
 
   // Used to serialize access to queued_workers_.
-  Lock lock_;
+  base::Lock lock_;
 
   // Used to serialize access to printing_enabled_
-  Lock enabled_lock_;
+  base::Lock enabled_lock_;
 
   PrinterQueries queued_queries_;
 
diff --git a/chrome/browser/printing/print_job_unittest.cc b/chrome/browser/printing/print_job_unittest.cc
index 1b62016..e5142ac 100644
--- a/chrome/browser/printing/print_job_unittest.cc
+++ b/chrome/browser/printing/print_job_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -107,7 +107,7 @@
   EXPECT_EQ(MessageLoop::current(), job->message_loop());
   scoped_refptr<TestOwner> owner(new TestOwner);
   TestSource source;
-  job->Initialize(owner, &source);
+  job->Initialize(owner, &source, 1);
   job->Stop();
   job = NULL;
   EXPECT_TRUE(check);
@@ -135,7 +135,6 @@
   job->FlushJob(timeout_ms);
   job->DisconnectSource();
   job->is_job_pending();
-  job->is_print_dialog_box_shown();
   job->document();
   // Private
   job->UpdatePrintedDocument(NULL);
diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc
index 201b2f7..50a1a18 100644
--- a/chrome/browser/printing/print_job_worker.cc
+++ b/chrome/browser/printing/print_job_worker.cc
@@ -223,10 +223,6 @@
   // context we run.
 }
 
-void PrintJobWorker::DismissDialog() {
-  printing_context_->DismissDialog();
-}
-
 void PrintJobWorker::OnDocumentDone() {
   DCHECK_EQ(message_loop(), MessageLoop::current());
   DCHECK_EQ(page_number_, PageNumber::npos());
diff --git a/chrome/browser/printing/print_job_worker.h b/chrome/browser/printing/print_job_worker.h
index 4087194..6b0183b 100644
--- a/chrome/browser/printing/print_job_worker.h
+++ b/chrome/browser/printing/print_job_worker.h
@@ -10,9 +10,9 @@
 #include "base/scoped_ptr.h"
 #include "base/task.h"
 #include "base/threading/thread.h"
-#include "gfx/native_widget_types.h"
 #include "printing/page_number.h"
 #include "printing/printing_context.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace printing {
 
@@ -57,9 +57,6 @@
   // This is the only function that can be called in a thread.
   void Cancel();
 
-  // Cancels the Print... dialog box if shown, noop otherwise.
-  void DismissDialog();
-
  protected:
   // Retrieves the context for testing only.
   PrintingContext* printing_context() { return printing_context_.get(); }
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc
new file mode 100644
index 0000000..fdf3b30
--- /dev/null
+++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/printing/print_preview_message_handler.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/dom_ui/print_preview_handler.h"
+#include "chrome/browser/dom_ui/print_preview_ui.h"
+#include "chrome/browser/dom_ui/print_preview_ui_html_source.h"
+#include "chrome/browser/printing/printer_query.h"
+#include "chrome/browser/printing/print_job_manager.h"
+#include "chrome/browser/printing/print_preview_tab_controller.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/render_messages_params.h"
+#include "ipc/ipc_message_macros.h"
+
+namespace printing {
+
+PrintPreviewMessageHandler::PrintPreviewMessageHandler(TabContents* owner)
+    : owner_(owner) {
+  DCHECK(owner);
+}
+
+PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {
+}
+
+TabContents* PrintPreviewMessageHandler::GetPrintPreviewTab() {
+  // Get/Create preview tab for initiator tab.
+  printing::PrintPreviewTabController* tab_controller =
+      printing::PrintPreviewTabController::GetInstance();
+  if (!tab_controller)
+    return NULL;
+  return tab_controller->GetPrintPreviewForTab(owner_);
+}
+
+void PrintPreviewMessageHandler::OnPagesReadyForPreview(
+    const ViewHostMsg_DidPreviewDocument_Params& params) {
+#if defined(OS_MACOSX)
+  base::SharedMemory* shared_buf =
+      new base::SharedMemory(params.metafile_data_handle, true);
+  if (!shared_buf->Map(params.data_size)) {
+    NOTREACHED();
+    return;
+  }
+#endif
+
+  // Get the print preview tab.
+  TabContents* print_preview_tab = GetPrintPreviewTab();
+  DCHECK(print_preview_tab);
+
+#if defined(OS_MACOSX)
+  PrintPreviewUI* print_preview_ui =
+      static_cast<PrintPreviewUI*>(print_preview_tab->web_ui());
+  print_preview_ui->html_source()->SetPrintPreviewData(
+      std::make_pair(shared_buf, params.data_size));
+  print_preview_ui->PreviewDataIsAvailable();
+#endif
+
+  scoped_refptr<printing::PrinterQuery> printer_query;
+  g_browser_process->print_job_manager()->PopPrinterQuery(
+      params.document_cookie, &printer_query);
+  if (printer_query.get()) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        NewRunnableMethod(printer_query.get(),
+                          &printing::PrinterQuery::StopWorker));
+  }
+
+  RenderViewHost* rvh = owner_->render_view_host();
+  rvh->Send(new ViewMsg_PrintingDone(rvh->routing_id(),
+                                     params.document_cookie,
+                                     true));
+}
+
+bool PrintPreviewMessageHandler::OnMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_PagesReadyForPreview,
+                        OnPagesReadyForPreview)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+}  // namespace printing
diff --git a/chrome/browser/printing/print_preview_message_handler.h b/chrome/browser/printing/print_preview_message_handler.h
new file mode 100644
index 0000000..27963b1
--- /dev/null
+++ b/chrome/browser/printing/print_preview_message_handler.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 CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
+#define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+
+struct ViewHostMsg_DidPreviewDocument_Params;
+
+namespace printing {
+
+// TabContents offloads print preview message handling to
+// PrintPreviewMessageHandler. This object has the same life time as the
+// TabContents that owns it.
+class PrintPreviewMessageHandler : public TabContentsObserver {
+ public:
+  explicit PrintPreviewMessageHandler(TabContents* owner);
+  virtual ~PrintPreviewMessageHandler();
+
+  void OnPagesReadyForPreview(
+      const ViewHostMsg_DidPreviewDocument_Params& params);
+
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+ private:
+  // Gets the print preview tab associated with |owner_|.
+  TabContents* GetPrintPreviewTab();
+
+  // The TabContents that owns this PrintPreviewMessageHandler.
+  TabContents* owner_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrintPreviewMessageHandler);
+};
+
+}  // namespace printing
+
+#endif  // CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
diff --git a/chrome/browser/printing/print_preview_tab_controller.cc b/chrome/browser/printing/print_preview_tab_controller.cc
index f6135c9..59f24f2 100644
--- a/chrome/browser/printing/print_preview_tab_controller.cc
+++ b/chrome/browser/printing/print_preview_tab_controller.cc
@@ -44,6 +44,22 @@
   return CreatePrintPreviewTab(initiator_tab, browser_window_id);
 }
 
+TabContents* PrintPreviewTabController::GetPrintPreviewForTab(
+    TabContents* tab) const {
+  PrintPreviewTabMap::const_iterator it = preview_tab_map_.find(tab);
+  if (it != preview_tab_map_.end())
+    return tab;
+
+  for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) {
+    // If |tab| is an initiator tab.
+    if (tab == it->second) {
+      // Return the associated preview tab.
+      return it->first;
+    }
+  }
+  return NULL;
+}
+
 void PrintPreviewTabController::Observe(NotificationType type,
                                         const NotificationSource& source,
                                         const NotificationDetails& details) {
@@ -138,19 +154,6 @@
   return NULL;
 }
 
-TabContents* PrintPreviewTabController::GetPrintPreviewForTab(
-    TabContents* tab) {
-  PrintPreviewTabMap::iterator it = preview_tab_map_.find(tab);
-  if (it != preview_tab_map_.end())
-    return tab;
-
-  for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) {
-    if (it->second == tab)
-      return it->first;
-  }
-  return NULL;
-}
-
 TabContents* PrintPreviewTabController::CreatePrintPreviewTab(
     TabContents* initiator_tab, int browser_window_id) {
   Browser* current_browser = BrowserList::FindBrowserWithID(browser_window_id);
diff --git a/chrome/browser/printing/print_preview_tab_controller.h b/chrome/browser/printing/print_preview_tab_controller.h
index a3d01ea..95e2224 100644
--- a/chrome/browser/printing/print_preview_tab_controller.h
+++ b/chrome/browser/printing/print_preview_tab_controller.h
@@ -39,6 +39,11 @@
   TabContents* GetOrCreatePreviewTab(
       TabContents* initiator_tab, int browser_window_id);
 
+  // Returns preview tab for |tab|.
+  // Returns |tab| if |tab| is a preview tab.
+  // Returns NULL if no preview tab exists for |tab|.
+  TabContents* GetPrintPreviewForTab(TabContents* tab) const;
+
   // Notification observer implementation.
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
@@ -59,11 +64,6 @@
   // Returns NULL if no initiator tab exists for |preview_tab|.
   TabContents* GetInitiatorTab(TabContents* preview_tab);
 
-  // Returns preview tab for |tab|.
-  // Returns |tab| if |tab| is a preview tab.
-  // Returns NULL if no preview tab exists for |tab|.
-  TabContents* GetPrintPreviewForTab(TabContents* tab);
-
   // Creates a new print preview tab.
   TabContents* CreatePrintPreviewTab(
       TabContents* initiator_tab, int browser_window_id);
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 6381f61..1871e31 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/printing/print_view_manager.h"
 
-#include "app/l10n_util.h"
 #include "base/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
@@ -16,17 +15,20 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "grit/generated_resources.h"
 #include "printing/native_metafile.h"
 #include "printing/printed_document.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::TimeDelta;
 
 namespace printing {
 
 PrintViewManager::PrintViewManager(TabContents& owner)
-    : waiting_to_print_(false),
+    : number_pages_(0),
+      waiting_to_print_(false),
       printing_succeeded_(false),
       inside_inner_message_loop_(false),
       owner_(owner) {
@@ -73,8 +75,10 @@
     return GURL();
 }
 
-void PrintViewManager::DidGetPrintedPagesCount(int cookie, int number_pages) {
+void PrintViewManager::OnDidGetPrintedPagesCount(int cookie, int number_pages) {
   DCHECK_GT(cookie, 0);
+  DCHECK_GT(number_pages, 0);
+  number_pages_ = number_pages;
   if (!OpportunisticallyCreatePrintJob(cookie))
     return;
 
@@ -84,14 +88,9 @@
     // spurious message can happen if one of the processes is overloaded.
     return;
   }
-
-  // Time to inform our print job. Make sure it is for the right document.
-  if (!document->page_count()) {
-    document->set_page_count(number_pages);
-  }
 }
 
-void PrintViewManager::DidPrintPage(
+void PrintViewManager::OnDidPrintPage(
     const ViewHostMsg_DidPrintPage_Params& params) {
   if (!OpportunisticallyCreatePrintJob(params.document_cookie))
     return;
@@ -143,6 +142,17 @@
   ShouldQuitFromInnerMessageLoop();
 }
 
+bool PrintViewManager::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetPrintedPagesCount,
+                        OnDidGetPrintedPagesCount)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_DidPrintPage, OnDidPrintPage)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
 void PrintViewManager::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {
@@ -278,7 +288,7 @@
     return false;
 
   print_job_ = new PrintJob();
-  print_job_->Initialize(job, this);
+  print_job_->Initialize(job, this, number_pages_);
   registrar_.Add(this, NotificationType::PRINT_JOB_EVENT,
                  Source<PrintJob>(print_job_.get()));
   printing_succeeded_ = false;
diff --git a/chrome/browser/printing/print_view_manager.h b/chrome/browser/printing/print_view_manager.h
index cee7382..3f40995 100644
--- a/chrome/browser/printing/print_view_manager.h
+++ b/chrome/browser/printing/print_view_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include "base/ref_counted.h"
 #include "base/string16.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "printing/printed_pages_source.h"
@@ -27,7 +27,7 @@
 // delegates a few printing related commands to this instance.
 class PrintViewManager : public NotificationObserver,
                          public PrintedPagesSource,
-                         public RenderViewHostDelegate::Printing {
+                         public TabContentsObserver {
  public:
   explicit PrintViewManager(TabContents& owner);
   virtual ~PrintViewManager();
@@ -43,16 +43,18 @@
   virtual string16 RenderSourceName();
   virtual GURL RenderSourceUrl();
 
-  // RenderViewHostDelegate::Printing implementation.
-  virtual void DidGetPrintedPagesCount(int cookie, int number_pages);
-  virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params);
-
   // NotificationObserver implementation.
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
+  // TabContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
  private:
+  void OnDidGetPrintedPagesCount(int cookie, int number_pages);
+  void OnDidPrintPage(const ViewHostMsg_DidPrintPage_Params& params);
+
   // Processes a NOTIFY_PRINT_JOB_EVENT notification.
   void OnNotifyPrintJobEvent(const JobEventDetails& event_details);
 
@@ -106,6 +108,9 @@
   // Manages the low-level talk to the printer.
   scoped_refptr<PrintJob> print_job_;
 
+  // Number of pages to print in the print job.
+  int number_pages_;
+
   // Waiting for print_job_ initialization to be completed to start printing.
   // Specifically the DEFAULT_INIT_DONE notification. Set when PrintNow() is
   // called.
diff --git a/chrome/browser/printing/printer_query.cc b/chrome/browser/printing/printer_query.cc
index 89f0e97..f39960f 100644
--- a/chrome/browser/printing/printer_query.cc
+++ b/chrome/browser/printing/printer_query.cc
@@ -118,10 +118,6 @@
   }
 }
 
-bool PrinterQuery::is_print_dialog_box_shown() const {
-  return is_print_dialog_box_shown_;
-}
-
 bool PrinterQuery::is_callback_pending() const {
   return callback_.get() != NULL;
 }
diff --git a/chrome/browser/printing/printer_query.h b/chrome/browser/printing/printer_query.h
index dc18b1f..edc0c63 100644
--- a/chrome/browser/printing/printer_query.h
+++ b/chrome/browser/printing/printer_query.h
@@ -8,7 +8,7 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/printing/print_job_worker_owner.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class CancelableTask;
 class MessageLoop;
@@ -54,9 +54,6 @@
   // Stops the worker thread since the client is done with this object.
   void StopWorker();
 
-  // Returns true if the Print... dialog box is currently displayed.
-  bool is_print_dialog_box_shown() const;
-
   // Returns true if a GetSettings() call is pending completion.
   bool is_callback_pending() const;
 
diff --git a/chrome/browser/printing/printing_layout_uitest.cc b/chrome/browser/printing/printing_layout_uitest.cc
index d2cdf9d..a3917c5 100644
--- a/chrome/browser/printing/printing_layout_uitest.cc
+++ b/chrome/browser/printing/printing_layout_uitest.cc
@@ -1,11 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/file_path.h"
 #include "base/file_util.h"
+#include "base/string_util.h"
 #include "base/test/test_file_util.h"
 #include "base/threading/simple_thread.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/ui/ui_test.h"
 #include "net/test/test_server.h"
@@ -56,7 +59,7 @@
       return 100.;
     }
 
-    std::wstring verification_file(test_data_directory_.ToWStringHack());
+    std::wstring verification_file(test_data_directory_.value());
     file_util::AppendToPath(&verification_file, L"printing");
     file_util::AppendToPath(&verification_file, verification_name);
     FilePath emf(verification_file + L".emf");
@@ -140,22 +143,22 @@
       prn_file.clear();
       found_emf = false;
       found_prn = false;
-      std::wstring file;
-      while (!(file = enumerator.Next().ToWStringHack()).empty()) {
-        std::wstring ext = file_util::GetFileExtensionFromPath(file);
-        if (!_wcsicmp(ext.c_str(), L"emf")) {
+      FilePath file;
+      while (!(file = enumerator.Next()).empty()) {
+        std::wstring ext = file.Extension();
+        if (base::strcasecmp(WideToUTF8(ext).c_str(), ".emf") == 0) {
           EXPECT_FALSE(found_emf) << "Found a leftover .EMF file: \"" <<
-              emf_file << "\" and \"" << file << "\" when looking for \"" <<
-              verification_name << "\"";
+              emf_file << "\" and \"" << file.value() <<
+              "\" when looking for \"" << verification_name << "\"";
           found_emf = true;
-          emf_file = file;
+          emf_file = file.value();
           continue;
         }
-        if (!_wcsicmp(ext.c_str(), L"prn")) {
+        if (base::strcasecmp(WideToUTF8(ext).c_str(), ".prn") == 0) {
           EXPECT_FALSE(found_prn) << "Found a leftover .PRN file: \"" <<
-              prn_file << "\" and \"" << file << "\" when looking for \"" <<
-              verification_name << "\"";
-          prn_file = file;
+              prn_file << "\" and \"" << file.value() <<
+              "\" when looking for \"" << verification_name << "\"";
+          prn_file = file.value();
           found_prn = true;
           file_util::Delete(file, false);
           continue;
diff --git a/chrome/browser/process_info_snapshot.h b/chrome/browser/process_info_snapshot.h
index e4e3f33..d571e7d 100644
--- a/chrome/browser/process_info_snapshot.h
+++ b/chrome/browser/process_info_snapshot.h
@@ -17,12 +17,7 @@
 // A class which captures process information at a given point in time when its
 // |Sample()| method is called. This information can then be probed by PID.
 // |Sample()| may take a while to complete, so if calling from the browser
-// process, only do so from the file thread. The current implementation, only on
-// Mac, pulls information from /bin/ps. /usr/bin/top provides much more
-// information about memory, but it has changed greatly from Mac OS 10.5.x to
-// 10.6.x, thereby raising future compatibility concerns. Moreover, the 10.6.x
-// version is less capable in terms of configuring output and its output is
-// harder to parse.
+// process, only do so from the file thread.
 // TODO(viettrungluu): This is currently only implemented and used on Mac, so
 // things are very Mac-specific. If this is ever implemented for other
 // platforms, we should subclass and add opaqueness (probably |ProcInfoEntry|
@@ -36,7 +31,7 @@
   // |Sample()| below.
   static const size_t kMaxPidListSize;
 
-  // Capture a snapshot of process memory information (by running ps) for the
+  // Capture a snapshot of process memory information for the
   // given list of PIDs. Call only from the file thread.
   //   |pid_list| - list of |ProcessId|s on which to capture information; must
   //     have no more than |kMaxPidListSize| (above) entries,
@@ -55,9 +50,24 @@
     base::ProcessId ppid;
     uid_t uid;
     uid_t euid;
-    size_t rss;
-    size_t vsize;
+    // Explicitly use uint64_t instead of size_t in case this code is running
+    // in a 32 bit process and the target process is 64 bit.
+    uint64_t rss;
+    uint64_t rshrd;
+    uint64_t rprvt;
+    uint64_t vsize;
     std::string command;
+
+    ProcInfoEntry()
+        : pid(0),
+          ppid(0),
+          uid(0),
+          euid(0),
+          rss(0),
+          rshrd(0),
+          rprvt(0),
+          vsize(0) {
+    }
   };
 
   // Get process information for a given PID.
@@ -85,9 +95,9 @@
   // Fills a |WorkingSetKBytes| containing resident private and shared memory,
   // as per its definition (or as close as we can manage). In the current (Mac)
   // implementation, we map:
-  //                              0 --> ws_priv,
+  //                          rprvt --> ws_priv,
   //                            rss --> ws_shareable,
-  //                              0 --> ws_shared;
+  //                          rshrd --> ws_shared;
   //   in about:memory: res:private  =  ws_priv + ws_shareable - ws_shared,
   //                     res:shared  =  ws_shared / num_procs,
   //                      res:total  =  res:private + res:shared.
diff --git a/chrome/browser/process_info_snapshot_mac.cc b/chrome/browser/process_info_snapshot_mac.cc
index 85adb19..98216e0 100644
--- a/chrome/browser/process_info_snapshot_mac.cc
+++ b/chrome/browser/process_info_snapshot_mac.cc
@@ -4,17 +4,17 @@
 
 #include "chrome/browser/process_info_snapshot.h"
 
+#include <sys/sysctl.h>
+
 #include <sstream>
 
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
+#include "base/sys_info.h"
 #include "base/threading/thread.h"
 
-// Implementation for the Mac; calls '/bin/ps' for information when
-// |Sample()| is called.
-
 // Default constructor.
 ProcessInfoSnapshot::ProcessInfoSnapshot() { }
 
@@ -25,30 +25,117 @@
 
 const size_t ProcessInfoSnapshot::kMaxPidListSize = 1000;
 
-// Capture the information by calling '/bin/ps'.
-// Note: we ignore the "tsiz" (text size) display option of ps because it's
-// always zero (tested on 10.5 and 10.6).
-bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) {
-  const char* kPsPathName = "/bin/ps";
-  Reset();
+static bool GetKInfoForProcessID(pid_t pid, kinfo_proc* kinfo) {
+  int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+  size_t len = sizeof(*kinfo);
+  if (sysctl(mib, arraysize(mib), kinfo, &len, NULL, 0) != 0) {
+    PLOG(ERROR) << "sysctl() for KERN_PROC";
+    return false;
+  }
 
-  // Nothing to do if no PIDs given.
-  if (pid_list.size() == 0)
-    return true;
-  if (pid_list.size() > kMaxPidListSize) {
-    // The spec says |pid_list| *must* not have more than this many entries.
+  if (len == 0) {
+    // If the process isn't found then sysctl returns a length of 0.
+    return false;
+  }
+
+  return true;
+}
+
+static bool GetExecutableNameForProcessID(
+    pid_t pid,
+    std::string* executable_name) {
+  if (!executable_name) {
     NOTREACHED();
     return false;
   }
 
+  static int s_arg_max = 0;
+  if (s_arg_max == 0) {
+    int mib[] = {CTL_KERN, KERN_ARGMAX};
+    size_t size = sizeof(s_arg_max);
+    if (sysctl(mib, arraysize(mib), &s_arg_max, &size, NULL, 0) != 0)
+      PLOG(ERROR) << "sysctl() for KERN_ARGMAX";
+  }
+
+  if (s_arg_max == 0)
+    return false;
+
+  int mib[] = {CTL_KERN, KERN_PROCARGS, pid};
+  size_t size = s_arg_max;
+  executable_name->resize(s_arg_max + 1);
+  if (sysctl(mib, arraysize(mib), &(*executable_name)[0],
+             &size, NULL, 0) != 0) {
+    // Don't log the error since it's normal for this to fail.
+    return false;
+  }
+
+  // KERN_PROCARGS returns multiple NULL terminated strings. Truncate
+  // executable_name to just the first string.
+  size_t end_pos = executable_name->find('\0');
+  if (end_pos == std::string::npos) {
+    return false;
+  }
+
+  executable_name->resize(end_pos);
+  return true;
+}
+
+// Converts a byte unit such as 'K' or 'M' into the scale for the unit.
+// The scale can then be used to calculate the number of bytes in a value.
+// The units are based on humanize_number(). See:
+// http://www.opensource.apple.com/source/libutil/libutil-21/humanize_number.c
+static bool ConvertByteUnitToScale(char unit, uint64_t* out_scale) {
+  int shift = 0;
+  switch (unit) {
+    case 'B':
+      shift = 0;
+      break;
+    case 'K':
+    case 'k':
+      shift = 1;
+      break;
+    case 'M':
+      shift = 2;
+      break;
+    case 'G':
+      shift = 3;
+      break;
+    case 'T':
+      shift = 4;
+      break;
+    case 'P':
+      shift = 5;
+      break;
+    case 'E':
+      shift = 6;
+      break;
+    default:
+      return false;
+  }
+
+  uint64_t scale = 1;
+  for (int i = 0; i < shift; i++)
+    scale *= 1024;
+  *out_scale = scale;
+
+  return true;
+}
+
+// Capture the information by calling '/bin/ps'.
+// Note: we ignore the "tsiz" (text size) display option of ps because it's
+// always zero (tested on 10.5 and 10.6).
+static bool GetProcessMemoryInfoUsingPS(
+    const std::vector<base::ProcessId>& pid_list,
+    std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
+  const char kPsPathName[] = "/bin/ps";
   std::vector<std::string> argv;
   argv.push_back(kPsPathName);
-  // Get PID, PPID, (real) UID, effective UID, resident set size, virtual memory
-  // size, and command.
+
+  // Get resident set size, virtual memory size.
   argv.push_back("-o");
-  argv.push_back("pid=,ppid=,ruid=,uid=,rss=,vsz=,comm=");
+  argv.push_back("pid=,rss=,vsz=");
   // Only display the specified PIDs.
-  for (std::vector<base::ProcessId>::iterator it = pid_list.begin();
+  for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin();
       it != pid_list.end(); ++it) {
     argv.push_back("-p");
     argv.push_back(base::Int64ToString(static_cast<int64>(*it)));
@@ -67,20 +154,21 @@
 
   // Process lines until done.
   while (true) {
-    ProcInfoEntry proc_info;
-
     // The format is as specified above to ps (see ps(1)):
-    //   "-o pid=,ppid=,ruid=,uid=,rss=,vsz=,comm=".
+    //   "-o pid=,rss=,vsz=".
     // Try to read the PID; if we get it, we should be able to get the rest of
     // the line.
-    in >> proc_info.pid;
+    pid_t pid;
+    in >> pid;
     if (in.eof())
       break;
-    in >> proc_info.ppid;
-    in >> proc_info.uid;
-    in >> proc_info.euid;
+
+    ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid];
+    proc_info.pid = pid;
     in >> proc_info.rss;
     in >> proc_info.vsize;
+    proc_info.rss *= 1024;                // Convert from kilobytes to bytes.
+    proc_info.vsize *= 1024;
     in.ignore(1, ' ');                    // Eat the space.
     std::getline(in, proc_info.command);  // Get the rest of the line.
     if (!in.good()) {
@@ -88,24 +176,231 @@
       return false;
     }
 
-    // Make sure the new PID isn't already in our list.
-    if (proc_info_entries_.find(proc_info.pid) != proc_info_entries_.end()) {
-      LOG(ERROR) << "Duplicate PID in output from " << kPsPathName << ".";
-      return false;
-    }
-
     if (!proc_info.pid || ! proc_info.vsize) {
       LOG(WARNING) << "Invalid data from " << kPsPathName << ".";
       return false;
     }
 
     // Record the process information.
-    proc_info_entries_[proc_info.pid] = proc_info;
+    proc_info_entries[proc_info.pid] = proc_info;
   }
 
   return true;
 }
 
+static bool GetProcessMemoryInfoUsingTop(
+    std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
+  const char kTopPathName[] = "/usr/bin/top";
+  std::vector<std::string> argv;
+  argv.push_back(kTopPathName);
+
+  // -stats tells top to print just the given fields as ordered.
+  argv.push_back("-stats");
+  argv.push_back("pid,"    // Process ID
+                 "rsize,"  // Resident memory
+                 "rshrd,"  // Resident shared memory
+                 "rprvt,"  // Resident private memory
+                 "vsize"); // Total virtual memory
+  // Run top in logging (non-interactive) mode.
+  argv.push_back("-l");
+  argv.push_back("1");
+  // Set the delay between updates to 0.
+  argv.push_back("-s");
+  argv.push_back("0");
+
+  std::string output;
+  CommandLine command_line(argv);
+  // Limit output read to a megabyte for safety.
+  if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
+    LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data.";
+    return false;
+  }
+
+  // Process lines until done. Lines should look something like this:
+  // PID    RSIZE  RSHRD  RPRVT  VSIZE
+  // 58539  1276K+ 336K+  740K+  2378M+
+  // 58485  1888K+ 592K+  1332K+ 2383M+
+  std::istringstream top_in(output, std::istringstream::in);
+  std::string line;
+  while (std::getline(top_in, line)) {
+    std::istringstream in(line, std::istringstream::in);
+
+    // Try to read the PID.
+    pid_t pid;
+    in >> pid;
+    if (in.fail())
+      continue;
+
+    // Make sure that caller is interested in this process.
+    if (proc_info_entries.find(pid) == proc_info_entries.end())
+      continue;
+
+    // Skip the - or + sign that top puts after the pid.
+    in.get();
+
+    uint64_t values[4];
+    size_t i;
+    for (i = 0; i < arraysize(values); i++) {
+      in >> values[i];
+      if (in.fail())
+        break;
+      std::string unit;
+      in >> unit;
+      if (in.fail())
+        break;
+
+      if (unit.size() == 0)
+        break;
+
+      uint64_t scale;
+      if (!ConvertByteUnitToScale(unit[0], &scale))
+        break;
+      values[i] *= scale;
+    }
+    if (i != arraysize(values))
+      continue;
+
+    ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid];
+    proc_info.rss = values[0];
+    proc_info.rshrd = values[1];
+    proc_info.rprvt = values[2];
+    proc_info.vsize = values[3];
+    // Record the process information.
+    proc_info_entries[proc_info.pid] = proc_info;
+  }
+
+  return true;
+}
+
+static bool GetProcessMemoryInfoUsingTop_10_5(
+    std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
+  const char kTopPathName[] = "/usr/bin/top";
+  std::vector<std::string> argv;
+  argv.push_back(kTopPathName);
+
+  // -p tells top to print just the given fields as ordered.
+  argv.push_back("-p");
+  argv.push_back("^aaaaaaaaaaaaaaaaaaaa "  // Process ID (PID)
+                 "^jjjjjjjjjjjjjjjjjjjj "  // Resident memory (RSIZE)
+                 "^iiiiiiiiiiiiiiiiiiii "  // Resident shared memory (RSHRD)
+                 "^hhhhhhhhhhhhhhhhhhhh "  // Resident private memory (RPRVT)
+                 "^llllllllllllllllllll"); // Total virtual memory (VSIZE)
+  // Run top in logging (non-interactive) mode.
+  argv.push_back("-l");
+  argv.push_back("1");
+  // Set the delay between updates to 0.
+  argv.push_back("-s");
+  argv.push_back("0");
+
+  std::string output;
+  CommandLine command_line(argv);
+  // Limit output read to a megabyte for safety.
+  if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
+    LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data.";
+    return false;
+  }
+
+  // Process lines until done. Lines should look something like this:
+  // PID      RSIZE     RSHRD     RPRVT     VSIZE
+  // 16943    815104    262144    290816    18489344
+  // 16922    954368    720896    278528    18976768
+  std::istringstream top_in(output, std::istringstream::in);
+  std::string line;
+  while (std::getline(top_in, line)) {
+    std::istringstream in(line, std::istringstream::in);
+
+    // Try to read the PID.
+    pid_t pid;
+    in >> pid;
+    if (in.fail())
+      continue;
+
+    // Make sure that caller is interested in this process.
+    if (proc_info_entries.find(pid) == proc_info_entries.end())
+      continue;
+
+    uint64_t values[4];
+    size_t i;
+    for (i = 0; i < arraysize(values); i++) {
+      in >> values[i];
+      if (in.fail())
+        break;
+    }
+    if (i != arraysize(values))
+      continue;
+
+    ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid];
+    proc_info.rss = values[0];
+    proc_info.rshrd = values[1];
+    proc_info.rprvt = values[2];
+    proc_info.vsize = values[3];
+    // Record the process information.
+    proc_info_entries[proc_info.pid] = proc_info;
+  }
+
+  return true;
+}
+
+
+bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) {
+  Reset();
+
+  // Nothing to do if no PIDs given.
+  if (pid_list.size() == 0)
+    return true;
+  if (pid_list.size() > kMaxPidListSize) {
+    // The spec says |pid_list| *must* not have more than this many entries.
+    NOTREACHED();
+    return false;
+  }
+
+  // Get basic process info from KERN_PROC.
+  for (std::vector<base::ProcessId>::iterator it = pid_list.begin();
+       it != pid_list.end(); ++it) {
+    ProcInfoEntry proc_info;
+    proc_info.pid = *it;
+
+    kinfo_proc kinfo;
+    if (!GetKInfoForProcessID(*it, &kinfo))
+      return false;
+
+    proc_info.ppid = kinfo.kp_eproc.e_ppid;
+    proc_info.uid = kinfo.kp_eproc.e_pcred.p_ruid;
+    proc_info.euid = kinfo.kp_eproc.e_ucred.cr_uid;
+    // Note, p_comm is truncated to 16 characters.
+    proc_info.command = kinfo.kp_proc.p_comm;
+    proc_info_entries_[*it] = proc_info;
+  }
+
+  // Use KERN_PROCARGS to get the full executable name. This may fail if this
+  // process doesn't have privileges to inspect the target process.
+  for (std::vector<base::ProcessId>::iterator it = pid_list.begin();
+       it != pid_list.end(); ++it) {
+    std::string exectuable_name;
+    if (GetExecutableNameForProcessID(*it, &exectuable_name)) {
+      ProcInfoEntry proc_info = proc_info_entries_[*it];
+      proc_info.command = exectuable_name;
+    }
+  }
+
+  // Get memory information using top.
+  bool memory_info_success = false;
+  int32 major, minor, bugfix;
+  base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
+  if (major == 10 && minor == 5)
+    memory_info_success = GetProcessMemoryInfoUsingTop_10_5(proc_info_entries_);
+  else if ((major == 10 && minor >= 6) || major > 10)
+    memory_info_success = GetProcessMemoryInfoUsingTop(proc_info_entries_);
+
+  // If top didn't work then fall back to ps.
+  if (!memory_info_success) {
+    memory_info_success = GetProcessMemoryInfoUsingPS(pid_list,
+                                                      proc_info_entries_);
+  }
+
+  return memory_info_success;
+}
+
 // Clear all the stored information.
 void ProcessInfoSnapshot::Reset() {
   proc_info_entries_.clear();
@@ -139,7 +434,7 @@
     return false;
   }
 
-  usage->priv = proc_info.vsize;
+  usage->priv = proc_info.vsize / 1024;
   usage->mapped = 0;
   usage->image = 0;
   return true;
@@ -163,8 +458,8 @@
     return false;
   }
 
-  ws_usage->priv = 0;
-  ws_usage->shareable = proc_info.rss;
-  ws_usage->shared = 0;
+  ws_usage->priv = proc_info.rprvt / 1024;
+  ws_usage->shareable = proc_info.rss / 1024;
+  ws_usage->shared = proc_info.rshrd / 1024;
   return true;
 }
diff --git a/chrome/browser/process_info_snapshot_mac_unittest.cc b/chrome/browser/process_info_snapshot_mac_unittest.cc
index fe28c74..64d1c84 100644
--- a/chrome/browser/process_info_snapshot_mac_unittest.cc
+++ b/chrome/browser/process_info_snapshot_mac_unittest.cc
@@ -10,7 +10,9 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/eintr_wrapper.h"
 #include "base/file_path.h"
+#include "base/logging.h"
 #include "base/process_util.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
@@ -77,6 +79,8 @@
                                       // should occupy at least 100 kilobytes.
   EXPECT_GE(proc_info.vsize, 1024u);  // Sanity check: our |vsize| is presumably
                                       // at least a megabyte.
+  EXPECT_GE(proc_info.rshrd, 1024u);  // Shared memory should also > 1 MB.
+  EXPECT_GE(proc_info.rprvt, 1024u);  // Same with private memory.
 
   // Find our parent.
   ASSERT_TRUE(snapshot.GetProcInfo(ppid, &proc_info));
@@ -88,11 +92,32 @@
   EXPECT_GT(proc_info.vsize, 0u);   // Its |vsize| should be nonzero though.
 }
 
+// To verify that ProcessInfoSnapshot is getting the actual uid and effective
+// uid, this test runs top. top should have a uid of the caller and effective
+// uid of 0 (root).
 TEST_F(ProcessInfoSnapshotMacTest, EffectiveVsRealUserIDTest) {
-  // Run top which has a uid of the caller and effective uid of 0.
+  // Create a pipe to be able to read top's output.
+  int fds[2];
+  PCHECK(pipe(fds) == 0);
+  base::file_handle_mapping_vector fds_to_remap;
+  fds_to_remap.push_back(std::make_pair(fds[1], 1));
+
+  // Hook up top's stderr to the test process' stderr.
+  fds_to_remap.push_back(std::make_pair(fileno(stderr), 2));
+
+  std::vector<std::string> argv;
+  argv.push_back("/usr/bin/top");
+  argv.push_back("-l");
+  argv.push_back("0");
+
   base::ProcessHandle process_handle;
-  ASSERT_TRUE(base::LaunchApp(CommandLine(FilePath("/usr/bin/top")),
-                              false, false, &process_handle));
+  ASSERT_TRUE(base::LaunchApp(argv, fds_to_remap, false, &process_handle));
+  PCHECK(HANDLE_EINTR(close(fds[1])) == 0);
+
+  // Wait until there's some output form top. This is an easy way to tell that
+  // the exec() call is done and top is actually running.
+  char buf[1];
+  PCHECK(HANDLE_EINTR(read(fds[0], buf, 1)) == 1);
 
   std::vector<base::ProcessId> pid_list;
   pid_list.push_back(process_handle);
@@ -107,4 +132,5 @@
   EXPECT_EQ(proc_info.uid, geteuid());
 
   ASSERT_TRUE(base::KillProcess(process_handle, 0, true));
+  PCHECK(HANDLE_EINTR(close(fds[0])) == 0);
 }
diff --git a/chrome/browser/process_singleton.h b/chrome/browser/process_singleton.h
index 9418c60..1aa80b2 100644
--- a/chrome/browser/process_singleton.h
+++ b/chrome/browser/process_singleton.h
@@ -16,7 +16,7 @@
 #include "base/logging.h"
 #include "base/ref_counted.h"
 #include "base/threading/non_thread_safe.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 #if defined(OS_POSIX)
 #include "base/file_path.h"
diff --git a/chrome/browser/process_singleton_linux.cc b/chrome/browser/process_singleton_linux.cc
index 982f370..0266f73 100644
--- a/chrome/browser/process_singleton_linux.cc
+++ b/chrome/browser/process_singleton_linux.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -50,11 +50,11 @@
 #include <sys/types.h>
 #include <sys/un.h>
 #include <unistd.h>
+
 #include <cstring>
 #include <set>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/base_paths.h"
 #include "base/basictypes.h"
 #include "base/command_line.h"
@@ -78,7 +78,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #if defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/process_singleton_dialog.h"
+#include "chrome/browser/ui/gtk/process_singleton_dialog.h"
 #endif
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/profiles/profile.h"
@@ -90,6 +90,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 const int ProcessSingleton::kTimeoutInSeconds;
 
@@ -951,7 +952,8 @@
     // We've already locked things, so we can't have lost the startup race,
     // but something doesn't like us.
     LOG(ERROR) << "Failed to create symlinks.";
-    socket_dir_.Delete();
+    if (!socket_dir_.Delete())
+      LOG(ERROR) << "Encountered a problem when deleting socket directory.";
     return false;
   }
 
diff --git a/chrome/browser/process_singleton_linux_uitest.cc b/chrome/browser/process_singleton_linux_uitest.cc
index 6abcefe..6b4d8e7 100644
--- a/chrome/browser/process_singleton_linux_uitest.cc
+++ b/chrome/browser/process_singleton_linux_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,9 +14,9 @@
 #include "base/eintr_wrapper.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -146,7 +146,7 @@
   int original_tab_count = GetTabCount();
 
   EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED,
-            NotifyOtherProcess(url, action_timeout_ms()));
+            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
   EXPECT_EQ(original_tab_count + 1, GetTabCount());
   EXPECT_EQ(url, GetActiveTabURL().spec());
 }
@@ -167,10 +167,10 @@
 
   std::string url("about:blank");
   EXPECT_EQ(ProcessSingleton::PROCESS_NONE,
-            NotifyOtherProcess(url, action_timeout_ms()));
+            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
 
   // Wait for a while to make sure the browser process is actually killed.
-  EXPECT_FALSE(CrashAwareSleep(sleep_timeout_ms()));
+  EXPECT_FALSE(CrashAwareSleep(TestTimeouts::action_timeout_ms()));
 }
 
 // Test that we don't kill ourselves by accident if a lockfile with the same pid
@@ -195,7 +195,7 @@
 
   std::string url("about:blank");
   EXPECT_EQ(ProcessSingleton::PROCESS_NONE,
-            NotifyOtherProcess(url, action_timeout_ms()));
+            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
   // If we've gotten to this point without killing ourself, the test succeeded.
 }
 
@@ -209,7 +209,7 @@
 
   std::string url("about:blank");
   EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED,
-            NotifyOtherProcess(url, action_timeout_ms()));
+            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
   EXPECT_EQ(original_tab_count + 1, GetTabCount());
   EXPECT_EQ(url, GetActiveTabURL().spec());
 }
@@ -224,14 +224,14 @@
   // Kill the browser process, so that it does not respond on the socket.
   kill(pid, SIGKILL);
   // Wait for a while to make sure the browser process is actually killed.
-  EXPECT_FALSE(CrashAwareSleep(sleep_timeout_ms()));
+  EXPECT_FALSE(CrashAwareSleep(TestTimeouts::action_timeout_ms()));
 
   EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
   EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
 
   std::string url("about:blank");
   EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
-            NotifyOtherProcess(url, action_timeout_ms()));
+            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
 
   ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
 }
@@ -246,14 +246,14 @@
   // Kill the browser process, so that it does not respond on the socket.
   kill(pid, SIGKILL);
   // Wait for a while to make sure the browser process is actually killed.
-  EXPECT_FALSE(CrashAwareSleep(sleep_timeout_ms()));
+  EXPECT_FALSE(CrashAwareSleep(TestTimeouts::action_timeout_ms()));
 
   EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
   EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
 
   std::string url("about:blank");
   EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
-            NotifyOtherProcessOrCreate(url, action_timeout_ms()));
+            NotifyOtherProcessOrCreate(url, TestTimeouts::action_timeout_ms()));
 
   ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
 }
@@ -295,5 +295,5 @@
 
   std::string url("about:blank");
   EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
-            NotifyOtherProcessOrCreate(url, action_timeout_ms()));
+            NotifyOtherProcessOrCreate(url, TestTimeouts::action_timeout_ms()));
 }
diff --git a/chrome/browser/process_singleton_mac_unittest.cc b/chrome/browser/process_singleton_mac_unittest.cc
index bdbeff6..978f6f9 100644
--- a/chrome/browser/process_singleton_mac_unittest.cc
+++ b/chrome/browser/process_singleton_mac_unittest.cc
@@ -25,8 +25,7 @@
 
     // Put the lock in a temporary directory.  Doesn't need to be a
     // full profile to test this code.
-    temp_dir_.CreateUniqueTempDir();
-    ASSERT_TRUE(temp_dir_.IsValid());
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     lock_path_ = temp_dir_.path().Append(chrome::kSingletonLockFilename);
   }
 
diff --git a/chrome/browser/process_singleton_uitest.cc b/chrome/browser/process_singleton_uitest.cc
index 235f181..cc9ec74 100644
--- a/chrome/browser/process_singleton_uitest.cc
+++ b/chrome/browser/process_singleton_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,6 +19,7 @@
 #include "base/ref_counted.h"
 #include "base/scoped_temp_dir.h"
 #include "base/threading/thread.h"
+#include "base/test/test_timeouts.h"
 #include "base/synchronization/waitable_event.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_constants.h"
@@ -38,7 +39,7 @@
   explicit ChromeStarter(int timeout_ms, const FilePath& user_data_dir)
       : ready_event_(false /* manual */, false /* signaled */),
         done_event_(false /* manual */, false /* signaled */),
-        process_handle_(NULL),
+        process_handle_(base::kNullProcessHandle),
         process_terminated_(false),
         timeout_ms_(timeout_ms),
         user_data_dir_(user_data_dir) {
@@ -136,7 +137,7 @@
       // We use a manual reset so that all threads wake up at once when signaled
       // and thus we must manually reset it for each attempt.
       : threads_waker_(true /* manual */, false /* signaled */) {
-    temp_profile_dir_.CreateUniqueTempDir();
+    EXPECT_TRUE(temp_profile_dir_.CreateUniqueTempDir());
   }
 
   void SetUp() {
@@ -144,8 +145,8 @@
     for (size_t i = 0; i < kNbThreads; ++i) {
       chrome_starter_threads_[i].reset(new base::Thread("ChromeStarter"));
       ASSERT_TRUE(chrome_starter_threads_[i]->Start());
-      chrome_starters_[i] = new ChromeStarter(action_max_timeout_ms(),
-                                              temp_profile_dir_.path());
+      chrome_starters_[i] = new ChromeStarter(
+          TestTimeouts::action_max_timeout_ms(), temp_profile_dir_.path());
     }
   }
 
diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc
index 47e28dd..17910dc 100644
--- a/chrome/browser/process_singleton_win.cc
+++ b/chrome/browser/process_singleton_win.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/process_singleton.h"
 
-#include "app/l10n_util.h"
-#include "app/win/hwnd_util.h"
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/file_path.h"
@@ -25,6 +23,8 @@
 #include "chrome/common/result_codes.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/win/hwnd_util.h"
 
 namespace {
 
@@ -42,10 +42,9 @@
 // Look for a Chrome instance that uses the same profile directory.
 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
     : window_(NULL), locked_(false), foreground_window_(NULL) {
-  std::wstring user_data_dir_str(user_data_dir.ToWStringHack());
   remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
                                 chrome::kMessageWindowClass,
-                                user_data_dir_str.c_str());
+                                user_data_dir.value().c_str());
   if (!remote_window_) {
     // Make sure we will be the one and only process creating the window.
     // We use a named Mutex since we are protecting against multi-process
@@ -68,7 +67,7 @@
     // was given to us.
     remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
                                   chrome::kMessageWindowClass,
-                                  user_data_dir_str.c_str());
+                                  user_data_dir.value().c_str());
     if (!remote_window_)
       Create();
     BOOL success = ReleaseMutex(only_me);
@@ -195,7 +194,7 @@
                          0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0);
   DCHECK(window_);
 
-  app::win::SetWindowUserData(window_, this);
+  ui::SetWindowUserData(window_, this);
   return true;
 }
 
diff --git a/chrome/browser/profile_import_process_host.cc b/chrome/browser/profile_import_process_host.cc
index 3663ef7..b2bfb26 100644
--- a/chrome/browser/profile_import_process_host.cc
+++ b/chrome/browser/profile_import_process_host.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/profile_import_process_host.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/string_number_conversions.h"
@@ -14,6 +13,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "grit/generated_resources.h"
 #include "ipc/ipc_switches.h"
+#include "ui/base/l10n/l10n_util.h"
 
 ProfileImportProcessHost::ProfileImportProcessHost(
     ResourceDispatcherHost* resource_dispatcher,
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index b03ca69..a11ec6e 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/profiles/profile.h"
 
-#include "app/resource_bundle.h"
+#include <string>
+
 #include "base/command_line.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
@@ -16,12 +17,15 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chrome_blob_storage_context.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extension_pref_store.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/file_system/browser_file_system_helper.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/net/pref_proxy_config_service.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/ssl/ssl_host_state.h"
 #include "chrome/browser/sync/profile_sync_service.h"
@@ -37,9 +41,11 @@
 #include "grit/browser_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/transport_security_state.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/database/database_tracker.h"
+
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
 #endif
 
 #if defined(OS_WIN)
@@ -68,7 +74,7 @@
     context->CleanupOnUIThread();
 }
 
-} // namespace
+}  // namespace
 
 #ifdef ANDROID
 // Android moved this to profile_android.cc to avoid compiling this file.
@@ -79,6 +85,9 @@
 }
 
 // static
+const char* Profile::kProfileKey = "__PROFILE__";
+
+// static
 const ProfileId Profile::InvalidProfileId = static_cast<ProfileId>(0);
 
 // static
@@ -113,6 +122,7 @@
   // in user's profile for other platforms as well.
   prefs->RegisterStringPref(prefs::kApplicationLocale, "");
   prefs->RegisterStringPref(prefs::kApplicationLocaleBackup, "");
+  prefs->RegisterStringPref(prefs::kApplicationLocaleAccepted, "");
 #endif
 }
 
@@ -121,6 +131,16 @@
   return default_request_context_;
 }
 
+bool Profile::IsGuestSession() {
+#if defined(OS_CHROMEOS)
+  static bool is_guest_session =
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession);
+  return is_guest_session;
+#else
+  return false;
+#endif
+}
+
 bool Profile::IsSyncAccessible() {
   ProfileSyncService* syncService = GetProfileSyncService();
   return syncService && !syncService->IsManaged();
@@ -137,6 +157,7 @@
  public:
   explicit OffTheRecordProfileImpl(Profile* real_profile)
       : profile_(real_profile),
+        prefs_(real_profile->GetOffTheRecordPrefs()),
         start_time_(Time::Now()) {
     request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this);
     extension_process_manager_.reset(ExtensionProcessManager::Create(this));
@@ -145,6 +166,8 @@
 
     background_contents_service_.reset(
         new BackgroundContentsService(this, CommandLine::ForCurrentProcess()));
+
+    DCHECK(real_profile->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled));
   }
 
   virtual ~OffTheRecordProfileImpl() {
@@ -162,6 +185,9 @@
             &webkit_database::DatabaseTracker::DeleteIncognitoDBDirectory));
 
     BrowserList::RemoveObserver(this);
+
+    if (pref_proxy_config_tracker_)
+      pref_proxy_config_tracker_->DetachFromPrefService();
   }
 
   virtual ProfileId GetRuntimeId() {
@@ -199,7 +225,8 @@
           NewRunnableMethod(appcache_service_.get(),
                             &ChromeAppCacheService::InitializeOnIOThread,
                             GetPath(), IsOffTheRecord(),
-                            make_scoped_refptr(GetHostContentSettingsMap())));
+                            make_scoped_refptr(GetHostContentSettingsMap()),
+                            false));
     }
     return appcache_service_;
   }
@@ -252,6 +279,10 @@
     return GetOriginalProfile()->GetExtensionEventRouter();
   }
 
+  virtual ExtensionIOEventRouter* GetExtensionIOEventRouter() {
+    return GetOriginalProfile()->GetExtensionIOEventRouter();
+  }
+
   virtual SSLHostState* GetSSLHostState() {
     if (!ssl_host_state_.get())
       ssl_host_state_.reset(new SSLHostState());
@@ -312,7 +343,11 @@
   }
 
   virtual PrefService* GetPrefs() {
-    return profile_->GetPrefs();
+    return prefs_;
+  }
+
+  virtual PrefService* GetOffTheRecordPrefs() {
+    return prefs_;
   }
 
   virtual TemplateURLModel* GetTemplateURLModel() {
@@ -341,7 +376,7 @@
     return NULL;
   }
 
-  virtual fileapi::SandboxedFileSystemContext* GetFileSystemContext() {
+  virtual fileapi::FileSystemContext* GetFileSystemContext() {
     if (!file_system_context_)
       file_system_context_ = CreateFileSystemContext(
           GetPath(), IsOffTheRecord());
@@ -599,12 +634,26 @@
     return NULL;
   }
 
+  virtual ChromeURLDataManager* GetChromeURLDataManager() {
+    if (!chrome_url_data_manager_.get())
+      chrome_url_data_manager_.reset(new ChromeURLDataManager(this));
+    return chrome_url_data_manager_.get();
+  }
+
   virtual PromoCounter* GetInstantPromoCounter() {
     return NULL;
   }
 
+#if defined(OS_CHROMEOS)
+  virtual void ChangeAppLocale(const std::string& locale, AppLocaleChangedVia) {
+  }
+#endif  // defined(OS_CHROMEOS)
+
   virtual PrefProxyConfigTracker* GetProxyConfigTracker() {
-    return profile_->GetProxyConfigTracker();
+    if (!pref_proxy_config_tracker_)
+      pref_proxy_config_tracker_ = new PrefProxyConfigTracker(GetPrefs());
+
+    return pref_proxy_config_tracker_;
   }
 
   virtual PrerenderManager* GetPrerenderManager() {
@@ -620,6 +669,9 @@
   // The real underlying profile.
   Profile* profile_;
 
+  // Weak pointer owned by |profile_|.
+  PrefService* prefs_;
+
   scoped_ptr<ExtensionProcessManager> extension_process_manager_;
 
   // The context to use for requests made from this OTR session.
@@ -673,11 +725,34 @@
   scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
 
   // The file_system context for this profile.
-  scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+  scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+
+  scoped_refptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
+
+  scoped_ptr<ChromeURLDataManager> chrome_url_data_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl);
 };
 
+#if defined(OS_CHROMEOS)
+// Special case of the OffTheRecordProfileImpl which is used while Guest
+// session in CrOS.
+class GuestSessionProfile : public OffTheRecordProfileImpl {
+ public:
+  explicit GuestSessionProfile(Profile* real_profile)
+      : OffTheRecordProfileImpl(real_profile) {
+  }
+
+  virtual PersonalDataManager* GetPersonalDataManager() {
+    return GetOriginalProfile()->GetPersonalDataManager();
+  }
+};
+#endif
+
 Profile* Profile::CreateOffTheRecordProfile() {
+#if defined(OS_CHROMEOS)
+  if (Profile::IsGuestSession())
+    return new GuestSessionProfile(this);
+#endif
   return new OffTheRecordProfileImpl(this);
 }
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 9df977c..b1b8817 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -40,7 +40,7 @@
 }
 
 namespace fileapi {
-class SandboxedFileSystemContext;
+class FileSystemContext;
 }
 
 class AutocompleteClassifier;
@@ -50,7 +50,7 @@
 class BrowserThemeProvider;
 class ChromeAppCacheService;
 class ChromeBlobStorageContext;
-class ChromeURLRequestContextGetter;
+class ChromeURLDataManager;
 class CloudPrintProxyService;
 class DesktopNotificationService;
 class DownloadManager;
@@ -58,7 +58,9 @@
 class ExtensionDevToolsManager;
 class ExtensionEventRouter;
 class ExtensionInfoMap;
+class ExtensionIOEventRouter;
 class ExtensionMessageService;
+class ExtensionPrefValueMap;
 class ExtensionProcessManager;
 class ExtensionService;
 class FaviconService;
@@ -91,7 +93,6 @@
 class TabRestoreService;
 class TemplateURLFetcher;
 class TemplateURLModel;
-class ThemeProvider;
 class TokenService;
 class TransportSecurityPersister;
 class URLRequestContextGetter;
@@ -132,6 +133,9 @@
     IMPLICIT_ACCESS
   };
 
+  // Key used to bind profile to the widget with which it is associated.
+  static const char* kProfileKey;
+
   // Value that represents no profile Id.
   static const ProfileId InvalidProfileId;
 
@@ -218,6 +222,9 @@
   // Accessor. The instance is created at startup.
   virtual ExtensionEventRouter* GetExtensionEventRouter() = 0;
 
+  // Accessor. The instance is created at startup.
+  virtual ExtensionIOEventRouter* GetExtensionIOEventRouter() = 0;
+
   // Retrieves a pointer to the SSLHostState associated with this profile.
   // The SSLHostState is lazily created the first time that this method is
   // called.
@@ -226,8 +233,7 @@
   // Retrieves a pointer to the TransportSecurityState associated with
   // this profile.  The TransportSecurityState is lazily created the
   // first time that this method is called.
-  virtual net::TransportSecurityState*
-      GetTransportSecurityState() = 0;
+  virtual net::TransportSecurityState* GetTransportSecurityState() = 0;
 
   // Retrieves a pointer to the FaviconService associated with this
   // profile.  The FaviconService is lazily created the first time
@@ -284,6 +290,11 @@
   // time that this method is called.
   virtual PrefService* GetPrefs() = 0;
 
+  // Retrieves a pointer to the PrefService that manages the preferences
+  // for OffTheRecord Profiles.  This PrefService is lazily created the first
+  // time that this method is called.
+  virtual PrefService* GetOffTheRecordPrefs() = 0;
+
   // Returns the TemplateURLModel for this profile. This is owned by the
   // the Profile.
   virtual TemplateURLModel* GetTemplateURLModel() = 0;
@@ -302,7 +313,7 @@
   // Returns the FileSystemContext associated to this profile.  The context
   // is lazily created the first time this method is called.  This is owned
   // by the profile.
-  virtual fileapi::SandboxedFileSystemContext* GetFileSystemContext() = 0;
+  virtual fileapi::FileSystemContext* GetFileSystemContext() = 0;
 
   // Returns the BrowserSignin object assigned to this profile.
   virtual BrowserSignin* GetBrowserSignin() = 0;
@@ -486,7 +497,25 @@
   // Gets the policy context associated with this profile.
   virtual policy::ProfilePolicyContext* GetPolicyContext() = 0;
 
+  // Returns the ChromeURLDataManager for this profile.
+  virtual ChromeURLDataManager* GetChromeURLDataManager() = 0;
+
 #if defined(OS_CHROMEOS)
+  enum AppLocaleChangedVia {
+    // Caused by chrome://settings change.
+    APP_LOCALE_CHANGED_VIA_SETTINGS,
+    // Locale has been reverted via LocaleChangeGuard.
+    APP_LOCALE_CHANGED_VIA_REVERT,
+    // From login screen.
+    APP_LOCALE_CHANGED_VIA_LOGIN,
+    // Source unknown.
+    APP_LOCALE_CHANGED_VIA_UNKNOWN
+  };
+
+  // Changes application locale for a profile.
+  virtual void ChangeAppLocale(
+      const std::string& locale, AppLocaleChangedVia via) = 0;
+
   // Returns ChromeOS's ProxyConfigServiceImpl, creating if not yet created.
   virtual chromeos::ProxyConfigServiceImpl*
       GetChromeOSProxyConfigServiceImpl() = 0;
@@ -504,6 +533,9 @@
   // profile.
   virtual PrerenderManager* GetPrerenderManager() = 0;
 
+  // Returns whether it is a guest session.
+  static bool IsGuestSession();
+
 #ifdef UNIT_TEST
   // Use with caution.  GetDefaultRequestContext may be called on any thread!
   static void set_default_request_context(URLRequestContextGetter* c) {
@@ -543,6 +575,8 @@
   Profile* CreateOffTheRecordProfile();
 
  protected:
+  friend class OffTheRecordProfileImpl;
+
   static URLRequestContextGetter* default_request_context_;
 
  private:
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 34a50fc..0fde233 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/profiles/profile_impl.h"
 
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/file_path.h"
@@ -14,7 +13,6 @@
 #include "base/scoped_ptr.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
-#include "chrome/browser/about_flags.h"
 #include "chrome/browser/appcache/chrome_appcache_service.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
@@ -27,13 +25,16 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/chrome_blob_storage_context.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/defaults.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
 #include "chrome/browser/dom_ui/ntp_resource_cache.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/extensions/default_apps.h"
 #include "chrome/browser/extensions/extension_devtools_manager.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
-#include "chrome/browser/extensions/extension_info_map.h"
 #include "chrome/browser/extensions/extension_event_router.h"
+#include "chrome/browser/extensions/extension_info_map.h"
+#include "chrome/browser/extensions/extension_io_event_router.h"
 #include "chrome/browser/extensions/extension_message_service.h"
 #include "chrome/browser/extensions/extension_pref_store.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
@@ -46,8 +47,8 @@
 #include "chrome/browser/history/history.h"
 #include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/host_zoom_map.h"
-#include "chrome/browser/instant/instant_controller.h"
 #include "chrome/browser/in_process_webkit/webkit_context.h"
+#include "chrome/browser/instant/instant_controller.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/gaia/token_service.h"
 #include "chrome/browser/net/net_pref_observer.h"
@@ -55,8 +56,8 @@
 #include "chrome/browser/net/ssl_config_service_manager.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/password_manager/password_store_default.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
 #include "chrome/browser/policy/profile_policy_context.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/pref_value_store.h"
@@ -93,10 +94,11 @@
 #include "grit/browser_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/transport_security_state.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/database/database_tracker.h"
 
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
 #endif
 
 #if defined(OS_WIN)
@@ -119,6 +121,7 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/preferences.h"
 #endif
 
@@ -127,11 +130,6 @@
 
 namespace {
 
-void CleanupRequestContext(ChromeURLRequestContextGetter* context) {
-  if (context)
-    context->CleanupOnUIThread();
-}
-
 // Delay, in milliseconds, before we explicitly create the SessionService.
 static const int kCreateSessionServiceDelayMS = 500;
 
@@ -247,9 +245,6 @@
     : path_(path),
       visited_link_event_listener_(new VisitedLinkEventListener()),
       extension_devtools_manager_(NULL),
-      request_context_(NULL),
-      media_request_context_(NULL),
-      extensions_request_context_(NULL),
       host_content_settings_map_(NULL),
       host_zoom_map_(NULL),
       history_service_created_(false),
@@ -278,15 +273,32 @@
   pref_change_registrar_.Add(prefs::kEnableAutoSpellCorrect, this);
   pref_change_registrar_.Add(prefs::kClearSiteDataOnExit, this);
 
-  // Convert active labs into switches. Modifies the current command line.
-  about_flags::ConvertFlagsToSwitches(prefs, CommandLine::ForCurrentProcess());
-
   // It would be nice to use PathService for fetching this directory, but
   // the cache directory depends on the profile directory, which isn't available
   // to PathService.
   chrome::GetUserCacheDirectory(path_, &base_cache_path_);
   file_util::CreateDirectory(base_cache_path_);
 
+  FilePath cookie_path = GetPath();
+  cookie_path = cookie_path.Append(chrome::kCookieFilename);
+  FilePath cache_path = base_cache_path_;
+  int cache_max_size;
+  GetCacheParameters(kNormalContext, &cache_path, &cache_max_size);
+  cache_path = GetCachePath(cache_path);
+
+  FilePath media_cache_path = base_cache_path_;
+  int media_cache_max_size;
+  GetCacheParameters(kMediaContext, &media_cache_path, &media_cache_max_size);
+  media_cache_path = GetMediaCachePath(media_cache_path);
+
+  FilePath extensions_cookie_path = GetPath();
+  extensions_cookie_path =
+      extensions_cookie_path.Append(chrome::kExtensionsCookieFilename);
+
+  io_data_.Init(cookie_path, cache_path, cache_max_size,
+                media_cache_path, media_cache_max_size, extensions_cookie_path,
+                this);
+
   // Listen for theme installations from our original profile.
   registrar_.Add(this, NotificationType::THEME_INSTALLED,
                  Source<Profile>(GetOriginalProfile()));
@@ -321,6 +333,7 @@
   background_contents_service_.reset(
       new BackgroundContentsService(this, CommandLine::ForCurrentProcess()));
 
+  extension_io_event_router_ = new ExtensionIOEventRouter(this);
   extension_info_map_ = new ExtensionInfoMap();
 
   GetPolicyContext()->Initialize();
@@ -346,6 +359,7 @@
 
   extension_process_manager_.reset(ExtensionProcessManager::Create(this));
   extension_event_router_.reset(new ExtensionEventRouter(this));
+  extension_io_event_router_ = new ExtensionIOEventRouter(this);
   extension_message_service_ = new ExtensionMessageService(this);
 
   ExtensionErrorReporter::Init(true);  // allow noisy errors.
@@ -375,29 +389,60 @@
 
 void ProfileImpl::RegisterComponentExtensions() {
   // Register the component extensions.
-  typedef std::list<std::pair<std::string, int> > ComponentExtensionList;
+  //
+  // Component extension manifest must contain a 'key' property with a unique
+  // public key, serialized in base64. You can create a suitable value with the
+  // following commands on a unixy system:
+  //
+  //   ssh-keygen -t rsa -b 1024 -N '' -f /tmp/key.pem
+  //   rsa -pubout -outform DER < /tmp/key.pem 2>/dev/null | base64 -w 0
+  typedef std::list<std::pair<FilePath::StringType, int> >
+      ComponentExtensionList;
   ComponentExtensionList component_extensions;
 
   // Bookmark manager.
-  component_extensions.push_back(
-      std::make_pair("bookmark_manager", IDR_BOOKMARKS_MANIFEST));
+  component_extensions.push_back(std::make_pair(
+      FILE_PATH_LITERAL("bookmark_manager"),
+      IDR_BOOKMARKS_MANIFEST));
 
 #if defined(TOUCH_UI)
-  component_extensions.push_back(
-      std::make_pair("keyboard", IDR_KEYBOARD_MANIFEST));
+  component_extensions.push_back(std::make_pair(
+      FILE_PATH_LITERAL("keyboard"),
+      IDR_KEYBOARD_MANIFEST));
+#endif
+
+#if defined(OS_CHROMEOS)
+  component_extensions.push_back(std::make_pair(
+      FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile"),
+      IDR_MOBILE_MANIFEST));
+
+#if defined(OFFICIAL_BUILD)
+  if (browser_defaults::enable_help_app) {
+    component_extensions.push_back(std::make_pair(
+        FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp"),
+        IDR_HELP_MANIFEST));
+  }
+
+  component_extensions.push_back(std::make_pair(
+      FILE_PATH_LITERAL("/usr/share/chromeos-assets/getstarted"),
+      IDR_GETSTARTED_MANIFEST));
+#endif
 #endif
 
   // Web Store.
-  component_extensions.push_back(
-      std::make_pair("web_store", IDR_WEBSTORE_MANIFEST));
+  component_extensions.push_back(std::make_pair(
+      FILE_PATH_LITERAL("web_store"),
+      IDR_WEBSTORE_MANIFEST));
 
   for (ComponentExtensionList::iterator iter = component_extensions.begin();
     iter != component_extensions.end(); ++iter) {
-    FilePath path;
-    if (PathService::Get(chrome::DIR_RESOURCES, &path)) {
-      path = path.AppendASCII(iter->first);
-    } else {
-      NOTREACHED();
+    FilePath path(iter->first);
+    if (!path.IsAbsolute()) {
+      if (PathService::Get(chrome::DIR_RESOURCES, &path)) {
+        path = path.Append(iter->first);
+      } else {
+        NOTREACHED();
+      }
     }
 
     std::string manifest =
@@ -406,6 +451,20 @@
     extensions_service_->register_component_extension(
         ExtensionService::ComponentExtensionInfo(manifest, path));
   }
+
+#if defined(OS_CHROMEOS)
+  // Register access extensions only if accessibility is enabled.
+  if (g_browser_process->local_state()->
+      GetBoolean(prefs::kAccessibilityEnabled)) {
+    FilePath path = FilePath(extension_misc::kAccessExtensionPath)
+        .AppendASCII("access_chromevox");
+    std::string manifest =
+        ResourceBundle::GetSharedInstance().GetRawDataResource(
+            IDR_CHROMEVOX_MANIFEST).as_string();
+    extensions_service_->register_component_extension(
+        ExtensionService::ComponentExtensionInfo(manifest, path));
+  }
+#endif
 }
 
 void ProfileImpl::InstallDefaultApps() {
@@ -498,12 +557,10 @@
   if (spellcheck_host_.get())
     spellcheck_host_->UnsetObserver();
 
-  if (default_request_context_ == request_context_)
+  if (io_data_.HasMainRequestContext() &&
+      default_request_context_ == GetRequestContext()) {
     default_request_context_ = NULL;
-
-  CleanupRequestContext(request_context_);
-  CleanupRequestContext(media_request_context_);
-  CleanupRequestContext(extensions_request_context_);
+  }
 
   // HistoryService may call into the BookmarkModel, as such we need to
   // delete HistoryService before the BookmarkModel. The destructor for
@@ -517,6 +574,9 @@
   // HistoryService first.
   favicon_service_ = NULL;
 
+  if (extension_io_event_router_)
+    extension_io_event_router_->DestroyingProfile();
+
   if (extension_message_service_)
     extension_message_service_->DestroyingProfile();
 
@@ -575,7 +635,8 @@
         NewRunnableMethod(appcache_service_.get(),
                           &ChromeAppCacheService::InitializeOnIOThread,
                           GetPath(), IsOffTheRecord(),
-                          make_scoped_refptr(GetHostContentSettingsMap())));
+                          make_scoped_refptr(GetHostContentSettingsMap()),
+                          clear_local_state_on_exit_));
   }
   return appcache_service_;
 }
@@ -634,6 +695,10 @@
   return extension_event_router_.get();
 }
 
+ExtensionIOEventRouter* ProfileImpl::GetExtensionIOEventRouter() {
+  return extension_io_event_router_.get();
+}
+
 SSLHostState* ProfileImpl::GetSSLHostState() {
   if (!ssl_host_state_.get())
     ssl_host_state_.reset(new SSLHostState());
@@ -657,15 +722,20 @@
 
 PrefService* ProfileImpl::GetPrefs() {
   if (!prefs_.get()) {
-    ExtensionPrefStore* extension_pref_store = new ExtensionPrefStore;
-    prefs_.reset(PrefService::CreatePrefService(GetPrefFilePath(),
-                                                extension_pref_store,
-                                                GetOriginalProfile()));
+    prefs_.reset(PrefService::CreatePrefService(
+        GetPrefFilePath(),
+        new ExtensionPrefStore(GetExtensionPrefValueMap(), false),
+        GetOriginalProfile()));
 
     // The Profile class and ProfileManager class may read some prefs so
     // register known prefs as soon as possible.
     Profile::RegisterUserPrefs(prefs_.get());
     browser::RegisterUserPrefs(prefs_.get());
+    // TODO(mirandac): remove migration code after 6 months (crbug.com/69995).
+    if (g_browser_process->local_state()) {
+      browser::MigrateBrowserPrefs(prefs_.get(),
+                                   g_browser_process->local_state());
+    }
 
     // The last session exited cleanly if there is no pref for
     // kSessionExitedCleanly or the value for kSessionExitedCleanly is true.
@@ -681,7 +751,7 @@
     extension_prefs_.reset(new ExtensionPrefs(
         prefs_.get(),
         GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),
-        extension_pref_store));
+        GetExtensionPrefValueMap()));
 
     DCHECK(!net_pref_observer_.get());
     net_pref_observer_.reset(new NetPrefObserver(prefs_.get()));
@@ -690,6 +760,16 @@
   return prefs_.get();
 }
 
+PrefService* ProfileImpl::GetOffTheRecordPrefs() {
+  if (!otr_prefs_.get()) {
+    // The new ExtensionPrefStore is ref_counted and the new PrefService
+    // stores a reference so that we do not leak memory here.
+    otr_prefs_.reset(GetPrefs()->CreateIncognitoPrefService(
+        new ExtensionPrefStore(GetExtensionPrefValueMap(), true)));
+  }
+  return otr_prefs_.get();
+}
+
 FilePath ProfileImpl::GetPrefFilePath() {
   FilePath pref_file_path = path_;
   pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename);
@@ -697,47 +777,26 @@
 }
 
 URLRequestContextGetter* ProfileImpl::GetRequestContext() {
-  if (!request_context_) {
-    FilePath cookie_path = GetPath();
-    cookie_path = cookie_path.Append(chrome::kCookieFilename);
-    FilePath cache_path = base_cache_path_;
-    int max_size;
-    GetCacheParameters(kNormalContext, &cache_path, &max_size);
-
-    cache_path = GetCachePath(cache_path);
-    request_context_ = ChromeURLRequestContextGetter::CreateOriginal(
-        this, cookie_path, cache_path, max_size);
-
-    // The first request context is always a normal (non-OTR) request context.
-    // Even when Chromium is started in OTR mode, a normal profile is always
-    // created first.
-    if (!default_request_context_) {
-      default_request_context_ = request_context_;
-      request_context_->set_is_main(true);
-      // TODO(eroman): this isn't terribly useful anymore now that the
-      // URLRequestContext is constructed by the IO thread...
-      NotificationService::current()->Notify(
-          NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
-          NotificationService::AllSources(), NotificationService::NoDetails());
-    }
+  URLRequestContextGetter* request_context =
+      io_data_.GetMainRequestContextGetter();
+  // The first request context is always a normal (non-OTR) request context.
+  // Even when Chromium is started in OTR mode, a normal profile is always
+  // created first.
+  if (!default_request_context_) {
+    default_request_context_ = request_context;
+    request_context->set_is_main(true);
+    // TODO(eroman): this isn't terribly useful anymore now that the
+    // net::URLRequestContext is constructed by the IO thread...
+    NotificationService::current()->Notify(
+        NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
+        NotificationService::AllSources(), NotificationService::NoDetails());
   }
 
-  return request_context_;
+  return request_context;
 }
 
 URLRequestContextGetter* ProfileImpl::GetRequestContextForMedia() {
-  if (!media_request_context_) {
-    FilePath cache_path = base_cache_path_;
-    int max_size;
-    GetCacheParameters(kMediaContext, &cache_path, &max_size);
-
-    cache_path = GetMediaCachePath(cache_path);
-    media_request_context_ =
-        ChromeURLRequestContextGetter::CreateOriginalForMedia(
-            this, cache_path, max_size);
-  }
-
-  return media_request_context_;
+  return io_data_.GetMediaRequestContextGetter();
 }
 
 FaviconService* ProfileImpl::GetFaviconService(ServiceAccessType sat) {
@@ -750,16 +809,7 @@
 }
 
 URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() {
-  if (!extensions_request_context_) {
-    FilePath cookie_path = GetPath();
-    cookie_path = cookie_path.Append(chrome::kExtensionsCookieFilename);
-
-    extensions_request_context_ =
-        ChromeURLRequestContextGetter::CreateOriginalForExtensions(
-            this, cookie_path);
-  }
-
-  return extensions_request_context_;
+  return io_data_.GetExtensionsRequestContextGetter();
 }
 
 void ProfileImpl::RegisterExtensionWithRequestContexts(
@@ -1002,7 +1052,7 @@
   return personal_data_manager_.get();
 }
 
-fileapi::SandboxedFileSystemContext* ProfileImpl::GetFileSystemContext() {
+fileapi::FileSystemContext* ProfileImpl::GetFileSystemContext() {
   if (!file_system_context_.get())
     file_system_context_ = CreateFileSystemContext(
         GetPath(), IsOffTheRecord());
@@ -1170,6 +1220,12 @@
           Source<Profile>(this), NotificationService::NoDetails());
 }
 
+ExtensionPrefValueMap* ProfileImpl::GetExtensionPrefValueMap() {
+  if (!extension_pref_value_map_.get())
+    extension_pref_value_map_.reset(new ExtensionPrefValueMap);
+  return extension_pref_value_map_.get();
+}
+
 WebKitContext* ProfileImpl::GetWebKitContext() {
   if (!webkit_context_.get())
     webkit_context_ = new WebKitContext(this, clear_local_state_on_exit_);
@@ -1214,9 +1270,14 @@
     } else if (*pref_name_in == prefs::kClearSiteDataOnExit) {
       clear_local_state_on_exit_ =
           prefs->GetBoolean(prefs::kClearSiteDataOnExit);
-      if (webkit_context_)
+      if (webkit_context_) {
         webkit_context_->set_clear_local_state_on_exit(
             clear_local_state_on_exit_);
+      }
+      if (appcache_service_) {
+        appcache_service_->SetClearLocalStateOnExit(
+            clear_local_state_on_exit_);
+      }
     }
   } else if (NotificationType::THEME_INSTALLED == type) {
     DCHECK_EQ(Source<Profile>(source).ptr(), GetOriginalProfile());
@@ -1242,12 +1303,13 @@
 
 ProfileSyncService* ProfileImpl::GetProfileSyncService() {
 #if defined(OS_CHROMEOS)
-  // If kLoginManager is specified, we shouldn't call this unless login has
-  // completed and specified cros_user. Guard with if (HasProfileSyncService())
-  // where this might legitimately get called before login has completed.
-  if (!sync_service_.get() &&
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginManager)) {
-    LOG(FATAL) << "GetProfileSyncService() called before login complete.";
+  if (!sync_service_.get()) {
+    // In ChromeOS, sync only gets initialized properly from login, when
+    // kLoginManager is specified. If this gets called before login, or
+    // during a debugging session without kLoginManager, this will return
+    // NULL, so ensure that calls either handle a NULL result, or use
+    // HasProfileSyncService() to guard against the call.
+    return NULL;
   }
 #endif
   return GetProfileSyncService("");
@@ -1311,6 +1373,12 @@
   return profile_policy_context_.get();
 }
 
+ChromeURLDataManager* ProfileImpl::GetChromeURLDataManager() {
+  if (!chrome_url_data_manager_.get())
+    chrome_url_data_manager_.reset(new ChromeURLDataManager(this));
+  return chrome_url_data_manager_.get();
+}
+
 PromoCounter* ProfileImpl::GetInstantPromoCounter() {
 #if defined(OS_WIN)
   // TODO: enable this when we're ready to turn on the promo.
@@ -1334,6 +1402,80 @@
 }
 
 #if defined(OS_CHROMEOS)
+void ProfileImpl::ChangeAppLocale(
+    const std::string& new_locale, AppLocaleChangedVia via) {
+  if (new_locale.empty()) {
+    NOTREACHED();
+    return;
+  }
+  PrefService* local_state = g_browser_process->local_state();
+  DCHECK(local_state);
+  if (local_state->IsManagedPreference(prefs::kApplicationLocale))
+    return;
+  std::string pref_locale = GetPrefs()->GetString(prefs::kApplicationLocale);
+  bool do_update_pref = true;
+  switch (via) {
+    case APP_LOCALE_CHANGED_VIA_SETTINGS:
+    case APP_LOCALE_CHANGED_VIA_REVERT: {
+      // We keep kApplicationLocaleBackup value as a reference.  In case value
+      // of kApplicationLocale preference would change due to sync from other
+      // device then kApplicationLocaleBackup value will trigger and allow us to
+      // show notification about automatic locale change in LocaleChangeGuard.
+      GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
+      GetPrefs()->ClearPref(prefs::kApplicationLocaleAccepted);
+      // We maintain kApplicationLocale property in both a global storage
+      // and user's profile.  Global property determines locale of login screen,
+      // while user's profile determines his personal locale preference.
+      break;
+    }
+    case APP_LOCALE_CHANGED_VIA_LOGIN: {
+      if (!pref_locale.empty()) {
+        DCHECK(pref_locale == new_locale);
+        std::string accepted_locale =
+            GetPrefs()->GetString(prefs::kApplicationLocaleAccepted);
+        if (accepted_locale == new_locale) {
+          // If locale is accepted then we do not want to show LocaleChange
+          // notification.  This notification is triggered by different values
+          // of kApplicationLocaleBackup and kApplicationLocale preferences,
+          // so make them identical.
+          GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
+        } else {
+          // Back up locale of login screen.
+          GetPrefs()->SetString(prefs::kApplicationLocaleBackup,
+                                g_browser_process->GetApplicationLocale());
+        }
+      } else {
+        std::string cur_locale = g_browser_process->GetApplicationLocale();
+        std::string backup_locale =
+            GetPrefs()->GetString(prefs::kApplicationLocaleBackup);
+        // Profile synchronization takes time and is not completed at that
+        // moment at first login.  So we initialize locale preference in steps:
+        // (1) first save it to temporary backup;
+        // (2) on next login we assume that synchronization is already completed
+        //     and we may finalize initialization.
+        GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
+        if (!backup_locale.empty())
+          GetPrefs()->SetString(prefs::kApplicationLocale, backup_locale);
+        do_update_pref = false;
+      }
+      break;
+    }
+    case APP_LOCALE_CHANGED_VIA_UNKNOWN:
+    default: {
+      NOTREACHED();
+      break;
+    }
+  }
+  if (do_update_pref)
+    GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
+  if (chromeos::UserManager::Get()->current_user_is_owner())
+    local_state->SetString(prefs::kOwnerLocale, new_locale);
+  local_state->SetString(prefs::kApplicationLocale, new_locale);
+
+  GetPrefs()->ScheduleSavePersistentPrefs();
+  local_state->ScheduleSavePersistentPrefs();
+}
+
 chromeos::ProxyConfigServiceImpl*
     ProfileImpl::GetChromeOSProxyConfigServiceImpl() {
   if (!chromeos_proxy_config_service_impl_) {
@@ -1358,10 +1500,9 @@
 }
 
 PrerenderManager* ProfileImpl::GetPrerenderManager() {
-  CommandLine* cl = CommandLine::ForCurrentProcess();
-  if (!cl->HasSwitch(switches::kEnablePagePrerender))
+  if (!PrerenderManager::IsPrerenderingEnabled())
     return NULL;
-  if (!prerender_manager_.get())
-    prerender_manager_.reset(new PrerenderManager(this));
-  return prerender_manager_.get();
+  if (!prerender_manager_)
+    prerender_manager_ = new PrerenderManager(this);
+  return prerender_manager_;
 }
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index ce29d28..d2b20f2 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,6 +13,7 @@
 #include "base/scoped_ptr.h"
 #include "base/timer.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/browser/spellcheck_host_observer.h"
 #include "chrome/common/notification_observer.h"
@@ -20,6 +21,7 @@
 
 class BackgroundModeManager;
 class ExtensionPrefs;
+class ExtensionPrefValueMap;
 class PrefService;
 
 #if defined(OS_CHROMEOS)
@@ -60,6 +62,7 @@
   virtual ExtensionProcessManager* GetExtensionProcessManager();
   virtual ExtensionMessageService* GetExtensionMessageService();
   virtual ExtensionEventRouter* GetExtensionEventRouter();
+  virtual ExtensionIOEventRouter* GetExtensionIOEventRouter();
   virtual FaviconService* GetFaviconService(ServiceAccessType sat);
   virtual HistoryService* GetHistoryService(ServiceAccessType sat);
   virtual HistoryService* GetHistoryServiceWithoutCreating();
@@ -68,11 +71,12 @@
   virtual WebDataService* GetWebDataServiceWithoutCreating();
   virtual PasswordStore* GetPasswordStore(ServiceAccessType sat);
   virtual PrefService* GetPrefs();
+  virtual PrefService* GetOffTheRecordPrefs();
   virtual TemplateURLModel* GetTemplateURLModel();
   virtual TemplateURLFetcher* GetTemplateURLFetcher();
   virtual DownloadManager* GetDownloadManager();
   virtual PersonalDataManager* GetPersonalDataManager();
-  virtual fileapi::SandboxedFileSystemContext* GetFileSystemContext();
+  virtual fileapi::FileSystemContext* GetFileSystemContext();
   virtual void InitThemes();
   virtual void SetTheme(const Extension* extension);
   virtual void SetNativeTheme();
@@ -127,8 +131,10 @@
   virtual PromoCounter* GetInstantPromoCounter();
   virtual BrowserSignin* GetBrowserSignin();
   virtual policy::ProfilePolicyContext* GetPolicyContext();
+  virtual ChromeURLDataManager* GetChromeURLDataManager();
 
 #if defined(OS_CHROMEOS)
+  virtual void ChangeAppLocale(const std::string& locale, AppLocaleChangedVia);
   virtual chromeos::ProxyConfigServiceImpl* GetChromeOSProxyConfigServiceImpl();
   virtual void SetupChromeOSEnterpriseExtensionObserver();
 #endif  // defined(OS_CHROMEOS)
@@ -167,15 +173,19 @@
   void RegisterComponentExtensions();
   void InstallDefaultApps();
 
+  ExtensionPrefValueMap* GetExtensionPrefValueMap();
+
   NotificationRegistrar registrar_;
   PrefChangeRegistrar pref_change_registrar_;
 
   FilePath path_;
   FilePath base_cache_path_;
+  scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
   // Keep prefs_ on top for destruction order because extension_prefs_,
   // net_pref_observer_, web_resource_service_ and background_contents_service_
   // store pointers to prefs_ and shall be destructed first.
   scoped_ptr<PrefService> prefs_;
+  scoped_ptr<PrefService> otr_prefs_;
   scoped_ptr<VisitedLinkEventListener> visited_link_event_listener_;
   scoped_ptr<VisitedLinkMaster> visited_link_master_;
   // Keep extension_prefs_ on top of extensions_service_ because the latter
@@ -187,6 +197,7 @@
   scoped_ptr<ExtensionProcessManager> extension_process_manager_;
   scoped_refptr<ExtensionMessageService> extension_message_service_;
   scoped_ptr<ExtensionEventRouter> extension_event_router_;
+  scoped_refptr<ExtensionIOEventRouter> extension_io_event_router_;
   scoped_ptr<SSLHostState> ssl_host_state_;
   scoped_refptr<net::TransportSecurityState>
       transport_security_state_;
@@ -205,11 +216,7 @@
   scoped_ptr<ProfileSyncService> sync_service_;
   scoped_refptr<CloudPrintProxyService> cloud_print_proxy_service_;
 
-  scoped_refptr<ChromeURLRequestContextGetter> request_context_;
-
-  scoped_refptr<ChromeURLRequestContextGetter> media_request_context_;
-
-  scoped_refptr<ChromeURLRequestContextGetter> extensions_request_context_;
+  ProfileIOData::Handle io_data_;
 
   scoped_ptr<SSLConfigServiceManager> ssl_config_service_manager_;
 
@@ -236,7 +243,7 @@
   scoped_ptr<StatusTray> status_tray_;
   scoped_refptr<PersonalDataManager> personal_data_manager_;
   scoped_ptr<PinnedTabService> pinned_tab_service_;
-  scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+  scoped_refptr<fileapi::FileSystemContext> file_system_context_;
   scoped_ptr<BrowserSignin> browser_signin_;
   bool history_service_created_;
   bool favicon_service_created_;
@@ -298,7 +305,9 @@
 
   scoped_refptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
 
-  scoped_ptr<PrerenderManager> prerender_manager_;
+  scoped_refptr<PrerenderManager> prerender_manager_;
+
+  scoped_ptr<ChromeURLDataManager> chrome_url_data_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileImpl);
 };
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
new file mode 100644
index 0000000..a2f6c5f
--- /dev/null
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/profiles/profile_io_data.h"
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/net/chrome_net_log.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+
+ProfileIOData::Handle::Handle() : io_data_(new ProfileIOData) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+ProfileIOData::Handle::~Handle() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (main_request_context_getter_)
+    main_request_context_getter_->CleanupOnUIThread();
+  if (media_request_context_getter_)
+    media_request_context_getter_->CleanupOnUIThread();
+  if (extensions_request_context_getter_)
+    extensions_request_context_getter_->CleanupOnUIThread();
+}
+
+void ProfileIOData::Handle::Init(const FilePath& cookie_path,
+                                 const FilePath& cache_path,
+                                 int cache_max_size,
+                                 const FilePath& media_cache_path,
+                                 int media_cache_max_size,
+                                 const FilePath& extensions_cookie_path,
+                                 Profile* profile) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!io_data_->lazy_params_.get());
+  LazyParams* lazy_params = new LazyParams;
+  lazy_params->cookie_path = cookie_path;
+  lazy_params->cache_path = cache_path;
+  lazy_params->cache_max_size = cache_max_size;
+  lazy_params->media_cache_path = media_cache_path;
+  lazy_params->media_cache_max_size = media_cache_max_size;
+  lazy_params->extensions_cookie_path = extensions_cookie_path;
+  lazy_params->profile = profile;
+  lazy_params->io_thread = g_browser_process->io_thread();
+  io_data_->lazy_params_.reset(lazy_params);
+}
+
+scoped_refptr<ChromeURLRequestContextGetter>
+ProfileIOData::Handle::GetMainRequestContextGetter() const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!main_request_context_getter_) {
+    main_request_context_getter_ =
+        ChromeURLRequestContextGetter::CreateOriginal(
+            io_data_->lazy_params_->profile, io_data_);
+  }
+  return main_request_context_getter_;
+}
+
+scoped_refptr<ChromeURLRequestContextGetter>
+ProfileIOData::Handle::GetMediaRequestContextGetter() const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!media_request_context_getter_) {
+    media_request_context_getter_ =
+        ChromeURLRequestContextGetter::CreateOriginalForMedia(
+            io_data_->lazy_params_->profile, io_data_);
+  }
+  return media_request_context_getter_;
+}
+
+scoped_refptr<ChromeURLRequestContextGetter>
+ProfileIOData::Handle::GetExtensionsRequestContextGetter() const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!extensions_request_context_getter_) {
+    extensions_request_context_getter_ =
+        ChromeURLRequestContextGetter::CreateOriginalForExtensions(
+            io_data_->lazy_params_->profile, io_data_);
+  }
+  return extensions_request_context_getter_;
+}
+
+
+ProfileIOData::LazyParams::LazyParams()
+    : cache_max_size(0),
+      media_cache_max_size(0),
+      io_thread(NULL),
+      profile(NULL) {
+}
+
+ProfileIOData::LazyParams::~LazyParams() {}
+
+class ProfileIOData::RequestContext : public ChromeURLRequestContext {
+ public:
+  RequestContext();
+  ~RequestContext();
+
+  void set_profile_io_data(const ProfileIOData* profile_io_data) {
+    profile_io_data_ = profile_io_data;
+  }
+
+ private:
+  scoped_refptr<const ProfileIOData> profile_io_data_;
+};
+
+ProfileIOData::RequestContext::RequestContext() {}
+ProfileIOData::RequestContext::~RequestContext() {}
+
+ProfileIOData::ProfileIOData() : initialized_(false) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+ProfileIOData::~ProfileIOData() {
+  // If we have never initialized ProfileIOData, then Handle may hold the only
+  // reference to it. The important thing is to make sure it hasn't been
+  // initialized yet, because the lazily initialized variables are supposed to
+  // live on the IO thread.
+  if (BrowserThread::CurrentlyOn(BrowserThread::UI))
+    DCHECK(!initialized_);
+  else
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+}
+
+scoped_refptr<ChromeURLRequestContext>
+ProfileIOData::GetMainRequestContext() const {
+  LazyInitialize();
+  DCHECK(main_request_context_);
+  scoped_refptr<ChromeURLRequestContext> context = main_request_context_;
+  main_request_context_->set_profile_io_data(this);
+  main_request_context_ = NULL;
+  return context;
+}
+
+scoped_refptr<ChromeURLRequestContext>
+ProfileIOData::GetMediaRequestContext() const {
+  LazyInitialize();
+  DCHECK(media_request_context_);
+  scoped_refptr<ChromeURLRequestContext> context = media_request_context_;
+  media_request_context_->set_profile_io_data(this);
+  media_request_context_ = NULL;
+  return context;
+}
+
+scoped_refptr<ChromeURLRequestContext>
+ProfileIOData::GetExtensionsRequestContext() const {
+  LazyInitialize();
+  DCHECK(extensions_request_context_);
+  scoped_refptr<ChromeURLRequestContext> context = extensions_request_context_;
+  extensions_request_context_->set_profile_io_data(this);
+  extensions_request_context_ = NULL;
+  return context;
+}
+
+const ProfileIOData::LazyParams& ProfileIOData::lazy_params() const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK(lazy_params_.get());
+  return *lazy_params_;
+}
+
+void ProfileIOData::LazyInitialize() const {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (initialized_)
+    return;
+
+  main_request_context_ = new RequestContext;
+  media_request_context_ = new RequestContext;
+  extensions_request_context_ = new RequestContext;
+
+  // Initialize context members.
+  IOThread::Globals* io_thread_globals = lazy_params_->io_thread->globals();
+
+  main_request_context_->set_net_log(lazy_params_->io_thread->net_log());
+  media_request_context_->set_net_log(lazy_params_->io_thread->net_log());
+
+  main_request_context_->set_host_resolver(
+      io_thread_globals->host_resolver.get());
+  main_request_context_->set_cert_verifier(
+      io_thread_globals->cert_verifier.get());
+  main_request_context_->set_dnsrr_resolver(
+      io_thread_globals->dnsrr_resolver.get());
+  main_request_context_->set_network_delegate(
+      &io_thread_globals->network_delegate);
+
+  main_request_context_->set_http_auth_handler_factory(
+      io_thread_globals->http_auth_handler_factory.get());
+  media_request_context_->set_http_auth_handler_factory(
+      io_thread_globals->http_auth_handler_factory.get());
+  // TODO(cbentzel): How should extensions handle HTTP Authentication?
+  extensions_request_context_->set_http_auth_handler_factory(
+      io_thread_globals->http_auth_handler_factory.get());
+
+  // TODO(willchan): Initialize more of the contexts!
+
+  // TODO(willchan): Enable this when LazyInitialize() is able to fully
+  // initialize all the ChromeURLRequestContexts.
+#if 0
+  params_.reset();
+#endif
+
+  initialized_ = true;
+}
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
new file mode 100644
index 0000000..2d7f888
--- /dev/null
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -0,0 +1,127 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_PROFILES_PROFILE_IO_DATA_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_IO_DATA_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+
+class ChromeURLRequestContext;
+class ChromeURLRequestContextGetter;
+class IOThread;
+class Profile;
+
+// ProfileImpl owns a ProfileIOData::Handle, which holds a reference to the
+// ProfileIOData. ProfileIOData is intended to own all the objects owned by
+// ProfileImpl which live on the IO thread, such as, but not limited to, network
+// objects like CookieMonster, HttpTransactionFactory, etc. ProfileIOData is
+// owned by the ProfileImpl and ProfileIOData's ChromeURLRequestContexts. When
+// all of them go away, then ProfileIOData will be deleted. Note that the
+// ProfileIOData will typically outlive the Profile it is "owned" by, so it's
+// important for ProfileIOData not to hold any references to the Profile beyond
+// what's used by LazyParams (which should be deleted after lazy
+// initialization).
+class ProfileIOData : public base::RefCountedThreadSafe<ProfileIOData> {
+ public:
+  class Handle {
+   public:
+    Handle();
+    ~Handle();
+
+    // Init() must be called before ~Handle(). It records all the necessary
+    // parameters needed to construct a ChromeURLRequestContextGetter.
+    void Init(const FilePath& cookie_path,
+              const FilePath& cache_path,
+              int cache_max_size,
+              const FilePath& media_cache_path,
+              int media_cache_max_size,
+              const FilePath& extensions_cookie_path,
+              Profile* profile);
+
+    bool HasMainRequestContext() const {
+      return main_request_context_getter_ != NULL;
+    }
+    scoped_refptr<ChromeURLRequestContextGetter>
+        GetMainRequestContextGetter() const;
+    scoped_refptr<ChromeURLRequestContextGetter>
+        GetMediaRequestContextGetter() const;
+    scoped_refptr<ChromeURLRequestContextGetter>
+        GetExtensionsRequestContextGetter() const;
+
+   private:
+    // Ordering is important here. Do not reorder unless you know what you're
+    // doing. |io_data_| must be released before the getters to ensure
+    // that ProfileIOData is deleted on the IO thread.
+    mutable scoped_refptr<ChromeURLRequestContextGetter>
+        main_request_context_getter_;
+    mutable scoped_refptr<ChromeURLRequestContextGetter>
+        media_request_context_getter_;
+    mutable scoped_refptr<ChromeURLRequestContextGetter>
+        extensions_request_context_getter_;
+    const scoped_refptr<ProfileIOData> io_data_;
+
+    DISALLOW_COPY_AND_ASSIGN(Handle);
+  };
+
+  // TODO(willchan): Move this to the private section when
+  // ChromeURLRequestContextFactory subclasses don't need it anymore.
+  struct LazyParams {
+    LazyParams();
+    ~LazyParams();
+
+    // All of these parameters are intended to be read on the IO thread.
+    FilePath cookie_path;
+    FilePath cache_path;
+    int cache_max_size;
+    FilePath media_cache_path;
+    int media_cache_max_size;
+    FilePath extensions_cookie_path;
+    IOThread* io_thread;
+
+    // TODO(willchan): Kill this, since the IO thread shouldn't be reading from
+    // the Profile. Instead, replace this with the parameters we want to copy
+    // from the UI thread to the IO thread.
+    Profile* profile;
+  };
+
+  // These should only be called at most once each. Ownership is reversed they
+  // get called, from ProfileIOData owning ChromeURLRequestContext to vice
+  // versa.
+  scoped_refptr<ChromeURLRequestContext> GetMainRequestContext() const;
+  scoped_refptr<ChromeURLRequestContext> GetMediaRequestContext() const;
+  scoped_refptr<ChromeURLRequestContext> GetExtensionsRequestContext() const;
+
+  // TODO(willchan): Delete this when ChromeURLRequestContextFactory subclasses
+  // don't need it anymore.
+  const LazyParams& lazy_params() const;
+
+ private:
+  friend class base::RefCountedThreadSafe<ProfileIOData>;
+
+  class RequestContext;
+
+  ProfileIOData();
+  ~ProfileIOData();
+
+  // Lazily initializes ProfileIOData.
+  void LazyInitialize() const;
+
+  // Lazy initialization params.
+  // TODO(willchan): Delete after Initialize() finishes initializing all the
+  // contexts.
+  scoped_ptr<const LazyParams> lazy_params_;
+
+  mutable bool initialized_;
+  mutable scoped_refptr<RequestContext> main_request_context_;
+  mutable scoped_refptr<RequestContext> media_request_context_;
+  mutable scoped_refptr<RequestContext> extensions_request_context_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfileIOData);
+};
+
+#endif  // CHROME_BROWSER_PROFILES_PROFILE_IO_DATA_H_
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index ae942df..83772f1 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -12,8 +12,6 @@
 #include "base/string_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/chrome_constants.h"
@@ -23,7 +21,6 @@
 #include "chrome/common/net/url_request_context_getter.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/url_request/url_request_context.h"
@@ -38,7 +35,7 @@
 // static
 void ProfileManager::ShutdownSessionServices() {
   ProfileManager* pm = g_browser_process->profile_manager();
-  if (!pm) // Is NULL when running unit tests.
+  if (!pm)  // Is NULL when running unit tests.
     return;
   for (ProfileManager::const_iterator i = pm->begin(); i != pm->end(); ++i)
     (*i)->ShutdownSessionService();
@@ -53,7 +50,7 @@
 }
 
 ProfileManager::ProfileManager() : logged_in_(false) {
-  SystemMonitor::Get()->AddObserver(this);
+  ui::SystemMonitor::Get()->AddObserver(this);
 #if defined(OS_CHROMEOS)
   registrar_.Add(
       this,
@@ -63,7 +60,7 @@
 }
 
 ProfileManager::~ProfileManager() {
-  SystemMonitor* system_monitor = SystemMonitor::Get();
+  ui::SystemMonitor* system_monitor = ui::SystemMonitor::Get();
   if (system_monitor)
     system_monitor->RemoveObserver(this);
 
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 1d6483d..d2f9281 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -10,18 +10,18 @@
 
 #include <vector>
 
-#include "app/system_monitor.h"
 #include "base/basictypes.h"
 #include "base/message_loop.h"
 #include "base/threading/non_thread_safe.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "ui/base/system_monitor/system_monitor.h"
 
 class FilePath;
 
 class ProfileManager : public base::NonThreadSafe,
-                       public SystemMonitor::PowerObserver,
+                       public ui::SystemMonitor::PowerObserver,
                        public NotificationObserver {
  public:
   ProfileManager();
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index e2f1381..825b030 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -4,21 +4,19 @@
 
 #include <string>
 
-#include "app/system_monitor.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "base/path_service.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/system_monitor/system_monitor.h"
 
 class ProfileManagerTest : public testing::Test {
  protected:
@@ -76,7 +74,7 @@
 
 TEST_F(ProfileManagerTest, DefaultProfileDir) {
   CommandLine *cl = CommandLine::ForCurrentProcess();
-  SystemMonitor dummy;
+  ui::SystemMonitor dummy;
   ProfileManager profile_manager;
   std::string profile_dir("my_user");
 
@@ -92,7 +90,7 @@
 // This functionality only exists on Chrome OS.
 TEST_F(ProfileManagerTest, LoggedInProfileDir) {
   CommandLine *cl = CommandLine::ForCurrentProcess();
-  SystemMonitor dummy;
+  ui::SystemMonitor dummy;
   ProfileManager profile_manager;
   std::string profile_dir("my_user");
 
diff --git a/chrome/browser/remoting/directory_add_request.cc b/chrome/browser/remoting/directory_add_request.cc
index c7d2645..691c7a2 100644
--- a/chrome/browser/remoting/directory_add_request.cc
+++ b/chrome/browser/remoting/directory_add_request.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -61,7 +61,7 @@
 void DirectoryAddRequest::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
diff --git a/chrome/browser/remoting/directory_add_request_unittest.cc b/chrome/browser/remoting/directory_add_request_unittest.cc
index 6389b3e..3c6d496 100644
--- a/chrome/browser/remoting/directory_add_request_unittest.cc
+++ b/chrome/browser/remoting/directory_add_request_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -36,7 +36,7 @@
         NewCallback(&callback, &MockDoneCallback::OnDone));
 
     GURL url;
-    URLRequestStatus status_ok;
+    net::URLRequestStatus status_ok;
     ResponseCookies cookies;
     target_->OnURLFetchComplete(NULL, url, status_ok, response_code,
                                cookies, data);
diff --git a/chrome/browser/remoting/remoting_options_handler.cc b/chrome/browser/remoting/remoting_options_handler.cc
new file mode 100644
index 0000000..02ebac6
--- /dev/null
+++ b/chrome/browser/remoting/remoting_options_handler.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/remoting/remoting_options_handler.h"
+
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/remoting/chromoting_host_info.h"
+#include "chrome/browser/dom_ui/web_ui.h"
+#include "chrome/browser/service/service_process_control_manager.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace remoting {
+
+RemotingOptionsHandler::RemotingOptionsHandler()
+    : web_ui_(NULL),
+      process_control_(NULL) {
+}
+
+RemotingOptionsHandler::~RemotingOptionsHandler() {
+  if (process_control_)
+    process_control_->RemoveMessageHandler(this);
+}
+
+void RemotingOptionsHandler::Init(WebUI* web_ui) {
+  web_ui_ = web_ui;
+
+  process_control_ =
+      ServiceProcessControlManager::GetInstance()->GetProcessControl(
+          web_ui_->GetProfile());
+  process_control_->AddMessageHandler(this);
+
+  if (!process_control_->RequestRemotingHostStatus()) {
+    // Assume that host is not started if we can't request status.
+    SetStatus(false, "");
+  }
+}
+
+// ServiceProcessControl::MessageHandler interface
+void RemotingOptionsHandler::OnRemotingHostInfo(
+    const remoting::ChromotingHostInfo& host_info) {
+  SetStatus(host_info.enabled, host_info.login);
+}
+
+void RemotingOptionsHandler::SetStatus(
+    bool enabled, const std::string& login) {
+  string16 status;
+  if (enabled) {
+    status = l10n_util::GetStringFUTF16(IDS_REMOTING_STATUS_ENABLED_TEXT,
+                                        UTF8ToUTF16(login));
+  } else {
+    status = l10n_util::GetStringUTF16(IDS_REMOTING_STATUS_DISABLED_TEXT);
+  }
+
+  FundamentalValue enabled_value(enabled);
+  StringValue status_value(status);
+  web_ui_->CallJavascriptFunction(L"options.AdvancedOptions.SetRemotingStatus",
+                                  enabled_value, status_value);
+}
+
+}  // namespace remoting
diff --git a/chrome/browser/remoting/remoting_options_handler.h b/chrome/browser/remoting/remoting_options_handler.h
new file mode 100644
index 0000000..634e435
--- /dev/null
+++ b/chrome/browser/remoting/remoting_options_handler.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_REMOTING_REMOTING_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_REMOTING_REMOTING_OPTIONS_HANDLER_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/service/service_process_control.h"
+
+class WebUI;
+
+namespace remoting {
+
+// Remoting options handler is responsinble for showing correct status
+// of the chromoting host in the preferences. It listens to the
+// messages from the service process (by registering MessageHandler
+// callback in the ServiceProcessControl) and updates current status
+// as neccessary.
+class RemotingOptionsHandler : public ServiceProcessControl::MessageHandler {
+ public:
+  RemotingOptionsHandler();
+  virtual ~RemotingOptionsHandler();
+
+  void Init(WebUI* web_ui);
+
+  // ServiceProcessControl::MessageHandler interface.
+  virtual void OnRemotingHostInfo(
+      const remoting::ChromotingHostInfo& host_info);
+
+ private:
+  void SetStatus(bool enabled, const std::string& login);
+
+  WebUI* web_ui_;
+  ServiceProcessControl* process_control_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemotingOptionsHandler);
+};
+
+}  // namespace remoting
+
+#endif  // CHROME_BROWSER_REMOTING_REMOTING_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/remoting/remoting_resources_source.cc b/chrome/browser/remoting/remoting_resources_source.cc
index 656763c..fdf5ba1 100644
--- a/chrome/browser/remoting/remoting_resources_source.cc
+++ b/chrome/browser/remoting/remoting_resources_source.cc
@@ -7,19 +7,19 @@
 #include <algorithm>
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/google/google_util.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "googleurl/src/gurl.h"
 #include "grit/app_resources.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Define the values of standard URLs.
 const char RemotingResourcesSource::kInvalidPasswordHelpUrl[] =
@@ -39,6 +39,7 @@
   const char kRemotingGaiaLoginPath[] = "gaialogin";
   const char kRemotingSetupFlowPath[] = "setup";
   const char kRemotingSetupDonePath[] = "setupdone";
+  const char kRemotingSettingUpPath[] = "settingup";
   const char kRemotingSetupErrorPath[] = "setuperror";
 
   std::string response;
@@ -86,11 +87,31 @@
         l10n_util::GetStringUTF16(IDS_SYNC_ERROR_SIGNING_IN));
     localized_strings.SetString("captchainstructions",
         l10n_util::GetStringUTF16(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS));
+    localized_strings.SetString("invalidaccesscode",
+        l10n_util::GetStringUTF16(IDS_SYNC_INVALID_ACCESS_CODE_LABEL));
+    localized_strings.SetString("enteraccesscode",
+        l10n_util::GetStringUTF16(IDS_SYNC_ENTER_ACCESS_CODE_LABEL));
+    localized_strings.SetString("getaccesscodehelp",
+        l10n_util::GetStringUTF16(IDS_SYNC_ACCESS_CODE_HELP_LABEL));
+    localized_strings.SetString("getaccesscodeurl",
+        l10n_util::GetStringUTF16(IDS_SYNC_GET_ACCESS_CODE_URL));
+
     static const base::StringPiece html(ResourceBundle::GetSharedInstance()
         .GetRawDataResource(IDR_GAIA_LOGIN_HTML));
     SetFontAndTextDirection(&localized_strings);
     response = jstemplate_builder::GetI18nTemplateHtml(
         html, &localized_strings);
+  } else if (path_raw == kRemotingSettingUpPath) {
+    DictionaryValue localized_strings;
+    localized_strings.SetString("settingup",
+        l10n_util::GetStringUTF16(IDS_REMOTING_SETTING_UP_MESSAGE));
+    localized_strings.SetString("cancel",
+        l10n_util::GetStringUTF16(IDS_CANCEL));
+    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
+        .GetRawDataResource(IDR_REMOTING_SETTING_UP_HTML));
+    SetFontAndTextDirection(&localized_strings);
+    response = jstemplate_builder::GetI18nTemplateHtml(
+        html, &localized_strings);
   } else if (path_raw == kRemotingSetupDonePath) {
     DictionaryValue localized_strings;
     localized_strings.SetString("success",
diff --git a/chrome/browser/remoting/resources/remoting_setting_up.html b/chrome/browser/remoting/resources/remoting_setting_up.html
new file mode 100644
index 0000000..c0a20a8
--- /dev/null
+++ b/chrome/browser/remoting/resources/remoting_setting_up.html
@@ -0,0 +1,34 @@
+<html i18n-values="dir:textdirection;">
+<head>
+<title></title>
+<link rel="stylesheet" type="text/css" href="remoting_setup_flow.css" />
+<style type="text/css">
+#throbber {
+  margin: -3px 10px;
+}
+#setting_up {
+  margin: 100px;
+  text-align: center;
+}
+#setting_up_label {
+  margin: 15px;
+  font-weight: bold;
+  font-size: 125%;
+}
+</style>
+<link rel="stylesheet" href="chrome://resources/css/throbber.css">
+<script src="chrome://resources/js/cr.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily">
+<form id="settingUpForm" onSubmit="return false;">
+  <div id="setting_up">
+    <div id="throbber" class="throbber"></div>
+    <div id="setting_up_label" i18n-content="settingup"></div>
+  </div>
+  <div class="remoting-footer">
+    <input id="cancelButton" type="button" i18n-values="value:cancel"
+           onclick='chrome.send("DialogClose", [""])' />
+  </div>
+</form>
+</body>
+</html>
diff --git a/chrome/browser/remoting/resources/remoting_setup_flow.css b/chrome/browser/remoting/resources/remoting_setup_flow.css
index 37094f0..467322e 100644
--- a/chrome/browser/remoting/resources/remoting_setup_flow.css
+++ b/chrome/browser/remoting/resources/remoting_setup_flow.css
@@ -29,10 +29,12 @@
   bottom: 0px;
   margin-left: 20px;
 }
+input[type='button'],
 input[type='submit'] {
   min-width: 87px;
   min-height: 26px;
 }
+html[os='mac'] input[type='button'],
 html[os='mac'] input[type='submit'] {
   font-size: 12pt;
 }
diff --git a/chrome/browser/remoting/resources/remoting_setup_flow.html b/chrome/browser/remoting/resources/remoting_setup_flow.html
index 13affed..97544b9 100644
--- a/chrome/browser/remoting/resources/remoting_setup_flow.html
+++ b/chrome/browser/remoting/resources/remoting_setup_flow.html
@@ -1,6 +1,19 @@
 <html id='t'>
 <head>
 <title></title>
+<style type="text/css">
+body {
+  margin:0;
+  border:0;
+}
+.setup-flow-page {
+  display: none;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  border: 0;
+}
+</style>
 <script type="text/javascript">
   // Called once, when this html/js is loaded.
   function showTheRightIframe() {
@@ -13,6 +26,8 @@
   function hideAllPages() {
     document.getElementById('login').style.display = 'none';
     document.getElementById('login').tabIndex = -1;
+    document.getElementById('settingup').style.display = 'none';
+    document.getElementById('settingup').tabIndex = -1;
     document.getElementById('done').style.display = 'none';
     document.getElementById('done').tabIndex = -1;
     document.getElementById('error').style.display = 'none';
@@ -29,6 +44,10 @@
     showPage('login')
   }
 
+  function showSettingUp() {
+    showPage('settingup')
+  }
+
   function showSetupDone() {
     showPage('done')
   }
@@ -38,15 +57,14 @@
   }
 </script>
 </head>
-<body style="margin:0; border:0;" onload="showTheRightIframe();">
-  <iframe id="login" frameborder="0" width="100%" scrolling="no" height="100%"
-          src="chrome://remotingresources/gaialogin" style="display:none"
-          tabindex="-1"></iframe>
-  <iframe id="done" frameborder="0" width="100%" scrolling="no" height="100%"
-          src="chrome://remotingresources/setupdone" style="display:none"
-          tabindex="-1"></iframe>
-  <iframe id="error" frameborder="0" width="100%" scrolling="no" height="100%"
-          src="chrome://remotingresources/setuperror" style="display:none"
-          tabindex="-1"></iframe>
+<body onload="showTheRightIframe();">
+  <iframe id="login" class="setup-flow-page" tabindex="-1"
+          src="chrome://remotingresources/gaialogin"></iframe>
+  <iframe id="settingup" class="setup-flow-page" tabindex="-1"
+          src="chrome://remotingresources/settingup"></iframe>
+  <iframe id="done" class="setup-flow-page" tabindex="-1"
+          src="chrome://remotingresources/setupdone"></iframe>
+  <iframe id="error"  class="setup-flow-page" tabindex="-1"
+          src="chrome://remotingresources/setuperror"></iframe>
 </body>
 </html>
diff --git a/chrome/browser/remoting/setup_flow.cc b/chrome/browser/remoting/setup_flow.cc
index 6070f1f..dc7effd 100644
--- a/chrome/browser/remoting/setup_flow.cc
+++ b/chrome/browser/remoting/setup_flow.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/remoting/setup_flow.h"
 
-#include "app/gfx/font_util.h"
-#include "app/l10n_util.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/utf_string_conversions.h"
@@ -20,9 +18,11 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/font.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_font_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/font.h"
 
 namespace remoting {
 
@@ -33,7 +33,9 @@
 SetupFlowStep::~SetupFlowStep() { }
 
 SetupFlowStepBase::SetupFlowStepBase()
-    : flow_(NULL) {
+    : flow_(NULL),
+      done_(false),
+      next_step_(NULL) {
 }
 
 SetupFlowStepBase::~SetupFlowStepBase() { }
@@ -51,11 +53,12 @@
 
 void SetupFlowStepBase::ExecuteJavascriptInIFrame(
     const std::wstring& iframe_xpath, const std::wstring& js) {
-  DOMUI* dom_ui = flow()->dom_ui();
-  DCHECK(dom_ui);
+  WebUI* web_ui = flow()->web_ui();
+  DCHECK(web_ui);
 
-  RenderViewHost* rvh = dom_ui->tab_contents()->render_view_host();
-  rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
+  RenderViewHost* rvh = web_ui->tab_contents()->render_view_host();
+  rvh->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath),
+                                   WideToUTF16Hack(js));
 }
 
 void SetupFlowStepBase::FinishStep(SetupFlowStep* next_step) {
@@ -81,7 +84,7 @@
       L"setMessage('" + UTF16ToWide(GetErrorMessage()) + L"');";
   ExecuteJavascriptInIFrame(kErrorIframeXPath, javascript);
 
-  flow()->dom_ui()->CallJavascriptFunction(L"showError");
+  flow()->web_ui()->CallJavascriptFunction(L"showError");
 
   ExecuteJavascriptInIFrame(kErrorIframeXPath, L"onPageShown();");
 }
@@ -107,7 +110,7 @@
       L"setMessage('" + UTF16ToWide(message_) + L"');";
   ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
 
-  flow()->dom_ui()->CallJavascriptFunction(L"showSetupDone");
+  flow()->web_ui()->CallJavascriptFunction(L"showSetupDone");
 
   ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();");
 }
@@ -115,18 +118,16 @@
 SetupFlowContext::SetupFlowContext() { }
 SetupFlowContext::~SetupFlowContext() { }
 
-SetupFlow::SetupFlow(const std::string& args, Profile* profile,
+SetupFlow::SetupFlow(const std::string& args,
+                     Profile* profile,
                      SetupFlowStep* first_step)
-    : dom_ui_(NULL),
+    : web_ui_(NULL),
       dialog_start_args_(args),
       profile_(profile),
       current_step_(first_step) {
   // TODO(hclam): The data source should be added once.
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(new RemotingResourcesSource())));
+  profile->GetChromeURLDataManager()->AddDataSource(
+      new RemotingResourcesSource());
 }
 
 SetupFlow::~SetupFlow() { }
@@ -156,8 +157,8 @@
   return GURL("chrome://remotingresources/setup");
 }
 
-void SetupFlow::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void SetupFlow::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   // The called will be responsible for deleting this object.
   handlers->push_back(const_cast<SetupFlow*>(this));
 }
@@ -165,11 +166,11 @@
 void SetupFlow::GetDialogSize(gfx::Size* size) const {
   PrefService* prefs = profile_->GetPrefs();
   gfx::Font approximate_web_font(
-      UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
+      UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
       prefs->GetInteger(prefs::kWebKitDefaultFontSize));
 
   // TODO(pranavk) Replace the following SYNC resources with REMOTING Resources.
-  *size = gfx::GetLocalizedContentsSizeForFont(
+  *size = ui::GetLocalizedContentsSizeForFont(
       IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
       IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
       approximate_web_font);
@@ -202,16 +203,16 @@
   return true;
 }
 
-DOMMessageHandler* SetupFlow::Attach(DOMUI* dom_ui) {
-  dom_ui_ = dom_ui;
+WebUIMessageHandler* SetupFlow::Attach(WebUI* web_ui) {
+  web_ui_ = web_ui;
   StartCurrentStep();
-  return DOMMessageHandler::Attach(dom_ui);
+  return WebUIMessageHandler::Attach(web_ui);
 }
 
 void SetupFlow::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "SubmitAuth", NewCallback(this, &SetupFlow::HandleSubmitAuth));
-  dom_ui_->RegisterMessageCallback(
+  web_ui_->RegisterMessageCallback(
       "RemotingSetup", NewCallback(this, &SetupFlow::HandleUIMessage));
 }
 
diff --git a/chrome/browser/remoting/setup_flow.h b/chrome/browser/remoting/setup_flow.h
index d5d16dc..b8a7de6 100644
--- a/chrome/browser/remoting/setup_flow.h
+++ b/chrome/browser/remoting/setup_flow.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/common/remoting/chromoting_host_info.h"
 
 class ListValue;
@@ -121,7 +122,7 @@
   virtual void Cancel();
 
  protected:
-  void DoStart();
+  virtual void DoStart();
 
  private:
   string16 message_;
@@ -161,14 +162,14 @@
 //
 // In this case auth_data would be passed in
 // SetupFlowStep::HandleMessage().
-class SetupFlow : public DOMMessageHandler,
+class SetupFlow : public WebUIMessageHandler,
                   public HtmlDialogUIDelegate {
  public:
   virtual ~SetupFlow();
 
   static SetupFlow* OpenSetupDialog(Profile* profile);
 
-  DOMUI* dom_ui() { return dom_ui_; }
+  WebUI* web_ui() { return web_ui_; }
   Profile* profile() { return profile_; }
   SetupFlowContext* context() { return &context_; }
 
@@ -178,8 +179,8 @@
 
   // HtmlDialogUIDelegate implementation.
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
@@ -188,8 +189,8 @@
   virtual bool IsDialogModal() const;
   virtual bool ShouldShowDialogTitle() const;
 
-  // DOMMessageHandler implementation.
-  virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+  // WebUIMessageHandler implementation.
+  virtual WebUIMessageHandler* Attach(WebUI* web_ui);
   virtual void RegisterMessages();
 
   // Message handlers for the messages we receive from UI.
@@ -199,9 +200,9 @@
   void StartCurrentStep();
   void OnStepDone();
 
-  // Pointer to the DOM UI. This is provided by RemotingSetupMessageHandler
+  // Pointer to the Web UI. This is provided by RemotingSetupMessageHandler
   // when attached.
-  DOMUI* dom_ui_;
+  WebUI* web_ui_;
 
   // The args to pass to the initial page.
   std::string dialog_start_args_;
diff --git a/chrome/browser/remoting/setup_flow_get_status_step.cc b/chrome/browser/remoting/setup_flow_get_status_step.cc
index 1f03bb9..02e47ca 100644
--- a/chrome/browser/remoting/setup_flow_get_status_step.cc
+++ b/chrome/browser/remoting/setup_flow_get_status_step.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/remoting/setup_flow_get_status_step.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/remoting/setup_flow_register_step.h"
 #include "chrome/browser/service/service_process_control.h"
 #include "chrome/browser/service/service_process_control_manager.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace remoting {
 
@@ -41,6 +41,8 @@
 }
 
 void SetupFlowGetStatusStep::DoStart() {
+  flow()->web_ui()->CallJavascriptFunction(L"showSettingUp");
+
   process_control_ =
       ServiceProcessControlManager::GetInstance()->GetProcessControl(
           flow()->profile());
diff --git a/chrome/browser/remoting/setup_flow_login_step.cc b/chrome/browser/remoting/setup_flow_login_step.cc
index 71ee79b..6170198 100644
--- a/chrome/browser/remoting/setup_flow_login_step.cc
+++ b/chrome/browser/remoting/setup_flow_login_step.cc
@@ -9,7 +9,7 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/remoting/setup_flow_get_status_step.h"
 #include "chrome/common/net/gaia/gaia_constants.h"
@@ -20,6 +20,11 @@
 static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']";
 
 SetupFlowLoginStep::SetupFlowLoginStep() { }
+
+SetupFlowLoginStep::SetupFlowLoginStep(const string16& error_message)
+    : error_message_(error_message) {
+}
+
 SetupFlowLoginStep::~SetupFlowLoginStep() { }
 
 void SetupFlowLoginStep::HandleMessage(const std::string& message,
@@ -41,17 +46,18 @@
 
     CHECK(parsed_value->IsType(Value::TYPE_DICTIONARY));
 
-    std::string username, password, captcha;
+    std::string username, password, captcha, access_code;
     const DictionaryValue* result =
         static_cast<const DictionaryValue*>(parsed_value.get());
     if (!result->GetString("user", &username) ||
         !result->GetString("pass", &password) ||
-        !result->GetString("captcha", &captcha)) {
+        !result->GetString("captcha", &captcha) ||
+        !result->GetString("access_code", &access_code)) {
       NOTREACHED() << "Unable to parse auth data";
       return;
     }
 
-    OnUserSubmittedAuth(username, password, captcha);
+    OnUserSubmittedAuth(username, password, captcha, access_code);
   }
 }
 
@@ -62,14 +68,22 @@
 
 void SetupFlowLoginStep::OnUserSubmittedAuth(const std::string& user,
                                              const std::string& password,
-                                             const std::string& captcha) {
+                                             const std::string& captcha,
+                                             const std::string& access_code) {
   flow()->context()->login = user;
 
   // Start the authenticator.
   authenticator_.reset(
       new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
                           flow()->profile()->GetRequestContext()));
-  authenticator_->StartClientLogin(user, password,
+
+  std::string remoting_password;
+  if (!access_code.empty())
+    remoting_password = access_code;
+  else
+    remoting_password = password;
+
+  authenticator_->StartClientLogin(user, remoting_password,
                                    GaiaConstants::kRemotingService,
                                    "", captcha,
                                    GaiaAuthFetcher::HostedAccountsAllowed);
@@ -112,25 +126,26 @@
   // TODO(sergeyu): Supply current login name if the service was started before.
   args.SetString("user", "");
   args.SetBoolean("editable_user", true);
+  if (!error_message_.empty())
+    args.SetString("error_message", error_message_);
   ShowGaiaLogin(args);
 }
 
 void SetupFlowLoginStep::ShowGaiaLogin(const DictionaryValue& args) {
-  DOMUI* dom_ui = flow()->dom_ui();
-  DCHECK(dom_ui);
+  WebUI* web_ui = flow()->web_ui();
+  DCHECK(web_ui);
 
-  dom_ui->CallJavascriptFunction(L"showLogin");
+  web_ui->CallJavascriptFunction(L"showLogin");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
-  std::wstring javascript = std::wstring(L"showGaiaLogin") +
-      L"(" + UTF8ToWide(json) + L");";
+  std::wstring javascript = std::wstring(L"showGaiaLogin(") +
+      UTF8ToWide(json) + L");";
   ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
 }
 
 void SetupFlowLoginStep::ShowGaiaFailed(const GoogleServiceAuthError& error) {
   DictionaryValue args;
-  args.SetString("user", "");
   args.SetInteger("error", error.state());
   args.SetBoolean("editable_user", true);
   args.SetString("captchaUrl", error.captcha().image_url.spec());
diff --git a/chrome/browser/remoting/setup_flow_login_step.h b/chrome/browser/remoting/setup_flow_login_step.h
index a7d8911..6a41d99 100644
--- a/chrome/browser/remoting/setup_flow_login_step.h
+++ b/chrome/browser/remoting/setup_flow_login_step.h
@@ -15,6 +15,7 @@
 class SetupFlowLoginStep : public SetupFlowStepBase, public GaiaAuthConsumer {
  public:
   SetupFlowLoginStep();
+  SetupFlowLoginStep(const string16& error_message);
   virtual ~SetupFlowLoginStep();
 
   // SetupFlowStep implementation.
@@ -36,12 +37,15 @@
  private:
   void OnUserSubmittedAuth(const std::string& user,
                            const std::string& password,
-                           const std::string& captcha);
+                           const std::string& captcha,
+                           const std::string& access_code);
 
   void ShowGaiaLogin(const DictionaryValue& args);
   void ShowGaiaSuccessAndSettingUp();
   void ShowGaiaFailed(const GoogleServiceAuthError& error);
 
+  string16 error_message_;
+
   // Fetcher to obtain the Chromoting Directory token.
   scoped_ptr<GaiaAuthFetcher> authenticator_;
 
diff --git a/chrome/browser/remoting/setup_flow_register_step.cc b/chrome/browser/remoting/setup_flow_register_step.cc
index 95799b5..699e290 100644
--- a/chrome/browser/remoting/setup_flow_register_step.cc
+++ b/chrome/browser/remoting/setup_flow_register_step.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/remoting/setup_flow_register_step.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/remoting/setup_flow_login_step.h"
 #include "chrome/browser/remoting/setup_flow_start_host_step.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace remoting {
 
@@ -20,11 +20,13 @@
 }
 
 void SetupFlowRegisterStep::Cancel() {
-  // Don't need to do anything here. Ther request will canceled when
+  // Don't need to do anything here. The request will be canceled when
   // |request_| is destroyed.
 }
 
 void SetupFlowRegisterStep::DoStart() {
+  flow()->web_ui()->CallJavascriptFunction(L"showSettingUp");
+
   request_.reset(new DirectoryAddRequest(
       flow()->profile()->GetRequestContext()));
   request_->AddHost(flow()->context()->host_info,
@@ -39,12 +41,13 @@
       FinishStep(new SetupFlowStartHostStep());
       break;
     case DirectoryAddRequest::ERROR_EXISTS:
-      LOG(INFO) << "Chromoting host is already reagistered.";
+      LOG(INFO) << "Chromoting host is already registered.";
       FinishStep(new SetupFlowStartHostStep());
       break;
     case DirectoryAddRequest::ERROR_AUTH:
-      LOG(ERROR) << "Chromoting Directory didn't accept auth token.";
-      FinishStep(new SetupFlowLoginStep());
+      LOG(ERROR) << "Access denied by Chromoting Directory.";
+      FinishStep(new SetupFlowLoginStep(l10n_util::GetStringUTF16(
+          IDS_REMOTING_REGISTRATION_ACCESS_DENIED)));
       break;
     default:
       LOG(ERROR) << "Chromoting Host registration failed: "
diff --git a/chrome/browser/remoting/setup_flow_start_host_step.cc b/chrome/browser/remoting/setup_flow_start_host_step.cc
index 19094de..8c53c2e 100644
--- a/chrome/browser/remoting/setup_flow_start_host_step.cc
+++ b/chrome/browser/remoting/setup_flow_start_host_step.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/remoting/setup_flow_start_host_step.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/remoting/setup_flow_get_status_step.h"
 #include "chrome/browser/service/service_process_control.h"
 #include "chrome/browser/service/service_process_control_manager.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace remoting {
 
@@ -44,6 +44,8 @@
 }
 
 void SetupFlowStartHostStep::DoStart() {
+  flow()->web_ui()->CallJavascriptFunction(L"showSettingUp");
+
   process_control_ =
       ServiceProcessControlManager::GetInstance()->GetProcessControl(
           flow()->profile());
diff --git a/chrome/browser/remove_rows_table_model.h b/chrome/browser/remove_rows_table_model.h
index fbab776..cf1f479 100644
--- a/chrome/browser/remove_rows_table_model.h
+++ b/chrome/browser/remove_rows_table_model.h
@@ -8,11 +8,11 @@
 
 #include <set>
 
-#include "app/table_model.h"
+#include "ui/base/models/table_model.h"
 
 // A table model that also supports removing rows. Used for example for the
 // content settings exception dialog for geolocation.
-class RemoveRowsTableModel : public TableModel {
+class RemoveRowsTableModel : public ui::TableModel {
  public:
   typedef std::set<size_t> Rows;
 
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_mac.h b/chrome/browser/renderer_host/accelerated_surface_container_mac.h
index 45979e0..02d43d1 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_mac.h
+++ b/chrome/browser/renderer_host/accelerated_surface_container_mac.h
@@ -33,8 +33,8 @@
 #include "base/basictypes.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/scoped_ptr.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 
 namespace webkit {
 namespace npapi {
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc
index a96782b..ff1f052 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc
+++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc
@@ -18,7 +18,7 @@
 gfx::PluginWindowHandle
 AcceleratedSurfaceContainerManagerMac::AllocateFakePluginWindowHandle(
     bool opaque, bool root) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   AcceleratedSurfaceContainerMac* container =
       new AcceleratedSurfaceContainerMac(this, opaque);
@@ -34,7 +34,7 @@
 
 void AcceleratedSurfaceContainerManagerMac::DestroyFakePluginWindowHandle(
     gfx::PluginWindowHandle id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   AcceleratedSurfaceContainerMac* container = MapIDToContainer(id);
   if (container) {
@@ -65,7 +65,7 @@
     int32 width,
     int32 height,
     uint64 io_surface_identifier) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   AcceleratedSurfaceContainerMac* container = MapIDToContainer(id);
   if (container) {
@@ -78,7 +78,7 @@
     int32 width,
     int32 height,
     TransportDIB::Handle transport_dib) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   AcceleratedSurfaceContainerMac* container = MapIDToContainer(id);
   if (container)
@@ -87,7 +87,7 @@
 
 void AcceleratedSurfaceContainerManagerMac::SetPluginContainerGeometry(
     const webkit::npapi::WebPluginGeometry& move) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   AcceleratedSurfaceContainerMac* container = MapIDToContainer(move.window);
   if (container)
@@ -96,7 +96,7 @@
 
 void AcceleratedSurfaceContainerManagerMac::Draw(CGLContextObj context,
                                                  gfx::PluginWindowHandle id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   glColorMask(true, true, true, true);
   // Should match the clear color of RenderWidgetHostViewMac.
@@ -123,7 +123,7 @@
 }
 
 void AcceleratedSurfaceContainerManagerMac::ForceTextureReload() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   for (PluginWindowToContainerMap::const_iterator i =
           plugin_window_to_container_map_.begin();
@@ -135,7 +135,7 @@
 
 void AcceleratedSurfaceContainerManagerMac::SetSurfaceWasPaintedTo(
     gfx::PluginWindowHandle id, uint64 surface_id) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   AcceleratedSurfaceContainerMac* container = MapIDToContainer(id);
   if (container)
@@ -143,14 +143,14 @@
 }
 
 void AcceleratedSurfaceContainerManagerMac::SetRootSurfaceInvalid() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (root_container_)
     root_container_->set_surface_invalid();
 }
 
 bool AcceleratedSurfaceContainerManagerMac::SurfaceShouldBeVisible(
     gfx::PluginWindowHandle id) const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   if (IsRootContainer(id) && !gpu_rendering_active_)
     return false;
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h
index a2855a4..8f963e6 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h
+++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h
@@ -11,8 +11,8 @@
 
 #include "app/surface/transport_dib.h"
 #include "base/basictypes.h"
-#include "base/lock.h"
-#include "gfx/native_widget_types.h"
+#include "base/synchronization/lock.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace webkit {
 namespace npapi {
@@ -116,7 +116,7 @@
   // Both |plugin_window_to_container_map_| and the
   // AcceleratedSurfaceContainerMac in it are not threadsafe, but accessed from
   // multiple threads. All these accesses are guarded by this lock.
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerManagerMac);
 };
diff --git a/chrome/browser/renderer_host/async_resource_handler.cc b/chrome/browser/renderer_host/async_resource_handler.cc
index 8f84d08..0a2bcbb 100644
--- a/chrome/browser/renderer_host/async_resource_handler.cc
+++ b/chrome/browser/renderer_host/async_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -229,7 +229,7 @@
 
 bool AsyncResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   Time completion_time = Time::Now();
   filter_->Send(new ViewMsg_Resource_RequestComplete(routing_id_,
@@ -241,7 +241,8 @@
   // If we still have a read buffer, then see about caching it for later...
   // Note that we have to make sure the buffer is not still being used, so we
   // have to perform an explicit check on the status code.
-  if (g_spare_read_buffer || URLRequestStatus::SUCCESS != status.status()) {
+  if (g_spare_read_buffer ||
+      net::URLRequestStatus::SUCCESS != status.status()) {
     read_buffer_ = NULL;
   } else if (read_buffer_.get()) {
     DCHECK(read_buffer_->data());
diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc
index fe3f3d0..4ab9a1a 100644
--- a/chrome/browser/renderer_host/audio_renderer_host.cc
+++ b/chrome/browser/renderer_host/audio_renderer_host.cc
@@ -460,7 +460,7 @@
 
   AudioEntryMap::iterator i = audio_entries_.find(
       AudioEntryId(route_id, stream_id));
-  if (i != audio_entries_.end())
+  if (i != audio_entries_.end() && !i->second->pending_close)
     return i->second;
   return NULL;
 }
@@ -473,7 +473,7 @@
   // TODO(hclam): Implement a faster look up method.
   for (AudioEntryMap::iterator i = audio_entries_.begin();
        i != audio_entries_.end(); ++i) {
-    if (controller == i->second->controller.get())
+    if (!i->second->pending_close && controller == i->second->controller.get())
       return i->second;
   }
   return NULL;
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h
index 57d5078..6df3209 100644
--- a/chrome/browser/renderer_host/backing_store.h
+++ b/chrome/browser/renderer_host/backing_store.h
@@ -10,7 +10,7 @@
 
 #include "app/surface/transport_dib.h"
 #include "base/basictypes.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 class RenderProcessHost;
 class RenderWidgetHost;
diff --git a/chrome/browser/renderer_host/backing_store_mac.mm b/chrome/browser/renderer_host/backing_store_mac.mm
index ede4d19..0ba853e 100644
--- a/chrome/browser/renderer_host/backing_store_mac.mm
+++ b/chrome/browser/renderer_host/backing_store_mac.mm
@@ -14,10 +14,10 @@
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "gfx/rect.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/gfx/rect.h"
 
 // Mac Backing Stores:
 //
diff --git a/chrome/browser/renderer_host/backing_store_manager.cc b/chrome/browser/renderer_host/backing_store_manager.cc
index 755a772..080c020 100644
--- a/chrome/browser/renderer_host/backing_store_manager.cc
+++ b/chrome/browser/renderer_host/backing_store_manager.cc
@@ -9,9 +9,9 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/browser/renderer_host/backing_store.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/mru_cache.h"
+#include "chrome/common/notification_service.h"
 
 namespace {
 
@@ -69,12 +69,10 @@
 // Expires the given |backing_store| from |cache|.
 void ExpireBackingStoreAt(BackingStoreCache* cache,
                           BackingStoreCache::iterator backing_store) {
-  RenderWidgetHost* rwh = backing_store->second->render_widget_host();
-  if (rwh->painting_observer()) {
-    rwh->painting_observer()->WidgetWillDestroyBackingStore(
-        backing_store->first,
-        backing_store->second);
-  }
+  NotificationService::current()->Notify(
+      NotificationType::RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE,
+      Source<RenderWidgetHost>(backing_store->first),
+      Details<BackingStore>(backing_store->second));
   cache->Erase(backing_store);
 }
 
@@ -148,7 +146,8 @@
     cache = small_cache;
   }
   BackingStore* backing_store = host->AllocBackingStore(backing_store_size);
-  cache->Put(host, backing_store);
+  if (backing_store)
+    cache->Put(host, backing_store);
   return backing_store;
 }
 
@@ -203,14 +202,14 @@
     // don't have a previous snapshot.
     if (bitmap_rect.size() != backing_store_size ||
         bitmap_rect.x() != 0 || bitmap_rect.y() != 0 ||
-        ComputeTotalArea(copy_rects) != backing_store_size.GetArea()) {
+        ComputeTotalArea(copy_rects) != backing_store_size.GetArea() ||
+        !(backing_store = CreateBackingStore(host, backing_store_size))) {
       DCHECK(needs_full_paint != NULL);
       *needs_full_paint = true;
       // Makes no sense to paint the transport dib if we are going
       // to request a full paint.
       return;
     }
-    backing_store = CreateBackingStore(host, backing_store_size);
   }
 
   backing_store->PaintToBackingStore(host->process(), bitmap,
diff --git a/chrome/browser/renderer_host/backing_store_manager.h b/chrome/browser/renderer_host/backing_store_manager.h
index 3db86b0..63f7bdb 100644
--- a/chrome/browser/renderer_host/backing_store_manager.h
+++ b/chrome/browser/renderer_host/backing_store_manager.h
@@ -11,8 +11,8 @@
 #include "app/surface/transport_dib.h"
 #include "base/basictypes.h"
 #include "base/process.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 class BackingStore;
 class RenderWidgetHost;
diff --git a/chrome/browser/renderer_host/backing_store_skia.cc b/chrome/browser/renderer_host/backing_store_skia.cc
new file mode 100644
index 0000000..8d07a26
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_skia.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/renderer_host/backing_store_skia.h"
+
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/rect.h"
+
+// Assume that somewhere along the line, someone will do width * height * 4
+// with signed numbers. If the maximum value is 2**31, then 2**31 / 4 =
+// 2**29 and floor(sqrt(2**29)) = 23170.
+
+// Max height and width for layers
+static const int kMaxVideoLayerSize = 23170;
+
+BackingStoreSkia::BackingStoreSkia(RenderWidgetHost* widget,
+                                   const gfx::Size& size)
+    : BackingStore(widget, size) {
+  bitmap_.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
+  bitmap_.allocPixels();
+  canvas_.reset(new SkCanvas(bitmap_));
+}
+
+BackingStoreSkia::~BackingStoreSkia() {
+}
+
+void BackingStoreSkia::SkiaShowRect(const gfx::Point& point,
+                                    gfx::Canvas* canvas) {
+  canvas->AsCanvasSkia()->drawBitmap(bitmap_,
+      SkIntToScalar(point.x()), SkIntToScalar(point.y()));
+}
+
+size_t BackingStoreSkia::MemorySize() {
+  // NOTE: The computation may be different when the canvas is a subrectangle of
+  // a larger bitmap.
+  return size().GetArea() * 4;
+}
+
+void BackingStoreSkia::PaintToBackingStore(
+    RenderProcessHost* process,
+    TransportDIB::Id bitmap,
+    const gfx::Rect& bitmap_rect,
+    const std::vector<gfx::Rect>& copy_rects) {
+  if (bitmap_rect.IsEmpty())
+    return;
+
+  const int width = bitmap_rect.width();
+  const int height = bitmap_rect.height();
+
+  if (width <= 0 || width > kMaxVideoLayerSize ||
+      height <= 0 || height > kMaxVideoLayerSize)
+    return;
+
+  TransportDIB* dib = process->GetTransportDIB(bitmap);
+  if (!dib)
+    return;
+
+  scoped_ptr<skia::PlatformCanvas> p_canvas(
+      dib->GetPlatformCanvas(width, height));
+  for (size_t i = 0; i < copy_rects.size(); i++) {
+    const gfx::Rect& copy_rect = copy_rects[i];
+    int x = copy_rect.x() - bitmap_rect.x();
+    int y = copy_rect.y() - bitmap_rect.y();
+    int w = copy_rect.width();
+    int h = copy_rect.height();
+    SkIRect srcrect = SkIRect::MakeXYWH(x, y, w, h);
+    SkRect dstrect = SkRect::MakeXYWH(
+        SkIntToScalar(copy_rect.x()), SkIntToScalar(copy_rect.y()),
+        SkIntToScalar(w), SkIntToScalar(h));
+    SkBitmap b = p_canvas->getTopPlatformDevice().accessBitmap(false);
+    canvas_.get()->drawBitmapRect(b, &srcrect, dstrect);
+  }
+}
+
+void BackingStoreSkia::ScrollBackingStore(int dx, int dy,
+                                          const gfx::Rect& clip_rect,
+                                          const gfx::Size& view_size) {
+  int x = std::min(clip_rect.x(), clip_rect.x() - dx);
+  int y = std::min(clip_rect.y(), clip_rect.y() - dy);
+  int w = clip_rect.width() + abs(dx);
+  int h = clip_rect.height() + abs(dy);
+  SkIRect rect = SkIRect::MakeXYWH(x, y, w, h);
+  bitmap_.scrollRect(&rect, dx, dy);
+}
+
+bool BackingStoreSkia::CopyFromBackingStore(const gfx::Rect& rect,
+                                            skia::PlatformCanvas* output) {
+  const int width = std::min(size().width(), rect.width());
+  const int height = std::min(size().height(), rect.height());
+  if (!output->initialize(width, height, true))
+    return false;
+
+  SkBitmap bitmap = output->getTopPlatformDevice().accessBitmap(true);
+  SkIRect skrect = SkIRect::MakeXYWH(rect.x(), rect.y(), width, height);
+  SkBitmap b;
+  if (!canvas_->readPixels(skrect, &b))
+    return false;
+  output->writePixels(b, rect.x(), rect.y());
+  return true;
+}
diff --git a/chrome/browser/renderer_host/backing_store_skia.h b/chrome/browser/renderer_host/backing_store_skia.h
new file mode 100644
index 0000000..4185496
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_skia.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_SKIA_H_
+#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_SKIA_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/renderer_host/backing_store.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+class SkCanvas;
+
+namespace gfx {
+class Point;
+class Canvas;
+}
+
+// A backing store that uses skia. This is a temporary backing store used by
+// RenderWidgetHostViewViews. In time, only GPU rendering will be used for
+// RWHVV, and then this backing store will be removed.
+class BackingStoreSkia : public BackingStore {
+ public:
+  BackingStoreSkia(RenderWidgetHost* widget, const gfx::Size& size);
+  virtual ~BackingStoreSkia();
+
+  void SkiaShowRect(const gfx::Point& point, gfx::Canvas* canvas);
+
+  // BackingStore implementation.
+  virtual size_t MemorySize();
+  virtual void PaintToBackingStore(
+      RenderProcessHost* process,
+      TransportDIB::Id bitmap,
+      const gfx::Rect& bitmap_rect,
+      const std::vector<gfx::Rect>& copy_rects);
+  virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+                                    skia::PlatformCanvas* output);
+  virtual void ScrollBackingStore(int dx, int dy,
+                                  const gfx::Rect& clip_rect,
+                                  const gfx::Size& view_size);
+
+ private:
+  SkBitmap bitmap_;
+
+  scoped_ptr<SkCanvas> canvas_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackingStoreSkia);
+};
+
+#endif  // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_SKIA_H_
diff --git a/chrome/browser/renderer_host/backing_store_win.cc b/chrome/browser/renderer_host/backing_store_win.cc
index 2013104..4e68a0e 100644
--- a/chrome/browser/renderer_host/backing_store_win.cc
+++ b/chrome/browser/renderer_host/backing_store_win.cc
@@ -9,8 +9,8 @@
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/common/chrome_switches.h"
-#include "gfx/gdi_util.h"
 #include "skia/ext/platform_canvas.h"
+#include "ui/gfx/gdi_util.h"
 
 namespace {
 
diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc
index d71b391..4272d40 100644
--- a/chrome/browser/renderer_host/backing_store_x.cc
+++ b/chrome/browser/renderer_host/backing_store_x.cc
@@ -19,16 +19,16 @@
 #include <limits>
 
 #include "app/surface/transport_dib.h"
-#include "app/x11_util.h"
-#include "app/x11_util_internal.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/time.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
-#include "gfx/rect.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/base/x/x11_util_internal.h"
+#include "ui/gfx/rect.h"
 
 // Assume that somewhere along the line, someone will do width * height * 4
 // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 =
@@ -64,12 +64,12 @@
                             void* visual,
                             int depth)
     : BackingStore(widget, size),
-      display_(x11_util::GetXDisplay()),
-      shared_memory_support_(x11_util::QuerySharedMemorySupport(display_)),
-      use_render_(x11_util::QueryRenderSupport(display_)),
+      display_(ui::GetXDisplay()),
+      shared_memory_support_(ui::QuerySharedMemorySupport(display_)),
+      use_render_(ui::QueryRenderSupport(display_)),
       visual_(visual),
       visual_depth_(depth),
-      root_window_(x11_util::GetX11RootWindow()) {
+      root_window_(ui::GetX11RootWindow()) {
 #if defined(OS_OPENBSD) || defined(OS_FREEBSD)
   COMPILE_ASSERT(_BYTE_ORDER == _LITTLE_ENDIAN, assumes_little_endian);
 #else
@@ -82,13 +82,13 @@
   if (use_render_) {
     picture_ = XRenderCreatePicture(
         display_, pixmap_,
-        x11_util::GetRenderVisualFormat(display_,
-                                        static_cast<Visual*>(visual)),
-                                        0, NULL);
+        ui::GetRenderVisualFormat(display_,
+                                  static_cast<Visual*>(visual)),
+                                  0, NULL);
     pixmap_bpp_ = 0;
   } else {
     picture_ = 0;
-    pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display_, depth);
+    pixmap_bpp_ = ui::BitsPerPixelForPixmapDepth(display_, depth);
   }
 
   pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
@@ -97,7 +97,7 @@
 BackingStoreX::BackingStoreX(RenderWidgetHost* widget, const gfx::Size& size)
     : BackingStore(widget, size),
       display_(NULL),
-      shared_memory_support_(x11_util::SHARED_MEMORY_NONE),
+      shared_memory_support_(ui::SHARED_MEMORY_NONE),
       use_render_(false),
       pixmap_bpp_(0),
       visual_(NULL),
@@ -135,9 +135,9 @@
                                 visual_depth_);
 
   // Draw ARGB transport DIB onto our pixmap.
-  x11_util::PutARGBImage(display_, visual_, visual_depth_, pixmap,
-                         pixmap_gc_, static_cast<uint8*>(bitmap->memory()),
-                         width, height);
+  ui::PutARGBImage(display_, visual_, visual_depth_, pixmap,
+                   pixmap_gc_, static_cast<uint8*>(bitmap->memory()),
+                   width, height);
 
   for (size_t i = 0; i < copy_rects.size(); i++) {
     const gfx::Rect& copy_rect = copy_rects[i];
@@ -184,7 +184,7 @@
   Picture picture;
   Pixmap pixmap;
 
-  if (shared_memory_support_ == x11_util::SHARED_MEMORY_PIXMAP) {
+  if (shared_memory_support_ == ui::SHARED_MEMORY_PIXMAP) {
     XShmSegmentInfo shminfo = {0};
     shminfo.shmseg = dib->MapToX(display_);
 
@@ -203,7 +203,7 @@
     pixmap = XCreatePixmap(display_, root_window_, width, height, 32);
     GC gc = XCreateGC(display_, pixmap, 0, NULL);
 
-    if (shared_memory_support_ == x11_util::SHARED_MEMORY_PUTIMAGE) {
+    if (shared_memory_support_ == ui::SHARED_MEMORY_PUTIMAGE) {
       const XID shmseg = dib->MapToX(display_);
 
       XShmSegmentInfo shminfo;
@@ -269,7 +269,7 @@
     XFreeGC(display_, gc);
   }
 
-  picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap);
+  picture = ui::CreatePictureFromSkiaPixmap(display_, pixmap);
 
   for (size_t i = 0; i < copy_rects.size(); i++) {
     const gfx::Rect& copy_rect = copy_rects[i];
@@ -291,7 +291,7 @@
   // In the case of shared memory, we wait for the composite to complete so that
   // we are sure that the X server has finished reading from the shared memory
   // segment.
-  if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
+  if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
     XSync(display_, False);
 
   XRenderFreePicture(display_, picture);
@@ -315,7 +315,7 @@
 
   XImage* image;
   XShmSegmentInfo shminfo;  // Used only when shared memory is enabled.
-  if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) {
+  if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) {
     // Use shared memory for faster copies when it's available.
     Visual* visual = static_cast<Visual*>(visual_);
     memset(&shminfo, 0, sizeof(shminfo));
@@ -364,7 +364,7 @@
   // Note that this also initializes the output bitmap as opaque.
   if (!output->initialize(width, height, true) ||
       image->bits_per_pixel != 32) {
-    if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
+    if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
       DestroySharedImage(display_, image, &shminfo);
     else
       XDestroyImage(image);
@@ -386,7 +386,7 @@
     }
   }
 
-  if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
+  if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
     DestroySharedImage(display_, image, &shminfo);
   else
     XDestroyImage(image);
diff --git a/chrome/browser/renderer_host/backing_store_x.h b/chrome/browser/renderer_host/backing_store_x.h
index fd249b3..ad0db60 100644
--- a/chrome/browser/renderer_host/backing_store_x.h
+++ b/chrome/browser/renderer_host/backing_store_x.h
@@ -6,10 +6,10 @@
 #define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_X_H_
 #pragma once
 
-#include "app/x11_util.h"
 #include "base/basictypes.h"
 #include "build/build_config.h"
 #include "chrome/browser/renderer_host/backing_store.h"
+#include "ui/base/x/x11_util.h"
 
 namespace gfx {
 class Point;
@@ -77,7 +77,7 @@
   // displayed.
   Display* const display_;
   // What flavor, if any, MIT-SHM (X shared memory) support we have.
-  const x11_util::SharedMemorySupport shared_memory_support_;
+  const ui::SharedMemorySupport shared_memory_support_;
   // If this is true, then we can use Xrender to composite our pixmaps.
   const bool use_render_;
   // If |use_render_| is false, this is the number of bits-per-pixel for |depth|
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 3b97c4b..e3aabd3 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -53,6 +53,7 @@
 #include "chrome/browser/renderer_host/blob_message_filter.h"
 #include "chrome/browser/renderer_host/database_message_filter.h"
 #include "chrome/browser/renderer_host/file_utilities_message_filter.h"
+#include "chrome/browser/renderer_host/gpu_message_filter.h"
 #include "chrome/browser/renderer_host/pepper_file_message_filter.h"
 #include "chrome/browser/renderer_host/pepper_message_filter.h"
 #include "chrome/browser/renderer_host/render_message_filter.h"
@@ -93,12 +94,13 @@
 #include "ipc/ipc_platform_file.h"
 #include "ipc/ipc_switches.h"
 #include "media/base/media_switches.h"
+#include "ui/base/ui_base_switches.h"
 #include "webkit/fileapi/file_system_path_manager.h"
 #include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include <objbase.h>
-#include "app/win/win_util.h"
+#include "chrome/common/section_util_win.h"
 #endif
 
 using WebKit::WebCache;
@@ -230,7 +232,7 @@
 namespace {
 
 // Helper class that we pass to ResourceMessageFilter so that it can find the
-// right URLRequestContext for a request.
+// right net::URLRequestContext for a request.
 class RendererURLRequestContextOverride
     : public ResourceMessageFilter::URLRequestContextOverride {
  public:
@@ -239,13 +241,13 @@
         media_request_context_(profile->GetRequestContextForMedia()) {
   }
 
-  virtual URLRequestContext* GetRequestContext(
-      uint32 request_id, ResourceType::Type resource_type) {
+  virtual net::URLRequestContext* GetRequestContext(
+      const ViewHostMsg_Resource_Request& resource_request) {
     URLRequestContextGetter* request_context = request_context_;
     // If the request has resource type of ResourceType::MEDIA, we use a request
     // context specific to media for handling it because these resources have
     // specific needs for caching.
-    if (resource_type == ResourceType::MEDIA)
+    if (resource_request.resource_type == ResourceType::MEDIA)
       request_context = media_request_context_;
     return request_context->GetURLRequestContext();
   }
@@ -452,6 +454,7 @@
   channel_->AddFilter(
       GeolocationDispatcherHost::New(
           id(), profile()->GetGeolocationPermissionContext()));
+  channel_->AddFilter(new GpuMessageFilter(id()));
   channel_->AddFilter(new PepperFileMessageFilter(id(), profile()));
   channel_->AddFilter(new PepperMessageFilter(profile()));
   channel_->AddFilter(new speech_input::SpeechInputDispatcherHost(id()));
@@ -634,101 +637,110 @@
   // Propagate the following switches to the renderer command line (along
   // with any associated values) if present in the browser command line.
   static const char* const kSwitchNames[] = {
+    switches::kAllowOutdatedPlugins,
+    switches::kAllowScriptingGallery,
+    switches::kAlwaysAuthorizePlugins,
+    switches::kAppsGalleryURL,
+    // We propagate the Chrome Frame command line here as well in case the
+    // renderer is not run in the sandbox.
+    switches::kChromeFrame,
+    switches::kDebugPrint,
+    switches::kDisable3DAPIs,
+    switches::kDisableAcceleratedCompositing,
+    switches::kDisableApplicationCache,
+    switches::kDisableAudio,
+    switches::kDisableBreakpad,
+    switches::kDisableDatabases,
+    switches::kDisableDesktopNotifications,
+    switches::kDisableDeviceOrientation,
+    // We need to propagate this flag to determine whether to make the
+    // WebGLArray constructors on the DOMWindow visible. This
+    // information is needed very early during bringup. We prefer to
+    // use the WebPreferences to set this flag on a page-by-page basis.
+    switches::kDisableExperimentalWebGL,
+    switches::kDisableFileSystem,
+    switches::kDisableGeolocation,
+    switches::kDisableGLMultisampling,
+    switches::kDisableGLSLTranslator,
+    switches::kDisableIndexedDatabase,
+    switches::kDisableLocalStorage,
+    switches::kDisableLogging,
+    switches::kDisableSeccompSandbox,
+    switches::kDisableSessionStorage,
+    switches::kDisableSharedWorkers,
+    switches::kDisableSpeechInput,
+    switches::kDisableWebSockets,
+    switches::kDomAutomationController,
+    switches::kDumpHistogramsOnExit,
+    switches::kEnableAcceleratedDecoding,
+    switches::kEnableBenchmarking,
+    switches::kEnableClickToPlay,
+    switches::kEnableCrxlessWebApps,
+    switches::kEnableDCHECK,
+    switches::kEnableExperimentalExtensionApis,
+    switches::kEnableInBrowserThumbnailing,
+    switches::kEnableLogging,
+    switches::kEnableNaCl,
+    switches::kEnableOpenMax,
+    switches::kEnablePepperTesting,
+    switches::kEnablePrintPreview,
+    switches::kEnableRemoting,
+    switches::kEnableResourceContentSettings,
+#if defined(OS_MACOSX)
+    // Allow this to be set when invoking the browser and relayed along.
+    switches::kEnableSandboxLogging,
+#endif
+    switches::kEnableSearchProviderApiV2,
+    switches::kEnableSeccompSandbox,
+    switches::kEnableStatsTable,
+    switches::kEnableTouch,
+    switches::kEnableVideoFullscreen,
+    switches::kEnableVideoLogging,
+    switches::kEnableWatchdog,
+    switches::kEnableWebAudio,
+    switches::kEnableJavaScriptI18NAPI,
+    switches::kExperimentalSpellcheckerFeatures,
+    switches::kFullMemoryCrashReport,
+#if !defined (GOOGLE_CHROME_BUILD)
+    // These are unsupported and not fully tested modes, so don't enable them
+    // for official Google Chrome builds.
+    switches::kInProcessPlugins,
+#endif  // GOOGLE_CHROME_BUILD
+    switches::kInProcessWebGL,
+    switches::kInternalPepper,
+    switches::kJavaScriptFlags,
+    switches::kLoggingLevel,
+    switches::kMemoryProfiling,
+    switches::kMessageLoopHistogrammer,
+    switches::kNoJsRandomness,
+    switches::kNoReferrers,
+    switches::kNoSandbox,
+    switches::kPlaybackMode,
+    switches::kPpapiOutOfProcess,
+    switches::kProfilingAtStart,
+    switches::kProfilingFile,
+    switches::kProfilingFlush,
+    switches::kRecordMode,
+    switches::kRegisterPepperPlugins,
+    switches::kRemoteShellPort,
     switches::kRendererAssertTest,
 #if !defined(OFFICIAL_BUILD)
     switches::kRendererCheckFalseTest,
 #endif  // !defined(OFFICIAL_BUILD)
     switches::kRendererCrashTest,
     switches::kRendererStartupDialog,
-    switches::kNoSandbox,
-    switches::kTestSandbox,
-    switches::kDisableSeccompSandbox,
-    switches::kEnableSeccompSandbox,
-#if !defined (GOOGLE_CHROME_BUILD)
-    // These are unsupported and not fully tested modes, so don't enable them
-    // for official Google Chrome builds.
-    switches::kInProcessPlugins,
-#endif  // GOOGLE_CHROME_BUILD
-    switches::kAllowScriptingGallery,
-    switches::kDomAutomationController,
-    switches::kUserAgent,
-    switches::kNoReferrers,
-    switches::kJavaScriptFlags,
-    switches::kRecordMode,
-    switches::kPlaybackMode,
-    switches::kNoJsRandomness,
-    switches::kDisableBreakpad,
-    switches::kFullMemoryCrashReport,
-    switches::kV,
-    switches::kVModule,
-    switches::kEnableLogging,
-    switches::kDumpHistogramsOnExit,
-    switches::kDisableLogging,
-    switches::kLoggingLevel,
-    switches::kDebugPrint,
-    switches::kMemoryProfiling,
-    switches::kEnableWatchdog,
-    switches::kMessageLoopHistogrammer,
-    switches::kEnableDCHECK,
-    switches::kSilentDumpOnDCHECK,
-    switches::kUseLowFragHeapCrt,
-    switches::kEnableSearchProviderApiV2,
-    switches::kEnableStatsTable,
-    switches::kExperimentalSpellcheckerFeatures,
-    switches::kDisableAudio,
-    switches::kSimpleDataSource,
-    switches::kEnableBenchmarking,
-    switches::kInternalNaCl,
-    switches::kInternalPepper,
-    switches::kRegisterPepperPlugins,
-    switches::kDisableDatabases,
-    switches::kDisableDesktopNotifications,
-    switches::kDisableWebSockets,
-    switches::kDisableLocalStorage,
-    switches::kDisableSessionStorage,
-    switches::kDisableSharedWorkers,
-    switches::kDisableApplicationCache,
-    switches::kDisableDeviceOrientation,
-    switches::kDisableIndexedDatabase,
-    switches::kDisableSpeechInput,
-    switches::kDisableGeolocation,
     switches::kShowPaintRects,
-    switches::kEnableOpenMax,
-    switches::kVideoThreads,
-    switches::kEnableVideoFullscreen,
-    switches::kEnableVideoLogging,
-    switches::kEnableTouch,
-    // We propagate the Chrome Frame command line here as well in case the
-    // renderer is not run in the sandbox.
-    switches::kChromeFrame,
-    // We need to propagate this flag to determine whether to make the
-    // WebGLArray constructors on the DOMWindow visible. This
-    // information is needed very early during bringup. We prefer to
-    // use the WebPreferences to set this flag on a page-by-page basis.
-    switches::kDisableExperimentalWebGL,
-    switches::kDisableGLSLTranslator,
-    switches::kInProcessWebGL,
+    switches::kSilentDumpOnDCHECK,
+    switches::kSimpleDataSource,
+    switches::kTestSandbox,
     // This flag needs to be propagated to the renderer process for
     // --in-process-webgl.
     switches::kUseGL,
-    switches::kDisableAcceleratedCompositing,
-#if defined(OS_MACOSX)
-    // Allow this to be set when invoking the browser and relayed along.
-    switches::kEnableSandboxLogging,
-#endif
-    switches::kRemoteShellPort,
-    switches::kEnablePepperTesting,
-    switches::kAllowOutdatedPlugins,
-    switches::kEnableRemoting,
-    switches::kEnableClickToPlay,
-    switches::kEnableResourceContentSettings,
-    switches::kPrelaunchGpuProcess,
-    switches::kEnableAcceleratedDecoding,
-    switches::kDisableFileSystem,
-    switches::kPpapiOutOfProcess,
-    switches::kEnablePrintPreview,
-    switches::kEnableCrxlessWebApps,
-    switches::kDisable3DAPIs
+    switches::kUseLowFragHeapCrt,
+    switches::kUserAgent,
+    switches::kV,
+    switches::kVideoThreads,
+    switches::kVModule,
   };
   renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
                                  arraysize(kSwitchNames));
@@ -783,11 +795,24 @@
 }
 
 void BrowserRenderProcessHost::InitExtensions() {
-  // TODO(aa): Should only bother sending these function names if this is an
-  // extension process.
+  // Valid extension function names, used to setup bindings in renderer.
   std::vector<std::string> function_names;
   ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names);
   Send(new ViewMsg_Extension_SetFunctionNames(function_names));
+
+  // Scripting whitelist. This is modified by tests and must be communicated to
+  // renderers.
+  Send(new ViewMsg_Extension_SetScriptingWhitelist(
+      *Extension::GetScriptingWhitelist()));
+
+  // Loaded extensions.
+  ExtensionService* service = profile()->GetExtensionService();
+  if (service) {
+    for (size_t i = 0; i < service->extensions()->size(); ++i) {
+      Send(new ViewMsg_ExtensionLoaded(
+          ViewMsg_ExtensionLoaded_Params(service->extensions()->at(i))));
+    }
+  }
 }
 
 void BrowserRenderProcessHost::InitSpeechInput() {
@@ -813,40 +838,6 @@
   }
 }
 
-void BrowserRenderProcessHost::SendExtensionInfo() {
-  // Check if the process is still starting and we don't have a handle for it
-  // yet, in which case this will happen later when InitVisitedLinks is called.
-  if (!run_renderer_in_process() &&
-      (!child_process_.get() || child_process_->IsStarting())) {
-    return;
-  }
-
-  ExtensionService* service = profile()->GetExtensionService();
-  if (!service)
-    return;
-  ViewMsg_ExtensionsUpdated_Params params;
-  for (size_t i = 0; i < service->extensions()->size(); ++i) {
-    const Extension* extension = service->extensions()->at(i);
-    ViewMsg_ExtensionRendererInfo info;
-    info.id = extension->id();
-    info.web_extent = extension->web_extent();
-    info.name = extension->name();
-    info.location = extension->location();
-    info.allowed_to_execute_script_everywhere =
-        extension->CanExecuteScriptEverywhere();
-    info.host_permissions = extension->host_permissions();
-
-    // The icon in the page is 96px.  We'd rather not scale up, so use 128.
-    info.icon_url = extension->GetIconURL(Extension::EXTENSION_ICON_LARGE,
-                                          ExtensionIconSet::MATCH_EXACTLY);
-    if (info.icon_url.is_empty())
-      info.icon_url = GURL("chrome://theme/IDR_APP_DEFAULT_ICON");
-    params.extensions.push_back(info);
-  }
-
-  Send(new ViewMsg_ExtensionsUpdated(params));
-}
-
 bool BrowserRenderProcessHost::FastShutdownIfPossible() {
   if (run_renderer_in_process())
     return false;  // Single process mode can't do fast shutdown.
@@ -899,7 +890,7 @@
     TransportDIB::Id dib_id) {
 #if defined(OS_WIN)
   // On Windows we need to duplicate the handle from the remote process
-  HANDLE section = app::win::GetSectionFromProcess(
+  HANDLE section = chrome::GetSectionFromProcess(
       dib_id.handle, GetHandle(), false /* read write */);
   return TransportDIB::Map(section);
 #elif defined(OS_MACOSX)
@@ -972,12 +963,6 @@
   if (deleting_soon_)
     return false;
 
-#if defined(OS_CHROMEOS)
-  // To troubleshoot crosbug.com/7327.
-  CHECK(this);
-  CHECK(&msg);
-#endif
-
   mark_child_process_activity_time();
   if (msg.routing_id() == MSG_ROUTING_CONTROL) {
     // Dispatch control messages.
@@ -1128,9 +1113,15 @@
       }
       break;
     }
-    case NotificationType::EXTENSION_LOADED:
+    case NotificationType::EXTENSION_LOADED: {
+      Send(new ViewMsg_ExtensionLoaded(
+          ViewMsg_ExtensionLoaded_Params(
+              Details<const Extension>(details).ptr())));
+      break;
+    }
     case NotificationType::EXTENSION_UNLOADED: {
-      SendExtensionInfo();
+      Send(new ViewMsg_ExtensionUnloaded(
+          Details<UnloadedExtensionInfo>(details).ptr()->extension->id()));
       break;
     }
     case NotificationType::SPELLCHECK_HOST_REINITIALIZED: {
@@ -1157,15 +1148,8 @@
 }
 
 void BrowserRenderProcessHost::OnProcessLaunched() {
-  // At this point, we used to set the process priority if it were marked as
-  // backgrounded_.  We don't do that anymore because when we create a process,
-  // we really don't know how it will be used.  If it is backgrounded, and not
-  // yet processed, a stray hung-cpu process (not chrome) can cause pages to
-  // not load at all.  (see http://crbug.com/21884).
-  // If we could perfectly track when a process is created as visible or not,
-  // we could potentially call SetBackgrounded() properly at this point.  But
-  // there are many cases, and no effective way to automate those cases.
-  // I'm choosing correctness over the feature of de-prioritizing this work.
+  if (child_process_.get())
+    child_process_->SetProcessBackgrounded(backgrounded_);
 
   Send(new ViewMsg_SetIsIncognitoProcess(profile()->IsOffTheRecord()));
 
@@ -1173,7 +1157,6 @@
   InitVisitedLinks();
   InitUserScripts();
   InitExtensions();
-  SendExtensionInfo();
 
   // We don't want to initialize the spellchecker unless SpellCheckHost has been
   // created. In InitSpellChecker(), we know if GetSpellCheckHost() is NULL
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index f1bc47a..ad30cfd 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -6,8 +6,6 @@
 #define CHROME_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_H_
 #pragma once
 
-#include "build/build_config.h"
-
 #include <map>
 #include <queue>
 #include <string>
@@ -22,24 +20,17 @@
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
 
 class CommandLine;
-class GURL;
 class RendererMainThread;
 class RenderWidgetHelper;
-class TabContents;
 class VisitedLinkUpdater;
-class URLRequestContextGetter;
 
 namespace base {
 class SharedMemory;
 }
 
-namespace gfx {
-class Size;
-}
-
 // Implements a concrete RenderProcessHost for the browser process for talking
 // to actual renderer processes (as opposed to mocks).
 //
@@ -132,10 +123,6 @@
   // Sends the renderer process a new set of user scripts.
   void SendUserScriptsUpdate(base::SharedMemory* shared_memory);
 
-  // Sends the renderer process the list of all loaded extensions along with a
-  // subset of information the renderer needs about them.
-  void SendExtensionInfo();
-
   // Generates a command line to be used to spawn a renderer and appends the
   // results to |*command_line|.
   void AppendRendererCommandLine(CommandLine* command_line) const;
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc
index bc35c42..05aa75f 100644
--- a/chrome/browser/renderer_host/buffered_resource_handler.cc
+++ b/chrome/browser/renderer_host/buffered_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -89,7 +89,7 @@
 
 bool BufferedResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   return real_handler_->OnResponseCompleted(request_id, status, security_info);
 }
@@ -434,7 +434,8 @@
   webkit::npapi::WebPluginInfo info;
   bool allow_wildcard = false;
   return !webkit::npapi::PluginList::Singleton()->GetPluginInfo(
-      GURL(), type, allow_wildcard, &info, NULL) || !info.enabled;
+      GURL(), type, allow_wildcard, &info, NULL) ||
+      !webkit::npapi::IsPluginEnabled(info);
 }
 
 void BufferedResourceHandler::UseAlternateResourceHandler(
@@ -455,7 +456,7 @@
   // Inform the original ResourceHandler that this will be handled entirely by
   // the new ResourceHandler.
   real_handler_->OnResponseStarted(info->request_id(), response_);
-  URLRequestStatus status(URLRequestStatus::HANDLED_EXTERNALLY, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0);
   real_handler_->OnResponseCompleted(info->request_id(), status, std::string());
 
   // Remove the non-owning pointer to the CrossSiteResourceHandler, if any,
diff --git a/chrome/browser/renderer_host/cross_site_resource_handler.cc b/chrome/browser/renderer_host/cross_site_resource_handler.cc
index b1ac20a..d3236f6 100644
--- a/chrome/browser/renderer_host/cross_site_resource_handler.cc
+++ b/chrome/browser/renderer_host/cross_site_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -100,7 +100,7 @@
 
 bool CrossSiteResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   if (!in_cross_site_transition_) {
     if (has_started_response_) {
diff --git a/chrome/browser/renderer_host/database_message_filter.cc b/chrome/browser/renderer_host/database_message_filter.cc
index 4ae0aca..c3dc055 100644
--- a/chrome/browser/renderer_host/database_message_filter.cc
+++ b/chrome/browser/renderer_host/database_message_filter.cc
@@ -15,7 +15,7 @@
 #include "chrome/common/result_codes.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/sqlite/sqlite3.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
 #include "webkit/database/database_util.h"
 #include "webkit/database/vfs_backend.h"
 
diff --git a/chrome/browser/renderer_host/download_resource_handler.cc b/chrome/browser/renderer_host/download_resource_handler.cc
index 7adc462..a297244 100644
--- a/chrome/browser/renderer_host/download_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -36,6 +36,7 @@
       global_id_(render_process_host_id, request_id),
       render_view_id_(render_view_id),
       url_(url),
+      original_url_(url),
       content_length_(0),
       download_file_manager_(download_file_manager),
       request_(request),
@@ -124,6 +125,7 @@
   // |download_file_manager_| consumes (deletes):
   DownloadCreateInfo* info = new DownloadCreateInfo;
   info->url = url_;
+  info->original_url = original_url_;
   info->referrer_url = GURL(request_->referrer());
   info->start_time = base::Time::Now();
   info->received_bytes = 0;
@@ -184,7 +186,7 @@
   if (!*bytes_read)
     return true;
   DCHECK(read_buffer_);
-  AutoLock auto_lock(buffer_->lock);
+  base::AutoLock auto_lock(buffer_->lock);
   bool need_update = buffer_->contents.empty();
 
   // We are passing ownership of this buffer to the download file manager.
@@ -210,7 +212,7 @@
 
 bool DownloadResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   VLOG(20) << __FUNCTION__ << "()" << DebugString()
            << " request_id = " << request_id
@@ -263,7 +265,7 @@
 
   size_t contents_size;
   {
-    AutoLock lock(buffer_->lock);
+    base::AutoLock lock(buffer_->lock);
     contents_size = buffer_->contents.size();
   }
 
diff --git a/chrome/browser/renderer_host/download_resource_handler.h b/chrome/browser/renderer_host/download_resource_handler.h
index bc26989..f416ee2 100644
--- a/chrome/browser/renderer_host/download_resource_handler.h
+++ b/chrome/browser/renderer_host/download_resource_handler.h
@@ -91,8 +91,9 @@
   void StartDownloadUrlCheck();
 
   // Called when the result of checking a download URL is known.
-  void OnDownloadUrlCheckResult(const GURL& url,
-                                SafeBrowsingService::UrlCheckResult result);
+  virtual void OnDownloadUrlCheckResult(
+      const GURL& url,
+      SafeBrowsingService::UrlCheckResult result);
 
   // A helper function that updates UMA for download url checks.
   static void UpdateDownloadUrlCheckStats(SBStatsType stat_type);
@@ -102,7 +103,8 @@
   int render_view_id_;
   scoped_refptr<net::IOBuffer> read_buffer_;
   std::string content_disposition_;
-  GURL url_;
+  GURL url_; // final URL from which we're downloading.
+  GURL original_url_; // original URL before any redirection by the server.
   int64 content_length_;
   DownloadFileManager* download_file_manager_;
   net::URLRequest* request_;
diff --git a/chrome/browser/renderer_host/download_throttling_resource_handler.cc b/chrome/browser/renderer_host/download_throttling_resource_handler.cc
index 833c8a1..ad1459f 100644
--- a/chrome/browser/renderer_host/download_throttling_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_throttling_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -119,7 +119,7 @@
 
 bool DownloadThrottlingResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   if (download_handler_.get())
     return download_handler_->OnResponseCompleted(request_id, status,
diff --git a/chrome/browser/renderer_host/gpu_message_filter.cc b/chrome/browser/renderer_host/gpu_message_filter.cc
new file mode 100644
index 0000000..4ff5357
--- /dev/null
+++ b/chrome/browser/renderer_host/gpu_message_filter.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/gpu_message_filter.h"
+
+#include "base/callback.h"
+#include "chrome/browser/gpu_process_host_ui_shim.h"
+#include "chrome/common/gpu_create_command_buffer_config.h"
+#include "chrome/common/gpu_messages.h"
+#include "chrome/common/render_messages.h"
+
+GpuMessageFilter::GpuMessageFilter(int render_process_id)
+    : render_process_id_(render_process_id) {
+}
+
+GpuMessageFilter::~GpuMessageFilter() {
+  // This function should be called on the IO thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+}
+
+void GpuMessageFilter::OverrideThreadForMessage(
+    const IPC::Message& message,
+    BrowserThread::ID* thread) {
+  if (IPC_MESSAGE_CLASS(message) == GpuMsgStart)
+    *thread = BrowserThread::UI;
+}
+
+bool GpuMessageFilter::OnMessageReceived(
+    const IPC::Message& message,
+    bool* message_was_ok) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP_EX(GpuMessageFilter, message, *message_was_ok)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_EstablishGpuChannel,
+                        OnEstablishGpuChannel)
+    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_SynchronizeGpu,
+                                    OnSynchronizeGpu)
+    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_CreateViewCommandBuffer,
+                                    OnCreateViewCommandBuffer)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP_EX()
+  return handled;
+}
+
+void GpuMessageFilter::OnDestruct() const {
+  BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+// Callbacks used in this file.
+namespace {
+
+class EstablishChannelCallback
+    : public CallbackRunner<Tuple2<const IPC::ChannelHandle&,
+                                   const GPUInfo&> > {
+ public:
+  explicit EstablishChannelCallback(GpuMessageFilter* filter):
+    filter_(filter->AsWeakPtr()) {
+  }
+
+  virtual void RunWithParams(const TupleType& params) {
+    DispatchToMethod(this, &EstablishChannelCallback::Send, params);
+  }
+
+  void Send(const IPC::ChannelHandle& channel,
+            const GPUInfo& gpu_info) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    ViewMsg_GpuChannelEstablished* reply =
+        new ViewMsg_GpuChannelEstablished(channel, gpu_info);
+    // If the renderer process is performing synchronous initialization,
+    // it needs to handle this message before receiving the reply for
+    // the synchronous GpuHostMsg_SynchronizeGpu message.
+    reply->set_unblock(true);
+
+    if (filter_)
+      filter_->Send(reply);
+  }
+
+ private:
+  base::WeakPtr<GpuMessageFilter> filter_;
+};
+
+class SynchronizeCallback : public CallbackRunner<Tuple0> {
+ public:
+  SynchronizeCallback(GpuMessageFilter* filter, IPC::Message* reply):
+    filter_(filter->AsWeakPtr()),
+    reply_(reply) {
+  }
+
+  virtual void RunWithParams(const TupleType& params) {
+    DispatchToMethod(this, &SynchronizeCallback::Send, params);
+  }
+
+  void Send() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    if (filter_)
+      filter_->Send(reply_);
+  }
+
+ private:
+  base::WeakPtr<GpuMessageFilter> filter_;
+  IPC::Message* reply_;
+};
+
+class CreateCommandBufferCallback : public CallbackRunner<Tuple1<int32> > {
+ public:
+  CreateCommandBufferCallback(GpuMessageFilter* filter,
+                              IPC::Message* reply) :
+    filter_(filter->AsWeakPtr()),
+    reply_(reply) {
+  }
+
+  virtual void RunWithParams(const TupleType& params) {
+    DispatchToMethod(this, &CreateCommandBufferCallback::Send, params);
+  }
+
+  void Send(int32 route_id) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    GpuHostMsg_CreateViewCommandBuffer::WriteReplyParams(reply_, route_id);
+    if (filter_)
+      filter_->Send(reply_);
+  }
+
+ private:
+  base::WeakPtr<GpuMessageFilter> filter_;
+  IPC::Message* reply_;
+};
+
+}  // namespace
+
+void GpuMessageFilter::OnEstablishGpuChannel() {
+  GpuProcessHostUIShim::GetInstance()->EstablishGpuChannel(
+      render_process_id_, new EstablishChannelCallback(this));
+}
+
+void GpuMessageFilter::OnSynchronizeGpu(IPC::Message* reply) {
+  GpuProcessHostUIShim::GetInstance()->
+      Synchronize(new SynchronizeCallback(this, reply));
+}
+
+void GpuMessageFilter::OnCreateViewCommandBuffer(
+    int32 render_view_id,
+    const GPUCreateCommandBufferConfig& init_params,
+    IPC::Message* reply) {
+  GpuProcessHostUIShim::GetInstance()->CreateViewCommandBuffer(
+      render_view_id, render_process_id_, init_params,
+      new CreateCommandBufferCallback(this, reply));
+}
diff --git a/chrome/browser/renderer_host/gpu_message_filter.h b/chrome/browser/renderer_host/gpu_message_filter.h
new file mode 100644
index 0000000..638464c
--- /dev/null
+++ b/chrome/browser/renderer_host/gpu_message_filter.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_
+#define CHROME_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_
+#pragma once
+
+#include <queue>
+
+#include "chrome/browser/browser_message_filter.h"
+
+struct GPUCreateCommandBufferConfig;
+class GPUInfo;
+
+namespace IPC {
+struct ChannelHandle;
+}
+
+// A message filter for messages from the renderer to the GpuProcessHost
+// in the browser. Such messages are typically destined for the GPU process,
+// but need to be mediated by the browser.
+class GpuMessageFilter : public BrowserMessageFilter,
+                         public base::SupportsWeakPtr<GpuMessageFilter> {
+ public:
+  explicit GpuMessageFilter(int render_process_id);
+
+  // BrowserMessageFilter methods:
+  virtual void OverrideThreadForMessage(const IPC::Message& message,
+                                        BrowserThread::ID* thread);
+  virtual bool OnMessageReceived(const IPC::Message& message,
+                                 bool* message_was_ok);
+  virtual void OnDestruct() const;
+
+ private:
+  friend class BrowserThread;
+  friend class DeleteTask<GpuMessageFilter>;
+  virtual ~GpuMessageFilter();
+
+  // Message handlers called on the browser IO thread:
+  void OnEstablishGpuChannel();
+  void OnSynchronizeGpu(IPC::Message* reply);
+  void OnCreateViewCommandBuffer(
+      int32 render_view_id,
+      const GPUCreateCommandBufferConfig& init_params,
+      IPC::Message* reply);
+
+  int render_process_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(GpuMessageFilter);
+};
+
+#endif  // CHROME_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc
index 0c2002c..f586864 100644
--- a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc
+++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,29 +7,30 @@
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
+
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "base/third_party/icu/icu_utf.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #if !defined(TOOLKIT_VIEWS)
-#include "chrome/browser/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
 #endif
 #include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
 #include "chrome/common/native_web_keyboard_event.h"
 #include "chrome/common/render_messages.h"
-#include "gfx/gtk_util.h"
-#include "gfx/rect.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/rect.h"
 
 namespace {
-// Copied from third_party/WebKit/WebCore/page/EventHandler.cpp
+// Copied from third_party/WebKit/Source/WebCore/page/EventHandler.cpp
 //
 // Match key code of composition keydown event on windows.
 // IE sends VK_PROCESSKEY which has value 229;
@@ -55,7 +56,10 @@
       preedit_selection_start_(0),
       preedit_selection_end_(0),
       is_preedit_changed_(false),
-      suppress_next_commit_(false) {
+      suppress_next_commit_(false),
+      last_key_code_(0),
+      last_key_was_up_(false),
+      last_key_filtered_no_result_(false) {
   DCHECK(context_);
   DCHECK(context_simple_);
 
@@ -158,11 +162,19 @@
   // RenderView::UnhandledKeyboardEvent() from processing it.
   // Otherwise unexpected result may occur. For example if it's a
   // Backspace key event, the browser may go back to previous page.
-  if (filtered)
+  // We just send all keyup events to the browser to avoid breaking the
+  // browser's MENU key function, which is actually the only keyup event
+  // handled in the browser.
+  if (filtered && event->type == GDK_KEY_PRESS)
     wke.skip_in_browser = true;
 
+  const int key_code = wke.windowsKeyCode;
+  const bool has_result = HasInputMethodResult();
+
   // Send filtered keydown event before sending IME result.
-  if (event->type == GDK_KEY_PRESS && filtered)
+  // In order to workaround http://crosbug.com/6582, we only send a filtered
+  // keydown event if it generated any input method result.
+  if (event->type == GDK_KEY_PRESS && filtered && has_result)
     ProcessFilteredKeyPressEvent(&wke);
 
   // Send IME results. In most cases, it's only available if the key event
@@ -182,13 +194,26 @@
   //
   // In this case, the input box will be in a strange state if keydown
   // Backspace is sent to webkit before commit "a" and preedit end.
-  ProcessInputMethodResult(event, filtered);
+  if (has_result)
+    ProcessInputMethodResult(event, filtered);
 
   // Send unfiltered keydown and keyup events after sending IME result.
-  if (event->type == GDK_KEY_PRESS && !filtered)
+  if (event->type == GDK_KEY_PRESS && !filtered) {
     ProcessUnfilteredKeyPressEvent(&wke);
-  else if (event->type == GDK_KEY_RELEASE)
-    host_view_->ForwardKeyboardEvent(wke);
+  } else if (event->type == GDK_KEY_RELEASE) {
+    // In order to workaround http://crosbug.com/6582, we need to suppress
+    // the keyup event if corresponding keydown event was suppressed, or
+    // the last key event was a keyup event with the same keycode.
+    const bool suppress = (last_key_code_ == key_code) &&
+        (last_key_was_up_ || last_key_filtered_no_result_);
+
+    if (!suppress)
+      host_view_->ForwardKeyboardEvent(wke);
+  }
+
+  last_key_code_ = key_code;
+  last_key_was_up_ = (event->type == GDK_KEY_RELEASE);
+  last_key_filtered_no_result_ = (filtered && !has_result);
 }
 
 void GtkIMContextWrapper::UpdateInputMethodState(WebKit::WebTextInputType type,
@@ -229,6 +254,10 @@
   // GtkIMContext object correctly later when IME is enabled by WebKit.
   is_focused_ = true;
 
+  last_key_code_ = 0;
+  last_key_was_up_ = false;
+  last_key_filtered_no_result_ = false;
+
   // Notify the GtkIMContext object of this focus-in event only if IME is
   // enabled by WebKit.
   if (is_enabled_)
@@ -322,7 +351,7 @@
   is_in_key_event_handler_ = false;
 }
 
-bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() {
+bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() const {
   // If there is no composition text and has only one character to be
   // committed, then the character will be send to webkit as a Char event
   // instead of a confirmed composition text.
@@ -331,6 +360,10 @@
   return !is_composing_text_ && commit_text_.length() == 1;
 }
 
+bool GtkIMContextWrapper::HasInputMethodResult() const {
+  return commit_text_.length() || is_preedit_changed_;
+}
+
 void GtkIMContextWrapper::ProcessFilteredKeyPressEvent(
     NativeWebKeyboardEvent* wke) {
   // If IME has filtered this event, then replace virtual key code with
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.h b/chrome/browser/renderer_host/gtk_im_context_wrapper.h
index 94d6bfa..60bff99 100644
--- a/chrome/browser/renderer_host/gtk_im_context_wrapper.h
+++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.h
@@ -13,9 +13,9 @@
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextInputType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextInputType.h"
 
 namespace gfx {
 class Rect;
@@ -70,7 +70,10 @@
 
   // Check if a text needs commit by forwarding a char event instead of
   // by confirming as a composition text.
-  bool NeedCommitByForwardingCharEvent();
+  bool NeedCommitByForwardingCharEvent() const;
+
+  // Check if the input method returned any result, eg. preedit and commit text.
+  bool HasInputMethodResult() const;
 
   void ProcessFilteredKeyPressEvent(NativeWebKeyboardEvent* wke);
   void ProcessUnfilteredKeyPressEvent(NativeWebKeyboardEvent* wke);
@@ -206,6 +209,12 @@
   // TODO(suzhe): Remove it after input methods get fixed.
   bool suppress_next_commit_;
 
+  // Information of the last key event, for working around
+  // http://crosbug.com/6582
+  int last_key_code_;
+  bool last_key_was_up_;
+  bool last_key_filtered_no_result_;
+
   DISALLOW_COPY_AND_ASSIGN(GtkIMContextWrapper);
 };
 
diff --git a/chrome/browser/renderer_host/gtk_key_bindings_handler.h b/chrome/browser/renderer_host/gtk_key_bindings_handler.h
index 4a58a4c..a33a417 100644
--- a/chrome/browser/renderer_host/gtk_key_bindings_handler.h
+++ b/chrome/browser/renderer_host/gtk_key_bindings_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 
 #include <string>
 
-#include "chrome/browser/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
 #include "chrome/common/edit_command.h"
 
 struct NativeWebKeyboardEvent;
@@ -30,7 +30,7 @@
 // class derived from GtkTextView is used, which overrides all signals related
 // to key bindings, to make sure GtkTextView won't receive them.
 //
-// See third_party/WebKit/WebCore/editing/EditorCommand.cpp for detailed
+// See third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp for detailed
 // definition of webkit edit commands.
 // See webkit/glue/editor_client_impl.cc for key bindings predefined in our
 // webkit glue.
diff --git a/chrome/browser/renderer_host/mock_render_process_host.h b/chrome/browser/renderer_host/mock_render_process_host.h
index 6309685..0e67224 100644
--- a/chrome/browser/renderer_host/mock_render_process_host.h
+++ b/chrome/browser/renderer_host/mock_render_process_host.h
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "base/scoped_vector.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
-#include "chrome/common/ipc_test_sink.h"
+#include "ipc/ipc_test_sink.h"
 
 class MockRenderProcessHostFactory;
 class TransportDIB;
diff --git a/chrome/browser/renderer_host/offline_resource_handler.cc b/chrome/browser/renderer_host/offline_resource_handler.cc
index 362f411..6013c16 100644
--- a/chrome/browser/renderer_host/offline_resource_handler.cc
+++ b/chrome/browser/renderer_host/offline_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -53,7 +53,7 @@
 
 bool OfflineResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   return next_handler_->OnResponseCompleted(request_id, status, security_info);
 }
diff --git a/chrome/browser/renderer_host/pepper_file_message_filter.cc b/chrome/browser/renderer_host/pepper_file_message_filter.cc
index 8c30300..5109e7b 100644
--- a/chrome/browser/renderer_host/pepper_file_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper_file_message_filter.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/browser_render_process_host.h"
 #include "chrome/common/child_process_host.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pepper_file_messages.h"
 #include "ipc/ipc_platform_file.h"
 
diff --git a/chrome/browser/renderer_host/pepper_message_filter.cc b/chrome/browser/renderer_host/pepper_message_filter.cc
index 62464af..de0793d 100644
--- a/chrome/browser/renderer_host/pepper_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper_message_filter.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/browser_render_process_host.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/common/pepper_messages.h"
 #include "net/base/address_list.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/host_resolver.h"
@@ -34,17 +34,19 @@
 const PP_Flash_NetAddress kInvalidNetAddress = { 0 };
 
 PepperMessageFilter::PepperMessageFilter(Profile* profile)
-    : profile_(profile) {
+    : profile_(profile),
+      request_context_(profile_->GetRequestContext()) {
 }
 
+PepperMessageFilter::~PepperMessageFilter() {}
+
 bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
                                             bool* message_was_ok) {
 #if defined(ENABLE_FLAPPER_HACKS)
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP_EX(PepperMessageFilter, msg, *message_was_ok)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PepperConnectTcp, OnPepperConnectTcp)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PepperConnectTcpAddress,
-                        OnPepperConnectTcpAddress)
+    IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcp, OnConnectTcp)
+    IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcpAddress, OnConnectTcpAddress)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP_EX()
   return handled;
@@ -144,7 +146,7 @@
 
  private:
   void OnLookupFinished(int /*result*/) {
-    pepper_message_filter_->PepperConnectTcpLookupFinished(
+    pepper_message_filter_->ConnectTcpLookupFinished(
         routing_id_, request_id_, addresses_);
     delete this;
   }
@@ -164,15 +166,14 @@
   DISALLOW_COPY_AND_ASSIGN(LookupRequest);
 };
 
-void PepperMessageFilter::OnPepperConnectTcp(
-    int routing_id,
-    int request_id,
-    const std::string& host,
-    uint16 port) {
+void PepperMessageFilter::OnConnectTcp(int routing_id,
+                                       int request_id,
+                                       const std::string& host,
+                                       uint16 port) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  URLRequestContext* req_context =
-      profile_->GetRequestContext()->GetURLRequestContext();
+  net::URLRequestContext* req_context =
+      request_context_->GetURLRequestContext();
   net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
 
   // The lookup request will delete itself on completion.
@@ -182,10 +183,9 @@
   lookup_request->Start();
 }
 
-void PepperMessageFilter::OnPepperConnectTcpAddress(
-    int routing_id,
-    int request_id,
-    const PP_Flash_NetAddress& addr) {
+void PepperMessageFilter::OnConnectTcpAddress(int routing_id,
+                                              int request_id,
+                                              const PP_Flash_NetAddress& addr) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // Validate the address and then continue (doing |connect()|) on a worker
@@ -194,22 +194,22 @@
       !base::WorkerPool::PostTask(FROM_HERE,
            NewRunnableMethod(
                this,
-               &PepperMessageFilter::PepperConnectTcpAddressOnWorkerThread,
+               &PepperMessageFilter::ConnectTcpAddressOnWorkerThread,
                routing_id, request_id, addr),
            true)) {
-    SendPepperConnectTcpACKError(routing_id, request_id);
+    SendConnectTcpACKError(routing_id, request_id);
   }
 }
 
-bool PepperMessageFilter::SendPepperConnectTcpACKError(int routing_id,
-                                                       int request_id) {
-  return Send(new ViewMsg_PepperConnectTcpACK(
-              routing_id, request_id,
-              IPC::InvalidPlatformFileForTransit(),
-              kInvalidNetAddress, kInvalidNetAddress));
+bool PepperMessageFilter::SendConnectTcpACKError(int routing_id,
+                                                 int request_id) {
+  return Send(
+      new PepperMsg_ConnectTcpACK(routing_id, request_id,
+                                  IPC::InvalidPlatformFileForTransit(),
+                                  kInvalidNetAddress, kInvalidNetAddress));
 }
 
-void PepperMessageFilter::PepperConnectTcpLookupFinished(
+void PepperMessageFilter::ConnectTcpLookupFinished(
     int routing_id,
     int request_id,
     const net::AddressList& addresses) {
@@ -221,19 +221,16 @@
       !base::WorkerPool::PostTask(FROM_HERE,
            NewRunnableMethod(
                this,
-               &PepperMessageFilter::PepperConnectTcpOnWorkerThread,
+               &PepperMessageFilter::ConnectTcpOnWorkerThread,
                routing_id, request_id, addresses),
            true)) {
-    SendPepperConnectTcpACKError(routing_id, request_id);
+    SendConnectTcpACKError(routing_id, request_id);
   }
 }
 
-void PepperMessageFilter::PepperConnectTcpOnWorkerThread(
-    int routing_id,
-    int request_id,
-    net::AddressList addresses) {
-  DCHECK(!MessageLoop::current());  // Check we are on a worker thread.
-
+void PepperMessageFilter::ConnectTcpOnWorkerThread(int routing_id,
+                                                   int request_id,
+                                                   net::AddressList addresses) {
   IPC::PlatformFileForTransit socket_for_transit =
       IPC::InvalidPlatformFileForTransit();
   PP_Flash_NetAddress local_addr = kInvalidNetAddress;
@@ -252,19 +249,17 @@
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
       NewRunnableMethod(
           this, &PepperMessageFilter::Send,
-          new ViewMsg_PepperConnectTcpACK(
+          new PepperMsg_ConnectTcpACK(
               routing_id, request_id,
               socket_for_transit, local_addr, remote_addr)));
 }
 
 // TODO(vluu): Eliminate duplication between this and
-// |PepperConnectTcpOnWorkerThread()|.
-void PepperMessageFilter::PepperConnectTcpAddressOnWorkerThread(
+// |ConnectTcpOnWorkerThread()|.
+void PepperMessageFilter::ConnectTcpAddressOnWorkerThread(
     int routing_id,
     int request_id,
     PP_Flash_NetAddress addr) {
-  DCHECK(!MessageLoop::current());  // Check we are on a worker thread.
-
   IPC::PlatformFileForTransit socket_for_transit =
       IPC::InvalidPlatformFileForTransit();
   PP_Flash_NetAddress local_addr = kInvalidNetAddress;
@@ -277,7 +272,7 @@
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
       NewRunnableMethod(
           this, &PepperMessageFilter::Send,
-          new ViewMsg_PepperConnectTcpACK(
+          new PepperMsg_ConnectTcpACK(
               routing_id, request_id,
               socket_for_transit, local_addr, remote_addr)));
 }
diff --git a/chrome/browser/renderer_host/pepper_message_filter.h b/chrome/browser/renderer_host/pepper_message_filter.h
index ec36c08..17ccf11 100644
--- a/chrome/browser/renderer_host/pepper_message_filter.h
+++ b/chrome/browser/renderer_host/pepper_message_filter.h
@@ -15,6 +15,7 @@
 #include "ppapi/c/private/ppb_flash.h"
 
 class Profile;
+class URLRequestContextGetter;
 
 namespace net {
 class AddressList;
@@ -23,6 +24,7 @@
 class PepperMessageFilter : public BrowserMessageFilter {
  public:
   explicit PepperMessageFilter(Profile* profile);
+  virtual ~PepperMessageFilter();
 
  private:
   // BrowserMessageFilter methods.
@@ -31,37 +33,38 @@
 
 #if defined(ENABLE_FLAPPER_HACKS)
   // Message handlers.
-  void OnPepperConnectTcp(int routing_id,
-                          int request_id,
-                          const std::string& host,
-                          uint16 port);
-  void OnPepperConnectTcpAddress(int routing_id,
-                                 int request_id,
-                                 const PP_Flash_NetAddress& address);
+  void OnConnectTcp(int routing_id,
+                    int request_id,
+                    const std::string& host,
+                    uint16 port);
+  void OnConnectTcpAddress(int routing_id,
+                           int request_id,
+                           const PP_Flash_NetAddress& address);
 
-  // |Send()| a |ViewMsg_PepperConnectTcpACK|, which reports an error.
-  bool SendPepperConnectTcpACKError(int routing_id,
-                                    int request_id);
+  // |Send()| a |PepperMsg_ConnectTcpACK|, which reports an error.
+  bool SendConnectTcpACKError(int routing_id,
+                              int request_id);
 
-  // Used by |OnPepperConnectTcp()| (below).
+  // Used by |OnConnectTcp()| (below).
   class LookupRequest;
   friend class LookupRequest;
 
-  // Continuation of |OnPepperConnectTcp()|.
-  void PepperConnectTcpLookupFinished(int routing_id,
-                                      int request_id,
-                                      const net::AddressList& addresses);
-  void PepperConnectTcpOnWorkerThread(int routing_id,
-                                      int request_id,
-                                      net::AddressList addresses);
+  // Continuation of |OnConnectTcp()|.
+  void ConnectTcpLookupFinished(int routing_id,
+                                int request_id,
+                                const net::AddressList& addresses);
+  void ConnectTcpOnWorkerThread(int routing_id,
+                                int request_id,
+                                net::AddressList addresses);
 
-  // Continuation of |OnPepperConnectTcpAddress()|.
-  void PepperConnectTcpAddressOnWorkerThread(int routing_id,
-                                             int request_id,
-                                             PP_Flash_NetAddress addr);
+  // Continuation of |OnConnectTcpAddress()|.
+  void ConnectTcpAddressOnWorkerThread(int routing_id,
+                                       int request_id,
+                                       PP_Flash_NetAddress addr);
 #endif  // ENABLE_FLAPPER_HACKS
 
   Profile* profile_;
+  scoped_refptr<URLRequestContextGetter> request_context_;
 };
 
 #endif  // CHROME_BROWSER_RENDERER_HOST_PEPPER_MESSAGE_FILTER_H_
diff --git a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
index 1e7d4b3..11d5934 100644
--- a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
+++ b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -133,7 +133,7 @@
 
 bool RedirectToFileResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   return next_handler_->OnResponseCompleted(request_id, status, security_info);
 }
diff --git a/chrome/browser/renderer_host/render_message_filter.cc b/chrome/browser/renderer_host/render_message_filter.cc
index 1f86ca8..f4f8514 100644
--- a/chrome/browser/renderer_host/render_message_filter.cc
+++ b/chrome/browser/renderer_host/render_message_filter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,7 +23,6 @@
 #include "chrome/browser/clipboard_dispatcher.h"
 #include "chrome/browser/download/download_types.h"
 #include "chrome/browser/extensions/extension_message_service.h"
-#include "chrome/browser/gpu_process_host.h"
 #include "chrome/browser/host_zoom_map.h"
 #include "chrome/browser/metrics/histogram_synchronizer.h"
 #include "chrome/browser/metrics/user_metrics.h"
@@ -62,19 +61,19 @@
 #include "net/http/http_cache.h"
 #include "net/http/http_network_layer.h"
 #include "net/url_request/url_request_context.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
 #include "webkit/glue/context_menu.h"
 #include "webkit/glue/webcookie.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/plugins/npapi/plugin_group.h"
 #include "webkit/plugins/npapi/plugin_list.h"
 #include "webkit/plugins/npapi/webplugin.h"
+#include "webkit/plugins/npapi/webplugininfo.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/plugin_selection_policy.h"
 #endif
 #if defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/task_helpers.h"
 #include "chrome/common/font_descriptor_mac.h"
 #include "chrome/common/font_loader_mac.h"
 #endif
@@ -84,6 +83,9 @@
 #if defined(OS_WIN)
 #include "chrome/common/child_process_host.h"
 #endif
+#if defined(USE_NSS)
+#include "chrome/browser/ui/crypto_module_password_dialog.h"
+#endif
 #if defined(USE_TCMALLOC)
 #include "chrome/browser/browser_about_handler.h"
 #endif
@@ -131,7 +133,7 @@
 // contents.
 class WriteClipboardTask : public Task {
  public:
-  explicit WriteClipboardTask(Clipboard::ObjectMap* objects)
+  explicit WriteClipboardTask(ui::Clipboard::ObjectMap* objects)
       : objects_(objects) {}
   ~WriteClipboardTask() {}
 
@@ -140,7 +142,7 @@
   }
 
  private:
-  scoped_ptr<Clipboard::ObjectMap> objects_;
+  scoped_ptr<ui::Clipboard::ObjectMap> objects_;
 };
 
 void RenderParamsFromPrintSettings(const printing::PrintSettings& settings,
@@ -162,41 +164,65 @@
   // Always use an invalid cookie.
   params->document_cookie = 0;
   params->selection_only = settings.selection_only;
+  params->supports_alpha_blend = settings.supports_alpha_blend();
 }
 
-class ClearCacheCompletion : public net::CompletionCallback {
+// Common functionality for converting a sync renderer message to a callback
+// function in the browser. Derive from this, create it on the heap when
+// issuing your callback. When done, write your reply parameters into
+// reply_msg(), and then call SendReplyAndDeleteThis().
+class RenderMessageCompletionCallback {
  public:
-  ClearCacheCompletion(IPC::Message* reply_msg,
-                       RenderMessageFilter* filter)
-      : reply_msg_(reply_msg),
-        filter_(filter) {
+  RenderMessageCompletionCallback(RenderMessageFilter* filter,
+                                  IPC::Message* reply_msg)
+      : filter_(filter),
+        reply_msg_(reply_msg) {
   }
 
-  virtual void RunWithParams(const Tuple1<int>& params) {
-    ViewHostMsg_ClearCache::WriteReplyParams(reply_msg_, params.a);
+  virtual ~RenderMessageCompletionCallback() {
+  }
+
+  RenderMessageFilter* filter() { return filter_.get(); }
+  IPC::Message* reply_msg() { return reply_msg_; }
+
+  void SendReplyAndDeleteThis() {
     filter_->Send(reply_msg_);
     delete this;
   }
 
  private:
-  IPC::Message* reply_msg_;
   scoped_refptr<RenderMessageFilter> filter_;
+  IPC::Message* reply_msg_;
 };
 
-class OpenChannelToPluginCallback : public PluginProcessHost::Client {
+class ClearCacheCompletion : public RenderMessageCompletionCallback,
+                             public net::CompletionCallback {
  public:
-  OpenChannelToPluginCallback(RenderMessageFilter* filter,
-                              IPC::Message* reply_msg)
-      : filter_(filter),
-        reply_msg_(reply_msg) {
+  ClearCacheCompletion(RenderMessageFilter* filter,
+                       IPC::Message* reply_msg)
+      : RenderMessageCompletionCallback(filter, reply_msg) {
+  }
+
+  virtual void RunWithParams(const Tuple1<int>& params) {
+    ViewHostMsg_ClearCache::WriteReplyParams(reply_msg(), params.a);
+    SendReplyAndDeleteThis();
+  }
+};
+
+class OpenChannelToNpapiPluginCallback : public RenderMessageCompletionCallback,
+                                         public PluginProcessHost::Client {
+ public:
+  OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter,
+                                   IPC::Message* reply_msg)
+      : RenderMessageCompletionCallback(filter, reply_msg) {
   }
 
   virtual int ID() {
-    return filter_->render_process_id();
+    return filter()->render_process_id();
   }
 
   virtual bool OffTheRecord() {
-    return filter_->off_the_record();
+    return filter()->off_the_record();
   }
 
   virtual void SetPluginInfo(const webkit::npapi::WebPluginInfo& info) {
@@ -204,27 +230,45 @@
   }
 
   virtual void OnChannelOpened(const IPC::ChannelHandle& handle) {
-    WriteReply(handle);
+    WriteReplyAndDeleteThis(handle);
   }
 
   virtual void OnError() {
-    WriteReply(IPC::ChannelHandle());
+    WriteReplyAndDeleteThis(IPC::ChannelHandle());
   }
 
  private:
-  void WriteReply(const IPC::ChannelHandle& handle) {
-    ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg_,
-                                                      handle,
-                                                      info_);
-    filter_->Send(reply_msg_);
-    delete this;
+  void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
+    ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
+                                                      handle, info_);
+    SendReplyAndDeleteThis();
   }
 
-  scoped_refptr<RenderMessageFilter> filter_;
-  IPC::Message* reply_msg_;
   webkit::npapi::WebPluginInfo info_;
 };
 
+class OpenChannelToPpapiPluginCallback : public RenderMessageCompletionCallback,
+                                         public PpapiPluginProcessHost::Client {
+ public:
+  OpenChannelToPpapiPluginCallback(RenderMessageFilter* filter,
+                                   IPC::Message* reply_msg)
+      : RenderMessageCompletionCallback(filter, reply_msg) {
+  }
+
+  virtual void GetChannelInfo(base::ProcessHandle* renderer_handle,
+                              int* renderer_id) {
+    *renderer_handle = filter()->peer_handle();
+    *renderer_id = filter()->render_process_id();
+  }
+
+  virtual void OnChannelOpened(base::ProcessHandle plugin_process_handle,
+                               const IPC::ChannelHandle& channel_handle) {
+    ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(
+        reply_msg(), plugin_process_handle, channel_handle);
+    SendReplyAndDeleteThis();
+  }
+};
+
 }  // namespace
 
 RenderMessageFilter::RenderMessageFilter(
@@ -280,6 +324,8 @@
                                     OnGetRootWindowRect)
 #endif
 
+    IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID)
+
     IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow)
     IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget)
     IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
@@ -388,9 +434,6 @@
 #if defined(USE_TCMALLOC)
     IPC_MESSAGE_HANDLER(ViewHostMsg_RendererTcmalloc, OnRendererTcmalloc)
 #endif
-    IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel, OnEstablishGpuChannel)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu,
-                                    OnSynchronizeGpu)
     IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenFile, OnAsyncOpenFile)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP_EX()
@@ -441,13 +484,22 @@
 void RenderMessageFilter::OnMsgCreateWindow(
     const ViewHostMsg_CreateWindow_Params& params,
     int* route_id, int64* cloned_session_storage_namespace_id) {
+  // If the opener is trying to create a background window but doesn't have
+  // the appropriate permission, fail the attempt.
+  if (params.window_container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) {
+    ChromeURLRequestContext* context =
+        GetRequestContextForURL(params.opener_url);
+    if (!context->extension_info_map()->CheckURLAccessToExtensionPermission(
+            params.opener_url, Extension::kBackgroundPermission)) {
+      *route_id = MSG_ROUTING_NONE;
+      return;
+    }
+  }
+
   *cloned_session_storage_namespace_id =
       webkit_context_->dom_storage_context()->CloneSessionStorage(
           params.session_storage_namespace_id);
-  render_widget_helper_->CreateNewWindow(params.opener_id,
-                                         params.user_gesture,
-                                         params.window_container_type,
-                                         params.frame_name,
+  render_widget_helper_->CreateNewWindow(params,
                                          peer_handle(),
                                          route_id);
 }
@@ -458,10 +510,9 @@
   render_widget_helper_->CreateNewWidget(opener_id, popup_type, route_id);
 }
 
-void RenderMessageFilter::OnMsgCreateFullscreenWidget(
-    int opener_id, WebKit::WebPopupType popup_type, int* route_id) {
-  render_widget_helper_->CreateNewFullscreenWidget(
-      opener_id, popup_type, route_id);
+void RenderMessageFilter::OnMsgCreateFullscreenWidget(int opener_id,
+                                                      int* route_id) {
+  render_widget_helper_->CreateNewFullscreenWidget(opener_id, route_id);
 }
 
 void RenderMessageFilter::OnSetCookie(const IPC::Message& message,
@@ -526,7 +577,7 @@
   // TODO(ananta) We need to support retreiving raw cookies from external
   // hosts.
   if (!ChildProcessSecurityPolicy::GetInstance()->CanReadRawCookies(
-          render_process_id_) || context->IsExternal()) {
+          render_process_id_)) {
     ViewHostMsg_GetRawCookies::WriteReplyParams(
         reply_msg,
         std::vector<webkit_glue::WebCookie>());
@@ -555,7 +606,7 @@
 
 void RenderMessageFilter::OnDeleteCookie(const GURL& url,
                                          const std::string& cookie_name) {
-  URLRequestContext* context = GetRequestContextForURL(url);
+  net::URLRequestContext* context = GetRequestContextForURL(url);
   context->cookie_store()->DeleteCookie(url, cookie_name);
 }
 
@@ -563,7 +614,7 @@
     const GURL& url,
     const GURL& first_party_for_cookies,
     IPC::Message* reply_msg) {
-  URLRequestContext* context = GetRequestContextForURL(url);
+  net::URLRequestContext* context = GetRequestContextForURL(url);
   CookiesEnabledCompletion* callback =
       new CookiesEnabledCompletion(reply_msg, this);
   int policy = net::OK;
@@ -645,7 +696,8 @@
       NewRunnableMethod(this, &RenderMessageFilter::Send, reply_msg));
 }
 
-void RenderMessageFilter::OnGetPluginInfo(const GURL& url,
+void RenderMessageFilter::OnGetPluginInfo(int routing_id,
+                                          const GURL& url,
                                           const GURL& policy_url,
                                           const std::string& mime_type,
                                           IPC::Message* reply_msg) {
@@ -655,20 +707,20 @@
       BrowserThread::FILE, FROM_HERE,
       NewRunnableMethod(
           this, &RenderMessageFilter::OnGetPluginInfoOnFileThread,
-          url, policy_url, mime_type, reply_msg));
+          routing_id, url, policy_url, mime_type, reply_msg));
 }
 
 void RenderMessageFilter::OnGetPluginInfoOnFileThread(
+    int render_view_id,
     const GURL& url,
     const GURL& policy_url,
     const std::string& mime_type,
     IPC::Message* reply_msg) {
   std::string actual_mime_type;
   webkit::npapi::WebPluginInfo info;
-  bool found = plugin_service_->GetFirstAllowedPluginInfo(url,
-                                                          mime_type,
-                                                          &info,
-                                                          &actual_mime_type);
+  bool found = plugin_service_->GetFirstAllowedPluginInfo(
+      render_process_id_, render_view_id, url, mime_type, &info,
+      &actual_mime_type);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       NewRunnableMethod(
@@ -685,8 +737,11 @@
   ContentSetting setting = CONTENT_SETTING_DEFAULT;
   webkit::npapi::WebPluginInfo info_copy = info;
   if (found) {
-    info_copy.enabled = info_copy.enabled &&
-        plugin_service_->PrivatePluginAllowedForURL(info_copy.path, policy_url);
+    // TODO(mpcomplete): The plugin service should do this check. We should
+    // not be calling the PluginList directly.
+    if (!plugin_service_->PrivatePluginAllowedForURL(
+            info_copy.path, policy_url))
+      info_copy.enabled |= webkit::npapi::WebPluginInfo::POLICY_DISABLED;
     std::string resource =
         webkit::npapi::PluginList::Singleton()->GetPluginGroupIdentifier(
             info_copy);
@@ -701,21 +756,20 @@
   Send(reply_msg);
 }
 
-void RenderMessageFilter::OnOpenChannelToPlugin(const GURL& url,
+void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id,
+                                                const GURL& url,
                                                 const std::string& mime_type,
                                                 IPC::Message* reply_msg) {
-  plugin_service_->OpenChannelToPlugin(
-      url,
-      mime_type,
-      new OpenChannelToPluginCallback(this, reply_msg));
+  plugin_service_->OpenChannelToNpapiPlugin(
+      render_process_id_, routing_id, url, mime_type,
+      new OpenChannelToNpapiPluginCallback(this, reply_msg));
 }
 
 void RenderMessageFilter::OnOpenChannelToPepperPlugin(
     const FilePath& path,
     IPC::Message* reply_msg) {
-  PpapiPluginProcessHost* host = new PpapiPluginProcessHost(this);
-  host->Init(path, reply_msg);
-  ppapi_plugin_hosts_.push_back(linked_ptr<PpapiPluginProcessHost>(host));
+  plugin_service_->OpenChannelToPpapiPlugin(
+      path, new OpenChannelToPpapiPluginCallback(this, reply_msg));
 }
 
 void RenderMessageFilter::OnLaunchNaCl(
@@ -724,10 +778,14 @@
   host->Launch(this, channel_descriptor, reply_msg);
 }
 
+void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
+  *route_id = render_widget_helper_->GetNextRoutingID();
+}
+
 void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message,
                                         const GURL& url,
                                         const GURL& referrer) {
-  URLRequestContext* context = request_context_->GetURLRequestContext();
+  net::URLRequestContext* context = request_context_->GetURLRequestContext();
 
   // Don't show "Save As" UI.
   bool prompt_for_save_location = false;
@@ -741,7 +799,7 @@
 }
 
 void RenderMessageFilter::OnClipboardWriteObjectsSync(
-    const Clipboard::ObjectMap& objects,
+    const ui::Clipboard::ObjectMap& objects,
     base::SharedMemoryHandle bitmap_handle) {
   DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle))
       << "Bad bitmap handle";
@@ -749,11 +807,12 @@
   // on the UI thread. We'll copy the relevant data and get a handle to any
   // shared memory so it doesn't go away when we resume the renderer, and post
   // a task to perform the write on the UI thread.
-  Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects);
+  ui::Clipboard::ObjectMap* long_living_objects =
+      new ui::Clipboard::ObjectMap(objects);
 
   // Splice the shared memory handle into the clipboard data.
-  Clipboard::ReplaceSharedMemHandle(long_living_objects, bitmap_handle,
-                                    peer_handle());
+  ui::Clipboard::ReplaceSharedMemHandle(long_living_objects, bitmap_handle,
+                                        peer_handle());
 
   BrowserThread::PostTask(
       BrowserThread::UI,
@@ -762,15 +821,16 @@
 }
 
 void RenderMessageFilter::OnClipboardWriteObjectsAsync(
-    const Clipboard::ObjectMap& objects) {
+    const ui::Clipboard::ObjectMap& objects) {
   // We cannot write directly from the IO thread, and cannot service the IPC
   // on the UI thread. We'll copy the relevant data and post a task to preform
   // the write on the UI thread.
-  Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects);
+  ui::Clipboard::ObjectMap* long_living_objects =
+      new ui::Clipboard::ObjectMap(objects);
 
   // This async message doesn't support shared-memory based bitmaps; they must
   // be removed otherwise we might dereference a rubbish pointer.
-  long_living_objects->erase(Clipboard::CBF_SMBITMAP);
+  long_living_objects->erase(ui::Clipboard::CBF_SMBITMAP);
 
   BrowserThread::PostTask(
       BrowserThread::UI,
@@ -791,14 +851,14 @@
 // functions.
 
 void RenderMessageFilter::OnClipboardIsFormatAvailable(
-    Clipboard::FormatType format, Clipboard::Buffer buffer,
+    ui::Clipboard::FormatType format, ui::Clipboard::Buffer buffer,
     IPC::Message* reply) {
   const bool result = GetClipboard()->IsFormatAvailable(format, buffer);
   ViewHostMsg_ClipboardIsFormatAvailable::WriteReplyParams(reply, result);
   Send(reply);
 }
 
-void RenderMessageFilter::OnClipboardReadText(Clipboard::Buffer buffer,
+void RenderMessageFilter::OnClipboardReadText(ui::Clipboard::Buffer buffer,
                                               IPC::Message* reply) {
   string16 result;
   GetClipboard()->ReadText(buffer, &result);
@@ -806,7 +866,7 @@
   Send(reply);
 }
 
-void RenderMessageFilter::OnClipboardReadAsciiText(Clipboard::Buffer buffer,
+void RenderMessageFilter::OnClipboardReadAsciiText(ui::Clipboard::Buffer buffer,
                                                    IPC::Message* reply) {
   std::string result;
   GetClipboard()->ReadAsciiText(buffer, &result);
@@ -814,7 +874,7 @@
   Send(reply);
 }
 
-void RenderMessageFilter::OnClipboardReadHTML(Clipboard::Buffer buffer,
+void RenderMessageFilter::OnClipboardReadHTML(ui::Clipboard::Buffer buffer,
                                               IPC::Message* reply) {
   std::string src_url_str;
   string16 markup;
@@ -826,7 +886,7 @@
 }
 
 void RenderMessageFilter::OnClipboardReadAvailableTypes(
-    Clipboard::Buffer buffer, IPC::Message* reply) {
+    ui::Clipboard::Buffer buffer, IPC::Message* reply) {
   std::vector<string16> types;
   bool contains_filenames = false;
   bool result = ClipboardDispatcher::ReadAvailableTypes(
@@ -837,7 +897,7 @@
 }
 
 void RenderMessageFilter::OnClipboardReadData(
-    Clipboard::Buffer buffer, const string16& type, IPC::Message* reply) {
+    ui::Clipboard::Buffer buffer, const string16& type, IPC::Message* reply) {
   string16 data;
   string16 metadata;
   bool result = ClipboardDispatcher::ReadData(buffer, type, &data, &metadata);
@@ -847,7 +907,7 @@
 }
 
 void RenderMessageFilter::OnClipboardReadFilenames(
-    Clipboard::Buffer buffer, IPC::Message* reply) {
+    ui::Clipboard::Buffer buffer, IPC::Message* reply) {
   std::vector<string16> filenames;
   bool result = ClipboardDispatcher::ReadFilenames(buffer, &filenames);
   ViewHostMsg_ClipboardReadFilenames::WriteReplyParams(
@@ -959,14 +1019,10 @@
                                        double zoom_level,
                                        bool remember,
                                        const GURL& url) {
-  Task* task = NewRunnableMethod(this,
-      &RenderMessageFilter::UpdateHostZoomLevelsOnUIThread, zoom_level,
-      remember, url, render_process_id_, message.routing_id());
-#if defined(OS_MACOSX)
-  cocoa_utils::PostTaskInEventTrackingRunLoopMode(FROM_HERE, task);
-#else
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task);
-#endif
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(this,
+          &RenderMessageFilter::UpdateHostZoomLevelsOnUIThread,
+          zoom_level, remember, url, render_process_id_, message.routing_id()));
 }
 
 void RenderMessageFilter::UpdateHostZoomLevelsOnUIThread(
@@ -1109,10 +1165,10 @@
 }
 
 // static
-Clipboard* RenderMessageFilter::GetClipboard() {
+ui::Clipboard* RenderMessageFilter::GetClipboard() {
   // We have a static instance of the clipboard service for use by all message
   // filters.  This instance lives for the life of the browser processes.
-  static Clipboard* clipboard = new Clipboard;
+  static ui::Clipboard* clipboard = new ui::Clipboard;
 
   return clipboard;
 }
@@ -1277,7 +1333,7 @@
         http_transaction_factory()->GetCache()->GetCurrentBackend();
     if (backend) {
       ClearCacheCompletion* callback =
-          new ClearCacheCompletion(reply_msg, this);
+          new ClearCacheCompletion(this, reply_msg);
       rv = backend->DoomAllEntries(callback);
       if (rv == net::ERR_IO_PENDING) {
         // The callback will send the reply.
@@ -1375,6 +1431,13 @@
   // Generate a signed public key and challenge, then send it back.
   net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string, url);
 
+#if defined(USE_NSS)
+  // Attach a password delegate so we can authenticate.
+  keygen_handler.set_crypto_module_password_delegate(
+      browser::NewCryptoModuleBlockingDialogDelegate(
+          browser::kCryptoModulePasswordKeygen, url.host()));
+#endif  // defined(USE_NSS)
+
   ViewHostMsg_Keygen::WriteReplyParams(
       reply_msg,
       keygen_handler.GenKeyAndSignChallenge());
@@ -1393,19 +1456,6 @@
 }
 #endif
 
-void RenderMessageFilter::OnEstablishGpuChannel() {
-  GpuProcessHost::Get()->EstablishGpuChannel(render_process_id_, this);
-}
-
-void RenderMessageFilter::OnSynchronizeGpu(IPC::Message* reply) {
-  // We handle this message (and the other GPU process messages) here
-  // rather than handing the message to the GpuProcessHost for
-  // dispatch so that we can use the DELAY_REPLY macro to synthesize
-  // the reply message, and also send down a "this" pointer so that
-  // the GPU process host can send the reply later.
-  GpuProcessHost::Get()->Synchronize(reply, this);
-}
-
 void RenderMessageFilter::OnGetExtensionMessageBundle(
     const std::string& extension_id, IPC::Message* reply_msg) {
   ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>(
@@ -1527,12 +1577,10 @@
     context_->cookie_store()->SetCookieWithOptions(url_, cookie_line_,
                                                    options);
   }
-  if (!context_->IsExternal()) {
-    CallRenderViewHostContentSettingsDelegate(
-        render_process_id_, render_view_id_,
-        &RenderViewHostDelegate::ContentSettings::OnCookieChanged,
-        url_, cookie_line_, options, blocked_by_policy);
-  }
+  CallRenderViewHostContentSettingsDelegate(
+      render_process_id_, render_view_id_,
+      &RenderViewHostDelegate::ContentSettings::OnCookieChanged,
+      url_, cookie_line_, options, blocked_by_policy);
   delete this;
 }
 
@@ -1563,17 +1611,15 @@
       cookies = cookie_store()->GetCookies(url_);
     ViewHostMsg_GetCookies::WriteReplyParams(reply_msg_, cookies);
     filter_->Send(reply_msg_);
-    if (!context_->IsExternal()) {
-      net::CookieMonster* cookie_monster =
-          context_->cookie_store()->GetCookieMonster();
-      net::CookieList cookie_list =
-          cookie_monster->GetAllCookiesForURLWithOptions(
-              url_, net::CookieOptions());
-      CallRenderViewHostContentSettingsDelegate(
-          render_process_id_, render_view_id_,
-          &RenderViewHostDelegate::ContentSettings::OnCookiesRead,
-          url_, cookie_list, result != net::OK);
-    }
+    net::CookieMonster* cookie_monster =
+        context_->cookie_store()->GetCookieMonster();
+    net::CookieList cookie_list =
+        cookie_monster->GetAllCookiesForURLWithOptions(
+            url_, net::CookieOptions());
+    CallRenderViewHostContentSettingsDelegate(
+        render_process_id_, render_view_id_,
+        &RenderViewHostDelegate::ContentSettings::OnCookiesRead,
+        url_, cookie_list, result != net::OK);
     delete this;
   } else {
     // Ignore the policy result.  We only waited on the policy result so that
diff --git a/chrome/browser/renderer_host/render_message_filter.h b/chrome/browser/renderer_host/render_message_filter.h
index 98e8402..a0339de 100644
--- a/chrome/browser/renderer_host/render_message_filter.h
+++ b/chrome/browser/renderer_host/render_message_filter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,6 @@
 #include <string>
 #include <vector>
 
-#include "app/clipboard/clipboard.h"
 #include "app/surface/transport_dib.h"
 #include "base/file_path.h"
 #include "base/linked_ptr.h"
@@ -25,16 +24,16 @@
 #include "chrome/browser/net/resolve_proxy_msg_helper.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/common/content_settings.h"
-#include "gfx/native_widget_types.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/gfx/native_widget_types.h"
 
 class ChromeURLRequestContext;
 struct FontDescriptor;
 class HostContentSettingsMap;
 class HostZoomMap;
 class NotificationsPrefsCache;
-class PpapiPluginProcessHost;
 class Profile;
 class RenderWidgetHelper;
 class URLRequestContextGetter;
@@ -84,8 +83,8 @@
   }
   bool off_the_record() { return off_the_record_; }
 
-  // Returns either the extension URLRequestContext or regular URLRequestContext
-  // depending on whether |url| is an extension URL.
+  // Returns either the extension net::URLRequestContext or regular
+  // net::URLRequestContext depending on whether |url| is an extension URL.
   // Only call on the IO thread.
   ChromeURLRequestContext* GetRequestContextForURL(const GURL& url);
 
@@ -101,9 +100,7 @@
   void OnMsgCreateWidget(int opener_id,
                          WebKit::WebPopupType popup_type,
                          int* route_id);
-  void OnMsgCreateFullscreenWidget(int opener_id,
-                                   WebKit::WebPopupType popup_type,
-                                   int* route_id);
+  void OnMsgCreateFullscreenWidget(int opener_id, int* route_id);
   void OnSetCookie(const IPC::Message& message,
                    const GURL& url,
                    const GURL& first_party_for_cookies,
@@ -143,11 +140,13 @@
 #endif
   void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
   void OnGetPluginsOnFileThread(bool refresh, IPC::Message* reply_msg);
-  void OnGetPluginInfo(const GURL& url,
+  void OnGetPluginInfo(int routing_id,
+                       const GURL& url,
                        const GURL& policy_url,
                        const std::string& mime_type,
                        IPC::Message* reply_msg);
-  void OnGetPluginInfoOnFileThread(const GURL& url,
+  void OnGetPluginInfoOnFileThread(int render_view_id,
+                                   const GURL& url,
                                    const GURL& policy_url,
                                    const std::string& mime_type,
                                    IPC::Message* reply_msg);
@@ -156,7 +155,8 @@
                        const std::string& actual_mime_type,
                        const GURL& policy_url,
                        IPC::Message* reply_msg);
-  void OnOpenChannelToPlugin(const GURL& url,
+  void OnOpenChannelToPlugin(int routing_id,
+                             const GURL& url,
                              const std::string& mime_type,
                              IPC::Message* reply_msg);
   void OnOpenChannelToPepperPlugin(const FilePath& path,
@@ -164,6 +164,7 @@
   void OnLaunchNaCl(const std::wstring& url,
                     int channel_descriptor,
                     IPC::Message* reply_msg);
+  void OnGenerateRoutingID(int* route_id);
   void OnDownloadUrl(const IPC::Message& message,
                      const GURL& url,
                      const GURL& referrer);
@@ -182,24 +183,26 @@
 #endif
   void OnReceiveContextMenuMsg(const IPC::Message& msg);
   // Clipboard messages
-  void OnClipboardWriteObjectsAsync(const Clipboard::ObjectMap& objects);
-  void OnClipboardWriteObjectsSync(const Clipboard::ObjectMap& objects,
+  void OnClipboardWriteObjectsAsync(const ui::Clipboard::ObjectMap& objects);
+  void OnClipboardWriteObjectsSync(const ui::Clipboard::ObjectMap& objects,
                                    base::SharedMemoryHandle bitmap_handle);
 
-  void OnClipboardIsFormatAvailable(Clipboard::FormatType format,
-                                    Clipboard::Buffer buffer,
+  void OnClipboardIsFormatAvailable(ui::Clipboard::FormatType format,
+                                    ui::Clipboard::Buffer buffer,
                                     IPC::Message* reply);
-  void OnClipboardReadText(Clipboard::Buffer buffer, IPC::Message* reply);
-  void OnClipboardReadAsciiText(Clipboard::Buffer buffer, IPC::Message* reply);
-  void OnClipboardReadHTML(Clipboard::Buffer buffer, IPC::Message* reply);
+  void OnClipboardReadText(ui::Clipboard::Buffer buffer, IPC::Message* reply);
+  void OnClipboardReadAsciiText(ui::Clipboard::Buffer buffer,
+                                IPC::Message* reply);
+  void OnClipboardReadHTML(ui::Clipboard::Buffer buffer, IPC::Message* reply);
 #if defined(OS_MACOSX)
   void OnClipboardFindPboardWriteString(const string16& text);
 #endif
-  void OnClipboardReadAvailableTypes(Clipboard::Buffer buffer,
+  void OnClipboardReadAvailableTypes(ui::Clipboard::Buffer buffer,
                                      IPC::Message* reply);
-  void OnClipboardReadData(Clipboard::Buffer buffer, const string16& type,
+  void OnClipboardReadData(ui::Clipboard::Buffer buffer, const string16& type,
                            IPC::Message* reply);
-  void OnClipboardReadFilenames(Clipboard::Buffer buffer, IPC::Message* reply);
+  void OnClipboardReadFilenames(ui::Clipboard::Buffer buffer,
+                                IPC::Message* reply);
 
   void OnCheckNotificationPermission(const GURL& source_url,
                                      int* permission_level);
@@ -223,7 +226,7 @@
   // Used to ask the browser allocate a temporary file for the renderer
   // to fill in resulting PDF in renderer.
   void OnAllocateTempFileForPrinting(IPC::Message* reply_msg);
-  void OnTempFileForPrintingWritten(int fd_in_browser);
+  void OnTempFileForPrintingWritten(int sequence_number);
 #endif
 
 #if defined(OS_POSIX)
@@ -324,9 +327,6 @@
       const std::string& extension_id,
       const std::string& default_locale,
       IPC::Message* reply_msg);
-  void OnEstablishGpuChannel();
-  void OnSynchronizeGpu(IPC::Message* reply);
-
   void OnAsyncOpenFile(const IPC::Message& msg,
                        const FilePath& path,
                        int flags,
@@ -340,20 +340,23 @@
   void DoOnGetScreenInfo(gfx::NativeViewId view, IPC::Message* reply_msg);
   void DoOnGetWindowRect(gfx::NativeViewId view, IPC::Message* reply_msg);
   void DoOnGetRootWindowRect(gfx::NativeViewId view, IPC::Message* reply_msg);
-  void DoOnClipboardIsFormatAvailable(Clipboard::FormatType format,
-                                      Clipboard::Buffer buffer,
+  void DoOnClipboardIsFormatAvailable(ui::Clipboard::FormatType format,
+                                      ui::Clipboard::Buffer buffer,
                                       IPC::Message* reply_msg);
-  void DoOnClipboardReadText(Clipboard::Buffer buffer, IPC::Message* reply_msg);
-  void DoOnClipboardReadAsciiText(Clipboard::Buffer buffer,
-                                  IPC::Message* reply_msg);
-  void DoOnClipboardReadHTML(Clipboard::Buffer buffer, IPC::Message* reply_msg);
-  void DoOnClipboardReadAvailableTypes(Clipboard::Buffer buffer,
-                                       IPC::Message* reply_msg);
-  void DoOnClipboardReadData(Clipboard::Buffer buffer, const string16& type,
+  void DoOnClipboardReadText(ui::Clipboard::Buffer buffer,
                              IPC::Message* reply_msg);
-  void DoOnClipboardReadFilenames(Clipboard::Buffer buffer,
+  void DoOnClipboardReadAsciiText(ui::Clipboard::Buffer buffer,
+                                  IPC::Message* reply_msg);
+  void DoOnClipboardReadHTML(ui::Clipboard::Buffer buffer,
+                             IPC::Message* reply_msg);
+  void DoOnClipboardReadAvailableTypes(ui::Clipboard::Buffer buffer,
+                                       IPC::Message* reply_msg);
+  void DoOnClipboardReadData(ui::Clipboard::Buffer buffer, const string16& type,
+                             IPC::Message* reply_msg);
+  void DoOnClipboardReadFilenames(ui::Clipboard::Buffer buffer,
                                   IPC::Message* reply_msg);
   void DoOnAllocateTempFileForPrinting(IPC::Message* reply_msg);
+  void DoOnTempFileForPrintingWritten(int sequence_number);
 #endif
 
   bool CheckBenchmarkingEnabled() const;
@@ -363,7 +366,7 @@
   // IO thread instead of forwarding (possibly synchronous) messages to the UI
   // thread. This instance of the clipboard should be accessed only on the IO
   // thread.
-  static Clipboard* GetClipboard();
+  static ui::Clipboard* GetClipboard();
 
   // Cached resource request dispatcher host and plugin service, guaranteed to
   // be non-null if Init succeeds. We do not own the objects, they are managed
@@ -406,9 +409,6 @@
 
   base::TimeTicks last_plugin_refresh_time_;  // Initialized to 0.
 
-  // A list of all Ppapi plugin processes for this renderer.
-  std::vector<linked_ptr<PpapiPluginProcessHost> > ppapi_plugin_hosts_;
-
   scoped_refptr<WebKitContext> webkit_context_;
 
   int render_process_id_;
diff --git a/chrome/browser/renderer_host/render_message_filter_gtk.cc b/chrome/browser/renderer_host/render_message_filter_gtk.cc
index 4088c8a..8e66dfb 100644
--- a/chrome/browser/renderer_host/render_message_filter_gtk.cc
+++ b/chrome/browser/renderer_host/render_message_filter_gtk.cc
@@ -7,8 +7,6 @@
 #include <fcntl.h>
 #include <map>
 
-#include "app/clipboard/clipboard.h"
-#include "app/x11_util.h"
 #include "base/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/path_service.h"
@@ -20,24 +18,27 @@
 #endif
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/render_messages.h"
-#include "gfx/gtk_native_view_id_manager.h"
 #include "grit/generated_resources.h"
-
-#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/x11/WebScreenInfoFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/x11/WebScreenInfoFactory.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_native_view_id_manager.h"
 
 using WebKit::WebScreenInfo;
 using WebKit::WebScreenInfoFactory;
 
 namespace {
 
-typedef std::map<int, FilePath> FdMap;
+typedef std::map<int, FilePath> SequenceToPathMap;
 
-struct PrintingFileDescriptorMap {
-  FdMap map;
+struct PrintingSequencePathMap {
+  SequenceToPathMap map;
+  int sequence;
 };
 
-static base::LazyInstance<PrintingFileDescriptorMap>
+// No locking, only access on the FILE thread.
+static base::LazyInstance<PrintingSequencePathMap>
     g_printing_file_descriptor_map(base::LINKER_INITIALIZED);
 
 }  // namespace
@@ -45,30 +46,30 @@
 // We get null window_ids passed into the two functions below; please see
 // http://crbug.com/9060 for more details.
 
-// Called on the BACKGROUND_X11 thread.
 void RenderMessageFilter::DoOnGetScreenInfo(gfx::NativeViewId view,
                                             IPC::Message* reply_msg) {
-  Display* display = x11_util::GetSecondaryDisplay();
-  int screen = x11_util::GetDefaultScreen(display);
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11));
+  Display* display = ui::GetSecondaryDisplay();
+  int screen = ui::GetDefaultScreen(display);
   WebScreenInfo results = WebScreenInfoFactory::screenInfo(display, screen);
   ViewHostMsg_GetScreenInfo::WriteReplyParams(reply_msg, results);
   Send(reply_msg);
 }
 
-// Called on the BACKGROUND_X11 thread.
 void RenderMessageFilter::DoOnGetWindowRect(gfx::NativeViewId view,
                                             IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11));
   // This is called to get the x, y offset (in screen coordinates) of the given
   // view and its width and height.
   gfx::Rect rect;
   XID window;
 
-  AutoLock lock(GtkNativeViewManager::GetInstance()->unrealize_lock());
+  base::AutoLock lock(GtkNativeViewManager::GetInstance()->unrealize_lock());
   if (GtkNativeViewManager::GetInstance()->GetXIDForId(&window, view)) {
     if (window) {
       int x, y;
       unsigned width, height;
-      if (x11_util::GetWindowGeometry(&x, &y, &width, &height, window))
+      if (ui::GetWindowGeometry(&x, &y, &width, &height, window))
         rect = gfx::Rect(x, y, width, height);
     }
   }
@@ -83,7 +84,7 @@
   bool parent_is_root;
   XID parent_window;
 
-  if (!x11_util::GetWindowParent(&parent_window, &parent_is_root, window))
+  if (!ui::GetWindowParent(&parent_window, &parent_is_root, window))
     return 0;
   if (parent_is_root)
     return window;
@@ -91,22 +92,22 @@
   return GetTopLevelWindow(parent_window);
 }
 
-// Called on the BACKGROUND_X11 thread.
 void RenderMessageFilter::DoOnGetRootWindowRect(gfx::NativeViewId view,
                                                 IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11));
   // This is called to get the screen coordinates and size of the browser
   // window itself.
   gfx::Rect rect;
   XID window;
 
-  AutoLock lock(GtkNativeViewManager::GetInstance()->unrealize_lock());
+  base::AutoLock lock(GtkNativeViewManager::GetInstance()->unrealize_lock());
   if (GtkNativeViewManager::GetInstance()->GetXIDForId(&window, view)) {
     if (window) {
       const XID toplevel = GetTopLevelWindow(window);
       if (toplevel) {
         int x, y;
         unsigned width, height;
-        if (x11_util::GetWindowGeometry(&x, &y, &width, &height, toplevel))
+        if (ui::GetWindowGeometry(&x, &y, &width, &height, toplevel))
           rect = gfx::Rect(x, y, width, height);
       }
     }
@@ -116,19 +117,19 @@
   Send(reply_msg);
 }
 
-// Called on the UI thread.
 void RenderMessageFilter::DoOnClipboardIsFormatAvailable(
-    Clipboard::FormatType format, Clipboard::Buffer buffer,
+    ui::Clipboard::FormatType format, ui::Clipboard::Buffer buffer,
     IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   const bool result = GetClipboard()->IsFormatAvailable(format, buffer);
 
   ViewHostMsg_ClipboardIsFormatAvailable::WriteReplyParams(reply_msg, result);
   Send(reply_msg);
 }
 
-// Called on the UI thread.
-void RenderMessageFilter::DoOnClipboardReadText(Clipboard::Buffer buffer,
+void RenderMessageFilter::DoOnClipboardReadText(ui::Clipboard::Buffer buffer,
                                                 IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   string16 result;
   GetClipboard()->ReadText(buffer, &result);
 
@@ -136,9 +137,9 @@
   Send(reply_msg);
 }
 
-// Called on the UI thread.
 void RenderMessageFilter::DoOnClipboardReadAsciiText(
-    Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+    ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   std::string result;
   GetClipboard()->ReadAsciiText(buffer, &result);
 
@@ -146,9 +147,9 @@
   Send(reply_msg);
 }
 
-// Called on the UI thread.
-void RenderMessageFilter::DoOnClipboardReadHTML(Clipboard::Buffer buffer,
+void RenderMessageFilter::DoOnClipboardReadHTML(ui::Clipboard::Buffer buffer,
                                                 IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   std::string src_url_str;
   string16 markup;
   GetClipboard()->ReadHTML(buffer, &markup, &src_url_str);
@@ -158,32 +159,28 @@
   Send(reply_msg);
 }
 
-// Called on the UI thread.
 void RenderMessageFilter::DoOnClipboardReadAvailableTypes(
-    Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+    ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   Send(reply_msg);
 }
 
-// Called on the UI thread.
-void RenderMessageFilter::DoOnClipboardReadData(Clipboard::Buffer buffer,
+void RenderMessageFilter::DoOnClipboardReadData(ui::Clipboard::Buffer buffer,
                                                 const string16& type,
                                                 IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   Send(reply_msg);
 }
-// Called on the UI thread.
 void RenderMessageFilter::DoOnClipboardReadFilenames(
-    Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+    ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   Send(reply_msg);
 }
 
-// Called on the FILE thread.
 void RenderMessageFilter::DoOnAllocateTempFileForPrinting(
     IPC::Message* reply_msg) {
-  base::FileDescriptor temp_file_fd;
-  int fd_in_browser;
-  temp_file_fd.fd = fd_in_browser = -1;
-  temp_file_fd.auto_close = false;
-
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  base::FileDescriptor temp_file_fd(-1, false);
   bool allow_print =
 #if defined(TOOLKIT_GTK)
     !PrintDialogGtk::DialogShowing();
@@ -191,142 +188,37 @@
     true;
 #endif
   FilePath path;
+  SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map;
+  const int sequence_number = g_printing_file_descriptor_map.Get().sequence++;
+
   if (allow_print &&
       file_util::CreateTemporaryFile(&path)) {
     int fd = open(path.value().c_str(), O_WRONLY);
     if (fd >= 0) {
-      FdMap* map = &g_printing_file_descriptor_map.Get().map;
-      FdMap::iterator it = map->find(fd);
+      SequenceToPathMap::iterator it = map->find(sequence_number);
       if (it != map->end()) {
-        NOTREACHED() << "The file descriptor is in use. fd=" << fd;
+        NOTREACHED() << "Sequence number already in use. seq=" <<
+            sequence_number;
       } else {
-        (*map)[fd] = path;
-        temp_file_fd.fd = fd_in_browser = fd;
+        (*map)[sequence_number] = path;
+        temp_file_fd.fd = fd;
         temp_file_fd.auto_close = true;
       }
     }
   }
 
   ViewHostMsg_AllocateTempFileForPrinting::WriteReplyParams(
-      reply_msg, temp_file_fd, fd_in_browser);
+      reply_msg, temp_file_fd, sequence_number);
   Send(reply_msg);
 }
 
-// Called on the IO thread.
-void RenderMessageFilter::OnGetScreenInfo(gfx::NativeViewId view,
-                                          IPC::Message* reply_msg) {
-   BrowserThread::PostTask(
-      BrowserThread::BACKGROUND_X11, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnGetScreenInfo, view, reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnGetWindowRect(gfx::NativeViewId view,
-                                          IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::BACKGROUND_X11, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnGetWindowRect, view, reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnGetRootWindowRect(gfx::NativeViewId view,
-                                              IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::BACKGROUND_X11, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnGetRootWindowRect, view, reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardIsFormatAvailable(
-    Clipboard::FormatType format, Clipboard::Buffer buffer,
-    IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardIsFormatAvailable, format,
-          buffer, reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardReadText(Clipboard::Buffer buffer,
-                                              IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardReadText, buffer,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardReadAsciiText(Clipboard::Buffer buffer,
-                                                   IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardReadAsciiText, buffer,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardReadHTML(Clipboard::Buffer buffer,
-                                              IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardReadHTML, buffer,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardReadAvailableTypes(
-    Clipboard::Buffer buffer, IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardReadAvailableTypes, buffer,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardReadData(
-    Clipboard::Buffer buffer, const string16& type, IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardReadData, buffer, type,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnClipboardReadFilenames(
-    Clipboard::Buffer buffer, IPC::Message* reply_msg) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnClipboardReadFilenames, buffer,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnAllocateTempFileForPrinting(
-    IPC::Message* reply_msg) {
-   BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      NewRunnableMethod(
-          this, &RenderMessageFilter::DoOnAllocateTempFileForPrinting,
-          reply_msg));
-}
-
-// Called on the IO thread.
-void RenderMessageFilter::OnTempFileForPrintingWritten(int fd_in_browser) {
-  FdMap* map = &g_printing_file_descriptor_map.Get().map;
-  FdMap::iterator it = map->find(fd_in_browser);
+void RenderMessageFilter::DoOnTempFileForPrintingWritten(int sequence_number) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map;
+  SequenceToPathMap::iterator it = map->find(sequence_number);
   if (it == map->end()) {
-    NOTREACHED() << "Got a file descriptor that we didn't pass to the "
-                    "renderer: " << fd_in_browser;
+    NOTREACHED() << "Got a sequence that we didn't pass to the "
+                    "renderer: " << sequence_number;
     return;
   }
 
@@ -334,7 +226,7 @@
   PrintDialogGtk::CreatePrintDialogForPdf(it->second);
 #else
   if (cloud_print_enabled_)
-    PrintDialogCloud::CreatePrintDialogForPdf(it->second);
+    PrintDialogCloud::CreatePrintDialogForPdf(it->second, string16(), true);
   else
     NOTIMPLEMENTED();
 #endif
@@ -342,3 +234,121 @@
   // Erase the entry in the map.
   map->erase(it);
 }
+
+void RenderMessageFilter::OnGetScreenInfo(gfx::NativeViewId view,
+                                          IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+     BrowserThread::BACKGROUND_X11, FROM_HERE,
+     NewRunnableMethod(
+         this, &RenderMessageFilter::DoOnGetScreenInfo, view, reply_msg));
+}
+
+void RenderMessageFilter::OnGetWindowRect(gfx::NativeViewId view,
+                                          IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::BACKGROUND_X11, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnGetWindowRect, view, reply_msg));
+}
+
+void RenderMessageFilter::OnGetRootWindowRect(gfx::NativeViewId view,
+                                              IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::BACKGROUND_X11, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnGetRootWindowRect, view, reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardIsFormatAvailable(
+    ui::Clipboard::FormatType format, ui::Clipboard::Buffer buffer,
+    IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardIsFormatAvailable, format,
+          buffer, reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardReadText(ui::Clipboard::Buffer buffer,
+                                              IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardReadText, buffer,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardReadAsciiText(ui::Clipboard::Buffer buffer,
+                                                   IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardReadAsciiText, buffer,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardReadHTML(ui::Clipboard::Buffer buffer,
+                                              IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardReadHTML, buffer,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardReadAvailableTypes(
+    ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardReadAvailableTypes, buffer,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardReadData(ui::Clipboard::Buffer buffer,
+                                              const string16& type,
+                                              IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardReadData, buffer, type,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnClipboardReadFilenames(
+    ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnClipboardReadFilenames, buffer,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnAllocateTempFileForPrinting(
+    IPC::Message* reply_msg) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnAllocateTempFileForPrinting,
+          reply_msg));
+}
+
+void RenderMessageFilter::OnTempFileForPrintingWritten(int sequence_number) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      NewRunnableMethod(
+          this, &RenderMessageFilter::DoOnTempFileForPrintingWritten,
+          sequence_number));
+}
diff --git a/chrome/browser/renderer_host/render_message_filter_win.cc b/chrome/browser/renderer_host/render_message_filter_win.cc
index 6bcd0c6..ab4dafb 100644
--- a/chrome/browser/renderer_host/render_message_filter_win.cc
+++ b/chrome/browser/renderer_host/render_message_filter_win.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/renderer_host/render_message_filter.h"
 #include "chrome/common/render_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/win/WebScreenInfoFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h"
 
 using WebKit::WebScreenInfo;
 using WebKit::WebScreenInfoFactory;
diff --git a/chrome/browser/renderer_host/render_process_host.cc b/chrome/browser/renderer_host/render_process_host.cc
index a2c328c..e319178 100644
--- a/chrome/browser/renderer_host/render_process_host.cc
+++ b/chrome/browser/renderer_host/render_process_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -65,8 +65,8 @@
     return false;
 
   RenderProcessHost::Type host_type = RenderProcessHost::TYPE_NORMAL;
-  if (ChildProcessSecurityPolicy::GetInstance()->HasDOMUIBindings(host->id()))
-    host_type = RenderProcessHost::TYPE_DOMUI;
+  if (ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(host->id()))
+    host_type = RenderProcessHost::TYPE_WEBUI;
   if (ChildProcessSecurityPolicy::GetInstance()->
         HasExtensionBindings(host->id()))
     host_type = RenderProcessHost::TYPE_EXTENSION;
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index 1e8523b..fa58495 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -43,7 +43,7 @@
   // in which case we call it an "extension" renderer.
   enum Type {
     TYPE_NORMAL,     // Normal renderer, no extra privileges.
-    TYPE_DOMUI,      // Renderer with DOMUI privileges, like New Tab.
+    TYPE_WEBUI,      // Renderer with WebUI privileges, like New Tab.
     TYPE_EXTENSION,  // Renderer with extension privileges.
   };
 
diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.cc b/chrome/browser/renderer_host/render_sandbox_host_linux.cc
index 8f265b1..7408031 100644
--- a/chrome/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/chrome/browser/renderer_host/render_sandbox_host_linux.cc
@@ -31,7 +31,7 @@
 #include "chrome/common/unix_domain_socket_posix.h"
 #include "skia/ext/SkFontHost_fontconfig_direct.h"
 #include "third_party/npapi/bindings/npapi_extensions.h"
-#include "third_party/WebKit/WebKit/chromium/public/gtk/WebFontInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/gtk/WebFontInfo.h"
 
 using WebKit::WebCString;
 using WebKit::WebFontInfo;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index ccbd57a..be4bd2b 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,9 +15,6 @@
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/child_process_security_policy.h"
 #include "chrome/browser/cross_site_request_manager.h"
 #include "chrome/browser/debugger/devtools_manager.h"
@@ -26,10 +23,6 @@
 #include "chrome/browser/in_process_webkit/session_storage_namespace.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/net/predictor_api.h"
-#include "chrome/browser/notifications/desktop_notification_service.h"
-#include "chrome/browser/printing/printer_query.h"
-#include "chrome/browser/printing/print_job_manager.h"
-#include "chrome/browser/printing/print_preview_tab_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
@@ -51,24 +44,16 @@
 #include "chrome/common/translate_errors.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/native_widget_types.h"
 #include "net/base/net_util.h"
 #include "printing/native_metafile.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/context_menu.h"
-#include "webkit/glue/form_data.h"
-#include "webkit/glue/form_field.h"
-#include "webkit/glue/password_form_dom_manager.h"
 #include "webkit/glue/webaccessibility.h"
 #include "webkit/glue/webdropdata.h"
 
 using base::TimeDelta;
-using webkit_glue::FormData;
-using webkit_glue::FormField;
-using webkit_glue::PasswordForm;
-using webkit_glue::PasswordFormDomManager;
-using webkit_glue::PasswordFormFillData;
 using WebKit::WebConsoleMessage;
 using WebKit::WebDragOperation;
 using WebKit::WebDragOperationNone;
@@ -121,7 +106,6 @@
       sudden_termination_allowed_(false),
       session_storage_namespace_(session_storage),
       is_extension_process_(false),
-      autofill_query_id_(0),
       save_accessibility_tree_for_testing_(false),
       render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
   if (!session_storage_namespace_) {
@@ -153,8 +137,8 @@
   DCHECK(process()->HasConnection());
   DCHECK(process()->profile());
 
-  if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
-    ChildProcessSecurityPolicy::GetInstance()->GrantDOMUIBindings(
+  if (BindingsPolicy::is_web_ui_enabled(enabled_bindings_)) {
+    ChildProcessSecurityPolicy::GetInstance()->GrantWebUIBindings(
         process()->id());
   }
 
@@ -169,21 +153,11 @@
 
   renderer_initialized_ = true;
 
-  // Force local storage to be enabled for extensions. This is so that we can
-  // enable extensions by default before databases, if necessary.
-  // TODO(aa): This should be removed when local storage and databases are
-  // enabled by default (bugs 4359 and 4360).
-  WebPreferences webkit_prefs = delegate_->GetWebkitPrefs();
-  if (delegate_->GetURL().SchemeIs(chrome::kExtensionScheme)) {
-    webkit_prefs.local_storage_enabled = true;
-    webkit_prefs.databases_enabled = true;
-  }
-
   ViewMsg_New_Params params;
   params.parent_window = GetNativeViewId();
   params.renderer_preferences =
       delegate_->GetRendererPrefs(process()->profile());
-  params.web_preferences = webkit_prefs;
+  params.web_preferences = delegate_->GetWebkitPrefs();
   params.view_id = routing_id();
   params.session_storage_namespace_id = session_storage_namespace_->id();
   params.frame_name = frame_name;
@@ -243,7 +217,7 @@
     // browser. But we want to keep the throbber in sync with what's happening
     // in the UI. For example, we want to start throbbing immediately when the
     // user naivgates even if the renderer is delayed. There is also an issue
-    // with the throbber starting because the DOMUI (which controls whether the
+    // with the throbber starting because the WebUI (which controls whether the
     // favicon is displayed) happens synchronously. If the start loading
     // messages was asynchronous, then the default favicon would flash in.
     //
@@ -361,6 +335,22 @@
   return pending_request_id_;
 }
 
+RenderViewHost::CommandState RenderViewHost::GetStateForCommand(
+    RenderViewCommand command) const {
+  if (command != RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK)
+    LOG(DFATAL) << "Unknown command " << command;
+
+  std::map<RenderViewCommand, CommandState>::const_iterator it =
+      command_states_.find(command);
+  if (it == command_states_.end()) {
+    CommandState state;
+    state.is_enabled = false;
+    state.checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED;
+    return state;
+  }
+  return it->second;
+}
+
 void RenderViewHost::Stop() {
   Send(new ViewMsg_Stop(routing_id()));
 }
@@ -440,11 +430,6 @@
   Send(new ViewMsg_SetAltErrorPageURL(routing_id(), url));
 }
 
-void RenderViewHost::FillPasswordForm(
-    const webkit_glue::PasswordFormFillData& form_data) {
-  Send(new ViewMsg_FillPasswordForm(routing_id(), form_data));
-}
-
 void RenderViewHost::DragTargetDragEnter(
     const WebDropData& drop_data,
     const gfx::Point& client_pt,
@@ -486,10 +471,9 @@
 }
 
 void RenderViewHost::ExecuteJavascriptInWebFrame(
-    const std::wstring& frame_xpath,
-    const std::wstring& jscript) {
-  Send(new ViewMsg_ScriptEvalRequest(routing_id(), WideToUTF16(frame_xpath),
-                                     WideToUTF16(jscript),
+    const string16& frame_xpath,
+    const string16& jscript) {
+  Send(new ViewMsg_ScriptEvalRequest(routing_id(), frame_xpath, jscript,
                                      0, false));
 }
 
@@ -647,10 +631,10 @@
   enabled_bindings_ |= bindings_flags;
 }
 
-void RenderViewHost::SetDOMUIProperty(const std::string& name,
+void RenderViewHost::SetWebUIProperty(const std::string& name,
                                       const std::string& value) {
-  DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
-  Send(new ViewMsg_SetDOMUIProperty(routing_id(), name, value));
+  DCHECK(BindingsPolicy::is_web_ui_enabled(enabled_bindings_));
+  Send(new ViewMsg_SetWebUIProperty(routing_id(), name, value));
 }
 
 void RenderViewHost::GotFocus() {
@@ -772,41 +756,28 @@
                         OnMsgDocumentAvailableInMainFrame)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
                         OnMsgDocumentOnLoadCompletedInMainFrame)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnMsgFindReply)
     IPC_MESSAGE_HANDLER(ViewMsg_ExecuteCodeFinished,
                         OnExecuteCodeFinished)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFavIconURL, OnMsgUpdateFavIconURL)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidDownloadFavIcon, OnMsgDidDownloadFavIcon)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnMsgContextMenu)
     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnMsgOpenURL)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
                         OnMsgDidContentsPreferredSizeChange)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
                         OnMsgDomOperationResponse)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DOMUISend, OnMsgDOMUISend)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnMsgWebUISend)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardMessageToExternalHost,
                         OnMsgForwardMessageToExternalHost)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnMsgGoToEntryAtOffset)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnMsgSetTooltipText)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnMsgRunFileChooser)
     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage,
                                     OnMsgRunJavaScriptMessage)
     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm,
                                     OnMsgRunBeforeUnloadConfirm)
     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ShowModalHTMLDialog,
                                     OnMsgShowModalHTMLDialog)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_FormsSeen, OnMsgFormsSeen)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PasswordFormsFound, OnMsgPasswordFormsFound)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PasswordFormsVisible,
-                        OnMsgPasswordFormsVisible)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_FormSubmitted, OnMsgFormSubmitted)
     IPC_MESSAGE_HANDLER(ViewHostMsg_StartDragging, OnMsgStartDragging)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateDragCursor, OnUpdateDragCursor)
     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
     IPC_MESSAGE_HANDLER(ViewHostMsg_PageHasOSDD, OnMsgPageHasOSDD)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetPrintedPagesCount,
-                        OnDidGetPrintedPagesCount)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidPrintPage, DidPrintPage)
     IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToDevToolsAgent,
                         OnForwardToDevToolsAgent)
@@ -822,39 +793,9 @@
                         OnRequestUndockDevToolsWindow)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DevToolsRuntimePropertyChanged,
                         OnDevToolsRuntimePropertyChanged)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_MissingPluginStatus, OnMissingPluginStatus)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_BlockedOutdatedPlugin,
-                        OnBlockedOutdatedPlugin)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SendCurrentPageAllSavableResourceLinks,
-                        OnReceivedSavableResourceLinksForCurrentPage)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData,
-                        OnReceivedSerializedHtmlData)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetApplicationInfo,
-                        OnDidGetApplicationInfo)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_InstallApplication,
-                        OnInstallApplication)
     IPC_MESSAGE_FORWARD(ViewHostMsg_JSOutOfMemory, delegate_,
                         RenderViewHostDelegate::OnJSOutOfMemory)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnMsgShouldCloseACK)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_QueryFormFieldAutoFill,
-                        OnQueryFormFieldAutoFill)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidShowAutoFillSuggestions,
-                        OnDidShowAutoFillSuggestions)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_RemoveAutocompleteEntry,
-                        OnRemoveAutocompleteEntry)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowAutoFillDialog,
-                        OnShowAutoFillDialog)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_FillAutoFillFormData,
-                        OnFillAutoFillFormData)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidFillAutoFillFormData,
-                        OnDidFillAutoFillFormData)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDesktopNotification,
-                        OnShowDesktopNotification)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_CancelDesktopNotification,
-                        OnCancelDesktopNotification)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_RequestNotificationPermission,
-                        OnRequestNotificationPermission)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRequest, OnExtensionRequest)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnMsgSelectionChanged)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage,
@@ -862,26 +803,19 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_AccessibilityNotifications,
                         OnAccessibilityNotifications)
     IPC_MESSAGE_HANDLER(ViewHostMsg_OnCSSInserted, OnCSSInserted)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PageTranslated, OnPageTranslated)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ContentBlocked, OnContentBlocked)
     IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
     IPC_MESSAGE_HANDLER(ViewHostMsg_WebDatabaseAccessed, OnWebDatabaseAccessed)
     IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnMsgFocusedNodeChanged)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SetSuggestions, OnSetSuggestions)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_InstantSupportDetermined,
-                        OnInstantSupportDetermined)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DetectedPhishingSite,
                         OnDetectedPhishingSite)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptEvalResponse, OnScriptEvalResponse)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions,
-                        OnUpdateContentRestrictions)
 #if defined(OS_MACOSX)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnMsgShowPopup)
 #endif
-    IPC_MESSAGE_HANDLER(ViewHostMsg_PagesReadyForPreview,
-                        OnPagesReadyForPreview)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_CommandStateChanged,
+                        OnCommandStateChanged)
     // Have the super handle all other messages.
     IPC_MESSAGE_UNHANDLED(handled = RenderWidgetHost::OnMessageReceived(msg))
   IPC_END_MESSAGE_MAP_EX()
@@ -916,13 +850,12 @@
 
 void RenderViewHost::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
   if (!view)
     return;
 
-  view->CreateNewWindow(route_id, window_container_type, frame_name);
+  view->CreateNewWindow(route_id, params);
 }
 
 void RenderViewHost::CreateNewWidget(int route_id,
@@ -932,11 +865,10 @@
     view->CreateNewWidget(route_id, popup_type);
 }
 
-void RenderViewHost::CreateNewFullscreenWidget(
-    int route_id, WebKit::WebPopupType popup_type) {
+void RenderViewHost::CreateNewFullscreenWidget(int route_id) {
   RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
   if (view)
-    view->CreateNewFullscreenWidget(route_id, popup_type);
+    view->CreateNewFullscreenWidget(route_id);
 }
 
 void RenderViewHost::OnMsgShowView(int route_id,
@@ -1140,28 +1072,6 @@
   delegate_->DocumentOnLoadCompletedInMainFrame(this, page_id);
 }
 
-void RenderViewHost::OnMsgFindReply(int request_id,
-                                    int number_of_matches,
-                                    const gfx::Rect& selection_rect,
-                                    int active_match_ordinal,
-                                    bool final_update) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate) {
-    integration_delegate->OnFindReply(request_id, number_of_matches,
-                                      selection_rect,
-                                      active_match_ordinal, final_update);
-  }
-
-  // Send a notification to the renderer that we are ready to receive more
-  // results from the scoping effort of the Find operation. The FindInPage
-  // scoping is asynchronous and periodically sends results back up to the
-  // browser using IPC. In an effort to not spam the browser we have the
-  // browser send an ACK for each FindReply message and have the renderer
-  // queue up the latest status message while waiting for this ACK.
-  Send(new ViewMsg_FindReplyACK(routing_id()));
-}
-
 void RenderViewHost::OnExecuteCodeFinished(int request_id, bool success) {
   std::pair<int, bool> result_details(request_id, success);
   NotificationService::current()->Notify(
@@ -1170,24 +1080,6 @@
       Details<std::pair<int, bool> >(&result_details));
 }
 
-void RenderViewHost::OnMsgUpdateFavIconURL(int32 page_id,
-                                           const GURL& icon_url) {
-  RenderViewHostDelegate::FavIcon* favicon_delegate =
-      delegate_->GetFavIconDelegate();
-  if (favicon_delegate)
-    favicon_delegate->UpdateFavIconURL(this, page_id, icon_url);
-}
-
-void RenderViewHost::OnMsgDidDownloadFavIcon(int id,
-                                             const GURL& image_url,
-                                             bool errored,
-                                             const SkBitmap& image) {
-  RenderViewHostDelegate::FavIcon* favicon_delegate =
-      delegate_->GetFavIconDelegate();
-  if (favicon_delegate)
-    favicon_delegate->DidDownloadFavIcon(this, id, image_url, errored, image);
-}
-
 void RenderViewHost::OnMsgContextMenu(const ContextMenuParams& params) {
   RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
   if (!view)
@@ -1239,12 +1131,12 @@
       Details<DomOperationNotificationDetails>(&details));
 }
 
-void RenderViewHost::OnMsgDOMUISend(
+void RenderViewHost::OnMsgWebUISend(
     const GURL& source_url, const std::string& message,
     const std::string& content) {
   if (!ChildProcessSecurityPolicy::GetInstance()->
-          HasDOMUIBindings(process()->id())) {
-    NOTREACHED() << "Blocked unauthorized use of DOMUIBindings.";
+          HasWebUIBindings(process()->id())) {
+    NOTREACHED() << "Blocked unauthorized use of WebUIBindings.";
     return;
   }
 
@@ -1254,7 +1146,7 @@
     if (!value.get() || !value->IsType(Value::TYPE_LIST)) {
       // The page sent us something that we didn't understand.
       // This probably indicates a programming error.
-      NOTREACHED() << "Invalid JSON argument in OnMsgDOMUISend.";
+      NOTREACHED() << "Invalid JSON argument in OnMsgWebUISend.";
       return;
     }
   }
@@ -1264,13 +1156,13 @@
   if (value.get())
     params.arguments.Swap(static_cast<ListValue*>(value.get()));
   params.source_url = source_url;
-  // DOMUI doesn't use these values yet.
-  // TODO(aa): When DOMUI is ported to ExtensionFunctionDispatcher, send real
+  // WebUI doesn't use these values yet.
+  // TODO(aa): When WebUI is ported to ExtensionFunctionDispatcher, send real
   // values here.
   params.request_id = -1;
   params.has_callback = false;
   params.user_gesture = false;
-  delegate_->ProcessDOMUIMessage(params);
+  delegate_->ProcessWebUIMessage(params);
 }
 
 void RenderViewHost::OnMsgForwardMessageToExternalHost(
@@ -1287,13 +1179,6 @@
   Send(new ViewMsg_AllowScriptToClose(routing_id(), script_can_close));
 }
 
-void RenderViewHost::OnMsgGoToEntryAtOffset(int offset) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->GoToEntryAtOffset(offset);
-}
-
 void RenderViewHost::OnMsgSetTooltipText(
     const std::wstring& tooltip_text,
     WebTextDirection text_direction_hint) {
@@ -1332,14 +1217,6 @@
     view()->SelectionChanged(text);
 }
 
-void RenderViewHost::OnMsgRunFileChooser(
-    const ViewHostMsg_RunFileChooser_Params& params) {
-  RenderViewHostDelegate::FileSelect* file_select_delegate =
-      delegate()->GetFileSelectDelegate();
-  if (file_select_delegate)
-    file_select_delegate->RunFileChooser(this, params);
-}
-
 void RenderViewHost::OnMsgRunJavaScriptMessage(
     const std::wstring& message,
     const std::wstring& default_prompt,
@@ -1378,33 +1255,13 @@
   Send(new ViewMsg_MediaPlayerActionAt(routing_id(), location, action));
 }
 
-void RenderViewHost::OnMsgFormsSeen(const std::vector<FormData>& forms) {
-  RenderViewHostDelegate::AutoFill* autofill_delegate =
-      delegate_->GetAutoFillDelegate();
-  if (autofill_delegate)
-    autofill_delegate->FormsSeen(forms);
+void RenderViewHost::ContextMenuClosed(
+    const webkit_glue::CustomContextMenuContext& custom_context) {
+  Send(new ViewMsg_ContextMenuClosed(routing_id(), custom_context));
 }
 
-void RenderViewHost::OnMsgPasswordFormsFound(
-    const std::vector<PasswordForm>& forms) {
-  delegate_->PasswordFormsFound(forms);
-}
-
-void RenderViewHost::OnMsgPasswordFormsVisible(
-    const std::vector<PasswordForm>& visible_forms) {
-  delegate_->PasswordFormsVisible(visible_forms);
-}
-
-void RenderViewHost::OnMsgFormSubmitted(const FormData& form) {
-  RenderViewHostDelegate::Autocomplete* autocomplete_delegate =
-      delegate_->GetAutocompleteDelegate();
-  if (autocomplete_delegate)
-    autocomplete_delegate->FormSubmitted(form);
-
-  RenderViewHostDelegate::AutoFill* autofill_delegate =
-      delegate_->GetAutoFillDelegate();
-  if (autofill_delegate)
-    autofill_delegate->FormSubmitted(form);
+void RenderViewHost::PrintNodeUnderContextMenu() {
+  Send(new ViewMsg_PrintNodeUnderContextMenu(routing_id()));
 }
 
 void RenderViewHost::OnMsgStartDragging(
@@ -1436,21 +1293,6 @@
   delegate_->PageHasOSDD(this, page_id, doc_url, provider_type);
 }
 
-void RenderViewHost::OnDidGetPrintedPagesCount(int cookie, int number_pages) {
-  RenderViewHostDelegate::Printing* printing_delegate =
-      delegate_->GetPrintingDelegate();
-  if (printing_delegate)
-    printing_delegate->DidGetPrintedPagesCount(cookie, number_pages);
-}
-
-void RenderViewHost::DidPrintPage(
-    const ViewHostMsg_DidPrintPage_Params& params) {
-  RenderViewHostDelegate::Printing* printing_delegate =
-      delegate_->GetPrintingDelegate();
-  if (printing_delegate)
-    printing_delegate->DidPrintPage(params);
-}
-
 void RenderViewHost::OnAddMessageToConsole(const std::wstring& message,
                                            int32 line_no,
                                            const std::wstring& source_id) {
@@ -1504,32 +1346,7 @@
 }
 
 void RenderViewHost::OnUserGesture() {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->OnUserGesture();
-}
-
-void RenderViewHost::OnMissingPluginStatus(int status) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->OnMissingPluginStatus(status);
-}
-
-void RenderViewHost::OnCrashedPlugin(const FilePath& plugin_path) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->OnCrashedPlugin(plugin_path);
-}
-
-void RenderViewHost::OnBlockedOutdatedPlugin(const string16& name,
-                                              const GURL& update_url) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->OnBlockedOutdatedPlugin(name, update_url);
+  delegate_->OnUserGesture();
 }
 
 void RenderViewHost::GetAllSavableResourceLinksForCurrentPage(
@@ -1538,33 +1355,6 @@
                                                             page_url));
 }
 
-void RenderViewHost::OnReceivedSavableResourceLinksForCurrentPage(
-    const std::vector<GURL>& resources_list,
-    const std::vector<GURL>& referrers_list,
-    const std::vector<GURL>& frames_list) {
-  RenderViewHostDelegate::Save* save_delegate = delegate_->GetSaveDelegate();
-  if (save_delegate) {
-    save_delegate->OnReceivedSavableResourceLinksForCurrentPage(
-        resources_list, referrers_list, frames_list);
-  }
-}
-
-void RenderViewHost::OnDidGetApplicationInfo(
-    int32 page_id, const WebApplicationInfo& info) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->OnDidGetApplicationInfo(page_id, info);
-}
-
-void RenderViewHost::OnInstallApplication(
-    const WebApplicationInfo& info) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (integration_delegate)
-    integration_delegate->OnInstallApplication(info);
-}
-
 void RenderViewHost::GetSerializedHtmlDataForCurrentPageWithLocalLinks(
     const std::vector<GURL>& links,
     const std::vector<FilePath>& local_paths,
@@ -1573,14 +1363,6 @@
       routing_id(), links, local_paths, local_directory_name));
 }
 
-void RenderViewHost::OnReceivedSerializedHtmlData(const GURL& frame_url,
-                                                  const std::string& data,
-                                                  int32 status) {
-  RenderViewHostDelegate::Save* save_delegate = delegate_->GetSaveDelegate();
-  if (save_delegate)
-    save_delegate->OnReceivedSerializedHtmlData(frame_url, data, status);
-}
-
 void RenderViewHost::OnMsgShouldCloseACK(bool proceed) {
   StopHangMonitorTimeout();
   // If this renderer navigated while the beforeunload request was in flight, we
@@ -1599,136 +1381,6 @@
   }
 }
 
-void RenderViewHost::OnQueryFormFieldAutoFill(int query_id,
-                                              const FormData& form,
-                                              const FormField& field) {
-  ResetAutoFillState(query_id);
-
-  // We first query the autofill delegate for suggestions. We keep track of the
-  // results it gives us, which we will later combine with the autocomplete
-  // suggestions.
-  RenderViewHostDelegate::AutoFill* autofill_delegate =
-      delegate_->GetAutoFillDelegate();
-  if (autofill_delegate)
-    autofill_delegate->GetAutoFillSuggestions(form, field);
-
-  // Now query the Autocomplete delegate for suggestions. These will be combined
-  // with the saved autofill suggestions in |AutocompleteSuggestionsReturned()|.
-  RenderViewHostDelegate::Autocomplete* autocomplete_delegate =
-      delegate_->GetAutocompleteDelegate();
-  if (autocomplete_delegate) {
-      autocomplete_delegate->GetAutocompleteSuggestions(field.name(),
-                                                        field.value());
-  } else {
-    AutocompleteSuggestionsReturned(std::vector<string16>());
-  }
-}
-
-void RenderViewHost::OnDidShowAutoFillSuggestions() {
-  NotificationService::current()->Notify(
-      NotificationType::AUTOFILL_DID_SHOW_SUGGESTIONS,
-      Source<RenderViewHost>(this),
-      NotificationService::NoDetails());
-}
-
-void RenderViewHost::OnRemoveAutocompleteEntry(const string16& field_name,
-                                               const string16& value) {
-  RenderViewHostDelegate::Autocomplete* autocomplete_delegate =
-      delegate_->GetAutocompleteDelegate();
-  if (autocomplete_delegate)
-    autocomplete_delegate->RemoveAutocompleteEntry(field_name, value);
-}
-
-void RenderViewHost::OnShowAutoFillDialog() {
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kDisableTabbedOptions)) {
-    Browser* browser = BrowserList::GetLastActive();
-    if (!browser)
-      return;
-    browser->ShowOptionsTab(chrome::kAutoFillSubPage);
-  } else {
-    RenderViewHostDelegate::AutoFill* autofill_delegate =
-      delegate_->GetAutoFillDelegate();
-    if (!autofill_delegate)
-      return;
-
-    autofill_delegate->ShowAutoFillDialog();
-  }
-}
-
-void RenderViewHost::OnFillAutoFillFormData(int query_id,
-                                            const FormData& form,
-                                            const FormField& field,
-                                            int unique_id) {
-  RenderViewHostDelegate::AutoFill* autofill_delegate =
-      delegate_->GetAutoFillDelegate();
-  if (!autofill_delegate)
-    return;
-
-  autofill_delegate->FillAutoFillFormData(query_id, form, field, unique_id);
-}
-
-void RenderViewHost::OnDidFillAutoFillFormData() {
-  NotificationService::current()->Notify(
-      NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
-      Source<RenderViewHost>(this),
-      NotificationService::NoDetails());
-}
-
-void RenderViewHost::ResetAutoFillState(int query_id) {
-  autofill_query_id_ = query_id;
-
-  autofill_values_.clear();
-  autofill_labels_.clear();
-  autofill_icons_.clear();
-  autofill_unique_ids_.clear();
-}
-
-void RenderViewHost::AutoFillSuggestionsReturned(
-    const std::vector<string16>& values,
-    const std::vector<string16>& labels,
-    const std::vector<string16>& icons,
-    const std::vector<int>& unique_ids) {
-  autofill_values_.assign(values.begin(), values.end());
-  autofill_labels_.assign(labels.begin(), labels.end());
-  autofill_icons_.assign(icons.begin(), icons.end());
-  autofill_unique_ids_.assign(unique_ids.begin(), unique_ids.end());
-}
-
-void RenderViewHost::AutocompleteSuggestionsReturned(
-    const std::vector<string16>& suggestions) {
-  // Combine AutoFill and Autocomplete values into values and labels.
-  for (size_t i = 0; i < suggestions.size(); ++i) {
-    bool unique = true;
-    for (size_t j = 0; j < autofill_values_.size(); ++j) {
-      // Don't add duplicate values.
-      if (autofill_values_[j] == suggestions[i]) {
-        unique = false;
-        break;
-      }
-    }
-
-    if (unique) {
-      autofill_values_.push_back(suggestions[i]);
-      autofill_labels_.push_back(string16());
-      autofill_icons_.push_back(string16());
-      autofill_unique_ids_.push_back(0);  // 0 means no profile.
-    }
-  }
-
-  Send(new ViewMsg_AutoFillSuggestionsReturned(routing_id(),
-                                               autofill_query_id_,
-                                               autofill_values_,
-                                               autofill_labels_,
-                                               autofill_icons_,
-                                               autofill_unique_ids_));
-}
-
-void RenderViewHost::AutoFillFormDataFilled(int query_id,
-                                            const FormData& form) {
-  Send(new ViewMsg_AutoFillFormDataFilled(routing_id(), query_id, form));
-}
-
 void RenderViewHost::WindowMoveOrResizeStarted() {
   Send(new ViewMsg_MoveOrResizeStarted(routing_id()));
 }
@@ -1829,39 +1481,6 @@
                                                  target));
 }
 
-void RenderViewHost::OnShowDesktopNotification(
-    const ViewHostMsg_ShowNotification_Params& params) {
-  DesktopNotificationService* service =
-      process()->profile()->GetDesktopNotificationService();
-
-    service->ShowDesktopNotification(
-        params, process()->id(), routing_id(),
-        DesktopNotificationService::PageNotification);
-}
-
-void RenderViewHost::OnCancelDesktopNotification(int notification_id) {
-  DesktopNotificationService* service=
-      process()->profile()->GetDesktopNotificationService();
-  service->CancelDesktopNotification(
-      process()->id(), routing_id(), notification_id);
-}
-
-void RenderViewHost::OnRequestNotificationPermission(
-    const GURL& source_origin, int callback_context) {
-  Browser* browser = BrowserList::GetLastActive();
-  // We may not have a BrowserList if the chrome browser process is launched as
-  // a ChromeFrame process in which case we attempt to use the TabContents
-  // provided by the RenderViewHostDelegate.
-  TabContents* tab = browser ? browser->GetSelectedTabContents() :
-      (delegate_ ? delegate_->GetAsTabContents() : NULL);
-  if (tab) {
-    DesktopNotificationService* service =
-        process()->profile()->GetDesktopNotificationService();
-    service->RequestPermission(
-        source_origin, process()->id(), routing_id(), callback_context, tab);
-  }
-}
-
 void RenderViewHost::OnExtensionRequest(
     const ViewHostMsg_DomMessage_Params& params) {
   if (!ChildProcessSecurityPolicy::GetInstance()->
@@ -1872,7 +1491,7 @@
     return;
   }
 
-  delegate_->ProcessDOMUIMessage(params);
+  delegate_->ProcessWebUIMessage(params);
 }
 
 void RenderViewHost::SendExtensionResponse(int request_id, bool success,
@@ -1891,29 +1510,12 @@
   Send(new ViewMsg_UpdateBrowserWindowId(routing_id(), window_id));
 }
 
-void RenderViewHost::PerformCustomContextMenuAction(unsigned action) {
-  Send(new ViewMsg_CustomContextMenuAction(routing_id(), action));
-}
-
-void RenderViewHost::TranslatePage(int page_id,
-                                   const std::string& translate_script,
-                                   const std::string& source_lang,
-                                   const std::string& target_lang) {
-  // Ideally we'd have a better way to uniquely identify form control elements,
-  // but we don't have that yet.  So before start translation, we clear the
-  // current form and re-parse it in AutoFillManager first to get the new
-  // labels.
-  RenderViewHostDelegate::AutoFill* autofill_delegate =
-      delegate_->GetAutoFillDelegate();
-  if (autofill_delegate)
-    autofill_delegate->Reset();
-
-  Send(new ViewMsg_TranslatePage(routing_id(), page_id, translate_script,
-                                 source_lang, target_lang));
-}
-
-void RenderViewHost::RevertTranslation(int page_id) {
-  Send(new ViewMsg_RevertTranslation(routing_id(), page_id));
+void RenderViewHost::PerformCustomContextMenuAction(
+    const webkit_glue::CustomContextMenuContext& custom_context,
+    unsigned action) {
+  Send(new ViewMsg_CustomContextMenuAction(routing_id(),
+                                           custom_context,
+                                           action));
 }
 
 void RenderViewHost::SendContentSettings(const GURL& url,
@@ -1957,9 +1559,11 @@
 }
 
 void RenderViewHost::DetermineIfPageSupportsInstant(const string16& value,
-                                                    bool verbatim) {
-  Send(new ViewMsg_DetermineIfPageSupportsInstant(routing_id(), value,
-                                                  verbatim));
+                                                    bool verbatim,
+                                                    int selection_start,
+                                                    int selection_end) {
+  Send(new ViewMsg_DetermineIfPageSupportsInstant(
+           routing_id(), value, verbatim, selection_start, selection_end));
 }
 
 void RenderViewHost::FilterURL(ChildProcessSecurityPolicy* policy,
@@ -1983,6 +1587,10 @@
   }
 }
 
+void RenderViewHost::JavaScriptStressTestControl(int cmd, int param) {
+  Send(new ViewMsg_JavaScriptStressTestControl(routing_id(), cmd, param));
+}
+
 void RenderViewHost::OnExtensionPostMessage(
     int port_id, const std::string& message) {
   if (process()->profile()->GetExtensionMessageService()) {
@@ -2025,31 +1633,6 @@
   delegate_->DidInsertCSS();
 }
 
-void RenderViewHost::OnPageContents(const GURL& url,
-                                    int32 page_id,
-                                    const string16& contents,
-                                    const std::string& language,
-                                    bool page_translatable) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (!integration_delegate)
-    return;
-  integration_delegate->OnPageContents(url, process()->id(), page_id, contents,
-                                       language, page_translatable);
-}
-
-void RenderViewHost::OnPageTranslated(int32 page_id,
-                                      const std::string& original_lang,
-                                      const std::string& translated_lang,
-                                      TranslateErrors::Type error_type) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (!integration_delegate)
-    return;
-  integration_delegate->OnPageTranslated(page_id, original_lang,
-                                         translated_lang, error_type);
-}
-
 void RenderViewHost::OnContentBlocked(ContentSettingsType type,
                                       const std::string& resource_identifier) {
   RenderViewHostDelegate::ContentSettings* content_settings_delegate =
@@ -2085,27 +1668,8 @@
   delegate_->UpdateZoomLimits(minimum_percent, maximum_percent, remember);
 }
 
-void RenderViewHost::OnSetSuggestions(
-    int32 page_id,
-    const std::vector<std::string>& suggestions) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (!integration_delegate)
-    return;
-  integration_delegate->OnSetSuggestions(page_id, suggestions);
-}
-
-void RenderViewHost::OnInstantSupportDetermined(int32 page_id, bool result) {
-  RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-      delegate_->GetBrowserIntegrationDelegate();
-  if (!integration_delegate)
-    return;
-  integration_delegate->OnInstantSupportDetermined(page_id, result);
-}
-
 void RenderViewHost::OnDetectedPhishingSite(const GURL& phishing_url,
-                                            double phishing_score,
-                                            const SkBitmap& thumbnail) {
+                                            double phishing_score) {
   // TODO(noelutz): send an HTTP request to the client-side detection frontends
   // to confirm that the URL is really phishing.
 }
@@ -2120,10 +1684,6 @@
       Details<std::pair<int, Value*> >(&details));
 }
 
-void RenderViewHost::OnUpdateContentRestrictions(int restrictions) {
-  delegate_->UpdateContentRestrictions(restrictions);
-}
-
 #if defined(OS_MACOSX)
 void RenderViewHost::OnMsgShowPopup(
     const ViewHostMsg_ShowPopup_Params& params) {
@@ -2139,51 +1699,24 @@
 }
 #endif
 
-TabContents* RenderViewHost::GetOrCreatePrintPreviewTab() {
-  TabContents* initiator_tab = delegate_ ? delegate_->GetAsTabContents() : NULL;
-  if (initiator_tab) {
-    // Get/Create preview tab for initiator tab.
-    printing::PrintPreviewTabController* tab_controller =
-        printing::PrintPreviewTabController::GetInstance();
-    if (tab_controller)
-      return tab_controller->GetOrCreatePreviewTab(
-        initiator_tab, delegate_->GetBrowserWindowID());
-  }
-  return NULL;
-}
-
-void RenderViewHost::OnPagesReadyForPreview(
-    const ViewHostMsg_DidPreviewDocument_Params& params) {
-#if defined(OS_MACOSX)
-  base::SharedMemory shared_buf(params.metafile_data_handle, true);
-  if (!shared_buf.Map(params.data_size)) {
-    NOTREACHED();
-    return;
-  }
-  scoped_ptr<printing::NativeMetafile> metafile(new printing::NativeMetafile());
-  if (!metafile->Init(shared_buf.memory(), params.data_size)) {
-    NOTREACHED();
+void RenderViewHost::OnCommandStateChanged(int command,
+                                           bool is_enabled,
+                                           int checked_state) {
+  if (command != RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK) {
+    LOG(DFATAL) << "Unknown command " << command;
     return;
   }
 
-  // TODO(kmadhusu): Add more functionality for the preview tab to access this
-  // |metafile| data.
-#endif
-
-  // Get/Create print preview tab.
-  TabContents* print_preview_tab = GetOrCreatePrintPreviewTab();
-  DCHECK(print_preview_tab);
-
-  scoped_refptr<printing::PrinterQuery> printer_query;
-  g_browser_process->print_job_manager()->PopPrinterQuery(
-      params.document_cookie, &printer_query);
-  if (printer_query.get()) {
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        NewRunnableMethod(printer_query.get(),
-                          &printing::PrinterQuery::StopWorker));
+  if (checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED &&
+      checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED &&
+      checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED) {
+    LOG(DFATAL) << "Invalid checked state " << checked_state;
+    return;
   }
 
-  // Send the printingDone msg for now.
-  Send(new ViewMsg_PrintingDone(routing_id(), params.document_cookie, true));
+  CommandState state;
+  state.is_enabled = is_enabled;
+  state.checked_state =
+      static_cast<RenderViewCommandCheckedState>(checked_state);
+  command_states_[static_cast<RenderViewCommand>(command)] = state;
 }
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 2174f2f..88ff1df 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,14 +15,15 @@
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/common/content_settings_types.h"
 #include "chrome/common/page_zoom.h"
+#include "chrome/common/render_view_commands.h"
 #include "chrome/common/translate_errors.h"
 #include "chrome/common/view_types.h"
 #include "chrome/common/window_container_type.h"
 #include "net/base/load_states.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
 #include "webkit/glue/webaccessibility.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -40,12 +41,9 @@
 struct MediaPlayerAction;
 struct ThumbnailScore;
 struct ViewHostMsg_AccessibilityNotification_Params;
-struct ViewHostMsg_DidPreviewDocument_Params;
-struct ViewHostMsg_DidPrintPage_Params;
+struct ViewHostMsg_CreateWindow_Params;
 struct ViewHostMsg_DomMessage_Params;
 struct ViewHostMsg_PageHasOSDD_Type;
-struct ViewHostMsg_RunFileChooser_Params;
-struct ViewHostMsg_ShowNotification_Params;
 struct ViewHostMsg_ShowPopup_Params;
 struct ViewMsg_Navigate_Params;
 struct WebApplicationInfo;
@@ -58,10 +56,7 @@
 }  // namespace gfx
 
 namespace webkit_glue {
-struct FormData;
-class FormField;
-struct PasswordForm;
-struct PasswordFormFillData;
+struct CustomContextMenuContext;
 struct WebAccessibility;
 }  // namespace webkit_glue
 
@@ -201,6 +196,12 @@
   // hangs, in which case we need to swap to the pending RenderViewHost.
   int GetPendingRequestId();
 
+  struct CommandState {
+    bool is_enabled;
+    RenderViewCommandCheckedState checked_state;
+  };
+  CommandState GetStateForCommand(RenderViewCommand command) const;
+
   // Stops the current load.
   void Stop();
 
@@ -244,11 +245,6 @@
   // alternate error pages.
   void SetAlternateErrorPageURL(const GURL& url);
 
-  // Fill out a password form and trigger DOM autocomplete in the case
-  // of multiple matching logins.
-  void FillPasswordForm(
-      const webkit_glue::PasswordFormFillData& form_data);
-
   // D&d drop target messages that get sent to WebKit.
   void DragTargetDragEnter(const WebDropData& drop_data,
                            const gfx::Point& client_pt,
@@ -265,8 +261,8 @@
   void ReservePageIDRange(int size);
 
   // Runs some javascript within the context of a frame in the page.
-  void ExecuteJavascriptInWebFrame(const std::wstring& frame_xpath,
-                                   const std::wstring& jscript);
+  void ExecuteJavascriptInWebFrame(const string16& frame_xpath,
+                                   const string16& jscript);
 
   // Runs some javascript within the context of a frame in the page. The result
   // is sent back via the notification EXECUTE_JAVASCRIPT_RESULT.
@@ -326,6 +322,13 @@
   void MediaPlayerActionAt(const gfx::Point& location,
                            const WebKit::WebMediaPlayerAction& action);
 
+  // Notifies the renderer that the context menu has closed.
+  void ContextMenuClosed(
+      const webkit_glue::CustomContextMenuContext& custom_context);
+
+  // Prints the node that's under the context menu.
+  void PrintNodeUnderContextMenu();
+
   // Copies the image at the specified point.
   void CopyImageAt(int x, int y);
 
@@ -358,9 +361,9 @@
     is_extension_process_ = is_extension_process;
   }
 
-  // Sets a property with the given name and value on the DOM UI binding object.
-  // Must call AllowDOMUIBindings() on this renderer first.
-  void SetDOMUIProperty(const std::string& name, const std::string& value);
+  // Sets a property with the given name and value on the Web UI binding object.
+  // Must call AllowWebUIBindings() on this renderer first.
+  void SetWebUIProperty(const std::string& name, const std::string& value);
 
   // Tells the renderer view to focus the first (last if reverse is true) node.
   void SetInitialFocus(bool reverse);
@@ -375,7 +378,7 @@
   void UpdateWebPreferences(const WebPreferences& prefs);
 
   // Request the Renderer to ask the default plugin to start installation of
-  // missing plugin. Called by PluginInstaller.
+  // missing plugin. Called by PluginInstallerInfoBarDelegate.
   void InstallMissingPlugin();
 
   // Load all blocked plugins in the RenderView.
@@ -423,23 +426,6 @@
   // set to false when creating a renderer-initiated window via window.open.
   void AllowScriptToClose(bool visible);
 
-  // Resets the stored AutoFill state.
-  void ResetAutoFillState(int query_id);
-
-  // Called by the AutoFillManager when the list of suggestions is ready.
-  void AutoFillSuggestionsReturned(const std::vector<string16>& values,
-                                   const std::vector<string16>& labels,
-                                   const std::vector<string16>& icons,
-                                   const std::vector<int>& unique_ids);
-
-  // Called by the AutocompleteHistoryManager when the list of suggestions is
-  // ready.
-  void AutocompleteSuggestionsReturned(
-      const std::vector<string16>& suggestions);
-
-  // Called by the AutoFillManager when the FormData has been filled out.
-  void AutoFillFormDataFilled(int query_id, const webkit_glue::FormData& form);
-
   // Notifies the Renderer that a move or resize of its containing window has
   // started (this is used to hide the autocomplete popups if any).
   void WindowMoveOrResizeStarted();
@@ -460,15 +446,14 @@
 
   // Creates a new RenderView with the given route id.
   void CreateNewWindow(int route_id,
-                       WindowContainerType window_container_type,
-                       const string16& frame_name);
+                       const ViewHostMsg_CreateWindow_Params& params);
 
   // Creates a new RenderWidget with the given route id.  |popup_type| indicates
   // if this widget is a popup and what kind of popup it is (select, autofill).
   void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
 
   // Creates a full screen RenderWidget.
-  void CreateNewFullscreenWidget(int route_id, WebKit::WebPopupType popup_type);
+  void CreateNewFullscreenWidget(int route_id);
 
   // Sends the response to an extension api call.
   void SendExtensionResponse(int request_id, bool success,
@@ -483,19 +468,9 @@
   void UpdateBrowserWindowId(int window_id);
 
   // Tells the render view that a custom context action has been selected.
-  void PerformCustomContextMenuAction(unsigned action);
-
-  // Tells the renderer to translate the current page from one language to
-  // another.  If the current page id is not |page_id|, the request is ignored.
-  // |translate_script| is the script that should be injected in the page to
-  // perform the translation.
-  void TranslatePage(int page_id,
-                     const std::string& translate_script,
-                     const std::string& source_lang,
-                     const std::string& target_lang);
-
-  // Reverts the text of current page to its original (non-translated) contents.
-  void RevertTranslation(int page_id);
+  void PerformCustomContextMenuAction(
+      const webkit_glue::CustomContextMenuContext& custom_context,
+      unsigned action);
 
   // Informs renderer of updated content settings.
   void SendContentSettings(const GURL& url,
@@ -523,7 +498,15 @@
   void SearchBoxCancel();
   void SearchBoxResize(const gfx::Rect& search_box_bounds);
   void DetermineIfPageSupportsInstant(const string16& value,
-                                      bool verbatim);
+                                      bool verbatim,
+                                      int selection_start,
+                                      int selection_end);
+
+  // Send a notification to the V8 JavaScript engine to change its parameters
+  // while performing stress testing. |cmd| is one of the values defined by
+  // |ViewHostMsg_JavaScriptStressTestControl_Commands|, which is defined
+  // in render_messages.h.
+  void JavaScriptStressTestControl(int cmd, int param);
 
 #if defined(UNIT_TEST)
   // These functions shouldn't be necessary outside of testing.
@@ -584,11 +567,6 @@
   void OnMsgDidChangeLoadProgress(double load_progress);
   void OnMsgDocumentAvailableInMainFrame();
   void OnMsgDocumentOnLoadCompletedInMainFrame(int32 page_id);
-  void OnMsgFindReply(int request_id,
-                      int number_of_matches,
-                      const gfx::Rect& selection_rect,
-                      int active_match_ordinal,
-                      bool final_update);
   void OnExecuteCodeFinished(int request_id, bool success);
   void OnMsgUpdateFavIconURL(int32 page_id, const GURL& icon_url);
   void OnMsgDidDownloadFavIcon(int id,
@@ -601,18 +579,16 @@
   void OnMsgDidContentsPreferredSizeChange(const gfx::Size& new_size);
   void OnMsgDomOperationResponse(const std::string& json_string,
                                  int automation_id);
-  void OnMsgDOMUISend(const GURL& source_url,
+  void OnMsgWebUISend(const GURL& source_url,
                       const std::string& message,
                       const std::string& content);
   void OnMsgForwardMessageToExternalHost(const std::string& message,
                                          const std::string& origin,
                                          const std::string& target);
-  void OnMsgGoToEntryAtOffset(int offset);
   void OnMsgSetTooltipText(const std::wstring& tooltip_text,
                            WebKit::WebTextDirection text_direction_hint);
   void OnMsgSelectionChanged(const std::string& text);
   void OnMsgPasteFromSelectionClipboard();
-  void OnMsgRunFileChooser(const ViewHostMsg_RunFileChooser_Params& params);
   void OnMsgRunJavaScriptMessage(const std::wstring& message,
                                  const std::wstring& default_prompt,
                                  const GURL& frame_url,
@@ -624,13 +600,6 @@
   void OnMsgShowModalHTMLDialog(const GURL& url, int width, int height,
                                 const std::string& json_arguments,
                                 IPC::Message* reply_msg);
-  void OnMsgFormsSeen(
-      const std::vector<webkit_glue::FormData>& forms);
-  void OnMsgPasswordFormsFound(
-      const std::vector<webkit_glue::PasswordForm>& forms);
-  void OnMsgPasswordFormsVisible(
-      const std::vector<webkit_glue::PasswordForm>& visible_forms);
-  void OnMsgFormSubmitted(const webkit_glue::FormData& forms);
   void OnMsgStartDragging(const WebDropData& drop_data,
                           WebKit::WebDragOperationsMask operations_allowed,
                           const SkBitmap& image,
@@ -640,8 +609,6 @@
   void OnMsgPageHasOSDD(int32 page_id,
                         const GURL& doc_url,
                         const ViewHostMsg_PageHasOSDD_Type& provider_type);
-  void OnDidGetPrintedPagesCount(int cookie, int number_pages);
-  void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params);
   void OnAddMessageToConsole(const std::wstring& message,
                              int32 line_no,
                              const std::wstring& source_id);
@@ -655,54 +622,13 @@
   void OnRequestUndockDevToolsWindow();
   void OnDevToolsRuntimePropertyChanged(const std::string& name,
                                         const std::string& value);
-  void OnMissingPluginStatus(int status);
-  void OnCrashedPlugin(const FilePath& plugin_path);
-  void OnBlockedOutdatedPlugin(const string16& name, const GURL& update_url);
-
-  void OnReceivedSavableResourceLinksForCurrentPage(
-      const std::vector<GURL>& resources_list,
-      const std::vector<GURL>& referrers_list,
-      const std::vector<GURL>& frames_list);
-
-  void OnReceivedSerializedHtmlData(const GURL& frame_url,
-                                    const std::string& data,
-                                    int32 status);
-
-  void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info);
-  void OnInstallApplication(const WebApplicationInfo& info);
   void OnMsgShouldCloseACK(bool proceed);
-  void OnQueryFormFieldAutoFill(int request_id,
-                                const webkit_glue::FormData& form,
-                                const webkit_glue::FormField& field);
-  void OnDidShowAutoFillSuggestions();
-  void OnRemoveAutocompleteEntry(const string16& field_name,
-                                 const string16& value);
-  void OnShowAutoFillDialog();
-  void OnFillAutoFillFormData(int query_id,
-                              const webkit_glue::FormData& form,
-                              const webkit_glue::FormField& field,
-                              int unique_id);
-  void OnDidFillAutoFillFormData();
-
-  void OnShowDesktopNotification(
-      const ViewHostMsg_ShowNotification_Params& params);
-  void OnCancelDesktopNotification(int notification_id);
-  void OnRequestNotificationPermission(const GURL& origin, int callback_id);
 
   void OnExtensionRequest(const ViewHostMsg_DomMessage_Params& params);
   void OnExtensionPostMessage(int port_id, const std::string& message);
   void OnAccessibilityNotifications(
       const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params);
   void OnCSSInserted();
-  void OnPageContents(const GURL& url,
-                      int32 page_id,
-                      const string16& contents,
-                      const std::string& language,
-                      bool page_translatable);
-  void OnPageTranslated(int32 page_id,
-                        const std::string& original_lang,
-                        const std::string& translated_lang,
-                        TranslateErrors::Type error_type);
   void OnContentBlocked(ContentSettingsType type,
                         const std::string& resource_identifier);
   void OnAppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy);
@@ -714,16 +640,11 @@
   void OnUpdateZoomLimits(int minimum_percent,
                           int maximum_percent,
                           bool remember);
-  void OnSetSuggestions(int32 page_id,
-                        const std::vector<std::string>& suggestions);
-  void OnInstantSupportDetermined(int32 page_id, bool result);
-  void OnDetectedPhishingSite(const GURL& phishing_url,
-                              double phishing_score,
-                              const SkBitmap& thumbnail);
+  void OnDetectedPhishingSite(const GURL& phishing_url, double phishing_score);
   void OnScriptEvalResponse(int id, const ListValue& result);
-  void OnUpdateContentRestrictions(int restrictions);
-  void OnPagesReadyForPreview(
-      const ViewHostMsg_DidPreviewDocument_Params& params);
+  void OnCommandStateChanged(int command,
+                             bool is_enabled,
+                             int checked_state);
 
 #if defined(OS_MACOSX)
   void OnMsgShowPopup(const ViewHostMsg_ShowPopup_Params& params);
@@ -732,9 +653,6 @@
  private:
   friend class TestRenderViewHost;
 
-  // Get/Create print preview tab.
-  TabContents* GetOrCreatePrintPreviewTab();
-
   // The SiteInstance associated with this RenderViewHost.  All pages drawn
   // in this RenderViewHost are part of this SiteInstance.  Should not change
   // over time.
@@ -803,15 +721,6 @@
   // what process type we use.
   bool is_extension_process_;
 
-  // TODO(isherman): Consider splitting these off into a helper class.
-  // AutoFill and Autocomplete suggestions.  We accumulate these separately and
-  // send them back to the renderer together.
-  std::vector<string16> autofill_values_;
-  std::vector<string16> autofill_labels_;
-  std::vector<string16> autofill_icons_;
-  std::vector<int> autofill_unique_ids_;
-  int autofill_query_id_;
-
   // Whether the accessibility tree should be saved, for unit testing.
   bool save_accessibility_tree_for_testing_;
 
@@ -821,6 +730,9 @@
   // The termination status of the last render view that terminated.
   base::TerminationStatus render_view_termination_status_;
 
+  // The enabled/disabled states of various commands.
+  std::map<RenderViewCommand, CommandState> command_states_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderViewHost);
 };
 
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.cc b/chrome/browser/renderer_host/render_view_host_delegate.cc
index a58eea5..1c6f2e6 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.cc
+++ b/chrome/browser/renderer_host/render_view_host_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,12 +8,12 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/common/renderer_preferences.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/webpreferences.h"
 
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #endif
 
 RenderViewHostDelegate::View* RenderViewHostDelegate::GetViewDelegate() {
@@ -25,41 +25,11 @@
   return NULL;
 }
 
-RenderViewHostDelegate::BrowserIntegration*
-RenderViewHostDelegate::GetBrowserIntegrationDelegate() {
-  return NULL;
-}
-
-
 RenderViewHostDelegate::ContentSettings*
 RenderViewHostDelegate::GetContentSettingsDelegate() {
   return NULL;
 }
 
-RenderViewHostDelegate::Save* RenderViewHostDelegate::GetSaveDelegate() {
-  return NULL;
-}
-
-RenderViewHostDelegate::Printing*
-RenderViewHostDelegate::GetPrintingDelegate() {
-  return NULL;
-}
-
-RenderViewHostDelegate::FavIcon*
-RenderViewHostDelegate::GetFavIconDelegate() {
-  return NULL;
-}
-
-RenderViewHostDelegate::Autocomplete*
-RenderViewHostDelegate::GetAutocompleteDelegate() {
-  return NULL;
-}
-
-RenderViewHostDelegate::AutoFill*
-RenderViewHostDelegate::GetAutoFillDelegate() {
-  return NULL;
-}
-
 RenderViewHostDelegate::BookmarkDrag*
 RenderViewHostDelegate::GetBookmarkDragDelegate() {
   return NULL;
@@ -70,11 +40,6 @@
   return NULL;
 }
 
-RenderViewHostDelegate::FileSelect*
-RenderViewHostDelegate::GetFileSelectDelegate() {
-  return NULL;
-}
-
 AutomationResourceRoutingDelegate*
 RenderViewHostDelegate::GetAutomationResourceRoutingDelegate() {
   return NULL;
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index 34c206b..0dddd30 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -20,8 +20,8 @@
 #include "chrome/common/window_container_type.h"
 #include "ipc/ipc_channel.h"
 #include "net/base/load_states.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
 #include "webkit/glue/window_open_disposition.h"
 
 
@@ -35,7 +35,6 @@
 class ListValue;
 struct NativeWebKeyboardEvent;
 class NavigationEntry;
-class OSExchangeData;
 class Profile;
 struct RendererPreferences;
 class RenderProcessHost;
@@ -47,11 +46,10 @@
 class SSLAddCertHandler;
 class TabContents;
 struct ThumbnailScore;
-struct ViewHostMsg_DidPrintPage_Params;
+struct ViewHostMsg_CreateWindow_Params;
 struct ViewHostMsg_DomMessage_Params;
 struct ViewHostMsg_FrameNavigate_Params;
 struct ViewHostMsg_PageHasOSDD_Type;
-struct ViewHostMsg_RunFileChooser_Params;
 struct WebApplicationInfo;
 struct WebDropData;
 struct WebMenuItem;
@@ -102,15 +100,15 @@
 
   class View {
    public:
-    // The page is trying to open a new page (e.g. a popup window). The
-    // window should be created associated with the given route, but it should
-    // not be shown yet. That should happen in response to ShowCreatedWindow.
-    // |window_container_type| describes the type of RenderViewHost container
-    // that is requested -- in particular, the window.open call may have
-    // specified 'background' and 'persistent' in the feature string.
+    // The page is trying to open a new page (e.g. a popup window). The window
+    // should be created associated with the given route, but it should not be
+    // shown yet. That should happen in response to ShowCreatedWindow.
+    // |params.window_container_type| describes the type of RenderViewHost
+    // container that is requested -- in particular, the window.open call may
+    // have specified 'background' and 'persistent' in the feature string.
     //
-    // The passed |frame_name| parameter is the name parameter that was passed
-    // to window.open(), and will be empty if none was passed.
+    // The passed |params.frame_name| parameter is the name parameter that was
+    // passed to window.open(), and will be empty if none was passed.
     //
     // Note: this is not called "CreateWindow" because that will clash with
     // the Windows function which is actually a #define.
@@ -118,8 +116,7 @@
     // NOTE: this takes ownership of @modal_dialog_event
     virtual void CreateNewWindow(
         int route_id,
-        WindowContainerType window_container_type,
-        const string16& frame_name) = 0;
+        const ViewHostMsg_CreateWindow_Params& params) = 0;
 
     // The page is trying to open a new widget (e.g. a select popup). The
     // widget should be created associated with the given route, but it should
@@ -130,8 +127,7 @@
                                  WebKit::WebPopupType popup_type) = 0;
 
     // Creates a full screen RenderWidget. Similar to above.
-    virtual void CreateNewFullscreenWidget(
-        int route_id, WebKit::WebPopupType popup_type) = 0;
+    virtual void CreateNewFullscreenWidget(int route_id) = 0;
 
     // Show a previously created page with the specified disposition and bounds.
     // The window is identified by the route_id passed to CreateNewWindow.
@@ -249,80 +245,6 @@
     virtual ~RendererManagement() {}
   };
 
-  // BrowserIntegration --------------------------------------------------------
-  // Functions that integrate with other browser services.
-
-  class BrowserIntegration {
-   public:
-    // Notification the user has made a gesture while focus was on the
-    // page. This is used to avoid uninitiated user downloads (aka carpet
-    // bombing), see DownloadRequestLimiter for details.
-    virtual void OnUserGesture() = 0;
-
-    // A find operation in the current page completed.
-    virtual void OnFindReply(int request_id,
-                             int number_of_matches,
-                             const gfx::Rect& selection_rect,
-                             int active_match_ordinal,
-                             bool final_update) = 0;
-
-    // Navigate to the history entry for the given offset from the current
-    // position within the NavigationController.  Makes no change if offset is
-    // not valid.
-    virtual void GoToEntryAtOffset(int offset) = 0;
-
-    // Notification when default plugin updates status of the missing plugin.
-    virtual void OnMissingPluginStatus(int status) = 0;
-
-    // Notification from the renderer that a plugin instance has crashed.
-    //
-    // BrowserIntegration isn't necessarily the best place for this, if you
-    // need to implement this function somewhere that doesn't need any other
-    // BrowserIntegration callbacks, feel free to move it elsewhere.
-    virtual void OnCrashedPlugin(const FilePath& plugin_path) = 0;
-
-    // Notification that a worker process has crashed.
-    virtual void OnCrashedWorker() = 0;
-
-    virtual void OnBlockedOutdatedPlugin(const string16& name,
-                                         const GURL& update_url) = 0;
-
-    // Notification that a user's request to install an application has
-    // completed.
-    virtual void OnDidGetApplicationInfo(
-        int32 page_id,
-        const WebApplicationInfo& app_info) = 0;
-
-    // Notification when an application programmatically requests installation.
-    virtual void OnInstallApplication(
-        const WebApplicationInfo& app_info) = 0;
-
-    // Notification that the contents of the page has been loaded.
-    virtual void OnPageContents(const GURL& url,
-                                int renderer_process_id,
-                                int32 page_id,
-                                const string16& contents,
-                                const std::string& language,
-                                bool page_translatable) = 0;
-
-    // Notification that the page has been translated.
-    virtual void OnPageTranslated(int32 page_id,
-                                  const std::string& original_lang,
-                                  const std::string& translated_lang,
-                                  TranslateErrors::Type error_type) = 0;
-
-    // Notification that the page has a suggest result.
-    virtual void OnSetSuggestions(
-        int32 page_id,
-        const std::vector<std::string>& result) = 0;
-
-    // Notification of whether the page supports instant-style interaction.
-    virtual void OnInstantSupportDetermined(int32 page_id, bool result) = 0;
-
-   protected:
-    virtual ~BrowserIntegration() {}
-  };
-
   // ContentSettings------------------------------------------------------------
   // Interface for content settings related events.
 
@@ -393,145 +315,6 @@
     virtual ~ContentSettings() {}
   };
 
-  // Save ----------------------------------------------------------------------
-  // Interface for saving web pages.
-
-  class Save {
-   public:
-    // Notification that we get when we receive all savable links of
-    // sub-resources for the current page, their referrers and list of frames
-    // (include main frame and sub frames).
-    virtual void OnReceivedSavableResourceLinksForCurrentPage(
-        const std::vector<GURL>& resources_list,
-        const std::vector<GURL>& referrers_list,
-        const std::vector<GURL>& frames_list) = 0;
-
-    // Notification that we get when we receive serialized html content data of
-    // a specified web page from render process. The parameter frame_url
-    // specifies what frame the data belongs. The parameter data contains the
-    // available data for sending. The parameter status indicates the
-    // serialization status, See
-    // webkit_glue::DomSerializerDelegate::PageSavingSerializationStatus for
-    // the detail meaning of status.
-    virtual void OnReceivedSerializedHtmlData(const GURL& frame_url,
-                                              const std::string& data,
-                                              int32 status) = 0;
-
-   protected:
-    virtual ~Save() {}
-  };
-
-  // Printing ------------------------------------------------------------------
-
-  class Printing {
-   public:
-    // Notification that the render view has calculated the number of printed
-    // pages.
-    virtual void DidGetPrintedPagesCount(int cookie, int number_pages) = 0;
-
-    // Notification that the render view is done rendering one printed page.
-    // This call is synchronous, the renderer is waiting on us because of the
-    // EMF memory mapped data.
-    virtual void DidPrintPage(
-        const ViewHostMsg_DidPrintPage_Params& params) = 0;
-
-   protected:
-    virtual ~Printing() {}
-  };
-
-  // FavIcon -------------------------------------------------------------------
-  // Interface for the renderer to supply favicon information.
-
-  class FavIcon {
-   public:
-    // An image that was requested to be downloaded by DownloadImage has
-    // completed.
-    //
-    // TODO(brettw) this should be renamed DidDownloadFavIcon, and the RVH
-    // function, IPC message, and the RenderView function DownloadImage should
-    // all be named DownloadFavIcon.
-    virtual void DidDownloadFavIcon(RenderViewHost* render_view_host,
-                                    int id,
-                                    const GURL& image_url,
-                                    bool errored,
-                                    const SkBitmap& image) = 0;
-
-    // The URL for the FavIcon of a page has changed.
-    virtual void UpdateFavIconURL(RenderViewHost* render_view_host,
-                                  int32 page_id,
-                                  const GURL& icon_url) = 0;
-
-   protected:
-    virtual ~FavIcon() {}
-  };
-
-  // Autocomplete --------------------------------------------------------------
-  // Interface for Autocomplete-related functions.
-
-  class Autocomplete {
-   public:
-    // Forms fillable by Autocomplete have been detected in the page.
-    virtual void FormSubmitted(const webkit_glue::FormData& form) = 0;
-
-    // Called to retrieve a list of suggestions from the web database given
-    // the name of the field |field_name| and what the user has already typed
-    // in the field |user_text|.  Appeals to the database thread to perform the
-    // query. When the database thread is finished, the AutocompleteHistory
-    // manager retrieves the calling RenderViewHost and then passes the vector
-    // of suggestions to RenderViewHost::AutocompleteSuggestionsReturned.
-    virtual void GetAutocompleteSuggestions(const string16& field_name,
-                                            const string16& user_text) = 0;
-
-    // Called when the user has indicated that she wants to remove the specified
-    // Autocomplete suggestion from the database.
-    virtual void RemoveAutocompleteEntry(const string16& field_name,
-                                         const string16& value) = 0;
-
-   protected:
-    virtual ~Autocomplete() {}
-  };
-
-  // AutoFill ------------------------------------------------------------------
-  // Interface for AutoFill-related functions.
-
-  class AutoFill {
-   public:
-    // Called when the user submits a form.
-    virtual void FormSubmitted(const webkit_glue::FormData& form) = 0;
-
-    // Called when the frame has finished loading and there are forms in the
-    // frame.
-    virtual void FormsSeen(const std::vector<webkit_glue::FormData>& forms) = 0;
-
-    // Called to retrieve a list of AutoFill suggestions for the portion of the
-    // |form| containing |field|, given the current state of the |form|.
-    // Returns true to indicate that RenderViewHost::AutoFillSuggestionsReturned
-    // has been called.
-    virtual bool GetAutoFillSuggestions(
-        const webkit_glue::FormData& form,
-        const webkit_glue::FormField& field) = 0;
-
-    // Called to fill the |form| with AutoFill profile information that matches
-    // the |unique_id| key. If the portion of the form containing |field| has
-    // been autofilled already, only fills |field|.
-    // Returns true to indicate that RenderViewHost::AutoFillFormDataFilled
-    // has been called.
-    virtual bool FillAutoFillFormData(int query_id,
-                                      const webkit_glue::FormData& form,
-                                      const webkit_glue::FormField& field,
-                                      int unique_id) = 0;
-
-    // Called when the user selects the 'AutoFill Options...' suggestions in the
-    // AutoFill popup.
-    virtual void ShowAutoFillDialog() = 0;
-
-    // Reset cache in AutoFillManager.
-    virtual void Reset() = 0;
-
-   protected:
-    virtual ~AutoFill() {}
-  };
-
   // BookmarkDrag --------------------------------------------------------------
   // Interface for forwarding bookmark drag and drop to extenstions.
 
@@ -587,36 +370,16 @@
     virtual ~SSL() {}
   };
 
-  // FileSelect ----------------------------------------------------------------
-  // Interface for handling file selection.
-
-  class FileSelect {
-   public:
-    // A file chooser should be shown.
-    virtual void RunFileChooser(
-        RenderViewHost* render_view_host,
-        const ViewHostMsg_RunFileChooser_Params& params) = 0;
-
-   protected:
-    virtual ~FileSelect() {}
-  };
-
   // ---------------------------------------------------------------------------
 
   // Returns the current delegate associated with a feature. May return NULL if
   // there is no corresponding delegate.
   virtual View* GetViewDelegate();
   virtual RendererManagement* GetRendererManagementDelegate();
-  virtual BrowserIntegration* GetBrowserIntegrationDelegate();
   virtual ContentSettings* GetContentSettingsDelegate();
-  virtual Save* GetSaveDelegate();
-  virtual Printing* GetPrintingDelegate();
-  virtual FavIcon* GetFavIconDelegate();
-  virtual Autocomplete* GetAutocompleteDelegate();
-  virtual AutoFill* GetAutoFillDelegate();
+
   virtual BookmarkDrag* GetBookmarkDragDelegate();
   virtual SSL* GetSSLDelegate();
-  virtual FileSelect* GetFileSelectDelegate();
 
   // Return the delegate for registering RenderViewHosts for automation resource
   // routing.
@@ -631,7 +394,8 @@
   virtual const GURL& GetURL() const;
 
   // Return this object cast to a TabContents, if it is one. If the object is
-  // not a TabContents, returns NULL.
+  // not a TabContents, returns NULL. DEPRECATED: Be sure to include brettw and
+  // jam as reviewers before you use this method.
   virtual TabContents* GetAsTabContents();
 
   // Return this object cast to a BackgroundContents, if it is one. If the
@@ -734,7 +498,7 @@
 
   // A message was sent from HTML-based UI.
   // By default we ignore such messages.
-  virtual void ProcessDOMUIMessage(
+  virtual void ProcessWebUIMessage(
       const ViewHostMsg_DomMessage_Params& params) {}
 
   // A message for external host. By default we ignore such messages.
@@ -759,14 +523,6 @@
                                    const std::string& json_arguments,
                                    IPC::Message* reply_msg) {}
 
-  // Password forms have been detected in the page.
-  virtual void PasswordFormsFound(
-      const std::vector<webkit_glue::PasswordForm>& forms) {}
-
-  // On initial layout, password forms are known to be visible on the page.
-  virtual void PasswordFormsVisible(
-      const std::vector<webkit_glue::PasswordForm>& visible_forms) {}
-
   // Notification that the page has an OpenSearch description document.
   virtual void PageHasOSDD(RenderViewHost* render_view_host,
                            int32 page_id, const GURL& doc_url,
@@ -785,6 +541,11 @@
   // associated with the owning render view host.
   virtual WebPreferences GetWebkitPrefs();
 
+  // Notification the user has made a gesture while focus was on the
+  // page. This is used to avoid uninitiated user downloads (aka carpet
+  // bombing), see DownloadRequestLimiter for details.
+  virtual void OnUserGesture() {}
+
   // Notification from the renderer host that blocked UI event occurred.
   // This happens when there are tab-modal dialogs. In this case, the
   // notification is needed to let us draw attention to the dialog (i.e.
@@ -822,8 +583,8 @@
                                 int maximum_percent,
                                 bool remember) {}
 
-  // Update the content restrictions, i.e. disable print/copy.
-  virtual void UpdateContentRestrictions(int restrictions) {}
+  // Notification that a worker process has crashed.
+  void WorkerCrashed() {}
 
  protected:
   virtual ~RenderViewHostDelegate() {}
diff --git a/chrome/browser/renderer_host/render_widget_helper.cc b/chrome/browser/renderer_host/render_widget_helper.cc
index 0ea4f8c..3d808df 100644
--- a/chrome/browser/renderer_host/render_widget_helper.cc
+++ b/chrome/browser/renderer_host/render_widget_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -102,7 +102,7 @@
   for (;;) {
     UpdateMsgProxy* proxy = NULL;
     {
-      AutoLock lock(pending_paints_lock_);
+      base::AutoLock lock(pending_paints_lock_);
 
       UpdateMsgProxyMap::iterator it = pending_paints_.find(render_widget_id);
       if (it != pending_paints_.end()) {
@@ -139,9 +139,17 @@
 
   UpdateMsgProxy* proxy = NULL;
   {
-    AutoLock lock(pending_paints_lock_);
+    base::AutoLock lock(pending_paints_lock_);
 
-    UpdateMsgProxyMap::value_type new_value(render_widget_id, NULL);
+    // Visual Studio 2010 has problems converting NULL to the null pointer for
+    // std::pair.  See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
+    // It will work if we pass nullptr.
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+    RenderWidgetHelper::UpdateMsgProxy* null_proxy = nullptr;
+#else
+    RenderWidgetHelper::UpdateMsgProxy* null_proxy = NULL;
+#endif
+    UpdateMsgProxyMap::value_type new_value(render_widget_id, null_proxy);
 
     // We expect only a single PaintRect message at a time.  Optimize for the
     // case that we don't already have an entry by using the 'insert' method.
@@ -169,7 +177,7 @@
 
   // Remove the proxy from the map now that we are going to handle it normally.
   {
-    AutoLock lock(pending_paints_lock_);
+    base::AutoLock lock(pending_paints_lock_);
 
     UpdateMsgProxyMap::iterator it = pending_paints_.find(msg.routing_id());
     DCHECK(it != pending_paints_.end());
@@ -200,10 +208,7 @@
 }
 
 void RenderWidgetHelper::CreateNewWindow(
-    int opener_id,
-    bool user_gesture,
-    WindowContainerType window_container_type,
-    const string16& frame_name,
+    const ViewHostMsg_CreateWindow_Params& params,
     base::ProcessHandle render_process,
     int* route_id) {
   *route_id = GetNextRoutingID();
@@ -215,18 +220,16 @@
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       NewRunnableMethod(
-          this, &RenderWidgetHelper::OnCreateWindowOnUI, opener_id, *route_id,
-          window_container_type, frame_name));
+          this, &RenderWidgetHelper::OnCreateWindowOnUI, params, *route_id));
 }
 
 void RenderWidgetHelper::OnCreateWindowOnUI(
-    int opener_id,
-    int route_id,
-    WindowContainerType window_container_type,
-    string16 frame_name) {
-  RenderViewHost* host = RenderViewHost::FromID(render_process_id_, opener_id);
+    const ViewHostMsg_CreateWindow_Params& params,
+    int route_id) {
+  RenderViewHost* host =
+      RenderViewHost::FromID(render_process_id_, params.opener_id);
   if (host)
-    host->CreateNewWindow(route_id, window_container_type, frame_name);
+    host->CreateNewWindow(route_id, params);
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
@@ -250,14 +253,14 @@
           popup_type));
 }
 
-void RenderWidgetHelper::CreateNewFullscreenWidget(
-    int opener_id, WebKit::WebPopupType popup_type, int* route_id) {
+void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id,
+                                                   int* route_id) {
   *route_id = GetNextRoutingID();
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       NewRunnableMethod(
           this, &RenderWidgetHelper::OnCreateFullscreenWidgetOnUI,
-          opener_id, *route_id, popup_type));
+          opener_id, *route_id));
 }
 
 void RenderWidgetHelper::OnCreateWidgetOnUI(
@@ -267,16 +270,16 @@
     host->CreateNewWidget(route_id, popup_type);
 }
 
-void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(
-    int opener_id, int route_id, WebKit::WebPopupType popup_type) {
+void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(int opener_id,
+                                                      int route_id) {
   RenderViewHost* host = RenderViewHost::FromID(render_process_id_, opener_id);
   if (host)
-    host->CreateNewFullscreenWidget(route_id, popup_type);
+    host->CreateNewFullscreenWidget(route_id);
 }
 
 #if defined(OS_MACOSX)
 TransportDIB* RenderWidgetHelper::MapTransportDIB(TransportDIB::Id dib_id) {
-  AutoLock locked(allocated_dibs_lock_);
+  base::AutoLock locked(allocated_dibs_lock_);
 
   const std::map<TransportDIB::Id, int>::iterator
       i = allocated_dibs_.find(dib_id);
@@ -300,13 +303,13 @@
 
   if (cache_in_browser) {
     // Keep a copy of the file descriptor around
-    AutoLock locked(allocated_dibs_lock_);
+    base::AutoLock locked(allocated_dibs_lock_);
     allocated_dibs_[shared_memory->id()] = dup(result->fd);
   }
 }
 
 void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) {
-  AutoLock locked(allocated_dibs_lock_);
+  base::AutoLock locked(allocated_dibs_lock_);
 
   const std::map<TransportDIB::Id, int>::iterator
     i = allocated_dibs_.find(dib_id);
diff --git a/chrome/browser/renderer_host/render_widget_helper.h b/chrome/browser/renderer_host/render_widget_helper.h
index 882a349..3ac67ad 100644
--- a/chrome/browser/renderer_host/render_widget_helper.h
+++ b/chrome/browser/renderer_host/render_widget_helper.h
@@ -13,10 +13,10 @@
 #include "base/hash_tables.h"
 #include "base/process.h"
 #include "base/ref_counted.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "chrome/common/window_container_type.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
 
 namespace IPC {
 class Message;
@@ -27,8 +27,10 @@
 }
 
 class ResourceDispatcherHost;
+struct ViewHostMsg_CreateWindow_Params;
 struct ViewMsg_ClosePage_Params;
 
+
 // Instantiated per RenderProcessHost to provide various optimizations on
 // behalf of a RenderWidgetHost.  This class bridges between the IO thread
 // where the RenderProcessHost's MessageFilter lives and the UI thread where
@@ -121,18 +123,13 @@
   // Called on the IO thread when a UpdateRect message is received.
   void DidReceiveUpdateMsg(const IPC::Message& msg);
 
-  void CreateNewWindow(int opener_id,
-                       bool user_gesture,
-                       WindowContainerType window_container_type,
-                       const string16& frame_name,
+  void CreateNewWindow(const ViewHostMsg_CreateWindow_Params& params,
                        base::ProcessHandle render_process,
                        int* route_id);
   void CreateNewWidget(int opener_id,
                        WebKit::WebPopupType popup_type,
                        int* route_id);
-  void CreateNewFullscreenWidget(int opener_id,
-                                 WebKit::WebPopupType popup_type,
-                                 int* route_id);
+  void CreateNewFullscreenWidget(int opener_id, int* route_id);
 
 #if defined(OS_MACOSX)
   // Called on the IO thread to handle the allocation of a TransportDIB.  If
@@ -167,10 +164,8 @@
   void OnDispatchUpdateMsg(UpdateMsgProxy* proxy);
 
   // Called on the UI thread to finish creating a window.
-  void OnCreateWindowOnUI(int opener_id,
-                          int route_id,
-                          WindowContainerType window_container_type,
-                          string16 frame_name);
+  void OnCreateWindowOnUI(const ViewHostMsg_CreateWindow_Params& params,
+                          int route_id);
 
   // Called on the IO thread after a window was created on the UI thread.
   void OnCreateWindowOnIO(int route_id);
@@ -180,10 +175,8 @@
                           int route_id,
                           WebKit::WebPopupType popup_type);
 
-  // Called on the UI thread to create a full screen widget.
-  void OnCreateFullscreenWidgetOnUI(int opener_id,
-                                    int route_id,
-                                    WebKit::WebPopupType popup_type);
+  // Called on the UI thread to create a fullscreen widget.
+  void OnCreateFullscreenWidgetOnUI(int opener_id, int route_id);
 
   // Called on the IO thread to cancel resource requests for the render widget.
   void OnCancelResourceRequests(int render_widget_id);
@@ -197,7 +190,7 @@
 
   // On OSX we keep file descriptors to all the allocated DIBs around until
   // the renderer frees them.
-  Lock allocated_dibs_lock_;
+  base::Lock allocated_dibs_lock_;
   std::map<TransportDIB::Id, int> allocated_dibs_;
 #endif
 
@@ -205,7 +198,7 @@
   // The UpdateMsgProxy objects are not owned by this map.  (See UpdateMsgProxy
   // for details about how the lifetime of instances are managed.)
   UpdateMsgProxyMap pending_paints_;
-  Lock pending_paints_lock_;
+  base::Lock pending_paints_lock_;
 
   int render_process_id_;
 
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 7a7a5d6..13e5da7 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/renderer_host/render_widget_host.h"
 
-#include "app/keyboard_codes.h"
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
@@ -15,7 +14,6 @@
 #include "chrome/browser/renderer_host/backing_store_manager.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_widget_helper.h"
-#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/result_codes.h"
@@ -23,7 +21,8 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "webkit/glue/webcursor.h"
 #include "webkit/plugins/npapi/webplugin.h"
 
@@ -32,8 +31,8 @@
 #endif
 
 #if defined (OS_MACOSX)
-#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/mac/WebScreenInfoFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebScreenInfoFactory.h"
 #endif
 
 using base::Time;
@@ -74,7 +73,6 @@
       renderer_accessible_(false),
       view_(NULL),
       process_(process),
-      painting_observer_(NULL),
       routing_id_(routing_id),
       is_loading_(false),
       is_hidden_(false),
@@ -175,8 +173,10 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnMsgGetScreenInfo)
     IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnMsgGetWindowRect)
     IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnMsgGetRootWindowRect)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SetPluginImeEnabled,
-                        OnMsgSetPluginImeEnabled)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_PluginFocusChanged,
+                        OnMsgPluginFocusChanged)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_StartPluginIme,
+                        OnMsgStartPluginIme)
     IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateFakePluginWindowHandle,
                         OnAllocateFakePluginWindowHandle)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyFakePluginWindowHandle,
@@ -286,7 +286,15 @@
     return;
   }
 
+#if !defined(OS_MACOSX)
   gfx::Size new_size = view_->GetViewBounds().size();
+#else
+  // When UI scaling is enabled on OS X, allocate a smaller bitmap and
+  // pixel-scale it up.
+  // TODO(thakis): Use pixel size on mac and set UI scale in renderer.
+  // http://crbug.com/31960
+  gfx::Size new_size(view_->GetViewCocoaBounds().size());
+#endif
   gfx::Rect reserved_rect = view_->reserved_contents_rect();
 
   // Avoid asking the RenderWidget to resize to its current size, since it
@@ -542,8 +550,8 @@
     return;
 
   if (key_event.type == WebKeyboardEvent::Char &&
-      (key_event.windowsKeyCode == app::VKEY_RETURN ||
-       key_event.windowsKeyCode == app::VKEY_SPACE)) {
+      (key_event.windowsKeyCode == ui::VKEY_RETURN ||
+       key_event.windowsKeyCode == ui::VKEY_SPACE)) {
     OnUserGesture();
   }
 
@@ -798,20 +806,27 @@
 }
 
 void RenderWidgetHost::OnMsgPaintAtSizeAck(int tag, const gfx::Size& size) {
-  if (painting_observer_) {
-    painting_observer_->WidgetDidReceivePaintAtSizeAck(this, tag, size);
-  }
+  PaintAtSizeAckDetails details = {tag, size};
+  gfx::Size size_details = size;
+  NotificationService::current()->Notify(
+      NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
+      Source<RenderWidgetHost>(this),
+      Details<PaintAtSizeAckDetails>(&details));
 }
 
 void RenderWidgetHost::OnMsgUpdateRect(
     const ViewHostMsg_UpdateRect_Params& params) {
   TimeTicks paint_start = TimeTicks::Now();
 
-  if (paint_observer_.get())
-    paint_observer_->RenderWidgetHostWillPaint(this);
+  NotificationService::current()->Notify(
+      NotificationType::RENDER_WIDGET_HOST_WILL_PAINT,
+      Source<RenderWidgetHost>(this),
+      NotificationService::NoDetails());
 
   // Update our knowledge of the RenderWidget's size.
   current_size_ = params.view_size;
+  // Update our knowledge of the RenderWidget's scroll offset.
+  last_scroll_offset_ = params.scroll_offset;
 
   bool is_resize_ack =
       ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
@@ -900,8 +915,10 @@
     }
   }
 
-  if (paint_observer_.get())
-    paint_observer_->RenderWidgetHostDidPaint(this);
+  NotificationService::current()->Notify(
+      NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
+      Source<RenderWidgetHost>(this),
+      NotificationService::NoDetails());
 
   // If we got a resize ack, then perhaps we have another resize to send?
   if (is_resize_ack && view_) {
@@ -910,8 +927,10 @@
     WasResized();
   }
 
-  if (painting_observer_)
-    painting_observer_->WidgetDidUpdateBackingStore(this);
+  NotificationService::current()->Notify(
+      NotificationType::RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
+      Source<RenderWidgetHost>(this),
+      NotificationService::NoDetails());
 
   // Log the time delta for processing a paint message.
   TimeDelta delta = TimeTicks::Now() - paint_start;
@@ -950,6 +969,11 @@
 
     ProcessKeyboardEventAck(type, processed);
   }
+  // This is used only for testing.
+  NotificationService::current()->Notify(
+      NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
+      Source<RenderWidgetHost>(this),
+      Details<int>(&type));
 }
 
 void RenderWidgetHost::ProcessWheelAck() {
@@ -1023,7 +1047,7 @@
 void RenderWidgetHost::OnMsgGetWindowRect(gfx::NativeViewId window_id,
                                           gfx::Rect* results) {
   if (view_) {
-    *results = view_->GetWindowRect();
+    *results = view_->GetViewBounds();
   }
 }
 
@@ -1034,8 +1058,14 @@
   }
 }
 
-void RenderWidgetHost::OnMsgSetPluginImeEnabled(bool enabled, int plugin_id) {
-  view_->SetPluginImeEnabled(enabled, plugin_id);
+void RenderWidgetHost::OnMsgPluginFocusChanged(bool focused, int plugin_id) {
+  if (view_)
+    view_->PluginFocusChanged(focused, plugin_id);
+}
+
+void RenderWidgetHost::OnMsgStartPluginIme() {
+  if (view_)
+    view_->StartPluginIme();
 }
 
 void RenderWidgetHost::OnAllocateFakePluginWindowHandle(
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 73d7fa4..f13828a 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -19,13 +19,13 @@
 #include "chrome/common/edit_command.h"
 #include "chrome/common/native_web_keyboard_event.h"
 #include "chrome/common/property_bag.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "ipc/ipc_channel.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextInputType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextInputType.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 namespace gfx {
 class Rect;
@@ -42,7 +42,6 @@
 class PaintObserver;
 class RenderProcessHost;
 class RenderWidgetHostView;
-class RenderWidgetHostPaintingObserver;
 class TransportDIB;
 class WebCursor;
 struct ViewHostMsg_UpdateRect_Params;
@@ -124,12 +123,13 @@
 class RenderWidgetHost : public IPC::Channel::Listener,
                          public IPC::Channel::Sender {
  public:
-  // An interface that gets called before and after a paint.
-  class PaintObserver {
-   public:
-    virtual ~PaintObserver() {}
-    virtual void RenderWidgetHostWillPaint(RenderWidgetHost* rhw) = 0;
-    virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh) = 0;
+  // Used as the details object for a
+  // RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK notification.
+  struct PaintAtSizeAckDetails {
+    // The tag that was passed to the PaintAtSize() call that triggered this
+    // ack.
+    int tag;
+    gfx::Size size;
   };
 
   // routing_id can be MSG_ROUTING_NONE, in which case the next available
@@ -148,27 +148,12 @@
   int routing_id() const { return routing_id_; }
   bool renderer_accessible() { return renderer_accessible_; }
 
-  // Set the PaintObserver on this object. Takes ownership.
-  void set_paint_observer(PaintObserver* paint_observer) {
-    paint_observer_.reset(paint_observer);
-  }
-
   // Returns the property bag for this widget, where callers can add extra data
   // they may wish to associate with it. Returns a pointer rather than a
   // reference since the PropertyAccessors expect this.
   const PropertyBag* property_bag() const { return &property_bag_; }
   PropertyBag* property_bag() { return &property_bag_; }
 
-  // The painting observer that will be called for paint events. This
-  // pointer's ownership will remain with the caller and must remain valid
-  // until this class is destroyed or the observer is replaced.
-  RenderWidgetHostPaintingObserver* painting_observer() const {
-    return painting_observer_;
-  }
-  void set_painting_observer(RenderWidgetHostPaintingObserver* observer) {
-    painting_observer_ = observer;
-  }
-
   // Called when a renderer object already been created for this host, and we
   // just need to be attached to it. Used for window.open, <select> dropdown
   // menus, and other times when the renderer initiates creating an object.
@@ -219,10 +204,10 @@
   // web widget to match the |page_size| and then returns the bitmap
   // scaled so it matches the |desired_size|, so that the scaling
   // happens on the rendering thread.  When the bitmap is ready, the
-  // renderer sends a PaintAtSizeACK to this host, and the painting
-  // observer is notified.  Note that this bypasses most of the update
-  // logic that is normally invoked, and doesn't put the results into
-  // the backing store.
+  // renderer sends a PaintAtSizeACK to this host, and a
+  // RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK notification is issued.
+  // Note that this bypasses most of the update logic that is normally invoked,
+  // and doesn't put the results into the backing store.
   void PaintAtSize(TransportDIB::Handle dib_handle,
                    int tag,
                    const gfx::Size& page_size,
@@ -408,6 +393,8 @@
   // Activate deferred plugin handles.
   void ActivateDeferredPluginHandles();
 
+  const gfx::Size& last_scroll_offset() const { return last_scroll_offset_; }
+
  protected:
   // Internal implementation of the public Forward*Event() methods.
   void ForwardInputEvent(const WebKit::WebInputEvent& input_event,
@@ -495,7 +482,8 @@
                           WebKit::WebScreenInfo* results);
   void OnMsgGetWindowRect(gfx::NativeViewId window_id, gfx::Rect* results);
   void OnMsgGetRootWindowRect(gfx::NativeViewId window_id, gfx::Rect* results);
-  void OnMsgSetPluginImeEnabled(bool enabled, int plugin_id);
+  void OnMsgPluginFocusChanged(bool focused, int plugin_id);
+  void OnMsgStartPluginIme();
   void OnAllocateFakePluginWindowHandle(bool opaque,
                                         bool root,
                                         gfx::PluginWindowHandle* id);
@@ -554,10 +542,6 @@
   // Stores random bits of data for others to associate with this object.
   PropertyBag property_bag_;
 
-  // Observer that will be called for paint events. This may be NULL. The
-  // pointer is not owned by this class.
-  RenderWidgetHostPaintingObserver* painting_observer_;
-
   // The ID of the corresponding object in the Renderer Instance.
   int routing_id_;
 
@@ -637,9 +621,6 @@
   // This timer runs to check if time_when_considered_hung_ has past.
   base::OneShotTimer<RenderWidgetHost> hung_renderer_timer_;
 
-  // Optional observer that listens for notifications of painting.
-  scoped_ptr<PaintObserver> paint_observer_;
-
   // Flag to detect recursive calls to GetBackingStore().
   bool in_get_backing_store_;
 
@@ -687,6 +668,9 @@
 
   std::vector<gfx::PluginWindowHandle> deferred_plugin_handles_;
 
+  // The last scroll offset of the render widget.
+  gfx::Size last_scroll_offset_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost);
 };
 
diff --git a/chrome/browser/renderer_host/render_widget_host_painting_observer.h b/chrome/browser/renderer_host/render_widget_host_painting_observer.h
deleted file mode 100644
index 3c6c867..0000000
--- a/chrome/browser/renderer_host/render_widget_host_painting_observer.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_PAINTING_OBSERVER_H_
-#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_PAINTING_OBSERVER_H_
-#pragma once
-
-class BackingStore;
-class RenderWidgetHost;
-
-namespace gfx {
-class Size;
-}
-
-// This class can be used to observe painting events for a RenderWidgetHost.
-// Its primary goal in Chrome is to allow thumbnails to be generated.
-class RenderWidgetHostPaintingObserver {
- public:
-  // Indicates the RenderWidgetHost is about to destroy the backing store. The
-  // backing store will still be valid when this call is made.
-  virtual void WidgetWillDestroyBackingStore(RenderWidgetHost* widget,
-                                             BackingStore* backing_store) = 0;
-
-  // Indicates that the RenderWidgetHost just updated the backing store.
-  virtual void WidgetDidUpdateBackingStore(RenderWidgetHost* widget) = 0;
-
-  // This notifies the painting observer that a PaintAtSizeACK was
-  // received.
-  virtual void WidgetDidReceivePaintAtSizeAck(
-      RenderWidgetHost* widget,
-      int tag,
-      const gfx::Size& size) = 0;
-
- protected:
-  virtual ~RenderWidgetHostPaintingObserver() {}
-};
-
-#endif  // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_PAINTING_OBSERVER_H_
diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc
index 758a5bd..546854e 100644
--- a/chrome/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc
@@ -2,20 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/keyboard_codes.h"
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/shared_memory.h"
 #include "base/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/renderer_host/backing_store.h"
-#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h"
 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/test/testing_profile.h"
-#include "gfx/canvas_skia.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/gfx/canvas_skia.h"
 
 using base::TimeDelta;
 
@@ -125,6 +126,12 @@
     return bounds_;
   }
 
+#if defined(OS_MACOSX)
+  virtual gfx::Rect GetViewCocoaBounds() const {
+    return bounds_;
+  }
+#endif
+
  protected:
   gfx::Rect bounds_;
   DISALLOW_COPY_AND_ASSIGN(TestView);
@@ -200,11 +207,8 @@
 
 // MockPaintingObserver --------------------------------------------------------
 
-class MockPaintingObserver : public RenderWidgetHostPaintingObserver {
+class MockPaintingObserver : public NotificationObserver {
  public:
-  void WidgetWillDestroyBackingStore(RenderWidgetHost* widget,
-                                     BackingStore* backing_store) {}
-  void WidgetDidUpdateBackingStore(RenderWidgetHost* widget) {}
   void WidgetDidReceivePaintAtSizeAck(RenderWidgetHost* host,
                                       int tag,
                                       const gfx::Size& size) {
@@ -213,6 +217,20 @@
     size_ = size;
   }
 
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    if (type ==
+        NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK) {
+      RenderWidgetHost::PaintAtSizeAckDetails* size_ack_details =
+          Details<RenderWidgetHost::PaintAtSizeAckDetails>(details).ptr();
+      WidgetDidReceivePaintAtSizeAck(
+          Source<RenderWidgetHost>(source).ptr(),
+          size_ack_details->tag,
+          size_ack_details->size);
+    }
+  }
+
   MockRenderWidgetHost* host() const { return host_; }
   int tag() const { return tag_; }
   gfx::Size size() const { return size_; }
@@ -264,7 +282,7 @@
   void SimulateKeyboardEvent(WebInputEvent::Type type) {
     NativeWebKeyboardEvent key_event;
     key_event.type = type;
-    key_event.windowsKeyCode = app::VKEY_L;  // non-null made up value.
+    key_event.windowsKeyCode = ui::VKEY_L;  // non-null made up value.
     host_->ForwardKeyboardEvent(key_event);
   }
 
@@ -549,15 +567,18 @@
   EXPECT_TRUE(
       process_->sink().GetUniqueMessageMatching(ViewMsg_PaintAtSize::ID));
 
+  NotificationRegistrar registrar;
   MockPaintingObserver observer;
-  host_->set_painting_observer(&observer);
+  registrar.Add(
+      &observer,
+      NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
+      Source<RenderWidgetHost>(host_.get()));
 
   host_->OnMsgPaintAtSizeAck(kPaintAtSizeTag, gfx::Size(20, 30));
   EXPECT_EQ(host_.get(), observer.host());
   EXPECT_EQ(kPaintAtSizeTag, observer.tag());
   EXPECT_EQ(20, observer.size().width());
   EXPECT_EQ(30, observer.size().height());
-  host_->set_painting_observer(NULL);
 }
 
 TEST_F(RenderWidgetHostTest, HandleKeyEventsWeSent) {
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 2d4b1ea..332c264 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -15,12 +15,12 @@
 
 #include "app/surface/transport_dib.h"
 #include "base/process_util.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextInputType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextInputType.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 
 namespace gfx {
 class Rect;
@@ -82,7 +82,7 @@
 
   // Perform all the initialization steps necessary for this object to represent
   // a full screen window.
-  virtual void InitAsFullscreen(RenderWidgetHostView* parent_host_view) = 0;
+  virtual void InitAsFullscreen() = 0;
 
   // Returns the associated RenderWidgetHost.
   virtual RenderWidgetHost* GetRenderWidgetHost() const = 0;
@@ -188,8 +188,11 @@
   // |flag| is false, the view participates in the key-view chain as normal.
   virtual void SetTakesFocusOnlyOnMouseDown(bool flag) = 0;
 
-  // Get the view's position on the screen.
-  virtual gfx::Rect GetWindowRect() = 0;
+  // Retrieve the bounds of the view, in cocoa view coordinates.
+  // If the UI scale factor is 2, |GetViewBounds()| will return a size of e.g.
+  // (400, 300) in pixels, while this method will return (200, 150).
+  // Even though this returns an gfx::Rect, the result is NOT IN PIXELS.
+  virtual gfx::Rect GetViewCocoaBounds() const = 0;
 
   // Get the view's window's position on the screen.
   virtual gfx::Rect GetRootWindowRect() = 0;
@@ -208,8 +211,11 @@
   // Informs the view that its containing window's frame changed.
   virtual void WindowFrameChanged() = 0;
 
-  // Start or stop plugin IME for the given plugin.
-  virtual void SetPluginImeEnabled(bool enabled, int plugin_id) = 0;
+  // Informs the view that a plugin gained or lost focus.
+  virtual void PluginFocusChanged(bool focused, int plugin_id) = 0;
+
+  // Start plugin IME.
+  virtual void StartPluginIme() = 0;
 
   // Does any event handling necessary for plugin IME; should be called after
   // the plugin has already had a chance to process the event. If plugin IME is
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 2d10e4e..7fce046 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 
 // If this gets included after the gtk headers, then a bunch of compiler
 // errors happen because of a "#define Status int" in Xlib.h, which interacts
-// badly with URLRequestStatus::Status.
+// badly with net::URLRequestStatus::Status.
 #include "chrome/common/render_messages.h"
 
 #include <cairo/cairo.h>
@@ -18,8 +18,6 @@
 #include <algorithm>
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/x11_util.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -27,17 +25,19 @@
 #include "base/string_number_conversions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/renderer_host/backing_store_x.h"
 #include "chrome/browser/renderer_host/gtk_im_context_wrapper.h"
 #include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/native_web_keyboard_event.h"
-#include "gfx/gtk_preserve_window.h"
-#include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/gtk/WebInputEventFactory.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_preserve_window.h"
 #include "webkit/glue/webaccessibility.h"
 #include "webkit/glue/webcursor_gtk_data.h"
 #include "webkit/plugins/npapi/webplugin.h"
@@ -489,11 +489,11 @@
       is_showing_context_menu_(false),
       overlay_color_(0),
       overlay_animation_(this),
-      parent_host_view_(NULL),
       parent_(NULL),
       is_popup_first_mouse_release_(true),
       was_focused_before_grab_(false),
       do_x_grab_(false),
+      is_fullscreen_(false),
       dragged_at_horizontal_edge_(0),
       dragged_at_vertical_edge_(0) {
   host_->set_view(this);
@@ -504,31 +504,71 @@
 }
 
 void RenderWidgetHostViewGtk::InitAsChild() {
-  view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this));
-  // |im_context_| must be created after creating |view_| widget.
-  im_context_.reset(new GtkIMContextWrapper(this));
-  // |key_bindings_handler_| must be created after creating |view_| widget.
-  key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get()));
-  plugin_container_manager_.set_host_widget(view_.get());
-
-#if defined(OS_CHROMEOS)
-  tooltip_window_.reset(new views::TooltipWindowGtk(view_.get()));
-#endif  // defined(OS_CHROMEOS)
-
+  DoSharedInit();
   overlay_animation_.SetDuration(kFadeEffectDuration);
   overlay_animation_.SetSlideDuration(kFadeEffectDuration);
-
   gtk_widget_show(view_.get());
 }
 
 void RenderWidgetHostViewGtk::InitAsPopup(
     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
-  DoInitAsPopup(parent_host_view, GTK_WINDOW_POPUP, pos, false);
+  // If we aren't a popup, then |window| will be leaked.
+  DCHECK(IsPopup());
+
+  DoSharedInit();
+  parent_ = parent_host_view->GetNativeView();
+  GtkWindow* window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_POPUP));
+  gtk_container_add(GTK_CONTAINER(window), view_.get());
+  DoPopupOrFullscreenInit(window, pos);
+
+  // The underlying X window needs to be created and mapped by the above code
+  // before we can grab the input devices.
+  if (NeedsInputGrab()) {
+    // Grab all input for the app. If a click lands outside the bounds of the
+    // popup, WebKit will notice and destroy us. Before doing this we need
+    // to ensure that the the popup is added to the browser's window group,
+    // to allow for the grabs to work correctly.
+    gtk_window_group_add_window(gtk_window_get_group(
+        GTK_WINDOW(gtk_widget_get_toplevel(parent_))), window);
+    gtk_grab_add(view_.get());
+
+    // We need for the application to do an X grab as well. However if the app
+    // already has an X grab (as in the case of extension popup), an app grab
+    // will suffice.
+    do_x_grab_ = !gdk_pointer_is_grabbed();
+
+    // Now grab all of X's input.
+    if (do_x_grab_) {
+      gdk_pointer_grab(
+          parent_->window,
+          TRUE,  // Only events outside of the window are reported with respect
+                 // to |parent_->window|.
+          static_cast<GdkEventMask>(GDK_BUTTON_PRESS_MASK |
+              GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
+          NULL,
+          NULL,
+          GDK_CURRENT_TIME);
+      // We grab keyboard events too so things like alt+tab are eaten.
+      gdk_keyboard_grab(parent_->window, TRUE, GDK_CURRENT_TIME);
+    }
+  }
 }
 
-void RenderWidgetHostViewGtk::InitAsFullscreen(
-    RenderWidgetHostView* parent_host_view) {
-  DoInitAsPopup(parent_host_view, GTK_WINDOW_TOPLEVEL, gfx::Rect(), true);
+void RenderWidgetHostViewGtk::InitAsFullscreen() {
+  DoSharedInit();
+
+  is_fullscreen_ = true;
+  GtkWindow* window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
+  gtk_window_set_decorated(window, FALSE);
+  gtk_window_fullscreen(window);
+  gtk_container_add(GTK_CONTAINER(window), view_.get());
+
+  // Try to move and resize the window to cover the screen in case the window
+  // manager doesn't support _NET_WM_STATE_FULLSCREEN.
+  GdkScreen* screen = gtk_window_get_screen(window);
+  gfx::Rect bounds(
+      0, 0, gdk_screen_get_width(screen), gdk_screen_get_height(screen));
+  DoPopupOrFullscreenInit(window, bounds);
 }
 
 RenderWidgetHost* RenderWidgetHostViewGtk::GetRenderWidgetHost() const {
@@ -692,16 +732,18 @@
 }
 
 void RenderWidgetHostViewGtk::Destroy() {
-  if (IsPopup()) {
-    if (do_x_grab_) {
-      // Undo the X grab.
-      GdkDisplay* display = gtk_widget_get_display(parent_);
-      gdk_display_pointer_ungrab(display, GDK_CURRENT_TIME);
-      gdk_display_keyboard_ungrab(display, GDK_CURRENT_TIME);
-    }
-    gtk_widget_destroy(gtk_widget_get_parent(view_.get()));
+  if (do_x_grab_) {
+    // Undo the X grab.
+    GdkDisplay* display = gtk_widget_get_display(parent_);
+    gdk_display_pointer_ungrab(display, GDK_CURRENT_TIME);
+    gdk_display_keyboard_ungrab(display, GDK_CURRENT_TIME);
   }
 
+  // If this is a popup or fullscreen widget, then we need to destroy the window
+  // that we created to hold it.
+  if (IsPopup() || is_fullscreen_)
+    gtk_widget_destroy(gtk_widget_get_parent(view_.get()));
+
   // Remove |view_| from all containers now, so nothing else can hold a
   // reference to |view_|'s widget except possibly a gtk signal handler if
   // this code is currently executing within the context of a gtk signal
@@ -759,14 +801,43 @@
   return popup_type_ == WebKit::WebPopupTypeSelect;
 }
 
-bool RenderWidgetHostViewGtk::IsPopup() {
+bool RenderWidgetHostViewGtk::IsPopup() const {
   return popup_type_ != WebKit::WebPopupTypeNone;
 }
 
+void RenderWidgetHostViewGtk::DoSharedInit() {
+  view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this));
+  im_context_.reset(new GtkIMContextWrapper(this));
+  key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get()));
+  plugin_container_manager_.set_host_widget(view_.get());
+#if defined(OS_CHROMEOS)
+  tooltip_window_.reset(new views::TooltipWindowGtk(view_.get()));
+#endif
+}
+
+void RenderWidgetHostViewGtk::DoPopupOrFullscreenInit(GtkWindow* window,
+                                                      const gfx::Rect& bounds) {
+  requested_size_ = bounds.size();
+  host_->WasResized();
+
+  gtk_widget_set_size_request(
+      view_.get(),
+      std::min(requested_size_.width(), kMaxWindowWidth),
+      std::min(requested_size_.height(), kMaxWindowHeight));
+
+  // Don't allow the window to be resized. This also forces the window to
+  // shrink down to the size of its child contents.
+  gtk_window_set_resizable(window, FALSE);
+  gtk_window_set_default_size(window, -1, -1);
+  gtk_window_move(window, bounds.x(), bounds.y());
+
+  gtk_widget_show_all(GTK_WIDGET(window));
+}
+
 BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
     const gfx::Size& size) {
   return new BackingStoreX(host_, size,
-                           x11_util::GetVisualFromGtkWidget(view_.get()),
+                           ui::GetVisualFromGtkWidget(view_.get()),
                            gtk_widget_get_visual(view_.get())->depth);
 }
 
@@ -858,7 +929,7 @@
         // In the common case, use XCopyArea. We don't draw more than once, so
         // we don't need to double buffer.
         backing_store->XShowRect(gfx::Point(0, 0),
-            paint_rect, x11_util::GetX11WindowFromGtkWidget(view_.get()));
+            paint_rect, ui::GetX11WindowFromGtkWidget(view_.get()));
       } else {
         // If the grey blend is showing, we make two drawing calls. Use double
         // buffering to prevent flicker. Use CairoShowRect because XShowRect
@@ -957,94 +1028,6 @@
     gdk_cursor_unref(gdk_cursor);
 }
 
-void RenderWidgetHostViewGtk::DoInitAsPopup(
-    RenderWidgetHostView* parent_host_view,
-    GtkWindowType window_type,
-    const gfx::Rect& pos,
-    bool is_fullscreen) {
-  // If we are not a popup, then popup will be leaked.
-  DCHECK(IsPopup());
-
-  parent_host_view_ = parent_host_view;
-  parent_ = parent_host_view->GetNativeView();
-  GtkWidget* popup = gtk_window_new(window_type);
-  gtk_window_set_decorated(GTK_WINDOW(popup), FALSE);
-  view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this));
-  // |im_context_| must be created after creating |view_| widget.
-  im_context_.reset(new GtkIMContextWrapper(this));
-  // |key_bindings_handler_| must be created after creating |view_| widget.
-  key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get()));
-  plugin_container_manager_.set_host_widget(view_.get());
-
-#if defined(OS_CHROMEOS)
-  tooltip_window_.reset(new views::TooltipWindowGtk(view_.get()));
-#endif  // defined(OS_CHROMEOS)
-
-  gtk_container_add(GTK_CONTAINER(popup), view_.get());
-
-  if (is_fullscreen) {
-    // Set the request size to the size of the screen.
-    // TODO(boliu): Make sure this works for multi-monitor set ups and move this
-    // to some utility function.
-    GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(popup));
-    requested_size_ = gfx::Size(
-        std::min(gdk_screen_get_width(screen), kMaxWindowWidth),
-        std::min(gdk_screen_get_height(screen), kMaxWindowHeight));
-  } else {
-    requested_size_ = gfx::Size(std::min(pos.width(), kMaxWindowWidth),
-                                std::min(pos.height(), kMaxWindowHeight));
-  }
-  host_->WasResized();
-
-  gtk_widget_set_size_request(view_.get(), requested_size_.width(),
-                              requested_size_.height());
-  // Don't allow the window to be resized. This also forces the window to
-  // shrink down to the size of its child contents.
-  gtk_window_set_resizable(GTK_WINDOW(popup), FALSE);
-  gtk_window_set_default_size(GTK_WINDOW(popup), -1, -1);
-  gtk_window_move(GTK_WINDOW(popup), pos.x(), pos.y());
-  if (is_fullscreen) {
-    gtk_window_fullscreen(GTK_WINDOW(popup));
-  }
-
-  gtk_widget_show_all(popup);
-
-  // If we are not activatable, we don't want to grab keyboard input,
-  // and webkit will manage our destruction.
-  // For unknown reason, calling gtk_grab_add() before realizing the widget may
-  // cause an assertion failure. See http://crbug.com/51834. So we do it after
-  // showing the popup.
-  if (NeedsInputGrab()) {
-    // Grab all input for the app. If a click lands outside the bounds of the
-    // popup, WebKit will notice and destroy us. Before doing this we need
-    // to ensure that the the popup is added to the browser's window group,
-    // to allow for the grabs to work correctly.
-    gtk_window_group_add_window(gtk_window_get_group(
-        GTK_WINDOW(gtk_widget_get_toplevel(parent_))), GTK_WINDOW(popup));
-    gtk_grab_add(view_.get());
-
-    // We need for the application to do an X grab as well. However if the app
-    // already has an X grab (as in the case of extension popup), an app grab
-    // will suffice.
-    do_x_grab_ = !gdk_pointer_is_grabbed();
-
-    // Now grab all of X's input.
-    if (do_x_grab_) {
-      gdk_pointer_grab(
-          parent_->window,
-          TRUE,  // Only events outside of the window are reported with respect
-                 // to |parent_->window|.
-          static_cast<GdkEventMask>(GDK_BUTTON_PRESS_MASK |
-              GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
-          NULL,
-          NULL,
-          GDK_CURRENT_TIME);
-      // We grab keyboard events too so things like alt+tab are eaten.
-      gdk_keyboard_grab(parent_->window, TRUE, GDK_CURRENT_TIME);
-    }
-  }
-}
-
 void RenderWidgetHostViewGtk::CreatePluginContainer(
     gfx::PluginWindowHandle id) {
   plugin_container_manager_.CreatePluginContainer(id);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index fcc5e75..b354a7b 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,17 +8,17 @@
 
 #include <gdk/gdk.h>
 
-#include <vector>
 #include <string>
+#include <vector>
 
 #include "base/scoped_ptr.h"
 #include "base/time.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/webcursor.h"
 #include "webkit/plugins/npapi/gtk_plugin_container_manager.h"
 
@@ -54,7 +54,7 @@
   // RenderWidgetHostView implementation.
   virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
                            const gfx::Rect& pos);
-  virtual void InitAsFullscreen(RenderWidgetHostView* parent_host_view);
+  virtual void InitAsFullscreen();
   virtual RenderWidgetHost* GetRenderWidgetHost() const;
   virtual void DidBecomeSelected();
   virtual void WasHidden();
@@ -128,18 +128,18 @@
 
   // Returns whether this render view is a popup (<select> dropdown or
   // autocomplete window).
-  bool IsPopup();
+  bool IsPopup() const;
+
+  // Do initialization needed by all InitAs*() methods.
+  void DoSharedInit();
+
+  // Do initialization needed just by InitAsPopup() and InitAsFullscreen().
+  // We move and resize |window| to |bounds| and show it and its contents.
+  void DoPopupOrFullscreenInit(GtkWindow* window, const gfx::Rect& bounds);
 
   // Update the display cursor for the render view.
   void ShowCurrentCursor();
 
-  // Helper method for InitAsPopup() and InitAsFullscreen().
-  void DoInitAsPopup(
-      RenderWidgetHostView* parent_host_view,
-      GtkWindowType window_type,
-      const gfx::Rect& pos,  // Ignored if is_fullscreen is true.
-      bool is_fullscreen);
-
   // The model object.
   RenderWidgetHost* host_;
 
@@ -159,6 +159,7 @@
 
   // Whether we are currently loading.
   bool is_loading_;
+
   // The cursor for the page. This is passed up from the renderer.
   WebCursor current_cursor_;
 
@@ -181,14 +182,10 @@
   // value affects the alpha we use for |overlay_color_|.
   ui::SlideAnimation overlay_animation_;
 
-  // Variables used only for popups --------------------------------------------
-  // Our parent widget.
-  RenderWidgetHostView* parent_host_view_;
-  // The native view of our parent, equivalent to
-  // parent_host_view_->GetNativeView().
+  // The native view of our parent widget.  Used only for popups.
   GtkWidget* parent_;
-  // We ignore the first mouse release on popups.  This allows the popup to
-  // stay open.
+
+  // We ignore the first mouse release on popups so the popup will remain open.
   bool is_popup_first_mouse_release_;
 
   // Whether or not this widget was focused before shadowed by another widget.
@@ -200,6 +197,9 @@
   // for extension popups.
   bool do_x_grab_;
 
+  // Is the widget fullscreen?
+  bool is_fullscreen_;
+
   // A convenience wrapper object for GtkIMContext;
   scoped_ptr<GtkIMContextWrapper> im_context_;
 
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index d538758..160197c 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -19,7 +19,7 @@
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/ui/cocoa/base_view.h"
 #include "chrome/common/edit_command.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
 #include "webkit/glue/webcursor.h"
 
 @class AcceleratedPluginView;
@@ -120,8 +120,11 @@
   // etc.
   EditCommands editCommands_;
 
-  // The plugin for which IME is currently enabled (-1 if not enabled).
-  int pluginImeIdentifier_;
+  // The plugin that currently has focus (-1 if no plugin has focus).
+  int focusedPluginIdentifier_;
+
+  // Whether or not plugin IME is currently enabled active.
+  BOOL pluginImeActive_;
 }
 
 @property(assign, nonatomic) NSRect caretRect;
@@ -141,8 +144,10 @@
 - (void)cancelComposition;
 // Confirm ongoing composition.
 - (void)confirmComposition;
-// Enables or disables plugin IME for the given plugin.
-- (void)setPluginImeEnabled:(BOOL)enabled forPlugin:(int)pluginId;
+// Enables or disables plugin IME.
+- (void)setPluginImeActive:(BOOL)active;
+// Updates the current plugin focus state.
+- (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId;
 // Evaluates the event in the context of plugin IME, if plugin IME is enabled.
 // Returns YES if the event was handled.
 - (BOOL)postProcessEventForPluginIme:(NSEvent*)event;
@@ -177,7 +182,7 @@
   // Implementation of RenderWidgetHostView:
   virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
                            const gfx::Rect& pos);
-  virtual void InitAsFullscreen(RenderWidgetHostView* parent_host_view);
+  virtual void InitAsFullscreen();
   virtual RenderWidgetHost* GetRenderWidgetHost() const;
   virtual void DidBecomeSelected();
   virtual void WasHidden();
@@ -208,7 +213,8 @@
   virtual void SelectionChanged(const std::string& text);
   virtual BackingStore* AllocBackingStore(const gfx::Size& size);
   virtual void SetTakesFocusOnlyOnMouseDown(bool flag);
-  virtual gfx::Rect GetWindowRect();
+  // See comment in RenderWidgetHostView!
+  virtual gfx::Rect GetViewCocoaBounds() const;
   virtual gfx::Rect GetRootWindowRect();
   virtual void SetActive(bool active);
   virtual void SetWindowVisibility(bool visible);
@@ -219,7 +225,8 @@
   virtual void OnAccessibilityNotifications(
       const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params);
 
-  virtual void SetPluginImeEnabled(bool enabled, int plugin_id);
+  virtual void PluginFocusChanged(bool focused, int plugin_id);
+  virtual void StartPluginIme();
   virtual bool PostProcessEventForPluginIme(
       const NativeWebKeyboardEvent& event);
 
@@ -269,8 +276,8 @@
 
   void SetTextInputActive(bool active);
 
-  // Sends confirmed plugin IME text back to the renderer.
-  void PluginImeCompositionConfirmed(const string16& text, int plugin_id);
+  // Sends completed plugin IME notification and text back to the renderer.
+  void PluginImeCompositionCompleted(const string16& text, int plugin_id);
 
   const std::string& selected_text() const { return selected_text_; }
 
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 7c803a7..943c8cc 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -38,8 +38,8 @@
 #include "chrome/common/render_messages.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkColor.h"
-#include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 #include "webkit/glue/webaccessibility.h"
 #include "webkit/plugins/npapi/webplugin.h"
 #import "third_party/mozilla/ComplexTextInputPanel.h"
@@ -63,6 +63,7 @@
 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
 - (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv;
 - (void)cancelChildPopups;
+- (void)checkForPluginImeCancellation;
 @end
 
 // This API was published since 10.6. Provide the declaration so it can be
@@ -91,8 +92,8 @@
       std::max(0, std::min(static_cast<int>(lroundf(255.0f * b)), 255));
 }
 
-// Extract underline information from an attributed string.
-// Mostly copied from third_party/WebKit/WebKit/mac/WebView/WebHTMLView.mm
+// Extract underline information from an attributed string. Mostly copied from
+// third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm
 void ExtractUnderlines(
     NSAttributedString* string,
     std::vector<WebKit::WebCompositionUnderline>* underlines) {
@@ -134,6 +135,39 @@
   TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag);
 }
 
+// Adjusts an NSRect in Cocoa screen coordinates to have an origin in the upper
+// left of the primary screen (Carbon coordinates), and stuffs it into a
+// gfx::Rect.
+gfx::Rect FlipNSRectToRectScreen(const NSRect& rect) {
+  gfx::Rect new_rect(NSRectToCGRect(rect));
+  if ([[NSScreen screens] count] > 0) {
+    new_rect.set_y([[[NSScreen screens] objectAtIndex:0] frame].size.height -
+                   new_rect.y() - new_rect.height());
+  }
+  return new_rect;
+}
+
+// Returns the window that visually contains the given view. This is different
+// from [view window] in the case of tab dragging, where the view's owning
+// window is a floating panel attached to the actual browser window that the tab
+// is visually part of.
+NSWindow* ApparentWindowForView(NSView* view) {
+  // TODO(shess): In case of !window, the view has been removed from
+  // the view hierarchy because the tab isn't main.  Could retrieve
+  // the information from the main tab for our window.
+  NSWindow* enclosing_window = [view window];
+
+  // See if this is a tab drag window. The width check is to distinguish that
+  // case from extension popup windows.
+  NSWindow* ancestor_window = [enclosing_window parentWindow];
+  if (ancestor_window && (NSWidth([enclosing_window frame]) ==
+                          NSWidth([ancestor_window frame]))) {
+    enclosing_window = ancestor_window;
+  }
+
+  return enclosing_window;
+}
+
 }  // namespace
 
 // AcceleratedPluginView ------------------------------------------------------
@@ -191,6 +225,9 @@
   // view's size, since it's required on the displaylink thread.
   NSSize cachedSize_;
 
+  // Rects that should show web content rather than plugin content.
+  scoped_nsobject<NSArray> cutoutRects_;
+
   // -globalFrameDidChange: can be called recursively, this counts how often it
   // holds the CGL lock.
   int globalFrameDidChangeCGLLockCount_;
@@ -200,6 +237,12 @@
                          pluginHandle:(gfx::PluginWindowHandle)pluginHandle;
 - (void)drawView;
 
+// Sets the list of rectangles that should show the web page, rather than the
+// accelerated plugin. This is used to simulate the iframe-based trick that web
+// pages have long used to show web content above windowed plugins on Windows
+// and Linux.
+- (void)setCutoutRects:(NSArray*)cutout_rects;
+
 // Updates the number of swap buffers calls that have been requested.
 // This is currently called with non-zero values only in response to
 // updates from the GPU process. For accelerated plugins, all zeros
@@ -328,6 +371,10 @@
   CGLUnlockContext(cglContext_);
 }
 
+- (void)setCutoutRects:(NSArray*)cutout_rects {
+  cutoutRects_.reset([cutout_rects copy]);
+}
+
 - (void)updateSwapBuffersCount:(uint64)count
                   fromRenderer:(int)rendererId
                        routeId:(int32)routeId {
@@ -361,9 +408,36 @@
     int dirtyRectCount;
     [self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount];
 
+    [NSGraphicsContext saveGraphicsState];
+
+    // Mask out any cutout rects--somewhat counterintuitively cutout rects are
+    // places where clearColor is *not* drawn. The trick is that drawing nothing
+    // lets the parent view (i.e., the web page) show through, whereas drawing
+    // clearColor punches a hole in the window (letting OpenGL show through).
+    if ([cutoutRects_.get() count] > 0) {
+      NSBezierPath* path = [NSBezierPath bezierPath];
+      // Trace the bounds clockwise to give a base clip rect of the whole view.
+      NSRect bounds = [self bounds];
+      [path moveToPoint:bounds.origin];
+      [path lineToPoint:NSMakePoint(NSMinX(bounds), NSMaxY(bounds))];
+      [path lineToPoint:NSMakePoint(NSMaxX(bounds), NSMaxY(bounds))];
+      [path lineToPoint:NSMakePoint(NSMaxX(bounds), NSMinY(bounds))];
+      [path closePath];
+
+      // Then trace each cutout rect counterclockwise to remove that region from
+      // the clip region.
+      for (NSValue* rectWrapper in cutoutRects_.get()) {
+        [path appendBezierPathWithRect:[rectWrapper rectValue]];
+      }
+
+      [path addClip];
+    }
+
     // Punch a hole so that the OpenGL view shows through.
     [[NSColor clearColor] set];
     NSRectFillList(dirtyRects, dirtyRectCount);
+
+    [NSGraphicsContext restoreGraphicsState];
   }
 
   [self drawView];
@@ -558,8 +632,7 @@
   [cocoa_view_ setFrame:initial_frame];
 }
 
-void RenderWidgetHostViewMac::InitAsFullscreen(
-    RenderWidgetHostView* parent_host_view) {
+void RenderWidgetHostViewMac::InitAsFullscreen() {
   NOTIMPLEMENTED() << "Full screen not implemented on Mac";
 }
 
@@ -648,6 +721,15 @@
       }
       NSRect new_rect([cocoa_view_ flipRectToNSRect:rect]);
       [view setFrame:new_rect];
+      NSMutableArray* cutout_rects =
+          [NSMutableArray arrayWithCapacity:geom.cutout_rects.size()];
+      for (unsigned int i = 0; i < geom.cutout_rects.size(); ++i) {
+        // Convert to NSRect, and flip vertically.
+        NSRect cutout_rect = NSRectFromCGRect(geom.cutout_rects[i].ToCGRect());
+        cutout_rect.origin.y = new_rect.size.height - NSMaxY(cutout_rect);
+        [cutout_rects addObject:[NSValue valueWithRect:cutout_rect]];
+      }
+      [view setCutoutRects:cutout_rects];
       [view setNeedsDisplay:YES];
     }
 
@@ -688,7 +770,17 @@
 }
 
 gfx::Rect RenderWidgetHostViewMac::GetViewBounds() const {
-  return [cocoa_view_ flipNSRectToRect:[cocoa_view_ bounds]];
+  // TODO(shess): In case of !window, the view has been removed from
+  // the view hierarchy because the tab isn't main.  Could retrieve
+  // the information from the main tab for our window.
+  NSWindow* enclosing_window = ApparentWindowForView(cocoa_view_);
+  if (!enclosing_window)
+    return gfx::Rect();
+
+  NSRect bounds = [cocoa_view_ bounds];
+  bounds = [cocoa_view_ convertRect:bounds toView:nil];
+  bounds.origin = [enclosing_window convertBaseToScreen:bounds.origin];
+  return FlipNSRectToRectScreen(bounds);
 }
 
 void RenderWidgetHostViewMac::UpdateCursor(const WebCursor& cursor) {
@@ -881,8 +973,12 @@
   }
 }
 
-void RenderWidgetHostViewMac::SetPluginImeEnabled(bool enabled, int plugin_id) {
-  [cocoa_view_ setPluginImeEnabled:(enabled ? YES : NO) forPlugin:plugin_id];
+void RenderWidgetHostViewMac::PluginFocusChanged(bool focused, int plugin_id) {
+  [cocoa_view_ pluginFocusChanged:(focused ? YES : NO) forPlugin:plugin_id];
+}
+
+void RenderWidgetHostViewMac::StartPluginIme() {
+  [cocoa_view_ setPluginImeActive:YES];
 }
 
 bool RenderWidgetHostViewMac::PostProcessEventForPluginIme(
@@ -898,10 +994,10 @@
   return false;
 }
 
-void RenderWidgetHostViewMac::PluginImeCompositionConfirmed(
+void RenderWidgetHostViewMac::PluginImeCompositionCompleted(
     const string16& text, int plugin_id) {
   if (render_widget_host_) {
-    render_widget_host_->Send(new ViewMsg_PluginImeCompositionConfirmed(
+    render_widget_host_->Send(new ViewMsg_PluginImeCompositionCompleted(
         render_widget_host_->routing_id(), text, plugin_id));
   }
 }
@@ -1190,55 +1286,8 @@
   return 1 == [user_defaults integerForKey:@"voiceOverOnOffKey"];
 }
 
-namespace {
-
-// Adjusts an NSRect in Cocoa screen coordinates to have an origin in the upper
-// left of the primary screen (Carbon coordinates), and stuffs it into a
-// gfx::Rect.
-gfx::Rect FlipNSRectToRectScreen(const NSRect& rect) {
-  gfx::Rect new_rect(NSRectToCGRect(rect));
-  if ([[NSScreen screens] count] > 0) {
-    new_rect.set_y([[[NSScreen screens] objectAtIndex:0] frame].size.height -
-                   new_rect.y() - new_rect.height());
-  }
-  return new_rect;
-}
-
-// Returns the window that visually contains the given view. This is different
-// from [view window] in the case of tab dragging, where the view's owning
-// window is a floating panel attached to the actual browser window that the tab
-// is visually part of.
-NSWindow* ApparentWindowForView(NSView* view) {
-  // TODO(shess): In case of !window, the view has been removed from
-  // the view hierarchy because the tab isn't main.  Could retrieve
-  // the information from the main tab for our window.
-  NSWindow* enclosing_window = [view window];
-
-  // See if this is a tab drag window. The width check is to distinguish that
-  // case from extension popup windows.
-  NSWindow* ancestor_window = [enclosing_window parentWindow];
-  if (ancestor_window && (NSWidth([enclosing_window frame]) ==
-                          NSWidth([ancestor_window frame]))) {
-    enclosing_window = ancestor_window;
-  }
-
-  return enclosing_window;
-}
-
-}  // namespace
-
-gfx::Rect RenderWidgetHostViewMac::GetWindowRect() {
-  // TODO(shess): In case of !window, the view has been removed from
-  // the view hierarchy because the tab isn't main.  Could retrieve
-  // the information from the main tab for our window.
-  NSWindow* enclosing_window = ApparentWindowForView(cocoa_view_);
-  if (!enclosing_window)
-    return gfx::Rect();
-
-  NSRect bounds = [cocoa_view_ bounds];
-  bounds = [cocoa_view_ convertRect:bounds toView:nil];
-  bounds.origin = [enclosing_window convertBaseToScreen:bounds.origin];
-  return FlipNSRectToRectScreen(bounds);
+gfx::Rect RenderWidgetHostViewMac::GetViewCocoaBounds() const {
+  return gfx::Rect(NSRectToCGRect([cocoa_view_ bounds]));
 }
 
 gfx::Rect RenderWidgetHostViewMac::GetRootWindowRect() {
@@ -1258,6 +1307,8 @@
     render_widget_host_->SetActive(active);
   if (HasFocus())
     SetTextInputActive(active);
+  if (!active)
+    [cocoa_view_ setPluginImeActive:NO];
 }
 
 void RenderWidgetHostViewMac::SetWindowVisibility(bool visible) {
@@ -1271,7 +1322,7 @@
   if (render_widget_host_) {
     render_widget_host_->Send(new ViewMsg_WindowFrameChanged(
         render_widget_host_->routing_id(), GetRootWindowRect(),
-        GetWindowRect()));
+        GetViewBounds()));
   }
 }
 
@@ -1331,7 +1382,7 @@
     canBeKeyView_ = YES;
     takesFocusOnlyOnMouseDown_ = NO;
     closeOnDeactivate_ = NO;
-    pluginImeIdentifier_ = -1;
+    focusedPluginIdentifier_ = -1;
   }
   return self;
 }
@@ -1487,11 +1538,17 @@
   hasEditCommands_ = NO;
   editCommands_.clear();
 
+  // Before doing anything with a key down, check to see if plugin IME has been
+  // cancelled, since the plugin host needs to be informed of that before
+  // receiving the keydown.
+  if ([theEvent type] == NSKeyDown)
+    [self checkForPluginImeCancellation];
+
   // Sends key down events to input method first, then we can decide what should
   // be done according to input method's feedback.
   // If a plugin is active, bypass this step since events are forwarded directly
   // to the plugin IME.
-  if (pluginImeIdentifier_ == -1)
+  if (focusedPluginIdentifier_ == -1)
     [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
 
   handlingKeyDown_ = NO;
@@ -1907,10 +1964,39 @@
       action == @selector(copy:) ||
       action == @selector(copyToFindPboard:) ||
       action == @selector(paste:) ||
-      action == @selector(pasteAsPlainText:)) {
+      action == @selector(pasteAsPlainText:) ||
+      action == @selector(checkSpelling:)) {
     return renderWidgetHostView_->render_widget_host_->IsRenderView();
   }
 
+  if (action == @selector(toggleContinuousSpellChecking:)) {
+    RenderViewHost::CommandState state;
+    state.is_enabled = false;
+    state.checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED;
+    if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
+      state = static_cast<RenderViewHost*>(
+          renderWidgetHostView_->render_widget_host_)->
+              GetStateForCommand(RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK);
+    }
+    if ([(id)item respondsToSelector:@selector(setState:)]) {
+      NSCellStateValue checked_state =
+          RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED;
+      switch (state.checked_state) {
+        case RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED:
+          checked_state = NSOffState;
+          break;
+        case RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED:
+          checked_state = NSOnState;
+          break;
+        case RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED:
+          checked_state = NSMixedState;
+          break;
+      }
+      [(id)item setState:checked_state];
+    }
+    return state.is_enabled;
+  }
+
   return editCommand_helper_->IsMenuItemEnabled(action, self);
 }
 
@@ -2062,6 +2148,7 @@
 // other spelling panel methods. This is probably because Apple assumes that the
 // the spelling panel will be used with an NSText, which will automatically
 // catch this and advance to the next word for you. Thanks Apple.
+// This is also called from the Edit -> Spelling -> Check Spelling menu item.
 - (void)checkSpelling:(id)sender {
   RenderWidgetHostViewMac* thisHostView = [self renderWidgetHostViewMac];
   thisHostView->GetRenderWidgetHost()->AdvanceToNextMisspelling();
@@ -2084,6 +2171,13 @@
       SpellCheckerPlatform::SpellingPanelVisible());
 }
 
+- (void)toggleContinuousSpellChecking:(id)sender {
+  if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
+    static_cast<RenderViewHost*>(renderWidgetHostView_->render_widget_host_)->
+      ToggleSpellCheck();
+  }
+}
+
 // END Spellchecking methods
 
 // Below is the nasty tooltip stuff -- copied from WebKit's WebHTMLView.mm
@@ -2399,7 +2493,7 @@
 // nil when the caret is in non-editable content or password box to avoid
 // making input methods do their work.
 - (NSTextInputContext *)inputContext {
-  if (pluginImeIdentifier_ != -1)
+  if (focusedPluginIdentifier_ != -1)
     return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
 
   switch(renderWidgetHostView_->text_input_type_) {
@@ -2632,33 +2726,30 @@
   [self cancelComposition];
 }
 
-- (void)setPluginImeEnabled:(BOOL)enabled forPlugin:(int)pluginId {
-  if ((enabled && pluginId == pluginImeIdentifier_) ||
-      (!enabled && pluginId != pluginImeIdentifier_))
+- (void)setPluginImeActive:(BOOL)active {
+  if (active == pluginImeActive_)
     return;
 
-  // If IME was already active then either it is being cancelled, or the plugin
-  // changed; either way the current input needs to be cleared.
-  if (pluginImeIdentifier_ != -1)
-    [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelInput];
+  pluginImeActive_ = active;
+  if (!active) {
+    [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelComposition];
+    renderWidgetHostView_->PluginImeCompositionCompleted(
+        string16(), focusedPluginIdentifier_);
+  }
+}
 
-  pluginImeIdentifier_ = enabled ? pluginId : -1;
+- (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId {
+  if (focused)
+    focusedPluginIdentifier_ = pluginId;
+  else if (focusedPluginIdentifier_ == pluginId)
+    focusedPluginIdentifier_ = -1;
+
+  // Whenever plugin focus changes, plugin IME resets.
+  [self setPluginImeActive:NO];
 }
 
 - (BOOL)postProcessEventForPluginIme:(NSEvent*)event {
-  if (pluginImeIdentifier_ == -1)
-    return false;
-
-  // ComplexTextInputPanel only works on 10.6+.
-  static BOOL sImeSupported = NO;
-  static BOOL sHaveCheckedSupport = NO;
-  if (!sHaveCheckedSupport) {
-    int32 major, minor, bugfix;
-    base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
-    sImeSupported = major > 10 || (major == 10 && minor > 5);
-    sHaveCheckedSupport = YES;
-  }
-  if (!sImeSupported)
+  if (!pluginImeActive_)
     return false;
 
   ComplexTextInputPanel* inputPanel =
@@ -2667,12 +2758,22 @@
   BOOL handled = [inputPanel interpretKeyEvent:event
                                         string:&composited_string];
   if (composited_string) {
-    renderWidgetHostView_->PluginImeCompositionConfirmed(
-        base::SysNSStringToUTF16(composited_string), pluginImeIdentifier_);
+    renderWidgetHostView_->PluginImeCompositionCompleted(
+        base::SysNSStringToUTF16(composited_string), focusedPluginIdentifier_);
+    pluginImeActive_ = NO;
   }
   return handled;
 }
 
+- (void)checkForPluginImeCancellation {
+  if (pluginImeActive_ &&
+      ![[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition]) {
+    renderWidgetHostView_->PluginImeCompositionCompleted(
+        string16(), focusedPluginIdentifier_);
+    pluginImeActive_ = NO;
+  }
+}
+
 - (ViewID)viewID {
   return VIEW_ID_TAB_CONTAINER_FOCUS_VIEW;
 }
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index a36c88f..95b16d6 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -10,6 +10,7 @@
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/cocoa/test_event_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/plugins/npapi/webplugin.h"
 
 class RenderWidgetHostViewMacTest : public RenderViewHostTestHarness {
  public:
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc
index a8049cf..cd38138 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc
@@ -7,9 +7,6 @@
 #include <algorithm>
 #include <string>
 
-#include "app/keyboard_code_conversion_gtk.h"
-#include "app/l10n_util.h"
-#include "app/x11_util.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -17,29 +14,64 @@
 #include "base/string_number_conversions.h"
 #include "base/task.h"
 #include "base/time.h"
+#include "chrome/browser/renderer_host/backing_store_skia.h"
 #include "chrome/browser/renderer_host/backing_store_x.h"
 #include "chrome/browser/renderer_host/render_widget_host.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/native_web_keyboard_event.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/result_codes.h"
-#include "gfx/canvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
-#include "views/event.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/gtk/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "views/events/event.h"
+#include "views/ime/ime_context.h"
 #include "views/widget/widget.h"
 #include "views/widget/widget_gtk.h"
 
 static const int kMaxWindowWidth = 4000;
 static const int kMaxWindowHeight = 4000;
-static const char* kRenderWidgetHostViewKey = "__RENDER_WIDGET_HOST_VIEW__";
+static const char kRenderWidgetHostViewKey[] = "__RENDER_WIDGET_HOST_VIEW__";
+static const char kBackingStoreSkiaSwitch[] = "use-backing-store-skia";
+
+// Copied from third_party/WebKit/Source/WebCore/page/EventHandler.cpp
+//
+// Match key code of composition keydown event on windows.
+// IE sends VK_PROCESSKEY which has value 229;
+//
+// Please refer to following documents for detals:
+// - Virtual-Key Codes
+//   http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx
+// - How the IME System Works
+//   http://msdn.microsoft.com/en-us/library/cc194848.aspx
+// - ImmGetVirtualKey Function
+//   http://msdn.microsoft.com/en-us/library/dd318570(VS.85).aspx
+static const int kCompositionEventKeyCode = 229;
 
 using WebKit::WebInputEventFactory;
 using WebKit::WebMouseWheelEvent;
 using WebKit::WebTouchEvent;
 
+const char RenderWidgetHostViewViews::kViewClassName[] =
+    "browser/renderer_host/RenderWidgetHostViewViews";
+
 namespace {
 
+bool UsingBackingStoreSkia() {
+  static bool decided = false;
+  static bool use_skia = false;
+  if (!decided) {
+    CommandLine* cmdline = CommandLine::ForCurrentProcess();
+    use_skia = (cmdline && cmdline->HasSwitch(kBackingStoreSkiaSwitch));
+    decided = true;
+  }
+
+  return use_skia;
+}
+
 int WebInputEventFlagsFromViewsEvent(const views::Event& event) {
   int modifiers = 0;
 
@@ -57,14 +89,14 @@
 
 WebKit::WebTouchPoint::State TouchPointStateFromEvent(
     const views::TouchEvent* event) {
-  switch (event->GetType()) {
-    case views::Event::ET_TOUCH_PRESSED:
+  switch (event->type()) {
+    case ui::ET_TOUCH_PRESSED:
       return WebKit::WebTouchPoint::StatePressed;
-    case views::Event::ET_TOUCH_RELEASED:
+    case ui::ET_TOUCH_RELEASED:
       return WebKit::WebTouchPoint::StateReleased;
-    case views::Event::ET_TOUCH_MOVED:
+    case ui::ET_TOUCH_MOVED:
       return WebKit::WebTouchPoint::StateMoved;
-    case views::Event::ET_TOUCH_CANCELLED:
+    case ui::ET_TOUCH_CANCELLED:
       return WebKit::WebTouchPoint::StateCancelled;
     default:
       return WebKit::WebTouchPoint::StateUndefined;
@@ -73,14 +105,14 @@
 
 WebKit::WebInputEvent::Type TouchEventTypeFromEvent(
     const views::TouchEvent* event) {
-  switch (event->GetType()) {
-    case views::Event::ET_TOUCH_PRESSED:
+  switch (event->type()) {
+    case ui::ET_TOUCH_PRESSED:
       return WebKit::WebInputEvent::TouchStart;
-    case views::Event::ET_TOUCH_RELEASED:
+    case ui::ET_TOUCH_RELEASED:
       return WebKit::WebInputEvent::TouchEnd;
-    case views::Event::ET_TOUCH_MOVED:
+    case ui::ET_TOUCH_MOVED:
       return WebKit::WebInputEvent::TouchMove;
-    case views::Event::ET_TOUCH_CANCELLED:
+    case ui::ET_TOUCH_CANCELLED:
       return WebKit::WebInputEvent::TouchCancel;
     default:
       return WebKit::WebInputEvent::Undefined;
@@ -111,6 +143,149 @@
 
 }  // namespace
 
+class IMEContextHandler : public views::CommitTextListener,
+                          public views::CompositionListener,
+                          public views::ForwardKeyEventListener {
+ public:
+  explicit IMEContextHandler(
+      RenderWidgetHostViewViews* host_view)
+    : host_view_(host_view),
+      is_enabled_(false),
+      is_focused_(false),
+      ime_context_(views::IMEContext::Create(host_view_)) {
+    ime_context_->set_commit_text_listener(this);
+    ime_context_->set_composition_listener(this);
+    ime_context_->set_forward_key_event_listener(this);
+  }
+
+  // IMEContext Listeners implementation
+  virtual void OnCommitText(views::IMEContext* sender,
+                            const string16& text) {
+    DCHECK(ime_context_ == sender);
+
+    RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
+    if (host) {
+      SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::RawKeyDown);
+      host->ImeConfirmComposition(text);
+      SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::KeyUp);
+    }
+  }
+
+  virtual void OnStartComposition(views::IMEContext* sender) {
+    DCHECK(ime_context_ == sender);
+  }
+
+  virtual void OnEndComposition(views::IMEContext* sender) {
+    DCHECK(ime_context_ == sender);
+
+    RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
+    if (host)
+      host->ImeCancelComposition();
+  }
+
+  virtual void OnSetComposition(views::IMEContext* sender,
+      const string16& text,
+      const views::CompositionAttributeList& attributes,
+      uint32 cursor_pos) {
+    DCHECK(ime_context_ == sender);
+
+    RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
+    if (host) {
+      SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::RawKeyDown);
+
+      // Cast CompositonAttribute to WebKit::WebCompositionUnderline directly,
+      // becasue CompositionAttribute is duplicated from
+      // WebKit::WebCompositionUnderline.
+      const std::vector<WebKit::WebCompositionUnderline>& underlines =
+          reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+              attributes);
+      host->ImeSetComposition(text, underlines, cursor_pos, cursor_pos);
+      SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::KeyUp);
+    }
+  }
+
+  virtual void OnForwardKeyEvent(views::IMEContext* sender,
+                                 const views::KeyEvent& event) {
+    DCHECK(ime_context_ == sender);
+
+    host_view_->ForwardKeyEvent(event);
+  }
+
+  bool FilterKeyEvent(const views::KeyEvent& event) {
+    return is_enabled_ && ime_context_->FilterKeyEvent(event);
+  }
+
+  void Focus() {
+    if (!is_focused_) {
+      ime_context_->Focus();
+      is_focused_ = true;
+    }
+
+    // Enables RenderWidget's IME related events, so that we can be notified
+    // when WebKit wants to enable or disable IME.
+    RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
+    if (host)
+      host->SetInputMethodActive(true);
+  }
+
+  void Blur() {
+    if (is_focused_) {
+      ime_context_->Blur();
+      is_focused_ = false;
+    }
+
+    // Disable RenderWidget's IME related events to save bandwidth.
+    RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
+    if (host)
+      host->SetInputMethodActive(false);
+  }
+
+  void ImeUpdateTextInputState(WebKit::WebTextInputType type,
+                               const gfx::Rect& caret_rect) {
+    bool enable =
+        (type != WebKit::WebTextInputTypeNone) &&
+        (type != WebKit::WebTextInputTypePassword);
+
+    if (is_enabled_ != enable) {
+      is_enabled_ = enable;
+      if (is_focused_) {
+        if (is_enabled_)
+          ime_context_->Focus();
+        else
+          ime_context_->Blur();
+      }
+    }
+
+    if (is_enabled_) {
+      gfx::Point p(caret_rect.origin());
+      views::View::ConvertPointToScreen(host_view_, &p);
+
+      ime_context_->SetCursorLocation(gfx::Rect(p, caret_rect.size()));
+    }
+  }
+
+  void Reset() {
+    ime_context_->Reset();
+  }
+
+ private:
+  void SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::Type type) {
+    NativeWebKeyboardEvent fake_event;
+    fake_event.windowsKeyCode = kCompositionEventKeyCode;
+    fake_event.skip_in_browser = true;
+    fake_event.type = type;
+    host_view_->ForwardWebKeyboardEvent(fake_event);
+  }
+
+ private:
+  RenderWidgetHostViewViews* host_view_;
+  bool is_enabled_;
+  bool is_focused_;
+  scoped_ptr<views::IMEContext> ime_context_;
+
+  DISALLOW_COPY_AND_ASSIGN(IMEContextHandler);
+};
+
 // static
 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
     RenderWidgetHost* widget) {
@@ -125,19 +300,17 @@
       native_cursor_(NULL),
       is_showing_context_menu_(false),
       visually_deemphasized_(false),
-      touch_event_()
-    {
+      touch_event_() {
   SetFocusable(true);
   host_->set_view(this);
 }
 
 RenderWidgetHostViewViews::~RenderWidgetHostViewViews() {
-  RenderViewGone(base::TERMINATION_STATUS_NORMAL_TERMINATION,
-                 ResultCodes::NORMAL_EXIT);
 }
 
 void RenderWidgetHostViewViews::InitAsChild() {
   Show();
+  ime_context_.reset(new IMEContextHandler(this));
 }
 
 RenderWidgetHost* RenderWidgetHostViewViews::GetRenderWidgetHost() const {
@@ -151,8 +324,7 @@
   NOTIMPLEMENTED();
 }
 
-void RenderWidgetHostViewViews::InitAsFullscreen(
-    RenderWidgetHostView* parent_host_view) {
+void RenderWidgetHostViewViews::InitAsFullscreen() {
   NOTIMPLEMENTED();
 }
 
@@ -187,7 +359,7 @@
   if (requested_size_.width() != width ||
       requested_size_.height() != height) {
     requested_size_ = gfx::Size(width, height);
-    SetBounds(gfx::Rect(x(), y(), width, height));
+    SetBounds(x(), y(), width, height);
     host_->WasResized();
   }
 }
@@ -251,13 +423,11 @@
 void RenderWidgetHostViewViews::ImeUpdateTextInputState(
     WebKit::WebTextInputType type,
     const gfx::Rect& caret_rect) {
-  // TODO(bryeung): im_context_->UpdateInputMethodState(type, caret_rect);
-  NOTIMPLEMENTED();
+  ime_context_->ImeUpdateTextInputState(type, caret_rect);
 }
 
 void RenderWidgetHostViewViews::ImeCancelComposition() {
-  // TODO(bryeung): im_context_->CancelComposition();
-  NOTIMPLEMENTED();
+  ime_context_->Reset();
 }
 
 void RenderWidgetHostViewViews::DidUpdateBackingStore(
@@ -286,6 +456,7 @@
     else
       SchedulePaint(rect, false);
   }
+  invalid_rect_ = invalid_rect_.Intersect(bounds());
 }
 
 void RenderWidgetHostViewViews::RenderViewGone(base::TerminationStatus status,
@@ -295,8 +466,12 @@
 }
 
 void RenderWidgetHostViewViews::Destroy() {
-  // TODO(anicolao): deal with any special popup cleanup
-  NOTIMPLEMENTED();
+  // host_'s destruction brought us here, null it out so we don't use it
+  host_ = NULL;
+
+  if (parent())
+    parent()->RemoveChildView(this);
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
 void RenderWidgetHostViewViews::SetTooltipText(const std::wstring& tip) {
@@ -324,15 +499,24 @@
 
 BackingStore* RenderWidgetHostViewViews::AllocBackingStore(
     const gfx::Size& size) {
-  return new BackingStoreX(host_, size,
-                           x11_util::GetVisualFromGtkWidget(native_view()),
-                           gtk_widget_get_visual(native_view())->depth);
+  gfx::NativeView nview = GetInnerNativeView();
+  if (!nview)
+    return NULL;
+
+  if (UsingBackingStoreSkia()) {
+    return new BackingStoreSkia(host_, size);
+  } else {
+    return new BackingStoreX(host_, size,
+                             ui::GetVisualFromGtkWidget(nview),
+                             gtk_widget_get_visual(nview)->depth);
+  }
 }
 
-gfx::NativeView RenderWidgetHostViewViews::native_view() const {
+gfx::NativeView RenderWidgetHostViewViews::GetInnerNativeView() const {
   // TODO(sad): Ideally this function should be equivalent to GetNativeView, and
   // WidgetGtk-specific function call should not be necessary.
-  views::WidgetGtk* widget = static_cast<views::WidgetGtk*>(GetWidget());
+  const views::WidgetGtk* widget =
+      static_cast<const views::WidgetGtk*>(GetWidget());
   return widget ? widget->window_contents() : NULL;
 }
 
@@ -355,7 +539,8 @@
   // Paint a "hole" in the canvas so that the render of the web page is on
   // top of whatever else has already been painted in the views hierarchy.
   // Later views might still get to paint on top.
-  canvas->FillRectInt(SK_ColorBLACK, 0, 0, kMaxWindowWidth, kMaxWindowHeight,
+  canvas->FillRectInt(SK_ColorBLACK, 0, 0,
+                      bounds().width(), bounds().height(),
                       SkXfermode::kClear_Mode);
 
   // Don't do any painting if the GPU process is rendering directly
@@ -365,7 +550,7 @@
     return;
   }
 
-  GdkWindow* window = native_view()->window;
+  GdkWindow* window = GetInnerNativeView()->window;
   DCHECK(!about_to_validate_and_paint_);
 
   // TODO(anicolao): get the damage somehow
@@ -375,8 +560,7 @@
   ConvertPointToWidget(this, &origin);
 
   about_to_validate_and_paint_ = true;
-  BackingStoreX* backing_store = static_cast<BackingStoreX*>(
-      host_->GetBackingStore(true));
+  BackingStore* backing_store = host_->GetBackingStore(true);
   // Calling GetBackingStore maybe have changed |invalid_rect_|...
   about_to_validate_and_paint_ = false;
 
@@ -391,9 +575,15 @@
       if (!visually_deemphasized_) {
         // In the common case, use XCopyArea. We don't draw more than once, so
         // we don't need to double buffer.
-        backing_store->XShowRect(origin,
-            paint_rect, x11_util::GetX11WindowFromGdkWindow(window));
-      } else {
+
+        if (UsingBackingStoreSkia()) {
+          static_cast<BackingStoreSkia*>(backing_store)->SkiaShowRect(
+              gfx::Point(paint_rect.x(), paint_rect.y()), canvas);
+        } else {
+          static_cast<BackingStoreX*>(backing_store)->XShowRect(origin,
+              paint_rect, ui::GetX11WindowFromGdkWindow(window));
+        }
+      } else if (!UsingBackingStoreSkia()) {
         // If the grey blend is showing, we make two drawing calls. Use double
         // buffering to prevent flicker. Use CairoShowRect because XShowRect
         // shortcuts GDK's double buffering.
@@ -401,7 +591,8 @@
                               paint_rect.width(), paint_rect.height() };
         gdk_window_begin_paint_rect(window, &rect);
 
-        backing_store->CairoShowRect(paint_rect, GDK_DRAWABLE(window));
+        static_cast<BackingStoreX*>(backing_store)->CairoShowRect(
+            paint_rect, GDK_DRAWABLE(window));
 
         cairo_t* cr = gdk_cairo_create(window);
         gdk_cairo_rectangle(cr, &rect);
@@ -410,6 +601,9 @@
         cairo_destroy(cr);
 
         gdk_window_end_paint(window);
+      } else {
+        // TODO(sad)
+        NOTIMPLEMENTED();
       }
     }
     if (!whiteout_start_time_.is_null()) {
@@ -437,7 +631,7 @@
 }
 
 gfx::NativeCursor RenderWidgetHostViewViews::GetCursorForPoint(
-    views::Event::EventType type, const gfx::Point& point) {
+    ui::EventType type, const gfx::Point& point) {
   return native_cursor_;
 }
 
@@ -488,66 +682,28 @@
 
 bool RenderWidgetHostViewViews::OnMouseWheel(const views::MouseWheelEvent& e) {
   WebMouseWheelEvent wmwe;
-  InitializeWebMouseEventFromViewsEvent(e, GetPosition(), &wmwe);
+  InitializeWebMouseEventFromViewsEvent(e, GetMirroredPosition(), &wmwe);
 
   wmwe.type = WebKit::WebInputEvent::MouseWheel;
   wmwe.button = WebKit::WebMouseEvent::ButtonNone;
 
   // TODO(sadrul): How do we determine if it's a horizontal scroll?
-  wmwe.deltaY = e.GetOffset();
+  wmwe.deltaY = e.offset();
   wmwe.wheelTicksY = wmwe.deltaY > 0 ? 1 : -1;
 
   GetRenderWidgetHost()->ForwardWheelEvent(wmwe);
   return true;
 }
 
-bool RenderWidgetHostViewViews::OnKeyPressed(const views::KeyEvent &e) {
-  // Send key event to input method.
-  // TODO host_view->im_context_->ProcessKeyEvent(event);
-
-  // This is how it works:
-  // (1) If a RawKeyDown event is an accelerator for a reserved command (see
-  //     Browser::IsReservedCommand), then the command is executed. Otherwise,
-  //     the event is first sent off to the renderer. The renderer is also
-  //     notified whether the event would trigger an accelerator in the browser.
-  // (2) A Char event is then sent to the renderer.
-  // (3) If the renderer does not process the event in step (1), and the event
-  //     triggers an accelerator, then it will ignore the event in step (2). The
-  //     renderer also sends back notification to the browser for both steps (1)
-  //     and (2) about whether the events were processed or not. If the event
-  //     for (1) is not processed by the renderer, then it is processed by the
-  //     browser, and (2) is ignored.
-
-  NativeWebKeyboardEvent wke;
-  wke.type = WebKit::WebInputEvent::RawKeyDown;
-  wke.windowsKeyCode = e.GetKeyCode();
-  wke.setKeyIdentifierFromWindowsKeyCode();
-
-  wke.text[0] = wke.unmodifiedText[0] =
-    static_cast<unsigned short>(gdk_keyval_to_unicode(
-          app::GdkKeyCodeForWindowsKeyCode(e.GetKeyCode(),
-              e.IsShiftDown() ^ e.IsCapsLockDown())));
-
-  wke.modifiers = WebInputEventFlagsFromViewsEvent(e);
-  ForwardKeyboardEvent(wke);
-
-  // send the keypress event
-  wke.type = WebKit::WebInputEvent::Char;
-  ForwardKeyboardEvent(wke);
-
+bool RenderWidgetHostViewViews::OnKeyPressed(const views::KeyEvent& e) {
+  if (!ime_context_->FilterKeyEvent(e))
+    ForwardKeyEvent(e);
   return TRUE;
 }
 
-bool RenderWidgetHostViewViews::OnKeyReleased(const views::KeyEvent &e) {
-  // TODO(bryeung): deal with input methods
-  NativeWebKeyboardEvent wke;
-
-  wke.type = WebKit::WebInputEvent::KeyUp;
-  wke.windowsKeyCode = e.GetKeyCode();
-  wke.setKeyIdentifierFromWindowsKeyCode();
-
-  ForwardKeyboardEvent(wke);
-
+bool RenderWidgetHostViewViews::OnKeyReleased(const views::KeyEvent& e) {
+  if (!ime_context_->FilterKeyEvent(e))
+    ForwardKeyEvent(e);
   return TRUE;
 }
 
@@ -577,7 +733,7 @@
     GetRenderWidgetHost()->ForwardMouseEvent(fake_event);
   }
 #endif
-
+  ime_context_->Focus();
   ShowCurrentCursor();
   GetRenderWidgetHost()->GotFocus();
 }
@@ -585,15 +741,16 @@
 void RenderWidgetHostViewViews::WillLoseFocus() {
   // If we are showing a context menu, maintain the illusion that webkit has
   // focus.
-  if (!is_showing_context_menu_ && !is_hidden_)
-    GetRenderWidgetHost()->Blur();
+  if (!is_showing_context_menu_ && !is_hidden_ && host_)
+    host_->Blur();
+  ime_context_->Blur();
 }
 
 
 void RenderWidgetHostViewViews::ShowCurrentCursor() {
   // The widget may not have a window. If that's the case, abort mission. This
   // is the same issue as that explained above in Paint().
-  if (!native_view() || !native_view()->window)
+  if (!GetInnerNativeView() || !GetInnerNativeView()->window)
     return;
 
   native_cursor_ = current_cursor_.GetNativeCursor();
@@ -632,7 +789,7 @@
 WebKit::WebMouseEvent RenderWidgetHostViewViews::WebMouseEventFromViewsEvent(
     const views::MouseEvent& event) {
   WebKit::WebMouseEvent wmevent;
-  InitializeWebMouseEventFromViewsEvent(event, GetPosition(), &wmevent);
+  InitializeWebMouseEventFromViewsEvent(event, GetMirroredPosition(), &wmevent);
 
   // Setting |wmevent.button| is not necessary for -move events, but it is
   // necessary for -clicks and -drags.
@@ -652,63 +809,127 @@
   return wmevent;
 }
 
-void RenderWidgetHostViewViews::ForwardKeyboardEvent(
+void RenderWidgetHostViewViews::ForwardKeyEvent(
+    const views::KeyEvent& event) {
+  // This is how it works:
+  // (1) If a RawKeyDown event is an accelerator for a reserved command (see
+  //     Browser::IsReservedCommand), then the command is executed. Otherwise,
+  //     the event is first sent off to the renderer. The renderer is also
+  //     notified whether the event would trigger an accelerator in the browser.
+  // (2) A Char event is then sent to the renderer.
+  // (3) If the renderer does not process the event in step (1), and the event
+  //     triggers an accelerator, then it will ignore the event in step (2). The
+  //     renderer also sends back notification to the browser for both steps (1)
+  //     and (2) about whether the events were processed or not. If the event
+  //     for (1) is not processed by the renderer, then it is processed by the
+  //     browser, and (2) is ignored.
+  if (event.type() == ui::ET_KEY_PRESSED) {
+    NativeWebKeyboardEvent wke;
+
+    wke.type = WebKit::WebInputEvent::RawKeyDown;
+    wke.windowsKeyCode = event.key_code();
+    wke.setKeyIdentifierFromWindowsKeyCode();
+
+    int keyval = ui::GdkKeyCodeForWindowsKeyCode(event.key_code(),
+        event.IsShiftDown() ^ event.IsCapsLockDown());
+
+    wke.text[0] = wke.unmodifiedText[0] =
+        static_cast<unsigned short>(gdk_keyval_to_unicode(keyval));
+
+    wke.modifiers = WebInputEventFlagsFromViewsEvent(event);
+
+    ForwardWebKeyboardEvent(wke);
+
+    wke.type = WebKit::WebInputEvent::Char;
+    ForwardWebKeyboardEvent(wke);
+  } else {
+    NativeWebKeyboardEvent wke;
+
+    wke.type = WebKit::WebInputEvent::KeyUp;
+    wke.windowsKeyCode = event.key_code();
+    wke.setKeyIdentifierFromWindowsKeyCode();
+    ForwardWebKeyboardEvent(wke);
+  }
+}
+
+void RenderWidgetHostViewViews::ForwardWebKeyboardEvent(
     const NativeWebKeyboardEvent& event) {
   if (!host_)
     return;
 
   EditCommands edit_commands;
 #if 0
-TODO(bryeung): key bindings
+  // TODO(bryeung): key bindings
   if (!event.skip_in_browser &&
       key_bindings_handler_->Match(event, &edit_commands)) {
     host_->ForwardEditCommandsForNextKeyEvent(edit_commands);
   }
 #endif
+
   host_->ForwardKeyboardEvent(event);
 }
 
-bool RenderWidgetHostViewViews::OnTouchEvent(const views::TouchEvent& e) {
+views::View::TouchStatus RenderWidgetHostViewViews::OnTouchEvent(
+    const views::TouchEvent& e) {
   // Update the list of touch points first.
   WebKit::WebTouchPoint* point = NULL;
+  TouchStatus status = TOUCH_STATUS_UNKNOWN;
 
-  switch (e.GetType()) {
-    case views::Event::ET_TOUCH_PRESSED:
+  switch (e.type()) {
+    case ui::ET_TOUCH_PRESSED:
       // Add a new touch point.
       if (touch_event_.touchPointsLength <
           WebTouchEvent::touchPointsLengthCap) {
         point = &touch_event_.touchPoints[touch_event_.touchPointsLength++];
         point->id = e.identity();
+
+        if (touch_event_.touchPointsLength == 1) {
+          // A new touch sequence has started.
+          status = TOUCH_STATUS_START;
+
+          // We also want the focus.
+          RequestFocus();
+        }
       }
       break;
-    case views::Event::ET_TOUCH_RELEASED:
-    case views::Event::ET_TOUCH_CANCELLED:
-    case views::Event::ET_TOUCH_MOVED: {
+    case ui::ET_TOUCH_RELEASED:
+    case ui::ET_TOUCH_CANCELLED:
+    case ui::ET_TOUCH_MOVED: {
       // The touch point should have been added to the event from an earlier
       // _PRESSED event. So find that.
       // At the moment, only a maximum of 4 touch-points are allowed. So a
       // simple loop should be sufficient.
-      for (int i = 0; i < WebTouchEvent::touchPointsLengthCap; ++i) {
+      for (int i = 0; i < touch_event_.touchPointsLength; ++i) {
         point = touch_event_.touchPoints + i;
         if (point->id == e.identity()) {
           break;
         }
         point = NULL;
       }
-      DCHECK(point != NULL) << "Touchpoint not found for event " << e.GetType();
       break;
     }
     default:
-      DLOG(WARNING) << "Unknown touch event " << e.GetType();
+      DLOG(WARNING) << "Unknown touch event " << e.type();
       break;
   }
 
   if (!point)
-    return false;
+    return TOUCH_STATUS_UNKNOWN;
+
+  if (status != TOUCH_STATUS_START)
+    status = TOUCH_STATUS_CONTINUE;
 
   // Update the location and state of the point.
-  UpdateTouchPointPosition(&e, GetPosition(), point);
   point->state = TouchPointStateFromEvent(&e);
+  if (point->state == WebKit::WebTouchPoint::StateMoved) {
+    // It is possible for badly written touch drivers to emit Move events even
+    // when the touch location hasn't changed. In such cases, consume the event
+    // and pretend nothing happened.
+    if (point->position.x == e.x() && point->position.y == e.y()) {
+      return status;
+    }
+  }
+  UpdateTouchPointPosition(&e, GetMirroredPosition(), point);
 
   // Mark the rest of the points as stationary.
   for (int i = 0; i < touch_event_.touchPointsLength; ++i) {
@@ -720,21 +941,30 @@
 
   // Update the type of the touch event.
   touch_event_.type = TouchEventTypeFromEvent(&e);
+  touch_event_.timeStampSeconds = base::Time::Now().ToDoubleT();
 
   // The event and all the touches have been updated. Dispatch.
   host_->ForwardTouchEvent(touch_event_);
 
   // If the touch was released, then remove it from the list of touch points.
-  if (e.GetType() == views::Event::ET_TOUCH_RELEASED) {
+  if (e.type() == ui::ET_TOUCH_RELEASED) {
     --touch_event_.touchPointsLength;
     for (int i = point - touch_event_.touchPoints;
          i < touch_event_.touchPointsLength;
          ++i) {
       touch_event_.touchPoints[i] = touch_event_.touchPoints[i + 1];
     }
+    if (touch_event_.touchPointsLength == 0)
+      status = TOUCH_STATUS_END;
+  } else if (e.type() == ui::ET_TOUCH_CANCELLED) {
+    status = TOUCH_STATUS_CANCEL;
   }
 
-  return true;
+  return status;
+}
+
+std::string RenderWidgetHostViewViews::GetClassName() const {
+  return kViewClassName;
 }
 
 // static
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.h b/chrome/browser/renderer_host/render_widget_host_view_views.h
index 8a582a7..90087d1 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.h
@@ -13,13 +13,14 @@
 #include "base/scoped_ptr.h"
 #include "base/time.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "gfx/native_widget_types.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/controls/native/native_view_host.h"
-#include "views/event.h"
+#include "views/events/event.h"
 #include "views/view.h"
 #include "webkit/glue/webcursor.h"
 
+class IMEContextHandler;
 class RenderWidgetHost;
 struct NativeWebKeyboardEvent;
 
@@ -29,6 +30,9 @@
 class RenderWidgetHostViewViews : public RenderWidgetHostView,
                                   public views::View {
  public:
+  // Internal class name.
+  static const char kViewClassName[];
+
   explicit RenderWidgetHostViewViews(RenderWidgetHost* widget);
   virtual ~RenderWidgetHostViewViews();
 
@@ -38,11 +42,12 @@
   // RenderWidgetHostView implementation.
   virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
                            const gfx::Rect& pos);
-  virtual void InitAsFullscreen(RenderWidgetHostView* parent_host_view);
+  virtual void InitAsFullscreen();
   virtual RenderWidgetHost* GetRenderWidgetHost() const;
   virtual void DidBecomeSelected();
   virtual void WasHidden();
   virtual void SetSize(const gfx::Size& size);
+  virtual gfx::NativeView GetNativeView();
   virtual void MovePluginWindows(
       const std::vector<webkit::npapi::WebPluginGeometry>& moves);
   virtual void Focus();
@@ -75,13 +80,16 @@
   virtual bool ContainsNativeView(gfx::NativeView native_view) const;
   virtual void AcceleratedCompositingActivated(bool activated);
 
-  gfx::NativeView native_view() const;
-  virtual gfx::NativeView GetNativeView();
+  // On some systems, there can be two native views, where an outer native view
+  // contains the inner native view (e.g. when using GTK+). This returns the
+  // inner view. This can return NULL when it's not attached to a view.
+  gfx::NativeView GetInnerNativeView() const;
 
   virtual void Paint(gfx::Canvas* canvas);
 
   // Overridden from views::View.
-  gfx::NativeCursor GetCursorForPoint(views::Event::EventType type,
+  virtual std::string GetClassName() const;
+  gfx::NativeCursor GetCursorForPoint(ui::EventType type,
                                       const gfx::Point& point);
 
   // Views mouse events, overridden from views::View.
@@ -100,11 +108,14 @@
   virtual void DidGainFocus();
   virtual void WillLoseFocus();
 
+  // Forwards a web keyboard event to renderer.
+  void ForwardWebKeyboardEvent(const NativeWebKeyboardEvent& event);
+
   // Forwards a keyboard event to renderer.
-  void ForwardKeyboardEvent(const NativeWebKeyboardEvent& event);
+  void ForwardKeyEvent(const views::KeyEvent& event);
 
   // Views touch events, overridden from views::View.
-  virtual bool OnTouchEvent(const views::TouchEvent& e);
+  virtual View::TouchStatus OnTouchEvent(const views::TouchEvent& e);
 
  private:
   friend class RenderWidgetHostViewViewsWidget;
@@ -169,6 +180,10 @@
   // removed from the list on an ET_TOUCH_RELEASED event.
   WebKit::WebTouchEvent touch_event_;
 
+  // Input method context used to translating sequence of key events into other
+  // languages.
+  scoped_ptr<IMEContextHandler> ime_context_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewViews);
 };
 
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index 46d341d..896862b 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -6,11 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_win.h"
-#include "app/resource_bundle.h"
-#include "app/win/hwnd_util.h"
-#include "app/view_prop.h"
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
 #include "base/metrics/histogram.h"
@@ -34,14 +29,19 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/plugin_messages.h"
 #include "chrome/common/render_messages.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/gdi_util.h"
-#include "gfx/rect.h"
 #include "grit/webkit_resources.h"
 #include "skia/ext/skia_utils_win.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
-#include "third_party/WebKit/WebKit/chromium/public/win/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_win.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/view_prop.h"
+#include "ui/base/win/hwnd_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/rect.h"
 #include "views/accessibility/view_accessibility.h"
 #include "views/focus/focus_manager.h"
 #include "views/focus/focus_util_win.h"
@@ -53,9 +53,9 @@
 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
 #include "webkit/plugins/npapi/webplugin.h"
 
-using app::ViewProp;
 using base::TimeDelta;
 using base::TimeTicks;
+using ui::ViewProp;
 using WebKit::WebInputEvent;
 using WebKit::WebInputEventFactory;
 using WebKit::WebMouseEvent;
@@ -325,8 +325,7 @@
   ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
 }
 
-void RenderWidgetHostViewWin::InitAsFullscreen(
-    RenderWidgetHostView* parent_host_view) {
+void RenderWidgetHostViewWin::InitAsFullscreen() {
   NOTIMPLEMENTED() << "Fullscreen not implemented on Win";
 }
 
@@ -565,6 +564,12 @@
   SetParent(parent_hwnd_);
   ShowWindow(SW_SHOW);
 
+  // Save away our HWND in the parent window as a property so that the
+  // accessibility code can find it.
+  accessibility_prop_.reset(new ViewProp(GetParent(),
+                                         kViewsNativeHostPropForAccessibility,
+                                         m_hWnd));
+
   DidBecomeSelected();
 }
 
@@ -575,6 +580,8 @@
     return;
   }
 
+  accessibility_prop_.reset();
+
   if (::GetFocus() == m_hWnd)
     ::SetFocus(NULL);
   ShowWindow(SW_HIDE);
@@ -832,11 +839,6 @@
   // Marks that window as supporting mouse-wheel messages rerouting so it is
   // scrolled when under the mouse pointer even if inactive.
   props_.push_back(views::SetWindowSupportsRerouteMouseWheel(m_hWnd));
-  // Save away our HWND in the parent window as a property so that the
-  // accessibility code can find it.
-  props_.push_back(new ViewProp(GetParent(),
-                                kViewsNativeHostPropForAccessibility,
-                                m_hWnd));
   props_.push_back(new ViewProp(m_hWnd, kRenderWidgetHostViewKey,
                                 static_cast<RenderWidgetHostView*>(this)));
   return 0;
@@ -1448,7 +1450,7 @@
     ::ScreenToClient(m_hWnd, &cursor_pos);
     HWND child_window = ::RealChildWindowFromPoint(m_hWnd, cursor_pos);
     if (::IsWindow(child_window) && child_window != m_hWnd) {
-      if (app::win::GetClassName(child_window) ==
+      if (ui::GetClassName(child_window) ==
               webkit::npapi::kWrapperNativeWindowClassName)
         child_window = ::GetWindow(child_window, GW_CHILD);
 
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 50e59a6..5af890a 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -22,12 +22,11 @@
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/webcursor.h"
 
-namespace app {
-class ViewProp;
-}
+class BackingStore;
+class RenderWidgetHost;
 
 namespace gfx {
 class Size;
@@ -38,8 +37,9 @@
 class Message;
 }
 
-class BackingStore;
-class RenderWidgetHost;
+namespace ui {
+class ViewProp;
+}
 
 typedef CWinTraits<WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0>
     RenderWidgetHostHWNDTraits;
@@ -125,7 +125,7 @@
   // Implementation of RenderWidgetHostView:
   virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
                            const gfx::Rect& pos);
-  virtual void InitAsFullscreen(RenderWidgetHostView* parent_host_view);
+  virtual void InitAsFullscreen();
   virtual RenderWidgetHost* GetRenderWidgetHost() const;
   virtual void DidBecomeSelected();
   virtual void WasHidden();
@@ -350,7 +350,9 @@
   // method.
   WebKit::WebTextInputType text_input_type_;
 
-  ScopedVector<app::ViewProp> props_;
+  ScopedVector<ui::ViewProp> props_;
+
+  scoped_ptr<ui::ViewProp> accessibility_prop_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewWin);
 };
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index 93749f3..5bfe445 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -31,6 +31,8 @@
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/url_request_tracking.h"
 #include "chrome/browser/plugin_service.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_resource_handler.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/async_resource_handler.h"
 #include "chrome/browser/renderer_host/buffered_resource_handler.h"
@@ -126,9 +128,11 @@
   if (process_type == ChildProcessInfo::PLUGIN_PROCESS)
     return true;
 
-  if (request_data.resource_type == ResourceType::PREFETCH &&
-      !ResourceDispatcherHost::is_prefetch_enabled())
-    return false;
+  if (request_data.resource_type == ResourceType::PREFETCH) {
+    PrerenderManager::RecordPrefetchTagObserved();
+    if (!ResourceDispatcherHost::is_prefetch_enabled())
+      return false;
+  }
 
   ChildProcessSecurityPolicy* policy =
       ChildProcessSecurityPolicy::GetInstance();
@@ -194,6 +198,16 @@
   return all_error_codes;
 }
 
+#if defined(OS_WIN)
+#pragma warning(disable: 4748)
+#pragma optimize("", off)
+#endif
+
+#if defined(OS_WIN)
+#pragma optimize("", on)
+#pragma warning(default: 4748)
+#endif
+
 }  // namespace
 
 ResourceDispatcherHost::ResourceDispatcherHost()
@@ -285,10 +299,10 @@
       NewRunnableFunction(
           &ExternalProtocolHandler::LaunchUrl, url, child_id, route_id));
 
-  handler->OnResponseCompleted(request_id, URLRequestStatus(
-                                               URLRequestStatus::FAILED,
-                                               net::ERR_ABORTED),
-                               std::string());  // No security info necessary.
+  handler->OnResponseCompleted(
+      request_id,
+      net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_ABORTED),
+      std::string());  // No security info necessary.
   return true;
 }
 
@@ -347,7 +361,7 @@
   int child_id = filter_->child_id();
 
   ChromeURLRequestContext* context = filter_->GetURLRequestContext(
-      request_id, request_data.resource_type);
+      request_data);
 
   // Might need to resolve the blob references in the upload data.
   if (request_data.upload_data && context) {
@@ -357,7 +371,8 @@
 
   if (is_shutdown_ ||
       !ShouldServiceRequest(process_type, child_id, request_data)) {
-    URLRequestStatus status(URLRequestStatus::FAILED, net::ERR_ABORTED);
+    net::URLRequestStatus status(net::URLRequestStatus::FAILED,
+                                 net::ERR_ABORTED);
     if (sync_result) {
       SyncLoadResult result;
       result.status = status;
@@ -444,6 +459,15 @@
     upload_size = request_data.upload_data->GetContentLength();
   }
 
+  // Install a PrerenderResourceHandler if the requested URL could
+  // be prerendered. This should be in front of the [a]syncResourceHandler,
+  // but after the BufferedResourceHandler since it depends on the MIME
+  // sniffing capabilities in the BufferedResourceHandler.
+  PrerenderResourceHandler* pre_handler = PrerenderResourceHandler::MaybeCreate(
+      *request, context, handler);
+  if (pre_handler)
+    handler = pre_handler;
+
   // Install a CrossSiteResourceHandler if this request is coming from a
   // RenderViewHost with a pending cross-site request.  We only check this for
   // MAIN_FRAME requests. Unblock requests only come from a blocked page, do
@@ -497,8 +521,8 @@
   ApplyExtensionLocalizationFilter(request_data.url, request_data.resource_type,
                                    extra_info);
   SetRequestInfo(request, extra_info);  // Request takes ownership.
-  chrome_browser_net::SetOriginProcessUniqueIDForRequest(
-      request_data.origin_child_id, request);
+  chrome_browser_net::SetOriginPIDForRequest(
+      request_data.origin_pid, request);
 
   if (request->url().SchemeIs(chrome::kBlobScheme) && context) {
     // Hang on to a reference to ensure the blob is not released prior
@@ -661,7 +685,7 @@
     bool prompt_for_save_location,
     int child_id,
     int route_id,
-    URLRequestContext* request_context) {
+    net::URLRequestContext* request_context) {
   if (is_shutdown_)
     return;
 
@@ -712,17 +736,17 @@
   ResourceDispatcherHostRequestInfo* extra_info =
       CreateRequestInfoForBrowserRequest(handler, child_id, route_id, true);
   SetRequestInfo(request, extra_info);  // Request takes ownership.
-  chrome_browser_net::SetOriginProcessUniqueIDForRequest(child_id, request);
 
   BeginRequestInternal(request);
 }
 
 // This function is only used for saving feature.
-void ResourceDispatcherHost::BeginSaveFile(const GURL& url,
-                                           const GURL& referrer,
-                                           int child_id,
-                                           int route_id,
-                                           URLRequestContext* request_context) {
+void ResourceDispatcherHost::BeginSaveFile(
+    const GURL& url,
+    const GURL& referrer,
+    int child_id,
+    int route_id,
+    net::URLRequestContext* request_context) {
   if (is_shutdown_)
     return;
 
@@ -759,7 +783,6 @@
   ResourceDispatcherHostRequestInfo* extra_info =
       CreateRequestInfoForBrowserRequest(handler, child_id, route_id, false);
   SetRequestInfo(request, extra_info);  // Request takes ownership.
-  chrome_browser_net::SetOriginProcessUniqueIDForRequest(child_id, request);
 
   BeginRequestInternal(request);
 }
@@ -1008,6 +1031,10 @@
 void ResourceDispatcherHost::OnAuthRequired(
     net::URLRequest* request,
     net::AuthChallengeInfo* auth_info) {
+  if (request->load_flags() & net::LOAD_PREFETCH) {
+    request->CancelAuth();
+    return;
+  }
   // Create a login dialog on the UI thread to get authentication data,
   // or pull from cache and continue on the IO thread.
   // TODO(mpcomplete): We should block the parent tab while waiting for
@@ -1056,10 +1083,7 @@
   if (!RenderViewForRequest(request, &render_process_id, &render_view_id))
     return;
 
-  ChromeURLRequestContext* context =
-      static_cast<ChromeURLRequestContext*>(request->context());
-  if (context->IsExternal())
-    return;
+  net::URLRequestContext* context = request->context();
 
   net::CookieMonster* cookie_monster =
       context->cookie_store()->GetCookieMonster();
@@ -1301,8 +1325,9 @@
     return;
   }
 
-  if (!defer_start)
+  if (!defer_start) {
     InsertIntoResourceQueue(request, *info);
+  }
 }
 
 void ResourceDispatcherHost::InsertIntoResourceQueue(
@@ -1618,11 +1643,11 @@
                                         T* detail) {
   RenderViewHost* rvh =
       RenderViewHost::FromID(render_process_id, render_view_id);
-  if (!rvh)
-    return;
-  RenderViewHostDelegate* rvhd = rvh->delegate();
-  NotificationService::current()->Notify(
-      type, Source<RenderViewHostDelegate>(rvhd), Details<T>(detail));
+  if (rvh) {
+    RenderViewHostDelegate* rvhd = rvh->delegate();
+    NotificationService::current()->Notify(
+        type, Source<RenderViewHostDelegate>(rvhd), Details<T>(detail));
+  }
   delete detail;
 }
 
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc
index 2b6c5a6..5271595 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,9 +9,9 @@
 #include "base/file_path.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/browser/net/url_request_failed_dns_job.h"
 #include "chrome/browser/net/url_request_mock_http_job.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/automation/browser_proxy.h"
 #include "chrome/test/automation/tab_proxy.h"
@@ -216,7 +216,7 @@
 #endif
   ASSERT_TRUE(tab->NavigateToURLAsync(GURL(chrome::kAboutCrashURL)));
   // Wait for browser to notice the renderer crash.
-  base::PlatformThread::Sleep(sleep_timeout_ms());
+  base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
 
   // Navigate to a new cross-site page.  The browser should not wait around for
   // the old renderer's on{before}unload handlers to run.
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc b/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc
index 5b6758c..bc3ab35 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -73,7 +73,7 @@
   request.frame_origin = "null";
   request.main_frame_origin = "null";
   request.load_flags = 0;
-  request.origin_child_id = 0;
+  request.origin_pid = 0;
   request.resource_type = type;
   request.request_context = 0;
   request.appcache_host_id = appcache::kNoHostId;
@@ -252,10 +252,12 @@
   static net::URLRequestJob* Factory(net::URLRequest* request,
                                      const std::string& scheme) {
     if (test_fixture_->response_headers_.empty()) {
-      return new URLRequestTestJob(request);
+      return new net::URLRequestTestJob(request);
     } else {
-      return new URLRequestTestJob(request, test_fixture_->response_headers_,
-                                   test_fixture_->response_data_, false);
+      return new net::URLRequestTestJob(request,
+                                        test_fixture_->response_headers_,
+                                        test_fixture_->response_data_,
+                                        false);
     }
   }
 
@@ -342,12 +344,12 @@
 TEST_F(ResourceDispatcherHostTest, TestMany) {
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
-  MakeTestRequest(0, 1, URLRequestTestJob::test_url_1());
-  MakeTestRequest(0, 2, URLRequestTestJob::test_url_2());
-  MakeTestRequest(0, 3, URLRequestTestJob::test_url_3());
+  MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
 
   // flush all the pending requests
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -358,9 +360,9 @@
   // there are three requests, so we should have gotten them classified as such
   ASSERT_EQ(3U, msgs.size());
 
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
-  CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_2());
-  CheckSuccessfulRequest(msgs[2], URLRequestTestJob::test_data_3());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_2());
+  CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
 }
 
 // Tests whether messages get canceled properly. We issue three requests,
@@ -368,13 +370,13 @@
 TEST_F(ResourceDispatcherHostTest, Cancel) {
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
-  MakeTestRequest(0, 1, URLRequestTestJob::test_url_1());
-  MakeTestRequest(0, 2, URLRequestTestJob::test_url_2());
-  MakeTestRequest(0, 3, URLRequestTestJob::test_url_3());
+  MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
   MakeCancelRequest(2);
 
   // flush all the pending requests
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
   MessageLoop::current()->RunAllPending();
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
@@ -385,8 +387,8 @@
   // there are three requests, so we should have gotten them classified as such
   ASSERT_EQ(3U, msgs.size());
 
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
-  CheckSuccessfulRequest(msgs[2], URLRequestTestJob::test_data_3());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
 
   // Check that request 2 got canceled.
   ASSERT_EQ(2U, msgs[1].size());
@@ -394,13 +396,13 @@
   ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[1][1].type());
 
   int request_id;
-  URLRequestStatus status;
+  net::URLRequestStatus status;
 
   void* iter = NULL;
   ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &request_id));
   ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &status));
 
-  EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
 }
 
 // The host delegate acts as a second one so we can have some requests
@@ -431,17 +433,19 @@
 
   // request 1 goes to the test delegate
   ViewHostMsg_Resource_Request request = CreateResourceRequest(
-      "GET", ResourceType::SUB_RESOURCE, URLRequestTestJob::test_url_1());
+      "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
-  MakeTestRequest(test_filter.get(), 0, 1, URLRequestTestJob::test_url_1());
+  MakeTestRequest(test_filter.get(), 0, 1,
+                  net::URLRequestTestJob::test_url_1());
 
   // request 2 goes to us
-  MakeTestRequest(0, 2, URLRequestTestJob::test_url_2());
+  MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
 
   // request 3 goes to the test delegate
-  MakeTestRequest(test_filter.get(), 0, 3, URLRequestTestJob::test_url_3());
+  MakeTestRequest(test_filter.get(), 0, 3,
+                  net::URLRequestTestJob::test_url_3());
 
   // TODO(mbelshe):
   // Now that the async IO path is in place, the IO always completes on the
@@ -451,14 +455,14 @@
 
   // Process each request for one level so one callback is called.
   for (int i = 0; i < 3; i++)
-    EXPECT_TRUE(URLRequestTestJob::ProcessOnePendingMessage());
+    EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
 
   // Cancel the requests to the test process.
   host_.CancelRequestsForProcess(filter_->child_id());
   test_filter->has_canceled_ = true;
 
   // Flush all the pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.pending_requests());
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
@@ -470,7 +474,7 @@
   ResourceIPCAccumulator::ClassifiedMessages msgs;
   accum_.GetClassifiedMessages(&msgs);
   ASSERT_EQ(1U, msgs.size());
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
 }
 
 // Tests blocking and resuming requests.
@@ -481,15 +485,15 @@
   host_.BlockRequestsForRoute(filter_->child_id(), 2);
   host_.BlockRequestsForRoute(filter_->child_id(), 3);
 
-  MakeTestRequest(0, 1, URLRequestTestJob::test_url_1());
-  MakeTestRequest(1, 2, URLRequestTestJob::test_url_2());
-  MakeTestRequest(0, 3, URLRequestTestJob::test_url_3());
-  MakeTestRequest(1, 4, URLRequestTestJob::test_url_1());
-  MakeTestRequest(2, 5, URLRequestTestJob::test_url_2());
-  MakeTestRequest(3, 6, URLRequestTestJob::test_url_3());
+  MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
+  MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3());
 
   // Flush all the pending requests
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   // Sort out all the messages we saw by request
   ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -498,41 +502,41 @@
   // All requests but the 2 for the RVH 0 should have been blocked.
   ASSERT_EQ(2U, msgs.size());
 
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
-  CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
 
   // Resume requests for RVH 1 and flush pending requests.
   host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 1);
   KickOffRequest();
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   msgs.clear();
   accum_.GetClassifiedMessages(&msgs);
   ASSERT_EQ(2U, msgs.size());
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2());
-  CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
+  CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_1());
 
   // Test that new requests are not blocked for RVH 1.
-  MakeTestRequest(1, 7, URLRequestTestJob::test_url_1());
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1());
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
   msgs.clear();
   accum_.GetClassifiedMessages(&msgs);
   ASSERT_EQ(1U, msgs.size());
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
 
   // Now resumes requests for all RVH (2 and 3).
   host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 2);
   host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 3);
   KickOffRequest();
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
 
   msgs.clear();
   accum_.GetClassifiedMessages(&msgs);
   ASSERT_EQ(2U, msgs.size());
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2());
-  CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
+  CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
 }
 
 // Tests blocking and canceling requests.
@@ -541,13 +545,13 @@
 
   host_.BlockRequestsForRoute(filter_->child_id(), 1);
 
-  MakeTestRequest(0, 1, URLRequestTestJob::test_url_1());
-  MakeTestRequest(1, 2, URLRequestTestJob::test_url_2());
-  MakeTestRequest(0, 3, URLRequestTestJob::test_url_3());
-  MakeTestRequest(1, 4, URLRequestTestJob::test_url_1());
+  MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
+  MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
 
   // Flush all the pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   // Sort out all the messages we saw by request.
   ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -556,13 +560,13 @@
   // The 2 requests for the RVH 0 should have been processed.
   ASSERT_EQ(2U, msgs.size());
 
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
-  CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
 
   // Cancel requests for RVH 1.
   host_.CancelBlockedRequestsForRoute(filter_->child_id(), 1);
   KickOffRequest();
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
 
@@ -582,16 +586,18 @@
 
   host_.BlockRequestsForRoute(second_filter->child_id(), 0);
 
-  MakeTestRequest(filter_.get(), 0, 1, URLRequestTestJob::test_url_1());
-  MakeTestRequest(second_filter.get(), 0, 2, URLRequestTestJob::test_url_2());
-  MakeTestRequest(filter_.get(), 0, 3, URLRequestTestJob::test_url_3());
-  MakeTestRequest(second_filter.get(), 0, 4, URLRequestTestJob::test_url_1());
+  MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(second_filter.get(), 0, 2,
+                  net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3());
+  MakeTestRequest(second_filter.get(), 0, 4,
+                  net::URLRequestTestJob::test_url_1());
 
   // Simulate process death.
   host_.CancelRequestsForProcess(second_filter->child_id());
 
   // Flush all the pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
   EXPECT_EQ(0,
@@ -604,8 +610,8 @@
   // The 2 requests for the RVH 0 should have been processed.
   ASSERT_EQ(2U, msgs.size());
 
-  CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
-  CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3());
+  CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
+  CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
 
   EXPECT_TRUE(host_.blocked_requests_map_.empty());
 }
@@ -622,15 +628,16 @@
   host_.BlockRequestsForRoute(filter_->child_id(), 2);
   host_.BlockRequestsForRoute(second_filter->child_id(), 1);
 
-  MakeTestRequest(filter_.get(), 0, 1, URLRequestTestJob::test_url_1());
-  MakeTestRequest(filter_.get(), 1, 2, URLRequestTestJob::test_url_2());
-  MakeTestRequest(filter_.get(), 0, 3, URLRequestTestJob::test_url_3());
-  MakeTestRequest(second_filter.get(), 1, 4, URLRequestTestJob::test_url_1());
-  MakeTestRequest(filter_.get(), 2, 5, URLRequestTestJob::test_url_2());
-  MakeTestRequest(filter_.get(), 2, 6, URLRequestTestJob::test_url_3());
+  MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(filter_.get(), 1, 2, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3());
+  MakeTestRequest(second_filter.get(), 1, 4,
+                  net::URLRequestTestJob::test_url_1());
+  MakeTestRequest(filter_.get(), 2, 5, net::URLRequestTestJob::test_url_2());
+  MakeTestRequest(filter_.get(), 2, 6, net::URLRequestTestJob::test_url_3());
 
   // Flush all the pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 }
 
 // Test the private helper method "CalculateApproximateMemoryCost()".
@@ -699,7 +706,7 @@
   int kMemoryCostOfTest2Req =
       ResourceDispatcherHost::kAvgBytesPerOutstandingRequest +
       std::string("GET").size() +
-      URLRequestTestJob::test_url_2().spec().size();
+      net::URLRequestTestJob::test_url_2().spec().size();
 
   // Tighten the bound on the ResourceDispatcherHost, to speed things up.
   int kMaxCostPerProcess = 440000;
@@ -713,24 +720,26 @@
   scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(this);
 
   // Saturate the number of outstanding requests for our process.
-  for (size_t i = 0; i < kMaxRequests; ++i)
-    MakeTestRequest(filter_.get(), 0, i + 1, URLRequestTestJob::test_url_2());
+  for (size_t i = 0; i < kMaxRequests; ++i) {
+    MakeTestRequest(filter_.get(), 0, i + 1,
+                    net::URLRequestTestJob::test_url_2());
+  }
 
   // Issue two more requests for our process -- these should fail immediately.
   MakeTestRequest(filter_.get(), 0, kMaxRequests + 1,
-                  URLRequestTestJob::test_url_2());
+                  net::URLRequestTestJob::test_url_2());
   MakeTestRequest(filter_.get(), 0, kMaxRequests + 2,
-                  URLRequestTestJob::test_url_2());
+                  net::URLRequestTestJob::test_url_2());
 
   // Issue two requests for the second process -- these should succeed since
   // it is just process 0 that is saturated.
   MakeTestRequest(second_filter.get(), 0, kMaxRequests + 3,
-                  URLRequestTestJob::test_url_2());
+                  net::URLRequestTestJob::test_url_2());
   MakeTestRequest(second_filter.get(), 0, kMaxRequests + 4,
-                  URLRequestTestJob::test_url_2());
+                  net::URLRequestTestJob::test_url_2());
 
   // Flush all the pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
   MessageLoop::current()->RunAllPending();
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
@@ -744,7 +753,7 @@
 
   // Check that the first kMaxRequests succeeded.
   for (size_t i = 0; i < kMaxRequests; ++i)
-    CheckSuccessfulRequest(msgs[i], URLRequestTestJob::test_data_2());
+    CheckSuccessfulRequest(msgs[i], net::URLRequestTestJob::test_data_2());
 
   // Check that the subsequent two requests (kMaxRequests + 1) and
   // (kMaxRequests + 2) were failed, since the per-process bound was reached.
@@ -757,22 +766,22 @@
     // The RequestComplete message should have had status
     // (CANCELLED, ERR_INSUFFICIENT_RESOURCES).
     int request_id;
-    URLRequestStatus status;
+    net::URLRequestStatus status;
 
     void* iter = NULL;
     EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &request_id));
     EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &status));
 
     EXPECT_EQ(index + 1, request_id);
-    EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
     EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, status.os_error());
   }
 
   // The final 2 requests should have succeeded.
   CheckSuccessfulRequest(msgs[kMaxRequests + 2],
-                         URLRequestTestJob::test_data_2());
+                         net::URLRequestTestJob::test_data_2());
   CheckSuccessfulRequest(msgs[kMaxRequests + 3],
-                         URLRequestTestJob::test_data_2());
+                         net::URLRequestTestJob::test_data_2());
 }
 
 // Tests that we sniff the mime type for a simple request.
@@ -789,7 +798,7 @@
   MakeTestRequest(0, 1, GURL("http:bla"));
 
   // Flush all pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -818,7 +827,7 @@
   MakeTestRequest(0, 1, GURL("http:bla"));
 
   // Flush all pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -846,7 +855,7 @@
   MakeTestRequest(0, 1, GURL("http:bla"));
 
   // Flush all pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -873,7 +882,7 @@
   MakeTestRequest(0, 1, GURL("http:bla"));
 
   // Flush all pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -906,7 +915,7 @@
   MakeTestRequest(0, 1, GURL("http:bla"));
 
   // Flush all pending requests.
-  while (URLRequestTestJob::ProcessOnePendingMessage()) {}
+  while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -921,14 +930,14 @@
   // The RequestComplete message should have had status
   // (CANCELED, ERR_FILE_NOT_FOUND).
   int request_id;
-  URLRequestStatus status;
+  net::URLRequestStatus status;
 
   void* iter = NULL;
   EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id));
   EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &status));
 
   EXPECT_EQ(1, request_id);
-  EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, status.os_error());
 }
 
@@ -962,7 +971,9 @@
   bool OnReadCompleted(int request_id, int* bytes_read) { return true; }
 
   bool OnResponseCompleted(
-    int request_id, const URLRequestStatus& status, const std::string& info) {
+    int request_id,
+    const net::URLRequestStatus& status,
+    const std::string& info) {
     return true;
   }
 
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index b8005f3..5a27f65 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,6 @@
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/common/render_messages.h"
 
-
 ResourceMessageFilter::ResourceMessageFilter(
     int child_id,
     ChildProcessInfo::ProcessType process_type,
@@ -37,12 +36,10 @@
 }
 
 ChromeURLRequestContext* ResourceMessageFilter::GetURLRequestContext(
-    uint32 request_id, ResourceType::Type resource_type) {
-  URLRequestContext* rv = NULL;
-  if (url_request_context_override_.get()) {
-    rv = url_request_context_override_->GetRequestContext(
-        request_id, resource_type);
-  }
+    const ViewHostMsg_Resource_Request& resource_request) {
+  net::URLRequestContext* rv = NULL;
+  if (url_request_context_override_.get())
+    rv = url_request_context_override_->GetRequestContext(resource_request);
 
   if (!rv) {
     URLRequestContextGetter* context_getter =
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 471c60a..8af9a3d 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -8,10 +8,10 @@
 #include "base/scoped_ptr.h"
 #include "chrome/browser/browser_message_filter.h"
 #include "chrome/common/child_process_info.h"
-#include "webkit/glue/resource_type.h"
 
 class ChromeURLRequestContext;
 class ResourceDispatcherHost;
+struct ViewHostMsg_Resource_Request;
 
 namespace net {
 class URLRequestContext;
@@ -24,14 +24,14 @@
 // will not interfere with browser UI.
 class ResourceMessageFilter : public BrowserMessageFilter {
  public:
-  // Allows overriding the URLRequestContext used to service requests.
+  // Allows overriding the net::URLRequestContext used to service requests.
   class URLRequestContextOverride
       : public base::RefCountedThreadSafe<URLRequestContextOverride> {
    public:
     URLRequestContextOverride() {}
 
     virtual net::URLRequestContext* GetRequestContext(
-        uint32 request_id, ResourceType::Type resource_type) = 0;
+        const ViewHostMsg_Resource_Request& resource_request) = 0;
 
    protected:
     friend class base::RefCountedThreadSafe<URLRequestContextOverride>;
@@ -49,9 +49,9 @@
   virtual bool OnMessageReceived(const IPC::Message& message,
                                  bool* message_was_ok);
 
-  // Returns the URLRequestContext for the given request.
+  // Returns the net::URLRequestContext for the given request.
   ChromeURLRequestContext* GetURLRequestContext(
-      uint32 request_id, ResourceType::Type resource_type);
+      const ViewHostMsg_Resource_Request& resource_request);
 
   void set_url_request_context_override(URLRequestContextOverride* u) {
     url_request_context_override_ = u;
diff --git a/chrome/browser/renderer_host/resource_queue.cc b/chrome/browser/renderer_host/resource_queue.cc
index 66d02a1..3b667bf 100644
--- a/chrome/browser/renderer_host/resource_queue.cc
+++ b/chrome/browser/renderer_host/resource_queue.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -86,7 +86,7 @@
     if (ContainsKey(requests_, request_id)) {
       net::URLRequest* request = requests_[request_id];
       // The request shouldn't have started (SUCCESS is the initial state).
-      DCHECK_EQ(URLRequestStatus::SUCCESS, request->status().status());
+      DCHECK_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
       request->Start();
     }
   }
diff --git a/chrome/browser/renderer_host/resource_queue_unittest.cc b/chrome/browser/renderer_host/resource_queue_unittest.cc
index 3339701..a1a32da 100644
--- a/chrome/browser/renderer_host/resource_queue_unittest.cc
+++ b/chrome/browser/renderer_host/resource_queue_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -59,7 +59,7 @@
   }
 
   virtual bool OnResponseCompleted(int request_id,
-                                   const URLRequestStatus& status,
+                                   const net::URLRequestStatus& status,
                                    const std::string& security_info) {
     NOTREACHED();
     return true;
diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
index 237cad8..a8b171e 100644
--- a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
+++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -29,6 +29,7 @@
     ResourceDispatcherHost* resource_dispatcher_host)
     : state_(STATE_NONE),
       defer_state_(DEFERRED_NONE),
+      safe_browsing_result_(SafeBrowsingService::URL_SAFE),
       deferred_request_id_(-1),
       next_handler_(handler),
       render_process_host_id_(render_process_host_id),
@@ -55,6 +56,9 @@
   CHECK(state_ == STATE_NONE);
   CHECK(defer_state_ == DEFERRED_NONE);
 
+  // Save the redirect urls for possible malware detail reporting later.
+  redirect_urls_.push_back(new_url);
+
   // We need to check the new URL before following the redirect.
   if (CheckUrl(new_url)) {
     return next_handler_->OnRequestRedirected(
@@ -121,7 +125,7 @@
 }
 
 bool SafeBrowsingResourceHandler::OnResponseCompleted(
-    int request_id, const URLRequestStatus& status,
+    int request_id, const net::URLRequestStatus& status,
     const std::string& security_info) {
   Shutdown();
   return next_handler_->OnResponseCompleted(request_id, status, security_info);
@@ -180,8 +184,8 @@
     original_url = url;
 
   safe_browsing_->DisplayBlockingPage(
-      url, original_url, resource_type_, result, this, render_process_host_id_,
-      render_view_id_);
+      url, original_url, redirect_urls_, resource_type_,
+      result, this, render_process_host_id_, render_view_id_);
 }
 
 // SafeBrowsingService::Client implementation, called on the IO thread when
diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.h b/chrome/browser/renderer_host/safe_browsing_resource_handler.h
index 723a32b..f171ea6 100644
--- a/chrome/browser/renderer_host/safe_browsing_resource_handler.h
+++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <string>
+#include <vector>
 
 #include "base/ref_counted.h"
 #include "base/time.h"
@@ -131,6 +132,9 @@
   // Timer to abort the safe browsing check if it takes too long.
   base::OneShotTimer<SafeBrowsingResourceHandler> timer_;
 
+  // The redirect chain for this resource
+  std::vector<GURL> redirect_urls_;
+
   // Details on the deferred request (either a start or redirect). It is only
   // valid to access these members when defer_state_ != DEFERRED_NONE.
   GURL deferred_url_;
diff --git a/chrome/browser/renderer_host/save_file_resource_handler.cc b/chrome/browser/renderer_host/save_file_resource_handler.cc
index d33e205..54b4388 100644
--- a/chrome/browser/renderer_host/save_file_resource_handler.cc
+++ b/chrome/browser/renderer_host/save_file_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -94,7 +94,7 @@
 
 bool SaveFileResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
diff --git a/chrome/browser/renderer_host/site_instance.cc b/chrome/browser/renderer_host/site_instance.cc
index 31f20f5..76d33fb 100644
--- a/chrome/browser/renderer_host/site_instance.cc
+++ b/chrome/browser/renderer_host/site_instance.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/renderer_host/site_instance.h"
 
 #include "chrome/browser/browsing_instance.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/renderer_host/browser_render_process_host.h"
 #include "chrome/common/url_constants.h"
@@ -19,6 +19,7 @@
     return false;
   return url.SchemeIs(chrome::kJavaScriptScheme) ||
          url.spec() == chrome::kAboutCrashURL ||
+         url.spec() == chrome::kAboutKillURL ||
          url.spec() == chrome::kAboutHangURL ||
          url.spec() == chrome::kAboutShorthangURL;
 }
@@ -209,9 +210,9 @@
   if (url.SchemeIs(chrome::kExtensionScheme))
     return RenderProcessHost::TYPE_EXTENSION;
 
-  // TODO(erikkay) creis recommends using UseDOMUIForURL instead.
-  if (DOMUIFactory::HasDOMUIScheme(url))
-    return RenderProcessHost::TYPE_DOMUI;
+  // TODO(erikkay) creis recommends using UseWebUIForURL instead.
+  if (WebUIFactory::HasWebUIScheme(url))
+    return RenderProcessHost::TYPE_WEBUI;
 
   return RenderProcessHost::TYPE_NORMAL;
 }
diff --git a/chrome/browser/renderer_host/socket_stream_dispatcher_host.cc b/chrome/browser/renderer_host/socket_stream_dispatcher_host.cc
index fc642e8..95db4d8 100644
--- a/chrome/browser/renderer_host/socket_stream_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/socket_stream_dispatcher_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/socket_stream_host.h"
 #include "chrome/common/render_messages.h"
+#include "chrome/common/render_messages_params.h"
 #include "chrome/common/net/socket_stream.h"
 #include "chrome/common/net/url_request_context_getter.h"
 #include "net/websockets/websocket_job.h"
@@ -146,11 +147,11 @@
   }
 }
 
-URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
-  URLRequestContext* rv = NULL;
+net::URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
+  net::URLRequestContext* rv = NULL;
   if (url_request_context_override_.get()) {
-    rv = url_request_context_override_->GetRequestContext(
-        0, ResourceType::SUB_RESOURCE);
+    ViewHostMsg_Resource_Request request;
+    rv = url_request_context_override_->GetRequestContext(request);
   }
   if (!rv) {
     URLRequestContextGetter* context_getter =
diff --git a/chrome/browser/renderer_host/socket_stream_dispatcher_host.h b/chrome/browser/renderer_host/socket_stream_dispatcher_host.h
index 5c1b47c..23d18e0 100644
--- a/chrome/browser/renderer_host/socket_stream_dispatcher_host.h
+++ b/chrome/browser/renderer_host/socket_stream_dispatcher_host.h
@@ -53,7 +53,6 @@
 
   void DeleteSocketStreamHost(int socket_id);
 
-  // Returns the URLRequestContext.
   net::URLRequestContext* GetURLRequestContext();
 
   IDMap<SocketStreamHost> hosts_;
diff --git a/chrome/browser/renderer_host/socket_stream_host.cc b/chrome/browser/renderer_host/socket_stream_host.cc
index 6c66f79..a38975f 100644
--- a/chrome/browser/renderer_host/socket_stream_host.cc
+++ b/chrome/browser/renderer_host/socket_stream_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -45,7 +45,7 @@
 }
 
 void SocketStreamHost::Connect(const GURL& url,
-                               URLRequestContext* request_context) {
+                               net::URLRequestContext* request_context) {
   VLOG(1) << "SocketStreamHost::Connect url=" << url;
   socket_ = net::SocketStreamJob::CreateSocketStreamJob(url, delegate_);
   socket_->set_context(request_context);
diff --git a/chrome/browser/renderer_host/sync_resource_handler.cc b/chrome/browser/renderer_host/sync_resource_handler.cc
index aa42c72..5ae3333 100644
--- a/chrome/browser/renderer_host/sync_resource_handler.cc
+++ b/chrome/browser/renderer_host/sync_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -98,7 +98,7 @@
 
 bool SyncResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info) {
   result_.status = status;
 
diff --git a/chrome/browser/renderer_host/test/render_process_host_browsertest.cc b/chrome/browser/renderer_host/test/render_process_host_browsertest.cc
index 46a960c..aa75b51 100644
--- a/chrome/browser/renderer_host/test/render_process_host_browsertest.cc
+++ b/chrome/browser/renderer_host/test/render_process_host_browsertest.cc
@@ -1,12 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "chrome/browser/debugger/devtools_manager.h"
 #include "chrome/browser/renderer_host/site_instance.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/in_process_browser_test.h"
@@ -28,6 +32,32 @@
     }
     return count;
   }
+
+  RenderViewHost* FindFirstDevToolsHost() {
+    RenderProcessHost::iterator hosts = RenderProcessHost::AllHostsIterator();
+    for (; !hosts.IsAtEnd(); hosts.Advance()) {
+      RenderProcessHost* render_process_host = hosts.GetCurrentValue();
+      DCHECK(render_process_host);
+      if (!render_process_host->HasConnection())
+        continue;
+      RenderProcessHost::listeners_iterator iter(
+          render_process_host->ListenersIterator());
+      for (; !iter.IsAtEnd(); iter.Advance()) {
+        const RenderWidgetHost* widget =
+            static_cast<const RenderWidgetHost*>(iter.GetCurrentValue());
+        DCHECK(widget);
+        if (!widget || !widget->IsRenderView())
+          continue;
+        RenderViewHost* host = const_cast<RenderViewHost*>(
+            static_cast<const RenderViewHost*>(widget));
+        RenderViewHostDelegate* host_delegate = host->delegate();
+        GURL url = host_delegate->GetURL();
+        if (url.SchemeIs(chrome::kChromeDevToolsScheme))
+          return host;
+      }
+    }
+    return NULL;
+  }
 };
 
 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ProcessPerTab) {
@@ -40,7 +70,7 @@
   int tab_count = 1;
   int host_count = 1;
 
-  // Change the first tab to be the new tab page (TYPE_DOMUI).
+  // Change the first tab to be the new tab page (TYPE_WEBUI).
   GURL newtab(chrome::kChromeUINewTabURL);
   ui_test_utils::NavigateToURL(browser(), newtab);
   EXPECT_EQ(tab_count, browser()->tab_count());
@@ -65,7 +95,7 @@
   EXPECT_EQ(tab_count, browser()->tab_count());
   EXPECT_EQ(host_count, RenderProcessHostCount());
 
-  // Create another new tab.  It should share the process with the other DOMUI.
+  // Create another new tab.  It should share the process with the other WebUI.
   browser()->NewTab();
   if (browser()->tab_count() == tab_count)
     ui_test_utils::WaitForNewTab(browser());
@@ -73,7 +103,7 @@
   EXPECT_EQ(tab_count, browser()->tab_count());
   EXPECT_EQ(host_count, RenderProcessHostCount());
 
-  // Create another new tab.  It should share the process with the other DOMUI.
+  // Create another new tab.  It should share the process with the other WebUI.
   browser()->NewTab();
   if (browser()->tab_count() == tab_count)
     ui_test_utils::WaitForNewTab(browser());
@@ -82,6 +112,73 @@
   EXPECT_EQ(host_count, RenderProcessHostCount());
 }
 
+// Ensure that DevTools opened to debug DevTools is launched in a separate
+// process when --process-per-tab is set. See crbug.com/69873.
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, DevToolsOnSelfInOwnProcessPPT) {
+  CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+  parsed_command_line.AppendSwitch(switches::kProcessPerTab);
+
+  int tab_count = 1;
+  int host_count = 1;
+
+  GURL page1("data:text/html,hello world1");
+  browser()->ShowSingletonTab(page1, false);
+  if (browser()->tab_count() == tab_count)
+    ui_test_utils::WaitForNewTab(browser());
+  tab_count++;
+  host_count++;
+  EXPECT_EQ(tab_count, browser()->tab_count());
+  EXPECT_EQ(host_count, RenderProcessHostCount());
+
+  // DevTools start in docked mode (no new tab), in a separate process.
+  browser()->ToggleDevToolsWindow(DEVTOOLS_TOGGLE_ACTION_INSPECT);
+  host_count++;
+  EXPECT_EQ(tab_count, browser()->tab_count());
+  EXPECT_EQ(host_count, RenderProcessHostCount());
+
+  RenderViewHost* devtools = FindFirstDevToolsHost();
+  DCHECK(devtools);
+
+  // DevTools start in a separate process.
+  DevToolsManager::GetInstance()->ToggleDevToolsWindow(
+      devtools, DEVTOOLS_TOGGLE_ACTION_INSPECT);
+  host_count++;
+  EXPECT_EQ(tab_count, browser()->tab_count());
+  EXPECT_EQ(host_count, RenderProcessHostCount());
+}
+
+// Ensure that DevTools opened to debug DevTools is launched in a separate
+// process. See crbug.com/69873.
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, DevToolsOnSelfInOwnProcess) {
+  int tab_count = 1;
+  int host_count = 1;
+
+  GURL page1("data:text/html,hello world1");
+  browser()->ShowSingletonTab(page1, false);
+  if (browser()->tab_count() == tab_count)
+    ui_test_utils::WaitForNewTab(browser());
+  tab_count++;
+  host_count++;
+  EXPECT_EQ(tab_count, browser()->tab_count());
+  EXPECT_EQ(host_count, RenderProcessHostCount());
+
+  // DevTools start in docked mode (no new tab), in a separate process.
+  browser()->ToggleDevToolsWindow(DEVTOOLS_TOGGLE_ACTION_INSPECT);
+  host_count++;
+  EXPECT_EQ(tab_count, browser()->tab_count());
+  EXPECT_EQ(host_count, RenderProcessHostCount());
+
+  RenderViewHost* devtools = FindFirstDevToolsHost();
+  DCHECK(devtools);
+
+  // DevTools start in a separate process.
+  DevToolsManager::GetInstance()->ToggleDevToolsWindow(
+      devtools, DEVTOOLS_TOGGLE_ACTION_INSPECT);
+  host_count++;
+  EXPECT_EQ(tab_count, browser()->tab_count());
+  EXPECT_EQ(host_count, RenderProcessHostCount());
+}
+
 // When we hit the max number of renderers, verify that the way we do process
 // sharing behaves correctly.  In particular, this test is verifying that even
 // when we hit the max process limit, that renderers of each type will wind up
@@ -100,7 +197,7 @@
   RenderProcessHost* rph2 = NULL;
   RenderProcessHost* rph3 = NULL;
 
-  // Change the first tab to be the new tab page (TYPE_DOMUI).
+  // Change the first tab to be the new tab page (TYPE_WEBUI).
   GURL newtab(chrome::kChromeUINewTabURL);
   ui_test_utils::NavigateToURL(browser(), newtab);
   EXPECT_EQ(tab_count, browser()->tab_count());
@@ -135,9 +232,9 @@
   EXPECT_EQ(host_count, RenderProcessHostCount());
   EXPECT_EQ(tab2->GetRenderProcessHost(), rph2);
 
-  // Create another TYPE_DOMUI tab.  It should share the process with newtab.
+  // Create another TYPE_WEBUI tab.  It should share the process with newtab.
   // Note: intentionally create this tab after the TYPE_NORMAL tabs to exercise
-  // bug 43448 where extension and DOMUI tabs could get combined into normal
+  // bug 43448 where extension and WebUI tabs could get combined into normal
   // renderers.
   GURL history(chrome::kChromeUIHistoryURL);
   browser()->ShowSingletonTab(history, false);
diff --git a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc
index 67c0dfb..6e37723 100644
--- a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc
+++ b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc
@@ -117,9 +117,9 @@
   {
     ExecuteNotificationObserver observer;
     ExecuteJavascriptAndGetValue("42.2;", &observer);
-    EXPECT_EQ(Value::TYPE_REAL, observer.value()->GetType());
+    EXPECT_EQ(Value::TYPE_DOUBLE, observer.value()->GetType());
     double double_value;
-    EXPECT_TRUE(observer.value()->GetAsReal(&double_value));
+    EXPECT_TRUE(observer.value()->GetAsDouble(&double_value));
     EXPECT_EQ(42.2, double_value);
   }
 
@@ -149,9 +149,9 @@
   {
     ExecuteNotificationObserver observer;
     ExecuteJavascriptAndGetValue("new Date(1);", &observer);
-    EXPECT_EQ(Value::TYPE_REAL, observer.value()->GetType());
+    EXPECT_EQ(Value::TYPE_DOUBLE, observer.value()->GetType());
     double date_seconds;
-    EXPECT_TRUE(observer.value()->GetAsReal(&date_seconds));
+    EXPECT_TRUE(observer.value()->GetAsDouble(&date_seconds));
 
     base::Time time = base::Time::FromDoubleT(date_seconds);
 
@@ -170,9 +170,9 @@
     ExecuteNotificationObserver observer;
     ExecuteJavascriptAndGetValue("new Date(Date.UTC(2006, 7, 16, 12, 0, 15));",
                                  &observer);
-    EXPECT_EQ(Value::TYPE_REAL, observer.value()->GetType());
+    EXPECT_EQ(Value::TYPE_DOUBLE, observer.value()->GetType());
     double date_seconds;
-    EXPECT_TRUE(observer.value()->GetAsReal(&date_seconds));
+    EXPECT_TRUE(observer.value()->GetAsDouble(&date_seconds));
 
     base::Time time = base::Time::FromDoubleT(date_seconds);
 
diff --git a/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc b/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc
index ba02667..a5ea2f6 100644
--- a/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc
+++ b/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,7 +12,6 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
@@ -211,13 +210,13 @@
 
   TabContents *contents = browser()->GetSelectedTabContents();
   ASSERT_TRUE(contents);
-  bool domui_responded = false;
+  bool webui_responded = false;
   EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
       contents->render_view_host(),
       L"",
-      L"window.domAutomationController.send(window.domui_responded_);",
-      &domui_responded));
-  EXPECT_TRUE(domui_responded);
+      L"window.domAutomationController.send(window.webui_responded_);",
+      &webui_responded));
+  EXPECT_TRUE(webui_responded);
 }
 
 class BrowserClosedObserver : public NotificationObserver {
diff --git a/chrome/browser/renderer_host/test/render_view_host_unittest.cc b/chrome/browser/renderer_host/test/render_view_host_unittest.cc
index da5a579..48f0c50 100644
--- a/chrome/browser/renderer_host/test/render_view_host_unittest.cc
+++ b/chrome/browser/renderer_host/test/render_view_host_unittest.cc
@@ -6,6 +6,7 @@
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/test_tab_contents.h"
+#include "chrome/common/page_transition_types.h"
 #include "chrome/common/render_messages.h"
 
 class RenderViewHostTest : public RenderViewHostTestHarness {
@@ -22,7 +23,7 @@
 // Create a full screen popup RenderWidgetHost and View.
 TEST_F(RenderViewHostTest, CreateFullscreenWidget) {
   int routing_id = process()->GetNextRoutingID();
-  rvh()->CreateNewFullscreenWidget(routing_id, WebKit::WebPopupTypeNone);
+  rvh()->CreateNewFullscreenWidget(routing_id);
 }
 
 // Makes sure that RenderViewHost::is_waiting_for_unload_ack_ is false when
@@ -45,7 +46,7 @@
   //     fires the tab gets closed.
 
   NavigateAndCommit(url1);
-  controller().LoadURL(url2, GURL(), 0);
+  controller().LoadURL(url2, GURL(), PageTransition::LINK);
   // Simulate the ClosePage call which is normally sent by the net::URLRequest.
   rvh()->ClosePage(true, 0, 0);
   // Needed so that navigations are not suspended on the RVH. Normally handled
diff --git a/chrome/browser/renderer_host/test/site_instance_unittest.cc b/chrome/browser/renderer_host/test/site_instance_unittest.cc
index fb0e2da..c887607 100644
--- a/chrome/browser/renderer_host/test/site_instance_unittest.cc
+++ b/chrome/browser/renderer_host/test/site_instance_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -439,10 +439,10 @@
   EXPECT_EQ(extension1_instance->GetProcess(),
             extension2_instance->GetProcess());
 
-  // Create some DOMUI instances and make sure they share a process.
+  // Create some WebUI instances and make sure they share a process.
   scoped_refptr<SiteInstance> dom1_instance(
       CreateSiteInstance(&rph_factory, GURL("chrome://newtab")));
-  policy->GrantDOMUIBindings(dom1_instance->GetProcess()->id());
+  policy->GrantWebUIBindings(dom1_instance->GetProcess()->id());
 
   scoped_refptr<SiteInstance> dom2_instance(
       CreateSiteInstance(&rph_factory, GURL("chrome://history")));
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 1c2e4b4..60e9f33 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -13,7 +13,7 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/test/testing_profile.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/webpreferences.h"
 #include "webkit/glue/password_form.h"
 
@@ -111,6 +111,35 @@
 TestRenderWidgetHostView::~TestRenderWidgetHostView() {
 }
 
+RenderWidgetHost* TestRenderWidgetHostView::GetRenderWidgetHost() const {
+  return NULL;
+}
+
+gfx::NativeView TestRenderWidgetHostView::GetNativeView() {
+  return NULL;
+}
+
+bool TestRenderWidgetHostView::HasFocus() {
+  return true;
+}
+
+void TestRenderWidgetHostView::Show() {
+  is_showing_ = true;
+}
+
+void TestRenderWidgetHostView::Hide() {
+  is_showing_ = false;
+}
+
+bool TestRenderWidgetHostView::IsShowing() {
+  return is_showing_;
+}
+
+void TestRenderWidgetHostView::RenderViewGone(base::TerminationStatus status,
+                                              int error_code) {
+  delete this;
+}
+
 gfx::Rect TestRenderWidgetHostView::GetViewBounds() const {
   return gfx::Rect();
 }
@@ -131,7 +160,7 @@
     bool right_aligned) {
 }
 
-gfx::Rect TestRenderWidgetHostView::GetWindowRect() {
+gfx::Rect TestRenderWidgetHostView::GetViewCocoaBounds() const {
   return gfx::Rect();
 }
 
@@ -143,8 +172,11 @@
   // <viettrungluu@gmail.com>: Do I need to do anything here?
 }
 
-void TestRenderWidgetHostView::SetPluginImeEnabled(bool enabled,
-                                                   int plugin_id) {
+void TestRenderWidgetHostView::PluginFocusChanged(bool focused,
+                                                  int plugin_id) {
+}
+
+void TestRenderWidgetHostView::StartPluginIme() {
 }
 
 bool TestRenderWidgetHostView::PostProcessEventForPluginIme(
@@ -199,6 +231,11 @@
 }
 #endif
 
+bool TestRenderWidgetHostView::ContainsNativeView(
+    gfx::NativeView native_view) const {
+  return false;
+}
+
 TestRenderViewHostFactory::TestRenderViewHostFactory(
     RenderProcessHostFactory* rph_factory)
     : render_process_host_factory_(rph_factory) {
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index 70f2d11..dfc3d53 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -53,12 +53,12 @@
 
   virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
                            const gfx::Rect& pos) {}
-  virtual void InitAsFullscreen(RenderWidgetHostView* parent_host_view) {}
-  virtual RenderWidgetHost* GetRenderWidgetHost() const { return NULL; }
+  virtual void InitAsFullscreen() {}
+  virtual RenderWidgetHost* GetRenderWidgetHost() const;
   virtual void DidBecomeSelected() {}
   virtual void WasHidden() {}
   virtual void SetSize(const gfx::Size& size) {}
-  virtual gfx::NativeView GetNativeView() { return NULL; }
+  virtual gfx::NativeView GetNativeView();
   virtual void MovePluginWindows(
       const std::vector<webkit::npapi::WebPluginGeometry>& moves) {}
 #if defined(OS_WIN)
@@ -68,11 +68,11 @@
 #endif
   virtual void Focus() {}
   virtual void Blur() {}
-  virtual bool HasFocus() { return true; }
+  virtual bool HasFocus();
   virtual void AdvanceFocus(bool reverse) {}
-  virtual void Show() { is_showing_ = true; }
-  virtual void Hide() { is_showing_ = false; }
-  virtual bool IsShowing() { return is_showing_; }
+  virtual void Show();
+  virtual void Hide();
+  virtual bool IsShowing();
   virtual gfx::Rect GetViewBounds() const;
   virtual void SetIsLoading(bool is_loading) {}
   virtual void UpdateCursor(const WebCursor& cursor) {}
@@ -84,7 +84,7 @@
       const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
       const std::vector<gfx::Rect>& rects) {}
   virtual void RenderViewGone(base::TerminationStatus status,
-                              int error_code) { delete this; }
+                              int error_code);
   virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { }
   virtual void Destroy() {}
   virtual void PrepareToDestroy() {}
@@ -98,12 +98,13 @@
                                   int selected_item,
                                   const std::vector<WebMenuItem>& items,
                                   bool right_aligned);
-  virtual gfx::Rect GetWindowRect();
+  virtual gfx::Rect GetViewCocoaBounds() const;
   virtual gfx::Rect GetRootWindowRect();
   virtual void SetActive(bool active);
   virtual void SetWindowVisibility(bool visible) {}
   virtual void WindowFrameChanged() {}
-  virtual void SetPluginImeEnabled(bool enabled, int plugin_id);
+  virtual void PluginFocusChanged(bool focused, int plugin_id);
+  virtual void StartPluginIme();
   virtual bool PostProcessEventForPluginIme(
       const NativeWebKeyboardEvent& event);
   virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(
@@ -139,9 +140,7 @@
   virtual void AcceleratedCompositingActivated(bool activated) { }
 #endif
 
-  virtual bool ContainsNativeView(gfx::NativeView native_view) const {
-    return false;
-  }
+  virtual bool ContainsNativeView(gfx::NativeView native_view) const;
 
   bool is_showing() const { return is_showing_; }
 
diff --git a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
index 3681c70..4926d26 100644
--- a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
+++ b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
@@ -20,8 +20,8 @@
 
 // Regression test for http://crbug.com/12362.  If a renderer crashes and the
 // user navigates to another tab and back, the browser doesn't crash.
-// Flaky, http://crbug.com/15288.
-IN_PROC_BROWSER_TEST_F(WebCacheManagerBrowserTest, FLAKY_CrashOnceOnly) {
+// Flaky, http://crbug.com/15288. Disabled, http://crbug.com/69918.
+IN_PROC_BROWSER_TEST_F(WebCacheManagerBrowserTest, DISABLED_CrashOnceOnly) {
   const FilePath kTestDir(FILE_PATH_LITERAL("google"));
   const FilePath kTestFile(FILE_PATH_LITERAL("google.html"));
   GURL url(ui_test_utils::GetTestUrl(kTestDir, kTestFile));
diff --git a/chrome/browser/renderer_host/web_cache_manager.h b/chrome/browser/renderer_host/web_cache_manager.h
index 1bd266b..327aa4f 100644
--- a/chrome/browser/renderer_host/web_cache_manager.h
+++ b/chrome/browser/renderer_host/web_cache_manager.h
@@ -17,7 +17,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/task.h"
 #include "base/time.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
 
 template<typename Type>
 struct DefaultSingletonTraits;
diff --git a/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc b/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc
index 68b62ca..c4703c1 100644
--- a/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc
+++ b/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -93,9 +93,9 @@
 
 bool X509UserCertResourceHandler::OnResponseCompleted(
     int request_id,
-    const URLRequestStatus& urs,
+    const net::URLRequestStatus& urs,
     const std::string& sec_info) {
-  if (urs.status() != URLRequestStatus::SUCCESS)
+  if (urs.status() != net::URLRequestStatus::SUCCESS)
     return false;
 
   // TODO(gauravsh): Verify that 'request_id' was actually a keygen form post
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index bfa0811..e487b93 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,8 +7,8 @@
 #include "chrome/browser/profiles/profile.h"
 
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #endif
 
 namespace renderer_preferences_util {
@@ -31,7 +31,7 @@
   prefs->inactive_selection_fg_color =
       provider->get_inactive_selection_fg_color();
 #else
-  prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0);
+  prefs->focus_ring_color = SkColorSetRGB(0x50, 0x7A, 0xD5);
   prefs->active_selection_bg_color = SkColorSetRGB(0xDC, 0xE4, 0xFA);
   prefs->active_selection_fg_color = SK_ColorBLACK;
   prefs->inactive_selection_bg_color = SkColorSetRGB(0xF7, 0xF7, 0xF7);
diff --git a/chrome/browser/repost_form_warning_uitest.cc b/chrome/browser/repost_form_warning_uitest.cc
index a80ac97..32f6d78 100644
--- a/chrome/browser/repost_form_warning_uitest.cc
+++ b/chrome/browser/repost_form_warning_uitest.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/browser_proxy.h"
diff --git a/chrome/browser/resources/OWNERS b/chrome/browser/resources/OWNERS
new file mode 100644
index 0000000..741a5c4
--- /dev/null
+++ b/chrome/browser/resources/OWNERS
@@ -0,0 +1 @@
+arv@chromium.org
diff --git a/chrome/browser/resources/about_credits.html b/chrome/browser/resources/about_credits.html
index 4f617a6..4734ba8 100644
--- a/chrome/browser/resources/about_credits.html
+++ b/chrome/browser/resources/about_credits.html
@@ -653,6 +653,43 @@
 
 
 <div class="product">
+<span class="title">Launchpad Translations</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://people.ubuntu.com/~fta/chromium/translations/trunk/patched-files/chrome/app/resources/">homepage</a></span>
+<div class="licence">
+<pre>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 the copyright holders 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
+HOLDER 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.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">Mozilla Personal Security Manager</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://mxr.mozilla.org/mozilla-central/source/security/manager/">homepage</a></span>
@@ -727,6 +764,217 @@
 
 
 <div class="product">
+<span class="title">Google Toolbox for Mac</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://code.google.com/p/google-toolbox-for-mac/">homepage</a></span>
+<div class="licence">
+<pre>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2007 Google Inc.
+
+   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.</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">WebKit</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://webkit.org/">homepage</a></span>
@@ -1704,6 +1952,68 @@
 
 
 <div class="product">
+<span class="title">ActiveX Scripting SDK</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://support.microsoft.com/kb/223389">homepage</a></span>
+<div class="licence">
+<pre>THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS
+
+PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.  MICROSOFT DISCLAIMS
+
+ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES
+
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
+
+EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
+
+ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
+
+CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
+
+MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
+
+POSSIBILITY OF SUCH DAMAGES.  SOME STATES DO NOT ALLOW THE EXCLUSION
+
+OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES
+
+SO THE FOREGOING LIMITATION MAY NOT APPLY.
+
+
+
+MICROSOFT DOES NOT WARRANT THAT THE FUNCTIONS FOR THE LICENSED SOFTWARE 
+
+OR CODE CONTAINED IN THE KNOWLEDGE BASE WILL MEET YOUR REQUIREMENTS, OR 
+
+THAT THE OPERATION OF THE LICENSED SOFTWARE OR CODE WILL BE UNINTERRUPTED 
+
+OR ERROR-FREE, OR THAT DEFECTS IN THE LICENSED SOFTWARE OR CODE CAN BE 
+
+CORRECTED.  FURTHERMORE, MICROSOFT DOES NOT WARRANT OR MAKE ANY 
+
+REPRESENTATIONS REGARDING THE USE OR THE RESULTS OF THE USE OF THE LICENSED 
+
+SOFTWARE, CODE OR RELATED DOCUMENTATION IN TERMS OF THEIR CORRECTNESS, 
+
+ACCURACY, RELIABILITY, OR OTHERWISE.  NO ORAL OR WRITTEN INFORMATION OR ADVICE 
+
+GIVEN BY MICROSOFT OR ITS AUTHORIZED REPRESENTATIVES SHALL CREATE A WARRANTY 
+
+OR IN ANY WAY INCREASE THE SCOPE OF THIS WARRANTY.  SHOULD THE LICENSED 
+
+SOFTWARE OR CODE PROVE DEFECTIVE AFTER MICROSOFT HAS DELIVERED THE SAME, 
+
+YOU, AND YOU ALONE, SHALL ASSUME THE ENTIRE COST ASSOCIATED WITH ALL 
+
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+
+
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">Almost Native Graphics Layer Engine</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://code.google.com/p/angleproject/">homepage</a></span>
@@ -3303,6 +3613,62 @@
 
 
 <div class="product">
+<span class="title">ffmpeg</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://ffmpeg.org/">homepage</a></span>
+<div class="licence">
+<pre>FFmpeg:
+-------
+
+Most files in FFmpeg are under the GNU Lesser General Public License version 2.1
+or later (LGPL v2.1+). Read the file COPYING.LGPLv2.1 for details. Some other
+files have MIT/X11/BSD-style licenses. In combination the LGPL v2.1+ applies to
+FFmpeg.
+
+Some optional parts of FFmpeg are licensed under the GNU General Public License
+version 2 or later (GPL v2+). See the file COPYING.GPLv2 for details. None of
+these parts are used by default, you have to explicitly pass --enable-gpl to
+configure to activate them. In this case, FFmpeg's license changes to GPL v2+.
+
+Specifically, the GPL parts of FFmpeg are
+
+- libpostproc
+- optional x86 optimizations in the files
+  libavcodec/x86/idct_mmx.c
+- the X11 grabber in libavdevice/x11grab.c
+
+There are a handful of files under other licensing terms, namely:
+
+* The files libavcodec/jfdctfst.c, libavcodec/jfdctint.c, libavcodec/jrevdct.c
+  are taken from libjpeg, see the top of the files for licensing details.
+
+Should you, for whatever reason, prefer to use version 3 of the (L)GPL, then
+the configure parameter --enable-version3 will activate this licensing option
+for you. Read the file COPYING.LGPLv3 or, if you have enabled GPL parts,
+COPYING.GPLv3 to learn the exact legal terms that apply in this case.
+
+
+external libraries:
+-------------------
+
+Some external libraries, e.g. libx264, are under GPL and can be used in
+conjunction with FFmpeg. They require --enable-gpl to be passed to configure
+as well.
+
+The OpenCORE external libraries are under the Apache License 2.0. That license
+is incompatible with the LGPL v2.1 and the GPL v2, but not with version 3 of
+those licenses. So to combine the OpenCORE libraries with FFmpeg, the license
+version needs to be upgraded by passing --enable-version3 to configure.
+
+The nonfree external library libfaac can be hooked up in FFmpeg. You need to
+pass --enable-nonfree to configure to enable it. Employ this option with care
+as FFmpeg then becomes nonfree and unredistributable.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">OpenGL ES 2.0 Programming Guide</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://opengles-book.com/">homepage</a></span>
@@ -3324,44 +3690,83 @@
 <span class="homepage"><a href="https://www.khronos.org/opengles/adopters/login/conformance/">homepage</a></span>
 <div class="licence">
 <pre>/*
+
 ** Copyright (c) 2008 The Khronos Group Inc.
+
 ** 
+
 ** All Rights Reserved.  This code is protected by copyright laws and 
+
 ** contains material proprietary to the Khronos Group, Inc.  This is 
+
 ** UNPUBLISHED PROPRIETARY SOURCE CODE that may not be disclosed in whole 
+
 ** or in part to third parties, and may not be reproduced, republished, 
+
 ** distributed, transmitted, displayed, broadcast or otherwise exploited 
+
 ** in any manner without the express prior written permission of Khronos 
+
 ** Group.
+
 ** 
+
 ** The receipt or possession of this code does not convey any rights to 
+
 ** reproduce, disclose, or distribute its contents, or to manufacture, 
+
 ** use, or sell anything that it may describe, in whole or in part other 
+
 ** than under the terms of the Khronos Adopters Agreement or Khronos 
+
 ** Conformance Test Source License Agreement as executed between Khronos 
+
 ** and the recipient.
+
 ** 
+
 ** For the avoidance of doubt, this code when provided: a) under the 
+
 ** Khronos Conformance Test Source License Agreement is for the sole 
+
 ** purpose of creating conformance tests for delivery to Khronos and does 
+
 ** not provide for formally testing products or use of Khronos trademarks 
+
 ** on conformant products; b) under the Khronos Adopters Agreement is for 
+
 ** the sole purpose of formally administering tests to products pursuant 
+
 ** to the Khronos Conformance Process Document.
+
 ** 
+
 ** Khronos, OpenKODE, OpenVG, OpenWF, glFX, OpenMAX and OpenSL ES are 
+
 ** trademarks of the Khronos Group Inc.  COLLADA is a trademark of Sony 
+
 ** Computer Entertainment Inc. used by permission by Khronos.  OpenGL and 
+
 ** OpenML are registered trademarks and the OpenGL ES logo is a trademark 
+
 ** of Silicon Graphics Inc. used by permission by Khronos. 
+
 ** 
+
 ** Use, duplication or disclosure by the Government is subject to 
+
 ** restrictions as set forth in subdivision (c)(1)(ii) of the Rights in 
+
 ** Technical Data and Computer Software clause at DFARS 252.227-7013, and/
+
 ** or in similar or successor clauses in the FAR, DOD or NASA FAR 
+
 ** Supplement. Unpublished rights reserved under the Copyright Laws of 
+
 ** the United States and other countries.
+
 */
+
 </pre>
 </div>
 </div>
@@ -3919,35 +4324,65 @@
 <span class="homepage"><a href="http://hg.mozilla.org/mozilla-central/src/memory">homepage</a></span>
 <div class="licence">
 <pre>The following is the license for the jemalloc source code, as provided
+
 in the initial section of the source files.
 
+
+
 Copyright (C) 2006-2008 Jason Evans &lt;jasone@FreeBSD.org&gt;.
+
 All rights reserved.
 
+
+
 Redistribution and use in source and binary forms, with or without
+
 modification, are permitted provided that the following conditions
+
 are met:
+
 1. Redistributions of source code must retain the above copyright
+
    notice(s), this list of conditions and the following disclaimer as
+
    the first lines of this file unmodified other than the possible
+
    addition of one or more copyright notices.
+
 2. Redistributions in binary form must reproduce the above copyright
+
    notice(s), this list of conditions and the following disclaimer in
+
    the documentation and/or other materials provided with the
+
    distribution.
 
+
+
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 HOLDER(S) 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.
 
+
+
 </pre>
 </div>
 </div>
@@ -4135,6 +4570,69 @@
 
 
 <div class="product">
+<span class="title">libjpeg-turbo</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://sourceforge.net/projects/libjpeg-turbo/">homepage</a></span>
+<div class="licence">
+<pre>                wxWindows Library Licence, Version 3.1
+                ======================================
+
+  Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
+
+  Everyone is permitted to copy and distribute verbatim copies
+  of this licence document, but changing it is not allowed.
+
+                       WXWINDOWS LIBRARY LICENCE
+     TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+  
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public Licence as published by
+  the Free Software Foundation; either version 2 of the Licence, or (at
+  your option) any later version.
+  
+  This library is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library
+  General Public Licence for more details.
+
+  You should have received a copy of the GNU Library General Public Licence
+  along with this software, usually in a file named COPYING.LIB.  If not,
+  write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA 02111-1307 USA.
+
+  EXCEPTION NOTICE
+
+  1. As a special exception, the copyright holders of this library give
+  permission for additional uses of the text contained in this release of
+  the library as licenced under the wxWindows Library Licence, applying
+  either version 3.1 of the Licence, or (at your option) any later version of
+  the Licence as published by the copyright holders of version
+  3.1 of the Licence document.
+
+  2. The exception is that you may use, copy, link, modify and distribute
+  under your own terms, binary object code versions of works based
+  on the Library.
+
+  3. If you copy code from files distributed under the terms of the GNU
+  General Public Licence or the GNU Library General Public Licence into a
+  copy of this library, as this licence permits, the exception does not
+  apply to the code that you add in this way.  To avoid misleading anyone as
+  to the status of such modified files, you must delete this exception
+  notice from such code and/or adjust the licensing conditions notice
+  accordingly.
+
+  4. If you write modifications of your own for this library, it is your
+  choice whether to permit this exception to apply to your modifications. 
+  If you do not wish that, you must delete the exception notice from such
+  code and/or adjust the licensing conditions notice accordingly.
+
+
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">libpng</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://libpng.org/">homepage</a></span>
@@ -5261,6 +5759,143 @@
 
 
 <div class="product">
+<span class="title">openssl</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://openssl.org/source/">homepage</a></span>
+<div class="licence">
+<pre>
+  LICENSE ISSUES
+  ==============
+
+  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+  the OpenSSL License and the original SSLeay license apply to the toolkit.
+  See below for the actual license texts. Actually both licenses are BSD-style
+  Open Source licenses. In case of any license issues related to OpenSSL
+  please contact openssl-core@openssl.org.
+
+  OpenSSL License
+  ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">OTS (OpenType Sanitizer)</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://code.google.com/p/ots/">homepage</a></span>
@@ -5298,6 +5933,217 @@
 
 
 <div class="product">
+<span class="title">pdfsqueeze</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://code.google.com/p/pdfsqueeze/">homepage</a></span>
+<div class="licence">
+<pre>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2007 Google Inc.
+
+   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.</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">ppapi</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://code.google.com/p/ppapi/">homepage</a></span>
@@ -5409,6 +6255,187 @@
 
 
 <div class="product">
+<span class="title">pywebsocket</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://code.google.com/p/pywebsocket/">homepage</a></span>
+<div class="licence">
+<pre>Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * 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.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
+<span class="title">qcms library</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://mxr.mozilla.org/mozilla-central/source/gfx/qcms/">homepage</a></span>
+<div class="licence">
+<pre>This license applies to certain files in the directory third_party/qcms/.
+
+
+
+Copyright (C) 2009 Mozilla Corporation
+
+Copyright (C) 1998-2007 Marti Maria
+
+
+
+Permission is hereby granted, free of charge, to any person
+
+obtaining a copy of this software and associated documentation 
+
+files (the "Software"), to deal in the Software without restriction, 
+
+including without limitation the rights to use, copy, modify, merge, 
+
+publish, distribute, sublicense, and/or sell copies of the Software, 
+
+and to permit persons to whom the Software is furnished to do so, subject 
+
+to the following conditions:
+
+
+
+The above copyright notice and this permission notice shall be included 
+
+in all copies or substantial portions of the Software.
+
+
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
+
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+
+
+
+
+This license applies to the ICC_H block in third_party/qcms/qcms.h.
+
+
+
+Copyright (c) 1994-1996 SunSoft, Inc.
+
+
+
+                    Rights Reserved
+
+
+
+Permission is hereby granted, free of charge, to any person 
+
+obtaining a copy of this software and associated documentation
+
+files (the "Software"), to deal in the Software without restrict- 
+
+ion, including without limitation the rights to use, copy, modify, 
+
+merge, publish distribute, sublicense, and/or sell copies of the 
+
+Software, and to permit persons to whom the Software is furnished 
+
+to do so, subject to the following conditions: 
+
+ 
+
+The above copyright notice and this permission notice shall be 
+
+included in all copies or substantial portions of the Software. 
+
+ 
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
+
+INFRINGEMENT.  IN NO EVENT SHALL SUNSOFT, INC. OR ITS PARENT 
+
+COMPANY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
+
+OTHER DEALINGS IN THE SOFTWARE. 
+
+ 
+
+Except as contained in this notice, the name of SunSoft, Inc. 
+
+shall not be used in advertising or otherwise to promote the 
+
+sale, use or other dealings in this Software without written 
+
+authorization from SunSoft Inc. 
+
+</pre>
+</div>
+</div>
+
+
+<div class="product">
+<span class="title">Google Safe Browsing</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://code.google.com/p/google-safe-browsing/">homepage</a></span>
+<div class="licence">
+<pre>Copyright 2009 Google Inc.
+
+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.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">simplejson</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://undefined.org/python/#simplejson">homepage</a></span>
@@ -5816,6 +6843,38 @@
 
 
 <div class="product">
+<span class="title">talloc</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://talloc.samba.org/talloc/doc/html/index.html">homepage</a></span>
+<div class="licence">
+<pre>   Unix SMB/CIFS implementation.
+   Samba temporary memory allocation functions
+
+   Copyright (C) Andrew Tridgell 2004-2005
+   Copyright (C) Stefan Metzmacher 2006
+   
+     ** NOTE! The following LGPL license applies to the talloc
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see &lt;http://www.gnu.org/licenses/&gt;.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">tcmalloc</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://google-perftools.googlecode.com/">homepage</a></span>
@@ -6060,70 +7119,135 @@
 <span class="homepage"><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e5ba5ba4-6e6b-462a-b24c-61115e846f0c">homepage</a></span>
 <div class="licence">
 <pre>Microsoft Permissive License (Ms-PL)
+
 Published: October 12, 2006
 
 
+
+
+
 This license governs use of the accompanying software. If you use the software,
+
 you accept this license. If you do not accept the license, do not use the
+
 software.
 
 
+
+
+
 1. Definitions
 
+
+
 The terms "reproduce," "reproduction," "derivative works," and "distribution"
+
 have the same meaning here as under U.S. copyright law.
 
+
+
 A "contribution" is the original software, or any additions or changes to the
+
 software.
 
+
+
 A "contributor" is any person that distributes its contribution under this
+
 license.
 
+
+
 "Licensed patents" are a contributor’s patent claims that read directly on its
+
 contribution.
 
 
+
+
+
 2. Grant of Rights
 
+
+
 (A) Copyright Grant- Subject to the terms of this license, including the
+
 license conditions and limitations in section 3, each contributor grants you a
+
 non-exclusive, worldwide, royalty-free copyright license to reproduce its
+
 contribution, prepare derivative works of its contribution, and distribute its
+
 contribution or any derivative works that you create.
 
+
+
 (B) Patent Grant- Subject to the terms of this license, including the license
+
 conditions and limitations in section 3, each contributor grants you a
+
 non-exclusive, worldwide, royalty-free license under its licensed patents to
+
 make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
+
 its contribution in the software or derivative works of the contribution in the
+
 software.
 
 
+
+
+
 3. Conditions and Limitations
 
+
+
 (A) No Trademark License- This license does not grant you rights to use any
+
 contributors’ name, logo, or trademarks.
 
+
+
 (B) If you bring a patent claim against any contributor over patents that you
+
 claim are infringed by the software, your patent license from such contributor
+
 to the software ends automatically.
 
+
+
 (C) If you distribute any portion of the software, you must retain all
+
 copyright, patent, trademark, and attribution notices that are present in the
+
 software.
 
+
+
 (D) If you distribute any portion of the software in source code form, you may
+
 do so only under this license by including a complete copy of this license with
+
 your distribution. If you distribute any portion of the software in compiled or
+
 object code form, you may only do so under a license that complies with this
+
 license.
 
+
+
 (E) The software is licensed "as-is." You bear the risk of using it. The
+
 contributors give no express warranties, guarantees or conditions. You may have
+
 additional consumer rights under your local laws which this license cannot
+
 change. To the extent permitted under your local laws, the contributors exclude
+
 the implied warranties of merchantability, fitness for a particular purpose and
+
 non-infringement.
+
 </pre>
 </div>
 </div>
@@ -6158,22 +7282,600 @@
 
 
 <div class="product">
+<span class="title">XUL Runner SDK</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="https://developer.mozilla.org/en/Gecko_SDK">homepage</a></span>
+<div class="licence">
+<pre>                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
+
+                              ---------------
+
+1. Definitions.
+
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
+
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
+
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
+
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
+
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation, method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your") means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a) under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code; or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a) under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d) Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2) separate from the Contributor Version;
+          3) for infringements caused by: i) third party modifications of
+          Contributor Version or ii) the combination of Modifications made
+          by that Contributor with other software (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+          (c) Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code. If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice. If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A. You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code. You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+     8.1. This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2. If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant") alleging that:
+
+     (a) such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant. If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b) any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3. If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4. In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+     ``The contents of this file are subject to the Mozilla Public License
+     Version 1.1 (the "License"); you may not use this file except in
+     compliance with the License. You may obtain a copy of the License at
+     http://www.mozilla.org/MPL/
+
+     Software distributed under the License is distributed on an "AS IS"
+     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+     License for the specific language governing rights and limitations
+     under the License.
+
+     The Original Code is ______________________________________.
+
+     The Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above. If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting the provisions above and replace them with the notice and
+     other provisions required by the [___] License. If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
+     ----------------------------------------------------------------------
+
+     AMENDMENTS
+
+     The Netscape Public License Version 1.1 ("NPL") consists of the
+     Mozilla Public License Version 1.1 with the following Amendments,
+     including Exhibit A-Netscape Public License. Files identified with
+     "Exhibit A-Netscape Public License" are governed by the Netscape
+     Public License Version 1.1.
+
+     Additional Terms applicable to the Netscape Public License.
+          I. Effect.
+          These additional terms described in this Netscape Public
+          License -- Amendments shall apply to the Mozilla Communicator
+          client code and to all Covered Code under this License.
+
+          II. "Netscape's Branded Code" means Covered Code that Netscape
+          distributes and/or permits others to distribute under one or more
+          trademark(s) which are controlled by Netscape but which are not
+          licensed for use under this License.
+
+          III. Netscape and logo.
+          This License does not grant any rights to use the trademarks
+          "Netscape", the "Netscape N and horizon" logo or the "Netscape
+          lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript",
+          "Smart Browsing" even if such marks are included in the Original
+          Code or Modifications.
+
+          IV. Inability to Comply Due to Contractual Obligation.
+          Prior to licensing the Original Code under this License, Netscape
+          has licensed third party code for use in Netscape's Branded Code.
+          To the extent that Netscape is limited contractually from making
+          such third party code available under this License, Netscape may
+          choose to reintegrate such code into Covered Code without being
+          required to distribute such code in Source Code form, even if
+          such code would otherwise be considered "Modifications" under
+          this License.
+
+          V. Use of Modifications and Covered Code by Initial Developer.
+               V.1. In General.
+               The obligations of Section 3 apply to Netscape, except to
+               the extent specified in this Amendment, Section V.2 and V.3.
+
+               V.2. Other Products.
+               Netscape may include Covered Code in products other than the
+               Netscape's Branded Code which are released by Netscape
+               during the two (2) years following the release date of the
+               Original Code, without such additional products becoming
+               subject to the terms of this License, and may license such
+               additional products on different terms from those contained
+               in this License.
+
+               V.3. Alternative Licensing.
+               Netscape may license the Source Code of Netscape's Branded
+               Code, including Modifications incorporated therein, without
+               such Netscape Branded Code becoming subject to the terms of
+               this License, and may license such Netscape Branded Code on
+               different terms from those contained in this License.
+
+          VI. Litigation.
+          Notwithstanding the limitations of Section 11 above, the
+          provisions regarding litigation in Section 11(a), (b) and (c) of
+          the License shall apply to all disputes relating to this License.
+
+     EXHIBIT A-Netscape Public License.
+
+          "The contents of this file are subject to the Netscape Public
+          License Version 1.1 (the "License"); you may not use this file
+          except in compliance with the License. You may obtain a copy of
+          the License at http://www.mozilla.org/NPL/
+
+          Software distributed under the License is distributed on an "AS
+          IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+          implied. See the License for the specific language governing
+          rights and limitations under the License.
+
+          The Original Code is Mozilla Communicator client code, released
+          March 31, 1998.
+
+          The Initial Developer of the Original Code is Netscape
+          Communications Corporation. Portions created by Netscape are
+          Copyright (C) 1998-1999 Netscape Communications Corporation. All
+          Rights Reserved.
+
+          Contributor(s): ______________________________________.
+
+          Alternatively, the contents of this file may be used under the
+          terms of the _____ license (the "[___] License"), in which case
+          the provisions of [______] License are applicable  instead of
+          those above. If you wish to allow use of your version of this
+          file only under the terms of the [____] License and not to allow
+          others to use your version of this file under the NPL, indicate
+          your decision by deleting the provisions above and replace  them
+          with the notice and other provisions required by the [___]
+          License. If you do not delete the provisions above, a recipient
+          may use your version of this file under either the NPL or the
+          [___] License."
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">yasm</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://www.tortall.net/projects/yasm/">homepage</a></span>
 <div class="licence">
-<pre>Yasm is Copyright (c) 2001-2009 Peter Johnson and other Yasm developers.
+<pre>Yasm is Copyright (c) 2001-2010 Peter Johnson and other Yasm developers.
 
 Yasm developers and/or contributors include:
   Peter Johnson
   Michael Urman
-  Brian Gladman (VC8 build files, other fixes)
+  Brian Gladman (Visual Studio build files, other fixes)
   Stanislav Karchebny (options parser)
-  Mathieu Monnier (SSE4 instruction patches)
+  Mathieu Monnier (SSE4 instruction patches, NASM preprocessor additions)
   Anonymous "NASM64" developer (NASM preprocessor fixes)
   Stephen Polkowski (x86 instruction patches)
   Henryk Richter (Mach-O object format)
   Ben Skeggs (patches, bug reports)
+  Alexei Svitkine (GAS preprocessor)
   Samuel Thibault (TASM parser and frontend)
 
 -----------------------------------
@@ -6203,8 +7905,7 @@
 -------
 Modules
 -------
-The modules are 2-clause or 3-clause BSD licensed, with the exception of:
- preprocs/nasm - LGPL licensed
+The modules are 2-clause or 3-clause BSD licensed.
 
 ---------
 Frontends
@@ -6263,6 +7964,72 @@
 </div>
 
 
+<div class="product">
+<span class="title">Strongtalk</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://www.strongtalk.org/">homepage</a></span>
+<div class="licence">
+<pre>Copyright (c) 1994-2006 Sun Microsystems Inc.
+
+All Rights Reserved.
+
+
+
+Redistribution and use in source and binary forms, with or without
+
+modification, are permitted provided that the following conditions are
+
+met:
+
+
+
+- Redistributions of source code must retain the above copyright notice,
+
+  this list of conditions and the following disclaimer.
+
+
+
+- Redistribution 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 Sun Microsystems or the names of 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.</pre>
+</div>
+</div>
+
+
 </div>
 
 </body>
diff --git a/chrome/browser/resources/about_memory_mac.html b/chrome/browser/resources/about_memory_mac.html
index 6184871..4edc6d3 100644
--- a/chrome/browser/resources/about_memory_mac.html
+++ b/chrome/browser/resources/about_memory_mac.html
@@ -22,12 +22,12 @@
   font-family: Helvetica, sans-serif;
 }
 table.list#browserComparison tr:not([class*='firstRow']) > *:nth-child(1),
-table.list#browserComparison tr:not([class*='firstRow']) > *:nth-child(4),
+table.list#browserComparison tr:not([class*='firstRow']) > *:nth-child(6),
 table.list#browserComparison tr.firstRow th:nth-child(1) {
   border-right: 1px solid #b5c6de;
 }
 table.list#memoryDetails tr:not([class*='firstRow']) > *:nth-child(2),
-table.list#memoryDetails tr:not([class*='firstRow']) > *:nth-child(5),
+table.list#memoryDetails tr:not([class*='firstRow']) > *:nth-child(7),
 table.list#memoryDetails tr.firstRow th:nth-child(2) {
   border-right: 1px solid #b5c6de;
 }
@@ -135,11 +135,13 @@
           <col class='name' />
           <col class='number' />
           <col class='number' />
+          <col class='number' />
+          <col class='number' />
         </colgroup>
         <tr class='firstRow doNotFilter'>
           <th>
           </th>
-          <th colspan='2'>
+          <th colspan='4'>
             Memory
             <div class='help'>
               <div>
@@ -152,6 +154,16 @@
                   This is the best indicator of browser memory resource usage.
                 </p>
                 <p>
+                  <strong>Shared:</strong>
+                  Amount of memory that is present in physical RAM and can
+                  be shared with another process.
+                </p>
+                <p>
+                  <strong>Private:</strong>
+                  Amount of memory that is present in physical RAM and can not
+                  be shared with another process.
+                </p>
+                <p>
                   <strong>Virtual:</strong>
                   Amount of address space allocated in virtual memory.
                 </p>
@@ -167,10 +179,16 @@
           <th class='name'>
             Browser
           </th>
-          <th class='name'>
+          <th class='number'>
             Resident
           </th>
           <th class='number'>
+            Shared
+          </th>
+          <th class='number'>
+            Private
+          </th>
+          <th class='number'>
             Virtual
           </th>
         </tr>
@@ -184,6 +202,12 @@
             <span class='th' jscontent="formatNumber(ws_shareable)"></span><span class='k'>k</span>
           </td>
           <td class='number'>
+            <span class='th' jscontent="formatNumber(ws_shared)"></span><span class='k'>k</span>
+          </td>
+          <td class='number'>
+            <span class='th' jscontent="formatNumber(ws_priv)"></span><span class='k'>k</span>
+          </td>
+          <td class='number'>
             <span class='th' jscontent="formatNumber(comm_priv)"></span><span class='k'>k</span>
           </td>
         </tr>
@@ -214,13 +238,15 @@
           <col class='name' />
           <col class='number' />
           <col class='number' />
+          <col class='number' />
+          <col class='number' />
         </colgroup>
         <tr class='firstRow doNotFilter'>
           <th>
           </th>
           <th>
           </th>
-          <th colspan='2'>
+          <th colspan='4'>
             Memory
           </th>
         </tr>
@@ -235,6 +261,12 @@
             Resident
           </th>
           <th class='number'>
+            Shared
+          </th>
+          <th class='number'>
+            Private
+          </th>
+          <th class='number'>
             Virtual
           </th>
         </tr>
@@ -252,6 +284,12 @@
             <span class='th' jscontent="formatNumber(ws_shareable)"></span><span class='k'>k</span>
           </td>
           <td class='number'>
+            <span class='th' jscontent="formatNumber(ws_shared)"></span><span class='k'>k</span>
+          </td>
+          <td class='number'>
+            <span class='th' jscontent="formatNumber(ws_priv)"></span><span class='k'>k</span>
+          </td>
+          <td class='number'>
             <span class='th' jscontent="formatNumber(comm_priv)"></span><span class='k'>k</span>
           </td>
         </tr>
@@ -269,6 +307,12 @@
             <span class='th' jscontent="formatNumber(ws_shareable)"></span><span class='k'>k</span>
           </td>
           <td class='number'>
+            <span class='th' jscontent="formatNumber(ws_shared)"></span><span class='k'>k</span>
+          </td>
+          <td class='number'>
+            <span class='th' jscontent="formatNumber(ws_priv)"></span><span class='k'>k</span>
+          </td>
+          <td class='number'>
             <span class='th' jscontent="formatNumber(comm_priv)"></span><span class='k'>k</span>
           </td>
         </tr>
diff --git a/chrome/browser/resources/about_os_credits.html b/chrome/browser/resources/about_os_credits.html
index a7f66e2..31d1508 100644
--- a/chrome/browser/resources/about_os_credits.html
+++ b/chrome/browser/resources/about_os_credits.html
@@ -30045,7 +30045,7 @@
 		       Version 2, June 1991
 
  Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -30479,7 +30479,7 @@
 
 		     END OF TERMS AND CONDITIONS
 
-     Appendix: How to Apply These Terms to Your New Libraries
+           How to Apply These Terms to Your New Libraries
 
   If you develop a new library, and you want it to be of the greatest
 possible use to the public, we recommend making it free software that
@@ -30506,9 +30506,9 @@
     Library General Public License for more details.
 
     You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-    MA 02111-1307, USA
+    License along with this library; if not, write to the 
+    Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
+    Boston, MA  02111-1307  USA.
 
 Also add information on how to contact you by electronic and paper mail.
 
@@ -30606,7 +30606,7 @@
 <div class="product">
 <span class="title">glproto</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="">homepage</a></span>
+<span class="homepage"><a href="http://www.x.org/">homepage</a></span>
 <div class="licence">
 <pre>SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
 
@@ -32517,11 +32517,17 @@
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://gpsd.berlios.de/">homepage</a></span>
 <div class="licence">
-<pre>			BSD LICENSE
+<pre>			COPYRIGHTS
 
-The GPSD code is Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by
-Remco Treffkorn. Portions of it are also Copyright (c) 2005 by Eric S. 
-Raymond. All rights reserved.
+Compilation copyright is held by the GPSD project.  All rights reserved.
+
+GPSD project copyrights are assigned to the project lead, currently
+Eric S. Raymond. Other portions of the GPSD code are Copyright (c)
+1997, 1998, 1999, 2000, 2001, 2002 by Remco Treffkorn, and others
+Copyright (c) 2005 by Eric S. Raymond.  For other copyrights, see
+individual files.
+
+			BSD LICENSE
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
@@ -40882,520 +40888,6 @@
 
 
 <div class="product">
-<span class="title">iso-codes</span>
-<a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="http://alioth.debian.org/projects/pkg-isocodes/">homepage</a></span>
-<div class="licence">
-<pre>		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    &lt;one line to give the library's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  &lt;signature of Ty Coon&gt;, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-
-</pre>
-</div>
-</div>
-
-
-<div class="product">
 <span class="title">iw</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://wireless.kernel.org/en/users/Documentation/iw">homepage</a></span>
@@ -46156,32 +45648,29 @@
 
 
 <div class="product">
-<span class="title">libcroco</span>
+<span class="title">liberation-fonts</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="http://www.freespiders.org/projects/libcroco/">homepage</a></span>
+<span class="homepage"><a href="https://fedorahosted.org/liberation-fonts">homepage</a></span>
 <div class="licence">
-<pre>		  GNU LIBRARY GENERAL PUBLIC LICENSE
+<pre>		    GNU GENERAL PUBLIC LICENSE
 		       Version 2, June 1991
 
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
 			    Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
 
   When we speak of free software, we are referring to freedom, not
 price.  Our General Public Licenses are designed to make sure that you
@@ -46192,347 +45681,195 @@
 
   To protect your rights, we need to make restrictions that forbid
 anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
 
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
 
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
 
-  Also, for each distributor's protection, we want to make certain
+  Also, for each author's protection and ours, we want to make certain
 that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
   Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
 
   The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
+modification follow.
 
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
 
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
+Activities other than copying, distribution and modification are not
 covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
 
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
 distribute such modifications or work under the terms of Section 1
 above, provided that you also meet all of these conditions:
 
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
+    a) You must cause the modified files to carry prominent notices
     stating that you changed the files and the date of any change.
 
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
 
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
 These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
+identifiable sections of that work are not derived from the Program,
 and can be reasonably considered independent and separate works in
 themselves, then this License, and its terms, do not apply to those
 sections when you distribute them as separate works.  But when you
 distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
+on the Program, the distribution of the whole must be on the terms of
 this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
+entire whole, and thus to each and every part regardless of who wrote it.
 
 Thus, it is not the intent of this section to claim rights or contest
 your rights to work written entirely by you; rather, the intent is to
 exercise the right to control the distribution of derivative or
-collective works based on the Library.
+collective works based on the Program.
 
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
 a storage or distribution medium does not bring the other work under
 the scope of this License.
 
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
 
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
 
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
 
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
 compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
 
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
 
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
+  5. You are not required to accept this License, since you have not
 signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
+distribute the Program or its derivative works.  These actions are
 prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
 all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
+the Program or works based on it.
 
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
 restrictions on the recipients' exercise of the rights granted herein.
 You are not responsible for enforcing compliance by third parties to
 this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
+
+  7. If, as a consequence of a court judgment or allegation of patent
 infringement or for any other reason (not limited to patent issues),
 conditions are imposed on you (whether by court order, agreement or
 otherwise) that contradict the conditions of this License, they do not
 excuse you from the conditions of this License.  If you cannot
 distribute so as to satisfy simultaneously your obligations under this
 License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
 all those who receive copies directly or indirectly through you, then
 the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
+refrain entirely from distribution of the Program.
 
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
 
 It is not the purpose of this section to induce you to infringe any
 patents or other property right claims or to contest validity of any
 such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
+integrity of the free software distribution system, which is
 implemented by public license practices.  Many people have made
 generous contributions to the wide range of software distributed
 through that system in reliance on consistent application of that
@@ -46542,106 +45879,119 @@
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
 
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
 
 			    NO WARRANTY
 
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
 
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
 
 		     END OF TERMS AND CONDITIONS
 
-     Appendix: How to Apply These Terms to Your New Libraries
+	    How to Apply These Terms to Your New Programs
 
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
 
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
 
-    &lt;one line to give the library's name and a brief idea of what it does.&gt;
+    &lt;one line to give the program's name and a brief idea of what it does.&gt;
     Copyright (C) &lt;year&gt;  &lt;name of author&gt;
 
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
 
-    This library is distributed in the hope that it will be useful,
+    This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
 
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-    MA 02111-1307, USA
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
 
 Also add information on how to contact you by electronic and paper mail.
 
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
 You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
+school, if any, to sign a "copyright disclaimer" for the program, if
 necessary.  Here is a sample; alter the names:
 
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 
-  &lt;signature of Ty Coon&gt;, 1 April 1990
+  &lt;signature of Ty Coon&gt;, 1 April 1989
   Ty Coon, President of Vice
 
-That's all there is to it!
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
 </pre>
 </div>
 </div>
@@ -47905,861 +47255,6 @@
 
 
 <div class="product">
-<span class="title">libgsf</span>
-<a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="http://www.gnome.org/">homepage</a></span>
-<div class="licence">
-<pre>		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    &lt;one line to give the program's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  &lt;signature of Ty Coon&gt;, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    &lt;one line to give the library's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  &lt;signature of Ty Coon&gt;, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-
-</pre>
-</div>
-</div>
-
-
-<div class="product">
 <span class="title">libhangul</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://kldp.net/projects/hangul/">homepage</a></span>
@@ -51114,7 +49609,7 @@
 PCRE is a library of functions to support regular expressions whose syntax
 and semantics are as close as possible to those of the Perl 5 language.
 
-Release 7 of PCRE is distributed under the terms of the "BSD" licence, as
+Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
 specified below. The documentation for PCRE, supplied in the "doc"
 directory, is distributed under the same terms as the software itself.
 
@@ -51132,7 +49627,7 @@
 University of Cambridge Computing Service,
 Cambridge, England.
 
-Copyright (c) 1997-2009 University of Cambridge
+Copyright (c) 1997-2010 University of Cambridge
 All rights reserved.
 
 
@@ -51141,7 +49636,7 @@
 
 Contributed by:   Google Inc.
 
-Copyright (c) 2007-2008, Google Inc.
+Copyright (c) 2007-2010, Google Inc.
 All rights reserved.
 
 
@@ -51334,498 +49829,6 @@
 
 
 <div class="product">
-<span class="title">librsvg</span>
-<a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="http://librsvg.sourceforge.net/">homepage</a></span>
-<div class="licence">
-<pre>		  GNU LIBRARY GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    &lt;one line to give the library's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-    MA 02111-1307, USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  &lt;signature of Ty Coon&gt;, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-</pre>
-</div>
-</div>
-
-
-<div class="product">
 <span class="title">libsndfile</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://www.mega-nerd.com/libsndfile">homepage</a></span>
@@ -53773,498 +51776,6 @@
 
 
 <div class="product">
-<span class="title">libxklavier</span>
-<a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="http://www.freedesktop.org/Software/LibXklavier">homepage</a></span>
-<div class="licence">
-<pre>		  GNU LIBRARY GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    &lt;one line to give the library's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-    MA 02111-1307, USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  &lt;signature of Ty Coon&gt;, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-</pre>
-</div>
-</div>
-
-
-<div class="product">
 <span class="title">libxml2</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://www.xmlsoft.org/">homepage</a></span>
@@ -68011,7 +65522,7 @@
 		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -68064,7 +65575,7 @@
 
   The precise terms and conditions for copying, distribution and
 modification follow.
-
+
 		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
@@ -68119,7 +65630,7 @@
     License.  (Exception: if the Program itself is interactive but
     does not normally print such an announcement, your work based on
     the Program is not required to print an announcement.)
-
+
 These requirements apply to the modified work as a whole.  If
 identifiable sections of that work are not derived from the Program,
 and can be reasonably considered independent and separate works in
@@ -68177,7 +65688,7 @@
 access to copy the source code from the same place counts as
 distribution of the source code, even though third parties are not
 compelled to copy the source along with the object code.
-
+
   4. You may not copy, modify, sublicense, or distribute the Program
 except as expressly provided under this License.  Any attempt
 otherwise to copy, modify, sublicense or distribute the Program is
@@ -68234,7 +65745,7 @@
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-
+
   8. If the distribution and/or use of the Program is restricted in
 certain countries either by patents or by copyrighted interfaces, the
 original copyright holder who places the Program under this License
@@ -68287,7 +65798,7 @@
 POSSIBILITY OF SUCH DAMAGES.
 
 		     END OF TERMS AND CONDITIONS
-
+
 	    How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
@@ -68314,7 +65825,7 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 
 Also add information on how to contact you by electronic and paper mail.
@@ -68322,7 +65833,7 @@
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision version 69, Copyright (C) year name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
@@ -75515,6 +73026,356 @@
 
 
 <div class="product">
+<span class="title">rxvt-unicode</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://software.schmorp.de/pkg/rxvt-unicode.html">homepage</a></span>
+<div class="licence">
+<pre>		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    &lt;one line to give the program's name and a brief idea of what it does.&gt;
+    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  &lt;signature of Ty Coon&gt;, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">sandbox</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
@@ -80016,7 +77877,7 @@
    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. 
+   POSSIBILITY OF SUCH DAMAGE.
 </pre>
 </div>
 </div>
@@ -80743,6 +78604,690 @@
 
 
 <div class="product">
+<span class="title">talloc</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://talloc.samba.org/">homepage</a></span>
+<div class="licence">
+<pre>                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    &lt;one line to give the program's name and a brief idea of what it does.&gt;
+    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    &lt;program&gt;  Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+&lt;http://www.gnu.org/licenses/&gt;.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+&lt;http://www.gnu.org/philosophy/why-not-lgpl.html&gt;.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">tar</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://www.gnu.org/software/tar/">homepage</a></span>
@@ -84385,7 +82930,7 @@
 <div class="product">
 <span class="title">vim</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="">homepage</a></span>
+<span class="homepage"><a href="http://www.vim.org/">homepage</a></span>
 <div class="licence">
 <pre>License details for VIM Editor:
 
@@ -87138,356 +85683,6 @@
 
 
 <div class="product">
-<span class="title">xinit</span>
-<a class="show" href="#" onclick="return toggle(this);">show license</a>
-<span class="homepage"><a href="">homepage</a></span>
-<div class="licence">
-<pre>		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    &lt;one line to give the program's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  &lt;signature of Ty Coon&gt;, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-</pre>
-</div>
-</div>
-
-
-<div class="product">
 <span class="title">xkeyboard-config</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://www.freedesktop.org/wiki/Software/XKeyboardConfig">homepage</a></span>
@@ -87694,6 +85889,355 @@
 
 
 <div class="product">
+<span class="title">xtrace</span>
+<a class="show" href="#" onclick="return toggle(this);">show license</a>
+<span class="homepage"><a href="http://xtrace.alioth.debian.org/">homepage</a></span>
+<div class="licence">
+<pre>		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    &lt;one line to give the program's name and a brief idea of what it does.&gt;
+    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  &lt;signature of Ty Coon&gt;, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+</pre>
+</div>
+</div>
+
+
+<div class="product">
 <span class="title">xxd</span>
 <a class="show" href="#" onclick="return toggle(this);">show license</a>
 <span class="homepage"><a href="http://ftp.uni-erlangen.de/pub/utilities/etc/?order=s">homepage</a></span>
diff --git a/chrome/browser/resources/access_chromevox/manifest.json b/chrome/browser/resources/access_chromevox/manifest.json
new file mode 100644
index 0000000..9d37904
--- /dev/null
+++ b/chrome/browser/resources/access_chromevox/manifest.json
@@ -0,0 +1,26 @@
+{
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDltVl1k15pjRzuZfMc3B69inxwm2bZeZ2O8/zFO+NluHnBm3GJ3fzdOoFGJd+M16I8p7zxxQyHeDMfWYASyCeB8XnUEDKjqNLQfCnncsANzHsYoEbYj2nEUML2P13b9q+AAvpCBpAJ4cZp81e9n1y/vbSXHE4385cgkKueItzikQIDAQAB",
+  "name": "ChromeVox",
+  "version": "1.0",
+  "description": "ChromeVox - Giving Voice to Chrome.",
+  "background_page": "chromevox/background/background.html",
+  "permissions": [
+    "bookmarks",
+    "tabs",
+    "experimental",
+    "http://*/",
+    "https://*/"
+  ],
+  "content_scripts": [
+    {
+      "matches": [ "<all_urls>" ],
+      "all_frames": true,
+      "js": [
+        "build/build_defs.js",
+        "build/build_config_chrome.js",
+        "chromevox/injected/main.js",
+        "common/extension_bridge.js"
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/bookmark_manager/css/bmm.css b/chrome/browser/resources/bookmark_manager/css/bmm.css
index 40e7951..48b3cf9 100644
--- a/chrome/browser/resources/bookmark_manager/css/bmm.css
+++ b/chrome/browser/resources/bookmark_manager/css/bmm.css
@@ -106,8 +106,8 @@
 /* Edit mode
 */
 
-list .label input,
-list .url input {
+list [editing] .label input,
+list [editing] .url input {
   /* Do not inherit the line-height */
   font-family: inherit;
   font-size: inherit;
@@ -122,6 +122,17 @@
   text-decoration: none;
 }
 
+.tree-item [editing] input {
+  margin: 0;
+  padding: 0;
+  -webkit-margin-start: -3px;
+  -webkit-padding-end: 7px;
+}
+
+html[os=mac] .tree-label [editing] input {
+  padding-top: 1px;
+}
+
 html:not([os=mac]) list .label input,
 html:not([os=mac]) list .url input {
   outline: none;
diff --git a/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js b/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js
index 64f5976..ef4fa82 100644
--- a/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js
+++ b/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js
@@ -68,7 +68,6 @@
     /** @inheritDoc */
     decorate: function() {
       List.prototype.decorate.call(this);
-      this.addEventListener('click', this.handleClick_);
       this.addEventListener('mousedown', this.handleMouseDown_);
 
       // HACK(arv): http://crbug.com/40902
@@ -190,26 +189,17 @@
     },
 
     /**
-     * Handles the clicks on the list so that we can check if the user clicked
-     * on a link or a folder.
+     * Dispatches an urlClicked event which is used to open URLs in new
+     * tabs etc.
      * @private
-     * @param {!Event} e The click event object.
+     * @param {string} url The URL that was clicked.
+     * @param {!Event} originalEvent The original click event object.
      */
-    handleClick_: function(e) {
-      // Handle middle click to open bookmark in a new tab.
-      if (e.button == 1) {
-        var el = e.target;
-        while (el.parentNode != this) {
-          el = el.parentNode;
-        }
-        var node = el.bookmarkNode;
-        if (!bmm.isFolder(node)) {
-          var event = new cr.Event('urlClicked', true, false);
-          event.url = node.url;
-          event.originalEvent = e;
-          this.dispatchEvent(event);
-        }
-      }
+    dispatchUrlClickedEvent_: function(url, originalEvent) {
+      var event = new cr.Event('urlClicked', true, false);
+      event.url = url;
+      event.originalEvent = originalEvent;
+      this.dispatchEvent(event);
     },
 
     /**
@@ -243,15 +233,13 @@
     handleMiddleMouseUp_: function(e) {
       this.removeEventListener('mouseup', this.handleMiddleMouseUp_);
       if (e.button == 1) {
-        var clickEvent = document.createEvent('MouseEvent');
-        clickEvent.initMouseEvent('click',
-                                  true,  // canBubble
-                                  true,  // cancelable,
-                                  e.view, e.detail,
-                                  e.screenX, e.screenY, e.clientX, e.clientY,
-                                  e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
-                                  e.button, e.relatedTarget);
-        e.target.dispatchEvent(clickEvent);
+        var el = e.target;
+        while (el.parentNode != this) {
+          el = el.parentNode;
+        }
+        var node = el.bookmarkNode;
+        if (node && !bmm.isFolder(node))
+          this.dispatchUrlClickedEvent_(node.url, e);
       }
     },
 
diff --git a/chrome/browser/resources/bookmark_manager/main.html b/chrome/browser/resources/bookmark_manager/main.html
index 4fc5dc4..06d9667 100644
--- a/chrome/browser/resources/bookmark_manager/main.html
+++ b/chrome/browser/resources/bookmark_manager/main.html
@@ -1387,7 +1387,8 @@
   // After the list is loaded we should select the revealed item.
   function f(e) {
     var index;
-    if (bookmarkNode && (index = list.dataModel.indexOf(bookmarkNode))) {
+    if (bookmarkNode &&
+        (index = list.dataModel.findIndexById(bookmarkNode.id)) != -1) {
       var sm = list.selectionModel;
       sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
       list.scrollIndexIntoView(index);
@@ -1519,20 +1520,33 @@
       if (isTree) {
         newItem = bmm.treeLookup[newNode.id];
         tree.selectedItem = newItem;
+        newItem.editing = true;
       } else {
         var index = list.dataModel.findIndexById(newNode.id);
         var sm = list.selectionModel;
         sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
-        list.scrollIndexIntoView(index);
-        newItem = list.getListItemByIndex(index);
+        scrollIntoViewAndMakeEditable(index);
       }
-
-      newItem.editing = true;
     }, 50);
   });
 }
 
 /**
+ * Scrolls the list item into view and makes it editable.
+ * @param {number} index The index of the item to make editable.
+ */
+function scrollIntoViewAndMakeEditable(index) {
+  list.scrollIndexIntoView(index);
+  // onscroll is now dispatched asynchronously so we have to postpone
+  // the rest.
+  setTimeout(function() {
+    var item = list.getListItemByIndex(index);
+    if (item)
+      item.editing = true;
+  });
+}
+
+/**
  * Adds a page to the current folder. This is called by the
  * add-new-bookmark-command handler.
  */
@@ -1550,9 +1564,7 @@
   dataModel.splice(length, 0, fakeNode);
   var sm = list.selectionModel;
   sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length;
-  list.scrollIndexIntoView(length);
-  var li = list.getListItemByIndex(length);
-  li.editing = true;
+  scrollIntoViewAndMakeEditable(length);
 }
 
 /**
@@ -1634,14 +1646,17 @@
       deleteBookmarks();
       break;
     case 'copy-command':
-      chrome.experimental.bookmarkManager.copy(getSelectedBookmarkIds());
+      chrome.experimental.bookmarkManager.copy(getSelectedBookmarkIds(),
+                                               updatePasteCommand);
       break;
     case 'cut-command':
-      chrome.experimental.bookmarkManager.cut(getSelectedBookmarkIds());
+      chrome.experimental.bookmarkManager.cut(getSelectedBookmarkIds(),
+                                              updatePasteCommand);
       break;
     case 'paste-command':
       selectItemsAfterUserAction(list);
-      chrome.experimental.bookmarkManager.paste(list.parentId);
+      chrome.experimental.bookmarkManager.paste(list.parentId,
+                                                getSelectedBookmarkIds());
       break;
     case 'sort-command':
       chrome.experimental.bookmarkManager.sortChildren(list.parentId);
diff --git a/chrome/browser/resources/extensions_ui.html b/chrome/browser/resources/extensions_ui.html
index e5f3976..7cebf12 100644
--- a/chrome/browser/resources/extensions_ui.html
+++ b/chrome/browser/resources/extensions_ui.html
@@ -332,6 +332,7 @@
       'description': 'Extension long format description',
       'version': '1.0.231',
       'enabled': 'true',
+      'terminated': 'false',
       'enabledIncognito': 'false',
       'wantsFileAccess': 'false',
       'allowFileAccess': 'false',
@@ -378,6 +379,7 @@
       'description': 'Extension long format description',
       'version': '1.0.231',
       'enabled': 'true',
+      'terminated': 'false',
       'enabledIncognito': 'false',
       'wantsFileAccess': 'false',
       'allowFileAccess': 'false',
@@ -459,17 +461,17 @@
 
 // Used for observing function of the backend datasource for this page by
 // tests.
-var domui_responded_ = false;
+var webui_responded_ = false;
 
 // Used to only do some work the first time we render.
 var rendered_once_ = false;
 
 /**
- * Called by the dom_ui_ to re-populate the page with data representing
+ * Called by the web_ui_ to re-populate the page with data representing
  * the current state of installed extensions.
  */
 function returnExtensionsData(extensionsData){
-  domui_responded_ = true;
+  webui_responded_ = true;
   devModeExpanded = extensionsData.developerMode;
 
   var bodyContainer = document.getElementById('body-container');
@@ -533,7 +535,7 @@
  * Tell the C++ ExtensionDOMHandler to inspect the page detailed in |viewData|.
  */
 function sendInspectMessage(viewData) {
-  // TODO(aa): This is ghetto, but DOMUIBindings doesn't support sending
+  // TODO(aa): This is ghetto, but WebUIBindings doesn't support sending
   // anything other than arrays of strings, and this is all going to get
   // replaced with V8 extensions soon anyway.
   chrome.send('inspect', [
@@ -832,8 +834,10 @@
                     jscontent="name">EXTENSION NAME</span>
               - <span i18n-content="extensionVersion">VERSION</span>
               <span jscontent="version">x.x.x.x</span>
-              <span jsdisplay="!enabled"
+              <span jsdisplay="!enabled && !terminated"
                     i18n-content="extensionDisabled">(DISABLED)</span>
+              <span jsdisplay="terminated"
+                    i18n-content="extensionCrashed">(CRASHED)</span>
               <span jsdisplay="order == 1"
                     i18n-content="inDevelopment">(IN DEVELOPMENT)</span>
             </div>
@@ -869,7 +873,7 @@
               <span class="extension-actions">
                 <a
                   jsvalues=".extensionId:id"
-                  jsdisplay="enabled && allow_reload"
+                  jsdisplay="(enabled && allow_reload) || terminated"
                   onclick="handleReloadExtension(this)"
                   href="javascript:void 0;"
                   i18n-content="reload"
@@ -884,13 +888,15 @@
                   >DISABLE</a>
                 <a
                   jsvalues=".extensionId:id"
-                  jsdisplay="!enabled"
+                  jsdisplay="!enabled && !terminated"
                   onclick="handleEnableExtension(this, true)"
                   href="javascript:void 0;"
                   i18n-content="enable"
-                  >ENABLE</a> -
+                  >ENABLE</a>
+                <span jsdisplay="!terminated">-</span>
                 <a
                   jsvalues=".extensionId:id"
+                  jsdisplay="!terminated"
                   onclick="handleUninstallExtension(this)"
                   href="javascript:void 0;"
                   i18n-content="uninstall"
diff --git a/chrome/browser/resources/filebrowse.html b/chrome/browser/resources/filebrowse.html
index 078b7a2..dfa6531 100644
--- a/chrome/browser/resources/filebrowse.html
+++ b/chrome/browser/resources/filebrowse.html
@@ -424,7 +424,7 @@
   margin: 3px;
 }
 
-div.newfolderbutton {
+#newfolderbutton {
   bottom: 3px;
   left: 10px;
   position: absolute;
@@ -591,7 +591,9 @@
 function partial(fn, var_args) {
   var args = Array.prototype.slice.call(arguments, 1);
   return function(e) {
-    if (e.stopPropagation) e.stopPropagation();
+    if (e.stopPropagation) {
+      e.stopPropagation();
+    }
     // Prepend the bound arguments to the current arguments.
     var newArgs = Array.prototype.slice.call(arguments);
     newArgs.unshift.apply(newArgs, args);
@@ -676,9 +678,9 @@
 
         var cancelbutton = document.createElement('button');
         cancelbutton.className = 'cancelbutton';
-        buttonsContainer.appendChild(cancelbutton);
         cancelbutton.textContent = localStrings.getString('confirmcancel');
         cancelbutton.onclick = dialogCancelClick;
+        buttonsContainer.appendChild(cancelbutton);
 
         var filenameprompt = document.createElement('div');
         filenameprompt.className = 'filenameprompt';
@@ -695,6 +697,7 @@
         filename.id = 'filename';
         filename.value = args.current_file;
         savemenu.appendChild(filename);
+
         if (advancedEnabled) {
           var newfolderbutton = document.createElement('button');
           newfolderbutton.id = 'newfolderbutton';
@@ -703,6 +706,7 @@
           newfolderbutton.onclick = dialogNewFolderClick;
           savemenu.appendChild(newfolderbutton);
         }
+        
         document.body.appendChild(savemenu);
         // Give focus to the save button. This has to be done after the
         // parent node is added to document.body.
@@ -765,16 +769,19 @@
   chrome.send('getDownloads', []);
 }
 
+function isPathUnderRoot(path, includeRoot) {
+  var downloadpath = localStrings.getString('downloadpath');
+  return (!includeRoot || path !== downloadpath) 
+    && path.search(downloadpath) === 0;
+}
+
 function goBackInList() {
   currentNode--;
-  if (currentSavedPath == localStrings.getString('downloadpath')) {
-    currentSavedPath = 'roots';
+  if (isPathUnderRoot(currentSavedPath, true)) {
+    var c = currentSavedPath.split('/');
+    c.pop();
+    currentSavedPath = c.join('/');
   } else {
-    var lastDirArray = currentSavedPath.split('/');
-    lastDirArray.splice(lastDirArray.length - 1, 1);
-    currentSavedPath = lastDirArray.join('/');
-  }
-  if (currentSavedPath == localStrings.getString('mediapath')) {
     currentSavedPath = 'roots';
   }
   getDataForPath(currentSavedPath);
@@ -862,7 +869,6 @@
       var dest = currentSavedPath + '/' + path[2];
       var dirId = $('list/dir/' + currentSavedPath);
       if (dirId) {
-
         var element = $(dest);
         if (!element) {
           // TODO(dhg): We probably should do some checking for
@@ -911,12 +917,18 @@
 }
 
 function getDataForPath(path) {
+  var newfolderbutton = $('newfolderbutton');
+  if (newfolderbutton && advancedEnabled) {
+    // Enable newfolder button for paths under downloadpath
+    if (inSaveMode && isPathUnderRoot(path, false)) {
+      newfolderbutton.className = 'newfolderbutton';
+    } else {
+      newfolderbutton.className = 'newfolderbutton disabled';
+    }
+  }
+  
   if (path == 'roots') {
     if (inSaveMode) {
-      if (advancedEnabled) {
-        var newfolderbutton = $('newfolderbutton');
-        newfolderbutton.className = 'newfolderbutton disabled';
-      }
       var savebutton = $('savebutton');
       savebutton.className = 'openbutton disabled';
     } else if (inSelectMode) {
@@ -926,10 +938,6 @@
     chrome.send('getRoots', []);
   } else {
     if (inSaveMode) {
-      if (advancedEnabled) {
-        var newfolderbutton = $('newfolderbutton');
-        newfolderbutton.className = 'newfolderbutton';
-      }
       var savebutton = $('savebutton');
       savebutton.className = 'openbutton';
     } else if (inSelectMode) {
@@ -1025,50 +1033,53 @@
 function createFolder(elementId) {
   var currentPath = currentSavedPath;
   var element = $('newfoldername');
-  if (element) {
-    element.id = '';
-    var filename = element.value;
-    currentPath += '/';
-    currentPath += filename;
-    var existingfolder = $(currentPath);
-    var counter = 1;
-    while (existingfolder) {
-      var testfilepath = currentPath;
-      testfilepath = testfilepath + counter;
-      existingfolder = $(testfilepath);
-      if (!existingfolder) {
-        currentPath = testfilepath;
-        filename = filename + counter;
-        break;
-      }
-      counter++;
-    }
-    if (filename == '') {
-      return false;
-    }
-    var parent = element.parentNode;
-    parent.removeChild(element);
-    listitem = parent.parentNode;
-
-    parent.onclick = getFunctionForItem(currentPath, listitem.id, true);
-
-    var span = document.createElement('span');
-    if (inSelectMode) {
-      span.className = 'name';
-    } else {
-      span.className = 'namelink';
-    }
-    span.textContent = filename;
-    parent.appendChild(span);
-
-    var rightArrow = document.createElement('span');
-    rightArrow.textContent = '»';
-    rightArrow.className = 'rightarrow';
-    parent.appendChild(rightArrow);
-
-    chrome.send('createNewFolder', [currentPath]);
+  if (!element) {
+    return false;
   }
-  return false;
+  element.id = '';
+  var filename = element.value;
+  currentPath += '/';
+  currentPath += filename;
+  var existingfolder = $(currentPath);
+  var counter = 1;
+  while (existingfolder) {
+    var testfilepath = currentPath;
+    testfilepath = testfilepath + counter;
+    existingfolder = $(testfilepath);
+    if (!existingfolder) {
+      currentPath = testfilepath;
+      filename = filename + counter;
+      break;
+    }
+    counter++;
+  }
+  
+  // Disallow / in folder name.
+  if (filename.match(/^[^\/]+$/) === null) {
+    return false;
+  }
+
+  var parent = element.parentNode;
+  parent.removeChild(element);
+  listitem = parent.parentNode;
+
+  parent.onclick = getFunctionForItem(currentPath, listitem.id, true);
+
+  var span = document.createElement('span');
+  if (inSelectMode) {
+    span.className = 'name';
+  } else {
+    span.className = 'namelink';
+  }
+  span.textContent = filename;
+  parent.appendChild(span);
+
+  var rightArrow = document.createElement('span');
+  rightArrow.textContent = '»';
+  rightArrow.className = 'rightarrow';
+  parent.appendChild(rightArrow);
+
+  chrome.send('createNewFolder', [currentPath]);
 }
 
 function deleteFile(path) {
@@ -1156,7 +1167,8 @@
 }
 
 function newDownload(results) {
-  for (var x = 0; x < results.length; x++) {
+  var x;
+  for (x = 0; x < results.length; x++) {
     var element = $(results[x].file_path);
     if (!element && results[x].state != 'CANCELLED') {
       var extracted = getPathAndFilenameForPath(results[x].file_path);
diff --git a/chrome/browser/resources/flags.html b/chrome/browser/resources/flags.html
index 5090084..203f425 100644
--- a/chrome/browser/resources/flags.html
+++ b/chrome/browser/resources/flags.html
@@ -176,6 +176,7 @@
       'internal_name': 'Experiment ID string',
       'name': 'Experiment Name',
       'description': 'description',
+      /* enabled is only set if the experiment is single valued */
       'enabled': true,
       /* choices is only set if the experiment has multiple values */
       'choices': [
@@ -313,6 +314,9 @@
             </div>
           </div>
           <div class="experiment-actions">
+	    <!-- If enabled isn't set (i.e. in multi_type options),
+		 then both jsdisplay tests fail, and we get no
+		 rendering from this section. -->
             <span>
               <a
                 jsvalues=".internal_name:internal_name"
diff --git a/chrome/browser/resources/getstarted/manifest.json b/chrome/browser/resources/getstarted/manifest.json
new file mode 100644
index 0000000..3b361f9
--- /dev/null
+++ b/chrome/browser/resources/getstarted/manifest.json
@@ -0,0 +1,18 @@
+{
+  "name": "Get Started",
+  "description": "Get Started",
+  "version": "1.0.26",
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAuFUzjec2nXa5iFEycabbHL9h4ga7hsRGT0LVUlhhfm0tH8OTGzQtzcZG+Skk/stWOHNcd03lSPrPwCEtjJ9pDjtM2I0bYwXrcnVSBx+h9JXnDIJ0zsdVQsjOIknSFunxcedfG0v+yfGAfgamLSpAhAg8Le2pniqDJ24u3nIPjQIDAQAB",
+  "app": {
+    "launch": {
+      "local_path": "index.html"
+    }
+  },
+  "icons": {
+    "16": "images/16x16.png",
+    "128": "images/128x128.png"
+  },
+  "permissions": [
+    "tabs"
+  ]
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/gpu_blacklist.json b/chrome/browser/resources/gpu_blacklist.json
index 188fead..8c976c7 100644
--- a/chrome/browser/resources/gpu_blacklist.json
+++ b/chrome/browser/resources/gpu_blacklist.json
@@ -1,8 +1,47 @@
+// Determines whether certain gpu-related features are blacklisted or not.
+// A valid gpu_blacklist.json file are in the format of
+// {
+//   "version": "x.y",
+//   "entries": [
+//     { // entry 1
+//     },
+//     ...
+//     { // entry n
+//     }
+//   ]
+// }
+//
+// Each entry contains the following fields:
+// "os", "vendor_id", "device_id", "driver_version", and "blacklist".
+// Only "blacklist" is mandatory.
+// 1. "os" contains "type" and an optional "version". "type" could be "macosx",
+//    "linux", "win", or "any".  "any" is the same as not specifying "os".
+//    "version" is a VERSION structure (defined below).
+// 2. "vendor_id" has the value of a string.
+// 3. "device_id" has the value of a string.
+// 4. "driver_vendor" is a STRING structure (defined below).
+// 5. "driver_version" is a VERSION structure (defined below).
+// 6. "gl_renderer" is a STRING structure (defined below).
+// 7. "blacklist" is a list of gpu feature strings, valid values include
+//    "accelerated_2d_canvas", "accelerated_compositing", "webgl", and "all".
+//    Currently whatever feature is selected, the effect is the same as "all",
+//    i.e., it's not supported to turn off one GPU feature and not the others.
+//
+// VERSION includes "op" "number", and "number2".  "op" can be any of the
+// following values: "=", "<", "<=", ">", ">=", "any", "between".  "number2" is
+// only used if "op" is "between".  "number" is used for all "op" values except
+// "any". "number" and "number2" are in the format of x, x.x, x.x.x, ect.
+//
+// STRING includes "op" and "value".  "op" can be any of the following values:
+// "contains", "beginwith", "endwith", "=".  "value" is a string.
+
 {
   "name": "gpu blacklist",
-  "version": "0.1",
+  // Please update the version number whenever you change this file.
+  "version": "0.8",
   "entries": [
-    { // ATI Radeon X1900 on Mac
+    { // ATI Radeon X1900 on Mac, BUGWEBKIT=47028
+      "id": "1",
       "os": {
         "type": "macosx"
       },
@@ -11,6 +50,94 @@
       "blacklist": [
         "webgl"
       ]
+    },
+    { // Intel cards with Mesa driver earlier than 7.9, BUG=66718,67345,67939
+      "id": "2",
+      "os": {
+        "type": "linux"
+      },
+      "vendor_id": "0x8086",
+      "driver_vendor": {
+        "op": "=",
+        "value": "mesa"
+      },
+      "driver_version": {
+        "op": "<",
+        "number": "7.9"
+      },
+      "blacklist": [
+        "webgl"
+      ]
+    },
+    { // In linux, don't allow GPU compositing if it's software rendering, BUG=59302
+      "id": "3",
+      "os": {
+        "type": "linux"
+      },
+      "gl_renderer": {
+        "op": "contains",
+        "value": "software"
+      },
+      "blacklist": [
+        "accelerated_compositing"
+      ]
+    },
+    { // Intel Mobile 945 Express Chipset Family
+      "id": "4",
+      "os": {
+        "type": "any"
+      },
+      "vendor_id": "0x8086",
+      "device_id": "0x27AE",
+      "blacklist": [
+        "webgl"
+      ]
+    },
+    { // All ATI cards in linux, BUG=71381
+      "id": "5",
+      "os": {
+        "type": "linux"
+      },
+      "vendor_id": "0x1002",
+      "blacklist": [
+        "webgl"
+      ]
+    },
+    { // ATI Radeon HD2600 on Mac, BUG=68859
+      "id": "6",
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x1002",
+      "device_id": "0x9583",
+      "blacklist": [
+        "webgl",
+        "accelerated_compositing"
+      ]
+    },
+    { // ATI Radeon HD2400 on Mac, BUG=68859
+      "id": "7",
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x1002",
+      "device_id": "0x94c8",
+      "blacklist": [
+        "webgl",
+        "accelerated_compositing"
+      ]
+    },
+    { // NVIDIA GeForce FX Go5200, BUG=72938
+      "id": "8",
+      "os": {
+        "type": "any"
+      },
+      "vendor_id": "0x10de",
+      "device_id": "0x0324",
+      "blacklist": [
+        "webgl",
+        "accelerated_compositing"
+      ]
     }
   ]
 }
diff --git a/chrome/browser/resources/gpu_internals.html b/chrome/browser/resources/gpu_internals.html
index 9b3fb86..0a39277 100644
--- a/chrome/browser/resources/gpu_internals.html
+++ b/chrome/browser/resources/gpu_internals.html
@@ -7,26 +7,35 @@
 -->
 <head i18n-values="dir:textdirection;">
 <link rel="stylesheet" href="dom_ui.css">
-<link rel="stylesheet" href="net_internals/tabswitcherview.css">
 <style>
 * {
   box-sizing: border-box;
 }
+
+html, body, #main-tabs {
+  height: 100%;
+}
+
 body {
+  cursor: default;
   font-family: sans-serif;
+  padding: 0;
+  margin: 0;
 }
 </style>
+<link rel="stylesheet" href="gpu_internals/tab_control.css">
 <link rel="stylesheet" href="gpu_internals/info_view.css">
 <script src="chrome://resources/js/cr.js"></script>
-<script src="net_internals/util.js"></script>
-<script src="net_internals/view.js"></script>
-<script src="net_internals/tabswitcherview.js"></script>
+<script src="chrome://resources/js/cr/event_target.js"></script>
+<script src="chrome://resources/js/cr/ui.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script src="gpu_internals/tab_control.js"></script>
 <script src="gpu_internals/browser_bridge.js"></script>
 <script src="gpu_internals/info_view.js"></script>
 
 
 <script>
-var browser = null;
+var browser;
 
 /**
  * Main entry point. called once the page has loaded.
@@ -34,41 +43,30 @@
 function onLoad() {
   browserBridge = new gpu.BrowserBridge();
 
-  // Create a view which will display general information
-  // about the gpu.
-  var infoView = new gpu.InfoView('info-view');
+  // Create the views.
+  cr.ui.decorate('#info-view', gpu.InfoView);
 
-  // Create a view which lets you tab between the different sub-views.
-  var categoryTabSwitcher =
-      new TabSwitcherView('category-tab-handles');
+  // Create the main tab control
+  var tabs = $('main-tabs');
+  cr.ui.decorate(tabs, gpu.TabControl);
 
-  // Populate the main tabs.
-  categoryTabSwitcher.addTab('info-tab', infoView, false);
-
-  // Build a map from the anchor name of each tab handle to its 'tab ID'.
-  // We will consider navigations to the #hash as a switch tab request.
-  var anchorMap = {};
-  var tabIds = categoryTabSwitcher.getAllTabIds();
-  for (var i = 0; i < tabIds.length; i++) {
-    var aNode = document.getElementById(tabIds[i]);
-    anchorMap[aNode.hash] = tabIds[i];
-  }
-  // Default the empty hash to the info tab.
-  anchorMap['#'] = anchorMap[''] = 'info-tab';
-
+  // Sync the main-tabs selectedTabs in-sync with the location.
+  tabs.addEventListener('selectedTabChanged', function() {
+    if (tabs.selectedTab.id) {
+      history.pushState('', '', '#' + tabs.selectedTab.id);
+    }
+  });
   window.onhashchange = function() {
-    var tabId = anchorMap[window.location.hash];
-    if (tabId)
-      categoryTabSwitcher.switchToTab(tabId);
+    var cur = window.location.hash;
+    if (cur == '#' || cur == '') {
+      if (tabs.tabs.length)
+        tabs.selectedTab = tabs.tabs[0];
+    } else {
+      var tab = $(window.location.hash.substr(1));
+      if (tab)
+        tabs.selectedTab = tab;
+    }
   };
-
-  // Make this category tab widget the primary view, that fills the whole page.
-  var windowView = new WindowView(categoryTabSwitcher);
-
-  // Trigger initial layout.
-  windowView.resetGeometry();
-
-  // Select the initial view based on the current URL.
   window.onhashchange();
 }
 
@@ -77,15 +75,9 @@
 </script>
 </head>
 <body>
-
-  <!-- Tab switcher for main categories. -->
-  <div id=category-tab-handles>
-    <ul>
-      <li><a href="#info" id="info-tab">GPU Info</a></li>
-    </ul>
-  </div>
-
   <!-- Tabs -->
-  <include src="gpu_internals/info_view.html">
+  <div id="main-tabs">
+    <include src="gpu_internals/info_view.html">
+  </div>
 </body>
 </html>
diff --git a/chrome/browser/resources/gpu_internals/browser_bridge.js b/chrome/browser/resources/gpu_internals/browser_bridge.js
index cd1bf6d..1b1e23b 100644
--- a/chrome/browser/resources/gpu_internals/browser_bridge.js
+++ b/chrome/browser/resources/gpu_internals/browser_bridge.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
    * @constructor
    */
   function BrowserBridge() {
-    // If we are not running inside DOMUI, output chrome.send messages
+    // If we are not running inside WebUI, output chrome.send messages
     // to the console to help with quick-iteration debugging.
     if (chrome.send === undefined && console.log) {
       chrome.send = function(messageHandler, args) {
diff --git a/chrome/browser/resources/gpu_internals/info_view.css b/chrome/browser/resources/gpu_internals/info_view.css
index a877032..c4cd6ca 100644
--- a/chrome/browser/resources/gpu_internals/info_view.css
+++ b/chrome/browser/resources/gpu_internals/info_view.css
@@ -16,6 +16,7 @@
 }
 
 #info-view table {
+  cursor: text;
   border-collapse: collapse;
 }
 
@@ -26,3 +27,4 @@
   padding-right: 4px;
   padding-left: 4px;
 }
+
diff --git a/chrome/browser/resources/gpu_internals/info_view.html b/chrome/browser/resources/gpu_internals/info_view.html
index 9ef43b8..dc4c0cb 100644
--- a/chrome/browser/resources/gpu_internals/info_view.html
+++ b/chrome/browser/resources/gpu_internals/info_view.html
@@ -3,7 +3,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<div id=info-view>
+<div id=info-view label="GPU Info">
   <h3>Chrome Version</h3>
   <div id="client-info"></div>
   <h3>Driver Information</h3>
@@ -12,6 +12,15 @@
   <h3>Diagnostics</h3>
   <div id="diagnostics">None</div>
 
+  <div id="log-messages" jsdisplay="values.length">
+    <h3>Log Messages</h3>
+    <ul>
+      <li jsselect="values">
+        <span jscontent="header"></span>: <span jscontent="message"></span>
+      </li>
+    </ul>
+  </div>
+    
   <!-- templates -->
   <div style="display:none">
     <div id="info-view-table-template">
diff --git a/chrome/browser/resources/gpu_internals/info_view.js b/chrome/browser/resources/gpu_internals/info_view.js
index acc4efc..6ce5a7f 100644
--- a/chrome/browser/resources/gpu_internals/info_view.js
+++ b/chrome/browser/resources/gpu_internals/info_view.js
@@ -15,17 +15,24 @@
   /**
    * Provides information on the GPU process and underlying graphics hardware.
    * @constructor
+   * @extends {Tab}
    */
-  function InfoView(mainBoxId) {
-    DivView.call(this, mainBoxId);
-
-    this.beginRequestClientInfo();
-    this.beginRequestGpuInfo();
-    this.refresh();
-  }
+  var InfoView = cr.ui.define(gpu.Tab);
 
   InfoView.prototype = {
-    __proto__: DivView.prototype,
+    __proto__: gpu.Tab.prototype,
+
+    decorate : function() {
+      gpu.Tab.prototype.decorate.apply(this);
+
+      this.beginRequestClientInfo();
+      this.beginRequestGpuInfo();
+
+      this.logMessages_ = [];
+      this.beginRequestLogMessages();
+
+      this.refresh();
+    },
 
     /**
      * This function begins a request for the ClientInfo. If it comes back
@@ -49,13 +56,30 @@
       browserBridge.callAsync('requestGpuInfo', undefined, (function(data) {
         this.gpuInfo_ = data;
         this.refresh();
-        if (!data || data.progress != 'complete') { // try again in 250 ms
+        if (!data || data.level != 'complete') { // try again in 250 ms
           window.setTimeout(this.beginRequestGpuInfo.bind(this), 250);
         }
       }).bind(this));
     },
 
     /**
+     * This function checks for new GPU_LOG messages.
+     * If any are found, a refresh is triggered.
+     */
+    beginRequestLogMessages : function() {
+      browserBridge.callAsync('requestLogMessages', undefined,
+        (function(messages) {
+           if(messages.length != this.logMessages_.length) {
+             this.logMessages_ = messages;
+             this.refresh();
+           }
+           // check again in 250 ms
+           window.setTimeout(this.beginRequestLogMessages.bind(this), 250);
+         }).bind(this));
+    },
+
+
+    /**
     * Updates the view based on its currently known data
     */
     refresh: function(data) {
@@ -83,7 +107,8 @@
         this.setTable_('basic-info', this.gpuInfo_.basic_info);
         if (this.gpuInfo_.diagnostics) {
           this.setTable_('diagnostics', this.gpuInfo_.diagnostics);
-        } else if (this.gpuInfo_.progress == 'partial') {
+        } else if (this.gpuInfo_.level == 'partial' ||
+                   this.gpuInfo_.level == 'completing') {
           this.setText_('diagnostics', '... loading...');
         } else {
           this.setText_('diagnostics', 'None');
@@ -92,6 +117,10 @@
         this.setText_('basic-info', '... loading ...');
         this.setText_('diagnostics', '... loading ...');
       }
+
+      // Log messages
+      jstProcess(new JsEvalContext({values: this.logMessages_}),
+                 document.getElementById('log-messages'));
     },
 
     setText_: function(outputElementId, text) {
diff --git a/chrome/browser/resources/gpu_internals/tab_control.css b/chrome/browser/resources/gpu_internals/tab_control.css
new file mode 100644
index 0000000..4d7b7f8
--- /dev/null
+++ b/chrome/browser/resources/gpu_internals/tab_control.css
@@ -0,0 +1,67 @@
+/*
+Copyright (c) 2011 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+*/
+.tab-control {
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-box-pack: start;
+
+  padding: 0;
+  margin: 0;
+}
+
+.tab-control > .tab-strip {
+  font-family: sans-serif;
+  background: #aaa;
+  border-bottom: 1px solid #555;
+
+  -webkit-user-select: none;
+
+  display: -webkit-box;
+  -webkit-box-orient: horizontal;
+  -webkit-box-pack: start;
+}
+
+.tab-control > .tabs {
+  -webkit-box-flex: 1;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-box-pack: stretch;
+  overflow: auto;
+}
+
+.tab-control > .tabs > :not([selected]) {
+  display: none;
+}
+
+.tab-control .tab-button {
+  -webkit-margin-start: 5px;
+  text-decoration: none;
+  text-align: center;
+  display: inline-block;
+  margin-top: 4px;
+  padding: 5px 10px 3px 10px;
+  border-top-right-radius: 8px;
+  border-top-left-radius: 8px;
+  background-clip: border-box;
+  background: #ccc;
+}
+
+.tab-control .tab-button:hover {
+  background: #eee;
+}
+
+
+.tab-control .tab-button:visited,
+.tab-control .tab-button {
+  color: blue;
+}
+
+.tab-control .tab-button[selected] {
+  position: relative;
+  top: 1px;
+  color: black;
+  background: white;
+}
diff --git a/chrome/browser/resources/gpu_internals/tab_control.js b/chrome/browser/resources/gpu_internals/tab_control.js
new file mode 100644
index 0000000..6c4a120
--- /dev/null
+++ b/chrome/browser/resources/gpu_internals/tab_control.js
@@ -0,0 +1,249 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+/**
+ *
+ * @fileoverview This implements a tab control.
+ *
+ * An individual tab within a tab control is, unsurprisingly, a Tab.
+ * Tabs must be explicitly added/removed from the control.
+ *
+ * Tab titles are based on the label attribute of each child:
+ *
+ * <div>
+ * <div label='Tab 1'>Hello</div>
+ * <div label='Tab 2'>World</div>
+ * </div>
+ *
+ * Results in:
+ *
+ * ---------------
+ * | Tab1 | Tab2 |
+ * | ---------------------------------------
+ * | Hello World |
+ * -----------------------------------------
+ *
+ */
+cr.define('gpu', function() {
+  /**
+   * Creates a new tab element. A tab element is one of multiple tabs
+   * within a TabControl.
+   * @constructor
+   * @param {Object=} opt_propertyBag Optional properties.
+   * @extends {HTMLDivElement}
+   */
+  var Tab = cr.ui.define('div');
+  Tab.prototype = {
+    __proto__: HTMLDivElement.prototype,
+
+    decorate : function() {
+    }
+  };
+
+  /**
+   * Title for the tab.
+   * @type {String}
+   */
+  cr.defineProperty(Tab, 'label', cr.PropertyKind.ATTR);
+
+  /**
+   * Whether the item is selected.
+   * @type {boolean}
+   */
+  cr.defineProperty(Tab, 'selected', cr.PropertyKind.BOOL_ATTR);
+
+
+  /**
+   * Creates a new tab button element in the tabstrip
+   * @constructor
+   * @param {Object=} opt_propertyBag Optional properties.
+   * @extends {HTMLDivElement}
+   */
+  var TabButton = cr.ui.define('a');
+  TabButton.prototype = {
+    __proto__: HTMLAnchorElement.prototype,
+
+    decorate: function() {
+      this.classList.add('tab-button');
+      this.onclick = function() {
+        if (this.tab_)
+          this.parentNode.parentNode.selectedTab = this.tab_;
+      }.bind(this);
+    },
+    get tab() {
+      return this.tab_;
+    },
+    set tab(tab) {
+      if (this.tab_)
+        throw Error('Cannot set tab once set.');
+      this.tab_ = tab;
+      this.tab_.addEventListener('titleChange', this.onTabChanged_.bind(this));
+      this.tab_.addEventListener('selectedChange',
+                                 this.onTabChanged_.bind(this));
+      this.onTabChanged_();
+    },
+
+    onTabChanged_ : function(e) {
+      if (this.tab_) {
+        this.textContent = this.tab_.label;
+        this.selected = this.tab_.selected;
+      }
+    }
+
+  };
+
+  /**
+   * Whether the TabButton is selected.
+   * @type {boolean}
+   */
+  cr.defineProperty(TabButton, 'selected', cr.PropertyKind.BOOL_ATTR);
+
+
+  /**
+   * Creates a new tab control element.
+   * @param {Object=} opt_propertyBag Optional properties.
+   * @constructor
+   * @extends {HTMLDivElement}
+   */
+  var TabControl = cr.ui.define('div');
+  TabControl.prototype = {
+    __proto__: HTMLDivElement.prototype,
+
+    selectedTab_ : null,
+
+    /**
+     * Initializes the tab control element.
+     * Any child elements pre-existing on the element will become tabs.
+     */
+    decorate: function() {
+      this.classList.add('tab-control');
+
+      this.tabStrip_ = this.ownerDocument.createElement('div');
+      this.tabStrip_.classList.add('tab-strip');
+
+      this.tabs_ = this.ownerDocument.createElement('div');
+      this.tabs_.classList.add('tabs');
+
+      this.insertBefore(this.tabs_, this.firstChild);
+      this.insertBefore(this.tabStrip_, this.firstChild);
+
+      this.boundOnTabSelectedChange_ = this.onTabSelectedChange_.bind(this);
+
+      // Reparent existing tabs to the tabs_ div.
+      while (this.children.length > 2)
+        this.addTab(this.children[2]);
+    },
+
+    /**
+     * Adds an element to the tab control.
+     */
+    addTab : function(tab) {
+      if (tab.parentNode == this.tabs_)
+        throw Error('Tab is already part of this control.');
+      if (!(tab instanceof Tab))
+        throw Error('Provided element is not instanceof Tab.');
+      this.tabs_.appendChild(tab);
+
+      tab.addEventListener('selectedChange', this.boundOnTabSelectedChange_);
+
+      var button = new TabButton();
+      button.tab = tab;
+      tab.tabStripButton_ = button;
+
+      this.tabStrip_.appendChild(button);
+
+      if (this.tabs_.length == 1)
+        this.tabs_.children[0].selected = true;
+    },
+
+    /**
+     * Removes a tab from the tab control.
+     * changing the selected tab if needed.
+     */
+    removeTab : function(tab) {
+      if (tab.parentNode != this.tabs_)
+        throw new Error('Tab is not attached to this control.');
+
+      tab.removeEventListener('selectedChange', this.boundOnTabSelectedChange_);
+
+      if (this.selectedTab_ == tab) {
+        if (this.tabs_.children.length) {
+          this.tabs_.children[0].selected = true;
+        } else {
+          this.selectedTab_ = undefined;
+        }
+      }
+
+      this.tabs_.removeChild(tab);
+      tab.tabStripButton_.parentNode.removeChild(
+        tab.tabStripButton_);
+    },
+
+    /**
+     * Gets the currently selected tab element.
+     */
+    get selectedTab() {
+      return this.selectedTab_;
+    },
+
+    /**
+     * Sets the currently selected tab element.
+     */
+    set selectedTab(tab) {
+      if (tab.parentNode != this.tabs_)
+        throw Error("Tab is not part of this TabControl.");
+      tab.selected = true;
+    },
+
+    /**
+     * Hides the previously selected tab element and dispatches a
+     * 'selectedTabChanged' event.
+     */
+    onTabSelectedChange_: function(e) {
+      var tab = e.target;
+      if (!e.newValue) {
+        // Usually we can ignore this event, as the tab becoming unselected
+        // needs no corrective action. However, if the currently selected
+        // tab is deselected, we do need to do some work.
+        if (tab == this.selectedTab_) {
+          var previousTab = this.selectedTab_;
+          var newTab;
+          for (var i = 0; i < this.tabs_.children.length; ++i) {
+            if (this.tabs_.children[i] != tab) {
+              newTab = this.tabs_.children[i];
+              break;
+            }
+          }
+          if (newTab) {
+            newTab.selected = true;
+          } else {
+            this.selectedTab_ = undefined;
+            cr.dispatchPropertyChange(
+                this, 'selectedTab', this.selectedTab_, previousTab);
+          }
+        }
+      } else {
+        var previousTab = this.selectedTab_;
+        this.selectedTab_ = tab;
+        if (previousTab)
+          previousTab.selected = false;
+        cr.dispatchPropertyChange(
+            this, 'selectedTab', this.selectedTab_, previousTab);
+      }
+    },
+
+    /**
+     * Returns an array of all the tabs within this control.  This is
+     * not the same as this.children because the actual tab elements are
+     * attached to the tabs_ element.
+     */
+    get tabs() {
+      return Array.prototype.slice.call(this.tabs_.children);
+    }
+  };
+
+  return {
+    Tab : Tab,
+    TabControl: TabControl
+  };
+});
\ No newline at end of file
diff --git a/chrome/browser/resources/help_app/manifest.json b/chrome/browser/resources/help_app/manifest.json
new file mode 100644
index 0000000..368171e
--- /dev/null
+++ b/chrome/browser/resources/help_app/manifest.json
@@ -0,0 +1,22 @@
+{
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqtHjbcvWT9Kbcapi0SaG28I66eRQHQvOqngCizm87qMb9RTgrftaUAGwPmxFLy4gBwO572N5ACpxsR6m2fRg9PSjeqaEojiFd28KY/b4VPoq/ukNOy97Ns7lPv4gmtNB8txuFIFuNw3s1k8nEJVAp659d7SnMsL4O1uXkW1huGQIDAQAB",
+  "name": "Help",
+  "version": "1.5",
+  "icons": {"16": "images/Help_16.png",
+            "24": "images/Help_24.png",
+            "48": "images/Help_48.png",
+            "128": "images/Help_128.png" },
+  "description": "Chrome OS Help",
+  "default_locale": "en",
+  "incognito": "split",
+  "permissions": [
+    "tabs",
+    "http://www.google.com/support/chromeos/*/*",
+    "https://www.google.com/support/chromeos/*/*"
+  ],
+  "browser_action": {
+    "default_icon": "images/question_16b.png",
+    "default_title": "Help Center",
+    "default_popup": "popup.html"
+  }
+}
diff --git a/chrome/browser/resources/history.html b/chrome/browser/resources/history.html
index 851601f..a6716a6 100644
--- a/chrome/browser/resources/history.html
+++ b/chrome/browser/resources/history.html
@@ -5,6 +5,7 @@
 <title i18n-content="title"></title>
 <link rel="icon" href="../../app/theme/history_favicon.png">
 <script src="shared/js/local_strings.js"></script>
+<script src="shared/js/util.js"></script>
 <script>
 ///////////////////////////////////////////////////////////////////////////////
 // Globals:
@@ -162,6 +163,7 @@
   node.className = 'title';
   var link = document.createElement('a');
   link.href = this.url_;
+
   link.style.backgroundImage =
       'url(chrome://favicon/' + encodeURIForCSS(this.url_) + ')';
   link.id = "id-" + this.id_;
diff --git a/chrome/browser/resources/host_registration_page.html b/chrome/browser/resources/host_registration_page.html
index 058c4c0..fc86439 100644
--- a/chrome/browser/resources/host_registration_page.html
+++ b/chrome/browser/resources/host_registration_page.html
@@ -60,7 +60,7 @@
   $('form').contentWindow.postMessage(msg, registrationUrl);
 }
 
-// Called by DOMUI handler when startup manifest is not defined.
+// Called by WebUI handler when startup manifest is not defined.
 function skipRegistration() {
   location.replace(registerSkipUrl);
 }
diff --git a/chrome/browser/resources/keyboard_overlay.css b/chrome/browser/resources/keyboard_overlay.css
index 239cb4e..2f9506f 100644
--- a/chrome/browser/resources/keyboard_overlay.css
+++ b/chrome/browser/resources/keyboard_overlay.css
@@ -12,26 +12,34 @@
 }
 
 .keyboard-overlay-instructions {
-  border-radius: 5px;
+  -webkit-box-orient: vertical;
   background: -webkit-linear-gradient(#334c7e, #0d172b);
+  border-radius: 5px;
   border: 2px solid #576ccf;
   color: #fff;
-  display: table;
+  display: -webkit-box;
   position: absolute;
   vertical-align: middle;
   z-index: 100;
 }
 
 .keyboard-overlay-instructions-text {
-  display: table-cell;
+  -webkit-box-flex: 3;
+  margin-top: 13px;
+  text-align: center;
+  vertical-align: middle;
+}
+
+.keyboard-overlay-instructions-hide-text {
+  -webkit-box-flex: 2;
   font-weight: bold;
   text-align: center;
   vertical-align: middle;
 }
 
 .keyboard-overlay-key {
-  border-radius: 4px;
   -webkit-box-orient: vertical;
+  border-radius: 4px;
   background-color: rgba(24, 24, 24, 0.9);
   border: 2px solid #7f7f7f;
   color: #979796;
diff --git a/chrome/browser/resources/keyboard_overlay.js b/chrome/browser/resources/keyboard_overlay.js
index cb72e43..6f414f9 100644
--- a/chrome/browser/resources/keyboard_overlay.js
+++ b/chrome/browser/resources/keyboard_overlay.js
@@ -6,14 +6,14 @@
   top: 0,
   left: 0,
   width: 1237,
-  height: 468
+  height: 514
 };
 
 var BASE_INSTRUCTIONS = {
-  top: 174,
+  top: 194,
   left: 370,
   width: 498,
-  height: 81
+  height: 112
 };
 
 var LABEL_TO_KEY_TEXT = {
@@ -33,11 +33,14 @@
   glyph_enter: 'enter',
   glyph_forward: 'forward',
   glyph_fullscreen: 'fullscreen',
+  glyph_ime: 'ime',
+  glyph_lock: 'lock',
   glyph_overview: 'windows',
   glyph_power: 'power',
-  glyph_reload: 'reload',
+  glyph_right: 'right',
   glyph_reload: 'reload',
   glyph_search: 'search',
+  glyph_shift: 'shift',
   glyph_tab: 'tab',
   glyph_tools: 'tools',
   glyph_volume_down: 'vol. down',
@@ -377,8 +380,7 @@
   keyboard.style.width = (width + 2 * (minX + 1)) + 'px';
   keyboard.style.height = (height + 2 * (minY + 1)) + 'px';
 
-  var instructions = document.createElement('instructions');
-  instructions = document.createElement('div');
+  var instructions = document.createElement('div');
   instructions.id = 'instructions';
   instructions.className = 'keyboard-overlay-instructions';
   instructions.style.left = ((BASE_INSTRUCTIONS.left - BASE_KEYBOARD.left) *
@@ -390,11 +392,16 @@
   instructions.style.height = (height * BASE_INSTRUCTIONS.height /
                                BASE_KEYBOARD.height) + 'px';
 
-  var instructionsText = document.createElement('span');
+  var instructionsText = document.createElement('div');
   instructionsText.id = 'instructions-text';
   instructionsText.className = 'keyboard-overlay-instructions-text';
   instructionsText.innerHTML = templateData.keyboardOverlayInstructions;
   instructions.appendChild(instructionsText);
+  var instructionsHideText = document.createElement('div');
+  instructionsHideText.id = 'instructions-hide-text';
+  instructionsHideText.className = 'keyboard-overlay-instructions-hide-text';
+  instructionsHideText.innerHTML = templateData.keyboardOverlayInstructionsHide;
+  instructions.appendChild(instructionsHideText);
   keyboard.appendChild(instructions);
 }
 
@@ -412,7 +419,12 @@
  * Called after sending the 'getKeyboardOverlayId' message.
  */
 function initKeyboardOverlayId(overlayId) {
-  keyboardOverlayId = overlayId;
+  // Libcros returns an empty string when it cannot find the keyboard overlay ID
+  // corresponding to the current input method.
+  // In such a case, fallback to the default ID (en_US).
+  if (overlayId) {
+    keyboardOverlayId = overlayId;
+  }
   while(document.body.firstChild) {
     document.body.removeChild(document.body.firstChild);
   }
diff --git a/chrome/browser/resources/keyboard_overlay_data.js b/chrome/browser/resources/keyboard_overlay_data.js
index 9d590af..3b40b5b 100644
--- a/chrome/browser/resources/keyboard_overlay_data.js
+++ b/chrome/browser/resources/keyboard_overlay_data.js
@@ -1803,8 +1803,8 @@
           "position": "11"
         },
         "3D": {
-          "key": " glyph_overview",
-          "label": "glyph_overview",
+          "key": " glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -1813,8 +1813,8 @@
           "position": "13"
         },
         "3F": {
-          "key": " glyph_tools",
-          "label": "glyph_tools",
+          "key": " glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -3155,8 +3155,8 @@
           "position": "11"
         },
         "3D": {
-          "key": " glyph_overview",
-          "label": "glyph_overview",
+          "key": " glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -3165,8 +3165,8 @@
           "position": "13"
         },
         "3F": {
-          "key": " glyph_tools",
-          "label": "glyph_tools",
+          "key": " glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -3245,6 +3245,464 @@
       },
       "layoutName": "E"
     },
+    "de_neo": {
+      "keys": {
+        "00": {
+          "key": " glyph_power",
+          "label": "glyph_power",
+          "notes": "power",
+          "position": "999"
+        },
+        "01": {
+          "format": "smaller",
+          "key": " esc",
+          "label": "esc",
+          "notes": "escape",
+          "position": "0"
+        },
+        "02": {
+          "key": " \u00b0\n 1 \u00b9",
+          "p2": "00B0",
+          "p8": "31",
+          "p9": "00B9",
+          "position": "110"
+        },
+        "03": {
+          "key": " \u00a7\n 2 \u00b2",
+          "p2": "00A7",
+          "p8": "32",
+          "p9": "00B2",
+          "position": "111"
+        },
+        "04": {
+          "key": " \u2113\n 3 \u00b3",
+          "p2": "2113",
+          "p8": "33",
+          "p9": "00B3",
+          "position": "112"
+        },
+        "05": {
+          "key": " \u00bb\n 4 \u203a",
+          "p2": "00BB",
+          "p8": "34",
+          "p9": "203A",
+          "position": "113"
+        },
+        "06": {
+          "key": " \u00ab\n 5 \u2039",
+          "p2": "00AB",
+          "p8": "35",
+          "p9": "2039",
+          "position": "114"
+        },
+        "07": {
+          "key": " $\n 6 \u00a2",
+          "p2": "24",
+          "p8": "36",
+          "p9": "00A2",
+          "position": "115"
+        },
+        "08": {
+          "key": " \u20ac\n 7 \u00a5",
+          "p2": "20AC",
+          "p8": "37",
+          "p9": "00A5",
+          "position": "116"
+        },
+        "09": {
+          "key": " \u201e\n 8 \u201a",
+          "p2": "201E",
+          "p8": "38",
+          "p9": "201A",
+          "position": "117"
+        },
+        "0A": {
+          "key": " \u201c\n 9 \u2018",
+          "p2": "201C",
+          "p8": "39",
+          "p9": "2018",
+          "position": "118"
+        },
+        "0B": {
+          "key": " \u201d\n 0 \u2019",
+          "p2": "201D",
+          "p8": "30",
+          "p9": "2019",
+          "position": "119"
+        },
+        "0C": {
+          "key": " \u2014\n -",
+          "p2": "2014",
+          "p8": "2D",
+          "position": "120"
+        },
+        "0D": {
+          "key": " \u00b8\n \u02cb \u02da",
+          "p2": "00B8",
+          "p8": "02CB",
+          "p9": "02DA",
+          "position": "121"
+        },
+        "0E": {
+          "format": "right",
+          "key": " glyph_backspace",
+          "label": "glyph_backspace",
+          "notes": "backspace",
+          "position": "190"
+        },
+        "0F": {
+          "format": "left",
+          "key": " glyph_tab",
+          "label": "glyph_tab",
+          "notes": "tab",
+          "position": "200"
+        },
+        "10": {
+          "key": " x \u2026",
+          "p5": "78",
+          "p9": "2026",
+          "position": "210"
+        },
+        "11": {
+          "key": " v _",
+          "p5": "76",
+          "p9": "005F",
+          "position": "211"
+        },
+        "12": {
+          "key": " l [",
+          "p5": "6C",
+          "p9": "005B",
+          "position": "212"
+        },
+        "13": {
+          "key": " c ]",
+          "p5": "63",
+          "p9": "005D",
+          "position": "213"
+        },
+        "14": {
+          "key": " w ^",
+          "p5": "77",
+          "p9": "005E",
+          "position": "214"
+        },
+        "15": {
+          "key": " k !",
+          "p5": "6B",
+          "p9": "21",
+          "position": "215"
+        },
+        "16": {
+          "key": " h <",
+          "p5": "68",
+          "p9": "003C",
+          "position": "216"
+        },
+        "17": {
+          "key": " g >",
+          "p5": "67",
+          "p9": "003E",
+          "position": "217"
+        },
+        "18": {
+          "key": " f =",
+          "p5": "66",
+          "p9": "003D",
+          "position": "218"
+        },
+        "19": {
+          "key": " q &",
+          "p5": "71",
+          "p9": "26",
+          "position": "219"
+        },
+        "1A": {
+          "key": " \u00df \u017f",
+          "p5": "DF",
+          "p9": "017F",
+          "position": "220"
+        },
+        "1B": {
+          "key": " \u02dc\n \u02ca /",
+          "p2": "02DC",
+          "p8": "02CA",
+          "p9": "002F",
+          "position": "221"
+        },
+        "1C": {
+          "format": "right",
+          "key": " glyph_enter",
+          "label": "glyph_enter",
+          "notes": "enter",
+          "position": "390"
+        },
+        "1D": {
+          "format": "left",
+          "key": " strg",
+          "label": "strg",
+          "notes": "left ctrl",
+          "position": "500"
+        },
+        "1E": {
+          "key": " u \\",
+          "p5": "75",
+          "p9": "005C",
+          "position": "310"
+        },
+        "1F": {
+          "key": " i /",
+          "p5": "69",
+          "p9": "002F",
+          "position": "311"
+        },
+        "20": {
+          "key": " a {",
+          "p5": "61",
+          "p9": "007B",
+          "position": "312"
+        },
+        "21": {
+          "key": " e }",
+          "p5": "65",
+          "p9": "007D",
+          "position": "313"
+        },
+        "22": {
+          "key": " o *",
+          "p5": "6F",
+          "p9": "002A",
+          "position": "314"
+        },
+        "23": {
+          "key": " s ?",
+          "p5": "73",
+          "p9": "003F",
+          "position": "315"
+        },
+        "24": {
+          "key": " n (",
+          "p5": "6E",
+          "p9": "28",
+          "position": "316"
+        },
+        "25": {
+          "key": " r )",
+          "p5": "72",
+          "p9": "29",
+          "position": "317"
+        },
+        "26": {
+          "key": " t -",
+          "p5": "74",
+          "p9": "002D",
+          "position": "318"
+        },
+        "27": {
+          "key": " d :",
+          "p5": "64",
+          "p9": "003A",
+          "position": "319"
+        },
+        "28": {
+          "key": " y @",
+          "p5": "79",
+          "p9": "40",
+          "position": "320"
+        },
+        "29": {
+          "key": " \u02c7\n \u02c6",
+          "p2": "02C7",
+          "p8": "02C6",
+          "position": "100"
+        },
+        "2A": {
+          "format": "left",
+          "key": " glyph_shift",
+          "label": "glyph_shift",
+          "notes": "left shift",
+          "position": "400"
+        },
+        "2B": {
+          "key": " mod3",
+          "label": "mod3",
+          "position": "290"
+        },
+        "2C": {
+          "key": " \u00fc #",
+          "p5": "00FC",
+          "p9": "23",
+          "position": "410"
+        },
+        "2D": {
+          "key": " \u00f6 $",
+          "p5": "00F6",
+          "p9": "24",
+          "position": "411"
+        },
+        "2E": {
+          "key": " \u00e4 |",
+          "p5": "E4",
+          "p9": "007C",
+          "position": "412"
+        },
+        "2F": {
+          "key": " p ~",
+          "p5": "70",
+          "p9": "007E",
+          "position": "413"
+        },
+        "30": {
+          "key": " z `",
+          "p5": "7a",
+          "p9": "60",
+          "position": "414"
+        },
+        "31": {
+          "key": " b +",
+          "p5": "62",
+          "p9": "002B",
+          "position": "415"
+        },
+        "32": {
+          "key": " m %",
+          "p5": "6D",
+          "p9": "25",
+          "position": "416"
+        },
+        "33": {
+          "key": " \u2013\n , \"",
+          "p2": "2013",
+          "p8": "2C",
+          "p9": "22",
+          "position": "417"
+        },
+        "34": {
+          "key": " \u2022\n . '",
+          "p2": "2022",
+          "p8": "2E",
+          "p9": "27",
+          "position": "418"
+        },
+        "35": {
+          "key": " j ;",
+          "p5": "6A",
+          "p9": "003B",
+          "position": "419"
+        },
+        "36": {
+          "format": "right",
+          "key": " glyph_shift",
+          "label": "glyph_shift",
+          "notes": "right shift",
+          "position": "490"
+        },
+        "38": {
+          "format": "left",
+          "key": " alt",
+          "label": "alt",
+          "notes": "left alt",
+          "position": "501"
+        },
+        "3B": {
+          "key": " glyph_back",
+          "label": "glyph_back",
+          "position": "10"
+        },
+        "3C": {
+          "key": " glyph_forward",
+          "label": "glyph_forward",
+          "position": "11"
+        },
+        "3D": {
+          "key": " glyph_reload",
+          "label": "glyph_reload",
+          "position": "12"
+        },
+        "3E": {
+          "key": " glyph_fullscreen",
+          "label": "glyph_fullscreen",
+          "position": "13"
+        },
+        "3F": {
+          "key": " glyph_overview",
+          "label": "glyph_overview",
+          "position": "14"
+        },
+        "40": {
+          "key": " glyph_brightness_down",
+          "label": "glyph_brightness_down",
+          "position": "15"
+        },
+        "41": {
+          "key": " glyph_brightness_up",
+          "label": "glyph_brightness_up",
+          "position": "16"
+        },
+        "42": {
+          "key": " glyph_volume_mute",
+          "label": "glyph_volume_mute",
+          "position": "17"
+        },
+        "43": {
+          "key": " glyph_volume_down",
+          "label": "glyph_volume_down",
+          "position": "18"
+        },
+        "44": {
+          "key": " glyph_volume_up",
+          "label": "glyph_volume_up",
+          "position": "19"
+        },
+        "56": {
+          "key": " mod4",
+          "label": "mod4",
+          "position": "409"
+        },
+        "E0 1D": {
+          "format": "smaller",
+          "key": " strg",
+          "label": "strg",
+          "notes": "right ctrl",
+          "position": "581"
+        },
+        "E0 38": {
+          "format": "smaller",
+          "key": " mod4",
+          "label": "mod4",
+          "notes": "right alt",
+          "position": "580"
+        },
+        "E0 48": {
+          "key": " glyph_arrow_up",
+          "label": "glyph_arrow_up",
+          "position": "590"
+        },
+        "E0 4B": {
+          "key": " glyph_arrow_left",
+          "label": "glyph_arrow_left",
+          "position": "591"
+        },
+        "E0 4D": {
+          "key": " glyph_arrow_right",
+          "label": "glyph_arrow_right",
+          "position": "593"
+        },
+        "E0 50": {
+          "key": " glyph_arrow_down",
+          "label": "glyph_arrow_down",
+          "position": "592"
+        },
+        "E0 5B": {
+          "format": "left",
+          "key": " mod3",
+          "label": "mod3",
+          "notes": "search",
+          "position": "300"
+        }
+      },
+      "layoutName": "E"
+    },
     "el": {
       "keys": {
         "00": {
@@ -4026,8 +4484,8 @@
           "position": "11"
         },
         "3D": {
-          "key": "glyph_overview",
-          "label": "glyph_overview",
+          "key": "glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -4036,8 +4494,8 @@
           "position": "13"
         },
         "3F": {
-          "key": "glyph_tools",
-          "label": "glyph_tools",
+          "key": "glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -4218,6 +4676,7 @@
         },
         "10": {
           "key": "q",
+          "notes": "71",
           "p5": "71",
           "position": "210"
         },
@@ -4529,6 +4988,194 @@
       },
       "layoutName": "U"
     },
+    "en_US_colemak": {
+      "keys": {
+        "00": {
+          "key": "glyph_power",
+          "label": "glyph_power",
+          "notes": "power"
+        },
+        "01": {
+          "format": "smaller",
+          "key": "esc",
+          "label": "esc",
+          "notes": "escape"
+        },
+        "02": {},
+        "03": {},
+        "04": {},
+        "05": {},
+        "06": {},
+        "07": {},
+        "08": {},
+        "09": {},
+        "0A": {},
+        "0B": {},
+        "0C": {},
+        "0D": {},
+        "0E": {
+          "format": "right",
+          "key": "backspace",
+          "label": "backspace",
+          "notes": "backspace"
+        },
+        "0F": {
+          "format": "left",
+          "key": "tab",
+          "label": "tab",
+          "notes": "tab"
+        },
+        "10": {},
+        "11": {},
+        "12": {},
+        "13": {},
+        "14": {},
+        "15": {},
+        "16": {},
+        "17": {},
+        "18": {},
+        "19": {},
+        "1A": {},
+        "1B": {},
+        "1C": {
+          "format": "right",
+          "key": "enter",
+          "label": "enter",
+          "notes": "enter"
+        },
+        "1D": {
+          "format": "left",
+          "key": "ctrl",
+          "label": "ctrl",
+          "notes": "left ctrl"
+        },
+        "1E": {},
+        "1F": {},
+        "20": {},
+        "21": {},
+        "22": {},
+        "23": {},
+        "24": {},
+        "25": {},
+        "26": {},
+        "27": {},
+        "28": {},
+        "29": {},
+        "2A": {
+          "format": "left",
+          "key": "shift",
+          "label": "shift",
+          "notes": "left shift"
+        },
+        "2B": {},
+        "2C": {},
+        "2D": {},
+        "2E": {},
+        "2F": {},
+        "30": {},
+        "31": {},
+        "32": {},
+        "33": {},
+        "34": {},
+        "35": {},
+        "36": {
+          "format": "right",
+          "key": "shift",
+          "label": "shift",
+          "notes": "right shift"
+        },
+        "37": {},
+        "38": {
+          "format": "left",
+          "key": "alt",
+          "label": "alt",
+          "notes": "left alt"
+        },
+        "3B": {
+          "key": "glyph_back",
+          "label": "glyph_back"
+        },
+        "3C": {
+          "key": "glyph_forward",
+          "label": "glyph_forward"
+        },
+        "3D": {
+          "key": "glyph_reload",
+          "label": "glyph_reload"
+        },
+        "3E": {
+          "key": "glyph_overview",
+          "label": "glyph_overview"
+        },
+        "3F": {
+          "key": "glyph_fullscreen",
+          "label": "glyph_fullscreen"
+        },
+        "40": {
+          "key": "glyph_brightness_down",
+          "label": "glyph_brightness_down"
+        },
+        "41": {
+          "key": "glyph_brightness_up",
+          "label": "glyph_brightness_up"
+        },
+        "42": {
+          "key": "glyph_volume_mute",
+          "label": "glyph_volume_mute"
+        },
+        "43": {
+          "key": "glyph_volume_down",
+          "label": "glyph_volume_down"
+        },
+        "44": {
+          "key": "glyph_volume_up",
+          "label": "glyph_volume_up"
+        },
+        "73": {},
+        "79": {
+          "format": "smaller"
+        },
+        "7B": {
+          "format": "smaller"
+        },
+        "7D": {},
+        "E0 1D": {
+          "format": "smaller",
+          "key": "ctrl",
+          "label": "ctrl",
+          "notes": "right ctrl"
+        },
+        "E0 38": {
+          "format": "smaller",
+          "key": "alt",
+          "label": "alt",
+          "notes": "right alt"
+        },
+        "E0 48": {
+          "key": "glyph_arrow_up",
+          "label": "glyph_arrow_up"
+        },
+        "E0 4B": {
+          "key": "glyph_arrow_left",
+          "label": "glyph_arrow_left"
+        },
+        "E0 4D": {
+          "key": "glyph_arrow_right",
+          "label": "glyph_arrow_right"
+        },
+        "E0 50": {
+          "key": "glyph_arrow_down",
+          "label": "glyph_arrow_down"
+        },
+        "E0 5B": {
+          "format": "left",
+          "key": "glyph_search",
+          "label": "glyph_search",
+          "notes": "search"
+        }
+      },
+      "layoutName": "U"
+    },
     "en_US_dvorak": {
       "keys": {
         "00": {
@@ -5684,8 +6331,8 @@
           "position": "11"
         },
         "3D": {
-          "key": " glyph_overview",
-          "label": "glyph_overview",
+          "key": " glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -5694,8 +6341,8 @@
           "position": "13"
         },
         "3F": {
-          "key": " glyph_tools",
-          "label": "glyph_tools",
+          "key": " glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -7866,7 +8513,7 @@
         },
         "3D": {
           "key": " glyph_overview",
-          "label": "glyph_overview",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -7875,8 +8522,8 @@
           "position": "13"
         },
         "3F": {
-          "key": " glyph_tools",
-          "label": "glyph_tools",
+          "key": " glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -8415,8 +9062,9 @@
           "position": "0"
         },
         "02": {
-          "key": "! \n1 \u0967",
+          "key": "! \u090d\n1 \u0967",
           "p1": "21",
+          "p3": "090D",
           "p7": "31",
           "p9": "967",
           "position": "110"
@@ -8430,49 +9078,55 @@
           "position": "111"
         },
         "04": {
-          "key": "# \n3 \u0969",
+          "key": "#VALUE!",
           "notes": "\u094d\u0930",
           "p1": "23",
+          "p3": "094D0930",
           "p7": "33",
           "p9": "969",
           "position": "112"
         },
         "05": {
-          "key": "$ \n4 \u096a",
+          "key": "#VALUE!",
           "notes": "\u0930\u094d",
           "p1": "24",
+          "p3": "0930094D",
           "p7": "34",
           "p9": "96A",
           "position": "113"
         },
         "06": {
-          "key": "% \n5 \u096b",
+          "key": "#NUM!",
           "notes": "\u091c\u094d\u091e",
           "p1": "25",
+          "p3": "091C094D091E",
           "p7": "35",
           "p9": "96B",
           "position": "114"
         },
         "07": {
-          "key": "^ \n6 \u096c",
+          "key": "#NUM!",
           "notes": "\u0924\u094d\u0930",
           "p1": "5E",
+          "p3": "0924094D0930",
           "p7": "36",
           "p9": "96C",
           "position": "115"
         },
         "08": {
-          "key": "& \n7 \u096d",
+          "key": "#NUM!",
           "notes": "\u0915\u094d\u0937",
           "p1": "26",
+          "p3": "0915094D0937",
           "p7": "37",
           "p9": "96D",
           "position": "116"
         },
         "09": {
-          "key": "* \n8 \u096e",
+          "key": "#NUM!",
           "notes": "\u0936\u094d\u0930",
           "p1": "2A",
+          "p3": "0936094D0930",
           "p7": "38",
           "p9": "96E",
           "position": "117"
@@ -8665,7 +9319,8 @@
           "position": "315"
         },
         "24": {
-          "key": "j \u0930",
+          "key": " \u0931\nj \u0930",
+          "p3": "931",
           "p7": "6A",
           "p9": "930",
           "position": "316"
@@ -8745,13 +9400,15 @@
           "position": "412"
         },
         "2F": {
-          "key": "v \u0928",
+          "key": " \u0929\nv \u0928",
+          "p3": "929",
           "p7": "76",
           "p9": "928",
           "position": "413"
         },
         "30": {
-          "key": "b \u0935",
+          "key": " \u0934\nb \u0935",
+          "p3": "934",
           "p7": "62",
           "p9": "935",
           "position": "414"
@@ -8787,8 +9444,9 @@
           "position": "418"
         },
         "35": {
-          "key": "? \n/ \u092f",
+          "key": "? \u095f\n/ \u092f",
           "p1": "3F",
+          "p3": "095F",
           "p7": "2F",
           "p9": "092F",
           "position": "419"
@@ -9340,8 +9998,8 @@
         },
         "E0 38": {
           "format": "smaller",
-          "key": "alt",
-          "label": "alt",
+          "key": "alt gr",
+          "label": "alt gr",
           "notes": "right alt",
           "position": "580"
         },
@@ -10589,8 +11247,8 @@
           "position": "11"
         },
         "3D": {
-          "key": " glyph_overview",
-          "label": "glyph_overview",
+          "key": " glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -10599,8 +11257,8 @@
           "position": "13"
         },
         "3F": {
-          "key": " glyph_tools",
-          "label": "glyph_tools",
+          "key": " glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -13562,9 +14220,10 @@
           "position": "220"
         },
         "1B": {
-          "key": " \u00a8 ~",
-          "p5": "00A8",
-          "p9": "007E",
+          "key": " ^ \n \u00a8 ~",
+          "p1": "5e",
+          "p7": "00A8",
+          "p9": "7e",
           "position": "221"
         },
         "1C": {
@@ -13650,8 +14309,9 @@
           "position": "400"
         },
         "2B": {
-          "key": " '",
-          "p5": "27",
+          "key": " *\n '",
+          "p2": "2a",
+          "p8": "27",
           "position": "290"
         },
         "2C": {
@@ -13685,8 +14345,9 @@
           "position": "415"
         },
         "32": {
-          "key": "m",
+          "key": "m \u03bc",
           "p5": "006D",
+          "p9": "3bc",
           "position": "416"
         },
         "33": {
@@ -13828,7 +14489,7 @@
         },
         "E0 5B": {
           "format": "left",
-          "key": "glyph_search",
+          "key": " glyph_search",
           "label": "glyph_search",
           "notes": "search",
           "position": "300"
@@ -14447,11 +15108,11 @@
           "position": "220"
         },
         "1B": {
-          "key": "{ \n[ \uda68\udf32",
+          "key": "#VALUE!",
           "notes": "The a needs to be underlined",
           "p1": "7B",
           "p7": "5B",
-          "p9": "AA332",
+          "p9": "AA0332",
           "position": "221"
         },
         "1C": {
@@ -14538,11 +15199,11 @@
           "position": "400"
         },
         "2B": {
-          "key": "} \n] \u00ba",
+          "key": "#VALUE!",
           "notes": "The o needs to be underlined",
           "p1": "7D",
           "p7": "5D",
-          "p9": "BA",
+          "p9": "BA0332",
           "position": "290"
         },
         "2C": {
@@ -14624,8 +15285,8 @@
           "position": "11"
         },
         "3D": {
-          "key": "glyph_overview",
-          "label": "glyph_overview",
+          "key": "glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -14634,8 +15295,8 @@
           "position": "13"
         },
         "3F": {
-          "key": "glyph_tools",
-          "label": "glyph_tools",
+          "key": "glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -14967,9 +15628,9 @@
           "position": "319"
         },
         "28": {
-          "key": "\u00aa\n\u00ba",
-          "p2": "aa",
-          "p8": "ba",
+          "key": "#VALUE!",
+          "p2": "aa0332",
+          "p8": "ba0332",
           "position": "320"
         },
         "29": {
@@ -15069,8 +15730,8 @@
           "position": "11"
         },
         "3D": {
-          "key": " glyph_overview",
-          "label": "glyph_overview",
+          "key": " glyph_reload",
+          "label": "glyph_reload",
           "position": "12"
         },
         "3E": {
@@ -15079,8 +15740,8 @@
           "position": "13"
         },
         "3F": {
-          "key": " glyph_tools",
-          "label": "glyph_tools",
+          "key": " glyph_overview",
+          "label": "glyph_overview",
           "position": "14"
         },
         "40": {
@@ -15319,8 +15980,8 @@
           "position": "214"
         },
         "15": {
-          "key": "z",
-          "p5": "7A",
+          "key": "y",
+          "p5": "79",
           "position": "215"
         },
         "16": {
@@ -15421,14 +16082,14 @@
           "position": "318"
         },
         "27": {
-          "key": "\u015f @",
-          "p5": "015F",
+          "key": "\u0219 @",
+          "p5": "219",
           "p9": "40",
           "position": "319"
         },
         "28": {
-          "key": "\u0163 \u00df",
-          "p5": "163",
+          "key": "\u021b \u00df",
+          "p5": "021b",
           "p9": "DF",
           "position": "320"
         },
@@ -15451,8 +16112,8 @@
           "position": "290"
         },
         "2C": {
-          "key": "y",
-          "p5": "79",
+          "key": "z",
+          "p5": "7a",
           "position": "410"
         },
         "2D": {
@@ -16215,69 +16876,68 @@
         },
         "0E": {
           "format": "right",
-          "key": "#NUM!",
+          "key": "glyph_backspace",
+          "label": "glyph_backspace",
           "notes": "backspace",
-          "p2": "backspace",
-          "p8": "glyph_backspace",
           "position": "190"
         },
         "0F": {
           "format": "left",
-          "key": "#NUM!",
+          "key": "glyph_tab",
+          "label": "glyph_tab",
           "notes": "tab",
-          "p2": "tab",
-          "p8": "glyph_tab",
           "position": "200"
         },
         "10": {
-          "key": "q ",
-          "p1": "71",
+          "key": "q",
+          "p5": "71",
           "position": "210"
         },
         "11": {
-          "key": "w ",
-          "p1": "77",
+          "key": "w",
+          "p5": "77",
           "position": "211"
         },
         "12": {
-          "key": "e ",
-          "p1": "65",
+          "key": "e \u20ac",
+          "p5": "65",
+          "p9": "20ac",
           "position": "212"
         },
         "13": {
-          "key": "r ",
-          "p1": "72",
+          "key": "r",
+          "p5": "72",
           "position": "213"
         },
         "14": {
-          "key": "t ",
-          "p1": "74",
+          "key": "t",
+          "p5": "74",
           "position": "214"
         },
         "15": {
-          "key": "y \n z",
-          "p1": "79",
-          "p9": "7a",
+          "key": "yz",
+          "p5": "79",
+          "p6": "7a",
           "position": "215"
         },
         "16": {
-          "key": "u ",
-          "p1": "75",
+          "key": "u",
+          "p5": "75",
           "position": "216"
         },
         "17": {
-          "key": "i ",
-          "p1": "69",
+          "key": "i",
+          "p5": "69",
           "position": "217"
         },
         "18": {
-          "key": "o ",
-          "p1": "6f",
+          "key": "o",
+          "p5": "6f",
           "position": "218"
         },
         "19": {
-          "key": "p ",
-          "p1": "70",
+          "key": "p",
+          "p5": "70",
           "position": "219"
         },
         "1A": {
@@ -16298,10 +16958,9 @@
         },
         "1C": {
           "format": "right",
-          "key": "#NUM!",
+          "key": "glyph_enter",
+          "label": "glyph_enter",
           "notes": "enter",
-          "p2": "enter",
-          "p8": "glyph_enter",
           "position": "390"
         },
         "1D": {
@@ -16312,48 +16971,48 @@
           "position": "500"
         },
         "1E": {
-          "key": "a ",
-          "p1": "61",
+          "key": "a",
+          "p5": "61",
           "position": "310"
         },
         "1F": {
-          "key": "s ",
-          "p1": "73",
+          "key": "s",
+          "p5": "73",
           "position": "311"
         },
         "20": {
-          "key": "d ",
-          "p1": "64",
+          "key": "d",
+          "p5": "64",
           "position": "312"
         },
         "21": {
-          "key": "f ",
-          "p1": "66",
+          "key": "f",
+          "p5": "66",
           "position": "313"
         },
         "22": {
-          "key": "g ",
-          "p1": "67",
+          "key": "g",
+          "p5": "67",
           "position": "314"
         },
         "23": {
-          "key": "h ",
-          "p1": "68",
+          "key": "h",
+          "p5": "68",
           "position": "315"
         },
         "24": {
-          "key": "j ",
-          "p1": "6a",
+          "key": "j",
+          "p5": "6a",
           "position": "316"
         },
         "25": {
-          "key": "k ",
-          "p1": "6b",
+          "key": "k",
+          "p5": "6b",
           "position": "317"
         },
         "26": {
-          "key": "l ",
-          "p1": "6c",
+          "key": "l",
+          "p5": "6c",
           "position": "318"
         },
         "27": {
@@ -16382,10 +17041,9 @@
         },
         "2A": {
           "format": "left",
-          "key": "#NUM!",
+          "key": "glyph_shift",
+          "label": "glyph_shift",
           "notes": "left shift",
-          "p2": "shift",
-          "p8": "glyph_shift",
           "position": "400"
         },
         "2B": {
@@ -16397,39 +17055,39 @@
           "position": "290"
         },
         "2C": {
-          "key": "z \n y",
-          "p1": "7a",
-          "p9": "79",
+          "key": "zy",
+          "p5": "7a",
+          "p6": "79",
           "position": "410"
         },
         "2D": {
-          "key": "x ",
-          "p1": "78",
+          "key": "x",
+          "p5": "78",
           "position": "411"
         },
         "2E": {
-          "key": "c ",
-          "p1": "63",
+          "key": "c",
+          "p5": "63",
           "position": "412"
         },
         "2F": {
-          "key": "v ",
-          "p1": "76",
+          "key": "v",
+          "p5": "76",
           "position": "413"
         },
         "30": {
-          "key": "b ",
-          "p1": "62",
+          "key": "b",
+          "p5": "62",
           "position": "414"
         },
         "31": {
-          "key": "n ",
-          "p1": "6e",
+          "key": "n",
+          "p5": "6e",
           "position": "415"
         },
         "32": {
-          "key": "m ",
-          "p1": "6d",
+          "key": "m",
+          "p5": "6d",
           "position": "416"
         },
         "33": {
@@ -16458,20 +17116,11 @@
         },
         "36": {
           "format": "right",
-          "key": "#NUM!",
+          "key": "glyph_shift",
+          "label": "glyph_shift",
           "notes": "right shift",
-          "p2": "shift",
-          "p8": "glyph_shift",
           "position": "490"
         },
-        "37": {
-          "key": "* |\n& \\",
-          "p1": "2a",
-          "p3": "7c",
-          "p7": "26",
-          "p9": "5c",
-          "position": "409"
-        },
         "38": {
           "format": "left",
           "key": "alt",
@@ -16529,6 +17178,14 @@
           "label": "glyph_volume_up",
           "position": "19"
         },
+        "56": {
+          "key": "* |\n& \\",
+          "p1": "2a",
+          "p3": "7c",
+          "p7": "26",
+          "p9": "5c",
+          "position": "409"
+        },
         "73": {
           "position": "420"
         },
@@ -16603,85 +17260,85 @@
           "position": "0"
         },
         "02": {
-          "key": " ! \n 1 ~",
-          "p1": "21",
+          "key": " !\n 1 ~",
+          "p2": "21",
           "p8": "31",
           "p9": "007E",
           "position": "110"
         },
         "03": {
-          "key": " \" \n 2 \u02c7",
-          "p1": "22",
+          "key": " \"\n 2 \u02c7",
+          "p2": "22",
           "p8": "32",
           "p9": "02C7",
           "position": "111"
         },
         "04": {
-          "key": " # \n 3 ^",
-          "p1": "23",
+          "key": " #\n 3 ^",
+          "p2": "23",
           "p8": "33",
           "p9": "005E",
           "position": "112"
         },
         "05": {
-          "key": " $ \n 4 \u02d8",
-          "p1": "24",
+          "key": " $\n 4 \u02d8",
+          "p2": "24",
           "p8": "34",
           "p9": "02D8",
           "position": "113"
         },
         "06": {
-          "key": " % \n 5 \u02da",
-          "p1": "25",
+          "key": " %\n 5 \u02da",
+          "p2": "25",
           "p8": "35",
           "p9": "02DA",
           "position": "114"
         },
         "07": {
-          "key": " & \n 6 \u02db",
-          "p1": "26",
+          "key": " &\n 6 \u02db",
+          "p2": "26",
           "p8": "36",
           "p9": "02DB",
           "position": "115"
         },
         "08": {
-          "key": " / \n 7 `",
-          "p1": "002F",
+          "key": " /\n 7 `",
+          "p2": "002F",
           "p8": "37",
           "p9": "60",
           "position": "116"
         },
         "09": {
-          "key": " ( \n 8 \u02d9",
-          "p1": "28",
+          "key": " (\n 8 \u02d9",
+          "p2": "28",
           "p8": "38",
           "p9": "02D9",
           "position": "117"
         },
         "0A": {
-          "key": " ) \n 9 \u00b4",
-          "p1": "29",
+          "key": " )\n 9 \u00b4",
+          "p2": "29",
           "p8": "39",
           "p9": "00B4",
           "position": "118"
         },
         "0B": {
-          "key": " = \n 0 \u02dd",
-          "p1": "003D",
+          "key": " =\n 0 \u02dd",
+          "p2": "003D",
           "p8": "30",
           "p9": "02DD",
           "position": "119"
         },
         "0C": {
-          "key": " ? \n ' \u00a8",
-          "p1": "003F",
+          "key": " ?\n ' \u00a8",
+          "p2": "003F",
           "p8": "27",
           "p9": "00A8",
           "position": "120"
         },
         "0D": {
-          "key": " * \n + \u00b8",
-          "p1": "002A",
+          "key": " *\n + \u00b8",
+          "p2": "002A",
           "p8": "002B",
           "p9": "00B8",
           "position": "121"
@@ -16701,67 +17358,67 @@
           "position": "200"
         },
         "10": {
-          "key": " Q \n  \\",
-          "p1": "51",
+          "key": " q \\",
+          "p5": "71",
           "p9": "005C",
           "position": "210"
         },
         "11": {
-          "key": " W \n  |",
-          "p1": "57",
+          "key": " w |",
+          "p5": "77",
           "p9": "007C",
           "position": "211"
         },
         "12": {
-          "key": "E \n \u20ac",
-          "p1": "45",
+          "key": "e \u20ac",
+          "p5": "65",
           "p9": "20AC",
           "position": "212"
         },
         "13": {
-          "key": "R ",
-          "p1": "52",
+          "key": "r",
+          "p5": "72",
           "position": "213"
         },
         "14": {
-          "key": "T ",
-          "p1": "54",
+          "key": "t",
+          "p5": "74",
           "position": "214"
         },
         "15": {
-          "key": "Z ",
-          "p1": "005A",
+          "key": "z",
+          "p5": "7A",
           "position": "215"
         },
         "16": {
-          "key": "U ",
-          "p1": "55",
+          "key": "u",
+          "p5": "75",
           "position": "216"
         },
         "17": {
-          "key": "I ",
-          "p1": "49",
+          "key": "i",
+          "p5": "69",
           "position": "217"
         },
         "18": {
-          "key": "O ",
-          "p1": "004F",
+          "key": "o",
+          "p5": "6F",
           "position": "218"
         },
         "19": {
-          "key": "P ",
-          "p1": "50",
+          "key": "p",
+          "p5": "70",
           "position": "219"
         },
         "1A": {
-          "key": "\u0160 \n \u00f7",
-          "p1": "160",
+          "key": "\u0161 \u00f7",
+          "p5": "161",
           "p9": "00F7",
           "position": "220"
         },
         "1B": {
-          "key": "\u00d0 \n \u00d7",
-          "p1": "00D0",
+          "key": "\u0111 \u00d7",
+          "p5": "111",
           "p9": "00D7",
           "position": "221"
         },
@@ -16780,68 +17437,68 @@
           "position": "500"
         },
         "1E": {
-          "key": "A ",
-          "p1": "41",
+          "key": "a",
+          "p5": "61",
           "position": "310"
         },
         "1F": {
-          "key": "S ",
-          "p1": "53",
+          "key": "s",
+          "p5": "73",
           "position": "311"
         },
         "20": {
-          "key": "D ",
-          "p1": "44",
+          "key": "d",
+          "p5": "64",
           "position": "312"
         },
         "21": {
-          "key": "F \n [",
-          "p1": "46",
+          "key": "f [",
+          "p5": "66",
           "p9": "005B",
           "position": "313"
         },
         "22": {
-          "key": "G \n ]",
-          "p1": "47",
+          "key": "g ]",
+          "p5": "67",
           "p9": "005D",
           "position": "314"
         },
         "23": {
-          "key": "H ",
-          "p1": "48",
+          "key": "h",
+          "p5": "68",
           "position": "315"
         },
         "24": {
-          "key": "J ",
-          "p1": "004A",
+          "key": "j",
+          "p5": "6A",
           "position": "316"
         },
         "25": {
-          "key": "K \n \u0142",
-          "p1": "004B",
+          "key": "k \u0142",
+          "p5": "6B",
           "p9": "142",
           "position": "317"
         },
         "26": {
-          "key": "L \n \u0141",
-          "p1": "004C",
+          "key": "l \u0141",
+          "p5": "6C",
           "p9": "141",
           "position": "318"
         },
         "27": {
-          "key": "\u010c ",
-          "p1": "010C",
+          "key": "\u010d",
+          "p5": "10D",
           "position": "319"
         },
         "28": {
-          "key": "\u0106 \n \u00df",
-          "p1": "106",
+          "key": "\u0107 \u00df",
+          "p5": "107",
           "p9": "00DF",
           "position": "320"
         },
         "29": {
-          "key": " \u00a8 \n \u00b8",
-          "p1": "00A8",
+          "key": " \u00a8\n \u00b8",
+          "p2": "00A8",
           "p8": "00B8",
           "position": "100"
         },
@@ -16853,66 +17510,66 @@
           "position": "400"
         },
         "2B": {
-          "key": "\u017d \n \u00a4",
-          "p1": "017D",
+          "key": "\u017e \u00a4",
+          "p5": "17E",
           "p9": "00A4",
           "position": "290"
         },
         "2C": {
-          "key": "Y ",
-          "p1": "59",
+          "key": "y",
+          "p5": "79",
           "position": "410"
         },
         "2D": {
-          "key": "X ",
-          "p1": "58",
+          "key": "x",
+          "p5": "78",
           "position": "411"
         },
         "2E": {
-          "key": "C ",
-          "p1": "43",
+          "key": "c",
+          "p5": "63",
           "position": "412"
         },
         "2F": {
-          "key": "V \n @",
-          "p1": "56",
+          "key": "v @",
+          "p5": "76",
           "p9": "40",
           "position": "413"
         },
         "30": {
-          "key": "B \n {",
-          "p1": "42",
+          "key": "b {",
+          "p5": "62",
           "p9": "007B",
           "position": "414"
         },
         "31": {
-          "key": "N \n }",
-          "p1": "004E",
+          "key": "n }",
+          "p5": "6E",
           "p9": "007D",
           "position": "415"
         },
         "32": {
-          "key": "M \n \u00a7",
-          "p1": "004D",
+          "key": "m \u00a7",
+          "p5": "6D",
           "p9": "00A7",
           "position": "416"
         },
         "33": {
-          "key": "; \n,",
-          "p1": "003B",
+          "key": ";\n,",
+          "p2": "003B",
           "p8": "002C",
           "position": "417"
         },
         "34": {
-          "key": ": \n.",
-          "p1": "003A",
+          "key": ":\n.",
+          "p2": "003A",
           "p8": "002E",
           "position": "418"
         },
         "35": {
-          "key": "_ \n -",
-          "p1": "005F",
-          "p9": "002D",
+          "key": "_\n-",
+          "p2": "005F",
+          "p8": "002D",
           "position": "419"
         },
         "36": {
@@ -16922,12 +17579,6 @@
           "notes": "right shift",
           "position": "490"
         },
-        "37": {
-          "key": "> \n<",
-          "p1": "003E",
-          "p8": "003C",
-          "position": "409"
-        },
         "38": {
           "format": "left",
           "key": "alt",
@@ -16985,6 +17636,12 @@
           "label": "glyph_volume_up",
           "position": "19"
         },
+        "56": {
+          "key": ">\n<",
+          "p2": "003E",
+          "p8": "003C",
+          "position": "409"
+        },
         "73": {
           "position": "420"
         },
@@ -17009,8 +17666,8 @@
         },
         "E0 38": {
           "format": "smaller",
-          "key": "alt",
-          "label": "alt",
+          "key": "alt gr",
+          "label": "alt gr",
           "notes": "right alt",
           "position": "580"
         },
@@ -17060,318 +17717,319 @@
           "position": "0"
         },
         "02": {
-          "key": " ! \n 1 ~",
-          "p1": "21",
+          "key": " !\n 1 ~",
+          "p2": "21",
           "p8": "31",
           "p9": "007E",
           "position": "110"
         },
         "03": {
-          "key": " \" \n 2",
-          "p1": "22",
+          "key": " \"\n 2",
+          "p2": "22",
           "p8": "32",
           "position": "111"
         },
         "04": {
-          "key": " # \n 3 ^",
-          "p1": "23",
+          "key": " #\n 3 ^",
+          "p2": "23",
           "p8": "33",
           "p9": "005E",
           "position": "112"
         },
         "05": {
-          "key": " $ \n 4",
-          "p1": "24",
+          "key": " $\n 4",
+          "p2": "24",
           "p8": "34",
           "position": "113"
         },
         "06": {
-          "key": " % \n 5",
-          "p1": "25",
+          "key": " %\n 5",
+          "p2": "25",
           "p8": "35",
           "position": "114"
         },
         "07": {
-          "key": " & \n 6",
-          "p1": "26",
+          "key": " &\n 6",
+          "p2": "26",
           "p8": "36",
           "position": "115"
         },
         "08": {
-          "key": " ' \n 7 `",
-          "p1": "27",
+          "key": " '\n 7 `",
+          "p2": "27",
           "p8": "37",
           "p9": "60",
           "position": "116"
         },
         "09": {
-          "key": " ( \n 8",
-          "p1": "28",
+          "key": " (\n 8",
+          "p2": "28",
           "p8": "38",
           "position": "117"
         },
         "0A": {
-          "key": " ) \n 9",
-          "p1": "29",
+          "key": " )\n 9",
+          "p2": "29",
           "p8": "39",
           "position": "118"
         },
         "0B": {
-          "key": " = \n 0",
-          "p1": "003D",
+          "key": " =\n 0",
+          "p2": "003D",
           "p8": "30",
           "position": "119"
         },
         "0C": {
-          "key": " ? \n '",
-          "p1": "003F",
+          "key": " ?\n '",
+          "p2": "003F",
           "p8": "27",
           "position": "120"
         },
         "0D": {
-          "key": " * \n +",
-          "p1": "002A",
+          "key": " *\n +",
+          "p2": "002A",
           "p8": "002B",
           "position": "121"
         },
         "0E": {
           "format": "right",
-          "key": "glyph_backspace",
+          "key": " glyph_backspace",
           "label": "glyph_backspace",
           "notes": "backspace",
           "position": "190"
         },
         "0F": {
           "format": "left",
-          "key": "glyph_tab",
+          "key": " glyph_tab",
           "label": "glyph_tab",
           "notes": "tab",
           "position": "200"
         },
         "10": {
-          "key": "\u0459 \n \\",
-          "p1": "459",
-          "p9": "005C",
+          "key": " q\u0459",
+          "p4": "71",
+          "p6": "459",
           "position": "210"
         },
         "11": {
-          "key": "\u045a \n |",
-          "p1": "045A",
-          "p9": "007C",
+          "key": " w\u045a",
+          "p4": "77",
+          "p6": "045A",
           "position": "211"
         },
         "12": {
-          "key": "\u0435 ",
-          "p1": "435",
+          "key": " e",
+          "p5": "65",
           "position": "212"
         },
         "13": {
-          "key": "\u0440 ",
-          "p1": "440",
+          "key": " r",
+          "p5": "72",
           "position": "213"
         },
         "14": {
-          "key": "\u0442 ",
-          "p1": "442",
+          "key": " t",
+          "p5": "74",
           "position": "214"
         },
         "15": {
-          "key": "\u0437 ",
-          "p1": "437",
+          "key": " z",
+          "p5": "7A",
           "position": "215"
         },
         "16": {
-          "key": "\u0443 ",
-          "p1": "443",
+          "key": " u",
+          "p5": "75",
           "position": "216"
         },
         "17": {
-          "key": "\u0438 ",
-          "p1": "438",
+          "key": " i",
+          "p5": "69",
           "position": "217"
         },
         "18": {
-          "key": "\u043e ",
-          "p1": "043E",
+          "key": " o",
+          "p5": "6F",
           "position": "218"
         },
         "19": {
-          "key": "\u043f ",
-          "p1": "043F",
+          "key": " p",
+          "p5": "70",
           "position": "219"
         },
         "1A": {
-          "key": "\u0448 ",
-          "p1": "448",
+          "key": " \u0161\u0448",
+          "p4": "161",
+          "p6": "448",
           "position": "220"
         },
         "1B": {
-          "key": "\u0442 ",
-          "p1": "442",
+          "key": " \u0111\u0442",
+          "p4": "111",
+          "p6": "442",
           "position": "221"
         },
         "1C": {
           "format": "right",
-          "key": "glyph_enter",
+          "key": " glyph_enter",
           "label": "glyph_enter",
           "notes": "enter",
           "position": "390"
         },
         "1D": {
           "format": "left",
-          "key": "\u043a\u043d\u0442\u0440",
+          "key": " \u043a\u043d\u0442\u0440",
           "label": "\u043a\u043d\u0442\u0440",
           "notes": "left ctrl",
           "position": "500"
         },
         "1E": {
-          "key": "\u0430 ",
-          "p1": "430",
+          "key": " a",
+          "p5": "61",
           "position": "310"
         },
         "1F": {
-          "key": "\u0441 ",
-          "p1": "441",
+          "key": " s",
+          "p5": "73",
           "position": "311"
         },
         "20": {
-          "key": "\u0434 ",
-          "p1": "434",
+          "key": " d",
+          "p5": "64",
           "position": "312"
         },
         "21": {
-          "key": "\u0444 \n [",
-          "p1": "444",
+          "key": " f [",
+          "p5": "66",
           "p9": "005B",
           "position": "313"
         },
         "22": {
-          "key": "\u0433 \n ]",
-          "p1": "433",
+          "key": " g ]",
+          "p5": "67",
           "p9": "005D",
           "position": "314"
         },
         "23": {
-          "key": "\u0445 ",
-          "p1": "445",
+          "key": " h",
+          "p5": "68",
           "position": "315"
         },
         "24": {
-          "key": "\u0458 ",
-          "p1": "458",
+          "key": " j",
+          "p5": "6A",
           "position": "316"
         },
         "25": {
-          "key": "\u043a ",
-          "p1": "043A",
+          "key": " k",
+          "p5": "6B",
           "position": "317"
         },
         "26": {
-          "key": "\u043b ",
-          "p1": "043B",
+          "key": " l",
+          "p5": "6C",
           "position": "318"
         },
         "27": {
-          "key": "\u0447 ",
-          "p1": "447",
+          "key": " \u010d\u0447",
+          "p4": "10D",
+          "p6": "447",
           "position": "319"
         },
         "28": {
-          "key": "\u045b ",
-          "p1": "045B",
+          "key": " \u0107\u045b",
+          "p4": "107",
+          "p6": "045B",
           "position": "320"
         },
         "29": {
-          "key": " | \n \\",
-          "p1": "007C",
+          "key": " |\n \\",
+          "p2": "007C",
           "p8": "005C",
           "position": "100"
         },
         "2A": {
           "format": "left",
-          "key": "glyph_shift",
+          "key": " glyph_shift",
           "label": "glyph_shift",
           "notes": "left shift",
           "position": "400"
         },
         "2B": {
-          "key": "\u0436 ",
-          "p1": "436",
+          "key": " \u017e\u0436",
+          "p4": "17E",
+          "p6": "436",
           "position": "290"
         },
         "2C": {
-          "key": "\u0455 ",
-          "p1": "455",
+          "key": " y",
+          "p5": "79",
           "position": "410"
         },
         "2D": {
-          "key": "\u045f ",
-          "p1": "045F",
+          "key": " x\u045f",
+          "p4": "78",
+          "p6": "045F",
           "position": "411"
         },
         "2E": {
-          "key": "\u0446 ",
-          "p1": "446",
+          "key": " c\u0446",
+          "p4": "63",
+          "p6": "446",
           "position": "412"
         },
         "2F": {
-          "key": "\u0432 \n @",
-          "p1": "432",
+          "key": " v @",
+          "p5": "76",
           "p9": "40",
           "position": "413"
         },
         "30": {
-          "key": "\u0431 \n {",
-          "p1": "431",
+          "key": " b {",
+          "p5": "62",
           "p9": "007B",
           "position": "414"
         },
         "31": {
-          "key": "\u043d \n }",
-          "p1": "043D",
+          "key": " n }",
+          "p5": "6E",
           "p9": "007D",
           "position": "415"
         },
         "32": {
-          "key": "\u043c \n \u00a7",
-          "p1": "043C",
+          "key": " m \u00a7",
+          "p5": "6D",
           "p9": "00A7",
           "position": "416"
         },
         "33": {
-          "key": "; \n,",
-          "p1": "003B",
+          "key": " ;\n ,",
+          "p2": "003B",
           "p8": "002C",
           "position": "417"
         },
         "34": {
-          "key": ": \n.",
-          "p1": "003A",
+          "key": " :\n .",
+          "p2": "003A",
           "p8": "002E",
           "position": "418"
         },
         "35": {
-          "key": "_ \n-",
-          "p1": "005F",
+          "key": " _\n -",
+          "p2": "005F",
           "p8": "002D",
           "position": "419"
         },
         "36": {
           "format": "right",
-          "key": "glyph_shift",
+          "key": " glyph_shift",
           "label": "glyph_shift",
           "notes": "right shift",
           "position": "490"
         },
-        "37": {
-          "key": "> \n<",
-          "p1": "003E",
-          "p8": "003C",
-          "position": "409"
-        },
         "38": {
           "format": "left",
-          "key": "\u0430\u043b\u0442",
+          "key": " \u0430\u043b\u0442",
           "label": "\u0430\u043b\u0442",
           "notes": "left alt",
           "position": "501"
@@ -17426,15 +18084,24 @@
           "label": "glyph_volume_up",
           "position": "19"
         },
+        "56": {
+          "key": " >\n <",
+          "p2": "003E",
+          "p8": "003C",
+          "position": "409"
+        },
         "73": {
+          "key": " ",
           "position": "420"
         },
         "79": {
           "format": "smaller",
+          "key": " ",
           "position": "551"
         },
         "7B": {
           "format": "smaller",
+          "key": " ",
           "position": "550"
         },
         "7D": {
@@ -17443,14 +18110,14 @@
         },
         "E0 1D": {
           "format": "smaller",
-          "key": "\u043a\u043d\u0442\u0440",
+          "key": " \u043a\u043d\u0442\u0440",
           "label": "\u043a\u043d\u0442\u0440",
           "notes": "right ctrl",
           "position": "581"
         },
         "E0 38": {
           "format": "smaller",
-          "key": "\u0430\u043b\u0442",
+          "key": " \u0430\u043b\u0442",
           "label": "\u0430\u043b\u0442",
           "notes": "right alt",
           "position": "580"
@@ -17477,7 +18144,7 @@
         },
         "E0 5B": {
           "format": "left",
-          "key": "glyph_search",
+          "key": " glyph_search",
           "label": "glyph_search",
           "notes": "search",
           "position": "300"
@@ -18904,176 +19571,176 @@
           "position": "0"
         },
         "02": {
-          "key": "! \n1 \u2013",
-          "p1": "21",
-          "p7": "31",
+          "key": "!\n1 \u2013",
+          "p2": "21",
+          "p8": "31",
           "p9": "2013",
           "position": "110"
         },
         "03": {
-          "key": "@ \n2 \"",
-          "p1": "40",
-          "p7": "32",
+          "key": "@\n2 \"",
+          "p2": "40",
+          "p8": "32",
           "p9": "22",
           "position": "111"
         },
         "04": {
-          "key": "\u2116 \n3 \u20ac",
-          "p1": "2116",
-          "p7": "33",
+          "key": "\u2116\n3 \u20ac",
+          "p2": "2116",
+          "p8": "33",
           "p9": "20AC",
           "position": "112"
         },
         "05": {
-          "key": "; \n4 $",
-          "p1": "003B",
-          "p7": "34",
+          "key": ";\n4 $",
+          "p2": "003B",
+          "p8": "34",
           "p9": "24",
           "position": "113"
         },
         "06": {
-          "key": "% \n5 \u00ba",
-          "p1": "25",
-          "p7": "35",
+          "key": "%\n5 \u00ba",
+          "p2": "25",
+          "p8": "35",
           "p9": "00BA",
           "position": "114"
         },
         "07": {
-          "key": ": \n6 ",
-          "p1": "003A",
-          "p7": "36",
+          "key": ":\n6",
+          "p2": "003A",
+          "p8": "36",
           "position": "115"
         },
         "08": {
-          "key": "? \n7 ",
-          "p1": "003F",
-          "p7": "37",
+          "key": "?\n7",
+          "p2": "003F",
+          "p8": "37",
           "position": "116"
         },
         "09": {
-          "key": "* \n8 \u00a7",
-          "p1": "002A",
-          "p7": "38",
+          "key": "*\n8 \u00a7",
+          "p2": "002A",
+          "p8": "38",
           "p9": "00A7",
           "position": "117"
         },
         "0A": {
-          "key": "( \n9 ",
-          "p1": "28",
-          "p7": "39",
+          "key": "(\n9",
+          "p2": "28",
+          "p8": "39",
           "position": "118"
         },
         "0B": {
-          "key": ") \n0 ",
-          "p1": "29",
-          "p7": "30",
+          "key": ")\n0",
+          "p2": "29",
+          "p8": "30",
           "position": "119"
         },
         "0C": {
-          "key": "_ \n- [",
-          "p1": "005F",
-          "p7": "002D",
+          "key": "_\n- [",
+          "p2": "005F",
+          "p8": "002D",
           "p9": "005B",
           "position": "120"
         },
         "0D": {
-          "key": "+ \n= ]",
-          "p1": "002B",
-          "p7": "003D",
+          "key": "+\n= ]",
+          "p2": "002B",
+          "p8": "003D",
           "p9": "005D",
           "position": "121"
         },
         "0E": {
           "format": "right",
-          "key": "backspace",
-          "label": "backspace",
+          "key": "glyph_backspace",
+          "label": "glyph_backspace",
           "notes": "backspace",
           "position": "190"
         },
         "0F": {
           "format": "left",
-          "key": "tab",
-          "label": "tab",
+          "key": "glyph_tab",
+          "label": "glyph_tab",
           "notes": "tab",
           "position": "200"
         },
         "10": {
-          "key": "q \n \u0439",
-          "p1": "71",
+          "key": "q \u0439",
+          "p5": "71",
           "p9": "439",
           "position": "210"
         },
         "11": {
-          "key": "w \n \u0446",
-          "p1": "77",
+          "key": "w \u0446",
+          "p5": "77",
           "p9": "446",
           "position": "211"
         },
         "12": {
-          "key": "e \n \u0443",
-          "p1": "65",
+          "key": "e \u0443",
+          "p5": "65",
           "p9": "443",
           "position": "212"
         },
         "13": {
-          "key": "r \n \u043a",
-          "p1": "72",
+          "key": "r \u043a",
+          "p5": "72",
           "p9": "043A",
           "position": "213"
         },
         "14": {
-          "key": "t \n \u0435",
-          "p1": "74",
+          "key": "t \u0435",
+          "p5": "74",
           "p9": "435",
           "position": "214"
         },
         "15": {
-          "key": "y \n \u043d",
-          "p1": "79",
+          "key": "y \u043d",
+          "p5": "79",
           "p9": "043D",
           "position": "215"
         },
         "16": {
-          "key": "u \n \u0433",
-          "p1": "75",
+          "key": "u \u0433",
+          "p5": "75",
           "p9": "433",
           "position": "216"
         },
         "17": {
-          "key": "i \n \u0448",
-          "p1": "69",
+          "key": "i \u0448",
+          "p5": "69",
           "p9": "448",
           "position": "217"
         },
         "18": {
-          "key": "o \n \u0449",
-          "p1": "006F",
+          "key": "o \u0449",
+          "p5": "006F",
           "p9": "449",
           "position": "218"
         },
         "19": {
-          "key": "p \n \u0437",
-          "p1": "70",
+          "key": "p \u0437",
+          "p5": "70",
           "p9": "437",
           "position": "219"
         },
         "1A": {
-          "key": "{ \n\u0445 ",
-          "p1": "007B",
-          "p7": "445",
+          "key": "{\n\u0445",
+          "p2": "007B",
+          "p8": "445",
           "position": "220"
         },
         "1B": {
-          "key": "} \n\u044a \u0457",
-          "p1": "007D",
-          "p7": "044A",
+          "key": "}\n\u044a \u0457",
+          "p2": "007D",
+          "p8": "044A",
           "p9": "457",
           "position": "221"
         },
         "1C": {
           "format": "right",
-          "key": "enter",
-          "label": "enter",
+          "key": "glyph_enter",
+          "label": "glyph_enter",
           "notes": "enter",
           "position": "390"
         },
@@ -19085,64 +19752,64 @@
           "position": "500"
         },
         "1E": {
-          "key": "a \n \u0444",
-          "p1": "61",
+          "key": "a \u0444",
+          "p5": "61",
           "p9": "444",
           "position": "310"
         },
         "1F": {
-          "key": "s \n\u044b \u0456",
-          "p1": "73",
-          "p7": "044B",
+          "key": "s\n\u044b \u0456",
+          "p2": "73",
+          "p8": "044B",
           "p9": "456",
           "position": "311"
         },
         "20": {
-          "key": "d \n \u0432",
-          "p1": "64",
+          "key": "d \u0432",
+          "p5": "64",
           "p9": "432",
           "position": "312"
         },
         "21": {
-          "key": "f \n \u0430",
-          "p1": "66",
+          "key": "f \u0430",
+          "p5": "66",
           "p9": "430",
           "position": "313"
         },
         "22": {
-          "key": "g \n \u043f",
-          "p1": "67",
+          "key": "g \u043f",
+          "p5": "67",
           "p9": "043F",
           "position": "314"
         },
         "23": {
-          "key": "h \n \u0440",
-          "p1": "68",
+          "key": "h \u0440",
+          "p5": "68",
           "p9": "440",
           "position": "315"
         },
         "24": {
-          "key": "j \n \u043e",
-          "p1": "006A",
+          "key": "j \u043e",
+          "p5": "006A",
           "p9": "043E",
           "position": "316"
         },
         "25": {
-          "key": "k \n \u043b",
-          "p1": "006B",
+          "key": "k \u043b",
+          "p5": "006B",
           "p9": "043B",
           "position": "317"
         },
         "26": {
-          "key": "l \n \u0434",
-          "p1": "006C",
+          "key": "l \u0434",
+          "p5": "006C",
           "p9": "434",
           "position": "318"
         },
         "27": {
-          "key": ": \n; \u0436",
-          "p1": "003A",
-          "p7": "003B",
+          "key": ":\n; \u0436",
+          "p2": "003A",
+          "p8": "003B",
           "p9": "436",
           "position": "319"
         },
@@ -19155,16 +19822,16 @@
           "position": "320"
         },
         "29": {
-          "key": "\u0491 \n' \u20b4",
-          "p1": "491",
-          "p7": "27",
+          "key": "\u0491\n' \u20b4",
+          "p2": "491",
+          "p8": "27",
           "p9": "20B4",
           "position": "100"
         },
         "2A": {
           "format": "left",
-          "key": "shift",
-          "label": "shift",
+          "key": "glyph_shift",
+          "label": "glyph_shift",
           "notes": "left shift",
           "position": "400"
         },
@@ -19177,57 +19844,57 @@
           "position": "290"
         },
         "2C": {
-          "key": "z \n \u044f",
-          "p1": "007A",
+          "key": "z \u044f",
+          "p5": "007A",
           "p9": "044F",
           "position": "410"
         },
         "2D": {
-          "key": "x \n \u0447",
-          "p1": "78",
+          "key": "x \u0447",
+          "p5": "78",
           "p9": "447",
           "position": "411"
         },
         "2E": {
-          "key": "c \n \u0441",
-          "p1": "63",
+          "key": "c \u0441",
+          "p5": "63",
           "p9": "441",
           "position": "412"
         },
         "2F": {
-          "key": "v \n \u043c",
-          "p1": "76",
+          "key": "v \u043c",
+          "p5": "76",
           "p9": "043C",
           "position": "413"
         },
         "30": {
-          "key": "b \n \u0438",
-          "p1": "62",
+          "key": "b \u0438",
+          "p5": "62",
           "p9": "438",
           "position": "414"
         },
         "31": {
-          "key": "n \n \u0442",
-          "p1": "006E",
+          "key": "n \u0442",
+          "p5": "006E",
           "p9": "442",
           "position": "415"
         },
         "32": {
-          "key": "m \n \u044c",
-          "p1": "006D",
+          "key": "m \u044c",
+          "p5": "006D",
           "p9": "044C",
           "position": "416"
         },
         "33": {
-          "key": "< \n, \u0431",
-          "p1": "003C",
+          "key": "<\n, \u0431",
+          "p2": "003C",
           "p8": "002C",
           "p9": "431",
           "position": "417"
         },
         "34": {
-          "key": "> \n. \u044e",
-          "p1": "003E",
+          "key": ">\n. \u044e",
+          "p2": "003E",
           "p8": "002E",
           "p9": "044E",
           "position": "418"
@@ -19242,8 +19909,8 @@
         },
         "36": {
           "format": "right",
-          "key": "shift",
-          "label": "shift",
+          "key": "glyph_shift",
+          "label": "glyph_shift",
           "notes": "right shift",
           "position": "490"
         },
@@ -19330,8 +19997,8 @@
         },
         "E0 38": {
           "format": "smaller",
-          "key": "alt",
-          "label": "alt",
+          "key": "alt gr",
+          "label": "alt gr",
           "notes": "right alt",
           "position": "580"
         },
diff --git a/chrome/browser/resources/login.html b/chrome/browser/resources/login.html
index 4238a25..6056a5a 100644
--- a/chrome/browser/resources/login.html
+++ b/chrome/browser/resources/login.html
@@ -28,16 +28,14 @@
       <a id="login-incognito" onclick="callLoginIncognito();">
         Browse without signing in
       </a>
+      <a id="shutdown-system" onclick="callShutdownSystem();">
+        Shutdown System
+      </a>
     </div>
   </div>
 </body>
 
 <script>
-function callLoginIncognito() {
-  loginStarted();
-  chrome.send('LaunchIncognito', []);
-}
-
 function callLogin() {
   var user = document.getElementById('user-text').value;
   var pass = document.getElementById('pass-text').value;
@@ -56,8 +54,19 @@
 function setLock(on) {
   document.getElementById('login-button').disabled = on;
   document.getElementById('login-incognito').disabled = on;
+  document.getElementById('shutdown-system').disabled = on;
   document.getElementById('user-text').disabled = on;
   document.getElementById('pass-text').disabled = on;
 }
+
+function callLoginIncognito() {
+  loginStarted();
+  chrome.send('LaunchIncognito', []);
+}
+
+function callShutdownSystem() {
+  chrome.send('ShutdownSystem', []);
+}
+
 </script>
 </html>
diff --git a/chrome/browser/resources/menu.js b/chrome/browser/resources/menu.js
index 8328db5..68fc48e 100644
--- a/chrome/browser/resources/menu.js
+++ b/chrome/browser/resources/menu.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
 var localStrings = new LocalStrings();
 
 /**
- * Sends 'activate' DOMUI message.
+ * Sends 'activate' WebUI message.
  * @param {number} index The index of menu item to activate in menu model.
  * @param {string} mode The activation mode, one of 'close_and_activate', or
  *    'activate_no_close'.
@@ -48,7 +48,7 @@
    *    will be added to.
    * @param {Object} attrs JSON object that represents this menu items
    *    properties.  This is created from menu model in C code.  See
-   *    chromeos/views/native_menu_domui.cc.
+   *    chromeos/views/native_menu_webui.cc.
    * @param {Object} model The model object.
    */
   init: function(menu, attrs, model) {
@@ -105,7 +105,7 @@
   },
 
   /**
-   * Sends open_submenu DOMUI message.
+   * Sends open_submenu WebUI message.
    */
   sendOpenSubmenuCommand: function() {
     chrome.send('open_submenu',
@@ -252,7 +252,7 @@
   /**
    * Initialize the menu.
    * @param {Object} config Configuration parameters in JSON format.
-   *  See chromeos/views/native_menu_domui.cc for details.
+   *  See chromeos/views/native_menu_webui.cc for details.
    */
   init: function(config) {
     // List of menu items
diff --git a/chrome/browser/resources/mobile_app/manifest.json b/chrome/browser/resources/mobile_app/manifest.json
new file mode 100644
index 0000000..22caa8a
--- /dev/null
+++ b/chrome/browser/resources/mobile_app/manifest.json
@@ -0,0 +1,9 @@
+{
+  "key": "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDITTAJ8zmgRjcmCRIAUbzlrSSzoWPBRY/kaBP3mxZ8nlCMljhQLDDKClnyGK6+krYq8/LayF4r0PR7g0Q27lwvw+asg1BFN+AL+suJqe4jJzxBK3GaMBRsBCCcwpAQw4F82zI9Hk0e6EqfrDq4ePNgv+PsI2MDbOuk3b1vS5oBjQIBIw==",
+  "name": "Mobile Activation",
+  "version": "1.0",
+  "description": "Chrome OS Mobile Activation Resources",
+  "default_locale": "en",
+  "incognito": "split",
+  "permissions": []
+}
diff --git a/chrome/browser/resources/mobile_setup.html b/chrome/browser/resources/mobile_setup.html
index adf555a..2424531 100644
--- a/chrome/browser/resources/mobile_setup.html
+++ b/chrome/browser/resources/mobile_setup.html
@@ -58,7 +58,7 @@
 }
 
 .logo {
-  background: url('file:///usr/share/chromeos-assets/mobile/carrier_logo.png') no-repeat;
+  background: url('chrome-extension://iadeocfgjdjdmpenejdbfeaocpbikmab/carrier_logo.png') no-repeat;
   background-position: 85% 50%;
   height: 58px;
   margin-bottom: 20px;
@@ -67,8 +67,6 @@
 
 .splitter {
   margin-top: 10px;
-  left: 50%;
-  width: 600px;
   border-bottom: 1px solid #EEE;
   height: 1px;
 }
@@ -178,19 +176,19 @@
           </tr>
         </tbody></table>
       </div>
-      <div id="errorMessage" class="hidden"></div>
-      <iframe id="carrierPage" frameborder="0"></iframe>
+      <iframe src="chrome-extension://iadeocfgjdjdmpenejdbfeaocpbikmab/activation.html"
+          id="carrierPage" frameborder="0"></iframe>
     </div>
   </div>
-  <div id="finalMessage" class="overlay hidden">
+  <div id="finalStatus" class="overlay hidden">
     <div class="startup">
-      <div class="header"><h3 i18n-content="completed_header"></h3></div>
-      <div i18n-content="completed_text"></div>
+      <div class="header"><h3 id="finalHeader"></h3></div>
+      <div id="finalMessage"></div>
       <div class="splitter"></div>
       <div class="logo"></div>
       <div class="action-area button-strip">
         <button id="closeButton"
-                i18n-content="close_button"></button>
+                i18n-content="close_button" class="hidden"></button>
       </div>
     </div>
   </div>
diff --git a/chrome/browser/resources/mobile_setup.js b/chrome/browser/resources/mobile_setup.js
index 25032a5..b53b75c 100644
--- a/chrome/browser/resources/mobile_setup.js
+++ b/chrome/browser/resources/mobile_setup.js
@@ -10,16 +10,22 @@
 
   cr.addSingletonGetter(MobileSetup);
 
-  MobileSetup.PLAN_ACTIVATION_LOADING = -1;
-  MobileSetup.PLAN_ACTIVATION_START = 0;
-  MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION = 1;
-  MobileSetup.PLAN_ACTIVATION_RECONNECTING = 2;
-  MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT = 3;
-  MobileSetup.PLAN_ACTIVATION_DONE = 4;
-  MobileSetup.PLAN_ACTIVATION_ERROR = 5;
+  MobileSetup.PLAN_ACTIVATION_PAGE_LOADING            = -1;
+  MobileSetup.PLAN_ACTIVATION_START                   = 0;
+  MobileSetup.PLAN_ACTIVATION_TRYING_OTASP            = 1;
+  MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP_TRY  = 2;
+  MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION   = 3;
+  MobileSetup.PLAN_ACTIVATION_RECONNECTING            = 4;
+  MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT         = 5;
+  MobileSetup.PLAN_ACTIVATION_DELAY_OTASP             = 6;
+  MobileSetup.PLAN_ACTIVATION_START_OTASP             = 7;
+  MobileSetup.PLAN_ACTIVATION_OTASP                   = 8;
+  MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP      = 9;
+  MobileSetup.PLAN_ACTIVATION_DONE                    = 10;
+  MobileSetup.PLAN_ACTIVATION_ERROR                   = 0xFF;
 
   MobileSetup.ACTIVATION_PAGE_URL =
-    'file:///usr/share/chromeos-assets/mobile/activation.html';
+    'chrome-extension://iadeocfgjdjdmpenejdbfeaocpbikmab/activation.html';
 
   MobileSetup.localStrings_ = new LocalStrings();
 
@@ -29,6 +35,7 @@
     frameName_ : '',
     initialized_ : false,
     faked_transaction_ : false,
+    payment_shown_ : false,
     // UI states.
     state_ : -1,
     STATE_UNKNOWN_: "unknown",
@@ -50,18 +57,15 @@
           self.onMessageReceived_(e);
       });
       $('closeButton').addEventListener('click', function(e) {
-          $('finalMessage').classList.add('hidden');
+          $('finalStatus').classList.add('hidden');
       });
-      $('carrierPage').contentWindow.location.href =
-          carrierPage;
       $(frame_name).addEventListener('load', function(e) {
         // Flip the visibility of the payment page only after the frame is
         // fully loaded.
         if (self.state_ == MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT) {
           $('statusHeader').textContent = '';
           $('auxHeader').textContent = '';
-          $('finalMessage').classList.add('hidden');
-          $('errorMessage').classList.add('hidden');
+          $('finalStatus').classList.add('hidden');
           $('systemStatus').classList.add('hidden');
           $('canvas').classList.add('hidden');
           $('carrierPage').classList.add('hidden');
@@ -69,7 +73,7 @@
         }
       });
 
-      this.changeState_(MobileSetup.PLAN_ACTIVATION_LOADING);
+      this.changeState_({state: MobileSetup.PLAN_ACTIVATION_PAGE_LOADING});
       setInterval(mobile.MobileSetup.drawProgress, 100);
       // Kick off activation process.
       chrome.send('startActivation', []);
@@ -105,30 +109,32 @@
       var main = $('mainbody');
       // Map handler state to UX.
       switch(new_state) {
-        case MobileSetup.PLAN_ACTIVATION_LOADING:
+        case MobileSetup.PLAN_ACTIVATION_PAGE_LOADING:
         case MobileSetup.PLAN_ACTIVATION_START:
+        case MobileSetup.PLAN_ACTIVATION_DELAY_OTASP:
+        case MobileSetup.PLAN_ACTIVATION_START_OTASP:
         case MobileSetup.PLAN_ACTIVATION_RECONNECTING:
+        case MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
+        case MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP:
           $('statusHeader').textContent =
               MobileSetup.localStrings_.getString('connecting_header');
           $('auxHeader').textContent =
               MobileSetup.localStrings_.getString('please_wait');
-          $('errorMessage').textContent = '';
           $('paymentForm').classList.add('hidden');
-          $('finalMessage').classList.add('hidden');
-          $('errorMessage').classList.add('hidden');
+          $('finalStatus').classList.add('hidden');
           $('systemStatus').classList.remove('hidden');
           $('canvas').classList.remove('hidden');
           $('carrierPage').classList.remove('hidden');
           break;
+        case MobileSetup.PLAN_ACTIVATION_TRYING_OTASP:
         case MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION:
+        case MobileSetup.PLAN_ACTIVATION_OTASP:
           $('statusHeader').textContent =
               MobileSetup.localStrings_.getString('activating_header');
           $('auxHeader').textContent =
               MobileSetup.localStrings_.getString('please_wait');
-          $('errorMessage').textContent = '';
           $('paymentForm').classList.add('hidden');
-          $('finalMessage').classList.add('hidden');
-          $('errorMessage').classList.add('hidden');
+          $('finalStatus').classList.add('hidden');
           $('systemStatus').classList.remove('hidden');
           $('canvas').classList.remove('hidden');
           $('carrierPage').classList.remove('hidden');
@@ -138,33 +144,45 @@
               MobileSetup.localStrings_.getString('connecting_header');
           $('auxHeader').textContent = '';
           $('paymentForm').classList.add('hidden');
-          $('finalMessage').classList.add('hidden');
-          $('errorMessage').classList.add('hidden');
+          $('finalStatus').classList.add('hidden');
           $('systemStatus').classList.remove('hidden');
           $('canvas').classList.remove('hidden');
           this.loadPaymentFrame_(deviceInfo);
+          this.payment_shown_ = true;
           break;
         case MobileSetup.PLAN_ACTIVATION_DONE:
           $('statusHeader').textContent = '';
           $('auxHeader').textContent = '';
-          $('errorMessage').classList.add('hidden');
+          $('finalHeader').textContent =
+              MobileSetup.localStrings_.getString('completed_header');
+          $('finalMessage').textContent =
+              MobileSetup.localStrings_.getString('completed_text');
           $('systemStatus').classList.add('hidden');
           $('canvas').classList.add('hidden');
           $('carrierPage').classList.add('hidden');
           $('paymentForm').classList.remove('hidden');
-          $('finalMessage').classList.remove('hidden');
+          $('closeButton').classList.remove('hidden');
+          $('finalStatus').classList.remove('hidden');
+          if (this.payment_shown_)
+            $('closeButton').classList.remove('hidden');
+          else
+            $('closeButton').classList.add('hidden');
           break;
         case MobileSetup.PLAN_ACTIVATION_ERROR:
-          $('statusHeader').textContent =
-              MobileSetup.localStrings_.getString('error_header');
+          $('statusHeader').textContent = '';
           $('auxHeader').textContent = '';
-          $('errorMessage').textContent = deviceInfo.error;
-          $('paymentForm').classList.add('hidden');
-          $('finalMessage').classList.add('hidden');
-          $('carrierPage').classList.add('hidden');
+          $('finalHeader').textContent =
+              MobileSetup.localStrings_.getString('error_header');
+          $('finalMessage').textContent = deviceInfo.error;
+          $('systemStatus').classList.add('hidden');
           $('canvas').classList.add('hidden');
-          $('errorMessage').classList.remove('hidden');
-          $('systemStatus').classList.remove('hidden');
+          $('carrierPage').classList.add('hidden');
+          $('paymentForm').classList.remove('hidden');
+          if (this.payment_shown_)
+            $('closeButton').classList.remove('hidden');
+          else
+            $('closeButton').classList.add('hidden');
+          $('finalStatus').classList.remove('hidden');
           break;
       }
       this.state_ = new_state;
diff --git a/chrome/browser/resources/net_internals/dataview.js b/chrome/browser/resources/net_internals/dataview.js
index 2535303..7b7a47c 100644
--- a/chrome/browser/resources/net_internals/dataview.js
+++ b/chrome/browser/resources/net_internals/dataview.js
@@ -19,7 +19,12 @@
                   byteLoggingCheckboxId,
                   passivelyCapturedCountId,
                   activelyCapturedCountId,
-                  deleteAllId) {
+                  deleteAllId,
+                  dumpDataDivId,
+                  loadDataDivId,
+                  loadLogFileId,
+                  capturingTextSpanId,
+                  loggingTextSpanId) {
   DivView.call(this, mainBoxId);
 
   this.textPre_ = document.getElementById(outputTextBoxId);
@@ -40,6 +45,14 @@
   document.getElementById(deleteAllId).onclick =
       g_browser.deleteAllEvents.bind(g_browser);
 
+  this.dumpDataDiv_ = document.getElementById(dumpDataDivId);
+  this.loadDataDiv_ = document.getElementById(loadDataDivId);
+  this.capturingTextSpan_ = document.getElementById(capturingTextSpanId);
+  this.loggingTextSpan_ = document.getElementById(loggingTextSpanId);
+
+  document.getElementById(loadLogFileId).onclick =
+      g_browser.loadLogFile.bind(g_browser);
+
   this.updateEventCounts_();
   this.waitingForUpdate_ = false;
 
@@ -71,6 +84,18 @@
 };
 
 /**
+ * Called when either a log file is loaded or when going back to actively
+ * logging events.  In either case, called after clearing the old entries,
+ * but before getting any new ones.
+ */
+DataView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) {
+  setNodeDisplay(this.dumpDataDiv_, !isViewingLogFile);
+  setNodeDisplay(this.capturingTextSpan_, !isViewingLogFile);
+  setNodeDisplay(this.loggingTextSpan_, isViewingLogFile);
+  this.setText_('');
+};
+
+/**
  * Updates the counters showing how many events have been captured.
  */
 DataView.prototype.updateEventCounts_ = function() {
@@ -108,6 +133,10 @@
  * Presents the captured data as formatted text.
  */
 DataView.prototype.onUpdateAllCompleted = function(data) {
+  // It's possible for a log file to be loaded while a dump is being generated.
+  // When that happens, don't display the log dump, to avoid any confusion.
+  if (g_browser.isViewingLogFile())
+    return;
   this.waitingForUpdate_ = false;
   var text = [];
 
@@ -241,6 +270,20 @@
 
   text.push('');
   text.push('----------------------------------------------');
+  text.push(' SPDY Status');
+  text.push('----------------------------------------------');
+  text.push('');
+
+  text.push('SPDY Enabled: ' + data.spdyStatus.spdy_enabled);
+  text.push('Use Alternate Protocol: ' +
+      data.spdyStatus.use_alternate_protocols);
+  text.push('Force SPDY Always: ' + data.spdyStatus.force_spdy_always);
+  text.push('Force SPDY Over SSL: ' + data.spdyStatus.force_spdy_over_ssl);
+  text.push('Next Protocols: ' + data.spdyStatus.next_protos);
+
+
+  text.push('');
+  text.push('----------------------------------------------');
   text.push(' SPDY Sessions');
   text.push('----------------------------------------------');
   text.push('');
@@ -253,6 +296,22 @@
     text.push(spdyTablePrinter.toText(2));
   }
 
+  text.push('');
+  text.push('----------------------------------------------');
+  text.push(' Alternate Protocol Mappings');
+  text.push('----------------------------------------------');
+  text.push('');
+
+  if (data.spdyAlternateProtocolMappings == null ||
+      data.spdyAlternateProtocolMappings.length == 0) {
+    text.push('None');
+  } else {
+    var spdyTablePrinter =
+      SpdyView.createAlternateProtocolMappingsTablePrinter(
+          data.spdyAlternateProtocolMappings);
+    text.push(spdyTablePrinter.toText(2));
+  }
+
   if (g_browser.isPlatformWindows()) {
     text.push('');
     text.push('----------------------------------------------');
diff --git a/chrome/browser/resources/net_internals/eventsview.js b/chrome/browser/resources/net_internals/eventsview.js
index 7af86aa..d3768ed 100644
--- a/chrome/browser/resources/net_internals/eventsview.js
+++ b/chrome/browser/resources/net_internals/eventsview.js
@@ -475,10 +475,20 @@
 /**
  * Called whenever all log events are deleted.
  */
-EventsView.prototype.onAllLogEntriesDeleted = function(offset) {
+EventsView.prototype.onAllLogEntriesDeleted = function() {
   this.initializeSourceList_();
 };
 
+/**
+ * Called when either a log file is loaded or when going back to actively
+ * logging events.  In either case, called after clearing the old entries,
+ * but before getting any new ones.
+ */
+EventsView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) {
+  // Needed to sort new sourceless entries correctly.
+  this.maxReceivedSourceId_ = 0;
+};
+
 EventsView.prototype.incrementPrefilterCount = function(offset) {
   this.numPrefilter_ += offset;
   this.invalidateFilterCounter_();
diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html
index 732c4be..d67957c 100644
--- a/chrome/browser/resources/net_internals/index.html
+++ b/chrome/browser/resources/net_internals/index.html
@@ -147,6 +147,15 @@
       </p>
     </div>
     <div id=spdyTabContent>
+      <h4>SPDY Status</h4>
+      <ul>
+        <li>SPDY Enabled: <span id=spdyEnabledSpan>????</span></li>
+        <li>Use Alternate Protocol: <span id=spdyUseAlternateProtocolSpan>????</span></li>
+        <li>Force SPDY Always: <span id=spdyForceAlwaysSpan>????</span></li>
+        <li>Force SPDY Over SSL: <span id=spdyForceOverSslSpan>????</span></li>
+        <li>Next Protocols: <span id=spdyNextProtocolsSpan>????</span></li>
+      </ul>
+
       <h4>SPDY sessions</h4>
         <!-- Only one of these two are shown -->
         <span id=spdySessionNoneSpan>None</span>
@@ -157,6 +166,11 @@
         <div id=spdySessionDiv>
         </div>
       </p>
+
+      <h4>Alternate Protocol Mappings</h4>
+      <p />
+        <div id=spdyAlternateProtocolMappingsDiv>
+        </div>
     </div>
     <div id=httpCacheTabContent>
       <h4>Entries</h4>
@@ -202,23 +216,41 @@
     <table width=100%>
     <tr>
     <td valign=top>
-      <h2>Dump data</h2>
-      <div style="margin: 8px">
-        <p><input id=securityStrippingCheckbox type=checkbox checked=yes>
-           Strip private information (cookies and credentials).
-        </p>
-        <p>
-          <a href="javascript:displayHelpForBugDump()">
-            Help: How to get data for bug reports?
-          </a>
-        </p>
-        <button id=exportToText class=bigButton>Dump to text</button>
+      <div id=dataViewDumpDataDiv>
+        <h2>Dump data</h2>
+        <div style="margin: 8px">
+          <p><input id=securityStrippingCheckbox type=checkbox checked=yes>
+             Strip private information (cookies and credentials).
+          </p>
+          <p>
+            <a href="javascript:displayHelpForBugDump()">
+              Help: How to get data for bug reports?
+            </a>
+          </p>
+          <button id=exportToText class=bigButton>Dump to text</button>
+        </div>
+      </div>
+      <div id=dataViewLoadDataDiv>
+        <h2>Load data</h2>
+        <div style="margin: 8px">
+          <p><input type=button value="Load log from file" id=dataViewLoadLogFile /></p>
+          <p>Only works with log files created with "--log-net-log=file_name".</p>
+          <p>Once a log is loaded, this page will stop collecting data, and will
+             only start gathering data again when the page is
+             <a href="javascript:history.go(0);">reloaded</a>.<BR>
+          </p>
+        </div>
       </div>
     </td>
 
     <td align=right valign=top>
-      <div class="capturingBox">
-        <b>Capturing all events...</b>
+      <div class="capturingBox" id=dataViewCapturingBox>
+        <span id=dataViewCapturingTextSpan>
+          <b>Capturing all events...</b>
+        </span>
+        <span id=dataViewLoggingTextSpan style="display: none;">
+          <b>Viewing loaded log file.</b>
+        </span>
         <table style="margin: 8px">
           <tr>
             <td>Passively captured:</td>
@@ -245,7 +277,7 @@
 <!-- START OF HELP TEXT -->
 <script>
 function displayHelpForBugDump() {
-  // We can't access the popups loaded from DOMUI pages, so we instead populate
+  // We can't access the popups loaded from WebUI pages, so we instead populate
   // its contents using a data:URL. YUCK!
   // TODO(eroman): do something less hacky, like exposing a new URL.
   var helpContents =
diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js
index d879c87..ed803c5 100644
--- a/chrome/browser/resources/net_internals/main.js
+++ b/chrome/browser/resources/net_internals/main.js
@@ -75,10 +75,12 @@
   // captured data.
   var dataView = new DataView('dataTabContent', 'exportedDataText',
                               'exportToText', 'securityStrippingCheckbox',
-                              'byteLoggingCheckbox',
-                              'passivelyCapturedCount',
-                              'activelyCapturedCount',
-                              'dataViewDeleteAll');
+                              'byteLoggingCheckbox', 'passivelyCapturedCount',
+                              'activelyCapturedCount', 'dataViewDeleteAll',
+                              'dataViewDumpDataDiv', 'dataViewLoadDataDiv',
+                              'dataViewLoadLogFile',
+                              'dataViewCapturingTextSpan',
+                              'dataViewLoggingTextSpan');
 
   // Create a view which will display the results and controls for connection
   // tests.
@@ -93,11 +95,16 @@
                                     'socketPoolGroupsDiv');
 
   var spdyView = new SpdyView('spdyTabContent',
+                              'spdyEnabledSpan',
+                              'spdyUseAlternateProtocolSpan',
+                              'spdyForceAlwaysSpan',
+                              'spdyForceOverSslSpan',
+                              'spdyNextProtocolsSpan',
+                              'spdyAlternateProtocolMappingsDiv',
                               'spdySessionNoneSpan',
                               'spdySessionLinkSpan',
                               'spdySessionDiv');
 
-
   var serviceView;
   if (g_browser.isPlatformWindows()) {
     serviceView = new ServiceProvidersView('serviceProvidersTab',
@@ -108,6 +115,7 @@
 
   // Create a view which lets you tab between the different sub-views.
   var categoryTabSwitcher = new TabSwitcherView('categoryTabHandles');
+  g_browser.setTabSwitcher(categoryTabSwitcher);
 
   // Populate the main tabs.
   categoryTabSwitcher.addTab('eventsTab', eventsView, false);
@@ -144,6 +152,9 @@
   // Select the initial view based on the current URL.
   window.onhashchange();
 
+  // Inform observers a log file is not currently being displayed.
+  g_browser.setIsViewingLogFile_(false);
+
   // Tell the browser that we are ready to start receiving log events.
   g_browser.sendReady();
 }
@@ -178,6 +189,13 @@
   this.pollableDataHelpers_.spdySessionInfo =
       new PollableDataHelper('onSpdySessionInfoChanged',
                              this.sendGetSpdySessionInfo.bind(this));
+  this.pollableDataHelpers_.spdyStatus =
+      new PollableDataHelper('onSpdyStatusChanged',
+                             this.sendGetSpdyStatus.bind(this));
+  this.pollableDataHelpers_.spdyAlternateProtocolMappings =
+      new PollableDataHelper('onSpdyAlternateProtocolMappingsChanged',
+                             this.sendGetSpdyAlternateProtocolMappings.bind(
+                                 this));
   if (this.isPlatformWindows()) {
     this.pollableDataHelpers_.serviceProviders =
         new PollableDataHelper('onServiceProvidersChanged',
@@ -191,6 +209,11 @@
   // Next unique id to be assigned to a log entry without a source.
   // Needed to simplify deletion, identify associated GUI elements, etc.
   this.nextSourcelessEventId_ = -1;
+
+  // True when viewing a log file rather than actively logged events.
+  // When viewing a log file, all tabs are hidden except the event view,
+  // and all received events are ignored.
+  this.isViewingLogFile_ = false;
 }
 
 /*
@@ -290,6 +313,14 @@
   chrome.send('getSpdySessionInfo');
 };
 
+BrowserBridge.prototype.sendGetSpdyStatus = function() {
+  chrome.send('getSpdyStatus');
+};
+
+BrowserBridge.prototype.sendGetSpdyAlternateProtocolMappings = function() {
+  chrome.send('getSpdyAlternateProtocolMappings');
+};
+
 BrowserBridge.prototype.sendGetServiceProviders = function() {
   chrome.send('getServiceProviders');
 };
@@ -302,23 +333,19 @@
   chrome.send('setLogLevel', ['' + logLevel]);
 }
 
+BrowserBridge.prototype.loadLogFile = function() {
+  chrome.send('loadLogFile');
+}
+
 //------------------------------------------------------------------------------
 // Messages received from the browser
 //------------------------------------------------------------------------------
 
 BrowserBridge.prototype.receivedLogEntries = function(logEntries) {
-  for (var e = 0; e < logEntries.length; ++e) {
-    var logEntry = logEntries[e];
-
-    // Assign unique ID, if needed.
-    if (logEntry.source.id == 0) {
-      logEntry.source.id = this.nextSourcelessEventId_;
-      --this.nextSourcelessEventId_;
-    }
-    this.capturedEvents_.push(logEntry);
-    for (var i = 0; i < this.logObservers_.length; ++i)
-      this.logObservers_[i].onLogEntryAdded(logEntry);
-  }
+  // Does nothing if viewing a log file.
+  if (this.isViewingLogFile_)
+    return;
+  this.addLogEntries(logEntries);
 };
 
 BrowserBridge.prototype.receivedLogEventTypeConstants = function(constantsMap) {
@@ -383,6 +410,16 @@
   this.pollableDataHelpers_.spdySessionInfo.update(spdySessionInfo);
 };
 
+BrowserBridge.prototype.receivedSpdyStatus = function(spdyStatus) {
+  this.pollableDataHelpers_.spdyStatus.update(spdyStatus);
+};
+
+BrowserBridge.prototype.receivedSpdyAlternateProtocolMappings =
+    function(spdyAlternateProtocolMappings) {
+  this.pollableDataHelpers_.spdyAlternateProtocolMappings.update(
+      spdyAlternateProtocolMappings);
+};
+
 BrowserBridge.prototype.receivedServiceProviders = function(serviceProviders) {
   this.pollableDataHelpers_.serviceProviders.update(serviceProviders);
 };
@@ -439,9 +476,91 @@
   this.pollableDataHelpers_.httpCacheInfo.update(info);
 };
 
+BrowserBridge.prototype.loadedLogFile = function(logFileContents) {
+  var match;
+  // Replace carriage returns with linebreaks and then split around linebreaks.
+  var lines = logFileContents.replace(/\r/g, '\n').split('\n');
+  var entries = [];
+  var numInvalidLines = 0;
+
+  for (var i = 0; i < lines.length; ++i) {
+    if (lines[i].trim().length == 0)
+      continue;
+    // Parse all valid lines, skipping any others.
+    try {
+      var entry = JSON.parse(lines[i]);
+      if (entry &&
+          typeof(entry) == 'object' &&
+          entry.phase != undefined &&
+          entry.source != undefined &&
+          entry.time != undefined &&
+          entry.type != undefined) {
+        entries.push(entry);
+        continue;
+      }
+    } catch (err) {
+    }
+    ++numInvalidLines;
+    console.log('Unable to parse log line: ' + lines[i]);
+  }
+
+  if (entries.length == 0) {
+    window.alert('Loading log file failed.');
+    return;
+  }
+
+  this.deleteAllEvents();
+
+  this.setIsViewingLogFile_(true);
+
+  var validEntries = [];
+  for (var i = 0; i < entries.length; ++i) {
+    entries[i].wasPassivelyCaptured = true;
+    if (LogEventType[entries[i].type] != undefined &&
+        LogSourceType[entries[i].source.type] != undefined &&
+        LogEventPhase[entries[i].phase] != undefined) {
+      entries[i].type = LogEventType[entries[i].type];
+      entries[i].source.type = LogSourceType[entries[i].source.type];
+      entries[i].phase = LogEventPhase[entries[i].phase];
+      validEntries.push(entries[i]);
+    } else {
+      // TODO(mmenke):  Do something reasonable when the event type isn't
+      //                found, which could happen when event types are
+      //                removed or added between versions.  Could also happen
+      //                with source types, but less likely.
+      console.log(
+        'Unrecognized values in log entry: ' + JSON.stringify(entry));
+    }
+  }
+
+  this.numPassivelyCapturedEvents_ = validEntries.length;
+  this.addLogEntries(validEntries);
+
+  var numInvalidEntries = entries.length - validEntries.length;
+  if (numInvalidEntries > 0 || numInvalidLines > 0) {
+    window.alert(
+      numInvalidLines.toString() +
+      ' could not be parsed as JSON strings, and ' +
+      numInvalidEntries.toString() +
+      ' entries don\'t have valid data.\n\n' +
+      'Unparseable lines may indicate log file corruption.\n' +
+      'Entries with invalid data may be caused by version differences.\n\n' +
+      'See console for more information.');
+  }
+}
+
 //------------------------------------------------------------------------------
 
 /**
+ * Sets the |categoryTabSwitcher_| of BrowserBridge.  Since views depend on
+ * g_browser being initialized, have to have a BrowserBridge prior to tab
+ * construction.
+ */
+BrowserBridge.prototype.setTabSwitcher = function(categoryTabSwitcher) {
+  this.categoryTabSwitcher_ = categoryTabSwitcher;
+};
+
+/**
  * Adds a listener of log entries. |observer| will be called back when new log
  * data arrives, through:
  *
@@ -520,6 +639,28 @@
 };
 
 /**
+ * Adds a listener of the SPDY status. |observer| will be called back
+ * when data is received, through:
+ *
+ *   observer.onSpdyStatusChanged(spdyStatus)
+ */
+BrowserBridge.prototype.addSpdyStatusObserver = function(observer) {
+  this.pollableDataHelpers_.spdyStatus.addObserver(observer);
+};
+
+/**
+ * Adds a listener of the AlternateProtocolMappings. |observer| will be called
+ * back when data is received, through:
+ *
+ *   observer.onSpdyAlternateProtocolMappingsChanged(
+ *       spdyAlternateProtocolMappings)
+ */
+BrowserBridge.prototype.addSpdyAlternateProtocolMappingsObserver =
+    function(observer) {
+  this.pollableDataHelpers_.spdyAlternateProtocolMappings.addObserver(observer);
+};
+
+/**
  * Adds a listener of the service providers info. |observer| will be called
  * back when data is received, through:
  *
@@ -592,6 +733,25 @@
 };
 
 /**
+ * Sends each entry to all log observers, and updates |capturedEvents_|.
+ * Also assigns unique ids to log entries without a source.
+ */
+BrowserBridge.prototype.addLogEntries = function(logEntries) {
+  for (var e = 0; e < logEntries.length; ++e) {
+    var logEntry = logEntries[e];
+
+    // Assign unique ID, if needed.
+    if (logEntry.source.id == 0) {
+      logEntry.source.id = this.nextSourcelessEventId_;
+      --this.nextSourcelessEventId_;
+    }
+    this.capturedEvents_.push(logEntry);
+    for (var i = 0; i < this.logObservers_.length; ++i)
+      this.logObservers_[i].onLogEntryAdded(logEntry);
+  }
+};
+
+/**
  * Deletes captured events with source IDs in |sourceIds|.
  */
 BrowserBridge.prototype.deleteEventsBySourceId = function(sourceIds) {
@@ -626,6 +786,39 @@
 };
 
 /**
+ * Informs log observers whether or not future events will be from a log file.
+ * Hides all tabs except the events and data tabs when viewing a log file, shows
+ * them all otherwise.
+ */
+BrowserBridge.prototype.setIsViewingLogFile_ = function(isViewingLogFile) {
+  this.isViewingLogFile_ = isViewingLogFile;
+  var tabIds = this.categoryTabSwitcher_.getAllTabIds();
+
+  for (var i = 0; i < this.logObservers_.length; ++i)
+    this.logObservers_[i].onSetIsViewingLogFile(isViewingLogFile);
+
+  // Shows/hides tabs not used when viewing a log file.
+  for (var i = 0; i < tabIds.length; ++i) {
+    if (tabIds[i] == 'eventsTab' || tabIds[i] == 'dataTab')
+      continue;
+    this.categoryTabSwitcher_.showTabHandleNode(tabIds[i], !isViewingLogFile);
+  }
+
+  if (isViewingLogFile) {
+    var activeTab = this.categoryTabSwitcher_.findActiveTab();
+    if (activeTab.id != 'eventsTab')
+      this.categoryTabSwitcher_.switchToTab('dataTab', null);
+  }
+};
+
+/**
+ * Returns true if a log file is currently being viewed.
+ */
+BrowserBridge.prototype.isViewingLogFile = function() {
+  return this.isViewingLogFile_;
+};
+
+/**
  * If |force| is true, calls all startUpdate functions.  Otherwise, just
  * runs updates with active observers.
  */
diff --git a/chrome/browser/resources/net_internals/proxyview.js b/chrome/browser/resources/net_internals/proxyview.js
index 0f7f68b..a6ff9a9 100644
--- a/chrome/browser/resources/net_internals/proxyview.js
+++ b/chrome/browser/resources/net_internals/proxyview.js
@@ -114,3 +114,7 @@
 ProxyView.prototype.onAllLogEntriesDeleted = function() {
   this.clearLog_();
 };
+
+ProxyView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) {
+};
+
diff --git a/chrome/browser/resources/net_internals/spdyview.js b/chrome/browser/resources/net_internals/spdyview.js
index e0d0bd2..d7abc54 100644
--- a/chrome/browser/resources/net_internals/spdyview.js
+++ b/chrome/browser/resources/net_internals/spdyview.js
@@ -8,11 +8,27 @@
  *
  * @constructor
  */
-function SpdyView(mainBoxId, spdySessionNoneSpanId, spdySessionLinkSpanId,
+function SpdyView(mainBoxId, spdyEnabledSpanId,
+                  spdyUseAlternateProtocolSpanId,
+                  spdyForceAlwaysSpanId, spdyForceOverSslSpanId,
+                  spdyNextProtocolsSpanId, spdyAlternateProtocolMappingsDivId,
+                  spdySessionNoneSpanId, spdySessionLinkSpanId,
                   spdySessionDivId) {
   DivView.call(this, mainBoxId);
   g_browser.addSpdySessionInfoObserver(this);
+  g_browser.addSpdyStatusObserver(this);
+  g_browser.addSpdyAlternateProtocolMappingsObserver(this);
 
+  this.spdyEnabledSpan_ = document.getElementById(spdyEnabledSpanId);
+  this.spdyUseAlternateProtocolSpan_ =
+      document.getElementById(spdyUseAlternateProtocolSpanId);
+  this.spdyForceAlwaysSpan_ = document.getElementById(spdyForceAlwaysSpanId);
+  this.spdyForceOverSslSpan_ = document.getElementById(spdyForceOverSslSpanId);
+  this.spdyNextProtocolsSpan_ =
+      document.getElementById(spdyNextProtocolsSpanId);
+
+  this.spdyAlternateProtocolMappingsDiv_ =
+      document.getElementById(spdyAlternateProtocolMappingsDivId);
   this.spdySessionNoneSpan_ = document.getElementById(spdySessionNoneSpanId);
   this.spdySessionLinkSpan_ = document.getElementById(spdySessionLinkSpanId);
   this.spdySessionDiv_ = document.getElementById(spdySessionDivId);
@@ -36,6 +52,39 @@
 
   var tablePrinter = SpdyView.createSessionTablePrinter(spdySessionInfo);
   tablePrinter.toHTML(this.spdySessionDiv_, 'styledTable');
+
+};
+
+/**
+ * Displays information on the global SPDY status.
+ */
+SpdyView.prototype.onSpdyStatusChanged = function(spdyStatus) {
+  this.spdyEnabledSpan_.innerText = spdyStatus.spdy_enabled;
+  this.spdyUseAlternateProtocolSpan_.innerText =
+      spdyStatus.use_alternate_protocols;
+  this.spdyForceAlwaysSpan_.innerText = spdyStatus.force_spdy_always;
+  this.spdyForceOverSslSpan_.innerText = spdyStatus.force_spdy_over_ssl;
+  this.spdyNextProtocolsSpan_.innerText = spdyStatus.next_protos;
+}
+
+/**
+ * If |spdyAlternateProtocolMappings| is not empty, displays a single table
+ * with information on each alternate protocol enabled server.  Otherwise,
+ * displays "None".
+ */
+SpdyView.prototype.onSpdyAlternateProtocolMappingsChanged =
+    function(spdyAlternateProtocolMappings) {
+
+  this.spdyAlternateProtocolMappingsDiv_.innerHTML = '';
+
+  if (spdyAlternateProtocolMappings != null &&
+      spdyAlternateProtocolMappings.length > 0) {
+    var tabPrinter = SpdyView.createAlternateProtocolMappingsTablePrinter(
+            spdyAlternateProtocolMappings);
+    tabPrinter.toHTML(this.spdyAlternateProtocolMappingsDiv_, 'styledTable');
+  } else {
+    this.spdyAlternateProtocolMappingsDiv_.innerHTML = 'None';
+  }
 };
 
 /**
@@ -85,3 +134,24 @@
   return tablePrinter;
 };
 
+
+/**
+ * Creates a table printer to print out the list of alternate protocol
+ * mappings.
+ */
+SpdyView.createAlternateProtocolMappingsTablePrinter =
+    function(spdyAlternateProtocolMappings) {
+  var tablePrinter = new TablePrinter();
+  tablePrinter.addHeaderCell('Host');
+  tablePrinter.addHeaderCell('Alternate Protocol');
+
+  for (var i = 0; i < spdyAlternateProtocolMappings.length; i++) {
+    var entry = spdyAlternateProtocolMappings[i];
+    tablePrinter.addRow();
+
+    tablePrinter.addCell(entry.host_port_pair);
+    tablePrinter.addCell(entry.alternate_protocol);
+  }
+  return tablePrinter;
+};
+
diff --git a/chrome/browser/resources/net_internals/tabswitcherview.css b/chrome/browser/resources/net_internals/tabswitcherview.css
index 4b8fb50..5600bee 100644
--- a/chrome/browser/resources/net_internals/tabswitcherview.css
+++ b/chrome/browser/resources/net_internals/tabswitcherview.css
@@ -24,7 +24,7 @@
   -webkit-margin-start: 5px;
 }
 
-xhtml[dir=rtl] .tab-switcher-view li {
+html[dir=rtl] .tab-switcher-view li {
   float: right;
 }
 
diff --git a/chrome/browser/resources/net_internals/tabswitcherview.js b/chrome/browser/resources/net_internals/tabswitcherview.js
index 646c983..18cfa7a 100644
--- a/chrome/browser/resources/net_internals/tabswitcherview.js
+++ b/chrome/browser/resources/net_internals/tabswitcherview.js
@@ -136,6 +136,13 @@
   return ids;
 };
 
+// Shows/hides the DOM node that is used to select the tab.  Will not change
+// the active tab.
+TabSwitcherView.prototype.showTabHandleNode = function(id, isVisible) {
+  var tab = this.findTabById(id);
+  setNodeDisplay(tab.getTabHandleNode(), isVisible);
+};
+
 //-----------------------------------------------------------------------------
 
 /**
diff --git a/chrome/browser/resources/network_menu.js b/chrome/browser/resources/network_menu.js
index 19f40a6..d1396dd 100644
--- a/chrome/browser/resources/network_menu.js
+++ b/chrome/browser/resources/network_menu.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -29,7 +29,7 @@
 })();
 
 /**
- * Sends "connect" using the 'action' DOMUI message.
+ * Sends "connect" using the 'action' WebUI message.
  */
 function sendConnect(index, passphrase, identity, auto_connect) {
   chrome.send('action',
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css
index 44ca39c..fc88c20 100644
--- a/chrome/browser/resources/new_new_tab.css
+++ b/chrome/browser/resources/new_new_tab.css
@@ -81,20 +81,21 @@
 }
 
 #notification {
+  -webkit-transition: opacity .15s;
   position: relative;
   background-color: hsl(52, 100%, 80%);
   border: 1px solid rgb(211, 211, 211);
   border-radius: 6px;
-  padding: 7px 15px;
-  white-space: nowrap;
-  display: table;
-  margin: 2px auto;
-  font-weight: bold;
-  opacity: 0;
-  pointer-events: none;
-  -webkit-transition: opacity .15s;
-  z-index: 1;
   color: black;
+  display: -webkit-box;
+  font-weight: bold;
+  margin: 2px auto;
+  opacity: 0;
+  padding: 7px 15px;
+  pointer-events: none;
+  white-space: nowrap;
+  width: intrinsic;
+  z-index: 2;
 }
 
 #notification.first-run {
@@ -117,8 +118,30 @@
   color: rgb(0, 102, 204);
 }
 
+#notification-close {
+  display: inline-block;
+  border: 0;
+  -webkit-margin-start: 10px;
+  -webkit-margin-end: auto;
+  vertical-align: middle;
+  width: 16px;
+  height: 16px;
+  background: no-repeat;
+  background-color: transparent;
+  background-image: url('chrome://theme/IDR_CLOSE_BAR');
+  padding: 0;
+}
+
+#notification-close:hover,
+#notification-close:focus {
+  background-image: url('chrome://theme/IDR_CLOSE_BAR_H');
+}
+
+#notification-close:active {
+  background-image: url('chrome://theme/IDR_CLOSE_BAR_P');
+}
+
 #notification > * {
-  display: table-cell;
   max-width: 500px;
   overflow: hidden;
   text-overflow: ellipsis;
@@ -139,7 +162,7 @@
   color: rgb(0, 102, 204);
 }
 
-#notification > span > .blacklist-title {
+#notification > * > .blacklist-title {
   display: inline-block;
   max-width: 30ex;
   overflow: hidden;
@@ -261,8 +284,8 @@
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
-  font-size: 100%;
-  margin: 0 10px;
+  font-size: 106%;
+  margin: 0;
 }
 
 .notification.hidden {
@@ -335,8 +358,20 @@
   text-align: end;
 }
 
-.section.disabled,
-#closed-sections-bar .disabled {
+/* A section in menu mode doesn't display its contents at all. Instead it is
+rendered as a menu along the bottom of the screen. We have a separate class for
+this so that when a hidden section is unhidden it can go back to its previous
+collapsed state. */
+.section.menu {
+  display: none !important;
+}
+
+/* A disabled section is not rendered in the UI in any way. Examples of this
+state include the 'recently closed' section when we have no data for it, or this
+'sync status' section, when there is no status to display. We have a separate
+class for this so that when a section is enabled, it can go back to its previous
+menu and collapsed state. */
+.section.disabled {
   display: none !important;
 }
 
@@ -369,7 +404,7 @@
   -webkit-transition: -webkit-transform .15s;
 }
 
-.section:not(.hidden) > h2 > .disclosure {
+.section:not(.collapsed) > h2 > .disclosure {
   -webkit-transform: rotate(90deg);
 }
 
@@ -433,6 +468,9 @@
 }
 
 #closed-sections-bar > button {
+  /* We hide all these buttons by default and turn them on when needed. */
+  display: none;
+
   -webkit-appearance: none;
   background: none;
   border: 0;
@@ -467,11 +505,11 @@
   opacity: 1;
 }
 
-.maxiview.hiding {
+.maxiview.collapsing {
   opacity: 0;
 }
 
-.maxiview.hidden {
+.maxiview.collapsed {
   display: none;
   opacity: 0;
 }
@@ -491,24 +529,24 @@
   overflow-x: hidden;
 }
 
-.section.hidden > * {
+.section.collapsed > * {
   display: none;
 }
 
-.section.hidden > h2 {
+.section.collapsed > h2 {
   display: block;
 }
 
-.section.hidden > .miniview {
+.section.collapsed > .miniview {
   display: block;
   opacity: 0;
 }
 
-.section.hidden > .miniview.opaque {
+.section.collapsed > .miniview.opaque {
   opacity: 1;
 }
 
-.section.hidden > h2 {
+.section.collapsed > h2 {
   margin-right: 0;
 }
 
@@ -532,23 +570,20 @@
 
 /* small */
 
-@media (max-width: 940px) {
+.small-layout #main,
+.small-layout .section,
+.small-layout .maxiview,
+.small-layout #login-container,
+.small-layout #notification-container {
+  width: 692px;
+}
 
-  #main,
-  .section,
-  .maxiview,
-  #login-container,
-  #notification-container {
-    width: 692px;
-  }
+.small-layout  #notification > * {
+  max-width: 300px;
+}
 
-  #notification > * {
-    max-width: 300px;
-  }
-
-  #notification > span > .blacklist-title {
-    max-width: 15ex;
-  }
+.small-layout  #notification > span > .blacklist-title {
+  max-width: 15ex;
 }
 
 /* Ensure we have at least 10px horizontal marging. */
diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html
index f987bde..1148bc7 100644
--- a/chrome/browser/resources/new_new_tab.html
+++ b/chrome/browser/resources/new_new_tab.html
@@ -10,6 +10,7 @@
 <head>
 <meta charset="utf-8">
 <title i18n-content="title"></title>
+<script src="shared/js/util.js"></script>
 <script>
 // Logging info for benchmarking purposes.
 var log = [];
@@ -21,8 +22,6 @@
 }
 logEvent('Tab.NewTabScriptStart', true);
 
-var global = this;
-
 /**
  * Registers a callback function so that if the backend calls it too early it
  * will get delayed until DOMContentLoaded is fired.
@@ -54,6 +53,8 @@
 registerCallback('getAppsCallback');
 registerCallback('setShownSections');
 registerCallback('foreignSessions');
+registerCallback('bookmarkBarDetached');
+registerCallback('bookmarkBarAttached');
 
 </script>
 <!-- template data placeholder -->
@@ -73,12 +74,15 @@
   APPS: 1 << 6
 };
 
-// These are used to hide sections and are part of the |shownSections| bitmask,
-// but are not sections themselves.
-var MINIMIZED_THUMB = 1 << (0 + 16);
-var MINIMIZED_RECENT = 1 << (2 + 16);
-var MINIMIZED_APPS = 1 << (6 + 16);
+// These are used to put sections into menu mode and are part of the
+// |shownSections| bitmask, but are not sections themselves.
+var MENU_THUMB = 1 << (0 + 16);
+var MENU_RECENT = 1 << (2 + 16);
+var MENU_APPS = 1 << (6 + 16);
 
+// TODO(aa): This state is duplicated. We keep this variable up to date, but we
+// also have the same information in the DOM. We can probably just have the DOM
+// be the truth and translate to and from the bitmask when needed.
 var shownSections = templateData['shown_sections'];
 
 // Until themes can clear the cache, force-reload the theme stylesheet.
@@ -130,8 +134,9 @@
 
   <div id="notification-container">
     <div id="notification">
-      <span>&nbsp;</span>
-      <span class="link"><span class="link-color"></span></span>
+      <div>&nbsp;</div>
+      <div class="link"><div class="link-color" id="action-link"></div></div>
+      <button id="notification-close"></button>
     </div>
   </div>
 
@@ -143,7 +148,7 @@
     <div id="apps-promo">
       <button id="apps-promo-hide" i18n-content="appspromohide"></button>
       <h3 i18n-content="appspromoheader"></h3>
-      <p id="apps-promo-text1" i18n-content="appspromotext1"></p>
+      <p id="apps-promo-text1" i18n-values=".innerHTML:appspromotext1"></p>
       <p id="apps-promo-text2" i18n-content="appspromotext2"></p>
     </div>
     <div id="apps-content"></div>
@@ -176,8 +181,8 @@
 
     <!-- Start this section disabled because it might not have data, and looks
          silly without any. -->
-    <div id="recently-closed" class="section hidden disabled" section="RECENT"
-        noexpand="true">
+    <div id="recently-closed" class="section collapsed disabled"
+        section="RECENT" noexpand="true">
       <h2>
         <div class="back"></div>
         <span i18n-content="recentlyclosed"></span>
@@ -188,7 +193,8 @@
 
     <!-- Start disabled until sync is enabled and foreign sessions are
          available. -->
-    <div id="foreign-sessions" class="section hidden disabled" section="SYNC">
+    <div id="foreign-sessions" class="section collapsed disabled"
+        section="SYNC">
       <h2>
         <div class="back"></div>
         <span i18n-content="foreignsessions"></span>
@@ -213,7 +219,6 @@
       <img src="ntp/ntp_disclosure_triangle.png">
     </button>
     <button id="most-visited-button"
-            class="disabled"
             menu="#most-visited-menu">
       <span i18n-content="mostvisited"></span>
       <img src="ntp/ntp_disclosure_triangle.png">
@@ -283,7 +288,7 @@
 <script src="shared/js/cr/ui/context_menu_button.js"></script>
 <script src="shared/js/cr/ui/context_menu_handler.js"></script>
 
-<script src="ntp/util.js"></script>
+<script src="ntp/drag_drop_controller.js"></script>
 <script src="ntp/most_visited.js"></script>
 <script src="new_new_tab.js"></script>
 <script src="ntp/apps.js"></script>
@@ -298,40 +303,20 @@
 
   initializeLogin();
 
-  initializeSection('apps', MINIMIZED_APPS, Section.APPS);
-  initializeSection('most-visited', MINIMIZED_THUMB, Section.THUMB);
-  initializeSection('recently-closed', MINIMIZED_RECENT);
+  initializeSection('apps', MENU_APPS, Section.APPS);
+  initializeSection('most-visited', MENU_THUMB, Section.THUMB);
+  initializeSection('recently-closed', MENU_RECENT);
 
   updateSimpleSection('apps', Section.APPS);
   updateSimpleSection('most-visited', Section.THUMB);
-  var appsInitiallyVisible = !(shownSections & MINIMIZED_APPS);
-  var mostVisitedInitiallyVisible = !(shownSections & MINIMIZED_THUMB);
-  var recentlyClosedInitiallyVisible = !(shownSections & MINIMIZED_RECENT);
-  // Apps and recently closed start as hidden in the HTML, most visited is
-  // initially visible. Adapt to the change received from the prefs by forcing
-  // all three sections to update.
-  shownSections &= ~MINIMIZED_THUMB;
-  shownSections |= MINIMIZED_APPS | MINIMIZED_RECENT;
-  setSectionVisible('apps', Section.APPS, appsInitiallyVisible, MINIMIZED_APPS);
-  setSectionVisible(
-      'most-visited', Section.THUMB,
-      mostVisitedInitiallyVisible, MINIMIZED_THUMB);
-  setSectionVisible(
-      'recently-closed', undefined,
-      recentlyClosedInitiallyVisible, MINIMIZED_RECENT);
-
-  // This is insane, but we use the CSS class 'disabled' for both 'minimized'
-  // sections and sections that are actually disabled, as in not accessible in
-  // any way.
-  //
-  // The above code syncs up the DOM and shownSection wrt minimized. But we
-  // don't know until we receive the apps data whether the apps section will be
-  // disabled or not. So we need to add the 'disabled' class back to the apps
-  // section here. We remove it later, once we know for sure we want it to be
-  // enabled.
-  //
-  // See also: crbug.com/67273.
-  $('apps').classList.add('disabled');
+  var appsInitiallyMenu = shownSections & MENU_APPS;
+  var mostVisitedInitiallyMenu = shownSections & MENU_THUMB;
+  var recentlyClosedInitiallyMenu = shownSections & MENU_RECENT;
+  setSectionMenuMode('apps', Section.APPS, appsInitiallyMenu, MENU_APPS);
+  setSectionMenuMode('most-visited', Section.THUMB, mostVisitedInitiallyMenu,
+                     MENU_THUMB);
+  setSectionMenuMode('recently-closed', undefined, recentlyClosedInitiallyMenu,
+                     MENU_RECENT);
 
   layoutSections();
 </script>
diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js
index a2dbc6b..eb425d5 100644
--- a/chrome/browser/resources/new_new_tab.js
+++ b/chrome/browser/resources/new_new_tab.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,9 @@
 // Extra spacing at the top of the layout.
 var LAYOUT_SPACING_TOP = 25;
 
+// The visible height of the expanded maxiview.
+var maxiviewVisibleHeight = 0;
+
 function getSectionCloseButton(sectionId) {
   return document.querySelector('#' + sectionId + ' .section-close-button');
 }
@@ -21,29 +24,21 @@
   return sectionId.replace(/-/g, '');
 }
 
-function setSectionVisible(sectionId, section, visible, hideMask) {
-  if (visible && !(shownSections & hideMask) ||
-      !visible && (shownSections & hideMask))
-    return;
-
-  if (visible) {
-    // Because sections are collapsed when they are minimized, it is not
+function setSectionMenuMode(sectionId, section, menuModeEnabled, menuModeMask) {
+  var el = $(sectionId);
+  if (!menuModeEnabled) {
+    // Because sections are collapsed when they are in menu mode, it is not
     // necessary to restore the maxiview here. It will happen if the section
     // header is clicked.
-    var el = $(sectionId);
-    el.classList.remove('disabled');
-    el = getSectionMenuButton(sectionId);
-    el.classList.add('disabled');
-    shownSections &= ~hideMask;
+    // TODO(aa): Sections should maintain their collapse state when minimized.
+    el.classList.remove('menu');
+    shownSections &= ~menuModeMask;
   } else {
     if (section) {
       hideSection(section);  // To hide the maxiview.
     }
-    var el = $(sectionId);
-    el.classList.add('disabled');
-    el = getSectionMenuButton(sectionId);
-    el.classList.remove('disabled');
-    shownSections |= hideMask;
+    el.classList.add('menu');
+    shownSections |= menuModeMask;
   }
   layoutSections();
 }
@@ -85,7 +80,7 @@
       function(e) {
         getSectionMenuButton(sectionId).hideMenu();
         e.preventDefault();
-        setSectionVisible(sectionId, opt_section, true, mask);
+        setSectionMenuMode(sectionId, opt_section, false, mask);
         shownSections &= ~mask;
         saveShownSections();
       });
@@ -97,7 +92,7 @@
   button.addEventListener(
     'click',
     function() {
-      setSectionVisible(sectionId, opt_section, false, mask);
+      setSectionMenuMode(sectionId, opt_section, true, mask);
       saveShownSections();
     });
 }
@@ -109,19 +104,19 @@
   if (shownSections & section) {
     // The section is expanded, so the maxiview should be opaque (visible) and
     // the miniview should be hidden.
-    elm.classList.remove('hidden');
+    elm.classList.remove('collapsed');
     if (maxiview) {
-      maxiview.classList.remove('hidden');
+      maxiview.classList.remove('collapsed');
       maxiview.classList.add('opaque');
     }
     if (miniview)
       miniview.classList.remove('opaque');
   } else {
-    // The section is minimized, so the maxiview should be hidden and the
+    // The section is collapsed, so the maxiview should be hidden and the
     // miniview should be opaque.
-    elm.classList.add('hidden');
+    elm.classList.add('collapsed');
     if (maxiview) {
-      maxiview.classList.add('hidden');
+      maxiview.classList.add('collapsed');
       maxiview.classList.remove('opaque');
     }
     if (miniview)
@@ -195,7 +190,7 @@
     // Sort tabs by MRU order
     win.tabs.sort(function(a, b) {
       return a.timestamp < b.timestamp;
-    })
+    });
 
     // Create individual tab information.
     win.tabs.forEach(function(data) {
@@ -213,7 +208,7 @@
                                handleIfEnterKey(maybeOpenForeignTab));
 
         winSpan.appendChild(tabEl);
-    })
+    });
 
     // Append the window.
     stack.appendChild(winSpan);
@@ -243,7 +238,7 @@
     parentEl.appendChild(createRecentItem(item));
     addRecentMenuItem(recentMenu, item);
   });
-  addClosedMenuFooter(recentMenu, 'recently-closed', MINIMIZED_RECENT);
+  addClosedMenuFooter(recentMenu, 'recently-closed', MENU_RECENT);
 
   layoutRecentlyClosed();
 }
@@ -294,7 +289,7 @@
 }
 
 function saveShownSections() {
-  chrome.send('setShownSections', [String(shownSections)]);
+  chrome.send('setShownSections', [shownSections]);
 }
 
 var LayoutMode = {
@@ -310,13 +305,22 @@
     return;
   }
 
+  // TODO(jstritar): Remove the small-layout class and revert back to the
+  // @media (max-width) directive once http://crbug.com/70930 is fixed.
   var oldLayoutMode = layoutMode;
   var b = useSmallGrid();
-  layoutMode = b ? LayoutMode.SMALL : LayoutMode.NORMAL;
+  if (b) {
+    layoutMode = LayoutMode.SMALL;
+    document.body.classList.add('small-layout');
+  } else {
+    layoutMode = LayoutMode.NORMAL;
+    document.body.classList.remove('small-layout');
+  }
 
   if (layoutMode != oldLayoutMode){
     mostVisited.useSmallGrid = b;
     mostVisited.layout();
+    apps.layout({force:true});
     renderRecentlyClosed();
     renderForeignSessions();
     updateAllMiniviewClippings();
@@ -332,7 +336,7 @@
   this.header = section.querySelector('h2');
   this.miniview = section.querySelector('.miniview');
   this.maxiview = getSectionMaxiview(section);
-  this.expanded = this.maxiview && !section.classList.contains('hidden');
+  this.expanded = this.maxiview && !section.classList.contains('collapsed');
   this.fixedHeight = this.section.offsetHeight;
   this.scrollingHeight = 0;
 
@@ -342,7 +346,8 @@
 
 // Get all sections to be layed out.
 SectionLayoutInfo.getAll = function() {
-  var sections = document.querySelectorAll('.section:not(.disabled)');
+  var sections = document.querySelectorAll(
+      '.section:not(.disabled):not(.menu)');
   var result = [];
   for (var i = 0, section; section = sections[i]; i++) {
     result.push(new SectionLayoutInfo(section));
@@ -367,7 +372,7 @@
 
 // Ensure none of the miniviews have any clipped items.
 function updateAllMiniviewClippings() {
-  var miniviews = document.querySelectorAll('.section.hidden .miniview');
+  var miniviews = document.querySelectorAll('.section.collapsed .miniview');
   for (var i = 0, miniview; miniview = miniviews[i]; i++) {
     updateMiniviewClipping(miniview);
   }
@@ -486,10 +491,12 @@
     }
   } else {
     // We only set the document height when a section is expanded. If
-    // all sections are minimized, then get rid of the previous height.
+    // all sections are collapsed, then get rid of the previous height.
     document.body.style.height = '';
   }
 
+  maxiviewVisibleHeight = expandedSectionHeight;
+
   // Now position all the elements.
   var y = LAYOUT_SPACING_TOP;
   for (i = 0, section; section = sections[i]; i++) {
@@ -518,6 +525,7 @@
   if (cr.isChromeOS)
     $('closed-sections-bar').style.top = y + 'px';
 
+  updateMenuSections();
   updateAttributionDisplay(y);
 }
 
@@ -557,6 +565,24 @@
   return color + ' ' + height * 100 + '%';
 }
 
+// Updates the visibility of the menu buttons for each section, based on
+// whether they are currently enabled and in menu mode.
+function updateMenuSections() {
+  var elms = document.getElementsByClassName('section');
+  for (var i = 0, elm; elm = elms[i]; i++) {
+    var button = getSectionMenuButton(elm.id);
+    if (!button)
+      continue;
+
+    if (!elm.classList.contains('disabled') &&
+        elm.classList.contains('menu')) {
+      button.style.display = 'inline-block';
+    } else {
+      button.style.display = 'none';
+    }
+  }
+}
+
 window.addEventListener('resize', handleWindowResize);
 
 var sectionToElementMap;
@@ -585,16 +611,16 @@
     shownSections |= section;
     var el = getSectionElement(section);
     if (el) {
-      el.classList.remove('hidden');
+      el.classList.remove('collapsed');
 
       var maxiview = getSectionMaxiview(el);
       if (maxiview) {
-        maxiview.classList.remove('hiding');
-        maxiview.classList.remove('hidden');
+        maxiview.classList.remove('collapsing');
+        maxiview.classList.remove('collapsed');
         // The opacity won't transition if you toggle the display property
         // at the same time. To get a fade effect, we set the opacity
         // asynchronously from another function, after the display is toggled.
-        //   1) 'hidden' (display: none, opacity: 0)
+        //   1) 'collapsed' (display: none, opacity: 0)
         //   2) none (display: block, opacity: 0)
         //   3) 'opaque' (display: block, opacity: 1)
         setTimeout(function () {
@@ -614,6 +640,10 @@
         mostVisited.visible = true;
         mostVisited.layout();
         break;
+      case Section.APPS:
+        apps.visible = true;
+        apps.layout({disableAnimations:true});
+        break;
     }
   }
 }
@@ -638,15 +668,19 @@
         mostVisited.visible = false;
         mostVisited.layout();
         break;
+      case Section.APPS:
+        apps.visible = false;
+        apps.layout();
+        break;
     }
 
     var el = getSectionElement(section);
     if (el) {
-      el.classList.add('hidden');
+      el.classList.add('collapsed');
 
       var maxiview = getSectionMaxiview(el);
       if (maxiview) {
-        maxiview.classList.add(isDoneLoading() ? 'hiding' : 'hidden');
+        maxiview.classList.add(isDoneLoading() ? 'collapsing' : 'collapsed');
         maxiview.classList.remove('opaque');
       }
 
@@ -663,9 +697,9 @@
 }
 
 window.addEventListener('webkitTransitionEnd', function(e) {
-  if (e.target.classList.contains('hiding')) {
-    e.target.classList.add('hidden');
-    e.target.classList.remove('hiding');
+  if (e.target.classList.contains('collapsing')) {
+    e.target.classList.add('collapsed');
+    e.target.classList.remove('collapsing');
   }
 
   if (e.target.classList.contains('maxiview') ||
@@ -686,15 +720,12 @@
     else
       hideSection(Section[key]);
   }
-  setSectionVisible(
-      'apps', Section.APPS,
-      !(newShownSections & MINIMIZED_APPS), MINIMIZED_APPS);
-  setSectionVisible(
-      'most-visited', Section.THUMB,
-      !(newShownSections & MINIMIZED_THUMB), MINIMIZED_THUMB);
-  setSectionVisible(
-      'recently-closed', undefined,
-      !(newShownSections & MINIMIZED_RECENT), MINIMIZED_RECENT);
+  setSectionMenuMode('apps', Section.APPS, newShownSections & MENU_APPS,
+                     MENU_APPS);
+  setSectionMenuMode('most-visited', Section.THUMB,
+                     newShownSections & MENU_THUMB, MENU_THUMB);
+  setSectionMenuMode('recently-closed', undefined,
+                     newShownSections & MENU_RECENT, MENU_RECENT);
   layoutSections();
 }
 
@@ -707,14 +738,14 @@
   updateMiniviewClipping(miniview);
 
   if (miniview.hasChildNodes()) {
-    if (!(shownSections & MINIMIZED_RECENT)) {
-      recentElement.classList.remove('disabled');
-      miniview.classList.add('opaque');
-    }
+    recentElement.classList.remove('disabled');
+    miniview.classList.add('opaque');
   } else {
     recentElement.classList.add('disabled');
     miniview.classList.remove('opaque');
   }
+
+  layoutSections();
 }
 
 /**
@@ -789,7 +820,7 @@
 }
 
 /**
- * Invoked when the link in the sync status section is clicked.
+ * Invoked when the link in the sync promo or sync status section is clicked.
  */
 function syncSectionLinkClicked(e) {
   chrome.send('SyncLinkClicked');
@@ -801,8 +832,7 @@
  * has already been synced to an account.
  */
 function syncAlreadyEnabled(message) {
-  showNotification(message.syncEnabledMessage,
-                   localStrings.getString('close'));
+  showNotification(message.syncEnabledMessage);
 }
 
 /**
@@ -911,15 +941,17 @@
 
 /*
  * Displays a message (either a string or a document fragment) in the
- * notification slot at the top of the NTP.
+ * notification slot at the top of the NTP. A close button ("x") will be
+ * inserted at the end of the message.
  * @param {string|Node} message String or node to use as message.
  * @param {string} actionText The text to show as a link next to the message.
  * @param {function=} opt_f Function to call when the user clicks the action
  *                          link.
  * @param {number=} opt_delay The time in milliseconds before hiding the
- * i                          notification.
+ *                            notification.
  */
 function showNotification(message, actionText, opt_f, opt_delay) {
+// TODO(arv): Create a notification component.
   var notificationElement = $('notification');
   var f = opt_f || function() {};
   var delay = opt_delay || 10000;
@@ -936,6 +968,12 @@
 
   function doAction() {
     f();
+    closeNotification();
+  }
+
+  function closeNotification() {
+    if (notification.classList.contains('promo'))
+      chrome.send('closePromo');
     hideNotification();
   }
 
@@ -944,7 +982,13 @@
   notification.classList.remove('promo');
 
   var messageContainer = notificationElement.firstElementChild;
-  var actionLink = notificationElement.querySelector('.link-color');
+  var actionLink = notificationElement.querySelector('#action-link');
+  var closeButton = notificationElement.querySelector('#notification-close');
+
+  // Remove any previous actionLink entry.
+  actionLink.textContent = '';
+
+  $('notification-close').onclick = closeNotification;
 
   if (typeof message == 'string') {
     messageContainer.textContent = message;
@@ -953,7 +997,12 @@
     messageContainer.appendChild(message);
   }
 
-  actionLink.textContent = actionText;
+  if (actionText) {
+    actionLink.style.display = '';
+    actionLink.textContent = actionText;
+  } else {
+    actionLink.style.display = 'none';
+  }
 
   actionLink.onclick = doAction;
   actionLink.onkeydown = handleIfEnterKey(doAction);
@@ -975,28 +1024,34 @@
   var notificationElement = $('notification');
   notificationElement.classList.remove('show');
   document.body.classList.remove('notification-shown');
-  var actionLink = notificationElement.querySelector('.link-color');
+  var actionLink = notificationElement.querySelector('#actionlink');
+  var closeButton = notificationElement.querySelector('#notification-close');
   // Prevent tabbing to the hidden link.
-  actionLink.tabIndex = -1;
   // Setting tabIndex to -1 only prevents future tabbing to it. If, however, the
   // user switches window or a tab and then moves back to this tab the element
   // may gain focus. We therefore make sure that we blur the element so that the
   // element focus is not restored when coming back to this window.
-  actionLink.blur();
+  if (actionLink) {
+    actionLink.tabIndex = -1;
+    actionLink.blur();
+  }
+  if (closeButton) {
+    closeButton.tabIndex = -1;
+    closeButton.blur();
+  }
 }
 
 function showFirstRunNotification() {
   showNotification(localStrings.getString('firstrunnotification'),
-                   localStrings.getString('closefirstrunnotification'),
-                   null, 30000);
+                   null, null, 30000);
   var notificationElement = $('notification');
   notification.classList.add('first-run');
 }
 
 function showPromoNotification() {
   showNotification(parseHtmlSubset(localStrings.getString('serverpromo')),
-                   localStrings.getString('closefirstrunnotification'),
-                   function () { chrome.send('closePromo'); },
+                   localStrings.getString('syncpromotext'),
+                   function () { chrome.send('SyncLinkClicked'); },
                    60000);
   var notificationElement = $('notification');
   notification.classList.add('promo');
@@ -1379,10 +1434,7 @@
 
 // Initialize the apps promo.
 document.addEventListener('DOMContentLoaded', function() {
-  var promoText1 = $('apps-promo-text1');
-  promoText1.innerHTML = promoText1.textContent;
-
-  var promoLink = promoText1.querySelector('a');
+  var promoLink = document.querySelector('#apps-promo-text1 a');
   promoLink.id = 'apps-promo-link';
   promoLink.href = localStrings.getString('web_store_url');
 
diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css
index e2add06..682cf16 100644
--- a/chrome/browser/resources/new_tab_theme.css
+++ b/chrome/browser/resources/new_tab_theme.css
@@ -134,7 +134,8 @@
   color: $8; /* COLOR_NTP_TEXT */
 }
 
-.app:hover > a {
+.app:hover > a,
+.app.dragging > a {
   color: $$3; /* COLOR_NTP_SECTION_TEXT */
   background-color: $$1; /* COLOR_NTP_SECTION */;
 }
diff --git a/chrome/browser/resources/ntp/apps.css b/chrome/browser/resources/ntp/apps.css
index 2d03d58..66e0411 100644
--- a/chrome/browser/resources/ntp/apps.css
+++ b/chrome/browser/resources/ntp/apps.css
@@ -2,7 +2,6 @@
 
 #apps-content {
   position: relative;
-  width: intrinsic;
   max-width: 780px;  /* (124 + margin * 2) * 6 */
 }
 
@@ -10,16 +9,17 @@
   max-width: 650px; /* (124 + margin * 2) * 5 */
 }
 
-/* small */
-@media (max-width: 940px) {
-  /*
-  We don't need to do anything for html.apps-promo-visible because there is
-  enough extra space in the small grid layout.
-  */
-  #apps-content,
-  html.apps-promo-visible #apps-content {
-    max-width: 520px;  /* (124 + margin * 2) * 4 */
-  }
+#apps-maxiview {
+  overflow: hidden;
+}
+
+/*
+We don't need to do anything for html.apps-promo-visible because there is
+enough extra space in the small grid layout.
+*/
+.small-layout #apps-content,
+.small-layout html.apps-promo-visible #apps-content {
+  max-width: 520px;  /* (124 + margin * 2) * 4 */
 }
 
 .app,
@@ -28,9 +28,8 @@
   -webkit-perspective: 400;
   border-radius: 10px;
   color: black;
-  display: inline-block;
   margin: 5px 3px;
-  position: relative;
+  position: absolute;
   height: 136px;
   width: 124px; /* 920 / 7 - margin * 2 */
 }
@@ -49,7 +48,7 @@
   background: rgba(255, 255, 255, 0) /* transparent white */
               no-repeat center 10px;
   background-size: 96px 96px;
-  font-family: Helvetica, Arial;
+  font-family: Helvetica, Arial, sans-serif;
   font-size: 107%;
   overflow: hidden;
   padding: 111px 10px 10px;  /* 10 + 96 + 5 */
@@ -62,6 +61,7 @@
 .app .app-settings {
   background-color: transparent;
   background-position: center center;
+  background-repeat: no-repeat;
   border: 0;
   height: 14px;
   padding: 0;
@@ -89,6 +89,18 @@
   opacity: .9;
 }
 
+.app.dragging > .app-settings {
+  background-image: none;
+}
+
+.app.dragging {
+  opacity: .7;
+}
+
+#apps-content[launcher-animations=true] .app {
+  -webkit-transition: top .2s, left .2s, right .2s, opacity .2s;
+}
+
 @-webkit-keyframes bounce {
   0% {
     -webkit-transform: scale(0, 0);
@@ -112,7 +124,7 @@
   -webkit-transition: opacity .5s;
 }
 
-.app[app-id=web-store-entry] > a {
+.app.web-store-entry > a {
   background-image: url("chrome://theme/IDR_WEBSTORE_ICON");
 }
 
@@ -154,18 +166,18 @@
   float: left;
 }
 
-html.apps-promo-visible .app[app-id=web-store-entry] {
+html.apps-promo-visible .app.web-store-entry {
   position: absolute;
   left: 100%;
   top: 0;
   -webkit-margin-start: 22px;
 }
 
-html.apps-promo-visible[dir=rtl] .app[app-id=web-store-entry] {
+html.apps-promo-visible[dir=rtl] .app.web-store-entry {
   right: 100%;
 }
 
-html.apps-promo-visible .app[app-id=web-store-entry] a {
+html.apps-promo-visible .app.web-store-entry a {
   font-weight: bold;
 }
 
@@ -175,12 +187,12 @@
 but different than its position during promo (html.apps-promo-visible), so we
 never set .loner while the promo is running.
 */
-.app[app-id=web-store-entry].loner {
+.app.web-store-entry.loner {
   position: absolute;
   left: 100%;
   top: 0;
 }
 
-html[dir=rtl] .app[app-id=web-store-entry].loner {
+html[dir=rtl] .app.web-store-entry.loner {
   right: 100%;
 }
diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js
index 973dada..3f50d76 100644
--- a/chrome/browser/resources/ntp/apps.js
+++ b/chrome/browser/resources/ntp/apps.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -45,6 +45,15 @@
     return a.app_launch_index - b.app_launch_index;
   });
 
+  // Determines if the web store link should be detached and place in the
+  // top right of the screen.
+  apps.detachWebstoreEntry =
+      !apps.showPromo && data.apps.length >= MAX_APPS_PER_ROW[layoutMode];
+
+  apps.data = data.apps;
+  if (!apps.detachWebstoreEntry)
+    apps.data.push('web-store-entry');
+
   clearClosedMenu(apps.menu);
   data.apps.forEach(function(app) {
     appsSectionContent.appendChild(apps.createElement(app));
@@ -66,27 +75,33 @@
                                apps.createWebStoreClosedMenuElement());
   }
 
-  if (!data.showLauncher || (shownSections & MINIMIZED_APPS)) {
+  if (!data.showLauncher)
     appsSection.classList.add('disabled');
-  } else {
+  else
     appsSection.classList.remove('disabled');
-  }
-  addClosedMenuFooter(apps.menu, 'apps', MINIMIZED_APPS, Section.APPS);
+
+  addClosedMenuFooter(apps.menu, 'apps', MENU_APPS, Section.APPS);
 
   apps.loaded = true;
   if (apps.showPromo)
     document.documentElement.classList.add('apps-promo-visible');
   else
     document.documentElement.classList.remove('apps-promo-visible');
-  $('apps-promo-link').setAttribute('ping', appsPromoPing);
+
+  var appsPromoLink = $('apps-promo-link');
+  if (appsPromoLink)
+    appsPromoLink.setAttribute('ping', appsPromoPing);
   maybeDoneLoading();
 
-  if (isDoneLoading()) {
-    if (!apps.showPromo && data.apps.length >= MAX_APPS_PER_ROW[layoutMode])
-      webStoreEntry.classList.add('loner');
-    else
-      webStoreEntry.classList.remove('loner');
+  // Disable the animations when the app launcher is being (re)initailized.
+  apps.layout({disableAnimations:true});
 
+  if (apps.detachWebstoreEntry)
+    webStoreEntry.classList.add('loner');
+  else
+    webStoreEntry.classList.remove('loner');
+
+  if (isDoneLoading()) {
     updateMiniviewClipping(appsMiniview);
     layoutSections();
   }
@@ -110,15 +125,23 @@
     var a = div.appendChild(document.createElement('a'));
     a.setAttribute('app-id', app['id']);
     a.setAttribute('launch-type', app['launch_type']);
+    a.draggable = false;
     a.xtitle = a.textContent = app['name'];
     a.href = app['launch_url'];
 
     return div;
   }
 
-  function launchApp(appId) {
+  /**
+   * Launches an application.
+   * @param {string} appId Application to launch.
+   * @param {MouseEvent} opt_mouseEvent Mouse event from the click that
+   *     triggered the launch, used to detect modifier keys that change
+   *     the tab's disposition.
+   */
+  function launchApp(appId, opt_mouseEvent) {
     var appsSection = $('apps');
-    var expanded = !appsSection.classList.contains('hidden');
+    var expanded = !appsSection.classList.contains('collapsed');
     var element = document.querySelector(
         (expanded ? '.maxiview' : '.miniview') + ' a[app-id=' + appId + ']');
 
@@ -146,9 +169,19 @@
         left = rect.left;
     }
 
-    chrome.send('launchApp', [appId,
-                              String(left), String(top),
-                              String(width), String(height)]);
+    if (opt_mouseEvent) {
+      // Launch came from a click.
+      chrome.send('launchApp', [appId, left, top, width, height,
+                                opt_mouseEvent.altKey, opt_mouseEvent.ctrlKey,
+                                opt_mouseEvent.metaKey, opt_mouseEvent.shiftKey,
+                                opt_mouseEvent.button]);
+    } else {
+      // Launch came from 'command' event from elsewhere in UI.
+      chrome.send('launchApp', [appId, left, top, width, height,
+                                false /* altKey */, false /* ctrlKey */,
+                                false /* metaKey */, false /* shiftKey */,
+                                0 /* button */]);
+    }
   }
 
   /**
@@ -156,7 +189,8 @@
    */
   function handleClick(e) {
     var appId = e.currentTarget.getAttribute('app-id');
-    launchApp(appId);
+    if (!appDragAndDrop.isDragging())
+      launchApp(appId, e);
     return false;
   }
 
@@ -241,7 +275,8 @@
       case 'apps-launch-type-fullscreen':
       case 'apps-launch-type-window':
         chrome.send('setLaunchType',
-            [currentApp['id'], e.command.getAttribute('launch-type')]);
+            [currentApp['id'],
+             Number(e.command.getAttribute('launch-type'))]);
         break;
     }
   });
@@ -258,6 +293,15 @@
     }
   });
 
+  // Moves the element at position |from| in array |arr| to position |to|.
+  function arrayMove(arr, from, to) {
+    var element = arr.splice(from, 1);
+    arr.splice(to, 0, element[0]);
+  }
+
+  // The autoscroll rate during drag and drop, in px per second.
+  var APP_AUTOSCROLL_RATE = 400;
+
   return {
     loaded: false,
 
@@ -265,6 +309,296 @@
 
     showPromo: false,
 
+    detachWebstoreEntry: false,
+
+    scrollMouseXY_: null,
+
+    scrollListener_: null,
+
+    // The list of app ids, in order, of each app in the launcher.
+    data_: null,
+    get data() { return this.data_; },
+    set data(data) {
+      this.data_ = data.map(function(app) {
+        return app.id;
+      });
+      this.invalidate_();
+    },
+
+    dirty_: true,
+    invalidate_: function() {
+      this.dirty_ = true;
+    },
+
+    visible_: true,
+    get visible() {
+      return this.visible_;
+    },
+    set visible(visible) {
+      this.visible_ = visible;
+      this.invalidate_();
+    },
+
+    // DragAndDropDelegate
+
+    dragContainer: $('apps-content'),
+    transitionsDuration: 200,
+
+    get dragItem() { return this.dragItem_; },
+    set dragItem(dragItem) {
+      if (this.dragItem_ != dragItem) {
+        this.dragItem_ = dragItem;
+        this.invalidate_();
+      }
+    },
+
+    // The dimensions of each item in the app launcher.
+    dimensions_: null,
+    get dimensions() {
+      if (this.dimensions_)
+        return this.dimensions_;
+
+      var width = 124;
+      var height = 136;
+
+      var marginWidth = 6;
+      var marginHeight = 10;
+
+      var borderWidth = 0;
+      var borderHeight = 0;
+
+      this.dimensions_ = {
+        width: width + marginWidth + borderWidth,
+        height: height + marginHeight + borderHeight
+      };
+
+      return this.dimensions_;
+    },
+
+    // Gets the item under the mouse event |e|. Returns null if there is no
+    // item or if the item is not draggable.
+    getItem: function(e) {
+      var item = findAncestorByClass(e.target, 'app');
+
+      // You can't drag the web store launcher.
+      if (item && item.classList.contains('web-store-entry'))
+        return null;
+
+      return item;
+    },
+
+    // Returns true if |coordinates| point to a valid drop location. The
+    // coordinates are relative to the drag container and the object should
+    // have the 'x' and 'y' properties set.
+    canDropOn: function(coordinates) {
+      var cols = MAX_APPS_PER_ROW[layoutMode];
+      var rows = Math.ceil(this.data.length / cols);
+
+      var bottom = rows * this.dimensions.height;
+      var right = cols * this.dimensions.width;
+
+      if (coordinates.x >= right || coordinates.x < 0 ||
+          coordinates.y >= bottom || coordinates.y < 0)
+        return false;
+
+      var position = this.getIndexAt_(coordinates);
+      var appCount = this.data.length;
+
+      if (!this.detachWebstoreEntry)
+        appCount--;
+
+      return position >= 0 && position < appCount;
+    },
+
+    setDragPlaceholder: function(coordinates) {
+      var position = this.getIndexAt_(coordinates);
+      var appId = this.dragItem.querySelector('a').getAttribute('app-id');
+      var current = this.data.indexOf(appId);
+
+      if (current == position || current < 0)
+        return;
+
+      arrayMove(this.data, current, position);
+      this.invalidate_();
+      this.layout();
+    },
+
+    getIndexAt_: function(coordinates) {
+      var w = this.dimensions.width;
+      var h = this.dimensions.height;
+
+      var appsPerRow = MAX_APPS_PER_ROW[layoutMode];
+
+      var row = Math.floor(coordinates.y / h);
+      var col = Math.floor(coordinates.x / w);
+      var index = appsPerRow * row + col;
+
+      var appCount = this.data.length;
+      var rows = Math.ceil(appCount / appsPerRow);
+
+      // Rather than making the free space on the last row invalid, we
+      // map it to the last valid position.
+      if (index >= appCount && index < appsPerRow * rows)
+        return appCount-1;
+
+      return index;
+    },
+
+    scrollPage: function(xy) {
+      var rect = this.dragContainer.getBoundingClientRect();
+
+      // Here, we calculate the visible boundaries of the app launcher, which
+      // are then used to determine when we should auto-scroll.
+      var top = $('apps').getBoundingClientRect().bottom;
+      var bottomFudge = 15; // Fudge factor due to a gradient mask.
+      var bottom = top + maxiviewVisibleHeight - bottomFudge;
+      var left = rect.left + window.scrollX;
+      var right = Math.min(window.innerWidth, rect.left + rect.width);
+
+      var dy = Math.min(0, xy.y - top) + Math.max(0, xy.y - bottom);
+      var dx = Math.min(0, xy.x - left) + Math.max(0, xy.x - right);
+
+      if (dx == 0 && dy == 0) {
+        this.stopScroll_();
+        return;
+      }
+
+      // If we scroll the page directly from this method, it may be choppy and
+      // inconsistent. Instead, we loop using animation frames, and scroll at a
+      // speed that's independent of how many times this method is called.
+      this.scrollMouseXY_ = {dx: dx, dy: dy};
+
+      if (!this.scrollListener_) {
+        this.scrollListener_ = this.scrollImpl_.bind(this);
+        this.scrollStep_();
+      }
+    },
+
+    scrollStep_: function() {
+      this.scrollStart_ = Date.now();
+      window.webkitRequestAnimationFrame(this.scrollListener_);
+    },
+
+    scrollImpl_: function(time) {
+      if (!appDragAndDrop.isDragging()) {
+        this.stopScroll_();
+        return;
+      }
+
+      if (!this.scrollMouseXY_)
+        return;
+
+      var step = time - this.scrollStart_;
+
+      window.scrollBy(
+          this.calcScroll_(this.scrollMouseXY_.dx, step),
+          this.calcScroll_(this.scrollMouseXY_.dy, step));
+
+      this.scrollStep_();
+    },
+
+    calcScroll_: function(delta, step) {
+      if (delta == 0)
+        return 0;
+
+      // Increase the multiplier for every 50px the mouse is beyond the edge.
+      var sign = delta > 0 ? 1 : -1;
+      var scalar = APP_AUTOSCROLL_RATE * step / 1000;
+      var multiplier = Math.floor(Math.abs(delta) / 50) + 1;
+
+      return sign * scalar * multiplier;
+    },
+
+    stopScroll_: function() {
+      this.scrollListener_ = null;
+      this.scrollMouseXY_ = null;
+    },
+
+    saveDrag: function() {
+      this.invalidate_();
+      this.layout();
+
+      var appIds = this.data.filter(function(id) {
+        return id != 'web-store-entry';
+      });
+
+      // Wait until the transitions are complete before notifying the browser.
+      // Otherwise, the apps will be re-rendered while still transitioning.
+      setTimeout(function() {
+        chrome.send('reorderApps', appIds);
+      }, this.transitionsDuration + 10);
+    },
+
+    layout: function(options) {
+      options = options || {};
+      if (!this.dirty_ && options.force != true)
+        return;
+
+      try {
+        var container = this.dragContainer;
+        if (options.disableAnimations)
+          container.setAttribute('launcher-animations', false);
+        var d0 = Date.now();
+        this.layoutImpl_();
+        this.dirty_ = false;
+        logEvent('apps.layout: ' + (Date.now() - d0));
+
+      } finally {
+        if (options.disableAnimations) {
+          // We need to re-enable animations asynchronously, so that the
+          // animations are still disabled for this layout update.
+          setTimeout(function() {
+            container.setAttribute('launcher-animations', true);
+          }, 0);
+        }
+      }
+    },
+
+    layoutImpl_: function() {
+      var apps = this.data;
+      var rects = this.getLayoutRects_(apps.length);
+      var appsContent = this.dragContainer;
+
+      if (!this.visible)
+        return;
+
+      for (var i = 0; i < apps.length; i++) {
+        var app = appsContent.querySelector('[app-id='+apps[i]+']').parentNode;
+
+        // If the node is being dragged, don't try to place it in the grid.
+        if (app == this.dragItem)
+          continue;
+
+        app.style.left = rects[i].left + 'px';
+        app.style.top = rects[i].top + 'px';
+      }
+
+      // We need to set the container's height manually because the apps use
+      // absolute positioning.
+      var rows = Math.ceil(apps.length / MAX_APPS_PER_ROW[layoutMode]);
+      appsContent.style.height = (rows * this.dimensions.height) + 'px';
+    },
+
+    getLayoutRects_: function(appCount) {
+      var availableWidth = this.dragContainer.offsetWidth;
+      var rtl = isRtl();
+      var rects = [];
+      var w = this.dimensions.width;
+      var h = this.dimensions.height;
+      var appsPerRow = MAX_APPS_PER_ROW[layoutMode];
+
+      for (var i = 0; i < appCount; i++) {
+        var top = Math.floor(i / appsPerRow) * h;
+        var left = (i % appsPerRow) * w;
+
+        // Reflect the X axis if an RTL language is active.
+        if (rtl)
+          left = availableWidth - left - w;
+        rects[i] = {left: left, top: top};
+      }
+      return rects;
+    },
+
     createElement: function(app) {
       var div = createElement(app);
       var a = div.firstChild;
@@ -341,7 +675,7 @@
         'name': localStrings.getString('web_store_title'),
         'launch_url': localStrings.getString('web_store_url')
       });
-      elm.setAttribute('app-id', 'web-store-entry');
+      elm.classList.add('web-store-entry');
       return elm;
     },
 
@@ -361,3 +695,6 @@
     }
   };
 })();
+
+// Enable drag and drop reordering of the app launcher.
+var appDragAndDrop = new DragAndDropController(apps);
diff --git a/chrome/browser/resources/ntp/drag_drop_controller.js b/chrome/browser/resources/ntp/drag_drop_controller.js
new file mode 100644
index 0000000..affa9de
--- /dev/null
+++ b/chrome/browser/resources/ntp/drag_drop_controller.js
@@ -0,0 +1,211 @@
+// Copyright (c) 2011 The Chromium 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 delegate interface:
+//   dragContainer -->
+//         element containing the draggable items
+//
+//   transitionsDuration -->
+//         length of time of transitions in ms
+//
+//   dragItem -->
+//         get / set property containing the item being dragged
+//
+//   getItem(e) -->
+//         get's the item that is under the mouse event |e|
+//
+//   canDropOn(coordinates) -->
+//         returns true if the coordinates (relative to the drag container)
+//         point to a valid place to drop an item
+//
+//   setDragPlaceholder(coordinates) -->
+//         tells the delegate that the dragged item is currently above
+//         the specified coordinates.
+//
+//   saveDrag() -->
+//         tells the delegate that the drag is done. move the item to the
+//         position last specified by setDragPlaceholder. (e.g., commit changes)
+//
+
+// The distance, in px, that the mouse must move before initiating a drag.
+var DRAG_THRESHOLD = 35;
+
+function DragAndDropController(delegate) {
+  this.delegate_ = delegate;
+
+  // Install the 'mousedown' handler, the entry point to drag and drop.
+  var el = this.delegate_.dragContainer;
+  el.addEventListener('mousedown', this.handleMouseDown_.bind(this));
+}
+
+DragAndDropController.prototype = {
+  isDragging_: false,
+  startItem_: null,
+  startItemXY_: null,
+  startMouseXY_: null,
+  mouseXY_: null,
+
+  // Enables the handlers that are only active during a drag.
+  enableHandlers_: function() {
+    // Record references to the generated functions so we can
+    // remove the listeners later.
+    this.mouseMoveListener_ = this.handleMouseMove_.bind(this);
+    this.mouseUpListener_ = this.handleMouseUp_.bind(this);
+    this.scrollListener_ = this.handleScroll_.bind(this);
+
+    document.addEventListener('mousemove', this.mouseMoveListener_, true);
+    document.addEventListener('mouseup', this.mouseUpListener_, true);
+    document.addEventListener('scroll', this.scrollListener_, true);
+  },
+
+  disableHandlers_: function() {
+    document.removeEventListener('mousemove', this.mouseMoveListener_, true);
+    document.removeEventListener('mouseup', this.mouseUpListener_, true);
+    document.removeEventListener('scroll', this.scrollListener_, true);
+  },
+
+  isDragging: function() {
+    return this.isDragging_;
+  },
+
+  distance_: function(p1, p2) {
+    var x2 = Math.pow(p1.x - p2.x, 2);
+    var y2 = Math.pow(p1.y - p2.y, 2);
+    return Math.sqrt(x2 + y2);
+  },
+
+  // Shifts the client coordinates, |xy|, so they are relative to the top left
+  // of the drag container.
+  getCoordinates_: function(xy) {
+    var rect = this.delegate_.dragContainer.getBoundingClientRect();
+    var coordinates = {
+      x: xy.x - rect.left,
+      y: xy.y - rect.top
+    };
+
+    // If we're in an RTL language, reflect the coordinates so the delegate
+    // doesn't need to worry about it.
+    if (isRtl())
+      coordinates.x = this.delegate_.dragContainer.offsetWidth - coordinates.x;
+
+    return coordinates;
+  },
+
+  // Listen to mousedown to get the relative position of the cursor when
+  // starting drag and drop.
+  handleMouseDown_: function(e) {
+    var item = this.delegate_.getItem(e);
+
+    // This can't be a drag & drop event if it's not the left mouse button
+    // or if the mouse is not above an item. We also bail out if the dragging
+    // flag is still set (the flag remains around for a bit so that 'click'
+    // event handlers can distinguish between a click and drag).
+    if (!item || e.button != 0 || this.isDragging())
+      return;
+
+    this.startItem_ = item;
+    this.startItemXY_ = {x: item.offsetLeft, y: item.offsetTop};
+    this.startMouseXY_ = {x: e.clientX, y: e.clientY};
+    this.startScrollXY_ = {x: window.scrollX, y: window.scrollY};
+
+    this.enableHandlers_();
+  },
+
+  handleMouseMove_: function(e) {
+    this.mouseXY_ = {x: e.clientX, y: e.clientY};
+
+    if (this.isDragging()) {
+      this.handleDrag_();
+      return;
+    }
+
+    // Initiate the drag if the mouse has moved far enough.
+    if (this.distance_(this.startMouseXY_, this.mouseXY_) >= DRAG_THRESHOLD)
+      this.handleDragStart_();
+  },
+
+  handleMouseUp_: function() {
+    this.handleDrop_();
+  },
+
+  handleScroll_: function(e) {
+    if (this.isDragging())
+      this.handleDrag_();
+  },
+
+  handleDragStart_: function() {
+    // Use the item that the mouse was above when 'mousedown' fired.
+    var item = this.startItem_;
+    if (!item)
+      return;
+
+    this.isDragging_ = true;
+    this.delegate_.dragItem = item;
+    item.classList.add('dragging');
+    item.style.zIndex = 2;
+  },
+
+  handleDragOver_: function() {
+    var coordinates = this.getCoordinates_(this.mouseXY_);
+    if (!this.delegate_.canDropOn(coordinates))
+      return;
+
+    this.delegate_.setDragPlaceholder(coordinates);
+  },
+
+  handleDrop_: function() {
+    this.disableHandlers_();
+
+    var dragItem = this.delegate_.dragItem;
+    if (!dragItem)
+      return;
+
+    this.delegate_.dragItem = this.startItem_ = null;
+    this.delegate_.saveDrag();
+    dragItem.classList.remove('dragging');
+
+    setTimeout(function() {
+      // Keep the flag around a little so other 'mouseup' and 'click'
+      // listeners know the event is from a drag operation.
+      this.isDragging_ = false;
+      dragItem.style.zIndex = 0;
+    }.bind(this), this.delegate_.transitionsDuration);
+  },
+
+  handleDrag_: function() {
+    // Moves the drag item making sure that it is not displayed outside the
+    // drag container.
+    var dragItem = this.delegate_.dragItem;
+    var dragContainer = this.delegate_.dragContainer;
+    var rect = dragContainer.getBoundingClientRect();
+
+    // First, move the item the same distance the mouse has moved.
+    var x = this.startItemXY_.x + this.mouseXY_.x - this.startMouseXY_.x +
+              window.scrollX - this.startScrollXY_.x;
+    var y = this.startItemXY_.y + this.mouseXY_.y - this.startMouseXY_.y +
+              window.scrollY - this.startScrollXY_.y;
+
+    var w = this.delegate_.dimensions.width;
+    var h = this.delegate_.dimensions.height;
+
+    var offset = parseInt(getComputedStyle(dragContainer).marginLeft);
+
+    // The position of the item is relative to the drag container. We
+    // want to make sure that half of the item's width or height is within
+    // the container.
+    x = Math.max(x, - w / 2 - offset);
+    x = Math.min(x, rect.width  + w / 2 - offset);
+
+    y = Math.max(- h / 2, y);
+    y = Math.min(y, rect.height - h / 2);
+
+    dragItem.style.left = x + 'px';
+    dragItem.style.top = y + 'px';
+
+    // Update the layouts and positions based on the new drag location.
+    this.handleDragOver_();
+
+    this.delegate_.scrollPage(this.mouseXY_);
+  }
+};
diff --git a/chrome/browser/resources/ntp/most_visited.css b/chrome/browser/resources/ntp/most_visited.css
index 2f875e2..cf930eb 100644
--- a/chrome/browser/resources/ntp/most_visited.css
+++ b/chrome/browser/resources/ntp/most_visited.css
@@ -274,6 +274,6 @@
   right: auto;
 }
 
-#most-visited:not(.hidden) #most-visited-settings.has-blacklist {
+#most-visited:not(.collapsed) #most-visited-settings.has-blacklist {
   visibility: visible;
 }
diff --git a/chrome/browser/resources/ntp/most_visited.js b/chrome/browser/resources/ntp/most_visited.js
index 1f8b740..183ad20 100644
--- a/chrome/browser/resources/ntp/most_visited.js
+++ b/chrome/browser/resources/ntp/most_visited.js
@@ -178,8 +178,8 @@
 
         // Now change the DOM.
         var removeText = localStrings.getString('thumbnailremovednotification');
-        var notifySpan = document.querySelector('#notification > span');
-        notifySpan.textContent = removeText;
+        var notifyMessageEl = document.querySelector('#notification > *');
+        notifyMessageEl.textContent = removeText;
 
         // Focus the undo link.
         var undoLink = document.querySelector(
@@ -620,7 +620,7 @@
         }
       }
       addClosedMenuFooter(
-          this.menu, 'most-visited', MINIMIZED_THUMB, Section.THUMB);
+          this.menu, 'most-visited', MENU_THUMB, Section.THUMB);
     },
 
     handleClick_: function(e) {
diff --git a/chrome/browser/resources/ntp/util.js b/chrome/browser/resources/ntp/util.js
deleted file mode 100644
index ebd1e4d..0000000
--- a/chrome/browser/resources/ntp/util.js
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(arv): Move to shared/js once namespaced and tested.
-
-var global = this;
-const IS_MAC = /^Mac/.test(navigator.platform);
-
-function $(id) {
-  return document.getElementById(id);
-}
-
-function url(s) {
-  // http://www.w3.org/TR/css3-values/#uris
-  // Parentheses, commas, whitespace characters, single quotes (') and double
-  // quotes (") appearing in a URI must be escaped with a backslash
-  var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
-  // WebKit has a bug when it comes to URLs that end with \
-  // https://bugs.webkit.org/show_bug.cgi?id=28885
-  if (/\\\\$/.test(s2)) {
-    // Add a space to work around the WebKit bug.
-    s2 += ' ';
-  }
-  return 'url("' + s2 + '")';
-}
-
-function findAncestorByClass(el, className) {
-  return findAncestor(el, function(el) {
-    if (el.classList)
-      return el.classList.contains(className);
-    return null;
-  });
-}
-
-/**
- * Return the first ancestor for which the {@code predicate} returns true.
- * @param {Node} node The node to check.
- * @param {function(Node) : boolean} predicate The function that tests the
- *     nodes.
- * @return {Node} The found ancestor or null if not found.
- */
-function findAncestor(node, predicate) {
-  var last = false;
-  while (node != null && !(last = predicate(node))) {
-    node = node.parentNode;
-  }
-  return last ? node : null;
-}
-
-function swapDomNodes(a, b) {
-  var afterA = a.nextSibling;
-  if (afterA == b) {
-    swapDomNodes(b, a);
-    return;
-  }
-  var aParent = a.parentNode;
-  b.parentNode.replaceChild(a, b);
-  aParent.insertBefore(b, afterA);
-}
-
-/**
- * Calls chrome.send with a callback and restores the original afterwards.
- */
-function chromeSend(name, params, callbackName, callback) {
-  var old = global[callbackName];
-  global[callbackName] = function() {
-    // restore
-    global[callbackName] = old;
-
-    var args = Array.prototype.slice.call(arguments);
-    return callback.apply(global, args);
-  };
-  chrome.send(name, params);
-}
-
-
diff --git a/chrome/browser/resources/options/OWNERS b/chrome/browser/resources/options/OWNERS
new file mode 100644
index 0000000..67257e6
--- /dev/null
+++ b/chrome/browser/resources/options/OWNERS
@@ -0,0 +1,4 @@
+csilv@chromium.org
+estade@chromium.org
+jhawkins@chromium.org
+stuartmorgan@chromium.org
diff --git a/chrome/browser/resources/options/about_page.js b/chrome/browser/resources/options/about_page.js
index 8fc57a0..7ca613f 100644
--- a/chrome/browser/resources/options/about_page.js
+++ b/chrome/browser/resources/options/about_page.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,7 +15,8 @@
    * Encapsulated handling of about page.
    */
   function AboutPage() {
-    OptionsPage.call(this, 'about', templateData.aboutPage, 'aboutPage');
+    OptionsPage.call(this, 'about', templateData.aboutPageTabTitle,
+                     'aboutPage');
   }
 
   cr.addSingletonGetter(AboutPage);
@@ -51,7 +52,7 @@
         $('aboutPageMoreInfo').classList.remove('hidden');
       };
 
-      if (cr.commandLine.options['--bwsi']) {
+      if (!AccountsOptions.currentUserIsOwner()) {
         $('channelSelect').disabled = true;
       } else {
         $('channelSelect').onchange = function(event) {
diff --git a/chrome/browser/resources/options/add_startup_page_overlay.css b/chrome/browser/resources/options/add_startup_page_overlay.css
index a863eb6..392a60d 100644
--- a/chrome/browser/resources/options/add_startup_page_overlay.css
+++ b/chrome/browser/resources/options/add_startup_page_overlay.css
@@ -19,15 +19,31 @@
   -webkit-box-flex: 1;
 }
 
-#addStartupRecentPageList .url {
-  display: none;
+#addStartupRecentPageList {
+  height: 320px;
+}
+
+#addStartupRecentPageList .vertical-center {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  width: 100%;
+  white-space: nowrap;
   color: hsl(0, 0%, 70%);
+}
+
+#addStartupRecentPageList .title {
+  box-sizing: border-box;
+  color: black;
+  display: inline-block;
+  max-width: 100%;
+}
+
+#addStartupRecentPageList .url {
   -webkit-padding-start: 3ex;
 }
 
-#addStartupRecentPageList > :hover > .url,
-#addStartupRecentPageList > [selected] > .url {
-  display: inline;
+#addStartupRecentPageList > :not(:hover):not([selected]) > .url,
+  display: none;
 }
 
 #addStartupPageOverlay .action-area {
diff --git a/chrome/browser/resources/options/add_startup_page_overlay.html b/chrome/browser/resources/options/add_startup_page_overlay.html
index c2f97d2..691399b 100644
--- a/chrome/browser/resources/options/add_startup_page_overlay.html
+++ b/chrome/browser/resources/options/add_startup_page_overlay.html
@@ -1,18 +1,19 @@
 <div class="page hidden" id="addStartupPageOverlay">
-  <h1 i18n-content="addStartupPageTitle"></h1>
-
+  <h1 i18n-content="addStartupPage"></h1>
   <form id="addStartupPageForm">
-    <label id="addURLBlock"><span
-        i18n-content="addStartupPageURLLabel"></span>
-      <input type="url" id="addStartupPageURL"></label>
-
-    <list id="addStartupRecentPageList"></list>
-
-    <div class="action-area button-strip">
-      <button type="reset"
-          i18n-content="addStartupPageCancelButton"></button>
-      <button type="submit" id="addStartupPageAddButton" disabled
-          i18n-content="addStartupPageAddButton"></button>
+    <div class="content-area">
+      <label id="addURLBlock"><span
+          i18n-content="addStartupPageURLLabel"></span>
+        <input id="addStartupPageURL" type="text"></label>
+      <list id="addStartupRecentPageList"></list>
+    </div>
+    <div class="action-area">
+      <div class="button-strip">
+        <button type="reset"
+            i18n-content="addStartupPageCancelButton"></button>
+        <button type="submit" id="addStartupPageAddButton" disabled
+            i18n-content="addStartupPageAddButton"></button>
+      </div>
     </div>
   </form>
 </div>
diff --git a/chrome/browser/resources/options/add_startup_page_overlay.js b/chrome/browser/resources/options/add_startup_page_overlay.js
index 659ef3b..4678629 100644
--- a/chrome/browser/resources/options/add_startup_page_overlay.js
+++ b/chrome/browser/resources/options/add_startup_page_overlay.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
    */
   function AddStartupPageOverlay() {
     OptionsPage.call(this, 'addStartupPageOverlay',
-                     templateData.addStartupPageTitle,
+                     templateData.addStartupPageTabTitle,
                      'addStartupPageOverlay');
   }
 
@@ -34,7 +34,7 @@
       addForm.onreset = this.dismissOverlay_.bind(this);
       addForm.onsubmit =  function(e) {
         var urlField = $('addStartupPageURL');
-        StartupPageManager.addStartupPage(urlField.value);
+        BrowserOptions.addStartupPage(urlField.value);
 
         self.dismissOverlay_();
         return false;
@@ -65,8 +65,9 @@
      */
     dismissOverlay_: function() {
       $('addStartupPageURL').value = '';
+      $('addStartupRecentPageList').selectionModel.unselectAll();
       this.updateAddButtonState_();
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
     },
 
     /**
@@ -110,6 +111,12 @@
       $('addStartupPageURL').value = url;
       this.updateAddButtonState_();
     },
+
+    /** @inheritDoc */
+    canShowPage: function() {
+      return BrowserOptions.getInstance().
+          shouldEnableCustomStartupPageControls();
+    },
   };
 
   AddStartupPageOverlay.updateRecentPageList = function(pages) {
diff --git a/chrome/browser/resources/options/add_startup_page_recent_pages_list.js b/chrome/browser/resources/options/add_startup_page_recent_pages_list.js
index ff080f6..95be30c 100644
--- a/chrome/browser/resources/options/add_startup_page_recent_pages_list.js
+++ b/chrome/browser/resources/options/add_startup_page_recent_pages_list.js
@@ -35,19 +35,23 @@
     decorate: function() {
       ListItem.prototype.decorate.call(this);
 
+      var wrapperEl = this.ownerDocument.createElement('div');
+      wrapperEl.className = 'vertical-center';
+      this.appendChild(wrapperEl);
+
       var titleEl = this.ownerDocument.createElement('span');
       titleEl.className = 'title';
       titleEl.classList.add('favicon-cell');
       titleEl.style.backgroundImage = url('chrome://favicon/' +
                                           this.pageInfo['url']);
-      this.appendChild(titleEl);
+      wrapperEl.appendChild(titleEl);
       if (this.pageInfo['title'].length > 0) {
         titleEl.textContent = this.pageInfo['title'];
 
         var urlEL = this.ownerDocument.createElement('span');
         urlEL.className = 'url';
         urlEL.textContent = this.pageInfo['displayURL'];
-        this.appendChild(urlEL);
+        wrapperEl.appendChild(urlEL);
       } else {
         titleEl.textContent = this.pageInfo['displayURL'];
       }
diff --git a/chrome/browser/resources/options/advanced_options.css b/chrome/browser/resources/options/advanced_options.css
index b897168..6f40b5b 100644
--- a/chrome/browser/resources/options/advanced_options.css
+++ b/chrome/browser/resources/options/advanced_options.css
@@ -1,9 +1,42 @@
 /*
- * Copyright (c) 2010 The Chromium Authors. All rights reserved.
+ * Copyright (c) 2011 The Chromium Authors. All rights reserved.
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-.informational-text {
+#advancedPage .informational-text {
   color: grey;
 }
+
+#advancedPage > section > div:only-of-type > label.checkbox {
+  margin: 10px 0;
+}
+
+#advancedPage .section-group {
+  margin: 10px 0;
+}
+
+#advancedPage select,
+#advancedPage .web-content-select-label {
+  min-width: 145px;
+}
+
+#advancedPage .web-content-select-label > span:only-of-type {
+  display: inline-block;
+  min-width: 100px;
+}
+
+#download-location-group {
+  margin: 10px 0 5px;
+  min-width: 700px;
+}
+
+#promptForDownload {
+  margin-bottom: 10px;
+}
+
+#fontSettingsCustomizeFontsButton,
+#gearSettingsConfigureGearsButton,
+#privacyClearDataButton {
+  margin-left: 10px;
+}
diff --git a/chrome/browser/resources/options/advanced_options.html b/chrome/browser/resources/options/advanced_options.html
index 50e18cd..1f096b9 100644
--- a/chrome/browser/resources/options/advanced_options.html
+++ b/chrome/browser/resources/options/advanced_options.html
@@ -1,9 +1,9 @@
-<div class="page hidden" id="advancedPage">
+<div id="advancedPage" class="page hidden">
   <h1 i18n-content="advancedPage"></h1>
   <section>
     <h3 i18n-content="advancedSectionTitlePrivacy"></h3>
     <div>
-      <div>
+      <div class="section-group">
         <button id="privacyContentSettingsButton"
             i18n-content="privacyContentSettingsButton"></button>
         <button id="privacyClearDataButton"
@@ -56,15 +56,8 @@
   <section>
     <h3 i18n-content="advancedSectionTitleContent"></h3>
     <div>
-<if expr="os == 'darwin'">
-      <label class="checkbox">
-        <input id="tabsToLinksPref" pref="webkit.webprefs.tabs_to_links"
-            metric="Options_TabsToLinks" type="checkbox">
-        <span i18n-content="tabsToLinksPref"></span>
-      </label>
-</if>
-      <div>
-        <label>
+      <div class="section-group">
+        <label class="web-content-select-label">
           <span i18n-content="defaultFontSizeLabel"></span>
           <select id="defaultFontSize">
             <option value="9" i18n-content="fontSizeLabelVerySmall"></option>
@@ -77,10 +70,11 @@
         <button id="fontSettingsCustomizeFontsButton"
             i18n-content="fontSettingsCustomizeFontsButton"></button>
       </div>
-      <div>
-        <label>
+      <div class="section-group">
+        <label class="web-content-select-label">
           <span i18n-content="defaultZoomLevelLabel"></span>
-          <select id="defaultZoomLevel">
+          <select id="defaultZoomLevel" pref="profile.default_zoom_level"
+                  dataType="double" metric="Options_ChangeDefaultZoomLevel">
             <option value="-3">57%</option>
             <option value="-2">69%</option>
             <option value="-1">83%</option>
@@ -94,23 +88,37 @@
           </select>
         </label>
       </div>
+<if expr="not pp_ifdef('chromeos') or os == 'win32'">
+      <div class="section-group">
+</if>
+<if expr="not pp_ifdef('chromeos')">
+        <button id="language-button"
+            i18n-content="languageAndSpellCheckSettingsButton"></button>
+</if>
 <if expr="os == 'win32'">
-      <div>
-        <label style="display:inline;">
-          <span i18n-content="gearSettingsGroupName"></span>
-          <button id="gearSettingsConfigureGearsButton"
-              i18n-content="gearSettingsConfigureGearsButton"></button>
-        </label>
+        <button id="gearSettingsConfigureGearsButton"
+            i18n-content="gearSettingsConfigureGearsButton"></button>
+</if>
+<if expr="not pp_ifdef('chromeos') or os == 'win32'">
       </div>
 </if>
+<if expr="os == 'darwin'">
+      <label class="checkbox">
+        <input id="tabsToLinksPref" pref="webkit.webprefs.tabs_to_links"
+            metric="Options_TabsToLinks" type="checkbox">
+        <span i18n-content="tabsToLinksPref"></span>
+      </label>
+</if>
     </div>
   </section>
   <section>
     <h3 i18n-content="advancedSectionTitleNetwork"></h3>
     <div>
       <div id="proxiesLabel"></div>
-      <button id="proxiesConfigureButton"
-          i18n-content="proxiesConfigureButton"></button>
+      <div class="section-group">
+        <button id="proxiesConfigureButton"
+            i18n-content="proxiesConfigureButton"></button>
+      </div>
     </div>
   </section>
   <section>
@@ -123,11 +131,11 @@
       </label>
     </div>
   </section>
+<if expr="not pp_ifdef('chromeos')">
   <section>
     <h3 i18n-content="downloadLocationGroupName"></h3>
     <div>
-<if expr="not pp_ifdef('chromeos')">
-      <div>
+      <div id="download-location-group">
         <label>
           <span i18n-content="downloadLocationBrowseTitle"></span>
           <input id="downloadLocationPath" type="text" size="60" disabled>
@@ -140,12 +148,15 @@
             metric="Options_AskForSaveLocation" type="checkbox">
         <span i18n-content="downloadLocationAskForSaveLocation"></span>
       </label>
-</if>
-      <div i18n-content="autoOpenFileTypesInfo"></div>
-      <div><button id="autoOpenFileTypesResetToDefault"
-          i18n-content="autoOpenFileTypesResetToDefault"></button></div>
+      <div id="auto-open-file-types-label"
+          i18n-content="autoOpenFileTypesInfo"></div>
+      <div class="section-group">
+        <button id="autoOpenFileTypesResetToDefault"
+            i18n-content="autoOpenFileTypesResetToDefault"></button>
+      </div>
     </div>
   </section>
+</if>
   <section>
     <h3 i18n-content="advancedSectionTitleSecurity"></h3>
     <div>
@@ -166,8 +177,8 @@
         <span i18n-content="sslUseTLS1"></span>
       </label>
 </if>
-<if expr="not pp_ifdef('chromeos') and (os == 'linux2' or os.find('bsd') != -1)">
-      <!-- Configure these options for Linux/BSD as preference keys -->
+<if expr="os == 'linux2' or os.find('bsd') != -1">
+      <!-- Configure these options for CrOS/Linux/BSD as preference keys -->
       <label class="checkbox">
         <input id="sslCheckRevocation" pref="ssl.rev_checking.enabled"
             metric="Options_CheckCertRevocation" type="checkbox">
@@ -192,7 +203,7 @@
     <div>
       <div id="cloudPrintProxyLabel"
            i18n-content="cloudPrintProxyDisabledLabel"></div>
-      <div>
+      <div class="section-group">
         <button id="cloudPrintProxySetupButton"
                 i18n-content="cloudPrintProxyDisabledButton"></button>
         <button id="cloudPrintProxyManageButton"
@@ -201,11 +212,20 @@
     </div>
   </section>
 </if>
+<if expr="pp_ifdef('remoting') and not pp_ifdef('chromeos')">
   <section id="remoting-section">
     <h3 i18n-content="advancedSectionTitleRemoting"></h3>
     <div>
-      <button id="remotingSetupButton"
-              i18n-content="remotingSetupButton"></button>
+      <div id="remotingStatus" class="section-text"></div>
+      <div class="section-group">
+        <button id="remotingSetupButton"
+                i18n-content="remotingSetupButton"
+                style="display:none;"></button>
+        <button id="remotingStopButton"
+                i18n-content="remotingStopButton"
+                style="display:none;"></button>
+      </div>
     </div>
   </section>
+</if>
 </div>
diff --git a/chrome/browser/resources/options/advanced_options.js b/chrome/browser/resources/options/advanced_options.js
index 8133d7b..97eaff0 100644
--- a/chrome/browser/resources/options/advanced_options.js
+++ b/chrome/browser/resources/options/advanced_options.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,7 @@
   // Encapsulated handling of advanced options page.
   //
   function AdvancedOptions() {
-    OptionsPage.call(this, 'advanced', templateData.advancedPage,
+    OptionsPage.call(this, 'advanced', templateData.advancedPageTabTitle,
                      'advancedPage');
   }
 
@@ -30,13 +30,13 @@
 
       // Set up click handlers for buttons.
       $('privacyContentSettingsButton').onclick = function(event) {
-        OptionsPage.showPageByName('content');
+        OptionsPage.navigateToPage('content');
         OptionsPage.showTab($('cookies-nav-tab'));
         chrome.send('coreOptionsUserMetricsAction',
             ['Options_ContentSettings']);
       };
       $('privacyClearDataButton').onclick = function(event) {
-        OptionsPage.showOverlay('clearBrowserDataOverlay');
+        OptionsPage.navigateToPage('clearBrowserData');
         chrome.send('coreOptionsUserMetricsAction', ['Options_ClearData']);
       };
 
@@ -49,21 +49,25 @@
         };
       }
 
-      $('autoOpenFileTypesResetToDefault').onclick = function(event) {
-        chrome.send('autoOpenFileTypesAction');
-      };
+      if (!cr.isChromeOS) {
+        $('autoOpenFileTypesResetToDefault').onclick = function(event) {
+          chrome.send('autoOpenFileTypesAction');
+        };
+      }
+
       $('fontSettingsCustomizeFontsButton').onclick = function(event) {
-        OptionsPage.showPageByName('fontSettings');
+        OptionsPage.navigateToPage('fontSettings');
         chrome.send('coreOptionsUserMetricsAction', ['Options_FontSettings']);
       };
-      $('defaultZoomLevel').onchange = function(event) {
-        chrome.send('defaultZoomLevelAction',
-            [String(event.target.options[event.target.selectedIndex].value)]);
-      };
       $('defaultFontSize').onchange = function(event) {
         chrome.send('defaultFontSizeAction',
             [String(event.target.options[event.target.selectedIndex].value)]);
       };
+      $('language-button').onclick = function(event) {
+        OptionsPage.navigateToPage('language');
+        chrome.send('coreOptionsUserMetricsAction',
+            ['Options_LanuageAndSpellCheckSettings']);
+      };
 
       if (cr.isWindows || cr.isMac) {
         $('certificatesManageButton').onclick = function(event) {
@@ -71,7 +75,7 @@
         };
       } else {
         $('certificatesManageButton').onclick = function(event) {
-          OptionsPage.showPageByName('certificateManager');
+          OptionsPage.navigateToPage('certificateManager');
           OptionsPage.showTab($('personal-certs-nav-tab'));
           chrome.send('coreOptionsUserMetricsAction',
                       ['Options_ManageSSLCertificates']);
@@ -94,7 +98,7 @@
                 'downloadLocationChangeButton');
       } else {
         $('proxiesConfigureButton').onclick = function(event) {
-          OptionsPage.showPageByName('proxy');
+          OptionsPage.navigateToPage('proxy');
           chrome.send('coreOptionsUserMetricsAction',
               ['Options_ShowProxySettings']);
         };
@@ -138,10 +142,15 @@
         };
       }
 
-      $('remotingSetupButton').onclick = function(event) {
-        chrome.send('showRemotingSetupDialog');
+      if ($('remotingSetupButton')) {
+          $('remotingSetupButton').onclick = function(event) {
+              chrome.send('showRemotingSetupDialog');
+          }
+          $('remotingStopButton').onclick = function(event) {
+              chrome.send('disableRemoting');
+          }
       }
-    }
+  }
   };
 
   //
@@ -165,18 +174,6 @@
     }
   }
 
-  // Set the default zoom level selected item.
-  AdvancedOptions.SetDefaultZoomLevel = function(value) {
-    var selectCtl = $('defaultZoomLevel');
-    for (var i = 0; i < selectCtl.options.length; i++) {
-      if (selectCtl.options[i].value == value) {
-        selectCtl.selectedIndex = i;
-        return;
-      }
-    }
-    selectCtl.selectedIndex = 4;  // 100%
-  };
-
   // Set the font size selected item.
   AdvancedOptions.SetFontSize = function(fixed_font_size_value,
       font_size_value) {
@@ -210,7 +207,14 @@
 
   // Set the enabled state for the autoOpenFileTypesResetToDefault button.
   AdvancedOptions.SetAutoOpenFileTypesDisabledAttribute = function(disabled) {
-    $('autoOpenFileTypesResetToDefault').disabled = disabled;
+    if (!cr.isChromeOS) {
+      $('autoOpenFileTypesResetToDefault').disabled = disabled;
+
+      if (disabled)
+        $('auto-open-file-types-label').classList.add('disabled');
+      else
+        $('auto-open-file-types-label').classList.remove('disabled');
+    }
   };
 
   // Set the enabled state for the proxy settings button.
@@ -239,10 +243,11 @@
   };
 
   // Set the Cloud Print proxy UI to enabled, disabled, or processing.
-  AdvancedOptions.SetupCloudPrintProxySection = function(disabled, label) {
+  AdvancedOptions.SetupCloudPrintProxySection = function(
+        disabled, label, allowed) {
     if (!cr.isChromeOS) {
       $('cloudPrintProxyLabel').textContent = label;
-      if (disabled) {
+      if (disabled || !allowed) {
         $('cloudPrintProxySetupButton').textContent =
           localStrings.getString('cloudPrintProxyDisabledButton');
         $('cloudPrintProxyManageButton').style.display = 'none';
@@ -251,20 +256,33 @@
           localStrings.getString('cloudPrintProxyEnabledButton');
         $('cloudPrintProxyManageButton').style.display = 'inline';
       }
-      $('cloudPrintProxySetupButton').disabled = false;
+      $('cloudPrintProxySetupButton').disabled = !allowed;
     }
   };
 
   AdvancedOptions.RemoveCloudPrintProxySection = function() {
     if (!cr.isChromeOS) {
       var proxySectionElm = $('cloud-print-proxy-section');
-      proxySectionElm.parentNode.removeChild(proxySectionElm);
+      if (proxySectionElm)
+        proxySectionElm.parentNode.removeChild(proxySectionElm);
     }
   };
 
+  AdvancedOptions.SetRemotingStatus = function(enabled, status) {
+    if (enabled) {
+      $('remotingSetupButton').style.display = 'none';
+      $('remotingStopButton').style.display = 'inline';
+    } else {
+      $('remotingSetupButton').style.display = 'inline';
+      $('remotingStopButton').style.display = 'none';
+    }
+    $('remotingStatus').textContent = status;
+  };
+
   AdvancedOptions.RemoveRemotingSection = function() {
     var proxySectionElm = $('remoting-section');
-    proxySectionElm.parentNode.removeChild(proxySectionElm);
+    if (proxySectionElm)
+      proxySectionElm.parentNode.removeChild(proxySectionElm);
   };
 
   // Export
diff --git a/chrome/browser/resources/options/alert_overlay.html b/chrome/browser/resources/options/alert_overlay.html
index 7512077..e1dbfc3 100644
--- a/chrome/browser/resources/options/alert_overlay.html
+++ b/chrome/browser/resources/options/alert_overlay.html
@@ -1,8 +1,12 @@
 <div class="page hidden" id="alertOverlay">
   <h1 id="alertOverlayTitle"></h1>
-  <div id="alertOverlayMessage"></div>
-  <div class="action-area button-strip">
-    <button type="reset" id="alertOverlayCancel"></button>
-    <button type="submit" id="alertOverlayOk"></button>
+  <div class="content-area">
+    <div id="alertOverlayMessage"></div>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="reset" id="alertOverlayCancel"></button>
+      <button type="submit" id="alertOverlayOk"></button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/alert_overlay.js b/chrome/browser/resources/options/alert_overlay.js
index 9274a3b..eb1fb8e 100644
--- a/chrome/browser/resources/options/alert_overlay.js
+++ b/chrome/browser/resources/options/alert_overlay.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 cr.define('options', function() {
-
   var OptionsPage = options.OptionsPage;
 
   /**
@@ -22,6 +21,13 @@
     __proto__: OptionsPage.prototype,
 
     /**
+     * Whether the page can be shown. Used to make sure the page is only
+     * shown via AlertOverlay.Show(), and not via the address bar.
+     * @private
+     */
+    canShow_: false,
+
+    /**
      * Initialize the page.
      */
     initializePage: function() {
@@ -44,7 +50,7 @@
      * @private
      */
     handleOK_: function() {
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
       if (this.okCallback != undefined) {
         this.okCallback.call();
       }
@@ -56,11 +62,23 @@
      * @private
      */
     handleCancel_: function() {
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
       if (this.cancelCallback != undefined) {
         this.cancelCallback.call();
       }
-    }
+    },
+
+    /**
+     * The page is getting hidden. Don't let it be shown again.
+     */
+    willHidePage: function() {
+      canShow_ = false;
+    },
+
+    /** @inheritDoc */
+    canShowPage: function() {
+      return this.canShow_;
+    },
   };
 
   /**
@@ -109,15 +127,18 @@
       $('alertOverlayCancel').style.display = 'none';
     }
 
-    AlertOverlay.getInstance().okCallback = okCallback;
-    AlertOverlay.getInstance().cancelCallback = cancelCallback;
+    var alertOverlay = AlertOverlay.getInstance();
+    alertOverlay.okCallback = okCallback;
+    alertOverlay.cancelCallback = cancelCallback;
+    alertOverlay.canShow_ = true;
 
-    OptionsPage.showOverlay('alertOverlay');
+    // Intentionally don't show the URL in the location bar as we don't want
+    // people trying to navigate here by hand.
+    OptionsPage.showPageByName('alertOverlay', false);
   }
 
   // Export
   return {
     AlertOverlay: AlertOverlay
   };
-
 });
diff --git a/chrome/browser/resources/options/autofill_edit_address_overlay.html b/chrome/browser/resources/options/autofill_edit_address_overlay.html
index 9528ccf..ba66968 100644
--- a/chrome/browser/resources/options/autofill_edit_address_overlay.html
+++ b/chrome/browser/resources/options/autofill_edit_address_overlay.html
@@ -1,103 +1,101 @@
 <div class="page hidden" id="autoFillEditAddressOverlay">
   <h1 id="autoFillAddressTitle"></h1>
-
-  <div class="input">
-    <label id="fullNameLabel">
-      <div><span i18n-content="fullNameLabel"></span></div>
-      <input type="text" class="form" class="form" id="fullName">
-    </label>
-  </div>
-  <div class="input">
-    <label id="companyNameLabel">
-      <div><span i18n-content="companyNameLabel"></span></div>
-      <input type="text" class="form" class="form" id="companyName">
-    </label>
-  </div>
-  <div class="input">
-    <label id="addrLine1Label">
-      <div><span i18n-content="addrLine1Label"></span></div>
-      <input type="text" class="form" class="form" id="addrLine1">
-    </label>
-  </div>
-  <div class="input">
-    <label id="addrLine2Label">
-      <div><span i18n-content="addrLine2Label"></span></div>
-      <input type="text" class="form" class="form" id="addrLine2">
-    </label>
-  </div>
-
-  <div class="table">
-    <div class="row">
-      <div class="input cell">
-        <label id="cityLabel" for="city">
-          <span i18n-content="cityLabel"></span>
-        </label>
+  <div class="content-area">
+    <div class="input">
+      <label id="fullNameLabel">
+        <div><span i18n-content="fullNameLabel"></span></div>
+        <input type="text" class="form" class="form" id="fullName">
+      </label>
+    </div>
+    <div class="input">
+      <label id="companyNameLabel">
+        <div><span i18n-content="companyNameLabel"></span></div>
+        <input type="text" class="form" class="form" id="companyName">
+      </label>
+    </div>
+    <div class="input">
+      <label id="addrLine1Label">
+        <div><span i18n-content="addrLine1Label"></span></div>
+        <input type="text" class="form" class="form" id="addrLine1">
+      </label>
+    </div>
+    <div class="input">
+      <label id="addrLine2Label">
+        <div><span i18n-content="addrLine2Label"></span></div>
+        <input type="text" class="form" class="form" id="addrLine2">
+      </label>
+    </div>
+    <div class="table">
+      <div class="row">
+        <div class="input cell">
+          <label id="cityLabel" for="city">
+            <span i18n-content="cityLabel"></span>
+          </label>
+        </div>
+        <div class="input cell">
+          <label id="stateLabel" for="state">
+            <span i18n-content="stateLabel"></span>
+          </label>
+        </div>
+        <div class="input cell">
+          <label id="zipCodeLabel" for="zipCode">
+            <span i18n-content="zipCodeLabel"></span>
+          </label>
+        </div>
       </div>
-      <div class="input cell">
-        <label id="stateLabel" for="state">
-          <span i18n-content="stateLabel"></span>
-        </label>
-      </div>
-      <div class="input cell">
-        <label id="zipCodeLabel" for="zipCode">
-          <span i18n-content="zipCodeLabel"></span>
-        </label>
+      <div class="row">
+        <div class="input cell">
+          <input type="text" class="form" id="city">
+        </div>
+        <div class="input cell">
+          <input type="text" class="form" id="state">
+        </div>
+        <div class="input cell">
+          <input type="text" class="form" id="zipCode">
+        </div>
       </div>
     </div>
-    <div class="row">
-      <div class="input cell">
-        <input type="text" class="form" id="city">
+    <div class="input">
+      <label id="countryLabel">
+        <div><span i18n-content="countryLabel"></span></div>
+        <input type="text" class="form" class="form" id="country">
+      </label>
+    </div>
+    <div class="table">
+      <div class="row">
+        <div class="input cell">
+          <label id="phoneLabel" for="phone">
+            <span i18n-content="phoneLabel"></span>
+          </label>
+        </div>
+        <div class="input cell">
+          <label id="faxLabel" for="fax">
+            <span i18n-content="faxLabel"></span>
+          </label>
+        </div>
       </div>
-      <div class="input cell">
-        <input type="text" class="form" id="state">
-      </div>
-      <div class="input cell">
-        <input type="text" class="form" id="zipCode">
+      <div class="row">
+        <div class="input cell">
+          <input type="text" class="form" class="form" id="phone">
+        </div>
+        <div class="input cell">
+          <input type="text" class="form" class="form" id="fax">
+        </div>
       </div>
     </div>
-  </div>
-
-  <div class="input">
-    <label id="countryLabel">
-      <div><span i18n-content="countryLabel"></span></div>
-      <input type="text" class="form" class="form" id="country">
-    </label>
-  </div>
-
-  <div class="table">
-    <div class="row">
-      <div class="input cell">
-        <label id="phoneLabel" for="phone">
-          <span i18n-content="phoneLabel"></span>
-        </label>
-      </div>
-      <div class="input cell">
-        <label id="faxLabel" for="fax">
-          <span i18n-content="faxLabel"></span>
-        </label>
-      </div>
-    </div>
-    <div class="row">
-      <div class="input cell">
-        <input type="text" class="form" class="form" id="phone">
-      </div>
-      <div class="input cell">
-        <input type="text" class="form" class="form" id="fax">
-      </div>
+    <div class="input">
+      <label id="emailLabel">
+        <div><span i18n-content="emailLabel"></span></div>
+        <input type="text" class="form" class="form" id="email">
+      </label>
     </div>
   </div>
-
-  <div class="input">
-    <label id="emailLabel">
-      <div><span i18n-content="emailLabel"></span></div>
-      <input type="text" class="form" class="form" id="email">
-    </label>
-  </div>
-
-  <div class="action-area button-strip">
-    <button type="reset" id="autoFillEditAddressCancelButton"
-            i18n-content="cancel"></button>
-    <button type="submit" id="autoFillEditAddressApplyButton" disabled
-            i18n-content="ok"></button>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="reset" id="autoFillEditAddressCancelButton"
+          i18n-content="cancel"></button>
+      <button type="submit" id="autoFillEditAddressApplyButton" disabled
+          i18n-content="ok"></button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/autofill_edit_address_overlay.js b/chrome/browser/resources/options/autofill_edit_address_overlay.js
index 5794daa..fe461f3 100644
--- a/chrome/browser/resources/options/autofill_edit_address_overlay.js
+++ b/chrome/browser/resources/options/autofill_edit_address_overlay.js
@@ -52,7 +52,7 @@
     dismissOverlay_: function() {
       this.clearInputFields_();
       this.guid = '';
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
     },
 
     /**
@@ -173,5 +173,4 @@
   return {
     AutoFillEditAddressOverlay: AutoFillEditAddressOverlay
   };
-
 });
diff --git a/chrome/browser/resources/options/autofill_edit_creditcard_overlay.html b/chrome/browser/resources/options/autofill_edit_creditcard_overlay.html
index 6b2f30d..13cacd2 100644
--- a/chrome/browser/resources/options/autofill_edit_creditcard_overlay.html
+++ b/chrome/browser/resources/options/autofill_edit_creditcard_overlay.html
@@ -1,32 +1,32 @@
 <div class="page hidden" id="autoFillEditCreditCardOverlay">
   <h1 id="autoFillCreditCardTitle"></h1>
-
-  <div>
-    <label id="nameOnCardLabel">
-      <span i18n-content="nameOnCardLabel"></span><br>
-      <input type="text" id="nameOnCard">
-    </label>
+  <div class="content-area">
+    <div>
+      <label id="nameOnCardLabel">
+        <span i18n-content="nameOnCardLabel"></span><br>
+        <input type="text" id="nameOnCard">
+      </label>
+    </div>
+    <div>
+      <label id="creditCardNumberLabel">
+        <span i18n-content="creditCardNumberLabel"></span><br>
+        <input type="text" id="creditCardNumber">
+      </label>
+    </div>
+    <div>
+      <label id="creditCardExpirationDateLabel">
+        <span i18n-content="creditCardExpirationDateLabel"></span><br>
+        <select id="expirationMonth"></select>
+        <select id="expirationYear"></select>
+      </label>
+    </div>
   </div>
-
-  <div>
-    <label id="creditCardNumberLabel">
-      <span i18n-content="creditCardNumberLabel"></span><br>
-      <input type="text" id="creditCardNumber">
-    </label>
-  </div>
-
-  <div>
-    <label id="creditCardExpirationDateLabel">
-      <span i18n-content="creditCardExpirationDateLabel"></span><br>
-      <select id="expirationMonth"></select>
-      <select id="expirationYear"></select>
-    </label>
-  </div>
-
-  <div class="action-area button-strip">
-    <button type="reset" id="autoFillEditCreditCardCancelButton"
-        i18n-content="cancel"></button>
-    <button type="submit" id="autoFillEditCreditCardApplyButton" disabled
-        i18n-content="ok"></button>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="reset" id="autoFillEditCreditCardCancelButton"
+          i18n-content="cancel"></button>
+      <button type="submit" id="autoFillEditCreditCardApplyButton" disabled
+          i18n-content="ok"></button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/autofill_edit_creditcard_overlay.js b/chrome/browser/resources/options/autofill_edit_creditcard_overlay.js
index c61255e..aaab39c 100644
--- a/chrome/browser/resources/options/autofill_edit_creditcard_overlay.js
+++ b/chrome/browser/resources/options/autofill_edit_creditcard_overlay.js
@@ -6,7 +6,15 @@
   const OptionsPage = options.OptionsPage;
 
   // The GUID of the loaded credit card.
-  var guid;
+  var guid_;
+
+  // The CC number of the profile, used to check for changes to the input field.
+  var storedCCNumber_;
+
+  // Set to true if the user has edited the CC number field. When saving the
+  // CC profile after editing, the stored CC number is saved if the input field
+  // has not been modified.
+  var hasEditedNumber_;
 
   /**
    * AutoFillEditCreditCardOverlay class
@@ -39,7 +47,9 @@
         self.dismissOverlay_();
       }
 
-      self.guid = '';
+      self.guid_ = '';
+      self.storedCCNumber_ = '';
+      self.hasEditedNumber_ = false;
       self.clearInputFields_();
       self.connectInputEvents_();
       self.setDefaultSelectOptions_();
@@ -51,8 +61,10 @@
      */
     dismissOverlay_: function() {
       this.clearInputFields_();
-      this.guid = '';
-      OptionsPage.clearOverlays();
+      this.guid_ = '';
+      this.storedCCNumber_ = '';
+      this.hasEditedNumber_ = false;
+      OptionsPage.closeOverlay();
     },
 
     /**
@@ -62,12 +74,16 @@
      */
     saveCreditCard_: function() {
       var creditCard = new Array(5);
-      creditCard[0] = this.guid;
+      creditCard[0] = this.guid_;
       creditCard[1] = $('nameOnCard').value;
-      creditCard[2] = $('creditCardNumber').value;
       creditCard[3] = $('expirationMonth').value;
       creditCard[4] = $('expirationYear').value;
 
+      if (this.hasEditedNumber_)
+        creditCard[2] = $('creditCardNumber').value;
+      else
+        creditCard[2] = this.storedCCNumber_;
+
       chrome.send('setCreditCard', creditCard);
     },
 
@@ -78,23 +94,31 @@
      * @private
      */
     connectInputEvents_: function() {
-      var self = this;
       $('nameOnCard').oninput = $('creditCardNumber').oninput =
-      $('expirationMonth').onchange = $('expirationYear').onchange =
-      // TODO(isherman): What should the indentation of this line be?
-      function(event) {
-        self.inputFieldChanged_();
-      }
+          $('expirationMonth').onchange = $('expirationYear').onchange =
+              this.inputFieldChanged_.bind(this);
     },
 
     /**
      * Checks the values of each of the input fields and disables the 'Ok'
      * button if all of the fields are empty.
+     * @param {Event} opt_event Optional data for the 'input' event.
      * @private
      */
-    inputFieldChanged_: function() {
-      var disabled = !$('nameOnCard').value && !$('creditCardNumber').value;
+    inputFieldChanged_: function(opt_event) {
+      var ccNumber = $('creditCardNumber');
+      var disabled = !$('nameOnCard').value && !ccNumber.value;
       $('autoFillEditCreditCardApplyButton').disabled = disabled;
+
+      if (opt_event && opt_event.target == ccNumber) {
+        // If the user hasn't edited the text yet, delete it all on edit.
+        if (!this.hasEditedNumber_ && this.storedCCNumber_.length &&
+            ccNumber.value != this.storedCCNumber_) {
+          ccNumber.value = '';
+        }
+
+        this.hasEditedNumber_ = true;
+      }
     },
 
     /**
@@ -151,7 +175,7 @@
      */
     setInputFields_: function(creditCard) {
       $('nameOnCard').value = creditCard['nameOnCard'];
-      $('creditCardNumber').value = creditCard['creditCardNumber'];
+      $('creditCardNumber').value = creditCard['obfuscatedCardNumber'];
 
       // The options for the year select control may be out-dated at this point,
       // e.g. the user opened the options page before midnight on New Year's Eve
@@ -180,7 +204,8 @@
     loadCreditCard_: function(creditCard) {
       this.setInputFields_(creditCard);
       this.inputFieldChanged_();
-      this.guid = creditCard['guid'];
+      this.guid_ = creditCard['guid'];
+      this.storedCCNumber_ = creditCard['creditCardNumber'];
     },
   };
 
@@ -200,5 +225,4 @@
   return {
     AutoFillEditCreditCardOverlay: AutoFillEditCreditCardOverlay
   };
-
 });
diff --git a/chrome/browser/resources/options/autofill_options.css b/chrome/browser/resources/options/autofill_options.css
index 5320dd7..ab6376c 100644
--- a/chrome/browser/resources/options/autofill_options.css
+++ b/chrome/browser/resources/options/autofill_options.css
@@ -16,3 +16,8 @@
   border-top: 1px solid #D9D9D9;
   padding: 5px 10px;
 }
+
+#autofill-add-address,
+#autofill-add-creditcard {
+  margin: 2px 0;
+}
diff --git a/chrome/browser/resources/options/autofill_options.html b/chrome/browser/resources/options/autofill_options.html
index 727c9ae..7c912c7 100644
--- a/chrome/browser/resources/options/autofill_options.html
+++ b/chrome/browser/resources/options/autofill_options.html
@@ -1,5 +1,11 @@
 <div id="autofill-options" class="page hidden">
-  <h1 i18n-content="autoFillOptionsTitle"></h1>
+  <h1 i18n-content="autoFillOptionsPage"></h1>
+<if expr="os == 'darwin'">
+  <label class="checkbox">
+    <input pref="autofill.auxiliary_profiles_enabled" type="checkbox">
+    <span i18n-content="auxiliaryProfilesEnabled"></span>
+  </label>
+</if>
   <h3 i18n-content="autoFillAddresses"></h3>
   <div class="settings-list">
     <list id="address-list"></list>
diff --git a/chrome/browser/resources/options/autofill_options.js b/chrome/browser/resources/options/autofill_options.js
index 2e129bb..9f4ac3b 100644
--- a/chrome/browser/resources/options/autofill_options.js
+++ b/chrome/browser/resources/options/autofill_options.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
   function AutoFillOptions() {
     OptionsPage.call(this,
                      'autoFillOptions',
-                     templateData.autoFillOptionsTitle,
+                     templateData.autoFillOptionsPageTabTitle,
                      'autofill-options');
   }
 
@@ -88,7 +88,7 @@
       var title = localStrings.getString('addAddressTitle');
       AutoFillEditAddressOverlay.setTitle(title);
       AutoFillEditAddressOverlay.clearInputFields();
-      OptionsPage.showOverlay('autoFillEditAddressOverlay');
+      OptionsPage.navigateToPage('autoFillEditAddressOverlay');
     },
 
     /**
@@ -101,7 +101,7 @@
       var title = localStrings.getString('addCreditCardTitle');
       AutoFillEditCreditCardOverlay.setTitle(title);
       AutoFillEditCreditCardOverlay.clearInputFields();
-      OptionsPage.showOverlay('autoFillEditCreditCardOverlay');
+      OptionsPage.navigateToPage('autoFillEditCreditCardOverlay');
     },
 
     /**
@@ -171,8 +171,8 @@
     showEditAddressOverlay_: function(address) {
       var title = localStrings.getString('editAddressTitle');
       AutoFillEditAddressOverlay.setTitle(title);
-      AutoFillEditAddressOverlay.loadAddress(address[0]);
-      OptionsPage.showOverlay('autoFillEditAddressOverlay');
+      AutoFillEditAddressOverlay.loadAddress(address);
+      OptionsPage.navigateToPage('autoFillEditAddressOverlay');
     },
 
     /**
@@ -184,8 +184,8 @@
     showEditCreditCardOverlay_: function(creditCard) {
       var title = localStrings.getString('editCreditCardTitle');
       AutoFillEditCreditCardOverlay.setTitle(title);
-      AutoFillEditCreditCardOverlay.loadCreditCard(creditCard[0]);
-      OptionsPage.showOverlay('autoFillEditCreditCardOverlay');
+      AutoFillEditCreditCardOverlay.loadCreditCard(creditCard);
+      OptionsPage.navigateToPage('autoFillEditCreditCardOverlay');
     },
   };
 
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index f31d364..300dca3 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -18,10 +18,10 @@
               i18n-content="startupShowPages"></span></label>
       <div class="suboption">
         <div id="startupPageManagement" class="settings-list">
-          <list id="startupPagesShortList"></list>
+          <list id="startupPagesList"></list>
           <div>
-            <button id="startupPageManagerButton"
-                i18n-content="startupManagePages"></button>
+            <button id="startupAddButton"
+                i18n-content="startupAddButton"></button>
             <button id="startupUseCurrentButton"
                 i18n-content="startupUseCurrent"></button>
           </div>
@@ -65,9 +65,7 @@
     <h3 i18n-content="defaultSearchGroupName"></h3>
       <div id="defaultSearchEngineGroup">
         <div>
-          <select id="defaultSearchEngine"
-              onchange="BrowserOptions.getInstance().setDefaultSearchEngine()">
-          </select>
+          <select id="defaultSearchEngine"></select>
           <button id="defaultSearchManageEnginesButton"
               i18n-content="defaultSearchManageEngines"></button>
         </div>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 369ffb3..4711539 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -1,18 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 cr.define('options', function() {
   const OptionsPage = options.OptionsPage;
   const ArrayDataModel = cr.ui.ArrayDataModel;
-  const ListSelectionModel = cr.ui.ListSelectionModel;
 
   //
   // BrowserOptions class
   // Encapsulated handling of browser options page.
   //
   function BrowserOptions() {
-    OptionsPage.call(this, 'browser', templateData.browserPage, 'browserPage');
+    OptionsPage.call(this, 'browser',
+                     templateData.browserPageTabTitle,
+                     'browserPage');
   }
 
   cr.addSingletonGetter(BrowserOptions);
@@ -44,11 +45,11 @@
       $('startupUseCurrentButton').onclick = function(event) {
         chrome.send('setStartupPagesToCurrentPages');
       };
-      $('startupPageManagerButton').onclick = function(event) {
-        OptionsPage.showPageByName('startupPages');
+      $('startupAddButton').onclick = function(event) {
+        OptionsPage.navigateToPage('addStartupPageOverlay');
       };
       $('defaultSearchManageEnginesButton').onclick = function(event) {
-        OptionsPage.showPageByName('searchEngines');
+        OptionsPage.navigateToPage('searchEngines');
         chrome.send('coreOptionsUserMetricsAction',
             ['Options_ManageSearchEngines']);
       };
@@ -59,23 +60,29 @@
           // Leave disabled for now. The PrefCheckbox handler already set it to
           // true so undo that.
           Preferences.setBooleanPref(this.pref, false, this.metric);
-          OptionsPage.showOverlay('instantConfirmOverlay');
+          OptionsPage.navigateToPage('instantConfirmOverlay');
         }
       };
+      $('defaultSearchEngine').onchange = this.setDefaultSearchEngine;
 
       var homepageField = $('homepageURL');
       $('homepageUseNTPButton').onchange =
           this.handleHomepageUseNTPButtonChange_.bind(this);
       $('homepageUseURLButton').onchange =
           this.handleHomepageUseURLButtonChange_.bind(this);
-      homepageField.onchange =
-          this.handleHomepageURLChange_.bind(this);
+      homepageField.onchange = this.handleHomepageURLChange_.bind(this);
+      homepageField.oninput = this.handleHomepageURLChange_.bind(this);
 
       // Ensure that changes are committed when closing the page.
       window.addEventListener('unload', function() {
-          if (document.activeElement == homepageField)
-            homepageField.blur();
-          });
+        if (document.activeElement == homepageField)
+          homepageField.blur();
+      });
+
+      // Remove Windows-style accelerators from button labels.
+      // TODO(stuartmorgan): Remove this once the strings are updated.
+      $('startupAddButton').textContent =
+          localStrings.getStringWithoutAccelerator('startupAddButton');
 
       if (!cr.isChromeOS) {
         $('defaultBrowserUseAsDefaultButton').onclick = function(event) {
@@ -83,10 +90,9 @@
         };
       }
 
-      var list = $('startupPagesShortList');
+      var list = $('startupPagesList');
       options.browser_options.StartupPageList.decorate(list);
       list.autoExpands = true;
-      list.selectionModel = new ListSelectionModel;
 
       // Check if we are in the guest mode.
       if (cr.commandLine.options['--bwsi']) {
@@ -133,7 +139,7 @@
     /**
      * Updates the search engine popup with the given entries.
      * @param {Array} engines List of available search engines.
-     * @param {Integer} defaultValue The value of the current default engine.
+     * @param {number} defaultValue The value of the current default engine.
      */
     updateSearchEngines_: function(engines, defaultValue) {
       this.clearSearchEngines_();
@@ -154,11 +160,10 @@
     /**
      * Returns true if the custom startup page control block should
      * be enabled.
-     * @private
      * @returns {boolean} Whether the startup page controls should be
      *     enabled.
      */
-    shouldEnableCustomStartupPageControls_: function(pages) {
+    shouldEnableCustomStartupPageControls: function(pages) {
       return $('startupShowPagesButton').checked;
     },
 
@@ -168,19 +173,7 @@
      * @param {Array} pages List of startup pages.
      */
     updateStartupPages_: function(pages) {
-      var list = $('startupPagesShortList');
-      list.dataModel = new ArrayDataModel(pages);
-      if (pages.length > 0 && pages.length <= 10) {
-        list.classList.remove("hidden");
-        $('startupPageManagement').classList.add('settings-list');
-        $('startupShowPagesLabel').textContent =
-            localStrings.getStringWithoutAccelerator('startupShowPages');
-      } else {
-        list.classList.add("hidden");
-        $('startupPageManagement').classList.remove('settings-list');
-        $('startupShowPagesLabel').textContent =
-            localStrings.getStringWithoutAccelerator('startupShowManyPages');
-      }
+      $('startupPagesList').dataModel = new ArrayDataModel(pages);
     },
 
     /**
@@ -202,12 +195,13 @@
     },
 
     /**
-     * Handles change events of the text field 'homepageURL'.
+     * Handles input and change events of the text field 'homepageURL'.
      * @private
-     * @param {event} change event.
+     * @param {event} input/change event.
      */
     handleHomepageURLChange_: function(event) {
-      Preferences.setStringPref('homepage', $('homepageURL').value);
+      var doFixup = event.type == 'change' ? '1' : '0';
+      chrome.send('setHomePage', [$('homepageURL').value, doFixup]);
     },
 
     /**
@@ -341,10 +335,10 @@
      * @private
      */
     updateCustomStartupPageControlStates_: function() {
-      var disable = !this.shouldEnableCustomStartupPageControls_();
-      $('startupPagesShortList').disabled = disable;
+      var disable = !this.shouldEnableCustomStartupPageControls();
+      $('startupPagesList').disabled = disable;
       $('startupUseCurrentButton').disabled = disable;
-      $('startupPageManagerButton').disabled = disable;
+      $('startupAddButton').disabled = disable;
     },
 
     /**
@@ -358,6 +352,16 @@
         chrome.send('setDefaultSearchEngine', [String(selection.value)]);
       }
     },
+
+    /**
+     * Adds the given startup page at the current selection point.
+     * @private
+     */
+    addStartupPage_: function(url) {
+      var selectedIndex =
+          $('startupPagesList').selectionModel.selectedIndex;
+      chrome.send('addStartupPage', [url, String(selectedIndex)]);
+    },
   };
 
   BrowserOptions.updateDefaultBrowserState = function(statusString, isDefault,
@@ -375,7 +379,10 @@
 
   BrowserOptions.updateStartupPages = function(pages) {
     BrowserOptions.getInstance().updateStartupPages_(pages);
-    StartupPageManager.getInstance().updateStartupPages_(pages);
+  };
+
+  BrowserOptions.addStartupPage = function(url) {
+    BrowserOptions.getInstance().addStartupPage_(url);
   };
 
   // Export
diff --git a/chrome/browser/resources/options/browser_options_page.css b/chrome/browser/resources/options/browser_options_page.css
index 67e078f..6694883 100644
--- a/chrome/browser/resources/options/browser_options_page.css
+++ b/chrome/browser/resources/options/browser_options_page.css
@@ -1,9 +1,21 @@
-
 #startupPageManagement.settings-list > :last-child {
   border-top: 1px solid #d9d9d9;
   padding: 5px 10px;
 }
 
+#startupPagesList {
+  min-height: 64px;
+}
+
+#startupPagesList .title {
+  width: 40%;
+}
+
+#startupPagesList .url {
+  -webkit-box-flex: 1;
+  color: #666;
+}
+
 #customHomePageGroup {
   display: -webkit-box;
   -webkit-box-orient: horizontal;
@@ -33,7 +45,7 @@
 #defaultSearchEngine {
   display: block;
   -webkit-box-flex: 1;
-  max-width: 300px;
+  max-width: 200px;
 }
 
 #defaultSearchManageEnginesButton {
diff --git a/chrome/browser/resources/options/browser_options_startup_page_list.js b/chrome/browser/resources/options/browser_options_startup_page_list.js
index 8265e13..ff3f69f 100644
--- a/chrome/browser/resources/options/browser_options_startup_page_list.js
+++ b/chrome/browser/resources/options/browser_options_startup_page_list.js
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 cr.define('options.browser_options', function() {
-  const DeletableItemList = options.DeletableItemList;
-  const DeletableItem = options.DeletableItem;
+  const InlineEditableItem = options.InlineEditableItem;
+  const InlineEditableItemList = options.InlineEditableItemList;
 
   /**
    * Creates a new startup page list item.
@@ -29,13 +29,20 @@
   };
 
   StartupPageListItem.prototype = {
-    __proto__: DeletableItem.prototype,
+    __proto__: InlineEditableItem.prototype,
+
+    /**
+     * Input field for editing the page url.
+     * @type {HTMLElement}
+     * @private
+     */
+    urlField_: null,
 
     /** @inheritDoc */
     decorate: function() {
-      DeletableItem.prototype.decorate.call(this);
+      InlineEditableItem.prototype.decorate.call(this);
 
-      var titleEl = this.ownerDocument.createElement('span');
+      var titleEl = this.ownerDocument.createElement('div');
       titleEl.className = 'title';
       titleEl.classList.add('favicon-cell');
       titleEl.textContent = this.pageInfo_['title'];
@@ -44,13 +51,42 @@
       titleEl.title = this.pageInfo_['tooltip'];
 
       this.contentElement.appendChild(titleEl);
+
+      var urlEl = this.createEditableTextCell(this.pageInfo_['url']);
+      urlEl.className = 'url';
+      this.contentElement.appendChild(urlEl);
+
+      this.urlField_ = urlEl.querySelector('input');
+      this.urlField_.required = true;
+
+      this.addEventListener('commitedit', this.onEditCommitted_.bind(this));
+    },
+
+    /** @inheritDoc */
+    get currentInputIsValid() {
+      return this.urlField_.validity.valid;
+    },
+
+    /** @inheritDoc */
+    get hasBeenEdited() {
+      return this.urlField_.value != this.pageInfo_['url'];
+    },
+
+    /**
+     * Called when committing an edit; updates the model.
+     * @param {Event} e The end event.
+     * @private
+     */
+    onEditCommitted_: function(e) {
+      chrome.send('editStartupPage',
+                  [this.pageInfo_['modelIndex'], this.urlField_.value]);
     },
   };
 
   var StartupPageList = cr.ui.define('list');
 
   StartupPageList.prototype = {
-    __proto__: DeletableItemList.prototype,
+    __proto__: InlineEditableItemList.prototype,
 
     /** @inheritDoc */
     createItem: function(pageInfo) {
diff --git a/chrome/browser/resources/options/certificate_backup_overlay.html b/chrome/browser/resources/options/certificate_backup_overlay.html
index c5b5a18..280c27a 100644
--- a/chrome/browser/resources/options/certificate_backup_overlay.html
+++ b/chrome/browser/resources/options/certificate_backup_overlay.html
@@ -1,9 +1,6 @@
 <div class="page hidden" id="certificateBackupOverlay">
-  <p>
-    <span i18n-content="certificateExportPasswordDescription"></span>
-  </p>
-
-  <p>
+  <h1 i18n-content="certificateExportPasswordDescription"></h1>
+  <div class="content-area">
     <table>
       <tr>
         <label id="certificateBackupPasswordLabel">
@@ -26,17 +23,16 @@
         </label>
       </tr>
     </table>
-  </p>
-
-  <p>
-    <span i18n-content="certificateExportPasswordHelp"></span>
-  </p>
-
-  <div class="action-area button-strip">
-    <button type="reset" id="certificateBackupCancelButton"
-        i18n-content="cancel"></button>
-    <button type="submit" id="certificateBackupOkButton"
-        i18n-content="ok" disabled></button>
+    <p>
+      <span i18n-content="certificateExportPasswordHelp"></span>
+    </p>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="reset" id="certificateBackupCancelButton"
+          i18n-content="cancel"></button>
+      <button type="submit" id="certificateBackupOkButton" i18n-content="ok"
+          disabled></button>
+    </div>
   </div>
 </div>
-
diff --git a/chrome/browser/resources/options/certificate_backup_overlay.js b/chrome/browser/resources/options/certificate_backup_overlay.js
index f5da035..e700347 100644
--- a/chrome/browser/resources/options/certificate_backup_overlay.js
+++ b/chrome/browser/resources/options/certificate_backup_overlay.js
@@ -48,7 +48,7 @@
      */
     dismissOverlay_: function() {
       this.clearInputFields_();
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
     },
 
     /**
@@ -102,7 +102,7 @@
 
   CertificateBackupOverlay.show = function() {
     CertificateBackupOverlay.getInstance().clearInputFields_();
-    OptionsPage.showOverlay('certificateBackupOverlay');
+    OptionsPage.navigateToPage('certificateBackupOverlay');
   };
 
   CertificateBackupOverlay.dismiss = function() {
@@ -113,6 +113,4 @@
   return {
     CertificateBackupOverlay: CertificateBackupOverlay
   };
-
 });
-
diff --git a/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.html b/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.html
index e3e5f6f..2560b18 100644
--- a/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.html
+++ b/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.html
@@ -1,31 +1,33 @@
 <div class="page hidden" id="certificateEditCaTrustOverlay">
-  <p>
-    <span id="certificateEditCaTrustDescription"></span>
-  </p>
-
-  <p>
-    <span i18n-content="certificateEditTrustLabel"></span>
-    <br>
-    <label id="certificateCaTrustSSLLabel">
-      <input type="checkbox" id="certificateCaTrustSSLCheckbox">
-      <span i18n-content="certificateCaTrustSSLLabel"></span>
-    </label>
-    <br>
-    <label id="certificateCaTrustEmailLabel">
-      <input type="checkbox" id="certificateCaTrustEmailCheckbox">
-      <span i18n-content="certificateCaTrustEmailLabel"></span>
-    </label>
-    <br>
-    <label id="certificateCaTrustObjSignLabel">
-      <input type="checkbox" id="certificateCaTrustObjSignCheckbox">
-      <span i18n-content="certificateCaTrustObjSignLabel"></span>
-    </label>
-  </p>
-
-  <div class="action-area button-strip">
-    <button type="reset" id="certificateEditCaTrustCancelButton"
-        i18n-content="cancel"></button>
-    <button type="submit" id="certificateEditCaTrustOkButton"
-        i18n-content="ok"></button>
+  <div class="content-area">
+    <p>
+      <span id="certificateEditCaTrustDescription"></span>
+    </p>
+    <p>
+      <span i18n-content="certificateEditTrustLabel"></span>
+      <br>
+      <label id="certificateCaTrustSSLLabel">
+        <input type="checkbox" id="certificateCaTrustSSLCheckbox">
+        <span i18n-content="certificateCaTrustSSLLabel"></span>
+      </label>
+      <br>
+      <label id="certificateCaTrustEmailLabel">
+        <input type="checkbox" id="certificateCaTrustEmailCheckbox">
+        <span i18n-content="certificateCaTrustEmailLabel"></span>
+      </label>
+      <br>
+      <label id="certificateCaTrustObjSignLabel">
+        <input type="checkbox" id="certificateCaTrustObjSignCheckbox">
+        <span i18n-content="certificateCaTrustObjSignLabel"></span>
+      </label>
+    </p>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="reset" id="certificateEditCaTrustCancelButton"
+          i18n-content="cancel"></button>
+      <button type="submit" id="certificateEditCaTrustOkButton"
+          i18n-content="ok"></button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.js b/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.js
index bcea4e3..86fa5f7 100644
--- a/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.js
+++ b/chrome/browser/resources/options/certificate_edit_ca_trust_overlay.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -26,7 +26,7 @@
      * @private
      */
     dismissOverlay_: function() {
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
     },
 
     /**
@@ -49,7 +49,7 @@
      */
     finishEdit_: function() {
       // TODO(mattm): Send checked values as booleans.  For now send them as
-      // strings, since DOMUIBindings::send does not support any other types :(
+      // strings, since WebUIBindings::send does not support any other types :(
       chrome.send('editCaCertificateTrust',
                   [this.certId,
                    $('certificateCaTrustSSLCheckbox').checked.toString(),
@@ -74,7 +74,7 @@
      */
     finishImport_: function() {
       // TODO(mattm): Send checked values as booleans.  For now send them as
-      // strings, since DOMUIBindings::send does not support any other types :(
+      // strings, since WebUIBindings::send does not support any other types :(
       chrome.send('importCaCertificateTrustSelected',
                   [$('certificateCaTrustSSLCheckbox').checked.toString(),
                    $('certificateCaTrustEmailCheckbox').checked.toString(),
@@ -126,7 +126,7 @@
         localStrings.getStringF('certificateEditCaTrustDescriptionFormat',
                                 certName);
     self.enableInputs_(false);
-    OptionsPage.showOverlay('certificateEditCaTrustOverlay');
+    OptionsPage.navigateToPage('certificateEditCaTrustOverlay');
     chrome.send('getCaCertificateTrust', [certId]);
   }
 
@@ -150,7 +150,7 @@
         localStrings.getStringF('certificateImportCaDescriptionFormat',
                                 certName);
     CertificateEditCaTrustOverlay.populateTrust(false, false, false);
-    OptionsPage.showOverlay('certificateEditCaTrustOverlay');
+    OptionsPage.navigateToPage('certificateEditCaTrustOverlay');
   }
 
   CertificateEditCaTrustOverlay.dismiss = function() {
@@ -161,5 +161,4 @@
   return {
     CertificateEditCaTrustOverlay: CertificateEditCaTrustOverlay
   };
-
 });
diff --git a/chrome/browser/resources/options/certificate_import_error_overlay.html b/chrome/browser/resources/options/certificate_import_error_overlay.html
index b686920..d9b11c6 100644
--- a/chrome/browser/resources/options/certificate_import_error_overlay.html
+++ b/chrome/browser/resources/options/certificate_import_error_overlay.html
@@ -1,9 +1,13 @@
 <div class="page hidden" id="certificateImportErrorOverlay">
   <h1 id="certificateImportErrorOverlayTitle"></h1>
-  <div id="certificateImportErrorOverlayMessage"></div>
-  <ul id="certificateImportErrorOverlayCertErrors"></ul>
-  <div class="action-area button-strip">
-    <button type="submit" id="certificateImportErrorOverlayOk"
-        i18n-content="ok"></button>
+  <div class="content-area">
+    <div id="certificateImportErrorOverlayMessage"></div>
+    <ul id="certificateImportErrorOverlayCertErrors"></ul>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="submit" id="certificateImportErrorOverlayOk"
+          i18n-content="ok"></button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/certificate_import_error_overlay.js b/chrome/browser/resources/options/certificate_import_error_overlay.js
index 222efda..efc99ff 100644
--- a/chrome/browser/resources/options/certificate_import_error_overlay.js
+++ b/chrome/browser/resources/options/certificate_import_error_overlay.js
@@ -30,7 +30,7 @@
       OptionsPage.prototype.initializePage.call(this);
 
       $('certificateImportErrorOverlayOk').onclick = function(event) {
-        OptionsPage.clearOverlays();
+        OptionsPage.closeOverlay();
       };
     },
   };
@@ -57,7 +57,7 @@
       ul.appendChild(li);
     }
 
-    OptionsPage.showOverlay('certificateImportErrorOverlay');
+    OptionsPage.navigateToPage('certificateImportErrorOverlay');
   }
 
   // Export
diff --git a/chrome/browser/resources/options/certificate_manager.html b/chrome/browser/resources/options/certificate_manager.html
index 2f205c1..39276a7 100644
--- a/chrome/browser/resources/options/certificate_manager.html
+++ b/chrome/browser/resources/options/certificate_manager.html
@@ -3,27 +3,27 @@
 
   <!-- Navigation tabs -->
   <div class="subpages-nav-tabs">
-    <span id="personal-certs-nav-tab" class="inactive-tab"
+    <span id="personal-certs-nav-tab" class="tab"
         tab-contents="personalCertsTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="personalCertsTabTitle"></span>
       <span class="active-tab-label"
           i18n-content="personalCertsTabTitle"></span>
     </span>
-    <span id="server-certs-nav-tab" class="inactive-tab"
+    <span id="server-certs-nav-tab" class="tab"
         tab-contents="serverCertsTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="serverCertsTabTitle"></span>
       <span class="active-tab-label" i18n-content="serverCertsTabTitle"></span>
     </span>
-    <span id="ca-certs-nav-tab" class="inactive-tab"
+    <span id="ca-certs-nav-tab" class="tab"
         tab-contents="caCertsTab">
-      <span class="inactive-tab-label" i18n-content="caCertsTabTitle"></span>
+      <span class="tab-label" i18n-content="caCertsTabTitle"></span>
       <span class="active-tab-label" i18n-content="caCertsTabTitle"></span>
     </span>
-    <span id="other-certs-nav-tab" class="inactive-tab"
+    <span id="other-certs-nav-tab" class="tab"
         tab-contents="otherCertsTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="unknownCertsTabTitle"></span>
       <span class="active-tab-label" i18n-content="unknownCertsTabTitle"></span>
     </span>
@@ -43,8 +43,6 @@
       <tr><td>
         <button id="personalCertsTab-view" i18n-content="view_certificate"
           disabled></button>
-        <button id="personalCertsTab-backup" i18n-content="export_certificate"
-          disabled></button>
         <!-- TODO(mattm):
         <button id="personalCertsTab-backup-all"
           i18n-content="export_all_certificates"
@@ -52,6 +50,8 @@
         -->
         <button id="personalCertsTab-import" i18n-content="import_certificate"
           ></button>
+        <button id="personalCertsTab-backup" i18n-content="export_certificate"
+          disabled></button>
         <button id="personalCertsTab-delete" i18n-content="delete_certificate"
           disabled></button>
       </td></tr>
diff --git a/chrome/browser/resources/options/certificate_manager.js b/chrome/browser/resources/options/certificate_manager.js
index 0209053..cf8a43d 100644
--- a/chrome/browser/resources/options/certificate_manager.js
+++ b/chrome/browser/resources/options/certificate_manager.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -40,8 +40,6 @@
           var data = tree.selectedItem.data;
           CertificateEditCaTrustOverlay.show(data.id, data.name);
         }
-      } else {
-        console.log('unknown edit button for: ' + id);
       }
     }
 
@@ -74,8 +72,6 @@
         this.importButton.onclick = function(e) {
           chrome.send('importCaCertificate', []);
         }
-      } else {
-        console.log('unknown import button for: ' + id);
       }
     }
 
@@ -147,7 +143,7 @@
    */
   function CertificateManager(model) {
     OptionsPage.call(this, 'certificateManager',
-                     localStrings.getString('certificateManagerPage'),
+                     templateData.certificateManagerPageTabTitle,
                      'certificateManagerPage');
   }
 
diff --git a/chrome/browser/resources/options/certificate_restore_overlay.html b/chrome/browser/resources/options/certificate_restore_overlay.html
index b584982..ecbbe0c 100644
--- a/chrome/browser/resources/options/certificate_restore_overlay.html
+++ b/chrome/browser/resources/options/certificate_restore_overlay.html
@@ -1,19 +1,17 @@
 <div class="page hidden" id="certificateRestoreOverlay">
-  <p>
-    <span i18n-content="certificateRestorePasswordDescription"></span>
-  </p>
-
-  <p>
+  <h1 i18n-content="certificateRestorePasswordDescription"></h1>
+  <div class="content-area">
     <label id="certificateRestorePasswordLabel">
       <span i18n-content="certificatePasswordLabel"></span>
       <input type="password" id="certificateRestorePassword">
     </label>
-  </p>
-
-  <div class="action-area button-strip">
-    <button type="reset" id="certificateRestoreCancelButton"
-        i18n-content="cancel"></button>
-    <button type="submit" id="certificateRestoreOkButton"
-        i18n-content="ok"></button>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button type="reset" id="certificateRestoreCancelButton"
+          i18n-content="cancel"></button>
+      <button type="submit" id="certificateRestoreOkButton" i18n-content="ok">
+      </button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/certificate_restore_overlay.js b/chrome/browser/resources/options/certificate_restore_overlay.js
index 2673c08..db75a9f 100644
--- a/chrome/browser/resources/options/certificate_restore_overlay.js
+++ b/chrome/browser/resources/options/certificate_restore_overlay.js
@@ -44,7 +44,7 @@
      */
     dismissOverlay_: function() {
       this.clearInputFields_();
-      OptionsPage.clearOverlays();
+      OptionsPage.closeOverlay();
     },
 
     /**
@@ -82,7 +82,7 @@
 
   CertificateRestoreOverlay.show = function() {
     CertificateRestoreOverlay.getInstance().clearInputFields_();
-    OptionsPage.showOverlay('certificateRestoreOverlay');
+    OptionsPage.navigateToPage('certificateRestoreOverlay');
   };
 
   CertificateRestoreOverlay.dismiss = function() {
diff --git a/chrome/browser/resources/options/chromeos_accounts_options.js b/chrome/browser/resources/options/chromeos_accounts_options.js
index 1a978c6..60006e8 100644
--- a/chrome/browser/resources/options/chromeos_accounts_options.js
+++ b/chrome/browser/resources/options/chromeos_accounts_options.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
    * @constructor
    */
   function AccountsOptions(model) {
-    OptionsPage.call(this, 'accounts', localStrings.getString('accountsPage'),
+    OptionsPage.call(this, 'accounts', templateData.accountsPageTabTitle,
                      'accountsPage');
   }
 
@@ -33,23 +33,37 @@
 
       // Set up accounts page.
       var userList = $('userList');
-      options.accounts.UserList.decorate(userList);
 
       var userNameEdit = $('userNameEdit');
       options.accounts.UserNameEdit.decorate(userNameEdit);
       userNameEdit.addEventListener('add', this.handleAddUser_);
 
-      userList.disabled =
-      userNameEdit.disabled = !AccountsOptions.currentUserIsOwner();
-      // If the current user is not the owner, show some warning.
-      if (!AccountsOptions.currentUserIsOwner()) {
+      // If the current user is not the owner, show some warning,
+      // and do not show the user list.
+      if (AccountsOptions.currentUserIsOwner()) {
+        options.accounts.UserList.decorate(userList);
+      } else {
         $('ownerOnlyWarning').classList.remove('hidden');
       }
 
       this.addEventListener('visibleChange', this.handleVisibleChange_);
 
-      $('useWhitelistCheck').addEventListener('click',
-          this.handleUseWhitelistCheckClick_);
+      $('useWhitelistCheck').addEventListener('change',
+          this.handleUseWhitelistCheckChange_.bind(this));
+
+      Preferences.getInstance().addEventListener(
+          $('useWhitelistCheck').pref,
+          this.handleUseWhitelistPrefChange_.bind(this));
+    },
+
+    /**
+     * Update user list control state.
+     * @private
+     */
+    updateControls_: function() {
+      $('userList').disabled =
+      $('userNameEdit').disabled = !AccountsOptions.currentUserIsOwner() ||
+                                   !$('useWhitelistCheck').checked;
     },
 
     /**
@@ -62,18 +76,30 @@
         // fetchUserPictures calls back AccountsOptions.setUserPictures and
         // triggers redraw.
         chrome.send('fetchUserPictures', []);
+
+        this.updateControls_();
       }
     },
 
     /**
-     * Handler for allow guest check click.
+     * Handler for allow guest check change.
      * @private
      */
-    handleUseWhitelistCheckClick_: function(e) {
+    handleUseWhitelistCheckChange_: function(e) {
       // Whitelist existing users when guest login is being disabled.
       if ($('useWhitelistCheck').checked) {
         chrome.send('whitelistExistingUsers', []);
       }
+
+      this.updateControls_();
+    },
+
+    /**
+     * handler for allow guest pref change.
+     * @private
+     */
+    handleUseWhitelistPrefChange_: function(e) {
+      this.updateControls_();
     },
 
     /**
diff --git a/chrome/browser/resources/options/chromeos_accounts_options_page.css b/chrome/browser/resources/options/chromeos_accounts_options_page.css
index ea316db..1cc4f2e 100644
--- a/chrome/browser/resources/options/chromeos_accounts_options_page.css
+++ b/chrome/browser/resources/options/chromeos_accounts_options_page.css
@@ -11,7 +11,6 @@
 }
 
 .user-list-item {
-  line-height: 35px;
   padding: 2px;
 }
 
@@ -19,7 +18,6 @@
   border: 1px solid black;
   width: 26px;
   height: 26px;
-  vertical-align: middle;
 }
 
 .user-email-label {
@@ -31,21 +29,18 @@
   -webkit-margin-start: 10px;
 }
 
+.user-email-name-block {
+  -webkit-box-flex: 1;
+  max-width: 318px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
 .remove-user-button {
   background-image: url(chrome://theme/IDR_CLOSE_BAR);
-  background-color: transparent;
-  border: 0;
   width: 16px;
   height: 16px;
-  margin-top: 8px;
-}
-
-html[dir=ltr] .remove-user-button {
-  float: right;
-}
-
-html[dir=rtl] .remove-user-button {
-  float: left;
 }
 
 .remove-user-button:hover {
diff --git a/chrome/browser/resources/options/chromeos_accounts_user_list.js b/chrome/browser/resources/options/chromeos_accounts_user_list.js
index 36f565f..591dc95 100644
--- a/chrome/browser/resources/options/chromeos_accounts_user_list.js
+++ b/chrome/browser/resources/options/chromeos_accounts_user_list.js
@@ -103,7 +103,7 @@
       // Handle left button click
       if (e.button == 0) {
         var el = e.target;
-        if (el.className == 'remove-user-button') {
+        if (el.classList.contains('remove-user-button')) {
           this.removeUser(el.parentNode.user);
         }
       }
@@ -173,13 +173,21 @@
           localStrings.getStringF('username_format', this.user.name) :
           this.user.name;
 
+      var emailNameBlock = this.ownerDocument.createElement('div');
+      emailNameBlock.className = 'user-email-name-block';
+      emailNameBlock.appendChild(labelEmail);
+      emailNameBlock.appendChild(labelName);
+      emailNameBlock.title = this.user.owner ?
+          localStrings.getStringF('username_format', this.user.email) :
+          this.user.email;
+
       this.appendChild(icon);
-      this.appendChild(labelEmail);
-      this.appendChild(labelName);
+      this.appendChild(emailNameBlock);
 
       if (!this.user.owner) {
         var removeButton = this.ownerDocument.createElement('button');
-        removeButton.className = 'remove-user-button';
+        removeButton.classList.add('raw-button');
+        removeButton.classList.add('remove-user-button');
         this.appendChild(removeButton);
       }
     }
diff --git a/chrome/browser/resources/options/chromeos_internet_detail.html b/chrome/browser/resources/options/chromeos_internet_detail.html
index 18245ea..8e85860 100644
--- a/chrome/browser/resources/options/chromeos_internet_detail.html
+++ b/chrome/browser/resources/options/chromeos_internet_detail.html
@@ -2,33 +2,33 @@
   <h1 id="inetTitle"></h1>
   <!-- Navigation tabs -->
   <div class="subpages-nav-tabs" id="details-tab-strip">
-    <span id="wifiNetworkNavTab" class="inactive-tab wifi-details"
+    <span id="wifiNetworkNavTab" class="tab wifi-details"
         tab-contents="wifiNetworkTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="wifiNetworkTabLabel"></span>
       <span class="active-tab-label" i18n-content="wifiNetworkTabLabel"></span>
     </span>
-    <span id="cellularPlanNavTab" class="inactive-tab cellular-details"
+    <span id="cellularPlanNavTab" class="tab cellular-details"
         tab-contents="cellularPlanTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="cellularPlanTabLabel"></span>
       <span class="active-tab-label" i18n-content="cellularPlanTabLabel"></span>
     </span>
-    <span id="cellularConnNavTab" class="inactive-tab cellular-details"
+    <span id="cellularConnNavTab" class="tab cellular-details"
         tab-contents="cellularConnTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="cellularConnTabLabel"></span>
       <span class="active-tab-label" i18n-content="cellularConnTabLabel"></span>
     </span>
-    <span id="cellularDeviceNavTab" class="inactive-tab cellular-details"
+    <span id="cellularDeviceNavTab" class="tab cellular-details"
         tab-contents="cellularDeviceTab">
-      <span class="inactive-tab-label"
+      <span class="tab-label"
           i18n-content="cellularDeviceTabLabel"></span>
       <span class="active-tab-label"
           i18n-content="cellularDeviceTabLabel"></span>
     </span>
-    <span id="internetNavTab" class="inactive-tab" tab-contents="internetTab">
-      <span class="inactive-tab-label" i18n-content="networkTabLabel"></span>
+    <span id="internetNavTab" class="tab" tab-contents="internetTab">
+      <span class="tab-label" i18n-content="networkTabLabel"></span>
       <span class="active-tab-label" i18n-content="networkTabLabel"></span>
     </span>
   </div>
diff --git a/chrome/browser/resources/options/chromeos_internet_options.html b/chrome/browser/resources/options/chromeos_internet_options.html
index 4dde7d4..c42ecd7 100644
--- a/chrome/browser/resources/options/chromeos_internet_options.html
+++ b/chrome/browser/resources/options/chromeos_internet_options.html
@@ -1,5 +1,9 @@
 <div class="page hidden" id="internetPage">
   <h1 i18n-content="internetPage"></h1>
+  <div id="lockedNetworkBanner">
+    <span id="lockedNetworkIcon"></span>
+    <span id="accessLockedText" i18n-content="accessLockedMsg"></span>
+  </div>
   <section id="wirelessButtons">
    <h3 i18n-content="generalNetworkingTitle"></h3>
    <div id="networkingControls">
diff --git a/chrome/browser/resources/options/chromeos_internet_options.js b/chrome/browser/resources/options/chromeos_internet_options.js
index 37556f9..59df059 100644
--- a/chrome/browser/resources/options/chromeos_internet_options.js
+++ b/chrome/browser/resources/options/chromeos_internet_options.js
@@ -1,9 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 cr.define('options', function() {
-
   var OptionsPage = options.OptionsPage;
 
   /////////////////////////////////////////////////////////////////////////////
@@ -14,8 +13,8 @@
    * @constructor
    */
   function InternetOptions() {
-    OptionsPage.call(this, 'internet', localStrings.getString('internetPage'),
-        'internetPage');
+    OptionsPage.call(this, 'internet', templateData.internetPageTabTitle,
+                     'internetPage');
   }
 
   cr.addSingletonGetter(InternetOptions);
@@ -31,6 +30,11 @@
     initializePage: function() {
       OptionsPage.prototype.initializePage.call(this);
 
+      if (templateData.accessLocked) {
+        var page = $('internetPage');
+        page.setAttribute('accesslocked', true);
+      }
+
       options.internet.NetworkElement.decorate($('wiredList'));
       $('wiredList').load(templateData.wiredList);
       options.internet.NetworkElement.decorate($('wirelessList'));
@@ -45,7 +49,7 @@
       $('rememberedSection').hidden = (templateData.rememberedList.length == 0);
       InternetOptions.setupAttributes(templateData);
       $('detailsInternetDismiss').addEventListener('click', function(event) {
-        OptionsPage.clearOverlays();
+        OptionsPage.closeOverlay();
       });
       $('detailsInternetLogin').addEventListener('click', function(event) {
         InternetOptions.loginFromDetails();
@@ -71,7 +75,7 @@
       });
       $('buyplanDetails').addEventListener('click', function(event) {
         chrome.send('buyDataPlan', []);
-        OptionsPage.clearOverlays();
+        OptionsPage.closeOverlay();
       });
       this.showNetworkDetails_();
     },
@@ -89,7 +93,7 @@
   };
 
   // A boolean flag from InternerOptionsHandler to indicate whether to use
-  // inline DOMUI for ethernet/wifi login/options.
+  // inline WebUI for ethernet/wifi login/options.
   InternetOptions.useSettingsUI = false;
 
   // Network status update will be blocked while typing in WEP password etc.
@@ -116,7 +120,7 @@
                                             servicePath,
                                             'connect']);
     }
-    OptionsPage.clearOverlays();
+    OptionsPage.closeOverlay();
   };
 
   InternetOptions.activateFromDetails = function () {
@@ -127,7 +131,7 @@
                                           servicePath,
                                           'activate']);
     }
-    OptionsPage.clearOverlays();
+    OptionsPage.closeOverlay();
   };
 
   InternetOptions.setupAttributes = function(data) {
@@ -175,6 +179,12 @@
   //Chrome callbacks
   //
   InternetOptions.refreshNetworkData = function (data) {
+    var page = $('internetPage');
+    if (data.accessLocked) {
+      page.setAttribute('accesslocked', true);
+      return;
+    }
+    page.removeAttribute('accesslocked');
     if (InternetOptions.updateLocked) {
       InternetOptions.updateData = data;
       InternetOptions.updatePending = true;
@@ -347,12 +357,11 @@
       page.removeAttribute('cellular');
       page.removeAttribute('gsm');
     }
-    OptionsPage.showOverlay('detailsInternetPage');
+    OptionsPage.navigateToPage('detailsInternetPage');
   };
 
   // Export
   return {
     InternetOptions: InternetOptions
   };
-
 });
diff --git a/chrome/browser/resources/options/chromeos_internet_options_page.css b/chrome/browser/resources/options/chromeos_internet_options_page.css
index d2ba444..753b2b6 100644
--- a/chrome/browser/resources/options/chromeos_internet_options_page.css
+++ b/chrome/browser/resources/options/chromeos_internet_options_page.css
@@ -6,10 +6,6 @@
   border: none;
 }
 
-#internetPage > section {
-  display: block;
-}
-
 #internetPage > section > h3 {
   font-size: 100%;
   width: auto;
@@ -150,6 +146,38 @@
   float: left;
 }
 
+#lockedNetworkBanner {
+  height: 31px;
+  width: 100%;
+  margin: 0;
+  padding-top: 10px;
+  vertical-align: middle;
+}
+
+#lockedNetworkIcon {
+  background-image: url("chrome://theme/IDR_WARNING");
+  background-repeat: no-repeat;
+  background-position:center;
+  display: inline-block;
+  padding: 5px;
+  height: 21px;
+  vertical-align: middle;
+  width: 24px;
+}
+
+#accessLockedText {
+  vertical-align: middle;
+}
+
+#internetPage:not([accesslocked]) #lockedNetworkBanner,
+#internetPage[accesslocked] #wirelessButtons,
+#internetPage[accesslocked] #wiredSection,
+#internetPage[accesslocked] #wirelessSection,
+#internetPage[accesslocked] #rememberedSection,
+#internetPage[accesslocked] #detailsInternetPage {
+  display: none;
+}
+
 #detailsInternetPage:not([connected]) > #advancedSection,
 #detailsInternetPage[connecting] > * > #detailsInternetLogin,
 #detailsInternetPage[connected] > * > #detailsInternetLogin,
diff --git a/chrome/browser/resources/options/chromeos_language_add_language_overlay.html b/chrome/browser/resources/options/chromeos_language_add_language_overlay.html
deleted file mode 100644
index 78747a1..0000000
--- a/chrome/browser/resources/options/chromeos_language_add_language_overlay.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<div class="page hidden" id="add-language-overlay-page">
-  <ul id="add-language-overlay-language-list">
-  </ul>
-  <button id="add-language-overlay-cancel-button"
-          i18n-content="cancel"></button>
-</div>
diff --git a/chrome/browser/resources/options/chromeos_language_add_language_overlay.js b/chrome/browser/resources/options/chromeos_language_add_language_overlay.js
deleted file mode 100644
index b86e1cc..0000000
--- a/chrome/browser/resources/options/chromeos_language_add_language_overlay.js
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-///////////////////////////////////////////////////////////////////////////////
-// AddLanguageOverlay class:
-
-cr.define('options.language', function() {
-
-  const OptionsPage = options.OptionsPage;
-
-  /**
-   * Encapsulated handling of ChromeOS add language overlay page.
-   * @constructor
-   */
-  function AddLanguageOverlay() {
-    OptionsPage.call(this, 'addLanguageOverlay',
-                     localStrings.getString('add_button'),
-                     'add-language-overlay-page');
-  }
-
-  cr.addSingletonGetter(AddLanguageOverlay);
-
-  AddLanguageOverlay.prototype = {
-    // Inherit AddLanguageOverlay from OptionsPage.
-    __proto__: OptionsPage.prototype,
-
-    /**
-     * Initializes AddLanguageOverlay page.
-     * Calls base class implementation to starts preference initialization.
-     */
-    initializePage: function() {
-      // Call base class implementation to starts preference initialization.
-      OptionsPage.prototype.initializePage.call(this);
-
-      // Set up the cancel button.
-      $('add-language-overlay-cancel-button').onclick = function(e) {
-        OptionsPage.clearOverlays();
-      };
-
-      // Create the language list with which users can add a language.
-      // Note that we have about 40 languages.
-      var addLanguageList = $('add-language-overlay-language-list');
-      var languageListData = templateData.languageList;
-      for (var i = 0; i < languageListData.length; i++) {
-        var language = languageListData[i];
-        var button = document.createElement('button');
-        button.className = 'link-button';
-        button.textContent = language.displayName;
-        // If the native name is different, add it.
-        if (language.displayName != language.nativeDisplayName) {
-          button.textContent += ' - ' + language.nativeDisplayName;
-        }
-        button.languageCode = language.code;
-        var li = document.createElement('li');
-        li.languageCode = language.code;
-        li.appendChild(button);
-        addLanguageList.appendChild(li);
-      }
-    },
-  };
-
-  return {
-    AddLanguageOverlay: AddLanguageOverlay
-  };
-});
diff --git a/chrome/browser/resources/options/chromeos_language_chewing_options.html b/chrome/browser/resources/options/chromeos_language_chewing_options.html
index dd11a85..810ecc8 100644
--- a/chrome/browser/resources/options/chromeos_language_chewing_options.html
+++ b/chrome/browser/resources/options/chromeos_language_chewing_options.html
@@ -97,6 +97,7 @@
          <td class="option-value">
            <select id="chewing-cand-per-page" class="control"
                 pref="settings.language.chewing_cand_per_page"
+                dataType="string"
                 i18n-options="Chewing_candPerPageValue"></select>
          </td>
        </tr>
@@ -105,6 +106,7 @@
          <td class="option-value">
            <select id="chewing-keyboard-type" class="control"
                 pref="settings.language.chewing_keyboard_type"
+                dataType="string"
                 i18n-options="Chewing_KBTypeValue"></select>
          </td>
        </tr>
@@ -113,6 +115,7 @@
          <td class="option-value">
            <select id="chewing-sel-keys" class="control"
                 pref="settings.language.chewing_sel_keys"
+                dataType="string"
                 i18n-options="Chewing_selKeysValue"></select>
          </td>
        </tr>
@@ -121,6 +124,7 @@
          <td class="option-value">
            <select id="chewing-sel-key-type" class="control"
                 pref="settings.language.chewing_hsu_sel_key_type"
+                dataType="string"
                 i18n-options="Chewing_hsuSelKeyTypeValue"></select>
          </td>
        </tr>
diff --git a/chrome/browser/resources/options/chromeos_language_customize_modifier_keys_overlay.html b/chrome/browser/resources/options/chromeos_language_customize_modifier_keys_overlay.html
index af29a3a..515e54c 100644
--- a/chrome/browser/resources/options/chromeos_language_customize_modifier_keys_overlay.html
+++ b/chrome/browser/resources/options/chromeos_language_customize_modifier_keys_overlay.html
@@ -1,11 +1,12 @@
 <div class="page hidden" id="languageCustomizeModifierKeysOverlay">
-  <section>
+  <div class="content-area">
     <table class="option-control-table">
        <tr>
          <td class="option-name" i18n-content="xkbRemapSearchKeyToContent"></td>
          <td class="option-value">
            <select id="xkb-remap-search-key-to" class="control"
                 pref="settings.language.xkb_remap_search_key_to"
+                dataType="number"
                 i18n-options="xkbRemapSearchKeyToValue"></select>
          </td>
        </tr>
@@ -15,6 +16,7 @@
          <td class="option-value">
            <select id="xkb-remap-control-key-to" class="control"
                 pref="settings.language.xkb_remap_control_key_to"
+                dataType="number"
                 i18n-options="xkbRemapControlKeyToValue"></select>
          </td>
        </tr>
@@ -23,12 +25,17 @@
          <td class="option-value">
            <select id="xkb-remap-alt-key-to" class="control"
                 pref="settings.language.xkb_remap_alt_key_to"
+                dataType="number"
                 i18n-options="xkbRemapAltKeyToValue"></select>
          </td>
        </tr>
     </table>
-  </section>
-  <button id="languageCustomizeModifierKeysOverleyDismissButton"
-      i18n-content="close"
-      onclick="OptionsPage.clearOverlays();"></button>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button id="languageCustomizeModifierKeysOverleyDismissButton"
+          i18n-content="close"
+          onclick="OptionsPage.closeOverlay();"></button>
+    </div>
+  </div>
 </div>
diff --git a/chrome/browser/resources/options/chromeos_language_hangul_options.html b/chrome/browser/resources/options/chromeos_language_hangul_options.html
index 7746a7b..6bda90d 100644
--- a/chrome/browser/resources/options/chromeos_language_hangul_options.html
+++ b/chrome/browser/resources/options/chromeos_language_hangul_options.html
@@ -8,6 +8,7 @@
          <td class="option-value">
            <select id="keyboard-layout-select" class="control"
                 pref="settings.language.hangul_keyboard"
+                dataType="string"
                 i18n-options="HangulkeyboardLayoutList"></select>
          </td>
        </tr>
diff --git a/chrome/browser/resources/options/chromeos_language_list.js b/chrome/browser/resources/options/chromeos_language_list.js
deleted file mode 100644
index df47550..0000000
--- a/chrome/browser/resources/options/chromeos_language_list.js
+++ /dev/null
@@ -1,351 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('options.language', function() {
-  const ArrayDataModel = cr.ui.ArrayDataModel;
-  const LanguageOptions = options.LanguageOptions;
-  const List = cr.ui.List;
-  const ListItem = cr.ui.ListItem;
-  const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
-
-  /**
-   * Creates a new language list.
-   * @param {Object=} opt_propertyBag Optional properties.
-   * @constructor
-   * @extends {cr.ui.List}
-   */
-  var LanguageList = cr.ui.define('list');
-
-  /**
-   * Gets display name from the given language code.
-   * @param {string} languageCode Language code (ex. "fr").
-   */
-  LanguageList.getDisplayNameFromLanguageCode = function(languageCode) {
-    // Build the language code to display name dictionary at first time.
-    if (!this.languageCodeToDisplayName_) {
-      this.languageCodeToDisplayName_ = {};
-      var languageList = templateData.languageList;
-      for (var i = 0; i < languageList.length; i++) {
-        var language = languageList[i];
-        this.languageCodeToDisplayName_[language.code] = language.displayName;
-      }
-    }
-
-    return this.languageCodeToDisplayName_[languageCode];
-  }
-
-  /**
-   * Gets native display name from the given language code.
-   * @param {string} languageCode Language code (ex. "fr").
-   */
-  LanguageList.getNativeDisplayNameFromLanguageCode = function(languageCode) {
-    // Build the language code to display name dictionary at first time.
-    if (!this.languageCodeToNativeDisplayName_) {
-      this.languageCodeToNativeDisplayName_ = {};
-      var languageList = templateData.languageList;
-      for (var i = 0; i < languageList.length; i++) {
-        var language = languageList[i];
-        this.languageCodeToNativeDisplayName_[language.code] =
-            language.nativeDisplayName;
-      }
-    }
-
-    return this.languageCodeToNativeDisplayName_[languageCode];
-  }
-
-  /**
-   * Returns true if the given language code is valid.
-   * @param {string} languageCode Language code (ex. "fr").
-   */
-  LanguageList.isValidLanguageCode = function(languageCode) {
-    // Having the display name for the language code means that the
-    // language code is valid.
-    if (LanguageList.getDisplayNameFromLanguageCode(languageCode)) {
-      return true;
-    }
-    return false;
-  }
-
-  LanguageList.prototype = {
-    __proto__: List.prototype,
-
-    // The list item being dragged.
-    draggedItem: null,
-    // The drop position information: "below" or "above".
-    dropPos: null,
-    // The preference is a CSV string that describes preferred languages
-    // in Chrome OS. The language list is used for showing the language
-    // list in "Language and Input" options page.
-    preferredLanguagesPref: 'settings.language.preferred_languages',
-    // The preference is a CSV string that describes accept languages used
-    // for content negotiation. To be more precise, the list will be used
-    // in "Accept-Language" header in HTTP requests.
-    acceptLanguagesPref: 'intl.accept_languages',
-
-    /** @inheritDoc */
-    decorate: function() {
-      List.prototype.decorate.call(this);
-      this.selectionModel = new ListSingleSelectionModel;
-
-      // HACK(arv): http://crbug.com/40902
-      window.addEventListener('resize', this.redraw.bind(this));
-
-      // Listen to pref change.
-      Preferences.getInstance().addEventListener(this.preferredLanguagesPref,
-          this.handlePreferredLanguagesPrefChange_.bind(this));
-
-      // Listen to drag and drop events.
-      this.addEventListener('dragstart', this.handleDragStart_.bind(this));
-      this.addEventListener('dragenter', this.handleDragEnter_.bind(this));
-      this.addEventListener('dragover', this.handleDragOver_.bind(this));
-      this.addEventListener('drop', this.handleDrop_.bind(this));
-    },
-
-    createItem: function(languageCode) {
-      var languageDisplayName =
-          LanguageList.getDisplayNameFromLanguageCode(languageCode);
-      var languageNativeDisplayName =
-          LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
-      return new ListItem({
-        label: languageDisplayName,
-        draggable: true,
-        languageCode: languageCode,
-        title: languageNativeDisplayName  // Show native name as tooltip.
-      });
-    },
-
-    /*
-     * Adds a language to the language list.
-     * @param {string} languageCode language code (ex. "fr").
-     */
-    addLanguage: function(languageCode) {
-      // It shouldn't happen but ignore the language code if it's
-      // null/undefined, or already present.
-      if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) {
-        return;
-      }
-      this.dataModel.push(languageCode);
-      // Select the last item, which is the language added.
-      this.selectionModel.selectedIndex = this.dataModel.length - 1;
-
-      this.savePreference_();
-    },
-
-    /*
-     * Gets the language codes of the currently listed languages.
-     */
-    getLanguageCodes: function() {
-      return this.dataModel.slice();
-    },
-
-    /*
-     * Gets the language code of the selected language.
-     */
-    getSelectedLanguageCode: function() {
-      return this.selectedItem;
-    },
-
-    /*
-     * Selects the language by the given language code.
-     * @returns {boolean} True if the operation is successful.
-     */
-    selectLanguageByCode: function(languageCode) {
-      var index = this.dataModel.indexOf(languageCode);
-      if (index >= 0) {
-        this.selectionModel.selectedIndex = index;
-        return true;
-      }
-      return false;
-    },
-
-    /*
-     * Removes the currently selected language.
-     */
-    removeSelectedLanguage: function() {
-      if (this.selectionModel.selectedIndex >= 0) {
-        this.dataModel.splice(this.selectionModel.selectedIndex, 1);
-        // Once the selected item is removed, there will be no selected item.
-        // Select the item pointed by the lead index.
-        this.selectionModel.selectedIndex = this.selectionModel.leadIndex;
-        this.savePreference_();
-      }
-    },
-
-    /*
-     * Handles the dragstart event.
-     * @param {Event} e The dragstart event.
-     * @private
-     */
-    handleDragStart_: function(e) {
-      var target = e.target;
-      // ListItem should be the only draggable element type in the page,
-      // but just in case.
-      if (target instanceof ListItem) {
-        this.draggedItem = target;
-        e.dataTransfer.effectAllowed = 'move';
-      }
-    },
-
-    /*
-     * Handles the dragenter event.
-     * @param {Event} e The dragenter event.
-     * @private
-     */
-    handleDragEnter_: function(e) {
-      e.preventDefault();
-    },
-
-    /*
-     * Handles the dragover event.
-     * @param {Event} e The dragover event.
-     * @private
-     */
-    handleDragOver_: function(e) {
-      var dropTarget = e.target;
-      // Determins whether the drop target is to accept the drop.
-      // The drop is only successful on another ListItem.
-      if (!(dropTarget instanceof ListItem) ||
-          dropTarget == this.draggedItem) {
-        return;
-      }
-      // Compute the drop postion. Should we move the dragged item to
-      // below or above the drop target?
-      var rect = dropTarget.getBoundingClientRect();
-      var dy = e.clientY - rect.top;
-      var yRatio = dy / rect.height;
-      var dropPos = yRatio <= .5 ? 'above' : 'below';
-      this.dropPos = dropPos;
-      e.preventDefault();
-      // TODO(satorux): Show the drop marker just like the bookmark manager.
-    },
-
-    /*
-     * Handles the drop event.
-     * @param {Event} e The drop event.
-     * @private
-     */
-    handleDrop_: function(e) {
-      var dropTarget = e.target;
-
-      // Delete the language from the original position.
-      var languageCode = this.draggedItem.languageCode;
-      var originalIndex = this.dataModel.indexOf(languageCode);
-      this.dataModel.splice(originalIndex, 1);
-      // Insert the language to the new position.
-      var newIndex = this.dataModel.indexOf(dropTarget.languageCode);
-      if (this.dropPos == 'below')
-        newIndex += 1;
-      this.dataModel.splice(newIndex, 0, languageCode);
-      // The cursor should move to the moved item.
-      this.selectionModel.selectedIndex = newIndex;
-      // Save the preference.
-      this.savePreference_();
-    },
-
-    /**
-     * Handles preferred languages pref change.
-     * @param {Event} e The change event object.
-     * @private
-     */
-    handlePreferredLanguagesPrefChange_: function(e) {
-      var languageCodesInCsv = e.value.value;
-      var languageCodes = this.filterBadLanguageCodes_(
-          languageCodesInCsv.split(','));
-      this.load_(languageCodes);
-    },
-
-    /**
-     * Loads given language list.
-     * @param {Array} languageCodes List of language codes.
-     * @private
-     */
-    load_: function(languageCodes) {
-      // Preserve the original selected index. See comments below.
-      var originalSelectedIndex = (this.selectionModel ?
-                                   this.selectionModel.selectedIndex : -1);
-      this.dataModel = new ArrayDataModel(languageCodes);
-      if (originalSelectedIndex >= 0 &&
-          originalSelectedIndex < this.dataModel.length) {
-        // Restore the original selected index if the selected index is
-        // valid after the data model is loaded. This is neeeded to keep
-        // the selected language after the languge is added or removed.
-        this.selectionModel.selectedIndex = originalSelectedIndex;
-        // The lead index should be updated too.
-        this.selectionModel.leadIndex = originalSelectedIndex;
-      } else if (this.dataModel.length > 0){
-        // Otherwise, select the first item if it's not empty.
-        // Note that ListSingleSelectionModel won't select an item
-        // automatically, hence we manually select the first item here.
-        this.selectionModel.selectedIndex = 0;
-      }
-    },
-
-    /**
-     * Saves the preference.
-     */
-    savePreference_: function() {
-      // Encode the language codes into a CSV string.
-      Preferences.setStringPref(this.preferredLanguagesPref,
-                                this.dataModel.slice().join(','));
-      // Save the same language list as accept languages preference as
-      // well, but we need to expand the language list, to make it more
-      // acceptable. For instance, some web sites don't understand 'en-US'
-      // but 'en'. See crosbug.com/9884.
-      var acceptLanguages = this.expandLanguageCodes(this.dataModel.slice());
-      Preferences.setStringPref(this.acceptLanguagesPref,
-                                acceptLanguages.join(','));
-      cr.dispatchSimpleEvent(this, 'save');
-    },
-
-    /**
-     * Expands language codes to make these more suitable for Accept-Language.
-     * Example: ['en-US', 'ja', 'en-CA'] => ['en-US', 'en', 'ja', 'en-CA'].
-     * 'en' won't appear twice as this function eliminates duplicates.
-     * @param {Array} languageCodes List of language codes.
-     * @private
-     */
-    expandLanguageCodes: function(languageCodes) {
-      var expandedLanguageCodes = [];
-      var seen = {};  // Used to eliminiate duplicates.
-      for (var i = 0; i < languageCodes.length; i++) {
-        var languageCode = languageCodes[i];
-        if (!(languageCode in seen)) {
-          expandedLanguageCodes.push(languageCode);
-          seen[languageCode] = true;
-        }
-        var parts = languageCode.split('-');
-        if (!(parts[0] in seen)) {
-          expandedLanguageCodes.push(parts[0]);
-          seen[parts[0]] = true;
-        }
-      }
-      return expandedLanguageCodes;
-    },
-
-    /**
-     * Filters bad language codes in case bad language codes are
-     * stored in the preference. Removes duplicates as well.
-     * @param {Array} languageCodes List of language codes.
-     * @private
-     */
-    filterBadLanguageCodes_: function(languageCodes) {
-      var filteredLanguageCodes = [];
-      var seen = {};
-      for (var i = 0; i < languageCodes.length; i++) {
-        // Check if the the language code is valid, and not
-        // duplicate. Otherwise, skip it.
-        if (LanguageList.isValidLanguageCode(languageCodes[i]) &&
-            !(languageCodes[i] in seen)) {
-          filteredLanguageCodes.push(languageCodes[i]);
-          seen[languageCodes[i]] = true;
-        }
-      }
-      return filteredLanguageCodes;
-    },
-  };
-
-  return {
-    LanguageList: LanguageList
-  };
-});
diff --git a/chrome/browser/resources/options/chromeos_language_mozc_options.html b/chrome/browser/resources/options/chromeos_language_mozc_options.html
index 0b40fc5..2d3c6c5 100644
--- a/chrome/browser/resources/options/chromeos_language_mozc_options.html
+++ b/chrome/browser/resources/options/chromeos_language_mozc_options.html
@@ -87,6 +87,7 @@
         <td class="option-value">
           <select id="mozc-preedit-method" class="control"
               pref="settings.language.mozc_preedit_method"
+              dataType="string"
               i18n-options="mozc_preedit_methodValue"></select>
          </td>
        </tr>
@@ -95,6 +96,7 @@
          <td class="option-value">
            <select id="mozc-session-keymap" class="control"
                pref="settings.language.mozc_session_keymap"
+               dataType="string"
                i18n-options="mozc_session_keymapValue"></select>
          </td>
        </tr>
@@ -103,6 +105,7 @@
          <td class="option-value">
            <select id="mozc-punctuation-method" class="control"
                pref="settings.language.mozc_punctuation_method"
+               dataType="string"
                i18n-options="mozc_punctuation_methodValue"></select>
          </td>
        </tr>
@@ -111,6 +114,7 @@
          <td class="option-value">
            <select id="mozc-symbol-method" class="control"
                pref="settings.language.mozc_symbol_method"
+               dataType="string"
                i18n-options="mozc_symbol_methodValue"></select>
          </td>
        </tr>
@@ -120,6 +124,7 @@
          <td class="option-value">
            <select id="mozc-space-character-form" class="control"
                pref="settings.language.mozc_space_character_form"
+               dataType="string"
                i18n-options="mozc_space_character_formValue"></select>
          </td>
        </tr>
@@ -129,6 +134,7 @@
          <td class="option-value">
            <select id="mozc-history-learning-level" class="control"
                pref="settings.language.mozc_history_learning_level"
+               dataType="string"
                i18n-options="mozc_history_learning_levelValue"></select>
          </td>
        </tr>
@@ -138,6 +144,7 @@
          <td class="option-value">
            <select id="mozc-shift-key-mode-switch" class="control"
                pref="settings.language.mozc_shift_key_mode_switch"
+               dataType="string"
                i18n-options="mozc_shift_key_mode_switchValue"></select>
          </td>
        </tr>
@@ -147,6 +154,7 @@
          <td class="option-value">
            <select id="mozc-numpad-character-form" class="control"
                pref="settings.language.mozc_numpad_character_form"
+               dataType="string"
                i18n-options="mozc_numpad_character_formValue"></select>
          </td>
        </tr>
@@ -156,6 +164,7 @@
          <td class="option-value">
            <select id="mozc-suggestions-size" class="control"
                pref="settings.language.mozc_suggestions_size"
+               dataType="string"
                i18n-options="mozc_suggestions_sizeValue"></select>
          </td>
        </tr>
diff --git a/chrome/browser/resources/options/chromeos_language_options.css b/chrome/browser/resources/options/chromeos_language_options.css
deleted file mode 100644
index 53dfdca..0000000
--- a/chrome/browser/resources/options/chromeos_language_options.css
+++ /dev/null
@@ -1,168 +0,0 @@
-.language-options {
-  display: -webkit-box;
-  margin: 15px;
-}
-
-.language-options button {
-  min-width: 70px;
-}
-
-.language-options h3 {
-  -webkit-margin-start: 12px;
-  font-size: 75%;
-  font-weight: bold;
-  margin-top: 12px;
-}
-
-.language-options label {
-  display: block;
-}
-
-.language-options-contents  {
-  -webkit-padding-start: 12px;
-  -webkit-padding-end: 12px;
-  padding-bottom: 10px;
-}
-
-.language-options-header, .language-options-footer {
-  margin: 15px;
-}
-
-.language-options-left, .language-options-right {
-  border: 1px solid #cccccc;
-  vertical-align: top;
-  padding: 0;
-  height: 400px;
-}
-
-.language-options-left {
-  -webkit-box-orient: vertical;
-  display: -webkit-box;
-  background-color: #ebeff9;
-  min-width: 200px;
-}
-
-.language-options-lower-left {
-  -webkit-box-flex: 0;
-  -webkit-padding-start: 12px;
-  padding-bottom: 10px;
-}
-
-.language-options-right {
-  /* To share the center line with the left pane. */
-  -webkit-margin-start: -1px;
-  width: 360px;
-}
-
-.language-options-notification {
-  display: none;
-  background-color: #fff29e;
-  border-top: 1px solid #ccc;
-  border-bottom: 1px solid #ccc;
-  padding: 12px 30px 12px 12px;
-}
-
-#language-options-input-method-list button {
-  display: block;
-  -webkit-margin-start: 20px;
-}
-
-#language-options-input-method-list label {
-  margin: 4px 0;
-}
-
-#language-options-list {
-  -webkit-box-flex: 1;
-  padding: 0;
-  width: 100%;
-}
-
-#language-options-list li {
-  -webkit-padding-start: 12px;
-  padding-top: 2px;
-  padding-bottom: 2px;
-}
-
-#language-options-ui-restart-button {
-  margin-top: 12px;
-}
-
-#add-language-overlay-language-list {
-  -webkit-column-count: 2;
-  -webkit-column-gap: 20px;
-}
-
-#add-language-overlay-cancel-button {
-  /* Place the button in the center. */
-  display: block;
-  margin: auto;
-  margin-top: 15px;
-}
-
-#add-language-overlay-page {
-  width: 800px;
-}
-
-#add-language-overlay-page button {
-  padding: 0;
-  text-align: left;
-}
-
-#add-language-overlay-page ul {
-  padding: 0;
-  margin: 0;
-}
-/* TODO(kochi): This is temporary copy from new_new_tab.css */
-/* Notification */
-
-#notification {
-  position: relative;
-  background-color: hsl(52, 100%, 80%);
-  border: 1px solid rgb(211, 211, 211);
-  border-radius: 6px;
-  padding: 7px 15px;
-  white-space: nowrap;
-  display: table;
-  /* Set the height and margin so that the element does not use any vertical
-    space */
-  height: 16px;
-  margin: -44px auto 12px auto;
-  font-weight: bold;
-  opacity: 0;
-  pointer-events: none;
-  -webkit-transition: opacity .15s;
-  z-index: 1;
-  color: black;
-}
-
-#notification > * {
-  display: table-cell;
-  max-width: 500px;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-#notification.show {
-  opacity: 1;
-  pointer-events: all;
-  -webkit-transition: opacity 1s;
-}
-
-#notification .link {
-  cursor: pointer;
-  text-decoration: underline;
-  -webkit-appearance: none;
-  border: 0;
-  background: none;
-  color: rgba(0, 102, 204, 0.3);
-  -webkit-padding-start: 20px;
-}
-
-#notification .link-color {
-  color: rgb(0, 102, 204);
-}
-
-#chewing-max-chi-symbol-len {
-  width: 100px;
-  height: 30%;
-}
diff --git a/chrome/browser/resources/options/chromeos_language_options.html b/chrome/browser/resources/options/chromeos_language_options.html
deleted file mode 100644
index 89531ad..0000000
--- a/chrome/browser/resources/options/chromeos_language_options.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<link rel="stylesheet" href="chrome://resources/css/list.css">
-
-<div class="page hidden" id="languagePage">
-  <h1 i18n-content="languagePage"></h1>
-  <div id="notification">
-    <span>&nbsp;</span>
-    <span class="link"><span class="link-color"></span></span>
-  </div>
-  <div class="language-options-header">
-    <div i18n-content="add_language_instructions"></div>
-    <div i18n-content="input_method_instructions"></div>
-  </div>
-  <div class="language-options">
-    <div class="language-options-left">
-      <h3 i18n-content="languages"></h3>
-      <list id="language-options-list"></list>
-      <div class="language-options-lower-left">
-        <button id="language-options-add-button"
-                i18n-content="add_button"></button>
-        <button id="language-options-remove-button"
-                i18n-content="remove_button"></button>
-      </div>
-    </div>
-    <div class="language-options-right">
-      <h3 id="language-options-language-name"></h3>
-      <div class="language-options-contents">
-        <button id="language-options-ui-language-button"></button>
-      </div>
-      <div class="language-options-contents">
-        <button id="language-options-spell-check-language-button"></button>
-      </div>
-      <div id="language-options-ui-notification-bar"
-           class="language-options-notification">
-        <div i18n-content="sign_out_required"></div>
-        <button id="language-options-ui-sign-out-button"
-                i18n-content="sign_out_button"></button>
-      </div>
-      <h3 i18n-content="input_method"></h3>
-      <div id="language-options-input-method-list"
-           class="language-options-contents">
-      </div>
-    </div>
-  </div>
-  <div class="language-options-footer">
-    <div i18n-content="switch_input_methods_hint"></div>
-    <div i18n-content="select_previous_input_method_hint"></div>
-  </div>
-</div>
diff --git a/chrome/browser/resources/options/chromeos_language_options.js b/chrome/browser/resources/options/chromeos_language_options.js
deleted file mode 100644
index af09401..0000000
--- a/chrome/browser/resources/options/chromeos_language_options.js
+++ /dev/null
@@ -1,761 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(kochi): Generalize the notification as a component and put it
-// in js/cr/ui/notification.js .
-
-cr.define('options', function() {
-
-  const OptionsPage = options.OptionsPage;
-  const AddLanguageOverlay = options.language.AddLanguageOverlay;
-  const LanguageList = options.language.LanguageList;
-
-  // Some input methods like Chinese Pinyin have config pages.
-  // This is the map of the input method names to their config page names.
-  const INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME = {
-    'chewing': 'languageChewing',
-    'hangul': 'languageHangul',
-    'mozc': 'languageMozc',
-    'mozc-dv': 'languageMozc',
-    'mozc-jp': 'languageMozc',
-    'pinyin': 'languagePinyin',
-  };
-
-  /////////////////////////////////////////////////////////////////////////////
-  // LanguageOptions class:
-
-  /**
-   * Encapsulated handling of ChromeOS language options page.
-   * @constructor
-   */
-  function LanguageOptions(model) {
-    OptionsPage.call(this, 'language', localStrings.getString('languagePage'),
-                     'languagePage');
-  }
-
-  cr.addSingletonGetter(LanguageOptions);
-
-  // Inherit LanguageOptions from OptionsPage.
-  LanguageOptions.prototype = {
-    __proto__: OptionsPage.prototype,
-
-    /**
-     * Initializes LanguageOptions page.
-     * Calls base class implementation to starts preference initialization.
-     */
-    initializePage: function() {
-      OptionsPage.prototype.initializePage.call(this);
-
-      var languageOptionsList = $('language-options-list');
-      LanguageList.decorate(languageOptionsList);
-
-      languageOptionsList.addEventListener('change',
-          this.handleLanguageOptionsListChange_.bind(this));
-      languageOptionsList.addEventListener('save',
-          this.handleLanguageOptionsListSave_.bind(this));
-
-      this.addEventListener('visibleChange',
-                            this.handleVisibleChange_.bind(this));
-
-      this.initializeInputMethodList_();
-      this.initializeLanguageCodeToInputMehotdIdsMap_();
-
-      // Set up add button.
-      $('language-options-add-button').onclick = function(e) {
-        // Add the language without showing the overlay if it's specified in
-        // the URL hash (ex. lang_add=ja).  Used for automated testing.
-        var match = document.location.hash.match(/\blang_add=([\w-]+)/);
-        if (match) {
-          var addLanguageCode = match[1];
-          $('language-options-list').addLanguage(addLanguageCode);
-        } else {
-          OptionsPage.showOverlay('addLanguageOverlay');
-        }
-      };
-      // Set up remove button.
-      $('language-options-remove-button').addEventListener('click',
-          this.handleRemoveButtonClick_.bind(this));
-
-      // Setup add language overlay page.
-      OptionsPage.registerOverlay(AddLanguageOverlay.getInstance());
-
-      // Listen to user clicks on the add language list.
-      var addLanguageList = $('add-language-overlay-language-list');
-      addLanguageList.addEventListener('click',
-          this.handleAddLanguageListClick_.bind(this));
-    },
-
-    // The preference is a CSV string that describes preload engines
-    // (i.e. active input methods).
-    preloadEnginesPref: 'settings.language.preload_engines',
-    // The list of preload engines, like ['mozc', 'pinyin'].
-    preloadEngines_: [],
-    // The preference is a string that describes the spell check
-    // dictionary language, like "en-US".
-    spellCheckDictionaryPref: 'spellcheck.dictionary',
-    spellCheckDictionary_: "",
-    // The map of language code to input method IDs, like:
-    // {'ja': ['mozc', 'mozc-jp'], 'zh-CN': ['pinyin'], ...}
-    languageCodeToInputMethodIdsMap_: {},
-
-    /**
-     * Initializes the input method list.
-     */
-    initializeInputMethodList_: function() {
-      var inputMethodList = $('language-options-input-method-list');
-      var inputMethodListData = templateData.inputMethodList;
-
-      // Add all input methods, but make all of them invisible here. We'll
-      // change the visibility in handleLanguageOptionsListChange_() based
-      // on the selected language. Note that we only have less than 100
-      // input methods, so creating DOM nodes at once here should be ok.
-      for (var i = 0; i < inputMethodListData.length; i++) {
-        var inputMethod = inputMethodListData[i];
-        var input = document.createElement('input');
-        input.type = 'checkbox';
-        input.inputMethodId = inputMethod.id;
-        // Listen to user clicks.
-        input.addEventListener('click',
-                               this.handleCheckboxClick_.bind(this));
-        var label = document.createElement('label');
-        label.appendChild(input);
-        label.appendChild(document.createTextNode(inputMethod.displayName));
-        label.style.display = 'none';
-        label.languageCodeSet = inputMethod.languageCodeSet;
-        // Add the configure button if the config page is present for this
-        // input method.
-        if (inputMethod.id in INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME) {
-          var pageName = INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME[inputMethod.id];
-          var button = this.createConfigureInputMethodButton_(inputMethod.id,
-                                                              pageName);
-          label.appendChild(button);
-        }
-
-        inputMethodList.appendChild(label);
-      }
-      // Listen to pref change once the input method list is initialized.
-      Preferences.getInstance().addEventListener(this.preloadEnginesPref,
-          this.handlePreloadEnginesPrefChange_.bind(this));
-      Preferences.getInstance().addEventListener(this.spellCheckDictionaryPref,
-          this.handleSpellCheckDictionaryPrefChange_.bind(this));
-    },
-
-    /**
-     * Creates a configure button for the given input method ID.
-     * @param {string} inputMethodId Input method ID (ex. "pinyin").
-     * @param {string} pageName Name of the config page (ex. "languagePinyin").
-     * @private
-     */
-    createConfigureInputMethodButton_: function(inputMethodId, pageName) {
-      var button = document.createElement('button');
-      button.textContent = localStrings.getString('configure');
-      button.onclick = function(e) {
-        // Prevent the default action (i.e. changing the checked property
-        // of the checkbox). The button click here should not be handled
-        // as checkbox click.
-        e.preventDefault();
-        chrome.send('inputMethodOptionsOpen', [inputMethodId]);
-        OptionsPage.showPageByName(pageName);
-      }
-      return button;
-    },
-
-    /**
-     * Handles OptionsPage's visible property change event.
-     * @param {Event} e Property change event.
-     * @private
-     */
-    handleVisibleChange_: function(e) {
-      if (this.visible) {
-        $('language-options-list').redraw();
-        chrome.send('languageOptionsOpen');
-      }
-    },
-
-    /**
-     * Handles languageOptionsList's change event.
-     * @param {Event} e Change event.
-     * @private
-     */
-    handleLanguageOptionsListChange_: function(e) {
-      var languageOptionsList = $('language-options-list');
-      var languageCode = languageOptionsList.getSelectedLanguageCode();
-      // Select the language if it's specified in the URL hash (ex. lang=ja).
-      // Used for automated testing.
-      var match = document.location.hash.match(/\blang=([\w-]+)/);
-      if (match) {
-        var specifiedLanguageCode = match[1];
-        if (languageOptionsList.selectLanguageByCode(specifiedLanguageCode)) {
-          languageCode = specifiedLanguageCode;
-        }
-      }
-      this.updateSelectedLanguageName_(languageCode);
-      this.updateUiLanguageButton_(languageCode);
-      this.updateSpellCheckLanguageButton_(languageCode);
-      this.updateInputMethodList_(languageCode);
-      this.updateLanguageListInAddLanguageOverlay_();
-    },
-
-    /**
-     * Handles languageOptionsList's save event.
-     * @param {Event} e Save event.
-     * @private
-     */
-    handleLanguageOptionsListSave_: function(e) {
-      // Sort the preload engines per the saved languages before save.
-      this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
-      this.savePreloadEnginesPref_();
-    },
-
-    /**
-     * Sorts preloadEngines_ by languageOptionsList's order.
-     * @param {Array} preloadEngines List of preload engines.
-     * @return {Array} Returns sorted preloadEngines.
-     * @private
-     */
-    sortPreloadEngines_: function(preloadEngines) {
-      // For instance, suppose we have two languages and associated input
-      // methods:
-      //
-      // - Korean: hangul
-      // - Chinese: pinyin
-      //
-      // The preloadEngines preference should look like "hangul,pinyin".
-      // If the user reverse the order, the preference should be reorderd
-      // to "pinyin,hangul".
-      var languageOptionsList = $('language-options-list');
-      var languageCodes = languageOptionsList.getLanguageCodes();
-
-      // Convert the list into a dictonary for simpler lookup.
-      var preloadEngineSet = {};
-      for (var i = 0; i < preloadEngines.length; i++) {
-        preloadEngineSet[preloadEngines[i]] = true;
-      }
-
-      // Create the new preload engine list per the language codes.
-      var newPreloadEngines = [];
-      for (var i = 0; i < languageCodes.length; i++) {
-        var languageCode = languageCodes[i];
-        var inputMethodIds = this.languageCodeToInputMethodIdsMap_[
-            languageCode];
-        // Check if we have active input methods associated with the language.
-        for (var j = 0; j < inputMethodIds.length; j++) {
-          var inputMethodId = inputMethodIds[j];
-          if (inputMethodId in preloadEngineSet) {
-            // If we have, add it to the new engine list.
-            newPreloadEngines.push(inputMethodId);
-            // And delete it from the set. This is necessary as one input
-            // method can be associated with more than one language thus
-            // we should avoid having duplicates in the new list.
-            delete preloadEngineSet[inputMethodId];
-          }
-        }
-      }
-
-      return newPreloadEngines;
-    },
-
-    /**
-     * Initializes the map of language code to input method IDs.
-     * @private
-     */
-    initializeLanguageCodeToInputMehotdIdsMap_: function() {
-      var inputMethodList = templateData.inputMethodList;
-      for (var i = 0; i < inputMethodList.length; i++) {
-        var inputMethod = inputMethodList[i];
-        for (var languageCode in inputMethod.languageCodeSet) {
-          if (languageCode in this.languageCodeToInputMethodIdsMap_) {
-            this.languageCodeToInputMethodIdsMap_[languageCode].push(
-                inputMethod.id);
-          } else {
-            this.languageCodeToInputMethodIdsMap_[languageCode] =
-                [inputMethod.id];
-          }
-        }
-      }
-    },
-
-    /**
-     * Updates the currently selected language name.
-     * @param {string} languageCode Language code (ex. "fr").
-     * @private
-     */
-    updateSelectedLanguageName_: function(languageCode) {
-      var languageDisplayName = LanguageList.getDisplayNameFromLanguageCode(
-          languageCode);
-      var languageNativeDisplayName =
-          LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
-      // If the native name is different, add it.
-      if (languageDisplayName != languageNativeDisplayName) {
-        languageDisplayName += ' - ' + languageNativeDisplayName;
-      }
-      // Update the currently selected language name.
-      $('language-options-language-name').textContent = languageDisplayName;
-    },
-
-    /**
-     * Updates the UI language button.
-     * @param {string} languageCode Language code (ex. "fr").
-     * @private
-     */
-    updateUiLanguageButton_: function(languageCode) {
-      var uiLanguageButton = $('language-options-ui-language-button');
-      // Check if the language code matches the current UI language.
-      if (languageCode == templateData.currentUiLanguageCode) {
-        // If it matches, the button just says that the UI language is
-        // currently in use.
-        uiLanguageButton.textContent =
-            localStrings.getString('is_displayed_in_this_language');
-        // Make it look like a text label.
-        uiLanguageButton.className = 'text-button';
-        // Remove the event listner.
-        uiLanguageButton.onclick = undefined;
-      } else if (languageCode in templateData.uiLanguageCodeSet) {
-        // If the language is supported as UI language, users can click on
-        // the button to change the UI language.
-        uiLanguageButton.textContent =
-            localStrings.getString('display_in_this_language');
-        uiLanguageButton.className = '';
-        // Send the change request to Chrome.
-        uiLanguageButton.onclick = function(e) {
-          chrome.send('uiLanguageChange', [languageCode]);
-        }
-        $('language-options-ui-sign-out-button').onclick = function(e) {
-          chrome.send('uiLanguageSignOut');
-        }
-      } else {
-        // If the language is not supported as UI language, the button
-        // just says that Chromium OS cannot be displayed in this language.
-        uiLanguageButton.textContent =
-            localStrings.getString('cannot_be_displayed_in_this_language');
-        uiLanguageButton.className = 'text-button';
-        uiLanguageButton.onclick = undefined;
-      }
-      uiLanguageButton.style.display = 'block';
-      $('language-options-ui-notification-bar').style.display = 'none';
-    },
-
-    /**
-     * Updates the spell check language button.
-     * @param {string} languageCode Language code (ex. "fr").
-     * @private
-     */
-    updateSpellCheckLanguageButton_: function(languageCode) {
-      var spellCheckLanguageButton = $(
-          'language-options-spell-check-language-button');
-      // Check if the language code matches the current spell check language.
-      if (languageCode == this.spellCheckDictionary_) {
-        // If it matches, the button just says that the spell check language is
-        // currently in use.
-        spellCheckLanguageButton.textContent =
-            localStrings.getString('is_used_for_spell_checking');
-        // Make it look like a text label.
-        spellCheckLanguageButton.className = 'text-button';
-        // Remove the event listner.
-        spellCheckLanguageButton.onclick = undefined;
-      } else if (languageCode in templateData.spellCheckLanguageCodeSet) {
-        // If the language is supported as spell check language, users can
-        // click on the button to change the spell check language.
-        spellCheckLanguageButton.textContent =
-            localStrings.getString('use_this_for_spell_checking');
-        spellCheckLanguageButton.className = '';
-        spellCheckLanguageButton.languageCode = languageCode;
-        // Add an event listner to the click event.
-        spellCheckLanguageButton.addEventListener('click',
-            this.handleSpellCheckLanguageButtonClick_.bind(this));
-      } else {
-        // If the language is not supported as spell check language, the
-        // button just says that this language cannot be used for spell
-        // checking.
-        spellCheckLanguageButton.textContent =
-            localStrings.getString('cannot_be_used_for_spell_checking');
-        spellCheckLanguageButton.className = 'text-button';
-        spellCheckLanguageButton.onclick = undefined;
-      }
-      spellCheckLanguageButton.style.display = 'block';
-      $('language-options-ui-notification-bar').style.display = 'none';
-    },
-
-    /**
-     * Updates the input method list.
-     * @param {string} languageCode Language code (ex. "fr").
-     * @private
-     */
-    updateInputMethodList_: function(languageCode) {
-      // Give one of the checkboxes or buttons focus, if it's specified in the
-      // URL hash (ex. focus=mozc). Used for automated testing.
-      var focusInputMethodId = -1;
-      var match = document.location.hash.match(/\bfocus=([\w:-]+)\b/);
-      if (match) {
-        focusInputMethodId = match[1];
-      }
-      // Change the visibility of the input method list. Input methods that
-      // matches |languageCode| will become visible.
-      var inputMethodList = $('language-options-input-method-list');
-      var labels = inputMethodList.querySelectorAll('label');
-      for (var i = 0; i < labels.length; i++) {
-        var label = labels[i];
-        if (languageCode in label.languageCodeSet) {
-          label.style.display = 'block';
-          var input = label.childNodes[0];
-          // Give it focus if the ID matches.
-          if (input.inputMethodId == focusInputMethodId) {
-            input.focus();
-          }
-        } else {
-          label.style.display = 'none';
-        }
-      }
-      if (focusInputMethodId == 'remove') {
-        $('language-options-remove-button').focus();
-      } else if (focusInputMethodId == 'add') {
-        $('language-options-add-button').focus();
-      }
-    },
-
-    /**
-     * Updates the language list in the add language overlay.
-     * @param {string} languageCode Language code (ex. "fr").
-     * @private
-     */
-    updateLanguageListInAddLanguageOverlay_: function(languageCode) {
-      // Change the visibility of the language list in the add language
-      // overlay. Languages that are already active will become invisible,
-      // so that users don't add the same language twice.
-      var languageOptionsList = $('language-options-list');
-      var languageCodes = languageOptionsList.getLanguageCodes();
-      var languageCodeSet = {};
-      for (var i = 0; i < languageCodes.length; i++) {
-        languageCodeSet[languageCodes[i]] = true;
-      }
-      var addLanguageList = $('add-language-overlay-language-list');
-      var lis = addLanguageList.querySelectorAll('li');
-      for (var i = 0; i < lis.length; i++) {
-        // The first child button knows the language code.
-        var button = lis[i].childNodes[0];
-        if (button.languageCode in languageCodeSet) {
-          lis[i].style.display = 'none';
-        } else {
-          lis[i].style.display = 'block';
-        }
-      }
-    },
-
-    /**
-     * Handles preloadEnginesPref change.
-     * @param {Event} e Change event.
-     * @private
-     */
-    handlePreloadEnginesPrefChange_: function(e) {
-      var value = e.value.value;
-      this.preloadEngines_ = this.filterBadPreloadEngines_(value.split(','));
-      this.updateCheckboxesFromPreloadEngines_();
-    },
-
-    /**
-     * Handles input method checkbox's click event.
-     * @param {Event} e Click event.
-     * @private
-     */
-    handleCheckboxClick_ : function(e) {
-      var checkbox = e.target;
-      if (this.preloadEngines_.length == 1 && !checkbox.checked) {
-        // Don't allow disabling the last input method.
-        this.showNotification_(
-            localStrings.getString('please_add_another_input_method'),
-            localStrings.getString('ok_button'));
-        checkbox.checked = true;
-        return;
-      }
-      if (checkbox.checked) {
-        chrome.send('inputMethodEnable', [checkbox.inputMethodId]);
-      } else {
-        chrome.send('inputMethodDisable', [checkbox.inputMethodId]);
-      }
-      this.updatePreloadEnginesFromCheckboxes_();
-      this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
-      this.savePreloadEnginesPref_();
-    },
-
-    /**
-     * Handles add language list's click event.
-     * @param {Event} e Click event.
-     */
-    handleAddLanguageListClick_ : function(e) {
-      var languageOptionsList = $('language-options-list');
-      var languageCode = e.target.languageCode;
-      // languageCode can be undefined, if click was made on some random
-      // place in the overlay, rather than a button. Ignore it.
-      if (!languageCode) {
-        return;
-      }
-      languageOptionsList.addLanguage(languageCode);
-      var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
-      // Enable the first input method for the language added.
-      if (inputMethodIds && inputMethodIds[0] &&
-          // Don't add the input method it's already present. This can
-          // happen if the same input method is shared among multiple
-          // languages (ex. English US keyboard is used for English US and
-          // Filipino).
-          this.preloadEngines_.indexOf(inputMethodIds[0]) == -1) {
-        this.preloadEngines_.push(inputMethodIds[0]);
-        this.updateCheckboxesFromPreloadEngines_();
-        this.savePreloadEnginesPref_();
-      }
-      OptionsPage.clearOverlays();
-    },
-
-    /**
-     * Handles remove button's click event.
-     * @param {Event} e Click event.
-     */
-    handleRemoveButtonClick_: function(e) {
-      var languageOptionsList = $('language-options-list');
-      var languageCode = languageOptionsList.getSelectedLanguageCode();
-      // Don't allow removing the language if it's as UI language.
-      if (languageCode == templateData.currentUiLanguageCode) {
-        this.showNotification_(
-            localStrings.getString('this_language_is_currently_in_use'),
-            localStrings.getString('ok_button'));
-        return;
-      }
-      // Disable input methods associated with |languageCode|.
-      // Don't allow removing the language if cerntain conditions are met.
-      // See removePreloadEnginesByLanguageCode_() for details.
-      if (!this.removePreloadEnginesByLanguageCode_(languageCode)) {
-        this.showNotification_(
-            localStrings.getString('please_add_another_language'),
-            localStrings.getString('ok_button'));
-        return;
-      }
-      languageOptionsList.removeSelectedLanguage();
-    },
-
-    /**
-     * Handles spellCheckDictionaryPref change.
-     * @param {Event} e Change event.
-     * @private
-     */
-    handleSpellCheckDictionaryPrefChange_: function(e) {
-      var languageCode = e.value.value
-      this.spellCheckDictionary_ = languageCode;
-      var languageOptionsList = $('language-options-list');
-      var selectedLanguageCode = languageOptionsList.getSelectedLanguageCode();
-      this.updateSpellCheckLanguageButton_(selectedLanguageCode);
-    },
-
-    /**
-     * Handles spellCheckLanguageButton click.
-     * @param {Event} e Click event.
-     * @private
-     */
-    handleSpellCheckLanguageButtonClick_: function(e) {
-      var languageCode = e.target.languageCode;
-      // Save the preference.
-      Preferences.setStringPref(this.spellCheckDictionaryPref,
-                                languageCode);
-      chrome.send('spellCheckLanguageChange', [languageCode]);
-    },
-
-    /**
-     * Removes preload engines associated with the given language code.
-     * However, this function does not remove engines (input methods) that
-     * are used for other active languages. For instance, if "xkb:us::eng"
-     * is used for English and Filipino, and the two languages are active,
-     * this function does not remove "xkb:us::eng" when either of these
-     * languages is removed. Instead, it'll remove "xkb:us::eng" when the
-     * both languages are gone.
-     *
-     * @param {string} languageCode Language code (ex. "fr").
-     * @return {boolean} Returns true on success.
-     * @private
-     */
-    removePreloadEnginesByLanguageCode_: function(languageCode) {
-      // First create the set of engines to be removed from input methods
-      // associated with the language code.
-      var enginesToBeRemovedSet = {};
-      var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
-      for (var i = 0; i < inputMethodIds.length; i++) {
-        enginesToBeRemovedSet[inputMethodIds[i]] = true;
-      }
-
-      // Then eliminate engines that are also used for other active languages.
-      var languageCodes = $('language-options-list').getLanguageCodes();
-      for (var i = 0; i < languageCodes.length; i++) {
-        // Skip the target language code.
-        if (languageCodes[i] == languageCode) {
-          continue;
-        }
-        // Check if input methods used in this language are included in
-        // enginesToBeRemovedSet. If so, eliminate these from the set, so
-        // we don't remove this time.
-        var inputMethodIdsForAnotherLanguage =
-            this.languageCodeToInputMethodIdsMap_[languageCodes[i]];
-        for (var j = 0; j < inputMethodIdsForAnotherLanguage.length; j++) {
-          var inputMethodId = inputMethodIdsForAnotherLanguage[j];
-          if (inputMethodId in enginesToBeRemovedSet) {
-            delete enginesToBeRemovedSet[inputMethodId];
-          }
-        }
-      }
-
-      // Update the preload engine list with the to-be-removed set.
-      var newPreloadEngines = [];
-      for (var i = 0; i < this.preloadEngines_.length; i++) {
-        if (!(this.preloadEngines_[i] in enginesToBeRemovedSet)) {
-          newPreloadEngines.push(this.preloadEngines_[i]);
-        }
-      }
-      // Don't allow this operation if it causes the number of preload
-      // engines to be zero.
-      if (newPreloadEngines.length == 0) {
-        return false;
-      }
-      this.preloadEngines_ = newPreloadEngines;
-      this.savePreloadEnginesPref_();
-      return true;
-    },
-
-    /**
-     * Saves the preload engines preference.
-     * @private
-     */
-    savePreloadEnginesPref_: function() {
-      Preferences.setStringPref(this.preloadEnginesPref,
-                                this.preloadEngines_.join(','));
-    },
-
-    /**
-     * Updates the checkboxes in the input method list from the preload
-     * engines preference.
-     * @private
-     */
-    updateCheckboxesFromPreloadEngines_: function() {
-      // Convert the list into a dictonary for simpler lookup.
-      var dictionary = {};
-      for (var i = 0; i < this.preloadEngines_.length; i++) {
-        dictionary[this.preloadEngines_[i]] = true;
-      }
-
-      var inputMethodList = $('language-options-input-method-list');
-      var checkboxes = inputMethodList.querySelectorAll('input');
-      for (var i = 0; i < checkboxes.length; i++) {
-        checkboxes[i].checked = (checkboxes[i].inputMethodId in dictionary);
-      }
-    },
-
-    /**
-     * Updates the preload engines preference from the checkboxes in the
-     * input method list.
-     * @private
-     */
-    updatePreloadEnginesFromCheckboxes_: function() {
-      this.preloadEngines_ = [];
-      var inputMethodList = $('language-options-input-method-list');
-      var checkboxes = inputMethodList.querySelectorAll('input');
-      for (var i = 0; i < checkboxes.length; i++) {
-        if (checkboxes[i].checked) {
-          this.preloadEngines_.push(checkboxes[i].inputMethodId);
-        }
-      }
-    },
-
-    /**
-     * Filters bad preload engines in case bad preload engines are
-     * stored in the preference. Removes duplicates as well.
-     * @param {Array} preloadEngines List of preload engines.
-     * @private
-     */
-    filterBadPreloadEngines_: function(preloadEngines) {
-      // Convert the list into a dictonary for simpler lookup.
-      var dictionary = {};
-      for (var i = 0; i < templateData.inputMethodList.length; i++) {
-        dictionary[templateData.inputMethodList[i].id] = true;
-      }
-
-      var filteredPreloadEngines = [];
-      var seen = {};
-      for (var i = 0; i < preloadEngines.length; i++) {
-        // Check if the preload engine is present in the
-        // dictionary, and not duplicate. Otherwise, skip it.
-        if (preloadEngines[i] in dictionary && !(preloadEngines[i] in seen)) {
-          filteredPreloadEngines.push(preloadEngines[i]);
-          seen[preloadEngines[i]] = true;
-        }
-      }
-      return filteredPreloadEngines;
-    },
-
-    // TODO(kochi): This is an adapted copy from new_new_tab.js.
-    // If this will go as final UI, refactor this to share the component with
-    // new new tab page.
-    /**
-     * Shows notification
-     * @private
-     */
-    notificationTimeout_: null,
-    showNotification_ : function(text, actionText, opt_delay) {
-      var notificationElement = $('notification');
-      var actionLink = notificationElement.querySelector('.link-color');
-      var delay = opt_delay || 10000;
-
-      function show() {
-        window.clearTimeout(this.notificationTimeout_);
-        notificationElement.classList.add('show');
-        document.body.classList.add('notification-shown');
-      }
-
-      function hide() {
-        window.clearTimeout(this.notificationTimeout_);
-        notificationElement.classList.remove('show');
-        document.body.classList.remove('notification-shown');
-        // Prevent tabbing to the hidden link.
-        actionLink.tabIndex = -1;
-        // Setting tabIndex to -1 only prevents future tabbing to it. If,
-        // however, the user switches window or a tab and then moves back to
-        // this tab the element may gain focus. We therefore make sure that we
-        // blur the element so that the element focus is not restored when
-        // coming back to this window.
-        actionLink.blur();
-      }
-
-      function delayedHide() {
-        this.notificationTimeout_ = window.setTimeout(hide, delay);
-      }
-
-      notificationElement.firstElementChild.textContent = text;
-      actionLink.textContent = actionText;
-
-      actionLink.onclick = hide;
-      actionLink.onkeydown = function(e) {
-        if (e.keyIdentifier == 'Enter') {
-          hide();
-        }
-      };
-      notificationElement.onmouseover = show;
-      notificationElement.onmouseout = delayedHide;
-      actionLink.onfocus = show;
-      actionLink.onblur = delayedHide;
-      // Enable tabbing to the link now that it is shown.
-      actionLink.tabIndex = 0;
-
-      show();
-      delayedHide();
-    }
-  };
-
-  /**
-   * Chrome callback for when the UI language preference is saved.
-   */
-  LanguageOptions.uiLanguageSaved = function() {
-    $('language-options-ui-language-button').style.display = 'none';
-    $('language-options-ui-notification-bar').style.display = 'block';
-  };
-
-  // Export
-  return {
-    LanguageOptions: LanguageOptions
-  };
-
-});
diff --git a/chrome/browser/resources/options/chromeos_language_pinyin_options.html b/chrome/browser/resources/options/chromeos_language_pinyin_options.html
index 8b0e68c..d99f82b 100644
--- a/chrome/browser/resources/options/chromeos_language_pinyin_options.html
+++ b/chrome/browser/resources/options/chromeos_language_pinyin_options.html
@@ -118,6 +118,7 @@
         <td class="option-value">
           <select id="pinyin-double-pinyin-schema" class="control"
               pref="settings.language.pinyin_double_pinyin_schema"
+              dataType="string"
               i18n-options="PinyinDoublePinyinSchemaValue"></select>
         </td>
       </tr>
diff --git a/chrome/browser/resources/options/chromeos_proxy_rules_list.js b/chrome/browser/resources/options/chromeos_proxy_rules_list.js
index 063b5e2..81f94d4 100644
--- a/chrome/browser/resources/options/chromeos_proxy_rules_list.js
+++ b/chrome/browser/resources/options/chromeos_proxy_rules_list.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -92,7 +92,7 @@
      * Updates backend.
      */
     updateBackend_: function() {
-      Preferences.setObjectPref(this.pref, this.dataModel.slice());
+      Preferences.setListPref(this.pref, this.dataModel.slice());
     }
   };
 
@@ -124,7 +124,6 @@
     /** @inheritDoc */
     decorate: function() {
       ListItem.prototype.decorate.call(this);
-      console.log('in exceptions decorate');
       this.className = 'exception-list-item';
 
       var labelException = this.ownerDocument.createElement('span');
diff --git a/chrome/browser/resources/options/chromeos_system_options.html b/chrome/browser/resources/options/chromeos_system_options.html
index e43b40a..93cf00b 100644
--- a/chrome/browser/resources/options/chromeos_system_options.html
+++ b/chrome/browser/resources/options/chromeos_system_options.html
@@ -8,6 +8,7 @@
         <td class="option-value">
         <select id="timezone-select" class="control"
              i18n-options="timezoneList"
+             dataType="string"
              pref="cros.system.timezone"></select>
         </td>
       </tr>
@@ -24,6 +25,14 @@
         </td>
       </tr>
       <tr>
+        <td></td>
+        <td>
+          <span i18n-content="sensitivity_less"></span>
+          <span i18n-content="sensitivity_more"
+              class="touchpad-sensitivity-more"></span>
+        </td>
+      </tr>
+      <tr>
         <td class="option-name" colspan="2">
           <label class="checkbox">
             <input id="tap-to-click-check"
@@ -54,8 +63,7 @@
       <tr>
         <td class="option-name">
           <label class="checkbox">
-            <input id="accesibility-check"
-                pref="settings.accessibility" type="checkbox">
+            <input id="accesibility-check" type="checkbox">
             <span i18n-content="accessibility"></span>
           </label>
         </td>
diff --git a/chrome/browser/resources/options/chromeos_system_options.js b/chrome/browser/resources/options/chromeos_system_options.js
index 52ffd70..84cd3b3 100644
--- a/chrome/browser/resources/options/chromeos_system_options.js
+++ b/chrome/browser/resources/options/chromeos_system_options.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,8 @@
    */
 
   function SystemOptions() {
-    OptionsPage.call(this, 'system', templateData.systemPage, 'systemPage');
+    OptionsPage.call(this, 'system', templateData.systemPageTabTitle,
+                     'systemPage');
   }
 
   cr.addSingletonGetter(SystemOptions);
@@ -38,14 +39,29 @@
       }
 
       $('language-button').onclick = function(event) {
-        OptionsPage.showPageByName('language');
+        OptionsPage.navigateToPage('language');
       };
       $('modifier-keys-button').onclick = function(event) {
-        OptionsPage.showOverlay('languageCustomizeModifierKeysOverlay');
+        OptionsPage.navigateToPage('languageCustomizeModifierKeysOverlay');
+      };
+      $('accesibility-check').onchange = function(event) {
+        chrome.send('accessibilityChange',
+                    [String($('accesibility-check').checked)]);
       };
     }
   };
 
+  //
+  // Chrome callbacks
+  //
+
+  /**
+   * Set the initial state of the accessibility checkbox.
+   */
+  SystemOptions.SetAccessibilityCheckboxState = function(checked) {
+    $('accesibility-check').checked = checked;
+  };
+
   // Export
   return {
     SystemOptions: SystemOptions
diff --git a/chrome/browser/resources/options/chromeos_system_options_page.css b/chrome/browser/resources/options/chromeos_system_options_page.css
new file mode 100644
index 0000000..988c987
--- /dev/null
+++ b/chrome/browser/resources/options/chromeos_system_options_page.css
@@ -0,0 +1,3 @@
+.touchpad-sensitivity-more {
+  float: right;
+}
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.css b/chrome/browser/resources/options/clear_browser_data_overlay.css
index 4a274f2..b2cf716 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.css
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.css
@@ -1,12 +1,24 @@
+/*
+Copyright (c) 2011 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+*/
+
 #clearBrowserDataOverlay {
-  width: 300px;
+  min-width: 500px;
+}
+
+#clearBrowserDataOverlay > .content-area label {
+  margin: 5px 0;
+}
+
+#clear-data-checkboxes {
+  -webkit-padding-start: 8px;
+  margin: 5px 0;
 }
 
 #cbdThrobber {
-  background-image: url("../../../../app/resources/throbber.png");
-  width: 16px;
-  height: 16px;
-  margin: -3px 10px;
-  display: inline-block;
+  margin: 4px 10px;
+  vertical-align: middle;
   visibility: hidden;
 }
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.html b/chrome/browser/resources/options/clear_browser_data_overlay.html
index 66d3739..e82a2e8 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.html
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.html
@@ -1,62 +1,58 @@
-<div class="page hidden" id="clearBrowserDataOverlay">
-  <h1 i18n-content="clearBrowsingDataTitle"></h1>
-  <h3 i18n-content="clearBrowsingDataLabel"></h3>
-  <div id="checkboxListData">
-    <div>
-      <input id="deleteBrowsingHistoryCheckbox"
-          pref="browser.clear_data.browsing_history" type="checkbox">
-      <label for="deleteBrowsingHistoryCheckbox"
-          i18n-content="deleteBrowsingHistoryCheckbox"></label>
+<div id="clearBrowserDataOverlay" class="page hidden">
+  <h1 i18n-content="clearBrowserDataOverlay"></h1>
+  <div id="cbdContentArea" class="content-area">
+    <span i18n-content="clearBrowserDataLabel"></span>
+    <select id="clearBrowserDataTimePeriod"
+        i18n-options="clearBrowserDataTimeList"
+        pref="browser.clear_data.time_period"
+        dataType="number">
+    </select>
+    <div id="clear-data-checkboxes">
+      <label class="checkbox">
+        <input id="deleteBrowsingHistoryCheckbox"
+            pref="browser.clear_data.browsing_history" type="checkbox">
+        <span i18n-content="deleteBrowsingHistoryCheckbox"></span>
+      </label>
+      <label class="checkbox">
+        <input id="deleteDownloadHistoryCheckbox"
+            pref="browser.clear_data.download_history" type="checkbox">
+        <span i18n-content="deleteDownloadHistoryCheckbox"></span>
+      </label>
+      <label class="checkbox">
+        <input id="deleteCacheCheckbox"
+            pref="browser.clear_data.cache" type="checkbox">
+        <span i18n-content="deleteCacheCheckbox"></span>
+      </label>
+      <label class="checkbox">
+        <input id="deleteCookiesCheckbox"
+            pref="browser.clear_data.cookies" type="checkbox">
+        <span id="deleteCookiesLabel"></span>
+      </label>
+      <label class="checkbox">
+        <input id="deletePasswordsCheckbox"
+            pref="browser.clear_data.passwords" type="checkbox">
+        <span i18n-content="deletePasswordsCheckbox"></span>
+      </label>
+      <label class="checkbox">
+        <input id="deleteFormDataCheckbox"
+            pref="browser.clear_data.form_data" type="checkbox">
+        <span i18n-content="deleteFormDataCheckbox"></span>
+      </label>
     </div>
-    <div>
-      <input id="deleteDownloadHistoryCheckbox"
-          pref="browser.clear_data.download_history" type="checkbox">
-      <label for="deleteDownloadHistoryCheckbox"
-          i18n-content="deleteDownloadHistoryCheckbox"></label>
-    </div>
-    <div>
-      <input id="deleteCacheCheckbox"
-          pref="browser.clear_data.cache" type="checkbox">
-      <label for="deleteCacheCheckbox"
-          i18n-content="deleteCacheCheckbox"></label>
-    </div>
-    <div>
-      <input id="deleteCookiesCheckbox"
-          pref="browser.clear_data.cookies" type="checkbox">
-      <label for="deleteCookiesCheckbox"
-          i18n-content="deleteCookiesCheckbox"></label>
-    </div>
-    <div>
-      <input id="deletePasswordsCheckbox"
-          pref="browser.clear_data.passwords" type="checkbox">
-      <label for="deletePasswordsCheckbox"
-          i18n-content="deletePasswordsCheckbox"></label>
-    </div>
-    <div>
-      <input id="deleteFormDataCheckbox"
-          pref="browser.clear_data.form_data" type="checkbox">
-      <label for="deleteFormDataCheckbox"
-          i18n-content="deleteFormDataCheckbox"></label>
-    </div>
-  </div>
-  <div>
-    <label for="" i18n-content="clearBrowsingDataTimeLabel"></label>
-    <select id="clearBrowsingDataTimePeriod"
-        i18n-options="clearBrowsingDataTimeList"
-        pref="browser.clear_data.time_period"></select>
   </div>
   <div class="action-area">
-    <span id="cbdThrobber"></span>
-    <div class="button-strip">
-      <button id="clearBrowsingDataDismiss" i18n-content="cancel"
-              onclick="ClearBrowserDataOverlay.dismiss();">
-      </button>
-      <button id="clearBrowsingDataCommit"
-              i18n-content="clearBrowsingDataCommit">
-      </button>
+    <div>
+      <a target="_blank" i18n-content="flash_storage_settings"
+          i18n-values="href:flash_storage_url"></a>
+    </div>
+    <div class="action-area-right">
+      <div id="cbdThrobber" class="throbber"></div>
+      <div class="button-strip">
+        <button id="clearBrowserDataDismiss" i18n-content="cancel"></button>
+        <button id="clearBrowserDataCommit"
+            i18n-content="clearBrowserDataCommit">
+        </button>
+      </div>
     </div>
   </div>
-  <hr>
-  <a target="_blank" i18n-content="flash_storage_settings"
-      i18n-values="href:flash_storage_url"></a>
 </div>
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.js b/chrome/browser/resources/options/clear_browser_data_overlay.js
index 6b1cf05..bc7eafc 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.js
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.js
@@ -1,24 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 cr.define('options', function() {
-
   var OptionsPage = options.OptionsPage;
 
   /**
-   * ClearBrowserData class
+   * ClearBrowserDataOverlay class
    * Encapsulated handling of the 'Clear Browser Data' overlay page.
    * @class
    */
   function ClearBrowserDataOverlay() {
-    OptionsPage.call(this, 'clearBrowserDataOverlay',
-                     templateData.clearBrowserDataTitle,
+    OptionsPage.call(this, 'clearBrowserData',
+                     templateData.clearBrowserDataOverlayTabTitle,
                      'clearBrowserDataOverlay');
   }
 
-  ClearBrowserDataOverlay.throbIntervalId = 0;
-
   cr.addSingletonGetter(ClearBrowserDataOverlay);
 
   ClearBrowserDataOverlay.prototype = {
@@ -44,14 +41,16 @@
       });
 
       var checkboxes = document.querySelectorAll(
-          '#checkboxListData input[type=checkbox]');
+          '#cbdContentArea input[type=checkbox]');
       for (var i = 0; i < checkboxes.length; i++) {
         checkboxes[i].onclick = f;
       }
       this.updateCommitButtonState_();
 
-      // Setup click handler for the clear(Ok) button.
-      $('clearBrowsingDataCommit').onclick = function(event) {
+      $('clearBrowserDataDismiss').onclick = function(event) {
+        ClearBrowserDataOverlay.dismiss();
+      };
+      $('clearBrowserDataCommit').onclick = function(event) {
         chrome.send('performClearBrowserData');
       };
     },
@@ -59,7 +58,7 @@
     // Set the enabled state of the commit button.
     updateCommitButtonState_: function() {
       var checkboxes = document.querySelectorAll(
-          '#checkboxListData input[type=checkbox]');
+          '#cbdContentArea input[type=checkbox]');
       var isChecked = false;
       for (var i = 0; i < checkboxes.length; i++) {
         if (checkboxes[i].checked) {
@@ -67,7 +66,7 @@
           break;
         }
       }
-      $('clearBrowsingDataCommit').disabled = !isChecked;
+      $('clearBrowserDataCommit').disabled = !isChecked;
     },
   };
 
@@ -81,39 +80,35 @@
     $('deleteCookiesCheckbox').disabled = state;
     $('deletePasswordsCheckbox').disabled = state;
     $('deleteFormDataCheckbox').disabled = state;
-    $('clearBrowsingDataTimePeriod').disabled = state;
-    $('clearBrowsingDataDismiss').disabled = state;
+    $('clearBrowserDataTimePeriod').disabled = state;
     $('cbdThrobber').style.visibility = state ? 'visible' : 'hidden';
 
     if (state)
-      $('clearBrowsingDataCommit').disabled = true;
+      $('clearBrowserDataCommit').disabled = true;
     else
       ClearBrowserDataOverlay.getInstance().updateCommitButtonState_();
+  };
 
-    function advanceThrobber() {
-      var throbber = $('cbdThrobber');
-      // TODO(csilv): make this smoother using time-based animation?
-      throbber.style.backgroundPositionX =
-          ((parseInt(getComputedStyle(throbber).backgroundPositionX, 10) - 16) %
-          576) + 'px';
-    }
-    if (state) {
-      ClearBrowserDataOverlay.throbIntervalId =
-          setInterval(advanceThrobber, 30);
-    } else {
-      clearInterval(ClearBrowserDataOverlay.throbIntervalId);
-    }
-  }
+  ClearBrowserDataOverlay.setClearLocalDataLabel = function(label) {
+    $('deleteCookiesLabel').innerText = label;
+  };
+
+  ClearBrowserDataOverlay.doneClearing = function() {
+    // The delay gives the user some feedback that the clearing
+    // actually worked. Otherwise the dialog just vanishes instantly in most
+    // cases.
+    window.setTimeout(function() {
+      ClearBrowserDataOverlay.dismiss();
+    }, 200);
+  };
 
   ClearBrowserDataOverlay.dismiss = function() {
-    OptionsPage.clearOverlays();
+    OptionsPage.closeOverlay();
     this.setClearingState(false);
-  }
+  };
 
   // Export
   return {
     ClearBrowserDataOverlay: ClearBrowserDataOverlay
   };
-
 });
-
diff --git a/chrome/browser/resources/options/content_settings.css b/chrome/browser/resources/options/content_settings.css
index f788261..b13e0b4 100644
--- a/chrome/browser/resources/options/content_settings.css
+++ b/chrome/browser/resources/options/content_settings.css
@@ -8,10 +8,6 @@
   -webkit-box-flex: 1;
   -webkit-margin-end: 10px;
   -webkit-margin-start: 14px;
-  display: -webkit-box;
-  margin-right: 4px;
-  overflow: hidden;
-  white-space: nowrap;
 }
 
 .exception-setting {
@@ -57,6 +53,7 @@
   margin-top: 4px;
 }
 
-#content-settings-exceptions-area input:invalid {
-  background-color: pink;
+#plugins-tab {
+  display: block;
+  margin: 7px 0px;
 }
diff --git a/chrome/browser/resources/options/content_settings.html b/chrome/browser/resources/options/content_settings.html
index f150024..dea3b86 100644
--- a/chrome/browser/resources/options/content_settings.html
+++ b/chrome/browser/resources/options/content_settings.html
@@ -21,7 +21,7 @@
       <label class="checkbox">
         <input id="clear-cookies-on-exit"
             pref="profile.clear_site_data_on_exit" type="checkbox">
-        <span i18n-content="cookies_clear_on_exit"></span>
+        <span id="clear-cookies-on-exit-label"></span>
       </label>
 
       <button class="exceptions-list-button" contentType="cookies"
@@ -86,6 +86,9 @@
 
       <button class="exceptions-list-button" contentType="plugins"
           i18n-content="manage_exceptions"></button>
+      <a i18n-content="disable_individual_plugins" id="plugins-tab"
+          href="about:plugins">
+      </a>
     </div>
   </section>
 
diff --git a/chrome/browser/resources/options/content_settings.js b/chrome/browser/resources/options/content_settings.js
index a9a80bb..59b0119 100644
--- a/chrome/browser/resources/options/content_settings.js
+++ b/chrome/browser/resources/options/content_settings.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,7 +15,7 @@
    */
   function ContentSettings() {
     this.activeNavTab = null;
-    OptionsPage.call(this, 'content', templateData.contentSettingsPage,
+    OptionsPage.call(this, 'content', templateData.contentSettingsPageTabTitle,
                      'content-settings-page');
   }
 
@@ -33,9 +33,15 @@
           this.pageDiv.querySelectorAll('.exceptions-list-button');
       for (var i = 0; i < exceptionsButtons.length; i++) {
         exceptionsButtons[i].onclick = function(event) {
-          ContentSettingsExceptionsArea.getInstance().showList(
+          var page = ContentSettingsExceptionsArea.getInstance();
+          page.showList(
               event.target.getAttribute('contentType'));
-          OptionsPage.showPageByName('contentExceptions');
+          OptionsPage.navigateToPage('contentExceptions');
+          // Add on the proper hash for the content type, and store that in the
+          // history so back/forward and tab restore works.
+          var hash = event.target.getAttribute('contentType');
+          window.history.replaceState({pageName: page.name}, page.title,
+                                      '/' + page.name + "#" + hash);
         };
       }
 
@@ -47,27 +53,12 @@
 
       $('show-cookies-button').onclick = function(event) {
         chrome.send('coreOptionsUserMetricsAction', ['Options_ShowCookies']);
-        OptionsPage.showPageByName('cookiesView');
-      };
-
-      $('plugins-tab').onclick = function(event) {
-        chrome.send('openPluginsTab');
-        return false;
+        OptionsPage.navigateToPage('cookiesView');
       };
 
       if (!templateData.enable_click_to_play)
         $('click_to_play').style.display = 'none';
     },
-
-    /**
-     * Handles a hash value in the URL (such as bar in
-     * chrome://options/foo#bar).
-     * @param {string} hash The hash value.
-     */
-    handleHash: function(hash) {
-      ContentSettingsExceptionsArea.getInstance().showList(hash);
-      OptionsPage.showPageByName('contentExceptions');
-    },
   };
 
   /**
@@ -83,8 +74,10 @@
                                              group + ']');
       for (var i = 0, len = radios.length; i < len; i++) {
         radios[i].disabled = dict[group]['managed'];
+        radios[i].managed = dict[group]['managed'];
       }
     }
+    OptionsPage.updateManagedBannerVisibility();
   };
 
   /**
@@ -98,11 +91,7 @@
         document.querySelector('div[contentType=' + type + ']' +
                                ' list[mode=normal]');
 
-    exceptionsList.reset();
-    for (var i = 0; i < list.length; i++) {
-      exceptionsList.addException(list[i]);
-    }
-    exceptionsList.redraw();
+    exceptionsList.setExceptions(list);
   };
 
   ContentSettings.setOTRExceptions = function(type, list) {
@@ -111,12 +100,7 @@
                                ' list[mode=otr]');
 
     exceptionsList.parentNode.classList.remove('hidden');
-
-    exceptionsList.reset();
-    for (var i = 0; i < list.length; i++) {
-      exceptionsList.addException(list[i]);
-    }
-    exceptionsList.redraw();
+    exceptionsList.setExceptions(list);
   };
 
   /**
@@ -144,6 +128,10 @@
     exceptionsList.patternValidityCheckComplete(pattern, valid);
   };
 
+  ContentSettings.setClearLocalDataOnShutdownLabel = function(label) {
+    $('clear-cookies-on-exit-label').innerText = label;
+  };
+
   // Export
   return {
     ContentSettings: ContentSettings
diff --git a/chrome/browser/resources/options/content_settings_exceptions_area.html b/chrome/browser/resources/options/content_settings_exceptions_area.html
index 59db53f..1c1bf0e 100644
--- a/chrome/browser/resources/options/content_settings_exceptions_area.html
+++ b/chrome/browser/resources/options/content_settings_exceptions_area.html
@@ -42,7 +42,6 @@
             i18n-content="otr_exceptions_explanation"></span>
       <list mode="otr"></list>
     </div>
-    <a i18n-content="disable_individual_plugins" id="plugins-tab" href="#"></a>
   </div>
 
   <div contentType="popups">
diff --git a/chrome/browser/resources/options/content_settings_exceptions_area.js b/chrome/browser/resources/options/content_settings_exceptions_area.js
index da67d01..a45228f 100644
--- a/chrome/browser/resources/options/content_settings_exceptions_area.js
+++ b/chrome/browser/resources/options/content_settings_exceptions_area.js
@@ -1,10 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 cr.define('options.contentSettings', function() {
-  const DeletableItemList = options.DeletableItemList;
-  const DeletableItem = options.DeletableItem;
+  const InlineEditableItemList = options.InlineEditableItemList;
+  const InlineEditableItem = options.InlineEditableItem;
   const ArrayDataModel = cr.ui.ArrayDataModel;
 
   /**
@@ -16,7 +16,7 @@
    * @param {Object} exception A dictionary that contains the data of the
    *     exception.
    * @constructor
-   * @extends {options.DeletableItem}
+   * @extends {options.InlineEditableItem}
    */
   function ExceptionsListItem(contentType, mode, enableAskOption, exception) {
     var el = cr.doc.createElement('div');
@@ -31,61 +31,65 @@
   }
 
   ExceptionsListItem.prototype = {
-    __proto__: DeletableItem.prototype,
+    __proto__: InlineEditableItem.prototype,
 
     /**
      * Called when an element is decorated as a list item.
      */
     decorate: function() {
-      DeletableItem.prototype.decorate.call(this);
+      InlineEditableItem.prototype.decorate.call(this);
 
-      // Labels for display mode. |pattern| will be null for the 'add new
+      var patternCell = this.createEditableTextCell(this.pattern,
+                                                    !this.pattern);
+      patternCell.className = 'exception-pattern';
+      this.contentElement.appendChild(patternCell);
+      if (this.pattern)
+        this.patternLabel = patternCell.querySelector('.static-text');
+      var input = patternCell.querySelector('input');
+
+      // TODO(stuartmorgan): Create an createEditableSelectCell abstracting
+      // this code.
+      // Setting label for display mode. |pattern| will be null for the 'add new
       // exception' row.
       if (this.pattern) {
-        var patternLabel = cr.doc.createElement('span');
-        patternLabel.textContent = this.pattern;
-        patternLabel.className = 'exception-pattern';
-        this.contentElement.appendChild(patternLabel);
-        this.patternLabel = patternLabel;
-
         var settingLabel = cr.doc.createElement('span');
         settingLabel.textContent = this.settingForDisplay();
         settingLabel.className = 'exception-setting';
+        settingLabel.setAttribute('displaymode', 'static');
         this.contentElement.appendChild(settingLabel);
         this.settingLabel = settingLabel;
       }
 
-      // Elements for edit mode.
-      var input = cr.doc.createElement('input');
-      input.type = 'text';
-      this.contentElement.appendChild(input);
-      input.className = 'exception-pattern hidden';
-
+      // Setting select element for edit mode.
       var select = cr.doc.createElement('select');
       var optionAllow = cr.doc.createElement('option');
       optionAllow.textContent = templateData.allowException;
+      optionAllow.value = 'allow';
       select.appendChild(optionAllow);
 
       if (this.enableAskOption) {
         var optionAsk = cr.doc.createElement('option');
         optionAsk.textContent = templateData.askException;
+        optionAsk.value = 'ask';
         select.appendChild(optionAsk);
-        this.optionAsk = optionAsk;
       }
 
       if (this.contentType == 'cookies') {
         var optionSession = cr.doc.createElement('option');
         optionSession.textContent = templateData.sessionException;
+        optionSession.value = 'session';
         select.appendChild(optionSession);
-        this.optionSession = optionSession;
       }
 
       var optionBlock = cr.doc.createElement('option');
       optionBlock.textContent = templateData.blockException;
+      optionBlock.value = 'block';
       select.appendChild(optionBlock);
 
       this.contentElement.appendChild(select);
-      select.className = 'exception-setting hidden';
+      select.className = 'exception-setting';
+      if (this.pattern)
+        select.setAttribute('displaymode', 'edit');
 
       // Used to track whether the URL pattern in the input is valid.
       // This will be true if the browser process has informed us that the
@@ -101,22 +105,16 @@
 
       this.input = input;
       this.select = select;
-      this.optionAllow = optionAllow;
-      this.optionBlock = optionBlock;
 
       this.updateEditables();
 
+      // Editing notifications and geolocation is disabled for now.
+      if (this.contentType == 'notifications' ||
+          this.contentType == 'location') {
+        this.editable = false;
+      }
+
       var listItem = this;
-
-      this.addEventListener('selectedChange', function(event) {
-        // Editing notifications and geolocation is disabled for now.
-        if (listItem.contentType == 'notifications' ||
-            listItem.contentType == 'location')
-          return;
-
-        listItem.editing = listItem.selected;
-      });
-
       // Handle events on the editable nodes.
       input.oninput = function(event) {
         listItem.inputValidityKnown = false;
@@ -124,25 +122,9 @@
                     [listItem.contentType, listItem.mode, input.value]);
       };
 
-      // Handles enter and escape which trigger reset and commit respectively.
-      function handleKeydown(e) {
-        // Make sure that the tree does not handle the key.
-        e.stopPropagation();
-
-        // Calling list.focus blurs the input which will stop editing the list
-        // item.
-        switch (e.keyIdentifier) {
-          case 'U+001B':  // Esc
-            // Reset the inputs.
-            listItem.updateEditables();
-            listItem.setPatternValid(true);
-          case 'Enter':
-            listItem.ownerDocument.activeElement.blur();
-        }
-      }
-
-      input.addEventListener('keydown', handleKeydown);
-      select.addEventListener('keydown', handleKeydown);
+      // Listen for edit events.
+      this.addEventListener('canceledit', this.onEditCancelled_);
+      this.addEventListener('commitedit', this.onEditCommitted_);
     },
 
     /**
@@ -211,97 +193,52 @@
     updateEditables: function() {
       this.resetInput();
 
-      if (this.setting == 'allow')
-        this.optionAllow.selected = true;
-      else if (this.setting == 'block')
-        this.optionBlock.selected = true;
-      else if (this.setting == 'session' && this.optionSession)
-        this.optionSession.selected = true;
-      else if (this.setting == 'ask' && this.optionAsk)
-        this.optionAsk.selected = true;
+      var settingOption =
+          this.select.querySelector('[value=\'' + this.setting + '\']');
+      if (settingOption)
+        settingOption.selected = true;
+    },
+
+    /** @inheritDoc */
+    get currentInputIsValid() {
+      return this.inputValidityKnown && this.inputIsValid;
+    },
+
+    /** @inheritDoc */
+    get hasBeenEdited() {
+      var livePattern = this.input.value;
+      var liveSetting = this.select.value;
+      return livePattern != this.pattern || liveSetting != this.setting;
     },
 
     /**
-     * Fiddle with the display of elements of this list item when the editing
-     * mode changes.
+     * Called when committing an edit.
+     * @param {Event} e The end event.
+     * @private
      */
-    toggleVisibilityForEditing: function() {
-      this.patternLabel.classList.toggle('hidden');
-      this.settingLabel.classList.toggle('hidden');
-      this.input.classList.toggle('hidden');
-      this.select.classList.toggle('hidden');
+    onEditCommitted_: function(e) {
+      var newPattern = this.input.value;
+      var newSetting = this.select.value;
+
+      this.finishEdit(newPattern, newSetting);
     },
 
     /**
-     * Whether the user is currently able to edit the list item.
-     * @type {boolean}
+     * Called when cancelling an edit; resets the control states.
+     * @param {Event} e The cancel event.
+     * @private
      */
-    get editing() {
-      return this.hasAttribute('editing');
-    },
-    set editing(editing) {
-      var oldEditing = this.editing;
-      if (oldEditing == editing)
-        return;
-
-      var input = this.input;
-
-      this.toggleVisibilityForEditing();
-
-      if (editing) {
-        this.setAttribute('editing', '');
-        cr.ui.limitInputWidth(input, this, 20);
-        // When this is called in response to the selectedChange event,
-        // the list grabs focus immediately afterwards. Thus we must delay
-        // our focus grab.
-        window.setTimeout(function() {
-          input.focus();
-          input.select();
-        }, 50);
-
-        // TODO(estade): should we insert example text here for the AddNewRow
-        // input?
-      } else {
-        this.removeAttribute('editing');
-
-        // Check that we have a valid pattern and if not we do not, abort
-        // changes to the exception.
-        if (!this.inputValidityKnown || !this.inputIsValid) {
-          this.updateEditables();
-          this.setPatternValid(true);
-          return;
-        }
-
-        var newPattern = input.value;
-
-        var newSetting;
-        var optionAllow = this.optionAllow;
-        var optionBlock = this.optionBlock;
-        var optionSession = this.optionSession;
-        var optionAsk = this.optionAsk;
-        if (optionAllow.selected)
-          newSetting = 'allow';
-        else if (optionBlock.selected)
-          newSetting = 'block';
-        else if (optionSession && optionSession.selected)
-          newSetting = 'session';
-        else if (optionAsk && optionAsk.selected)
-          newSetting = 'ask';
-
-        this.finishEdit(newPattern, newSetting);
-      }
+    onEditCancelled_: function() {
+      this.updateEditables();
+      this.setPatternValid(true);
     },
 
     /**
      * Editing is complete; update the model.
-     * @type {string} newPattern The pattern that the user entered.
-     * @type {string} newSetting The setting the user chose.
+     * @param {string} newPattern The pattern that the user entered.
+     * @param {string} newSetting The setting the user chose.
      */
     finishEdit: function(newPattern, newSetting) {
-      // Empty edit - do nothing.
-      if (newPattern == this.pattern && newSetting == this.setting)
-        return;
-
       this.patternLabel.textContent = newPattern;
       this.settingLabel.textContent = this.settingForDisplay();
       var oldPattern = this.pattern;
@@ -350,8 +287,6 @@
       ExceptionsListItem.prototype.decorate.call(this);
 
       this.input.placeholder = templateData.addNewExceptionInstructions;
-      this.input.classList.remove('hidden');
-      this.select.classList.remove('hidden');
 
       // Do we always want a default of allow?
       this.setting = 'allow';
@@ -364,23 +299,18 @@
       this.input.value = '';
     },
 
-    /**
-     * No elements show or hide when going into edit mode, so do nothing.
-     */
-    toggleVisibilityForEditing: function() {
-      // No-op.
+    /** @inheritDoc */
+    get hasBeenEdited() {
+      return this.input.value != '';
     },
 
     /**
      * Editing is complete; update the model. As long as the pattern isn't
      * empty, we'll just add it.
-     * @type {string} newPattern The pattern that the user entered.
-     * @type {string} newSetting The setting the user chose.
+     * @param {string} newPattern The pattern that the user entered.
+     * @param {string} newSetting The setting the user chose.
      */
     finishEdit: function(newPattern, newSetting) {
-      if (newPattern == '')
-        return;
-
       chrome.send('setException',
                   [this.contentType, this.mode, newPattern, newSetting]);
     },
@@ -394,15 +324,14 @@
   var ExceptionsList = cr.ui.define('list');
 
   ExceptionsList.prototype = {
-    __proto__: DeletableItemList.prototype,
+    __proto__: InlineEditableItemList.prototype,
 
     /**
      * Called when an element is decorated as a list.
      */
     decorate: function() {
-      DeletableItemList.prototype.decorate.call(this);
+      InlineEditableItemList.prototype.decorate.call(this);
 
-      this.selectionModel = new cr.ui.ListSingleSelectionModel;
       this.classList.add('settings-list');
 
       for (var parentNode = this.parentNode; parentNode;
@@ -424,7 +353,7 @@
         window.setTimeout(function() {
           var activeElement = doc.activeElement;
           if (!exceptionList.contains(activeElement))
-            exceptionList.selectionModel.clear();
+            exceptionList.selectionModel.unselectAll();
         }, 50);
       }
 
@@ -458,16 +387,21 @@
     },
 
     /**
-     * Adds an exception to the js model.
-     * @param {Object} entry A dictionary of values for the exception.
+     * Sets the exceptions in the js model.
+     * @param {Object} entries A list of dictionaries of values, each dictionary
+     *     represents an exception.
      */
-    addException: function(entry) {
+    setExceptions: function(entries) {
+      var deleteCount = this.dataModel.length;
+
       if (this.isEditable()) {
-        // We have to add it before the Add New Exception row.
-        this.dataModel.splice(this.dataModel.length - 1, 0, entry);
-      } else {
-        this.dataModel.push(entry);
+        // We don't want to remove the Add New Exception row.
+        deleteCount = deleteCount - 1;
       }
+
+      var args = [0, deleteCount];
+      args.push.apply(args, entries);
+      this.dataModel.splice.apply(this.dataModel, args);
     },
 
     /**
@@ -513,10 +447,8 @@
     /** @inheritDoc */
     deleteItemAtIndex: function(index) {
       var listItem = this.getListItemByIndex(index);
-      if (listItem.undeletable) {
-        console.log('Tried to delete an undeletable row.');
+      if (listItem.undeletable)
         return;
-      }
 
       var dataItem = listItem.dataItem;
       var args = [listItem.contentType];
@@ -529,15 +461,6 @@
 
       chrome.send('removeException', args);
     },
-
-    /**
-     * Puts the selected row in editing mode.
-     */
-    editSelectedRow: function() {
-      var li = this.getListItem(this.selectedItem);
-      if (li)
-        li.editing = true;
-    }
   };
 
   var OptionsPage = options.OptionsPage;
@@ -548,7 +471,8 @@
    */
   function ContentSettingsExceptionsArea() {
     OptionsPage.call(this, 'contentExceptions',
-                     '', 'content-settings-exceptions-area');
+                     templateData.contentSettingsPageTabTitle,
+                     'content-settings-exceptions-area');
   }
 
   cr.addSingletonGetter(ContentSettingsExceptionsArea);
@@ -565,6 +489,9 @@
       }
 
       ContentSettingsExceptionsArea.hideOTRLists();
+
+      // If the user types in the URL without a hash, show just cookies.
+      this.showList('cookies');
     },
 
     /**
@@ -583,6 +510,16 @@
           divs[i].classList.add('hidden');
       }
     },
+
+    /**
+     * Called after the page has been shown. Show the content type for the
+     * location's hash.
+     */
+    didShowPage: function() {
+      var hash = location.hash;
+      if (hash)
+        this.showList(hash.slice(1));
+    },
   };
 
   /**
diff --git a/chrome/browser/resources/options/cookies_view.css b/chrome/browser/resources/options/cookies_view.css
index 737c910..3efe4e7 100644
--- a/chrome/browser/resources/options/cookies_view.css
+++ b/chrome/browser/resources/options/cookies_view.css
@@ -5,6 +5,7 @@
 */
 
 .cookies-info-table {
+  table-layout: fixed;
   width: 100%;
 }
 
@@ -31,13 +32,12 @@
 
 #cookiesTree {
   border: 1px solid lightgrey;
-  height: 200px;
   margin: 0;
   padding: 5px;
 }
 
 #cookieContent {
   display: block;
-  width: 520px;
+  width: 300px;
   word-wrap: break-word;
 }
diff --git a/chrome/browser/resources/options/cookies_view.html b/chrome/browser/resources/options/cookies_view.html
index 7092290..be24052 100644
--- a/chrome/browser/resources/options/cookies_view.html
+++ b/chrome/browser/resources/options/cookies_view.html
@@ -47,6 +47,12 @@
           </tr>
           <tr>
             <td class="cookie-details-label"
+                i18n-content="label_cookie_accessible_to_script">
+            </td>
+            <td><span id="cookieAccessibleToScript"></span></td>
+          </tr>
+          <tr>
+            <td class="cookie-details-label"
                 i18n-content="label_cookie_created">
             </td>
             <td><span id="cookieCreated"></span></td>
diff --git a/chrome/browser/resources/options/cookies_view.js b/chrome/browser/resources/options/cookies_view.js
index 0f51fcb..f640404 100644
--- a/chrome/browser/resources/options/cookies_view.js
+++ b/chrome/browser/resources/options/cookies_view.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,7 +15,7 @@
    */
   function CookiesView(model) {
     OptionsPage.call(this, 'cookiesView',
-                     localStrings.getString('cookiesViewPage'),
+                     templateData.cookiesViewPageTabTitle,
                      'cookiesViewPage');
   }
 
@@ -93,13 +93,15 @@
      * Clears cookie info.
      */
     clearCookieInfo: function() {
-      $('cookieName').textContent = localStrings.getString('no_cookie');
-      $('cookieContent').textContent = localStrings.getString('no_cookie');
-      $('cookieDomain').textContent = localStrings.getString('no_cookie');
-      $('cookiePath').textContent = localStrings.getString('no_cookie');
-      $('cookieSendFor').textContent = localStrings.getString('no_cookie');
-      $('cookieCreated').textContent = localStrings.getString('no_cookie');
-      $('cookieExpires').textContent = localStrings.getString('no_cookie');
+      var noCookie = localStrings.getString('no_cookie');
+      $('cookieName').textContent = noCookie;
+      $('cookieContent').textContent = noCookie;
+      $('cookieDomain').textContent = noCookie;
+      $('cookiePath').textContent = noCookie;
+      $('cookieSendFor').textContent = noCookie;
+      $('cookieAccessibleToScript').textContent = noCookie;
+      $('cookieCreated').textContent = noCookie;
+      $('cookieExpires').textContent = noCookie;
     },
 
     /**
@@ -111,6 +113,7 @@
       $('cookieDomain').textContent = cookie.domain;
       $('cookiePath').textContent = cookie.path;
       $('cookieSendFor').textContent = cookie.sendfor;
+      $('cookieAccessibleToScript').textContent = cookie.accessibleToScript;
       $('cookieCreated').textContent = cookie.created;
       $('cookieExpires').textContent = cookie.expires;
     },
@@ -119,7 +122,7 @@
      * Sets app cache info to display.
      */
     setAppCacheInfo: function(appCache) {
-      $('appCacheManifest').textContent = appCache.manefest;
+      $('appCacheManifest').textContent = appCache.manifest;
       $('appCacheSize').textContent = appCache.size;
       $('appCacheCreated').textContent = appCache.created;
       $('appCacheLastAccessed').textContent = appCache.accessed;
diff --git a/chrome/browser/resources/options/deletable_item_list.js b/chrome/browser/resources/options/deletable_item_list.js
index 5d5b35b..f397611 100644
--- a/chrome/browser/resources/options/deletable_item_list.js
+++ b/chrome/browser/resources/options/deletable_item_list.js
@@ -59,7 +59,8 @@
       this.appendChild(this.contentElement_);
 
       this.closeButtonElement_ = this.ownerDocument.createElement('button');
-      this.closeButtonElement_.className = 'close-button';
+      this.closeButtonElement_.classList.add('raw-button');
+      this.closeButtonElement_.classList.add('close-button');
       this.closeButtonElement_.addEventListener('mousedown',
                                                 this.handleMouseDownUpOnClose_);
       this.closeButtonElement_.addEventListener('mouseup',
@@ -107,6 +108,7 @@
     decorate: function() {
       List.prototype.decorate.call(this);
       this.addEventListener('click', this.handleClick_);
+      this.addEventListener('keydown', this.handleKeyDown_);
     },
 
     /**
@@ -119,7 +121,7 @@
         return;
 
       var target = e.target;
-      if (target.className == 'close-button') {
+      if (target.classList.contains('close-button')) {
         var listItem = this.getListItemAncestor(target);
         var selected = this.selectionModel.selectedIndexes;
 
@@ -130,15 +132,43 @@
         if (selected.indexOf(idx) == -1) {
           this.deleteItemAtIndex(idx);
         } else {
-          // Reverse through the list of selected indexes to maintain the
-          // correct index values after deletion.
-          for (var j = selected.length - 1; j >= 0; j--)
-            this.deleteItemAtIndex(selected[j]);
+          this.deleteSelectedItems_();
         }
       }
     },
 
     /**
+     * Callback for keydown events.
+     * @param {Event} e The keydown event object.
+     * @private
+     */
+    handleKeyDown_: function(e) {
+      // Map delete (and backspace on Mac) to item deletion (unless focus is
+      // in an input field, where it's intended for text editing).
+      if ((e.keyCode == 46 || (e.keyCode == 8 && cr.isMac)) &&
+          e.target.tagName != 'INPUT') {
+        this.deleteSelectedItems_();
+        // Prevent the browser from going back.
+        e.preventDefault();
+      }
+    },
+
+    /**
+     * Deletes all the currently selected items that are deletable.
+     * @private
+     */
+    deleteSelectedItems_: function() {
+      var selected = this.selectionModel.selectedIndexes;
+      // Reverse through the list of selected indexes to maintain the
+      // correct index values after deletion.
+      for (var j = selected.length - 1; j >= 0; j--) {
+        var index = selected[j];
+        if (this.getListItemByIndex(index).deletable)
+          this.deleteItemAtIndex(index);
+      }
+    },
+
+    /**
      * Called when an item should be deleted; subclasses are responsible for
      * implementing.
      * @param {number} index The index of the item that is being deleted.
diff --git a/chrome/browser/resources/options/edit_search_engine_overlay.css b/chrome/browser/resources/options/edit_search_engine_overlay.css
deleted file mode 100644
index fad104e..0000000
--- a/chrome/browser/resources/options/edit_search_engine_overlay.css
+++ /dev/null
@@ -1,36 +0,0 @@
-#editSearchEngineOverlay {
-  width: 500px;
-}
-
-#editSearchEngineOverlay table label {
-  text-align: end;
-}
-
-#editSearchEngineOverlay table,
-#editSearchEngineOverlay table td:nth-child(2) {
-  width: 100%;
-}
-
-#editSearchEngineOverlay table input {
-  width: 100%;
-  box-sizing: border-box;
-}
-
-#editSearchEngineOverlay .action-area {
-  margin-top: 2ex;
-}
-
-.valid-badge, .alert-badge {
-  width: 22px;
-  height: 21px;
-  background-position: 50% 1px;
-  background-repeat: no-repeat;
-}
-
-.valid-badge {
-  background-image: url("../../../../app/resources/input_good.png");
-}
-
-.alert-badge {
-  background-image: url("../../../app/theme/input_alert.png");
-}
diff --git a/chrome/browser/resources/options/edit_search_engine_overlay.html b/chrome/browser/resources/options/edit_search_engine_overlay.html
deleted file mode 100644
index 19c425a..0000000
--- a/chrome/browser/resources/options/edit_search_engine_overlay.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<div class="page hidden" id="editSearchEngineOverlay">
-  <h1 i18n-content="editSearchEngineTitle"></h1>
-
-  <form id="editSearchEngineForm">
-    <table>
-      <tr>
-        <td><label for="editSearchEngineName"><span
-            i18n-content="editSearchEngineNameLabel"></span></label></td>
-        <td><input type="text" id="editSearchEngineName"></td>
-        <td><div id="editSearchEngineNameValidity"
-            class="alert-badge">&nbsp;</div></td>
-      </tr>
-      <tr>
-        <td><label for="editSearchEngineKeyword"><span
-            i18n-content="editSearchEngineKeywordLabel"></span></label></td>
-        <td><input type="text" id="editSearchEngineKeyword"></td>
-        <td><div id="editSearchEngineKeywordValidity"
-            class="alert-badge">&nbsp;</div></td>
-      </tr>
-      <tr>
-        <td><label for="editSearchEngineURL"><span
-            i18n-content="editSearchEngineURLLabel"></span></label></td>
-        <td><input type="url" id="editSearchEngineURL"></td>
-        <td><div id="editSearchEngineURLValidity"
-            class="alert-badge">&nbsp;</div></td>
-      </tr>
-      <tr>
-        <td></td>
-        <td><span i18n-content="editSearchEngineURLExplanation"><span></td>
-        <td></td>
-    </table>
-
-    <div class="action-area button-strip">
-      <button type="reset"
-          i18n-content="editSearchEngineCancelButton"></button>
-      <button type="submit" id="editSearchEngineOkayButton" disabled
-          i18n-content="editSearchEngineOkayButton"></button>
-    </div>
-  </form>
-</div>
diff --git a/chrome/browser/resources/options/edit_search_engine_overlay.js b/chrome/browser/resources/options/edit_search_engine_overlay.js
deleted file mode 100644
index a4f72b5..0000000
--- a/chrome/browser/resources/options/edit_search_engine_overlay.js
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('options', function() {
-  const OptionsPage = options.OptionsPage;
-
-  /**
-   * EditSearchEngineOverlay class
-   * Encapsulated handling of the 'Edit Search Engine' overlay page.
-   * @class
-   * @constructor
-   */
-  function EditSearchEngineOverlay() {
-    OptionsPage.call(this, 'editSearchEngineOverlay',
-                     templateData.editSearchEngineTitle,
-                     'editSearchEngineOverlay');
-  }
-
-  cr.addSingletonGetter(EditSearchEngineOverlay);
-
-  EditSearchEngineOverlay.prototype = {
-    __proto__: OptionsPage.prototype,
-
-    /**
-     * Initializes the page.
-     */
-    initializePage: function() {
-      OptionsPage.prototype.initializePage.call(this);
-
-      var self = this;
-      var editForm = $('editSearchEngineForm');
-      editForm.onreset = function(e) {
-        chrome.send('searchEngineEditCancelled');
-        self.dismissOverlay_();
-      };
-      editForm.onsubmit = function(e) {
-        chrome.send('searchEngineEditCompleted', self.getInputFieldValues_());
-        self.dismissOverlay_();
-        return false;
-      };
-      var fieldIDs = ['editSearchEngineName',
-                      'editSearchEngineKeyword',
-                      'editSearchEngineURL'];
-      for (var i = 0; i < fieldIDs.length; i++) {
-        var field = $(fieldIDs[i]);
-        field.oninput = this.validateFields_.bind(this);
-        field.onkeydown = function(e) {
-          if (e.keyCode == 27)  // Esc
-            editForm.reset();
-        };
-      }
-    },
-
-    /**
-     * Clears any uncommited input, and dismisses the overlay.
-     * @private
-     */
-    dismissOverlay_: function() {
-      this.setEditDetails_();
-      OptionsPage.clearOverlays();
-    },
-
-    /**
-     * Fills the text fields from the given search engine.
-     * @private
-     */
-    setEditDetails_: function(engineDetails) {
-      if (engineDetails) {
-        $('editSearchEngineName').value = engineDetails['name'];
-        $('editSearchEngineKeyword').value = engineDetails['keyword'];
-        var urlField = $('editSearchEngineURL');
-        urlField.value = engineDetails['url'];
-        urlField.disabled = engineDetails['urlLocked'];
-        this.validateFields_();
-      } else {
-        $('editSearchEngineName').value = '';
-        $('editSearchEngineKeyword').value = '';
-        $('editSearchEngineURL').value = '';
-        var invalid = { name: false, keyword: false, url: false };
-        this.updateValidityWithResults_(invalid);
-      }
-    },
-
-    /**
-     * Starts the process of asynchronously validating the user input. Results
-     * will be reported to updateValidityWithResults_.
-     * @private
-     */
-    validateFields_: function() {
-      chrome.send('checkSearchEngineInfoValidity', this.getInputFieldValues_());
-    },
-
-    /**
-     * Sets the validation images and the enabled state of the Add button based
-     * on the current values of the text fields.
-     * @private
-     * @param {Object} The dictionary of validity states.
-     */
-    updateValidityWithResults_: function(validity) {
-      this.setBadgeValidity_($('editSearchEngineNameValidity'),
-                             validity['name'],
-                             'editSearchEngineInvalidTitleToolTip');
-      this.setBadgeValidity_($('editSearchEngineKeywordValidity'),
-                             validity['keyword'],
-                             'editSearchEngineInvalidKeywordToolTip');
-      this.setBadgeValidity_($('editSearchEngineURLValidity'),
-                             validity['url'],
-                             'editSearchEngineInvalidURLToolTip');
-      $('editSearchEngineOkayButton').disabled =
-          !(validity['name'] && validity['keyword'] && validity['url']);
-    },
-
-    /**
-     * Updates the state of the given validity indicator badge.
-     * @private
-     * @param {HTMLElement} The badge element to adjust.
-     * @param {boolean} Whether or not the badge should be set to the valid
-     *     state.
-     * @param {string} The tooltip string id for the invalid state.
-     */
-    setBadgeValidity_: function(element, isValid, tooltip_id) {
-      if (isValid) {
-        element.className = 'valid-badge';
-        element.title = '';
-      } else {
-        element.className = 'alert-badge';
-        element.title = localStrings.getString(tooltip_id);
-      }
-    },
-
-    /**
-     * Returns the input field values as an array suitable for passing to
-     * chrome.send. The order of the array is important.
-     * @private
-     * @return {array} The current input field values.
-     */
-    getInputFieldValues_: function() {
-      return [ $('editSearchEngineName').value,
-               $('editSearchEngineKeyword').value,
-               $('editSearchEngineURL').value ];
-    }
-  };
-
-  EditSearchEngineOverlay.setEditDetails = function(engineDetails) {
-    EditSearchEngineOverlay.getInstance().setEditDetails_(engineDetails);
-  };
-
-  EditSearchEngineOverlay.validityCheckCallback = function(validity) {
-    EditSearchEngineOverlay.getInstance().updateValidityWithResults_(validity);
-  };
-
-  // Export
-  return {
-    EditSearchEngineOverlay: EditSearchEngineOverlay
-  };
-
-});
diff --git a/chrome/browser/resources/options/font_settings.css b/chrome/browser/resources/options/font_settings.css
new file mode 100644
index 0000000..12dbea2
--- /dev/null
+++ b/chrome/browser/resources/options/font_settings.css
@@ -0,0 +1,25 @@
+#font-settings > section > .font-input-div {
+  -webkit-margin-end: 4em;
+}
+
+.font-input-div > div > select {
+  margin-bottom: 10px;
+}
+
+.font-input-div > div > .font-input {
+  width: 12em;
+}
+
+#font-settings > section > .font-sample-div {
+  height: 90px;
+  overflow: hidden;
+  width: 300px;
+}
+
+.font-settings-huge {
+  float: right;
+}
+
+#minimum-font-sample {
+  height: 60px;
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/options/font_settings.html b/chrome/browser/resources/options/font_settings.html
index 97ba0f7..d9e289a 100644
--- a/chrome/browser/resources/options/font_settings.html
+++ b/chrome/browser/resources/options/font_settings.html
@@ -1,75 +1,71 @@
 <div id="font-settings" class="page hidden">
-  <h1 i18n-content="fontSettingsTitle"></h1>
+  <h1 i18n-content="fontSettingsPage"></h1>
   <section>
-    <h3 i18n-content="fontSettingsFontTitle"></h3>
-    <div>
+    <h3 i18n-content="fontSettingsStandard"></h3>
+    <div class="font-input-div">
       <div>
-        <label style="display:inline;">
-          <span i18n-content="fontSettingsSerifLabel"></span>
-          <select id="fontSettingsSerifSelector"
-              i18n-options="fontSettingsFontList"
-              pref="webkit.webprefs.serif_font_family"
-              metric="Options_ChangeSerifFont"></select>
-        </label>
-        <label style="display:inline;">
-          <span i18n-content="fontSettingsSizeLabel"></span>
-          <select id="fontSettingsSerifSizeSelector"
-              i18n-options="fontSettingsFontSizeList"
-              pref="webkit.webprefs.default_font_size"
-              metric="Options_ChangeSerifFontSize"></select>
-        </label>
-        <div id="fontSettingsSerifPreview"></div>
+        <select class="font-input" i18n-options="fontSettingsFontList"
+            pref="webkit.webprefs.serif_font_family"
+            dataType="string"
+            metric="Options_ChangeSerifFont"></select>
       </div>
       <div>
-        <label style="display:inline;">
-          <span i18n-content="fontSettingsSansSerifLabel"></span>
-          <select id="fontSettingsSansSerifSelector"
-              i18n-options="fontSettingsFontList"
-              pref="webkit.webprefs.sansserif_font_family"
-              metric="Options_ChangeSansSerifFont"></select>
-        </label>
-        <label style="display:inline;">
-          <span i18n-content="fontSettingsSizeLabel"></span>
-          <select id="fontSettingsSansSerifSizeSelector"
-              18n-options="fontSettingsFontSizeList"
-              pref="webkit.webprefs.default_font_size"
-              metric="Options_ChangeSansSerifFontSize"></select>
-        </label>
-        <div id="fontSettingsSansSerifPreview"></div>
-      </div>
-      <div>
-        <label style="display:inline;">
-          <span i18n-content="fontSettingsFixedWidthLabel"></span>
-          <select id="fontSettingsFixedWidthSelector"
-              i18n-options="fontSettingsFontList"
-              pref="webkit.webprefs.fixed_font_family"
-              metric="Options_ChangeFixedFont"></select>
-        </label>
-        <label style="display:inline;">
-          <span i18n-content="fontSettingsSizeLabel"></span>
-          <select id="fontSettingsFixedWidthSizeSelector"
-              i18n-options="fontSettingsFontSizeList"
-              pref="webkit.webprefs.default_fixed_font_size"
-              metric="Options_ChangeFixedFontSize"></select>
-        </label>
-        <div id="fontSettingsFixedWidthPreview"></div>
+        <input id="serif-font-size" type="range" min="0" max="24"
+            pref="webkit.webprefs.default_font_size" class="font-input">
+        <div>
+          <span i18n-content="fontSettingsSizeTiny"></span>
+          <span i18n-content="fontSettingsSizeHuge" class="font-settings-huge">
+              </span>
+        </div>
       </div>
     </div>
+    <div id="serif-font-sample" class="font-sample-div"></div>
   </section>
   <section>
-    <h3 i18n-content="fontSettingsMinimumSizeTitle"></h3>
-    <div>
-      <select id="fontSettingsMinimumSizeSelector"
-          i18n-options="fontSettingsMinimumFontSizeList"></select>
+    <h3 i18n-content="fontSettingsFixedWidth"></h3>
+    <div class="font-input-div">
+      <div>
+        <select class="font-input" i18n-options="fontSettingsFontList"
+            pref="webkit.webprefs.fixed_font_family"
+            dataType="string"
+            metric="Options_ChangeFixedFont"></select>
+      </div>
+      <div>
+        <input id="fixed-font-size" type="range" min="0" max="24"
+            pref="webkit.webprefs.default_fixed_font_size" class="font-input">
+        <div>
+          <span i18n-content="fontSettingsSizeTiny"></span>
+          <span i18n-content="fontSettingsSizeHuge" class="font-settings-huge">
+              </span>
+        </div>
+      </div>
     </div>
+    <div id="fixed-font-sample" class="font-sample-div"></div>
   </section>
   <section>
-    <h3 i18n-content="fontSettingsEncodingTitle"></h3>
-    <div>
-      <select id="fontSettingsEncodingSelector"
-          i18n-options="fontSettingsEncodingList"
-          pref="intl.charset_default"
-          metric="Options_ChangeFontEncoding"></select>
+    <h3 i18n-content="fontSettingsMinimumSize"></h3>
+    <div class="font-input-div">
+      <div>
+        <input id="minimum-font-size" type="range" min="0" max="12"
+            pref="webkit.webprefs.minimum_font_size" class="font-input">
+        <div>
+          <span i18n-content="fontSettingsSizeTiny"></span>
+          <span i18n-content="fontSettingsSizeHuge" class="font-settings-huge">
+              </span>
+        </div>
+      </div>
+    </div>
+    <div id="minimum-font-sample" class="font-sample-div"></div>
+  </section>
+  <section>
+    <h3 i18n-content="fontSettingsEncoding"></h3>
+    <div class="font-input-div">
+      <div>
+        <select class="font-input" i18n-options="fontSettingsEncodingList"
+            pref="intl.charset_default"
+            dataType="string"
+            metric="Options_ChangeFontEncoding"></select>
+      </div>
     </div>
   </section>
 </div>
diff --git a/chrome/browser/resources/options/font_settings.js b/chrome/browser/resources/options/font_settings.js
index e828635..1f3d075 100644
--- a/chrome/browser/resources/options/font_settings.js
+++ b/chrome/browser/resources/options/font_settings.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,13 +8,13 @@
 
   /**
    * FontSettings class
-   * Encapsulated handling of the 'Font Settings' page.
+   * Encapsulated handling of the 'Fonts and Encoding' page.
    * @class
    */
   function FontSettings() {
     OptionsPage.call(this,
                      'fontSettings',
-                     templateData.fontSettingsTitle,
+                     templateData.fontSettingsPageTabTitle,
                      'font-settings');
   }
 
@@ -27,34 +27,67 @@
      * Initialize the page.
      */
     initializePage: function() {
-      // Call base class implementation to starts preference initialization.
       OptionsPage.prototype.initializePage.call(this);
-    }
+
+      var serifFontRange = $('serif-font-size');
+      serifFontRange.valueMap = $('fixed-font-size').valueMap = [9, 10, 11, 12,
+          13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 40, 44,
+          48, 56, 64, 72];
+      serifFontRange.continuous = false;
+      serifFontRange.fontSampleEl = $('serif-font-sample');
+      serifFontRange.notifyChange = this.rangeChanged_.bind(this);
+
+      var minimumFontRange = $('minimum-font-size');
+      minimumFontRange.valueMap = [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20,
+          22, 24];
+      minimumFontRange.continuous = false;
+      minimumFontRange.fontSampleEl = $('minimum-font-sample');
+      minimumFontRange.notifyChange = this.rangeChanged_.bind(this);
+    },
+
+    /**
+     * @inheritDoc
+     */
+    rangeChanged_: function(el, value) {
+      this.setupFontSample_(
+          el.fontSampleEl, value, el.fontSampleEl.style.fontFamily);
+    },
+
+    /**
+     * Sets the text, font size and font family of the sample text.
+     * @param {Element} el The div containing the sample text.
+     * @param {number} size The font size of the sample text.
+     * @param {string} font The font family of the sample text.
+     * @private
+     */
+    setupFontSample_: function(el, size, font) {
+      el.textContent =
+          size + "pt: " + localStrings.getString('fontSettingsLoremIpsum');
+      el.style.fontSize = size + "pt";
+      if (font)
+        el.style.fontFamily = font;
+    },
   };
 
-  FontSettings.setupFontPreview = function(id, font, size) {
-    $(id).textContent = font + " " + size;
-    $(id).style.fontFamily = font;
-    $(id).style.fontSize = size + "pt";
-  }
-
   // Chrome callbacks
-  FontSettings.setupSerifFontPreview = function(text, size) {
-    this.setupFontPreview('fontSettingsSerifPreview', text, size);
-  }
+  FontSettings.setupSerifFontSample = function(font, size) {
+    FontSettings.getInstance().setupFontSample_(
+        $('serif-font-sample'), size, font);
+  };
 
-  FontSettings.setupSansSerifFontPreview = function(text, size) {
-    this.setupFontPreview('fontSettingsSansSerifPreview', text, size);
-  }
+  FontSettings.setupFixedFontSample = function(font, size) {
+    FontSettings.getInstance().setupFontSample_(
+        $('fixed-font-sample'), size, font);
+  };
 
-  FontSettings.setupFixedFontPreview = function(text, size) {
-    this.setupFontPreview('fontSettingsFixedWidthPreview', text, size);
-  }
+  FontSettings.setupMinimumFontSample = function(size) {
+    FontSettings.getInstance().setupFontSample_(
+        $('minimum-font-sample'), size);
+  };
 
   // Export
   return {
     FontSettings: FontSettings
   };
-
 });
 
diff --git a/chrome/browser/resources/options/font_settings_ui.js b/chrome/browser/resources/options/font_settings_ui.js
index 4af8141..8a0b7b6 100644
--- a/chrome/browser/resources/options/font_settings_ui.js
+++ b/chrome/browser/resources/options/font_settings_ui.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,12 +11,9 @@
   var MinimumFontSizeSelect = cr.ui.define('select');
 
   MinimumFontSizeSelect.prototype = {
-    // Set up the prototype chain
     __proto__: HTMLSelectElement.prototype,
 
-    /**
-    * Initialization function for the cr.ui framework.
-    */
+    /** @inheritDoc */
     decorate: function() {
       var self = this;
 
diff --git a/chrome/browser/resources/options/import_data_overlay.css b/chrome/browser/resources/options/import_data_overlay.css
index f49ee22..5c4fedd 100644
--- a/chrome/browser/resources/options/import_data_overlay.css
+++ b/chrome/browser/resources/options/import_data_overlay.css
@@ -1,8 +1,14 @@
+#import-from-div {
+  margin-bottom: 20px;
+}
+
+#import-checkboxes > div:not(:first-child) {
+  -webkit-padding-start: 8px;
+  margin: 5px 0;
+}
+
 #import-throbber {
-  background-image: url("../../../../app/resources/throbber.png");
-  width: 16px;
-  height: 16px;
-  margin: -3px 10px;
-  display: inline-block;
+  margin: 4px 10px;
+  vertical-align: middle;
   visibility: hidden;
 }
diff --git a/chrome/browser/resources/options/import_data_overlay.html b/chrome/browser/resources/options/import_data_overlay.html
index ace3502..adb2d9d 100644
--- a/chrome/browser/resources/options/import_data_overlay.html
+++ b/chrome/browser/resources/options/import_data_overlay.html
@@ -1,35 +1,39 @@
 <div id="import-data-overlay" class="page hidden">
-  <h1 i18n-content="importDataTitle"></h1>
-  <div>
-    <span i18n-content="importFromLabel"></span>
-    <select id="import-browsers">
-      <option i18n-content="importLoading"></option>
-    </select>
-  </div>
-  <div id="import-checkboxes">
-    <div i18n-content="importDescription"></div>
-    <div>
-      <input id="import-history" type="checkbox">
-      <label for="import-history" i18n-content="importHistory"></label>
+  <h1 i18n-content="importDataOverlayTitle"></h1>
+  <div class="content-area">
+    <div id="import-from-div">
+      <span i18n-content="importFromLabel"></span>
+      <select id="import-browsers">
+        <option i18n-content="importLoading"></option>
+      </select>
     </div>
-    <div>
-      <input id="import-favorites" type="checkbox">
-      <label for="import-favorites" i18n-content="importFavorites"></label>
-    </div>
-    <div>
-      <input id="import-passwords" type="checkbox">
-      <label for="import-passwords" i18n-content="importPasswords"></label>
-    </div>
-    <div>
-      <input id="import-search" type="checkbox">
-      <label for="import-search" i18n-content="importSearch"></label>
+    <div id="import-checkboxes">
+      <div i18n-content="importDescription"></div>
+      <div>
+        <input id="import-history" type="checkbox">
+        <label for="import-history" i18n-content="importHistory"></label>
+      </div>
+      <div>
+        <input id="import-favorites" type="checkbox">
+        <label for="import-favorites" i18n-content="importFavorites"></label>
+      </div>
+      <div>
+        <input id="import-passwords" type="checkbox">
+        <label for="import-passwords" i18n-content="importPasswords"></label>
+      </div>
+      <div>
+        <input id="import-search" type="checkbox">
+        <label for="import-search" i18n-content="importSearch"></label>
+      </div>
     </div>
   </div>
   <div class="action-area">
-    <span id="import-throbber"></span>
-    <div class="button-strip">
-      <button id="import-data-cancel" i18n-content="cancel"></button>
-      <button id="import-data-commit" i18n-content="importCommit"></button>
+    <div class="action-area-right">
+      <div id="import-throbber" class="throbber"></div>
+      <div class="button-strip">
+        <button id="import-data-cancel" i18n-content="cancel"></button>
+        <button id="import-data-commit" i18n-content="importCommit"></button>
+      </div>
     </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/import_data_overlay.js b/chrome/browser/resources/options/import_data_overlay.js
index 0b7ebab..9496f8a 100644
--- a/chrome/browser/resources/options/import_data_overlay.js
+++ b/chrome/browser/resources/options/import_data_overlay.js
@@ -1,9 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 cr.define('options', function() {
-
   var OptionsPage = options.OptionsPage;
 
   /**
@@ -14,12 +13,10 @@
   function ImportDataOverlay() {
     OptionsPage.call(this,
                      'importDataOverlay',
-                     templateData.import_data_title,
+                     templateData.importDataOverlayTabTitle,
                      'import-data-overlay');
   }
 
-  ImportDataOverlay.throbIntervalId = 0;
-
   cr.addSingletonGetter(ImportDataOverlay);
 
   ImportDataOverlay.prototype = {
@@ -168,18 +165,6 @@
     $('import-browsers').disabled = state;
     $('import-data-commit').disabled = state;
     $('import-throbber').style.visibility = state ? "visible" : "hidden";
-
-    function advanceThrobber() {
-      var throbber = $('import-throbber');
-      throbber.style.backgroundPositionX =
-          ((parseInt(getComputedStyle(throbber).backgroundPositionX, 10) - 16)
-          % 576) + 'px';
-    }
-    if (state) {
-      ImportDataOverlay.throbIntervalId = setInterval(advanceThrobber, 30);
-    } else {
-      clearInterval(ImportDataOverlay.throbIntervalId);
-    }
   };
 
   /**
@@ -187,12 +172,11 @@
    */
   ImportDataOverlay.dismiss = function() {
     ImportDataOverlay.setImportingState(false);
-    OptionsPage.clearOverlays();
-  }
+    OptionsPage.closeOverlay();
+  };
 
   // Export
   return {
     ImportDataOverlay: ImportDataOverlay
   };
-
 });
diff --git a/chrome/browser/resources/options/inline_editable_list.js b/chrome/browser/resources/options/inline_editable_list.js
new file mode 100644
index 0000000..81f9108
--- /dev/null
+++ b/chrome/browser/resources/options/inline_editable_list.js
@@ -0,0 +1,303 @@
+// 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.
+
+cr.define('options', function() {
+  const DeletableItem = options.DeletableItem;
+  const DeletableItemList = options.DeletableItemList;
+
+  /**
+   * Creates a new list item with support for inline editing.
+   * @constructor
+   * @extends {options.DeletableListItem}
+   */
+  function InlineEditableItem() {
+    var el = cr.doc.createElement('div');
+    InlineEditableItem.decorate(el);
+    return el;
+  }
+
+  /**
+   * Decorates an element as a inline-editable list item. Note that this is
+   * a subclass of DeletableItem.
+   * @param {!HTMLElement} el The element to decorate.
+   */
+  InlineEditableItem.decorate = function(el) {
+    el.__proto__ = InlineEditableItem.prototype;
+    el.decorate();
+  };
+
+  InlineEditableItem.prototype = {
+    __proto__: DeletableItem.prototype,
+
+    /**
+     * Whether or not this item can be edited.
+     * @type {boolean}
+     * @private
+     */
+    editable_: true,
+
+    /**
+     * Whether or not the current edit should be considered cancelled, rather
+     * than committed, when editing ends.
+     * @type {boolean}
+     * @private
+     */
+    editCancelled_: true,
+
+    /** @inheritDoc */
+    decorate: function() {
+      DeletableItem.prototype.decorate.call(this);
+
+      this.addEventListener('keydown', this.handleKeyDown_.bind(this));
+      this.addEventListener('leadChange', this.handleLeadChange_);
+    },
+
+    /** @inheritDoc */
+    selectionChanged: function() {
+      this.updateEditState();
+    },
+
+    /**
+     * Called when this element gains or loses 'lead' status. Updates editing
+     * mode accordingly.
+     * @private
+     */
+    handleLeadChange_: function() {
+      this.updateEditState();
+    },
+
+    /**
+     * Updates the edit state based on the current selected and lead states.
+     */
+    updateEditState: function() {
+      if (this.editable)
+        this.editing = this.selected && this.lead;
+    },
+
+    /**
+     * Whether the user is currently editing the list item.
+     * @type {boolean}
+     */
+    get editing() {
+      return this.hasAttribute('editing');
+    },
+    set editing(editing) {
+      if (this.editing == editing)
+        return;
+
+      if (editing)
+        this.setAttribute('editing', '');
+      else
+        this.removeAttribute('editing');
+
+      if (editing) {
+        this.editCancelled_ = false;
+
+        cr.dispatchSimpleEvent(this, 'edit', true);
+
+        var self = this;
+        var focusElement = this.initialFocusElement;
+        // When this is called in response to the selectedChange event,
+        // the list grabs focus immediately afterwards. Thus we must delay
+        // our focus grab.
+        if (focusElement) {
+          window.setTimeout(function() {
+            // Make sure we are still in edit mode by the time we execute.
+            if (self.editing) {
+              focusElement.focus();
+              focusElement.select();
+            }
+          }, 50);
+        }
+      } else {
+        if (!this.editCancelled_ && this.hasBeenEdited &&
+            this.currentInputIsValid) {
+          this.updateStaticValues_();
+          cr.dispatchSimpleEvent(this, 'commitedit', true);
+        } else {
+          this.resetEditableValues_();
+          cr.dispatchSimpleEvent(this, 'canceledit', true);
+        }
+      }
+    },
+
+    /**
+     * Whether the item is editable.
+     * @type {boolean}
+     */
+    get editable() {
+      return this.editable_;
+    },
+    set editable(editable) {
+      this.editable_ = editable;
+      if (!editable)
+        this.editing = false;
+    },
+
+    /**
+     * The HTML element that should have focus initially when editing starts.
+     * Defaults to the first <input> element; can be overriden by subclasses if
+     * a different element should be focused.
+     * @type {HTMLElement}
+     */
+    get initialFocusElement() {
+      return this.contentElement.querySelector('input');
+    },
+
+    /**
+     * Whether the input in currently valid to submit. If this returns false
+     * when editing would be submitted, either editing will not be ended,
+     * or it will be cancelled, depending on the context.
+     * Can be overrided by subclasses to perform input validation.
+     * @type {boolean}
+     */
+    get currentInputIsValid() {
+      return true;
+    },
+
+    /**
+     * Returns true if the item has been changed by an edit.
+     * Can be overrided by subclasses to return false when nothing has changed
+     * to avoid unnecessary commits.
+     * @type {boolean}
+     */
+    get hasBeenEdited() {
+      return true;
+    },
+
+    /**
+     * Returns a div containing an <input>, as well as static text if
+     * opt_alwaysEditable is not true.
+     * @param {string} text The text of the cell.
+     * @param {bool} opt_alwaysEditable True if the cell always shows the input.
+     * @return {HTMLElement} The HTML element for the cell.
+     * @private
+     */
+    createEditableTextCell: function(text, opt_alwaysEditable) {
+      var container = this.ownerDocument.createElement('div');
+
+      if (!opt_alwaysEditable) {
+        var textEl = this.ownerDocument.createElement('div');
+        textEl.className = 'static-text';
+        textEl.textContent = text;
+        textEl.setAttribute('displaymode', 'static');
+        container.appendChild(textEl);
+      }
+
+      var inputEl = this.ownerDocument.createElement('input');
+      inputEl.type = 'text';
+      inputEl.value = text;
+      if (!opt_alwaysEditable) {
+        inputEl.setAttribute('displaymode', 'edit');
+        inputEl.staticVersion = textEl;
+      }
+      container.appendChild(inputEl);
+
+      return container;
+    },
+
+    /**
+     * Resets the editable version of any controls created by createEditable*
+     * to match the static text.
+     * @private
+     */
+    resetEditableValues_: function() {
+      var editFields = this.querySelectorAll('[editmode=true]');
+      for (var i = 0; i < editFields.length; i++) {
+        var staticLabel = editFields[i].staticVersion;
+        if (!staticLabel)
+          continue;
+        if (editFields[i].tagName == 'INPUT')
+          editFields[i].value = staticLabel.textContent;
+        // Add more tag types here as new createEditable* methods are added.
+
+        editFields[i].setCustomValidity('');
+      }
+    },
+
+    /**
+     * Sets the static version of any controls created by createEditable*
+     * to match the current value of the editable version. Called on commit so
+     * that there's no flicker of the old value before the model updates.
+     * @private
+     */
+    updateStaticValues_: function() {
+      var editFields = this.querySelectorAll('[editmode=true]');
+      for (var i = 0; i < editFields.length; i++) {
+        var staticLabel = editFields[i].staticVersion;
+        if (!staticLabel)
+          continue;
+        if (editFields[i].tagName == 'INPUT')
+          staticLabel.textContent = editFields[i].value;
+        // Add more tag types here as new createEditable* methods are added.
+      }
+    },
+
+    /**
+     * Called a key is pressed. Handles committing and cancelling edits.
+     * @param {Event} e The key down event.
+     * @private
+     */
+    handleKeyDown_: function(e) {
+      if (!this.editing)
+        return;
+
+      var endEdit = false;
+      switch (e.keyIdentifier) {
+        case 'U+001B':  // Esc
+          this.editCancelled_ = true;
+          endEdit = true;
+          break;
+        case 'Enter':
+          if (this.currentInputIsValid)
+            endEdit = true;
+          break;
+      }
+
+      if (endEdit) {
+        // Blurring will trigger the edit to end; see InlineEditableItemList.
+        this.ownerDocument.activeElement.blur();
+        // Make sure that handled keys aren't passed on and double-handled.
+        // (e.g., esc shouldn't both cancel an edit and close a subpage)
+        e.stopPropagation();
+      }
+    },
+  };
+
+  var InlineEditableItemList = cr.ui.define('list');
+
+  InlineEditableItemList.prototype = {
+    __proto__: DeletableItemList.prototype,
+
+    /** @inheritDoc */
+    decorate: function() {
+      DeletableItemList.prototype.decorate.call(this);
+      this.setAttribute('inlineeditable', '');
+      this.addEventListener('hasElementFocusChange',
+                            this.handleListFocusChange_);
+    },
+
+    /**
+     * Called when the list hierarchy as a whole loses or gains focus; starts
+     * or ends editing for the lead item if necessary.
+     * @param {Event} e The change event.
+     * @private
+     */
+    handleListFocusChange_: function(e) {
+      var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex);
+      if (leadItem) {
+        if (e.newValue)
+          leadItem.updateEditState();
+        else
+          leadItem.editing = false;
+      }
+    },
+  };
+
+  // Export
+  return {
+    InlineEditableItem: InlineEditableItem,
+    InlineEditableItemList: InlineEditableItemList,
+  };
+});
diff --git a/chrome/browser/resources/options/instant_confirm_overlay.html b/chrome/browser/resources/options/instant_confirm_overlay.html
index fe0b8b1..e49d609 100644
--- a/chrome/browser/resources/options/instant_confirm_overlay.html
+++ b/chrome/browser/resources/options/instant_confirm_overlay.html
@@ -1,12 +1,16 @@
-<div class="page hidden" id="instantConfirmOverlay">
+<div id="instantConfirmOverlay" class="page hidden">
   <h1 i18n-content="instantConfirmTitle"></h1>
   <!-- The text has line breaks, so we must use a pre. -->
-  <pre id="instantConfirmText" i18n-content="instantConfirmMessage"></pre>
-  <a target="_blank" i18n-values="href:instantLearnMoreLink"
-     i18n-content="learnMore" id="instantConfirmLearnMore"></a>
-  <div class="action-area button-strip">
-    <button id="instantConfirmCancel" i18n-content="cancel"
-            class="cancel-button"></button>
-    <button id="instantConfirmOk" i18n-content="ok"></button>
+  <div class="content-area">
+    <pre id="instantConfirmText" i18n-content="instantConfirmMessage"></pre>
+    <a target="_blank" i18n-values="href:instantLearnMoreLink"
+       i18n-content="learnMore" id="instantConfirmLearnMore"></a>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button id="instantConfirmCancel" i18n-content="cancel"
+              class="cancel-button"></button>
+      <button id="instantConfirmOk" i18n-content="ok"></button>
+    </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/instant_confirm_overlay.js b/chrome/browser/resources/options/instant_confirm_overlay.js
index 53d0542..327ab53 100644
--- a/chrome/browser/resources/options/instant_confirm_overlay.js
+++ b/chrome/browser/resources/options/instant_confirm_overlay.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 cr.define('options', function() {
-
   var OptionsPage = options.OptionsPage;
 
   function InstantConfirmOverlay() {
@@ -22,10 +21,10 @@
       OptionsPage.prototype.initializePage.call(this);
 
       $('instantConfirmCancel').onclick = function() {
-        OptionsPage.clearOverlays();
+        OptionsPage.closeOverlay();
       };
       $('instantConfirmOk').onclick = function() {
-        OptionsPage.clearOverlays();
+        OptionsPage.closeOverlay();
         var instantDialogShown = $('instantDialogShown');
         Preferences.setBooleanPref(instantDialogShown.pref, true,
                                    instantDialogShown.metric);
@@ -40,5 +39,4 @@
   return {
     InstantConfirmOverlay: InstantConfirmOverlay
   };
-
 });
diff --git a/chrome/browser/resources/options/language_add_language_overlay.html b/chrome/browser/resources/options/language_add_language_overlay.html
new file mode 100644
index 0000000..f270acc
--- /dev/null
+++ b/chrome/browser/resources/options/language_add_language_overlay.html
@@ -0,0 +1,24 @@
+<div class="page hidden" id="add-language-overlay-page">
+<if expr="pp_ifdef('chromeos')">
+  <ul id="add-language-overlay-language-list">
+  </ul>
+  <button id="add-language-overlay-cancel-button"
+          i18n-content="cancel"></button>
+</if>
+<if expr="not pp_ifdef('chromeos')">
+  <h1 i18n-content="add_language_title"></h1>
+  <div class="content-area">
+    <label>
+      <span i18n-content="add_language_select_label"></span>
+      <select id="add-language-overlay-language-list"></select>
+    </label>
+  </div>
+  <div class="action-area">
+    <div class="button-strip">
+      <button id="add-language-overlay-cancel-button" i18n-content="cancel">
+      </button>
+      <button id="add-language-overlay-ok-button" i18n-content="ok"></button>
+    </div>
+  </div>
+</if>
+</div>
diff --git a/chrome/browser/resources/options/language_add_language_overlay.js b/chrome/browser/resources/options/language_add_language_overlay.js
new file mode 100644
index 0000000..56d193a
--- /dev/null
+++ b/chrome/browser/resources/options/language_add_language_overlay.js
@@ -0,0 +1,72 @@
+// 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.
+
+///////////////////////////////////////////////////////////////////////////////
+// AddLanguageOverlay class:
+
+cr.define('options', function() {
+  const OptionsPage = options.OptionsPage;
+
+  /**
+   * Encapsulated handling of ChromeOS add language overlay page.
+   * @constructor
+   */
+  function AddLanguageOverlay() {
+    OptionsPage.call(this, 'addLanguageOverlay',
+                     localStrings.getString('add_button'),
+                     'add-language-overlay-page');
+  }
+
+  cr.addSingletonGetter(AddLanguageOverlay);
+
+  AddLanguageOverlay.prototype = {
+    // Inherit AddLanguageOverlay from OptionsPage.
+    __proto__: OptionsPage.prototype,
+
+    /**
+     * Initializes AddLanguageOverlay page.
+     * Calls base class implementation to starts preference initialization.
+     */
+    initializePage: function() {
+      // Call base class implementation to starts preference initialization.
+      OptionsPage.prototype.initializePage.call(this);
+
+      // Set up the cancel button.
+      $('add-language-overlay-cancel-button').onclick = function(e) {
+        OptionsPage.closeOverlay();
+      };
+
+      // Create the language list with which users can add a language.
+      var addLanguageList = $('add-language-overlay-language-list');
+      var languageListData = templateData.languageList;
+      for (var i = 0; i < languageListData.length; i++) {
+        var language = languageListData[i];
+        var displayText = language.displayName;
+        // If the native name is different, add it.
+        if (language.displayName != language.nativeDisplayName) {
+          displayText += ' - ' + language.nativeDisplayName;
+        }
+        if (cr.isChromeOS) {
+          var button = document.createElement('button');
+          button.className = 'link-button';
+          button.textContent = displayText;
+          button.languageCode = language.code;
+          var li = document.createElement('li');
+          li.languageCode = language.code;
+          li.appendChild(button);
+          addLanguageList.appendChild(li);
+        } else {
+          var option = document.createElement('option');
+          option.value = language.code;
+          option.textContent = displayText;
+          addLanguageList.appendChild(option);
+        }
+      }
+    },
+  };
+
+  return {
+    AddLanguageOverlay: AddLanguageOverlay
+  };
+});
diff --git a/chrome/browser/resources/options/language_list.js b/chrome/browser/resources/options/language_list.js
new file mode 100644
index 0000000..ad9f499
--- /dev/null
+++ b/chrome/browser/resources/options/language_list.js
@@ -0,0 +1,373 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('options', function() {
+  const ArrayDataModel = cr.ui.ArrayDataModel;
+  const LanguageOptions = options.LanguageOptions;
+  const List = cr.ui.List;
+  const ListItem = cr.ui.ListItem;
+  const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
+
+  /**
+   * Creates a new language list.
+   * @param {Object=} opt_propertyBag Optional properties.
+   * @constructor
+   * @extends {cr.ui.List}
+   */
+  var LanguageList = cr.ui.define('list');
+
+  /**
+   * Gets display name from the given language code.
+   * @param {string} languageCode Language code (ex. "fr").
+   */
+  LanguageList.getDisplayNameFromLanguageCode = function(languageCode) {
+    // Build the language code to display name dictionary at first time.
+    if (!this.languageCodeToDisplayName_) {
+      this.languageCodeToDisplayName_ = {};
+      var languageList = templateData.languageList;
+      for (var i = 0; i < languageList.length; i++) {
+        var language = languageList[i];
+        this.languageCodeToDisplayName_[language.code] = language.displayName;
+      }
+    }
+
+    return this.languageCodeToDisplayName_[languageCode];
+  }
+
+  /**
+   * Gets native display name from the given language code.
+   * @param {string} languageCode Language code (ex. "fr").
+   */
+  LanguageList.getNativeDisplayNameFromLanguageCode = function(languageCode) {
+    // Build the language code to display name dictionary at first time.
+    if (!this.languageCodeToNativeDisplayName_) {
+      this.languageCodeToNativeDisplayName_ = {};
+      var languageList = templateData.languageList;
+      for (var i = 0; i < languageList.length; i++) {
+        var language = languageList[i];
+        this.languageCodeToNativeDisplayName_[language.code] =
+            language.nativeDisplayName;
+      }
+    }
+
+    return this.languageCodeToNativeDisplayName_[languageCode];
+  }
+
+  /**
+   * Returns true if the given language code is valid.
+   * @param {string} languageCode Language code (ex. "fr").
+   */
+  LanguageList.isValidLanguageCode = function(languageCode) {
+    // Having the display name for the language code means that the
+    // language code is valid.
+    if (LanguageList.getDisplayNameFromLanguageCode(languageCode)) {
+      return true;
+    }
+    return false;
+  }
+
+  LanguageList.prototype = {
+    __proto__: List.prototype,
+
+    // The list item being dragged.
+    draggedItem: null,
+    // The drop position information: "below" or "above".
+    dropPos: null,
+    // The preference is a CSV string that describes preferred languages
+    // in Chrome OS. The language list is used for showing the language
+    // list in "Language and Input" options page.
+    preferredLanguagesPref: 'settings.language.preferred_languages',
+    // The preference is a CSV string that describes accept languages used
+    // for content negotiation. To be more precise, the list will be used
+    // in "Accept-Language" header in HTTP requests.
+    acceptLanguagesPref: 'intl.accept_languages',
+
+    /** @inheritDoc */
+    decorate: function() {
+      List.prototype.decorate.call(this);
+      this.selectionModel = new ListSingleSelectionModel;
+
+      // HACK(arv): http://crbug.com/40902
+      window.addEventListener('resize', this.redraw.bind(this));
+
+      // Listen to pref change.
+      if (cr.isChromeOS) {
+        Preferences.getInstance().addEventListener(this.preferredLanguagesPref,
+            this.handlePreferredLanguagesPrefChange_.bind(this));
+      } else {
+        Preferences.getInstance().addEventListener(this.acceptLanguagesPref,
+            this.handleAcceptLanguagesPrefChange_.bind(this));
+      }
+
+      // Listen to drag and drop events.
+      this.addEventListener('dragstart', this.handleDragStart_.bind(this));
+      this.addEventListener('dragenter', this.handleDragEnter_.bind(this));
+      this.addEventListener('dragover', this.handleDragOver_.bind(this));
+      this.addEventListener('drop', this.handleDrop_.bind(this));
+    },
+
+    createItem: function(languageCode) {
+      var languageDisplayName =
+          LanguageList.getDisplayNameFromLanguageCode(languageCode);
+      var languageNativeDisplayName =
+          LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
+      return new ListItem({
+        label: languageDisplayName,
+        draggable: true,
+        languageCode: languageCode,
+        title: languageNativeDisplayName  // Show native name as tooltip.
+      });
+    },
+
+    /*
+     * Adds a language to the language list.
+     * @param {string} languageCode language code (ex. "fr").
+     */
+    addLanguage: function(languageCode) {
+      // It shouldn't happen but ignore the language code if it's
+      // null/undefined, or already present.
+      if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) {
+        return;
+      }
+      this.dataModel.push(languageCode);
+      // Select the last item, which is the language added.
+      this.selectionModel.selectedIndex = this.dataModel.length - 1;
+
+      this.savePreference_();
+    },
+
+    /*
+     * Gets the language codes of the currently listed languages.
+     */
+    getLanguageCodes: function() {
+      return this.dataModel.slice();
+    },
+
+    /*
+     * Gets the language code of the selected language.
+     */
+    getSelectedLanguageCode: function() {
+      return this.selectedItem;
+    },
+
+    /*
+     * Selects the language by the given language code.
+     * @returns {boolean} True if the operation is successful.
+     */
+    selectLanguageByCode: function(languageCode) {
+      var index = this.dataModel.indexOf(languageCode);
+      if (index >= 0) {
+        this.selectionModel.selectedIndex = index;
+        return true;
+      }
+      return false;
+    },
+
+    /*
+     * Removes the currently selected language.
+     */
+    removeSelectedLanguage: function() {
+      if (this.selectionModel.selectedIndex >= 0) {
+        this.dataModel.splice(this.selectionModel.selectedIndex, 1);
+        // Once the selected item is removed, there will be no selected item.
+        // Select the item pointed by the lead index.
+        this.selectionModel.selectedIndex = this.selectionModel.leadIndex;
+        this.savePreference_();
+      }
+    },
+
+    /*
+     * Handles the dragstart event.
+     * @param {Event} e The dragstart event.
+     * @private
+     */
+    handleDragStart_: function(e) {
+      var target = e.target;
+      // ListItem should be the only draggable element type in the page,
+      // but just in case.
+      if (target instanceof ListItem) {
+        this.draggedItem = target;
+        e.dataTransfer.effectAllowed = 'move';
+        // We need to put some kind of data in the drag or it will be
+        // ignored.  Use the display name in case the user drags to a text
+        // field or the desktop.
+        e.dataTransfer.setData('text/plain', target.title);
+      }
+    },
+
+    /*
+     * Handles the dragenter event.
+     * @param {Event} e The dragenter event.
+     * @private
+     */
+    handleDragEnter_: function(e) {
+      e.preventDefault();
+    },
+
+    /*
+     * Handles the dragover event.
+     * @param {Event} e The dragover event.
+     * @private
+     */
+    handleDragOver_: function(e) {
+      var dropTarget = e.target;
+      // Determins whether the drop target is to accept the drop.
+      // The drop is only successful on another ListItem.
+      if (!(dropTarget instanceof ListItem) ||
+          dropTarget == this.draggedItem) {
+        return;
+      }
+      // Compute the drop postion. Should we move the dragged item to
+      // below or above the drop target?
+      var rect = dropTarget.getBoundingClientRect();
+      var dy = e.clientY - rect.top;
+      var yRatio = dy / rect.height;
+      var dropPos = yRatio <= .5 ? 'above' : 'below';
+      this.dropPos = dropPos;
+      e.preventDefault();
+      // TODO(satorux): Show the drop marker just like the bookmark manager.
+    },
+
+    /*
+     * Handles the drop event.
+     * @param {Event} e The drop event.
+     * @private
+     */
+    handleDrop_: function(e) {
+      var dropTarget = e.target;
+
+      // Delete the language from the original position.
+      var languageCode = this.draggedItem.languageCode;
+      var originalIndex = this.dataModel.indexOf(languageCode);
+      this.dataModel.splice(originalIndex, 1);
+      // Insert the language to the new position.
+      var newIndex = this.dataModel.indexOf(dropTarget.languageCode);
+      if (this.dropPos == 'below')
+        newIndex += 1;
+      this.dataModel.splice(newIndex, 0, languageCode);
+      // The cursor should move to the moved item.
+      this.selectionModel.selectedIndex = newIndex;
+      // Save the preference.
+      this.savePreference_();
+    },
+
+    /**
+     * Handles preferred languages pref change.
+     * @param {Event} e The change event object.
+     * @private
+     */
+    handlePreferredLanguagesPrefChange_: function(e) {
+      var languageCodesInCsv = e.value.value;
+      var languageCodes = this.filterBadLanguageCodes_(
+          languageCodesInCsv.split(','));
+      this.load_(languageCodes);
+    },
+
+    /**
+     * Handles accept languages pref change.
+     * @param {Event} e The change event object.
+     * @private
+     */
+    handleAcceptLanguagesPrefChange_: function(e) {
+      var languageCodesInCsv = e.value.value;
+      var languageCodes = this.filterBadLanguageCodes_(
+          languageCodesInCsv.split(','));
+      this.load_(languageCodes);
+    },
+
+    /**
+     * Loads given language list.
+     * @param {Array} languageCodes List of language codes.
+     * @private
+     */
+    load_: function(languageCodes) {
+      // Preserve the original selected index. See comments below.
+      var originalSelectedIndex = (this.selectionModel ?
+                                   this.selectionModel.selectedIndex : -1);
+      this.dataModel = new ArrayDataModel(languageCodes);
+      if (originalSelectedIndex >= 0 &&
+          originalSelectedIndex < this.dataModel.length) {
+        // Restore the original selected index if the selected index is
+        // valid after the data model is loaded. This is neeeded to keep
+        // the selected language after the languge is added or removed.
+        this.selectionModel.selectedIndex = originalSelectedIndex;
+        // The lead index should be updated too.
+        this.selectionModel.leadIndex = originalSelectedIndex;
+      } else if (this.dataModel.length > 0){
+        // Otherwise, select the first item if it's not empty.
+        // Note that ListSingleSelectionModel won't select an item
+        // automatically, hence we manually select the first item here.
+        this.selectionModel.selectedIndex = 0;
+      }
+    },
+
+    /**
+     * Saves the preference.
+     */
+    savePreference_: function() {
+      // Encode the language codes into a CSV string.
+      if (cr.isChromeOS)
+        Preferences.setStringPref(this.preferredLanguagesPref,
+                                  this.dataModel.slice().join(','));
+      // Save the same language list as accept languages preference as
+      // well, but we need to expand the language list, to make it more
+      // acceptable. For instance, some web sites don't understand 'en-US'
+      // but 'en'. See crosbug.com/9884.
+      var acceptLanguages = this.expandLanguageCodes(this.dataModel.slice());
+      Preferences.setStringPref(this.acceptLanguagesPref,
+                                acceptLanguages.join(','));
+      cr.dispatchSimpleEvent(this, 'save');
+    },
+
+    /**
+     * Expands language codes to make these more suitable for Accept-Language.
+     * Example: ['en-US', 'ja', 'en-CA'] => ['en-US', 'en', 'ja', 'en-CA'].
+     * 'en' won't appear twice as this function eliminates duplicates.
+     * @param {Array} languageCodes List of language codes.
+     * @private
+     */
+    expandLanguageCodes: function(languageCodes) {
+      var expandedLanguageCodes = [];
+      var seen = {};  // Used to eliminiate duplicates.
+      for (var i = 0; i < languageCodes.length; i++) {
+        var languageCode = languageCodes[i];
+        if (!(languageCode in seen)) {
+          expandedLanguageCodes.push(languageCode);
+          seen[languageCode] = true;
+        }
+        var parts = languageCode.split('-');
+        if (!(parts[0] in seen)) {
+          expandedLanguageCodes.push(parts[0]);
+          seen[parts[0]] = true;
+        }
+      }
+      return expandedLanguageCodes;
+    },
+
+    /**
+     * Filters bad language codes in case bad language codes are
+     * stored in the preference. Removes duplicates as well.
+     * @param {Array} languageCodes List of language codes.
+     * @private
+     */
+    filterBadLanguageCodes_: function(languageCodes) {
+      var filteredLanguageCodes = [];
+      var seen = {};
+      for (var i = 0; i < languageCodes.length; i++) {
+        // Check if the the language code is valid, and not
+        // duplicate. Otherwise, skip it.
+        if (LanguageList.isValidLanguageCode(languageCodes[i]) &&
+            !(languageCodes[i] in seen)) {
+          filteredLanguageCodes.push(languageCodes[i]);
+          seen[languageCodes[i]] = true;
+        }
+      }
+      return filteredLanguageCodes;
+    },
+  };
+
+  return {
+    LanguageList: LanguageList
+  };
+});
diff --git a/chrome/browser/resources/options/language_options.css b/chrome/browser/resources/options/language_options.css
new file mode 100644
index 0000000..f79fc5d
--- /dev/null
+++ b/chrome/browser/resources/options/language_options.css
@@ -0,0 +1,174 @@
+.language-options {
+  display: -webkit-box;
+  margin: 10px 0;
+}
+
+.language-options button {
+  min-width: 70px;
+}
+
+.language-options h3 {
+  -webkit-margin-start: 12px;
+  font-size: 100%;
+  font-weight: bold;
+  margin-top: 12px;
+}
+
+.language-options label {
+  display: block;
+}
+
+.language-options-contents  {
+  -webkit-padding-start: 12px;
+  -webkit-padding-end: 12px;
+  padding-bottom: 10px;
+}
+
+.language-options-header, .language-options-footer {
+  margin: 10px 0;
+}
+
+.language-options-left, .language-options-right {
+  border: 1px solid #cccccc;
+  vertical-align: top;
+  padding: 0;
+  height: 400px;
+}
+
+.language-options-left {
+  -webkit-box-orient: vertical;
+  display: -webkit-box;
+  background-color: #ebeff9;
+  min-width: 200px;
+}
+
+.language-options-lower-left {
+  -webkit-box-flex: 0;
+  -webkit-padding-start: 12px;
+  padding-bottom: 10px;
+}
+
+.language-options-right {
+  /* To share the center line with the left pane. */
+  -webkit-margin-start: -1px;
+  width: 360px;
+}
+
+.language-options-notification {
+  display: none;
+  background-color: #fff29e;
+  border-top: 1px solid #ccc;
+  border-bottom: 1px solid #ccc;
+  padding: 12px 30px 12px 12px;
+}
+
+#language-options-input-method-list button {
+  display: block;
+  -webkit-margin-start: 20px;
+}
+
+#language-options-input-method-list label {
+  margin: 4px 0;
+}
+
+#language-options-list {
+  -webkit-box-flex: 1;
+  padding: 1px 0 0;
+  width: 100%;
+}
+
+#language-options-list li {
+  -webkit-padding-start: 12px;
+  padding-top: 2px;
+  padding-bottom: 2px;
+}
+
+#language-options-ui-restart-button {
+  margin-top: 12px;
+}
+
+html[os=chromeos] #add-language-overlay-language-list {
+  -webkit-column-count: 2;
+  -webkit-column-gap: 20px;
+}
+
+html[os=chromeos] #add-language-overlay-cancel-button {
+  /* Place the button in the center. */
+  display: block;
+  margin: auto;
+  margin-top: 15px;
+}
+
+html[os=chromeos] #add-language-overlay-page {
+  width: 800px;
+  padding: 20px;
+}
+
+html[os=chromeos] #add-language-overlay-page button.link-button {
+  padding: 0;
+  text-align: left;
+}
+
+html[os=chromeos] #add-language-overlay-page ul {
+  padding: 0;
+  margin: 0;
+}
+
+/* TODO(kochi): This is temporary copy from new_new_tab.css */
+/* Notification */
+
+#notification {
+  position: relative;
+  background-color: hsl(52, 100%, 80%);
+  border: 1px solid rgb(211, 211, 211);
+  border-radius: 6px;
+  padding: 7px 15px;
+  white-space: nowrap;
+  display: table;
+  /* Set the height and margin so that the element does not use any vertical
+    space */
+  height: 16px;
+  margin: -44px auto 12px auto;
+  font-weight: bold;
+  opacity: 0;
+  pointer-events: none;
+  -webkit-transition: opacity .15s;
+  z-index: 1;
+  color: black;
+}
+
+#notification > * {
+  display: table-cell;
+  max-width: 500px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+#notification.show {
+  opacity: 1;
+  pointer-events: all;
+  -webkit-transition: opacity 1s;
+}
+
+#notification .link {
+  cursor: pointer;
+  text-decoration: underline;
+  -webkit-appearance: none;
+  border: 0;
+  background: none;
+  color: rgba(0, 102, 204, 0.3);
+  -webkit-padding-start: 20px;
+}
+
+#notification .link-color {
+  color: rgb(0, 102, 204);
+}
+
+#chewing-max-chi-symbol-len {
+  width: 100px;
+  height: 30%;
+}
+
+#add-language-overlay-page .content-area {
+  padding-bottom: 10px;
+}
diff --git a/chrome/browser/resources/options/language_options.html b/chrome/browser/resources/options/language_options.html
new file mode 100644
index 0000000..bd561b5
--- /dev/null
+++ b/chrome/browser/resources/options/language_options.html
@@ -0,0 +1,71 @@
+<div class="page hidden" id="languagePage">
+  <h1 i18n-content="languagePage"></h1>
+  <div id="notification">
+    <span>&nbsp;</span>
+    <span class="link"><span class="link-color"></span></span>
+  </div>
+  <div class="language-options-header">
+    <div i18n-content="add_language_instructions"></div>
+<if expr="pp_ifdef('chromeos')">
+    <div i18n-content="input_method_instructions"></div>
+</if>
+  </div>
+  <div class="language-options">
+    <div class="language-options-left">
+      <h3 i18n-content="languages"></h3>
+      <list id="language-options-list"></list>
+      <div class="language-options-lower-left">
+        <button id="language-options-add-button"
+                i18n-content="add_button"></button>
+        <button id="language-options-remove-button"
+                i18n-content="remove_button"></button>
+      </div>
+    </div>
+    <div class="language-options-right">
+      <h3 id="language-options-language-name"></h3>
+<if expr="os == 'win32' or pp_ifdef('chromeos')">
+      <div class="language-options-contents">
+        <button id="language-options-ui-language-button"></button>
+      </div>
+</if>
+      <div class="language-options-contents">
+        <button id="language-options-spell-check-language-button"></button>
+      </div>
+      <div id="language-options-ui-notification-bar"
+           class="language-options-notification">
+        <div i18n-content="restart_required"></div>
+        <button id="language-options-ui-restart-button"
+                i18n-content="restart_button"></button>
+      </div>
+<if expr="pp_ifdef('chromeos')">
+      <h3 i18n-content="input_method"></h3>
+      <div id="language-options-input-method-list"
+           class="language-options-contents">
+      </div>
+</if>
+    </div>
+  </div>
+  <div class="language-options-footer">
+<if expr="pp_ifdef('chromeos')">
+    <div i18n-content="switch_input_methods_hint"></div>
+    <div i18n-content="select_previous_input_method_hint"></div>
+</if>
+<if expr="not pp_ifdef('chromeos')">
+    <div id="spell-check-option">
+      <label class="checkbox">
+        <input id="enable-spell-check" pref="browser.enable_spellchecking"
+            metric="Options_SpellCheck" type="checkbox">
+        <span i18n-content="enable_spell_check"></span>
+      </label>
+    </div>
+    <div id="auto-spell-correction-option" class="hidden">
+      <label class="checkbox">
+        <input id="enable-auto-spell-correction"
+            pref="browser.enable_autospellcorrect"
+            metric="Options_AutoSpellCorrection" type="checkbox">
+        <span i18n-content="enable_auto_spell_correction"></span>
+      </label>
+    </div>
+</if>
+  </div>
+</div>
diff --git a/chrome/browser/resources/options/language_options.js b/chrome/browser/resources/options/language_options.js
new file mode 100644
index 0000000..eae331a
--- /dev/null
+++ b/chrome/browser/resources/options/language_options.js
@@ -0,0 +1,791 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(kochi): Generalize the notification as a component and put it
+// in js/cr/ui/notification.js .
+
+cr.define('options', function() {
+  const OptionsPage = options.OptionsPage;
+  const LanguageList = options.LanguageList;
+
+  // Some input methods like Chinese Pinyin have config pages.
+  // This is the map of the input method names to their config page names.
+  const INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME = {
+    'chewing': 'languageChewing',
+    'hangul': 'languageHangul',
+    'mozc': 'languageMozc',
+    'mozc-dv': 'languageMozc',
+    'mozc-jp': 'languageMozc',
+    'pinyin': 'languagePinyin',
+  };
+
+  /////////////////////////////////////////////////////////////////////////////
+  // LanguageOptions class:
+
+  /**
+   * Encapsulated handling of ChromeOS language options page.
+   * @constructor
+   */
+  function LanguageOptions(model) {
+    OptionsPage.call(this, 'language', templateData.languagePageTabTitle,
+                     'languagePage');
+  }
+
+  cr.addSingletonGetter(LanguageOptions);
+
+  // Inherit LanguageOptions from OptionsPage.
+  LanguageOptions.prototype = {
+    __proto__: OptionsPage.prototype,
+
+    /**
+     * Initializes LanguageOptions page.
+     * Calls base class implementation to starts preference initialization.
+     */
+    initializePage: function() {
+      OptionsPage.prototype.initializePage.call(this);
+
+      var languageOptionsList = $('language-options-list');
+      LanguageList.decorate(languageOptionsList);
+
+      languageOptionsList.addEventListener('change',
+          this.handleLanguageOptionsListChange_.bind(this));
+      languageOptionsList.addEventListener('save',
+          this.handleLanguageOptionsListSave_.bind(this));
+
+      this.addEventListener('visibleChange',
+                            this.handleVisibleChange_.bind(this));
+
+      if (cr.isChromeOS) {
+        this.initializeInputMethodList_();
+        this.initializeLanguageCodeToInputMehotdIdsMap_();
+      }
+      Preferences.getInstance().addEventListener(this.spellCheckDictionaryPref,
+          this.handleSpellCheckDictionaryPrefChange_.bind(this));
+
+      // Set up add button.
+      $('language-options-add-button').onclick = function(e) {
+        // Add the language without showing the overlay if it's specified in
+        // the URL hash (ex. lang_add=ja).  Used for automated testing.
+        var match = document.location.hash.match(/\blang_add=([\w-]+)/);
+        if (match) {
+          var addLanguageCode = match[1];
+          $('language-options-list').addLanguage(addLanguageCode);
+        } else {
+          OptionsPage.navigateToPage('addLanguageOverlay');
+        }
+      };
+      // Set up remove button.
+      $('language-options-remove-button').addEventListener('click',
+          this.handleRemoveButtonClick_.bind(this));
+
+      if (cr.isChromeOS) {
+        // Listen to user clicks on the add language list.
+        var addLanguageList = $('add-language-overlay-language-list');
+        addLanguageList.addEventListener('click',
+            this.handleAddLanguageListClick_.bind(this));
+      } else {
+        // Listen to add language dialog ok button.
+        var addLanguageOkButton = $('add-language-overlay-ok-button');
+        addLanguageOkButton.addEventListener('click',
+            this.handleAddLanguageOkButtonClick_.bind(this));
+
+        // Show experimental features if enabled.
+        if (templateData.experimentalSpellCheckFeatures == 'true') {
+          $('auto-spell-correction-option').classList.remove('hidden');
+        }
+      }
+    },
+
+    // The preference is a CSV string that describes preload engines
+    // (i.e. active input methods).
+    preloadEnginesPref: 'settings.language.preload_engines',
+    // The list of preload engines, like ['mozc', 'pinyin'].
+    preloadEngines_: [],
+    // The preference is a string that describes the spell check
+    // dictionary language, like "en-US".
+    spellCheckDictionaryPref: 'spellcheck.dictionary',
+    spellCheckDictionary_: "",
+    // The map of language code to input method IDs, like:
+    // {'ja': ['mozc', 'mozc-jp'], 'zh-CN': ['pinyin'], ...}
+    languageCodeToInputMethodIdsMap_: {},
+
+    /**
+     * Initializes the input method list.
+     */
+    initializeInputMethodList_: function() {
+      var inputMethodList = $('language-options-input-method-list');
+      var inputMethodListData = templateData.inputMethodList;
+
+      // Add all input methods, but make all of them invisible here. We'll
+      // change the visibility in handleLanguageOptionsListChange_() based
+      // on the selected language. Note that we only have less than 100
+      // input methods, so creating DOM nodes at once here should be ok.
+      for (var i = 0; i < inputMethodListData.length; i++) {
+        var inputMethod = inputMethodListData[i];
+        var input = document.createElement('input');
+        input.type = 'checkbox';
+        input.inputMethodId = inputMethod.id;
+        // Listen to user clicks.
+        input.addEventListener('click',
+                               this.handleCheckboxClick_.bind(this));
+        var label = document.createElement('label');
+        label.appendChild(input);
+        // Adding a space between the checkbox and the text. This is a bit
+        // dirty, but we rely on a space character for all other checkboxes.
+        label.appendChild(document.createTextNode(
+            ' ' + inputMethod.displayName));
+        label.style.display = 'none';
+        label.languageCodeSet = inputMethod.languageCodeSet;
+        // Add the configure button if the config page is present for this
+        // input method.
+        if (inputMethod.id in INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME) {
+          var pageName = INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME[inputMethod.id];
+          var button = this.createConfigureInputMethodButton_(inputMethod.id,
+                                                              pageName);
+          label.appendChild(button);
+        }
+
+        inputMethodList.appendChild(label);
+      }
+      // Listen to pref change once the input method list is initialized.
+      Preferences.getInstance().addEventListener(this.preloadEnginesPref,
+          this.handlePreloadEnginesPrefChange_.bind(this));
+    },
+
+    /**
+     * Creates a configure button for the given input method ID.
+     * @param {string} inputMethodId Input method ID (ex. "pinyin").
+     * @param {string} pageName Name of the config page (ex. "languagePinyin").
+     * @private
+     */
+    createConfigureInputMethodButton_: function(inputMethodId, pageName) {
+      var button = document.createElement('button');
+      button.textContent = localStrings.getString('configure');
+      button.onclick = function(e) {
+        // Prevent the default action (i.e. changing the checked property
+        // of the checkbox). The button click here should not be handled
+        // as checkbox click.
+        e.preventDefault();
+        chrome.send('inputMethodOptionsOpen', [inputMethodId]);
+        OptionsPage.navigateToPage(pageName);
+      }
+      return button;
+    },
+
+    /**
+     * Handles OptionsPage's visible property change event.
+     * @param {Event} e Property change event.
+     * @private
+     */
+    handleVisibleChange_: function(e) {
+      if (this.visible) {
+        $('language-options-list').redraw();
+        chrome.send('languageOptionsOpen');
+      }
+    },
+
+    /**
+     * Handles languageOptionsList's change event.
+     * @param {Event} e Change event.
+     * @private
+     */
+    handleLanguageOptionsListChange_: function(e) {
+      var languageOptionsList = $('language-options-list');
+      var languageCode = languageOptionsList.getSelectedLanguageCode();
+      // Select the language if it's specified in the URL hash (ex. lang=ja).
+      // Used for automated testing.
+      var match = document.location.hash.match(/\blang=([\w-]+)/);
+      if (match) {
+        var specifiedLanguageCode = match[1];
+        if (languageOptionsList.selectLanguageByCode(specifiedLanguageCode)) {
+          languageCode = specifiedLanguageCode;
+        }
+      }
+      this.updateSelectedLanguageName_(languageCode);
+      if (cr.isWindows || cr.isChromeOS)
+        this.updateUiLanguageButton_(languageCode);
+      this.updateSpellCheckLanguageButton_(languageCode);
+      if (cr.isChromeOS)
+        this.updateInputMethodList_(languageCode);
+      this.updateLanguageListInAddLanguageOverlay_();
+    },
+
+    /**
+     * Handles languageOptionsList's save event.
+     * @param {Event} e Save event.
+     * @private
+     */
+    handleLanguageOptionsListSave_: function(e) {
+      if (cr.isChromeOS) {
+        // Sort the preload engines per the saved languages before save.
+        this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
+        this.savePreloadEnginesPref_();
+      }
+    },
+
+    /**
+     * Sorts preloadEngines_ by languageOptionsList's order.
+     * @param {Array} preloadEngines List of preload engines.
+     * @return {Array} Returns sorted preloadEngines.
+     * @private
+     */
+    sortPreloadEngines_: function(preloadEngines) {
+      // For instance, suppose we have two languages and associated input
+      // methods:
+      //
+      // - Korean: hangul
+      // - Chinese: pinyin
+      //
+      // The preloadEngines preference should look like "hangul,pinyin".
+      // If the user reverse the order, the preference should be reorderd
+      // to "pinyin,hangul".
+      var languageOptionsList = $('language-options-list');
+      var languageCodes = languageOptionsList.getLanguageCodes();
+
+      // Convert the list into a dictonary for simpler lookup.
+      var preloadEngineSet = {};
+      for (var i = 0; i < preloadEngines.length; i++) {
+        preloadEngineSet[preloadEngines[i]] = true;
+      }
+
+      // Create the new preload engine list per the language codes.
+      var newPreloadEngines = [];
+      for (var i = 0; i < languageCodes.length; i++) {
+        var languageCode = languageCodes[i];
+        var inputMethodIds = this.languageCodeToInputMethodIdsMap_[
+            languageCode];
+        // Check if we have active input methods associated with the language.
+        for (var j = 0; j < inputMethodIds.length; j++) {
+          var inputMethodId = inputMethodIds[j];
+          if (inputMethodId in preloadEngineSet) {
+            // If we have, add it to the new engine list.
+            newPreloadEngines.push(inputMethodId);
+            // And delete it from the set. This is necessary as one input
+            // method can be associated with more than one language thus
+            // we should avoid having duplicates in the new list.
+            delete preloadEngineSet[inputMethodId];
+          }
+        }
+      }
+
+      return newPreloadEngines;
+    },
+
+    /**
+     * Initializes the map of language code to input method IDs.
+     * @private
+     */
+    initializeLanguageCodeToInputMehotdIdsMap_: function() {
+      var inputMethodList = templateData.inputMethodList;
+      for (var i = 0; i < inputMethodList.length; i++) {
+        var inputMethod = inputMethodList[i];
+        for (var languageCode in inputMethod.languageCodeSet) {
+          if (languageCode in this.languageCodeToInputMethodIdsMap_) {
+            this.languageCodeToInputMethodIdsMap_[languageCode].push(
+                inputMethod.id);
+          } else {
+            this.languageCodeToInputMethodIdsMap_[languageCode] =
+                [inputMethod.id];
+          }
+        }
+      }
+    },
+
+    /**
+     * Updates the currently selected language name.
+     * @param {string} languageCode Language code (ex. "fr").
+     * @private
+     */
+    updateSelectedLanguageName_: function(languageCode) {
+      var languageDisplayName = LanguageList.getDisplayNameFromLanguageCode(
+          languageCode);
+      var languageNativeDisplayName =
+          LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
+      // If the native name is different, add it.
+      if (languageDisplayName != languageNativeDisplayName) {
+        languageDisplayName += ' - ' + languageNativeDisplayName;
+      }
+      // Update the currently selected language name.
+      $('language-options-language-name').textContent = languageDisplayName;
+    },
+
+    /**
+     * Updates the UI language button.
+     * @param {string} languageCode Language code (ex. "fr").
+     * @private
+     */
+    updateUiLanguageButton_: function(languageCode) {
+      var uiLanguageButton = $('language-options-ui-language-button');
+      // Check if the language code matches the current UI language.
+      if (languageCode == templateData.currentUiLanguageCode) {
+        // If it matches, the button just says that the UI language is
+        // currently in use.
+        uiLanguageButton.textContent =
+            localStrings.getString('is_displayed_in_this_language');
+        // Make it look like a text label.
+        uiLanguageButton.className = 'text-button';
+        // Remove the event listner.
+        uiLanguageButton.onclick = undefined;
+      } else if (languageCode in templateData.uiLanguageCodeSet) {
+        // If the language is supported as UI language, users can click on
+        // the button to change the UI language.
+        uiLanguageButton.textContent =
+            localStrings.getString('display_in_this_language');
+        uiLanguageButton.className = '';
+        // Send the change request to Chrome.
+        uiLanguageButton.onclick = function(e) {
+          chrome.send('uiLanguageChange', [languageCode]);
+        }
+        $('language-options-ui-restart-button').onclick = function(e) {
+          chrome.send('uiLanguageRestart');
+        }
+      } else {
+        // If the language is not supported as UI language, the button
+        // just says that Chromium OS cannot be displayed in this language.
+        uiLanguageButton.textContent =
+            localStrings.getString('cannot_be_displayed_in_this_language');
+        uiLanguageButton.className = 'text-button';
+        uiLanguageButton.onclick = undefined;
+      }
+      uiLanguageButton.style.display = 'block';
+      $('language-options-ui-notification-bar').style.display = 'none';
+    },
+
+    /**
+     * Updates the spell check language button.
+     * @param {string} languageCode Language code (ex. "fr").
+     * @private
+     */
+    updateSpellCheckLanguageButton_: function(languageCode) {
+      var spellCheckLanguageButton = $(
+          'language-options-spell-check-language-button');
+      // Check if the language code matches the current spell check language.
+      if (languageCode == this.spellCheckDictionary_) {
+        // If it matches, the button just says that the spell check language is
+        // currently in use.
+        spellCheckLanguageButton.textContent =
+            localStrings.getString('is_used_for_spell_checking');
+        // Make it look like a text label.
+        spellCheckLanguageButton.className = 'text-button';
+        // Remove the event listner.
+        spellCheckLanguageButton.onclick = undefined;
+      } else if (languageCode in templateData.spellCheckLanguageCodeSet) {
+        // If the language is supported as spell check language, users can
+        // click on the button to change the spell check language.
+        spellCheckLanguageButton.textContent =
+            localStrings.getString('use_this_for_spell_checking');
+        spellCheckLanguageButton.className = '';
+        spellCheckLanguageButton.languageCode = languageCode;
+        // Add an event listner to the click event.
+        spellCheckLanguageButton.addEventListener('click',
+            this.handleSpellCheckLanguageButtonClick_.bind(this));
+      } else {
+        // If the language is not supported as spell check language, the
+        // button just says that this language cannot be used for spell
+        // checking.
+        spellCheckLanguageButton.textContent =
+            localStrings.getString('cannot_be_used_for_spell_checking');
+        spellCheckLanguageButton.className = 'text-button';
+        spellCheckLanguageButton.onclick = undefined;
+      }
+      spellCheckLanguageButton.style.display = 'block';
+      $('language-options-ui-notification-bar').style.display = 'none';
+    },
+
+    /**
+     * Updates the input method list.
+     * @param {string} languageCode Language code (ex. "fr").
+     * @private
+     */
+    updateInputMethodList_: function(languageCode) {
+      // Give one of the checkboxes or buttons focus, if it's specified in the
+      // URL hash (ex. focus=mozc). Used for automated testing.
+      var focusInputMethodId = -1;
+      var match = document.location.hash.match(/\bfocus=([\w:-]+)\b/);
+      if (match) {
+        focusInputMethodId = match[1];
+      }
+      // Change the visibility of the input method list. Input methods that
+      // matches |languageCode| will become visible.
+      var inputMethodList = $('language-options-input-method-list');
+      var labels = inputMethodList.querySelectorAll('label');
+      for (var i = 0; i < labels.length; i++) {
+        var label = labels[i];
+        if (languageCode in label.languageCodeSet) {
+          label.style.display = 'block';
+          var input = label.childNodes[0];
+          // Give it focus if the ID matches.
+          if (input.inputMethodId == focusInputMethodId) {
+            input.focus();
+          }
+        } else {
+          label.style.display = 'none';
+        }
+      }
+      if (focusInputMethodId == 'remove') {
+        $('language-options-remove-button').focus();
+      } else if (focusInputMethodId == 'add') {
+        $('language-options-add-button').focus();
+      }
+    },
+
+    /**
+     * Updates the language list in the add language overlay.
+     * @param {string} languageCode Language code (ex. "fr").
+     * @private
+     */
+    updateLanguageListInAddLanguageOverlay_: function(languageCode) {
+      // Change the visibility of the language list in the add language
+      // overlay. Languages that are already active will become invisible,
+      // so that users don't add the same language twice.
+      var languageOptionsList = $('language-options-list');
+      var languageCodes = languageOptionsList.getLanguageCodes();
+      var languageCodeSet = {};
+      for (var i = 0; i < languageCodes.length; i++) {
+        languageCodeSet[languageCodes[i]] = true;
+      }
+      var addLanguageList = $('add-language-overlay-language-list');
+      var lis = addLanguageList.querySelectorAll('li');
+      for (var i = 0; i < lis.length; i++) {
+        // The first child button knows the language code.
+        var button = lis[i].childNodes[0];
+        if (button.languageCode in languageCodeSet) {
+          lis[i].style.display = 'none';
+        } else {
+          lis[i].style.display = 'block';
+        }
+      }
+    },
+
+    /**
+     * Handles preloadEnginesPref change.
+     * @param {Event} e Change event.
+     * @private
+     */
+    handlePreloadEnginesPrefChange_: function(e) {
+      var value = e.value.value;
+      this.preloadEngines_ = this.filterBadPreloadEngines_(value.split(','));
+      this.updateCheckboxesFromPreloadEngines_();
+    },
+
+    /**
+     * Handles input method checkbox's click event.
+     * @param {Event} e Click event.
+     * @private
+     */
+    handleCheckboxClick_ : function(e) {
+      var checkbox = e.target;
+      if (this.preloadEngines_.length == 1 && !checkbox.checked) {
+        // Don't allow disabling the last input method.
+        this.showNotification_(
+            localStrings.getString('please_add_another_input_method'),
+            localStrings.getString('ok_button'));
+        checkbox.checked = true;
+        return;
+      }
+      if (checkbox.checked) {
+        chrome.send('inputMethodEnable', [checkbox.inputMethodId]);
+      } else {
+        chrome.send('inputMethodDisable', [checkbox.inputMethodId]);
+      }
+      this.updatePreloadEnginesFromCheckboxes_();
+      this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
+      this.savePreloadEnginesPref_();
+    },
+
+    /**
+     * Handles add language list's click event.
+     * @param {Event} e Click event.
+     */
+    handleAddLanguageListClick_ : function(e) {
+      var languageOptionsList = $('language-options-list');
+      var languageCode = e.target.languageCode;
+      // languageCode can be undefined, if click was made on some random
+      // place in the overlay, rather than a button. Ignore it.
+      if (!languageCode) {
+        return;
+      }
+      languageOptionsList.addLanguage(languageCode);
+      var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
+      // Enable the first input method for the language added.
+      if (inputMethodIds && inputMethodIds[0] &&
+          // Don't add the input method it's already present. This can
+          // happen if the same input method is shared among multiple
+          // languages (ex. English US keyboard is used for English US and
+          // Filipino).
+          this.preloadEngines_.indexOf(inputMethodIds[0]) == -1) {
+        this.preloadEngines_.push(inputMethodIds[0]);
+        this.updateCheckboxesFromPreloadEngines_();
+        this.savePreloadEnginesPref_();
+      }
+      OptionsPage.closeOverlay();
+    },
+
+    /**
+     * Handles add language dialog ok button.
+     */
+    handleAddLanguageOkButtonClick_ : function() {
+      var languagesSelect = $('add-language-overlay-language-list');
+      var selectedIndex = languagesSelect.selectedIndex;
+      if (selectedIndex >= 0) {
+        var selection = languagesSelect.options[selectedIndex];
+        $('language-options-list').addLanguage(String(selection.value));
+        OptionsPage.closeOverlay();
+      }
+    },
+
+    /**
+     * Handles remove button's click event.
+     * @param {Event} e Click event.
+     */
+    handleRemoveButtonClick_: function(e) {
+      var languageOptionsList = $('language-options-list');
+      var languageCode = languageOptionsList.getSelectedLanguageCode();
+      // Don't allow removing the language if it's as UI language.
+      if (languageCode == templateData.currentUiLanguageCode) {
+        this.showNotification_(
+            localStrings.getString('this_language_is_currently_in_use'),
+            localStrings.getString('ok_button'));
+        return;
+      }
+      if (cr.isChromeOS) {
+        // Disable input methods associated with |languageCode|.
+        // Don't allow removing the language if cerntain conditions are met.
+        // See removePreloadEnginesByLanguageCode_() for details.
+        if (!this.removePreloadEnginesByLanguageCode_(languageCode)) {
+          this.showNotification_(
+              localStrings.getString('please_add_another_language'),
+              localStrings.getString('ok_button'));
+          return;
+        }
+      }
+      languageOptionsList.removeSelectedLanguage();
+    },
+
+    /**
+     * Handles spellCheckDictionaryPref change.
+     * @param {Event} e Change event.
+     * @private
+     */
+    handleSpellCheckDictionaryPrefChange_: function(e) {
+      var languageCode = e.value.value
+      this.spellCheckDictionary_ = languageCode;
+      var languageOptionsList = $('language-options-list');
+      var selectedLanguageCode = languageOptionsList.getSelectedLanguageCode();
+      this.updateSpellCheckLanguageButton_(selectedLanguageCode);
+    },
+
+    /**
+     * Handles spellCheckLanguageButton click.
+     * @param {Event} e Click event.
+     * @private
+     */
+    handleSpellCheckLanguageButtonClick_: function(e) {
+      var languageCode = e.target.languageCode;
+      // Save the preference.
+      Preferences.setStringPref(this.spellCheckDictionaryPref,
+                                languageCode);
+      chrome.send('spellCheckLanguageChange', [languageCode]);
+    },
+
+    /**
+     * Removes preload engines associated with the given language code.
+     * However, this function does not remove engines (input methods) that
+     * are used for other active languages. For instance, if "xkb:us::eng"
+     * is used for English and Filipino, and the two languages are active,
+     * this function does not remove "xkb:us::eng" when either of these
+     * languages is removed. Instead, it'll remove "xkb:us::eng" when the
+     * both languages are gone.
+     *
+     * @param {string} languageCode Language code (ex. "fr").
+     * @return {boolean} Returns true on success.
+     * @private
+     */
+    removePreloadEnginesByLanguageCode_: function(languageCode) {
+      // First create the set of engines to be removed from input methods
+      // associated with the language code.
+      var enginesToBeRemovedSet = {};
+      var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
+      for (var i = 0; i < inputMethodIds.length; i++) {
+        enginesToBeRemovedSet[inputMethodIds[i]] = true;
+      }
+
+      // Then eliminate engines that are also used for other active languages.
+      var languageCodes = $('language-options-list').getLanguageCodes();
+      for (var i = 0; i < languageCodes.length; i++) {
+        // Skip the target language code.
+        if (languageCodes[i] == languageCode) {
+          continue;
+        }
+        // Check if input methods used in this language are included in
+        // enginesToBeRemovedSet. If so, eliminate these from the set, so
+        // we don't remove this time.
+        var inputMethodIdsForAnotherLanguage =
+            this.languageCodeToInputMethodIdsMap_[languageCodes[i]];
+        for (var j = 0; j < inputMethodIdsForAnotherLanguage.length; j++) {
+          var inputMethodId = inputMethodIdsForAnotherLanguage[j];
+          if (inputMethodId in enginesToBeRemovedSet) {
+            delete enginesToBeRemovedSet[inputMethodId];
+          }
+        }
+      }
+
+      // Update the preload engine list with the to-be-removed set.
+      var newPreloadEngines = [];
+      for (var i = 0; i < this.preloadEngines_.length; i++) {
+        if (!(this.preloadEngines_[i] in enginesToBeRemovedSet)) {
+          newPreloadEngines.push(this.preloadEngines_[i]);
+        }
+      }
+      // Don't allow this operation if it causes the number of preload
+      // engines to be zero.
+      if (newPreloadEngines.length == 0) {
+        return false;
+      }
+      this.preloadEngines_ = newPreloadEngines;
+      this.savePreloadEnginesPref_();
+      return true;
+    },
+
+    /**
+     * Saves the preload engines preference.
+     * @private
+     */
+    savePreloadEnginesPref_: function() {
+      Preferences.setStringPref(this.preloadEnginesPref,
+                                this.preloadEngines_.join(','));
+    },
+
+    /**
+     * Updates the checkboxes in the input method list from the preload
+     * engines preference.
+     * @private
+     */
+    updateCheckboxesFromPreloadEngines_: function() {
+      // Convert the list into a dictonary for simpler lookup.
+      var dictionary = {};
+      for (var i = 0; i < this.preloadEngines_.length; i++) {
+        dictionary[this.preloadEngines_[i]] = true;
+      }
+
+      var inputMethodList = $('language-options-input-method-list');
+      var checkboxes = inputMethodList.querySelectorAll('input');
+      for (var i = 0; i < checkboxes.length; i++) {
+        checkboxes[i].checked = (checkboxes[i].inputMethodId in dictionary);
+      }
+    },
+
+    /**
+     * Updates the preload engines preference from the checkboxes in the
+     * input method list.
+     * @private
+     */
+    updatePreloadEnginesFromCheckboxes_: function() {
+      this.preloadEngines_ = [];
+      var inputMethodList = $('language-options-input-method-list');
+      var checkboxes = inputMethodList.querySelectorAll('input');
+      for (var i = 0; i < checkboxes.length; i++) {
+        if (checkboxes[i].checked) {
+          this.preloadEngines_.push(checkboxes[i].inputMethodId);
+        }
+      }
+    },
+
+    /**
+     * Filters bad preload engines in case bad preload engines are
+     * stored in the preference. Removes duplicates as well.
+     * @param {Array} preloadEngines List of preload engines.
+     * @private
+     */
+    filterBadPreloadEngines_: function(preloadEngines) {
+      // Convert the list into a dictonary for simpler lookup.
+      var dictionary = {};
+      for (var i = 0; i < templateData.inputMethodList.length; i++) {
+        dictionary[templateData.inputMethodList[i].id] = true;
+      }
+
+      var filteredPreloadEngines = [];
+      var seen = {};
+      for (var i = 0; i < preloadEngines.length; i++) {
+        // Check if the preload engine is present in the
+        // dictionary, and not duplicate. Otherwise, skip it.
+        if (preloadEngines[i] in dictionary && !(preloadEngines[i] in seen)) {
+          filteredPreloadEngines.push(preloadEngines[i]);
+          seen[preloadEngines[i]] = true;
+        }
+      }
+      return filteredPreloadEngines;
+    },
+
+    // TODO(kochi): This is an adapted copy from new_new_tab.js.
+    // If this will go as final UI, refactor this to share the component with
+    // new new tab page.
+    /**
+     * Shows notification
+     * @private
+     */
+    notificationTimeout_: null,
+    showNotification_ : function(text, actionText, opt_delay) {
+      var notificationElement = $('notification');
+      var actionLink = notificationElement.querySelector('.link-color');
+      var delay = opt_delay || 10000;
+
+      function show() {
+        window.clearTimeout(this.notificationTimeout_);
+        notificationElement.classList.add('show');
+        document.body.classList.add('notification-shown');
+      }
+
+      function hide() {
+        window.clearTimeout(this.notificationTimeout_);
+        notificationElement.classList.remove('show');
+        document.body.classList.remove('notification-shown');
+        // Prevent tabbing to the hidden link.
+        actionLink.tabIndex = -1;
+        // Setting tabIndex to -1 only prevents future tabbing to it. If,
+        // however, the user switches window or a tab and then moves back to
+        // this tab the element may gain focus. We therefore make sure that we
+        // blur the element so that the element focus is not restored when
+        // coming back to this window.
+        actionLink.blur();
+      }
+
+      function delayedHide() {
+        this.notificationTimeout_ = window.setTimeout(hide, delay);
+      }
+
+      notificationElement.firstElementChild.textContent = text;
+      actionLink.textContent = actionText;
+
+      actionLink.onclick = hide;
+      actionLink.onkeydown = function(e) {
+        if (e.keyIdentifier == 'Enter') {
+          hide();
+        }
+      };
+      notificationElement.onmouseover = show;
+      notificationElement.onmouseout = delayedHide;
+      actionLink.onfocus = show;
+      actionLink.onblur = delayedHide;
+      // Enable tabbing to the link now that it is shown.
+      actionLink.tabIndex = 0;
+
+      show();
+      delayedHide();
+    }
+  };
+
+  /**
+   * Chrome callback for when the UI language preference is saved.
+   */
+  LanguageOptions.uiLanguageSaved = function() {
+    $('language-options-ui-language-button').style.display = 'none';
+    $('language-options-ui-notification-bar').style.display = 'block';
+  };
+
+  // Export
+  return {
+    LanguageOptions: LanguageOptions
+  };
+});
diff --git a/chrome/browser/resources/options/list_inline_header_selection_controller.js b/chrome/browser/resources/options/list_inline_header_selection_controller.js
deleted file mode 100644
index 2ec57ff..0000000
--- a/chrome/browser/resources/options/list_inline_header_selection_controller.js
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('options', function() {
-  const ListSelectionController = cr.ui.ListSelectionController;
-
-  /**
-   * Creates a selection controller with a delegate that controls whether or
-   * not individual items are selectable. This is used for lists containing
-   * subgroups with headings that are in the list, since the headers themselves
-   * should not be selectable.
-   *
-   * @param {cr.ui.ListSelectionModel} selectionModel The selection model to
-   *     interact with.
-   * @param {*} selectabilityDelegate A delegate responding to
-   *     canSelectIndex(index).
-   *
-   * @constructor
-   * @extends {!cr.ui.ListSelectionController}
-   */
-  function ListInlineHeaderSelectionController(selectionModel,
-                                               selectabilityDelegate) {
-    ListSelectionController.call(this, selectionModel);
-    this.selectabilityDelegate_ = selectabilityDelegate;
-  }
-
-  ListInlineHeaderSelectionController.prototype = {
-    __proto__: ListSelectionController.prototype,
-
-    /** @inheritDoc */
-    getIndexBelow: function(index) {
-      var next = ListSelectionController.prototype.getIndexBelow.call(this,
-                                                                      index);
-      if (next == -1 || this.canSelect(next))
-        return next;
-      return this.getIndexBelow(next);
-    },
-
-    /** @inheritDoc */
-    getNextIndex: function(index) {
-      return this.getIndexBelow(index);
-    },
-
-    /** @inheritDoc */
-    getIndexAbove: function(index) {
-      var previous = ListSelectionController.prototype.getIndexAbove.call(
-          this, index);
-      if (previous == -1 || this.canSelect(previous))
-        return previous;
-      return this.getIndexAbove(previous);
-    },
-
-    /** @inheritDoc */
-    getPreviousIndex: function(index) {
-      return this.getIndexAbove(index);
-    },
-
-    /** @inheritDoc */
-    getFirstIndex: function(index) {
-      var first = ListSelectionController.prototype.getFirstIndex.call(this);
-      if (this.canSelect(first))
-        return first;
-      return this.getNextIndex(first);
-    },
-
-    /** @inheritDoc */
-    getLastIndex: function(index) {
-      var last = ListSelectionController.prototype.getLastIndex.call(this);
-      if (this.canSelect(last))
-        return last;
-      return this.getPreviousIndex(last);
-    },
-
-    /** @inheritDoc */
-    handleMouseDownUp: function(e, index) {
-      if (this.canSelect(index)) {
-        ListSelectionController.prototype.handleMouseDownUp.call(
-            this, e, index);
-      }
-    },
-
-    /**
-     * Returns true if the given index is selectable.
-     * @private
-     * @param {number} index The index to check.
-     */
-    canSelect: function(index) {
-      return this.selectabilityDelegate_.canSelectIndex(index);
-    }
-  };
-
-  return {
-    ListInlineHeaderSelectionController: ListInlineHeaderSelectionController
-  };
-});
diff --git a/chrome/browser/resources/options/options.html b/chrome/browser/resources/options/options.html
index 30e0cb0..4658de9 100644
--- a/chrome/browser/resources/options/options.html
+++ b/chrome/browser/resources/options/options.html
@@ -5,10 +5,13 @@
     id="t">
 <head>
 <meta charset="utf-8">
-<title i18n-content="title"></title>
+<!-- Set the title to that of the default page so that the title doesn't flash
+     on load (for the most common case). -->
+<title i18n-content="browserPageTabTitle"></title>
 
 <link rel="icon" href="../../../app/theme/settings_favicon.png">
 <link rel="stylesheet" href="chrome://resources/css/list.css">
+<link rel="stylesheet" href="chrome://resources/css/throbber.css">
 <link rel="stylesheet" href="chrome://resources/css/tree.css">
 <link rel="stylesheet" href="../dom_ui.css">
 <link rel="stylesheet" href="options_page.css">
@@ -22,11 +25,11 @@
 <link rel="stylesheet" href="clear_browser_data_overlay.css">
 <link rel="stylesheet" href="content_settings.css">
 <link rel="stylesheet" href="cookies_view.css">
-<link rel="stylesheet" href="edit_search_engine_overlay.css">
-<link rel="stylesheet" href="password_manager.css">
+<link rel="stylesheet" href="font_settings.css">
+<link rel="stylesheet" href="import_data_overlay.css">
+<link rel="stylesheet" href="language_options.css">
 <link rel="stylesheet" href="password_manager_list.css">
 <link rel="stylesheet" href="personal_options.css">
-<link rel="stylesheet" href="import_data_overlay.css">
 <link rel="stylesheet" href="search_engine_manager.css">
 <link rel="stylesheet" href="search_page.css">
 <link rel="stylesheet" href="subpages_tab_controls.css">
@@ -34,8 +37,8 @@
   <link rel="stylesheet" href="about_page.css">
   <link rel="stylesheet" href="chromeos_accounts_options_page.css">
   <link rel="stylesheet" href="chromeos_internet_options_page.css">
-  <link rel="stylesheet" href="chromeos_language_options.css">
   <link rel="stylesheet" href="chromeos_proxy.css">
+  <link rel="stylesheet" href="chromeos_system_options_page.css">
 </if>
 
 <if expr="not pp_ifdef('win32') and not pp_ifdef('darwin')">
@@ -60,16 +63,13 @@
 <script src="preferences.js"></script>
 <script src="pref_ui.js"></script>
 <script src="deletable_item_list.js"></script>
-<script src="list_inline_header_selection_controller.js"></script>
+<script src="inline_editable_list.js"></script>
 <script src="options_page.js"></script>
 <if expr="pp_ifdef('chromeos')">
   <script src="about_page.js"></script>
   <script src="chromeos_cellular_plan_element.js"></script>
   <script src="chromeos_internet_network_element.js"></script>
   <script src="chromeos_internet_options.js"></script>
-  <script src="chromeos_language_add_language_overlay.js"></script>
-  <script src="chromeos_language_list.js"></script>
-  <script src="chromeos_language_options.js"></script>
   <script src="chromeos_system_options.js"></script>
   <script src="chromeos_accounts_options.js"></script>
   <script src="chromeos_proxy_options.js"></script>
@@ -81,7 +81,6 @@
     var AccountsOptions = options.AccountsOptions;
     var InternetOptions = options.InternetOptions;
     var LanguageHangulOptions = options.LanguageHangulOptions;
-    var LanguageOptions = options.LanguageOptions;
     var SystemOptions = options.SystemOptions;
   </script>
 </if>
@@ -116,22 +115,23 @@
 <script src="content_settings_ui.js"></script>
 <script src="cookies_tree.js"></script>
 <script src="cookies_view.js"></script>
-<script src="edit_search_engine_overlay.js"></script>
 <script src="font_settings.js"></script>
 <script src="font_settings_ui.js"></script>
 <script src="import_data_overlay.js"></script>
 <script src="instant_confirm_overlay.js"></script>
+<script src="language_add_language_overlay.js"></script>
+<script src="language_list.js"></script>
+<script src="language_options.js"></script>
 <script src="password_manager.js"></script>
 <script src="password_manager_list.js"></script>
 <script src="personal_options.js"></script>
 <script src="search_engine_manager.js"></script>
 <script src="search_engine_manager_engine_list.js"></script>
 <script src="search_page.js"></script>
-<script src="startup_page_manager.js"></script>
 <script src="options.js"></script>
 
 </head>
-<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+<body i18n-values=".style.fontFamily:fontfamily;">
 <div class="header">
 </div>
 <div id="overlay" class="overlay hidden">
@@ -140,11 +140,10 @@
   <include src="autofill_edit_address_overlay.html">
   <include src="autofill_edit_creditcard_overlay.html">
   <include src="clear_browser_data_overlay.html">
-  <include src="edit_search_engine_overlay.html">
   <include src="import_data_overlay.html">
   <include src="instant_confirm_overlay.html">
+  <include src="language_add_language_overlay.html">
   <if expr="pp_ifdef('chromeos')">
-     <include src="chromeos_language_add_language_overlay.html">
      <include
          src="chromeos_language_customize_modifier_keys_overlay.html">
      <include src="chromeos_internet_detail.html">
@@ -168,6 +167,7 @@
        <span id="managed-prefs-text"
              i18n-content="managedPrefsBannerText"></span>
      </div>
+     <div id="subpage-backdrop" class="hidden"></div>
      <div id="mainview-content">
        <!-- Start main pages -->
        <!-- Please keep the main pages in desired order of display.  This will
@@ -185,14 +185,9 @@
        <div id="subpage-sheet-container-1"
            class="subpage-sheet-container hidden">
          <div id="subpage-sheet-1" class="subpage-sheet">
-           <button class="close-subpage"></button>
+           <button class="raw-button close-subpage"></button>
            <if expr="pp_ifdef('chromeos')">
              <include src="about_page.html">
-             <include src="chromeos_language_options.html">
-             <include src="chromeos_language_chewing_options.html">
-             <include src="chromeos_language_hangul_options.html">
-             <include src="chromeos_language_mozc_options.html">
-             <include src="chromeos_language_pinyin_options.html">
              <include src="chromeos_proxy.html">
            </if>
            <if expr="not pp_ifdef('win32') and not pp_ifdef('darwin')">
@@ -201,15 +196,21 @@
            <include src="autofill_options.html">
            <include src="content_settings.html">
            <include src="font_settings.html">
+           <include src="language_options.html">
            <include src="password_manager.html">
            <include src="search_engine_manager.html">
-           <include src="startup_page_manager.html">
          </div>
        </div>
        <div id="subpage-sheet-container-2"
            class="subpage-sheet-container hidden">
          <div id="subpage-sheet-2" class="subpage-sheet">
-           <button class="close-subpage"></button>
+           <button class="raw-button close-subpage"></button>
+           <if expr="pp_ifdef('chromeos')">
+             <include src="chromeos_language_chewing_options.html">
+             <include src="chromeos_language_hangul_options.html">
+             <include src="chromeos_language_mozc_options.html">
+             <include src="chromeos_language_pinyin_options.html">
+           </if>
            <include src="cookies_view.html">
            <include src="content_settings_exceptions_area.html">
          </div>
diff --git a/chrome/browser/resources/options/options.js b/chrome/browser/resources/options/options.js
index b72f8b5..dc69759 100644
--- a/chrome/browser/resources/options/options.js
+++ b/chrome/browser/resources/options/options.js
@@ -1,7 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+var AddLanguageOverlay = options.AddLanguageOverlay;
 var AddStartupPageOverlay = options.AddStartupPageOverlay;
 var AdvancedOptions = options.AdvancedOptions;
 var AlertOverlay = options.AlertOverlay;
@@ -14,10 +15,10 @@
 var ContentSettingsExceptionsArea =
     options.contentSettings.ContentSettingsExceptionsArea;
 var CookiesView = options.CookiesView;
-var EditSearchEngineOverlay = options.EditSearchEngineOverlay;
 var FontSettings = options.FontSettings;
 var ImportDataOverlay = options.ImportDataOverlay;
 var InstantConfirmOverlay = options.InstantConfirmOverlay;
+var LanguageOptions = options.LanguageOptions;
 var OptionsPage = options.OptionsPage;
 var PasswordManager = options.PasswordManager;
 var PersonalOptions = options.PersonalOptions;
@@ -25,7 +26,6 @@
 var ProxyOptions = options.ProxyOptions;
 var SearchEngineManager = options.SearchEngineManager;
 var SearchPage = options.SearchPage;
-var StartupPageManager = options.StartupPageManager;
 
 /**
  * DOMContentLoaded handler, sets up the page.
@@ -41,8 +41,6 @@
   cr.ui.decorate('input[pref][type=url]', options.PrefTextField);
   cr.ui.decorate('#content-settings-page input[type=radio]',
       options.ContentSettingsRadio);
-  cr.ui.decorate('#fontSettingsMinimumSizeSelector',
-      options.MinimumFontSizeSelect);
 
   var menuOffPattern = /(^\?|&)menu=off($|&)/;
   var menuDisabled = menuOffPattern.test(window.location.search);
@@ -56,9 +54,6 @@
   OptionsPage.registerSubPage(SearchEngineManager.getInstance(),
                               BrowserOptions.getInstance(),
                               [$('defaultSearchManageEnginesButton')]);
-  OptionsPage.registerSubPage(StartupPageManager.getInstance(),
-                              BrowserOptions.getInstance(),
-                              [$('startupPageManagerButton')]);
   OptionsPage.register(PersonalOptions.getInstance());
   OptionsPage.registerSubPage(AutoFillOptions.getInstance(),
                               PersonalOptions.getInstance(),
@@ -75,24 +70,24 @@
                                 [$('language-button')]);
     OptionsPage.registerSubPage(
         new OptionsPage('languageChewing',
-                        localStrings.getString('languageChewingPage'),
+                        templateData.languageChewingPageTabTitle,
                         'languageChewingPage'),
-        SystemOptions.getInstance());
+        LanguageOptions.getInstance());
     OptionsPage.registerSubPage(
         new OptionsPage('languageHangul',
-                        localStrings.getString('languageHangulPage'),
+                        templateData.languageHangulPageTabTitle,
                         'languageHangulPage'),
-        SystemOptions.getInstance());
+        LanguageOptions.getInstance());
     OptionsPage.registerSubPage(
         new OptionsPage('languageMozc',
-                        localStrings.getString('languageMozcPage'),
+                        templateData.languageMozcPageTabTitle,
                         'languageMozcPage'),
-        SystemOptions.getInstance());
+        LanguageOptions.getInstance());
     OptionsPage.registerSubPage(
         new OptionsPage('languagePinyin',
-                        localStrings.getString('languagePinyinPage'),
+                        templateData.languagePinyinPageTabTitle,
                         'languagePinyinPage'),
-        SystemOptions.getInstance());
+        LanguageOptions.getInstance());
     OptionsPage.register(InternetOptions.getInstance());
   }
   OptionsPage.register(AdvancedOptions.getInstance());
@@ -108,24 +103,40 @@
   OptionsPage.registerSubPage(FontSettings.getInstance(),
                               AdvancedOptions.getInstance(),
                               [$('fontSettingsCustomizeFontsButton')]);
+  if (!cr.isChromeOS) {
+    OptionsPage.registerSubPage(LanguageOptions.getInstance(),
+                                AdvancedOptions.getInstance(),
+                                [$('language-button')]);
+  }
   if (!cr.isWindows && !cr.isMac) {
     OptionsPage.registerSubPage(CertificateManager.getInstance(),
                                 AdvancedOptions.getInstance(),
                                 [$('show-cookies-button')]);
-    OptionsPage.registerOverlay(CertificateRestoreOverlay.getInstance());
-    OptionsPage.registerOverlay(CertificateBackupOverlay.getInstance());
-    OptionsPage.registerOverlay(CertificateEditCaTrustOverlay.getInstance());
-    OptionsPage.registerOverlay(CertificateImportErrorOverlay.getInstance());
+    OptionsPage.registerOverlay(CertificateRestoreOverlay.getInstance(),
+                                CertificateManager.getInstance());
+    OptionsPage.registerOverlay(CertificateBackupOverlay.getInstance(),
+                                CertificateManager.getInstance());
+    OptionsPage.registerOverlay(CertificateEditCaTrustOverlay.getInstance(),
+                                CertificateManager.getInstance());
+    OptionsPage.registerOverlay(CertificateImportErrorOverlay.getInstance(),
+                                CertificateManager.getInstance());
   }
-  OptionsPage.registerOverlay(AddStartupPageOverlay.getInstance());
+  OptionsPage.registerOverlay(AddLanguageOverlay.getInstance(),
+                              LanguageOptions.getInstance());
+  OptionsPage.registerOverlay(AddStartupPageOverlay.getInstance(),
+                              BrowserOptions.getInstance());
   OptionsPage.registerOverlay(AlertOverlay.getInstance());
-  OptionsPage.registerOverlay(AutoFillEditAddressOverlay.getInstance());
-  OptionsPage.registerOverlay(AutoFillEditCreditCardOverlay.getInstance());
+  OptionsPage.registerOverlay(AutoFillEditAddressOverlay.getInstance(),
+                              AutoFillOptions.getInstance());
+  OptionsPage.registerOverlay(AutoFillEditCreditCardOverlay.getInstance(),
+                              AutoFillOptions.getInstance());
   OptionsPage.registerOverlay(ClearBrowserDataOverlay.getInstance(),
+                              AdvancedOptions.getInstance(),
                               [$('privacyClearDataButton')]);
-  OptionsPage.registerOverlay(EditSearchEngineOverlay.getInstance());
-  OptionsPage.registerOverlay(ImportDataOverlay.getInstance());
-  OptionsPage.registerOverlay(InstantConfirmOverlay.getInstance());
+  OptionsPage.registerOverlay(ImportDataOverlay.getInstance(),
+                              PersonalOptions.getInstance());
+  OptionsPage.registerOverlay(InstantConfirmOverlay.getInstance(),
+                              BrowserOptions.getInstance());
 
   if (cr.isChromeOS) {
     OptionsPage.register(AccountsOptions.getInstance());
@@ -134,13 +145,15 @@
                                 [$('proxiesConfigureButton')]);
     OptionsPage.registerOverlay(new OptionsPage('detailsInternetPage',
                                                 'detailsInternetPage',
-                                                'detailsInternetPage'));
+                                                'detailsInternetPage'),
+                                InternetOptions.getInstance());
 
     var languageModifierKeysOverlay = new OptionsPage(
         'languageCustomizeModifierKeysOverlay',
         localStrings.getString('languageCustomizeModifierKeysOverlay'),
         'languageCustomizeModifierKeysOverlay')
     OptionsPage.registerOverlay(languageModifierKeysOverlay,
+                                SystemOptions.getInstance(),
                                 [$('modifier-keys-button')]);
   }
 
@@ -148,16 +161,13 @@
   OptionsPage.initialize();
 
   var path = document.location.pathname;
-  var hash = document.location.hash;
 
   if (path.length > 1) {
     var pageName = path.slice(1);
-    OptionsPage.showPageByName(pageName);
-    if (hash.length > 1)
-      OptionsPage.handleHashForPage(pageName, hash.slice(1));
+    // Show page, but don't update history (there's already an entry for it).
+    OptionsPage.showPageByName(pageName, false);
   } else {
-    // TODO(csilv): Save/restore last selected page.
-    OptionsPage.showPageByName(BrowserOptions.getInstance().name);
+    OptionsPage.showDefaultPage();
   }
 
   var subpagesNavTabs = document.querySelectorAll('.subpages-nav-tabs');
@@ -170,10 +180,21 @@
   // Allow platform specific CSS rules.
   if (cr.isMac)
     document.documentElement.setAttribute('os', 'mac');
-  if (cr.isLinux)
+  if (cr.isWindows)
+    document.documentElement.setAttribute('os', 'windows');
+  if (cr.isChromeOS)
+    document.documentElement.setAttribute('os', 'chromeos');
+  if (cr.isLinux) {
+    document.documentElement.setAttribute('os', 'linux');
     document.documentElement.setAttribute('toolkit', 'gtk');
+  }
   if (cr.isViews)
     document.documentElement.setAttribute('toolkit', 'views');
+
+  // Clicking on the Settings title brings up the 'Basics' page.
+  $('settings-title').onclick = function() {
+    OptionsPage.navigateToPage(BrowserOptions.getInstance().name);
+  };
 }
 
 document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/resources/options/options_page.css b/chrome/browser/resources/options/options_page.css
index 47447f4..e132bd4 100644
--- a/chrome/browser/resources/options/options_page.css
+++ b/chrome/browser/resources/options/options_page.css
@@ -1,18 +1,28 @@
 body {
-  -webkit-user-select: none;
   cursor: default;
-  font-size: 100%;
+  font-size: 13px;
+}
+
+a:link {
+  color: rgb(63, 110, 194);
+}
+
+a:active {
+  color: rgb(37, 64, 113);
 }
 
 #settings-title {
   -webkit-padding-end: 24px;
+  -webkit-user-select: none;
   color: #53637d;
+  cursor: pointer;
   font-size: 200%;
   font-weight: normal;
   margin: 0;
   padding-bottom: 14px;
   padding-top: 13px;
   text-align: end;
+  text-shadow: white 0 1px 2px;
 }
 
 #main-content {
@@ -29,26 +39,39 @@
 }
 
 .overlay {
-  position: fixed;
-  left: 0;
-  right: 0;
-  background: rgba(0, 0, 0, .2);
-  top: 0;
-  bottom: 0;
-  z-index: 10;
-  padding: 20px;
-  display: -webkit-box;
   -webkit-box-align: center;
   -webkit-box-pack: center;
+  background: -webkit-radial-gradient(rgba(127, 127, 127, 0.5),
+                                      rgba(127, 127, 127, 0.5) 35%,
+                                      rgba(0, 0, 0, 0.7));
+  bottom: 0;
+  display: -webkit-box;
+  left: 0;
+  padding: 20px;
+  padding-bottom: 130px;
+  position: fixed;
+  right: 0;
+  top: 0;
+  z-index: 10;
+}
+
+.raw-button,
+.raw-button:hover,
+.raw-button:active {
+  -webkit-box-shadow: none;
+  background-color: transparent;
+  background-repeat: no-repeat;
+  border: none;
+  min-width: 0;
+  padding: 1px 6px;
 }
 
 .close-subpage {
-  background-color: transparent;
   background-image: url('chrome://theme/IDR_CLOSE_BAR');
-  border: none;
+  height: 16px;
+  min-width: 0;
   position: relative;
   top: 12px;
-  height: 16px;
   width: 16px;
 }
 
@@ -74,20 +97,27 @@
   display: none
 }
 
+.content-area {
+  padding: 10px 15px 5px 15px;
+}
+
 .action-area {
   -webkit-box-align: center;
   -webkit-box-orient: horizontal;
-  bottom: 0;
+  -webkit-box-pack: end;
+  border-top: 1px solid rgba(188, 193, 208, .5);
   display: -webkit-box;
   padding: 12px;
-  position: absolute;
-  right: 0;
 }
 
 html[dir='rtl'] .action-area {
   left: 0;
 }
 
+.action-area-right {
+  display: -webkit-box;
+}
+
 .button-strip {
   -webkit-box-orient: horizontal;
   display: -webkit-box;
@@ -98,17 +128,17 @@
 }
 
 .button-strip > button {
-  -webkit-margin-start: 4px;
+  -webkit-margin-start: 10px;
   display: block;
 }
 
-.overlay > div {
-  -webkit-box-shadow: 3px 3px 3px #666;
+.overlay .page {
+  -webkit-box-shadow: 0px 5px 80px #505050;
   background: white;
-  border-radius: 5px;
-  padding: 15px;
-  border: 1px solid #666;
-  padding-bottom: 50px;
+  border: 1px solid rgb(188, 193, 208);
+  border-radius: 2px;
+  min-width: 400px;
+  padding: 0;
   position: relative;
 }
 
@@ -118,23 +148,20 @@
 
 #navbar-container {
   -webkit-border-end: 1px solid #c6c9ce;
-  background: -webkit-linear-gradient(rgba(234, 238, 243, 0), #eaeef3),
+  background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #eaeef3),
               -webkit-linear-gradient(left, #eaeef3, #eaeef3 97%, #d3d7db);
   bottom: 0;
-  cursor: pointer;
   display: none;
   left: 0;
-  position: fixed;
   top: 0;
   width: 266px;
+  position: absolute;
   z-index: 2;
 }
 
 html[dir='rtl'] #navbar-container {
-  background: -webkit-linear-gradient(rgba(255, 255, 255, 0)),
-                                      rgba(255, 255, 255, 0) 70%,
-                                      white),
-              -webkit-linear-gradient(right, white, white 80%, #f3f3f3);
+  background: -webkit-linear-gradient(rgba(234, 238, 243, 0), #EAEEF3),
+              -webkit-linear-gradient(right, #EAEEF3, #EAEEF3 97%, #D3D7DB);
   left: auto;
   right: 0;
 }
@@ -143,40 +170,34 @@
   display: block;
 }
 
-#navbar-container > hr {
-  -webkit-margin-start: 35%;
-  background-color: #dbdbdb;
-  border: 0;
-  height: 1px;
-  width: 65%;
-}
-
 #navbar-container > ul {
+  -webkit-user-select: none;
   list-style-type: none;
   margin: 0;
   padding: 0;
 }
 
-.navbar-item, .navbar-item2 {
+.navbar-item {
+  border-bottom: 1px solid transparent;
+  border-top: 1px solid transparent;
   color: #426dc9;
+  cursor: pointer;
   display: block;
   font-size: 105%;
   outline: none;
   padding: 7px 0;
   text-align: end;
+  text-shadow: white 0 1px 1px;
   -webkit-padding-end: 24px;
 }
 
 .navbar-item-selected {
-  background: #bbcee9;
+  -webkit-box-shadow: 0px 1px 0px #f7f7f7;
+  background: -webkit-linear-gradient(left, #bbcee9, #bbcee9 97%, #aabedc);
   border-bottom: 1px solid #8faad9;
   border-top: 1px solid #8faad9;
   color: black;
-  font-weight: bold;
-}
-
-.navbar-item-normal {
-  background-color: #dfdfdf;
+  text-shadow: #bbcee9 0 1px 1px;
 }
 
 #mainview {
@@ -204,29 +225,43 @@
   position: relative;
 }
 
+#subpage-backdrop {
+  background-color: rgba(233, 238, 242, .5);
+  height: 100%;
+  left: 267px;
+  position: fixed;
+  top: 0;
+  width: 100%;
+  z-index: 3;
+}
+
 .subpage-sheet-container {
-  padding: 8px;
-  -webkit-padding-start: 60px;
+  -webkit-margin-start: 60px;
   box-sizing: border-box;
   height: 100%;
+  padding: 8px;
+  /* Must come after padding. */
+  -webkit-padding-start: 0;
   position: absolute;
-  top: 0;
+  /* We set both left and right for the sake of RTL. */
   left: 0;
+  right: 0;
+  top: 0;
+  width: 688px;
 }
 
 #subpage-sheet-container-1 {
-  width: 748px;
   z-index: 5;
 }
 
 #subpage-sheet-container-2 {
-  left: 60px;
-  width: 688px;
+  -webkit-padding-start: 60px;
+  background-color: rgba(233, 238, 242, .5);
   z-index: 10;
 }
 
 .subpage-sheet {
-  -webkit-box-shadow: #666 0px 3px 5px;
+  -webkit-box-shadow: #666 0px 2px 5px;
   background-color: white;
   border: 1px solid #b8b8b8;
   border-radius: 2px;
@@ -266,6 +301,7 @@
 
 .page h1 {
   -webkit-padding-end: 24px;
+  -webkit-user-select: none;
   border-bottom: 1px solid #eeeeee;
   color: #53637d;
   font-size: 200%;
@@ -273,10 +309,25 @@
   margin: 0;
   padding-bottom: 4px;
   padding-top: 13px;
+  text-shadow: white 0 1px 2px;
 }
 
 .subpage-sheet .page h1 {
   padding-top: 4px;
+  margin-bottom: 10px;
+}
+
+.overlay .page h1 {
+  background: -webkit-linear-gradient(white, #F8F8F8);
+  border-bottom: 1px solid rgba(188, 193, 208, .5);
+  font-size: 105%;
+  font-weight: bold;
+  padding: 10px 15px 8px 15px;
+}
+
+.page list {
+  /* Min height is a multiple of the list item height (32) */
+  min-height: 192px;
 }
 
 section {
@@ -329,25 +380,34 @@
   display: none !important;
 }
 
+div.disabled {
+  color: #888;
+}
+
 .touch-slider {
   -webkit-appearance: slider-horizontal;
 }
 
-select {
-  margin: 0;
-}
-
-.link-button {
-  background-color: transparent;
+.link-button,
+.link-button:active,
+.link-button:focus,
+.link-button:hover {
+  -webkit-box-shadow: none;
+  background: transparent none;
   border: none;
   color: blue;
   cursor: pointer;
   text-decoration: underline;
 }
 
-.text-button {
-  background-color: transparent;
+.text-button,
+.text-button:active,
+.text-button:focus,
+.text-button:hover {
+  -webkit-box-shadow: none;
+  background: transparent none;
   border-color: transparent;
+  color: #000;
 }
 
 .settings-list {
@@ -367,17 +427,43 @@
 }
 
 list:not([disabled]) > :hover {
-  background-color: #f2f2f2;
+  background-color: #e4ecf7;
 }
 
-list > [selected],
-list:focus > [selected],
-list:focus > [lead][selected],
-list > [selected]:hover {
-  background-color: #f2f2f2;
+/* TODO(stuartmorgan): Once this becomes the list style for other WebUI pages
+ * these rules can be simplified (since they wont need to override other rules).
+ */
+
+list:not([hasElementFocus]) > [selected],
+list:not([hasElementFocus]) > [lead][selected] {
+  background-color: #d0d0d0;
   background-image: none;
 }
 
+list[hasElementFocus] > [selected],
+list[hasElementFocus] > [lead][selected],
+list:not([hasElementFocus]) > [selected]:hover,
+list:not([hasElementFocus]) > [selected][lead]:hover {
+  background-color: #bbcee9;
+  background-image: none;
+}
+
+list[hasElementFocus] > [lead],
+list[hasElementFocus] > [lead][selected] {
+  border-top: 1px solid #7892b4;
+  border-bottom: 1px solid #7892b4;
+}
+
+list[hasElementFocus] > [lead]:nth-child(2),
+list[hasElementFocus] > [lead][selected]:nth-child(2) {
+  border-top: 1px solid transparent;
+}
+
+list[hasElementFocus] > [lead]:nth-last-child(2),
+list[hasElementFocus] > [lead][selected]:nth-last-child(2) {
+  border-bottom: 1px solid transparent;
+}
+
 list[disabled] > [lead][selected],
 list[disabled]:focus > [lead][selected] {
   border: none;
@@ -401,7 +487,9 @@
 }
 
 list .deletable-item > :first-child {
+  -webkit-box-align: center;
   -webkit-box-flex: 1;
+  -webkit-padding-end: 5px;
   display: -webkit-box;
 }
 
@@ -411,12 +499,15 @@
   /* TODO(stuartmorgan): Replace with real images once they are available. */
   background-image: url("../../../app/theme/close_bar.png");
   border: none;
+  display: block;
   height: 16px;
   opacity: 1;
   width: 16px;
 }
 
-list > *:not(:hover) .close-button,
+list > *:not(:hover):not([lead]) .close-button,
+list > *:not(:hover):not([selected]) .close-button,
+list:not([hasElementFocus]) > *:not(:hover) .close-button,
 list[disabled] .close-button,
 list .close-button[disabled] {
   opacity: 0;
@@ -431,22 +522,31 @@
   background-image: url("../../../app/theme/close_bar_p.png");
 }
 
-.left-side-table {
-  display: -webkit-box;
+list .static-text {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
-.left-side-table > div:first-child {
-  -webkit-box-flex: 1;
-}
-
-.left-side-table > :last-child {
-  -webkit-padding-start: 20px;
-}
-
-.left-side-table > :last-child button {
+list[inlineeditable] input {
+  box-sizing: border-box;
+  margin: 0;
   width: 100%;
 }
 
+list > :not([editing]) [displaymode="edit"] {
+  display: none;
+}
+
+list > [editing] [displaymode="static"] {
+  display: none;
+}
+
+list > [editing] input:invalid {
+  /* TODO(stuartmorgan): Replace with validity badge */
+  background-color: pink;
+}
+
 .option-name {
   padding-right: 5px;
 }
@@ -461,6 +561,18 @@
   background-repeat: no-repeat;
 }
 
+input[type="url"].favicon-cell {
+  -webkit-padding-start: 22px;
+  background-position-x: 4px;
+}
+
+/* TODO(jhawkins): Use something better than 99.3% when CSS3 background
+ * positioning is available.
+ */
+html[dir=rtl] input.favicon-cell {
+  background-position-x: 99.3%;
+}
+
 list .favicon-cell {
   -webkit-margin-start: 7px;
   -webkit-padding-start: 26px;
@@ -486,11 +598,116 @@
  display: none;
 }
 
+/* UI Controls */
+
+/* Currently we can't make custom focus outlines look right on the Mac, so
+ * we stick to native focus rings. Once outlines follow border radius, we
+ * can revisit.
+ */
+html:not([os=mac]) button:focus,
+html:not([os=mac]) input:focus,
+html:not([os=mac]) input[type='submit']:focus,
+html:not([os=mac]) select:focus {
+  outline-color: rgba(0, 128, 256, 0.5);
+}
+html[os=mac] button:focus,
+html[os=mac] input[type='submit']:focus {
+  outline-offset: -2px;
+}
+
+/* TEXT */
+input[type='password'],
+input[type='text'],
+input[type='url'],
+input:not([type]) {
+  -webkit-border-radius: 2px;
+  border: 1px solid #aaa;
+  font-size: inherit;
+  padding: 3px;
+}
+
+/* BUTTON */
+button,
+input[type='submit'] {
+  -webkit-border-radius: 2px;
+  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
+  -webkit-user-select: none;
+  background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5);
+  border: 1px solid #aaa;
+  color: #444;
+  font-size: inherit;
+  margin-bottom: 0px;
+  min-width: 4em;
+  padding: 3px 12px 3px 12px;
+}
+
+button:hover,
+input[type='submit']:hover {
+  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);
+  background: #ebebeb -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9);
+  border-color: #999;
+  color: #222;
+}
+
+button:active,
+input[type='submit']:active {
+  -webkit-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.2);
+  background: #ebebeb -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc);
+  color: #333;
+}
+
+button[disabled],
+input[type='submit'][disabled],
+button[disabled]:hover,
+input[type='submit'][disabled]:hover {
+  -webkit-box-shadow: none;
+  background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5);
+  border-color: #aaa;
+  color: #888;
+}
+
+/* SELECT */
+select {
+  -webkit-appearance: button;
+  -webkit-border-radius: 2px;
+  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
+  -webkit-user-select: none;
+  background-image: url("select.png"), -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5);
+  background-position: center right;
+  background-repeat: no-repeat;
+  border: 1px solid #aaa;
+  color: #555;
+  font-size: inherit;
+  margin: 0;
+  overflow: hidden;
+  padding: 2px 20px 2px 5px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+html[dir='rtl'] select {
+  background-position: center left;
+}
+
+select:hover {
+  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);
+  background-image: url("select.png"), -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9);
+  color: #333;
+}
+
+select:active {
+  -webkit-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.2);
+  background-image: url("select.png"), -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc);
+  color: #444;
+}
+
+/* CHECKBOX, RADIO */
 input[type=checkbox],
-input[type=radio],
-button {
+input[type=radio] {
   margin-left: 0;
   margin-right: 0;
+  position: relative;
+  top: 1px;
 }
 
 /* Checkbox and radio buttons have different sizes on different platforms. The
@@ -503,11 +720,11 @@
   margin-top: 1px;
 }
 
-.suboption {
-  -webkit-margin-start: 16px;
-}
-
 html[os=mac] label > input[type=checkbox],
 html[os=mac] label > input[type=radio] {
   margin-top: 2px;
 }
+
+.suboption {
+  -webkit-margin-start: 16px;
+}
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js
index 057e86d..4d563ab 100644
--- a/chrome/browser/resources/options/options_page.js
+++ b/chrome/browser/resources/options/options_page.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -43,11 +43,49 @@
   OptionsPage.initialized_ = false;
 
   /**
-   * Shows a registered page. This handles both top-level pages and sub-pages.
+   * Gets the default page (to be shown on initial load).
+   */
+  OptionsPage.getDefaultPage = function() {
+    return BrowserOptions.getInstance();
+  };
+
+  /**
+   * Shows the default page.
+   */
+  OptionsPage.showDefaultPage = function() {
+    this.navigateToPage(this.getDefaultPage().name);
+  };
+
+  /**
+   * "Navigates" to a page, meaning that the page will be shown and the
+   * appropriate entry is placed in the history.
    * @param {string} pageName Page name.
    */
-  OptionsPage.showPageByName = function(pageName) {
+  OptionsPage.navigateToPage = function(pageName) {
+    this.showPageByName(pageName, true);
+  };
+
+  /**
+   * Shows a registered page. This handles both top-level pages and sub-pages.
+   * @param {string} pageName Page name.
+   * @param {boolean} updateHistory True if we should update the history after
+   *     showing the page.
+   * @private
+   */
+  OptionsPage.showPageByName = function(pageName, updateHistory) {
     var targetPage = this.registeredPages[pageName];
+    if (!targetPage || !targetPage.canShowPage()) {
+      // If it's not a page, try it as an overlay.
+      if (!targetPage && this.showOverlay_(pageName)) {
+        if (updateHistory)
+          this.updateHistoryState_();
+        return;
+      } else {
+        targetPage = this.getDefaultPage();
+      }
+    }
+
+    pageName = targetPage.name;
 
     // Determine if the root page is 'sticky', meaning that it
     // shouldn't change when showing a sub-page.  This can happen for special
@@ -83,6 +121,10 @@
            page.isAncestorOfPage(targetPage));
     }
 
+    // Update the history and current location.
+    if (updateHistory)
+      this.updateHistoryState_();
+
     // Notify pages if they were shown.
     for (var name in this.registeredPages) {
       var page = this.registeredPages[name];
@@ -95,24 +137,47 @@
   };
 
   /**
-   * Called on load. Dispatch the URL hash to the given page's handleHash
-   * function.
-   * @param {string} pageName The string name of the (registered) options page.
-   * @param {string} hash The value of the hash component of the URL.
+   * Pushes the current page onto the history stack, overriding the last page
+   * if it is the generic chrome://settings/.
+   * @private
    */
-  OptionsPage.handleHashForPage = function(pageName, hash) {
-    var page = this.registeredPages[pageName];
-    page.handleHash(hash);
+  OptionsPage.updateHistoryState_ = function() {
+    var page = this.getTopmostVisiblePage();
+    var path = location.pathname;
+    if (path)
+      path = path.slice(1);
+    // The page is already in history (the user may have clicked the same link
+    // twice). Do nothing.
+    if (path == page.name)
+      return;
+
+    // If there is no path, the current location is chrome://settings/.
+    // Override this with the new page.
+    var historyFunction = path ? window.history.pushState :
+                                 window.history.replaceState;
+    historyFunction.call(window.history,
+                         {pageName: page.name},
+                         page.title,
+                         '/' + page.name);
+    // Update tab title.
+    document.title = page.title;
   };
 
   /**
-   * Shows a registered Overlay page.
+   * Shows a registered Overlay page. Does not update history.
    * @param {string} overlayName Page name.
+   * @return {boolean} whether we showed an overlay.
    */
-  OptionsPage.showOverlay = function(overlayName) {
-    if (this.registeredOverlayPages[overlayName]) {
-      this.registeredOverlayPages[overlayName].visible = true;
-    }
+  OptionsPage.showOverlay_ = function(overlayName) {
+    var overlay = this.registeredOverlayPages[overlayName];
+    if (!overlay || !overlay.canShowPage())
+      return false;
+
+    if (overlay.parentPage)
+      this.showPageByName(overlay.parentPage.name, false);
+
+    this.registeredOverlayPages[overlayName].visible = true;
+    return true;
   };
 
   /**
@@ -121,21 +186,43 @@
    * @private
    */
   OptionsPage.isOverlayVisible_ = function() {
-    for (var name in this.registeredOverlayPages) {
-      if (this.registeredOverlayPages[name].visible)
-        return true;
-    }
-    return false;
+    return this.getVisibleOverlay_() != null;
   };
 
   /**
-   * Clears overlays (i.e. hide all overlays).
+   * Returns the currently visible overlay, or null if no page is visible.
+   * @return {OptionPage} The visible overlay.
    */
-  OptionsPage.clearOverlays = function() {
-     for (var name in this.registeredOverlayPages) {
-       var page = this.registeredOverlayPages[name];
-       page.visible = false;
-     }
+  OptionsPage.getVisibleOverlay_ = function() {
+    for (var name in this.registeredOverlayPages) {
+      var page = this.registeredOverlayPages[name];
+      if (page.visible)
+        return page;
+    }
+    return null;
+  };
+
+  /**
+   * Closes the visible overlay. Updates the history state after closing the
+   * overlay.
+   */
+  OptionsPage.closeOverlay = function() {
+    var overlay = this.getVisibleOverlay_();
+    if (!overlay)
+      return;
+
+    overlay.visible = false;
+    this.updateHistoryState_();
+  };
+
+  /**
+   * Hides the visible overlay. Does not affect the history state.
+   * @private
+   */
+  OptionsPage.hideOverlay_ = function() {
+    var overlay = this.getVisibleOverlay_();
+    if (overlay)
+      overlay.visible = false;
   };
 
   /**
@@ -143,6 +230,11 @@
    * @return {OptionPage} The topmost visible page.
    */
   OptionsPage.getTopmostVisiblePage = function() {
+    // Check overlays first since they're top-most if visible.
+    var overlay = this.getVisibleOverlay_();
+    if (overlay)
+      return overlay;
+
     var topPage = null;
     for (var name in this.registeredPages) {
       var page = this.registeredPages[name];
@@ -150,16 +242,20 @@
           (!topPage || page.nestingLevel > topPage.nestingLevel))
         topPage = page;
     }
+
     return topPage;
-  }
+  };
 
   /**
    * Closes the topmost open subpage, if any.
+   * @private
    */
-  OptionsPage.closeTopSubPage = function() {
+  OptionsPage.closeTopSubPage_ = function() {
     var topPage = this.getTopmostVisiblePage();
-    if (topPage && topPage.parentPage)
+    if (topPage && !topPage.isOverlay && topPage.parentPage)
       topPage.visible = false;
+
+    this.updateHistoryState_();
   };
 
   /**
@@ -172,6 +268,8 @@
       topPage.visible = false;
       topPage = topPage.parentPage;
     }
+
+    this.updateHistoryState_();
   };
 
   /**
@@ -191,10 +289,10 @@
     // Search parents until we find a tab, or the nav bar itself. This allows
     // tabs to have child nodes, e.g. labels in separately-styled spans.
     while (tab && !tab.classList.contains('subpages-nav-tabs') &&
-           !tab.classList.contains('inactive-tab')) {
+           !tab.classList.contains('tab')) {
       tab = tab.parentNode;
     }
-    if (!tab || !tab.classList.contains('inactive-tab'))
+    if (!tab || !tab.classList.contains('tab'))
       return;
 
     if (this.activeNavTab != null) {
@@ -219,15 +317,15 @@
     pageNav.id = page.name + 'PageNav';
     pageNav.className = 'navbar-item';
     pageNav.setAttribute('pageName', page.name);
-    pageNav.textContent = page.title;
+    pageNav.textContent = page.pageDiv.querySelector('h1').textContent;
     pageNav.tabIndex = 0;
     pageNav.onclick = function(event) {
-      OptionsPage.showPageByName(this.getAttribute('pageName'));
+      OptionsPage.navigateToPage(this.getAttribute('pageName'));
     };
     pageNav.onkeypress = function(event) {
       // Enter or space
       if (event.keyCode == 13 || event.keyCode == 32) {
-        OptionsPage.showPageByName(this.getAttribute('pageName'));
+        OptionsPage.navigateToPage(this.getAttribute('pageName'));
       }
     };
     var navbar = $('navbar');
@@ -255,8 +353,8 @@
    * @param {OptionsPage} subPage Sub-page to register.
    * @param {OptionsPage} parentPage Associated parent page for this page.
    * @param {Array} associatedControls Array of control elements that lead to
-   *     this sub-page.  The first item is typically a button in a root-level
-   *     page.  There may be additional buttons for nested sub-pages.
+   *     this sub-page. The first item is typically a button in a root-level
+   *     page. There may be additional buttons for nested sub-pages.
    */
   OptionsPage.registerSubPage = function(subPage,
                                          parentPage,
@@ -276,23 +374,26 @@
 
   /**
    * Registers a new Overlay page.
-   * @param {OptionsPage} page Page to register, must be a class derived from
+   * @param {OptionsPage} overlay Overlay to register.
+   * @param {OptionsPage} parentPage Associated parent page for this overlay.
    * @param {Array} associatedControls Array of control elements associated with
    *   this page.
    */
-  OptionsPage.registerOverlay = function(page,
+  OptionsPage.registerOverlay = function(overlay,
+                                         parentPage,
                                          associatedControls) {
-    this.registeredOverlayPages[page.name] = page;
+    this.registeredOverlayPages[overlay.name] = overlay;
+    overlay.parentPage = parentPage;
     if (associatedControls) {
-      page.associatedControls = associatedControls;
+      overlay.associatedControls = associatedControls;
       if (associatedControls.length) {
-        page.associatedSection =
+        overlay.associatedSection =
             this.findSectionForNode_(associatedControls[0]);
       }
     }
-    page.tab = undefined;
-    page.isOverlay = true;
-    page.initializePage();
+    overlay.tab = undefined;
+    overlay.isOverlay = true;
+    overlay.initializePage();
   };
 
   /**
@@ -301,13 +402,17 @@
    */
   OptionsPage.setState = function(data) {
     if (data && data.pageName) {
-      this.showPageByName(data.pageName);
+      // It's possible an overlay may be the last top-level page shown.
+      if (this.isOverlayVisible_())
+        this.hideOverlay_();
+
+      this.showPageByName(data.pageName, false);
     }
   };
 
   /**
-   * Initializes the complete options page.  This will cause
-   * all C++ handlers to be invoked to do final setup.
+   * Initializes the complete options page.  This will cause all C++ handlers to
+   * be invoked to do final setup.
    */
   OptionsPage.initialize = function() {
     chrome.send('coreOptionsInitialize');
@@ -319,45 +424,126 @@
       var containerId = 'subpage-sheet-container-' + level;
       $(containerId).onclick = this.subPageClosingClickHandler_(level);
     }
-    // Hook up the close buttons.
+
     var self = this;
+    // Close subpages if the user clicks on the html body. Listen in the
+    // capturing phase so that we can stop the click from doing anything.
+    document.body.addEventListener('click',
+                                   this.bodyMouseEventHandler_.bind(this),
+                                   true);
+    // We also need to cancel mousedowns on non-subpage content.
+    document.body.addEventListener('mousedown',
+                                   this.bodyMouseEventHandler_.bind(this),
+                                   true);
+
+    // Hook up the close buttons.
     subpageCloseButtons = document.querySelectorAll('.close-subpage');
     for (var i = 0; i < subpageCloseButtons.length; i++) {
       subpageCloseButtons[i].onclick = function() {
-        self.closeTopSubPage();
+        self.closeTopSubPage_();
       };
-    }
+    };
 
-    // Close the top overlay or sub-page on esc.
-    document.addEventListener('keydown', function(e) {
-      if (e.keyCode == 27) { // Esc
-        if (self.isOverlayVisible_())
-          self.clearOverlays();
-        else
-          self.closeTopSubPage();
-      }
-    });
+    // Install handler for key presses.
+    document.addEventListener('keydown', this.keyDownEventHandler_.bind(this));
+
+    document.addEventListener('focus', this.manageFocusChange_.bind(this),
+                              true);
   };
 
   /**
    * Returns a function to handle clicks behind a subpage at level |level| by
    * closing all subpages down to |level| - 1.
    * @param {number} level The level of the subpage being handled.
-   * @return {function} a function to handle clicks outside the given subpage.
+   * @return {Function} a function to handle clicks outside the given subpage.
    * @private
    */
   OptionsPage.subPageClosingClickHandler_ = function(level) {
     var self = this;
     return function(event) {
-      // Clicks on the visible part of the parent page should close the overlay,
+      // Clicks on the narrow strip between the left of the subpage sheet and
+      // that shows part of the parent page should close the overlay, but
       // not fall through to the parent page.
-      if (!$('subpage-sheet-' + level).contains(event.target))
+      if (!$('subpage-sheet-' + level).contains(event.target)) {
         self.closeSubPagesToLevel(level - 1);
-      event.stopPropagation();
+        event.stopPropagation();
+        event.preventDefault();
+      }
     };
   };
 
   /**
+   * Called when focus changes; ensures that focus doesn't move outside
+   * the topmost subpage/overlay.
+   * @param {Event} e The focus change event.
+   * @private
+   */
+  OptionsPage.manageFocusChange_ = function(e) {
+    var focusableItemsRoot;
+    var topPage = this.getTopmostVisiblePage();
+    if (!topPage)
+      return;
+
+    if (topPage.isOverlay) {
+      // If an overlay is visible, that defines the tab loop.
+      focusableItemsRoot = topPage.pageDiv;
+    } else {
+      // If a subpage is visible, use its parent as the tab loop constraint.
+      // (The parent is used because it contains the close button.)
+      if (topPage.nestingLevel > 0)
+        focusableItemsRoot = topPage.pageDiv.parentNode;
+    }
+
+    if (focusableItemsRoot && !focusableItemsRoot.contains(e.target))
+      topPage.focusFirstElement();
+  };
+
+  /**
+   * A function to handle mouse events (mousedown or click) on the html body by
+   * closing subpages and/or stopping event propagation.
+   * @return {Event} a mousedown or click event.
+   * @private
+   */
+  OptionsPage.bodyMouseEventHandler_ = function(event) {
+    // Do nothing if a subpage isn't showing.
+    var topPage = this.getTopmostVisiblePage();
+    if (!topPage || topPage.isOverlay || !topPage.parentPage)
+      return;
+
+    // Don't interfere with navbar clicks.
+    if ($('navbar').contains(event.target))
+      return;
+
+    // If the click was within a subpage, do nothing.
+    for (var level = 1; level <= 2; level++) {
+      if ($('subpage-sheet-container-' + level).contains(event.target))
+        return;
+    }
+
+    // Close all subpages on click.
+    if (event.type == 'click')
+      this.closeSubPagesToLevel(0);
+
+    event.stopPropagation();
+    event.preventDefault();
+  };
+
+  /**
+   * A function to handle key press events.
+   * @return {Event} a keydown event.
+   * @private
+   */
+  OptionsPage.keyDownEventHandler_ = function(event) {
+    // Close the top overlay or sub-page on esc.
+    if (event.keyCode == 27) {  // Esc
+      if (this.isOverlayVisible_())
+        this.closeOverlay();
+      else
+        this.closeTopSubPage_();
+    }
+  };
+
+  /**
    * Re-initializes the C++ handlers if necessary. This is called if the
    * handlers are torn down and recreated but the DOM may not have been (in
    * which case |initialize| won't be called again). If |initialize| hasn't been
@@ -408,13 +594,32 @@
     },
 
     /**
-     * Updates managed banner visibility state.
+     * Updates managed banner visibility state. This function iterates over
+     * all input fields of a window and if any of these is marked as managed
+     * it triggers the managed banner to be visible. The banner can be enforced
+     * being on through the managed flag of this class but it can not be forced
+     * being off if managed items exist.
      */
     updateManagedBannerVisibility: function() {
-      if (this.managed) {
-        $('managed-prefs-banner').classList.remove('hidden');
+      var bannerDiv = $('managed-prefs-banner');
+
+      var hasManaged = this.managed;
+      if (!hasManaged) {
+        var inputElements = this.pageDiv.querySelectorAll('input');
+        for (var i = 0, len = inputElements.length; i < len; i++) {
+          if (inputElements[i].managed) {
+            hasManaged = true;
+            break;
+          }
+        }
+      }
+      if (hasManaged) {
+        bannerDiv.classList.remove('hidden');
+        var height = window.getComputedStyle($('managed-prefs-banner')).height;
+        $('subpage-backdrop').style.top = height;
       } else {
-        $('managed-prefs-banner').classList.add('hidden');
+        bannerDiv.classList.add('hidden');
+        $('subpage-backdrop').style.top = '0';
       }
     },
 
@@ -443,16 +648,11 @@
           if (nestingLevel > 0) {
             var containerId = 'subpage-sheet-container-' + nestingLevel;
             $(containerId).classList.remove('hidden');
+            if (nestingLevel == 1)
+              $('subpage-backdrop').classList.remove('hidden');
           }
-
-          // The managed prefs banner is global, so after any visibility change
-          // update it based on the topmost page, not necessarily this page.
-          // (e.g., if an ancestor is made visible after a child).
-          OptionsPage.updateManagedBannerVisibility();
-
-          // Recent webkit change no longer allows url change from "chrome://".
-          window.history.pushState({pageName: this.name}, this.title);
         }
+
         if (this.tab) {
           this.tab.classList.add('navbar-item-selected');
         }
@@ -465,19 +665,36 @@
           if (nestingLevel > 0) {
             var containerId = 'subpage-sheet-container-' + nestingLevel;
             $(containerId).classList.add('hidden');
+            if (nestingLevel == 1)
+              $('subpage-backdrop').classList.add('hidden');
           }
-
-          OptionsPage.updateManagedBannerVisibility();
         }
+
         if (this.tab) {
           this.tab.classList.remove('navbar-item-selected');
         }
       }
 
+      // The managed prefs banner is global, so after any visibility change
+      // update it based on the topmost page, not necessarily this page
+      // (e.g., if an ancestor is made visible after a child).
+      OptionsPage.updateManagedBannerVisibility();
+
       cr.dispatchPropertyChange(this, 'visible', visible, !visible);
     },
 
     /**
+     * Focuses the first control on the page.
+     */
+    focusFirstElement: function() {
+      // Sets focus on the first interactive element in the page.
+      var focusElement =
+          this.pageDiv.querySelector('button, input, list, select');
+      if (focusElement)
+        focusElement.focus();
+    },
+
+    /**
      * The nesting level of this page.
      * @type {number} The nesting level of this page (0 for top-level page)
      */
@@ -517,14 +734,11 @@
     },
 
     /**
-     * Handles a hash value in the URL (such as bar in
-     * chrome://options/foo#bar). Called on page load. By default, this shows
-     * an overlay that matches the hash name, but can be overriden by individual
-     * OptionsPage subclasses to get other behavior.
-     * @param {string} hash The hash value.
+     * Whether it should be possible to show the page.
+     * @return {boolean} True if the page should be shown
      */
-    handleHash: function(hash) {
-      OptionsPage.showOverlay(hash);
+    canShowPage: function() {
+      return true;
     },
   };
 
@@ -532,5 +746,4 @@
   return {
     OptionsPage: OptionsPage
   };
-
 });
diff --git a/chrome/browser/resources/options/password_manager.css b/chrome/browser/resources/options/password_manager.css
deleted file mode 100644
index 48ac0d9..0000000
--- a/chrome/browser/resources/options/password_manager.css
+++ /dev/null
@@ -1,38 +0,0 @@
-#saved-passwords-list .url {
-  box-sizing: border-box;
-  width: 40%;
-}
-
-#saved-passwords-list .name {
-  -webkit-box-flex: 1;
-  width: 20%;
-}
-
-#saved-passwords-list .password {
-  -webkit-box-flex: 1;
-  position: relative;
-}
-
-#saved-passwords-list .password > span {
-  background: url('show_password.png');
-  cursor: pointer;
-  height: 18px;
-  position: absolute;
-  top: 5px;
-  width: 40px;
-}
-
-html[dir='ltr'] #saved-passwords-list .password > span {
-  right: 50px;
-}
-
-html[dir='rtl'] #saved-passwords-list .password > span {
-  left: 50px;
-}
-
-#saved-passwords-list .url,
-#saved-passwords-list .name,
-#password-exceptions-list .url {
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
diff --git a/chrome/browser/resources/options/password_manager.html b/chrome/browser/resources/options/password_manager.html
index b103dbf..1e404fe 100644
--- a/chrome/browser/resources/options/password_manager.html
+++ b/chrome/browser/resources/options/password_manager.html
@@ -1,5 +1,5 @@
 <div id="password-manager" class="page hidden">
-  <h1 i18n-content="passwordsTitle"></h1>
+  <h1 i18n-content="passwordsPage"></h1>
   <h3 i18n-content="savedPasswordsTitle"></h3>
   <list id="saved-passwords-list" class="settings-list"></list>
   <h3 i18n-content="passwordExceptionsTitle"></h3>
diff --git a/chrome/browser/resources/options/password_manager.js b/chrome/browser/resources/options/password_manager.js
index ac3fc3a..41a8c5d 100644
--- a/chrome/browser/resources/options/password_manager.js
+++ b/chrome/browser/resources/options/password_manager.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,7 +18,7 @@
     this.activeNavTab = null;
     OptionsPage.call(this,
                      'passwordManager',
-                     templateData.passwordsTitle,
+                     templateData.passwordsPageTabTitle,
                      'password-manager');
   }
 
@@ -41,12 +41,23 @@
      */
     passwordExceptionsList_: null,
 
+    /** @inheritDoc */
     initializePage: function() {
       OptionsPage.prototype.initializePage.call(this);
 
       this.createSavedPasswordsList_();
       this.createPasswordExceptionsList_();
+    },
 
+    /** @inheritDoc */
+    canShowPage: function() {
+      return !PersonalOptions.disablePasswordManagement();
+    },
+
+    /** @inheritDoc */
+    didShowPage: function() {
+      // Updating the password lists may cause a blocking platform dialog pop up
+      // (Mac, Linux), so we delay this operation until the page is shown.
       chrome.send('updatePasswordLists');
     },
 
diff --git a/chrome/browser/resources/options/password_manager_list.css b/chrome/browser/resources/options/password_manager_list.css
index 40201e9..fd7e733 100644
--- a/chrome/browser/resources/options/password_manager_list.css
+++ b/chrome/browser/resources/options/password_manager_list.css
@@ -1,10 +1,53 @@
 /*
-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.
-*/
+ * Copyright (c) 2011 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
 
-.inactive-password {
+button.password-button {
+  background: #8aaaed;
+  color: #fff;
+  display: inline;
+  font-size: 90%;
+  font-weight: bold;
+  height: 18px;
+  padding: 0 2px;
+  position: absolute;
+  top: 5px;
+  width: 50px;
+}
+
+html[dir='ltr'] button.password-button {
+  right: 50px;
+}
+
+html[dir='rtl'] button.password-button {
+  left: 50px;
+}
+
+input[type="password"].inactive-password {
   background: transparent;
   border: none;
 }
+
+#saved-passwords-list .url {
+  box-sizing: border-box;
+  width: 40%;
+}
+
+#saved-passwords-list .name {
+  -webkit-box-flex: 1;
+  width: 20%;
+}
+
+#saved-passwords-list .password {
+  -webkit-box-flex: 1;
+  position: relative;
+}
+
+#saved-passwords-list .url,
+#saved-passwords-list .name,
+#password-exceptions-list .url {
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
diff --git a/chrome/browser/resources/options/password_manager_list.js b/chrome/browser/resources/options/password_manager_list.js
index 593a9bc..b286e8e 100644
--- a/chrome/browser/resources/options/password_manager_list.js
+++ b/chrome/browser/resources/options/password_manager_list.js
@@ -32,8 +32,8 @@
 
       // The URL of the site.
       var urlLabel = this.ownerDocument.createElement('div');
-      urlLabel.className = 'url';
       urlLabel.classList.add('favicon-cell');
+      urlLabel.classList.add('url');
       urlLabel.textContent = this.url;
       urlLabel.style.backgroundImage = url('chrome://favicon/' + this.url);
       this.contentElement.appendChild(urlLabel);
@@ -50,16 +50,19 @@
 
       // The password input field.
       var passwordInput = this.ownerDocument.createElement('input');
-      passwordInput.className = 'inactive-password';
       passwordInput.type = 'password';
+      passwordInput.className = 'inactive-password';
+      passwordInput.readOnly = true;
       passwordInput.value = this.password;
       passwordInputDiv.appendChild(passwordInput);
 
       // The show/hide button.
-      var buttonSpan = this.ownerDocument.createElement('span');
-      buttonSpan.className = 'hidden';
-      buttonSpan.addEventListener('click', this.onClick_, true);
-      passwordInputDiv.appendChild(buttonSpan);
+      var button = this.ownerDocument.createElement('button');
+      button.classList.add('hidden');
+      button.classList.add('password-button');
+      button.textContent = localStrings.getString('passwordShowButton');
+      button.addEventListener('click', this.onClick_, true);
+      passwordInputDiv.appendChild(button);
 
       this.contentElement.appendChild(passwordInputDiv);
     },
@@ -67,13 +70,15 @@
     /** @inheritDoc */
     selectionChanged: function() {
       var passwordInput = this.querySelector('input[type=password]');
-      var buttonSpan = passwordInput.nextSibling;
+      var textInput = this.querySelector('input[type=text]');
+      var input = passwordInput || textInput;
+      var button = input.nextSibling;
       if (this.selected) {
-        passwordInput.classList.remove('inactive-password');
-        buttonSpan.classList.remove('hidden');
+        input.classList.remove('inactive-password');
+        button.classList.remove('hidden');
       } else {
-        passwordInput.classList.add('inactive-password');
-        buttonSpan.classList.add('hidden');
+        input.classList.add('inactive-password');
+        button.classList.add('hidden');
       }
     },
 
@@ -83,11 +88,16 @@
      * @private
      */
     onClick_: function(event) {
-      // The password is the input element previous to the button span.
-      var buttonSpan = event.currentTarget;
-      var passwordInput = buttonSpan.previousSibling;
-      var type = passwordInput.type;
-      passwordInput.type = type == 'password' ? 'text' : 'password';
+      // The password is the input element previous to the button.
+      var button = event.currentTarget;
+      var passwordInput = button.previousSibling;
+      if (passwordInput.type == 'password') {
+        passwordInput.type = 'text';
+        button.textContent = localStrings.getString('passwordHideButton');
+      } else {
+        passwordInput.type = 'password';
+        button.textContent = localStrings.getString('passwordShowButton');
+      }
     },
 
     /**
diff --git a/chrome/browser/resources/options/personal_options.css b/chrome/browser/resources/options/personal_options.css
index fda8a45..5ea1835 100644
--- a/chrome/browser/resources/options/personal_options.css
+++ b/chrome/browser/resources/options/personal_options.css
@@ -5,6 +5,27 @@
   height: 70px;
 }
 
+#sync-buttons {
+  margin: 10px 0;
+}
+
+#start-stop-sync {
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+#themes-gallery-div {
+  margin: 10px 0;
+}
+
 .sync-error {
-  background-color: #FF9A9A;
+  background: #FFDBDB;
+  border: 1px solid #ce4c4c;
+  border-radius: 2px;
+  padding: 10px;
+}
+
+.sync-error .link-button {
+  margin: 0 1ex;
+  padding: 0;
 }
diff --git a/chrome/browser/resources/options/personal_options.html b/chrome/browser/resources/options/personal_options.html
index a028945..0891c32 100644
--- a/chrome/browser/resources/options/personal_options.html
+++ b/chrome/browser/resources/options/personal_options.html
@@ -26,77 +26,13 @@
   <section id="sync-section">
     <h3 i18n-content="syncSection"></h3>
     <div>
-      <select id="sync-select" pref="sync.keep_everything_synced"
-          i18n-options="syncSelectList"></select>
-      <table id="sync-table">
-        <tr>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="settings-check" pref="sync.preferences"
-                  type="checkbox">
-              <span i18n-content="syncsettings"></span>
-            </label>
-          </td>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="bookmarks-check" pref="sync.bookmarks" type="checkbox">
-              <span i18n-content="syncbookmarks"></span>
-            </label>
-          </td>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="extensions-check" pref="sync.extensions"
-                  type="checkbox">
-              <span i18n-content="syncextensions"></span>
-            </label>
-          </td>
-        </tr>
-        <tr>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="autofill-check" pref="sync.autofill" type="checkbox">
-              <span i18n-content="syncautofill"></span>
-            </label>
-          </td>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="themes-check" pref="sync.themes" type="checkbox">
-              <span i18n-content="syncthemes"></span>
-            </label>
-          </td>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="apps-check" pref="sync.apps" type="checkbox">
-              <span i18n-content="syncapps"></span>
-            </label>
-          </td>
-        </tr>
-        <tr>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="typedurls-check" pref="sync.typed_urls"
-                  type="checkbox">
-              <span i18n-content="synctypedurls"></span>
-            </label>
-          </td>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="passwords-check" pref="sync.passwords" type="checkbox">
-              <span i18n-content="syncpasswords"></span>
-            </label>
-          </td>
-          <td class="option-name">
-            <label class="checkbox">
-              <input id="sessions-check" pref="sync.sessions" type="checkbox">
-              <span i18n-content="syncsessions"></span>
-            </label>
-          </td>
-        </tr>
-      </table>
-      <div id="sync-status" class="section-text"></div>
-      <button id="sync-action-link" class="link-button"></button>
-      <div>
+      <div id="sync-status">
+        <span id="sync-status-text"></span>
+        <button id="sync-action-link" class="link-button"></button>
+      </div>
+      <div id="sync-buttons">
         <button id="start-stop-sync"></button>
+        <button id="customize-sync" i18n-content="customizeSync"></button>
       </div>
       <a href="https://www.google.com/dashboard" id="privacy-dashboard-link"
           i18n-content="privacyDashboardLink" target="_blank"></a>
@@ -106,8 +42,9 @@
     <h3 i18n-content="passwords"></h3>
     <div>
       <label class="radio">
-        <input type="radio" pref="profile.password_manager_enabled" value="true"
-            metric="Options_PasswordManager">
+        <input id="passwords-offersave"
+            pref="profile.password_manager_enabled"
+            type="radio" value="true" metric="Options_PasswordManager">
         <span i18n-content="passwordsAskToSave"></span>
       </label>
       <label class="radio">
@@ -151,8 +88,10 @@
         <button id="themes-reset"
             i18n-content="themesSetClassic"></button>
       </div>
-      <a id="themes-gallery" i18n-content="themesGallery"
-          i18n-values="href:themesGalleryURL" target="_blank"></a>
+      <div id="themes-gallery-div">
+        <a id="themes-gallery" i18n-content="themesGallery"
+            i18n-values="href:themesGalleryURL" target="_blank"></a>
+      </div>
       <label class="radio">
         <input name="decorations_radio"
             pref="browser.custom_chrome_frame"
@@ -175,8 +114,10 @@
       <div>
         <button id="themes-reset" i18n-content="themesReset"></button>
       </div>
-      <a id="themes-gallery" i18n-content="themesGallery"
-          i18n-values="href:themesGalleryURL" target="_blank"></a>
+      <div id="themes-gallery-div">
+        <a id="themes-gallery" i18n-content="themesGallery"
+            i18n-values="href:themesGalleryURL" target="_blank"></a>
+      </div>
     </div>
   </section>
 </if>
diff --git a/chrome/browser/resources/options/personal_options.js b/chrome/browser/resources/options/personal_options.js
index 7a92a94..8775ec0 100644
--- a/chrome/browser/resources/options/personal_options.js
+++ b/chrome/browser/resources/options/personal_options.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,7 +15,8 @@
    * @constructor
    */
   function PersonalOptions() {
-    OptionsPage.call(this, 'personal', templateData.personalPage,
+    OptionsPage.call(this, 'personal',
+                     templateData.personalPageTabTitle,
                      'personal-page');
   }
 
@@ -32,7 +33,7 @@
 
       var self = this;
       $('sync-action-link').onclick = function(event) {
-        chrome.send('showSyncLoginDialog');
+        chrome.send('showSyncActionDialog');
       };
       $('start-stop-sync').onclick = function(event) {
         if (self.syncSetupCompleted)
@@ -40,17 +41,20 @@
         else
           chrome.send('showSyncLoginDialog');
       };
+      $('customize-sync').onclick = function(event) {
+        chrome.send('showCustomizeSyncDialog');
+      };
       $('privacy-dashboard-link').onclick = function(event) {
         chrome.send('openPrivacyDashboardTabAndActivate');
       };
       $('manage-passwords').onclick = function(event) {
-        OptionsPage.showPageByName('passwordManager');
+        OptionsPage.navigateToPage('passwordManager');
         OptionsPage.showTab($('passwords-nav-tab'));
         chrome.send('coreOptionsUserMetricsAction',
             ['Options_ShowPasswordManager']);
       };
       $('autofill-settings').onclick = function(event) {
-        OptionsPage.showPageByName('autoFillOptions');
+        OptionsPage.navigateToPage('autoFillOptions');
         chrome.send('coreOptionsUserMetricsAction',
             ['Options_ShowAutoFillSettings']);
       };
@@ -58,23 +62,9 @@
         chrome.send('themesReset');
       };
 
-      // Initialize sync select control.
-      $('sync-select').onchange = function(event) {
-        self.updateSyncSelection_();
-      }
-
-      var syncCheckboxes = $('sync-table').getElementsByTagName('input');
-      for (var i = 0; i < syncCheckboxes.length; i++) {
-        if (syncCheckboxes[i].type == "checkbox") {
-          syncCheckboxes[i].onclick = function(event) {
-            chrome.send('updatePreferredDataTypes');
-          };
-        }
-      }
-
       if (!cr.isChromeOS) {
         $('import-data').onclick = function(event) {
-          OptionsPage.showOverlay('importDataOverlay');
+          OptionsPage.navigateToPage('importDataOverlay');
           chrome.send('coreOptionsUserMetricsAction', ['Import_ShowDlg']);
         };
 
@@ -87,31 +77,17 @@
         chrome.send('loadAccountPicture');
       }
 
-      // Disable the screen lock checkbox for the guest mode.
-      if (cr.commandLine.options['--bwsi'])
+      if (cr.commandLine.options['--bwsi']) {
+        // Disable the screen lock checkbox for the guest mode.
         $('enable-screen-lock').disabled = true;
-    },
+      }
 
-    /**
-     * Updates the sync datatype checkboxes based on the selected sync option.
-     * @private
-     */
-    updateSyncSelection_: function() {
-      var idx = $('sync-select').selectedIndex;
-      var syncCheckboxes = $('sync-table').getElementsByTagName('input');
-      if (idx == 0) {
-        for (var i = 0; i < syncCheckboxes.length; i++) {
-          syncCheckboxes[i].disabled = false;
-        }
-      } else if (idx == 1) {
-        for (var i = 0; i < syncCheckboxes.length; i++) {
-          // Merely setting checked = true is not enough to trigger the pref
-          // being set; thus, we simulate the click.
-          if (!syncCheckboxes[i].checked)
-            syncCheckboxes[i].click();
-
-          syncCheckboxes[i].disabled = true;
-        }
+      if (PersonalOptions.disablePasswordManagement()) {
+        $('passwords-offersave').disabled = true;
+        $('passwords-neversave').disabled = true;
+        $('passwords-offersave').value = false;
+        $('passwords-neversave').value = true;
+        $('manage-passwords').disabled = true;
       }
     },
 
@@ -130,17 +106,13 @@
         element.classList.add('hidden');
     },
 
-    setElementClassSyncError_: function(element, visible) {
-      visible ? element.classList.add('sync-error') :
-                element.classList.remove('sync-error');
-    },
-
     setSyncEnabled_: function(enabled) {
       this.syncEnabled = enabled;
     },
 
     setSyncSetupCompleted_: function(completed) {
       this.syncSetupCompleted = completed;
+      this.setElementVisible_($('customize-sync'), completed);
     },
 
     setAccountPicture_: function(image) {
@@ -148,15 +120,12 @@
     },
 
     setSyncStatus_: function(status) {
-      $('sync-status').textContent = status;
+      $('sync-status-text').textContent = status;
     },
 
     setSyncStatusErrorVisible_: function(visible) {
-      this.setElementClassSyncError_($('sync-status'), visible);
-    },
-
-    setSyncActionLinkErrorVisible_: function(visible) {
-      this.setElementClassSyncError_($('sync-action-link'), visible);
+      visible ? $('sync-status').classList.add('sync-error') :
+                $('sync-status').classList.remove('sync-error');
     },
 
     setSyncActionLinkEnabled_: function(enabled) {
@@ -216,6 +185,15 @@
     },
   };
 
+  /**
+   * Returns whether the user should be able to manage (view and edit) their
+   * stored passwords. Password management is disabled in guest mode.
+   * @return {boolean} True if password management should be disabled.
+   */
+  PersonalOptions.disablePasswordManagement = function() {
+    return cr.commandLine.options['--bwsi'];
+  };
+
   // Forward public APIs to private implementations.
   [
     'setSyncEnabled',
@@ -223,7 +201,6 @@
     'setAccountPicture',
     'setSyncStatus',
     'setSyncStatusErrorVisible',
-    'setSyncActionLinkErrorVisible',
     'setSyncActionLinkEnabled',
     'setSyncActionLinkLabel',
     'setStartStopButtonVisible',
diff --git a/chrome/browser/resources/options/pref_ui.js b/chrome/browser/resources/options/pref_ui.js
index 0734b6b..431ffa1 100644
--- a/chrome/browser/resources/options/pref_ui.js
+++ b/chrome/browser/resources/options/pref_ui.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -50,7 +50,7 @@
 
       // Listen to user events.
       this.addEventListener(
-          'click',
+          'change',
           function(e) {
             var value = self.inverted_pref ? !self.checked : self.checked;
             switch(self.valueType) {
@@ -72,7 +72,7 @@
      */
     initializeValueType: function(valueType) {
       this.valueType = valueType || 'boolean';
-    }
+    },
   };
 
   /**
@@ -138,23 +138,15 @@
             }
           });
     },
-
-    /**
-     * Getter for preference name attribute.
-     */
-    get pref() {
-      return this.getAttribute('pref');
-    },
-
-    /**
-     * Setter for preference name attribute.
-     */
-    set pref(name) {
-      this.setAttribute('pref', name);
-    }
   };
 
   /**
+   * The preference name.
+   * @type {string}
+   */
+  cr.defineProperty(PrefRadio, 'pref', cr.PropertyKind.ATTR);
+
+  /**
    * The user metric string.
    * @type {string}
    */
@@ -247,40 +239,117 @@
 
   PrefRange.prototype = {
     // Set up the prototype chain
-    __proto__: PrefNumeric.prototype,
+    __proto__: HTMLInputElement.prototype,
+
+    /**
+     * The map from input range value to the corresponding preference value.
+     */
+    valueMap: undefined,
+
+    /**
+     * If true, the associated pref will be modified on each onchange event;
+     * otherwise, the pref will only be modified on the onmouseup event after
+     * the drag.
+     */
+    continuous: true,
 
     /**
      * Initialization function for the cr.ui framework.
      */
     decorate: function() {
       this.type = 'range';
-      PrefNumeric.prototype.decorate.call(this);
-      var self = this;
 
-      // Additionally change the indicator as well.
-      Preferences.getInstance().addEventListener(this.pref,
-          function(event) {
-            self.updateIndicator();
-          });
+      // Update the UI when the pref changes.
+      Preferences.getInstance().addEventListener(
+          this.pref, this.onPrefChange_.bind(this));
 
       // Listen to user events.
-      this.addEventListener('input',
-          function(e) {
-            this.updateIndicator();
-          });
+      // TODO(jhawkins): Add onmousewheel handling once the associated WK bug is
+      // fixed.
+      // https://bugs.webkit.org/show_bug.cgi?id=52256
+      this.onchange = this.onChange_.bind(this);
+      this.onkeyup = this.onmouseup = this.onInputUp_.bind(this);
     },
 
-    updateIndicator: function() {
-      if ($(this.id + '-value')) {
-        $(this.id + '-value').textContent = this.value;
-      }
-    }
+    /**
+     * Event listener that updates the UI when the underlying pref changes.
+     * @param {Event} event The event that details the pref change.
+     * @private
+     */
+    onPrefChange_: function(event) {
+      var value = event.value && event.value['value'] != undefined ?
+          event.value['value'] : event.value;
+      if (value != undefined)
+        this.value = this.valueMap ? this.valueMap.indexOf(value) : value;
+    },
+
+    /**
+     * onchange handler that sets the pref when the user changes the value of
+     * the input element.
+     * @private
+     */
+    onChange_: function(event) {
+      if (this.continuous)
+        this.setRangePref_();
+
+      this.notifyChange(this, this.mapValueToRange_(this.value));
+    },
+
+    /**
+     * Sets the integer value of |pref| to the value of this element.
+     * @private
+     */
+    setRangePref_: function() {
+      Preferences.setIntegerPref(
+          this.pref, this.mapValueToRange_(this.value), this.metric);
+    },
+
+    /**
+     * onkeyup/onmouseup handler that modifies the pref if |continuous| is
+     * false.
+     * @private
+     */
+    onInputUp_: function(event) {
+      if (!this.continuous)
+        this.setRangePref_();
+    },
+
+    /**
+     * Maps the value of this element into the range provided by the client,
+     * represented by |valueMap|.
+     * @param {number} value The value to map.
+     * @private
+     */
+    mapValueToRange_: function(value) {
+      return this.valueMap ? this.valueMap[value] : value;
+    },
+
+    /**
+     * Called when the client has specified non-continuous mode and the value of
+     * the range control changes.
+     * @param {Element} el This element.
+     * @param {number} value The value of this element.
+     */
+    notifyChange: function(el, value) {
+    },
   };
 
+  /**
+   * The preference name.
+   * @type {string}
+   */
+  cr.defineProperty(PrefRange, 'pref', cr.PropertyKind.ATTR);
+
+  /**
+   * The user metric string.
+   * @type {string}
+   */
+  cr.defineProperty(PrefRange, 'metric', cr.PropertyKind.ATTR);
+
   /////////////////////////////////////////////////////////////////////////////
   // PrefSelect class:
 
-  // Define a constructor that uses an select element as its underlying element.
+  // Define a constructor that uses a select element as its underlying element.
   var PrefSelect = cr.ui.define('select');
 
   PrefSelect.prototype = {
@@ -331,11 +400,20 @@
       // Listen to user events.
       this.addEventListener('change',
           function(e) {
+            if (!self.dataType) {
+              console.error('undefined data type for <select> pref');
+              return;
+            }
+
             switch(self.dataType) {
               case 'number':
                 Preferences.setIntegerPref(self.pref,
                     self.options[self.selectedIndex].value, self.metric);
                 break;
+              case 'double':
+                Preferences.setDoublePref(self.pref,
+                    self.options[self.selectedIndex].value, self.metric);
+                break;
               case 'boolean':
                 var option = self.options[self.selectedIndex];
                 var value = (option.value == 'true') ? true : false;
@@ -345,6 +423,9 @@
                 Preferences.setStringPref(self.pref,
                     self.options[self.selectedIndex].value, self.metric);
                 break;
+              default:
+                console.error('unknown data type for <select> pref: ' +
+                              self.dataType);
             }
           });
     },
@@ -362,6 +443,12 @@
    */
   cr.defineProperty(PrefSelect, 'metric', cr.PropertyKind.ATTR);
 
+  /**
+   * The data type for the preference options.
+   * @type {string}
+   */
+  cr.defineProperty(PrefSelect, 'dataType', cr.PropertyKind.ATTR);
+
   /////////////////////////////////////////////////////////////////////////////
   // PrefTextField class:
 
diff --git a/chrome/browser/resources/options/preferences.js b/chrome/browser/resources/options/preferences.js
index 207a6f5..44d10e0 100644
--- a/chrome/browser/resources/options/preferences.js
+++ b/chrome/browser/resources/options/preferences.js
@@ -44,9 +44,9 @@
    * @param {string} metric User metrics identifier.
    */
   Preferences.setBooleanPref = function (name, value, metric) {
-    var arguments = [name, value ? 'true' : 'false'];
-    if (metric != undefined) arguments.push(metric);
-    chrome.send('setBooleanPref', arguments);
+    var argumentList = [name, Boolean(value)];
+    if (metric != undefined) argumentList.push(metric);
+    chrome.send('setBooleanPref', argumentList);
   };
 
   /**
@@ -57,9 +57,22 @@
    * @param {string} metric User metrics identifier.
    */
   Preferences.setIntegerPref = function(name, value, metric) {
-    var arguments = [name, String(value)];
-    if (metric != undefined) arguments.push(metric);
-    chrome.send('setIntegerPref', arguments);
+    var argumentList = [name, Number(value)];
+    if (metric != undefined) argumentList.push(metric);
+    chrome.send('setIntegerPref', argumentList);
+  };
+
+  /**
+   * Sets value of a double-valued preference.
+   * and signals its changed value.
+   * @param {string} name Preference name.
+   * @param {number} value New preference value.
+   * @param {string} metric User metrics identifier.
+   */
+  Preferences.setDoublePref = function(name, value, metric) {
+    var argumentList = [name, Number(value)];
+    if (metric != undefined) argumentList.push(metric);
+    chrome.send('setDoublePref', argumentList);
   };
 
   /**
@@ -70,22 +83,22 @@
    * @param {string} metric User metrics identifier.
    */
   Preferences.setStringPref = function(name, value, metric) {
-    var arguments = [name, value];
-    if (metric != undefined) arguments.push(metric);
-    chrome.send('setStringPref', arguments);
+    var argumentList = [name, String(value)];
+    if (metric != undefined) argumentList.push(metric);
+    chrome.send('setStringPref', argumentList);
   };
 
   /**
-   * Sets value of a JSON preference.
+   * Sets value of a JSON list preference.
    * and signals its changed value.
    * @param {string} name Preference name.
-   * @param {string} value New preference value.
+   * @param {Array} value New preference value.
    * @param {string} metric User metrics identifier.
    */
-  Preferences.setObjectPref = function(name, value, metric) {
-    var arguments = [name, JSON.stringify(value)];
-    if (metric != undefined) arguments.push(metric);
-    chrome.send('setObjectPref', arguments);
+  Preferences.setListPref = function(name, value, metric) {
+    var argumentList = [name, JSON.stringify(value)];
+    if (metric != undefined) argumentList.push(metric);
+    chrome.send('setListPref', argumentList);
   };
 
   /**
@@ -94,9 +107,9 @@
    * @param {string} metric User metrics identifier.
    */
   Preferences.clearPref = function(name, metric) {
-    var arguments = [name];
-    if (metric != undefined) arguments.push(metric);
-    chrome.send('clearPref', arguments);
+    var argumentList = [name];
+    if (metric != undefined) argumentList.push(metric);
+    chrome.send('clearPref', argumentList);
   };
 
   Preferences.prototype = {
@@ -177,4 +190,3 @@
   };
 
 });
-
diff --git a/chrome/browser/resources/options/search_engine_manager.css b/chrome/browser/resources/options/search_engine_manager.css
index 1eac1c4..fc94232 100644
--- a/chrome/browser/resources/options/search_engine_manager.css
+++ b/chrome/browser/resources/options/search_engine_manager.css
@@ -1,54 +1,62 @@
-#searchEngineList {
-  -webkit-border-radius: 2px;
-  border-bottom: 1px solid #d9d9d9;
-  height: auto;
-}
-
-#searchEngineManagerPage .left-side-table {
-  margin-top: 12px;
-}
-
-#searchEngineList .heading {
-  -webkit-border-radius: 2px;
-  color: black;
-  border-bottom: 1px solid #d9d9d9;
-}
-
-#searchEngineList .heading:not(:nth-child(2)) {
-  border-top: 1px solid #d9d9d9;
-}
-
-#searchEngineList .heading .name {
-  font-weight: bold;
-}
-
-#searchEngineList > div:not(.heading) {
-  border-left: 1px solid #d9d9d9;
-  border-right: 1px solid #d9d9d9;
-}
-
-#searchEngineList > div, #searchEngineHeading {
+.search-engine-list > div {
   display: -webkit-box;
 }
 
-#searchEngineList .name {
-  box-sizing: border-box;
-  width: 50%;
+.search-engine-list .favicon {
+  padding: 1px 7px 0px 7px;
+  height: 16px;
 }
 
-#searchEngineList .keyword {
+.search-engine-list .name-column {
+  -webkit-box-align: center;
+  -webkit-padding-end: 1ex;
+  box-sizing: border-box;
+  display: -webkit-box;
+  width: 37%;
+}
+
+.search-engine-list .name-column :last-child {
   -webkit-box-flex: 1;
 }
 
-#searchEngineList > div:not(.heading) .keyword {
+.search-engine-list .keyword-column {
+  width: 26%;
+}
+
+.search-engine-list .url-column {
+  width: 37%;
+}
+
+.search-engine-list .keyword-column,
+.search-engine-list .url-column {
+  -webkit-padding-end: 1ex;
   color: #666666;
 }
 
-#searchEngineList .default {
+.search-engine-list .default .name-column,
+.search-engine-list .default .keyword-column {
   font-weight: bold;
 }
 
-#searchEngineList .name, #searchEngineList .keyword {
-  overflow: hidden;
-  text-overflow: ellipsis;
+/* For temporary Make Default button */
+.search-engine-list .url-column {
+  display: -webkit-box;
+  -webkit-box-align: center;
 }
+
+.search-engine-list .url-column :first-child {
+  -webkit-box-flex: 1;
+}
+
+.search-engine-list .url-column button {
+  -webkit-margin-start: 3px;
+  -webkit-margin-end: 5px;
+  background: #8aaaed;
+  color: #fff;
+  margin-top: 0;
+}
+
+.search-engine-list > :not(:hover):not([editing]) .url-column button {
+  display: none;
+}
+/* End temporary Make Default button styling */
diff --git a/chrome/browser/resources/options/search_engine_manager.html b/chrome/browser/resources/options/search_engine_manager.html
index 58d1ab1..695aaa9 100644
--- a/chrome/browser/resources/options/search_engine_manager.html
+++ b/chrome/browser/resources/options/search_engine_manager.html
@@ -1,16 +1,9 @@
 <div class="page hidden" id="searchEngineManagerPage">
   <h1 i18n-content="searchEngineManagerPage"></h1>
-  <div class="left-side-table">
-    <div>
-      <list id="searchEngineList"></list>
-    </div>
-    <div>
-      <div><button id="addSearchEngineButton"
-          i18n-content="addSearchEngineButton"></div>
-      <div><button id="editSearchEngineButton" disabled
-          i18n-content="editSearchEngineButton"></div>
-      <div><button id="makeDefaultSearchEngineButton" disabled
-          i18n-content="makeDefaultSearchEngineButton"></div>
-    </div>
-  </div>
+  <h3 i18n-content="defaultSearchEngineListTitle"></h3>
+  <list id="defaultSearchEngineList"
+      class="search-engine-list settings-list"></list>
+  <h3 i18n-content="otherSearchEngineListTitle"></h3>
+  <list id="otherSearchEngineList"
+      class=" search-engine-list settings-list"></list>
 </div>
diff --git a/chrome/browser/resources/options/search_engine_manager.js b/chrome/browser/resources/options/search_engine_manager.js
index 7a56bad..b46f312 100644
--- a/chrome/browser/resources/options/search_engine_manager.js
+++ b/chrome/browser/resources/options/search_engine_manager.js
@@ -1,11 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 cr.define('options', function() {
   const OptionsPage = options.OptionsPage;
   const ArrayDataModel = cr.ui.ArrayDataModel;
-  const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
 
   /**
    * Encapsulated handling of search engine management page.
@@ -14,7 +13,7 @@
   function SearchEngineManager() {
     this.activeNavTab = null;
     OptionsPage.call(this, 'searchEngines',
-                     templateData.searchEngineManagerPage,
+                     templateData.searchEngineManagerPageTabTitle,
                      'searchEngineManagerPage');
   }
 
@@ -22,76 +21,72 @@
 
   SearchEngineManager.prototype = {
     __proto__: OptionsPage.prototype,
-    list_: null,
 
+    /**
+     * List for default search engine options
+     * @type {boolean}
+     * @private
+     */
+    defaultsList_: null,
+
+    /**
+     * List for other search engine options
+     * @type {boolean}
+     * @private
+     */
+    othersList_: null,
+
+    /** inheritDoc */
     initializePage: function() {
       OptionsPage.prototype.initializePage.call(this);
 
-      this.list_ = $('searchEngineList')
-      options.search_engines.SearchEngineList.decorate(this.list_);
-      var selectionModel = new ListSingleSelectionModel;
-      this.list_.selectionModel = selectionModel;
-      this.list_.autoExpands = true;
+      this.defaultsList_ = $('defaultSearchEngineList');
+      this.setUpList_(this.defaultsList_);
 
-      selectionModel.addEventListener('change',
-          this.selectionChanged_.bind(this));
+      this.othersList_ = $('otherSearchEngineList');
+      this.setUpList_(this.othersList_);
+    },
 
-      var self = this;
-      $('addSearchEngineButton').onclick = function(event) {
-        chrome.send('editSearchEngine', ["-1"]);
-        OptionsPage.showOverlay('editSearchEngineOverlay');
-      };
-      $('editSearchEngineButton').onclick = function(event) {
-        chrome.send('editSearchEngine', [self.selectedModelIndex_]);
-        OptionsPage.showOverlay('editSearchEngineOverlay');
-      };
-      $('makeDefaultSearchEngineButton').onclick = function(event) {
-        chrome.send('managerSetDefaultSearchEngine',
-                    [self.selectedModelIndex_]);
-      };
-
-      // Remove Windows-style accelerators from button labels.
-      // TODO(stuartmorgan): Remove this once the strings are updated.
-      $('addSearchEngineButton').textContent =
-          localStrings.getStringWithoutAccelerator('addSearchEngineButton');
+    /**
+     * Sets up the given list as a search engine list
+     * @param {List} list The list to set up.
+     * @private
+     */
+    setUpList_: function(list) {
+      options.search_engines.SearchEngineList.decorate(list);
+      list.autoExpands = true;
     },
 
     /**
      * Updates the search engine list with the given entries.
      * @private
-     * @param {Array} engineList List of available search engines.
+     * @param {Array} defaultEngines List of possible default search engines.
+     * @param {Array} otherEngines List of other search engines.
      */
-    updateSearchEngineList_: function(engineList) {
-      this.list_.dataModel = new ArrayDataModel(engineList);
-    },
-
-    /**
-     * Returns the currently selected list item's underlying model index.
-     * @private
-     */
-    get selectedModelIndex_() {
-      var listIndex = this.list_.selectionModel.selectedIndex;
-      return this.list_.dataModel.item(listIndex)['modelIndex'];
-    },
-
-    /**
-     * Callback from the selection model when the selection changes.
-     * @private
-     * @param {!cr.Event} e Event with change info.
-     */
-    selectionChanged_: function(e) {
-      var selectedIndex = this.list_.selectionModel.selectedIndex;
-      var engine = selectedIndex != -1 ?
-          this.list_.dataModel.item(selectedIndex) : null;
-
-      $('editSearchEngineButton').disabled = engine == null;
-      $('makeDefaultSearchEngineButton').disabled =
-          !(engine && engine['canBeDefault']);
+    updateSearchEngineList_: function(defaultEngines, otherEngines) {
+      this.defaultsList_.dataModel = new ArrayDataModel(defaultEngines);
+      var othersModel = new ArrayDataModel(otherEngines);
+      // Add a "new engine" row.
+      othersModel.push({
+        'modelIndex': '-1'
+      });
+      this.othersList_.dataModel = othersModel;
     },
   };
 
-  SearchEngineManager.updateSearchEngineList = function(engineList) {
-    SearchEngineManager.getInstance().updateSearchEngineList_(engineList);
+  SearchEngineManager.updateSearchEngineList = function(defaultEngines,
+                                                        otherEngines) {
+    SearchEngineManager.getInstance().updateSearchEngineList_(defaultEngines,
+                                                              otherEngines);
+  };
+
+  SearchEngineManager.validityCheckCallback = function(validity, modelIndex) {
+    // Forward to both lists; the one without a matching modelIndex will ignore
+    // it.
+    SearchEngineManager.getInstance().defaultsList_.validationComplete(
+        validity, modelIndex);
+    SearchEngineManager.getInstance().othersList_.validationComplete(
+        validity, modelIndex);
   };
 
   // Export
diff --git a/chrome/browser/resources/options/search_engine_manager_engine_list.js b/chrome/browser/resources/options/search_engine_manager_engine_list.js
index 1e7d93e..f536926 100644
--- a/chrome/browser/resources/options/search_engine_manager_engine_list.js
+++ b/chrome/browser/resources/options/search_engine_manager_engine_list.js
@@ -3,10 +3,9 @@
 // found in the LICENSE file.
 
 cr.define('options.search_engines', function() {
-  const DeletableItem = options.DeletableItem;
-  const DeletableItemList = options.DeletableItemList;
-  const ListInlineHeaderSelectionController =
-      options.ListInlineHeaderSelectionController;
+  const InlineEditableItemList = options.InlineEditableItemList;
+  const InlineEditableItem = options.InlineEditableItem;
+  const ListSelectionController = cr.ui.ListSelectionController;
 
   /**
    * Creates a new search engine list item.
@@ -31,46 +30,257 @@
   };
 
   SearchEngineListItem.prototype = {
-    __proto__: DeletableItem.prototype,
+    __proto__: InlineEditableItem.prototype,
+
+    /**
+     * Input field for editing the engine name.
+     * @type {HTMLElement}
+     * @private
+     */
+    nameField_: null,
+
+    /**
+     * Input field for editing the engine keyword.
+     * @type {HTMLElement}
+     * @private
+     */
+    keywordField_: null,
+
+    /**
+     * Input field for editing the engine url.
+     * @type {HTMLElement}
+     * @private
+     */
+    urlField_: null,
+
+    /**
+     * Whether or not this is a placeholder for adding an engine.
+     * @type {boolean}
+     * @private
+     */
+    isPlaceholder_: false,
+
+    /**
+     * Whether or not an input validation request is currently outstanding.
+     * @type {boolean}
+     * @private
+     */
+    waitingForValidation_: false,
+
+    /**
+     * Whether or not the current set of input is known to be valid.
+     * @type {boolean}
+     * @private
+     */
+    currentlyValid_: false,
 
     /** @inheritDoc */
     decorate: function() {
-      DeletableItem.prototype.decorate.call(this);
+      InlineEditableItem.prototype.decorate.call(this);
 
       var engine = this.searchEngine_;
 
-      if (engine['heading'])
-        this.classList.add('heading');
-      else if (engine['default'])
+      if (engine['modelIndex'] == '-1') {
+        this.isPlaceholder_ = true;
+        engine['name'] = '';
+        engine['keyword'] = '';
+        engine['url'] = '';
+      }
+
+      this.currentlyValid_ = !this.isPlaceholder_;
+
+      if (engine['default'])
         this.classList.add('default');
 
       this.deletable = engine['canBeRemoved'];
 
-      var nameEl = this.ownerDocument.createElement('div');
-      nameEl.className = 'name';
-      if (engine['heading']) {
-        nameEl.textContent = engine['heading'];
-      } else {
-        nameEl.textContent = engine['name'];
-        nameEl.classList.add('favicon-cell');
-        nameEl.style.backgroundImage = url('chrome://favicon/iconurl/' +
-                                           engine['iconURL']);
-      }
-      this.contentElement.appendChild(nameEl);
+      // Construct the name column.
+      var nameColEl = this.ownerDocument.createElement('div');
+      nameColEl.className = 'name-column';
+      this.contentElement.appendChild(nameColEl);
 
-      var keywordEl = this.ownerDocument.createElement('div');
-      keywordEl.className = 'keyword';
-      keywordEl.textContent = engine['heading'] ?
-          localStrings.getString('searchEngineTableKeywordHeader') :
-          engine['keyword'];
+      // Add the favicon.
+      var faviconDivEl = this.ownerDocument.createElement('div');
+      faviconDivEl.className = 'favicon';
+      var imgEl = this.ownerDocument.createElement('img');
+      imgEl.src = 'chrome://favicon/iconurl/' + engine['iconURL'];
+      faviconDivEl.appendChild(imgEl);
+      nameColEl.appendChild(faviconDivEl);
+
+      var nameEl = this.createEditableTextCell(engine['name'],
+                                               this.isPlaceholder_);
+      nameColEl.appendChild(nameEl);
+
+      // Then the keyword column.
+      var keywordEl = this.createEditableTextCell(engine['keyword'],
+                                                  this.isPlaceholder_);
+      keywordEl.className = 'keyword-column';
       this.contentElement.appendChild(keywordEl);
+
+      // And the URL column.
+      var urlEl = this.createEditableTextCell(engine['url'],
+                                              this.isPlaceholder_);
+      var urlWithButtonEl = this.ownerDocument.createElement('div');
+      urlWithButtonEl.appendChild(urlEl);
+      urlWithButtonEl.className = 'url-column';
+      this.contentElement.appendChild(urlWithButtonEl);
+      // Add the Make Default button. Temporary until drag-and-drop re-ordering
+      // is implemented. When this is removed, remove the extra div above.
+      if (engine['canBeDefault']) {
+        var makeDefaultButtonEl = this.ownerDocument.createElement('button');
+        makeDefaultButtonEl.className = "raw-button";
+        makeDefaultButtonEl.textContent =
+            templateData.makeDefaultSearchEngineButton;
+        makeDefaultButtonEl.onclick = function(e) {
+          chrome.send('managerSetDefaultSearchEngine', [engine['modelIndex']]);
+        };
+        // Don't select the row when clicking the button.
+        makeDefaultButtonEl.onmousedown = function(e) {
+          e.stopPropagation();
+        };
+        urlWithButtonEl.appendChild(makeDefaultButtonEl);
+      }
+
+      // Do final adjustment to the input fields.
+      this.nameField_ = nameEl.querySelector('input');
+      this.keywordField_ = keywordEl.querySelector('input');
+      this.urlField_ = urlEl.querySelector('input');
+
+      if (engine['urlLocked'])
+        this.urlField_.disabled = true;
+
+      if (this.isPlaceholder_) {
+        this.nameField_.placeholder =
+            localStrings.getString('searchEngineTableNamePlaceholder');
+        this.keywordField_.placeholder =
+            localStrings.getString('searchEngineTableKeywordPlaceholder');
+        this.urlField_.placeholder =
+            localStrings.getString('searchEngineTableURLPlaceholder');
+      }
+
+      var fields = [ this.nameField_, this.keywordField_, this.urlField_ ];
+        for (var i = 0; i < fields.length; i++) {
+        fields[i].oninput = this.startFieldValidation_.bind(this);
+      }
+
+      // Listen for edit events.
+      this.addEventListener('edit', this.onEditStarted_.bind(this));
+      this.addEventListener('canceledit', this.onEditCancelled_.bind(this));
+      this.addEventListener('commitedit', this.onEditCommitted_.bind(this));
+    },
+
+    /** @inheritDoc */
+    get currentInputIsValid() {
+      return !this.waitingForValidation_ && this.currentlyValid_;
+    },
+
+    /** @inheritDoc */
+    get hasBeenEdited() {
+      var engine = this.searchEngine_;
+      return this.nameField_.value != engine['name'] ||
+             this.keywordField_.value != engine['keyword'] ||
+             this.urlField_.value != engine['url'];
+    },
+
+    /**
+     * Called when entering edit mode; starts an edit session in the model.
+     * @param {Event} e The edit event.
+     * @private
+     */
+    onEditStarted_: function(e) {
+      var editIndex = this.searchEngine_['modelIndex'];
+      chrome.send('editSearchEngine', [String(editIndex)]);
+      this.startFieldValidation_();
+    },
+
+    /**
+     * Called when committing an edit; updates the model.
+     * @param {Event} e The end event.
+     * @private
+     */
+    onEditCommitted_: function(e) {
+      chrome.send('searchEngineEditCompleted', this.getInputFieldValues_());
+    },
+
+    /**
+     * Called when cancelling an edit; informs the model and resets the control
+     * states.
+     * @param {Event} e The cancel event.
+     * @private
+     */
+    onEditCancelled_: function() {
+      chrome.send('searchEngineEditCancelled');
+
+      if (this.isPlaceholder_) {
+        var engine = this.searchEngine_;
+        this.nameField_.value = '';
+        this.keywordField_.value = '';
+        this.urlField_.value = '';
+      }
+      this.currentlyValid_ = !this.isPlaceholder_;
+    },
+
+    /**
+     * Returns the input field values as an array suitable for passing to
+     * chrome.send. The order of the array is important.
+     * @private
+     * @return {array} The current input field values.
+     */
+    getInputFieldValues_: function() {
+      return [ this.nameField_.value,
+               this.keywordField_.value,
+               this.urlField_.value ];
+    },
+
+    /**
+     * Begins the process of asynchronously validing the input fields.
+     * @private
+     */
+    startFieldValidation_: function() {
+      this.waitingForValidation_ = true;
+      var args = this.getInputFieldValues_();
+      args.push(this.searchEngine_['modelIndex']);
+      chrome.send('checkSearchEngineInfoValidity', args);
+    },
+
+    /**
+     * Callback for the completion of an input validition check.
+     * @param {Object} validity A dictionary of validitation results.
+     */
+    validationComplete: function(validity) {
+      this.waitingForValidation_ = false;
+      // TODO(stuartmorgan): Implement the full validation UI with
+      // checkmark/exclamation mark icons and tooltips showing the errors.
+      if (validity['name']) {
+        this.nameField_.setCustomValidity('');
+      } else {
+        this.nameField_.setCustomValidity(
+            templateData.editSearchEngineInvalidTitleToolTip);
+      }
+
+      if (validity['keyword']) {
+        this.keywordField_.setCustomValidity('');
+      } else {
+        this.keywordField_.setCustomValidity(
+            templateData.editSearchEngineInvalidKeywordToolTip);
+      }
+
+      if (validity['url']) {
+        this.urlField_.setCustomValidity('');
+      } else {
+        this.urlField_.setCustomValidity(
+            templateData.editSearchEngineInvalidURLToolTip);
+      }
+
+      this.currentlyValid_ = validity['name'] && validity['keyword'] &&
+          validity['url'];
     },
   };
 
   var SearchEngineList = cr.ui.define('list');
 
   SearchEngineList.prototype = {
-    __proto__: DeletableItemList.prototype,
+    __proto__: InlineEditableItemList.prototype,
 
     /** @inheritDoc */
     createItem: function(searchEngine) {
@@ -78,22 +288,25 @@
     },
 
     /** @inheritDoc */
-    createSelectionController: function(sm) {
-      return new ListInlineHeaderSelectionController(sm, this);
-    },
-
-    /** @inheritDoc */
     deleteItemAtIndex: function(index) {
       var modelIndex = this.dataModel.item(index)['modelIndex']
       chrome.send('removeSearchEngine', [String(modelIndex)]);
     },
 
     /**
-     * Returns true if the given item is selectable.
-     * @param {number} index The index to check.
+     * Passes the results of an input validation check to the requesting row
+     * if it's still being edited.
+     * @param {number} modelIndex The model index of the item that was checked.
+     * @param {Object} validity A dictionary of validitation results.
      */
-    canSelectIndex: function(index) {
-      return !this.dataModel.item(index).hasOwnProperty('heading');
+    validationComplete: function(validity, modelIndex) {
+      // If it's not still being edited, it no longer matters.
+      var currentSelection = this.selectedItem;
+      if (!currentSelection)
+        return;
+      var listItem = this.getListItem(currentSelection);
+      if (listItem.editing && currentSelection['modelIndex'] == modelIndex)
+        listItem.validationComplete(validity);
     },
   };
 
diff --git a/chrome/browser/resources/options/search_page.css b/chrome/browser/resources/options/search_page.css
index e5e44d6..dbb4b74 100644
--- a/chrome/browser/resources/options/search_page.css
+++ b/chrome/browser/resources/options/search_page.css
@@ -3,5 +3,30 @@
 }
 
 .search-highlighted {
-  background-color: #fff29f;
+  background-color: rgba(255, 240, 120, 0.9);
+}
+
+.search-bubble {
+  -webkit-box-shadow: 0 2px 2px #888;
+  background-color: rgba(255, 240, 120, 0.8);
+  border-radius: 6px;
+  box-shadow: 0 2px 2px #888;
+  left: 0;
+  margin: 12px 0 0;
+  padding: 4px 10px;
+  pointer-events: none;
+  position: absolute;
+  text-align: center;
+  top: -1000px;  /* minor hack: position off-screen by default */
+  width: 100px;
+}
+
+.search-bubble:after {
+  border-color: rgba(255, 240, 120, 0.9) transparent;
+  border-style: solid;
+  border-width: 0 10px 10px;
+  content: "";
+  left: 50px;
+  position: absolute;
+  top: -10px;
 }
diff --git a/chrome/browser/resources/options/search_page.html b/chrome/browser/resources/options/search_page.html
index 9c12cf2..9bc5a0b 100644
--- a/chrome/browser/resources/options/search_page.html
+++ b/chrome/browser/resources/options/search_page.html
@@ -1,8 +1,5 @@
-<div id="searchPage" class="page">
+<div id="searchPage" class="page hidden">
   <h1 i18n-content="searchPageTitle"></h1>
-  <div id="searchPageInfo">
-    <p i18n-content="searchPageInfo"></p>
-  </div>
   <div id="searchPageNoMatches">
     <p i18n-content="searchPageNoMatches"></p>
     <p><span i18n-content="searchPageHelpLabel"></span>
diff --git a/chrome/browser/resources/options/search_page.js b/chrome/browser/resources/options/search_page.js
index 965ee73..51ba027 100644
--- a/chrome/browser/resources/options/search_page.js
+++ b/chrome/browser/resources/options/search_page.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,77 @@
   const OptionsPage = options.OptionsPage;
 
   /**
+   * Encapsulated handling of a search bubble.
+   * @constructor
+   */
+  function SearchBubble(text) {
+    var el = cr.doc.createElement('div');
+    SearchBubble.decorate(el);
+    el.textContent = text;
+    return el;
+  }
+
+  SearchBubble.decorate = function(el) {
+    el.__proto__ = SearchBubble.prototype;
+    el.decorate();
+  };
+
+  SearchBubble.prototype = {
+    __proto__: HTMLDivElement.prototype,
+
+    decorate: function() {
+      this.className = 'search-bubble';
+
+      // We create a timer to periodically update the position of the bubbles.
+      // While this isn't all that desirable, it's the only sure-fire way of
+      // making sure the bubbles stay in the correct location as sections
+      // may dynamically change size at any time.
+      var self = this;
+      this.intervalId = setInterval(this.updatePosition.bind(this), 250);
+    },
+
+    /**
+     * Clear the interval timer and remove the element from the page.
+     */
+    dispose: function() {
+      clearInterval(this.intervalId);
+
+      var parent = this.parentNode;
+      if (parent)
+        parent.removeChild(this);
+    },
+
+    /**
+     * Update the position of the bubble.  Called at creation time and then
+     * periodically while the bubble remains visible.
+     */
+    updatePosition: function() {
+      // This bubble is 'owned' by the next sibling.
+      var owner = this.nextSibling;
+
+      // If there isn't an offset parent, we have nothing to do.
+      if (!owner.offsetParent)
+        return;
+
+      // Position the bubble below the location of the owner.
+      var left = owner.offsetLeft + owner.offsetWidth / 2 -
+          this.offsetWidth / 2;
+      var top = owner.offsetTop + owner.offsetHeight;
+
+      // Update the position in the CSS.  Cache the last values for
+      // best performance.
+      if (left != this.lastLeft) {
+        this.style.left = left + 'px';
+        this.lastLeft = left;
+      }
+      if (top != this.lastTop) {
+        this.style.top = top + 'px';
+        this.lastTop = top;
+      }
+    }
+  }
+
+  /**
    * Encapsulated handling of the search page.
    * @constructor
    */
@@ -36,16 +107,52 @@
       searchField.setAttribute('autosave', 'org.chromium.options.search');
       searchField.setAttribute('results', '10');
       searchField.setAttribute('incremental', 'true');
+      this.searchField = searchField;
 
       // Replace the contents of the navigation tab with the search field.
       self.tab.textContent = '';
       self.tab.appendChild(searchField);
+      self.tab.onclick = self.tab.onkeypress = undefined;
 
       // Handle search events. (No need to throttle, WebKit's search field
       // will do that automatically.)
       searchField.onsearch = function(e) {
-        self.setSearchText_(this.value);
+        self.setSearchText_(SearchPage.canonicalizeQuery(this.value));
       };
+
+      // We update the history stack every time the search field blurs. This way
+      // we get a history entry for each search, roughly, but not each letter
+      // typed.
+      searchField.onblur = function(e) {
+        var query = SearchPage.canonicalizeQuery(searchField.value);
+        if (!query)
+          return;
+
+        // Don't push the same page onto the history stack more than once (if
+        // the user clicks in the search field and away several times).
+        var currentHash = location.hash;
+        var newHash = '#' + escape(query);
+        if (currentHash == newHash)
+          return;
+
+        // If there is no hash on the current URL, the history entry has no
+        // search query. Replace the history entry with no search with an entry
+        // that does have a search. Otherwise, add it onto the history stack.
+        var historyFunction = currentHash ? window.history.pushState :
+                                            window.history.replaceState;
+        historyFunction.call(
+            window.history,
+            {pageName: self.name},
+            self.title,
+            '/' + self.name + newHash);
+      };
+
+      // Install handler for key presses.
+      document.addEventListener('keydown',
+                                this.keyDownEventHandler_.bind(this));
+
+      // Focus the search field by default.
+      searchField.focus();
     },
 
     /**
@@ -87,15 +194,15 @@
       if (!this.searchActive_ && !active)
         return;
 
-      if (this.searchActive_ != active) {
-        this.searchActive_ = active;
-        if (active) {
-          // Reset the search criteria, effectively hiding all the sections.
-          this.setSearchText_('');
-        } else {
+      this.searchActive_ = active;
+
+      if (active) {
+        var hash = location.hash;
+        if (hash)
+          this.searchField.value = unescape(hash.slice(1));
+      } else {
           // Just wipe out any active search text since it's no longer relevant.
-          $('search-field').value = '';
-        }
+        this.searchField.value = '';
       }
 
       var pagesToSearch = this.getSearchablePages_();
@@ -108,17 +215,12 @@
         // Update the visible state of all top-level elements that are not
         // sections (ie titles, button strips).  We do this before changing
         // the page visibility to avoid excessive re-draw.
-        var length = page.pageDiv.childNodes.length;
-        var childDiv;
-        for (var i = 0; i < length; i++) {
-          childDiv = page.pageDiv.childNodes[i];
-          if (childDiv.nodeType == document.ELEMENT_NODE) {
-            if (active) {
-              if (childDiv.nodeName.toLowerCase() != 'section')
-                childDiv.classList.add('search-hidden');
-            } else {
-              childDiv.classList.remove('search-hidden');
-            }
+        for (var i = 0, childDiv; childDiv = page.pageDiv.children[i]; i++) {
+          if (active) {
+            if (childDiv.tagName != 'SECTION')
+              childDiv.classList.add('search-hidden');
+          } else {
+            childDiv.classList.remove('search-hidden');
           }
         }
 
@@ -129,9 +231,13 @@
         }
       }
 
-      // After hiding all page content, remove any highlighted matches.
-      if (!active)
+      if (active) {
+        this.setSearchText_(this.searchField.value);
+      } else {
+        // After hiding all page content, remove any search results.
         this.unhighlightMatches_();
+        this.removeSearchBubbles_();
+      }
     },
 
     /**
@@ -140,10 +246,22 @@
      * @private
      */
     setSearchText_: function(text) {
-      var foundMatches = false;
+      // Toggle the search page if necessary.
+      if (text.length) {
+        if (!this.searchActive_)
+          OptionsPage.navigateToPage(this.name);
+      } else {
+        if (this.searchActive_)
+          OptionsPage.showDefaultPage();
+        return;
+      }
 
-      // Remove any highlighted matches.
+      var foundMatches = false;
+      var bubbleControls = [];
+
+      // Remove any prior search results.
       this.unhighlightMatches_();
+      this.removeSearchBubbles_();
 
       // Generate search text by applying lowercase and escaping any characters
       // that would be problematic for regular expressions.
@@ -152,12 +270,12 @@
 
       // Generate a regular expression and replace string for hilighting
       // search terms.
-      var regEx = new RegExp('(\\b' + searchText + ')', 'ig');
+      var regEx = new RegExp('(' + searchText + ')', 'ig');
       var replaceString = '<span class="search-highlighted">$1</span>';
 
       // Initialize all sections.  If the search string matches a title page,
       // show sections for that page.
-      var page, pageMatch, childDiv;
+      var page, pageMatch, childDiv, length;
       var pagesToSearch = this.getSearchablePages_();
       for (var key in pagesToSearch) {
         page = pagesToSearch[key];
@@ -167,10 +285,8 @@
         }
         if (pageMatch)
           foundMatches = true;
-        for (var i = 0; i < page.pageDiv.childNodes.length; i++) {
-          childDiv = page.pageDiv.childNodes[i];
-          if (childDiv.nodeType == document.ELEMENT_NODE &&
-              childDiv.nodeName == 'SECTION') {
+        for (var i = 0, childDiv; childDiv = page.pageDiv.children[i]; i++) {
+          if (childDiv.tagName == 'SECTION') {
             if (pageMatch) {
               childDiv.classList.remove('search-hidden');
             } else {
@@ -181,6 +297,18 @@
       }
 
       if (searchText.length) {
+        // Search all top-level sections for anchored string matches.
+        for (var key in pagesToSearch) {
+          page = pagesToSearch[key];
+          for (var i = 0, childDiv; childDiv = page.pageDiv.children[i]; i++) {
+            if (childDiv.tagName == 'SECTION' &&
+                this.performReplace_(regEx, replaceString, childDiv)) {
+              childDiv.classList.remove('search-hidden');
+              foundMatches = true;
+            }
+          }
+        }
+
         // Search all sub-pages, generating an array of top-level sections that
         // we need to make visible.
         var subPagesToSearch = this.getSearchableSubPages_();
@@ -188,44 +316,34 @@
         for (var key in subPagesToSearch) {
           page = subPagesToSearch[key];
           if (this.performReplace_(regEx, replaceString, page.pageDiv)) {
+            // Reveal the section for this search result.
             section = page.associatedSection;
             if (section)
               section.classList.remove('search-hidden');
-            controls = page.associatedControls;
+
+            // Identify any controls that should have bubbles.
+            var controls = page.associatedControls;
             if (controls) {
-              // TODO(csilv): highlight each control.
+              length = controls.length;
+              for (var i = 0; i < length; i++)
+                bubbleControls.push(controls[i]);
             }
 
             foundMatches = true;
           }
         }
-
-        // Search all top-level sections for anchored string matches.
-        for (var key in pagesToSearch) {
-          page = pagesToSearch[key];
-          for (var i = 0; i < page.pageDiv.childNodes.length; i++) {
-            childDiv = page.pageDiv.childNodes[i];
-            if (childDiv.nodeType == document.ELEMENT_NODE &&
-                childDiv.nodeName == 'SECTION' &&
-                this.performReplace_(regEx, replaceString, childDiv)) {
-              childDiv.classList.remove('search-hidden');
-              foundMatches = true;
-            }
-          }
-        }
       }
 
       // Configure elements on the search results page based on search results.
-      if (searchText.length == 0) {
-        $('searchPageInfo').classList.remove('search-hidden');
+      if (foundMatches)
         $('searchPageNoMatches').classList.add('search-hidden');
-      } else if (foundMatches) {
-        $('searchPageInfo').classList.add('search-hidden');
-        $('searchPageNoMatches').classList.add('search-hidden');
-      } else {
-        $('searchPageInfo').classList.add('search-hidden');
+      else
         $('searchPageNoMatches').classList.remove('search-hidden');
-      }
+
+      // Create search balloons for sub-page results.
+      length = bubbleControls.length;
+      for (var i = 0; i < length; i++)
+        this.createSearchBubble_(bubbleControls[i], text);
     },
 
     /**
@@ -288,9 +406,8 @@
       var elements = document.querySelectorAll('.search-highlighted');
 
       // For each element, remove the highlighting.
-      var node, parent, i, length = elements.length;
-      for (i = 0; i < length; i++) {
-        node = elements[i];
+      var parent, i;
+      for (var i = 0, node; node = elements[i]; i++) {
         parent = node.parentNode;
 
         // Replace the highlight element with the first child (the text node).
@@ -302,6 +419,37 @@
     },
 
     /**
+     * Creates a search result bubble attached to an element.
+     * @param {Element} element An HTML element, usually a button.
+     * @param {string} text A string to show in the bubble.
+     * @private
+     */
+    createSearchBubble_: function(element, text) {
+      // avoid appending multiple ballons to a button.
+      var sibling = element.previousElementSibling;
+      if (sibling && sibling.classList.contains('search-bubble'))
+        return;
+
+      var parent = element.parentElement;
+      if (parent) {
+        var bubble = new SearchBubble(text);
+        parent.insertBefore(bubble, element);
+        bubble.updatePosition();
+      }
+    },
+
+    /**
+     * Removes all search match bubbles.
+     * @private
+     */
+    removeSearchBubbles_: function() {
+      var elements = document.querySelectorAll('.search-bubble');
+      var length = elements.length;
+      for (var i = 0; i < length; i++)
+        elements[i].dispose();
+    },
+
+    /**
      * Builds a list of top-level pages to search.  Omits the search page and
      * all sub-pages.
      * @returns {Array} An array of pages to search.
@@ -338,7 +486,32 @@
           pages.push(page);
       }
       return pages;
-    }
+    },
+
+    /**
+     * A function to handle key press events.
+     * @return {Event} a keydown event.
+     * @private
+     */
+    keyDownEventHandler_: function(event) {
+      // Focus the search field on an unused forward-slash.
+      if (event.keyCode == 191 &&
+          !/INPUT|SELECT|BUTTON|TEXTAREA/.test(event.target.tagName)) {
+        this.searchField.focus();
+        event.stopPropagation();
+        event.preventDefault();
+      }
+    },
+  };
+
+  /**
+   * Standardizes a user-entered text query by removing extra whitespace.
+   * @param {string} The user-entered text.
+   * @return {string} The trimmed query.
+   */
+  SearchPage.canonicalizeQuery = function(text) {
+    // Trim beginning and ending whitespace.
+    return text.replace(/^\s+|\s+$/g, '');
   };
 
   // Export
diff --git a/chrome/browser/resources/options/select.png b/chrome/browser/resources/options/select.png
new file mode 100644
index 0000000..a510326
--- /dev/null
+++ b/chrome/browser/resources/options/select.png
Binary files differ
diff --git a/chrome/browser/resources/options/startup_page_manager.html b/chrome/browser/resources/options/startup_page_manager.html
deleted file mode 100644
index 77ad1f1..0000000
--- a/chrome/browser/resources/options/startup_page_manager.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<div id="startupPageManagerPage" class="page hidden">
-  <h1 i18n-content="startupPageManagerPage"></h1>
-  <list id="startupPagesFullList" class="settings-list"></list>
-  <button id="startupAddButton" i18n-content="startupAddButton"></button>
-</div>
diff --git a/chrome/browser/resources/options/startup_page_manager.js b/chrome/browser/resources/options/startup_page_manager.js
deleted file mode 100644
index 56771f8..0000000
--- a/chrome/browser/resources/options/startup_page_manager.js
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('options', function() {
-  const OptionsPage = options.OptionsPage;
-  const ArrayDataModel = cr.ui.ArrayDataModel;
-  const ListSelectionModel = cr.ui.ListSelectionModel;
-
-  /**
-   * Encapsulated handling of startup page management page.
-   * @constructor
-   */
-  function StartupPageManager() {
-    this.activeNavTab = null;
-    OptionsPage.call(this, 'startupPages',
-                     templateData.StartupPageManagerPage,
-                     'startupPageManagerPage');
-  }
-
-  cr.addSingletonGetter(StartupPageManager);
-
-  StartupPageManager.prototype = {
-    __proto__: OptionsPage.prototype,
-    list_: null,
-
-    initializePage: function() {
-      OptionsPage.prototype.initializePage.call(this);
-
-      var list = $('startupPagesFullList');
-      options.browser_options.StartupPageList.decorate(list);
-      list.autoExpands = true;
-      list.selectionModel = new ListSelectionModel;
-
-      // Wire up controls.
-      $('startupAddButton').onclick = function(event) {
-        OptionsPage.showOverlay('addStartupPageOverlay');
-      };
-
-      // Remove Windows-style accelerators from button labels.
-      // TODO(stuartmorgan): Remove this once the strings are updated.
-      $('startupAddButton').textContent =
-          localStrings.getStringWithoutAccelerator('startupAddButton');
-    },
-
-    /**
-     * Updates the startup pages list with the given entries.
-     * @param {Array} pages List of startup pages.
-     * @private
-     */
-    updateStartupPages_: function(pages) {
-      $('startupPagesFullList').dataModel = new ArrayDataModel(pages);
-    },
-
-    /**
-     * Adds the given startup page at the current selection point.
-     * @private
-     */
-    addStartupPage_: function(url) {
-      var firstSelection =
-          $('startupPagesFullList').selectionModel.selectedIndex;
-      chrome.send('addStartupPage', [url, String(firstSelection)]);
-    },
-  };
-
-  StartupPageManager.updateStartupPages = function(pages) {
-    StartupPageManager.getInstance().updateStartupPages_(pages);
-  };
-
-  StartupPageManager.addStartupPage = function(url) {
-    StartupPageManager.getInstance().addStartupPage_(url);
-  };
-
-  // Export
-  return {
-    StartupPageManager: StartupPageManager
-  };
-
-});
-
diff --git a/chrome/browser/resources/options/subpages_tab_controls.css b/chrome/browser/resources/options/subpages_tab_controls.css
index 5d74b6e..774520c 100644
--- a/chrome/browser/resources/options/subpages_tab_controls.css
+++ b/chrome/browser/resources/options/subpages_tab_controls.css
@@ -4,7 +4,7 @@
 found in the LICENSE file.
 */
 
-.subpages-nav-tabs .inactive-tab {
+.subpages-nav-tabs .tab {
   position: relative;
   padding: 4px 8px;
 }
@@ -21,29 +21,30 @@
 /* To avoid tabs changing size when they are clicked and their labels become
  * bold, we actually put two labels inside each tab: an inactive label and an
  * active label. Only one is visible at a time, but the bold label is used to
- * size the tab even when it's not visible. This keeps the tab size constant. */
+ * size the tab even when it's not visible. This keeps the tab size constant.
+ */
 .subpages-nav-tabs .active-tab-label {
   font-weight: bold;
 }
 
-.subpages-nav-tabs .inactive-tab-label {
+.subpages-nav-tabs .tab-label {
   position: absolute;
   top: 5px;
   left: 9px;
 }
 
-html[dir=rtl] .subpages-nav-tabs .inactive-tab-label {
+html[dir=rtl] .subpages-nav-tabs .tab-label {
   right: 9px;
 }
 
 .subpages-nav-tabs .active-tab-label,
-.subpages-nav-tabs .active-tab .inactive-tab-label {
+.subpages-nav-tabs .active-tab .tab-label {
   visibility: hidden;
 }
 
-/* .inactive-tab is not removed when .active-tab is added, so we must
- * override the hidden visibility above in the active tab case. */
-/* BUG(62409): rename .inactive-tab to help avoid this confusion */
+/* .tab is not removed when .active-tab is added, so we must
+ * override the hidden visibility above in the active tab case.
+ */
 .subpages-nav-tabs .active-tab .active-tab-label {
   visibility: visible;
 }
diff --git a/chrome/browser/resources/plugins.html b/chrome/browser/resources/plugins.html
index cb0a164..7434968 100644
--- a/chrome/browser/resources/plugins.html
+++ b/chrome/browser/resources/plugins.html
@@ -324,6 +324,18 @@
  */
 function requestPluginsData() {
   chrome.send('requestPluginsData', []);
+  chrome.send('getShowDetails', []);
+}
+
+function loadShowDetailsFromPrefs(show_details) {
+  tmiModeExpanded = show_details;
+  document.getElementById('collapse').style.display =
+      show_details ? 'inline' : 'none';
+  document.getElementById('expand').style.display =
+      show_details ? 'none' : 'inline';
+
+  document.body.className =
+      show_details ? 'showTmiMode' : 'hideTmiMode';
 }
 
 /**
@@ -334,7 +346,7 @@
 }
 
 /**
- * Called by the dom_ui_ to re-populate the page with data representing the
+ * Called by the web_ui_ to re-populate the page with data representing the
  * current state of installed plugins.
  */
 function returnPluginsData(pluginsData){
@@ -402,6 +414,8 @@
 
   document.body.className =
       tmiModeExpanded ? 'showTmiMode' : 'hideTmiMode';
+
+  chrome.send('saveShowDetailsToPrefs', [String(tmiModeExpanded)]);
 }
 
 /**
@@ -528,11 +542,6 @@
                   </tr></table></div>
                   <div><table><tr>
                     <td class="plugin-details-label"
-                        i18n-content="pluginPriority">PRIORITY:</td>
-                    <td><span dir="ltr" jscontent="priority">x</span></td>
-                  </tr></table></div>
-                  <div><table><tr>
-                    <td class="plugin-details-label"
                         i18n-content="pluginPath">PATH:</td>
                     <td><span dir="ltr" jscontent="path"></span></td>
                   </tr></table></div>
diff --git a/chrome/browser/resources/print_preview.js b/chrome/browser/resources/print_preview.js
index 38694ea..2856989 100644
--- a/chrome/browser/resources/print_preview.js
+++ b/chrome/browser/resources/print_preview.js
@@ -14,7 +14,6 @@
   });
 
   chrome.send('getPrinters');
-  chrome.send('getPreview');
 };
 
 /**
diff --git a/chrome/browser/resources/reader_out_of_date.html b/chrome/browser/resources/reader_out_of_date.html
new file mode 100644
index 0000000..df20c5b
--- /dev/null
+++ b/chrome/browser/resources/reader_out_of_date.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title i18n-content="title"></title>
+<style type="text/css">
+body {
+  background-color:#500;
+  font-family:Helvetica,Arial,sans-serif;
+  margin:0px;
+}
+.background {
+  position:absolute;
+  width:100%;
+  height:100%;
+}
+.cell {
+  padding:40px;
+}
+.box {
+  width:80%;
+  background-color:white;
+  color:black;
+  font-size:10pt;
+  line-height:16pt;
+  text-align:left;
+  padding:20px;
+  position:relative;
+  -webkit-box-shadow:3px 3px 8px #200;
+  border-radius:5px;
+}
+html[dir='rtl'] .box {
+  text-align:right;
+}
+
+.icon {
+  position:absolute;
+}
+.title {
+  margin: 0px 77px 0px;
+  font-size:18pt;
+  line-height: 140%;
+  margin-bottom:6pt;
+  font-weight:bold;
+  color:#660000;
+}
+.main {
+  margin:0px 80px 0px;
+}
+
+.submission {
+  margin:15px 5px 15px 0px;
+  padding:0px;
+}
+input {
+  margin:0px;
+}
+.proceedbutton {
+}
+</style>
+
+<script>
+function sendCommand(cmd) {
+  window.domAutomationController.setAutomationId(1);
+  window.domAutomationController.send(cmd);
+}
+
+function getChecked() {
+  for (var i = 0; i < document.form.group.length; i++) {
+    if (document.form.group[i].checked)
+      return parseInt(document.form.group[i].value);
+  }
+  return 0;
+}
+</script>
+</head>
+<body oncontextmenu="return false;">
+<div class="background"><img src="ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"></div>
+<table width="100%" cellspacing="0" cellpadding="0">
+  <td class="cell" valign="middle" align="center">
+    <div class="box">
+      <div class="icon"><img src="ssl_roadblock_icon.png" alt="Reader out of date icon" onmousedown="return false;"></div>
+      <div class="title" i18n-content="headLine"></div>
+      <div class="main">
+        <form name="form" class="submission">
+          <input type="radio" name="group" value="1" checked> <span i18n-content="update"></span><br>
+          <input type="radio" name="group" value="2"> <span i18n-content="open_with_reader"></span><br>
+          <br>
+          <input type="button" i18n-values="value:ok" name="ok" class="proceedbutton" onClick="sendCommand(getChecked());">
+          <input type="button" i18n-values="value:cancel" name="cancel" onClick="sendCommand(0);">
+        </form>
+      </div>
+  </td>
+</table>
+</body>
+</html>
diff --git a/chrome/browser/resources/safe_browsing_malware_block.html b/chrome/browser/resources/safe_browsing_malware_block.html
index c62350a..56f4eca 100644
--- a/chrome/browser/resources/safe_browsing_malware_block.html
+++ b/chrome/browser/resources/safe_browsing_malware_block.html
@@ -143,7 +143,7 @@
 
 </head>
 <body oncontextmenu="return false;">
-<div class="background"><img src="../security/resources/ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"/></div>
+<div class="background"><img src="ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"/></div>
 <table width="100%" cellspacing="0" cellpadding="0">
   <td class="cell" valign="middle" align="center">
     <div class="box">
@@ -166,7 +166,7 @@
         <label class="checkbox" for="checkreport">
           <input name="checked" id="checkreport" type="checkbox"
                  jsvalues=".checked:boxchecked" onclick="savePreference()">
-          <span i18n-content="confirm_text"></span>
+          <span i18n-values=".innerHTML:confirm_text"></span>
         </label>
       </div>
 
diff --git a/chrome/browser/resources/safe_browsing_multiple_threat_block.html b/chrome/browser/resources/safe_browsing_multiple_threat_block.html
index a8aaf70..40dd0c4 100644
--- a/chrome/browser/resources/safe_browsing_multiple_threat_block.html
+++ b/chrome/browser/resources/safe_browsing_multiple_threat_block.html
@@ -110,7 +110,7 @@
 </head>
 
 <body oncontextmenu="return false;">
-<div class="background"><img src="../security/resources/ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"/></div>
+<div class="background"><img src="ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"/></div>
 <table width="100%" cellspacing="0" cellpadding="0">
   <td class="cell" valign="middle" align="center">
     <div class="box">
diff --git a/chrome/browser/resources/safe_browsing_phishing_block.html b/chrome/browser/resources/safe_browsing_phishing_block.html
index 448548e..b39e95c 100644
--- a/chrome/browser/resources/safe_browsing_phishing_block.html
+++ b/chrome/browser/resources/safe_browsing_phishing_block.html
@@ -114,7 +114,7 @@
 
 </head>
 <body oncontextmenu="return false;">
-<div class="background"><img src="../security/resources/ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"></div>
+<div class="background"><img src="ssl_roadblock_background.png" width="100%" height="100%" alt="background" onmousedown="return false;"></div>
 <table width="100%" cellspacing="0" cellpadding="0">
   <td class="cell" valign="middle" align="center">
     <div class="box">
diff --git a/chrome/browser/resources/shared/css/throbber.css b/chrome/browser/resources/shared/css/throbber.css
new file mode 100644
index 0000000..8744040
--- /dev/null
+++ b/chrome/browser/resources/shared/css/throbber.css
@@ -0,0 +1,6 @@
+.throbber {
+  background: url('chrome://resources/images/throbber.svg');
+  display: inline-block;
+  height: 16px;
+  width: 16px;
+}
diff --git a/chrome/browser/resources/shared/images/throbber.svg b/chrome/browser/resources/shared/images/throbber.svg
new file mode 100644
index 0000000..efd7990
--- /dev/null
+++ b/chrome/browser/resources/shared/images/throbber.svg
@@ -0,0 +1,12 @@
+<svg width="16" height="16" viewBox="0 0 300 300"
+     xmlns="http://www.w3.org/2000/svg" version="1.1">
+  <path d="M 150,0
+           a 150,150 0 0,1 106.066,256.066
+           l -35.355,-35.355
+           a -100,-100 0 0,0 -70.711,-170.711 z"
+        fill="#3d7fe6">
+    <animateTransform attributeName="transform" attributeType="XML"
+           type="rotate" from="0 150 150" to="360 150 150"
+           begin="0s" dur="1s" fill="freeze" repeatCount="indefinite" />
+  </path>
+</svg>
diff --git a/chrome/browser/resources/shared/js/cr.js b/chrome/browser/resources/shared/js/cr.js
index 6686269..93c83b2 100644
--- a/chrome/browser/resources/shared/js/cr.js
+++ b/chrome/browser/resources/shared/js/cr.js
@@ -130,11 +130,9 @@
    * property.
    * @param {string} name
    * @param {cr.PropertyKind} kind
-   * @param {*} defaultValue The default value. This is only used for the ATTR
-   *    kind.
    * @return {function():*} The getter for the property.
    */
-  function getGetter(name, kind, defaultValue) {
+  function getGetter(name, kind) {
     switch (kind) {
       case PropertyKind.JS:
         var privateName = name + '_';
@@ -142,21 +140,10 @@
           return this[privateName];
         };
       case PropertyKind.ATTR:
-        // For attr with default value we return the default value if the
-        // element is missing the attribute.
-        if (defaultValue == undefined) {
-          return function() {
-            return this.getAttribute(name);
-          };
-        } else {
-          return function() {
-            // WebKit uses null for non existant attributes.
-            var value = this.getAttribute(name);
-            return value !== null ? value : defaultValue;
-          };
-        }
+        return function() {
+          return this.getAttribute(name);
+        };
       case PropertyKind.BOOL_ATTR:
-        // Boolean attributes don't support default values.
         return function() {
           return this.hasAttribute(name);
         };
@@ -170,9 +157,11 @@
    *     for.
    * @param {cr.PropertyKind} kind The kind of property we are getting the
    *     setter for.
+   * @param {function(*):void} opt_setHook A function to run after the property
+   *     is set, but before the propertyChange event is fired.
    * @return {function(*):void} The function to use as a setter.
    */
-  function getSetter(name, kind) {
+  function getSetter(name, kind, opt_setHook) {
     switch (kind) {
       case PropertyKind.JS:
         var privateName = name + '_';
@@ -180,6 +169,8 @@
           var oldValue = this[privateName];
           if (value !== oldValue) {
             this[privateName] = value;
+            if (opt_setHook)
+              opt_setHook.call(this, value, oldValue);
             dispatchPropertyChange(this, name, value, oldValue);
           }
         };
@@ -189,6 +180,8 @@
           var oldValue = this[name];
           if (value !== oldValue) {
             this.setAttribute(name, value);
+            if (opt_setHook)
+              opt_setHook.call(this, value, oldValue);
             dispatchPropertyChange(this, name, value, oldValue);
           }
         };
@@ -201,6 +194,8 @@
               this.setAttribute(name, name);
             else
               this.removeAttribute(name);
+            if (opt_setHook)
+              opt_setHook.call(this, value, oldValue);
             dispatchPropertyChange(this, name, value, oldValue);
           }
         };
@@ -210,28 +205,24 @@
   /**
    * Defines a property on an object. When the setter changes the value a
    * property change event with the type {@code name + 'Change'} is fired.
-   * @param {!Object} The object to define the property for.
-   * @param {string} The name of the property.
+   * @param {!Object} obj The object to define the property for.
+   * @param {string} name The name of the property.
    * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use.
-   * @param {*} opt_defaultValue The default value.
+   * @param {function(*):void} opt_setHook A function to run after the
+   *     property is set, but before the propertyChange event is fired.
    */
-  function defineProperty(obj, name, opt_kind, opt_default) {
+  function defineProperty(obj, name, opt_kind, opt_setHook) {
     if (typeof obj == 'function')
       obj = obj.prototype;
 
     var kind = opt_kind || PropertyKind.JS;
 
     if (!obj.__lookupGetter__(name)) {
-      // For js properties we set the default value on the prototype.
-      if (kind == PropertyKind.JS && arguments.length > 3)  {
-        var privateName = name + '_';
-        obj[privateName] = opt_default;
-      }
-      obj.__defineGetter__(name, getGetter(name, kind, opt_default));
+      obj.__defineGetter__(name, getGetter(name, kind));
     }
 
     if (!obj.__lookupSetter__(name)) {
-      obj.__defineSetter__(name, getSetter(name, kind));
+      obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));
     }
   }
 
diff --git a/chrome/browser/resources/shared/js/cr/command_line.js b/chrome/browser/resources/shared/js/cr/command_line.js
index 2333b51..3c03f93 100644
--- a/chrome/browser/resources/shared/js/cr/command_line.js
+++ b/chrome/browser/resources/shared/js/cr/command_line.js
@@ -7,7 +7,7 @@
  * command line string.
  *
  * This file depends on chrome.commandLineString, which is only set if your
- * DOM UI explicitly sets it.  The DOM UI based options dialog does this from
+ * Web UI explicitly sets it.  The Web UI based options dialog does this from
  * OptionsUI::RenderViewCreated, in options_ui.cc.
  */
 
diff --git a/chrome/browser/resources/shared/js/cr/link_controller.js b/chrome/browser/resources/shared/js/cr/link_controller.js
index 07e323f..27fc1c0 100644
--- a/chrome/browser/resources/shared/js/cr/link_controller.js
+++ b/chrome/browser/resources/shared/js/cr/link_controller.js
@@ -82,22 +82,18 @@
      */
     openUrlFromEvent: function(url, e) {
       // We only support keydown Enter and non right click events.
-      if (e.type == 'keydown') {
-        if(e.keyIdentifier != 'Enter')
-          return;
-      } else if (e.type != 'click' || e.button == 2) {
-        return;
+      if (e.type == 'keydown' && e.keyIdentifier == 'Enter' ||
+          e.button != 2) {
+        var kind;
+        var ctrl = cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey;
+
+        if (e.button == 1 || ctrl) // middle, ctrl or keyboard
+          kind = e.shiftKey ? LinkKind.FOREGROUND_TAB : LinkKind.BACKGROUND_TAB;
+        else // left or keyboard
+          kind = e.shiftKey ? LinkKind.WINDOW : LinkKind.SELF;
+
+        this.openUrls([url], kind);
       }
-
-      var kind;
-      var ctrl = cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey;
-
-      if (e.button == 1 || ctrl) // middle, ctrl or keyboard
-        kind = e.shiftKey ? LinkKind.FOREGROUND_TAB : LinkKind.BACKGROUND_TAB;
-      else // left or keyboard
-        kind = e.shiftKey ? LinkKind.WINDOW : LinkKind.SELF;
-
-      this.openUrls([url], kind);
     },
 
 
diff --git a/chrome/browser/resources/shared/js/cr/ui/list.js b/chrome/browser/resources/shared/js/cr/ui/list.js
index 6fbe1cc..a4cd4cb 100644
--- a/chrome/browser/resources/shared/js/cr/ui/list.js
+++ b/chrome/browser/resources/shared/js/cr/ui/list.js
@@ -46,10 +46,11 @@
     if (!opt_item)
       list.appendChild(item);
 
+    var rect = item.getBoundingClientRect();
     var cs = getComputedStyle(item);
     var mt = parseFloat(cs.marginTop);
     var mb = parseFloat(cs.marginBottom);
-    var h = item.offsetHeight;
+    var h = rect.height;
 
     // Handle margin collapsing.
     if (mt < 0 && mb < 0) {
@@ -273,6 +274,8 @@
       this.addEventListener('mousedown', this.handleMouseDownUp_);
       this.addEventListener('mouseup', this.handleMouseDownUp_);
       this.addEventListener('keydown', this.handleKeyDown);
+      this.addEventListener('focus', this.handleElementFocus_, true);
+      this.addEventListener('blur', this.handleElementBlur_, true);
       this.addEventListener('scroll', this.redraw.bind(this));
 
       // Make list focusable
@@ -281,7 +284,7 @@
     },
 
     /**
-     * Returns the height of an item, measuring it if necessary.
+     * @return {number} The height of an item, measuring it if necessary.
      * @private
      */
     getItemHeight_: function() {
@@ -327,6 +330,56 @@
     },
 
     /**
+     * Called when an element in the list is focused. Marks the list as having
+     * a focused element, and dispatches an event if it didn't have focus.
+     * @param {Event} e The focus event.
+     * @private
+     */
+    handleElementFocus_: function(e) {
+      if (!this.hasElementFocus) {
+        this.hasElementFocus = true;
+        // Force styles based on hasElementFocus to take effect.
+        this.forceRepaint_();
+      }
+    },
+
+    /**
+     * Called when an element in the list is blurred. If focus moves outside
+     * the list, marks the list as no longer having focus and dispatches an
+     * event.
+     * @param {Event} e The blur event.
+     * @private
+     */
+    handleElementBlur_: function(e) {
+      // When the blur event happens we do not know who is getting focus so we
+      // delay this a bit until we know if the new focus node is outside the
+      // list.
+      var list = this;
+      var doc = e.target.ownerDocument;
+      window.setTimeout(function() {
+        var activeElement = doc.activeElement;
+        if (!list.contains(activeElement)) {
+          list.hasElementFocus = false;
+          // Force styles based on hasElementFocus to take effect.
+          list.forceRepaint_();
+        }
+      });
+    },
+
+    /**
+     * Forces a repaint of the list. Changing custom attributes, even if there
+     * are style rules depending on them, doesn't cause a repaint
+     * (<https://bugs.webkit.org/show_bug.cgi?id=12519>), so this can be called
+     * to force the list to repaint.
+     * @private
+     */
+    forceRepaint_: function(e) {
+      var dummyElement = document.createElement('div');
+      this.appendChild(dummyElement);
+      this.removeChild(dummyElement);
+    },
+
+    /**
      * Returns the list item element containing the given element, or null if
      * it doesn't belong to any list item element.
      * @param {HTMLElement} element The element.
@@ -485,11 +538,13 @@
       var paddingTop = parseFloat(getComputedStyle(this).paddingTop);
       var cs = getComputedStyle(item);
       var top = item.offsetTop - parseFloat(cs.marginTop) - paddingTop;
-      var index = Math.floor(top / this.getItemHeight_());
+      var itemHeight = this.getItemHeight_();
+      var index = Math.floor((top + itemHeight / 2) / itemHeight);
       var childIndex = index - this.firstIndex_ + 1;
       if (childIndex >= 0 && childIndex < this.children.length &&
-          this.children[childIndex] == item)
+          this.children[childIndex] == item) {
         return index;
+      }
       return -1;
     },
 
@@ -525,7 +580,6 @@
         return;
       }
 
-      console.time('redraw');
       var scrollTop = this.scrollTop;
       var clientHeight = this.clientHeight;
 
@@ -580,8 +634,6 @@
 
       this.cachedItems_ = newCachedItems;
 
-      console.timeEnd('redraw');
-
       // Measure again in case the item height has change due to a page zoom.
       //
       // The measure above is only done the first time but this measure is done
@@ -608,10 +660,26 @@
         this.redraw();
       }
     },
+
+    /**
+     * Called when a list item is activated, currently only by a double click
+     * event.
+     * @param {number} index The index of the activated item.
+     */
+    activateItemAtIndex: function(index) {
+    },
   };
 
   cr.defineProperty(List, 'disabled', cr.PropertyKind.BOOL_ATTR);
 
+  /**
+   * Whether the list or one of its descendents has focus. This is necessary
+   * because list items can contain controls that can be focused, and for some
+   * purposes (e.g., styling), the list can still be conceptually focused at
+   * that point even though it doesn't actually have the page focus.
+   */
+  cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR);
+
   return {
     List: List
   }
diff --git a/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js b/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js
index f68818c..ff3c8c6 100644
--- a/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js
+++ b/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js
@@ -140,7 +140,6 @@
         if (this.selectedIndexBefore_ != this.selectedIndex_) {
           var e = new Event('change');
           var indexes = [this.selectedIndexBefore_, this.selectedIndex_];
-          indexes.sort();
           e.changes = indexes.filter(function(index) {
             return index != -1;
           }).map(function(index) {
diff --git a/chrome/browser/resources/shared/js/cr/ui/menu.js b/chrome/browser/resources/shared/js/cr/ui/menu.js
index 1145d0f..2ba261e 100644
--- a/chrome/browser/resources/shared/js/cr/ui/menu.js
+++ b/chrome/browser/resources/shared/js/cr/ui/menu.js
@@ -17,6 +17,8 @@
   Menu.prototype = {
     __proto__: HTMLMenuElement.prototype,
 
+    selectedIndex_: -1,
+
     /**
      * Initializes the menu element.
      */
@@ -64,25 +66,6 @@
     },
 
     /**
-     * The index of the selected item.
-     * @type {boolean}
-     */
-    // getter and default value is defined using cr.defineProperty.
-    set selectedIndex(selectedIndex) {
-      if (this.selectedIndex_ != selectedIndex) {
-        var oldSelectedItem = this.selectedItem;
-        this.selectedIndex_ = selectedIndex;
-        if (oldSelectedItem)
-          oldSelectedItem.selected = false;
-        var item = this.selectedItem;
-        if (item)
-          item.selected = true;
-
-        cr.dispatchSimpleEvent(this, 'change');
-      }
-    },
-
-    /**
      * The selected menu item or null if none.
      * @type {cr.ui.MenuItem}
      */
@@ -144,11 +127,20 @@
     }
   };
 
+  function selectedIndexChanged(selectedIndex, oldSelectedIndex) {
+    var oldSelectedItem = this.chidren[oldSelectedIndex];
+    if (oldSelectedItem)
+      oldSelectedItem.selected = false;
+    var item = this.selectedItem;
+    if (item)
+      item.selected = true;
+  }
   /**
    * The selected menu item.
    * @type {number}
    */
-  cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS, -1);
+  cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS,
+      selectedIndexChanged);
 
   // Export
   return {
diff --git a/chrome/browser/resources/shared/js/cr_test.html b/chrome/browser/resources/shared/js/cr_test.html
index b20281c..f17e1b4 100644
--- a/chrome/browser/resources/shared/js/cr_test.html
+++ b/chrome/browser/resources/shared/js/cr_test.html
@@ -39,22 +39,27 @@
   cr.defineProperty(C, 'test');
 
   var obj = new C;
+  assertUndefined(obj.test);
+
   obj.test = 1;
   assertEquals(1, obj.test);
   assertEquals(1, obj.test_);
 }
 
-function testDefinePropertyWithDefault() {
+function testDefinePropertyWithSetter() {
   var obj = new EventTarget;
 
-  cr.defineProperty(obj, 'test', null, 1);
-
-  assertEquals(1, obj.test);
-  assertEquals(1, obj.test_);
-
+  var hit = false;
+  function onTestSet(value, oldValue) {
+    assertEquals(obj, this);
+    assertEquals(2, this.test);
+    assertUndefined(oldValue);
+    assertEquals(2, value);
+    hit = true;
+  }
+  cr.defineProperty(obj, 'test', cr.PropertyKind.JS, onTestSet); 
   obj.test = 2;
-  assertEquals(2, obj.test);
-  assertEquals(2, obj.test_);
+  assertTrue(hit);
 }
 
 function testDefinePropertyEvent() {
@@ -82,20 +87,20 @@
 
 function testDefinePropertyEventWithDefault() {
   var obj = new EventTarget;
-  cr.defineProperty(obj, 'test', cr.PropertyKind.JS, 1);
+  cr.defineProperty(obj, 'test', cr.PropertyKind.JS);
 
   var count = 0;
   function f(e) {
     assertEquals('testChange', e.type);
     assertEquals('test', e.propertyName);
-    assertEquals(1, e.oldValue);
+    assertUndefined(e.oldValue);
     assertEquals(2, e.newValue);
     count++;
   }
 
   obj.addEventListener('testChange', f);
 
-  obj.test = 1;
+  obj.test = undefined;
   assertEquals('Should not have called the property change listener', 0, count);
 
   obj.test = 2;
@@ -119,62 +124,45 @@
   var obj = document.createElement('button');
   cr.defineProperty(HTMLButtonElement, 'test', cr.PropertyKind.ATTR);
 
+  assertEquals(null, obj.test);
+
   obj.test = 'a';
   assertEquals('a', obj.test);
   assertEquals('a', obj.getAttribute('test'));
 }
 
-function testDefinePropertyAttrWithDefault() {
+function testDefinePropertyAttrWithSetter() {
   var obj = document.createElement('div');
-  cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR, 'a');
 
-  assertEquals('a', obj.test);
-  assertFalse(obj.hasAttribute('test'));
-
+  var hit = false;
+  function onTestSet(value, oldValue) {
+    assertEquals(obj, this);
+    assertEquals(null, oldValue);
+    assertEquals('b', value);
+    assertEquals('b', this.test);
+    hit = true;
+  }
+  cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR, onTestSet);
   obj.test = 'b';
-  assertEquals('b', obj.test);
-  assertEquals('b', obj.getAttribute('test'));
+  assertTrue(hit);
 }
 
 function testDefinePropertyAttrEvent() {
   var obj = document.createElement('div');
   cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR);
-  obj.test = 'a';
 
   var count = 0;
   function f(e) {
     assertEquals('testChange', e.type);
     assertEquals('test', e.propertyName);
-    assertEquals('a', e.oldValue);
-    assertEquals('b', e.newValue);
-    count++;
-  }
-
-  obj.addEventListener('testChange', f);
-  obj.test = 'b';
-  assertEquals('b', obj.test);
-  assertEquals('Should have called the property change listener', 1, count);
-
-  obj.test = 'b';
-  assertEquals(1, count);
-}
-
-function testDefinePropertyAttrEventWithDefault() {
-  var obj = document.createElement('div');
-  cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR, 'a');
-
-  var count = 0;
-  function f(e) {
-    assertEquals('testChange', e.type);
-    assertEquals('test', e.propertyName);
-    assertEquals('a', e.oldValue);
+    assertEquals(null, e.oldValue);
     assertEquals('b', e.newValue);
     count++;
   }
 
   obj.addEventListener('testChange', f);
 
-  obj.test = 'a';
+  obj.test = null;
   assertEquals('Should not have called the property change listener', 0, count);
 
   obj.test = 'b';
@@ -223,6 +211,21 @@
   assertEquals(1, count);
 }
 
+function testDefinePropertyBoolAttrEvent() {
+  var obj = document.createElement('div');
+  var hit = false;
+  function onTestSet(value, oldValue) {
+    assertEquals(obj, this);
+    assertTrue(this.test);
+    assertFalse(oldValue);
+    assertTrue(value);
+    hit = true;
+  }
+  cr.defineProperty(obj, 'test', cr.PropertyKind.BOOL_ATTR, onTestSet);
+  obj.test = true;
+  assertTrue(hit);
+}
+
 function testAddSingletonGetter() {
   function Foo() {};
   cr.addSingletonGetter(Foo);
diff --git a/chrome/browser/resources/shared/js/util.js b/chrome/browser/resources/shared/js/util.js
index baa88af..63b3a8c 100644
--- a/chrome/browser/resources/shared/js/util.js
+++ b/chrome/browser/resources/shared/js/util.js
@@ -1,13 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 /**
  * The global object.
- * @param {!Object}
+ * @type {!Object}
  */
 const global = this;
 
+// TODO(estade): This should be removed and calls replaced with cr.isMac
+const IS_MAC = /^Mac/.test(navigator.platform);
+
 /**
  * Alias for document.getElementById.
  * @param {string} id The ID of the element to find.
@@ -36,7 +39,6 @@
   chrome.send(name, params);
 }
 
-
 /**
  * Generates a CSS url string.
  * @param {string} s The URL to generate the CSS url for.
@@ -70,4 +72,68 @@
     params[pair[0]] = pair[1];
   }
   return params;
- }
+}
+
+function findAncestorByClass(el, className) {
+  return findAncestor(el, function(el) {
+    if (el.classList)
+      return el.classList.contains(className);
+    return null;
+  });
+}
+
+/**
+ * Return the first ancestor for which the {@code predicate} returns true.
+ * @param {Node} node The node to check.
+ * @param {function(Node) : boolean} predicate The function that tests the
+ *     nodes.
+ * @return {Node} The found ancestor or null if not found.
+ */
+function findAncestor(node, predicate) {
+  var last = false;
+  while (node != null && !(last = predicate(node))) {
+    node = node.parentNode;
+  }
+  return last ? node : null;
+}
+
+function swapDomNodes(a, b) {
+  var afterA = a.nextSibling;
+  if (afterA == b) {
+    swapDomNodes(b, a);
+    return;
+  }
+  var aParent = a.parentNode;
+  b.parentNode.replaceChild(a, b);
+  aParent.insertBefore(b, afterA);
+}
+
+/*
+ * Handles a click or mouseup on a link. If the link points to a chrome: or
+ * file: url, then call into the browser to do the navigation.
+ * @return {Object} e The click or mouseup event.
+ */
+function handleLinkClickOrMouseUp(e) {
+  // Allow preventDefault to work.
+  if (!e.returnValue)
+    return;
+
+  var el = e.target;
+  if (el.nodeType == Node.ELEMENT_NODE &&
+      el.webkitMatchesSelector('A, A *')) {
+    while (el.tagName != 'A') {
+      el = el.parentElement;
+    }
+
+    if ((el.protocol == 'file:' || el.protocol == 'about:') &&
+        ((e.button == 0 && e.type == 'click') ||
+        (e.button == 1 && e.type == 'mouseup'))) {
+      chrome.send('navigateToUrl',
+          [el.href, e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]);
+      e.preventDefault();
+    }
+  }
+}
+
+document.addEventListener('click', handleLinkClickOrMouseUp);
+document.addEventListener('mouseup', handleLinkClickOrMouseUp);
diff --git a/chrome/browser/resources/shared_resources.grd b/chrome/browser/resources/shared_resources.grd
index 0005019..5acc08a 100644
--- a/chrome/browser/resources/shared_resources.grd
+++ b/chrome/browser/resources/shared_resources.grd
@@ -20,10 +20,14 @@
                file="shared/css/list.css" type="BINDATA" />
       <include name="IDR_SHARED_CSS_MENU"
                file="shared/css/menu.css" type="BINDATA" />
+      <include name="IDR_SHARED_CSS_THROBBER"
+               file="shared/css/throbber.css" type="BINDATA" />
       <include name="IDR_SHARED_CSS_TREE"
                file="shared/css/tree.css" type="BINDATA" />
       <include name="IDR_SHARED_CSS_TREE_JS"
                file="shared/css/tree.css.js" type="BINDATA" />
+      <include name="IDR_SHARED_IMAGES_THROBBER"
+               file="shared/images/throbber.svg" type="BINDATA" />
       <include name="IDR_SHARED_JS_CR"
                file="shared/js/cr.js" type="BINDATA" />
       <include name="IDR_SHARED_JS_CR_COMMAND_LINE"
diff --git a/chrome/browser/security/resources/ssl_error.html b/chrome/browser/resources/ssl_error.html
similarity index 100%
rename from chrome/browser/security/resources/ssl_error.html
rename to chrome/browser/resources/ssl_error.html
diff --git a/chrome/browser/security/resources/ssl_roadblock.html b/chrome/browser/resources/ssl_roadblock.html
similarity index 100%
rename from chrome/browser/security/resources/ssl_roadblock.html
rename to chrome/browser/resources/ssl_roadblock.html
diff --git a/chrome/browser/security/resources/ssl_roadblock_background.png b/chrome/browser/resources/ssl_roadblock_background.png
similarity index 100%
rename from chrome/browser/security/resources/ssl_roadblock_background.png
rename to chrome/browser/resources/ssl_roadblock_background.png
Binary files differ
diff --git a/chrome/browser/security/resources/ssl_roadblock_icon.png b/chrome/browser/resources/ssl_roadblock_icon.png
similarity index 100%
rename from chrome/browser/security/resources/ssl_roadblock_icon.png
rename to chrome/browser/resources/ssl_roadblock_icon.png
Binary files differ
diff --git a/chrome/browser/resources/sync_internals/sync_index.html b/chrome/browser/resources/sync_internals/sync_index.html
new file mode 100644
index 0000000..ccc7543
--- /dev/null
+++ b/chrome/browser/resources/sync_internals/sync_index.html
@@ -0,0 +1,363 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+<!-- If you change the title, make sure you also update
+chrome/test/functional/special_tabs.py. -->
+<title>Sync Internals</title>
+<script>
+function onLoad() {
+  chrome.send('getAboutInfo');
+  chrome.send('getNotificationState');
+  chrome.send('getRootNode');
+}
+
+function onGetAboutInfoFinished(aboutInfo) {
+  var aboutInfoDiv = document.getElementById('aboutInfo');
+  jstProcess(new JsEvalContext(aboutInfo), aboutInfoDiv);
+}
+
+function onGetNotificationStateFinished(notificationsEnabled) {
+  onSyncNotificationStateChange(notificationsEnabled);
+}
+
+function onGetRootNodeFinished(rootNodeInfo) {
+  onGetNodeByIdFinished(rootNodeInfo);
+}
+
+function onGetNodeByIdFinished(nodeInfo) {
+  var nodeBrowser = document.getElementById('nodeBrowser');
+  nodeInfo.specifics = JSON.stringify(nodeInfo.specifics);
+  jstProcess(new JsEvalContext(nodeInfo), nodeBrowser);
+}
+
+function processNodeLink(link) {
+  var id = link.text;
+  chrome.send('getNodeById', [id]);
+}
+
+function onSyncServiceStateChanged() {
+  chrome.send('getAboutInfo');
+}
+
+function onSyncNotificationStateChange(notificationsEnabled) {
+  var notificationsEnabledInfo =
+    document.getElementById('notificationsEnabledInfo');
+  jstProcess(
+      new JsEvalContext({ 'notificationsEnabled': notificationsEnabled }),
+      notificationsEnabledInfo);
+}
+
+var notificationCounts = {};
+
+function onSyncIncomingNotification(changedTypes) {
+  for (var i = 0; i < changedTypes.length; ++i) {
+    var changedType = changedTypes[i];
+    notificationCounts[changedType] = notificationCounts[changedType] || 0;
+    ++notificationCounts[changedType];
+  }
+
+  var infos = [];
+  for (var k in notificationCounts) {
+    var info = { 'modelType': k, 'notificationCount': notificationCounts[k] };
+    infos.push(info);
+  }
+
+  var notificationCountsInfo =
+    document.getElementById('notificationCountsInfo');
+  jstProcess(new JsEvalContext({ 'notificationCounts': infos }),
+             notificationCountsInfo);
+}
+
+// TODO(akalin): Do something with these notifications.
+
+function onChangesApplied(modelType, changes) {
+  console.log('onChangesApplied: ' + modelType + ': ' + JSON.stringify(changes));
+}
+
+function onChangesComplete(modelType) {
+ console.log('onChangesComplete: ' + modelType);
+}
+
+function onSyncCycleCompleted(snapshot) {
+  console.log('onSyncCycleCompleted: ' + JSON.stringify(snapshot));
+}
+
+function onAuthError(authError) {
+  console.log('onAuthError: ' + JSON.stringify(authError));
+}
+
+function onUpdatedToken(token) {
+  console.log('onUpdatedToken: ' + token);
+}
+
+function onPassphraseRequired(forDecryption) {
+  console.log('onPassphraseRequired: ' + forDecryption);
+}
+
+function onPassphraseAccepted(bootstrapToken) {
+  console.log('onPassphraseAccepted: ' + bootstrapToken);
+}
+
+function onInitializationComplete() {
+  console.log('onInitializationComplete');
+}
+
+function onPaused() {
+  console.log('onPaused');
+}
+
+function onResumed() {
+  console.log('onResumed');
+}
+
+function onStopSyncingPermanently() {
+  console.log('onStopSyncingPermanently');
+}
+
+function onClearServerDataSucceeded() {
+  console.log('onClearServerDataSucceeded');
+}
+
+function onClearServerDataFailed() {
+  console.log('onClearServerDataFailed');
+}
+</script>
+
+<style type="text/css">
+body {
+  padding: 0.75em;
+  margin: 0;
+  min-width: 45em;
+}
+
+h1 {
+  font-size: 110%;
+  font-weight: bold;
+  color: #4a8ee6;
+  letter-spacing: -1px;
+  padding: 0;
+  margin: 0;
+}
+h2 {
+  font-size: 110%;
+  letter-spacing: -1px;
+  font-weight: normal;
+  color: #4a8ee6;
+  padding: 0;
+  margin: 0;
+  padding: 0.5em 1em;
+  color: #3a75bd;
+  margin-left: -38px;
+  padding-left: 38px;
+
+  border-top: 1px solid #3a75bd;
+  padding-top: 0.5em;
+
+}
+h2:first-child {
+  border-top: 0;
+  padding-top: 0;
+}
+
+div#header {
+  padding: 0.75em 1em;
+  padding-top: 0.6em;
+  padding-left: 0;
+  margin-bottom: 0.75em;
+  position: relative;
+  overflow: hidden;
+  background: #5296de;
+  background-size: 100%;
+  border: 1px solid #3a75bd;
+  border-radius: 6px;
+  color: white;
+  text-shadow: 0 0 2px black;
+}
+div#header h1 {
+  padding-left: 37px;
+  margin: 0;
+  display: inline;
+  background: url('../../resources/shared/images/gear.png') 12px 60% no-repeat;
+  color: white;
+}
+
+.err {
+  color: red;
+}
+
+div#header p {
+  font-style: italic;
+  padding: 0;
+  margin: 0;
+  color: white;
+  padding-left: 0.4em;
+  display: inline;
+}
+
+table.list {
+  line-height: 200%;
+  border-collapse: collapse;
+  table-layout: fixed;
+}
+table.list:not([class*='filtered']) tr:nth-child(odd) td {
+  background: #eff3ff;
+}
+table.list#details2 tr:nth-child(odd) td {
+  background: #ccffcc
+}
+
+table.list td {
+  padding: 0 0.5em;
+  vertical-align: top;
+  line-height: 1.4em;
+  padding-top: 0.35em;
+}
+table.list tr td:nth-last-child(1),
+table.list tr th:nth-last-child(1) {
+  padding-right: 1em;
+}
+table.list:not([class*='filtered']) .tab .name {
+  padding-left: 1.5em;
+}
+
+table.list .name {
+}
+
+table.list .name div {
+  height: 1.6em;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+table.list .number {
+  width: 7em;
+  text-align: right;
+}
+
+table.list tr:not([class*='firstRow']) > *:nth-child(1),
+table.list tr:not([class*='firstRow']) > *:nth-child(4),
+table.list tr.firstRow th:nth-child(1),
+table.list tr.firstRow th:nth-child(2) {
+  border-right: 1px solid #b5c6de;
+}
+table.list#details .name {
+  padding-left: 25px;
+  background-position: 5px center;
+  background-repeat: no-repeat;
+}
+</style>
+
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"
+      onload="onLoad()">
+
+<div id='aboutInfo'>
+  <div id='header'>
+    <h1>Sync Internals</h1>
+    <p> Sync engine diagnostic data</p>
+  </div>
+  <div id='content'>
+    <table width="100%">
+      <tr>
+        <td width="20%">
+          <span class="desc"><h2> Summary </h2></span>
+          <strong jscontent="summary"></strong>
+        </td>
+        <td>
+          <div class="desc" jsdisplay="unrecoverable_error_detected">
+            <span class="err">Unrecoverable Error Detected!</span>
+            <div jscontent="unrecoverable_error_message"></div>
+            <div jscontent="unrecoverable_error_location"></div>
+          </div>
+        </td>
+      </tr>
+      <tr>
+        <td colspan="2">
+          <span class="desc"><h2> Sync URL </h2></span>
+          <strong jscontent="service_url"></strong>
+        </td>
+      </tr>
+    </table>
+    <br /><br /><br />
+    <h2>  </h2>
+    <table>
+      <tr>
+        <td>
+        <div class="desc"><h2> Details </h2></div>
+        <table class='list' id='details'>
+          <tr>
+            <td class='name'> Authenticated </td>
+            <td class='number'>
+              <div jscontent="authenticated"> </div>
+              <div jsdisplay="!authenticated"
+                   style="color:red"
+                   jscontent="auth_problem"></div>
+            </td>
+          </tr>
+          </tr>
+          <tr>
+            <td class='name'>Last Synced</td>
+            <td class='number' jscontent="time_since_sync"> </td>
+          </tr>
+          <tr jsselect="details">
+            <td class='name'>
+              <div jscontent="stat_name"></div>
+            </td>
+            <td class='number'>
+              <div jscontent="stat_value"></div>
+            </td>
+          </tr>
+        </table>
+      </td>
+      <td valign="top">
+        <div class="desc"><h2> Routing Info </h2></div>
+        <table class='list' id='details2'>
+          <tr jsselect="routing_info">
+            <td class ='name'>
+              <div jscontent="model_type"></div>
+            </td>
+            <td class='number'>
+              <div jscontent="group"></div>
+            </td>
+          </tr>
+        </table>
+      </td>
+    </table>
+  </div>
+</div>
+
+<div class="desc"><h2> Notifications </h2></div>
+<p id='notificationsEnabledInfo'>
+  Enabled: <span jscontent='notificationsEnabled'></span>
+</p>
+
+<table class='list' id='notificationCountsInfo'>
+  <tr jsselect='notificationCounts'>
+    <td class='name'>
+      <div jscontent='modelType'></div>
+    </td>
+    <td class='number'>
+      <div jscontent='notificationCount'></div>
+    </td>
+  </tr>
+</table>
+</td>
+
+<div class="desc"><h2> Node Browser </h2></div>
+<ul id='nodeBrowser'>
+<li>ID: <span jscontent='id'></span></li>
+<li>Modification Time: <span jscontent='modificationTime'></span></li>
+<li>Parent: <a jscontent='parentId' href="#" onclick="processNodeLink(this); return false"></a></li>
+<li>Is Folder: <span jscontent='isFolder'></span></li>
+<li>Title: <span jscontent='title'></span></li>
+<li>Type: <span jscontent='type'></span></li>
+<li>Specifics: <span jscontent='specifics'></span></li>
+<li>External ID: <span jscontent='externalId'></span></li>
+<li>Predecessor: <a jscontent='predecessorId' href="#" onclick="processNodeLink(this); return false"></a></li>
+<li>Successor: <a jscontent='successorId' href="#" onclick="processNodeLink(this); return false"></a></li>
+<li>First Child: <a jscontent='firstChildId' href="#" onclick="processNodeLink(this); return false"></a></li>
+</ul>
+
+</body>
+</html>
diff --git a/chrome/browser/resources/sync_internals_resources.grd b/chrome/browser/resources/sync_internals_resources.grd
new file mode 100644
index 0000000..1c5c98b
--- /dev/null
+++ b/chrome/browser/resources/sync_internals_resources.grd
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This comment is only here because changes to resources are not picked up
+     without changes to the corresponding grd file. -->
+<grit latest_public_release="0" current_release="1">
+  <outputs>
+    <output filename="grit/sync_internals_resources.h" type="rc_header">
+      <emit emit_type='prepend'></emit>
+    </output>
+    <!-- Note: These next two files aren't actually used by Chrome, but they're
+         needed so that Visual Studio doesn't try to continually rebuild this
+         .grd (which it will do if it can't find some relevant output files).
+         Supposedly we could update our .gyp rules to not need this, but I don't
+         know how to do it and this doesn't really cost us anything... -->
+    <output filename="grit/sync_internals_resources_map.cc" type="resource_file_map_source" />
+    <output filename="grit/sync_internals_resources_map.h" type="resource_map_header" />
+    <output filename="sync_internals_resources.pak" type="data_package" />
+  </outputs>
+  <release seq="1">
+    <includes>
+      <!-- TODO(akalin): rename back to index.html once bug 69633 is fixed. -->
+      <include name="IDR_SYNC_INTERNALS_INDEX_HTML" file="sync_internals/sync_index.html" flattenhtml="true" type="BINDATA" />
+    </includes>
+  </release>
+</grit>
diff --git a/chrome/browser/security/resources/twisty_closed.png b/chrome/browser/resources/twisty_closed.png
similarity index 100%
rename from chrome/browser/security/resources/twisty_closed.png
rename to chrome/browser/resources/twisty_closed.png
Binary files differ
diff --git a/chrome/browser/security/resources/twisty_closed_rtl.png b/chrome/browser/resources/twisty_closed_rtl.png
similarity index 100%
rename from chrome/browser/security/resources/twisty_closed_rtl.png
rename to chrome/browser/resources/twisty_closed_rtl.png
Binary files differ
diff --git a/chrome/browser/security/resources/twisty_open.png b/chrome/browser/resources/twisty_open.png
similarity index 100%
rename from chrome/browser/security/resources/twisty_open.png
rename to chrome/browser/resources/twisty_open.png
Binary files differ
diff --git a/chrome/browser/rlz/rlz.cc b/chrome/browser/rlz/rlz.cc
index e0798fc..83a55bc 100644
--- a/chrome/browser/rlz/rlz.cc
+++ b/chrome/browser/rlz/rlz.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -20,8 +20,10 @@
 #include "base/task.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/synchronization/lock.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url.h"
@@ -45,6 +47,7 @@
 // Tracks if we have tried and succeeded sending the ping. This helps us
 // decide if we need to refresh the some cached strings.
 volatile int access_values_state = ACCESS_VALUES_STALE;
+base::Lock rlz_lock;
 
 bool SendFinancialPing(const std::wstring& brand, const std::wstring& lang,
                        const std::wstring& referral, bool exclude_id) {
@@ -147,6 +150,7 @@
     std::wstring referral;
     GoogleUpdateSettings::GetReferral(&referral);
     if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
+      base::AutoLock lock(rlz_lock);
       access_values_state = ACCESS_VALUES_STALE;
       GoogleUpdateSettings::ClearReferral();
     }
@@ -168,9 +172,6 @@
   virtual ~DelayedInitTask() {
   }
   virtual void Run() {
-    // Needs to be evaluated. See http://crbug.com/62328.
-    base::ThreadRestrictions::ScopedAllowIO allow_io;
-
     // For non-interactive tests we don't do the rest of the initialization
     // because sometimes the very act of loading the dll causes QEMU to crash.
     if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(),
@@ -212,9 +213,7 @@
                                      rlz_lib::FIRST_SEARCH);
     }
     // Schedule the daily RLZ ping.
-    base::Thread* thread = g_browser_process->file_thread();
-    if (thread)
-      thread->message_loop()->PostTask(FROM_HERE, new DailyPingTask());
+    MessageLoop::current()->PostTask(FROM_HERE, new DailyPingTask());
   }
 
  private:
@@ -258,8 +257,8 @@
     new OmniBoxUsageObserver();
 
   // Schedule the delayed init items.
-  MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      new DelayedInitTask(first_run), delay);
+  BrowserThread::PostDelayedTask(
+      BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run), delay);
   return true;
 }
 
@@ -280,18 +279,40 @@
 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
                                    std::wstring* rlz) {
   static std::wstring cached_ommibox_rlz;
-  if ((rlz_lib::CHROME_OMNIBOX == point) &&
-      (access_values_state == ACCESS_VALUES_FRESH)) {
-    *rlz = cached_ommibox_rlz;
-    return true;
+  if (rlz_lib::CHROME_OMNIBOX == point) {
+    base::AutoLock lock(rlz_lock);
+    if (access_values_state == ACCESS_VALUES_FRESH) {
+      *rlz = cached_ommibox_rlz;
+      return true;
+    }
   }
+
+  // Make sure we don't access disk outside of the file context.
+  // In such case we repost the task on the right thread and return error.
+  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+    // Caching of access points is now only implemented for the CHROME_OMNIBOX.
+    // Thus it is not possible to call this function on another thread for
+    // other access points until proper caching for these has been implemented
+    // and the code that calls this function can handle synchronous fetching
+    // of the access point.
+    DCHECK_EQ(rlz_lib::CHROME_OMNIBOX, point);
+
+    BrowserThread::PostTask(
+        BrowserThread::FILE, FROM_HERE,
+        NewRunnableFunction(&RLZTracker::GetAccessPointRlz,
+                            point, &cached_ommibox_rlz));
+      rlz->erase();
+      return false;
+  }
+
   char str_rlz[kMaxRlzLength + 1];
   if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL))
     return false;
   *rlz = ASCIIToWide(std::string(str_rlz));
   if (rlz_lib::CHROME_OMNIBOX == point) {
-    access_values_state = ACCESS_VALUES_FRESH;
+    base::AutoLock lock(rlz_lock);
     cached_ommibox_rlz.assign(*rlz);
+    access_values_state = ACCESS_VALUES_FRESH;
   }
   return true;
 }
diff --git a/chrome/browser/rlz/rlz_unittest.cc b/chrome/browser/rlz/rlz_unittest.cc
index f2ca69f..1b53bf6 100644
--- a/chrome/browser/rlz/rlz_unittest.cc
+++ b/chrome/browser/rlz/rlz_unittest.cc
@@ -16,9 +16,10 @@
 // is nothing to clean.
 bool CleanValue(const wchar_t* key_name, const wchar_t* value) {
   RegKey key;
-  if (!key.Open(HKEY_CURRENT_USER, key_name, KEY_READ | KEY_WRITE))
+  if (key.Open(HKEY_CURRENT_USER, key_name, KEY_READ | KEY_WRITE) !=
+      ERROR_SUCCESS)
     return false;
-  EXPECT_TRUE(key.DeleteValue(value));
+  EXPECT_EQ(ERROR_SUCCESS, key.DeleteValue(value));
   return true;
 }
 
@@ -33,8 +34,8 @@
       rlz_lib::CHROME_OMNIBOX, rlz_lib::FIRST_SEARCH));
   const wchar_t kEvent1[] = L"C1F";
   RegKey key1;
-  EXPECT_TRUE(key1.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ));
-  EXPECT_TRUE(key1.ReadValueDW(kEvent1, &recorded_value));
+  EXPECT_EQ(ERROR_SUCCESS, key1.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ));
+  EXPECT_EQ(ERROR_SUCCESS, key1.ReadValueDW(kEvent1, &recorded_value));
   EXPECT_EQ(1, recorded_value);
   EXPECT_TRUE(CleanValue(kKeyName, kEvent1));
 
@@ -42,9 +43,9 @@
       rlz_lib::CHROME_HOME_PAGE, rlz_lib::SET_TO_GOOGLE));
   const wchar_t kEvent2[] = L"C2S";
   RegKey key2;
-  EXPECT_TRUE(key2.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ));
+  EXPECT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ));
   DWORD value = 0;
-  EXPECT_TRUE(key2.ReadValueDW(kEvent2, &recorded_value));
+  EXPECT_EQ(ERROR_SUCCESS, key2.ReadValueDW(kEvent2, &recorded_value));
   EXPECT_EQ(1, recorded_value);
   EXPECT_TRUE(CleanValue(kKeyName, kEvent2));
 }
@@ -55,8 +56,8 @@
       rlz_lib::CHROME_OMNIBOX, rlz_lib::FIRST_SEARCH));
   const wchar_t kEvent1[] = L"C1F";
   RegKey key1;
-  EXPECT_TRUE(key1.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ));
-  EXPECT_TRUE(key1.ReadValueDW(kEvent1, &recorded_value));
+  EXPECT_EQ(ERROR_SUCCESS, key1.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ));
+  EXPECT_EQ(ERROR_SUCCESS, key1.ReadValueDW(kEvent1, &recorded_value));
   EXPECT_EQ(1, recorded_value);
 
   EXPECT_TRUE(RLZTracker::ClearAllProductEvents(rlz_lib::CHROME));
diff --git a/chrome/browser/safe_browsing/OWNERS b/chrome/browser/safe_browsing/OWNERS
new file mode 100644
index 0000000..f3667cb
--- /dev/null
+++ b/chrome/browser/safe_browsing/OWNERS
@@ -0,0 +1,3 @@
+lzheng@chromium.org
+shess@chromium.org
+erikkay@chromium.org
diff --git a/chrome/browser/safe_browsing/chunk_range.cc b/chrome/browser/safe_browsing/chunk_range.cc
index b2f60ba..f389342 100644
--- a/chrome/browser/safe_browsing/chunk_range.cc
+++ b/chrome/browser/safe_browsing/chunk_range.cc
@@ -4,6 +4,8 @@
 //
 // Implementation of ChunkRange class.
 
+#include <algorithm>
+
 #include "chrome/browser/safe_browsing/chunk_range.h"
 
 #include "base/logging.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index 14aac20..6a0a99e 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,24 +9,38 @@
 #include "base/file_util_proxy.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
+#include "base/metrics/histogram.h"
 #include "base/platform_file.h"
-#include "base/ref_counted_memory.h"
 #include "base/scoped_ptr.h"
 #include "base/stl_util-inl.h"
 #include "base/task.h"
+#include "base/time.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/safe_browsing/csd.pb.h"
+#include "chrome/browser/tab_contents/provisional_load_details.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/net/http_return.h"
 #include "chrome/common/net/url_fetcher.h"
 #include "chrome/common/net/url_request_context_getter.h"
-#include "gfx/codec/png_codec.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/render_messages.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request_status.h"
-#include "third_party/skia/include/core/SkBitmap.h"
 
 namespace safe_browsing {
 
+const int ClientSideDetectionService::kMaxReportsPerInterval = 3;
+
+const base::TimeDelta ClientSideDetectionService::kReportsInterval =
+    base::TimeDelta::FromDays(1);
+const base::TimeDelta ClientSideDetectionService::kNegativeCacheInterval =
+    base::TimeDelta::FromDays(1);
+const base::TimeDelta ClientSideDetectionService::kPositiveCacheInterval =
+    base::TimeDelta::FromMinutes(30);
+
 const char ClientSideDetectionService::kClientReportPhishingUrl[] =
     "https://sb-ssl.google.com/safebrowsing/clientreport/phishing";
 const char ClientSideDetectionService::kClientModelUrl[] =
@@ -37,16 +51,91 @@
   GURL phishing_url;
 };
 
+ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time)
+    : is_phishing(phish),
+      timestamp(time) {}
+
+// ShouldClassifyUrlRequest tracks the pre-classification checks for a
+// toplevel URL that has started loading into a renderer.  When these
+// checks are complete, the renderer is notified if it should run
+// client-side phishing classification, then the ShouldClassifyUrlRequest
+// deletes itself.
+class ClientSideDetectionService::ShouldClassifyUrlRequest
+    : public NotificationObserver {
+ public:
+  ShouldClassifyUrlRequest(const GURL& url, TabContents* tab_contents)
+      : url_(url),
+        tab_contents_(tab_contents),
+        ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    registrar_.Add(this,
+                   NotificationType::TAB_CONTENTS_DESTROYED,
+                   Source<TabContents>(tab_contents));
+  }
+
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) {
+    switch (type.value) {
+      case NotificationType::TAB_CONTENTS_DESTROYED:
+        Cancel();
+        break;
+      default:
+        NOTREACHED();
+    };
+  }
+
+  void Start() {
+    // TODO(bryner): add pre-classification checks here.
+    // For now we just call Finish() asynchronously for consistency,
+    // since the pre-classification checks are asynchronous.
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    BrowserThread::PostTask(BrowserThread::UI,
+                            FROM_HERE,
+                            method_factory_.NewRunnableMethod(
+                                &ShouldClassifyUrlRequest::Finish));
+  }
+
+ private:
+  // This object always deletes itself, so make the destructor private.
+  virtual ~ShouldClassifyUrlRequest() {}
+
+  void Cancel() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    tab_contents_ = NULL;
+    Finish();
+  }
+
+  void Finish() {
+    if (tab_contents_) {
+      RenderViewHost* rvh = tab_contents_->render_view_host();
+      rvh->Send(new ViewMsg_StartPhishingDetection(rvh->routing_id(), url_));
+    }
+    delete this;
+  }
+
+  GURL url_;
+  TabContents* tab_contents_;
+  NotificationRegistrar registrar_;
+  ScopedRunnableMethodFactory<ShouldClassifyUrlRequest> method_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShouldClassifyUrlRequest);
+};
+
 ClientSideDetectionService::ClientSideDetectionService(
     const FilePath& model_path,
     URLRequestContextGetter* request_context_getter)
     : model_path_(model_path),
       model_status_(UNKNOWN_STATUS),
       model_file_(base::kInvalidPlatformFileValue),
-      model_fetcher_(NULL),
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
       ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)),
       request_context_getter_(request_context_getter) {
+  // Register to find out when pages begin loading into a renderer.
+  // When this happens, we'll start our pre-classificaton checks.
+  registrar_.Add(this,
+                 NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED,
+                 NotificationService::AllSources());
 }
 
 ClientSideDetectionService::~ClientSideDetectionService() {
@@ -92,34 +181,56 @@
 void ClientSideDetectionService::SendClientReportPhishingRequest(
     const GURL& phishing_url,
     double score,
-    SkBitmap thumbnail,
     ClientReportPhishingRequestCallback* callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   MessageLoop::current()->PostTask(
       FROM_HERE,
       method_factory_.NewRunnableMethod(
           &ClientSideDetectionService::StartClientReportPhishingRequest,
-          phishing_url, score, thumbnail, callback));
+          phishing_url, score, callback));
 }
 
 void ClientSideDetectionService::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
-  if (source == model_fetcher_) {
+  if (source == model_fetcher_.get()) {
     HandleModelResponse(source, url, status, response_code, cookies, data);
-    // The fetcher object will be invalid after this method returns.
-    model_fetcher_ = NULL;
   } else if (client_phishing_reports_.find(source) !=
              client_phishing_reports_.end()) {
     HandlePhishingVerdict(source, url, status, response_code, cookies, data);
   } else {
     NOTREACHED();
   }
-  delete source;
+}
+
+void ClientSideDetectionService::Observe(NotificationType type,
+                                         const NotificationSource& source,
+                                         const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED: {
+      // Check whether the load should trigger a phishing classification.
+      // This is true if the navigation happened in the main frame and was
+      // not an in-page navigation.
+      ProvisionalLoadDetails* load_details =
+          Details<ProvisionalLoadDetails>(details).ptr();
+
+      if (load_details->main_frame() && !load_details->in_page_navigation()) {
+        NavigationController* controller =
+            Source<NavigationController>(source).ptr();
+        ShouldClassifyUrlRequest* request =
+            new ShouldClassifyUrlRequest(load_details->url(),
+                                         controller->tab_contents());
+        request->Start();  // the request will delete itself on completion
+      }
+      break;
+    }
+    default:
+      NOTREACHED();
+  };
 }
 
 void ClientSideDetectionService::SetModelStatus(ModelStatus status) {
@@ -146,10 +257,10 @@
     SetModelStatus(READY_STATUS);
   } else if (base::PLATFORM_FILE_ERROR_NOT_FOUND == error_code) {
     // We need to fetch the model since it does not exist yet.
-    model_fetcher_ = URLFetcher::Create(0 /* ID is not used */,
-                                        GURL(kClientModelUrl),
-                                        URLFetcher::GET,
-                                        this);
+    model_fetcher_.reset(URLFetcher::Create(0 /* ID is not used */,
+                                            GURL(kClientModelUrl),
+                                            URLFetcher::GET,
+                                            this));
     model_fetcher_->set_request_context(request_context_getter_.get());
     model_fetcher_->Start();
   } else {
@@ -165,7 +276,7 @@
     base::PassPlatformFile file,
     bool created) {
   model_file_ = file.ReleaseValue();
-  base::FileUtilProxy::ReadWriteCallback* cb = callback_factory_.NewCallback(
+  base::FileUtilProxy::WriteCallback* cb = callback_factory_.NewCallback(
       &ClientSideDetectionService::WriteModelFileDone);
   if (!created ||
       base::PLATFORM_FILE_OK != error_code ||
@@ -226,17 +337,31 @@
 void ClientSideDetectionService::StartClientReportPhishingRequest(
     const GURL& phishing_url,
     double score,
-    SkBitmap thumbnail,
     ClientReportPhishingRequestCallback* callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   scoped_ptr<ClientReportPhishingRequestCallback> cb(callback);
-  // The server expects an encoded PNG image.
-  scoped_refptr<RefCountedBytes> thumbnail_data(new RefCountedBytes);
-  SkAutoLockPixels lock(thumbnail);
-  if (!thumbnail.readyToDraw() ||
-      !gfx::PNGCodec::EncodeBGRASkBitmap(thumbnail,
-                                         true /* discard_transparency */,
-                                         &thumbnail_data->data)) {
+
+  bool is_phishing;
+  if (GetCachedResult(phishing_url, &is_phishing)) {
+    VLOG(1) << "Satisfying request for " << phishing_url << " from cache";
+    UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestSatisfiedFromCache", 1);
+    cb->Run(phishing_url, is_phishing);
+    return;
+  }
+
+  // We limit the number of distinct pings to kMaxReports, but we don't count
+  // urls already in the cache against this number. We don't want to start
+  // classifying too many pages as phishing, but for those that we already
+  // think are phishing we want to give ourselves a chance to fix false
+  // positives.
+  if (cache_.find(phishing_url) != cache_.end()) {
+    VLOG(1) << "Refreshing cache for " << phishing_url;
+    UMA_HISTOGRAM_COUNTS("SBClientPhishing.CacheRefresh", 1);
+  } else if (GetNumReports() > kMaxReportsPerInterval) {
+    VLOG(1) << "Too many report phishing requests sent in the last "
+            << kReportsInterval.InHours() << " hours, not checking "
+            << phishing_url;
+    UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSent", 1);
     cb->Run(phishing_url, false);
     return;
   }
@@ -244,13 +369,10 @@
   ClientPhishingRequest request;
   request.set_url(phishing_url.spec());
   request.set_client_score(static_cast<float>(score));
-  request.set_snapshot(reinterpret_cast<const char*>(thumbnail_data->front()),
-                       thumbnail_data->size());
   std::string request_data;
   if (!request.SerializeToString(&request_data)) {
-    // For consistency, we always call the callback asynchronously, rather than
-    // directly from this method.
-    LOG(ERROR) << "Unable to serialize the CSD request. Proto file changed?";
+    UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1);
+    VLOG(1) << "Unable to serialize the CSD request. Proto file changed?";
     cb->Run(phishing_url, false);
     return;
   }
@@ -270,12 +392,15 @@
   fetcher->set_request_context(request_context_getter_.get());
   fetcher->set_upload_data("application/octet-stream", request_data);
   fetcher->Start();
+
+  // Record that we made a request
+  phishing_report_times_.push(base::Time::Now());
 }
 
 void ClientSideDetectionService::HandleModelResponse(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -306,14 +431,17 @@
 void ClientSideDetectionService::HandlePhishingVerdict(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
   ClientPhishingResponse response;
   scoped_ptr<ClientReportInfo> info(client_phishing_reports_[source]);
-  if (status.is_success() && RC_REQUEST_OK == response_code  &&
+  if (status.is_success() && RC_REQUEST_OK == response_code &&
       response.ParseFromString(data)) {
+    // Cache response, possibly flushing an old one.
+    cache_[info->phishing_url] =
+        make_linked_ptr(new CacheState(response.phishy(), base::Time::Now()));
     info->callback->Run(info->phishing_url, response.phishy());
   } else {
     DLOG(ERROR) << "Unable to get the server verdict for URL: "
@@ -321,6 +449,63 @@
     info->callback->Run(info->phishing_url, false);
   }
   client_phishing_reports_.erase(source);
+  delete source;
+}
+
+bool ClientSideDetectionService::GetCachedResult(const GURL& url,
+                                                 bool* is_phishing) {
+  UpdateCache();
+
+  PhishingCache::iterator it = cache_.find(url);
+  if (it == cache_.end()) {
+    return false;
+  }
+
+  // We still need to check if the result is valid.
+  const CacheState& cache_state = *it->second;
+  if (cache_state.is_phishing ?
+      cache_state.timestamp > base::Time::Now() - kPositiveCacheInterval :
+      cache_state.timestamp > base::Time::Now() - kNegativeCacheInterval) {
+    *is_phishing = cache_state.is_phishing;
+    return true;
+  }
+  return false;
+}
+
+void ClientSideDetectionService::UpdateCache() {
+  // Since we limit the number of requests but allow pass-through for cache
+  // refreshes, we don't want to remove elements from the cache if they
+  // could be used for this purpose even if we will not use the entry to
+  // satisfy the request from the cache.
+  base::TimeDelta positive_cache_interval =
+      std::max(kPositiveCacheInterval, kReportsInterval);
+  base::TimeDelta negative_cache_interval =
+      std::max(kNegativeCacheInterval, kReportsInterval);
+
+  // Remove elements from the cache that will no longer be used.
+  for (PhishingCache::iterator it = cache_.begin(); it != cache_.end();) {
+    const CacheState& cache_state = *it->second;
+    if (cache_state.is_phishing ?
+        cache_state.timestamp > base::Time::Now() - positive_cache_interval :
+        cache_state.timestamp > base::Time::Now() - negative_cache_interval) {
+      ++it;
+    } else {
+      cache_.erase(it++);
+    }
+  }
+}
+
+int ClientSideDetectionService::GetNumReports() {
+  base::Time cutoff = base::Time::Now() - kReportsInterval;
+
+  // Erase items older than cutoff because we will never care about them again.
+  while (!phishing_report_times_.empty() &&
+         phishing_report_times_.front() < cutoff) {
+    phishing_report_times_.pop();
+  }
+
+  // Return the number of elements that are above the cutoff.
+  return phishing_report_times_.size();
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.h b/chrome/browser/safe_browsing/client_side_detection_service.h
index 7e048e5..fcc823d 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.h
+++ b/chrome/browser/safe_browsing/client_side_detection_service.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <map>
+#include <queue>
 #include <string>
 #include <vector>
 
@@ -24,16 +25,19 @@
 #include "base/callback.h"
 #include "base/file_path.h"
 #include "base/gtest_prod_util.h"
+#include "base/linked_ptr.h"
 #include "base/platform_file.h"
 #include "base/ref_counted.h"
 #include "base/scoped_callback_factory.h"
 #include "base/scoped_ptr.h"
 #include "base/task.h"
+#include "base/time.h"
 #include "chrome/browser/safe_browsing/csd.pb.h"
 #include "chrome/common/net/url_fetcher.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
 #include "googleurl/src/gurl.h"
 
-class SkBitmap;
 class URLRequestContextGetter;
 
 namespace net {
@@ -42,7 +46,8 @@
 
 namespace safe_browsing {
 
-class ClientSideDetectionService : public URLFetcher::Delegate {
+class ClientSideDetectionService : public URLFetcher::Delegate,
+                                   public NotificationObserver {
  public:
   typedef Callback1<base::PlatformFile>::Type OpenModelDoneCallback;
 
@@ -66,6 +71,11 @@
                                   const ResponseCookies& cookies,
                                   const std::string& data);
 
+  // From the NotificationObserver interface.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
   // Gets the model file descriptor once the model is ready and stored
   // on disk.  If there was an error the callback is called and the
   // platform file is set to kInvalidPlatformFileValue. The
@@ -75,21 +85,21 @@
   void GetModelFile(OpenModelDoneCallback* callback);
 
   // Sends a request to the SafeBrowsing servers with the potentially phishing
-  // URL, the client-side phishing score, and a low resolution thumbnail.  The
-  // |phishing_url| scheme should be HTTP.  This method takes ownership of the
-  // |callback| and calls it once the result has come back from the server or
-  // if an error occurs during the fetch.  If an error occurs the phishing
-  // verdict will always be false.  The callback is always called after
-  // SendClientReportPhishingRequest() returns and on the same thread as
-  // SendClientReportPhishingRequest() was called.
+  // URL and the client-side phishing score.  The |phishing_url| scheme should
+  // be HTTP.  This method takes ownership of the |callback| and calls it once
+  // the result has come back from the server or if an error occurs during the
+  // fetch.  If an error occurs the phishing verdict will always be false.  The
+  // callback is always called after SendClientReportPhishingRequest() returns
+  // and on the same thread as SendClientReportPhishingRequest() was called.
   void SendClientReportPhishingRequest(
       const GURL& phishing_url,
       double score,
-      SkBitmap thumbnail,
       ClientReportPhishingRequestCallback* callback);
 
  private:
   friend class ClientSideDetectionServiceTest;
+  friend class ClientSideDetectionServiceHooksTest;
+  class ShouldClassifyUrlRequest;
 
   enum ModelStatus {
     // It's unclear whether or not the model was already fetched.
@@ -100,8 +110,22 @@
     ERROR_STATUS,
   };
 
+  // CacheState holds all information necessary to respond to a caller without
+  // actually making a HTTP request.
+  struct CacheState {
+    bool is_phishing;
+    base::Time timestamp;
+
+    CacheState(bool phish, base::Time time);
+  };
+  typedef std::map<GURL, linked_ptr<CacheState> > PhishingCache;
+
   static const char kClientReportPhishingUrl[];
   static const char kClientModelUrl[];
+  static const int kMaxReportsPerInterval;
+  static const base::TimeDelta kReportsInterval;
+  static const base::TimeDelta kNegativeCacheInterval;
+  static const base::TimeDelta kPositiveCacheInterval;
 
   // Use Create() method to create an instance of this object.
   ClientSideDetectionService(const FilePath& model_path,
@@ -142,7 +166,6 @@
   void StartClientReportPhishingRequest(
       const GURL& phishing_url,
       double score,
-      SkBitmap thumbnail,
       ClientReportPhishingRequestCallback* callback);
 
   // Starts getting the model file.
@@ -166,10 +189,19 @@
                              const ResponseCookies& cookies,
                              const std::string& data);
 
+  // Returns true and sets is_phishing if url is in the cache and valid.
+  bool GetCachedResult(const GURL& url, bool* is_phishing);
+
+  // Invalidate cache results which are no longer useful.
+  void UpdateCache();
+
+  // Get the number of phishing reports that we have sent over kReportsInterval
+  int GetNumReports();
+
   FilePath model_path_;
   ModelStatus model_status_;
   base::PlatformFile model_file_;
-  URLFetcher* model_fetcher_;
+  scoped_ptr<URLFetcher> model_fetcher_;
   scoped_ptr<std::string> tmp_model_string_;
   std::vector<OpenModelDoneCallback*> open_callbacks_;
 
@@ -178,6 +210,19 @@
   struct ClientReportInfo;
   std::map<const URLFetcher*, ClientReportInfo*> client_phishing_reports_;
 
+  // Cache of completed requests. Used to satisfy requests for the same urls
+  // as long as the next request falls within our caching window (which is
+  // determined by kNegativeCacheInterval and kPositiveCacheInterval). The
+  // size of this cache is limited by kMaxReportsPerDay *
+  // ceil(InDays(max(kNegativeCacheInterval, kPositiveCacheInterval))).
+  // TODO(gcasto): Serialize this so that it doesn't reset on browser restart.
+  PhishingCache cache_;
+
+  // Timestamp of when we sent a phishing request. Used to limit the number
+  // of phishing requests that we send in a day.
+  // TODO(gcasto): Serialize this so that it doesn't reset on browser restart.
+  std::queue<base::Time> phishing_report_times_;
+
   // Used to asynchronously call the callbacks for GetModelFile and
   // SendClientReportPhishingRequest.
   ScopedRunnableMethodFactory<ClientSideDetectionService> method_factory_;
@@ -191,6 +236,9 @@
   // The context we use to issue network requests.
   scoped_refptr<URLRequestContextGetter> request_context_getter_;
 
+  // Used to register for page load notifications.
+  NotificationRegistrar registrar_;
+
   DISALLOW_COPY_AND_ASSIGN(ClientSideDetectionService);
 };
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
index ca3cdc5..0e7cdbd 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <map>
+#include <queue>
 #include <string>
 
 #include "base/callback.h"
@@ -15,15 +16,19 @@
 #include "base/scoped_ptr.h"
 #include "base/scoped_temp_dir.h"
 #include "base/task.h"
+#include "base/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
 #include "chrome/browser/safe_browsing/csd.pb.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/common/net/test_url_fetcher_factory.h"
 #include "chrome/common/net/url_fetcher.h"
 #include "googleurl/src/gurl.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_test_sink.h"
 #include "net/url_request/url_request_status.h"
-#include "third_party/skia/include/core/SkBitmap.h"
 
 namespace safe_browsing {
 
@@ -63,12 +68,10 @@
   }
 
   bool SendClientReportPhishingRequest(const GURL& phishing_url,
-                                       double score,
-                                       SkBitmap thumbnail) {
+                                       double score) {
     csd_service_->SendClientReportPhishingRequest(
         phishing_url,
         score,
-        thumbnail,
         NewCallback(this, &ClientSideDetectionServiceTest::SendRequestDone));
     phishing_url_ = phishing_url;
     msg_loop_.Run();  // Waits until callback is called.
@@ -87,6 +90,66 @@
         response_data, success);
   }
 
+  int GetNumReports() {
+    return csd_service_->GetNumReports();
+  }
+
+  std::queue<base::Time>& GetPhishingReportTimes() {
+    return csd_service_->phishing_report_times_;
+  }
+
+  void SetCache(const GURL& gurl, bool is_phishing, base::Time time) {
+    csd_service_->cache_[gurl] =
+        make_linked_ptr(new ClientSideDetectionService::CacheState(is_phishing,
+                                                                   time));
+  }
+
+  void TestCache() {
+    ClientSideDetectionService::PhishingCache& cache = csd_service_->cache_;
+    base::Time now = base::Time::Now();
+    base::Time time = now - ClientSideDetectionService::kNegativeCacheInterval +
+        base::TimeDelta::FromMinutes(5);
+    cache[GURL("http://first.url.com/")] =
+        make_linked_ptr(new ClientSideDetectionService::CacheState(false,
+                                                                   time));
+
+    time = now - ClientSideDetectionService::kNegativeCacheInterval -
+        base::TimeDelta::FromHours(1);
+    cache[GURL("http://second.url.com/")] =
+        make_linked_ptr(new ClientSideDetectionService::CacheState(false,
+                                                                   time));
+
+    time = now - ClientSideDetectionService::kPositiveCacheInterval -
+        base::TimeDelta::FromMinutes(5);
+    cache[GURL("http://third.url.com/")] =
+        make_linked_ptr(new ClientSideDetectionService::CacheState(true, time));
+
+    time = now - ClientSideDetectionService::kPositiveCacheInterval +
+        base::TimeDelta::FromMinutes(5);
+    cache[GURL("http://fourth.url.com/")] =
+        make_linked_ptr(new ClientSideDetectionService::CacheState(true, time));
+
+    csd_service_->UpdateCache();
+
+    // 3 elements should be in the cache, the first, third, and fourth.
+    EXPECT_EQ(3U, cache.size());
+    EXPECT_TRUE(cache.find(GURL("http://first.url.com/")) != cache.end());
+    EXPECT_TRUE(cache.find(GURL("http://third.url.com/")) != cache.end());
+    EXPECT_TRUE(cache.find(GURL("http://fourth.url.com/")) != cache.end());
+
+    // While 3 elements remain, only the first and the fourth are actually
+    // valid.
+    bool is_phishing;
+    EXPECT_TRUE(csd_service_->GetCachedResult(GURL("http://first.url.com"),
+                                              &is_phishing));
+    EXPECT_FALSE(is_phishing);
+    EXPECT_FALSE(csd_service_->GetCachedResult(GURL("http://third.url.com"),
+                                               &is_phishing));
+    EXPECT_TRUE(csd_service_->GetCachedResult(GURL("http://fourth.url.com"),
+                                              &is_phishing));
+    EXPECT_TRUE(is_phishing);
+  }
+
  protected:
   scoped_ptr<ClientSideDetectionService> csd_service_;
   scoped_ptr<FakeURLFetcherFactory> factory_;
@@ -166,33 +229,181 @@
   csd_service_.reset(ClientSideDetectionService::Create(
       tmp_dir.path().AppendASCII("model"), NULL));
 
-  // Invalid thumbnail.
-  SkBitmap thumbnail;
   GURL url("http://a.com/");
   double score = 0.4;  // Some random client score.
-  EXPECT_FALSE(SendClientReportPhishingRequest(url, score, thumbnail));
 
-  // Valid thumbnail but the server returns an error.
-  thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
-  ASSERT_TRUE(thumbnail.allocPixels());
-  thumbnail.eraseRGB(255, 0, 0);
-  SetClientReportPhishingResponse("", false /* fail */);
-  EXPECT_FALSE(SendClientReportPhishingRequest(url, score, thumbnail));
+  base::Time before = base::Time::Now();
 
   // Invalid response body from the server.
   SetClientReportPhishingResponse("invalid proto response", true /* success */);
-  EXPECT_FALSE(SendClientReportPhishingRequest(url, score, thumbnail));
+  EXPECT_FALSE(SendClientReportPhishingRequest(url, score));
 
   // Normal behavior.
   ClientPhishingResponse response;
   response.set_phishy(true);
   SetClientReportPhishingResponse(response.SerializeAsString(),
                                   true /* success */);
-  EXPECT_TRUE(SendClientReportPhishingRequest(url, score, thumbnail));
+  EXPECT_TRUE(SendClientReportPhishingRequest(url, score));
+
+  // Caching causes this to still count as phishy.
   response.set_phishy(false);
   SetClientReportPhishingResponse(response.SerializeAsString(),
                                   true /* success */);
-  EXPECT_FALSE(SendClientReportPhishingRequest(url, score, thumbnail));
+  EXPECT_TRUE(SendClientReportPhishingRequest(url, score));
+
+  // This request will fail and should not be cached.
+  GURL second_url("http://b.com/");
+  response.set_phishy(false);
+  SetClientReportPhishingResponse(response.SerializeAsString(),
+                                  false /* success*/);
+  EXPECT_FALSE(SendClientReportPhishingRequest(second_url, score));
+
+  // Verify that the previous request was not cached.
+  response.set_phishy(true);
+  SetClientReportPhishingResponse(response.SerializeAsString(),
+                                  true /* success */);
+  EXPECT_TRUE(SendClientReportPhishingRequest(second_url, score));
+
+  // This request is blocked because it's not in the cache and we have more
+  // than 3 requests.
+  GURL third_url("http://c.com");
+  response.set_phishy(true);
+  SetClientReportPhishingResponse(response.SerializeAsString(),
+                                  true /* success */);
+  EXPECT_FALSE(SendClientReportPhishingRequest(third_url, score));
+
+  // Verify that caching still works even when new requests are blocked.
+  response.set_phishy(true);
+  SetClientReportPhishingResponse(response.SerializeAsString(),
+                                  true /* success */);
+  EXPECT_TRUE(SendClientReportPhishingRequest(url, score));
+
+  // Verify that we allow cache refreshing even when requests are blocked.
+  base::Time cache_time = base::Time::Now() - base::TimeDelta::FromHours(1);
+  SetCache(second_url, true, cache_time);
+
+  // Even though this element is in the cache, it's not currently valid so
+  // we make request and return that value instead.
+  response.set_phishy(false);
+  SetClientReportPhishingResponse(response.SerializeAsString(),
+                                  true /* success */);
+  EXPECT_FALSE(SendClientReportPhishingRequest(second_url, score));
+
+  base::Time after = base::Time::Now();
+
+  // Check that we have recorded 5 requests, all within the correct time range.
+  // The blocked request and the cached requests should not be present.
+  std::queue<base::Time>& report_times = GetPhishingReportTimes();
+  EXPECT_EQ(5U, report_times.size());
+  while (!report_times.empty()) {
+    base::Time time = report_times.back();
+    report_times.pop();
+    EXPECT_LE(before, time);
+    EXPECT_GE(after, time);
+  }
+}
+
+TEST_F(ClientSideDetectionServiceTest, GetNumReportTest) {
+  SetModelFetchResponse("bogus model", true /* success */);
+  ScopedTempDir tmp_dir;
+  ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
+  csd_service_.reset(ClientSideDetectionService::Create(
+      tmp_dir.path().AppendASCII("model"), NULL));
+
+  std::queue<base::Time>& report_times = GetPhishingReportTimes();
+  base::Time now = base::Time::Now();
+  base::TimeDelta twenty_five_hours = base::TimeDelta::FromHours(25);
+  report_times.push(now - twenty_five_hours);
+  report_times.push(now - twenty_five_hours);
+  report_times.push(now);
+  report_times.push(now);
+
+  EXPECT_EQ(2, GetNumReports());
+}
+
+TEST_F(ClientSideDetectionServiceTest, CacheTest) {
+  SetModelFetchResponse("bogus model", true /* success */);
+  ScopedTempDir tmp_dir;
+  ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
+  csd_service_.reset(ClientSideDetectionService::Create(
+      tmp_dir.path().AppendASCII("model"), NULL));
+
+  TestCache();
+}
+
+// We use a separate test fixture for testing the ClientSideDetectionService's
+// handling of load notifications from TabContents.  This uses
+// RenderViewHostTestHarness to set up a fake TabContents and related objects.
+class ClientSideDetectionServiceHooksTest : public RenderViewHostTestHarness,
+                                            public IPC::Channel::Listener {
+ public:
+  // IPC::Channel::Listener
+  virtual bool OnMessageReceived(const IPC::Message& msg) {
+    if (msg.type() == ViewMsg_StartPhishingDetection::ID) {
+      received_msg_ = msg;
+      did_receive_msg_ = true;
+      return true;
+    }
+    return false;
+  }
+
+ protected:
+  virtual void SetUp() {
+    RenderViewHostTestHarness::SetUp();
+    file_thread_.reset(new BrowserThread(BrowserThread::FILE, &message_loop_));
+    ui_thread_.reset(new BrowserThread(BrowserThread::UI, &message_loop_));
+
+    // We're not exercising model fetching here, so just set up a canned
+    // success response.
+    factory_.reset(new FakeURLFetcherFactory());
+    factory_->SetFakeResponse(ClientSideDetectionService::kClientModelUrl,
+                              "dummy model data", true);
+    URLFetcher::set_factory(factory_.get());
+
+    process()->sink().AddFilter(this);
+  }
+
+  virtual void TearDown() {
+    process()->sink().RemoveFilter(this);
+    URLFetcher::set_factory(NULL);
+    file_thread_.reset();
+    ui_thread_.reset();
+    RenderViewHostTestHarness::TearDown();
+  }
+
+  scoped_ptr<FakeURLFetcherFactory> factory_;
+  scoped_ptr<BrowserThread> ui_thread_;
+  scoped_ptr<BrowserThread> file_thread_;
+  IPC::Message received_msg_;
+  bool did_receive_msg_;
+};
+
+TEST_F(ClientSideDetectionServiceHooksTest, ShouldClassifyUrl) {
+  ScopedTempDir tmp_dir;
+  ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
+  FilePath model_path = tmp_dir.path().AppendASCII("model");
+
+  scoped_ptr<ClientSideDetectionService> csd_service(
+      ClientSideDetectionService::Create(model_path, NULL));
+
+  // Navigate the tab to a page.  We should see a StartPhishingDetection IPC.
+  did_receive_msg_ = false;
+  NavigateAndCommit(GURL("http://host.com/"));
+  // The IPC is sent asynchronously, so run the message loop to wait for
+  // the message.
+  MessageLoop::current()->RunAllPending();
+  ASSERT_TRUE(did_receive_msg_);
+
+  Tuple1<GURL> url;
+  ViewMsg_StartPhishingDetection::Read(&received_msg_, &url);
+  EXPECT_EQ(GURL("http://host.com/"), url.a);
+  EXPECT_EQ(rvh()->routing_id(), received_msg_.routing_id());
+
+  // Now try an in-page navigation.  This should not trigger an IPC.
+  did_receive_msg_ = false;
+  NavigateAndCommit(GURL("http://host.com/#foo"));
+  MessageLoop::current()->RunAllPending();
+  ASSERT_FALSE(did_receive_msg_);
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/csd.proto b/chrome/browser/safe_browsing/csd.proto
index 6fcc544..fc01f96 100644
--- a/chrome/browser/safe_browsing/csd.proto
+++ b/chrome/browser/safe_browsing/csd.proto
@@ -23,10 +23,6 @@
   // Score that was computed on the client.  Value is between 0.0 and 1.0.
   // The larger the value the more likely the url is phishing.
   required float client_score = 2;
-
-  // Thumbnail from the client.  Supports all typical image formats (png, jpg
-  // etc.).
-  required bytes snapshot = 3;
 }
 
 message ClientPhishingResponse {
diff --git a/chrome/browser/safe_browsing/filter_false_positive_perftest.cc b/chrome/browser/safe_browsing/filter_false_positive_perftest.cc
index eec1c2e..34c4512 100644
--- a/chrome/browser/safe_browsing/filter_false_positive_perftest.cc
+++ b/chrome/browser/safe_browsing/filter_false_positive_perftest.cc
@@ -52,6 +52,7 @@
 //           <url>,<weight> where weight is an integer indicating the number of
 //           unique views for the URL.
 
+#include <algorithm>
 #include <fstream>
 #include <vector>
 
@@ -380,4 +381,3 @@
             << ", per-check (us): "        << time_per_check
             << std::endl;
 }
-
diff --git a/chrome/browser/safe_browsing/malware_details.cc b/chrome/browser/safe_browsing/malware_details.cc
index b4860a2..d7b113c 100644
--- a/chrome/browser/safe_browsing/malware_details.cc
+++ b/chrome/browser/safe_browsing/malware_details.cc
@@ -11,6 +11,8 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/safe_browsing/report.pb.h"
 
+using safe_browsing::ClientMalwareReportRequest;
+
 // Create a MalwareDetails for the given tab. Runs in the UI thread.
 MalwareDetails::MalwareDetails(
     TabContents* tab_contents,
@@ -26,21 +28,46 @@
   return url.SchemeIs("http");  // TODO(panayiotis): also skip internal urls.
 }
 
-void MalwareDetails::AddNode(const std::string& url,
+// Looks for a Resource for the given url in resources_.  If found, it
+// updates |resource|. Otherwise, it creates a new message, adds it to
+// resources_ and updates |resource| to point to it.
+ClientMalwareReportRequest::Resource* MalwareDetails::FindOrCreateResource(
+    const std::string& url) {
+  ResourceMap::iterator it = resources_.find(url);
+  if (it != resources_.end()) {
+    return it->second.get();
+  }
+
+  // Create the resource for |url|.
+  int id = resources_.size();
+  linked_ptr<ClientMalwareReportRequest::Resource> new_resource(
+      new ClientMalwareReportRequest::Resource());
+  new_resource->set_url(url);
+  new_resource->set_id(id);
+  resources_[url] = new_resource;
+  return new_resource.get();
+}
+
+void MalwareDetails::AddUrl(const std::string& url,
                              const std::string& parent) {
   if (!IsPublicUrl(GURL(url)))
     return;
-  linked_ptr<safe_browsing::ClientMalwareReportRequest::Resource> resource(
-      new safe_browsing::ClientMalwareReportRequest::Resource());
-  resource->set_url(url);
-  if (!parent.empty() && IsPublicUrl(GURL(parent)))
-    resource->set_parent(parent);
-  urls_[url] = resource;
+
+  // Find (or create) the resource for the url.
+  ClientMalwareReportRequest::Resource* url_resource =
+      FindOrCreateResource(url);
+  if (!parent.empty() && IsPublicUrl(GURL(parent))) {
+    // Add the resource for the parent.
+    ClientMalwareReportRequest::Resource* parent_resource =
+        FindOrCreateResource(parent);
+    // Update the parent-child relation
+    url_resource->set_parent_id(parent_resource->id());
+  }
 }
 
 void MalwareDetails::StartCollection() {
   DVLOG(1) << "Starting to compute malware details.";
-  report_.reset(new safe_browsing::ClientMalwareReportRequest());
+  report_.reset(new ClientMalwareReportRequest());
 
   if (IsPublicUrl(resource_.url)) {
     report_->set_malware_url(resource_.url.spec());
@@ -61,28 +88,44 @@
   }
 
   // Add the nodes, starting from the page url.
-  AddNode(page_url.spec(), "");
+  AddUrl(page_url.spec(), "");
 
   // Add the resource_url and its original url, if non-empty and different.
   if (!resource_.original_url.spec().empty() &&
       resource_.url != resource_.original_url) {
     // Add original_url, as the parent of resource_url.
-    AddNode(resource_.original_url.spec(), "");
-    AddNode(resource_.url.spec(), resource_.original_url.spec());
+    AddUrl(resource_.original_url.spec(), "");
+    AddUrl(resource_.url.spec(), resource_.original_url.spec());
   } else {
-    AddNode(resource_.url.spec(), "");
+    AddUrl(resource_.url.spec(), "");
+  }
+
+  // Add the redirect urls, if non-empty. The redirect urls do not include the
+  // original url, but include the unsafe url which is the last one of the
+  // redirect urls chain
+  std::string parent_url = "";
+  // Set the original url as the parent of the first redirect url if it's not
+  // empty.
+  if (!resource_.original_url.is_empty()) {
+    parent_url = resource_.original_url.spec();
+  }
+  // Set the previous redirect url as the parent of the next one
+  for (unsigned int i = 0; i < resource_.redirect_urls.size(); ++i) {
+    AddUrl(resource_.redirect_urls[i].spec(), parent_url);
+    parent_url = resource_.redirect_urls[i].spec();
   }
 
   // Add the referrer url.
   if (nav_entry && !referrer_url.spec().empty()) {
-    AddNode(referrer_url.spec(), "");
+    AddUrl(referrer_url.spec(), "");
   }
 
-  // Add all the urls in our |urls_| map to the |report_| protobuf.
-  for (ResourceMap::const_iterator it = urls_.begin();
-       it != urls_.end(); it++) {
-    safe_browsing::ClientMalwareReportRequest::Resource* pb_resource =
-        report_->add_nodes();
+  // The |report_| protocol buffer is now generated: We add all the
+  // urls in our |resources_| maps.
+  for (ResourceMap::const_iterator it = resources_.begin();
+       it != resources_.end(); it++) {
+    ClientMalwareReportRequest::Resource* pb_resource =
+        report_->add_resources();
     pb_resource->CopyFrom(*(it->second));
   }
 }
diff --git a/chrome/browser/safe_browsing/malware_details.h b/chrome/browser/safe_browsing/malware_details.h
index 7d21dc4..bbe63e1 100644
--- a/chrome/browser/safe_browsing/malware_details.h
+++ b/chrome/browser/safe_browsing/malware_details.h
@@ -36,6 +36,7 @@
  private:
   friend class base::RefCountedThreadSafe<MalwareDetails>;
 
+  // Maps a URL to its Resource.
   typedef base::hash_map<
     std::string,
     linked_ptr<safe_browsing::ClientMalwareReportRequest::Resource> >
@@ -47,17 +48,24 @@
   // Whether the url is "public" so we can add it to the report.
   bool IsPublicUrl(const GURL& url) const;
 
-  // Adds a node to |urls_|. |parent| can be empty.
-  void AddNode(const std::string& url, const std::string& parent);
+  // Finds an existing Resource for the given url, or creates a new
+  // one if not found, and adds it to |resources_|. Returns the
+  // found/created resource.
+  safe_browsing::ClientMalwareReportRequest::Resource* FindOrCreateResource(
+      const std::string& url);
+
+  // Adds a Resource to resources_ with the given parent
+  // relationship. |parent| can be empty.
+  void AddUrl(const std::string& url, const std::string& parent);
 
   ~MalwareDetails();
 
   TabContents* tab_contents_;
   const SafeBrowsingService::UnsafeResource resource_;
 
-  // The urls that we collect. We first add them into this map and then
-  // generate a protocol buffer from it.
-  ResourceMap urls_;
+  // For every Url we collect we create a Resource message. We keep
+  // them in a map so we can avoid duplicates.
+  ResourceMap resources_;
 
   // The report protocol buffer.
   scoped_ptr<safe_browsing::ClientMalwareReportRequest> report_;
diff --git a/chrome/browser/safe_browsing/malware_details_unittest.cc b/chrome/browser/safe_browsing/malware_details_unittest.cc
index b6136c8..d5ba537 100644
--- a/chrome/browser/safe_browsing/malware_details_unittest.cc
+++ b/chrome/browser/safe_browsing/malware_details_unittest.cc
@@ -17,6 +17,10 @@
 static const char* kLandingURL = "http://www.landingpage.com/";
 static const char* kMalwareURL = "http://www.malware.com/";
 static const char* kHttpsURL = "https://www.url.com/";
+static const char* kFirstRedirectURL = "http://redirectone.com/";
+static const char* kSecondRedirectURL = "http://redirecttwo.com/";
+
+using safe_browsing::ClientMalwareReportRequest;
 
 class MalwareDetailsTest : public RenderViewHostTestHarness {
  public:
@@ -30,9 +34,9 @@
   }
 
   static bool ResourceLessThan(
-      const safe_browsing::ClientMalwareReportRequest::Resource* lhs,
-      const safe_browsing::ClientMalwareReportRequest::Resource* rhs) {
-    return lhs->url() < rhs->url();
+      const ClientMalwareReportRequest::Resource* lhs,
+      const ClientMalwareReportRequest::Resource* rhs) {
+    return lhs->id() < rhs->id();
   }
 
  protected:
@@ -47,38 +51,36 @@
     resource->render_view_id = contents_->render_view_host()->routing_id();
   }
 
-  void VerifyResults(
-      const safe_browsing::ClientMalwareReportRequest& report_pb,
-      const safe_browsing::ClientMalwareReportRequest& expected_pb) {
+  void VerifyResults(const ClientMalwareReportRequest& report_pb,
+                     const ClientMalwareReportRequest& expected_pb) {
     EXPECT_EQ(expected_pb.malware_url(), report_pb.malware_url());
     EXPECT_EQ(expected_pb.page_url(), report_pb.page_url());
     EXPECT_EQ(expected_pb.referrer_url(), report_pb.referrer_url());
 
-    ASSERT_EQ(expected_pb.nodes_size(), report_pb.nodes_size());
-    // Sort the nodes, to make the test deterministic
-    std::vector<const safe_browsing::ClientMalwareReportRequest::Resource*>
-        nodes;
-    for (int i = 0; i < report_pb.nodes_size(); ++i) {
-      const safe_browsing::ClientMalwareReportRequest::Resource& resource =
-        report_pb.nodes(i);
-      nodes.push_back(&resource);
+    ASSERT_EQ(expected_pb.resources_size(), report_pb.resources_size());
+    // Sort the resources, to make the test deterministic
+    std::vector<const ClientMalwareReportRequest::Resource*> resources;
+    for (int i = 0; i < report_pb.resources_size(); ++i) {
+      const ClientMalwareReportRequest::Resource& resource =
+          report_pb.resources(i);
+      resources.push_back(&resource);
     }
-    std::sort(nodes.begin(), nodes.end(),
+    std::sort(resources.begin(), resources.end(),
               &MalwareDetailsTest::ResourceLessThan);
 
-    std::vector<const safe_browsing::ClientMalwareReportRequest::Resource*>
-        expected;
-    for (int i = 0; i < report_pb.nodes_size(); ++i) {
-      const safe_browsing::ClientMalwareReportRequest::Resource& resource =
-        expected_pb.nodes(i);
+    std::vector<const ClientMalwareReportRequest::Resource*> expected;
+    for (int i = 0; i < report_pb.resources_size(); ++i) {
+      const ClientMalwareReportRequest::Resource& resource =
+          expected_pb.resources(i);
       expected.push_back(&resource);
     }
     std::sort(expected.begin(), expected.end(),
               &MalwareDetailsTest::ResourceLessThan);
 
     for (uint32 i = 0; i < expected.size(); ++i) {
-      EXPECT_EQ(expected[i]->url(), nodes[i]->url());
-      EXPECT_EQ(expected[i]->parent(), nodes[i]->parent());
+      EXPECT_EQ(expected[i]->id(), resources[i]->id());
+      EXPECT_EQ(expected[i]->url(), resources[i]->url());
+      EXPECT_EQ(expected[i]->parent_id(), resources[i]->parent_id());
     }
   }
 
@@ -98,19 +100,20 @@
       contents(), resource);
 
   scoped_ptr<const std::string> serialized(report->GetSerializedReport());
-  safe_browsing::ClientMalwareReportRequest actual;
+  ClientMalwareReportRequest actual;
   actual.ParseFromString(*serialized);
 
-  safe_browsing::ClientMalwareReportRequest expected;
+  ClientMalwareReportRequest expected;
   expected.set_malware_url(kMalwareURL);
   expected.set_page_url(kLandingURL);
   expected.set_referrer_url("");
 
-  safe_browsing::ClientMalwareReportRequest::Resource* node =
-      expected.add_nodes();
-  node->set_url(kLandingURL);
-  node = expected.add_nodes();
-  node->set_url(kMalwareURL);
+  ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+  pb_resource->set_id(0);
+  pb_resource->set_url(kLandingURL);
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(1);
+  pb_resource->set_url(kMalwareURL);
 
   VerifyResults(actual, expected);
 }
@@ -128,25 +131,28 @@
       contents(), resource);
 
   scoped_ptr<const std::string> serialized(report->GetSerializedReport());
-  safe_browsing::ClientMalwareReportRequest actual;
+  ClientMalwareReportRequest actual;
   actual.ParseFromString(*serialized);
 
-  safe_browsing::ClientMalwareReportRequest expected;
+  ClientMalwareReportRequest expected;
   expected.set_malware_url(kMalwareURL);
   expected.set_page_url(kLandingURL);
   expected.set_referrer_url("");
 
-  safe_browsing::ClientMalwareReportRequest::Resource* node =
-      expected.add_nodes();
-  node->set_url(kLandingURL);
+  ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+  pb_resource->set_id(0);
+  pb_resource->set_url(kLandingURL);
 
-  // Malware url should have originalurl as parent.
-  node = expected.add_nodes();
-  node->set_url(kMalwareURL);
-  node->set_parent(kOriginalLandingURL);
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(1);
+  pb_resource->set_url(kOriginalLandingURL);
 
-  node = expected.add_nodes();
-  node->set_url(kOriginalLandingURL);
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(2);
+  pb_resource->set_url(kMalwareURL);
+  // The Resource for kMmalwareUrl should have the Resource for
+  // kOriginalLandingURL (with id 1) as parent.
+  pb_resource->set_parent_id(1);
 
   VerifyResults(actual, expected);
 }
@@ -160,16 +166,67 @@
       contents(), resource);
 
   scoped_ptr<const std::string> serialized(report->GetSerializedReport());
-  safe_browsing::ClientMalwareReportRequest actual;
+  ClientMalwareReportRequest actual;
   actual.ParseFromString(*serialized);
 
-  safe_browsing::ClientMalwareReportRequest expected;
+  ClientMalwareReportRequest expected;
   expected.set_malware_url(kMalwareURL);  // No page_url
   expected.set_referrer_url("");
 
-  safe_browsing::ClientMalwareReportRequest::Resource* node =
-      expected.add_nodes();
-  node->set_url(kMalwareURL);  // Only one node
+  ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+  pb_resource->set_url(kMalwareURL);  // Only one resource
+
+  VerifyResults(actual, expected);
+}
+
+// Tests creating a malware report where there are redirect urls to an unsafe
+// resource url
+TEST_F(MalwareDetailsTest, MalwareWithRedirectUrl) {
+  controller().LoadURL(GURL(kLandingURL), GURL(), PageTransition::TYPED);
+
+  SafeBrowsingService::UnsafeResource resource;
+  InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
+  resource.original_url = GURL(kOriginalLandingURL);
+
+  // add some redirect urls
+  resource.redirect_urls.push_back(GURL(kFirstRedirectURL));
+  resource.redirect_urls.push_back(GURL(kSecondRedirectURL));
+  resource.redirect_urls.push_back(GURL(kMalwareURL));
+
+  scoped_refptr<MalwareDetails> report = new MalwareDetails(
+      contents(), resource);
+
+  scoped_ptr<const std::string> serialized(report->GetSerializedReport());
+  ClientMalwareReportRequest actual;
+  actual.ParseFromString(*serialized);
+
+  ClientMalwareReportRequest expected;
+  expected.set_malware_url(kMalwareURL);
+  expected.set_page_url(kLandingURL);
+  expected.set_referrer_url("");
+
+  ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+  pb_resource->set_id(0);
+  pb_resource->set_url(kLandingURL);
+
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(1);
+  pb_resource->set_url(kOriginalLandingURL);
+
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(2);
+  pb_resource->set_url(kMalwareURL);
+  pb_resource->set_parent_id(4);
+
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(3);
+  pb_resource->set_url(kFirstRedirectURL);
+  pb_resource->set_parent_id(1);
+
+  pb_resource = expected.add_resources();
+  pb_resource->set_id(4);
+  pb_resource->set_url(kSecondRedirectURL);
+  pb_resource->set_parent_id(3);
 
   VerifyResults(actual, expected);
 }
diff --git a/chrome/browser/safe_browsing/prefix_set.cc b/chrome/browser/safe_browsing/prefix_set.cc
new file mode 100644
index 0000000..dae9578
--- /dev/null
+++ b/chrome/browser/safe_browsing/prefix_set.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/safe_browsing/prefix_set.h"
+
+#include <algorithm>
+#include <math.h>
+
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+
+namespace {
+
+// For |std::upper_bound()| to find a prefix w/in a vector of pairs.
+bool PrefixLess(const std::pair<SBPrefix,size_t>& a,
+                const std::pair<SBPrefix,size_t>& b) {
+  return a.first < b.first;
+}
+
+}  // namespace
+
+namespace safe_browsing {
+
+PrefixSet::PrefixSet(const std::vector<SBPrefix>& prefixes) {
+  if (prefixes.size()) {
+    std::vector<SBPrefix> sorted(prefixes.begin(), prefixes.end());
+    std::sort(sorted.begin(), sorted.end());
+
+    // Lead with the first prefix.
+    SBPrefix prev_prefix = sorted[0];
+    size_t run_length = 0;
+    index_.push_back(std::make_pair(prev_prefix, deltas_.size()));
+
+    for (size_t i = 1; i < sorted.size(); ++i) {
+      // Don't encode zero deltas.
+      if (sorted[i] == prev_prefix)
+        continue;
+
+      // Calculate the delta.  |unsigned| is mandatory, because the
+      // prefixes could be more than INT_MAX apart.
+      unsigned delta = sorted[i] - prev_prefix;
+
+      // New index ref if the delta is too wide, or if too many
+      // consecutive deltas have been encoded.  Note that
+      // |kMaxDelta| cannot itself be encoded.
+      if (delta >= kMaxDelta || run_length >= kMaxRun) {
+        index_.push_back(std::make_pair(sorted[i], deltas_.size()));
+        run_length = 0;
+      } else {
+        // Continue the run of deltas.
+        deltas_.push_back(static_cast<uint16>(delta));
+        ++run_length;
+      }
+
+      prev_prefix = sorted[i];
+    }
+
+    // Send up some memory-usage stats.  Bits because fractional bytes
+    // are weird.
+    const size_t bits_used = index_.size() * sizeof(index_[0]) * CHAR_BIT +
+        deltas_.size() * sizeof(deltas_[0]) * CHAR_BIT;
+    const size_t unique_prefixes = index_.size() + deltas_.size();
+    static const size_t kMaxBitsPerPrefix = sizeof(SBPrefix) * CHAR_BIT;
+    UMA_HISTOGRAM_ENUMERATION("SB2.PrefixSetBitsPerPrefix",
+                              bits_used / unique_prefixes,
+                              kMaxBitsPerPrefix);
+  }
+}
+
+PrefixSet::~PrefixSet() {}
+
+bool PrefixSet::Exists(SBPrefix prefix) const {
+  if (index_.empty())
+    return false;
+
+  // Find the first position after |prefix| in |index_|.
+  std::vector<std::pair<SBPrefix,size_t> >::const_iterator
+      iter = std::upper_bound(index_.begin(), index_.end(),
+                              std::pair<SBPrefix,size_t>(prefix, 0),
+                              PrefixLess);
+
+  // |prefix| comes before anything that's in the set.
+  if (iter == index_.begin())
+    return false;
+
+  // Capture the upper bound of our target entry's deltas.
+  const size_t bound = (iter == index_.end() ? deltas_.size() : iter->second);
+
+  // Back up to the entry our target is in.
+  --iter;
+
+  // All prefixes in |index_| are in the set.
+  SBPrefix current = iter->first;
+  if (current == prefix)
+    return true;
+
+  // Scan forward accumulating deltas while a match is possible.
+  for (size_t di = iter->second; di < bound && current < prefix; ++di) {
+    current += deltas_[di];
+  }
+
+  return current == prefix;
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/prefix_set.h b/chrome/browser/safe_browsing/prefix_set.h
new file mode 100644
index 0000000..229b772
--- /dev/null
+++ b/chrome/browser/safe_browsing/prefix_set.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A read-only set implementation for |SBPrefix| items.  Prefixes are
+// sorted and stored as 16-bit deltas from the previous prefix.  An
+// index structure provides quick random access, and also handles
+// cases where 16 bits cannot encode a delta.
+//
+// For example, the sequence {20, 25, 41, 65432, 150000, 160000} would
+// be stored as:
+//  A pair {20, 0} in |index_|.
+//  5, 16, 65391 in |deltas_|.
+//  A pair {150000, 3} in |index_|.
+//  10000 in |deltas_|.
+// |index_.size()| will be 2, |deltas_.size()| will be 4.
+//
+// This structure is intended for storage of sparse uniform sets of
+// prefixes of a certain size.  As of this writing, my safe-browsing
+// database contains:
+//   653132 add prefixes
+//   6446 are duplicates (from different chunks)
+//   24301 w/in 2^8 of the prior prefix
+//   622337 w/in 2^16 of the prior prefix
+//   47 further than 2^16 from the prior prefix
+// For this input, the memory usage is approximately 2 bytes per
+// prefix, a bit over 1.2M.  The bloom filter used 25 bits per prefix,
+// a bit over 1.9M on this data.
+//
+// Experimenting with random selections of the above data, storage
+// size drops almost linearly as prefix count drops, until the index
+// overhead starts to become a problem a bit under 200k prefixes.  The
+// memory footprint gets worse than storing the raw prefix data around
+// 75k prefixes.  Fortunately, the actual memory footprint also falls.
+// If the prefix count increases the memory footprint should increase
+// approximately linearly.  The worst-case would be 2^16 items all
+// 2^16 apart, which would need 512k (versus 256k to store the raw
+// data).
+//
+// TODO(shess): Write serialization code.  Something like this should
+// work:
+//         4 byte magic number
+//         4 byte version number
+//         4 byte |index_.size()|
+//         4 byte |deltas_.size()|
+//     n * 8 byte |&index_[0]..&index_[n]|
+//     m * 2 byte |&deltas_[0]..&deltas_[m]|
+//        16 byte digest
+
+#ifndef CHROME_BROWSER_SAFE_BROWSING_PREFIX_SET_H_
+#define CHROME_BROWSER_SAFE_BROWSING_PREFIX_SET_H_
+#pragma once
+
+#include <vector>
+
+#include "chrome/browser/safe_browsing/safe_browsing_util.h"
+
+namespace safe_browsing {
+
+class PrefixSet {
+ public:
+  explicit PrefixSet(const std::vector<SBPrefix>& prefixes);
+  ~PrefixSet();
+
+  // |true| if |prefix| was in |prefixes| passed to the constructor.
+  bool Exists(SBPrefix prefix) const;
+
+ private:
+  // Maximum delta that can be encoded in a 16-bit unsigned.
+  static const unsigned kMaxDelta = 256 * 256;
+
+  // Maximum number of consecutive deltas to encode before generating
+  // a new index entry.  This helps keep the worst-case performance
+  // for |Exists()| under control.
+  static const size_t kMaxRun = 100;
+
+  // Top-level index of prefix to offset in |deltas_|.  Each pair
+  // indicates a base prefix and where the deltas from that prefix
+  // begin in |deltas_|.  The deltas for a pair end at the next pair's
+  // index into |deltas_|.
+  std::vector<std::pair<SBPrefix,size_t> > index_;
+
+  // Deltas which are added to the prefix in |index_| to generate
+  // prefixes.  Deltas are only valid between consecutive items from
+  // |index_|, or the end of |deltas_| for the last |index_| pair.
+  std::vector<uint16> deltas_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefixSet);
+};
+
+}  // namespace safe_browsing
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_PREFIX_SET_H_
diff --git a/chrome/browser/safe_browsing/prefix_set_unittest.cc b/chrome/browser/safe_browsing/prefix_set_unittest.cc
new file mode 100644
index 0000000..9328b77
--- /dev/null
+++ b/chrome/browser/safe_browsing/prefix_set_unittest.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/prefix_set.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+SBPrefix GenPrefix() {
+  return static_cast<SBPrefix>(base::RandUint64());
+}
+
+// Test that a small sparse random input works.
+TEST(PrefixSetTest, Baseline) {
+  std::vector<SBPrefix> prefixes;
+
+  static const size_t kCount = 50000;
+
+  for (size_t i = 0; i < kCount; ++i) {
+    prefixes.push_back(GenPrefix());
+  }
+
+  safe_browsing::PrefixSet prefix_set(prefixes);
+
+  // Check that the set flags all of the inputs, and also check items
+  // just above and below the inputs to make sure they aren't there.
+  std::set<SBPrefix> check(prefixes.begin(), prefixes.end());
+  for (size_t i = 0; i < prefixes.size(); ++i) {
+    EXPECT_TRUE(prefix_set.Exists(prefixes[i]));
+
+    const SBPrefix left_sibling = prefixes[i] - 1;
+    if (check.count(left_sibling) == 0)
+      EXPECT_FALSE(prefix_set.Exists(left_sibling));
+
+    const SBPrefix right_sibling = prefixes[i] + 1;
+    if (check.count(right_sibling) == 0)
+      EXPECT_FALSE(prefix_set.Exists(right_sibling));
+  }
+}
+
+// Test that the empty set doesn't appear to have anything in it.
+TEST(PrefixSetTest, xEmpty) {
+  std::vector<SBPrefix> prefixes;
+  safe_browsing::PrefixSet prefix_set(prefixes);
+  for (size_t i = 0; i < 500; ++i) {
+    EXPECT_FALSE(prefix_set.Exists(GenPrefix()));
+  }
+}
+
+// Use artificial inputs to test various edge cases in Exists().
+// Items before the lowest item aren't present.  Items after the
+// largest item aren't present.  Create a sequence of items with
+// deltas above and below 2^16, and make sure they're all present.
+// Create a very long sequence with deltas below 2^16 to test crossing
+// |kMaxRun|.
+TEST(PrefixSetTest, EdgeCases) {
+  std::vector<SBPrefix> prefixes;
+
+  const SBPrefix kVeryPositive = 1000 * 1000 * 1000;
+  const SBPrefix kVeryNegative = -kVeryPositive;
+
+  // Put in a very negative prefix.
+  SBPrefix prefix = kVeryNegative;
+  prefixes.push_back(prefix);
+
+  // Add a sequence with very large deltas.
+  unsigned delta = 100 * 1000 * 1000;
+  for (int i = 0; i < 10; ++i) {
+    prefix += delta;
+    prefixes.push_back(prefix);
+  }
+
+  // Add a sequence with deltas that start out smaller than the
+  // maximum delta, and end up larger.  Also include some duplicates.
+  delta = 256 * 256 - 100;
+  for (int i = 0; i < 200; ++i) {
+    prefix += delta;
+    prefixes.push_back(prefix);
+    prefixes.push_back(prefix);
+    delta++;
+  }
+
+  // Add a long sequence with deltas smaller than the maximum delta,
+  // so a new index item will be injected.
+  delta = 256 * 256 - 1;
+  prefix = kVeryPositive - delta * 1000;
+  prefixes.push_back(prefix);
+  for (int i = 0; i < 1000; ++i) {
+    prefix += delta;
+    prefixes.push_back(prefix);
+    delta--;
+  }
+
+  // Shuffle things up for giggles.
+  std::random_shuffle(prefixes.begin(), prefixes.end());
+
+  safe_browsing::PrefixSet prefix_set(prefixes);
+
+  // Items before and after the set are not present, and don't crash.
+  EXPECT_FALSE(prefix_set.Exists(kVeryNegative - 100));
+  EXPECT_FALSE(prefix_set.Exists(kVeryPositive + 100));
+
+  // Check that the set correctly flags all of the inputs, and also
+  // check items just above and below the inputs to make sure they
+  // aren't present.
+  for (size_t i = 0; i < prefixes.size(); ++i) {
+    EXPECT_TRUE(prefix_set.Exists(prefixes[i]));
+
+    EXPECT_FALSE(prefix_set.Exists(prefixes[i] - 1));
+    EXPECT_FALSE(prefix_set.Exists(prefixes[i] + 1));
+  }
+}
+
+}  // namespace
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc
index 69f8583..2ff5f4c 100644
--- a/chrome/browser/safe_browsing/protocol_manager.cc
+++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -201,7 +201,7 @@
 void SafeBrowsingProtocolManager::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -255,7 +255,7 @@
       }
     } else {
       HandleGetHashError(Time::Now());
-      if (status.status() == URLRequestStatus::FAILED) {
+      if (status.status() == net::URLRequestStatus::FAILED) {
         VLOG(1) << "SafeBrowsing GetHash request for: " << source->url()
                 << " failed with os error: " << status.os_error();
       } else {
@@ -329,7 +329,7 @@
       if (request_type_ == CHUNK_REQUEST)
         chunk_request_urls_.clear();
       UpdateFinished(false);
-      if (status.status() == URLRequestStatus::FAILED) {
+      if (status.status() == net::URLRequestStatus::FAILED) {
         VLOG(1) << "SafeBrowsing request for: " << source->url()
                 << " failed with os error: " << status.os_error();
       } else {
@@ -417,7 +417,7 @@
       scoped_ptr<SBChunkList> chunks(new SBChunkList);
       UMA_HISTOGRAM_COUNTS("SB2.ChunkSize", length);
       update_size_ += length;
-      if (!parser.ParseChunk(data, length,
+      if (!parser.ParseChunk(chunk_url.list_name, data, length,
                              client_key_, chunk_url.mac,
                              &re_key, chunks.get())) {
 #ifndef NDEBUG
diff --git a/chrome/browser/safe_browsing/protocol_parser.cc b/chrome/browser/safe_browsing/protocol_parser.cc
index 7290376..08e521e 100644
--- a/chrome/browser/safe_browsing/protocol_parser.cc
+++ b/chrome/browser/safe_browsing/protocol_parser.cc
@@ -4,7 +4,10 @@
 //
 // Parse the data returned from the SafeBrowsing v2.1 protocol response.
 
+#include <stdlib.h>
+
 #include "chrome/browser/safe_browsing/protocol_parser.h"
+#include "chrome/browser/safe_browsing/safe_browsing_util.h"
 
 #include "build/build_config.h"
 
@@ -245,7 +248,8 @@
   return true;
 }
 
-bool SafeBrowsingProtocolParser::ParseChunk(const char* data,
+bool SafeBrowsingProtocolParser::ParseChunk(const std::string& list_name,
+                                            const char* data,
                                             int length,
                                             const std::string& key,
                                             const std::string& mac,
@@ -265,6 +269,8 @@
       return false;  // Error: bad chunk format!
 
     const int line_len = static_cast<int>(cmd_line.length()) + 1;
+    chunk_data += line_len;
+    remaining -= line_len;
     std::vector<std::string> cmd_parts;
     base::SplitString(cmd_line, ':', &cmd_parts);
 
@@ -274,8 +280,6 @@
           cmd_parts[0] == "e" &&
           cmd_parts[1] == "pleaserekey") {
         *re_key = true;
-        chunk_data += line_len;
-        remaining -= line_len;
         continue;
       }
       return false;
@@ -290,20 +294,21 @@
     }
 
     const int chunk_len = atoi(cmd_parts[3].c_str());
-    chunk_data += line_len;
-    remaining -= line_len;
+
+    if (remaining < chunk_len)
+      return false;  // parse error.
 
     chunks->push_back(SBChunk());
     chunks->back().chunk_number = chunk_number;
 
     if (cmd_parts[0] == "a") {
       chunks->back().is_add = true;
-      if (!ParseAddChunk(chunk_data, chunk_len, hash_len,
+      if (!ParseAddChunk(list_name, chunk_data, chunk_len, hash_len,
                          &chunks->back().hosts))
         return false;  // Parse error.
     } else if (cmd_parts[0] == "s") {
       chunks->back().is_add = false;
-      if (!ParseSubChunk(chunk_data, chunk_len, hash_len,
+      if (!ParseSubChunk(list_name, chunk_data, chunk_len, hash_len,
                          &chunks->back().hosts))
         return false;  // Parse error.
     } else {
@@ -313,8 +318,7 @@
 
     chunk_data += chunk_len;
     remaining -= chunk_len;
-    if (remaining < 0)
-      return false;  // Parse error.
+    DCHECK_LE(0, remaining);
   }
 
   DCHECK(remaining == 0);
@@ -322,85 +326,88 @@
   return true;
 }
 
-bool SafeBrowsingProtocolParser::ParseAddChunk(
-    const char* data, int data_len, int hash_len,
-    std::deque<SBChunkHost>* hosts) {
-
-  int remaining = data_len;
+bool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name,
+                                               const char* data,
+                                               int data_len,
+                                               int hash_len,
+                                               std::deque<SBChunkHost>* hosts) {
   const char* chunk_data = data;
-  const int min_size = sizeof(SBPrefix) + 1;
+  int remaining = data_len;
+  int prefix_count;
+  SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
+      SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH;
 
-  while (remaining >= min_size) {
+  if (list_name == safe_browsing_util::kBinHashList) {
+    // kBinHashList only contains prefixes, no HOSTKEY and COUNT.
+    DCHECK_EQ(0, remaining % hash_len);
+    prefix_count = remaining / hash_len;
+    SBChunkHost chunk_host;
+    chunk_host.host = 0;
+    chunk_host.entry = SBEntry::Create(type, prefix_count);
+    hosts->push_back(chunk_host);
+    if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count))
+      return false;
+  } else {
     SBPrefix host;
-    int prefix_count;
-    ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
-    SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
-        SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH;
-    SBEntry* entry;
-    int index_start = 0;
-
-    // If a host has more than 255 prefixes, then subsequent entries are used.
-    // Check if this is the case, and if so put them in one SBEntry since the
-    // database code assumes that all prefixes from the same host and chunk are
-    // in one SBEntry.
-    if (!hosts->empty() && hosts->back().host == host &&
-        hosts->back().entry->HashLen() == hash_len) {
-      // Reuse the SBChunkHost, but need to create a new SBEntry since we have
-      // more prefixes.
-      index_start = hosts->back().entry->prefix_count();
-      entry = hosts->back().entry->Enlarge(prefix_count);
-      hosts->back().entry = entry;
-    } else {
-      entry = SBEntry::Create(type, prefix_count);
+    const int min_size = sizeof(SBPrefix) + 1;
+    while (remaining >= min_size) {
+      ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
       SBChunkHost chunk_host;
       chunk_host.host = host;
-      chunk_host.entry = entry;
+      chunk_host.entry = SBEntry::Create(type, prefix_count);
       hosts->push_back(chunk_host);
+      if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry,
+                        prefix_count))
+        return false;
     }
-
-    if (!ReadPrefixes(&chunk_data, &remaining, entry, prefix_count,
-                      index_start))
-      return false;
   }
-
   return remaining == 0;
 }
 
-bool SafeBrowsingProtocolParser::ParseSubChunk(
-    const char* data, int data_len, int hash_len,
-    std::deque<SBChunkHost>* hosts) {
-
+bool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name,
+                                               const char* data,
+                                               int data_len,
+                                               int hash_len,
+                                               std::deque<SBChunkHost>* hosts) {
   int remaining = data_len;
   const char* chunk_data = data;
-  const int min_size = 2 * sizeof(SBPrefix) + 1;
+  int prefix_count;
+  SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
+      SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH;
 
-  while (remaining >= min_size) {
-    SBPrefix host;
-    int prefix_count;
-    ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
-    SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
-        SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH;
-    SBEntry* entry = SBEntry::Create(type, prefix_count);
-
+  if (list_name == safe_browsing_util::kBinHashList) {
     SBChunkHost chunk_host;
-    chunk_host.host = host;
-    chunk_host.entry = entry;
-    hosts->push_back(chunk_host);
-
-    if (prefix_count == 0) {
-      // There is only an add chunk number (no prefixes).
-      entry->set_chunk_id(ReadChunkId(&chunk_data, &remaining));
-      continue;
-    }
-
-    if (!ReadPrefixes(&chunk_data, &remaining, entry, prefix_count, 0))
+    // Set host to 0 and it won't be used for kBinHashList.
+    chunk_host.host = 0;
+    // kBinHashList only contains (add_chunk_number, prefix) pairs, no HOSTKEY
+    // and COUNT. |add_chunk_number| is int32.
+    prefix_count = remaining / (sizeof(int32) + hash_len);
+    chunk_host.entry = SBEntry::Create(type, prefix_count);
+    if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count))
       return false;
+    hosts->push_back(chunk_host);
+  } else {
+    SBPrefix host;
+    const int min_size = 2 * sizeof(SBPrefix) + 1;
+    while (remaining >= min_size) {
+      ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count);
+      SBChunkHost chunk_host;
+      chunk_host.host = host;
+      chunk_host.entry = SBEntry::Create(type, prefix_count);
+      hosts->push_back(chunk_host);
+      if (prefix_count == 0) {
+        // There is only an add chunk number (no prefixes).
+        chunk_host.entry->set_chunk_id(ReadChunkId(&chunk_data, &remaining));
+        continue;
+      }
+      if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry,
+                        prefix_count))
+        return false;
+    }
   }
-
   return remaining == 0;
 }
 
-
 void SafeBrowsingProtocolParser::ReadHostAndPrefixCount(
     const char** data, int* remaining, SBPrefix* host, int* count) {
   // Next 4 bytes are the host prefix.
@@ -424,22 +431,19 @@
 }
 
 bool SafeBrowsingProtocolParser::ReadPrefixes(
-    const char** data, int* remaining, SBEntry* entry, int count,
-    int index_start) {
+    const char** data, int* remaining, SBEntry* entry, int count) {
   int hash_len = entry->HashLen();
   for (int i = 0; i < count; ++i) {
     if (entry->IsSub()) {
-      entry->SetChunkIdAtPrefix(index_start + i, ReadChunkId(data, remaining));
+      entry->SetChunkIdAtPrefix(i, ReadChunkId(data, remaining));
       if (*remaining <= 0)
         return false;
     }
 
     if (entry->IsPrefix()) {
-      entry->SetPrefixAt(index_start + i,
-                         *reinterpret_cast<const SBPrefix*>(*data));
+      entry->SetPrefixAt(i, *reinterpret_cast<const SBPrefix*>(*data));
     } else {
-      entry->SetFullHashAt(index_start + i,
-                           *reinterpret_cast<const SBFullHash*>(*data));
+      entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data));
     }
     *data += hash_len;
     *remaining -= hash_len;
diff --git a/chrome/browser/safe_browsing/protocol_parser.h b/chrome/browser/safe_browsing/protocol_parser.h
index 9384f07..d074f2a 100644
--- a/chrome/browser/safe_browsing/protocol_parser.h
+++ b/chrome/browser/safe_browsing/protocol_parser.h
@@ -75,7 +75,8 @@
   // Parse the response from a chunk URL request and returns the hosts/prefixes
   // for adds and subs in "chunks".  Returns 'true' on successful parsing,
   // 'false' otherwise. Any result should be ignored when a parse has failed.
-  bool ParseChunk(const char* chunk_data,
+  bool ParseChunk(const std::string& list_name,
+                  const char* chunk_data,
                   int chunk_len,
                   const std::string& key,
                   const std::string& mac,
@@ -102,22 +103,25 @@
                    std::string* wrapped_key);
 
  private:
-  bool ParseAddChunk(const char* data,
+  bool ParseAddChunk(const std::string& list_name,
+                     const char* data,
                      int data_len,
                      int hash_len,
                      std::deque<SBChunkHost>* hosts);
-  bool ParseSubChunk(const char* data,
+  bool ParseSubChunk(const std::string& list_name,
+                     const char* data,
                      int data_len,
                      int hash_len,
                      std::deque<SBChunkHost>* hosts);
 
   // Helper functions used by ParseAddChunk and ParseSubChunk.
-  static void ReadHostAndPrefixCount(
-      const char** data, int* remaining, SBPrefix* host, int* count);
+  static void ReadHostAndPrefixCount(const char** data,
+                                     int* remaining,
+                                     SBPrefix* host,
+                                     int* count);
   static int ReadChunkId(const char** data, int* remaining);
   static bool ReadPrefixes(
-      const char** data, int* remaining, SBEntry* entry, int count,
-      int index_start);
+      const char** data, int* remaining, SBEntry* entry, int count);
 
   // The name of the current list
   std::string list_name_;
diff --git a/chrome/browser/safe_browsing/protocol_parser_unittest.cc b/chrome/browser/safe_browsing/protocol_parser_unittest.cc
index 3aa5bd1..d52b3d6 100644
--- a/chrome/browser/safe_browsing/protocol_parser_unittest.cc
+++ b/chrome/browser/safe_browsing/protocol_parser_unittest.cc
@@ -6,9 +6,9 @@
 
 #include "base/string_util.h"
 #include "chrome/browser/safe_browsing/protocol_parser.h"
+#include "chrome/browser/safe_browsing/safe_browsing_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-
 // Test parsing one add chunk.
 TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) {
   std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999");
@@ -18,14 +18,16 @@
   SafeBrowsingProtocolParser parser;
   bool re_key = false;
   SBChunkList chunks;
-  bool result = parser.ParseChunk(add_chunk.data(),
-                                  static_cast<int>(add_chunk.length()),
-                                  "", "",  &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "",  &re_key, &chunks);
   EXPECT_TRUE(result);
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(3));
+  EXPECT_EQ(chunks[0].hosts.size(), 3U);
 
   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
   SBEntry* entry = chunks[0].hosts[0].entry;
@@ -69,14 +71,16 @@
   SafeBrowsingProtocolParser parser;
   bool re_key = false;
   SBChunkList chunks;
-  bool result = parser.ParseChunk(add_chunk.data(),
-                                  static_cast<int>(add_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks[0].hosts.size(), 1U);
 
   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
   SBEntry* entry = chunks[0].hosts[0].entry;
@@ -98,14 +102,16 @@
   SafeBrowsingProtocolParser parser;
   bool re_key = false;
   SBChunkList chunks;
-  bool result = parser.ParseChunk(add_chunk.data(),
-                                  static_cast<int>(add_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(2));
+  EXPECT_EQ(chunks.size(), 2U);
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(3));
+  EXPECT_EQ(chunks[0].hosts.size(), 3U);
 
   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
   SBEntry* entry = chunks[0].hosts[0].entry;
@@ -132,7 +138,7 @@
 
 
   EXPECT_EQ(chunks[1].chunk_number, 2);
-  EXPECT_EQ(chunks[1].hosts.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks[1].hosts.size(), 1U);
 
   EXPECT_EQ(chunks[1].hosts[0].host, 0x35353535);
   entry = chunks[1].hosts[0].entry;
@@ -158,19 +164,77 @@
   SafeBrowsingProtocolParser parser;
   bool re_key = false;
   SBChunkList chunks;
-  bool result = parser.ParseChunk(add_chunk.data(),
-                                  static_cast<int>(add_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 1);
 
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks[0].hosts.size(), 2U);
 
-  const SBChunkHost& host = chunks[0].hosts[0];
-  EXPECT_EQ(host.host, 0x61616161);
-  EXPECT_EQ(host.entry->prefix_count(), 260);
+  const SBChunkHost& host0 = chunks[0].hosts[0];
+  EXPECT_EQ(host0.host, 0x61616161);
+  EXPECT_EQ(host0.entry->prefix_count(), 255);
+
+  const SBChunkHost& host1 = chunks[0].hosts[1];
+  EXPECT_EQ(host1.host, 0x61616161);
+  EXPECT_EQ(host1.entry->prefix_count(), 5);
+}
+
+// Test to make sure we could deal with truncated bin hash chunk.
+TEST(SafeBrowsingProtocolParsingTest, TestTruncatedBinHashChunk) {
+  // This chunk delares there are 4 prefixes but actually only contains 2.
+  const char add_chunk[] = "a:1:4:16\n11112222";
+  SafeBrowsingProtocolParser parser;
+  bool re_key = false;
+  SBChunkList chunks;
+  bool result = parser.ParseChunk(add_chunk,
+                                  safe_browsing_util::kBinHashList,
+                                  static_cast<int>(sizeof(add_chunk)),
+                                  "", "", &re_key, &chunks);
+  EXPECT_FALSE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 0U);
+}
+
+// Test to make sure we could deal with truncated malwarelist chunk.
+TEST(SafeBrowsingProtocolParsingTest, TestTruncatedUrlHashChunk) {
+  // This chunk delares there are 4 prefixes but actually only contains 2.
+  const char add_chunk[] = "a:1:4:21\naaaa\00411112222";
+  SafeBrowsingProtocolParser parser;
+  bool re_key = false;
+  SBChunkList chunks;
+
+  // For safe_browsing_util::kMalwareList.
+  bool result = parser.ParseChunk(add_chunk,
+                                  safe_browsing_util::kMalwareList,
+                                  static_cast<int>(sizeof(add_chunk)),
+                                  "", "", &re_key, &chunks);
+  EXPECT_FALSE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 0U);
+
+  // For safe_browsing_util::kPhishingList.
+  result = parser.ParseChunk(add_chunk,
+                             safe_browsing_util::kPhishingList,
+                             static_cast<int>(sizeof(add_chunk)),
+                             "", "", &re_key, &chunks);
+  EXPECT_FALSE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 0U);
+
+  // For safe_browsing_util::kBinUrlList.
+  result = parser.ParseChunk(add_chunk,
+                             safe_browsing_util::kBinUrlList,
+                             static_cast<int>(sizeof(add_chunk)),
+                             "", "", &re_key, &chunks);
+  EXPECT_FALSE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 0U);
 }
 
 // Test parsing one sub chunk.
@@ -184,14 +248,16 @@
   SafeBrowsingProtocolParser parser;
   bool re_key = false;
   SBChunkList chunks;
-  bool result = parser.ParseChunk(sub_chunk.data(),
-                                  static_cast<int>(sub_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      sub_chunk.data(),
+      static_cast<int>(sub_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 9);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(3));
+  EXPECT_EQ(chunks[0].hosts.size(), 3U);
 
   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
   SBEntry* entry = chunks[0].hosts[0].entry;
@@ -243,14 +309,16 @@
   SafeBrowsingProtocolParser parser;
   bool re_key = false;
   SBChunkList chunks;
-  bool result = parser.ParseChunk(sub_chunk.data(),
-                                  static_cast<int>(sub_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      sub_chunk.data(),
+      static_cast<int>(sub_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks[0].hosts.size(), 1U);
 
   EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161);
   SBEntry* entry = chunks[0].hosts[0].entry;
@@ -283,15 +351,15 @@
   EXPECT_FALSE(re_key);
   EXPECT_FALSE(reset);
   EXPECT_EQ(next_query_sec, 1700);
-  EXPECT_EQ(deletes.size(), static_cast<size_t>(2));
+  EXPECT_EQ(deletes.size(), 2U);
 
-  EXPECT_EQ(deletes[0].chunk_del.size(), static_cast<size_t>(4));
+  EXPECT_EQ(deletes[0].chunk_del.size(), 4U);
   EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7));
   EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597));
   EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444));
   EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999));
 
-  EXPECT_EQ(deletes[1].chunk_del.size(), static_cast<size_t>(3));
+  EXPECT_EQ(deletes[1].chunk_del.size(), 3U);
   EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27));
   EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42));
   EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717));
@@ -330,7 +398,7 @@
 
   EXPECT_FALSE(re_key);
   EXPECT_FALSE(reset);
-  EXPECT_EQ(urls.size(), static_cast<size_t>(4));
+  EXPECT_EQ(urls.size(), 4U);
   EXPECT_EQ(urls[0].url,
       "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1");
   EXPECT_EQ(urls[1].url,
@@ -366,7 +434,7 @@
 
   EXPECT_FALSE(re_key);
   EXPECT_FALSE(reset);
-  EXPECT_EQ(urls.size(), static_cast<size_t>(2));
+  EXPECT_EQ(urls.size(), 2U);
   EXPECT_EQ(urls[0].url,
       "s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6501-6505:6501-6505");
   EXPECT_EQ(urls[0].mac, "pcY6iVeT9-CBQ3fdAF0rpnKjR1Y=");
@@ -412,7 +480,7 @@
                                   &full_hashes));
 
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(full_hashes.size(), static_cast<size_t>(3));
+  EXPECT_EQ(full_hashes.size(), 3U);
   EXPECT_EQ(memcmp(&full_hashes[0].hash,
                    "00112233445566778899aabbccddeeff",
                    sizeof(SBFullHash)), 0);
@@ -438,7 +506,7 @@
                                   &full_hashes));
 
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(full_hashes.size(), static_cast<size_t>(3));
+  EXPECT_EQ(full_hashes.size(), 3U);
   EXPECT_EQ(memcmp(&full_hashes[0].hash,
                    "00112233445566778899aabbccddeeff",
                    sizeof(SBFullHash)), 0);
@@ -485,7 +553,7 @@
                                   &re_key,
                                   &full_hashes));
   EXPECT_FALSE(re_key);
-  EXPECT_EQ(full_hashes.size(), static_cast<size_t>(1));
+  EXPECT_EQ(full_hashes.size(), 1U);
   EXPECT_EQ(memcmp(hash_result, &full_hashes[0].hash, sizeof(SBFullHash)), 0);
 }
 
@@ -504,7 +572,7 @@
                                   &re_key,
                                   &full_hashes));
 
-  EXPECT_EQ(full_hashes.size(), static_cast<size_t>(1));
+  EXPECT_EQ(full_hashes.size(), 1U);
   EXPECT_EQ(memcmp("12345678901234567890123456789012",
                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
   EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
@@ -519,7 +587,7 @@
                                   &re_key,
                                   &full_hashes));
 
-  EXPECT_EQ(full_hashes.size(), static_cast<size_t>(2));
+  EXPECT_EQ(full_hashes.size(), 2U);
   EXPECT_EQ(memcmp("12345678901234567890123456789012",
                    &full_hashes[0].hash, sizeof(SBFullHash)), 0);
   EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar");
@@ -599,38 +667,42 @@
   bool re_key = false;
   SBChunkList chunks;
 
-  bool result = parser.ParseChunk(add_chunk.data(),
-                                  static_cast<int>(add_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(0));
+  EXPECT_EQ(chunks[0].hosts.size(), 0U);
 
   // Now test a zero size chunk in between normal chunks.
   chunks.clear();
   std::string add_chunks("a:1:4:18\n1234\001abcd5678\001wxyz"
                          "a:2:4:0\n"
                          "a:3:4:9\ncafe\001beef");
-  result = parser.ParseChunk(add_chunks.data(),
-                             static_cast<int>(add_chunks.length()),
-                             "", "", &re_key, &chunks);
+  result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      add_chunks.data(),
+      static_cast<int>(add_chunks.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(3));
+  EXPECT_EQ(chunks.size(), 3U);
 
   // See that each chunk has the right content.
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(2));
+  EXPECT_EQ(chunks[0].hosts.size(), 2U);
   EXPECT_EQ(chunks[0].hosts[0].host, 0x34333231);
   EXPECT_EQ(chunks[0].hosts[0].entry->PrefixAt(0), 0x64636261);
   EXPECT_EQ(chunks[0].hosts[1].host, 0x38373635);
   EXPECT_EQ(chunks[0].hosts[1].entry->PrefixAt(0), 0x7a797877);
 
   EXPECT_EQ(chunks[1].chunk_number, 2);
-  EXPECT_EQ(chunks[1].hosts.size(), static_cast<size_t>(0));
+  EXPECT_EQ(chunks[1].hosts.size(), 0U);
 
   EXPECT_EQ(chunks[2].chunk_number, 3);
-  EXPECT_EQ(chunks[2].hosts.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks[2].hosts.size(), 1U);
   EXPECT_EQ(chunks[2].hosts[0].host, 0x65666163);
   EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x66656562);
 }
@@ -642,13 +714,15 @@
   bool re_key = false;
   SBChunkList chunks;
 
-  bool result = parser.ParseChunk(sub_chunk.data(),
-                                  static_cast<int>(sub_chunk.length()),
-                                  "", "", &re_key, &chunks);
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      sub_chunk.data(),
+      static_cast<int>(sub_chunk.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
-  EXPECT_EQ(chunks.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks.size(), 1U);
   EXPECT_EQ(chunks[0].chunk_number, 9);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(0));
+  EXPECT_EQ(chunks[0].hosts.size(), 0U);
   chunks.clear();
 
   // Test parsing a zero sized sub chunk mixed in with content carrying chunks.
@@ -657,21 +731,23 @@
                          "s:3:4:26\nefgh\0011234pqrscafe\0015678lmno");
   sub_chunks[12] = '\0';
 
-  result = parser.ParseChunk(sub_chunks.data(),
-                             static_cast<int>(sub_chunks.length()),
-                             "", "", &re_key, &chunks);
+  result = parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      sub_chunks.data(),
+      static_cast<int>(sub_chunks.length()),
+      "", "", &re_key, &chunks);
   EXPECT_TRUE(result);
 
   EXPECT_EQ(chunks[0].chunk_number, 1);
-  EXPECT_EQ(chunks[0].hosts.size(), static_cast<size_t>(1));
+  EXPECT_EQ(chunks[0].hosts.size(), 1U);
   EXPECT_EQ(chunks[0].hosts[0].host, 0x64636261);
   EXPECT_EQ(chunks[0].hosts[0].entry->prefix_count(), 0);
 
   EXPECT_EQ(chunks[1].chunk_number, 2);
-  EXPECT_EQ(chunks[1].hosts.size(), static_cast<size_t>(0));
+  EXPECT_EQ(chunks[1].hosts.size(), 0U);
 
   EXPECT_EQ(chunks[2].chunk_number, 3);
-  EXPECT_EQ(chunks[2].hosts.size(), static_cast<size_t>(2));
+  EXPECT_EQ(chunks[2].hosts.size(), 2U);
   EXPECT_EQ(chunks[2].hosts[0].host, 0x68676665);
   EXPECT_EQ(chunks[2].hosts[0].entry->prefix_count(), 1);
   EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x73727170);
@@ -749,8 +825,102 @@
   const std::string key("v_aDSz6jI92WeHCOoZ07QA==");
   const std::string mac("W9Xp2fUcQ9V66If6Cvsrstpa4Kk=");
 
-  EXPECT_TRUE(parser.ParseChunk(reinterpret_cast<const char*>(chunk),
-                                sizeof(chunk), key, mac,
-                                &re_key, &chunks));
+  EXPECT_TRUE(parser.ParseChunk(
+      safe_browsing_util::kMalwareList,
+      reinterpret_cast<const char*>(chunk),
+      sizeof(chunk), key, mac,
+      &re_key, &chunks));
   EXPECT_FALSE(re_key);
 }
+
+TEST(SafeBrowsingProtocolParsingTest, TestAddBinHashChunks) {
+  std::string add_chunk("a:1:4:16\naaaabbbbccccdddd"
+                        "a:2:4:8\n11112222");
+  // Run the parse.
+  SafeBrowsingProtocolParser parser;
+  bool re_key = false;
+  SBChunkList chunks;
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kBinHashList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "", &re_key, &chunks);
+  EXPECT_TRUE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 2U);
+  EXPECT_EQ(chunks[0].chunk_number, 1);
+  EXPECT_EQ(chunks[0].hosts.size(), 1U);
+
+  EXPECT_EQ(chunks[0].hosts[0].host, 0);
+  SBEntry* entry = chunks[0].hosts[0].entry;
+  EXPECT_TRUE(entry->IsAdd());
+  EXPECT_TRUE(entry->IsPrefix());
+  EXPECT_EQ(entry->prefix_count(), 4);
+
+  EXPECT_EQ(chunks[1].chunk_number, 2);
+  EXPECT_EQ(chunks[1].hosts.size(), 1U);
+
+  EXPECT_EQ(chunks[1].hosts[0].host, 0);
+  entry = chunks[1].hosts[0].entry;
+  EXPECT_TRUE(entry->IsAdd());
+  EXPECT_TRUE(entry->IsPrefix());
+  EXPECT_EQ(entry->prefix_count(), 2);
+  EXPECT_EQ(entry->PrefixAt(0), 0x31313131);
+  EXPECT_EQ(entry->PrefixAt(1), 0x32323232);
+}
+
+// Test parsing one add chunk where a hostkey spans several entries.
+TEST(SafeBrowsingProtocolParsingTest, TestAddBigBinHashChunk) {
+  std::string add_chunk("a:1:4:1028\n");
+  for (int i = 0; i < 257; ++i)
+    add_chunk.append(StringPrintf("%04d", i));
+
+  SafeBrowsingProtocolParser parser;
+  bool re_key = false;
+  SBChunkList chunks;
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kBinHashList,
+      add_chunk.data(),
+      static_cast<int>(add_chunk.length()),
+      "", "", &re_key, &chunks);
+  EXPECT_TRUE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 1U);
+  EXPECT_EQ(chunks[0].chunk_number, 1);
+
+  EXPECT_EQ(chunks[0].hosts.size(), 1U);
+
+  const SBChunkHost& host0 = chunks[0].hosts[0];
+  EXPECT_EQ(host0.host, 0);
+  EXPECT_EQ(host0.entry->prefix_count(), 257);
+}
+
+// Test parsing one sub chunk.
+TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) {
+  std::string sub_chunk("s:9:4:16\n1111mmmm2222nnnn");
+
+  // Run the parser.
+  SafeBrowsingProtocolParser parser;
+  bool re_key = false;
+  SBChunkList chunks;
+  bool result = parser.ParseChunk(
+      safe_browsing_util::kBinHashList,
+      sub_chunk.data(),
+      static_cast<int>(sub_chunk.length()),
+      "", "", &re_key, &chunks);
+  EXPECT_TRUE(result);
+  EXPECT_FALSE(re_key);
+  EXPECT_EQ(chunks.size(), 1U);
+  EXPECT_EQ(chunks[0].chunk_number, 9);
+  EXPECT_EQ(chunks[0].hosts.size(), 1U);
+
+  EXPECT_EQ(chunks[0].hosts[0].host, 0);
+  SBEntry* entry = chunks[0].hosts[0].entry;
+  EXPECT_TRUE(entry->IsSub());
+  EXPECT_TRUE(entry->IsPrefix());
+  EXPECT_EQ(entry->prefix_count(), 2);
+  EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131);
+  EXPECT_EQ(entry->PrefixAt(0), 0x6d6d6d6d);
+  EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232);
+  EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e);
+}
diff --git a/chrome/browser/safe_browsing/report.proto b/chrome/browser/safe_browsing/report.proto
index ea4cfda..719c918 100644
--- a/chrome/browser/safe_browsing/report.proto
+++ b/chrome/browser/safe_browsing/report.proto
@@ -23,61 +23,60 @@
 message ClientMalwareReportRequest {
 
   message HTTPHeader {
-    required string name = 1;
-    optional string value = 2;
+    required bytes name = 1;
+    optional bytes value = 2;
   }
 
   message HTTPRequest {
     message FirstLine {
-      optional string verb = 1;  // Also known as method, eg "GET"
-      optional string uri = 2;
-      optional string version = 3;
+      optional bytes verb = 1;  // Also known as method, eg "GET"
+      optional bytes uri = 2;
+      optional bytes version = 3;
     }
     
     optional FirstLine firstline = 1;
     repeated HTTPHeader headers = 2;
-    optional string body = 3;
+    optional bytes body = 3;
 
     // bodydigest and bodylength can be useful if the report does not
     // contain the body itself.
-    optional string bodydigest = 4;  
+    optional bytes bodydigest = 4;  
     optional int32 bodylength = 5;
   }
 
   message HTTPResponse {
     message FirstLine {
       optional int32 code = 1;
-      optional string reason = 2;
-      optional string version = 3;
+      optional bytes reason = 2;
+      optional bytes version = 3;
     }
 
     optional FirstLine firstline = 1;
     repeated HTTPHeader headers = 2;
-    optional string body = 3;
+    optional bytes body = 3;
 
     // bodydigest and bodylength can be useful if the report does not
     // contain the body itself.
-    optional string bodydigest = 4;
+    optional bytes bodydigest = 4;
     optional int32 bodylength = 5;
-    optional string remote_ip = 6;
+    optional bytes remote_ip = 6;
   }
 
   message Resource {
-    optional string url = 1;
+    required int32 id = 1;
+    optional string url = 2;
+    optional HTTPRequest request = 3;
+    optional HTTPResponse response = 4;
 
-    // URL of the parent frame.
-    optional string parent = 2;
-
-    // Tag that was used to include this resource, eg "iframe"
-    optional string tag_name = 3;
-
-    optional HTTPRequest request = 4;
-    optional HTTPResponse response = 5;
+    optional int32 parent_id = 5;  // Id of the parent, if known.
 
     // A list of children. The order of the children in this list is
-    // significant. The |parent| field for child nodes can be derived
+    // significant. The |parent_id| field for child nodes can be derived
     // from this, but this allows us to be more flexible.
-    repeated string children = 6;
+    repeated int32 child_ids = 6;
+
+    // Tag that was used to include this resource, eg "iframe"
+    optional string tag_name = 7;
   }
 
   // URL of the resource that matches the safe browsing list.
@@ -87,5 +86,5 @@
   optional string page_url = 2;
 
   optional string referrer_url = 3;
-  repeated Resource nodes = 4;
+  repeated Resource resources = 4;
 }
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index 95baed4..6f2f945 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -8,8 +8,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/lazy_instance.h"
 #include "base/string_number_conversions.h"
@@ -36,6 +34,8 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // For malware interstitial pages, we link the problematic URL to Google's
 // diagnostic page.
@@ -59,6 +59,11 @@
 static const char* const kLearnMorePhishingUrl =
     "http://www.google.com/support/bin/answer.py?answer=106318";
 
+// URL for the "Safe Browsing Privacy Policies" link on the blocking page.
+// Note: this page is not yet localized.
+static const char* const kSbPrivacyPolicyUrl =
+    "http://www.google.com/intl/en_us/privacy/browsing.html";
+
 static const char* const kSbDiagnosticHtml =
     "<a href=\"\" onclick=\"sendCommand('showDiagnostic'); return false;\" "
     "onmousedown=\"return false;\">%s</a>";
@@ -67,10 +72,15 @@
     "<a href=\"\" onclick=\"sendCommand('proceed'); return false;\" "
     "onmousedown=\"return false;\">%s</a>";
 
+static const char* const kPrivacyLinkHtml =
+    "<a href=\"\" onclick=\"sendCommand('showPrivacy'); return false;\" "
+    "onmousedown=\"return false;\">%s</a>";
+
 // The commands returned by the page when the user performs an action.
 static const char* const kShowDiagnosticCommand = "showDiagnostic";
 static const char* const kReportErrorCommand = "reportError";
 static const char* const kLearnMoreCommand = "learnMore";
+static const char* const kShowPrivacyCommand = "showPrivacy";
 static const char* const kProceedCommand = "proceed";
 static const char* const kTakeMeBackCommand = "takeMeBack";
 static const char* const kDoReportCommand = "doReport";
@@ -327,9 +337,16 @@
   } else {
     // Show the checkbox for sending malware details.
     strings->SetBoolean(kDisplayCheckBox, true);
-    strings->SetString(
-        "confirm_text",
-        l10n_util::GetStringUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE));
+
+    std::string privacy_link = StringPrintf(
+        kPrivacyLinkHtml,
+        l10n_util::GetStringUTF8(
+            IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str());
+
+    strings->SetString("confirm_text",
+                       l10n_util::GetStringFUTF16(
+                           IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE,
+                           UTF8ToUTF16(privacy_link)));
 
     const PrefService::Preference* pref =
         tab()->profile()->GetPrefs()->FindPreference(
@@ -400,6 +417,13 @@
     return;
   }
 
+  if (command == kShowPrivacyCommand) {
+    // User pressed "Safe Browsing privacy policy".
+    GURL url(kSbPrivacyPolicyUrl);
+    tab()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::LINK);
+    return;
+  }
+
   if (command == kProceedCommand) {
     Proceed();
     // We are deleted after this.
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index 9b4c57e..92ef562 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -12,9 +12,8 @@
 #include "base/process_util.h"
 #include "base/sha2.h"
 #include "chrome/browser/safe_browsing/bloom_filter.h"
+#include "chrome/browser/safe_browsing/prefix_set.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
-#include "chrome/browser/safe_browsing/safe_browsing_store_sqlite.h"
-#include "chrome/browser/safe_browsing/safe_browsing_util.h"
 #include "googleurl/src/gurl.h"
 
 namespace {
@@ -179,6 +178,37 @@
   return a.full_hash.prefix < b.full_hash.prefix;
 }
 
+// Create a |PrefixSet| from a vector of add-prefixes.
+safe_browsing::PrefixSet* CreatePrefixSet(
+    const std::vector<SBAddPrefix>& add_prefixes) {
+  std::vector<SBPrefix> prefixes;
+  for (size_t i = 0; i < add_prefixes.size(); ++i) {
+    prefixes.push_back(add_prefixes[i].prefix);
+  }
+  return new safe_browsing::PrefixSet(prefixes);
+}
+
+// As compared to the bloom filter, PrefixSet should have these
+// properties:
+// - Any bloom filter miss should be a prefix set miss.
+// - Any prefix set hit should be a bloom filter hit.
+// - Bloom filter false positives are prefix set misses.
+// The following is to log actual performance to verify this.
+enum PrefixSetEvent {
+  PREFIX_SET_EVENT_HIT,
+  PREFIX_SET_EVENT_BLOOM_HIT,
+  PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT,
+
+  // Memory space for histograms is determined by the max.  ALWAYS ADD
+  // NEW VALUES BEFORE THIS ONE.
+  PREFIX_SET_EVENT_MAX
+};
+
+void RecordPrefixSetInfo(PrefixSetEvent event_type) {
+  UMA_HISTOGRAM_ENUMERATION("SB2.PrefixSetEvent", event_type,
+                            PREFIX_SET_EVENT_MAX);
+}
+
 }  // namespace
 
 // The default SafeBrowsingDatabaseFactory.
@@ -206,11 +236,9 @@
 
 // Factory method, non-thread safe. Caller has to make sure this s called
 // on SafeBrowsing Thread.
-// TODO(shess): Milestone-7 is converting from SQLite-based
-// SafeBrowsingDatabaseBloom to the new file format with
-// SafeBrowsingDatabaseNew.  Once that conversion is too far along to
-// consider reversing, circle back and lift SafeBrowsingDatabaseNew up
-// to SafeBrowsingDatabase and get rid of the abstract class.
+// TODO(shess): There's no need for a factory any longer.  Convert
+// SafeBrowsingDatabaseNew to SafeBrowsingDatabase, and have Create()
+// callers just construct things directly.
 SafeBrowsingDatabase* SafeBrowsingDatabase::Create(
     bool enable_download_protection) {
   if (!factory_)
@@ -259,7 +287,7 @@
 
 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew()
     : creation_loop_(MessageLoop::current()),
-      browse_store_(new SafeBrowsingStoreSqlite),
+      browse_store_(new SafeBrowsingStoreFile),
       download_store_(NULL),
       ALLOW_THIS_IN_INITIALIZER_LIST(reset_factory_(this)) {
   DCHECK(browse_store_.get());
@@ -287,7 +315,7 @@
   // until it returns, there are no pointers to this class on other
   // threads.  Then again, that means there is no possibility of
   // contention on the lock...
-  AutoLock locked(lookup_lock_);
+  base::AutoLock locked(lookup_lock_);
 
   DCHECK(browse_filename_.empty());  // Ensure we haven't been run before.
   DCHECK(download_filename_.empty());  // Ensure we haven't been run before.
@@ -324,13 +352,16 @@
 
   // Reset objects in memory.
   {
-    AutoLock locked(lookup_lock_);
+    base::AutoLock locked(lookup_lock_);
     full_browse_hashes_.clear();
     pending_browse_hashes_.clear();
     prefix_miss_cache_.clear();
     // TODO(shess): This could probably be |bloom_filter_.reset()|.
     browse_bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize *
                                            BloomFilter::kBloomFilterSizeRatio);
+    // TODO(shess): It is simpler for the code to assume that presence
+    // of a bloom filter always implies presence of a prefix set.
+    prefix_set_.reset(CreatePrefixSet(std::vector<SBAddPrefix>()));
   }
 
   return true;
@@ -355,17 +386,28 @@
 
   // This function is called on the I/O thread, prevent changes to
   // bloom filter and caches.
-  AutoLock locked(lookup_lock_);
+  base::AutoLock locked(lookup_lock_);
 
   if (!browse_bloom_filter_.get())
     return false;
+  DCHECK(prefix_set_.get());
 
   size_t miss_count = 0;
   for (size_t i = 0; i < prefixes.size(); ++i) {
+    bool found = prefix_set_->Exists(prefixes[i]);
+
     if (browse_bloom_filter_->Exists(prefixes[i])) {
+      RecordPrefixSetInfo(PREFIX_SET_EVENT_BLOOM_HIT);
+      if (found)
+        RecordPrefixSetInfo(PREFIX_SET_EVENT_HIT);
       prefix_hits->push_back(prefixes[i]);
       if (prefix_miss_cache_.count(prefixes[i]) > 0)
         ++miss_count;
+    } else {
+      // Bloom filter misses should never be in prefix set.
+      DCHECK(!found);
+      if (found)
+        RecordPrefixSetInfo(PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT);
     }
   }
 
@@ -566,6 +608,8 @@
   SafeBrowsingStore* store = GetStore(list_id);
   if (!store) return;
 
+  change_detected_ = true;
+
   store->BeginChunk();
   if (chunks.front().is_add) {
     InsertAddChunks(list_id, chunks);
@@ -590,6 +634,8 @@
   SafeBrowsingStore* store = GetStore(list_id);
   if (!store) return;
 
+  change_detected_ = true;
+
   for (size_t i = 0; i < chunk_deletes.size(); ++i) {
     std::vector<int> chunk_numbers;
     RangesToChunks(chunk_deletes[i].chunk_del, &chunk_numbers);
@@ -607,7 +653,7 @@
     const std::vector<SBPrefix>& prefixes,
     const std::vector<SBFullHashResult>& full_hits) {
   // This is called on the I/O thread, lock against updates.
-  AutoLock locked(lookup_lock_);
+  base::AutoLock locked(lookup_lock_);
 
   if (full_hits.empty()) {
     prefix_miss_cache_.insert(prefixes.begin(), prefixes.end());
@@ -677,6 +723,7 @@
   }
 
   corruption_detected_ = false;
+  change_detected_ = false;
   return true;
 }
 
@@ -685,8 +732,13 @@
   if (corruption_detected_)
     return;
 
-  // Unroll any partially-received transaction.
-  if (!update_succeeded) {
+  // Unroll the transaction if there was a protocol error or if the
+  // transaction was empty.  This will leave the bloom filter, the
+  // pending hashes, and the prefix miss cache in place.
+  if (!update_succeeded || !change_detected_) {
+    // Track empty updates to answer questions at http://crbug.com/72216 .
+    if (update_succeeded && !change_detected_)
+      UMA_HISTOGRAM_COUNTS("SB2.DatabaseUpdateKilobytes", 0);
     browse_store_->CancelUpdate();
     if (download_store_.get())
       download_store_->CancelUpdate();
@@ -716,10 +768,10 @@
   std::vector<SBAddPrefix> add_prefixes_result;
   std::vector<SBAddFullHash> add_full_hashes_result;
 
-  if (download_store_->FinishUpdate(empty_add_hashes,
-                                    empty_miss_cache,
-                                    &add_prefixes_result,
-                                    &add_full_hashes_result))
+  if (!download_store_->FinishUpdate(empty_add_hashes,
+                                     empty_miss_cache,
+                                     &add_prefixes_result,
+                                     &add_full_hashes_result))
     RecordFailure(FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH);
   return;
 }
@@ -729,7 +781,7 @@
   // case |ContainsBrowseURL()| is called before the new filter is complete.
   std::vector<SBAddFullHash> pending_add_hashes;
   {
-    AutoLock locked(lookup_lock_);
+    base::AutoLock locked(lookup_lock_);
     pending_add_hashes.insert(pending_add_hashes.end(),
                               pending_browse_hashes_.begin(),
                               pending_browse_hashes_.end());
@@ -772,13 +824,16 @@
     filter->Insert(add_prefixes[i].prefix);
   }
 
+  scoped_ptr<safe_browsing::PrefixSet>
+      prefix_set(CreatePrefixSet(add_prefixes));
+
   // This needs to be in sorted order by prefix for efficient access.
   std::sort(add_full_hashes.begin(), add_full_hashes.end(),
             SBAddFullHashPrefixLess);
 
   // Swap in the newly built filter and cache.
   {
-    AutoLock locked(lookup_lock_);
+    base::AutoLock locked(lookup_lock_);
     full_browse_hashes_.swap(add_full_hashes);
 
     // TODO(shess): If |CacheHashResults()| is posted between the
@@ -789,6 +844,7 @@
     pending_browse_hashes_.clear();
     prefix_miss_cache_.clear();
     browse_bloom_filter_.swap(filter);
+    prefix_set_.swap(prefix_set);
   }
 
   const base::TimeDelta bloom_gen = base::Time::Now() - before;
@@ -872,6 +928,12 @@
 
   if (!browse_bloom_filter_.get())
     RecordFailure(FAILURE_DATABASE_FILTER_READ);
+
+  // Manually re-generate the prefix set from the main database.
+  // TODO(shess): Write/read for prefix set.
+  std::vector<SBAddPrefix> add_prefixes;
+  browse_store_->GetAddPrefixes(&add_prefixes);
+  prefix_set_.reset(CreatePrefixSet(add_prefixes));
 }
 
 bool SafeBrowsingDatabaseNew::Delete() {
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h
index 980a8d3..d233ec6 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -10,8 +10,8 @@
 #include <vector>
 
 #include "base/file_path.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
@@ -20,6 +20,10 @@
   class Time;
 }
 
+namespace safe_browsing {
+class PrefixSet;
+}
+
 class BloomFilter;
 class GURL;
 class MessageLoop;
@@ -236,7 +240,7 @@
   // Lock for protecting access to variables that may be used on the
   // IO thread.  This includes |browse_bloom_filter_|, |full_browse_hashes_|,
   // |pending_browse_hashes_|, and |prefix_miss_cache_|.
-  Lock lookup_lock_;
+  base::Lock lookup_lock_;
 
   // Underlying persistent store for chunk data.
   // For browsing related (phishing and malware URLs) chunks and prefixes.
@@ -272,6 +276,13 @@
   // Causes the update functions to fail with no side effects, until
   // the next call to |UpdateStarted()|.
   bool corruption_detected_;
+
+  // Set to true if any chunks are added or deleted during an update.
+  // Used to optimize away database update.
+  bool change_detected_;
+
+  // Used to check if a prefix was in the database.
+  scoped_ptr<safe_browsing::PrefixSet> prefix_set_;
 };
 
 #endif  // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index 249c44c..8491212 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/time.h"
 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
-#include "chrome/browser/safe_browsing/safe_browsing_store_sqlite.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -218,57 +217,6 @@
   }
 };
 
-// Helper function which corrupts the root page of the indicated
-// table.  After this the table can be opened successfully, and
-// queries to other tables work, and possibly queries to this table
-// which only hit an index may work, but queries which hit the table
-// itself should not.  Returns |true| on success.
-bool CorruptSqliteTable(const FilePath& filename,
-                        const std::string& table_name) {
-  size_t root_page;  // Root page of the table.
-  size_t page_size;  // Page size of the database.
-
-  sql::Connection db;
-  if (!db.Open(filename))
-    return false;
-
-  sql::Statement stmt(db.GetUniqueStatement("PRAGMA page_size"));
-  if (!stmt.Step())
-    return false;
-  page_size = stmt.ColumnInt(0);
-
-  stmt.Assign(db.GetUniqueStatement(
-      "SELECT rootpage FROM sqlite_master WHERE name = ?"));
-  stmt.BindString(0, "sub_prefix");
-  if (!stmt.Step())
-    return false;
-  root_page = stmt.ColumnInt(0);
-
-  // The page numbers are 1-based.
-  const size_t root_page_offset = (root_page - 1) * page_size;
-
-  // Corrupt the file by overwriting the table's root page.
-  FILE* fp = file_util::OpenFile(filename, "r+");
-  if (!fp)
-    return false;
-
-  file_util::ScopedFILE file_closer(fp);
-  if (fseek(fp, root_page_offset, SEEK_SET) == -1)
-    return false;
-
-  for (size_t i = 0; i < page_size; ++i) {
-    fputc('!', fp);  // Character experimentally verified.
-  }
-
-  // Close the file manually because if there is an error in the
-  // close, it's likely because the data could not be flushed to the
-  // file.
-  if (!file_util::CloseFile(file_closer.release()))
-    return false;
-
-  return true;
-}
-
 }  // namespace
 
 class SafeBrowsingDatabaseTest : public PlatformTest {
@@ -431,7 +379,6 @@
   InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
                               "www.evil.com/malware.html");
   chunks.push_back(chunk);
-
   std::vector<SBListChunkRanges> lists;
   EXPECT_TRUE(database_->UpdateStarted(&lists));
   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
@@ -1089,84 +1036,6 @@
 // corruption is detected in the midst of the update.
 // TODO(shess): Disabled until ScopedLogMessageIgnorer resolved.
 // http://crbug.com/56448
-TEST_F(SafeBrowsingDatabaseTest, DISABLED_SqliteCorruptionHandling) {
-  // Re-create the database in a captive message loop so that we can
-  // influence task-posting.  Database specifically needs to the
-  // SQLite-backed.
-  database_.reset();
-  MessageLoop loop(MessageLoop::TYPE_DEFAULT);
-  SafeBrowsingStoreSqlite* store = new SafeBrowsingStoreSqlite();
-  database_.reset(new SafeBrowsingDatabaseNew(store, NULL));
-  database_->Init(database_filename_);
-
-  // This will cause an empty database to be created.
-  std::vector<SBListChunkRanges> lists;
-  EXPECT_TRUE(database_->UpdateStarted(&lists));
-  database_->UpdateFinished(true);
-
-  // Create a sub chunk to insert.
-  SBChunkList chunks;
-  SBChunk chunk;
-  SBChunkHost host;
-  host.host = Sha256Prefix("www.subbed.com/");
-  host.entry = SBEntry::Create(SBEntry::SUB_PREFIX, 1);
-  host.entry->set_chunk_id(7);
-  host.entry->SetChunkIdAtPrefix(0, 19);
-  host.entry->SetPrefixAt(0, Sha256Prefix("www.subbed.com/notevil1.html"));
-  chunk.chunk_number = 7;
-  chunk.is_add = false;
-  chunk.hosts.clear();
-  chunk.hosts.push_back(host);
-  chunks.clear();
-  chunks.push_back(chunk);
-
-  // Corrupt the |sub_prefix| table.
-  ASSERT_TRUE(CorruptSqliteTable(database_filename_, "sub_prefix"));
-
-  {
-    // The following code will cause DCHECKs, so suppress the crashes.
-    ScopedLogMessageIgnorer ignorer;
-
-    // Start an update.  The insert will fail due to corruption.
-    EXPECT_TRUE(database_->UpdateStarted(&lists));
-    VLOG(1) << "Expect failed check on: sqlite error 11";
-    database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
-
-    // Database file still exists until the corruption handler has run.
-    EXPECT_TRUE(file_util::PathExists(database_filename_));
-
-    // Flush through the corruption-handler task.
-    VLOG(1) << "Expect failed check on: SafeBrowsing database reset";
-    MessageLoop::current()->RunAllPending();
-  }
-
-  // Database file should not exist.
-  EXPECT_FALSE(file_util::PathExists(database_filename_));
-
-  // Finish the transaction.  This should short-circuit, so no
-  // DCHECKs.
-  database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
-  database_->UpdateFinished(true);
-
-  // Flush through any posted tasks.
-  MessageLoop::current()->RunAllPending();
-
-  // Database file should still not exist.
-  EXPECT_FALSE(file_util::PathExists(database_filename_));
-
-  // Run the update again successfully.
-  EXPECT_TRUE(database_->UpdateStarted(&lists));
-  database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
-  database_->UpdateFinished(true);
-  EXPECT_TRUE(file_util::PathExists(database_filename_));
-
-  database_.reset();
-}
-
-// Test that corrupt databases are appropriately handled, even if the
-// corruption is detected in the midst of the update.
-// TODO(shess): Disabled until ScopedLogMessageIgnorer resolved.
-// http://crbug.com/56448
 TEST_F(SafeBrowsingDatabaseTest, DISABLED_FileCorruptionHandling) {
   // Re-create the database in a captive message loop so that we can
   // influence task-posting.  Database specifically needs to the
@@ -1290,3 +1159,191 @@
   EXPECT_EQ(prefix_hits.size(), 0U);
   database_.reset();
 }
+
+// Test to make sure we could insert chunk list that
+// contains entries for the same host.
+TEST_F(SafeBrowsingDatabaseTest, SameHostEntriesOkay) {
+  SBChunk chunk;
+
+  // Add a malware add chunk with two entries of the same host.
+  InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
+                              "www.evil.com/malware1.html");
+  InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
+                              "www.evil.com/malware2.html");
+  SBChunkList chunks;
+  chunks.push_back(chunk);
+
+  // Insert the testing chunks into database.
+  std::vector<SBListChunkRanges> lists;
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
+  database_->UpdateFinished(true);
+
+  GetListsInfo(&lists);
+  EXPECT_EQ(std::string(safe_browsing_util::kMalwareList), lists[0].name);
+  EXPECT_EQ("1", lists[0].adds);
+  EXPECT_TRUE(lists[0].subs.empty());
+
+  // Add a phishing add chunk with two entries of the same host.
+  chunk.hosts.clear();
+  InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
+                              "www.evil.com/phishing1.html");
+  InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
+                              "www.evil.com/phishing2.html");
+  chunks.clear();
+  chunks.push_back(chunk);
+
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
+  database_->UpdateFinished(true);
+
+  GetListsInfo(&lists);
+  EXPECT_EQ(std::string(safe_browsing_util::kMalwareList), lists[0].name);
+  EXPECT_EQ("1", lists[0].adds);
+  EXPECT_EQ(std::string(safe_browsing_util::kPhishingList), lists[1].name);
+  EXPECT_EQ("47", lists[1].adds);
+
+  const Time now = Time::Now();
+  std::vector<SBPrefix> prefixes;
+  std::vector<SBFullHashResult> full_hashes;
+  std::vector<SBPrefix> prefix_hits;
+  std::string matching_list;
+  std::string listname;
+
+  EXPECT_TRUE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/malware1.html"),
+      &listname, &prefixes, &full_hashes, now));
+  EXPECT_TRUE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/malware2.html"),
+      &listname, &prefixes, &full_hashes, now));
+  EXPECT_TRUE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/phishing1.html"),
+      &listname, &prefixes, &full_hashes, now));
+  EXPECT_TRUE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/phishing2.html"),
+      &listname, &prefixes, &full_hashes, now));
+
+  // Test removing a single prefix from the add chunk.
+  // Remove the prefix that added first.
+  chunk.hosts.clear();
+  InsertSubChunkHostPrefixUrl(&chunk, 4, 1, "www.evil.com/",
+                              "www.evil.com/malware1.html");
+  chunks.clear();
+  chunks.push_back(chunk);
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
+  database_->UpdateFinished(true);
+
+  // Remove the prefix that added last.
+  chunk.hosts.clear();
+  InsertSubChunkHostPrefixUrl(&chunk, 5, 47, "www.evil.com/",
+                              "www.evil.com/phishing2.html");
+  chunks.clear();
+  chunks.push_back(chunk);
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
+  database_->UpdateFinished(true);
+
+  // Verify that the database contains urls expected.
+  EXPECT_FALSE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/malware1.html"),
+      &listname, &prefixes, &full_hashes, now));
+  EXPECT_TRUE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/malware2.html"),
+      &listname, &prefixes, &full_hashes, now));
+  EXPECT_TRUE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/phishing1.html"),
+      &listname, &prefixes, &full_hashes, now));
+  EXPECT_FALSE(database_->ContainsBrowseUrl(
+      GURL("http://www.evil.com/phishing2.html"),
+      &listname, &prefixes, &full_hashes, now));
+}
+
+TEST_F(SafeBrowsingDatabaseTest, BinHashEntries) {
+  database_.reset();
+  MessageLoop loop(MessageLoop::TYPE_DEFAULT);
+  SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
+  SafeBrowsingStoreFile* download_store = new SafeBrowsingStoreFile();
+  database_.reset(new SafeBrowsingDatabaseNew(browse_store, download_store));
+  database_->Init(database_filename_);
+
+  SBChunkList chunks;
+  SBChunk chunk;
+  // Insert one host.
+  InsertAddChunkHostPrefixValue(&chunk, 1, 0, 0x31313131);
+  // Insert a second host, which has the same host prefix as the first one.
+  InsertAddChunkHostPrefixValue(&chunk, 1, 0, 0x32323232);
+  chunks.push_back(chunk);
+
+  // Insert the testing chunks into database.
+  std::vector<SBListChunkRanges> lists;
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->InsertChunks(safe_browsing_util::kBinHashList, chunks);
+  database_->UpdateFinished(true);
+
+  GetListsInfo(&lists);
+  ASSERT_EQ(4U, lists.size());
+  EXPECT_EQ(std::string(safe_browsing_util::kBinHashList), lists[3].name);
+  EXPECT_EQ("1", lists[3].adds);
+  EXPECT_TRUE(lists[3].subs.empty());
+
+  // TODO(lzheng): Query database and verifies the prefixes once that API
+  // database is available in database.
+  database_.reset();
+}
+
+// Test that an empty update doesn't actually update the database.
+// This isn't a functionality requirement, but it is a useful
+// optimization.
+TEST_F(SafeBrowsingDatabaseTest, EmptyUpdate) {
+  SBChunkList chunks;
+  SBChunk chunk;
+
+  FilePath filename = database_->BrowseDBFilename(database_filename_);
+
+  // Prime the database.
+  std::vector<SBListChunkRanges> lists;
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+
+  InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
+                              "www.evil.com/malware.html");
+  chunks.clear();
+  chunks.push_back(chunk);
+  database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
+  database_->UpdateFinished(true);
+
+  // Inserting another chunk updates the database file.  The sleep is
+  // needed because otherwise the entire test can finish w/in the
+  // resolution of the lastmod time.
+  base::PlatformFileInfo before_info, after_info;
+  base::PlatformThread::Sleep(1500);
+  ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  chunk.hosts.clear();
+  InsertAddChunkHostPrefixUrl(&chunk, 2, "www.foo.com/",
+                              "www.foo.com/malware.html");
+  chunks.clear();
+  chunks.push_back(chunk);
+  database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
+  database_->UpdateFinished(true);
+  ASSERT_TRUE(file_util::GetFileInfo(filename, &after_info));
+  EXPECT_LT(before_info.last_modified, after_info.last_modified);
+
+  // Deleting a chunk updates the database file.
+  base::PlatformThread::Sleep(1500);
+  ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  AddDelChunk(safe_browsing_util::kMalwareList, chunk.chunk_number);
+  database_->UpdateFinished(true);
+  ASSERT_TRUE(file_util::GetFileInfo(filename, &after_info));
+  EXPECT_LT(before_info.last_modified, after_info.last_modified);
+
+  // Simply calling |UpdateStarted()| then |UpdateFinished()| does not
+  // update the database file.
+  base::PlatformThread::Sleep(1500);
+  ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
+  EXPECT_TRUE(database_->UpdateStarted(&lists));
+  database_->UpdateFinished(true);
+  ASSERT_TRUE(file_util::GetFileInfo(filename, &after_info));
+  EXPECT_EQ(before_info.last_modified, after_info.last_modified);
+}
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index c4e8eff..11d0657 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -9,6 +9,7 @@
 #include "base/lazy_instance.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/metrics/metrics_service.h"
@@ -47,6 +48,7 @@
 const char* const kSbDefaultMacKeyURLPrefix =
     "https://sb-ssl.google.com/safebrowsing";
 
+// TODO(lzheng): Replace this with Profile* ProfileManager::GetDefaultProfile().
 Profile* GetDefaultProfile() {
   FilePath user_data_dir;
   PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
@@ -154,6 +156,20 @@
          url.SchemeIs(chrome::kHttpsScheme);
 }
 
+// Only report SafeBrowsing related stats when UMA is enabled and
+// safe browsing is enabled.
+bool SafeBrowsingService::CanReportStats() const {
+  const MetricsService* metrics = g_browser_process->metrics_service();
+  const PrefService* pref_service = GetDefaultProfile()->GetPrefs();
+  return metrics && metrics->reporting_active() &&
+      pref_service && pref_service->GetBoolean(prefs::kSafeBrowsingEnabled);
+}
+
+// Binhash verification is only enabled for UMA users for now.
+bool SafeBrowsingService::DownloadBinHashNeeded() const {
+  return enable_download_protection_ && CanReportStats();
+}
+
 void SafeBrowsingService::CheckDownloadUrlDone(
     SafeBrowsingCheck* check, UrlCheckResult result) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -281,13 +297,15 @@
   }
 }
 
-void SafeBrowsingService::DisplayBlockingPage(const GURL& url,
-                                              const GURL& original_url,
-                                              ResourceType::Type resource_type,
-                                              UrlCheckResult result,
-                                              Client* client,
-                                              int render_process_host_id,
-                                              int render_view_id) {
+void SafeBrowsingService::DisplayBlockingPage(
+    const GURL& url,
+    const GURL& original_url,
+    const std::vector<GURL>& redirect_urls,
+    ResourceType::Type resource_type,
+    UrlCheckResult result,
+    Client* client,
+    int render_process_host_id,
+    int render_view_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // Check if the user has already ignored our warning for this render_view
@@ -309,6 +327,7 @@
   UnsafeResource resource;
   resource.url = url;
   resource.original_url = original_url;
+  resource.redirect_urls = redirect_urls;
   resource.resource_type = resource_type;
   resource.threat_type= result;
   resource.client = client;
@@ -560,7 +579,12 @@
   // Note that to avoid leaking the database, we rely on the fact that no new
   // tasks will be added to the db thread between the call above and this one.
   // See comments on the declaration of |safe_browsing_thread_|.
-  safe_browsing_thread_.reset();
+  {
+    // A ScopedAllowIO object is required to join the thread when calling Stop.
+    // See http://crbug.com/72696.
+    base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
+    safe_browsing_thread_.reset();
+  }
 
   // Delete pending checks, calling back any clients with 'URL_SAFE'.  We have
   // to do this after the db thread returns because methods on it can have
@@ -577,7 +601,7 @@
 }
 
 bool SafeBrowsingService::DatabaseAvailable() const {
-  AutoLock lock(database_lock_);
+  base::AutoLock lock(database_lock_);
   return !closing_database_ && (database_ != NULL);
 }
 
@@ -610,7 +634,7 @@
   {
     // Acquiring the lock here guarantees correct ordering between the writes to
     // the new database object above, and the setting of |databse_| below.
-    AutoLock lock(database_lock_);
+    base::AutoLock lock(database_lock_);
     database_ = database;
   }
 
@@ -814,7 +838,7 @@
   // of |database_| above and of |closing_database_| below, which ensures there
   // won't be a window during which the IO thread falsely believes the database
   // is available.
-  AutoLock lock(database_lock_);
+  base::AutoLock lock(database_lock_);
   closing_database_ = false;
 }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index 73eb201..abebc32 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -15,9 +15,9 @@
 #include <vector>
 
 #include "base/hash_tables.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
 #include "googleurl/src/gurl.h"
@@ -84,6 +84,7 @@
 
     GURL url;
     GURL original_url;
+    std::vector<GURL> redirect_urls;
     ResourceType::Type resource_type;
     UrlCheckResult threat_type;
     Client* client;
@@ -117,6 +118,10 @@
   // Create an instance of the safe browsing service.
   static SafeBrowsingService* CreateSafeBrowsingService();
 
+  // Called on UI thread to decide if safe browsing related stats
+  // could be reported.
+  bool CanReportStats() const;
+
   // Called on the UI thread to initialize the service.
   void Initialize();
 
@@ -126,6 +131,10 @@
   // Returns true if the url's scheme can be checked.
   bool CanCheckUrl(const GURL& url) const;
 
+  // Called on UI thread to decide if the download file's sha256 hash
+  // should be calculated for safebrowsing.
+  bool DownloadBinHashNeeded() const;
+
   // Called on the IO thread to check if the given url is safe or not.  If we
   // can synchronously determine that the url is safe, CheckUrl returns true.
   // Otherwise it returns false, and "client" is called asynchronously with the
@@ -147,6 +156,7 @@
   // chain). Otherwise, |original_url| = |url|.
   void DisplayBlockingPage(const GURL& url,
                            const GURL& original_url,
+                           const std::vector<GURL>& redirect_urls,
                            ResourceType::Type resource_type,
                            UrlCheckResult result,
                            Client* client,
@@ -340,12 +350,12 @@
   // Used for issuing only one GetHash request for a given prefix.
   GetHashRequests gethash_requests_;
 
-  // The sqlite database.  We don't use a scoped_ptr because it needs to be
-  // destructed on a different thread than this object.
+  // The persistent database.  We don't use a scoped_ptr because it
+  // needs to be destructed on a different thread than this object.
   SafeBrowsingDatabase* database_;
 
   // Lock used to prevent possible data races due to compiler optimizations.
-  mutable Lock database_lock_;
+  mutable base::Lock database_lock_;
 
   // Handles interaction with SafeBrowsing servers.
   SafeBrowsingProtocolManager* protocol_manager_;
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.cc b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
index cc8ae87..fcdb4ce 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
@@ -8,9 +8,6 @@
 #include "base/metrics/histogram.h"
 #include "base/md5.h"
 
-// TODO(shess): Remove after migration.
-#include "chrome/browser/safe_browsing/safe_browsing_store_sqlite.h"
-
 namespace {
 
 // NOTE(shess): kFileMagic should not be a byte-wise palindrome, so
@@ -261,16 +258,13 @@
     return false;
   }
 
-  // Also make sure any SQLite data is deleted.  This should only be
-  // needed if a journal file is left from a crash and the database is
-  // reset before SQLite gets a chance to straighten things out.
-  // TODO(shess): Remove after migration.
-  SafeBrowsingStoreSqlite old_store;
-  old_store.Init(
-      filename_,
-      NewCallback(this, &SafeBrowsingStoreFile::HandleCorruptDatabase));
-  if (!old_store.Delete())
-    return false;
+  // With SQLite support gone, one way to get to this code is if the
+  // existing file is a SQLite file.  Make sure the journal file is
+  // also removed.
+  const FilePath journal_filename(
+      filename_.value() + FILE_PATH_LITERAL("-journal"));
+  if (file_util::PathExists(journal_filename))
+    file_util::Delete(journal_filename, false);
 
   return true;
 }
@@ -344,27 +338,17 @@
   return false;
 }
 
-void SafeBrowsingStoreFile::HandleCorruptDatabase() {
-  if (!corruption_seen_)
-    RecordFormatEvent(FORMAT_EVENT_SQLITE_CORRUPT);
-  corruption_seen_ = true;
-
-  if (corruption_callback_.get())
-    corruption_callback_->Run();
-}
-
 bool SafeBrowsingStoreFile::Close() {
   ClearUpdateBuffers();
 
   // Make sure the files are closed.
   file_.reset();
   new_file_.reset();
-  old_store_.reset();
   return true;
 }
 
 bool SafeBrowsingStoreFile::BeginUpdate() {
-  DCHECK(!file_.get() && !new_file_.get() && !old_store_.get());
+  DCHECK(!file_.get() && !new_file_.get());
 
   // Structures should all be clear unless something bad happened.
   DCHECK(add_chunks_cache_.empty());
@@ -412,32 +396,10 @@
       RecordFormatEvent(FORMAT_EVENT_FOUND_UNKNOWN);
     }
 
-    // Something about having the file open causes a problem with
-    // SQLite opening it.  Perhaps PRAGMA locking_mode = EXCLUSIVE?
+    // Close the file so that it can be deleted.
     file.reset();
 
-    // Magic numbers didn't match, maybe it's a SQLite database.
-    scoped_ptr<SafeBrowsingStoreSqlite>
-        sqlite_store(new SafeBrowsingStoreSqlite());
-    sqlite_store->Init(
-        filename_,
-        NewCallback(this, &SafeBrowsingStoreFile::HandleCorruptDatabase));
-    if (!sqlite_store->BeginUpdate())
-      return OnCorruptDatabase();
-
-    // Pull chunks-seen data into local structures, rather than
-    // optionally wiring various calls through to the SQLite store.
-    std::vector<int32> chunks;
-    sqlite_store->GetAddChunks(&chunks);
-    add_chunks_cache_.insert(chunks.begin(), chunks.end());
-
-    sqlite_store->GetSubChunks(&chunks);
-    sub_chunks_cache_.insert(chunks.begin(), chunks.end());
-
-    new_file_.swap(new_file);
-    old_store_.swap(sqlite_store);
-
-    return true;
+    return OnCorruptDatabase();
   }
 
   // TODO(shess): Under POSIX it is possible that this could size a
@@ -489,7 +451,7 @@
     const std::set<SBPrefix>& prefix_misses,
     std::vector<SBAddPrefix>* add_prefixes_result,
     std::vector<SBAddFullHash>* add_full_hashes_result) {
-  DCHECK(old_store_.get() || file_.get() || empty_);
+  DCHECK(file_.get() || empty_);
   DCHECK(new_file_.get());
   CHECK(add_prefixes_result);
   CHECK(add_full_hashes_result);
@@ -499,29 +461,8 @@
   std::vector<SBAddFullHash> add_full_hashes;
   std::vector<SBSubFullHash> sub_full_hashes;
 
-  // Read |old_store_| into the vectors.
-  if (old_store_.get()) {
-    // Push deletions to |old_store_| so they can be applied to the
-    // data being read.
-    for (base::hash_set<int32>::const_iterator iter = add_del_cache_.begin();
-         iter != add_del_cache_.end(); ++iter) {
-      old_store_->DeleteAddChunk(*iter);
-    }
-    for (base::hash_set<int32>::const_iterator iter = sub_del_cache_.begin();
-         iter != sub_del_cache_.end(); ++iter) {
-      old_store_->DeleteSubChunk(*iter);
-    }
-
-    if (!old_store_->ReadAddPrefixes(&add_prefixes) ||
-        !old_store_->ReadSubPrefixes(&sub_prefixes) ||
-        !old_store_->ReadAddHashes(&add_full_hashes) ||
-        !old_store_->ReadSubHashes(&sub_full_hashes))
-      return OnCorruptDatabase();
-
-    // Do not actually update the old store.
-    if (!old_store_->CancelUpdate())
-      return OnCorruptDatabase();
-  } else if (!empty_) {
+  // Read original data into the vectors.
+  if (!empty_) {
     DCHECK(file_.get());
 
     if (!FileRewind(file_.get()))
@@ -580,6 +521,12 @@
   if (!file_util::GetFileSize(TemporaryFileForFilename(filename_), &size))
     return OnCorruptDatabase();
 
+  // Track update size to answer questions at http://crbug.com/72216 .
+  // Log small updates as 1k so that the 0 (underflow) bucket can be
+  // used for "empty" in SafeBrowsingDatabase.
+  UMA_HISTOGRAM_COUNTS("SB2.DatabaseUpdateKilobytes",
+                       std::max(static_cast<int>(size / 1024), 1));
+
   // Append the accumulated chunks onto the vectors read from |file_|.
   for (int i = 0; i < chunks_written_; ++i) {
     ChunkHeader header;
@@ -677,19 +624,9 @@
 
   // Close the file handle and swizzle the file into place.
   new_file_.reset();
-  if (old_store_.get()) {
-    const bool deleted = old_store_->Delete();
-    old_store_.reset();
-    if (!deleted) {
-      RecordFormatEvent(FORMAT_EVENT_SQLITE_DELETE_FAILED);
-      return false;
-    }
-    RecordFormatEvent(FORMAT_EVENT_SQLITE_DELETED);
-  } else {
-    if (!file_util::Delete(filename_, false) &&
-        file_util::PathExists(filename_))
-      return false;
-  }
+  if (!file_util::Delete(filename_, false) &&
+      file_util::PathExists(filename_))
+    return false;
 
   const FilePath new_filename = TemporaryFileForFilename(filename_);
   if (!file_util::Move(new_filename, filename_))
@@ -724,13 +661,11 @@
 
   DCHECK(!new_file_.get());
   DCHECK(!file_.get());
-  DCHECK(!old_store_.get());
 
   return Close();
 }
 
 bool SafeBrowsingStoreFile::CancelUpdate() {
-  old_store_.reset();
   return Close();
 }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.h b/chrome/browser/safe_browsing/safe_browsing_store_file.h
index 02a2920..88e1b2f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file.h
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file.h
@@ -14,12 +14,6 @@
 #include "base/callback.h"
 #include "base/file_util.h"
 
-// TODO(shess): Data is migrated from SafeBrowsingStoreSqlite as part
-// of the next update.  That way everyone doesn't pull a new database
-// when the code rolls out (and the migration code isn't gnarly).
-// After substantially everyone has migrated, the migration code can
-// be removed.  Make sure that it deletes any journal file.
-
 // Implement SafeBrowsingStore in terms of a flat file.  The file
 // format is pretty literal:
 //
@@ -110,9 +104,6 @@
 // often, consider retaining the last known-good file for recovery
 // purposes, rather than deleting it.
 
-// TODO(shess): Remove after migration.
-class SafeBrowsingStoreSqlite;
-
 class SafeBrowsingStoreFile : public SafeBrowsingStore {
  public:
   SafeBrowsingStoreFile();
@@ -176,7 +167,7 @@
   enum FormatEventType {
     // Corruption detected, broken down by file format.
     FORMAT_EVENT_FILE_CORRUPT,
-    FORMAT_EVENT_SQLITE_CORRUPT,
+    FORMAT_EVENT_SQLITE_CORRUPT,  // Obsolete
 
     // The type of format found in the file.  The expected case (new
     // file format) is intentionally not covered.
@@ -186,8 +177,8 @@
     // The number of SQLite-format files deleted should be the same as
     // FORMAT_EVENT_FOUND_SQLITE.  It can differ if the delete fails,
     // or if a failure prevents the update from succeeding.
-    FORMAT_EVENT_SQLITE_DELETED,
-    FORMAT_EVENT_SQLITE_DELETE_FAILED,
+    FORMAT_EVENT_SQLITE_DELETED,  // Obsolete
+    FORMAT_EVENT_SQLITE_DELETE_FAILED,  // Obsolete
 
     // Found and deleted (or failed to delete) the ancient "Safe
     // Browsing" file.
@@ -263,11 +254,6 @@
   file_util::ScopedFILE new_file_;
   bool empty_;
 
-  // If the main file existed, but was an SQLite store, this is a
-  // handle to it.
-  // TODO(shess): Remove this (and all references) after migration.
-  scoped_ptr<SafeBrowsingStoreSqlite> old_store_;
-
   // Cache of chunks which have been seen.  Loaded from the database
   // on BeginUpdate() so that it can be queried during the
   // transaction.
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
index 01977a7..39fe53a 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
-#include "chrome/browser/safe_browsing/safe_browsing_store_sqlite.h"
 
 #include "base/callback.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
@@ -146,169 +145,4 @@
   EXPECT_TRUE(corruption_detected_);
 }
 
-// Info to build a trivial store for migration testing.
-const int kAddChunk1 = 1;
-const int kAddChunk2 = 3;
-const int kAddChunk3 = 5;
-const int kSubChunk1 = 2;
-const int kSubChunk2 = 4;
-const SBFullHash kHash1 = SBFullHashFromString("one");
-const SBFullHash kHash2 = SBFullHashFromString("two");
-const SBPrefix kPrefix1 = kHash1.prefix;
-const SBPrefix kPrefix2 = kHash2.prefix;
-const SBPrefix kPrefix3 = SBFullHashFromString("three").prefix;
-const SBPrefix kPrefix4 = SBFullHashFromString("four").prefix;
-const SBPrefix kPrefix5 = SBFullHashFromString("five").prefix;
-
-// Load the store with some data.
-void LoadStore(SafeBrowsingStore* store) {
-  EXPECT_TRUE(store->BeginUpdate());
-  EXPECT_TRUE(store->BeginChunk());
-
-  store->SetAddChunk(kAddChunk1);
-  store->SetSubChunk(kSubChunk1);
-  store->SetAddChunk(kAddChunk2);
-
-  EXPECT_TRUE(store->WriteAddPrefix(kAddChunk1, kPrefix1));
-  EXPECT_TRUE(store->WriteAddPrefix(kAddChunk1, kPrefix2));
-  EXPECT_TRUE(store->WriteAddPrefix(kAddChunk2, kPrefix3));
-  EXPECT_TRUE(store->WriteSubPrefix(kSubChunk1, kAddChunk3, kPrefix4));
-  EXPECT_TRUE(store->WriteAddHash(kAddChunk1, base::Time::Now(), kHash1));
-  EXPECT_TRUE(store->WriteSubHash(kSubChunk1, kAddChunk1, kHash2));
-
-  EXPECT_TRUE(store->FinishChunk());
-
-  std::vector<SBAddFullHash> pending_adds;
-  std::set<SBPrefix> prefix_misses;
-  std::vector<SBAddPrefix> add_prefixes;
-  std::vector<SBAddFullHash> add_hashes;
-  EXPECT_TRUE(store->FinishUpdate(pending_adds, prefix_misses,
-                                  &add_prefixes, &add_hashes));
-  EXPECT_EQ(3U, add_prefixes.size());
-  EXPECT_EQ(1U, add_hashes.size());
-
-  // Make sure add prefixes are correct.
-  std::vector<SBAddPrefix> in_store_add_prefixes;
-  EXPECT_TRUE(store->GetAddPrefixes(&in_store_add_prefixes));
-  ASSERT_EQ(3U, in_store_add_prefixes.size());
-  EXPECT_EQ(kPrefix1, in_store_add_prefixes[0].prefix);
-  EXPECT_EQ(kAddChunk1, in_store_add_prefixes[0].chunk_id);
-  EXPECT_EQ(kPrefix2, in_store_add_prefixes[1].prefix);
-  EXPECT_EQ(kAddChunk1, in_store_add_prefixes[1].chunk_id);
-  EXPECT_EQ(kPrefix3, in_store_add_prefixes[2].prefix);
-  EXPECT_EQ(kAddChunk2, in_store_add_prefixes[2].chunk_id);
-}
-
-// Verify that the store looks like what results from LoadStore(), and
-// update it.
-void UpdateStore(SafeBrowsingStore* store) {
-  EXPECT_TRUE(store->BeginUpdate());
-  EXPECT_TRUE(store->BeginChunk());
-
-  // The chunks in the database should be the same.
-  std::vector<int> add_chunks;
-  store->GetAddChunks(&add_chunks);
-  ASSERT_EQ(2U, add_chunks.size());
-  EXPECT_EQ(kAddChunk1, add_chunks[0]);
-  EXPECT_EQ(kAddChunk2, add_chunks[1]);
-
-  std::vector<int> sub_chunks;
-  store->GetSubChunks(&sub_chunks);
-  ASSERT_EQ(1U, sub_chunks.size());
-  EXPECT_EQ(kSubChunk1, sub_chunks[0]);
-
-  EXPECT_TRUE(store->CheckAddChunk(kAddChunk1));
-  EXPECT_TRUE(store->CheckSubChunk(kSubChunk1));
-  EXPECT_TRUE(store->CheckAddChunk(kAddChunk2));
-
-  EXPECT_FALSE(store->CheckAddChunk(kAddChunk3));
-  store->SetAddChunk(kAddChunk3);
-  // This one already has a sub.
-  EXPECT_TRUE(store->WriteAddPrefix(kAddChunk3, kPrefix4));
-  EXPECT_TRUE(store->WriteAddPrefix(kAddChunk3, kPrefix5));
-
-  EXPECT_FALSE(store->CheckSubChunk(kSubChunk2));
-  store->SetSubChunk(kSubChunk2);
-  EXPECT_TRUE(store->WriteSubPrefix(kSubChunk2, kAddChunk1, kPrefix1));
-
-  EXPECT_TRUE(store->FinishChunk());
-
-  store->DeleteAddChunk(kAddChunk2);
-
-  std::vector<SBAddFullHash> pending_adds;
-  std::set<SBPrefix> prefix_misses;
-  std::vector<SBAddPrefix> add_prefixes;
-  std::vector<SBAddFullHash> add_hashes;
-  EXPECT_TRUE(store->FinishUpdate(pending_adds, prefix_misses,
-                                  &add_prefixes, &add_hashes));
-  EXPECT_EQ(2U, add_prefixes.size());
-  EXPECT_EQ(0U, add_hashes.size());
-}
-
-// Verify that the expected UpdateStore() data is present.
-void CheckStore(SafeBrowsingStore* store) {
-  EXPECT_TRUE(store->BeginUpdate());
-
-  // The chunks in the database should be the same.
-  std::vector<int> add_chunks;
-  store->GetAddChunks(&add_chunks);
-  ASSERT_EQ(2U, add_chunks.size());
-  EXPECT_EQ(kAddChunk1, add_chunks[0]);
-  EXPECT_EQ(kAddChunk3, add_chunks[1]);
-
-  std::vector<int> sub_chunks;
-  store->GetSubChunks(&sub_chunks);
-  ASSERT_EQ(2U, sub_chunks.size());
-  EXPECT_EQ(kSubChunk1, sub_chunks[0]);
-  EXPECT_EQ(kSubChunk2, sub_chunks[1]);
-
-  EXPECT_TRUE(store->CancelUpdate());
-
-  // Make sure add prefixes are correct.
-  std::vector<SBAddPrefix> add_prefixes;
-  EXPECT_TRUE(store->GetAddPrefixes(&add_prefixes));
-  ASSERT_EQ(2U, add_prefixes.size());
-  EXPECT_EQ(kPrefix2, add_prefixes[0].prefix);
-  EXPECT_EQ(kAddChunk1, add_prefixes[0].chunk_id);
-  EXPECT_EQ(kPrefix5, add_prefixes[1].prefix);
-  EXPECT_EQ(kAddChunk3, add_prefixes[1].chunk_id);
-}
-
-// Verify that the migration sequence works as expected in the
-// non-migration cases.
-TEST_F(SafeBrowsingStoreFileTest, MigrateBaselineFile) {
-  LoadStore(store_.get());
-  UpdateStore(store_.get());
-  CheckStore(store_.get());
-}
-TEST_F(SafeBrowsingStoreFileTest, MigrateBaselineSqlite) {
-  SafeBrowsingStoreSqlite sqlite_store;
-  sqlite_store.Init(filename_, NULL);
-
-  LoadStore(&sqlite_store);
-  UpdateStore(&sqlite_store);
-  CheckStore(&sqlite_store);
-}
-
-// The sequence should work exactly the same when we migrate from
-// SQLite to file.
-TEST_F(SafeBrowsingStoreFileTest, Migrate) {
-  // No existing store.
-  EXPECT_FALSE(file_util::PathExists(filename_));
-
-  {
-    SafeBrowsingStoreSqlite sqlite_store;
-    sqlite_store.Init(filename_, NULL);
-
-    LoadStore(&sqlite_store);
-  }
-
-  // At this point |filename_| references a SQLite store.
-  EXPECT_TRUE(file_util::PathExists(filename_));
-
-  // Update and check using a file store.
-  UpdateStore(store_.get());
-  CheckStore(store_.get());
-}
-
 }  // namespace
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_sqlite.cc b/chrome/browser/safe_browsing/safe_browsing_store_sqlite.cc
deleted file mode 100644
index c9cf026..0000000
--- a/chrome/browser/safe_browsing/safe_browsing_store_sqlite.cc
+++ /dev/null
@@ -1,749 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/safe_browsing/safe_browsing_store_sqlite.h"
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/file_util.h"
-#include "base/metrics/histogram.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/common/sqlite_compiled_statement.h"
-#include "chrome/common/sqlite_utils.h"
-
-namespace {
-
-// Database version.  If this is different than what's stored on disk, the
-// database is reset.
-const int kDatabaseVersion = 6;
-
-// Used for reading full hashes from the database.
-SBFullHash ReadFullHash(SqliteCompiledStatement* statement, int column) {
-  std::vector<unsigned char> blob;
-  (*statement)->column_blob_as_vector(column, &blob);
-
-  SBFullHash ret;
-  DCHECK_EQ(blob.size(), sizeof(ret));
-  memcpy(ret.full_hash, &blob[0], sizeof(ret));
-  return ret;
-}
-
-void DeleteChunksFromSet(const base::hash_set<int32>& deleted,
-                         std::set<int32>* chunks) {
-  for (std::set<int32>::iterator iter = chunks->begin();
-       iter != chunks->end();) {
-    std::set<int32>::iterator prev = iter++;
-    if (deleted.count(*prev) > 0)
-      chunks->erase(prev);
-  }
-}
-
-}  // namespace
-
-SafeBrowsingStoreSqlite::SafeBrowsingStoreSqlite()
-    : db_(NULL),
-      statement_cache_(NULL),
-      insert_transaction_(NULL) {
-}
-SafeBrowsingStoreSqlite::~SafeBrowsingStoreSqlite() {
-  Close();
-}
-
-bool SafeBrowsingStoreSqlite::Delete() {
-  // The file must be closed, both so that the journal file is deleted
-  // by SQLite, and because open files cannot be deleted on Windows.
-  if (!Close()) {
-    NOTREACHED();
-    return false;
-  }
-
-  // Just in case, delete the journal file, because associating the
-  // wrong journal file with a database is very bad.
-  const FilePath journal_file = JournalFileForFilename(filename_);
-  if (!file_util::Delete(journal_file, false) &&
-      file_util::PathExists(journal_file)) {
-    NOTREACHED();
-    return false;
-  }
-
-  if (!file_util::Delete(filename_, false) &&
-      file_util::PathExists(filename_)) {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
-void SafeBrowsingStoreSqlite::Init(const FilePath& filename,
-                                   Callback0::Type* corruption_callback) {
-  filename_ = filename;
-  corruption_callback_.reset(corruption_callback);
-}
-
-bool SafeBrowsingStoreSqlite::BeginChunk() {
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::GetAddPrefixes(
-    std::vector<SBAddPrefix>* add_prefixes) {
-  add_prefixes->clear();
-  if (!Open()) return false;
-  bool ret = ReadAddPrefixes(add_prefixes);
-  Close();
-  return ret;
-}
-
-bool SafeBrowsingStoreSqlite::WriteAddPrefix(int32 chunk_id, SBPrefix prefix) {
-  const std::vector<SBAddPrefix> prefixes(1, SBAddPrefix(chunk_id, prefix));
-  return WriteAddPrefixes(prefixes);
-}
-
-bool SafeBrowsingStoreSqlite::WriteAddHash(int32 chunk_id,
-                                           base::Time receive_time,
-                                           const SBFullHash& full_hash) {
-  const std::vector<SBAddFullHash>
-      hashes(1, SBAddFullHash(chunk_id, receive_time, full_hash));
-  return WriteAddHashes(hashes);
-}
-
-bool SafeBrowsingStoreSqlite::WriteSubPrefix(int32 chunk_id,
-                                             int32 add_chunk_id,
-                                             SBPrefix prefix) {
-  const std::vector<SBSubPrefix>
-      prefixes(1, SBSubPrefix(chunk_id, add_chunk_id, prefix));
-  return WriteSubPrefixes(prefixes);
-}
-
-bool SafeBrowsingStoreSqlite::WriteSubHash(int32 chunk_id,
-                                           int32 add_chunk_id,
-                                           const SBFullHash& full_hash) {
-  const std::vector<SBSubFullHash>
-      hashes(1, SBSubFullHash(chunk_id, add_chunk_id, full_hash));
-  return WriteSubHashes(hashes);
-}
-
-bool SafeBrowsingStoreSqlite::FinishChunk() {
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::OnCorruptDatabase() {
-  if (corruption_callback_.get())
-    corruption_callback_->Run();
-  return false;
-}
-
-bool SafeBrowsingStoreSqlite::Open() {
-  // This case should never happen, but if it does we shouldn't leak
-  // handles.
-  if (db_) {
-    NOTREACHED() << " Database was already open in Open().";
-    return true;
-  }
-
-  if (sqlite_utils::OpenSqliteDb(filename_, &db_) != SQLITE_OK) {
-    sqlite3_close(db_);
-    db_ = NULL;
-    return false;
-  }
-
-  // Run the database in exclusive mode. Nobody else should be accessing the
-  // database while we're running, and this will give somewhat improved perf.
-  ExecSql("PRAGMA locking_mode = EXCLUSIVE");
-  ExecSql("PRAGMA cache_size = 100");
-
-  statement_cache_.reset(new SqliteStatementCache(db_));
-
-  if (!sqlite_utils::DoesSqliteTableExist(db_, "add_prefix"))
-    return SetupDatabase();
-
-  return CheckCompatibleVersion();
-}
-
-bool SafeBrowsingStoreSqlite::ExecSql(const char* sql) {
-  DCHECK(db_);
-
-  int rv = sqlite3_exec(db_, sql, NULL, NULL, NULL);
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  DCHECK(rv == SQLITE_OK);
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::Close() {
-  if (!db_)
-    return true;
-
-  add_chunks_cache_.clear();
-  sub_chunks_cache_.clear();
-
-  add_del_cache_.clear();
-  sub_del_cache_.clear();
-
-  insert_transaction_.reset();
-  statement_cache_.reset();  // Must free statements before closing DB.
-  bool result = sqlite3_close(db_) == SQLITE_OK;
-  db_ = NULL;
-
-  return result;
-}
-
-bool SafeBrowsingStoreSqlite::CreateTables() {
-  DCHECK(db_);
-
-  // Store 32 bit add prefixes here.
-  if (!ExecSql("CREATE TABLE add_prefix ("
-               "  chunk INTEGER,"
-               "  prefix INTEGER"
-               ")"))
-    return false;
-
-  // Store 32 bit sub prefixes here.
-  if (!ExecSql("CREATE TABLE sub_prefix ("
-               "  chunk INTEGER,"
-               "  add_chunk INTEGER,"
-               "  prefix INTEGER"
-               ")"))
-    return false;
-
-  // Store 256 bit add full hashes (and GetHash results) here.
-  if (!ExecSql("CREATE TABLE add_full_hash ("
-               "  chunk INTEGER,"
-               "  prefix INTEGER,"
-               "  receive_time INTEGER,"
-               "  full_hash BLOB"
-               ")"))
-    return false;
-
-  // Store 256 bit sub full hashes here.
-  if (!ExecSql("CREATE TABLE sub_full_hash ("
-               "  chunk INTEGER,"
-               "  add_chunk INTEGER,"
-               "  prefix INTEGER,"
-               "  full_hash BLOB"
-               ")"))
-    return false;
-
-  // Store all the add and sub chunk numbers we receive. We cannot
-  // just rely on the prefix tables to generate these lists, since
-  // some chunks will have zero entries (and thus no prefixes), or
-  // potentially an add chunk can have all of its entries sub'd
-  // without receiving an AddDel, or a sub chunk might have been
-  // entirely consumed by adds. In these cases, we still have to
-  // report the chunk number but it will not have any prefixes in the
-  // prefix tables.
-  //
-  // TODO(paulg): Investigate storing the chunks as a string of
-  // ChunkRanges, one string for each of phish-add, phish-sub,
-  // malware-add, malware-sub. This might be better performance when
-  // the number of chunks is large, and is the natural format for the
-  // update request.
-  if (!ExecSql("CREATE TABLE add_chunks ("
-               "  chunk INTEGER PRIMARY KEY"
-               ")"))
-    return false;
-
-  if (!ExecSql("CREATE TABLE sub_chunks ("
-               "  chunk INTEGER PRIMARY KEY"
-               ")"))
-    return false;
-
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::SetupDatabase() {
-  DCHECK(db_);
-
-  SQLTransaction transaction(db_);
-  if (transaction.Begin() != SQLITE_OK) {
-    NOTREACHED();
-    return false;
-  }
-
-  if (!CreateTables())
-    return false;
-
-  // PRAGMA does not support bind parameters...
-  const std::string version =
-      StringPrintf("PRAGMA user_version = %d", kDatabaseVersion);
-  if (!ExecSql(version.c_str()))
-    return false;
-
-  if (transaction.Commit() != SQLITE_OK)
-    return false;
-
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::CheckCompatibleVersion() {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "PRAGMA user_version");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int result = statement->step();
-  if (result != SQLITE_ROW)
-    return false;
-
-  return statement->column_int(0) == kDatabaseVersion;
-}
-
-bool SafeBrowsingStoreSqlite::ReadAddChunks() {
-  DCHECK(db_);
-
-  add_chunks_cache_.clear();
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "SELECT chunk FROM add_chunks");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int rv;
-  while ((rv = statement->step()) == SQLITE_ROW) {
-    add_chunks_cache_.insert(statement->column_int(0));
-  }
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  DCHECK_EQ(rv, SQLITE_DONE);
-  return rv == SQLITE_DONE;
-}
-
-bool SafeBrowsingStoreSqlite::WriteAddChunks() {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "INSERT INTO add_chunks (chunk) VALUES (?)");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  for (std::set<int32>::const_iterator iter = add_chunks_cache_.begin();
-       iter != add_chunks_cache_.end(); ++iter) {
-    statement->bind_int(0, *iter);
-    int rv = statement->step();
-    if (rv == SQLITE_CORRUPT)
-      return OnCorruptDatabase();
-    DCHECK(rv == SQLITE_DONE);
-    statement->reset();
-  }
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::ReadSubChunks() {
-  DCHECK(db_);
-
-  sub_chunks_cache_.clear();
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "SELECT chunk FROM sub_chunks");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int rv;
-  while ((rv = statement->step()) == SQLITE_ROW) {
-    sub_chunks_cache_.insert(statement->column_int(0));
-  }
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  return rv == SQLITE_DONE;
-}
-
-bool SafeBrowsingStoreSqlite::WriteSubChunks() {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "INSERT INTO sub_chunks (chunk) VALUES (?)");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  for (std::set<int32>::const_iterator iter = sub_chunks_cache_.begin();
-       iter != sub_chunks_cache_.end(); ++iter) {
-    statement->bind_int(0, *iter);
-    int rv = statement->step();
-    if (rv == SQLITE_CORRUPT)
-      return OnCorruptDatabase();
-    DCHECK(rv == SQLITE_DONE);
-    statement->reset();
-  }
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::ReadAddPrefixes(
-    std::vector<SBAddPrefix>* add_prefixes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "SELECT chunk, prefix FROM add_prefix");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int rv;
-  while ((rv = statement->step()) == SQLITE_ROW) {
-    const int32 chunk_id = statement->column_int(0);
-    const SBPrefix prefix = statement->column_int(1);
-    add_prefixes->push_back(SBAddPrefix(chunk_id, prefix));
-  }
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  DCHECK_EQ(rv, SQLITE_DONE);
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::WriteAddPrefixes(
-    const std::vector<SBAddPrefix>& add_prefixes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "INSERT INTO add_prefix "
-                          "(chunk, prefix) VALUES (?,?)");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  for (std::vector<SBAddPrefix>::const_iterator iter = add_prefixes.begin();
-       iter != add_prefixes.end(); ++iter) {
-    statement->bind_int(0, iter->chunk_id);
-    statement->bind_int(1, iter->prefix);
-    int rv = statement->step();
-    if (rv == SQLITE_CORRUPT)
-      return OnCorruptDatabase();
-    DCHECK(rv == SQLITE_DONE);
-    statement->reset();
-  }
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::ReadSubPrefixes(
-    std::vector<SBSubPrefix>* sub_prefixes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "SELECT chunk, add_chunk, prefix "
-                          "FROM sub_prefix");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int rv;
-  while ((rv = statement->step()) == SQLITE_ROW) {
-    const int32 chunk_id = statement->column_int(0);
-    const int32 add_chunk_id = statement->column_int(1);
-    const SBPrefix add_prefix = statement->column_int(2);
-    sub_prefixes->push_back(SBSubPrefix(chunk_id, add_chunk_id, add_prefix));
-  }
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  DCHECK_EQ(rv, SQLITE_DONE);
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::WriteSubPrefixes(
-    const std::vector<SBSubPrefix>& sub_prefixes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "INSERT INTO sub_prefix "
-                          "(chunk, add_chunk, prefix) VALUES (?,?, ?)");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  for (std::vector<SBSubPrefix>::const_iterator iter = sub_prefixes.begin();
-       iter != sub_prefixes.end(); ++iter) {
-    statement->bind_int(0, iter->chunk_id);
-    statement->bind_int(1, iter->add_chunk_id);
-    statement->bind_int(2, iter->add_prefix);
-    int rv = statement->step();
-    if (rv == SQLITE_CORRUPT)
-      return OnCorruptDatabase();
-    DCHECK(rv == SQLITE_DONE);
-    statement->reset();
-  }
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::ReadAddHashes(
-    std::vector<SBAddFullHash>* add_hashes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "SELECT chunk, prefix, receive_time, full_hash "
-                          "FROM add_full_hash");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int rv;
-  while ((rv = statement->step()) == SQLITE_ROW) {
-    const int32 chunk_id = statement->column_int(0);
-    // NOTE: Legacy format duplicated |hash.prefix| in column 1.
-    const SBPrefix prefix = statement->column_int(1);
-    const int32 received = statement->column_int(2);
-    const SBFullHash full_hash = ReadFullHash(&statement, 3);
-    DCHECK_EQ(prefix, full_hash.prefix);
-    add_hashes->push_back(SBAddFullHash(chunk_id, received, full_hash));
-  }
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  DCHECK_EQ(rv, SQLITE_DONE);
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::WriteAddHashes(
-    const std::vector<SBAddFullHash>& add_hashes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "INSERT INTO add_full_hash "
-                          "(chunk, prefix, receive_time, full_hash) "
-                          "VALUES (?,?, ?, ?)");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  for (std::vector<SBAddFullHash>::const_iterator iter = add_hashes.begin();
-       iter != add_hashes.end(); ++iter) {
-    // NOTE: Legacy format duplicated |hash.prefix| in column 1.
-    statement->bind_int(0, iter->chunk_id);
-    statement->bind_int(1, iter->full_hash.prefix);
-    statement->bind_int(2, iter->received);
-    statement->bind_blob(3, iter->full_hash.full_hash,
-                         sizeof(iter->full_hash.full_hash));
-    int rv = statement->step();
-    if (rv == SQLITE_CORRUPT)
-      return OnCorruptDatabase();
-    DCHECK(rv == SQLITE_DONE);
-    statement->reset();
-  }
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::ReadSubHashes(
-    std::vector<SBSubFullHash>* sub_hashes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "SELECT chunk, add_chunk, prefix, full_hash "
-                          "FROM sub_full_hash");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  int rv;
-  while ((rv = statement->step()) == SQLITE_ROW) {
-    const int32 chunk_id = statement->column_int(0);
-    // NOTE: Legacy format duplicated |hash.prefix| in column 2.
-    const int32 add_chunk_id = statement->column_int(1);
-    const SBPrefix add_prefix = statement->column_int(2);
-    const SBFullHash full_hash = ReadFullHash(&statement, 3);
-    DCHECK_EQ(add_prefix, full_hash.prefix);
-    sub_hashes->push_back(SBSubFullHash(chunk_id, add_chunk_id, full_hash));
-  }
-  if (rv == SQLITE_CORRUPT)
-    return OnCorruptDatabase();
-  DCHECK_EQ(rv, SQLITE_DONE);
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::WriteSubHashes(
-    const std::vector<SBSubFullHash>& sub_hashes) {
-  DCHECK(db_);
-
-  SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
-                          "INSERT INTO sub_full_hash "
-                          "(chunk, add_chunk, prefix, full_hash) "
-                          "VALUES (?,?,?,?)");
-  if (!statement.is_valid()) {
-    NOTREACHED();
-    return false;
-  }
-
-  for (std::vector<SBSubFullHash>::const_iterator iter = sub_hashes.begin();
-       iter != sub_hashes.end(); ++iter) {
-    // NOTE: Legacy format duplicated |hash.prefix| in column 2.
-    statement->bind_int(0, iter->chunk_id);
-    statement->bind_int(1, iter->add_chunk_id);
-    statement->bind_int(2, iter->full_hash.prefix);
-    statement->bind_blob(3, iter->full_hash.full_hash,
-                         sizeof(iter->full_hash.full_hash));
-    int rv = statement->step();
-    if (rv == SQLITE_CORRUPT)
-      return OnCorruptDatabase();
-    DCHECK(rv == SQLITE_DONE);
-    statement->reset();
-  }
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::ResetTables() {
-  DCHECK(db_);
-
-  if (!ExecSql("DELETE FROM add_prefix") ||
-      !ExecSql("DELETE FROM sub_prefix") ||
-      !ExecSql("DELETE FROM add_full_hash") ||
-      !ExecSql("DELETE FROM sub_full_hash") ||
-      !ExecSql("DELETE FROM add_chunks") ||
-      !ExecSql("DELETE FROM sub_chunks"))
-    return false;
-
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::BeginUpdate() {
-  DCHECK(!db_);
-
-  if (!Open())
-    return false;
-
-  insert_transaction_.reset(new SQLTransaction(db_));
-  if (insert_transaction_->Begin() != SQLITE_OK) {
-    DCHECK(false) << "Safe browsing store couldn't start transaction";
-    Close();
-    return false;
-  }
-
-  if (!ReadAddChunks() || !ReadSubChunks())
-    return false;
-
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::DoUpdate(
-    const std::vector<SBAddFullHash>& pending_adds,
-    std::vector<SBAddPrefix>* add_prefixes_result,
-    std::vector<SBAddFullHash>* add_full_hashes_result) {
-  DCHECK(db_);
-
-  std::vector<SBAddPrefix> add_prefixes;
-  std::vector<SBAddFullHash> add_full_hashes;
-  std::vector<SBSubPrefix> sub_prefixes;
-  std::vector<SBSubFullHash> sub_full_hashes;
-
-  if (!ReadAddPrefixes(&add_prefixes) ||
-      !ReadAddHashes(&add_full_hashes) ||
-      !ReadSubPrefixes(&sub_prefixes) ||
-      !ReadSubHashes(&sub_full_hashes))
-    return false;
-
-  // Append items from |pending_adds|.
-  add_full_hashes.insert(add_full_hashes.end(),
-                         pending_adds.begin(), pending_adds.end());
-
-  // Knock the subs from the adds and process deleted chunks.
-  SBProcessSubs(&add_prefixes, &sub_prefixes,
-                &add_full_hashes, &sub_full_hashes,
-                add_del_cache_, sub_del_cache_);
-
-  DeleteChunksFromSet(add_del_cache_, &add_chunks_cache_);
-  DeleteChunksFromSet(sub_del_cache_, &sub_chunks_cache_);
-
-  // Clear the existing tables before rewriting them.
-  if (!ResetTables())
-    return false;
-
-  if (!WriteAddChunks() ||
-      !WriteSubChunks() ||
-      !WriteAddPrefixes(add_prefixes) ||
-      !WriteSubPrefixes(sub_prefixes) ||
-      !WriteAddHashes(add_full_hashes) ||
-      !WriteSubHashes(sub_full_hashes))
-    return false;
-
-  // Commit all the changes to the database.
-  int rv = insert_transaction_->Commit();
-  if (rv != SQLITE_OK) {
-    NOTREACHED() << "SafeBrowsing update transaction failed to commit.";
-    UMA_HISTOGRAM_COUNTS("SB2.FailedUpdate", 1);
-    return false;
-  }
-
-  // Record counts before swapping to caller.
-  UMA_HISTOGRAM_COUNTS("SB2.AddPrefixes", add_prefixes.size());
-  UMA_HISTOGRAM_COUNTS("SB2.SubPrefixes", sub_prefixes.size());
-
-  add_prefixes_result->swap(add_prefixes);
-  add_full_hashes_result->swap(add_full_hashes);
-
-  return true;
-}
-
-bool SafeBrowsingStoreSqlite::FinishUpdate(
-    const std::vector<SBAddFullHash>& pending_adds,
-    const std::set<SBPrefix>& prefix_misses,
-    std::vector<SBAddPrefix>* add_prefixes_result,
-    std::vector<SBAddFullHash>* add_full_hashes_result) {
-  bool ret = DoUpdate(pending_adds,
-                      add_prefixes_result, add_full_hashes_result);
-
-  // Make sure everything is closed even if DoUpdate() fails.
-  if (!Close())
-    return false;
-
-  return ret;
-}
-
-bool SafeBrowsingStoreSqlite::CancelUpdate() {
-  return Close();
-}
-
-void SafeBrowsingStoreSqlite::SetAddChunk(int32 chunk_id) {
-  add_chunks_cache_.insert(chunk_id);
-}
-
-bool SafeBrowsingStoreSqlite::CheckAddChunk(int32 chunk_id) {
-  return add_chunks_cache_.count(chunk_id) > 0;
-}
-
-void SafeBrowsingStoreSqlite::GetAddChunks(std::vector<int32>* out) {
-  out->clear();
-  out->insert(out->end(), add_chunks_cache_.begin(), add_chunks_cache_.end());
-}
-
-void SafeBrowsingStoreSqlite::SetSubChunk(int32 chunk_id) {
-  sub_chunks_cache_.insert(chunk_id);
-}
-
-bool SafeBrowsingStoreSqlite::CheckSubChunk(int32 chunk_id) {
-  return sub_chunks_cache_.count(chunk_id) > 0;
-}
-
-void SafeBrowsingStoreSqlite::GetSubChunks(std::vector<int32>* out) {
-  out->clear();
-  out->insert(out->end(), sub_chunks_cache_.begin(), sub_chunks_cache_.end());
-}
-
-void SafeBrowsingStoreSqlite::DeleteAddChunk(int32 chunk_id) {
-  add_del_cache_.insert(chunk_id);
-}
-
-void SafeBrowsingStoreSqlite::DeleteSubChunk(int32 chunk_id) {
-  sub_del_cache_.insert(chunk_id);
-}
-
-// static
-const FilePath SafeBrowsingStoreSqlite::JournalFileForFilename(
-    const FilePath& filename) {
-  return FilePath(filename.value() + FILE_PATH_LITERAL("-journal"));
-}
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_sqlite.h b/chrome/browser/safe_browsing/safe_browsing_store_sqlite.h
deleted file mode 100644
index f9d4381..0000000
--- a/chrome/browser/safe_browsing/safe_browsing_store_sqlite.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_STORE_SQLITE_H_
-#define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_STORE_SQLITE_H_
-#pragma once
-
-#include <set>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/file_path.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/safe_browsing/safe_browsing_store.h"
-#include "testing/gtest/include/gtest/gtest_prod.h"
-
-struct sqlite3;
-class SqliteStatementCache;
-class SQLTransaction;
-
-class SafeBrowsingStoreSqlite : public SafeBrowsingStore {
- public:
-  SafeBrowsingStoreSqlite();
-  virtual ~SafeBrowsingStoreSqlite();
-
-  virtual bool Delete();
-
-  virtual void Init(const FilePath& filename,
-                    Callback0::Type* corruption_callback);
-
-  virtual bool BeginChunk();
-
-  // Get all Add prefixes out from the store.
-  virtual bool GetAddPrefixes(std::vector<SBAddPrefix>* add_prefixes);
-  virtual bool WriteAddPrefix(int32 chunk_id, SBPrefix prefix);
-  virtual bool WriteAddHash(int32 chunk_id,
-                            base::Time receive_time,
-                            const SBFullHash& full_hash);
-  virtual bool WriteSubPrefix(int32 chunk_id,
-                              int32 add_chunk_id, SBPrefix prefix);
-  virtual bool WriteSubHash(int32 chunk_id, int32 add_chunk_id,
-                            const SBFullHash& full_hash);
-  virtual bool FinishChunk();
-
-  virtual bool BeginUpdate();
-  // TODO(shess): Should not be public.
-  virtual bool DoUpdate(const std::vector<SBAddFullHash>& pending_adds,
-                        std::vector<SBAddPrefix>* add_prefixes_result,
-                        std::vector<SBAddFullHash>* add_full_hashes_result);
-  // NOTE: |prefix_misses| is ignored, as it will be handled in
-  // |SafeBrowsingStoreFile::DoUpdate()|.
-  virtual bool FinishUpdate(const std::vector<SBAddFullHash>& pending_adds,
-                            const std::set<SBPrefix>& prefix_misses,
-                            std::vector<SBAddPrefix>* add_prefixes_result,
-                            std::vector<SBAddFullHash>* add_full_hashes_result);
-  virtual bool CancelUpdate();
-
-  virtual void SetAddChunk(int32 chunk_id);
-  virtual bool CheckAddChunk(int32 chunk_id);
-  virtual void GetAddChunks(std::vector<int32>* out);
-
-  virtual void SetSubChunk(int32 chunk_id);
-  virtual bool CheckSubChunk(int32 chunk_id);
-  virtual void GetSubChunks(std::vector<int32>* out);
-
-  virtual void DeleteAddChunk(int32 chunk_id);
-  virtual void DeleteSubChunk(int32 chunk_id);
-
-  // Returns the name of the SQLite journal file for |filename|.
-  // Exported for unit tests.
-  static const FilePath JournalFileForFilename(const FilePath& filename);
-
- private:
-  // For on-the-fly migration.
-  // TODO(shess): Remove (entire class) after migration.
-  friend class SafeBrowsingStoreFile;
-
-  // The following routines return true on success, or false on
-  // failure.  Failure is presumed to be persistent, so the caller
-  // should stop trying and unwind the transaction.
-  // OnCorruptDatabase() is called if SQLite returns SQLITE_CORRUPT.
-
-  // Open |db_| from |filename_|, creating if necessary.
-  bool Open();
-
-  // Close |db_|, rolling back any in-progress transaction.
-  bool Close();
-
-  // Execute all statements in sql, returning true if every one of
-  // them returns SQLITE_OK.
-  bool ExecSql(const char* sql);
-
-  bool SetupDatabase();
-  bool CheckCompatibleVersion();
-
-  bool CreateTables();
-
-  // Clear the old safe-browsing data from the tables.
-  bool ResetTables();
-
-  // Read and write the chunks-seen data from |*_chunks_cache_|.
-  // Chunk deletions are not accounted for.
-  bool ReadAddChunks();
-  bool ReadSubChunks();
-  bool WriteAddChunks();
-  bool WriteSubChunks();
-
-  // Read the various types of data, skipping items which belong to
-  // deleted chunks.  New data is appended to the vectors.
-  bool ReadAddPrefixes(std::vector<SBAddPrefix>* add_prefixes);
-  bool ReadSubPrefixes(std::vector<SBSubPrefix>* sub_prefixes);
-  bool ReadAddHashes(std::vector<SBAddFullHash>* add_hashes);
-  bool ReadSubHashes(std::vector<SBSubFullHash>* sub_hashes);
-
-  // Write the various types of data.  The existing data is not
-  // cleared.
-  bool WriteAddPrefixes(const std::vector<SBAddPrefix>& add_prefixes);
-  bool WriteSubPrefixes(const std::vector<SBSubPrefix>& sub_prefixes);
-  bool WriteAddHashes(const std::vector<SBAddFullHash>& add_hashes);
-  bool WriteSubHashes(const std::vector<SBSubFullHash>& sub_hashes);
-
-  // Calls |corruption_callback_| if non-NULL, always returns false as
-  // a convenience to the caller.
-  bool OnCorruptDatabase();
-
-  // The database path from Init().
-  FilePath filename_;
-
-  // Between BeginUpdate() and FinishUpdate(), this will be the SQLite
-  // database connection.  Otherwise NULL.
-  sqlite3 *db_;
-
-  // Cache of compiled statements for |db_|.
-  // TODO(shess): Probably doesn't gain us much.
-  scoped_ptr<SqliteStatementCache> statement_cache_;
-
-  // Transaction for protecting database integrity between
-  // BeginUpdate() and FinishUpdate().
-  scoped_ptr<SQLTransaction> insert_transaction_;
-
-  // The set of chunks which the store has seen.  Elements are added
-  // by SetAddChunk() and SetSubChunk(), and deleted on write for
-  // chunks that have been deleted.
-  std::set<int32> add_chunks_cache_;
-  std::set<int32> sub_chunks_cache_;
-
-  // Cache the DeletedAddChunk() and DeleteSubChunk() chunks for later
-  // use in FinishUpdate().
-  base::hash_set<int32> add_del_cache_;
-  base::hash_set<int32> sub_del_cache_;
-
-  // Called when SQLite returns SQLITE_CORRUPT.
-  scoped_ptr<Callback0::Type> corruption_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingStoreSqlite);
-};
-
-#endif  // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_STORE_SQLITE_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_sqlite_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_sqlite_unittest.cc
deleted file mode 100644
index 8364cf2..0000000
--- a/chrome/browser/safe_browsing/safe_browsing_store_sqlite_unittest.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/safe_browsing/safe_browsing_store_sqlite.h"
-
-#include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
-#include "chrome/test/file_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-const FilePath::CharType kFolderPrefix[] =
-    FILE_PATH_LITERAL("SafeBrowsingTestStoreSqlite");
-
-class SafeBrowsingStoreSqliteTest : public PlatformTest {
- public:
-  virtual void SetUp() {
-    PlatformTest::SetUp();
-
-    FilePath temp_dir;
-    ASSERT_TRUE(file_util::CreateNewTempDirectory(kFolderPrefix, &temp_dir));
-
-    file_deleter_.reset(new FileAutoDeleter(temp_dir));
-
-    filename_ = temp_dir;
-    filename_ = filename_.AppendASCII("SafeBrowsingTestStore");
-    file_util::Delete(filename_, false);
-
-    const FilePath journal_file =
-        SafeBrowsingStoreSqlite::JournalFileForFilename(filename_);
-    file_util::Delete(journal_file, false);
-
-    store_.reset(new SafeBrowsingStoreSqlite());
-    store_->Init(filename_, NULL);
-  }
-  virtual void TearDown() {
-    store_->Delete();
-    store_.reset();
-    file_deleter_.reset();
-
-    PlatformTest::TearDown();
-  }
-
-  scoped_ptr<FileAutoDeleter> file_deleter_;
-  FilePath filename_;
-  scoped_ptr<SafeBrowsingStoreSqlite> store_;
-};
-
-TEST_STORE(SafeBrowsingStoreSqliteTest, store_.get(), filename_);
-
-}  // namespace
diff --git a/chrome/browser/safe_browsing/safe_browsing_test.cc b/chrome/browser/safe_browsing/safe_browsing_test.cc
index 7cc8f86..fb48e28 100644
--- a/chrome/browser/safe_browsing/safe_browsing_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -341,7 +341,7 @@
   explicit SafeBrowsingServiceTestHelper(
       SafeBrowsingServiceTest* safe_browsing_test)
       : safe_browsing_test_(safe_browsing_test),
-        response_status_(URLRequestStatus::FAILED) {
+        response_status_(net::URLRequestStatus::FAILED) {
   }
 
   // Callbacks for SafeBrowsingService::Client.
@@ -441,13 +441,13 @@
   }
 
   void WaitTillServerReady(const char* host, int port) {
-    response_status_ = URLRequestStatus::FAILED;
+    response_status_ = net::URLRequestStatus::FAILED;
     GURL url(StringPrintf("http://%s:%d%s?test_step=0",
                           host, port, kDBResetPath));
     // TODO(lzheng): We should have a way to reliably tell when a server is
     // ready so we could get rid of the Sleep and retry loop.
     while (true) {
-      if (FetchUrl(url) == URLRequestStatus::SUCCESS)
+      if (FetchUrl(url) == net::URLRequestStatus::SUCCESS)
         break;
       // Wait and try again if last fetch was failed. The loop will hit the
       // timeout in OutOfProcTestRunner if the fetch can not get success
@@ -457,8 +457,8 @@
   }
 
   // Calls test server to fetch database for verification.
-  URLRequestStatus::Status FetchDBToVerify(const char* host, int port,
-                                           int test_step) {
+  net::URLRequestStatus::Status FetchDBToVerify(const char* host, int port,
+                                                int test_step) {
     // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
     GURL url(StringPrintf("http://%s:%d%s?"
                           "client=chromium&appver=1.0&pver=2.2&test_step=%d&"
@@ -468,8 +468,8 @@
   }
 
   // Calls test server to fetch URLs for verification.
-  URLRequestStatus::Status FetchUrlsToVerify(const char* host, int port,
-                                             int test_step) {
+  net::URLRequestStatus::Status FetchUrlsToVerify(const char* host, int port,
+                                                  int test_step) {
     GURL url(StringPrintf("http://%s:%d%s?"
                           "client=chromium&appver=1.0&pver=2.2&test_step=%d",
                           host, port, kUrlVerifyPath, test_step));
@@ -479,8 +479,8 @@
   // Calls test server to check if test data is done. E.g.: if there is a
   // bad URL that server expects test to fetch full hash but the test didn't,
   // this verification will fail.
-  URLRequestStatus::Status VerifyTestComplete(const char* host, int port,
-                                              int test_step) {
+  net::URLRequestStatus::Status VerifyTestComplete(const char* host, int port,
+                                                   int test_step) {
     GURL url(StringPrintf("http://%s:%d%s?test_step=%d",
                           host, port, kTestCompletePath, test_step));
     return FetchUrl(url);
@@ -489,7 +489,7 @@
   // Callback for URLFetcher.
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data) {
@@ -511,7 +511,7 @@
 
   // Fetch a URL. If message_loop_started is true, starts the message loop
   // so the caller could wait till OnURLFetchComplete is called.
-  URLRequestStatus::Status FetchUrl(const GURL& url) {
+  net::URLRequestStatus::Status FetchUrl(const GURL& url) {
     url_fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this));
     url_fetcher_->set_load_flags(net::LOAD_DISABLE_CACHE);
     url_fetcher_->set_request_context(Profile::GetDefaultRequestContext());
@@ -524,7 +524,7 @@
   SafeBrowsingServiceTest* safe_browsing_test_;
   scoped_ptr<URLFetcher> url_fetcher_;
   std::string response_data_;
-  URLRequestStatus::Status response_status_;
+  net::URLRequestStatus::Status response_status_;
   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceTestHelper);
 };
 
@@ -584,7 +584,7 @@
     }
 
     // Fetches URLs to verify and waits till server responses with data.
-    EXPECT_EQ(URLRequestStatus::SUCCESS,
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS,
               safe_browsing_helper->FetchUrlsToVerify(server_host,
                                                       server_port,
                                                       step));
@@ -615,7 +615,7 @@
     }
     // TODO(lzheng): We should verify the fetched database with local
     // database to make sure they match.
-    EXPECT_EQ(URLRequestStatus::SUCCESS,
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS,
               safe_browsing_helper->FetchDBToVerify(server_host,
                                                     server_port,
                                                     step));
@@ -624,7 +624,7 @@
   }
 
   // Verifies with server if test is done and waits till server responses.
-  EXPECT_EQ(URLRequestStatus::SUCCESS,
+  EXPECT_EQ(net::URLRequestStatus::SUCCESS,
             safe_browsing_helper->VerifyTestComplete(server_host,
                                                      server_port,
                                                      last_step));
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.cc b/chrome/browser/safe_browsing/safe_browsing_util.cc
index f43ee51..3e449e0 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_util.cc
@@ -111,16 +111,6 @@
   return sizeof(Data) + prefix_count * PrefixSize(type);
 }
 
-SBEntry* SBEntry::Enlarge(int extra_prefixes) {
-  int new_prefix_count = prefix_count() + extra_prefixes;
-  SBEntry* rv = SBEntry::Create(type(), new_prefix_count);
-  memcpy(rv, this, Size());  // NOTE: Blows away rv.data_!
-  // We have to re-set |rv|'s prefix count since we just copied our own over it.
-  rv->set_prefix_count(new_prefix_count);
-  Destroy();
-  return rv;
-}
-
 int SBEntry::ChunkIdAtPrefix(int index) const {
   if (type() == SUB_PREFIX)
     return sub_prefixes_[index].add_chunk;
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.h b/chrome/browser/safe_browsing/safe_browsing_util.h
index b0351c1..85a79ef 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util.h
+++ b/chrome/browser/safe_browsing/safe_browsing_util.h
@@ -157,10 +157,6 @@
   int chunk_id() const { return data_.chunk_id; }
   int prefix_count() const { return data_.prefix_count; }
 
-  // Returns a new entry that is larger by the given number of prefixes, with
-  // all the existing data already copied over.  The old entry is destroyed.
-  SBEntry* Enlarge(int extra_prefixes);
-
   // Returns true if this is a prefix as opposed to a full hash.
   bool IsPrefix() const {
     return type() == ADD_PREFIX || type() == SUB_PREFIX;
diff --git a/chrome/browser/search_engines/edit_search_engine_controller.cc b/chrome/browser/search_engines/edit_search_engine_controller.cc
index b2b6a6d..10c02ef 100644
--- a/chrome/browser/search_engines/edit_search_engine_controller.cc
+++ b/chrome/browser/search_engines/edit_search_engine_controller.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -51,8 +51,8 @@
   // If the url has a search term, replace it with a random string and make
   // sure the resulting URL is valid. We don't check the validity of the url
   // with the search term as that is not necessarily valid.
-  return GURL(template_ref.ReplaceSearchTerms(TemplateURL(), L"a",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring())).is_valid();
+  return GURL(template_ref.ReplaceSearchTerms(TemplateURL(), ASCIIToUTF16("a"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())).is_valid();
 }
 
 bool EditSearchEngineController::IsKeywordValid(
@@ -62,7 +62,7 @@
     return false;  // Do not allow empty keyword.
   const TemplateURL* turl_with_keyword =
       profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(
-          UTF16ToWideHack(keyword_input_trimmed));
+          keyword_input_trimmed);
   return (turl_with_keyword == NULL || turl_with_keyword == template_url_);
 }
 
@@ -75,7 +75,7 @@
 
   const TemplateURL* existing =
       profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(
-          UTF16ToWideHack(keyword_input));
+          keyword_input);
   if (existing &&
       (!edit_keyword_delegate_ || existing != template_url_)) {
     // An entry may have been added with the same keyword string while the
@@ -96,8 +96,8 @@
     // does in a similar situation (updating an existing TemplateURL with
     // data from a new one).
     TemplateURL* modifiable_url = const_cast<TemplateURL*>(template_url_);
-    modifiable_url->set_short_name(UTF16ToWideHack(title_input));
-    modifiable_url->set_keyword(UTF16ToWideHack(keyword_input));
+    modifiable_url->set_short_name(title_input);
+    modifiable_url->set_keyword(keyword_input);
     modifiable_url->SetURL(url_string, 0, 0);
     // TemplateURLModel takes ownership of template_url_.
     profile_->GetTemplateURLModel()->Add(modifiable_url);
@@ -124,7 +124,7 @@
 std::string EditSearchEngineController::GetFixedUpURL(
     const std::string& url_input) const {
   std::string url;
-  TrimWhitespace(TemplateURLRef::DisplayURLToURLRef(UTF8ToWide(url_input)),
+  TrimWhitespace(TemplateURLRef::DisplayURLToURLRef(UTF8ToUTF16(url_input)),
                  TRIM_ALL, &url);
   if (url.empty())
     return url;
@@ -135,7 +135,7 @@
   TemplateURL t_url;
   t_url.SetURL(url, 0, 0);
   std::string expanded_url =
-      t_url.url()->ReplaceSearchTerms(t_url, L"x", 0, std::wstring());
+      t_url.url()->ReplaceSearchTerms(t_url, ASCIIToUTF16("x"), 0, string16());
   url_parse::Parsed parts;
   std::string scheme(
       URLFixerUpper::SegmentURL(expanded_url, &parts));
diff --git a/chrome/browser/search_engines/edit_search_engine_controller.h b/chrome/browser/search_engines/edit_search_engine_controller.h
index e2edee6..2d5f534 100644
--- a/chrome/browser/search_engines/edit_search_engine_controller.h
+++ b/chrome/browser/search_engines/edit_search_engine_controller.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/string16.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Profile;
 class TemplateURL;
diff --git a/chrome/browser/search_engines/keyword_editor_controller.cc b/chrome/browser/search_engines/keyword_editor_controller.cc
index b7d2c5e..349d469 100644
--- a/chrome/browser/search_engines/keyword_editor_controller.cc
+++ b/chrome/browser/search_engines/keyword_editor_controller.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -37,8 +37,8 @@
                             profile_);
 
   TemplateURL* template_url = new TemplateURL();
-  template_url->set_short_name(UTF16ToWideHack(title));
-  template_url->set_keyword(UTF16ToWideHack(keyword));
+  template_url->set_short_name(title);
+  template_url->set_keyword(keyword);
   template_url->SetURL(url, 0, 0);
 
   // There's a bug (1090726) in TableView with groups enabled such that newly
@@ -64,8 +64,8 @@
   }
 
   // Don't do anything if the entry didn't change.
-  if (template_url->short_name() == UTF16ToWideHack(title) &&
-      template_url->keyword() == UTF16ToWideHack(keyword) &&
+  if (template_url->short_name() == title &&
+      template_url->keyword() == keyword &&
       ((url.empty() && !template_url->url()) ||
        (!url.empty() && template_url->url() &&
         template_url->url()->url() == url))) {
diff --git a/chrome/browser/search_engines/keyword_editor_controller_unittest.cc b/chrome/browser/search_engines/keyword_editor_controller_unittest.cc
index 4952166..9ea48ac 100644
--- a/chrome/browser/search_engines/keyword_editor_controller_unittest.cc
+++ b/chrome/browser/search_engines/keyword_editor_controller_unittest.cc
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/table_model_observer.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
@@ -16,6 +15,7 @@
 #include "chrome/test/testing_pref_service.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/models/table_model_observer.h"
 
 static const string16 kA(ASCIIToUTF16("a"));
 static const string16 kA1(ASCIIToUTF16("a1"));
@@ -25,7 +25,7 @@
 // Base class for keyword editor tests. Creates a profile containing an
 // empty TemplateURLModel.
 class KeywordEditorControllerTest : public testing::Test,
-                                    public TableModelObserver {
+                                    public ui::TableModelObserver {
  public:
   // Initializes all of the state.
   void Init(bool simulate_load_failure);
@@ -137,8 +137,8 @@
 
   // Verify the entry is what we added.
   const TemplateURL* turl = model_->GetTemplateURLs()[0];
-  EXPECT_EQ(L"a", turl->short_name());
-  EXPECT_EQ(L"b", turl->keyword());
+  EXPECT_EQ(ASCIIToUTF16("a"), turl->short_name());
+  EXPECT_EQ(ASCIIToUTF16("b"), turl->keyword());
   ASSERT_TRUE(turl->url() != NULL);
   EXPECT_EQ("http://c", turl->url()->url());
 }
@@ -154,8 +154,8 @@
 
   // Make sure it was updated appropriately.
   VerifyChangeCount(0, 1, 0, 0);
-  EXPECT_EQ(L"a1", turl->short_name());
-  EXPECT_EQ(L"b1", turl->keyword());
+  EXPECT_EQ(ASCIIToUTF16("a1"), turl->short_name());
+  EXPECT_EQ(ASCIIToUTF16("b1"), turl->keyword());
   ASSERT_TRUE(turl->url() != NULL);
   EXPECT_EQ("http://c1", turl->url()->url());
 }
@@ -186,9 +186,11 @@
   controller_->AddTemplateURL(kA1, kB1, "http://d{searchTerms}");
   ClearChangeCount();
 
-  const TemplateURL* turl1 = model_->GetTemplateURLForKeyword(L"b");
+  const TemplateURL* turl1 =
+      model_->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
   ASSERT_TRUE(turl1 != NULL);
-  const TemplateURL* turl2 = model_->GetTemplateURLForKeyword(L"b1");
+  const TemplateURL* turl2 =
+      model_->GetTemplateURLForKeyword(ASCIIToUTF16("b1"));
   ASSERT_TRUE(turl2 != NULL);
 
   EXPECT_TRUE(controller_->CanMakeDefault(turl1));
@@ -208,9 +210,11 @@
   controller_->AddTemplateURL(kA1, kB1, "http://d{searchTerms}");
   ClearChangeCount();
 
-  const TemplateURL* turl1 = model_->GetTemplateURLForKeyword(L"b");
+  const TemplateURL* turl1 =
+      model_->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
   ASSERT_TRUE(turl1 != NULL);
-  const TemplateURL* turl2 = model_->GetTemplateURLForKeyword(L"b1");
+  const TemplateURL* turl2 =
+      model_->GetTemplateURLForKeyword(ASCIIToUTF16("b1"));
   ASSERT_TRUE(turl2 != NULL);
 
   EXPECT_TRUE(controller_->CanEdit(turl1));
@@ -241,8 +245,8 @@
 // appropriately.
 TEST_F(KeywordEditorControllerTest, MutateTemplateURLModel) {
   TemplateURL* turl = new TemplateURL();
-  turl->set_keyword(L"a");
-  turl->set_short_name(L"b");
+  turl->set_keyword(ASCIIToUTF16("a"));
+  turl->set_short_name(ASCIIToUTF16("b"));
   model_->Add(turl);
 
   // Table model should have updated.
diff --git a/chrome/browser/search_engines/search_provider_install_data.cc b/chrome/browser/search_engines/search_provider_install_data.cc
index 2a32c92..f0ef037 100644
--- a/chrome/browser/search_engines/search_provider_install_data.cc
+++ b/chrome/browser/search_engines/search_provider_install_data.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -36,9 +36,9 @@
   virtual std::string GoogleBaseURLValue() const;
   virtual std::string GetApplicationLocale() const;
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
-  virtual std::wstring GetRlzParameterValue() const {
+  virtual string16 GetRlzParameterValue() const {
     // This value doesn't matter for our purposes.
-    return std::wstring();
+    return string16();
   }
 #endif
 
diff --git a/chrome/browser/search_engines/search_provider_install_data_unittest.cc b/chrome/browser/search_engines/search_provider_install_data_unittest.cc
index 28bcd47..f132032 100644
--- a/chrome/browser/search_engines/search_provider_install_data_unittest.cc
+++ b/chrome/browser/search_engines/search_provider_install_data_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/task.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/search_engines/search_provider_install_data.h"
 #include "chrome/browser/search_engines/template_url.h"
@@ -23,11 +24,11 @@
 
 // Create a TemplateURL. The caller owns the returned TemplateURL*.
 static TemplateURL* CreateTemplateURL(const std::string& url,
-                                      const std::wstring& keyword) {
+                                      const std::string& keyword) {
   TemplateURL* t_url = new TemplateURL();
   t_url->SetURL(url, 0, 0);
-  t_url->set_keyword(keyword);
-  t_url->set_short_name(keyword);
+  t_url->set_keyword(UTF8ToUTF16(keyword));
+  t_url->set_short_name(UTF8ToUTF16(keyword));
   return t_url;
 }
 
@@ -225,7 +226,7 @@
   util_.ChangeModelToLoadState();
   std::string host = "www.unittest.com";
   TemplateURL* t_url = CreateTemplateURL("http://" + host + "/path",
-                                         L"unittest");
+                                         "unittest");
   util_.model()->Add(t_url);
 
   // Wait for the changes to be saved.
@@ -240,7 +241,7 @@
   // Set-up a default and try it all one more time.
   std::string default_host = "www.mmm.com";
   TemplateURL* default_url = CreateTemplateURL("http://" + default_host + "/",
-                                               L"mmm");
+                                               "mmm");
   util_.model()->Add(default_url);
   util_.model()->SetDefaultSearchProvider(default_url);
   test_get_install_state->set_default_search_provider_host(default_host);
@@ -253,7 +254,7 @@
   util_.ChangeModelToLoadState();
   std::string host = "www.unittest.com";
   TemplateURL* t_url = CreateTemplateURL("http://" + host + "/path",
-                                         L"unittest");
+                                         "unittest");
   util_.model()->Add(t_url);
 
   // Set a managed preference that establishes a default search provider.
@@ -287,10 +288,10 @@
   TemplateURLModelTestUtil::BlockTillIOThreadProcessesRequests();
 
   TemplateURL* t_url = CreateTemplateURL("{google:baseURL}?q={searchTerms}",
-                                         L"t");
+                                         "t");
   util_.model()->Add(t_url);
   TemplateURL* default_url = CreateTemplateURL("http://d.com/",
-                                               L"d");
+                                               "d");
   util_.model()->Add(default_url);
   util_.model()->SetDefaultSearchProvider(default_url);
 
diff --git a/chrome/browser/search_engines/search_terms_data.cc b/chrome/browser/search_engines/search_terms_data.cc
index 7e5b9ff..8e9c93c 100644
--- a/chrome/browser/search_engines/search_terms_data.cc
+++ b/chrome/browser/search_engines/search_terms_data.cc
@@ -1,11 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/search_engines/search_terms_data.h"
 
 #include "base/logging.h"
-#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/google/google_url_tracker.h"
@@ -73,18 +72,20 @@
 }
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
-std::wstring UIThreadSearchTermsData::GetRlzParameterValue() const {
+string16 UIThreadSearchTermsData::GetRlzParameterValue() const {
   DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
-  std::wstring rlz_string;
+  string16 rlz_string;
   // For organic brandcodes do not use rlz at all. Empty brandcode usually
   // means a chromium install. This is ok.
-  std::wstring brand;
-  // See http://crbug.com/62337.
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  string16 brand;
   if (GoogleUpdateSettings::GetBrand(&brand) && !brand.empty() &&
-      !GoogleUpdateSettings::IsOrganic(brand))
+      !GoogleUpdateSettings::IsOrganic(brand)) {
+    // This call will return false the first time(s) it is called until the
+    // value has been cached. This normally would mean that at most one omnibox
+    // search might not send the RLZ data but this is not really a problem.
     RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz_string);
+  }
   return rlz_string;
 }
 #endif
diff --git a/chrome/browser/search_engines/search_terms_data.h b/chrome/browser/search_engines/search_terms_data.h
index 41807c3..a695a11 100644
--- a/chrome/browser/search_engines/search_terms_data.h
+++ b/chrome/browser/search_engines/search_terms_data.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/string16.h"
 
 // All data needed by TemplateURLRef::ReplaceSearchTerms which typically may
 // only be accessed on the UI thread.
@@ -28,7 +29,7 @@
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
   // Returns the value for the Chrome Omnibox rlz.
-  virtual std::wstring GetRlzParameterValue() const = 0;
+  virtual string16 GetRlzParameterValue() const = 0;
 #endif
 
  private:
@@ -44,7 +45,7 @@
   virtual std::string GoogleBaseURLValue() const;
   virtual std::string GetApplicationLocale() const;
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
-  virtual std::wstring GetRlzParameterValue() const;
+  virtual string16 GetRlzParameterValue() const;
 #endif
 
   // Used by tests to set the value for the Google base url. This takes
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
index c1ebf51..24c2f6b 100644
--- a/chrome/browser/search_engines/template_url.cc
+++ b/chrome/browser/search_engines/template_url.cc
@@ -1,21 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/search_engines/template_url.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/icu_string_conversions.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/search_engines/search_engine_type.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/favicon_size.h"
+#include "chrome/installer/util/google_update_settings.h"
 #include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/favicon_size.h"
+// TODO(pastarmovj): Remove google_update_settings and user_metrics when the
+// CollectRLZMetrics function is not needed anymore.
 
 // The TemplateURLRef has any number of terms that need to be replaced. Each of
 // the terms is enclosed in braces. If the character preceeding the final
@@ -262,9 +266,9 @@
 
 std::string TemplateURLRef::ReplaceSearchTerms(
     const TemplateURL& host,
-    const std::wstring& terms,
+    const string16& terms,
     int accepted_suggestion,
-    const std::wstring& original_query_for_suggestion) const {
+    const string16& original_query_for_suggestion) const {
   UIThreadSearchTermsData search_terms_data;
   return ReplaceSearchTermsUsingTermsData(host,
                                           terms,
@@ -275,9 +279,9 @@
 
 std::string TemplateURLRef::ReplaceSearchTermsUsingTermsData(
     const TemplateURL& host,
-    const std::wstring& terms,
+    const string16& terms,
     int accepted_suggestion,
-    const std::wstring& original_query_for_suggestion,
+    const string16& original_query_for_suggestion,
     const SearchTermsData& search_terms_data) const {
   ParseIfNecessaryUsingTermsData(search_terms_data);
   if (!valid_)
@@ -292,9 +296,9 @@
   for (Replacements::iterator i = replacements_.begin();
        i != replacements_.end(); ++i) {
     if (i->type == SEARCH_TERMS) {
-      std::wstring::size_type query_start = parsed_url_.find('?');
-      is_in_query = query_start != std::wstring::npos &&
-          (static_cast<std::wstring::size_type>(i->index) > query_start);
+      string16::size_type query_start = parsed_url_.find('?');
+      is_in_query = query_start != string16::npos &&
+          (static_cast<string16::size_type>(i->index) > query_start);
       break;
     }
   }
@@ -307,11 +311,11 @@
     // Encode the search terms so that we know the encoding.
     const std::vector<std::string>& encodings = host.input_encodings();
     for (size_t i = 0; i < encodings.size(); ++i) {
-      if (EscapeQueryParamValue(WideToUTF16Hack(terms),
+      if (EscapeQueryParamValue(terms,
                                 encodings[i].c_str(), true,
                                 &encoded_terms)) {
         if (!original_query_for_suggestion.empty()) {
-          EscapeQueryParamValue(WideToUTF16Hack(original_query_for_suggestion),
+          EscapeQueryParamValue(original_query_for_suggestion,
                                 encodings[i].c_str(),
                                 true,
                                 &encoded_original_query);
@@ -321,17 +325,15 @@
       }
     }
     if (input_encoding.empty()) {
-      encoded_terms = WideToUTF16Hack(
-          EscapeQueryParamValueUTF8(terms, true));
+      encoded_terms = EscapeQueryParamValueUTF8(terms, true);
       if (!original_query_for_suggestion.empty()) {
         encoded_original_query =
-            WideToUTF16Hack(EscapeQueryParamValueUTF8(
-            original_query_for_suggestion, true));
+            EscapeQueryParamValueUTF8(original_query_for_suggestion, true);
       }
       input_encoding = "UTF-8";
     }
   } else {
-    encoded_terms = WideToUTF16Hack(UTF8ToWide(EscapePath(WideToUTF8(terms))));
+    encoded_terms = UTF8ToUTF16(EscapePath(UTF16ToUTF8(terms)));
     input_encoding = "UTF-8";
   }
 
@@ -373,10 +375,10 @@
         // empty string.  (If we don't handle this case, we hit a
         // NOTREACHED below.)
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
-        std::wstring rlz_string = search_terms_data.GetRlzParameterValue();
+        string16 rlz_string = search_terms_data.GetRlzParameterValue();
         if (!rlz_string.empty()) {
           rlz_string = L"rlz=" + rlz_string + L"&";
-          url.insert(i->index, WideToUTF8(rlz_string));
+          url.insert(i->index, UTF16ToUTF8(rlz_string));
         }
 #endif
         break;
@@ -384,9 +386,9 @@
 
       case GOOGLE_UNESCAPED_SEARCH_TERMS: {
         std::string unescaped_terms;
-        base::WideToCodepage(terms, input_encoding.c_str(),
-                             base::OnStringConversionError::SKIP,
-                             &unescaped_terms);
+        base::UTF16ToCodepage(terms, input_encoding.c_str(),
+                              base::OnStringConversionError::SKIP,
+                              &unescaped_terms);
         url.insert(i->index, std::string(unescaped_terms.begin(),
                                          unescaped_terms.end()));
         break;
@@ -431,10 +433,10 @@
   return valid_;
 }
 
-std::wstring TemplateURLRef::DisplayURL() const {
+string16 TemplateURLRef::DisplayURL() const {
   ParseIfNecessary();
   if (!valid_ || replacements_.empty())
-    return UTF8ToWide(url_);
+    return UTF8ToUTF16(url_);
 
   string16 result = UTF8ToUTF16(url_);
   ReplaceSubstringsAfterOffset(&result, 0,
@@ -446,13 +448,13 @@
       ASCIIToUTF16(kGoogleUnescapedSearchTermsParameterFull),
       ASCIIToUTF16(kDisplayUnescapedSearchTerms));
 
-  return UTF16ToWideHack(result);
+  return result;
 }
 
 // static
 std::string TemplateURLRef::DisplayURLToURLRef(
-    const std::wstring& display_url) {
-  string16 result = WideToUTF16Hack(display_url);
+    const string16& display_url) {
+  string16 result = display_url;
   ReplaceSubstringsAfterOffset(&result, 0, ASCIIToUTF16(kDisplaySearchTerms),
                                ASCIIToUTF16(kSearchTermsParameterFull));
   ReplaceSubstringsAfterOffset(
@@ -477,29 +479,29 @@
   return search_term_key_;
 }
 
-std::wstring TemplateURLRef::SearchTermToWide(const TemplateURL& host,
+string16 TemplateURLRef::SearchTermToString16(const TemplateURL& host,
                                               const std::string& term) const {
   const std::vector<std::string>& encodings = host.input_encodings();
-  std::wstring result;
+  string16 result;
 
   std::string unescaped =
       UnescapeURLComponent(term, UnescapeRule::REPLACE_PLUS_WITH_SPACE |
                                  UnescapeRule::URL_SPECIAL_CHARS);
   for (size_t i = 0; i < encodings.size(); ++i) {
-    if (base::CodepageToWide(unescaped, encodings[i].c_str(),
-                             base::OnStringConversionError::FAIL, &result))
+    if (base::CodepageToUTF16(unescaped, encodings[i].c_str(),
+                              base::OnStringConversionError::FAIL, &result))
       return result;
   }
 
   // Always fall back on UTF-8 if it works.
-  if (base::CodepageToWide(unescaped, base::kCodepageUTF8,
-                           base::OnStringConversionError::FAIL, &result))
+  if (base::CodepageToUTF16(unescaped, base::kCodepageUTF8,
+                            base::OnStringConversionError::FAIL, &result))
     return result;
 
   // When nothing worked, just use the escaped text. We have no idea what the
   // encoding is. We need to substitute spaces for pluses ourselves since we're
   // not sending it through an unescaper.
-  result = UTF8ToWide(term);
+  result = UTF8ToUTF16(term);
   std::replace(result.begin(), result.end(), '+', ' ');
   return result;
 }
@@ -520,6 +522,28 @@
   return ref1 == ref2 || (ref1 && ref2 && ref1->url() == ref2->url());
 }
 
+void TemplateURLRef::CollectRLZMetrics() const {
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+  ParseIfNecessary();
+  for (size_t i = 0; i < replacements_.size(); ++i) {
+    // We are interesed in searches that were supposed to send the RLZ token.
+    if (replacements_[i].type == GOOGLE_RLZ) {
+      string16 brand;
+      // We only have RLZ tocken on a branded browser version.
+      if (GoogleUpdateSettings::GetBrand(&brand) && !brand.empty() &&
+           !GoogleUpdateSettings::IsOrganic(brand)) {
+        // Now we know we should have had RLZ token check if there was one.
+        if (url().find("rlz=") != std::string::npos)
+          UserMetrics::RecordAction(UserMetricsAction("SearchWithRLZ"));
+        else
+          UserMetrics::RecordAction(UserMetricsAction("SearchWithoutRLZ"));
+      }
+      return;
+    }
+  }
+#endif
+}
+
 void TemplateURLRef::InvalidateCachedValues() const {
   supports_replacements_ = valid_ = parsed_ = false;
   host_.clear();
@@ -577,8 +601,8 @@
 TemplateURL::~TemplateURL() {
 }
 
-std::wstring TemplateURL::AdjustedShortNameForLocaleDirection() const {
-  std::wstring bidi_safe_short_name = short_name_;
+string16 TemplateURL::AdjustedShortNameForLocaleDirection() const {
+  string16 bidi_safe_short_name = short_name_;
   base::i18n::AdjustStringForLocaleDirection(&bidi_safe_short_name);
   return bidi_safe_short_name;
 }
@@ -601,14 +625,14 @@
   instant_url_.Set(url, index_offset, page_offset);
 }
 
-void TemplateURL::set_keyword(const std::wstring& keyword) {
+void TemplateURL::set_keyword(const string16& keyword) {
   // Case sensitive keyword matching is confusing. As such, we force all
   // keywords to be lower case.
-  keyword_ = UTF16ToWide(l10n_util::ToLower(WideToUTF16(keyword)));
+  keyword_ = l10n_util::ToLower(keyword);
   autogenerate_keyword_ = false;
 }
 
-const std::wstring& TemplateURL::keyword() const {
+string16 TemplateURL::keyword() const {
   EnsureKeyword();
   return keyword_;
 }
@@ -629,7 +653,7 @@
 void TemplateURL::SetFavIconURL(const GURL& url) {
   for (std::vector<ImageRef>::iterator i = image_refs_.begin();
        i != image_refs_.end(); ++i) {
-    if (i->type == L"image/x-icon" &&
+    if (i->type == "image/x-icon" &&
         i->width == kFavIconSize && i->height == kFavIconSize) {
       if (!url.is_valid())
         image_refs_.erase(i);
@@ -641,15 +665,15 @@
   // Don't have one yet, add it.
   if (url.is_valid()) {
     add_image_ref(
-        TemplateURL::ImageRef(L"image/x-icon", kFavIconSize, kFavIconSize,
-                              url));
+        TemplateURL::ImageRef("image/x-icon", kFavIconSize,
+                              kFavIconSize, url));
   }
 }
 
 GURL TemplateURL::GetFavIconURL() const {
   for (std::vector<ImageRef>::const_iterator i = image_refs_.begin();
        i != image_refs_.end(); ++i) {
-    if ((i->type == L"image/x-icon" || i->type == L"image/vnd.microsoft.icon")
+    if ((i->type == "image/x-icon" || i->type == "image/vnd.microsoft.icon")
         && i->width == kFavIconSize && i->height == kFavIconSize) {
       return i->url;
     }
diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h
index ba2a96e..0947d3f 100644
--- a/chrome/browser/search_engines/template_url.h
+++ b/chrome/browser/search_engines/template_url.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -72,18 +72,18 @@
   // The TemplateURL is used to determine the input encoding for the term.
   std::string ReplaceSearchTerms(
       const TemplateURL& host,
-      const std::wstring& terms,
+      const string16& terms,
       int accepted_suggestion,
-      const std::wstring& original_query_for_suggestion) const;
+      const string16& original_query_for_suggestion) const;
 
   // Just like ReplaceSearchTerms except that it takes SearchTermsData to supply
   // the data for some search terms. Most of the time ReplaceSearchTerms should
   // be called.
   std::string ReplaceSearchTermsUsingTermsData(
       const TemplateURL& host,
-      const std::wstring& terms,
+      const string16& terms,
       int accepted_suggestion,
-      const std::wstring& original_query_for_suggestion,
+      const string16& original_query_for_suggestion,
       const SearchTermsData& search_terms_data) const;
 
   // Returns the raw URL. None of the parameters will have been replaced.
@@ -104,11 +104,11 @@
 
   // Returns a string representation of this TemplateURLRef suitable for
   // display. The display format is the same as the format used by Firefox.
-  std::wstring DisplayURL() const;
+  string16 DisplayURL() const;
 
   // Converts a string as returned by DisplayURL back into a string as
   // understood by TemplateURLRef.
-  static std::string DisplayURLToURLRef(const std::wstring& display_url);
+  static std::string DisplayURLToURLRef(const string16& display_url);
 
   // If this TemplateURLRef is valid and contains one search term, this returns
   // the host/path of the URL, otherwise this returns an empty string.
@@ -120,8 +120,8 @@
   const std::string& GetSearchTermKey() const;
 
   // Converts the specified term in the encoding of the host TemplateURL to a
-  // wide string.
-  std::wstring SearchTermToWide(const TemplateURL& host,
+  // string16.
+  string16 SearchTermToString16(const TemplateURL& host,
                                 const std::string& term) const;
 
   // Returns true if this TemplateURLRef has a replacement term of
@@ -132,6 +132,9 @@
   static bool SameUrlRefs(const TemplateURLRef* ref1,
                           const TemplateURLRef* ref2);
 
+  // Collects metrics whether searches through Google are sent with RLZ string.
+  void CollectRLZMetrics() const;
+
  private:
   friend class SearchHostToURLsMapTest;
   friend class TemplateURL;
@@ -259,17 +262,17 @@
   // If a TemplateURL has no images, the favicon for the generated URL
   // should be used.
   struct ImageRef {
-    ImageRef(const std::wstring& type, int width, int height)
+    ImageRef(const std::string& type, int width, int height)
         : type(type), width(width), height(height) {
     }
 
-    ImageRef(const std::wstring& type, int width, int height, const GURL& url)
+    ImageRef(const std::string& type, int width, int height, const GURL& url)
       : type(type), width(width), height(height), url(url) {
     }
 
     // Mime type for the image.
     // ICO image will have the format: image/x-icon or image/vnd.microsoft.icon
-    std::wstring type;
+    std::string type;
 
     // Size of the image
     int width;
@@ -297,20 +300,20 @@
   // A short description of the template. This is the name we show to the user
   // in various places that use keywords. For example, the location bar shows
   // this when the user selects the keyword.
-  void set_short_name(const std::wstring& short_name) {
+  void set_short_name(const string16& short_name) {
     short_name_ = short_name;
   }
-  const std::wstring& short_name() const { return short_name_; }
+  string16 short_name() const { return short_name_; }
 
   // An accessor for the short_name, but adjusted so it can be appropriately
   // displayed even if it is LTR and the UI is RTL.
-  std::wstring AdjustedShortNameForLocaleDirection() const;
+  string16 AdjustedShortNameForLocaleDirection() const;
 
   // A description of the template; this may be empty.
-  void set_description(const std::wstring& description) {
+  void set_description(const string16& description) {
     description_ = description;
   }
-  const std::wstring& description() const { return description_; }
+  string16 description() const { return description_; }
 
   // URL providing JSON results. This is typically used to provide suggestions
   // as your type. If NULL, this url does not support suggestions.
@@ -350,8 +353,8 @@
   const GURL& originating_url() const { return originating_url_; }
 
   // The shortcut for this template url. May be empty.
-  void set_keyword(const std::wstring& keyword);
-  const std::wstring& keyword() const;
+  void set_keyword(const string16& keyword);
+  string16 keyword() const;
 
   // Whether to autogenerate a keyword from the url() in GetKeyword().  Most
   // consumers should not need this.
@@ -410,10 +413,10 @@
   GURL GetFavIconURL() const;
 
   // Set of languages supported. This may be empty.
-  void add_language(const std::wstring& language) {
+  void add_language(const string16& language) {
     languages_.push_back(language);
   }
-  const std::vector<std::wstring>& languages() const { return languages_; }
+  std::vector<string16> languages() const { return languages_; }
 
   // Date this keyword was created.
   //
@@ -487,13 +490,13 @@
   // Unique identifier, used when archived to the database.
   void set_id(TemplateURLID id) { id_ = id;}
 
-  std::wstring short_name_;
-  std::wstring description_;
+  string16 short_name_;
+  string16 description_;
   TemplateURLRef suggestions_url_;
   TemplateURLRef url_;
   TemplateURLRef instant_url_;
   GURL originating_url_;
-  mutable std::wstring keyword_;
+  mutable string16 keyword_;
   bool autogenerate_keyword_;  // If this is set, |keyword_| holds the cached
                                // generated keyword if available.
   mutable bool keyword_generated_;  // True if the keyword was generated. This
@@ -502,7 +505,7 @@
   bool show_in_default_list_;
   bool safe_for_autoreplace_;
   std::vector<ImageRef> image_refs_;
-  std::vector<std::wstring> languages_;
+  std::vector<string16> languages_;
   // List of supported input encodings.
   std::vector<std::string> input_encodings_;
   TemplateURLID id_;
diff --git a/chrome/browser/search_engines/template_url_fetcher.cc b/chrome/browser/search_engines/template_url_fetcher.cc
index b5fe3db..a86c5c1 100644
--- a/chrome/browser/search_engines/template_url_fetcher.cc
+++ b/chrome/browser/search_engines/template_url_fetcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -26,7 +26,7 @@
  public:
   // Takes ownership of |callbacks|.
   RequestDelegate(TemplateURLFetcher* fetcher,
-                  const std::wstring& keyword,
+                  const string16& keyword,
                   const GURL& osdd_url,
                   const GURL& favicon_url,
                   TemplateURLFetcherCallbacks* callbacks,
@@ -42,16 +42,16 @@
   // the TemplateURLModel.
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
 
   // URL of the OSDD.
-  const GURL& url() const { return osdd_url_; }
+  GURL url() const { return osdd_url_; }
 
   // Keyword to use.
-  const std::wstring keyword() const { return keyword_; }
+  string16 keyword() const { return keyword_; }
 
   // The type of search provider being fetched.
   ProviderType provider_type() const { return provider_type_; }
@@ -62,7 +62,7 @@
   URLFetcher url_fetcher_;
   TemplateURLFetcher* fetcher_;
   scoped_ptr<TemplateURL> template_url_;
-  std::wstring keyword_;
+  string16 keyword_;
   const GURL osdd_url_;
   const GURL favicon_url_;
   const ProviderType provider_type_;
@@ -76,7 +76,7 @@
 
 TemplateURLFetcher::RequestDelegate::RequestDelegate(
     TemplateURLFetcher* fetcher,
-    const std::wstring& keyword,
+    const string16& keyword,
     const GURL& osdd_url,
     const GURL& favicon_url,
     TemplateURLFetcherCallbacks* callbacks,
@@ -119,7 +119,7 @@
 void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -160,7 +160,7 @@
     // it gives wrong result when OSDD is located on third party site that
     // has nothing in common with search engine in OSDD.
     GURL keyword_url(template_url_->url()->url());
-    std::wstring new_keyword = TemplateURLModel::GenerateKeyword(
+    string16 new_keyword = TemplateURLModel::GenerateKeyword(
         keyword_url, false);
     if (!new_keyword.empty())
       keyword_ = new_keyword;
@@ -183,13 +183,13 @@
     // provider. The keyword isn't as important in this case.
     if (provider_type_ == EXPLICIT_DEFAULT_PROVIDER) {
       // The loop numbers are arbitrary and are simply a strong effort.
-      std::wstring new_keyword;
+      string16 new_keyword;
       for (int i = 0; i < 100; ++i) {
         // Concatenate a number at end of the keyword and try that.
         new_keyword = keyword_;
         // Try the keyword alone the first time
         if (i > 0)
-          new_keyword.append(UTF16ToWide(base::IntToString16(i)));
+          new_keyword.append(base::IntToString16(i));
         if (!model->GetTemplateURLForKeyword(new_keyword) ||
             model->CanReplaceKeyword(new_keyword,
                                      GURL(template_url_->url()->url()),
@@ -268,7 +268,7 @@
 }
 
 void TemplateURLFetcher::ScheduleDownload(
-    const std::wstring& keyword,
+    const string16& keyword,
     const GURL& osdd_url,
     const GURL& favicon_url,
     TemplateURLFetcherCallbacks* callbacks,
diff --git a/chrome/browser/search_engines/template_url_fetcher.h b/chrome/browser/search_engines/template_url_fetcher.h
index b1e15cc..e159877 100644
--- a/chrome/browser/search_engines/template_url_fetcher.h
+++ b/chrome/browser/search_engines/template_url_fetcher.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,8 @@
 #pragma once
 
 #include "base/scoped_vector.h"
-#include "gfx/native_widget_types.h"
+#include "base/string16.h"
+#include "ui/gfx/native_widget_types.h"
 
 class GURL;
 class Profile;
@@ -33,7 +34,7 @@
   // If TemplateURLFetcher is not already downloading the OSDD for osdd_url,
   // it is downloaded. If successful and the result can be parsed, a TemplateURL
   // is added to the TemplateURLModel. Takes ownership of |callbacks|.
-  void ScheduleDownload(const std::wstring& keyword,
+  void ScheduleDownload(const string16& keyword,
                         const GURL& osdd_url,
                         const GURL& favicon_url,
                         TemplateURLFetcherCallbacks* callbacks,
diff --git a/chrome/browser/search_engines/template_url_fetcher_unittest.cc b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
index 737a349..ec20c66 100644
--- a/chrome/browser/search_engines/template_url_fetcher_unittest.cc
+++ b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 #include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_fetcher.h"
 #include "chrome/browser/search_engines/template_url_fetcher_callbacks.h"
@@ -76,7 +77,7 @@
 
  protected:
   // Schedules the download of the url.
-  void StartDownload(const std::wstring& keyword,
+  void StartDownload(const string16& keyword,
                      const std::string& osdd_file_name,
                      TemplateURLFetcher::ProviderType provider_type,
                      bool check_that_file_exists);
@@ -154,7 +155,7 @@
 }
 
 void TemplateURLFetcherTest::StartDownload(
-    const std::wstring& keyword,
+    const string16& keyword,
     const std::string& osdd_file_name,
     TemplateURLFetcher::ProviderType provider_type,
     bool check_that_file_exists) {
@@ -183,7 +184,7 @@
 }
 
 TEST_F(TemplateURLFetcherTest, BasicAutodetectedTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
 
   test_util_.ChangeModelToLoadState();
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
@@ -203,13 +204,13 @@
   const TemplateURL* t_url = test_util_.model()->GetTemplateURLForKeyword(
       keyword);
   ASSERT_TRUE(t_url);
-  EXPECT_STREQ(L"http://example.com/%s/other_stuff",
-               t_url->url()->DisplayURL().c_str());
+  EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
+            t_url->url()->DisplayURL());
   EXPECT_TRUE(t_url->safe_for_autoreplace());
 }
 
 TEST_F(TemplateURLFetcherTest, DuplicatesThrownAway) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
 
   test_util_.ChangeModelToLoadState();
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
@@ -224,7 +225,7 @@
   struct {
     std::string description;
     std::string osdd_file_name;
-    std::wstring keyword;
+    string16 keyword;
     TemplateURLFetcher::ProviderType provider_type;
   } test_cases[] = {
       { "Duplicate keyword and osdd url with autodetected provider.",
@@ -232,7 +233,8 @@
       { "Duplicate keyword and osdd url with explicit provider.",
         osdd_file_name, keyword, TemplateURLFetcher::EXPLICIT_PROVIDER },
       { "Duplicate osdd url with explicit provider.",
-        osdd_file_name, keyword + L"1", TemplateURLFetcher::EXPLICIT_PROVIDER },
+        osdd_file_name, keyword + ASCIIToUTF16("1"),
+        TemplateURLFetcher::EXPLICIT_PROVIDER },
       { "Duplicate keyword with explicit provider.",
         osdd_file_name + "1", keyword, TemplateURLFetcher::EXPLICIT_PROVIDER }
   };
@@ -255,7 +257,7 @@
 }
 
 TEST_F(TemplateURLFetcherTest, BasicExplicitTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
 
   test_util_.ChangeModelToLoadState();
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
@@ -273,13 +275,13 @@
   ASSERT_EQ(1, callbacks_destroyed_);
 
   ASSERT_TRUE(last_callback_template_url_.get());
-  EXPECT_STREQ(L"http://example.com/%s/other_stuff",
-               last_callback_template_url_->url()->DisplayURL().c_str());
+  EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
+            last_callback_template_url_->url()->DisplayURL());
   EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace());
 }
 
 TEST_F(TemplateURLFetcherTest, BasicExplicitDefaultTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
 
   test_util_.ChangeModelToLoadState();
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
@@ -297,13 +299,13 @@
   ASSERT_EQ(1, callbacks_destroyed_);
 
   ASSERT_TRUE(last_callback_template_url_.get());
-  EXPECT_STREQ(L"http://example.com/%s/other_stuff",
-               last_callback_template_url_->url()->DisplayURL().c_str());
+  EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
+            last_callback_template_url_->url()->DisplayURL());
   EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace());
 }
 
 TEST_F(TemplateURLFetcherTest, AutodetectedBeforeLoadTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
 
   std::string osdd_file_name("simple_open_search.xml");
@@ -315,7 +317,7 @@
 }
 
 TEST_F(TemplateURLFetcherTest, ExplicitBeforeLoadTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
 
   std::string osdd_file_name("simple_open_search.xml");
@@ -327,7 +329,7 @@
 }
 
 TEST_F(TemplateURLFetcherTest, ExplicitDefaultBeforeLoadTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
   ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword));
 
   std::string osdd_file_name("simple_open_search.xml");
@@ -343,13 +345,13 @@
   ASSERT_EQ(1, callbacks_destroyed_);
 
   ASSERT_TRUE(last_callback_template_url_.get());
-  EXPECT_STREQ(L"http://example.com/%s/other_stuff",
-               last_callback_template_url_->url()->DisplayURL().c_str());
+  EXPECT_EQ(ASCIIToUTF16("http://example.com/%s/other_stuff"),
+            last_callback_template_url_->url()->DisplayURL());
   EXPECT_FALSE(last_callback_template_url_->safe_for_autoreplace());
 }
 
 TEST_F(TemplateURLFetcherTest, DuplicateKeywordsTest) {
-  std::wstring keyword(L"test");
+  string16 keyword(ASCIIToUTF16("test"));
 
   TemplateURL* t_url = new TemplateURL();
   t_url->SetURL("http://example.com/", 0, 0);
@@ -384,5 +386,5 @@
   ASSERT_EQ(0, add_provider_called_);
   ASSERT_EQ(3, callbacks_destroyed_);
   ASSERT_TRUE(last_callback_template_url_.get());
-  ASSERT_STRNE(keyword.c_str(), last_callback_template_url_->keyword().c_str());
+  ASSERT_NE(keyword, last_callback_template_url_->keyword());
 }
diff --git a/chrome/browser/search_engines/template_url_model.cc b/chrome/browser/search_engines/template_url_model.cc
index 7372262..9a7a193 100644
--- a/chrome/browser/search_engines/template_url_model.cc
+++ b/chrome/browser/search_engines/template_url_model.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/search_engines/template_url_model.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/stl_util-inl.h"
@@ -33,6 +32,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using base::Time;
 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;
@@ -46,7 +46,7 @@
 // Term used when generating a search url. Use something obscure so that on
 // the rare case the term replaces the URL it's unlikely another keyword would
 // have the same url.
-static const wchar_t kReplacementTerm[] = L"blah.blah.blah.blah.blah";
+static const char kReplacementTerm[] = "blah.blah.blah.blah.blah";
 
 
 // Removes from the vector any template URL that was created because of
@@ -129,8 +129,8 @@
 }
 
 // static
-std::wstring TemplateURLModel::GenerateKeyword(const GURL& url,
-                                               bool autodetected) {
+string16 TemplateURLModel::GenerateKeyword(const GURL& url,
+                                           bool autodetected) {
   // Don't autogenerate keywords for referrers that are the result of a form
   // submission (TODO: right now we approximate this by checking for the URL
   // having a query, but we should replace this with a call to WebCore to see if
@@ -143,44 +143,43 @@
   if (!url.is_valid() ||
       (autodetected && (url.has_query() || !url.SchemeIs(chrome::kHttpScheme) ||
                         ((url.path() != "") && (url.path() != "/")))))
-    return std::wstring();
+    return string16();
 
   // Strip "www." off the front of the keyword; otherwise the keyword won't work
   // properly.  See http://code.google.com/p/chromium/issues/detail?id=6984 .
-  return UTF16ToWideHack(net::StripWWW(UTF8ToUTF16(url.host())));
+  return net::StripWWW(UTF8ToUTF16(url.host()));
 }
 
 // static
-std::wstring TemplateURLModel::CleanUserInputKeyword(
-    const std::wstring& keyword) {
+string16 TemplateURLModel::CleanUserInputKeyword(const string16& keyword) {
   // Remove the scheme.
-  std::wstring result(UTF16ToWide(l10n_util::ToLower(WideToUTF16(keyword))));
+  string16 result(l10n_util::ToLower(keyword));
   url_parse::Component scheme_component;
-  if (url_parse::ExtractScheme(WideToUTF8(keyword).c_str(),
+  if (url_parse::ExtractScheme(UTF16ToUTF8(keyword).c_str(),
                                static_cast<int>(keyword.length()),
                                &scheme_component)) {
     // If the scheme isn't "http" or "https", bail.  The user isn't trying to
     // type a web address, but rather an FTP, file:, or other scheme URL, or a
     // search query with some sort of initial operator (e.g. "site:").
     if (result.compare(0, scheme_component.end(),
-                       ASCIIToWide(chrome::kHttpScheme)) &&
+                       ASCIIToUTF16(chrome::kHttpScheme)) &&
         result.compare(0, scheme_component.end(),
-                       ASCIIToWide(chrome::kHttpsScheme)))
-      return std::wstring();
+                       ASCIIToUTF16(chrome::kHttpsScheme)))
+      return string16();
 
     // Include trailing ':'.
     result.erase(0, scheme_component.end() + 1);
     // Many schemes usually have "//" after them, so strip it too.
-    const std::wstring after_scheme(L"//");
+    const string16 after_scheme(ASCIIToUTF16("//"));
     if (result.compare(0, after_scheme.length(), after_scheme) == 0)
       result.erase(0, after_scheme.length());
   }
 
   // Remove leading "www.".
-  result = UTF16ToWideHack(net::StripWWW(WideToUTF16(result)));
+  result = net::StripWWW(result);
 
   // Remove trailing "/".
-  return (result.length() > 0 && result[result.length() - 1] == L'/') ?
+  return (result.length() > 0 && result[result.length() - 1] == '/') ?
       result.substr(0, result.length() - 1) : result;
 }
 
@@ -206,12 +205,13 @@
     return GURL(search_ref->url());
 
   return GURL(search_ref->ReplaceSearchTermsUsingTermsData(
-      *t_url, kReplacementTerm, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
-      std::wstring(), search_terms_data));
+      *t_url, ASCIIToUTF16(kReplacementTerm),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
+      string16(), search_terms_data));
 }
 
 bool TemplateURLModel::CanReplaceKeyword(
-    const std::wstring& keyword,
+    const string16& keyword,
     const GURL& url,
     const TemplateURL** template_url_to_replace) {
   DCHECK(!keyword.empty());  // This should only be called for non-empty
@@ -237,15 +237,24 @@
 }
 
 void TemplateURLModel::FindMatchingKeywords(
-    const std::wstring& prefix,
+    const string16& prefix,
     bool support_replacement_only,
-    std::vector<std::wstring>* matches) const {
+    std::vector<string16>* matches) const {
   // Sanity check args.
   if (prefix.empty())
     return;
   DCHECK(matches != NULL);
   DCHECK(matches->empty());  // The code for exact matches assumes this.
 
+  // Visual Studio 2010 has problems converting NULL to the null pointer for
+  // std::pair.  See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
+  // It will work if we pass nullptr.
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+  const TemplateURL* null_url = nullptr;
+#else
+  const TemplateURL* null_url = NULL;
+#endif
+
   // Find matching keyword range.  Searches the element map for keywords
   // beginning with |prefix| and stores the endpoints of the resulting set in
   // |match_range|.
@@ -253,7 +262,8 @@
                   KeywordToTemplateMap::const_iterator> match_range(
       std::equal_range(
           keyword_to_template_map_.begin(), keyword_to_template_map_.end(),
-          KeywordToTemplateMap::value_type(prefix, NULL), LessWithPrefix()));
+          KeywordToTemplateMap::value_type(prefix, null_url),
+          LessWithPrefix()));
 
   // Return vector of matching keywords.
   for (KeywordToTemplateMap::const_iterator i(match_range.first);
@@ -265,7 +275,7 @@
 }
 
 const TemplateURL* TemplateURLModel::GetTemplateURLForKeyword(
-                                     const std::wstring& keyword) const {
+                                     const string16& keyword) const {
   KeywordToTemplateMap::const_iterator elem(
       keyword_to_template_map_.find(keyword));
   return (elem == keyword_to_template_map_.end()) ? NULL : elem->second;
@@ -320,10 +330,10 @@
   }
 
   const TemplateURL* existing_url = GetTemplateURLForExtension(extension);
-  std::wstring keyword = UTF8ToWide(extension->omnibox_keyword());
+  string16 keyword = UTF8ToUTF16(extension->omnibox_keyword());
 
   scoped_ptr<TemplateURL> template_url(new TemplateURL);
-  template_url->set_short_name(UTF8ToWide(extension->name()));
+  template_url->set_short_name(UTF8ToUTF16(extension->name()));
   template_url->set_keyword(keyword);
   // This URL is not actually used for navigation. It holds the extension's
   // ID, as well as forcing the TemplateURL to be treated as a search keyword.
@@ -372,8 +382,8 @@
 }
 
 void TemplateURLModel::ResetTemplateURL(const TemplateURL* url,
-                                        const std::wstring& title,
-                                        const std::wstring& keyword,
+                                        const string16& title,
+                                        const string16& keyword,
                                         const std::string& search_url) {
   TemplateURL new_url(*url);
   new_url.set_short_name(title);
@@ -538,8 +548,8 @@
   NotifyLoaded();
 }
 
-std::wstring TemplateURLModel::GetKeywordShortName(const std::wstring& keyword,
-                                                   bool* is_extension_keyword) {
+string16 TemplateURLModel::GetKeywordShortName(const string16& keyword,
+                                               bool* is_extension_keyword) {
   const TemplateURL* template_url = GetTemplateURLForKeyword(keyword);
 
   // TODO(sky): Once LocationBarView adds a listener to the TemplateURLModel
@@ -549,7 +559,7 @@
     return template_url->AdjustedShortNameForLocaleDirection();
   }
   *is_extension_keyword = false;
-  return std::wstring();
+  return string16();
 }
 
 void TemplateURLModel::Observe(NotificationType type,
@@ -602,12 +612,12 @@
 
 void TemplateURLModel::SetKeywordSearchTermsForURL(const TemplateURL* t_url,
                                                    const GURL& url,
-                                                   const std::wstring& term) {
+                                                   const string16& term) {
   HistoryService* history = profile_  ?
       profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL;
   if (!history)
     return;
-  history->SetKeywordSearchTermsForURL(url, t_url->id(), WideToUTF16Hack(term));
+  history->SetKeywordSearchTermsForURL(url, t_url->id(), term);
 }
 
 void TemplateURLModel::Init(const Initializer* initializers,
@@ -640,15 +650,15 @@
 
       size_t template_position =
           std::string(initializers[i].url).find(kTemplateParameter);
-      DCHECK(template_position != std::wstring::npos);
+      DCHECK(template_position != std::string::npos);
       std::string osd_url(initializers[i].url);
       osd_url.replace(template_position, arraysize(kTemplateParameter) - 1,
                       kSearchTermParameter);
 
       // TemplateURLModel ends up owning the TemplateURL, don't try and free it.
       TemplateURL* template_url = new TemplateURL();
-      template_url->set_keyword(initializers[i].keyword);
-      template_url->set_short_name(initializers[i].content);
+      template_url->set_keyword(UTF8ToUTF16(initializers[i].keyword));
+      template_url->set_short_name(UTF8ToUTF16(initializers[i].content));
       template_url->SetURL(osd_url, 0, 0);
       AddNoNotify(template_url);
     }
@@ -777,8 +787,8 @@
     if (!icon_gurl.is_empty())
       icon_url = icon_gurl.spec();
     encodings = JoinString(t_url->input_encodings(), ';');
-    short_name = WideToUTF8(t_url->short_name());
-    keyword = WideToUTF8(t_url->keyword());
+    short_name = UTF16ToUTF8(t_url->short_name());
+    keyword = UTF16ToUTF8(t_url->keyword());
     id_string = base::Int64ToString(t_url->id());
     prepopulate_id = base::Int64ToString(t_url->prepopulate_id());
   }
@@ -822,10 +832,10 @@
     return true;
   }
 
-  std::wstring name =
-      UTF8ToWide(prefs->GetString(prefs::kDefaultSearchProviderName));
-  std::wstring keyword =
-      UTF8ToWide(prefs->GetString(prefs::kDefaultSearchProviderKeyword));
+  string16 name =
+      UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderName));
+  string16 keyword =
+      UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderKeyword));
   std::string icon_url =
       prefs->GetString(prefs::kDefaultSearchProviderIconURL);
   std::string encodings =
@@ -983,7 +993,7 @@
       if (terms_iterator != query_terms.end() &&
           !terms_iterator->second.empty()) {
         SetKeywordSearchTermsForURL(
-            *i, row.url(), search_ref->SearchTermToWide(*(*i),
+            *i, row.url(), search_ref->SearchTermToString16(*(*i),
             terms_iterator->second));
       }
     }
@@ -1006,7 +1016,8 @@
   if (!history)
     return;
 
-  GURL url(URLFixerUpper::FixupURL(WideToUTF8(t_url.keyword()), std::string()));
+  GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(t_url.keyword()),
+                                   std::string()));
   if (!url.is_valid())
     return;
 
diff --git a/chrome/browser/search_engines/template_url_model.h b/chrome/browser/search_engines/template_url_model.h
index a16bad7..b25da9b 100644
--- a/chrome/browser/search_engines/template_url_model.h
+++ b/chrome/browser/search_engines/template_url_model.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -45,7 +45,7 @@
 //
 // There is a TemplateURLModel per Profile.
 //
-// TemplateURLModel does not load the vector of TemplateURLs in it's
+// TemplateURLModel does not load the vector of TemplateURLs in its
 // constructor (except for testing). Use the Load method to trigger a load.
 // When TemplateURLModel has completed loading, observers are notified via
 // OnTemplateURLModelChanged as well as the TEMPLATE_URL_MODEL_LOADED
@@ -59,13 +59,14 @@
                          public NotificationObserver {
  public:
   typedef std::map<std::string, std::string> QueryTerms;
+  typedef std::vector<const TemplateURL*> TemplateURLVector;
 
   // Struct used for initializing the data store with fake data.
   // Each initializer is mapped to a TemplateURL.
   struct Initializer {
-    const wchar_t* const keyword;
+    const char* const keyword;
     const char* const url;
-    const wchar_t* const content;
+    const char* const content;
   };
 
   explicit TemplateURLModel(Profile* profile);
@@ -78,11 +79,11 @@
   // don't generate keywords for a variety of situations where we would probably
   // not want to auto-add keywords, such as keywords for searches on pages that
   // themselves come from form submissions.
-  static std::wstring GenerateKeyword(const GURL& url, bool autodetected);
+  static string16 GenerateKeyword(const GURL& url, bool autodetected);
 
   // Removes any unnecessary characters from a user input keyword.
   // This removes the leading scheme, "www." and any trailing slash.
-  static std::wstring CleanUserInputKeyword(const std::wstring& keyword);
+  static string16 CleanUserInputKeyword(const string16& keyword);
 
   // Returns the search url for t_url.  Returns an empty GURL if t_url has no
   // url().
@@ -102,23 +103,22 @@
   //
   // url gives the url of the search query. The url is used to avoid generating
   // a TemplateURL for an existing TemplateURL that shares the same host.
-  bool CanReplaceKeyword(const std::wstring& keyword,
+  bool CanReplaceKeyword(const string16& keyword,
                          const GURL& url,
                          const TemplateURL** template_url_to_replace);
 
   // Returns (in |matches|) all keywords beginning with |prefix|, sorted
   // shortest-first. If support_replacement_only is true, only keywords that
   // support replacement are returned.
-  void FindMatchingKeywords(const std::wstring& prefix,
+  void FindMatchingKeywords(const string16& prefix,
                             bool support_replacement_only,
-                            std::vector<std::wstring>* matches) const;
+                            std::vector<string16>* matches) const;
 
   // Looks up |keyword| and returns the element it maps to.  Returns NULL if
   // the keyword was not found.
   // The caller should not try to delete the returned pointer; the data store
   // retains ownership of it.
-  const TemplateURL* GetTemplateURLForKeyword(
-    const std::wstring& keyword) const;
+  const TemplateURL* GetTemplateURLForKeyword(const string16& keyword) const;
 
   // Returns the first TemplateURL found with a URL using the specified |host|,
   // or NULL if there are no such TemplateURLs
@@ -158,7 +158,7 @@
 
   // Returns the set of URLs describing the keywords. The elements are owned
   // by TemplateURLModel and should not be deleted.
-  std::vector<const TemplateURL*> GetTemplateURLs() const;
+  TemplateURLVector GetTemplateURLs() const;
 
   // Increment the usage count of a keyword.
   // Called when a URL is loaded that was generated from a keyword.
@@ -167,8 +167,8 @@
   // Resets the title, keyword and search url of the specified TemplateURL.
   // The TemplateURL is marked as not replaceable.
   void ResetTemplateURL(const TemplateURL* url,
-                        const std::wstring& title,
-                        const std::wstring& keyword,
+                        const string16& title,
+                        const string16& keyword,
                         const std::string& search_url);
 
   // Return true if the given |url| can be made the default.
@@ -211,8 +211,8 @@
   // Returns the locale-direction-adjusted short name for the given keyword.
   // Also sets the out param to indicate whether the keyword belongs to an
   // extension.
-  std::wstring GetKeywordShortName(const std::wstring& keyword,
-                                   bool* is_extension_keyword);
+  string16 GetKeywordShortName(const string16& keyword,
+                               bool* is_extension_keyword);
 
   // NotificationObserver method. TemplateURLModel listens for three
   // notification types:
@@ -245,7 +245,7 @@
   // This exists and is virtual for testing.
   virtual void SetKeywordSearchTermsForURL(const TemplateURL* t_url,
                                            const GURL& url,
-                                           const std::wstring& term);
+                                           const string16& term);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(TemplateURLModelTest, BuildQueryTerms);
@@ -258,8 +258,7 @@
   FRIEND_TEST_ALL_PREFIXES(TemplateURLModelTest, MergeDeletesUnusedProviders);
   friend class TemplateURLModelTestUtil;
 
-  typedef std::map<std::wstring, const TemplateURL*> KeywordToTemplateMap;
-  typedef std::vector<const TemplateURL*> TemplateURLVector;
+  typedef std::map<string16, const TemplateURL*> KeywordToTemplateMap;
 
   // Helper functor for FindMatchingKeywords(), for finding the range of
   // keywords which begin with a prefix.
diff --git a/chrome/browser/search_engines/template_url_model_test_util.cc b/chrome/browser/search_engines/template_url_model_test_util.cc
index 7803b12..477999c 100644
--- a/chrome/browser/search_engines/template_url_model_test_util.cc
+++ b/chrome/browser/search_engines/template_url_model_test_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -85,8 +85,8 @@
       : TemplateURLModel(profile) {
   }
 
-  std::wstring GetAndClearSearchTerm() {
-    std::wstring search_term;
+  string16 GetAndClearSearchTerm() {
+    string16 search_term;
     search_term.swap(search_term_);
     return search_term;
   }
@@ -94,12 +94,12 @@
  protected:
   virtual void SetKeywordSearchTermsForURL(const TemplateURL* t_url,
                                            const GURL& url,
-                                           const std::wstring& term) {
+                                           const string16& term) {
     search_term_ = term;
   }
 
  private:
-  std::wstring search_term_;
+  string16 search_term_;
 
   DISALLOW_COPY_AND_ASSIGN(TestingTemplateURLModel);
 };
@@ -210,7 +210,7 @@
     VerifyLoad();
 }
 
-std::wstring TemplateURLModelTestUtil::GetAndClearSearchTerm() {
+string16 TemplateURLModelTestUtil::GetAndClearSearchTerm() {
   return
       static_cast<TestingTemplateURLModel*>(model())->GetAndClearSearchTerm();
 }
diff --git a/chrome/browser/search_engines/template_url_model_test_util.h b/chrome/browser/search_engines/template_url_model_test_util.h
index 058b64b..18cfb58 100644
--- a/chrome/browser/search_engines/template_url_model_test_util.h
+++ b/chrome/browser/search_engines/template_url_model_test_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "base/string16.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/search_engines/template_url_model_observer.h"
 
@@ -70,7 +71,7 @@
 
   // Returns the search term from the last invocation of
   // TemplateURLModel::SetKeywordSearchTermsForURL and clears the search term.
-  std::wstring GetAndClearSearchTerm();
+  string16 GetAndClearSearchTerm();
 
   // Set the google base url.
   void SetGoogleBaseURL(const std::string& base_url) const;
diff --git a/chrome/browser/search_engines/template_url_model_unittest.cc b/chrome/browser/search_engines/template_url_model_unittest.cc
index 9e5477c..ab64c2a 100644
--- a/chrome/browser/search_engines/template_url_model_unittest.cc
+++ b/chrome/browser/search_engines/template_url_model_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #include "base/string_util.h"
 #include "base/ref_counted.h"
 #include "base/threading/thread.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/history/history.h"
 #include "chrome/browser/history/history_notifications.h"
@@ -77,8 +78,8 @@
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
   // Returns the value for the Chrome Omnibox rlz.
-  virtual std::wstring GetRlzParameterValue() const {
-    return std::wstring();
+  virtual string16 GetRlzParameterValue() const {
+    return string16();
   }
 #endif
 
@@ -93,8 +94,8 @@
 static TemplateURL* CreatePreloadedTemplateURL() {
   TemplateURL* t_url = new TemplateURL();
   t_url->SetURL("http://www.unittest.com/", 0, 0);
-  t_url->set_keyword(L"unittest");
-  t_url->set_short_name(L"unittest");
+  t_url->set_keyword(ASCIIToUTF16("unittest"));
+  t_url->set_short_name(ASCIIToUTF16("unittest"));
   t_url->set_safe_for_autoreplace(true);
   GURL favicon_url("http://favicon.url");
   t_url->SetFavIconURL(favicon_url);
@@ -115,22 +116,22 @@
     test_util_.TearDown();
   }
 
-  TemplateURL* AddKeywordWithDate(const std::wstring& keyword,
+  TemplateURL* AddKeywordWithDate(const std::string& keyword,
                                   bool autogenerate_keyword,
                                   const std::string& url,
                                   const std::string& suggest_url,
                                   const std::string& fav_icon_url,
                                   const std::string& encodings,
-                                  const std::wstring& short_name,
+                                  const std::string& short_name,
                                   bool safe_for_autoreplace,
                                   Time created_date) {
     TemplateURL* template_url = new TemplateURL();
     template_url->SetURL(url, 0, 0);
     template_url->SetSuggestionsURL(suggest_url, 0, 0);
     template_url->SetFavIconURL(GURL(fav_icon_url));
-    template_url->set_keyword(keyword);
+    template_url->set_keyword(UTF8ToUTF16(keyword));
     template_url->set_autogenerate_keyword(autogenerate_keyword);
-    template_url->set_short_name(short_name);
+    template_url->set_short_name(UTF8ToUTF16(short_name));
     std::vector<std::string> encodings_vector;
     base::SplitString(encodings, ';', &encodings_vector);
     template_url->set_input_encodings(encodings_vector);
@@ -240,12 +241,12 @@
         prefs::kDefaultSearchProviderPrepopulateID);
   }
 
-  // Creates a TemplateURL with the same prepopluated id as a real prepopulated
+  // Creates a TemplateURL with the same prepopulated id as a real prepopulated
   // item. The input number determines which prepopulated item. The caller is
   // responsible for owning the returned TemplateURL*.
   TemplateURL* CreateReplaceablePreloadedTemplateURL(
       size_t index_offset_from_default,
-      std::wstring* prepopulated_display_url);
+      string16* prepopulated_display_url);
 
   // Verifies the behavior of when a preloaded url later gets changed.
   // Since the input is the offset from the default, when one passes in
@@ -269,7 +270,7 @@
   void VerifyLoad() { test_util_.VerifyLoad(); }
   void ChangeModelToLoadState() { test_util_.ChangeModelToLoadState(); }
   void ResetModel(bool verify_load) { test_util_.ResetModel(verify_load); }
-  std::wstring GetAndClearSearchTerm() {
+  string16 GetAndClearSearchTerm() {
     return test_util_.GetAndClearSearchTerm();
   }
   void SetGoogleBaseURL(const std::string& base_url) const {
@@ -323,7 +324,7 @@
 
 TemplateURL* TemplateURLModelTest::CreateReplaceablePreloadedTemplateURL(
     size_t index_offset_from_default,
-    std::wstring* prepopulated_display_url) {
+    string16* prepopulated_display_url) {
   TemplateURL* t_url = CreatePreloadedTemplateURL();
   ScopedVector<TemplateURL> prepopulated_urls;
   size_t default_search_provider_index = 0;
@@ -344,39 +345,37 @@
 
 void TemplateURLModelTest::TestLoadUpdatingPreloadedURL(
     size_t index_offset_from_default) {
-  std::wstring prepopulated_url;
+  string16 prepopulated_url;
   TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL(
       index_offset_from_default, &prepopulated_url);
   t_url->set_safe_for_autoreplace(false);
 
-  std::wstring original_url = t_url->url()->DisplayURL();
-  ASSERT_STRNE(prepopulated_url.c_str(), original_url.c_str());
+  string16 original_url = t_url->url()->DisplayURL();
+  ASSERT_NE(prepopulated_url, original_url);
 
   // Then add it to the model and save it all.
   ChangeModelToLoadState();
   model()->Add(t_url);
   const TemplateURL* keyword_url =
-      model()->GetTemplateURLForKeyword(L"unittest");
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   ASSERT_EQ(t_url, keyword_url);
-  ASSERT_STREQ(original_url.c_str(), keyword_url->url()->DisplayURL().c_str());
+  ASSERT_EQ(original_url, keyword_url->url()->DisplayURL());
   BlockTillServiceProcessesRequests();
 
   // Now reload the model and verify that the merge updates the url.
   ResetModel(true);
-  keyword_url = model()->GetTemplateURLForKeyword(L"unittest");
+  keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   ASSERT_TRUE(keyword_url != NULL);
-  ASSERT_STREQ(prepopulated_url.c_str(),
-               keyword_url->url()->DisplayURL().c_str());
+  ASSERT_EQ(prepopulated_url, keyword_url->url()->DisplayURL());
 
   // Wait for any saves to finish.
   BlockTillServiceProcessesRequests();
 
   // Reload the model to verify that change was saved correctly.
   ResetModel(true);
-  keyword_url = model()->GetTemplateURLForKeyword(L"unittest");
+  keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   ASSERT_TRUE(keyword_url != NULL);
-  ASSERT_STREQ(prepopulated_url.c_str(),
-               keyword_url->url()->DisplayURL().c_str());
+  ASSERT_EQ(prepopulated_url, keyword_url->url()->DisplayURL());
 }
 
 TEST_F(TemplateURLModelTest, MAYBE_Load) {
@@ -390,14 +389,15 @@
 
   TemplateURL* t_url = new TemplateURL();
   t_url->SetURL("http://www.google.com/foo/bar", 0, 0);
-  t_url->set_keyword(L"keyword");
-  t_url->set_short_name(L"google");
+  t_url->set_keyword(ASCIIToUTF16("keyword"));
+  t_url->set_short_name(ASCIIToUTF16("google"));
   GURL favicon_url("http://favicon.url");
   t_url->SetFavIconURL(favicon_url);
   t_url->set_date_created(Time::FromTimeT(100));
   t_url->set_safe_for_autoreplace(true);
   model()->Add(t_url);
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"keyword", GURL(), NULL));
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
+                                         GURL(), NULL));
   VerifyObserverCount(1);
   BlockTillServiceProcessesRequests();
   // We need to clone as model takes ownership of TemplateURL and will
@@ -410,24 +410,28 @@
   // Reload the model to verify it was actually saved to the database.
   ResetModel(true);
   ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
-  const TemplateURL* loaded_url = model()->GetTemplateURLForKeyword(L"keyword");
+  const TemplateURL* loaded_url =
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
   ASSERT_TRUE(loaded_url != NULL);
   AssertEquals(cloned_url, *loaded_url);
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"keyword", GURL(), NULL));
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
+                                         GURL(), NULL));
 
   // Mutate an element and verify it succeeded.
-  model()->ResetTemplateURL(loaded_url, L"a", L"b", "c");
-  ASSERT_EQ(L"a", loaded_url->short_name());
-  ASSERT_EQ(L"b", loaded_url->keyword());
+  model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"),
+                            ASCIIToUTF16("b"), "c");
+  ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name());
+  ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword());
   ASSERT_EQ("c", loaded_url->url()->url());
   ASSERT_FALSE(loaded_url->safe_for_autoreplace());
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"keyword", GURL(), NULL));
-  ASSERT_FALSE(model()->CanReplaceKeyword(L"b", GURL(), NULL));
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
+                                         GURL(), NULL));
+  ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL));
   cloned_url = *loaded_url;
   BlockTillServiceProcessesRequests();
   ResetModel(true);
   ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
-  loaded_url = model()->GetTemplateURLForKeyword(L"b");
+  loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
   ASSERT_TRUE(loaded_url != NULL);
   AssertEquals(cloned_url, *loaded_url);
 
@@ -436,28 +440,30 @@
   VerifyObserverCount(1);
   ResetModel(true);
   ASSERT_EQ(initial_count, model()->GetTemplateURLs().size());
-  EXPECT_TRUE(model()->GetTemplateURLForKeyword(L"b") == NULL);
+  EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL);
 }
 
 TEST_F(TemplateURLModelTest, GenerateKeyword) {
-  ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL(), true));
+  ASSERT_EQ(string16(), TemplateURLModel::GenerateKeyword(GURL(), true));
   // Shouldn't generate keywords for https.
-  ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("https://blah"), true));
-  ASSERT_EQ(L"foo", TemplateURLModel::GenerateKeyword(GURL("http://foo"),
-                                                      true));
+  ASSERT_EQ(string16(),
+            TemplateURLModel::GenerateKeyword(GURL("https://blah"), true));
+  ASSERT_EQ(ASCIIToUTF16("foo"),
+            TemplateURLModel::GenerateKeyword(GURL("http://foo"), true));
   // www. should be stripped.
-  ASSERT_EQ(L"foo", TemplateURLModel::GenerateKeyword(GURL("http://www.foo"),
-                                                      true));
+  ASSERT_EQ(ASCIIToUTF16("foo"),
+            TemplateURLModel::GenerateKeyword(GURL("http://www.foo"), true));
   // Shouldn't generate keywords with paths, if autodetected.
-  ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"),
-                                                   true));
-  ASSERT_EQ(L"blah", TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"),
-                                                       false));
+  ASSERT_EQ(string16(),
+            TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), true));
+  ASSERT_EQ(ASCIIToUTF16("blah"),
+            TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), false));
   // FTP shouldn't generate a keyword.
-  ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("ftp://blah/"), true));
+  ASSERT_EQ(string16(),
+            TemplateURLModel::GenerateKeyword(GURL("ftp://blah/"), true));
   // Make sure we don't get a trailing /
-  ASSERT_EQ(L"blah", TemplateURLModel::GenerateKeyword(GURL("http://blah/"),
-                                                       true));
+  ASSERT_EQ(ASCIIToUTF16("blah"),
+            TemplateURLModel::GenerateKeyword(GURL("http://blah/"), true));
 }
 
 TEST_F(TemplateURLModelTest, GenerateSearchURL) {
@@ -492,21 +498,21 @@
   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
 
   // Create one with a 0 time.
-  AddKeywordWithDate(L"key1", false, "http://foo1", "http://suggest1",
-                     "http://icon1", "UTF-8;UTF-16", L"name1", true, Time());
+  AddKeywordWithDate("key1", false, "http://foo1", "http://suggest1",
+                     "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
   // Create one for now and +/- 1 day.
-  AddKeywordWithDate(L"key2", false, "http://foo2", "http://suggest2",
-                     "http://icon2", "UTF-8;UTF-16", L"name2", true,
+  AddKeywordWithDate("key2", false, "http://foo2", "http://suggest2",
+                     "http://icon2", "UTF-8;UTF-16", "name2", true,
                      now - one_day);
-  AddKeywordWithDate(L"key3", false, "http://foo3", "", "", "", L"name3",
+  AddKeywordWithDate("key3", false, "http://foo3", "", "", "", "name3",
                      true, now);
-  AddKeywordWithDate(L"key4", false, "http://foo4", "", "", "", L"name4",
+  AddKeywordWithDate("key4", false, "http://foo4", "", "", "", "name4",
                      true, now + one_day);
   // Try the other three states.
-  AddKeywordWithDate(L"key5", false, "http://foo5", "http://suggest5",
-                     "http://icon5", "UTF-8;UTF-16", L"name5", false, now);
-  AddKeywordWithDate(L"key6", false, "http://foo6", "http://suggest6",
-                     "http://icon6", "UTF-8;UTF-16", L"name6", false,
+  AddKeywordWithDate("key5", false, "http://foo5", "http://suggest5",
+                     "http://icon5", "UTF-8;UTF-16", "name5", false, now);
+  AddKeywordWithDate("key6", false, "http://foo6", "http://suggest6",
+                     "http://icon6", "UTF-8;UTF-16", "name6", false,
                      month_ago);
 
   // We just added a few items, validate them.
@@ -523,17 +529,17 @@
   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
 
   // Make sure the right values remain.
-  EXPECT_EQ(L"key1", model()->GetTemplateURLs()[0]->keyword());
+  EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
   EXPECT_EQ(0U,
             model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
 
-  EXPECT_EQ(L"key5", model()->GetTemplateURLs()[1]->keyword());
+  EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
   EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
   EXPECT_EQ(now.ToInternalValue(),
             model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
 
-  EXPECT_EQ(L"key6", model()->GetTemplateURLs()[2]->keyword());
+  EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
   EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
   EXPECT_EQ(month_ago.ToInternalValue(),
             model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
@@ -549,8 +555,8 @@
   const size_t initial_count = model()->GetTemplateURLs().size();
   TemplateURL* t_url = new TemplateURL();
   t_url->SetURL("http://www.google.com/foo/bar", 0, 0);
-  t_url->set_keyword(L"keyword");
-  t_url->set_short_name(L"google");
+  t_url->set_keyword(ASCIIToUTF16("keyword"));
+  t_url->set_short_name(ASCIIToUTF16("google"));
   GURL favicon_url("http://favicon.url");
   t_url->SetFavIconURL(favicon_url);
   t_url->set_date_created(Time::FromTimeT(100));
@@ -560,8 +566,8 @@
   BlockTillServiceProcessesRequests();
 
   // Reset the short name, keyword, url and make sure it takes.
-  const std::wstring new_short_name(L"a");
-  const std::wstring new_keyword(L"b");
+  const string16 new_short_name(ASCIIToUTF16("a"));
+  const string16 new_keyword(ASCIIToUTF16("b"));
   const std::string new_url("c");
   model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
   ASSERT_EQ(new_short_name, t_url->short_name());
@@ -570,7 +576,8 @@
 
   // Make sure the mappings in the model were updated.
   ASSERT_TRUE(model()->GetTemplateURLForKeyword(new_keyword) == t_url);
-  ASSERT_TRUE(model()->GetTemplateURLForKeyword(L"keyword") == NULL);
+  ASSERT_TRUE(
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
 
   TemplateURL last_url = *t_url;
 
@@ -587,8 +594,8 @@
   // Add a new TemplateURL.
   VerifyLoad();
   const size_t initial_count = model()->GetTemplateURLs().size();
-  TemplateURL* t_url = AddKeywordWithDate(L"key1", false, "http://foo1",
-      "http://sugg1", "http://icon1", "UTF-8;UTF-16", L"name1", true, Time());
+  TemplateURL* t_url = AddKeywordWithDate("key1", false, "http://foo1",
+      "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
 
   test_util_.ResetObserverCount();
   model()->SetDefaultSearchProvider(t_url);
@@ -619,8 +626,8 @@
 
   const size_t initial_count = model()->GetTemplateURLs().size();
 
-  AddKeywordWithDate(std::wstring(), false, "http://foo1", "http://sugg1",
-      "http://icon1", "UTF-8;UTF-16", L"name1", true, Time());
+  AddKeywordWithDate("", false, "http://foo1", "http://sugg1",
+      "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
 
   // We just added a few items, validate them.
   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
@@ -642,36 +649,40 @@
 
 TEST_F(TemplateURLModelTest, CantReplaceWithSameKeyword) {
   ChangeModelToLoadState();
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"foo", GURL(), NULL));
-  TemplateURL* t_url = AddKeywordWithDate(L"foo", false, "http://foo1",
-      "http://sugg1", "http://icon1", "UTF-8;UTF-16",  L"name1", true, Time());
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
+  TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo1",
+      "http://sugg1", "http://icon1", "UTF-8;UTF-16",  "name1", true, Time());
 
   // Can still replace, newly added template url is marked safe to replace.
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"foo", GURL("http://foo2"), NULL));
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
+                                         GURL("http://foo2"), NULL));
 
   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
   // no longer be replaceable.
   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
                            t_url->url()->url());
 
-  ASSERT_FALSE(model()->CanReplaceKeyword(L"foo", GURL("http://foo2"), NULL));
+  ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
+                                          GURL("http://foo2"), NULL));
 }
 
 TEST_F(TemplateURLModelTest, CantReplaceWithSameHosts) {
   ChangeModelToLoadState();
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"foo", GURL("http://foo.com"), NULL));
-  TemplateURL* t_url = AddKeywordWithDate(L"foo", false, "http://foo.com",
-      "http://sugg1", "http://icon1", "UTF-8;UTF-16",  L"name1", true, Time());
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
+                                         GURL("http://foo.com"), NULL));
+  TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo.com",
+      "http://sugg1", "http://icon1", "UTF-8;UTF-16",  "name1", true, Time());
 
   // Can still replace, newly added template url is marked safe to replace.
-  ASSERT_TRUE(model()->CanReplaceKeyword(L"bar", GURL("http://foo.com"), NULL));
+  ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
+                                         GURL("http://foo.com"), NULL));
 
   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
   // no longer be replaceable.
   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
                            t_url->url()->url());
 
-  ASSERT_FALSE(model()->CanReplaceKeyword(L"bar",
+  ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
                                           GURL("http://foo.com"), NULL));
 }
 
@@ -692,7 +703,7 @@
   template_url->SetURL("http://url", 0, 0);
   template_url->SetSuggestionsURL("http://url2", 0, 0);
   template_url->SetInstantURL("http://instant", 0, 0);
-  template_url->set_short_name(L"a");
+  template_url->set_short_name(ASCIIToUTF16("a"));
   template_url->set_safe_for_autoreplace(true);
   template_url->set_date_created(Time::FromTimeT(100));
 
@@ -722,7 +733,7 @@
   ASSERT_EQ("http://url2", default_turl->suggestions_url()->url());
   ASSERT_TRUE(default_turl->instant_url());
   EXPECT_EQ("http://instant", default_turl->instant_url()->url());
-  ASSERT_EQ(L"a", default_turl->short_name());
+  ASSERT_EQ(ASCIIToUTF16("a"), default_turl->short_name());
   ASSERT_EQ(id, default_turl->id());
 
   // Now do a load and make sure the default search provider really takes.
@@ -782,20 +793,20 @@
 TEST_F(TemplateURLModelTest, UpdateKeywordSearchTermsForURL) {
   struct TestData {
     const std::string url;
-    const std::wstring term;
+    const string16 term;
   } data[] = {
-    { "http://foo/", L"" },
-    { "http://foo/foo?q=xx", L"" },
-    { "http://x/bar?q=xx", L"" },
-    { "http://x/foo?y=xx", L"" },
-    { "http://x/foo?q=xx", L"xx" },
-    { "http://x/foo?a=b&q=xx", L"xx" },
-    { "http://x/foo?q=b&q=xx", L"" },
+    { "http://foo/", string16() },
+    { "http://foo/foo?q=xx", string16() },
+    { "http://x/bar?q=xx", string16() },
+    { "http://x/foo?y=xx", string16() },
+    { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
+    { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
+    { "http://x/foo?q=b&q=xx", string16() },
   };
 
   ChangeModelToLoadState();
-  AddKeywordWithDate(L"x", false, "http://x/foo?q={searchTerms}",
-      "http://sugg1", "http://icon1", "UTF-8;UTF-16", L"name", false, Time());
+  AddKeywordWithDate("x", false, "http://x/foo?q={searchTerms}",
+      "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name", false, Time());
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
     history::URLVisitedDetails details;
@@ -816,15 +827,15 @@
   };
 
   ChangeModelToLoadState();
-  AddKeywordWithDate(L"x", false, "http://x/foo", "http://sugg1",
-      "http://icon1", "UTF-8;UTF-16", L"name", false, Time());
+  AddKeywordWithDate("x", false, "http://x/foo", "http://sugg1",
+      "http://icon1", "UTF-8;UTF-16", "name", false, Time());
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
     history::URLVisitedDetails details;
     details.row = history::URLRow(GURL(data[i].url));
     details.transition = 0;
     model()->UpdateKeywordSearchTermsForURL(details);
-    ASSERT_EQ(std::wstring(), GetAndClearSearchTerm());
+    ASSERT_EQ(string16(), GetAndClearSearchTerm());
   }
 }
 
@@ -834,12 +845,12 @@
   // test.
   ChangeModelToLoadState();
   SetGoogleBaseURL("http://google.com/");
-  const TemplateURL* t_url = AddKeywordWithDate(std::wstring(), true,
+  const TemplateURL* t_url = AddKeywordWithDate("", true,
       "{google:baseURL}?q={searchTerms}", "http://sugg1", "http://icon1",
-      "UTF-8;UTF-16", L"name", false, Time());
+      "UTF-8;UTF-16", "name", false, Time());
   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
   EXPECT_EQ("google.com", t_url->url()->GetHost());
-  EXPECT_EQ(L"google.com", t_url->keyword());
+  EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
 
   // Change the Google base url.
   test_util_.ResetObserverCount();
@@ -850,9 +861,9 @@
   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("foo.com"));
   EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL);
   EXPECT_EQ("foo.com", t_url->url()->GetHost());
-  EXPECT_EQ(L"foo.com", t_url->keyword());
+  EXPECT_EQ(ASCIIToUTF16("foo.com"), t_url->keyword());
   EXPECT_EQ("http://foo.com/?q=x", t_url->url()->ReplaceSearchTerms(*t_url,
-      L"x", TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+      ASCIIToUTF16("x"), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
 }
 
 struct QueryHistoryCallbackImpl {
@@ -881,16 +892,16 @@
 
   // Create a keyword.
   TemplateURL* t_url = AddKeywordWithDate(
-      L"keyword", false, "http://foo.com/foo?query={searchTerms}",
-      "http://sugg1", "http://icon1", "UTF-8;UTF-16", L"keyword", true,
-      base::Time::Now());
+      "keyword", false, "http://foo.com/foo?query={searchTerms}",
+      "http://sugg1", "http://icon1", "UTF-8;UTF-16", "keyword",
+      true, base::Time::Now());
 
   // Add a visit that matches the url of the keyword.
   HistoryService* history =
       profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
   history->AddPage(
-      GURL(t_url->url()->ReplaceSearchTerms(*t_url, L"blah", 0,
-                                            std::wstring())),
+      GURL(t_url->url()->ReplaceSearchTerms(*t_url, ASCIIToUTF16("blah"), 0,
+                                            string16())),
       NULL, 0, GURL(), PageTransition::KEYWORD, history::RedirectList(),
       history::SOURCE_BROWSED, false);
 
@@ -922,12 +933,14 @@
   TemplateURL* t_url = CreatePreloadedTemplateURL();
   ChangeModelToLoadState();
   model()->Add(t_url);
-  ASSERT_TRUE(model()->GetTemplateURLForKeyword(L"unittest") != NULL);
+  ASSERT_TRUE(
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
   BlockTillServiceProcessesRequests();
 
   // Ensure that merging clears this engine.
   ResetModel(true);
-  ASSERT_TRUE(model()->GetTemplateURLForKeyword(L"unittest") == NULL);
+  ASSERT_TRUE(
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
 
   // Wait for any saves to finish.
   BlockTillServiceProcessesRequests();
@@ -935,7 +948,8 @@
   // Reload the model to verify that the database was updated as a result of the
   // merge.
   ResetModel(true);
-  ASSERT_TRUE(model()->GetTemplateURLForKeyword(L"unittest") == NULL);
+  ASSERT_TRUE(
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
 }
 
 // Make sure that load routine doesn't delete prepopulated engines that no
@@ -949,7 +963,7 @@
 
   // Do the copy after t_url is added so that the id is set.
   TemplateURL copy_t_url = *t_url;
-  ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(L"unittest"));
+  ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
 
   // Wait for any saves to finish.
   BlockTillServiceProcessesRequests();
@@ -957,7 +971,7 @@
   // Ensure that merging won't clear it if the user has edited it.
   ResetModel(true);
   const TemplateURL* url_for_unittest =
-      model()->GetTemplateURLForKeyword(L"unittest");
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   ASSERT_TRUE(url_for_unittest != NULL);
   AssertEquals(copy_t_url, *url_for_unittest);
 
@@ -966,7 +980,8 @@
 
   // Reload the model to verify that save/reload retains the item.
   ResetModel(true);
-  ASSERT_TRUE(model()->GetTemplateURLForKeyword(L"unittest") != NULL);
+  ASSERT_TRUE(
+      model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
 }
 
 // Make sure that load routine doesn't delete
@@ -1003,7 +1018,7 @@
   // internal state is correct.
   TemplateURL copy_t_url = *t_url;
 
-  ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(L"unittest"));
+  ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
   BlockTillServiceProcessesRequests();
 
@@ -1012,7 +1027,7 @@
   ResetModel(true);
   {
     const TemplateURL* keyword_url =
-        model()->GetTemplateURLForKeyword(L"unittest");
+        model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
     ASSERT_TRUE(keyword_url != NULL);
     AssertEquals(copy_t_url, *keyword_url);
     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
@@ -1025,7 +1040,7 @@
   ResetModel(true);
   {
     const TemplateURL* keyword_url =
-        model()->GetTemplateURLForKeyword(L"unittest");
+        model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
     ASSERT_TRUE(keyword_url != NULL);
     AssertEquals(copy_t_url, *keyword_url);
     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
@@ -1048,7 +1063,7 @@
 // This test basically verifies that no asserts or crashes occur
 // during this operation.
 TEST_F(TemplateURLModelTest, LoadDoesAutoKeywordUpdate) {
-  std::wstring prepopulated_url;
+  string16 prepopulated_url;
   TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL(
       0, &prepopulated_url);
   t_url->set_safe_for_autoreplace(false);
@@ -1092,8 +1107,8 @@
   test_util_.ResetObserverCount();
 
   // Set a regular default search provider.
-  TemplateURL* regular_default = AddKeywordWithDate(L"key1", false,
-      "http://foo1", "http://sugg1", "http://icon1", "UTF-8;UTF-16", L"name1",
+  TemplateURL* regular_default = AddKeywordWithDate("key1", false,
+      "http://foo1", "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1",
       true, Time());
   VerifyObserverCount(1);
   model()->SetDefaultSearchProvider(regular_default);
@@ -1118,7 +1133,7 @@
   scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL());
   expected_managed_default1->SetURL(kSearchURL, 0, 0);
   expected_managed_default1->SetFavIconURL(GURL(kIconURL));
-  expected_managed_default1->set_short_name(L"test1");
+  expected_managed_default1->set_short_name(ASCIIToUTF16("test1"));
   std::vector<std::string> encodings_vector;
   base::SplitString(kEncodings, ';', &encodings_vector);
   expected_managed_default1->set_input_encodings(encodings_vector);
@@ -1142,7 +1157,7 @@
   scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL());
   expected_managed_default2->SetURL(kNewSearchURL, 0, 0);
   expected_managed_default2->SetSuggestionsURL(kNewSuggestURL, 0, 0);
-  expected_managed_default2->set_short_name(L"test2");
+  expected_managed_default2->set_short_name(ASCIIToUTF16("test2"));
   expected_managed_default2->set_show_in_default_list(true);
   actual_managed_default = model()->GetDefaultSearchProvider();
   ExpectSimilar(actual_managed_default, expected_managed_default2.get());
diff --git a/chrome/browser/search_engines/template_url_parser.cc b/chrome/browser/search_engines/template_url_parser.cc
index 245ca3f..e671d63 100644
--- a/chrome/browser/search_engines/template_url_parser.cc
+++ b/chrome/browser/search_engines/template_url_parser.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -138,7 +138,7 @@
 
   TemplateURL* template_url() { return url_; }
 
-  void AddImageRef(const std::wstring& type, int width, int height) {
+  void AddImageRef(const std::string& type, int width, int height) {
     if (width > 0 && height > 0)
       current_image_.reset(new TemplateURL::ImageRef(type, width, height));
   }
@@ -147,9 +147,9 @@
     current_image_.reset();
   }
 
-  void SetImageURL(const std::wstring& url) {
+  void SetImageURL(const GURL& url) {
     if (current_image_.get()) {
-      current_image_->url = GURL(WideToUTF8(url));
+      current_image_->url = url;
       url_->add_image_ref(*current_image_);
       current_image_.reset();
     }
@@ -159,11 +159,11 @@
     string_.clear();
   }
 
-  void AppendString(const std::wstring& string) {
+  void AppendString(const string16& string) {
     string_ += string;
   }
 
-  const std::wstring& GetString() {
+  const string16& GetString() {
     return string_;
   }
 
@@ -233,7 +233,7 @@
   scoped_ptr<TemplateURL::ImageRef> current_image_;
 
   // Character content for the current element.
-  std::wstring string_;
+  string16 string_;
 
   TemplateURLParser::ParameterFilter* parameter_filter_;
 
@@ -259,12 +259,8 @@
 std::map<std::string, ParsingContext::ElementType>*
     ParsingContext::kElementNameToElementTypeMap = NULL;
 
-std::wstring XMLCharToWide(const xmlChar* value) {
-  return UTF8ToWide(std::string((const char*)value));
-}
-
-std::wstring XMLCharToWide(const xmlChar* value, int length) {
-  return UTF8ToWide(std::string((const char*)value, length));
+string16 XMLCharToUTF16(const xmlChar* value, int length) {
+  return UTF8ToUTF16(std::string((const char*)value, length));
 }
 
 std::string XMLCharToString(const xmlChar* value) {
@@ -344,12 +340,12 @@
   const xmlChar** attributes = atts;
   int width = 0;
   int height = 0;
-  std::wstring type;
+  std::string type;
   while (*attributes) {
     std::string name(XMLCharToString(*attributes));
     const xmlChar* value = attributes[1];
     if (name == kImageTypeAttribute) {
-      type = XMLCharToWide(value);
+      type = XMLCharToString(value);
     } else if (name == kImageWidthAttribute) {
       base::StringToInt(XMLCharToString(value), &width);
     } else if (name == kImageHeightAttribute) {
@@ -368,7 +364,6 @@
     return;
 
   const xmlChar** attributes = atts;
-  std::wstring type;
   std::string key, value;
   while (*attributes) {
     std::string name(XMLCharToString(*attributes));
@@ -487,14 +482,14 @@
       context->template_url()->set_description(context->GetString());
       break;
     case ParsingContext::IMAGE: {
-      GURL image_url(WideToUTF8(context->GetString()));
+      GURL image_url(UTF16ToUTF8(context->GetString()));
       if (image_url.SchemeIs(chrome::kDataScheme)) {
         // TODO (jcampan): bug 1169256: when dealing with data URL, we need to
         // decode the data URL in the renderer. For now, we'll just point to the
         // fav icon from the URL.
         context->set_derive_image_from_url(true);
       } else {
-        context->SetImageURL(context->GetString());
+        context->SetImageURL(image_url);
       }
       context->EndImage();
       break;
@@ -503,7 +498,7 @@
       context->template_url()->add_language(context->GetString());
       break;
     case ParsingContext::INPUT_ENCODING: {
-      std::string input_encoding = WideToASCII(context->GetString());
+      std::string input_encoding = UTF16ToASCII(context->GetString());
       if (IsValidEncodingString(input_encoding))
         context->template_url()->add_input_encoding(input_encoding);
       break;
@@ -520,7 +515,7 @@
 
 void CharactersImpl(void *ctx, const xmlChar *ch, int len) {
   ParsingContext* context = reinterpret_cast<ParsingContext*>(ctx);
-  context->AppendString(XMLCharToWide(ch, len));
+  context->AppendString(XMLCharToUTF16(ch, len));
 }
 
 // Returns true if the ref is null, or the url wrapped by ref is
diff --git a/chrome/browser/search_engines/template_url_parser_unittest.cc b/chrome/browser/search_engines/template_url_parser_unittest.cc
index 14d6203..c339092 100644
--- a/chrome/browser/search_engines/template_url_parser_unittest.cc
+++ b/chrome/browser/search_engines/template_url_parser_unittest.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/path_service.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_parser.h"
 #include "chrome/common/chrome_paths.h"
@@ -84,7 +85,7 @@
     return;
   ParseFile("dictionary.xml", NULL);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"Dictionary.com", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("Dictionary.com"), template_url_.short_name());
   EXPECT_TRUE(template_url_.GetFavIconURL() ==
               GURL("http://cache.lexico.com/g/d/favicon.ico"));
   EXPECT_TRUE(template_url_.url() != NULL);
@@ -98,7 +99,7 @@
     return;
   ParseFile("msdn.xml", NULL);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"Search \" MSDN", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("Search \" MSDN"), template_url_.short_name());
   EXPECT_TRUE(template_url_.GetFavIconURL() ==
               GURL("http://search.msdn.microsoft.com/search/favicon.ico"));
   EXPECT_TRUE(template_url_.url() != NULL);
@@ -112,7 +113,7 @@
     return;
   ParseFile("wikipedia.xml", NULL);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"Wikipedia (English)", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("Wikipedia (English)"), template_url_.short_name());
   EXPECT_TRUE(template_url_.GetFavIconURL() ==
               GURL("http://en.wikipedia.org/favicon.ico"));
   EXPECT_TRUE(template_url_.url() != NULL);
@@ -163,7 +164,7 @@
   ParamFilterImpl filter("ebay", "ebay");
   ParseFile("firefox_ebay.xml", &filter);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"eBay", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("eBay"), template_url_.short_name());
   EXPECT_TRUE(template_url_.url() != NULL);
   EXPECT_TRUE(template_url_.url()->SupportsReplacement());
   std::string exp_url =
@@ -184,7 +185,7 @@
   ParamFilterImpl filter("", "Mozilla");
   ParseFile("firefox_webster.xml", &filter);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"Webster", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("Webster"), template_url_.short_name());
   EXPECT_TRUE(template_url_.url() != NULL);
   EXPECT_TRUE(template_url_.url()->SupportsReplacement());
   EXPECT_EQ("http://www.webster.com/cgi-bin/dictionary?va={searchTerms}",
@@ -202,7 +203,7 @@
   ParamFilterImpl filter("", "Mozilla");
   ParseFile("firefox_yahoo.xml", &filter);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"Yahoo", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_.short_name());
   EXPECT_TRUE(template_url_.url() != NULL);
   EXPECT_TRUE(template_url_.url()->SupportsReplacement());
   EXPECT_EQ("http://ff.search.yahoo.com/gossip?"
@@ -225,7 +226,7 @@
   ParamFilterImpl filter("", "Mozilla");
   ParseFile("post_suggestion.xml", &filter);
   ASSERT_TRUE(parse_result_);
-  EXPECT_EQ(L"Yahoo", template_url_.short_name());
+  EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_.short_name());
   EXPECT_TRUE(template_url_.url() != NULL);
   EXPECT_TRUE(template_url_.url()->SupportsReplacement());
   EXPECT_TRUE(template_url_.suggestions_url() == NULL);
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index b1fa624..6cb64bd 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -1186,7 +1186,7 @@
   "UTF-8",
   L"{google:baseSuggestURL}search?client=chrome&hl={language}&q={searchTerms}",
   L"{google:baseURL}webhp?{google:RLZ}sourceid=chrome-instant"
-      L"&ie={inputEncoding}&ion=1{searchTerms}",
+      L"&ie={inputEncoding}&ion=1{searchTerms}&nord=1",
   SEARCH_ENGINE_GOOGLE,
   IDR_SEARCH_ENGINE_LOGO_GOOGLE,
   1,
@@ -3351,7 +3351,7 @@
 int GetDataVersion(PrefService* prefs) {
   // Increment this if you change the above data in ways that mean users with
   // existing data should get a new version.
-  const int kCurrentDataVersion = 32;
+  const int kCurrentDataVersion = 33;
   if (!prefs)
     return kCurrentDataVersion;
   // If a version number exist in the preferences file, it overrides the
@@ -3379,11 +3379,11 @@
     new_turl->SetSuggestionsURL(WideToUTF8(suggest_url), 0, 0);
   if (instant_url)
     new_turl->SetInstantURL(WideToUTF8(instant_url), 0, 0);
-  new_turl->set_short_name(name);
+  new_turl->set_short_name(WideToUTF16Hack(name));
   if (keyword == NULL)
     new_turl->set_autogenerate_keyword(true);
   else
-    new_turl->set_keyword(keyword);
+    new_turl->set_keyword(WideToUTF16Hack(keyword));
   new_turl->set_show_in_default_list(true);
   new_turl->set_safe_for_autoreplace(true);
   new_turl->set_date_created(Time());
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
index f79f6b6..1261915 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/file_util.h"
 #include "base/scoped_temp_dir.h"
 #include "base/scoped_vector.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/search_engines/search_engine_type.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url.h"
@@ -119,8 +120,8 @@
       &prefs, &(t_urls.get()), &default_index);
 
   ASSERT_EQ(1u, t_urls.size());
-  EXPECT_EQ(L"foo", t_urls[0]->short_name());
-  EXPECT_EQ(L"fook", t_urls[0]->keyword());
+  EXPECT_EQ(ASCIIToUTF16("foo"), t_urls[0]->short_name());
+  EXPECT_EQ(ASCIIToUTF16("fook"), t_urls[0]->keyword());
   EXPECT_EQ("foo.com", t_urls[0]->url()->GetHost());
   EXPECT_EQ("foi.com", t_urls[0]->GetFavIconURL().host());
   EXPECT_EQ(1u, t_urls[0]->input_encodings().size());
diff --git a/chrome/browser/search_engines/template_url_table_model.cc b/chrome/browser/search_engines/template_url_table_model.cc
index 12189f1..3d342f7 100644
--- a/chrome/browser/search_engines/template_url_table_model.cc
+++ b/chrome/browser/search_engines/template_url_table_model.cc
@@ -1,12 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/search_engines/template_url_table_model.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/table_model_observer.h"
 #include "base/callback.h"
 #include "base/i18n/rtl.h"
 #include "base/stl_util-inl.h"
@@ -15,10 +12,13 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
 
 // Group IDs used by TemplateURLTableModel.
 static const int kMainGroupID = 0;
@@ -180,7 +180,7 @@
 
   switch (col_id) {
     case IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN: {
-      string16 url_short_name = WideToUTF16Hack(url.short_name());
+      string16 url_short_name = url.short_name();
       // TODO(xji): Consider adding a special case if the short name is a URL,
       // since those should always be displayed LTR. Please refer to
       // http://crbug.com/6726 for more information.
@@ -195,7 +195,7 @@
 
     case IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN: {
       // Keyword should be domain name. Force it to have LTR directionality.
-      string16 keyword = WideToUTF16(url.keyword());
+      string16 keyword = url.keyword();
       keyword = base::i18n::GetDisplayStringInLTRDirectionality(keyword);
       return keyword;
     }
@@ -211,7 +211,7 @@
   return entries_[row]->GetIcon();
 }
 
-void TemplateURLTableModel::SetObserver(TableModelObserver* observer) {
+void TemplateURLTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
@@ -279,8 +279,7 @@
   DCHECK(index >= 0 && index <= RowCount());
   const TemplateURL* template_url = &GetTemplateURL(index);
   template_url_model_->RemoveObserver(this);
-  template_url_model_->ResetTemplateURL(template_url, UTF16ToWideHack(title),
-                                        UTF16ToWideHack(keyword), url);
+  template_url_model_->ResetTemplateURL(template_url, title, keyword, url);
   if (template_url_model_->GetDefaultSearchProvider() == template_url &&
       !TemplateURL::SupportsReplacement(template_url)) {
     // The entry was the default search provider, but the url has been modified
diff --git a/chrome/browser/search_engines/template_url_table_model.h b/chrome/browser/search_engines/template_url_table_model.h
index 95ca739..7a0d42b 100644
--- a/chrome/browser/search_engines/template_url_table_model.h
+++ b/chrome/browser/search_engines/template_url_table_model.h
@@ -9,10 +9,10 @@
 #include <string>
 #include <vector>
 
-#include "app/table_model.h"
 #include "base/compiler_specific.h"
 #include "base/string16.h"
 #include "chrome/browser/search_engines/template_url_model_observer.h"
+#include "ui/base/models/table_model.h"
 
 class ModelEntry;
 class SkBitmap;
@@ -30,7 +30,7 @@
 // the favicon. The entries in the model are sorted such that non-generated
 // appear first (grouped together) and are followed by generated keywords.
 
-class TemplateURLTableModel : public TableModel,
+class TemplateURLTableModel : public ui::TableModel,
                                      TemplateURLModelObserver {
  public:
   explicit TemplateURLTableModel(TemplateURLModel* template_url_model);
@@ -41,11 +41,11 @@
   // if the TemplateURLModel wasn't initially loaded and has been loaded.
   void Reload();
 
-  // TableModel overrides.
+  // ui::TableModel overrides.
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column) OVERRIDE;
   virtual SkBitmap GetIcon(int row) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
   virtual bool HasGroups() OVERRIDE;
   virtual Groups GetGroups() OVERRIDE;
   virtual int GetGroupID(int row) OVERRIDE;
@@ -98,7 +98,7 @@
   // TemplateURLModelObserver notification.
   virtual void OnTemplateURLModelChanged();
 
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   // The entries.
   std::vector<ModelEntry*> entries_;
diff --git a/chrome/browser/search_engines/template_url_unittest.cc b/chrome/browser/search_engines/template_url_unittest.cc
index 3faa2aa..819164c 100644
--- a/chrome/browser/search_engines/template_url_unittest.cc
+++ b/chrome/browser/search_engines/template_url_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,8 +28,8 @@
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
   // Returns the value for the Chrome Omnibox rlz.
-  virtual std::wstring GetRlzParameterValue() const {
-    return L"";
+  virtual string16 GetRlzParameterValue() const {
+    return string16();
   }
 #endif
 
@@ -68,15 +68,16 @@
 TEST_F(TemplateURLTest, URLRefTestSearchTerms) {
   struct SearchTermsCase {
     const char* url;
-    const wchar_t* terms;
+    const string16 terms;
     const char* output;
   } search_term_cases[] = {
-    { "http://foo{searchTerms}", L"sea rch/bar", "http://foosea%20rch/bar" },
-    { "http://foo{searchTerms}?boo=abc", L"sea rch/bar",
+    { "http://foo{searchTerms}", ASCIIToUTF16("sea rch/bar"),
+      "http://foosea%20rch/bar" },
+    { "http://foo{searchTerms}?boo=abc", ASCIIToUTF16("sea rch/bar"),
       "http://foosea%20rch/bar?boo=abc" },
-    { "http://foo/?boo={searchTerms}", L"sea rch/bar",
+    { "http://foo/?boo={searchTerms}", ASCIIToUTF16("sea rch/bar"),
       "http://foo/?boo=sea+rch%2Fbar" },
-    { "http://en.wikipedia.org/{searchTerms}", L"wiki/?",
+    { "http://en.wikipedia.org/{searchTerms}", ASCIIToUTF16("wiki/?"),
       "http://en.wikipedia.org/wiki/%3F" }
   };
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) {
@@ -87,7 +88,7 @@
 
     ASSERT_TRUE(ref.SupportsReplacement());
     GURL result = GURL(ref.ReplaceSearchTerms(t_url, value.terms,
-        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
     ASSERT_TRUE(result.is_valid());
     ASSERT_EQ(value.output, result.spec());
   }
@@ -98,8 +99,8 @@
   TemplateURLRef ref("http://foo{searchTerms}{count?}", 0, 0);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://foox/", result.spec());
 }
@@ -109,8 +110,8 @@
   TemplateURLRef ref("http://foo{searchTerms}{count}", 0, 0);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://foox10/", result.spec());
 }
@@ -121,8 +122,8 @@
                      1, 2);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://fooxxy/", result.spec());
 }
@@ -132,8 +133,8 @@
   TemplateURLRef ref("http://foo{searchTerms}x{startIndex}y{startPage}", 1, 2);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://fooxx1y2/", result.spec());
 }
@@ -144,8 +145,8 @@
       "http://foo{searchTerms}x{inputEncoding?}y{outputEncoding?}a", 1, 2);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://fooxxutf-8ya/", result.spec());
 }
@@ -156,8 +157,8 @@
       "http://foox{inputEncoding?}a{searchTerms}y{outputEncoding?}b", 1, 2);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://fooxutf-8axyb/", result.spec());
 }
@@ -168,8 +169,8 @@
       "http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a", 1, 2);
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
-  GURL result = GURL(ref.ReplaceSearchTerms(t_url, L"X",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+  GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   ASSERT_EQ("http://fooxxutf-8yutf-8a/", result.spec());
 }
@@ -177,12 +178,12 @@
 TEST_F(TemplateURLTest, URLRefTestSearchTermsUsingTermsData) {
   struct SearchTermsCase {
     const char* url;
-    const wchar_t* terms;
+    const string16 terms;
     const char* output;
   } search_term_cases[] = {
-    { "{google:baseURL}{language}{searchTerms}", L"",
+    { "{google:baseURL}{language}{searchTerms}", string16(),
       "http://example.com/e/yy" },
-    { "{google:baseSuggestURL}{searchTerms}", L"",
+    { "{google:baseSuggestURL}{searchTerms}", string16(),
       "http://clients1.example.com/complete/" }
   };
 
@@ -196,7 +197,7 @@
     ASSERT_TRUE(ref.SupportsReplacement());
     GURL result = GURL(ref.ReplaceSearchTermsUsingTermsData(
         t_url, value.terms,
-        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring(),
+        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16(),
         search_terms_data));
     ASSERT_TRUE(result.is_valid());
     ASSERT_EQ(value.output, result.spec());
@@ -206,21 +207,21 @@
 TEST_F(TemplateURLTest, URLRefTermToWide) {
   struct ToWideCase {
     const char* encoded_search_term;
-    const wchar_t* expected_decoded_term;
+    const string16 expected_decoded_term;
   } to_wide_cases[] = {
-    {"hello+world", L"hello world"},
+    {"hello+world", ASCIIToUTF16("hello world")},
     // Test some big-5 input.
-    {"%a7A%A6%6e+to+you", L"\x4f60\x597d to you"},
+    {"%a7A%A6%6e+to+you", WideToUTF16(L"\x4f60\x597d to you")},
     // Test some UTF-8 input. We should fall back to this when the encoding
     // doesn't look like big-5. We have a '5' in the middle, which is an invalid
     // Big-5 trailing byte.
-    {"%e4%bd%a05%e5%a5%bd+to+you", L"\x4f60\x35\x597d to you"},
+    {"%e4%bd%a05%e5%a5%bd+to+you", WideToUTF16(L"\x4f60\x35\x597d to you")},
     // Undecodable input should stay escaped.
-    {"%91%01+abcd", L"%91%01 abcd"},
+    {"%91%01+abcd", WideToUTF16(L"%91%01 abcd")},
     // Make sure we convert %2B to +.
-    {"C%2B%2B", L"C++"},
+    {"C%2B%2B", ASCIIToUTF16("C++")},
     // C%2B is escaped as C%252B, make sure we unescape it properly.
-    {"C%252B", L"C%2B"},
+    {"C%252B", ASCIIToUTF16("C%2B")},
   };
 
   TemplateURL t_url;
@@ -235,10 +236,10 @@
   ASSERT_TRUE(ref.SupportsReplacement());
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(to_wide_cases); i++) {
-    std::wstring result = ref.SearchTermToWide(t_url,
+    string16 result = ref.SearchTermToString16(t_url,
         to_wide_cases[i].encoded_search_term);
 
-    EXPECT_EQ(std::wstring(to_wide_cases[i].expected_decoded_term), result);
+    EXPECT_EQ(to_wide_cases[i].expected_decoded_term, result);
   }
 }
 
@@ -258,16 +259,16 @@
 TEST_F(TemplateURLTest, DisplayURLToURLRef) {
   struct TestData {
     const std::string url;
-    const std::wstring expected_result;
+    const string16 expected_result;
   } data[] = {
     { "http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a",
-      L"http://foo%sx{inputEncoding}y{outputEncoding}a" },
+      ASCIIToUTF16("http://foo%sx{inputEncoding}y{outputEncoding}a") },
     { "http://X",
-      L"http://X" },
+      ASCIIToUTF16("http://X") },
     { "http://foo{searchTerms",
-      L"http://foo{searchTerms" },
+      ASCIIToUTF16("http://foo{searchTerms") },
     { "http://foo{searchTerms}{language}",
-      L"http://foo%s{language}" },
+      ASCIIToUTF16("http://foo%s{language}") },
   };
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
     TemplateURLRef ref(data[i].url, 1, 2);
@@ -316,8 +317,8 @@
     std::string expected_result = data[i].expected_result;
     ReplaceSubstringsAfterOffset(&expected_result, 0, "{language}",
         g_browser_process->GetApplicationLocale());
-    GURL result = GURL(ref.ReplaceSearchTerms(turl, L"X",
-        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+    GURL result = GURL(ref.ReplaceSearchTerms(turl, ASCIIToUTF16("X"),
+        TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
     EXPECT_TRUE(result.is_valid());
     EXPECT_EQ(expected_result, result.spec());
   }
@@ -329,13 +330,15 @@
 TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
   struct TestData {
     const std::string encoding;
-    const std::wstring search_term;
+    const string16 search_term;
     const std::string url;
     const std::string expected_result;
   } data[] = {
-    { "BIG5",  L"\x60BD", "http://foo/?{searchTerms}{inputEncoding}",
+    { "BIG5",  WideToUTF16(L"\x60BD"),
+      "http://foo/?{searchTerms}{inputEncoding}",
       "http://foo/?%B1~BIG5" },
-    { "UTF-8", L"blah",   "http://foo/?{searchTerms}{inputEncoding}",
+    { "UTF-8", ASCIIToUTF16("blah"),
+      "http://foo/?{searchTerms}{inputEncoding}",
       "http://foo/?blahUTF-8" },
   };
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
@@ -344,7 +347,7 @@
     TemplateURLRef ref(data[i].url, 1, 2);
     GURL result = GURL(ref.ReplaceSearchTerms(turl,
         data[i].search_term, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
-        std::wstring()));
+        string16()));
     EXPECT_TRUE(result.is_valid());
     EXPECT_EQ(data[i].expected_result, result.spec());
   }
@@ -353,19 +356,19 @@
 TEST_F(TemplateURLTest, Suggestions) {
   struct TestData {
     const int accepted_suggestion;
-    const std::wstring original_query_for_suggestion;
+    const string16 original_query_for_suggestion;
     const std::string expected_result;
   } data[] = {
-    { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring(),
+    { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16(),
       "http://bar/foo?q=foobar" },
-    { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, L"foo",
+    { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, ASCIIToUTF16("foo"),
       "http://bar/foo?q=foobar" },
-    { TemplateURLRef::NO_SUGGESTION_CHOSEN, std::wstring(),
+    { TemplateURLRef::NO_SUGGESTION_CHOSEN, string16(),
       "http://bar/foo?aq=f&q=foobar" },
-    { TemplateURLRef::NO_SUGGESTION_CHOSEN, L"foo",
+    { TemplateURLRef::NO_SUGGESTION_CHOSEN, ASCIIToUTF16("foo"),
       "http://bar/foo?aq=f&q=foobar" },
-    { 0, std::wstring(), "http://bar/foo?aq=0&oq=&q=foobar" },
-    { 1, L"foo", "http://bar/foo?aq=1&oq=foo&q=foobar" },
+    { 0, string16(), "http://bar/foo?aq=0&oq=&q=foobar" },
+    { 1, ASCIIToUTF16("foo"), "http://bar/foo?aq=1&oq=foo&q=foobar" },
   };
   TemplateURL turl;
   turl.add_input_encoding("UTF-8");
@@ -374,7 +377,7 @@
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
-    GURL result = GURL(ref.ReplaceSearchTerms(turl, L"foobar",
+    GURL result = GURL(ref.ReplaceSearchTerms(turl, ASCIIToUTF16("foobar"),
         data[i].accepted_suggestion, data[i].original_query_for_suggestion));
     EXPECT_TRUE(result.is_valid());
     EXPECT_EQ(data[i].expected_result, result.spec());
@@ -383,7 +386,7 @@
 
 #if defined(OS_WIN)
 TEST_F(TemplateURLTest, RLZ) {
-  std::wstring rlz_string;
+  string16 rlz_string;
 #if defined(GOOGLE_CHROME_BUILD)
   RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz_string);
 #endif
@@ -393,7 +396,7 @@
   ASSERT_TRUE(ref.IsValid());
   ASSERT_TRUE(ref.SupportsReplacement());
   GURL result(ref.ReplaceSearchTerms(t_url, L"x",
-      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+      TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
   ASSERT_TRUE(result.is_valid());
   std::string expected_url = "http://bar/?";
   if (!rlz_string.empty()) {
@@ -461,14 +464,14 @@
   TemplateURL t_url;
   t_url.SetURL("http://www.google.com/search", 0, 0);
   EXPECT_FALSE(t_url.autogenerate_keyword());
-  t_url.set_keyword(L"foo");
-  EXPECT_EQ(L"foo", t_url.keyword());
+  t_url.set_keyword(ASCIIToUTF16("foo"));
+  EXPECT_EQ(ASCIIToUTF16("foo"), t_url.keyword());
   t_url.set_autogenerate_keyword(true);
   EXPECT_TRUE(t_url.autogenerate_keyword());
-  EXPECT_EQ(L"google.com", t_url.keyword());
-  t_url.set_keyword(L"foo");
+  EXPECT_EQ(ASCIIToUTF16("google.com"), t_url.keyword());
+  t_url.set_keyword(ASCIIToUTF16("foo"));
   EXPECT_FALSE(t_url.autogenerate_keyword());
-  EXPECT_EQ(L"foo", t_url.keyword());
+  EXPECT_EQ(ASCIIToUTF16("foo"), t_url.keyword());
 }
 
 TEST_F(TemplateURLTest, ParseParameterKnown) {
diff --git a/chrome/browser/search_engines/util.cc b/chrome/browser/search_engines/util.cc
index 94b46d6..203042d 100644
--- a/chrome/browser/search_engines/util.cc
+++ b/chrome/browser/search_engines/util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
@@ -29,7 +28,7 @@
     // http://code.google.com/p/chromium/issues/detail?id=2573
     return string16();
   }
-  return WideToUTF16(default_provider->short_name());
+  return default_provider->short_name();
 }
 
 // Removes (and deletes) TemplateURLs from |urls| that have duplicate
diff --git a/chrome/browser/service/service_process_control.cc b/chrome/browser/service/service_process_control.cc
index 0ca4729..09bc1ad 100644
--- a/chrome/browser/service/service_process_control.cc
+++ b/chrome/browser/service/service_process_control.cc
@@ -19,6 +19,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/service_messages.h"
 #include "chrome/common/service_process_util.h"
+#include "ui/base/ui_base_switches.h"
 
 // ServiceProcessControl::Launcher implementation.
 // This class is responsible for launching the service process on the
@@ -121,20 +122,9 @@
   // TODO(hclam): Handle error connecting to channel.
   const std::string channel_id = GetServiceProcessChannelName();
   channel_.reset(
-      new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this,
+      new IPC::SyncChannel(channel_id, IPC::Channel::MODE_NAMED_CLIENT, this,
                            io_thread->message_loop(), true,
                            g_browser_process->shutdown_event()));
-  channel_->set_sync_messages_with_no_timeout_allowed(false);
-
-  // We just established a channel with the service process. Notify it if an
-  // upgrade is available.
-  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
-    Send(new ServiceMsg_UpdateAvailable);
-  } else {
-    if (registrar_.IsEmpty())
-      registrar_.Add(this, NotificationType::UPGRADE_RECOMMENDED,
-                     NotificationService::AllSources());
-  }
 }
 
 void ServiceProcessControl::RunConnectDoneTasks() {
@@ -178,14 +168,14 @@
   if (failure_task)
     connect_failure_tasks_.push_back(failure_task);
 
-  // If the service process is already running then connects to it.
-  if (CheckServiceProcessReady()) {
-    ConnectInternal();
+  // If we already in the process of launching, then we are done.
+  if (launcher_) {
     return;
   }
 
-  // If we already in the process of launching, then we are done.
-  if (launcher_) {
+  // If the service process is already running then connects to it.
+  if (CheckServiceProcessReady()) {
+    ConnectInternal();
     return;
   }
 
@@ -215,6 +205,9 @@
     cmd_line->AppendSwitch(switches::kWaitForDebugger);
   }
 
+  std::string locale = g_browser_process->GetApplicationLocale();
+  cmd_line->AppendSwitchASCII(switches::kLang, locale);
+
   // And then start the process asynchronously.
   launcher_ = new Launcher(this, cmd_line);
   launcher_->Run(
@@ -251,6 +244,17 @@
 
 void ServiceProcessControl::OnChannelConnected(int32 peer_pid) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  channel_->set_sync_messages_with_no_timeout_allowed(false);
+
+  // We just established a channel with the service process. Notify it if an
+  // upgrade is available.
+  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
+    Send(new ServiceMsg_UpdateAvailable);
+  } else {
+    if (registrar_.IsEmpty())
+      registrar_.Add(this, NotificationType::UPGRADE_RECOMMENDED,
+                     NotificationService::AllSources());
+  }
   RunConnectDoneTasks();
 }
 
diff --git a/chrome/browser/service/service_process_control_browsertest.cc b/chrome/browser/service/service_process_control_browsertest.cc
index 9087b8d..a0dee5d 100644
--- a/chrome/browser/service/service_process_control_browsertest.cc
+++ b/chrome/browser/service/service_process_control_browsertest.cc
@@ -71,7 +71,8 @@
   }
 
   void ProcessControlLaunched() {
-    base::ProcessId service_pid = GetServiceProcessPid();
+    base::ProcessId service_pid;
+    EXPECT_TRUE(GetServiceProcessSharedData(NULL, &service_pid));
     EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
     EXPECT_TRUE(base::OpenProcessHandleWithAccess(
         service_pid,
@@ -96,10 +97,11 @@
   base::ProcessHandle service_process_handle_;
 };
 
-#if defined(OS_WIN)
 // They way that the IPC is implemented only works on windows. This has to
 // change when we implement a different scheme for IPC.
-IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, LaunchAndIPC) {
+// Times out flakily, http://crbug.com/70076.
+IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
+                       DISABLED_LaunchAndIPC) {
   LaunchServiceProcessControl();
 
   // Make sure we are connected to the service process.
@@ -184,23 +186,28 @@
   WaitForShutdown();
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, ForceShutdown) {
+//http://code.google.com/p/chromium/issues/detail?id=70793
+IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
+                       DISABLED_ForceShutdown) {
   // Launch the service process.
   LaunchServiceProcessControl();
   // Make sure we are connected to the service process.
   EXPECT_TRUE(process()->is_connected());
+  base::ProcessId service_pid;
+  EXPECT_TRUE(GetServiceProcessSharedData(NULL, &service_pid));
+  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
   chrome::VersionInfo version_info;
-  ForceServiceProcessShutdown(version_info.Version());
+  ForceServiceProcessShutdown(version_info.Version(), service_pid);
   WaitForShutdown();
 }
 
 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, CheckPid) {
-  EXPECT_EQ(0, GetServiceProcessPid());
+  base::ProcessId service_pid;
+  EXPECT_FALSE(GetServiceProcessSharedData(NULL, &service_pid));
   // Launch the service process.
   LaunchServiceProcessControl();
-  EXPECT_NE(static_cast<base::ProcessId>(0), GetServiceProcessPid());
+  EXPECT_TRUE(GetServiceProcessSharedData(NULL, &service_pid));
+  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
 }
 
-#endif
-
 DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest);
diff --git a/chrome/browser/session_history_uitest.cc b/chrome/browser/session_history_uitest.cc
index 1553b1d..b65c90c 100644
--- a/chrome/browser/session_history_uitest.cc
+++ b/chrome/browser/session_history_uitest.cc
@@ -215,15 +215,9 @@
   EXPECT_EQ(frames, GetTabURL());
 }
 
-#if defined(OS_WIN)
 // See http://crbug.com/61619
-#define MAYBE_FrameFormBackForward FLAKY_FrameFormBackForward
-#else
-#define MAYBE_FrameFormBackForward FrameFormBackForward
-#endif
-
 // Test that back/forward preserves POST data and document state in subframes.
-TEST_F(SessionHistoryTest, MAYBE_FrameFormBackForward) {
+TEST_F(SessionHistoryTest, FLAKY_FrameFormBackForward) {
   ASSERT_TRUE(test_server_.Start());
 
   // about:blank should be loaded first.
diff --git a/chrome/browser/sessions/session_backend.cc b/chrome/browser/sessions/session_backend.cc
index f5a0c39..314e427 100644
--- a/chrome/browser/sessions/session_backend.cc
+++ b/chrome/browser/sessions/session_backend.cc
@@ -21,6 +21,13 @@
 
 namespace {
 
+// The file header is the first bytes written to the file,
+// and is used to identify the file as one written by us.
+struct FileHeader {
+  int32 signature;
+  int32 version;
+};
+
 // SessionFileReader ----------------------------------------------------------
 
 // SessionFileReader is responsible for reading the set of SessionCommands that
@@ -81,13 +88,13 @@
                              std::vector<SessionCommand*>* commands) {
   if (!file_->IsOpen())
     return false;
-  int32 header[2];
+  FileHeader header;
   int read_count;
   TimeTicks start_time = TimeTicks::Now();
   read_count = file_->ReadUntilComplete(reinterpret_cast<char*>(&header),
                                         sizeof(header));
-  if (read_count != sizeof(header) || header[0] != kFileSignature ||
-      header[1] != kFileCurrentVersion)
+  if (read_count != sizeof(header) || header.signature != kFileSignature ||
+      header.version != kFileCurrentVersion)
     return false;
 
   ScopedVector<SessionCommand> read_commands;
@@ -346,7 +353,8 @@
     // reopening to avoid the possibility of scanners locking the file out
     // from under us once we close it. If truncation fails, we'll try to
     // recreate.
-    if (current_session_file_->Truncate(sizeof_header()) != sizeof_header())
+    const int header_size = static_cast<int>(sizeof(FileHeader));
+    if (current_session_file_->Truncate(header_size) != header_size)
       current_session_file_.reset(NULL);
   }
   if (!current_session_file_.get())
@@ -362,12 +370,12 @@
              base::PLATFORM_FILE_EXCLUSIVE_READ);
   if (!file->IsOpen())
     return NULL;
-  int32 header[2];
-  header[0] = kFileSignature;
-  header[1] = kFileCurrentVersion;
+  FileHeader header;
+  header.signature = kFileSignature;
+  header.version = kFileCurrentVersion;
   int wrote = file->Write(reinterpret_cast<char*>(&header),
                           sizeof(header), NULL);
-  if (wrote != sizeof_header())
+  if (wrote != sizeof(header))
     return NULL;
   return file.release();
 }
diff --git a/chrome/browser/sessions/session_backend.h b/chrome/browser/sessions/session_backend.h
index 883a58f..a0594b1 100644
--- a/chrome/browser/sessions/session_backend.h
+++ b/chrome/browser/sessions/session_backend.h
@@ -114,13 +114,6 @@
   bool AppendCommandsToFile(net::FileStream* file,
                             const std::vector<SessionCommand*>& commands);
 
-  // Returns the size of the header. The header is the first bytes written to
-  // the file, and is used to identify the file as one written by us.
-  int32 sizeof_header() const {
-    int32 header[2];
-    return sizeof(header);
-  }
-
   const BaseSessionService::SessionType type_;
 
   // Returns the path to the last file.
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index 929042b..49e6399 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -11,11 +11,14 @@
 
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/metrics/histogram.h"
 #include "base/scoped_ptr.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sessions/session_types.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
@@ -26,7 +29,6 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_service.h"
 
@@ -55,14 +57,16 @@
 // of SessionRestoreImpl doesn't have timing problems.
 class TabLoader : public NotificationObserver {
  public:
-  typedef std::list<NavigationController*> TabsToLoad;
-
-  TabLoader();
+  explicit TabLoader(base::TimeTicks restore_started);
   ~TabLoader();
 
   // Schedules a tab for loading.
   void ScheduleLoad(NavigationController* controller);
 
+  // Notifies the loader that a tab has been scheduled for loading through
+  // some other mechanism.
+  void TabIsLoading(NavigationController* controller);
+
   // Invokes |LoadNextTab| to load a tab.
   //
   // This must be invoked once to start loading.
@@ -70,6 +74,8 @@
 
  private:
   typedef std::set<NavigationController*> TabsLoading;
+  typedef std::list<NavigationController*> TabsToLoad;
+  typedef std::set<RenderWidgetHost*> RenderWidgetHostSet;
 
   // Loads the next tab. If there are no more tabs to load this deletes itself,
   // otherwise |force_load_timer_| is restarted.
@@ -90,6 +96,16 @@
   // |LoadNextTab| to load the next tab
   void ForceLoadTimerFired();
 
+  // Returns the RenderWidgetHost associated with a tab if there is one,
+  // NULL otherwise.
+  static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab);
+
+  // Register for necessary notificaitons on a tab navigation controller.
+  void RegisterForNotifications(NavigationController* controller);
+
+  // Called when a tab goes away or a load completes.
+  void HandleTabClosedOrLoaded(NavigationController* controller);
+
   NotificationRegistrar registrar_;
 
   // Current delay before a new tab is loaded. See class description for
@@ -99,6 +115,9 @@
   // Has Load been invoked?
   bool loading_;
 
+  // Have we recorded the times for a tab paint?
+  bool got_first_paint_;
+
   // The set of tabs we've initiated loading on. This does NOT include the
   // selected tabs.
   TabsLoading tabs_loading_;
@@ -106,36 +125,58 @@
   // The tabs we need to load.
   TabsToLoad tabs_to_load_;
 
+  // The renderers we have started loading into.
+  RenderWidgetHostSet render_widget_hosts_loading_;
+
+  // The renderers we have loaded and are waiting on to paint.
+  RenderWidgetHostSet render_widget_hosts_to_paint_;
+
+  // The number of tabs that have been restored.
+  int tab_count_;
+
   base::OneShotTimer<TabLoader> force_load_timer_;
 
+  // The time the restore process started.
+  base::TimeTicks restore_started_;
+
   DISALLOW_COPY_AND_ASSIGN(TabLoader);
 };
 
-TabLoader::TabLoader()
+TabLoader::TabLoader(base::TimeTicks restore_started)
     : force_load_delay_(kInitialDelayTimerMS),
-      loading_(false) {
+      loading_(false),
+      got_first_paint_(false),
+      tab_count_(0),
+      restore_started_(restore_started) {
 }
 
 TabLoader::~TabLoader() {
-  DCHECK(tabs_to_load_.empty() && tabs_loading_.empty());
+  DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
+          tabs_loading_.empty() && tabs_to_load_.empty());
 }
 
 void TabLoader::ScheduleLoad(NavigationController* controller) {
-  if (controller) {
-    DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) ==
-           tabs_to_load_.end());
-    tabs_to_load_.push_back(controller);
-    registrar_.Add(this, NotificationType::TAB_CLOSED,
-                   Source<NavigationController>(controller));
-    registrar_.Add(this, NotificationType::LOAD_STOP,
-                   Source<NavigationController>(controller));
-  } else {
-    // Should never get a NULL tab.
-    NOTREACHED();
-  }
+  DCHECK(controller);
+  DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) ==
+         tabs_to_load_.end());
+  tabs_to_load_.push_back(controller);
+  RegisterForNotifications(controller);
+}
+
+void TabLoader::TabIsLoading(NavigationController* controller) {
+  DCHECK(controller);
+  DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) ==
+         tabs_loading_.end());
+  tabs_loading_.insert(controller);
+  RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller);
+  DCHECK(render_widget_host);
+  render_widget_hosts_loading_.insert(render_widget_host);
+  RegisterForNotifications(controller);
 }
 
 void TabLoader::StartLoading() {
+  registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
+                 NotificationService::AllSources());
 #if defined(OS_CHROMEOS)
   if (chromeos::NetworkStateNotifier::is_connected()) {
     loading_ = true;
@@ -174,17 +215,14 @@
     }
   }
 
-  if (tabs_to_load_.empty()) {
-    tabs_loading_.clear();
-    delete this;
-    return;
-  }
-
-  if (force_load_timer_.IsRunning())
+  if (!tabs_to_load_.empty()) {
     force_load_timer_.Stop();
-  force_load_timer_.Start(
-      base::TimeDelta::FromMilliseconds(force_load_delay_),
-      this, &TabLoader::ForceLoadTimerFired);
+    // Each time we load a tab we also set a timer to force us to start loading
+    // the next tab if this one doesn't load quickly enough.
+    force_load_timer_.Start(
+        base::TimeDelta::FromMilliseconds(force_load_delay_),
+        this, &TabLoader::ForceLoadTimerFired);
+  }
 }
 
 void TabLoader::Observe(NotificationType type,
@@ -216,30 +254,86 @@
       break;
     }
 #endif
-    case NotificationType::TAB_CLOSED:
+    case NotificationType::LOAD_START: {
+      // Add this render_widget_host to the set of those we're waiting for
+      // paints on. We want to only record stats for paints that occur after
+      // a load has finished.
+      NavigationController* tab = Source<NavigationController>(source).ptr();
+      RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
+      DCHECK(render_widget_host);
+      render_widget_hosts_loading_.insert(render_widget_host);
+      break;
+    }
+    case NotificationType::TAB_CONTENTS_DESTROYED: {
+      TabContents* tab_contents = Source<TabContents>(source).ptr();
+      if (!got_first_paint_) {
+        render_widget_hosts_loading_.erase(
+            tab_contents->GetRenderWidgetHostView()->GetRenderWidgetHost());
+      }
+      HandleTabClosedOrLoaded(&tab_contents->controller());
+      break;
+    }
     case NotificationType::LOAD_STOP: {
       NavigationController* tab = Source<NavigationController>(source).ptr();
-      RemoveTab(tab);
-      if (loading_) {
-        LoadNextTab();
-        // WARNING: if there are no more tabs to load, we have been deleted.
-      } else if (tabs_to_load_.empty()) {
-        tabs_loading_.clear();
-        delete this;
-        return;
+      render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab));
+      HandleTabClosedOrLoaded(tab);
+      break;
+    }
+    case NotificationType::RENDER_WIDGET_HOST_DID_PAINT: {
+      if (!got_first_paint_) {
+        RenderWidgetHost* render_widget_host =
+            Source<RenderWidgetHost>(source).ptr();
+        if (render_widget_hosts_to_paint_.find(render_widget_host) !=
+            render_widget_hosts_to_paint_.end()) {
+          // Got a paint for one of our renderers, so record time.
+          got_first_paint_ = true;
+          base::TimeDelta time_to_paint =
+              base::TimeTicks::Now() - restore_started_;
+          HISTOGRAM_CUSTOM_TIMES(
+              "SessionRestore.FirstTabPainted",
+              time_to_paint,
+              base::TimeDelta::FromMilliseconds(10),
+              base::TimeDelta::FromSeconds(100),
+              100);
+          // Record a time for the number of tabs, to help track down
+          // contention.
+          std::string time_for_count =
+              StringPrintf("SessionRestore.FirstTabPainted_%d", tab_count_);
+          scoped_refptr<base::Histogram> counter_for_count =
+              base::Histogram::FactoryTimeGet(
+                  time_for_count,
+                  base::TimeDelta::FromMilliseconds(10),
+                  base::TimeDelta::FromSeconds(100),
+                  100,
+                  base::Histogram::kNoFlags);
+          counter_for_count->AddTime(time_to_paint);
+        } else if (render_widget_hosts_loading_.find(render_widget_host) ==
+            render_widget_hosts_loading_.end()) {
+          // If this is a host for a tab we're not loading some other tab
+          // has rendered and there's no point tracking the time. This could
+          // happen because the user opened a different tab or restored tabs
+          // to an already existing browser and an existing tab painted.
+          got_first_paint_ = true;
+        }
       }
       break;
     }
     default:
       NOTREACHED() << "Unknown notification received:" << type.value;
   }
+  // Delete ourselves when we're not waiting for any more notifications.
+  if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
+      tabs_loading_.empty() && tabs_to_load_.empty())
+    delete this;
 }
 
 void TabLoader::RemoveTab(NavigationController* tab) {
-  registrar_.Remove(this, NotificationType::TAB_CLOSED,
-                    Source<NavigationController>(tab));
+  registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                    Source<TabContents>(tab->tab_contents()));
   registrar_.Remove(this, NotificationType::LOAD_STOP,
                     Source<NavigationController>(tab));
+  registrar_.Remove(this, NotificationType::LOAD_START,
+                    Source<NavigationController>(tab));
 
   TabsLoading::iterator i = tabs_loading_.find(tab);
   if (i != tabs_loading_.end())
@@ -256,6 +350,54 @@
   LoadNextTab();
 }
 
+RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) {
+  TabContents* tab_contents = tab->tab_contents();
+  if (tab_contents) {
+    RenderWidgetHostView* render_widget_host_view =
+        tab_contents->GetRenderWidgetHostView();
+    if (render_widget_host_view)
+      return render_widget_host_view->GetRenderWidgetHost();
+  }
+  return NULL;
+}
+
+void TabLoader::RegisterForNotifications(NavigationController* controller) {
+  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                 Source<TabContents>(controller->tab_contents()));
+  registrar_.Add(this, NotificationType::LOAD_STOP,
+                 Source<NavigationController>(controller));
+  registrar_.Add(this, NotificationType::LOAD_START,
+                 Source<NavigationController>(controller));
+  ++tab_count_;
+}
+
+void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) {
+  RemoveTab(tab);
+  if (loading_)
+    LoadNextTab();
+  if (tabs_loading_.empty() && tabs_to_load_.empty()) {
+    base::TimeDelta time_to_load =
+        base::TimeTicks::Now() - restore_started_;
+    HISTOGRAM_CUSTOM_TIMES(
+        "SessionRestore.AllTabsLoaded",
+        time_to_load,
+        base::TimeDelta::FromMilliseconds(10),
+        base::TimeDelta::FromSeconds(100),
+        100);
+    // Record a time for the number of tabs, to help track down contention.
+    std::string time_for_count =
+        StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
+    scoped_refptr<base::Histogram> counter_for_count =
+        base::Histogram::FactoryTimeGet(
+            time_for_count,
+            base::TimeDelta::FromMilliseconds(10),
+            base::TimeDelta::FromSeconds(100),
+            100,
+            base::Histogram::kNoFlags);
+    counter_for_count->AddTime(time_to_load);
+  }
+}
+
 // SessionRestoreImpl ---------------------------------------------------------
 
 // SessionRestoreImpl is responsible for fetching the set of tabs to create
@@ -274,7 +416,8 @@
         synchronous_(synchronous),
         clobber_existing_window_(clobber_existing_window),
         always_create_tabbed_browser_(always_create_tabbed_browser),
-        urls_to_open_(urls_to_open) {
+        urls_to_open_(urls_to_open),
+        restore_started_(base::TimeTicks::Now()) {
   }
 
   void Restore() {
@@ -315,8 +458,11 @@
 
       // Restore and show the browser.
       const int initial_tab_count = browser->tab_count();
-      RestoreTabsToBrowser(*(*i), browser);
-      ShowBrowser(browser, initial_tab_count, (*i)->selected_tab_index);
+      int selected_tab_index = (*i)->selected_tab_index;
+      RestoreTabsToBrowser(*(*i), browser, selected_tab_index);
+      ShowBrowser(browser, initial_tab_count, selected_tab_index);
+      tab_loader_->TabIsLoading(
+          &browser->GetSelectedTabContents()->controller());
       NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
     }
 
@@ -330,7 +476,7 @@
     StartTabCreation();
     Browser* current_browser =
         browser_ ? browser_ : BrowserList::GetLastActive();
-    RestoreTab(tab, current_browser->tab_count(), current_browser);
+    RestoreTab(tab, current_browser->tab_count(), current_browser, true);
     NotifySessionServiceOfRestoredTabs(current_browser,
                                        current_browser->tab_count());
     FinishedTabCreation(true, true);
@@ -358,7 +504,7 @@
  private:
   // Invoked when beginning to create new tabs. Resets the tab_loader_.
   void StartTabCreation() {
-    tab_loader_.reset(new TabLoader());
+    tab_loader_.reset(new TabLoader(restore_started_));
   }
 
   // Invoked when done with creating all the tabs/browsers.
@@ -447,8 +593,11 @@
       if ((*i)->type == Browser::TYPE_NORMAL)
         last_browser = browser;
       const int initial_tab_count = browser->tab_count();
-      RestoreTabsToBrowser(*(*i), browser);
-      ShowBrowser(browser, initial_tab_count, (*i)->selected_tab_index);
+      int selected_tab_index = (*i)->selected_tab_index;
+      RestoreTabsToBrowser(*(*i), browser, selected_tab_index);
+      ShowBrowser(browser, initial_tab_count, selected_tab_index);
+      tab_loader_->TabIsLoading(
+          &browser->GetSelectedTabContents()->controller());
       NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
     }
 
@@ -467,33 +616,41 @@
     FinishedTabCreation(true, has_tabbed_browser);
   }
 
-  void RestoreTabsToBrowser(const SessionWindow& window, Browser* browser) {
+  void RestoreTabsToBrowser(const SessionWindow& window,
+                            Browser* browser,
+                            int selected_tab_index) {
     DCHECK(!window.tabs.empty());
     for (std::vector<SessionTab*>::const_iterator i = window.tabs.begin();
          i != window.tabs.end(); ++i) {
       const SessionTab& tab = *(*i);
-      RestoreTab(tab, static_cast<int>(i - window.tabs.begin()), browser);
+      const int tab_index = static_cast<int>(i - window.tabs.begin());
+      // Don't schedule a load for the selected tab, as ShowBrowser() will
+      // already have done that.
+      RestoreTab(tab, tab_index, browser, tab_index != selected_tab_index);
     }
   }
 
   void RestoreTab(const SessionTab& tab,
                   const int tab_index,
-                  Browser* browser) {
+                  Browser* browser,
+                  bool schedule_load) {
     DCHECK(!tab.navigations.empty());
     int selected_index = tab.current_navigation_index;
     selected_index = std::max(
         0,
         std::min(selected_index,
                  static_cast<int>(tab.navigations.size() - 1)));
-    tab_loader_->ScheduleLoad(
-        &browser->AddRestoredTab(tab.navigations,
-                                 tab_index,
-                                 selected_index,
-                                 tab.extension_app_id,
-                                 false,
-                                 tab.pinned,
-                                 true,
-                                 NULL)->controller());
+    TabContents* tab_contents =
+        browser->AddRestoredTab(tab.navigations,
+                                tab_index,
+                                selected_index,
+                                tab.extension_app_id,
+                                false,
+                                tab.pinned,
+                                true,
+                                NULL);
+    if (schedule_load)
+      tab_loader_->ScheduleLoad(&tab_contents->controller());
   }
 
   Browser* CreateRestoredBrowser(Browser::Type type,
@@ -586,6 +743,9 @@
   std::vector<SessionWindow*> windows_;
 
   NotificationRegistrar registrar_;
+
+  // The time we started the restore.
+  base::TimeTicks restore_started_;
 };
 
 }  // namespace
diff --git a/chrome/browser/sessions/session_restore_uitest.cc b/chrome/browser/sessions/session_restore_uitest.cc
index 5dcbb77..d79efa5 100644
--- a/chrome/browser/sessions/session_restore_uitest.cc
+++ b/chrome/browser/sessions/session_restore_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 #include "base/file_path.h"
 #include "base/scoped_ptr.h"
 #include "base/string_number_conversions.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/common/chrome_paths.h"
@@ -32,7 +33,7 @@
 
   virtual void QuitBrowserAndRestore(int expected_tab_count) {
 #if defined(OS_MACOSX)
-    shutdown_type_ = ProxyLauncher::USER_QUIT;
+    set_shutdown_type(ProxyLauncher::USER_QUIT);
 #endif
     UITest::TearDown();
 
@@ -76,7 +77,8 @@
 
     scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetActiveTab());
     ASSERT_TRUE(tab_proxy.get());
-    ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+    ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+        TestTimeouts::action_max_timeout_ms()));
 
     ASSERT_TRUE(tab_proxy->GetCurrentURL(url));
   }
@@ -103,7 +105,8 @@
   scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser_proxy.get());
   scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_max_timeout_ms()));
 
   ASSERT_EQ(url2_, GetActiveTabURL());
   ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab_proxy->GoBack());
@@ -129,7 +132,8 @@
   scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser_proxy.get());
   scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_max_timeout_ms()));
 
   ASSERT_TRUE(GetActiveTabURL() == url2_);
   ASSERT_TRUE(tab_proxy->GoForward());
@@ -173,7 +177,8 @@
   ASSERT_EQ(1, tab_count);
   scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
   ASSERT_TRUE(tab_proxy.get());
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_max_timeout_ms()));
 
   // Check that back and forward work as expected.
   GURL url;
@@ -223,14 +228,16 @@
 
   scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetActiveTab());
   ASSERT_TRUE(tab_proxy.get());
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_max_timeout_ms()));
 
   ASSERT_EQ(url2_, GetActiveTabURL());
 
   ASSERT_TRUE(browser_proxy->ActivateTab(0));
   tab_proxy = browser_proxy->GetActiveTab();
   ASSERT_TRUE(tab_proxy.get());
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_max_timeout_ms()));
 
   ASSERT_EQ(url1_, GetActiveTabURL());
 }
@@ -370,7 +377,8 @@
   ASSERT_TRUE(browser_proxy.get());
   scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
   ASSERT_TRUE(tab_proxy.get());
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_max_timeout_ms()));
   GURL url;
   ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
   ASSERT_TRUE(url != url1_);
@@ -442,7 +450,8 @@
 // process-per-site and process-per-site-instance, because we treat the new tab
 // as a special case in process-per-site-instance so that it only ever uses one
 // process.)
-// Flaky as per http://crbug.com/52022
+//
+// Flaky: http://code.google.com/p/chromium/issues/detail?id=52022
 TEST_F(SessionRestoreUITest, FLAKY_ShareProcessesOnRestore) {
   if (ProxyLauncher::in_process_renderer()) {
     // No point in running this test in single process mode.
@@ -461,7 +470,8 @@
   ASSERT_TRUE(browser_proxy->GetTabCount(&new_tab_count));
   ASSERT_EQ(tab_count + 2, new_tab_count);
 
-  int expected_process_count = GetBrowserProcessCount();
+  int expected_process_count = 0;
+  ASSERT_TRUE(GetBrowserProcessCount(&expected_process_count));
   int expected_tab_count = new_tab_count;
 
   // Restart.
@@ -475,14 +485,16 @@
   ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
   ASSERT_EQ(expected_tab_count, tab_count);
 
-  scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(tab_count - 2));
-  ASSERT_TRUE(tab_proxy.get() != NULL);
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
-  tab_proxy = browser_proxy->GetTab(tab_count - 1);
-  ASSERT_TRUE(tab_proxy.get() != NULL);
-  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(action_max_timeout_ms()));
+  for (int i = 0; i < expected_tab_count; ++i) {
+    scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(i));
+    ASSERT_TRUE(tab_proxy.get() != NULL);
+    ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
+                    TestTimeouts::action_max_timeout_ms()));
+  }
 
-  ASSERT_EQ(expected_process_count, GetBrowserProcessCount());
+  int process_count = 0;
+  ASSERT_TRUE(GetBrowserProcessCount(&process_count));
+  ASSERT_EQ(expected_process_count, process_count);
 }
 
 }  // namespace
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h
index f17b77a..df97a78 100644
--- a/chrome/browser/sessions/session_service.h
+++ b/chrome/browser/sessions/session_service.h
@@ -444,7 +444,7 @@
   // current/previous session.
   bool move_on_new_browser_;
 
-  // Used for reporting frequency of session alteriing operations.
+  // Used for reporting frequency of session altering operations.
   base::TimeTicks last_updated_tab_closed_time_;
   base::TimeTicks last_updated_nav_list_pruned_time_;
   base::TimeTicks last_updated_nav_entry_commit_time_;
diff --git a/chrome/browser/sessions/session_service_test_helper.cc b/chrome/browser/sessions/session_service_test_helper.cc
index fda500b..5a87303 100644
--- a/chrome/browser/sessions/session_service_test_helper.cc
+++ b/chrome/browser/sessions/session_service_test_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,6 +13,13 @@
 
 using base::Time;
 
+SessionServiceTestHelper::SessionServiceTestHelper() {}
+
+SessionServiceTestHelper::SessionServiceTestHelper(SessionService* service)
+    : service_(service) {}
+
+SessionServiceTestHelper::~SessionServiceTestHelper() {}
+
 void SessionServiceTestHelper::RestoreSessionFromCommands(
     const std::vector<SessionCommand*>& commands,
     std::vector<SessionWindow*>* valid_windows) {
diff --git a/chrome/browser/sessions/session_service_test_helper.h b/chrome/browser/sessions/session_service_test_helper.h
index 062bb1c..882a0b5 100644
--- a/chrome/browser/sessions/session_service_test_helper.h
+++ b/chrome/browser/sessions/session_service_test_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,10 +23,9 @@
 
 class SessionServiceTestHelper {
  public:
-  explicit SessionServiceTestHelper() {}
-
-  explicit SessionServiceTestHelper(SessionService* service)
-      : service_(service) {}
+  explicit SessionServiceTestHelper();
+  explicit SessionServiceTestHelper(SessionService* service);
+  ~SessionServiceTestHelper();
 
   void RestoreSessionFromCommands(const std::vector<SessionCommand*>& commands,
                                   std::vector<SessionWindow*>* valid_windows);
diff --git a/chrome/browser/sessions/session_types.h b/chrome/browser/sessions/session_types.h
index 563663c..529393b 100644
--- a/chrome/browser/sessions/session_types.h
+++ b/chrome/browser/sessions/session_types.h
@@ -14,8 +14,8 @@
 #include "base/time.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/rect.h"
 
 class NavigationEntry;
 class Profile;
diff --git a/chrome/browser/sessions/tab_restore_service_browsertest.cc b/chrome/browser/sessions/tab_restore_service_browsertest.cc
index dc37fa1..c66d97e 100644
--- a/chrome/browser/sessions/tab_restore_service_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_service_browsertest.cc
@@ -12,7 +12,7 @@
 #include "chrome/test/render_view_test.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
 
 // Create subclass that overrides TimeNow so that we can control the time used
 // for closed tabs and windows.
diff --git a/chrome/browser/shell_dialogs.cc b/chrome/browser/shell_dialogs.cc
deleted file mode 100644
index c0f6875..0000000
--- a/chrome/browser/shell_dialogs.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/shell_dialogs.h"
-
-SelectFileDialog::FileTypeInfo::FileTypeInfo() : include_all_files(false) {}
-
-SelectFileDialog::FileTypeInfo::~FileTypeInfo() {}
-
-SelectFileDialog::SelectFileDialog() {}
-
-SelectFileDialog::~SelectFileDialog() {}
-
-SelectFontDialog::SelectFontDialog() {}
-
-SelectFontDialog::~SelectFontDialog() {}
diff --git a/chrome/browser/shell_dialogs.h b/chrome/browser/shell_dialogs.h
deleted file mode 100644
index d856720..0000000
--- a/chrome/browser/shell_dialogs.h
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SHELL_DIALOGS_H_
-#define CHROME_BROWSER_SHELL_DIALOGS_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include "base/file_path.h"
-#include "base/ref_counted.h"
-#include "base/string16.h"
-#include "gfx/native_widget_types.h"
-
-namespace gfx {
-class Font;
-}
-
-// This function is declared extern such that it is accessible for unit tests
-// in /chrome/browser/views/shell_dialogs_win_unittest.cc
-extern std::wstring AppendExtensionIfNeeded(const std::wstring& filename,
-                                            const std::wstring& filter_selected,
-                                            const std::wstring& suggested_ext);
-
-// A base class for shell dialogs.
-class BaseShellDialog {
- public:
-  // Returns true if a shell dialog box is currently being shown modally
-  // to the specified owner.
-  virtual bool IsRunning(gfx::NativeWindow owning_window) const = 0;
-
-  // Notifies the dialog box that the listener has been destroyed and it should
-  // no longer be sent notifications.
-  virtual void ListenerDestroyed() = 0;
-
- protected:
-  virtual ~BaseShellDialog() {}
-};
-
-// Shows a dialog box for selecting a file or a folder.
-class SelectFileDialog
-    : public base::RefCountedThreadSafe<SelectFileDialog>,
-      public BaseShellDialog {
- public:
-  enum Type {
-    SELECT_NONE,
-    SELECT_FOLDER,
-    SELECT_SAVEAS_FILE,
-    SELECT_OPEN_FILE,
-    SELECT_OPEN_MULTI_FILE
-  };
-
-  // An interface implemented by a Listener object wishing to know about the
-  // the result of the Select File/Folder action. These callbacks must be
-  // re-entrant.
-  class Listener {
-   public:
-    // Notifies the Listener that a file/folder selection has been made. The
-    // file/folder path is in |path|. |params| is contextual passed to
-    // SelectFile. |index| specifies the index of the filter passed to the
-    // the initial call to SelectFile.
-    virtual void FileSelected(const FilePath& path,
-                              int index, void* params) = 0;
-
-    // Notifies the Listener that many files have been selected. The
-    // files are in |files|. |params| is contextual passed to SelectFile.
-    virtual void MultiFilesSelected(
-      const std::vector<FilePath>& files, void* params) {}
-
-    // Notifies the Listener that the file/folder selection was aborted (via
-    // the  user canceling or closing the selection dialog box, for example).
-    // |params| is contextual passed to SelectFile.
-    virtual void FileSelectionCanceled(void* params) {}
-
-   protected:
-    virtual ~Listener() {}
-  };
-
-  // Creates a dialog box helper. This object is ref-counted, but the returned
-  // object will have no reference (refcount is 0).
-  static SelectFileDialog* Create(Listener* listener);
-
-  // Holds information about allowed extensions on a file save dialog.
-  // |extensions| is a list of allowed extensions. For example, it might be
-  //   { { "htm", "html" }, { "txt" } }. Only pass more than one extension
-  //   in the inner vector if the extensions are equivalent. Do NOT include
-  //   leading periods.
-  // |extension_description_overrides| overrides the system descriptions of the
-  //   specified extensions. Entries correspond to |extensions|; if left blank
-  //   the system descriptions will be used.
-  // |include_all_files| specifies whether there will be a filter added for all
-  //   files (i.e. *.*).
-  struct FileTypeInfo {
-    FileTypeInfo();
-    ~FileTypeInfo();
-
-    std::vector<std::vector<FilePath::StringType> > extensions;
-    std::vector<string16> extension_description_overrides;
-    bool include_all_files;
-  };
-
-  // Selects a file. This will start displaying the dialog box. This will also
-  // block the calling window until the dialog box is complete. The listener
-  // associated with this object will be notified when the selection is
-  // complete.
-  // |type| is the type of file dialog to be shown, see Type enumeration above.
-  // |title| is the title to be displayed in the dialog. If this string is
-  //   empty, the default title is used.
-  // |default_path| is the default path and suggested file name to be shown in
-  //   the dialog. This only works for SELECT_SAVEAS_FILE and SELECT_OPEN_FILE.
-  //   Can be an empty string to indicate the platform default.
-  // |file_types| holds the infomation about the file types allowed. Pass NULL
-  //   to get no special behavior
-  // |file_type_index| is the 1-based index into the file type list in
-  //   |file_types|. Specify 0 if you don't need to specify extension behavior.
-  // |default_extension| is the default extension to add to the file if the
-  //   user doesn't type one. This should NOT include the '.'. On Windows, if
-  //   you specify this you must also specify |file_types|.
-  // |owning_window| is the window the dialog is modal to, or NULL for a
-  //   modeless dialog.
-  // |params| is data from the calling context which will be passed through to
-  //   the listener. Can be NULL.
-  // NOTE: only one instance of any shell dialog can be shown per owning_window
-  //       at a time (for obvious reasons).
-  virtual void SelectFile(Type type,
-                          const string16& title,
-                          const FilePath& default_path,
-                          const FileTypeInfo* file_types,
-                          int file_type_index,
-                          const FilePath::StringType& default_extension,
-                          gfx::NativeWindow owning_window,
-                          void* params) = 0;
-
-  // browser_mode is true when running inside the browser.
-  virtual void set_browser_mode(bool value) {}
-
- protected:
-  friend class base::RefCountedThreadSafe<SelectFileDialog>;
-  SelectFileDialog();
-  virtual ~SelectFileDialog();
-};
-
-// Shows a dialog box for selecting a font.
-class SelectFontDialog
-    : public base::RefCountedThreadSafe<SelectFontDialog>,
-      public BaseShellDialog {
- public:
-
-  // An interface implemented by a Listener object wishing to know about the
-  // the result of the Select Font action. These callbacks must be
-  // re-entrant.
-  class Listener {
-   public:
-    // Notifies the Listener that a font selection has been made. The font
-    // details are supplied in |font|. |params| is contextual passed to
-    // SelectFont.
-    virtual void FontSelected(const gfx::Font& font, void* params) = 0;
-
-    // Notifies the Listener that the font selection was aborted (via the user
-    // canceling or closing the selection dialog box, for example). |params| is
-    // contextual passed to SelectFont.
-    virtual void FontSelectionCanceled(void* params) {}
-
-   protected:
-    virtual ~Listener() {}
-  };
-
-  // Creates a dialog box helper. This object is ref-counted, but the returned
-  // object will have no reference (refcount is 0).
-  static SelectFontDialog* Create(Listener* listener);
-
-  // Selects a font. This will start displaying the dialog box. This will also
-  // block the calling window until the dialog box is complete. The listener
-  // associated with this object will be notified when the selection is
-  // complete.
-  // |owning_window| is the window the dialog is modal to, or NULL for a
-  // modeless dialog.
-  // |params| is data from the calling context which will be passed through to
-  // the listener. Can be NULL.
-  // NOTE: only one instance of any shell dialog can be shown per owning_window
-  //       at a time (for obvious reasons).
-  // TODO(beng): support specifying the default font selected in the list when
-  //             the dialog appears.
-  virtual void SelectFont(gfx::NativeWindow owning_window,
-                          void* params) = 0;
-
-  // Same as above - also support specifying the default font selected in the
-  // list when the dialog appears.
-  virtual void SelectFont(gfx::NativeWindow owning_window,
-                          void* params,
-                          const std::wstring& font_name,
-                          int font_size) = 0;
-
- protected:
-  friend class base::RefCountedThreadSafe<SelectFontDialog>;
-  SelectFontDialog();
-  virtual ~SelectFontDialog();
-};
-
-#endif  // CHROME_BROWSER_SHELL_DIALOGS_H_
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index 4b6b2a5..ad0106d 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,8 +10,10 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
 
 ShellIntegration::ShortcutInfo::ShortcutInfo()
     : create_on_desktop(false),
@@ -21,7 +23,8 @@
 
 ShellIntegration::ShortcutInfo::~ShortcutInfo() {}
 
-std::string ShellIntegration::GetCommandLineArgumentsCommon(const GURL& url,
+std::string ShellIntegration::GetCommandLineArgumentsCommon(
+    const GURL& url,
     const string16& extension_app_id) {
   const CommandLine cmd = *CommandLine::ForCurrentProcess();
   std::wstring arguments_w;
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index b9c6530..6caed57 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,6 +15,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 
 class FilePath;
+class PrefService;
 
 #if defined(USE_X11)
 namespace base {
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index accbd58..cbcafba 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -33,9 +33,8 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_plugin_util.h"
-#include "chrome/common/chrome_switches.h"
-#include "gfx/codec/png_codec.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace {
 
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index aaf1d78..470a953 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -36,7 +36,7 @@
 namespace {
 
 // Helper function for ShellIntegration::GetAppId to generates profile id
-// from profile path. "profile_id"  is composed of sanitized basenames of
+// from profile path. "profile_id" is composed of sanitized basenames of
 // user data dir and profile dir joined by a ".".
 std::wstring GetProfileIdFromPath(const FilePath& profile_path) {
   // Return empty string if profile_path is empty
@@ -227,6 +227,9 @@
   if (command_line.HasSwitch(switches::kApp)) {
     app_name = UTF8ToWide(web_app::GenerateApplicationNameFromURL(
         GURL(command_line.GetSwitchValueASCII(switches::kApp))));
+  } else if (command_line.HasSwitch(switches::kAppId)) {
+    app_name = UTF8ToWide(web_app::GenerateApplicationNameFromExtensionId(
+        command_line.GetSwitchValueASCII(switches::kAppId)));
   } else {
     app_name = BrowserDistribution::GetDistribution()->GetBrowserAppId();
   }
@@ -343,7 +346,7 @@
       std::wstring key_path(kChromeProtocols[i] + ShellUtil::kRegShellOpen);
       base::win::RegKey key(root_key, key_path.c_str(), KEY_READ);
       std::wstring value;
-      if (!key.Valid() || !key.ReadValue(L"", &value))
+      if (!key.Valid() || (key.ReadValue(L"", &value) != ERROR_SUCCESS))
         return NOT_DEFAULT_BROWSER;
       // Need to normalize path in case it's been munged.
       CommandLine command_line = CommandLine::FromString(value);
@@ -374,7 +377,7 @@
     std::wstring app_cmd;
     base::win::RegKey key(HKEY_CURRENT_USER,
                           ShellUtil::kRegVistaUrlPrefs, KEY_READ);
-    if (key.Valid() && key.ReadValue(L"Progid", &app_cmd) &&
+    if (key.Valid() && (key.ReadValue(L"Progid", &app_cmd) == ERROR_SUCCESS) &&
         app_cmd == L"FirefoxURL")
       ff_default = true;
   } else {
@@ -382,7 +385,7 @@
     key_path.append(ShellUtil::kRegShellOpen);
     base::win::RegKey key(HKEY_CLASSES_ROOT, key_path.c_str(), KEY_READ);
     std::wstring app_cmd;
-    if (key.Valid() && key.ReadValue(L"", &app_cmd) &&
+    if (key.Valid() && (key.ReadValue(L"", &app_cmd) == ERROR_SUCCESS) &&
         std::wstring::npos != StringToLowerASCII(app_cmd).find(L"firefox"))
       ff_default = true;
   }
diff --git a/chrome/browser/sidebar/sidebar_browsertest.cc b/chrome/browser/sidebar/sidebar_browsertest.cc
new file mode 100644
index 0000000..041a683
--- /dev/null
+++ b/chrome/browser/sidebar/sidebar_browsertest.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2011 The Chromium 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/command_line.h"
+#include "base/file_path.h"
+#include "base/path_service.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/sidebar/sidebar_manager.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "net/test/test_server.h"
+
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+
+namespace {
+
+const char kSimplePage[] = "files/sidebar/simple_page.html";
+
+class SidebarTest : public ExtensionBrowserTest {
+ public:
+  SidebarTest() {
+    CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kEnableExperimentalExtensionApis);
+  }
+
+ protected:
+  // InProcessBrowserTest overrides.
+  virtual void SetUpOnMainThread() {
+    ExtensionBrowserTest::SetUpOnMainThread();
+
+    // Load test sidebar extension.
+    FilePath extension_path;
+    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extension_path));
+    extension_path = extension_path.AppendASCII("sidebar");
+
+    ASSERT_TRUE(LoadExtension(extension_path));
+
+    // For now content_id == extension_id.
+    content_id_ = last_loaded_extension_id_;
+  }
+
+  void ShowSidebarForCurrentTab() {
+    ShowSidebar(browser()->GetSelectedTabContents());
+  }
+
+  void ExpandSidebarForCurrentTab() {
+    ExpandSidebar(browser()->GetSelectedTabContents());
+  }
+
+  void CollapseSidebarForCurrentTab() {
+    CollapseSidebar(browser()->GetSelectedTabContents());
+  }
+
+  void HideSidebarForCurrentTab() {
+    HideSidebar(browser()->GetSelectedTabContents());
+  }
+
+  void NavigateSidebarForCurrentTabTo(const std::string& test_page) {
+    GURL url = test_server()->GetURL(test_page);
+
+    TabContents* tab = browser()->GetSelectedTabContents();
+
+    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+
+    sidebar_manager->NavigateSidebar(tab, content_id_, url);
+
+    SidebarContainer* sidebar_container =
+        sidebar_manager->GetSidebarContainerFor(tab, content_id_);
+
+    TabContents* client_contents = sidebar_container->sidebar_contents();
+    ui_test_utils::WaitForNavigation(&client_contents->controller());
+  }
+
+  void ShowSidebar(TabContents* tab) {
+    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+    sidebar_manager->ShowSidebar(tab, content_id_);
+  }
+
+  void ExpandSidebar(TabContents* tab) {
+    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+    sidebar_manager->ExpandSidebar(tab, content_id_);
+    if (browser()->GetSelectedTabContents() == tab)
+      EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
+  }
+
+  void CollapseSidebar(TabContents* tab) {
+    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+    sidebar_manager->CollapseSidebar(tab, content_id_);
+    if (browser()->GetSelectedTabContents() == tab)
+      EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+  }
+
+  void HideSidebar(TabContents* tab) {
+    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+    sidebar_manager->HideSidebar(tab, content_id_);
+    if (browser()->GetSelectedTabContents() == tab)
+      EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+  }
+
+  TabContents* tab_contents(int i) {
+    return browser()->GetTabContentsAt(i);
+  }
+
+  BrowserView* browser_view() const {
+    return static_cast<BrowserView*>(browser()->window());
+  }
+
+ private:
+  std::string content_id_;
+};
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, OpenClose) {
+  ShowSidebarForCurrentTab();
+
+  ExpandSidebarForCurrentTab();
+  CollapseSidebarForCurrentTab();
+
+  ExpandSidebarForCurrentTab();
+  CollapseSidebarForCurrentTab();
+
+  ExpandSidebarForCurrentTab();
+  CollapseSidebarForCurrentTab();
+
+  HideSidebarForCurrentTab();
+
+  ShowSidebarForCurrentTab();
+
+  ExpandSidebarForCurrentTab();
+  CollapseSidebarForCurrentTab();
+
+  HideSidebarForCurrentTab();
+}
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, SwitchingTabs) {
+  ShowSidebarForCurrentTab();
+  ExpandSidebarForCurrentTab();
+
+  browser()->NewTab();
+
+  // Make sure sidebar is not visbile for the newly opened tab.
+  EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+
+  // Switch back to the first tab.
+  browser()->SelectNumberedTab(0);
+
+  // Make sure it is visible now.
+  EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
+
+  HideSidebarForCurrentTab();
+}
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, SidebarOnInactiveTab) {
+  ShowSidebarForCurrentTab();
+  ExpandSidebarForCurrentTab();
+
+  browser()->NewTab();
+
+  // Hide sidebar on inactive (first) tab.
+  HideSidebar(tab_contents(0));
+
+  // Switch back to the first tab.
+  browser()->SelectNumberedTab(0);
+
+  // Make sure sidebar is not visbile anymore.
+  EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+
+  // Show sidebar on inactive (second) tab.
+  ShowSidebar(tab_contents(1));
+  ExpandSidebar(tab_contents(1));
+  // Make sure sidebar is not visible yet.
+  EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+
+  // Switch back to the second tab.
+  browser()->SelectNumberedTab(1);
+  // Make sure sidebar is visible now.
+  EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
+
+  HideSidebarForCurrentTab();
+}
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, SidebarNavigate) {
+  ASSERT_TRUE(test_server()->Start());
+
+  ShowSidebarForCurrentTab();
+
+  NavigateSidebarForCurrentTabTo(kSimplePage);
+
+  HideSidebarForCurrentTab();
+}
+
+}  // namespace
+
diff --git a/chrome/browser/sidebar/sidebar_container.cc b/chrome/browser/sidebar/sidebar_container.cc
index 7112433..4c17dc5 100644
--- a/chrome/browser/sidebar/sidebar_container.cc
+++ b/chrome/browser/sidebar/sidebar_container.cc
@@ -4,12 +4,18 @@
 
 #include "chrome/browser/sidebar/sidebar_container.h"
 
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/common/bindings_policy.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/extensions/extension_sidebar_defaults.h"
+#include "chrome/common/extensions/extension_sidebar_utils.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -19,7 +25,9 @@
     : tab_(tab),
       content_id_(content_id),
       delegate_(delegate),
-      icon_(new SkBitmap) {
+      icon_(new SkBitmap),
+      navigate_to_default_page_on_expand_(true),
+      use_default_icon_(true) {
   // Create TabContents for sidebar.
   sidebar_contents_.reset(
       new TabContents(tab->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL));
@@ -36,11 +44,41 @@
   delegate_->UpdateSidebar(this);
 }
 
+void SidebarContainer::LoadDefaults() {
+  const Extension* extension = GetExtension();
+  if (!extension)
+    return;  // Can be NULL in tests.
+  const ExtensionSidebarDefaults* sidebar_defaults =
+      extension->sidebar_defaults();
+
+  title_ = sidebar_defaults->default_title();
+
+  if (!sidebar_defaults->default_icon_path().empty()) {
+    image_loading_tracker_.reset(new ImageLoadingTracker(this));
+    image_loading_tracker_->LoadImage(
+        extension,
+        extension->GetResource(sidebar_defaults->default_icon_path()),
+        gfx::Size(Extension::kSidebarIconMaxSize,
+                  Extension::kSidebarIconMaxSize),
+        ImageLoadingTracker::CACHE);
+  }
+}
+
 void SidebarContainer::Show() {
   delegate_->UpdateSidebar(this);
 }
 
 void SidebarContainer::Expand() {
+  if (navigate_to_default_page_on_expand_) {
+    navigate_to_default_page_on_expand_ = false;
+    // Check whether a default page is specified for this sidebar.
+    const Extension* extension = GetExtension();
+    if (extension) {  // Can be NULL in tests.
+      if (extension->sidebar_defaults()->default_page().is_valid())
+        Navigate(extension->sidebar_defaults()->default_page());
+    }
+  }
+
   delegate_->UpdateSidebar(this);
   sidebar_contents_->view()->SetInitialFocus();
 }
@@ -50,8 +88,8 @@
 }
 
 void SidebarContainer::Navigate(const GURL& url) {
-  DCHECK(sidebar_contents_.get());
   // TODO(alekseys): add a progress UI.
+  navigate_to_default_page_on_expand_ = false;
   sidebar_contents_->controller().LoadURL(
       url, GURL(), PageTransition::START_PAGE);
 }
@@ -61,6 +99,7 @@
 }
 
 void SidebarContainer::SetIcon(const SkBitmap& bitmap) {
+  use_default_icon_ = false;
   *icon_ = bitmap;
 }
 
@@ -72,3 +111,20 @@
   return false;
 }
 
+void SidebarContainer::OnImageLoaded(SkBitmap* image,
+                                     ExtensionResource resource,
+                                     int index) {
+  if (image && use_default_icon_) {
+    *icon_ = *image;
+     delegate_->UpdateSidebar(this);
+  }
+}
+
+const Extension* SidebarContainer::GetExtension() const {
+  ExtensionService* service =
+      sidebar_contents_->profile()->GetExtensionService();
+  if (!service)
+    return NULL;
+  return service->GetExtensionById(
+      extension_sidebar_utils::GetExtensionIdByContentId(content_id_), false);
+}
diff --git a/chrome/browser/sidebar/sidebar_container.h b/chrome/browser/sidebar/sidebar_container.h
index b519de8..6b1bbed 100644
--- a/chrome/browser/sidebar/sidebar_container.h
+++ b/chrome/browser/sidebar/sidebar_container.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,6 +10,7 @@
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 
 class BrowserWindow;
@@ -25,7 +26,8 @@
 //  tab it is linked to, mini tab icon, title etc.
 //
 class SidebarContainer
-    : public TabContentsDelegate {
+    : public TabContentsDelegate,
+      private ImageLoadingTracker::Observer {
  public:
   // Interface to implement to listen for sidebar update notification.
   class Delegate {
@@ -37,7 +39,8 @@
     DISALLOW_COPY_AND_ASSIGN(Delegate);
   };
 
-  SidebarContainer(TabContents* tab, const std::string& content_id,
+  SidebarContainer(TabContents* tab,
+                   const std::string& content_id,
                    Delegate* delegate);
   virtual ~SidebarContainer();
 
@@ -45,6 +48,9 @@
   // Does all the necessary cleanup.
   void SidebarClosing();
 
+  // Sets default sidebar parameters, as specified in extension manifest.
+  void LoadDefaults();
+
   // Returns sidebar's content id.
   const std::string& content_id() const { return content_id_; }
 
@@ -106,10 +112,17 @@
   virtual void CloseContents(TabContents* source) {}
   virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
   virtual bool IsPopup(const TabContents* source) const;
-  virtual void URLStarredChanged(TabContents* source, bool starred) {}
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
 
+  // Overridden from ImageLoadingTracker::Observer.
+  virtual void OnImageLoaded(SkBitmap* image,
+                             ExtensionResource resource,
+                             int index);
+
+  // Returns an extension this sidebar belongs to.
+  const Extension* GetExtension() const;
+
   // Contents of the tab this sidebar is linked to.
   TabContents* tab_;
 
@@ -132,6 +145,20 @@
   // Sidebar's title, displayed as a tooltip for sidebar's mini tab.
   string16 title_;
 
+  // On the first expand sidebar will be automatically navigated to the default
+  // page (specified in the extension manifest), but only if the extension has
+  // not explicitly navigated it yet. This variable is set to false on the first
+  // sidebar navigation.
+  bool navigate_to_default_page_on_expand_;
+  // Since the default icon (specified in the extension manifest) is loaded
+  // asynchronously, sidebar icon can already be set by the extension
+  // by the time it's loaded. This variable tracks whether the loaded default
+  // icon should be used or discarded.
+  bool use_default_icon_;
+
+  // Helper to load icons from extension asynchronously.
+  scoped_ptr<ImageLoadingTracker> image_loading_tracker_;
+
   DISALLOW_COPY_AND_ASSIGN(SidebarContainer);
 };
 
diff --git a/chrome/browser/sidebar/sidebar_manager.cc b/chrome/browser/sidebar/sidebar_manager.cc
index 9793224..27d7e33 100644
--- a/chrome/browser/sidebar/sidebar_manager.cc
+++ b/chrome/browser/sidebar/sidebar_manager.cc
@@ -9,13 +9,11 @@
 #include "base/command_line.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_sidebar_api.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/sidebar/sidebar_container.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
 
 struct SidebarManager::SidebarStateForTab {
@@ -109,6 +107,9 @@
   if (!host) {
     host = new SidebarContainer(tab, content_id, this);
     RegisterSidebarContainerFor(tab, host);
+    // It might trigger UpdateSidebar notification, so load them after
+    // the registration.
+    host->LoadDefaults();
   }
 
   host->Show();
diff --git a/chrome/browser/sidebar/sidebar_manager.h b/chrome/browser/sidebar/sidebar_manager.h
index 6f2d20b..e1a0080 100644
--- a/chrome/browser/sidebar/sidebar_manager.h
+++ b/chrome/browser/sidebar/sidebar_manager.h
@@ -74,19 +74,23 @@
   void HideSidebar(TabContents* tab, const std::string& content_id);
 
   // Navigates sidebar identified by |tab| and |content_id| to |url|.
-  void NavigateSidebar(TabContents* tab, const std::string& content_id,
+  void NavigateSidebar(TabContents* tab,
+                       const std::string& content_id,
                        const GURL& url);
 
   // Changes sidebar's badge text (displayed on the mini tab).
-  void SetSidebarBadgeText(TabContents* tab, const std::string& content_id,
+  void SetSidebarBadgeText(TabContents* tab,
+                           const std::string& content_id,
                            const string16& badge_text);
 
   // Changes sidebar's icon (displayed on the mini tab).
-  void SetSidebarIcon(TabContents* tab, const std::string& content_id,
+  void SetSidebarIcon(TabContents* tab,
+                      const std::string& content_id,
                       const SkBitmap& bitmap);
 
   // Changes sidebar's title (mini tab's tooltip).
-  void SetSidebarTitle(TabContents* tab, const std::string& content_id,
+  void SetSidebarTitle(TabContents* tab,
+                       const std::string& content_id,
                        const string16& title);
 
  private:
diff --git a/chrome/browser/sidebar/sidebar_test.cc b/chrome/browser/sidebar/sidebar_test.cc
deleted file mode 100644
index e567791..0000000
--- a/chrome/browser/sidebar/sidebar_test.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/sidebar/sidebar_manager.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/in_process_browser_test.h"
-#include "chrome/test/ui_test_utils.h"
-#include "net/test/test_server.h"
-
-namespace {
-
-const char kSampleContentId[] = "sample_content_id";
-const char kSimplePage[] = "files/sidebar/simple_page.html";
-
-class SidebarTest : public InProcessBrowserTest {
- public:
-  SidebarTest() {
-    CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableExperimentalExtensionApis);
-    set_show_window(true);
-  }
-
- protected:
-  void ShowSidebarForCurrentTab() {
-    ShowSidebar(browser()->GetSelectedTabContents());
-  }
-
-  void ExpandSidebarForCurrentTab() {
-    ExpandSidebar(browser()->GetSelectedTabContents());
-  }
-
-  void CollapseSidebarForCurrentTab() {
-    CollapseSidebar(browser()->GetSelectedTabContents());
-  }
-
-  void HideSidebarForCurrentTab() {
-    HideSidebar(browser()->GetSelectedTabContents());
-  }
-
-  void NavigateSidebarForCurrentTabTo(const std::string& test_page) {
-    GURL url = test_server()->GetURL(test_page);
-
-    TabContents* tab = browser()->GetSelectedTabContents();
-
-    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
-
-    sidebar_manager->NavigateSidebar(tab, kSampleContentId, url);
-
-    SidebarContainer* sidebar_container =
-        sidebar_manager->GetSidebarContainerFor(tab, kSampleContentId);
-
-    TabContents* client_contents = sidebar_container->sidebar_contents();
-    ui_test_utils::WaitForNavigation(&client_contents->controller());
-  }
-
-  void ShowSidebar(TabContents* tab) {
-    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
-    sidebar_manager->ShowSidebar(tab, kSampleContentId);
-  }
-
-  void ExpandSidebar(TabContents* tab) {
-    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
-    sidebar_manager->ExpandSidebar(tab, kSampleContentId);
-    if (browser()->GetSelectedTabContents() == tab)
-      EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
-  }
-
-  void CollapseSidebar(TabContents* tab) {
-    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
-    sidebar_manager->CollapseSidebar(tab, kSampleContentId);
-    if (browser()->GetSelectedTabContents() == tab)
-      EXPECT_EQ(0, browser_view()->GetSidebarWidth());
-  }
-
-  void HideSidebar(TabContents* tab) {
-    SidebarManager* sidebar_manager = SidebarManager::GetInstance();
-    sidebar_manager->HideSidebar(tab, kSampleContentId);
-    if (browser()->GetSelectedTabContents() == tab)
-      EXPECT_EQ(0, browser_view()->GetSidebarWidth());
-  }
-
-  TabContents* tab_contents(int i) {
-    return browser()->GetTabContentsAt(i);
-  }
-
-  BrowserView* browser_view() const {
-    return static_cast<BrowserView*>(browser()->window());
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(SidebarTest, OpenClose) {
-  ShowSidebarForCurrentTab();
-
-  ExpandSidebarForCurrentTab();
-  CollapseSidebarForCurrentTab();
-
-  ExpandSidebarForCurrentTab();
-  CollapseSidebarForCurrentTab();
-
-  ExpandSidebarForCurrentTab();
-  CollapseSidebarForCurrentTab();
-
-  HideSidebarForCurrentTab();
-
-  ShowSidebarForCurrentTab();
-
-  ExpandSidebarForCurrentTab();
-  CollapseSidebarForCurrentTab();
-
-  HideSidebarForCurrentTab();
-}
-
-IN_PROC_BROWSER_TEST_F(SidebarTest, SwitchingTabs) {
-  ShowSidebarForCurrentTab();
-  ExpandSidebarForCurrentTab();
-
-  browser()->NewTab();
-
-  // Make sure sidebar is not visbile for the newly opened tab.
-  EXPECT_EQ(0, browser_view()->GetSidebarWidth());
-
-  // Switch back to the first tab.
-  browser()->SelectNumberedTab(0);
-
-  // Make sure it is visible now.
-  EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
-
-  HideSidebarForCurrentTab();
-}
-
-IN_PROC_BROWSER_TEST_F(SidebarTest, SidebarOnInactiveTab) {
-  ShowSidebarForCurrentTab();
-  ExpandSidebarForCurrentTab();
-
-  browser()->NewTab();
-
-  // Hide sidebar on inactive (first) tab.
-  HideSidebar(tab_contents(0));
-
-  // Switch back to the first tab.
-  browser()->SelectNumberedTab(0);
-
-  // Make sure sidebar is not visbile anymore.
-  EXPECT_EQ(0, browser_view()->GetSidebarWidth());
-
-  // Show sidebar on inactive (second) tab.
-  ShowSidebar(tab_contents(1));
-  ExpandSidebar(tab_contents(1));
-  // Make sure sidebar is not visible yet.
-  EXPECT_EQ(0, browser_view()->GetSidebarWidth());
-
-  // Switch back to the second tab.
-  browser()->SelectNumberedTab(1);
-  // Make sure sidebar is visible now.
-  EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
-
-  HideSidebarForCurrentTab();
-}
-
-IN_PROC_BROWSER_TEST_F(SidebarTest, SidebarNavigate) {
-  ASSERT_TRUE(test_server()->Start());
-
-  ShowSidebarForCurrentTab();
-
-  NavigateSidebarForCurrentTabTo(kSimplePage);
-
-  HideSidebarForCurrentTab();
-}
-
-}  // namespace
-
diff --git a/chrome/browser/speech/OWNERS b/chrome/browser/speech/OWNERS
new file mode 100644
index 0000000..2ad1bbd
--- /dev/null
+++ b/chrome/browser/speech/OWNERS
@@ -0,0 +1 @@
+satish@chromium.org
diff --git a/chrome/browser/speech/audio_encoder.cc b/chrome/browser/speech/audio_encoder.cc
new file mode 100644
index 0000000..fe48639
--- /dev/null
+++ b/chrome/browser/speech/audio_encoder.cc
@@ -0,0 +1,206 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/speech/audio_encoder.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
+#include "base/string_number_conversions.h"
+#include "third_party/flac/flac.h"
+#include "third_party/speex/speex.h"
+
+using std::string;
+
+namespace {
+
+//-------------------------------- FLACEncoder ---------------------------------
+
+const char* const kContentTypeFLAC = "audio/x-flac; rate=";
+const int kFLACCompressionLevel = 0;  // 0 for speed
+
+class FLACEncoder : public speech_input::AudioEncoder {
+ public:
+  FLACEncoder(int sampling_rate, int bits_per_sample);
+  virtual ~FLACEncoder();
+  virtual void Encode(const short* samples, int num_samples);
+  virtual void Flush();
+
+ private:
+  static FLAC__StreamEncoderWriteStatus WriteCallback(
+      const FLAC__StreamEncoder* encoder,
+      const FLAC__byte buffer[],
+      size_t bytes,
+      unsigned samples,
+      unsigned current_frame,
+      void* client_data);
+
+  FLAC__StreamEncoder* encoder_;
+  bool is_encoder_initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(FLACEncoder);
+};
+
+FLAC__StreamEncoderWriteStatus FLACEncoder::WriteCallback(
+    const FLAC__StreamEncoder* encoder,
+    const FLAC__byte buffer[],
+    size_t bytes,
+    unsigned samples,
+    unsigned current_frame,
+    void* client_data) {
+  FLACEncoder* me = static_cast<FLACEncoder*>(client_data);
+  DCHECK(me->encoder_ == encoder);
+  me->AppendToBuffer(new string(reinterpret_cast<const char*>(buffer), bytes));
+  return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+}
+
+FLACEncoder::FLACEncoder(int sampling_rate, int bits_per_sample)
+    : AudioEncoder(std::string(kContentTypeFLAC) +
+                   base::IntToString(sampling_rate)),
+      encoder_(FLAC__stream_encoder_new()),
+      is_encoder_initialized_(false) {
+  FLAC__stream_encoder_set_channels(encoder_, 1);
+  FLAC__stream_encoder_set_bits_per_sample(encoder_, bits_per_sample);
+  FLAC__stream_encoder_set_sample_rate(encoder_, sampling_rate);
+  FLAC__stream_encoder_set_compression_level(encoder_, kFLACCompressionLevel);
+
+  // Initializing the encoder will cause sync bytes to be written to
+  // its output stream, so we wait until the first call to this method
+  // before doing so.
+}
+
+FLACEncoder::~FLACEncoder() {
+  FLAC__stream_encoder_delete(encoder_);
+}
+
+void FLACEncoder::Encode(const short* samples, int num_samples) {
+  if (!is_encoder_initialized_) {
+    const FLAC__StreamEncoderInitStatus encoder_status =
+        FLAC__stream_encoder_init_stream(encoder_, WriteCallback, NULL, NULL,
+                                         NULL, this);
+    DCHECK(encoder_status == FLAC__STREAM_ENCODER_INIT_STATUS_OK);
+    is_encoder_initialized_ = true;
+  }
+
+  // FLAC encoder wants samples as int32s.
+  scoped_ptr<FLAC__int32> flac_samples(new FLAC__int32[num_samples]);
+  FLAC__int32* flac_samples_ptr = flac_samples.get();
+  for (int i = 0; i < num_samples; ++i)
+    flac_samples_ptr[i] = samples[i];
+
+  FLAC__stream_encoder_process(encoder_, &flac_samples_ptr, num_samples);
+}
+
+void FLACEncoder::Flush() {
+  FLAC__stream_encoder_finish(encoder_);
+}
+
+//-------------------------------- SpeexEncoder --------------------------------
+
+const char* const kContentTypeSpeex = "audio/x-speex-with-header-byte; rate=";
+const int kSpeexEncodingQuality = 8;
+const int kMaxSpeexFrameLength = 110;  // (44kbps rate sampled at 32kHz).
+
+// Since the frame length gets written out as a byte in the encoded packet,
+// make sure it is within the byte range.
+COMPILE_ASSERT(kMaxSpeexFrameLength <= 0xFF, invalidLength);
+
+class SpeexEncoder : public speech_input::AudioEncoder {
+ public:
+  explicit SpeexEncoder(int sampling_rate);
+  virtual ~SpeexEncoder();
+  virtual void Encode(const short* samples, int num_samples);
+  virtual void Flush() {}
+
+ private:
+  void* encoder_state_;
+  SpeexBits bits_;
+  int samples_per_frame_;
+  char encoded_frame_data_[kMaxSpeexFrameLength + 1];  // +1 for the frame size.
+  DISALLOW_COPY_AND_ASSIGN(SpeexEncoder);
+};
+
+SpeexEncoder::SpeexEncoder(int sampling_rate)
+    : AudioEncoder(std::string(kContentTypeSpeex) +
+                   base::IntToString(sampling_rate)) {
+   // speex_bits_init() does not initialize all of the |bits_| struct.
+   memset(&bits_, 0, sizeof(bits_));
+   speex_bits_init(&bits_);
+   encoder_state_ = speex_encoder_init(&speex_wb_mode);
+   DCHECK(encoder_state_);
+   speex_encoder_ctl(encoder_state_, SPEEX_GET_FRAME_SIZE, &samples_per_frame_);
+   DCHECK(samples_per_frame_ > 0);
+   int quality = kSpeexEncodingQuality;
+   speex_encoder_ctl(encoder_state_, SPEEX_SET_QUALITY, &quality);
+   int vbr = 1;
+   speex_encoder_ctl(encoder_state_, SPEEX_SET_VBR, &vbr);
+   memset(encoded_frame_data_, 0, sizeof(encoded_frame_data_));
+}
+
+SpeexEncoder::~SpeexEncoder() {
+  speex_bits_destroy(&bits_);
+  speex_encoder_destroy(encoder_state_);
+}
+
+void SpeexEncoder::Encode(const short* samples, int num_samples) {
+  // Drop incomplete frames, typically those which come in when recording stops.
+  num_samples -= (num_samples % samples_per_frame_);
+  for (int i = 0; i < num_samples; i += samples_per_frame_) {
+    speex_bits_reset(&bits_);
+    speex_encode_int(encoder_state_, const_cast<spx_int16_t*>(samples + i),
+                     &bits_);
+
+    // Encode the frame and place the size of the frame as the first byte. This
+    // is the packet format for MIME type x-speex-with-header-byte.
+    int frame_length = speex_bits_write(&bits_, encoded_frame_data_ + 1,
+                                        kMaxSpeexFrameLength);
+    encoded_frame_data_[0] = static_cast<char>(frame_length);
+    AppendToBuffer(new string(encoded_frame_data_, frame_length + 1));
+  }
+}
+
+}  // namespace
+
+namespace speech_input {
+
+AudioEncoder* AudioEncoder::Create(Codec codec,
+                                   int sampling_rate,
+                                   int bits_per_sample) {
+  if (codec == CODEC_FLAC)
+    return new FLACEncoder(sampling_rate, bits_per_sample);
+  return new SpeexEncoder(sampling_rate);
+}
+
+AudioEncoder::AudioEncoder(const std::string& mime_type)
+    : mime_type_(mime_type) {
+}
+
+AudioEncoder::~AudioEncoder() {
+  STLDeleteElements(&audio_buffers_);
+}
+
+bool AudioEncoder::GetEncodedData(std::string* encoded_data) {
+  if (!audio_buffers_.size())
+    return false;
+
+  int audio_buffer_length = 0;
+  for (AudioBufferQueue::iterator it = audio_buffers_.begin();
+       it != audio_buffers_.end(); ++it) {
+    audio_buffer_length += (*it)->length();
+  }
+  encoded_data->reserve(audio_buffer_length);
+  for (AudioBufferQueue::iterator it = audio_buffers_.begin();
+       it != audio_buffers_.end(); ++it) {
+    encoded_data->append(*(*it));
+  }
+
+  return true;
+}
+
+void AudioEncoder::AppendToBuffer(std::string* item) {
+  audio_buffers_.push_back(item);
+}
+
+}  // namespace speech_input
diff --git a/chrome/browser/speech/audio_encoder.h b/chrome/browser/speech/audio_encoder.h
new file mode 100644
index 0000000..e17a413
--- /dev/null
+++ b/chrome/browser/speech/audio_encoder.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SPEECH_AUDIO_ENCODER_H_
+#define CHROME_BROWSER_SPEECH_AUDIO_ENCODER_H_
+
+#include <list>
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace speech_input {
+
+// Provides a simple interface to encode raw audio using the various speech
+// codecs.
+class AudioEncoder {
+ public:
+  enum Codec {
+    CODEC_FLAC,
+    CODEC_SPEEX,
+  };
+
+  static AudioEncoder* Create(Codec codec,
+                              int sampling_rate,
+                              int bits_per_sample);
+
+  virtual ~AudioEncoder();
+
+  // Encodes each frame of raw audio in |samples| to the internal buffer. Use
+  // |GetEncodedData| to read the result after this call or when recording
+  // completes.
+  virtual void Encode(const short* samples, int num_samples) = 0;
+
+  // Finish encoding and flush any pending encoded bits out.
+  virtual void Flush() = 0;
+
+  // Copies the encoded audio to the given string. Returns true if the output
+  // is not empty.
+  bool GetEncodedData(std::string* encoded_data);
+
+  const std::string& mime_type() { return mime_type_; }
+
+ protected:
+  AudioEncoder(const std::string& mime_type);
+
+  void AppendToBuffer(std::string* item);
+
+ private:
+  // Buffer holding the recorded audio. Owns the strings inside the list.
+  typedef std::list<std::string*> AudioBufferQueue;
+  AudioBufferQueue audio_buffers_;
+  std::string mime_type_;
+  DISALLOW_COPY_AND_ASSIGN(AudioEncoder);
+};
+
+}  // namespace speech_input
+
+#endif  // CHROME_BROWSER_SPEECH_AUDIO_ENCODER_H_
diff --git a/chrome/browser/speech/speech_input_browsertest.cc b/chrome/browser/speech/speech_input_browsertest.cc
index 05dd4f6..0b8c904 100644
--- a/chrome/browser/speech/speech_input_browsertest.cc
+++ b/chrome/browser/speech/speech_input_browsertest.cc
@@ -14,7 +14,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 
 namespace speech_input {
 class FakeSpeechInputManager;
@@ -42,13 +42,14 @@
   }
 
   // SpeechInputManager methods.
-  void StartRecognition(Delegate* delegate,
-                        int caller_id,
-                        int render_process_id,
-                        int render_view_id,
-                        const gfx::Rect& element_rect,
-                        const std::string& language,
-                        const std::string& grammar) {
+  virtual void StartRecognition(Delegate* delegate,
+                                int caller_id,
+                                int render_process_id,
+                                int render_view_id,
+                                const gfx::Rect& element_rect,
+                                const std::string& language,
+                                const std::string& grammar,
+                                const std::string& origin_url) {
     VLOG(1) << "StartRecognition invoked.";
     EXPECT_EQ(0, caller_id_);
     EXPECT_EQ(NULL, delegate_);
@@ -59,17 +60,20 @@
     MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
         &FakeSpeechInputManager::SetFakeRecognitionResult));
   }
-  void CancelRecognition(int caller_id) {
+  virtual void CancelRecognition(int caller_id) {
     VLOG(1) << "CancelRecognition invoked.";
     EXPECT_EQ(caller_id_, caller_id);
     caller_id_ = 0;
     delegate_ = NULL;
   }
-  void StopRecording(int caller_id) {
+  virtual void StopRecording(int caller_id) {
     VLOG(1) << "StopRecording invoked.";
     EXPECT_EQ(caller_id_, caller_id);
     // Nothing to do here since we aren't really recording.
   }
+  virtual void CancelAllRequestsWithDelegate(Delegate* delegate) {
+    VLOG(1) << "CancelAllRequestsWithDelegate invoked.";
+  }
 
  private:
   void SetFakeRecognitionResult() {
@@ -166,7 +170,16 @@
 // check for sending many clicks in succession to the speech button and verify
 // that it doesn't cause any crash but works as expected. This should act as the
 // test for http://crbug.com/59173
-#if defined(OS_WIN)
+//
+// TODO(satish): Similar to above, once this flakiness has been fixed add
+// another test here to check that when speech recognition is in progress and
+// a renderer crashes, we get a call to
+// SpeechInputManager::CancelAllRequestsWithDelegate.
+//
+// Marked as DISABLED due to http://crbug.com/71227
+#if defined(GOOGLE_CHROME_BUILD)
+#define MAYBE_TestBasicRecognition DISABLED_TestBasicRecognition
+#elif defined(OS_WIN)
 #define MAYBE_TestBasicRecognition FLAKY_TestBasicRecognition
 #else
 #define MAYBE_TestBasicRecognition TestBasicRecognition
@@ -177,7 +190,10 @@
 }
 
 // Marked as FLAKY due to http://crbug.com/51337
-#if defined(OS_WIN)
+// Marked as DISALBED due to http://crbug.com/71227
+#if defined(GOOGLE_CHROME_BUILD)
+#define MAYBE_GrammarAttribute DISABLED_GrammarAttribute
+#elif defined(OS_WIN)
 #define MAYBE_GrammarAttribute FLAKY_GrammarAttribute
 #else
 #define MAYBE_GrammarAttribute GrammarAttribute
@@ -188,4 +204,4 @@
             fake_speech_input_manager_.grammar());
 }
 
-} //  namespace speech_input
+}  // namespace speech_input
diff --git a/chrome/browser/speech/speech_input_bubble.cc b/chrome/browser/speech/speech_input_bubble.cc
index 77619e9..59cfd45 100644
--- a/chrome/browser/speech/speech_input_bubble.cc
+++ b/chrome/browser/speech/speech_input_bubble.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/speech/speech_input_bubble.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/rect.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/rect.h"
 
 SpeechInputBubble::FactoryMethod SpeechInputBubble::factory_ = NULL;
 const int SpeechInputBubble::kBubbleTargetOffsetX = 5;
@@ -149,3 +149,7 @@
 
   SetImage(*mic_image_.get());
 }
+
+TabContents* SpeechInputBubbleBase::tab_contents() {
+  return tab_contents_;
+}
diff --git a/chrome/browser/speech/speech_input_bubble.h b/chrome/browser/speech/speech_input_bubble.h
index 436e6bb..dd5d21b 100644
--- a/chrome/browser/speech/speech_input_bubble.h
+++ b/chrome/browser/speech/speech_input_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -130,7 +130,7 @@
   virtual void SetRecognizingMode();
   virtual void SetMessage(const string16& text);
   virtual void SetInputVolume(float volume);
-  virtual TabContents* tab_contents() { return tab_contents_; }
+  virtual TabContents* tab_contents();
 
  protected:
   // Updates the platform specific UI layout for the current display mode.
diff --git a/chrome/browser/speech/speech_input_bubble_browsertest.cc b/chrome/browser/speech/speech_input_bubble_browsertest.cc
index c5e98b8..0b3232f 100644
--- a/chrome/browser/speech/speech_input_bubble_browsertest.cc
+++ b/chrome/browser/speech/speech_input_bubble_browsertest.cc
@@ -6,8 +6,8 @@
 #include "chrome/browser/speech/speech_input_bubble.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/in_process_browser_test.h"
-#include "gfx/rect.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/rect.h"
 
 class SpeechInputBubbleTest : public SpeechInputBubbleDelegate,
                               public InProcessBrowserTest {
diff --git a/chrome/browser/speech/speech_input_bubble_controller.cc b/chrome/browser/speech/speech_input_bubble_controller.cc
index b048589..2dd9a8b 100644
--- a/chrome/browser/speech/speech_input_bubble_controller.cc
+++ b/chrome/browser/speech/speech_input_bubble_controller.cc
@@ -10,7 +10,7 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 namespace speech_input {
 
@@ -201,7 +201,6 @@
 
   int old_bubble_caller_id = current_bubble_caller_id_;
   current_bubble_caller_id_ = 0;
-  bubbles_[old_bubble_caller_id]->Hide();
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
diff --git a/chrome/browser/speech/speech_input_bubble_controller_unittest.cc b/chrome/browser/speech/speech_input_bubble_controller_unittest.cc
index e0ca5ba..612326e 100644
--- a/chrome/browser/speech/speech_input_bubble_controller_unittest.cc
+++ b/chrome/browser/speech/speech_input_bubble_controller_unittest.cc
@@ -5,10 +5,11 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/speech/speech_input_bubble_controller.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/testing_profile.h"
-#include "gfx/rect.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/rect.h"
 
 class SkBitmap;
 
diff --git a/chrome/browser/speech/speech_input_bubble_gtk.cc b/chrome/browser/speech/speech_input_bubble_gtk.cc
index eb8b906..86cd28b 100644
--- a/chrome/browser/speech/speech_input_bubble_gtk.cc
+++ b/chrome/browser/speech/speech_input_bubble_gtk.cc
@@ -1,21 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/speech/speech_input_bubble.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/info_bubble_gtk.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "gfx/gtk_util.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/rect.h"
 
 namespace {
 
@@ -196,7 +196,7 @@
 }
 
 void SpeechInputBubbleGtk::SetImage(const SkBitmap& image) {
-  if (image.isNull())
+  if (image.isNull() || !info_bubble_)
     return;
 
   GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&image);
diff --git a/chrome/browser/speech/speech_input_bubble_views.cc b/chrome/browser/speech/speech_input_bubble_views.cc
index 2140ef4..9b33685 100644
--- a/chrome/browser/speech/speech_input_bubble_views.cc
+++ b/chrome/browser/speech/speech_input_bubble_views.cc
@@ -1,25 +1,24 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/speech/speech_input_bubble.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/info_bubble.h"
-#include "gfx/canvas.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/view.h"
 
 namespace {
@@ -130,7 +129,7 @@
   int width = heading_->GetPreferredSize().width();
   int control_width = cancel_->GetPreferredSize().width() +
                       try_again_->GetPreferredSize().width() +
-                      kRelatedButtonHSpacing;
+                      views::kRelatedButtonHSpacing;
   if (control_width > width)
     width = control_width;
   control_width = icon_->GetPreferredSize().width();
@@ -165,9 +164,9 @@
     int cancel_width = cancel_->GetPreferredSize().width();
     y += available_height - height;
     x += (available_width - cancel_width - try_again_width -
-          kRelatedButtonHSpacing) / 2;
+          views::kRelatedButtonHSpacing) / 2;
     try_again_->SetBounds(x, y, try_again_width, height);
-    cancel_->SetBounds(x + try_again_width + kRelatedButtonHSpacing, y,
+    cancel_->SetBounds(x + try_again_width + views::kRelatedButtonHSpacing, y,
                        cancel_width, height);
 
     height = message_->GetHeightForWidth(available_width);
diff --git a/chrome/browser/speech/speech_input_dispatcher_host.cc b/chrome/browser/speech/speech_input_dispatcher_host.cc
index 50b9aec..dc993d5 100644
--- a/chrome/browser/speech/speech_input_dispatcher_host.cc
+++ b/chrome/browser/speech/speech_input_dispatcher_host.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/speech/speech_input_dispatcher_host.h"
 
 #include "base/lazy_instance.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/common/speech_input_messages.h"
 
 namespace speech_input {
 
@@ -105,13 +105,21 @@
     SpeechInputDispatcherHost::manager_accessor_ = &SpeechInputManager::Get;
 
 SpeechInputDispatcherHost::SpeechInputDispatcherHost(int render_process_id)
-    : render_process_id_(render_process_id) {
+    : render_process_id_(render_process_id),
+      may_have_pending_requests_(false) {
   // This is initialized by Browser. Do not add any non-trivial
   // initialization here, instead do it lazily when required (e.g. see the
   // method |manager()|) or add an Init() method.
 }
 
 SpeechInputDispatcherHost::~SpeechInputDispatcherHost() {
+  // If the renderer crashed for some reason or if we didn't receive a proper
+  // Cancel/Stop call for an existing session, cancel such active sessions now.
+  // We first check if this dispatcher received any speech IPC requst so that
+  // we don't end up creating the speech input manager for web pages which don't
+  // use speech input.
+  if (may_have_pending_requests_)
+    manager()->CancelAllRequestsWithDelegate(this);
 }
 
 SpeechInputManager* SpeechInputDispatcherHost::manager() {
@@ -123,21 +131,22 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   uint32 message_type = message.type();
-  if (message_type == ViewHostMsg_SpeechInput_StartRecognition::ID ||
-      message_type == ViewHostMsg_SpeechInput_CancelRecognition::ID ||
-      message_type == ViewHostMsg_SpeechInput_StopRecording::ID) {
+  if (message_type == SpeechInputHostMsg_StartRecognition::ID ||
+      message_type == SpeechInputHostMsg_CancelRecognition::ID ||
+      message_type == SpeechInputHostMsg_StopRecording::ID) {
     if (!SpeechInputManager::IsFeatureEnabled()) {
       *message_was_ok = false;
       return true;
     }
 
+    may_have_pending_requests_ = true;
     IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, message,
                              *message_was_ok)
-      IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StartRecognition,
+      IPC_MESSAGE_HANDLER(SpeechInputHostMsg_StartRecognition,
                           OnStartRecognition)
-      IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_CancelRecognition,
+      IPC_MESSAGE_HANDLER(SpeechInputHostMsg_CancelRecognition,
                           OnCancelRecognition)
-      IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StopRecording,
+      IPC_MESSAGE_HANDLER(SpeechInputHostMsg_StopRecording,
                           OnStopRecording)
     IPC_END_MESSAGE_MAP()
     return true;
@@ -147,17 +156,14 @@
 }
 
 void SpeechInputDispatcherHost::OnStartRecognition(
-    int render_view_id,
-    int request_id,
-    const gfx::Rect& element_rect,
-    const std::string& language,
-    const std::string& grammar) {
+    const SpeechInputHostMsg_StartRecognition_Params &params) {
   int caller_id = g_speech_input_callers.Get().CreateId(
-      render_process_id_, render_view_id, request_id);
+      render_process_id_, params.render_view_id, params.request_id);
   manager()->StartRecognition(this, caller_id,
                               render_process_id_,
-                              render_view_id, element_rect,
-                              language, grammar);
+                              params.render_view_id, params.element_rect,
+                              params.language, params.grammar,
+                              params.origin_url);
 }
 
 void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id,
@@ -186,9 +192,9 @@
   int caller_render_view_id =
       g_speech_input_callers.Get().render_view_id(caller_id);
   int caller_request_id = g_speech_input_callers.Get().request_id(caller_id);
-  Send(new ViewMsg_SpeechInput_SetRecognitionResult(caller_render_view_id,
-                                                    caller_request_id,
-                                                    result));
+  Send(new SpeechInputMsg_SetRecognitionResult(caller_render_view_id,
+                                               caller_request_id,
+                                               result));
   VLOG(1) << "SpeechInputDispatcherHost::SetRecognitionResult exit";
 }
 
@@ -198,8 +204,8 @@
   int caller_render_view_id =
     g_speech_input_callers.Get().render_view_id(caller_id);
   int caller_request_id = g_speech_input_callers.Get().request_id(caller_id);
-  Send(new ViewMsg_SpeechInput_RecordingComplete(caller_render_view_id,
-                                                 caller_request_id));
+  Send(new SpeechInputMsg_RecordingComplete(caller_render_view_id,
+                                            caller_request_id));
   VLOG(1) << "SpeechInputDispatcherHost::DidCompleteRecording exit";
 }
 
@@ -209,8 +215,8 @@
   int caller_render_view_id =
     g_speech_input_callers.Get().render_view_id(caller_id);
   int caller_request_id = g_speech_input_callers.Get().request_id(caller_id);
-  Send(new ViewMsg_SpeechInput_RecognitionComplete(caller_render_view_id,
-                                                   caller_request_id));
+  Send(new SpeechInputMsg_RecognitionComplete(caller_render_view_id,
+                                              caller_request_id));
   // Request sequence ended, so remove mapping.
   g_speech_input_callers.Get().RemoveId(caller_id);
   VLOG(1) << "SpeechInputDispatcherHost::DidCompleteRecognition exit";
diff --git a/chrome/browser/speech/speech_input_dispatcher_host.h b/chrome/browser/speech/speech_input_dispatcher_host.h
index 51ae04c..23a1f23 100644
--- a/chrome/browser/speech/speech_input_dispatcher_host.h
+++ b/chrome/browser/speech/speech_input_dispatcher_host.h
@@ -9,6 +9,8 @@
 #include "chrome/browser/browser_message_filter.h"
 #include "chrome/browser/speech/speech_input_manager.h"
 
+struct SpeechInputHostMsg_StartRecognition_Params;
+
 namespace speech_input {
 
 // SpeechInputDispatcherHost is a delegate for Speech API messages used by
@@ -39,10 +41,8 @@
  private:
   virtual ~SpeechInputDispatcherHost();
 
-  void OnStartRecognition(int render_view_id, int request_id,
-                          const gfx::Rect& element_rect,
-                          const std::string& language,
-                          const std::string& grammar);
+  void OnStartRecognition(
+      const SpeechInputHostMsg_StartRecognition_Params &params);
   void OnCancelRecognition(int render_view_id, int request_id);
   void OnStopRecording(int render_view_id, int request_id);
 
@@ -51,6 +51,7 @@
   SpeechInputManager* manager();
 
   int render_process_id_;
+  bool may_have_pending_requests_;  // Set if we received any speech IPC request
 
   static SpeechInputManager::AccessorMethod* manager_accessor_;
 
diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc
index 25f0550..7a07543 100644
--- a/chrome/browser/speech/speech_input_manager.cc
+++ b/chrome/browser/speech/speech_input_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,46 +7,48 @@
 #include <map>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/speech/speech_input_bubble_controller.h"
 #include "chrome/browser/speech/speech_recognizer.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "media/audio/audio_manager.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/browser_process.h"
 #include "chrome/installer/util/wmi.h"
 #endif
 
+namespace speech_input {
+
 namespace {
 
-// Asynchronously fetches the PC and audio hardware/driver info on windows if
+// Asynchronously fetches the PC and audio hardware/driver info if
 // the user has opted into UMA. This information is sent with speech input
 // requests to the server for identifying and improving quality issues with
 // specific device configurations.
-class HardwareInfo : public base::RefCountedThreadSafe<HardwareInfo> {
+class OptionalRequestInfo
+    : public base::RefCountedThreadSafe<OptionalRequestInfo> {
  public:
-  HardwareInfo() {}
+  OptionalRequestInfo() : can_report_metrics_(false) {}
 
-#if defined(OS_WIN)
   void Refresh() {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     // UMA opt-in can be checked only from the UI thread, so switch to that.
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        NewRunnableMethod(this, &HardwareInfo::CheckUMAAndGetHardwareInfo));
+        NewRunnableMethod(this,
+                          &OptionalRequestInfo::CheckUMAAndGetHardwareInfo));
   }
 
   void CheckUMAAndGetHardwareInfo() {
@@ -55,39 +57,42 @@
         prefs::kMetricsReportingEnabled)) {
       // Access potentially slow OS calls from the FILE thread.
       BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-          NewRunnableMethod(this, &HardwareInfo::GetHardwareInfo));
+          NewRunnableMethod(this, &OptionalRequestInfo::GetHardwareInfo));
     }
   }
 
   void GetHardwareInfo() {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
+    can_report_metrics_ = true;
+#if defined(OS_WIN)
     value_ = UTF16ToUTF8(
         installer::WMIComputerSystem::GetModel() + L"|" +
         AudioManager::GetAudioManager()->GetAudioInputDeviceModel());
+#else  // defined(OS_WIN)
+    value_ = UTF16ToUTF8(
+        AudioManager::GetAudioManager()->GetAudioInputDeviceModel());
+#endif  // defined(OS_WIN)
   }
 
   std::string value() {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     return value_;
   }
 
+  bool can_report_metrics() {
+    base::AutoLock lock(lock_);
+    return can_report_metrics_;
+  }
+
  private:
-  Lock lock_;
+  base::Lock lock_;
   std::string value_;
+  bool can_report_metrics_;
 
-#else  // defined(OS_WIN)
-  void Refresh() {}
-  std::string value() { return std::string(); }
-#endif  // defined(OS_WIN)
-
-  DISALLOW_COPY_AND_ASSIGN(HardwareInfo);
+  DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo);
 };
 
-}  // namespace
-
-namespace speech_input {
-
 class SpeechInputManagerImpl : public SpeechInputManager,
                                public SpeechInputBubbleControllerDelegate,
                                public SpeechRecognizerDelegate {
@@ -99,9 +104,12 @@
                                 int render_view_id,
                                 const gfx::Rect& element_rect,
                                 const std::string& language,
-                                const std::string& grammar);
+                                const std::string& grammar,
+                                const std::string& origin_url);
   virtual void CancelRecognition(int caller_id);
   virtual void StopRecording(int caller_id);
+  virtual void CancelAllRequestsWithDelegate(
+      SpeechInputManagerDelegate* delegate);
 
   // SpeechRecognizer::Delegate methods.
   virtual void SetRecognitionResult(int caller_id,
@@ -143,12 +151,14 @@
   SpeechRecognizerMap requests_;
   int recording_caller_id_;
   scoped_refptr<SpeechInputBubbleController> bubble_controller_;
-  scoped_refptr<HardwareInfo> hardware_info_;
+  scoped_refptr<OptionalRequestInfo> optional_request_info_;
 };
 
-static ::base::LazyInstance<SpeechInputManagerImpl> g_speech_input_manager_impl(
+base::LazyInstance<SpeechInputManagerImpl> g_speech_input_manager_impl(
     base::LINKER_INITIALIZED);
 
+}  // namespace
+
 SpeechInputManager* SpeechInputManager::Get() {
   return g_speech_input_manager_impl.Pointer();
 }
@@ -200,14 +210,15 @@
     int render_view_id,
     const gfx::Rect& element_rect,
     const std::string& language,
-    const std::string& grammar) {
+    const std::string& grammar,
+    const std::string& origin_url) {
   DCHECK(!HasPendingRequest(caller_id));
 
   bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id,
                                    element_rect);
 
-  if (!hardware_info_.get()) {
-    hardware_info_ = new HardwareInfo();
+  if (!optional_request_info_.get()) {
+    optional_request_info_ = new OptionalRequestInfo();
     // Since hardware info is optional with speech input requests, we start an
     // asynchronous fetch here and move on with recording audio. This first
     // speech input request would send an empty string for hardware info and
@@ -215,13 +226,14 @@
     // completed before them. This way we don't end up stalling the user with
     // a long wait and disk seeks when they click on a UI element and start
     // speaking.
-    hardware_info_->Refresh();
+    optional_request_info_->Refresh();
   }
 
   SpeechInputRequest* request = &requests_[caller_id];
   request->delegate = delegate;
-  request->recognizer = new SpeechRecognizer(this, caller_id, language,
-                                             grammar, hardware_info_->value());
+  request->recognizer = new SpeechRecognizer(
+      this, caller_id, language, grammar, optional_request_info_->value(),
+      optional_request_info_->can_report_metrics() ? origin_url : "");
   request->is_active = false;
 
   StartRecognitionForRequest(caller_id);
@@ -254,6 +266,20 @@
   bubble_controller_->CloseBubble(caller_id);
 }
 
+void SpeechInputManagerImpl::CancelAllRequestsWithDelegate(
+    SpeechInputManagerDelegate* delegate) {
+  SpeechRecognizerMap::iterator it = requests_.begin();
+  while (it != requests_.end()) {
+    if (it->second.delegate == delegate) {
+      CancelRecognition(it->first);
+      // This map will have very few elements so it is simpler to restart.
+      it = requests_.begin();
+    } else {
+      ++it;
+    }
+  }
+}
+
 void SpeechInputManagerImpl::StopRecording(int caller_id) {
   DCHECK(HasPendingRequest(caller_id));
   requests_[caller_id].recognizer->StopRecording();
diff --git a/chrome/browser/speech/speech_input_manager.h b/chrome/browser/speech/speech_input_manager.h
index ffeaba0..3646f4f 100644
--- a/chrome/browser/speech/speech_input_manager.h
+++ b/chrome/browser/speech/speech_input_manager.h
@@ -7,8 +7,8 @@
 
 #include "base/basictypes.h"
 #include "chrome/common/speech_input_result.h"
-#include "gfx/rect.h"
 #include "ipc/ipc_message.h"
+#include "ui/gfx/rect.h"
 
 namespace speech_input {
 
@@ -37,7 +37,7 @@
   static bool IsFeatureEnabled();
 
   // Factory method to access the singleton. We have this method here instead of
-  // using Singleton<> directly in the calling code to aid tests in injection
+  // using Singleton directly in the calling code to aid tests in injection
   // mocks.
   static SpeechInputManager* Get();
   // Factory method definition useful for tests.
@@ -59,9 +59,12 @@
                                 int render_view_id,
                                 const gfx::Rect& element_rect,
                                 const std::string& language,
-                                const std::string& grammar)  = 0;
+                                const std::string& grammar,
+                                const std::string& origin_url)  = 0;
   virtual void CancelRecognition(int caller_id) = 0;
   virtual void StopRecording(int caller_id) = 0;
+
+  virtual void CancelAllRequestsWithDelegate(Delegate* delegate) = 0;
 };
 
 // This typedef is to workaround the issue with certain versions of
diff --git a/chrome/browser/speech/speech_recognition_request.cc b/chrome/browser/speech/speech_recognition_request.cc
index b1234b0..dc8dc27 100644
--- a/chrome/browser/speech/speech_recognition_request.cc
+++ b/chrome/browser/speech/speech_recognition_request.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/json/json_reader.h"
 #include "base/string_util.h"
 #include "base/values.h"
@@ -15,6 +14,7 @@
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -91,7 +91,7 @@
 
     // It is not an error if the 'confidence' field is missing.
     double confidence = 0.0;
-    hypothesis_value->GetReal(kConfidenceString, &confidence);
+    hypothesis_value->GetDouble(kConfidenceString, &confidence);
 
     result->push_back(speech_input::SpeechInputResultItem(utterance,
                                                           confidence));
@@ -123,6 +123,7 @@
 bool SpeechRecognitionRequest::Send(const std::string& language,
                                     const std::string& grammar,
                                     const std::string& hardware_info,
+                                    const std::string& origin_url,
                                     const std::string& content_type,
                                     const std::string& audio_data) {
   DCHECK(!url_fetcher_.get());
@@ -134,7 +135,8 @@
     // If no language is provided then we use the first from the accepted
     // language list. If this list is empty then it defaults to "en-US".
     // Example of the contents of this list: "es,en-GB;q=0.8", ""
-    URLRequestContext* request_context = url_context_->GetURLRequestContext();
+    net::URLRequestContext* request_context =
+        url_context_->GetURLRequestContext();
     DCHECK(request_context);
     std::string accepted_language_list = request_context->accept_language();
     size_t separator = accepted_language_list.find_first_of(",;");
@@ -160,6 +162,7 @@
                                         this));
   url_fetcher_->set_upload_data(content_type, audio_data);
   url_fetcher_->set_request_context(url_context_);
+  url_fetcher_->set_referrer(origin_url);
 
   // The speech recognition API does not require user identification as part
   // of requests, so we don't send cookies or auth data for these requests to
@@ -175,7 +178,7 @@
 void SpeechRecognitionRequest::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
diff --git a/chrome/browser/speech/speech_recognition_request.h b/chrome/browser/speech/speech_recognition_request.h
index c12fc4d..9b022cf 100644
--- a/chrome/browser/speech/speech_recognition_request.h
+++ b/chrome/browser/speech/speech_recognition_request.h
@@ -48,6 +48,7 @@
   bool Send(const std::string& language,
             const std::string& grammar,
             const std::string& hardware_info,
+            const std::string& origin_url,
             const std::string& content_type,
             const std::string& audio_data);
 
diff --git a/chrome/browser/speech/speech_recognition_request_unittest.cc b/chrome/browser/speech/speech_recognition_request_unittest.cc
index 6d1db5f..bd2a26e 100644
--- a/chrome/browser/speech/speech_recognition_request_unittest.cc
+++ b/chrome/browser/speech/speech_recognition_request_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -47,12 +47,12 @@
     bool success, const std::string& http_response) {
   SpeechRecognitionRequest request(NULL, this);
   request.Send(std::string(), std::string(), std::string(), std::string(),
-               std::string());
+               std::string(), std::string());
   TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
-  URLRequestStatus status;
-  status.set_status(success ? URLRequestStatus::SUCCESS :
-                              URLRequestStatus::FAILED);
+  net::URLRequestStatus status;
+  status.set_status(success ? net::URLRequestStatus::SUCCESS :
+                              net::URLRequestStatus::FAILED);
   fetcher->delegate()->OnURLFetchComplete(fetcher, fetcher->original_url(),
                                           status, success ? 200 : 500,
                                           ResponseCookies(),
diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc
index 277393c..113600b 100644
--- a/chrome/browser/speech/speech_recognizer.cc
+++ b/chrome/browser/speech/speech_recognizer.cc
@@ -10,21 +10,11 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/net/url_request_context_getter.h"
-#include "third_party/speex/speex.h"
 
 using media::AudioInputController;
-using std::list;
 using std::string;
 
 namespace {
-const char* const kContentTypeSpeex =
-    "audio/x-speex-with-header-byte; rate=16000";
-const int kSpeexEncodingQuality = 8;
-const int kMaxSpeexFrameLength = 110;  // (44kbps rate sampled at 32kHz).
-
-// Since the frame length gets written out as a byte in the encoded packet,
-// make sure it is within the byte range.
-COMPILE_ASSERT(kMaxSpeexFrameLength <= 0xFF, invalidLength);
 
 // The following constants are related to the volume level indicator shown in
 // the UI for recorded audio.
@@ -45,79 +35,20 @@
 const int SpeechRecognizer::kNoSpeechTimeoutSec = 8;
 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300;
 
-// Provides a simple interface to encode raw audio using the Speex codec.
-class SpeexEncoder {
- public:
-  SpeexEncoder();
-  ~SpeexEncoder();
-
-  int samples_per_frame() const { return samples_per_frame_; }
-
-  // Encodes each frame of raw audio in |samples| and adds the
-  // encoded frames as a set of strings to the |encoded_frames| list.
-  // Ownership of the newly added strings is transferred to the caller.
-  void Encode(const short* samples,
-              int num_samples,
-              std::list<std::string*>* encoded_frames);
-
- private:
-  SpeexBits bits_;
-  void* encoder_state_;
-  int samples_per_frame_;
-  char encoded_frame_data_[kMaxSpeexFrameLength + 1];  // +1 for the frame size.
-};
-
-SpeexEncoder::SpeexEncoder() {
-  // speex_bits_init() does not initialize all of the |bits_| struct.
-  memset(&bits_, 0, sizeof(bits_));
-  speex_bits_init(&bits_);
-  encoder_state_ = speex_encoder_init(&speex_wb_mode);
-  DCHECK(encoder_state_);
-  speex_encoder_ctl(encoder_state_, SPEEX_GET_FRAME_SIZE, &samples_per_frame_);
-  DCHECK(samples_per_frame_ > 0);
-  int quality = kSpeexEncodingQuality;
-  speex_encoder_ctl(encoder_state_, SPEEX_SET_QUALITY, &quality);
-  int vbr = 1;
-  speex_encoder_ctl(encoder_state_, SPEEX_SET_VBR, &vbr);
-  memset(encoded_frame_data_, 0, sizeof(encoded_frame_data_));
-}
-
-SpeexEncoder::~SpeexEncoder() {
-  speex_bits_destroy(&bits_);
-  speex_encoder_destroy(encoder_state_);
-}
-
-void SpeexEncoder::Encode(const short* samples,
-                          int num_samples,
-                          std::list<std::string*>* encoded_frames) {
-  // Drop incomplete frames, typically those which come in when recording stops.
-  num_samples -= (num_samples % samples_per_frame_);
-  for (int i = 0; i < num_samples; i += samples_per_frame_) {
-    speex_bits_reset(&bits_);
-    speex_encode_int(encoder_state_, const_cast<spx_int16_t*>(samples + i),
-                     &bits_);
-
-    // Encode the frame and place the size of the frame as the first byte. This
-    // is the packet format for MIME type x-speex-with-header-byte.
-    int frame_length = speex_bits_write(&bits_, encoded_frame_data_ + 1,
-                                        kMaxSpeexFrameLength);
-    encoded_frame_data_[0] = static_cast<char>(frame_length);
-    encoded_frames->push_back(new string(encoded_frame_data_,
-                                         frame_length + 1));
-  }
-}
-
 SpeechRecognizer::SpeechRecognizer(Delegate* delegate,
                                    int caller_id,
                                    const std::string& language,
                                    const std::string& grammar,
-                                   const std::string& hardware_info)
+                                   const std::string& hardware_info,
+                                   const std::string& origin_url)
     : delegate_(delegate),
       caller_id_(caller_id),
       language_(language),
       grammar_(grammar),
       hardware_info_(hardware_info),
-      encoder_(new SpeexEncoder()),
+      origin_url_(origin_url),
+      codec_(AudioEncoder::CODEC_SPEEX),
+      encoder_(NULL),
       endpointer_(kAudioSampleRate),
       num_samples_recorded_(0),
       audio_level_(0.0f) {
@@ -134,7 +65,7 @@
   // |StopRecording| being called.
   DCHECK(!audio_controller_.get());
   DCHECK(!request_.get() || !request_->HasPendingRequest());
-  DCHECK(audio_buffers_.empty());
+  DCHECK(!encoder_.get());
   endpointer_.EndSession();
 }
 
@@ -142,14 +73,16 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(!audio_controller_.get());
   DCHECK(!request_.get() || !request_->HasPendingRequest());
+  DCHECK(!encoder_.get());
 
   // The endpointer needs to estimate the environment/background noise before
   // starting to treat the audio as user input. In |HandleOnData| we wait until
   // such time has passed before switching to user input mode.
   endpointer_.SetEnvironmentEstimationMode();
 
+  encoder_.reset(AudioEncoder::Create(codec_, kAudioSampleRate,
+                                      kNumBitsPerAudioSample));
   int samples_per_packet = (kAudioSampleRate * kAudioPacketIntervalMs) / 1000;
-  DCHECK((samples_per_packet % encoder_->samples_per_frame()) == 0);
   AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kNumAudioChannels,
                          kAudioSampleRate, kNumBitsPerAudioSample,
                          samples_per_packet);
@@ -174,7 +107,7 @@
   }
 
   VLOG(1) << "SpeechRecognizer canceling recognition.";
-  ReleaseAudioBuffers();
+  encoder_.reset();
   request_.reset();
 }
 
@@ -189,44 +122,32 @@
   VLOG(1) << "SpeechRecognizer stopping record.";
   audio_controller_->Close();
   audio_controller_ = NULL;  // Releases the ref ptr.
+  encoder_->Flush();
 
   delegate_->DidCompleteRecording(caller_id_);
 
-  // If we haven't got any audio yet end the recognition sequence here.
-  if (audio_buffers_.empty()) {
+  // Since the http request takes a single string as POST data, allocate
+  // one and copy over bytes from the audio buffers to the string.
+  // And If we haven't got any audio yet end the recognition sequence here.
+  string mime_type = encoder_->mime_type();
+  string data;
+  encoder_->GetEncodedData(&data);
+  encoder_.reset();
+
+  if (data.empty()) {
     // Guard against the delegate freeing us until we finish our job.
     scoped_refptr<SpeechRecognizer> me(this);
     delegate_->DidCompleteRecognition(caller_id_);
-    return;
+  } else {
+    DCHECK(!request_.get());
+    request_.reset(new SpeechRecognitionRequest(
+        Profile::GetDefaultRequestContext(), this));
+    request_->Send(language_, grammar_, hardware_info_, origin_url_,
+                   mime_type, data);
   }
-
-  // We now have recorded audio in our buffers, so start a recognition request.
-  // Since the http request takes a single string as POST data, allocate
-  // one and copy over bytes from the audio buffers to the string.
-  int audio_buffer_length = 0;
-  for (AudioBufferQueue::iterator it = audio_buffers_.begin();
-       it != audio_buffers_.end(); it++) {
-    audio_buffer_length += (*it)->length();
-  }
-  string data;
-  data.reserve(audio_buffer_length);
-  for (AudioBufferQueue::iterator it = audio_buffers_.begin();
-       it != audio_buffers_.end(); it++) {
-    data.append(*(*it));
-  }
-
-  DCHECK(!request_.get());
-  request_.reset(new SpeechRecognitionRequest(
-      Profile::GetDefaultRequestContext(), this));
-  request_->Send(language_, grammar_, hardware_info_, kContentTypeSpeex, data);
-  ReleaseAudioBuffers();  // No need to keep the audio anymore.
 }
 
 void SpeechRecognizer::ReleaseAudioBuffers() {
-  for (AudioBufferQueue::iterator it = audio_buffers_.begin();
-       it != audio_buffers_.end(); it++)
-    delete *it;
-  audio_buffers_.clear();
 }
 
 // Invoked in the audio thread.
@@ -275,7 +196,7 @@
   DCHECK((data->length() % sizeof(short)) == 0);
   int num_samples = data->length() / sizeof(short);
 
-  encoder_->Encode(samples, num_samples, &audio_buffers_);
+  encoder_->Encode(samples, num_samples);
   float rms;
   endpointer_.ProcessAudio(samples, num_samples, &rms);
   delete data;
diff --git a/chrome/browser/speech/speech_recognizer.h b/chrome/browser/speech/speech_recognizer.h
index cafba28..2570fba 100644
--- a/chrome/browser/speech/speech_recognizer.h
+++ b/chrome/browser/speech/speech_recognizer.h
@@ -11,14 +11,13 @@
 
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "chrome/browser/speech/audio_encoder.h"
 #include "chrome/browser/speech/endpointer/endpointer.h"
 #include "chrome/browser/speech/speech_recognition_request.h"
 #include "media/audio/audio_input_controller.h"
 
 namespace speech_input {
 
-class SpeexEncoder;
-
 // Records audio, sends recorded audio to server and translates server response
 // to recognition result.
 class SpeechRecognizer
@@ -77,7 +76,8 @@
                    int caller_id,
                    const std::string& language,
                    const std::string& grammar,
-                   const std::string& hardware_info);
+                   const std::string& hardware_info,
+                   const std::string& origin_url);
   ~SpeechRecognizer();
 
   // Starts audio recording and does recognition after recording ends. The same
@@ -127,14 +127,12 @@
   std::string language_;
   std::string grammar_;
   std::string hardware_info_;
-
-  // Buffer holding the recorded audio. Owns the strings inside the list.
-  typedef std::list<std::string*> AudioBufferQueue;
-  AudioBufferQueue audio_buffers_;
+  std::string origin_url_;
 
   scoped_ptr<SpeechRecognitionRequest> request_;
   scoped_refptr<media::AudioInputController> audio_controller_;
-  scoped_ptr<SpeexEncoder> encoder_;
+  AudioEncoder::Codec codec_;
+  scoped_ptr<AudioEncoder> encoder_;
   Endpointer endpointer_;
   int num_samples_recorded_;
   float audio_level_;
diff --git a/chrome/browser/speech/speech_recognizer_unittest.cc b/chrome/browser/speech/speech_recognizer_unittest.cc
index 44967b1..855f35a 100644
--- a/chrome/browser/speech/speech_recognizer_unittest.cc
+++ b/chrome/browser/speech/speech_recognizer_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -24,7 +24,8 @@
       : io_thread_(BrowserThread::IO, &message_loop_),
         ALLOW_THIS_IN_INITIALIZER_LIST(
             recognizer_(new SpeechRecognizer(this, 1, std::string(),
-                                             std::string(), std::string()))),
+                                             std::string(), std::string(),
+                                             std::string()))),
         recording_complete_(false),
         recognition_complete_(false),
         result_received_(false),
@@ -38,10 +39,6 @@
     audio_packet_.resize(audio_packet_length_bytes);
   }
 
-  void StartTest() {
-    EXPECT_TRUE(recognizer_->StartRecording());
-  }
-
   // SpeechRecognizer::Delegate methods.
   virtual void SetRecognitionResult(int caller_id,
                                     bool error,
@@ -142,8 +139,8 @@
   // Issue the network callback to complete the process.
   TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::SUCCESS);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::SUCCESS);
   fetcher->delegate()->OnURLFetchComplete(
       fetcher, fetcher->original_url(), status, 200, ResponseCookies(),
       "{\"hypotheses\":[{\"utterance\":\"123\"}]}");
diff --git a/chrome/browser/spellcheck_host.cc b/chrome/browser/spellcheck_host.cc
index 7a5ffa6..4c59b56 100644
--- a/chrome/browser/spellcheck_host.cc
+++ b/chrome/browser/spellcheck_host.cc
@@ -6,7 +6,6 @@
 
 #include <fcntl.h>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/path_service.h"
@@ -25,6 +24,7 @@
 #include "chrome/common/spellcheck_common.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/hunspell/google/bdict.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
diff --git a/chrome/browser/ssl/ssl_add_cert_handler_mac.mm b/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
index 68b9418..48b9859 100644
--- a/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
+++ b/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
@@ -7,7 +7,6 @@
 #include <SecurityInterface/SFCertificatePanel.h>
 #include <SecurityInterface/SFCertificateView.h>
 
-#include "app/l10n_util_mac.h"
 #include "base/logging.h"
 #include "base/scoped_nsobject.h"
 #include "chrome/common/logging_chrome.h"
@@ -16,6 +15,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "grit/generated_resources.h"
 #include "net/base/x509_certificate.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @interface SSLAddCertHandlerCocoa : NSObject
 {
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index ebec519..8d3b315 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/ssl/ssl_blocking_page.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/metrics/histogram.h"
 #include "base/string_piece.h"
@@ -13,7 +11,6 @@
 #include "base/values.h"
 #include "chrome/browser/cert_store.h"
 #include "chrome/browser/dom_operation_notification_details.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/ssl/ssl_cert_error_handler.h"
@@ -21,12 +18,12 @@
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 0e6b44a..1a8dded 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -4,7 +4,6 @@
 
 #include "base/time.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/tab_contents/interstitial_page.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
@@ -12,7 +11,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/base/cert_status_flags.h"
@@ -660,16 +658,10 @@
   CheckAuthenticationBrokenState(tab, 0, true, false);
 }
 
-#if defined(OS_WIN)
-// See http://crbug.com/47170
-#define MAYBE_TestCNInvalidStickiness FLAKY_TestCNInvalidStickiness
-#else
-#define MAYBE_TestCNInvalidStickiness TestCNInvalidStickiness
-#endif
-
 // This test ensures the CN invalid status does not 'stick' to a certificate
 // (see bug #1044942) and that it depends on the host-name.
-IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestCNInvalidStickiness) {
+// Disabled, see http://crbug.com/68448 and http://crbug.com/49377.
+IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestCNInvalidStickiness) {
   ASSERT_TRUE(https_server_.Start());
   ASSERT_TRUE(https_server_mismatched_.Start());
 
@@ -810,7 +802,8 @@
 }
 
 // Visit a page over http that is a redirect to a page with good HTTPS.
-IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectHTTPToGoodHTTPS) {
+// Disabled, http://crbug.com/70216.
+IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestRedirectHTTPToGoodHTTPS) {
   ASSERT_TRUE(test_server()->Start());
   ASSERT_TRUE(https_server_.Start());
 
diff --git a/chrome/browser/ssl/ssl_error_info.cc b/chrome/browser/ssl/ssl_error_info.cc
index 6769d88..ee3df60 100644
--- a/chrome/browser/ssl/ssl_error_info.cc
+++ b/chrome/browser/ssl/ssl_error_info.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ssl/ssl_error_info.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/cert_store.h"
 #include "chrome/common/time_format.h"
@@ -14,6 +13,7 @@
 #include "net/base/cert_status_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/ssl_info.h"
+#include "ui/base/l10n/l10n_util.h"
 
 SSLErrorInfo::SSLErrorInfo(const string16& title,
                            const string16& details,
diff --git a/chrome/browser/ssl/ssl_manager.cc b/chrome/browser/ssl/ssl_manager.cc
index 7c9cd8f..7d662c0 100644
--- a/chrome/browser/ssl/ssl_manager.cc
+++ b/chrome/browser/ssl/ssl_manager.cc
@@ -4,12 +4,10 @@
 
 #include "chrome/browser/ssl/ssl_manager.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/load_from_memory_cache_details.h"
 #include "chrome/browser/net/url_request_tracking.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/renderer_host/resource_request_details.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
@@ -21,9 +19,9 @@
 #include "chrome/browser/tab_contents/provisional_load_details.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "net/base/cert_status_flags.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // static
 void SSLManager::OnSSLCertificateError(ResourceDispatcherHost* rdh,
diff --git a/chrome/browser/ssl/ssl_policy.cc b/chrome/browser/ssl/ssl_policy.cc
index 6205722..afe861b 100644
--- a/chrome/browser/ssl/ssl_policy.cc
+++ b/chrome/browser/ssl/ssl_policy.cc
@@ -9,7 +9,6 @@
 #include "base/singleton.h"
 #include "base/string_piece.h"
 #include "base/string_util.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/site_instance.h"
@@ -18,9 +17,7 @@
 #include "chrome/browser/ssl/ssl_request_info.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/jstemplate_builder.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/time_format.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
diff --git a/chrome/browser/status_icons/OWNERS b/chrome/browser/status_icons/OWNERS
new file mode 100644
index 0000000..3e63b46
--- /dev/null
+++ b/chrome/browser/status_icons/OWNERS
@@ -0,0 +1 @@
+atwilson@chromium.org
diff --git a/chrome/browser/status_icons/status_icon.cc b/chrome/browser/status_icons/status_icon.cc
index baaa6cc..f018842 100644
--- a/chrome/browser/status_icons/status_icon.cc
+++ b/chrome/browser/status_icons/status_icon.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/status_icons/status_icon.h"
 
-#include "app/menus/menu_model.h"
+#include "ui/base/models/menu_model.h"
 
 StatusIcon::StatusIcon()
 {
@@ -29,7 +29,7 @@
   FOR_EACH_OBSERVER(Observer, observers_, OnClicked());
 }
 
-void StatusIcon::SetContextMenu(menus::MenuModel* menu) {
+void StatusIcon::SetContextMenu(ui::MenuModel* menu) {
   context_menu_contents_.reset(menu);
   UpdatePlatformContextMenu(menu);
 }
diff --git a/chrome/browser/status_icons/status_icon.h b/chrome/browser/status_icons/status_icon.h
index 5398eb3..3b53dc5 100644
--- a/chrome/browser/status_icons/status_icon.h
+++ b/chrome/browser/status_icons/status_icon.h
@@ -12,7 +12,7 @@
 
 class SkBitmap;
 
-namespace menus {
+namespace ui {
 class MenuModel;
 }
 
@@ -32,7 +32,7 @@
 
   // Set the context menu for this icon. The icon takes ownership of the passed
   // context menu. Passing NULL results in no menu at all.
-  void SetContextMenu(menus::MenuModel* menu);
+  void SetContextMenu(ui::MenuModel* menu);
 
   class Observer {
    public:
@@ -63,12 +63,12 @@
   // Invoked after a call to SetContextMenu() to let the platform-specific
   // subclass update the native context menu based on the new model. If NULL is
   // passed, subclass should destroy the native context menu.
-  virtual void UpdatePlatformContextMenu(menus::MenuModel* model) = 0;
+  virtual void UpdatePlatformContextMenu(ui::MenuModel* model) = 0;
 
  private:
   ObserverList<Observer> observers_;
   // Context menu, if any.
-  scoped_ptr<menus::MenuModel> context_menu_contents_;
+  scoped_ptr<ui::MenuModel> context_menu_contents_;
   DISALLOW_COPY_AND_ASSIGN(StatusIcon);
 };
 
diff --git a/chrome/browser/status_icons/status_icon_unittest.cc b/chrome/browser/status_icons/status_icon_unittest.cc
index 48fbc20..a3a2596 100644
--- a/chrome/browser/status_icons/status_icon_unittest.cc
+++ b/chrome/browser/status_icons/status_icon_unittest.cc
@@ -18,7 +18,7 @@
   virtual void SetImage(const SkBitmap& image) {}
   virtual void SetPressedImage(const SkBitmap& image) {}
   virtual void SetToolTip(const string16& tool_tip) {}
-  virtual void UpdatePlatformContextMenu(menus::MenuModel* menu) {}
+  virtual void UpdatePlatformContextMenu(ui::MenuModel* menu) {}
 };
 
 TEST(StatusIconTest, ObserverAdd) {
diff --git a/chrome/browser/status_icons/status_tray_unittest.cc b/chrome/browser/status_icons/status_tray_unittest.cc
index a047689..61555f9 100644
--- a/chrome/browser/status_icons/status_tray_unittest.cc
+++ b/chrome/browser/status_icons/status_tray_unittest.cc
@@ -15,7 +15,7 @@
   virtual void SetImage(const SkBitmap& image) {}
   virtual void SetPressedImage(const SkBitmap& image) {}
   virtual void SetToolTip(const string16& tool_tip) {}
-  virtual void UpdatePlatformContextMenu(menus::MenuModel* menu) {}
+  virtual void UpdatePlatformContextMenu(ui::MenuModel* menu) {}
   virtual void AddObserver(StatusIcon::Observer* observer) {}
   virtual void RemoveObserver(StatusIcon::Observer* observer) {}
 };
@@ -23,7 +23,7 @@
 class TestStatusTray : public StatusTray {
  public:
   MOCK_METHOD0(CreatePlatformStatusIcon, StatusIcon*());
-  MOCK_METHOD1(UpdatePlatformContextMenu, void(menus::MenuModel*));
+  MOCK_METHOD1(UpdatePlatformContextMenu, void(ui::MenuModel*));
 };
 
 TEST(StatusTrayTest, Create) {
diff --git a/chrome/browser/sync/PRESUBMIT.py b/chrome/browser/sync/PRESUBMIT.py
new file mode 100644
index 0000000..badc220
--- /dev/null
+++ b/chrome/browser/sync/PRESUBMIT.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Chromium presubmit script for src/chrome/browser/sync.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+def GetPreferredTrySlaves():
+  return ['win', 'linux', 'mac', 'win_sync', 'linux_sync', 'mac_sync']
diff --git a/chrome/browser/sync/README.js b/chrome/browser/sync/README.js
new file mode 100644
index 0000000..f7ef38e
--- /dev/null
+++ b/chrome/browser/sync/README.js
@@ -0,0 +1,56 @@
+Overview of chrome://sync-internals
+-----------------------------------
+
+This note explains how chrome://sync-internals (also known as
+about:sync) interacts with the sync service/backend.
+
+Basically, chrome://sync-internals sends asynchronous messages to the
+sync backend and the sync backend asynchronously raises events to
+chrome://sync-internals, either when replying to messages or when
+something interesting happens.
+
+Both messages and events have a name and a list of arguments, the
+latter of which is represented by a JsArgList (js_arg_list.h) object,
+which is basically a wrapper around an immutable ListValue.
+
+TODO(akalin): Move all the js_* files into a js/ subdirectory.
+
+Message/event flow
+------------------
+
+chrome://sync-internals is represented by SyncInternalsUI
+(chrome/browser/dom_ui/sync_internals_ui.h).  SyncInternalsUI
+interacts with the sync service via a JsFrontend (js_frontend.h)
+object, which has a ProcessMessage() method.  The JsFrontend can
+handle some messages itself, but it can also delegate the rest to a
+JsBackend instance (js_backend.h), which also has a ProcessMessage()
+method.  A JsBackend can in turn handle some messages itself and
+delegate to other JsBackend instances.
+
+Essentially, there is a tree with a JsFrontend as the root and
+JsBackend as non-root internal nodes and leaf nodes (although
+currently, the tree is more like a simple list).  The sets of messages
+handled by the JsBackends and the JsFrontend are disjoint, which means
+that at most one node handles a given message type.  Also, the
+JsBackends may live on different threads, but JsArgList is thread-safe
+so that's okay.
+
+SyncInternalsUI is a JsEventHandler (js_event_handler.h), which means
+that it has a HandleJsEvent() method, but JsBackends cannot easily
+access those objects.  Instead, each JsBackend keeps track of its
+parent router, which is a JsEventRouter object (js_event_router.h).
+Basically, a JsEventRouter is another JsBackend object or a JsFrontend
+object.  So an event travels up through the JsEventRouter until it
+reaches the JsFrontend, which knows about the existing JsEventHandlers
+(via AddHandler()/RemoveHandler()) and so can delegate to the right
+one.
+
+A diagram of the flow of a message and its reply:
+
+msg(args) -> F -> B -> B -> B
+             |    |    |
+        H <- R <- R <- R <- reply-event(args)
+
+F = JsFrontend, B = JsBackend, R = JsEventRouter, H = JsEventHandler
+
+Non-reply events are percolated up similarly.
diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.cc b/chrome/browser/sync/abstract_profile_sync_service_test.cc
new file mode 100644
index 0000000..3c54e23
--- /dev/null
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/abstract_profile_sync_service_test.h"
+
+#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/autofill_model_associator.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
+#include "chrome/browser/sync/glue/password_model_associator.h"
+#include "chrome/browser/sync/glue/preference_model_associator.h"
+#include "chrome/browser/sync/glue/session_model_associator.h"
+#include "chrome/browser/sync/glue/typed_url_model_associator.h"
+#include "chrome/browser/sync/protocol/sync.pb.h"
+#include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/syncable/syncable.h"
+#include "chrome/browser/sync/test_profile_sync_service.h"
+#include "chrome/browser/sync/util/cryptographer.h"
+#include "chrome/test/profile_mock.h"
+#include "chrome/test/sync/engine/test_id_factory.h"
+
+using browser_sync::TestIdFactory;
+using sync_api::UserShare;
+using syncable::BASE_VERSION;
+using syncable::CREATE;
+using syncable::DirectoryManager;
+using syncable::IS_DEL;
+using syncable::IS_DIR;
+using syncable::IS_UNAPPLIED_UPDATE;
+using syncable::IS_UNSYNCED;
+using syncable::ModelType;
+using syncable::MutableEntry;
+using syncable::SERVER_IS_DIR;
+using syncable::SERVER_VERSION;
+using syncable::SPECIFICS;
+using syncable::ScopedDirLookup;
+using syncable::UNIQUE_SERVER_TAG;
+using syncable::UNITTEST;
+using syncable::WriteTransaction;
+
+const std::string ProfileSyncServiceTestHelper::GetTagForType(
+    ModelType model_type) {
+  switch (model_type) {
+    case syncable::AUTOFILL:
+      return browser_sync::kAutofillTag;
+    case syncable::AUTOFILL_PROFILE:
+      return browser_sync::kAutofillProfileTag;
+    case syncable::PREFERENCES:
+      return browser_sync::kPreferencesTag;
+    case syncable::PASSWORDS:
+      return browser_sync::kPasswordTag;
+    case syncable::NIGORI:
+      return browser_sync::kNigoriTag;
+    case syncable::TYPED_URLS:
+      return browser_sync::kTypedUrlTag;
+    case syncable::SESSIONS:
+      return browser_sync::kSessionsTag;
+    case syncable::BOOKMARKS:
+      return "google_chrome_bookmarks";
+    default:
+      NOTREACHED();
+  }
+  return std::string();
+}
+
+bool ProfileSyncServiceTestHelper::CreateRoot(
+    ModelType model_type, UserShare* user_share,
+    TestIdFactory* ids) {
+  DirectoryManager* dir_manager = user_share->dir_manager.get();
+
+  ScopedDirLookup dir(dir_manager, user_share->name);
+  if (!dir.good())
+    return false;
+
+  std::string tag_name = GetTagForType(model_type);
+
+  WriteTransaction wtrans(dir, UNITTEST, __FILE__, __LINE__);
+  MutableEntry node(&wtrans,
+                    CREATE,
+                    wtrans.root_id(),
+                    tag_name);
+  node.Put(UNIQUE_SERVER_TAG, tag_name);
+  node.Put(IS_DIR, true);
+  node.Put(SERVER_IS_DIR, false);
+  node.Put(IS_UNSYNCED, false);
+  node.Put(IS_UNAPPLIED_UPDATE, false);
+  node.Put(SERVER_VERSION, 20);
+  node.Put(BASE_VERSION, 20);
+  node.Put(IS_DEL, false);
+  node.Put(syncable::ID, ids->MakeServer(tag_name));
+  sync_pb::EntitySpecifics specifics;
+  syncable::AddDefaultExtensionValue(model_type, &specifics);
+  node.Put(SPECIFICS, specifics);
+
+  return true;
+}
+
+AbstractProfileSyncServiceTest::AbstractProfileSyncServiceTest()
+    : ui_thread_(BrowserThread::UI, &message_loop_) {}
+
+AbstractProfileSyncServiceTest::~AbstractProfileSyncServiceTest() {}
+
+bool AbstractProfileSyncServiceTest::CreateRoot(ModelType model_type) {
+  return ProfileSyncServiceTestHelper::CreateRoot(
+      model_type,
+      service_->GetUserShare(),
+      service_->id_factory());
+}
+
+CreateRootTask::CreateRootTask(
+    AbstractProfileSyncServiceTest* test, ModelType model_type)
+    : test_(test), model_type_(model_type), success_(false) {
+}
+
+CreateRootTask::~CreateRootTask() {}
+void CreateRootTask::Run() {
+  success_ = test_->CreateRoot(model_type_);
+}
+
+bool CreateRootTask::success() {
+  return success_;
+}
diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.h b/chrome/browser/sync/abstract_profile_sync_service_test.h
index b5fc1c2..8e67378 100644
--- a/chrome/browser/sync/abstract_profile_sync_service_test.h
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,139 +13,58 @@
 #include "base/task.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/net/gaia/token_service.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/autofill_model_associator.h"
-#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
-#include "chrome/browser/sync/glue/password_model_associator.h"
-#include "chrome/browser/sync/glue/preference_model_associator.h"
-#include "chrome/browser/sync/glue/session_model_associator.h"
-#include "chrome/browser/sync/glue/typed_url_model_associator.h"
 #include "chrome/browser/sync/profile_sync_factory_mock.h"
-#include "chrome/browser/sync/protocol/sync.pb.h"
-#include "chrome/browser/sync/syncable/directory_manager.h"
 #include "chrome/browser/sync/syncable/model_type.h"
-#include "chrome/browser/sync/syncable/syncable.h"
-#include "chrome/browser/sync/test_profile_sync_service.h"
-#include "chrome/browser/sync/util/cryptographer.h"
-#include "chrome/test/profile_mock.h"
-#include "chrome/test/sync/engine/test_id_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using browser_sync::TestIdFactory;
-using sync_api::UserShare;
-using syncable::BASE_VERSION;
-using syncable::CREATE;
-using syncable::DirectoryManager;
-using syncable::IS_DEL;
-using syncable::IS_DIR;
-using syncable::IS_UNAPPLIED_UPDATE;
-using syncable::IS_UNSYNCED;
-using syncable::ModelType;
-using syncable::MutableEntry;
-using syncable::SERVER_IS_DIR;
-using syncable::SERVER_VERSION;
-using syncable::SPECIFICS;
-using syncable::ScopedDirLookup;
-using syncable::UNIQUE_SERVER_TAG;
-using syncable::UNITTEST;
-using syncable::WriteTransaction;
+class ProfileSyncService;
+class TestProfileSyncService;
+
+namespace browser_sync {
+class TestIdFactory;
+}  // namespace browser_sync
+
+namespace sync_api {
+struct UserShare;
+}  //  namespace sync_api
 
 class ProfileSyncServiceTestHelper {
  public:
-  static bool CreateRoot(ModelType model_type, ProfileSyncService* service,
-                         TestIdFactory* ids) {
-    UserShare* user_share = service->backend()->GetUserShareHandle();
-    DirectoryManager* dir_manager = user_share->dir_manager.get();
+  static const std::string GetTagForType(syncable::ModelType model_type);
 
-    ScopedDirLookup dir(dir_manager, user_share->name);
-    if (!dir.good())
-      return false;
-
-    std::string tag_name;
-    switch (model_type) {
-      case syncable::AUTOFILL:
-        tag_name = browser_sync::kAutofillTag;
-        break;
-      case syncable::AUTOFILL_PROFILE:
-        tag_name = browser_sync::kAutofillProfileTag;
-        break;
-      case syncable::PREFERENCES:
-        tag_name = browser_sync::kPreferencesTag;
-        break;
-      case syncable::PASSWORDS:
-        tag_name = browser_sync::kPasswordTag;
-        break;
-      case syncable::NIGORI:
-        tag_name = browser_sync::kNigoriTag;
-        break;
-      case syncable::TYPED_URLS:
-        tag_name = browser_sync::kTypedUrlTag;
-        break;
-      case syncable::SESSIONS:
-        tag_name = browser_sync::kSessionsTag;
-        break;
-      default:
-        return false;
-    }
-
-    WriteTransaction wtrans(dir, UNITTEST, __FILE__, __LINE__);
-    MutableEntry node(&wtrans,
-                      CREATE,
-                      wtrans.root_id(),
-                      tag_name);
-    node.Put(UNIQUE_SERVER_TAG, tag_name);
-    node.Put(IS_DIR, true);
-    node.Put(SERVER_IS_DIR, false);
-    node.Put(IS_UNSYNCED, false);
-    node.Put(IS_UNAPPLIED_UPDATE, false);
-    node.Put(SERVER_VERSION, 20);
-    node.Put(BASE_VERSION, 20);
-    node.Put(IS_DEL, false);
-    node.Put(syncable::ID, ids->MakeServer(tag_name));
-    sync_pb::EntitySpecifics specifics;
-    syncable::AddDefaultExtensionValue(model_type, &specifics);
-    node.Put(SPECIFICS, specifics);
-
-    return true;
-  }
+  static bool CreateRoot(syncable::ModelType model_type,
+                         sync_api::UserShare* service,
+                         browser_sync::TestIdFactory* ids);
 };
 
 class AbstractProfileSyncServiceTest : public testing::Test {
  public:
-  AbstractProfileSyncServiceTest()
-      : ui_thread_(BrowserThread::UI, &message_loop_) {}
+  AbstractProfileSyncServiceTest();
+  virtual ~AbstractProfileSyncServiceTest();
 
-  bool CreateRoot(ModelType model_type) {
-    return ProfileSyncServiceTestHelper::CreateRoot(model_type,
-                                                    service_.get(), &ids_);
-  }
+  bool CreateRoot(syncable::ModelType model_type);
 
  protected:
-
   MessageLoopForUI message_loop_;
   BrowserThread ui_thread_;
   ProfileSyncFactoryMock factory_;
   TokenService token_service_;
   scoped_ptr<TestProfileSyncService> service_;
-  TestIdFactory ids_;
 };
 
 class CreateRootTask : public Task {
  public:
-  CreateRootTask(AbstractProfileSyncServiceTest* test, ModelType model_type)
-      : test_(test), model_type_(model_type), success_(false) {
-  }
+  CreateRootTask(AbstractProfileSyncServiceTest* test,
+                 syncable::ModelType model_type);
 
-  virtual ~CreateRootTask() {}
-  virtual void Run() {
-    success_ = test_->CreateRoot(model_type_);
-  }
+  virtual ~CreateRootTask();
+  virtual void Run();
 
-  bool success() { return success_; }
+  bool success();
 
  private:
   AbstractProfileSyncServiceTest* test_;
-  ModelType model_type_;
+  syncable::ModelType model_type_;
   bool success_;
 };
 
diff --git a/chrome/browser/sync/engine/all_status.cc b/chrome/browser/sync/engine/all_status.cc
index 5beaa80..1580dc4 100644
--- a/chrome/browser/sync/engine/all_status.cc
+++ b/chrome/browser/sync/engine/all_status.cc
@@ -15,17 +15,8 @@
 
 namespace browser_sync {
 
-const char* AllStatus::GetSyncStatusString(SyncStatus icon) {
-  const char* strings[] = {"OFFLINE", "OFFLINE_UNSYNCED", "SYNCING", "READY",
-      "CONFLICT", "OFFLINE_UNUSABLE"};
-  COMPILE_ASSERT(arraysize(strings) == ICON_STATUS_COUNT, enum_indexed_array);
-  if (icon < 0 || icon >= static_cast<SyncStatus>(arraysize(strings)))
-    LOG(FATAL) << "Illegal Icon State:" << icon;
-  return strings[icon];
-}
-
-static const AllStatus::Status init_status =
-  { AllStatus::OFFLINE };
+static const sync_api::SyncManager::Status init_status =
+  { sync_api::SyncManager::Status::OFFLINE };
 
 AllStatus::AllStatus() : status_(init_status) {
   status_.initial_sync_ended = true;
@@ -35,8 +26,11 @@
 AllStatus::~AllStatus() {
 }
 
-AllStatus::Status AllStatus::CreateBlankStatus() const {
-  Status status = status_;
+sync_api::SyncManager::Status AllStatus::CreateBlankStatus() const {
+  // Status is initialized with the previous status value.  Variables
+  // whose values accumulate (e.g. lifetime counters like updates_received)
+  // are not to be cleared here.
+  sync_api::SyncManager::Status status = status_;
   status.syncing = true;
   status.unsynced_count = 0;
   status.conflicting_count = 0;
@@ -45,12 +39,12 @@
   status.max_consecutive_errors = 0;
   status.server_broken = false;
   status.updates_available = 0;
-  status.updates_received = 0;
   return status;
 }
 
-AllStatus::Status AllStatus::CalcSyncing(const SyncEngineEvent &event) const {
-  Status status = CreateBlankStatus();
+sync_api::SyncManager::Status AllStatus::CalcSyncing(
+    const SyncEngineEvent &event) const {
+  sync_api::SyncManager::Status status = CreateBlankStatus();
   const sessions::SyncSessionSnapshot* snapshot = event.snapshot;
   status.unsynced_count += static_cast<int>(snapshot->unsynced_count);
   status.conflicting_count += snapshot->errors.num_conflicting_commits;
@@ -72,7 +66,16 @@
     status.server_broken = true;
 
   status.updates_available += snapshot->num_server_changes_remaining;
-  status.updates_received += snapshot->max_local_timestamp;
+
+  // Accumulate update count only once per session to avoid double-counting.
+  // TODO(ncarter): Make this realtime by having the syncer_status
+  // counter preserve its value across sessions.  http://crbug.com/26339
+  if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) {
+    status.updates_received +=
+        snapshot->syncer_status.num_updates_downloaded_total;
+    status.tombstone_updates_received +=
+        snapshot->syncer_status.num_tombstone_updates_downloaded_total;
+  }
   return status;
 }
 
@@ -82,17 +85,17 @@
     status_.server_reachable && status_.server_up && !status_.server_broken;
   if (online) {
     if (status_.syncer_stuck)
-      status_.icon = CONFLICT;
+      status_.summary = sync_api::SyncManager::Status::CONFLICT;
     else if (unsynced_changes || status_.syncing)
-      status_.icon = SYNCING;
+      status_.summary = sync_api::SyncManager::Status::SYNCING;
     else
-      status_.icon = READY;
+      status_.summary = sync_api::SyncManager::Status::READY;
   } else if (!status_.initial_sync_ended) {
-    status_.icon = OFFLINE_UNUSABLE;
+    status_.summary = sync_api::SyncManager::Status::OFFLINE_UNUSABLE;
   } else if (unsynced_changes) {
-    status_.icon = OFFLINE_UNSYNCED;
+    status_.summary = sync_api::SyncManager::Status::OFFLINE_UNSYNCED;
   } else {
-    status_.icon = OFFLINE;
+    status_.summary = sync_api::SyncManager::Status::OFFLINE;
   }
 }
 
@@ -134,8 +137,8 @@
   }
 }
 
-AllStatus::Status AllStatus::status() const {
-  AutoLock lock(mutex_);
+sync_api::SyncManager::Status AllStatus::status() const {
+  base::AutoLock lock(mutex_);
   return status_;
 }
 
diff --git a/chrome/browser/sync/engine/all_status.h b/chrome/browser/sync/engine/all_status.h
index d9947d0..015bfb7 100644
--- a/chrome/browser/sync/engine/all_status.h
+++ b/chrome/browser/sync/engine/all_status.h
@@ -11,8 +11,9 @@
 
 #include <map>
 
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/engine/syncer_types.h"
 
 namespace browser_sync {
@@ -27,59 +28,6 @@
 class AllStatus : public SyncEngineEventListener {
   friend class ScopedStatusLock;
  public:
-  // Status of the entire sync process distilled into a single enum.
-  enum SyncStatus {
-    // Can't connect to server, but there are no pending changes in
-    // our local dataase.
-    OFFLINE,
-    // Can't connect to server, and there are pending changes in our
-    // local cache.
-    OFFLINE_UNSYNCED,
-    // Connected and syncing.
-    SYNCING,
-    // Connected, no pending changes.
-    READY,
-    // Internal sync error.
-    CONFLICT,
-    // Can't connect to server, and we haven't completed the initial
-    // sync yet.  So there's nothing we can do but wait for the server.
-    OFFLINE_UNUSABLE,
-    // For array sizing, etc.
-    ICON_STATUS_COUNT
-  };
-
-  struct Status {
-    SyncStatus icon;
-    int unsynced_count;
-    int conflicting_count;
-    bool syncing;
-    bool authenticated;  // Successfully authenticated via gaia
-    // True if we have received at least one good reply from the server.
-    bool server_up;
-    bool server_reachable;
-    // True after a client has done a first sync.
-    bool initial_sync_ended;
-    // True if any syncer is stuck.
-    bool syncer_stuck;
-    // True if any syncer is stopped because of server issues.
-    bool server_broken;
-    // True only if the notification listener has subscribed.
-    bool notifications_enabled;
-    // Notifications counters updated by the actions in synapi.
-    int notifications_received;
-    int notifications_sent;
-    // The max number of consecutive errors from any component.
-    int max_consecutive_errors;
-    bool disk_full;
-
-    // Contains current transfer item meta handle
-    int64 current_item_meta_handle;
-    // The next two values will be equal if all updates have been received.
-    // total updates available.
-    int64 updates_available;
-    // total updates received.
-    int64 updates_received;
-  };
 
   AllStatus();
   ~AllStatus();
@@ -90,11 +38,7 @@
 
   virtual void OnSyncEngineEvent(const SyncEngineEvent& event);
 
-  // Returns a string description of the SyncStatus (currently just the ascii
-  // version of the enum). Will LOG(FATAL) if the status us out of range.
-  static const char* GetSyncStatusString(SyncStatus status);
-
-  Status status() const;
+  sync_api::SyncManager::Status status() const;
 
   void SetNotificationsEnabled(bool notifications_enabled);
 
@@ -105,15 +49,15 @@
  protected:
   // Examines syncer to calculate syncing and the unsynced count,
   // and returns a Status with new values.
-  Status CalcSyncing(const SyncEngineEvent& event) const;
-  Status CreateBlankStatus() const;
+  sync_api::SyncManager::Status CalcSyncing(const SyncEngineEvent& event) const;
+  sync_api::SyncManager::Status CreateBlankStatus() const;
 
   // Examines status to see what has changed, updates old_status in place.
   void CalcStatusChanges();
 
-  Status status_;
+  sync_api::SyncManager::Status status_;
 
-  mutable Lock mutex_;  // Protects all data members.
+  mutable base::Lock mutex_;  // Protects all data members.
   DISALLOW_COPY_AND_ASSIGN(AllStatus);
 };
 
diff --git a/chrome/browser/sync/engine/download_updates_command.cc b/chrome/browser/sync/engine/download_updates_command.cc
index a8d495d..4c01784 100644
--- a/chrome/browser/sync/engine/download_updates_command.cc
+++ b/chrome/browser/sync/engine/download_updates_command.cc
@@ -41,25 +41,18 @@
     return;
   }
 
-  // Pick some subset of the enabled types where all types in the set
-  // are at the same last_download_timestamp.  Do an update for those types.
+  // Request updates for all enabled types.
   syncable::ModelTypeBitSet enabled_types;
   for (ModelSafeRoutingInfo::const_iterator i = session->routing_info().begin();
        i != session->routing_info().end(); ++i) {
+    syncable::ModelType model_type = syncable::ModelTypeFromInt(i->first);
     enabled_types[i->first] = true;
+    dir->GetDownloadProgress(model_type,
+        get_updates->add_from_progress_marker());
   }
-  syncable::MultiTypeTimeStamp target =
-      dir->GetTypesWithOldestLastDownloadTimestamp(enabled_types);
-  VLOG(1) << "Getting updates from ts " << target.timestamp
-          << " for types " << target.data_types.to_string()
-          << " (of possible " << enabled_types.to_string() << ")";
-  DCHECK(target.data_types.any());
-  target.data_types.set(syncable::TOP_LEVEL_FOLDER);  // Always fetched.
 
-  get_updates->set_from_timestamp(target.timestamp);
-
-  // Set the requested_types protobuf field so that we fetch all enabled types.
-  SetRequestedTypes(target.data_types, get_updates->mutable_requested_types());
+  VLOG(1) << "Getting updates for types " << enabled_types.to_string();
+  DCHECK(enabled_types.any());
 
   // We want folders for our associated types, always.  If we were to set
   // this to false, the server would send just the non-container items
@@ -67,8 +60,10 @@
   get_updates->set_fetch_folders(true);
 
   // Set GetUpdatesMessage.GetUpdatesCallerInfo information.
+  // TODO(zea): send SyncSourceInfo's payloads to server once we know it's all
+  // working properly.
   get_updates->mutable_caller_info()->set_source(
-      session->TestAndSetSource().first);
+      session->TestAndSetSource().updates_source);
   get_updates->mutable_caller_info()->set_notifications_enabled(
       session->context()->notifications_enabled());
 
@@ -83,7 +78,7 @@
       update_response);
 
   StatusController* status = session->status_controller();
-  status->set_updates_request_parameters(target);
+  status->set_updates_request_types(enabled_types);
   if (!ok) {
     status->increment_num_consecutive_errors();
     status->mutable_updates_response()->Clear();
@@ -93,7 +88,7 @@
 
   status->mutable_updates_response()->CopyFrom(update_response);
 
-  VLOG(1) << "GetUpdates from ts " << get_updates->from_timestamp()
+  VLOG(1) << "GetUpdates "
           << " returned " << update_response.get_updates().entries_size()
           << " updates and indicated "
           << update_response.get_updates().changes_remaining()
diff --git a/chrome/browser/sync/engine/download_updates_command.h b/chrome/browser/sync/engine/download_updates_command.h
index 4b68531..713f03b 100644
--- a/chrome/browser/sync/engine/download_updates_command.h
+++ b/chrome/browser/sync/engine/download_updates_command.h
@@ -17,36 +17,24 @@
 
 namespace browser_sync {
 
-// Pick a subset of the enabled datatypes, download updates for them from
-// the server, place the result in the SyncSession for further processing.
+// Determine the enabled datatypes, download a batch of updates for them
+// from the server, place the result in the SyncSession for further processing.
 //
-// The main inputs to this operation are the last_download_timestamp state
+// The main inputs to this operation are the download_progress state
 // in the syncable::Directory, and the set of enabled types as indicated by
-// the SyncSession. DownloadUpdatesCommand will fetch the enabled type
-// or types having the smallest (oldest) value for last_download_timestamp.
-// DownloadUpdatesCommand will request a download of those types and will
-// store the server response in the SyncSession. Only one server request
-// is performed per Execute operation. A loop that causes multiple Execute
-// operations within a sync session can be found in the Syncer logic.
-// When looping, the DownloadUpdatesCommand consumes the information stored
-// by the StoreTimestampsCommand.
+// the SyncSession. DownloadUpdatesCommand will fetch updates for
+// all the enabled types, using download_progress to indicate the starting
+// point to the server. DownloadUpdatesCommand stores the server response
+// in the SyncSession. Only one server request is performed per Execute
+// operation. A loop that causes multiple Execute operations within a sync
+// session can be found in the Syncer logic. When looping, the
+// DownloadUpdatesCommand consumes the information stored by the
+// StoreTimestampsCommand.
 //
-// In practice, DownloadUpdatesCommand should exhibit one of two behaviors.
-// (a) If one or more datatypes has just been enabled, then they will have the
-//     oldest last_download_timestamp value (0). DownloadUpdatesCommand will
-//     choose to download updates for those types, and likely this will happen
-//     for several invocations of DownloadUpdatesCommand. Once the newly
-//     enabled types have caught up to the timestamp value of any previously
-//     enabled timestamps, DownloadUpdatesCommand will do a fetch for those
-//     datatypes. If nothing has changed on the server in the meantime,
-//     then the timestamp value for the new and old datatypes will now match.
-//     When that happens (and it eventually should), we have entered case (b).
-// (b) The common case is for all enabled datatypes to have the same
-//     last_download_timestamp value. This means that one server request
-//     tells us whether there are updates available to any datatype.  When
-//     the last_download_timestamp values for two datatypes is identical,
-//     those datatypes will never be separately requested, and the values
-//     will stay in lockstep indefinitely.
+// In practice, DownloadUpdatesCommand should loop until all updates are
+// downloaded for all enabled datatypes (i.e., until the server indicates
+// changes_remaining == 0 in the GetUpdates response), or until an error
+// is encountered.
 class DownloadUpdatesCommand : public SyncerCommand {
  public:
   DownloadUpdatesCommand();
diff --git a/chrome/browser/sync/engine/download_updates_command_unittest.cc b/chrome/browser/sync/engine/download_updates_command_unittest.cc
index 8df602c..5eb010c 100644
--- a/chrome/browser/sync/engine/download_updates_command_unittest.cc
+++ b/chrome/browser/sync/engine/download_updates_command_unittest.cc
@@ -87,50 +87,4 @@
   }
 }
 
-TEST_F(DownloadUpdatesCommandTest, OldestTimestampPicked) {
-  syncable::ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
-  ASSERT_TRUE(dir.good());
-
-  // i,j,k range over every possible model type.  j and k are enabled and at
-  // the same timestamp.  if i != j or k, i is enabled but at an older
-  // timestamp.
-  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
-    syncable::ModelType type_i = syncable::ModelTypeFromInt(i);
-    for (int j = FIRST_REAL_MODEL_TYPE; j < MODEL_TYPE_COUNT; ++j) {
-      syncable::ModelType type_j = syncable::ModelTypeFromInt(j);
-      for (int k = FIRST_REAL_MODEL_TYPE; k < MODEL_TYPE_COUNT; ++k) {
-        syncable::ModelType type_k = syncable::ModelTypeFromInt(k);
-        SCOPED_TRACE(testing::Message() << "Iteration (" << i << "," << j
-                                        << "," << k << ")");
-        mutable_routing_info()->clear();
-        (*mutable_routing_info())[type_i] = browser_sync::GROUP_UI;
-        (*mutable_routing_info())[type_j] = browser_sync::GROUP_DB;
-        (*mutable_routing_info())[type_k] = browser_sync::GROUP_UI;
-        dir->set_last_download_timestamp(type_i, 5000 + j);
-        dir->set_last_download_timestamp(type_j, 1000 + i);
-        dir->set_last_download_timestamp(type_k, 1000 + i);
-
-        ConfigureMockServerConnection();
-        dir->set_store_birthday(mock_server()->store_birthday());
-
-        syncable::ModelTypeBitSet expected_request_types;
-        expected_request_types[j] = true;
-        expected_request_types[k] = true;
-        mock_server()->ExpectGetUpdatesRequestTypes(expected_request_types);
-
-        command_.Execute(session());
-
-        const sync_pb::ClientToServerMessage& r = mock_server()->last_request();
-        EXPECT_EQ(1, mock_server()->GetAndClearNumGetUpdatesRequests());
-        EXPECT_TRUE(r.has_get_updates());
-        EXPECT_TRUE(r.get_updates().has_from_timestamp());
-        EXPECT_EQ(1000 + i, r.get_updates().from_timestamp());
-        EXPECT_TRUE(r.get_updates().has_fetch_folders());
-        EXPECT_TRUE(r.get_updates().fetch_folders());
-        EXPECT_TRUE(r.get_updates().has_requested_types());
-      }
-    }
-  }
-}
-
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/engine/mock_model_safe_workers.cc b/chrome/browser/sync/engine/mock_model_safe_workers.cc
new file mode 100644
index 0000000..bd6a26b
--- /dev/null
+++ b/chrome/browser/sync/engine/mock_model_safe_workers.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/engine/mock_model_safe_workers.h"
+
+namespace browser_sync {
+
+ModelSafeGroup MockUIModelWorker::GetModelSafeGroup() { return GROUP_UI; }
+bool MockUIModelWorker::CurrentThreadIsWorkThread() { return true; }
+
+ModelSafeGroup MockDBModelWorker::GetModelSafeGroup() { return GROUP_DB; }
+bool MockDBModelWorker::CurrentThreadIsWorkThread() { return true; }
+
+MockModelSafeWorkerRegistrar::~MockModelSafeWorkerRegistrar() {}
+
+// static
+MockModelSafeWorkerRegistrar*
+    MockModelSafeWorkerRegistrar::PassiveBookmarks() {
+  ModelSafeRoutingInfo routes;
+  routes[syncable::BOOKMARKS] = GROUP_PASSIVE;
+  MockModelSafeWorkerRegistrar* m = new MockModelSafeWorkerRegistrar(routes);
+  m->passive_worker_ = new ModelSafeWorker();
+  return m;
+}
+
+void MockModelSafeWorkerRegistrar::GetWorkers(
+    std::vector<ModelSafeWorker*>* out) {
+  if (passive_worker_.get())
+    out->push_back(passive_worker_.get());
+}
+
+void MockModelSafeWorkerRegistrar::GetModelSafeRoutingInfo(
+    ModelSafeRoutingInfo* out) {
+  *out = routes_;
+}
+
+MockModelSafeWorkerRegistrar::MockModelSafeWorkerRegistrar(
+    const ModelSafeRoutingInfo& routes) {
+  routes_ = routes;
+}
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/engine/mock_model_safe_workers.h b/chrome/browser/sync/engine/mock_model_safe_workers.h
index 3d0aa8a..a76a51c 100644
--- a/chrome/browser/sync/engine/mock_model_safe_workers.h
+++ b/chrome/browser/sync/engine/mock_model_safe_workers.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,20 +6,38 @@
 #define CHROME_BROWSER_SYNC_ENGINE_MOCK_MODEL_SAFE_WORKERS_H_
 #pragma once
 
+#include <vector>
+
+#include "base/ref_counted.h"
 #include "chrome/browser/sync/engine/model_safe_worker.h"
+#include "chrome/browser/sync/syncable/model_type.h"
 
 namespace browser_sync {
 
 class MockUIModelWorker : public ModelSafeWorker {
  public:
-  virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_UI; }
-  virtual bool CurrentThreadIsWorkThread() { return true; }
+  virtual ModelSafeGroup GetModelSafeGroup();
+  virtual bool CurrentThreadIsWorkThread();
 };
 
 class MockDBModelWorker : public ModelSafeWorker {
  public:
-  virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_DB; }
-  virtual bool CurrentThreadIsWorkThread() { return true; }
+  virtual ModelSafeGroup GetModelSafeGroup();
+  virtual bool CurrentThreadIsWorkThread();
+};
+
+class MockModelSafeWorkerRegistrar : public ModelSafeWorkerRegistrar {
+ public:
+  virtual ~MockModelSafeWorkerRegistrar();
+  static MockModelSafeWorkerRegistrar* PassiveBookmarks();
+  virtual void GetWorkers(std::vector<ModelSafeWorker*>* out);
+  virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out);
+
+ private:
+  explicit MockModelSafeWorkerRegistrar(const ModelSafeRoutingInfo& routes);
+
+  scoped_refptr<ModelSafeWorker> passive_worker_;
+  ModelSafeRoutingInfo routes_;
 };
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.cc b/chrome/browser/sync/engine/net/server_connection_manager.cc
index 20776fe..7f53a29 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.cc
+++ b/chrome/browser/sync/engine/net/server_connection_manager.cc
@@ -255,7 +255,7 @@
 
 void ServerConnectionManager::kill() {
   {
-    AutoLock lock(terminate_all_io_mutex_);
+    base::AutoLock lock(terminate_all_io_mutex_);
     terminate_all_io_ = true;
   }
 }
@@ -294,7 +294,7 @@
                                                   int port,
                                                   bool use_ssl) {
   {
-    AutoLock lock(server_parameters_mutex_);
+    base::AutoLock lock(server_parameters_mutex_);
     sync_server_ = server_url;
     sync_server_port_ = port;
     use_ssl_ = use_ssl;
@@ -305,7 +305,7 @@
 void ServerConnectionManager::GetServerParameters(string* server_url,
                                                   int* port,
                                                   bool* use_ssl) const {
-  AutoLock lock(server_parameters_mutex_);
+  base::AutoLock lock(server_parameters_mutex_);
   if (server_url != NULL)
     *server_url = sync_server_;
   if (port != NULL)
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.h b/chrome/browser/sync/engine/net/server_connection_manager.h
index 6380151..214c622 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.h
+++ b/chrome/browser/sync/engine/net/server_connection_manager.h
@@ -10,8 +10,8 @@
 #include <string>
 
 #include "base/atomicops.h"
-#include "base/lock.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/sync/syncable/syncable_id.h"
 #include "chrome/common/deprecated/event_sys.h"
 #include "chrome/common/deprecated/event_sys-inl.h"
@@ -149,7 +149,7 @@
 //  one instance for every server that you need to talk to.
 class ServerConnectionManager {
  public:
-  typedef EventChannel<ServerConnectionEvent, Lock> Channel;
+  typedef EventChannel<ServerConnectionEvent, base::Lock> Channel;
 
   // buffer_in - will be POSTed
   // buffer_out - string will be overwritten with response
@@ -192,7 +192,7 @@
     void GetServerParams(std::string* server,
                          int* server_port,
                          bool* use_ssl) const {
-      AutoLock lock(scm_->server_parameters_mutex_);
+      base::AutoLock lock(scm_->server_parameters_mutex_);
       server->assign(scm_->sync_server_);
       *server_port = scm_->sync_server_port_;
       *use_ssl = scm_->use_ssl_;
@@ -207,8 +207,6 @@
     RequestTimingInfo* timing_info_;
   };
 
-  // The lifetime of the GaiaAuthenticator must be longer than the instance
-  // of the ServerConnectionManager that you're creating.
   ServerConnectionManager(const std::string& server,
                           int port,
                           bool use_ssl,
@@ -269,7 +267,7 @@
   std::string GetServerHost() const;
 
   bool terminate_all_io() const {
-    AutoLock lock(terminate_all_io_mutex_);
+    base::AutoLock lock(terminate_all_io_mutex_);
     return terminate_all_io_;
   }
 
@@ -284,23 +282,23 @@
 
   void set_auth_token(const std::string& auth_token) {
     // TODO(chron): Consider adding a message loop check here.
-    AutoLock lock(auth_token_mutex_);
+    base::AutoLock lock(auth_token_mutex_);
     auth_token_.assign(auth_token);
   }
 
   const std::string auth_token() const {
-    AutoLock lock(auth_token_mutex_);
+    base::AutoLock lock(auth_token_mutex_);
     return auth_token_;
   }
 
  protected:
   inline std::string proto_sync_path() const {
-    AutoLock lock(path_mutex_);
+    base::AutoLock lock(path_mutex_);
     return proto_sync_path_;
   }
 
   std::string get_time_path() const {
-    AutoLock lock(path_mutex_);
+    base::AutoLock lock(path_mutex_);
     return get_time_path_;
   }
 
@@ -317,7 +315,7 @@
                                 ScopedServerStatusWatcher* watcher);
 
   // Protects access to sync_server_, sync_server_port_ and use_ssl_:
-  mutable Lock server_parameters_mutex_;
+  mutable base::Lock server_parameters_mutex_;
 
   // The sync_server_ is the server that requests will be made to.
   std::string sync_server_;
@@ -335,15 +333,15 @@
   bool use_ssl_;
 
   // The paths we post to.
-  mutable Lock path_mutex_;
+  mutable base::Lock path_mutex_;
   std::string proto_sync_path_;
   std::string get_time_path_;
 
-  mutable Lock auth_token_mutex_;
+  mutable base::Lock auth_token_mutex_;
   // The auth token to use in authenticated requests. Set by the AuthWatcher.
   std::string auth_token_;
 
-  Lock error_count_mutex_;  // Protects error_count_
+  base::Lock error_count_mutex_;  // Protects error_count_
   int error_count_;  // Tracks the number of connection errors.
 
   Channel* const channel_;
@@ -363,7 +361,7 @@
   void NotifyStatusChanged();
   void ResetConnection();
 
-  mutable Lock terminate_all_io_mutex_;
+  mutable base::Lock terminate_all_io_mutex_;
   bool terminate_all_io_;  // When set to true, terminate all connections asap.
   DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager);
 };
diff --git a/chrome/browser/sync/engine/nudge_source.h b/chrome/browser/sync/engine/nudge_source.h
new file mode 100644
index 0000000..3e3b3ae
--- /dev/null
+++ b/chrome/browser/sync/engine/nudge_source.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_ENGINE_NUDGE_SOURCE_H_
+#define CHROME_BROWSER_SYNC_ENGINE_NUDGE_SOURCE_H_
+#pragma once
+
+namespace browser_sync {
+
+namespace s3 {
+
+enum NudgeSource {
+  NUDGE_SOURCE_UNKNOWN = 0,
+  // We received an invalidation message and are nudging to check for updates.
+  NUDGE_SOURCE_NOTIFICATION,
+  // A local change occurred (e.g. bookmark moved).
+  NUDGE_SOURCE_LOCAL,
+  // A previous sync cycle did not fully complete (e.g. HTTP error).
+  NUDGE_SOURCE_CONTINUATION,
+};
+
+}  // namespace s3
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_ENGINE_NUDGE_SOURCE_H_
diff --git a/chrome/browser/sync/engine/polling_constants.cc b/chrome/browser/sync/engine/polling_constants.cc
new file mode 100644
index 0000000..74f24ba
--- /dev/null
+++ b/chrome/browser/sync/engine/polling_constants.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "chrome/browser/sync/engine/polling_constants.h"
+
+namespace browser_sync {
+
+// Server can overwrite these values via client commands.
+// Standard short poll. This is used when XMPP is off.
+// We use high values here to ensure that failure to receive poll updates from
+// the server doesn't result in rapid-fire polling from the client due to low
+// local limits.
+const int64 kDefaultShortPollIntervalSeconds = 3600 * 8;
+// Long poll is used when XMPP is on.
+const int64 kDefaultLongPollIntervalSeconds = 3600 * 12;
+
+// Maximum interval for exponential backoff.
+const int64 kMaxBackoffSeconds = 60 * 60 * 4;  // 4 hours.
+
+// Backoff interval randomization factor.
+const int kBackoffRandomizationFactor = 2;
+
+}  // namespace browser_sync
+
diff --git a/chrome/browser/sync/engine/polling_constants.h b/chrome/browser/sync/engine/polling_constants.h
new file mode 100644
index 0000000..a970f96
--- /dev/null
+++ b/chrome/browser/sync/engine/polling_constants.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Constants used by SyncerThread when polling servers for updates.
+
+#ifndef CHROME_BROWSER_SYNC_ENGINE_POLLING_CONSTANTS_H_
+#define CHROME_BROWSER_SYNC_ENGINE_POLLING_CONSTANTS_H_
+#pragma once
+
+namespace browser_sync {
+
+extern const int64 kDefaultShortPollIntervalSeconds;
+extern const int64 kDefaultLongPollIntervalSeconds;
+extern const int64 kMaxBackoffSeconds;
+extern const int kBackoffRandomizationFactor;
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_ENGINE_POLLING_CONSTANTS_H_
diff --git a/chrome/browser/sync/engine/process_commit_response_command.h b/chrome/browser/sync/engine/process_commit_response_command.h
index bbc85bf..dbba580 100644
--- a/chrome/browser/sync/engine/process_commit_response_command.h
+++ b/chrome/browser/sync/engine/process_commit_response_command.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <set>
+#include <string>
 
 #include "base/basictypes.h"
 #include "chrome/browser/sync/engine/model_changing_syncer_command.h"
@@ -82,7 +83,7 @@
       syncable::MutableEntry* local_entry);
 
   // Helper to extract the final name from the protobufs.
-  const string& GetResultingPostCommitName(
+  const std::string& GetResultingPostCommitName(
       const sync_pb::SyncEntity& committed_entry,
       const CommitResponse_EntryResponse& entry_response);
 
diff --git a/chrome/browser/sync/engine/store_timestamps_command.cc b/chrome/browser/sync/engine/store_timestamps_command.cc
index 8cf8f58..a063bf4 100644
--- a/chrome/browser/sync/engine/store_timestamps_command.cc
+++ b/chrome/browser/sync/engine/store_timestamps_command.cc
@@ -28,28 +28,35 @@
       session->status_controller()->updates_response().get_updates();
 
   sessions::StatusController* status = session->status_controller();
+
+  // Update the progress marker tokens from the server result.  If a marker
+  // was omitted for any one type, that indicates no change from the previous
+  // state.
+  syncable::ModelTypeBitSet forward_progress_types;
+  for (int i = 0; i < updates.new_progress_marker_size(); ++i) {
+    syncable::ModelType model =
+        syncable::GetModelTypeFromExtensionFieldNumber(
+            updates.new_progress_marker(i).data_type_id());
+    if (model == syncable::UNSPECIFIED || model == syncable::TOP_LEVEL_FOLDER) {
+      NOTREACHED() << "Unintelligible server response.";
+      continue;
+    }
+    forward_progress_types[model] = true;
+    dir->SetDownloadProgress(model, updates.new_progress_marker(i));
+  }
+  DCHECK(forward_progress_types.any() ||
+         updates.changes_remaining() == 0);
+  if (VLOG_IS_ON(1)) {
+    VLOG_IF(1, forward_progress_types.any())
+        << "Get Updates got new progress marker for types: "
+        << forward_progress_types.to_string() << " out of possible: "
+        << status->updates_request_types().to_string();
+  }
   if (updates.has_changes_remaining()) {
     int64 changes_left = updates.changes_remaining();
-    VLOG(1) << "Changes remaining:" << changes_left;
+    VLOG(1) << "Changes remaining: " << changes_left;
     status->set_num_server_changes_remaining(changes_left);
   }
-
-  VLOG_IF(1, updates.has_new_timestamp())
-      << "Get Updates got new timestamp: " << updates.new_timestamp()
-      << " for type mask: "
-      << status->updates_request_parameters().data_types.to_string();
-
-  // Update the saved download timestamp for any items we fetched.
-  for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
-    syncable::ModelType model = syncable::ModelTypeFromInt(i);
-    if (status->updates_request_parameters().data_types[i] &&
-        updates.has_new_timestamp() &&
-        (updates.new_timestamp() > dir->last_download_timestamp(model))) {
-      dir->set_last_download_timestamp(model, updates.new_timestamp());
-    }
-    status->set_current_download_timestamp(model,
-        dir->last_download_timestamp(model));
-  }
 }
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 206125b..12fe48d 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -11,14 +11,17 @@
 #include <vector>
 
 #include "base/base64.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
+#include "base/observer_list.h"
 #include "base/scoped_ptr.h"
 #include "base/sha1.h"
+#include "base/string_number_conversions.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "base/utf_string_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/sync/sync_constants.h"
 #include "chrome/browser/sync/engine/all_status.h"
@@ -28,6 +31,9 @@
 #include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h"
 #include "chrome/browser/sync/engine/syncer.h"
 #include "chrome/browser/sync/engine/syncer_thread.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_backend.h"
+#include "chrome/browser/sync/js_event_router.h"
 #include "chrome/browser/sync/notifier/server_notifier_thread.h"
 #include "chrome/browser/sync/notifier/state_writer.h"
 #include "chrome/browser/sync/protocol/app_specifics.pb.h"
@@ -36,17 +42,18 @@
 #include "chrome/browser/sync/protocol/extension_specifics.pb.h"
 #include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
 #include "chrome/browser/sync/protocol/preference_specifics.pb.h"
-#include "chrome/browser/sync/protocol/session_specifics.pb.h"
+#include "chrome/browser/sync/protocol/proto_value_conversions.h"
 #include "chrome/browser/sync/protocol/service_constants.h"
+#include "chrome/browser/sync/protocol/session_specifics.pb.h"
 #include "chrome/browser/sync/protocol/sync.pb.h"
 #include "chrome/browser/sync/protocol/theme_specifics.pb.h"
 #include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
+#include "chrome/browser/sync/sessions/sync_session.h"
 #include "chrome/browser/sync/sessions/sync_session_context.h"
 #include "chrome/browser/sync/syncable/autofill_migration.h"
 #include "chrome/browser/sync/syncable/directory_manager.h"
 #include "chrome/browser/sync/syncable/syncable.h"
 #include "chrome/browser/sync/util/crypto_helpers.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/deprecated/event_sys.h"
 #include "chrome/common/net/gaia/gaia_authenticator.h"
 #include "jingle/notifier/listener/mediator_thread_impl.h"
@@ -84,6 +91,7 @@
 
 static const int kThreadExitTimeoutMsec = 60000;
 static const int kSSLPort = 443;
+static const int kSyncerThreadDelayMsec = 250;
 
 #if defined(OS_CHROMEOS)
 static const int kChromeOSNetworkChangeReactionDelayHackMsec = 5000;
@@ -258,6 +266,42 @@
   return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string);
 }
 
+DictionaryValue* BaseNode::ToValue() const {
+  DictionaryValue* node_info = new DictionaryValue();
+  node_info->SetString("id", base::Int64ToString(GetId()));
+  // TODO(akalin): Return time in a better format.
+  node_info->SetString("modificationTime",
+                       base::Int64ToString(GetModificationTime()));
+  node_info->SetString("parentId", base::Int64ToString(GetParentId()));
+  node_info->SetBoolean("isFolder", GetIsFolder());
+  // TODO(akalin): Add a std::string accessor for the title.
+  node_info->SetString("title", WideToUTF8(GetTitle()));
+  {
+    syncable::ModelType model_type = GetModelType();
+    if (model_type >= syncable::FIRST_REAL_MODEL_TYPE) {
+      node_info->SetString("type", ModelTypeToString(model_type));
+    } else if (model_type == syncable::TOP_LEVEL_FOLDER) {
+      node_info->SetString("type", "Top-level folder");
+    } else if (model_type == syncable::UNSPECIFIED) {
+      node_info->SetString("type", "Unspecified");
+    } else {
+      node_info->SetString("type", base::IntToString(model_type));
+    }
+  }
+  node_info->Set(
+      "specifics",
+      browser_sync::EntitySpecificsToValue(GetEntry()->Get(SPECIFICS)));
+  node_info->SetString("externalId",
+                       base::Int64ToString(GetExternalId()));
+  node_info->SetString("predecessorId",
+                       base::Int64ToString(GetPredecessorId()));
+  node_info->SetString("successorId",
+                       base::Int64ToString(GetSuccessorId()));
+  node_info->SetString("firstChildId",
+                       base::Int64ToString(GetFirstChildId()));
+  return node_info;
+}
+
 void BaseNode::GetFaviconBytes(std::vector<unsigned char>* output) const {
   if (!output)
     return;
@@ -890,65 +934,72 @@
   return transaction_;
 }
 
-// A GaiaAuthenticator that uses HttpPostProviders instead of CURL.
-class BridgedGaiaAuthenticator : public gaia::GaiaAuthenticator {
- public:
-  BridgedGaiaAuthenticator(const string& user_agent, const string& service_id,
-                           const string& gaia_url,
-                           HttpPostProviderFactory* factory)
-      : GaiaAuthenticator(user_agent, service_id, gaia_url),
-        gaia_source_(user_agent), post_factory_(factory) {
-  }
-
-  virtual ~BridgedGaiaAuthenticator() {
-  }
-
-  virtual bool Post(const GURL& url, const string& post_body,
-                    unsigned long* response_code, string* response_body) {
-    string connection_url = "https://";
-    connection_url += url.host();
-    connection_url += url.path();
-    HttpPostProviderInterface* http = post_factory_->Create();
-    http->SetUserAgent(gaia_source_.c_str());
-    // SSL is on 443 for Gaia Posts always.
-    http->SetURL(connection_url.c_str(), kSSLPort);
-    http->SetPostPayload("application/x-www-form-urlencoded",
-                         post_body.length(), post_body.c_str());
-
-    int os_error_code = 0;
-    int int_response_code = 0;
-    if (!http->MakeSynchronousPost(&os_error_code, &int_response_code)) {
-      VLOG(1) << "Http POST failed, error returns: " << os_error_code;
-      return false;
-    }
-    *response_code = static_cast<int>(int_response_code);
-    response_body->assign(http->GetResponseContent(),
-                          http->GetResponseContentLength());
-    post_factory_->Destroy(http);
-    return true;
-  }
-
-  virtual int GetBackoffDelaySeconds(int current_backoff_delay) {
-    return SyncerThread::GetRecommendedDelaySeconds(current_backoff_delay);
-  }
- private:
-  const std::string gaia_source_;
-  scoped_ptr<HttpPostProviderFactory> post_factory_;
-  DISALLOW_COPY_AND_ASSIGN(BridgedGaiaAuthenticator);
-};
+SyncManager::ExtraChangeRecordData::~ExtraChangeRecordData() {}
 
 SyncManager::ChangeRecord::ChangeRecord()
     : id(kInvalidId), action(ACTION_ADD) {}
 
 SyncManager::ChangeRecord::~ChangeRecord() {}
 
-SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData(
-    const sync_pb::PasswordSpecificsData& data)
-    : unencrypted_(data) {
+DictionaryValue* SyncManager::ChangeRecord::ToValue(
+    const BaseTransaction* trans) const {
+  DictionaryValue* value = new DictionaryValue();
+  std::string action_str;
+  switch (action) {
+    case ACTION_ADD:
+      action_str = "Add";
+      break;
+    case ACTION_DELETE:
+      action_str = "Delete";
+      break;
+    case ACTION_UPDATE:
+      action_str = "Update";
+      break;
+    default:
+      NOTREACHED();
+      action_str = "Unknown";
+      break;
+  }
+  value->SetString("action", action_str);
+  Value* node_value = NULL;
+  if (action == ACTION_DELETE) {
+    DictionaryValue* node_dict = new DictionaryValue();
+    node_dict->SetString("id", base::Int64ToString(id));
+    node_dict->Set("specifics",
+                    browser_sync::EntitySpecificsToValue(specifics));
+    if (extra.get()) {
+      node_dict->Set("extra", extra->ToValue());
+    }
+    node_value = node_dict;
+  } else {
+    ReadNode node(trans);
+    if (node.InitByIdLookup(id)) {
+      node_value = node.ToValue();
+    }
+  }
+  if (!node_value) {
+    NOTREACHED();
+    node_value = Value::CreateNullValue();
+  }
+  value->Set("node", node_value);
+  return value;
 }
 
+SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData(
+    const sync_pb::PasswordSpecificsData& data)
+    : unencrypted_(data) {}
+
 SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {}
 
+DictionaryValue* SyncManager::ExtraPasswordChangeRecordData::ToValue() const {
+  return browser_sync::PasswordSpecificsDataToValue(unencrypted_);
+}
+
+const sync_pb::PasswordSpecificsData&
+    SyncManager::ExtraPasswordChangeRecordData::unencrypted() const {
+  return unencrypted_;
+}
+
 //////////////////////////////////////////////////////////////////////////
 // SyncManager's implementation: SyncManager::SyncInternal
 class SyncManager::SyncInternal
@@ -956,13 +1007,14 @@
       public TalkMediator::Delegate,
       public sync_notifier::StateWriter,
       public browser_sync::ChannelEventHandler<syncable::DirectoryChangeEvent>,
+      public browser_sync::JsBackend,
       public SyncEngineEventListener {
   static const int kDefaultNudgeDelayMilliseconds;
   static const int kPreferencesNudgeDelayMilliseconds;
  public:
   explicit SyncInternal(SyncManager* sync_manager)
       : core_message_loop_(NULL),
-        observer_(NULL),
+        parent_router_(NULL),
         sync_manager_(sync_manager),
         registrar_(NULL),
         notification_pending_(false),
@@ -1047,6 +1099,10 @@
   // sync_notifier::StateWriter implementation.
   virtual void WriteState(const std::string& state);
 
+  void AddObserver(SyncManager::Observer* observer);
+
+  void RemoveObserver(SyncManager::Observer* observer);
+
   // Accessors for the private members.
   DirectoryManager* dir_manager() { return share_.dir_manager.get(); }
   SyncAPIServerConnectionManager* connection_manager() {
@@ -1054,7 +1110,6 @@
   }
   SyncerThread* syncer_thread() { return syncer_thread_.get(); }
   TalkMediator* talk_mediator() { return talk_mediator_.get(); }
-  void set_observer(SyncManager::Observer* observer) { observer_ = observer; }
   UserShare* GetUserShare() { return &share_; }
 
   // Return the currently active (validated) username for use with syncable
@@ -1063,16 +1118,7 @@
     return share_.name;
   }
 
-  // Note about SyncManager::Status implementation: Status is a trimmed
-  // down AllStatus::Status, augmented with authentication failure information
-  // gathered from the internal AuthWatcher. The sync UI itself hooks up to
-  // various sources like the AuthWatcher individually, but with syncapi we try
-  // to keep everything status-related in one place. This means we have to
-  // privately manage state about authentication failures, and whenever the
-  // status or status summary is requested we aggregate this state with
-  // AllStatus::Status information.
-  Status ComputeAggregatedStatus();
-  Status::Summary ComputeAggregatedStatusSummary();
+  Status GetStatus();
 
   // See SyncManager::Shutdown for information.
   void Shutdown();
@@ -1080,7 +1126,7 @@
   // Whether we're initialized to the point of being able to accept changes
   // (and hence allow transaction creation). See initialized_ for details.
   bool initialized() const {
-    AutoLock lock(initialized_mutex_);
+    base::AutoLock lock(initialized_mutex_);
     return initialized_;
   }
 
@@ -1158,6 +1204,15 @@
 
   // SyncEngineEventListener implementation.
   virtual void OnSyncEngineEvent(const SyncEngineEvent& event);
+
+  // browser_sync::JsBackend implementation.
+  virtual void SetParentJsEventRouter(browser_sync::JsEventRouter* router);
+  virtual void RemoveParentJsEventRouter();
+  virtual const browser_sync::JsEventRouter* GetParentJsEventRouter() const;
+  virtual void ProcessMessage(const std::string& name,
+                              const browser_sync::JsArgList& args,
+                              const browser_sync::JsEventHandler* sender);
+
  private:
   // Helper to handle the details of initializing the TalkMediator.
   // Must be called only after OpenDirectory() is called.
@@ -1256,6 +1311,10 @@
   // Checks for server reachabilty and requests a nudge.
   void OnIPAddressChangedImpl();
 
+  // Functions called by ProcessMessage().
+  browser_sync::JsArgList ProcessGetNodeByIdMessage(
+      const browser_sync::JsArgList& args);
+
   // We couple the DirectoryManager and username together in a UserShare member
   // so we can return a handle to share_ to clients of the API for use when
   // constructing any transaction type.
@@ -1263,9 +1322,9 @@
 
   MessageLoop* core_message_loop_;
 
-  // Observer registered via SetObserver/RemoveObserver.
-  // WARNING: This can be NULL!
-  SyncManager::Observer* observer_;
+  ObserverList<SyncManager::Observer> observers_;
+
+  browser_sync::JsEventRouter* parent_router_;
 
   // The ServerConnectionManager used to abstract communication between the
   // client (the Syncer) and the sync server.
@@ -1320,7 +1379,7 @@
   // meaning we are ready to accept changes.  Protected by initialized_mutex_
   // as it can get read/set by both the SyncerThread and the AuthWatcherThread.
   bool initialized_;
-  mutable Lock initialized_mutex_;
+  mutable base::Lock initialized_mutex_;
 
   notifier::NotifierOptions notifier_options_;
 
@@ -1333,6 +1392,8 @@
 const int SyncManager::SyncInternal::kDefaultNudgeDelayMilliseconds = 200;
 const int SyncManager::SyncInternal::kPreferencesNudgeDelayMilliseconds = 2000;
 
+SyncManager::Observer::~Observer() {}
+
 SyncManager::SyncManager() {
   data_ = new SyncInternal(this);
 }
@@ -1471,7 +1532,7 @@
       method_factory_.NewRunnableMethod(&SyncInternal::CheckServerReachable));
 
   // Test mode does not use a syncer context or syncer thread.
-  if (!setup_for_test_mode) {
+  if (!setup_for_test_mode_) {
     // Build a SyncSessionContext and store the worker in it.
     VLOG(1) << "Sync is bringing up SyncSessionContext.";
     std::vector<SyncEngineEventListener*> listeners;
@@ -1521,7 +1582,8 @@
       cryptographer->SetKeys(nigori.encrypted());
     } else {
       cryptographer->SetPendingKeys(nigori.encrypted());
-      observer_->OnPassphraseRequired(true);
+      FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                        OnPassphraseRequired(true));
     }
   }
 }
@@ -1541,15 +1603,15 @@
   // between their respective threads to call MarkAndNotify.  We need to make
   // sure the observer is notified once and only once.
   {
-    AutoLock lock(initialized_mutex_);
+    base::AutoLock lock(initialized_mutex_);
     if (initialized_)
       return;
     initialized_ = true;
   }
 
   // Notify that initialization is complete.
-  if (observer_)
-    observer_->OnInitializationComplete();
+  FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                    OnInitializationComplete());
 }
 
 void SyncManager::SyncInternal::SendPendingXMPPNotification(
@@ -1592,8 +1654,8 @@
   bool share_opened = dir_manager()->Open(username_for_share());
   DCHECK(share_opened);
   if (!share_opened) {
-    if (observer_)
-      observer_->OnStopSyncingPermanently();
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnStopSyncingPermanently());
 
     LOG(ERROR) << "Could not open share for:" << username_for_share();
     return false;
@@ -1625,7 +1687,9 @@
   if (!OpenDirectory())
     return false;
 
-  UpdateCredentials(credentials);
+  if (!setup_for_test_mode_) {
+    UpdateCredentials(credentials);
+  }
   return true;
 }
 
@@ -1673,9 +1737,9 @@
 }
 
 void SyncManager::SyncInternal::RaiseAuthNeededEvent() {
-  if (observer_) {
-    observer_->OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS));
-  }
+  FOR_EACH_OBSERVER(
+      SyncManager::Observer, observers_,
+      OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS)));
 }
 
 void SyncManager::SyncInternal::SetUsingExplicitPassphrasePrefForMigration() {
@@ -1697,7 +1761,8 @@
   KeyParams params = {"localhost", "dummy", passphrase};
   if (cryptographer->has_pending_keys()) {
     if (!cryptographer->DecryptPendingKeys(params)) {
-      observer_->OnPassphraseRequired(true);
+      FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                        OnPassphraseRequired(true));
       return;
     }
 
@@ -1739,7 +1804,8 @@
 
   std::string bootstrap_token;
   cryptographer->GetBootstrapToken(&bootstrap_token);
-  observer_->OnPassphraseAccepted(bootstrap_token);
+  FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                    OnPassphraseAccepted(bootstrap_token));
 }
 
 bool SyncManager::SyncInternal::IsUsingExplicitPassphrase() {
@@ -1782,12 +1848,16 @@
   delete data_;
 }
 
-void SyncManager::SetObserver(Observer* observer) {
-  data_->set_observer(observer);
+void SyncManager::AddObserver(Observer* observer) {
+  data_->AddObserver(observer);
 }
 
-void SyncManager::RemoveObserver() {
-  data_->set_observer(NULL);
+void SyncManager::RemoveObserver(Observer* observer) {
+  data_->RemoveObserver(observer);
+}
+
+browser_sync::JsBackend* SyncManager::GetJsBackend() {
+  return data_;
 }
 
 void SyncManager::Shutdown() {
@@ -1901,13 +1971,14 @@
   // This allows work to be performed without holding the WriteTransaction lock
   // but before the transaction is finished.
   DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::TRANSACTION_COMPLETE);
-  if (!observer_)
+  if (observers_.size() <= 0)
     return;
 
   // Call commit
   for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
     if (model_has_change_.test(i)) {
-      observer_->OnChangesComplete(syncable::ModelTypeFromInt(i));
+      FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                        OnChangesComplete(syncable::ModelTypeFromInt(i)));
       model_has_change_.reset(i);
     }
   }
@@ -1919,15 +1990,14 @@
   if (event.what_happened == ServerConnectionEvent::STATUS_CHANGED) {
     if (event.connection_code ==
         browser_sync::HttpResponse::SERVER_CONNECTION_OK) {
-      if (observer_) {
-        observer_->OnAuthError(AuthError::None());
-      }
+      FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                        OnAuthError(AuthError::None()));
     }
 
     if (event.connection_code == browser_sync::HttpResponse::SYNC_AUTH_ERROR) {
-      if (observer_) {
-        observer_->OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS));
-      }
+      FOR_EACH_OBSERVER(
+          SyncManager::Observer, observers_,
+          OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS)));
     }
   }
 }
@@ -1938,7 +2008,7 @@
   // falls out of scope. It happens while the channel mutex is still held,
   // and while the transaction mutex is held, so it cannot be re-entrant.
   DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::TRANSACTION_ENDING);
-  if (!observer_ || ChangeBuffersAreEmpty())
+  if (observers_.size() <= 0 || ChangeBuffersAreEmpty())
     return;
 
   // This will continue the WriteTransaction using a read only wrapper.
@@ -1954,8 +2024,10 @@
     vector<ChangeRecord> ordered_changes;
     change_buffers_[i].GetAllChangesInTreeOrder(&trans, &ordered_changes);
     if (!ordered_changes.empty()) {
-      observer_->OnChangesApplied(syncable::ModelTypeFromInt(i), &trans,
-                                  &ordered_changes[0], ordered_changes.size());
+      FOR_EACH_OBSERVER(
+          SyncManager::Observer, observers_,
+          OnChangesApplied(syncable::ModelTypeFromInt(i), &trans,
+                           &ordered_changes[0], ordered_changes.size()));
       model_has_change_.set(i, true);
     }
     change_buffers_[i].Clear();
@@ -2064,52 +2136,13 @@
   }
 }
 
-SyncManager::Status::Summary
-SyncManager::SyncInternal::ComputeAggregatedStatusSummary() {
-  switch (allstatus_.status().icon) {
-    case AllStatus::OFFLINE:
-      return Status::OFFLINE;
-    case AllStatus::OFFLINE_UNSYNCED:
-      return Status::OFFLINE_UNSYNCED;
-    case AllStatus::SYNCING:
-      return Status::SYNCING;
-    case AllStatus::READY:
-      return Status::READY;
-    case AllStatus::CONFLICT:
-      return Status::CONFLICT;
-    case AllStatus::OFFLINE_UNUSABLE:
-      return Status::OFFLINE_UNUSABLE;
-    default:
-      return Status::INVALID;
-  }
-}
-
-SyncManager::Status SyncManager::SyncInternal::ComputeAggregatedStatus() {
-  Status return_status =
-      { ComputeAggregatedStatusSummary(),
-        allstatus_.status().authenticated,
-        allstatus_.status().server_up,
-        allstatus_.status().server_reachable,
-        allstatus_.status().server_broken,
-        allstatus_.status().notifications_enabled,
-        allstatus_.status().notifications_received,
-        allstatus_.status().notifications_sent,
-        allstatus_.status().unsynced_count,
-        allstatus_.status().conflicting_count,
-        allstatus_.status().syncing,
-        allstatus_.status().initial_sync_ended,
-        allstatus_.status().syncer_stuck,
-        allstatus_.status().updates_available,
-        allstatus_.status().updates_received,
-        allstatus_.status().disk_full,
-        false,   // TODO(ncarter): invalid store?
-        allstatus_.status().max_consecutive_errors};
-  return return_status;
+SyncManager::Status SyncManager::SyncInternal::GetStatus() {
+  return allstatus_.status();
 }
 
 void SyncManager::SyncInternal::OnSyncEngineEvent(
     const SyncEngineEvent& event) {
-  if (!observer_)
+  if (observers_.size() <= 0)
     return;
 
   // Only send an event if this is due to a cycle ending and this cycle
@@ -2142,9 +2175,11 @@
       // If we've completed a sync cycle and the cryptographer isn't ready yet,
       // prompt the user for a passphrase.
       if (cryptographer->has_pending_keys()) {
-        observer_->OnPassphraseRequired(true);
+        FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                          OnPassphraseRequired(true));
       } else if (!cryptographer->is_ready()) {
-        observer_->OnPassphraseRequired(false);
+        FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                          OnPassphraseRequired(false));
       }
     }
 
@@ -2152,7 +2187,8 @@
       return;
 
     if (!event.snapshot->has_more_to_sync) {
-      observer_->OnSyncCycleCompleted(event.snapshot);
+      FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                        OnSyncCycleCompleted(event.snapshot));
     }
 
     if (notifier_options_.notification_method !=
@@ -2171,36 +2207,134 @@
   }
 
   if (event.what_happened == SyncEngineEvent::SYNCER_THREAD_PAUSED) {
-    observer_->OnPaused();
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnPaused());
     return;
   }
 
   if (event.what_happened == SyncEngineEvent::SYNCER_THREAD_RESUMED) {
-    observer_->OnResumed();
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnResumed());
     return;
   }
 
   if (event.what_happened == SyncEngineEvent::STOP_SYNCING_PERMANENTLY) {
-    observer_->OnStopSyncingPermanently();
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnStopSyncingPermanently());
     return;
   }
 
   if (event.what_happened == SyncEngineEvent::CLEAR_SERVER_DATA_SUCCEEDED) {
-    observer_->OnClearServerDataSucceeded();
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnClearServerDataSucceeded());
     return;
   }
 
   if (event.what_happened == SyncEngineEvent::CLEAR_SERVER_DATA_FAILED) {
-    observer_->OnClearServerDataFailed();
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnClearServerDataFailed());
     return;
   }
 
   if (event.what_happened == SyncEngineEvent::UPDATED_TOKEN) {
-    observer_->OnUpdatedToken(event.updated_token);
+    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                      OnUpdatedToken(event.updated_token));
     return;
   }
 }
 
+void SyncManager::SyncInternal::SetParentJsEventRouter(
+    browser_sync::JsEventRouter* router) {
+  DCHECK(router);
+  parent_router_ = router;
+}
+
+void SyncManager::SyncInternal::RemoveParentJsEventRouter() {
+  parent_router_ = NULL;
+}
+
+const browser_sync::JsEventRouter*
+    SyncManager::SyncInternal::GetParentJsEventRouter() const {
+  return parent_router_;
+}
+
+namespace {
+
+void LogNoRouter(const std::string& name,
+                 const browser_sync::JsArgList& args) {
+  VLOG(1) << "No parent router; not replying to message " << name
+          << " with args " << args.ToString();
+}
+
+}  // namespace
+
+void SyncManager::SyncInternal::ProcessMessage(
+    const std::string& name, const browser_sync::JsArgList& args,
+    const browser_sync::JsEventHandler* sender) {
+  DCHECK(initialized_);
+  if (name == "getNotificationState") {
+    if (!parent_router_) {
+      LogNoRouter(name, args);
+      return;
+    }
+    bool notifications_enabled = allstatus_.status().notifications_enabled;
+    ListValue return_args;
+    return_args.Append(Value::CreateBooleanValue(notifications_enabled));
+    parent_router_->RouteJsEvent(
+        "onGetNotificationStateFinished",
+        browser_sync::JsArgList(return_args), sender);
+  } else if (name == "getRootNode") {
+    if (!parent_router_) {
+      LogNoRouter(name, args);
+      return;
+    }
+    ReadTransaction trans(GetUserShare());
+    ReadNode root(&trans);
+    root.InitByRootLookup();
+    ListValue return_args;
+    return_args.Append(root.ToValue());
+    parent_router_->RouteJsEvent(
+        "onGetRootNodeFinished",
+        browser_sync::JsArgList(return_args), sender);
+  } else if (name == "getNodeById") {
+    if (!parent_router_) {
+      LogNoRouter(name, args);
+      return;
+    }
+    parent_router_->RouteJsEvent(
+        "onGetNodeByIdFinished", ProcessGetNodeByIdMessage(args), sender);
+  } else {
+    VLOG(1) << "Dropping unknown message " << name
+              << " with args " << args.ToString();
+  }
+}
+
+browser_sync::JsArgList SyncManager::SyncInternal::ProcessGetNodeByIdMessage(
+    const browser_sync::JsArgList& args) {
+  ListValue null_return_args_list;
+  null_return_args_list.Append(Value::CreateNullValue());
+  browser_sync::JsArgList null_return_args(null_return_args_list);
+  std::string id_str;
+  if (!args.Get().GetString(0, &id_str)) {
+    return null_return_args;
+  }
+  int64 id;
+  if (!base::StringToInt64(id_str, &id)) {
+    return null_return_args;
+  }
+  if (id == kInvalidId) {
+    return null_return_args;
+  }
+  ReadTransaction trans(GetUserShare());
+  ReadNode node(&trans);
+  if (!node.InitByIdLookup(id)) {
+    return null_return_args;
+  }
+  ListValue return_args;
+  return_args.Append(node.ToValue());
+  return browser_sync::JsArgList(return_args);
+}
+
 void SyncManager::SyncInternal::OnNotificationStateChange(
     bool notifications_enabled) {
   VLOG(1) << "P2P: Notifications enabled = "
@@ -2209,6 +2343,13 @@
   if (syncer_thread()) {
     syncer_thread()->SetNotificationsEnabled(notifications_enabled);
   }
+  if (parent_router_) {
+    ListValue args;
+    args.Append(Value::CreateBooleanValue(notifications_enabled));
+    // TODO(akalin): Tidy up grammar in event names.
+    parent_router_->RouteJsEvent("onSyncNotificationStateChange",
+                                 browser_sync::JsArgList(args), NULL);
+  }
   if ((notifier_options_.notification_method !=
        notifier::NOTIFICATION_SERVER) && notifications_enabled) {
     // Nudge the syncer thread when notifications are enabled, in case there is
@@ -2242,22 +2383,29 @@
 
 void SyncManager::SyncInternal::OnIncomingNotification(
     const IncomingNotificationData& notification_data) {
-  syncable::ModelTypeBitSet model_types;
+  browser_sync::sessions::TypePayloadMap model_types_with_payloads;
 
   // Check if the service url is a sync URL.  An empty service URL is
   // treated as a legacy sync notification.  If we're listening to
   // server-issued notifications, no need to check the service_url.
   if (notifier_options_.notification_method ==
       notifier::NOTIFICATION_SERVER) {
-    VLOG(1) << "Sync received server notification: " <<
+    VLOG(1) << "Sync received server notification from " <<
+        notification_data.service_url << ": " <<
+        notification_data.service_specific_data;
+    syncable::ModelTypeBitSet model_types;
+    const std::string& model_type_list = notification_data.service_url;
+    const std::string& notification_payload =
         notification_data.service_specific_data;
 
-    if (!syncable::ModelTypeBitSetFromString(
-            notification_data.service_specific_data,
-            &model_types)) {
+    if (!syncable::ModelTypeBitSetFromString(model_type_list, &model_types)) {
       LOG(DFATAL) << "Could not extract model types from server data.";
       model_types.set();
     }
+
+    model_types_with_payloads =
+        browser_sync::sessions::MakeTypePayloadMapFromBitSet(model_types,
+            notification_payload);
   } else if (notification_data.service_url.empty() ||
              (notification_data.service_url ==
               browser_sync::kSyncLegacyServiceUrl) ||
@@ -2265,25 +2413,44 @@
               browser_sync::kSyncServiceUrl)) {
     VLOG(1) << "Sync received P2P notification.";
 
-    // Catch for sync integration tests (uses p2p). Just set all datatypes.
-    model_types.set();
+    // Catch for sync integration tests (uses p2p). Just set all enabled
+    // datatypes.
+    ModelSafeRoutingInfo routes;
+    registrar_->GetModelSafeRoutingInfo(&routes);
+    model_types_with_payloads =
+        browser_sync::sessions::MakeTypePayloadMapFromRoutingInfo(routes,
+            std::string());
   } else {
     LOG(WARNING) << "Notification fron unexpected source: "
                  << notification_data.service_url;
   }
 
-  if (model_types.any()) {
+  if (!model_types_with_payloads.empty()) {
     if (syncer_thread()) {
-     // Introduce a delay to help coalesce initial notifications.
-     syncer_thread()->NudgeSyncerWithDataTypes(
-         250,
-         SyncerThread::kNotification,
-         model_types);
+      syncer_thread()->NudgeSyncerWithPayloads(
+          kSyncerThreadDelayMsec,
+          SyncerThread::kNotification,
+          model_types_with_payloads);
     }
     allstatus_.IncrementNotificationsReceived();
   } else {
     LOG(WARNING) << "Sync received notification without any type information.";
   }
+
+  if (parent_router_) {
+    ListValue args;
+    ListValue* changed_types = new ListValue();
+    args.Append(changed_types);
+    for (browser_sync::sessions::TypePayloadMap::const_iterator
+             it = model_types_with_payloads.begin();
+         it != model_types_with_payloads.end(); ++it) {
+      const std::string& model_type_str =
+          syncable::ModelTypeToString(it->first);
+      changed_types->Append(Value::CreateStringValue(model_type_str));
+    }
+    parent_router_->RouteJsEvent("onSyncIncomingNotification",
+                                 browser_sync::JsArgList(args), NULL);
+  }
 }
 
 void SyncManager::SyncInternal::OnOutgoingNotification() {
@@ -2309,12 +2476,22 @@
   lookup->SaveChanges();
 }
 
+void SyncManager::SyncInternal::AddObserver(
+    SyncManager::Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void SyncManager::SyncInternal::RemoveObserver(
+    SyncManager::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 SyncManager::Status::Summary SyncManager::GetStatusSummary() const {
-  return data_->ComputeAggregatedStatusSummary();
+  return data_->GetStatus().summary;
 }
 
 SyncManager::Status SyncManager::GetDetailedStatus() const {
-  return data_->ComputeAggregatedStatus();
+  return data_->GetStatus();
 }
 
 SyncManager::SyncInternal* SyncManager::GetImpl() const { return data_; }
@@ -2357,4 +2534,17 @@
   return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0);
 }
 
+void SyncManager::TriggerOnNotificationStateChangeForTest(
+    bool notifications_enabled) {
+  data_->OnNotificationStateChange(notifications_enabled);
+}
+
+void SyncManager::TriggerOnIncomingNotificationForTest(
+    const syncable::ModelTypeBitSet& model_types) {
+  IncomingNotificationData notification_data;
+  notification_data.service_url = model_types.to_string();
+  // Here we rely on the default notification method being SERVER.
+  data_->OnIncomingNotification(notification_data);
+}
+
 }  // namespace sync_api
diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h
index d86ed71..2be895c 100644
--- a/chrome/browser/sync/engine/syncapi.h
+++ b/chrome/browser/sync/engine/syncapi.h
@@ -53,9 +53,11 @@
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "googleurl/src/gurl.h"
 
+class DictionaryValue;
 class FilePath;
 
 namespace browser_sync {
+class JsBackend;
 class ModelSafeWorkerRegistrar;
 
 namespace sessions {
@@ -250,6 +252,10 @@
   virtual const syncable::Entry* GetEntry() const = 0;
   virtual const BaseTransaction* GetTransaction() const = 0;
 
+  // Dumps all node info into a DictionaryValue and returns it.
+  // Transfers ownership of the DictionaryValue to the caller.
+  DictionaryValue* ToValue() const;
+
  protected:
   BaseNode();
   virtual ~BaseNode();
@@ -586,8 +592,10 @@
   // wrapper / add a templated method to return unencrypted protobufs.
   class ExtraChangeRecordData {
    public:
-    ExtraChangeRecordData() {}
-    virtual ~ExtraChangeRecordData() {}
+    virtual ~ExtraChangeRecordData();
+
+    // Transfers ownership of the DictionaryValue to the caller.
+    virtual DictionaryValue* ToValue() const = 0;
   };
 
   // ChangeRecord indicates a single item that changed as a result of a sync
@@ -603,6 +611,9 @@
     ChangeRecord();
     ~ChangeRecord();
 
+    // Transfers ownership of the DictionaryValue to the caller.
+    DictionaryValue* ToValue(const BaseTransaction* trans) const;
+
     int64 id;
     Action action;
     sync_pb::EntitySpecifics specifics;
@@ -616,9 +627,12 @@
     explicit ExtraPasswordChangeRecordData(
         const sync_pb::PasswordSpecificsData& data);
     virtual ~ExtraPasswordChangeRecordData();
-    const sync_pb::PasswordSpecificsData& unencrypted() {
-      return unencrypted_;
-    }
+
+    // Transfers ownership of the DictionaryValue to the caller.
+    virtual DictionaryValue* ToValue() const;
+
+    const sync_pb::PasswordSpecificsData& unencrypted() const;
+
    private:
     sync_pb::PasswordSpecificsData unencrypted_;
   };
@@ -648,32 +662,43 @@
       // Can't connect to server, and we haven't completed the initial
       // sync yet.  So there's nothing we can do but wait for the server.
       OFFLINE_UNUSABLE,
-    };
-    Summary summary;
 
-    // Various server related information.
+      SUMMARY_STATUS_COUNT,
+    };
+
+    Summary summary;
     bool authenticated;      // Successfully authenticated via GAIA.
     bool server_up;          // True if we have received at least one good
                              // reply from the server.
     bool server_reachable;   // True if we received any reply from the server.
     bool server_broken;      // True of the syncer is stopped because of server
                              // issues.
-
     bool notifications_enabled;  // True only if subscribed for notifications.
+
+    // Notifications counters updated by the actions in synapi.
     int notifications_received;
     int notifications_sent;
 
-    // Various Syncer data.
+    // The max number of consecutive errors from any component.
+    int max_consecutive_errors;
+
     int unsynced_count;
+
     int conflicting_count;
     bool syncing;
+    // True after a client has done a first sync.
     bool initial_sync_ended;
+    // True if any syncer is stuck.
     bool syncer_stuck;
+
+    // Total updates available.  If zero, nothing left to download.
     int64 updates_available;
-    int64 updates_received;
+    // Total updates received by the syncer since browser start.
+    int updates_received;
+
+    // Of updates_received, how many were tombstones.
+    int tombstone_updates_received;
     bool disk_full;
-    bool invalid_store;
-    int max_consecutive_errors;  // The max number of errors from any component.
   };
 
   // An interface the embedding application implements to receive notifications
@@ -686,9 +711,6 @@
   // to dispatch to a native thread or synchronize accordingly.
   class Observer {
    public:
-    Observer() { }
-    virtual ~Observer() { }
-
     // Notify the observer that changes have been applied to the sync model.
     //
     // This will be invoked on the same thread as on which ApplyChanges was
@@ -783,8 +805,8 @@
     virtual void OnClearServerDataSucceeded() = 0;
     virtual void OnClearServerDataFailed() = 0;
 
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Observer);
+   protected:
+    virtual ~Observer();
   };
 
   // Create an uninitialized SyncManager.  Callers must Init() before using.
@@ -881,12 +903,46 @@
   // Adds a listener to be notified of sync events.
   // NOTE: It is OK (in fact, it's probably a good idea) to call this before
   // having received OnInitializationCompleted.
-  void SetObserver(Observer* observer);
+  void AddObserver(Observer* observer);
 
-  // Remove the observer set by SetObserver (no op if none was set).
-  // Make sure to call this if the Observer set in SetObserver is being
-  // destroyed so the SyncManager doesn't potentially dereference garbage.
-  void RemoveObserver();
+  // Remove the given observer.  Make sure to call this if the
+  // Observer is being destroyed so the SyncManager doesn't
+  // potentially dereference garbage.
+  void RemoveObserver(Observer* observer);
+
+  // Returns a pointer to the JsBackend (which is owned by the sync
+  // manager).  Never returns NULL.  The following events are sent by
+  // the returned backend:
+  //
+  // onSyncNotificationStateChange(boolean notificationsEnabled):
+  //   Sent when notifications are enabled or disabled.
+  //
+  // onSyncIncomingNotification(array changedTypes):
+  //   Sent when an incoming notification arrives.  |changedTypes|
+  //   contains a list of sync types (strings) which have changed.
+  //
+  // The following messages are processed by the returned backend:
+  //
+  // getNotificationState():
+  //   If there is a parent router, sends the
+  //   onGetNotificationStateFinished(boolean notificationsEnabled)
+  //   event to |sender| via the parent router with whether or not
+  //   notifications are enabled.
+  //
+  // getRootNode():
+  //   If there is a parent router, sends the
+  //   onGetRootNodeFinished(dictionary nodeInfo) event to |sender|
+  //   via the parent router with information on the root node.
+  //
+  // getNodeById(string id):
+  //   If there is a parent router, sends the
+  //   onGetNodeByIdFinished(dictionary nodeInfo) event to |sender|
+  //   via the parent router with information on the node with the
+  //   given id (metahandle), if the id is valid and a node with that
+  //   id exists.  Otherwise, calls onGetNodeByIdFinished(null).
+  //
+  // All other messages are dropped.
+  browser_sync::JsBackend* GetJsBackend();
 
   // Status-related getters. Typically GetStatusSummary will suffice, but
   // GetDetailedSyncStatus can be useful for gathering debug-level details of
@@ -914,6 +970,14 @@
   // any remaining unsynced items.
   bool HasUnsyncedItems() const;
 
+  // Functions used for testing.
+
+  void TriggerOnNotificationStateChangeForTest(
+      bool notifications_enabled);
+
+  void TriggerOnIncomingNotificationForTest(
+      const syncable::ModelTypeBitSet& model_types);
+
  private:
   // An opaque pointer to the nested private class.
   SyncInternal* data_;
diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc
index b83c501..c2e3584 100644
--- a/chrome/browser/sync/engine/syncapi_unittest.cc
+++ b/chrome/browser/sync/engine/syncapi_unittest.cc
@@ -6,20 +6,71 @@
 // functionality is provided by the Syncable layer, which has its own
 // unit tests. We'll test SyncApi specific things in this harness.
 
+#include "base/basictypes.h"
+#include "base/message_loop.h"
 #include "base/scoped_ptr.h"
 #include "base/scoped_temp_dir.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_backend.h"
+#include "chrome/browser/sync/js_event_handler.h"
+#include "chrome/browser/sync/js_event_router.h"
+#include "chrome/browser/sync/js_test_util.h"
 #include "chrome/browser/sync/protocol/password_specifics.pb.h"
+#include "chrome/browser/sync/protocol/proto_value_conversions.h"
 #include "chrome/browser/sync/syncable/directory_manager.h"
 #include "chrome/browser/sync/syncable/syncable.h"
 #include "chrome/test/sync/engine/test_directory_setter_upper.h"
-
+#include "chrome/test/values_test_util.h"
+#include "jingle/notifier/base/notifier_options.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using browser_sync::HasArgsAsList;
 using browser_sync::KeyParams;
+using browser_sync::JsArgList;
+using browser_sync::MockJsEventHandler;
+using browser_sync::MockJsEventRouter;
+using test::ExpectDictionaryValue;
+using test::ExpectStringValue;
+using testing::_;
+using testing::Invoke;
+using testing::SaveArg;
+using testing::StrictMock;
 
 namespace sync_api {
 
+namespace {
+
+void ExpectInt64Value(int64 expected_value,
+                      const DictionaryValue& value, const std::string& key) {
+  std::string int64_str;
+  EXPECT_TRUE(value.GetString(key, &int64_str));
+  int64 val = 0;
+  EXPECT_TRUE(base::StringToInt64(int64_str, &val));
+  EXPECT_EQ(expected_value, val);
+}
+
+// Makes a non-folder child of the root node.  Returns the id of the
+// newly-created node.
+int64 MakeNode(UserShare* share,
+               syncable::ModelType model_type,
+               const std::string& client_tag) {
+  WriteTransaction trans(share);
+  ReadNode root_node(&trans);
+  root_node.InitByRootLookup();
+  WriteNode node(&trans);
+  EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag));
+  node.SetIsFolder(false);
+  return node.GetId();
+}
+
+}  // namespace
+
 class SyncApiTest : public testing::Test {
  public:
   virtual void SetUp() {
@@ -59,16 +110,14 @@
 
 TEST_F(SyncApiTest, BasicTagWrite) {
   {
-    WriteTransaction trans(&share_);
+    ReadTransaction trans(&share_);
     ReadNode root_node(&trans);
     root_node.InitByRootLookup();
     EXPECT_EQ(root_node.GetFirstChildId(), 0);
-
-    WriteNode wnode(&trans);
-    EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS,
-        root_node, "testtag"));
-    wnode.SetIsFolder(false);
   }
+
+  ignore_result(MakeNode(&share_, syncable::BOOKMARKS, "testtag"));
+
   {
     ReadTransaction trans(&share_);
     ReadNode node(&trans);
@@ -104,22 +153,12 @@
     ReadNode root_node(&trans);
     root_node.InitByRootLookup();
     EXPECT_EQ(root_node.GetFirstChildId(), 0);
-
-    WriteNode bookmarknode(&trans);
-    EXPECT_TRUE(bookmarknode.InitUniqueByCreation(syncable::BOOKMARKS,
-        root_node, "collideme"));
-    bookmarknode.SetIsFolder(false);
-
-    WriteNode prefnode(&trans);
-    EXPECT_TRUE(prefnode.InitUniqueByCreation(syncable::PREFERENCES,
-        root_node, "collideme"));
-    prefnode.SetIsFolder(false);
-
-    WriteNode autofillnode(&trans);
-    EXPECT_TRUE(autofillnode.InitUniqueByCreation(syncable::AUTOFILL,
-        root_node, "collideme"));
-    autofillnode.SetIsFolder(false);
   }
+
+  ignore_result(MakeNode(&share_, syncable::BOOKMARKS, "collideme"));
+  ignore_result(MakeNode(&share_, syncable::PREFERENCES, "collideme"));
+  ignore_result(MakeNode(&share_, syncable::AUTOFILL, "collideme"));
+
   {
     ReadTransaction trans(&share_);
 
@@ -264,4 +303,506 @@
   }
 }
 
+namespace {
+
+void CheckNodeValue(const BaseNode& node, const DictionaryValue& value) {
+  ExpectInt64Value(node.GetId(), value, "id");
+  ExpectInt64Value(node.GetModificationTime(), value, "modificationTime");
+  ExpectInt64Value(node.GetParentId(), value, "parentId");
+  {
+    bool is_folder = false;
+    EXPECT_TRUE(value.GetBoolean("isFolder", &is_folder));
+    EXPECT_EQ(node.GetIsFolder(), is_folder);
+  }
+  ExpectStringValue(WideToUTF8(node.GetTitle()), value, "title");
+  {
+    syncable::ModelType expected_model_type = node.GetModelType();
+    std::string type_str;
+    EXPECT_TRUE(value.GetString("type", &type_str));
+    if (expected_model_type >= syncable::FIRST_REAL_MODEL_TYPE) {
+      syncable::ModelType model_type =
+          syncable::ModelTypeFromString(type_str);
+      EXPECT_EQ(expected_model_type, model_type);
+    } else if (expected_model_type == syncable::TOP_LEVEL_FOLDER) {
+      EXPECT_EQ("Top-level folder", type_str);
+    } else if (expected_model_type == syncable::UNSPECIFIED) {
+      EXPECT_EQ("Unspecified", type_str);
+    } else {
+      ADD_FAILURE();
+    }
+  }
+  {
+    scoped_ptr<DictionaryValue> expected_specifics(
+        browser_sync::EntitySpecificsToValue(
+            node.GetEntry()->Get(syncable::SPECIFICS)));
+    Value* specifics = NULL;
+    EXPECT_TRUE(value.Get("specifics", &specifics));
+    EXPECT_TRUE(Value::Equals(specifics, expected_specifics.get()));
+  }
+  ExpectInt64Value(node.GetExternalId(), value, "externalId");
+  ExpectInt64Value(node.GetPredecessorId(), value, "predecessorId");
+  ExpectInt64Value(node.GetSuccessorId(), value, "successorId");
+  ExpectInt64Value(node.GetFirstChildId(), value, "firstChildId");
+  EXPECT_EQ(11u, value.size());
+}
+
+}  // namespace
+
+TEST_F(SyncApiTest, BaseNodeToValue) {
+  ReadTransaction trans(&share_);
+  ReadNode node(&trans);
+  node.InitByRootLookup();
+  scoped_ptr<DictionaryValue> value(node.ToValue());
+  if (value.get()) {
+    CheckNodeValue(node, *value);
+  } else {
+    ADD_FAILURE();
+  }
+}
+
+namespace {
+
+void ExpectChangeRecordActionValue(SyncManager::ChangeRecord::Action
+                                       expected_value,
+                                   const DictionaryValue& value,
+                                   const std::string& key) {
+  std::string str_value;
+  EXPECT_TRUE(value.GetString(key, &str_value));
+  switch (expected_value) {
+    case SyncManager::ChangeRecord::ACTION_ADD:
+      EXPECT_EQ("Add", str_value);
+      break;
+    case SyncManager::ChangeRecord::ACTION_UPDATE:
+      EXPECT_EQ("Update", str_value);
+      break;
+    case SyncManager::ChangeRecord::ACTION_DELETE:
+      EXPECT_EQ("Delete", str_value);
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+
+void CheckNonDeleteChangeRecordValue(const SyncManager::ChangeRecord& record,
+                                     const DictionaryValue& value,
+                                     BaseTransaction* trans) {
+  EXPECT_NE(SyncManager::ChangeRecord::ACTION_DELETE, record.action);
+  ExpectChangeRecordActionValue(record.action, value, "action");
+  {
+    ReadNode node(trans);
+    EXPECT_TRUE(node.InitByIdLookup(record.id));
+    scoped_ptr<DictionaryValue> expected_node_value(node.ToValue());
+    ExpectDictionaryValue(*expected_node_value, value, "node");
+  }
+}
+
+void CheckDeleteChangeRecordValue(const SyncManager::ChangeRecord& record,
+                                  const DictionaryValue& value) {
+  EXPECT_EQ(SyncManager::ChangeRecord::ACTION_DELETE, record.action);
+  ExpectChangeRecordActionValue(record.action, value, "action");
+  DictionaryValue* node_value = NULL;
+  EXPECT_TRUE(value.GetDictionary("node", &node_value));
+  if (node_value) {
+    ExpectInt64Value(record.id, *node_value, "id");
+    scoped_ptr<DictionaryValue> expected_specifics_value(
+        browser_sync::EntitySpecificsToValue(record.specifics));
+    ExpectDictionaryValue(*expected_specifics_value,
+                          *node_value, "specifics");
+    scoped_ptr<DictionaryValue> expected_extra_value;
+    if (record.extra.get()) {
+      expected_extra_value.reset(record.extra->ToValue());
+    }
+    Value* extra_value = NULL;
+    EXPECT_EQ(record.extra.get() != NULL,
+              node_value->Get("extra", &extra_value));
+    EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get()));
+  }
+}
+
+class MockExtraChangeRecordData : public SyncManager::ExtraChangeRecordData {
+ public:
+  MOCK_CONST_METHOD0(ToValue, DictionaryValue*());
+};
+
+}  // namespace
+
+TEST_F(SyncApiTest, ChangeRecordToValue) {
+  int64 child_id = MakeNode(&share_, syncable::BOOKMARKS, "testtag");
+  sync_pb::EntitySpecifics child_specifics;
+  {
+    ReadTransaction trans(&share_);
+    ReadNode node(&trans);
+    EXPECT_TRUE(node.InitByIdLookup(child_id));
+    child_specifics = node.GetEntry()->Get(syncable::SPECIFICS);
+  }
+
+  // Add
+  {
+    ReadTransaction trans(&share_);
+    SyncManager::ChangeRecord record;
+    record.action = SyncManager::ChangeRecord::ACTION_ADD;
+    record.id = 1;
+    record.specifics = child_specifics;
+    record.extra.reset(new StrictMock<MockExtraChangeRecordData>());
+    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
+    CheckNonDeleteChangeRecordValue(record, *value, &trans);
+  }
+
+  // Update
+  {
+    ReadTransaction trans(&share_);
+    SyncManager::ChangeRecord record;
+    record.action = SyncManager::ChangeRecord::ACTION_UPDATE;
+    record.id = child_id;
+    record.specifics = child_specifics;
+    record.extra.reset(new StrictMock<MockExtraChangeRecordData>());
+    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
+    CheckNonDeleteChangeRecordValue(record, *value, &trans);
+  }
+
+  // Delete (no extra)
+  {
+    ReadTransaction trans(&share_);
+    SyncManager::ChangeRecord record;
+    record.action = SyncManager::ChangeRecord::ACTION_DELETE;
+    record.id = child_id + 1;
+    record.specifics = child_specifics;
+    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
+    CheckDeleteChangeRecordValue(record, *value);
+  }
+
+  // Delete (with extra)
+  {
+    ReadTransaction trans(&share_);
+    SyncManager::ChangeRecord record;
+    record.action = SyncManager::ChangeRecord::ACTION_DELETE;
+    record.id = child_id + 1;
+    record.specifics = child_specifics;
+
+    DictionaryValue extra_value;
+    extra_value.SetString("foo", "bar");
+    scoped_ptr<StrictMock<MockExtraChangeRecordData> > extra(
+        new StrictMock<MockExtraChangeRecordData>());
+    EXPECT_CALL(*extra, ToValue()).Times(2).WillRepeatedly(
+        Invoke(&extra_value, &DictionaryValue::DeepCopy));
+
+    record.extra.reset(extra.release());
+    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
+    CheckDeleteChangeRecordValue(record, *value);
+  }
+}
+
+namespace {
+
+class TestHttpPostProviderFactory : public HttpPostProviderFactory {
+ public:
+  virtual ~TestHttpPostProviderFactory() {}
+  virtual HttpPostProviderInterface* Create() {
+    NOTREACHED();
+    return NULL;
+  }
+  virtual void Destroy(HttpPostProviderInterface* http) {
+    NOTREACHED();
+  }
+};
+
+class SyncManagerTest : public testing::Test {
+ protected:
+  SyncManagerTest() : ui_thread_(BrowserThread::UI, &ui_loop_) {}
+
+  void SetUp() {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    sync_manager_.Init(temp_dir_.path(), "bogus", 0, false,
+                       new TestHttpPostProviderFactory(), NULL, "bogus",
+                       SyncCredentials(), notifier::NotifierOptions(),
+                       "", true /* setup_for_test_mode */);
+  }
+
+  void TearDown() {
+    sync_manager_.Shutdown();
+  }
+
+ private:
+  // Needed by |ui_thread_|.
+  MessageLoopForUI ui_loop_;
+  // Needed by |sync_manager_|.
+  BrowserThread ui_thread_;
+  // Needed by |sync_manager_|.
+  ScopedTempDir temp_dir_;
+
+ protected:
+  SyncManager sync_manager_;
+};
+
+TEST_F(SyncManagerTest, ParentJsEventRouter) {
+  StrictMock<MockJsEventRouter> event_router;
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+  EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter());
+  js_backend->SetParentJsEventRouter(&event_router);
+  EXPECT_EQ(&event_router, js_backend->GetParentJsEventRouter());
+  js_backend->RemoveParentJsEventRouter();
+  EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter());
+}
+
+TEST_F(SyncManagerTest, ProcessMessage) {
+  const JsArgList kNoArgs;
+
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+
+  // Messages sent without any parent router should be dropped.
+  {
+    StrictMock<MockJsEventHandler> event_handler;
+    js_backend->ProcessMessage("unknownMessage",
+                               kNoArgs, &event_handler);
+    js_backend->ProcessMessage("getNotificationState",
+                               kNoArgs, &event_handler);
+  }
+
+  {
+    StrictMock<MockJsEventHandler> event_handler;
+    StrictMock<MockJsEventRouter> event_router;
+
+    ListValue false_args;
+    false_args.Append(Value::CreateBooleanValue(false));
+
+    EXPECT_CALL(event_router,
+                RouteJsEvent("onGetNotificationStateFinished",
+                             HasArgsAsList(false_args), &event_handler));
+
+    js_backend->SetParentJsEventRouter(&event_router);
+
+    // This message should be dropped.
+    js_backend->ProcessMessage("unknownMessage",
+                                 kNoArgs, &event_handler);
+
+    // This should trigger the reply.
+    js_backend->ProcessMessage("getNotificationState",
+                                 kNoArgs, &event_handler);
+
+    js_backend->RemoveParentJsEventRouter();
+  }
+
+  // Messages sent after a parent router has been removed should be
+  // dropped.
+  {
+    StrictMock<MockJsEventHandler> event_handler;
+    js_backend->ProcessMessage("unknownMessage",
+                                 kNoArgs, &event_handler);
+    js_backend->ProcessMessage("getNotificationState",
+                                 kNoArgs, &event_handler);
+  }
+}
+
+TEST_F(SyncManagerTest, ProcessMessageGetRootNode) {
+  const JsArgList kNoArgs;
+
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+
+  StrictMock<MockJsEventHandler> event_handler;
+  StrictMock<MockJsEventRouter> event_router;
+
+  JsArgList return_args;
+
+  EXPECT_CALL(event_router,
+              RouteJsEvent("onGetRootNodeFinished", _, &event_handler)).
+      WillOnce(SaveArg<1>(&return_args));
+
+  js_backend->SetParentJsEventRouter(&event_router);
+
+  // Should trigger the reply.
+  js_backend->ProcessMessage("getRootNode", kNoArgs, &event_handler);
+
+  EXPECT_EQ(1u, return_args.Get().GetSize());
+  DictionaryValue* node_info = NULL;
+  EXPECT_TRUE(return_args.Get().GetDictionary(0, &node_info));
+  if (node_info) {
+    ReadTransaction trans(sync_manager_.GetUserShare());
+    ReadNode node(&trans);
+    node.InitByRootLookup();
+    CheckNodeValue(node, *node_info);
+  } else {
+    ADD_FAILURE();
+  }
+
+  js_backend->RemoveParentJsEventRouter();
+}
+
+void CheckGetNodeByIdReturnArgs(const SyncManager& sync_manager,
+                                const JsArgList& return_args,
+                                int64 id) {
+  EXPECT_EQ(1u, return_args.Get().GetSize());
+  DictionaryValue* node_info = NULL;
+  EXPECT_TRUE(return_args.Get().GetDictionary(0, &node_info));
+  if (node_info) {
+    ReadTransaction trans(sync_manager.GetUserShare());
+    ReadNode node(&trans);
+    node.InitByIdLookup(id);
+    CheckNodeValue(node, *node_info);
+  } else {
+    ADD_FAILURE();
+  }
+}
+
+TEST_F(SyncManagerTest, ProcessMessageGetNodeById) {
+  int64 child_id =
+      MakeNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, "testtag");
+
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+
+  StrictMock<MockJsEventHandler> event_handler;
+  StrictMock<MockJsEventRouter> event_router;
+
+  JsArgList return_args;
+
+  EXPECT_CALL(event_router,
+              RouteJsEvent("onGetNodeByIdFinished", _, &event_handler))
+      .Times(2).WillRepeatedly(SaveArg<1>(&return_args));
+
+  js_backend->SetParentJsEventRouter(&event_router);
+
+  // Should trigger the reply.
+  {
+    ListValue args;
+    args.Append(Value::CreateStringValue("1"));
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  CheckGetNodeByIdReturnArgs(sync_manager_, return_args, 1);
+
+  // Should trigger another reply.
+  {
+    ListValue args;
+    args.Append(Value::CreateStringValue(base::Int64ToString(child_id)));
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  CheckGetNodeByIdReturnArgs(sync_manager_, return_args, child_id);
+
+  js_backend->RemoveParentJsEventRouter();
+}
+
+TEST_F(SyncManagerTest, ProcessMessageGetNodeByIdFailure) {
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+
+  StrictMock<MockJsEventHandler> event_handler;
+  StrictMock<MockJsEventRouter> event_router;
+
+  ListValue null_args;
+  null_args.Append(Value::CreateNullValue());
+
+  EXPECT_CALL(event_router,
+              RouteJsEvent("onGetNodeByIdFinished",
+                           HasArgsAsList(null_args), &event_handler))
+      .Times(5);
+
+  js_backend->SetParentJsEventRouter(&event_router);
+
+  {
+    ListValue args;
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  {
+    ListValue args;
+    args.Append(Value::CreateStringValue(""));
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  {
+    ListValue args;
+    args.Append(Value::CreateStringValue("nonsense"));
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  {
+    ListValue args;
+    args.Append(Value::CreateStringValue("nonsense"));
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  {
+    ListValue args;
+    args.Append(Value::CreateStringValue("0"));
+    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
+  }
+
+  // TODO(akalin): Figure out how to test InitByIdLookup() failure.
+
+  js_backend->RemoveParentJsEventRouter();
+}
+
+TEST_F(SyncManagerTest, OnNotificationStateChange) {
+  StrictMock<MockJsEventRouter> event_router;
+
+  ListValue true_args;
+  true_args.Append(Value::CreateBooleanValue(true));
+  ListValue false_args;
+  false_args.Append(Value::CreateBooleanValue(false));
+
+  EXPECT_CALL(event_router,
+              RouteJsEvent("onSyncNotificationStateChange",
+                           HasArgsAsList(true_args), NULL));
+  EXPECT_CALL(event_router,
+              RouteJsEvent("onSyncNotificationStateChange",
+                           HasArgsAsList(false_args), NULL));
+
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+
+  sync_manager_.TriggerOnNotificationStateChangeForTest(true);
+  sync_manager_.TriggerOnNotificationStateChangeForTest(false);
+
+  js_backend->SetParentJsEventRouter(&event_router);
+  sync_manager_.TriggerOnNotificationStateChangeForTest(true);
+  sync_manager_.TriggerOnNotificationStateChangeForTest(false);
+  js_backend->RemoveParentJsEventRouter();
+
+  sync_manager_.TriggerOnNotificationStateChangeForTest(true);
+  sync_manager_.TriggerOnNotificationStateChangeForTest(false);
+}
+
+TEST_F(SyncManagerTest, OnIncomingNotification) {
+  StrictMock<MockJsEventRouter> event_router;
+
+  const syncable::ModelTypeBitSet empty_model_types;
+  syncable::ModelTypeBitSet model_types;
+  model_types.set(syncable::BOOKMARKS);
+  model_types.set(syncable::THEMES);
+
+  // Build expected_args to have a single argument with the string
+  // equivalents of model_types.
+  ListValue expected_args;
+  {
+    ListValue* model_type_list = new ListValue();
+    expected_args.Append(model_type_list);
+    for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+         i < syncable::MODEL_TYPE_COUNT; ++i) {
+      if (model_types[i]) {
+        model_type_list->Append(
+            Value::CreateStringValue(
+                syncable::ModelTypeToString(
+                    syncable::ModelTypeFromInt(i))));
+      }
+    }
+  }
+
+  EXPECT_CALL(event_router,
+              RouteJsEvent("onSyncIncomingNotification",
+                           HasArgsAsList(expected_args), NULL));
+
+  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
+
+  sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types);
+  sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
+
+  js_backend->SetParentJsEventRouter(&event_router);
+  sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
+  js_backend->RemoveParentJsEventRouter();
+
+  sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types);
+  sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
+}
+
+}  // namespace
+
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/engine/syncer.cc b/chrome/browser/sync/engine/syncer.cc
index cbf9753..9ca668e 100644
--- a/chrome/browser/sync/engine/syncer.cc
+++ b/chrome/browser/sync/engine/syncer.cc
@@ -55,22 +55,22 @@
 
 Syncer::Syncer()
     : early_exit_requested_(false),
-      max_commit_batch_size_(kDefaultMaxCommitBatchSize),
       pre_conflict_resolution_closure_(NULL) {
 }
 
 Syncer::~Syncer() {}
 
 bool Syncer::ExitRequested() {
-  AutoLock lock(early_exit_requested_lock_);
+  base::AutoLock lock(early_exit_requested_lock_);
   return early_exit_requested_;
 }
 
 void Syncer::RequestEarlyExit() {
-  AutoLock lock(early_exit_requested_lock_);
+  base::AutoLock lock(early_exit_requested_lock_);
   early_exit_requested_ = true;
 }
 
+// TODO(tim): Deprecated.
 void Syncer::SyncShare(sessions::SyncSession* session) {
   ScopedDirLookup dir(session->context()->directory_manager(),
                       session->context()->account_name());
@@ -78,21 +78,11 @@
   CHECK(dir.good());
 
   const sessions::SyncSourceInfo& source(session->source());
-  if (sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA == source.first) {
+  if (sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA ==
+      source.updates_source) {
     SyncShare(session, CLEAR_PRIVATE_DATA, SYNCER_END);
     return;
   } else {
-    // This isn't perfect, as we can end up bundling extensions activity
-    // intended for the next session into the current one.  We could do a
-    // test-and-reset as with the source, but note that also falls short if
-    // the commit request fails (e.g. due to lost connection), as we will
-    // fall all the way back to the syncer thread main loop in that case, and
-    // wind up creating a new session when a connection is established, losing
-    // the records set here on the original attempt.  This should provide us
-    // with the right data "most of the time", and we're only using this for
-    // analysis purposes, so Law of Large Numbers FTW.
-    session->context()->extensions_monitor()->GetAndClearRecords(
-        session->mutable_extensions_activity());
     SyncShare(session, SYNCER_BEGIN, SYNCER_END);
   }
 }
@@ -100,6 +90,11 @@
 void Syncer::SyncShare(sessions::SyncSession* session,
                        const SyncerStep first_step,
                        const SyncerStep last_step) {
+  ScopedDirLookup dir(session->context()->directory_manager(),
+                      session->context()->account_name());
+  // The directory must be good here.
+  CHECK(dir.good());
+
   ScopedSessionContextConflictResolver scoped(session->context(),
                                               &resolver_);
   SyncerStep current_step = first_step;
@@ -109,6 +104,17 @@
     switch (current_step) {
       case SYNCER_BEGIN:
         VLOG(1) << "Syncer Begin";
+        // This isn't perfect, as we can end up bundling extensions activity
+        // intended for the next session into the current one.  We could do a
+        // test-and-reset as with the source, but note that also falls short if
+        // the commit request fails (e.g. due to lost connection), as we will
+        // fall all the way back to the syncer thread main loop in that case,
+        // creating a new session when a connection is established, losing the
+        // records set here on the original attempt.  This should provide us
+        // with the right data "most of the time", and we're only using this
+        // for analysis purposes, so Law of Large Numbers FTW.
+        session->context()->extensions_monitor()->GetAndClearRecords(
+            session->mutable_extensions_activity());
         next_step = CLEANUP_DISABLED_TYPES;
         break;
       case CLEANUP_DISABLED_TYPES: {
@@ -182,7 +188,8 @@
         sessions::ScopedSetSessionWriteTransaction set_trans(session, &trans);
 
         VLOG(1) << "Getting the Commit IDs";
-        GetCommitIdsCommand get_commit_ids_command(max_commit_batch_size_);
+        GetCommitIdsCommand get_commit_ids_command(
+            session->context()->max_commit_batch_size());
         get_commit_ids_command.Execute(session);
 
         if (!session->status_controller()->commit_ids().empty()) {
@@ -288,8 +295,10 @@
   const ClientCommand& command = response.client_command();
 
   // The server limits the number of items a client can commit in one batch.
-  if (command.has_max_commit_batch_size())
-    max_commit_batch_size_ = command.max_commit_batch_size();
+  if (command.has_max_commit_batch_size()) {
+    session->context()->set_max_commit_batch_size(
+        command.max_commit_batch_size());
+  }
   if (command.has_set_sync_long_poll_interval()) {
     session->delegate()->OnReceivedLongPollIntervalUpdate(
         TimeDelta::FromSeconds(command.set_sync_long_poll_interval()));
diff --git a/chrome/browser/sync/engine/syncer.h b/chrome/browser/sync/engine/syncer.h
index 2789ed2..b9deb23 100644
--- a/chrome/browser/sync/engine/syncer.h
+++ b/chrome/browser/sync/engine/syncer.h
@@ -12,8 +12,8 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/sync/engine/conflict_resolver.h"
 #include "chrome/browser/sync/engine/syncer_types.h"
 #include "chrome/browser/sync/engine/syncproto.h"
@@ -41,8 +41,6 @@
 class URLFactory;
 struct HttpResponse;
 
-static const int kDefaultMaxCommitBatchSize = 25;
-
 enum SyncerStep {
   SYNCER_BEGIN,
   CLEANUP_DISABLED_TYPES,
@@ -58,7 +56,7 @@
   BUILD_AND_PROCESS_CONFLICT_SETS,
   RESOLVE_CONFLICTS,
   APPLY_UPDATES_TO_RESOLVE_CONFLICTS,
-  CLEAR_PRIVATE_DATA,
+  CLEAR_PRIVATE_DATA,  // TODO(tim): Rename 'private' to 'user'.
   SYNCER_END
 };
 
@@ -79,39 +77,31 @@
   // The constructor may be called from a thread that is not the Syncer's
   // dedicated thread, to allow some flexibility in the setup.
   Syncer();
-  ~Syncer();
+  virtual ~Syncer();
 
   // Called by other threads to tell the syncer to stop what it's doing
   // and return early from SyncShare, if possible.
   bool ExitRequested();
   void RequestEarlyExit();
 
+  // TODO(tim): Deprecated.
   // Cause one sync cycle to occur.  Like a good parent, it is the caller's
   // responsibility to clean up after the syncer when it finishes a sync share
   // operation and honor server mandated throttles.
-  void SyncShare(sessions::SyncSession* session);
+  virtual void SyncShare(sessions::SyncSession* session);
 
-  // Limit the batch size of commit operations to a specified number of items.
-  void set_max_commit_batch_size(int x) { max_commit_batch_size_ = x; }
+  // Like SyncShare() above, but |first_step| and |last_step| are provided to
+  // perform a partial sync cycle, stopping after |last_step| is performed.
+  virtual void SyncShare(sessions::SyncSession* session,
+                         SyncerStep first_step,
+                         SyncerStep last_step);
 
  private:
-  void RequestNudge(int milliseconds);
-
   // Implements the PROCESS_CLIENT_COMMAND syncer step.
   void ProcessClientCommand(sessions::SyncSession *session);
 
-  // This is the bottom-most SyncShare variant, and does not cause transient
-  // state to be reset in session.
-  // Like SyncShare(), but |first_step| and |last_step| are provided to perform
-  // a partial sync cycle, stopping after |last_step| is performed.
-  void SyncShare(sessions::SyncSession* session,
-                 SyncerStep first_step,
-                 SyncerStep last_step);
-
   bool early_exit_requested_;
-  Lock early_exit_requested_lock_;
-
-  int32 max_commit_batch_size_;
+  base::Lock early_exit_requested_lock_;
 
   ConflictResolver resolver_;
 
@@ -174,3 +164,4 @@
 }  // namespace browser_sync
 
 #endif  // CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_
+
diff --git a/chrome/browser/sync/engine/syncer_end_command.cc b/chrome/browser/sync/engine/syncer_end_command.cc
index 1311b57..ff5c03e 100644
--- a/chrome/browser/sync/engine/syncer_end_command.cc
+++ b/chrome/browser/sync/engine/syncer_end_command.cc
@@ -34,7 +34,7 @@
 
     for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
       syncable::ModelType model_type = syncable::ModelTypeFromInt(i);
-      if (status->updates_request_parameters().data_types[i]) {
+      if (status->updates_request_types()[i]) {
         // This gets persisted to the directory's backing store.
         dir->set_initial_sync_ended_for_type(model_type, true);
       }
diff --git a/chrome/browser/sync/engine/syncer_proto_util.cc b/chrome/browser/sync/engine/syncer_proto_util.cc
index 2603b0a..5dbb202 100644
--- a/chrome/browser/sync/engine/syncer_proto_util.cc
+++ b/chrome/browser/sync/engine/syncer_proto_util.cc
@@ -167,6 +167,22 @@
   return false;
 }
 
+namespace {
+
+// Helper function for an assertion in PostClientToServerMessage.
+bool IsVeryFirstGetUpdates(const ClientToServerMessage& message) {
+  if (!message.has_get_updates())
+    return false;
+  DCHECK_LT(0, message.get_updates().from_progress_marker_size());
+  for (int i = 0; i < message.get_updates().from_progress_marker_size(); ++i) {
+    if (!message.get_updates().from_progress_marker(i).token().empty())
+      return false;
+  }
+  return true;
+}
+
+}  // namespace
+
 // static
 bool SyncerProtoUtil::PostClientToServerMessage(
     const ClientToServerMessage& msg,
@@ -174,9 +190,9 @@
     SyncSession* session) {
 
   CHECK(response);
-  DCHECK(msg.has_store_birthday() || (msg.has_get_updates() &&
-                                      msg.get_updates().has_from_timestamp() &&
-                                      msg.get_updates().from_timestamp() == 0))
+  DCHECK(!msg.get_updates().has_from_timestamp());  // Deprecated.
+  DCHECK(!msg.get_updates().has_requested_types());  // Deprecated.
+  DCHECK(msg.has_store_birthday() || IsVeryFirstGetUpdates(msg))
       << "Must call AddRequestBirthday to set birthday.";
 
   ScopedDirLookup dir(session->context()->directory_manager(),
diff --git a/chrome/browser/sync/engine/syncer_proto_util_unittest.cc b/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
index 57cae0a..3e8b9c6 100644
--- a/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/sync/engine/syncer_proto_util.h"
 
+#include <string>
+
 #include "base/basictypes.h"
 #include "chrome/browser/sync/engine/syncproto.h"
 #include "chrome/browser/sync/syncable/blob.h"
@@ -33,11 +35,11 @@
   for (size_t i = 0; i < arraysize(test_data3); ++i)
     test_blob3.push_back(test_data3[i]);
 
-  string test_message1(reinterpret_cast<char*>(test_data1),
+  std::string test_message1(reinterpret_cast<char*>(test_data1),
       arraysize(test_data1));
-  string test_message2(reinterpret_cast<char*>(test_data2),
+  std::string test_message2(reinterpret_cast<char*>(test_data2),
       arraysize(test_data2));
-  string test_message3(reinterpret_cast<char*>(test_data3),
+  std::string test_message3(reinterpret_cast<char*>(test_data3),
       arraysize(test_data3));
 
   EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc
index 3c0cd06..ee45cca 100644
--- a/chrome/browser/sync/engine/syncer_thread.cc
+++ b/chrome/browser/sync/engine/syncer_thread.cc
@@ -1,9 +1,22 @@
 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
+
 #include "chrome/browser/sync/engine/syncer_thread.h"
 
+#include <algorithm>
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/rand_util.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "build/build_config.h"
+#include "chrome/browser/sync/engine/model_safe_worker.h"
+#include "chrome/browser/sync/engine/net/server_connection_manager.h"
+#include "chrome/browser/sync/engine/syncer.h"
+#include "chrome/browser/sync/sessions/sync_session.h"
+#include "jingle/notifier/listener/notification_constants.h"
 
 #if defined(OS_MACOSX)
 #include <CoreFoundation/CFNumber.h>
@@ -11,19 +24,6 @@
 #include <IOKit/IOKitLib.h>
 #endif
 
-#include <algorithm>
-#include <map>
-#include <queue>
-
-#include "base/rand_util.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "chrome/browser/sync/engine/model_safe_worker.h"
-#include "chrome/browser/sync/engine/net/server_connection_manager.h"
-#include "chrome/browser/sync/engine/syncer.h"
-#include "chrome/browser/sync/sessions/sync_session.h"
-#include "chrome/common/chrome_switches.h"
-#include "jingle/notifier/listener/notification_constants.h"
-
 using std::priority_queue;
 using std::min;
 using base::Time;
@@ -35,6 +35,7 @@
 using sessions::SyncSession;
 using sessions::SyncSessionSnapshot;
 using sessions::SyncSourceInfo;
+using sessions::TypePayloadMap;
 
 // We use high values here to ensure that failure to receive poll updates from
 // the server doesn't result in rapid-fire polling from the client due to low
@@ -55,6 +56,28 @@
 
 const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4;  // 4 hours.
 
+SyncerThread::ProtectedFields::ProtectedFields()
+        : stop_syncer_thread_(false),
+          pause_requested_(false),
+          paused_(false),
+          syncer_(NULL),
+          connected_(false),
+          pending_nudge_source_(kUnknown) {}
+
+SyncerThread::ProtectedFields::~ProtectedFields() {}
+
+void SyncerThread::NudgeSyncerWithPayloads(
+    int milliseconds_from_now,
+    NudgeSource source,
+    const TypePayloadMap& model_types_with_payloads) {
+  base::AutoLock lock(lock_);
+  if (vault_.syncer_ == NULL) {
+    return;
+  }
+
+  NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
+}
+
 void SyncerThread::NudgeSyncerWithDataTypes(
     int milliseconds_from_now,
     NudgeSource source,
@@ -64,7 +87,9 @@
     return;
   }
 
-  NudgeSyncImpl(milliseconds_from_now, source, model_types);
+  TypePayloadMap model_types_with_payloads =
+      sessions::MakeTypePayloadMapFromBitSet(model_types, std::string());
+  NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
 }
 
 void SyncerThread::NudgeSyncer(
@@ -75,8 +100,12 @@
     return;
   }
 
-  syncable::ModelTypeBitSet model_types;  // All false by default.
-  NudgeSyncImpl(milliseconds_from_now, source, model_types);
+  // Set all enabled datatypes.
+  ModelSafeRoutingInfo routes;
+  session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
+  TypePayloadMap model_types_with_payloads =
+      sessions::MakeTypePayloadMapFromRoutingInfo(routes, std::string());
+  NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
 }
 
 SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
@@ -343,11 +372,12 @@
     // Update timing information for how often these datatypes are triggering
     // nudges.
     base::TimeTicks now = TimeTicks::Now();
-    for (size_t i = syncable::FIRST_REAL_MODEL_TYPE;
-         i < session->source().second.size();
-         ++i) {
-      if (session->source().second[i]) {
-        syncable::PostTimeToTypeHistogram(syncable::ModelType(i),
+    if (!last_sync_time.is_null()) {
+      TypePayloadMap::const_iterator iter;
+      for (iter = session->source().types.begin();
+           iter != session->source().types.end();
+           ++iter) {
+        syncable::PostTimeToTypeHistogram(iter->first,
                                           now - last_sync_time);
       }
     }
@@ -472,8 +502,8 @@
   // Determine if the syncer has unfinished work to do.
   SyncSessionSnapshot* snapshot = session_context_->previous_session_snapshot();
   const bool syncer_has_work_to_do = snapshot &&
-      (snapshot->num_server_changes_remaining > snapshot->max_local_timestamp ||
-          snapshot->unsynced_count > 0);
+      (snapshot->num_server_changes_remaining > 0 ||
+       snapshot->unsynced_count > 0);
   VLOG(1) << "syncer_has_work_to_do is " << syncer_has_work_to_do;
 
   // First calculate the expected wait time, figuring in any backoff because of
@@ -557,7 +587,7 @@
       continue_sync_cycle, initial_sync_for_thread, was_nudged));
   scoped_ptr<SyncSession> session;
 
-  AutoUnlock unlock(lock_);
+  base::AutoUnlock unlock(lock_);
   do {
     session.reset(new SyncSession(session_context_.get(), this,
                                   info, routes, workers));
@@ -575,7 +605,7 @@
                                                     bool* was_nudged) {
   bool nudged = false;
   NudgeSource nudge_source = kUnknown;
-  syncable::ModelTypeBitSet model_types;
+  TypePayloadMap model_types_with_payloads;
   // Has the previous sync cycle completed?
   if (continue_sync_cycle)
     nudge_source = kContinuation;
@@ -584,13 +614,13 @@
   if (!vault_.pending_nudge_time_.is_null()) {
     if (!was_throttled) {
       nudge_source = vault_.pending_nudge_source_;
-      model_types = vault_.pending_nudge_types_;
+      model_types_with_payloads = vault_.pending_nudge_types_;
       nudged = true;
     }
     VLOG(1) << "Clearing pending nudge from " << vault_.pending_nudge_source_
             << " at tick " << vault_.pending_nudge_time_.ToInternalValue();
     vault_.pending_nudge_source_ = kUnknown;
-    vault_.pending_nudge_types_.reset();
+    vault_.pending_nudge_types_.clear();
     vault_.pending_nudge_time_ = base::TimeTicks();
   }
 
@@ -600,11 +630,12 @@
   // from syncer having more work to do.  This will be handled properly with
   // the message loop based syncer thread, bug 26339.
   return MakeSyncSourceInfo(nudged || nudge_source == kContinuation,
-      nudge_source, model_types, initial_sync);
+      nudge_source, model_types_with_payloads, initial_sync);
 }
 
 SyncSourceInfo SyncerThread::MakeSyncSourceInfo(bool nudged,
-    NudgeSource nudge_source, const syncable::ModelTypeBitSet& nudge_types,
+    NudgeSource nudge_source,
+    const TypePayloadMap& model_types_with_payloads,
     bool* initial_sync) {
   sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source =
       sync_pb::GetUpdatesCallerInfo::UNKNOWN;
@@ -633,7 +664,19 @@
         break;
     }
   }
-  return SyncSourceInfo(updates_source, nudge_types);
+
+  TypePayloadMap sync_source_types;
+  if (model_types_with_payloads.empty()) {
+    // No datatypes requested. This must be a poll so set all enabled datatypes.
+    ModelSafeRoutingInfo routes;
+    session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
+    sync_source_types = sessions::MakeTypePayloadMapFromRoutingInfo(routes,
+        std::string());
+  } else {
+    sync_source_types = model_types_with_payloads;
+  }
+
+  return SyncSourceInfo(updates_source, sync_source_types);
 }
 
 void SyncerThread::CreateSyncer(const std::string& dirname) {
@@ -735,9 +778,10 @@
 }
 
 // Called with mutex_ already locked.
-void SyncerThread::NudgeSyncImpl(int milliseconds_from_now,
-                                 NudgeSource source,
-                                 const syncable::ModelTypeBitSet& model_types) {
+void SyncerThread::NudgeSyncImpl(
+    int milliseconds_from_now,
+    NudgeSource source,
+    const TypePayloadMap& model_types_with_payloads) {
   // TODO(sync): Add the option to reset the backoff state machine.
   // This is needed so nudges that are a result of the user's desire
   // to download updates for a new data type can be satisfied quickly.
@@ -748,11 +792,12 @@
     return;
   }
 
-  // Union the current bitset with any from nudges that may have already
+  // Union the current TypePayloadMap with any from nudges that may have already
   // posted (coalesce the nudge datatype information).
   // TODO(tim): It seems weird to do this if the sources don't match up (e.g.
   // if pending_source is kLocal and |source| is kClearPrivateData).
-  vault_.pending_nudge_types_ |= model_types;
+  sessions::CoalescePayloads(&vault_.pending_nudge_types_,
+                             model_types_with_payloads);
 
   const TimeTicks nudge_time = TimeTicks::Now() +
       TimeDelta::FromMilliseconds(milliseconds_from_now);
diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h
index 22531d8..b8bf724 100644
--- a/chrome/browser/sync/engine/syncer_thread.h
+++ b/chrome/browser/sync/engine/syncer_thread.h
@@ -49,6 +49,9 @@
   FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithDataTypes);
   FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest,
                            NudgeWithDataTypesCoalesced);
+  FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithPayloads);
+  FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest,
+                           NudgeWithPayloadsCoalesced);
   FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Throttling);
   FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, AuthInvalid);
   FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Pause);
@@ -138,7 +141,15 @@
   virtual void NudgeSyncerWithDataTypes(
       int milliseconds_from_now,
       NudgeSource source,
-      const syncable::ModelTypeBitSet& model_type);
+      const syncable::ModelTypeBitSet& model_types);
+
+  // Same as |NudgeSyncer|, but supports including a payload for passing on to
+  // the download updates command. Datatypes with payloads are also considered
+  // to have caused a nudged to occur and treated accordingly.
+  virtual void NudgeSyncerWithPayloads(
+      int milliseconds_from_now,
+      NudgeSource source,
+      const sessions::TypePayloadMap& model_types_with_payloads);
 
   void SetNotificationsEnabled(bool notifications_enabled);
 
@@ -170,6 +181,9 @@
   // Fields that are modified / accessed by multiple threads go in this struct
   // for clarity and explicitness.
   struct ProtectedFields {
+    ProtectedFields();
+    ~ProtectedFields();
+
     // False when we want to stop the thread.
     bool stop_syncer_thread_;
 
@@ -189,9 +203,13 @@
     // check pending_nudge_time_.)
     NudgeSource pending_nudge_source_;
 
-    // BitSet of the datatypes that have triggered the current nudge
-    // (can be union of various bitsets when multiple nudges are coalesced)
-    syncable::ModelTypeBitSet pending_nudge_types_;
+    // Map of all datatypes that are requesting a nudge. Can be union
+    // from multiple nudges that are coalesced. In addition, we
+    // optionally track a payload associated with each datatype (most recent
+    // payload overwrites old ones). These payloads are used by the download
+    // updates command and can contain datatype specific information the server
+    // might use.
+    sessions::TypePayloadMap pending_nudge_types_;
 
     // null iff there is no pending nudge.
     base::TimeTicks pending_nudge_time_;
@@ -202,14 +220,6 @@
     // really need to access mutually exclusively as the data races that exist
     // are intrinsic, but do so anyway and avoid using 'volatile'.
     WaitInterval current_wait_interval_;
-
-    ProtectedFields()
-        : stop_syncer_thread_(false),
-          pause_requested_(false),
-          paused_(false),
-          syncer_(NULL),
-          connected_(false),
-          pending_nudge_source_(kUnknown) {}
   } vault_;
 
   // Gets signaled whenever a thread outside of the syncer thread changes a
@@ -280,7 +290,7 @@
   sessions::SyncSourceInfo MakeSyncSourceInfo(
       bool nudged,
       NudgeSource nudge_source,
-      const syncable::ModelTypeBitSet& nudge_types,
+      const sessions::TypePayloadMap& model_types_with_payloads,
       bool* initial_sync);
 
   int UserIdleTime();
@@ -327,7 +337,7 @@
   void NudgeSyncImpl(
       int milliseconds_from_now,
       NudgeSource source,
-      const syncable::ModelTypeBitSet& model_types);
+      const sessions::TypePayloadMap& model_types_with_payloads);
 
 #if defined(OS_LINUX)
   // On Linux, we need this information in order to query idle time.
diff --git a/chrome/browser/sync/engine/syncer_thread2.cc b/chrome/browser/sync/engine/syncer_thread2.cc
new file mode 100644
index 0000000..be49a39
--- /dev/null
+++ b/chrome/browser/sync/engine/syncer_thread2.cc
@@ -0,0 +1,587 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/engine/syncer_thread2.h"
+
+#include <algorithm>
+
+#include "base/rand_util.h"
+#include "chrome/browser/sync/engine/syncer.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace browser_sync {
+
+using sessions::SyncSession;
+using sessions::SyncSessionSnapshot;
+using sessions::SyncSourceInfo;
+using sessions::TypePayloadMap;
+using syncable::ModelTypeBitSet;
+using sync_pb::GetUpdatesCallerInfo;
+
+namespace s3 {
+
+struct SyncerThread::WaitInterval {
+  enum Mode {
+    // A wait interval whose duration has been affected by exponential
+    // backoff.
+    // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
+    EXPONENTIAL_BACKOFF,
+    // A server-initiated throttled interval.  We do not allow any syncing
+    // during such an interval.
+    THROTTLED,
+  };
+  Mode mode;
+
+  // This bool is set to true if we have observed a nudge during this
+  // interval and mode == EXPONENTIAL_BACKOFF.
+  bool had_nudge;
+  base::TimeDelta length;
+  base::OneShotTimer<SyncerThread> timer;
+  WaitInterval(Mode mode, base::TimeDelta length);
+};
+
+struct SyncerThread::SyncSessionJob {
+  SyncSessionJobPurpose purpose;
+  base::TimeTicks scheduled_start;
+  linked_ptr<sessions::SyncSession> session;
+};
+
+SyncerThread::DelayProvider::DelayProvider() {}
+SyncerThread::DelayProvider::~DelayProvider() {}
+
+TimeDelta SyncerThread::DelayProvider::GetDelay(
+    const base::TimeDelta& last_delay) {
+  return SyncerThread::GetRecommendedDelay(last_delay);
+}
+
+SyncerThread::WaitInterval::WaitInterval(Mode mode, TimeDelta length)
+    : mode(mode), had_nudge(false), length(length) { }
+
+SyncerThread::SyncerThread(sessions::SyncSessionContext* context,
+                           Syncer* syncer)
+    : thread_("SyncEngine_SyncerThread"),
+      syncer_short_poll_interval_seconds_(
+          TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)),
+      syncer_long_poll_interval_seconds_(
+          TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)),
+      mode_(NORMAL_MODE),
+      server_connection_ok_(false),
+      delay_provider_(new DelayProvider()),
+      syncer_(syncer),
+      session_context_(context) {
+}
+
+SyncerThread::~SyncerThread() {
+  DCHECK(!thread_.IsRunning());
+}
+
+void SyncerThread::Start(Mode mode) {
+  if (!thread_.IsRunning() && !thread_.Start()) {
+    NOTREACHED() << "Unable to start SyncerThread.";
+    return;
+  }
+
+  thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &SyncerThread::StartImpl, mode));
+}
+
+void SyncerThread::StartImpl(Mode mode) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  DCHECK(!session_context_->account_name().empty());
+  DCHECK(syncer_.get());
+  mode_ = mode;
+  AdjustPolling(NULL);  // Will kick start poll timer if needed.
+}
+
+bool SyncerThread::ShouldRunJob(SyncSessionJobPurpose purpose,
+    const TimeTicks& scheduled_start) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+
+  // Check wait interval.
+  if (wait_interval_.get()) {
+    // TODO(tim): Consider different handling for CLEAR_USER_DATA (i.e. permit
+    // when throttled).
+    if (wait_interval_->mode == WaitInterval::THROTTLED)
+      return false;
+
+    DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF);
+    DCHECK(purpose == POLL ||
+           purpose == NUDGE);
+    if ((purpose != NUDGE) || wait_interval_->had_nudge)
+      return false;
+  }
+
+  // Mode / purpose contract (See 'Mode' enum in header). Don't run jobs that
+  // were intended for a normal sync if we are in configuration mode, and vice
+  // versa.
+  switch (mode_) {
+    case CONFIGURATION_MODE:
+      if (purpose != CONFIGURATION)
+        return false;
+      break;
+    case NORMAL_MODE:
+      if (purpose == CONFIGURATION)
+        return false;
+      break;
+    default:
+      NOTREACHED() << "Unknown SyncerThread Mode: " << mode_;
+      return false;
+  }
+
+  // Continuation NUDGE tasks have priority over POLLs because they are the
+  // only tasks that trigger exponential backoff, so this prevents them from
+  // being starved from running (e.g. due to a very, very low poll interval,
+  // such as 0ms). It's rare that this would ever matter in practice.
+  if (purpose == POLL && (pending_nudge_.get() &&
+      pending_nudge_->session->source().updates_source ==
+          GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION)) {
+    return false;
+  }
+
+  // Freshness condition.
+  if (purpose == NUDGE &&
+      (scheduled_start < last_sync_session_end_time_)) {
+    return false;
+  }
+
+  return server_connection_ok_;
+}
+
+namespace {
+GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource(
+    NudgeSource source) {
+  switch (source) {
+    case NUDGE_SOURCE_NOTIFICATION:
+      return GetUpdatesCallerInfo::NOTIFICATION;
+    case NUDGE_SOURCE_LOCAL:
+      return GetUpdatesCallerInfo::LOCAL;
+    case NUDGE_SOURCE_CONTINUATION:
+      return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
+    case NUDGE_SOURCE_UNKNOWN:
+      return GetUpdatesCallerInfo::UNKNOWN;
+    default:
+      NOTREACHED();
+      return GetUpdatesCallerInfo::UNKNOWN;
+  }
+}
+
+// Functor for std::find_if to search by ModelSafeGroup.
+struct WorkerGroupIs {
+  explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {}
+  bool operator()(ModelSafeWorker* w) {
+    return group == w->GetModelSafeGroup();
+  }
+  ModelSafeGroup group;
+};
+}  // namespace
+
+void SyncerThread::ScheduleClearUserData() {
+  if (!thread_.IsRunning()) {
+    NOTREACHED();
+    return;
+  }
+  thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &SyncerThread::ScheduleClearUserDataImpl));
+}
+
+void SyncerThread::ScheduleNudge(const TimeDelta& delay,
+    NudgeSource source, const ModelTypeBitSet& types) {
+  if (!thread_.IsRunning()) {
+    NOTREACHED();
+    return;
+  }
+
+  TypePayloadMap types_with_payloads =
+      sessions::MakeTypePayloadMapFromBitSet(types, std::string());
+  thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &SyncerThread::ScheduleNudgeImpl, delay, source,
+      types_with_payloads));
+}
+
+void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay,
+    NudgeSource source, const TypePayloadMap& types_with_payloads) {
+  if (!thread_.IsRunning()) {
+    NOTREACHED();
+    return;
+  }
+
+  thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &SyncerThread::ScheduleNudgeImpl, delay, source,
+      types_with_payloads));
+}
+
+void SyncerThread::ScheduleClearUserDataImpl() {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  SyncSession* session = new SyncSession(session_context_.get(), this,
+      SyncSourceInfo(), ModelSafeRoutingInfo(),
+      std::vector<ModelSafeWorker*>());
+  ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), CLEAR_USER_DATA, session);
+}
+
+void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay,
+    NudgeSource source, const TypePayloadMap& types_with_payloads) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  TimeTicks rough_start = TimeTicks::Now() + delay;
+
+  // Note we currently nudge for all types regardless of the ones incurring
+  // the nudge.  Doing different would throw off some syncer commands like
+  // CleanupDisabledTypes.  We may want to change this in the future.
+  ModelSafeRoutingInfo routes;
+  std::vector<ModelSafeWorker*> workers;
+  session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
+  session_context_->registrar()->GetWorkers(&workers);
+  SyncSourceInfo info(GetUpdatesFromNudgeSource(source),
+                      types_with_payloads);
+
+  scoped_ptr<SyncSession> session(new SyncSession(
+      session_context_.get(), this, info, routes, workers));
+
+  if (pending_nudge_.get()) {
+    if (IsBackingOff() && delay > TimeDelta::FromSeconds(1))
+      return;
+
+    pending_nudge_->session->Coalesce(*session.get());
+    if (!IsBackingOff()) {
+      return;
+    } else {
+      // Re-schedule the current pending nudge.
+      SyncSession* s = pending_nudge_->session.get();
+      session.reset(new SyncSession(s->context(), s->delegate(), s->source(),
+          s->routing_info(), s->workers()));
+      pending_nudge_.reset();
+    }
+  }
+  ScheduleSyncSessionJob(delay, NUDGE, session.release());
+}
+
+// Helper to extract the routing info and workers corresponding to types in
+// |types| from |registrar|.
+void GetModelSafeParamsForTypes(const ModelTypeBitSet& types,
+    ModelSafeWorkerRegistrar* registrar, ModelSafeRoutingInfo* routes,
+    std::vector<ModelSafeWorker*>* workers) {
+  ModelSafeRoutingInfo r_tmp;
+  std::vector<ModelSafeWorker*> w_tmp;
+  registrar->GetModelSafeRoutingInfo(&r_tmp);
+  registrar->GetWorkers(&w_tmp);
+
+  typedef std::vector<ModelSafeWorker*>::const_iterator iter;
+  for (size_t i = syncable::FIRST_REAL_MODEL_TYPE; i < types.size(); ++i) {
+    if (!types.test(i))
+      continue;
+    syncable::ModelType t = syncable::ModelTypeFromInt(i);
+    DCHECK_EQ(1U, r_tmp.count(t));
+    (*routes)[t] = r_tmp[t];
+    iter it = std::find_if(w_tmp.begin(), w_tmp.end(), WorkerGroupIs(r_tmp[t]));
+    if (it != w_tmp.end())
+      workers->push_back(*it);
+    else
+      NOTREACHED();
+  }
+
+  iter it = std::find_if(w_tmp.begin(), w_tmp.end(),
+                         WorkerGroupIs(GROUP_PASSIVE));
+  if (it != w_tmp.end())
+    workers->push_back(*it);
+  else
+    NOTREACHED();
+}
+
+void SyncerThread::ScheduleConfig(const TimeDelta& delay,
+    const ModelTypeBitSet& types) {
+  if (!thread_.IsRunning()) {
+    NOTREACHED();
+    return;
+  }
+
+  ModelSafeRoutingInfo routes;
+  std::vector<ModelSafeWorker*> workers;
+  GetModelSafeParamsForTypes(types, session_context_->registrar(),
+                             &routes, &workers);
+
+  thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &SyncerThread::ScheduleConfigImpl, delay, routes, workers));
+}
+
+void SyncerThread::ScheduleConfigImpl(const TimeDelta& delay,
+    const ModelSafeRoutingInfo& routing_info,
+    const std::vector<ModelSafeWorker*>& workers) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  NOTIMPLEMENTED() << "TODO(tim)";
+}
+
+void SyncerThread::ScheduleSyncSessionJob(const base::TimeDelta& delay,
+    SyncSessionJobPurpose purpose, sessions::SyncSession* session) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  SyncSessionJob job = {purpose, TimeTicks::Now() + delay,
+                        make_linked_ptr(session)};
+  if (purpose == NUDGE) {
+    DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session);
+    pending_nudge_.reset(new SyncSessionJob(job));
+  }
+  MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this,
+      &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds());
+}
+
+void SyncerThread::SetSyncerStepsForPurpose(SyncSessionJobPurpose purpose,
+    SyncerStep* start, SyncerStep* end) {
+  *end = SYNCER_END;
+  switch (purpose) {
+    case CONFIGURATION:
+      *start = DOWNLOAD_UPDATES;
+      *end = APPLY_UPDATES;
+      return;
+    case CLEAR_USER_DATA:
+      *start = CLEAR_PRIVATE_DATA;
+       return;
+    case NUDGE:
+    case POLL:
+      *start = SYNCER_BEGIN;
+      return;
+    default:
+      NOTREACHED();
+  }
+}
+
+void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+
+  if (job.purpose == NUDGE) {
+    DCHECK(pending_nudge_.get());
+    if (pending_nudge_->session != job.session)
+      return;  // Another nudge must have been scheduled in in the meantime.
+    pending_nudge_.reset();
+  }
+
+  SyncerStep begin(SYNCER_BEGIN);
+  SyncerStep end(SYNCER_END);
+  SetSyncerStepsForPurpose(job.purpose, &begin, &end);
+
+  bool has_more_to_sync = true;
+  bool did_job = false;
+  while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) {
+    VLOG(1) << "SyncerThread: Calling SyncShare.";
+    did_job = true;
+    // Synchronously perform the sync session from this thread.
+    syncer_->SyncShare(job.session.get(), begin, end);
+    has_more_to_sync = job.session->HasMoreToSync();
+    if (has_more_to_sync)
+      job.session->ResetTransientState();
+  }
+  VLOG(1) << "SyncerThread: Done SyncShare looping.";
+  if (did_job)
+    FinishSyncSessionJob(job);
+}
+
+void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  // Update timing information for how often datatypes are triggering nudges.
+  base::TimeTicks now = TimeTicks::Now();
+  if (!last_sync_session_end_time_.is_null()) {
+    TypePayloadMap::const_iterator iter;
+    for (iter = job.session->source().types.begin();
+         iter != job.session->source().types.end();
+         ++iter) {
+      syncable::PostTimeToTypeHistogram(iter->first,
+                                        now - last_sync_session_end_time_);
+    }
+  }
+  last_sync_session_end_time_ = now;
+  if (IsSyncingCurrentlySilenced())
+    return;  // Nothing to do.
+
+  VLOG(1) << "Updating the next polling time after SyncMain";
+  ScheduleNextSync(job);
+}
+
+void SyncerThread::ScheduleNextSync(const SyncSessionJob& old_job) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  DCHECK(!old_job.session->HasMoreToSync());
+  // Note: |num_server_changes_remaining| > 0 here implies that we received a
+  // broken response while trying to download all updates, because the Syncer
+  // will loop until this value is exhausted. Also, if unsynced_handles exist
+  // but HasMoreToSync is false, this implies that the Syncer determined no
+  // forward progress was possible at this time (an error, such as an HTTP
+  // 500, is likely to have occurred during commit).
+  const bool work_to_do =
+     old_job.session->status_controller()->num_server_changes_remaining() > 0
+     || old_job.session->status_controller()->unsynced_handles().size() > 0;
+  VLOG(1) << "syncer has work to do: " << work_to_do;
+
+  AdjustPolling(&old_job);
+
+  // TODO(tim): Old impl had special code if notifications disabled. Needed?
+  if (!work_to_do) {
+    // Success implies backoff relief.  Note that if this was a "one-off" job
+    // (i.e. purpose == CLEAR_USER_DATA), if there was work_to_do before it
+    // ran this wont have changed, as jobs like this don't run a full sync
+    // cycle.  So we don't need special code here.
+    wait_interval_.reset();
+    return;
+  }
+
+  if (old_job.session->source().updates_source ==
+      GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) {
+    // We don't seem to have made forward progress. Start or extend backoff.
+    HandleConsecutiveContinuationError(old_job);
+  } else if (IsBackingOff()) {
+    // We weren't continuing but we're in backoff; must have been a nudge.
+    DCHECK_EQ(NUDGE, old_job.purpose);
+    DCHECK(!wait_interval_->had_nudge);
+    wait_interval_->had_nudge = true;
+    wait_interval_->timer.Reset();
+  } else {
+    // We weren't continuing and we aren't in backoff.  Schedule a normal
+    // continuation.
+    ScheduleNudgeImpl(TimeDelta::FromSeconds(0), NUDGE_SOURCE_CONTINUATION,
+                      old_job.session->source().types);
+  }
+}
+
+void SyncerThread::AdjustPolling(const SyncSessionJob* old_job) {
+  DCHECK(thread_.IsRunning());
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+
+  TimeDelta poll  = (!session_context_->notifications_enabled()) ?
+      syncer_short_poll_interval_seconds_ :
+      syncer_long_poll_interval_seconds_;
+  bool rate_changed = !poll_timer_.IsRunning() ||
+                       poll != poll_timer_.GetCurrentDelay();
+
+  if (old_job && old_job->purpose != POLL && !rate_changed)
+    poll_timer_.Reset();
+
+  if (!rate_changed)
+    return;
+
+  // Adjust poll rate.
+  poll_timer_.Stop();
+  poll_timer_.Start(poll, this, &SyncerThread::PollTimerCallback);
+}
+
+void SyncerThread::HandleConsecutiveContinuationError(
+    const SyncSessionJob& old_job) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  DCHECK(!IsBackingOff() || !wait_interval_->timer.IsRunning());
+  SyncSession* old = old_job.session.get();
+  SyncSession* s(new SyncSession(session_context_.get(), this,
+      old->source(), old->routing_info(), old->workers()));
+  TimeDelta length = delay_provider_->GetDelay(
+      IsBackingOff() ? wait_interval_->length : TimeDelta::FromSeconds(1));
+  wait_interval_.reset(new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF,
+                                        length));
+  SyncSessionJob job = {NUDGE, TimeTicks::Now() + length,
+                        make_linked_ptr(s)};
+  pending_nudge_.reset(new SyncSessionJob(job));
+  wait_interval_->timer.Start(length, this, &SyncerThread::DoCanaryJob);
+}
+
+// static
+TimeDelta SyncerThread::GetRecommendedDelay(const TimeDelta& last_delay) {
+  if (last_delay.InSeconds() >= kMaxBackoffSeconds)
+    return TimeDelta::FromSeconds(kMaxBackoffSeconds);
+
+  // This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2
+  int64 backoff_s =
+      std::max(static_cast<int64>(1),
+               last_delay.InSeconds() * kBackoffRandomizationFactor);
+
+  // Flip a coin to randomize backoff interval by +/- 50%.
+  int rand_sign = base::RandInt(0, 1) * 2 - 1;
+
+  // Truncation is adequate for rounding here.
+  backoff_s = backoff_s +
+      (rand_sign * (last_delay.InSeconds() / kBackoffRandomizationFactor));
+
+  // Cap the backoff interval.
+  backoff_s = std::max(static_cast<int64>(1),
+                       std::min(backoff_s, kMaxBackoffSeconds));
+
+  return TimeDelta::FromSeconds(backoff_s);
+}
+
+void SyncerThread::Stop() {
+  syncer_->RequestEarlyExit();  // Safe to call from any thread.
+  thread_.Stop();
+  Notify(SyncEngineEvent::SYNCER_THREAD_EXITING);
+}
+
+void SyncerThread::DoCanaryJob() {
+  DCHECK(pending_nudge_.get());
+  wait_interval_->had_nudge = false;
+  SyncSessionJob copy = {pending_nudge_->purpose,
+                         pending_nudge_->scheduled_start,
+                         pending_nudge_->session};
+  DoSyncSessionJob(copy);
+}
+
+void SyncerThread::PollTimerCallback() {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  ModelSafeRoutingInfo r;
+  std::vector<ModelSafeWorker*> w;
+  session_context_->registrar()->GetModelSafeRoutingInfo(&r);
+  session_context_->registrar()->GetWorkers(&w);
+  TypePayloadMap types_with_payloads =
+      sessions::MakeTypePayloadMapFromRoutingInfo(r, std::string());
+  SyncSourceInfo info(GetUpdatesCallerInfo::PERIODIC, types_with_payloads);
+  SyncSession* s = new SyncSession(session_context_.get(), this, info, r, w);
+  ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), POLL, s);
+}
+
+void SyncerThread::Unthrottle() {
+  DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode);
+  wait_interval_.reset();
+}
+
+void SyncerThread::Notify(SyncEngineEvent::EventCause cause) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  session_context_->NotifyListeners(SyncEngineEvent(cause));
+}
+
+bool SyncerThread::IsBackingOff() const {
+  return wait_interval_.get() && wait_interval_->mode ==
+      WaitInterval::EXPONENTIAL_BACKOFF;
+}
+
+void SyncerThread::OnSilencedUntil(const base::TimeTicks& silenced_until) {
+  wait_interval_.reset(new WaitInterval(WaitInterval::THROTTLED,
+                                        silenced_until - TimeTicks::Now()));
+  wait_interval_->timer.Start(wait_interval_->length, this,
+      &SyncerThread::Unthrottle);
+}
+
+bool SyncerThread::IsSyncingCurrentlySilenced() {
+  return wait_interval_.get() && wait_interval_->mode ==
+      WaitInterval::THROTTLED;
+}
+
+void SyncerThread::OnReceivedShortPollIntervalUpdate(
+    const base::TimeDelta& new_interval) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  syncer_short_poll_interval_seconds_ = new_interval;
+}
+
+void SyncerThread::OnReceivedLongPollIntervalUpdate(
+    const base::TimeDelta& new_interval) {
+  DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+  syncer_long_poll_interval_seconds_ = new_interval;
+}
+
+void SyncerThread::OnShouldStopSyncingPermanently() {
+  syncer_->RequestEarlyExit();  // Thread-safe.
+  Notify(SyncEngineEvent::STOP_SYNCING_PERMANENTLY);
+}
+
+void SyncerThread::OnServerConnectionEvent(
+    const ServerConnectionEvent& event) {
+  NOTIMPLEMENTED();
+}
+
+void SyncerThread::set_notifications_enabled(bool notifications_enabled) {
+  session_context_->set_notifications_enabled(notifications_enabled);
+}
+
+}  // s3
+}  // browser_sync
diff --git a/chrome/browser/sync/engine/syncer_thread2.h b/chrome/browser/sync/engine/syncer_thread2.h
new file mode 100644
index 0000000..a9848ff
--- /dev/null
+++ b/chrome/browser/sync/engine/syncer_thread2.h
@@ -0,0 +1,229 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A class to run the syncer on a thread.
+#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
+#define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
+#pragma once
+
+#include "base/linked_ptr.h"
+#include "base/observer_list.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "base/threading/thread.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "chrome/browser/sync/engine/nudge_source.h"
+#include "chrome/browser/sync/engine/polling_constants.h"
+#include "chrome/browser/sync/engine/syncer.h"
+#include "chrome/browser/sync/sessions/sync_session.h"
+#include "chrome/browser/sync/sessions/sync_session_context.h"
+
+namespace browser_sync {
+
+struct ServerConnectionEvent;
+
+namespace s3 {
+
+class SyncerThread : public sessions::SyncSession::Delegate {
+ public:
+  enum Mode {
+    // In this mode, the thread only performs configuration tasks.  This is
+    // designed to make the case where we want to download updates for a
+    // specific type only, and not continue syncing until we are moved into
+    // normal mode.
+    CONFIGURATION_MODE,
+    // Resumes polling and allows nudges, drops configuration tasks.  Runs
+    // through entire sync cycle.
+    NORMAL_MODE,
+  };
+
+  // Takes ownership of both |context| and |syncer|.
+  SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer);
+  virtual ~SyncerThread();
+
+  // Change the mode of operation.
+  // We don't use a lock when changing modes, so we won't cause currently
+  // scheduled jobs to adhere to the new mode.  We could protect it, but it
+  // doesn't buy very much as a) a session could already be in progress and it
+  // will continue no matter what, b) the scheduled sessions already contain
+  // all their required state and won't be affected by potential change at
+  // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once
+  // the mode changes all future jobs will be run against the updated mode.
+  void Start(Mode mode);
+
+  // Joins on the thread as soon as possible (currently running session
+  // completes).
+  void Stop();
+
+  // The meat and potatoes.
+  void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source,
+                     const syncable::ModelTypeBitSet& types);
+  void ScheduleNudgeWithPayloads(
+      const base::TimeDelta& delay, NudgeSource source,
+      const sessions::TypePayloadMap& types_with_payloads);
+  void ScheduleConfig(const base::TimeDelta& delay,
+                      const syncable::ModelTypeBitSet& types);
+  void ScheduleClearUserData();
+
+  // Change status of notifications in the SyncSessionContext.
+  void set_notifications_enabled(bool notifications_enabled);
+
+  // DDOS avoidance function.  Calculates how long we should wait before trying
+  // again after a failed sync attempt, where the last delay was |base_delay|.
+  // TODO(tim): Look at URLRequestThrottlerEntryInterface.
+  static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
+
+  // SyncSession::Delegate implementation.
+  virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
+  virtual bool IsSyncingCurrentlySilenced();
+  virtual void OnReceivedShortPollIntervalUpdate(
+      const base::TimeDelta& new_interval);
+  virtual void OnReceivedLongPollIntervalUpdate(
+      const base::TimeDelta& new_interval);
+  virtual void OnShouldStopSyncingPermanently();
+
+ private:
+  friend class SyncerThread2Test;
+
+  // State pertaining to exponential backoff or throttling periods.
+  struct WaitInterval;
+
+  // An enum used to describe jobs for scheduling purposes.
+  enum SyncSessionJobPurpose {
+    // Our poll timer schedules POLL jobs periodically based on a server
+    // assigned poll interval.
+    POLL,
+    // A nudge task can come from a variety of components needing to force
+    // a sync.  The source is inferable from |session.source()|.
+    NUDGE,
+    // The user invoked a function in the UI to clear their entire account
+    // and stop syncing (globally).
+    CLEAR_USER_DATA,
+    // Typically used for fetching updates for a subset of the enabled types
+    // during initial sync or reconfiguration.  We don't run all steps of
+    // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
+    CONFIGURATION,
+  };
+
+  // Internal state for every sync task that is scheduled.
+  struct SyncSessionJob;
+
+  // A component used to get time delays associated with exponential backoff.
+  // Encapsulated into a class to facilitate testing.
+  class DelayProvider {
+   public:
+    DelayProvider();
+    virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
+    virtual ~DelayProvider();
+   private:
+    DISALLOW_COPY_AND_ASSIGN(DelayProvider);
+  };
+
+  // Helper to assemble a job and post a delayed task to sync.
+  void ScheduleSyncSessionJob(const base::TimeDelta& delay,
+                              SyncSessionJobPurpose purpose,
+                              sessions::SyncSession* session);
+
+  // Invoke the Syncer to perform a sync.
+  void DoSyncSessionJob(const SyncSessionJob& job);
+
+  // Called after the Syncer has performed the sync represented by |job|, to
+  // reset our state.
+  void FinishSyncSessionJob(const SyncSessionJob& job);
+
+  // Helper to FinishSyncSessionJob to schedule the next sync operation.
+  void ScheduleNextSync(const SyncSessionJob& old_job);
+
+  // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
+  void AdjustPolling(const SyncSessionJob* old_job);
+
+  // Helper to ScheduleNextSync in case of consecutive sync errors.
+  void HandleConsecutiveContinuationError(const SyncSessionJob& old_job);
+
+  // Determines if it is legal to run a sync job for |purpose| at
+  // |scheduled_start|.  This checks current operational mode, backoff or
+  // throttling, freshness (so we don't make redundant syncs), and connection.
+  bool ShouldRunJob(SyncSessionJobPurpose purpose,
+                    const base::TimeTicks& scheduled_start);
+
+  // 'Impl' here refers to real implementation of public functions, running on
+  // |thread_|.
+  void StartImpl(Mode mode);
+  void ScheduleNudgeImpl(const base::TimeDelta& delay,
+                         NudgeSource source,
+                         const sessions::TypePayloadMap& types_with_payloads);
+  void ScheduleConfigImpl(const base::TimeDelta& delay,
+                          const ModelSafeRoutingInfo& routing_info,
+                          const std::vector<ModelSafeWorker*>& workers);
+  void ScheduleClearUserDataImpl();
+
+  // Returns true if the client is currently in exponential backoff.
+  bool IsBackingOff() const;
+
+  // Helper to signal all listeners registered with |session_context_|.
+  void Notify(SyncEngineEvent::EventCause cause);
+
+  // ServerConnectionEventListener implementation.
+  // TODO(tim): schedule a nudge when valid connection detected? in 1 minute?
+  virtual void OnServerConnectionEvent(const ServerConnectionEvent& event);
+
+  // Callback to change backoff state.
+  void DoCanaryJob();
+  void Unthrottle();
+
+  // Creates a session for a poll and performs the sync.
+  void PollTimerCallback();
+
+  // Assign |start| and |end| to appropriate SyncerStep values for the
+  // specified |purpose|.
+  void SetSyncerStepsForPurpose(SyncSessionJobPurpose purpose,
+                                SyncerStep* start,
+                                SyncerStep* end);
+
+  base::Thread thread_;
+
+  // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
+  // updated by the server.
+  base::TimeDelta syncer_short_poll_interval_seconds_;
+  base::TimeDelta syncer_long_poll_interval_seconds_;
+
+  // Periodic timer for polling.  See AdjustPolling.
+  base::RepeatingTimer<SyncerThread> poll_timer_;
+
+  // The mode of operation. We don't use a lock, see Start(...) comment.
+  Mode mode_;
+
+  // TODO(tim): Bug 26339. This needs to track more than just time I think,
+  // since the nudges could be for different types. Current impl doesn't care.
+  base::TimeTicks last_sync_session_end_time_;
+
+  // Have we observed a valid server connection?
+  bool server_connection_ok_;
+
+  // Tracks in-flight nudges so we can coalesce.
+  scoped_ptr<SyncSessionJob> pending_nudge_;
+
+  // Current wait state.  Null if we're not in backoff and not throttled.
+  scoped_ptr<WaitInterval> wait_interval_;
+
+  scoped_ptr<DelayProvider> delay_provider_;
+
+  // Invoked to run through the sync cycle.
+  scoped_ptr<Syncer> syncer_;
+
+  scoped_ptr<sessions::SyncSessionContext> session_context_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncerThread);
+};
+
+}  // namespace s3
+
+}  // namespace browser_sync
+
+// The SyncerThread manages its own internal thread and thus outlives it. We
+// don't need refcounting for posting tasks to this internal thread.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::s3::SyncerThread);
+
+#endif  // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
diff --git a/chrome/browser/sync/engine/syncer_thread2_unittest.cc b/chrome/browser/sync/engine/syncer_thread2_unittest.cc
new file mode 100644
index 0000000..1268593
--- /dev/null
+++ b/chrome/browser/sync/engine/syncer_thread2_unittest.cc
@@ -0,0 +1,711 @@
+// Copyright (c) 2011 The Chromium 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/synchronization/waitable_event.h"
+#include "base/test/test_timeouts.h"
+#include "chrome/browser/sync/engine/mock_model_safe_workers.h"
+#include "chrome/browser/sync/engine/syncer.h"
+#include "chrome/browser/sync/engine/syncer_thread2.h"
+#include "chrome/browser/sync/sessions/test_util.h"
+#include "chrome/test/sync/engine/test_directory_setter_upper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+using testing::_;
+using testing::AtLeast;
+using testing::DoAll;
+using testing::Eq;
+using testing::Invoke;
+using testing::Mock;
+using testing::Return;
+using testing::WithArg;
+
+namespace browser_sync {
+using sessions::SyncSession;
+using sessions::SyncSessionContext;
+using sessions::SyncSessionSnapshot;
+using syncable::ModelTypeBitSet;
+using sync_pb::GetUpdatesCallerInfo;
+
+class MockSyncer : public Syncer {
+ public:
+  MOCK_METHOD3(SyncShare, void(sessions::SyncSession*, SyncerStep,
+                               SyncerStep));
+};
+
+namespace s3 {
+
+// Used when tests want to record syncing activity to examine later.
+struct SyncShareRecords {
+  std::vector<TimeTicks> times;
+  std::vector<linked_ptr<SyncSessionSnapshot> > snapshots;
+};
+
+// Convenient to use in tests wishing to analyze SyncShare calls over time.
+static const size_t kMinNumSamples = 5;
+
+class SyncerThread2Test : public testing::Test {
+ public:
+  class MockDelayProvider : public SyncerThread::DelayProvider {
+   public:
+    MOCK_METHOD1(GetDelay, TimeDelta(const TimeDelta&));
+  };
+
+  virtual void SetUp() {
+    syncdb_.SetUp();
+    syncer_ = new MockSyncer();
+    delay_ = NULL;
+    registrar_.reset(MockModelSafeWorkerRegistrar::PassiveBookmarks());
+    context_ = new SyncSessionContext(NULL, syncdb_.manager(),
+        registrar_.get(), std::vector<SyncEngineEventListener*>());
+    context_->set_notifications_enabled(true);
+    context_->set_account_name("Test");
+    syncer_thread_.reset(new SyncerThread(context_, syncer_));
+    // TODO(tim): Once the SCM is hooked up, remove this.
+    syncer_thread_->server_connection_ok_ = true;
+  }
+
+  SyncerThread* syncer_thread() { return syncer_thread_.get(); }
+  MockSyncer* syncer() { return syncer_; }
+  MockDelayProvider* delay() { return delay_; }
+  TimeDelta zero() { return TimeDelta::FromSeconds(0); }
+  TimeDelta timeout() {
+    return TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms());
+  }
+
+  virtual void TearDown() {
+    syncer_thread()->Stop();
+    syncdb_.TearDown();
+  }
+
+  void AnalyzePollRun(const SyncShareRecords& records, size_t min_num_samples,
+      const TimeTicks& optimal_start, const TimeDelta& poll_interval) {
+    const std::vector<TimeTicks>& data(records.times);
+    EXPECT_GE(data.size(), min_num_samples);
+    for (size_t i = 0; i < data.size(); i++) {
+      SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
+      TimeTicks optimal_next_sync = optimal_start + poll_interval * i;
+      EXPECT_GE(data[i], optimal_next_sync);
+      EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC,
+                records.snapshots[i]->source.updates_source);
+    }
+  }
+
+  bool GetBackoffAndResetTest(base::WaitableEvent* done) {
+    syncable::ModelTypeBitSet nudge_types;
+    syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+    syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
+    done->TimedWait(timeout());
+    TearDown();
+    done->Reset();
+    Mock::VerifyAndClearExpectations(syncer());
+    bool backing_off = syncer_thread()->IsBackingOff();
+    SetUp();
+    UseMockDelayProvider();
+    EXPECT_CALL(*delay(), GetDelay(_))
+        .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1)));
+    return backing_off;
+  }
+
+  void UseMockDelayProvider() {
+    delay_ = new MockDelayProvider();
+    syncer_thread_->delay_provider_.reset(delay_);
+  }
+
+  void PostSignalTask(base::WaitableEvent* done) {
+    syncer_thread_->thread_.message_loop()->PostTask(FROM_HERE,
+        NewRunnableFunction(&SyncerThread2Test::SignalWaitableEvent, done));
+  }
+
+  void FlushLastTask(base::WaitableEvent* done) {
+    PostSignalTask(done);
+    done->TimedWait(timeout());
+    done->Reset();
+  }
+
+  static void SignalWaitableEvent(base::WaitableEvent* event) {
+    event->Signal();
+  }
+
+  // Compare a ModelTyepBitSet to a TypePayloadMap, ignoring payload values.
+  bool CompareModelTypeBitSetToTypePayloadMap(
+      const syncable::ModelTypeBitSet& lhs,
+      const sessions::TypePayloadMap& rhs) {
+    size_t count = 0;
+    for (sessions::TypePayloadMap::const_iterator i = rhs.begin();
+         i != rhs.end(); ++i, ++count) {
+      if (!lhs.test(i->first))
+        return false;
+    }
+    if (lhs.count() != count)
+      return false;
+    return true;
+  }
+
+ private:
+  scoped_ptr<SyncerThread> syncer_thread_;
+  SyncSessionContext* context_;
+  MockSyncer* syncer_;
+  MockDelayProvider* delay_;
+  scoped_ptr<MockModelSafeWorkerRegistrar> registrar_;
+  MockDirectorySetterUpper syncdb_;
+};
+
+bool RecordSyncShareImpl(SyncSession* s, SyncShareRecords* record,
+                         size_t signal_after) {
+  record->times.push_back(TimeTicks::Now());
+  record->snapshots.push_back(make_linked_ptr(new SyncSessionSnapshot(
+      s->TakeSnapshot())));
+  return record->times.size() >= signal_after;
+}
+
+ACTION_P4(RecordSyncShareAndPostSignal, record, signal_after, test, event) {
+  if (RecordSyncShareImpl(arg0, record, signal_after) && event)
+    test->PostSignalTask(event);
+}
+
+ACTION_P3(RecordSyncShare, record, signal_after, event) {
+  if (RecordSyncShareImpl(arg0, record, signal_after) && event)
+    event->Signal();
+}
+
+ACTION_P(SignalEvent, event) {
+  SyncerThread2Test::SignalWaitableEvent(event);
+}
+
+// Test nudge scheduling.
+TEST_F(SyncerThread2Test, Nudge) {
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  base::WaitableEvent done(false, false);
+  SyncShareRecords records;
+  syncable::ModelTypeBitSet model_types;
+  model_types[syncable::BOOKMARKS] = true;
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          WithArg<0>(RecordSyncShare(&records, 1U, &done))))
+      .RetiresOnSaturation();
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types);
+  done.TimedWait(timeout());
+
+  EXPECT_EQ(1U, records.snapshots.size());
+  EXPECT_TRUE(CompareModelTypeBitSetToTypePayloadMap(model_types,
+      records.snapshots[0]->source.types));
+  EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
+            records.snapshots[0]->source.updates_source);
+
+  // Make sure a second, later, nudge is unaffected by first (no coalescing).
+  SyncShareRecords records2;
+  model_types[syncable::BOOKMARKS] = false;
+  model_types[syncable::AUTOFILL] = true;
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          WithArg<0>(RecordSyncShare(&records2, 1U, &done))));
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types);
+  done.TimedWait(timeout());
+
+  EXPECT_EQ(1U, records2.snapshots.size());
+  EXPECT_TRUE(CompareModelTypeBitSetToTypePayloadMap(model_types,
+      records2.snapshots[0]->source.types));
+  EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
+            records2.snapshots[0]->source.updates_source);
+}
+
+// Test that nudges are coalesced.
+TEST_F(SyncerThread2Test, NudgeCoalescing) {
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  base::WaitableEvent done(false, false);
+  SyncShareRecords r;
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&r, 1U, &done))));
+  syncable::ModelTypeBitSet types1, types2, types3;
+  types1[syncable::BOOKMARKS] = true;
+  types2[syncable::AUTOFILL] = true;
+  types3[syncable::THEMES] = true;
+  TimeDelta delay = TimeDelta::FromMilliseconds(20);
+  TimeTicks optimal_time = TimeTicks::Now() + delay;
+  syncer_thread()->ScheduleNudge(delay, NUDGE_SOURCE_UNKNOWN, types1);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types2);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3);
+  done.TimedWait(timeout());
+
+  EXPECT_EQ(1U, r.snapshots.size());
+  EXPECT_GE(r.times[0], optimal_time);
+  EXPECT_TRUE(CompareModelTypeBitSetToTypePayloadMap(types1 | types2 | types3,
+      r.snapshots[0]->source.types));
+  EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION,
+            r.snapshots[0]->source.updates_source);
+
+  SyncShareRecords r2;
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&r2, 1U, &done))));
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3);
+  done.TimedWait(timeout());
+  EXPECT_EQ(1U, r2.snapshots.size());
+  EXPECT_TRUE(CompareModelTypeBitSetToTypePayloadMap(types3,
+      r2.snapshots[0]->source.types));
+  EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION,
+            r2.snapshots[0]->source.updates_source);
+}
+
+// Test nudge scheduling.
+TEST_F(SyncerThread2Test, NudgeWithPayloads) {
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  base::WaitableEvent done(false, false);
+  SyncShareRecords records;
+  sessions::TypePayloadMap model_types_with_payloads;
+  model_types_with_payloads[syncable::BOOKMARKS] = "test";
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          WithArg<0>(RecordSyncShare(&records, 1U, &done))))
+      .RetiresOnSaturation();
+  syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_LOCAL,
+      model_types_with_payloads);
+  done.TimedWait(timeout());
+
+  EXPECT_EQ(1U, records.snapshots.size());
+  EXPECT_EQ(model_types_with_payloads, records.snapshots[0]->source.types);
+  EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
+            records.snapshots[0]->source.updates_source);
+
+  // Make sure a second, later, nudge is unaffected by first (no coalescing).
+  SyncShareRecords records2;
+  model_types_with_payloads.erase(syncable::BOOKMARKS);
+  model_types_with_payloads[syncable::AUTOFILL] = "test2";
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          WithArg<0>(RecordSyncShare(&records2, 1U, &done))));
+  syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_LOCAL,
+      model_types_with_payloads);
+  done.TimedWait(timeout());
+
+  EXPECT_EQ(1U, records2.snapshots.size());
+  EXPECT_EQ(model_types_with_payloads, records2.snapshots[0]->source.types);
+  EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
+            records2.snapshots[0]->source.updates_source);
+}
+
+// Test that nudges are coalesced.
+TEST_F(SyncerThread2Test, NudgeWithPayloadsCoalescing) {
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  base::WaitableEvent done(false, false);
+  SyncShareRecords r;
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&r, 1U, &done))));
+  sessions::TypePayloadMap types1, types2, types3;
+  types1[syncable::BOOKMARKS] = "test1";
+  types2[syncable::AUTOFILL] = "test2";
+  types3[syncable::THEMES] = "test3";
+  TimeDelta delay = TimeDelta::FromMilliseconds(20);
+  TimeTicks optimal_time = TimeTicks::Now() + delay;
+  syncer_thread()->ScheduleNudgeWithPayloads(delay, NUDGE_SOURCE_UNKNOWN,
+      types1);
+  syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_LOCAL,
+      types2);
+  syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_NOTIFICATION,
+      types3);
+  done.TimedWait(timeout());
+
+  EXPECT_EQ(1U, r.snapshots.size());
+  EXPECT_GE(r.times[0], optimal_time);
+  sessions::TypePayloadMap coalesced_types;
+  sessions::CoalescePayloads(&coalesced_types, types1);
+  sessions::CoalescePayloads(&coalesced_types, types2);
+  sessions::CoalescePayloads(&coalesced_types, types3);
+  EXPECT_EQ(coalesced_types, r.snapshots[0]->source.types);
+  EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION,
+            r.snapshots[0]->source.updates_source);
+
+  SyncShareRecords r2;
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&r2, 1U, &done))));
+  syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_NOTIFICATION,
+      types3);
+  done.TimedWait(timeout());
+  EXPECT_EQ(1U, r2.snapshots.size());
+  EXPECT_EQ(types3, r2.snapshots[0]->source.types);
+  EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION,
+            r2.snapshots[0]->source.updates_source);
+}
+
+// Test that polling works as expected.
+TEST_F(SyncerThread2Test, Polling) {
+  SyncShareRecords records;
+  base::WaitableEvent done(false, false);
+  TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll_interval);
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
+
+  TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  done.TimedWait(timeout());
+  syncer_thread()->Stop();
+
+  AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
+}
+
+// Test that the short poll interval is used.
+TEST_F(SyncerThread2Test, PollNotificationsDisabled) {
+  SyncShareRecords records;
+  base::WaitableEvent done(false, false);
+  TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
+  syncer_thread()->OnReceivedShortPollIntervalUpdate(poll_interval);
+  syncer_thread()->set_notifications_enabled(false);
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
+
+  TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  done.TimedWait(timeout());
+  syncer_thread()->Stop();
+
+  AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
+}
+
+// Test that polling intervals are updated when needed.
+TEST_F(SyncerThread2Test, PollIntervalUpdate) {
+  SyncShareRecords records;
+  base::WaitableEvent done(false, false);
+  TimeDelta poll1(TimeDelta::FromMilliseconds(120));
+  TimeDelta poll2(TimeDelta::FromMilliseconds(30));
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll1);
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples))
+      .WillOnce(WithArg<0>(
+          sessions::test_util::SimulatePollIntervalUpdate(poll2)))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
+
+  TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2;
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  done.TimedWait(timeout());
+  syncer_thread()->Stop();
+
+  AnalyzePollRun(records, kMinNumSamples, optimal_start, poll2);
+}
+
+// Test that a sync session is run through to completion.
+TEST_F(SyncerThread2Test, HasMoreToSync) {
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  base::WaitableEvent done(false, false);
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateHasMoreToSync))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+                      SignalEvent(&done)));
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet());
+  done.TimedWait(timeout());
+  // If more nudges are scheduled, they'll be waited on by TearDown, and would
+  // cause our expectation to break.
+}
+
+// Test that no syncing occurs when throttled.
+TEST_F(SyncerThread2Test, ThrottlingDoesThrottle) {
+  syncable::ModelTypeBitSet types;
+  types[syncable::BOOKMARKS] = true;
+  base::WaitableEvent done(false, false);
+  TimeDelta poll(TimeDelta::FromMilliseconds(5));
+  TimeDelta throttle(TimeDelta::FromMinutes(10));
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle)));
+
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
+  FlushLastTask(&done);
+
+  syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
+  syncer_thread()->ScheduleConfig(zero(), types);
+  FlushLastTask(&done);
+}
+
+TEST_F(SyncerThread2Test, ThrottlingExpires) {
+  SyncShareRecords records;
+  base::WaitableEvent done(false, false);
+  TimeDelta poll(TimeDelta::FromMilliseconds(15));
+  TimeDelta throttle1(TimeDelta::FromMilliseconds(150));
+  TimeDelta throttle2(TimeDelta::FromMinutes(10));
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+
+  ::testing::InSequence seq;
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle1)))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+           WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
+
+  TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1;
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  done.TimedWait(timeout());
+  syncer_thread()->Stop();
+
+  AnalyzePollRun(records, kMinNumSamples, optimal_start, poll);
+}
+
+// Test nudges / polls don't run in config mode and config tasks do.
+TEST_F(SyncerThread2Test, ConfigurationMode) {
+  TimeDelta poll(TimeDelta::FromMilliseconds(15));
+  base::WaitableEvent done(false, false);
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(0);
+  syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
+  syncable::ModelTypeBitSet nudge_types;
+  nudge_types[syncable::AUTOFILL] = true;
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
+
+  syncable::ModelTypeBitSet config_types;
+  config_types[syncable::BOOKMARKS] = true;
+  // TODO(tim): This will fail once CONFIGURATION tasks are implemented. Update
+  // the EXPECT when that happens.
+  syncer_thread()->ScheduleConfig(zero(), config_types);
+  FlushLastTask(&done);
+}
+
+// Test that exponential backoff is properly triggered.
+TEST_F(SyncerThread2Test, BackoffTriggers) {
+  base::WaitableEvent done(false, false);
+  UseMockDelayProvider();
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          SignalEvent(&done)));
+  EXPECT_FALSE(GetBackoffAndResetTest(&done));
+  // Note GetBackoffAndResetTest clears mocks and re-instantiates the syncer.
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          SignalEvent(&done)));
+  EXPECT_FALSE(GetBackoffAndResetTest(&done));
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
+      .WillRepeatedly(DoAll(Invoke(
+          sessions::test_util::SimulateDownloadUpdatesFailed),
+          SignalEvent(&done)));
+  EXPECT_TRUE(GetBackoffAndResetTest(&done));
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
+          SignalEvent(&done)));
+  EXPECT_TRUE(GetBackoffAndResetTest(&done));
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
+      .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          SignalEvent(&done)));
+  EXPECT_FALSE(GetBackoffAndResetTest(&done));
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
+      .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          SignalEvent(&done)));
+  EXPECT_FALSE(GetBackoffAndResetTest(&done));
+}
+
+// Test that no polls or extraneous nudges occur when in backoff.
+TEST_F(SyncerThread2Test, BackoffDropsJobs) {
+  SyncShareRecords r;
+  TimeDelta poll(TimeDelta::FromMilliseconds(5));
+  base::WaitableEvent done(false, false);
+  syncable::ModelTypeBitSet types;
+  types[syncable::BOOKMARKS] = true;
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+  UseMockDelayProvider();
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(2)
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
+          RecordSyncShareAndPostSignal(&r, 2U, this, &done)));
+  EXPECT_CALL(*delay(), GetDelay(_))
+      .WillRepeatedly(Return(TimeDelta::FromDays(1)));
+
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  ASSERT_TRUE(done.TimedWait(timeout()));
+  done.Reset();
+
+  Mock::VerifyAndClearExpectations(syncer());
+  EXPECT_EQ(2U, r.snapshots.size());
+  EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC,
+            r.snapshots[0]->source.updates_source);
+  EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
+            r.snapshots[1]->source.updates_source);
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(1)
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
+          RecordSyncShareAndPostSignal(&r, 1U, this, &done)));
+
+  // We schedule a nudge with enough delay (10X poll interval) that at least
+  // one or two polls would have taken place.  The nudge should succeed.
+  syncer_thread()->ScheduleNudge(poll * 10, NUDGE_SOURCE_LOCAL, types);
+  ASSERT_TRUE(done.TimedWait(timeout()));
+  done.Reset();
+
+  Mock::VerifyAndClearExpectations(syncer());
+  Mock::VerifyAndClearExpectations(delay());
+  EXPECT_EQ(3U, r.snapshots.size());
+  EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
+            r.snapshots[2]->source.updates_source);
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(0);
+  EXPECT_CALL(*delay(), GetDelay(_)).Times(0);
+
+  syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
+  syncer_thread()->ScheduleConfig(zero(), types);
+  FlushLastTask(&done);
+
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
+  FlushLastTask(&done);
+}
+
+// Test that backoff is shaping traffic properly with consecutive errors.
+TEST_F(SyncerThread2Test, BackoffElevation) {
+  SyncShareRecords r;
+  const TimeDelta poll(TimeDelta::FromMilliseconds(10));
+  base::WaitableEvent done(false, false);
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+  UseMockDelayProvider();
+
+  const TimeDelta first = TimeDelta::FromSeconds(1);
+  const TimeDelta second = TimeDelta::FromMilliseconds(10);
+  const TimeDelta third = TimeDelta::FromMilliseconds(20);
+  const TimeDelta fourth = TimeDelta::FromMilliseconds(30);
+  const TimeDelta fifth = TimeDelta::FromDays(1);
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(kMinNumSamples)
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
+          RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
+
+  EXPECT_CALL(*delay(), GetDelay(Eq(first))).WillOnce(Return(second))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*delay(), GetDelay(Eq(second))).WillOnce(Return(third))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*delay(), GetDelay(Eq(third))).WillOnce(Return(fourth))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*delay(), GetDelay(Eq(fourth))).WillOnce(Return(fifth));
+
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  ASSERT_TRUE(done.TimedWait(timeout()));
+
+  EXPECT_GE(r.times[2] - r.times[1], second);
+  EXPECT_GE(r.times[3] - r.times[2], third);
+  EXPECT_GE(r.times[4] - r.times[3], fourth);
+}
+
+// Test that things go back to normal once a canary task makes forward progress
+// following a succession of failures.
+TEST_F(SyncerThread2Test, BackoffRelief) {
+  SyncShareRecords r;
+  const TimeDelta poll(TimeDelta::FromMilliseconds(10));
+  base::WaitableEvent done(false, false);
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+  UseMockDelayProvider();
+
+  const TimeDelta backoff = TimeDelta::FromMilliseconds(100);
+
+  EXPECT_CALL(*syncer(), SyncShare(_,_,_))
+      .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
+      .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
+      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
+          RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
+  EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff));
+
+  // Optimal start for the post-backoff poll party.
+  TimeTicks optimal_start = TimeTicks::Now() + poll + backoff;
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  done.TimedWait(timeout());
+  syncer_thread()->Stop();
+
+  // Check for healthy polling after backoff is relieved.
+  // Can't use AnalyzePollRun because first sync is a continuation. Bleh.
+  for (size_t i = 0; i < r.times.size(); i++) {
+    SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
+    TimeTicks optimal_next_sync = optimal_start + poll * i;
+    EXPECT_GE(r.times[i], optimal_next_sync);
+    EXPECT_EQ(i == 0 ? GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION
+                     : GetUpdatesCallerInfo::PERIODIC,
+              r.snapshots[i]->source.updates_source);
+  }
+}
+
+TEST_F(SyncerThread2Test, GetRecommendedDelay) {
+  EXPECT_LE(TimeDelta::FromSeconds(0),
+            SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(0)));
+  EXPECT_LE(TimeDelta::FromSeconds(1),
+            SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(1)));
+  EXPECT_LE(TimeDelta::FromSeconds(50),
+            SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(50)));
+  EXPECT_LE(TimeDelta::FromSeconds(10),
+            SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(10)));
+  EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
+            SyncerThread::GetRecommendedDelay(
+                TimeDelta::FromSeconds(kMaxBackoffSeconds)));
+  EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
+            SyncerThread::GetRecommendedDelay(
+                TimeDelta::FromSeconds(kMaxBackoffSeconds + 1)));
+}
+
+// Test that appropriate syncer steps are requested for each job type.
+TEST_F(SyncerThread2Test, SyncerSteps) {
+  // Nudges.
+  base::WaitableEvent done(false, false);
+  EXPECT_CALL(*syncer(), SyncShare(_, SYNCER_BEGIN, SYNCER_END))
+      .Times(1);
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet());
+  FlushLastTask(&done);
+  syncer_thread()->Stop();
+  Mock::VerifyAndClearExpectations(syncer());
+
+  // ClearUserData.
+  EXPECT_CALL(*syncer(), SyncShare(_, CLEAR_PRIVATE_DATA, SYNCER_END))
+      .Times(1);
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  syncer_thread()->ScheduleClearUserData();
+  FlushLastTask(&done);
+  syncer_thread()->Stop();
+  Mock::VerifyAndClearExpectations(syncer());
+
+  // Poll.
+  EXPECT_CALL(*syncer(), SyncShare(_, SYNCER_BEGIN, SYNCER_END))
+      .Times(AtLeast(1))
+      .WillRepeatedly(SignalEvent(&done));
+  const TimeDelta poll(TimeDelta::FromMilliseconds(10));
+  syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
+  syncer_thread()->Start(SyncerThread::NORMAL_MODE);
+  done.TimedWait(timeout());
+  syncer_thread()->Stop();
+  Mock::VerifyAndClearExpectations(syncer());
+  done.Reset();
+}
+
+// Test config tasks don't run during normal mode.
+// TODO(tim): Implement this test and then the functionality!
+TEST_F(SyncerThread2Test, DISABLED_NoConfigDuringNormal) {
+}
+
+// Test that starting the syncer thread without a valid connection doesn't
+// break things when a connection is detected.
+// Test config tasks don't run during normal mode.
+// TODO(tim): Implement this test and then the functionality!
+TEST_F(SyncerThread2Test, DISABLED_StartWhenNotConnected) {
+
+}
+
+}  // namespace s3
+}  // namespace browser_sync
+
+// SyncerThread won't outlive the test!
+DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::s3::SyncerThread2Test);
+
diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc
index df0733b..0ac0715 100644
--- a/chrome/browser/sync/engine/syncer_thread_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc
@@ -5,8 +5,8 @@
 #include <list>
 #include <map>
 
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "base/synchronization/waitable_event.h"
 #include "chrome/browser/sync/engine/model_safe_worker.h"
@@ -42,11 +42,23 @@
 }
 
 SyncSessionSnapshot SessionSnapshotForTest(
-    int64 num_server_changes_remaining, int64 max_local_timestamp,
+    int64 num_server_changes_remaining,
     int64 unsynced_count) {
+  std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT;
+       ++i) {
+    syncable::ModelType type(syncable::ModelTypeFromInt(i));
+    sync_pb::DataTypeProgressMarker token;
+    token.set_data_type_id(
+        syncable::GetExtensionFieldNumberFromModelType(type));
+    token.set_token("foobar");
+    token.SerializeToString(&download_progress_markers[i]);
+  }
   return SyncSessionSnapshot(SyncerStatus(), ErrorCounters(),
-      num_server_changes_remaining, max_local_timestamp, false,
-      syncable::ModelTypeBitSet(), false, false, unsynced_count, 0, false);
+      num_server_changes_remaining, false,
+      syncable::ModelTypeBitSet(), download_progress_markers,
+      false, false, unsynced_count, 0, false, sessions::SyncSourceInfo());
 }
 
 class ListenerMock : public SyncEngineEventListener {
@@ -113,7 +125,7 @@
   void WaitForDisconnect() {
     // Wait for the SyncerThread to detect loss of connection, up to a max of
     // 10 seconds to timeout the test.
-    AutoLock lock(syncer_thread()->lock_);
+    base::AutoLock lock(syncer_thread()->lock_);
     TimeTicks start = TimeTicks::Now();
     TimeDelta ten_seconds = TimeDelta::FromSeconds(10);
     while (syncer_thread()->vault_.connected_) {
@@ -127,7 +139,7 @@
   bool Pause(ListenerMock* listener) {
     WaitableEvent event(false, false);
     {
-      AutoLock lock(syncer_thread()->lock_);
+      base::AutoLock lock(syncer_thread()->lock_);
       EXPECT_CALL(*listener, OnSyncEngineEvent(
           Field(&SyncEngineEvent::what_happened,
           SyncEngineEvent::SYNCER_THREAD_PAUSED))).
@@ -141,7 +153,7 @@
   bool Resume(ListenerMock* listener) {
     WaitableEvent event(false, false);
     {
-      AutoLock lock(syncer_thread()->lock_);
+      base::AutoLock lock(syncer_thread()->lock_);
       EXPECT_CALL(*listener, OnSyncEngineEvent(
           Field(&SyncEngineEvent::what_happened,
           SyncEngineEvent::SYNCER_THREAD_RESUMED))).
@@ -157,6 +169,34 @@
     syncer_thread()->SetSyncerShortPollInterval(poll_interval);
   }
 
+  // Compare a provided TypePayloadMap to the pending nudge info stored in the
+  // SyncerThread vault.
+  bool CompareNudgeTypesToVault(const sessions::TypePayloadMap& lhs) {
+    const sessions::TypePayloadMap& vault_nudge_types =
+        syncer_thread()->vault_.pending_nudge_types_;
+    return lhs == vault_nudge_types;
+  }
+
+  // Compare a provided ModelTypeBitset to the pending nudge info stored in the
+  // SyncerThread vault. Nudge info in vault must not have any non-empty
+  // payloads.
+  bool CompareNudgeTypesBitSetToVault(const syncable::ModelTypeBitSet& lhs) {
+    sessions::TypePayloadMap model_types_with_payloads =
+        sessions::MakeTypePayloadMapFromBitSet(lhs, std::string());
+    size_t count = 0;
+    for (sessions::TypePayloadMap::const_iterator i =
+             syncer_thread()->vault_.pending_nudge_types_.begin();
+         i != syncer_thread()->vault_.pending_nudge_types_.end();
+         ++i, ++count) {
+      if (!lhs.test(i->first))
+        return false;
+    }
+    if (lhs.count() != count)
+      return false;
+    return true;
+  }
+
+
  private:
 
   virtual void OnSyncEngineEvent(const SyncEngineEvent& event) {
@@ -318,7 +358,7 @@
   scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
   syncer_thread->DisableIdleDetection();
   // Hold the lock to appease asserts in code.
-  AutoLock lock(syncer_thread->lock_);
+  base::AutoLock lock(syncer_thread->lock_);
 
   // Notifications disabled should result in a polling interval of
   // kDefaultShortPollInterval.
@@ -393,7 +433,7 @@
   // non-zero.
   {
     // More server changes remaining to download.
-    context->set_last_snapshot(SessionSnapshotForTest(1, 0, 0));
+    context->set_last_snapshot(SessionSnapshotForTest(1, 0));
     bool continue_sync_cycle_param = false;
 
     WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
@@ -441,7 +481,7 @@
     ASSERT_TRUE(continue_sync_cycle_param);
 
     // Now simulate no more server changes remaining.
-    context->set_last_snapshot(SessionSnapshotForTest(1, 1, 0));
+    context->set_last_snapshot(SessionSnapshotForTest(0, 0));
     interval = syncer_thread->CalculatePollingWaitTime(
         0,
         &user_idle_milliseconds_param,
@@ -456,9 +496,8 @@
   }
 
   {
-
     // Now try with unsynced local items.
-    context->set_last_snapshot(SessionSnapshotForTest(0, 0, 1));
+    context->set_last_snapshot(SessionSnapshotForTest(0, 1));
     bool continue_sync_cycle_param = false;
 
     WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
@@ -484,7 +523,7 @@
     ASSERT_FALSE(interval.had_nudge_during_backoff);
     ASSERT_TRUE(continue_sync_cycle_param);
 
-    context->set_last_snapshot(SessionSnapshotForTest(0, 0, 0));
+    context->set_last_snapshot(SessionSnapshotForTest(0, 0));
     interval = syncer_thread->CalculatePollingWaitTime(
         4,
         &user_idle_milliseconds_param,
@@ -500,8 +539,7 @@
 
   // Regression for exponential backoff reset when the syncer is nudged.
   {
-
-    context->set_last_snapshot(SessionSnapshotForTest(0, 0, 1));
+    context->set_last_snapshot(SessionSnapshotForTest(0, 1));
     bool continue_sync_cycle_param = false;
 
     // Expect move from default polling interval to exponential backoff due to
@@ -623,7 +661,7 @@
     ASSERT_TRUE(continue_sync_cycle_param);
 
     // Setting unsynced_count = 0 returns us to the default polling interval.
-    context->set_last_snapshot(SessionSnapshotForTest(0, 0, 0));
+    context->set_last_snapshot(SessionSnapshotForTest(0, 0));
     interval = syncer_thread->CalculatePollingWaitTime(
         4,
         &user_idle_milliseconds_param,
@@ -720,7 +758,7 @@
   syncer_thread()->NudgeSyncerWithDataTypes(5,
       SyncerThread::kUnknown,
       model_types);
-  EXPECT_EQ(model_types, syncer_thread()->vault_.pending_nudge_types_);
+  EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types));
   syncer_thread()->RequestResume();
 
   interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
@@ -729,7 +767,7 @@
 
   // SyncerThread should be waiting again.  Signal it to stop.
   EXPECT_TRUE(syncer_thread()->Stop(2000));
-  EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.none());
+  EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
 }
 
 TEST_F(SyncerThreadWithSyncerTest, NudgeWithDataTypesCoalesced) {
@@ -755,7 +793,7 @@
   syncer_thread()->NudgeSyncerWithDataTypes(100,
       SyncerThread::kUnknown,
       model_types);
-  EXPECT_EQ(model_types, syncer_thread()->vault_.pending_nudge_types_);
+  EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types));
 
   model_types[syncable::BOOKMARKS] = false;
   model_types[syncable::AUTOFILL] = true;
@@ -765,7 +803,7 @@
 
   // Reset BOOKMARKS for expectations.
   model_types[syncable::BOOKMARKS] = true;
-  EXPECT_EQ(model_types, syncer_thread()->vault_.pending_nudge_types_);
+  EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types));
 
   syncer_thread()->RequestResume();
 
@@ -775,7 +813,88 @@
 
   // SyncerThread should be waiting again.  Signal it to stop.
   EXPECT_TRUE(syncer_thread()->Stop(2000));
-  EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.none());
+  EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
+}
+
+TEST_F(SyncerThreadWithSyncerTest, NudgeWithPayloads) {
+  SyncShareIntercept interceptor;
+  connection()->SetMidCommitObserver(&interceptor);
+  // We don't want a poll to happen during this test (except the first one).
+  PreventThreadFromPolling();
+  EXPECT_TRUE(syncer_thread()->Start());
+  metadb()->Open();
+  syncer_thread()->CreateSyncer(metadb()->name());
+  const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
+  interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
+  EXPECT_EQ(static_cast<unsigned int>(1),
+            interceptor.times_sync_occured().size());
+
+  // The SyncerThread should be waiting for the poll now.  Nudge it to sync
+  // immediately (5ms).
+  sessions::TypePayloadMap nudge_types;
+  nudge_types[syncable::BOOKMARKS] = "test";
+
+  // Paused so we can verify the nudge types safely.
+  syncer_thread()->RequestPause();
+  syncer_thread()->NudgeSyncerWithPayloads(5,
+      SyncerThread::kUnknown,
+      nudge_types);
+  EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types));
+  syncer_thread()->RequestResume();
+
+  interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
+  EXPECT_EQ(static_cast<unsigned int>(2),
+      interceptor.times_sync_occured().size());
+
+  // SyncerThread should be waiting again.  Signal it to stop.
+  EXPECT_TRUE(syncer_thread()->Stop(2000));
+  EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
+}
+
+TEST_F(SyncerThreadWithSyncerTest, NudgeWithPayloadsCoalesced) {
+  SyncShareIntercept interceptor;
+  connection()->SetMidCommitObserver(&interceptor);
+  // We don't want a poll to happen during this test (except the first one).
+  PreventThreadFromPolling();
+  EXPECT_TRUE(syncer_thread()->Start());
+  metadb()->Open();
+  syncer_thread()->CreateSyncer(metadb()->name());
+  const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
+  interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
+  EXPECT_EQ(static_cast<unsigned int>(1),
+    interceptor.times_sync_occured().size());
+
+  // The SyncerThread should be waiting for the poll now.  Nudge it to sync
+  // immediately (5ms).
+  sessions::TypePayloadMap nudge_types;
+  nudge_types[syncable::BOOKMARKS] = "books";
+
+  // Paused so we can verify the nudge types safely.
+  syncer_thread()->RequestPause();
+  syncer_thread()->NudgeSyncerWithPayloads(100,
+      SyncerThread::kUnknown,
+      nudge_types);
+  EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types));
+
+  nudge_types.erase(syncable::BOOKMARKS);
+  nudge_types[syncable::AUTOFILL] = "auto";
+  syncer_thread()->NudgeSyncerWithPayloads(0,
+      SyncerThread::kUnknown,
+      nudge_types);
+
+  // Reset BOOKMARKS for expectations.
+  nudge_types[syncable::BOOKMARKS] = "books";
+  EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types));
+
+  syncer_thread()->RequestResume();
+
+  interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
+  EXPECT_EQ(static_cast<unsigned int>(2),
+      interceptor.times_sync_occured().size());
+
+  // SyncerThread should be waiting again.  Signal it to stop.
+  EXPECT_TRUE(syncer_thread()->Stop(2000));
+  EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
 }
 
 TEST_F(SyncerThreadWithSyncerTest, Throttling) {
diff --git a/chrome/browser/sync/engine/syncer_types.h b/chrome/browser/sync/engine/syncer_types.h
index 0ed1f19..0e05e0e 100644
--- a/chrome/browser/sync/engine/syncer_types.h
+++ b/chrome/browser/sync/engine/syncer_types.h
@@ -87,10 +87,12 @@
 
     // This event is sent when the thread is paused in response to a
     // pause request.
+    // TODO(tim): Deprecated.
     SYNCER_THREAD_PAUSED,
 
     // This event is sent when the thread is resumed in response to a
     // resume request.
+    // TODO(tim): Deprecated.
     SYNCER_THREAD_RESUMED,
 
     // This event is sent when the thread is waiting for a connection
diff --git a/chrome/browser/sync/engine/syncer_unittest.cc b/chrome/browser/sync/engine/syncer_unittest.cc
index 27725b3..57f8eda 100644
--- a/chrome/browser/sync/engine/syncer_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_unittest.cc
@@ -5,6 +5,8 @@
 // Syncer unit tests. Unfortunately a lot of these tests
 // are outdated and need to be reworked and updated.
 
+#include <algorithm>
+#include <limits>
 #include <list>
 #include <map>
 #include <set>
@@ -24,7 +26,9 @@
 #include "chrome/browser/sync/engine/syncer_util.h"
 #include "chrome/browser/sync/engine/syncproto.h"
 #include "chrome/browser/sync/protocol/sync.pb.h"
+#include "chrome/browser/sync/sessions/sync_session_context.h"
 #include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/sync/syncable/syncable.h"
 #include "chrome/common/deprecated/event_sys-inl.h"
 #include "chrome/test/sync/engine/mock_connection_manager.h"
@@ -150,8 +154,11 @@
     std::vector<ModelSafeWorker*> workers;
     GetModelSafeRoutingInfo(&info);
     GetWorkers(&workers);
-    return new SyncSession(context_.get(), this, sessions::SyncSourceInfo(),
-                           info, workers);
+    sessions::TypePayloadMap types =
+        sessions::MakeTypePayloadMapFromRoutingInfo(info, std::string());
+    return new SyncSession(context_.get(), this,
+        sessions::SyncSourceInfo(sync_pb::GetUpdatesCallerInfo::UNKNOWN, types),
+        info, workers);
   }
 
   bool SyncShareAsDelegate() {
@@ -712,7 +719,7 @@
 }
 
 TEST_F(SyncerTest, TestCommitListOrderingThreeItemsTallLimitedSize) {
-  syncer_->set_max_commit_batch_size(2);
+  context_->set_max_commit_batch_size(2);
   CommitOrderingTest items[] = {
     {1, ids_.FromNumber(-2001), ids_.FromNumber(-2000)},
     {0, ids_.FromNumber(-2000), ids_.FromNumber(0)},
@@ -765,7 +772,7 @@
 }
 
 TEST_F(SyncerTest, TestCommitListOrdering3LongDeletedItemsWithSizeLimit) {
-  syncer_->set_max_commit_batch_size(2);
+  context_->set_max_commit_batch_size(2);
   CommitOrderingTest items[] = {
     {0, ids_.FromNumber(1000), ids_.FromNumber(0), {DELETED, OLD_MTIME}},
     {1, ids_.FromNumber(1001), ids_.FromNumber(0), {DELETED, OLD_MTIME}},
@@ -3567,7 +3574,7 @@
 TEST_F(SyncerTest, LongChangelistWithApplicationConflict) {
   ScopedDirLookup dir(syncdb_.manager(), syncdb_.name());
   CHECK(dir.good());
-  const int DEPTH = 400;
+  const int depth = 400;
   syncable::Id folder_id = ids_.FromNumber(1);
 
   // First we an item in a folder in the root. However the folder won't come
@@ -3575,17 +3582,23 @@
   syncable::Id stuck_entry_id = TestIdFactory::FromNumber(99999);
   mock_server_->AddUpdateDirectory(stuck_entry_id,
       folder_id, "stuck", 1, 1);
-  mock_server_->SetChangesRemaining(DEPTH - 1);
+  mock_server_->SetChangesRemaining(depth - 1);
   syncer_->SyncShare(session_.get());
 
-  // Very long changelist. We should never be stuck.
-  for (int i = 0; i < DEPTH; i++) {
-    mock_server_->SetNewTimestamp(i);
-    mock_server_->SetChangesRemaining(DEPTH - i);
-    syncer_->SyncShare(session_.get());
-    EXPECT_FALSE(session_->status_controller()->syncer_status().syncer_stuck);
+  // Buffer up a very long series of downloads.
+  // We should never be stuck (conflict resolution shouldn't
+  // kick in so long as we're making forward progress).
+  for (int i = 0; i < depth; i++) {
+    mock_server_->NextUpdateBatch();
+    mock_server_->SetNewTimestamp(i + 1);
+    mock_server_->SetChangesRemaining(depth - i);
+  }
 
-    // Ensure our folder hasn't somehow applied.
+  syncer_->SyncShare(session_.get());
+  EXPECT_FALSE(session_->status_controller()->syncer_status().syncer_stuck);
+
+  // Ensure our folder hasn't somehow applied.
+  {
     ReadTransaction trans(dir, __FILE__, __LINE__);
     Entry child(&trans, GET_BY_ID, stuck_entry_id);
     EXPECT_TRUE(child.good());
diff --git a/chrome/browser/sync/engine/verify_updates_command.cc b/chrome/browser/sync/engine/verify_updates_command.cc
index 02fb3c9..2e907d0 100644
--- a/chrome/browser/sync/engine/verify_updates_command.cc
+++ b/chrome/browser/sync/engine/verify_updates_command.cc
@@ -52,6 +52,9 @@
     VerifyUpdateResult result = VerifyUpdate(&trans, update,
                                              session->routing_info());
     status->mutable_update_progress()->AddVerifyResult(result.value, update);
+    status->increment_num_updates_downloaded_by(1);
+    if (update.deleted())
+      status->increment_num_tombstone_updates_downloaded_by(1);
   }
 }
 
diff --git a/chrome/browser/sync/glue/autofill_change_processor.cc b/chrome/browser/sync/glue/autofill_change_processor.cc
index 6914308..6177f9e 100644
--- a/chrome/browser/sync/glue/autofill_change_processor.cc
+++ b/chrome/browser/sync/glue/autofill_change_processor.cc
@@ -10,9 +10,7 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/glue/autofill_change_processor2.h"
 #include "chrome/browser/sync/glue/autofill_model_associator.h"
 #include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
 #include "chrome/browser/sync/glue/do_optimistic_refresh_task.h"
@@ -22,7 +20,6 @@
 #include "chrome/browser/webdata/web_database.h"
 #include "chrome/common/guid.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 
 namespace browser_sync {
 
diff --git a/chrome/browser/sync/glue/autofill_change_processor.h b/chrome/browser/sync/glue/autofill_change_processor.h
index ba132fa..3b5ff35 100644
--- a/chrome/browser/sync/glue/autofill_change_processor.h
+++ b/chrome/browser/sync/glue/autofill_change_processor.h
@@ -12,7 +12,6 @@
 #include "chrome/browser/autofill/credit_card.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/autofill_change_processor2.h"
 #include "chrome/browser/sync/glue/change_processor.h"
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
diff --git a/chrome/browser/sync/glue/autofill_change_processor2.cc b/chrome/browser/sync/glue/autofill_change_processor2.cc
deleted file mode 100644
index 49b669c..0000000
--- a/chrome/browser/sync/glue/autofill_change_processor2.cc
+++ /dev/null
@@ -1,583 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync/glue/autofill_change_processor2.h"
-
-#include <string>
-#include <vector>
-
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/glue/autofill_model_associator.h"
-#include "chrome/browser/sync/glue/autofill_model_associator2.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/webdata/autofill_change.h"
-#include "chrome/browser/webdata/web_data_service.h"
-#include "chrome/browser/webdata/web_database.h"
-#include "chrome/common/notification_service.h"
-
-namespace browser_sync {
-
-class AutofillModelAssociator2;
-struct AutofillChangeProcessor2::AutofillChangeRecord {
-  sync_api::SyncManager::ChangeRecord::Action action_;
-  int64 id_;
-  sync_pb::AutofillSpecifics autofill_;
-  AutofillChangeRecord(sync_api::SyncManager::ChangeRecord::Action action,
-                       int64 id, const sync_pb::AutofillSpecifics& autofill)
-      : action_(action),
-        id_(id),
-        autofill_(autofill) { }
-};
-
-AutofillChangeProcessor2::AutofillChangeProcessor2(
-    AutofillModelAssociator2* model_associator,
-    WebDatabase* web_database,
-    PersonalDataManager* personal_data,
-    UnrecoverableErrorHandler* error_handler)
-    : ChangeProcessor(error_handler),
-      model_associator_(model_associator),
-      web_database_(web_database),
-      personal_data_(personal_data),
-      observing_(false) {
-  DCHECK(model_associator);
-  DCHECK(web_database);
-  DCHECK(error_handler);
-  DCHECK(personal_data);
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  StartObserving();
-}
-
-AutofillChangeProcessor2::~AutofillChangeProcessor2() {}
-
-void AutofillChangeProcessor2::Observe(NotificationType type,
-                                      const NotificationSource& source,
-                                      const NotificationDetails& details) {
-  // Ensure this notification came from our web database.
-  WebDataService* wds = Source<WebDataService>(source).ptr();
-  if (!wds || wds->GetDatabase() != web_database_)
-    return;
-
-  DCHECK(running());
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  if (!observing_)
-    return;
-
-  sync_api::WriteTransaction trans(share_handle());
-  sync_api::ReadNode autofill_root(&trans);
-  if (!autofill_root.InitByTagLookup(kAutofillTag)) {
-    error_handler()->OnUnrecoverableError(FROM_HERE,
-        "Server did not create the top-level autofill node. "
-        "We might be running against an out-of-date server.");
-    return;
-  }
-
-  switch (type.value) {
-    case NotificationType::AUTOFILL_ENTRIES_CHANGED: {
-      AutofillChangeList* changes = Details<AutofillChangeList>(details).ptr();
-      ObserveAutofillEntriesChanged(changes, &trans, autofill_root);
-      break;
-    }
-    case NotificationType::AUTOFILL_PROFILE_CHANGED: {
-      AutofillProfileChange* change =
-          Details<AutofillProfileChange>(details).ptr();
-      ObserveAutofillProfileChanged(change, &trans, autofill_root);
-      break;
-    }
-    default:
-      NOTREACHED()  << "Invalid NotificationType.";
-  }
-}
-
-void AutofillChangeProcessor2::ChangeProfileLabelIfAlreadyTaken(
-    sync_api::BaseTransaction* trans,
-    const string16& pre_update_label,
-    AutoFillProfile* profile,
-    std::string* tag) {
-  DCHECK_EQ(AutofillModelAssociator2::ProfileLabelToTag(profile->Label()),
-                                                       *tag);
-  sync_api::ReadNode read_node(trans);
-  if (!pre_update_label.empty() && pre_update_label == profile->Label())
-    return;
-  if (read_node.InitByClientTagLookup(syncable::AUTOFILL, *tag)) {
-    // Handle the edge case of duplicate labels.
-    string16 new_label(AutofillModelAssociator2::MakeUniqueLabel(
-        profile->Label(), pre_update_label, trans));
-    if (new_label.empty()) {
-      error_handler()->OnUnrecoverableError(FROM_HERE,
-          "No unique label; can't move aside");
-      return;
-    }
-    OverrideProfileLabel(new_label, profile, tag);
-  }
-}
-
-void AutofillChangeProcessor2::OverrideProfileLabel(
-    const string16& new_label,
-    AutoFillProfile* profile_to_update,
-    std::string* tag_to_update) {
-  tag_to_update->assign(AutofillModelAssociator2::ProfileLabelToTag(new_label));
-
-  profile_to_update->set_label(new_label);
-  if (!web_database_->UpdateAutoFillProfile(*profile_to_update)) {
-    std::string err = "Failed to overwrite label for node ";
-    err += UTF16ToUTF8(new_label);
-    error_handler()->OnUnrecoverableError(FROM_HERE, err);
-    return;
-  }
-
-  // Notify the PersonalDataManager that it's out of date.
-  PostOptimisticRefreshTask();
-}
-
-void AutofillChangeProcessor2::PostOptimisticRefreshTask() {
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-      new AutofillModelAssociator2::DoOptimisticRefreshTask(
-           personal_data_));
-}
-
-void AutofillChangeProcessor2::AddAutofillProfileSyncNode(
-    sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill,
-    const std::string& tag, const AutoFillProfile* profile) {
-  sync_api::WriteNode sync_node(trans);
-  if (!sync_node.InitUniqueByCreation(syncable::AUTOFILL, autofill, tag)) {
-    error_handler()->OnUnrecoverableError(FROM_HERE,
-        "Failed to create autofill sync node.");
-    return;
-  }
-  sync_node.SetTitle(UTF8ToWide(tag));
-
-  WriteAutofillProfile(*profile, &sync_node);
-  model_associator_->Associate(&tag, sync_node.GetId());
-}
-
-void AutofillChangeProcessor2::ObserveAutofillProfileChanged(
-    AutofillProfileChange* change, sync_api::WriteTransaction* trans,
-    const sync_api::ReadNode& autofill_root) {
-  std::string tag(AutofillModelAssociator2::ProfileLabelToTag(change->key()));
-  switch (change->type()) {
-    case AutofillProfileChange::ADD: {
-      scoped_ptr<AutoFillProfile> clone(
-          static_cast<AutoFillProfile*>(change->profile()->Clone()));
-      DCHECK_EQ(clone->Label(), change->key());
-      ChangeProfileLabelIfAlreadyTaken(trans, string16(), clone.get(), &tag);
-      AddAutofillProfileSyncNode(trans, autofill_root, tag, clone.get());
-      break;
-    }
-    case AutofillProfileChange::UPDATE: {
-      scoped_ptr<AutoFillProfile> clone(
-          static_cast<AutoFillProfile*>(change->profile()->Clone()));
-      std::string pre_update_tag = AutofillModelAssociator2::ProfileLabelToTag(
-          change->pre_update_label());
-      DCHECK_EQ(clone->Label(), change->key());
-      sync_api::WriteNode sync_node(trans);
-      ChangeProfileLabelIfAlreadyTaken(trans, change->pre_update_label(),
-                                       clone.get(), &tag);
-      if (pre_update_tag != tag) {
-        // If the label changes, replace the node instead of updating it.
-        RemoveSyncNode(pre_update_tag, trans);
-        AddAutofillProfileSyncNode(trans, autofill_root, tag, clone.get());
-        return;
-      }
-      int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
-      if (sync_api::kInvalidId == sync_id) {
-        std::string err = "Unexpected notification for: " + tag;
-        error_handler()->OnUnrecoverableError(FROM_HERE, err);
-        return;
-      } else {
-        if (!sync_node.InitByIdLookup(sync_id)) {
-          error_handler()->OnUnrecoverableError(FROM_HERE,
-              "Autofill node lookup failed.");
-          return;
-        }
-        WriteAutofillProfile(*clone.get(), &sync_node);
-      }
-      break;
-    }
-    case AutofillProfileChange::REMOVE: {
-      RemoveSyncNode(tag, trans);
-      break;
-    }
-  }
-}
-
-void AutofillChangeProcessor2::ObserveAutofillEntriesChanged(
-    AutofillChangeList* changes, sync_api::WriteTransaction* trans,
-    const sync_api::ReadNode& autofill_root) {
-  for (AutofillChangeList::iterator change = changes->begin();
-       change != changes->end(); ++change) {
-    switch (change->type()) {
-      case AutofillChange::ADD:
-        {
-          sync_api::WriteNode sync_node(trans);
-          std::string tag =
-              AutofillModelAssociator2::KeyToTag(change->key().name(),
-                                                change->key().value());
-          if (!sync_node.InitUniqueByCreation(syncable::AUTOFILL,
-                                              autofill_root, tag)) {
-            error_handler()->OnUnrecoverableError(FROM_HERE,
-                "Failed to create autofill sync node.");
-            return;
-          }
-
-          std::vector<base::Time> timestamps;
-          if (!web_database_->GetAutofillTimestamps(
-                  change->key().name(),
-                  change->key().value(),
-                  &timestamps)) {
-            error_handler()->OnUnrecoverableError(FROM_HERE,
-                "Failed to get timestamps.");
-            return;
-          }
-
-          sync_node.SetTitle(UTF8ToWide(tag));
-
-          WriteAutofillEntry(AutofillEntry(change->key(), timestamps),
-                             &sync_node);
-          model_associator_->Associate(&tag, sync_node.GetId());
-        }
-        break;
-
-      case AutofillChange::UPDATE:
-        {
-          sync_api::WriteNode sync_node(trans);
-          std::string tag = AutofillModelAssociator2::KeyToTag(
-              change->key().name(), change->key().value());
-          int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
-          if (sync_api::kInvalidId == sync_id) {
-            std::string err = "Unexpected notification for: " +
-                UTF16ToUTF8(change->key().name());
-            error_handler()->OnUnrecoverableError(FROM_HERE, err);
-            return;
-          } else {
-            if (!sync_node.InitByIdLookup(sync_id)) {
-              error_handler()->OnUnrecoverableError(FROM_HERE,
-                  "Autofill node lookup failed.");
-              return;
-            }
-          }
-
-          std::vector<base::Time> timestamps;
-          if (!web_database_->GetAutofillTimestamps(
-                   change->key().name(),
-                   change->key().value(),
-                   &timestamps)) {
-            error_handler()->OnUnrecoverableError(FROM_HERE,
-                "Failed to get timestamps.");
-            return;
-          }
-
-          WriteAutofillEntry(AutofillEntry(change->key(), timestamps),
-                             &sync_node);
-        }
-        break;
-      case AutofillChange::REMOVE: {
-        std::string tag = AutofillModelAssociator2::KeyToTag(
-            change->key().name(), change->key().value());
-        RemoveSyncNode(tag, trans);
-        }
-        break;
-    }
-  }
-}
-
-void AutofillChangeProcessor2::RemoveSyncNode(const std::string& tag,
-    sync_api::WriteTransaction* trans) {
-  sync_api::WriteNode sync_node(trans);
-  int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
-  if (sync_api::kInvalidId == sync_id) {
-    std::string err = "Unexpected notification for: " + tag;
-    error_handler()->OnUnrecoverableError(FROM_HERE, err);
-    return;
-  } else {
-    if (!sync_node.InitByIdLookup(sync_id)) {
-      error_handler()->OnUnrecoverableError(FROM_HERE,
-          "Autofill node lookup failed.");
-      return;
-    }
-    model_associator_->Disassociate(sync_node.GetId());
-    sync_node.Remove();
-  }
-}
-
-void AutofillChangeProcessor2::ApplyChangesFromSyncModel(
-    const sync_api::BaseTransaction* trans,
-    const sync_api::SyncManager::ChangeRecord* changes,
-    int change_count) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  if (!running())
-    return;
-  StopObserving();
-
-  sync_api::ReadNode autofill_root(trans);
-  if (!autofill_root.InitByTagLookup(kAutofillTag)) {
-    error_handler()->OnUnrecoverableError(FROM_HERE,
-        "Autofill root node lookup failed.");
-    return;
-  }
-
-  for (int i = 0; i < change_count; ++i) {
-    sync_api::SyncManager::ChangeRecord::Action action(changes[i].action);
-    if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE == action) {
-      DCHECK(changes[i].specifics.HasExtension(sync_pb::autofill))
-          << "Autofill specifics data not present on delete!";
-      const sync_pb::AutofillSpecifics& autofill =
-          changes[i].specifics.GetExtension(sync_pb::autofill);
-      if (autofill.has_value() || autofill.has_profile()) {
-        autofill_changes_.push_back(AutofillChangeRecord(changes[i].action,
-                                                         changes[i].id,
-                                                         autofill));
-      } else {
-        NOTREACHED() << "Autofill specifics has no data!";
-      }
-      continue;
-    }
-
-    // Handle an update or add.
-    sync_api::ReadNode sync_node(trans);
-    if (!sync_node.InitByIdLookup(changes[i].id)) {
-      error_handler()->OnUnrecoverableError(FROM_HERE,
-          "Autofill node lookup failed.");
-      return;
-    }
-
-    // Check that the changed node is a child of the autofills folder.
-    DCHECK(autofill_root.GetId() == sync_node.GetParentId());
-    DCHECK(syncable::AUTOFILL == sync_node.GetModelType());
-
-    const sync_pb::AutofillSpecifics& autofill(
-        sync_node.GetAutofillSpecifics());
-    int64 sync_id = sync_node.GetId();
-    if (autofill.has_value() || autofill.has_profile()) {
-      autofill_changes_.push_back(AutofillChangeRecord(changes[i].action,
-                                                       sync_id, autofill));
-    } else {
-      NOTREACHED() << "Autofill specifics has no data!";
-    }
-  }
-
-  StartObserving();
-}
-
-void AutofillChangeProcessor2::CommitChangesFromSyncModel() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  if (!running())
-    return;
-  StopObserving();
-
-  std::vector<AutofillEntry> new_entries;
-  for (unsigned int i = 0; i < autofill_changes_.size(); i++) {
-    // Handle deletions.
-    if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
-        autofill_changes_[i].action_) {
-      if (autofill_changes_[i].autofill_.has_value()) {
-        ApplySyncAutofillEntryDelete(autofill_changes_[i].autofill_);
-      } else if (autofill_changes_[i].autofill_.has_profile()) {
-        ApplySyncAutofillProfileDelete(autofill_changes_[i].autofill_.profile(),
-                                       autofill_changes_[i].id_);
-      } else {
-        NOTREACHED() << "Autofill's CommitChanges received change with no"
-            " data!";
-      }
-      continue;
-    }
-
-    // Handle update/adds.
-    if (autofill_changes_[i].autofill_.has_value()) {
-      ApplySyncAutofillEntryChange(autofill_changes_[i].action_,
-                                   autofill_changes_[i].autofill_, &new_entries,
-                                   autofill_changes_[i].id_);
-    } else if (autofill_changes_[i].autofill_.has_profile()) {
-      ApplySyncAutofillProfileChange(autofill_changes_[i].action_,
-                                     autofill_changes_[i].autofill_.profile(),
-                                     autofill_changes_[i].id_);
-    } else {
-      NOTREACHED() << "Autofill's CommitChanges received change with no data!";
-    }
-  }
-  autofill_changes_.clear();
-
-  // Make changes
-  if (!web_database_->UpdateAutofillEntries(new_entries)) {
-    error_handler()->OnUnrecoverableError(FROM_HERE,
-                                          "Could not update autofill entries.");
-    return;
-  }
-
-  PostOptimisticRefreshTask();
-
-  StartObserving();
-}
-
-void AutofillChangeProcessor2::ApplySyncAutofillEntryDelete(
-      const sync_pb::AutofillSpecifics& autofill) {
-  if (!web_database_->RemoveFormElement(
-      UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value()))) {
-    error_handler()->OnUnrecoverableError(FROM_HERE,
-        "Could not remove autofill node.");
-    return;
-  }
-}
-
-void AutofillChangeProcessor2::ApplySyncAutofillEntryChange(
-      sync_api::SyncManager::ChangeRecord::Action action,
-      const sync_pb::AutofillSpecifics& autofill,
-      std::vector<AutofillEntry>* new_entries,
-      int64 sync_id) {
-  DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action);
-
-  std::vector<base::Time> timestamps;
-  size_t timestamps_size = autofill.usage_timestamp_size();
-  for (size_t c = 0; c < timestamps_size; ++c) {
-    timestamps.push_back(
-        base::Time::FromInternalValue(autofill.usage_timestamp(c)));
-  }
-  AutofillKey k(UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value()));
-  AutofillEntry new_entry(k, timestamps);
-
-  new_entries->push_back(new_entry);
-  std::string tag(AutofillModelAssociator2::KeyToTag(k.name(), k.value()));
-  if (action == sync_api::SyncManager::ChangeRecord::ACTION_ADD)
-    model_associator_->Associate(&tag, sync_id);
-}
-
-void AutofillChangeProcessor2::ApplySyncAutofillProfileChange(
-    sync_api::SyncManager::ChangeRecord::Action action,
-    const sync_pb::AutofillProfileSpecifics& profile,
-    int64 sync_id) {
-  DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action);
-
-  std::string tag(AutofillModelAssociator2::ProfileLabelToTag(
-      UTF8ToUTF16(profile.label())));
-  switch (action) {
-    case sync_api::SyncManager::ChangeRecord::ACTION_ADD: {
-      PersonalDataManager* pdm = model_associator_->sync_service()->
-          profile()->GetPersonalDataManager();
-      scoped_ptr<AutoFillProfile> p(
-          pdm->CreateNewEmptyAutoFillProfileForDBThread(
-              UTF8ToUTF16(profile.label())));
-      AutofillModelAssociator2::OverwriteProfileWithServerData(p.get(),
-                                                              profile);
-
-      model_associator_->Associate(&tag, sync_id);
-      if (!web_database_->AddAutoFillProfile(*p.get())) {
-        NOTREACHED() << "Couldn't add autofill profile: " << profile.label();
-        return;
-      }
-      break;
-    }
-    case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
-      AutoFillProfile* p = NULL;
-      string16 label = UTF8ToUTF16(profile.label());
-      if (!web_database_->GetAutoFillProfileForLabel(label, &p)) {
-        NOTREACHED() << "Couldn't retrieve autofill profile: " << label;
-        return;
-      }
-      AutofillModelAssociator2::OverwriteProfileWithServerData(p, profile);
-      if (!web_database_->UpdateAutoFillProfile(*p)) {
-        NOTREACHED() << "Couldn't update autofill profile: " << label;
-        return;
-      }
-      delete p;
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-}
-
-void AutofillChangeProcessor2::ApplySyncAutofillProfileDelete(
-    const sync_pb::AutofillProfileSpecifics& profile,
-    int64 sync_id) {
-  string16 label(UTF8ToUTF16(profile.label()));
-  AutoFillProfile* ptr = NULL;
-  bool get_success = web_database_->GetAutoFillProfileForLabel(label, &ptr);
-  scoped_ptr<AutoFillProfile> p(ptr);
-  if (!get_success) {
-    NOTREACHED() << "Couldn't retrieve autofill profile: " << label;
-    return;
-  }
-  if (!web_database_->RemoveAutoFillProfile(p->guid())) {
-    NOTREACHED() << "Couldn't remove autofill profile: " << label;
-    return;
-  }
-  model_associator_->Disassociate(sync_id);
-}
-
-void AutofillChangeProcessor2::StartImpl(Profile* profile) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  observing_ = true;
-}
-
-void AutofillChangeProcessor2::StopImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  observing_ = false;
-}
-
-
-void AutofillChangeProcessor2::StartObserving() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  notification_registrar_.Add(this, NotificationType::AUTOFILL_ENTRIES_CHANGED,
-                              NotificationService::AllSources());
-  notification_registrar_.Add(this, NotificationType::AUTOFILL_PROFILE_CHANGED,
-                              NotificationService::AllSources());
-}
-
-void AutofillChangeProcessor2::StopObserving() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  notification_registrar_.RemoveAll();
-}
-
-// static
-void AutofillChangeProcessor2::WriteAutofillEntry(
-    const AutofillEntry& entry,
-    sync_api::WriteNode* node) {
-  sync_pb::AutofillSpecifics autofill;
-  autofill.set_name(UTF16ToUTF8(entry.key().name()));
-  autofill.set_value(UTF16ToUTF8(entry.key().value()));
-  const std::vector<base::Time>& ts(entry.timestamps());
-  for (std::vector<base::Time>::const_iterator timestamp = ts.begin();
-       timestamp != ts.end(); ++timestamp) {
-    autofill.add_usage_timestamp(timestamp->ToInternalValue());
-  }
-  node->SetAutofillSpecifics(autofill);
-}
-
-// static
-void AutofillChangeProcessor2::WriteAutofillProfile(
-    const AutoFillProfile& profile, sync_api::WriteNode* node) {
-  sync_pb::AutofillSpecifics autofill;
-  sync_pb::AutofillProfileSpecifics* s(autofill.mutable_profile());
-  s->set_label(UTF16ToUTF8(profile.Label()));
-  s->set_name_first(UTF16ToUTF8(
-      profile.GetFieldText(AutoFillType(NAME_FIRST))));
-  s->set_name_middle(UTF16ToUTF8(
-      profile.GetFieldText(AutoFillType(NAME_MIDDLE))));
-  s->set_name_last(UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST))));
-  s->set_address_home_line1(
-      UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1))));
-  s->set_address_home_line2(
-      UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2))));
-  s->set_address_home_city(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(ADDRESS_HOME_CITY))));
-  s->set_address_home_state(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(ADDRESS_HOME_STATE))));
-  s->set_address_home_country(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(ADDRESS_HOME_COUNTRY))));
-  s->set_address_home_zip(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(ADDRESS_HOME_ZIP))));
-  s->set_email_address(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(EMAIL_ADDRESS))));
-  s->set_company_name(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(COMPANY_NAME))));
-  s->set_phone_fax_whole_number(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(PHONE_FAX_WHOLE_NUMBER))));
-  s->set_phone_home_whole_number(UTF16ToUTF8(profile.GetFieldText(
-      AutoFillType(PHONE_HOME_WHOLE_NUMBER))));
-  node->SetAutofillSpecifics(autofill);
-}
-
-}  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/autofill_change_processor2.h b/chrome/browser/sync/glue/autofill_change_processor2.h
deleted file mode 100644
index 25d7f51..0000000
--- a/chrome/browser/sync/glue/autofill_change_processor2.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_CHANGE_PROCESSOR2_H_
-#define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_CHANGE_PROCESSOR2_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include "chrome/browser/autofill/autofill_profile.h"
-#include "chrome/browser/autofill/credit_card.h"
-#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/change_processor.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
-#include "chrome/browser/webdata/web_data_service.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class AutofillCreditCardChange;
-class AutofillEntry;
-class AutofillProfileChange;
-class PersonalDataManager;
-class WebDatabase;
-
-namespace browser_sync {
-
-class AutofillModelAssociator2;
-class UnrecoverableErrorHandler;
-
-// This class is responsible for taking changes from the web data service and
-// applying them to the sync_api 'syncable' model, and vice versa. All
-// operations and use of this class are from the DB thread.
-class AutofillChangeProcessor2 : public ChangeProcessor,
-                                 public NotificationObserver {
- public:
-  AutofillChangeProcessor2(AutofillModelAssociator2* model_associator,
-                          WebDatabase* web_database,
-                          PersonalDataManager* personal_data,
-                          UnrecoverableErrorHandler* error_handler);
-  virtual ~AutofillChangeProcessor2();
-
-  // NotificationObserver implementation.
-  // WebDataService -> sync_api model change application.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // sync_api model -> WebDataService change application.
-  virtual void ApplyChangesFromSyncModel(
-      const sync_api::BaseTransaction* trans,
-      const sync_api::SyncManager::ChangeRecord* changes,
-      int change_count);
-
-  // Commit any changes from ApplyChangesFromSyncModel buffered in
-  // autofill_changes_.
-  virtual void CommitChangesFromSyncModel();
-
-  // Copy the properties of the given Autofill entry into the sync
-  // node.
-  static void WriteAutofillEntry(const AutofillEntry& entry,
-                                 sync_api::WriteNode* node);
-  // As above, for autofill profiles.
-  static void WriteAutofillProfile(const AutoFillProfile& profile,
-                                   sync_api::WriteNode* node);
-  // TODO(georgey) : add the same processing for CC info (already in protocol
-  // buffers).
-
- protected:
-  virtual void StartImpl(Profile* profile);
-  virtual void StopImpl();
-
- private:
-  void StartObserving();
-  void StopObserving();
-
-  // A function to remove the sync node for an autofill entry or profile.
-  void RemoveSyncNode(const std::string& tag,
-                      sync_api::WriteTransaction* trans);
-
-  // These two methods are dispatched to by Observe depending on the type.
-  void ObserveAutofillEntriesChanged(AutofillChangeList* changes,
-      sync_api::WriteTransaction* trans,
-      const sync_api::ReadNode& autofill_root);
-  void ObserveAutofillProfileChanged(AutofillProfileChange* change,
-      sync_api::WriteTransaction* trans,
-      const sync_api::ReadNode& autofill_root);
-
-  // The following methods are the implementation of ApplyChangeFromSyncModel
-  // for the respective autofill subtypes.
-  void ApplySyncAutofillEntryChange(
-      sync_api::SyncManager::ChangeRecord::Action action,
-      const sync_pb::AutofillSpecifics& autofill,
-      std::vector<AutofillEntry>* new_entries,
-      int64 sync_id);
-  void ApplySyncAutofillProfileChange(
-      sync_api::SyncManager::ChangeRecord::Action action,
-      const sync_pb::AutofillProfileSpecifics& profile,
-      int64 sync_id);
-
-  // Delete is a special case of change application.
-  void ApplySyncAutofillEntryDelete(
-      const sync_pb::AutofillSpecifics& autofill);
-  void ApplySyncAutofillProfileDelete(
-      const sync_pb::AutofillProfileSpecifics& profile,
-      int64 sync_id);
-
-  // If the chrome model tries to add an AutoFillProfile with a label that
-  // is already in use, we perform a move-aside by calling-back into the chrome
-  // model and overwriting the label with a unique value we can apply for sync.
-  // This method should be called on an ADD notification from the chrome model.
-  // |tag| contains the unique sync client tag identifier for |profile|, which
-  // is derived from the profile label using ProfileLabelToTag.
-  // |existing_unique_label| is the current label of the object, if any; this
-  // is an allowed value, because it's taken by the item in question.
-  // For new items, set |existing_unique_label| to the empty string.
-  void ChangeProfileLabelIfAlreadyTaken(
-      sync_api::BaseTransaction* trans,
-      const string16& existing_unique_label,
-      AutoFillProfile* profile,
-      std::string* tag);
-
-  // Reassign the label of the profile, write this back to the web database,
-  // and update |tag| with the tag corresponding to the new label.
-  void OverrideProfileLabel(
-      const string16& new_label,
-      AutoFillProfile* profile_to_update,
-      std::string* tag_to_update);
-
-  // Helper to create a sync node with tag |tag|, storing |profile| as
-  // the node's AutofillSpecifics.
-  void AddAutofillProfileSyncNode(
-      sync_api::WriteTransaction* trans,
-      const sync_api::BaseNode& autofill,
-      const std::string& tag,
-      const AutoFillProfile* profile);
-
-  // Helper to post a task to the UI loop to inform the PersonalDataManager
-  // it needs to refresh itself.
-  void PostOptimisticRefreshTask();
-
-  // The two models should be associated according to this ModelAssociator.
-  AutofillModelAssociator2* model_associator_;
-
-  // The model we are processing changes from.  This is owned by the
-  // WebDataService which is kept alive by our data type controller
-  // holding a reference.
-  WebDatabase* web_database_;
-
-  // We periodically tell the PersonalDataManager to refresh as we make
-  // changes to the autofill data in the WebDatabase.
-  PersonalDataManager* personal_data_;
-
-  NotificationRegistrar notification_registrar_;
-
-  bool observing_;
-
-  // Record of changes from ApplyChangesFromSyncModel. These are then processed
-  // in CommitChangesFromSyncModel.
-  struct AutofillChangeRecord;
-  std::vector<AutofillChangeRecord> autofill_changes_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutofillChangeProcessor2);
-};
-
-}  // namespace browser_sync
-
-#endif  // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_CHANGE_PROCESSOR2_H_
-
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.cc b/chrome/browser/sync/glue/autofill_data_type_controller.cc
index 8661e14..1c57df2 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.cc
@@ -109,7 +109,7 @@
   // thread to finish the StartImpl() task.
   if (state_ == ASSOCIATING) {
     {
-      AutoLock lock(abort_association_lock_);
+      base::AutoLock lock(abort_association_lock_);
       abort_association_ = true;
       if (model_associator_.get())
         model_associator_->AbortAssociation();
@@ -189,7 +189,7 @@
   // No additional services need to be started before we can proceed
   // with model association.
   {
-    AutoLock lock(abort_association_lock_);
+    base::AutoLock lock(abort_association_lock_);
     if (abort_association_) {
       abort_association_complete_.Signal();
       return;
@@ -232,7 +232,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
 
   abort_association_complete_.Signal();
-  AutoLock lock(abort_association_lock_);
+  base::AutoLock lock(abort_association_lock_);
   if (!abort_association_) {
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                             NewRunnableMethod(
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.h b/chrome/browser/sync/glue/autofill_data_type_controller.h
index 2daedb4..05b964c 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.h
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.h
@@ -101,7 +101,7 @@
 
   NotificationRegistrar notification_registrar_;
 
-  Lock abort_association_lock_;
+  base::Lock abort_association_lock_;
   bool abort_association_;
   base::WaitableEvent abort_association_complete_;
 
diff --git a/chrome/browser/sync/glue/autofill_model_associator.cc b/chrome/browser/sync/glue/autofill_model_associator.cc
index 289d5fb..60c92d2 100644
--- a/chrome/browser/sync/glue/autofill_model_associator.cc
+++ b/chrome/browser/sync/glue/autofill_model_associator.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/sync/glue/autofill_model_associator.h"
 
+#include <functional>
 #include <vector>
 
 #include "base/task.h"
@@ -12,7 +13,6 @@
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autofill/autofill_profile.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/glue/autofill_change_processor.h"
@@ -22,7 +22,6 @@
 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
 #include "chrome/browser/webdata/web_database.h"
 #include "chrome/common/guid.h"
-#include "chrome/common/pref_names.h"
 #include "net/base/escape.h"
 
 using base::TimeTicks;
@@ -137,7 +136,7 @@
   VLOG(1) << "Associating Autofill Models";
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
   {
-    AutoLock lock(abort_association_pending_lock_);
+    base::AutoLock lock(abort_association_pending_lock_);
     abort_association_pending_ = false;
   }
 
@@ -152,8 +151,7 @@
 
   DataBundle bundle;
   {
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
 
     sync_api::ReadNode autofill_root(&trans);
     if (!autofill_root.InitByTagLookup(kAutofillTag)) {
@@ -186,12 +184,12 @@
     return false;
   }
 
-  if (sync_service_->backend()->GetAutofillMigrationState() !=
+  if (sync_service_->GetAutofillMigrationState() !=
       syncable::MIGRATED) {
     syncable::AutofillMigrationDebugInfo debug_info;
     debug_info.autofill_entries_added_during_migration =
         number_of_entries_created_;
-    sync_service_->backend()->SetAutofillMigrationDebugInfo(
+    sync_service_->SetAutofillMigrationDebugInfo(
         syncable::AutofillMigrationDebugInfo::ENTRIES_ADDED,
         debug_info);
   }
@@ -384,8 +382,7 @@
                << "might be running against an out-of-date server.";
     return false;
   }
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   sync_api::ReadNode autofill_node(&trans);
   if (!autofill_node.InitByIdLookup(autofill_sync_id)) {
@@ -402,7 +399,7 @@
 
 void AutofillModelAssociator::AbortAssociation() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  AutoLock lock(abort_association_pending_lock_);
+  base::AutoLock lock(abort_association_pending_lock_);
   abort_association_pending_ = true;
 }
 
@@ -445,8 +442,7 @@
 
 bool AutofillModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
                                                      int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode sync_node(&trans);
   if (!sync_node.InitByTagLookup(tag.c_str()))
     return false;
@@ -455,7 +451,7 @@
 }
 
 bool AutofillModelAssociator::IsAbortPending() {
-  AutoLock lock(abort_association_pending_lock_);
+  base::AutoLock lock(abort_association_pending_lock_);
   return abort_association_pending_;
 }
 
@@ -534,7 +530,7 @@
 
   // Now read the current value from the directory.
   syncable::AutofillMigrationState autofill_migration_state =
-      sync_service()->backend()->GetAutofillMigrationState();
+      sync_service_->GetAutofillMigrationState();
 
   DCHECK_NE(autofill_migration_state, syncable::NOT_DETERMINED);
 
@@ -556,7 +552,7 @@
           browser_sync::kAutofillProfileTag) ||
           autofill_profile_root_node.GetFirstChildId()==
             static_cast<int64>(0)) {
-        sync_service()->backend()->SetAutofillMigrationState(
+        sync_service_->SetAutofillMigrationState(
             syncable::NOT_MIGRATED);
 
         VLOG(1) << "[AUTOFILL MIGRATION]"
@@ -566,7 +562,7 @@
         return true;
       }
 
-      sync_service()->backend()->SetAutofillMigrationState(syncable::MIGRATED);
+      sync_service_->SetAutofillMigrationState(syncable::MIGRATED);
 
       VLOG(1) << "[AUTOFILL MIGRATION]"
               << "Current autofill migration state is migrated.";
@@ -576,4 +572,3 @@
 }
 
 }  // namespace browser_sync
-
diff --git a/chrome/browser/sync/glue/autofill_model_associator.h b/chrome/browser/sync/glue/autofill_model_associator.h
index 553580f..09cfcdc 100644
--- a/chrome/browser/sync/glue/autofill_model_associator.h
+++ b/chrome/browser/sync/glue/autofill_model_associator.h
@@ -12,11 +12,10 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/autofill_model_associator2.h"
 #include "chrome/browser/sync/glue/model_associator.h"
 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
 #include "chrome/browser/webdata/autofill_entry.h"
@@ -100,9 +99,6 @@
   // TODO(georgey) : add the same processing for CC info (already in protocol
   // buffers).
 
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
   // Is called to determine if we need to upgrade to the new
   // autofillprofile2 data type. If so we need to sync up autofillprofile
   // first to the latest available changes on the server and then upgrade
@@ -184,7 +180,7 @@
   // Abort association pending flag and lock.  If this is set to true
   // (via the AbortAssociation method), return from the
   // AssociateModels method as soon as possible.
-  Lock abort_association_pending_lock_;
+  base::Lock abort_association_pending_lock_;
   bool abort_association_pending_;
   int number_of_entries_created_;
 
diff --git a/chrome/browser/sync/glue/autofill_model_associator2.cc b/chrome/browser/sync/glue/autofill_model_associator2.cc
deleted file mode 100644
index 28872df..0000000
--- a/chrome/browser/sync/glue/autofill_model_associator2.cc
+++ /dev/null
@@ -1,547 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync/glue/autofill_model_associator2.h"
-
-#include <vector>
-
-#include "base/task.h"
-#include "base/time.h"
-#include "base/string_number_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/autofill_profile.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/autofill_change_processor.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
-#include "chrome/browser/webdata/web_database.h"
-#include "net/base/escape.h"
-
-using base::TimeTicks;
-
-namespace browser_sync {
-
-extern const char kAutofillTag[];
-extern const char kAutofillEntryNamespaceTag[];
-const char kAutofillProfileNamespaceTag[] = "autofill_profile|";
-
-static const int kMaxNumAttemptsToFindUniqueLabel = 100;
-
-struct AutofillModelAssociator2::DataBundle {
-  std::set<AutofillKey> current_entries;
-  std::vector<AutofillEntry> new_entries;
-  std::set<string16> current_profiles;
-  std::vector<AutoFillProfile*> updated_profiles;
-  std::vector<AutoFillProfile*> new_profiles;  // We own these pointers.
-  ~DataBundle() { STLDeleteElements(&new_profiles); }
-};
-
-AutofillModelAssociator2::DoOptimisticRefreshTask::DoOptimisticRefreshTask(
-    PersonalDataManager* pdm) : pdm_(pdm) {}
-
-AutofillModelAssociator2::DoOptimisticRefreshTask::~DoOptimisticRefreshTask() {}
-
-void AutofillModelAssociator2::DoOptimisticRefreshTask::Run() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  pdm_->Refresh();
-}
-
-AutofillModelAssociator2::AutofillModelAssociator2(
-    ProfileSyncService* sync_service,
-    WebDatabase* web_database,
-    PersonalDataManager* personal_data)
-    : sync_service_(sync_service),
-      web_database_(web_database),
-      personal_data_(personal_data),
-      autofill_node_id_(sync_api::kInvalidId),
-      abort_association_pending_(false) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  DCHECK(sync_service_);
-  DCHECK(web_database_);
-  DCHECK(personal_data_);
-}
-
-AutofillModelAssociator2::~AutofillModelAssociator2() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-}
-
-bool AutofillModelAssociator2::TraverseAndAssociateChromeAutofillEntries(
-    sync_api::WriteTransaction* write_trans,
-    const sync_api::ReadNode& autofill_root,
-    const std::vector<AutofillEntry>& all_entries_from_db,
-    std::set<AutofillKey>* current_entries,
-    std::vector<AutofillEntry>* new_entries) {
-
-  const std::vector<AutofillEntry>& entries = all_entries_from_db;
-  for (std::vector<AutofillEntry>::const_iterator ix = entries.begin();
-       ix != entries.end(); ++ix) {
-    std::string tag = KeyToTag(ix->key().name(), ix->key().value());
-    if (id_map_.find(tag) != id_map_.end()) {
-      // It seems that name/value pairs are not unique in the web database.
-      // As a result, we have to filter out duplicates here.  This is probably
-      // a bug in the database.
-      continue;
-    }
-
-    sync_api::ReadNode node(write_trans);
-    if (node.InitByClientTagLookup(syncable::AUTOFILL, tag)) {
-      const sync_pb::AutofillSpecifics& autofill(node.GetAutofillSpecifics());
-      DCHECK_EQ(tag, KeyToTag(UTF8ToUTF16(autofill.name()),
-                              UTF8ToUTF16(autofill.value())));
-
-      std::vector<base::Time> timestamps;
-      if (MergeTimestamps(autofill, ix->timestamps(), &timestamps)) {
-        AutofillEntry new_entry(ix->key(), timestamps);
-        new_entries->push_back(new_entry);
-
-        sync_api::WriteNode write_node(write_trans);
-        if (!write_node.InitByClientTagLookup(syncable::AUTOFILL, tag)) {
-          LOG(ERROR) << "Failed to write autofill sync node.";
-          return false;
-        }
-        AutofillChangeProcessor2::WriteAutofillEntry(new_entry, &write_node);
-      }
-
-      Associate(&tag, node.GetId());
-    } else {
-      sync_api::WriteNode node(write_trans);
-      if (!node.InitUniqueByCreation(syncable::AUTOFILL,
-                                     autofill_root, tag)) {
-        LOG(ERROR) << "Failed to create autofill sync node.";
-        return false;
-      }
-      node.SetTitle(UTF8ToWide(tag));
-      AutofillChangeProcessor2::WriteAutofillEntry(*ix, &node);
-      Associate(&tag, node.GetId());
-    }
-
-    current_entries->insert(ix->key());
-  }
-  return true;
-}
-
-bool AutofillModelAssociator2::TraverseAndAssociateChromeAutoFillProfiles(
-    sync_api::WriteTransaction* write_trans,
-    const sync_api::ReadNode& autofill_root,
-    const std::vector<AutoFillProfile*>& all_profiles_from_db,
-    std::set<string16>* current_profiles,
-    std::vector<AutoFillProfile*>* updated_profiles) {
-  const std::vector<AutoFillProfile*>& profiles = all_profiles_from_db;
-  for (std::vector<AutoFillProfile*>::const_iterator ix = profiles.begin();
-       ix != profiles.end(); ++ix) {
-    string16 label((*ix)->Label());
-    std::string tag(ProfileLabelToTag(label));
-
-    sync_api::ReadNode node(write_trans);
-    if (node.InitByClientTagLookup(syncable::AUTOFILL, tag)) {
-      const sync_pb::AutofillSpecifics& autofill(node.GetAutofillSpecifics());
-      DCHECK(autofill.has_profile());
-      DCHECK_EQ(ProfileLabelToTag(UTF8ToUTF16(autofill.profile().label())),
-                tag);
-      int64 sync_id = node.GetId();
-      if (id_map_.find(tag) != id_map_.end()) {
-        // We just looked up something we already associated.  Move aside.
-        label = MakeUniqueLabel(label, string16(), write_trans);
-        if (label.empty()) {
-          return false;
-        }
-        tag = ProfileLabelToTag(label);
-        // TODO(dhollowa): Replace with |AutoFillProfile::set_guid|.
-        // http://crbug.com/58813
-        (*ix)->set_label(label);
-        if (!MakeNewAutofillProfileSyncNode(write_trans, autofill_root,
-                                            tag, **ix, &sync_id)) {
-          return false;
-        }
-        updated_profiles->push_back(*ix);
-      } else {
-        // Overwrite local with cloud state.
-        if (OverwriteProfileWithServerData(*ix, autofill.profile()))
-          updated_profiles->push_back(*ix);
-        sync_id = node.GetId();
-      }
-
-      Associate(&tag, sync_id);
-    } else {
-      int64 id;
-      if (!MakeNewAutofillProfileSyncNode(write_trans, autofill_root,
-                                          tag, **ix, &id)) {
-        return false;
-      }
-      Associate(&tag, id);
-    }
-    current_profiles->insert(label);
-  }
-  return true;
-}
-
-// static
-string16 AutofillModelAssociator2::MakeUniqueLabel(
-    const string16& non_unique_label,
-    const string16& existing_unique_label,
-    sync_api::BaseTransaction* trans) {
-  if (!non_unique_label.empty() && non_unique_label == existing_unique_label) {
-    return existing_unique_label;
-  }
-  int unique_id = 1;  // Priming so we start by appending "2".
-  while (unique_id++ < kMaxNumAttemptsToFindUniqueLabel) {
-    string16 suffix(base::IntToString16(unique_id));
-    string16 unique_label = non_unique_label + suffix;
-    if (unique_label == existing_unique_label)
-      return unique_label;  // We'll use the one we already have.
-    sync_api::ReadNode node(trans);
-    if (node.InitByClientTagLookup(syncable::AUTOFILL,
-                                   ProfileLabelToTag(unique_label))) {
-      continue;
-    }
-    return unique_label;
-  }
-
-  LOG(ERROR) << "Couldn't create unique tag for autofill node. Srsly?!";
-  return string16();
-}
-
-bool AutofillModelAssociator2::MakeNewAutofillProfileSyncNode(
-    sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill_root,
-    const std::string& tag, const AutoFillProfile& profile, int64* sync_id) {
-  sync_api::WriteNode node(trans);
-  if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) {
-    LOG(ERROR) << "Failed to create autofill sync node.";
-    return false;
-  }
-  node.SetTitle(UTF8ToWide(tag));
-  AutofillChangeProcessor2::WriteAutofillProfile(profile, &node);
-  *sync_id = node.GetId();
-  return true;
-}
-
-
-bool AutofillModelAssociator2::LoadAutofillData(
-    std::vector<AutofillEntry>* entries,
-    std::vector<AutoFillProfile*>* profiles) {
-  if (IsAbortPending())
-    return false;
-  if (!web_database_->GetAllAutofillEntries(entries))
-    return false;
-
-  if (IsAbortPending())
-    return false;
-  if (!web_database_->GetAutoFillProfiles(profiles))
-    return false;
-
-  return true;
-}
-
-bool AutofillModelAssociator2::AssociateModels() {
-  VLOG(1) << "Associating Autofill Models";
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  {
-    AutoLock lock(abort_association_pending_lock_);
-    abort_association_pending_ = false;
-  }
-
-  // TODO(zork): Attempt to load the model association from storage.
-  std::vector<AutofillEntry> entries;
-  ScopedVector<AutoFillProfile> profiles;
-
-  if (!LoadAutofillData(&entries, &profiles.get())) {
-    LOG(ERROR) << "Could not get the autofill data from WebDatabase.";
-    return false;
-  }
-
-  DataBundle bundle;
-  {
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
-
-    sync_api::ReadNode autofill_root(&trans);
-    if (!autofill_root.InitByTagLookup(kAutofillTag)) {
-      LOG(ERROR) << "Server did not create the top-level autofill node. We "
-                 << "might be running against an out-of-date server.";
-      return false;
-    }
-
-    if (!TraverseAndAssociateChromeAutofillEntries(&trans, autofill_root,
-            entries, &bundle.current_entries, &bundle.new_entries) ||
-        !TraverseAndAssociateChromeAutoFillProfiles(&trans, autofill_root,
-            profiles.get(), &bundle.current_profiles,
-            &bundle.updated_profiles) ||
-        !TraverseAndAssociateAllSyncNodes(&trans, autofill_root, &bundle)) {
-      return false;
-    }
-  }
-
-  // Since we're on the DB thread, we don't have to worry about updating
-  // the autofill database after closing the write transaction, since
-  // this is the only thread that writes to the database.  We also don't have
-  // to worry about the sync model getting out of sync, because changes are
-  // propogated to the ChangeProcessor on this thread.
-  if (!SaveChangesToWebData(bundle)) {
-    LOG(ERROR) << "Failed to update autofill entries.";
-    return false;
-  }
-
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-      new DoOptimisticRefreshTask(personal_data_));
-  return true;
-}
-
-bool AutofillModelAssociator2::SaveChangesToWebData(const DataBundle& bundle) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-
-  if (IsAbortPending())
-    return false;
-
-  if (bundle.new_entries.size() &&
-      !web_database_->UpdateAutofillEntries(bundle.new_entries)) {
-    return false;
-  }
-
-  for (size_t i = 0; i < bundle.new_profiles.size(); i++) {
-    if (IsAbortPending())
-      return false;
-    if (!web_database_->AddAutoFillProfile(*bundle.new_profiles[i]))
-      return false;
-  }
-
-  for (size_t i = 0; i < bundle.updated_profiles.size(); i++) {
-    if (IsAbortPending())
-      return false;
-    if (!web_database_->UpdateAutoFillProfile(*bundle.updated_profiles[i]))
-      return false;
-  }
-  return true;
-}
-
-bool AutofillModelAssociator2::TraverseAndAssociateAllSyncNodes(
-    sync_api::WriteTransaction* write_trans,
-    const sync_api::ReadNode& autofill_root,
-    DataBundle* bundle) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-
-  int64 sync_child_id = autofill_root.GetFirstChildId();
-  while (sync_child_id != sync_api::kInvalidId) {
-    sync_api::ReadNode sync_child(write_trans);
-    if (!sync_child.InitByIdLookup(sync_child_id)) {
-      LOG(ERROR) << "Failed to fetch child node.";
-      return false;
-    }
-    const sync_pb::AutofillSpecifics& autofill(
-        sync_child.GetAutofillSpecifics());
-
-    if (autofill.has_value())
-      AddNativeEntryIfNeeded(autofill, bundle, sync_child);
-    else if (autofill.has_profile())
-      AddNativeProfileIfNeeded(autofill.profile(), bundle, sync_child);
-    else
-      NOTREACHED() << "AutofillSpecifics has no autofill data!";
-
-    sync_child_id = sync_child.GetSuccessorId();
-  }
-  return true;
-}
-
-void AutofillModelAssociator2::AddNativeEntryIfNeeded(
-    const sync_pb::AutofillSpecifics& autofill, DataBundle* bundle,
-    const sync_api::ReadNode& node) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  AutofillKey key(UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value()));
-
-  if (bundle->current_entries.find(key) == bundle->current_entries.end()) {
-    std::vector<base::Time> timestamps;
-    int timestamps_count = autofill.usage_timestamp_size();
-    for (int c = 0; c < timestamps_count; ++c) {
-      timestamps.push_back(base::Time::FromInternalValue(
-          autofill.usage_timestamp(c)));
-    }
-    std::string tag(KeyToTag(key.name(), key.value()));
-    Associate(&tag, node.GetId());
-    bundle->new_entries.push_back(AutofillEntry(key, timestamps));
-  }
-}
-
-void AutofillModelAssociator2::AddNativeProfileIfNeeded(
-    const sync_pb::AutofillProfileSpecifics& profile, DataBundle* bundle,
-    const sync_api::ReadNode& node) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  if (bundle->current_profiles.find(UTF8ToUTF16(profile.label())) ==
-      bundle->current_profiles.end()) {
-    std::string tag(ProfileLabelToTag(UTF8ToUTF16(profile.label())));
-    Associate(&tag, node.GetId());
-    AutoFillProfile* p = personal_data_->
-        CreateNewEmptyAutoFillProfileForDBThread(UTF8ToUTF16(profile.label()));
-    OverwriteProfileWithServerData(p, profile);
-    bundle->new_profiles.push_back(p);
-  }
-}
-
-bool AutofillModelAssociator2::DisassociateModels() {
-  id_map_.clear();
-  id_map_inverse_.clear();
-  return true;
-}
-
-bool AutofillModelAssociator2::SyncModelHasUserCreatedNodes(bool* has_nodes) {
-  DCHECK(has_nodes);
-  *has_nodes = false;
-  int64 autofill_sync_id;
-  if (!GetSyncIdForTaggedNode(kAutofillTag, &autofill_sync_id)) {
-    LOG(ERROR) << "Server did not create the top-level autofill node. We "
-               << "might be running against an out-of-date server.";
-    return false;
-  }
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
-
-  sync_api::ReadNode autofill_node(&trans);
-  if (!autofill_node.InitByIdLookup(autofill_sync_id)) {
-    LOG(ERROR) << "Server did not create the top-level autofill node. We "
-               << "might be running against an out-of-date server.";
-    return false;
-  }
-
-  // The sync model has user created nodes if the autofill folder has any
-  // children.
-  *has_nodes = sync_api::kInvalidId != autofill_node.GetFirstChildId();
-  return true;
-}
-
-void AutofillModelAssociator2::AbortAssociation() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  AutoLock lock(abort_association_pending_lock_);
-  abort_association_pending_ = true;
-}
-
-const std::string*
-AutofillModelAssociator2::GetChromeNodeFromSyncId(int64 sync_id) {
-  return NULL;
-}
-
-bool AutofillModelAssociator2::InitSyncNodeFromChromeId(
-    const std::string& node_id,
-    sync_api::BaseNode* sync_node) {
-  return false;
-}
-
-int64 AutofillModelAssociator2::GetSyncIdFromChromeId(
-    const std::string& autofill) {
-  AutofillToSyncIdMap::const_iterator iter = id_map_.find(autofill);
-  return iter == id_map_.end() ? sync_api::kInvalidId : iter->second;
-}
-
-void AutofillModelAssociator2::Associate(
-    const std::string* autofill, int64 sync_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  DCHECK_NE(sync_api::kInvalidId, sync_id);
-  DCHECK(id_map_.find(*autofill) == id_map_.end());
-  DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end());
-  id_map_[*autofill] = sync_id;
-  id_map_inverse_[sync_id] = *autofill;
-}
-
-void AutofillModelAssociator2::Disassociate(int64 sync_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  SyncIdToAutofillMap::iterator iter = id_map_inverse_.find(sync_id);
-  if (iter == id_map_inverse_.end())
-    return;
-  CHECK(id_map_.erase(iter->second));
-  id_map_inverse_.erase(iter);
-}
-
-bool AutofillModelAssociator2::GetSyncIdForTaggedNode(const std::string& tag,
-                                                     int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
-  sync_api::ReadNode sync_node(&trans);
-  if (!sync_node.InitByTagLookup(tag.c_str()))
-    return false;
-  *sync_id = sync_node.GetId();
-  return true;
-}
-
-bool AutofillModelAssociator2::IsAbortPending() {
-  AutoLock lock(abort_association_pending_lock_);
-  return abort_association_pending_;
-}
-
-// static
-std::string AutofillModelAssociator2::KeyToTag(const string16& name,
-                                              const string16& value) {
-  std::string ns(kAutofillEntryNamespaceTag);
-  return ns + EscapePath(UTF16ToUTF8(name)) + "|" +
-         EscapePath(UTF16ToUTF8(value));
-}
-
-// static
-std::string AutofillModelAssociator2::ProfileLabelToTag(const string16& label) {
-  std::string ns(kAutofillProfileNamespaceTag);
-  return ns + EscapePath(UTF16ToUTF8(label));
-}
-
-// static
-bool AutofillModelAssociator2::MergeTimestamps(
-    const sync_pb::AutofillSpecifics& autofill,
-    const std::vector<base::Time>& timestamps,
-    std::vector<base::Time>* new_timestamps) {
-  DCHECK(new_timestamps);
-  std::set<base::Time> timestamp_union(timestamps.begin(),
-                                       timestamps.end());
-
-  size_t timestamps_count = autofill.usage_timestamp_size();
-
-  bool different = timestamps.size() != timestamps_count;
-  for (size_t c = 0; c < timestamps_count; ++c) {
-    if (timestamp_union.insert(base::Time::FromInternalValue(
-            autofill.usage_timestamp(c))).second) {
-      different = true;
-    }
-  }
-
-  if (different) {
-    new_timestamps->insert(new_timestamps->begin(),
-                           timestamp_union.begin(),
-                           timestamp_union.end());
-  }
-  return different;
-}
-
-// Helper to compare the local value and cloud value of a field, merge into
-// the local value if they differ, and return whether the merge happened.
-bool MergeField2(FormGroup* f, AutoFillFieldType t,
-                const std::string& specifics_field) {
-  if (UTF16ToUTF8(f->GetFieldText(AutoFillType(t))) == specifics_field)
-    return false;
-  f->SetInfo(AutoFillType(t), UTF8ToUTF16(specifics_field));
-  return true;
-}
-
-// static
-bool AutofillModelAssociator2::OverwriteProfileWithServerData(
-    AutoFillProfile* merge_into,
-    const sync_pb::AutofillProfileSpecifics& specifics) {
-  bool diff = false;
-  AutoFillProfile* p = merge_into;
-  const sync_pb::AutofillProfileSpecifics& s(specifics);
-  diff = MergeField2(p, NAME_FIRST, s.name_first()) || diff;
-  diff = MergeField2(p, NAME_LAST, s.name_last()) || diff;
-  diff = MergeField2(p, NAME_MIDDLE, s.name_middle()) || diff;
-  diff = MergeField2(p, ADDRESS_HOME_LINE1, s.address_home_line1()) || diff;
-  diff = MergeField2(p, ADDRESS_HOME_LINE2, s.address_home_line2()) || diff;
-  diff = MergeField2(p, ADDRESS_HOME_CITY, s.address_home_city()) || diff;
-  diff = MergeField2(p, ADDRESS_HOME_STATE, s.address_home_state()) || diff;
-  diff = MergeField2(p, ADDRESS_HOME_COUNTRY, s.address_home_country()) || diff;
-  diff = MergeField2(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff;
-  diff = MergeField2(p, EMAIL_ADDRESS, s.email_address()) || diff;
-  diff = MergeField2(p, COMPANY_NAME, s.company_name()) || diff;
-  diff = MergeField2(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number())
-      || diff;
-  diff = MergeField2(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number())
-      || diff;
-  return diff;
-}
-
-}  // namespace browser_sync
-
diff --git a/chrome/browser/sync/glue/autofill_model_associator2.h b/chrome/browser/sync/glue/autofill_model_associator2.h
deleted file mode 100644
index 2b50310..0000000
--- a/chrome/browser/sync/glue/autofill_model_associator2.h
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_MODEL_ASSOCIATOR2_H_
-#define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_MODEL_ASSOCIATOR2_H_
-#pragma once
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/lock.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/model_associator.h"
-#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
-#include "chrome/browser/webdata/autofill_entry.h"
-
-class AutoFillProfile;
-
-class ProfileSyncService;
-class WebDatabase;
-
-namespace sync_api {
-class WriteTransaction;
-}
-
-namespace browser_sync {
-
-class AutofillChangeProcessor;
-class UnrecoverableErrorHandler;
-
-extern const char kAutofillTag[];
-extern const char kAutofillProfileNamespaceTag[];
-extern const char kAutofillEntryNamespaceTag[];
-
-// Contains all model association related logic:
-// * Algorithm to associate autofill model and sync model.
-// We do not check if we have local data before this run; we always
-// merge and sync.
-class AutofillModelAssociator2
-    : public PerDataTypeAssociatorInterface<std::string, std::string> {
- public:
-  static syncable::ModelType model_type() { return syncable::AUTOFILL; }
-  AutofillModelAssociator2(ProfileSyncService* sync_service,
-                          WebDatabase* web_database,
-                          PersonalDataManager* data_manager);
-  virtual ~AutofillModelAssociator2();
-
-  // A task used by this class and the change processor to inform the
-  // PersonalDataManager living on the UI thread that it needs to refresh.
-  class DoOptimisticRefreshTask : public Task {
-   public:
-    explicit DoOptimisticRefreshTask(PersonalDataManager* pdm);
-    virtual ~DoOptimisticRefreshTask();
-    virtual void Run();
-   private:
-    scoped_refptr<PersonalDataManager> pdm_;
-  };
-
-  // PerDataTypeAssociatorInterface implementation.
-  //
-  // Iterates through the sync model looking for matched pairs of items.
-  virtual bool AssociateModels();
-
-  // Clears all associations.
-  virtual bool DisassociateModels();
-
-  // The has_nodes out param is true if the sync model has nodes other
-  // than the permanent tagged nodes.
-  virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes);
-
-  // See ModelAssociator interface.
-  virtual void AbortAssociation();
-
-  // Not implemented.
-  virtual const std::string* GetChromeNodeFromSyncId(int64 sync_id);
-
-  // Not implemented.
-  virtual bool InitSyncNodeFromChromeId(const std::string& node_id,
-                                        sync_api::BaseNode* sync_node);
-
-  // Returns the sync id for the given autofill name, or sync_api::kInvalidId
-  // if the autofill name is not associated to any sync id.
-  virtual int64 GetSyncIdFromChromeId(const std::string& node_id);
-
-  // Associates the given autofill name with the given sync id.
-  virtual void Associate(const std::string* node, int64 sync_id);
-
-  // Remove the association that corresponds to the given sync id.
-  virtual void Disassociate(int64 sync_id);
-
-  // Returns whether a node with the given permanent tag was found and update
-  // |sync_id| with that node's id.
-  virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id);
-
-  static std::string KeyToTag(const string16& name, const string16& value);
-  static std::string ProfileLabelToTag(const string16& label);
-
-  static bool MergeTimestamps(const sync_pb::AutofillSpecifics& autofill,
-                              const std::vector<base::Time>& timestamps,
-                              std::vector<base::Time>* new_timestamps);
-  static bool OverwriteProfileWithServerData(
-      AutoFillProfile* merge_into,
-      const sync_pb::AutofillProfileSpecifics& specifics);
-
-  // TODO(georgey) : add the same processing for CC info (already in protocol
-  // buffers).
-
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
-  // Compute and apply suffix to a label so that the resulting label is
-  // unique in the sync database.
-  // |new_non_unique_label| is the colliding label which is to be uniquified.
-  // |existing_unique_label| is the current label of the object, if any; this
-  // is treated as a unique label even if colliding.  If no such label is
-  // available, |existing_unique_label| may be empty.
-  static string16 MakeUniqueLabel(const string16& new_non_unique_label,
-                                  const string16& existing_unique_label,
-                                  sync_api::BaseTransaction* trans);
-
- private:
-  typedef std::map<std::string, int64> AutofillToSyncIdMap;
-  typedef std::map<int64, std::string> SyncIdToAutofillMap;
-
-  // A convenience wrapper of a bunch of state we pass around while associating
-  // models, and send to the WebDatabase for persistence.
-  struct DataBundle;
-
-  // Helper to query WebDatabase for the current autofill state.
-  bool LoadAutofillData(std::vector<AutofillEntry>* entries,
-                        std::vector<AutoFillProfile*>* profiles);
-
-  // We split up model association first by autofill sub-type (entries, and
-  // profiles.  There is a Traverse* method for each of these.
-  bool TraverseAndAssociateChromeAutofillEntries(
-      sync_api::WriteTransaction* write_trans,
-      const sync_api::ReadNode& autofill_root,
-      const std::vector<AutofillEntry>& all_entries_from_db,
-      std::set<AutofillKey>* current_entries,
-      std::vector<AutofillEntry>* new_entries);
-  bool TraverseAndAssociateChromeAutoFillProfiles(
-      sync_api::WriteTransaction* write_trans,
-      const sync_api::ReadNode& autofill_root,
-      const std::vector<AutoFillProfile*>& all_profiles_from_db,
-      std::set<string16>* current_profiles,
-      std::vector<AutoFillProfile*>* updated_profiles);
-
-  // Once the above traversals are complete, we traverse the sync model to
-  // associate all remaining nodes.
-  bool TraverseAndAssociateAllSyncNodes(
-      sync_api::WriteTransaction* write_trans,
-      const sync_api::ReadNode& autofill_root,
-      DataBundle* bundle);
-
-  // Helper to persist any changes that occured during model association to
-  // the WebDatabase.
-  bool SaveChangesToWebData(const DataBundle& bundle);
-
-  // Helper to insert an AutofillEntry into the WebDatabase (e.g. in response
-  // to encountering a sync node that doesn't exist yet locally).
-  void AddNativeEntryIfNeeded(const sync_pb::AutofillSpecifics& autofill,
-                              DataBundle* bundle,
-                              const sync_api::ReadNode& node);
-
-  // Helper to insert an AutoFillProfile into the WebDatabase (e.g. in response
-  // to encountering a sync node that doesn't exist yet locally).
-  void AddNativeProfileIfNeeded(
-      const sync_pb::AutofillProfileSpecifics& profile,
-      DataBundle* bundle,
-      const sync_api::ReadNode& node);
-
-  // Helper to insert a sync node for the given AutoFillProfile (e.g. in
-  // response to encountering a native profile that doesn't exist yet in the
-  // cloud).
-  bool MakeNewAutofillProfileSyncNode(
-      sync_api::WriteTransaction* trans,
-      const sync_api::BaseNode& autofill_root,
-      const std::string& tag,
-      const AutoFillProfile& profile,
-      int64* sync_id);
-
-  // Called at various points in model association to determine if the
-  // user requested an abort.
-  bool IsAbortPending();
-
-  ProfileSyncService* sync_service_;
-  WebDatabase* web_database_;
-  PersonalDataManager* personal_data_;
-  int64 autofill_node_id_;
-
-  AutofillToSyncIdMap id_map_;
-  SyncIdToAutofillMap id_map_inverse_;
-
-  // Abort association pending flag and lock.  If this is set to true
-  // (via the AbortAssociation method), return from the
-  // AssociateModels method as soon as possible.
-  Lock abort_association_pending_lock_;
-  bool abort_association_pending_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutofillModelAssociator2);
-};
-
-}  // namespace browser_sync
-
-#endif  // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_MODEL_ASSOCIATOR2_H_
-
diff --git a/chrome/browser/sync/glue/autofill_profile_change_processor.cc b/chrome/browser/sync/glue/autofill_profile_change_processor.cc
index bb99391..51d5b07 100644
--- a/chrome/browser/sync/glue/autofill_profile_change_processor.cc
+++ b/chrome/browser/sync/glue/autofill_profile_change_processor.cc
@@ -1,6 +1,6 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.

+// Copyright (c) 2011 The Chromium Authors. All rights reserved.

 // Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file

+// found in the LICENSE file.

 

 #include "chrome/browser/sync/glue/autofill_profile_change_processor.h"

 

@@ -18,7 +18,6 @@
 #include "chrome/browser/sync/unrecoverable_error_handler.h"

 #include "chrome/browser/webdata/autofill_change.h"

 #include "chrome/browser/webdata/web_database.h"

-#include "chrome/common/notification_observer.h"

 #include "chrome/common/notification_registrar.h"

 #include "chrome/common/notification_service.h"

 #include "chrome/common/notification_type.h"

@@ -44,6 +43,8 @@
   StartObserving();

 }

 

+AutofillProfileChangeProcessor::~AutofillProfileChangeProcessor() {}

+

 AutofillProfileChangeProcessor::ScopedStopObserving::ScopedStopObserving(

     AutofillProfileChangeProcessor* processor) {

   processor_ = processor;

@@ -286,6 +287,9 @@
   node.SetTitle(UTF8ToWide(profile.guid()));

 

   WriteAutofillProfile(profile, &node);

+

+  std::string guid = profile.guid();

+  model_associator_->Associate(&guid, node.GetId());

 }

 

 void AutofillProfileChangeProcessor::StartObserving() {

@@ -335,4 +339,3 @@
 }

 

 }  // namespace browser_sync

-

diff --git a/chrome/browser/sync/glue/autofill_profile_change_processor.h b/chrome/browser/sync/glue/autofill_profile_change_processor.h
index 0b408a3..c10a15c 100644
--- a/chrome/browser/sync/glue/autofill_profile_change_processor.h
+++ b/chrome/browser/sync/glue/autofill_profile_change_processor.h
@@ -1,6 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
+
 #ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_CHANGE_PROCESSOR_H_
 #define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_CHANGE_PROCESSOR_H_
 #pragma once
@@ -31,7 +32,7 @@
       PersonalDataManager* personal_data_manager,
       UnrecoverableErrorHandler* error_handler);
 
-  virtual ~AutofillProfileChangeProcessor() {}
+  virtual ~AutofillProfileChangeProcessor();
 
   // Virtual methods from ChangeProcessor class.
   virtual void ApplyChangesFromSyncModel(
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
index 230b680..1b5214b 100644
--- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,6 +17,17 @@
         profile,
         sync_service) {}
 
+AutofillProfileDataTypeController::~AutofillProfileDataTypeController() {}
+
+syncable::ModelType AutofillProfileDataTypeController::type() {
+  return syncable::AUTOFILL_PROFILE;
+}
+
+const char* AutofillProfileDataTypeController::name() const {
+  // For logging only.
+  return "autofill_profile";
+}
+
 ProfileSyncFactory::SyncComponents
     AutofillProfileDataTypeController::CreateSyncComponents(
       ProfileSyncService* profile_sync_service,
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
index 8bb6e8e..83cafc3 100644
--- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
@@ -1,6 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
+
 #ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
 #define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
 #pragma once
@@ -16,16 +17,12 @@
       ProfileSyncFactory* profile_sync_factory,
       Profile* profile,
       ProfileSyncService* sync_service);
-  virtual ~AutofillProfileDataTypeController() {}
+  virtual ~AutofillProfileDataTypeController();
 
-  virtual syncable::ModelType type() {
-    return syncable::AUTOFILL_PROFILE;
-  }
+  virtual syncable::ModelType type();
 
-  virtual const char* name() const {
-    // For logging only.
-    return "autofill_profile";
-  }
+  virtual const char* name() const;
+
  protected:
   virtual ProfileSyncFactory::SyncComponents CreateSyncComponents(
       ProfileSyncService* profile_sync_service,
diff --git a/chrome/browser/sync/glue/autofill_profile_model_associator.cc b/chrome/browser/sync/glue/autofill_profile_model_associator.cc
index c517e2c..0b7e651 100644
--- a/chrome/browser/sync/glue/autofill_profile_model_associator.cc
+++ b/chrome/browser/sync/glue/autofill_profile_model_associator.cc
@@ -105,8 +105,7 @@
 bool AutofillProfileModelAssociator::GetSyncIdForTaggedNode(
     const std::string& tag,
     int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode sync_node(&trans);
   if (!sync_node.InitByTagLookup(tag.c_str()))
     return false;
@@ -129,7 +128,7 @@
   VLOG(1) << "Associating Autofill Models";
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
   {
-    AutoLock lock(abort_association_pending_lock_);
+    base::AutoLock lock(abort_association_pending_lock_);
     abort_association_pending_ = false;
   }
 
@@ -147,8 +146,7 @@
   {
     // The write transaction lock is held inside this block.
     // We do all the web db operations outside this block.
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
 
     sync_api::ReadNode autofill_root(&trans);
     if (!autofill_root.InitByTagLookup(kAutofillProfileTag)) {
@@ -172,15 +170,15 @@
     return false;
   }
 
-  if (sync_service_->backend()->GetAutofillMigrationState() !=
+  if (sync_service_->GetAutofillMigrationState() !=
      syncable::MIGRATED) {
     syncable::AutofillMigrationDebugInfo debug_info;
     debug_info.autofill_profile_added_during_migration =
         number_of_profiles_created_;
-    sync_service_->backend()->SetAutofillMigrationDebugInfo(
+    sync_service_->SetAutofillMigrationDebugInfo(
         syncable::AutofillMigrationDebugInfo::PROFILES_ADDED,
         debug_info);
-    sync_service()->backend()->SetAutofillMigrationState(
+    sync_service_->SetAutofillMigrationState(
         syncable::MIGRATED);
   }
 
@@ -208,8 +206,7 @@
 bool AutofillProfileModelAssociator::SyncModelHasUserCreatedNodes(
     bool *has_nodes) {
   CHECK_NE(has_nodes, reinterpret_cast<bool*>(NULL));
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   sync_api::ReadNode node(&trans);
 
@@ -458,7 +455,7 @@
 
 void AutofillProfileModelAssociator::AbortAssociation() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  AutoLock lock(abort_association_pending_lock_);
+  base::AutoLock lock(abort_association_pending_lock_);
   abort_association_pending_ = true;
 }
 
@@ -469,9 +466,16 @@
 }
 
 bool AutofillProfileModelAssociator::IsAbortPending() {
-  AutoLock lock(abort_association_pending_lock_);
+  base::AutoLock lock(abort_association_pending_lock_);
   return abort_association_pending_;
 }
 
+AutofillProfileModelAssociator::DataBundle::DataBundle() {}
+
+AutofillProfileModelAssociator::DataBundle::~DataBundle() {
+  STLDeleteElements(&new_profiles);
+}
+
+
 }  // namespace browser_sync
 
diff --git a/chrome/browser/sync/glue/autofill_profile_model_associator.h b/chrome/browser/sync/glue/autofill_profile_model_associator.h
index e2abdaf..f5d999e 100644
--- a/chrome/browser/sync/glue/autofill_profile_model_associator.h
+++ b/chrome/browser/sync/glue/autofill_profile_model_associator.h
@@ -12,8 +12,8 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/glue/model_associator.h"
@@ -93,9 +93,6 @@
   // only for completeness.
   virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id);
 
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
   static bool OverwriteProfileWithServerData(
       AutoFillProfile* merge_into,
       const sync_pb::AutofillProfileSpecifics& specifics);
@@ -175,7 +172,7 @@
   // Abort association pending flag and lock.  If this is set to true
   // (via the AbortAssociation method), return from the
   // AssociateModels method as soon as possible.
-  Lock abort_association_pending_lock_;
+  base::Lock abort_association_pending_lock_;
   bool abort_association_pending_;
 
   int number_of_profiles_created_;
@@ -184,11 +181,13 @@
 };
 
 struct AutofillProfileModelAssociator::DataBundle {
+  DataBundle();
+  ~DataBundle();
+
   std::set<std::string> current_profiles;
   std::vector<std::string> profiles_to_delete;
   std::vector<AutoFillProfile*> updated_profiles;
   std::vector<AutoFillProfile*> new_profiles;  // We own these pointers.
-  ~DataBundle() { STLDeleteElements(&new_profiles); }
 };
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.cc b/chrome/browser/sync/glue/bookmark_change_processor.cc
index ebc7f1f..4e53d53 100644
--- a/chrome/browser/sync/glue/bookmark_change_processor.cc
+++ b/chrome/browser/sync/glue/bookmark_change_processor.cc
@@ -15,8 +15,8 @@
 #include "chrome/browser/favicon_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "gfx/codec/png_codec.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace browser_sync {
 
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc
index dba6a21..3a5f1bd 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.cc
+++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
@@ -237,8 +237,7 @@
     return false;
   }
 
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   sync_api::ReadNode bookmark_bar_node(&trans);
   if (!bookmark_bar_node.InitByIdLookup(bookmark_bar_sync_id)) {
@@ -288,8 +287,7 @@
 
 bool BookmarkModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
                                                      int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode sync_node(&trans);
   if (!sync_node.InitByTagLookup(tag.c_str()))
     return false;
@@ -355,8 +353,7 @@
   dfs_stack.push(other_bookmarks_sync_id);
   dfs_stack.push(bookmark_bar_sync_id);
 
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
 
   while (!dfs_stack.empty()) {
     int64 sync_parent_id = dfs_stack.top();
@@ -419,12 +416,12 @@
     }
   }
 
-  if (sync_service_->backend()->GetAutofillMigrationState() !=
+  if (sync_service_->GetAutofillMigrationState() !=
       syncable::MIGRATED) {
     syncable::AutofillMigrationDebugInfo debug_info;
     debug_info.bookmarks_added_during_migration =
         number_of_new_sync_nodes_created_at_association_;
-    sync_service_->backend()->SetAutofillMigrationDebugInfo(
+    sync_service_->SetAutofillMigrationDebugInfo(
         syncable::AutofillMigrationDebugInfo::BOOKMARK_ADDED,
         debug_info);
   }
@@ -451,8 +448,7 @@
     return;
   }
 
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   DirtyAssociationsSyncIds::iterator iter;
   for (iter = dirty_associations_sync_ids_.begin();
        iter != dirty_associations_sync_ids_.end();
@@ -506,8 +502,7 @@
   dfs_stack.push(other_bookmarks_id);
   dfs_stack.push(bookmark_bar_id);
 
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   // Count total number of nodes in sync model so that we can compare that
   // with the total number of nodes in the bookmark model.
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.h b/chrome/browser/sync/glue/bookmark_model_associator.h
index 577979f..035f684 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.h
+++ b/chrome/browser/sync/glue/bookmark_model_associator.h
@@ -83,15 +83,15 @@
     // thread.
   }
 
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
  protected:
   // Stores the id of the node with the given tag in |sync_id|.
   // Returns of that node was found successfully.
   // Tests override this.
   virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id);
 
+  // Used by TestBookmarkModelAssociator.
+  ProfileSyncService* sync_service() { return sync_service_; }
+
  private:
   typedef std::map<int64, int64> BookmarkIdToSyncIdMap;
   typedef std::map<int64, const BookmarkNode*> SyncIdToBookmarkNodeMap;
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.cc b/chrome/browser/sync/glue/data_type_manager_impl.cc
index 0177e66..dfb13b5 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl.cc
@@ -6,6 +6,7 @@
 #include <functional>
 
 #include "base/logging.h"
+#include "base/message_loop.h"
 #include "base/task.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/sync/glue/data_type_controller.h"
@@ -160,6 +161,7 @@
   // The task will be invoked when updates are downloaded.
   state_ = DOWNLOAD_PENDING;
   backend_->ConfigureDataTypes(
+      controllers_,
       last_requested_types_,
       method_factory_.NewRunnableMethod(&DataTypeManagerImpl::DownloadReady));
 
@@ -197,8 +199,11 @@
   DCHECK(state_ == DOWNLOAD_PENDING || state_ == RESTARTING);
 
   // If we had a restart while waiting for downloads, just restart.
+  // Note: Restart() can cause DownloadReady to be directly invoked, so we post
+  // a task to avoid re-entrancy issues.
   if (state_ == RESTARTING) {
-    Restart();
+    MessageLoop::current()->PostTask(FROM_HERE,
+        method_factory_.NewRunnableMethod(&DataTypeManagerImpl::Restart));
     return;
   }
 
@@ -357,7 +362,8 @@
   for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
        it != controllers_.end(); ++it) {
     DataTypeController* dtc = (*it).second;
-    if (dtc->state() == DataTypeController::RUNNING) {
+    if (dtc->state() != DataTypeController::NOT_RUNNING &&
+        dtc->state() != DataTypeController::STOPPING) {
       dtc->Stop();
       VLOG(1) << "Stopped " << dtc->name();
     }
diff --git a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
index b8625c7..6f4cd0f 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
@@ -97,6 +97,20 @@
         WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
   }
 
+  void SetBusyStartStopExpectations(DataTypeControllerMock* mock_dtc,
+                                    DataTypeController::State busy_state) {
+    InSequence seq;
+    EXPECT_CALL(*mock_dtc, state()).
+        WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
+    EXPECT_CALL(*mock_dtc, Start(_)).
+        WillOnce(InvokeCallback((DataTypeController::OK)));
+    EXPECT_CALL(*mock_dtc, state()).
+        WillRepeatedly(Return(busy_state));
+    EXPECT_CALL(*mock_dtc, Stop()).Times(1);
+    EXPECT_CALL(*mock_dtc, state()).
+        WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
+  }
+
   void SetNotUsedExpectations(DataTypeControllerMock* mock_dtc) {
     EXPECT_CALL(*mock_dtc, Start(_)).Times(0);
     EXPECT_CALL(*mock_dtc, Stop()).Times(0);
@@ -120,7 +134,7 @@
   }
 
   void SetBackendExpectations(int times) {
-    EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(times);
+    EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(times);
     EXPECT_CALL(backend_, StartSyncingWithServer()).Times(times);
     EXPECT_CALL(backend_, RequestPause()).Times(times);
     EXPECT_CALL(backend_, RequestResume()).Times(times);
@@ -160,6 +174,37 @@
   EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
 }
 
+TEST_F(DataTypeManagerImplTest, ConfigureOneStopWhileStarting) {
+  DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
+  SetBusyStartStopExpectations(bookmark_dtc,
+                               DataTypeController::MODEL_STARTING);
+  controllers_[syncable::BOOKMARKS] = bookmark_dtc;
+  SetBackendExpectations(1);
+  DataTypeManagerImpl dtm(&backend_, controllers_);
+  types_.insert(syncable::BOOKMARKS);
+  SetConfigureStartExpectation();
+  SetConfigureDoneExpectation(DataTypeManager::OK);
+  dtm.Configure(types_);
+  EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
+  dtm.Stop();
+  EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
+}
+
+TEST_F(DataTypeManagerImplTest, ConfigureOneStopWhileAssociating) {
+  DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
+  SetBusyStartStopExpectations(bookmark_dtc, DataTypeController::ASSOCIATING);
+  controllers_[syncable::BOOKMARKS] = bookmark_dtc;
+  SetBackendExpectations(1);
+  DataTypeManagerImpl dtm(&backend_, controllers_);
+  types_.insert(syncable::BOOKMARKS);
+  SetConfigureStartExpectation();
+  SetConfigureDoneExpectation(DataTypeManager::OK);
+  dtm.Configure(types_);
+  EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
+  dtm.Stop();
+  EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
+}
+
 TEST_F(DataTypeManagerImplTest, OneWaitingForCrypto) {
   DataTypeControllerMock* password_dtc = MakePasswordDTC();
   EXPECT_CALL(*password_dtc, state()).
@@ -290,7 +335,7 @@
   controllers_[syncable::PREFERENCES] = preference_dtc;
 
   // Don't notify the first time pause is called.
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(2);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
   EXPECT_CALL(backend_, RequestPause()).
       WillOnce(Return(true)).
@@ -326,7 +371,7 @@
   SetNotUsedExpectations(bookmark_dtc);
   controllers_[syncable::BOOKMARKS] = bookmark_dtc;
 
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   // Never notify when RequestPause is called.
   EXPECT_CALL(backend_, RequestPause()).WillOnce(Return(true));
@@ -357,7 +402,7 @@
   SetStartStopExpectations(preference_dtc);
   controllers_[syncable::PREFERENCES] = preference_dtc;
 
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(2);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
   EXPECT_CALL(backend_, RequestPause()).Times(2);
   // Don't notify the first time resume is called.
@@ -394,7 +439,7 @@
   SetStartStopExpectations(bookmark_dtc);
   controllers_[syncable::BOOKMARKS] = bookmark_dtc;
 
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   EXPECT_CALL(backend_, RequestPause()).Times(1);
   // Never notify pause resumed.
@@ -429,7 +474,7 @@
   DataTypeManagerImpl dtm(&backend_, controllers_);
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED);
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   EXPECT_CALL(backend_, RequestPause()).Times(1);
   EXPECT_CALL(backend_, RequestResume()).Times(0);
@@ -457,7 +502,7 @@
   DataTypeManagerImpl dtm(&backend_, controllers_);
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::ABORTED);
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   EXPECT_CALL(backend_, RequestPause()).Times(1);
   EXPECT_CALL(backend_, RequestResume()).Times(0);
@@ -492,7 +537,7 @@
   DataTypeManagerImpl dtm(&backend_, controllers_);
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED);
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   EXPECT_CALL(backend_, RequestPause()).Times(1);
   EXPECT_CALL(backend_, RequestResume()).Times(0);
@@ -513,7 +558,7 @@
   DataTypeManagerImpl dtm(&backend_, controllers_);
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   EXPECT_CALL(backend_, RequestPause()).WillOnce(Return(false));
   EXPECT_CALL(backend_, RequestResume()).Times(0);
@@ -531,7 +576,7 @@
   DataTypeManagerImpl dtm(&backend_, controllers_);
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
   EXPECT_CALL(backend_, RequestPause()).Times(1);
   EXPECT_CALL(backend_, RequestResume()).WillOnce(Return(false));
@@ -556,8 +601,8 @@
   CancelableTask* task;
   // Grab the task the first time this is called so we can configure
   // before it is finished.
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).
-      WillOnce(SaveArg<1>(&task)).
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).
+      WillOnce(SaveArg<2>(&task)).
       WillOnce(DoDefault());
   EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
   EXPECT_CALL(backend_, RequestPause()).Times(1);
@@ -575,10 +620,12 @@
   // Should now be RESTARTING.
   EXPECT_EQ(DataTypeManager::RESTARTING, dtm.state());
 
-  // Run the task, and this should finish the restart and eventually
-  // get us configured.
+  // Running the task will queue a restart task to the message loop, and
+  // eventually get us configured.
   task->Run();
   delete task;
+  EXPECT_EQ(DataTypeManager::RESTARTING, dtm.state());
+  MessageLoop::current()->RunAllPending();
   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
 
   dtm.Stop();
@@ -596,8 +643,8 @@
   CancelableTask* task;
   // Grab the task the first time this is called so we can stop
   // before it is finished.
-  EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).
-      WillOnce(SaveArg<1>(&task));
+  EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).
+      WillOnce(SaveArg<2>(&task));
   EXPECT_CALL(backend_, StartSyncingWithServer());
   EXPECT_CALL(backend_, RequestPause()).Times(0);
   EXPECT_CALL(backend_, RequestResume()).Times(0);
diff --git a/chrome/browser/sync/glue/extension_sync.cc b/chrome/browser/sync/glue/extension_sync.cc
index 83068df..3933515 100644
--- a/chrome/browser/sync/glue/extension_sync.cc
+++ b/chrome/browser/sync/glue/extension_sync.cc
@@ -23,8 +23,7 @@
                          bool* has_children) {
   CHECK(has_children);
   *has_children = false;
-  sync_api::ReadTransaction trans(
-      sync_service->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service->GetUserShare());
   sync_api::ReadNode node(&trans);
   if (!node.InitByTagLookup(tag)) {
     LOG(ERROR) << "Root node with tag " << tag << " does not exist";
@@ -148,8 +147,7 @@
     const std::set<std::string>& unsynced_extensions,
     ProfileSyncService* sync_service,
     ExtensionDataMap* extension_data_map) {
-  sync_api::WriteTransaction trans(
-      sync_service->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByTagLookup(root_node_tag)) {
     LOG(ERROR) << GetRootNodeDoesNotExistError(root_node_tag);
@@ -324,8 +322,7 @@
 bool FlushExtensionData(const ExtensionSyncTraits& traits,
                         const ExtensionDataMap& extension_data_map,
                         ProfileSyncService* sync_service) {
-  sync_api::WriteTransaction trans(
-      sync_service->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByTagLookup(traits.root_node_tag)) {
     LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag);
@@ -388,8 +385,7 @@
   ExtensionData extension_data =
       ExtensionData::FromData(ExtensionData::CLIENT, client_data);
 
-  sync_api::WriteTransaction trans(
-      sync_service->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service->GetUserShare());
 
   sync_api::ReadNode node(&trans);
   if (node.InitByClientTagLookup(traits.model_type, id)) {
@@ -428,8 +424,7 @@
 void RemoveServerData(const ExtensionSyncTraits& traits,
                       const std::string& id,
                       ProfileSyncService* sync_service) {
-  sync_api::WriteTransaction trans(
-      sync_service->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service->GetUserShare());
   sync_api::WriteNode write_node(&trans);
   if (write_node.InitByClientTagLookup(traits.model_type, id)) {
     write_node.Remove();
diff --git a/chrome/browser/sync/glue/http_bridge.cc b/chrome/browser/sync/glue/http_bridge.cc
index 2ec5a1b..b51975c 100644
--- a/chrome/browser/sync/glue/http_bridge.cc
+++ b/chrome/browser/sync/glue/http_bridge.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -26,10 +26,11 @@
     : baseline_context_getter_(baseline_context_getter) {
 }
 
-URLRequestContext* HttpBridge::RequestContextGetter::GetURLRequestContext() {
+net::URLRequestContext*
+HttpBridge::RequestContextGetter::GetURLRequestContext() {
   // Lazily create the context.
   if (!context_) {
-    URLRequestContext* baseline_context =
+    net::URLRequestContext* baseline_context =
         baseline_context_getter_->GetURLRequestContext();
     context_ = new RequestContext(baseline_context);
     baseline_context_getter_ = NULL;
@@ -67,7 +68,8 @@
   static_cast<HttpBridge*>(http)->Release();
 }
 
-HttpBridge::RequestContext::RequestContext(URLRequestContext* baseline_context)
+HttpBridge::RequestContext::RequestContext(
+    net::URLRequestContext* baseline_context)
     : baseline_context_(baseline_context) {
 
   // Create empty, in-memory cookie store.
@@ -85,7 +87,7 @@
   net::HttpNetworkSession* session =
       baseline_context->http_transaction_factory()->GetSession();
   DCHECK(session);
-  http_transaction_factory_ = net::HttpNetworkLayer::CreateFactory(session);
+  http_transaction_factory_ = new net::HttpNetworkLayer(session);
 
   // TODO(timsteele): We don't currently listen for pref changes of these
   // fields or CookiePolicy; I'm not sure we want to strictly follow the
@@ -219,15 +221,16 @@
   return value;
 }
 
-void HttpBridge::OnURLFetchComplete(const URLFetcher *source, const GURL &url,
-                                    const URLRequestStatus &status,
+void HttpBridge::OnURLFetchComplete(const URLFetcher *source,
+                                    const GURL &url,
+                                    const net::URLRequestStatus &status,
                                     int response_code,
                                     const ResponseCookies &cookies,
                                     const std::string &data) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   request_completed_ = true;
-  request_succeeded_ = (URLRequestStatus::SUCCESS == status.status());
+  request_succeeded_ = (net::URLRequestStatus::SUCCESS == status.status());
   http_response_code_ = response_code;
   os_error_code_ = status.os_error();
 
diff --git a/chrome/browser/sync/glue/http_bridge.h b/chrome/browser/sync/glue/http_bridge.h
index 5fb2419..57c9f94 100644
--- a/chrome/browser/sync/glue/http_bridge.h
+++ b/chrome/browser/sync/glue/http_bridge.h
@@ -45,7 +45,7 @@
    public:
     // |baseline_context| is used to obtain the accept-language,
     // accept-charsets, and proxy service information for bridged requests.
-    // Typically |baseline_context| should be the URLRequestContext of the
+    // Typically |baseline_context| should be the net::URLRequestContext of the
     // currently active profile.
     explicit RequestContext(net::URLRequestContext* baseline_context);
 
@@ -86,7 +86,7 @@
    private:
     ~RequestContextGetter() {}
 
-    // User agent to apply to the URLRequestContext.
+    // User agent to apply to the net::URLRequestContext.
     std::string user_agent_;
 
     scoped_refptr<URLRequestContextGetter> baseline_context_getter_;
@@ -146,7 +146,7 @@
   // still have a function to statically pass to PostTask.
   void CallMakeAsynchronousPost() { MakeAsynchronousPost(); }
 
-  // Gets a customized URLRequestContext for bridged requests. See
+  // Gets a customized net::URLRequestContext for bridged requests. See
   // RequestContext definition for details.
   scoped_refptr<RequestContextGetter> context_getter_for_request_;
 
diff --git a/chrome/browser/sync/glue/http_bridge_unittest.cc b/chrome/browser/sync/glue/http_bridge_unittest.cc
index f9aa32c..88cd775 100644
--- a/chrome/browser/sync/glue/http_bridge_unittest.cc
+++ b/chrome/browser/sync/glue/http_bridge_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,8 @@
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/sync/glue/http_bridge.h"
 #include "chrome/common/net/test_url_fetcher_factory.h"
-#include "net/url_request/url_request_unittest.h"
+#include "chrome/test/test_url_request_context_getter.h"
+#include "net/url_request/url_request_test_util.h"
 #include "net/test/test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -18,24 +19,6 @@
 const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data");
 }
 
-// Lazy getter for TestURLRequestContext instances.
-class TestURLRequestContextGetter : public URLRequestContextGetter {
- public:
-  virtual URLRequestContext* GetURLRequestContext() {
-    if (!context_)
-      context_ = new TestURLRequestContext;
-    return context_;
-  }
-  virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const {
-    return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
-  }
-
- private:
-  ~TestURLRequestContextGetter() {}
-
-  scoped_refptr<URLRequestContext> context_;
-};
-
 class HttpBridgeTest : public testing::Test {
  public:
   HttpBridgeTest()
@@ -137,7 +120,8 @@
 
     std::string response_content = "success!";
     DummyURLFetcher fetcher;
-    OnURLFetchComplete(&fetcher, GURL("www.google.com"), URLRequestStatus(),
+    OnURLFetchComplete(&fetcher, GURL("www.google.com"),
+                       net::URLRequestStatus(),
                        200, cookies, response_content);
   }
   HttpBridgeTest* test_;
diff --git a/chrome/browser/sync/glue/model_associator_mock.cc b/chrome/browser/sync/glue/model_associator_mock.cc
new file mode 100644
index 0000000..f05ede4
--- /dev/null
+++ b/chrome/browser/sync/glue/model_associator_mock.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/glue/model_associator_mock.h"
+
+namespace browser_sync {
+
+ModelAssociatorMock::ModelAssociatorMock() {}
+
+ModelAssociatorMock::~ModelAssociatorMock() {}
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/model_associator_mock.h b/chrome/browser/sync/glue/model_associator_mock.h
index 219a204..a949932 100644
--- a/chrome/browser/sync/glue/model_associator_mock.h
+++ b/chrome/browser/sync/glue/model_associator_mock.h
@@ -13,6 +13,9 @@
 
 class ModelAssociatorMock : public AssociatorInterface {
  public:
+  ModelAssociatorMock();
+  virtual ~ModelAssociatorMock();
+
   MOCK_METHOD0(AssociateModels, bool());
   MOCK_METHOD0(DisassociateModels, bool());
   MOCK_METHOD1(SyncModelHasUserCreatedNodes, bool(bool* has_nodes));
diff --git a/chrome/browser/sync/glue/password_data_type_controller.cc b/chrome/browser/sync/glue/password_data_type_controller.cc
index c483860..b43b5ba 100644
--- a/chrome/browser/sync/glue/password_data_type_controller.cc
+++ b/chrome/browser/sync/glue/password_data_type_controller.cc
@@ -43,6 +43,16 @@
     return;
   }
 
+  password_store_ = profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+  if (!password_store_.get()) {
+    LOG(ERROR) << "PasswordStore not initialized, password datatype controller"
+        << " aborting.";
+    state_ = NOT_RUNNING;
+    start_callback->Run(ABORTED);
+    delete start_callback;
+    return;
+  }
+
   if (!sync_service_->IsCryptographerReady()) {
     start_callback->Run(NEEDS_CRYPTO);
     delete start_callback;
@@ -50,10 +60,7 @@
   }
 
   start_callback_.reset(start_callback);
-
   set_state(ASSOCIATING);
-  password_store_ = profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
-  DCHECK(password_store_.get());
   password_store_->ScheduleTask(
       NewRunnableMethod(this, &PasswordDataTypeController::StartImpl));
 }
diff --git a/chrome/browser/sync/glue/password_model_associator.cc b/chrome/browser/sync/glue/password_model_associator.cc
index 3c9d01a..3ed5946 100644
--- a/chrome/browser/sync/glue/password_model_associator.cc
+++ b/chrome/browser/sync/glue/password_model_associator.cc
@@ -41,12 +41,11 @@
 bool PasswordModelAssociator::AssociateModels() {
   DCHECK(expected_loop_ == MessageLoop::current());
   {
-    AutoLock lock(abort_association_pending_lock_);
+    base::AutoLock lock(abort_association_pending_lock_);
     abort_association_pending_ = false;
   }
 
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode password_root(&trans);
   if (!password_root.InitByTagLookup(kPasswordTag)) {
     LOG(ERROR) << "Server did not create the top-level password node. We "
@@ -176,8 +175,7 @@
                << "might be running against an out-of-date server.";
     return false;
   }
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   sync_api::ReadNode password_node(&trans);
   if (!password_node.InitByIdLookup(password_sync_id)) {
@@ -194,7 +192,7 @@
 
 void PasswordModelAssociator::AbortAssociation() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  AutoLock lock(abort_association_pending_lock_);
+  base::AutoLock lock(abort_association_pending_lock_);
   abort_association_pending_ = true;
 }
 
@@ -210,7 +208,7 @@
 }
 
 bool PasswordModelAssociator::IsAbortPending() {
-  AutoLock lock(abort_association_pending_lock_);
+  base::AutoLock lock(abort_association_pending_lock_);
   return abort_association_pending_;
 }
 
@@ -241,8 +239,7 @@
 
 bool PasswordModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
                                                      int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode sync_node(&trans);
   if (!sync_node.InitByTagLookup(tag.c_str()))
     return false;
diff --git a/chrome/browser/sync/glue/password_model_associator.h b/chrome/browser/sync/glue/password_model_associator.h
index 15eb372..449bde7 100644
--- a/chrome/browser/sync/glue/password_model_associator.h
+++ b/chrome/browser/sync/glue/password_model_associator.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/sync/glue/model_associator.h"
@@ -117,10 +117,6 @@
   // user requested an abort.
   bool IsAbortPending();
 
- protected:
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
  private:
   typedef std::map<std::string, int64> PasswordToSyncIdMap;
   typedef std::map<int64, std::string> SyncIdToPasswordMap;
@@ -132,7 +128,7 @@
   // Abort association pending flag and lock.  If this is set to true
   // (via the AbortAssociation method), return from the
   // AssociateModels method as soon as possible.
-  Lock abort_association_pending_lock_;
+  base::Lock abort_association_pending_lock_;
   bool abort_association_pending_;
 
   MessageLoop* expected_loop_;
diff --git a/chrome/browser/sync/glue/preference_model_associator.cc b/chrome/browser/sync/glue/preference_model_associator.cc
index e9fcfdf..dd9cb96 100644
--- a/chrome/browser/sync/glue/preference_model_associator.cc
+++ b/chrome/browser/sync/glue/preference_model_associator.cc
@@ -32,8 +32,7 @@
   // synced_preferences set, taking care to filter out any preferences
   // that are not registered.
   PrefService* pref_service = sync_service_->profile()->GetPrefs();
-  for (size_t i = 0;
-       i < static_cast<size_t>(arraysize(kSynchronizedPreferences)); ++i) {
+  for (size_t i = 0; i < arraysize(kSynchronizedPreferences); ++i) {
     if (pref_service->FindPreference(kSynchronizedPreferences[i]))
       synced_preferences_.insert(kSynchronizedPreferences[i]);
   }
@@ -74,8 +73,15 @@
 
       // Update the local preference based on what we got from the
       // sync server.
-      if (!pref->GetValue()->Equals(new_value.get()))
+      if (new_value->IsType(Value::TYPE_NULL)) {
+        pref_service->ClearPref(pref_name.c_str());
+      } else if (!new_value->IsType(pref->GetType())) {
+        LOG(WARNING) << "Synced value for " << preference.name()
+                     << " is of type " << new_value->GetType()
+                     << " which doesn't match pref type " << pref->GetType();
+      } else if (!pref->GetValue()->Equals(new_value.get())) {
         pref_service->Set(pref_name.c_str(), *new_value);
+      }
 
       AfterUpdateOperations(pref_name);
 
@@ -116,8 +122,7 @@
     return false;
   }
 
-  sync_api::WriteTransaction trans(
-      sync_service()->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByIdLookup(root_id)) {
     LOG(ERROR) << "Server did not create the top-level preferences node. We "
@@ -149,8 +154,7 @@
                << "might be running against an out-of-date server.";
     return false;
   }
-  sync_api::ReadTransaction trans(
-      sync_service()->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   sync_api::ReadNode preferences_node(&trans);
   if (!preferences_node.InitByIdLookup(preferences_sync_id)) {
@@ -204,8 +208,7 @@
 
 bool PreferenceModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
                                                        int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode sync_node(&trans);
   if (!sync_node.InitByTagLookup(tag.c_str()))
     return false;
@@ -263,7 +266,7 @@
   DCHECK(to_value.GetType() == Value::TYPE_LIST);
   const ListValue& from_list_value = static_cast<const ListValue&>(from_value);
   const ListValue& to_list_value = static_cast<const ListValue&>(to_value);
-  ListValue* result = static_cast<ListValue*>(to_list_value.DeepCopy());
+  ListValue* result = to_list_value.DeepCopy();
 
   for (ListValue::const_iterator i = from_list_value.begin();
        i != from_list_value.end(); ++i) {
@@ -288,8 +291,7 @@
       static_cast<const DictionaryValue&>(from_value);
   const DictionaryValue& to_dict_value =
       static_cast<const DictionaryValue&>(to_value);
-  DictionaryValue* result =
-      static_cast<DictionaryValue*>(to_dict_value.DeepCopy());
+  DictionaryValue* result = to_dict_value.DeepCopy();
 
   for (DictionaryValue::key_iterator key = from_dict_value.begin_keys();
        key != from_dict_value.end_keys(); ++key) {
diff --git a/chrome/browser/sync/glue/preference_model_associator.h b/chrome/browser/sync/glue/preference_model_associator.h
index f50bb2c..5924e72 100644
--- a/chrome/browser/sync/glue/preference_model_associator.h
+++ b/chrome/browser/sync/glue/preference_model_associator.h
@@ -109,10 +109,6 @@
   // has been updated.
   void AfterUpdateOperations(const std::string& pref_name);
 
- protected:
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
  private:
   typedef std::map<std::string, int64> PreferenceNameToSyncIdMap;
   typedef std::map<int64, std::string> SyncIdToPreferenceNameMap;
diff --git a/chrome/browser/sync/glue/preference_model_associator_unittest.cc b/chrome/browser/sync/glue/preference_model_associator_unittest.cc
index b3dca08..394720a 100644
--- a/chrome/browser/sync/glue/preference_model_associator_unittest.cc
+++ b/chrome/browser/sync/glue/preference_model_associator_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -34,11 +34,6 @@
         Value::CreateIntegerValue(setting));
   }
 
-  void SetPrefToNull(const std::string& pref_name) {
-    scoped_ptr<Value> null_value(Value::CreateNullValue());
-    pref_service_->Set(pref_name.c_str(), *null_value);
-  }
-
   void SetPrefToEmpty(const std::string& pref_name) {
     scoped_ptr<Value> empty_value;
     const PrefService::Preference* pref =
@@ -89,15 +84,6 @@
   EXPECT_TRUE(merged_value->Equals(server_value.get()));
 }
 
-TEST_F(ListPreferenceMergeTest, LocalNull) {
-  SetPrefToNull(prefs::kURLsToRestoreOnStartup);
-  const PrefService::Preference* pref =
-      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
-  scoped_ptr<Value> merged_value(
-      PreferenceModelAssociator::MergePreference(*pref, server_url_list_));
-  EXPECT_TRUE(merged_value->Equals(&server_url_list_));
-}
-
 TEST_F(ListPreferenceMergeTest, LocalEmpty) {
   SetPrefToEmpty(prefs::kURLsToRestoreOnStartup);
   const PrefService::Preference* pref =
@@ -133,16 +119,6 @@
   EXPECT_TRUE(merged_value->Equals(local_list_value));
 }
 
-TEST_F(ListPreferenceMergeTest, BothNull) {
-  SetPrefToNull(prefs::kURLsToRestoreOnStartup);
-  scoped_ptr<Value> null_value(Value::CreateNullValue());
-  const PrefService::Preference* pref =
-      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
-  scoped_ptr<Value> merged_value(
-      PreferenceModelAssociator::MergePreference(*pref, *null_value));
-  EXPECT_TRUE(merged_value->Equals(null_value.get()));
-}
-
 TEST_F(ListPreferenceMergeTest, Merge) {
   ListValue* local_list_value =
       pref_service_->GetMutableList(prefs::kURLsToRestoreOnStartup);
@@ -219,15 +195,6 @@
   DictionaryValue server_patterns_;
 };
 
-TEST_F(DictionaryPreferenceMergeTest, LocalNull) {
-  SetPrefToNull(prefs::kContentSettingsPatterns);
-  const PrefService::Preference* pref =
-      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
-  scoped_ptr<Value> merged_value(
-      PreferenceModelAssociator::MergePreference(*pref, server_patterns_));
-  EXPECT_TRUE(merged_value->Equals(&server_patterns_));
-}
-
 TEST_F(DictionaryPreferenceMergeTest, LocalEmpty) {
   SetPrefToEmpty(prefs::kContentSettingsPatterns);
   const PrefService::Preference* pref =
@@ -263,16 +230,6 @@
   EXPECT_TRUE(merged_value->Equals(local_dict_value));
 }
 
-TEST_F(DictionaryPreferenceMergeTest, BothNull) {
-  scoped_ptr<Value> null_value(Value::CreateNullValue());
-  SetPrefToNull(prefs::kContentSettingsPatterns);
-  const PrefService::Preference* pref =
-      pref_service_->FindPreference(prefs::kContentSettingsPatterns);
-  scoped_ptr<Value> merged_value(
-      PreferenceModelAssociator::MergePreference(*pref, *null_value));
-  EXPECT_TRUE(merged_value->Equals(null_value.get()));
-}
-
 TEST_F(DictionaryPreferenceMergeTest, MergeNoConflicts) {
   DictionaryValue* local_dict_value =
       pref_service_->GetMutableDictionary(prefs::kContentSettingsPatterns);
diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc
index 8c8cb6d..cad5b98 100644
--- a/chrome/browser/sync/glue/session_model_associator.cc
+++ b/chrome/browser/sync/glue/session_model_associator.cc
@@ -55,8 +55,7 @@
   DCHECK(CalledOnValidThread());
   CHECK(has_nodes);
   *has_nodes = false;
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByTagLookup(kSessionsTag)) {
     LOG(ERROR) << kNoSessionsFolderError;
@@ -75,13 +74,26 @@
 
 int64 SessionModelAssociator::GetSyncIdFromSessionTag(const std::string& tag) {
   DCHECK(CalledOnValidThread());
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode node(&trans);
   if (!node.InitByClientTagLookup(syncable::SESSIONS, tag))
     return sync_api::kInvalidId;
   return node.GetId();
 }
+
+const TabContents*
+SessionModelAssociator::GetChromeNodeFromSyncId(int64 sync_id) {
+  NOTREACHED();
+  return NULL;
+}
+
+bool SessionModelAssociator::InitSyncNodeFromChromeId(
+    const size_t& id,
+    sync_api::BaseNode* sync_node) {
+  NOTREACHED();
+  return false;
+}
+
 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) {
   DCHECK(CalledOnValidThread());
   sync_pb::SessionSpecifics specifics;
@@ -134,8 +146,7 @@
     }
   }
 
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   sync_api::WriteNode header_node(&trans);
   if (!header_node.InitByIdLookup(local_session_syncid_)) {
     LOG(ERROR) << "Failed to load local session header node.";
@@ -210,8 +221,7 @@
   TabLinks t(sync_id, tab);
   tab_map_[session_id] = t;
 
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   WriteTabContentsToSyncModel(*tab, sync_id, &trans);
 }
 
@@ -363,8 +373,7 @@
   // Read any available foreign sessions and load any session data we may have.
   // If we don't have any local session data in the db, create a header node.
   {
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
 
     sync_api::ReadNode root(&trans);
     if (!root.InitByTagLookup(kSessionsTag)) {
@@ -697,6 +706,8 @@
       sync_service_(sync_service) {
 }
 
+SessionModelAssociator::TabNodePool::~TabNodePool() {}
+
 void SessionModelAssociator::TabNodePool::AddTabNode(int64 sync_id) {
   tab_syncid_pool_.resize(tab_syncid_pool_.size() + 1);
   tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id;
@@ -706,8 +717,7 @@
   DCHECK_GT(machine_tag_.length(), 0U);
   if (tab_pool_fp_ == -1) {
     // Tab pool has no free nodes, allocate new one.
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
     sync_api::ReadNode root(&trans);
     if (!root.InitByTagLookup(kSessionsTag)) {
       LOG(ERROR) << kNoSessionsFolderError;
@@ -838,8 +848,7 @@
   sync_pb::SessionHeader* header_s = specifics.mutable_header();
   PopulateSessionSpecificsHeader(*windows, header_s);
 
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByTagLookup(kSessionsTag)) {
     LOG(ERROR) << kNoSessionsFolderError;
@@ -913,8 +922,7 @@
       return false;
     }
 
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
     if (!WriteSessionTabToSyncModel(*tab, id, &trans)) {
       return false;
     }
diff --git a/chrome/browser/sync/glue/session_model_associator.h b/chrome/browser/sync/glue/session_model_associator.h
index cff376f..7864c12 100644
--- a/chrome/browser/sync/glue/session_model_associator.h
+++ b/chrome/browser/sync/glue/session_model_associator.h
@@ -27,7 +27,6 @@
 #include "chrome/browser/sync/protocol/session_specifics.pb.h"
 #include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_registrar.h"
 
 class Profile;
 class ProfileSyncService;
@@ -77,17 +76,11 @@
   virtual int64 GetSyncIdFromSessionTag(const std::string& tag);
 
   // Not used.
-  virtual const TabContents* GetChromeNodeFromSyncId(int64 sync_id) {
-    NOTREACHED();
-    return NULL;
-  }
+  virtual const TabContents* GetChromeNodeFromSyncId(int64 sync_id);
 
   // Not used.
-  bool InitSyncNodeFromChromeId(const size_t& id,
-                                sync_api::BaseNode* sync_node) {
-    NOTREACHED();
-    return false;
-  }
+  virtual bool InitSyncNodeFromChromeId(const size_t& id,
+                                        sync_api::BaseNode* sync_node);
 
   // Resync local window information. Updates the local sessions header node
   // with the status of open windows and the order of tabs they contain. Should
@@ -224,6 +217,7 @@
   class TabNodePool {
    public:
     explicit TabNodePool(ProfileSyncService* sync_service);
+    ~TabNodePool();
 
     // Add a previously allocated tab sync node to our pool. Increases the size
     // of tab_syncid_pool_ by one and marks the new tab node as free.
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index 4dafe24..681f8a9 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -6,9 +6,11 @@
 
 #include <algorithm>
 
+#include "base/compiler_specific.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/task.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/net/gaia/token_service.h"
@@ -23,6 +25,7 @@
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/glue/http_bridge.h"
 #include "chrome/browser/sync/glue/password_model_worker.h"
+#include "chrome/browser/sync/js_arg_list.h"
 #include "chrome/browser/sync/sessions/session_state.h"
 // TODO(tim): Remove this! We should have a syncapi pass-thru instead.
 #include "chrome/browser/sync/syncable/directory_manager.h"  // Cryptographer.
@@ -49,21 +52,16 @@
 using sessions::SyncSessionSnapshot;
 using sync_api::SyncCredentials;
 
-SyncBackendHost::SyncBackendHost(
-    SyncFrontend* frontend,
-    Profile* profile,
-    const FilePath& profile_path,
-    const DataTypeController::TypeMap& data_type_controllers)
-    : core_thread_("Chrome_SyncCoreThread"),
+SyncBackendHost::SyncBackendHost(Profile* profile)
+    : core_(new Core(ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+      core_thread_("Chrome_SyncCoreThread"),
       frontend_loop_(MessageLoop::current()),
       profile_(profile),
-      frontend_(frontend),
-      sync_data_folder_path_(profile_path.Append(kSyncDataFolderName)),
-      data_type_controllers_(data_type_controllers),
+      frontend_(NULL),
+      sync_data_folder_path_(
+          profile_->GetPath().Append(kSyncDataFolderName)),
       last_auth_error_(AuthError::None()),
       syncapi_initialized_(false) {
-
-  core_ = new Core(this);
 }
 
 SyncBackendHost::SyncBackendHost()
@@ -81,6 +79,7 @@
 }
 
 void SyncBackendHost::Initialize(
+    SyncFrontend* frontend,
     const GURL& sync_service_url,
     const syncable::ModelTypeSet& types,
     URLRequestContextGetter* baseline_context_getter,
@@ -90,6 +89,9 @@
   if (!core_thread_.Start())
     return;
 
+  frontend_ = frontend;
+  DCHECK(frontend);
+
   // Create a worker for the UI thread and route bookmark changes to it.
   // TODO(tim): Pull this into a method to reuse.  For now we don't even
   // need to lock because we init before the syncapi exists and we tear down
@@ -97,19 +99,16 @@
   // when a new type is synced as the worker may already exist and you just
   // need to update routing_info_.
   registrar_.workers[GROUP_DB] = new DatabaseModelWorker();
-  registrar_.workers[GROUP_HISTORY] =
-      new HistoryModelWorker(
-          profile_->GetHistoryService(Profile::IMPLICIT_ACCESS));
   registrar_.workers[GROUP_UI] = new UIModelWorker(frontend_loop_);
   registrar_.workers[GROUP_PASSIVE] = new ModelSafeWorker();
 
-  PasswordStore* password_store =
-      profile_->GetPasswordStore(Profile::IMPLICIT_ACCESS);
-  if (password_store) {
-    registrar_.workers[GROUP_PASSWORD] =
-        new PasswordModelWorker(password_store);
-  } else {
-    LOG(WARNING) << "Password store not initialized, cannot sync passwords";
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableSyncTypedUrls) || types.count(syncable::TYPED_URLS)) {
+    // TODO(tim): Bug 53916.  HistoryModelWorker crashes, so avoid adding it
+    // unless specifically requested until bug is fixed.
+    registrar_.workers[GROUP_HISTORY] =
+        new HistoryModelWorker(
+            profile_->GetHistoryService(Profile::IMPLICIT_ACCESS));
   }
 
   // Any datatypes that we want the syncer to pull down must
@@ -120,11 +119,21 @@
     registrar_.routing_info[(*it)] = GROUP_PASSIVE;
   }
 
+  PasswordStore* password_store =
+      profile_->GetPasswordStore(Profile::IMPLICIT_ACCESS);
+  if (password_store) {
+    registrar_.workers[GROUP_PASSWORD] =
+        new PasswordModelWorker(password_store);
+  } else {
+    LOG(WARNING) << "Password store not initialized, cannot sync passwords";
+    registrar_.routing_info.erase(syncable::PASSWORDS);
+  }
+
   // TODO(tim): Remove this special case once NIGORI is populated by
   // default.  We piggy back off of the passwords flag for now to not
   // require both encryption and passwords flags.
-  bool enable_encryption = CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableSyncPasswords) || types.count(syncable::PASSWORDS);
+  bool enable_encryption = !CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableSyncPasswords) || types.count(syncable::PASSWORDS);
   if (enable_encryption)
     registrar_.routing_info[syncable::NIGORI] = GROUP_PASSIVE;
 
@@ -153,7 +162,7 @@
 }
 
 bool SyncBackendHost::IsNigoriEnabled() const {
-  AutoLock lock(registrar_lock_);
+  base::AutoLock lock(registrar_lock_);
   // Note that NIGORI is only ever added/removed from routing_info once,
   // during initialization / first configuration, so there is no real 'race'
   // possible here or possibility of stale return value.
@@ -169,7 +178,16 @@
 
 bool SyncBackendHost::IsCryptographerReady() const {
   return syncapi_initialized_ &&
-      GetUserShareHandle()->dir_manager->cryptographer()->is_ready();
+      GetUserShare()->dir_manager->cryptographer()->is_ready();
+}
+
+JsBackend* SyncBackendHost::GetJsBackend() {
+  if (syncapi_initialized_) {
+    return core_.get();
+  } else {
+    NOTREACHED();
+    return NULL;
+  }
 }
 
 sync_api::HttpPostProviderFactory* SyncBackendHost::MakeHttpBridgeFactory(
@@ -234,10 +252,14 @@
   // thread (ui loop) can exit before DoShutdown finishes, at which point
   // virtually anything the sync backend does (or the post-back to
   // frontend_loop_ by our Core) will epically fail because the CRT won't be
-  // initialized. For now this only ever happens at sync-enabled-Chrome exit,
-  // meaning bug 1482548 applies to prolonged "waiting" that may occur in
-  // DoShutdown.
-  core_thread_.Stop();
+  // initialized.
+  // Since we are blocking the UI thread here, we need to turn ourselves in
+  // with the ThreadRestriction police.  For sentencing and how we plan to fix
+  // this, see bug 19757.
+  {
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    core_thread_.Stop();
+  }
 
   registrar_.routing_info.clear();
   registrar_.workers[GROUP_DB] = NULL;
@@ -277,7 +299,7 @@
 
 void SyncBackendHost::ConfigureAutofillMigration() {
   if (GetAutofillMigrationState() == syncable::NOT_DETERMINED) {
-    sync_api::ReadTransaction trans(GetUserShareHandle());
+    sync_api::ReadTransaction trans(GetUserShare());
     sync_api::ReadNode autofil_root_node(&trans);
 
     // Check for the presence of autofill node.
@@ -311,8 +333,10 @@
   }
 }
 
-void SyncBackendHost::ConfigureDataTypes(const syncable::ModelTypeSet& types,
-                                         CancelableTask* ready_task) {
+void SyncBackendHost::ConfigureDataTypes(
+    const DataTypeController::TypeMap& data_type_controllers,
+    const syncable::ModelTypeSet& types,
+    CancelableTask* ready_task) {
   // Only one configure is allowed at a time.
   DCHECK(!configure_ready_task_.get());
   DCHECK(syncapi_initialized_);
@@ -324,10 +348,10 @@
   bool deleted_type = false;
 
   {
-    AutoLock lock(registrar_lock_);
+    base::AutoLock lock(registrar_lock_);
     for (DataTypeController::TypeMap::const_iterator it =
-             data_type_controllers_.begin();
-         it != data_type_controllers_.end(); ++it) {
+             data_type_controllers.begin();
+         it != data_type_controllers.end(); ++it) {
       syncable::ModelType type = (*it).first;
 
       // If a type is not specified, remove it from the routing_info.
@@ -382,7 +406,7 @@
 void SyncBackendHost::ActivateDataType(
     DataTypeController* data_type_controller,
     ChangeProcessor* change_processor) {
-  AutoLock lock(registrar_lock_);
+  base::AutoLock lock(registrar_lock_);
 
   // Ensure that the given data type is in the PASSIVE group.
   browser_sync::ModelSafeRoutingInfo::iterator i =
@@ -402,7 +426,7 @@
 void SyncBackendHost::DeactivateDataType(
     DataTypeController* data_type_controller,
     ChangeProcessor* change_processor) {
-  AutoLock lock(registrar_lock_);
+  base::AutoLock lock(registrar_lock_);
   registrar_.routing_info.erase(data_type_controller->type());
 
   std::map<syncable::ModelType, ChangeProcessor*>::size_type erased =
@@ -448,21 +472,23 @@
 }
 
 void SyncBackendHost::Core::NotifyPassphraseRequired(bool for_decryption) {
-  NotificationService::current()->Notify(
-      NotificationType::SYNC_PASSPHRASE_REQUIRED,
-      Source<SyncBackendHost>(host_),
-      Details<bool>(&for_decryption));
+  if (!host_ || !host_->frontend_)
+    return;
+
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+
+  host_->frontend_->OnPassphraseRequired(for_decryption);
 }
 
 void SyncBackendHost::Core::NotifyPassphraseAccepted(
     const std::string& bootstrap_token) {
-  if (!host_)
+  if (!host_ || !host_->frontend_)
     return;
+
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+
   host_->PersistEncryptionBootstrapToken(bootstrap_token);
-  NotificationService::current()->Notify(
-      NotificationType::SYNC_PASSPHRASE_ACCEPTED,
-      Source<SyncBackendHost>(host_),
-      NotificationService::NoDetails());
+  host_->frontend_->OnPassphraseAccepted();
 }
 
 void SyncBackendHost::Core::NotifyUpdatedToken(const std::string& token) {
@@ -476,7 +502,26 @@
       Details<const TokenAvailableDetails>(&details));
 }
 
-SyncBackendHost::UserShareHandle SyncBackendHost::GetUserShareHandle() const {
+SyncBackendHost::Core::DoInitializeOptions::DoInitializeOptions(
+    const GURL& service_url,
+    sync_api::HttpPostProviderFactory* http_bridge_factory,
+    const sync_api::SyncCredentials& credentials,
+    bool delete_sync_data_folder,
+    const notifier::NotifierOptions& notifier_options,
+    std::string restored_key_for_bootstrapping,
+    bool setup_for_test_mode)
+    : service_url(service_url),
+      http_bridge_factory(http_bridge_factory),
+      credentials(credentials),
+      delete_sync_data_folder(delete_sync_data_folder),
+      notifier_options(notifier_options),
+      restored_key_for_bootstrapping(restored_key_for_bootstrapping),
+      setup_for_test_mode(setup_for_test_mode) {
+}
+
+SyncBackendHost::Core::DoInitializeOptions::~DoInitializeOptions() {}
+
+sync_api::UserShare* SyncBackendHost::GetUserShare() const {
   DCHECK(syncapi_initialized_);
   return core_->syncapi()->GetUserShare();
 }
@@ -505,7 +550,7 @@
 }
 
 void SyncBackendHost::GetWorkers(std::vector<ModelSafeWorker*>* out) {
-  AutoLock lock(registrar_lock_);
+  base::AutoLock lock(registrar_lock_);
   out->clear();
   for (WorkerMap::const_iterator it = registrar_.workers.begin();
        it != registrar_.workers.end(); ++it) {
@@ -514,7 +559,7 @@
 }
 
 void SyncBackendHost::GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
-  AutoLock lock(registrar_lock_);
+  base::AutoLock lock(registrar_lock_);
   ModelSafeRoutingInfo copy(registrar_.routing_info);
   out->swap(copy);
 }
@@ -526,7 +571,9 @@
 
 SyncBackendHost::Core::Core(SyncBackendHost* backend)
     : host_(backend),
-      syncapi_(new sync_api::SyncManager()) {
+      syncapi_(new sync_api::SyncManager()),
+      sync_manager_observer_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      parent_router_(NULL) {
 }
 
 // Helper to construct a user agent string (ASCII) suitable for use by
@@ -573,7 +620,7 @@
   bool success = file_util::CreateDirectory(host_->sync_data_folder_path());
   DCHECK(success);
 
-  syncapi_->SetObserver(this);
+  syncapi_->AddObserver(this);
   const FilePath& path_str = host_->sync_data_folder_path();
   success = syncapi_->Init(
       path_str,
@@ -621,7 +668,8 @@
 
   save_changes_timer_.Stop();
   syncapi_->Shutdown();  // Stops the SyncerThread.
-  syncapi_->RemoveObserver();
+  syncapi_->RemoveObserver(this);
+  DisconnectChildJsEventRouter();
   host_->ui_worker()->OnSyncerShutdownComplete();
 
   if (sync_disabled)
@@ -760,7 +808,7 @@
 
 bool SyncBackendHost::Core::IsCurrentThreadSafeForModel(
     syncable::ModelType model_type) {
-  AutoLock lock(host_->registrar_lock_);
+  base::AutoLock lock(host_->registrar_lock_);
 
   browser_sync::ModelSafeRoutingInfo::const_iterator routing_it =
       host_->registrar_.routing_info.find(model_type);
@@ -774,7 +822,6 @@
   return worker->CurrentThreadIsWorkThread();
 }
 
-
 void SyncBackendHost::Core::OnAuthError(const AuthError& auth_error) {
   // Post to our core loop so we can modify state. Could be on another thread.
   host_->frontend_loop_->PostTask(FROM_HERE,
@@ -826,6 +873,14 @@
       &Core::HandleClearServerDataFailedOnFrontendLoop));
 }
 
+void SyncBackendHost::Core::RouteJsEvent(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* target) {
+  host_->frontend_loop_->PostTask(
+      FROM_HERE, NewRunnableMethod(
+          this, &Core::RouteJsEventOnFrontendLoop, name, args, target));
+}
+
 void SyncBackendHost::Core::HandleStopSyncingPermanentlyOnFrontendLoop() {
   if (!host_ || !host_->frontend_)
     return;
@@ -855,6 +910,17 @@
   host_->frontend_->OnAuthError();
 }
 
+void SyncBackendHost::Core::RouteJsEventOnFrontendLoop(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* target) {
+  if (!host_ || !parent_router_)
+    return;
+
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+
+  parent_router_->RouteJsEvent(name, args, target);
+}
+
 void SyncBackendHost::Core::StartSavingChanges() {
   save_changes_timer_.Start(
       base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
@@ -888,4 +954,68 @@
   }
 }
 
+void SyncBackendHost::Core::SetParentJsEventRouter(JsEventRouter* router) {
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+  DCHECK(router);
+  parent_router_ = router;
+  MessageLoop* core_message_loop = host_->core_thread_.message_loop();
+  CHECK(core_message_loop);
+  core_message_loop->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this,
+                        &SyncBackendHost::Core::ConnectChildJsEventRouter));
+}
+
+void SyncBackendHost::Core::RemoveParentJsEventRouter() {
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+  parent_router_ = NULL;
+  MessageLoop* core_message_loop = host_->core_thread_.message_loop();
+  CHECK(core_message_loop);
+  core_message_loop->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this,
+                        &SyncBackendHost::Core::DisconnectChildJsEventRouter));
+}
+
+const JsEventRouter* SyncBackendHost::Core::GetParentJsEventRouter() const {
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+  return parent_router_;
+}
+
+void SyncBackendHost::Core::ProcessMessage(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* sender) {
+  DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
+  MessageLoop* core_message_loop = host_->core_thread_.message_loop();
+  CHECK(core_message_loop);
+  core_message_loop->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this,
+                        &SyncBackendHost::Core::DoProcessMessage,
+                        name, args, sender));
+}
+
+void SyncBackendHost::Core::ConnectChildJsEventRouter() {
+  DCHECK_EQ(MessageLoop::current(), host_->core_thread_.message_loop());
+  // We need this check since AddObserver() can be called at most once
+  // for a given observer.
+  if (!syncapi_->GetJsBackend()->GetParentJsEventRouter()) {
+    syncapi_->GetJsBackend()->SetParentJsEventRouter(this);
+    syncapi_->AddObserver(&sync_manager_observer_);
+  }
+}
+
+void SyncBackendHost::Core::DisconnectChildJsEventRouter() {
+  DCHECK_EQ(MessageLoop::current(), host_->core_thread_.message_loop());
+  syncapi_->GetJsBackend()->RemoveParentJsEventRouter();
+  syncapi_->RemoveObserver(&sync_manager_observer_);
+}
+
+void SyncBackendHost::Core::DoProcessMessage(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* sender) {
+  DCHECK_EQ(MessageLoop::current(), host_->core_thread_.message_loop());
+  syncapi_->GetJsBackend()->ProcessMessage(name, args, sender);
+}
+
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 3543a4f..a8056fe 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -11,16 +11,19 @@
 #include <vector>
 
 #include "base/file_path.h"
-#include "base/lock.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
 #include "base/timer.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/engine/model_safe_worker.h"
+#include "chrome/browser/sync/js_backend.h"
+#include "chrome/browser/sync/js_sync_manager_observer.h"
 #include "chrome/browser/sync/glue/data_type_controller.h"
 #include "chrome/browser/sync/glue/ui_model_worker.h"
+#include "chrome/browser/sync/js_event_router.h"
 #include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "chrome/common/net/url_request_context_getter.h"
@@ -42,6 +45,7 @@
 
 class ChangeProcessor;
 class DataTypeController;
+class JsArgList;
 
 // SyncFrontend is the interface used by SyncBackendHost to communicate with
 // the entity that created it and, presumably, is interested in sync-related
@@ -71,6 +75,19 @@
   virtual void OnClearServerDataSucceeded() = 0;
   virtual void OnClearServerDataFailed() = 0;
 
+  // The syncer requires a passphrase to decrypt sensitive
+  // updates. This is called when the first sensitive data type is
+  // setup by the user as well as anytime any the passphrase is
+  // changed in another synced client.  if
+  // |passphrase_required_for_decryption| is false, the passphrase is
+  // required only for encryption.
+  virtual void OnPassphraseRequired(bool for_decryption) = 0;
+
+  // Called when the passphrase provided by the user is
+  // accepted. After this is called, updates to sensitive nodes are
+  // encrypted using the accepted passphrase.
+  virtual void OnPassphraseAccepted() = 0;
+
  protected:
   // Don't delete through SyncFrontend interface.
   virtual ~SyncFrontend() {
@@ -85,7 +102,6 @@
 // that the SyncFrontend is only accessed on the UI loop.
 class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
  public:
-  typedef sync_api::UserShare* UserShareHandle;
   typedef sync_api::SyncManager::Status::Summary StatusSummary;
   typedef sync_api::SyncManager::Status Status;
   typedef std::map<ModelSafeGroup,
@@ -94,20 +110,18 @@
   // Create a SyncBackendHost with a reference to the |frontend| that it serves
   // and communicates to via the SyncFrontend interface (on the same thread
   // it used to call the constructor).
-  SyncBackendHost(SyncFrontend* frontend,
-                  Profile* profile,
-                  const FilePath& profile_path,
-                  const DataTypeController::TypeMap& data_type_controllers);
+  explicit SyncBackendHost(Profile* profile);
   // For testing.
   // TODO(skrul): Extract an interface so this is not needed.
   SyncBackendHost();
-  ~SyncBackendHost();
+  virtual ~SyncBackendHost();
 
   // Called on |frontend_loop_| to kick off asynchronous initialization.
   // As a fallback when no cached auth information is available, try to
   // bootstrap authentication using |lsid|, if it isn't empty.
   // Optionally delete the Sync Data folder (if it's corrupt).
-  void Initialize(const GURL& service_url,
+  void Initialize(SyncFrontend* frontend,
+                  const GURL& service_url,
                   const syncable::ModelTypeSet& types,
                   URLRequestContextGetter* baseline_context_getter,
                   const sync_api::SyncCredentials& credentials,
@@ -139,8 +153,10 @@
   // The ready_task will be run when all of the requested data types
   // are up-to-date and ready for activation.  The task will cancelled
   // upon shutdown.  The method takes ownership of the task pointer.
-  virtual void ConfigureDataTypes(const syncable::ModelTypeSet& types,
-                                  CancelableTask* ready_task);
+  virtual void ConfigureDataTypes(
+      const DataTypeController::TypeMap& data_type_controllers,
+      const syncable::ModelTypeSet& types,
+      CancelableTask* ready_task);
 
   syncable::AutofillMigrationState
       GetAutofillMigrationState();
@@ -181,7 +197,7 @@
 
   // Called on |frontend_loop_| to obtain a handle to the UserShare needed
   // for creating transactions.
-  UserShareHandle GetUserShareHandle() const;
+  sync_api::UserShare* GetUserShare() const;
 
   // Called from any thread to obtain current status information in detailed or
   // summarized form.
@@ -219,10 +235,21 @@
   // using a token previously received.
   bool IsCryptographerReady() const;
 
+  // Returns a pointer to the JsBackend (which is owned by the
+  // service).  Must be called only after the sync backend has been
+  // initialized, and never returns NULL if you do so.  Overrideable
+  // for testing purposes.
+  virtual JsBackend* GetJsBackend();
+
+  // TODO(akalin): Write unit tests for the JsBackend, finding a way
+  // to make this class testable in general.
+
  protected:
   // The real guts of SyncBackendHost, to keep the public client API clean.
   class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
-               public sync_api::SyncManager::Observer {
+               public sync_api::SyncManager::Observer,
+               public JsBackend,
+               public JsEventRouter {
    public:
     explicit Core(SyncBackendHost* backend);
 
@@ -248,6 +275,18 @@
     virtual void OnClearServerDataFailed();
     virtual void OnClearServerDataSucceeded();
 
+    // JsBackend implementation.
+    virtual void SetParentJsEventRouter(JsEventRouter* router);
+    virtual void RemoveParentJsEventRouter();
+    virtual const JsEventRouter* GetParentJsEventRouter() const;
+    virtual void ProcessMessage(const std::string& name, const JsArgList& args,
+                                const JsEventHandler* sender);
+
+    // JsEventRouter implementation.
+    virtual void RouteJsEvent(const std::string& event_name,
+                              const JsArgList& args,
+                              const JsEventHandler* dst);
+
     struct DoInitializeOptions {
       DoInitializeOptions(
           const GURL& service_url,
@@ -256,14 +295,8 @@
           bool delete_sync_data_folder,
           const notifier::NotifierOptions& notifier_options,
           std::string restored_key_for_bootstrapping,
-          bool setup_for_test_mode)
-          : service_url(service_url),
-            http_bridge_factory(http_bridge_factory),
-            credentials(credentials),
-            delete_sync_data_folder(delete_sync_data_folder),
-            notifier_options(notifier_options),
-            restored_key_for_bootstrapping(restored_key_for_bootstrapping),
-            setup_for_test_mode(setup_for_test_mode) {}
+          bool setup_for_test_mode);
+      ~DoInitializeOptions();
 
       GURL service_url;
       sync_api::HttpPostProviderFactory* http_bridge_factory;
@@ -326,6 +359,14 @@
     // sync databases), as well as shutdown when you're no longer syncing.
     void DeleteSyncDataFolder();
 
+    void ConnectChildJsEventRouter();
+
+    void DisconnectChildJsEventRouter();
+
+    void DoProcessMessage(
+        const std::string& name, const JsArgList& args,
+        const JsEventHandler* sender);
+
 #if defined(UNIT_TEST)
     // Special form of initialization that does not try and authenticate the
     // last known user (since it will fail in test mode) and does some extra
@@ -348,7 +389,7 @@
     friend class base::RefCountedThreadSafe<SyncBackendHost::Core>;
     friend class SyncBackendHostForProfileSyncTest;
 
-    ~Core();
+    virtual ~Core();
 
     // Return change processor for a particular model (return NULL on failure).
     ChangeProcessor* GetProcessor(syncable::ModelType modeltype);
@@ -407,12 +448,13 @@
     // frontend thread components.
     void HandleInitalizationCompletedOnFrontendLoop();
 
+    void RouteJsEventOnFrontendLoop(
+        const std::string& name, const JsArgList& args,
+        const JsEventHandler* dst);
+
     // Return true if a model lives on the current thread.
     bool IsCurrentThreadSafeForModel(syncable::ModelType model_type);
 
-    // True if credentials are ready for sync use.
-    bool CredentialsAvailable();
-
     // Our parent SyncBackendHost
     SyncBackendHost* host_;
 
@@ -422,6 +464,10 @@
     // The top-level syncapi entry point.
     scoped_ptr<sync_api::SyncManager> syncapi_;
 
+    JsSyncManagerObserver sync_manager_observer_;
+
+    JsEventRouter* parent_router_;
+
     DISALLOW_COPY_AND_ASSIGN(Core);
   };
 
@@ -495,7 +541,7 @@
   // pointer value", and then invoke methods), because lifetimes are managed on
   // the UI thread.  Of course, this comment only applies to ModelSafeWorker
   // impls that are themselves thread-safe, such as UIModelWorker.
-  mutable Lock registrar_lock_;
+  mutable base::Lock registrar_lock_;
 
   // The frontend which we serve (and are owned by).
   SyncFrontend* frontend_;
@@ -506,9 +552,6 @@
   // Path of the folder that stores the sync data files.
   FilePath sync_data_folder_path_;
 
-  // List of registered data type controllers.
-  DataTypeController::TypeMap data_type_controllers_;
-
   // A task that should be called once data type configuration is
   // complete.
   scoped_ptr<CancelableTask> configure_ready_task_;
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.cc b/chrome/browser/sync/glue/sync_backend_host_mock.cc
index fe488ad..2d618f7 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_mock.cc
@@ -6,6 +6,11 @@
 
 namespace browser_sync {
 
+ACTION(InvokeTask) {
+  arg2->Run();
+  delete arg2;
+}
+
 SyncBackendHostMock::SyncBackendHostMock() {
   // By default, the RequestPause and RequestResume methods will
   // send the confirmation notification and return true.
@@ -17,7 +22,7 @@
                                    testing::Return(true)));
 
   // By default, invoke the ready callback.
-  ON_CALL(*this, ConfigureDataTypes(testing::_, testing::_)).
+  ON_CALL(*this, ConfigureDataTypes(testing::_, testing::_, testing::_)).
       WillByDefault(InvokeTask());
 }
 
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.h b/chrome/browser/sync/glue/sync_backend_host_mock.h
index e133a57..16f2594 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.h
+++ b/chrome/browser/sync/glue/sync_backend_host_mock.h
@@ -16,18 +16,14 @@
 
 namespace browser_sync {
 
-ACTION(InvokeTask) {
-  arg1->Run();
-  delete arg1;
-}
-
 class SyncBackendHostMock : public SyncBackendHost {
  public:
   SyncBackendHostMock();
   virtual ~SyncBackendHostMock();
 
-  MOCK_METHOD2(ConfigureDataTypes,
-               void(const std::set<syncable::ModelType>&, CancelableTask*));
+  MOCK_METHOD3(ConfigureDataTypes,
+               void(const DataTypeController::TypeMap&,
+                    const std::set<syncable::ModelType>&, CancelableTask*));
   MOCK_METHOD0(RequestPause, bool());
   MOCK_METHOD0(RequestResume, bool());
   MOCK_METHOD0(StartSyncingWithServer, void());
diff --git a/chrome/browser/sync/glue/synchronized_preferences.h b/chrome/browser/sync/glue/synchronized_preferences.h
index 545df8e..25135fa 100644
--- a/chrome/browser/sync/glue/synchronized_preferences.h
+++ b/chrome/browser/sync/glue/synchronized_preferences.h
@@ -56,7 +56,6 @@
   prefs::kDeleteCache,
   prefs::kDeleteCookies,
   prefs::kDeletePasswords,
-  prefs::kDeleteLSOData,
   prefs::kDeleteFormData,
   prefs::kDeleteTimePeriod,
 
diff --git a/chrome/browser/sync/glue/theme_model_associator.cc b/chrome/browser/sync/glue/theme_model_associator.cc
index 2dd02c2..6b51af2 100644
--- a/chrome/browser/sync/glue/theme_model_associator.cc
+++ b/chrome/browser/sync/glue/theme_model_associator.cc
@@ -36,8 +36,7 @@
 ThemeModelAssociator::~ThemeModelAssociator() {}
 
 bool ThemeModelAssociator::AssociateModels() {
-  sync_api::WriteTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByTagLookup(kThemesTag)) {
     LOG(ERROR) << kNoThemesFolderError;
@@ -83,8 +82,7 @@
 bool ThemeModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
   DCHECK(has_nodes);
   *has_nodes = false;
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode root(&trans);
   if (!root.InitByTagLookup(kThemesTag)) {
     LOG(ERROR) << kNoThemesFolderError;
diff --git a/chrome/browser/sync/glue/theme_util.cc b/chrome/browser/sync/glue/theme_util.cc
index c2d70ca..2e91f02 100644
--- a/chrome/browser/sync/glue/theme_util.cc
+++ b/chrome/browser/sync/glue/theme_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,17 +9,15 @@
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
-#include "chrome/browser/extensions/extension_updater.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_updater.h"
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
 #endif
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/protocol/theme_specifics.pb.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/pref_names.h"
 #include "googleurl/src/gurl.h"
 
 namespace browser_sync {
diff --git a/chrome/browser/sync/glue/typed_url_model_associator.cc b/chrome/browser/sync/glue/typed_url_model_associator.cc
index 9c88fc0..02144fc 100644
--- a/chrome/browser/sync/glue/typed_url_model_associator.cc
+++ b/chrome/browser/sync/glue/typed_url_model_associator.cc
@@ -58,8 +58,7 @@
   TypedUrlUpdateVector updated_urls;
 
   {
-    sync_api::WriteTransaction trans(
-        sync_service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
     sync_api::ReadNode typed_url_root(&trans);
     if (!typed_url_root.InitByTagLookup(kTypedUrlTag)) {
       LOG(ERROR) << "Server did not create the top-level typed_url node. We "
@@ -216,8 +215,7 @@
                << "might be running against an out-of-date server.";
     return false;
   }
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
 
   sync_api::ReadNode typed_url_node(&trans);
   if (!typed_url_node.InitByIdLookup(typed_url_sync_id)) {
@@ -274,8 +272,7 @@
 
 bool TypedUrlModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
                                                      int64* sync_id) {
-  sync_api::ReadTransaction trans(
-      sync_service_->backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode sync_node(&trans);
   if (!sync_node.InitByTagLookup(tag.c_str()))
     return false;
diff --git a/chrome/browser/sync/glue/typed_url_model_associator.h b/chrome/browser/sync/glue/typed_url_model_associator.h
index 6388de4..0ab3533 100644
--- a/chrome/browser/sync/glue/typed_url_model_associator.h
+++ b/chrome/browser/sync/glue/typed_url_model_associator.h
@@ -124,10 +124,6 @@
                          std::vector<base::Time>* new_visits,
                          history::VisitVector* removed_visits);
 
- protected:
-  // Returns sync service instance.
-  ProfileSyncService* sync_service() { return sync_service_; }
-
  private:
   typedef std::map<std::string, int64> TypedUrlToSyncIdMap;
   typedef std::map<int64, std::string> SyncIdToTypedUrlMap;
diff --git a/chrome/browser/sync/js_arg_list.cc b/chrome/browser/sync/js_arg_list.cc
new file mode 100644
index 0000000..23165a3
--- /dev/null
+++ b/chrome/browser/sync/js_arg_list.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/js_arg_list.h"
+
+#include "base/json/json_writer.h"
+#include "base/scoped_ptr.h"
+
+namespace browser_sync {
+
+JsArgList::JsArgList() : args_(new SharedListValue()) {}
+
+JsArgList::JsArgList(const ListValue& args)
+    : args_(new SharedListValue(args)) {}
+
+JsArgList::JsArgList(const std::vector<const Value*>& args)
+    : args_(new SharedListValue(args)) {}
+
+JsArgList::~JsArgList() {}
+
+const ListValue& JsArgList::Get() const {
+  return args_->Get();
+}
+
+std::string JsArgList::ToString() const {
+  std::string str;
+  base::JSONWriter::Write(&Get(), false, &str);
+  return str;
+}
+
+JsArgList::SharedListValue::SharedListValue() {}
+
+JsArgList::SharedListValue::SharedListValue(const ListValue& list_value) {
+  // Go through contortions to copy the list since ListValues are not
+  // copyable.
+  scoped_ptr<ListValue> list_value_copy(list_value.DeepCopy());
+  list_value_.Swap(list_value_copy.get());
+}
+
+JsArgList::SharedListValue::SharedListValue(
+    const std::vector<const Value*>& value_list) {
+  for (std::vector<const Value*>::const_iterator it = value_list.begin();
+       it != value_list.end(); ++it) {
+    list_value_.Append((*it)->DeepCopy());
+  }
+}
+
+const ListValue& JsArgList::SharedListValue::Get() const {
+  return list_value_;
+}
+
+JsArgList::SharedListValue::~SharedListValue() {}
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/js_arg_list.h b/chrome/browser/sync/js_arg_list.h
new file mode 100644
index 0000000..66d1b21
--- /dev/null
+++ b/chrome/browser/sync/js_arg_list.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_SYNC_JS_ARG_LIST_H_
+#define CHROME_BROWSER_SYNC_JS_ARG_LIST_H_
+#pragma once
+
+// See README.js for design comments.
+
+#include <string>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "base/values.h"
+
+namespace browser_sync {
+
+// A thread-safe ref-counted wrapper around an immutable ListValue.
+// Used for passing around argument lists to different threads.
+class JsArgList {
+ public:
+  JsArgList();
+  explicit JsArgList(const ListValue& args);
+  explicit JsArgList(const std::vector<const Value*>& args);
+  ~JsArgList();
+
+  const ListValue& Get() const;
+
+  std::string ToString() const;
+
+ private:
+  class SharedListValue : public base::RefCountedThreadSafe<SharedListValue> {
+   public:
+    SharedListValue();
+    explicit SharedListValue(const ListValue& list_value);
+    explicit SharedListValue(const std::vector<const Value*>& value_list);
+
+    const ListValue& Get() const;
+
+   private:
+    virtual ~SharedListValue();
+    friend class base::RefCountedThreadSafe<SharedListValue>;
+
+    ListValue list_value_;
+  };
+
+  scoped_refptr<const SharedListValue> args_;
+
+  // Copy constructor and assignment operator welcome.
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_ARG_LIST_H_
diff --git a/chrome/browser/sync/js_arg_list_unittest.cc b/chrome/browser/sync/js_arg_list_unittest.cc
new file mode 100644
index 0000000..961a46b
--- /dev/null
+++ b/chrome/browser/sync/js_arg_list_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/js_arg_list.h"
+
+#include "base/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+class JsArgListTest : public testing::Test {};
+
+TEST_F(JsArgListTest, EmptyList) {
+  JsArgList arg_list;
+  EXPECT_TRUE(arg_list.Get().empty());
+}
+
+TEST_F(JsArgListTest, FromList) {
+  scoped_ptr<ListValue> list(new ListValue());
+  list->Append(Value::CreateBooleanValue(false));
+  list->Append(Value::CreateIntegerValue(5));
+  DictionaryValue* dict = new DictionaryValue();
+  list->Append(dict);
+  dict->SetString("foo", "bar");
+  dict->Set("baz", new ListValue());
+
+  JsArgList arg_list(*list);
+
+  // Make sure arg_list takes a deep copy.
+  scoped_ptr<ListValue> list_copy(list->DeepCopy());
+  list.reset();
+  EXPECT_TRUE(arg_list.Get().Equals(list_copy.get()));
+}
+
+TEST_F(JsArgListTest, FromVector) {
+  FundamentalValue bool_value(false);
+  FundamentalValue int_value(5);
+  DictionaryValue dict;
+  dict.SetString("foo", "bar");
+  dict.Set("baz", new ListValue());
+
+  std::vector<const Value*> vec;
+  vec.push_back(&bool_value);
+  vec.push_back(&int_value);
+  vec.push_back(&dict);
+
+  JsArgList arg_list(vec);
+
+  ListValue list;
+  list.Append(bool_value.DeepCopy());
+  list.Append(int_value.DeepCopy());
+  list.Append(dict.DeepCopy());
+
+  // Make sure arg_list takes a deep copy.
+  vec.clear();
+  dict.SetString("baz", "foo");
+  EXPECT_TRUE(arg_list.Get().Equals(&list));
+}
+
+}  // namespace
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/js_backend.h b/chrome/browser/sync/js_backend.h
new file mode 100644
index 0000000..6d5ec92
--- /dev/null
+++ b/chrome/browser/sync/js_backend.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_SYNC_JS_BACKEND_H_
+#define CHROME_BROWSER_SYNC_JS_BACKEND_H_
+#pragma once
+
+// See README.js for design comments.
+
+#include <string>
+
+namespace browser_sync {
+
+class JsArgList;
+class JsEventHandler;
+class JsEventRouter;
+
+class JsBackend {
+ public:
+  // Sets the JS event router to which all backend events will be
+  // sent.
+  virtual void SetParentJsEventRouter(JsEventRouter* router) = 0;
+
+  // Removes any existing JS event router.
+  virtual void RemoveParentJsEventRouter() = 0;
+
+  // Gets the crurent JS event router, or NULL if there is none.  Used
+  // for testing.
+  virtual const JsEventRouter* GetParentJsEventRouter() const = 0;
+
+  // Processes the given message.  All reply events are sent to the
+  // parent JS event router (if set).
+  virtual void ProcessMessage(
+      const std::string& name, const JsArgList& args,
+      const JsEventHandler* sender) = 0;
+
+ protected:
+  virtual ~JsBackend() {}
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_BACKEND_H_
diff --git a/chrome/browser/sync/js_event_handler.h b/chrome/browser/sync/js_event_handler.h
new file mode 100644
index 0000000..0e8b301
--- /dev/null
+++ b/chrome/browser/sync/js_event_handler.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_SYNC_JS_EVENT_HANDLER_H_
+#define CHROME_BROWSER_SYNC_JS_EVENT_HANDLER_H_
+#pragma once
+
+// See README.js for design comments.
+
+#include <string>
+
+namespace browser_sync {
+
+class JsArgList;
+
+// An interface for objects that handle Javascript events (e.g.,
+// WebUIs).
+class JsEventHandler {
+ public:
+  virtual void HandleJsEvent(
+      const std::string& name, const JsArgList& args) = 0;
+
+ protected:
+  virtual ~JsEventHandler() {}
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_EVENT_HANDLER_H_
diff --git a/chrome/browser/sync/js_event_handler_list.cc b/chrome/browser/sync/js_event_handler_list.cc
new file mode 100644
index 0000000..abc6193
--- /dev/null
+++ b/chrome/browser/sync/js_event_handler_list.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/js_event_handler_list.h"
+
+#include <cstddef>
+
+#include "base/logging.h"
+#include "chrome/browser/sync/js_backend.h"
+#include "chrome/browser/sync/js_event_handler.h"
+
+namespace browser_sync {
+
+JsEventHandlerList::PendingMessage::PendingMessage(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* sender)
+    : name(name), args(args), sender(sender) {}
+
+JsEventHandlerList::JsEventHandlerList() : backend_(NULL) {}
+
+JsEventHandlerList::~JsEventHandlerList() {
+  RemoveBackend();
+}
+
+// We connect to the backend only when necessary, i.e. when there is
+// at least one handler.
+
+void JsEventHandlerList::AddHandler(JsEventHandler* handler) {
+  handlers_.AddObserver(handler);
+  if (backend_) {
+    backend_->SetParentJsEventRouter(this);
+  }
+}
+
+void JsEventHandlerList::RemoveHandler(JsEventHandler* handler) {
+  handlers_.RemoveObserver(handler);
+  if (backend_ && handlers_.size() == 0) {
+    backend_->RemoveParentJsEventRouter();
+  }
+}
+
+void JsEventHandlerList::SetBackend(JsBackend* backend) {
+  DCHECK(!backend_);
+  DCHECK(backend);
+  backend_ = backend;
+
+  if (handlers_.size() > 0) {
+    backend_->SetParentJsEventRouter(this);
+
+    // Process any queued messages.
+    PendingMessageList pending_messages;
+    pending_messages_.swap(pending_messages);
+    for (PendingMessageList::const_iterator it = pending_messages.begin();
+         it != pending_messages.end(); ++it) {
+      backend_->ProcessMessage(it->name, it->args, it->sender);
+    }
+  }
+}
+
+void JsEventHandlerList::RemoveBackend() {
+  if (backend_) {
+    backend_->RemoveParentJsEventRouter();
+    backend_ = NULL;
+  }
+}
+
+void JsEventHandlerList::ProcessMessage(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* sender) {
+  if (backend_) {
+    backend_->ProcessMessage(name, args, sender);
+  } else {
+    pending_messages_.push_back(PendingMessage(name, args, sender));
+  }
+}
+
+void JsEventHandlerList::RouteJsEvent(const std::string& name,
+                                      const JsArgList& args,
+                                      const JsEventHandler* target) {
+  if (target) {
+    JsEventHandler* non_const_target(const_cast<JsEventHandler*>(target));
+    if (handlers_.HasObserver(non_const_target)) {
+      non_const_target->HandleJsEvent(name, args);
+    } else {
+      VLOG(1) << "Unknown target; dropping event " << name
+              << " with args " << args.ToString();
+    }
+  } else {
+    FOR_EACH_OBSERVER(JsEventHandler, handlers_, HandleJsEvent(name, args));
+  }
+}
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/js_event_handler_list.h b/chrome/browser/sync/js_event_handler_list.h
new file mode 100644
index 0000000..2d5cf9e
--- /dev/null
+++ b/chrome/browser/sync/js_event_handler_list.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 CHROME_BROWSER_SYNC_JS_EVENT_HANDLER_LIST_H_
+#define CHROME_BROWSER_SYNC_JS_EVENT_HANDLER_LIST_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_event_router.h"
+#include "chrome/browser/sync/js_frontend.h"
+
+namespace browser_sync {
+
+class JsBackend;
+class JsEventHandler;
+
+// A beefed-up ObserverList<JsEventHandler> that transparently handles
+// the communication between the handlers and a backend.
+class JsEventHandlerList : public JsFrontend, public JsEventRouter {
+ public:
+  JsEventHandlerList();
+
+  virtual ~JsEventHandlerList();
+
+  // Sets the backend to route all messages to.  Should be called only
+  // if a backend has not already been set.
+  void SetBackend(JsBackend* backend);
+
+  // Removes any existing backend.
+  void RemoveBackend();
+
+  // JsFrontend implementation.  Routes messages to any attached
+  // backend; if there is none, queues up the message for processing
+  // when the next backend is attached.
+  virtual void AddHandler(JsEventHandler* handler);
+  virtual void RemoveHandler(JsEventHandler* handler);
+  virtual void ProcessMessage(
+      const std::string& name, const JsArgList& args,
+      const JsEventHandler* sender);
+
+  // JsEventRouter implementation.  Routes the event to the
+  // appropriate handler(s).
+  virtual void RouteJsEvent(const std::string& name,
+                            const JsArgList& args,
+                            const JsEventHandler* target);
+
+ private:
+  // A struct used to hold the arguments to ProcessMessage() for
+  // future invocation.
+  struct PendingMessage {
+    std::string name;
+    JsArgList args;
+    const JsEventHandler* sender;
+
+    PendingMessage(const std::string& name, const JsArgList& args,
+                   const JsEventHandler* sender);
+  };
+
+  typedef std::vector<PendingMessage> PendingMessageList;
+
+  JsBackend* backend_;
+  ObserverList<JsEventHandler> handlers_;
+  PendingMessageList pending_messages_;
+
+  DISALLOW_COPY_AND_ASSIGN(JsEventHandlerList);
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_EVENT_HANDLER_LIST_H_
diff --git a/chrome/browser/sync/js_event_handler_list_unittest.cc b/chrome/browser/sync/js_event_handler_list_unittest.cc
new file mode 100644
index 0000000..449e70f
--- /dev/null
+++ b/chrome/browser/sync/js_event_handler_list_unittest.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/js_event_handler_list.h"
+
+#include "base/values.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+using ::testing::StrictMock;
+
+class JsEventHandlerListTest : public testing::Test {};
+
+TEST_F(JsEventHandlerListTest, Basic) {
+  // |backend| must outlive |event_handlers|.
+  StrictMock<MockJsBackend> backend;
+
+  JsEventHandlerList event_handlers;
+
+  ListValue arg_list1, arg_list2;
+  arg_list1.Append(Value::CreateBooleanValue(false));
+  arg_list2.Append(Value::CreateIntegerValue(5));
+  JsArgList args1(arg_list1), args2(arg_list2);
+
+  StrictMock<MockJsEventHandler> handler1, handler2;
+
+  // Once from each call to AddHandler().
+  EXPECT_CALL(backend, SetParentJsEventRouter(&event_handlers)).Times(2);
+  // Once from the second RemoveHandler(), once from the destructor.
+  EXPECT_CALL(backend, RemoveParentJsEventRouter()).Times(2);
+  EXPECT_CALL(backend, ProcessMessage("test1", HasArgs(args2), &handler1));
+  EXPECT_CALL(backend, ProcessMessage("test2", HasArgs(args1), &handler2));
+
+  EXPECT_CALL(handler1, HandleJsEvent("reply1", HasArgs(args2)));
+  EXPECT_CALL(handler1, HandleJsEvent("allreply", HasArgs(args1)));
+
+  EXPECT_CALL(handler2, HandleJsEvent("reply2", HasArgs(args1)));
+  EXPECT_CALL(handler2, HandleJsEvent("allreply", HasArgs(args1)));
+  EXPECT_CALL(handler2, HandleJsEvent("anotherreply2", HasArgs(args2)));
+  EXPECT_CALL(handler2, HandleJsEvent("anotherallreply", HasArgs(args2)));
+
+  event_handlers.SetBackend(&backend);
+
+  event_handlers.AddHandler(&handler1);
+  event_handlers.AddHandler(&handler2);
+
+  event_handlers.ProcessMessage("test1", args2, &handler1);
+
+  event_handlers.RouteJsEvent("reply2", args1, &handler2);
+  event_handlers.RouteJsEvent("reply1", args2, &handler1);
+  event_handlers.RouteJsEvent("allreply", args1, NULL);
+
+  event_handlers.RemoveHandler(&handler1);
+
+  event_handlers.ProcessMessage("test2", args1, &handler2);
+
+  event_handlers.RouteJsEvent("droppedreply1", args1, &handler1);
+  event_handlers.RouteJsEvent("anotherreply2", args2, &handler2);
+  event_handlers.RouteJsEvent("anotherallreply", args2, NULL);
+
+  event_handlers.RemoveHandler(&handler2);
+
+  event_handlers.RouteJsEvent("anotherdroppedreply1", args1, &handler1);
+  event_handlers.RouteJsEvent("anotheranotherreply2", args2, &handler2);
+  event_handlers.RouteJsEvent("droppedallreply", args2, NULL);
+
+  // Let destructor of |event_handlers| call RemoveBackend().
+}
+
+TEST_F(JsEventHandlerListTest, QueuedMessages) {
+  // |backend| must outlive |event_handlers|.
+  StrictMock<MockJsBackend> backend;
+
+  JsEventHandlerList event_handlers;
+
+  ListValue arg_list1, arg_list2;
+  arg_list1.Append(Value::CreateBooleanValue(false));
+  arg_list2.Append(Value::CreateIntegerValue(5));
+  JsArgList args1(arg_list1), args2(arg_list2);
+
+  StrictMock<MockJsEventHandler> handler1, handler2;
+
+  // Once from the call to SetBackend().
+  EXPECT_CALL(backend, SetParentJsEventRouter(&event_handlers));
+  // Once from the first call to RemoveBackend().
+  EXPECT_CALL(backend, RemoveParentJsEventRouter());
+  // Once from the call to SetBackend().
+  EXPECT_CALL(backend, ProcessMessage("test1", HasArgs(args2), &handler1));
+  // Once from the call to SetBackend().
+  EXPECT_CALL(backend, ProcessMessage("test2", HasArgs(args1), &handler2));
+
+  event_handlers.AddHandler(&handler1);
+  event_handlers.AddHandler(&handler2);
+
+  // Should queue messages.
+  event_handlers.ProcessMessage("test1", args2, &handler1);
+  event_handlers.ProcessMessage("test2", args1, &handler2);
+
+  // Should call the queued messages.
+  event_handlers.SetBackend(&backend);
+
+  event_handlers.RemoveBackend();
+  // Should do nothing.
+  event_handlers.RemoveBackend();
+}
+
+}  // namespace
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/js_event_router.h b/chrome/browser/sync/js_event_router.h
new file mode 100644
index 0000000..be783f4
--- /dev/null
+++ b/chrome/browser/sync/js_event_router.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_SYNC_JS_EVENT_ROUTER_H_
+#define CHROME_BROWSER_SYNC_JS_EVENT_ROUTER_H_
+#pragma once
+
+// See README.js for design comments.
+
+#include <string>
+
+namespace browser_sync {
+
+class JsArgList;
+class JsEventHandler;
+
+// An interface for objects that don't directly handle Javascript
+// events but can pass them to JsEventHandlers or route them to other
+// JsEventRouters.
+class JsEventRouter {
+ public:
+  // If |target| is NULL that means the event is intended for every
+  // handler.  Otherwise the event is meant for the given target only.
+  // |target| is const because it shouldn't be used except by the
+  // router that directly knows about it (which can then safely cast
+  // away the constness).
+  virtual void RouteJsEvent(const std::string& name, const JsArgList& args,
+                            const JsEventHandler* target) = 0;
+
+ protected:
+  virtual ~JsEventRouter() {}
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_EVENT_ROUTER_H_
diff --git a/chrome/browser/sync/js_frontend.h b/chrome/browser/sync/js_frontend.h
new file mode 100644
index 0000000..e57cacd
--- /dev/null
+++ b/chrome/browser/sync/js_frontend.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_JS_FRONTEND_H_
+#define CHROME_BROWSER_SYNC_JS_FRONTEND_H_
+#pragma once
+
+// See README.js for design comments.
+
+#include <string>
+
+namespace browser_sync {
+
+class JsArgList;
+class JsEventHandler;
+
+// An interface for objects that interact directly with
+// JsEventHandlers.
+class JsFrontend {
+ public:
+  // Adds a handler which will start receiving JS events (not
+  // immediately, so this can be called in the handler's constructor).
+  // A handler must be added at most once.
+  virtual void AddHandler(JsEventHandler* handler) = 0;
+
+  // Removes the given handler if it has been added.  It will
+  // immediately stop receiving any JS events.
+  virtual void RemoveHandler(JsEventHandler* handler) = 0;
+
+  // Sends a JS message.  The reply (if any) will be sent to |sender|
+  // if it has been added.
+  virtual void ProcessMessage(
+      const std::string& name, const JsArgList& args,
+      const JsEventHandler* sender) = 0;
+
+ protected:
+  virtual ~JsFrontend() {}
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_FRONTEND_H_
diff --git a/chrome/browser/sync/js_sync_manager_observer.cc b/chrome/browser/sync/js_sync_manager_observer.cc
new file mode 100644
index 0000000..407ce98
--- /dev/null
+++ b/chrome/browser/sync/js_sync_manager_observer.cc
@@ -0,0 +1,117 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/js_sync_manager_observer.h"
+
+#include <cstddef>
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_event_router.h"
+#include "chrome/browser/sync/sessions/session_state.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "chrome/browser/sync/sessions/session_state.h"
+
+namespace browser_sync {
+
+JsSyncManagerObserver::JsSyncManagerObserver(JsEventRouter* parent_router)
+    : parent_router_(parent_router) {
+  DCHECK(parent_router_);
+}
+
+JsSyncManagerObserver::~JsSyncManagerObserver() {}
+
+void JsSyncManagerObserver::OnChangesApplied(
+    syncable::ModelType model_type,
+    const sync_api::BaseTransaction* trans,
+    const sync_api::SyncManager::ChangeRecord* changes,
+    int change_count) {
+  ListValue return_args;
+  return_args.Append(Value::CreateStringValue(
+      syncable::ModelTypeToString(model_type)));
+  ListValue* change_values = new ListValue();
+  return_args.Append(change_values);
+  for (int i = 0; i < change_count; ++i) {
+    change_values->Append(changes->ToValue(trans));
+  }
+  parent_router_->RouteJsEvent("onChangesApplied",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnChangesComplete(
+    syncable::ModelType model_type) {
+  ListValue return_args;
+  return_args.Append(Value::CreateStringValue(
+      syncable::ModelTypeToString(model_type)));
+  parent_router_->RouteJsEvent("onChangesComplete",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnSyncCycleCompleted(
+    const sessions::SyncSessionSnapshot* snapshot) {
+  ListValue return_args;
+  return_args.Append(snapshot->ToValue());
+  parent_router_->RouteJsEvent("onSyncCycleCompleted",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnAuthError(
+    const GoogleServiceAuthError& auth_error) {
+  ListValue return_args;
+  return_args.Append(auth_error.ToValue());
+  parent_router_->RouteJsEvent("onAuthError",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnUpdatedToken(const std::string& token) {
+  ListValue return_args;
+  return_args.Append(Value::CreateStringValue("<redacted>"));
+  parent_router_->RouteJsEvent("onUpdatedToken",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnPassphraseRequired(bool for_decryption) {
+  ListValue return_args;
+  return_args.Append(Value::CreateBooleanValue(for_decryption));
+  parent_router_->RouteJsEvent("onPassphraseRequired",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnPassphraseAccepted(
+    const std::string& bootstrap_token) {
+  ListValue return_args;
+  return_args.Append(Value::CreateStringValue("<redacted>"));
+  parent_router_->RouteJsEvent("onPassphraseAccepted",
+                               JsArgList(return_args), NULL);
+}
+
+void JsSyncManagerObserver::OnInitializationComplete() {
+  parent_router_->RouteJsEvent("onInitializationComplete",
+                               JsArgList(), NULL);
+}
+
+void JsSyncManagerObserver::OnPaused() {
+  parent_router_->RouteJsEvent("onPaused", JsArgList(), NULL);
+}
+
+void JsSyncManagerObserver::OnResumed() {
+  parent_router_->RouteJsEvent("onResumed", JsArgList(), NULL);
+}
+
+void JsSyncManagerObserver::OnStopSyncingPermanently() {
+  parent_router_->RouteJsEvent("onStopSyncingPermanently",
+                               JsArgList(), NULL);
+}
+
+void JsSyncManagerObserver::OnClearServerDataSucceeded() {
+  parent_router_->RouteJsEvent("onClearServerDataSucceeded",
+                               JsArgList(), NULL);
+}
+
+void JsSyncManagerObserver::OnClearServerDataFailed() {
+  parent_router_->RouteJsEvent("onClearServerDataFailed", JsArgList(), NULL);
+}
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/js_sync_manager_observer.h b/chrome/browser/sync/js_sync_manager_observer.h
new file mode 100644
index 0000000..aa710ef
--- /dev/null
+++ b/chrome/browser/sync/js_sync_manager_observer.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_SYNC_JS_SYNC_MANAGER_OBSERVER_H_
+#define CHROME_BROWSER_SYNC_JS_SYNC_MANAGER_OBSERVER_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/sync/engine/syncapi.h"
+
+namespace browser_sync {
+
+class JsEventRouter;
+
+// Routes SyncManager events to a JsEventRouter.
+class JsSyncManagerObserver : public sync_api::SyncManager::Observer {
+ public:
+  // |parent_router| must be non-NULL and must outlive this object.
+  explicit JsSyncManagerObserver(JsEventRouter* parent_router);
+
+  virtual ~JsSyncManagerObserver();
+
+  // sync_api::SyncManager::Observer implementation.
+  virtual void OnChangesApplied(
+      syncable::ModelType model_type,
+      const sync_api::BaseTransaction* trans,
+      const sync_api::SyncManager::ChangeRecord* changes,
+      int change_count);
+  virtual void OnChangesComplete(syncable::ModelType model_type);
+  virtual void OnSyncCycleCompleted(
+      const sessions::SyncSessionSnapshot* snapshot);
+  virtual void OnAuthError(const GoogleServiceAuthError& auth_error);
+  virtual void OnUpdatedToken(const std::string& token);
+  virtual void OnPassphraseRequired(bool for_decryption);
+  virtual void OnPassphraseAccepted(const std::string& bootstrap_token);
+  virtual void OnInitializationComplete();
+  virtual void OnPaused();
+  virtual void OnResumed();
+  virtual void OnStopSyncingPermanently();
+  virtual void OnClearServerDataSucceeded();
+  virtual void OnClearServerDataFailed();
+
+ private:
+  JsEventRouter* parent_router_;
+
+  DISALLOW_COPY_AND_ASSIGN(JsSyncManagerObserver);
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_SYNC_MANAGER_OBSERVER_H_
diff --git a/chrome/browser/sync/js_sync_manager_observer_unittest.cc b/chrome/browser/sync/js_sync_manager_observer_unittest.cc
new file mode 100644
index 0000000..11df4d5
--- /dev/null
+++ b/chrome/browser/sync/js_sync_manager_observer_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 "chrome/browser/sync/js_sync_manager_observer.h"
+
+#include <cstddef>
+
+#include "base/basictypes.h"
+#include "base/values.h"
+#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_test_util.h"
+#include "chrome/browser/sync/sessions/session_state.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "chrome/test/sync/engine/test_directory_setter_upper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+using ::testing::InSequence;
+using ::testing::StrictMock;
+
+class JsSyncManagerObserverTest : public testing::Test {
+ protected:
+  JsSyncManagerObserverTest() : sync_manager_observer_(&mock_router_) {}
+
+  StrictMock<MockJsEventRouter> mock_router_;
+  JsSyncManagerObserver sync_manager_observer_;
+};
+
+TEST_F(JsSyncManagerObserverTest, NoArgNotifiations) {
+  InSequence dummy;
+
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onInitializationComplete",
+                           HasArgs(JsArgList()), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onPaused",
+                           HasArgs(JsArgList()), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onResumed",
+                           HasArgs(JsArgList()), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onStopSyncingPermanently",
+                           HasArgs(JsArgList()), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onClearServerDataSucceeded",
+                           HasArgs(JsArgList()), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onClearServerDataFailed",
+                           HasArgs(JsArgList()), NULL));
+
+  sync_manager_observer_.OnInitializationComplete();
+  sync_manager_observer_.OnPaused();
+  sync_manager_observer_.OnResumed();
+  sync_manager_observer_.OnStopSyncingPermanently();
+  sync_manager_observer_.OnClearServerDataSucceeded();
+  sync_manager_observer_.OnClearServerDataFailed();
+}
+
+TEST_F(JsSyncManagerObserverTest, OnChangesComplete) {
+  InSequence dummy;
+
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT; ++i) {
+    const std::string& model_type_str =
+        syncable::ModelTypeToString(syncable::ModelTypeFromInt(i));
+    ListValue expected_args;
+    expected_args.Append(Value::CreateStringValue(model_type_str));
+    EXPECT_CALL(mock_router_,
+                RouteJsEvent("onChangesComplete",
+                             HasArgsAsList(expected_args), NULL));
+  }
+
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT; ++i) {
+    sync_manager_observer_.OnChangesComplete(syncable::ModelTypeFromInt(i));
+  }
+}
+
+TEST_F(JsSyncManagerObserverTest, OnSyncCycleCompleted) {
+  std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
+  sessions::SyncSessionSnapshot snapshot(sessions::SyncerStatus(),
+                                         sessions::ErrorCounters(),
+                                         100,
+                                         false,
+                                         syncable::ModelTypeBitSet(),
+                                         download_progress_markers,
+                                         false,
+                                         true,
+                                         100,
+                                         5,
+                                         false,
+                                         sessions::SyncSourceInfo());
+  ListValue expected_args;
+  expected_args.Append(snapshot.ToValue());
+
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onSyncCycleCompleted",
+                           HasArgsAsList(expected_args), NULL));
+
+  sync_manager_observer_.OnSyncCycleCompleted(&snapshot);
+}
+
+TEST_F(JsSyncManagerObserverTest, OnAuthError) {
+  GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
+  ListValue expected_args;
+  expected_args.Append(error.ToValue());
+
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onAuthError",
+                           HasArgsAsList(expected_args), NULL));
+
+  sync_manager_observer_.OnAuthError(error);
+}
+
+TEST_F(JsSyncManagerObserverTest, OnPassphraseRequired) {
+  InSequence dummy;
+
+  ListValue true_args, false_args;
+  true_args.Append(Value::CreateBooleanValue(true));
+  false_args.Append(Value::CreateBooleanValue(false));
+
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onPassphraseRequired",
+                           HasArgsAsList(false_args), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onPassphraseRequired",
+                           HasArgsAsList(true_args), NULL));
+
+  sync_manager_observer_.OnPassphraseRequired(false);
+  sync_manager_observer_.OnPassphraseRequired(true);
+}
+
+TEST_F(JsSyncManagerObserverTest, SensitiveNotifiations) {
+  ListValue redacted_args;
+  redacted_args.Append(Value::CreateStringValue("<redacted>"));
+
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onUpdatedToken",
+                           HasArgsAsList(redacted_args), NULL));
+  EXPECT_CALL(mock_router_,
+              RouteJsEvent("onPassphraseAccepted",
+                           HasArgsAsList(redacted_args), NULL));
+
+  sync_manager_observer_.OnUpdatedToken("sensitive_token");
+  sync_manager_observer_.OnPassphraseAccepted("sensitive_token");
+}
+
+namespace {
+
+// Makes a node of the given model type.  Returns the id of the
+// newly-created node.
+int64 MakeNode(sync_api::UserShare* share, syncable::ModelType model_type) {
+  sync_api::WriteTransaction trans(share);
+  sync_api::ReadNode root_node(&trans);
+  root_node.InitByRootLookup();
+  sync_api::WriteNode node(&trans);
+  EXPECT_TRUE(node.InitUniqueByCreation(
+      model_type, root_node,
+      syncable::ModelTypeToString(model_type)));
+  node.SetIsFolder(false);
+  return node.GetId();
+}
+
+}  // namespace
+
+TEST_F(JsSyncManagerObserverTest, OnChangesApplied) {
+  InSequence dummy;
+
+  TestDirectorySetterUpper setter_upper;
+  sync_api::UserShare share;
+  setter_upper.SetUp();
+  share.dir_manager.reset(setter_upper.manager());
+  share.name = setter_upper.name();
+
+  // We don't test with passwords as that requires additional setup.
+
+  // Build a list of example ChangeRecords.
+  sync_api::SyncManager::ChangeRecord changes[syncable::PASSWORDS];
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::PASSWORDS; ++i) {
+    changes[i].id = MakeNode(&share, syncable::ModelTypeFromInt(i));
+    switch (i % 3) {
+      case 0:
+        changes[i].action =
+            sync_api::SyncManager::ChangeRecord::ACTION_ADD;
+        break;
+      case 1:
+        changes[i].action =
+            sync_api::SyncManager::ChangeRecord::ACTION_UPDATE;
+        break;
+      default:
+        changes[i].action =
+            sync_api::SyncManager::ChangeRecord::ACTION_DELETE;
+        break;
+    }
+    {
+      sync_api::ReadTransaction trans(&share);
+      sync_api::ReadNode node(&trans);
+      EXPECT_TRUE(node.InitByIdLookup(changes[i].id));
+      changes[i].specifics = node.GetEntry()->Get(syncable::SPECIFICS);
+    }
+  }
+
+  // Set expectations for each data type.
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::PASSWORDS; ++i) {
+    const std::string& model_type_str =
+        syncable::ModelTypeToString(syncable::ModelTypeFromInt(i));
+    ListValue expected_args;
+    expected_args.Append(Value::CreateStringValue(model_type_str));
+    ListValue* expected_changes = new ListValue();
+    expected_args.Append(expected_changes);
+    for (int j = i; j < syncable::PASSWORDS; ++j) {
+      sync_api::ReadTransaction trans(&share);
+      expected_changes->Append(changes[i].ToValue(&trans));
+    }
+    EXPECT_CALL(mock_router_,
+                RouteJsEvent("onChangesApplied",
+                             HasArgsAsList(expected_args), NULL));
+  }
+
+  // Fire OnChangesApplied() for each data type.
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::PASSWORDS; ++i) {
+    sync_api::ReadTransaction trans(&share);
+    sync_manager_observer_.OnChangesApplied(syncable::ModelTypeFromInt(i),
+                                            &trans, &changes[i],
+                                            syncable::PASSWORDS - i);
+  }
+
+  // |share.dir_manager| does not actually own its value.
+  ignore_result(share.dir_manager.release());
+  setter_upper.TearDown();
+}
+
+}  // namespace
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/js_test_util.cc b/chrome/browser/sync/js_test_util.cc
new file mode 100644
index 0000000..bd4f9c0
--- /dev/null
+++ b/chrome/browser/sync/js_test_util.cc
@@ -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.
+
+#include "chrome/browser/sync/js_test_util.h"
+
+#include "base/basictypes.h"
+#include "chrome/browser/sync/js_arg_list.h"
+
+namespace browser_sync {
+
+void PrintTo(const JsArgList& args, ::std::ostream* os) {
+  *os << args.ToString();
+}
+
+namespace {
+
+// Matcher implementation for HasArgs().
+class HasArgsMatcher
+    : public ::testing::MatcherInterface<const JsArgList&> {
+ public:
+  explicit HasArgsMatcher(const JsArgList& expected_args)
+      : expected_args_(expected_args) {}
+
+  virtual ~HasArgsMatcher() {}
+
+  virtual bool MatchAndExplain(
+      const JsArgList& args,
+      ::testing::MatchResultListener* listener) const {
+    // No need to annotate listener since we already define PrintTo().
+    return args.Get().Equals(&expected_args_.Get());
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has args " << expected_args_.ToString();
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't have args " << expected_args_.ToString();
+  }
+
+ private:
+  const JsArgList expected_args_;
+
+  DISALLOW_COPY_AND_ASSIGN(HasArgsMatcher);
+};
+
+}  // namespace
+
+::testing::Matcher<const JsArgList&> HasArgs(const JsArgList& expected_args) {
+  return ::testing::MakeMatcher(new HasArgsMatcher(expected_args));
+}
+
+::testing::Matcher<const JsArgList&> HasArgsAsList(
+    const ListValue& expected_args) {
+  return HasArgs(JsArgList(expected_args));
+}
+
+MockJsBackend::MockJsBackend() {}
+
+MockJsBackend::~MockJsBackend() {}
+
+MockJsFrontend::MockJsFrontend() {}
+
+MockJsFrontend::~MockJsFrontend() {}
+
+MockJsEventHandler::MockJsEventHandler() {}
+
+MockJsEventHandler::~MockJsEventHandler() {}
+
+MockJsEventRouter::MockJsEventRouter() {}
+
+MockJsEventRouter::~MockJsEventRouter() {}
+
+}  // namespace browser_sync
+
diff --git a/chrome/browser/sync/js_test_util.h b/chrome/browser/sync/js_test_util.h
new file mode 100644
index 0000000..23a8dad
--- /dev/null
+++ b/chrome/browser/sync/js_test_util.h
@@ -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.
+
+#ifndef CHROME_BROWSER_SYNC_JS_TEST_UTIL_H_
+#define CHROME_BROWSER_SYNC_JS_TEST_UTIL_H_
+#pragma once
+
+#include <ostream>
+#include <string>
+
+#include "chrome/browser/sync/js_backend.h"
+#include "chrome/browser/sync/js_frontend.h"
+#include "chrome/browser/sync/js_event_handler.h"
+#include "chrome/browser/sync/js_event_router.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class ListValue;
+
+namespace browser_sync {
+
+class JsArgList;
+
+// Defined for googletest.  Equivalent to "*os << args.ToString()".
+void PrintTo(const JsArgList& args, ::std::ostream* os);
+
+// A matcher for gmock.  Use like:
+//
+//   EXPECT_CALL(mock, ProcessMessage("foo", HasArgs(args))).Times(1);
+::testing::Matcher<const JsArgList&> HasArgs(const JsArgList& expected_args);
+
+// Like HasArgs() but takes a ListValue instead.
+::testing::Matcher<const JsArgList&> HasArgsAsList(
+    const ListValue& expected_args);
+
+// Mocks.
+
+class MockJsBackend : public JsBackend {
+ public:
+  MockJsBackend();
+  ~MockJsBackend();
+
+  MOCK_METHOD1(SetParentJsEventRouter, void(JsEventRouter*));
+  MOCK_METHOD0(RemoveParentJsEventRouter, void());
+  MOCK_CONST_METHOD0(GetParentJsEventRouter, const JsEventRouter*());
+  MOCK_METHOD3(ProcessMessage, void(const ::std::string&, const JsArgList&,
+                                    const JsEventHandler*));
+};
+
+class MockJsFrontend : public JsFrontend {
+ public:
+  MockJsFrontend();
+  ~MockJsFrontend();
+
+  MOCK_METHOD1(AddHandler, void(JsEventHandler*));
+  MOCK_METHOD1(RemoveHandler, void(JsEventHandler*));
+  MOCK_METHOD3(ProcessMessage,
+               void(const ::std::string&, const JsArgList&,
+                    const JsEventHandler*));
+};
+
+class MockJsEventHandler : public JsEventHandler {
+ public:
+  MockJsEventHandler();
+  ~MockJsEventHandler();
+
+  MOCK_METHOD2(HandleJsEvent, void(const ::std::string&, const JsArgList&));
+};
+
+class MockJsEventRouter : public JsEventRouter {
+ public:
+  MockJsEventRouter();
+  ~MockJsEventRouter();
+
+  MOCK_METHOD3(RouteJsEvent,
+               void(const ::std::string&, const JsArgList&,
+                    const JsEventHandler*));
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_JS_TEST_UTIL_H_
diff --git a/chrome/browser/sync/notifier/cache_invalidation_packet_handler.cc b/chrome/browser/sync/notifier/cache_invalidation_packet_handler.cc
index be46eca..7fec7f4 100644
--- a/chrome/browser/sync/notifier/cache_invalidation_packet_handler.cc
+++ b/chrome/browser/sync/notifier/cache_invalidation_packet_handler.cc
@@ -84,15 +84,9 @@
 
  private:
   bool IsValidCacheInvalidationIqPacket(const buzz::XmlElement* stanza) {
-    // We make sure to compare jids (which are normalized) instead of
-    // just strings -- server may use non-normalized jids in
-    // attributes.
-    //
-    // TODO(akalin): Add unit tests for this.
-    buzz::Jid to(stanza->Attr(buzz::QN_TO));
-    return
-        (MatchRequestIq(stanza, buzz::STR_SET, kQnData) &&
-         (to == GetClient()->jid()));
+    // We deliberately minimize the verification we do here: see
+    // http://crbug.com/71285 .
+    return MatchRequestIq(stanza, buzz::STR_SET, kQnData);
   }
 
   bool GetCacheInvalidationIqPacketData(const buzz::XmlElement* stanza,
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client.cc b/chrome/browser/sync/notifier/chrome_invalidation_client.cc
index 4a84d3d..f80a346 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client.cc
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client.cc
@@ -38,9 +38,9 @@
 }
 
 void ChromeInvalidationClient::Start(
-    const std::string& client_id, const std::string& state,
-    Listener* listener, StateWriter* state_writer,
-    base::WeakPtr<talk_base::Task> base_task) {
+    const std::string& client_id, const std::string& client_info,
+    const std::string& state, Listener* listener,
+    StateWriter* state_writer, base::WeakPtr<talk_base::Task> base_task) {
   DCHECK(non_thread_safe_.CalledOnValidThread());
   Stop();
 
@@ -64,8 +64,8 @@
   client_config.max_ops_per_message = 40;
   invalidation_client_.reset(
       new invalidation::InvalidationClientImpl(
-          &chrome_system_resources_, client_type, client_id, client_config,
-          this));
+          &chrome_system_resources_, client_type, client_id, client_info,
+          client_config, this));
   invalidation_client_->Start(state);
   invalidation::NetworkEndpoint* network_endpoint =
       invalidation_client_->network_endpoint();
@@ -112,10 +112,6 @@
        i < syncable::MODEL_TYPE_COUNT; ++i) {
     registration_manager_->RegisterType(syncable::ModelTypeFromInt(i));
   }
-  // TODO(akalin): This is a hack to make new sync data types work
-  // with server-issued notifications.  Remove this when it's not
-  // needed anymore.
-  registration_manager_->RegisterType(syncable::UNSPECIFIED);
 }
 
 void ChromeInvalidationClient::Invalidate(
@@ -126,7 +122,12 @@
   VLOG(1) << "Invalidate: " << InvalidationToString(invalidation);
   syncable::ModelType model_type;
   if (ObjectIdToRealModelType(invalidation.object_id(), &model_type)) {
-    listener_->OnInvalidate(model_type);
+    std::string payload;
+    // payload() CHECK()'s has_payload(), so we must check it ourselves first.
+    if (invalidation.has_payload())
+      payload = invalidation.payload();
+
+    listener_->OnInvalidate(model_type, payload);
   } else {
     LOG(WARNING) << "Could not get invalidation model type; "
                  << "invalidating everything";
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client.h b/chrome/browser/sync/notifier/chrome_invalidation_client.h
index 99af02c..873b877 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client.h
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client.h
@@ -41,7 +41,8 @@
    public:
     virtual ~Listener();
 
-    virtual void OnInvalidate(syncable::ModelType model_type) = 0;
+    virtual void OnInvalidate(syncable::ModelType model_type,
+                              const std::string& payload) = 0;
 
     virtual void OnInvalidateAll() = 0;
   };
@@ -54,9 +55,9 @@
   // Does not take ownership of |listener| or |state_writer|.
   // |base_task| must still be non-NULL.
   void Start(
-      const std::string& client_id, const std::string& state,
-      Listener* listener, StateWriter* state_writer,
-      base::WeakPtr<talk_base::Task> base_task);
+      const std::string& client_id, const std::string& client_info,
+      const std::string& state, Listener* listener,
+      StateWriter* state_writer, base::WeakPtr<talk_base::Task> base_task);
 
   void Stop();
 
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc b/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc
index 8e09e13..13438b9 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc
@@ -18,7 +18,8 @@
 
 class MockListener : public ChromeInvalidationClient::Listener {
  public:
-  MOCK_METHOD1(OnInvalidate, void(syncable::ModelType));
+  MOCK_METHOD2(OnInvalidate, void(syncable::ModelType,
+                                  const std::string& payload));
   MOCK_METHOD0(OnInvalidateAll, void());
 };
 
@@ -37,13 +38,15 @@
 
 namespace {
 const char kClientId[] = "client_id";
+const char kClientInfo[] = "client_info";
 const char kState[] = "state";
 }  // namespace
 
 class ChromeInvalidationClientTest : public testing::Test {
  protected:
   virtual void SetUp() {
-    client_.Start(kClientId, kState, &mock_listener_, &mock_state_writer_,
+    client_.Start(kClientId, kClientInfo, kState,
+                  &mock_listener_, &mock_state_writer_,
                   fake_base_task_.AsWeakPtr());
   }
 
diff --git a/chrome/browser/sync/notifier/server_notifier_thread.cc b/chrome/browser/sync/notifier/server_notifier_thread.cc
index f16587f..e8ca751 100644
--- a/chrome/browser/sync/notifier/server_notifier_thread.cc
+++ b/chrome/browser/sync/notifier/server_notifier_thread.cc
@@ -9,9 +9,11 @@
 
 #include "base/logging.h"
 #include "chrome/browser/sync/notifier/chrome_invalidation_client.h"
+#include "googleurl/src/gurl.h"
 #include "jingle/notifier/base/notifier_options.h"
 #include "jingle/notifier/listener/notification_defines.h"
 #include "talk/xmpp/xmppclient.h"
+#include "webkit/glue/webkit_glue.h"
 
 namespace sync_notifier {
 
@@ -64,18 +66,19 @@
                   "used";
 }
 
-void ServerNotifierThread::OnInvalidate(syncable::ModelType model_type) {
+void ServerNotifierThread::OnInvalidate(
+    syncable::ModelType model_type,
+    const std::string& payload) {
   DCHECK_EQ(MessageLoop::current(), worker_message_loop());
-  // TODO(akalin): This is a hack to make new sync data types work
-  // with server-issued notifications.  Remove this when it's not
-  // needed anymore.
-  VLOG(1) << "OnInvalidate: " << ((model_type == syncable::UNSPECIFIED) ?
-      "UNKNOWN" : syncable::ModelTypeToString(model_type));
+  DCHECK_GE(model_type, syncable::FIRST_REAL_MODEL_TYPE);
+  DCHECK_LT(model_type, syncable::MODEL_TYPE_COUNT);
+  VLOG(1) << "OnInvalidate: " << syncable::ModelTypeToString(model_type);
 
   syncable::ModelTypeBitSet model_types;
   model_types[model_type] = true;
   IncomingNotificationData notification_data;
-  notification_data.service_specific_data = model_types.to_string();
+  notification_data.service_url = model_types.to_string();
+  notification_data.service_specific_data = payload;
   observers_->Notify(&Observer::OnIncomingNotification, notification_data);
 }
 
@@ -86,7 +89,8 @@
   syncable::ModelTypeBitSet model_types;
   model_types.set();  // InvalidateAll, so set all datatypes to true.
   IncomingNotificationData notification_data;
-  notification_data.service_specific_data = model_types.to_string();
+  notification_data.service_url = model_types.to_string();
+  notification_data.service_specific_data = std::string();  // No payload.
   observers_->Notify(&Observer::OnIncomingNotification, notification_data);
 }
 
@@ -115,8 +119,11 @@
     // make it so that we won't receive any notifications that were
     // generated from our own changes.
     const std::string kClientId = "server_notifier_thread";
+    // Use user agent as |client_info| so we can use it for debugging
+    // server-side.
+    const std::string& client_info = webkit_glue::GetUserAgent(GURL());
     chrome_invalidation_client_->Start(
-        kClientId, state_, this, this, base_task_);
+        kClientId, client_info, state_, this, this, base_task_);
     state_.clear();
   }
 }
diff --git a/chrome/browser/sync/notifier/server_notifier_thread.h b/chrome/browser/sync/notifier/server_notifier_thread.h
index 55b60fe..b0b9819 100644
--- a/chrome/browser/sync/notifier/server_notifier_thread.h
+++ b/chrome/browser/sync/notifier/server_notifier_thread.h
@@ -59,7 +59,14 @@
   virtual void SendNotification(const OutgoingNotificationData& data);
 
   // ChromeInvalidationClient::Listener implementation.
-  virtual void OnInvalidate(syncable::ModelType model_type);
+  // We pass on two pieces of information to observers through the
+  // IncomingNotificationData.
+  // - the model type being invalidated, through IncomingNotificationData's
+  //       service_url.
+  // - the invalidation payload for that model type, through
+  //       IncomingNotificationData's service_specific_data.
+  virtual void OnInvalidate(syncable::ModelType model_type,
+                            const std::string& payload);
   virtual void OnInvalidateAll();
 
   // StateWriter implementation.
diff --git a/chrome/browser/sync/profile_sync_factory_impl.cc b/chrome/browser/sync/profile_sync_factory_impl.cc
index 07c1145..c6e0268 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl.cc
@@ -6,10 +6,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/glue/app_data_type_controller.h"
 #include "chrome/browser/sync/glue/autofill_change_processor.h"
-#include "chrome/browser/sync/glue/autofill_change_processor2.h"
 #include "chrome/browser/sync/glue/autofill_data_type_controller.h"
 #include "chrome/browser/sync/glue/autofill_model_associator.h"
-#include "chrome/browser/sync/glue/autofill_model_associator2.h"
 #include "chrome/browser/sync/glue/autofill_profile_change_processor.h"
 #include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h"
 #include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
@@ -41,16 +39,13 @@
 #include "chrome/browser/sync/profile_sync_factory_impl.h"
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 
 using browser_sync::AppDataTypeController;
 using browser_sync::AutofillChangeProcessor;
-using browser_sync::AutofillChangeProcessor2;
 using browser_sync::AutofillProfileChangeProcessor;
 using browser_sync::AutofillDataTypeController;
 using browser_sync::AutofillProfileDataTypeController;
 using browser_sync::AutofillModelAssociator;
-using browser_sync::AutofillModelAssociator2;
 using browser_sync::AutofillProfileModelAssociator;
 using browser_sync::BookmarkChangeProcessor;
 using browser_sync::BookmarkDataTypeController;
@@ -121,7 +116,7 @@
 
   // Password sync is disabled by default.  Register only if
   // explicitly enabled.
-  if (command_line_->HasSwitch(switches::kEnableSyncPasswords)) {
+  if (!command_line_->HasSwitch(switches::kDisableSyncPasswords)) {
     pss->RegisterDataTypeController(
         new PasswordDataTypeController(this, profile_, pss));
   }
@@ -153,8 +148,7 @@
         new SessionDataTypeController(this, pss));
   }
 
-  if (!command_line_->HasSwitch(switches::kDisableSyncAutofillProfile) &&
-      command_line_->HasSwitch(switches::kEnableSyncNewAutofill)) {
+  if (!command_line_->HasSwitch(switches::kDisableSyncAutofillProfile)) {
     pss->RegisterDataTypeController(new AutofillProfileDataTypeController(
         this, profile_, pss));
   }
@@ -189,29 +183,16 @@
     PersonalDataManager* personal_data,
     browser_sync::UnrecoverableErrorHandler* error_handler) {
 
-  if (command_line_->HasSwitch(switches::kEnableSyncNewAutofill)) {
-    AutofillModelAssociator* model_associator =
-        new AutofillModelAssociator(profile_sync_service,
-                                    web_database,
-                                    personal_data);
-    AutofillChangeProcessor* change_processor =
-        new AutofillChangeProcessor(model_associator,
-                                    web_database,
-                                    personal_data,
-                                    error_handler);
-    return SyncComponents(model_associator, change_processor);
-  } else {
-    AutofillModelAssociator2* model_associator =
-        new AutofillModelAssociator2(profile_sync_service,
-                                    web_database,
-                                    personal_data);
-    AutofillChangeProcessor2* change_processor =
-        new AutofillChangeProcessor2(model_associator,
-                                    web_database,
-                                    personal_data,
-                                    error_handler);
-    return SyncComponents(model_associator, change_processor);
-  }
+  AutofillModelAssociator* model_associator =
+      new AutofillModelAssociator(profile_sync_service,
+                                  web_database,
+                                  personal_data);
+  AutofillChangeProcessor* change_processor =
+      new AutofillChangeProcessor(model_associator,
+                                  web_database,
+                                  personal_data,
+                                  error_handler);
+  return SyncComponents(model_associator, change_processor);
 }
 
 ProfileSyncFactory::SyncComponents
diff --git a/chrome/browser/sync/profile_sync_factory_impl_unittest.cc b/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
index f622ef4..a3b9e05 100644
--- a/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "base/command_line.h"
 #include "base/file_path.h"
@@ -30,6 +32,56 @@
         new ProfileSyncFactoryImpl(profile_.get(), command_line_.get()));
   }
 
+  // Returns the collection of default datatypes.
+  static std::vector<syncable::ModelType> DefaultDatatypes() {
+    std::vector<syncable::ModelType> datatypes;
+    datatypes.push_back(syncable::BOOKMARKS);
+    datatypes.push_back(syncable::PREFERENCES);
+    datatypes.push_back(syncable::AUTOFILL);
+    datatypes.push_back(syncable::THEMES);
+    datatypes.push_back(syncable::EXTENSIONS);
+    datatypes.push_back(syncable::APPS);
+    datatypes.push_back(syncable::AUTOFILL_PROFILE);
+    datatypes.push_back(syncable::PASSWORDS);
+    return datatypes;
+  }
+
+  // Returns the number of default datatypes.
+  static size_t DefaultDatatypesCount() {
+    return DefaultDatatypes().size();
+  }
+
+  // Asserts that all the default datatypes are in |map|, except
+  // for |exception_type|, which unless it is UNDEFINED, is asserted to
+  // not be in |map|.
+  static void CheckDefaultDatatypesInMapExcept(
+      DataTypeController::StateMap* map,
+      syncable::ModelType exception_type) {
+    std::vector<syncable::ModelType> defaults = DefaultDatatypes();
+    std::vector<syncable::ModelType>::iterator iter;
+    for (iter = defaults.begin(); iter != defaults.end(); ++iter) {
+      if (exception_type != syncable::UNSPECIFIED && exception_type == *iter)
+        EXPECT_EQ(0U, map->count(*iter))
+            << *iter << " found in dataypes map, shouldn't be there.";
+      else
+        EXPECT_EQ(1U, map->count(*iter))
+            << *iter << " not found in datatypes map";
+    }
+  }
+
+  // Asserts that if you apply the command line switch |cmd_switch|,
+  // all types are enabled except for |type|, which is disabled.
+  void TestSwitchDisablesType(const char* cmd_switch,
+                              syncable::ModelType type) {
+    command_line_->AppendSwitch(cmd_switch);
+    scoped_ptr<ProfileSyncService> pss(
+        profile_sync_service_factory_->CreateProfileSyncService(""));
+    DataTypeController::StateMap controller_states;
+    pss->GetDataTypeControllerStates(&controller_states);
+    EXPECT_EQ(DefaultDatatypesCount() - 1, controller_states.size());
+    CheckDefaultDatatypesInMapExcept(&controller_states, type);
+  }
+
   MessageLoop message_loop_;
   BrowserThread ui_thread_;
   scoped_ptr<Profile> profile_;
@@ -38,112 +90,50 @@
 };
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDefault) {
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
+  scoped_ptr<ProfileSyncService> pss(
+      profile_sync_service_factory_->CreateProfileSyncService(""));
   DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(6U, controller_states_ptr->size());
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::APPS));
+  pss->GetDataTypeControllerStates(&controller_states);
+  EXPECT_EQ(DefaultDatatypesCount(), controller_states.size());
+  CheckDefaultDatatypesInMapExcept(&controller_states, syncable::UNSPECIFIED);
 }
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableAutofill) {
-  command_line_->AppendSwitch(switches::kDisableSyncAutofill);
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
-  DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(5U, controller_states_ptr->size());
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(0U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::APPS));
+  TestSwitchDisablesType(switches::kDisableSyncAutofill,
+                         syncable::AUTOFILL);
 }
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableBookmarks) {
-  command_line_->AppendSwitch(switches::kDisableSyncBookmarks);
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
-  DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(5U, controller_states_ptr->size());
-  EXPECT_EQ(0U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::APPS));
+  TestSwitchDisablesType(switches::kDisableSyncBookmarks,
+                         syncable::BOOKMARKS);
 }
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisablePreferences) {
-  command_line_->AppendSwitch(switches::kDisableSyncPreferences);
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
-  DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(5U, controller_states_ptr->size());
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(0U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::APPS));
+  TestSwitchDisablesType(switches::kDisableSyncPreferences,
+                         syncable::PREFERENCES);
 }
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableThemes) {
-  command_line_->AppendSwitch(switches::kDisableSyncThemes);
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
-  DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(5U, controller_states_ptr->size());
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(0U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::APPS));
+  TestSwitchDisablesType(switches::kDisableSyncThemes,
+                         syncable::THEMES);
 }
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableExtensions) {
-  command_line_->AppendSwitch(switches::kDisableSyncExtensions);
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
-  DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(5U, controller_states_ptr->size());
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(0U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::APPS));
+  TestSwitchDisablesType(switches::kDisableSyncExtensions,
+                         syncable::EXTENSIONS);
 }
 
 TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableApps) {
-  command_line_->AppendSwitch(switches::kDisableSyncApps);
-  scoped_ptr<ProfileSyncService> pss;
-  pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
-  DataTypeController::StateMap controller_states;
-  DataTypeController::StateMap* controller_states_ptr = &controller_states;
-  pss->GetDataTypeControllerStates(controller_states_ptr);
-  EXPECT_EQ(5U, controller_states_ptr->size());
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::BOOKMARKS));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::PREFERENCES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::AUTOFILL));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::THEMES));
-  EXPECT_EQ(1U, controller_states_ptr->count(syncable::EXTENSIONS));
-  EXPECT_EQ(0U, controller_states_ptr->count(syncable::APPS));
+  TestSwitchDisablesType(switches::kDisableSyncApps,
+                         syncable::APPS);
+}
+
+TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableAutofillProfile) {
+  TestSwitchDisablesType(switches::kDisableSyncAutofillProfile,
+                         syncable::AUTOFILL_PROFILE);
+}
+
+TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisablePasswords) {
+  TestSwitchDisablesType(switches::kDisableSyncPasswords,
+                         syncable::PASSWORDS);
 }
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 852ed4b..0ed4af3 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 #include <map>
 #include <set>
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -18,6 +17,7 @@
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/task.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_signin.h"
 #include "chrome/browser/history/history_types.h"
@@ -30,9 +30,9 @@
 #include "chrome/browser/sync/glue/data_type_controller.h"
 #include "chrome/browser/sync/glue/data_type_manager.h"
 #include "chrome/browser/sync/glue/session_data_type_controller.h"
+#include "chrome/browser/sync/js_arg_list.h"
 #include "chrome/browser/sync/profile_sync_factory.h"
 #include "chrome/browser/sync/signin_manager.h"
-#include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/sync/token_migrator.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/net/gaia/gaia_constants.h"
@@ -45,6 +45,7 @@
 #include "grit/generated_resources.h"
 #include "jingle/notifier/communicator/const_communicator.h"
 #include "net/base/cookie_monster.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using browser_sync::ChangeProcessor;
 using browser_sync::DataTypeController;
@@ -66,17 +67,20 @@
                                        Profile* profile,
                                        const std::string& cros_user)
     : last_auth_error_(AuthError::None()),
+      tried_creating_explicit_passphrase_(false),
+      tried_setting_explicit_passphrase_(false),
       observed_passphrase_required_(false),
       passphrase_required_for_decryption_(false),
+      passphrase_migration_in_progress_(false),
       factory_(factory),
       profile_(profile),
       cros_user_(cros_user),
       sync_service_url_(kDevServerUrl),
       backend_initialized_(false),
       is_auth_in_progress_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)),
+      wizard_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
       unrecoverable_error_detected_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)),
+      scoped_runnable_method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
       token_migrator_(NULL),
       clear_server_data_state_(CLEAR_NOT_STARTED) {
   DCHECK(factory);
@@ -89,9 +93,11 @@
   // Dev servers have more features than standard sync servers.
   // Chrome stable and beta builds will go to the standard sync servers.
 #if defined(GOOGLE_CHROME_BUILD)
+  // GetVersionStringModifier hits the registry. See http://crbug.com/70380.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   // For stable, this is "". For dev, this is "dev". For beta, this is "beta".
   // For daily, this is "canary build".
-  // For linux Chromium builds, this could be anything depending on the
+  // For Linux Chromium builds, this could be anything depending on the
   // distribution, so always direct those users to dev server urls.
   // If this is an official build, it will always be one of the above.
   std::string channel = platform_util::GetVersionStringModifier();
@@ -402,12 +408,6 @@
     return;
   }
 
-  // TODO(chron): Reimplement invalidate XMPP login / Sync login
-  //              command line switches. Perhaps make it a command
-  //              line in the TokenService itself to pass an arbitrary
-  //              token.
-
-
   syncable::ModelTypeSet types;
   // If sync setup hasn't finished, we don't want to initialize routing info
   // for any data types so that we don't download updates for types that the
@@ -418,7 +418,8 @@
 
   SyncCredentials credentials = GetCredentials();
 
-  backend_->Initialize(sync_service_url_,
+  backend_->Initialize(this,
+                       sync_service_url_,
                        types,
                        profile_->GetRequestContext(),
                        credentials,
@@ -427,9 +428,15 @@
 }
 
 void ProfileSyncService::CreateBackend() {
-  backend_.reset(
-      new SyncBackendHost(this, profile_, profile_->GetPath(),
-                          data_type_controllers_));
+  backend_.reset(new SyncBackendHost(profile_));
+}
+
+bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
+  // Currently on passwords are an encrypted datatype, so
+  // we check to see if it is enabled.
+  syncable::ModelTypeSet types;
+  GetPreferredDataTypes(&types);
+  return types.count(syncable::PASSWORDS) != 0;
 }
 
 void ProfileSyncService::StartUp() {
@@ -446,13 +453,6 @@
 
   CreateBackend();
 
-  registrar_.Add(this,
-                 NotificationType::SYNC_PASSPHRASE_REQUIRED,
-                 Source<SyncBackendHost>(backend_.get()));
-  registrar_.Add(this,
-                 NotificationType::SYNC_PASSPHRASE_ACCEPTED,
-                 Source<SyncBackendHost>(backend_.get()));
-
   // Initialize the backend.  Every time we start up a new SyncBackendHost,
   // we'll want to start from a fresh SyncDB, so delete any old one that might
   // be there.
@@ -475,19 +475,14 @@
     data_type_manager_.reset();
   }
 
+  js_event_handlers_.RemoveBackend();
+
   // Move aside the backend so nobody else tries to use it while we are
   // shutting it down.
   scoped_ptr<SyncBackendHost> doomed_backend(backend_.release());
   if (doomed_backend.get()) {
     doomed_backend->Shutdown(sync_disabled);
 
-    registrar_.Remove(this,
-                   NotificationType::SYNC_PASSPHRASE_REQUIRED,
-                   Source<SyncBackendHost>(doomed_backend.get()));
-    registrar_.Remove(this,
-                   NotificationType::SYNC_PASSPHRASE_ACCEPTED,
-                   Source<SyncBackendHost>(doomed_backend.get()));
-
     doomed_backend.reset();
   }
 
@@ -517,7 +512,7 @@
     signin_->SignOut();
   }
 
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 }
 
 bool ProfileSyncService::HasSyncSetupCompleted() const {
@@ -543,6 +538,14 @@
   profile_->GetPrefs()->ScheduleSavePersistentPrefs();
 }
 
+void ProfileSyncService::NotifyObservers() {
+  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  // TODO(akalin): Make an Observer subclass that listens and does the
+  // event routing.
+  js_event_handlers_.RouteJsEvent(
+      "onSyncServiceStateChanged", browser_sync::JsArgList(), NULL);
+}
+
 // static
 const char* ProfileSyncService::GetPrefNameForDataType(
     syncable::ModelType data_type) {
@@ -557,7 +560,6 @@
       return prefs::kSyncAutofill;
     case syncable::AUTOFILL_PROFILE:
       return prefs::kSyncAutofillProfile;
-      break;
     case syncable::THEMES:
       return prefs::kSyncThemes;
     case syncable::TYPED_URLS:
@@ -569,9 +571,10 @@
     case syncable::SESSIONS:
       return prefs::kSyncSessions;
     default:
-      NOTREACHED();
-      return NULL;
+      break;
   }
+  NOTREACHED();
+  return NULL;
 }
 
 // An invariant has been violated.  Transition to an error state where we try
@@ -589,7 +592,7 @@
   // Tell the wizard so it can inform the user only if it is already open.
   wizard_.Step(SyncSetupWizard::FATAL_ERROR);
 
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
   LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable."
       << message;
   std::string location;
@@ -605,13 +608,15 @@
 void ProfileSyncService::OnBackendInitialized() {
   backend_initialized_ = true;
 
+  js_event_handlers_.SetBackend(backend_->GetJsBackend());
+
   // The very first time the backend initializes is effectively the first time
   // we can say we successfully "synced".  last_synced_time_ will only be null
   // in this case, because the pref wasn't restored on StartUp.
   if (last_synced_time_.is_null()) {
     UpdateLastSyncedTime();
   }
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 
   if (!cros_user_.empty()) {
     if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) {
@@ -628,7 +633,7 @@
 
 void ProfileSyncService::OnSyncCycleCompleted() {
   UpdateLastSyncedTime();
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 }
 
 void ProfileSyncService::UpdateAuthErrorState(
@@ -652,7 +657,7 @@
 
   is_auth_in_progress_ = false;
   // Fan the notification out to interested UI-thread components.
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 }
 
 void ProfileSyncService::OnAuthError() {
@@ -672,7 +677,7 @@
   if (clear_server_data_state_ != CLEAR_SUCCEEDED &&
       clear_server_data_state_ != CLEAR_FAILED) {
     clear_server_data_state_ = CLEAR_FAILED;
-    FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+    NotifyObservers();
   }
 }
 
@@ -685,7 +690,7 @@
   if (clear_server_data_state_ != CLEAR_SUCCEEDED &&
       clear_server_data_state_ != CLEAR_FAILED) {
     clear_server_data_state_ = CLEAR_FAILED;
-    FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+    NotifyObservers();
   }
 }
 
@@ -696,10 +701,55 @@
   // we want UI to update itself and no longer allow the user to press "clear"
   if (clear_server_data_state_ != CLEAR_SUCCEEDED) {
     clear_server_data_state_ = CLEAR_SUCCEEDED;
-    FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+    NotifyObservers();
   }
 }
 
+void ProfileSyncService::OnPassphraseRequired(bool for_decryption) {
+  DCHECK(backend_.get());
+  DCHECK(backend_->IsNigoriEnabled());
+  observed_passphrase_required_ = true;
+  passphrase_required_for_decryption_ = for_decryption;
+
+  if (!cached_passphrase_.value.empty()) {
+    SetPassphrase(cached_passphrase_.value,
+                  cached_passphrase_.is_explicit,
+                  cached_passphrase_.is_creation);
+    cached_passphrase_ = CachedPassphrase();
+    return;
+  }
+
+  // We will skip the passphrase prompt and suppress the warning
+  // if the passphrase is needed for decryption but the user is
+  // not syncing an encrypted data type on this machine.
+  // Otherwise we prompt.
+  if (!IsEncryptedDatatypeEnabled() && for_decryption) {
+    OnPassphraseAccepted();
+    return;
+  }
+
+  if (WizardIsVisible()) {
+    wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE);
+  }
+
+  NotifyObservers();
+}
+
+void ProfileSyncService::OnPassphraseAccepted() {
+  // Make sure the data types that depend on the passphrase are started at
+  // this time.
+  syncable::ModelTypeSet types;
+  GetPreferredDataTypes(&types);
+  data_type_manager_->Configure(types);
+
+  NotifyObservers();
+  observed_passphrase_required_ = false;
+  tried_setting_explicit_passphrase_ = false;
+  tried_creating_explicit_passphrase_ = false;
+
+  wizard_.Step(SyncSetupWizard::DONE);
+}
+
 void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) {
   // TODO(johnnyg): File a bug to make sure this doesn't happen.
   if (!cros_user_.empty()) {
@@ -721,9 +771,28 @@
   wizard_.SetParent(parent_window);
   wizard_.Step(SyncSetupWizard::GAIA_LOGIN);
 
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 }
 
+void ProfileSyncService::ShowErrorUI(gfx::NativeWindow parent_window) {
+  if (observed_passphrase_required()) {
+    if (IsUsingSecondaryPassphrase())
+      PromptForExistingPassphrase(parent_window);
+    else
+      SigninForPassphraseMigration(parent_window);
+    return;
+  }
+  const GoogleServiceAuthError& error = GetAuthError();
+  if (error.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
+      error.state() == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
+      error.state() == GoogleServiceAuthError::ACCOUNT_DELETED ||
+      error.state() == GoogleServiceAuthError::ACCOUNT_DISABLED ||
+      error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
+    ShowLoginDialog(parent_window);
+  }
+}
+
+
 void ProfileSyncService::ShowConfigure(gfx::NativeWindow parent_window) {
   if (WizardIsVisible()) {
     wizard_.Focus();
@@ -743,19 +812,10 @@
   wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE);
 }
 
-void ProfileSyncService::ShowPassphraseMigration(
+void ProfileSyncService::SigninForPassphraseMigration(
     gfx::NativeWindow parent_window) {
-  wizard_.SetParent(parent_window);
-  wizard_.Step(SyncSetupWizard::PASSPHRASE_MIGRATION);
-}
-
-void ProfileSyncService::SigninForPassphrase(TabContents* container) {
-  string16 prefilled_username = GetAuthenticatedUsername();
-  string16 login_message = sync_ui_util::GetLoginMessageForEncryption();
-  profile_->GetBrowserSignin()->RequestSignin(container,
-                                              prefilled_username,
-                                              login_message,
-                                              this);
+  passphrase_migration_in_progress_ = true;
+  ShowLoginDialog(parent_window);
 }
 
 SyncBackendHost::StatusSummary ProfileSyncService::QuerySyncStatusSummary() {
@@ -780,24 +840,18 @@
 }
 
 std::string ProfileSyncService::BuildSyncStatusSummaryText(
-  const sync_api::SyncManager::Status::Summary& summary) {
-  switch (summary) {
-    case sync_api::SyncManager::Status::OFFLINE:
-      return "OFFLINE";
-    case sync_api::SyncManager::Status::OFFLINE_UNSYNCED:
-      return "OFFLINE_UNSYNCED";
-    case sync_api::SyncManager::Status::SYNCING:
-      return "SYNCING";
-    case sync_api::SyncManager::Status::READY:
-      return "READY";
-    case sync_api::SyncManager::Status::CONFLICT:
-      return "CONFLICT";
-    case sync_api::SyncManager::Status::OFFLINE_UNUSABLE:
-      return "OFFLINE_UNUSABLE";
-    case sync_api::SyncManager::Status::INVALID:  // fall through
-    default:
-      return "UNKNOWN";
+    const sync_api::SyncManager::Status::Summary& summary) {
+  const char* strings[] = {"INVALID", "OFFLINE", "OFFLINE_UNSYNCED", "SYNCING",
+      "READY", "CONFLICT", "OFFLINE_UNUSABLE"};
+  COMPILE_ASSERT(arraysize(strings) ==
+                 sync_api::SyncManager::Status::SUMMARY_STATUS_COUNT,
+                 enum_indexed_array);
+  if (summary < 0 ||
+      summary >= sync_api::SyncManager::Status::SUMMARY_STATUS_COUNT) {
+    LOG(DFATAL) << "Illegal Summary Value: " << summary;
+    return "UNKNOWN";
   }
+  return strings[summary];
 }
 
 bool ProfileSyncService::unrecoverable_error_detected() const {
@@ -828,7 +882,7 @@
     const std::string& captcha, const std::string& access_code) {
   last_attempted_user_email_ = username;
   is_auth_in_progress_ = true;
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 
   auth_start_time_ = base::TimeTicks::Now();
 
@@ -893,7 +947,7 @@
   // good if invalid creds were provided, but it's an edge case and the user
   // can of course get themselves out of it.
   is_auth_in_progress_ = false;
-  FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+  NotifyObservers();
 }
 
 void ProfileSyncService::ChangePreferredDataTypes(
@@ -980,6 +1034,12 @@
   return backend_.get() && backend_->IsCryptographerReady();
 }
 
+SyncBackendHost* ProfileSyncService::GetBackendForTest() {
+  // We don't check |backend_initialized_|; we assume the test class
+  // knows what it's doing.
+  return backend_.get();
+}
+
 void ProfileSyncService::ConfigureDataTypeManager() {
   if (!data_type_manager_.get()) {
     data_type_manager_.reset(
@@ -998,6 +1058,78 @@
   data_type_manager_->Configure(types);
 }
 
+sync_api::UserShare* ProfileSyncService::GetUserShare() const {
+  if (backend_.get() && backend_initialized_) {
+    return backend_->GetUserShare();
+  }
+  NOTREACHED();
+  return NULL;
+}
+
+const browser_sync::sessions::SyncSessionSnapshot*
+    ProfileSyncService::GetLastSessionSnapshot() const {
+  if (backend_.get() && backend_initialized_) {
+    return backend_->GetLastSessionSnapshot();
+  }
+  NOTREACHED();
+  return NULL;
+}
+
+bool ProfileSyncService::HasUnsyncedItems() const {
+  if (backend_.get() && backend_initialized_) {
+    return backend_->HasUnsyncedItems();
+  }
+  NOTREACHED();
+  return false;
+}
+
+void ProfileSyncService::GetModelSafeRoutingInfo(
+    browser_sync::ModelSafeRoutingInfo* out) {
+  if (backend_.get() && backend_initialized_) {
+    backend_->GetModelSafeRoutingInfo(out);
+  } else {
+    NOTREACHED();
+  }
+}
+
+syncable::AutofillMigrationState
+    ProfileSyncService::GetAutofillMigrationState() {
+  if (backend_.get() && backend_initialized_) {
+    return backend_->GetAutofillMigrationState();
+  }
+  NOTREACHED();
+  return syncable::NOT_DETERMINED;
+}
+
+void ProfileSyncService::SetAutofillMigrationState(
+    syncable::AutofillMigrationState state) {
+  if (backend_.get() && backend_initialized_) {
+    backend_->SetAutofillMigrationState(state);
+  } else {
+    NOTREACHED();
+  }
+}
+
+syncable::AutofillMigrationDebugInfo
+    ProfileSyncService::GetAutofillMigrationDebugInfo() {
+  if (backend_.get() && backend_initialized_) {
+    return backend_->GetAutofillMigrationDebugInfo();
+  }
+  NOTREACHED();
+  syncable::AutofillMigrationDebugInfo debug_info = { 0 };
+  return debug_info;
+}
+
+void ProfileSyncService::SetAutofillMigrationDebugInfo(
+    syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+    const syncable::AutofillMigrationDebugInfo& info) {
+  if (backend_.get() && backend_initialized_) {
+    backend_->SetAutofillMigrationDebugInfo(property_to_set, info);
+  } else {
+    NOTREACHED();
+  }
+}
+
 void ProfileSyncService::ActivateDataType(
     DataTypeController* data_type_controller,
     ChangeProcessor* change_processor) {
@@ -1006,7 +1138,7 @@
     return;
   }
   DCHECK(backend_initialized_);
-  change_processor->Start(profile(), backend_->GetUserShareHandle());
+  change_processor->Start(profile(), backend_->GetUserShare());
   backend_->ActivateDataType(data_type_controller, change_processor);
 }
 
@@ -1019,13 +1151,20 @@
 }
 
 void ProfileSyncService::SetPassphrase(const std::string& passphrase,
-                                       bool is_explicit) {
+                                       bool is_explicit,
+                                       bool is_creation) {
   if (ShouldPushChanges() || observed_passphrase_required_) {
     backend_->SetPassphrase(passphrase, is_explicit);
   } else {
     cached_passphrase_.value = passphrase;
     cached_passphrase_.is_explicit = is_explicit;
+    cached_passphrase_.is_creation = is_creation;
   }
+
+  if (is_explicit && is_creation)
+    tried_creating_explicit_passphrase_ = true;
+  else if (is_explicit)
+    tried_setting_explicit_passphrase_ = true;
 }
 
 void ProfileSyncService::Observe(NotificationType type,
@@ -1033,7 +1172,7 @@
                                  const NotificationDetails& details) {
   switch (type.value) {
     case NotificationType::SYNC_CONFIGURE_START: {
-      FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+      NotifyObservers();
       // TODO(sync): Maybe toast?
       break;
     }
@@ -1053,37 +1192,18 @@
       if (!cached_passphrase_.value.empty()) {
         // Don't hold on to the passphrase in raw form longer than needed.
         SetPassphrase(cached_passphrase_.value,
-                      cached_passphrase_.is_explicit);
+                      cached_passphrase_.is_explicit,
+                      cached_passphrase_.is_creation);
         cached_passphrase_ = CachedPassphrase();
       }
 
       // TODO(sync): Less wizard, more toast.
       if (!observed_passphrase_required_)
         wizard_.Step(SyncSetupWizard::DONE);
-      FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+      NotifyObservers();
 
       break;
     }
-    case NotificationType::SYNC_PASSPHRASE_REQUIRED: {
-      DCHECK(backend_.get());
-      DCHECK(backend_->IsNigoriEnabled());
-      observed_passphrase_required_ = true;
-      passphrase_required_for_decryption_ = *(Details<bool>(details).ptr());
-
-      if (!cached_passphrase_.value.empty()) {
-        SetPassphrase(cached_passphrase_.value,
-                      cached_passphrase_.is_explicit);
-        cached_passphrase_ = CachedPassphrase();
-        break;
-      }
-
-      if (WizardIsVisible()) {
-        wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE);
-      }
-
-      FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-      break;
-    }
     case NotificationType::SYNC_DATA_TYPES_UPDATED: {
       if (!HasSyncSetupCompleted()) break;
 
@@ -1092,23 +1212,10 @@
       OnUserChoseDatatypes(false, types);
       break;
     }
-    case NotificationType::SYNC_PASSPHRASE_ACCEPTED: {
-      // Make sure the data types that depend on the passphrase are started at
-      // this time.
-      syncable::ModelTypeSet types;
-      GetPreferredDataTypes(&types);
-      data_type_manager_->Configure(types);
-
-      FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-      observed_passphrase_required_ = false;
-
-      wizard_.Step(SyncSetupWizard::DONE);
-      break;
-    }
     case NotificationType::PREF_CHANGED: {
       std::string* pref_name = Details<std::string>(details).ptr();
       if (*pref_name == prefs::kSyncManaged) {
-        FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+        NotifyObservers();
         if (*pref_sync_managed_) {
           DisableForUser();
         } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) {
@@ -1126,7 +1233,16 @@
       // actually change), or the user has an explicit passphrase set so this
       // becomes a no-op.
       tried_implicit_gaia_remove_when_bug_62103_fixed_ = true;
-      SetPassphrase(successful->password, false);
+      SetPassphrase(successful->password, false, true);
+
+      // If this signin was to initiate a passphrase migration (on the
+      // first computer, thus not for decryption), continue the migration.
+      if (passphrase_migration_in_progress_ &&
+          !passphrase_required_for_decryption_) {
+        wizard_.Step(SyncSetupWizard::PASSPHRASE_MIGRATION);
+        passphrase_migration_in_progress_ = false;
+      }
+
       break;
     }
     case NotificationType::GOOGLE_SIGNIN_FAILED: {
@@ -1162,27 +1278,6 @@
   }
 }
 
-// This is the delegate callback from BrowserSigin.
-void ProfileSyncService::OnLoginSuccess() {
-  // The reason for the browser signin was a non-explicit passphrase
-  // required signal.  If this is the first time through the passphrase
-  // process, we want to show the migration UI and offer an explicit
-  // passphrase.  Otherwise, we're done because the implicit is enough.
-
-  if (passphrase_required_for_decryption_) {
-    // NOT first time (decrypting something encrypted elsewhere).
-    // Do nothing.
-  } else {
-    ShowPassphraseMigration(NULL);
-  }
-}
-
-// This is the delegate callback from BrowserSigin.
-void ProfileSyncService::OnLoginFailure(const GoogleServiceAuthError& error) {
-  // Do nothing.  The UI will already reflect the fact that the
-  // user is not signed in.
-}
-
 void ProfileSyncService::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
 }
@@ -1195,6 +1290,10 @@
   return observers_.HasObserver(observer);
 }
 
+browser_sync::JsFrontend* ProfileSyncService::GetJsFrontend() {
+  return &js_event_handlers_;
+}
+
 void ProfileSyncService::SyncEvent(SyncEventCodes code) {
   UMA_HISTOGRAM_ENUMERATION("Sync.EventCodes", code, MAX_SYNC_EVENT_CODE);
 }
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 62a8e07..ec9ce6b 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -15,13 +15,13 @@
 #include "base/string16.h"
 #include "base/time.h"
 #include "base/timer.h"
-#include "chrome/browser/browser_signin.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/glue/data_type_controller.h"
 #include "chrome/browser/sync/glue/data_type_manager.h"
 #include "chrome/browser/sync/glue/session_model_associator.h"
 #include "chrome/browser/sync/glue/sync_backend_host.h"
+#include "chrome/browser/sync/js_event_handler_list.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/sync/signin_manager.h"
 #include "chrome/browser/sync/sync_setup_wizard.h"
@@ -41,6 +41,10 @@
 class TabContents;
 class TokenMigrator;
 
+namespace browser_sync {
+class JsFrontend;
+}  // namespace browser_sync
+
 // ProfileSyncService is the layer between browser subsystems like bookmarks,
 // and the sync backend.  Each subsystem is logically thought of as being
 // a sync datatype.
@@ -85,7 +89,6 @@
 //
 class ProfileSyncService : public browser_sync::SyncFrontend,
                            public browser_sync::UnrecoverableErrorHandler,
-                           public BrowserSignin::SigninDelegate,
                            public NotificationObserver {
  public:
   typedef ProfileSyncServiceObserver Observer;
@@ -185,6 +188,8 @@
   virtual void OnClearServerDataFailed();
   virtual void OnClearServerDataTimeout();
   virtual void OnClearServerDataSucceeded();
+  virtual void OnPassphraseRequired(bool for_decryption);
+  virtual void OnPassphraseAccepted();
 
   // Called when a user enters credentials through UI.
   virtual void OnUserSubmittedAuth(const std::string& username,
@@ -225,10 +230,14 @@
     return wizard_.IsVisible();
   }
   virtual void ShowLoginDialog(gfx::NativeWindow parent_window);
+
+  // This method handles clicks on "sync error" UI, showing the appropriate
+  // dialog for the error condition (relogin / enter passphrase).
+  virtual void ShowErrorUI(gfx::NativeWindow parent_window);
+
   void ShowConfigure(gfx::NativeWindow parent_window);
   void PromptForExistingPassphrase(gfx::NativeWindow parent_window);
-  void SigninForPassphrase(TabContents* container);
-  void ShowPassphraseMigration(gfx::NativeWindow parent_window);
+  void SigninForPassphraseMigration(gfx::NativeWindow parent_window);
 
   // Pretty-printed strings for a given StatusSummary.
   static std::string BuildSyncStatusSummaryText(
@@ -256,6 +265,14 @@
     return is_auth_in_progress_;
   }
 
+  bool tried_creating_explicit_passphrase() const {
+    return tried_creating_explicit_passphrase_;
+  }
+
+  bool tried_setting_explicit_passphrase() const {
+    return tried_setting_explicit_passphrase_;
+  }
+
   bool observed_passphrase_required() const {
     return observed_passphrase_required_;
   }
@@ -294,6 +311,11 @@
   // Returns true if |observer| has already been added as an observer.
   bool HasObserver(Observer* observer) const;
 
+  // Returns a pointer to the service's JsFrontend (which is owned by
+  // the service).  Never returns NULL.  Overrideable for testing
+  // purposes.
+  virtual browser_sync::JsFrontend* GetJsFrontend();
+
   // Record stats on various events.
   static void SyncEvent(SyncEventCodes code);
 
@@ -311,7 +333,52 @@
       const tracked_objects::Location& from_here,
       const std::string& message);
 
-  browser_sync::SyncBackendHost* backend() { return backend_.get(); }
+  // The functions below (until ActivateDataType()) should only be
+  // called if sync_initialized() is true.
+
+  // TODO(akalin): This is called mostly by ModelAssociators and
+  // tests.  Figure out how to pass the handle to the ModelAssociators
+  // directly, figure out how to expose this to tests, and remove this
+  // function.
+  sync_api::UserShare* GetUserShare() const;
+
+  // TODO(akalin): These two functions are used only by
+  // ProfileSyncServiceHarness.  Figure out a different way to expose
+  // this info to that class, and remove these functions.
+
+  const browser_sync::sessions::SyncSessionSnapshot*
+      GetLastSessionSnapshot() const;
+
+  // Returns whether or not the underlying sync engine has made any
+  // local changes to items that have not yet been synced with the
+  // server.
+  bool HasUnsyncedItems() const;
+
+  // Get the current routing information for all enabled model types.
+  // If a model type is not enabled (that is, if the syncer should not
+  // be trying to sync it), it is not in this map.
+  //
+  // TODO(akalin): This function is used by
+  // sync_ui_util::ConstructAboutInformation() and by some test
+  // classes.  Figure out a different way to expose this info and
+  // remove this function.
+  void GetModelSafeRoutingInfo(browser_sync::ModelSafeRoutingInfo* out);
+
+  // TODO(akalin): Remove these four functions once we're done with
+  // autofill migration.
+
+  syncable::AutofillMigrationState
+      GetAutofillMigrationState();
+
+  void SetAutofillMigrationState(
+      syncable::AutofillMigrationState state);
+
+  syncable::AutofillMigrationDebugInfo
+      GetAutofillMigrationDebugInfo();
+
+  void SetAutofillMigrationDebugInfo(
+      syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+      const syncable::AutofillMigrationDebugInfo& info);
 
   virtual void ActivateDataType(
       browser_sync::DataTypeController* data_type_controller,
@@ -325,10 +392,6 @@
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
-  // BrowserSignin::SigninDelegate interface.
-  virtual void OnLoginSuccess();
-  virtual void OnLoginFailure(const GoogleServiceAuthError& error);
-
   // Changes which data types we're going to be syncing to |preferred_types|.
   // If it is running, the DataTypeManager will be instructed to reconfigure
   // the sync backend so that exactly these datatypes are actively synced.  See
@@ -364,7 +427,12 @@
   // setting a passphrase as opposed to implicitly (from the users' perspective)
   // using their Google Account password.  An implicit SetPassphrase will *not*
   // *not* override an explicit passphrase set previously.
-  virtual void SetPassphrase(const std::string& passphrase, bool is_explicit);
+  // |is_creation| is true if the call is in response to the user setting
+  // up a new passphrase, and false if it's being set in response to a prompt
+  // for an existing passphrase.
+  virtual void SetPassphrase(const std::string& passphrase,
+                             bool is_explicit,
+                             bool is_creation);
 
   // Returns whether processing changes is allowed.  Check this before doing
   // any model-modifying operations.
@@ -382,6 +450,9 @@
   // so we don't need this hack anymore.
   ProfileSyncService();
 
+  // Used by test classes that derive from ProfileSyncService.
+  virtual browser_sync::SyncBackendHost* GetBackendForTest();
+
   // Helper to install and configure a data type manager.
   void ConfigureDataTypeManager();
 
@@ -400,12 +471,19 @@
 
   // Test need to override this to create backends that allow setting up
   // initial conditions, such as populating sync nodes.
+  //
+  // TODO(akalin): Figure out a better way to do this.  Ideally, we'd
+  // construct the backend outside this class and pass it in to the
+  // contructor or Initialize().
   virtual void CreateBackend();
 
   const browser_sync::DataTypeController::TypeMap& data_type_controllers() {
     return data_type_controllers_;
   }
 
+  // Helper method for managing encryption UI.
+  bool IsEncryptedDatatypeEnabled() const;
+
   // The wizard will try to read the auth state out of the profile sync
   // service using this member. Captcha and error state are reflected.
   GoogleServiceAuthError last_auth_error_;
@@ -417,6 +495,14 @@
   // Cache of the last name the client attempted to authenticate.
   std::string last_attempted_user_email_;
 
+  // Whether the user has tried creating an explicit passphrase on this
+  // machine.
+  bool tried_creating_explicit_passphrase_;
+
+  // Whether the user has tried setting an explicit passphrase on this
+  // machine.
+  bool tried_setting_explicit_passphrase_;
+
   // Whether we have seen a SYNC_PASSPHRASE_REQUIRED since initializing the
   // backend, telling us that it is safe to send a passphrase down ASAP.
   bool observed_passphrase_required_;
@@ -425,14 +511,13 @@
   // was required for decryption?
   bool passphrase_required_for_decryption_;
 
+  // Is the user in a passphrase migration?
+  bool passphrase_migration_in_progress_;
+
  private:
-  friend class ProfileSyncServiceTest;
   friend class ProfileSyncServicePasswordTest;
-  friend class ProfileSyncServicePreferenceTest;
-  friend class ProfileSyncServiceSessionTest;
+  friend class TestProfileSyncService;
   FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceTest, InitialState);
-  FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceTest,
-                           UnrecoverableErrorSuspendsService);
 
   // If |delete_sync_data_folder| is true, then this method will delete all
   // previous "Sync Data" folders. (useful if the folder is partial/corrupt).
@@ -444,6 +529,8 @@
   // Sets the last synced time to the current time.
   void UpdateLastSyncedTime();
 
+  void NotifyObservers();
+
   static const char* GetPrefNameForDataType(syncable::ModelType data_type);
 
   // Time at which we begin an attempt a GAIA authorization.
@@ -504,6 +591,8 @@
 
   ObserverList<Observer> observers_;
 
+  browser_sync::JsEventHandlerList js_event_handlers_;
+
   NotificationRegistrar registrar_;
 
   ScopedRunnableMethodFactory<ProfileSyncService>
@@ -527,7 +616,8 @@
   struct CachedPassphrase {
     std::string value;
     bool is_explicit;
-    CachedPassphrase() : is_explicit(false) {}
+    bool is_creation;
+    CachedPassphrase() : is_explicit(false), is_creation(false) {}
   };
   CachedPassphrase cached_passphrase_;
 
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 025c573..808a744 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -24,10 +24,8 @@
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/engine/syncer_util.h"
 #include "chrome/browser/sync/glue/autofill_change_processor.h"
-#include "chrome/browser/sync/glue/autofill_change_processor2.h"
 #include "chrome/browser/sync/glue/autofill_data_type_controller.h"
 #include "chrome/browser/sync/glue/autofill_model_associator.h"
-#include "chrome/browser/sync/glue/autofill_model_associator2.h"
 #include "chrome/browser/sync/glue/autofill_profile_change_processor.h"
 #include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h"
 #include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
@@ -37,6 +35,7 @@
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
 #include "chrome/browser/sync/syncable/autofill_migration.h"
+#include "chrome/browser/sync/syncable/directory_manager.h"
 #include "chrome/browser/sync/syncable/syncable.h"
 #include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/sync/test_profile_sync_service.h"
@@ -53,10 +52,8 @@
 using base::Time;
 using base::WaitableEvent;
 using browser_sync::AutofillChangeProcessor;
-using browser_sync::AutofillChangeProcessor2;
 using browser_sync::AutofillDataTypeController;
 using browser_sync::AutofillModelAssociator;
-using browser_sync::AutofillModelAssociator2;
 using browser_sync::AutofillProfileChangeProcessor;
 using browser_sync::AutofillProfileDataTypeController;
 using browser_sync::AutofillProfileModelAssociator;
@@ -68,12 +65,17 @@
 using browser_sync::UnrecoverableErrorHandler;
 using syncable::CREATE_NEW_UPDATE_ITEM;
 using syncable::AUTOFILL;
+using syncable::BASE_VERSION;
+using syncable::CREATE;
 using syncable::DirectoryChangeEvent;
 using syncable::GET_BY_SERVER_TAG;
 using syncable::INVALID;
+using syncable::MutableEntry;
+using syncable::OriginalEntries;
 using syncable::SERVER_PARENT_ID;
 using syncable::SERVER_SPECIFICS;
-using syncable::OriginalEntries;
+using syncable::SPECIFICS;
+using syncable::UNITTEST;
 using syncable::WriterTag;
 using syncable::WriteTransaction;
 using testing::_;
@@ -110,7 +112,7 @@
   MOCK_METHOD1(AddAutoFillProfile,
                bool(const AutoFillProfile&));  // NOLINT
   MOCK_METHOD1(RemoveAutoFillProfile,
-               bool(const string&));  // NOLINT
+               bool(const std::string&));  // NOLINT
 };
 
 class ProfileSyncServiceAutofillTest;
@@ -318,8 +320,7 @@
   }
 
   bool AddAutofillSyncNode(const AutofillEntry& entry) {
-    sync_api::WriteTransaction trans(
-        service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     sync_api::ReadNode autofill_root(&trans);
     if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
       return false;
@@ -335,8 +336,7 @@
   }
 
   bool AddAutofillSyncNode(const AutoFillProfile& profile) {
-    sync_api::WriteTransaction trans(
-        service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     sync_api::ReadNode autofill_root(&trans);
     if (!autofill_root.InitByTagLookup(browser_sync::kAutofillProfileTag))
       return false;
@@ -351,7 +351,7 @@
 
   bool GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries,
                                     std::vector<AutoFillProfile>* profiles) {
-    sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     sync_api::ReadNode autofill_root(&trans);
     if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
       return false;
@@ -388,7 +388,7 @@
 
   bool GetAutofillProfilesFromSyncDBUnderProfileNode(
       std::vector<AutoFillProfile>* profiles) {
-    sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     sync_api::ReadNode autofill_root(&trans);
     if (!autofill_root.InitByTagLookup(browser_sync::kAutofillProfileTag))
       return false;
@@ -478,7 +478,7 @@
 static const bool kLoggingInfo = true;
 class WriteTransactionTest: public WriteTransaction {
  public:
-  WriteTransactionTest(const ScopedDirLookup& directory,
+  WriteTransactionTest(const syncable::ScopedDirLookup& directory,
                        WriterTag writer, const char* source_file,
                        int line,
                        scoped_ptr<WaitableEvent> *wait_for_syncapi)
@@ -514,9 +514,9 @@
     // This gets called in a modelsafeworker thread.
     ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::DB));
 
-    UserShare* user_share = service_->backend()->GetUserShareHandle();
-    DirectoryManager* dir_manager = user_share->dir_manager.get();
-    ScopedDirLookup dir(dir_manager, user_share->name);
+    sync_api::UserShare* user_share = service_->GetUserShare();
+    syncable::DirectoryManager* dir_manager = user_share->dir_manager.get();
+    syncable::ScopedDirLookup dir(dir_manager, user_share->name);
     ASSERT_TRUE(dir.good());
 
     // Create autofill protobuf
@@ -551,7 +551,7 @@
       item.Put(SPECIFICS, entity_specifics);
       item.Put(SERVER_SPECIFICS, entity_specifics);
       item.Put(BASE_VERSION, 1);
-      syncable::Id server_parent_id = ids_.NewServerId();
+      syncable::Id server_parent_id = service_->id_factory()->NewServerId();
       item.Put(syncable::ID, server_parent_id);
       syncable::Id new_predecessor =
           SyncerUtil::ComputePrevIdFromServerPosition(&trans, &item,
@@ -567,7 +567,7 @@
     scoped_ptr<Callback0::Type> c(NewCallback((FakeServerUpdater *)this,
                                               &FakeServerUpdater::Update));
     std::vector<browser_sync::ModelSafeWorker*> workers;
-    service_->backend()->GetWorkers(&workers);
+    service_->GetBackendForTest()->GetWorkers(&workers);
 
     ASSERT_FALSE(BrowserThread::CurrentlyOn(BrowserThread::DB));
     if (!BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
@@ -582,7 +582,7 @@
     scoped_ptr<Callback0::Type> c(NewCallback((FakeServerUpdater *)this,
                                               &FakeServerUpdater::Update));
     std::vector<browser_sync::ModelSafeWorker*> workers;
-    service_->backend()->GetWorkers(&workers);
+    service_->GetBackendForTest()->GetWorkers(&workers);
 
     ASSERT_FALSE(BrowserThread::CurrentlyOn(BrowserThread::DB));
     is_finished_.Reset();
@@ -604,7 +604,6 @@
   scoped_ptr<WaitableEvent> *wait_for_syncapi_;
   WaitableEvent is_finished_;
   syncable::Id parent_id_;
-  TestIdFactory ids_;
 };
 
 // TODO(skrul): Test abort startup.
@@ -810,7 +809,7 @@
       "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
       "91601", "US", "12345678910", "01987654321");
 
-  string native_guid = "{EDC609ED-7EEE-4f27-B00C-423242A9C44B}";
+  std::string native_guid = "{EDC609ED-7EEE-4f27-B00C-423242A9C44B}";
   AutoFillProfile* native_profile = new AutoFillProfile;
   autofill_test::SetProfileInfoWithGuid(native_profile,
       native_guid.c_str(), "Billing",
diff --git a/chrome/browser/sync/profile_sync_service_harness.cc b/chrome/browser/sync/profile_sync_service_harness.cc
index 14fba6e..95eaff1 100644
--- a/chrome/browser/sync/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/profile_sync_service_harness.cc
@@ -8,23 +8,16 @@
 #include <vector>
 
 #include "base/message_loop.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/net/gaia/token_service.h"
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/sessions/session_state.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/common/net/gaia/gaia_constants.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "chrome/common/notification_source.h"
-#include "chrome/common/pref_names.h"
-
-// The default value for min_timestamp_needed_ when we're not in the
-// WAITING_FOR_UPDATES state.
-static const int kMinTimestampNeededNone = -1;
 
 // The amount of time for which we wait for a live sync operation to complete.
-static const int kLiveSyncOperationTimeoutMs = 30000;
+static const int kLiveSyncOperationTimeoutMs = 45000;
 
 // Simple class to implement a timeout using PostDelayedTask.  If it is not
 // aborted before picked up by a message queue, then it asserts with the message
@@ -137,7 +130,7 @@
 bool ProfileSyncServiceHarness::SetupSync(
     const syncable::ModelTypeSet& synced_datatypes) {
   // Initialize the sync client's profile sync service object.
-  service_ = profile_->GetProfileSyncService();
+  service_ = profile_->GetProfileSyncService("");
   if (service_ == NULL) {
     LOG(ERROR) << "SetupSync(): service_ is null.";
     return false;
@@ -260,7 +253,6 @@
         }
         break;
       }
-      GetUpdatedTimestamp();
       SignalStateCompleteWithNextState(FULLY_SYNCED);
       break;
     }
@@ -349,7 +341,6 @@
     }
   } else {
     // Client is already synced; don't wait.
-    GetUpdatedTimestamp();
     return true;
   }
 }
@@ -456,7 +447,7 @@
           snap->num_conflicting_updates == 0 &&  // We can decrypt everything.
           ServiceIsPushingChanges() &&
           GetStatus().notifications_enabled &&
-          !service()->backend()->HasUnsyncedItems() &&
+          !service()->HasUnsyncedItems() &&
           !snap->has_more_to_sync &&
           snap->unsynced_count == 0);
 }
@@ -475,18 +466,22 @@
                         other_types.end(),
                         inserter(intersection_types,
                                  intersection_types.begin()));
-  if (intersection_types.empty()) {
-    return true;
+  for (syncable::ModelTypeSet::iterator i = intersection_types.begin();
+       i != intersection_types.end();
+       ++i) {
+    if (!partner->IsSynced() ||
+        partner->GetUpdatedTimestamp(*i) != GetUpdatedTimestamp(*i)) {
+      return false;
+    }
   }
-  return partner->IsSynced() &&
-      partner->GetUpdatedTimestamp() == GetUpdatedTimestamp();
+  return true;
 }
 
 const SyncSessionSnapshot*
     ProfileSyncServiceHarness::GetLastSessionSnapshot() const {
   DCHECK(service_ != NULL) << "Sync service has not yet been set up.";
-  if (service_->backend()) {
-    return service_->backend()->GetLastSessionSnapshot();
+  if (service_->sync_initialized()) {
+    return service_->GetLastSessionSnapshot();
   }
   return NULL;
 }
@@ -569,10 +564,11 @@
              "Client " << id_;
 }
 
-int64 ProfileSyncServiceHarness::GetUpdatedTimestamp() {
+std::string ProfileSyncServiceHarness::GetUpdatedTimestamp(
+    syncable::ModelType model_type) {
   const SyncSessionSnapshot* snap = GetLastSessionSnapshot();
   DCHECK(snap != NULL) << "GetUpdatedTimestamp(): Sync snapshot is NULL.";
-  return snap->max_local_timestamp;
+  return snap->download_progress_markers[model_type];
 }
 
 void ProfileSyncServiceHarness::LogClientInfo(std::string message) {
@@ -580,12 +576,13 @@
     const SyncSessionSnapshot* snap = GetLastSessionSnapshot();
     if (snap) {
       VLOG(1) << "Client " << id_ << ": " << message
-              << ": max_local_timestamp: " << snap->max_local_timestamp
+              << ": num_updates_downloaded : "
+              << snap->syncer_status.num_updates_downloaded_total
               << ", has_more_to_sync: " << snap->has_more_to_sync
               << ", unsynced_count: " << snap->unsynced_count
               << ", num_conflicting_updates: " << snap->num_conflicting_updates
               << ", has_unsynced_items: "
-              << service()->backend()->HasUnsyncedItems()
+              << service()->HasUnsyncedItems()
               << ", observed_passphrase_required: "
               << service()->observed_passphrase_required()
               << ", notifications_enabled: "
diff --git a/chrome/browser/sync/profile_sync_service_harness.h b/chrome/browser/sync/profile_sync_service_harness.h
index 064afe1..ddbfbe2 100644
--- a/chrome/browser/sync/profile_sync_service_harness.h
+++ b/chrome/browser/sync/profile_sync_service_harness.h
@@ -175,8 +175,9 @@
   // Logs message with relevant info about client's sync state (if available).
   void LogClientInfo(std::string message);
 
-  // Gets the current progress indicator of the current sync session.
-  int64 GetUpdatedTimestamp();
+  // Gets the current progress indicator of the current sync session
+  // for a particular datatype.
+  std::string GetUpdatedTimestamp(syncable::ModelType model_type);
 
   WaitState wait_state_;
 
diff --git a/chrome/browser/sync/profile_sync_service_mock.cc b/chrome/browser/sync/profile_sync_service_mock.cc
index 8bfdb10..99e9ede 100644
--- a/chrome/browser/sync/profile_sync_service_mock.cc
+++ b/chrome/browser/sync/profile_sync_service_mock.cc
@@ -3,7 +3,10 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/sync/profile_sync_service_mock.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/common/url_constants.h"
 
 ProfileSyncServiceMock::ProfileSyncServiceMock() {}
 
-ProfileSyncServiceMock::~ProfileSyncServiceMock() {}
+ProfileSyncServiceMock::~ProfileSyncServiceMock() {
+}
diff --git a/chrome/browser/sync/profile_sync_service_mock.h b/chrome/browser/sync/profile_sync_service_mock.h
index 32bff66..0727ebe 100644
--- a/chrome/browser/sync/profile_sync_service_mock.h
+++ b/chrome/browser/sync/profile_sync_service_mock.h
@@ -24,10 +24,11 @@
   MOCK_METHOD0(OnBackendInitialized, void());
   MOCK_METHOD0(OnSyncCycleCompleted, void());
   MOCK_METHOD0(OnAuthError, void());
-  MOCK_METHOD3(OnUserSubmittedAuth,
+  MOCK_METHOD4(OnUserSubmittedAuth,
                void(const std::string& username,
                     const std::string& password,
-                    const std::string& captcha));
+                    const std::string& captcha,
+                    const std::string& access_code));
   MOCK_METHOD0(OnUserCancelledDialog, void());
   MOCK_CONST_METHOD0(GetAuthenticatedUsername, string16());
   MOCK_METHOD2(OnUnrecoverableError,
@@ -43,6 +44,7 @@
   MOCK_METHOD0(InitializeBackend, void());
   MOCK_METHOD1(AddObserver, void(Observer*));
   MOCK_METHOD1(RemoveObserver, void(Observer*));
+  MOCK_METHOD0(GetJsFrontend, browser_sync::JsFrontend*());
   MOCK_CONST_METHOD0(HasSyncSetupCompleted, bool());
 
   MOCK_METHOD1(ChangePreferredDataTypes,
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index dfb172b..080e600 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -10,12 +10,12 @@
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/sync/abstract_profile_sync_service_test.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/glue/password_change_processor.h"
 #include "chrome/browser/sync/glue/password_data_type_controller.h"
 #include "chrome/browser/sync/glue/password_model_associator.h"
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
 #include "chrome/browser/sync/profile_sync_factory.h"
 #include "chrome/browser/sync/profile_sync_factory_mock.h"
 #include "chrome/browser/sync/profile_sync_service.h"
@@ -38,7 +38,6 @@
 using browser_sync::PasswordChangeProcessor;
 using browser_sync::PasswordDataTypeController;
 using browser_sync::PasswordModelAssociator;
-using browser_sync::SyncBackendHostMock;
 using browser_sync::TestIdFactory;
 using browser_sync::UnrecoverableErrorHandler;
 using sync_api::SyncManager;
@@ -101,6 +100,38 @@
       bool(std::vector<PasswordForm*>*));
 };
 
+class PasswordTestProfileSyncService : public TestProfileSyncService {
+ public:
+  PasswordTestProfileSyncService(ProfileSyncFactory* factory,
+                                 Profile* profile,
+                                 const std::string& test_user,
+                                 bool synchronous_backend_initialization,
+                                 Task* initial_condition_setup_task,
+                                 Task* passphrase_accept_task)
+      : TestProfileSyncService(factory, profile, test_user,
+                               synchronous_backend_initialization,
+                               initial_condition_setup_task),
+        passphrase_accept_task_(passphrase_accept_task) {}
+
+  virtual ~PasswordTestProfileSyncService() {}
+
+  virtual void OnPassphraseRequired(bool for_decryption) {
+    TestProfileSyncService::OnPassphraseRequired(for_decryption);
+    ADD_FAILURE();
+  }
+
+  virtual void OnPassphraseAccepted() {
+    TestProfileSyncService::OnPassphraseAccepted();
+
+    if (passphrase_accept_task_) {
+      passphrase_accept_task_->Run();
+    }
+  }
+
+ private:
+  Task* passphrase_accept_task_;
+};
+
 class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
  protected:
   ProfileSyncServicePasswordTest()
@@ -114,16 +145,8 @@
     notification_service_ = new ThreadNotificationService(&db_thread_);
     notification_service_->Init();
     registrar_.Add(&observer_,
-        NotificationType::SYNC_PASSPHRASE_ACCEPTED,
-        NotificationService::AllSources());
-    registrar_.Add(&observer_,
         NotificationType::SYNC_CONFIGURE_DONE,
         NotificationService::AllSources());
-
-    // We shouldn't ever get this. Gmock will complain if we do.
-    registrar_.Add(&observer_,
-        NotificationType::SYNC_PASSPHRASE_REQUIRED,
-        NotificationService::AllSources());
   }
 
   virtual void TearDown() {
@@ -141,8 +164,8 @@
                         int num_resume_expectations,
                         int num_pause_expectations) {
     if (!service_.get()) {
-      service_.reset(new TestProfileSyncService(&factory_, &profile_,
-                                                "test_user", false, root_task));
+      service_.reset(new PasswordTestProfileSyncService(
+          &factory_, &profile_, "test_user", false, root_task, node_task));
       service_->RegisterPreferences();
       profile_.GetPrefs()->SetBoolean(prefs::kSyncPasswords, true);
       service_->set_num_expected_resumes(num_resume_expectations);
@@ -166,15 +189,8 @@
       EXPECT_CALL(profile_, GetTokenService()).
           WillRepeatedly(Return(&token_service_));
 
-      // Creating model safe workers will request the history service and
-      // password store.  I couldn't manage to convince gmock that splitting up
-      // the expectations to match the class responsibilities was a good thing,
-      // so we set them all together here.
-      EXPECT_CALL(profile_, GetHistoryService(_)).
-         WillOnce(Return(static_cast<HistoryService*>(NULL)));
-
       EXPECT_CALL(profile_, GetPasswordStore(_)).
-          Times(2).
+          Times(3).
           WillRepeatedly(Return(password_store_.get()));
 
       EXPECT_CALL(observer_,
@@ -185,28 +201,19 @@
       service_->Initialize();
       MessageLoop::current()->Run();
 
-      // Only set the passphrase if we actually created the password and nigori
-      // root nodes.
-      if (root_task) {
-        EXPECT_CALL(observer_,
-            Observe(
-                NotificationType(NotificationType::SYNC_PASSPHRASE_ACCEPTED),
-                    _,_)).
-            WillOnce(InvokeTask(node_task));
-        EXPECT_CALL(observer_,
-            Observe(
-                NotificationType(NotificationType::SYNC_CONFIGURE_DONE),
-                    _,_)).
-            WillOnce(QuitUIMessageLoop());
-        service_->SetPassphrase("foo", false);
-        MessageLoop::current()->Run();
-      }
+      EXPECT_CALL(
+          observer_,
+          Observe(
+              NotificationType(NotificationType::SYNC_CONFIGURE_DONE),
+              _,_)).
+          WillOnce(QuitUIMessageLoop());
+      service_->SetPassphrase("foo", false, true);
+      MessageLoop::current()->Run();
     }
   }
 
   void AddPasswordSyncNode(const PasswordForm& entry) {
-    sync_api::WriteTransaction trans(
-        service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     sync_api::ReadNode password_root(&trans);
     ASSERT_TRUE(password_root.InitByTagLookup(browser_sync::kPasswordTag));
 
@@ -219,7 +226,7 @@
   }
 
   void GetPasswordEntriesFromSyncDB(std::vector<PasswordForm>* entries) {
-    sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     sync_api::ReadNode password_root(&trans);
     ASSERT_TRUE(password_root.InitByTagLookup(browser_sync::kPasswordTag));
 
@@ -270,22 +277,6 @@
   scoped_refptr<MockPasswordStore> password_store_;
   NotificationRegistrar registrar_;
 
-  TestIdFactory ids_;
-};
-
-class CreatePasswordRootTask : public Task {
- public:
-  explicit CreatePasswordRootTask(AbstractProfileSyncServiceTest* test)
-      : test_(test) {
-  }
-
-  virtual void Run() {
-    test_->CreateRoot(syncable::NIGORI);
-    test_->CreateRoot(syncable::PASSWORDS);
-  }
-
- private:
-  AbstractProfileSyncServiceTest* test_;
 };
 
 class AddPasswordEntriesTask : public Task {
@@ -307,10 +298,7 @@
 };
 
 TEST_F(ProfileSyncServicePasswordTest, FailModelAssociation) {
-  // Create the nigori root node so that password model association is
-  // attempted, but not the password root node so that it fails.
-  CreateRootTask task(this, syncable::NIGORI);
-  StartSyncService(&task, NULL, 1, 2);
+  StartSyncService(NULL, NULL, 1, 2);
   EXPECT_TRUE(service_->unrecoverable_error_detected());
 }
 
@@ -320,7 +308,7 @@
   EXPECT_CALL(*password_store_, FillBlacklistLogins(_))
       .WillOnce(Return(true));
   SetIdleChangeProcessorExpectations();
-  CreatePasswordRootTask task(this);
+  CreateRootTask task(this, syncable::PASSWORDS);
   StartSyncService(&task, NULL);
   std::vector<PasswordForm> sync_entries;
   GetPasswordEntriesFromSyncDB(&sync_entries);
@@ -350,7 +338,7 @@
   EXPECT_CALL(*password_store_, FillBlacklistLogins(_))
       .WillOnce(Return(true));
   SetIdleChangeProcessorExpectations();
-  CreatePasswordRootTask task(this);
+  CreateRootTask task(this, syncable::PASSWORDS);
   StartSyncService(&task, NULL);
   std::vector<PasswordForm> sync_forms;
   GetPasswordEntriesFromSyncDB(&sync_forms);
@@ -402,7 +390,7 @@
   EXPECT_CALL(*password_store_, FillBlacklistLogins(_))
       .WillOnce(Return(true));
   SetIdleChangeProcessorExpectations();
-  CreatePasswordRootTask task(this);
+  CreateRootTask task(this, syncable::PASSWORDS);
   StartSyncService(&task, NULL);
   std::vector<PasswordForm> sync_forms;
   GetPasswordEntriesFromSyncDB(&sync_forms);
@@ -457,7 +445,7 @@
   EXPECT_CALL(*password_store_, FillBlacklistLogins(_)).WillOnce(Return(true));
   EXPECT_CALL(*password_store_, AddLoginImpl(_)).Times(1);
 
-  CreatePasswordRootTask root_task(this);
+  CreateRootTask root_task(this, syncable::PASSWORDS);
   AddPasswordEntriesTask node_task(this, sync_forms);
   StartSyncService(&root_task, &node_task);
 
@@ -530,7 +518,7 @@
   EXPECT_CALL(*password_store_, FillBlacklistLogins(_)).WillOnce(Return(true));
   EXPECT_CALL(*password_store_, UpdateLoginImpl(_)).Times(1);
 
-  CreatePasswordRootTask root_task(this);
+  CreateRootTask root_task(this, syncable::PASSWORDS);
   AddPasswordEntriesTask node_task(this, sync_forms);
 
   StartSyncService(&root_task, &node_task);
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index e1f3299..8c44e17 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -95,8 +95,6 @@
     return true;
   }
 
-  SyncBackendHost* backend() { return service_->backend_.get(); }
-
   const Value& GetPreferenceValue(const std::string& name) {
     const PrefService::Preference* preference =
         prefs_->FindPreference(name.c_str());
@@ -105,7 +103,7 @@
 
   // Caller gets ownership of the returned value.
   const Value* GetSyncedValue(const std::string& name) {
-    sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     sync_api::ReadNode node(&trans);
 
     int64 node_id = model_associator_->GetSyncIdFromChromeId(name);
@@ -130,7 +128,7 @@
   }
 
   int64 SetSyncedValue(const std::string& name, const Value& value) {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     sync_api::ReadNode root(&trans);
     if (!root.InitByTagLookup(browser_sync::kPreferencesTag))
       return sync_api::kInvalidId;
@@ -219,7 +217,7 @@
 
   const PrefService::Preference* pref =
       prefs_->FindPreference(prefs::kHomePage);
-  sync_api::WriteTransaction trans(service_->backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(service_->GetUserShare());
   sync_api::WriteNode node(&trans);
   EXPECT_TRUE(node.InitByClientTagLookup(syncable::PREFERENCES,
                                          prefs::kHomePage));
@@ -362,7 +360,7 @@
   record->action = SyncManager::ChangeRecord::ACTION_UPDATE;
   record->id = node_id;
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
 
@@ -382,7 +380,7 @@
   record->action = SyncManager::ChangeRecord::ACTION_ADD;
   record->id = node_id;
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
 
@@ -404,7 +402,7 @@
   record->action = SyncManager::ChangeRecord::ACTION_ADD;
   record->id = node_id;
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
 
@@ -437,7 +435,7 @@
   record->action = SyncManager::ChangeRecord::ACTION_UPDATE;
   record->id = node_id;
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
   EXPECT_TRUE(managed_value->Equals(
@@ -476,7 +474,7 @@
   record->action = SyncManager::ChangeRecord::ACTION_ADD;
   record->id = node_id;
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
 
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index 7f90cd6..fef7e14 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -30,7 +30,6 @@
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/file_test_utils.h"
 #include "chrome/test/profile_mock.h"
@@ -60,7 +59,7 @@
 
   ProfileSyncService* sync_service() { return sync_service_.get(); }
 
-  TestIdFactory* ids() { return &ids_; }
+  TestIdFactory* ids() { return sync_service_->id_factory(); }
 
  protected:
   SessionService* service() { return helper_.service(); }
@@ -124,8 +123,6 @@
     return true;
   }
 
-  SyncBackendHost* backend() { return sync_service_->backend(); }
-
   // Path used in testing.
   ScopedTempDir temp_dir_;
   SessionServiceTestHelper helper_;
@@ -134,7 +131,6 @@
   SessionID window_id_;
   ProfileSyncFactoryMock factory_;
   scoped_ptr<TestProfileSyncService> sync_service_;
-  TestIdFactory ids_;
   const gfx::Rect window_bounds_;
   bool notified_of_update_;
   NotificationRegistrar registrar_;
@@ -148,8 +144,10 @@
 
   virtual ~CreateRootTask() {}
   virtual void Run() {
-    success_ = ProfileSyncServiceTestHelper::CreateRoot(syncable::SESSIONS,
-        test_->sync_service(), test_->ids());
+    success_ = ProfileSyncServiceTestHelper::CreateRoot(
+        syncable::SESSIONS,
+        test_->sync_service()->GetUserShare(),
+        test_->ids());
   }
 
   bool success() { return success_; }
@@ -175,8 +173,7 @@
   ASSERT_NE(sync_api::kInvalidId, sync_id);
 
   // Check that we can get the correct session specifics back from the node.
-  sync_api::ReadTransaction trans(sync_service_->
-      backend()->GetUserShareHandle());
+  sync_api::ReadTransaction trans(sync_service_->GetUserShare());
   sync_api::ReadNode node(&trans);
   ASSERT_TRUE(node.InitByClientTagLookup(syncable::SESSIONS,
       machine_tag));
@@ -322,7 +319,7 @@
   record->id = node_id;
   ASSERT_FALSE(notified_of_update_);
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
   ASSERT_TRUE(notified_of_update_);
@@ -341,7 +338,7 @@
   record->id = node_id;
   ASSERT_FALSE(notified_of_update_);
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
   ASSERT_TRUE(notified_of_update_);
@@ -360,7 +357,7 @@
   record->id = node_id;
   ASSERT_FALSE(notified_of_update_);
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(sync_service_->GetUserShare());
     change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
   }
   ASSERT_TRUE(notified_of_update_);
@@ -425,4 +422,3 @@
 }
 
 }  // namespace browser_sync
-
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index 98b70c0..4e9b98d 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -84,7 +84,7 @@
                                history::VisitSource visit_source));
   MOCK_METHOD1(RemoveVisits, bool(const history::VisitVector& visits));
   MOCK_METHOD2(GetURL, bool(const GURL& url_id, history::URLRow* url_row));
-  MOCK_METHOD2(SetPageTitle, void(const GURL& url, const std::wstring& title));
+  MOCK_METHOD2(SetPageTitle, void(const GURL& url, const string16& title));
   MOCK_METHOD1(DeleteURL, void(const GURL& url));
 };
 
@@ -192,8 +192,7 @@
 
   void AddTypedUrlSyncNode(const history::URLRow& url,
                            const history::VisitVector& visits) {
-    sync_api::WriteTransaction trans(
-        service_->backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     sync_api::ReadNode typed_url_root(&trans);
     ASSERT_TRUE(typed_url_root.InitByTagLookup(browser_sync::kTypedUrlTag));
 
@@ -206,7 +205,7 @@
   }
 
   void GetTypedUrlsFromSyncDB(std::vector<history::URLRow>* urls) {
-    sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     sync_api::ReadNode typed_url_root(&trans);
     if (!typed_url_root.InitByTagLookup(browser_sync::kTypedUrlTag))
       return;
@@ -279,8 +278,6 @@
   ProfileSyncFactoryMock factory_;
   scoped_refptr<HistoryBackendMock> history_backend_;
   scoped_refptr<HistoryServiceMock> history_service_;
-
-  TestIdFactory ids_;
 };
 
 class AddTypedUrlEntriesTask : public Task {
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 74cfc24..04fc316 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -13,11 +13,13 @@
 #include "base/string_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/net/gaia/token_service.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/abstract_profile_sync_service_test.h"
 #include "chrome/browser/sync/engine/syncapi.h"
 #include "chrome/browser/sync/glue/change_processor.h"
 #include "chrome/browser/sync/glue/bookmark_change_processor.h"
@@ -27,11 +29,12 @@
 #include "chrome/browser/sync/glue/model_associator.h"
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
+#include "chrome/browser/sync/js_arg_list.h"
+#include "chrome/browser/sync/js_test_util.h"
 #include "chrome/browser/sync/profile_sync_factory.h"
 #include "chrome/browser/sync/profile_sync_factory_mock.h"
 #include "chrome/browser/sync/test_profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/net/gaia/gaia_constants.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/testing_profile.h"
@@ -44,27 +47,99 @@
 using browser_sync::BookmarkModelAssociator;
 using browser_sync::ChangeProcessor;
 using browser_sync::DataTypeController;
+using browser_sync::HasArgs;
+using browser_sync::JsArgList;
+using browser_sync::MockJsEventHandler;
 using browser_sync::ModelAssociator;
 using browser_sync::SyncBackendHost;
 using browser_sync::SyncBackendHostMock;
 using browser_sync::UnrecoverableErrorHandler;
 using testing::_;
+using testing::AtMost;
 using testing::Return;
+using testing::StrictMock;
 using testing::WithArg;
 using testing::Invoke;
 
+// TODO(akalin): Bookmark-specific tests should be moved into their
+// own file.
 class TestBookmarkModelAssociator : public BookmarkModelAssociator {
  public:
-  TestBookmarkModelAssociator(ProfileSyncService* service,
+  TestBookmarkModelAssociator(
+      TestProfileSyncService* service,
       UnrecoverableErrorHandler* persist_ids_error_handler)
       : BookmarkModelAssociator(service, persist_ids_error_handler),
-        helper_(new TestModelAssociatorHelper()) {
-  }
+        id_factory_(service->id_factory()) {}
+
+  // TODO(akalin): This logic lazily creates any tagged node that is
+  // requested.  A better way would be to have utility functions to
+  // create sync nodes from some bookmark structure and to use that.
   virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id) {
-    return helper_->GetSyncIdForTaggedNode(this, tag, sync_id);
+    std::wstring tag_wide;
+    if (!UTF8ToWide(tag.c_str(), tag.length(), &tag_wide)) {
+      NOTREACHED() << "Unable to convert UTF8 to wide for string: " << tag;
+      return false;
+    }
+
+    bool root_exists = false;
+    syncable::ModelType type = model_type();
+    {
+      sync_api::WriteTransaction trans(sync_service()->GetUserShare());
+      sync_api::ReadNode uber_root(&trans);
+      uber_root.InitByRootLookup();
+
+      sync_api::ReadNode root(&trans);
+      root_exists = root.InitByTagLookup(
+          ProfileSyncServiceTestHelper::GetTagForType(type));
+    }
+
+    if (!root_exists) {
+      bool created = ProfileSyncServiceTestHelper::CreateRoot(
+          type,
+          sync_service()->GetUserShare(),
+          id_factory_);
+      if (!created)
+        return false;
+    }
+
+    sync_api::WriteTransaction trans(sync_service()->GetUserShare());
+    sync_api::ReadNode root(&trans);
+    EXPECT_TRUE(root.InitByTagLookup(
+        ProfileSyncServiceTestHelper::GetTagForType(type)));
+
+    // First, try to find a node with the title among the root's children.
+    // This will be the case if we are testing model persistence, and
+    // are reloading a sync repository created earlier in the test.
+    int64 last_child_id = sync_api::kInvalidId;
+    for (int64 id = root.GetFirstChildId(); id != sync_api::kInvalidId; /***/) {
+      sync_api::ReadNode child(&trans);
+      child.InitByIdLookup(id);
+      last_child_id = id;
+      if (tag_wide == child.GetTitle()) {
+        *sync_id = id;
+        return true;
+      }
+      id = child.GetSuccessorId();
+    }
+
+    sync_api::ReadNode predecessor_node(&trans);
+    sync_api::ReadNode* predecessor = NULL;
+    if (last_child_id != sync_api::kInvalidId) {
+      predecessor_node.InitByIdLookup(last_child_id);
+      predecessor = &predecessor_node;
+    }
+    sync_api::WriteNode node(&trans);
+    // Create new fake tagged nodes at the end of the ordering.
+    node.InitByCreation(type, root, predecessor);
+    node.SetIsFolder(true);
+    node.SetTitle(tag_wide);
+    node.SetExternalId(0);
+    *sync_id = node.GetId();
+    return true;
   }
+
  private:
-  scoped_ptr<TestModelAssociatorHelper> helper_;
+  browser_sync::TestIdFactory* id_factory_;
 };
 
 // FakeServerChange constructs a list of sync_api::ChangeRecords while modifying
@@ -244,14 +319,16 @@
   }
 
   void StartSyncService() {
-    StartSyncServiceAndSetInitialSyncEnded(true);
+    StartSyncServiceAndSetInitialSyncEnded(true, true);
   }
-  void StartSyncServiceAndSetInitialSyncEnded(bool set_initial_sync_ended) {
+  void StartSyncServiceAndSetInitialSyncEnded(
+      bool set_initial_sync_ended,
+      bool issue_auth_token) {
     if (!service_.get()) {
       // Set bootstrap to true and it will provide a logged in user for test
       service_.reset(new TestProfileSyncService(&factory_,
                                                 profile_.get(),
-                                                "test", false, NULL));
+                                                "test", true, NULL));
       if (!set_initial_sync_ended)
         service_->dont_set_initial_sync_ended_on_init();
 
@@ -271,10 +348,11 @@
                                                        profile_.get(),
                                                        service_.get()));
 
-      profile_->GetTokenService()->IssueAuthTokenForTest(
-          GaiaConstants::kSyncService, "token");
+      if (issue_auth_token) {
+        profile_->GetTokenService()->IssueAuthTokenForTest(
+            GaiaConstants::kSyncService, "token");
+      }
       service_->Initialize();
-      MessageLoop::current()->Run();
     }
   }
 
@@ -343,7 +421,7 @@
   }
 
   void ExpectSyncerNodeMatching(const BookmarkNode* bnode) {
-    sync_api::ReadTransaction trans(service_->backend_->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     ExpectSyncerNodeMatching(&trans, bnode);
   }
 
@@ -421,7 +499,7 @@
   }
 
   void ExpectModelMatch() {
-    sync_api::ReadTransaction trans(service_->backend_->GetUserShareHandle());
+    sync_api::ReadTransaction trans(service_->GetUserShare());
     ExpectModelMatch(&trans);
   }
 
@@ -434,8 +512,6 @@
         model_->GetBookmarkBarNode()->id());
   }
 
-  SyncBackendHost* backend() { return service_->backend_.get(); }
-
   // This serves as the "UI loop" on which the ProfileSyncService lives and
   // operates. It is needed because the SyncBackend can post tasks back to
   // the service, meaning it can't be null. It doesn't have to be running,
@@ -549,7 +625,7 @@
   LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
   StartSyncService();
 
-  sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(service_->GetUserShare());
 
   FakeServerChange adds(&trans);
   int64 f1 = adds.AddFolder(L"Server Folder B", bookmark_bar_id(), 0);
@@ -638,7 +714,7 @@
   LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
   StartSyncService();
 
-  sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+  sync_api::WriteTransaction trans(service_->GetUserShare());
 
   // Stress the immediate children of other_node because that's where
   // ApplyModelChanges puts a temporary foster parent node.
@@ -647,11 +723,11 @@
   int64 f0 = other_bookmarks_id();                 // + other_node
   int64 f1 = adds.AddFolder(L"f1",      f0, 0);    //   + f1
   int64 f2 = adds.AddFolder(L"f2",      f1, 0);    //     + f2
-  int64 u3 = adds.AddURL(   L"u3", url, f2, 0);    //       + u3
-  int64 u4 = adds.AddURL(   L"u4", url, f2, u3);   //       + u4
-  int64 u5 = adds.AddURL(   L"u5", url, f1, f2);   //     + u5
+  int64 u3 = adds.AddURL(   L"u3", url, f2, 0);    //       + u3    NOLINT
+  int64 u4 = adds.AddURL(   L"u4", url, f2, u3);   //       + u4    NOLINT
+  int64 u5 = adds.AddURL(   L"u5", url, f1, f2);   //     + u5      NOLINT
   int64 f6 = adds.AddFolder(L"f6",      f1, u5);   //     + f6
-  int64 u7 = adds.AddURL(   L"u7", url, f0, f1);   //   + u7
+  int64 u7 = adds.AddURL(   L"u7", url, f0, f1);   //   + u7        NOLINT
 
   vector<sync_api::SyncManager::ChangeRecord>::const_iterator it;
   // The bookmark model shouldn't yet have seen any of the nodes of |adds|.
@@ -687,7 +763,7 @@
   StartSyncService();
 
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
 
     FakeServerChange adds(&trans);
     std::string url("http://dev.chromium.org");
@@ -718,7 +794,7 @@
 
   int child_count = 0;
   {
-    sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
 
     FakeServerChange adds(&trans);
     std::string url("x");
@@ -835,7 +911,7 @@
   // updating the ProfileSyncService state.  This should introduce
   // inconsistency between the two models.
   {
-    sync_api::WriteTransaction trans(service_->backend_->GetUserShareHandle());
+    sync_api::WriteTransaction trans(service_->GetUserShare());
     sync_api::WriteNode sync_node(&trans);
     EXPECT_TRUE(associator()->InitSyncNodeFromChromeId(node->id(),
                                                        &sync_node));
@@ -883,6 +959,180 @@
   ExpectModelMatch();
 }
 
+TEST_F(ProfileSyncServiceTest, JsFrontendHandlersBasic) {
+  LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
+  StartSyncService();
+
+  StrictMock<MockJsEventHandler> event_handler;
+
+  browser_sync::SyncBackendHostForProfileSyncTest* test_backend =
+      service_->GetBackendForTest();
+
+  EXPECT_TRUE(service_->sync_initialized());
+  ASSERT_TRUE(test_backend != NULL);
+  ASSERT_TRUE(test_backend->GetJsBackend() != NULL);
+  EXPECT_EQ(NULL, test_backend->GetJsBackend()->GetParentJsEventRouter());
+
+  browser_sync::JsFrontend* js_backend = service_->GetJsFrontend();
+  js_backend->AddHandler(&event_handler);
+  ASSERT_TRUE(test_backend->GetJsBackend() != NULL);
+  EXPECT_TRUE(test_backend->GetJsBackend()->GetParentJsEventRouter() != NULL);
+
+  js_backend->RemoveHandler(&event_handler);
+  EXPECT_EQ(NULL, test_backend->GetJsBackend()->GetParentJsEventRouter());
+}
+
+TEST_F(ProfileSyncServiceTest,
+       JsFrontendHandlersDelayedBackendInitialization) {
+  LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
+  StartSyncServiceAndSetInitialSyncEnded(true, false);
+
+  StrictMock<MockJsEventHandler> event_handler;
+  EXPECT_CALL(event_handler,
+              HandleJsEvent("onSyncServiceStateChanged",
+                            HasArgs(JsArgList()))).Times(3);
+  // For some reason, these two events don't fire on Linux.
+  EXPECT_CALL(event_handler, HandleJsEvent("onChangesApplied", _))
+      .Times(AtMost(1));
+  EXPECT_CALL(event_handler, HandleJsEvent("onChangesComplete", _))
+      .Times(AtMost(1));
+
+  EXPECT_EQ(NULL, service_->GetBackendForTest());
+  EXPECT_FALSE(service_->sync_initialized());
+
+  browser_sync::JsFrontend* js_backend = service_->GetJsFrontend();
+  js_backend->AddHandler(&event_handler);
+  // Since we're doing synchronous initialization, backend should be
+  // initialized by this call.
+  profile_->GetTokenService()->IssueAuthTokenForTest(
+      GaiaConstants::kSyncService, "token");
+
+  browser_sync::SyncBackendHostForProfileSyncTest* test_backend =
+      service_->GetBackendForTest();
+
+  EXPECT_TRUE(service_->sync_initialized());
+  ASSERT_TRUE(test_backend != NULL);
+  ASSERT_TRUE(test_backend->GetJsBackend() != NULL);
+  EXPECT_TRUE(test_backend->GetJsBackend()->GetParentJsEventRouter() != NULL);
+
+  js_backend->RemoveHandler(&event_handler);
+  EXPECT_EQ(NULL, test_backend->GetJsBackend()->GetParentJsEventRouter());
+}
+
+TEST_F(ProfileSyncServiceTest, JsFrontendProcessMessageBasic) {
+  LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
+  StartSyncService();
+
+  StrictMock<MockJsEventHandler> event_handler;
+
+  ListValue arg_list1;
+  arg_list1.Append(Value::CreateBooleanValue(true));
+  arg_list1.Append(Value::CreateIntegerValue(5));
+  JsArgList args1(arg_list1);
+  EXPECT_CALL(event_handler, HandleJsEvent("testMessage1", HasArgs(args1)));
+
+  ListValue arg_list2;
+  arg_list2.Append(Value::CreateStringValue("test"));
+  arg_list2.Append(arg_list1.DeepCopy());
+  JsArgList args2(arg_list2);
+  EXPECT_CALL(event_handler,
+              HandleJsEvent("delayTestMessage2", HasArgs(args2)));
+
+  ListValue arg_list3;
+  arg_list3.Append(arg_list1.DeepCopy());
+  arg_list3.Append(arg_list2.DeepCopy());
+  JsArgList args3(arg_list3);
+
+  browser_sync::JsFrontend* js_backend = service_->GetJsFrontend();
+
+  // Never replied to.
+  js_backend->ProcessMessage("notRepliedTo", args3, &event_handler);
+
+  // Replied to later.
+  js_backend->ProcessMessage("delayTestMessage2", args2, &event_handler);
+
+  js_backend->AddHandler(&event_handler);
+
+  // Replied to immediately.
+  js_backend->ProcessMessage("testMessage1", args1, &event_handler);
+
+  // Fires off reply for delayTestMessage2.
+  message_loop_.RunAllPending();
+
+  // Never replied to.
+  js_backend->ProcessMessage("delayNotRepliedTo", args3, &event_handler);
+
+  js_backend->RemoveHandler(&event_handler);
+
+  message_loop_.RunAllPending();
+
+  // Never replied to.
+  js_backend->ProcessMessage("notRepliedTo", args3, &event_handler);
+}
+
+TEST_F(ProfileSyncServiceTest,
+       JsFrontendProcessMessageBasicDelayedBackendInitialization) {
+  LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
+  StartSyncServiceAndSetInitialSyncEnded(true, false);
+
+  StrictMock<MockJsEventHandler> event_handler;
+  // For some reason, these two events don't fire on Linux.
+  EXPECT_CALL(event_handler, HandleJsEvent("onChangesApplied", _))
+      .Times(AtMost(1));
+  EXPECT_CALL(event_handler, HandleJsEvent("onChangesComplete", _))
+      .Times(AtMost(1));
+
+  ListValue arg_list1;
+  arg_list1.Append(Value::CreateBooleanValue(true));
+  arg_list1.Append(Value::CreateIntegerValue(5));
+  JsArgList args1(arg_list1);
+  EXPECT_CALL(event_handler, HandleJsEvent("testMessage1", HasArgs(args1)));
+
+  ListValue arg_list2;
+  arg_list2.Append(Value::CreateStringValue("test"));
+  arg_list2.Append(arg_list1.DeepCopy());
+  JsArgList args2(arg_list2);
+  EXPECT_CALL(event_handler, HandleJsEvent("testMessage2", HasArgs(args2)));
+
+  ListValue arg_list3;
+  arg_list3.Append(arg_list1.DeepCopy());
+  arg_list3.Append(arg_list2.DeepCopy());
+  JsArgList args3(arg_list3);
+  EXPECT_CALL(event_handler,
+              HandleJsEvent("delayTestMessage3", HasArgs(args3)));
+
+  const JsArgList kNoArgs;
+
+  EXPECT_CALL(event_handler, HandleJsEvent("onSyncServiceStateChanged",
+                                           HasArgs(kNoArgs))).Times(3);
+
+  browser_sync::JsFrontend* js_backend = service_->GetJsFrontend();
+
+  // We expect a reply for this message, even though its sent before
+  // |event_handler| is added as a handler.
+  js_backend->ProcessMessage("testMessage1", args1, &event_handler);
+
+  js_backend->AddHandler(&event_handler);
+
+  js_backend->ProcessMessage("testMessage2", args2, &event_handler);
+  js_backend->ProcessMessage("delayTestMessage3", args3, &event_handler);
+
+  // Fires testMessage1 and testMessage2.
+  profile_->GetTokenService()->IssueAuthTokenForTest(
+      GaiaConstants::kSyncService, "token");
+
+  // Fires delayTestMessage3.
+  message_loop_.RunAllPending();
+
+  js_backend->ProcessMessage("delayNotRepliedTo", kNoArgs, &event_handler);
+
+  js_backend->RemoveHandler(&event_handler);
+
+  message_loop_.RunAllPending();
+
+  js_backend->ProcessMessage("notRepliedTo", kNoArgs, &event_handler);
+}
+
 struct TestData {
   const wchar_t* title;
   const char* url;
@@ -1324,7 +1574,8 @@
   WriteTestDataToBookmarkModel();
 
   // While the service is running.
-  FilePath sync_data_directory = backend()->sync_data_folder_path();
+  FilePath sync_data_directory =
+      service_->GetBackendForTest()->sync_data_folder_path();
 
   // Simulate a normal shutdown for the sync service (don't disable it for
   // the user, which would reset the preferences and delete the sync data
@@ -1336,7 +1587,7 @@
 
   // Restart the sync service.  Don't fake out setting initial sync ended; lets
   // make sure the system does in fact nudge and wait for this to happen.
-  StartSyncServiceAndSetInitialSyncEnded(false);
+  StartSyncServiceAndSetInitialSyncEnded(false, true);
 
   // Make sure we're back in sync.  In real life, the user would need
   // to reauthenticate before this happens, but in the test, authentication
@@ -1385,11 +1636,10 @@
                                                      profile_.get(),
                                                      service_.get()));
 
-    service_->Initialize(); // will call disableForUser because sync setup
-                            // hasn't been completed.
+    service_->Initialize();  // will call disableForUser because sync setup
+                             // hasn't been completed.
   }
 
-  ASSERT_FALSE(service_->backend());
   ASSERT_FALSE(service_->HasSyncSetupCompleted());
 
   // Create some tokens in the token service; the service will startup when
diff --git a/chrome/browser/sync/profile_sync_test_util.cc b/chrome/browser/sync/profile_sync_test_util.cc
new file mode 100644
index 0000000..a533fd4
--- /dev/null
+++ b/chrome/browser/sync/profile_sync_test_util.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/profile_sync_test_util.h"
+
+#include "base/task.h"
+#include "base/threading/thread.h"
+
+ProfileSyncServiceObserverMock::ProfileSyncServiceObserverMock() {}
+
+ProfileSyncServiceObserverMock::~ProfileSyncServiceObserverMock() {}
+
+ThreadNotificationService::ThreadNotificationService(
+    base::Thread* notification_thread)
+    : done_event_(false, false),
+      notification_thread_(notification_thread) {}
+
+void ThreadNotificationService::Init() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  notification_thread_->message_loop()->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this, &ThreadNotificationService::InitTask));
+  done_event_.Wait();
+}
+
+void ThreadNotificationService::TearDown() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  notification_thread_->message_loop()->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this,
+                        &ThreadNotificationService::TearDownTask));
+  done_event_.Wait();
+}
+
+ThreadNotificationService::~ThreadNotificationService() {}
+
+void ThreadNotificationService::InitTask() {
+  service_.reset(new NotificationService());
+  done_event_.Signal();
+}
+
+void ThreadNotificationService::TearDownTask() {
+  service_.reset(NULL);
+  done_event_.Signal();
+}
+
+ThreadNotifier::ThreadNotifier(base::Thread* notify_thread)
+    : done_event_(false, false),
+      notify_thread_(notify_thread) {}
+
+void ThreadNotifier::Notify(NotificationType type,
+                            const NotificationDetails& details) {
+  Notify(type, NotificationService::AllSources(), details);
+}
+
+void ThreadNotifier::Notify(NotificationType type,
+                            const NotificationSource& source,
+                            const NotificationDetails& details) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  notify_thread_->message_loop()->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this,
+                        &ThreadNotifier::NotifyTask,
+                        type,
+                        source,
+                        details));
+  done_event_.Wait();
+}
+
+ThreadNotifier::~ThreadNotifier() {}
+
+void ThreadNotifier::NotifyTask(NotificationType type,
+                                const NotificationSource& source,
+                                const NotificationDetails& details) {
+  NotificationService::current()->Notify(type, source, details);
+  done_event_.Signal();
+}
diff --git a/chrome/browser/sync/profile_sync_test_util.h b/chrome/browser/sync/profile_sync_test_util.h
index 4e28efa..b7d7aa2 100644
--- a/chrome/browser/sync/profile_sync_test_util.h
+++ b/chrome/browser/sync/profile_sync_test_util.h
@@ -8,31 +8,21 @@
 
 #include <string>
 
-#include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "base/threading/thread.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/webdata/web_database.h"
-#include "chrome/browser/sync/glue/bookmark_change_processor.h"
-#include "chrome/browser/sync/glue/bookmark_data_type_controller.h"
-#include "chrome/browser/sync/glue/bookmark_model_associator.h"
-#include "chrome/browser/sync/glue/change_processor.h"
-#include "chrome/browser/sync/glue/data_type_manager_impl.h"
-#include "chrome/browser/sync/profile_sync_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/unrecoverable_error_handler.h"
-#include "chrome/common/notification_details.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "chrome/test/sync/test_http_bridge_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
+namespace base {
+class Thread;
+}
+
 ACTION_P(Notify, type) {
   NotificationService::current()->Notify(type,
                                          NotificationService::AllSources(),
@@ -44,102 +34,28 @@
   MessageLoop::current()->Quit();
 }
 
-ACTION_P(InvokeTask, task) {
-  if (task)
-    task->Run();
-}
-
-class TestModelAssociatorHelper {
- public:
-  template <class ModelAssociatorImpl>
-  bool GetSyncIdForTaggedNode(ModelAssociatorImpl* associator,
-                              const std::string& tag, int64* sync_id) {
-    std::wstring tag_wide;
-    if (!UTF8ToWide(tag.c_str(), tag.length(), &tag_wide)) {
-      NOTREACHED() << "Unable to convert UTF8 to wide for string: " << tag;
-      return false;
-    }
-
-    sync_api::WriteTransaction trans(
-        associator->sync_service()->backend()->GetUserShareHandle());
-    sync_api::ReadNode root(&trans);
-    root.InitByRootLookup();
-
-    // First, try to find a node with the title among the root's children.
-    // This will be the case if we are testing model persistence, and
-    // are reloading a sync repository created earlier in the test.
-    int64 last_child_id = sync_api::kInvalidId;
-    for (int64 id = root.GetFirstChildId(); id != sync_api::kInvalidId; /***/) {
-      sync_api::ReadNode child(&trans);
-      child.InitByIdLookup(id);
-      last_child_id = id;
-      if (tag_wide == child.GetTitle()) {
-        *sync_id = id;
-        return true;
-      }
-      id = child.GetSuccessorId();
-    }
-
-    sync_api::ReadNode predecessor_node(&trans);
-    sync_api::ReadNode* predecessor = NULL;
-    if (last_child_id != sync_api::kInvalidId) {
-      predecessor_node.InitByIdLookup(last_child_id);
-      predecessor = &predecessor_node;
-    }
-    sync_api::WriteNode node(&trans);
-    // Create new fake tagged nodes at the end of the ordering.
-    node.InitByCreation(ModelAssociatorImpl::model_type(), root, predecessor);
-    node.SetIsFolder(true);
-    node.SetTitle(tag_wide);
-    node.SetExternalId(0);
-    *sync_id = node.GetId();
-    return true;
-  }
-
-  ~TestModelAssociatorHelper() {}
-};
-
 class ProfileSyncServiceObserverMock : public ProfileSyncServiceObserver {
  public:
+  ProfileSyncServiceObserverMock();
+  virtual ~ProfileSyncServiceObserverMock();
+
   MOCK_METHOD0(OnStateChanged, void());
 };
 
 class ThreadNotificationService
     : public base::RefCountedThreadSafe<ThreadNotificationService> {
  public:
-  explicit ThreadNotificationService(base::Thread* notification_thread)
-      : done_event_(false, false),
-      notification_thread_(notification_thread) {}
+  explicit ThreadNotificationService(base::Thread* notification_thread);
 
-  void Init() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    notification_thread_->message_loop()->PostTask(
-        FROM_HERE,
-        NewRunnableMethod(this, &ThreadNotificationService::InitTask));
-    done_event_.Wait();
-  }
-
-  void TearDown() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    notification_thread_->message_loop()->PostTask(
-        FROM_HERE,
-        NewRunnableMethod(this,
-                          &ThreadNotificationService::TearDownTask));
-    done_event_.Wait();
-  }
+  void Init();
+  void TearDown();
 
  private:
   friend class base::RefCountedThreadSafe<ThreadNotificationService>;
+  virtual ~ThreadNotificationService();
 
-  void InitTask() {
-    service_.reset(new NotificationService());
-    done_event_.Signal();
-  }
-
-  void TearDownTask() {
-    service_.reset(NULL);
-    done_event_.Signal();
-  }
+  void InitTask();
+  void TearDownTask();
 
   base::WaitableEvent done_event_;
   base::Thread* notification_thread_;
@@ -149,37 +65,21 @@
 class ThreadNotifier :  // NOLINT
     public base::RefCountedThreadSafe<ThreadNotifier> {
  public:
-  explicit ThreadNotifier(base::Thread* notify_thread)
-      : done_event_(false, false),
-        notify_thread_(notify_thread) {}
+  explicit ThreadNotifier(base::Thread* notify_thread);
 
-  void Notify(NotificationType type, const NotificationDetails& details) {
-    Notify(type, NotificationService::AllSources(), details);
-  }
+  void Notify(NotificationType type, const NotificationDetails& details);
 
   void Notify(NotificationType type,
               const NotificationSource& source,
-              const NotificationDetails& details) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    notify_thread_->message_loop()->PostTask(
-        FROM_HERE,
-        NewRunnableMethod(this,
-                          &ThreadNotifier::NotifyTask,
-                          type,
-                          source,
-                          details));
-    done_event_.Wait();
-  }
+              const NotificationDetails& details);
 
  private:
   friend class base::RefCountedThreadSafe<ThreadNotifier>;
+  virtual ~ThreadNotifier();
 
   void NotifyTask(NotificationType type,
                   const NotificationSource& source,
-                  const NotificationDetails& details) {
-    NotificationService::current()->Notify(type, source, details);
-    done_event_.Signal();
-  }
+                  const NotificationDetails& details);
 
   base::WaitableEvent done_event_;
   base::Thread* notify_thread_;
diff --git a/chrome/browser/sync/protocol/app_specifics.proto b/chrome/browser/sync/protocol/app_specifics.proto
index 452cc50..4bfc225 100644
--- a/chrome/browser/sync/protocol/app_specifics.proto
+++ b/chrome/browser/sync/protocol/app_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for apps.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/autofill_specifics.proto b/chrome/browser/sync/protocol/autofill_specifics.proto
index 536623c..520f25f 100644
--- a/chrome/browser/sync/protocol/autofill_specifics.proto
+++ b/chrome/browser/sync/protocol/autofill_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for autofill.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/bookmark_specifics.proto b/chrome/browser/sync/protocol/bookmark_specifics.proto
index c94fd2e..75321f8 100644
--- a/chrome/browser/sync/protocol/bookmark_specifics.proto
+++ b/chrome/browser/sync/protocol/bookmark_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for bookmarks.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/encryption.proto b/chrome/browser/sync/protocol/encryption.proto
index 6d6a792..da51ff0 100644
--- a/chrome/browser/sync/protocol/encryption.proto
+++ b/chrome/browser/sync/protocol/encryption.proto
@@ -4,6 +4,9 @@
 //
 // Common sync protocol for encrypted data.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/extension_specifics.proto b/chrome/browser/sync/protocol/extension_specifics.proto
index dff29b2..25b98a0 100644
--- a/chrome/browser/sync/protocol/extension_specifics.proto
+++ b/chrome/browser/sync/protocol/extension_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for extensions.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/nigori_specifics.proto b/chrome/browser/sync/protocol/nigori_specifics.proto
index e7458c6..98ee1b7 100644
--- a/chrome/browser/sync/protocol/nigori_specifics.proto
+++ b/chrome/browser/sync/protocol/nigori_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for nigori keys.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/password_specifics.proto b/chrome/browser/sync/protocol/password_specifics.proto
index 210ec6e..49f1343 100644
--- a/chrome/browser/sync/protocol/password_specifics.proto
+++ b/chrome/browser/sync/protocol/password_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for password data.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/preference_specifics.proto b/chrome/browser/sync/protocol/preference_specifics.proto
index 8e22144..72bc375 100644
--- a/chrome/browser/sync/protocol/preference_specifics.proto
+++ b/chrome/browser/sync/protocol/preference_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for preferences.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions.cc b/chrome/browser/sync/protocol/proto_enum_conversions.cc
new file mode 100644
index 0000000..df3d184
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_enum_conversions.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "chrome/browser/sync/protocol/proto_enum_conversions.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+namespace browser_sync {
+
+#define ASSERT_ENUM_BOUNDS(enum_parent, enum_type, enum_min, enum_max)  \
+  COMPILE_ASSERT(enum_parent::enum_type##_MIN == enum_parent::enum_min, \
+                 enum_type##_MIN_not_##enum_min);                       \
+  COMPILE_ASSERT(enum_parent::enum_type##_MAX == enum_parent::enum_max, \
+                 enum_type##_MAX_not_##enum_max);
+
+#define ENUM_CASE(enum_parent, enum_value)              \
+  case enum_parent::enum_value: return #enum_value
+
+const char* GetBrowserTypeString(
+    sync_pb::SessionWindow::BrowserType browser_type) {
+  ASSERT_ENUM_BOUNDS(sync_pb::SessionWindow, BrowserType,
+                     TYPE_NORMAL, TYPE_POPUP);
+  switch (browser_type) {
+    ENUM_CASE(sync_pb::SessionWindow, TYPE_NORMAL);
+    ENUM_CASE(sync_pb::SessionWindow, TYPE_POPUP);
+  }
+  NOTREACHED();
+  return "";
+}
+
+const char* GetPageTransitionString(
+    sync_pb::TabNavigation::PageTransition page_transition) {
+  ASSERT_ENUM_BOUNDS(sync_pb::TabNavigation, PageTransition,
+                     LINK, CHAIN_END);
+  switch (page_transition) {
+    ENUM_CASE(sync_pb::TabNavigation, LINK);
+    ENUM_CASE(sync_pb::TabNavigation, TYPED);
+    ENUM_CASE(sync_pb::TabNavigation, AUTO_BOOKMARK);
+    ENUM_CASE(sync_pb::TabNavigation, AUTO_SUBFRAME);
+    ENUM_CASE(sync_pb::TabNavigation, MANUAL_SUBFRAME);
+    ENUM_CASE(sync_pb::TabNavigation, GENERATED);
+    ENUM_CASE(sync_pb::TabNavigation, START_PAGE);
+    ENUM_CASE(sync_pb::TabNavigation, FORM_SUBMIT);
+    ENUM_CASE(sync_pb::TabNavigation, RELOAD);
+    ENUM_CASE(sync_pb::TabNavigation, KEYWORD);
+    ENUM_CASE(sync_pb::TabNavigation, KEYWORD_GENERATED);
+    ENUM_CASE(sync_pb::TabNavigation, CHAIN_START);
+    ENUM_CASE(sync_pb::TabNavigation, CHAIN_END);
+  }
+  NOTREACHED();
+  return "";
+}
+
+const char* GetPageTransitionQualifierString(
+    sync_pb::TabNavigation::PageTransitionQualifier
+        page_transition_qualifier) {
+  ASSERT_ENUM_BOUNDS(sync_pb::TabNavigation, PageTransitionQualifier,
+                     CLIENT_REDIRECT, SERVER_REDIRECT);
+  switch (page_transition_qualifier) {
+    ENUM_CASE(sync_pb::TabNavigation, CLIENT_REDIRECT);
+    ENUM_CASE(sync_pb::TabNavigation, SERVER_REDIRECT);
+  }
+  NOTREACHED();
+  return "";
+}
+
+const char* GetUpdatesSourceString(
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source) {
+  ASSERT_ENUM_BOUNDS(sync_pb::GetUpdatesCallerInfo, GetUpdatesSource,
+                     UNKNOWN, CLEAR_PRIVATE_DATA);
+  switch (updates_source) {
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, UNKNOWN);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, FIRST_UPDATE);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, LOCAL);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, NOTIFICATION);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, PERIODIC);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, SYNC_CYCLE_CONTINUATION);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, CLEAR_PRIVATE_DATA);
+  }
+  NOTREACHED();
+  return "";
+}
+
+#undef ASSERT_ENUM_BOUNDS
+#undef ENUM_CASE
+
+}  // namespace
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions.h b/chrome/browser/sync/protocol/proto_enum_conversions.h
new file mode 100644
index 0000000..fd1142d
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_enum_conversions.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
+#define CHROME_BROWSER_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
+#pragma once
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "chrome/browser/sync/protocol/session_specifics.pb.h"
+
+// Utility functions to get the string equivalent for some sync proto
+// enums.
+
+namespace browser_sync {
+
+// The returned strings (which don't have to be freed) are in ASCII.
+// The result of passing in an invalid enum value is undefined.
+
+const char* GetBrowserTypeString(
+    sync_pb::SessionWindow::BrowserType browser_type);
+
+const char* GetPageTransitionString(
+    sync_pb::TabNavigation::PageTransition page_transition);
+
+const char* GetPageTransitionQualifierString(
+    sync_pb::TabNavigation::PageTransitionQualifier
+        page_transition_qualifier);
+
+const char* GetUpdatesSourceString(
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source);
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc b/chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc
new file mode 100644
index 0000000..648cfe6
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "chrome/browser/sync/protocol/proto_enum_conversions.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+class ProtoEnumConversionsTest : public testing::Test {
+};
+
+template <class T>
+void TestEnumStringFunction(const char* (*enum_string_fn)(T),
+                            int enum_min, int enum_max) {
+  for (int i = enum_min; i <= enum_max; ++i) {
+    const std::string& str = enum_string_fn(static_cast<T>(i));
+    EXPECT_FALSE(str.empty());
+  }
+}
+
+TEST_F(ProtoEnumConversionsTest, GetBrowserTypeString) {
+  TestEnumStringFunction(
+      GetBrowserTypeString,
+      sync_pb::SessionWindow::BrowserType_MIN,
+      sync_pb::SessionWindow::BrowserType_MAX);
+}
+
+TEST_F(ProtoEnumConversionsTest, GetPageTransitionString) {
+  // We have a gap, so we need to do two ranges.
+  TestEnumStringFunction(
+      GetPageTransitionString,
+      sync_pb::TabNavigation::PageTransition_MIN,
+      sync_pb::TabNavigation::KEYWORD_GENERATED);
+  TestEnumStringFunction(
+      GetPageTransitionString,
+      sync_pb::TabNavigation::CHAIN_START,
+      sync_pb::TabNavigation::PageTransition_MAX);
+}
+
+TEST_F(ProtoEnumConversionsTest, GetPageTransitionQualifierString) {
+  TestEnumStringFunction(
+      GetPageTransitionQualifierString,
+      sync_pb::TabNavigation::PageTransitionQualifier_MIN,
+      sync_pb::TabNavigation::PageTransitionQualifier_MAX);
+}
+
+TEST_F(ProtoEnumConversionsTest, GetUpdatesSourceString) {
+  TestEnumStringFunction(
+      GetUpdatesSourceString,
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource_MIN,
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource_MAX);
+}
+
+}  // namespace
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/protocol/proto_value_conversions.cc b/chrome/browser/sync/protocol/proto_value_conversions.cc
new file mode 100644
index 0000000..12ece6e
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_value_conversions.cc
@@ -0,0 +1,324 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "chrome/browser/sync/protocol/proto_value_conversions.h"
+
+#include "base/base64.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/sync/protocol/app_specifics.pb.h"
+#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
+#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
+#include "chrome/browser/sync/protocol/encryption.pb.h"
+#include "chrome/browser/sync/protocol/extension_specifics.pb.h"
+#include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
+#include "chrome/browser/sync/protocol/password_specifics.pb.h"
+#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
+#include "chrome/browser/sync/protocol/proto_enum_conversions.h"
+#include "chrome/browser/sync/protocol/session_specifics.pb.h"
+#include "chrome/browser/sync/protocol/sync.pb.h"
+#include "chrome/browser/sync/protocol/theme_specifics.pb.h"
+#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
+
+namespace browser_sync {
+
+namespace {
+
+// Basic Type -> Value functions.
+
+StringValue* MakeInt64Value(int64 x) {
+  return Value::CreateStringValue(base::Int64ToString(x));
+}
+
+// TODO(akalin): Perhaps make JSONWriter support BinaryValue and use
+// that instead of a StringValue.
+StringValue* MakeBytesValue(const std::string& bytes) {
+  std::string bytes_base64;
+  if (!base::Base64Encode(bytes, &bytes_base64)) {
+    NOTREACHED();
+  }
+  return Value::CreateStringValue(bytes_base64);
+}
+
+// T is the enum type.
+template <class T>
+StringValue* MakeEnumValue(T t, const char* (*converter_fn)(T)) {
+  return Value::CreateStringValue(converter_fn(t));
+}
+
+// T is the field type, F is either RepeatedField or RepeatedPtrField,
+// and V is a subclass of Value.
+template <class T, class F, class V>
+ListValue* MakeRepeatedValue(const F& fields, V* (*converter_fn)(T)) {
+  ListValue* list = new ListValue();
+  for (typename F::const_iterator it = fields.begin(); it != fields.end();
+       ++it) {
+    list->Append(converter_fn(*it));
+  }
+  return list;
+}
+
+}  // namespace
+
+// Helper macros to reduce the amount of boilerplate.
+
+#define SET(field, fn) value->Set(#field, fn(proto.field()))
+#define SET_REP(field, fn) \
+  value->Set(#field, MakeRepeatedValue(proto.field(), fn))
+#define SET_ENUM(field, fn) \
+  value->Set(#field, MakeEnumValue(proto.field(), fn))
+
+#define SET_BOOL(field) SET(field, Value::CreateBooleanValue)
+#define SET_BYTES(field) SET(field, MakeBytesValue)
+#define SET_INT32(field) SET(field, MakeInt64Value)
+#define SET_INT32_REP(field) SET_REP(field, MakeInt64Value)
+#define SET_INT64(field) SET(field, MakeInt64Value)
+#define SET_INT64_REP(field) SET_REP(field, MakeInt64Value)
+#define SET_STR(field) SET(field, Value::CreateStringValue)
+
+#define SET_EXTENSION(ns, field, fn)                                    \
+  do {                                                                  \
+    if (specifics.HasExtension(ns::field)) {                            \
+      value->Set(#field, fn(specifics.GetExtension(ns::field)));        \
+    }                                                                   \
+  } while (0)
+
+// If you add another macro, don't forget to add an #undef at the end
+// of this file, too.
+
+DictionaryValue* EncryptedDataToValue(const sync_pb::EncryptedData& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(key_name);
+  // TODO(akalin): Shouldn't blob be of type bytes instead of string?
+  SET_BYTES(blob);
+  return value;
+}
+
+DictionaryValue* SessionHeaderToValue(
+    const sync_pb::SessionHeader& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_REP(window, SessionWindowToValue);
+  return value;
+}
+
+DictionaryValue* SessionTabToValue(
+    const sync_pb::SessionTab& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_INT32(tab_id);
+  SET_INT32(window_id);
+  SET_INT32(tab_visual_index);
+  SET_INT32(current_navigation_index);
+  SET_BOOL(pinned);
+  SET_STR(extension_app_id);
+  SET_REP(navigation, TabNavigationToValue);
+  return value;
+}
+
+DictionaryValue* SessionWindowToValue(
+    const sync_pb::SessionWindow& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_INT32(window_id);
+  SET_INT32(selected_tab_index);
+  SET_INT32_REP(tab);
+  SET_ENUM(browser_type, GetBrowserTypeString);
+  return value;
+}
+
+DictionaryValue* TabNavigationToValue(
+    const sync_pb::TabNavigation& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_INT32(index);
+  SET_STR(virtual_url);
+  SET_STR(referrer);
+  SET_STR(title);
+  SET_STR(state);
+  SET_ENUM(page_transition, GetPageTransitionString);
+  SET_ENUM(navigation_qualifier, GetPageTransitionQualifierString);
+  return value;
+}
+
+DictionaryValue* PasswordSpecificsDataToValue(
+    const sync_pb::PasswordSpecificsData& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_INT32(scheme);
+  SET_STR(signon_realm);
+  SET_STR(origin);
+  SET_STR(action);
+  SET_STR(username_element);
+  SET_STR(username_value);
+  SET_STR(password_element);
+  value->SetString("password_value", "<redacted>");
+  SET_BOOL(ssl_valid);
+  SET_BOOL(preferred);
+  SET_INT64(date_created);
+  SET_BOOL(blacklisted);
+  return value;
+}
+
+DictionaryValue* AppSpecificsToValue(
+    const sync_pb::AppSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET(extension, ExtensionSpecificsToValue);
+  return value;
+}
+
+DictionaryValue* AutofillSpecificsToValue(
+    const sync_pb::AutofillSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(name);
+  SET_STR(value);
+  SET_INT64_REP(usage_timestamp);
+  SET(profile, AutofillProfileSpecificsToValue);
+  SET_BYTES(encrypted_credit_card);
+  SET(credit_card, AutofillCreditCardSpecificsToValue);
+  return value;
+}
+
+DictionaryValue* AutofillCreditCardSpecificsToValue(
+    const sync_pb::AutofillCreditCardSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(label);
+  SET_STR(name_on_card);
+  SET_STR(type);
+  SET_STR(card_number);
+  SET_STR(expiration_month);
+  SET_STR(expiration_year);
+  SET_STR(verification_code);
+  SET_STR(billing_address);
+  SET_STR(shipping_address);
+  return value;
+}
+
+DictionaryValue* AutofillProfileSpecificsToValue(
+    const sync_pb::AutofillProfileSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(label);
+  SET_STR(guid);
+
+  SET_STR(name_first);
+  SET_STR(name_middle);
+  SET_STR(name_last);
+  SET_STR(email_address);
+  SET_STR(company_name);
+
+  SET_STR(address_home_line1);
+  SET_STR(address_home_line2);
+  SET_STR(address_home_city);
+  SET_STR(address_home_state);
+  SET_STR(address_home_zip);
+  SET_STR(address_home_country);
+
+  SET_STR(phone_home_whole_number);
+  SET_STR(phone_fax_whole_number);
+  return value;
+}
+
+DictionaryValue* BookmarkSpecificsToValue(
+    const sync_pb::BookmarkSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(url);
+  SET_BYTES(favicon);
+  return value;
+}
+
+DictionaryValue* ExtensionSpecificsToValue(
+    const sync_pb::ExtensionSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(id);
+  SET_STR(version);
+  SET_STR(update_url);
+  SET_BOOL(enabled);
+  SET_BOOL(incognito_enabled);
+  SET_STR(name);
+  return value;
+}
+
+DictionaryValue* NigoriSpecificsToValue(
+    const sync_pb::NigoriSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET(encrypted, EncryptedDataToValue);
+  SET_BOOL(using_explicit_passphrase);
+  return value;
+}
+
+DictionaryValue* PasswordSpecificsToValue(
+    const sync_pb::PasswordSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET(encrypted, EncryptedDataToValue);
+  return value;
+}
+
+DictionaryValue* PreferenceSpecificsToValue(
+    const sync_pb::PreferenceSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(name);
+  SET_STR(value);
+  return value;
+}
+
+DictionaryValue* SessionSpecificsToValue(
+    const sync_pb::SessionSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(session_tag);
+  SET(header, SessionHeaderToValue);
+  SET(tab, SessionTabToValue);
+  return value;
+}
+
+DictionaryValue* ThemeSpecificsToValue(
+    const sync_pb::ThemeSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_BOOL(use_custom_theme);
+  SET_BOOL(use_system_theme_by_default);
+  SET_STR(custom_theme_name);
+  SET_STR(custom_theme_id);
+  SET_STR(custom_theme_update_url);
+  return value;
+}
+
+DictionaryValue* TypedUrlSpecificsToValue(
+    const sync_pb::TypedUrlSpecifics& proto) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_STR(url);
+  SET_STR(title);
+  SET_INT32(typed_count);
+  SET_BOOL(hidden);
+  SET_INT64_REP(visit);
+  return value;
+}
+
+DictionaryValue* EntitySpecificsToValue(
+    const sync_pb::EntitySpecifics& specifics) {
+  DictionaryValue* value = new DictionaryValue();
+  SET_EXTENSION(sync_pb, app, AppSpecificsToValue);
+  SET_EXTENSION(sync_pb, autofill, AutofillSpecificsToValue);
+  SET_EXTENSION(sync_pb, autofill_profile, AutofillProfileSpecificsToValue);
+  SET_EXTENSION(sync_pb, bookmark, BookmarkSpecificsToValue);
+  SET_EXTENSION(sync_pb, extension, ExtensionSpecificsToValue);
+  SET_EXTENSION(sync_pb, nigori, NigoriSpecificsToValue);
+  SET_EXTENSION(sync_pb, password, PasswordSpecificsToValue);
+  SET_EXTENSION(sync_pb, preference, PreferenceSpecificsToValue);
+  SET_EXTENSION(sync_pb, session, SessionSpecificsToValue);
+  SET_EXTENSION(sync_pb, theme, ThemeSpecificsToValue);
+  SET_EXTENSION(sync_pb, typed_url, TypedUrlSpecificsToValue);
+  return value;
+}
+
+#undef SET
+#undef SET_REP
+
+#undef SET_BOOL
+#undef SET_BYTES
+#undef SET_INT32
+#undef SET_INT64
+#undef SET_INT64_REP
+#undef SET_STR
+
+#undef SET_EXTENSION
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/protocol/proto_value_conversions.h b/chrome/browser/sync/protocol/proto_value_conversions.h
new file mode 100644
index 0000000..c2c1ab5
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_value_conversions.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Keep this file in sync with the .proto files in this directory.
+
+#ifndef CHROME_BROWSER_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
+#define CHROME_BROWSER_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
+#pragma once
+
+class DictionaryValue;
+
+namespace sync_pb {
+class AppSpecifics;
+class AutofillCreditCardSpecifics;
+class AutofillProfileSpecifics;
+class AutofillSpecifics;
+class BookmarkSpecifics;
+class EncryptedData;
+class EntitySpecifics;
+class ExtensionSpecifics;
+class NigoriSpecifics;
+class PasswordSpecifics;
+class PasswordSpecificsData;
+class PreferenceSpecifics;
+class SessionHeader;
+class SessionSpecifics;
+class SessionTab;
+class SessionWindow;
+class TabNavigation;
+class ThemeSpecifics;
+class TypedUrlSpecifics;
+}  // namespace sync_pb
+
+// Utility functions to convert sync protocol buffers to dictionaries.
+// Each protocol field is mapped to a key of the same name.  Repeated
+// fields are mapped to array values and sub-messages are mapped to
+// sub-dictionary values.
+//
+// TODO(akalin): Add has_* information.
+//
+// TODO(akalin): Improve enum support.
+
+namespace browser_sync {
+
+// Ownership of all returned DictionaryValues are transferred to the
+// caller.
+
+// TODO(akalin): Perhaps extend this to decrypt?
+DictionaryValue* EncryptedDataToValue(
+    const sync_pb::EncryptedData& encrypted_data);
+
+// Sub-protocols of SessionSpecifics.
+
+DictionaryValue* SessionHeaderToValue(
+    const sync_pb::SessionHeader& session_header);
+
+DictionaryValue* SessionTabToValue(
+    const sync_pb::SessionTab& session_tab);
+
+DictionaryValue* SessionWindowToValue(
+    const sync_pb::SessionWindow& session_window);
+
+DictionaryValue* TabNavigationToValue(
+    const sync_pb::TabNavigation& tab_navigation);
+
+// Sub-protocol of PasswordSpecifics.
+
+DictionaryValue* PasswordSpecificsDataToValue(
+    const sync_pb::PasswordSpecificsData& password_specifics_data);
+
+// Main *SpecificsToValue functions.
+
+DictionaryValue* AppSpecificsToValue(
+    const sync_pb::AppSpecifics& app_specifics);
+
+DictionaryValue* AutofillSpecificsToValue(
+    const sync_pb::AutofillSpecifics& autofill_specifics);
+
+DictionaryValue* AutofillCreditCardSpecificsToValue(
+    const sync_pb::AutofillCreditCardSpecifics&
+        autofill_credit_card_specifics);
+
+DictionaryValue* AutofillProfileSpecificsToValue(
+    const sync_pb::AutofillProfileSpecifics& autofill_profile_specifics);
+
+DictionaryValue* BookmarkSpecificsToValue(
+    const sync_pb::BookmarkSpecifics& bookmark_specifics);
+
+DictionaryValue* ExtensionSpecificsToValue(
+    const sync_pb::ExtensionSpecifics& extension_specifics);
+
+DictionaryValue* NigoriSpecificsToValue(
+    const sync_pb::NigoriSpecifics& nigori_specifics);
+
+DictionaryValue* PasswordSpecificsToValue(
+    const sync_pb::PasswordSpecifics& password_specifics);
+
+DictionaryValue* PreferenceSpecificsToValue(
+    const sync_pb::PreferenceSpecifics& password_specifics);
+
+DictionaryValue* SessionSpecificsToValue(
+    const sync_pb::SessionSpecifics& session_specifics);
+
+DictionaryValue* ThemeSpecificsToValue(
+    const sync_pb::ThemeSpecifics& theme_specifics);
+
+DictionaryValue* TypedUrlSpecificsToValue(
+    const sync_pb::TypedUrlSpecifics& typed_url_specifics);
+
+// Any present extensions are mapped to sub-dictionary values with the
+// key equal to the extension name.
+DictionaryValue* EntitySpecificsToValue(
+    const sync_pb::EntitySpecifics& entity_specifics);
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
diff --git a/chrome/browser/sync/protocol/proto_value_conversions_unittest.cc b/chrome/browser/sync/protocol/proto_value_conversions_unittest.cc
new file mode 100644
index 0000000..20e73e4
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_value_conversions_unittest.cc
@@ -0,0 +1,161 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "chrome/browser/sync/protocol/proto_value_conversions.h"
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/sync/protocol/app_specifics.pb.h"
+#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
+#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
+#include "chrome/browser/sync/protocol/encryption.pb.h"
+#include "chrome/browser/sync/protocol/extension_specifics.pb.h"
+#include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
+#include "chrome/browser/sync/protocol/password_specifics.pb.h"
+#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
+#include "chrome/browser/sync/protocol/session_specifics.pb.h"
+#include "chrome/browser/sync/protocol/sync.pb.h"
+#include "chrome/browser/sync/protocol/theme_specifics.pb.h"
+#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+class ProtoValueConversionsTest : public testing::Test {
+ protected:
+  template <class T>
+  void TestSpecificsToValue(
+      DictionaryValue* (*specifics_to_value)(const T&)) {
+    const T& specifics(T::default_instance());
+    scoped_ptr<DictionaryValue> value(specifics_to_value(specifics));
+    // We can't do much but make sure that the returned value has
+    // something in it.
+    EXPECT_FALSE(value->empty());
+  }
+};
+
+TEST_F(ProtoValueConversionsTest, ProtoChangeCheck) {
+  // If this number changes, that means we added or removed a data
+  // type.  Don't forget to add a unit test for {New
+  // type}SpecificsToValue below.
+  EXPECT_EQ(13, syncable::MODEL_TYPE_COUNT);
+
+  // We'd also like to check if we changed any field in our messages.
+  // However, that's hard to do: sizeof could work, but it's
+  // platform-dependent.  default_instance().ByteSize() won't change
+  // for most changes, since most of our fields are optional.  So we
+  // just settle for comments in the proto files.
+}
+
+TEST_F(ProtoValueConversionsTest, EncryptedDataToValue) {
+  TestSpecificsToValue(EncryptedDataToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionHeaderToValue) {
+  TestSpecificsToValue(SessionHeaderToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionTabToValue) {
+  TestSpecificsToValue(SessionTabToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionWindowToValue) {
+  TestSpecificsToValue(SessionWindowToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, TabNavigationToValue) {
+  TestSpecificsToValue(TabNavigationToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, PasswordSpecificsData) {
+  sync_pb::PasswordSpecificsData specifics;
+  specifics.set_password_value("secret");
+  scoped_ptr<DictionaryValue> value(PasswordSpecificsDataToValue(specifics));
+  EXPECT_FALSE(value->empty());
+  std::string password_value;
+  EXPECT_TRUE(value->GetString("password_value", &password_value));
+  EXPECT_EQ("<redacted>", password_value);
+}
+
+TEST_F(ProtoValueConversionsTest, AppSpecificsToValue) {
+  TestSpecificsToValue(AppSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AutofillSpecificsToValue) {
+  TestSpecificsToValue(AutofillSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AutofillCreditCardSpecificsToValue) {
+  TestSpecificsToValue(AutofillCreditCardSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AutofillProfileSpecificsToValue) {
+  TestSpecificsToValue(AutofillProfileSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, BookmarkSpecificsToValue) {
+  TestSpecificsToValue(BookmarkSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, ExtensionSpecificsToValue) {
+  TestSpecificsToValue(ExtensionSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, NigoriSpecificsToValue) {
+  TestSpecificsToValue(NigoriSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, PasswordSpecificsToValue) {
+  TestSpecificsToValue(PasswordSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, PreferenceSpecificsToValue) {
+  TestSpecificsToValue(PreferenceSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionSpecificsToValue) {
+  TestSpecificsToValue(SessionSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, ThemeSpecificsToValue) {
+  TestSpecificsToValue(ThemeSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, TypedUrlSpecificsToValue) {
+  TestSpecificsToValue(TypedUrlSpecificsToValue);
+}
+
+// TODO(akalin): Figure out how to better test EntitySpecificsToValue.
+
+TEST_F(ProtoValueConversionsTest, EntitySpecificsToValue) {
+  sync_pb::EntitySpecifics specifics;
+  // Touch the extensions to make sure it shows up in the generated
+  // value.
+#define SET_EXTENSION(key) (void)specifics.MutableExtension(sync_pb::key)
+
+  SET_EXTENSION(app);
+  SET_EXTENSION(autofill);
+  SET_EXTENSION(autofill_profile);
+  SET_EXTENSION(bookmark);
+  SET_EXTENSION(extension);
+  SET_EXTENSION(nigori);
+  SET_EXTENSION(password);
+  SET_EXTENSION(preference);
+  SET_EXTENSION(session);
+  SET_EXTENSION(theme);
+  SET_EXTENSION(typed_url);
+
+#undef SET_EXTENSION
+
+  scoped_ptr<DictionaryValue> value(EntitySpecificsToValue(specifics));
+  EXPECT_EQ(syncable::MODEL_TYPE_COUNT - syncable::FIRST_REAL_MODEL_TYPE,
+            static_cast<int>(value->size()));
+}
+
+}  // namespace
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/protocol/session_specifics.proto b/chrome/browser/sync/protocol/session_specifics.proto
index 5b00b35..bfed4aa 100644
--- a/chrome/browser/sync/protocol/session_specifics.proto
+++ b/chrome/browser/sync/protocol/session_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for sessions.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/sync.proto b/chrome/browser/sync/protocol/sync.proto
index 1ada951..6af021b 100644
--- a/chrome/browser/sync/protocol/sync.proto
+++ b/chrome/browser/sync/protocol/sync.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol for communication between sync client and server.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
@@ -263,7 +266,7 @@
                                   // continuation of a previous update.
     CLEAR_PRIVATE_DATA = 6;       // Source is a call to remove all private data                                  
   }
-  
+
   required GetUpdatesSource source = 1;
 
   // True only if notifications were enabled for this GetUpdateMessage.
@@ -306,6 +309,11 @@
   // will perform a get updates operation as normal from the indicated
   // timestamp, and return only an opaque progress token.
   optional int64 timestamp_token_for_migration = 3;
+
+  // An opaque-to-the-client string of bytes, received through a notification,
+  // that the server may interpret as a hint about the location of the latest
+  // version of the data for this type.
+  optional string notification_hint = 4;
 }
 
 message GetUpdatesMessage {
@@ -363,7 +371,7 @@
 
 message ClientToServerMessage {
   required string share = 1;
-  optional int32 protocol_version = 2 [default = 25];
+  optional int32 protocol_version = 2 [default = 26];
   enum Contents {
     COMMIT = 1;
     GET_UPDATES = 2;
diff --git a/chrome/browser/sync/protocol/theme_specifics.proto b/chrome/browser/sync/protocol/theme_specifics.proto
index 5439bc4..eb864ff 100644
--- a/chrome/browser/sync/protocol/theme_specifics.proto
+++ b/chrome/browser/sync/protocol/theme_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for themes.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/typed_url_specifics.proto b/chrome/browser/sync/protocol/typed_url_specifics.proto
index 7dd4041..011ae4e 100644
--- a/chrome/browser/sync/protocol/typed_url_specifics.proto
+++ b/chrome/browser/sync/protocol/typed_url_specifics.proto
@@ -4,6 +4,9 @@
 //
 // Sync protocol datatype extension for typed urls.
 
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/resources/about_sync.html b/chrome/browser/sync/resources/about_sync.html
deleted file mode 100644
index 6f62f5d..0000000
--- a/chrome/browser/sync/resources/about_sync.html
+++ /dev/null
@@ -1,214 +0,0 @@
-<html>
-</html>
-<html id="t">
-<head>
-<title>About Sync</title>
-
-<style type="text/css">
-body {
-  font-size: 84%;
-  font-family: Arial, Helvetica, sans-serif;
-  padding: 0.75em;
-  margin: 0;
-  min-width: 45em;
-}
-
-h1 {
-  font-size: 110%;
-  font-weight: bold;
-  color: #4a8ee6;
-  letter-spacing: -1px;
-  padding: 0;
-  margin: 0;
-}
-h2 {
-  font-size: 110%;
-  letter-spacing: -1px;
-  font-weight: normal;
-  color: #4a8ee6;
-  padding: 0;
-  margin: 0;
-  padding: 0.5em 1em;
-  color: #3a75bd;
-  margin-left: -38px;
-  padding-left: 38px;
-
-  border-top: 1px solid #3a75bd;
-  padding-top: 0.5em;
-
-}
-h2:first-child {
-  border-top: 0;
-  padding-top: 0;
-}
-
-div#header {
-  padding: 0.75em 1em;
-  padding-top: 0.6em;
-  padding-left: 0;
-  margin-bottom: 0.75em;
-  position: relative;
-  overflow: hidden;
-  background: #5296de;
-  background-size: 100%;
-  border: 1px solid #3a75bd;
-  border-radius: 6px;
-  color: white;
-  text-shadow: 0 0 2px black;
-}
-div#header h1 {
-  padding-left: 37px;
-  margin: 0;
-  display: inline;
-  background: url('../../resources/shared/images/gear.png') 12px 60% no-repeat;
-  color: white;
-}
-
-.desc {
-  font-size: 84%;
-}
-
-.err {
-  color: red;
-}
-
-div#header p {
-  font-size: 84%;
-  font-style: italic;
-  padding: 0;
-  margin: 0;
-  color: white;
-  padding-left: 0.4em;
-  display: inline;
-}
-
-table.list {
-  line-height: 200%;
-  border-collapse: collapse;
-  font-size: 84%;
-  table-layout: fixed;
-}
-table.list:not([class*='filtered']) tr:nth-child(odd) td {
-  background: #eff3ff;
-}
-table.list#details2 tr:nth-child(odd) td {
-  background: #ccffcc
-}
-
-table.list td {
-  padding: 0 0.5em;
-  vertical-align: top;
-  line-height: 1.4em;
-  padding-top: 0.35em;
-}
-table.list tr td:nth-last-child(1),
-table.list tr th:nth-last-child(1) {
-  padding-right: 1em;
-}
-table.list:not([class*='filtered']) .tab .name {
-  padding-left: 1.5em;
-}
-
-table.list .name {
-}
-
-table.list .name div {
-  height: 1.6em;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-}
-
-table.list .number {
-  width: 7em;
-  text-align: right;
-}
-
-table.list tr:not([class*='firstRow']) > *:nth-child(1),
-table.list tr:not([class*='firstRow']) > *:nth-child(4),
-table.list tr.firstRow th:nth-child(1),
-table.list tr.firstRow th:nth-child(2) {
-  border-right: 1px solid #b5c6de;
-}
-table.list#details .name {
-  padding-left: 25px;
-  background-position: 5px center;
-  background-repeat: no-repeat;
-}
-</style>
-</head>
-<body>
-  <div id='header'>
-    <h1>About Sync</h1>
-    <p> Sync engine diagnostic data</p>
-  </div>
-  <div id='content'>
-    <table width="100%">
-      <tr>
-        <td width="20%">
-          <span class="desc"><h2> Summary </h2></span>
-          <strong jscontent="summary"></strong>
-        </td>
-        <td>
-          <div class="desc" jsdisplay="unrecoverable_error_detected">
-            <span class="err">Unrecoverable Error Detected!</span>
-            <div jscontent="unrecoverable_error_message"></div>
-            <div jscontent="unrecoverable_error_location"></div>
-          </div>
-        </td>
-      </tr>
-      <tr>
-        <td colspan="2">
-          <span class="desc"><h2> Sync URL </h2></span>
-          <strong jscontent="service_url"></strong>
-        </td>
-      </tr>
-    </table>
-    <br /><br /><br />
-    <h2>  </h2>
-    <table>
-      <tr>
-        <td>
-        <div class="desc"><h2> Details </h2></div>
-        <table class='list' id='details'>
-          <tr>
-            <td class='name'> Authenticated </td>
-            <td class='number'>
-              <div jscontent="authenticated"> </div>
-              <div jsdisplay="!authenticated"
-                   style="color:red"
-                   jscontent="auth_problem"></div>
-            </td>
-          </tr>
-          </tr>
-          <tr>
-            <td class='name'>Last Synced</td>
-            <td class='number' jscontent="time_since_sync"> </td>
-          </tr>
-          <tr jsselect="details">
-            <td class='name'>
-              <div jscontent="stat_name"></div>
-            </td>
-            <td class='number'>
-              <div jscontent="stat_value"></div>
-            </td>
-          </tr>
-        </table>
-      </td>
-      <td valign="top">
-        <div class="desc"><h2> Routing Info </h2></div>
-        <table class='list' id='details2'>
-          <tr jsselect="routing_info">
-            <td class ='name'>
-              <div jscontent="model_type"></div>
-            </td>
-            <td class='number'>
-              <div jscontent="group"></div>
-            </td>
-          </tr>
-        </table>
-      </td>
-    </table>
-  </div>
-</body>
-</html>
diff --git a/chrome/browser/sync/resources/configure.html b/chrome/browser/sync/resources/configure.html
index b087169..12b4f30 100644
--- a/chrome/browser/sync/resources/configure.html
+++ b/chrome/browser/sync/resources/configure.html
@@ -3,7 +3,7 @@
 <title></title>
 <style type="text/css">
 body {
-   line-height: 1.5em;
+   line-height: 1.33em;
    background: #FFFFFF;
    font-size: 11pt;
 }
@@ -67,9 +67,9 @@
 .sync-config-tab-inactive {
   float: left;
   height: 22px;
-  padding-top: 3px;
+  padding: 3px 5px 0px;
   margin-left: 15px;
-  width: 100px;
+  min-width: 100px;
   text-align: center;
 }
 .sync-config-tab-active A,
@@ -145,7 +145,7 @@
 }
 .sync-section {
   background: #EEE;
-  margin: 5px 0px;
+  margin: 5px 0px 5px 19px;
   padding: 6px;
 }
 
@@ -153,6 +153,10 @@
   margin-bottom: 5px;
 }
 
+#learn-more-link {
+  float: right;
+}
+
 #change-passphrase {
   margin: 10px 0;
   background: #EEE;
@@ -385,6 +389,10 @@
           "sync-config-tab-contents-inactive";
     }
 
+    // Default to the 'Data Types' tab.
+    if (!newTab)
+      newTab = "data-type";
+
     document.getElementById(newTab + "-tab").className =
         "sync-config-tab-active";
     document.getElementById(newTab + "-tab-contents").className =
@@ -424,28 +432,21 @@
     emptyError.style.display = "none";
     mismatchError.style.display = "none";
 
-    if (getRadioCheckedValue() != "explicit") {
+    var f = document.getElementById("chooseDataTypesForm");
+    if (getRadioCheckedValue() != "explicit" || f.option[0].disabled) {
       return true;
     }
-    var f = document.getElementById("chooseDataTypesForm");
     if (f.passphrase.value.length == 0) {
       emptyError.style.display = "block";
       return false;
     }
-    if (f.confirmpassphrase.value.length > 0 &&
-        f.confirmpassphrase.value != f.passphrase.value) {
+    if (f.confirmpassphrase.value != f.passphrase.value) {
       mismatchError.style.display = "block";
       return false;
     }
     return true;
   }
 
-  function sendValuesAndClose() {
-    var result = JSON.stringify({"option": getRadioCheckedValue(),
-                                 "passphrase": f.passphrase.value});
-    chrome.send("FirstPassphrase", [result]);
-  }
-
   function goToDashboard() {
     chrome.send("GoToDashboard", [""]);
     chrome.send("DialogClose", [""]);
@@ -569,13 +570,17 @@
     <div>
       <input id="google-option" name="option" type="radio"
              value="google" onchange="onRadioChange();">
-      <span i18n-content="googleOption"></span>
+      <label for="google-option" i18n-content="googleOption"></label>
     </input>
     </div>
     <div>
-      <input id="explicit-option" name="option" type="radio"
-             value="explicit" onchange="onRadioChange();">
-      <span i18n-content="explicitOption"></span>
+      <input id="explicit-option" name="option" type="radio" value="explicit"
+             onchange="onRadioChange();">
+      <div id="learn-more-link">
+        <a i18n-values="href:encryptionhelpurl" target="_blank"
+           i18n-content="learnmore"></a>
+      </div>
+      <label for="explicit-option" i18n-content="explicitOption"></label>
     </input>
     </div>
 
@@ -587,16 +592,13 @@
       <div>
         <div i18n-content="passphraseLabel" id="passphraseLabel"></div>
         <input id="passphrase" name="passphrase" label="passphraseLabel"
-               type="password" onkeyup="checkPassphraseMatch();"
-               onchange="checkPassphraseMatch();"/>
+               type="password" />
       </div>
       <div>
         <div i18n-content="confirmLabel" id="confirmPassphraseLabel">
         </div>
         <input id="confirmpassphrase" name="confirmpassphrase" type="password"
-               label="confirmPassphraseLabel"
-               onkeyup="checkPassphraseMatch();"
-               onchange="checkPassphraseMatch();" />
+               label="confirmPassphraseLabel" />
       </div>
       <div class="error" style="display:none"
            id="emptyerror" i18n-content="emptyErrorMessage"></div>
@@ -607,9 +609,6 @@
     <div id="change-passphrase">
       <div id="sync-passphrase-warning" i18n-content="passphraseWarning">
       </div>
-      <div id="sync-reset-confirmation" i18n-content="cleardataconfirmation"
-           style="display: none;">
-      </div>
       <a id="clear-data-link" i18n-content="cleardatalink" href="#"
              onclick='goToDashboard(); return false;'></a>
     </div>
diff --git a/chrome/browser/sync/resources/firstpassphrase.html b/chrome/browser/sync/resources/firstpassphrase.html
index 4f82ef9..15156ee 100644
--- a/chrome/browser/sync/resources/firstpassphrase.html
+++ b/chrome/browser/sync/resources/firstpassphrase.html
@@ -39,6 +39,11 @@
   margin: 5px;
   padding: 10px;
 }
+
+#learn-more-link {
+  float: right;
+}
+
 html[dir='rtl'] .sync-footer {
   text-align: left;
   left: 0px;
@@ -49,6 +54,7 @@
 input[type='submit'] {
   min-width: 87px;
   min-height: 26px;
+  margin-left: 7px;
 }
 html[os='mac'] input[type='button'],
 html[os='mac'] input[type='submit'] {
@@ -59,15 +65,6 @@
   margin-top: 5px;
 }
 
-#passphraseLabel,
-#confirmPassphraseLabel {
-  width: 145px;
-  float: left;
-  text-align: right;
-  margin-right: 4px;
-  padding-top: 3px;
-}
-
 </style>
 <script src="chrome://resources/js/cr.js"></script>
 <script>
@@ -87,15 +84,9 @@
 
   function switchToMode(mode) {
     document.getElementById("section-explicit").style.display = "none";
-    document.getElementById("section-nothanks").style.display = "none";
-    document.getElementById("section-google").style.display = "none";
 
-    if (mode == "google") {
-      document.getElementById("section-google").style.display = "block";
-    } else if (mode =="explicit") {
+    if (mode == "explicit") {
       document.getElementById("section-explicit").style.display = "block";
-    } else if (mode == "nothanks") {
-      document.getElementById("section-nothanks").style.display = "block";
     }
   }
 
@@ -127,8 +118,7 @@
       emptyError.style.display = "block";
       return false;
     }
-    if (f.confirmpassphrase.value.length > 0 &&
-        f.confirmpassphrase.value != f.passphrase.value) {
+    if (f.confirmpassphrase.value != f.passphrase.value) {
       mismatchError.style.display = "block";
       return false;
     }
@@ -145,6 +135,12 @@
                                  "passphrase": f.passphrase.value});
     chrome.send("FirstPassphrase", [result]);
   }
+
+  function optOutOfPasswordsAndClose() {
+    var result = JSON.stringify({"option": "nothanks",
+                                 "passphrase": ""});
+    chrome.send("FirstPassphrase", [result]);
+  }
 </script>
 </head>
 <body i18n-values=".style.fontFamily:fontfamily" onload="setupDialog();">
@@ -153,51 +149,45 @@
   <div class="sync-instructions" id="instructions"
        i18n-content="instructions"></div>
   <div>
-    <input name="option" type="radio" value="google" onchange="onRadioChange();">
-      <span i18n-content="googleOption"></span>
+    <input name="option" type="radio" value="google"
+           id="google-option" onchange="onRadioChange();">
+      <label for="google-option" i18n-content="googleOption"></label>
     </input>
   </div>
   <div>
-    <input name="option" type="radio" value="explicit" onchange="onRadioChange();">
-    <span i18n-content="explicitOption"></span>
-    </input>
-  </div>
-  <div>
-    <input name="option" type="radio" value="nothanks" onchange="onRadioChange();">
-    <span i18n-content="nothanksOption"></span>
+    <input name="option" type="radio" value="explicit"
+           id="explicit-option" onchange="onRadioChange();">
+    <div id="learn-more-link">
+      <a i18n-values="href:encryptionhelpurl" target="_blank"
+         i18n-content="learnmore"></a>
+    </div>
+    <label for="explicit-option" i18n-content="explicitOption"></label>
     </input>
   </div>
 
-  <div class="sync-section" id="section-google">
-    <div i18n-content="sectionGoogleMessage"></div>
-  </div>
   <div class="sync-section" id="section-explicit">
     <div i18n-content="sectionExplicitMessage"></div>
     <div>
       <div i18n-content="passphraseLabel" id="passphraseLabel"></div>
       <input id="passphrase" name="passphrase" label="passphraseLabel"
-             type="password" onkeyup="checkPassphraseMatch();"
-             onchange="checkPassphraseMatch();"/>
+             type="password"/>
     </div>
     <div>
       <div i18n-content="confirmLabel" id="confirmPassphraseLabel">
       </div>
       <input id="confirmpassphrase" name="confirmpassphrase" type="password"
-             label="confirmPassphraseLabel"
-             onkeyup="checkPassphraseMatch();"
-             onchange="checkPassphraseMatch();" />
+             label="confirmPassphraseLabel" />
     </div>
     <div class="error" style="display:none"
          id="emptyerror" i18n-content="emptyErrorMessage"></div>
     <div class="error" style="display:none"
          id="mismatcherror" i18n-content="mismatchErrorMessage"></div>
   </div>
-  <div class="sync-section" id="section-nothanks">
-    <div i18n-content="sectionNothanksMessage"></div>
-  </div>
 
   <div class="sync-footer">
-    <input id="okButton" type="submit" i18n-values="value:ok" />
+    <input id="okButton" type="submit" i18n-values="value:syncpasswords" />
+    <input id="noThanksButton" type="submit" i18n-values="value:nothanks"
+           onclick="optOutOfPasswordsAndClose(); return false;"/>
   </div>
 </form>
 </body>
diff --git a/chrome/browser/sync/resources/gaia_login.css b/chrome/browser/sync/resources/gaia_login.css
new file mode 100644
index 0000000..bd7b82b
--- /dev/null
+++ b/chrome/browser/sync/resources/gaia_login.css
@@ -0,0 +1,188 @@
+body {
+  -webkit-user-select: none;
+  background-color: #fff;
+  margin-bottom: 6px;
+  margin-top: 6px;
+}
+
+a:link {
+  color: #00c;
+}
+
+a:visited {
+  color: #551a8b;
+}
+
+a:active {
+  color: #f00;
+}
+
+hr {
+  background-color: #ddd;
+  border: 0;
+  height: 1px;
+  margin: 5px;
+  text-align: left;
+  width: 100%;
+}
+
+input[type='button'],
+input[type='submit'] {
+  min-height: 26px;
+  min-width: 87px;
+}
+
+.form-noindent {
+  background-color: #fff;
+  border: #c3d9ff 1px solid;
+}
+
+.endaligned {
+  text-align: end;
+}
+
+#gaia_account_text {
+  font-weight: bold;
+}
+
+#email_readonly {
+  display: none;
+  font-size: 10pt;
+  font-weight: bold;
+}
+
+div.errormsg {
+  color: red;
+  display: none;
+  font-size: smaller;
+}
+
+font.errormsg {
+  color: red;
+  font-size: smaller;
+}
+
+div.errormsgspacer {
+  min-height: 1em;
+}
+
+font.errormsgspacer {
+  font-size: smaller;
+}
+
+#gaia_loginform {
+  margin-bottom: 0;
+}
+
+#captcha_wrapper {
+  background: no-repeat;
+  background-color: #e8eefa;
+  background-position: center;
+  background-size: 200px 70px;
+  display: block;
+}
+
+.captcha_image {
+  display: block;
+  height: 70px;
+  width: 200px;
+}
+
+#logging_in_throbber {
+  margin: 0 10px;
+}
+
+.toppageverticalspace {
+  height: 15px;
+}
+
+.bottompaddedcell {
+  padding-bottom: 3px;
+}
+
+.noverticalpadding {
+  padding-bottom: 0;
+  padding-top: 0;
+}
+
+.cancelspacenocaptcha {
+  height: 22px;
+}
+
+.cancelspaceforcaptcha {
+  height: 5px;
+}
+
+#top_blurb {
+  font-size: 11pt;
+  line-height: 1.5em;
+}
+
+#top_blurb_error {
+  background-color: #eeb939;
+  border-radius: 4px;
+  display: block;
+  font-size: 11pt;
+  font-weight: bold;
+  margin-bottom: 10px;
+  margin-left: auto;
+  margin-right: auto;
+  padding: 4px 10px;
+  text-align: center;
+  visibility: hidden;
+  width: 70%;
+}
+
+#content_table {
+ padding: 2px;
+}
+
+.access_code_row {
+  display: none;
+}
+
+.access_code_row > td {
+  padding-bottom: 1px;
+  text-align: center;
+}
+
+#access_code_label_row > td {
+  padding-top: 6px;
+}
+
+.centeredtext {
+  text-align: center;
+}
+
+.gaia.le.lbl,
+.gaia.le.val,
+.gaia.le.rem,
+.gaia.captchahtml.desc
+.gaia.captchahtml.cmt {
+  font-size: smaller;
+}
+
+.gaia.captchahtml.cmt {
+  font-style: italic;
+}
+
+.gaia.le.fpwd,
+.gaia.le.chusr {
+  font-size: 70%;
+}
+
+#error_custom {
+  display: none;
+}
+
+#captchadiv {
+  display: none;
+}
+
+#password_row {
+  margin-top: 2px;
+}
+
+#action-area {
+  margin-top: 2px;
+}
diff --git a/chrome/browser/sync/resources/gaia_login.html b/chrome/browser/sync/resources/gaia_login.html
index 2ae8727..7b9382a 100644
--- a/chrome/browser/sync/resources/gaia_login.html
+++ b/chrome/browser/sync/resources/gaia_login.html
@@ -1,583 +1,211 @@
 <html i18n-values="dir:textdirection;">
 <head>
-<style type="text/css">
-  body,td,div,p,a,font,span {font-family: arial,sans-serif;}
-  body {
-    background-color:#ffffff;
-    -webkit-user-select: none;
-  }
-  A:link {color:#0000cc; }
-  A:visited { color:#551a8b; }
-  A:active { color:#ff0000; }
-  .form-noindent {background-color: #ffffff; border: #C3D9FF 1px solid}
-  .body { margin-left: 3em;
-    margin-right: 5em;
-    font-family: arial,sans-serif; }
-  .endaligned {
-    text-align: right;
-  }
-  html[dir='rtl'] .endaligned {
-    text-align: left;
-  }
-  #gaia_account_text { font-weight: bold; }
-  #email_readonly { font-size: 10pt;
-                    font-weight: bold;
-                    display: none; }
-  div.errorbox-good {}
-  div.errorbox-bad {}
-  div.errormsg { color: red; font-size: smaller;
-    font-family: arial,sans-serif;
-    display: none;}
-  font.errormsg { color: red; font-size: smaller;
-    font-family: arial,sans-serif;}
-  div.errormsgspacer { min-height: 1em;}
-  font.errormsgspacer { font-size: smaller;
-    font-family: arial,sans-serif;}
-
-  hr {
-    border: 0;
-    background-color:#DDDDDD;
-    height: 1px;
-    width: 100%;
-    text-align: left;
-    margin: 5px;
-  }
-  #gaia_loginform {
-    margin-bottom: 0;
-  }
-
-  #captcha_wrapper {
-    background-size: 200px 70px;
-    background: no-repeat;
-    background-position: center;
-    background-color: #e8eefa;
-    display: block;
-  }
-  .captcha_image {
-    display: block;
-    width: 200px;
-    height: 70px;
-  }
-  #throb {
-    background-image: url("../../../../app/resources/throbber.png");
-    width: 16px;
-    height: 16px;
-    background-position: 0px;
-    margin: 0px 10px 0px 10px;
-  }
-  .toppageverticalspace {
-    height: 15px;
-  }
-  .bottompaddedcell {
-    padding-bottom: 3px;
-  }
-  .noverticalpadding {
-    padding-top: 0;
-    padding-bottom: 0;
-  }
-  .cancelspacenocaptcha {
-    height: 22px;
-  }
-  .cancelspaceforcaptcha {
-    height: 5px;
-  }
-  #top_blurb {
-    font-size: 11pt;
-    line-height: 1.5em;
-  }
-  input[type='button'],
-  input[type='submit'] {
-    min-width: 87px;
-    min-height: 26px;
-  }
-  #top_blurb_error {
-    display: block;
-    margin-bottom: 10px;
-    margin-right: auto;
-    margin-left: auto;
-    width: 70%;
-    text-align: center;
-    padding: 4px 10px;
-    background-color: #eeb939;
-    border-radius: 4px;
-    font-weight: bold;
-    font-size: 11pt;
-  }
-  #content_table {
-   padding: 2px;
-  }
-  .access_code_row {
-    display: none;
-  }
-  .access_code_row > td {
-    text-align: center;
-    padding-bottom: 1px;
-  }
-  #access_code_label_row > td {
-    padding-top: 6px;
-  }
-  .centeredtext {
-    text-align: center;
-  }
-</style>
+<link rel="stylesheet" href="gaia_login.css">
+<link rel="stylesheet" href="chrome://resources/css/throbber.css">
+<script src="gaia_login.js"></script>
 </head>
-<body bgcolor="#ffffff" vlink="#666666"
-      i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"
-      style="margin-bottom: 6px; margin-top: 6px;" onload="initGaiaLoginForm();">
-  <table width="100%" height="100%" align="center" cellpadding="1" cellspacing="1">
-  <tr>
-  <td valign="top"> <!-- LOGIN BOX -->
-  <script>
-    // Variable to track if a captcha challenge was issued. If this gets set to
-    // true, it stays that way until we are told about successful login from
-    // the browser.  This means subsequent errors (like invalid password) are
-    // rendered in the captcha state, which is basically identical except we
-    // don't show the top error blurb "Error Signing in" or the "Create
-    // account" link.
-    var g_is_captcha_challenge_active = false;
-
-    // Taken from new_new_tab.js.
-    // TODO(tim): Can this be unified?
-    function url(s) {
-      // http://www.w3.org/TR/css3-values/#uris
-      // Parentheses, commas, whitespace characters, single quotes (') and
-      // double quotes (") appearing in a URI must be escaped with a backslash
-      var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
-      // WebKit has a bug when it comes to URLs that end with \
-      // https://bugs.webkit.org/show_bug.cgi?id=28885
-      if (/\\\\$/.test(s2)) {
-        // Add a space to work around the WebKit bug.
-        s2 += ' ';
-      }
-      return 'url("' + s2 + '")';
-    }
-
-    function gaia_setFocus() {
-      var f = null;
-      if (document.getElementById) {
-        f = document.getElementById("gaia_loginform");
-      } else if (window.gaia_loginform) {
-        f = window.gaia_loginform;
-      }
-      if (f) {
-        if (f.Email && (f.Email.value == null || f.Email.value == "")) {
-          f.Email.focus();
-        } else if (f.Passwd) {
-          f.Passwd.focus();
-        }
-      }
-    }
-
-    function advanceThrobber() {
-      var throbber = document.getElementById('throb');
-      throbber.style.backgroundPositionX =
-          ((parseInt(getComputedStyle(throbber).backgroundPositionX) - 16) %
-          576) + 'px';
-    }
-
-    function showGaiaLogin(args) {
-      var throbber = document.getElementById('throbber_container');
-      throbber.style.display = "none";
-      var f = document.getElementById("gaia_loginform");
-      if (f) {
-        f.Email.value = args.user;
-        if (!args.editable_user) {
-          f.Email.style.display = 'none';
-          var span = document.getElementById('email_readonly');
-          span.appendChild(document.createTextNode(f.Email.value));
-          span.style.display = 'inline';
-          setElementDisplay("createaccountdiv", "none");
-        }
-
-        f.AccessCode.disabled = true;
-      }
-      if (1 == args.error) {
-        var access_code = document.getElementById('AccessCode');
-        if (access_code.value && access_code.value != "") {
-          setElementDisplay("errormsg_0_AccessCode", 'block');
-          showAccessCodeRequired();
-        } else {
-          setElementDisplay("errormsg_1_Password", 'table-row');
-        }
-        setBlurbError();
-      }
-      if (3 == args.error) {
-        setElementDisplay("errormsg_0_Connection", 'table-row');
-        setBlurbError();
-      }
-      if (4 == args.error) {
-        showCaptcha(args);
-      }
-      if (8 == args.error) {
-        showAccessCodeRequired();
-      }
-      document.getElementById("signIn").disabled = false;
-      document.getElementById("signIn").value = templateData['signin'];
-      gaia_setFocus();
-    }
-
-    function showCaptcha(args) {
-      g_is_captcha_challenge_active = true;
-
-      // The captcha takes up lots of space, so make room.
-      setElementDisplay("top_blurb", "none");
-      setElementDisplay("top_blurb_error", "none");
-      setElementDisplay("createaccountdiv", "none");
-      var gaiaTable = document.getElementById('gaia_table');
-      gaiaTable.cellPadding = 0;
-      gaiaTable.cellSpacing = 1;
-      document.getElementById('cancelspacer').className =
-          "cancelspaceforcaptcha";
-      document.getElementById('createaccountcell').height = 0;
-
-      // It's showtime for the captcha now.
-      setElementDisplay("captchadiv", "block");
-      document.getElementById('Email').disabled = true;
-      document.getElementById('Passwd').disabled = false;
-      document.getElementById('CaptchaValue').disabled = false;
-      document.getElementById('captcha_wrapper').style.backgroundImage =
-          url(args.captchaUrl);
-    }
-
-    function showAccessCodeRequired() {
-      setElementDisplay("password_row", "none");
-      setElementDisplay("email_row", "none");
-      document.getElementById("createaccountcell").style.visibility =
-          "hidden";
-
-      setElementDisplay("access_code_label_row", "table-row");
-      setElementDisplay("access_code_input_row", "table-row");
-      setElementDisplay("access_code_help_row", "table-row");
-      document.getElementById('AccessCode').disabled = false;
-    }
-
-    function CloseDialog() {
-      chrome.send("DialogClose", [""]);
-    }
-
-    function showGaiaSuccessAndClose() {
-      document.getElementById("signIn").value = templateData['success'];
-      setTimeout(CloseDialog, 1600);
-    }
-
-    function showGaiaSuccessAndSettingUp() {
-      document.getElementById("signIn").value = templateData['settingup'];
-    }
-
-    // Called once, when this html/js is loaded.
-    function initGaiaLoginForm() {
-      var acct_text = document.getElementById("gaia_account_text");
-      var translated_text = acct_text.textContent;
-      var posGoogle = translated_text.indexOf('Google');
-      if (posGoogle != -1) {
-        var ltr = templateData['textdirection'] == 'ltr';
-        var googleIsAtEndOfSentence = posGoogle != 0;
-        if (googleIsAtEndOfSentence == ltr) {
-          // We're in ltr and in the translation the word 'Google' is AFTER the
-          // word 'Account' OR we're in rtl and 'Google' is BEFORE 'Account'.
-          var logo_td = document.getElementById('gaia_logo');
-          logo_td.parentNode.appendChild(logo_td);
-        }
-        acct_text.textContent = translated_text.replace('Google','');
-      }
-      setInterval(advanceThrobber, 30);
-      var args = JSON.parse(chrome.dialogArguments);
-      showGaiaLogin(args);
-    }
-
-    function sendCredentialsAndClose() {
-
-      if (!setErrorVisibility())
-        return false;
-
-      document.getElementById('Email').disabled = true;
-      document.getElementById('Passwd').disabled = true;
-      document.getElementById('CaptchaValue').disabled = true;
-      document.getElementById('AccessCode').disabled = true;
-
-      var throbber = document.getElementById('throbber_container');
-      throbber.style.display = "inline";
-      var f = document.getElementById("gaia_loginform");
-      var result = JSON.stringify({"user" : f.Email.value,
-                                   "pass" : f.Passwd.value,
-                                   "captcha" : f.CaptchaValue.value,
-                                   "access_code" : f.AccessCode.value});
-      document.getElementById("signIn").disabled = true;
-      chrome.send("SubmitAuth", [result]);
-    }
-
-    function setElementDisplay(id, display) {
-      var d = document.getElementById(id);
-      if (d)
-        d.style.display = display;
-    }
-    
-    function hideBlurb() {
-      setElementDisplay('top_blurb', 'none');
-    }
-
-    function setBlurbError() {
-      if (g_is_captcha_challenge_active)
-        return;  // No blurb in captcha challenge mode.
-      document.getElementById("top_blurb_error").style.visibility = "visible";
-      document.getElementById('Email').disabled = false;
-      document.getElementById('Passwd').disabled = false;
-    }
-
-    function resetErrorVisibility() {
-      setElementDisplay("errormsg_0_Email", 'none');
-      setElementDisplay("errormsg_0_Password", 'none');
-      setElementDisplay("errormsg_1_Password", 'none');
-      setElementDisplay("errormsg_0_Connection", 'none');
-      setElementDisplay("errormsg_0_AccessCode", 'none');
-    }
-
-    function setErrorVisibility() {
-      resetErrorVisibility();
-      var f = document.getElementById("gaia_loginform");
-      if (null == f.Email.value || "" == f.Email.value) {
-        setElementDisplay("errormsg_0_Email", 'table-row');
-        setBlurbError();
-        return false;
-      }
-      if (null == f.Passwd.value || "" == f.Passwd.value) {
-        setElementDisplay("errormsg_0_Password", 'table-row');
-        setBlurbError();
-        return false;
-      }
-      if (!f.AccessCode.disabled && (null == f.AccessCode.value ||
-          "" == f.AccessCode.value)) {
-        setElementDisplay("errormsg_0_Password", 'table-row');
-        return false;
-      }
-      return true;
-    }
-  </script>
-  <style type="text/css">
-    div.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif; }
-    font.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif;}
-  </style>
-  <style type="text/css">
-    .gaia.le.lbl { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-    .gaia.le.fpwd { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
-    .gaia.le.chusr { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
-    .gaia.le.val { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-    .gaia.le.button { font-family: Arial, Helvetica, sans-serif; }
-    .gaia.le.rem { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-    .gaia.captchahtml.desc { font-family: arial, sans-serif; font-size: smaller; }
-    .gaia.captchahtml.cmt { font-family: arial, sans-serif; font-size: smaller;
-                            font-style: italic; }
-  </style>
-  <div id="top_blurb">
-    <span i18n-content="introduction"></span>
-  </div>
-  <div id="top_blurb_error" style="visibility:hidden">
-      <span i18n-content="errorsigningin"></span>
-  </div>
-<form id="gaia_loginform" onsubmit="sendCredentialsAndClose(); return false;">
-<div id="gaia_loginbox">
-<table id="content_table" class="form-noindent" cellspacing="0" cellpadding="5"
-       width="75%" border="0" align="center">
-  <tr>
-    <td valign="top" style="text-align:center" nowrap="nowrap"
-        bgcolor="#e8eefa">
-      <div>
-        <table id="gaia_table" align="center" border="0" cellpadding="1"
-               cellspacing="0">
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+<div>
+  <div>
+    <div id="top_blurb">
+      <span i18n-content="introduction"></span>
+    </div>
+    <div id="top_blurb_error">
+      <span id="error_signing_in" i18n-content="errorsigningin"></span>
+      <span id="error_custom"></span>
+    </div>
+    <form id="gaia_loginform">
+      <div id="gaia_loginbox">
+        <table id="content_table" class="form-noindent" cellspacing="0"
+            cellpadding="5" width="75%" border="0" align="center">
           <tr>
-            <td colspan="2" align="center">
-              <table>
-                <tr>
-                  <td valign="top" id="gaia_logo">
-                    <img src="google_transparent.png" alt="Google">
-                  </td>
-                  <td valign="middle">
-                    <font size="+0">
-                      <span id="gaia_account_text" i18n-content="signinsuffix"></span>
-                    </font>
-                  </td>
-                </tr>
-              </table>
-            </td>
-          </tr>
-          <script type="text/javascript">
-            function onPreCreateAccount() {
-              return true;
-            }
-            function onPreLogin() {
-              if (window["onlogin"] != null) {
-                return onlogin();
-              } else {
-                return true;
-              }
-            }
-          </script>
-          <tr>
-            <td colspan="2" align="center"> </td>
-          </tr>
-          <tr id="email_row">
-            <td nowrap="nowrap">
-              <div class="endaligned">
-                <span class="gaia le lbl" i18n-content="emaillabel">
-                </span>
-              </div>
-            </td>
-            <td>
-              <input type="text" name="Email"  id="Email" size="18"
-                     value="" class='gaia le val' />
-              <span id="email_readonly"></span>
-            </td>
-          </tr>
-          <tr id="access_code_label_row" class="access_code_row">
-            <td colspan="2">
-                <span class="gaia le lbl" i18n-content="enteraccesscode"></span>
-            </td>
-          </tr>
-          <tr id="access_code_help_row" class="access_code_row">
-            <td colspan="2" class="gaia le fpwd">
-              <a i18n-values="href:getaccesscodeurl" i18n-content="getaccesscodehelp" target="_blank"></a>
-            </td>
-          <tr>
-            <td></td>
-            <td>
-              <div class="errormsg" id="errormsg_0_Email"
-                   i18n-content="cannotbeblank">
-              </div>
-            </td>
-          </tr>
-          <tr>
-            <td></td>
-            <td></td>
-          </tr>
-          <tr id="password_row">
-            <td class="endaligned">
-              <span class="gaia le lbl" i18n-content="passwordlabel">
-              </span>
-            </td>
-            <td>
-              <input type="password" name="Passwd" id="Passwd" size="18"
-                     class="gaia le val"/>
-            </td>
-          </tr>
-          <tr id="access_code_input_row" class="access_code_row">
-            <td colspan="2">
-              <input type="password" name="AccessCode" id="AccessCode" size="18"
-                     class="gaia le val"/>
-            </td>
-          </tr>
-          <tr>
-            <td>
-            </td>
-            <td>
-              <div class="errormsgspacer">
-                <div class="errormsg" id="errormsg_0_Password"
-                     i18n-content="cannotbeblank">
-                </div>
-                <div class="errormsg" id="errormsg_1_Password">
-                  <span i18n-content="invalidcredentials"></span>[<a i18n-values="href:invalidpasswordhelpurl" target="_blank">?</a>]
-                </div>
-                <div class="errormsg centeredtext" id="errormsg_0_AccessCode"
-                     i18n-content="invalidaccesscode">
-                </div>
-              </div>
-            </td>
-          </tr>
-          <tr>
-            <td colspan="2">
-              <div id="captchadiv" style="display:none">
-                <table cellpadding="1" cellspacing="0" border="0">
-                  <tbody>
-                    <tr>
-                      <td colspan="2" align="center" class="bottompaddedcell">
-                        <font size="-1">
-                          <span i18n-content="captchainstructions"></span>
-                        </font>
-                      </td>
-                    </tr>
-                    <tr>
-                      <td colspan="2" align="center" class="bottompaddedcell">
-                        <span id="captcha_wrapper">
-                          <span class="captcha_image"></span>
+            <td valign="top" style="text-align:center" nowrap="nowrap"
+                bgcolor="#e8eefa">
+              <div>
+                <table id="gaia_table" align="center" border="0"
+                    cellpadding="1" cellspacing="0">
+                  <tr>
+                    <td colspan="2" align="center">
+                      <table>
+                        <tr>
+                          <td valign="top" id="gaia_logo">
+                            <img src="google_transparent.png" alt="Google">
+                          </td>
+                          <td valign="middle">
+                            <font size="+0">
+                              <span id="gaia_account_text"
+                                  i18n-content="signinsuffix"></span>
+                            </font>
+                          </td>
+                        </tr>
+                      </table>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td colspan="2" align="center"> </td>
+                  </tr>
+                  <tr id="email_row">
+                    <td nowrap="nowrap">
+                      <div class="endaligned">
+                        <span class="gaia le lbl" i18n-content="emaillabel">
                         </span>
-                      </td>
-                    </tr>
-                    <tr>
-                      <td colspan="2" align="center">
-                        <input type="text" name="CaptchaValue"
-                               id="CaptchaValue" size="18"
-                               value="" class="gaia le val" />
-                      </td>
-                    </tr>
-                  </tbody>
+                      </div>
+                    </td>
+                    <td>
+                      <input type="text" name="Email"  id="Email" size="18"
+                          value="" class='gaia le val'>
+                      <span id="email_readonly"></span>
+                    </td>
+                  </tr>
+                  <tr id="access_code_label_row" class="access_code_row">
+                    <td colspan="2">
+                      <span class="gaia le lbl"
+                          i18n-content="enteraccesscode"></span>
+                    </td>
+                  </tr>
+                  <tr id="access_code_help_row" class="access_code_row">
+                    <td colspan="2" class="gaia le fpwd">
+                      <a i18n-values="href:getaccesscodeurl"
+                          i18n-content="getaccesscodehelp" target="_blank">
+                      </a>
+                    </td>
+                  <tr>
+                    <td></td>
+                    <td>
+                      <div class="errormsg" id="errormsg_0_Email"
+                          i18n-content="cannotbeblank">
+                      </div>
+                    </td>
+                  </tr>
+                  <tr id="password_row">
+                    <td class="endaligned">
+                      <span class="gaia le lbl"
+                          i18n-content="passwordlabel"></span>
+                    </td>
+                    <td>
+                      <input type="password" name="Passwd" id="Passwd"
+                          size="18" class="gaia le val">
+                    </td>
+                  </tr>
+                  <tr id="access_code_input_row" class="access_code_row">
+                    <td colspan="2">
+                      <input type="password" name="AccessCode"
+                          id="AccessCode" size="18" class="gaia le val">
+                    </td>
+                  </tr>
+                  <tr>
+                    <td></td>
+                    <td>
+                      <div class="errormsgspacer">
+                        <div class="errormsg" id="errormsg_0_Password"
+                            i18n-content="cannotbeblank">
+                        </div>
+                        <div class="errormsg" id="errormsg_1_Password">
+                          <span i18n-content="invalidcredentials"></span>
+                          <!-- Brackets are intentional -->
+                          [<a i18n-values="href:invalidpasswordhelpurl"
+                               target="_blank">?</a>]
+                        </div>
+                        <div class="errormsg centeredtext"
+                            id="errormsg_0_AccessCode"
+                            i18n-content="invalidaccesscode">
+                        </div>
+                      </div>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td colspan="2">
+                      <div id="captchadiv">
+                        <table cellpadding="1" cellspacing="0" border="0">
+                          <tbody>
+                            <tr>
+                              <td colspan="2" align="center"
+                                  class="bottompaddedcell">
+                                <font size="-1">
+                                  <span i18n-content="captchainstructions">
+                                  </span>
+                                </font>
+                              </td>
+                            </tr>
+                            <tr>
+                              <td colspan="2" align="center"
+                                  class="bottompaddedcell">
+                                <span id="captcha_wrapper">
+                                  <span class="captcha_image"></span>
+                                </span>
+                              </td>
+                            </tr>
+                            <tr>
+                              <td colspan="2" align="center">
+                                <input type="text" name="CaptchaValue"
+                                    id="CaptchaValue" size="18" value=""
+                                    class="gaia le val">
+                              </td>
+                            </tr>
+                          </tbody>
+                        </table>
+                      </div>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td colspan="2" align="center">
+                      <div class="errormsg" id="errormsg_0_Connection"
+                          i18n-content="couldnotconnect">
+                      </div>
+                    </td>
+                  </tr>
+                  <tr id="action-area">
+                    <td colspan="2">
+                      <table align="center" cellpadding="0"
+                          cellspacing="0">
+                        <tr>
+                          <td>
+                            <div id="logging_in_throbber" class="throbber">
+                            </div>
+                          </td>
+                          <td class="noverticalpadding">
+                            <input id="signIn" type="submit"
+                                class="gaia le button" name="signIn"
+                                i18n-values="value:signin">
+                            <input id="gaia-cancel" type="button"
+                                name="cancel"
+                                i18n-values="value:cancel">
+                          </td>
+                        </tr>
+                      </table>
+                    </td>
+                  </tr>
+                  <tr id="ga-fprow">
+                    <td colspan="2" height="16.0" class="gaia le fpwd"
+                        align="center" valign="bottom">
+                      <a i18n-values="href:cannotaccessaccounturl"
+                          target="_blank"
+                          i18n-content="cannotaccessaccount">
+                      </a>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td id="createaccountcell" colspan="2" height="16.0"
+                        class="gaia le fpwd" align="center" valign="bottom">
+                      <div id="createaccountdiv">
+                        <a i18n-values="href:createnewaccounturl"
+                            i18n-content="createaccount" target="_blank">
+                        </a>
+                      </div>
+                   </td>
+                  </tr>
                 </table>
               </div>
             </td>
           </tr>
-          <tr>
-            <td colspan="2" align="center">
-              <div class="errormsg" id="errormsg_0_Connection"
-                   i18n-content="couldnotconnect">
-              </div>
-            </td>
-          </tr>
-          <tr>
-            <td>
-            </td>
-            <td>
-            </td>
-          </tr>
-          <tr>
-            <td colspan="2">
-              <table align="center" cellpadding="0" cellspacing="0">
-                <tr>
-                  <td>
-                    <div id="throbber_container" style="display:none;">
-                      <div id="throb">
-                      </div>
-                    </div>
-                  </td>
-                  <td class="noverticalpadding">
-                    <input id="signIn" type="submit" class="gaia le button"
-                           name="signIn" i18n-values="value:signin"/>
-                    <input type="button" name="cancel" i18n-values="value:cancel"
-                           onclick="CloseDialog();" >
-
-                  </td>
-                </tr>
-              </table>
-            </td>
-          </tr>
-          <tr id="ga-fprow">
-            <td colspan="2" height="16.0" class="gaia le fpwd"
-                align="center" valign="bottom">
-              <a i18n-values="href:cannotaccessaccounturl"
-                 target="_blank" i18n-content="cannotaccessaccount">
-              </a>
-            </td>
-          </tr>
-          <tr>
-            <td id="createaccountcell" colspan="2" height="16.0"
-                class="gaia le fpwd" align="center" valign="bottom">
-              <div id="createaccountdiv">
-                <a i18n-values="href:createnewaccounturl"
-                   i18n-content="createaccount" target="_blank">
-                </a>
-              </div>
-           </td>
-          </tr>
         </table>
       </div>
-    </td>
-  </tr>
-</table>
+    </form>
+  </div>
+  <div>
+    <div class="cancelspacenocaptcha" id="cancelspacer" colspan="2">
+    </div>
+  </div>
 </div>
-</form>
-</td>
-</tr>
-<tr>
-  <td class="cancelspacenocaptcha" id="cancelspacer" colspan="2">
-  </td>
-</tr>
-</table>
 </body>
 </html>
diff --git a/chrome/browser/sync/resources/gaia_login.js b/chrome/browser/sync/resources/gaia_login.js
new file mode 100644
index 0000000..8697873
--- /dev/null
+++ b/chrome/browser/sync/resources/gaia_login.js
@@ -0,0 +1,262 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Variable to track if a captcha challenge was issued. If this gets set to
+// true, it stays that way until we are told about successful login from
+// the browser.  This means subsequent errors (like invalid password) are
+// rendered in the captcha state, which is basically identical except we
+// don't show the top error blurb "Error Signing in" or the "Create
+// account" link.
+var g_is_captcha_challenge_active = false;
+
+// Taken from new_new_tab.js.
+// TODO(tim): Can this be unified?
+function url(s) {
+  // http://www.w3.org/TR/css3-values/#uris
+  // Parentheses, commas, whitespace characters, single quotes (') and
+  // double quotes (") appearing in a URI must be escaped with a backslash
+  var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
+  // WebKit has a bug when it comes to URLs that end with \
+  // https://bugs.webkit.org/show_bug.cgi?id=28885
+  if (/\\\\$/.test(s2)) {
+    // Add a space to work around the WebKit bug.
+    s2 += ' ';
+  }
+  return 'url("' + s2 + '")';
+}
+
+function gaia_setFocus() {
+  var f = null;
+  if (document.getElementById) {
+    f = document.getElementById("gaia_loginform");
+  } else if (window.gaia_loginform) {
+    f = window.gaia_loginform;
+  }
+  if (f) {
+    if (f.Email && (f.Email.value == null || f.Email.value == "")) {
+      f.Email.focus();
+    } else if (f.Passwd) {
+      f.Passwd.focus();
+    }
+  }
+}
+
+function showGaiaLogin(args) {
+  document.getElementById('logging_in_throbber').style.display = "none";
+
+  document.getElementById('Email').disabled = false;
+  document.getElementById('Passwd').disabled = false;
+
+  var f = document.getElementById("gaia_loginform");
+  if (f) {
+    if (args.user != undefined) {
+      if (f.Email.value != args.user)
+        f.Passwd.value = ""; // Reset the password field
+      f.Email.value = args.user;
+    }
+
+    if (!args.editable_user) {
+      f.Email.style.display = 'none';
+      var span = document.getElementById('email_readonly');
+      span.appendChild(document.createTextNode(f.Email.value));
+      span.style.display = 'inline';
+      setElementDisplay("createaccountdiv", "none");
+    }
+
+    f.AccessCode.disabled = true;
+  }
+
+  if (1 == args.error) {
+    var access_code = document.getElementById('AccessCode');
+    if (access_code.value && access_code.value != "") {
+      setElementDisplay("errormsg_0_AccessCode", 'block');
+      showAccessCodeRequired();
+    } else {
+      setElementDisplay("errormsg_1_Password", 'table-row');
+    }
+    setBlurbError(args.error_message);
+  } else if (3 == args.error) {
+    setElementDisplay("errormsg_0_Connection", 'table-row');
+    setBlurbError(args.error_message);
+  } else if (4 == args.error) {
+    showCaptcha(args);
+  } else if (8 == args.error) {
+    showAccessCodeRequired();
+  } else if (args.error_message) {
+    setBlurbError(args.error_message);
+  }
+
+  document.getElementById("signIn").disabled = false;
+  document.getElementById("signIn").value = templateData['signin'];
+  gaia_setFocus();
+}
+
+function showCaptcha(args) {
+  g_is_captcha_challenge_active = true;
+
+  // The captcha takes up lots of space, so make room.
+  setElementDisplay("top_blurb", "none");
+  setElementDisplay("top_blurb_error", "none");
+  setElementDisplay("createaccountdiv", "none");
+  var gaiaTable = document.getElementById('gaia_table');
+  gaiaTable.cellPadding = 0;
+  gaiaTable.cellSpacing = 1;
+  document.getElementById('createaccountcell').height = 0;
+
+  // It's showtime for the captcha now.
+  setElementDisplay("captchadiv", "block");
+  document.getElementById('Email').disabled = true;
+  document.getElementById('Passwd').disabled = false;
+  document.getElementById('CaptchaValue').disabled = false;
+  document.getElementById('captcha_wrapper').style.backgroundImage =
+      url(args.captchaUrl);
+}
+
+function showAccessCodeRequired() {
+  setElementDisplay("password_row", "none");
+  setElementDisplay("email_row", "none");
+  document.getElementById("createaccountcell").style.visibility =
+      "hidden";
+
+  setElementDisplay("access_code_label_row", "table-row");
+  setElementDisplay("access_code_input_row", "table-row");
+  setElementDisplay("access_code_help_row", "table-row");
+  document.getElementById('AccessCode').disabled = false;
+}
+
+function CloseDialog() {
+  chrome.send("DialogClose", [""]);
+}
+
+function showGaiaSuccessAndClose() {
+  document.getElementById("signIn").value = templateData['success'];
+  setTimeout(CloseDialog, 1600);
+}
+
+function showGaiaSuccessAndSettingUp() {
+  document.getElementById("signIn").value = templateData['settingup'];
+}
+
+/**
+ * DOMContentLoaded handler, sets up the page.
+ */
+function load() {
+  var acct_text = document.getElementById("gaia_account_text");
+  var translated_text = acct_text.textContent;
+  var posGoogle = translated_text.indexOf('Google');
+  if (posGoogle != -1) {
+    var ltr = templateData['textdirection'] == 'ltr';
+    var googleIsAtEndOfSentence = posGoogle != 0;
+    if (googleIsAtEndOfSentence == ltr) {
+      // We're in ltr and in the translation the word 'Google' is AFTER the
+      // word 'Account' OR we're in rtl and 'Google' is BEFORE 'Account'.
+      var logo_td = document.getElementById('gaia_logo');
+      logo_td.parentNode.appendChild(logo_td);
+    }
+    acct_text.textContent = translated_text.replace('Google','');
+  }
+
+  var loginForm = document.getElementById("gaia_loginform");
+  loginForm.onsubmit = function() {
+    sendCredentialsAndClose();
+    return false;
+  };
+
+  var gaiaCancel = document.getElementById("gaia-cancel");
+  gaiaCancel.onclick = function() {
+    CloseDialog();
+  };
+
+  var args = JSON.parse(chrome.dialogArguments);
+  showGaiaLogin(args);
+}
+
+function sendCredentialsAndClose() {
+  if (!setErrorVisibility())
+    return false;
+
+  document.getElementById('Email').disabled = true;
+  document.getElementById('Passwd').disabled = true;
+  document.getElementById('CaptchaValue').disabled = true;
+  document.getElementById('AccessCode').disabled = true;
+
+  document.getElementById('logging_in_throbber').style.display = "block";
+
+  var f = document.getElementById("gaia_loginform");
+  var result = JSON.stringify({"user" : f.Email.value,
+                               "pass" : f.Passwd.value,
+                               "captcha" : f.CaptchaValue.value,
+                               "access_code" : f.AccessCode.value});
+  document.getElementById("signIn").disabled = true;
+  chrome.send("SubmitAuth", [result]);
+}
+
+function setElementDisplay(id, display) {
+  var d = document.getElementById(id);
+  if (d)
+    d.style.display = display;
+}
+
+function hideBlurb() {
+  setElementDisplay('top_blurb', 'none');
+}
+
+function setBlurbError(error_message) {
+  if (g_is_captcha_challenge_active)
+    return;  // No blurb in captcha challenge mode.
+  if (error_message) {
+    document.getElementById('error_signing_in').style.display = 'none';
+    document.getElementById('error_custom').style.display = 'inline';
+    document.getElementById('error_custom').textContent = error_message;
+  } else {
+    document.getElementById('error_signing_in').style.display = 'inline';
+    document.getElementById('error_custom').style.display = 'none';
+  }
+  document.getElementById("top_blurb_error").style.visibility = "visible";
+  document.getElementById('Email').disabled = false;
+  document.getElementById('Passwd').disabled = false;
+}
+
+function resetErrorVisibility() {
+  setElementDisplay("errormsg_0_Email", 'none');
+  setElementDisplay("errormsg_0_Password", 'none');
+  setElementDisplay("errormsg_1_Password", 'none');
+  setElementDisplay("errormsg_0_Connection", 'none');
+  setElementDisplay("errormsg_0_AccessCode", 'none');
+}
+
+function setErrorVisibility() {
+  resetErrorVisibility();
+  var f = document.getElementById("gaia_loginform");
+  if (null == f.Email.value || "" == f.Email.value) {
+    setElementDisplay("errormsg_0_Email", 'table-row');
+    setBlurbError();
+    return false;
+  }
+  if (null == f.Passwd.value || "" == f.Passwd.value) {
+    setElementDisplay("errormsg_0_Password", 'table-row');
+    setBlurbError();
+    return false;
+  }
+  if (!f.AccessCode.disabled && (null == f.AccessCode.value ||
+      "" == f.AccessCode.value)) {
+    setElementDisplay("errormsg_0_Password", 'table-row');
+    return false;
+  }
+  return true;
+}
+
+function onPreCreateAccount() {
+  return true;
+}
+
+function onPreLogin() {
+  if (window["onlogin"] != null) {
+    return onlogin();
+  } else {
+    return true;
+  }
+}
+
+document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/sync/resources/passphrase.html b/chrome/browser/sync/resources/passphrase.html
index 4ea8317..e92df66 100644
--- a/chrome/browser/sync/resources/passphrase.html
+++ b/chrome/browser/sync/resources/passphrase.html
@@ -3,7 +3,7 @@
 <title></title>
 <style type="text/css">
 body {
-   line-height: 1.5em;
+   line-height: 1.4em;
    background: #FFFFFF;
    font-size: 11pt;
 }
@@ -19,8 +19,9 @@
   font-weight: bold;
   margin-bottom: 10px;
 }
-.sync-instructions {
+.sync-instructions-start-hidden {
   margin-top: 10px;
+  display: none;
 }
 .sync-footer {
   position: fixed;
@@ -44,17 +45,40 @@
 html[os='mac'] input[type='submit'] {
   font-size: 12pt;
 }
-
-#new-passphrase,
-#enter-passphrase {
-  display: none;
+#passphrase-input {
+  margin-top: 20px;
+  margin-bottom: 20px;
 }
-
+#incorrectPassphrase {
+  margin-top: 5px;
+}
+.error {
+  color: red;
+}
+.overlay-warning {
+  position: absolute;
+  display: none;
+  left: 25px;
+  right: 25px;
+  top: 100px;
+  background: white;
+  border: 2px solid #888;
+  border-radius: 8px;
+  padding: 15px;
+  box-shadow: 0.2em 0.2em 0.5em #888;
+}
+#cancel-warning-header {
+  font-weight: bold;
+  margin-bottom: 8px;
+}
+.overlay-warning INPUT {
+  margin-top: 12px;
+  float: right;
+  margin-left: 5px;
+}
 </style>
 <script src="chrome://resources/js/cr.js"></script>
 <script>

-  var currentMode;
-
   // Called once, when this html/js is loaded.
   function setupPassphraseDialog(args) {
     // Allow platform specific rules
@@ -64,59 +88,56 @@
       document.documentElement.setAttribute('os', 'linux');
     }
 
-    if (args) {
-      currentMode = args['mode'];
-      switchToMode(currentMode);
-    }
-  }
+    document.getElementById("passphraseRejectedBody").style.display = "none";
+    document.getElementById("normalBody").style.display = "none";
+    document.getElementById("incorrectPassphrase").style.display = "none";
 
-  function switchToMode(mode) {
-    if (mode == "new") {
-      document.getElementById("enter-passphrase").style.display = "none";
-      document.getElementById("gaia-passphrase").style.display = "none";
-      document.getElementById("new-passphrase").style.display = "block";
-    } else if (mode =="enter") {
-      document.getElementById("enter-passphrase").style.display = "block";
-      document.getElementById("gaia-passphrase").style.display = "none";
-      document.getElementById("new-passphrase").style.display = "none";
-    } else if (mode == "gaia") {
-      document.getElementById("enter-passphrase").style.display = "none";
-      document.getElementById("gaia-passphrase").style.display = "block";
-      document.getElementById("new-passphrase").style.display = "none";
+    if (args["passphrase_creation_rejected"]) {
+      document.getElementById("passphraseRejectedBody").style.display = "block";
+    } else {
+      document.getElementById("normalBody").style.display = "block";
+    }
+
+    if (args["passphrase_setting_rejected"]) {
+      document.getElementById("incorrectPassphrase").style.display = "block";
     }
   }
 
   function sendPassphraseAndClose() {
     var f = document.getElementById("passphraseForm");
-    var result = JSON.stringify({"passphrase": f.passphrase.value,
-                                 "mode": currentMode});
+    var result = JSON.stringify({"passphrase": f.passphrase.value});
     chrome.send("Passphrase", [result]);
   }
+
+  function showCancelWarning() {
+    document.getElementById("cancel-warning-box").style.display = "block";
+    document.getElementById("okButton").disabled = true;
+    document.getElementById("cancelButton").disabled = true;
+  }
+
+  function hideCancelWarning() {
+    document.getElementById("cancel-warning-box").style.display = "none";
+    document.getElementById("okButton").disabled = false;
+    document.getElementById("cancelButton").disabled = false;
+  }
+
+  function goToDashboard() {
+    chrome.send("GoToDashboard", [""]);
+    chrome.send("DialogClose", [""]);
+  }
 </script>
 </head>
 <body i18n-values=".style.fontFamily:fontfamily"
-      onload="setupPassphraseDialog();">
-<form id="passphraseForm" 
+      onload="setupPassphraseDialog(JSON.parse(chrome.dialogArguments));">
+<form id="passphraseForm"
       onSubmit="sendPassphraseAndClose(); return false;">
-  <div id="new-passphrase">
-    <div class="sync-header" id="newTitle"
-         i18n-content="newPassphraseTitle"></div>
-    <div class="sync-instructions" id="newInstructions"
-         i18n-content="newPassphraseBody"></div>
-  </div>
-
   <div id="enter-passphrase">
     <div class="sync-header" id="enterTitle"
          i18n-content="enterPassphraseTitle"></div>
-    <div class="sync-instructions" id="enterInstructions"
+    <div class="sync-instructions-start-hidden" id="normalBody"
          i18n-content="enterPassphraseBody"></div>
-  </div>
-
-  <div id="gaia-passphrase">
-    <div class="sync-header" id="gaiaTitle"
-         i18n-content="gaiaPassphraseTitle"></div>
-    <div class="sync-instructions" id="gaiaInstructions"
-         i18n-content="gaiaPassphraseBody"></div>
+    <div class="sync-instructions-start-hidden" id="passphraseRejectedBody"
+         i18n-content="enterOtherPassphraseBody"></div>
   </div>
 
   <div id="passphrase-input">
@@ -124,12 +145,28 @@
            for="passphrase" i18n-content="passphraseLabel">
     </label>
     <input id="passphrase" name="passphrase" type="password" />
-  </div> 
+    <div class="error" id="incorrectPassphrase"
+         i18n-content="incorrectPassphrase">
+    </div>
+  </div>
+
+  <span id="sync-passphrase-warning" i18n-content="passphraseRecover">
+  </span> <a id="clear-data-link" i18n-content="cleardatalink" href="#"
+     onclick="goToDashboard(); return false;"></a>
+
+  <div class="overlay-warning" id="cancel-warning-box">
+    <div id="cancel-warning-header" i18n-content="cancelWarningHeader"></div>
+    <div id="cancel-warning" i18n-content="cancelWarning"></div>
+    <input id="cancel-no-button" type="submit" i18n-values="value:no"
+           onclick="hideCancelWarning(); return false;" />
+    <input id="cancel-yes-button" type="submit" i18n-values="value:yes"
+           onclick="chrome.send('PassphraseCancel', ['']);" />
+  </div>
 
   <div class="sync-footer">
     <input id="okButton" type="submit" i18n-values="value:ok" />
     <input id="cancelButton" type="button" i18n-values="value:cancel"
-           onclick='chrome.send("DialogClose", [""])' />
+           onclick="showCancelWarning(); return false;" />
   </div>
 </form>
 </body>
diff --git a/chrome/browser/sync/resources/setting_up.html b/chrome/browser/sync/resources/setting_up.html
index 02f5bd3..fc258f3 100644
--- a/chrome/browser/sync/resources/setting_up.html
+++ b/chrome/browser/sync/resources/setting_up.html
@@ -36,13 +36,8 @@
 html[os='mac'] input[type='submit'] {
   font-size: 12pt;
 }
-#throb {
-  background-image: url("../../../../app/resources/throbber.png");
-  width: 16px;
-  height: 16px;
-  background-position: 0px;
+#throbber {
   margin: -3px 10px;
-  display: inline-block;
 }
 #setting_up {
   margin: 100px;
@@ -55,23 +50,13 @@
 }
 
 </style>
+<link rel="stylesheet" href="chrome://resources/css/throbber.css">
 <script src="chrome://resources/js/cr.js"></script>
-<script>
-  function advanceThrobber() {
-    var throbber = document.getElementById('throb');
-    throbber.style.backgroundPositionX =
-        ((parseInt(getComputedStyle(throbber).backgroundPositionX) - 16) %
-        576) + 'px';
-  }
-  setInterval(advanceThrobber, 30);
-</script>
 </head>
 <body i18n-values=".style.fontFamily:fontfamily">
 <form id="settingUpForm" onSubmit="return false;">
   <div id="setting_up">
-    <span id="throbber_container">
-      <span id="throb"></span>
-    </span>
+    <div id="throbber" class="throbber"></div>
     <div id="setting_up_label" i18n-content="settingup"></div>
   </div>
   <div class="sync-footer">
diff --git a/chrome/browser/sync/sessions/session_state.cc b/chrome/browser/sync/sessions/session_state.cc
index 644d2f6..e52ebdc 100644
--- a/chrome/browser/sync/sessions/session_state.cc
+++ b/chrome/browser/sync/sessions/session_state.cc
@@ -7,39 +7,199 @@
 #include <set>
 #include <vector>
 
+#include "base/base64.h"
+#include "base/values.h"
+#include "chrome/browser/sync/protocol/proto_enum_conversions.h"
+
 using std::set;
 using std::vector;
 
 namespace browser_sync {
 namespace sessions {
 
+TypePayloadMap MakeTypePayloadMapFromBitSet(
+    const syncable::ModelTypeBitSet& types,
+    const std::string& payload) {
+  TypePayloadMap types_with_payloads;
+  for (size_t i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < types.size(); ++i) {
+    if (types[i]) {
+      types_with_payloads[syncable::ModelTypeFromInt(i)] = payload;
+    }
+  }
+  return types_with_payloads;
+}
+
+TypePayloadMap MakeTypePayloadMapFromRoutingInfo(
+    const ModelSafeRoutingInfo& routes,
+    const std::string& payload) {
+  TypePayloadMap types_with_payloads;
+  for (ModelSafeRoutingInfo::const_iterator i = routes.begin();
+       i != routes.end(); ++i) {
+    types_with_payloads[i->first] = payload;
+  }
+  return types_with_payloads;
+}
+
+DictionaryValue* TypePayloadMapToValue(const TypePayloadMap& type_payloads) {
+  DictionaryValue* value = new DictionaryValue();
+  for (TypePayloadMap::const_iterator it = type_payloads.begin();
+       it != type_payloads.end(); ++it) {
+    value->SetString(syncable::ModelTypeToString(it->first), it->second);
+  }
+  return value;
+}
+
+void CoalescePayloads(TypePayloadMap* original,
+                      const TypePayloadMap& update) {
+  for (TypePayloadMap::const_iterator i = update.begin();
+       i != update.end(); ++i) {
+    if (original->count(i->first) == 0) {
+      // If this datatype isn't already in our map, add it with whatever payload
+      // it has.
+      (*original)[i->first] = i->second;
+    } else if (i->second.length() > 0) {
+      // If this datatype is already in our map, we only overwrite the payload
+      // if the new one is non-empty.
+      (*original)[i->first] = i->second;
+    }
+  }
+}
+
+SyncSourceInfo::SyncSourceInfo()
+    : updates_source(sync_pb::GetUpdatesCallerInfo::UNKNOWN) {}
+
+SyncSourceInfo::SyncSourceInfo(
+    const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& u,
+    const TypePayloadMap& t)
+    : updates_source(u), types(t) {}
+
+SyncSourceInfo::~SyncSourceInfo() {}
+
+DictionaryValue* SyncSourceInfo::ToValue() const {
+  DictionaryValue* value = new DictionaryValue();
+  value->SetString("updatesSource",
+                   GetUpdatesSourceString(updates_source));
+  value->Set("types", TypePayloadMapToValue(types));
+  return value;
+}
+
+SyncerStatus::SyncerStatus()
+    : invalid_store(false),
+      syncer_stuck(false),
+      syncing(false),
+      num_successful_commits(0),
+      num_successful_bookmark_commits(0),
+      num_updates_downloaded_total(0),
+      num_tombstone_updates_downloaded_total(0) {
+}
+
+DictionaryValue* SyncerStatus::ToValue() const {
+  DictionaryValue* value = new DictionaryValue();
+  value->SetBoolean("invalidStore", invalid_store);
+  value->SetBoolean("syncerStuck", syncer_stuck);
+  value->SetBoolean("syncing", syncing);
+  value->SetInteger("numSuccessfulCommits", num_successful_commits);
+  value->SetInteger("numSuccessfulBookmarkCommits",
+                num_successful_bookmark_commits);
+  value->SetInteger("numUpdatesDownloadedTotal",
+                num_updates_downloaded_total);
+  value->SetInteger("numTombstoneUpdatesDownloadedTotal",
+                num_tombstone_updates_downloaded_total);
+  return value;
+}
+
+DictionaryValue* DownloadProgressMarkersToValue(
+    const std::string
+        (&download_progress_markers)[syncable::MODEL_TYPE_COUNT]) {
+  DictionaryValue* value = new DictionaryValue();
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT; ++i) {
+    // TODO(akalin): Unpack the value into a protobuf.
+    std::string base64_marker;
+    bool encoded =
+        base::Base64Encode(download_progress_markers[i], &base64_marker);
+    DCHECK(encoded);
+    value->SetString(
+        syncable::ModelTypeToString(syncable::ModelTypeFromInt(i)),
+        base64_marker);
+  }
+  return value;
+}
+
+ErrorCounters::ErrorCounters()
+    : num_conflicting_commits(0),
+      consecutive_transient_error_commits(0),
+      consecutive_errors(0) {
+}
+
+DictionaryValue* ErrorCounters::ToValue() const {
+  DictionaryValue* value = new DictionaryValue();
+  value->SetInteger("numConflictingCommits", num_conflicting_commits);
+  value->SetInteger("consecutiveTransientErrorCommits",
+                consecutive_transient_error_commits);
+  value->SetInteger("consecutiveErrors", consecutive_errors);
+  return value;
+}
+
 SyncSessionSnapshot::SyncSessionSnapshot(
     const SyncerStatus& syncer_status,
     const ErrorCounters& errors,
     int64 num_server_changes_remaining,
-    int64 max_local_timestamp,
     bool is_share_usable,
     const syncable::ModelTypeBitSet& initial_sync_ended,
+    const std::string
+        (&download_progress_markers)[syncable::MODEL_TYPE_COUNT],
     bool more_to_sync,
     bool is_silenced,
     int64 unsynced_count,
     int num_conflicting_updates,
-    bool did_commit_items)
+    bool did_commit_items,
+    const SyncSourceInfo& source)
     : syncer_status(syncer_status),
       errors(errors),
       num_server_changes_remaining(num_server_changes_remaining),
-      max_local_timestamp(max_local_timestamp),
       is_share_usable(is_share_usable),
       initial_sync_ended(initial_sync_ended),
+      download_progress_markers(),
       has_more_to_sync(more_to_sync),
       is_silenced(is_silenced),
       unsynced_count(unsynced_count),
       num_conflicting_updates(num_conflicting_updates),
-      did_commit_items(did_commit_items) {
+      did_commit_items(did_commit_items),
+      source(source) {
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT; ++i) {
+    const_cast<std::string&>(this->download_progress_markers[i]).assign(
+        download_progress_markers[i]);
+  }
 }
 
 SyncSessionSnapshot::~SyncSessionSnapshot() {}
 
+DictionaryValue* SyncSessionSnapshot::ToValue() const {
+  DictionaryValue* value = new DictionaryValue();
+  value->Set("syncerStatus", syncer_status.ToValue());
+  value->Set("errors", errors.ToValue());
+  // We don't care too much if we lose precision here.
+  value->SetInteger("numServerChangesRemaining",
+                    static_cast<int>(num_server_changes_remaining));
+  value->SetBoolean("isShareUsable", is_share_usable);
+  value->Set("initialSyncEnded",
+             syncable::ModelTypeBitSetToValue(initial_sync_ended));
+  value->Set("downloadProgressMarkers",
+             DownloadProgressMarkersToValue(download_progress_markers));
+  value->SetBoolean("hasMoreToSync", has_more_to_sync);
+  value->SetBoolean("isSilenced", is_silenced);
+  // We don't care too much if we lose precision here, also.
+  value->SetInteger("unsyncedCount",
+                    static_cast<int>(unsynced_count));
+  value->SetInteger("numConflictingUpdates", num_conflicting_updates);
+  value->SetBoolean("didCommitItems", did_commit_items);
+  value->Set("source", source.ToValue());
+  return value;
+}
+
 ConflictProgress::ConflictProgress(bool* dirty_flag) : dirty_(dirty_flag) {}
 
 ConflictProgress::~ConflictProgress() {
@@ -238,12 +398,5 @@
 PerModelSafeGroupState::~PerModelSafeGroupState() {
 }
 
-PerModelTypeState::PerModelTypeState(bool* dirty_flag)
-    : current_download_timestamp(dirty_flag, 0) {
-}
-
-PerModelTypeState::~PerModelTypeState() {
-}
-
 }  // namespace sessions
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/session_state.h b/chrome/browser/sync/sessions/session_state.h
index aca18dc..69fbf7a 100644
--- a/chrome/browser/sync/sessions/session_state.h
+++ b/chrome/browser/sync/sessions/session_state.h
@@ -23,6 +23,8 @@
 #include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/sync/syncable/syncable.h"
 
+class DictionaryValue;
+
 namespace syncable {
 class DirectoryManager;
 }
@@ -32,12 +34,52 @@
 
 class UpdateProgress;
 
+// A container that contains a set of datatypes with possible string payloads.
+typedef std::map<syncable::ModelType, std::string> TypePayloadMap;
+
+// Helper utils for building TypePayloadMaps.
+// Make a TypePayloadMap from all the types in a ModelTypeBitSet using a
+// default payload.
+TypePayloadMap MakeTypePayloadMapFromBitSet(
+    const syncable::ModelTypeBitSet& types,
+    const std::string& payload);
+
+// Make a TypePayloadMap for all the enabled types in a ModelSafeRoutingInfo
+// using a default payload.
+TypePayloadMap MakeTypePayloadMapFromRoutingInfo(
+    const ModelSafeRoutingInfo& routes,
+    const std::string& payload);
+
+// Caller takes ownership of the returned dictionary.
+DictionaryValue* TypePayloadMapToValue(const TypePayloadMap& type_payloads);
+
+// Coalesce |update| into |original|, overwriting only when |update| has
+// a non-empty payload.
+void CoalescePayloads(TypePayloadMap* original, const TypePayloadMap& update);
+
+// A container for the source of a sync session. This includes the update
+// source, the datatypes triggering the sync session, and possible session
+// specific payloads which should be sent to the server.
+struct SyncSourceInfo {
+  SyncSourceInfo();
+  SyncSourceInfo(
+      const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& u,
+      const TypePayloadMap& t);
+  ~SyncSourceInfo();
+
+  // Caller takes ownership of the returned dictionary.
+  DictionaryValue* ToValue() const;
+
+  sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source;
+  TypePayloadMap types;
+};
+
 // Data pertaining to the status of an active Syncer object.
 struct SyncerStatus {
-  SyncerStatus()
-      : invalid_store(false), syncer_stuck(false),
-        syncing(false), num_successful_commits(0),
-        num_successful_bookmark_commits(0) {}
+  SyncerStatus();
+
+  // Caller takes ownership of the returned dictionary.
+  DictionaryValue* ToValue() const;
 
   // True when we get such an INVALID_STORE error from the server.
   bool invalid_store;
@@ -47,13 +89,19 @@
   int num_successful_commits;
   // This is needed for monitoring extensions activity.
   int num_successful_bookmark_commits;
+
+  // Download event counters.
+  int num_updates_downloaded_total;
+  int num_tombstone_updates_downloaded_total;
 };
 
 // Counters for various errors that can occur repeatedly during a sync session.
 struct ErrorCounters {
-  ErrorCounters() : num_conflicting_commits(0),
-                    consecutive_transient_error_commits(0),
-                    consecutive_errors(0) {}
+  ErrorCounters();
+
+  // Caller takes ownership of the returned dictionary.
+  DictionaryValue* ToValue() const;
+
   int num_conflicting_commits;
 
   // Number of commits hitting transient errors since the last successful
@@ -66,33 +114,45 @@
   int consecutive_errors;
 };
 
+// Caller takes ownership of the returned dictionary.
+DictionaryValue* DownloadProgressMarkersToValue(
+    const std::string
+        (&download_progress_markers)[syncable::MODEL_TYPE_COUNT]);
+
 // An immutable snapshot of state from a SyncSession.  Convenient to use as
 // part of notifications as it is inherently thread-safe.
 struct SyncSessionSnapshot {
-  SyncSessionSnapshot(const SyncerStatus& syncer_status,
+  SyncSessionSnapshot(
+      const SyncerStatus& syncer_status,
       const ErrorCounters& errors,
       int64 num_server_changes_remaining,
-      int64 max_local_timestamp,
       bool is_share_usable,
       const syncable::ModelTypeBitSet& initial_sync_ended,
+      const std::string
+          (&download_progress_markers)[syncable::MODEL_TYPE_COUNT],
       bool more_to_sync,
       bool is_silenced,
       int64 unsynced_count,
       int num_conflicting_updates,
-                      bool did_commit_items);
+      bool did_commit_items,
+      const SyncSourceInfo& source);
   ~SyncSessionSnapshot();
 
+  // Caller takes ownership of the returned dictionary.
+  DictionaryValue* ToValue() const;
+
   const SyncerStatus syncer_status;
   const ErrorCounters errors;
   const int64 num_server_changes_remaining;
-  const int64 max_local_timestamp;
   const bool is_share_usable;
   const syncable::ModelTypeBitSet initial_sync_ended;
+  const std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
   const bool has_more_to_sync;
   const bool is_silenced;
   const int64 unsynced_count;
   const int num_conflicting_updates;
   const bool did_commit_items;
+  const SyncSourceInfo source;
 };
 
 // Tracks progress of conflicts and their resolution using conflict sets.
@@ -233,7 +293,7 @@
   ClientToServerResponse commit_response;
   // We GetUpdates for some combination of types at once.
   // requested_update_types stores the set of types which were requested.
-  syncable::MultiTypeTimeStamp updates_request_parameters;
+  syncable::ModelTypeBitSet updates_request_types;
   ClientToServerResponse updates_response;
   // Used to build the shared commit message.
   DirtyOnWrite<std::vector<int64> > unsynced_handles;
@@ -253,14 +313,6 @@
   ConflictProgress conflict_progress;
 };
 
-// Grouping of all state that applies to a single ModelType.
-struct PerModelTypeState {
-  explicit PerModelTypeState(bool* dirty_flag);
-  ~PerModelTypeState();
-
-  DirtyOnWrite<int64> current_download_timestamp;
-};
-
 }  // namespace sessions
 }  // namespace browser_sync
 
diff --git a/chrome/browser/sync/sessions/session_state_unittest.cc b/chrome/browser/sync/sessions/session_state_unittest.cc
new file mode 100644
index 0000000..3ac832f
--- /dev/null
+++ b/chrome/browser/sync/sessions/session_state_unittest.cc
@@ -0,0 +1,191 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/sessions/session_state.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/test/values_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace sessions {
+namespace {
+
+using test::ExpectBooleanValue;
+using test::ExpectDictionaryValue;
+using test::ExpectIntegerValue;
+using test::ExpectListValue;
+using test::ExpectStringValue;
+
+class SessionStateTest : public testing::Test {};
+
+TEST_F(SessionStateTest, TypePayloadMapToValue) {
+  TypePayloadMap payloads;
+  payloads[syncable::BOOKMARKS] = "bookmarkpayload";
+  payloads[syncable::APPS] = "";
+
+  scoped_ptr<DictionaryValue> value(TypePayloadMapToValue(payloads));
+  EXPECT_EQ(2u, value->size());
+  ExpectStringValue("bookmarkpayload", *value, "Bookmarks");
+  ExpectStringValue("", *value, "Apps");
+  EXPECT_FALSE(value->HasKey("Preferences"));
+}
+
+TEST_F(SessionStateTest, SyncSourceInfoToValue) {
+  sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source =
+      sync_pb::GetUpdatesCallerInfo::PERIODIC;
+  TypePayloadMap types;
+  types[syncable::PREFERENCES] = "preferencespayload";
+  types[syncable::EXTENSIONS] = "";
+  scoped_ptr<DictionaryValue> expected_types_value(
+      TypePayloadMapToValue(types));
+
+  SyncSourceInfo source_info(updates_source, types);
+
+  scoped_ptr<DictionaryValue> value(source_info.ToValue());
+  EXPECT_EQ(2u, value->size());
+  ExpectStringValue("PERIODIC", *value, "updatesSource");
+  ExpectDictionaryValue(*expected_types_value, *value, "types");
+}
+
+TEST_F(SessionStateTest, SyncerStatusToValue) {
+  SyncerStatus status;
+  status.invalid_store = true;
+  status.syncer_stuck = false;
+  status.syncing = true;
+  status.num_successful_commits = 5;
+  status.num_successful_bookmark_commits = 10;
+  status.num_updates_downloaded_total = 100;
+  status.num_tombstone_updates_downloaded_total = 200;
+
+  scoped_ptr<DictionaryValue> value(status.ToValue());
+  EXPECT_EQ(7u, value->size());
+  ExpectBooleanValue(status.invalid_store, *value, "invalidStore");
+  ExpectBooleanValue(status.syncer_stuck, *value, "syncerStuck");
+  ExpectBooleanValue(status.syncing, *value, "syncing");
+  ExpectIntegerValue(status.num_successful_commits,
+                     *value, "numSuccessfulCommits");
+  ExpectIntegerValue(status.num_successful_bookmark_commits,
+                     *value, "numSuccessfulBookmarkCommits");
+  ExpectIntegerValue(status.num_updates_downloaded_total,
+                     *value, "numUpdatesDownloadedTotal");
+  ExpectIntegerValue(status.num_tombstone_updates_downloaded_total,
+                     *value, "numTombstoneUpdatesDownloadedTotal");
+}
+
+TEST_F(SessionStateTest, ErrorCountersToValue) {
+  ErrorCounters counters;
+  counters.num_conflicting_commits = 1;
+  counters.consecutive_transient_error_commits = 5;
+  counters.consecutive_errors = 3;
+
+  scoped_ptr<DictionaryValue> value(counters.ToValue());
+  EXPECT_EQ(3u, value->size());
+  ExpectIntegerValue(counters.num_conflicting_commits,
+                     *value, "numConflictingCommits");
+  ExpectIntegerValue(counters.consecutive_transient_error_commits,
+                     *value, "consecutiveTransientErrorCommits");
+  ExpectIntegerValue(counters.consecutive_errors,
+                     *value, "consecutiveErrors");
+}
+
+TEST_F(SessionStateTest, DownloadProgressMarkersToValue) {
+  std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT; ++i) {
+    std::string marker(i, i);
+    download_progress_markers[i] = marker;
+  }
+
+  scoped_ptr<DictionaryValue> value(
+      DownloadProgressMarkersToValue(download_progress_markers));
+  EXPECT_EQ(syncable::MODEL_TYPE_COUNT - syncable::FIRST_REAL_MODEL_TYPE,
+            static_cast<int>(value->size()));
+  for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+       i < syncable::MODEL_TYPE_COUNT; ++i) {
+    syncable::ModelType model_type = syncable::ModelTypeFromInt(i);
+    std::string marker(i, i);
+    std::string expected_value;
+    EXPECT_TRUE(base::Base64Encode(marker, &expected_value));
+    ExpectStringValue(expected_value,
+                      *value, syncable::ModelTypeToString(model_type));
+  }
+}
+
+TEST_F(SessionStateTest, SyncSessionSnapshotToValue) {
+  SyncerStatus syncer_status;
+  syncer_status.num_successful_commits = 500;
+  scoped_ptr<DictionaryValue> expected_syncer_status_value(
+      syncer_status.ToValue());
+
+  ErrorCounters errors;
+  errors.num_conflicting_commits = 250;
+  scoped_ptr<DictionaryValue> expected_errors_value(
+      errors.ToValue());
+
+  const int kNumServerChangesRemaining = 105;
+  const bool kIsShareUsable = true;
+
+  syncable::ModelTypeBitSet initial_sync_ended;
+  initial_sync_ended.set(syncable::BOOKMARKS);
+  initial_sync_ended.set(syncable::PREFERENCES);
+  scoped_ptr<ListValue> expected_initial_sync_ended_value(
+      syncable::ModelTypeBitSetToValue(initial_sync_ended));
+
+  std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
+  download_progress_markers[syncable::BOOKMARKS] = "test";
+  download_progress_markers[syncable::APPS] = "apps";
+  scoped_ptr<DictionaryValue> expected_download_progress_markers_value(
+      DownloadProgressMarkersToValue(download_progress_markers));
+
+  const bool kHasMoreToSync = false;
+  const bool kIsSilenced = true;
+  const int kUnsyncedCount = 1053;
+  const int kNumConflictingUpdates = 1055;
+  const bool kDidCommitItems = true;
+
+  SyncSourceInfo source;
+  scoped_ptr<DictionaryValue> expected_source_value(source.ToValue());
+
+  SyncSessionSnapshot snapshot(syncer_status,
+                               errors,
+                               kNumServerChangesRemaining,
+                               kIsShareUsable,
+                               initial_sync_ended,
+                               download_progress_markers,
+                               kHasMoreToSync,
+                               kIsSilenced,
+                               kUnsyncedCount,
+                               kNumConflictingUpdates,
+                               kDidCommitItems,
+                               source);
+  scoped_ptr<DictionaryValue> value(snapshot.ToValue());
+  EXPECT_EQ(12u, value->size());
+  ExpectDictionaryValue(*expected_syncer_status_value, *value,
+                        "syncerStatus");
+  ExpectDictionaryValue(*expected_errors_value, *value, "errors");
+  ExpectIntegerValue(kNumServerChangesRemaining, *value,
+                     "numServerChangesRemaining");
+  ExpectBooleanValue(kIsShareUsable, *value, "isShareUsable");
+  ExpectListValue(*expected_initial_sync_ended_value, *value,
+                  "initialSyncEnded");
+  ExpectDictionaryValue(*expected_download_progress_markers_value,
+                        *value, "downloadProgressMarkers");
+  ExpectBooleanValue(kHasMoreToSync, *value, "hasMoreToSync");
+  ExpectBooleanValue(kIsSilenced, *value, "isSilenced");
+  ExpectIntegerValue(kUnsyncedCount, *value, "unsyncedCount");
+  ExpectIntegerValue(kNumConflictingUpdates, *value,
+                     "numConflictingUpdates");
+  ExpectBooleanValue(kDidCommitItems, *value,
+                     "didCommitItems");
+  ExpectDictionaryValue(*expected_source_value, *value, "source");
+}
+
+}  // namespace
+}  // namespace sessions
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/status_controller.cc b/chrome/browser/sync/sessions/status_controller.cc
index 7c1602d..c8d6866 100644
--- a/chrome/browser/sync/sessions/status_controller.cc
+++ b/chrome/browser/sync/sessions/status_controller.cc
@@ -16,7 +16,6 @@
 StatusController::StatusController(const ModelSafeRoutingInfo& routes)
     : shared_(&is_dirty_),
       per_model_group_deleter_(&per_model_group_),
-      per_model_type_deleter_(&per_model_type_),
       is_dirty_(false),
       group_restriction_in_effect_(false),
       group_restriction_(GROUP_PASSIVE),
@@ -42,26 +41,22 @@
   return per_model_group_[group];
 }
 
-PerModelTypeState* StatusController::GetOrCreateModelTypeState(
-    bool restrict, syncable::ModelType model) {
-  if (restrict) {
-    DCHECK(group_restriction_in_effect_) << "No group restriction in effect!";
-    DCHECK_EQ(group_restriction_, GetGroupForModelType(model, routing_info_));
-  }
-  if (per_model_type_.find(model) == per_model_type_.end()) {
-    PerModelTypeState* state = new PerModelTypeState(&is_dirty_);
-    per_model_type_[model] = state;
-    return state;
-  }
-  return per_model_type_[model];
-}
-
 void StatusController::increment_num_conflicting_commits_by(int value) {
   if (value == 0)
     return;
   shared_.error_counters.mutate()->num_conflicting_commits += value;
 }
 
+void StatusController::increment_num_updates_downloaded_by(int value) {
+  shared_.syncer_status.mutate()->num_updates_downloaded_total += value;
+}
+
+void StatusController::increment_num_tombstone_updates_downloaded_by(
+    int value) {
+  shared_.syncer_status.mutate()->num_tombstone_updates_downloaded_total +=
+      value;
+}
+
 void StatusController::reset_num_conflicting_commits() {
   if (shared_.error_counters.value().num_conflicting_commits != 0)
     shared_.error_counters.mutate()->num_conflicting_commits = 0;
@@ -87,14 +82,6 @@
     shared_.error_counters.mutate()->consecutive_errors = value;
 }
 
-void StatusController::set_current_download_timestamp(
-    syncable::ModelType model,
-    int64 current_timestamp) {
-  PerModelTypeState* state = GetOrCreateModelTypeState(false, model);
-  if (current_timestamp > state->current_download_timestamp.value())
-    *(state->current_download_timestamp.mutate()) = current_timestamp;
-}
-
 void StatusController::set_num_server_changes_remaining(
     int64 changes_remaining) {
   if (shared_.num_server_changes_remaining.value() != changes_remaining)
@@ -181,17 +168,6 @@
   return std::binary_search(proj.begin(), proj.end(), index);
 }
 
-int64 StatusController::ComputeMaxLocalTimestamp() const {
-  std::map<syncable::ModelType, PerModelTypeState*>::const_iterator it =
-      per_model_type_.begin();
-  int64 max_timestamp = 0;
-  for (; it != per_model_type_.end(); ++it) {
-    if (it->second->current_download_timestamp.value() > max_timestamp)
-      max_timestamp = it->second->current_download_timestamp.value();
-  }
-  return max_timestamp;
-}
-
 bool StatusController::HasConflictingUpdates() const {
   DCHECK(!group_restriction_in_effect_)
       << "HasConflictingUpdates applies to all ModelSafeGroups";
@@ -219,23 +195,14 @@
 bool StatusController::ServerSaysNothingMoreToDownload() const {
   if (!download_updates_succeeded())
     return false;
-  // If we didn't request every enabled datatype, then we can't say for
-  // sure that there's nothing left to download.
-  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
-    if (!updates_request_parameters().data_types[i] &&
-        routing_info_.count(syncable::ModelTypeFromInt(i)) != 0) {
-      return false;
-    }
+
+  if (!updates_response().get_updates().has_changes_remaining()) {
+    NOTREACHED();  // Server should always send changes remaining.
+    return false;  // Avoid looping forever.
   }
   // Changes remaining is an estimate, but if it's estimated to be
   // zero, that's firm and we don't have to ask again.
-  if (updates_response().get_updates().has_changes_remaining() &&
-      updates_response().get_updates().changes_remaining() == 0) {
-    return true;
-  }
-  // Otherwise, the server can also indicate "you're up to date"
-  // by not sending a new timestamp.
-  return !updates_response().get_updates().has_new_timestamp();
+  return updates_response().get_updates().changes_remaining() == 0;
 }
 
 }  // namespace sessions
diff --git a/chrome/browser/sync/sessions/status_controller.h b/chrome/browser/sync/sessions/status_controller.h
index 7663e4e..805ff28 100644
--- a/chrome/browser/sync/sessions/status_controller.h
+++ b/chrome/browser/sync/sessions/status_controller.h
@@ -10,13 +10,13 @@
 // set for the restricted ModelSafeGroup behind the scenes.  For example, if
 // GROUP_UI is set, then accessors such as conflict_progress() and commit_ids()
 // are implicitly restricted to returning only data pertaining to GROUP_UI.
-// You can see which parts of status fall into this "restricted" category, the
-// global "shared" category for all model types, or the single per-model type
-// category by looking at the struct declarations in session_state.h.
-// If these accessors are invoked without a restriction in place, this is a
-// violation and will cause debug assertions to surface improper use of the API
-// in development.  Likewise for invocation of "shared" accessors when a
-// restriction is in place; for safety's sake, an assertion will fire.
+// You can see which parts of status fall into this "restricted" category, or
+// the global "shared" category for all model types, by looking at the struct
+// declarations in session_state.h. If these accessors are invoked without a
+// restriction in place, this is a violation and will cause debug assertions
+// to surface improper use of the API in development.  Likewise for
+// invocation of "shared" accessors when a restriction is in place; for
+// safety's sake, an assertion will fire.
 //
 // NOTE: There is no concurrent access protection provided by this class. It
 // assumes one single thread is accessing this class for each unique
@@ -87,12 +87,11 @@
   ClientToServerResponse* mutable_commit_response() {
     return &shared_.commit_response;
   }
-  const syncable::MultiTypeTimeStamp& updates_request_parameters() const {
-    return shared_.updates_request_parameters;
+  const syncable::ModelTypeBitSet& updates_request_types() const {
+    return shared_.updates_request_types;
   }
-  void set_updates_request_parameters(
-      const syncable::MultiTypeTimeStamp& value) {
-    shared_.updates_request_parameters = value;
+  void set_updates_request_types(const syncable::ModelTypeBitSet& value) {
+    shared_.updates_request_types = value;
   }
   const ClientToServerResponse& updates_response() const {
     return shared_.updates_response;
@@ -113,8 +112,6 @@
   int64 num_server_changes_remaining() const {
     return shared_.num_server_changes_remaining.value();
   }
-  // Aggregate max over all data type timestamps, used for UI reporting.
-  int64 ComputeMaxLocalTimestamp() const;
 
   // Commit path data.
   const std::vector<syncable::Id>& commit_ids() const {
@@ -206,8 +203,6 @@
   void set_num_consecutive_errors(int value);
   void increment_num_consecutive_errors();
   void increment_num_consecutive_errors_by(int value);
-  void set_current_download_timestamp(syncable::ModelType model,
-                                      int64 current_timestamp);
   void set_num_server_changes_remaining(int64 changes_remaining);
   void set_invalid_store(bool invalid_store);
   void set_syncer_stuck(bool syncer_stuck);
@@ -215,6 +210,8 @@
   void set_num_successful_bookmark_commits(int value);
   void increment_num_successful_commits();
   void increment_num_successful_bookmark_commits();
+  void increment_num_updates_downloaded_by(int value);
+  void increment_num_tombstone_updates_downloaded_by(int value);
   void set_unsynced_handles(const std::vector<int64>& unsynced_handles);
 
   void set_commit_set(const OrderedCommitSet& commit_set);
@@ -233,18 +230,12 @@
   // Helper to lazily create objects for per-ModelSafeGroup state.
   PerModelSafeGroupState* GetOrCreateModelSafeGroupState(bool restrict,
                                                          ModelSafeGroup group);
-  // Helper to lazily create objects for per-model type state.
-  PerModelTypeState* GetOrCreateModelTypeState(bool restrict,
-                                               syncable::ModelType model);
 
   AllModelTypeState shared_;
   std::map<ModelSafeGroup, PerModelSafeGroupState*> per_model_group_;
-  std::map<syncable::ModelType, PerModelTypeState*> per_model_type_;
 
   STLValueDeleter<std::map<ModelSafeGroup, PerModelSafeGroupState*> >
       per_model_group_deleter_;
-  STLValueDeleter<std::map<syncable::ModelType, PerModelTypeState*> >
-      per_model_type_deleter_;
 
   // Set to true if any DirtyOnWrite pieces of state we maintain are changed.
   // Reset to false by TestAndClearIsDirty.
diff --git a/chrome/browser/sync/sessions/status_controller_unittest.cc b/chrome/browser/sync/sessions/status_controller_unittest.cc
index 88605bf..ba76f28 100644
--- a/chrome/browser/sync/sessions/status_controller_unittest.cc
+++ b/chrome/browser/sync/sessions/status_controller_unittest.cc
@@ -47,12 +47,6 @@
   status.increment_num_consecutive_errors_by(0);
   EXPECT_FALSE(status.TestAndClearIsDirty());
 
-  {
-    ScopedModelSafeGroupRestriction r(&status, GROUP_UI);
-    status.set_current_download_timestamp(syncable::BOOKMARKS, 100);
-    EXPECT_TRUE(status.TestAndClearIsDirty());
-  }
-
   status.set_num_server_changes_remaining(30);
   EXPECT_TRUE(status.TestAndClearIsDirty());
 
@@ -130,12 +124,6 @@
   status.increment_num_consecutive_errors_by(2);
   EXPECT_EQ(11, status.error_counters().consecutive_errors);
 
-  {
-    ScopedModelSafeGroupRestriction r(&status, GROUP_UI);
-    status.set_current_download_timestamp(syncable::BOOKMARKS, 12);
-    EXPECT_EQ(12, status.ComputeMaxLocalTimestamp());
-  }
-
   status.set_num_server_changes_remaining(13);
   EXPECT_EQ(13, status.num_server_changes_remaining());
 
@@ -226,7 +214,6 @@
   status.error_counters();
   status.syncer_status();
   status.num_server_changes_remaining();
-  status.ComputeMaxLocalTimestamp();
   status.commit_ids();
   status.HasBookmarkCommitActivity();
   status.download_updates_succeeded();
diff --git a/chrome/browser/sync/sessions/sync_session.cc b/chrome/browser/sync/sessions/sync_session.cc
index d968e83..52a44fa 100644
--- a/chrome/browser/sync/sessions/sync_session.cc
+++ b/chrome/browser/sync/sessions/sync_session.cc
@@ -12,18 +12,46 @@
 SyncSession::SyncSession(SyncSessionContext* context, Delegate* delegate,
     SyncSourceInfo source,
     const ModelSafeRoutingInfo& routing_info,
-    const std::vector<ModelSafeWorker*>& workers) :
-        context_(context),
-        source_(source),
-        write_transaction_(NULL),
-        delegate_(delegate),
-        workers_(workers),
-        routing_info_(routing_info) {
+    const std::vector<ModelSafeWorker*>& workers)
+    : context_(context),
+      source_(source),
+      write_transaction_(NULL),
+      delegate_(delegate),
+      workers_(workers),
+      routing_info_(routing_info) {
   status_controller_.reset(new StatusController(routing_info_));
 }
 
 SyncSession::~SyncSession() {}
 
+void SyncSession::Coalesce(const SyncSession& session) {
+  if (context_ != session.context() || delegate_ != session.delegate_) {
+    NOTREACHED();
+    return;
+  }
+
+  // When we coalesce sessions, the sync update source gets overwritten with the
+  // most recent, while the type/payload map gets merged.
+  CoalescePayloads(&source_.types, session.source_.types);
+  source_.updates_source = session.source_.updates_source;
+
+  std::vector<ModelSafeWorker*> temp;
+  std::set_union(workers_.begin(), workers_.end(),
+                 session.workers_.begin(), session.workers_.end(),
+                 std::back_inserter(temp));
+  workers_.swap(temp);
+
+  ModelSafeRoutingInfo temp_r;
+  std::set_union(routing_info_.begin(), routing_info_.end(),
+      session.routing_info_.begin(), session.routing_info_.end(),
+      std::insert_iterator<ModelSafeRoutingInfo>(temp_r, temp_r.begin()));
+  routing_info_.swap(temp_r);
+}
+
+void SyncSession::ResetTransientState() {
+  status_controller_.reset(new StatusController(routing_info_));
+}
+
 SyncSessionSnapshot SyncSession::TakeSnapshot() const {
   syncable::ScopedDirLookup dir(context_->directory_manager(),
                                 context_->account_name());
@@ -32,6 +60,7 @@
 
   bool is_share_useable = true;
   syncable::ModelTypeBitSet initial_sync_ended;
+  std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
   for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
     syncable::ModelType type(syncable::ModelTypeFromInt(i));
     if (routing_info_.count(type) != 0) {
@@ -39,6 +68,7 @@
         initial_sync_ended.set(type);
       else
         is_share_useable = false;
+      dir->GetDownloadProgressAsString(type, &download_progress_markers[i]);
     }
   }
 
@@ -46,21 +76,22 @@
       status_controller_->syncer_status(),
       status_controller_->error_counters(),
       status_controller_->num_server_changes_remaining(),
-      status_controller_->ComputeMaxLocalTimestamp(),
       is_share_useable,
       initial_sync_ended,
+      download_progress_markers,
       HasMoreToSync(),
       delegate_->IsSyncingCurrentlySilenced(),
       status_controller_->unsynced_handles().size(),
       status_controller_->TotalNumConflictingItems(),
-      status_controller_->did_commit_items());
+      status_controller_->did_commit_items(),
+      source_);
 }
 
 SyncSourceInfo SyncSession::TestAndSetSource() {
   SyncSourceInfo old_source = source_;
   source_ = SyncSourceInfo(
       sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
-      source_.second);
+      source_.types);
   return old_source;
 }
 
diff --git a/chrome/browser/sync/sessions/sync_session.h b/chrome/browser/sync/sessions/sync_session.h
index ce7c9e5..693d652 100644
--- a/chrome/browser/sync/sessions/sync_session.h
+++ b/chrome/browser/sync/sessions/sync_session.h
@@ -15,16 +15,20 @@
 #define CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSION_H_
 #pragma once
 
+#include <map>
+#include <string>
 #include <utility>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/time.h"
+#include "chrome/browser/sync/engine/model_safe_worker.h"
 #include "chrome/browser/sync/sessions/ordered_commit_set.h"
 #include "chrome/browser/sync/sessions/session_state.h"
 #include "chrome/browser/sync/sessions/status_controller.h"
 #include "chrome/browser/sync/sessions/sync_session_context.h"
+#include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/sync/util/extensions_activity_monitor.h"
 
 namespace syncable {
@@ -35,8 +39,6 @@
 class ModelSafeWorker;
 
 namespace sessions {
-typedef std::pair<sync_pb::GetUpdatesCallerInfo::GetUpdatesSource,
-    syncable::ModelTypeBitSet> SyncSourceInfo;
 
 class SyncSession {
  public:
@@ -92,8 +94,19 @@
   // engine again.
   bool HasMoreToSync() const;
 
-  SyncSessionContext* context() { return context_; }
-  Delegate* delegate() { return delegate_; }
+  // Collects all state pertaining to how and why |s| originated and unions it
+  // with corresponding state in |this|, leaving |s| unchanged.  Allows |this|
+  // to take on the responsibilities |s| had (e.g. certain data types) in the
+  // next SyncShare operation using |this|, rather than needed two separate
+  // sessions.
+  void Coalesce(const SyncSession& session);
+
+  // Should be called any time |this| is being re-used in a new call to
+  // SyncShare (e.g., HasMoreToSync returned true).
+  void ResetTransientState();
+
+  SyncSessionContext* context() const { return context_; }
+  Delegate* delegate() const { return delegate_; }
   syncable::WriteTransaction* write_transaction() { return write_transaction_; }
   StatusController* status_controller() { return status_controller_.get(); }
 
@@ -138,12 +151,13 @@
   scoped_ptr<StatusController> status_controller_;
 
   // The set of active ModelSafeWorkers for the duration of this session.
-  const std::vector<ModelSafeWorker*> workers_;
+  // This can change if this session is Coalesce()'d with another.
+  std::vector<ModelSafeWorker*> workers_;
 
   // The routing info for the duration of this session, dictating which
   // datatypes should be synced and which workers should be used when working
   // on those datatypes.
-  const ModelSafeRoutingInfo routing_info_;
+  ModelSafeRoutingInfo routing_info_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncSession);
 };
diff --git a/chrome/browser/sync/sessions/sync_session_context.cc b/chrome/browser/sync/sessions/sync_session_context.cc
index dbb4da6..6b0e91e 100644
--- a/chrome/browser/sync/sessions/sync_session_context.cc
+++ b/chrome/browser/sync/sessions/sync_session_context.cc
@@ -21,7 +21,8 @@
       directory_manager_(directory_manager),
       registrar_(model_safe_worker_registrar),
       extensions_activity_monitor_(new ExtensionsActivityMonitor()),
-      notifications_enabled_(false) {
+      notifications_enabled_(false),
+      max_commit_batch_size_(kDefaultMaxCommitBatchSize) {
   std::vector<SyncEngineEventListener*>::const_iterator it;
   for (it = listeners.begin(); it != listeners.end(); ++it)
     listeners_.AddObserver(*it);
diff --git a/chrome/browser/sync/sessions/sync_session_context.h b/chrome/browser/sync/sessions/sync_session_context.h
index c6d87a1..3f402ae 100644
--- a/chrome/browser/sync/sessions/sync_session_context.h
+++ b/chrome/browser/sync/sessions/sync_session_context.h
@@ -36,6 +36,9 @@
 class ModelSafeWorkerRegistrar;
 class ServerConnectionManager;
 
+// Default number of items a client can commit in a single message.
+static const int kDefaultMaxCommitBatchSize = 25;
+
 namespace sessions {
 class ScopedSessionContextConflictResolver;
 struct SyncSessionSnapshot;
@@ -76,6 +79,11 @@
   }
   const std::string& account_name() { return account_name_; }
 
+  void set_max_commit_batch_size(int batch_size) {
+    max_commit_batch_size_ = batch_size;
+  }
+  int32 max_commit_batch_size() const { return max_commit_batch_size_; }
+
   const ModelSafeRoutingInfo& previous_session_routing_info() const {
     return previous_session_routing_info_;
   }
@@ -84,6 +92,7 @@
     previous_session_routing_info_ = info;
   }
 
+  // TODO(tim): Deprecated.  Bug 26339.
   sessions::SyncSessionSnapshot* previous_session_snapshot() {
     return previous_session_snapshot_.get();
   }
@@ -125,6 +134,9 @@
   // The name of the account being synced.
   std::string account_name_;
 
+  // The server limits the number of items a client can commit in one batch.
+  int max_commit_batch_size_;
+
   // Some routing info history to help us clean up types that get disabled
   // by the user.
   ModelSafeRoutingInfo previous_session_routing_info_;
diff --git a/chrome/browser/sync/sessions/sync_session_unittest.cc b/chrome/browser/sync/sessions/sync_session_unittest.cc
index 32156bd..0f433de 100644
--- a/chrome/browser/sync/sessions/sync_session_unittest.cc
+++ b/chrome/browser/sync/sessions/sync_session_unittest.cc
@@ -4,15 +4,17 @@
 
 #include "chrome/browser/sync/sessions/sync_session.h"
 
+#include "base/ref_counted.h"
 #include "chrome/browser/sync/engine/conflict_resolver.h"
+#include "chrome/browser/sync/engine/mock_model_safe_workers.h"
 #include "chrome/browser/sync/engine/syncer_types.h"
 #include "chrome/browser/sync/engine/syncer_util.h"
 #include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/sync/syncable/syncable.h"
 #include "chrome/test/sync/engine/test_directory_setter_upper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using syncable::MultiTypeTimeStamp;
 using syncable::WriteTransaction;
 
 namespace browser_sync {
@@ -30,7 +32,7 @@
   SyncSession* MakeSession() {
     return new SyncSession(context_.get(), this, SyncSourceInfo(), routes_,
                            std::vector<ModelSafeWorker*>());
-  }  
+  }
 
   virtual void SetUp() {
     context_.reset(new SyncSessionContext(NULL, NULL, this,
@@ -77,18 +79,16 @@
       FAIL() << msg;
   }
 
-  MultiTypeTimeStamp ParamsMeaningAllEnabledTypes() {
-    MultiTypeTimeStamp request_params;
-    request_params.timestamp = 2000;
-    request_params.data_types[syncable::BOOKMARKS] = true;
-    request_params.data_types[syncable::AUTOFILL] = true;
+  syncable::ModelTypeBitSet ParamsMeaningAllEnabledTypes() {
+    syncable::ModelTypeBitSet request_params;
+    request_params[syncable::BOOKMARKS] = true;
+    request_params[syncable::AUTOFILL] = true;
     return request_params;
   }
 
-  MultiTypeTimeStamp ParamsMeaningJustOneEnabledType() {
-    MultiTypeTimeStamp request_params;
-    request_params.timestamp = 5000;
-    request_params.data_types[syncable::AUTOFILL] = true;
+  syncable::ModelTypeBitSet ParamsMeaningJustOneEnabledType() {
+    syncable::ModelTypeBitSet request_params;
+    request_params[syncable::AUTOFILL] = true;
     return request_params;
   }
 
@@ -111,7 +111,7 @@
 TEST_F(SyncSessionTest, SetWriteTransaction) {
   TestDirectorySetterUpper db;
   db.SetUp();
-  session_.reset(NULL);
+  session_.reset();
   context_.reset(new SyncSessionContext(NULL, db.manager(), this,
       std::vector<SyncEngineEventListener*>()));
   session_.reset(MakeSession());
@@ -158,7 +158,7 @@
 }
 
 TEST_F(SyncSessionTest, MoreToDownloadIfDownloadFailed) {
-  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
+  status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
 
   // When DownloadUpdatesCommand fails, these should be false.
   EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
@@ -169,12 +169,13 @@
   EXPECT_FALSE(session_->HasMoreToSync());
 }
 
-TEST_F(SyncSessionTest, MoreToDownloadIfGotTimestamp) {
-  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
+TEST_F(SyncSessionTest, MoreToDownloadIfGotChangesRemaining) {
+  status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
 
-  // When the server returns a timestamp, that means there's more to download.
+  // When the server returns changes_remaining, that means there's
+  // more to download.
   status()->mutable_updates_response()->mutable_get_updates()
-      ->set_new_timestamp(1000000L);
+     ->set_changes_remaining(1000L);
   EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
   EXPECT_TRUE(status()->download_updates_succeeded());
 
@@ -183,12 +184,12 @@
   EXPECT_FALSE(session_->HasMoreToSync());
 }
 
-TEST_F(SyncSessionTest, MoreToDownloadIfGotNoTimestamp) {
-  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
+TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemaining) {
+  status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
 
   // When the server returns a timestamp, that means we're up to date.
   status()->mutable_updates_response()->mutable_get_updates()
-      ->clear_new_timestamp();
+      ->set_changes_remaining(0);
   EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
   EXPECT_TRUE(status()->download_updates_succeeded());
 
@@ -197,15 +198,16 @@
   EXPECT_FALSE(session_->HasMoreToSync());
 }
 
-TEST_F(SyncSessionTest, MoreToDownloadIfGotNoTimestampForSubset) {
-  status()->set_updates_request_parameters(ParamsMeaningJustOneEnabledType());
+TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemainingForSubset) {
+  status()->set_updates_request_types(ParamsMeaningJustOneEnabledType());
 
   // When the server returns a timestamp, that means we're up to date for that
   // type.  But there may still be more to download if there are other
   // datatypes that we didn't request on this go-round.
   status()->mutable_updates_response()->mutable_get_updates()
-    ->clear_new_timestamp();
-  EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
+      ->set_changes_remaining(0);
+
+  EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
   EXPECT_TRUE(status()->download_updates_succeeded());
 
   // Download updates has its own loop in the syncer; it shouldn't factor
@@ -213,13 +215,13 @@
   EXPECT_FALSE(session_->HasMoreToSync());
 }
 
-TEST_F(SyncSessionTest, MoreToDownloadIfGotTimestampAndEntries) {
-  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
+TEST_F(SyncSessionTest, MoreToDownloadIfGotChangesRemainingAndEntries) {
+  status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
   // The actual entry count should not factor into the HasMoreToSync
   // determination.
   status()->mutable_updates_response()->mutable_get_updates()->add_entries();
   status()->mutable_updates_response()->mutable_get_updates()
-      ->set_new_timestamp(1000000L);;
+      ->set_changes_remaining(1000000L);;
   EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
   EXPECT_TRUE(status()->download_updates_succeeded());
 
@@ -228,6 +230,20 @@
   EXPECT_FALSE(session_->HasMoreToSync());
 }
 
+TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemainingAndEntries) {
+  status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
+  // The actual entry count should not factor into the HasMoreToSync
+  // determination.
+  status()->mutable_updates_response()->mutable_get_updates()->add_entries();
+  status()->mutable_updates_response()->mutable_get_updates()
+      ->set_changes_remaining(0);
+  EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
+  EXPECT_TRUE(status()->download_updates_succeeded());
+
+  // Download updates has its own loop in the syncer; it shouldn't factor
+  // into HasMoreToSync.
+  EXPECT_FALSE(session_->HasMoreToSync());
+}
 
 TEST_F(SyncSessionTest, MoreToSyncIfConflictsResolved) {
   // Conflict resolution happens after get updates and commit,
@@ -237,6 +253,110 @@
   EXPECT_TRUE(session_->HasMoreToSync());
 }
 
+TEST_F(SyncSessionTest, ResetTransientState) {
+  status()->update_conflicts_resolved(true);
+  status()->increment_num_successful_commits();
+  EXPECT_TRUE(session_->HasMoreToSync());
+  session_->ResetTransientState();
+  EXPECT_FALSE(status()->conflicts_resolved());
+  EXPECT_FALSE(session_->HasMoreToSync());
+  EXPECT_FALSE(status()->TestAndClearIsDirty());
+}
+
+TEST_F(SyncSessionTest, Coalesce) {
+  std::vector<ModelSafeWorker*> workers_one, workers_two;
+  ModelSafeRoutingInfo routes_one, routes_two;
+  TypePayloadMap one_type = sessions::MakeTypePayloadMapFromBitSet(
+      ParamsMeaningJustOneEnabledType(),
+      std::string());;
+  TypePayloadMap all_types = sessions::MakeTypePayloadMapFromBitSet(
+      ParamsMeaningAllEnabledTypes(),
+      std::string());;
+  SyncSourceInfo source_one(sync_pb::GetUpdatesCallerInfo::PERIODIC, one_type);
+  SyncSourceInfo source_two(sync_pb::GetUpdatesCallerInfo::LOCAL, all_types);
+
+  scoped_refptr<MockDBModelWorker> db_worker(new MockDBModelWorker());
+  scoped_refptr<MockUIModelWorker> ui_worker(new MockUIModelWorker());
+  workers_one.push_back(db_worker);
+  workers_two.push_back(db_worker);
+  workers_two.push_back(ui_worker);
+  routes_one[syncable::AUTOFILL] = GROUP_DB;
+  routes_two[syncable::AUTOFILL] = GROUP_DB;
+  routes_two[syncable::BOOKMARKS] = GROUP_UI;
+  SyncSession one(context_.get(), this, source_one, routes_one, workers_one);
+  SyncSession two(context_.get(), this, source_two, routes_two, workers_two);
+
+  one.Coalesce(two);
+
+  EXPECT_EQ(two.source().updates_source, one.source().updates_source);
+  EXPECT_EQ(all_types, one.source().types);
+  std::vector<ModelSafeWorker*>::const_iterator it_db =
+      std::find(one.workers().begin(), one.workers().end(), db_worker);
+  std::vector<ModelSafeWorker*>::const_iterator it_ui =
+      std::find(one.workers().begin(), one.workers().end(), ui_worker);
+  EXPECT_NE(it_db, one.workers().end());
+  EXPECT_NE(it_ui, one.workers().end());
+  EXPECT_EQ(routes_two, one.routing_info());
+}
+
+TEST_F(SyncSessionTest, MakeTypePayloadMapFromBitSet) {
+  syncable::ModelTypeBitSet types;
+  std::string payload = "test";
+  TypePayloadMap types_with_payloads = MakeTypePayloadMapFromBitSet(types,
+      payload);
+  EXPECT_TRUE(types_with_payloads.empty());
+
+  types[syncable::BOOKMARKS] = true;
+  types[syncable::PASSWORDS] = true;
+  types[syncable::AUTOFILL] = true;
+  payload = "test2";
+  types_with_payloads = MakeTypePayloadMapFromBitSet(types, payload);
+
+  ASSERT_EQ(3U, types_with_payloads.size());
+  EXPECT_EQ(types_with_payloads[syncable::BOOKMARKS], payload);
+  EXPECT_EQ(types_with_payloads[syncable::PASSWORDS], payload);
+  EXPECT_EQ(types_with_payloads[syncable::AUTOFILL], payload);
+}
+
+TEST_F(SyncSessionTest, MakeTypePayloadMapFromRoutingInfo) {
+  std::string payload = "test";
+  TypePayloadMap types_with_payloads
+      = MakeTypePayloadMapFromRoutingInfo(routes_, payload);
+  ASSERT_EQ(routes_.size(), types_with_payloads.size());
+  for (ModelSafeRoutingInfo::iterator iter = routes_.begin();
+       iter != routes_.end();
+       ++iter) {
+    EXPECT_EQ(payload, types_with_payloads[iter->first]);
+  }
+}
+
+TEST_F(SyncSessionTest, CoalescePayloads) {
+  TypePayloadMap original;
+  std::string empty_payload;
+  std::string payload1 = "payload1";
+  std::string payload2 = "payload2";
+  std::string payload3 = "payload3";
+  original[syncable::BOOKMARKS] = empty_payload;
+  original[syncable::PASSWORDS] = payload1;
+  original[syncable::AUTOFILL] = payload2;
+  original[syncable::THEMES] = payload3;
+
+  TypePayloadMap update;
+  update[syncable::BOOKMARKS] = empty_payload;  // Same.
+  update[syncable::PASSWORDS] = empty_payload;  // Overwrite with empty.
+  update[syncable::AUTOFILL] = payload1;        // Overwrite with non-empty.
+  update[syncable::SESSIONS] = payload2;        // New.
+  // Themes untouched.
+
+  CoalescePayloads(&original, update);
+  ASSERT_EQ(5U, original.size());
+  EXPECT_EQ(empty_payload, original[syncable::BOOKMARKS]);
+  EXPECT_EQ(payload1, original[syncable::PASSWORDS]);
+  EXPECT_EQ(payload1, original[syncable::AUTOFILL]);
+  EXPECT_EQ(payload2, original[syncable::SESSIONS]);
+  EXPECT_EQ(payload3, original[syncable::THEMES]);
+}
+
 }  // namespace
 }  // namespace sessions
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/test_util.cc b/chrome/browser/sync/sessions/test_util.cc
new file mode 100644
index 0000000..6f69de6
--- /dev/null
+++ b/chrome/browser/sync/sessions/test_util.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/sessions/test_util.h"
+
+namespace browser_sync {
+namespace sessions {
+namespace test_util {
+
+void SimulateHasMoreToSync(sessions::SyncSession* session,
+                           SyncerStep begin, SyncerStep end) {
+  session->status_controller()->update_conflicts_resolved(true);
+  ASSERT_TRUE(session->HasMoreToSync());
+}
+
+void SimulateDownloadUpdatesFailed(sessions::SyncSession* session,
+                                   SyncerStep begin, SyncerStep end) {
+  // Note that a non-zero value of changes_remaining once a session has
+  // completed implies that the Syncer was unable to exhaust this count during
+  // the GetUpdates cycle.  This is an indication that an error occurred.
+  session->status_controller()->set_num_server_changes_remaining(1);
+}
+
+void SimulateCommitFailed(sessions::SyncSession* session,
+                          SyncerStep begin, SyncerStep end) {
+  // Note that a non-zero number of unsynced handles once a session has
+  // completed implies that the Syncer was unable to make forward progress
+  // during a commit, indicating an error occurred.
+  // See implementation of SyncSession::HasMoreToSync.
+  std::vector<int64> handles;
+  handles.push_back(1);
+  session->status_controller()->set_unsynced_handles(handles);
+}
+
+void SimulateSuccess(sessions::SyncSession* session,
+                     SyncerStep begin, SyncerStep end) {
+  if (session->HasMoreToSync()) {
+    ADD_FAILURE() << "Shouldn't have more to sync";
+  }
+  ASSERT_EQ(0U, session->status_controller()->num_server_changes_remaining());
+  ASSERT_EQ(0U, session->status_controller()->unsynced_handles().size());
+}
+
+void SimulateThrottledImpl(sessions::SyncSession* session,
+    const base::TimeDelta& delta) {
+  session->delegate()->OnSilencedUntil(base::TimeTicks::Now() + delta);
+}
+
+void SimulatePollIntervalUpdateImpl(sessions::SyncSession* session,
+    const base::TimeDelta& new_poll) {
+  session->delegate()->OnReceivedLongPollIntervalUpdate(new_poll);
+}
+
+}  // namespace test_util
+}  // namespace sessions
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/test_util.h b/chrome/browser/sync/sessions/test_util.h
new file mode 100644
index 0000000..12a0119
--- /dev/null
+++ b/chrome/browser/sync/sessions/test_util.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Utils to simulate various outcomes of a sync session.
+#ifndef CHROME_BROWSER_SYNC_SESSIONS_TEST_UTIL_H_
+#define CHROME_BROWSER_SYNC_SESSIONS_TEST_UTIL_H_
+#pragma once
+
+#include "chrome/browser/sync/engine/syncer.h"
+#include "chrome/browser/sync/sessions/sync_session.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace browser_sync {
+namespace sessions {
+namespace test_util {
+
+void SimulateHasMoreToSync(sessions::SyncSession* session,
+                           SyncerStep begin, SyncerStep end);
+void SimulateDownloadUpdatesFailed(sessions::SyncSession* session,
+                                   SyncerStep begin, SyncerStep end);
+void SimulateCommitFailed(sessions::SyncSession* session,
+                          SyncerStep begin, SyncerStep end);
+void SimulateSuccess(sessions::SyncSession* session,
+                     SyncerStep begin, SyncerStep end);
+void SimulateThrottledImpl(sessions::SyncSession* session,
+    const base::TimeDelta& delta);
+void SimulatePollIntervalUpdateImpl(sessions::SyncSession* session,
+    const base::TimeDelta& new_poll);
+
+ACTION_P(SimulateThrottled, throttle) {
+  SimulateThrottledImpl(arg0, throttle);
+}
+
+ACTION_P(SimulatePollIntervalUpdate, poll) {
+  SimulatePollIntervalUpdateImpl(arg0, poll);
+}
+
+}  // namespace test_util
+}  // namespace sessions
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_SESSIONS_TEST_UTIL_H_
diff --git a/chrome/browser/sync/signin_manager_unittest.cc b/chrome/browser/sync/signin_manager_unittest.cc
index d54ed66..12c4204 100644
--- a/chrome/browser/sync/signin_manager_unittest.cc
+++ b/chrome/browser/sync/signin_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -35,8 +35,9 @@
     DCHECK(fetcher);
     DCHECK(fetcher->delegate());
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, GURL(GaiaAuthFetcher::kClientLoginUrl), URLRequestStatus(),
-        200, ResponseCookies(), "SID=sid\nLSID=lsid\nAuth=auth");
+        fetcher, GURL(GaiaAuthFetcher::kClientLoginUrl),
+        net::URLRequestStatus(), 200, ResponseCookies(),
+        "SID=sid\nLSID=lsid\nAuth=auth");
 
     // Then simulate the correct GetUserInfo response for the canonical email.
     // A new URL fetcher is used for each call.
@@ -44,8 +45,9 @@
     DCHECK(fetcher);
     DCHECK(fetcher->delegate());
     fetcher->delegate()->OnURLFetchComplete(
-        fetcher, GURL(GaiaAuthFetcher::kGetUserInfoUrl), URLRequestStatus(),
-        200, ResponseCookies(), "email=user@gmail.com");
+        fetcher, GURL(GaiaAuthFetcher::kGetUserInfoUrl),
+        net::URLRequestStatus(), 200, ResponseCookies(),
+        "email=user@gmail.com");
   }
 
 
diff --git a/chrome/browser/sync/sync_setup_flow.cc b/chrome/browser/sync/sync_setup_flow.cc
index adb06ea..f215e1a 100644
--- a/chrome/browser/sync/sync_setup_flow.cc
+++ b/chrome/browser/sync/sync_setup_flow.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/sync/sync_setup_flow.h"
 
-#include "app/gfx/font_util.h"
 #include "base/callback.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -12,7 +11,7 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/dom_ui/dom_ui_util.h"
+#include "chrome/browser/dom_ui/web_ui_util.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -20,14 +19,13 @@
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_list.h"
-#if defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/html_dialog_window_controller_cppsafe.h"
-#endif
 #include "chrome/common/net/gaia/google_service_auth_error.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/font.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_font_util.h"
+#include "ui/gfx/font.h"
 
 // XPath expression for finding specific iframes.
 static const wchar_t* kLoginIFrameXPath = L"//iframe[@id='login']";
@@ -37,16 +35,25 @@
     L"//iframe[@id='passphrase']";
 static const wchar_t* kDoneIframeXPath = L"//iframe[@id='done']";
 
+SyncConfiguration::SyncConfiguration()
+    : sync_everything(false),
+      use_secondary_passphrase(false) {
+}
+
+SyncConfiguration::~SyncConfiguration() {}
+
 void FlowHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("SubmitAuth",
+  web_ui_->RegisterMessageCallback("SubmitAuth",
       NewCallback(this, &FlowHandler::HandleSubmitAuth));
-  dom_ui_->RegisterMessageCallback("Configure",
+  web_ui_->RegisterMessageCallback("Configure",
       NewCallback(this, &FlowHandler::HandleConfigure));
-  dom_ui_->RegisterMessageCallback("Passphrase",
+  web_ui_->RegisterMessageCallback("Passphrase",
       NewCallback(this, &FlowHandler::HandlePassphraseEntry));
-  dom_ui_->RegisterMessageCallback("FirstPassphrase",
+  web_ui_->RegisterMessageCallback("PassphraseCancel",
+      NewCallback(this, &FlowHandler::HandlePassphraseCancel));
+  web_ui_->RegisterMessageCallback("FirstPassphrase",
       NewCallback(this, &FlowHandler::HandleFirstPassphrase));
-  dom_ui_->RegisterMessageCallback("GoToDashboard",
+  web_ui_->RegisterMessageCallback("GoToDashboard",
       NewCallback(this, &FlowHandler::HandleGoToDashboard));
 }
 
@@ -69,15 +76,13 @@
   return true;
 }
 
-bool GetPassphrase(const std::string& json, std::string* passphrase,
-                   std::string* mode) {
+bool GetPassphrase(const std::string& json, std::string* passphrase) {
   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
     return false;
 
   DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
-  return result->GetString("passphrase", passphrase) &&
-         result->GetString("mode", mode);
+  return result->GetString("passphrase", passphrase);
 }
 
 bool GetFirstPassphrase(const std::string& json,
@@ -168,8 +173,15 @@
   return true;
 }
 
+static void DisablePasswordSync(ProfileSyncService* service) {
+  syncable::ModelTypeSet types;
+  service->GetPreferredDataTypes(&types);
+  types.erase(syncable::PASSWORDS);
+  service->OnUserChoseDatatypes(false, types);
+}
+
 void FlowHandler::HandleSubmitAuth(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
   std::string username, password, captcha, access_code;
   if (json.empty())
     return;
@@ -186,7 +198,7 @@
 }
 
 void FlowHandler::HandleConfigure(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
   SyncConfiguration configuration;
 
   if (json.empty())
@@ -206,25 +218,29 @@
 }
 
 void FlowHandler::HandlePassphraseEntry(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
 
   if (json.empty())
     return;
 
   std::string passphrase;
-  std::string mode;
-  if (!GetPassphrase(json, &passphrase, &mode)) {
+  if (!GetPassphrase(json, &passphrase)) {
     // Couldn't understand what the page sent.  Indicates a programming error.
     NOTREACHED();
     return;
   }
 
   DCHECK(flow_);
-  flow_->OnPassphraseEntry(passphrase, mode);
+  flow_->OnPassphraseEntry(passphrase);
+}
+
+void FlowHandler::HandlePassphraseCancel(const ListValue* args) {
+  DCHECK(flow_);
+  flow_->OnPassphraseCancel();
 }
 
 void FlowHandler::HandleFirstPassphrase(const ListValue* args) {
-  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
+  std::string json(web_ui_util::GetJsonResponseFromFirstArgumentInList(args));
 
   if (json.empty())
     return;
@@ -254,8 +270,8 @@
   // So if you ever made a wizard that involved a gaia login as not the first
   // frame, this call would be necessary to ensure that this method actually
   // shows the gaia login.
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showGaiaLoginIframe");
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"showGaiaLoginIframe");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
@@ -278,8 +294,8 @@
   // If you're starting the wizard at the configure screen (i.e. from
   // "Customize Sync"), this will be redundant.  However, if you're coming from
   // another wizard state, this will make sure Choose Data Types is on top.
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showConfigure");
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"showConfigure");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
@@ -289,8 +305,8 @@
 }
 
 void FlowHandler::ShowPassphraseEntry(const DictionaryValue& args) {
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showPassphrase");
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"showPassphrase");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
@@ -300,8 +316,8 @@
 }
 
 void FlowHandler::ShowFirstPassphrase(const DictionaryValue& args) {
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showFirstPassphrase");
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"showFirstPassphrase");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
@@ -311,8 +327,8 @@
 }
 
 void FlowHandler::ShowSettingUp() {
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showSettingUp");
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"showSettingUp");
 }
 
 void FlowHandler::ShowSetupDone(const std::wstring& user) {
@@ -324,8 +340,8 @@
       L"(" + UTF8ToWide(json) + L");";
   ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
 
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showSetupDone", synced_to_string);
+  if (web_ui_)
+    web_ui_->CallJavascriptFunction(L"showSetupDone", synced_to_string);
 
   ExecuteJavascriptInIFrame(kDoneIframeXPath,
                             L"onPageShown();");
@@ -339,9 +355,10 @@
 
 void FlowHandler::ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath,
                                             const std::wstring& js) {
-  if (dom_ui_) {
-    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
-    rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
+  if (web_ui_) {
+    RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
+    rvh->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath),
+                                     WideToUTF16Hack(js));
   }
 }
 
@@ -373,10 +390,10 @@
 void SyncSetupFlow::GetDialogSize(gfx::Size* size) const {
   PrefService* prefs = service_->profile()->GetPrefs();
   gfx::Font approximate_web_font = gfx::Font(
-      UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
+      UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
       prefs->GetInteger(prefs::kWebKitDefaultFontSize));
 
-  *size = gfx::GetLocalizedContentsSizeForFont(
+  *size = ui::GetLocalizedContentsSizeForFont(
       IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
       IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
       approximate_web_font);
@@ -480,10 +497,10 @@
 void SyncSetupFlow::GetArgsForEnterPassphrase(
     const ProfileSyncService* service, DictionaryValue* args) {
   args->SetString("iframeToShow", "passphrase");
-  if (service->IsUsingSecondaryPassphrase())
-    args->SetString("mode", "enter");
-  else
-    args->SetString("mode", "gaia");
+  args->SetBoolean("passphrase_creation_rejected",
+                   service->tried_creating_explicit_passphrase());
+  args->SetBoolean("passphrase_setting_rejected",
+                   service->tried_setting_explicit_passphrase());
 }
 
 // static
@@ -536,8 +553,8 @@
   args->SetBoolean("usePassphrase", service->IsUsingSecondaryPassphrase());
 }
 
-void SyncSetupFlow::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void SyncSetupFlow::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   handlers->push_back(flow_handler_);
   // We don't own flow_handler_ anymore, but it sticks around until at least
   // right after OnDialogClosed() is called (and this object is destroyed).
@@ -557,6 +574,8 @@
     case SyncSetupWizard::ENTER_PASSPHRASE:
       return current_state_ == SyncSetupWizard::CONFIGURE ||
              current_state_ == SyncSetupWizard::SETTING_UP;
+    case SyncSetupWizard::PASSPHRASE_MIGRATION:
+      return current_state_ == SyncSetupWizard::GAIA_LOGIN;
     case SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR:
       return current_state_ == SyncSetupWizard::CONFIGURE;
     case SyncSetupWizard::SETTING_UP:
@@ -693,9 +712,8 @@
   // function that is not tied to a browser instance.  Note that if we do
   // that, we'll have to fix sync_setup_wizard_unittest.cc as it relies on
   // being able to intercept ShowHtmlDialog() calls.
-  flow->html_dialog_window_ =
-      html_dialog_window_controller::ShowHtmlDialog(
-          flow, service->profile());
+  flow->html_dialog_window_ = browser::ShowHtmlDialog(NULL, service->profile(),
+                                                      flow);
 #else
   Browser* b = BrowserList::GetLastActive();
   if (b) {
@@ -726,31 +744,37 @@
 
   if (configuration.use_secondary_passphrase &&
       !service_->IsUsingSecondaryPassphrase()) {
-    service_->SetPassphrase(configuration.secondary_passphrase, true);
+    service_->SetPassphrase(configuration.secondary_passphrase, true, true);
   }
 
   service_->OnUserChoseDatatypes(configuration.sync_everything,
                                  configuration.data_types);
 }
 
-void SyncSetupFlow::OnPassphraseEntry(const std::string& passphrase,
-                                      const std::string& mode) {
+void SyncSetupFlow::OnPassphraseEntry(const std::string& passphrase) {
   Advance(SyncSetupWizard::SETTING_UP);
-  service_->SetPassphrase(passphrase, true);
+  service_->SetPassphrase(passphrase, true, false);
+}
+
+void SyncSetupFlow::OnPassphraseCancel() {
+  // If the user cancels when being asked for the passphrase,
+  // just disable encrypted sync and continue setting up.
+  if (current_state_ == SyncSetupWizard::ENTER_PASSPHRASE)
+    DisablePasswordSync(service_);
+
+  Advance(SyncSetupWizard::SETTING_UP);
 }
 
 void SyncSetupFlow::OnFirstPassphraseEntry(const std::string& option,
                                            const std::string& passphrase) {
   Advance(SyncSetupWizard::SETTING_UP);
+
   if (option == "explicit") {
-    service_->SetPassphrase(passphrase, true);
+    service_->SetPassphrase(passphrase, true, true);
   } else if (option == "nothanks") {
     // User opted out of encrypted sync, need to turn off encrypted
     // data types.
-    syncable::ModelTypeSet registered_types;
-    service_->GetRegisteredDataTypes(&registered_types);
-    registered_types.erase(syncable::PASSWORDS);
-    service_->OnUserChoseDatatypes(false, registered_types);
+    DisablePasswordSync(service_);
   } else if (option == "google") {
     // Implicit passphrase already set up.
     Advance(SyncSetupWizard::DONE);
diff --git a/chrome/browser/sync/sync_setup_flow.h b/chrome/browser/sync/sync_setup_flow.h
index f6c0233..dc22804 100644
--- a/chrome/browser/sync/sync_setup_flow.h
+++ b/chrome/browser/sync/sync_setup_flow.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,15 +9,15 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/gtest_prod_util.h"
 #include "base/time.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/sync_setup_wizard.h"
 #include "chrome/browser/sync/syncable/model_type.h"
-#include "gfx/native_widget_types.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/native_widget_types.h"
 
 class FlowHandler;
 class SyncSetupFlowContainer;
@@ -26,6 +26,9 @@
 // This can be stored or passed around when the configuration is managed
 // by multiple stages of the wizard.
 struct SyncConfiguration {
+  SyncConfiguration();
+  ~SyncConfiguration();
+
   bool sync_everything;
   syncable::ModelTypeSet data_types;
   bool use_secondary_passphrase;
@@ -75,8 +78,8 @@
   virtual GURL GetDialogContentURL() const;
 
   // HtmlDialogUIDelegate implementation.
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
 
   // HtmlDialogUIDelegate implementation.
   // Get the size of the dialog.
@@ -107,9 +110,15 @@
 
   void OnUserConfigured(const SyncConfiguration& configuration);
 
-  void OnPassphraseEntry(const std::string& passphrase,
-                         const std::string& mode);
+  // The 'passphrase' screen is used when the user is prompted to enter
+  // an existing passphrase.
+  void OnPassphraseEntry(const std::string& passphrase);
 
+  // The user canceled the passphrase entry without supplying a passphrase.
+  void OnPassphraseCancel();
+
+  // The 'first passphrase' screen is for users migrating from a build
+  // without passwords, who are prompted to make a passphrase choice.
   void OnFirstPassphraseEntry(const std::string& option,
                               const std::string& passphrase);
 
@@ -153,7 +162,7 @@
   FlowHandler* flow_handler_;
   mutable bool owns_flow_handler_;
 
-  // We need this to write the sentinel "setup completed" pref.
+  // We need this to propagate back all user settings changes.
   ProfileSyncService* service_;
 
   // Currently used only on OS X
@@ -183,20 +192,21 @@
 };
 
 // The FlowHandler connects the state machine to the dialog backing HTML and
-// JS namespace by implementing DOMMessageHandler and being invoked by the
+// JS namespace by implementing WebUIMessageHandler and being invoked by the
 // SyncSetupFlow.  Exposed here to facilitate testing.
-class FlowHandler : public DOMMessageHandler {
+class FlowHandler : public WebUIMessageHandler {
  public:
   FlowHandler()  {}
   virtual ~FlowHandler() {}
 
-  // DOMMessageHandler implementation.
+  // WebUIMessageHandler implementation.
   virtual void RegisterMessages();
 
   // Callbacks from the page.
   void HandleSubmitAuth(const ListValue* args);
   void HandleConfigure(const ListValue* args);
   void HandlePassphraseEntry(const ListValue* args);
+  void HandlePassphraseCancel(const ListValue* args);
   void HandleFirstPassphrase(const ListValue* args);
   void HandleGoToDashboard(const ListValue* args);
 
diff --git a/chrome/browser/sync/sync_setup_wizard.cc b/chrome/browser/sync/sync_setup_wizard.cc
index 6e9d254..632d60d 100644
--- a/chrome/browser/sync/sync_setup_wizard.cc
+++ b/chrome/browser/sync/sync_setup_wizard.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/sync/sync_setup_wizard.h"
 
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/singleton.h"
 #include "chrome/browser/browser_thread.h"
@@ -22,6 +21,7 @@
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/locale_settings.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -51,6 +51,7 @@
   static const char* kInvalidPasswordHelpUrl;
   static const char* kCanNotAccessAccountUrl;
   static const char* kCreateNewAccountUrl;
+  static const char* kEncryptionHelpUrl;
 
  private:
   virtual ~SyncResourcesSource() {}
@@ -64,11 +65,13 @@
 };
 
 const char* SyncResourcesSource::kInvalidPasswordHelpUrl =
-  "http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444";
+    "http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444";
 const char* SyncResourcesSource::kCanNotAccessAccountUrl =
-  "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
+    "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
+const char* SyncResourcesSource::kEncryptionHelpUrl =
+    "http://www.google.com/support/chrome/bin/answer.py?answer=165139";
 const char* SyncResourcesSource::kCreateNewAccountUrl =
-  "https://www.google.com/accounts/NewAccount?service=chromiumsync";
+    "https://www.google.com/accounts/NewAccount?service=chromiumsync";
 
 void SyncResourcesSource::StartDataRequest(const std::string& path_raw,
     bool is_off_the_record, int request_id) {
@@ -164,6 +167,10 @@
     AddString(dict, "cleardata", IDS_SYNC_CLEAR_DATA_FOR_PASSPHRASE);
     AddString(dict, "cleardatalink", IDS_SYNC_CLEAR_DATA_LINK);
 
+    AddString(dict, "learnmore", IDS_LEARN_MORE);
+    dict->SetString("encryptionhelpurl",
+                    GetLocalizedUrl(kEncryptionHelpUrl));
+
     // Stuff for the footer.
     AddString(dict, "ok", IDS_OK);
     AddString(dict, "cancel", IDS_CANCEL);
@@ -171,7 +178,20 @@
     html_resource_id = IDR_SYNC_PASSPHRASE_HTML;
     AddString(dict, "enterPassphraseTitle", IDS_SYNC_ENTER_PASSPHRASE_TITLE);
     AddString(dict, "enterPassphraseBody", IDS_SYNC_ENTER_PASSPHRASE_BODY);
+    AddString(dict, "enterOtherPassphraseBody",
+              IDS_SYNC_ENTER_OTHER_PASSPHRASE_BODY);
     AddString(dict, "passphraseLabel", IDS_SYNC_PASSPHRASE_LABEL);
+    AddString(dict, "incorrectPassphrase", IDS_SYNC_INCORRECT_PASSPHRASE);
+    AddString(dict, "passphraseRecover", IDS_SYNC_PASSPHRASE_RECOVER);
+    AddString(dict, "passphraseWarning", IDS_SYNC_PASSPHRASE_WARNING);
+    AddString(dict, "cleardatalink", IDS_SYNC_CLEAR_DATA_LINK);
+
+    AddString(dict, "cancelWarningHeader",
+              IDS_SYNC_PASSPHRASE_CANCEL_WARNING_HEADER);
+    AddString(dict, "cancelWarning", IDS_SYNC_PASSPHRASE_CANCEL_WARNING);
+    AddString(dict, "yes", IDS_SYNC_PASSPHRASE_CANCEL_YES);
+    AddString(dict, "no", IDS_SYNC_PASSPHRASE_CANCEL_NO);
+
     AddString(dict, "ok", IDS_OK);
     AddString(dict, "cancel", IDS_CANCEL);
   } else if (path_raw == kSyncFirstPassphrasePath) {
@@ -182,16 +202,19 @@
                                     GetStringUTF16(IDS_PRODUCT_NAME)));
     AddString(dict, "googleOption", IDS_SYNC_PASSPHRASE_OPT_GOOGLE);
     AddString(dict, "explicitOption", IDS_SYNC_PASSPHRASE_OPT_EXPLICIT);
-    AddString(dict, "nothanksOption", IDS_SYNC_PASSPHRASE_OPT_CANCEL);
     AddString(dict, "sectionGoogleMessage", IDS_SYNC_PASSPHRASE_MSG_GOOGLE);
     AddString(dict, "sectionExplicitMessage", IDS_SYNC_PASSPHRASE_MSG_EXPLICIT);
-    AddString(dict, "sectionNothanksMessage", IDS_SYNC_PASSPHRASE_MSG_CANCEL);
     AddString(dict, "passphraseLabel", IDS_SYNC_PASSPHRASE_LABEL);
     AddString(dict, "confirmLabel", IDS_SYNC_CONFIRM_PASSPHRASE_LABEL);
     AddString(dict, "emptyErrorMessage", IDS_SYNC_EMPTY_PASSPHRASE_ERROR);
     AddString(dict, "mismatchErrorMessage", IDS_SYNC_PASSPHRASE_MISMATCH_ERROR);
-    AddString(dict, "ok", IDS_OK);
-    AddString(dict, "cancel", IDS_CANCEL);
+
+    AddString(dict, "learnmore", IDS_LEARN_MORE);
+    dict->SetString("encryptionhelpurl",
+                    GetLocalizedUrl(kEncryptionHelpUrl));
+
+    AddString(dict, "syncpasswords", IDS_SYNC_FIRST_PASSPHRASE_OK);
+    AddString(dict, "nothanks", IDS_SYNC_FIRST_PASSPHRASE_CANCEL);
   } else if (path_raw == kSyncSettingUpPath) {
     html_resource_id = IDR_SYNC_SETTING_UP_HTML;
 
@@ -237,13 +260,15 @@
     : service_(service),
       flow_container_(new SyncSetupFlowContainer()),
       parent_window_(NULL) {
-  // Add our network layer data source for 'cloudy' URLs.
-  SyncResourcesSource* sync_source = new SyncResourcesSource();
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      NewRunnableMethod(ChromeURLDataManager::GetInstance(),
-                        &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(sync_source)));
+  // If we're in a unit test, we may not have an IO thread or profile.  Avoid
+  // creating a SyncResourcesSource since we may leak it (since it's
+  // DeleteOnUIThread).
+  if (BrowserThread::IsMessageLoopValid(BrowserThread::IO) &&
+      service_->profile()) {
+    // Add our network layer data source for 'cloudy' URLs.
+    SyncResourcesSource* sync_source = new SyncResourcesSource();
+    service_->profile()->GetChromeURLDataManager()->AddDataSource(sync_source);
+  }
 }
 
 SyncSetupWizard::~SyncSetupWizard() {
diff --git a/chrome/browser/sync/sync_setup_wizard.h b/chrome/browser/sync/sync_setup_wizard.h
index 76b6fae..ce08266 100644
--- a/chrome/browser/sync/sync_setup_wizard.h
+++ b/chrome/browser/sync/sync_setup_wizard.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class SyncSetupFlowContainer;
 
diff --git a/chrome/browser/sync/sync_setup_wizard_unittest.cc b/chrome/browser/sync/sync_setup_wizard_unittest.cc
index b0da0d7..d705706 100644
--- a/chrome/browser/sync/sync_setup_wizard_unittest.cc
+++ b/chrome/browser/sync/sync_setup_wizard_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -60,7 +60,8 @@
   }
 
   virtual void SetPassphrase(const std::string& passphrase,
-                             bool is_explicit) {
+                             bool is_explicit,
+                             bool is_creation) {
     passphrase_ = passphrase;
   }
 
@@ -125,11 +126,11 @@
 
   virtual ~TestBrowserWindowForWizardTest() {
     if (flow_.get()) {
-      // In real life, the handlers are destroyed by the DOMUI infrastructure,
-      // which calls GetDOMMessageHandlers to take ownership.  This does not
+      // In real life, the handlers are destroyed by the WebUI infrastructure,
+      // which calls GetWebUIMessageHandlers to take ownership.  This does not
       // exist in our test, so we perform cleanup manually.
-      std::vector<DOMMessageHandler*> handlers;
-      flow_->GetDOMMessageHandlers(&handlers);
+      std::vector<WebUIMessageHandler*> handlers;
+      flow_->GetWebUIMessageHandlers(&handlers);
       // The handler contract is that they are valid for the lifetime of the
       // HTMLDialogUIDelegate, but are cleaned up after the dialog is closed
       // and/or deleted.
@@ -156,8 +157,8 @@
   // Handles cleaning up the delegate and associated handlers.
   void CloseDialog() {
     if (flow_.get()) {
-      std::vector<DOMMessageHandler*> handlers;
-      flow_->GetDOMMessageHandlers(&handlers);
+      std::vector<WebUIMessageHandler*> handlers;
+      flow_->GetWebUIMessageHandlers(&handlers);
       // The flow deletes itself here.  Don't use reset().
       flow_.release()->OnDialogClosed("");
       STLDeleteElements(&handlers);
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index d49ada1..8cfe948 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -1,22 +1,26 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/sync/sync_ui_util.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include "base/command_line.h"
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/time_formatting.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/options/options_window.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/net/gaia/google_service_auth_error.h"
+#include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 typedef GoogleServiceAuthError AuthError;
 
@@ -107,23 +111,20 @@
     } else if (service->observed_passphrase_required()) {
       if (service->passphrase_required_for_decryption()) {
         // NOT first machine.
-        // Show a link and present as an error ("needs attention").
+        // Show a link ("needs attention"), but still indicate the
+        // current synced status.  Return SYNC_PROMO so that
+        // the configure link will still be shown.
         if (status_label && link_label) {
-          status_label->assign(string16());
+          status_label->assign(GetSyncedStateStatusLabel(service));
           link_label->assign(
-              l10n_util::GetStringUTF16(IDS_SYNC_CONFIGURE_ENCRYPTION));
-        }
-        result_type = SYNC_ERROR;
-      } else {
-        // First machine.  Show as a promotion.
-        if (status_label && link_label) {
-          status_label->assign(
-              l10n_util::GetStringFUTF16(IDS_SYNC_NTP_PASSWORD_PROMO,
-                  l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
-          link_label->assign(
-              l10n_util::GetStringUTF16(IDS_SYNC_NTP_PASSWORD_ENABLE));
+              l10n_util::GetStringUTF16(IDS_SYNC_PASSWORD_SYNC_ATTENTION));
         }
         result_type = SYNC_PROMO;
+      } else {
+        // First machine.  Don't show promotion, just show everything
+        // normal.
+        if (status_label)
+          status_label->assign(GetSyncedStateStatusLabel(service));
       }
     } else if (auth_error.state() != AuthError::NONE) {
       if (status_label && link_label) {
@@ -176,6 +177,43 @@
   return result_type;
 }
 
+// Returns the status info for use on the new tab page, where we want slightly
+// different information than in the settings panel.
+MessageType GetStatusInfoForNewTabPage(ProfileSyncService* service,
+                                       string16* status_label,
+                                       string16* link_label) {
+  DCHECK(status_label);
+  DCHECK(link_label);
+
+  if (service->HasSyncSetupCompleted() &&
+      service->observed_passphrase_required()) {
+    if (!service->passphrase_required_for_decryption()) {
+      // First machine migrating to passwords.  Show as a promotion.
+      if (status_label && link_label) {
+        status_label->assign(
+            l10n_util::GetStringFUTF16(
+                IDS_SYNC_NTP_PASSWORD_PROMO,
+                l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+        link_label->assign(
+            l10n_util::GetStringUTF16(IDS_SYNC_NTP_PASSWORD_ENABLE));
+      }
+      return SYNC_PROMO;
+    } else {
+      // NOT first machine.
+      // Show a link and present as an error ("needs attention").
+      if (status_label && link_label) {
+        status_label->assign(string16());
+        link_label->assign(
+            l10n_util::GetStringUTF16(IDS_SYNC_CONFIGURE_ENCRYPTION));
+      }
+      return SYNC_ERROR;
+    }
+  }
+
+  // Fallback to default.
+  return GetStatusInfo(service, status_label, link_label);
+}
+
 }  // namespace
 
 // Returns an HTML chunk for a login prompt related to encryption.
@@ -200,6 +238,15 @@
   return sync_ui_util::GetStatusInfo(service, status_label, link_label);
 }
 
+MessageType GetStatusLabelsForNewTabPage(ProfileSyncService* service,
+                                         string16* status_label,
+                                         string16* link_label) {
+  DCHECK(status_label);
+  DCHECK(link_label);
+  return sync_ui_util::GetStatusInfoForNewTabPage(
+      service, status_label, link_label);
+}
+
 MessageType GetStatus(ProfileSyncService* service) {
   return sync_ui_util::GetStatusInfo(service, NULL, NULL);
 }
@@ -220,16 +267,30 @@
     return l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL);
 }
 
-void OpenSyncMyBookmarksDialog(
-    Profile* profile, ProfileSyncService::SyncEventCodes code) {
+void OpenSyncMyBookmarksDialog(Profile* profile,
+                               Browser* browser,
+                               ProfileSyncService::SyncEventCodes code) {
   ProfileSyncService* service =
     profile->GetOriginalProfile()->GetProfileSyncService();
   if (!service || !service->IsSyncEnabled()) {
     LOG(DFATAL) << "OpenSyncMyBookmarksDialog called with sync disabled";
     return;
   }
+
+  bool use_tabbed_options = !CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableTabbedOptions);
+
   if (service->HasSyncSetupCompleted()) {
-    ShowOptionsWindow(OPTIONS_PAGE_CONTENT, OPTIONS_GROUP_NONE, profile);
+    if (use_tabbed_options) {
+      bool create_window = browser == NULL;
+      if (create_window)
+        browser = Browser::Create(profile);
+      browser->ShowOptionsTab(chrome::kPersonalOptionsSubPage);
+      if (create_window)
+        browser->window()->Show();
+    } else {
+      ShowOptionsWindow(OPTIONS_PAGE_CONTENT, OPTIONS_GROUP_NONE, profile);
+    }
   } else {
     service->ShowLoginDialog(NULL);
     ProfileSyncService::SyncEvent(code);  // UMA stats
@@ -281,8 +342,8 @@
 
 void ConstructAboutInformation(ProfileSyncService* service,
                                DictionaryValue* strings) {
-  CHECK(strings != NULL);
-  if (!service->HasSyncSetupCompleted()) {
+  CHECK(strings);
+  if (!service || !service->HasSyncSetupCompleted()) {
     strings->SetString("summary", "SYNC DISABLED");
   } else {
     sync_api::SyncManager::Status full_status(
@@ -338,14 +399,14 @@
                                    "Updates Available",
                                    full_status.updates_available);
     sync_ui_util::AddIntSyncDetail(details,
-                                   "Updates Received",
+                                   "Updates Downloaded (All)",
                                    full_status.updates_received);
+    sync_ui_util::AddIntSyncDetail(details,
+                                   "Updates Downloaded (Tombstones)",
+                                   full_status.tombstone_updates_received);
     sync_ui_util::AddBoolSyncDetail(details,
                                     "Disk Full",
                                     full_status.disk_full);
-    sync_ui_util::AddBoolSyncDetail(details,
-                                    "Invalid Store",
-                                    full_status.invalid_store);
     sync_ui_util::AddIntSyncDetail(details,
                                    "Max Consecutive Errors",
                                    full_status.max_consecutive_errors);
@@ -360,13 +421,9 @@
       strings->SetString("unrecoverable_error_location", location_str);
     } else if (!service->sync_initialized()) {
       strings->SetString("summary", "Sync not yet initialized");
-    } else if (service->backend() == NULL) {
-      strings->SetString("summary",
-          "Unrecoverable error detected. Backend is null when it shouldnt be");
-      NOTREACHED();
     } else {
       browser_sync::ModelSafeRoutingInfo routes;
-      service->backend()->GetModelSafeRoutingInfo(&routes);
+      service->GetModelSafeRoutingInfo(&routes);
       ListValue* routing_info = new ListValue();
       strings->Set("routing_info", routing_info);
       browser_sync::ModelSafeRoutingInfo::const_iterator it = routes.begin();
@@ -379,10 +436,10 @@
 
       sync_ui_util::AddBoolSyncDetail(details,
           "Autofill Migrated",
-          service->backend()->GetAutofillMigrationState() ==
+          service->GetAutofillMigrationState() ==
           syncable::MIGRATED);
       syncable::AutofillMigrationDebugInfo info =
-          service->backend()->GetAutofillMigrationDebugInfo();
+          service->GetAutofillMigrationDebugInfo();
 
       sync_ui_util::AddIntSyncDetail(details,
                                      "Bookmarks created during migration",
diff --git a/chrome/browser/sync/sync_ui_util.h b/chrome/browser/sync/sync_ui_util.h
index 5a168c4..819916d 100644
--- a/chrome/browser/sync/sync_ui_util.h
+++ b/chrome/browser/sync/sync_ui_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include "base/values.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 
+class Browser;
 class Profile;
 class ListValue;
 class DictionaryValue;
@@ -39,6 +40,11 @@
                             string16* status_label,
                             string16* link_label);
 
+// Same as above but for use specifically on the New Tab Page.
+MessageType GetStatusLabelsForNewTabPage(ProfileSyncService* service,
+                                         string16* status_label,
+                                         string16* link_label);
+
 MessageType GetStatus(ProfileSyncService* service);
 
 // Determines whether or not the sync error button should be visible.
@@ -48,14 +54,17 @@
 string16 GetSyncMenuLabel(ProfileSyncService* service);
 
 // Open the appropriate sync dialog for the given profile (which can be
-// incognito).  |code| should be one of the START_FROM_* codes.
-void OpenSyncMyBookmarksDialog(
-    Profile* profile, ProfileSyncService::SyncEventCodes code);
+// incognito). |browser| is the browser window that should be used if the UI
+// is in-window (i.e., WebUI). |code| should be one of the START_FROM_* codes.
+void OpenSyncMyBookmarksDialog(Profile* profile,
+                               Browser* browser,
+                               ProfileSyncService::SyncEventCodes code);
 
 void AddBoolSyncDetail(ListValue* details,
                        const std::string& stat_name,
                        bool stat_value);
 
+// |service| can be NULL.
 void ConstructAboutInformation(ProfileSyncService* service,
                                DictionaryValue* strings);
 
diff --git a/chrome/browser/sync/sync_ui_util_mac.mm b/chrome/browser/sync/sync_ui_util_mac.mm
index f65f2a0..51a6bb7 100644
--- a/chrome/browser/sync/sync_ui_util_mac.mm
+++ b/chrome/browser/sync/sync_ui_util_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/l10n_util_mac.h"
 #include "base/logging.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace sync_ui_util {
 
@@ -40,7 +40,7 @@
   }
 
   // TODO(akalin): consolidate this code with the equivalent Windows code in
-  // chrome/browser/views/toolbar_view.cc.
+  // chrome/browser/ui/views/toolbar_view.cc.
   int titleId;
   switch (status) {
     case sync_ui_util::SYNCED:
diff --git a/chrome/browser/sync/sync_ui_util_mac_unittest.mm b/chrome/browser/sync/sync_ui_util_mac_unittest.mm
index ef5e32f..bebb06e 100644
--- a/chrome/browser/sync/sync_ui_util_mac_unittest.mm
+++ b/chrome/browser/sync/sync_ui_util_mac_unittest.mm
@@ -6,12 +6,12 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/l10n_util_mac.h"
 #include "base/scoped_nsobject.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
diff --git a/chrome/browser/sync/sync_ui_util_unittest.cc b/chrome/browser/sync/sync_ui_util_unittest.cc
index 7122170..96dd2c9 100644
--- a/chrome/browser/sync/sync_ui_util_unittest.cc
+++ b/chrome/browser/sync/sync_ui_util_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
+#include "chrome/browser/browser_thread.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -12,6 +13,8 @@
 using ::testing::Return;
 using ::testing::NiceMock;
 TEST(SyncUIUtilTest, ConstructAboutInformationWithUnrecoverableErrorTest) {
+  MessageLoopForUI message_loop;
+  BrowserThread ui_thread(BrowserThread::UI, &message_loop);
   NiceMock<ProfileSyncServiceMock> service;
   DictionaryValue strings;
 
diff --git a/chrome/browser/sync/syncable/directory_backing_store.cc b/chrome/browser/sync/syncable/directory_backing_store.cc
index feefd91..fcadba1 100644
--- a/chrome/browser/sync/syncable/directory_backing_store.cc
+++ b/chrome/browser/sync/syncable/directory_backing_store.cc
@@ -44,7 +44,7 @@
 
 // Increment this version whenever updating DB tables.
 extern const int32 kCurrentDBVersion;  // Global visibility for our unittest.
-const int32 kCurrentDBVersion = 74;
+const int32 kCurrentDBVersion = 75;
 
 namespace {
 
@@ -411,11 +411,13 @@
     for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
       SQLStatement op;
       op.prepare(dbhandle, "INSERT OR REPLACE INTO models (model_id, "
-      "last_download_timestamp, initial_sync_ended) VALUES ( ?, ?, ?)");
+      "progress_marker, initial_sync_ended) VALUES ( ?, ?, ?)");
       // We persist not ModelType but rather a protobuf-derived ID.
       string model_id = ModelTypeEnumToModelId(ModelTypeFromInt(i));
+      string progress_marker;
+      info.download_progress[i].SerializeToString(&progress_marker);
       op.bind_blob(0, model_id.data(), model_id.length());
-      op.bind_int64(1, info.last_download_timestamp[i]);
+      op.bind_blob(1, progress_marker.data(), progress_marker.length());
       op.bind_bool(2, info.initial_sync_ended[i]);
 
       if (!(SQLITE_DONE == op.step() &&
@@ -473,11 +475,18 @@
       version_on_disk = 73;
   }
 
+  // Version 74 added state for the autofill migration.
   if (version_on_disk == 73) {
     if (MigrateVersion73To74())
       version_on_disk = 74;
   }
 
+  // Version 75 migrated from int64-based timestamps to per-datatype tokens.
+  if (version_on_disk == 74) {
+    if (MigrateVersion74To75())
+      version_on_disk = 75;
+  }
+
   // If one of the migrations requested it, drop columns that aren't current.
   // It's only safe to do this after migrating all the way to the current
   // version.
@@ -606,14 +615,14 @@
   {
     SQLStatement query;
     query.prepare(load_dbhandle_,
-        "SELECT model_id, last_download_timestamp, initial_sync_ended "
+        "SELECT model_id, progress_marker, initial_sync_ended "
         "FROM models");
     while (SQLITE_ROW == query.step()) {
-      string model_id;
-      query.column_blob_as_string(0, &model_id);
-      ModelType type = ModelIdToModelTypeEnum(model_id);
-      if (type != UNSPECIFIED) {
-        info->kernel_info.last_download_timestamp[type] = query.column_int64(1);
+      ModelType type = ModelIdToModelTypeEnum(query.column_blob(0),
+                                              query.column_bytes(0));
+      if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER) {
+        info->kernel_info.download_progress[type].ParseFromArray(
+            query.column_blob(1), query.column_bytes(1));
         info->kernel_info.initial_sync_ended[type] = query.column_bool(2);
       }
     }
@@ -709,14 +718,15 @@
   SafeDropTable("share_version");
   SafeDropTable("extended_attributes");
   SafeDropTable("models");
+  SafeDropTable("temp_models");
   needs_column_refresh_ = false;
 }
 
 // static
 ModelType DirectoryBackingStore::ModelIdToModelTypeEnum(
-    const string& model_id) {
+    const void* data, int size) {
   sync_pb::EntitySpecifics specifics;
-  if (!specifics.ParseFromString(model_id))
+  if (!specifics.ParseFromArray(data, size))
     return syncable::UNSPECIFIED;
   return syncable::GetModelTypeFromSpecifics(specifics);
 }
@@ -900,7 +910,7 @@
 // were removed from the share_info table.  They were replaced by
 // the 'models' table, which has these values on a per-datatype basis.
 bool DirectoryBackingStore::MigrateVersion70To71() {
-  if (SQLITE_DONE != CreateModelsTable())
+  if (SQLITE_DONE != CreateV71ModelsTable())
     return false;
 
   // Move data from the old share_info columns to the new models table.
@@ -950,12 +960,15 @@
 }
 
 bool DirectoryBackingStore::MigrateVersion71To72() {
+  // Version 72 removed a table 'extended_attributes', whose
+  // contents didn't matter.
   SafeDropTable("extended_attributes");
   SetVersion(72);
   return true;
 }
 
 bool DirectoryBackingStore::MigrateVersion72To73() {
+  // Version 73 added one column to the table 'share_info': notification_state
   int result =
       ExecQuery(load_dbhandle_,
                 "ALTER TABLE share_info ADD COLUMN notification_state BLOB");
@@ -966,6 +979,13 @@
 }
 
 bool DirectoryBackingStore::MigrateVersion73To74() {
+  // Version 74 added the following columns to the table 'share_info':
+  //   autofill_migration_state
+  //   bookmarks_added_during_autofill_migration
+  //   autofill_migration_time
+  //   autofill_entries_added_during_migration
+  //   autofill_profiles_added_during_migration
+
   int result =
       ExecQuery(load_dbhandle_,
                 "ALTER TABLE share_info ADD COLUMN autofill_migration_state "
@@ -1008,6 +1028,60 @@
   return true;
 }
 
+bool DirectoryBackingStore::MigrateVersion74To75() {
+  // In version 74, there was a table 'models':
+  //     blob model_id (entity specifics, primary key)
+  //     int last_download_timestamp
+  //     boolean initial_sync_ended
+  // In version 75, we deprecated the integer-valued last_download_timestamp,
+  // using insted a protobuf-valued progress_marker field:
+  //     blob progress_marker
+  // The progress_marker values are initialized from the value of
+  // last_download_timestamp, thereby preserving the download state.
+
+  // Move aside the old table and create a new empty one at the current schema.
+  if (SQLITE_DONE != ExecQuery(load_dbhandle_,
+          "ALTER TABLE models RENAME TO temp_models")) {
+    return false;
+  }
+  if (!CreateModelsTable())
+    return false;
+
+  SQLStatement query;
+  query.prepare(load_dbhandle_,
+      "SELECT model_id, last_download_timestamp, initial_sync_ended "
+      "FROM temp_models");
+  while (SQLITE_ROW == query.step()) {
+    ModelType type = ModelIdToModelTypeEnum(query.column_blob(0),
+                                            query.column_bytes(0));
+    if (type != UNSPECIFIED) {
+      // Set the |timestamp_token_for_migration| on a new
+      // DataTypeProgressMarker, using the old value of last_download_timestamp.
+      // The server will turn this into a real token on our behalf the next
+      // time we check for updates.
+      sync_pb::DataTypeProgressMarker progress_marker;
+      progress_marker.set_data_type_id(
+          GetExtensionFieldNumberFromModelType(type));
+      progress_marker.set_timestamp_token_for_migration(query.column_int64(1));
+      std::string progress_blob;
+      progress_marker.SerializeToString(&progress_blob);
+
+      SQLStatement update;
+      update.prepare(load_dbhandle_, "INSERT INTO models (model_id, "
+          "progress_marker, initial_sync_ended) VALUES (?, ?, ?)");
+      update.bind_blob(0, query.column_blob(0), query.column_bytes(0));
+      update.bind_blob(1, progress_blob.data(), progress_blob.length());
+      update.bind_bool(2, query.column_bool(2));
+      if (SQLITE_DONE != update.step())
+        return false;
+    }
+  }
+  // Drop the old table.
+  SafeDropTable("temp_models");
+
+  SetVersion(75);
+  return true;
+}
 
 int DirectoryBackingStore::CreateTables() {
   VLOG(1) << "First run, creating tables";
@@ -1106,10 +1180,8 @@
   return ExecQuery(load_dbhandle_, query.c_str());
 }
 
-int DirectoryBackingStore::CreateModelsTable() {
-  // This is the current schema for the Models table, from version 71
-  // onward.  If you change the schema, you'll probably want to double-check
-  // the use of this function in the v70-v71 migration.
+int DirectoryBackingStore::CreateV71ModelsTable() {
+  // This is an old schema for the Models table, used from versions 71 to 74.
   return ExecQuery(load_dbhandle_,
       "CREATE TABLE models ("
       "model_id BLOB primary key, "
@@ -1120,13 +1192,26 @@
       "initial_sync_ended BOOLEAN default 0)");
 }
 
+int DirectoryBackingStore::CreateModelsTable() {
+  // This is the current schema for the Models table, from version 75
+  // onward.  If you change the schema, you'll probably want to double-check
+  // the use of this function in the v74-v75 migration.
+  return ExecQuery(load_dbhandle_,
+      "CREATE TABLE models ("
+      "model_id BLOB primary key, "
+      "progress_marker BLOB, "
+      // Gets set if the syncer ever gets updates from the
+      // server and the server returns 0.  Lets us detect the
+      // end of the initial sync.
+      "initial_sync_ended BOOLEAN default 0)");
+}
+
 int DirectoryBackingStore::CreateShareInfoTable(bool is_temporary) {
   const char* name = is_temporary ? "temp_share_info" : "share_info";
   string query = "CREATE TABLE ";
   query.append(name);
-  // This is the current schema for the ShareInfo table, from version 71
-  // onward.  If you change the schema, you'll probably want to double-check
-  // the use of this function in the v70-v71 migration.
+  // This is the current schema for the ShareInfo table, from version 74
+  // onward.
   query.append(" ("
       "id TEXT primary key, "
       "name TEXT, "
@@ -1151,9 +1236,7 @@
   const char* name = is_temporary ? "temp_share_info" : "share_info";
   string query = "CREATE TABLE ";
   query.append(name);
-  // This is the current schema for the ShareInfo table, from version 71
-  // onward.  If you change the schema, you'll probably want to double-check
-  // the use of this function in the v70-v71 migration.
+  // This is the schema for the ShareInfo table used from versions 71 to 72.
   query.append(" ("
       "id TEXT primary key, "
       "name TEXT, "
diff --git a/chrome/browser/sync/syncable/directory_backing_store.h b/chrome/browser/sync/syncable/directory_backing_store.h
index e7ded8d..7c4efdf 100644
--- a/chrome/browser/sync/syncable/directory_backing_store.h
+++ b/chrome/browser/sync/syncable/directory_backing_store.h
@@ -81,6 +81,7 @@
   FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion71To72);
   FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion72To73);
   FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion73To74);
+  FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion74To75);
   FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, ModelTypeIds);
   FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, Corruption);
   FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, DeleteEntries);
@@ -103,6 +104,7 @@
   int CreateMetasTable(bool is_temporary);
   // Returns an sqlite return code, SQLITE_DONE on success.
   int CreateModelsTable();
+  int CreateV71ModelsTable();
 
   // We don't need to load any synced and applied deleted entries, we can
   // in fact just purge them forever on startup.
@@ -147,13 +149,13 @@
   // the ModelType enum and the values we persist in the database to identify
   // a model.  We persist a default instance of the specifics protobuf as the
   // ID, rather than the enum value.
-  static ModelType ModelIdToModelTypeEnum(const string& model_id);
-  static string ModelTypeEnumToModelId(ModelType model_type);
+  static ModelType ModelIdToModelTypeEnum(const void* data, int length);
+  static std::string ModelTypeEnumToModelId(ModelType model_type);
 
   // Runs an integrity check on the current database.  If the
   // integrity check fails, false is returned and error is populated
   // with an error message.
-  bool CheckIntegrity(sqlite3* handle, string* error) const;
+  bool CheckIntegrity(sqlite3* handle, std::string* error) const;
 
   // Migration utilities.
   bool AddColumn(const ColumnSpec* column);
@@ -175,6 +177,7 @@
   bool MigrateVersion71To72();
   bool MigrateVersion72To73();
   bool MigrateVersion73To74();
+  bool MigrateVersion74To75();
 
   // The handle to our sqlite on-disk store for initialization and loading, and
   // for saving changes periodically via SaveChanges, respectively.
diff --git a/chrome/browser/sync/syncable/directory_backing_store_unittest.cc b/chrome/browser/sync/syncable/directory_backing_store_unittest.cc
index d80200f..db40397 100644
--- a/chrome/browser/sync/syncable/directory_backing_store_unittest.cc
+++ b/chrome/browser/sync/syncable/directory_backing_store_unittest.cc
@@ -49,6 +49,7 @@
   void SetUpVersion71Database();
   void SetUpVersion72Database();
   void SetUpVersion73Database();
+  void SetUpVersion74Database();
 
   void SetUpCurrentDatabaseAndCheckVersion() {
     SetUpVersion70Database();  // Prepopulates data.
@@ -847,6 +848,109 @@
   ASSERT_TRUE(connection.CommitTransaction());
 }
 
+void MigrationTest::SetUpVersion74Database() {
+  sql::Connection connection;
+  ASSERT_TRUE(connection.Open(GetDatabasePath()));
+  ASSERT_TRUE(connection.BeginTransaction());
+  ASSERT_TRUE(connection.Execute(
+      "CREATE TABLE share_version (id VARCHAR(128) primary key, data INT);"
+      "INSERT INTO 'share_version' VALUES('nick@chromium.org',74);"
+      "CREATE TABLE models (model_id BLOB primary key, last_download_timestamp"
+          " INT, initial_sync_ended BOOLEAN default 0);"
+      "INSERT INTO 'models' VALUES(X'C2881000',694,1);"
+      "CREATE TABLE 'share_info' (id TEXT primary key, name TEXT, store_birthd"
+          "ay TEXT, db_create_version TEXT, db_create_time INT, next_id INT de"
+          "fault -2, cache_guid TEXT , notification_state BLOB, autofill_migra"
+          "tion_state INT default 0, bookmarks_added_during_autofill_migration"
+          " INT default 0, autofill_migration_time INT default 0, autofill_ent"
+          "ries_added_during_migration INT default 0, autofill_profiles_added_"
+          "during_migration INT default 0);"
+      "INSERT INTO 'share_info' VALUES('nick@chromium.org','nick@chromium.org'"
+          ",'c27e9f59-08ca-46f8-b0cc-f16a2ed778bb','Unknown',1263522064,-65542"
+          ",'9010788312004066376x-6609234393368420856x',NULL,0,0,0,0,0);"
+      "CREATE TABLE 'metas'(metahandle bigint primary key ON CONFLICT FAIL,bas"
+          "e_version bigint default -1,server_version bigint default 0,mtime b"
+          "igint default 0,server_mtime bigint default 0,ctime bigint default "
+          "0,server_ctime bigint default 0,server_position_in_parent bigint de"
+          "fault 0,local_external_id bigint default 0,id varchar(255) default "
+          "'r',parent_id varchar(255) default 'r',server_parent_id varchar(255"
+          ") default 'r',prev_id varchar(255) default 'r',next_id varchar(255)"
+          " default 'r',is_unsynced bit default 0,is_unapplied_update bit defa"
+          "ult 0,is_del bit default 0,is_dir bit default 0,server_is_dir bit d"
+          "efault 0,server_is_del bit default 0,non_unique_name varchar,server"
+          "_non_unique_name varchar(255),unique_server_tag varchar,unique_clie"
+          "nt_tag varchar,specifics blob,server_specifics blob);"
+      "INSERT INTO 'metas' VALUES(1,-1,0,129079956640320000,0,1290799566403200"
+          "00,0,0,0,'r','r','r','r','r',0,0,0,1,0,0,NULL,NULL,NULL,NULL,X'',X'"
+          "');"
+      "INSERT INTO 'metas' VALUES(2,669,669,128976886618480000,128976886618480"
+          "000,128976886618480000,128976886618480000,-2097152,4,'s_ID_2','s_ID"
+          "_9','s_ID_9','s_ID_2','s_ID_2',0,0,1,0,0,1,'Deleted Item','Deleted "
+          "Item',NULL,NULL,X'C28810220A16687474703A2F2F7777772E676F6F676C652E6"
+          "36F6D2F12084141534741534741',X'C28810260A17687474703A2F2F7777772E67"
+          "6F6F676C652E636F6D2F32120B4153414447414447414447');"
+      "INSERT INTO 'metas' VALUES(4,681,681,129002163642690000,129002163642690"
+          "000,129002163642690000,129002163642690000,-3145728,3,'s_ID_4','s_ID"
+          "_9','s_ID_9','s_ID_4','s_ID_4',0,0,1,0,0,1,'Welcome to Chromium','W"
+          "elcome to Chromium',NULL,NULL,X'C28810350A31687474703A2F2F7777772E6"
+          "76F6F676C652E636F6D2F6368726F6D652F696E746C2F656E2F77656C636F6D652E"
+          "68746D6C1200',X'C28810350A31687474703A2F2F7777772E676F6F676C652E636"
+          "F6D2F6368726F6D652F696E746C2F656E2F77656C636F6D652E68746D6C1200');"
+      "INSERT INTO 'metas' VALUES(5,677,677,129001555500000000,129001555500000"
+          "000,129001555500000000,129001555500000000,1048576,7,'s_ID_5','s_ID_"
+          "9','s_ID_9','s_ID_5','s_ID_5',0,0,1,0,0,1,'Google','Google',NULL,NU"
+          "LL,X'C28810220A16687474703A2F2F7777772E676F6F676C652E636F6D2F120841"
+          "47415347415347',X'C28810220A16687474703A2F2F7777772E676F6F676C652E6"
+          "36F6D2F12084147464447415347');"
+      "INSERT INTO 'metas' VALUES(6,694,694,129053976170000000,129053976170000"
+          "000,129053976170000000,129053976170000000,-4194304,6,'s_ID_6','s_ID"
+          "_9','s_ID_9','r','r',0,0,0,1,1,0,'The Internet','The Internet',NULL"
+          ",NULL,X'C2881000',X'C2881000');"
+      "INSERT INTO 'metas' VALUES(7,663,663,128976864758480000,128976864758480"
+          "000,128976864758480000,128976864758480000,1048576,0,'s_ID_7','r','r"
+          "','r','r',0,0,0,1,1,0,'Google Chrome','Google Chrome','google_chrom"
+          "e',NULL,NULL,NULL);"
+      "INSERT INTO 'metas' VALUES(8,664,664,128976864758480000,128976864758480"
+          "000,128976864758480000,128976864758480000,1048576,0,'s_ID_8','s_ID_"
+          "7','s_ID_7','r','r',0,0,0,1,1,0,'Bookmarks','Bookmarks','google_chr"
+          "ome_bookmarks',NULL,X'C2881000',X'C2881000');"
+      "INSERT INTO 'metas' VALUES(9,665,665,128976864758480000,128976864758480"
+          "000,128976864758480000,128976864758480000,1048576,1,'s_ID_9','s_ID_"
+          "8','s_ID_8','r','s_ID_10',0,0,0,1,1,0,'Bookmark Bar','Bookmark Bar'"
+          ",'bookmark_bar',NULL,X'C2881000',X'C2881000');"
+      "INSERT INTO 'metas' VALUES(10,666,666,128976864758480000,12897686475848"
+          "0000,128976864758480000,128976864758480000,2097152,2,'s_ID_10','s_I"
+          "D_8','s_ID_8','s_ID_9','r',0,0,0,1,1,0,'Other Bookmarks','Other Boo"
+          "kmarks','other_bookmarks',NULL,X'C2881000',X'C2881000');"
+      "INSERT INTO 'metas' VALUES(11,683,683,129079956948440000,12907995694844"
+          "0000,129079956948440000,129079956948440000,-1048576,8,'s_ID_11','s_"
+          "ID_6','s_ID_6','r','s_ID_13',0,0,0,0,0,0,'Home (The Chromium Projec"
+          "ts)','Home (The Chromium Projects)',NULL,NULL,X'C28810220A186874747"
+          "03A2F2F6465762E6368726F6D69756D2E6F72672F1206414741545741',X'C28810"
+          "290A1D687474703A2F2F6465762E6368726F6D69756D2E6F72672F6F74686572120"
+          "84146414756415346');"
+      "INSERT INTO 'metas' VALUES(12,685,685,129079957513650000,12907995751365"
+          "0000,129079957513650000,129079957513650000,0,9,'s_ID_12','s_ID_6','"
+          "s_ID_6','s_ID_13','s_ID_14',0,0,0,1,1,0,'Extra Bookmarks','Extra Bo"
+          "okmarks',NULL,NULL,X'C2881000',X'C2881000');"
+      "INSERT INTO 'metas' VALUES(13,687,687,129079957985300000,12907995798530"
+          "0000,129079957985300000,129079957985300000,-917504,10,'s_ID_13','s_"
+          "ID_6','s_ID_6','s_ID_11','s_ID_12',0,0,0,0,0,0,'ICANN | Internet Co"
+          "rporation for Assigned Names and Numbers','ICANN | Internet Corpora"
+          "tion for Assigned Names and Numbers',NULL,NULL,X'C28810240A15687474"
+          "703A2F2F7777772E6963616E6E2E636F6D2F120B504E474158463041414646',X'C"
+          "28810200A15687474703A2F2F7777772E6963616E6E2E636F6D2F12074441414641"
+          "5346');"
+      "INSERT INTO 'metas' VALUES(14,692,692,129079958383000000,12907995838300"
+          "0000,129079958383000000,129079958383000000,1048576,11,'s_ID_14','s_"
+          "ID_6','s_ID_6','s_ID_12','r',0,0,0,0,0,0,'The WebKit Open Source Pr"
+          "oject','The WebKit Open Source Project',NULL,NULL,X'C288101A0A12687"
+          "474703A2F2F7765626B69742E6F72672F1204504E4758',X'C288101C0A13687474"
+          "703A2F2F7765626B69742E6F72672F781205504E473259');"
+      ));
+  ASSERT_TRUE(connection.CommitTransaction());
+}
+
 TEST_F(DirectoryBackingStoreTest, MigrateVersion67To68) {
   SetUpVersion67Database();
 
@@ -987,7 +1091,7 @@
   std::string model_id = s.ColumnString(0);
   EXPECT_EQ("C2881000", base::HexEncode(model_id.data(), model_id.size()))
       << "Model ID is expected to be the empty BookmarkSpecifics proto.";
-  EXPECT_EQ(true, s.ColumnBool(1));
+  EXPECT_TRUE(s.ColumnBool(1));
   EXPECT_EQ(694, s.ColumnInt64(2));
   ASSERT_FALSE(s.Step());
 }
@@ -1093,6 +1197,35 @@
           "autofill_profiles_added_during_migration"));
 }
 
+TEST_F(DirectoryBackingStoreTest, MigrateVersion74To75) {
+  SetUpVersion74Database();
+
+  {
+    sql::Connection connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_FALSE(connection.DoesColumnExist("models", "progress_marker"));
+    ASSERT_TRUE(connection.DoesColumnExist("models",
+        "last_download_timestamp"));
+  }
+
+  scoped_ptr<DirectoryBackingStore> dbs(
+      new DirectoryBackingStore(GetUsername(), GetDatabasePath()));
+
+  dbs->BeginLoad();
+  ASSERT_FALSE(dbs->needs_column_refresh_);
+  ASSERT_TRUE(dbs->MigrateVersion74To75());
+  ASSERT_EQ(75, dbs->GetVersion());
+  dbs->EndLoad();
+  ASSERT_FALSE(dbs->needs_column_refresh_);
+
+  sql::Connection connection;
+  ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+  ASSERT_TRUE(connection.DoesColumnExist("models", "progress_marker"));
+  ASSERT_FALSE(connection.DoesColumnExist("models",
+      "last_download_timestamp"));
+}
+
 TEST_P(MigrationTest, ToCurrentVersion) {
   switch (GetParam()) {
     case 67:
@@ -1116,6 +1249,9 @@
     case 73:
       SetUpVersion73Database();
       break;
+    case 74:
+      SetUpVersion74Database();
+      break;
     default:
       // If you see this error, it may mean that you've increased the
       // database version number but you haven't finished adding unit tests
@@ -1178,6 +1314,38 @@
     // Columns added in version 74.
     ASSERT_TRUE(connection.DoesColumnExist("share_info",
         "autofill_migration_state"));
+
+    // Column replaced in version 75.
+    ASSERT_TRUE(connection.DoesColumnExist("models", "progress_marker"));
+    ASSERT_FALSE(connection.DoesColumnExist("models",
+        "last_download_timestamp"));
+  }
+  {
+    syncable::Directory::KernelLoadInfo dir_info;
+    dbs->LoadInfo(&dir_info);
+
+    // Check download_progress state (v75 migration)
+    ASSERT_EQ(694,
+        dir_info.kernel_info.download_progress[syncable::BOOKMARKS]
+        .timestamp_token_for_migration());
+    ASSERT_FALSE(
+        dir_info.kernel_info.download_progress[syncable::BOOKMARKS]
+        .has_token());
+    ASSERT_EQ(32904,
+        dir_info.kernel_info.download_progress[syncable::BOOKMARKS]
+        .data_type_id());
+    ASSERT_FALSE(
+        dir_info.kernel_info.download_progress[syncable::THEMES]
+        .has_timestamp_token_for_migration());
+    ASSERT_TRUE(
+        dir_info.kernel_info.download_progress[syncable::THEMES]
+        .has_token());
+    ASSERT_TRUE(
+        dir_info.kernel_info.download_progress[syncable::THEMES]
+        .token().empty());
+    ASSERT_EQ(41210,
+        dir_info.kernel_info.download_progress[syncable::THEMES]
+        .data_type_id());
   }
 
   MetahandlesIndex index;
@@ -1317,7 +1485,8 @@
     std::string model_id =
         DirectoryBackingStore::ModelTypeEnumToModelId(ModelTypeFromInt(i));
     EXPECT_EQ(i,
-        DirectoryBackingStore::ModelIdToModelTypeEnum(model_id));
+        DirectoryBackingStore::ModelIdToModelTypeEnum(model_id.data(),
+                                                      model_id.size()));
   }
 }
 
diff --git a/chrome/browser/sync/syncable/directory_manager.cc b/chrome/browser/sync/syncable/directory_manager.cc
index fbdeb46..989fd0e 100644
--- a/chrome/browser/sync/syncable/directory_manager.cc
+++ b/chrome/browser/sync/syncable/directory_manager.cc
@@ -44,7 +44,7 @@
 }
 
 DirectoryManager::~DirectoryManager() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   DCHECK_EQ(managed_directory_, static_cast<Directory*>(NULL))
       << "Dir " << managed_directory_->name() << " not closed!";
   delete channel_;
@@ -63,7 +63,7 @@
                                          bool* was_open) {
   bool opened = false;
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     // Check to see if it's already open.
     if (managed_directory_) {
       DCHECK_EQ(ComparePathNames(name, managed_directory_->name()), 0)
@@ -79,7 +79,7 @@
   scoped_ptr<Directory> dir(new Directory);
   const DirOpenResult result = dir->Open(path, name);
   if (syncable::OPENED == result) {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     managed_directory_ = dir.release();
   }
   return result;
@@ -90,7 +90,7 @@
 void DirectoryManager::Close(const std::string& name) {
   // Erase from mounted and opened directory lists.
   {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     if (!managed_directory_ ||
         ComparePathNames(name, managed_directory_->name()) != 0) {
       // It wasn't open.
@@ -109,14 +109,14 @@
 }
 
 void DirectoryManager::FinalSaveChangesForAll() {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (managed_directory_)
     managed_directory_->SaveChanges();
 }
 
 void DirectoryManager::GetOpenDirectories(DirNames* result) {
   result->clear();
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (managed_directory_)
     result->push_back(managed_directory_->name());
 }
diff --git a/chrome/browser/sync/syncable/directory_manager.h b/chrome/browser/sync/syncable/directory_manager.h
index 0c0b55d..625d082 100644
--- a/chrome/browser/sync/syncable/directory_manager.h
+++ b/chrome/browser/sync/syncable/directory_manager.h
@@ -18,7 +18,7 @@
 
 #include "base/basictypes.h"
 #include "base/file_path.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/sync/syncable/dir_open_result.h"
 #include "chrome/browser/sync/syncable/path_name_cmp.h"
 #include "chrome/browser/sync/syncable/syncable.h"
@@ -87,7 +87,7 @@
   const FilePath root_path_;
 
   // protects managed_directory_
-  Lock lock_;
+  base::Lock lock_;
   Directory* managed_directory_;
 
   Channel* const channel_;
diff --git a/chrome/browser/sync/syncable/model_type.cc b/chrome/browser/sync/syncable/model_type.cc
index 7bbb29a..0ff67bd 100644
--- a/chrome/browser/sync/syncable/model_type.cc
+++ b/chrome/browser/sync/syncable/model_type.cc
@@ -7,6 +7,7 @@
 #include <sstream>
 
 #include "base/metrics/histogram.h"
+#include "base/values.h"
 #include "chrome/browser/sync/engine/syncproto.h"
 #include "chrome/browser/sync/protocol/app_specifics.pb.h"
 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
@@ -63,6 +64,57 @@
   }
 }
 
+ModelType GetModelTypeFromExtensionFieldNumber(int field_number) {
+  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
+    ModelType model_type = ModelTypeFromInt(i);
+    if (GetExtensionFieldNumberFromModelType(model_type) == field_number)
+      return model_type;
+  }
+  NOTREACHED();
+  return UNSPECIFIED;
+}
+
+int GetExtensionFieldNumberFromModelType(ModelType model_type) {
+  switch (model_type) {
+    case BOOKMARKS:
+      return sync_pb::kBookmarkFieldNumber;
+      break;
+    case PASSWORDS:
+      return sync_pb::kPasswordFieldNumber;
+      break;
+    case PREFERENCES:
+      return sync_pb::kPreferenceFieldNumber;
+      break;
+    case AUTOFILL:
+      return sync_pb::kAutofillFieldNumber;
+      break;
+    case AUTOFILL_PROFILE:
+      return sync_pb::kAutofillProfileFieldNumber;
+      break;
+    case THEMES:
+      return sync_pb::kThemeFieldNumber;
+      break;
+    case TYPED_URLS:
+      return sync_pb::kTypedUrlFieldNumber;
+      break;
+    case EXTENSIONS:
+      return sync_pb::kExtensionFieldNumber;
+      break;
+    case NIGORI:
+      return sync_pb::kNigoriFieldNumber;
+      break;
+    case SESSIONS:
+      return sync_pb::kSessionFieldNumber;
+      break;
+    case APPS:
+      return sync_pb::kAppFieldNumber;
+      break;
+    default:
+      NOTREACHED() << "No known extension for model type.";
+      return 0;
+  }
+}
+
 // Note: keep this consistent with GetModelType in syncable.cc!
 ModelType GetModelType(const sync_pb::SyncEntity& sync_pb_entity) {
   const browser_sync::SyncEntity& sync_entity =
@@ -154,12 +206,12 @@
     case APPS:
       return "Apps";
     case AUTOFILL_PROFILE:
-      return "Autofill Profile";
-      break;
+      return "Autofill Profiles";
     default:
-      NOTREACHED() << "No known extension for model type.";
-      return "INVALID";
+      break;
   }
+  NOTREACHED() << "No known extension for model type.";
+  return "INVALID";
 }
 
 ModelType ModelTypeFromString(const std::string& model_type_string) {
@@ -171,6 +223,8 @@
     return PASSWORDS;
   else if (model_type_string == "Autofill")
     return AUTOFILL;
+  else if (model_type_string == "Autofill Profiles")
+    return AUTOFILL_PROFILE;
   else if (model_type_string == "Themes")
     return THEMES;
   else if (model_type_string == "Typed URLs")
@@ -202,6 +256,18 @@
   return iss.eof();
 }
 
+ListValue* ModelTypeBitSetToValue(const ModelTypeBitSet& model_types) {
+  ListValue* value = new ListValue();
+  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
+    if (model_types[i]) {
+      value->Append(
+          Value::CreateStringValue(
+              ModelTypeToString(ModelTypeFromInt(i))));
+    }
+  }
+  return value;
+}
+
 // For now, this just implements UMA_HISTOGRAM_LONG_TIMES. This can be adjusted
 // if we feel the min, max, or bucket count amount are not appropriate.
 #define SYNC_FREQ_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES( \
@@ -226,6 +292,10 @@
         SYNC_FREQ_HISTOGRAM("Sync.FreqAutofill", time);
         return;
     }
+    case AUTOFILL_PROFILE: {
+        SYNC_FREQ_HISTOGRAM("Sync.FreqAutofillProfiles", time);
+        return;
+    }
     case THEMES: {
         SYNC_FREQ_HISTOGRAM("Sync.FreqThemes", time);
         return;
@@ -270,13 +340,7 @@
 const char kNigoriNotificationType[] = "NIGORI";
 const char kAppNotificationType[] = "APP";
 const char kSessionNotificationType[] = "SESSION";
-// TODO(lipalani) Bug 64111.
-// talk to akalin to make sure this is what I understand this to be.
 const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE";
-// TODO(akalin): This is a hack to make new sync data types work with
-// server-issued notifications.  Remove this when it's not needed
-// anymore.
-const char kUnknownNotificationType[] = "UNKNOWN";
 }  // namespace
 
 bool RealModelTypeToNotificationType(ModelType model_type,
@@ -315,12 +379,6 @@
     case AUTOFILL_PROFILE:
       *notification_type = kAutofillProfileNotificationType;
       return true;
-    // TODO(akalin): This is a hack to make new sync data types work with
-    // server-issued notifications.  Remove this when it's not needed
-    // anymore.
-    case UNSPECIFIED:
-      *notification_type = kUnknownNotificationType;
-      return true;
     default:
       break;
   }
@@ -363,12 +421,6 @@
   } else if (notification_type == kAutofillProfileNotificationType) {
     *model_type = AUTOFILL_PROFILE;
     return true;
-  } else if (notification_type == kUnknownNotificationType) {
-    // TODO(akalin): This is a hack to make new sync data types work with
-    // server-issued notifications.  Remove this when it's not needed
-    // anymore.
-    *model_type = UNSPECIFIED;
-    return true;
   }
   *model_type = UNSPECIFIED;
   return false;
diff --git a/chrome/browser/sync/syncable/model_type.h b/chrome/browser/sync/syncable/model_type.h
index 2760fbe..62f1787 100644
--- a/chrome/browser/sync/syncable/model_type.h
+++ b/chrome/browser/sync/syncable/model_type.h
@@ -17,6 +17,8 @@
 #include "base/logging.h"
 #include "base/time.h"
 
+class ListValue;
+
 namespace sync_pb {
 class EntitySpecifics;
 class SyncEntity;
@@ -93,6 +95,14 @@
 // prefer using GetModelType where possible.
 ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics);
 
+// Determine a model type from the field number of its associated
+// EntitySpecifics extension.
+ModelType GetModelTypeFromExtensionFieldNumber(int field_number);
+
+// Return the field number of the EntitySpecifics extension associated with
+// a model type.
+int GetExtensionFieldNumberFromModelType(ModelType model_type);
+
 // Returns a string that represents the name of |model_type|.
 std::string ModelTypeToString(ModelType model_type);
 
@@ -105,6 +115,9 @@
     const std::string& model_type_bitset_string,
     ModelTypeBitSet* model_types);
 
+// Caller takes ownership of returned list.
+ListValue* ModelTypeBitSetToValue(const ModelTypeBitSet& model_types);
+
 // Posts timedeltas to histogram of datatypes. Allows tracking of the frequency
 // at which datatypes cause syncs.
 void PostTimeToTypeHistogram(ModelType model_type, base::TimeDelta time);
diff --git a/chrome/browser/sync/syncable/model_type_unittest.cc b/chrome/browser/sync/syncable/model_type_unittest.cc
new file mode 100644
index 0000000..b15f0a0
--- /dev/null
+++ b/chrome/browser/sync/syncable/model_type_unittest.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/syncable/model_type.h"
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncable {
+namespace {
+
+class ModelTypeTest : public testing::Test {};
+
+TEST_F(ModelTypeTest, ModelTypeBitSetToValue) {
+  ModelTypeBitSet model_types;
+  model_types.set(syncable::BOOKMARKS);
+  model_types.set(syncable::APPS);
+
+  scoped_ptr<ListValue> value(ModelTypeBitSetToValue(model_types));
+  EXPECT_EQ(2u, value->GetSize());
+  std::string types[2];
+  EXPECT_TRUE(value->GetString(0, &types[0]));
+  EXPECT_TRUE(value->GetString(1, &types[1]));
+  EXPECT_EQ("Bookmarks", types[0]);
+  EXPECT_EQ("Apps", types[1]);
+}
+
+}  // namespace
+}  // namespace syncable
diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
index 2794efa..ac66083 100644
--- a/chrome/browser/sync/syncable/syncable.cc
+++ b/chrome/browser/sync/syncable/syncable.cc
@@ -51,7 +51,6 @@
 #include "chrome/browser/sync/syncable/syncable_changes_version.h"
 #include "chrome/browser/sync/syncable/syncable_columns.h"
 #include "chrome/browser/sync/util/crypto_helpers.h"
-#include "chrome/browser/sync/util/fast_dump.h"
 #include "chrome/common/deprecated/event_sys-inl.h"
 #include "net/base/escape.h"
 
@@ -68,7 +67,6 @@
 static const int kInvariantCheckMaxMs = 50;
 }  // namespace
 
-using browser_sync::FastDump;
 using browser_sync::SyncerUtil;
 using std::string;
 
@@ -176,14 +174,22 @@
 
 Directory::PersistedKernelInfo::PersistedKernelInfo()
     : next_id(0) {
-  for (int i = 0; i < MODEL_TYPE_COUNT; ++i) {
-    last_download_timestamp[i] = 0;
+  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
+    reset_download_progress(ModelTypeFromInt(i));
   }
   autofill_migration_state = NOT_DETERMINED;
 }
 
 Directory::PersistedKernelInfo::~PersistedKernelInfo() {}
 
+void Directory::PersistedKernelInfo::reset_download_progress(
+    ModelType model_type) {
+  download_progress[model_type].set_data_type_id(
+      GetExtensionFieldNumberFromModelType(model_type));
+  // An empty-string token indicates no prior knowledge.
+  download_progress[model_type].set_token(std::string());
+}
+
 Directory::SaveChangesSnapshot::SaveChangesSnapshot()
     : kernel_info_status(KERNEL_SHARE_INFO_INVALID) {
 }
@@ -578,7 +584,7 @@
   bool success = false;
   DCHECK(store_);
 
-  AutoLock scoped_lock(kernel_->save_changes_mutex);
+  base::AutoLock scoped_lock(kernel_->save_changes_mutex);
 
   // Snapshot and save.
   SaveChangesSnapshot snapshot;
@@ -676,7 +682,7 @@
       for (std::set<ModelType>::const_iterator it = types.begin();
            it != types.end(); ++it) {
         set_initial_sync_ended_for_type_unsafe(*it, false);
-        set_last_download_timestamp_unsafe(*it, 0);
+        kernel_->persisted_info.reset_download_progress(*it);
       }
     }
   }
@@ -705,15 +711,27 @@
                                         snapshot.metahandles_to_purge.end());
 }
 
-int64 Directory::last_download_timestamp(ModelType model_type) const {
+void Directory::GetDownloadProgress(
+    ModelType model_type,
+    sync_pb::DataTypeProgressMarker* value_out) const {
   ScopedKernelLock lock(this);
-  return kernel_->persisted_info.last_download_timestamp[model_type];
+  return value_out->CopyFrom(
+      kernel_->persisted_info.download_progress[model_type]);
 }
 
-void Directory::set_last_download_timestamp(ModelType model_type,
-    int64 timestamp) {
+void Directory::GetDownloadProgressAsString(
+    ModelType model_type,
+    std::string* value_out) const {
   ScopedKernelLock lock(this);
-  set_last_download_timestamp_unsafe(model_type, timestamp);
+  kernel_->persisted_info.download_progress[model_type].SerializeToString(
+      value_out);
+}
+
+void Directory::SetDownloadProgress(
+    ModelType model_type,
+    const sync_pb::DataTypeProgressMarker& new_progress) {
+  ScopedKernelLock lock(this);
+  kernel_->persisted_info.download_progress[model_type].CopyFrom(new_progress);
 }
 
 bool Directory::initial_sync_ended_for_type(ModelType type) const {
@@ -811,14 +829,6 @@
   kernel_->info_status = KERNEL_SHARE_INFO_DIRTY;
 }
 
-void Directory::set_last_download_timestamp_unsafe(ModelType model_type,
-                                                   int64 timestamp) {
-  if (kernel_->persisted_info.last_download_timestamp[model_type] == timestamp)
-    return;
-  kernel_->persisted_info.last_download_timestamp[model_type] = timestamp;
-  kernel_->info_status = KERNEL_SHARE_INFO_DIRTY;
-}
-
 void Directory::SetNotificationStateUnsafe(
     const std::string& notification_state) {
   if (notification_state == kernel_->persisted_info.notification_state)
@@ -1049,7 +1059,7 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// ScopedKernelLocks
+// ScopedKernelLock
 
 ScopedKernelLock::ScopedKernelLock(const Directory* dir)
   :  scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) {
@@ -1087,7 +1097,7 @@
       dirkernel_(NULL),
       name_(NULL),
       source_file_(NULL),
-      line_(NULL),
+      line_(0),
       writer_(INVALID) {
 }
 
@@ -1129,7 +1139,7 @@
   {
     // Scoped_lock is only active through the calculate_changes and
     // transaction_ending events.
-    AutoLock scoped_lock(dirkernel_->changes_channel_mutex);
+    base::AutoLock scoped_lock(dirkernel_->changes_channel_mutex);
 
     // Tell listeners to calculate changes while we still have the mutex.
     DirectoryChangeEvent event = { DirectoryChangeEvent::CALCULATE_CHANGES,
@@ -1662,63 +1672,38 @@
   e->Put(SYNCING, false);
 }
 
-}  // namespace syncable
-
-namespace {
-  class DumpSeparator {
-  } separator;
-  class DumpColon {
-  } colon;
-
-inline FastDump& operator<<(FastDump& dump, const DumpSeparator&) {
-  dump.out_->sputn(", ", 2);
-  return dump;
-}
-
-inline FastDump& operator<<(FastDump& dump, const DumpColon&) {
-  dump.out_->sputn(": ", 2);
-  return dump;
-}
-}  // namespace
-
-namespace syncable {
-
-std::ostream& operator<<(std::ostream& stream, const Entry& entry) {
-  // Using ostreams directly here is dreadfully slow, because a mutex is
-  // acquired for every <<.  Users noticed it spiking CPU.
-
+std::ostream& operator<<(std::ostream& os, const Entry& entry) {
   int i;
-  FastDump s(&stream);
   EntryKernel* const kernel = entry.kernel_;
   for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
-    s << g_metas_columns[i].name << colon
-      << kernel->ref(static_cast<Int64Field>(i)) << separator;
+    os << g_metas_columns[i].name << ": "
+       << kernel->ref(static_cast<Int64Field>(i)) << ", ";
   }
   for ( ; i < ID_FIELDS_END; ++i) {
-    s << g_metas_columns[i].name << colon
-      << kernel->ref(static_cast<IdField>(i)) << separator;
+    os << g_metas_columns[i].name << ": "
+       << kernel->ref(static_cast<IdField>(i)) << ", ";
   }
-  s << "Flags: ";
+  os << "Flags: ";
   for ( ; i < BIT_FIELDS_END; ++i) {
     if (kernel->ref(static_cast<BitField>(i)))
-      s << g_metas_columns[i].name << separator;
+      os << g_metas_columns[i].name << ", ";
   }
   for ( ; i < STRING_FIELDS_END; ++i) {
     const string& field = kernel->ref(static_cast<StringField>(i));
-    s << g_metas_columns[i].name << colon << field << separator;
+    os << g_metas_columns[i].name << ": " << field << ", ";
   }
   for ( ; i < PROTO_FIELDS_END; ++i) {
-    s << g_metas_columns[i].name << colon
-      << EscapePath(
-          kernel->ref(static_cast<ProtoField>(i)).SerializeAsString())
-      << separator;
+    os << g_metas_columns[i].name << ": "
+       << EscapePath(
+           kernel->ref(static_cast<ProtoField>(i)).SerializeAsString())
+       << ", ";
   }
-  s << "TempFlags: ";
+  os << "TempFlags: ";
   for ( ; i < BIT_TEMPS_END; ++i) {
     if (kernel->ref(static_cast<BitTemp>(i)))
-      s << "#" << i - BIT_TEMPS_BEGIN << separator;
+      os << "#" << i - BIT_TEMPS_BEGIN << ", ";
   }
-  return stream;
+  return os;
 }
 
 std::ostream& operator<<(std::ostream& s, const Blob& blob) {
@@ -1728,12 +1713,4 @@
   return s << std::dec;
 }
 
-FastDump& operator<<(FastDump& dump, const Blob& blob) {
-  if (blob.empty())
-    return dump;
-  string buffer(base::HexEncode(&blob[0], blob.size()));
-  dump.out_->sputn(buffer.c_str(), buffer.size());
-  return dump;
-}
-
 }  // namespace syncable
diff --git a/chrome/browser/sync/syncable/syncable.h b/chrome/browser/sync/syncable/syncable.h
index cccf417..ba46115 100644
--- a/chrome/browser/sync/syncable/syncable.h
+++ b/chrome/browser/sync/syncable/syncable.h
@@ -18,7 +18,7 @@
 #include "base/basictypes.h"
 #include "base/file_path.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "chrome/browser/sync/protocol/sync.pb.h"
 #include "chrome/browser/sync/syncable/autofill_migration.h"
@@ -557,13 +557,6 @@
 };
 typedef std::set<EntryKernel, LessEntryMetaHandles> OriginalEntries;
 
-// Represents one or more model types sharing an update timestamp, as is
-// the case with a GetUpdates request.
-struct MultiTypeTimeStamp {
-  syncable::ModelTypeBitSet data_types;
-  int64 timestamp;
-};
-
 // a WriteTransaction has a writer tag describing which body of code is doing
 // the write. This is defined up here since DirectoryChangeEvent also contains
 // one.
@@ -666,8 +659,13 @@
     PersistedKernelInfo();
     ~PersistedKernelInfo();
 
+    // Set the |download_progress| entry for the given model to a
+    // "first sync" start point.  When such a value is sent to the server,
+    // a full download of all objects of the model will be initiated.
+    void reset_download_progress(ModelType model_type);
+
     // Last sync timestamp fetched from the server.
-    int64 last_download_timestamp[MODEL_TYPE_COUNT];
+    sync_pb::DataTypeProgressMarker download_progress[MODEL_TYPE_COUNT];
     // true iff we ever reached the end of the changelog.
     ModelTypeBitSet initial_sync_ended;
     // The store birthday we were given by the server. Contents are opaque to
@@ -727,35 +725,17 @@
   const FilePath& file_path() const { return kernel_->db_path; }
   bool good() const { return NULL != store_; }
 
-  // The download timestamp is an index into the server's list of changes for
-  // an account.  We keep this for each datatype.  It doesn't actually map
-  // to any time scale; its name is an historical artifact.
-  int64 last_download_timestamp(ModelType type) const;
-  virtual void set_last_download_timestamp(ModelType type, int64 value);
-
-  // Find the model type or model types which have the least timestamp, and
-  // return them along with the types having that timestamp.  This is done
-  // with the intent of sequencing GetUpdates requests in an efficient way:
-  // bundling together requests that have the same timestamp, and requesting
-  // the oldest such bundles first in hopes that they might catch up to
-  // (and thus be merged with) the newer bundles.
-  MultiTypeTimeStamp GetTypesWithOldestLastDownloadTimestamp(
-      ModelTypeBitSet enabled_types) {
-    MultiTypeTimeStamp result;
-    result.timestamp = std::numeric_limits<int64>::max();
-    for (int i = 0; i < MODEL_TYPE_COUNT; ++i) {
-      if (!enabled_types[i])
-        continue;
-      int64 stamp = last_download_timestamp(ModelTypeFromInt(i));
-      if (stamp < result.timestamp) {
-        result.data_types.reset();
-        result.timestamp = stamp;
-      }
-      if (stamp == result.timestamp)
-        result.data_types.set(i);
-    }
-    return result;
-  }
+  // The download progress is an opaque token provided by the sync server
+  // to indicate the continuation state of the next GetUpdates operation.
+  void GetDownloadProgress(
+      ModelType type,
+      sync_pb::DataTypeProgressMarker* value_out) const;
+  void GetDownloadProgressAsString(
+      ModelType type,
+      std::string* value_out) const;
+  void SetDownloadProgress(
+      ModelType type,
+      const sync_pb::DataTypeProgressMarker& value);
 
   bool initial_sync_ended_for_type(ModelType type) const;
   void set_initial_sync_ended_for_type(ModelType type, bool value);
@@ -827,7 +807,7 @@
     }
   };
  public:
-  typedef EventChannel<DirectoryEventTraits, Lock> Channel;
+  typedef EventChannel<DirectoryEventTraits, base::Lock> Channel;
   typedef std::vector<int64> ChildHandles;
 
   // Returns the child meta handles for given parent id.
@@ -934,7 +914,6 @@
   // on their own; caller must guarantee exclusive access manually by holding
   // a ScopedKernelLock.
   void set_initial_sync_ended_for_type_unsafe(ModelType type, bool x);
-  void set_last_download_timestamp_unsafe(ModelType model_type, int64 x);
   void SetNotificationStateUnsafe(const std::string& notification_state);
 
   Directory& operator = (const Directory&);
@@ -981,7 +960,7 @@
     volatile base::subtle::AtomicWord refcount;
 
     // Implements ReadTransaction / WriteTransaction using a simple lock.
-    Lock transaction_mutex;
+    base::Lock transaction_mutex;
 
     // The name of this directory.
     std::string const name;
@@ -993,7 +972,7 @@
     //
     // Never hold the mutex and do anything with the database or any
     // other buffered IO.  Violating this rule will result in deadlock.
-    Lock mutex;
+    base::Lock mutex;
     MetahandlesIndex* metahandles_index;  // Entries indexed by metahandle
     IdsIndex* ids_index;  // Entries indexed by id
     ParentIdChildIndex* parent_id_child_index;
@@ -1021,7 +1000,7 @@
     // releasing the transaction mutex.
     browser_sync::Channel<DirectoryChangeEvent> changes_channel;
 
-    Lock changes_channel_mutex;
+    base::Lock changes_channel_mutex;
     KernelShareInfoStatus info_status;
 
     // These 3 members are backed in the share_info table, and
@@ -1037,7 +1016,7 @@
 
     // It doesn't make sense for two threads to run SaveChanges at the same
     // time; this mutex protects that activity.
-    Lock save_changes_mutex;
+    base::Lock save_changes_mutex;
 
     // The next metahandle is protected by kernel mutex.
     int64 next_metahandle;
@@ -1057,7 +1036,7 @@
   explicit ScopedKernelLock(const Directory*);
   ~ScopedKernelLock() {}
 
-  AutoLock scoped_lock_;
+  base::AutoLock scoped_lock_;
   Directory* const dir_;
   DISALLOW_COPY_AND_ASSIGN(ScopedKernelLock);
 };
@@ -1157,7 +1136,4 @@
 
 std::ostream& operator <<(std::ostream&, const syncable::Blob&);
 
-browser_sync::FastDump& operator <<
-  (browser_sync::FastDump&, const syncable::Blob&);
-
 #endif  // CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_
diff --git a/chrome/browser/sync/syncable/syncable_id.cc b/chrome/browser/sync/syncable/syncable_id.cc
index 60cf8c9..766289b 100644
--- a/chrome/browser/sync/syncable/syncable_id.cc
+++ b/chrome/browser/sync/syncable/syncable_id.cc
@@ -19,12 +19,6 @@
   return out;
 }
 
-using browser_sync::FastDump;
-FastDump& operator<<(FastDump& dump, const Id& id) {
-  dump.out_->sputn(id.s_.data(), id.s_.size());
-  return dump;
-}
-
 string Id::GetServerId() const {
   // Currently root is the string "0". We need to decide on a true value.
   // "" would be convenient here, as the IsRoot call would not be needed.
diff --git a/chrome/browser/sync/syncable/syncable_id.h b/chrome/browser/sync/syncable/syncable_id.h
index 148fe21..f606867 100644
--- a/chrome/browser/sync/syncable/syncable_id.h
+++ b/chrome/browser/sync/syncable/syncable_id.h
@@ -12,7 +12,6 @@
 #include <string>
 
 #include "base/hash_tables.h"
-#include "chrome/browser/sync/util/fast_dump.h"
 
 extern "C" {
 struct sqlite3;
@@ -31,7 +30,6 @@
 namespace syncable {
 
 std::ostream& operator<<(std::ostream& out, const Id& id);
-browser_sync::FastDump& operator<<(browser_sync::FastDump& out, const Id& id);
 
 // For historical reasons, 3 concepts got everloaded into the Id:
 // 1. A unique, opaque identifier for the object.
@@ -49,8 +47,6 @@
   friend struct syncable::IdRowTraits;
   friend int BindFields(const EntryKernel& entry, SQLStatement* statement);
   friend std::ostream& operator<<(std::ostream& out, const Id& id);
-  friend browser_sync::FastDump& operator<<
-    (browser_sync::FastDump& out, const Id& id);
   friend class MockConnectionManager;
   friend class SyncableIdTest;
  public:
diff --git a/chrome/browser/sync/syncable/syncable_mock.cc b/chrome/browser/sync/syncable/syncable_mock.cc
new file mode 100644
index 0000000..83851cf
--- /dev/null
+++ b/chrome/browser/sync/syncable/syncable_mock.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/syncable/syncable_mock.h"
+
+MockDirectory::MockDirectory() {
+  init_kernel("myk");
+}
+
+MockDirectory::~MockDirectory() {}
+
+MockSyncableWriteTransaction::MockSyncableWriteTransaction(
+    Directory *directory)
+    : WriteTransaction(directory, syncable::UNITTEST, "dontcare.cpp", 25) {
+}
diff --git a/chrome/browser/sync/syncable/syncable_mock.h b/chrome/browser/sync/syncable/syncable_mock.h
index 9412fe0..e6e0912 100644
--- a/chrome/browser/sync/syncable/syncable_mock.h
+++ b/chrome/browser/sync/syncable/syncable_mock.h
@@ -17,9 +17,9 @@
 
 class MockDirectory : public Directory {
  public:
-  MockDirectory() {
-    init_kernel("myk");
-  }
+  MockDirectory();
+  virtual ~MockDirectory();
+
   MOCK_METHOD1(GetEntryByHandle, syncable::EntryKernel*(int64));
 
   MOCK_METHOD2(set_last_downloadstamp, void(syncable::ModelType, int64));
@@ -30,9 +30,7 @@
 
 class MockSyncableWriteTransaction : public syncable::WriteTransaction {
  public:
-  explicit MockSyncableWriteTransaction(Directory *directory) :
-       WriteTransaction(directory, syncable::UNITTEST, "dontcare.cpp", 25) {
-  }
+  explicit MockSyncableWriteTransaction(Directory *directory);
 };
 
 
diff --git a/chrome/browser/sync/syncable/syncable_unittest.cc b/chrome/browser/sync/syncable/syncable_unittest.cc
index 6c887b2..0b49926 100644
--- a/chrome/browser/sync/syncable/syncable_unittest.cc
+++ b/chrome/browser/sync/syncable/syncable_unittest.cc
@@ -323,10 +323,6 @@
     EXPECT_FALSE(dir_->initial_sync_ended_for_type(PREFERENCES));
     EXPECT_FALSE(dir_->initial_sync_ended_for_type(AUTOFILL));
     EXPECT_TRUE(dir_->initial_sync_ended_for_type(BOOKMARKS));
-
-    EXPECT_EQ(0, dir_->last_download_timestamp(PREFERENCES));
-    EXPECT_EQ(0, dir_->last_download_timestamp(AUTOFILL));
-    EXPECT_EQ(1, dir_->last_download_timestamp(BOOKMARKS));
   }
 
   scoped_ptr<Directory> dir_;
@@ -469,12 +465,8 @@
   AddDefaultExtensionValue(PREFERENCES, &preference_specs);
   AddDefaultExtensionValue(AUTOFILL, &autofill_specs);
   dir_->set_initial_sync_ended_for_type(BOOKMARKS, true);
-  dir_->set_last_download_timestamp(BOOKMARKS, 1);
   dir_->set_initial_sync_ended_for_type(PREFERENCES, true);
-  dir_->set_last_download_timestamp(PREFERENCES, 1);
   dir_->set_initial_sync_ended_for_type(AUTOFILL, true);
-  dir_->set_last_download_timestamp(AUTOFILL, 1);
-
 
   std::set<ModelType> types_to_purge;
   types_to_purge.insert(PREFERENCES);
@@ -1000,29 +992,22 @@
 }
 
 TEST_F(SyncableDirectoryTest, TestShareInfo) {
-  dir_->set_last_download_timestamp(AUTOFILL, 100);
-  dir_->set_last_download_timestamp(BOOKMARKS, 1000);
   dir_->set_initial_sync_ended_for_type(AUTOFILL, true);
   dir_->set_store_birthday("Jan 31st");
   dir_->SetNotificationState("notification_state");
   {
     ReadTransaction trans(dir_.get(), __FILE__, __LINE__);
-    EXPECT_EQ(100, dir_->last_download_timestamp(AUTOFILL));
-    EXPECT_EQ(1000, dir_->last_download_timestamp(BOOKMARKS));
     EXPECT_TRUE(dir_->initial_sync_ended_for_type(AUTOFILL));
     EXPECT_FALSE(dir_->initial_sync_ended_for_type(BOOKMARKS));
     EXPECT_EQ("Jan 31st", dir_->store_birthday());
     EXPECT_EQ("notification_state", dir_->GetAndClearNotificationState());
     EXPECT_EQ("", dir_->GetAndClearNotificationState());
   }
-  dir_->set_last_download_timestamp(AUTOFILL, 200);
   dir_->set_store_birthday("April 10th");
   dir_->SetNotificationState("notification_state2");
   dir_->SaveChanges();
   {
     ReadTransaction trans(dir_.get(), __FILE__, __LINE__);
-    EXPECT_EQ(200, dir_->last_download_timestamp(AUTOFILL));
-    EXPECT_EQ(1000, dir_->last_download_timestamp(BOOKMARKS));
     EXPECT_TRUE(dir_->initial_sync_ended_for_type(AUTOFILL));
     EXPECT_FALSE(dir_->initial_sync_ended_for_type(BOOKMARKS));
     EXPECT_EQ("April 10th", dir_->store_birthday());
@@ -1034,8 +1019,6 @@
   SaveAndReloadDir();
   {
     ReadTransaction trans(dir_.get(), __FILE__, __LINE__);
-    EXPECT_EQ(200, dir_->last_download_timestamp(AUTOFILL));
-    EXPECT_EQ(1000, dir_->last_download_timestamp(BOOKMARKS));
     EXPECT_TRUE(dir_->initial_sync_ended_for_type(AUTOFILL));
     EXPECT_FALSE(dir_->initial_sync_ended_for_type(BOOKMARKS));
     EXPECT_EQ("April 10th", dir_->store_birthday());
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
new file mode 100644
index 0000000..ed4668e
--- /dev/null
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -0,0 +1,280 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/sync/test_profile_sync_service.h"
+
+#include "chrome/browser/sync/abstract_profile_sync_service_test.h"
+#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/data_type_controller.h"
+#include "chrome/browser/sync/glue/sync_backend_host.h"
+#include "chrome/browser/sync/profile_sync_factory.h"
+#include "chrome/browser/sync/sessions/session_state.h"
+#include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/syncable/syncable.h"
+#include "chrome/test/sync/test_http_bridge_factory.h"
+
+using browser_sync::ModelSafeRoutingInfo;
+using browser_sync::sessions::ErrorCounters;
+using browser_sync::sessions::SyncSourceInfo;
+using browser_sync::sessions::SyncerStatus;
+using browser_sync::sessions::SyncSessionSnapshot;
+using syncable::DirectoryManager;
+using syncable::ModelType;
+using syncable::ScopedDirLookup;
+using sync_api::UserShare;
+
+ACTION_P(CallOnPaused, core) {
+  core->OnPaused();
+};
+
+ACTION_P(CallOnResumed, core) {
+  core->OnResumed();
+}
+
+namespace browser_sync {
+
+SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest(
+    Profile* profile,
+    int num_expected_resumes,
+    int num_expected_pauses,
+    bool set_initial_sync_ended_on_init,
+    bool synchronous_init)
+    : browser_sync::SyncBackendHost(profile),
+      synchronous_init_(synchronous_init) {
+  // By default, the RequestPause and RequestResume methods will
+  // send the confirmation notification and return true.
+  ON_CALL(*this, RequestPause()).
+      WillByDefault(testing::DoAll(CallOnPaused(core_),
+                                   testing::Return(true)));
+  ON_CALL(*this, RequestResume()).
+      WillByDefault(testing::DoAll(CallOnResumed(core_),
+                                   testing::Return(true)));
+  ON_CALL(*this, RequestNudge()).WillByDefault(
+      testing::Invoke(this,
+                      &SyncBackendHostForProfileSyncTest::
+                      SimulateSyncCycleCompletedInitialSyncEnded));
+
+  EXPECT_CALL(*this, RequestPause()).Times(num_expected_pauses);
+  EXPECT_CALL(*this, RequestResume()).Times(num_expected_resumes);
+  EXPECT_CALL(*this,
+              RequestNudge()).Times(set_initial_sync_ended_on_init ? 0 : 1);
+}
+
+SyncBackendHostForProfileSyncTest::~SyncBackendHostForProfileSyncTest() {}
+
+void SyncBackendHostForProfileSyncTest::ConfigureDataTypes(
+    const DataTypeController::TypeMap& data_type_controllers,
+    const syncable::ModelTypeSet& types,
+    CancelableTask* ready_task) {
+  SetAutofillMigrationState(syncable::MIGRATED);
+  SyncBackendHost::ConfigureDataTypes(
+      data_type_controllers, types, ready_task);
+}
+
+void SyncBackendHostForProfileSyncTest::
+    SimulateSyncCycleCompletedInitialSyncEnded() {
+  syncable::ModelTypeBitSet sync_ended;
+  ModelSafeRoutingInfo enabled_types;
+  GetModelSafeRoutingInfo(&enabled_types);
+  std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
+  for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin();
+       i != enabled_types.end(); ++i) {
+    sync_ended.set(i->first);
+  }
+  core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot(
+      SyncerStatus(), ErrorCounters(), 0, false,
+      sync_ended, download_progress_markers, false, false, 0, 0, false,
+      SyncSourceInfo()));
+}
+
+sync_api::HttpPostProviderFactory*
+    SyncBackendHostForProfileSyncTest::MakeHttpBridgeFactory(
+        URLRequestContextGetter* getter) {
+  return new browser_sync::TestHttpBridgeFactory;
+}
+
+void SyncBackendHostForProfileSyncTest::InitCore(
+    const Core::DoInitializeOptions& options) {
+  std::wstring user = L"testuser";
+  core_loop()->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(core_.get(),
+                        &SyncBackendHost::Core::DoInitializeForTest,
+                        user,
+                        options.http_bridge_factory,
+                        options.delete_sync_data_folder));
+
+  // TODO(akalin): Figure out a better way to do this.
+  if (synchronous_init_) {
+    // The SyncBackend posts a task to the current loop when
+    // initialization completes.
+    MessageLoop::current()->Run();
+  }
+}
+
+JsBackend* SyncBackendHostForProfileSyncTest::GetJsBackend() {
+  // Return a non-NULL result only when the overridden function does.
+  if (SyncBackendHost::GetJsBackend()) {
+    return this;
+  } else {
+    NOTREACHED();
+    return NULL;
+  }
+}
+
+void SyncBackendHostForProfileSyncTest::SetParentJsEventRouter(
+    JsEventRouter* router) {
+  core_->SetParentJsEventRouter(router);
+}
+
+void SyncBackendHostForProfileSyncTest::RemoveParentJsEventRouter() {
+  core_->RemoveParentJsEventRouter();
+}
+
+const JsEventRouter*
+    SyncBackendHostForProfileSyncTest::GetParentJsEventRouter() const {
+  return core_->GetParentJsEventRouter();
+}
+
+void SyncBackendHostForProfileSyncTest::ProcessMessage(
+    const std::string& name, const JsArgList& args,
+    const JsEventHandler* sender) {
+  if (name.find("delay") != name.npos) {
+    core_->RouteJsEvent(name, args, sender);
+  } else {
+    core_->RouteJsEventOnFrontendLoop(name, args, sender);
+  }
+}
+
+void SyncBackendHostForProfileSyncTest::
+    SetDefaultExpectationsForWorkerCreation(ProfileMock* profile) {
+  EXPECT_CALL(*profile, GetPasswordStore(testing::_)).
+      WillOnce(testing::Return((PasswordStore*)NULL));
+}
+
+void SyncBackendHostForProfileSyncTest::SetHistoryServiceExpectations(
+    ProfileMock* profile) {
+  EXPECT_CALL(*profile, GetHistoryService(testing::_)).
+      WillOnce(testing::Return((HistoryService*)NULL));
+}
+
+}  // namespace browser_sync
+
+browser_sync::TestIdFactory* TestProfileSyncService::id_factory() {
+  return &id_factory_;
+}
+
+browser_sync::SyncBackendHostForProfileSyncTest*
+    TestProfileSyncService::GetBackendForTest() {
+  return static_cast<browser_sync::SyncBackendHostForProfileSyncTest*>(
+      ProfileSyncService::GetBackendForTest());
+}
+
+TestProfileSyncService::TestProfileSyncService(
+    ProfileSyncFactory* factory,
+                       Profile* profile,
+                       const std::string& test_user,
+                       bool synchronous_backend_initialization,
+                       Task* initial_condition_setup_task)
+    : ProfileSyncService(factory, profile, test_user),
+      synchronous_backend_initialization_(
+          synchronous_backend_initialization),
+      synchronous_sync_configuration_(false),
+      num_expected_resumes_(1),
+      num_expected_pauses_(1),
+      initial_condition_setup_task_(initial_condition_setup_task),
+      set_initial_sync_ended_on_init_(true) {
+  RegisterPreferences();
+  SetSyncSetupCompleted();
+}
+
+TestProfileSyncService::~TestProfileSyncService() {}
+
+void TestProfileSyncService::SetInitialSyncEndedForEnabledTypes() {
+  UserShare* user_share = GetUserShare();
+  DirectoryManager* dir_manager = user_share->dir_manager.get();
+
+  ScopedDirLookup dir(dir_manager, user_share->name);
+  if (!dir.good())
+    FAIL();
+
+  ModelSafeRoutingInfo enabled_types;
+  backend_->GetModelSafeRoutingInfo(&enabled_types);
+  for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin();
+       i != enabled_types.end(); ++i) {
+    dir->set_initial_sync_ended_for_type(i->first, true);
+  }
+}
+
+void TestProfileSyncService::OnBackendInitialized() {
+  // Set this so below code can access GetUserShare().
+  backend_initialized_ = true;
+
+  // Set up any nodes the test wants around before model association.
+  if (initial_condition_setup_task_) {
+    initial_condition_setup_task_->Run();
+    initial_condition_setup_task_ = NULL;
+  }
+
+  // Pretend we downloaded initial updates and set initial sync ended bits
+  // if we were asked to.
+  if (set_initial_sync_ended_on_init_) {
+    UserShare* user_share = GetUserShare();
+    DirectoryManager* dir_manager = user_share->dir_manager.get();
+
+    ScopedDirLookup dir(dir_manager, user_share->name);
+    if (!dir.good())
+      FAIL();
+
+    if (!dir->initial_sync_ended_for_type(syncable::NIGORI)) {
+      ProfileSyncServiceTestHelper::CreateRoot(
+          syncable::NIGORI, GetUserShare(),
+          id_factory());
+    }
+
+    SetInitialSyncEndedForEnabledTypes();
+  }
+
+  ProfileSyncService::OnBackendInitialized();
+
+  // TODO(akalin): Figure out a better way to do this.
+  if (synchronous_backend_initialization_) {
+    MessageLoop::current()->Quit();
+  }
+}
+
+void TestProfileSyncService::Observe(NotificationType type,
+                                     const NotificationSource& source,
+                                     const NotificationDetails& details) {
+  ProfileSyncService::Observe(type, source, details);
+  if (type == NotificationType::SYNC_CONFIGURE_DONE &&
+      !synchronous_sync_configuration_) {
+    MessageLoop::current()->Quit();
+  }
+}
+
+void TestProfileSyncService::set_num_expected_resumes(int times) {
+  num_expected_resumes_ = times;
+}
+void TestProfileSyncService::set_num_expected_pauses(int num) {
+  num_expected_pauses_ = num;
+}
+void TestProfileSyncService::dont_set_initial_sync_ended_on_init() {
+  set_initial_sync_ended_on_init_ = false;
+}
+void TestProfileSyncService::set_synchronous_sync_configuration() {
+  synchronous_sync_configuration_ = true;
+}
+
+void TestProfileSyncService::CreateBackend() {
+  backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest(
+      profile(),
+      num_expected_resumes_, num_expected_pauses_,
+      set_initial_sync_ended_on_init_,
+      synchronous_backend_initialization_));
+}
+
+std::string TestProfileSyncService::GetLsidForAuthBootstraping() {
+  return "foo";
+}
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index 2615b24..c027725 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -8,38 +8,16 @@
 
 #include <string>
 
-#include "base/message_loop.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/profile_sync_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/glue/data_type_controller.h"
 #include "chrome/browser/sync/glue/data_type_manager_impl.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/sessions/session_state.h"
-#include "chrome/browser/sync/syncable/directory_manager.h"
-#include "chrome/browser/sync/syncable/syncable.h"
+#include "chrome/browser/sync/js_backend.h"
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/test/profile_mock.h"
-#include "chrome/test/sync/test_http_bridge_factory.h"
+#include "chrome/test/sync/engine/test_id_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 class Profile;
-
-using browser_sync::ModelSafeRoutingInfo;
-using browser_sync::sessions::ErrorCounters;
-using browser_sync::sessions::SyncerStatus;
-using browser_sync::sessions::SyncSessionSnapshot;
-using sync_api::UserShare;
-using syncable::DirectoryManager;
-using syncable::ModelType;
-using syncable::ScopedDirLookup;
-
-ACTION_P(CallOnPaused, core) {
-  core->OnPaused();
-};
-
-ACTION_P(CallOnResumed, core) {
-  core->OnResumed();
-}
+class Task;
+class TestProfileSyncService;
 
 ACTION(ReturnNewDataTypeManager) {
   return new browser_sync::DataTypeManagerImpl(arg0, arg1);
@@ -51,135 +29,53 @@
 // running in these tests, and allows tests to provide a task on construction
 // to set up initial nodes to mock out an actual server initial sync
 // download.
-class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
+class SyncBackendHostForProfileSyncTest
+    : public SyncBackendHost, public JsBackend {
  public:
-  // |initial_condition_setup_task| can be used to populate nodes before the
-  //     OnBackendInitialized callback fires.
-  // |set_initial_sync_ended_on_init| determines whether we pretend that a full
-  //     initial download has occurred and set bits for enabled data types.  If
-  //     this is false, configuring data types will require a syncer nudge.
   // |synchronous_init| causes initialization to block until the syncapi has
   //     completed setting itself up and called us back.
-  SyncBackendHostForProfileSyncTest(SyncFrontend* frontend,
+  SyncBackendHostForProfileSyncTest(
       Profile* profile,
-      const FilePath& profile_path,
-      const DataTypeController::TypeMap& data_type_controllers,
-      Task* initial_condition_setup_task,
       int num_expected_resumes,
       int num_expected_pauses,
       bool set_initial_sync_ended_on_init,
-      bool synchronous_init)
-      : browser_sync::SyncBackendHost(frontend, profile, profile_path,
-                                      data_type_controllers),
-        initial_condition_setup_task_(initial_condition_setup_task),
-        set_initial_sync_ended_on_init_(set_initial_sync_ended_on_init),
-        synchronous_init_(synchronous_init) {
-    // By default, the RequestPause and RequestResume methods will
-    // send the confirmation notification and return true.
-    ON_CALL(*this, RequestPause()).
-        WillByDefault(testing::DoAll(CallOnPaused(core_),
-                                     testing::Return(true)));
-    ON_CALL(*this, RequestResume()).
-        WillByDefault(testing::DoAll(CallOnResumed(core_),
-                                     testing::Return(true)));
-    ON_CALL(*this, RequestNudge()).WillByDefault(testing::Invoke(this,
-         &SyncBackendHostForProfileSyncTest::
-             SimulateSyncCycleCompletedInitialSyncEnded));
-
-    EXPECT_CALL(*this, RequestPause()).Times(num_expected_pauses);
-    EXPECT_CALL(*this, RequestResume()).Times(num_expected_resumes);
-    EXPECT_CALL(*this, RequestNudge()).
-        Times(set_initial_sync_ended_on_init ? 0 : 1);
-  }
+      bool synchronous_init);
+  virtual ~SyncBackendHostForProfileSyncTest();
 
   MOCK_METHOD0(RequestPause, bool());
   MOCK_METHOD0(RequestResume, bool());
   MOCK_METHOD0(RequestNudge, void());
 
-  void SetInitialSyncEndedForEnabledTypes() {
-    UserShare* user_share = core_->syncapi()->GetUserShare();
-    DirectoryManager* dir_manager = user_share->dir_manager.get();
-
-    ScopedDirLookup dir(dir_manager, user_share->name);
-    if (!dir.good())
-      FAIL();
-
-    ModelSafeRoutingInfo enabled_types;
-    GetModelSafeRoutingInfo(&enabled_types);
-    for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin();
-         i != enabled_types.end(); ++i) {
-      dir->set_initial_sync_ended_for_type(i->first, true);
-    }
-  }
-
-  virtual void ConfigureDataTypes(const syncable::ModelTypeSet& types,
-      CancelableTask* ready_task) {
-    SetAutofillMigrationState(syncable::MIGRATED);
-    SyncBackendHost::ConfigureDataTypes(types, ready_task);
-  }
-
-  virtual void HandleInitializationCompletedOnFrontendLoop() {
-    set_syncapi_initialized();  // Need to do this asap so task below works.
-
-    // Set up any nodes the test wants around before model association.
-    if (initial_condition_setup_task_) {
-      initial_condition_setup_task_->Run();
-    }
-
-    // Pretend we downloaded initial updates and set initial sync ended bits
-    // if we were asked to.
-    if (set_initial_sync_ended_on_init_)
-      SetInitialSyncEndedForEnabledTypes();
-
-    SyncBackendHost::HandleInitializationCompletedOnFrontendLoop();
-  }
+  virtual void ConfigureDataTypes(
+      const DataTypeController::TypeMap& data_type_controllers,
+      const syncable::ModelTypeSet& types,
+      CancelableTask* ready_task);
 
   // Called when a nudge comes in.
-  void SimulateSyncCycleCompletedInitialSyncEnded() {
-    syncable::ModelTypeBitSet sync_ended;
-    ModelSafeRoutingInfo enabled_types;
-    GetModelSafeRoutingInfo(&enabled_types);
-    for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin();
-         i != enabled_types.end(); ++i) {
-      sync_ended.set(i->first);
-    }
-    core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot(
-        SyncerStatus(), ErrorCounters(), 0, 0, false,
-        sync_ended, false, false, 0, 0, false));
-  }
+  void SimulateSyncCycleCompletedInitialSyncEnded();
 
   virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory(
-      URLRequestContextGetter* getter) {
-    return new browser_sync::TestHttpBridgeFactory;
-  }
+      URLRequestContextGetter* getter);
 
-  virtual void InitCore(const Core::DoInitializeOptions& options) {
-    std::wstring user = L"testuser";
-    core_loop()->PostTask(FROM_HERE,
-        NewRunnableMethod(core_.get(),
-        &SyncBackendHost::Core::DoInitializeForTest,
-        user,
-        options.http_bridge_factory,
-        options.delete_sync_data_folder));
+  virtual void InitCore(const Core::DoInitializeOptions& options);
 
-    // TODO(akalin): Figure out a better way to do this.
-    if (synchronous_init_) {
-      // The SyncBackend posts a task to the current loop when
-      // initialization completes.
-      MessageLoop::current()->Run();
-    }
-  }
+  virtual JsBackend* GetJsBackend();
 
-  static void SetDefaultExpectationsForWorkerCreation(ProfileMock* profile) {
-    EXPECT_CALL(*profile, GetPasswordStore(testing::_)).
-        WillOnce(testing::Return((PasswordStore*)NULL));
-    EXPECT_CALL(*profile, GetHistoryService(testing::_)).
-        WillOnce(testing::Return((HistoryService*)NULL));
-  }
+  // JsBackend implementation.
+  virtual void SetParentJsEventRouter(JsEventRouter* router);
+  virtual void RemoveParentJsEventRouter();
+  virtual const JsEventRouter* GetParentJsEventRouter() const;
+  // Fires an event identical to the message unless the message has
+  // "delay" as a prefix, in which case a task to fire the identical
+  // event is posted instead.
+  virtual void ProcessMessage(const std::string& name, const JsArgList& args,
+                              const JsEventHandler* sender);
+
+  static void SetDefaultExpectationsForWorkerCreation(ProfileMock* profile);
+
+  static void SetHistoryServiceExpectations(ProfileMock* profile);
 
  private:
-  Task* initial_condition_setup_task_;
-  bool set_initial_sync_ended_on_init_;
   bool synchronous_init_;
 };
 
@@ -187,73 +83,49 @@
 
 class TestProfileSyncService : public ProfileSyncService {
  public:
+  // |initial_condition_setup_task| can be used to populate nodes
+  // before the OnBackendInitialized callback fires.
   TestProfileSyncService(ProfileSyncFactory* factory,
                          Profile* profile,
                          const std::string& test_user,
                          bool synchronous_backend_initialization,
-                         Task* initial_condition_setup_task)
-      : ProfileSyncService(factory, profile,
-                           !test_user.empty() ?
-                           test_user : ""),
-        synchronous_backend_initialization_(
-            synchronous_backend_initialization),
-        synchronous_sync_configuration_(false),
-        num_expected_resumes_(1),
-        num_expected_pauses_(1),
-        initial_condition_setup_task_(initial_condition_setup_task),
-        set_initial_sync_ended_on_init_(true) {
-    RegisterPreferences();
-    SetSyncSetupCompleted();
-  }
-  virtual ~TestProfileSyncService() { }
+                         Task* initial_condition_setup_task);
 
-  virtual void CreateBackend() {
-    backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest(
-        this, profile(),
-        profile()->GetPath(), data_type_controllers(),
-        initial_condition_setup_task_.release(),
-        num_expected_resumes_, num_expected_pauses_,
-        set_initial_sync_ended_on_init_,
-        synchronous_backend_initialization_));
-  }
+  virtual ~TestProfileSyncService();
 
-  virtual void OnBackendInitialized() {
-    ProfileSyncService::OnBackendInitialized();
-    // TODO(akalin): Figure out a better way to do this.
-    if (synchronous_backend_initialization_) {
-      MessageLoop::current()->Quit();
-    }
-  }
+  void SetInitialSyncEndedForEnabledTypes();
+
+  virtual void OnBackendInitialized();
 
   virtual void Observe(NotificationType type,
-                      const NotificationSource& source,
-                      const NotificationDetails& details) {
-    ProfileSyncService::Observe(type, source, details);
-    if (type == NotificationType::SYNC_CONFIGURE_DONE &&
-        !synchronous_sync_configuration_) {
-      MessageLoop::current()->Quit();
-    }
-  }
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
 
-  void set_num_expected_resumes(int times) {
-    num_expected_resumes_ = times;
-  }
-  void set_num_expected_pauses(int num) {
-    num_expected_pauses_ = num;
-  }
-  void dont_set_initial_sync_ended_on_init() {
-    set_initial_sync_ended_on_init_ = false;
-  }
-  void set_synchronous_sync_configuration() {
-    synchronous_sync_configuration_ = true;
-  }
+  void set_num_expected_resumes(int times);
+  void set_num_expected_pauses(int num);
+
+  // If this is called, configuring data types will require a syncer
+  // nudge.
+  void dont_set_initial_sync_ended_on_init();
+  void set_synchronous_sync_configuration();
+
+  browser_sync::TestIdFactory* id_factory();
+
+  // Override of ProfileSyncService::GetBackendForTest() with a more
+  // specific return type (since C++ supports covariant return types)
+  // that is made public.
+  virtual browser_sync::SyncBackendHostForProfileSyncTest*
+      GetBackendForTest();
+
+ protected:
+  virtual void CreateBackend();
 
  private:
   // When testing under ChromiumOS, this method must not return an empty
   // value value in order for the profile sync service to start.
-  virtual std::string GetLsidForAuthBootstraping() {
-    return "foo";
-  }
+  virtual std::string GetLsidForAuthBootstraping();
+
+  browser_sync::TestIdFactory id_factory_;
 
   bool synchronous_backend_initialization_;
 
@@ -264,8 +136,10 @@
   int num_expected_resumes_;
   int num_expected_pauses_;
 
-  scoped_ptr<Task> initial_condition_setup_task_;
+  Task* initial_condition_setup_task_;
   bool set_initial_sync_ended_on_init_;
 };
 
+
+
 #endif  // CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_
diff --git a/chrome/browser/sync/tools/sync_listen_notifications.cc b/chrome/browser/sync/tools/sync_listen_notifications.cc
index 0f66c27..35dfeff 100644
--- a/chrome/browser/sync/tools/sync_listen_notifications.cc
+++ b/chrome/browser/sync/tools/sync_listen_notifications.cc
@@ -153,16 +153,10 @@
  public:
   ChromeInvalidationListener() {}
 
-  virtual void OnInvalidate(syncable::ModelType model_type) {
-    // TODO(akalin): This is a hack to make new sync data types work
-    // with server-issued notifications.  Remove this when it's not
-    // needed anymore.
-    if (model_type == syncable::UNSPECIFIED) {
-      LOG(INFO) << "OnInvalidate: UNKNOWN";
-    } else {
-      LOG(INFO) << "OnInvalidate: "
-                << syncable::ModelTypeToString(model_type);
-    }
+  virtual void OnInvalidate(syncable::ModelType model_type,
+                            const std::string& payload) {
+    LOG(INFO) << "OnInvalidate: "
+              << syncable::ModelTypeToString(model_type) << " - " << payload;
     // A real implementation would respond to the invalidation.
   }
 
@@ -192,7 +186,9 @@
 
     // TODO(akalin): app_name should be per-client unique.
     const std::string kAppName = "cc_sync_listen_notifications";
-    chrome_invalidation_client_.Start(kAppName, server_notifier_state_,
+    const std::string kAppInfo = kAppName;
+    chrome_invalidation_client_.Start(kAppName, kAppInfo,
+                                      server_notifier_state_,
                                       &chrome_invalidation_listener_,
                                       this, base_task);
     chrome_invalidation_client_.RegisterTypes();
@@ -222,9 +218,12 @@
 int main(int argc, char* argv[]) {
   base::AtExitManager exit_manager;
   CommandLine::Init(argc, argv);
-  logging::InitLogging(NULL, logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
-                       logging::LOCK_LOG_FILE, logging::DELETE_OLD_LOG_FILE);
-  logging::SetMinLogLevel(logging::LOG_INFO);
+  logging::InitLogging(
+      NULL,
+      logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
+      logging::LOCK_LOG_FILE,
+      logging::DELETE_OLD_LOG_FILE,
+      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
   // TODO(akalin): Make sure that all log messages are printed to the
   // console, even on Windows (SetMinLogLevel isn't enough).
   talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
diff --git a/chrome/browser/sync/util/channel.h b/chrome/browser/sync/util/channel.h
index 88ddfc4..839d653 100644
--- a/chrome/browser/sync/util/channel.h
+++ b/chrome/browser/sync/util/channel.h
@@ -50,8 +50,8 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "base/lock.h"
 #include "base/observer_list.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 
 namespace browser_sync {
@@ -98,7 +98,7 @@
 
   ChannelHookup<EventType>* AddObserver(
       ChannelEventHandler<EventType>* observer) {
-    AutoLock scoped_lock(event_handlers_mutex_);
+    base::AutoLock scoped_lock(event_handlers_mutex_);
     event_handlers_.AddObserver(observer);
     return new ChannelHookup<EventType>(this, observer);
   }
@@ -117,7 +117,7 @@
   }
 
   void Notify(const EventType& event) {
-    AutoLock scoped_lock(event_handlers_mutex_);
+    base::AutoLock scoped_lock(event_handlers_mutex_);
 
     // This may result in an observer trying to remove itself, so keep track
     // of the thread we're locked on.
@@ -135,7 +135,7 @@
   }
 
  private:
-  Lock event_handlers_mutex_;
+  base::Lock event_handlers_mutex_;
   base::PlatformThreadId locking_thread_;
   ObserverList<EventHandler> event_handlers_;
 };
diff --git a/chrome/browser/sync/util/extensions_activity_monitor.cc b/chrome/browser/sync/util/extensions_activity_monitor.cc
index aad4ab6..8c7a52a 100644
--- a/chrome/browser/sync/util/extensions_activity_monitor.cc
+++ b/chrome/browser/sync/util/extensions_activity_monitor.cc
@@ -65,13 +65,13 @@
 }
 
 void ExtensionsActivityMonitor::GetAndClearRecords(Records* buffer) {
-  AutoLock lock(records_lock_);
+  base::AutoLock lock(records_lock_);
   buffer->clear();
   buffer->swap(records_);
 }
 
 void ExtensionsActivityMonitor::PutRecords(const Records& records) {
-  AutoLock lock(records_lock_);
+  base::AutoLock lock(records_lock_);
   for (Records::const_iterator i = records.begin(); i != records.end(); ++i) {
     records_[i->first].extension_id = i->second.extension_id;
     records_[i->first].bookmark_write_count += i->second.bookmark_write_count;
@@ -81,7 +81,7 @@
 void ExtensionsActivityMonitor::Observe(NotificationType type,
                                         const NotificationSource& source,
                                         const NotificationDetails& details) {
-  AutoLock lock(records_lock_);
+  base::AutoLock lock(records_lock_);
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   const Extension* extension = Source<const Extension>(source).ptr();
   const BookmarksFunction* f = Details<const BookmarksFunction>(details).ptr();
diff --git a/chrome/browser/sync/util/extensions_activity_monitor.h b/chrome/browser/sync/util/extensions_activity_monitor.h
index f4d1037..f19090d 100644
--- a/chrome/browser/sync/util/extensions_activity_monitor.h
+++ b/chrome/browser/sync/util/extensions_activity_monitor.h
@@ -8,8 +8,8 @@
 
 #include <map>
 
-#include "base/lock.h"
 #include "base/message_loop.h"
+#include "base/synchronization/lock.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
@@ -62,7 +62,7 @@
                        const NotificationDetails& details);
  private:
   Records records_;
-  mutable Lock records_lock_;
+  mutable base::Lock records_lock_;
 
   // Used only from UI loop.
   NotificationRegistrar registrar_;
diff --git a/chrome/browser/sync/util/fast_dump.h b/chrome/browser/sync/util/fast_dump.h
deleted file mode 100644
index 44e48c1..0000000
--- a/chrome/browser/sync/util/fast_dump.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_UTIL_FAST_DUMP_H_
-#define CHROME_BROWSER_SYNC_UTIL_FAST_DUMP_H_
-#pragma once
-
-#include <ostream>
-#include <streambuf>
-#include <string>
-
-#include "base/string_number_conversions.h"
-
-using std::ostream;
-using std::streambuf;
-using std::string;
-
-// This seems totally gratuitous, and it would be if std::ostream was fast, but
-// std::ostream is slow. It's slow because it creates a ostream::sentry (mutex)
-// for every little << operator. When you want to dump a whole lot of stuff
-// under a single mutex lock, use this FastDump class.
-namespace browser_sync {
-class FastDump {
- public:
-  explicit FastDump(ostream* outs) : sentry_(*outs), out_(outs->rdbuf()) {
-  }
-  ostream::sentry sentry_;
-  streambuf* const out_;
-};
-
-inline FastDump& operator << (FastDump& dump, int64 n) {
-  string numbuf(base::Int64ToString(n));
-  const char* number = numbuf.c_str();
-  dump.out_->sputn(number, numbuf.length());
-  return dump;
-}
-
-inline FastDump& operator << (FastDump& dump, int32 n) {
-  string numbuf(base::IntToString(n));
-  const char* number = numbuf.c_str();
-  dump.out_->sputn(number, numbuf.length());
-  return dump;
-}
-
-inline FastDump& operator << (FastDump& dump, const char* s) {
-  dump.out_->sputn(s, strlen(s));
-  return dump;
-}
-
-inline FastDump& operator << (FastDump& dump, const string& s) {
-  dump.out_->sputn(s.data(), s.size());
-  return dump;
-}
-
-}  // namespace browser_sync
-
-#endif  // CHROME_BROWSER_SYNC_UTIL_FAST_DUMP_H_
diff --git a/chrome/browser/sync/util/nigori.cc b/chrome/browser/sync/util/nigori.cc
index 49ed1db..51f767b 100644
--- a/chrome/browser/sync/util/nigori.cc
+++ b/chrome/browser/sync/util/nigori.cc
@@ -84,7 +84,8 @@
   DCHECK(user_salt.get());
 
   std::string raw_user_salt;
-  user_salt->GetRawKey(&raw_user_salt);
+  if (!user_salt->GetRawKey(&raw_user_salt))
+    return false;
 
   // Kuser = PBKDF2(P, Suser, Nuser, 16)
   user_key_.reset(SymmetricKey::DeriveKeyFromPassword(SymmetricKey::AES,
diff --git a/chrome/browser/sync/util/user_settings.cc b/chrome/browser/sync/util/user_settings.cc
index 9f52088..d49a071 100644
--- a/chrome/browser/sync/util/user_settings.cc
+++ b/chrome/browser/sync/util/user_settings.cc
@@ -79,7 +79,7 @@
 }
 
 string UserSettings::email() const {
-  AutoLock lock(mutex_);
+  base::AutoLock lock(mutex_);
   return email_;
 }
 
@@ -421,7 +421,7 @@
 
 void UserSettings::SwitchUser(const string& username) {
   {
-    AutoLock lock(mutex_);
+    base::AutoLock lock(mutex_);
     email_ = username;
   }
 }
diff --git a/chrome/browser/sync/util/user_settings.h b/chrome/browser/sync/util/user_settings.h
index 5545c8c..546c8b0 100644
--- a/chrome/browser/sync/util/user_settings.h
+++ b/chrome/browser/sync/util/user_settings.h
@@ -9,7 +9,7 @@
 #include <map>
 #include <string>
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "build/build_config.h"
 
 extern "C" struct sqlite3;
@@ -79,7 +79,7 @@
   struct ScopedDBHandle {
     explicit ScopedDBHandle(UserSettings* settings);
     inline sqlite3* get() const { return *handle_; }
-    AutoLock mutex_lock_;
+    base::AutoLock mutex_lock_;
     sqlite3** const handle_;
   };
 
@@ -90,11 +90,11 @@
 
  private:
   std::string email_;
-  mutable Lock mutex_;  // protects email_.
+  mutable base::Lock mutex_;  // protects email_.
 
   // We keep a single dbhandle.
   sqlite3* dbhandle_;
-  Lock dbhandle_mutex_;
+  base::Lock dbhandle_mutex_;
 
   // TODO(sync): Use in-memory cache for service auth tokens on posix.
   // Have someone competent in Windows switch it over to not use Sqlite in the
diff --git a/chrome/browser/sync/util/user_settings_unittest.cc b/chrome/browser/sync/util/user_settings_unittest.cc
index 036dcd3..0545b94 100644
--- a/chrome/browser/sync/util/user_settings_unittest.cc
+++ b/chrome/browser/sync/util/user_settings_unittest.cc
@@ -225,13 +225,13 @@
 }
 
 TEST_F(UserSettingsTest, APEncode) {
-  string test;
+  std::string test;
   char i;
   for (i = numeric_limits<char>::min(); i < numeric_limits<char>::max(); ++i)
     test.push_back(i);
   test.push_back(i);
-  const string encoded = APEncode(test);
-  const string decoded = APDecode(encoded);
+  const std::string encoded = APEncode(test);
+  const std::string decoded = APDecode(encoded);
   ASSERT_EQ(test, decoded);
 }
 
diff --git a/chrome/browser/tab_contents/background_contents.cc b/chrome/browser/tab_contents/background_contents.cc
index 1904d38..059d393 100644
--- a/chrome/browser/tab_contents/background_contents.cc
+++ b/chrome/browser/tab_contents/background_contents.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/background_contents_service.h"
 #include "chrome/browser/browsing_instance.h"
+#include "chrome/browser/desktop_notification_handler.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/site_instance.h"
@@ -15,7 +16,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/common/view_types.h"
 #include "chrome/common/render_messages_params.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 ////////////////
 // BackgroundContents
@@ -39,6 +40,8 @@
   // APP_TERMINATING before non-OTR profiles are destroyed).
   registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
                  Source<Profile>(profile));
+  desktop_notification_handler_.reset(
+      new DesktopNotificationHandler(NULL, site_instance->GetProcess()));
 }
 
 // Exposed to allow creating mocks.
@@ -175,6 +178,22 @@
   delete this;
 }
 
+void BackgroundContents::RenderViewGone(RenderViewHost* rvh,
+                                        base::TerminationStatus status,
+                                        int error_code) {
+  // Our RenderView went away, so we should go away also, so killing the process
+  // via the TaskManager doesn't permanently leave a BackgroundContents hanging
+  // around the system, blocking future instances from being created
+  // (http://crbug.com/65189).
+  delete this;
+}
+
+bool BackgroundContents::OnMessageReceived(const IPC::Message& message) {
+  // Forward desktop notification IPCs if any to the
+  // DesktopNotificationHandler.
+  return desktop_notification_handler_->OnMessageReceived(message);
+}
+
 RendererPreferences BackgroundContents::GetRendererPrefs(
     Profile* profile) const {
   RendererPreferences preferences;
@@ -190,7 +209,7 @@
                                                       false);  // is_dom_ui
 }
 
-void BackgroundContents::ProcessDOMUIMessage(
+void BackgroundContents::ProcessWebUIMessage(
     const ViewHostMsg_DomMessage_Params& params) {
   // TODO(rafaelw): It may make sense for extensions to be able to open
   // BackgroundContents to chrome-extension://<id> pages. Consider implementing.
@@ -199,16 +218,15 @@
 
 void BackgroundContents::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   delegate_view_helper_.CreateNewWindow(
       route_id,
       render_view_host_->process()->profile(),
       render_view_host_->site_instance(),
-      DOMUIFactory::GetDOMUIType(render_view_host_->process()->profile(), url_),
+      WebUIFactory::GetWebUIType(render_view_host_->process()->profile(), url_),
       this,
-      window_container_type,
-      frame_name);
+      params.window_container_type,
+      params.frame_name);
 }
 
 void BackgroundContents::CreateNewWidget(int route_id,
@@ -216,8 +234,7 @@
   NOTREACHED();
 }
 
-void BackgroundContents::CreateNewFullscreenWidget(
-    int route_id, WebKit::WebPopupType popup_type) {
+void BackgroundContents::CreateNewFullscreenWidget(int route_id) {
   NOTREACHED();
 }
 
diff --git a/chrome/browser/tab_contents/background_contents.h b/chrome/browser/tab_contents/background_contents.h
index ad57800..11aa3e2 100644
--- a/chrome/browser/tab_contents/background_contents.h
+++ b/chrome/browser/tab_contents/background_contents.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,6 +19,7 @@
 
 class TabContents;
 struct WebPreferences;
+class DesktopNotificationHandler;
 
 namespace gfx {
 class Rect;
@@ -66,7 +67,7 @@
   virtual void DidNavigate(RenderViewHost* render_view_host,
                            const ViewHostMsg_FrameNavigate_Params& params);
   virtual WebPreferences GetWebkitPrefs();
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
   virtual void RunJavaScriptMessage(const std::wstring& message,
                                     const std::wstring& default_prompt,
                                     const GURL& frame_url,
@@ -75,15 +76,17 @@
                                     bool* did_suppress_message);
   virtual void Close(RenderViewHost* render_view_host);
   virtual RendererPreferences GetRendererPrefs(Profile* profile) const;
+  virtual void RenderViewGone(RenderViewHost* rvh,
+                              base::TerminationStatus status,
+                              int error_code);
+  virtual bool OnMessageReceived(const IPC::Message& message);
 
   // RenderViewHostDelegate::View
   virtual void CreateNewWindow(
       int route_id,
-      WindowContainerType window_container_type,
-      const string16& frame_name);
+      const ViewHostMsg_CreateWindow_Params& params);
   virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
-  virtual void CreateNewFullscreenWidget(
-      int route_id, WebKit::WebPopupType popup_type);
+  virtual void CreateNewFullscreenWidget(int route_id);
   virtual void ShowCreatedWindow(int route_id,
                                  WindowOpenDisposition disposition,
                                  const gfx::Rect& initial_pos,
@@ -162,6 +165,9 @@
 
   NotificationRegistrar registrar_;
 
+  // Handles desktop notification IPCs.
+  scoped_ptr<DesktopNotificationHandler> desktop_notification_handler_;
+
   DISALLOW_COPY_AND_ASSIGN(BackgroundContents);
 };
 
diff --git a/chrome/browser/tab_contents/infobar_delegate.cc b/chrome/browser/tab_contents/infobar_delegate.cc
index 671d17b..b6115d1 100644
--- a/chrome/browser/tab_contents/infobar_delegate.cc
+++ b/chrome/browser/tab_contents/infobar_delegate.cc
@@ -1,18 +1,21 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
-// InfoBarDelegate: ------------------------------------------------------------
+// InfoBarDelegate ------------------------------------------------------------
+
+InfoBarDelegate::~InfoBarDelegate() {
+}
 
 bool InfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
   return false;
@@ -20,34 +23,31 @@
 
 bool InfoBarDelegate::ShouldExpire(
     const NavigationController::LoadCommittedDetails& details) const {
-  bool is_reload =
-      PageTransition::StripQualifier(details.entry->transition_type()) ==
-          PageTransition::RELOAD;
-  return is_reload || (contents_unique_id_ != details.entry->unique_id());
+  return (contents_unique_id_ != details.entry->unique_id()) ||
+      (PageTransition::StripQualifier(details.entry->transition_type()) ==
+          PageTransition::RELOAD);
+}
+
+void InfoBarDelegate::InfoBarDismissed() {
+}
+
+void InfoBarDelegate::InfoBarClosed() {
 }
 
 SkBitmap* InfoBarDelegate::GetIcon() const {
   return NULL;
 }
 
-AlertInfoBarDelegate* InfoBarDelegate::AsAlertInfoBarDelegate() {
-  return NULL;
-}
-
-LinkInfoBarDelegate* InfoBarDelegate::AsLinkInfoBarDelegate() {
-  return NULL;
+InfoBarDelegate::Type InfoBarDelegate::GetInfoBarType() const {
+  return WARNING_TYPE;
 }
 
 ConfirmInfoBarDelegate* InfoBarDelegate::AsConfirmInfoBarDelegate() {
   return NULL;
 }
 
-ThemeInstalledInfoBarDelegate*
-InfoBarDelegate::AsThemePreviewInfobarDelegate() {
-  return NULL;
-}
-
-TranslateInfoBarDelegate* InfoBarDelegate::AsTranslateInfoBarDelegate() {
+CrashedExtensionInfoBarDelegate*
+    InfoBarDelegate::AsCrashedExtensionInfoBarDelegate() {
   return NULL;
 }
 
@@ -55,13 +55,22 @@
   return NULL;
 }
 
-CrashedExtensionInfoBarDelegate*
-InfoBarDelegate::AsCrashedExtensionInfoBarDelegate() {
+LinkInfoBarDelegate* InfoBarDelegate::AsLinkInfoBarDelegate() {
   return NULL;
 }
 
-InfoBarDelegate::Type InfoBarDelegate::GetInfoBarType() {
-  return WARNING_TYPE;
+PluginInstallerInfoBarDelegate*
+    InfoBarDelegate::AsPluginInstallerInfoBarDelegate() {
+  return NULL;
+}
+
+ThemeInstalledInfoBarDelegate*
+    InfoBarDelegate::AsThemePreviewInfobarDelegate() {
+  return NULL;
+}
+
+TranslateInfoBarDelegate* InfoBarDelegate::AsTranslateInfoBarDelegate() {
+  return NULL;
 }
 
 InfoBarDelegate::InfoBarDelegate(TabContents* contents)
@@ -75,29 +84,8 @@
   contents_unique_id_ = active_entry ? active_entry->unique_id() : 0;
 }
 
-// AlertInfoBarDelegate: -------------------------------------------------------
 
-SkBitmap* AlertInfoBarDelegate::GetIcon() const {
-  return NULL;
-}
-
-bool AlertInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
-  AlertInfoBarDelegate* alert_delegate = delegate->AsAlertInfoBarDelegate();
-  if (!alert_delegate)
-    return false;
-
-  return alert_delegate->GetMessageText() == GetMessageText();
-}
-
-AlertInfoBarDelegate* AlertInfoBarDelegate::AsAlertInfoBarDelegate() {
-  return this;
-}
-
-AlertInfoBarDelegate::AlertInfoBarDelegate(TabContents* contents)
-    : InfoBarDelegate(contents) {
-}
-
-// LinkInfoBarDelegate: --------------------------------------------------------
+// LinkInfoBarDelegate --------------------------------------------------------
 
 string16 LinkInfoBarDelegate::GetMessageTextWithOffset(
     size_t* link_offset) const {
@@ -105,36 +93,30 @@
   return string16();
 }
 
-SkBitmap* LinkInfoBarDelegate::GetIcon() const {
-  return NULL;
-}
-
 bool LinkInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
   return true;
 }
 
-LinkInfoBarDelegate* LinkInfoBarDelegate::AsLinkInfoBarDelegate() {
-  return this;
-}
-
 LinkInfoBarDelegate::LinkInfoBarDelegate(TabContents* contents)
     : InfoBarDelegate(contents) {
 }
 
-// ConfirmInfoBarDelegate: -----------------------------------------------------
-
-int ConfirmInfoBarDelegate::GetButtons() const {
-  return BUTTON_NONE;
+LinkInfoBarDelegate::~LinkInfoBarDelegate() {
 }
 
-string16 ConfirmInfoBarDelegate::GetButtonLabel(
-    InfoBarButton button) const {
-  if (button == BUTTON_OK)
-    return l10n_util::GetStringUTF16(IDS_OK);
-  if (button == BUTTON_CANCEL)
-    return l10n_util::GetStringUTF16(IDS_CANCEL);
-  NOTREACHED();
-  return string16();
+LinkInfoBarDelegate* LinkInfoBarDelegate::AsLinkInfoBarDelegate() {
+  return this;
+}
+
+
+// ConfirmInfoBarDelegate -----------------------------------------------------
+
+int ConfirmInfoBarDelegate::GetButtons() const {
+  return BUTTON_OK | BUTTON_CANCEL;
+}
+
+string16 ConfirmInfoBarDelegate::GetButtonLabel(InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ? IDS_OK : IDS_CANCEL);
 }
 
 bool ConfirmInfoBarDelegate::NeedElevation(InfoBarButton button) const {
@@ -157,43 +139,58 @@
   return true;
 }
 
+ConfirmInfoBarDelegate::ConfirmInfoBarDelegate(TabContents* contents)
+    : InfoBarDelegate(contents) {
+}
+
+ConfirmInfoBarDelegate::~ConfirmInfoBarDelegate() {
+}
+
+bool ConfirmInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
+  ConfirmInfoBarDelegate* confirm_delegate =
+      delegate->AsConfirmInfoBarDelegate();
+  return confirm_delegate &&
+      (confirm_delegate->GetMessageText() == GetMessageText());
+}
+
 ConfirmInfoBarDelegate* ConfirmInfoBarDelegate::AsConfirmInfoBarDelegate() {
   return this;
 }
 
-ConfirmInfoBarDelegate::ConfirmInfoBarDelegate(TabContents* contents)
-    : AlertInfoBarDelegate(contents) {
-}
 
-// SimpleAlertInfoBarDelegate: -------------------------------------------------
+// SimpleAlertInfoBarDelegate -------------------------------------------------
 
 SimpleAlertInfoBarDelegate::SimpleAlertInfoBarDelegate(
     TabContents* contents,
-    const string16& message,
     SkBitmap* icon,
+    const string16& message,
     bool auto_expire)
-    : AlertInfoBarDelegate(contents),
-      message_(message),
+    : ConfirmInfoBarDelegate(contents),
       icon_(icon),
+      message_(message),
       auto_expire_(auto_expire) {
 }
 
+SimpleAlertInfoBarDelegate::~SimpleAlertInfoBarDelegate() {
+}
+
 bool SimpleAlertInfoBarDelegate::ShouldExpire(
       const NavigationController::LoadCommittedDetails& details) const {
-  if (auto_expire_)
-    return AlertInfoBarDelegate::ShouldExpire(details);
-
-  return false;
+  return auto_expire_ && ConfirmInfoBarDelegate::ShouldExpire(details);
 }
 
-string16 SimpleAlertInfoBarDelegate::GetMessageText() const {
-  return message_;
+void SimpleAlertInfoBarDelegate::InfoBarClosed() {
+  delete this;
 }
 
 SkBitmap* SimpleAlertInfoBarDelegate::GetIcon() const {
   return icon_;
 }
 
-void SimpleAlertInfoBarDelegate::InfoBarClosed() {
-  delete this;
+string16 SimpleAlertInfoBarDelegate::GetMessageText() const {
+  return message_;
+}
+
+int SimpleAlertInfoBarDelegate::GetButtons() const {
+  return BUTTON_NONE;
 }
diff --git a/chrome/browser/tab_contents/infobar_delegate.h b/chrome/browser/tab_contents/infobar_delegate.h
index af9b9c9..04b58b2 100644
--- a/chrome/browser/tab_contents/infobar_delegate.h
+++ b/chrome/browser/tab_contents/infobar_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,20 +11,20 @@
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "webkit/glue/window_open_disposition.h"
 
-class AlertInfoBarDelegate;
 class ConfirmInfoBarDelegate;
 class CrashedExtensionInfoBarDelegate;
 class ExtensionInfoBarDelegate;
-class TranslateInfoBarDelegate;
 class InfoBar;
 class LinkInfoBarDelegate;
+class PluginInstallerInfoBarDelegate;
 class SkBitmap;
 class ThemeInstalledInfoBarDelegate;
+class TranslateInfoBarDelegate;
 
 // An interface implemented by objects wishing to control an InfoBar.
 // Implementing this interface is not sufficient to use an InfoBar, since it
 // does not map to a specific InfoBar type. Instead, you must implement either
-// AlertInfoBarDelegate or ConfirmInfoBarDelegate, or override with your own
+// LinkInfoBarDelegate or ConfirmInfoBarDelegate, or override with your own
 // delegate for your own InfoBar variety.
 //
 // --- WARNING ---
@@ -52,6 +52,12 @@
     PAGE_ACTION_TYPE,
   };
 
+  virtual ~InfoBarDelegate();
+
+  // Called to create the InfoBar. Implementation of this method is
+  // platform-specific.
+  virtual InfoBar* CreateInfoBar() = 0;
+
   // Returns true if the supplied |delegate| is equal to this one. Equality is
   // left to the implementation to define. This function is called by the
   // TabContents when determining whether or not a delegate should be added
@@ -67,48 +73,28 @@
       const NavigationController::LoadCommittedDetails& details) const;
 
   // Called when the user clicks on the close button to dismiss the infobar.
-  virtual void InfoBarDismissed() {}
+  virtual void InfoBarDismissed();
 
   // Called after the InfoBar is closed. The delegate is free to delete itself
   // at this point.
-  virtual void InfoBarClosed() {}
-
-  // Called to create the InfoBar. Implementation of this method is
-  // platform-specific.
-  virtual InfoBar* CreateInfoBar() = 0;
+  virtual void InfoBarClosed();
 
   // Return the icon to be shown for this InfoBar. If the returned bitmap is
   // NULL, no icon is shown.
   virtual SkBitmap* GetIcon() const;
 
-  // Returns a pointer to the AlertInfoBarDelegate interface, if implemented.
-  virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate();
-
-  // Returns a pointer to the LinkInfoBarDelegate interface, if implemented.
-  virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate();
-
-  // Returns a pointer to the ConfirmInfoBarDelegate interface, if implemented.
-  virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate();
-
-  // Returns a pointer to the ThemeInstalledInfoBarDelegate interface, if
-  // implemented.
-  virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
-
-  // Returns a pointer to the TranslateInfoBarDelegate interface, if
-  // implemented.
-  virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
-
-  // Returns a pointer to the ExtensionInfoBarDelegate interface, if
-  // implemented.
-  virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate();
-
-  // Returns a pointer to the CrashedExtensionInfoBarDelegate interface, if
-  // implemented.
-  virtual CrashedExtensionInfoBarDelegate* AsCrashedExtensionInfoBarDelegate();
-
   // Returns the type of the infobar.  The type determines the appearance (such
   // as background color) of the infobar.
-  virtual Type GetInfoBarType();
+  virtual Type GetInfoBarType() const;
+
+  // Type-checking downcast routines:
+  virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate();
+  virtual CrashedExtensionInfoBarDelegate* AsCrashedExtensionInfoBarDelegate();
+  virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate();
+  virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate();
+  virtual PluginInstallerInfoBarDelegate* AsPluginInstallerInfoBarDelegate();
+  virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
+  virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
 
  protected:
   // Provided to subclasses as a convenience to initialize the state of this
@@ -116,15 +102,13 @@
   // stored using StoreActiveEntryUniqueID automatically.
   explicit InfoBarDelegate(TabContents* contents);
 
-  virtual ~InfoBarDelegate() { }
-
   // Store the unique id for the active entry in the specified TabContents, to
   // be used later upon navigation to determine if this InfoBarDelegate should
   // be expired from |contents_|.
   void StoreActiveEntryUniqueID(TabContents* contents);
 
  private:
-  // The unique id of the active NavigationEntry of the TabContents taht we were
+  // The unique id of the active NavigationEntry of the TabContents that we were
   // opened for. Used to help expire on navigations.
   int contents_unique_id_;
 
@@ -132,27 +116,6 @@
 };
 
 // An interface derived from InfoBarDelegate implemented by objects wishing to
-// control an AlertInfoBar.
-class AlertInfoBarDelegate : public InfoBarDelegate {
- public:
-  // Returns the message string to be displayed for the InfoBar.
-  virtual string16 GetMessageText() const = 0;
-
-  // Overridden from InfoBarDelegate.
-  virtual SkBitmap* GetIcon() const;
-
-  // Overridden from InfoBarDelegate:
-  virtual bool EqualsDelegate(InfoBarDelegate* delegate) const;
-  virtual InfoBar* CreateInfoBar();
-  virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate();
-
- protected:
-  explicit AlertInfoBarDelegate(TabContents* contents);
-
-  DISALLOW_COPY_AND_ASSIGN(AlertInfoBarDelegate);
-};
-
-// An interface derived from InfoBarDelegate implemented by objects wishing to
 // control a LinkInfoBar.
 class LinkInfoBarDelegate : public InfoBarDelegate {
  public:
@@ -165,9 +128,6 @@
   // Returns the text of the link to be displayed.
   virtual string16 GetLinkText() const = 0;
 
-  // Overridden from InfoBarDelegate.
-  virtual SkBitmap* GetIcon() const;
-
   // Called when the Link is clicked. The |disposition| specifies how the
   // resulting document should be loaded (based on the event flags present when
   // the link was clicked). This function returns true if the InfoBar should be
@@ -175,28 +135,31 @@
   // it.
   virtual bool LinkClicked(WindowOpenDisposition disposition);
 
-  // Overridden from InfoBarDelegate:
-  virtual InfoBar* CreateInfoBar();
-  virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate();
-
  protected:
   explicit LinkInfoBarDelegate(TabContents* contents);
+  virtual ~LinkInfoBarDelegate();
+
+ private:
+  // InfoBarDelegate:
+  virtual InfoBar* CreateInfoBar();
+  virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate();
 
   DISALLOW_COPY_AND_ASSIGN(LinkInfoBarDelegate);
 };
 
 // An interface derived from InfoBarDelegate implemented by objects wishing to
 // control a ConfirmInfoBar.
-class ConfirmInfoBarDelegate : public AlertInfoBarDelegate {
+class ConfirmInfoBarDelegate : public InfoBarDelegate {
  public:
   enum InfoBarButton {
-    BUTTON_NONE = 0,
-    BUTTON_OK = 1,
-    BUTTON_CANCEL = 2,
-    // Specifies that the OK button should be rendered like a default button.
-    BUTTON_OK_DEFAULT = 4
+    BUTTON_NONE   = 0,
+    BUTTON_OK     = 1 << 0,
+    BUTTON_CANCEL = 1 << 1,
   };
 
+  // Returns the message string to be displayed for the InfoBar.
+  virtual string16 GetMessageText() const = 0;
+
   // Return the buttons to be shown for this InfoBar.
   virtual int GetButtons() const;
 
@@ -227,36 +190,41 @@
   // Will only be called if GetLinkText() returns non-empty string.
   virtual bool LinkClicked(WindowOpenDisposition disposition);
 
-  // Overridden from InfoBarDelegate:
-  virtual InfoBar* CreateInfoBar();
-  virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate();
-
  protected:
   explicit ConfirmInfoBarDelegate(TabContents* contents);
+  virtual ~ConfirmInfoBarDelegate();
+
+ private:
+  // InfoBarDelegate:
+  virtual InfoBar* CreateInfoBar();
+  virtual bool EqualsDelegate(InfoBarDelegate* delegate) const;
+  virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate();
 
   DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBarDelegate);
 };
 
 // Simple implementations for common use cases ---------------------------------
 
-class SimpleAlertInfoBarDelegate : public AlertInfoBarDelegate {
+class SimpleAlertInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
-  // |icon| may be |NULL|.
   SimpleAlertInfoBarDelegate(TabContents* contents,
+                             SkBitmap* icon,  // May be NULL.
                              const string16& message,
-                             SkBitmap* icon,
                              bool auto_expire);
 
-  // Overridden from AlertInfoBarDelegate:
+ private:
+  virtual ~SimpleAlertInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
   virtual bool ShouldExpire(
       const NavigationController::LoadCommittedDetails& details) const;
-  virtual string16 GetMessageText() const;
-  virtual SkBitmap* GetIcon() const;
   virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
 
- private:
-  string16 message_;
   SkBitmap* icon_;
+  string16 message_;
   bool auto_expire_;  // Should it expire automatically on navigation?
 
   DISALLOW_COPY_AND_ASSIGN(SimpleAlertInfoBarDelegate);
diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc
index 263b67c..47fb774 100644
--- a/chrome/browser/tab_contents/interstitial_page.cc
+++ b/chrome/browser/tab_contents/interstitial_page.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -34,7 +34,7 @@
 #include "net/base/escape.h"
 
 #if defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
 #endif
 
 using WebKit::WebDragOperation;
@@ -92,12 +92,10 @@
   // RenderViewHostDelegate::View implementation:
   virtual void CreateNewWindow(
       int route_id,
-      WindowContainerType window_container_type,
-      const string16& frame_name);
+      const ViewHostMsg_CreateWindow_Params& params);
   virtual void CreateNewWidget(int route_id,
                                WebKit::WebPopupType popup_type);
-  virtual void CreateNewFullscreenWidget(int route_id,
-                                         WebKit::WebPopupType popup_type);
+  virtual void CreateNewFullscreenWidget(int route_id);
   virtual void ShowCreatedWindow(int route_id,
                                  WindowOpenDisposition disposition,
                                  const gfx::Rect& initial_pos,
@@ -594,8 +592,7 @@
 
 void InterstitialPage::InterstitialPageRVHViewDelegate::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   NOTREACHED() << "InterstitialPage does not support showing popups yet.";
 }
 
@@ -606,7 +603,7 @@
 
 void
 InterstitialPage::InterstitialPageRVHViewDelegate::CreateNewFullscreenWidget(
-    int route_id, WebKit::WebPopupType popup_type) {
+    int route_id) {
   NOTREACHED()
       << "InterstitialPage does not support showing full screen popups.";
 }
diff --git a/chrome/browser/tab_contents/interstitial_page.h b/chrome/browser/tab_contents/interstitial_page.h
index 3592a9d..f7d1edd 100644
--- a/chrome/browser/tab_contents/interstitial_page.h
+++ b/chrome/browser/tab_contents/interstitial_page.h
@@ -15,8 +15,8 @@
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/renderer_preferences.h"
-#include "gfx/size.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/size.h"
 
 class NavigationEntry;
 class TabContents;
diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc
index 9439f21..f294535 100644
--- a/chrome/browser/tab_contents/navigation_controller.cc
+++ b/chrome/browser/tab_contents/navigation_controller.cc
@@ -975,14 +975,6 @@
     if (last_committed_entry_index_ != -1)
       last_committed_entry_index_--;
   }
-
-  // Take over the session id from source.
-  session_id_ = source->session_id_;
-
-  // Reset source's session id as we're taking it over. We give it a new id in
-  // case source is added later on, which can happen with instant enabled if the
-  // tab has a before unload handler.
-  source->session_id_ = SessionID();
 }
 
 void NavigationController::PruneAllButActive() {
diff --git a/chrome/browser/tab_contents/navigation_controller.h b/chrome/browser/tab_contents/navigation_controller.h
index d86b587..adbc348 100644
--- a/chrome/browser/tab_contents/navigation_controller.h
+++ b/chrome/browser/tab_contents/navigation_controller.h
@@ -364,10 +364,8 @@
 
   // A variant of CopyStateFrom. Removes all entries from this except the last
   // entry, inserts all entries from |source| before and including the active
-  // entry and resets the |session_id_| of this to match |source|.  This is
-  // intended for use when you're going to throw away |source| and replace it
-  // with this. This method is intended for use when the last entry of |this|
-  // is the active entry. For example:
+  // entry. This method is intended for use when the last entry of |this| is the
+  // active entry. For example:
   // source: A B *C* D
   // this:   E F *G*   (last must be active or pending)
   // result: A B *G*
diff --git a/chrome/browser/tab_contents/navigation_controller_unittest.cc b/chrome/browser/tab_contents/navigation_controller_unittest.cc
index 91c23ea..2691305 100644
--- a/chrome/browser/tab_contents/navigation_controller_unittest.cc
+++ b/chrome/browser/tab_contents/navigation_controller_unittest.cc
@@ -31,8 +31,6 @@
 
 using base::Time;
 
-namespace {
-
 // NavigationControllerTest ----------------------------------------------------
 
 class NavigationControllerTest : public RenderViewHostTestHarness {
@@ -1641,7 +1639,7 @@
   controller().RendererDidNavigate(params, 0, &details);
 
   EXPECT_EQ(ASCIIToUTF16(kExpected), contents()->GetTitle());
-  EXPECT_EQ(true, contents()->ShouldDisplayURL());
+  EXPECT_TRUE(contents()->ShouldDisplayURL());
 }
 
 // Make sure that on cloning a tabcontents and going back needs_reload is false.
@@ -1725,6 +1723,7 @@
 
   scoped_ptr<TestTabContents> other_contents(CreateTestTabContents());
   NavigationController& other_controller = other_contents->controller();
+  SessionID other_id(other_controller.session_id());
   other_contents->NavigateAndCommit(url3);
   other_controller.CopyStateFromAndPrune(&controller());
 
@@ -1738,10 +1737,9 @@
   EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->url());
   EXPECT_EQ(url3, other_controller.GetEntryAtIndex(2)->url());
 
-  // The session id of the new tab should be that of the old, and the old should
-  // get a new id.
-  EXPECT_EQ(id.id(), other_controller.session_id().id());
-  EXPECT_NE(id.id(), controller().session_id().id());
+  // Make sure session ids didn't change.
+  EXPECT_EQ(id.id(), controller().session_id().id());
+  EXPECT_EQ(other_id.id(), other_controller.session_id().id());
 }
 
 // Test CopyStateFromAndPrune with 2 urls, the first selected and nothing in
@@ -1758,6 +1756,7 @@
 
   scoped_ptr<TestTabContents> other_contents(CreateTestTabContents());
   NavigationController& other_controller = other_contents->controller();
+  SessionID other_id(other_controller.session_id());
   other_controller.CopyStateFromAndPrune(&controller());
 
   // other_controller should now contain the 1 url: url1.
@@ -1768,10 +1767,9 @@
 
   EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->url());
 
-  // The session id of the new tab should be that of the old, and the old should
-  // get a new id.
-  EXPECT_EQ(id.id(), other_controller.session_id().id());
-  EXPECT_NE(id.id(), controller().session_id().id());
+  // Make sure session ids didn't change.
+  EXPECT_EQ(id.id(), controller().session_id().id());
+  EXPECT_EQ(other_id.id(), other_controller.session_id().id());
 }
 
 // Test CopyStateFromAndPrune with 2 urls, the first selected and nothing in
@@ -1788,6 +1786,7 @@
 
   scoped_ptr<TestTabContents> other_contents(CreateTestTabContents());
   NavigationController& other_controller = other_contents->controller();
+  SessionID other_id(other_controller.session_id());
   other_controller.LoadURL(url3, GURL(), PageTransition::TYPED);
   other_controller.CopyStateFromAndPrune(&controller());
 
@@ -1805,10 +1804,9 @@
 
   EXPECT_EQ(url3, other_controller.pending_entry()->url());
 
-  // The session id of the new tab should be that of the old, and the old should
-  // be get a new id.
-  EXPECT_EQ(id.id(), other_controller.session_id().id());
-  EXPECT_NE(id.id(), controller().session_id().id());
+  // Make sure session ids didn't change.
+  EXPECT_EQ(id.id(), controller().session_id().id());
+  EXPECT_EQ(other_id.id(), other_controller.session_id().id());
 }
 
 // Tests that navigations initiated from the page (with the history object)
@@ -1824,14 +1822,9 @@
   controller().GoBack();
   contents()->CommitPendingNavigation();
 
-  // Casts the TabContents to a RenderViewHostDelegate::BrowserIntegration so we
-  // can call GoToEntryAtOffset which is private.
-  RenderViewHostDelegate::BrowserIntegration* rvh_delegate =
-      static_cast<RenderViewHostDelegate::BrowserIntegration*>(contents());
-
   // Simulate the page calling history.back(), it should not create a pending
   // entry.
-  rvh_delegate->GoToEntryAtOffset(-1);
+  contents()->OnGoToEntryAtOffset(-1);
   EXPECT_EQ(-1, controller().pending_entry_index());
   // The actual cross-navigation is suspended until the current RVH tells us
   // it unloaded, simulate that.
@@ -1846,7 +1839,7 @@
   process()->sink().ClearMessages();
 
   // Now test history.forward()
-  rvh_delegate->GoToEntryAtOffset(1);
+  contents()->OnGoToEntryAtOffset(1);
   EXPECT_EQ(-1, controller().pending_entry_index());
   // The actual cross-navigation is suspended until the current RVH tells us
   // it unloaded, simulate that.
@@ -1858,7 +1851,7 @@
   process()->sink().ClearMessages();
 
   // Make sure an extravagant history.go() doesn't break.
-  rvh_delegate->GoToEntryAtOffset(120);  // Out of bounds.
+  contents()->OnGoToEntryAtOffset(120);  // Out of bounds.
   EXPECT_EQ(-1, controller().pending_entry_index());
   message = process()->sink().GetFirstMessageMatching(ViewMsg_Navigate::ID);
   EXPECT_TRUE(message == NULL);
@@ -2030,5 +2023,3 @@
                                          windows_[0]->tabs[0]->navigations[1]);
 }
 */
-
-}  // namespace
diff --git a/chrome/browser/tab_contents/navigation_entry.cc b/chrome/browser/tab_contents/navigation_entry.cc
index d5504ba..25af057 100644
--- a/chrome/browser/tab_contents/navigation_entry.cc
+++ b/chrome/browser/tab_contents/navigation_entry.cc
@@ -4,11 +4,8 @@
 
 #include "chrome/browser/tab_contents/navigation_entry.h"
 
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/site_instance.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
@@ -16,6 +13,8 @@
 #include "chrome/common/url_constants.h"
 #include "grit/app_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
 
 // Use this to get a new unique ID for a NavigationEntry during construction.
 // The returned ID is guaranteed to be nonzero (which is the "no ID" indicator).
@@ -96,9 +95,8 @@
   } else if (!url_.is_empty()) {
     title = net::FormatUrl(url_, languages);
   }
-  gfx::ElideString(UTF16ToWideHack(title),
-                   chrome::kMaxTitleChars,
-                   &elided_title);
+  ui::ElideString(UTF16ToWideHack(title), chrome::kMaxTitleChars,
+                  &elided_title);
   cached_display_title_ = WideToUTF16Hack(elided_title);
   return cached_display_title_;
 }
diff --git a/chrome/browser/tab_contents/popup_menu_helper_mac.h b/chrome/browser/tab_contents/popup_menu_helper_mac.h
index 08a4c19..4b46098 100644
--- a/chrome/browser/tab_contents/popup_menu_helper_mac.h
+++ b/chrome/browser/tab_contents/popup_menu_helper_mac.h
@@ -9,7 +9,7 @@
 
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class RenderViewHost;
 struct WebMenuItem;
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index f35c0e0..f439321 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,6 @@
 
 #include "chrome/browser/tab_contents/render_view_context_menu.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
@@ -48,18 +47,111 @@
 #include "chrome/common/content_restriction.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/favicon_size.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "net/url_request/url_request.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/favicon_size.h"
 #include "webkit/glue/webmenuitem.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerAction.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
 
 using WebKit::WebContextMenuData;
 using WebKit::WebMediaPlayerAction;
 
+namespace {
+
+bool IsCustomItemEnabled(const std::vector<WebMenuItem>& items, int id) {
+  DCHECK(id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+         id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST);
+  for (size_t i = 0; i < items.size(); ++i) {
+    int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action;
+    if (action_id == id)
+      return items[i].enabled;
+    if (items[i].type == WebMenuItem::SUBMENU) {
+      if (IsCustomItemEnabled(items[i].submenu, id))
+        return true;
+    }
+  }
+  return false;
+}
+
+bool IsCustomItemChecked(const std::vector<WebMenuItem>& items, int id) {
+  DCHECK(id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+         id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST);
+  for (size_t i = 0; i < items.size(); ++i) {
+    int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action;
+    if (action_id == id)
+      return items[i].checked;
+    if (items[i].type == WebMenuItem::SUBMENU) {
+      if (IsCustomItemChecked(items[i].submenu, id))
+        return true;
+    }
+  }
+  return false;
+}
+
+const size_t kMaxCustomMenuDepth = 5;
+const size_t kMaxCustomMenuTotalItems = 1000;
+
+void AddCustomItemsToMenu(const std::vector<WebMenuItem>& items,
+                          size_t depth,
+                          size_t* total_items,
+                          ui::SimpleMenuModel::Delegate* delegate,
+                          ui::SimpleMenuModel* menu_model) {
+  if (depth > kMaxCustomMenuDepth) {
+    LOG(ERROR) << "Custom menu too deeply nested.";
+    return;
+  }
+  for (size_t i = 0; i < items.size(); ++i) {
+    if (IDC_CONTENT_CONTEXT_CUSTOM_FIRST + items[i].action >=
+        IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
+      LOG(ERROR) << "Custom menu action value too big.";
+      return;
+    }
+    if (*total_items >= kMaxCustomMenuTotalItems) {
+      LOG(ERROR) << "Custom menu too large (too many items).";
+      return;
+    }
+    (*total_items)++;
+    switch (items[i].type) {
+      case WebMenuItem::OPTION:
+        menu_model->AddItem(
+            items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+            items[i].label);
+        break;
+      case WebMenuItem::CHECKABLE_OPTION:
+        menu_model->AddCheckItem(
+            items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+            items[i].label);
+        break;
+      case WebMenuItem::GROUP:
+        // TODO(viettrungluu): I don't know what this is supposed to do.
+        NOTREACHED();
+        break;
+      case WebMenuItem::SEPARATOR:
+        menu_model->AddSeparator();
+        break;
+      case WebMenuItem::SUBMENU: {
+        ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate);
+        AddCustomItemsToMenu(items[i].submenu, depth + 1, total_items, delegate,
+                             submenu);
+        menu_model->AddSubMenu(
+            items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+            items[i].label,
+            submenu);
+        break;
+      }
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+}
+
+}  // namespace
+
 // static
 const size_t RenderViewContextMenu::kMaxExtensionItemTitleLength = 75;
 // static
@@ -230,7 +322,7 @@
   if (submenu_items.empty()) {
     menu_model_.AddItem(menu_id, title);
   } else {
-    menus::SimpleMenuModel* submenu = new menus::SimpleMenuModel(this);
+    ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(this);
     extension_menu_models_.push_back(submenu);
     menu_model_.AddSubMenu(menu_id, title, submenu);
     RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito, submenu,
@@ -242,7 +334,7 @@
 void RenderViewContextMenu::RecursivelyAppendExtensionItems(
     const ExtensionMenuItem::List& items,
     bool can_cross_incognito,
-    menus::SimpleMenuModel* menu_model,
+    ui::SimpleMenuModel* menu_model,
     int *index) {
   string16 selection_text = PrintableSelectionText();
   ExtensionMenuItem::Type last_type = ExtensionMenuItem::NORMAL;
@@ -273,7 +365,7 @@
       if (children.size() == 0) {
         menu_model->AddItem(menu_id, title);
       } else {
-        menus::SimpleMenuModel* submenu = new menus::SimpleMenuModel(this);
+        ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(this);
         extension_menu_models_.push_back(submenu);
         menu_model->AddSubMenu(menu_id, title, submenu);
         RecursivelyAppendExtensionItems(children, can_cross_incognito,
@@ -358,7 +450,9 @@
   bool has_selection = !params_.selection_text.empty();
 
   if (AppendCustomItems()) {
-    AppendDeveloperItems();
+    // Don't add items for Pepper menu.
+    if (!params_.custom_context.is_pepper_menu)
+      AppendDeveloperItems();
     return;
   }
 
@@ -369,15 +463,21 @@
       !has_link &&
       !params_.is_editable &&
       !has_selection) {
-    // If context is in subframe, show subframe options instead.
-    if (!params_.frame_url.is_empty()) {
-      is_devtools = IsDevToolsURL(params_.frame_url);
-      if (!is_devtools && !IsInternalResourcesURL(params_.frame_url))
-        AppendFrameItems();
-    } else if (!params_.page_url.is_empty()) {
+    if (!params_.page_url.is_empty()) {
       is_devtools = IsDevToolsURL(params_.page_url);
-      if (!is_devtools && !IsInternalResourcesURL(params_.page_url))
+      if (!is_devtools && !IsInternalResourcesURL(params_.page_url)) {
         AppendPageItems();
+        // Merge in frame items if we clicked within a frame that needs them.
+        if (!params_.frame_url.is_empty()) {
+          is_devtools = IsDevToolsURL(params_.frame_url);
+          if (!is_devtools && !IsInternalResourcesURL(params_.frame_url)) {
+            menu_model_.AddSeparator();
+            AppendFrameItems();
+          }
+        }
+      }
+    } else {
+      DCHECK(params_.frame_url.is_empty());
     }
   }
 
@@ -399,6 +499,9 @@
     case WebContextMenuData::MediaTypeAudio:
       AppendAudioItems();
       break;
+    case WebContextMenuData::MediaTypePlugin:
+      AppendPluginItems();
+      break;
   }
 
   if (params_.is_editable)
@@ -421,23 +524,10 @@
 }
 
 bool RenderViewContextMenu::AppendCustomItems() {
-  std::vector<WebMenuItem>& custom_items = params_.custom_items;
-  for (size_t i = 0; i < custom_items.size(); ++i) {
-    DCHECK(IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action <
-        IDC_CONTENT_CONTEXT_CUSTOM_LAST);
-    if (custom_items[i].type == WebMenuItem::SEPARATOR) {
-      menu_model_.AddSeparator();
-    } else if (custom_items[i].type == WebMenuItem::CHECKABLE_OPTION) {
-      menu_model_.AddCheckItem(
-          custom_items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
-          custom_items[i].label);
-    } else {
-      menu_model_.AddItem(
-          custom_items[i].action + IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
-          custom_items[i].label);
-    }
-  }
-  return custom_items.size() > 0;
+  size_t total_items = 0;
+  AddCustomItemsToMenu(params_.custom_items, 0, &total_items, this,
+                       &menu_model_);
+  return total_items > 0;
 }
 
 void RenderViewContextMenu::AppendDeveloperItems() {
@@ -524,6 +614,18 @@
                                        IDS_CONTENT_CONTEXT_CONTROLS);
 }
 
+void RenderViewContextMenu::AppendPluginItems() {
+  if (params_.page_url == params_.src_url) {
+    // Full page plugin, so show page menu items.
+    if (params_.link_url.is_empty() && params_.selection_text.empty())
+      AppendPageItems();
+  } else {
+    menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS,
+                                    IDS_CONTENT_CONTEXT_SAVEPAGEAS);
+    menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT);
+  }
+}
+
 void RenderViewContextMenu::AppendPageItems() {
   menu_model_.AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
   menu_model_.AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
@@ -547,12 +649,8 @@
 }
 
 void RenderViewContextMenu::AppendFrameItems() {
-  menu_model_.AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
-  menu_model_.AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
-  menu_model_.AddSeparator();
   menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_RELOADFRAME,
                                   IDS_CONTENT_CONTEXT_RELOADFRAME);
-  menu_model_.AddSeparator();
   // These two menu items have yet to be implemented.
   // http://code.google.com/p/chromium/issues/detail?id=11827
   //   IDS_CONTENT_CONTEXT_SAVEFRAMEAS
@@ -577,8 +675,7 @@
 
   AutocompleteMatch match;
   profile_->GetAutocompleteClassifier()->Classify(
-      UTF16ToWideHack(params_.selection_text),
-      std::wstring(), false, &match, NULL);
+      params_.selection_text, string16(), false, &match, NULL);
   selection_navigation_url_ = match.destination_url;
   if (!selection_navigation_url_.is_valid())
     return;
@@ -605,7 +702,7 @@
     menu_model_.AddItem(
         IDC_CONTENT_CONTEXT_SEARCHWEBFOR,
         l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFOR,
-                                   WideToUTF16(default_provider->short_name()),
+                                   default_provider->short_name(),
                                    printable_selection_text));
   }
 }
@@ -759,28 +856,10 @@
     return profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck);
   }
 
-  // Process custom actions range.
-  if ((id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST) &&
-      (id < IDC_CONTENT_CONTEXT_CUSTOM_LAST)) {
-    unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
-    for (size_t i = 0; i < params_.custom_items.size(); ++i) {
-      if (params_.custom_items[i].action == action)
-        return params_.custom_items[i].enabled;
-    }
-    NOTREACHED();
-    return false;
-  }
-
-  // Custom WebKit items.
+  // Custom items.
   if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
       id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
-    const std::vector<WebMenuItem>& custom_items = params_.custom_items;
-    for (size_t i = 0; i < custom_items.size(); ++i) {
-      int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action;
-      if (action_id == id)
-        return custom_items[i].enabled;
-    }
-    return true;
+    return IsCustomItemEnabled(params_.custom_items, id);
   }
 
   // Extension items.
@@ -929,12 +1008,16 @@
       return !!(params_.edit_flags & WebContextMenuData::CanSelectAll);
 
     case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
-      return !profile_->IsOffTheRecord() && params_.link_url.is_valid();
+      return !profile_->IsOffTheRecord() && params_.link_url.is_valid() &&
+             profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
 
     case IDC_SPELLCHECK_ADD_TO_DICTIONARY:
       return !params_.misspelled_word.empty();
 
     case IDC_PRINT:
+      return params_.media_type == WebContextMenuData::MediaTypeNone ||
+        params_.media_flags & WebContextMenuData::MediaCanPrint;
+
     case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
     case IDC_CONTENT_CONTEXT_GOTOURL:
     case IDC_SPELLCHECK_SUGGESTION_0:
@@ -1002,16 +1085,10 @@
             WebContextMenuData::MediaControls) != 0;
   }
 
-  // Custom WebKit items.
+  // Custom items.
   if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
       id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
-    const std::vector<WebMenuItem>& custom_items = params_.custom_items;
-    for (size_t i = 0; i < custom_items.size(); ++i) {
-      int action_id = IDC_CONTENT_CONTEXT_CUSTOM_FIRST + custom_items[i].action;
-      if (action_id == id)
-        return custom_items[i].checked;
-    }
-    return false;
+    return IsCustomItemChecked(params_.custom_items, id);
   }
 
   // Extension items.
@@ -1072,11 +1149,11 @@
   }
 
   // Process custom actions range.
-  if ((id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST) &&
-      (id < IDC_CONTENT_CONTEXT_CUSTOM_LAST)) {
+  if (id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+      id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
     unsigned action = id - IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
-    source_tab_contents_->render_view_host()->
-        PerformCustomContextMenuAction(action);
+    source_tab_contents_->render_view_host()->PerformCustomContextMenuAction(
+        params_.custom_context, action);
     return;
   }
 
@@ -1212,7 +1289,11 @@
       break;
 
     case IDC_PRINT:
-      source_tab_contents_->PrintPreview();
+      if (params_.media_type == WebContextMenuData::MediaTypeNone) {
+        source_tab_contents_->PrintPreview();
+      } else {
+        source_tab_contents_->render_view_host()->PrintNodeUnderContextMenu();
+      }
       break;
 
     case IDC_VIEW_SOURCE:
@@ -1376,6 +1457,11 @@
   }
 }
 
+void RenderViewContextMenu::MenuClosed() {
+  source_tab_contents_->render_view_host()->ContextMenuClosed(
+      params_.custom_context);
+}
+
 bool RenderViewContextMenu::IsDevCommandEnabled(int id) const {
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kAlwaysEnableDevTools))
@@ -1406,11 +1492,6 @@
     if (!profile_->GetPrefs()->GetBoolean(prefs::kWebKitJavascriptEnabled) ||
         command_line.HasSwitch(switches::kDisableJavaScript))
       return false;
-    // Don't enable the web inspector on web inspector if there is no process
-    // per tab flag set.
-    if (IsDevToolsURL(active_entry->url()) &&
-        !command_line.HasSwitch(switches::kProcessPerTab))
-      return false;
     // Don't enable the web inspector if the developer tools are disabled via
     // the preference dev-tools-disabled.
     if (profile_->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled))
diff --git a/chrome/browser/tab_contents/render_view_context_menu.h b/chrome/browser/tab_contents/render_view_context_menu.h
index 2f1a83e..2aac240 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.h
+++ b/chrome/browser/tab_contents/render_view_context_menu.h
@@ -10,11 +10,11 @@
 #include <string>
 #include <vector>
 
-#include "app/menus/simple_menu_model.h"
 #include "base/string16.h"
 #include "base/scoped_vector.h"
 #include "chrome/common/page_transition_types.h"
 #include "chrome/browser/extensions/extension_menu_manager.h"
+#include "ui/base/models/simple_menu_model.h"
 #include "webkit/glue/context_menu.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -30,7 +30,7 @@
 struct WebMediaPlayerAction;
 }
 
-class RenderViewContextMenu : public menus::SimpleMenuModel::Delegate {
+class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate {
  public:
   static const size_t kMaxExtensionItemTitleLength;
   static const size_t kMaxSelectionTextLength;
@@ -47,6 +47,7 @@
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual void ExecuteCommand(int command_id);
+  virtual void MenuClosed();
 
  protected:
   void InitMenu();
@@ -55,7 +56,7 @@
   virtual void PlatformInit() = 0;
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) = 0;
+      ui::Accelerator* accelerator) = 0;
   virtual void LookUpInDictionary();
 
   // Attempts to get an ExtensionMenuItem given the id of a context menu item.
@@ -65,7 +66,7 @@
   TabContents* source_tab_contents_;
   Profile* profile_;
 
-  menus::SimpleMenuModel menu_model_;
+  ui::SimpleMenuModel menu_model_;
 
   // True if we are showing for an external tab contents. The default is false.
   bool external_;
@@ -85,6 +86,7 @@
   void AppendAudioItems();
   void AppendVideoItems();
   void AppendMediaItems();
+  void AppendPluginItems();
   void AppendPageItems();
   void AppendFrameItems();
   void AppendCopyItem();
@@ -104,7 +106,7 @@
   void RecursivelyAppendExtensionItems(
       const std::vector<ExtensionMenuItem*>& items,
       bool can_cross_incognito,
-      menus::SimpleMenuModel* menu_model,
+      ui::SimpleMenuModel* menu_model,
       int *index);
   // This will set the icon on the most recently-added item in the menu_model_.
   void SetExtensionIcon(const std::string& extension_id);
@@ -137,9 +139,9 @@
   // a text selection.
   GURL selection_navigation_url_;
 
-  menus::SimpleMenuModel spellcheck_submenu_model_;
-  menus::SimpleMenuModel bidi_submenu_model_;
-  ScopedVector<menus::SimpleMenuModel> extension_menu_models_;
+  ui::SimpleMenuModel spellcheck_submenu_model_;
+  ui::SimpleMenuModel bidi_submenu_model_;
+  ScopedVector<ui::SimpleMenuModel> extension_menu_models_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenu);
 };
diff --git a/chrome/browser/tab_contents/render_view_context_menu_gtk.cc b/chrome/browser/tab_contents/render_view_context_menu_gtk.cc
index 4c2a6d3..5478d6f 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_gtk.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu_gtk.cc
@@ -36,7 +36,7 @@
 
 bool RenderViewContextMenuGtk::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   return false;
 }
 
@@ -44,7 +44,7 @@
   RenderWidgetHostView* rwhv = source_tab_contents_->GetRenderWidgetHostView();
   if (rwhv)
     rwhv->ShowingContextMenu(true);
-  menu_gtk_->PopupAsContextAt(triggering_event_time_, point);
+  menu_gtk_->PopupAsContext(point, triggering_event_time_);
 }
 
 void RenderViewContextMenuGtk::StoppedShowing() {
diff --git a/chrome/browser/tab_contents/render_view_context_menu_gtk.h b/chrome/browser/tab_contents/render_view_context_menu_gtk.h
index f9da630..364d9fe 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_gtk.h
+++ b/chrome/browser/tab_contents/render_view_context_menu_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,9 +7,9 @@
 #pragma once
 
 #include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/menu_gtk.h"
 #include "chrome/browser/tab_contents/render_view_context_menu.h"
-#include "gfx/point.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "ui/gfx/point.h"
 
 struct ContextMenuParams;
 
@@ -35,7 +35,7 @@
   // TODO(port): implement.
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator);
+      ui::Accelerator* accelerator);
 
  private:
   scoped_ptr<MenuGtk> menu_gtk_;
diff --git a/chrome/browser/tab_contents/render_view_context_menu_mac.h b/chrome/browser/tab_contents/render_view_context_menu_mac.h
index 72f402c..58a8eaf 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_mac.h
+++ b/chrome/browser/tab_contents/render_view_context_menu_mac.h
@@ -29,7 +29,7 @@
   virtual void PlatformInit();
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) {
+      ui::Accelerator* accelerator) {
     return false;
   }
 
diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
index 568ae4c..37efe34 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -46,12 +46,13 @@
       !extensions_service->is_ready())
     return NULL;
 
+  // Only hosted apps have web extents, so this ensures that only hosted apps
+  // can create BackgroundContents. We don't have to check for background
+  // permission as that is checked in RenderMessageFilter when the CreateWindow
+  // message is processed.
   const Extension* extension =
-      extensions_service->GetExtensionByURL(opener_url);
+      extensions_service->GetExtensionByWebExtent(opener_url);
   if (!extension)
-    extension = extensions_service->GetExtensionByWebExtent(opener_url);
-  if (!extension ||
-      !extension->HasApiPermission(Extension::kBackgroundPermission))
     return NULL;
 
   // Only allow a single background contents per app.
@@ -76,7 +77,7 @@
     int route_id,
     Profile* profile,
     SiteInstance* site,
-    DOMUITypeID domui_type,
+    WebUITypeID webui_type,
     RenderViewHostDelegate* opener,
     WindowContainerType window_container_type,
     const string16& frame_name) {
@@ -101,7 +102,7 @@
                       route_id,
                       opener->GetAsTabContents(),
                       NULL);
-  new_contents->set_opener_dom_ui_type(domui_type);
+  new_contents->set_opener_web_ui_type(webui_type);
   TabContentsView* new_view = new_contents->view();
 
   // TODO(brettw) it seems bogus that we have to call this function on the
@@ -128,12 +129,11 @@
 
 RenderWidgetHostView*
 RenderViewHostDelegateViewHelper::CreateNewFullscreenWidget(
-    int route_id, WebKit::WebPopupType popup_type, RenderProcessHost* process) {
+    int route_id, RenderProcessHost* process) {
   RenderWidgetFullscreenHost* fullscreen_widget_host =
       new RenderWidgetFullscreenHost(process, route_id);
   RenderWidgetHostView* widget_view =
       RenderWidgetHostView::CreateViewForWidget(fullscreen_widget_host);
-  widget_view->set_popup_type(popup_type);
   pending_widget_views_[route_id] = widget_view;
   return widget_view;
 }
@@ -265,7 +265,7 @@
     web_prefs.remote_fonts_enabled =
         !command_line.HasSwitch(switches::kDisableRemoteFonts);
     web_prefs.xss_auditor_enabled =
-        command_line.HasSwitch(switches::kEnableXSSAuditor);
+        !command_line.HasSwitch(switches::kDisableXSSAuditor);
     web_prefs.application_cache_enabled =
         !command_line.HasSwitch(switches::kDisableApplicationCache);
 
@@ -273,10 +273,14 @@
         !command_line.HasSwitch(switches::kDisableLocalStorage);
     web_prefs.databases_enabled =
         !command_line.HasSwitch(switches::kDisableDatabases);
+    web_prefs.webaudio_enabled =
+        command_line.HasSwitch(switches::kEnableWebAudio);
     web_prefs.experimental_webgl_enabled =
         gpu_enabled() &&
         !command_line.HasSwitch(switches::kDisable3DAPIs) &&
         !command_line.HasSwitch(switches::kDisableExperimentalWebGL);
+    web_prefs.gl_multisampling_enabled =
+        !command_line.HasSwitch(switches::kDisableGLMultisampling);
     web_prefs.site_specific_quirks_enabled =
         !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks);
     web_prefs.allow_file_access_from_file_urls =
@@ -291,12 +295,16 @@
         command_line.HasSwitch(switches::kEnableAccelerated2dCanvas);
     web_prefs.accelerated_layers_enabled =
         command_line.HasSwitch(switches::kEnableAcceleratedLayers);
+    web_prefs.accelerated_plugins_enabled =
+        command_line.HasSwitch(switches::kEnableAcceleratedPlugins);
     web_prefs.accelerated_video_enabled =
         !command_line.HasSwitch(switches::kDisableAcceleratedVideo);
     web_prefs.memory_info_enabled =
         command_line.HasSwitch(switches::kEnableMemoryInfo);
     web_prefs.hyperlink_auditing_enabled =
         !command_line.HasSwitch(switches::kNoPings);
+    web_prefs.interactive_form_validation_enabled =
+        !command_line.HasSwitch(switches::kDisableInteractiveFormValidation);
     // The user stylesheet watcher may not exist in a testing profile.
     if (profile->GetUserStyleSheetWatcher()) {
       web_prefs.user_style_sheet_enabled = true;
diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.h b/chrome/browser/tab_contents/render_view_host_delegate_helper.h
index d4ea3a3..d112af9 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.h
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,10 +9,10 @@
 #include <map>
 
 #include "base/basictypes.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/common/window_container_type.h"
-#include "gfx/rect.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/webpreferences.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -41,7 +41,7 @@
       int route_id,
       Profile* profile,
       SiteInstance* site,
-      DOMUITypeID domui_type,
+      WebUITypeID webui_type,
       RenderViewHostDelegate* opener,
       WindowContainerType window_container_type,
       const string16& frame_name);
@@ -53,9 +53,7 @@
                                                 RenderProcessHost* process);
 
   virtual RenderWidgetHostView* CreateNewFullscreenWidget(
-      int route_id,
-      WebKit::WebPopupType popup_type,
-      RenderProcessHost* process);
+      int route_id, RenderProcessHost* process);
 
   // Finds the new RenderWidgetHost and returns it. Note that this can only be
   // called once as this call also removes it from the internal map.
diff --git a/chrome/browser/tab_contents/render_view_host_manager.cc b/chrome/browser/tab_contents/render_view_host_manager.cc
index ed5628e..7aaf5f3 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.cc
+++ b/chrome/browser/tab_contents/render_view_host_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,8 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/dom_ui/web_ui.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
@@ -178,8 +178,8 @@
     // We should only hear this from our current renderer.
     DCHECK(render_view_host == render_view_host_);
 
-    // Even when there is no pending RVH, there may be a pending DOM UI.
-    if (pending_dom_ui_.get())
+    // Even when there is no pending RVH, there may be a pending Web UI.
+    if (pending_web_ui_.get())
       CommitPending();
     return;
   }
@@ -199,9 +199,9 @@
   }
 }
 
-void RenderViewHostManager::SetDOMUIPostCommit(DOMUI* dom_ui) {
-  DCHECK(!dom_ui_.get());
-  dom_ui_.reset(dom_ui);
+void RenderViewHostManager::SetWebUIPostCommit(WebUI* web_ui) {
+  DCHECK(!web_ui_.get());
+  web_ui_.reset(web_ui);
 }
 
 void RenderViewHostManager::RendererAbortedProvisionalLoad(
@@ -292,18 +292,32 @@
     const NavigationEntry* new_entry) const {
   DCHECK(new_entry);
 
+  // Check for reasons to swap processes even if we are in a process model that
+  // doesn't usually swap (e.g., process-per-tab).
+
+  // For security, we should transition between processes when one is a Web UI
+  // page and one isn't.  If there's no cur_entry, check the current RVH's
+  // site, which might already be committed to a Web UI URL (such as the NTP).
+  const GURL& current_url = (cur_entry) ? cur_entry->url() :
+      render_view_host_->site_instance()->site();
+  Profile* profile = delegate_->GetControllerForRenderManager().profile();
+  if (WebUIFactory::UseWebUIForURL(profile, current_url)) {
+    // Force swap if it's not an acceptable URL for Web UI.
+    if (!WebUIFactory::IsURLAcceptableForWebUI(profile, new_entry->url()))
+      return true;
+  } else {
+    // Force swap if it's a Web UI URL.
+    if (WebUIFactory::UseWebUIForURL(profile, new_entry->url()))
+      return true;
+  }
+
   if (!cur_entry) {
     // Always choose a new process when navigating to extension URLs. The
     // process grouping logic will combine all of a given extension's pages
     // into the same process.
     if (new_entry->url().SchemeIs(chrome::kExtensionScheme))
       return true;
-    // When a tab is created, it starts as TYPE_NORMAL. If the new entry is a
-    // DOM UI page, it needs to be grouped with other DOM UI pages. This matches
-    // the logic when transitioning between DOM UI and normal pages.
-    Profile* profile = delegate_->GetControllerForRenderManager().profile();
-    if (DOMUIFactory::UseDOMUIForURL(profile, new_entry->url()))
-      return true;
+
     return false;
   }
 
@@ -314,19 +328,6 @@
   if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
     return true;
 
-  // For security, we should transition between processes when one is a DOM UI
-  // page and one isn't.
-  Profile* profile = delegate_->GetControllerForRenderManager().profile();
-  if (DOMUIFactory::UseDOMUIForURL(profile, cur_entry->url())) {
-    // Force swap if it's not an acceptable URL for DOM UI.
-    if (!DOMUIFactory::IsURLAcceptableForDOMUI(profile, new_entry->url()))
-      return true;
-  } else {
-    // Force swap if it's a DOM UI URL.
-    if (DOMUIFactory::UseDOMUIForURL(profile, new_entry->url()))
-      return true;
-  }
-
   // Also, we must switch if one is an extension and the other is not the exact
   // same extension.
   if (cur_entry->url().SchemeIs(chrome::kExtensionScheme) ||
@@ -366,7 +367,7 @@
   // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it
   // for this entry.  We won't commit the SiteInstance to this site until the
   // navigation commits (in DidNavigate), unless the navigation entry was
-  // restored or it's a DOM UI as described below.
+  // restored or it's a Web UI as described below.
   if (!curr_instance->has_site()) {
     // If we've already created a SiteInstance for our destination, we don't
     // want to use this unused SiteInstance; use the existing one.  (We don't
@@ -386,13 +387,13 @@
       // we need to set the site first, otherwise after a restore none of the
       // pages would share renderers.
       //
-      // For DOM UI (this mostly comes up for the new tab page), the
+      // For Web UI (this mostly comes up for the new tab page), the
       // SiteInstance has special meaning: we never want to reassign the
-      // process. If you navigate to another site before the DOM UI commits,
+      // process. If you navigate to another site before the Web UI commits,
       // we still want to create a new process rather than re-using the
-      // existing DOM UI process.
+      // existing Web UI process.
       if (entry.restore_type() != NavigationEntry::RESTORE_NONE ||
-          DOMUIFactory::HasDOMUIScheme(dest_url))
+          WebUIFactory::HasWebUIScheme(dest_url))
         curr_instance->SetSite(dest_url);
       return curr_instance;
     }
@@ -479,10 +480,10 @@
 
 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host,
                                            const NavigationEntry& entry) {
-  // If the pending navigation is to a DOMUI, tell the RenderView about any
+  // If the pending navigation is to a WebUI, tell the RenderView about any
   // bindings it will need enabled.
-  if (pending_dom_ui_.get())
-    render_view_host->AllowBindings(pending_dom_ui_->bindings());
+  if (pending_web_ui_.get())
+    render_view_host->AllowBindings(pending_web_ui_->bindings());
 
   // Tell the RenderView whether it will be used for an extension process.
   Profile* profile = delegate_->GetControllerForRenderManager().profile();
@@ -496,18 +497,18 @@
 void RenderViewHostManager::CommitPending() {
   // First check whether we're going to want to focus the location bar after
   // this commit.  We do this now because the navigation hasn't formally
-  // committed yet, so if we've already cleared |pending_dom_ui_| the call chain
+  // committed yet, so if we've already cleared |pending_web_ui_| the call chain
   // this triggers won't be able to figure out what's going on.
   bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
 
-  // Next commit the DOM UI, if any.
-  dom_ui_.swap(pending_dom_ui_);
-  if (dom_ui_.get() && pending_dom_ui_.get() && !pending_render_view_host_)
-    dom_ui_->DidBecomeActiveForReusedRenderView();
-  pending_dom_ui_.reset();
+  // Next commit the Web UI, if any.
+  web_ui_.swap(pending_web_ui_);
+  if (web_ui_.get() && pending_web_ui_.get() && !pending_render_view_host_)
+    web_ui_->DidBecomeActiveForReusedRenderView();
+  pending_web_ui_.reset();
 
   // It's possible for the pending_render_view_host_ to be NULL when we aren't
-  // crossing process boundaries. If so, we just needed to handle the DOM UI
+  // crossing process boundaries. If so, we just needed to handle the Web UI
   // committing above and we're done.
   if (!pending_render_view_host_) {
     if (will_focus_location_bar)
@@ -572,13 +573,13 @@
     cross_navigation_pending_ = false;
   }
 
-  // This will possibly create (set to NULL) a DOM UI object for the pending
+  // This will possibly create (set to NULL) a Web UI object for the pending
   // page. We'll use this later to give the page special access. This must
   // happen before the new renderer is created below so it will get bindings.
   // It must also happen after the above conditional call to CancelPending(),
-  // otherwise CancelPending may clear the pending_dom_ui_ and the page will
+  // otherwise CancelPending may clear the pending_web_ui_ and the page will
   // not have it's bindings set appropriately.
-  pending_dom_ui_.reset(delegate_->CreateDOMUIForRenderManager(entry.url()));
+  pending_web_ui_.reset(delegate_->CreateWebUIForRenderManager(entry.url()));
 
   // render_view_host_ will not be deleted before the end of this method, so we
   // don't have to worry about this SiteInstance's ref count dropping to zero.
@@ -646,8 +647,8 @@
 
     return pending_render_view_host_;
   } else {
-    if (pending_dom_ui_.get() && render_view_host_->IsRenderViewLive())
-      pending_dom_ui_->RenderViewReused(render_view_host_);
+    if (pending_web_ui_.get() && render_view_host_->IsRenderViewLive())
+      pending_web_ui_->RenderViewReused(render_view_host_);
 
     // The renderer can exit view source mode when any error or cancellation
     // happen. We must overwrite to recover the mode.
@@ -668,7 +669,7 @@
   pending_render_view_host_ = NULL;
   pending_render_view_host->Shutdown();
 
-  pending_dom_ui_.reset();
+  pending_web_ui_.reset();
 }
 
 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
@@ -686,7 +687,7 @@
 }
 
 void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) {
-  dom_ui_.reset();
+  web_ui_.reset();
 
   // Hide the current view and prepare to destroy it.
   if (render_view_host_->view())
diff --git a/chrome/browser/tab_contents/render_view_host_manager.h b/chrome/browser/tab_contents/render_view_host_manager.h
index 345b9cd..23fb866 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.h
+++ b/chrome/browser/tab_contents/render_view_host_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,9 +11,8 @@
 #include "base/scoped_ptr.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_observer.h"
 
-class DOMUI;
+class WebUI;
 class InterstitialPage;
 class NavigationController;
 class NavigationEntry;
@@ -52,10 +51,10 @@
     virtual void NotifySwappedFromRenderManager() = 0;
     virtual NavigationController& GetControllerForRenderManager() = 0;
 
-    // Creates a DOMUI object for the given URL if one applies. Ownership of the
-    // returned pointer will be passed to the caller. If no DOMUI applies,
+    // Creates a WebUI object for the given URL if one applies. Ownership of the
+    // returned pointer will be passed to the caller. If no WebUI applies,
     // returns NULL.
-    virtual DOMUI* CreateDOMUIForRenderManager(const GURL& url) = 0;
+    virtual WebUI* CreateWebUIForRenderManager(const GURL& url) = 0;
 
     // Returns the navigation entry of the current navigation, or NULL if there
     // is none.
@@ -108,11 +107,11 @@
     return pending_render_view_host_;
   }
 
-  // Returns the current committed DOM UI or NULL if none applies.
-  DOMUI* dom_ui() const { return dom_ui_.get(); }
+  // Returns the current committed Web UI or NULL if none applies.
+  WebUI* web_ui() const { return web_ui_.get(); }
 
-  // Returns the DOM UI for the pending navigation, or NULL of none applies.
-  DOMUI* pending_dom_ui() const { return pending_dom_ui_.get(); }
+  // Returns the Web UI for the pending navigation, or NULL of none applies.
+  WebUI* pending_web_ui() const { return pending_web_ui_.get(); }
 
   // Called when we want to instruct the renderer to navigate to the given
   // navigation entry. It may create a new RenderViewHost or re-use an existing
@@ -137,10 +136,10 @@
   // Called when a renderer's main frame navigates.
   void DidNavigateMainFrame(RenderViewHost* render_view_host);
 
-  // Set the DOMUI after committing a page load. This is useful for navigations
-  // initiated from a renderer, where we want to give the new renderer DOMUI
+  // Set the WebUI after committing a page load. This is useful for navigations
+  // initiated from a renderer, where we want to give the new renderer WebUI
   // privileges from the originating renderer.
-  void SetDOMUIPostCommit(DOMUI* dom_ui);
+  void SetWebUIPostCommit(WebUI* web_ui);
 
   // Called when a provisional load on the given renderer is aborted.
   void RendererAbortedProvisionalLoad(RenderViewHost* render_view_host);
@@ -190,7 +189,7 @@
   bool ShouldTransitionCrossSite();
 
   // Returns true if the two navigation entries are incompatible in some way
-  // other than site instances. Cases where this can happen include DOM UI
+  // other than site instances. Cases where this can happen include Web UI
   // to regular web pages. It will cause us to swap RenderViewHosts (and hence
   // RenderProcessHosts) even if the site instance would otherwise be the same.
   // As part of this, we'll also force new SiteInstances and BrowsingInstances.
@@ -215,9 +214,9 @@
   bool InitRenderView(RenderViewHost* render_view_host,
                       const NavigationEntry& entry);
 
-  // Sets the pending RenderViewHost/DOMUI to be the active one. Note that this
+  // Sets the pending RenderViewHost/WebUI to be the active one. Note that this
   // doesn't require the pending render_view_host_ pointer to be non-NULL, since
-  // there could be DOM UI switching as well. Call this for every commit.
+  // there could be Web UI switching as well. Call this for every commit.
   void CommitPending();
 
   // Helper method to terminate the pending RenderViewHost.
@@ -237,23 +236,23 @@
   // the RenderViewHosts that we create.
   RenderViewHostDelegate* render_view_delegate_;
 
-  // Our RenderView host and its associated DOM UI (if any, will be NULL for
+  // Our RenderView host and its associated Web UI (if any, will be NULL for
   // non-DOM-UI pages). This object is responsible for all communication with
   // a child RenderView instance.
   RenderViewHost* render_view_host_;
-  scoped_ptr<DOMUI> dom_ui_;
+  scoped_ptr<WebUI> web_ui_;
 
   // A RenderViewHost used to load a cross-site page. This remains hidden
   // while a cross-site request is pending until it calls DidNavigate. It may
-  // have an associated DOM UI, in which case the DOM UI pointer will be non-
+  // have an associated Web UI, in which case the Web UI pointer will be non-
   // NULL.
   //
-  // The pending_dom_ui may be non-NULL even when the pending_render_view_host_
-  // is. This will happen when we're transitioning between two DOM UI pages:
+  // The pending_web_ui may be non-NULL even when the pending_render_view_host_
+  // is. This will happen when we're transitioning between two Web UI pages:
   // the RVH won't be swapped, so the pending pointer will be unused, but there
-  // will be a pending DOM UI associated with the navigation.
+  // will be a pending Web UI associated with the navigation.
   RenderViewHost* pending_render_view_host_;
-  scoped_ptr<DOMUI> pending_dom_ui_;
+  scoped_ptr<WebUI> pending_web_ui_;
 
   // The intersitial page currently shown if any, not own by this class
   // (the InterstitialPage is self-owned, it deletes itself when hidden).
diff --git a/chrome/browser/tab_contents/render_view_host_manager_unittest.cc b/chrome/browser/tab_contents/render_view_host_manager_unittest.cc
index 5325abe..a4b82d8 100644
--- a/chrome/browser/tab_contents/render_view_host_manager_unittest.cc
+++ b/chrome/browser/tab_contents/render_view_host_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include "chrome/browser/tab_contents/test_tab_contents.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
+#include "chrome/common/page_transition_types.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/common/url_constants.h"
@@ -26,7 +27,7 @@
     // Note: we navigate the active RenderViewHost because previous navigations
     // won't have committed yet, so NavigateAndCommit does the wrong thing
     // for us.
-    controller().LoadURL(url, GURL(), 0);
+    controller().LoadURL(url, GURL(), PageTransition::LINK);
     active_rvh()->SendNavigate(
         static_cast<MockRenderProcessHost*>(active_rvh()->process())->
             max_page_id() + 1,
@@ -234,8 +235,8 @@
       NotificationType::RENDER_VIEW_HOST_CHANGED));
 }
 
-// Tests DOMUI creation.
-TEST_F(RenderViewHostManagerTest, DOMUI) {
+// Tests WebUI creation.
+TEST_F(RenderViewHostManagerTest, WebUI) {
   BrowserThread ui_thread(BrowserThread::UI, MessageLoop::current());
   SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get());
 
@@ -254,39 +255,40 @@
   EXPECT_TRUE(host == manager.current_host());
   EXPECT_FALSE(manager.pending_render_view_host());
 
-  // It's important that the site instance get set on the DOM UI page as soon
+  // It's important that the site instance get set on the Web UI page as soon
   // as the navigation starts, rather than lazily after it commits, so we don't
   // try to re-use the SiteInstance/process for non DOM-UI things that may
   // get loaded in between.
   EXPECT_TRUE(host->site_instance()->has_site());
   EXPECT_EQ(url, host->site_instance()->site());
 
-  // The DOM UI is committed immediately because the RenderViewHost has not been
+  // The Web UI is committed immediately because the RenderViewHost has not been
   // used yet. UpdateRendererStateForNavigate() took the short cut path.
-  EXPECT_FALSE(manager.pending_dom_ui());
-  EXPECT_TRUE(manager.dom_ui());
+  EXPECT_FALSE(manager.pending_web_ui());
+  EXPECT_TRUE(manager.web_ui());
 
   // Commit.
   manager.DidNavigateMainFrame(host);
 }
 
-// Tests that chrome: URLs that are not DOM UI pages do not get grouped into
-// DOM UI renderers, even if --process-per-tab is enabled.  In that mode, we
+// Tests that chrome: URLs that are not Web UI pages do not get grouped into
+// Web UI renderers, even if --process-per-tab is enabled.  In that mode, we
 // still swap processes if ShouldSwapProcessesForNavigation is true.
 // Regression test for bug 46290.
-TEST_F(RenderViewHostManagerTest, NonDOMUIChromeURLs) {
+TEST_F(RenderViewHostManagerTest, NonWebUIChromeURLs) {
+  BrowserThread thread(BrowserThread::UI, &message_loop_);
   SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get());
   TestTabContents tab_contents(profile_.get(), instance);
   RenderViewHostManager manager(&tab_contents, &tab_contents);
   manager.Init(profile_.get(), instance, MSG_ROUTING_NONE);
 
-  // NTP is a DOM UI page.
+  // NTP is a Web UI page.
   GURL ntp_url(chrome::kChromeUINewTabURL);
   NavigationEntry ntp_entry(NULL /* instance */, -1 /* page_id */, ntp_url,
                             GURL() /* referrer */, string16() /* title */,
                             PageTransition::TYPED);
 
-  // about: URLs are not DOM UI pages.
+  // about: URLs are not Web UI pages.
   GURL about_url(chrome::kAboutMemoryURL);
   // Rewrite so it looks like chrome://about/memory
   bool reverse_on_redirect = false;
@@ -313,13 +315,8 @@
   contents()->NavigateAndCommit(url2);
   RenderViewHost* evil_rvh = contents()->render_view_host();
 
-  // Casts the TabContents to a RenderViewHostDelegate::BrowserIntegration so we
-  // can call GoToEntryAtOffset which is private.
-  RenderViewHostDelegate::BrowserIntegration* rvh_delegate =
-      static_cast<RenderViewHostDelegate::BrowserIntegration*>(contents());
-
   // Now let's simulate the evil page calling history.back().
-  rvh_delegate->GoToEntryAtOffset(-1);
+  contents()->OnGoToEntryAtOffset(-1);
   // We should have a new pending RVH.
   // Note that in this case, the navigation has not committed, so evil_rvh will
   // not be deleted yet.
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 698d691..5810f59 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <cmath>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/auto_reset.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/stats_counters.h"
@@ -18,7 +16,6 @@
 #include "chrome/browser/autocomplete_history_manager.h"
 #include "chrome/browser/autofill/autofill_manager.h"
 #include "chrome/browser/blocked_content_container.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/character_encoding.h"
@@ -27,8 +24,9 @@
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/debugger/devtools_manager.h"
 #include "chrome/browser/defaults.h"
+#include "chrome/browser/desktop_notification_handler.h"
 #include "chrome/browser/dom_operation_notification_details.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/download/download_request_limiter.h"
@@ -49,10 +47,13 @@
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/modal_html_dialog_delegate.h"
 #include "chrome/browser/omnibox_search_hint.h"
+#include "chrome/browser/pdf_unsupported_feature.h"
 #include "chrome/browser/platform_util.h"
-#include "chrome/browser/plugin_installer.h"
+#include "chrome/browser/plugin_observer.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_plt_recorder.h"
+#include "chrome/browser/printing/print_preview_message_handler.h"
 #include "chrome/browser/printing/print_preview_tab_controller.h"
 #include "chrome/browser/printing/print_view_manager.h"
 #include "chrome/browser/profiles/profile.h"
@@ -73,12 +74,12 @@
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/provisional_load_details.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
 #include "chrome/browser/tab_contents/tab_contents_ssl_helper.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/tab_contents/web_navigation_observer.h"
+#include "chrome/browser/tab_contents/thumbnail_generator.h"
 #include "chrome/browser/translate/page_translated_details.h"
 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h"
-#include "chrome/browser/ui/find_bar/find_bar_state.h"
 #include "chrome/common/bindings_policy.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/content_restriction.h"
@@ -94,7 +95,6 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
@@ -102,15 +102,21 @@
 #include "grit/theme_resources.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domain.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "webkit/glue/password_form.h"
-#include "webkit/plugins/npapi/plugin_list.h"
 #include "webkit/glue/webpreferences.h"
 
 #if defined(OS_MACOSX)
 #include "app/surface/io_surface_support_mac.h"
 #endif  // defined(OS_MACOSX)
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/locale_change_guard.h"
+#endif  // defined(OS_CHROMEOS)
+
 // Cross-Site Navigations
 //
 // If a TabContents is told to navigate to a different web site (as determined
@@ -242,77 +248,10 @@
   params->request_time = base::Time::Now();
 }
 
-class OutdatedPluginInfoBar : public ConfirmInfoBarDelegate {
- public:
-  OutdatedPluginInfoBar(TabContents* tab_contents,
-                        const string16& name,
-                        const GURL& update_url)
-      : ConfirmInfoBarDelegate(tab_contents),
-        tab_contents_(tab_contents),
-        name_(name),
-        update_url_(update_url) {
-    tab_contents->AddInfoBar(this);
-  }
-
-  virtual int GetButtons() const {
-    return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    if (button == BUTTON_CANCEL)
-      return l10n_util::GetStringUTF16(IDS_PLUGIN_ENABLE_TEMPORARILY);
-    if (button == BUTTON_OK)
-      return l10n_util::GetStringUTF16(IDS_PLUGIN_UPDATE);
-    return ConfirmInfoBarDelegate::GetButtonLabel(button);
-  }
-
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED_PROMPT, name_);
-  }
-
-  virtual string16 GetLinkText() {
-    return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-        IDR_INFOBAR_PLUGIN_INSTALL);
-  }
-
-  virtual bool Accept() {
-    tab_contents_->OpenURL(update_url_, GURL(),
-                           NEW_FOREGROUND_TAB, PageTransition::LINK);
-    return false;
-  }
-
-  virtual bool Cancel() {
-    tab_contents_->render_view_host()->LoadBlockedPlugins();
-    return true;
-  }
-
-  virtual bool LinkClicked(WindowOpenDisposition disposition) {
-    // TODO(bauerb): Navigate to a help page explaining why we disabled
-    // the plugin, once we have one.
-    return false;
-  }
-
-  virtual void InfoBarClosed() {
-    delete this;
-  }
-
- private:
-  TabContents* tab_contents_;
-  string16 name_;
-  GURL update_url_;
-};
-
 }  // namespace
 
-// -----------------------------------------------------------------------------
 
-// static
-int TabContents::find_request_id_counter_ = -1;
-
+// TabContents ----------------------------------------------------------------
 
 TabContents::TabContents(Profile* profile,
                          SiteInstance* site_instance,
@@ -329,10 +268,12 @@
       registrar_(),
       ALLOW_THIS_IN_INITIALIZER_LIST(printing_(
           new printing::PrintViewManager(*this))),
+      ALLOW_THIS_IN_INITIALIZER_LIST(print_preview_(
+          new printing::PrintPreviewMessageHandler(this))),
       save_package_(),
       autocomplete_history_manager_(),
       autofill_manager_(),
-      plugin_installer_(),
+      prerender_plt_recorder_(),
       bookmark_drag_(NULL),
       ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)),
       is_loading_(false),
@@ -346,7 +287,6 @@
       upload_size_(0),
       upload_position_(0),
       received_page_title_(false),
-      is_starred_(false),
       contents_mime_type_(),
       encoding_(),
       blocked_contents_(NULL),
@@ -354,11 +294,6 @@
       dont_notify_render_view_(false),
       displayed_insecure_content_(false),
       infobar_delegates_(),
-      find_ui_active_(false),
-      find_op_aborted_(false),
-      current_find_request_id_(find_request_id_counter_++),
-      last_search_case_sensitive_(false),
-      last_search_result_(),
       extension_app_(NULL),
       capturing_contents_(false),
       is_being_destroyed_(false),
@@ -371,7 +306,7 @@
       suppress_javascript_messages_(false),
       is_showing_before_unload_dialog_(false),
       renderer_preferences_(),
-      opener_dom_ui_type_(DOMUIFactory::kNoDOMUI),
+      opener_web_ui_type_(WebUIFactory::kNoWebUI),
       language_state_(&controller_),
       closed_by_user_gesture_(false),
       minimum_zoom_percent_(
@@ -401,11 +336,6 @@
       pref_change_registrar_.Add(kPrefsToObserve[i], this);
   }
 
-  // Register for notifications about URL starredness changing on any profile.
-  registrar_.Add(this, NotificationType::URLS_STARRED,
-                 NotificationService::AllSources());
-  registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED,
-                 NotificationService::AllSources());
   registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
                  NotificationService::AllSources());
 #if defined(OS_LINUX)
@@ -433,6 +363,21 @@
   // Set-up the showing of the omnibox search infobar if applicable.
   if (OmniboxSearchHint::IsEnabled(profile))
     omnibox_search_hint_.reset(new OmniboxSearchHint(this));
+
+  autofill_manager_.reset(new AutoFillManager(this));
+  AddObserver(autofill_manager_.get());
+  autocomplete_history_manager_.reset(new AutocompleteHistoryManager(this));
+  AddObserver(autocomplete_history_manager_.get());
+  prerender_plt_recorder_.reset(new PrerenderPLTRecorder(this));
+  AddObserver(prerender_plt_recorder_.get());
+  AddObserver(&fav_icon_helper_);
+  AddObserver(printing_.get());
+  desktop_notification_handler_.reset(
+      new DesktopNotificationHandler(this, GetRenderProcessHost()));
+  AddObserver(desktop_notification_handler_.get());
+  plugin_observer_.reset(new PluginObserver(this));
+  AddObserver(plugin_observer_.get());
+  AddObserver(print_preview_.get());
 }
 
 TabContents::~TabContents() {
@@ -468,7 +413,7 @@
   // notification may trigger infobars calls that access their delegate. (and
   // some implementations of InfoBarDelegate do delete themselves on
   // InfoBarClosed()).
-  for (int i = 0; i < infobar_delegate_count(); ++i) {
+  for (size_t i = 0; i < infobar_count(); ++i) {
     InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
     delegate->InfoBarClosed();
   }
@@ -552,6 +497,12 @@
 }
 
 bool TabContents::OnMessageReceived(const IPC::Message& message) {
+  ObserverListBase<TabContentsObserver>::Iterator it(observers_);
+  TabContentsObserver* observer;
+  while ((observer = it.GetNext()) != NULL)
+    if (observer->OnMessageReceived(message))
+      return true;
+
   bool handled = true;
   bool message_is_ok = true;
   IPC_BEGIN_MESSAGE_MAP_EX(TabContents, message, message_is_ok)
@@ -570,6 +521,21 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame,
                         OnDocumentLoadedInFrame)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions,
+                        OnUpdateContentRestrictions)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_PDFHasUnsupportedFeature,
+                        OnPDFHasUnsupportedFeature)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetApplicationInfo,
+                        OnDidGetApplicationInfo)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_InstallApplication,
+                        OnInstallApplication)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_PageTranslated, OnPageTranslated)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_SetSuggestions, OnSetSuggestions)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_InstantSupportDetermined,
+                        OnInstantSupportDetermined)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP_EX()
 
@@ -586,18 +552,6 @@
   return GetURL().SchemeIs(chrome::kExtensionScheme);
 }
 
-AutoFillManager* TabContents::GetAutoFillManager() {
-  if (autofill_manager_.get() == NULL)
-    autofill_manager_.reset(new AutoFillManager(this));
-  return autofill_manager_.get();
-}
-
-PluginInstaller* TabContents::GetPluginInstaller() {
-  if (plugin_installer_.get() == NULL)
-    plugin_installer_.reset(new PluginInstaller(this));
-  return plugin_installer_.get();
-}
-
 TabContentsSSLHelper* TabContents::GetSSLHelper() {
   if (ssl_helper_.get() == NULL)
     ssl_helper_.reset(new TabContentsSSLHelper(this));
@@ -655,14 +609,14 @@
     return entry->GetTitleForDisplay(profile()->GetPrefs()->
         GetString(prefs::kAcceptLanguages));
   }
-  DOMUI* our_dom_ui = render_manager_.pending_dom_ui() ?
-      render_manager_.pending_dom_ui() : render_manager_.dom_ui();
-  if (our_dom_ui) {
+  WebUI* our_web_ui = render_manager_.pending_web_ui() ?
+      render_manager_.pending_web_ui() : render_manager_.web_ui();
+  if (our_web_ui) {
     // Don't override the title in view source mode.
     entry = controller_.GetActiveEntry();
     if (!(entry && entry->IsViewSourceMode())) {
-      // Give the DOM UI the chance to override our title.
-      const string16& title = our_dom_ui->overridden_title();
+      // Give the Web UI the chance to override our title.
+      const string16& title = our_web_ui->overridden_title();
       if (!title.empty())
         return title;
     }
@@ -713,9 +667,9 @@
     return true;
   }
 
-  DOMUI* dom_ui = GetDOMUIForCurrentState();
-  if (dom_ui)
-    return !dom_ui->should_hide_url();
+  WebUI* web_ui = GetWebUIForCurrentState();
+  if (web_ui)
+    return !web_ui->should_hide_url();
   return true;
 }
 
@@ -749,9 +703,9 @@
   if (controller_.GetLastCommittedEntry() && controller_.pending_entry())
     return true;
 
-  DOMUI* dom_ui = GetDOMUIForCurrentState();
-  if (dom_ui)
-    return !dom_ui->hide_favicon();
+  WebUI* web_ui = GetWebUIForCurrentState();
+  if (web_ui)
+    return !web_ui->hide_favicon();
   return true;
 }
 
@@ -792,12 +746,12 @@
   return string16();
 }
 
-void TabContents::AddNavigationObserver(WebNavigationObserver* observer) {
-  web_navigation_observers_.AddObserver(observer);
+void TabContents::AddObserver(TabContentsObserver* observer) {
+  observers_.AddObserver(observer);
 }
 
-void TabContents::RemoveNavigationObserver(WebNavigationObserver* observer) {
-  web_navigation_observers_.RemoveObserver(observer);
+void TabContents::RemoveObserver(TabContentsObserver* observer) {
+  observers_.RemoveObserver(observer);
 }
 
 void TabContents::SetIsCrashed(base::TerminationStatus status, int error_code) {
@@ -830,6 +784,9 @@
 
   WebCacheManager::GetInstance()->ObserveActivity(GetRenderProcessHost()->id());
   last_selected_time_ = base::TimeTicks::Now();
+#if defined(OS_CHROMEOS)
+  chromeos::LocaleChangeGuard::Check(this);
+#endif
 }
 
 void TabContents::FadeForInstant(bool animate) {
@@ -920,13 +877,13 @@
         kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
   }
 
-  // For security, we should never send non-DOM-UI URLs to a DOM UI renderer.
+  // For security, we should never send non-Web-UI URLs to a Web UI renderer.
   // Double check that here.
   int enabled_bindings = dest_render_view_host->enabled_bindings();
-  bool is_allowed_in_dom_ui_renderer =
-      DOMUIFactory::IsURLAcceptableForDOMUI(profile(), entry.url());
-  CHECK(!BindingsPolicy::is_dom_ui_enabled(enabled_bindings) ||
-        is_allowed_in_dom_ui_renderer);
+  bool is_allowed_in_web_ui_renderer =
+      WebUIFactory::IsURLAcceptableForWebUI(profile(), entry.url());
+  CHECK(!BindingsPolicy::is_web_ui_enabled(enabled_bindings) ||
+        is_allowed_in_web_ui_renderer);
 
   // Tell DevTools agent that it is attached prior to the navigation.
   DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
@@ -959,8 +916,7 @@
   }
 
   // Notify observers about navigation.
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
-                    NavigateToPendingEntry());
+  FOR_EACH_OBSERVER(TabContentsObserver, observers_, NavigateToPendingEntry());
 
   if (reload_type != NavigationController::NO_RELOAD &&
       !profile()->IsOffTheRecord()) {
@@ -1137,9 +1093,9 @@
 }
 
 bool TabContents::FocusLocationBarByDefault() {
-  DOMUI* dom_ui = GetDOMUIForCurrentState();
-  if (dom_ui)
-    return dom_ui->focus_location_bar_by_default();
+  WebUI* web_ui = GetWebUIForCurrentState();
+  if (web_ui)
+    return web_ui->focus_location_bar_by_default();
   NavigationEntry* entry = controller_.GetActiveEntry();
   if (entry && entry->url() == GURL(chrome::kAboutBlankURL))
     return true;
@@ -1159,7 +1115,7 @@
 
   // Look through the existing InfoBarDelegates we have for a match. If we've
   // already got one that matches, then we don't add the new one.
-  for (int i = 0; i < infobar_delegate_count(); ++i) {
+  for (size_t i = 0; i < infobar_count(); ++i) {
     if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) {
       // Tell the new infobar to close so that it can clean itself up.
       delegate->InfoBarClosed();
@@ -1169,8 +1125,7 @@
 
   infobar_delegates_.push_back(delegate);
   NotificationService::current()->Notify(
-      NotificationType::TAB_CONTENTS_INFOBAR_ADDED,
-      Source<TabContents>(this),
+      NotificationType::TAB_CONTENTS_INFOBAR_ADDED, Source<TabContents>(this),
       Details<InfoBarDelegate>(delegate));
 
   // Add ourselves as an observer for navigations the first time a delegate is
@@ -1196,19 +1151,11 @@
         Source<TabContents>(this),
         Details<InfoBarDelegate>(delegate));
 
-    // Just to be safe, make sure the delegate was not removed by an observer.
-    it = find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
-    if (it != infobar_delegates_.end()) {
-      infobar_delegates_.erase(it);
-      // Remove ourselves as an observer if we are tracking no more InfoBars.
-      if (infobar_delegates_.empty()) {
-        registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
-                          Source<NavigationController>(&controller_));
-      }
-    } else {
-      // If you hit this NOTREACHED, please comment in bug
-      // http://crbug.com/50428 how you got there.
-      NOTREACHED();
+    infobar_delegates_.erase(it);
+    // Remove ourselves as an observer if we are tracking no more InfoBars.
+    if (infobar_delegates_.empty()) {
+      registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
+                        Source<NavigationController>(&controller_));
     }
   }
 }
@@ -1233,16 +1180,8 @@
       Source<TabContents>(this),
       Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details.get()));
 
-  // Just to be safe, make sure the delegate was not removed by an observer.
-  it = find(infobar_delegates_.begin(), infobar_delegates_.end(), old_delegate);
-  if (it != infobar_delegates_.end()) {
-    // Remove the old one.
-    infobar_delegates_.erase(it);
-  } else {
-    // If you hit this NOTREACHED, please comment in bug
-    // http://crbug.com/50428 how you got there.
-    NOTREACHED();
-  }
+  // Remove the old one.
+  infobar_delegates_.erase(it);
 
   // Add the new one.
   DCHECK(find(infobar_delegates_.begin(),
@@ -1259,22 +1198,22 @@
   if (!browser_defaults::bookmarks_enabled)
     return false;
 
-  // See GetDOMUIForCurrentState() comment for more info. This case is very
+  // See GetWebUIForCurrentState() comment for more info. This case is very
   // similar, but for non-first loads, we want to use the committed entry. This
   // is so the bookmarks bar disappears at the same time the page does.
   if (controller_.GetLastCommittedEntry()) {
-    // Not the first load, always use the committed DOM UI.
-    return (render_manager_.dom_ui() == NULL) ?
-        false : render_manager_.dom_ui()->force_bookmark_bar_visible();
+    // Not the first load, always use the committed Web UI.
+    return (render_manager_.web_ui() == NULL) ?
+        false : render_manager_.web_ui()->force_bookmark_bar_visible();
   }
 
   // When it's the first load, we know either the pending one or the committed
-  // one will have the DOM UI in it (see GetDOMUIForCurrentState), and only one
+  // one will have the Web UI in it (see GetWebUIForCurrentState), and only one
   // of them will be valid, so we can just check both.
-  if (render_manager_.pending_dom_ui())
-    return render_manager_.pending_dom_ui()->force_bookmark_bar_visible();
-  return (render_manager_.dom_ui() == NULL) ?
-      false : render_manager_.dom_ui()->force_bookmark_bar_visible();
+  if (render_manager_.pending_web_ui())
+    return render_manager_.pending_web_ui()->force_bookmark_bar_visible();
+  return (render_manager_.web_ui() == NULL) ?
+      false : render_manager_.web_ui()->force_bookmark_bar_visible();
 }
 
 void TabContents::ToolbarSizeChanged(bool is_animating) {
@@ -1328,74 +1267,6 @@
 #endif
 }
 
-void TabContents::StartFinding(string16 search_string,
-                               bool forward_direction,
-                               bool case_sensitive) {
-  // If search_string is empty, it means FindNext was pressed with a keyboard
-  // shortcut so unless we have something to search for we return early.
-  if (search_string.empty() && find_text_.empty()) {
-    string16 last_search_prepopulate_text =
-        FindBarState::GetLastPrepopulateText(profile());
-
-    // Try the last thing we searched for on this tab, then the last thing
-    // searched for on any tab.
-    if (!previous_find_text_.empty())
-      search_string = previous_find_text_;
-    else if (!last_search_prepopulate_text.empty())
-      search_string = last_search_prepopulate_text;
-    else
-      return;
-  }
-
-  // Keep track of the previous search.
-  previous_find_text_ = find_text_;
-
-  // This is a FindNext operation if we are searching for the same text again,
-  // or if the passed in search text is empty (FindNext keyboard shortcut). The
-  // exception to this is if the Find was aborted (then we don't want FindNext
-  // because the highlighting has been cleared and we need it to reappear). We
-  // therefore treat FindNext after an aborted Find operation as a full fledged
-  // Find.
-  bool find_next = (find_text_ == search_string || search_string.empty()) &&
-                   (last_search_case_sensitive_ == case_sensitive) &&
-                   !find_op_aborted_;
-  if (!find_next)
-    current_find_request_id_ = find_request_id_counter_++;
-
-  if (!search_string.empty())
-    find_text_ = search_string;
-  last_search_case_sensitive_ = case_sensitive;
-
-  find_op_aborted_ = false;
-
-  // Keep track of what the last search was across the tabs.
-  FindBarState* find_bar_state = profile()->GetFindBarState();
-  find_bar_state->set_last_prepopulate_text(find_text_);
-  render_view_host()->StartFinding(current_find_request_id_,
-                                   find_text_,
-                                   forward_direction,
-                                   case_sensitive,
-                                   find_next);
-}
-
-void TabContents::StopFinding(
-    FindBarController::SelectionAction selection_action) {
-  if (selection_action == FindBarController::kClearSelection) {
-    // kClearSelection means the find string has been cleared by the user, but
-    // the UI has not been dismissed. In that case we want to clear the
-    // previously remembered search (http://crbug.com/42639).
-    previous_find_text_ = string16();
-  } else {
-    find_ui_active_ = false;
-    if (!find_text_.empty())
-      previous_find_text_ = find_text_;
-  }
-  find_text_.clear();
-  find_op_aborted_ = true;
-  last_search_result_ = FindNotificationDetails();
-  render_view_host()->StopFinding(selection_action);
-}
-
 void TabContents::OnSavePage() {
   // If we can not save the page, try to download it.
   if (!SavePackage::IsSavableContents(contents_mime_type())) {
@@ -1411,7 +1282,7 @@
   // Create the save package and possibly prompt the user for the name to save
   // the page as. The user prompt is an asynchronous operation that runs on
   // another thread.
-  save_package_ = new SavePackage(this);
+  SetSavePackage(new SavePackage(this));
   save_package_->GetSaveInfo();
 }
 
@@ -1423,10 +1294,17 @@
   // Stop the page from navigating.
   Stop();
 
-  save_package_ = new SavePackage(this, save_type, main_file, dir_path);
+  SetSavePackage(new SavePackage(this, save_type, main_file, dir_path));
   return save_package_->Init();
 }
 
+void TabContents::SetSavePackage(SavePackage* save_package) {
+  if (save_package_.get())
+    RemoveObserver(save_package_.get());
+  save_package_ = save_package;
+  AddObserver(save_package);
+}
+
 void TabContents::EmailPageLocation() {
   std::string title = EscapeQueryParamValue(UTF16ToUTF8(GetTitle()), false);
   std::string page_url = EscapeQueryParamValue(GetURL().spec(), false);
@@ -1440,6 +1318,13 @@
           switches::kEnablePrintPreview)) {
     if (showing_interstitial_page())
       return;
+
+    printing::PrintPreviewTabController* tab_controller =
+      printing::PrintPreviewTabController::GetInstance();
+    if (!tab_controller)
+      return;
+    tab_controller->GetOrCreatePreviewTab(this, controller().window_id().id());
+
     render_view_host()->PrintPreview();
   } else {
     PrintNow();
@@ -1536,6 +1421,13 @@
 #endif
 }
 
+void TabContents::SystemDragEnded() {
+  if (render_view_host())
+    render_view_host()->DragSourceSystemDragEnded();
+  if (delegate())
+    delegate()->DragEnded();
+}
+
 void TabContents::UpdateHistoryForNavigation(
     scoped_refptr<history::HistoryAddPageArgs> add_page_args) {
   if (profile()->IsOffTheRecord())
@@ -1615,6 +1507,10 @@
     if (!is_error_page)
       content_settings_delegate_->ClearCookieSpecificContentSettings();
     content_settings_delegate_->ClearGeolocationContentSettings();
+
+    // Check if the URL we are about to load has been prerendered by any chance,
+    // and use it if possible.
+    MaybeUsePreloadedPage(url);
   }
 }
 
@@ -1629,6 +1525,10 @@
   if (!entry || entry->url() != source_url)
     return;
   entry->set_url(target_url);
+
+  // Check if the URL we are about to load has been prerendered by any chance,
+  // and use it if possible.
+  MaybeUsePreloadedPage(target_url);
 }
 
 void TabContents::OnDidFailProvisionalLoadWithError(
@@ -1726,7 +1626,9 @@
 }
 
 void TabContents::OnDidRunInsecureContent(
-    const std::string& security_origin) {
+    const std::string& security_origin, const GURL& target_url) {
+  LOG(INFO) << security_origin << " ran insecure content from "
+            << target_url.possibly_invalid_spec();
   controller_.ssl_manager()->DidRunInsecureContent(security_origin);
 }
 
@@ -1745,6 +1647,15 @@
       Details<int64>(&frame_id));
 }
 
+void TabContents::OnUpdateContentRestrictions(int restrictions) {
+  content_restrictions_ = restrictions;
+  delegate()->ContentRestrictionsChanged(this);
+}
+
+void TabContents::OnPDFHasUnsupportedFeature() {
+  PDFHasUnsupportedFeature(this);
+}
+
 // Notifies the RenderWidgetHost instance about the fact that the page is
 // loading, or done loading and calls the base implementation.
 void TabContents::SetIsLoading(bool is_loading,
@@ -1812,22 +1723,18 @@
   if (!details.is_user_initiated_main_frame_load())
     return;
 
-  for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
-    InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
-    if (!delegate) {
-      // If you hit this NOTREACHED, please comment in bug
-      // http://crbug.com/50428 how you got there.
-      NOTREACHED();
-      continue;
-    }
-
+  // NOTE: It is not safe to change the following code to count upwards or use
+  // iterators, as the RemoveInfoBar() call synchronously modifies our delegate
+  // list.
+  for (size_t i = infobar_count(); i > 0; --i) {
+    InfoBarDelegate* delegate = GetInfoBarDelegateAt(i - 1);
     if (delegate->ShouldExpire(details))
       RemoveInfoBar(delegate);
   }
 }
 
-DOMUI* TabContents::GetDOMUIForCurrentState() {
-  // When there is a pending navigation entry, we want to use the pending DOMUI
+WebUI* TabContents::GetWebUIForCurrentState() {
+  // When there is a pending navigation entry, we want to use the pending WebUI
   // that goes along with it to control the basic flags. For example, we want to
   // show the pending URL in the URL bar, so we want the display_url flag to
   // be from the pending entry.
@@ -1836,53 +1743,53 @@
   // initial load in a tab as a side effect of the way the RenderViewHostManager
   // works.
   //
-  //  - For the very first tab the load looks "normal". The new tab DOM UI is
+  //  - For the very first tab the load looks "normal". The new tab Web UI is
   //    the pending one, and we want it to apply here.
   //
   //  - For subsequent new tabs, they'll get a new SiteInstance which will then
   //    get switched to the one previously associated with the new tab pages.
-  //    This switching will cause the manager to commit the RVH/DOMUI. So we'll
-  //    have a committed DOM UI in this case.
+  //    This switching will cause the manager to commit the RVH/WebUI. So we'll
+  //    have a committed Web UI in this case.
   //
   // This condition handles all of these cases:
   //
   //  - First load in first tab: no committed nav entry + pending nav entry +
   //    pending dom ui:
-  //    -> Use pending DOM UI if any.
+  //    -> Use pending Web UI if any.
   //
   //  - First load in second tab: no committed nav entry + pending nav entry +
-  //    no pending DOM UI:
-  //    -> Use the committed DOM UI if any.
+  //    no pending Web UI:
+  //    -> Use the committed Web UI if any.
   //
   //  - Second navigation in any tab: committed nav entry + pending nav entry:
-  //    -> Use pending DOM UI if any.
+  //    -> Use pending Web UI if any.
   //
   //  - Normal state with no load: committed nav entry + no pending nav entry:
-  //    -> Use committed DOM UI.
+  //    -> Use committed Web UI.
   if (controller_.pending_entry() &&
       (controller_.GetLastCommittedEntry() ||
-       render_manager_.pending_dom_ui()))
-    return render_manager_.pending_dom_ui();
-  return render_manager_.dom_ui();
+       render_manager_.pending_web_ui()))
+    return render_manager_.pending_web_ui();
+  return render_manager_.web_ui();
 }
 
 void TabContents::DidNavigateMainFramePostCommit(
     const NavigationController::LoadCommittedDetails& details,
     const ViewHostMsg_FrameNavigate_Params& params) {
-  if (opener_dom_ui_type_ != DOMUIFactory::kNoDOMUI) {
-    // If this is a window.open navigation, use the same DOMUI as the renderer
+  if (opener_web_ui_type_ != WebUIFactory::kNoWebUI) {
+    // If this is a window.open navigation, use the same WebUI as the renderer
     // that opened the window, as long as both renderers have the same
     // privileges.
-    if (opener_dom_ui_type_ ==
-        DOMUIFactory::GetDOMUIType(profile(), GetURL())) {
-      DOMUI* dom_ui = DOMUIFactory::CreateDOMUIForURL(this, GetURL());
-      // dom_ui might be NULL if the URL refers to a non-existent extension.
-      if (dom_ui) {
-        render_manager_.SetDOMUIPostCommit(dom_ui);
-        dom_ui->RenderViewCreated(render_view_host());
+    if (opener_web_ui_type_ ==
+        WebUIFactory::GetWebUIType(profile(), GetURL())) {
+      WebUI* web_ui = WebUIFactory::CreateWebUIForURL(this, GetURL());
+      // web_ui might be NULL if the URL refers to a non-existent extension.
+      if (web_ui) {
+        render_manager_.SetWebUIPostCommit(web_ui);
+        web_ui->RenderViewCreated(render_view_host());
       }
     }
-    opener_dom_ui_type_ = DOMUIFactory::kNoDOMUI;
+    opener_web_ui_type_ = WebUIFactory::kNoWebUI;
   }
 
   if (details.is_user_initiated_main_frame_load()) {
@@ -1951,16 +1858,9 @@
       details.previous_url, details.entry->url()))
     CloseConstrainedWindows();
 
-  // Update the starred state.
-  UpdateStarredStateForCurrentURL();
-
   // Notify observers about navigation.
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
+  FOR_EACH_OBSERVER(TabContentsObserver, observers_,
                     DidNavigateMainFramePostCommit(details, params));
-
-  // Clear the cache of forms in AutoFill.
-  if (autofill_manager_.get())
-    autofill_manager_->Reset();
 }
 
 void TabContents::DidNavigateAnyFramePostCommit(
@@ -1973,7 +1873,7 @@
   suppress_javascript_messages_ = false;
 
   // Notify observers about navigation.
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
+  FOR_EACH_OBSERVER(TabContentsObserver, observers_,
                     DidNavigateAnyFramePostCommit(details, params));
 
   // Let the LanguageState clear its state.
@@ -1984,9 +1884,8 @@
   // Clear out any constrained windows since we are leaving this page entirely.
   // We use indices instead of iterators in case CloseWindow does something
   // that may invalidate an iterator.
-  int size = static_cast<int>(child_windows_.size());
-  for (int i = size - 1; i >= 0; --i) {
-    ConstrainedWindow* window = child_windows_[i];
+  for (size_t i = 0; i < child_windows_.size(); ++i) {
+    ConstrainedWindow* window = child_windows_[child_windows_.size() - 1 - i];
     if (window) {
       window->CloseConstrainedWindow();
       BlockTabContent(false);
@@ -1994,15 +1893,6 @@
   }
 }
 
-void TabContents::UpdateStarredStateForCurrentURL() {
-  BookmarkModel* model = profile()->GetBookmarkModel();
-  const bool old_state = is_starred_;
-  is_starred_ = (model && model->IsBookmarked(GetURL()));
-
-  if (is_starred_ != old_state && delegate())
-    delegate()->URLStarredChanged(this, is_starred_);
-}
-
 void TabContents::UpdateAlternateErrorPageURL() {
   GURL url = GetAlternateErrorPageURL();
   render_view_host()->SetAlternateErrorPageURL(url);
@@ -2157,7 +2047,7 @@
 
   GURL keyword_url = previous_entry->user_typed_url().is_valid() ?
           previous_entry->user_typed_url() : previous_entry->url();
-  std::wstring keyword =
+  string16 keyword =
       TemplateURLModel::GenerateKeyword(keyword_url, true);  // autodetected
   if (keyword.empty())
     return;
@@ -2206,51 +2096,7 @@
   url_model->Add(new_url);
 }
 
-void TabContents::OnUserGesture() {
-  // See comment in RenderViewHostDelegate::OnUserGesture as to why we do this.
-  DownloadRequestLimiter* limiter =
-      g_browser_process->download_request_limiter();
-  if (limiter)
-    limiter->OnUserGesture(this);
-  ExternalProtocolHandler::PermitLaunchUrl();
-}
-
-void TabContents::OnFindReply(int request_id,
-                              int number_of_matches,
-                              const gfx::Rect& selection_rect,
-                              int active_match_ordinal,
-                              bool final_update) {
-  // Ignore responses for requests that have been aborted.
-  if (find_op_aborted_)
-    return;
-
-  // Ignore responses for requests other than the one we have most recently
-  // issued. That way we won't act on stale results when the user has
-  // already typed in another query.
-  if (request_id != current_find_request_id_)
-    return;
-
-  if (number_of_matches == -1)
-    number_of_matches = last_search_result_.number_of_matches();
-  if (active_match_ordinal == -1)
-    active_match_ordinal = last_search_result_.active_match_ordinal();
-
-  gfx::Rect selection = selection_rect;
-  if (selection.IsEmpty())
-    selection = last_search_result_.selection_rect();
-
-  // Notify the UI, automation and any other observers that a find result was
-  // found.
-  last_search_result_ = FindNotificationDetails(request_id, number_of_matches,
-                                                selection, active_match_ordinal,
-                                                final_update);
-  NotificationService::current()->Notify(
-      NotificationType::FIND_RESULT_AVAILABLE,
-      Source<TabContents>(this),
-      Details<FindNotificationDetails>(&last_search_result_));
-}
-
-void TabContents::GoToEntryAtOffset(int offset) {
+void TabContents::OnGoToEntryAtOffset(int offset) {
   if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) {
     NavigationEntry* entry = controller_.GetEntryAtOffset(offset);
     if (!entry)
@@ -2264,44 +2110,6 @@
   }
 }
 
-void TabContents::OnMissingPluginStatus(int status) {
-#if defined(OS_WIN)
-// TODO(PORT): pull in when plug-ins work
-  GetPluginInstaller()->OnMissingPluginStatus(status);
-#endif
-}
-
-void TabContents::OnCrashedPlugin(const FilePath& plugin_path) {
-  DCHECK(!plugin_path.value().empty());
-
-  std::wstring plugin_name = plugin_path.ToWStringHack();
-  webkit::npapi::WebPluginInfo plugin_info;
-  if (webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath(
-          plugin_path, &plugin_info) &&
-      !plugin_info.name.empty()) {
-    plugin_name = UTF16ToWide(plugin_info.name);
-#if defined(OS_MACOSX)
-    // Many plugins on the Mac have .plugin in the actual name, which looks
-    // terrible, so look for that and strip it off if present.
-    const std::wstring plugin_extension(L".plugin");
-    if (EndsWith(plugin_name, plugin_extension, true))
-      plugin_name.erase(plugin_name.length() - plugin_extension.length());
-#endif  // OS_MACOSX
-  }
-  SkBitmap* crash_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed(
-      IDR_INFOBAR_PLUGIN_CRASHED);
-  AddInfoBar(new SimpleAlertInfoBarDelegate(
-      this, l10n_util::GetStringFUTF16(IDS_PLUGIN_CRASHED_PROMPT,
-                                       WideToUTF16Hack(plugin_name)),
-      crash_icon, true));
-}
-
-void TabContents::OnCrashedWorker() {
-  AddInfoBar(new SimpleAlertInfoBarDelegate(
-      this, l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT),
-      NULL, true));
-}
-
 void TabContents::OnDidGetApplicationInfo(int32 page_id,
                                           const WebApplicationInfo& info) {
   web_app_info_ = info;
@@ -2315,13 +2123,7 @@
     delegate()->OnInstallApplication(this, info);
 }
 
-void TabContents::OnBlockedOutdatedPlugin(const string16& name,
-                                          const GURL& update_url) {
-  new OutdatedPluginInfoBar(this, name, update_url);
-}
-
 void TabContents::OnPageContents(const GURL& url,
-                                 int renderer_process_id,
                                  int32 page_id,
                                  const string16& contents,
                                  const std::string& language,
@@ -2352,6 +2154,12 @@
       NotificationType::TAB_LANGUAGE_DETERMINED,
       Source<TabContents>(this),
       Details<std::string>(&lang));
+
+  // Generate the thumbnail here if the in-browser thumbnailing is enabled.
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableInBrowserThumbnailing)) {
+    ThumbnailGenerator::UpdateThumbnailIfNecessary(this, url);
+  }
 }
 
 void TabContents::OnPageTranslated(int32 page_id,
@@ -2379,6 +2187,14 @@
     delegate()->OnInstantSupportDetermined(page_id, result);
 }
 
+void TabContents::OnRunFileChooser(
+    const ViewHostMsg_RunFileChooser_Params& params) {
+  if (file_select_helper_.get() == NULL)
+    file_select_helper_.reset(new FileSelectHelper(profile()));
+  file_select_helper_->RunFileChooser(render_view_host(), params);
+}
+
+
 void TabContents::OnContentSettingsAccessed(bool content_was_blocked) {
   if (delegate_)
     delegate_->OnContentSettingsChange(this);
@@ -2393,48 +2209,15 @@
   return &render_manager_;
 }
 
-RenderViewHostDelegate::BrowserIntegration*
-    TabContents::GetBrowserIntegrationDelegate() {
-  return this;
-}
-
 RenderViewHostDelegate::ContentSettings*
 TabContents::GetContentSettingsDelegate() {
   return content_settings_delegate_.get();
 }
 
-RenderViewHostDelegate::Save* TabContents::GetSaveDelegate() {
-  return save_package_.get();  // May be NULL, but we can return NULL.
-}
-
-RenderViewHostDelegate::Printing* TabContents::GetPrintingDelegate() {
-  return printing_.get();
-}
-
-RenderViewHostDelegate::FavIcon* TabContents::GetFavIconDelegate() {
-  return &fav_icon_helper_;
-}
-
-RenderViewHostDelegate::Autocomplete* TabContents::GetAutocompleteDelegate() {
-  if (autocomplete_history_manager_.get() == NULL)
-    autocomplete_history_manager_.reset(new AutocompleteHistoryManager(this));
-  return autocomplete_history_manager_.get();
-}
-
-RenderViewHostDelegate::AutoFill* TabContents::GetAutoFillDelegate() {
-  return GetAutoFillManager();
-}
-
 RenderViewHostDelegate::SSL* TabContents::GetSSLDelegate() {
   return GetSSLHelper();
 }
 
-RenderViewHostDelegate::FileSelect* TabContents::GetFileSelectDelegate() {
-  if (file_select_helper_.get() == NULL)
-    file_select_helper_.reset(new FileSelectHelper(profile()));
-  return file_select_helper_.get();
-}
-
 AutomationResourceRoutingDelegate*
 TabContents::GetAutomationResourceRoutingDelegate() {
   return delegate();
@@ -2479,9 +2262,9 @@
     return;
 
   // When we're creating views, we're still doing initial setup, so we always
-  // use the pending DOM UI rather than any possibly existing committed one.
-  if (render_manager_.pending_dom_ui()) {
-    render_manager_.pending_dom_ui()->RenderViewCreated(render_view_host);
+  // use the pending Web UI rather than any possibly existing committed one.
+  if (render_manager_.pending_web_ui()) {
+    render_manager_.pending_web_ui()->RenderViewCreated(render_view_host);
   }
 
   if (entry->IsViewSourceMode()) {
@@ -2528,15 +2311,15 @@
   SetIsCrashed(status, error_code);
 
   // Remove all infobars.
-  for (int i = infobar_delegate_count() - 1; i >=0 ; --i)
-    RemoveInfoBar(GetInfoBarDelegateAt(i));
+  while (!infobar_delegates_.empty())
+    RemoveInfoBar(GetInfoBarDelegateAt(infobar_count() - 1));
 
   // Tell the view that we've crashed so it can prepare the sad tab page.
   // Only do this if we're not in browser shutdown, so that TabContents
   // objects that are not in a browser (e.g., HTML dialogs) and thus are
   // visible do not flash a sad tab page.
   if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID)
-    view_->OnTabCrashed();
+    view_->OnTabCrashed(status, error_code);
 
   // Hide any visible hung renderer warning for this web contents' process.
   hung_renderer_dialog::HideForTabContents(this);
@@ -2555,14 +2338,8 @@
   int extra_invalidate_flags = 0;
 
   if (PageTransition::IsMainFrame(params.transition)) {
-    PrerenderManager* pm = profile()->GetPrerenderManager();
-    if (pm != NULL) {
-      if (pm->MaybeUsePreloadedPage(this, params.url)) {
-        // TODO(tburkard): If the preloaded page has not finished preloading
-        // yet, we should not do this.
-        DidStopLoading();
-        return;
-      }
+    if (MaybeUsePreloadedPage(params.url)) {
+      return;
     }
 
     bool was_bookmark_bar_visible = ShouldShowBookmarkBar();
@@ -2707,16 +2484,9 @@
     return;
 
   // Tell History about this thumbnail
-  if (history::TopSites::IsEnabled()) {
-    history::TopSites* ts = profile()->GetTopSites();
-    if (ts)
-      ts->SetPageThumbnail(url, bitmap, score);
-  } else {
-    HistoryService* hs =
-        profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
-    if (hs)
-      hs->SetPageThumbnail(url, bitmap, score);
-  }
+  history::TopSites* ts = profile()->GetTopSites();
+  if (ts)
+    ts->SetPageThumbnail(url, bitmap, score);
 }
 
 void TabContents::UpdateInspectorSetting(const std::string& key,
@@ -2775,8 +2545,7 @@
   }
 
   // Notify observers about navigation.
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
-                    DidStartLoading());
+  FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidStartLoading());
 }
 
 void TabContents::DidStopLoading() {
@@ -2799,8 +2568,7 @@
   SetIsLoading(false, details.get());
 
   // Notify observers about navigation.
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
-                    DidStopLoading());
+  FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidStopLoading());
 }
 
 void TabContents::DidChangeLoadProgress(double progress) {
@@ -2819,17 +2587,17 @@
 
 void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer,
                                  WindowOpenDisposition disposition) {
-  if (render_manager_.dom_ui()) {
-    // When we're a DOM UI, it will provide a page transition type for us (this
+  if (render_manager_.web_ui()) {
+    // When we're a Web UI, it will provide a page transition type for us (this
     // is so the new tab page can specify AUTO_BOOKMARK for automatically
     // generated suggestions).
     //
-    // Note also that we hide the referrer for DOM UI pages. We don't really
+    // Note also that we hide the referrer for Web UI pages. We don't really
     // want web sites to see a referrer of "chrome://blah" (and some
     // chrome: URLs might have search terms or other stuff we don't want to
     // send to the site), so we send no referrer.
     OpenURL(url, GURL(), disposition,
-            render_manager_.dom_ui()->link_transition_type());
+            render_manager_.web_ui()->link_transition_type());
   } else {
     OpenURL(url, referrer, disposition, PageTransition::LINK);
   }
@@ -2839,15 +2607,15 @@
                                        int automation_id) {
 }
 
-void TabContents::ProcessDOMUIMessage(
+void TabContents::ProcessWebUIMessage(
     const ViewHostMsg_DomMessage_Params& params) {
-  if (!render_manager_.dom_ui()) {
+  if (!render_manager_.web_ui()) {
     // This can happen if someone uses window.open() to open an extension URL
     // from a non-extension context.
     render_view_host()->BlockExtensionRequest(params.request_id);
     return;
   }
-  render_manager_.dom_ui()->ProcessDOMUIMessage(params);
+  render_manager_.web_ui()->ProcessWebUIMessage(params);
 }
 
 void TabContents::ProcessExternalHostMessage(const std::string& message,
@@ -2923,18 +2691,6 @@
   }
 }
 
-void TabContents::PasswordFormsFound(
-    const std::vector<webkit_glue::PasswordForm>& forms) {
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
-                    PasswordFormsFound(forms));
-}
-
-void TabContents::PasswordFormsVisible(
-    const std::vector<webkit_glue::PasswordForm>& visible_forms) {
-  FOR_EACH_OBSERVER(WebNavigationObserver, web_navigation_observers_,
-                    PasswordFormsVisible(visible_forms));
-}
-
 // Checks to see if we should generate a keyword based on the OSDD, and if
 // necessary uses TemplateURLFetcher to download the OSDD and create a keyword.
 void TabContents::PageHasOSDD(
@@ -2995,7 +2751,7 @@
   if (!keyword_url.is_valid())
     return;
 
-  std::wstring keyword = TemplateURLModel::GenerateKeyword(
+  string16 keyword = TemplateURLModel::GenerateKeyword(
       keyword_url,
       provider_type == TemplateURLFetcher::AUTODETECTED_PROVIDER);
 
@@ -3027,9 +2783,9 @@
 
 WebPreferences TabContents::GetWebkitPrefs() {
   Profile* profile = render_view_host()->process()->profile();
-  bool is_dom_ui = false;
+  bool is_web_ui = false;
   WebPreferences web_prefs =
-      RenderViewHostDelegateHelper::GetWebkitPrefs(profile, is_dom_ui);
+      RenderViewHostDelegateHelper::GetWebkitPrefs(profile, is_web_ui);
 
   // Force accelerated compositing and 2d canvas off for chrome: and
   // chrome-extension: pages.
@@ -3049,6 +2805,15 @@
   return web_prefs;
 }
 
+void TabContents::OnUserGesture() {
+  // See comment in RenderViewHostDelegate::OnUserGesture as to why we do this.
+  DownloadRequestLimiter* limiter =
+      g_browser_process->download_request_limiter();
+  if (limiter)
+    limiter->OnUserGesture(this);
+  ExternalProtocolHandler::PermitLaunchUrl();
+}
+
 void TabContents::OnIgnoredUIEvent() {
   if (constrained_window_count()) {
     ConstrainedWindow* window = *constrained_window_begin();
@@ -3057,9 +2822,8 @@
 }
 
 void TabContents::OnJSOutOfMemory() {
-  AddInfoBar(new SimpleAlertInfoBarDelegate(
-                 this, l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT),
-                 NULL, true));
+  AddInfoBar(new SimpleAlertInfoBarDelegate(this, NULL,
+      l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT), true));
 }
 
 void TabContents::OnCrossSiteResponse(int new_render_process_host_id,
@@ -3089,8 +2853,10 @@
     return;
   }
 
-  if (render_view_host() && render_view_host()->IsRenderViewLive())
+  if (render_view_host() && render_view_host()->IsRenderViewLive() &&
+      (!delegate() || delegate()->ShouldShowHungRendererDialog())) {
     hung_renderer_dialog::ShowForTabContents(this);
+  }
 }
 
 void TabContents::RendererResponsive(RenderViewHost* render_view_host) {
@@ -3129,7 +2895,7 @@
 void TabContents::FocusedNodeChanged(bool is_editable_node) {
   NotificationService::current()->Notify(
       NotificationType::FOCUS_CHANGED_IN_PAGE,
-      Source<RenderViewHost>(render_view_host()),
+      Source<TabContents>(this),
       Details<const bool>(&is_editable_node));
 }
 
@@ -3141,9 +2907,9 @@
   temporary_zoom_settings_ = !remember;
 }
 
-void TabContents::UpdateContentRestrictions(int restrictions) {
-  content_restrictions_ = restrictions;
-  delegate()->ContentRestrictionsChanged(this);
+void TabContents::WorkerCrashed() {
+  AddInfoBar(new SimpleAlertInfoBarDelegate(this, NULL,
+      l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT), true));
 }
 
 void TabContents::BeforeUnloadFiredFromRenderManager(
@@ -3183,8 +2949,8 @@
   return controller();
 }
 
-DOMUI* TabContents::CreateDOMUIForRenderManager(const GURL& url) {
-  return DOMUIFactory::CreateDOMUIForURL(this, url);
+WebUI* TabContents::CreateWebUIForRenderManager(const GURL& url) {
+  return WebUIFactory::CreateWebUIForURL(this, url);
 }
 
 NavigationEntry*
@@ -3211,18 +2977,6 @@
                           const NotificationSource& source,
                           const NotificationDetails& details) {
   switch (type.value) {
-    case NotificationType::BOOKMARK_MODEL_LOADED:
-      // BookmarkModel finished loading, fall through to update starred state.
-    case NotificationType::URLS_STARRED: {
-      // Somewhere, a URL has been starred.
-      // Ignore notifications for profiles other than our current one.
-      Profile* source_profile = Source<Profile>(source).ptr();
-      if (!source_profile || !source_profile->IsSameProfile(profile()))
-        return;
-
-      UpdateStarredStateForCurrentURL();
-      break;
-    }
     case NotificationType::PREF_CHANGED: {
       std::string* pref_name_in = Details<std::string>(details).ptr();
       DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs());
@@ -3377,3 +3131,12 @@
   RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh);
   rwh_view->SetSize(view()->GetContainerSize());
 }
+
+bool TabContents::MaybeUsePreloadedPage(const GURL& url) {
+  PrerenderManager* pm = profile()->GetPrerenderManager();
+  if (pm != NULL) {
+    if (pm->MaybeUsePreloadedPage(this, url))
+      return true;
+  }
+  return false;
+}
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 150d101..3a1b89a 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -49,7 +49,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
+#include "chrome/browser/dom_ui/web_ui_factory.h"
 #include "chrome/browser/download/save_package.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
 #include "chrome/browser/fav_icon_helper.h"
@@ -63,15 +63,13 @@
 #include "chrome/browser/tab_contents/render_view_host_manager.h"
 #include "chrome/browser/tab_contents/tab_specific_content_settings.h"
 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/property_bag.h"
 #include "chrome/common/renderer_preferences.h"
 #include "chrome/common/translate_errors.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/native_widget_types.h"
 #include "net/base/load_states.h"
+#include "ui/gfx/native_widget_types.h"
 
 #if defined(OS_WIN)
 #include "base/win/scoped_handle.h"
@@ -86,40 +84,40 @@
 }
 
 namespace printing {
+class PrintPreviewMessageHandler;
 class PrintViewManager;
 }
 
-namespace webkit_glue {
-struct PasswordForm;
-}
-
 class AutocompleteHistoryManager;
 class AutoFillManager;
 class BlockedContentContainer;
-class DOMUI;
+class WebUI;
+class DesktopNotificationHandler;
 class DownloadItem;
 class Extension;
 class FileSelectHelper;
 class InfoBarDelegate;
 class LoadNotificationDetails;
 class OmniboxSearchHint;
-class PluginInstaller;
+class PluginObserver;
 class Profile;
 class PrerenderManager;
-struct RendererPreferences;
+class PrerenderPLTRecorder;
 class RenderViewHost;
 class SessionStorageNamespace;
 class SiteInstance;
 class SkBitmap;
 class TabContents;
 class TabContentsDelegate;
+class TabContentsObserver;
 class TabContentsSSLHelper;
 class TabContentsView;
 class URLPattern;
+struct RendererPreferences;
 struct ThumbnailScore;
 struct ViewHostMsg_DomMessage_Params;
 struct ViewHostMsg_FrameNavigate_Params;
-class WebNavigationObserver;
+struct ViewHostMsg_RunFileChooser_Params;
 struct WebPreferences;
 
 // Describes what goes in the main content area of a tab. TabContents is
@@ -127,7 +125,6 @@
 class TabContents : public PageNavigator,
                     public NotificationObserver,
                     public RenderViewHostDelegate,
-                    public RenderViewHostDelegate::BrowserIntegration,
                     public RenderViewHostManager::Delegate,
                     public JavaScriptAppModalDialogDelegate,
                     public ImageLoadingTracker::Observer,
@@ -184,12 +181,6 @@
   // Returns true if contains content rendered by an extension.
   bool HostsExtension() const;
 
-  // Returns the AutoFillManager, creating it if necessary.
-  AutoFillManager* GetAutoFillManager();
-
-  // Returns the PluginInstaller, creating it if necessary.
-  PluginInstaller* GetPluginInstaller();
-
   // Returns the TabContentsSSLHelper, creating it if necessary.
   TabContentsSSLHelper* GetSSLHelper();
 
@@ -203,9 +194,9 @@
     return render_manager_.current_host();
   }
 
-  DOMUI* dom_ui() const {
-    return render_manager_.dom_ui() ? render_manager_.dom_ui()
-        : render_manager_.pending_dom_ui();
+  WebUI* web_ui() const {
+    return render_manager_.web_ui() ? render_manager_.web_ui()
+        : render_manager_.pending_web_ui();
   }
 
   // Returns the currently active RenderWidgetHostView. This may change over
@@ -246,7 +237,7 @@
   // If an app extension has been explicitly set for this TabContents its icon
   // is returned.
   //
-  // NOTE: the returned icon is larger than 16x16 (it's size is
+  // NOTE: the returned icon is larger than 16x16 (its size is
   // Extension::EXTENSION_ICON_SMALLISH).
   SkBitmap* GetExtensionAppIcon();
 
@@ -300,8 +291,8 @@
   // removing multiple times has no effect. The order in which notifications
   // are sent to observers is undefined. Clients must be sure to remove the
   // observer before they go away.
-  void AddNavigationObserver(WebNavigationObserver* observer);
-  void RemoveNavigationObserver(WebNavigationObserver* observer);
+  void AddObserver(TabContentsObserver* observer);
+  void RemoveObserver(TabContentsObserver* observer);
 
   // Return whether this tab contents is loading a resource.
   bool is_loading() const { return is_loading_; }
@@ -311,8 +302,6 @@
   // "waiting" or "loading."
   bool waiting_for_response() const { return waiting_for_response_; }
 
-  bool is_starred() const { return is_starred_; }
-
   const std::string& encoding() const { return encoding_; }
   void set_encoding(const std::string& encoding);
   void reset_encoding() {
@@ -526,9 +515,10 @@
                       InfoBarDelegate* new_delegate);
 
   // Enumeration and access functions.
-  int infobar_delegate_count() const { return infobar_delegates_.size(); }
-  InfoBarDelegate* GetInfoBarDelegateAt(int index) {
-    return infobar_delegates_.at(index);
+  size_t infobar_count() const { return infobar_delegates_.size(); }
+  // WARNING: This does not sanity-check |index|!
+  InfoBarDelegate* GetInfoBarDelegateAt(size_t index) {
+    return infobar_delegates_[index];
   }
 
   // Toolbars and such ---------------------------------------------------------
@@ -581,50 +571,6 @@
     return render_manager_.interstitial_page();
   }
 
-  // Find in Page --------------------------------------------------------------
-
-  // Starts the Find operation by calling StartFinding on the Tab. This function
-  // can be called from the outside as a result of hot-keys, so it uses the
-  // last remembered search string as specified with set_find_string(). This
-  // function does not block while a search is in progress. The controller will
-  // receive the results through the notification mechanism. See Observe(...)
-  // for details.
-  void StartFinding(string16 search_string,
-                    bool forward_direction,
-                    bool case_sensitive);
-
-  // Stops the current Find operation.
-  void StopFinding(FindBarController::SelectionAction selection_action);
-
-  // Accessors/Setters for find_ui_active_.
-  bool find_ui_active() const { return find_ui_active_; }
-  void set_find_ui_active(bool find_ui_active) {
-      find_ui_active_ = find_ui_active;
-  }
-
-  // Setter for find_op_aborted_.
-  void set_find_op_aborted(bool find_op_aborted) {
-    find_op_aborted_ = find_op_aborted;
-  }
-
-  // Used _only_ by testing to get or set the current request ID.
-  int current_find_request_id() { return current_find_request_id_; }
-  void set_current_find_request_id(int current_find_request_id) {
-    current_find_request_id_ = current_find_request_id;
-  }
-
-  // Accessor for find_text_. Used to determine if this TabContents has any
-  // active searches.
-  string16 find_text() const { return find_text_; }
-
-  // Accessor for the previous search we issued.
-  string16 previous_find_text() const { return previous_find_text_; }
-
-  // Accessor for find_result_.
-  const FindNotificationDetails& find_result() const {
-    return last_search_result_;
-  }
-
   // Misc state & callbacks ----------------------------------------------------
 
   // Set whether the contents should block javascript message boxes or not.
@@ -642,6 +588,9 @@
   bool SavePage(const FilePath& main_file, const FilePath& dir_path,
                 SavePackage::SavePackageType save_type);
 
+  // Sets save_package_, taking care to register and unregister the observers.
+  void SetSavePackage(SavePackage* save_package);
+
   // Tells the user's email client to open a compose window containing the
   // current page's URL.
   void EmailPageLocation();
@@ -698,8 +647,8 @@
     return &renderer_preferences_;
   }
 
-  void set_opener_dom_ui_type(DOMUITypeID opener_dom_ui_type) {
-    opener_dom_ui_type_ = opener_dom_ui_type;
+  void set_opener_web_ui_type(WebUITypeID opener_web_ui_type) {
+    opener_web_ui_type_ = opener_web_ui_type;
   }
 
   // We want to time how long it takes to create a new tab page.  This method
@@ -723,6 +672,10 @@
   // Returns true if underlying TabContentsView should accept drag-n-drop.
   bool ShouldAcceptDragAndDrop() const;
 
+  // A render view-originated drag has ended. Informs the render view host and
+  // tab contents delegate.
+  void SystemDragEnded();
+
   // Indicates if this tab was explicitly closed by the user (control-w, close
   // tab menu item...). This is false for actions that indirectly close the tab,
   // such as closing the window.  The setter is maintained by TabStripModel, and
@@ -786,6 +739,15 @@
 
   int content_restrictions() const { return content_restrictions_; }
 
+  AutocompleteHistoryManager* autocomplete_history_manager() {
+    return autocomplete_history_manager_.get();
+  }
+  AutoFillManager* autofill_manager() { return autofill_manager_.get(); }
+
+ protected:
+  // from RenderViewHostDelegate.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
  private:
   friend class NavigationController;
   // Used to access the child_windows_ (ConstrainedWindowList) for testing
@@ -795,6 +757,9 @@
   FRIEND_TEST_ALL_PREFIXES(TabContentsTest, NoJSMessageOnInterstitials);
   FRIEND_TEST_ALL_PREFIXES(TabContentsTest, UpdateTitle);
   FRIEND_TEST_ALL_PREFIXES(TabContentsTest, CrossSiteCantPreemptAfterUnload);
+  FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles);
+  FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewHostManagerTest, PageDoesBackAndReload);
 
   // Temporary until the view/contents separation is complete.
   friend class TabContentsView;
@@ -835,9 +800,29 @@
                                         const std::string& main_frame_origin,
                                         const std::string& security_info);
   void OnDidDisplayInsecureContent();
-  void OnDidRunInsecureContent(const std::string& security_origin);
+  void OnDidRunInsecureContent(const std::string& security_origin,
+                               const GURL& target_url);
   void OnDocumentLoadedInFrame(int64 frame_id);
   void OnDidFinishLoad(int64 frame_id);
+  void OnUpdateContentRestrictions(int restrictions);
+  void OnPDFHasUnsupportedFeature();
+
+  void OnGoToEntryAtOffset(int offset);
+  void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info);
+  void OnInstallApplication(const WebApplicationInfo& info);
+  void OnPageContents(const GURL& url,
+                      int32 page_id,
+                      const string16& contents,
+                      const std::string& language,
+                      bool page_translatable);
+  void OnPageTranslated(int32 page_id,
+                        const std::string& original_lang,
+                        const std::string& translated_lang,
+                        TranslateErrors::Type error_type);
+  void OnSetSuggestions(int32 page_id,
+                        const std::vector<std::string>& suggestions);
+  void OnInstantSupportDetermined(int32 page_id, bool result);
+  void OnRunFileChooser(const ViewHostMsg_RunFileChooser_Params& params);
 
   // Changes the IsLoading state and notifies delegate as needed
   // |details| is used to provide details on the load that just finished
@@ -862,9 +847,9 @@
   void ExpireInfoBars(
       const NavigationController::LoadCommittedDetails& details);
 
-  // Returns the DOMUI for the current state of the tab. This will either be
-  // the pending DOMUI, the committed DOMUI, or NULL.
-  DOMUI* GetDOMUIForCurrentState();
+  // Returns the WebUI for the current state of the tab. This will either be
+  // the pending WebUI, the committed WebUI, or NULL.
+  WebUI* GetWebUIForCurrentState();
 
   // Navigation helpers --------------------------------------------------------
   //
@@ -885,10 +870,6 @@
   // Closes all constrained windows.
   void CloseConstrainedWindows();
 
-  // Updates the starred state from the bookmark bar model. If the state has
-  // changed, the delegate is notified.
-  void UpdateStarredStateForCurrentURL();
-
   // Send the alternate error page URL to the renderer. This method is virtual
   // so special html pages can override this (e.g., the new tab page).
   virtual void UpdateAlternateErrorPageURL();
@@ -944,54 +925,15 @@
 
   // RenderViewHostDelegate ----------------------------------------------------
 
-  // RenderViewHostDelegate::BrowserIntegration implementation.
-  virtual void OnUserGesture();
-  virtual void OnFindReply(int request_id,
-                           int number_of_matches,
-                           const gfx::Rect& selection_rect,
-                           int active_match_ordinal,
-                           bool final_update);
-  virtual void GoToEntryAtOffset(int offset);
-  virtual void OnMissingPluginStatus(int status);
-  virtual void OnCrashedPlugin(const FilePath& plugin_path);
-  virtual void OnCrashedWorker();
-  virtual void OnDidGetApplicationInfo(int32 page_id,
-                                       const WebApplicationInfo& info);
-  virtual void OnInstallApplication(const WebApplicationInfo& info);
-  virtual void OnBlockedOutdatedPlugin(const string16& name,
-                                       const GURL& update_url);
-  virtual void OnPageContents(const GURL& url,
-                              int renderer_process_id,
-                              int32 page_id,
-                              const string16& contents,
-                              const std::string& language,
-                              bool page_translatable);
-  virtual void OnPageTranslated(int32 page_id,
-                                const std::string& original_lang,
-                                const std::string& translated_lang,
-                                TranslateErrors::Type error_type);
-  virtual void OnSetSuggestions(int32 page_id,
-                                const std::vector<std::string>& suggestions);
-  virtual void OnInstantSupportDetermined(int32 page_id, bool result);
-
   // RenderViewHostDelegate implementation.
   virtual RenderViewHostDelegate::View* GetViewDelegate();
   virtual RenderViewHostDelegate::RendererManagement*
       GetRendererManagementDelegate();
-  virtual RenderViewHostDelegate::BrowserIntegration*
-      GetBrowserIntegrationDelegate();
   virtual RenderViewHostDelegate::ContentSettings* GetContentSettingsDelegate();
-  virtual RenderViewHostDelegate::Save* GetSaveDelegate();
-  virtual RenderViewHostDelegate::Printing* GetPrintingDelegate();
-  virtual RenderViewHostDelegate::FavIcon* GetFavIconDelegate();
-  virtual RenderViewHostDelegate::Autocomplete* GetAutocompleteDelegate();
-  virtual RenderViewHostDelegate::AutoFill* GetAutoFillDelegate();
   virtual RenderViewHostDelegate::SSL* GetSSLDelegate();
-  virtual RenderViewHostDelegate::FileSelect* GetFileSelectDelegate();
   virtual AutomationResourceRoutingDelegate*
       GetAutomationResourceRoutingDelegate();
   virtual TabContents* GetAsTabContents();
-  virtual bool OnMessageReceived(const IPC::Message& message);
   virtual ViewType::Type GetRenderViewType() const;
   virtual int GetBrowserWindowID() const;
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
@@ -1029,7 +971,7 @@
                               WindowOpenDisposition disposition);
   virtual void DomOperationResponse(const std::string& json_string,
                                     int automation_id);
-  virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params);
+  virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params);
   virtual void ProcessExternalHostMessage(const std::string& message,
                                           const std::string& origin,
                                           const std::string& target);
@@ -1044,10 +986,6 @@
   virtual void ShowModalHTMLDialog(const GURL& url, int width, int height,
                                    const std::string& json_arguments,
                                    IPC::Message* reply_msg);
-  virtual void PasswordFormsFound(
-      const std::vector<webkit_glue::PasswordForm>& forms);
-  virtual void PasswordFormsVisible(
-      const std::vector<webkit_glue::PasswordForm>& visible_forms);
   virtual void PageHasOSDD(RenderViewHost* render_view_host,
                            int32 page_id,
                            const GURL& url,
@@ -1055,6 +993,7 @@
   virtual GURL GetAlternateErrorPageURL() const;
   virtual RendererPreferences GetRendererPrefs(Profile* profile) const;
   virtual WebPreferences GetWebkitPrefs();
+  virtual void OnUserGesture();
   virtual void OnIgnoredUIEvent();
   virtual void OnJSOutOfMemory();
   virtual void OnCrossSiteResponse(int new_render_process_host_id,
@@ -1070,7 +1009,7 @@
   virtual void UpdateZoomLimits(int minimum_percent,
                                 int maximum_percent,
                                 bool remember);
-  virtual void UpdateContentRestrictions(int restrictions);
+  virtual void WorkerCrashed();
 
   // RenderViewHostManager::Delegate -------------------------------------------
 
@@ -1087,7 +1026,7 @@
   virtual void UpdateRenderViewSizeForRenderManager();
   virtual void NotifySwappedFromRenderManager();
   virtual NavigationController& GetControllerForRenderManager();
-  virtual DOMUI* CreateDOMUIForRenderManager(const GURL& url);
+  virtual WebUI* CreateWebUIForRenderManager(const GURL& url);
   virtual NavigationEntry* GetLastCommittedNavigationEntryForRenderManager();
 
   // Initializes the given renderer if necessary and creates the view ID
@@ -1120,6 +1059,11 @@
   virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
                              int index);
 
+  // Checks with the PrerenderManager if the specified URL has been preloaded,
+  // and if so, swap the RenderViewHost with the preload into this TabContents
+  // object.
+  bool MaybeUsePreloadedPage(const GURL& url);
+
   // Data for core operation ---------------------------------------------------
 
   // Delegate for notifying our owner about stuff. Not owned by us.
@@ -1145,20 +1089,26 @@
   // Registers and unregisters for pref notifications.
   PrefChangeRegistrar pref_change_registrar_;
 
-  // Handles print preview and print job for this contents.
+  // Handles print job for this contents.
   scoped_ptr<printing::PrintViewManager> printing_;
 
+  // Handles print preview for this contents.
+  scoped_ptr<printing::PrintPreviewMessageHandler> print_preview_;
+
   // SavePackage, lazily created.
   scoped_refptr<SavePackage> save_package_;
 
-  // AutocompleteHistoryManager, lazily created.
+  // AutocompleteHistoryManager.
   scoped_ptr<AutocompleteHistoryManager> autocomplete_history_manager_;
 
-  // AutoFillManager, lazily created.
+  // AutoFillManager.
   scoped_ptr<AutoFillManager> autofill_manager_;
 
-  // PluginInstaller, lazily created.
-  scoped_ptr<PluginInstaller> plugin_installer_;
+  // Handles plugin messages.
+  scoped_ptr<PluginObserver> plugin_observer_;
+
+  // Prerender PageLoadTime Recorder.
+  scoped_ptr<PrerenderPLTRecorder> prerender_plt_recorder_;
 
   // TabContentsSSLHelper, lazily created.
   scoped_ptr<TabContentsSSLHelper> ssl_helper_;
@@ -1181,6 +1131,10 @@
   // RenderViewHost::ContentSettingsDelegate.
   scoped_ptr<TabSpecificContentSettings> content_settings_delegate_;
 
+  // Handles desktop notification IPCs.
+  scoped_ptr<DesktopNotificationHandler> desktop_notification_handler_;
+
+
   // Data for loading state ----------------------------------------------------
 
   // Indicates whether we're currently loading a resource.
@@ -1218,9 +1172,6 @@
   // messages.
   bool received_page_title_;
 
-  // Whether the current URL is starred
-  bool is_starred_;
-
   // When a navigation occurs, we record its contents MIME type. It can be
   // used to check whether we can do something for some special contents.
   std::string contents_mime_type_;
@@ -1245,45 +1196,6 @@
   // Delegates for InfoBars associated with this TabContents.
   std::vector<InfoBarDelegate*> infobar_delegates_;
 
-  // Data for find in page -----------------------------------------------------
-
-  // TODO(brettw) this should be separated into a helper class.
-
-  // Each time a search request comes in we assign it an id before passing it
-  // over the IPC so that when the results come in we can evaluate whether we
-  // still care about the results of the search (in some cases we don't because
-  // the user has issued a new search).
-  static int find_request_id_counter_;
-
-  // True if the Find UI is active for this Tab.
-  bool find_ui_active_;
-
-  // True if a Find operation was aborted. This can happen if the Find box is
-  // closed or if the search term inside the Find box is erased while a search
-  // is in progress. This can also be set if a page has been reloaded, and will
-  // on FindNext result in a full Find operation so that the highlighting for
-  // inactive matches can be repainted.
-  bool find_op_aborted_;
-
-  // This variable keeps track of what the most recent request id is.
-  int current_find_request_id_;
-
-  // The current string we are/just finished searching for. This is used to
-  // figure out if this is a Find or a FindNext operation (FindNext should not
-  // increase the request id).
-  string16 find_text_;
-
-  // The string we searched for before |find_text_|.
-  string16 previous_find_text_;
-
-  // Whether the last search was case sensitive or not.
-  bool last_search_case_sensitive_;
-
-  // The last find result. This object contains details about the number of
-  // matches, the find selection rectangle, etc. The UI can access this
-  // information to build its presentation.
-  FindNotificationDetails last_search_result_;
-
   // Data for app extensions ---------------------------------------------------
 
   // If non-null this tab is an app tab and this is the extension the tab was
@@ -1341,8 +1253,8 @@
   RendererPreferences renderer_preferences_;
 
   // If this tab was created from a renderer using window.open, this will be
-  // non-NULL and represent the DOMUI of the opening renderer.
-  DOMUITypeID opener_dom_ui_type_;
+  // non-NULL and represent the WebUI of the opening renderer.
+  WebUITypeID opener_web_ui_type_;
 
   // The time that we started to create the new tab page.
   base::TimeTicks new_tab_start_time_;
@@ -1368,14 +1280,12 @@
   bool temporary_zoom_settings_;
 
   // A list of observers notified when page state changes. Weak references.
-  ObserverList<WebNavigationObserver> web_navigation_observers_;
+  ObserverList<TabContentsObserver> observers_;
 
   // Content restrictions, used to disable print/copy etc based on content's
   // (full-page plugins for now only) permissions.
   int content_restrictions_;
 
-  // ---------------------------------------------------------------------------
-
   DISALLOW_COPY_AND_ASSIGN(TabContents);
 };
 
diff --git a/chrome/browser/tab_contents/tab_contents_delegate.cc b/chrome/browser/tab_contents/tab_contents_delegate.cc
index 987e620..7f3a1a0 100644
--- a/chrome/browser/tab_contents/tab_contents_delegate.cc
+++ b/chrome/browser/tab_contents/tab_contents_delegate.cc
@@ -6,7 +6,7 @@
 
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 std::string TabContentsDelegate::GetNavigationHeaders(const GURL& url) {
   return std::string();
@@ -165,6 +165,9 @@
 void TabContentsDelegate::HandleMouseActivate() {
 }
 
+void TabContentsDelegate::DragEnded() {
+}
+
 void TabContentsDelegate::ShowRepostFormWarningDialog(
     TabContents* tab_contents) {
 }
@@ -227,5 +230,9 @@
 void TabContentsDelegate::ContentRestrictionsChanged(TabContents* source) {
 }
 
+bool TabContentsDelegate::ShouldShowHungRendererDialog() {
+  return true;
+}
+
 TabContentsDelegate::~TabContentsDelegate() {
 }
diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h
index 9b52e32..05fe138 100644
--- a/chrome/browser/tab_contents/tab_contents_delegate.h
+++ b/chrome/browser/tab_contents/tab_contents_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,7 +15,7 @@
 #include "chrome/common/content_settings_types.h"
 #include "chrome/common/navigation_types.h"
 #include "chrome/common/page_transition_types.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/window_open_disposition.h"
 
 namespace gfx {
@@ -125,9 +125,6 @@
   // part of an animation.
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) = 0;
 
-  // Notification that the starredness of the current URL changed.
-  virtual void URLStarredChanged(TabContents* source, bool starred) = 0;
-
   // Notification that the target URL has changed.
   virtual void UpdateTargetURL(TabContents* source, const GURL& url) = 0;
 
@@ -274,6 +271,9 @@
   virtual void HandleMouseUp();
   virtual void HandleMouseActivate();
 
+  // Render view drag n drop ended.
+  virtual void DragEnded();
+
   // Shows the repost form confirmation dialog box.
   virtual void ShowRepostFormWarningDialog(TabContents* tab_contents);
 
@@ -332,6 +332,9 @@
   // changed.
   virtual void ContentRestrictionsChanged(TabContents* source);
 
+  // Returns true if the hung renderer dialog should be shown. Default is true.
+  virtual bool ShouldShowHungRendererDialog();
+
  protected:
   virtual ~TabContentsDelegate();
 };
diff --git a/chrome/browser/tab_contents/tab_contents_observer.cc b/chrome/browser/tab_contents/tab_contents_observer.cc
new file mode 100644
index 0000000..5ad1e1d
--- /dev/null
+++ b/chrome/browser/tab_contents/tab_contents_observer.cc
@@ -0,0 +1,9 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/tab_contents/tab_contents_observer.h"
+
+bool TabContentsObserver::OnMessageReceived(const IPC::Message& message) {
+  return false;
+}
diff --git a/chrome/browser/tab_contents/tab_contents_observer.h b/chrome/browser/tab_contents/tab_contents_observer.h
new file mode 100644
index 0000000..7e56ed9
--- /dev/null
+++ b/chrome/browser/tab_contents/tab_contents_observer.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_OBSERVER_H_
+#define CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_OBSERVER_H_
+
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "ipc/ipc_channel.h"
+
+struct ViewHostMsg_FrameNavigate_Params;
+
+// An observer API implemented by classes which are interested in various page
+// load events from TabContents.  They also get a chance to filter IPC messages.
+class TabContentsObserver : public IPC::Channel::Listener {
+ public:
+  virtual void NavigateToPendingEntry() { }
+
+  virtual void DidNavigateMainFramePostCommit(
+      const NavigationController::LoadCommittedDetails& details,
+      const ViewHostMsg_FrameNavigate_Params& params) { }
+  virtual void DidNavigateAnyFramePostCommit(
+      const NavigationController::LoadCommittedDetails& details,
+      const ViewHostMsg_FrameNavigate_Params& params) { }
+
+  virtual void DidStartLoading() { }
+  virtual void DidStopLoading() { }
+
+  // IPC::Channel::Listener implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+#if 0
+  // For unifying with delegate...
+
+  // Notifies the delegate that this contents is starting or is done loading
+  // some resource. The delegate should use this notification to represent
+  // loading feedback. See TabContents::is_loading()
+  virtual void LoadingStateChanged(TabContents* contents) { }
+  // Called to inform the delegate that the tab content's navigation state
+  // changed. The |changed_flags| indicates the parts of the navigation state
+  // that have been updated, and is any combination of the
+  // |TabContents::InvalidateTypes| bits.
+  virtual void NavigationStateChanged(const TabContents* source,
+                                      unsigned changed_flags) { }
+#endif
+};
+
+#endif  // CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_OBSERVER_H_
diff --git a/chrome/browser/tab_contents/tab_contents_ssl_helper.cc b/chrome/browser/tab_contents/tab_contents_ssl_helper.cc
index 020886c..98d0ec4 100644
--- a/chrome/browser/tab_contents/tab_contents_ssl_helper.cc
+++ b/chrome/browser/tab_contents/tab_contents_ssl_helper.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/tab_contents/tab_contents_ssl_helper.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/basictypes.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -20,6 +18,8 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/net_errors.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -29,134 +29,147 @@
       IDR_INFOBAR_SAVE_PASSWORD);
 }
 
+
+// SSLCertAddedInfoBarDelegate ------------------------------------------------
+
 class SSLCertAddedInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   SSLCertAddedInfoBarDelegate(TabContents* tab_contents,
-                              net::X509Certificate* cert)
-      : ConfirmInfoBarDelegate(tab_contents),
-        tab_contents_(tab_contents),
-        cert_(cert) {
-  }
-
-  virtual ~SSLCertAddedInfoBarDelegate() {
-  }
-
-  // Overridden from ConfirmInfoBarDelegate:
-  virtual string16 GetMessageText() const {
-    // TODO(evanm): GetDisplayName should return UTF-16.
-    return l10n_util::GetStringFUTF16(
-        IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL,
-        UTF8ToUTF16(cert_->issuer().GetDisplayName()));
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return GetCertIcon();
-  }
-
-  virtual int GetButtons() const {
-    return BUTTON_OK;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    switch (button) {
-      case BUTTON_OK:
-        return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON);
-      default:
-        return string16();
-    }
-  }
-
-  virtual Type GetInfoBarType() {
-    return PAGE_ACTION_TYPE;
-  }
-
-  virtual bool Accept() {
-    ShowCertificateViewer(tab_contents_->GetMessageBoxRootWindow(), cert_);
-    return false;  // Hiding the infobar just as the dialog opens looks weird.
-  }
-
-  virtual void InfoBarClosed() {
-    // ConfirmInfoBarDelegate doesn't delete itself.
-    delete this;
-  }
+                              net::X509Certificate* cert);
 
  private:
-  // The TabContents we are attached to
-  TabContents* tab_contents_;
-  // The cert we added.
-  scoped_refptr<net::X509Certificate> cert_;
+  virtual ~SSLCertAddedInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+
+  TabContents* tab_contents_;  // The TabContents we are attached to.
+  scoped_refptr<net::X509Certificate> cert_;  // The cert we added.
 };
 
+SSLCertAddedInfoBarDelegate::SSLCertAddedInfoBarDelegate(
+    TabContents* tab_contents,
+    net::X509Certificate* cert)
+    : ConfirmInfoBarDelegate(tab_contents),
+      tab_contents_(tab_contents),
+      cert_(cert) {
+}
+
+SSLCertAddedInfoBarDelegate::~SSLCertAddedInfoBarDelegate() {
+}
+
+void SSLCertAddedInfoBarDelegate::InfoBarClosed() {
+  // ConfirmInfoBarDelegate doesn't delete itself.
+  delete this;
+}
+
+SkBitmap* SSLCertAddedInfoBarDelegate::GetIcon() const {
+  return GetCertIcon();
+}
+
+InfoBarDelegate::Type SSLCertAddedInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+string16 SSLCertAddedInfoBarDelegate::GetMessageText() const {
+  // TODO(evanm): GetDisplayName should return UTF-16.
+  return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL,
+      UTF8ToUTF16(cert_->issuer().GetDisplayName()));
+}
+
+int SSLCertAddedInfoBarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
+
+string16 SSLCertAddedInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON);
+}
+
+bool SSLCertAddedInfoBarDelegate::Accept() {
+  ShowCertificateViewer(tab_contents_->GetMessageBoxRootWindow(), cert_);
+  return false;  // Hiding the infobar just as the dialog opens looks weird.
+}
+
 }  // namespace
 
+
+// TabContentsSSLHelper::SSLAddCertData ---------------------------------------
+
 class TabContentsSSLHelper::SSLAddCertData : public NotificationObserver {
  public:
-  SSLAddCertData(TabContents* tab, SSLAddCertHandler* handler)
-      : tab_(tab),
-        handler_(handler),
-        infobar_delegate_(NULL) {
-    // Listen for disappearing InfoBars.
-    Source<TabContents> tc_source(tab_);
-    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
-                   tc_source);
-    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED,
-                   tc_source);
-  }
-  ~SSLAddCertData() {}
+  explicit SSLAddCertData(TabContents* tab_contents);
+  virtual ~SSLAddCertData();
 
   // Displays |delegate| as an infobar in |tab_|, replacing our current one if
   // still active.
-  void ShowInfoBar(InfoBarDelegate* delegate) {
-    if (infobar_delegate_) {
-      tab_->ReplaceInfoBar(infobar_delegate_, delegate);
-    } else {
-      tab_->AddInfoBar(delegate);
-    }
-    infobar_delegate_ = delegate;
-  }
+  void ShowInfoBar(InfoBarDelegate* delegate);
 
-  void ShowErrorInfoBar(const string16& message) {
-    ShowInfoBar(
-        new SimpleAlertInfoBarDelegate(tab_, message, GetCertIcon(), true));
-  }
-
-  // NotificationObserver implementation.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    switch (type.value) {
-      case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
-        InfoBarClosed(Details<InfoBarDelegate>(details).ptr());
-        break;
-      case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED:
-        typedef std::pair<InfoBarDelegate*, InfoBarDelegate*>
-            InfoBarDelegatePair;
-        InfoBarClosed(Details<InfoBarDelegatePair>(details).ptr()->first);
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
-  }
+  // Same as above, for the common case of wanting to show a simple alert
+  // message.
+  void ShowErrorInfoBar(const string16& message);
 
  private:
-  void InfoBarClosed(InfoBarDelegate* delegate) {
-    if (infobar_delegate_ == delegate)
-      infobar_delegate_ = NULL;
-  }
+  // NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
 
-  // The TabContents we are attached to.
-  TabContents* tab_;
-  // The handler we call back to.
-  scoped_refptr<SSLAddCertHandler> handler_;
-  // The current InfoBarDelegate we're displaying.
+  TabContents* tab_contents_;
   InfoBarDelegate* infobar_delegate_;
-
   NotificationRegistrar registrar_;
 
   DISALLOW_COPY_AND_ASSIGN(SSLAddCertData);
 };
 
+TabContentsSSLHelper::SSLAddCertData::SSLAddCertData(TabContents* tab_contents)
+    : tab_contents_(tab_contents),
+      infobar_delegate_(NULL) {
+  Source<TabContents> source(tab_contents_);
+  registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source);
+  registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, source);
+}
+
+TabContentsSSLHelper::SSLAddCertData::~SSLAddCertData() {
+}
+
+void TabContentsSSLHelper::SSLAddCertData::ShowInfoBar(
+    InfoBarDelegate* delegate) {
+  if (infobar_delegate_)
+    tab_contents_->ReplaceInfoBar(infobar_delegate_, delegate);
+  else
+    tab_contents_->AddInfoBar(delegate);
+  infobar_delegate_ = delegate;
+}
+
+void TabContentsSSLHelper::SSLAddCertData::ShowErrorInfoBar(
+    const string16& message) {
+  ShowInfoBar(new SimpleAlertInfoBarDelegate(tab_contents_, GetCertIcon(),
+                                             message, true));
+}
+
+void TabContentsSSLHelper::SSLAddCertData::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  typedef std::pair<InfoBarDelegate*, InfoBarDelegate*> InfoBarDelegatePair;
+  if (infobar_delegate_ ==
+      ((type.value == NotificationType::TAB_CONTENTS_INFOBAR_REMOVED) ?
+          Details<InfoBarDelegate>(details).ptr() :
+          Details<InfoBarDelegatePair>(details).ptr()->first))
+    infobar_delegate_ = NULL;
+}
+
+
+// TabContentsSSLHelper -------------------------------------------------------
+
 TabContentsSSLHelper::TabContentsSSLHelper(TabContents* tab_contents)
     : tab_contents_(tab_contents) {
 }
@@ -218,6 +231,6 @@
       request_id_to_add_cert_data_[handler->network_request_id()];
   // Fill it if necessary.
   if (!ptr_ref.get())
-    ptr_ref.reset(new SSLAddCertData(tab_contents_, handler));
+    ptr_ref.reset(new SSLAddCertData(tab_contents_));
   return ptr_ref.get();
 }
diff --git a/chrome/browser/tab_contents/tab_contents_ssl_helper.h b/chrome/browser/tab_contents/tab_contents_ssl_helper.h
index 9233561..2269c87 100644
--- a/chrome/browser/tab_contents/tab_contents_ssl_helper.h
+++ b/chrome/browser/tab_contents/tab_contents_ssl_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,7 @@
 #include "base/linked_ptr.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 
+class SSLAddCertHandler;
 class SSLClientAuthHandler;
 class TabContents;
 
@@ -39,7 +40,7 @@
   class SSLAddCertData;
   std::map<int, linked_ptr<SSLAddCertData> > request_id_to_add_cert_data_;
 
-  SSLAddCertData* GetAddCertData(SSLAddCertHandler *handler);
+  SSLAddCertData* GetAddCertData(SSLAddCertHandler* handler);
 
   DISALLOW_COPY_AND_ASSIGN(TabContentsSSLHelper);
 };
diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc
index 47e71f2..9574a56 100644
--- a/chrome/browser/tab_contents/tab_contents_view.cc
+++ b/chrome/browser/tab_contents/tab_contents_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,6 +11,8 @@
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/render_messages_params.h"
 
 TabContentsView::TabContentsView(TabContents* tab_contents)
     : tab_contents_(tab_contents) {
@@ -30,20 +32,26 @@
 
 void TabContentsView::CreateNewWindow(
     int route_id,
-    WindowContainerType window_container_type,
-    const string16& frame_name) {
+    const ViewHostMsg_CreateWindow_Params& params) {
   TabContents* new_contents = delegate_view_helper_.CreateNewWindow(
       route_id,
       tab_contents_->profile(),
       tab_contents_->GetSiteInstance(),
-      DOMUIFactory::GetDOMUIType(tab_contents_->profile(),
+      WebUIFactory::GetWebUIType(tab_contents_->profile(),
           tab_contents_->GetURL()),
       tab_contents_,
-      window_container_type,
-      frame_name);
+      params.window_container_type,
+      params.frame_name);
 
-  if (new_contents && tab_contents_->delegate())
-    tab_contents_->delegate()->TabContentsCreated(new_contents);
+  if (new_contents) {
+    NotificationService::current()->Notify(
+        NotificationType::CREATING_NEW_WINDOW,
+        Source<TabContents>(tab_contents_),
+        Details<const ViewHostMsg_CreateWindow_Params>(&params));
+
+    if (tab_contents_->delegate())
+      tab_contents_->delegate()->TabContentsCreated(new_contents);
+  }
 }
 
 void TabContentsView::CreateNewWidget(int route_id,
@@ -51,9 +59,8 @@
   CreateNewWidgetInternal(route_id, popup_type);
 }
 
-void TabContentsView::CreateNewFullscreenWidget(
-    int route_id, WebKit::WebPopupType popup_type) {
-  CreateNewFullscreenWidgetInternal(route_id, popup_type);
+void TabContentsView::CreateNewFullscreenWidget(int route_id) {
+  CreateNewFullscreenWidgetInternal(route_id);
 }
 
 void TabContentsView::ShowCreatedWindow(int route_id,
@@ -137,9 +144,9 @@
 }
 
 RenderWidgetHostView* TabContentsView::CreateNewFullscreenWidgetInternal(
-    int route_id, WebKit::WebPopupType popup_type) {
+    int route_id) {
   return delegate_view_helper_.CreateNewFullscreenWidget(
-      route_id, popup_type, tab_contents()->render_view_host()->process());
+      route_id, tab_contents()->render_view_host()->process());
 }
 
 void TabContentsView::ShowCreatedWidgetInternal(
@@ -157,6 +164,6 @@
   if (tab_contents_->delegate())
     tab_contents_->delegate()->RenderWidgetShowing();
 
-  widget_host_view->InitAsFullscreen(tab_contents_->GetRenderWidgetHostView());
+  widget_host_view->InitAsFullscreen();
   widget_host_view->GetRenderWidgetHost()->Init();
 }
diff --git a/chrome/browser/tab_contents/tab_contents_view.h b/chrome/browser/tab_contents/tab_contents_view.h
index c6b9a61..a25b13f 100644
--- a/chrome/browser/tab_contents/tab_contents_view.h
+++ b/chrome/browser/tab_contents/tab_contents_view.h
@@ -12,9 +12,9 @@
 #include "base/basictypes.h"
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 class RenderViewHost;
 class RenderWidgetHost;
@@ -80,7 +80,8 @@
 
   // Used to notify the view that a tab has crashed so each platform can
   // prepare the sad tab.
-  virtual void OnTabCrashed() = 0;
+  virtual void OnTabCrashed(base::TerminationStatus status,
+                            int error_code) = 0;
 
   // TODO(brettw) this is a hack. It's used in two places at the time of this
   // writing: (1) when render view hosts switch, we need to size the replaced
@@ -153,6 +154,9 @@
   virtual bool IsEventTracking() const;
   virtual void CloseTabAfterEventTracking() {}
 
+  // Get the bounds of the View, relative to the parent.
+  virtual void GetViewBounds(gfx::Rect* out) const = 0;
+
  protected:
   TabContentsView();  // Abstract interface.
 
@@ -172,9 +176,7 @@
                                          const gfx::Rect& initial_pos);
   virtual void ShowCreatedFullscreenWidgetInternal(
       RenderWidgetHostView* widget_host_view);
-  virtual RenderWidgetHostView* CreateNewFullscreenWidgetInternal(
-      int route_id,
-      WebKit::WebPopupType popup_type);
+  virtual RenderWidgetHostView* CreateNewFullscreenWidgetInternal(int route_id);
 
   // Common implementations of some RenderViewHostDelegate::View methods.
   RenderViewHostDelegateViewHelper delegate_view_helper_;
@@ -185,11 +187,9 @@
   // forwarded to *Internal which does platform-specific work.
   virtual void CreateNewWindow(
       int route_id,
-      WindowContainerType window_container_type,
-      const string16& frame_name);
+      const ViewHostMsg_CreateWindow_Params& params);
   virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
-  virtual void CreateNewFullscreenWidget(
-      int route_id, WebKit::WebPopupType popup_type);
+  virtual void CreateNewFullscreenWidget(int route_id);
   virtual void ShowCreatedWindow(int route_id,
                                  WindowOpenDisposition disposition,
                                  const gfx::Rect& initial_pos,
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
index dbd2797..1449e58 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,14 +14,6 @@
 #include "base/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/download/download_shelf.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/gtk_expanded_container.h"
-#include "chrome/browser/gtk/gtk_floating_container.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/gtk/sad_tab_gtk.h"
-#include "chrome/browser/gtk/tab_contents_drag_source.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_view_host_factory.h"
 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
@@ -30,11 +22,19 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/web_drag_dest_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_expanded_container.h"
+#include "chrome/browser/ui/gtk/gtk_floating_container.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/sad_tab_gtk.h"
+#include "chrome/browser/ui/gtk/tab_contents_drag_source.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "webkit/glue/webdropdata.h"
 
 using WebKit::WebDragOperation;
@@ -203,9 +203,13 @@
     gdk_window_set_title(content_view->window, WideToUTF8(title).c_str());
 }
 
-void TabContentsViewGtk::OnTabCrashed() {
+void TabContentsViewGtk::OnTabCrashed(base::TerminationStatus status,
+                                      int error_code) {
   if (tab_contents() != NULL && !sad_tab_.get()) {
-    sad_tab_.reset(new SadTabGtk(tab_contents()));
+    sad_tab_.reset(new SadTabGtk(
+        tab_contents(),
+        status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
+        SadTabGtk::KILLED : SadTabGtk::CRASHED));
     InsertIntoContentArea(sad_tab_->widget());
     gtk_widget_show(sad_tab_->widget());
   }
@@ -249,6 +253,16 @@
     SetInitialFocus();
 }
 
+void TabContentsViewGtk::GetViewBounds(gfx::Rect* out) const {
+  if (!floating_->window) {
+    out->SetRect(0, 0, requested_size_.width(), requested_size_.height());
+    return;
+  }
+  int x = 0, y = 0, w, h;
+  gdk_window_get_geometry(floating_->window, &x, &y, &w, &h, NULL);
+  out->SetRect(x, y, w, h);
+}
+
 void TabContentsViewGtk::SetFocusedWidget(GtkWidget* widget) {
   focus_store_.SetWidget(widget);
 }
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h
index 9a016a1..a11a307 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.h
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,13 +10,13 @@
 
 #include <vector>
 
-#include "app/gtk_signal.h"
 #include "base/scoped_ptr.h"
-#include "chrome/browser/gtk/focus_store_gtk.h"
-#include "chrome/browser/gtk/owned_widget_gtk.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/ui/gtk/focus_store_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
 
 class ConstrainedWindowGtk;
 class RenderViewContextMenuGtk;
@@ -53,12 +53,14 @@
   virtual gfx::NativeWindow GetTopLevelNativeWindow() const;
   virtual void GetContainerBounds(gfx::Rect* out) const;
   virtual void SetPageTitle(const std::wstring& title);
-  virtual void OnTabCrashed();
+  virtual void OnTabCrashed(base::TerminationStatus status,
+                            int error_code);
   virtual void SizeContents(const gfx::Size& size);
   virtual void Focus();
   virtual void SetInitialFocus();
   virtual void StoreFocus();
   virtual void RestoreFocus();
+  virtual void GetViewBounds(gfx::Rect* out) const;
 
   // Backend implementation of RenderViewHostDelegate::View.
   virtual void ShowContextMenu(const ContextMenuParams& params);
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.h b/chrome/browser/tab_contents/tab_contents_view_mac.h
index 1aab6b8..76d7888 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.h
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.h
@@ -14,8 +14,9 @@
 #include "base/scoped_nsobject.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/ui/cocoa/base_view.h"
+#include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 @class FocusTracker;
 @class SadTabController;
@@ -60,7 +61,8 @@
   virtual void GetContainerBounds(gfx::Rect* out) const;
   virtual void RenderViewCreated(RenderViewHost* host);
   virtual void SetPageTitle(const std::wstring& title);
-  virtual void OnTabCrashed();
+  virtual void OnTabCrashed(base::TerminationStatus status,
+                            int error_code);
   virtual void SizeContents(const gfx::Size& size);
   virtual void Focus();
   virtual void SetInitialFocus();
@@ -74,6 +76,7 @@
                                          const gfx::Rect& initial_pos);
   virtual bool IsEventTracking() const;
   virtual void CloseTabAfterEventTracking();
+  virtual void GetViewBounds(gfx::Rect* out) const;
 
   // Backend implementation of RenderViewHostDelegate::View.
   virtual void ShowContextMenu(const ContextMenuParams& params);
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.mm b/chrome/browser/tab_contents/tab_contents_view_mac.mm
index 8d810dd..10cd690 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.mm
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.mm
@@ -19,9 +19,9 @@
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #import "chrome/browser/ui/cocoa/focus_tracker.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/sad_tab_controller.h"
-#import "chrome/browser/ui/cocoa/web_drag_source.h"
-#import "chrome/browser/ui/cocoa/web_drop_target.h"
+#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/web_drag_source.h"
+#import "chrome/browser/ui/cocoa/tab_contents/web_drop_target.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #import "chrome/common/chrome_application_mac.h"
 #include "chrome/common/notification_details.h"
@@ -175,7 +175,8 @@
   // Meaningless on the Mac; widgets don't have a "title" attribute
 }
 
-void TabContentsViewMac::OnTabCrashed() {
+void TabContentsViewMac::OnTabCrashed(base::TerminationStatus /* status */,
+                                      int /* error_code */) {
   if (!sad_tab_.get()) {
     TabContents* contents = tab_contents();
     DCHECK(contents);
@@ -321,6 +322,11 @@
                     afterDelay:0.0];
 }
 
+void TabContentsViewMac::GetViewBounds(gfx::Rect* out) const {
+  // This method is noth currently used on mac.
+  NOTIMPLEMENTED();
+}
+
 void TabContentsViewMac::CloseTab() {
   tab_contents()->Close(tab_contents()->render_view_host());
 }
diff --git a/chrome/browser/tab_contents/tab_specific_content_settings.cc b/chrome/browser/tab_contents/tab_specific_content_settings.cc
index e5e6f42..65eb1f2 100644
--- a/chrome/browser/tab_contents/tab_specific_content_settings.cc
+++ b/chrome/browser/tab_contents/tab_specific_content_settings.cc
@@ -107,6 +107,8 @@
     const GURL& url,
     const net::CookieList& cookie_list,
     bool blocked_by_policy) {
+  if (cookie_list.empty())
+    return;
   LocalSharedObjectsContainer& container = blocked_by_policy ?
       blocked_local_shared_objects_ : allowed_local_shared_objects_;
   typedef net::CookieList::const_iterator cookie_iterator;
diff --git a/chrome/browser/tab_contents/tab_specific_content_settings_unittest.cc b/chrome/browser/tab_contents/tab_specific_content_settings_unittest.cc
index d23d877..61fdcfe 100644
--- a/chrome/browser/tab_contents/tab_specific_content_settings_unittest.cc
+++ b/chrome/browser/tab_contents/tab_specific_content_settings_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/tab_contents/tab_specific_content_settings.h"
 
 #include "chrome/test/testing_profile.h"
-#include "net/base/cookie_options.h"
+#include "net/base/cookie_monster.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -137,3 +137,20 @@
   ASSERT_TRUE(
       content_settings.IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
 }
+
+TEST(TabSpecificContentSettingsTest, EmptyCookieList) {
+  TestContentSettingsDelegate test_delegate;
+  TestingProfile profile;
+  TabSpecificContentSettings content_settings(&test_delegate, &profile);
+
+  ASSERT_FALSE(
+      content_settings.IsContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES));
+  ASSERT_FALSE(
+      content_settings.IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
+  content_settings.OnCookiesRead(
+      GURL("http://google.com"), net::CookieList(), true);
+  ASSERT_FALSE(
+      content_settings.IsContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES));
+  ASSERT_FALSE(
+      content_settings.IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
+}
diff --git a/chrome/browser/tab_contents/test_tab_contents.cc b/chrome/browser/tab_contents/test_tab_contents.cc
index 0c227a4..69fc0cf 100644
--- a/chrome/browser/tab_contents/test_tab_contents.cc
+++ b/chrome/browser/tab_contents/test_tab_contents.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
+#include "chrome/common/page_transition_types.h"
 
 TestTabContents::TestTabContents(Profile* profile, SiteInstance* instance)
     : TabContents(profile, instance, MSG_ROUTING_NONE, NULL, NULL),
@@ -68,7 +69,7 @@
 }
 
 void TestTabContents::NavigateAndCommit(const GURL& url) {
-  controller().LoadURL(url, GURL(), 0);
+  controller().LoadURL(url, GURL(), PageTransition::LINK);
   GURL loaded_url(url);
   bool reverse_on_redirect = false;
   BrowserURLHandler::RewriteURLIfNecessary(
diff --git a/chrome/browser/tab_contents/test_tab_contents.h b/chrome/browser/tab_contents/test_tab_contents.h
index 21bc096..729730b 100644
--- a/chrome/browser/tab_contents/test_tab_contents.h
+++ b/chrome/browser/tab_contents/test_tab_contents.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -50,8 +50,9 @@
   }
 
   // Prevent interaction with views.
-  bool CreateRenderViewForRenderManager(RenderViewHost* render_view_host);
-  void UpdateRenderViewSizeForRenderManager() {}
+  virtual bool CreateRenderViewForRenderManager(
+      RenderViewHost* render_view_host);
+  virtual void UpdateRenderViewSizeForRenderManager() {}
 
   // Returns a clone of this TestTabContents. The returned object is also a
   // TestTabContents. The caller owns the returned object.
diff --git a/chrome/browser/tab_contents/thumbnail_generator.cc b/chrome/browser/tab_contents/thumbnail_generator.cc
index 1844f67..c0dd91d 100644
--- a/chrome/browser/tab_contents/thumbnail_generator.cc
+++ b/chrome/browser/tab_contents/thumbnail_generator.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,19 +11,27 @@
 #include "base/scoped_ptr.h"
 #include "base/time.h"
 #include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/history/top_sites.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/backing_store.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/property_bag.h"
-#include "gfx/rect.h"
-#include "gfx/skbitmap_operations.h"
+#include "chrome/common/thumbnail_score.h"
+#include "googleurl/src/gurl.h"
+#include "skia/ext/bitmap_platform_device.h"
+#include "skia/ext/image_operations.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/skbitmap_operations.h"
 
 #if defined(OS_WIN)
-#include "app/win/win_util.h"
+#include "chrome/common/section_util_win.h"
 #endif
 
 // Overview
@@ -99,9 +107,12 @@
 
 // Creates a downsampled thumbnail for the given backing store. The returned
 // bitmap will be isNull if there was an error creating it.
-SkBitmap GetBitmapForBackingStore(BackingStore* backing_store,
-                                  int desired_width,
-                                  int desired_height) {
+SkBitmap GetBitmapForBackingStore(
+    BackingStore* backing_store,
+    int desired_width,
+    int desired_height,
+    int options,
+    ThumbnailGenerator::ClipResult* clip_result) {
   base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now();
 
   SkBitmap result;
@@ -115,20 +126,31 @@
     return result;
   const SkBitmap& bmp = temp_canvas.getTopPlatformDevice().accessBitmap(false);
 
-  // Need to resize it to the size we want, so downsample until it's
-  // close, and let the caller make it the exact size if desired.
-  result = SkBitmapOperations::DownsampleByTwoUntilSize(
-      bmp, desired_width, desired_height);
+  // Check if a clipped thumbnail is requested.
+  if (options & ThumbnailGenerator::kClippedThumbnail) {
+    SkBitmap clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
+        bmp, desired_width, desired_height, clip_result);
 
-  // This is a bit subtle. SkBitmaps are refcounted, but the magic
-  // ones in PlatformCanvas can't be assigned to SkBitmap with proper
-  // refcounting.  If the bitmap doesn't change, then the downsampler
-  // will return the input bitmap, which will be the reference to the
-  // weird PlatformCanvas one insetad of a regular one. To get a
-  // regular refcounted bitmap, we need to copy it.
-  if (bmp.width() == result.width() &&
-      bmp.height() == result.height())
-    bmp.copyTo(&result, SkBitmap::kARGB_8888_Config);
+    // Need to resize it to the size we want, so downsample until it's
+    // close, and let the caller make it the exact size if desired.
+    result = SkBitmapOperations::DownsampleByTwoUntilSize(
+        clipped_bitmap, desired_width, desired_height);
+  } else {
+    // Need to resize it to the size we want, so downsample until it's
+    // close, and let the caller make it the exact size if desired.
+    result = SkBitmapOperations::DownsampleByTwoUntilSize(
+        bmp, desired_width, desired_height);
+
+    // This is a bit subtle. SkBitmaps are refcounted, but the magic
+    // ones in PlatformCanvas can't be assigned to SkBitmap with proper
+    // refcounting.  If the bitmap doesn't change, then the downsampler
+    // will return the input bitmap, which will be the reference to the
+    // weird PlatformCanvas one insetad of a regular one. To get a
+    // regular refcounted bitmap, we need to copy it.
+    if (bmp.width() == result.width() &&
+        bmp.height() == result.height())
+      bmp.copyTo(&result, SkBitmap::kARGB_8888_Config);
+  }
 
   HISTOGRAM_TIMES(kThumbnailHistogramName,
                   base::TimeTicks::Now() - begin_compute_thumbnail);
@@ -172,6 +194,45 @@
   }
 }
 
+void ThumbnailGenerator::MonitorRenderer(RenderWidgetHost* renderer,
+                                         bool monitor) {
+  Source<RenderWidgetHost> renderer_source = Source<RenderWidgetHost>(renderer);
+  bool currently_monitored =
+      registrar_.IsRegistered(
+        this,
+        NotificationType::RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE,
+        renderer_source);
+  if (monitor != currently_monitored) {
+    if (monitor) {
+      registrar_.Add(
+          this,
+          NotificationType::RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE,
+          renderer_source);
+      registrar_.Add(
+          this,
+          NotificationType::RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
+          renderer_source);
+      registrar_.Add(
+          this,
+          NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
+          renderer_source);
+    } else {
+      registrar_.Remove(
+          this,
+          NotificationType::RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE,
+          renderer_source);
+      registrar_.Remove(
+          this,
+          NotificationType::RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
+          renderer_source);
+      registrar_.Remove(
+          this,
+          NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
+          renderer_source);
+    }
+  }
+}
+
 void ThumbnailGenerator::AskForSnapshot(RenderWidgetHost* renderer,
                                         bool prefer_backing_store,
                                         ThumbnailReadyCallback* callback,
@@ -184,7 +245,9 @@
       // we'll go with it.
       SkBitmap first_try = GetBitmapForBackingStore(backing_store,
                                                     desired_size.width(),
-                                                    desired_size.height());
+                                                    desired_size.height(),
+                                                    kNoOptions,
+                                                    NULL);
       callback->Run(first_try);
 
       delete callback;
@@ -205,7 +268,7 @@
   // Duplicate the handle to the DIB here because the renderer process does not
   // have permission. The duplicated handle is owned by the renderer process,
   // which is responsible for closing it.
-  TransportDIB::Handle renderer_dib_handle = app::win::GetSectionForProcess(
+  TransportDIB::Handle renderer_dib_handle = chrome::GetSectionForProcess(
       thumbnail_dib->handle(),
       renderer->process()->GetHandle(),
       false);
@@ -236,6 +299,13 @@
 
 SkBitmap ThumbnailGenerator::GetThumbnailForRenderer(
     RenderWidgetHost* renderer) const {
+  return GetThumbnailForRendererWithOptions(renderer, kNoOptions, NULL);
+}
+
+SkBitmap ThumbnailGenerator::GetThumbnailForRendererWithOptions(
+    RenderWidgetHost* renderer,
+    int options,
+    ClipResult* clip_result) const {
   WidgetThumbnail* wt = GetDataForHost(renderer);
 
   BackingStore* backing_store = renderer->GetBackingStore(false);
@@ -260,7 +330,9 @@
   // invalidated on the next paint.
   wt->thumbnail = GetBitmapForBackingStore(backing_store,
                                            kThumbnailWidth,
-                                           kThumbnailHeight);
+                                           kThumbnailHeight,
+                                           options,
+                                           clip_result);
   return wt->thumbnail;
 }
 
@@ -281,7 +353,9 @@
   // an existing thumbnail.
   SkBitmap new_thumbnail = GetBitmapForBackingStore(backing_store,
                                                     kThumbnailWidth,
-                                                    kThumbnailHeight);
+                                                    kThumbnailHeight,
+                                                    kNoOptions,
+                                                    NULL);
   if (!new_thumbnail.isNull())
     wt->thumbnail = new_thumbnail;
 }
@@ -356,7 +430,7 @@
     case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
       // Install our observer for all new RVHs.
       RenderViewHost* renderer = Details<RenderViewHost>(details).ptr();
-      renderer->set_painting_observer(this);
+      MonitorRenderer(renderer, true);
       break;
     }
 
@@ -371,6 +445,26 @@
       WidgetDestroyed(Source<RenderWidgetHost>(source).ptr());
       break;
 
+    case NotificationType::RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE:
+      WidgetWillDestroyBackingStore(
+          Source<RenderWidgetHost>(source).ptr(),
+          Details<BackingStore>(details).ptr());
+      break;
+
+    case NotificationType::RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE:
+      WidgetDidUpdateBackingStore(Source<RenderWidgetHost>(source).ptr());
+      break;
+
+    case NotificationType::RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK: {
+      RenderWidgetHost::PaintAtSizeAckDetails* size_ack_details =
+          Details<RenderWidgetHost::PaintAtSizeAckDetails>(details).ptr();
+      WidgetDidReceivePaintAtSizeAck(
+          Source<RenderWidgetHost>(source).ptr(),
+          size_ack_details->tag,
+          size_ack_details->size);
+      break;
+    }
+
     case NotificationType::TAB_CONTENTS_DISCONNECTED:
       TabContentsDisconnected(Source<TabContents>(source).ptr());
       break;
@@ -475,3 +569,117 @@
   if (found != shown_hosts_.end())
     shown_hosts_.erase(found);
 }
+
+double ThumbnailGenerator::CalculateBoringScore(SkBitmap* bitmap) {
+  if (bitmap->isNull() || bitmap->empty())
+    return 1.0;
+  int histogram[256] = {0};
+  color_utils::BuildLumaHistogram(bitmap, histogram);
+
+  int color_count = *std::max_element(histogram, histogram + 256);
+  int pixel_count = bitmap->width() * bitmap->height();
+  return static_cast<double>(color_count) / pixel_count;
+}
+
+SkBitmap ThumbnailGenerator::GetClippedBitmap(const SkBitmap& bitmap,
+                                              int desired_width,
+                                              int desired_height,
+                                              ClipResult* clip_result) {
+  const SkRect dest_rect = { 0, 0,
+                             SkIntToScalar(desired_width),
+                             SkIntToScalar(desired_height) };
+  const float dest_aspect = dest_rect.width() / dest_rect.height();
+
+  // Get the src rect so that we can preserve the aspect ratio while filling
+  // the destination.
+  SkIRect src_rect;
+  if (bitmap.width() < dest_rect.width() ||
+      bitmap.height() < dest_rect.height()) {
+    // Source image is smaller: we clip the part of source image within the
+    // dest rect, and then stretch it to fill the dest rect. We don't respect
+    // the aspect ratio in this case.
+    src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
+                 static_cast<S16CPU>(dest_rect.height()));
+    if (clip_result)
+      *clip_result = ThumbnailGenerator::kSourceIsSmaller;
+  } else {
+    const float src_aspect =
+        static_cast<float>(bitmap.width()) / bitmap.height();
+    if (src_aspect > dest_aspect) {
+      // Wider than tall, clip horizontally: we center the smaller
+      // thumbnail in the wider screen.
+      S16CPU new_width = static_cast<S16CPU>(bitmap.height() * dest_aspect);
+      S16CPU x_offset = (bitmap.width() - new_width) / 2;
+      src_rect.set(x_offset, 0, new_width + x_offset, bitmap.height());
+      if (clip_result)
+        *clip_result = ThumbnailGenerator::kWiderThanTall;
+    } else if (src_aspect < dest_aspect) {
+      src_rect.set(0, 0, bitmap.width(),
+                   static_cast<S16CPU>(bitmap.width() / dest_aspect));
+      if (clip_result)
+        *clip_result = ThumbnailGenerator::kTallerThanWide;
+    } else {
+      src_rect.set(0, 0, bitmap.width(), bitmap.height());
+      if (clip_result)
+        *clip_result = ThumbnailGenerator::kNotClipped;
+    }
+  }
+
+  SkBitmap clipped_bitmap;
+  bitmap.extractSubset(&clipped_bitmap, src_rect);
+  return clipped_bitmap;
+}
+
+void ThumbnailGenerator::UpdateThumbnailIfNecessary(
+    TabContents* tab_contents, const GURL& url) {
+  history::TopSites* top_sites = tab_contents->profile()->GetTopSites();
+  // Skip if we don't need to update the thumbnail.
+  if (!ShouldUpdateThumbnail(tab_contents->profile(), top_sites, url))
+    return;
+
+  ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator();
+  const int options = ThumbnailGenerator::kClippedThumbnail;
+  ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped;
+  SkBitmap thumbnail = generator->GetThumbnailForRendererWithOptions(
+      tab_contents->render_view_host(), options, &clip_result);
+  // Failed to generate a thumbnail. Maybe the tab is in the background?
+  if (thumbnail.isNull())
+    return;
+
+  // Compute the thumbnail score.
+  ThumbnailScore score;
+  score.at_top =
+      (tab_contents->render_view_host()->last_scroll_offset().height() == 0);
+  score.boring_score = ThumbnailGenerator::CalculateBoringScore(&thumbnail);
+  score.good_clipping =
+      (clip_result == ThumbnailGenerator::kTallerThanWide ||
+       clip_result == ThumbnailGenerator::kNotClipped);
+
+  top_sites->SetPageThumbnail(url, thumbnail, score);
+  VLOG(1) << "Thumbnail taken for " << url << ": " << score.ToString();
+}
+
+bool ThumbnailGenerator::ShouldUpdateThumbnail(Profile* profile,
+                                               history::TopSites* top_sites,
+                                               const GURL& url) {
+  if (!profile || !top_sites)
+    return false;
+  // Skip if it's in the off-the-record mode.
+  if (profile->IsOffTheRecord())
+    return false;
+  // Skip if the given URL is not appropriate for history.
+  if (!HistoryService::CanAddURL(url))
+    return false;
+  // Skip if the top sites list is full, and the URL is not known.
+  const bool is_known = top_sites->IsKnownURL(url);
+  if (top_sites->IsFull() && !is_known)
+    return false;
+  // Skip if we don't have to udpate the existing thumbnail.
+  ThumbnailScore current_score;
+  if (is_known &&
+      top_sites->GetPageThumbnailScore(url, &current_score) &&
+      !current_score.ShouldConsiderUpdating())
+    return false;
+
+  return true;
+}
diff --git a/chrome/browser/tab_contents/thumbnail_generator.h b/chrome/browser/tab_contents/thumbnail_generator.h
index 51fc1ff..595df34 100644
--- a/chrome/browser/tab_contents/thumbnail_generator.h
+++ b/chrome/browser/tab_contents/thumbnail_generator.h
@@ -13,22 +13,45 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/linked_ptr.h"
-#include "base/lock.h"
 #include "base/timer.h"
-#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h"
+#include "chrome/browser/renderer_host/backing_store.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
+class GURL;
+class Profile;
 class RenderWidgetHost;
 class SkBitmap;
 class TabContents;
 
-// This class MUST be destroyed after the RenderWidgetHosts, since it installs
-// a painting observer that is not removed.
-class ThumbnailGenerator : public RenderWidgetHostPaintingObserver,
-                           public NotificationObserver {
+namespace history {
+class TopSites;
+}
+
+class ThumbnailGenerator : NotificationObserver {
  public:
   typedef Callback1<const SkBitmap&>::Type ThumbnailReadyCallback;
+  // The result of clipping. This can be used to determine if the
+  // generated thumbnail is good or not.
+  enum ClipResult {
+    // The source image is smaller.
+    kSourceIsSmaller,
+    // Wider than tall, clip horizontally.
+    kWiderThanTall,
+    // Taller than wide, clip vertically.
+    kTallerThanWide,
+    // The source and destination aspect ratios are identical.
+    kNotClipped,
+  };
+
+  // Bitmasks of options for generating a thumbnail.
+  enum ThumbnailOptions {
+    // No options.
+    kNoOptions = 0,
+    // Request a clipped thumbnail with the aspect ratio preserved.
+    kClippedThumbnail = 1 << 0,
+  };
+
   // This class will do nothing until you call StartThumbnailing.
   ThumbnailGenerator();
   ~ThumbnailGenerator();
@@ -64,6 +87,17 @@
   // renderer.
   SkBitmap GetThumbnailForRenderer(RenderWidgetHost* renderer) const;
 
+  // This returns a thumbnail of a fixed, small size for the given
+  // renderer. |options| is a bitmask of ThumbnailOptions. If
+  // |clip_result| is non-NULL, the result of clipping will be written.
+  SkBitmap GetThumbnailForRendererWithOptions(RenderWidgetHost* renderer,
+                                              int options,
+                                              ClipResult* clip_result) const;
+
+  // Start or stop monitoring notifications for |renderer| based on the value
+  // of |monitor|.
+  void MonitorRenderer(RenderWidgetHost* renderer, bool monitor);
+
 #ifdef UNIT_TEST
   // When true, the class will not use a timeout to do the expiration. This
   // will cause expiration to happen on the next run of the message loop.
@@ -72,6 +106,31 @@
   void set_no_timeout(bool no_timeout) { no_timeout_ = no_timeout; }
 #endif
 
+  // Calculates how "boring" a thumbnail is. The boring score is the
+  // 0,1 ranged percentage of pixels that are the most common
+  // luma. Higher boring scores indicate that a higher percentage of a
+  // bitmap are all the same brightness.
+  static double CalculateBoringScore(SkBitmap* bitmap);
+
+  // Gets the clipped bitmap from |bitmap| per the aspect ratio of the
+  // desired width and the desired height. For instance, if the input
+  // bitmap is vertically long (ex. 400x900) and the desired size is
+  // square (ex. 100x100), the clipped bitmap will be the top half of the
+  // input bitmap (400x400).
+  static SkBitmap GetClippedBitmap(const SkBitmap& bitmap,
+                                   int desired_width,
+                                   int desired_height,
+                                   ClipResult* clip_result);
+
+  // Update the thumbnail of the given URL if necessary.
+  static void UpdateThumbnailIfNecessary(TabContents* tab_contents,
+                                         const GURL& url);
+
+  // Returns true if we should update the thumbnail of the given URL.
+  static bool ShouldUpdateThumbnail(Profile* profile,
+                                    history::TopSites* top_sites,
+                                    const GURL& url);
+
  private:
   // RenderWidgetHostPaintingObserver implementation.
   virtual void WidgetWillDestroyBackingStore(RenderWidgetHost* widget,
diff --git a/chrome/browser/tab_contents/thumbnail_generator_unittest.cc b/chrome/browser/tab_contents/thumbnail_generator_unittest.cc
index 787873c..ef639fd 100644
--- a/chrome/browser/tab_contents/thumbnail_generator_unittest.cc
+++ b/chrome/browser/tab_contents/thumbnail_generator_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "app/surface/transport_dib.h"
 #include "base/basictypes.h"
+#include "base/stringprintf.h"
+#include "chrome/browser/history/top_sites.h"
 #include "chrome/browser/renderer_host/backing_store_manager.h"
 #include "chrome/browser/renderer_host/mock_render_process_host.h"
 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
@@ -14,6 +16,7 @@
 #include "skia/ext/platform_canvas.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColorPriv.h"
+#include "ui/gfx/canvas_skia.h"
 
 static const int kBitmapWidth = 100;
 static const int kBitmapHeight = 100;
@@ -178,3 +181,199 @@
 }
 
 #endif
+
+TEST(ThumbnailGeneratorSimpleTest, CalculateBoringScore_Empty) {
+  SkBitmap bitmap;
+  EXPECT_DOUBLE_EQ(1.0, ThumbnailGenerator::CalculateBoringScore(&bitmap));
+}
+
+TEST(ThumbnailGeneratorSimpleTest, CalculateBoringScore_SingleColor) {
+  const SkColor kBlack = SkColorSetRGB(0, 0, 0);
+  const gfx::Size kSize(20, 10);
+  gfx::CanvasSkia canvas(kSize.width(), kSize.height(), true);
+  // Fill all pixesl in black.
+  canvas.FillRectInt(kBlack, 0, 0, kSize.width(), kSize.height());
+
+  SkBitmap bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
+  // The thumbnail should deserve the highest boring score.
+  EXPECT_DOUBLE_EQ(1.0, ThumbnailGenerator::CalculateBoringScore(&bitmap));
+}
+
+TEST(ThumbnailGeneratorSimpleTest, CalculateBoringScore_TwoColors) {
+  const SkColor kBlack = SkColorSetRGB(0, 0, 0);
+  const SkColor kWhite = SkColorSetRGB(0xFF, 0xFF, 0xFF);
+  const gfx::Size kSize(20, 10);
+
+  gfx::CanvasSkia canvas(kSize.width(), kSize.height(), true);
+  // Fill all pixesl in black.
+  canvas.FillRectInt(kBlack, 0, 0, kSize.width(), kSize.height());
+  // Fill the left half pixels in white.
+  canvas.FillRectInt(kWhite, 0, 0, kSize.width() / 2, kSize.height());
+
+  SkBitmap bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
+  ASSERT_EQ(kSize.width(), bitmap.width());
+  ASSERT_EQ(kSize.height(), bitmap.height());
+  // The thumbnail should be less boring because two colors are used.
+  EXPECT_DOUBLE_EQ(0.5, ThumbnailGenerator::CalculateBoringScore(&bitmap));
+}
+
+TEST(ThumbnailGeneratorSimpleTest, GetClippedBitmap_TallerThanWide) {
+  // The input bitmap is vertically long.
+  gfx::CanvasSkia canvas(40, 90, true);
+  const SkBitmap bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
+
+  // The desired size is square.
+  ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped;
+  SkBitmap clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
+      bitmap, 10, 10, &clip_result);
+  // The clipped bitmap should be square.
+  EXPECT_EQ(40, clipped_bitmap.width());
+  EXPECT_EQ(40, clipped_bitmap.height());
+  // The input was taller than wide.
+  EXPECT_EQ(ThumbnailGenerator::kTallerThanWide, clip_result);
+}
+
+TEST(ThumbnailGeneratorSimpleTest, GetClippedBitmap_WiderThanTall) {
+  // The input bitmap is horizontally long.
+  gfx::CanvasSkia canvas(90, 40, true);
+  const SkBitmap bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
+
+  // The desired size is square.
+  ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped;
+  SkBitmap clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
+      bitmap, 10, 10, &clip_result);
+  // The clipped bitmap should be square.
+  EXPECT_EQ(40, clipped_bitmap.width());
+  EXPECT_EQ(40, clipped_bitmap.height());
+  // The input was wider than tall.
+  EXPECT_EQ(ThumbnailGenerator::kWiderThanTall, clip_result);
+}
+
+TEST(ThumbnailGeneratorSimpleTest, GetClippedBitmap_NotClipped) {
+  // The input bitmap is square.
+  gfx::CanvasSkia canvas(40, 40, true);
+  const SkBitmap bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
+
+  // The desired size is square.
+  ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped;
+  SkBitmap clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
+      bitmap, 10, 10, &clip_result);
+  // The clipped bitmap should be square.
+  EXPECT_EQ(40, clipped_bitmap.width());
+  EXPECT_EQ(40, clipped_bitmap.height());
+  // There was no need to clip.
+  EXPECT_EQ(ThumbnailGenerator::kNotClipped, clip_result);
+}
+
+TEST(ThumbnailGeneratorSimpleTest, GetClippedBitmap_NonSquareOutput) {
+  // The input bitmap is square.
+  gfx::CanvasSkia canvas(40, 40, true);
+  const SkBitmap bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
+
+  // The desired size is horizontally long.
+  ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped;
+  SkBitmap clipped_bitmap = ThumbnailGenerator::GetClippedBitmap(
+      bitmap, 20, 10, &clip_result);
+  // The clipped bitmap should have the same aspect ratio of the desired size.
+  EXPECT_EQ(40, clipped_bitmap.width());
+  EXPECT_EQ(20, clipped_bitmap.height());
+  // The input was taller than wide.
+  EXPECT_EQ(ThumbnailGenerator::kTallerThanWide, clip_result);
+}
+
+// A mock version of TopSites, used for testing ShouldUpdateThumbnail().
+class MockTopSites : public history::TopSites {
+ public:
+  MockTopSites(Profile* profile)
+      : history::TopSites(profile),
+        capacity_(1) {
+  }
+
+  // history::TopSites overrides.
+  virtual bool IsFull() {
+    return known_url_map_.size() >= capacity_;
+  }
+  virtual bool IsKnownURL(const GURL& url) {
+    return known_url_map_.find(url.spec()) != known_url_map_.end();
+  }
+  virtual bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score) {
+    std::map<std::string, ThumbnailScore>::const_iterator iter =
+        known_url_map_.find(url.spec());
+    if (iter == known_url_map_.end()) {
+      return false;
+    } else {
+      *score = iter->second;
+      return true;
+    }
+  }
+
+  // Adds a known URL with the associated thumbnail score.
+  void AddKnownURL(const GURL& url, const ThumbnailScore& score) {
+    known_url_map_[url.spec()] = score;
+  }
+
+ private:
+  virtual ~MockTopSites() {}
+  size_t capacity_;
+  std::map<std::string, ThumbnailScore> known_url_map_;
+};
+
+TEST(ThumbnailGeneratorSimpleTest, ShouldUpdateThumbnail) {
+  const GURL kGoodURL("http://www.google.com/");
+  const GURL kBadURL("chrome://newtab");
+
+  // Set up the profile.
+  TestingProfile profile;
+
+  // Set up the top sites service.
+  ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  scoped_refptr<MockTopSites> top_sites(new MockTopSites(&profile));
+
+  // Should be false because it's a bad URL.
+  EXPECT_FALSE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kBadURL));
+
+  // Should be true, as it's a good URL.
+  EXPECT_TRUE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kGoodURL));
+
+  // Should be false, if it's in the off-the-record mode.
+  profile.set_off_the_record(true);
+  EXPECT_FALSE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kGoodURL));
+
+  // Should be true again, once turning off the off-the-record mode.
+  profile.set_off_the_record(false);
+  EXPECT_TRUE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kGoodURL));
+
+  // Add a known URL. This makes the top sites data full.
+  ThumbnailScore bad_score;
+  bad_score.time_at_snapshot = base::Time::UnixEpoch();  // Ancient time stamp.
+  top_sites->AddKnownURL(kGoodURL, bad_score);
+  ASSERT_TRUE(top_sites->IsFull());
+
+  // Should be false, as the top sites data is full, and the new URL is
+  // not known.
+  const GURL kAnotherGoodURL("http://www.youtube.com/");
+  EXPECT_FALSE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kAnotherGoodURL));
+
+  // Should be true, as the existing thumbnail is bad (i.e need a better one).
+  EXPECT_TRUE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kGoodURL));
+
+  // Replace the thumbnail score with a really good one.
+  ThumbnailScore good_score;
+  good_score.time_at_snapshot = base::Time::Now();  // Very new.
+  good_score.at_top = true;
+  good_score.good_clipping = true;
+  good_score.boring_score = 0.0;
+  top_sites->AddKnownURL(kGoodURL, good_score);
+
+  // Should be false, as the existing thumbnail is good enough (i.e. don't
+  // need to replace the existing thumbnail which is new and good).
+  EXPECT_FALSE(ThumbnailGenerator::ShouldUpdateThumbnail(
+      &profile, top_sites.get(), kGoodURL));
+}
diff --git a/chrome/browser/tab_contents/view_source_uitest.cc b/chrome/browser/tab_contents/view_source_uitest.cc
index 3e22b70..63f4b85 100644
--- a/chrome/browser/tab_contents/view_source_uitest.cc
+++ b/chrome/browser/tab_contents/view_source_uitest.cc
@@ -91,7 +91,9 @@
 
 // Make sure that when looking at the page source, we can't select "View Source"
 // from the menu.
-TEST_F(ViewSourceTest, ViewSourceInMenuDisabledWhileViewingSource) {
+//
+// Occasionally crashes on all platforms, see http://crbug.com/69249
+TEST_F(ViewSourceTest, FLAKY_ViewSourceInMenuDisabledWhileViewingSource) {
   ASSERT_TRUE(test_server_.Start());
 
   GURL url_viewsource(chrome::kViewSourceScheme + std::string(":") +
diff --git a/chrome/browser/tab_contents/web_contents_unittest.cc b/chrome/browser/tab_contents/web_contents_unittest.cc
index a494dd5..39f0d60 100644
--- a/chrome/browser/tab_contents/web_contents_unittest.cc
+++ b/chrome/browser/tab_contents/web_contents_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <vector>
 
-#include "app/message_box_flags.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
@@ -27,6 +26,7 @@
 #include "chrome/test/testing_profile.h"
 #include "ipc/ipc_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/message_box_flags.h"
 
 using webkit_glue::PasswordForm;
 
@@ -1524,7 +1524,7 @@
   IPC::Message* dummy_message = new IPC::Message;
   bool did_suppress_message = false;
   contents()->RunJavaScriptMessage(L"This is an informative message", L"OK",
-      kGURL, MessageBoxFlags::kIsJavascriptAlert, dummy_message,
+      kGURL, ui::MessageBoxFlags::kIsJavascriptAlert, dummy_message,
       &did_suppress_message);
   EXPECT_TRUE(did_suppress_message);
 }
diff --git a/chrome/browser/tab_contents/web_drag_dest_gtk.cc b/chrome/browser/tab_contents/web_drag_dest_gtk.cc
index eaede71..2a80e7b 100644
--- a/chrome/browser/tab_contents/web_drag_dest_gtk.cc
+++ b/chrome/browser/tab_contents/web_drag_dest_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,16 +6,16 @@
 
 #include <string>
 
-#include "app/gtk_dnd_util.h"
 #include "base/file_path.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/gtk/bookmark_utils_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/common/url_constants.h"
 #include "net/base/net_util.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
 
 using WebKit::WebDragOperation;
 using WebKit::WebDragOperationNone;
@@ -25,8 +25,8 @@
 // Returns the bookmark target atom, based on the underlying toolkit.
 //
 // For GTK, bookmark drag data is encoded as pickle and associated with
-// gtk_dnd_util::CHROME_BOOKMARK_ITEM. See
-// bookmark_utils::WriteBookmarksToSelection() for details.
+// ui::CHROME_BOOKMARK_ITEM. See // bookmark_utils::WriteBookmarksToSelection()
+// for details.
 // For Views, bookmark drag data is encoded in the same format, and
 // associated with a custom format. See BookmarkNodeData::Write() for
 // details.
@@ -34,7 +34,7 @@
 #if defined(TOOLKIT_VIEWS)
   return BookmarkNodeData::GetBookmarkCustomFormat();
 #else
-  return gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_BOOKMARK_ITEM);
+  return ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM);
 #endif
 }
 
@@ -104,11 +104,11 @@
     // text/uri-list after text/plain so that the plain text can be cleared if
     // it's a file drag.
     static int supported_targets[] = {
-      gtk_dnd_util::TEXT_PLAIN,
-      gtk_dnd_util::TEXT_URI_LIST,
-      gtk_dnd_util::TEXT_HTML,
-      gtk_dnd_util::NETSCAPE_URL,
-      gtk_dnd_util::CHROME_NAMED_URL,
+      ui::TEXT_PLAIN,
+      ui::TEXT_URI_LIST,
+      ui::TEXT_HTML,
+      ui::NETSCAPE_URL,
+      ui::CHROME_NAMED_URL,
       // TODO(estade): support image drags?
     };
 
@@ -116,7 +116,7 @@
     data_requests_ = arraysize(supported_targets) + 1;
     for (size_t i = 0; i < arraysize(supported_targets); ++i) {
       gtk_drag_get_data(widget_, context,
-                        gtk_dnd_util::GetAtomForTarget(supported_targets[i]),
+                        ui::GetAtomForTarget(supported_targets[i]),
                         time);
     }
 
@@ -151,8 +151,7 @@
   if (data->data && data->length > 0) {
     // If the source can't provide us with valid data for a requested target,
     // data->data will be NULL.
-    if (data->target ==
-        gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::TEXT_PLAIN)) {
+    if (data->target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) {
       guchar* text = gtk_selection_data_get_text(data);
       if (text) {
         drop_data_->plain_text =
@@ -160,8 +159,7 @@
                                     data->length));
         g_free(text);
       }
-    } else if (data->target ==
-               gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::TEXT_URI_LIST)) {
+    } else if (data->target == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
       gchar** uris = gtk_selection_data_get_uris(data);
       if (uris) {
         drop_data_->url = GURL();
@@ -186,15 +184,13 @@
         }
         g_strfreev(uris);
       }
-    } else if (data->target ==
-               gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::TEXT_HTML)) {
+    } else if (data->target == ui::GetAtomForTarget(ui::TEXT_HTML)) {
       // TODO(estade): Can the html have a non-UTF8 encoding?
       drop_data_->text_html =
           UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data),
                                   data->length));
       // We leave the base URL empty.
-    } else if (data->target ==
-               gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::NETSCAPE_URL)) {
+    } else if (data->target == ui::GetAtomForTarget(ui::NETSCAPE_URL)) {
       std::string netscape_url(reinterpret_cast<char*>(data->data),
                                data->length);
       size_t split = netscape_url.find_first_of('\n');
@@ -203,10 +199,8 @@
         if (split < netscape_url.size() - 1)
           drop_data_->url_title = UTF8ToUTF16(netscape_url.substr(split + 1));
       }
-    } else if (data->target ==
-               gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_NAMED_URL)) {
-      gtk_dnd_util::ExtractNamedURL(data,
-                                    &drop_data_->url, &drop_data_->url_title);
+    } else if (data->target == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
+      ui::ExtractNamedURL(data, &drop_data_->url, &drop_data_->url_title);
     }
   }
 
@@ -220,7 +214,7 @@
       bookmark_drag_data_.ReadFromVector(
           bookmark_utils::GetNodesFromSelection(
               NULL, data,
-              gtk_dnd_util::CHROME_BOOKMARK_ITEM,
+              ui::CHROME_BOOKMARK_ITEM,
               tab_contents_->profile(), NULL, NULL));
       bookmark_drag_data_.SetOriginatingProfile(tab_contents_->profile());
     } else {
@@ -238,7 +232,7 @@
             gtk_util::ScreenPoint(widget_),
             gtk_util::GdkDragActionToWebDragOp(context->actions));
 
-    // This is non-null if tab_contents_ is showing an ExtensionDOMUI with
+    // This is non-null if tab_contents_ is showing an ExtensionWebUI with
     // support for (at the moment experimental) drag and drop extensions.
     if (tab_contents_->GetBookmarkDragDelegate()) {
       tab_contents_->GetBookmarkDragDelegate()->OnDragEnter(
@@ -274,7 +268,7 @@
       DragTargetDrop(gtk_util::ClientPoint(widget_),
                      gtk_util::ScreenPoint(widget_));
 
-  // This is non-null if tab_contents_ is showing an ExtensionDOMUI with
+  // This is non-null if tab_contents_ is showing an ExtensionWebUI with
   // support for (at the moment experimental) drag and drop extensions.
   if (tab_contents_->GetBookmarkDragDelegate())
     tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data_);
diff --git a/chrome/browser/tab_contents/web_drag_dest_gtk.h b/chrome/browser/tab_contents/web_drag_dest_gtk.h
index 4b85f9f..00f785a 100644
--- a/chrome/browser/tab_contents/web_drag_dest_gtk.h
+++ b/chrome/browser/tab_contents/web_drag_dest_gtk.h
@@ -8,11 +8,11 @@
 
 #include <gtk/gtk.h>
 
-#include "app/gtk_signal.h"
 #include "base/scoped_ptr.h"
 #include "base/task.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "ui/base/gtk/gtk_signal.h"
 #include "webkit/glue/webdropdata.h"
 
 class TabContents;
diff --git a/chrome/browser/tab_contents/web_drag_source_win.cc b/chrome/browser/tab_contents/web_drag_source_win.cc
index c4e4ebd..ecad8fc 100644
--- a/chrome/browser/tab_contents/web_drag_source_win.cc
+++ b/chrome/browser/tab_contents/web_drag_source_win.cc
@@ -32,7 +32,7 @@
 
 WebDragSource::WebDragSource(gfx::NativeWindow source_wnd,
                              TabContents* tab_contents)
-    : app::win::DragSource(),
+    : ui::DragSource(),
       source_wnd_(source_wnd),
       render_view_host_(tab_contents->render_view_host()),
       effect_(DROPEFFECT_NONE) {
diff --git a/chrome/browser/tab_contents/web_drag_source_win.h b/chrome/browser/tab_contents/web_drag_source_win.h
index 4669f8a..edcbfa3 100644
--- a/chrome/browser/tab_contents/web_drag_source_win.h
+++ b/chrome/browser/tab_contents/web_drag_source_win.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_TAB_CONTENTS_WEB_DRAG_SOURCE_WIN_H_
 #pragma once
 
-#include "app/win/drag_source.h"
 #include "base/basictypes.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/point.h"
+#include "ui/base/dragdrop/drag_source.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
 
 class RenderViewHost;
 class TabContents;
@@ -20,7 +20,7 @@
 // by an active drag-drop operation as the user mouses over other drop targets
 // on their system. This object tells Windows whether or not the drag should
 // continue, and supplies the appropriate cursors.
-class WebDragSource : public app::win::DragSource,
+class WebDragSource : public ui::DragSource,
                       public NotificationObserver {
  public:
   // Create a new DragSource for a given HWND and TabContents.
@@ -35,7 +35,7 @@
   void set_effect(DWORD effect) { effect_ = effect; }
 
  protected:
-  // app::win::DragSource
+  // ui::DragSource
   virtual void OnDragSourceCancel();
   virtual void OnDragSourceDrop();
   virtual void OnDragSourceMove();
diff --git a/chrome/browser/tab_contents/web_drag_utils_win.h b/chrome/browser/tab_contents/web_drag_utils_win.h
index caa1875..5ab311c 100644
--- a/chrome/browser/tab_contents/web_drag_utils_win.h
+++ b/chrome/browser/tab_contents/web_drag_utils_win.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_TAB_CONTENTS_WEB_DRAG_UTILS_WIN_H_
 #pragma once
 
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
 
 #include <windows.h>
 
diff --git a/chrome/browser/tab_contents/web_drop_target_win.cc b/chrome/browser/tab_contents/web_drop_target_win.cc
index d70b851..3567e45 100644
--- a/chrome/browser/tab_contents/web_drop_target_win.cc
+++ b/chrome/browser/tab_contents/web_drop_target_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,16 +7,16 @@
 #include <windows.h>
 #include <shlobj.h>
 
-#include "app/clipboard/clipboard_util_win.h"
-#include "app/os_exchange_data.h"
-#include "app/os_exchange_data_provider_win.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/web_drag_utils_win.h"
-#include "gfx/point.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
+#include "ui/base/clipboard/clipboard_util_win.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
+#include "ui/gfx/point.h"
 #include "webkit/glue/webdropdata.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -51,23 +51,23 @@
       : tab_contents_(tab_contents) {}
 
   DWORD OnDragEnter(IDataObject* data_object, DWORD effect) {
-    return ClipboardUtil::HasUrl(data_object) ? GetPreferredDropEffect(effect)
-                                              : DROPEFFECT_NONE;
+    return ui::ClipboardUtil::HasUrl(data_object) ?
+        GetPreferredDropEffect(effect) : DROPEFFECT_NONE;
   }
 
   DWORD OnDragOver(IDataObject* data_object, DWORD effect) {
-    return ClipboardUtil::HasUrl(data_object) ? GetPreferredDropEffect(effect)
-                                              : DROPEFFECT_NONE;
+    return ui::ClipboardUtil::HasUrl(data_object) ?
+        GetPreferredDropEffect(effect) : DROPEFFECT_NONE;
   }
 
   void OnDragLeave(IDataObject* data_object) {
   }
 
   DWORD OnDrop(IDataObject* data_object, DWORD effect) {
-    if (ClipboardUtil::HasUrl(data_object)) {
+    if (ui::ClipboardUtil::HasUrl(data_object)) {
       std::wstring url;
       std::wstring title;
-      ClipboardUtil::GetUrl(data_object, &url, &title, true);
+      ui::ClipboardUtil::GetUrl(data_object, &url, &title, true);
       tab_contents_->OpenURL(GURL(url), GURL(), CURRENT_TAB,
                              PageTransition::AUTO_BOOKMARK);
       return GetPreferredDropEffect(effect);
@@ -82,7 +82,7 @@
 };
 
 WebDropTarget::WebDropTarget(HWND source_hwnd, TabContents* tab_contents)
-    : app::win::DropTarget(source_hwnd),
+    : ui::DropTarget(source_hwnd),
       tab_contents_(tab_contents),
       current_rvh_(NULL),
       drag_cursor_(WebDragOperationNone),
@@ -110,7 +110,7 @@
   WebDropData::PopulateWebDropData(data_object, &drop_data);
 
   if (drop_data.url.is_empty())
-    OSExchangeDataProviderWin::GetPlainTextURL(data_object, &drop_data.url);
+    ui::OSExchangeDataProviderWin::GetPlainTextURL(data_object, &drop_data.url);
 
   drag_cursor_ = WebDragOperationNone;
 
@@ -121,10 +121,11 @@
       gfx::Point(cursor_position.x, cursor_position.y),
       web_drag_utils_win::WinDragOpMaskToWebDragOpMask(effects));
 
-  // This is non-null if tab_contents_ is showing an ExtensionDOMUI with
+  // This is non-null if tab_contents_ is showing an ExtensionWebUI with
   // support for (at the moment experimental) drag and drop extensions.
   if (tab_contents_->GetBookmarkDragDelegate()) {
-    OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object));
+    ui::OSExchangeData os_exchange_data(
+        new ui::OSExchangeDataProviderWin(data_object));
     BookmarkNodeData bookmark_drag_data;
     if (bookmark_drag_data.Read(os_exchange_data))
       tab_contents_->GetBookmarkDragDelegate()->OnDragEnter(bookmark_drag_data);
@@ -154,7 +155,8 @@
       web_drag_utils_win::WinDragOpMaskToWebDragOpMask(effects));
 
   if (tab_contents_->GetBookmarkDragDelegate()) {
-    OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object));
+    ui::OSExchangeData os_exchange_data(
+        new ui::OSExchangeDataProviderWin(data_object));
     BookmarkNodeData bookmark_drag_data;
     if (bookmark_drag_data.Read(os_exchange_data))
       tab_contents_->GetBookmarkDragDelegate()->OnDragOver(bookmark_drag_data);
@@ -175,7 +177,8 @@
   }
 
   if (tab_contents_->GetBookmarkDragDelegate()) {
-    OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object));
+    ui::OSExchangeData os_exchange_data(
+        new ui::OSExchangeDataProviderWin(data_object));
     BookmarkNodeData bookmark_drag_data;
     if (bookmark_drag_data.Read(os_exchange_data))
       tab_contents_->GetBookmarkDragDelegate()->OnDragLeave(bookmark_drag_data);
@@ -203,7 +206,8 @@
       gfx::Point(cursor_position.x, cursor_position.y));
 
   if (tab_contents_->GetBookmarkDragDelegate()) {
-    OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object));
+    ui::OSExchangeData os_exchange_data(
+        new ui::OSExchangeDataProviderWin(data_object));
     BookmarkNodeData bookmark_drag_data;
     if (bookmark_drag_data.Read(os_exchange_data))
       tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data);
diff --git a/chrome/browser/tab_contents/web_drop_target_win.h b/chrome/browser/tab_contents/web_drop_target_win.h
index 7125b4b..f93d5d0 100644
--- a/chrome/browser/tab_contents/web_drop_target_win.h
+++ b/chrome/browser/tab_contents/web_drop_target_win.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_TAB_CONTENTS_WEB_DROP_TARGET_WIN_H_
 #pragma once
 
-#include "app/win/drop_target.h"
 #include "base/scoped_ptr.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "ui/base/dragdrop/drop_target.h"
 
 class InterstitialDropTarget;
 class RenderViewHost;
@@ -17,7 +17,7 @@
 // A helper object that provides drop capabilities to a TabContents. The
 // DropTarget handles drags that enter the region of the TabContents by
 // passing on the events to the renderer.
-class WebDropTarget : public app::win::DropTarget {
+class WebDropTarget : public ui::DropTarget {
  public:
   // Create a new WebDropTarget associating it with the given HWND and
   // TabContents.
diff --git a/chrome/browser/tab_contents/web_navigation_observer.h b/chrome/browser/tab_contents/web_navigation_observer.h
deleted file mode 100644
index 40981b9..0000000
--- a/chrome/browser/tab_contents/web_navigation_observer.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_TAB_CONTENTS_WEB_NAVIGATION_OBSERVER_H_
-#define CHROME_BROWSER_TAB_CONTENTS_WEB_NAVIGATION_OBSERVER_H_
-
-#include "chrome/browser/tab_contents/navigation_controller.h"
-
-struct ViewHostMsg_FrameNavigate_Params;
-
-// An observer API implemented by classes which are interested in various page
-// load events from TabContents.
-
-// TODO(pink): Is it worth having a bitfield where certain clients can only
-// register for certain events? Is the extra function call worth the added pain
-// on the caller to build the bitfield?
-
-class WebNavigationObserver {
- public:
-  // For removing PasswordManager deps...
-
-  virtual void NavigateToPendingEntry() { }
-
-  virtual void DidNavigateMainFramePostCommit(
-      const NavigationController::LoadCommittedDetails& details,
-      const ViewHostMsg_FrameNavigate_Params& params) { }
-  virtual void DidNavigateAnyFramePostCommit(
-      const NavigationController::LoadCommittedDetails& details,
-      const ViewHostMsg_FrameNavigate_Params& params) { }
-
-  virtual void DidStartLoading() { }
-  virtual void DidStopLoading() { }
-
-  // TODO(beng): These should move from here once PasswordManager is able to
-  //             establish its own private communication protocol to the
-  //             renderer.
-  virtual void PasswordFormsFound(
-      const std::vector<webkit_glue::PasswordForm>& forms) { }
-  virtual void PasswordFormsVisible(
-      const std::vector<webkit_glue::PasswordForm>& visible_forms) { }
-
-#if 0
-  // For unifying with delegate...
-
-  // Notifies the delegate that this contents is starting or is done loading
-  // some resource. The delegate should use this notification to represent
-  // loading feedback. See TabContents::is_loading()
-  virtual void LoadingStateChanged(TabContents* contents) { }
-  // Called to inform the delegate that the tab content's navigation state
-  // changed. The |changed_flags| indicates the parts of the navigation state
-  // that have been updated, and is any combination of the
-  // |TabContents::InvalidateTypes| bits.
-  virtual void NavigationStateChanged(const TabContents* source,
-                                      unsigned changed_flags) { }
-#endif
-};
-
-#endif  // CHROME_BROWSER_TAB_CONTENTS_WEB_NAVIGATION_OBSERVER_H_
diff --git a/chrome/browser/tab_restore_uitest.cc b/chrome/browser/tab_restore_uitest.cc
index eba8f50..975a627 100644
--- a/chrome/browser/tab_restore_uitest.cc
+++ b/chrome/browser/tab_restore_uitest.cc
@@ -1,14 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
 #include "base/command_line.h"
 #include "base/file_path.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/browser_proxy.h"
@@ -25,13 +24,17 @@
 #define MAYBE_BasicRestoreFromClosedWindow BasicRestoreFromClosedWindow
 #endif
 
-// http://crbug.com/
+// http://crbug.com/48911
 #if defined(OS_CHROMEOS) && !defined(NDEBUG)
 #define MAYBE_RestoreWindowAndTab DISABLED_RestoreWindowAndTab
 #define MAYBE_RestoreWindow DISABLED_RestoreWindow
+#define MAYBE_RestoreToDifferentWindow DISABLED_RestoreToDifferentWindow
+#define MAYBE_RestoreIntoSameWindow DISABLED_RestoreIntoSameWindow
 #else
 #define MAYBE_RestoreWindowAndTab RestoreWindowAndTab
 #define MAYBE_RestoreWindow RestoreWindow
+#define MAYBE_RestoreToDifferentWindow RestoreToDifferentWindow
+#define MAYBE_RestoreIntoSameWindow RestoreIntoSameWindow
 #endif
 
 class TabRestoreUITest : public UITest {
@@ -93,7 +96,7 @@
     ASSERT_TRUE(restored_tab_proxy.get());
     // Wait for the restored tab to finish loading.
     ASSERT_TRUE(restored_tab_proxy->WaitForTabToBeRestored(
-        action_max_timeout_ms()));
+        TestTimeouts::action_max_timeout_ms()));
 
     // Ensure that the tab and window are active.
     CheckActiveWindow(browser_proxy.get());
@@ -208,8 +211,7 @@
 
 // Close a tab, switch windows, then restore the tab. The tab should be in its
 // original window and position, and active.
-// This test is flaky. See http://crbug.com/54894
-TEST_F(TabRestoreUITest, FLAKY_RestoreToDifferentWindow) {
+TEST_F(TabRestoreUITest, MAYBE_RestoreToDifferentWindow) {
   scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser_proxy.get());
 
@@ -397,8 +399,7 @@
 
 // Open a window with two tabs, close both (closing the window), then restore
 // both. Make sure both restored tabs are in the same window.
-// http://crbug.com/39925
-TEST_F(TabRestoreUITest, FLAKY_RestoreIntoSameWindow) {
+TEST_F(TabRestoreUITest, MAYBE_RestoreIntoSameWindow) {
   scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
   ASSERT_TRUE(browser_proxy.get());
   CheckActiveWindow(browser_proxy.get());
@@ -600,14 +601,16 @@
   scoped_refptr<TabProxy> restored_tab_proxy(
         browser_proxy->GetTab(initial_tab_count));
   ASSERT_TRUE(restored_tab_proxy.get());
-  ASSERT_TRUE(restored_tab_proxy->WaitForTabToBeRestored(action_timeout_ms()));
+  ASSERT_TRUE(restored_tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_timeout_ms()));
   GURL url;
   ASSERT_TRUE(restored_tab_proxy->GetCurrentURL(&url));
   EXPECT_TRUE(url == url1_);
 
   restored_tab_proxy = browser_proxy->GetTab(initial_tab_count + 1);
   ASSERT_TRUE(restored_tab_proxy.get());
-  ASSERT_TRUE(restored_tab_proxy->WaitForTabToBeRestored(action_timeout_ms()));
+  ASSERT_TRUE(restored_tab_proxy->WaitForTabToBeRestored(
+      TestTimeouts::action_timeout_ms()));
   ASSERT_TRUE(restored_tab_proxy->GetCurrentURL(&url));
   EXPECT_TRUE(url == url2_);
 }
@@ -632,7 +635,7 @@
   RestoreTab(0, 1);
   tab = browser->GetTab(1);
   ASSERT_TRUE(tab.get());
-  ASSERT_TRUE(tab->WaitForTabToBeRestored(action_timeout_ms()));
+  ASSERT_TRUE(tab->WaitForTabToBeRestored(TestTimeouts::action_timeout_ms()));
 
   // See if content is as expected.
   EXPECT_TRUE(tab->FindInPage(std::wstring(L"webkit"), FWD, IGNORE_CASE, false,
@@ -668,7 +671,7 @@
   RestoreTab(0, 1);
   tab = browser->GetTab(1);
   ASSERT_TRUE(tab.get());
-  ASSERT_TRUE(tab->WaitForTabToBeRestored(action_timeout_ms()));
+  ASSERT_TRUE(tab->WaitForTabToBeRestored(TestTimeouts::action_timeout_ms()));
   GURL url;
   ASSERT_TRUE(tab->GetCurrentURL(&url));
   ASSERT_EQ(http_url, url);
diff --git a/chrome/browser/tabs/default_tab_handler.cc b/chrome/browser/tabs/default_tab_handler.cc
index bf8b0ee..f25a526 100644
--- a/chrome/browser/tabs/default_tab_handler.cc
+++ b/chrome/browser/tabs/default_tab_handler.cc
@@ -171,10 +171,12 @@
   delegate_->AsBrowser()->TabMoved(contents, from_index, to_index);
 }
 
-void DefaultTabHandler::TabReplacedAt(TabContentsWrapper* old_contents,
+void DefaultTabHandler::TabReplacedAt(TabStripModel* tab_strip_model,
+                                      TabContentsWrapper* old_contents,
                                       TabContentsWrapper* new_contents,
                                       int index) {
-  delegate_->AsBrowser()->TabReplacedAt(old_contents, new_contents, index);
+  delegate_->AsBrowser()->TabReplacedAt(tab_strip_model, old_contents,
+                                        new_contents, index);
 }
 
 void DefaultTabHandler::TabPinnedStateChanged(TabContentsWrapper* contents,
diff --git a/chrome/browser/tabs/default_tab_handler.h b/chrome/browser/tabs/default_tab_handler.h
index 5d433fb..9a365fa 100644
--- a/chrome/browser/tabs/default_tab_handler.h
+++ b/chrome/browser/tabs/default_tab_handler.h
@@ -71,7 +71,8 @@
   virtual void TabMoved(TabContentsWrapper* contents,
                         int from_index,
                         int to_index);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int index);
   virtual void TabPinnedStateChanged(TabContentsWrapper* contents, int index);
diff --git a/chrome/browser/tabs/pinned_tab_codec_unittest.cc b/chrome/browser/tabs/pinned_tab_codec_unittest.cc
index 6737c01..7030b18 100644
--- a/chrome/browser/tabs/pinned_tab_codec_unittest.cc
+++ b/chrome/browser/tabs/pinned_tab_codec_unittest.cc
@@ -7,6 +7,7 @@
 
 #include "chrome/browser/tabs/pinned_tab_codec.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -62,4 +63,3 @@
   std::string result = TabsToString(PinnedTabCodec::ReadPinnedTabs(profile()));
   EXPECT_EQ("http://www.google.com/::pinned:", result);
 }
-
diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc
index 7d93921..b58eb90 100644
--- a/chrome/browser/tabs/tab_strip_model.cc
+++ b/chrome/browser/tabs/tab_strip_model.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/tabs/tab_strip_model.h"
 
 #include <algorithm>
+#include <map>
 
 #include "base/command_line.h"
 #include "base/stl_util-inl.h"
@@ -26,7 +27,6 @@
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/url_constants.h"
@@ -168,15 +168,15 @@
 TabContentsWrapper* TabStripModel::ReplaceTabContentsAt(
     int index,
     TabContentsWrapper* new_contents) {
-  // TODO: this should reset group/opener of any tabs that point at
-  // old_contents.
   DCHECK(ContainsIndex(index));
   TabContentsWrapper* old_contents = GetContentsAt(index);
 
+  ForgetOpenersAndGroupsReferencing(&(old_contents->controller()));
+
   contents_data_[index]->contents = new_contents;
 
   FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
-                    TabReplacedAt(old_contents, new_contents, index));
+                    TabReplacedAt(this, old_contents, new_contents, index));
 
   // When the selected tab contents is replaced send out selected notification
   // too. We do this as nearly all observers need to treat a replace of the
@@ -212,6 +212,7 @@
   int next_selected_index = order_controller_->DetermineNewSelectedIndex(index);
   delete contents_data_.at(index);
   contents_data_.erase(contents_data_.begin() + index);
+  ForgetOpenersAndGroupsReferencing(&(removed_contents->controller()));
   if (empty())
     closing_all_ = true;
   FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
@@ -1011,3 +1012,14 @@
                                   bool use_group) {
   return data->opener == opener || (use_group && data->group == opener);
 }
+
+void TabStripModel::ForgetOpenersAndGroupsReferencing(
+    const NavigationController* tab) {
+  for (TabContentsDataVector::const_iterator i = contents_data_.begin();
+       i != contents_data_.end(); ++i) {
+    if ((*i)->group == tab)
+      (*i)->group = NULL;
+    if ((*i)->opener == tab)
+      (*i)->opener = NULL;
+  }
+}
diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h
index 7a3c8d9..7ed42f1 100644
--- a/chrome/browser/tabs/tab_strip_model.h
+++ b/chrome/browser/tabs/tab_strip_model.h
@@ -480,6 +480,9 @@
                             const NavigationController* opener,
                             bool use_group);
 
+  // Sets the group/opener of any tabs that reference |tab| to NULL.
+  void ForgetOpenersAndGroupsReferencing(const NavigationController* tab);
+
   // Our delegate.
   TabStripModelDelegate* delegate_;
 
diff --git a/chrome/browser/tabs/tab_strip_model_observer.cc b/chrome/browser/tabs/tab_strip_model_observer.cc
index 8ba8814..dec6f41 100644
--- a/chrome/browser/tabs/tab_strip_model_observer.cc
+++ b/chrome/browser/tabs/tab_strip_model_observer.cc
@@ -38,7 +38,8 @@
                                          TabChangeType change_type) {
 }
 
-void TabStripModelObserver::TabReplacedAt(TabContentsWrapper* old_contents,
+void TabStripModelObserver::TabReplacedAt(TabStripModel* tab_strip_model,
+                                          TabContentsWrapper* old_contents,
                                           TabContentsWrapper* new_contents,
                                           int index) {
 }
diff --git a/chrome/browser/tabs/tab_strip_model_observer.h b/chrome/browser/tabs/tab_strip_model_observer.h
index c681ae0..d123961 100644
--- a/chrome/browser/tabs/tab_strip_model_observer.h
+++ b/chrome/browser/tabs/tab_strip_model_observer.h
@@ -85,9 +85,9 @@
                             TabChangeType change_type);
 
   // The tab contents was replaced at the specified index. This is invoked when
-  // a tab becomes phantom. See description of phantom tabs in class description
-  // of TabStripModel for details.
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
+  // instant is enabled and the user navigates by way of instant.
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int index);
 
diff --git a/chrome/browser/tabs/tab_strip_model_order_controller.cc b/chrome/browser/tabs/tab_strip_model_order_controller.cc
index c7d10f4..bd309fa 100644
--- a/chrome/browser/tabs/tab_strip_model_order_controller.cc
+++ b/chrome/browser/tabs/tab_strip_model_order_controller.cc
@@ -74,6 +74,8 @@
   // group of the removed tab.
   NavigationController* removed_controller =
       &tabstrip_->GetTabContentsAt(removing_index)->controller();
+  // The parent opener should never be the same as the controller being removed.
+  DCHECK(parent_opener != removed_controller);
   int index = tabstrip_->GetIndexOfNextTabContentsOpenedBy(removed_controller,
                                                            removing_index,
                                                            false);
diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc
index b33aaa6..21ed2a5 100644
--- a/chrome/browser/tabs/tab_strip_model_unittest.cc
+++ b/chrome/browser/tabs/tab_strip_model_unittest.cc
@@ -5,7 +5,6 @@
 #include <map>
 #include <string>
 
-#include "app/system_monitor.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
@@ -32,11 +31,11 @@
 #include "chrome/common/notification_observer_mock.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/property_bag.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/system_monitor/system_monitor.h"
 
 using testing::_;
 
@@ -231,8 +230,8 @@
   std::wstring profile_path_;
   std::map<TabContents*, int> foo_;
 
-  // ProfileManager requires a SystemMonitor.
-  SystemMonitor system_monitor;
+  // ProfileManager requires a ui::SystemMonitor.
+  ui::SystemMonitor system_monitor;
 
   ProfileManager pm_;
 };
@@ -341,8 +340,10 @@
                             TabChangeType change_type) {
     states_.push_back(new State(contents, index, CHANGE));
   }
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* new_contents, int index) {
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index) {
     State* s = new State(new_contents, index, REPLACED);
     s ->src_contents = old_contents;
     states_.push_back(s);
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index ac58e03..1f113b7 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/task_manager/task_manager.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/compiler_specific.h"
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
@@ -33,6 +31,8 @@
 #include "grit/generated_resources.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "unicode/coll.h"
 
 #if defined(OS_MACOSX)
@@ -122,7 +122,7 @@
 
 string16 TaskManagerModel::GetResourceTitle(int index) const {
   CHECK_LT(index, ResourceCount());
-  return WideToUTF16Hack(resources_[index]->GetTitle());
+  return resources_[index]->GetTitle();
 }
 
 int64 TaskManagerModel::GetNetworkUsage(int index) const {
@@ -149,13 +149,13 @@
 
 string16 TaskManagerModel::GetResourceCPUUsage(int index) const {
   CHECK_LT(index, ResourceCount());
-  return WideToUTF16Hack(StringPrintf(
+  return UTF8ToUTF16(StringPrintf(
 #if defined(OS_MACOSX)
       // Activity Monitor shows %cpu with one decimal digit -- be
       // consistent with that.
-      L"%.1f",
+      "%.1f",
 #else
-      L"%.0f",
+      "%.0f",
 #endif
       GetCPUUsage(resources_[index])));
 }
@@ -839,16 +839,22 @@
   TaskManager::Resource* resource = NULL;
   for (ResourceProviderList::iterator iter = providers_.begin();
        iter != providers_.end(); ++iter) {
-    resource = (*iter)->GetResource(param.origin_child_id,
+    resource = (*iter)->GetResource(param.origin_pid,
                                     param.render_process_host_child_id,
                                     param.routing_id);
     if (resource)
       break;
   }
+
   if (resource == NULL) {
-    // We may not have that resource anymore (example: close a tab while a
-    // a network resource is being retrieved), in which case we just ignore the
-    // notification.
+    // We can't match a resource to the notification.  That might mean the
+    // tab that started a download was closed, or the request may have had
+    // no originating resource associated with it in the first place.
+    // We attribute orphaned/unaccounted activity to the Browser process.
+    CHECK(param.origin_pid || (param.render_process_host_child_id != -1));
+    param.origin_pid = 0;
+    param.render_process_host_child_id = param.routing_id = -1;
+    BytesRead(param);
     return;
   }
 
@@ -877,7 +883,7 @@
 }
 
 void TaskManagerModel::OnJobDone(net::URLRequestJob* job,
-                                 const URLRequestStatus& status) {
+                                 const net::URLRequestStatus& status) {
 }
 
 void TaskManagerModel::OnJobRedirect(net::URLRequestJob* job,
@@ -887,19 +893,28 @@
 
 void TaskManagerModel::OnBytesRead(net::URLRequestJob* job, const char* buf,
                                    int byte_count) {
+  // Only net::URLRequestJob instances created by the ResourceDispatcherHost
+  // have a render view associated.  All other jobs will have -1 returned for
+  // the render process child and routing ids - the jobs may still match a
+  // resource based on their origin id, otherwise BytesRead() will attribute
+  // the activity to the Browser resource.
   int render_process_host_child_id = -1, routing_id = -1;
   ResourceDispatcherHost::RenderViewForRequest(job->request(),
                                                &render_process_host_child_id,
                                                &routing_id);
+
+  // Get the origin PID of the request's originator.  This will only be set for
+  // plugins - for renderer or browser initiated requests it will be zero.
+  int origin_pid =
+      chrome_browser_net::GetOriginPIDForRequest(job->request());
+
   // This happens in the IO thread, post it to the UI thread.
-  int origin_child_id =
-      chrome_browser_net::GetOriginProcessUniqueIDForRequest(job->request());
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       NewRunnableMethod(
           this,
           &TaskManagerModel::BytesRead,
-          BytesReadParam(origin_child_id,
+          BytesReadParam(origin_pid,
           render_process_host_child_id,
           routing_id, byte_count)));
 }
diff --git a/chrome/browser/task_manager/task_manager.h b/chrome/browser/task_manager/task_manager.h
index 7117092..1f606de 100644
--- a/chrome/browser/task_manager/task_manager.h
+++ b/chrome/browser/task_manager/task_manager.h
@@ -13,7 +13,6 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
 #include "base/observer_list.h"
 #include "base/process_util.h"
 #include "base/ref_counted.h"
@@ -22,7 +21,7 @@
 #include "base/timer.h"
 #include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "net/url_request/url_request_job_tracker.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
 
 class Extension;
 class SkBitmap;
@@ -58,7 +57,7 @@
       GPU              // A graphics process.
     };
 
-    virtual std::wstring GetTitle() const = 0;
+    virtual string16 GetTitle() const = 0;
     virtual SkBitmap GetIcon() const = 0;
     virtual base::ProcessHandle GetProcess() const = 0;
     virtual Type GetType() const = 0;
@@ -346,21 +345,20 @@
 
   // This struct is used to exchange information between the io and ui threads.
   struct BytesReadParam {
-    BytesReadParam(int origin_child_id,
+    BytesReadParam(int origin_pid,
                    int render_process_host_child_id,
                    int routing_id,
                    int byte_count)
-        : origin_child_id(origin_child_id),
+        : origin_pid(origin_pid),
           render_process_host_child_id(render_process_host_child_id),
           routing_id(routing_id),
           byte_count(byte_count) {}
 
-    // This is the child ID of the originator of the request. It will often be
-    // the same as the render_process_host_child_id, but will be different when
-    // another sub-process like a plugin is routing requests through a renderer.
-    int origin_child_id;
+    // The process ID that triggered the request.  For plugin requests this
+    // will differ from the renderer process ID.
+    int origin_pid;
 
-    // The child ID of the RenderProcessHist this request was routed through.
+    // The child ID of the RenderProcessHost this request was routed through.
     int render_process_host_child_id;
 
     int routing_id;
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index b17132f..4243aba 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/task_manager/task_manager.h"
 
-#include "app/l10n_util.h"
 #include "base/file_path.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/background_contents_service.h"
@@ -29,6 +28,7 @@
 #include "chrome/test/ui_test_utils.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -68,6 +68,24 @@
   const int target_resource_count_;
 };
 
+// Helper class used to wait for a BackgroundContents to finish loading.
+class BackgroundContentsListener : public NotificationObserver {
+ public:
+  explicit BackgroundContentsListener(Profile* profile) {
+    registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
+                   Source<Profile>(profile));
+  }
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) {
+    // Quit once the BackgroundContents has been loaded.
+    if (type.value == NotificationType::BACKGROUND_CONTENTS_NAVIGATED)
+      MessageLoopForUI::current()->Quit();
+  }
+ private:
+  NotificationRegistrar registrar_;
+};
+
 }  // namespace
 
 class TaskManagerBrowserTest : public ExtensionBrowserTest {
@@ -84,6 +102,12 @@
     ui_test_utils::RunMessageLoop();
     model()->RemoveObserver(&observer);
   }
+
+  // Wait for any pending BackgroundContents to finish starting up.
+  void WaitForBackgroundContents() {
+    BackgroundContentsListener listener(browser()->profile());
+    ui_test_utils::RunMessageLoop();
+  }
 };
 
 // Regression test for http://crbug.com/13361
@@ -149,6 +173,45 @@
   WaitForResourceChange(2);
 }
 
+IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillBGContents) {
+  EXPECT_EQ(0, model()->ResourceCount());
+
+  // Show the task manager. This populates the model, and helps with debugging
+  // (you see the task manager).
+  browser()->window()->ShowTaskManager();
+
+  // Browser and the New Tab Page.
+  WaitForResourceChange(2);
+
+  // Open a new background contents and make sure we notice that.
+  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
+                                     FilePath(kTitle1File)));
+
+  BackgroundContentsService* service =
+      browser()->profile()->GetBackgroundContentsService();
+  string16 application_id(ASCIIToUTF16("test_app_id"));
+  service->LoadBackgroundContents(browser()->profile(),
+                                  url,
+                                  ASCIIToUTF16("background_page"),
+                                  application_id);
+  // Wait for the background contents process to finish loading.
+  WaitForBackgroundContents();
+  EXPECT_EQ(3, model()->ResourceCount());
+
+  // Kill the background contents process and verify that it disappears from the
+  // model.
+  bool found = false;
+  for (int i = 0; i < model()->ResourceCount(); ++i) {
+    if (model()->IsBackgroundResource(i)) {
+      TaskManager::GetInstance()->KillProcess(i);
+      found = true;
+      break;
+    }
+  }
+  ASSERT_TRUE(found);
+  WaitForResourceChange(2);
+}
+
 IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionChanges) {
   EXPECT_EQ(0, model()->ResourceCount());
 
@@ -322,12 +385,11 @@
   // manager is still visible. Make sure we don't crash and the extension
   // gets reloaded and noticed in the task manager.
   TabContents* current_tab = browser()->GetSelectedTabContents();
-  ASSERT_EQ(1, current_tab->infobar_delegate_count());
-  InfoBarDelegate* delegate = current_tab->GetInfoBarDelegateAt(0);
-  CrashedExtensionInfoBarDelegate* crashed_delegate =
-      delegate->AsCrashedExtensionInfoBarDelegate();
-  ASSERT_TRUE(crashed_delegate);
-  crashed_delegate->Accept();
+  ASSERT_EQ(1U, current_tab->infobar_count());
+  ConfirmInfoBarDelegate* delegate =
+      current_tab->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
+  ASSERT_TRUE(delegate);
+  delegate->Accept();
   WaitForResourceChange(3);
 }
 
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc
index ed8f848..2197b33 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager/task_manager_resource_providers.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include "build/build_config.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/basictypes.h"
 #include "base/file_version_info.h"
 #include "base/i18n/rtl.h"
@@ -41,13 +39,15 @@
 #include "chrome/common/sqlite_utils.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_MACOSX)
 #include "skia/ext/skia_utils_mac.h"
 #endif
 #if defined(OS_WIN)
 #include "chrome/browser/app_icon_win.h"
-#include "gfx/icon_util.h"
+#include "ui/gfx/icon_util.h"
 #endif  // defined(OS_WIN)
 
 namespace {
@@ -169,7 +169,7 @@
   return tab_contents_->HostsExtension() ? EXTENSION : RENDERER;
 }
 
-std::wstring TaskManagerTabContentsResource::GetTitle() const {
+string16 TaskManagerTabContentsResource::GetTitle() const {
   // Fall back on the URL if there's no title.
   string16 tab_title = tab_contents_->GetTitle();
   if (tab_title.empty()) {
@@ -195,7 +195,7 @@
       extensions_service->IsInstalledApp(tab_contents_->GetURL()),
       tab_contents_->HostsExtension(),
       tab_contents_->profile()->IsOffTheRecord());
-  return UTF16ToWideHack(l10n_util::GetStringFUTF16(message_id, tab_title));
+  return l10n_util::GetStringFUTF16(message_id, tab_title);
 }
 
 SkBitmap TaskManagerTabContentsResource::GetIcon() const {
@@ -234,23 +234,14 @@
     int origin_pid,
     int render_process_host_id,
     int routing_id) {
-
   TabContents* tab_contents =
       tab_util::GetTabContentsByID(render_process_host_id, routing_id);
   if (!tab_contents)  // Not one of our resource.
     return NULL;
 
-  base::ProcessHandle process_handle =
-      tab_contents->GetRenderProcessHost()->GetHandle();
-  if (!process_handle) {
-    // We should not be holding on to a dead tab (it should have been removed
-    // through the NOTIFY_TAB_CONTENTS_DISCONNECTED notification.
-    NOTREACHED();
-    return NULL;
-  }
-
-  int pid = base::GetProcId(process_handle);
-  if (pid != origin_pid)
+  // If an origin PID was specified then the request originated in a plugin
+  // working on the TabContent's behalf, so ignore it.
+  if (origin_pid)
     return NULL;
 
   std::map<TabContents*, TaskManagerTabContentsResource*>::iterator
@@ -392,7 +383,7 @@
 
 TaskManagerBackgroundContentsResource::TaskManagerBackgroundContentsResource(
     BackgroundContents* background_contents,
-    const std::wstring& application_name)
+    const string16& application_name)
     : TaskManagerRendererResource(
           background_contents->render_view_host()->process()->GetHandle(),
           background_contents->render_view_host()),
@@ -413,8 +404,8 @@
     ) {
 }
 
-std::wstring TaskManagerBackgroundContentsResource::GetTitle() const {
-  string16 title = WideToUTF16Hack(application_name_);
+string16 TaskManagerBackgroundContentsResource::GetTitle() const {
+  string16 title = application_name_;
 
   if (title.empty()) {
     // No title (can't locate the parent app for some reason) so just display
@@ -422,8 +413,7 @@
     title = base::i18n::GetDisplayStringInLTRDirectionality(
         UTF8ToUTF16(background_contents_->GetURL().spec()));
   }
-  return UTF16ToWideHack(
-      l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX, title));
+  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX, title);
 }
 
 
@@ -454,19 +444,14 @@
     int origin_pid,
     int render_process_host_id,
     int routing_id) {
-
   BackgroundContents* contents = BackgroundContents::GetBackgroundContentsByID(
       render_process_host_id, routing_id);
   if (!contents)  // This resource no longer exists.
     return NULL;
 
-  base::ProcessHandle process_handle =
-      contents->render_view_host()->process()->GetHandle();
-  if (!process_handle) // Process crashed.
-    return NULL;
-
-  int pid = base::GetProcId(process_handle);
-  if (pid != origin_pid)
+  // If an origin PID was specified, the request is from a plugin, not the
+  // render view host process
+  if (origin_pid)
     return NULL;
 
   std::map<BackgroundContents*,
@@ -495,7 +480,7 @@
         background_contents_service->GetBackgroundContents();
     for (std::vector<BackgroundContents*>::iterator iterator = contents.begin();
          iterator != contents.end(); ++iterator) {
-      std::wstring application_name;
+      string16 application_name;
       // Lookup the name from the parent extension.
       if (extensions_service) {
         const string16& application_id =
@@ -503,7 +488,7 @@
         const Extension* extension = extensions_service->GetExtensionById(
             UTF16ToUTF8(application_id), false);
         if (extension)
-          application_name = UTF8ToWide(extension->name());
+          application_name = UTF8ToUTF16(extension->name());
       }
       Add(*iterator, application_name);
     }
@@ -538,7 +523,7 @@
 
 void TaskManagerBackgroundContentsResourceProvider::AddToTaskManager(
     BackgroundContents* background_contents,
-    const std::wstring& application_name) {
+    const string16& application_name) {
   TaskManagerBackgroundContentsResource* resource =
       new TaskManagerBackgroundContentsResource(background_contents,
                                                 application_name);
@@ -547,7 +532,7 @@
 }
 
 void TaskManagerBackgroundContentsResourceProvider::Add(
-    BackgroundContents* contents, const std::wstring& application_name) {
+    BackgroundContents* contents, const string16& application_name) {
   if (!updating_)
     return;
 
@@ -589,7 +574,7 @@
       // will display the URL instead in this case. This should never happen
       // except in rare cases when an extension is being unloaded or chrome is
       // exiting while the task manager is displayed.
-      std::wstring application_name;
+      string16 application_name;
       ExtensionService* service =
           Source<Profile>(source)->GetExtensionService();
       if (service) {
@@ -599,7 +584,7 @@
             service->GetExtensionById(application_id, false);
         // Extension can be NULL when running unit tests.
         if (extension)
-          application_name = UTF8ToWide(extension->name());
+          application_name = UTF8ToUTF16(extension->name());
       }
       Add(Details<BackgroundContentsOpenedDetails>(details)->contents,
           application_name);
@@ -613,7 +598,7 @@
       // Should never get a NAVIGATED before OPENED.
       DCHECK(resources_.find(contents) != resources_.end());
       // Preserve the application name.
-      std::wstring application_name(
+      string16 application_name(
           resources_.find(contents)->second->application_name());
       Remove(contents);
       Add(contents, application_name);
@@ -643,7 +628,7 @@
       network_usage_support_(false) {
   // We cache the process id because it's not cheap to calculate, and it won't
   // be available when we get the plugin disconnected notification.
-  pid_ = child_proc.id();
+  pid_ = child_proc.pid();
   if (!default_icon_) {
     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
     default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN);
@@ -655,9 +640,9 @@
 }
 
 // TaskManagerResource methods:
-std::wstring TaskManagerChildProcessResource::GetTitle() const {
+string16 TaskManagerChildProcessResource::GetTitle() const {
   if (title_.empty())
-    title_ = UTF16ToWideHack(child_process_.GetLocalizedTitle());
+    title_ = child_process_.GetLocalizedTitle();
 
   return title_;
 }
@@ -886,14 +871,13 @@
 
   int message_id = GetMessagePrefixID(GetExtension()->is_app(), true,
       extension_host_->profile()->IsOffTheRecord());
-  title_ = UTF16ToWideHack(l10n_util::GetStringFUTF16(message_id,
-                                                      extension_name));
+  title_ = l10n_util::GetStringFUTF16(message_id, extension_name);
 }
 
 TaskManagerExtensionProcessResource::~TaskManagerExtensionProcessResource() {
 }
 
-std::wstring TaskManagerExtensionProcessResource::GetTitle() const {
+string16 TaskManagerExtensionProcessResource::GetTitle() const {
   return title_;
 }
 
@@ -1084,15 +1068,14 @@
   }
   process_handle_ = balloon_host_->render_view_host()->process()->GetHandle();
   pid_ = base::GetProcId(process_handle_);
-  title_ = UTF16ToWide(l10n_util::GetStringFUTF16(
-      IDS_TASK_MANAGER_NOTIFICATION_PREFIX,
-      balloon_host_->GetSource()));
+  title_ = l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NOTIFICATION_PREFIX,
+                                      balloon_host_->GetSource());
 }
 
 TaskManagerNotificationResource::~TaskManagerNotificationResource() {
 }
 
-std::wstring TaskManagerNotificationResource::GetTitle() const {
+string16 TaskManagerNotificationResource::GetTitle() const {
   return title_;
 }
 
@@ -1223,8 +1206,8 @@
 
 TaskManagerBrowserProcessResource::TaskManagerBrowserProcessResource()
     : title_() {
-  pid_ = base::GetCurrentProcId();
-  bool success = base::OpenPrivilegedProcessHandle(pid_, &process_);
+  int pid = base::GetCurrentProcId();
+  bool success = base::OpenPrivilegedProcessHandle(pid, &process_);
   DCHECK(success);
 #if defined(OS_WIN)
   if (!default_icon_) {
@@ -1262,10 +1245,9 @@
 }
 
 // TaskManagerResource methods:
-std::wstring TaskManagerBrowserProcessResource::GetTitle() const {
+string16 TaskManagerBrowserProcessResource::GetTitle() const {
   if (title_.empty()) {
-    title_ = UTF16ToWideHack(
-        l10n_util::GetStringUTF16(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT));
+    title_ = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT);
   }
   return title_;
 }
@@ -1316,7 +1298,7 @@
     int origin_pid,
     int render_process_host_id,
     int routing_id) {
-  if (origin_pid != resource_.process_id()) {
+  if (origin_pid || render_process_host_id != -1) {
     return NULL;
   }
 
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.h b/chrome/browser/task_manager/task_manager_resource_providers.h
index b43a2d3..c1ce1eb 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.h
+++ b/chrome/browser/task_manager/task_manager_resource_providers.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,12 +10,13 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "base/process_util.h"
 #include "chrome/browser/task_manager/task_manager.h"
 #include "chrome/common/child_process_info.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
 
 class BackgroundContents;
 class BalloonHost;
@@ -35,13 +36,14 @@
   virtual ~TaskManagerRendererResource();
 
   // TaskManager::Resource methods:
-  virtual base::ProcessHandle GetProcess() const;
-  virtual Type GetType() const;
-  virtual bool ReportsCacheStats() const;
-  virtual WebKit::WebCache::ResourceTypeStats GetWebCoreCacheStats() const;
-  virtual bool ReportsV8MemoryStats() const;
-  virtual size_t GetV8MemoryAllocated() const;
-  virtual size_t GetV8MemoryUsed() const;
+  virtual base::ProcessHandle GetProcess() const OVERRIDE;
+  virtual Type GetType() const OVERRIDE;
+  virtual bool ReportsCacheStats() const OVERRIDE;
+  virtual WebKit::WebCache::ResourceTypeStats GetWebCoreCacheStats() const
+      OVERRIDE;
+  virtual bool ReportsV8MemoryStats() const OVERRIDE;
+  virtual size_t GetV8MemoryAllocated() const OVERRIDE;
+  virtual size_t GetV8MemoryUsed() const OVERRIDE;
 
   // RenderResources always provide the network usage.
   virtual bool SupportNetworkUsage() const;
@@ -81,11 +83,11 @@
   virtual ~TaskManagerTabContentsResource();
 
   // TaskManager::Resource methods:
-  virtual Type GetType() const;
-  virtual std::wstring GetTitle() const;
-  virtual SkBitmap GetIcon() const;
-  virtual TabContents* GetTabContents() const;
-  virtual const Extension* GetExtension() const;
+  virtual Type GetType() const OVERRIDE;
+  virtual string16 GetTitle() const OVERRIDE;
+  virtual SkBitmap GetIcon() const OVERRIDE;
+  virtual TabContents* GetTabContents() const OVERRIDE;
+  virtual const Extension* GetExtension() const OVERRIDE;
 
  private:
   TabContents* tab_contents_;
@@ -139,19 +141,19 @@
  public:
   TaskManagerBackgroundContentsResource(
       BackgroundContents* background_contents,
-      const std::wstring& application_name);
+      const string16& application_name);
   virtual ~TaskManagerBackgroundContentsResource();
 
   // TaskManager::Resource methods:
-  virtual std::wstring GetTitle() const;
-  virtual SkBitmap GetIcon() const;
-  virtual bool IsBackground() const;
+  virtual string16 GetTitle() const OVERRIDE;
+  virtual SkBitmap GetIcon() const OVERRIDE;
+  virtual bool IsBackground() const OVERRIDE;
 
-  const std::wstring& application_name() const { return application_name_; }
+  const string16& application_name() const { return application_name_; }
  private:
   BackgroundContents* background_contents_;
 
-  std::wstring application_name_;
+  string16 application_name_;
 
   // The icon painted for BackgroundContents.
   // TODO(atwilson): Use the favicon when there's a way to get the favicon for
@@ -182,11 +184,11 @@
  private:
   virtual ~TaskManagerBackgroundContentsResourceProvider();
 
-  void Add(BackgroundContents* background_contents, const std::wstring& title);
+  void Add(BackgroundContents* background_contents, const string16& title);
   void Remove(BackgroundContents* background_contents);
 
   void AddToTaskManager(BackgroundContents* background_contents,
-                        const std::wstring& title);
+                        const string16& title);
 
   // Whether we are currently reporting to the task manager. Used to ignore
   // notifications sent after StopUpdating().
@@ -210,13 +212,13 @@
   explicit TaskManagerChildProcessResource(const ChildProcessInfo& child_proc);
   virtual ~TaskManagerChildProcessResource();
 
-  // TaskManagerResource methods:
-  virtual std::wstring GetTitle() const;
-  virtual SkBitmap GetIcon() const;
-  virtual base::ProcessHandle GetProcess() const;
-  virtual Type GetType() const;
-  virtual bool SupportNetworkUsage() const;
-  virtual void SetSupportNetworkUsage();
+  // TaskManager::Resource methods:
+  virtual string16 GetTitle() const OVERRIDE;
+  virtual SkBitmap GetIcon() const OVERRIDE;
+  virtual base::ProcessHandle GetProcess() const OVERRIDE;
+  virtual Type GetType() const OVERRIDE;
+  virtual bool SupportNetworkUsage() const OVERRIDE;
+  virtual void SetSupportNetworkUsage() OVERRIDE;
 
   // Returns the pid of the child process.
   int process_id() const { return pid_; }
@@ -224,7 +226,7 @@
  private:
   ChildProcessInfo child_process_;
   int pid_;
-  mutable std::wstring title_;
+  mutable string16 title_;
   bool network_usage_support_;
 
   // The icon painted for the child processs.
@@ -294,14 +296,14 @@
   explicit TaskManagerExtensionProcessResource(ExtensionHost* extension_host);
   virtual ~TaskManagerExtensionProcessResource();
 
-  // TaskManagerResource methods:
-  virtual std::wstring GetTitle() const;
-  virtual SkBitmap GetIcon() const;
-  virtual base::ProcessHandle GetProcess() const;
-  virtual Type GetType() const;
-  virtual bool SupportNetworkUsage() const;
-  virtual void SetSupportNetworkUsage();
-  virtual const Extension* GetExtension() const;
+  // TaskManager::Resource methods:
+  virtual string16 GetTitle() const OVERRIDE;
+  virtual SkBitmap GetIcon() const OVERRIDE;
+  virtual base::ProcessHandle GetProcess() const OVERRIDE;
+  virtual Type GetType() const OVERRIDE;
+  virtual bool SupportNetworkUsage() const OVERRIDE;
+  virtual void SetSupportNetworkUsage() OVERRIDE;
+  virtual const Extension* GetExtension() const OVERRIDE;
 
   // Returns the pid of the extension process.
   int process_id() const { return pid_; }
@@ -318,7 +320,7 @@
   // Cached data about the extension.
   base::ProcessHandle process_handle_;
   int pid_;
-  std::wstring title_;
+  string16 title_;
 
   DISALLOW_COPY_AND_ASSIGN(TaskManagerExtensionProcessResource);
 };
@@ -370,12 +372,12 @@
   virtual ~TaskManagerNotificationResource();
 
   // TaskManager::Resource interface
-  virtual std::wstring GetTitle() const;
-  virtual SkBitmap GetIcon() const;
-  virtual base::ProcessHandle GetProcess() const;
-  virtual Type GetType() const;
-  virtual bool SupportNetworkUsage() const;
-  virtual void SetSupportNetworkUsage() { }
+  virtual string16 GetTitle() const OVERRIDE;
+  virtual SkBitmap GetIcon() const OVERRIDE;
+  virtual base::ProcessHandle GetProcess() const OVERRIDE;
+  virtual Type GetType() const OVERRIDE;
+  virtual bool SupportNetworkUsage() const OVERRIDE;
+  virtual void SetSupportNetworkUsage() OVERRIDE { }
 
  private:
   // The icon painted for notifications.       .
@@ -387,7 +389,7 @@
   // Cached data about the balloon host.
   base::ProcessHandle process_handle_;
   int pid_;
-  std::wstring title_;
+  string16 title_;
 
   DISALLOW_COPY_AND_ASSIGN(TaskManagerNotificationResource);
 };
@@ -434,25 +436,21 @@
   TaskManagerBrowserProcessResource();
   virtual ~TaskManagerBrowserProcessResource();
 
-  // TaskManagerResource methods:
-  virtual std::wstring GetTitle() const;
-  virtual SkBitmap GetIcon() const;
-  virtual base::ProcessHandle GetProcess() const;
-  virtual Type GetType() const;
+  // TaskManager::Resource methods:
+  virtual string16 GetTitle() const OVERRIDE;
+  virtual SkBitmap GetIcon() const OVERRIDE;
+  virtual base::ProcessHandle GetProcess() const OVERRIDE;
+  virtual Type GetType() const OVERRIDE;
 
-  virtual bool SupportNetworkUsage() const;
-  virtual void SetSupportNetworkUsage();
+  virtual bool SupportNetworkUsage() const OVERRIDE;
+  virtual void SetSupportNetworkUsage() OVERRIDE;
 
-  virtual bool ReportsSqliteMemoryUsed() const;
-  virtual size_t SqliteMemoryUsedBytes() const;
-
-  // Returns the pid of the browser process.
-  int process_id() const { return pid_; }
+  virtual bool ReportsSqliteMemoryUsed() const OVERRIDE;
+  virtual size_t SqliteMemoryUsedBytes() const OVERRIDE;
 
  private:
   base::ProcessHandle process_;
-  int pid_;
-  mutable std::wstring title_;
+  mutable string16 title_;
 
   static SkBitmap* default_icon_;
 
diff --git a/chrome/browser/task_manager/task_manager_unittest.cc b/chrome/browser/task_manager/task_manager_unittest.cc
index 03b5705..d7478a4 100644
--- a/chrome/browser/task_manager/task_manager_unittest.cc
+++ b/chrome/browser/task_manager/task_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/utf_string_conversions.h"
@@ -14,6 +13,7 @@
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -30,7 +30,9 @@
  public:
   TestResource() : refresh_called_(false) {}
 
-  virtual std::wstring GetTitle() const { return L"test title"; }
+  virtual string16 GetTitle() const OVERRIDE {
+    return ASCIIToUTF16("test title");
+  }
   virtual SkBitmap GetIcon() const { return SkBitmap(); }
   virtual base::ProcessHandle GetProcess() const {
     return base::GetCurrentProcessHandle();
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 3ddc0cb..7982e42 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/themes/browser_theme_pack.h"
 
-#include "app/data_pack.h"
-#include "app/resource_bundle.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "base/threading/thread_restrictions.h"
@@ -13,13 +11,15 @@
 #include "base/values.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/skbitmap_operations.h"
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/file_stream.h"
 #include "net/base/net_errors.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/base/resource/data_pack.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/skbitmap_operations.h"
 
 namespace {
 
@@ -298,8 +298,8 @@
 
 // Does error checking for invalid incoming data while trying to read an
 // floating point value.
-bool ValidRealValue(ListValue* tint_list, int index, double* out) {
-  if (tint_list->GetReal(index, out))
+bool ValidDoubleValue(ListValue* tint_list, int index, double* out) {
+  if (tint_list->GetDouble(index, out))
     return true;
 
   int value = 0;
@@ -370,7 +370,7 @@
     FilePath path, const std::string& expected_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   scoped_refptr<BrowserThemePack> pack(new BrowserThemePack);
-  pack->data_pack_.reset(new app::DataPack);
+  pack->data_pack_.reset(new ui::DataPack);
 
   if (!pack->data_pack_->Load(path)) {
     LOG(ERROR) << "Failed to load theme data pack.";
@@ -448,7 +448,7 @@
   RepackImages(prepared_images_, &reencoded_images);
   AddRawImagesTo(reencoded_images, &resources);
 
-  return app::DataPack::WritePack(path, resources);
+  return ui::DataPack::WritePack(path, resources);
 }
 
 bool BrowserThemePack::GetTint(int id, color_utils::HSL* hsl) const {
@@ -583,7 +583,7 @@
   header_->version = kThemePackVersion;
 
   // TODO(erg): Need to make this endian safe on other computers. Prerequisite
-  // is that app::DataPack removes this same check.
+  // is that ui::DataPack removes this same check.
 #if defined(__BYTE_ORDER)
   // Linux check
   COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN,
@@ -619,9 +619,9 @@
         (tint_list->GetSize() == 3)) {
       color_utils::HSL hsl = { -1, -1, -1 };
 
-      if (ValidRealValue(tint_list, 0, &hsl.h) &&
-          ValidRealValue(tint_list, 1, &hsl.s) &&
-          ValidRealValue(tint_list, 2, &hsl.l)) {
+      if (ValidDoubleValue(tint_list, 0, &hsl.h) &&
+          ValidDoubleValue(tint_list, 1, &hsl.s) &&
+          ValidDoubleValue(tint_list, 2, &hsl.l)) {
         int id = GetIntForString(*iter, kTintTable);
         if (id != -1) {
           temp_tints[id] = hsl;
@@ -680,7 +680,7 @@
         if (color_list->GetSize() == 4) {
           double alpha;
           int alpha_int;
-          if (color_list->GetReal(3, &alpha)) {
+          if (color_list->GetDouble(3, &alpha)) {
             color = SkColorSetARGB(static_cast<int>(alpha * 255), r, g, b);
           } else if (color_list->GetInteger(3, &alpha_int) &&
                      (alpha_int == 0 || alpha_int == 1)) {
diff --git a/chrome/browser/themes/browser_theme_pack.h b/chrome/browser/themes/browser_theme_pack.h
index b90f30a..5a9b98a 100644
--- a/chrome/browser/themes/browser_theme_pack.h
+++ b/chrome/browser/themes/browser_theme_pack.h
@@ -12,16 +12,16 @@
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "base/ref_counted.h"
-#include "gfx/color_utils.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/common/extensions/extension.h"
+#include "ui/gfx/color_utils.h"
 
-namespace app {
-class DataPack;
-}
 class DictionaryValue;
 class FilePath;
 class RefCountedMemory;
+namespace ui {
+class DataPack;
+}
 
 // An optimized representation of a theme, backed by a mmapped DataPack.
 //
@@ -170,7 +170,7 @@
   color_utils::HSL GetTintInternal(int id) const;
 
   // Data pack, if we have one.
-  scoped_ptr<app::DataPack> data_pack_;
+  scoped_ptr<ui::DataPack> data_pack_;
 
   // All structs written to disk need to be packed; no alignment tricks here,
   // please.
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index 5d4be22..b36959c 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/themes/browser_theme_provider.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/json_value_serializer.h"
-#include "gfx/color_utils.h"
 #include "grit/theme_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/color_utils.h"
 
 class BrowserThemePackTest : public ::testing::Test {
  public:
diff --git a/chrome/browser/themes/browser_theme_provider.cc b/chrome/browser/themes/browser_theme_provider.cc
index bdd9bf1..87a73aa 100644
--- a/chrome/browser/themes/browser_theme_provider.cc
+++ b/chrome/browser/themes/browser_theme_provider.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/themes/browser_theme_provider.h"
 
-#include "app/resource_bundle.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -18,9 +17,10 @@
 #include "chrome/common/pref_names.h"
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_WIN)
-#include "app/win/hwnd_util.h"
+#include "views/widget/widget_win.h"
 #endif
 
 // Strings used in alignment properties.
@@ -255,7 +255,7 @@
   if (HasCustomImage(IDR_THEME_FRAME))
     return false;
 #if defined(OS_WIN)
-  return app::win::ShouldUseVistaFrame();
+  return views::WidgetWin::IsAeroGlassEnabled();
 #else
   return false;
 #endif
diff --git a/chrome/browser/themes/browser_theme_provider.h b/chrome/browser/themes/browser_theme_provider.h
index e400a1f..fe65a7d 100644
--- a/chrome/browser/themes/browser_theme_provider.h
+++ b/chrome/browser/themes/browser_theme_provider.h
@@ -10,20 +10,24 @@
 #include <set>
 #include <string>
 
-#include "app/theme_provider.h"
 #include "base/ref_counted.h"
 #include "base/threading/non_thread_safe.h"
-
-namespace color_utils {
-  struct HSL;
-}
+#include "ui/base/theme_provider.h"
 
 class BrowserThemePack;
 class BrowserThemeProviderTest;
 class Extension;
 class FilePath;
 class Profile;
+
+namespace color_utils {
+struct HSL;
+}
+
+namespace ui {
 class ResourceBundle;
+}
+using ui::ResourceBundle;
 
 #ifdef __OBJC__
 @class NSString;
@@ -33,7 +37,7 @@
 #endif  // __OBJC__
 
 class BrowserThemeProvider : public base::NonThreadSafe,
-                             public ThemeProvider {
+                             public ui::ThemeProvider {
  public:
   // Public constants used in BrowserThemeProvider and its subclasses:
 
@@ -130,7 +134,7 @@
     REPEAT = 3
   } Tiling;
 
-  // ThemeProvider implementation.
+  // ui::ThemeProvider implementation.
   virtual void Init(Profile* profile);
   virtual SkBitmap* GetBitmapNamed(int id) const;
   virtual SkColor GetColor(int id) const;
diff --git a/chrome/browser/themes/browser_theme_provider_gtk.cc b/chrome/browser/themes/browser_theme_provider_gtk.cc
index a730f3b..52be010 100644
--- a/chrome/browser/themes/browser_theme_provider_gtk.cc
+++ b/chrome/browser/themes/browser_theme_provider_gtk.cc
@@ -8,8 +8,8 @@
 
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
-#include "gfx/gtk_util.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/gtk_util.h"
 
 GdkPixbuf* BrowserThemeProvider::GetPixbufNamed(int id) const {
   return GetPixbufImpl(id, false);
diff --git a/chrome/browser/themes/browser_theme_provider_mac.mm b/chrome/browser/themes/browser_theme_provider_mac.mm
index 0ad2674..887f625 100644
--- a/chrome/browser/themes/browser_theme_provider_mac.mm
+++ b/chrome/browser/themes/browser_theme_provider_mac.mm
@@ -8,9 +8,9 @@
 
 #include "base/logging.h"
 #include "chrome/browser/themes/browser_theme_pack.h"
-#include "gfx/color_utils.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
+#include "ui/gfx/color_utils.h"
 
 NSString* const kBrowserThemeDidChangeNotification =
     @"BrowserThemeDidChangeNotification";
diff --git a/chrome/browser/translate/languages_menu_model.cc b/chrome/browser/translate/languages_menu_model.cc
index e6934b5..22b6be3 100644
--- a/chrome/browser/translate/languages_menu_model.cc
+++ b/chrome/browser/translate/languages_menu_model.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,41 +10,44 @@
 LanguagesMenuModel::LanguagesMenuModel(
     TranslateInfoBarDelegate* translate_delegate,
     LanguageType language_type)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       translate_infobar_delegate_(translate_delegate),
       language_type_(language_type) {
-  for (int i = 0; i < translate_delegate->GetLanguageCount(); ++i)
-    AddCheckItem(i, translate_delegate->GetLanguageDisplayableNameAt(i));
+  for (size_t i = 0; i < translate_delegate->GetLanguageCount(); ++i) {
+    AddCheckItem(static_cast<int>(i),
+                 translate_delegate->GetLanguageDisplayableNameAt(i));
+  }
 }
 
 LanguagesMenuModel::~LanguagesMenuModel() {
 }
 
 bool LanguagesMenuModel::IsCommandIdChecked(int command_id) const {
-  if (language_type_ == ORIGINAL)
-    return command_id == translate_infobar_delegate_->original_language_index();
-  return command_id == translate_infobar_delegate_->target_language_index();
+  return static_cast<size_t>(command_id) == ((language_type_ == ORIGINAL) ?
+      translate_infobar_delegate_->original_language_index() :
+      translate_infobar_delegate_->target_language_index());
 }
 
 bool LanguagesMenuModel::IsCommandIdEnabled(int command_id) const {
-  // Prevent from having the same language selectable in original and target.
-  if (language_type_ == ORIGINAL)
-    return command_id != translate_infobar_delegate_->target_language_index();
-  return command_id != translate_infobar_delegate_->original_language_index();
+  // Prevent the same language from being selectable in original and target.
+  return static_cast<size_t>(command_id) != ((language_type_ == ORIGINAL) ?
+      translate_infobar_delegate_->target_language_index() :
+      translate_infobar_delegate_->original_language_index());
 }
 
 bool LanguagesMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   return false;
 }
 
 void LanguagesMenuModel::ExecuteCommand(int command_id) {
+  size_t command_id_size_t = static_cast<size_t>(command_id);
   if (language_type_ == ORIGINAL) {
     UMA_HISTOGRAM_COUNTS("Translate.ModifyOriginalLang", 1);
-    translate_infobar_delegate_->SetOriginalLanguage(command_id);
+    translate_infobar_delegate_->SetOriginalLanguage(command_id_size_t);
     return;
   }
   UMA_HISTOGRAM_COUNTS("Translate.ModifyTargetLang", 1);
-  translate_infobar_delegate_->SetTargetLanguage(command_id);
+  translate_infobar_delegate_->SetTargetLanguage(command_id_size_t);
 }
diff --git a/chrome/browser/translate/languages_menu_model.h b/chrome/browser/translate/languages_menu_model.h
index 8f91076..74a16a0 100644
--- a/chrome/browser/translate/languages_menu_model.h
+++ b/chrome/browser/translate/languages_menu_model.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_TRANSLATE_LANGUAGES_MENU_MODEL_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class TranslateInfoBarDelegate;
 
 // A menu model that builds the contents of the language menus in the translate
 // infobar. This menu has only one level (no submenus).
-class LanguagesMenuModel : public menus::SimpleMenuModel,
-                           public menus::SimpleMenuModel::Delegate {
+class LanguagesMenuModel : public ui::SimpleMenuModel,
+                           public ui::SimpleMenuModel::Delegate {
  public:
   enum LanguageType {
     ORIGINAL,
@@ -23,11 +23,11 @@
                      LanguageType language_type);
   virtual ~LanguagesMenuModel();
 
-  // menus::SimpleMenuModel::Delegate implementation:
+  // ui::SimpleMenuModel::Delegate implementation:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
  private:
diff --git a/chrome/browser/translate/options_menu_model.cc b/chrome/browser/translate/options_menu_model.cc
index 4a074ce..04278e7 100644
--- a/chrome/browser/translate/options_menu_model.cc
+++ b/chrome/browser/translate/options_menu_model.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/translate/options_menu_model.h"
 
-#include "app/l10n_util.h"
 #include "base/metrics/histogram.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/google/google_util.h"
@@ -13,6 +12,7 @@
 #include "chrome/browser/translate/translate_infobar_delegate.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -27,7 +27,7 @@
 
 OptionsMenuModel::OptionsMenuModel(
     TranslateInfoBarDelegate* translate_delegate)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       translate_infobar_delegate_(translate_delegate) {
   string16 original_language = translate_delegate->GetLanguageDisplayableNameAt(
       translate_delegate->original_language_index());
@@ -94,7 +94,7 @@
 }
 
 bool OptionsMenuModel::GetAcceleratorForCommandId(
-    int command_id, menus::Accelerator* accelerator) {
+    int command_id, ui::Accelerator* accelerator) {
   return false;
 }
 
diff --git a/chrome/browser/translate/options_menu_model.h b/chrome/browser/translate/options_menu_model.h
index 68f9297..83f0f4e 100644
--- a/chrome/browser/translate/options_menu_model.h
+++ b/chrome/browser/translate/options_menu_model.h
@@ -6,23 +6,23 @@
 #define CHROME_BROWSER_TRANSLATE_OPTIONS_MENU_MODEL_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class TranslateInfoBarDelegate;
 
 // A menu model that builds the contents of the options menu in the translate
 // infobar. This menu has only one level (no submenus).
-class OptionsMenuModel : public menus::SimpleMenuModel,
-                         public menus::SimpleMenuModel::Delegate {
+class OptionsMenuModel : public ui::SimpleMenuModel,
+                         public ui::SimpleMenuModel::Delegate {
  public:
   explicit OptionsMenuModel(TranslateInfoBarDelegate* translate_delegate);
   virtual ~OptionsMenuModel();
 
-  // menus::SimpleMenuModel::Delegate implementation:
+  // ui::SimpleMenuModel::Delegate implementation:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
  private:
diff --git a/chrome/browser/translate/translate_infobar_delegate.cc b/chrome/browser/translate/translate_infobar_delegate.cc
index 356975d..0d9b688 100644
--- a/chrome/browser/translate/translate_infobar_delegate.cc
+++ b/chrome/browser/translate/translate_infobar_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/metrics/histogram.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
@@ -17,6 +15,11 @@
 #include "chrome/common/chrome_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+// static
+const size_t TranslateInfoBarDelegate::kNoIndex = static_cast<size_t>(-1);
 
 // static
 TranslateInfoBarDelegate* TranslateInfoBarDelegate::CreateDelegate(
@@ -24,7 +27,7 @@
     TabContents* tab_contents,
     const std::string& original_language,
     const std::string& target_language) {
-  DCHECK(type != TRANSLATION_ERROR);
+  DCHECK_NE(TRANSLATION_ERROR, type);
   // The original language can only be "unknown" for the "translating"
   // infobar, which is the case when the user started a translation from the
   // context menu.
@@ -32,14 +35,12 @@
       original_language != chrome::kUnknownLanguageCode);
   if ((original_language != chrome::kUnknownLanguageCode &&
           !TranslateManager::IsSupportedLanguage(original_language)) ||
-      !TranslateManager::IsSupportedLanguage(target_language)) {
+      !TranslateManager::IsSupportedLanguage(target_language))
     return NULL;
-  }
   TranslateInfoBarDelegate* delegate =
-      new TranslateInfoBarDelegate(type, TranslateErrors::NONE,
-                                   tab_contents,
+      new TranslateInfoBarDelegate(type, TranslateErrors::NONE, tab_contents,
                                    original_language, target_language);
-  DCHECK(delegate->target_language_index() != -1);
+  DCHECK_NE(kNoIndex, delegate->target_language_index());
   return delegate;
 }
 
@@ -52,84 +53,32 @@
                                       original_language, target_language);
 }
 
-TranslateInfoBarDelegate::TranslateInfoBarDelegate(
-    Type type,
-    TranslateErrors::Type error,
-    TabContents* tab_contents,
-    const std::string& original_language,
-    const std::string& target_language)
-    : InfoBarDelegate(tab_contents),
-      type_(type),
-      background_animation_(NONE),
-      tab_contents_(tab_contents),
-      original_language_index_(-1),
-      initial_original_language_index_(-1),
-      target_language_index_(-1),
-      error_(error),
-      infobar_view_(NULL),
-      prefs_(tab_contents_->profile()->GetPrefs()) {
-  DCHECK((type_ != TRANSLATION_ERROR && error == TranslateErrors::NONE) ||
-         (type_ == TRANSLATION_ERROR && error != TranslateErrors::NONE));
-
-  std::vector<std::string> language_codes;
-  TranslateManager::GetSupportedLanguages(&language_codes);
-
-  languages_.reserve(language_codes.size());
-  for (std::vector<std::string>::const_iterator iter = language_codes.begin();
-       iter != language_codes.end(); ++iter) {
-    std::string language_code = *iter;
-
-    string16 language_name = GetLanguageDisplayableName(language_code);
-    // Insert the language in languages_ in alphabetical order.
-    std::vector<LanguageNamePair>::iterator iter2;
-    for (iter2 = languages_.begin(); iter2 != languages_.end(); ++iter2) {
-      if (language_name.compare(iter2->second) < 0)
-        break;
-    }
-    languages_.insert(iter2, LanguageNamePair(language_code, language_name));
-  }
-  for (std::vector<LanguageNamePair>::const_iterator iter = languages_.begin();
-       iter != languages_.end(); ++iter) {
-    std::string language_code = iter->first;
-    if (language_code == original_language) {
-      original_language_index_ = iter - languages_.begin();
-      initial_original_language_index_ = original_language_index_;
-    }
-    if (language_code == target_language)
-      target_language_index_ = iter - languages_.begin();
-  }
+TranslateInfoBarDelegate::~TranslateInfoBarDelegate() {
 }
 
-TranslateInfoBarDelegate::~TranslateInfoBarDelegate() {}
-
-int TranslateInfoBarDelegate::GetLanguageCount() const {
-  return static_cast<int>(languages_.size());
-}
-
-std::string TranslateInfoBarDelegate::GetLanguageCodeAt(
-    int index) const {
-  DCHECK(index >=0 && index < GetLanguageCount());
+std::string TranslateInfoBarDelegate::GetLanguageCodeAt(size_t index) const {
+  DCHECK_LT(index, GetLanguageCount());
   return languages_[index].first;
 }
 
 string16 TranslateInfoBarDelegate::GetLanguageDisplayableNameAt(
-    int index) const {
-  DCHECK(index >=0 && index < GetLanguageCount());
+    size_t index) const {
+  DCHECK_LT(index, GetLanguageCount());
   return languages_[index].second;
 }
 
 std::string TranslateInfoBarDelegate::GetOriginalLanguageCode() const {
-  if (original_language_index() == -1)
-    return chrome::kUnknownLanguageCode;
-  return GetLanguageCodeAt(original_language_index());
+  return (original_language_index() == kNoIndex) ?
+      chrome::kUnknownLanguageCode :
+      GetLanguageCodeAt(original_language_index());
 }
 
 std::string TranslateInfoBarDelegate::GetTargetLanguageCode() const {
   return GetLanguageCodeAt(target_language_index());
 }
 
-void TranslateInfoBarDelegate::SetOriginalLanguage(int language_index) {
-  DCHECK(language_index < static_cast<int>(languages_.size()));
+void TranslateInfoBarDelegate::SetOriginalLanguage(size_t language_index) {
+  DCHECK_LT(language_index, GetLanguageCount());
   original_language_index_ = language_index;
   if (infobar_view_)
     infobar_view_->OriginalLanguageChanged();
@@ -137,8 +86,8 @@
     Translate();
 }
 
-void TranslateInfoBarDelegate::SetTargetLanguage(int language_index) {
-  DCHECK(language_index < static_cast<int>(languages_.size()));
+void TranslateInfoBarDelegate::SetTargetLanguage(size_t language_index) {
+  DCHECK_LT(language_index, GetLanguageCount());
   target_language_index_ = language_index;
   if (infobar_view_)
     infobar_view_->TargetLanguageChanged();
@@ -146,10 +95,6 @@
     Translate();
 }
 
-bool TranslateInfoBarDelegate::IsError() {
-  return type_ == TRANSLATION_ERROR;
-}
-
 void TranslateInfoBarDelegate::Translate() {
   const std::string& original_language_code = GetOriginalLanguageCode();
   if (!tab_contents()->profile()->IsOffTheRecord()) {
@@ -157,8 +102,7 @@
     prefs_.IncrementTranslationAcceptedCount(original_language_code);
   }
 
-  TranslateManager::GetInstance()->TranslatePage(
-      tab_contents_,
+  TranslateManager::GetInstance()->TranslatePage(tab_contents_,
       GetLanguageCodeAt(original_language_index()),
       GetLanguageCodeAt(target_language_index()));
 }
@@ -169,8 +113,7 @@
 }
 
 void TranslateInfoBarDelegate::ReportLanguageDetectionError() {
-  TranslateManager::GetInstance()->
-      ReportLanguageDetectionError(tab_contents_);
+  TranslateManager::GetInstance()->ReportLanguageDetectionError(tab_contents_);
 }
 
 void TranslateInfoBarDelegate::TranslationDeclined() {
@@ -188,34 +131,6 @@
   tab_contents_->language_state().set_translation_declined(true);
 }
 
-void TranslateInfoBarDelegate::InfoBarDismissed() {
-  if (type_ != BEFORE_TRANSLATE)
-    return;
-
-  // The user closed the infobar without clicking the translate button.
-  TranslationDeclined();
-  UMA_HISTOGRAM_COUNTS("Translate.DeclineTranslateCloseInfobar", 1);
-}
-
-void TranslateInfoBarDelegate::InfoBarClosed() {
-  delete this;
-}
-
-SkBitmap* TranslateInfoBarDelegate::GetIcon() const {
-  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-      IDR_INFOBAR_TRANSLATE);
-}
-
-InfoBarDelegate::Type TranslateInfoBarDelegate::GetInfoBarType() {
-  return InfoBarDelegate::PAGE_ACTION_TYPE;
-}
-
-TranslateInfoBarDelegate*
-TranslateInfoBarDelegate::AsTranslateInfoBarDelegate() {
-  return this;
-}
-
-
 bool TranslateInfoBarDelegate::IsLanguageBlacklisted() {
   return prefs_.IsLanguageBlacklisted(GetOriginalLanguageCode());
 }
@@ -278,35 +193,31 @@
 }
 
 string16 TranslateInfoBarDelegate::GetMessageInfoBarText() {
-  switch (type_) {
-    case TRANSLATING:
+  if (type_ == TRANSLATING) {
+    return l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_TRANSLATING_TO,
+        GetLanguageDisplayableNameAt(target_language_index_));
+  }
+
+  DCHECK_EQ(TRANSLATION_ERROR, type_);
+  switch (error_) {
+    case TranslateErrors::NETWORK:
+      return l10n_util::GetStringUTF16(
+          IDS_TRANSLATE_INFOBAR_ERROR_CANT_CONNECT);
+    case TranslateErrors::INITIALIZATION_ERROR:
+    case TranslateErrors::TRANSLATION_ERROR:
+      return l10n_util::GetStringUTF16(
+          IDS_TRANSLATE_INFOBAR_ERROR_CANT_TRANSLATE);
+    case TranslateErrors::UNKNOWN_LANGUAGE:
+      return l10n_util::GetStringUTF16(
+          IDS_TRANSLATE_INFOBAR_UNKNOWN_PAGE_LANGUAGE);
+    case TranslateErrors::UNSUPPORTED_LANGUAGE:
       return l10n_util::GetStringFUTF16(
-          IDS_TRANSLATE_INFOBAR_TRANSLATING_TO,
+          IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE,
           GetLanguageDisplayableNameAt(target_language_index_));
-    case TRANSLATION_ERROR:
-      switch (error_) {
-        case TranslateErrors::NETWORK:
-          return l10n_util::GetStringUTF16(
-              IDS_TRANSLATE_INFOBAR_ERROR_CANT_CONNECT);
-        case TranslateErrors::INITIALIZATION_ERROR:
-        case TranslateErrors::TRANSLATION_ERROR:
-          return l10n_util::GetStringUTF16(
-              IDS_TRANSLATE_INFOBAR_ERROR_CANT_TRANSLATE);
-        case TranslateErrors::UNKNOWN_LANGUAGE:
-          return l10n_util::GetStringUTF16(
-              IDS_TRANSLATE_INFOBAR_UNKNOWN_PAGE_LANGUAGE);
-        case TranslateErrors::UNSUPPORTED_LANGUAGE:
-          return l10n_util::GetStringFUTF16(
-              IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE,
-              GetLanguageDisplayableNameAt(target_language_index_));
-        case TranslateErrors::IDENTICAL_LANGUAGES:
-          return l10n_util::GetStringFUTF16(
-              IDS_TRANSLATE_INFOBAR_ERROR_SAME_LANGUAGE,
-              GetLanguageDisplayableNameAt(target_language_index_));
-        default:
-          NOTREACHED();
-          return string16();
-      }
+    case TranslateErrors::IDENTICAL_LANGUAGES:
+      return l10n_util::GetStringFUTF16(
+          IDS_TRANSLATE_INFOBAR_ERROR_SAME_LANGUAGE,
+          GetLanguageDisplayableNameAt(target_language_index_));
     default:
       NOTREACHED();
       return string16();
@@ -314,33 +225,26 @@
 }
 
 string16 TranslateInfoBarDelegate::GetMessageInfoBarButtonText() {
-  switch (type_) {
-    case TRANSLATING:
-      return string16();
-    case TRANSLATION_ERROR:
-      if (error_ == TranslateErrors::IDENTICAL_LANGUAGES ||
-          error_ == TranslateErrors::UNKNOWN_LANGUAGE) {
-        // No retry button, we would fail again with the same error.
-        return string16();
-      }
-      if (error_ == TranslateErrors::UNSUPPORTED_LANGUAGE)
-        return l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT);
-      return l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_RETRY);
-    default:
-      NOTREACHED();
-      return string16();
+  if (type_ != TRANSLATION_ERROR) {
+    DCHECK_EQ(TRANSLATING, type_);
+  } else if ((error_ != TranslateErrors::IDENTICAL_LANGUAGES) &&
+             (error_ != TranslateErrors::UNKNOWN_LANGUAGE)) {
+    return l10n_util::GetStringUTF16(
+        (error_ == TranslateErrors::UNSUPPORTED_LANGUAGE) ?
+        IDS_TRANSLATE_INFOBAR_REVERT : IDS_TRANSLATE_INFOBAR_RETRY);
   }
+  return string16();
 }
 
 void TranslateInfoBarDelegate::MessageInfoBarButtonPressed() {
-  DCHECK(type_ == TRANSLATION_ERROR);
+  DCHECK_EQ(TRANSLATION_ERROR, type_);
   if (error_ == TranslateErrors::UNSUPPORTED_LANGUAGE) {
     RevertTranslation();
     return;
   }
   // This is the "Try again..." case.
-  TranslateManager::GetInstance()->TranslatePage(
-      tab_contents_, GetOriginalLanguageCode(), GetTargetLanguageCode());
+  TranslateManager::GetInstance()->TranslatePage(tab_contents_,
+      GetOriginalLanguageCode(), GetTargetLanguageCode());
 }
 
 bool TranslateInfoBarDelegate::ShouldShowMessageInfoBarButton() {
@@ -348,31 +252,23 @@
 }
 
 bool TranslateInfoBarDelegate::ShouldShowNeverTranslateButton() {
-  DCHECK(type_ == BEFORE_TRANSLATE);
-  if (tab_contents()->profile()->IsOffTheRecord())
-    return false;
-  return prefs_.GetTranslationDeniedCount(GetOriginalLanguageCode()) >= 3;
+  DCHECK_EQ(BEFORE_TRANSLATE, type_);
+  return !tab_contents()->profile()->IsOffTheRecord() &&
+      (prefs_.GetTranslationDeniedCount(GetOriginalLanguageCode()) >= 3);
 }
 
 bool TranslateInfoBarDelegate::ShouldShowAlwaysTranslateButton() {
-  DCHECK(type_ == BEFORE_TRANSLATE);
-  if (tab_contents()->profile()->IsOffTheRecord())
-    return false;
-  return prefs_.GetTranslationAcceptedCount(GetOriginalLanguageCode()) >= 3;
+  DCHECK_EQ(BEFORE_TRANSLATE, type_);
+  return !tab_contents()->profile()->IsOffTheRecord() &&
+      (prefs_.GetTranslationAcceptedCount(GetOriginalLanguageCode()) >= 3);
 }
 
 void TranslateInfoBarDelegate::UpdateBackgroundAnimation(
     TranslateInfoBarDelegate* previous_infobar) {
-  if (!previous_infobar || previous_infobar->IsError() == IsError()) {
+  if (!previous_infobar || previous_infobar->IsError() == IsError())
     background_animation_ = NONE;
-    return;
-  }
-  background_animation_ = IsError() ? NORMAL_TO_ERROR: ERROR_TO_NORMAL;
-}
-
-std::string TranslateInfoBarDelegate::GetPageHost() {
-  NavigationEntry* entry = tab_contents_->controller().GetActiveEntry();
-  return entry ? entry->url().HostNoBrackets() : std::string();
+  else
+    background_animation_ = IsError() ? NORMAL_TO_ERROR : ERROR_TO_NORMAL;
 }
 
 // static
@@ -392,17 +288,92 @@
   string16 text =
       l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE,
                                  string16(), string16(), &offsets);
-  DCHECK(offsets.size() == 2U);
+  DCHECK_EQ(2U, offsets.size());
 
-  if (offsets[0] > offsets[1]) {
-    // Target language comes before source.
+  *swap_languages = (offsets[0] > offsets[1]);
+  if (*swap_languages)
     std::swap(offsets[0], offsets[1]);
-    *swap_languages = true;
-  } else {
-    *swap_languages = false;
-  }
 
   strings->push_back(text.substr(0, offsets[0]));
   strings->push_back(text.substr(offsets[0], offsets[1] - offsets[0]));
   strings->push_back(text.substr(offsets[1]));
 }
+
+TranslateInfoBarDelegate::TranslateInfoBarDelegate(
+    Type type,
+    TranslateErrors::Type error,
+    TabContents* tab_contents,
+    const std::string& original_language,
+    const std::string& target_language)
+    : InfoBarDelegate(tab_contents),
+      type_(type),
+      background_animation_(NONE),
+      tab_contents_(tab_contents),
+      original_language_index_(kNoIndex),
+      initial_original_language_index_(kNoIndex),
+      target_language_index_(kNoIndex),
+      error_(error),
+      infobar_view_(NULL),
+      prefs_(tab_contents_->profile()->GetPrefs()) {
+  DCHECK_NE((type_ == TRANSLATION_ERROR), (error == TranslateErrors::NONE));
+
+  std::vector<std::string> language_codes;
+  TranslateManager::GetSupportedLanguages(&language_codes);
+
+  languages_.reserve(language_codes.size());
+  for (std::vector<std::string>::const_iterator iter = language_codes.begin();
+       iter != language_codes.end(); ++iter) {
+    std::string language_code = *iter;
+
+    string16 language_name = GetLanguageDisplayableName(language_code);
+    // Insert the language in languages_ in alphabetical order.
+    std::vector<LanguageNamePair>::iterator iter2;
+    for (iter2 = languages_.begin(); iter2 != languages_.end(); ++iter2) {
+      if (language_name.compare(iter2->second) < 0)
+        break;
+    }
+    languages_.insert(iter2, LanguageNamePair(language_code, language_name));
+  }
+  for (std::vector<LanguageNamePair>::const_iterator iter = languages_.begin();
+       iter != languages_.end(); ++iter) {
+    std::string language_code = iter->first;
+    if (language_code == original_language) {
+      original_language_index_ = iter - languages_.begin();
+      initial_original_language_index_ = original_language_index_;
+    }
+    if (language_code == target_language)
+      target_language_index_ = iter - languages_.begin();
+  }
+}
+
+void TranslateInfoBarDelegate::InfoBarDismissed() {
+  if (type_ != BEFORE_TRANSLATE)
+    return;
+
+  // The user closed the infobar without clicking the translate button.
+  TranslationDeclined();
+  UMA_HISTOGRAM_COUNTS("Translate.DeclineTranslateCloseInfobar", 1);
+}
+
+void TranslateInfoBarDelegate::InfoBarClosed() {
+  delete this;
+}
+
+SkBitmap* TranslateInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_TRANSLATE);
+}
+
+InfoBarDelegate::Type TranslateInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+TranslateInfoBarDelegate*
+    TranslateInfoBarDelegate::AsTranslateInfoBarDelegate() {
+  return this;
+}
+
+std::string TranslateInfoBarDelegate::GetPageHost() {
+  NavigationEntry* entry = tab_contents_->controller().GetActiveEntry();
+  return entry ? entry->url().HostNoBrackets() : std::string();
+}
diff --git a/chrome/browser/translate/translate_infobar_delegate.h b/chrome/browser/translate/translate_infobar_delegate.h
index 549af3d..5dd2e73 100644
--- a/chrome/browser/translate/translate_infobar_delegate.h
+++ b/chrome/browser/translate/translate_infobar_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -33,6 +33,8 @@
     ERROR_TO_NORMAL
   };
 
+  static const size_t kNoIndex;
+
   // Factory method to create a non-error translate infobar.
   // The original and target language specified are the ASCII language codes
   // (ex: en, fr...).
@@ -54,13 +56,13 @@
   virtual ~TranslateInfoBarDelegate();
 
   // Returns the number of languages supported.
-  int GetLanguageCount() const;
+  size_t GetLanguageCount() const { return languages_.size(); }
 
   // Returns the ISO code for the language at |index|.
-  std::string GetLanguageCodeAt(int index) const;
+  std::string GetLanguageCodeAt(size_t index) const;
 
   // Returns the displayable name for the language at |index|.
-  string16 GetLanguageDisplayableNameAt(int index) const;
+  string16 GetLanguageDisplayableNameAt(size_t index) const;
 
   TabContents* tab_contents() const { return tab_contents_; }
 
@@ -68,8 +70,8 @@
 
   TranslateErrors::Type error() const { return error_; }
 
-  int original_language_index() const { return original_language_index_; }
-  int target_language_index() const { return target_language_index_; }
+  size_t original_language_index() const { return original_language_index_; }
+  size_t target_language_index() const { return target_language_index_; }
 
   // Convenience methods.
   std::string GetOriginalLanguageCode() const;
@@ -77,12 +79,12 @@
 
   // Called by the InfoBar to notify that the original/target language has
   // changed and is now the language at |language_index|.
-  virtual void SetOriginalLanguage(int language_index);
-  virtual void SetTargetLanguage(int language_index);
+  virtual void SetOriginalLanguage(size_t language_index);
+  virtual void SetTargetLanguage(size_t language_index);
 
   // Returns true if the current infobar indicates an error (in which case it
   // should get a yellow background instead of a blue one).
-  bool IsError();
+  bool IsError() const { return type_ == TRANSLATION_ERROR; }
 
   // Returns what kind of background fading effect the infobar should use when
   // its is shown.
@@ -98,14 +100,6 @@
   // infobar or pressing the "Don't translate" button.
   void TranslationDeclined();
 
-  // InfoBarDelegate implementation:
-  virtual InfoBar* CreateInfoBar();
-  virtual void InfoBarDismissed();
-  virtual void InfoBarClosed();
-  virtual SkBitmap* GetIcon() const;
-  virtual InfoBarDelegate::Type GetInfoBarType();
-  virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
-
   // Methods called by the Options menu delegate.
   virtual bool IsLanguageBlacklisted();
   virtual void ToggleLanguageBlacklist();
@@ -164,6 +158,14 @@
  private:
   typedef std::pair<std::string, string16> LanguageNamePair;
 
+  // InfoBarDelegate:
+  virtual InfoBar* CreateInfoBar();
+  virtual void InfoBarDismissed();
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual InfoBarDelegate::Type GetInfoBarType() const;
+  virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
+
   // Gets the host of the page being translated, or an empty string if no URL is
   // associated with the current page.
   std::string GetPageHost();
@@ -181,17 +183,17 @@
   std::vector<LanguageNamePair> languages_;
 
   // The index for language the page is originally in.
-  int original_language_index_;
+  size_t original_language_index_;
 
   // The index for language the page is originally in that was originally
   // reported (original_language_index_ changes if the user selects a new
   // original language, but this one does not).  This is necessary to report
   // language detection errors with the right original language even if the user
   // changed the original language.
-  int initial_original_language_index_;
+  size_t initial_original_language_index_;
 
   // The index for language the page should be translated to.
-  int target_language_index_;
+  size_t target_language_index_;
 
   // The error that occurred when trying to translate (NONE if no error).
   TranslateErrors::Type error_;
diff --git a/chrome/browser/translate/translate_infobar_view.h b/chrome/browser/translate/translate_infobar_view.h
index 2b4af28..e9b282f 100644
--- a/chrome/browser/translate/translate_infobar_view.h
+++ b/chrome/browser/translate/translate_infobar_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,8 +10,8 @@
 // sense) of the TranslateInfoBarDelegate (which is the model).
 class TranslateInfoBarView {
  public:
-  virtual void OriginalLanguageChanged() = 0;
-  virtual void TargetLanguageChanged() = 0;
+  virtual void OriginalLanguageChanged() {}
+  virtual void TargetLanguageChanged() {}
 
  protected:
   virtual ~TranslateInfoBarView() {}
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
index 84b576e..9146f3d 100644
--- a/chrome/browser/translate/translate_manager.cc
+++ b/chrome/browser/translate/translate_manager.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/translate/translate_manager.h"
 
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/metrics/histogram.h"
 #include "base/singleton.h"
 #include "base/string_split.h"
 #include "base/string_util.h"
+#include "chrome/browser/autofill/autofill_manager.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_service.h"
@@ -33,11 +33,13 @@
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/common/translate_errors.h"
 #include "chrome/common/url_constants.h"
 #include "grit/browser_resources.h"
 #include "net/base/escape.h"
 #include "net/url_request/url_request_status.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -279,7 +281,7 @@
 
 void TranslateManager::OnURLFetchComplete(const URLFetcher* source,
                                           const GURL& url,
-                                          const URLRequestStatus& status,
+                                          const net::URLRequestStatus& status,
                                           int response_code,
                                           const ResponseCookies& cookies,
                                           const std::string& data) {
@@ -287,7 +289,8 @@
   DCHECK(translate_script_request_pending_);
   translate_script_request_pending_ = false;
   bool error =
-      (status.status() != URLRequestStatus::SUCCESS || response_code != 200);
+      (status.status() != net::URLRequestStatus::SUCCESS ||
+       response_code != 200);
 
   if (!error) {
     base::StringPiece str = ResourceBundle::GetSharedInstance().
@@ -352,7 +355,7 @@
 
 void TranslateManager::InitiateTranslation(TabContents* tab,
                                            const std::string& page_lang) {
-  PrefService* prefs = tab->profile()->GetPrefs();
+  PrefService* prefs = tab->profile()->GetOriginalProfile()->GetPrefs();
   if (!prefs->GetBoolean(prefs::kEnableTranslate))
     return;
 
@@ -412,8 +415,7 @@
 
   // Prompts the user if he/she wants the page translated.
   tab->AddInfoBar(TranslateInfoBarDelegate::CreateDelegate(
-      TranslateInfoBarDelegate::BEFORE_TRANSLATE, tab,
-      page_lang, target_lang));
+      TranslateInfoBarDelegate::BEFORE_TRANSLATE, tab, page_lang, target_lang));
 }
 
 void TranslateManager::InitiateTranslationPosted(
@@ -471,7 +473,8 @@
     NOTREACHED();
     return;
   }
-  tab_contents->render_view_host()->RevertTranslation(entry->page_id());
+  tab_contents->render_view_host()->Send(new ViewMsg_RevertTranslation(
+      tab_contents->render_view_host()->routing_id(), entry->page_id()));
   tab_contents->language_state().set_current_language(
       tab_contents->language_state().original_language());
 }
@@ -508,8 +511,16 @@
   }
 
   tab->language_state().set_translation_pending(true);
-  tab->render_view_host()->TranslatePage(entry->page_id(), translate_script,
-                                         source_lang, target_lang);
+
+  tab->render_view_host()->Send(new ViewMsg_TranslatePage(
+      tab->render_view_host()->routing_id(), entry->page_id(), translate_script,
+      source_lang, target_lang));
+
+  // Ideally we'd have a better way to uniquely identify form control elements,
+  // but we don't have that yet.  So before start translation, we clear the
+  // current form and re-parse it in AutoFillManager first to get the new
+  // labels.
+  tab->autofill_manager()->Reset();
 }
 
 void TranslateManager::PageTranslated(TabContents* tab,
@@ -517,9 +528,8 @@
   // Create the new infobar to display.
   TranslateInfoBarDelegate* infobar;
   if (details->error_type != TranslateErrors::NONE) {
-    infobar = TranslateInfoBarDelegate::CreateErrorDelegate(
-        details->error_type, tab,
-        details->source_language, details->target_language);
+    infobar = TranslateInfoBarDelegate::CreateErrorDelegate(details->error_type,
+        tab, details->source_language, details->target_language);
   } else if (!IsSupportedLanguage(details->source_language)) {
     // TODO(jcivelli): http://crbug.com/9390 We should change the "after
     //                 translate" infobar to support unknown as the original
@@ -538,7 +548,7 @@
 
 bool TranslateManager::IsAcceptLanguage(TabContents* tab,
                                         const std::string& language) {
-  PrefService* pref_service = tab->profile()->GetPrefs();
+  PrefService* pref_service = tab->profile()->GetOriginalProfile()->GetPrefs();
   PrefServiceLanguagesMap::const_iterator iter =
       accept_languages_.find(pref_service);
   if (iter == accept_languages_.end()) {
@@ -615,15 +625,13 @@
 std::string TranslateManager::GetTargetLanguage() {
   std::string target_lang =
       GetLanguageCode(g_browser_process->GetApplicationLocale());
-  if (IsSupportedLanguage(target_lang))
-    return target_lang;
-  return std::string();
+  return IsSupportedLanguage(target_lang) ? target_lang : std::string();
 }
 
 // static
 TranslateInfoBarDelegate* TranslateManager::GetTranslateInfoBarDelegate(
     TabContents* tab) {
-  for (int i = 0; i < tab->infobar_delegate_count(); ++i) {
+  for (size_t i = 0; i < tab->infobar_count(); ++i) {
     TranslateInfoBarDelegate* delegate =
         tab->GetInfoBarDelegateAt(i)->AsTranslateInfoBarDelegate();
     if (delegate)
diff --git a/chrome/browser/translate/translate_manager_unittest.cc b/chrome/browser/translate/translate_manager_unittest.cc
index 89cc355..d093b38 100644
--- a/chrome/browser/translate/translate_manager_unittest.cc
+++ b/chrome/browser/translate/translate_manager_unittest.cc
@@ -1,9 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/renderer_host/test/test_render_view_host.h"
 
+#include <set>
+
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/prefs/pref_service.h"
@@ -15,7 +17,6 @@
 #include "chrome/browser/translate/translate_infobar_delegate.h"
 #include "chrome/browser/translate/translate_manager.h"
 #include "chrome/browser/translate/translate_prefs.h"
-#include "chrome/common/ipc_test_sink.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer_mock.h"
 #include "chrome/common/notification_registrar.h"
@@ -26,9 +27,10 @@
 #include "chrome/test/testing_browser_process.h"
 #include "chrome/test/testing_profile.h"
 #include "grit/generated_resources.h"
+#include "ipc/ipc_test_sink.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/cld/languages/public/languages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
 
 using testing::_;
 using testing::Pointee;
@@ -84,15 +86,15 @@
   // Returns the translate infobar if there is 1 infobar and it is a translate
   // infobar.
   TranslateInfoBarDelegate* GetTranslateInfoBar() {
-    if (contents()->infobar_delegate_count() != 1)
-      return NULL;
-    return contents()->GetInfoBarDelegateAt(0)->AsTranslateInfoBarDelegate();
+    return (contents()->infobar_count() == 1) ?
+        contents()->GetInfoBarDelegateAt(0)->AsTranslateInfoBarDelegate() :
+        NULL;
   }
 
   // If there is 1 infobar and it is a translate infobar, closes it and returns
   // true.  Returns false otherwise.
   bool CloseTranslateInfoBar() {
-    TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
+    InfoBarDelegate* infobar = GetTranslateInfoBar();
     if (!infobar)
       return false;
     infobar->InfoBarDismissed();  // Simulates closing the infobar.
@@ -102,9 +104,8 @@
 
   // Checks whether |infobar| has been removed and clears the removed infobar
   // list.
-  bool CheckInfoBarRemovedAndReset(InfoBarDelegate* infobar) {
-    bool found = std::find(removed_infobars_.begin(), removed_infobars_.end(),
-                           infobar) != removed_infobars_.end();
+  bool CheckInfoBarRemovedAndReset(InfoBarDelegate* delegate) {
+    bool found = removed_infobars_.count(delegate) != 0;
     removed_infobars_.clear();
     return found;
   }
@@ -137,8 +138,8 @@
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details) {
-    DCHECK(type == NotificationType::TAB_CONTENTS_INFOBAR_REMOVED);
-    removed_infobars_.push_back(Details<InfoBarDelegate>(details).ptr());
+    DCHECK_EQ(NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, type.value);
+    removed_infobars_.insert(Details<InfoBarDelegate>(details).ptr());
   }
 
  protected:
@@ -159,8 +160,7 @@
 
     RenderViewHostTestHarness::SetUp();
 
-    notification_registrar_.Add(
-        this,
+    notification_registrar_.Add(this,
         NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
         Source<TabContents>(contents()));
   }
@@ -168,8 +168,7 @@
   virtual void TearDown() {
     process()->sink().ClearMessages();
 
-    notification_registrar_.Remove(
-        this,
+    notification_registrar_.Remove(this,
         NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
         Source<TabContents>(contents()));
 
@@ -181,9 +180,9 @@
   void SimulateURLFetch(bool success) {
     TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
     ASSERT_TRUE(fetcher);
-    URLRequestStatus status;
-    status.set_status(success ? URLRequestStatus::SUCCESS :
-                                URLRequestStatus::FAILED);
+    net::URLRequestStatus status;
+    status.set_status(success ? net::URLRequestStatus::SUCCESS :
+                                net::URLRequestStatus::FAILED);
     fetcher->delegate()->OnURLFetchComplete(fetcher, fetcher->original_url(),
                                             status, success ? 200 : 500,
                                             ResponseCookies(),
@@ -204,9 +203,9 @@
   NotificationRegistrar notification_registrar_;
   TestURLFetcherFactory url_fetcher_factory_;
 
-  // The list of infobars that have been removed.
-  // WARNING: the pointers points to deleted objects, use only for comparison.
-  std::vector<InfoBarDelegate*> removed_infobars_;
+  // The infobars that have been removed.
+  // WARNING: the pointers point to deleted objects, use only for comparison.
+  std::set<InfoBarDelegate*> removed_infobars_;
 
   DISALLOW_COPY_AND_ASSIGN(TranslateManagerTest);
 };
@@ -268,7 +267,7 @@
   virtual void PlatformInit() { }
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) { return false; }
+      ui::Accelerator* accelerator) { return false; }
 
  private:
   TestRenderViewContextMenu(TabContents* tab_contents,
@@ -546,21 +545,21 @@
 
   // Simulate clicking 'Nope' (don't translate).
   EXPECT_TRUE(DenyTranslation());
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
 
   // Send a new PageContents, we should not show an infobar.
   SimulateOnPageContents(GURL("http://www.google.fr"), 0, "Le Google", "fr",
                          true);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
 
   // Do the same steps but simulate closing the infobar this time.
   SimulateNavigation(GURL("http://www.youtube.fr"), "Le YouTube", "fr",
                      true);
   EXPECT_TRUE(CloseTranslateInfoBar());
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
   SimulateOnPageContents(GURL("http://www.youtube.fr"), 1, "Le YouTube", "fr",
                          true);
-  EXPECT_EQ(0, contents()->infobar_delegate_count());
+  EXPECT_EQ(0U, contents()->infobar_count());
 }
 
 // Test that reloading the page brings back the infobar.
diff --git a/chrome/browser/transport_security_persister.h b/chrome/browser/transport_security_persister.h
index 7db6b58..0073ea4 100644
--- a/chrome/browser/transport_security_persister.h
+++ b/chrome/browser/transport_security_persister.h
@@ -35,7 +35,6 @@
 #pragma once
 
 #include "base/file_path.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
 #include "base/task.h"
 #include "net/base/transport_security_state.h"
diff --git a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h
index ddc1808..93a80db 100644
--- a/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h
+++ b/chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h
@@ -10,8 +10,6 @@
 
 #include "base/basictypes.h"
 #include "build/build_config.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
 
 class NativeAppModalDialog;
 class TabContents;
diff --git a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc
index 801562d..6df8d16 100644
--- a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc
+++ b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
 
-#include "app/text_elider.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_shutdown.h"
@@ -14,6 +13,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "ipc/ipc_message.h"
+#include "ui/base/text/text_elider.h"
 
 namespace {
 
@@ -43,11 +43,11 @@
   // We trim the various parts of the message dialog because otherwise we can
   // overflow the message dialog (and crash/hang the GTK+ version).
   string16 elided_text;
-  gfx::ElideRectangleString(WideToUTF16(message_text),
-       kMessageTextMaxRows, kMessageTextMaxCols, &elided_text);
+  ui::ElideRectangleString(WideToUTF16(message_text),
+      kMessageTextMaxRows, kMessageTextMaxCols, &elided_text);
   message_text_ = UTF16ToWide(elided_text);
-  gfx::ElideString(default_prompt_text, kDefaultPromptTextSize,
-                   &default_prompt_text_);
+  ui::ElideString(default_prompt_text, kDefaultPromptTextSize,
+                  &default_prompt_text_);
 
   DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL));
   InitNotifications();
diff --git a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h
index 10615eb..0bd8a4b 100644
--- a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h
+++ b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class ExtensionHost;
 class NativeAppModalDialog;
diff --git a/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc b/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc
index bdf7d42..11cc982 100644
--- a/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc
+++ b/chrome/browser/ui/app_modal_dialogs/message_box_handler.cc
@@ -4,9 +4,6 @@
 
 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
-#include "app/text_elider.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -17,10 +14,13 @@
 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/font.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/chromium_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/font.h"
 
 static std::wstring GetTitle(Profile* profile,
                              bool is_alert,
@@ -46,7 +46,7 @@
 
   // TODO(brettw) it should be easier than this to do the correct language
   // handling without getting the accept language from the profile.
-  string16 base_address = gfx::ElideUrl(frame_url.GetOrigin(),
+  string16 base_address = ui::ElideUrl(frame_url.GetOrigin(),
       gfx::Font(), 0,
       UTF8ToWide(profile->GetPrefs()->GetString(prefs::kAcceptLanguages)));
 
@@ -68,7 +68,7 @@
                              const std::wstring& default_prompt_text,
                              bool display_suppress_checkbox,
                              IPC::Message* reply_msg) {
-  bool is_alert = dialog_flags == MessageBoxFlags::kIsJavascriptAlert;
+  bool is_alert = dialog_flags == ui::MessageBoxFlags::kIsJavascriptAlert;
   std::wstring title = GetTitle(profile, is_alert, frame_url);
   AppModalDialogQueue::GetInstance()->AddDialog(new JavaScriptAppModalDialog(
       delegate, title, dialog_flags, message_text, default_prompt_text,
@@ -84,7 +84,7 @@
       tab_contents,
       UTF16ToWideHack(
           l10n_util::GetStringUTF16(IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE)),
-      MessageBoxFlags::kIsJavascriptConfirm,
+      ui::MessageBoxFlags::kIsJavascriptConfirm,
       message_text,
       std::wstring(),
       false,
diff --git a/chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h b/chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h
index 36701fb..c97f5ad 100644
--- a/chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h
+++ b/chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_APP_MODAL_DIALOGS_NATIVE_APP_MODAL_DIALOG_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class JavaScriptAppModalDialog;
 
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index cdaf933..26d36c5 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,7 +12,6 @@
 #include <algorithm>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/logging.h"
@@ -22,7 +21,6 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/point.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autofill/autofill_manager.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -36,6 +34,7 @@
 #include "chrome/browser/debugger/devtools_manager.h"
 #include "chrome/browser/debugger/devtools_toggle_action.h"
 #include "chrome/browser/debugger/devtools_window.h"
+#include "chrome/browser/dom_ui/bug_report_ui.h"
 #include "chrome/browser/dom_ui/filebrowse_ui.h"
 #include "chrome/browser/dom_ui/options/content_settings_handler.h"
 #include "chrome/browser/download/download_item.h"
@@ -81,6 +80,7 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/options/options_window.h"
 #include "chrome/browser/ui/status_bubble.h"
@@ -97,6 +97,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/page_transition_types.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/profiling.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/web_apps.h"
 #include "grit/chromium_strings.h"
@@ -108,6 +109,8 @@
 #include "net/base/static_cookie_policy.h"
 #include "net/url_request/url_request_context.h"
 #include "ui/base/animation/animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/point.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -129,7 +132,6 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/boot_times_loader.h"
-#include "chrome/browser/chromeos/options/language_config_view.h"
 #endif
 
 using base::TimeDelta;
@@ -139,13 +141,14 @@
 namespace {
 
 // The URL to be loaded to display Help.
+const char kHelpContentUrl[] =
 #if defined(OS_CHROMEOS)
-const char kHelpContentUrl[] =
-    "chrome-extension://oonnajkebngbfpmcpekfdeofeannbapp/main.html";
-const char kHelpContentOnlineUrl[] =
-    "http://www.google.com/support/chromeos/";
+  #if defined(OFFICIAL_BUILD)
+      "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html";
+  #else
+      "http://www.google.com/support/chromeos/";
+  #endif
 #else
-const char kHelpContentUrl[] =
     "http://www.google.com/support/chrome/";
 #endif
 
@@ -220,11 +223,15 @@
   registrar_.Add(this, NotificationType::EXTENSION_READY_FOR_INSTALL,
                  NotificationService::AllSources());
 
+  // NOTE: These prefs all need to be explicitly destroyed in the destructor
+  // or you'll get a nasty surprise when you run the incognito tests.
   PrefService* local_state = g_browser_process->local_state();
   if (local_state)
     printing_enabled_.Init(prefs::kPrintingEnabled, local_state, this);
   dev_tools_disabled_.Init(prefs::kDevToolsDisabled,
                            profile_->GetPrefs(), this);
+  incognito_mode_allowed_.Init(prefs::kIncognitoEnabled,
+                               profile_->GetPrefs(), this);
 
   InitCommandState();
   BrowserList::AddBrowser(this);
@@ -285,6 +292,13 @@
   if (tab_restore_service)
     tab_restore_service->BrowserClosed(this);
 
+  encoding_auto_detect_.Destroy();
+  printing_enabled_.Destroy();
+  dev_tools_disabled_.Destroy();
+  incognito_mode_allowed_.Destroy();
+  instant_enabled_.Destroy();
+  use_vertical_tabs_.Destroy();
+
   if (profile_->IsOffTheRecord() &&
       !BrowserList::IsOffTheRecordSessionActive()) {
     // An off-the-record profile is no longer needed, this indirectly
@@ -437,7 +451,7 @@
     FindBar* find_bar = BrowserWindow::CreateFindBar(this);
     find_bar_controller_.reset(new FindBarController(find_bar));
     find_bar->SetFindBarController(find_bar_controller_.get());
-    find_bar_controller_->ChangeTabContents(GetSelectedTabContents());
+    find_bar_controller_->ChangeTabContents(GetSelectedTabContentsWrapper());
     find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
   }
   return find_bar_controller_.get();
@@ -536,9 +550,14 @@
     url = extension->GetFullLaunchURL();
   }
 
-  // TODO(erikkay) this can't be correct for extensions
-  std::string app_name = web_app::GenerateApplicationNameFromURL(url);
-  RegisterAppPrefs(app_name);
+  std::string app_name;
+  if (extension)
+    app_name =
+        web_app::GenerateApplicationNameFromExtensionId(extension->id());
+  else
+    app_name = web_app::GenerateApplicationNameFromURL(url);
+
+  RegisterAppPrefs(app_name, profile);
 
   bool as_panel = extension && (container == extension_misc::LAUNCH_PANEL);
 
@@ -595,9 +614,10 @@
 TabContents* Browser::OpenApplicationTab(Profile* profile,
                                          const Extension* extension,
                                          TabContents* existing_tab) {
-  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
+  Browser* browser =
+      BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false);
   TabContents* contents = NULL;
-  if (!browser || browser->type() != Browser::TYPE_NORMAL)
+  if (!browser)
     return contents;
 
   // Check the prefs for overridden mode.
@@ -606,15 +626,23 @@
 
   ExtensionPrefs::LaunchType launch_type =
       extensions_service->extension_prefs()->GetLaunchType(
-          extension->id(), ExtensionPrefs::LAUNCH_REGULAR);
+          extension->id(), ExtensionPrefs::LAUNCH_DEFAULT);
   UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", launch_type, 100);
   int add_type = TabStripModel::ADD_SELECTED;
   if (launch_type == ExtensionPrefs::LAUNCH_PINNED)
     add_type |= TabStripModel::ADD_PINNED;
 
+  // For extensions lacking launch urls, determine a reasonable fallback.
+  GURL extension_url = extension->GetFullLaunchURL();
+  if (!extension_url.is_valid()) {
+    extension_url = extension->options_url();
+    if (!extension_url.is_valid())
+      extension_url = GURL(chrome::kChromeUIExtensionsURL);
+  }
+
   // TODO(erikkay): START_PAGE doesn't seem like the right transition in all
   // cases.
-  browser::NavigateParams params(browser, extension->GetFullLaunchURL(),
+  browser::NavigateParams params(browser, extension_url,
                                  PageTransition::START_PAGE);
   params.tabstrip_add_types = add_type;
 
@@ -639,8 +667,13 @@
     contents = params.target_contents->tab_contents();
   }
 
-  if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN)
-    browser->window()->SetFullscreen(true);
+  // TODO(skerner):  If we are already in full screen mode, and the user
+  // set the app to open as a regular or pinned tab, what should happen?
+  // Today we open the tab, but stay in full screen mode.  Should we leave
+  // full screen mode in this case?
+  if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN &&
+      !browser->window()->IsFullscreen())
+    browser->ToggleFullscreenMode();
 
   return contents;
 }
@@ -680,6 +713,20 @@
   browser->ShowOptionsTab(chrome::kDefaultOptionsSubPage);
   browser->window()->Show();
 }
+
+// static
+void Browser::OpenClearBrowingDataDialogWindow(Profile* profile) {
+  Browser* browser = Browser::Create(profile);
+  browser->OpenClearBrowsingDataDialog();
+  browser->window()->Show();
+}
+
+// static
+void Browser::OpenImportSettingsDialogWindow(Profile* profile) {
+  Browser* browser = Browser::Create(profile);
+  browser->OpenImportSettingsDialog();
+  browser->window()->Show();
+}
 #endif
 
 // static
@@ -734,7 +781,7 @@
 
   gfx::Rect restored_bounds = override_bounds_;
   bool maximized;
-  WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL,
+  WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this,
                                       &restored_bounds, &maximized);
   return restored_bounds;
 }
@@ -753,7 +800,7 @@
   // An explicit maximized state was not set. Query the window sizer.
   gfx::Rect restored_bounds;
   bool maximized = false;
-  WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL,
+  WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this,
                                       &restored_bounds, &maximized);
   return maximized;
 }
@@ -1117,6 +1164,9 @@
   command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui);
   command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui);
   command_updater_.UpdateCommandEnabled(IDC_TOGGLE_VERTICAL_TABS, show_main_ui);
+#if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC)
+  command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui);
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1282,7 +1332,8 @@
 
 void Browser::NewWindow() {
   if (browser_defaults::kAlwaysOpenIncognitoWindow &&
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kIncognito)) {
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kIncognito) &&
+      incognito_mode_allowed_.GetValue()) {
     NewIncognitoWindow();
     return;
   }
@@ -1296,6 +1347,11 @@
 }
 
 void Browser::NewIncognitoWindow() {
+  if (!incognito_mode_allowed_.GetValue()) {
+    NewWindow();
+    return;
+  }
+
   UserMetrics::RecordAction(UserMetricsAction("NewIncognitoWindow"), profile_);
   Browser::OpenEmptyWindow(profile_->GetOffTheRecordProfile());
 }
@@ -1310,6 +1366,7 @@
 
   if (type() == TYPE_NORMAL) {
     AddBlankTab(true);
+    GetSelectedTabContentsWrapper()->view()->RestoreFocus();
   } else {
     Browser* b = GetOrCreateTabbedBrowser(profile_);
     b->AddBlankTab(true);
@@ -1344,11 +1401,6 @@
 
 void Browser::OpenTabpose() {
 #if defined(OS_MACOSX)
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kEnableExposeForTabs)) {
-    return;
-  }
-
   UserMetrics::RecordAction(UserMetricsAction("OpenTabpose"), profile_);
   window()->OpenTabpose();
 #else
@@ -1472,6 +1524,18 @@
   // Write /tmp/uptime-logout-started as well.
   const char kLogoutStarted[] = "logout-started";
   chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted);
+
+  // Login screen should show up in owner's locale.
+  PrefService* state = g_browser_process->local_state();
+  if (state) {
+    std::string owner_locale = state->GetString(prefs::kOwnerLocale);
+    if (!owner_locale.empty() &&
+        state->GetString(prefs::kApplicationLocale) != owner_locale &&
+        !state->IsManagedPreference(prefs::kApplicationLocale)) {
+      state->SetString(prefs::kApplicationLocale, owner_locale);
+      state->ScheduleSavePersistentPrefs();
+    }
+  }
 #endif
   BrowserList::Exit();
 }
@@ -1717,14 +1781,17 @@
       GetSelectedTabContentsWrapper()->render_view_host(), action);
 }
 
-void Browser::OpenTaskManager() {
+void Browser::OpenTaskManager(bool highlight_background_resources) {
   UserMetrics::RecordAction(UserMetricsAction("TaskManager"), profile_);
-  window_->ShowTaskManager();
+  if (highlight_background_resources)
+    window_->ShowBackgroundPages();
+  else
+    window_->ShowTaskManager();
 }
 
 void Browser::OpenBugReportDialog() {
   UserMetrics::RecordAction(UserMetricsAction("ReportBug"), profile_);
-  window_->ShowReportBugDialog();
+  browser::ShowHtmlBugReportView(this);
 }
 
 void Browser::ToggleBookmarkBar() {
@@ -1738,7 +1805,7 @@
 }
 
 void Browser::ShowAppMenu() {
-  UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu"), profile_);
+  // We record the user metric for this event in WrenchMenu::RunMenu.
   window_->ShowAppMenu();
 }
 
@@ -1792,9 +1859,7 @@
                             profile_);
   if (!CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableTabbedOptions)) {
-    ShowOptionsTab(
-        chrome::kAdvancedOptionsSubPage + std::string(kHashMark) +
-        chrome::kClearBrowserDataSubPage);
+    ShowOptionsTab(chrome::kClearBrowserDataSubPage);
   } else {
     window_->ShowClearBrowsingDataDialog();
   }
@@ -1828,9 +1893,7 @@
   UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"), profile_);
   if (!CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableTabbedOptions)) {
-    ShowOptionsTab(
-        chrome::kPersonalOptionsSubPage + std::string(kHashMark) +
-        chrome::kImportDataSubPage);
+    ShowOptionsTab(chrome::kImportDataSubPage);
   } else {
     window_->ShowImportDialog();
   }
@@ -1838,7 +1901,7 @@
 
 void Browser::OpenSyncMyBookmarksDialog() {
   sync_ui_util::OpenSyncMyBookmarksDialog(
-      profile_, ProfileSyncService::START_FROM_WRENCH);
+      profile_, this, ProfileSyncService::START_FROM_WRENCH);
 }
 
 void Browser::OpenAboutChromeDialog() {
@@ -1857,11 +1920,6 @@
 
 void Browser::OpenHelpTab() {
   GURL help_url(kHelpContentUrl);
-#if defined(OS_CHROMEOS)
-  // TODO(nkostylev): Always redirect to HelpApp http://crosbug.com/6923
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession))
-    help_url = GURL(kHelpContentOnlineUrl);
-#endif
   GURL localized_help_url = google_util::AppendGoogleLocaleParam(help_url);
   AddSelectedTabWithURL(localized_help_url, PageTransition::AUTO_BOOKMARK);
 }
@@ -1924,7 +1982,7 @@
       switches::kDisableTabbedOptions)) {
     ShowOptionsTab(chrome::kLanguageOptionsSubPage);
   } else {
-    chromeos::LanguageConfigView::Show(profile_, NULL);
+    // Language options dialog has been replaced by WebUI.
   }
 }
 
@@ -1969,11 +2027,9 @@
 
 // static
 void Browser::RegisterPrefs(PrefService* prefs) {
-  prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
   prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
-  prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
-  prefs->RegisterDictionaryPref(prefs::kPreferencesWindowPlacement);
   prefs->RegisterIntegerPref(prefs::kExtensionSidebarWidth, -1);
+  prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0);
   // Educated guess: Chrome has a bundled Flash version supporting
   // clearing LSO data, Chromium hasn't.
 #if defined(GOOGLE_CHROME_BUILD)
@@ -1989,7 +2045,6 @@
                             chrome::kChromeUINewTabURL);
   prefs->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
   prefs->RegisterBooleanPref(prefs::kClearSiteDataOnExit, false);
-  prefs->RegisterBooleanPref(prefs::kClearPluginLSODataOnExit, false);
   prefs->RegisterBooleanPref(prefs::kShowHomeButton, false);
 #if defined(OS_MACOSX)
   // This really belongs in platform code, but there's no good place to
@@ -2010,7 +2065,6 @@
   prefs->RegisterBooleanPref(prefs::kDeleteCookies, true);
   prefs->RegisterBooleanPref(prefs::kDeletePasswords, false);
   prefs->RegisterBooleanPref(prefs::kDeleteFormData, false);
-  prefs->RegisterBooleanPref(prefs::kDeleteLSOData, false);
   prefs->RegisterIntegerPref(prefs::kDeleteTimePeriod, 0);
   prefs->RegisterBooleanPref(prefs::kCheckDefaultBrowser, true);
   prefs->RegisterBooleanPref(prefs::kShowOmniboxSearchHint, true);
@@ -2021,9 +2075,13 @@
   prefs->RegisterBooleanPref(prefs::kEnableTranslate, true);
   prefs->RegisterBooleanPref(prefs::kRemotingHasSetupCompleted, false);
   prefs->RegisterStringPref(prefs::kCloudPrintEmail, std::string());
+  prefs->RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, true);
   prefs->RegisterBooleanPref(prefs::kDevToolsDisabled, false);
-  prefs->RegisterRealPref(prefs::kDefaultZoomLevel, 0.0);
-  prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0);
+  prefs->RegisterBooleanPref(prefs::kIncognitoEnabled, true);
+  prefs->RegisterDoublePref(prefs::kDefaultZoomLevel, 0.0);
+  prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
+  prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
+  prefs->RegisterDictionaryPref(prefs::kPreferencesWindowPlacement);
   // We need to register the type of this preference in order to query
   // it even though it's only typically controlled via policy.
   prefs->RegisterBooleanPref(prefs::kDisable3DAPIs, false);
@@ -2216,11 +2274,12 @@
     case IDC_DEV_TOOLS_INSPECT:     ToggleDevToolsWindow(
                                         DEVTOOLS_TOGGLE_ACTION_INSPECT);
                                     break;
-    case IDC_TASK_MANAGER:          // fall through to OpenTaskManager().
-    case IDC_VIEW_BACKGROUND_PAGES: OpenTaskManager();                break;
+    case IDC_TASK_MANAGER:          OpenTaskManager(false);           break;
+    case IDC_VIEW_BACKGROUND_PAGES: OpenTaskManager(true);            break;
     case IDC_FEEDBACK:              OpenBugReportDialog();            break;
 
     case IDC_SHOW_BOOKMARK_BAR:     ToggleBookmarkBar();              break;
+    case IDC_PROFILING_ENABLED:     Profiling::Toggle();              break;
 
     case IDC_SHOW_BOOKMARK_MANAGER: OpenBookmarkManager();            break;
     case IDC_SHOW_APP_MENU:         ShowAppMenu();                    break;
@@ -2258,7 +2317,30 @@
   return false;
 }
 
-bool Browser::IsReservedCommand(int command_id) {
+bool Browser::IsReservedCommandOrKey(int command_id,
+                                     const NativeWebKeyboardEvent& event) {
+#if defined(OS_CHROMEOS)
+  // Chrome OS's top row of keys produces F1-10.  Make sure that web pages
+  // aren't able to block Chrome from performing the standard actions for F1-F4
+  // (F5-7 are grabbed by other X clients and hence don't need this protection,
+  // and F8-10 are handled separately in Chrome via a GDK event filter, but
+  // let's future-proof this).
+  ui::KeyboardCode key_code =
+      static_cast<ui::KeyboardCode>(event.windowsKeyCode);
+  if (key_code == ui::VKEY_F1 ||
+      key_code == ui::VKEY_F2 ||
+      key_code == ui::VKEY_F3 ||
+      key_code == ui::VKEY_F4 ||
+      key_code == ui::VKEY_F5 ||
+      key_code == ui::VKEY_F6 ||
+      key_code == ui::VKEY_F7 ||
+      key_code == ui::VKEY_F8 ||
+      key_code == ui::VKEY_F9 ||
+      key_code == ui::VKEY_F10) {
+    return true;
+  }
+#endif
+
   return command_id == IDC_CLOSE_TAB ||
          command_id == IDC_CLOSE_WINDOW ||
          command_id == IDC_NEW_INCOGNITO_WINDOW ||
@@ -2476,7 +2558,7 @@
     new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
                           window()->GetRestoredBounds().size()));
 
-    // We need to show the browser now. Otherwise ContainerWin assumes the
+    // We need to show the browser now.  Otherwise ContainerWin assumes the
     // TabContents is invisible and won't size it.
     browser->window()->Show();
 
@@ -2580,6 +2662,7 @@
 void Browser::TabInsertedAt(TabContentsWrapper* contents,
                             int index,
                             bool foreground) {
+  contents->set_delegate(this);
   contents->tab_contents()->set_delegate(this);
   contents->controller().SetWindowID(session_id());
 
@@ -2604,6 +2687,7 @@
       NotificationService::NoDetails());
 
   // Sever the TabContents' connection back to us.
+  contents->set_delegate(NULL);
   contents->tab_contents()->set_delegate(NULL);
 }
 
@@ -2626,6 +2710,17 @@
                             bool user_gesture) {
   DCHECK(old_contents != new_contents);
 
+  // On some platforms we want to automatically reload tabs that are
+  // killed when the user selects them.
+  if (user_gesture && new_contents->tab_contents()->crashed_status() ==
+        base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+    const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+    if (parsed_command_line.HasSwitch(switches::kReloadKilledTabs)) {
+      Reload(CURRENT_TAB);
+      return;
+    }
+  }
+
   // If we have any update pending, do it now.
   if (!chrome_updater_factory_.empty() && old_contents)
     ProcessPendingUIUpdates();
@@ -2649,7 +2744,7 @@
   }
 
   if (HasFindBarController()) {
-    find_bar_controller_->ChangeTabContents(new_contents->tab_contents());
+    find_bar_controller_->ChangeTabContents(new_contents);
     find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
   }
 
@@ -2672,7 +2767,8 @@
   SyncHistoryWithTabs(std::min(from_index, to_index));
 }
 
-void Browser::TabReplacedAt(TabContentsWrapper* old_contents,
+void Browser::TabReplacedAt(TabStripModel* tab_strip_model,
+                            TabContentsWrapper* old_contents,
                             TabContentsWrapper* new_contents,
                             int index) {
   TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE);
@@ -2695,6 +2791,10 @@
         &new_contents->controller(),
         tab_handler_->GetTabStripModel()->IsTabPinned(index));
   }
+
+  DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
+  if (devtools_manager)  // NULL in unit tests.
+    devtools_manager->TabReplaced(old_contents, new_contents);
 }
 
 void Browser::TabPinnedStateChanged(TabContentsWrapper* contents, int index) {
@@ -2836,7 +2936,7 @@
     // waiting for unload to fire. Don't actually try to close the tab as it
     // will go down the slow shutdown path instead of the fast path of killing
     // all the renderer processes.
-    ClearUnloadState(source);
+    ClearUnloadState(source, true);
     return;
   }
 
@@ -2876,11 +2976,6 @@
   }
 }
 
-void Browser::URLStarredChanged(TabContents* source, bool starred) {
-  if (source == GetSelectedTabContents())
-    window_->SetStarredState(starred);
-}
-
 void Browser::ContentsMouseEvent(
     TabContents* source, const gfx::Point& location, bool motion) {
   if (!GetStatusBubble())
@@ -2950,7 +3045,7 @@
 void Browser::ConvertContentsToApplication(TabContents* contents) {
   const GURL& url = contents->controller().GetActiveEntry()->url();
   std::string app_name = web_app::GenerateApplicationNameFromURL(url);
-  RegisterAppPrefs(app_name);
+  RegisterAppPrefs(app_name, contents->profile());
 
   DetachContents(contents);
   Browser* app_browser = Browser::CreateForApp(
@@ -3115,7 +3210,7 @@
   if (!CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableTabbedOptions)) {
     ShowOptionsTab(
-        chrome::kContentSettingsSubPage + std::string(kHashMark) +
+        chrome::kContentSettingsExceptionsSubPage + std::string(kHashMark) +
         ContentSettingsHandler::ContentSettingsTypeToGroupName(content_type));
   } else {
     window()->ShowContentSettingsWindow(content_type,
@@ -3179,6 +3274,14 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Browser, TabContentsWrapperDelegate implementation:
+
+void Browser::URLStarredChanged(TabContentsWrapper* source, bool starred) {
+  if (source == GetSelectedTabContentsWrapper())
+    window_->SetStarredState(starred);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Browser, SelectFileDialog::Listener implementation:
 
 void Browser::FileSelected(const FilePath& path, int index, void* params) {
@@ -3197,12 +3300,10 @@
   switch (type.value) {
     case NotificationType::TAB_CONTENTS_DISCONNECTED:
       if (is_attempting_to_close_browser_) {
-        // Need to do this asynchronously as it will close the tab, which is
-        // currently on the call stack above us.
-        MessageLoop::current()->PostTask(
-            FROM_HERE,
-            method_factory_.NewRunnableMethod(&Browser::ClearUnloadState,
-                Source<TabContents>(source).ptr()));
+        // Pass in false so that we delay processing. We need to delay the
+        // processing as it may close the tab, which is currently on the call
+        // stack above us.
+        ClearUnloadState(Source<TabContents>(source).ptr(), false);
       }
       break;
 
@@ -3272,19 +3373,16 @@
       // this extension, it means that it has been reloaded in another window
       // so just remove the remaining CrashedExtensionInfoBarDelegate objects.
       const Extension* extension = Details<const Extension>(details).ptr();
-      CrashedExtensionInfoBarDelegate* delegate = NULL;
       TabStripModel* model = tab_handler_->GetTabStripModel();
       for (int m = 0; m < model->count(); ++m) {
         TabContents* tab_contents = model->GetTabContentsAt(m)->tab_contents();
-        for (int i = 0; i < tab_contents->infobar_delegate_count();) {
-          delegate = tab_contents->GetInfoBarDelegateAt(i)->
-              AsCrashedExtensionInfoBarDelegate();
-          if (delegate && delegate->extension_id() == extension->id()) {
+        for (size_t i = 0; i < tab_contents->infobar_count(); ) {
+          CrashedExtensionInfoBarDelegate* delegate = tab_contents->
+              GetInfoBarDelegateAt(i)->AsCrashedExtensionInfoBarDelegate();
+          if (delegate && delegate->extension_id() == extension->id())
             tab_contents->RemoveInfoBar(delegate);
-            continue;
-          }
-          // Only increment |i| if we didn't remove an entry.
-          ++i;
+          else
+            ++i;
         }
       }
       break;
@@ -3339,6 +3437,8 @@
         UpdateCommandsForDevTools();
         if (dev_tools_disabled_.GetValue())
           g_browser_process->devtools_manager()->CloseAllClientHosts();
+      } else if (pref_name == prefs::kIncognitoEnabled) {
+        break;  // No further action is required.
       } else {
         NOTREACHED();
       }
@@ -3419,7 +3519,8 @@
 
   // Window management commands
   command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW, true);
-  command_updater_.UpdateCommandEnabled(IDC_NEW_INCOGNITO_WINDOW, true);
+  command_updater_.UpdateCommandEnabled(IDC_NEW_INCOGNITO_WINDOW,
+                                        incognito_mode_allowed_.GetValue());
   command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
   command_updater_.UpdateCommandEnabled(IDC_NEW_TAB, true);
   command_updater_.UpdateCommandEnabled(IDC_CLOSE_TAB, true);
@@ -3565,7 +3666,8 @@
 
 void Browser::UpdateCommandsForTabState() {
   TabContents* current_tab = GetSelectedTabContents();
-  if (!current_tab)  // May be NULL during tab restore.
+  TabContentsWrapper* current_tab_wrapper = GetSelectedTabContentsWrapper();
+  if (!current_tab || !current_tab_wrapper)  // May be NULL during tab restore.
     return;
 
   // Navigation commands
@@ -3587,7 +3689,7 @@
       non_app_window && tab_count() > 1);
 
   // Page-related commands
-  window_->SetStarredState(current_tab->is_starred());
+  window_->SetStarredState(current_tab_wrapper->is_starred());
   command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS,
       browser_defaults::bookmarks_enabled && CanBookmarkAllTabs());
   command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE,
@@ -3841,7 +3943,12 @@
 // Browser, OnBeforeUnload handling (private):
 
 void Browser::ProcessPendingTabs() {
-  DCHECK(is_attempting_to_close_browser_);
+  if (!is_attempting_to_close_browser_) {
+    // Because we might invoke this after a delay it's possible for the value of
+    // is_attempting_to_close_browser_ to have changed since we scheduled the
+    // task.
+    return;
+  }
 
   if (HasCompletedUnloadProcessing()) {
     // We've finished all the unload events and can proceed to close the
@@ -3859,7 +3966,7 @@
     if (tab->render_view_host()) {
       tab->render_view_host()->FirePageBeforeUnload(false);
     } else {
-      ClearUnloadState(tab);
+      ClearUnloadState(tab, true);
     }
   } else if (!tabs_needing_unload_fired_.empty()) {
     // We've finished firing all beforeunload events and can proceed with unload
@@ -3876,7 +3983,7 @@
     if (tab->render_view_host()) {
       tab->render_view_host()->ClosePage(false, -1, -1);
     } else {
-      ClearUnloadState(tab);
+      ClearUnloadState(tab, true);
     }
   } else {
     NOTREACHED();
@@ -3916,18 +4023,23 @@
   return false;
 }
 
-void Browser::ClearUnloadState(TabContents* tab) {
+void Browser::ClearUnloadState(TabContents* tab, bool process_now) {
   // Closing of browser could be canceled (via IsClosingPermitted) between the
   // time when request was initiated and when this method is called, so check
   // for is_attempting_to_close_browser_ flag before proceeding.
   if (is_attempting_to_close_browser_) {
     RemoveFromSet(&tabs_needing_before_unload_fired_, tab);
     RemoveFromSet(&tabs_needing_unload_fired_, tab);
-    ProcessPendingTabs();
+    if (process_now) {
+      ProcessPendingTabs();
+    } else {
+      MessageLoop::current()->PostTask(
+          FROM_HERE,
+          method_factory_.NewRunnableMethod(&Browser::ProcessPendingTabs));
+    }
   }
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 // Browser, In-progress download termination handling (private):
 
@@ -4054,9 +4166,10 @@
     // We always want to search for the contents of the find pasteboard on OS X.
     find_text = GetFindPboardText();
 #endif
-    GetSelectedTabContents()->StartFinding(find_text,
-                                           forward_direction,
-                                           false);  // Not case sensitive.
+    GetSelectedTabContentsWrapper()->
+        GetFindManager()->StartFinding(find_text,
+                                       forward_direction,
+                                       false);  // Not case sensitive.
   }
 }
 
@@ -4078,6 +4191,7 @@
       SyncHistoryWithTabs(0);
   }
 
+  contents->set_delegate(NULL);
   contents->tab_contents()->set_delegate(NULL);
   RemoveScheduledUpdatesFor(contents->tab_contents());
 
@@ -4086,12 +4200,20 @@
     find_bar_controller_->ChangeTabContents(NULL);
   }
 
+  if (is_attempting_to_close_browser_) {
+    // If this is the last tab with unload handlers, then ProcessPendingTabs
+    // would call back into the TabStripModel (which is invoking this method on
+    // us). Avoid that by passing in false so that the call to
+    // ProcessPendingTabs is delayed.
+    ClearUnloadState(contents->tab_contents(), false);
+  }
+
   registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
                     Source<TabContentsWrapper>(contents));
 }
 
 // static
-void Browser::RegisterAppPrefs(const std::string& app_name) {
+void Browser::RegisterAppPrefs(const std::string& app_name, Profile* profile) {
   // A set of apps that we've already started.
   static std::set<std::string>* g_app_names = NULL;
 
@@ -4107,10 +4229,7 @@
   std::string window_pref(prefs::kBrowserWindowPlacement);
   window_pref.append("_");
   window_pref.append(app_name);
-  PrefService* prefs = g_browser_process->local_state();
-  DCHECK(prefs);
-
-  prefs->RegisterDictionaryPref(window_pref.c_str());
+  profile->GetPrefs()->RegisterDictionaryPref(window_pref.c_str());
 }
 
 void Browser::TabRestoreServiceChanged(TabRestoreService* service) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index cc1686d..8e32d5e 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
@@ -22,19 +23,20 @@
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/sessions/session_id.h"
 #include "chrome/browser/sessions/tab_restore_service_observer.h"
-#include "chrome/browser/shell_dialogs.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/tabs/tab_handler.h"
 #include "chrome/browser/tabs/tab_strip_model_delegate.h"   // TODO(beng): remove
 #include "chrome/browser/tabs/tab_strip_model_observer.h"   // TODO(beng): remove
 #include "chrome/browser/tab_contents/page_navigator.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/browser/ui/shell_dialogs.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
 #include "chrome/browser/ui/toolbar/toolbar_model.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/page_transition_types.h"
 #include "chrome/common/page_zoom.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class BrowserWindow;
 class Extension;
@@ -55,6 +57,7 @@
 
 class Browser : public TabHandlerDelegate,
                 public TabContentsDelegate,
+                public TabContentsWrapperDelegate,
                 public PageNavigator,
                 public CommandUpdater::CommandUpdaterDelegate,
                 public NotificationObserver,
@@ -187,6 +190,8 @@
   }
 #endif
 
+  // |window()| will return NULL if called before |CreateBrowserWindow()|
+  // is done.
   BrowserWindow* window() const { return window_; }
   ToolbarModel* toolbar_model() { return &toolbar_model_; }
   const SessionID& session_id() const { return session_id_; }
@@ -275,6 +280,8 @@
   static void OpenDownloadsWindow(Profile* profile);
   static void OpenHelpWindow(Profile* profile);
   static void OpenOptionsWindow(Profile* profile);
+  static void OpenClearBrowingDataDialogWindow(Profile* profile);
+  static void OpenImportSettingsDialogWindow(Profile* profile);
 #endif
 
   // Opens a window with the extensions tab in it - needed by long-lived
@@ -523,7 +530,7 @@
   void OpenFile();
   void OpenCreateShortcutsDialog();
   void ToggleDevToolsWindow(DevToolsToggleAction action);
-  void OpenTaskManager();
+  void OpenTaskManager(bool highlight_background_resources);
   void OpenBugReportDialog();
 
   void ToggleBookmarkBar();
@@ -606,9 +613,11 @@
   // Returns true if the command is executed.
   bool ExecuteCommandIfEnabled(int id);
 
-  // Returns whether the |id| is a reserved command, whose keyboard shortcuts
-  // should not be sent to the renderer.
-  bool IsReservedCommand(int id);
+  // Returns true if |command_id| is a reserved command whose keyboard shortcuts
+  // should not be sent to the renderer or |event| was triggered by a key that
+  // we never want to send to the renderer.
+  bool IsReservedCommandOrKey(int command_id,
+                              const NativeWebKeyboardEvent& event);
 
   // Sets if command execution shall be blocked. If |block| is true then
   // following calls to ExecuteCommand() or ExecuteCommandWithDisposition()
@@ -706,7 +715,8 @@
   virtual void TabMoved(TabContentsWrapper* contents,
                         int from_index,
                         int to_index);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int index);
   virtual void TabPinnedStateChanged(TabContentsWrapper* contents, int index);
@@ -718,6 +728,8 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(BrowserTest, NoTabsInPopups);
   FRIEND_TEST_ALL_PREFIXES(BrowserTest, ConvertTabToAppShortcut);
+  FRIEND_TEST_ALL_PREFIXES(BrowserTest, OpenAppWindowLikeNtp);
+  FRIEND_TEST_ALL_PREFIXES(BrowserTest, AppIdSwitch);
 
   // Used to describe why a tab is being detached. This is used by
   // TabDetachedAtImpl.
@@ -754,7 +766,6 @@
   virtual bool IsPopup(const TabContents* source) const;
   virtual bool CanReloadContents(TabContents* source) const;
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
-  virtual void URLStarredChanged(TabContents* source, bool starred);
   virtual void UpdateTargetURL(TabContents* source, const GURL& url);
   virtual void ContentsMouseEvent(
       TabContents* source, const gfx::Point& location, bool motion);
@@ -801,6 +812,10 @@
                                     const WebApplicationInfo& app_info);
   virtual void ContentRestrictionsChanged(TabContents* source);
 
+  // Overridden from TabContentsWrapperDelegate:
+  virtual void URLStarredChanged(TabContentsWrapper* source,
+                                 bool starred) OVERRIDE;
+
   // Overridden from SelectFileDialog::Listener:
   virtual void FileSelected(const FilePath& path, int index, void* params);
 
@@ -906,8 +921,13 @@
   // Cleans up state appropriately when we are trying to close the browser and
   // the tab has finished firing its unload handler. We also use this in the
   // cases where a tab crashes or hangs even if the beforeunload/unload haven't
-  // successfully fired.
-  void ClearUnloadState(TabContents* tab);
+  // successfully fired. If |process_now| is true |ProcessPendingTabs| is
+  // invoked immediately, otherwise it is invoked after a delay (PostTask).
+  //
+  // Typically you'll want to pass in true for |process_now|. Passing in true
+  // may result in deleting |tab|. If you know that shouldn't happen (because of
+  // the state of the stack), pass in false.
+  void ClearUnloadState(TabContents* tab, bool process_now);
 
   // In-progress download termination handling /////////////////////////////////
 
@@ -918,24 +938,6 @@
 
   // Assorted utility functions ///////////////////////////////////////////////
 
-  // Checks whether |source| is about to navigate across extension extents, and
-  // if so, navigates in the correct window. For example if this is a normal
-  // browser and we're about to navigate into an extent, this method will
-  // navigate the app's window instead. If we're in an app window and
-  // navigating out of the app, this method will find and navigate a normal
-  // browser instead.
-  //
-  // Returns true if the navigation was handled, eg, it was opened in some other
-  // browser.
-  //
-  // Returns false if it was not handled. In this case, the method may also
-  // modify |disposition| to a more suitable value.
-  bool HandleCrossAppNavigation(TabContents* source,
-                                const GURL& url,
-                                const GURL& referrer,
-                                WindowOpenDisposition *disposition,
-                                PageTransition::Type transition);
-
   // Shows the Find Bar, optionally selecting the next entry that matches the
   // existing search string for that Tab. |forward_direction| controls the
   // search direction.
@@ -949,9 +951,10 @@
   void TabDetachedAtImpl(TabContentsWrapper* contents,
       int index, DetachType type);
 
-  // Create a preference dictionary for the provided application name. This is
-  // done only once per application name / per session.
-  static void RegisterAppPrefs(const std::string& app_name);
+  // Create a preference dictionary for the provided application name, in the
+  // given user profile. This is done only once per application name / per
+  // session / per user profile.
+  static void RegisterAppPrefs(const std::string& app_name, Profile* profile);
 
   // Shared code between Reload() and ReloadIgnoringCache().
   void ReloadInternal(WindowOpenDisposition disposition, bool ignore_cache);
@@ -1100,6 +1103,9 @@
   // Keep track of when instant enabled changes.
   BooleanPrefMember instant_enabled_;
 
+  // Tracks the preference that controls whether incognito mode is allowed.
+  BooleanPrefMember incognito_mode_allowed_;
+
   // Indicates if command execution is blocked.
   bool block_command_execution_;
 
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h
new file mode 100644
index 0000000..aabf63a
--- /dev/null
+++ b/chrome/browser/ui/browser_dialogs.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_BROWSER_DIALOGS_H_
+#define CHROME_BROWSER_UI_BROWSER_DIALOGS_H_
+#pragma once
+
+#include "ipc/ipc_message.h"
+#include "ui/gfx/native_widget_types.h"
+
+class Browser;
+class Extension;
+class ImporterHost;
+class HtmlDialogUIDelegate;
+class Profile;
+class SkBitmap;
+
+namespace browser {
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+
+// The dialog is a singleton. If the dialog is already opened, it won't do
+// anything, so you can just blindly call this function all you want.
+// This is Called from chrome/browser/browser_about_handler.cc
+void ShowAboutIPCDialog();
+
+#endif  // IPC_MESSAGE_LOG_ENABLED
+
+// Creates and shows an HTML dialog with the given delegate and profile.
+// The window is automatically destroyed when it is closed.
+// Returns the created window.
+//
+// Make sure to use the returned window only when you know it is safe
+// to do so, i.e. before OnDialogClosed() is called on the delegate.
+gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile,
+                                 HtmlDialogUIDelegate* delegate);
+
+// This function is called by an ImporterHost, and displays the Firefox profile
+// locked warning by creating a dialog.  On the closing of the dialog, the
+// ImportHost receives a callback with the message either to skip the import,
+// or to try again.
+void ShowImportLockDialog(gfx::NativeWindow parent,
+                          ImporterHost* importer_host);
+
+// Creates the ExtensionInstalledBubble and schedules it to be shown once
+// the extension has loaded. |extension| is the installed extension. |browser|
+// is the browser window which will host the bubble. |icon| is the install
+// icon of the extension.
+void ShowExtensionInstalledBubble(const Extension* extension,
+                                  Browser* browser,
+                                  SkBitmap icon,
+                                  Profile* profile);
+
+} // namespace browser
+
+#endif  // CHROME_BROWSER_UI_BROWSER_DIALOGS_H_
diff --git a/chrome/browser/ui/browser_init.cc b/chrome/browser/ui/browser_init.cc
index 6977552..e379855 100644
--- a/chrome/browser/ui/browser_init.cc
+++ b/chrome/browser/ui/browser_init.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>   // For max().
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/environment.h"
 #include "base/event_recorder.h"
 #include "base/file_path.h"
@@ -66,6 +64,8 @@
 #include "grit/theme_resources.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "webkit/glue/webkit_glue.h"
 
 #if defined(OS_MACOSX)
@@ -73,7 +73,7 @@
 #endif
 
 #if defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -101,90 +101,53 @@
 
 namespace {
 
+// SetAsDefaultBrowserTask ----------------------------------------------------
+
 class SetAsDefaultBrowserTask : public Task {
  public:
-  SetAsDefaultBrowserTask() { }
-  virtual void Run() {
-    ShellIntegration::SetAsDefaultBrowser();
-  }
+  SetAsDefaultBrowserTask();
+  virtual ~SetAsDefaultBrowserTask();
 
  private:
+  virtual void Run();
+
   DISALLOW_COPY_AND_ASSIGN(SetAsDefaultBrowserTask);
 };
 
+SetAsDefaultBrowserTask::SetAsDefaultBrowserTask() {
+}
+
+SetAsDefaultBrowserTask::~SetAsDefaultBrowserTask() {
+}
+
+void SetAsDefaultBrowserTask::Run() {
+  ShellIntegration::SetAsDefaultBrowser();
+}
+
+
+// DefaultBrowserInfoBarDelegate ----------------------------------------------
+
 // The delegate for the infobar shown when Chrome is not the default browser.
 class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
-  explicit DefaultBrowserInfoBarDelegate(TabContents* contents)
-      : ConfirmInfoBarDelegate(contents),
-        profile_(contents->profile()),
-        action_taken_(false),
-        should_expire_(false),
-        ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
-    // We want the info-bar to stick-around for few seconds and then be hidden
-    // on the next navigation after that.
-    MessageLoop::current()->PostDelayedTask(FROM_HERE,
-        method_factory_.NewRunnableMethod(
-            &DefaultBrowserInfoBarDelegate::Expire),
-        8000);  // 8 seconds.
-  }
-
-  virtual bool ShouldExpire(
-      const NavigationController::LoadCommittedDetails& details) const {
-    return should_expire_;
-  }
-
-  // Overridden from ConfirmInfoBarDelegate:
-  virtual void InfoBarClosed() {
-    if (!action_taken_)
-      UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.Ignored", 1);
-    delete this;
-  }
-
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringUTF16(IDS_DEFAULT_BROWSER_INFOBAR_SHORT_TEXT);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-       IDR_PRODUCT_ICON_32);
-  }
-
-  virtual int GetButtons() const {
-    return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    return button == BUTTON_OK ?
-        l10n_util::GetStringUTF16(IDS_SET_AS_DEFAULT_INFOBAR_BUTTON_LABEL) :
-        l10n_util::GetStringUTF16(IDS_DONT_ASK_AGAIN_INFOBAR_BUTTON_LABEL);
-  }
-
-  virtual bool NeedElevation(InfoBarButton button) const {
-    return button == BUTTON_OK;
-  }
-
-  virtual bool Accept() {
-    action_taken_ = true;
-    UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefault", 1);
-    g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
-        new SetAsDefaultBrowserTask());
-    return true;
-  }
-
-  virtual bool Cancel() {
-    action_taken_ = true;
-    UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.DontSetAsDefault", 1);
-    // User clicked "Don't ask me again", remember that.
-    profile_->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, false);
-    return true;
-  }
-
-  void Expire() {
-    should_expire_ = true;
-  }
+  explicit DefaultBrowserInfoBarDelegate(TabContents* contents);
 
  private:
+  virtual ~DefaultBrowserInfoBarDelegate();
+
+  void AllowExpiry() { should_expire_ = true; }
+
+  // ConfirmInfoBarDelegate:
+  virtual bool ShouldExpire(
+      const NavigationController::LoadCommittedDetails& details) const;
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool NeedElevation(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+
   // The Profile that we restore sessions from.
   Profile* profile_;
 
@@ -200,95 +163,213 @@
   DISALLOW_COPY_AND_ASSIGN(DefaultBrowserInfoBarDelegate);
 };
 
+DefaultBrowserInfoBarDelegate::DefaultBrowserInfoBarDelegate(
+    TabContents* contents)
+    : ConfirmInfoBarDelegate(contents),
+      profile_(contents->profile()),
+      action_taken_(false),
+      should_expire_(false),
+      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+  // We want the info-bar to stick-around for few seconds and then be hidden
+  // on the next navigation after that.
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &DefaultBrowserInfoBarDelegate::AllowExpiry), 8000);  // 8 seconds.
+}
+
+DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() {
+}
+
+bool DefaultBrowserInfoBarDelegate::ShouldExpire(
+    const NavigationController::LoadCommittedDetails& details) const {
+  return should_expire_;
+}
+
+void DefaultBrowserInfoBarDelegate::InfoBarClosed() {
+  if (!action_taken_)
+    UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.Ignored", 1);
+  delete this;
+}
+
+SkBitmap* DefaultBrowserInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+     IDR_PRODUCT_ICON_32);
+}
+
+string16 DefaultBrowserInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_DEFAULT_BROWSER_INFOBAR_SHORT_TEXT);
+}
+
+string16 DefaultBrowserInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_SET_AS_DEFAULT_INFOBAR_BUTTON_LABEL :
+      IDS_DONT_ASK_AGAIN_INFOBAR_BUTTON_LABEL);
+}
+
+bool DefaultBrowserInfoBarDelegate::NeedElevation(InfoBarButton button) const {
+  return button == BUTTON_OK;
+}
+
+bool DefaultBrowserInfoBarDelegate::Accept() {
+  action_taken_ = true;
+  UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefault", 1);
+  g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
+      new SetAsDefaultBrowserTask());
+  return true;
+}
+
+bool DefaultBrowserInfoBarDelegate::Cancel() {
+  action_taken_ = true;
+  UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.DontSetAsDefault", 1);
+  // User clicked "Don't ask me again", remember that.
+  profile_->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, false);
+  return true;
+}
+
+
+// NotifyNotDefaultBrowserTask ------------------------------------------------
+
 class NotifyNotDefaultBrowserTask : public Task {
  public:
-  NotifyNotDefaultBrowserTask() { }
-
-  virtual void Run() {
-    Browser* browser = BrowserList::GetLastActive();
-    if (!browser) {
-      // Reached during ui tests.
-      return;
-    }
-    TabContents* tab = browser->GetSelectedTabContents();
-    // Don't show the info-bar if there are already info-bars showing.
-    // In ChromeBot tests, there might be a race. This line appears to get
-    // called during shutdown and |tab| can be NULL.
-    if (!tab || tab->infobar_delegate_count() > 0)
-      return;
-    tab->AddInfoBar(new DefaultBrowserInfoBarDelegate(tab));
-  }
+  NotifyNotDefaultBrowserTask();
+  virtual ~NotifyNotDefaultBrowserTask();
 
  private:
+  virtual void Run();
+
   DISALLOW_COPY_AND_ASSIGN(NotifyNotDefaultBrowserTask);
 };
 
+NotifyNotDefaultBrowserTask::NotifyNotDefaultBrowserTask() {
+}
+
+NotifyNotDefaultBrowserTask::~NotifyNotDefaultBrowserTask() {
+}
+
+void NotifyNotDefaultBrowserTask::Run() {
+  Browser* browser = BrowserList::GetLastActive();
+  if (!browser)
+    return;  // Reached during ui tests.
+  // Don't show the info-bar if there are already info-bars showing.
+  // In ChromeBot tests, there might be a race. This line appears to get
+  // called during shutdown and |tab| can be NULL.
+  TabContents* tab = browser->GetSelectedTabContents();
+  if (!tab || tab->infobar_count() > 0)
+    return;
+  tab->AddInfoBar(new DefaultBrowserInfoBarDelegate(tab));
+}
+
+
+// CheckDefaultBrowserTask ----------------------------------------------------
+
 class CheckDefaultBrowserTask : public Task {
  public:
-  CheckDefaultBrowserTask() {
-  }
-
-  virtual void Run() {
-    if (ShellIntegration::IsDefaultBrowser())
-      return;
-#if defined(OS_WIN)
-    if (!BrowserDistribution::GetDistribution()->CanSetAsDefault())
-      return;
-#endif
-
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE, new NotifyNotDefaultBrowserTask());
-  }
+  CheckDefaultBrowserTask();
+  virtual ~CheckDefaultBrowserTask();
 
  private:
+  virtual void Run();
+
   DISALLOW_COPY_AND_ASSIGN(CheckDefaultBrowserTask);
 };
 
-// A delegate for the InfoBar shown when the previous session has crashed. The
-// bar deletes itself automatically after it is closed.
+CheckDefaultBrowserTask::CheckDefaultBrowserTask() {
+}
+
+CheckDefaultBrowserTask::~CheckDefaultBrowserTask() {
+}
+
+void CheckDefaultBrowserTask::Run() {
+  if (ShellIntegration::IsDefaultBrowser())
+    return;
+#if defined(OS_WIN)
+  if (!BrowserDistribution::GetDistribution()->CanSetAsDefault())
+    return;
+#endif
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          new NotifyNotDefaultBrowserTask());
+}
+
+
+// SessionCrashedInfoBarDelegate ----------------------------------------------
+
+// A delegate for the InfoBar shown when the previous session has crashed.
 class SessionCrashedInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
-  explicit SessionCrashedInfoBarDelegate(TabContents* contents)
-      : ConfirmInfoBarDelegate(contents),
-        profile_(contents->profile()) {
-  }
-
-  // Overridden from ConfirmInfoBarDelegate:
-  virtual void InfoBarClosed() {
-    delete this;
-  }
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE);
-  }
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-        IDR_INFOBAR_RESTORE_SESSION);
-  }
-  virtual int GetButtons() const { return BUTTON_OK; }
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON);
-  }
-  virtual bool Accept() {
-    // Restore the session.
-    SessionRestore::RestoreSession(profile_, NULL, true, false,
-                                   std::vector<GURL>());
-    return true;
-  }
+  explicit SessionCrashedInfoBarDelegate(TabContents* contents);
 
  private:
+  virtual ~SessionCrashedInfoBarDelegate();
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual Type GetInfoBarType() const;
+  virtual string16 GetMessageText() const;
+  virtual int GetButtons() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+
   // The Profile that we restore sessions from.
   Profile* profile_;
 
   DISALLOW_COPY_AND_ASSIGN(SessionCrashedInfoBarDelegate);
 };
 
+SessionCrashedInfoBarDelegate::SessionCrashedInfoBarDelegate(
+    TabContents* contents)
+    : ConfirmInfoBarDelegate(contents),
+      profile_(contents->profile()) {
+}
+
+SessionCrashedInfoBarDelegate::~SessionCrashedInfoBarDelegate() {
+}
+
+void SessionCrashedInfoBarDelegate::InfoBarClosed() {
+  delete this;
+}
+
+SkBitmap* SessionCrashedInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_INFOBAR_RESTORE_SESSION);
+}
+
+InfoBarDelegate::Type SessionCrashedInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+string16 SessionCrashedInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE);
+}
+
+int SessionCrashedInfoBarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
+
+string16 SessionCrashedInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON);
+}
+
+bool SessionCrashedInfoBarDelegate::Accept() {
+  SessionRestore::RestoreSession(profile_, NULL, true, false,
+                                 std::vector<GURL>());
+  return true;
+}
+
+
+// Utility functions ----------------------------------------------------------
+
 SessionStartupPref GetSessionStartupPref(const CommandLine& command_line,
                                          Profile* profile) {
   SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile);
   if (command_line.HasSwitch(switches::kRestoreLastSession))
     pref.type = SessionStartupPref::LAST;
   if (command_line.HasSwitch(switches::kIncognito) &&
-      pref.type == SessionStartupPref::LAST) {
+      pref.type == SessionStartupPref::LAST &&
+      profile->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)) {
     // We don't store session information when incognito. If the user has
     // chosen to restore last session and launched incognito, fallback to
     // default launch behavior.
@@ -367,6 +448,9 @@
 
 }  // namespace
 
+
+// BrowserInit ----------------------------------------------------------------
+
 BrowserInit::BrowserInit() {}
 
 BrowserInit::~BrowserInit() {}
@@ -399,11 +483,15 @@
 #endif
 
   // Continue with the off-the-record profile from here on if --incognito
-  if (command_line.HasSwitch(switches::kIncognito))
+  if (command_line.HasSwitch(switches::kIncognito) &&
+      profile->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)) {
     profile = profile->GetOffTheRecordProfile();
+  }
 
   BrowserInit::LaunchWithProfile lwp(cur_dir, command_line, this);
-  bool launched = lwp.Launch(profile, process_startup);
+  std::vector<GURL> urls_to_launch = BrowserInit::GetURLsFromCommandLine(
+      command_line, cur_dir, profile);
+  bool launched = lwp.Launch(profile, urls_to_launch, process_startup);
   in_startup = false;
 
   if (!launched) {
@@ -472,13 +560,15 @@
   return true;
 }
 
-// Tab ------------------------------------------------------------------------
+
+// BrowserInit::LaunchWithProfile::Tab ----------------------------------------
 
 BrowserInit::LaunchWithProfile::Tab::Tab() : is_app(false), is_pinned(true) {}
 
 BrowserInit::LaunchWithProfile::Tab::~Tab() {}
 
-// LaunchWithProfile ----------------------------------------------------------
+
+// BrowserInit::LaunchWithProfile ---------------------------------------------
 
 BrowserInit::LaunchWithProfile::LaunchWithProfile(
     const FilePath& cur_dir,
@@ -502,8 +592,10 @@
 BrowserInit::LaunchWithProfile::~LaunchWithProfile() {
 }
 
-bool BrowserInit::LaunchWithProfile::Launch(Profile* profile,
-                                            bool process_startup) {
+bool BrowserInit::LaunchWithProfile::Launch(
+    Profile* profile,
+    const std::vector<GURL>& urls_to_open,
+    bool process_startup) {
   DCHECK(profile);
   profile_ = profile;
 
@@ -519,18 +611,24 @@
     std::string port_str =
         command_line_.GetSwitchValueASCII(switches::kRemoteShellPort);
     int64 port;
-    if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535)
-      g_browser_process->InitDebuggerWrapper(static_cast<int>(port), false);
-    else
+    if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535) {
+      g_browser_process->InitDevToolsLegacyProtocolHandler(
+          static_cast<int>(port));
+    } else {
       DLOG(WARNING) << "Invalid remote shell port number " << port;
+    }
   } else if (command_line_.HasSwitch(switches::kRemoteDebuggingPort)) {
     std::string port_str =
         command_line_.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
     int64 port;
-    if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535)
-      g_browser_process->InitDebuggerWrapper(static_cast<int>(port), true);
-    else
+    if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535) {
+      g_browser_process->InitDevToolsHttpProtocolHandler(
+          "127.0.0.1",
+          static_cast<int>(port),
+          "");
+    } else {
       DLOG(WARNING) << "Invalid http debugger port number " << port;
+    }
   }
 
   if (command_line_.HasSwitch(switches::kUserAgent)) {
@@ -541,7 +639,6 @@
   // Open the required browser windows and tabs.
   // First, see if we're being run as an application window.
   if (!OpenApplicationWindow(profile)) {
-    std::vector<GURL> urls_to_open = GetURLsFromCommandLine(profile_);
     RecordLaunchModeHistogram(urls_to_open.empty()?
                               LM_TO_BE_DECIDED : LM_WITH_URLS);
     ProcessLaunchURLs(process_startup, urls_to_open);
@@ -843,10 +940,13 @@
   // Unsupported flags for which to display a warning that "stability and
   // security will suffer".
   static const char* kBadFlags[] = {
-    // All imply disabling the sandbox.
+    // These imply disabling the sandbox.
     switches::kSingleProcess,
     switches::kNoSandbox,
     switches::kInProcessWebGL,
+    // These are scary features for developers that shouldn't be turned on
+    // persistently.
+    switches::kEnableNaCl,
     NULL
   };
 
@@ -859,65 +959,13 @@
   }
 
   if (bad_flag) {
-    tab->AddInfoBar(new SimpleAlertInfoBarDelegate(tab,
+    tab->AddInfoBar(new SimpleAlertInfoBarDelegate(tab, NULL,
         l10n_util::GetStringFUTF16(IDS_BAD_FLAGS_WARNING_MESSAGE,
                                    UTF8ToUTF16(std::string("--") + bad_flag)),
-        NULL, false));
+        false));
   }
 }
 
-std::vector<GURL> BrowserInit::LaunchWithProfile::GetURLsFromCommandLine(
-    Profile* profile) {
-  std::vector<GURL> urls;
-  const std::vector<CommandLine::StringType>& params = command_line_.args();
-
-  for (size_t i = 0; i < params.size(); ++i) {
-    FilePath param = FilePath(params[i]);
-    // Handle Vista way of searching - "? <search-term>"
-    if (param.value().find(FILE_PATH_LITERAL("? ")) == 0) {
-      const TemplateURL* default_provider =
-          profile->GetTemplateURLModel()->GetDefaultSearchProvider();
-      if (!default_provider || !default_provider->url()) {
-        // No search provider available. Just treat this as regular URL.
-        urls.push_back(URLFixerUpper::FixupRelativeFile(cur_dir_, param));
-        continue;
-      }
-      const TemplateURLRef* search_url = default_provider->url();
-      DCHECK(search_url->SupportsReplacement());
-      std::wstring search_term = param.ToWStringHack().substr(2);
-      urls.push_back(GURL(search_url->ReplaceSearchTerms(
-          *default_provider, search_term,
-          TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring())));
-    } else {
-      // This will create a file URL or a regular URL.
-      // This call can (in rare circumstances) block the UI thread.
-      // Allow it until this bug is fixed.
-      //  http://code.google.com/p/chromium/issues/detail?id=60641
-      GURL url;
-      {
-        base::ThreadRestrictions::ScopedAllowIO allow_io;
-        url = URLFixerUpper::FixupRelativeFile(cur_dir_, param);
-      }
-      // Exclude dangerous schemes.
-      if (url.is_valid()) {
-        ChildProcessSecurityPolicy *policy =
-            ChildProcessSecurityPolicy::GetInstance();
-        if (policy->IsWebSafeScheme(url.scheme()) ||
-            url.SchemeIs(chrome::kFileScheme) ||
-#if defined(OS_CHROMEOS)
-            // In ChromeOS, allow a settings page to be specified on the
-            // command line. See ExistingUserController::OnLoginSuccess.
-            (url.spec().find(chrome::kChromeUISettingsURL) == 0) ||
-#endif
-            (url.spec().compare(chrome::kAboutBlankURL) == 0)) {
-          urls.push_back(url);
-        }
-      }
-    }
-  }
-  return urls;
-}
-
 void BrowserInit::LaunchWithProfile::AddStartupURLs(
     std::vector<GURL>* startup_urls) const {
   // If we have urls specified beforehand (i.e. from command line) use them
@@ -962,14 +1010,82 @@
   // We do not check if we are the default browser if:
   // - the user said "don't ask me again" on the infobar earlier.
   // - this is the first launch after the first run flow.
+  // - There is a policy in control of this setting.
   if (!profile->GetPrefs()->GetBoolean(prefs::kCheckDefaultBrowser) ||
       FirstRun::IsChromeFirstRun()) {
     return;
   }
+  if (g_browser_process->local_state()->IsManagedPreference(
+      prefs::kDefaultBrowserSettingEnabled)) {
+    if (g_browser_process->local_state()->GetBoolean(
+        prefs::kDefaultBrowserSettingEnabled)) {
+      BrowserThread::PostTask(
+          BrowserThread::FILE, FROM_HERE, NewRunnableFunction(
+              &ShellIntegration::SetAsDefaultBrowser));
+    } else {
+      // TODO(pastarmovj): We can't really do anything meaningful here yet but
+      // just prevent showing the infobar.
+    }
+    return;
+  }
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE, new CheckDefaultBrowserTask());
 }
 
+std::vector<GURL> BrowserInit::GetURLsFromCommandLine(
+    const CommandLine& command_line,
+    const FilePath& cur_dir,
+    Profile* profile) {
+  std::vector<GURL> urls;
+  const std::vector<CommandLine::StringType>& params = command_line.args();
+
+  for (size_t i = 0; i < params.size(); ++i) {
+    FilePath param = FilePath(params[i]);
+    // Handle Vista way of searching - "? <search-term>"
+    if (param.value().find(FILE_PATH_LITERAL("? ")) == 0) {
+      const TemplateURL* default_provider =
+          profile->GetTemplateURLModel()->GetDefaultSearchProvider();
+      if (!default_provider || !default_provider->url()) {
+        // No search provider available. Just treat this as regular URL.
+        urls.push_back(URLFixerUpper::FixupRelativeFile(cur_dir, param));
+        continue;
+      }
+      const TemplateURLRef* search_url = default_provider->url();
+      DCHECK(search_url->SupportsReplacement());
+      std::wstring search_term = param.ToWStringHack().substr(2);
+      urls.push_back(GURL(search_url->ReplaceSearchTerms(
+          *default_provider, WideToUTF16Hack(search_term),
+          TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())));
+    } else {
+      // This will create a file URL or a regular URL.
+      // This call can (in rare circumstances) block the UI thread.
+      // Allow it until this bug is fixed.
+      //  http://code.google.com/p/chromium/issues/detail?id=60641
+      GURL url;
+      {
+        base::ThreadRestrictions::ScopedAllowIO allow_io;
+        url = URLFixerUpper::FixupRelativeFile(cur_dir, param);
+      }
+      // Exclude dangerous schemes.
+      if (url.is_valid()) {
+        ChildProcessSecurityPolicy *policy =
+            ChildProcessSecurityPolicy::GetInstance();
+        if (policy->IsWebSafeScheme(url.scheme()) ||
+            url.SchemeIs(chrome::kFileScheme) ||
+#if defined(OS_CHROMEOS)
+            // In ChromeOS, allow a settings page to be specified on the
+            // command line. See ExistingUserController::OnLoginSuccess.
+            (url.spec().find(chrome::kChromeUISettingsURL) == 0) ||
+#endif
+            (url.spec().compare(chrome::kAboutBlankURL) == 0)) {
+          urls.push_back(url);
+        }
+      }
+    }
+  }
+  return urls;
+}
+
 bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line,
                                      const FilePath& cur_dir,
                                      bool process_startup,
@@ -992,13 +1108,21 @@
       int expected_tab_count = 1;
       if (command_line.HasSwitch(switches::kNoStartupWindow)) {
         expected_tab_count = 0;
+#if defined(OS_CHROMEOS)
+      // kLoginManager will cause Chrome to start up with the ChromeOS login
+      // screen instead of a browser window, so it won't load any tabs.
+      } else if (command_line.HasSwitch(switches::kLoginManager)) {
+        expected_tab_count = 0;
+#endif
       } else if (command_line.HasSwitch(switches::kRestoreLastSession)) {
         std::string restore_session_value(
             command_line.GetSwitchValueASCII(switches::kRestoreLastSession));
         base::StringToInt(restore_session_value, &expected_tab_count);
       } else {
+        std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
+            command_line, cur_dir, profile);
         expected_tab_count =
-            std::max(1, static_cast<int>(command_line.args().size()));
+            std::max(1, static_cast<int>(urls_to_open.size()));
       }
       if (!CreateAutomationProvider<TestingAutomationProvider>(
           testing_channel_id,
@@ -1015,8 +1139,10 @@
         switches::kAutomationClientChannelID);
     // If there are any extra parameters, we expect each one to generate a
     // new tab; if there are none then we have no tabs
+    std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
+        command_line, cur_dir, profile);
     size_t expected_tabs =
-        std::max(static_cast<int>(command_line.args().size()), 0);
+        std::max(static_cast<int>(urls_to_open.size()), 0);
     if (expected_tabs == 0)
       silent_launch = true;
 
@@ -1037,6 +1163,12 @@
     silent_launch = true;
     profile->GetCloudPrintProxyService()->ShowTokenExpiredNotification();
   }
+  // If we are just displaying a print dialog we shouldn't open browser
+  // windows.
+  if (!command_line.GetSwitchValuePath(switches::kCloudPrintFile).empty()) {
+    silent_launch = true;
+  }
+
 
   if (command_line.HasSwitch(switches::kExplicitlyAllowedPorts)) {
     std::string allowed_ports =
diff --git a/chrome/browser/ui/browser_init.h b/chrome/browser/ui/browser_init.h
index 746320c..6d3f8ae 100644
--- a/chrome/browser/ui/browser_init.h
+++ b/chrome/browser/ui/browser_init.h
@@ -107,7 +107,9 @@
     // false on failure. process_startup is true if Chrome is just
     // starting up. If process_startup is false, it indicates Chrome was
     // already running and the user wants to launch another instance.
-    bool Launch(Profile* profile, bool process_startup);
+    bool Launch(Profile* profile,
+                const std::vector<GURL>& urls_to_open,
+                bool process_startup);
 
     // Convenience for OpenTabsInBrowser that converts |urls| into a set of
     // Tabs.
@@ -126,6 +128,7 @@
 
    private:
     FRIEND_TEST_ALL_PREFIXES(BrowserTest, RestorePinnedTabs);
+    FRIEND_TEST_ALL_PREFIXES(BrowserTest, AppIdSwitch);
 
     // If the process was launched with the web application command line flags,
     // e.g. --app=http://www.google.com/ or --app_id=... return true.
@@ -166,10 +169,6 @@
     // politely nag the user about it.
     void AddBadFlagsInfoBarIfNecessary(TabContents* tab);
 
-    // Returns the list of URLs to open from the command line. The returned
-    // vector is empty if the user didn't specify any URLs on the command line.
-    std::vector<GURL> GetURLsFromCommandLine(Profile* profile);
-
     // Adds additional startup URLs to the specified vector.
     void AddStartupURLs(std::vector<GURL>* startup_urls) const;
 
@@ -185,6 +184,13 @@
   };
 
  private:
+  // Returns the list of URLs to open from the command line. The returned
+  // vector is empty if the user didn't specify any URLs on the command line.
+  static std::vector<GURL> GetURLsFromCommandLine(
+      const CommandLine& command_line,
+      const FilePath& cur_dir,
+      Profile* profile);
+
   static bool ProcessCmdLineImpl(const CommandLine& command_line,
                                  const FilePath& cur_dir, bool process_startup,
                                  Profile* profile, int* return_code,
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc
index ec5fef1..0ff8d64 100644
--- a/chrome/browser/ui/browser_list.cc
+++ b/chrome/browser/ui/browser_list.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/chromeos/boot_times_loader.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/login_library.h"
+#include "chrome/browser/chromeos/cros/update_library.h"
 #include "chrome/browser/chromeos/wm_ipc.h"
 #endif
 
@@ -183,16 +184,53 @@
       << "observer list modified during notification";
 }
 
+// static
+void BrowserList::MarkAsCleanShutdown() {
+  for (const_iterator i = begin(); i != end(); ++i) {
+    (*i)->profile()->MarkAsCleanShutdown();
+  }
+}
+
+#if defined(OS_CHROMEOS)
+// static
+void BrowserList::NotifyWindowManagerAboutSignout() {
+  static bool notified = false;
+  if (!notified) {
+    // Let the window manager know that we're going away before we start closing
+    // windows so it can display a graceful transition to a black screen.
+    chromeos::WmIpc::instance()->NotifyAboutSignout();
+    notified = true;
+  }
+}
 
 // static
-void BrowserList::NotifyAndTerminate() {
-  NotificationService::current()->Notify(NotificationType::APP_TERMINATING,
-                                         NotificationService::AllSources(),
-                                         NotificationService::NoDetails());
+bool BrowserList::signout_ = false;
+
+#endif
+
+// static
+void BrowserList::NotifyAndTerminate(bool fast_path) {
 #if defined(OS_CHROMEOS)
-  chromeos::WmIpc::instance()->NotifyAboutSignout();
-  if (chromeos::CrosLibrary::Get()->EnsureLoaded()) {
-    chromeos::CrosLibrary::Get()->GetLoginLibrary()->StopSession("");
+  if (!signout_) return;
+  NotifyWindowManagerAboutSignout();
+#endif
+
+  if (fast_path) {
+    NotificationService::current()->Notify(NotificationType::APP_TERMINATING,
+                                           NotificationService::AllSources(),
+                                           NotificationService::NoDetails());
+  }
+
+#if defined(OS_CHROMEOS)
+  chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get();
+  if (cros_library->EnsureLoaded()) {
+    // If update has been installed, reboot, otherwise, sign out.
+    if (cros_library->GetUpdateLibrary()->status().status ==
+          chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+      cros_library->GetUpdateLibrary()->RebootAfterUpdate();
+    } else {
+      cros_library->GetLoginLibrary()->StopSession("");
+    }
     return;
   }
   // If running the Chrome OS build, but we're not on the device, fall through
@@ -262,8 +300,7 @@
 // static
 bool BrowserList::NeedBeforeUnloadFired() {
   bool need_before_unload_fired = false;
-  for (BrowserList::const_iterator i = BrowserList::begin();
-       i != BrowserList::end(); ++i) {
+  for (const_iterator i = begin(); i != end(); ++i) {
     need_before_unload_fired = need_before_unload_fired ||
       (*i)->TabsNeedBeforeUnloadFired();
   }
@@ -272,8 +309,7 @@
 
 // static
 bool BrowserList::PendingDownloads() {
-  for (BrowserList::const_iterator i = BrowserList::begin();
-       i != BrowserList::end(); ++i) {
+  for (const_iterator i = begin(); i != end(); ++i) {
     bool normal_downloads_are_present = false;
     bool incognito_downloads_are_present = false;
     (*i)->CheckDownloadsInProgress(&normal_downloads_are_present,
@@ -305,7 +341,7 @@
   // If there are no browsers, send the APP_TERMINATING action here. Otherwise,
   // it will be sent by RemoveBrowser() when the last browser has closed.
   if (force_exit || browsers_.empty()) {
-    NotifyAndTerminate();
+    NotifyAndTerminate(true);
     return;
   }
 #if defined(OS_CHROMEOS)
@@ -341,11 +377,12 @@
 // static
 void BrowserList::Exit() {
 #if defined(OS_CHROMEOS)
+  signout_ = true;
   // Fast shutdown for ChromeOS when there's no unload processing to be done.
   if (chromeos::CrosLibrary::Get()->EnsureLoaded()
       && !NeedBeforeUnloadFired()
       && !PendingDownloads()) {
-    NotifyAndTerminate();
+    NotifyAndTerminate(true);
     return;
   }
 #endif
@@ -354,6 +391,7 @@
 
 // static
 void BrowserList::CloseAllBrowsersAndExit() {
+  MarkAsCleanShutdown();  // Don't notify users of crashes beyond this point.
   NotificationService::current()->Notify(
       NotificationType::APP_EXITING,
       NotificationService::AllSources(),
@@ -374,7 +412,9 @@
 void BrowserList::SessionEnding() {
   // EndSession is invoked once per frame. Only do something the first time.
   static bool already_ended = false;
-  if (already_ended)
+  // We may get called in the middle of shutdown, e.g. http://crbug.com/70852
+  // In this case, do nothing.
+  if (already_ended || !NotificationService::current())
     return;
   already_ended = true;
 
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h
index 4ad4e7b..d11d4bf 100644
--- a/chrome/browser/ui/browser_list.h
+++ b/chrome/browser/ui/browser_list.h
@@ -110,7 +110,7 @@
   // message.
   static void CloseAllBrowsers();
 
-  // Begins shutdown of the application when the session is ending.
+  // Begins shutdown of the application when the desktop session is ending.
   static void SessionEnding();
 
   // Returns true if there is at least one Browser with the specified profile.
@@ -130,6 +130,8 @@
   // closes.
   static bool WillKeepAlive();
 
+  // Browsers are added to |browsers_| before they have constructed windows,
+  // so the |window()| member function may return NULL.
   static const_iterator begin() { return browsers_.begin(); }
   static const_iterator end() { return browsers_.end(); }
 
@@ -159,16 +161,23 @@
   // Returns true if at least one off the record session is active.
   static bool IsOffTheRecordSessionActive();
 
+  // Send out notifications.
+  // For ChromeOS, also request session manager to end the session.
+  static void NotifyAndTerminate(bool fast_path);
+
   // Called once there are no more browsers open and the application is exiting.
   static void AllBrowsersClosedAndAppExiting();
 
  private:
   // Helper method to remove a browser instance from a list of browsers
   static void RemoveBrowserFrom(Browser* browser, BrowserVector* browser_list);
-  static void NotifyAndTerminate();
+  static void MarkAsCleanShutdown();
 #if defined(OS_CHROMEOS)
   static bool NeedBeforeUnloadFired();
   static bool PendingDownloads();
+  static void NotifyWindowManagerAboutSignout();
+
+  static bool signout_;
 #endif
 
   static BrowserVector browsers_;
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index 9f50a36..bcd40cf 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -105,7 +105,8 @@
 
 // Change some of the navigation parameters based on the particular URL.
 // Currently this applies to chrome://settings and the bookmark manager,
-// which we always want to open in a normal (not incognito) window.
+// which we always want to open in a normal (not incognito) window. Guest
+// session is an exception.
 void AdjustNavigateParamsForURL(browser::NavigateParams* params) {
   if (!params->target_contents &&
       params->url.scheme() == chrome::kChromeUIScheme &&
@@ -114,7 +115,7 @@
     Profile* profile =
         params->browser ? params->browser->profile() : params->profile;
 
-    if (profile->IsOffTheRecord()) {
+    if (profile->IsOffTheRecord() && !Profile::IsGuestSession()) {
       profile = profile->GetOriginalProfile();
 
       params->disposition = SINGLETON_TAB;
@@ -161,9 +162,8 @@
       // Make a new popup window. Coerce app-style if |params->browser| or the
       // |source| represents an app.
       Browser::Type type = Browser::TYPE_POPUP;
-      if ((params->browser && params->browser->type() == Browser::TYPE_APP) ||
-          (params->source_contents &&
-              params->source_contents->is_app())) {
+      if ((params->browser && (params->browser->type() & Browser::TYPE_APP)) ||
+          (params->source_contents && params->source_contents->is_app())) {
         type = Browser::TYPE_APP_POPUP;
       }
       if (profile) {
@@ -420,9 +420,8 @@
     }
 
     if (user_initiated) {
-      RenderViewHostDelegate::BrowserIntegration* integration =
-          params->target_contents->tab_contents();
-      integration->OnUserGesture();
+      static_cast<RenderViewHostDelegate*>(params->target_contents->
+          tab_contents())->OnUserGesture();
     }
 
     // Perform the actual navigation.
@@ -442,35 +441,36 @@
         params->target_contents,
         params->transition,
         user_initiated);
-  } else {
-    if (params->disposition == SINGLETON_TAB && singleton_index >= 0) {
-      TabContents* target = params->browser->GetTabContentsAt(singleton_index);
+  } else if (singleton_index == -1) {
+    // If some non-default value is set for the index, we should tell the
+    // TabStripModel to respect it.
+    if (params->tabstrip_index != -1)
+      params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX;
 
-      // Load the URL if the target contents URL doesn't match. This can happen
-      // if the URL path is ignored when locating the singleton tab.
-      if (target->GetURL() != params->url) {
-        target->controller().LoadURL(
-            params->url, params->referrer, params->transition);
-      }
+    // The navigation should insert a new tab into the target Browser.
+    params->browser->tabstrip_model()->AddTabContents(
+        params->target_contents,
+        params->tabstrip_index,
+        params->transition,
+        params->tabstrip_add_types);
+    // Now that the |params->target_contents| is safely owned by the target
+    // Browser's TabStripModel, we can release ownership.
+    target_contents_owner.ReleaseOwnership();
+  }
 
-      // The navigation should re-select an existing tab in the target Browser.
-      params->browser->SelectTabContentsAt(singleton_index, user_initiated);
-    } else {
-      // If some non-default value is set for the index, we should tell the
-      // TabStripModel to respect it.
-      if (params->tabstrip_index != -1)
-        params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX;
+  if (singleton_index >= 0) {
+    TabContents* target = params->browser->GetTabContentsAt(singleton_index);
 
-      // The navigation should insert a new tab into the target Browser.
-      params->browser->tabstrip_model()->AddTabContents(
-          params->target_contents,
-          params->tabstrip_index,
-          params->transition,
-          params->tabstrip_add_types);
-      // Now that the |params->target_contents| is safely owned by the target
-      // Browser's TabStripModel, we can release ownership.
-      target_contents_owner.ReleaseOwnership();
+    // Load the URL if the target contents URL doesn't match. This can happen
+    // if the URL path is ignored when locating the singleton tab.
+    if (target->GetURL() != params->url) {
+      target->controller().LoadURL(
+          params->url, params->referrer, params->transition);
     }
+
+    // If the singleton tab isn't already selected, select it.
+    if (params->source_contents != params->target_contents)
+      params->browser->SelectTabContentsAt(singleton_index, user_initiated);
   }
 }
 
diff --git a/chrome/browser/ui/browser_navigator.h b/chrome/browser/ui/browser_navigator.h
index 5ad52d8..2b726d0 100644
--- a/chrome/browser/ui/browser_navigator.h
+++ b/chrome/browser/ui/browser_navigator.h
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "chrome/common/page_transition_types.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class Browser;
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index a5a2291..53f613c 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -2,81 +2,79 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ui/browser_navigator_browsertest.h"
+
 #include "base/command_line.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "ipc/ipc_message.h"
 
-namespace {
+GURL BrowserNavigatorTest::GetGoogleURL() const {
+  return GURL("http://www.google.com/");
+}
 
-class BrowserNavigatorTest : public InProcessBrowserTest,
-                             public NotificationObserver {
- protected:
-  GURL GetGoogleURL() const {
-    return GURL("http://www.google.com/");
-  }
+browser::NavigateParams BrowserNavigatorTest::MakeNavigateParams() const {
+  return MakeNavigateParams(browser());
+}
 
-  browser::NavigateParams MakeNavigateParams() const {
-    return MakeNavigateParams(browser());
-  }
-  browser::NavigateParams MakeNavigateParams(Browser* browser) const {
-    browser::NavigateParams params(browser, GetGoogleURL(),
-                                   PageTransition::LINK);
-    params.show_window = true;
-    return params;
-  }
+browser::NavigateParams BrowserNavigatorTest::MakeNavigateParams(
+    Browser* browser) const {
+  browser::NavigateParams params(browser, GetGoogleURL(),
+                                 PageTransition::LINK);
+  params.show_window = true;
+  return params;
+}
 
-  Browser* CreateEmptyBrowserForType(Browser::Type type, Profile* profile) {
-    Browser* browser = Browser::CreateForType(type, profile);
-    browser->AddBlankTab(true);
-    return browser;
-  }
+Browser* BrowserNavigatorTest::CreateEmptyBrowserForType(Browser::Type type,
+                                                         Profile* profile) {
+  Browser* browser = Browser::CreateForType(type, profile);
+  browser->AddBlankTab(true);
+  return browser;
+}
 
-  TabContentsWrapper* CreateTabContents() {
-    return Browser::TabContentsFactory(
-        browser()->profile(),
-        NULL,
-        MSG_ROUTING_NONE,
-        browser()->GetSelectedTabContents(),
-        NULL);
-  }
+TabContentsWrapper* BrowserNavigatorTest::CreateTabContents() {
+  return Browser::TabContentsFactory(
+      browser()->profile(),
+      NULL,
+      MSG_ROUTING_NONE,
+      browser()->GetSelectedTabContents(),
+      NULL);
+}
 
-  void RunSuppressTest(WindowOpenDisposition disposition) {
-    GURL old_url = browser()->GetSelectedTabContents()->GetURL();
-    browser::NavigateParams p(MakeNavigateParams());
-    p.disposition = disposition;
-    browser::Navigate(&p);
+void BrowserNavigatorTest::RunSuppressTest(WindowOpenDisposition disposition) {
+  GURL old_url = browser()->GetSelectedTabContents()->GetURL();
+  browser::NavigateParams p(MakeNavigateParams());
+  p.disposition = disposition;
+  browser::Navigate(&p);
 
-    // Nothing should have happened as a result of Navigate();
-    EXPECT_EQ(1, browser()->tab_count());
-    EXPECT_EQ(1u, BrowserList::size());
-    EXPECT_EQ(old_url, browser()->GetSelectedTabContents()->GetURL());
-  }
+  // Nothing should have happened as a result of Navigate();
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_EQ(1u, BrowserList::size());
+  EXPECT_EQ(old_url, browser()->GetSelectedTabContents()->GetURL());
+}
 
-  void Observe(NotificationType type, const NotificationSource& source,
-               const NotificationDetails& details) {
-    switch (type.value) {
-      case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
-        ++this->created_tab_contents_count_;
-        break;
-      }
-      default:
-        break;
+void BrowserNavigatorTest::Observe(NotificationType type,
+                                   const NotificationSource& source,
+                                   const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
+      ++this->created_tab_contents_count_;
+      break;
     }
+    default:
+      break;
   }
+}
 
-  size_t created_tab_contents_count_;
-};
+namespace {
 
 // This test verifies that when a navigation occurs within a tab, the tab count
 // of the Browser remains the same and the current tab bears the loaded URL.
@@ -90,14 +88,14 @@
   EXPECT_EQ(1, browser()->tab_count());
 }
 
-// This test verifies that a singleton tab is refocused if one is already open
+// This test verifies that a singleton tab is refocused if one is already opened
 // in another or an existing window, or added if it is not.
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_SingletonTabExisting) {
   GURL url("http://www.google.com/");
   GURL singleton_url1("http://maps.google.com/");
 
   // Register for a notification if an additional tab_contents was instantiated.
-  // Opening a Singleton tab that is already open should not be opening a new
+  // Opening a Singleton tab that is already opened should not be opening a new
   // tab nor be creating a new TabContents object
   NotificationRegistrar registrar;
 
@@ -135,7 +133,7 @@
   GURL url("http://www.google.com/");
   GURL singleton_url1("http://maps.google.com/");
 
-  // We should have one browser with 3 tabs, the 3rd selected.
+  // We should have one browser with 1 tab.
   EXPECT_EQ(1u, BrowserList::size());
   EXPECT_EQ(0, browser()->selected_index());
 
@@ -261,6 +259,30 @@
 }
 
 // This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
+// from a normal popup results in a new Browser with TYPE_POPUP.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewPopupFromPopup) {
+  // Open a popup.
+  browser::NavigateParams p1(MakeNavigateParams());
+  p1.disposition = NEW_POPUP;
+  browser::Navigate(&p1);
+  // Open another popup.
+  browser::NavigateParams p2(MakeNavigateParams(p1.browser));
+  p2.disposition = NEW_POPUP;
+  browser::Navigate(&p2);
+
+  // Navigate() should have opened a new normal popup window.
+  EXPECT_NE(p1.browser, p2.browser);
+  EXPECT_EQ(Browser::TYPE_POPUP, p2.browser->type());
+
+  // We should have three windows, the browser() provided by the framework,
+  // the first popup window, and the second popup window.
+  EXPECT_EQ(3u, BrowserList::size());
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_EQ(1, p1.browser->tab_count());
+  EXPECT_EQ(1, p2.browser->tab_count());
+}
+
+// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
 // from an app frame results in a new Browser with TYPE_APP_POPUP.
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
                        Disposition_NewPopupFromAppWindow) {
@@ -284,6 +306,35 @@
 }
 
 // This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
+// from an app popup results in a new Browser also of TYPE_APP_POPUP.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
+                       Disposition_NewPopupFromAppPopup) {
+  Browser* app_browser = CreateEmptyBrowserForType(Browser::TYPE_APP,
+                                                   browser()->profile());
+  // Open an app popup.
+  browser::NavigateParams p1(MakeNavigateParams(app_browser));
+  p1.disposition = NEW_POPUP;
+  browser::Navigate(&p1);
+  // Now open another app popup.
+  browser::NavigateParams p2(MakeNavigateParams(p1.browser));
+  p2.disposition = NEW_POPUP;
+  browser::Navigate(&p2);
+
+  // Navigate() should have opened a new popup app window.
+  EXPECT_NE(browser(), p1.browser);
+  EXPECT_NE(p1.browser, p2.browser);
+  EXPECT_EQ(Browser::TYPE_APP_POPUP, p2.browser->type());
+
+  // We should now have four windows, the app window, the first app popup,
+  // the second app popup, and the original browser() provided by the framework.
+  EXPECT_EQ(4u, BrowserList::size());
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_EQ(1, app_browser->tab_count());
+  EXPECT_EQ(1, p1.browser->tab_count());
+  EXPECT_EQ(1, p2.browser->tab_count());
+}
+
+// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
 // from an extension app tab results in a new Browser with TYPE_APP_POPUP.
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
                        Disposition_NewPopupFromExtensionApp) {
@@ -597,4 +648,87 @@
             browser()->GetSelectedTabContents()->GetURL());
 }
 
+// This test verifies that constructing params with disposition = SINGLETON_TAB
+// and |ignore_paths| = true will update the current tab's URL if the currently
+// selected tab is a match but has a different path.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
+                       Disposition_SingletonTabFocused_IgnorePath) {
+  GURL singleton_url_current("chrome://settings/advanced");
+  GURL url("http://www.google.com/");
+  browser()->AddSelectedTabWithURL(singleton_url_current, PageTransition::LINK);
+
+  // We should have one browser with 2 tabs, the 2nd selected.
+  EXPECT_EQ(1u, BrowserList::size());
+  EXPECT_EQ(2, browser()->tab_count());
+  EXPECT_EQ(1, browser()->selected_index());
+
+  // Navigate to a different settings path.
+  GURL singleton_url_target("chrome://settings/personal");
+  browser::NavigateParams p(MakeNavigateParams());
+  p.disposition = SINGLETON_TAB;
+  p.url = singleton_url_target;
+  p.show_window = true;
+  p.ignore_path = true;
+  browser::Navigate(&p);
+
+  // The second tab should still be selected, but navigated to the new path.
+  EXPECT_EQ(browser(), p.browser);
+  EXPECT_EQ(2, browser()->tab_count());
+  EXPECT_EQ(1, browser()->selected_index());
+  EXPECT_EQ(singleton_url_target,
+            browser()->GetSelectedTabContents()->GetURL());
+}
+
+// This test verifies that the settings page isn't opened in the incognito
+// window.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
+                       Disposition_Settings_UseNonIncognitoWindow) {
+  Browser* incognito_browser = CreateIncognitoBrowser();
+
+  EXPECT_EQ(2u, BrowserList::size());
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_EQ(1, incognito_browser->tab_count());
+
+  // Navigate to the settings page.
+  browser::NavigateParams p(MakeNavigateParams(incognito_browser));
+  p.disposition = SINGLETON_TAB;
+  p.url = GURL("chrome://settings");
+  p.show_window = true;
+  p.ignore_path = true;
+  browser::Navigate(&p);
+
+  // The settings page should be opened in browser() window.
+  EXPECT_NE(incognito_browser, p.browser);
+  EXPECT_EQ(browser(), p.browser);
+  EXPECT_EQ(2, browser()->tab_count());
+  EXPECT_EQ(GURL("chrome://settings"),
+            browser()->GetSelectedTabContents()->GetURL());
+}
+
+// This test verifies that the bookmarks page isn't opened in the incognito
+// window.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
+                       Disposition_Bookmarks_UseNonIncognitoWindow) {
+  Browser* incognito_browser = CreateIncognitoBrowser();
+
+  EXPECT_EQ(2u, BrowserList::size());
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_EQ(1, incognito_browser->tab_count());
+
+  // Navigate to the settings page.
+  browser::NavigateParams p(MakeNavigateParams(incognito_browser));
+  p.disposition = SINGLETON_TAB;
+  p.url = GURL("chrome://bookmarks");
+  p.show_window = true;
+  p.ignore_path = true;
+  browser::Navigate(&p);
+
+  // The bookmarks page should be opened in browser() window.
+  EXPECT_NE(incognito_browser, p.browser);
+  EXPECT_EQ(browser(), p.browser);
+  EXPECT_EQ(2, browser()->tab_count());
+  EXPECT_EQ(GURL("chrome://bookmarks"),
+            browser()->GetSelectedTabContents()->GetURL());
+}
+
 }  // namespace
diff --git a/chrome/browser/ui/browser_navigator_browsertest.h b/chrome/browser/ui/browser_navigator_browsertest.h
new file mode 100644
index 0000000..0f18da5
--- /dev/null
+++ b/chrome/browser/ui/browser_navigator_browsertest.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_BROWSER_NAVIGATOR_BROWSERTEST_H_
+#define CHROME_BROWSER_UI_BROWSER_NAVIGATOR_BROWSERTEST_H_
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/test/in_process_browser_test.h"
+
+class GURL;
+class NotificationDetails;
+class NotificationSource;
+class Profile;
+class TabContentsWrapper;
+
+namespace browser {
+struct NavigateParams;
+}
+
+// Browsertest class for testing the browser navigation. It is also a base class
+// for the |BrowserGuestModeNavigation| which tests navigation while in guest
+// mode.
+class BrowserNavigatorTest : public InProcessBrowserTest,
+                             public NotificationObserver {
+ protected:
+  GURL GetGoogleURL() const;
+
+  browser::NavigateParams MakeNavigateParams() const;
+  browser::NavigateParams MakeNavigateParams(Browser* browser) const;
+
+  Browser* CreateEmptyBrowserForType(Browser::Type type, Profile* profile);
+
+  TabContentsWrapper* CreateTabContents();
+
+  void RunSuppressTest(WindowOpenDisposition disposition);
+
+  void Observe(NotificationType type, const NotificationSource& source,
+               const NotificationDetails& details);
+
+  size_t created_tab_contents_count_;
+};
+
+#endif  // CHROME_BROWSER_UI_BROWSER_NAVIGATOR_BROWSERTEST_H_
diff --git a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
new file mode 100644
index 0000000..960d244
--- /dev/null
+++ b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/browser_navigator_browsertest.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_navigator.h"
+
+namespace {
+
+// Subclass that tests navigation while in the Guest session.
+class BrowserGuestSessionNavigatorTest: public BrowserNavigatorTest {
+ protected:
+  virtual void SetUpCommandLine(CommandLine* command_line) {
+    CommandLine command_line_copy = *command_line;
+    chromeos::LoginUtils::Get()->GetOffTheRecordCommandLine(GetGoogleURL(),
+                                                            command_line_copy,
+                                                            command_line);
+  }
+};
+
+// This test verifies that the settings page is opened in the incognito window
+// in Guest Session (as well as all other windows in Guest session).
+IN_PROC_BROWSER_TEST_F(BrowserGuestSessionNavigatorTest,
+                       Disposition_Settings_UseIncognitoWindow) {
+  Browser* incognito_browser = CreateIncognitoBrowser();
+
+  EXPECT_EQ(2u, BrowserList::size());
+  EXPECT_EQ(1, browser()->tab_count());
+  EXPECT_EQ(1, incognito_browser->tab_count());
+
+  // Navigate to the settings page.
+  browser::NavigateParams p(MakeNavigateParams(incognito_browser));
+  p.disposition = SINGLETON_TAB;
+  p.url = GURL("chrome://settings");
+  p.show_window = true;
+  p.ignore_path = true;
+  browser::Navigate(&p);
+
+  // Settings page should be opened in incognito window.
+  EXPECT_NE(browser(), p.browser);
+  EXPECT_EQ(incognito_browser, p.browser);
+  EXPECT_EQ(2, incognito_browser->tab_count());
+  EXPECT_EQ(GURL("chrome://settings"),
+            incognito_browser->GetSelectedTabContents()->GetURL());
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index 154431e..c297122 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/common/content_settings_types.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Browser;
 class BrowserWindowTesting;
@@ -119,6 +119,11 @@
   // currently maximized or minimized) in terms of the screen coordinates.
   virtual gfx::Rect GetRestoredBounds() const = 0;
 
+  // Retrieves the window's current bounds, including its frame.
+  // This will only differ from GetRestoredBounds() for maximized
+  // and minimized windows.
+  virtual gfx::Rect GetBounds() const = 0;
+
   // TODO(beng): REMOVE?
   // Returns true if the frame is maximized (aka zoomed).
   virtual bool IsMaximized() const = 0;
@@ -206,6 +211,9 @@
   // Shows the Task manager.
   virtual void ShowTaskManager() = 0;
 
+  // Shows task information related to background pages.
+  virtual void ShowBackgroundPages() = 0;
+
   // Shows the Bookmark bubble. |url| is the URL being bookmarked,
   // |already_bookmarked| is true if the url is already bookmarked.
   virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked) = 0;
@@ -216,9 +224,6 @@
   // Returns the DownloadShelf.
   virtual DownloadShelf* GetDownloadShelf() = 0;
 
-  // Shows the Report a Bug dialog box.
-  virtual void ShowReportBugDialog() = 0;
-
   // Shows the Clear Browsing Data dialog box.
   virtual void ShowClearBrowsingDataDialog() = 0;
 
diff --git a/chrome/browser/ui/cocoa/OWNERS b/chrome/browser/ui/cocoa/OWNERS
new file mode 100644
index 0000000..4b87745
--- /dev/null
+++ b/chrome/browser/ui/cocoa/OWNERS
@@ -0,0 +1,2 @@
+mark@chromium.org
+pinkerton@chromium.org
diff --git a/chrome/browser/ui/cocoa/about_ipc_bridge.h b/chrome/browser/ui/cocoa/about_ipc_bridge.h
deleted file mode 100644
index 77041b3..0000000
--- a/chrome/browser/ui/cocoa/about_ipc_bridge.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_ABOUT_IPC_BRIDGE_H_
-#define CHROME_BROWSER_UI_COCOA_ABOUT_IPC_BRIDGE_H_
-#pragma once
-
-#include "ipc/ipc_logging.h"
-#include "ipc/ipc_message_utils.h"
-
-#if defined(IPC_MESSAGE_LOG_ENABLED)
-
-@class AboutIPCController;
-
-// On Windows, the AboutIPCDialog is a views::View.  On Mac we have a
-// Cocoa dialog.  This class bridges from C++ to ObjC.
-class AboutIPCBridge : public IPC::Logging::Consumer {
- public:
-  AboutIPCBridge(AboutIPCController* controller) : controller_(controller) { }
-  virtual ~AboutIPCBridge() { }
-
-  // IPC::Logging::Consumer implementation.
-  virtual void Log(const IPC::LogData& data);
-
- private:
-  AboutIPCController* controller_;  // weak; owns me
-  DISALLOW_COPY_AND_ASSIGN(AboutIPCBridge);
-};
-
-#endif  // IPC_MESSAGE_LOG_ENABLED
-
-#endif  // CHROME_BROWSER_UI_COCOA_ABOUT_IPC_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/about_ipc_bridge.mm b/chrome/browser/ui/cocoa/about_ipc_bridge.mm
deleted file mode 100644
index 7a7f41f..0000000
--- a/chrome/browser/ui/cocoa/about_ipc_bridge.mm
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/about_ipc_bridge.h"
-#include "chrome/browser/ui/cocoa/about_ipc_controller.h"
-
-#if defined(IPC_MESSAGE_LOG_ENABLED)
-
-void AboutIPCBridge::Log(const IPC::LogData& data) {
-  CocoaLogData* cocoa_data = [[CocoaLogData alloc] initWithLogData:data];
-  if ([NSThread isMainThread]) {
-    [controller_ log:cocoa_data];
-  } else {
-    [controller_ performSelectorOnMainThread:@selector(log:)
-                                  withObject:cocoa_data
-                               waitUntilDone:NO];
-  }
-}
-
-#endif
diff --git a/chrome/browser/ui/cocoa/about_ipc_controller.h b/chrome/browser/ui/cocoa/about_ipc_controller.h
index f0818f9..f0d4075 100644
--- a/chrome/browser/ui/cocoa/about_ipc_controller.h
+++ b/chrome/browser/ui/cocoa/about_ipc_controller.h
@@ -14,7 +14,7 @@
 #include "third_party/GTM/Foundation/GTMRegex.h"
 
 // Must be included after IPC_MESSAGE_LOG_ENABLED gets defined
-#import "chrome/browser/ui/cocoa/about_ipc_bridge.h"
+#import "chrome/browser/ui/cocoa/about_ipc_dialog.h"
 
 #if defined(IPC_MESSAGE_LOG_ENABLED)
 
diff --git a/chrome/browser/ui/cocoa/about_ipc_dialog.h b/chrome/browser/ui/cocoa/about_ipc_dialog.h
index 3eb2bcd..f93fff9 100644
--- a/chrome/browser/ui/cocoa/about_ipc_dialog.h
+++ b/chrome/browser/ui/cocoa/about_ipc_dialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,19 +6,33 @@
 #define CHROME_BROWSER_UI_COCOA_ABOUT_IPC_DIALOG_H_
 #pragma once
 
-#include "ipc/ipc_message.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message_utils.h"
 
 #if defined(IPC_MESSAGE_LOG_ENABLED)
 
-namespace AboutIPCDialog {
-// The dialog is a singleton. If the dialog is already opened, it won't do
-// anything, so you can just blindly call this function all you want.
-// RunDialog() is Called from chrome/browser/browser_about_handler.cc
-// in response to an about:ipc URL.
-void RunDialog();
+#ifdef __OBJC__
+@class AboutIPCController;
+#else
+class AboutIPCController;
+#endif
+
+
+// On Windows, the AboutIPCDialog is a views::View.  On Mac we have a
+// Cocoa dialog.  This class bridges from C++ to ObjC.
+class AboutIPCBridge : public IPC::Logging::Consumer {
+ public:
+  AboutIPCBridge(AboutIPCController* controller) : controller_(controller) { }
+  virtual ~AboutIPCBridge() { }
+
+  // IPC::Logging::Consumer implementation.
+  virtual void Log(const IPC::LogData& data);
+
+ private:
+  AboutIPCController* controller_;  // weak; owns me
+  DISALLOW_COPY_AND_ASSIGN(AboutIPCBridge);
 };
 
+#endif  // IPC_MESSAGE_LOG_ENABLED
 
-#endif  /* IPC_MESSAGE_LOG_ENABLED */
-
-#endif  /* CHROME_BROWSER_UI_COCOA_ABOUT_IPC_DIALOG_H_ */
+#endif  // CHROME_BROWSER_UI_COCOA_ABOUT_IPC_DIALOG_H_
diff --git a/chrome/browser/ui/cocoa/about_ipc_dialog.mm b/chrome/browser/ui/cocoa/about_ipc_dialog.mm
index 7715f24..6cf14b1 100644
--- a/chrome/browser/ui/cocoa/about_ipc_dialog.mm
+++ b/chrome/browser/ui/cocoa/about_ipc_dialog.mm
@@ -1,21 +1,33 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/cocoa/about_ipc_dialog.h"
 #include "chrome/browser/ui/cocoa/about_ipc_controller.h"
 
 #if defined(IPC_MESSAGE_LOG_ENABLED)
 
-namespace AboutIPCDialog {
+namespace browser {
 
-void RunDialog() {
+void ShowAboutIPCDialog() {
   // The controller gets deallocated when then window is closed,
   // so it is safe to "fire and forget".
   AboutIPCController* controller = [AboutIPCController sharedController];
   [[controller window] makeKeyAndOrderFront:controller];
 }
 
-};  // namespace AboutIPCDialog
+}  // namespace browser
+
+void AboutIPCBridge::Log(const IPC::LogData& data) {
+  CocoaLogData* cocoa_data = [[CocoaLogData alloc] initWithLogData:data];
+  if ([NSThread isMainThread]) {
+    [controller_ log:cocoa_data];
+  } else {
+    [controller_ performSelectorOnMainThread:@selector(log:)
+                                  withObject:cocoa_data
+                               waitUntilDone:NO];
+  }
+}
 
 #endif  // IPC_MESSAGE_LOG_ENABLED
diff --git a/chrome/browser/ui/cocoa/about_window_controller.mm b/chrome/browser/ui/cocoa/about_window_controller.mm
index f83c9a1..af08577 100644
--- a/chrome/browser/ui/cocoa/about_window_controller.mm
+++ b/chrome/browser/ui/cocoa/about_window_controller.mm
@@ -1,12 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/about_window_controller.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "base/string_number_conversions.h"
@@ -14,10 +11,10 @@
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
+#import "chrome/browser/cocoa/keystone_glue.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/platform_util.h"
 #import "chrome/browser/ui/cocoa/background_tile_view.h"
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
 #include "chrome/browser/ui/cocoa/restart_browser.h"
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
@@ -25,6 +22,9 @@
 #include "grit/theme_resources.h"
 #include "grit/locale_settings.h"
 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -645,7 +645,7 @@
   // it the best we can to get all the information in (they actually do it
   // but created Labels and Links that they carefully place to make it appear
   // to be a paragraph of text).
-  // src/chrome/browser/views/about_chrome_view.cc AboutChromeView::Init()
+  // src/chrome/browser/ui/views/about_chrome_view.cc AboutChromeView::Init()
 
   NSMutableAttributedString* legal_block =
       [[[NSMutableAttributedString alloc] init] autorelease];
diff --git a/chrome/browser/ui/cocoa/about_window_controller_unittest.mm b/chrome/browser/ui/cocoa/about_window_controller_unittest.mm
index 4747efe..4b57809 100644
--- a/chrome/browser/ui/cocoa/about_window_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/about_window_controller_unittest.mm
@@ -5,10 +5,10 @@
 #import <Cocoa/Cocoa.h>
 
 #import "base/scoped_nsobject.h"
+#import "chrome/browser/cocoa/keystone_glue.h"
 #import "chrome/browser/ui/cocoa/about_window_controller.h"
 #include "chrome/browser/ui/cocoa/browser_test_helper.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa.h b/chrome/browser/ui/cocoa/accelerators_cocoa.h
index 9b0a555..c4c5521 100644
--- a/chrome/browser/ui/cocoa/accelerators_cocoa.h
+++ b/chrome/browser/ui/cocoa/accelerators_cocoa.h
@@ -8,7 +8,7 @@
 
 #include <map>
 
-#include "app/menus/accelerator_cocoa.h"
+#include "ui/base/models/accelerator_cocoa.h"
 
 template <typename T> struct DefaultSingletonTraits;
 
@@ -26,10 +26,10 @@
 //
 class AcceleratorsCocoa {
  public:
-  typedef std::map<int, menus::AcceleratorCocoa> AcceleratorCocoaMap;
+  typedef std::map<int, ui::AcceleratorCocoa> AcceleratorCocoaMap;
 
   // Returns NULL if there is no accelerator for the command.
-  const menus::AcceleratorCocoa* GetAcceleratorForCommand(int command_id);
+  const ui::AcceleratorCocoa* GetAcceleratorForCommand(int command_id);
 
   // Returns the singleton instance.
   static AcceleratorsCocoa* GetInstance();
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa.mm b/chrome/browser/ui/cocoa/accelerators_cocoa.mm
index 6f28a0f..f62bd50 100644
--- a/chrome/browser/ui/cocoa/accelerators_cocoa.mm
+++ b/chrome/browser/ui/cocoa/accelerators_cocoa.mm
@@ -44,7 +44,7 @@
 AcceleratorsCocoa::AcceleratorsCocoa() {
   for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) {
     const AcceleratorMapping& entry = kAcceleratorMap[i];
-    menus::AcceleratorCocoa accelerator(entry.key, entry.modifiers);
+    ui::AcceleratorCocoa accelerator(entry.key, entry.modifiers);
     accelerators_.insert(std::make_pair(entry.command_id, accelerator));
   }
 }
@@ -54,7 +54,7 @@
   return Singleton<AcceleratorsCocoa>::get();
 }
 
-const menus::AcceleratorCocoa* AcceleratorsCocoa::GetAcceleratorForCommand(
+const ui::AcceleratorCocoa* AcceleratorsCocoa::GetAcceleratorForCommand(
     int command_id) {
   AcceleratorCocoaMap::iterator it = accelerators_.find(command_id);
   if (it == accelerators_.end())
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa_unittest.mm b/chrome/browser/ui/cocoa/accelerators_cocoa_unittest.mm
index ef1436d..2a39ffe 100644
--- a/chrome/browser/ui/cocoa/accelerators_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/accelerators_cocoa_unittest.mm
@@ -4,16 +4,16 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/menus/accelerator_cocoa.h"
 #include "base/singleton.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/accelerators_cocoa.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
+#include "ui/base/models/accelerator_cocoa.h"
 
 TEST(AcceleratorsCocoaTest, GetAccelerator) {
   AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance();
-  const menus::AcceleratorCocoa* accelerator =
+  const ui::AcceleratorCocoa* accelerator =
       keymap->GetAcceleratorForCommand(IDC_COPY);
   ASSERT_TRUE(accelerator);
   EXPECT_NSEQ(@"c", accelerator->characters());
@@ -22,7 +22,7 @@
 
 TEST(AcceleratorsCocoaTest, GetNullAccelerator) {
   AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance();
-  const menus::AcceleratorCocoa* accelerator =
+  const ui::AcceleratorCocoa* accelerator =
       keymap->GetAcceleratorForCommand(314159265);
   EXPECT_FALSE(accelerator);
 }
diff --git a/chrome/browser/ui/cocoa/animatable_image.h b/chrome/browser/ui/cocoa/animatable_image.h
index 65fd023..a6f8ab9 100644
--- a/chrome/browser/ui/cocoa/animatable_image.h
+++ b/chrome/browser/ui/cocoa/animatable_image.h
@@ -36,11 +36,11 @@
   CGFloat duration_;
 }
 
-@property (nonatomic) CGRect startFrame;
-@property (nonatomic) CGRect endFrame;
-@property (nonatomic) CGFloat startOpacity;
-@property (nonatomic) CGFloat endOpacity;
-@property (nonatomic) CGFloat duration;
+@property(nonatomic) CGRect startFrame;
+@property(nonatomic) CGRect endFrame;
+@property(nonatomic) CGFloat startOpacity;
+@property(nonatomic) CGFloat endOpacity;
+@property(nonatomic) CGFloat duration;
 
 // Designated initializer. Do not use any other NSWindow initializers. Creates
 // but does not show the blank animation window of the given size. The
diff --git a/chrome/browser/ui/cocoa/applescript/OWNERS b/chrome/browser/ui/cocoa/applescript/OWNERS
new file mode 100644
index 0000000..cda345a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/applescript/OWNERS
@@ -0,0 +1 @@
+pinkerton@chromium.org
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h
index 41e22d2..293d738 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,7 +23,7 @@
  @public
   BrowserTestHelper* helper_;  // weak.
 }
-@property (nonatomic) BrowserTestHelper* helper;
+@property(nonatomic) BrowserTestHelper* helper;
 // Return the |TestingProfile*| which is used for testing.
 - (Profile*)defaultProfile;
 @end
@@ -41,6 +41,7 @@
 class BookmarkAppleScriptTest : public CocoaTest {
  public:
   BookmarkAppleScriptTest();
+  virtual ~BookmarkAppleScriptTest();
  private:
   BrowserTestHelper helper_;
   scoped_nsobject<FakeAppDelegate> appDelegate_;
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm
index 108b1fb..353e592 100644
--- a/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm
+++ b/chrome/browser/ui/cocoa/applescript/bookmark_applescript_utils_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -49,6 +49,7 @@
 BookmarkAppleScriptTest::BookmarkAppleScriptTest() {
   appDelegate_.reset([[FakeAppDelegate alloc] init]);
   [appDelegate_.get() setHelper:&helper_];
+  DCHECK([NSApp delegate] == nil);
   [NSApp setDelegate:appDelegate_];
   const BookmarkNode* root = model().GetBookmarkBarNode();
   const std::string modelString("a f1:[ b d c ] d f2:[ e f g ] h ");
@@ -57,6 +58,10 @@
       initWithBookmarkNode:model().GetBookmarkBarNode()]);
 }
 
+BookmarkAppleScriptTest::~BookmarkAppleScriptTest() {
+  [NSApp setDelegate:nil];
+}
+
 BookmarkModel& BookmarkAppleScriptTest::model() {
   return *helper_.profile()->GetBookmarkModel();
 }
diff --git a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm
index 31af858..73e5167 100644
--- a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm
+++ b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm
@@ -10,9 +10,9 @@
 #import "chrome/browser/ui/cocoa/applescript/constants_applescript.h"
 #import "chrome/browser/ui/cocoa/applescript/window_applescript.h"
 #include "chrome/test/in_process_browser_test.h"
-#include "gfx/size.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
+#include "ui/gfx/size.h"
 
 typedef InProcessBrowserTest BrowserCrApplicationAppleScriptTest;
 
diff --git a/chrome/browser/ui/cocoa/applescript/element_applescript.h b/chrome/browser/ui/cocoa/applescript/element_applescript.h
index 49a3481..b53c01c 100644
--- a/chrome/browser/ui/cocoa/applescript/element_applescript.h
+++ b/chrome/browser/ui/cocoa/applescript/element_applescript.h
@@ -19,9 +19,9 @@
   NSString* containerProperty_;
 }
 
-@property (nonatomic, copy) NSNumber* uniqueID;
-@property (nonatomic, retain) id container;
-@property (nonatomic, copy) NSString* containerProperty;
+@property(nonatomic, copy) NSNumber* uniqueID;
+@property(nonatomic, retain) id container;
+@property(nonatomic, copy) NSString* containerProperty;
 
 // Calculates the objectspecifier by using the uniqueID, container and
 // container property.
diff --git a/chrome/browser/ui/cocoa/applescript/error_applescript.mm b/chrome/browser/ui/cocoa/applescript/error_applescript.mm
index e86ffd0..1c9d72b 100644
--- a/chrome/browser/ui/cocoa/applescript/error_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/error_applescript.mm
@@ -4,9 +4,9 @@
 
 #import "chrome/browser/ui/cocoa/applescript/error_applescript.h"
 
-#import "app/l10n_util_mac.h"
 #include "base/logging.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 void AppleScript::SetError(AppleScript::ErrorCode errorCode) {
   using namespace l10n_util;
diff --git a/chrome/browser/ui/cocoa/applescript/tab_applescript.mm b/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
index 3a10095..b99fcd8 100644
--- a/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
@@ -285,9 +285,9 @@
     return nil;
   }
 
-  std::wstring script = base::SysNSStringToWide(
+  string16 script = base::SysNSStringToUTF16(
       [[command evaluatedArguments] objectForKey:@"javascript"]);
-  view->ExecuteJavascriptInWebFrame(L"", script);
+  view->ExecuteJavascriptInWebFrame(string16(), script);
 
   // TODO(Shreyas): Figure out a way to get the response back.
   return nil;
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.mm b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
index d6c7b5a..3bc817d 100644
--- a/chrome/browser/ui/cocoa/applescript/window_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
@@ -180,7 +180,6 @@
 
 - (void)insertInTabs:(TabAppleScript*)aTab atIndex:(int)index {
   // This method gets called when a new tab is created so
-  // This method gets called when a new tab is created so
   // the container and property are set here.
   [aTab setContainer:self
             property:AppleScript::kTabsProperty];
diff --git a/chrome/browser/ui/cocoa/authorization_util.h b/chrome/browser/ui/cocoa/authorization_util.h
deleted file mode 100644
index 9694998..0000000
--- a/chrome/browser/ui/cocoa/authorization_util.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_AUTHORIZATION_UTIL_H_
-#define CHROME_BROWSER_UI_COCOA_AUTHORIZATION_UTIL_H_
-#pragma once
-
-// AuthorizationExecuteWithPrivileges fork()s and exec()s the tool, but it
-// does not wait() for it.  It also doesn't provide the caller with access to
-// the forked pid.  If used irresponsibly, zombie processes will accumulate.
-//
-// Apple's really gotten us between a rock and a hard place, here.
-//
-// Fortunately, AuthorizationExecuteWithPrivileges does give access to the
-// tool's stdout (and stdin) via a FILE* pipe.  The tool can output its pid
-// to this pipe, and the main program can read it, and then have something
-// that it can wait() for.
-//
-// The contract is that any tool executed by the wrappers declared in this
-// file must print its pid to stdout on a line by itself before doing anything
-// else.
-//
-// http://developer.apple.com/mac/library/samplecode/BetterAuthorizationSample/listing1.html
-// (Look for "What's This About Zombies?")
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/Authorization.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-namespace authorization_util {
-
-// Obtains an AuthorizationRef that can be used to run commands as root.  If
-// necessary, prompts the user for authentication.  If the user is prompted,
-// |prompt| will be used as the prompt string and an icon appropriate for the
-// application will be displayed in a prompt dialog.  Note that the system
-// appends its own text to the prompt string.  Returns NULL on failure.
-AuthorizationRef AuthorizationCreateToRunAsRoot(CFStringRef prompt);
-
-// Calls straight through to AuthorizationExecuteWithPrivileges.  If that
-// call succeeds, |pid| will be set to the pid of the executed tool.  If the
-// pid can't be determined, |pid| will be set to -1.  |pid| must not be NULL.
-// |pipe| may be NULL, but the tool will always be executed with a pipe in
-// order to read the pid from its stdout.
-OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization,
-                                        const char* tool_path,
-                                        AuthorizationFlags options,
-                                        const char** arguments,
-                                        FILE** pipe,
-                                        pid_t* pid);
-
-// Calls ExecuteWithPrivilegesAndGetPID, and if that call succeeds, calls
-// waitpid() to wait for the process to exit.  If waitpid() succeeds, the
-// exit status is placed in |exit_status|, otherwise, -1 is stored.
-// |exit_status| may be NULL and this function will still wait for the process
-// to exit.
-OSStatus ExecuteWithPrivilegesAndWait(AuthorizationRef authorization,
-                                      const char* tool_path,
-                                      AuthorizationFlags options,
-                                      const char** arguments,
-                                      FILE** pipe,
-                                      int* exit_status);
-
-}  // namespace authorization_util
-
-#endif  // CHROME_BROWSER_UI_COCOA_AUTHORIZATION_UTIL_H_
diff --git a/chrome/browser/ui/cocoa/authorization_util.mm b/chrome/browser/ui/cocoa/authorization_util.mm
deleted file mode 100644
index 9c434f3..0000000
--- a/chrome/browser/ui/cocoa/authorization_util.mm
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/authorization_util.h"
-
-#import <Foundation/Foundation.h>
-#include <sys/wait.h>
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/eintr_wrapper.h"
-#include "base/logging.h"
-#import "base/mac/mac_util.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-#include "chrome/browser/ui/cocoa/scoped_authorizationref.h"
-
-namespace authorization_util {
-
-AuthorizationRef AuthorizationCreateToRunAsRoot(CFStringRef prompt) {
-  // Create an empty AuthorizationRef.
-  scoped_AuthorizationRef authorization;
-  OSStatus status = AuthorizationCreate(NULL,
-                                        kAuthorizationEmptyEnvironment,
-                                        kAuthorizationFlagDefaults,
-                                        &authorization);
-  if (status != errAuthorizationSuccess) {
-    LOG(ERROR) << "AuthorizationCreate: " << status;
-    return NULL;
-  }
-
-  // Specify the "system.privilege.admin" right, which allows
-  // AuthorizationExecuteWithPrivileges to run commands as root.
-  AuthorizationItem right_items[] = {
-    {kAuthorizationRightExecute, 0, NULL, 0}
-  };
-  AuthorizationRights rights = {arraysize(right_items), right_items};
-
-  // product_logo_32.png is used instead of app.icns because Authorization
-  // Services can't deal with .icns files.
-  NSString* icon_path =
-      [base::mac::MainAppBundle() pathForResource:@"product_logo_32"
-                                          ofType:@"png"];
-  const char* icon_path_c = [icon_path fileSystemRepresentation];
-  size_t icon_path_length = icon_path_c ? strlen(icon_path_c) : 0;
-
-  // The OS will append " Type an administrator's name and password to allow
-  // <CFBundleDisplayName> to make changes."
-  NSString* prompt_ns = base::mac::CFToNSCast(prompt);
-  const char* prompt_c = [prompt_ns UTF8String];
-  size_t prompt_length = prompt_c ? strlen(prompt_c) : 0;
-
-  AuthorizationItem environment_items[] = {
-    {kAuthorizationEnvironmentIcon, icon_path_length, (void*)icon_path_c, 0},
-    {kAuthorizationEnvironmentPrompt, prompt_length, (void*)prompt_c, 0}
-  };
-
-  AuthorizationEnvironment environment = {arraysize(environment_items),
-                                          environment_items};
-
-  AuthorizationFlags flags = kAuthorizationFlagDefaults |
-                             kAuthorizationFlagInteractionAllowed |
-                             kAuthorizationFlagExtendRights |
-                             kAuthorizationFlagPreAuthorize;
-
-  status = AuthorizationCopyRights(authorization,
-                                   &rights,
-                                   &environment,
-                                   flags,
-                                   NULL);
-  if (status != errAuthorizationSuccess) {
-    if (status != errAuthorizationCanceled) {
-      LOG(ERROR) << "AuthorizationCopyRights: " << status;
-    }
-    return NULL;
-  }
-
-  return authorization.release();
-}
-
-OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization,
-                                        const char* tool_path,
-                                        AuthorizationFlags options,
-                                        const char** arguments,
-                                        FILE** pipe,
-                                        pid_t* pid) {
-  // pipe may be NULL, but this function needs one.  In that case, use a local
-  // pipe.
-  FILE* local_pipe;
-  FILE** pipe_pointer;
-  if (pipe) {
-    pipe_pointer = pipe;
-  } else {
-    pipe_pointer = &local_pipe;
-  }
-
-  // AuthorizationExecuteWithPrivileges wants |char* const*| for |arguments|,
-  // but it doesn't actually modify the arguments, and that type is kind of
-  // silly and callers probably aren't dealing with that.  Put the cast here
-  // to make things a little easier on callers.
-  OSStatus status = AuthorizationExecuteWithPrivileges(authorization,
-                                                       tool_path,
-                                                       options,
-                                                       (char* const*)arguments,
-                                                       pipe_pointer);
-  if (status != errAuthorizationSuccess) {
-    return status;
-  }
-
-  int line_pid = -1;
-  size_t line_length = 0;
-  char* line_c = fgetln(*pipe_pointer, &line_length);
-  if (line_c) {
-    if (line_length > 0 && line_c[line_length - 1] == '\n') {
-      // line_c + line_length is the start of the next line if there is one.
-      // Back up one character.
-      --line_length;
-    }
-    std::string line(line_c, line_length);
-    if (!base::StringToInt(line, &line_pid)) {
-      // StringToInt may have set line_pid to something, but if the conversion
-      // was imperfect, use -1.
-      LOG(ERROR) << "ExecuteWithPrivilegesAndGetPid: funny line: " << line;
-      line_pid = -1;
-    }
-  } else {
-    LOG(ERROR) << "ExecuteWithPrivilegesAndGetPid: no line";
-  }
-
-  if (!pipe) {
-    fclose(*pipe_pointer);
-  }
-
-  if (pid) {
-    *pid = line_pid;
-  }
-
-  return status;
-}
-
-OSStatus ExecuteWithPrivilegesAndWait(AuthorizationRef authorization,
-                                      const char* tool_path,
-                                      AuthorizationFlags options,
-                                      const char** arguments,
-                                      FILE** pipe,
-                                      int* exit_status) {
-  pid_t pid;
-  OSStatus status = ExecuteWithPrivilegesAndGetPID(authorization,
-                                                   tool_path,
-                                                   options,
-                                                   arguments,
-                                                   pipe,
-                                                   &pid);
-  if (status != errAuthorizationSuccess) {
-    return status;
-  }
-
-  // exit_status may be NULL, but this function needs it.  In that case, use a
-  // local version.
-  int local_exit_status;
-  int* exit_status_pointer;
-  if (exit_status) {
-    exit_status_pointer = exit_status;
-  } else {
-    exit_status_pointer = &local_exit_status;
-  }
-
-  if (pid != -1) {
-    pid_t wait_result = HANDLE_EINTR(waitpid(pid, exit_status_pointer, 0));
-    if (wait_result != pid) {
-      PLOG(ERROR) << "waitpid";
-      *exit_status_pointer = -1;
-    }
-  } else {
-    *exit_status_pointer = -1;
-  }
-
-  return status;
-}
-
-}  // namespace authorization_util
diff --git a/chrome/browser/ui/cocoa/back_forward_menu_controller.h b/chrome/browser/ui/cocoa/back_forward_menu_controller.h
deleted file mode 100644
index 7e58051..0000000
--- a/chrome/browser/ui/cocoa/back_forward_menu_controller.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_BACK_FORWARD_MENU_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_BACK_FORWARD_MENU_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
-
-@class MenuButton;
-
-typedef BackForwardMenuModel::ModelType BackForwardMenuType;
-const BackForwardMenuType BACK_FORWARD_MENU_TYPE_BACK =
-    BackForwardMenuModel::BACKWARD_MENU;
-const BackForwardMenuType BACK_FORWARD_MENU_TYPE_FORWARD =
-    BackForwardMenuModel::FORWARD_MENU;
-
-// A class that manages the back/forward menu (and delayed-menu button, and
-// model).
-
-@interface BackForwardMenuController : NSObject {
- @private
-  BackForwardMenuType type_;
-  MenuButton* button_;  // Weak; comes from nib.
-  scoped_ptr<BackForwardMenuModel> model_;
-  scoped_nsobject<NSMenu> backForwardMenu_;
-}
-
-// Type (back or forwards); can only be set on initialization.
-@property(readonly, nonatomic) BackForwardMenuType type;
-
-- (id)initWithBrowser:(Browser*)browser
-            modelType:(BackForwardMenuType)type
-               button:(MenuButton*)button;
-
-@end  // @interface BackForwardMenuController
-
-#endif  // CHROME_BROWSER_UI_COCOA_BACK_FORWARD_MENU_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/back_forward_menu_controller.mm b/chrome/browser/ui/cocoa/back_forward_menu_controller.mm
deleted file mode 100644
index 96a9a18..0000000
--- a/chrome/browser/ui/cocoa/back_forward_menu_controller.mm
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/back_forward_menu_controller.h"
-
-#include "base/logging.h"
-#include "base/scoped_ptr.h"
-#include "base/sys_string_conversions.h"
-#import "chrome/browser/ui/cocoa/event_utils.h"
-#import "chrome/browser/ui/cocoa/menu_button.h"
-#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-using base::SysUTF16ToNSString;
-using gfx::SkBitmapToNSImage;
-
-@implementation BackForwardMenuController
-
-// Accessors and mutators:
-
-@synthesize type = type_;
-
-// Own methods:
-
-- (id)initWithBrowser:(Browser*)browser
-            modelType:(BackForwardMenuType)type
-               button:(MenuButton*)button {
-  if ((self = [super init])) {
-    type_ = type;
-    button_ = button;
-    model_.reset(new BackForwardMenuModel(browser, type_));
-    DCHECK(model_.get());
-    backForwardMenu_.reset([[NSMenu alloc] initWithTitle:@""]);
-    DCHECK(backForwardMenu_.get());
-    [backForwardMenu_ setDelegate:self];
-
-    [button_ setAttachedMenu:backForwardMenu_];
-    [button_ setOpenMenuOnClick:NO];
-  }
-  return self;
-}
-
-// Methods as delegate:
-
-// Called by backForwardMenu_ just before tracking begins.
-//TODO(viettrungluu): should we do anything for chapter stops (see model)?
-- (void)menuNeedsUpdate:(NSMenu*)menu {
-  DCHECK(menu == backForwardMenu_);
-
-  // Remove old menu items (backwards order is as good as any).
-  for (NSInteger i = [menu numberOfItems]; i > 0; i--)
-    [menu removeItemAtIndex:(i - 1)];
-
-  // 0-th item must be blank. (This is because we use a pulldown list, for which
-  // Cocoa uses the 0-th item as "title" in the button.)
-  [menu insertItemWithTitle:@""
-                     action:nil
-              keyEquivalent:@""
-                    atIndex:0];
-  for (int menuID = 0; menuID < model_->GetItemCount(); menuID++) {
-    if (model_->IsSeparator(menuID)) {
-      [menu insertItem:[NSMenuItem separatorItem]
-               atIndex:(menuID + 1)];
-    } else {
-      // Create a menu item with the right label.
-      NSMenuItem* menuItem = [[NSMenuItem alloc]
-              initWithTitle:SysUTF16ToNSString(model_->GetLabelAt(menuID))
-                     action:nil
-              keyEquivalent:@""];
-      [menuItem autorelease];
-
-      SkBitmap icon;
-      // Icon (if it has one).
-      if (model_->GetIconAt(menuID, &icon))
-        [menuItem setImage:SkBitmapToNSImage(icon)];
-
-      // This will make it call our |-executeMenuItem:| method. We store the
-      // |menuID| (or |menu_id|) in the tag.
-      [menuItem setTag:menuID];
-      [menuItem setTarget:self];
-      [menuItem setAction:@selector(executeMenuItem:)];
-
-      // Put it in the menu!
-      [menu insertItem:menuItem
-               atIndex:(menuID + 1)];
-    }
-  }
-}
-
-// Action methods:
-
-- (void)executeMenuItem:(id)sender {
-  DCHECK([sender isKindOfClass:[NSMenuItem class]]);
-  int menuID = [sender tag];
-  model_->ActivatedAtWithDisposition(
-      menuID,
-      event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
-}
-
-@end  // @implementation BackForwardMenuController
diff --git a/chrome/browser/ui/cocoa/background_gradient_view.mm b/chrome/browser/ui/cocoa/background_gradient_view.mm
index 1c5735f..7b031a2 100644
--- a/chrome/browser/ui/cocoa/background_gradient_view.mm
+++ b/chrome/browser/ui/cocoa/background_gradient_view.mm
@@ -33,7 +33,7 @@
 
 - (void)drawBackground {
   BOOL isKey = [[self window] isKeyWindow];
-  ThemeProvider* themeProvider = [[self window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[self window] themeProvider];
   if (themeProvider) {
     NSColor* backgroundImageColor =
         themeProvider->GetNSImageColorNamed(IDR_THEME_TOOLBAR, false);
@@ -70,7 +70,7 @@
 
 - (NSColor*)strokeColor {
   BOOL isKey = [[self window] isKeyWindow];
-  ThemeProvider* themeProvider = [[self window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[self window] themeProvider];
   if (!themeProvider)
     return [NSColor blackColor];
   return themeProvider->GetNSColor(
diff --git a/chrome/browser/ui/cocoa/base_bubble_controller.h b/chrome/browser/ui/cocoa/base_bubble_controller.h
index 99b491a..216406b 100644
--- a/chrome/browser/ui/cocoa/base_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/base_bubble_controller.h
@@ -33,9 +33,9 @@
   scoped_ptr<BaseBubbleControllerInternal::Bridge> base_bridge_;
 }
 
-@property (nonatomic, readonly) NSWindow* parentWindow;
-@property (nonatomic, assign) NSPoint anchorPoint;
-@property (nonatomic, readonly) InfoBubbleView* bubble;
+@property(nonatomic, readonly) NSWindow* parentWindow;
+@property(nonatomic, assign) NSPoint anchorPoint;
+@property(nonatomic, readonly) InfoBubbleView* bubble;
 
 // Creates a bubble. |nibPath| is just the basename, e.g. @"FirstRunBubble".
 // |anchoredAt| is in screen space. You need to call -showWindow: to make the
diff --git a/chrome/browser/ui/cocoa/base_bubble_controller.mm b/chrome/browser/ui/cocoa/base_bubble_controller.mm
index 768e9f1..618faf9 100644
--- a/chrome/browser/ui/cocoa/base_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/base_bubble_controller.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "base/scoped_nsobject.h"
@@ -15,6 +14,7 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 @interface BaseBubbleController (Private)
 - (void)updateOriginFromAnchor;
diff --git a/chrome/browser/ui/cocoa/base_view.h b/chrome/browser/ui/cocoa/base_view.h
index 0a8da9e..bb2aeed 100644
--- a/chrome/browser/ui/cocoa/base_view.h
+++ b/chrome/browser/ui/cocoa/base_view.h
@@ -9,7 +9,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/scoped_nsobject.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 // A view that provides common functionality that many views will need:
 // - Automatic registration for mouse-moved events.
diff --git a/chrome/browser/ui/cocoa/bookmarks/OWNERS b/chrome/browser/ui/cocoa/bookmarks/OWNERS
new file mode 100644
index 0000000..df805b9
--- /dev/null
+++ b/chrome/browser/ui/cocoa/bookmarks/OWNERS
@@ -0,0 +1,2 @@
+jrg@chromium.org
+mrossetti@chromium.org
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm
index 5e8b0f2..37896a5 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/string16.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @implementation BookmarkAllTabsController
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h
index b4e4bef..81071f1 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -33,6 +33,13 @@
 // The height of buttons in the bookmark bar.
 const int kBookmarkButtonHeight = kBookmarkBarHeight + kVisualHeightOffset;
 
+// The height of buttons in a bookmark bar folder menu.
+const CGFloat kBookmarkFolderButtonHeight = 24.0;
+
+// The radius of the corner curves on the menu. Also used for sizing the shadow
+// window behind the menu window at times when the menu can be scrolled.
+const CGFloat kBookmarkBarMenuCornerRadius = 4.0;
+
 }  // namespace bookmarks
 
 #endif  // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_CONSTANTS_H_
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
index 64591ba..4989f57 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,7 +16,7 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_state.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
-#include "chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h"
+#include "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
 #import "chrome/common/chrome_application_mac.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -54,19 +54,6 @@
 const CGFloat kBookmarkMenuButtonMinimumWidth = 100.0;
 const CGFloat kBookmarkMenuButtonMaximumWidth = 485.0;
 
-// Horizontal separation between a menu button and both edges of its menu.
-const CGFloat kBookmarkSubMenuHorizontalPadding = 5.0;
-
-// TODO(mrossetti): Add constant (kBookmarkVerticalSeparation) for the gap
-// between buttons in a folder menu. Right now we're using
-// kBookmarkVerticalPadding, which is dual purpose and wrong.
-// http://crbug.com/59057
-
-// Convenience constant giving the vertical distance from the top extent of one
-// folder button to the next button.
-const CGFloat kBookmarkButtonVerticalSpan =
-    kBookmarkButtonHeight + kBookmarkVerticalPadding;
-
 // The minimum separation between a folder menu and the edge of the screen.
 // If the menu gets closer to the edge of the screen (either right or left)
 // then it is pops up in the opposite direction.
@@ -82,7 +69,23 @@
 
 // Make subfolder menus overlap their parent menu a bit to give a better
 // perception of a menuing system.
-const CGFloat kBookmarkMenuOverlap = 5.0;
+const CGFloat kBookmarkMenuOverlap = 2.0;
+
+// When constraining a scrolling bookmark bar folder window to the
+// screen, shrink the "constrain" by this much vertically.  Currently
+// this is 0.0 to avoid a problem with tracking areas leaving the
+// window, but should probably be 8.0 or something.
+const CGFloat kScrollWindowVerticalMargin = 6.0;
+
+// How far to offset a folder menu from the top of the bookmark bar. This
+// is set just above the bar so that it become distinctive when drawn.
+const CGFloat kBookmarkBarMenuOffset = 2.0;
+
+// How far to offset a folder menu's left edge horizontally in relation to
+// the left edge of the button from which it springs. Because of drawing
+// differences, simply aligning the |frame| of each does not render the
+// pproper result, so we have to offset.
+const CGFloat kBookmarkBarButtonOffset = 2.0;
 
 // Delay before opening a subfolder (and closing the previous one)
 // when hovering over a folder button.
@@ -383,7 +386,7 @@
 - (int64)nodeIdFromMenuTag:(int32)tag;
 - (int32)menuTagFromNodeId:(int64)menuid;
 - (const BookmarkNode*)nodeFromMenuItem:(id)sender;
-- (void)updateTheme:(ThemeProvider*)themeProvider;
+- (void)updateTheme:(ui::ThemeProvider*)themeProvider;
 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point;
 - (BOOL)isEventAnExitEvent:(NSEvent*)event;
 - (BOOL)shrinkOrHideView:(NSView*)view forMaxX:(CGFloat)maxViewX;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index 261c742..d2be924 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
 
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_editor.h"
@@ -35,10 +33,10 @@
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/event_utils.h"
 #import "chrome/browser/ui/cocoa/fullscreen_controller.h"
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
+#import "chrome/browser/ui/cocoa/importer/import_settings_dialog.h"
 #import "chrome/browser/ui/cocoa/menu_button.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
 #include "chrome/common/pref_names.h"
@@ -46,6 +44,8 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Bookmark bar state changing and animations
 //
@@ -720,8 +720,8 @@
 
 // Called after the current theme has changed.
 - (void)themeDidChangeNotification:(NSNotification*)aNotification {
-  ThemeProvider* themeProvider =
-      static_cast<ThemeProvider*>([[aNotification object] pointerValue]);
+  ui::ThemeProvider* themeProvider =
+      static_cast<ui::ThemeProvider*>([[aNotification object] pointerValue]);
   [self updateTheme:themeProvider];
 }
 
@@ -936,7 +936,9 @@
   // If this is an incognito window, don't allow "open in incognito".
   if ((action == @selector(openBookmarkInIncognitoWindow:)) ||
       (action == @selector(openAllBookmarksIncognitoWindow:))) {
-    if (browser_->profile()->IsOffTheRecord()) {
+    Profile* profile = browser_->profile();
+    if (profile->IsOffTheRecord() ||
+        !profile->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)) {
       return NO;
     }
   }
@@ -1105,7 +1107,7 @@
   // the hierarchy.  If that second part is now true, set the color.
   // (If not we'll set the color on the 1st themeChanged:
   // notification.)
-  ThemeProvider* themeProvider = [[[self view] window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[[self view] window] themeProvider];
   if (themeProvider) {
     NSColor* color =
         themeProvider->GetNSColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT,
@@ -1584,7 +1586,7 @@
 // because our trigger is an [NSView viewWillMoveToWindow:], which the
 // controller doesn't normally know about.  Otherwise we don't have
 // access to the theme before we know what window we will be on.
-- (void)updateTheme:(ThemeProvider*)themeProvider {
+- (void)updateTheme:(ui::ThemeProvider*)themeProvider {
   if (!themeProvider)
     return;
   NSColor* color =
@@ -1974,7 +1976,7 @@
   return tc ? tc->view()->GetContainerSize().height() : 0;
 }
 
-- (ThemeProvider*)themeProvider {
+- (ui::ThemeProvider*)themeProvider {
   return browser_->profile()->GetThemeProvider();
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
index 80f6bc7..95255c8 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/theme_provider.h"
 #include "base/basictypes.h"
 #include "base/scoped_nsobject.h"
 #include "base/string16.h"
@@ -24,12 +23,12 @@
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/cocoa/test_event_utils.h"
 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/model_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "ui/base/theme_provider.h"
 
 // Just like a BookmarkBarController but openURL: is stubbed out.
 @interface BookmarkBarControllerNoOpen : BookmarkBarController {
@@ -171,7 +170,7 @@
 @end
 
 
-class FakeTheme : public ThemeProvider {
+class FakeTheme : public ui::ThemeProvider {
  public:
   FakeTheme(NSColor* color) : color_(color) { }
   scoped_nsobject<NSColor> color_;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h
index 083efac..d974ad8 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_CONTROLLER_H_
+#pragma once
+
 #import <Cocoa/Cocoa.h>
 
 #include "base/scoped_nsobject.h"
@@ -11,6 +15,8 @@
 @class BookmarkBarFolderView;
 @class BookmarkFolderTarget;
 @class BookmarkBarFolderHoverState;
+@class BookmarkBarFolderWindow;
+@class BookmarkBarFolderWindowContentView;
 
 // A controller for the pop-up windows from bookmark folder buttons
 // which look sort of like menus.
@@ -60,20 +66,33 @@
   // The scroll view that contains our main button view (below).
   IBOutlet NSScrollView* scrollView_;
 
-  // Are we scrollable?  If no, the full contents of the folder are
-  // always visible.
-  BOOL scrollable_;
+  // The view defining the visible area in which we draw our content.
+  IBOutlet BookmarkBarFolderWindowContentView* visibleView_;
 
-  BOOL scrollUpArrowShown_;
-  BOOL scrollDownArrowShown_;
+  // The main view of this window (where the buttons go) within the scroller.
+  IBOutlet BookmarkBarFolderView* folderView_;
+
+  // A window used to show the shadow behind the main window when it is
+  // scrollable. (A 'shadow' window is needed because the main window, when
+  // scrollable in either or both directions, will reach completely to the
+  // top and/or bottom edge of the screen in order to support mouse tracking
+  // during scrolling operations. In that case, though, the 'visible'
+  // window must be inset a bit from the edge of the screen for aesthetics;
+  // it will also be inset much more from the bottom of the screen when the
+  // Dock is showing. When scrollable, the main window would show a shadow
+  // incorrectly positioned, hence the 'shadow' window.)
+  IBOutlet BookmarkBarFolderWindow* shadowWindow_;
+
+  // The up and down scroll arrow views. These arrows are hidden and shown
+  // as necessary (when scrolling is possible) and are contained in the nib
+  // as siblings to the scroll view.
+  IBOutlet NSView* scrollDownArrowView_;  // Positioned at the top.
+  IBOutlet NSView* scrollUpArrowView_;  // Positioned at the bottom.
 
   // YES if subfolders should grow to the right (the default).
   // Direction switches if we'd grow off the screen.
   BOOL subFolderGrowthToRight_;
 
-  // The main view of this window (where the buttons go).
-  IBOutlet BookmarkBarFolderView* mainView_;
-
   // Weak; we keep track to work around a
   // setShowsBorderOnlyWhileMouseInside bug.
   BookmarkButton* buttonThatMouseIsIn_;
@@ -105,6 +124,11 @@
   // don't release it when done (we invalidate it).
   NSTimer* scrollTimer_;
 
+  // Precalculated sum of left and right edge padding of buttons in a
+  // folder menu window. This is calculated from the widths of the main
+  // folder menu window and the scroll view within.
+  CGFloat padding_;
+
   // Amount to scroll by on each timer fire.  Can be + or -.
   CGFloat verticalScrollDelta_;
 
@@ -156,12 +180,11 @@
 - (IBAction)openBookmarkInNewForegroundTab:(id)sender;
 - (IBAction)openBookmarkInNewWindow:(id)sender;
 
-@property (assign, nonatomic) BOOL subFolderGrowthToRight;
+@property(assign, nonatomic) BOOL subFolderGrowthToRight;
 
 @end
 
 @interface BookmarkBarFolderController(TestingAPI)
-- (NSView*)mainView;
 - (NSPoint)windowTopLeftForWidth:(int)windowWidth;
 - (NSArray*)buttons;
 - (BookmarkBarFolderController*)folderController;
@@ -172,11 +195,15 @@
 // Set to YES in order to prevent animations.
 - (void)setIgnoreAnimations:(BOOL)ignore;
 
-// Return YES if we can scroll up or down.
+// Return YES if the scroll-up or scroll-down arrows are showing.
 - (BOOL)canScrollUp;
 - (BOOL)canScrollDown;
-// Return YES if the scrollable_ flag has been set.
-- (BOOL)scrollable;
+- (CGFloat)verticalScrollArrowHeight;
+- (NSView*)visibleView;
+- (NSScrollView*)scrollView;
+- (NSView*)folderView;
 
 - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point;
 @end
+
+#endif  // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_FOLDER_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm
index 86420c2..53bb97d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h"
 
-#include "app/mac/nsimage_cache.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -15,10 +14,13 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_button_cell.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view.h"
+#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/event_utils.h"
 
+using bookmarks::kBookmarkBarMenuCornerRadius;
+
 namespace {
 
 // Frequency of the scrolling timer in seconds.
@@ -27,18 +29,77 @@
 // Amount to scroll by per timer fire.  We scroll rather slowly; to
 // accomodate we do several at a time.
 const CGFloat kBookmarkBarFolderScrollAmount =
-    3 * bookmarks::kBookmarkButtonVerticalSpan;
+    3 * bookmarks::kBookmarkFolderButtonHeight;
 
-// Amount to scroll for each scroll wheel delta.
+// Amount to scroll for each scroll wheel roll.
 const CGFloat kBookmarkBarFolderScrollWheelAmount =
-    1 * bookmarks::kBookmarkButtonVerticalSpan;
+    1 * bookmarks::kBookmarkFolderButtonHeight;
 
-// When constraining a scrolling bookmark bar folder window to the
-// screen, shrink the "constrain" by this much vertically.  Currently
-// this is 0.0 to avoid a problem with tracking areas leaving the
-// window, but should probably be 8.0 or something.
-// TODO(jrg): http://crbug.com/36225
-const CGFloat kScrollWindowVerticalMargin = 0.0;
+// Determining adjustments to the layout of the folder menu window in response
+// to resizing and scrolling relies on many visual factors. The following
+// struct is used to pass around these factors to the several support
+// functions involved in the adjustment calculations and application.
+struct LayoutMetrics {
+  // Metrics applied during the final layout adjustments to the window,
+  // the main visible content view, and the menu content view (i.e. the
+  // scroll view).
+  CGFloat windowLeft;
+  NSSize windowSize;
+  // The proposed and then final scrolling adjustment made to the scrollable
+  // area of the folder menu. This may be modified during the window layout
+  // primarily as a result of hiding or showing the scroll arrows.
+  CGFloat scrollDelta;
+  NSRect windowFrame;
+  NSRect visibleFrame;
+  NSRect scrollerFrame;
+  NSPoint scrollPoint;
+  // The difference between 'could' and 'can' in these next four data members
+  // is this: 'could' represents the previous condition for scrollability
+  // while 'can' represents what the new condition will be for scrollability.
+  BOOL couldScrollUp;
+  BOOL canScrollUp;
+  BOOL couldScrollDown;
+  BOOL canScrollDown;
+  // Determines the optimal time during folder menu layout when the contents
+  // of the button scroll area should be scrolled in order to prevent
+  // flickering.
+  BOOL preScroll;
+
+  // Intermediate metrics used in determining window vertical layout changes.
+  CGFloat deltaWindowHeight;
+  CGFloat deltaWindowY;
+  CGFloat deltaVisibleHeight;
+  CGFloat deltaVisibleY;
+  CGFloat deltaScrollerHeight;
+  CGFloat deltaScrollerY;
+
+  // Convenience metrics used in multiple functions (carried along here in
+  // order to eliminate the need to calculate in multiple places and
+  // reduce the possibility of bugs).
+  CGFloat minimumY;
+  CGFloat oldWindowY;
+  CGFloat folderY;
+  CGFloat folderTop;
+
+  LayoutMetrics(CGFloat windowLeft, NSSize windowSize, CGFloat scrollDelta) :
+    windowLeft(windowLeft),
+    windowSize(windowSize),
+    scrollDelta(scrollDelta),
+    couldScrollUp(NO),
+    canScrollUp(NO),
+    couldScrollDown(NO),
+    canScrollDown(NO),
+    preScroll(NO),
+    deltaWindowHeight(0.0),
+    deltaWindowY(0.0),
+    deltaVisibleHeight(0.0),
+    deltaVisibleY(0.0),
+    deltaScrollerHeight(0.0),
+    deltaScrollerY(0.0),
+    oldWindowY(0.0),
+    folderY(0.0),
+    folderTop(0.0) {}
+};
 
 }  // namespace
 
@@ -49,22 +110,82 @@
 - (void)endScroll;
 - (void)addScrollTimerWithDelta:(CGFloat)delta;
 
+// Helper function to configureWindow which performs a basic layout of
+// the window subviews, in particular the menu buttons and the window width.
+- (void)layOutWindowWithHeight:(CGFloat)height;
+
 // Determine the best button width (which will be the widest button or the
 // maximum allowable button width, whichever is less) and resize all buttons.
-// Return the new width (so that the window can be adjusted, if necessary).
+// Return the new width so that the window can be adjusted.
 - (CGFloat)adjustButtonWidths;
 
 // Returns the total menu height needed to display |buttonCount| buttons.
 // Does not do any fancy tricks like trimming the height to fit on the screen.
-- (int)windowHeightForButtonCount:(int)buttonCount;
+- (int)menuHeightForButtonCount:(int)buttonCount;
 
-// Adjust the height and horizontal position of the window such that the
-// scroll arrows are shown as needed and the window appears completely
-// on screen.
-- (void)adjustWindowForHeight:(int)windowHeight;
+// Adjust layout of the folder menu window components, showing/hiding the
+// scroll up/down arrows, and resizing as necessary for a proper disaplay.
+// In order to reduce window flicker, all layout changes are deferred until
+// the final step of the adjustment. To accommodate this deferral, window
+// height and width changes needed by callers to this function pass their
+// desired window changes in |size|. When scrolling is to be performed
+// any scrolling change is given by |scrollDelta|. The ultimate amount of
+// scrolling may be different from |scrollDelta| in order to accommodate
+// changes in the scroller view layout. These proposed window adjustments
+// are passed to helper functions using a LayoutMetrics structure.
+//
+// This function should be called when: 1) initially setting up a folder menu
+// window, 2) responding to scrolling of the contents (which may affect the
+// height of the window), 3) addition or removal of bookmark items (such as
+// during cut/paste/delete/drag/drop operations).
+- (void)adjustWindowLeft:(CGFloat)windowLeft
+                    size:(NSSize)windowSize
+             scrollingBy:(CGFloat)scrollDelta;
 
-// Show or hide the scroll arrows at the top/bottom of the window.
-- (void)showOrHideScrollArrows;
+// Support function for adjustWindowLeft:size:scrollingBy: which initializes
+// the layout adjustments by gathering current folder menu window and subviews
+// positions and sizes. This information is set in the |layoutMetrics|
+// structure.
+- (void)gatherMetrics:(LayoutMetrics*)layoutMetrics;
+
+// Support function for adjustWindowLeft:size:scrollingBy: which calculates
+// the changes which must be applied to the folder menu window and subviews
+// positions and sizes. |layoutMetrics| contains the proposed window size
+// and scrolling along with the other current window and subview layout
+// information. The values in |layoutMetrics| are then adjusted to
+// accommodate scroll arrow presentation and window growth.
+- (void)adjustMetrics:(LayoutMetrics*)layoutMetrics;
+
+// Support function for adjustMetrics: which calculates the layout changes
+// required to accommodate changes in the position and scrollability
+// of the top of the folder menu window.
+- (void)adjustMetricsForMenuTopChanges:(LayoutMetrics*)layoutMetrics;
+
+// Support function for adjustMetrics: which calculates the layout changes
+// required to accommodate changes in the position and scrollability
+// of the bottom of the folder menu window.
+- (void)adjustMetricsForMenuBottomChanges:(LayoutMetrics*)layoutMetrics;
+
+// Support function for adjustWindowLeft:size:scrollingBy: which applies
+// the layout adjustments to the folder menu window and subviews.
+- (void)applyMetrics:(LayoutMetrics*)layoutMetrics;
+
+// This function is called when buttons are added or removed from the folder
+// menu, and which may require a change in the layout of the folder menu
+// window. Such layout changes may include horizontal placement, width,
+// height, and scroller visibility changes. (This function calls through
+// to -[adjustWindowLeft:size:scrollingBy:].)
+// |buttonCount| should contain the updated count of menu buttons.
+- (void)adjustWindowForButtonCount:(NSUInteger)buttonCount;
+
+// A helper function which takes the desired amount to scroll, given by
+// |scrollDelta|, and calculates the actual scrolling change to be applied
+// taking into account the layout of the folder menu window and any
+// changes in it's scrollability. (For example, when scrolling down and the
+// top-most menu item is coming into view we will only scroll enough for
+// that item to be completely presented, which may be less than the
+// scroll amount requested.)
+- (CGFloat)determineFinalScrollDelta:(CGFloat)scrollDelta;
 
 // |point| is in the base coordinate system of the destination window;
 // it comes from an id<NSDraggingInfo>. |copy| is YES if a copy is to be
@@ -131,9 +252,6 @@
     barController_ = barController;  // WEAK
     buttons_.reset([[NSMutableArray alloc] init]);
     folderTarget_.reset([[BookmarkFolderTarget alloc] initWithController:self]);
-    NSImage* image = app::mac::GetCachedImageWithName(@"menu_overflow_up.pdf");
-    DCHECK(image);
-    verticalScrollArrowHeight_ = [image size].height;
     [self configureWindow];
     hoverState_.reset([[BookmarkBarFolderHoverState alloc] init]);
   }
@@ -163,6 +281,13 @@
   [super dealloc];
 }
 
+- (void)awakeFromNib {
+  NSRect windowFrame = [[self window] frame];
+  NSRect scrollViewFrame = [scrollView_ frame];
+  padding_ = NSWidth(windowFrame) - NSWidth(scrollViewFrame);
+  verticalScrollArrowHeight_ = NSHeight([scrollUpArrowView_ frame]);
+}
+
 // Overriden from NSWindowController to call childFolderWillShow: before showing
 // the window.
 - (void)showWindow:(id)sender {
@@ -276,11 +401,6 @@
   return button;
 }
 
-// Exposed for testing.
-- (NSView*)mainView {
-  return mainView_;
-}
-
 - (id)folderTarget {
   return folderTarget_.get();
 }
@@ -353,8 +473,9 @@
         [[parentButton_ window]
             convertBaseToScreen:[[parentButton_ superview]
                                     convertPoint:NSZeroPoint toView:nil]];
-    newWindowTopLeft = NSMakePoint(buttonBottomLeftInScreen.x,
-                                   bookmarkBarBottomLeftInScreen.y);
+    newWindowTopLeft = NSMakePoint(
+        buttonBottomLeftInScreen.x + bookmarks::kBookmarkBarButtonOffset,
+        bookmarkBarBottomLeftInScreen.y + bookmarks::kBookmarkBarMenuOffset);
     // Make sure the window is on-screen; if not, push left.  It is
     // intentional that top level folders "push left" slightly
     // different than subfolders.
@@ -365,14 +486,14 @@
                                     NSMinX(screenFrame));
     }
   } else {
-    // Parent is a folder; grow right/left.
+    // Parent is a folder: expose as much as we can vertically; grow right/left.
     newWindowTopLeft.x = [self childFolderWindowLeftForWidth:windowWidth];
-    NSPoint top = NSMakePoint(0, (NSMaxY([parentButton_ frame]) +
-                                  bookmarks::kBookmarkVerticalPadding));
-    NSPoint topOfWindow =
-        [[parentButton_ window]
-            convertBaseToScreen:[[parentButton_ superview]
-                                    convertPoint:top toView:nil]];
+    NSPoint topOfWindow = NSMakePoint(0,
+                                      NSMaxY([parentButton_ frame]) -
+                                          bookmarks::kBookmarkVerticalPadding);
+    topOfWindow = [[parentButton_ window]
+                   convertBaseToScreen:[[parentButton_ superview]
+                                        convertPoint:topOfWindow toView:nil]];
     newWindowTopLeft.y = topOfWindow.y;
   }
   return newWindowTopLeft;
@@ -384,72 +505,207 @@
   [[self window] setLevel:NSPopUpMenuWindowLevel];
 }
 
-- (int)windowHeightForButtonCount:(int)buttonCount {
-  return (buttonCount * bookmarks::kBookmarkButtonVerticalSpan) +
-      bookmarks::kBookmarkVerticalPadding;
+- (int)menuHeightForButtonCount:(int)buttonCount {
+  // This does not take into account any padding which may be required at the
+  // top and/or bottom of the window.
+  return (buttonCount * bookmarks::kBookmarkFolderButtonHeight) +
+      2 * bookmarks::kBookmarkVerticalPadding;
 }
 
-- (void)adjustWindowForHeight:(int)windowHeight {
-  // Adjust all button widths to be consistent, determine the best size for
-  // the window, and set the window frame.
-  CGFloat windowWidth =
-      [self adjustButtonWidths] +
-      (2 * bookmarks::kBookmarkSubMenuHorizontalPadding);
-  NSPoint newWindowTopLeft = [self windowTopLeftForWidth:windowWidth];
-  NSSize windowSize = NSMakeSize(windowWidth, windowHeight);
-  windowSize = [scrollView_ convertSize:windowSize toView:nil];
+- (void)adjustWindowLeft:(CGFloat)windowLeft
+                    size:(NSSize)windowSize
+             scrollingBy:(CGFloat)scrollDelta {
+  // Callers of this function should make adjustments to the vertical
+  // attributes of the folder view only (height, scroll position).
+  // This function will then make appropriate layout adjustments in order
+  // to accommodate screen/dock margins, scroll-up and scroll-down arrow
+  // presentation, etc.
+  // The 4 views whose vertical height and origins may be adjusted
+  // by this function are:
+  //  1) window, 2) visible content view, 3) scroller view, 4) folder view.
+
+  LayoutMetrics layoutMetrics(windowLeft, windowSize, scrollDelta);
+  [self gatherMetrics:&layoutMetrics];
+  [self adjustMetrics:&layoutMetrics];
+  [self applyMetrics:&layoutMetrics];
+}
+
+- (void)gatherMetrics:(LayoutMetrics*)layoutMetrics {
+  LayoutMetrics& metrics(*layoutMetrics);
   NSWindow* window = [self window];
-  // If the window is already visible then make sure its top remains stable.
-  BOOL windowAlreadyShowing = [window isVisible];
-  CGFloat deltaY = windowHeight - NSHeight([mainView_ frame]);
-  if (windowAlreadyShowing) {
-    NSRect oldFrame = [window frame];
-    newWindowTopLeft.y = oldFrame.origin.y + NSHeight(oldFrame);
-  }
-  NSRect windowFrame = NSMakeRect(newWindowTopLeft.x,
-      newWindowTopLeft.y - windowHeight, windowSize.width, windowHeight);
-  // Make the scrolled content be the right size (full size).
-  NSRect mainViewFrame = NSMakeRect(0, 0, NSWidth(windowFrame) -
-      bookmarks::kScrollViewContentWidthMargin, NSHeight(windowFrame));
-  [mainView_ setFrame:mainViewFrame];
-  // Make sure the window fits on the screen.  If not, constrain.
-  // We'll scroll to allow the user to see all the content.
-  NSRect screenFrame = [[[self window] screen] frame];
-  screenFrame = NSInsetRect(screenFrame, 0, kScrollWindowVerticalMargin);
-  BOOL wasScrollable = scrollable_;
-  if (!NSContainsRect(screenFrame, windowFrame)) {
-    scrollable_ = YES;
-    windowFrame = NSIntersectionRect(screenFrame, windowFrame);
+  metrics.windowFrame = [window frame];
+  metrics.visibleFrame = [visibleView_ frame];
+  metrics.scrollerFrame = [scrollView_ frame];
+  metrics.scrollPoint = [scrollView_ documentVisibleRect].origin;
+  metrics.scrollPoint.y -= metrics.scrollDelta;
+  metrics.couldScrollUp = ![scrollUpArrowView_ isHidden];
+  metrics.couldScrollDown = ![scrollDownArrowView_ isHidden];
+
+  metrics.deltaWindowHeight = 0.0;
+  metrics.deltaWindowY = 0.0;
+  metrics.deltaVisibleHeight = 0.0;
+  metrics.deltaVisibleY = 0.0;
+  metrics.deltaScrollerHeight = 0.0;
+  metrics.deltaScrollerY = 0.0;
+
+  metrics.minimumY = NSMinY([[window screen] visibleFrame]) +
+                     bookmarks::kScrollWindowVerticalMargin;
+  metrics.oldWindowY = NSMinY(metrics.windowFrame);
+  metrics.folderY =
+      metrics.scrollerFrame.origin.y + metrics.visibleFrame.origin.y +
+      metrics.oldWindowY - metrics.scrollPoint.y;
+  metrics.folderTop = metrics.folderY + NSHeight([folderView_ frame]);
+}
+
+- (void)adjustMetrics:(LayoutMetrics*)layoutMetrics {
+  LayoutMetrics& metrics(*layoutMetrics);
+  NSScreen* screen = [[self window] screen];
+  CGFloat effectiveFolderY = metrics.folderY;
+  if (!metrics.couldScrollUp && !metrics.couldScrollDown)
+    effectiveFolderY -= metrics.windowSize.height;
+  metrics.canScrollUp = effectiveFolderY < metrics.minimumY;
+  CGFloat maximumY =
+      NSMaxY([screen frame]) - bookmarks::kScrollWindowVerticalMargin;
+  metrics.canScrollDown = metrics.folderTop > maximumY;
+
+  // Accommodate changes in the bottom of the menu.
+  [self adjustMetricsForMenuBottomChanges:layoutMetrics];
+
+  // Accommodate changes in the top of the menu.
+  [self adjustMetricsForMenuTopChanges:layoutMetrics];
+
+  metrics.scrollerFrame.origin.y += metrics.deltaScrollerY;
+  metrics.scrollerFrame.size.height += metrics.deltaScrollerHeight;
+  metrics.visibleFrame.origin.y += metrics.deltaVisibleY;
+  metrics.visibleFrame.size.height += metrics.deltaVisibleHeight;
+  metrics.preScroll = metrics.canScrollUp && !metrics.couldScrollUp &&
+      metrics.scrollDelta == 0.0 && metrics.deltaWindowHeight >= 0.0;
+  metrics.windowFrame.origin.y += metrics.deltaWindowY;
+  metrics.windowFrame.origin.x = metrics.windowLeft;
+  metrics.windowFrame.size.height += metrics.deltaWindowHeight;
+  metrics.windowFrame.size.width = metrics.windowSize.width;
+}
+
+- (void)adjustMetricsForMenuBottomChanges:(LayoutMetrics*)layoutMetrics {
+  LayoutMetrics& metrics(*layoutMetrics);
+  if (metrics.canScrollUp) {
+    if (!metrics.couldScrollUp) {
+      // Couldn't -> Can
+      metrics.deltaWindowY = -metrics.oldWindowY;
+      metrics.deltaWindowHeight = -metrics.deltaWindowY;
+      metrics.deltaVisibleY = metrics.minimumY;
+      metrics.deltaVisibleHeight = -metrics.deltaVisibleY;
+      metrics.deltaScrollerY = verticalScrollArrowHeight_;
+      metrics.deltaScrollerHeight = -metrics.deltaScrollerY;
+      // Adjust the scroll delta if we've grown the window and it is
+      // now scroll-up-able, but don't adjust it if we've
+      // scrolled down and it wasn't scroll-up-able but now is.
+      if (metrics.canScrollDown == metrics.couldScrollDown) {
+        CGFloat deltaScroll = metrics.deltaWindowY + metrics.deltaScrollerY +
+                              metrics.deltaVisibleY;
+        metrics.scrollPoint.y += deltaScroll + metrics.windowSize.height;
+      }
+    } else if (!metrics.canScrollDown && metrics.windowSize.height > 0.0) {
+      metrics.scrollPoint.y += metrics.windowSize.height;
+    }
   } else {
-    scrollable_ = NO;
+    if (metrics.couldScrollUp) {
+      // Could -> Can't
+      metrics.deltaWindowY = metrics.folderY - metrics.oldWindowY;
+      metrics.deltaWindowHeight = -metrics.deltaWindowY;
+      metrics.deltaVisibleY = -metrics.visibleFrame.origin.y;
+      metrics.deltaVisibleHeight = -metrics.deltaVisibleY;
+      metrics.deltaScrollerY = -verticalScrollArrowHeight_;
+      metrics.deltaScrollerHeight = -metrics.deltaScrollerY;
+      // We are no longer scroll-up-able so the scroll point drops to zero.
+      metrics.scrollPoint.y = 0.0;
+    } else {
+      // Couldn't -> Can't
+      // Check for menu height change by looking at the relative tops of the
+      // menu folder and the window folder, which previously would have been
+      // the same.
+      metrics.deltaWindowY = NSMaxY(metrics.windowFrame) - metrics.folderTop;
+      metrics.deltaWindowHeight = -metrics.deltaWindowY;
+    }
   }
-  [window setFrame:windowFrame display:NO];
-  if (wasScrollable != scrollable_) {
-    // If scrollability changed then rework visibility of the scroll arrows
-    // and the scroll offset of the menu view.
-    NSSize windowLocalSize =
-        [scrollView_ convertSize:windowFrame.size fromView:nil];
-    CGFloat scrollPointY = NSHeight(mainViewFrame) - windowLocalSize.height +
-        bookmarks::kBookmarkVerticalPadding;
-    [mainView_ scrollPoint:NSMakePoint(0, scrollPointY)];
-    [self showOrHideScrollArrows];
-    [self addOrUpdateScrollTracking];
-  } else if (scrollable_ && windowAlreadyShowing) {
-    // If the window was already showing and is still scrollable then make
-    // sure the main view moves upward, not downward so that the content
-    // at the bottom of the menu, not the top, appears to move.
-    // The edge case is when the menu is scrolled all the way to top (hence
-    // the test of scrollDownArrowShown_) - don't scroll then.
-    NSView* superView = [mainView_ superview];
-    DCHECK([superView isKindOfClass:[NSClipView class]]);
-    NSClipView* clipView = static_cast<NSClipView*>(superView);
-    CGFloat scrollPointY = [clipView bounds].origin.y +
-        bookmarks::kBookmarkVerticalPadding;
-    if (scrollDownArrowShown_ || deltaY > 0.0)
-      scrollPointY += deltaY;
-    [mainView_ scrollPoint:NSMakePoint(0, scrollPointY)];
+}
+
+- (void)adjustMetricsForMenuTopChanges:(LayoutMetrics*)layoutMetrics {
+  LayoutMetrics& metrics(*layoutMetrics);
+  if (metrics.canScrollDown == metrics.couldScrollDown) {
+    if (!metrics.canScrollDown) {
+      // Not scroll-down-able but the menu top has changed.
+      metrics.deltaWindowHeight += metrics.scrollDelta;
+    }
+  } else {
+    if (metrics.canScrollDown) {
+      // Couldn't -> Can
+      metrics.deltaWindowHeight += (NSMaxY([[[self window] screen] frame]) -
+                                    NSMaxY(metrics.windowFrame));
+      metrics.deltaVisibleHeight -= bookmarks::kScrollWindowVerticalMargin;
+      metrics.deltaScrollerHeight -= verticalScrollArrowHeight_;
+    } else {
+      // Could -> Can't
+      metrics.deltaWindowHeight -= bookmarks::kScrollWindowVerticalMargin;
+      metrics.deltaVisibleHeight += bookmarks::kScrollWindowVerticalMargin;
+      metrics.deltaScrollerHeight += verticalScrollArrowHeight_;
+    }
   }
-  [window display];
+}
+
+- (void)applyMetrics:(LayoutMetrics*)layoutMetrics {
+  LayoutMetrics& metrics(*layoutMetrics);
+  // Hide or show the scroll arrows.
+  if (metrics.canScrollUp != metrics.couldScrollUp)
+    [scrollUpArrowView_ setHidden:metrics.couldScrollUp];
+  if (metrics.canScrollDown != metrics.couldScrollDown)
+    [scrollDownArrowView_ setHidden:metrics.couldScrollDown];
+
+  // Adjust the geometry. The order is important because of sizer dependencies.
+  [scrollView_ setFrame:metrics.scrollerFrame];
+  [visibleView_ setFrame:metrics.visibleFrame];
+  // This little bit of trickery handles the one special case where
+  // the window is now scroll-up-able _and_ going to be resized -- scroll
+  // first in order to prevent flashing.
+  if (metrics.preScroll)
+    [[scrollView_ documentView] scrollPoint:metrics.scrollPoint];
+
+  [[self window] setFrame:metrics.windowFrame display:YES];
+
+  // In all other cases we defer scrolling until the window has been resized
+  // in order to prevent flashing.
+  if (!metrics.preScroll)
+    [[scrollView_ documentView] scrollPoint:metrics.scrollPoint];
+
+  if (metrics.canScrollUp != metrics.couldScrollUp ||
+      metrics.canScrollDown != metrics.couldScrollDown ||
+      metrics.scrollDelta != 0.0) {
+    if (metrics.canScrollUp || metrics.canScrollDown)
+      [self addOrUpdateScrollTracking];
+    else
+      [self removeScrollTracking];
+  }
+}
+
+- (void)adjustWindowForButtonCount:(NSUInteger)buttonCount {
+  NSRect folderFrame = [folderView_ frame];
+  CGFloat newMenuHeight =
+      (CGFloat)[self menuHeightForButtonCount:[buttons_ count]];
+  CGFloat deltaMenuHeight = newMenuHeight - NSHeight(folderFrame);
+  // If the height has changed then also change the origin, and adjust the
+  // scroll (if scrolling).
+  if ([self canScrollUp]) {
+    NSPoint scrollPoint = [scrollView_ documentVisibleRect].origin;
+    scrollPoint.y += deltaMenuHeight;
+    [[scrollView_ documentView] scrollPoint:scrollPoint];
+  }
+  folderFrame.size.height += deltaMenuHeight;
+  [folderView_ setFrameSize:folderFrame.size];
+  CGFloat windowWidth = [self adjustButtonWidths] + padding_;
+  NSPoint newWindowTopLeft = [self windowTopLeftForWidth:windowWidth];
+  CGFloat left = newWindowTopLeft.x;
+  NSSize newSize = NSMakeSize(windowWidth, deltaMenuHeight);
+  [self adjustWindowLeft:left size:newSize scrollingBy:0.0];
 }
 
 // Determine window size and position.
@@ -464,17 +720,18 @@
   int buttons = std::max(node->GetChildCount() - startingIndex, 1);
 
   // Prelim height of the window.  We'll trim later as needed.
-  int height = [self windowHeightForButtonCount:buttons];
+  int height = [self menuHeightForButtonCount:buttons];
   // We'll need this soon...
   [self window];
 
   // TODO(jrg): combine with frame code in bookmark_bar_controller.mm
   // http://crbug.com/35966
   NSRect buttonsOuterFrame = NSMakeRect(
-    bookmarks::kBookmarkSubMenuHorizontalPadding,
-    (height - bookmarks::kBookmarkButtonVerticalSpan),
-    bookmarks::kDefaultBookmarkWidth,
-    bookmarks::kBookmarkButtonHeight);
+      0,
+      height - bookmarks::kBookmarkFolderButtonHeight -
+          bookmarks::kBookmarkVerticalPadding,
+      bookmarks::kDefaultBookmarkWidth,
+      bookmarks::kBookmarkFolderButtonHeight);
 
   // TODO(jrg): combine with addNodesToButtonList: code from
   // bookmark_bar_controller.mm (but use y offset)
@@ -484,7 +741,7 @@
     BookmarkButton* button = [self makeButtonForNode:nil
                                                frame:buttonsOuterFrame];
     [buttons_ addObject:button];
-    [mainView_ addSubview:button];
+    [folderView_ addSubview:button];
   } else {
     for (int i = startingIndex;
          i < node->GetChildCount();
@@ -493,13 +750,37 @@
       BookmarkButton* button = [self makeButtonForNode:child
                                                  frame:buttonsOuterFrame];
       [buttons_ addObject:button];
-      [mainView_ addSubview:button];
-      buttonsOuterFrame.origin.y -= bookmarks::kBookmarkButtonVerticalSpan;
+      [folderView_ addSubview:button];
+      buttonsOuterFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight;
     }
   }
+  [self layOutWindowWithHeight:height];
+}
 
-  [self adjustWindowForHeight:height];
-  // Finally pop me up.
+- (void)layOutWindowWithHeight:(CGFloat)height {
+  // Lay out the window by adjusting all button widths to be consistent, then
+  // base the window width on this ideal button width.
+  CGFloat buttonWidth = [self adjustButtonWidths];
+  CGFloat windowWidth = buttonWidth + padding_;
+  NSPoint newWindowTopLeft = [self windowTopLeftForWidth:windowWidth];
+  // Make sure as much of a submenu is exposed (which otherwise would be a
+  // problem if the parent button is close to the bottom of the screen).
+  if ([parentController_ isKindOfClass:[self class]]) {
+    CGFloat minimumY = NSMinY([[[self window] screen] visibleFrame]) +
+                       bookmarks::kScrollWindowVerticalMargin +
+                       height;
+    newWindowTopLeft.y = MAX(newWindowTopLeft.y, minimumY);
+  }
+  NSWindow* window = [self window];
+  NSRect windowFrame = NSMakeRect(newWindowTopLeft.x,
+                                  newWindowTopLeft.y - height,
+                                  windowWidth, height);
+  [window setFrame:windowFrame display:NO];
+  NSRect folderFrame = NSMakeRect(0, 0, windowWidth, height);
+  [folderView_ setFrame:folderFrame];
+  NSSize newSize = NSMakeSize(windowWidth, 0.0);
+  [self adjustWindowLeft:newWindowTopLeft.x size:newSize scrollingBy:0.0];
+  [window display];
   [self configureWindowLevel];
 }
 
@@ -525,85 +806,6 @@
   return width;
 }
 
-- (BOOL)canScrollUp {
-  // If removal of an arrow would make things "finished", state as
-  // such.
-  CGFloat scrollY = [scrollView_ documentVisibleRect].origin.y;
-  if (scrollUpArrowShown_)
-    scrollY -= verticalScrollArrowHeight_;
-
-  if (scrollY <= 0)
-    return NO;
-  return YES;
-}
-
-- (BOOL)canScrollDown {
-  CGFloat arrowAdjustment = 0.0;
-
-  // We do NOT adjust based on the scrollDOWN arrow.  This keeps
-  // things from "jumping"; if removal of the down arrow (at the top
-  // of the window) would cause a scroll to end, we'll end.
-  if (scrollUpArrowShown_)
-    arrowAdjustment += verticalScrollArrowHeight_;
-
-  NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin;
-  NSRect documentRect = [[scrollView_ documentView] frame];
-
-  // If we are exactly the right height, return no.  We need this
-  // extra conditional in the case where we've just scrolled/grown
-  // into position.
-  if (NSHeight([[self window] frame]) == NSHeight(documentRect))
-    return NO;
-
-  if ((scrollPosition.y + NSHeight([[self window] frame])) >=
-      (NSHeight(documentRect) + arrowAdjustment)) {
-    return NO;
-  }
-  return YES;
-}
-
-- (void)showOrHideScrollArrows {
-  NSRect frame = [scrollView_ frame];
-  CGFloat scrollDelta = 0.0;
-  BOOL canScrollDown = [self canScrollDown];
-  BOOL canScrollUp = [self canScrollUp];
-
-  if (canScrollUp != scrollUpArrowShown_) {
-    if (scrollUpArrowShown_) {
-      frame.origin.y -= verticalScrollArrowHeight_;
-      frame.size.height += verticalScrollArrowHeight_;
-      scrollDelta = verticalScrollArrowHeight_;
-    } else {
-      frame.origin.y += verticalScrollArrowHeight_;
-      frame.size.height -= verticalScrollArrowHeight_;
-      scrollDelta = -verticalScrollArrowHeight_;
-    }
-  }
-  if (canScrollDown != scrollDownArrowShown_) {
-    if (scrollDownArrowShown_) {
-      frame.size.height += verticalScrollArrowHeight_;
-    } else {
-      frame.size.height -= verticalScrollArrowHeight_;
-    }
-  }
-  scrollUpArrowShown_ = canScrollUp;
-  scrollDownArrowShown_ = canScrollDown;
-  [scrollView_ setFrame:frame];
-
-  // Adjust scroll based on new frame.  For example, if we make room
-  // for an arrow at the bottom, adjust the scroll so the topmost item
-  // is still fully visible.
-  if (scrollDelta) {
-    NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin;
-    scrollPosition.y -= scrollDelta;
-    [[scrollView_ documentView] scrollPoint:scrollPosition];
-  }
-}
-
-- (BOOL)scrollable {
-  return scrollable_;
-}
-
 // Start a "scroll up" timer.
 - (void)beginScrollWindowUp {
   [self addScrollTimerWithDelta:kBookmarkBarFolderScrollAmount];
@@ -624,67 +826,55 @@
 }
 
 // Perform a single scroll of the specified amount.
-// Scroll up:
-// Scroll the documentView by the growth amount.
-// If we cannot grow the window, simply scroll the documentView.
-// If we can grow the window up without falling off the screen, do it.
-// Scroll down:
-// Never change the window size; only scroll the documentView.
 - (void)performOneScroll:(CGFloat)delta {
-  NSRect windowFrame = [[self window] frame];
-  NSRect screenFrame = [[[self window] screen] frame];
-
-  // First scroll the "document" area.
-  NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin;
-  scrollPosition.y -= delta;
-  [[scrollView_ documentView] scrollPoint:scrollPosition];
-
-  if (buttonThatMouseIsIn_)
-    [buttonThatMouseIsIn_ toggleButtonBorderingWhileMouseInside];
-
-  // We update the window size after shifting the scroll to avoid a race.
-  CGFloat screenHeightMinusMargin = (NSHeight(screenFrame) -
-                                     (2 * kScrollWindowVerticalMargin));
-  if (delta) {
-    // If we can, grow the window (up).
-    if (NSHeight(windowFrame) < screenHeightMinusMargin) {
-      CGFloat growAmount = delta;
-      // Don't scroll more than enough to "finish".
-      if (scrollPosition.y < 0)
-        growAmount += scrollPosition.y;
-      windowFrame.size.height += growAmount;
-      windowFrame.size.height = std::min(NSHeight(windowFrame),
-                                         screenHeightMinusMargin);
-      // Watch out for a finish that isn't the full height of the screen.
-      // We get here if using the scroll wheel to scroll by small amounts.
-      windowFrame.size.height = std::min(NSHeight(windowFrame),
-                                         NSHeight([mainView_ frame]));
-      // Don't allow scrolling to make the window smaller, ever.  This
-      // conditional is important when processing scrollWheel events.
-      if (windowFrame.size.height > [[self window] frame].size.height) {
-        [[self window] setFrame:windowFrame display:YES];
-        [self addOrUpdateScrollTracking];
-      }
-    }
+  CGFloat finalDelta = [self determineFinalScrollDelta:delta];
+  if (finalDelta > 0.0 || finalDelta < 0.0) {
+    if (buttonThatMouseIsIn_)
+      [buttonThatMouseIsIn_ toggleButtonBorderingWhileMouseInside];
+    NSRect windowFrame = [[self window] frame];
+    NSSize newSize = NSMakeSize(NSWidth(windowFrame), 0.0);
+    [self adjustWindowLeft:windowFrame.origin.x
+                      size:newSize
+               scrollingBy:finalDelta];
   }
+}
 
-  // If we're at either end, happiness.
-  if ((scrollPosition.y <= 0) ||
-      ((scrollPosition.y + NSHeight(windowFrame) >=
-        NSHeight([mainView_ frame])) &&
-       (windowFrame.size.height == screenHeightMinusMargin))) {
-    [self endScroll];
+- (CGFloat)determineFinalScrollDelta:(CGFloat)delta {
+  if ((delta > 0.0 && ![scrollUpArrowView_ isHidden]) ||
+      (delta < 0.0 && ![scrollDownArrowView_ isHidden])) {
+    NSWindow* window = [self window];
+    NSRect windowFrame = [window frame];
+    NSScreen* screen = [window screen];
+    NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin;
+    CGFloat scrollY = scrollPosition.y;
+    NSRect scrollerFrame = [scrollView_ frame];
+    CGFloat scrollerY = NSMinY(scrollerFrame);
+    NSRect visibleFrame = [visibleView_ frame];
+    CGFloat visibleY = NSMinY(visibleFrame);
+    CGFloat windowY = NSMinY(windowFrame);
+    CGFloat offset = scrollerY + visibleY + windowY;
 
-    // If we can't scroll either up or down we are completely done.
-    // For example, perhaps we've scrolled a little and grown the
-    // window on-screen until there is now room for everything.
-    if (![self canScrollUp] && ![self canScrollDown]) {
-      scrollable_ = NO;
-      [self removeScrollTracking];
+    if (delta > 0.0) {
+      // Scrolling up.
+      CGFloat minimumY = NSMinY([screen visibleFrame]) +
+                         bookmarks::kScrollWindowVerticalMargin;
+      CGFloat maxUpDelta = scrollY - offset + minimumY;
+      delta = MIN(delta, maxUpDelta);
+    } else {
+      // Scrolling down.
+      NSRect screenFrame =  [screen frame];
+      CGFloat topOfScreen = NSMaxY(screenFrame);
+      NSRect folderFrame = [folderView_ frame];
+      CGFloat folderHeight = NSHeight(folderFrame);
+      CGFloat folderTop = folderHeight - scrollY + offset;
+      CGFloat maxDownDelta =
+          topOfScreen - folderTop - bookmarks::kScrollWindowVerticalMargin;
+      delta = MAX(delta, maxDownDelta);
     }
+  } else {
+    delta = 0.0;
   }
-
-  [self showOrHideScrollArrows];
+  return delta;
 }
 
 // Perform a scroll of the window on the screen.
@@ -716,22 +906,28 @@
 // menubar (to be fixed by setting the proper window level; see
 // initializer).
 - (void)mouseMoved:(NSEvent*)theEvent {
-  DCHECK([theEvent window] == [self window]);
+  NSWindow* window = [theEvent window];
+  DCHECK(window == [self window]);
 
   NSPoint eventScreenLocation =
-      [[theEvent window] convertBaseToScreen:[theEvent locationInWindow]];
+      [window convertBaseToScreen:[theEvent locationInWindow]];
 
-  // We use frame (not visibleFrame) since our bookmark folder is on
-  // TOP of the menubar.
-  NSRect visibleRect = [[[self window] screen] frame];
-  CGFloat closeToTopOfScreen = NSMaxY(visibleRect) -
-      verticalScrollArrowHeight_;
-  CGFloat closeToBottomOfScreen = NSMinY(visibleRect) +
-      verticalScrollArrowHeight_;
+  // Base hot spot calculations on the positions of the scroll arrow views.
+  NSRect testRect = [scrollDownArrowView_ frame];
+  NSPoint testPoint = [visibleView_ convertPoint:testRect.origin
+                                                  toView:nil];
+  testPoint = [window convertBaseToScreen:testPoint];
+  CGFloat closeToTopOfScreen = testPoint.y;
 
-  if (eventScreenLocation.y <= closeToBottomOfScreen) {
+  testRect = [scrollUpArrowView_ frame];
+  testPoint = [visibleView_ convertPoint:testRect.origin toView:nil];
+  testPoint = [window convertBaseToScreen:testPoint];
+  CGFloat closeToBottomOfScreen = testPoint.y + testRect.size.height;
+  if (eventScreenLocation.y <= closeToBottomOfScreen &&
+      ![scrollUpArrowView_ isHidden]) {
     [self beginScrollWindowUp];
-  } else if (eventScreenLocation.y > closeToTopOfScreen) {
+  } else if (eventScreenLocation.y > closeToTopOfScreen &&
+      ![scrollDownArrowView_ isHidden]) {
     [self beginScrollWindowDown];
   } else {
     [self endScroll];
@@ -766,17 +962,6 @@
   scrollTrackingArea_.reset();
 }
 
-// Delegate callback.
-- (void)windowWillClose:(NSNotification*)notification {
-  // If a "hover open" is pending when the bookmark bar folder is
-  // closed, be sure it gets cancelled.
-  [NSObject cancelPreviousPerformRequestsWithTarget:self];
-
-  [barController_ childFolderWillClose:self];
-  [self closeBookmarkFolder:self];
-  [self autorelease];
-}
-
 // Close the old hover-open bookmark folder, and open a new one.  We
 // do both in one step to allow for a delay in closing the old one.
 // See comments above kDragHoverCloseDelay (bookmark_bar_controller.h)
@@ -800,7 +985,7 @@
 }
 
 - (void)scrollWheel:(NSEvent *)theEvent {
-  if (scrollable_) {
+  if (![scrollUpArrowView_ isHidden] || ![scrollDownArrowView_ isHidden]) {
     // We go negative since an NSScrollView has a flipped coordinate frame.
     CGFloat amt = kBookmarkBarFolderScrollWheelAmount * -[theEvent deltaY];
     [self performOneScroll:amt];
@@ -926,7 +1111,7 @@
   // dropLocation is in bar local coordinates.
   // http://crbug.com/36276
   NSPoint dropLocation =
-      [mainView_ convertPoint:point
+      [folderView_ convertPoint:point
                      fromView:[[self window] contentView]];
   BookmarkButton* buttonToTheTopOfDraggedButton = nil;
   // Buttons are laid out in this array from top to bottom (screen
@@ -1000,6 +1185,19 @@
   return wasCopiedOrMoved;
 }
 
+#pragma mark NSWindowDelegate Functions
+
+- (void)windowWillClose:(NSNotification*)notification {
+  // If a "hover open" is pending when the bookmark bar folder is
+  // closed, be sure it gets cancelled.
+  [NSObject cancelPreviousPerformRequestsWithTarget:self];
+
+  [self endScroll];  // Just in case we were scrolling.
+  [barController_ childFolderWillClose:self];
+  [self closeBookmarkFolder:self];
+  [self autorelease];
+}
+
 #pragma mark BookmarkButtonDelegate Protocol
 
 - (void)fillPasteboard:(NSPasteboard*)pboard
@@ -1209,7 +1407,7 @@
   return y;
 }
 
-- (ThemeProvider*)themeProvider {
+- (ui::ThemeProvider*)themeProvider {
   return [parentController_ themeProvider];
 }
 
@@ -1249,7 +1447,7 @@
   // topmost button's frame (and there will always be one) offset upward in
   // anticipation of insertion.
   NSRect newButtonFrame = [[buttons_ objectAtIndex:0] frame];
-  newButtonFrame.origin.y += bookmarks::kBookmarkButtonVerticalSpan;
+  newButtonFrame.origin.y += bookmarks::kBookmarkFolderButtonHeight;
   // When adding a button to an empty folder we must remove the 'empty'
   // placeholder button. This can be detected by checking for a parent
   // child count of 1.
@@ -1273,21 +1471,19 @@
     // which is where the new button will be located.
     newButtonFrame = [button frame];
     NSRect buttonFrame = [button frame];
-    buttonFrame.origin.y += bookmarks::kBookmarkButtonVerticalSpan;
+    buttonFrame.origin.y += bookmarks::kBookmarkFolderButtonHeight;
     [button setFrame:buttonFrame];
   }
   [[button cell] mouseExited:nil];  // De-highlight.
   BookmarkButton* newButton = [self makeButtonForNode:node
                                                 frame:newButtonFrame];
   [buttons_ insertObject:newButton atIndex:buttonIndex];
-  [mainView_ addSubview:newButton];
+  [folderView_ addSubview:newButton];
 
   // Close any child folder(s) which may still be open.
   [self closeBookmarkFolder:self];
 
-  // Prelim height of the window.  We'll trim later as needed.
-  int height = [self windowHeightForButtonCount:[buttons_ count]];
-  [self adjustWindowForHeight:height];
+  [self adjustWindowForButtonCount:[buttons_ count]];
 }
 
 // More code which essentially duplicates that of BookmarkBarController.
@@ -1347,7 +1543,7 @@
       for (NSInteger i = fromIndex; i < toIndex; ++i) {
         BookmarkButton* button = [buttons_ objectAtIndex:i];
         NSRect frame = [button frame];
-        frame.origin.y += bookmarks::kBookmarkButtonVerticalSpan;
+        frame.origin.y += bookmarks::kBookmarkFolderButtonHeight;
         [button setFrameOrigin:frame.origin];
       }
     } else {
@@ -1356,7 +1552,7 @@
       for (NSInteger i = fromIndex - 1; i >= toIndex; --i) {
         BookmarkButton* button = [buttons_ objectAtIndex:i];
         NSRect buttonFrame = [button frame];
-        buttonFrame.origin.y -= bookmarks::kBookmarkButtonVerticalSpan;
+        buttonFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight;
         [button setFrameOrigin:buttonFrame.origin];
       }
     }
@@ -1394,14 +1590,11 @@
 
   [oldButton setDelegate:nil];
   [oldButton removeFromSuperview];
-  if (animate && !ignoreAnimations_)
-    NSShowAnimationEffect(NSAnimationEffectDisappearingItemDefault, poofPoint,
-                          NSZeroSize, nil, nil, nil);
   [buttons_ removeObjectAtIndex:buttonIndex];
   for (NSInteger i = 0; i < buttonIndex; ++i) {
     BookmarkButton* button = [buttons_ objectAtIndex:i];
     NSRect buttonFrame = [button frame];
-    buttonFrame.origin.y -= bookmarks::kBookmarkButtonVerticalSpan;
+    buttonFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight;
     [button setFrame:buttonFrame];
   }
   // Search for and adjust submenus, if necessary.
@@ -1419,22 +1612,20 @@
     // If all nodes have been removed from this folder then add in the
     // 'empty' placeholder button.
     NSRect buttonFrame =
-        NSMakeRect(bookmarks::kBookmarkSubMenuHorizontalPadding,
-                   bookmarks::kBookmarkButtonHeight -
-                   (bookmarks::kBookmarkBarHeight -
-                    bookmarks::kBookmarkVerticalPadding),
-                   bookmarks::kDefaultBookmarkWidth,
-                   (bookmarks::kBookmarkBarHeight -
-                    2 * bookmarks::kBookmarkVerticalPadding));
+        NSMakeRect(0.0, 0.0, bookmarks::kDefaultBookmarkWidth,
+                   bookmarks::kBookmarkFolderButtonHeight);
     BookmarkButton* button = [self makeButtonForNode:nil
                                                frame:buttonFrame];
     [buttons_ addObject:button];
-    [mainView_ addSubview:button];
+    [folderView_ addSubview:button];
     buttonCount = 1;
   }
 
-  // Propose a height for the window.  We'll trim later as needed.
-  [self adjustWindowForHeight:[self windowHeightForButtonCount:buttonCount]];
+  [self adjustWindowForButtonCount:buttonCount];
+
+  if (animate && !ignoreAnimations_)
+    NSShowAnimationEffect(NSAnimationEffectDisappearingItemDefault, poofPoint,
+                          NSZeroSize, nil, nil, nil);
 }
 
 - (id<BookmarkButtonControllerProtocol>)controllerForNode:
@@ -1448,6 +1639,30 @@
 
 #pragma mark TestingAPI Only
 
+- (BOOL)canScrollUp {
+  return ![scrollUpArrowView_ isHidden];
+}
+
+- (BOOL)canScrollDown {
+  return ![scrollDownArrowView_ isHidden];
+}
+
+- (CGFloat)verticalScrollArrowHeight {
+  return verticalScrollArrowHeight_;
+}
+
+- (NSView*)visibleView {
+  return visibleView_;
+}
+
+- (NSScrollView*)scrollView {
+  return scrollView_;
+}
+
+- (NSView*)folderView {
+  return folderView_;
+}
+
 - (void)setIgnoreAnimations:(BOOL)ignore {
   ignoreAnimations_ = ignore;
 }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
index cae8766..c0949b8 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -44,7 +44,7 @@
     } else {
       CGFloat nextVerticalOffset = [button frame].origin.y;
       EXPECT_CGFLOAT_EQ(lastVerticalOffset -
-                            bookmarks::kBookmarkButtonVerticalSpan,
+                            bookmarks::kBookmarkFolderButtonHeight,
                         nextVerticalOffset);
       lastVerticalOffset = nextVerticalOffset;
     }
@@ -64,28 +64,7 @@
 }
 @end
 
-// No window level and the ability to fake the "top left" point of the window.
-// For testing.
-@interface BookmarkBarFolderControllerLow : BookmarkBarFolderControllerNoLevel {
-  BOOL realTopLeft_;  // Use the real windowTopLeft call?
-}
-@property (nonatomic) BOOL realTopLeft;
-@end
-
-
-@implementation BookmarkBarFolderControllerLow
-
-@synthesize realTopLeft = realTopLeft_;
-
-- (NSPoint)windowTopLeftForWidth:(int)width {
-  return realTopLeft_ ? [super windowTopLeftForWidth:width] :
-      NSMakePoint(200,200);
-}
-
-@end
-
-
-@interface BookmarkBarFolderControllerPong : BookmarkBarFolderControllerLow {
+@interface BookmarkBarFolderControllerPong : BookmarkBarFolderController {
   BOOL childFolderWillShow_;
   BOOL childFolderWillClose_;
 }
@@ -181,7 +160,9 @@
     [bar_ loaded:model];
     // Make parent frame for bookmark bar then open it.
     NSRect frame = [[test_window() contentView] frame];
-    frame = NSInsetRect(frame, 100, 200);
+    frame = NSMakeRect(frame.origin.x,
+                       frame.size.height - bookmarks::kNTPBookmarkBarHeight,
+                       frame.size.width, bookmarks::kNTPBookmarkBarHeight);
     NSView* fakeToolbarView = [[[NSView alloc] initWithFrame:frame]
                                 autorelease];
     [[test_window() contentView] addSubview:fakeToolbarView];
@@ -235,9 +216,9 @@
   }
   Class cellClass = [BookmarkBarFolderButtonCell class];
   for (BookmarkButton* button in buttons) {
-    NSRect r = [[bbfc mainView] convertRect:[button frame] fromView:button];
+    NSRect r = [[bbfc folderView] convertRect:[button frame] fromView:button];
     // TODO(jrg): remove this adjustment.
-    NSRect bigger = NSInsetRect([[bbfc mainView] frame], -2, 0);
+    NSRect bigger = NSInsetRect([[bbfc folderView] frame], -2, 0);
     EXPECT_TRUE(NSContainsRect(bigger, r));
     EXPECT_TRUE([[button cell] isKindOfClass:cellClass]);
   }
@@ -269,13 +250,12 @@
   EXPECT_TRUE(parentButton);
 
   // If parent is a BookmarkBarController, grow down.
-  scoped_nsobject<BookmarkBarFolderControllerLow> bbfc;
-  bbfc.reset([[BookmarkBarFolderControllerLow alloc]
+  scoped_nsobject<BookmarkBarFolderController> bbfc;
+  bbfc.reset([[BookmarkBarFolderController alloc]
                initWithParentButton:parentButton
                    parentController:nil
                       barController:bar_]);
   [bbfc window];
-  [bbfc setRealTopLeft:YES];
   NSPoint pt = [bbfc windowTopLeftForWidth:0];  // screen coords
   NSPoint buttonOriginInScreen =
       [[parentButton window]
@@ -293,13 +273,12 @@
   EXPECT_LT(shifted.x, pt.x);
 
   // If parent is a BookmarkBarFolderController, grow right.
-  scoped_nsobject<BookmarkBarFolderControllerLow> bbfc2;
-  bbfc2.reset([[BookmarkBarFolderControllerLow alloc]
+  scoped_nsobject<BookmarkBarFolderController> bbfc2;
+  bbfc2.reset([[BookmarkBarFolderController alloc]
                 initWithParentButton:[[bbfc buttons] objectAtIndex:0]
                     parentController:bbfc.get()
                        barController:bar_]);
   [bbfc2 window];
-  [bbfc2 setRealTopLeft:YES];
   pt = [bbfc2 windowTopLeftForWidth:0];
   // We're now overlapping the window a bit.
   EXPECT_EQ(pt.x, NSMaxX([[bbfc.get() window] frame]) -
@@ -376,10 +355,10 @@
   EXPECT_TRUE(bbfc.get());
 
   // Confirm "off the top" and "off the bottom" match no buttons.
-  NSPoint p = NSMakePoint(NSMidX([[bbfc mainView] frame]), 10000);
+  NSPoint p = NSMakePoint(NSMidX([[bbfc folderView] frame]), 10000);
   EXPECT_FALSE([bbfc buttonForDroppingOnAtPoint:p]);
   EXPECT_TRUE([bbfc shouldShowIndicatorShownForPoint:p]);
-  p = NSMakePoint(NSMidX([[bbfc mainView] frame]), -1);
+  p = NSMakePoint(NSMidX([[bbfc folderView] frame]), -1);
   EXPECT_FALSE([bbfc buttonForDroppingOnAtPoint:p]);
   EXPECT_TRUE([bbfc shouldShowIndicatorShownForPoint:p]);
 
@@ -470,29 +449,53 @@
 // Simple scrolling tests.
 TEST_F(BookmarkBarFolderControllerTest, SimpleScroll) {
   scoped_nsobject<BookmarkBarFolderController> bbfc;
-
+  NSRect screenFrame = [[NSScreen mainScreen] frame];
+  CGFloat screenHeight = NSHeight(screenFrame);
   int nodecount = AddLotsOfNodes();
   bbfc.reset(SimpleBookmarkBarFolderController());
   EXPECT_TRUE(bbfc.get());
   [bbfc showWindow:bbfc.get()];
+  NSWindow* window = [bbfc window];
 
-  // Make sure the window fits on the screen.
-  EXPECT_LT(NSHeight([[bbfc window] frame]),
-            NSHeight([[NSScreen mainScreen] frame]));
+  // The window should be shorter than the screen but reach exactly to the
+  // bottom of the screen since it's scrollable.
+  EXPECT_LT(NSHeight([window frame]), screenHeight);
+  EXPECT_CGFLOAT_EQ(0.0, [window frame].origin.y);
 
-  // Verify the logic used by the scroll arrow code.
+  // Initially, should show scroll-up but not scroll-down.
   EXPECT_TRUE([bbfc canScrollUp]);
   EXPECT_FALSE([bbfc canScrollDown]);
 
-  // Scroll it up.  Make sure the window has gotten bigger each time.
+  // Scroll up a bit.  Make sure the window has gotten bigger each time.
   // Also, for each scroll, make sure our hit test finds a new button
   // (to confirm the content area changed).
   NSView* savedHit = nil;
-  for (int i=0; i<3; i++) {
-    CGFloat height = NSHeight([[bbfc window] frame]);
+  NSScrollView* scrollView = [bbfc scrollView];
+
+  // Find the next-to-last button showing at the bottom of the window and
+  // us its center for hit testing.
+  BookmarkButton* targetButton = nil;
+  NSPoint scrollPoint = [scrollView documentVisibleRect].origin;
+  for (BookmarkButton* button in [bbfc buttons]) {
+    NSRect buttonFrame = [button frame];
+    buttonFrame.origin.y -= scrollPoint.y;
+    if (buttonFrame.origin.y < 0.0)
+      break;
+    targetButton = button;
+  }
+  EXPECT_TRUE(targetButton != nil);
+  NSPoint hitPoint = [targetButton frame].origin;
+  hitPoint.x += 50.0;
+  hitPoint.y += (bookmarks::kBookmarkFolderButtonHeight / 2.0) - scrollPoint.y;
+  hitPoint = [targetButton convertPoint:hitPoint toView:scrollView];
+
+  for (int i = 0; i < 3; i++) {
+    CGFloat height = NSHeight([window frame]);
     [bbfc performOneScroll:60];
-    EXPECT_GT(NSHeight([[bbfc window] frame]), height);
-    NSView* hit = [[[bbfc window] contentView] hitTest:NSMakePoint(22, 22)];
+    EXPECT_GT(NSHeight([window frame]), height);
+    NSView* hit = [scrollView hitTest:hitPoint];
+    // We should hit a bookmark button.
+    EXPECT_TRUE([[hit className] isEqualToString:@"BookmarkButton"]);
     EXPECT_NE(hit, savedHit);
     savedHit = hit;
   }
@@ -500,11 +503,9 @@
   // Keep scrolling up; make sure we never get bigger than the screen.
   // Also confirm we never scroll the window off the screen.
   bool bothAtOnce = false;
-  NSRect screenFrame = [[NSScreen mainScreen] frame];
-  for (int i = 0; i < nodecount; i++) {
+  while ([bbfc canScrollUp]) {
     [bbfc performOneScroll:60];
-    EXPECT_TRUE(NSContainsRect(screenFrame,
-                               [[bbfc window] frame]));
+    EXPECT_TRUE(NSContainsRect(screenFrame, [window frame]));
     // Make sure, sometime during our scroll, we have the ability to
     // scroll in either direction.
     if ([bbfc canScrollUp] &&
@@ -520,16 +521,23 @@
   // Now scroll down and make sure the window size does not change.
   // Also confirm we never scroll the window off the screen the other
   // way.
-  for (int i=0; i<nodecount+50; i++) {
-    CGFloat height = NSHeight([[bbfc window] frame]);
+  for (int i = 0; i < nodecount+50; ++i) {
     [bbfc performOneScroll:-60];
-    EXPECT_EQ(height, NSHeight([[bbfc window] frame]));
-    EXPECT_TRUE(NSContainsRect(screenFrame,
-                               [[bbfc window] frame]));
+    // Once we can no longer scroll down the window height changes.
+    if (![bbfc canScrollDown])
+      break;
+    EXPECT_EQ(screenHeight, NSHeight([window frame]));
+    EXPECT_TRUE(NSContainsRect(screenFrame, [window frame]));
   }
+  // The final height should be offset from the top of the screen and still
+  // within the screen.
+  CGFloat height = screenHeight - bookmarks::kScrollWindowVerticalMargin;
+  EXPECT_CGFLOAT_EQ(height, NSHeight([window frame]));
+  EXPECT_TRUE(NSContainsRect(screenFrame, [window frame]));
 }
 
-// Folder menu sizing and placementwhile deleting bookmarks and scrolling tests.
+// Folder menu sizing and placement while deleting bookmarks
+// and scrolling tests.
 TEST_F(BookmarkBarFolderControllerTest, MenuPlacementWhileScrollingDeleting) {
   scoped_nsobject<BookmarkBarFolderController> bbfc;
   AddLotsOfNodes();
@@ -551,7 +559,7 @@
   // the top of the window has moved up, then delete a visible button and
   // make sure the top has not moved.
   oldTop = newTop;
-  const CGFloat scrollOneBookmark = bookmarks::kBookmarkButtonHeight +
+  const CGFloat scrollOneBookmark = bookmarks::kBookmarkFolderButtonHeight +
       bookmarks::kBookmarkVerticalPadding;
   NSUInteger buttonCounter = 0;
   NSUInteger extraButtonLimit = 3;
@@ -579,7 +587,7 @@
   button = [buttons objectAtIndex:buttonCounter + 3];
   [folder deleteBookmark:button];
   newTop = [menuWindow frame].origin.y + NSHeight([menuWindow frame]);
-  EXPECT_CGFLOAT_EQ(oldTop, newTop);
+  EXPECT_CGFLOAT_EQ(oldTop - bookmarks::kScrollWindowVerticalMargin, newTop);
 }
 
 @interface FakedDragInfo : NSObject {
@@ -656,7 +664,7 @@
     // Awkwardness to look like we've been installed.
     [parent_view_ addSubview:[bar view]];
     NSRect frame = [[[bar view] superview] frame];
-    frame.origin.y = 100;
+    frame.origin.y = 400;
     [[[bar view] superview] setFrame:frame];
 
     // Make sure it's on in a window so viewDidMoveToWindow is called
@@ -723,10 +731,8 @@
   // and grown vertically.
   NSRect expectedToWindowFrame = oldToWindowFrame;
   expectedToWindowFrame.origin.x -= horizontalShift;
-  CGFloat diff = (bookmarks::kBookmarkBarHeight +
-                  2*bookmarks::kBookmarkVerticalPadding);
-  expectedToWindowFrame.origin.y -= diff;
-  expectedToWindowFrame.size.height += diff;
+  expectedToWindowFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight;
+  expectedToWindowFrame.size.height += bookmarks::kBookmarkFolderButtonHeight;
   EXPECT_NSRECT_EQ(expectedToWindowFrame, newToWindowFrame);
 
   // Check button spacing.
@@ -790,10 +796,8 @@
   EXPECT_NSRECT_EQ(oldToFolderFrame, newToFolderFrame);
   // The toWindow should have shifted down vertically and grown vertically.
   NSRect expectedToWindowFrame = oldToWindowFrame;
-  CGFloat diff = (bookmarks::kBookmarkBarHeight +
-                  2*bookmarks::kBookmarkVerticalPadding);
-  expectedToWindowFrame.origin.y -= diff;
-  expectedToWindowFrame.size.height += diff;
+  expectedToWindowFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight;
+  expectedToWindowFrame.size.height += bookmarks::kBookmarkFolderButtonHeight;
   EXPECT_NSRECT_EQ(expectedToWindowFrame, newToWindowFrame);
 
   // Copy the button back to the bar after "3b".
@@ -869,10 +873,9 @@
   EXPECT_NSRECT_EQ(oldToWindowFrame, newToWindowFrame);
   NSRect newToSubwindowFrame = [toSubwindow frame];
   NSRect expectedToSubwindowFrame = oldToSubwindowFrame;
-  expectedToSubwindowFrame.origin.y -=
-      bookmarks::kBookmarkBarHeight + bookmarks::kVisualHeightOffset;
+  expectedToSubwindowFrame.origin.y -= bookmarks::kBookmarkFolderButtonHeight;
   expectedToSubwindowFrame.size.height +=
-      bookmarks::kBookmarkBarHeight + bookmarks::kVisualHeightOffset;
+      bookmarks::kBookmarkFolderButtonHeight;
   EXPECT_NSRECT_EQ(expectedToSubwindowFrame, newToSubwindowFrame);
 }
 
@@ -1173,69 +1176,73 @@
                         withObject:button];
   BookmarkBarFolderController* folderController = [bar_ folderController];
   EXPECT_TRUE(folderController);
-  NSWindow* folderMenu = [folderController window];
-  EXPECT_TRUE(folderMenu);
-  CGFloat expectedHeight = (CGFloat)bookmarks::kBookmarkButtonHeight +
+  NSWindow* folderWindow = [folderController window];
+  EXPECT_TRUE(folderWindow);
+  CGFloat expectedHeight = (CGFloat)bookmarks::kBookmarkFolderButtonHeight +
       (2*bookmarks::kBookmarkVerticalPadding);
-  NSRect menuFrame = [folderMenu frame];
-  CGFloat menuHeight = NSHeight(menuFrame);
-  EXPECT_CGFLOAT_EQ(expectedHeight, menuHeight);
-  EXPECT_FALSE([folderController scrollable]);
+  NSRect windowFrame = [folderWindow frame];
+  CGFloat windowHeight = NSHeight(windowFrame);
+  EXPECT_CGFLOAT_EQ(expectedHeight, windowHeight);
+  EXPECT_FALSE([folderController canScrollUp]);
+  EXPECT_FALSE([folderController canScrollDown]);
 
   // Now add a real bookmark and reopen.
   model.AddURL(folder, folder->GetChildCount(), ASCIIToUTF16("a"),
                GURL("http://a.com/"));
   folderController = [bar_ folderController];
   EXPECT_TRUE(folderController);
-  folderMenu = [folderController window];
-  EXPECT_TRUE(folderMenu);
-  menuFrame = [folderMenu frame];
-  menuHeight = NSHeight(menuFrame);
+  NSView* folderView = [folderController folderView];
+  EXPECT_TRUE(folderView);
+  NSRect menuFrame = [folderView frame];
+  NSView* visibleView = [folderController visibleView];
+  NSRect visibleFrame = [visibleView frame];
+  NSScrollView* scrollView = [folderController scrollView];
+  NSRect scrollFrame = [scrollView frame];
+
+  // Determine the margins between the scroll frame and the visible frame.
+  CGFloat widthDelta = NSWidth(visibleFrame) - NSWidth(scrollFrame);
+
+  CGFloat menuHeight = NSHeight(menuFrame);
   EXPECT_CGFLOAT_EQ(expectedHeight, menuHeight);
-  CGFloat menuWidth = NSWidth(menuFrame);
+  CGFloat scrollerWidth = NSWidth(scrollFrame);
   button = [folderController buttonWithTitleEqualTo:@"a"];
   CGFloat buttonWidth = NSWidth([button frame]);
-  CGFloat expectedWidth =
-      buttonWidth + (2 * bookmarks::kBookmarkSubMenuHorizontalPadding);
-  EXPECT_CGFLOAT_EQ(expectedWidth, menuWidth);
+  EXPECT_CGFLOAT_EQ(scrollerWidth, buttonWidth);
+  CGFloat visibleWidth = NSWidth(visibleFrame);
+  EXPECT_CGFLOAT_EQ(visibleWidth - widthDelta, buttonWidth);
+  EXPECT_LT(scrollerWidth, NSWidth([folderView frame]));
 
   // Add a wider bookmark and make sure the button widths match.
-  model.AddURL(folder, folder->GetChildCount(),
-               ASCIIToUTF16("A really, really long name"),
+  int reallyWideButtonNumber = folder->GetChildCount();
+  model.AddURL(folder, reallyWideButtonNumber,
+               ASCIIToUTF16("A really, really, really, really, really, "
+                            "really long name"),
                GURL("http://www.google.com/a"));
-  EXPECT_LT(menuWidth, NSWidth([folderMenu frame]));
-  EXPECT_LT(buttonWidth, NSWidth([button frame]));
-  buttonWidth = NSWidth([button frame]);
-  BookmarkButton* buttonB =
-      [folderController buttonWithTitleEqualTo:@"A really, really long name"];
-  EXPECT_TRUE(buttonB);
-  CGFloat buttonWidthB = NSWidth([buttonB frame]);
-  EXPECT_CGFLOAT_EQ(buttonWidth, buttonWidthB);
-  // Add a bunch of bookmarks until the window grows no more, then check for
-  // a scroll down arrow.
-  CGFloat oldMenuHeight = 0.0;  // It just has to be different for first run.
-  menuHeight = NSHeight([folderMenu frame]);
+  BookmarkButton* bigButton =
+      [folderController buttonWithTitleEqualTo:
+       @"A really, really, really, really, really, really long name"];
+  EXPECT_TRUE(bigButton);
+  CGFloat buttonWidthB = NSWidth([bigButton frame]);
+  EXPECT_LT(buttonWidth, buttonWidthB);
+  // Add a bunch of bookmarks until the window becomes scrollable, then check
+  // for a scroll up arrow.
   NSUInteger tripWire = 0;  // Prevent a runaway.
-  while (![folderController scrollable] && ++tripWire < 100) {
+  while (![folderController canScrollUp] && ++tripWire < 1000) {
     model.AddURL(folder, folder->GetChildCount(), ASCIIToUTF16("B"),
                  GURL("http://b.com/"));
-    oldMenuHeight = menuHeight;
-    menuHeight = NSHeight([folderMenu frame]);
   }
-  EXPECT_TRUE([folderController scrollable]);
   EXPECT_TRUE([folderController canScrollUp]);
 
   // Remove one bookmark and make sure the scroll down arrow has been removed.
   // We'll remove the really long node so we can see if the buttons get resized.
-  menuWidth = NSWidth([folderMenu frame]);
+  scrollerWidth = NSWidth([folderView frame]);
   buttonWidth = NSWidth([button frame]);
-  model.Remove(folder, 1);
-  EXPECT_FALSE([folderController scrollable]);
+  model.Remove(folder, reallyWideButtonNumber);
   EXPECT_FALSE([folderController canScrollUp]);
   EXPECT_FALSE([folderController canScrollDown]);
 
   // Check the size. It should have reduced.
-  EXPECT_GT(menuWidth, NSWidth([folderMenu frame]));
+  EXPECT_GT(scrollerWidth, NSWidth([folderView frame]));
   EXPECT_GT(buttonWidth, NSWidth([button frame]));
 
   // Check button spacing.
@@ -1362,7 +1369,7 @@
   // Verify the model.
   const std::string expectedA("1b 2f:[ O3f:[ O3f1b O3f2f ] 2f1b 2f2f:[ "
                               "2f2f1b 2f2f2b 2f2f3b O4f:[ O4f1b O4f2f ] ] "
-                               "2f3b ] 3b 4b ");
+                              "2f3b ] 3b 4b ");
   actual = model_test_utils::ModelStringFromNode(root);
   EXPECT_EQ(expectedA, actual);
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view.h
index 8f60b8e..b0a6817 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_view.h
@@ -23,7 +23,7 @@
 @end
 
 @interface BookmarkBarFolderView()  // TestingOrInternalAPI
-@property (assign) BOOL dropIndicatorShown;
-@property (readonly) CGFloat dropIndicatorPosition;
+@property(assign) BOOL dropIndicatorShown;
+@property(readonly) CGFloat dropIndicatorPosition;
 - (void)setController:(id)controller;
 @end
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h
index cd97d9e..7fe6608 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h
@@ -13,17 +13,16 @@
 
 // Window for a bookmark folder "menu".  This menu pops up when you
 // click on a bookmark button that represents a folder of bookmarks.
-// This window is borderless.
+// This window is borderless but has a shadow, at least initially.
+// Once the down scroll arrow is shown, the shadow is turned off and
+// a secondary window is added which is sized to match the visible
+// area of the menu and which provides the shadow.
 @interface BookmarkBarFolderWindow : NSWindow
 @end
 
 // Content view for the above window.  "Stock" other than the drawing
 // of rounded corners.  Only used in the nib.
-@interface BookmarkBarFolderWindowContentView : NSView {
-  // Arrows to show ability to scroll up and down as needed.
-  scoped_nsobject<NSImage> arrowUpImage_;
-  scoped_nsobject<NSImage> arrowDownImage_;
-}
+@interface BookmarkBarFolderWindowContentView : NSView
 @end
 
 // Scroll view that contains the main view (where the buttons go).
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm
index 65cb664..c64de1e 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.mm
@@ -5,13 +5,14 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
 
 #import "base/logging.h"
-#include "app/mac/nsimage_cache.h"
 #import "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h"
 #import "chrome/browser/ui/cocoa/image_utils.h"
 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
 
+using bookmarks::kBookmarkBarMenuCornerRadius;
 
 @implementation BookmarkBarFolderWindow
 
@@ -32,89 +33,30 @@
 @end
 
 
-namespace {
-// Corner radius for our bookmark bar folder window.
-// Copied from bubble_view.mm.
-const CGFloat kViewCornerRadius = 4.0;
-}
-
 @implementation BookmarkBarFolderWindowContentView
 
-- (void)awakeFromNib {
-  arrowUpImage_.reset(
-      [app::mac::GetCachedImageWithName(@"menu_overflow_up.pdf") retain]);
-  arrowDownImage_.reset(
-      [app::mac::GetCachedImageWithName(@"menu_overflow_down.pdf") retain]);
-}
-
-// Draw the arrows at the top and bottom of the folder window as a
-// visual indication that scrolling is possible.  We always draw the
-// scrolling arrows; when not relevant (e.g. when not scrollable), the
-// scroll view overlaps the window and the arrows aren't visible.
-- (void)drawScrollArrows:(NSRect)rect {
-  NSRect visibleRect = [self bounds];
-
-  // On top
-  NSRect imageRect = NSZeroRect;
-  imageRect.size = [arrowUpImage_ size];
-  NSRect drawRect = NSOffsetRect(
-      imageRect,
-      (NSWidth(visibleRect) - NSWidth(imageRect)) / 2,
-      NSHeight(visibleRect) - NSHeight(imageRect));
-  [arrowUpImage_ drawInRect:drawRect
-                   fromRect:imageRect
-                  operation:NSCompositeSourceOver
-                   fraction:1.0
-               neverFlipped:YES];
-
-  // On bottom
-  imageRect = NSZeroRect;
-  imageRect.size = [arrowDownImage_ size];
-  drawRect = NSOffsetRect(imageRect,
-                          (NSWidth(visibleRect) - NSWidth(imageRect)) / 2,
-                          0);
-  [arrowDownImage_ drawInRect:drawRect
-                     fromRect:imageRect
-                    operation:NSCompositeSourceOver
-                     fraction:1.0
-                 neverFlipped:YES];
-}
-
 - (void)drawRect:(NSRect)rect {
-  NSRect bounds = [self bounds];
   // Like NSMenus, only the bottom corners are rounded.
   NSBezierPath* bezier =
-      [NSBezierPath gtm_bezierPathWithRoundRect:bounds
-                            topLeftCornerRadius:0
-                           topRightCornerRadius:0
-                         bottomLeftCornerRadius:kViewCornerRadius
-                        bottomRightCornerRadius:kViewCornerRadius];
-  [bezier closePath];
-
-  // TODO(jrg): share code with info_bubble_view.mm?  Or bubble_view.mm?
-  NSColor* base_color = [NSColor colorWithCalibratedWhite:0.5 alpha:1.0];
-  NSColor* startColor =
-      [base_color gtm_colorAdjustedFor:GTMColorationLightHighlight
-                                 faded:YES];
+      [NSBezierPath gtm_bezierPathWithRoundRect:[self bounds]
+                            topLeftCornerRadius:kBookmarkBarMenuCornerRadius
+                           topRightCornerRadius:kBookmarkBarMenuCornerRadius
+                         bottomLeftCornerRadius:kBookmarkBarMenuCornerRadius
+                        bottomRightCornerRadius:kBookmarkBarMenuCornerRadius];
+  NSColor* startColor = [NSColor colorWithCalibratedWhite:0.91 alpha:1.0];
   NSColor* midColor =
-      [base_color gtm_colorAdjustedFor:GTMColorationLightMidtone
-                                 faded:YES];
+      [startColor gtm_colorAdjustedFor:GTMColorationLightMidtone faded:YES];
   NSColor* endColor =
-      [base_color gtm_colorAdjustedFor:GTMColorationLightShadow
-                                 faded:YES];
-  NSColor* glowColor =
-      [base_color gtm_colorAdjustedFor:GTMColorationLightPenumbra
-                                 faded:YES];
+      [startColor gtm_colorAdjustedFor:GTMColorationLightPenumbra faded:YES];
 
   scoped_nsobject<NSGradient> gradient(
     [[NSGradient alloc] initWithColorsAndLocations:startColor, 0.0,
                         midColor, 0.25,
                         endColor, 0.5,
-                        glowColor, 0.75,
+                        midColor, 0.75,
+                        startColor, 1.0,
                         nil]);
   [gradient drawInBezierPath:bezier angle:0.0];
-
-  [self drawScrollArrows:rect];
 }
 
 @end
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
index 1942ebd..02936ae 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
@@ -18,7 +18,10 @@
 
 @class BookmarkBarView;
 class TabContents;
+
+namespace ui {
 class ThemeProvider;
+}
 
 // An interface to allow mocking of a BookmarkBarController by the
 // BookmarkBarToolbarView.
@@ -29,7 +32,7 @@
 - (int)currentTabContentsHeight;
 
 // Current theme provider, passed to the cross platform NtpBackgroundUtil class.
-- (ThemeProvider*)themeProvider;
+- (ui::ThemeProvider*)themeProvider;
 
 @end
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
index 760de17..94c364d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
@@ -4,15 +4,15 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h"
 
-#include "app/theme_provider.h"
-#include "gfx/rect.h"
 #include "chrome/browser/ntp_background_util.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
-#include "gfx/canvas_skia_paint.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/rect.h"
 
 const CGFloat kBorderRadius = 3.0;
 
@@ -45,7 +45,7 @@
 
   NSRect bounds = [self bounds];
 
-  ThemeProvider* themeProvider = [controller_ themeProvider];
+  ui::ThemeProvider* themeProvider = [controller_ themeProvider];
   if (!themeProvider)
     return;
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
index 24d971a..ef8bfc8 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/theme_provider.h"
 #include "base/scoped_nsobject.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
@@ -16,6 +15,7 @@
 #include "testing/platform_test.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/theme_provider.h"
 
 using ::testing::_;
 using ::testing::DoAll;
@@ -23,7 +23,7 @@
 using ::testing::SetArgumentPointee;
 
 // When testing the floating drawing, we need to have a source of theme data.
-class MockThemeProvider : public ThemeProvider {
+class MockThemeProvider : public ui::ThemeProvider {
  public:
   // Cross platform methods
   MOCK_METHOD1(Init, void(Profile*));
@@ -58,11 +58,11 @@
     NSObject<BookmarkBarState, BookmarkBarToolbarViewController> {
  @private
   int currentTabContentsHeight_;
-  ThemeProvider* themeProvider_;
+  ui::ThemeProvider* themeProvider_;
   bookmarks::VisualState visualState_;
 }
 @property (nonatomic, assign) int currentTabContentsHeight;
-@property (nonatomic, assign) ThemeProvider* themeProvider;
+@property (nonatomic, assign) ui::ThemeProvider* themeProvider;
 @property (nonatomic, assign) bookmarks::VisualState visualState;
 
 // |BookmarkBarState| protocol:
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h
index abcbdf0..6efe6b0 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h
@@ -29,12 +29,12 @@
 - (NSButton*)importBookmarksButton;
 - (BookmarkBarController*)controller;
 
-@property (nonatomic, assign) IBOutlet NSView* noItemContainer;
+@property(nonatomic, assign) IBOutlet NSView* noItemContainer;
 @end
 
 @interface BookmarkBarView()  // TestingOrInternalAPI
-@property (nonatomic, readonly) BOOL dropIndicatorShown;
-@property (nonatomic, readonly) CGFloat dropIndicatorPosition;
+@property(nonatomic, readonly) BOOL dropIndicatorShown;
+@property(nonatomic, readonly) CGFloat dropIndicatorPosition;
 - (void)setController:(id)controller;
 @end
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm
index 5083367..06a5443 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.mm
@@ -16,7 +16,7 @@
 
 @interface BookmarkBarView (Private)
 - (void)themeDidChangeNotification:(NSNotification*)aNotification;
-- (void)updateTheme:(ThemeProvider*)themeProvider;
+- (void)updateTheme:(ui::ThemeProvider*)themeProvider;
 @end
 
 @implementation BookmarkBarView
@@ -59,7 +59,7 @@
 // controller desn't have access to it until it's placed in the view
 // hierarchy.  This is the spot where we close the loop.
 - (void)viewWillMoveToWindow:(NSWindow*)window {
-  ThemeProvider* themeProvider = [window themeProvider];
+  ui::ThemeProvider* themeProvider = [window themeProvider];
   [self updateTheme:themeProvider];
   [controller_ updateTheme:themeProvider];
 }
@@ -70,14 +70,14 @@
 
 // Called after the current theme has changed.
 - (void)themeDidChangeNotification:(NSNotification*)aNotification {
-  ThemeProvider* themeProvider =
-      static_cast<ThemeProvider*>([[aNotification object] pointerValue]);
+  ui::ThemeProvider* themeProvider =
+      static_cast<ui::ThemeProvider*>([[aNotification object] pointerValue]);
   [self updateTheme:themeProvider];
 }
 
 // Adapt appearance to the current theme. Called after theme changes and before
 // this is shown for the first time.
-- (void)updateTheme:(ThemeProvider*)themeProvider {
+- (void)updateTheme:(ui::ThemeProvider*)themeProvider {
   if (!themeProvider)
     return;
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h
index 3ed8f7b..e1d7bb4 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h
@@ -44,7 +44,7 @@
   IBOutlet InfoBubbleView* bubble_;  // to set arrow position
 }
 
-@property (readonly, nonatomic) const BookmarkNode* node;
+@property(readonly, nonatomic) const BookmarkNode* node;
 
 // |node| is the bookmark node we edit in this bubble.
 // |alreadyBookmarked| tells us if the node was bookmarked before the
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm
index 82258da..d0a6dd8 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"  // TODO(viettrungluu): remove
@@ -17,6 +16,7 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 
 // Simple class to watch for tab creation/destruction and close the bubble.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h
index 0bea5a5..6525e8e 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h
@@ -13,7 +13,10 @@
 class BookmarkModel;
 class BookmarkNode;
 @class BrowserWindowController;
+
+namespace ui {
 class ThemeProvider;
+}
 
 // Protocol for a BookmarkButton's delegate, responsible for doing
 // things on behalf of a bookmark button.
@@ -115,7 +118,7 @@
 - (CGFloat)indicatorPosForDragToPoint:(NSPoint)point;
 
 // Return the theme provider associated with this browser window.
-- (ThemeProvider*)themeProvider;
+- (ui::ThemeProvider*)themeProvider;
 
 // Called just before a child folder puts itself on screen.
 - (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
index 2e28cf4..dbcff34 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
@@ -30,9 +30,9 @@
   scoped_nsobject<NSImage> arrowImage_;
 }
 
-@property (nonatomic, readwrite, assign) const BookmarkNode* bookmarkNode;
-@property (nonatomic, readwrite, assign) int startingChildIndex;
-@property (nonatomic, readwrite, assign) BOOL drawFolderArrow;
+@property(nonatomic, readwrite, assign) const BookmarkNode* bookmarkNode;
+@property(nonatomic, readwrite, assign) int startingChildIndex;
+@property(nonatomic, readwrite, assign) BOOL drawFolderArrow;
 
 // Create a button cell which draws with a theme.
 + (id)buttonCellForNode:(const BookmarkNode*)node
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
index a78d627..129117d 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h"
 
-#include "app/l10n_util_mac.h"
 #include "app/mac/nsimage_cache.h"
 #include "base/logging.h"
 #include "base/sys_string_conversions.h"
@@ -14,6 +13,7 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
 #import "chrome/browser/ui/cocoa/image_utils.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 
 @interface BookmarkButtonCell(Private)
@@ -231,10 +231,11 @@
   if ([button isFolder]) {
     NSRect imageRect = NSZeroRect;
     imageRect.size = [arrowImage_ size];
-    NSRect drawRect = NSOffsetRect(imageRect,
-                                   NSWidth(cellFrame) - NSWidth(imageRect),
-                                   (NSHeight(cellFrame) / 2.0) -
-                                   (NSHeight(imageRect) / 2.0));
+    const CGFloat kArrowOffset = 1.0;  // Required for proper centering.
+    CGFloat dX = NSWidth(cellFrame) - NSWidth(imageRect);
+    CGFloat dY = (NSHeight(cellFrame) / 2.0) - (NSHeight(imageRect) / 2.0) +
+        kArrowOffset;
+    NSRect drawRect = NSOffsetRect(imageRect, dX, dY);
     [arrowImage_ drawInRect:drawRect
                     fromRect:imageRect
                    operation:NSCompositeSourceOver
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
index ff26512..f3663b4 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/resource_bundle.h"
 #include "base/scoped_nsobject.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
@@ -13,6 +12,7 @@
 #include "grit/app_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Simple class to remember how many mouseEntered: and mouseExited:
 // calls it gets.  Only used by BookmarkMouseForwarding but placed
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_source.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_source.h
index 53d4361..c3ab0a5 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_source.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_drag_source.h
@@ -5,7 +5,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/ui/cocoa/web_contents_drag_source.h"
+#include "chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.h"
 
 // A class that handles tracking and event processing for a drag and drop
 // originating from the content area.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h
index 34e7032..b39953b 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h
@@ -47,11 +47,11 @@
   scoped_ptr<BookmarkEditorBaseControllerBridge> observer_;
 }
 
-@property (nonatomic, copy) NSString* initialName;
-@property (nonatomic, copy) NSString* displayName;
-@property (nonatomic, assign) BOOL okEnabled;
-@property (nonatomic, retain, readonly) NSArray* folderTreeArray;
-@property (nonatomic, copy) NSArray* tableSelectionPaths;
+@property(nonatomic, copy) NSString* initialName;
+@property(nonatomic, copy) NSString* displayName;
+@property(nonatomic, assign) BOOL okEnabled;
+@property(nonatomic, retain, readonly) NSArray* folderTreeArray;
+@property(nonatomic, copy) NSArray* tableSelectionPaths;
 
 // Designated initializer.  Derived classes should call through to this init.
 - (id)initWithParentWindow:(NSWindow*)parentWindow
@@ -121,10 +121,10 @@
   BOOL newFolder_;
 }
 
-@property (nonatomic, copy) NSString* folderName;
-@property (nonatomic, assign) const BookmarkNode* folderNode;
-@property (nonatomic, retain) NSMutableArray* children;
-@property (nonatomic, assign) BOOL newFolder;
+@property(nonatomic, copy) NSString* folderName;
+@property(nonatomic, assign) const BookmarkNode* folderNode;
+@property(nonatomic, retain) NSMutableArray* children;
+@property(nonatomic, assign) BOOL newFolder;
 
 // Convenience creator for adding a new folder to the editor's bookmark
 // structure.  This folder will be added to the bookmark model when the
@@ -153,7 +153,7 @@
 
 @interface BookmarkEditorBaseController(TestingAPI)
 
-@property (nonatomic, readonly) BOOL okButtonEnabled;
+@property(nonatomic, readonly) BOOL okButtonEnabled;
 
 // Create any newly added folders.  New folders are nodes in folderTreeArray
 // which are marked as being new (i.e. their kFolderTreeNewFolderKey
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm
index 8cce1b4..329a027 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm
@@ -6,8 +6,6 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
@@ -18,6 +16,8 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @interface BookmarkEditorBaseController ()
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
index 6325346..1df1697 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/l10n_util_mac.h"
 #include "base/scoped_nsobject.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -16,6 +15,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 class BookmarkEditorBaseControllerTest : public CocoaTest {
  public:
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h
index 30f1c75..9fc6e95 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h
@@ -19,7 +19,7 @@
   IBOutlet NSTextField* urlField_;
 }
 
-@property (nonatomic, copy) NSString* displayURL;
+@property(nonatomic, copy) NSString* displayURL;
 
 - (id)initWithParentWindow:(NSWindow*)parentWindow
                    profile:(Profile*)profile
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.mm
index 88ed4bf..557150f 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.mm
@@ -4,10 +4,10 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
+#include "ui/base/l10n/l10n_util.h"
 
 @interface BookmarkEditorController (Private)
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu.h
index d4ac001..bba953f 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu.h
@@ -15,6 +15,6 @@
   int64 id_;  // id of the bookmark node we represent.
 }
 - (void)setRepresentedObject:(id)object;
-@property (nonatomic) int64 id;
+@property(nonatomic) int64 id;
 @end
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
index 3792fe3..f5ac98a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
@@ -4,21 +4,20 @@
 
 #import <AppKit/AppKit.h>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "app/mac/nsimage_cache.h"
 #include "base/sys_string_conversions.h"
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 BookmarkMenuBridge::BookmarkMenuBridge(Profile* profile)
     : menuIsValid_(false),
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
index cec14eb..87fcb34 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
@@ -12,7 +12,6 @@
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/browser.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h
index ac7def4..c746311 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h
@@ -23,7 +23,7 @@
 }
 
 // The Bookmarks menu
-@property (nonatomic, readonly) NSMenu* menu;
+@property(nonatomic, readonly) NSMenu* menu;
 
 // Return an autoreleased string to be used as a menu title for the
 // given bookmark node.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
index 1d2fb2d..7f9e616 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h"
 
-#include "app/text_elider.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"  // IDC_BOOKMARK_MENU
@@ -13,6 +12,7 @@
 #include "chrome/browser/ui/browser.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/event_utils.h"
+#include "ui/base/text/text_elider.h"
 #include "webkit/glue/window_open_disposition.h"
 
 namespace {
@@ -27,12 +27,12 @@
 
 + (NSString*)menuTitleForNode:(const BookmarkNode*)node {
   NSFont* nsfont = [NSFont menuBarFontOfSize:0];  // 0 means "default"
-  gfx::Font font(base::SysNSStringToWide([nsfont fontName]),
+  gfx::Font font(base::SysNSStringToUTF16([nsfont fontName]),
                  static_cast<int>([nsfont pointSize]));
-  string16 title = gfx::ElideText(node->GetTitle(),
-                                  font,
-                                  kMaximumMenuPixelsWide,
-                                  false);
+  string16 title = ui::ElideText(node->GetTitle(),
+                                 font,
+                                 kMaximumMenuPixelsWide,
+                                 false);
   return base::SysUTF16ToNSString(title);
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm
index 4db77eb..fa369a2 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm
@@ -4,13 +4,13 @@
 
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @implementation BookmarkNameFolderController
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h
index 08b195d..9ae31cc 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h
@@ -23,9 +23,9 @@
   SEL action_;
 }
 
-@property (nonatomic, assign) NSMatrix* matrix;
-@property (nonatomic, assign) id target;
-@property (nonatomic, assign) SEL action;
+@property(nonatomic, assign) NSMatrix* matrix;
+@property(nonatomic, assign) id target;
+@property(nonatomic, assign) SEL action;
 
 - (const BookmarkNode*)bookmarkNode;
 - (void)setBookmarkNode:(const BookmarkNode*)bookmarkNode;
diff --git a/chrome/browser/ui/cocoa/browser_frame_view.mm b/chrome/browser/ui/cocoa/browser_frame_view.mm
index a966785..4b6980b 100644
--- a/chrome/browser/ui/cocoa/browser_frame_view.mm
+++ b/chrome/browser/ui/cocoa/browser_frame_view.mm
@@ -212,7 +212,7 @@
                             bounds:(NSRect)bounds
                             offset:(NSPoint)offset
               forceBlackBackground:(BOOL)forceBlackBackground {
-  ThemeProvider* themeProvider = [[view window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[view window] themeProvider];
   if (!themeProvider)
     return NO;
 
@@ -324,7 +324,7 @@
 }
 
 + (NSColor*)titleColorForThemeView:(NSView*)view {
-  ThemeProvider* themeProvider = [[view window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[view window] themeProvider];
   if (!themeProvider)
     return [NSColor windowFrameTextColor];
 
diff --git a/chrome/browser/ui/cocoa/browser_test_helper.h b/chrome/browser/ui/cocoa/browser_test_helper.h
index 44cde96..af22364 100644
--- a/chrome/browser/ui/cocoa/browser_test_helper.h
+++ b/chrome/browser/ui/cocoa/browser_test_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,8 +15,8 @@
 //
 // This class creates fake UI, file, and IO threads because many objects that
 // are attached to the TestingProfile (and other objects) have traits that limit
-// their destruction to certain threads. For example, the URLRequestContext can
-// only be deleted on the IO thread; without this fake IO thread, the object
+// their destruction to certain threads. For example, the net::URLRequestContext
+// can only be deleted on the IO thread; without this fake IO thread, the object
 // would never be deleted and would report as a leak under Valgrind. Note that
 // these are fake threads and they all share the same MessageLoop.
 //
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index d41afc1..548bb55 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -49,6 +49,7 @@
   virtual void UpdateLoadingAnimations(bool should_animate);
   virtual void SetStarredState(bool is_starred);
   virtual gfx::Rect GetRestoredBounds() const;
+  virtual gfx::Rect GetBounds() const;
   virtual bool IsMaximized() const;
   virtual void SetFullscreen(bool fullscreen);
   virtual bool IsFullscreen() const;
@@ -73,10 +74,10 @@
   virtual views::Window* ShowAboutChromeDialog();
   virtual void ShowUpdateChromeDialog();
   virtual void ShowTaskManager();
+  virtual void ShowBackgroundPages();
   virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
   virtual bool IsDownloadShelfVisible() const;
   virtual DownloadShelf* GetDownloadShelf();
-  virtual void ShowReportBugDialog();
   virtual void ShowClearBrowsingDataDialog();
   virtual void ShowImportDialog();
   virtual void ShowSearchEnginesDialog();
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index 1d3f512..8edbe5a 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -25,29 +24,29 @@
 #import "chrome/browser/ui/cocoa/bug_report_window_controller.h"
 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
 #import "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
-#import "chrome/browser/ui/cocoa/collected_cookies_mac.h"
-#import "chrome/browser/ui/cocoa/content_settings_dialog_controller.h"
+#import "chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h"
 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
-#import "chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.h"
 #import "chrome/browser/ui/cocoa/html_dialog_window_controller.h"
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
-#import "chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/importer/import_settings_dialog.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
+#import "chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h"
+#import "chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h"
 #import "chrome/browser/ui/cocoa/nsmenuitem_additions.h"
 #include "chrome/browser/ui/cocoa/repost_form_warning_mac.h"
 #include "chrome/browser/ui/cocoa/restart_browser.h"
 #include "chrome/browser/ui/cocoa/status_bubble_mac.h"
 #include "chrome/browser/ui/cocoa/task_manager_mac.h"
 #import "chrome/browser/ui/cocoa/theme_install_bubble_view.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/native_web_keyboard_event.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/rect.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/gfx/rect.h"
 
 BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser,
                                        BrowserWindowController* controller,
@@ -78,6 +77,7 @@
 }
 
 void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) {
+  SetFullscreen(false);
   NSRect cocoa_bounds = NSMakeRect(bounds.x(), 0, bounds.width(),
                                    bounds.height());
   // Flip coordinates based on the primary screen.
@@ -201,6 +201,10 @@
   return bounds;
 }
 
+gfx::Rect BrowserWindowCocoa::GetBounds() const {
+  return GetRestoredBounds();
+}
+
 bool BrowserWindowCocoa::IsMaximized() const {
   return [window() isZoomed];
 }
@@ -306,11 +310,15 @@
 }
 
 void BrowserWindowCocoa::ShowUpdateChromeDialog() {
-  restart_browser::RequestRestart(nil);
+  restart_browser::RequestRestart(window());
 }
 
 void BrowserWindowCocoa::ShowTaskManager() {
-  TaskManagerMac::Show();
+  TaskManagerMac::Show(false);
+}
+
+void BrowserWindowCocoa::ShowBackgroundPages() {
+  TaskManagerMac::Show(true);
 }
 
 void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
@@ -328,13 +336,6 @@
   return [shelfController bridge];
 }
 
-void BrowserWindowCocoa::ShowReportBugDialog() {
-  TabContents* current_tab = browser_->GetSelectedTabContents();
-  if (current_tab && current_tab->controller().GetActiveEntry()) {
-    browser_->ShowBrokenPageTab(current_tab);
-  }
-}
-
 void BrowserWindowCocoa::ShowClearBrowsingDataDialog() {
   [ClearBrowsingDataController
       showClearBrowsingDialogForProfile:browser_->profile()];
@@ -435,7 +436,7 @@
   if (id == -1)
     return false;
 
-  if (browser_->IsReservedCommand(id))
+  if (browser_->IsReservedCommandOrKey(id, event))
     return HandleKeyboardEventInternal(event.os_event);
 
   DCHECK(is_keyboard_shortcut != NULL);
@@ -494,7 +495,7 @@
 
   // "Close window" doesn't use the |commandDispatch:| mechanism. Menu items
   // that do not correspond to IDC_ constants need no special treatment however,
-  // as they can't be blacklisted in |Browser::IsReservedCommand()| anyhow.
+  // as they can't be blacklisted in |Browser::IsReservedCommandOrKey()| anyhow.
   if (item && [item action] == @selector(performClose:))
     return IDC_CLOSE_WINDOW;
 
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index 4ff053e..0820217 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -19,9 +19,9 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h"
 #import "chrome/browser/ui/cocoa/browser_command_executor.h"
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_window_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
@@ -245,7 +245,7 @@
 - (void)updateSidebarForContents:(TabContents*)contents;
 
 // Gets the current theme provider.
-- (ThemeProvider*)themeProvider;
+- (ui::ThemeProvider*)themeProvider;
 
 // Gets the window style.
 - (ThemedWindowStyle)themedWindowStyle;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 6240065..ce8697a 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <Carbon/Carbon.h>
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "app/mac/scoped_nsdisable_screen_updates.h"
 #include "app/mac/nsimage_cache.h"
 #include "base/mac/mac_util.h"
@@ -35,25 +33,24 @@
 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
 #import "chrome/browser/ui/cocoa/event_utils.h"
 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
-#import "chrome/browser/ui/cocoa/find_bar_bridge.h"
-#import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
 #import "chrome/browser/ui/cocoa/focus_tracker.h"
 #import "chrome/browser/ui/cocoa/fullscreen_controller.h"
 #import "chrome/browser/ui/cocoa/fullscreen_window.h"
 #import "chrome/browser/ui/cocoa/image_utils.h"
-#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
-#import "chrome/browser/ui/cocoa/previewable_contents_controller.h"
-#import "chrome/browser/ui/cocoa/nswindow_additions.h"
-#import "chrome/browser/ui/cocoa/sad_tab_controller.h"
 #import "chrome/browser/ui/cocoa/sidebar_controller.h"
 #import "chrome/browser/ui/cocoa/status_bubble_mac.h"
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-#import "chrome/browser/ui/cocoa/tab_view.h"
+#import "chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_view.h"
 #import "chrome/browser/ui/cocoa/tabpose_window.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/browser/ui/tabs/dock_info.h"
@@ -62,6 +59,8 @@
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 // ORGANIZATION: This is a big file. It is (in principle) organized as follows
 // (in order):
@@ -299,12 +298,6 @@
     // managing the creation of new tabs.
     [self createTabStripController];
 
-    // Create the infobar container view, so we can pass it to the
-    // ToolbarController.
-    infoBarContainerController_.reset(
-        [[InfoBarContainerController alloc] initWithResizeDelegate:self]);
-    [[[self window] contentView] addSubview:[infoBarContainerController_ view]];
-
     // Create a controller for the toolbar, giving it the toolbar model object
     // and the toolbar view from the nib. The controller will handle
     // registering for the appropriate command state changes from the back-end.
@@ -336,6 +329,12 @@
                                  relativeTo:[toolbarController_ view]];
     [bookmarkBarController_ setBookmarkBarEnabled:[self supportsBookmarkBar]];
 
+    // Create the infobar container view, so we can pass it to the
+    // ToolbarController.
+    infoBarContainerController_.reset(
+        [[InfoBarContainerController alloc] initWithResizeDelegate:self]);
+    [[[self window] contentView] addSubview:[infoBarContainerController_ view]];
+
     // We don't want to try and show the bar before it gets placed in its parent
     // view, so this step shoudn't be inside the bookmark bar controller's
     // |-awakeFromNib|.
@@ -480,7 +479,8 @@
 }
 
 - (void)updateDevToolsForContents:(TabContents*)contents {
-  [devToolsController_ updateDevToolsForTabContents:contents];
+  [devToolsController_ updateDevToolsForTabContents:contents
+                                        withProfile:browser_->profile()];
   [devToolsController_ ensureContentsVisible];
 }
 
@@ -906,7 +906,7 @@
 
   // Update the checked/Unchecked state of items in the encoding menu.
   // On Windows, this logic is part of |EncodingMenuModel| in
-  // browser/views/toolbar_view.h.
+  // browser/ui/views/toolbar_view.h.
   EncodingMenuController encoding_controller;
   if (encoding_controller.DoesCommandBelongToEncodingMenu(tag)) {
     DCHECK(browser_.get());
@@ -1429,7 +1429,8 @@
   windowShim_->UpdateTitleBar();
 
   [sidebarController_ updateSidebarForTabContents:contents];
-  [devToolsController_ updateDevToolsForTabContents:contents];
+  [devToolsController_ updateDevToolsForTabContents:contents
+                                        withProfile:browser_->profile()];
 
   // Update the bookmark bar.
   // Must do it after sidebar and devtools update, otherwise bookmark bar might
@@ -1478,7 +1479,7 @@
   [[self window] setViewsNeedDisplay:YES];
 }
 
-- (ThemeProvider*)themeProvider {
+- (ui::ThemeProvider*)themeProvider {
   return browser_->profile()->GetThemeProvider();
 }
 
@@ -1902,11 +1903,6 @@
     DCHECK(savedRegularWindow_);
     destWindow = [savedRegularWindow_ autorelease];
     savedRegularWindow_ = nil;
-
-    CGSWorkspaceID workspace;
-    if ([window cr_workspace:&workspace]) {
-      [destWindow cr_moveToWorkspace:workspace];
-    }
   }
   DCHECK(destWindow);
 
@@ -1957,7 +1953,15 @@
   [destWindow setTitle:[window title]];
 
   // The window needs to be onscreen before we can set its first responder.
+  // Ordering the window to the front can change the active Space (either to
+  // the window's old Space or to the application's assigned Space). To prevent
+  // this by temporarily change the collectionBehavior.
+  NSWindowCollectionBehavior behavior = [window collectionBehavior];
+  [destWindow setCollectionBehavior:
+      NSWindowCollectionBehaviorMoveToActiveSpace];
   [destWindow makeKeyAndOrderFront:self];
+  [destWindow setCollectionBehavior:behavior];
+
   [focusTracker restoreFocusInWindow:destWindow];
   [window orderOut:self];
 
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index 98f1718..c063dcc 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,18 +12,18 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
-#import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
 #import "chrome/browser/ui/cocoa/floating_bar_backing_view.h"
 #import "chrome/browser/ui/cocoa/framed_browser_window.h"
 #import "chrome/browser/ui/cocoa/fullscreen_controller.h"
-#import "chrome/browser/ui/cocoa/previewable_contents_controller.h"
-#import "chrome/browser/ui/cocoa/side_tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/common/pref_names.h"
 
 namespace {
@@ -63,11 +63,12 @@
   if (browser_ != BrowserList::GetLastActive())
     return;
 
-  if (!g_browser_process || !g_browser_process->local_state() ||
-      !browser_->ShouldSaveWindowPlacement())
+  if (!browser_->profile()->GetPrefs() ||
+      !browser_->ShouldSaveWindowPlacement()) {
     return;
+  }
 
-  [self saveWindowPositionToPrefs:g_browser_process->local_state()];
+  [self saveWindowPositionToPrefs:browser_->profile()->GetPrefs()];
 }
 
 - (void)saveWindowPositionToPrefs:(PrefService*)prefs {
@@ -395,13 +396,14 @@
 - (CGFloat)layoutInfoBarAtMinX:(CGFloat)minX
                           maxY:(CGFloat)maxY
                          width:(CGFloat)width {
-  NSView* infoBarView = [infoBarContainerController_ view];
-  NSRect infoBarFrame = [infoBarView frame];
-  infoBarFrame.origin.x = minX;
-  infoBarFrame.origin.y = maxY - NSHeight(infoBarFrame);
-  infoBarFrame.size.width = width;
-  [infoBarView setFrame:infoBarFrame];
-  maxY -= NSHeight(infoBarFrame);
+  NSView* containerView = [infoBarContainerController_ view];
+  NSRect containerFrame = [containerView frame];
+  maxY -= NSHeight(containerFrame);
+  maxY += [infoBarContainerController_ antiSpoofHeight];
+  containerFrame.origin.x = minX;
+  containerFrame.origin.y = maxY;
+  containerFrame.size.width = width;
+  [containerView setFrame:containerFrame];
   return maxY;
 }
 
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
index d16401f..8ca0617 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util_mac.h"
 #include "base/scoped_nsobject.h"
 #include "base/scoped_ptr.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -12,10 +11,11 @@
 #include "chrome/browser/ui/cocoa/browser_test_helper.h"
 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "chrome/browser/ui/cocoa/find_bar_bridge.h"
+#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/testing_profile.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @interface BrowserWindowController (JustForTesting)
 // Already defined in BWC.
@@ -85,14 +85,18 @@
   ASSERT_TRUE(prefs != NULL);
 
   // Check to make sure there is no existing pref for window placement.
-  ASSERT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) == NULL);
+  const DictionaryValue* browser_window_placement =
+      prefs->GetDictionary(prefs::kBrowserWindowPlacement);
+  ASSERT_TRUE(browser_window_placement);
+  EXPECT_TRUE(browser_window_placement->empty());
 
   // Ask the window to save its position, then check that a preference
-  // exists.  We're technically passing in a pointer to the user prefs
-  // and not the local state prefs, but a PrefService* is a
-  // PrefService*, and this is a unittest.
+  // exists.
   [controller_ saveWindowPositionToPrefs:prefs];
-  EXPECT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) != NULL);
+  browser_window_placement =
+      prefs->GetDictionary(prefs::kBrowserWindowPlacement);
+  ASSERT_TRUE(browser_window_placement);
+  EXPECT_FALSE(browser_window_placement->empty());
 }
 
 TEST_F(BrowserWindowControllerTest, TestFullScreenWindow) {
diff --git a/chrome/browser/ui/cocoa/browser_window_factory.mm b/chrome/browser/ui/cocoa/browser_window_factory.mm
index e7222e7..c74ca8a 100644
--- a/chrome/browser/ui/cocoa/browser_window_factory.mm
+++ b/chrome/browser/ui/cocoa/browser_window_factory.mm
@@ -5,7 +5,7 @@
 #include "base/basictypes.h"
 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/find_bar_bridge.h"
+#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 
diff --git a/chrome/browser/ui/cocoa/bubble_view.mm b/chrome/browser/ui/cocoa/bubble_view.mm
index a888ebc..0b92f39 100644
--- a/chrome/browser/ui/cocoa/bubble_view.mm
+++ b/chrome/browser/ui/cocoa/bubble_view.mm
@@ -74,7 +74,7 @@
   float bottomRightRadius =
       cornerFlags_ & kRoundedBottomRightCorner ? kBubbleCornerRadius : 0;
 
-  ThemeProvider* themeProvider =
+  ui::ThemeProvider* themeProvider =
       themeProvider_ ? [themeProvider_ themeProvider] :
                        [[self window] themeProvider];
 
diff --git a/chrome/browser/ui/cocoa/bug_report_window_controller.h b/chrome/browser/ui/cocoa/bug_report_window_controller.h
index 15aa707..c0c9384 100644
--- a/chrome/browser/ui/cocoa/bug_report_window_controller.h
+++ b/chrome/browser/ui/cocoa/bug_report_window_controller.h
@@ -69,6 +69,15 @@
   NSDictionary* bugTypeDictionary_;  // Strong
 }
 
+// Properties for bindings.
+@property(nonatomic, copy) NSString* bugDescription;
+@property(nonatomic) NSUInteger bugTypeIndex;
+@property(nonatomic, copy) NSString* pageTitle;
+@property(nonatomic, copy) NSString* pageURL;
+@property(nonatomic) BOOL sendScreenshot;
+@property(nonatomic) BOOL disableScreenshotCheckbox;
+@property(nonatomic, readonly) NSArray* bugTypeList;
+
 // Initialize with the contents of the tab to be reported as buggy / wrong.
 // If dialog is called without an open window, currentTab may be null; in
 // that case, a dialog is opened with options for reporting a bugs not
@@ -98,15 +107,6 @@
 - (BOOL)control:(NSControl*)control textView:(NSTextView*)textView
     doCommandBySelector:(SEL)commandSelector;
 
-// Properties for bindings.
-@property (nonatomic, copy) NSString* bugDescription;
-@property (nonatomic) NSUInteger bugTypeIndex;
-@property (nonatomic, copy) NSString* pageTitle;
-@property (nonatomic, copy) NSString* pageURL;
-@property (nonatomic) BOOL sendScreenshot;
-@property (nonatomic) BOOL disableScreenshotCheckbox;
-@property (nonatomic, readonly) NSArray* bugTypeList;
-
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_BUG_REPORT_WINDOW_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/bug_report_window_controller.mm b/chrome/browser/ui/cocoa/bug_report_window_controller.mm
index 5ea378a..b323379 100644
--- a/chrome/browser/ui/cocoa/bug_report_window_controller.mm
+++ b/chrome/browser/ui/cocoa/bug_report_window_controller.mm
@@ -1,18 +1,19 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/bug_report_window_controller.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/bug_report_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/ui/window_snapshot/window_snapshot.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @implementation BugReportWindowController
 
@@ -41,6 +42,9 @@
         l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_OTHER_PROBLEM),
         nil];
 
+    pngHeight_ = 0;
+    pngWidth_ = 0;
+
     if (currentTab_ != NULL) {
       // Get data from current tab, if one exists. This dialog could be called
       // from the main menu with no tab contents, so currentTab_ is not
@@ -62,18 +66,16 @@
       [self setPageURL:base::SysUTF8ToNSString(
           currentTab_->controller().GetActiveEntry()->url().spec())];
       [self setPageTitle:base::SysUTF16ToNSString(currentTab_->GetTitle())];
-      base::mac::GrabWindowSnapshot(
-          currentTab_->view()->GetTopLevelNativeWindow(), &pngData_,
-          &pngWidth_, &pngHeight_);
+      gfx::Rect pngRect = browser::GrabWindowSnapshot(
+          currentTab_->view()->GetTopLevelNativeWindow(), &pngData_);
+      pngWidth_ = pngRect.width();
+      pngHeight_ = pngRect.height();
     } else {
       // If no current tab exists, create a menu without the "broken page"
       // options, with page URL and title empty, and screenshot disabled.
       [self setSendScreenshot:NO];
       [self setDisableScreenshotCheckbox:YES];
     }
-
-    pngHeight_ = 0;
-    pngWidth_ = 0;
   }
   return self;
 }
@@ -110,7 +112,6 @@
   } else {
     BugReportUtil::SendReport(
         profile_,
-        base::SysNSStringToUTF8(pageTitle_),
         [self bugTypeFromIndex],
         base::SysNSStringToUTF8(pageURL_),
         base::SysNSStringToUTF8(bugDescription_),
diff --git a/chrome/browser/ui/cocoa/chrome_browser_window.mm b/chrome/browser/ui/cocoa/chrome_browser_window.mm
index abac221..cceeb14 100644
--- a/chrome/browser/ui/cocoa/chrome_browser_window.mm
+++ b/chrome/browser/ui/cocoa/chrome_browser_window.mm
@@ -28,7 +28,7 @@
     [self setOpaque:YES];
 }
 
-- (ThemeProvider*)themeProvider {
+- (ui::ThemeProvider*)themeProvider {
   id delegate = [self delegate];
   if (![delegate respondsToSelector:@selector(themeProvider)])
     return NULL;
diff --git a/chrome/browser/ui/cocoa/chrome_event_processing_window.mm b/chrome/browser/ui/cocoa/chrome_event_processing_window.mm
index be6591b..2275e2a 100644
--- a/chrome/browser/ui/cocoa/chrome_event_processing_window.mm
+++ b/chrome/browser/ui/cocoa/chrome_event_processing_window.mm
@@ -8,7 +8,7 @@
 #import "chrome/browser/renderer_host/render_widget_host_view_mac.h"
 #import "chrome/browser/ui/cocoa/browser_command_executor.h"
 #import "chrome/browser/ui/cocoa/browser_frame_view.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
 #include "chrome/browser/global_keyboard_shortcuts_mac.h"
 
 typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
diff --git a/chrome/browser/ui/cocoa/clear_browsing_data_controller.h b/chrome/browser/ui/cocoa/clear_browsing_data_controller.h
index 776841d..ac52b38 100644
--- a/chrome/browser/ui/cocoa/clear_browsing_data_controller.h
+++ b/chrome/browser/ui/cocoa/clear_browsing_data_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -46,9 +46,19 @@
   NSInteger timePeriod_;
 }
 
+// Properties for bindings
+@property(nonatomic) BOOL clearBrowsingHistory;
+@property(nonatomic) BOOL clearDownloadHistory;
+@property(nonatomic) BOOL emptyCache;
+@property(nonatomic) BOOL deleteCookies;
+@property(nonatomic) BOOL clearSavedPasswords;
+@property(nonatomic) BOOL clearFormData;
+@property(nonatomic) NSInteger timePeriod;
+@property(nonatomic) BOOL isClearing;
+
 // Show the clear browsing data window.  Do not use |-initWithProfile:|,
 // go through this instead so we don't end up with multiple instances.
-// This function does not block, so it can be used from DOMUI calls.
+// This function does not block, so it can be used from WebUI calls.
 + (void)showClearBrowsingDialogForProfile:(Profile*)profile;
 + (ClearBrowsingDataController*)controllerForProfile:(Profile*)profile;
 
@@ -62,23 +72,14 @@
 - (IBAction)cancel:(id)sender;
 - (IBAction)openFlashPlayerSettings:(id)sender;
 
-// Properties for bindings
-@property (nonatomic) BOOL clearBrowsingHistory;
-@property (nonatomic) BOOL clearDownloadHistory;
-@property (nonatomic) BOOL emptyCache;
-@property (nonatomic) BOOL deleteCookies;
-@property (nonatomic) BOOL clearSavedPasswords;
-@property (nonatomic) BOOL clearFormData;
-@property (nonatomic) NSInteger timePeriod;
-@property (nonatomic) BOOL isClearing;
-
 @end
 
 
 @interface ClearBrowsingDataController (ExposedForUnitTests)
+@property(readonly) int removeMask;
+
 // Create the controller with the given profile (which must not be NULL).
 - (id)initWithProfile:(Profile*)profile;
-@property (readonly) int removeMask;
 - (void)persistToPrefs;
 - (void)closeDialog;
 - (void)dataRemoverDidFinish;
diff --git a/chrome/browser/ui/cocoa/clear_browsing_data_controller.mm b/chrome/browser/ui/cocoa/clear_browsing_data_controller.mm
index 0ced443..9251763 100644
--- a/chrome/browser/ui/cocoa/clear_browsing_data_controller.mm
+++ b/chrome/browser/ui/cocoa/clear_browsing_data_controller.mm
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/lazy_instance.h"
 #include "base/mac/mac_util.h"
 #include "base/scoped_nsobject.h"
@@ -16,6 +15,7 @@
 #include "chrome/common/pref_names.h"
 #include "grit/locale_settings.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
 
 NSString* const kClearBrowsingDataControllerDidDelete =
     @"kClearBrowsingDataControllerDidDelete";
@@ -63,7 +63,7 @@
   if (![controller isWindowLoaded]) {
     // This function needs to return instead of blocking, to match the windows
     // api call.  It caused problems when launching the dialog from the
-    // DomUI history page.  See bug and code review for more details.
+    // WebUI history page.  See bug and code review for more details.
     // http://crbug.com/37976
     [controller performSelector:@selector(runModalDialog)
                      withObject:nil
diff --git a/chrome/browser/ui/cocoa/collected_cookies_mac.h b/chrome/browser/ui/cocoa/collected_cookies_mac.h
deleted file mode 100644
index 0329819..0000000
--- a/chrome/browser/ui/cocoa/collected_cookies_mac.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/cookies_tree_model.h"
-#include "chrome/browser/ui/cocoa/constrained_window_mac.h"
-#import "chrome/browser/ui/cocoa/cookie_tree_node.h"
-#include "chrome/common/notification_registrar.h"
-
-@class CollectedCookiesWindowController;
-@class VerticalGradientView;
-class TabContents;
-
-// The constrained window delegate reponsible for managing the collected
-// cookies dialog.
-class CollectedCookiesMac : public ConstrainedWindowMacDelegateCustomSheet,
-                            public NotificationObserver {
- public:
-  CollectedCookiesMac(NSWindow* parent, TabContents* tab_contents);
-
-  void OnSheetDidEnd(NSWindow* sheet);
-
-  // ConstrainedWindowMacDelegateCustomSheet implementation.
-  virtual void DeleteDelegate();
-
- private:
-  virtual ~CollectedCookiesMac();
-
-  // NotificationObserver implementation.
-  void Observe(NotificationType type,
-               const NotificationSource& source,
-               const NotificationDetails& details);
-
-  NotificationRegistrar registrar_;
-
-  ConstrainedWindow* window_;
-
-  TabContents* tab_contents_;
-
-  CollectedCookiesWindowController* sheet_controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(CollectedCookiesMac);
-};
-
-// Controller for the collected cookies dialog. This class stores an internal
-// copy of the CookiesTreeModel but with Cocoa-converted values (NSStrings and
-// NSImages instead of std::strings and SkBitmaps). Doing this allows us to use
-// bindings for the interface. Changes are pushed to this internal model via a
-// very thin bridge (see cookies_window_controller.h).
-@interface CollectedCookiesWindowController : NSWindowController
-                                              <NSOutlineViewDelegate,
-                                               NSWindowDelegate> {
- @private
-  // Platform-independent model.
-  scoped_ptr<CookiesTreeModel> allowedTreeModel_;
-  scoped_ptr<CookiesTreeModel> blockedTreeModel_;
-
-  // Cached array of icons.
-  scoped_nsobject<NSMutableArray> icons_;
-
-  // Our Cocoa copy of the model.
-  scoped_nsobject<CocoaCookieTreeNode> cocoaAllowedTreeModel_;
-  scoped_nsobject<CocoaCookieTreeNode> cocoaBlockedTreeModel_;
-
-  BOOL allowedCookiesButtonsEnabled_;
-  BOOL blockedCookiesButtonsEnabled_;
-
-  IBOutlet NSTreeController* allowedTreeController_;
-  IBOutlet NSTreeController* blockedTreeController_;
-  IBOutlet NSOutlineView* allowedOutlineView_;
-  IBOutlet NSOutlineView* blockedOutlineView_;
-  IBOutlet VerticalGradientView* infoBar_;
-  IBOutlet NSImageView* infoBarIcon_;
-  IBOutlet NSTextField* infoBarText_;
-  IBOutlet NSSplitView* splitView_;
-  IBOutlet NSScrollView* lowerScrollView_;
-  IBOutlet NSTextField* blockedCookiesText_;
-
-  scoped_nsobject<NSViewAnimation> animation_;
-
-  TabContents* tabContents_;  // weak
-
-  BOOL infoBarVisible_;
-}
-@property (readonly, nonatomic) NSTreeController* allowedTreeController;
-@property (readonly, nonatomic) NSTreeController* blockedTreeController;
-
-@property (assign, nonatomic) BOOL allowedCookiesButtonsEnabled;
-@property (assign, nonatomic) BOOL blockedCookiesButtonsEnabled;
-
-// Designated initializer. TabContents cannot be NULL.
-- (id)initWithTabContents:(TabContents*)tabContents;
-
-// Closes the sheet and ends the modal loop. This will also cleanup the memory.
-- (IBAction)closeSheet:(id)sender;
-
-- (IBAction)allowOrigin:(id)sender;
-- (IBAction)allowForSessionFromOrigin:(id)sender;
-- (IBAction)blockOrigin:(id)sender;
-
-// NSSplitView delegate methods:
-- (CGFloat)    splitView:(NSSplitView *)sender
-  constrainMinCoordinate:(CGFloat)proposedMin
-             ofSubviewAt:(NSInteger)offset;
-- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview;
-
-// Returns the cocoaAllowedTreeModel_ and cocoaBlockedTreeModel_.
-- (CocoaCookieTreeNode*)cocoaAllowedTreeModel;
-- (CocoaCookieTreeNode*)cocoaBlockedTreeModel;
-- (void)setCocoaAllowedTreeModel:(CocoaCookieTreeNode*)model;
-- (void)setCocoaBlockedTreeModel:(CocoaCookieTreeNode*)model;
-
-// Returns the allowedTreeModel_ and blockedTreeModel_.
-- (CookiesTreeModel*)allowedTreeModel;
-- (CookiesTreeModel*)blockedTreeModel;
-
-- (void)loadTreeModelFromTabContents;
-@end
diff --git a/chrome/browser/ui/cocoa/collected_cookies_mac.mm b/chrome/browser/ui/cocoa/collected_cookies_mac.mm
deleted file mode 100644
index ef19437..0000000
--- a/chrome/browser/ui/cocoa/collected_cookies_mac.mm
+++ /dev/null
@@ -1,500 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/collected_cookies_mac.h"
-
-#include <vector>
-
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#import "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/apple/ImageAndTextCell.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-namespace {
-// Colors for the infobar.
-const double kBannerGradientColorTop[3] =
-    {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
-const double kBannerGradientColorBottom[3] =
-    {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
-const double kBannerStrokeColor = 135.0 / 255.0;
-
-// Minimal height for the collected cookies dialog.
-const CGFloat kMinCollectedCookiesViewHeight = 116;
-} // namespace
-
-#pragma mark Bridge between the constrained window delegate and the sheet
-
-// The delegate used to forward the events from the sheet to the constrained
-// window delegate.
-@interface CollectedCookiesSheetBridge : NSObject {
-  CollectedCookiesMac* collectedCookies_;  // weak
-}
-- (id)initWithCollectedCookiesMac:(CollectedCookiesMac*)collectedCookies;
-- (void)sheetDidEnd:(NSWindow*)sheet
-         returnCode:(int)returnCode
-        contextInfo:(void*)contextInfo;
-@end
-
-@implementation CollectedCookiesSheetBridge
-- (id)initWithCollectedCookiesMac:(CollectedCookiesMac*)collectedCookies {
-  if ((self = [super init])) {
-    collectedCookies_ = collectedCookies;
-  }
-  return self;
-}
-
-- (void)sheetDidEnd:(NSWindow*)sheet
-         returnCode:(int)returnCode
-        contextInfo:(void*)contextInfo {
-  collectedCookies_->OnSheetDidEnd(sheet);
-}
-@end
-
-#pragma mark Constrained window delegate
-
-CollectedCookiesMac::CollectedCookiesMac(NSWindow* parent,
-                                         TabContents* tab_contents)
-    : ConstrainedWindowMacDelegateCustomSheet(
-        [[[CollectedCookiesSheetBridge alloc]
-            initWithCollectedCookiesMac:this] autorelease],
-        @selector(sheetDidEnd:returnCode:contextInfo:)),
-      tab_contents_(tab_contents) {
-  TabSpecificContentSettings* content_settings =
-      tab_contents->GetTabSpecificContentSettings();
-  registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN,
-                 Source<TabSpecificContentSettings>(content_settings));
-
-  sheet_controller_ = [[CollectedCookiesWindowController alloc]
-      initWithTabContents:tab_contents];
-
-  set_sheet([sheet_controller_ window]);
-
-  window_ = tab_contents->CreateConstrainedDialog(this);
-}
-
-CollectedCookiesMac::~CollectedCookiesMac() {
-  NSWindow* window = [sheet_controller_ window];
-  if (window_ && window && is_sheet_open()) {
-    window_ = NULL;
-    [NSApp endSheet:window];
-  }
-}
-
-void CollectedCookiesMac::DeleteDelegate() {
-  delete this;
-}
-
-void CollectedCookiesMac::Observe(NotificationType type,
-                                  const NotificationSource& source,
-                                  const NotificationDetails& details) {
-  DCHECK(type == NotificationType::COLLECTED_COOKIES_SHOWN);
-  DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(),
-            tab_contents_->GetTabSpecificContentSettings());
-  window_->CloseConstrainedWindow();
-}
-
-void CollectedCookiesMac::OnSheetDidEnd(NSWindow* sheet) {
-  [sheet orderOut:sheet_controller_];
-  if (window_)
-    window_->CloseConstrainedWindow();
-}
-
-#pragma mark Window Controller
-
-@interface CollectedCookiesWindowController(Private)
--(void)showInfoBarForDomain:(const string16&)domain
-                    setting:(ContentSetting)setting;
--(void)showInfoBarForMultipleDomainsAndSetting:(ContentSetting)setting;
--(void)animateInfoBar;
-@end
-
-@implementation CollectedCookiesWindowController
-
-@synthesize allowedCookiesButtonsEnabled =
-    allowedCookiesButtonsEnabled_;
-@synthesize blockedCookiesButtonsEnabled =
-    blockedCookiesButtonsEnabled_;
-
-@synthesize allowedTreeController = allowedTreeController_;
-@synthesize blockedTreeController = blockedTreeController_;
-
-- (id)initWithTabContents:(TabContents*)tabContents {
-  DCHECK(tabContents);
-  infoBarVisible_ = NO;
-  tabContents_ = tabContents;
-
-  NSString* nibpath =
-      [base::mac::MainAppBundle() pathForResource:@"CollectedCookies"
-                                          ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    [self loadTreeModelFromTabContents];
-
-    animation_.reset([[NSViewAnimation alloc] init]);
-    [animation_ setAnimationBlockingMode:NSAnimationNonblocking];
-  }
-  return self;
-}
-
-- (void)awakeFromNib {
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  NSImage* infoIcon = rb.GetNativeImageNamed(IDR_INFO);
-  DCHECK(infoIcon);
-  [infoBarIcon_ setImage:infoIcon];
-
-  // Initialize the banner gradient and stroke color.
-  NSColor* bannerStartingColor =
-      [NSColor colorWithCalibratedRed:kBannerGradientColorTop[0]
-                                green:kBannerGradientColorTop[1]
-                                 blue:kBannerGradientColorTop[2]
-                                alpha:1.0];
-  NSColor* bannerEndingColor =
-      [NSColor colorWithCalibratedRed:kBannerGradientColorBottom[0]
-                                green:kBannerGradientColorBottom[1]
-                                 blue:kBannerGradientColorBottom[2]
-                                alpha:1.0];
-  scoped_nsobject<NSGradient> bannerGradient(
-      [[NSGradient alloc] initWithStartingColor:bannerStartingColor
-                                    endingColor:bannerEndingColor]);
-  [infoBar_ setGradient:bannerGradient];
-
-  NSColor* bannerStrokeColor =
-      [NSColor colorWithCalibratedWhite:kBannerStrokeColor
-                                  alpha:1.0];
-  [infoBar_ setStrokeColor:bannerStrokeColor];
-
-  // Change the label of the blocked cookies part if necessary.
-  if (tabContents_->profile()->GetHostContentSettingsMap()->
-      BlockThirdPartyCookies()) {
-    [blockedCookiesText_ setStringValue:l10n_util::GetNSString(
-        IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED)];
-    CGFloat textDeltaY = [GTMUILocalizerAndLayoutTweaker
-        sizeToFitFixedWidthTextField:blockedCookiesText_];
-
-    // Shrink the upper custom view.
-    NSView* upperContentView = [[splitView_ subviews] objectAtIndex:0];
-    NSRect frame = [upperContentView frame];
-    [splitView_ setPosition:(frame.size.height - textDeltaY/2.0)
-           ofDividerAtIndex:0];
-
-    // Shrink the lower outline view.
-    frame = [lowerScrollView_ frame];
-    frame.size.height -= textDeltaY;
-    [lowerScrollView_ setFrame:frame];
-
-    // Move the label down so it actually fits.
-    frame = [blockedCookiesText_ frame];
-    frame.origin.y -= textDeltaY;
-    [blockedCookiesText_ setFrame:frame];
-  }
-}
-
-- (void)windowWillClose:(NSNotification*)notif {
-  [allowedOutlineView_ setDelegate:nil];
-  [blockedOutlineView_ setDelegate:nil];
-  [animation_ stopAnimation];
-  [self autorelease];
-}
-
-- (IBAction)closeSheet:(id)sender {
-  [NSApp endSheet:[self window]];
-}
-
-- (void)addException:(ContentSetting)setting
-   forTreeController:(NSTreeController*)controller {
-  NSArray* nodes = [controller selectedNodes];
-  BOOL multipleDomainsChanged = NO;
-  string16 lastDomain;
-  for (NSTreeNode* treeNode in nodes) {
-    CocoaCookieTreeNode* node = [treeNode representedObject];
-    CookieTreeNode* cookie = static_cast<CookieTreeNode*>([node treeNode]);
-    if (cookie->GetDetailedInfo().node_type !=
-        CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
-      continue;
-    }
-    CookieTreeOriginNode* origin_node =
-        static_cast<CookieTreeOriginNode*>(cookie);
-    origin_node->CreateContentException(
-        tabContents_->profile()->GetHostContentSettingsMap(),
-        setting);
-    if (!lastDomain.empty())
-      multipleDomainsChanged = YES;
-    lastDomain = origin_node->GetTitle();
-  }
-  if (multipleDomainsChanged)
-    [self showInfoBarForMultipleDomainsAndSetting:setting];
-  else
-    [self showInfoBarForDomain:lastDomain setting:setting];
-}
-
-- (IBAction)allowOrigin:(id)sender {
-  [self    addException:CONTENT_SETTING_ALLOW
-      forTreeController:blockedTreeController_];
-}
-
-- (IBAction)allowForSessionFromOrigin:(id)sender {
-  [self    addException:CONTENT_SETTING_SESSION_ONLY
-      forTreeController:blockedTreeController_];
-}
-
-- (IBAction)blockOrigin:(id)sender {
-  [self    addException:CONTENT_SETTING_BLOCK
-      forTreeController:allowedTreeController_];
-}
-
-- (CGFloat)    splitView:(NSSplitView *)sender
-  constrainMinCoordinate:(CGFloat)proposedMin
-             ofSubviewAt:(NSInteger)offset {
-  return proposedMin + kMinCollectedCookiesViewHeight;
-}
-- (CGFloat)    splitView:(NSSplitView *)sender
-  constrainMaxCoordinate:(CGFloat)proposedMax
-             ofSubviewAt:(NSInteger)offset {
-  return proposedMax - kMinCollectedCookiesViewHeight;
-}
-- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview {
-  return YES;
-}
-
-- (CocoaCookieTreeNode*)cocoaAllowedTreeModel {
-  return cocoaAllowedTreeModel_.get();
-}
-- (void)setCocoaAllowedTreeModel:(CocoaCookieTreeNode*)model {
-  cocoaAllowedTreeModel_.reset([model retain]);
-}
-
-- (CookiesTreeModel*)allowedTreeModel {
-  return allowedTreeModel_.get();
-}
-
-- (CocoaCookieTreeNode*)cocoaBlockedTreeModel {
-  return cocoaBlockedTreeModel_.get();
-}
-- (void)setCocoaBlockedTreeModel:(CocoaCookieTreeNode*)model {
-  cocoaBlockedTreeModel_.reset([model retain]);
-}
-
-- (CookiesTreeModel*)blockedTreeModel {
-  return blockedTreeModel_.get();
-}
-
-- (void)outlineView:(NSOutlineView*)outlineView
-    willDisplayCell:(id)cell
-     forTableColumn:(NSTableColumn*)tableColumn
-               item:(id)item {
-  CocoaCookieTreeNode* node = [item representedObject];
-  int index;
-  if (outlineView == allowedOutlineView_)
-    index = allowedTreeModel_->GetIconIndex([node treeNode]);
-  else
-    index = blockedTreeModel_->GetIconIndex([node treeNode]);
-  NSImage* icon = nil;
-  if (index >= 0)
-    icon = [icons_ objectAtIndex:index];
-  else
-    icon = [icons_ lastObject];
-  DCHECK([cell isKindOfClass:[ImageAndTextCell class]]);
-  [static_cast<ImageAndTextCell*>(cell) setImage:icon];
-}
-
-- (void)outlineViewSelectionDidChange:(NSNotification*)notif {
-  BOOL isAllowedOutlineView;
-  if ([notif object] == allowedOutlineView_) {
-    isAllowedOutlineView = YES;
-  } else if ([notif object] == blockedOutlineView_) {
-    isAllowedOutlineView = NO;
-  } else {
-    NOTREACHED();
-    return;
-  }
-  NSTreeController* controller =
-      isAllowedOutlineView ? allowedTreeController_ : blockedTreeController_;
-
-  NSArray* nodes = [controller selectedNodes];
-  for (NSTreeNode* treeNode in nodes) {
-    CocoaCookieTreeNode* node = [treeNode representedObject];
-    CookieTreeNode* cookie = static_cast<CookieTreeNode*>([node treeNode]);
-    if (cookie->GetDetailedInfo().node_type !=
-        CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
-      continue;
-    }
-   CookieTreeOriginNode* origin_node =
-       static_cast<CookieTreeOriginNode*>(cookie);
-   if (origin_node->CanCreateContentException()) {
-      if (isAllowedOutlineView) {
-        [self setAllowedCookiesButtonsEnabled:YES];
-      } else {
-        [self setBlockedCookiesButtonsEnabled:YES];
-      }
-      return;
-    }
-  }
-  if (isAllowedOutlineView) {
-    [self setAllowedCookiesButtonsEnabled:NO];
-  } else {
-    [self setBlockedCookiesButtonsEnabled:NO];
-  }
-}
-
-// Initializes the |allowedTreeModel_| and |blockedTreeModel_|, and builds
-// the |cocoaAllowedTreeModel_| and |cocoaBlockedTreeModel_|.
-- (void)loadTreeModelFromTabContents {
-  TabSpecificContentSettings* content_settings =
-      tabContents_->GetTabSpecificContentSettings();
-  allowedTreeModel_.reset(content_settings->GetAllowedCookiesTreeModel());
-  blockedTreeModel_.reset(content_settings->GetBlockedCookiesTreeModel());
-
-  // Convert the model's icons from Skia to Cocoa.
-  std::vector<SkBitmap> skiaIcons;
-  allowedTreeModel_->GetIcons(&skiaIcons);
-  icons_.reset([[NSMutableArray alloc] init]);
-  for (std::vector<SkBitmap>::iterator it = skiaIcons.begin();
-       it != skiaIcons.end(); ++it) {
-    [icons_ addObject:gfx::SkBitmapToNSImage(*it)];
-  }
-
-  // Default icon will be the last item in the array.
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  // TODO(rsesek): Rename this resource now that it's in multiple places.
-  [icons_ addObject:rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER)];
-
-  // Create the Cocoa model.
-  CookieTreeNode* root =
-      static_cast<CookieTreeNode*>(allowedTreeModel_->GetRoot());
-  scoped_nsobject<CocoaCookieTreeNode> model(
-      [[CocoaCookieTreeNode alloc] initWithNode:root]);
-  [self setCocoaAllowedTreeModel:model.get()];  // Takes ownership.
-  root = static_cast<CookieTreeNode*>(blockedTreeModel_->GetRoot());
-  model.reset(
-      [[CocoaCookieTreeNode alloc] initWithNode:root]);
-  [self setCocoaBlockedTreeModel:model.get()];  // Takes ownership.
-}
-
--(void)showInfoBarForMultipleDomainsAndSetting:(ContentSetting)setting {
-  NSString* label;
-  switch (setting) {
-    case CONTENT_SETTING_BLOCK:
-      label = l10n_util::GetNSString(
-          IDS_COLLECTED_COOKIES_MULTIPLE_BLOCK_RULES_CREATED);
-      break;
-
-    case CONTENT_SETTING_ALLOW:
-      label = l10n_util::GetNSString(
-          IDS_COLLECTED_COOKIES_MULTIPLE_ALLOW_RULES_CREATED);
-      break;
-
-    case CONTENT_SETTING_SESSION_ONLY:
-      label = l10n_util::GetNSString(
-          IDS_COLLECTED_COOKIES_MULTIPLE_SESSION_RULES_CREATED);
-      break;
-
-    default:
-      NOTREACHED();
-      label = [[[NSString alloc] init] autorelease];
-  }
-  [infoBarText_ setStringValue:label];
-  [self animateInfoBar];
-}
-
--(void)showInfoBarForDomain:(const string16&)domain
-                    setting:(ContentSetting)setting {
-  NSString* label;
-  switch (setting) {
-    case CONTENT_SETTING_BLOCK:
-      label = l10n_util::GetNSStringF(
-          IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED,
-          domain);
-      break;
-
-    case CONTENT_SETTING_ALLOW:
-      label = l10n_util::GetNSStringF(
-          IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED,
-          domain);
-      break;
-
-    case CONTENT_SETTING_SESSION_ONLY:
-      label = l10n_util::GetNSStringF(
-          IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED,
-          domain);
-      break;
-
-    default:
-      NOTREACHED();
-      label = [[[NSString alloc] init] autorelease];
-  }
-  [infoBarText_ setStringValue:label];
-  [self animateInfoBar];
-}
-
--(void)animateInfoBar {
-  if (infoBarVisible_)
-    return;
-
-  infoBarVisible_ = YES;
-
-  NSMutableArray* animations = [NSMutableArray arrayWithCapacity:3];
-
-  NSWindow* sheet = [self window];
-  NSRect sheetFrame = [sheet frame];
-  NSRect infoBarFrame = [infoBar_ frame];
-  NSRect splitViewFrame = [splitView_ frame];
-
-  // Calculate the end position of the info bar and set it to its start
-  // position.
-  infoBarFrame.origin.y = NSHeight(sheetFrame);
-  infoBarFrame.size.width = NSWidth(sheetFrame);
-  NSRect infoBarStartFrame = infoBarFrame;
-  infoBarStartFrame.origin.y += NSHeight(infoBarFrame);
-  infoBarStartFrame.size.height = 0.0;
-  [infoBar_ setFrame:infoBarStartFrame];
-  [[[self window] contentView] addSubview:infoBar_];
-
-  // Calculate the new position of the sheet.
-  sheetFrame.origin.y -= NSHeight(infoBarFrame);
-  sheetFrame.size.height += NSHeight(infoBarFrame);
-
-  // Slide the infobar in.
-  [animations addObject:
-      [NSDictionary dictionaryWithObjectsAndKeys:
-          infoBar_, NSViewAnimationTargetKey,
-          [NSValue valueWithRect:infoBarFrame],
-              NSViewAnimationEndFrameKey,
-          [NSValue valueWithRect:infoBarStartFrame],
-              NSViewAnimationStartFrameKey,
-          nil]];
-  // Make sure the split view ends up in the right position.
-  [animations addObject:
-      [NSDictionary dictionaryWithObjectsAndKeys:
-          splitView_, NSViewAnimationTargetKey,
-          [NSValue valueWithRect:splitViewFrame],
-              NSViewAnimationEndFrameKey,
-          nil]];
-
-  // Grow the sheet.
-  [animations addObject:
-      [NSDictionary dictionaryWithObjectsAndKeys:
-          sheet, NSViewAnimationTargetKey,
-          [NSValue valueWithRect:sheetFrame],
-              NSViewAnimationEndFrameKey,
-          nil]];
-  [animation_ setViewAnimations:animations];
-  // The default duration is 0.5s, which actually feels slow in here, so speed
-  // it up a bit.
-  [animation_ gtm_setDuration:0.2
-                    eventMask:NSLeftMouseUpMask];
-  [animation_ startAnimation];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/collected_cookies_mac_unittest.mm b/chrome/browser/ui/cocoa/collected_cookies_mac_unittest.mm
deleted file mode 100644
index a7bc6b7..0000000
--- a/chrome/browser/ui/cocoa/collected_cookies_mac_unittest.mm
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/ref_counted.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/site_instance.h"
-#include "chrome/browser/renderer_host/test/test_render_view_host.h"
-#include "chrome/browser/tab_contents/test_tab_contents.h"
-#import "chrome/browser/ui/cocoa/collected_cookies_mac.h"
-#include "chrome/test/testing_profile.h"
-
-namespace {
-
-class CollectedCookiesWindowControllerTest : public RenderViewHostTestHarness {
-};
-
-TEST_F(CollectedCookiesWindowControllerTest, Construction) {
-  BrowserThread ui_thread(BrowserThread::UI, MessageLoop::current());
-  // Create a test tab.  SiteInstance will be deleted when tabContents is
-  // deleted.
-  SiteInstance* instance =
-      SiteInstance::CreateSiteInstance(profile_.get());
-  TestTabContents* tabContents = new TestTabContents(profile_.get(),
-                                                      instance);
-  CollectedCookiesWindowController* controller =
-      [[CollectedCookiesWindowController alloc]
-          initWithTabContents:tabContents];
-
-  [controller release];
-
-  delete tabContents;
-}
-
-}  // namespace
-
diff --git a/chrome/browser/ui/cocoa/constrained_html_delegate_mac.mm b/chrome/browser/ui/cocoa/constrained_html_delegate_mac.mm
index 9e0344e..553f3e2 100644
--- a/chrome/browser/ui/cocoa/constrained_html_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/constrained_html_delegate_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -51,7 +51,7 @@
   HtmlDialogUIDelegate* html_delegate_;  // weak.
 
   // The constrained window that owns |this|. Saved here because it needs to be
-  // closed in response to the DOMUI OnDialogClose callback.
+  // closed in response to the WebUI OnDialogClose callback.
   ConstrainedWindow* constrained_window_;
 
   DISALLOW_COPY_AND_ASSIGN(ConstrainedHtmlDelegateMac);
diff --git a/chrome/browser/ui/cocoa/content_exceptions_window_controller.mm b/chrome/browser/ui/cocoa/content_exceptions_window_controller.mm
deleted file mode 100644
index eaced8e..0000000
--- a/chrome/browser/ui/cocoa/content_exceptions_window_controller.mm
+++ /dev/null
@@ -1,489 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/content_exceptions_window_controller.h"
-
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "app/table_model_observer.h"
-#include "base/command_line.h"
-#import "base/mac/mac_util.h"
-#import "base/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/content_exceptions_table_model.h"
-#include "chrome/browser/content_setting_combo_model.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_service.h"
-#include "grit/generated_resources.h"
-#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-@interface ContentExceptionsWindowController (Private)
-- (id)initWithType:(ContentSettingsType)settingsType
-       settingsMap:(HostContentSettingsMap*)settingsMap
-    otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap;
-- (void)updateRow:(NSInteger)row
-        withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry
-           forOtr:(BOOL)isOtr;
-- (void)adjustEditingButtons;
-- (void)modelDidChange;
-- (NSString*)titleForIndex:(size_t)index;
-@end
-
-////////////////////////////////////////////////////////////////////////////////
-// PatternFormatter
-
-// A simple formatter that accepts text that vaguely looks like a pattern.
-@interface PatternFormatter : NSFormatter
-@end
-
-@implementation PatternFormatter
-- (NSString*)stringForObjectValue:(id)object {
-  if (![object isKindOfClass:[NSString class]])
-    return nil;
-  return object;
-}
-
-- (BOOL)getObjectValue:(id*)object
-             forString:(NSString*)string
-      errorDescription:(NSString**)error {
-  if ([string length]) {
-      if (ContentSettingsPattern(
-          base::SysNSStringToUTF8(string)).IsValid()) {
-      *object = string;
-      return YES;
-    }
-  }
-  if (error)
-    *error = @"Invalid pattern";
-  return NO;
-}
-
-- (NSAttributedString*)attributedStringForObjectValue:(id)object
-                                withDefaultAttributes:(NSDictionary*)attribs {
-  return nil;
-}
-@end
-
-////////////////////////////////////////////////////////////////////////////////
-// UpdatingContentSettingsObserver
-
-// UpdatingContentSettingsObserver is a notification observer that tells a
-// window controller to update its data on every notification.
-class UpdatingContentSettingsObserver : public NotificationObserver {
- public:
-  UpdatingContentSettingsObserver(ContentExceptionsWindowController* controller)
-      : controller_(controller) {
-    // One would think one could register a TableModelObserver to be notified of
-    // changes to ContentExceptionsTableModel. One would be wrong: The table
-    // model only sends out changes that are made through the model, not for
-    // changes made directly to its backing HostContentSettings object (that
-    // happens e.g. if the user uses the cookie confirmation dialog). Hence,
-    // observe the CONTENT_SETTINGS_CHANGED notification directly.
-    registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
-                   NotificationService::AllSources());
-  }
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
- private:
-  NotificationRegistrar registrar_;
-  ContentExceptionsWindowController* controller_;
-};
-
-void UpdatingContentSettingsObserver::Observe(
-    NotificationType type,
-    const NotificationSource& source,
-    const NotificationDetails& details) {
-  [controller_ modelDidChange];
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static functions
-
-namespace  {
-
-NSString* GetWindowTitle(ContentSettingsType settingsType) {
-  switch (settingsType) {
-    case CONTENT_SETTINGS_TYPE_COOKIES:
-      return l10n_util::GetNSStringWithFixup(IDS_COOKIE_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_IMAGES:
-      return l10n_util::GetNSStringWithFixup(IDS_IMAGES_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
-      return l10n_util::GetNSStringWithFixup(IDS_JS_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_PLUGINS:
-      return l10n_util::GetNSStringWithFixup(IDS_PLUGINS_EXCEPTION_TITLE);
-    case CONTENT_SETTINGS_TYPE_POPUPS:
-      return l10n_util::GetNSStringWithFixup(IDS_POPUP_EXCEPTION_TITLE);
-    default:
-      NOTREACHED();
-  }
-  return @"";
-}
-
-const CGFloat kButtonBarHeight = 35.0;
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// ContentExceptionsWindowController implementation
-
-static ContentExceptionsWindowController*
-    g_exceptionWindows[CONTENT_SETTINGS_NUM_TYPES] = { nil };
-
-@implementation ContentExceptionsWindowController
-
-+ (id)controllerForType:(ContentSettingsType)settingsType
-            settingsMap:(HostContentSettingsMap*)settingsMap
-         otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap {
-  if (!g_exceptionWindows[settingsType]) {
-    g_exceptionWindows[settingsType] =
-        [[ContentExceptionsWindowController alloc]
-            initWithType:settingsType
-             settingsMap:settingsMap
-          otrSettingsMap:otrSettingsMap];
-  }
-  return g_exceptionWindows[settingsType];
-}
-
-- (id)initWithType:(ContentSettingsType)settingsType
-       settingsMap:(HostContentSettingsMap*)settingsMap
-    otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap {
-  NSString* nibpath =
-      [base::mac::MainAppBundle() pathForResource:@"ContentExceptionsWindow"
-                                          ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    settingsType_ = settingsType;
-    settingsMap_ = settingsMap;
-    otrSettingsMap_ = otrSettingsMap;
-    model_.reset(new ContentExceptionsTableModel(
-        settingsMap_, otrSettingsMap_, settingsType_));
-    popup_model_.reset(new ContentSettingComboModel(settingsType_));
-    otrAllowed_ = otrSettingsMap != NULL;
-    tableObserver_.reset(new UpdatingContentSettingsObserver(self));
-    updatesEnabled_ = YES;
-
-    // TODO(thakis): autoremember window rect.
-    // TODO(thakis): sorting support.
-  }
-  return self;
-}
-
-- (void)awakeFromNib {
-  DCHECK([self window]);
-  DCHECK_EQ(self, [[self window] delegate]);
-  DCHECK(tableView_);
-  DCHECK_EQ(self, [tableView_ dataSource]);
-  DCHECK_EQ(self, [tableView_ delegate]);
-
-  [[self window] setTitle:GetWindowTitle(settingsType_)];
-
-  CGFloat minWidth = [[addButton_ superview] bounds].size.width +
-                     [[doneButton_ superview] bounds].size.width;
-  [self setMinWidth:minWidth];
-
-  [self adjustEditingButtons];
-
-  // Initialize menu for the data cell in the "action" column.
-  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"exceptionMenu"]);
-  for (int i = 0; i < popup_model_->GetItemCount(); ++i) {
-    NSString* title =
-        l10n_util::FixUpWindowsStyleLabel(popup_model_->GetItemAt(i));
-    scoped_nsobject<NSMenuItem> allowItem(
-        [[NSMenuItem alloc] initWithTitle:title action:NULL keyEquivalent:@""]);
-    [allowItem.get() setTag:popup_model_->SettingForIndex(i)];
-    [menu.get() addItem:allowItem.get()];
-  }
-  NSCell* menuCell =
-      [[tableView_ tableColumnWithIdentifier:@"action"] dataCell];
-  [menuCell setMenu:menu.get()];
-
-  NSCell* patternCell =
-      [[tableView_ tableColumnWithIdentifier:@"pattern"] dataCell];
-  [patternCell setFormatter:[[[PatternFormatter alloc] init] autorelease]];
-
-  if (!otrAllowed_) {
-    [tableView_
-        removeTableColumn:[tableView_ tableColumnWithIdentifier:@"otr"]];
-  }
-}
-
-- (void)setMinWidth:(CGFloat)minWidth {
-  NSWindow* window = [self window];
-  [window setMinSize:NSMakeSize(minWidth, [window minSize].height)];
-  if ([window frame].size.width < minWidth) {
-    NSRect frame = [window frame];
-    frame.size.width = minWidth;
-    [window setFrame:frame display:NO];
-  }
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
-  // Without this, some of the unit tests fail on 10.6:
-  [tableView_ setDataSource:nil];
-
-  g_exceptionWindows[settingsType_] = nil;
-  [self autorelease];
-}
-
-- (BOOL)editingNewException {
-  return newException_.get() != NULL;
-}
-
-// Let esc cancel editing if the user is currently editing a pattern. Else, let
-// esc close the window.
-- (void)cancel:(id)sender {
-  if ([tableView_ currentEditor] != nil) {
-    [tableView_ abortEditing];
-    [[self window] makeFirstResponder:tableView_];  // Re-gain focus.
-
-    if ([tableView_ selectedRow] == model_->RowCount()) {
-      // Cancel addition of new row.
-      [self removeException:self];
-    }
-  } else {
-    [self closeSheet:self];
-  }
-}
-
-- (void)keyDown:(NSEvent*)event {
-  NSString* chars = [event charactersIgnoringModifiers];
-  if ([chars length] == 1) {
-    switch ([chars characterAtIndex:0]) {
-      case NSDeleteCharacter:
-      case NSDeleteFunctionKey:
-        // Delete deletes.
-        if ([[tableView_ selectedRowIndexes] count] > 0)
-          [self removeException:self];
-        return;
-      case NSCarriageReturnCharacter:
-      case NSEnterCharacter:
-        // Return enters rename mode.
-        if ([[tableView_ selectedRowIndexes] count] == 1) {
-          [tableView_ editColumn:0
-                             row:[[tableView_ selectedRowIndexes] lastIndex]
-                       withEvent:nil
-                          select:YES];
-        }
-        return;
-    }
-  }
-  [super keyDown:event];
-}
-
-- (void)attachSheetTo:(NSWindow*)window {
-  [NSApp beginSheet:[self window]
-     modalForWindow:window
-      modalDelegate:self
-     didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
-        contextInfo:nil];
-}
-
-- (void)sheetDidEnd:(NSWindow*)sheet
-         returnCode:(NSInteger)returnCode
-        contextInfo:(void*)context {
-  [sheet close];
-  [sheet orderOut:self];
-}
-
-- (IBAction)addException:(id)sender {
-  if (newException_.get()) {
-    // The invariant is that |newException_| is non-NULL exactly if the pattern
-    // of a new exception is currently being edited - so there's nothing to do
-    // in that case.
-    return;
-  }
-  newException_.reset(new HostContentSettingsMap::PatternSettingPair);
-  newException_->first = ContentSettingsPattern(
-      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_SAMPLE_PATTERN));
-  newException_->second = CONTENT_SETTING_BLOCK;
-  [tableView_ reloadData];
-
-  [self adjustEditingButtons];
-  int index = model_->RowCount();
-  NSIndexSet* selectedSet = [NSIndexSet indexSetWithIndex:index];
-  [tableView_ selectRowIndexes:selectedSet byExtendingSelection:NO];
-  [tableView_ editColumn:0 row:index withEvent:nil select:YES];
-}
-
-- (IBAction)removeException:(id)sender {
-  updatesEnabled_ = NO;
-  NSIndexSet* selection = [tableView_ selectedRowIndexes];
-  [tableView_ deselectAll:self];  // Else we'll get a -setObjectValue: later.
-  DCHECK_GT([selection count], 0U);
-  NSUInteger index = [selection lastIndex];
-  while (index != NSNotFound) {
-    if (index == static_cast<NSUInteger>(model_->RowCount()))
-      newException_.reset();
-    else
-      model_->RemoveException(index);
-    index = [selection indexLessThanIndex:index];
-  }
-  updatesEnabled_ = YES;
-  [self modelDidChange];
-}
-
-- (IBAction)removeAllExceptions:(id)sender {
-  updatesEnabled_ = NO;
-  [tableView_ deselectAll:self];  // Else we'll get a -setObjectValue: later.
-  newException_.reset();
-  model_->RemoveAll();
-  updatesEnabled_ = YES;
-  [self modelDidChange];
-}
-
-- (IBAction)closeSheet:(id)sender {
-  [NSApp endSheet:[self window]];
-}
-
-// Table View Data Source -----------------------------------------------------
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView*)table {
-  return model_->RowCount() + (newException_.get() ? 1 : 0);
-}
-
-- (id)tableView:(NSTableView*)tv
-    objectValueForTableColumn:(NSTableColumn*)tableColumn
-                          row:(NSInteger)row {
-  const HostContentSettingsMap::PatternSettingPair* entry;
-  int isOtr;
-  if (newException_.get() && row >= model_->RowCount()) {
-    entry = newException_.get();
-    isOtr = 0;
-  } else {
-    entry = &model_->entry_at(row);
-    isOtr = model_->entry_is_off_the_record(row) ? 1 : 0;
-  }
-
-  NSObject* result = nil;
-  NSString* identifier = [tableColumn identifier];
-  if ([identifier isEqualToString:@"pattern"]) {
-    result = base::SysUTF8ToNSString(entry->first.AsString());
-  } else if ([identifier isEqualToString:@"action"]) {
-    result =
-        [NSNumber numberWithInt:popup_model_->IndexForSetting(entry->second)];
-  } else if ([identifier isEqualToString:@"otr"]) {
-    result = [NSNumber numberWithInt:isOtr];
-  } else {
-    NOTREACHED();
-  }
-  return result;
-}
-
-// Updates exception at |row| to contain the data in |entry|.
-- (void)updateRow:(NSInteger)row
-        withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry
-           forOtr:(BOOL)isOtr {
-  // TODO(thakis): This apparently moves an edited row to the back of the list.
-  // It's what windows and linux do, but it's kinda sucky. Fix.
-  // http://crbug.com/36904
-  updatesEnabled_ = NO;
-  if (row < model_->RowCount())
-    model_->RemoveException(row);
-  model_->AddException(entry.first, entry.second, isOtr);
-  updatesEnabled_ = YES;
-  [self modelDidChange];
-
-  // For now, at least re-select the edited element.
-  int newIndex = model_->IndexOfExceptionByPattern(entry.first, isOtr);
-  DCHECK(newIndex != -1);
-  [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex]
-          byExtendingSelection:NO];
-}
-
-- (void) tableView:(NSTableView*)tv
-    setObjectValue:(id)object
-    forTableColumn:(NSTableColumn*)tableColumn
-               row:(NSInteger)row {
-  // -remove: and -removeAll: both call |tableView_|'s -deselectAll:, which
-  // calls this method if a cell is currently being edited. Do not commit edits
-  // of rows that are about to be deleted.
-  if (!updatesEnabled_) {
-    // If this method gets called, the pattern filed of the new exception can no
-    // longer be being edited. Reset |newException_| to keep the invariant true.
-    newException_.reset();
-    return;
-  }
-
-  // Get model object.
-  bool isNewRow = newException_.get() && row >= model_->RowCount();
-  HostContentSettingsMap::PatternSettingPair originalEntry =
-      isNewRow ? *newException_ : model_->entry_at(row);
-  HostContentSettingsMap::PatternSettingPair entry = originalEntry;
-  bool isOtr =
-      isNewRow ? 0 : model_->entry_is_off_the_record(row);
-  bool wasOtr = isOtr;
-
-  // Modify it.
-  NSString* identifier = [tableColumn identifier];
-  if ([identifier isEqualToString:@"pattern"]) {
-    entry.first = ContentSettingsPattern(base::SysNSStringToUTF8(object));
-  }
-  if ([identifier isEqualToString:@"action"]) {
-    int index = [object intValue];
-    entry.second = popup_model_->SettingForIndex(index);
-  }
-  if ([identifier isEqualToString:@"otr"]) {
-    isOtr = [object intValue] != 0;
-  }
-
-  // Commit modification, if any.
-  if (isNewRow) {
-    newException_.reset();
-    if (![identifier isEqualToString:@"pattern"]) {
-      [tableView_ reloadData];
-      [self adjustEditingButtons];
-      return;  // Commit new rows only when the pattern has been set.
-    }
-    int newIndex = model_->IndexOfExceptionByPattern(entry.first, false);
-    if (newIndex != -1) {
-      // The new pattern was already in the table. Focus existing row instead of
-      // overwriting it with a new one.
-      [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex]
-              byExtendingSelection:NO];
-      [tableView_ reloadData];
-      [self adjustEditingButtons];
-      return;
-    }
-  }
-  if (entry != originalEntry || wasOtr != isOtr || isNewRow)
-    [self updateRow:row withEntry:entry forOtr:isOtr];
-}
-
-
-// Table View Delegate --------------------------------------------------------
-
-// When the selection in the table view changes, we need to adjust buttons.
-- (void)tableViewSelectionDidChange:(NSNotification*)notification {
-  [self adjustEditingButtons];
-}
-
-// Private --------------------------------------------------------------------
-
-// This method appropriately sets the enabled states on the table's editing
-// buttons.
-- (void)adjustEditingButtons {
-  NSIndexSet* selection = [tableView_ selectedRowIndexes];
-  [removeButton_ setEnabled:([selection count] > 0)];
-  [removeAllButton_ setEnabled:([tableView_ numberOfRows] > 0)];
-}
-
-- (void)modelDidChange {
-  // Some calls on |model_|, e.g. RemoveException(), change something on the
-  // backing content settings map object (which sends a notification) and then
-  // change more stuff in |model_|. If |model_| is deleted when the notification
-  // is sent, this second access causes a segmentation violation. Hence, disable
-  // resetting |model_| while updates can be in progress.
-  if (!updatesEnabled_)
-    return;
-
-  // The model caches its data, meaning we need to recreate it on every change.
-  model_.reset(new ContentExceptionsTableModel(
-      settingsMap_, otrSettingsMap_, settingsType_));
-
-  [tableView_ reloadData];
-  [self adjustEditingButtons];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/content_exceptions_window_controller_unittest.mm b/chrome/browser/ui/cocoa/content_exceptions_window_controller_unittest.mm
deleted file mode 100644
index d42e171..0000000
--- a/chrome/browser/ui/cocoa/content_exceptions_window_controller_unittest.mm
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/content_exceptions_window_controller.h"
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-void ProcessEvents() {
-  for (;;) {
-    base::mac::ScopedNSAutoreleasePool pool;
-    NSEvent* next_event = [NSApp nextEventMatchingMask:NSAnyEventMask
-                                             untilDate:nil
-                                                inMode:NSDefaultRunLoopMode
-                                               dequeue:YES];
-    if (!next_event)
-      break;
-    [NSApp sendEvent:next_event];
-  }
-}
-
-void SendKeyEvents(NSString* characters) {
-  for (NSUInteger i = 0; i < [characters length]; ++i) {
-    unichar character = [characters characterAtIndex:i];
-    NSString* charString = [NSString stringWithCharacters:&character length:1];
-    NSEvent* event = [NSEvent keyEventWithType:NSKeyDown
-                                      location:NSZeroPoint
-                                 modifierFlags:0
-                                     timestamp:0.0
-                                  windowNumber:0
-                                       context:nil
-                                    characters:charString
-                   charactersIgnoringModifiers:charString
-                                     isARepeat:NO
-                                       keyCode:0];
-    [NSApp sendEvent:event];
-  }
-}
-
-class ContentExceptionsWindowControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    TestingProfile* profile = browser_helper_.profile();
-    settingsMap_ = new HostContentSettingsMap(profile);
-  }
-
-  ContentExceptionsWindowController* GetController(ContentSettingsType type) {
-    id controller = [ContentExceptionsWindowController
-        controllerForType:type
-              settingsMap:settingsMap_.get()
-           otrSettingsMap:NULL];
-    [controller showWindow:nil];
-    return controller;
-  }
-
-  void ClickAdd(ContentExceptionsWindowController* controller) {
-    [controller addException:nil];
-    ProcessEvents();
-  }
-
-  void ClickRemove(ContentExceptionsWindowController* controller) {
-    [controller removeException:nil];
-    ProcessEvents();
-  }
-
-  void ClickRemoveAll(ContentExceptionsWindowController* controller) {
-    [controller removeAllExceptions:nil];
-    ProcessEvents();
-  }
-
-  void EnterText(NSString* str) {
-    SendKeyEvents(str);
-    ProcessEvents();
-  }
-
-  void HitEscape(ContentExceptionsWindowController* controller) {
-    [controller cancel:nil];
-    ProcessEvents();
-  }
-
- protected:
-  BrowserTestHelper browser_helper_;
-  scoped_refptr<HostContentSettingsMap> settingsMap_;
-};
-
-TEST_F(ContentExceptionsWindowControllerTest, Construction) {
-  ContentExceptionsWindowController* controller =
-      [ContentExceptionsWindowController
-          controllerForType:CONTENT_SETTINGS_TYPE_PLUGINS
-                settingsMap:settingsMap_.get()
-             otrSettingsMap:NULL];
-  [controller showWindow:nil];
-  [controller close];  // Should autorelease.
-}
-
-// Regression test for http://crbug.com/37137
-TEST_F(ContentExceptionsWindowControllerTest, AddRemove) {
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
-
-  HostContentSettingsMap::SettingsForOneType settings;
-
-  ClickAdd(controller);
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(0u, settings.size());
-
-  ClickRemove(controller);
-
-  EXPECT_FALSE([controller editingNewException]);
-  [controller close];
-
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(0u, settings.size());
-}
-
-// Regression test for http://crbug.com/37137
-TEST_F(ContentExceptionsWindowControllerTest, AddRemoveAll) {
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
-
-  ClickAdd(controller);
-  ClickRemoveAll(controller);
-
-  EXPECT_FALSE([controller editingNewException]);
-  [controller close];
-
-  HostContentSettingsMap::SettingsForOneType settings;
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(0u, settings.size());
-}
-
-TEST_F(ContentExceptionsWindowControllerTest, Add) {
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
-
-  ClickAdd(controller);
-  EnterText(@"addedhost\n");
-
-  EXPECT_FALSE([controller editingNewException]);
-  [controller close];
-
-  HostContentSettingsMap::SettingsForOneType settings;
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(1u, settings.size());
-  EXPECT_EQ(ContentSettingsPattern("addedhost"), settings[0].first);
-}
-
-TEST_F(ContentExceptionsWindowControllerTest, AddEscDoesNotAdd) {
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
-
-  ClickAdd(controller);
-  EnterText(@"addedhost");  // but do not press enter
-  HitEscape(controller);
-
-  HostContentSettingsMap::SettingsForOneType settings;
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(0u, settings.size());
-  EXPECT_FALSE([controller editingNewException]);
-
-  [controller close];
-}
-
-// Regression test for http://crbug.com/37208
-TEST_F(ContentExceptionsWindowControllerTest, AddEditAddAdd) {
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
-
-  ClickAdd(controller);
-  EnterText(@"testtesttest");  // but do not press enter
-  ClickAdd(controller);
-  ClickAdd(controller);
-
-  EXPECT_TRUE([controller editingNewException]);
-  [controller close];
-
-  HostContentSettingsMap::SettingsForOneType settings;
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(0u, settings.size());
-}
-
-TEST_F(ContentExceptionsWindowControllerTest, AddExistingEditAdd) {
-  settingsMap_->SetContentSetting(ContentSettingsPattern("myhost"),
-                                  CONTENT_SETTINGS_TYPE_PLUGINS,
-                                  "",
-                                  CONTENT_SETTING_BLOCK);
-
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
-
-  ClickAdd(controller);
-  EnterText(@"myhost");  // but do not press enter
-  ClickAdd(controller);
-
-  EXPECT_TRUE([controller editingNewException]);
-  [controller close];
-
-
-  HostContentSettingsMap::SettingsForOneType settings;
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(1u, settings.size());
-}
-
-TEST_F(ContentExceptionsWindowControllerTest, AddExistingDoesNotOverwrite) {
-  settingsMap_->SetContentSetting(ContentSettingsPattern("myhost"),
-                                  CONTENT_SETTINGS_TYPE_COOKIES,
-                                  "",
-                                  CONTENT_SETTING_SESSION_ONLY);
-
-  ContentExceptionsWindowController* controller =
-      GetController(CONTENT_SETTINGS_TYPE_COOKIES);
-
-  ClickAdd(controller);
-  EnterText(@"myhost\n");
-
-  EXPECT_FALSE([controller editingNewException]);
-  [controller close];
-
-  HostContentSettingsMap::SettingsForOneType settings;
-  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES,
-                                      "",
-                                      &settings);
-  EXPECT_EQ(1u, settings.size());
-  EXPECT_EQ(CONTENT_SETTING_SESSION_ONLY, settings[0].second);
-}
-
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/content_setting_bubble_cocoa.mm b/chrome/browser/ui/cocoa/content_setting_bubble_cocoa.mm
deleted file mode 100644
index d59a05e..0000000
--- a/chrome/browser/ui/cocoa/content_setting_bubble_cocoa.mm
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/content_setting_bubble_cocoa.h"
-
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/sys_string_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/blocked_content_container.h"
-#include "chrome/browser/content_setting_bubble_model.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/plugin_updater.h"
-#import "chrome/browser/ui/cocoa/content_settings_dialog_controller.h"
-#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
-#import "chrome/browser/ui/cocoa/info_bubble_view.h"
-#import "chrome/browser/ui/cocoa/l10n_util.h"
-#include "chrome/common/chrome_switches.h"
-#include "grit/generated_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#include "webkit/glue/plugins/plugin_list.h"
-
-namespace {
-
-// Must match the tag of the unblock radio button in the xib files.
-const int kAllowTag = 1;
-
-// Must match the tag of the block radio button in the xib files.
-const int kBlockTag = 2;
-
-// Height of one link in the popup list.
-const int kLinkHeight = 16;
-
-// Space between two popup links.
-const int kLinkPadding = 4;
-
-// Space taken in total by one popup link.
-const int kLinkLineHeight = kLinkHeight + kLinkPadding;
-
-// Space between popup list and surrounding UI elements.
-const int kLinkOuterPadding = 8;
-
-// Height of each of the labels in the geolocation bubble.
-const int kGeoLabelHeight = 14;
-
-// Height of the "Clear" button in the geolocation bubble.
-const int kGeoClearButtonHeight = 17;
-
-// Padding between radio buttons and "Load all plugins" button
-// in the plugin bubble.
-const int kLoadAllPluginsButtonVerticalPadding = 8;
-
-// General padding between elements in the geolocation bubble.
-const int kGeoPadding = 8;
-
-// Padding between host names in the geolocation bubble.
-const int kGeoHostPadding = 4;
-
-// Minimal padding between "Manage" and "Done" buttons.
-const int kManageDonePadding = 8;
-
-void SetControlSize(NSControl* control, NSControlSize controlSize) {
-  CGFloat fontSize = [NSFont systemFontSizeForControlSize:controlSize];
-  NSCell* cell = [control cell];
-  NSFont* font = [NSFont fontWithName:[[cell font] fontName] size:fontSize];
-  [cell setFont:font];
-  [cell setControlSize:controlSize];
-}
-
-// Returns an autoreleased NSTextField that is configured to look like a Label
-// looks in Interface Builder.
-NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
-  NSTextField* label = [[NSTextField alloc] initWithFrame:frame];
-  [label setStringValue:text];
-  [label setSelectable:NO];
-  [label setBezeled:NO];
-  return [label autorelease];
-}
-
-}  // namespace
-
-@interface ContentSettingBubbleController(Private)
-- (id)initWithModel:(ContentSettingBubbleModel*)settingsBubbleModel
-       parentWindow:(NSWindow*)parentWindow
-         anchoredAt:(NSPoint)anchoredAt;
-- (NSButton*)hyperlinkButtonWithFrame:(NSRect)frame
-                                title:(NSString*)title
-                                 icon:(NSImage*)icon
-                       referenceFrame:(NSRect)referenceFrame;
-- (void)initializeBlockedPluginsList;
-- (void)initializeTitle;
-- (void)initializeRadioGroup;
-- (void)initializePopupList;
-- (void)initializeGeoLists;
-- (void)sizeToFitLoadPluginsButton;
-- (void)sizeToFitManageDoneButtons;
-- (void)removeInfoButton;
-- (void)popupLinkClicked:(id)sender;
-- (void)clearGeolocationForCurrentHost:(id)sender;
-@end
-
-@implementation ContentSettingBubbleController
-
-+ (ContentSettingBubbleController*)
-    showForModel:(ContentSettingBubbleModel*)contentSettingBubbleModel
-    parentWindow:(NSWindow*)parentWindow
-      anchoredAt:(NSPoint)anchor {
-  // Autoreleases itself on bubble close.
-  return [[ContentSettingBubbleController alloc]
-             initWithModel:contentSettingBubbleModel
-              parentWindow:parentWindow
-                anchoredAt:anchor];
-}
-
-- (id)initWithModel:(ContentSettingBubbleModel*)contentSettingBubbleModel
-       parentWindow:(NSWindow*)parentWindow
-         anchoredAt:(NSPoint)anchoredAt {
-  // This method takes ownership of |contentSettingBubbleModel| in all cases.
-  scoped_ptr<ContentSettingBubbleModel> model(contentSettingBubbleModel);
-  DCHECK(model.get());
-
-  NSString* const nibPaths[] = {
-    @"ContentBlockedCookies",
-    @"ContentBlockedImages",
-    @"ContentBlockedJavaScript",
-    @"ContentBlockedPlugins",
-    @"ContentBlockedPopups",
-    @"ContentBubbleGeolocation",
-    @"",  // Notifications do not have a bubble.
-  };
-  COMPILE_ASSERT(arraysize(nibPaths) == CONTENT_SETTINGS_NUM_TYPES,
-                 nibPaths_requires_an_entry_for_every_setting_type);
-  const int settingsType = model->content_type();
-  // Nofifications do not have a bubble.
-  CHECK_NE(settingsType, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
-  DCHECK_LT(settingsType, CONTENT_SETTINGS_NUM_TYPES);
-  if ((self = [super initWithWindowNibPath:nibPaths[settingsType]
-                              parentWindow:parentWindow
-                                anchoredAt:anchoredAt])) {
-    contentSettingBubbleModel_.reset(model.release());
-    [self showWindow:nil];
-  }
-  return self;
-}
-
-- (void)initializeTitle {
-  if (!titleLabel_)
-    return;
-
-  NSString* label = base::SysUTF8ToNSString(
-      contentSettingBubbleModel_->bubble_content().title);
-  [titleLabel_ setStringValue:label];
-
-  // Layout title post-localization.
-  CGFloat deltaY = [GTMUILocalizerAndLayoutTweaker
-      sizeToFitFixedWidthTextField:titleLabel_];
-  NSRect windowFrame = [[self window] frame];
-  windowFrame.size.height += deltaY;
-  [[self window] setFrame:windowFrame display:NO];
-  NSRect titleFrame = [titleLabel_ frame];
-  titleFrame.origin.y -= deltaY;
-  [titleLabel_ setFrame:titleFrame];
-}
-
-- (void)initializeRadioGroup {
-  // Configure the radio group. For now, only deal with the
-  // strictly needed case of group containing 2 radio buttons.
-  const ContentSettingBubbleModel::RadioGroup& radio_group =
-      contentSettingBubbleModel_->bubble_content().radio_group;
-
-  // Select appropriate radio button.
-  [allowBlockRadioGroup_ selectCellWithTag:
-      radio_group.default_item == 0 ? kAllowTag : kBlockTag];
-
-  const ContentSettingBubbleModel::RadioItems& radio_items =
-      radio_group.radio_items;
-  DCHECK_EQ(2u, radio_items.size()) << "Only 2 radio items per group supported";
-  // Set radio group labels from model.
-  NSCell* radioCell = [allowBlockRadioGroup_ cellWithTag:kAllowTag];
-  [radioCell setTitle:base::SysUTF8ToNSString(radio_items[0])];
-
-  radioCell = [allowBlockRadioGroup_ cellWithTag:kBlockTag];
-  [radioCell setTitle:base::SysUTF8ToNSString(radio_items[1])];
-
-  // Layout radio group labels post-localization.
-  [GTMUILocalizerAndLayoutTweaker
-      wrapRadioGroupForWidth:allowBlockRadioGroup_];
-  CGFloat radioDeltaY = [GTMUILocalizerAndLayoutTweaker
-      sizeToFitView:allowBlockRadioGroup_].height;
-  NSRect windowFrame = [[self window] frame];
-  windowFrame.size.height += radioDeltaY;
-  [[self window] setFrame:windowFrame display:NO];
-}
-
-- (NSButton*)hyperlinkButtonWithFrame:(NSRect)frame
-                                title:(NSString*)title
-                                 icon:(NSImage*)icon
-                       referenceFrame:(NSRect)referenceFrame {
-  scoped_nsobject<HyperlinkButtonCell> cell([[HyperlinkButtonCell alloc]
-      initTextCell:title]);
-  [cell.get() setAlignment:NSNaturalTextAlignment];
-  if (icon) {
-    [cell.get() setImagePosition:NSImageLeft];
-    [cell.get() setImage:icon];
-  } else {
-    [cell.get() setImagePosition:NSNoImage];
-  }
-  [cell.get() setControlSize:NSSmallControlSize];
-
-  NSButton* button = [[[NSButton alloc] initWithFrame:frame] autorelease];
-  // Cell must be set immediately after construction.
-  [button setCell:cell.get()];
-
-  // If the link text is too long, clamp it.
-  [button sizeToFit];
-  int maxWidth = NSWidth([[self bubble] frame]) - 2 * NSMinX(referenceFrame);
-  NSRect buttonFrame = [button frame];
-  if (NSWidth(buttonFrame) > maxWidth) {
-    buttonFrame.size.width = maxWidth;
-    [button setFrame:buttonFrame];
-  }
-
-  [button setTarget:self];
-  [button setAction:@selector(popupLinkClicked:)];
-  return button;
-}
-
-- (void)initializeBlockedPluginsList {
-  NSMutableArray* pluginArray = [NSMutableArray array];
-  const std::set<std::string>& plugins =
-      contentSettingBubbleModel_->bubble_content().resource_identifiers;
-  if (plugins.empty()) {
-    int delta = NSMinY([titleLabel_ frame]) -
-                NSMinY([blockedResourcesField_ frame]);
-    [blockedResourcesField_ removeFromSuperview];
-    NSRect frame = [[self window] frame];
-    frame.size.height -= delta;
-    [[self window] setFrame:frame display:NO];
-  } else {
-    for (std::set<std::string>::iterator it = plugins.begin();
-         it != plugins.end(); ++it) {
-      NSString* name = SysUTF16ToNSString(
-          NPAPI::PluginList::Singleton()->GetPluginGroupName(*it));
-      if ([name length] == 0)
-        name = base::SysUTF8ToNSString(*it);
-      [pluginArray addObject:name];
-    }
-    [blockedResourcesField_
-        setStringValue:[pluginArray componentsJoinedByString:@"\n"]];
-    [GTMUILocalizerAndLayoutTweaker
-        sizeToFitFixedWidthTextField:blockedResourcesField_];
-  }
-}
-
-- (void)initializePopupList {
-  // I didn't put the buttons into a NSMatrix because then they are only one
-  // entity in the key view loop. This way, one can tab through all of them.
-  const ContentSettingBubbleModel::PopupItems& popupItems =
-      contentSettingBubbleModel_->bubble_content().popup_items;
-
-  // Get the pre-resize frame of the radio group. Its origin is where the
-  // popup list should go.
-  NSRect radioFrame = [allowBlockRadioGroup_ frame];
-
-  // Make room for the popup list. The bubble view and its subviews autosize
-  // themselves when the window is enlarged.
-  // Heading and radio box are already 1 * kLinkOuterPadding apart in the nib,
-  // so only 1 * kLinkOuterPadding more is needed.
-  int delta = popupItems.size() * kLinkLineHeight - kLinkPadding +
-              kLinkOuterPadding;
-  NSSize deltaSize = NSMakeSize(0, delta);
-  deltaSize = [[[self window] contentView] convertSize:deltaSize toView:nil];
-  NSRect windowFrame = [[self window] frame];
-  windowFrame.size.height += deltaSize.height;
-  [[self window] setFrame:windowFrame display:NO];
-
-  // Create popup list.
-  int topLinkY = NSMaxY(radioFrame) + delta - kLinkHeight;
-  int row = 0;
-  for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
-       it(popupItems.begin()); it != popupItems.end(); ++it, ++row) {
-    const SkBitmap& icon = it->bitmap;
-    NSImage* image = nil;
-    if (!icon.empty())
-      image = gfx::SkBitmapToNSImage(icon);
-
-    std::string title(it->title);
-    // The popup may not have committed a load yet, in which case it won't
-    // have a URL or title.
-    if (title.empty())
-      title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
-
-    NSRect linkFrame =
-        NSMakeRect(NSMinX(radioFrame), topLinkY - kLinkLineHeight * row,
-                   200, kLinkHeight);
-    NSButton* button = [self
-        hyperlinkButtonWithFrame:linkFrame
-                           title:base::SysUTF8ToNSString(title)
-                            icon:image
-                  referenceFrame:radioFrame];
-    [[self bubble] addSubview:button];
-    popupLinks_[button] = row;
-  }
-}
-
-- (void)initializeGeoLists {
-  // Cocoa has its origin in the lower left corner. This means elements are
-  // added from bottom to top, which explains why loops run backwards and the
-  // order of operations is the other way than on Linux/Windows.
-  const ContentSettingBubbleModel::BubbleContent& content =
-      contentSettingBubbleModel_->bubble_content();
-  NSRect containerFrame = [contentsContainer_ frame];
-  NSRect frame = NSMakeRect(0, 0, NSWidth(containerFrame), kGeoLabelHeight);
-
-  // "Clear" button / text field.
-  if (!content.custom_link.empty()) {
-    scoped_nsobject<NSControl> control;
-    if(content.custom_link_enabled) {
-      NSRect buttonFrame = NSMakeRect(0, 0,
-                                      NSWidth(containerFrame),
-                                      kGeoClearButtonHeight);
-      NSButton* button = [[NSButton alloc] initWithFrame:buttonFrame];
-      control.reset(button);
-      [button setTitle:base::SysUTF8ToNSString(content.custom_link)];
-      [button setTarget:self];
-      [button setAction:@selector(clearGeolocationForCurrentHost:)];
-      [button setBezelStyle:NSRoundRectBezelStyle];
-      SetControlSize(button, NSSmallControlSize);
-      [button sizeToFit];
-    } else {
-      // Add the notification that settings will be cleared on next reload.
-      control.reset([LabelWithFrame(
-          base::SysUTF8ToNSString(content.custom_link), frame) retain]);
-      SetControlSize(control.get(), NSSmallControlSize);
-    }
-
-    // If the new control is wider than the container, widen the window.
-    CGFloat controlWidth = NSWidth([control frame]);
-    if (controlWidth > NSWidth(containerFrame)) {
-      NSRect windowFrame = [[self window] frame];
-      windowFrame.size.width += controlWidth - NSWidth(containerFrame);
-      [[self window] setFrame:windowFrame display:NO];
-      // Fetch the updated sizes.
-      containerFrame = [contentsContainer_ frame];
-      frame = NSMakeRect(0, 0, NSWidth(containerFrame), kGeoLabelHeight);
-    }
-
-    DCHECK(control);
-    [contentsContainer_ addSubview:control];
-    frame.origin.y = NSMaxY([control frame]) + kGeoPadding;
-  }
-
-  typedef
-      std::vector<ContentSettingBubbleModel::DomainList>::const_reverse_iterator
-      GeolocationGroupIterator;
-  for (GeolocationGroupIterator i = content.domain_lists.rbegin();
-       i != content.domain_lists.rend(); ++i) {
-    // Add all hosts in the current domain list.
-    for (std::set<std::string>::const_reverse_iterator j = i->hosts.rbegin();
-         j != i->hosts.rend(); ++j) {
-      NSTextField* title = LabelWithFrame(base::SysUTF8ToNSString(*j), frame);
-      SetControlSize(title, NSSmallControlSize);
-      [contentsContainer_ addSubview:title];
-
-      frame.origin.y = NSMaxY(frame) + kGeoHostPadding +
-          [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
-    }
-    if (!i->hosts.empty())
-      frame.origin.y += kGeoPadding - kGeoHostPadding;
-
-    // Add the domain list's title.
-    NSTextField* title =
-        LabelWithFrame(base::SysUTF8ToNSString(i->title), frame);
-    SetControlSize(title, NSSmallControlSize);
-    [contentsContainer_ addSubview:title];
-
-    frame.origin.y = NSMaxY(frame) + kGeoPadding +
-        [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
-  }
-
-  CGFloat containerHeight = frame.origin.y;
-  // Undo last padding.
-  if (!content.domain_lists.empty())
-    containerHeight -= kGeoPadding;
-
-  // Resize container to fit its subviews, and window to fit the container.
-  NSRect windowFrame = [[self window] frame];
-  windowFrame.size.height += containerHeight - NSHeight(containerFrame);
-  [[self window] setFrame:windowFrame display:NO];
-  containerFrame.size.height = containerHeight;
-  [contentsContainer_ setFrame:containerFrame];
-}
-
-- (void)sizeToFitLoadPluginsButton {
-  const ContentSettingBubbleModel::BubbleContent& content =
-      contentSettingBubbleModel_->bubble_content();
-  [loadAllPluginsButton_ setEnabled:content.custom_link_enabled];
-
-  // Resize horizontally to fit button if necessary.
-  NSRect windowFrame = [[self window] frame];
-  int widthNeeded = NSWidth([loadAllPluginsButton_ frame]) +
-      2 * NSMinX([loadAllPluginsButton_ frame]);
-  if (NSWidth(windowFrame) < widthNeeded) {
-    windowFrame.size.width = widthNeeded;
-    [[self window] setFrame:windowFrame display:NO];
-  }
-}
-
-- (void)sizeToFitManageDoneButtons {
-  CGFloat actualWidth = NSWidth([[[self window] contentView] frame]);
-  CGFloat requiredWidth = NSMaxX([manageButton_ frame]) + kManageDonePadding +
-      NSWidth([[doneButton_ superview] frame]) - NSMinX([doneButton_ frame]);
-  if (requiredWidth <= actualWidth || !doneButton_ || !manageButton_)
-    return;
-
-  // Resize window, autoresizing takes care of the rest.
-  NSSize size = NSMakeSize(requiredWidth - actualWidth, 0);
-  size = [[[self window] contentView] convertSize:size toView:nil];
-  NSRect frame = [[self window] frame];
-  frame.origin.x -= size.width;
-  frame.size.width += size.width;
-  [[self window] setFrame:frame display:NO];
-}
-
-- (void)awakeFromNib {
-  [super awakeFromNib];
-
-  [[self bubble] setArrowLocation:info_bubble::kTopRight];
-
-  // Adapt window size to bottom buttons. Do this before all other layouting.
-  [self sizeToFitManageDoneButtons];
-
-  [self initializeTitle];
-
-  ContentSettingsType type = contentSettingBubbleModel_->content_type();
-  if (type == CONTENT_SETTINGS_TYPE_PLUGINS) {
-    [self sizeToFitLoadPluginsButton];
-    [self initializeBlockedPluginsList];
-  }
-  if (allowBlockRadioGroup_)  // not bound in cookie bubble xib
-    [self initializeRadioGroup];
-
-  if (type == CONTENT_SETTINGS_TYPE_POPUPS)
-    [self initializePopupList];
-  if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION)
-    [self initializeGeoLists];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Actual application logic
-
-- (IBAction)allowBlockToggled:(id)sender {
-  NSButtonCell *selectedCell = [sender selectedCell];
-  contentSettingBubbleModel_->OnRadioClicked(
-      [selectedCell tag] == kAllowTag ? 0 : 1);
-}
-
-- (void)popupLinkClicked:(id)sender {
-  content_setting_bubble::PopupLinks::iterator i(popupLinks_.find(sender));
-  DCHECK(i != popupLinks_.end());
-  contentSettingBubbleModel_->OnPopupClicked(i->second);
-}
-
-- (void)clearGeolocationForCurrentHost:(id)sender {
-  contentSettingBubbleModel_->OnCustomLinkClicked();
-  [self close];
-}
-
-- (IBAction)showMoreInfo:(id)sender {
-  contentSettingBubbleModel_->OnCustomLinkClicked();
-  [self close];
-}
-
-- (IBAction)loadAllPlugins:(id)sender {
-  contentSettingBubbleModel_->OnCustomLinkClicked();
-  [self close];
-}
-
-- (IBAction)manageBlocking:(id)sender {
-  contentSettingBubbleModel_->OnManageLinkClicked();
-}
-
-- (IBAction)closeBubble:(id)sender {
-  [self close];
-}
-
-@end  // ContentSettingBubbleController
diff --git a/chrome/browser/ui/cocoa/content_setting_bubble_cocoa_unittest.mm b/chrome/browser/ui/cocoa/content_setting_bubble_cocoa_unittest.mm
deleted file mode 100644
index e67b0aa..0000000
--- a/chrome/browser/ui/cocoa/content_setting_bubble_cocoa_unittest.mm
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/content_setting_bubble_cocoa.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/debug/debugger.h"
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/content_setting_bubble_model.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "chrome/common/content_settings_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class DummyContentSettingBubbleModel : public ContentSettingBubbleModel {
- public:
-  DummyContentSettingBubbleModel(ContentSettingsType content_type)
-      : ContentSettingBubbleModel(NULL, NULL, content_type) {
-    RadioGroup radio_group;
-    radio_group.default_item = 0;
-    radio_group.radio_items.resize(2);
-    set_radio_group(radio_group);
-  }
-};
-
-class ContentSettingBubbleControllerTest : public CocoaTest {
-};
-
-// Check that the bubble doesn't crash or leak for any settings type
-TEST_F(ContentSettingBubbleControllerTest, Init) {
-  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
-    if (i == CONTENT_SETTINGS_TYPE_NOTIFICATIONS)
-      continue;  // Notifications have no bubble.
-
-    ContentSettingsType settingsType = static_cast<ContentSettingsType>(i);
-
-    scoped_nsobject<NSWindow> parent([[NSWindow alloc]
-        initWithContentRect:NSMakeRect(0, 0, 800, 600)
-                  styleMask:NSBorderlessWindowMask
-                    backing:NSBackingStoreBuffered
-           defer:NO]);
-    [parent setReleasedWhenClosed:NO];
-    if (base::debug::BeingDebugged())
-      [parent.get() orderFront:nil];
-    else
-      [parent.get() orderBack:nil];
-
-    ContentSettingBubbleController* controller = [ContentSettingBubbleController
-        showForModel:new DummyContentSettingBubbleModel(settingsType)
-        parentWindow:parent
-         anchoredAt:NSMakePoint(50, 20)];
-    EXPECT_TRUE(controller != nil);
-    EXPECT_TRUE([[controller window] isVisible]);
-    [parent.get() close];
-  }
-}
-
-}  // namespace
-
-
diff --git a/chrome/browser/ui/cocoa/content_settings/OWNERS b/chrome/browser/ui/cocoa/content_settings/OWNERS
new file mode 100644
index 0000000..44115d7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/OWNERS
@@ -0,0 +1,3 @@
+bauerb@chromium.org
+jochen@chromium.org
+thakis@chromium.org
diff --git a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h
new file mode 100644
index 0000000..8f6157e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h
@@ -0,0 +1,123 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "chrome/browser/ui/cocoa/constrained_window_mac.h"
+#import "chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h"
+#include "chrome/common/notification_registrar.h"
+
+@class CollectedCookiesWindowController;
+@class VerticalGradientView;
+class TabContents;
+
+// The constrained window delegate reponsible for managing the collected
+// cookies dialog.
+class CollectedCookiesMac : public ConstrainedWindowMacDelegateCustomSheet,
+                            public NotificationObserver {
+ public:
+  CollectedCookiesMac(NSWindow* parent, TabContents* tab_contents);
+
+  void OnSheetDidEnd(NSWindow* sheet);
+
+  // ConstrainedWindowMacDelegateCustomSheet implementation.
+  virtual void DeleteDelegate();
+
+ private:
+  virtual ~CollectedCookiesMac();
+
+  // NotificationObserver implementation.
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details);
+
+  NotificationRegistrar registrar_;
+
+  ConstrainedWindow* window_;
+
+  TabContents* tab_contents_;
+
+  CollectedCookiesWindowController* sheet_controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(CollectedCookiesMac);
+};
+
+// Controller for the collected cookies dialog. This class stores an internal
+// copy of the CookiesTreeModel but with Cocoa-converted values (NSStrings and
+// NSImages instead of std::strings and SkBitmaps). Doing this allows us to use
+// bindings for the interface. Changes are pushed to this internal model via a
+// very thin bridge (see cookies_window_controller.h).
+@interface CollectedCookiesWindowController : NSWindowController
+                                              <NSOutlineViewDelegate,
+                                               NSWindowDelegate> {
+ @private
+  // Platform-independent model.
+  scoped_ptr<CookiesTreeModel> allowedTreeModel_;
+  scoped_ptr<CookiesTreeModel> blockedTreeModel_;
+
+  // Cached array of icons.
+  scoped_nsobject<NSMutableArray> icons_;
+
+  // Our Cocoa copy of the model.
+  scoped_nsobject<CocoaCookieTreeNode> cocoaAllowedTreeModel_;
+  scoped_nsobject<CocoaCookieTreeNode> cocoaBlockedTreeModel_;
+
+  BOOL allowedCookiesButtonsEnabled_;
+  BOOL blockedCookiesButtonsEnabled_;
+
+  IBOutlet NSTreeController* allowedTreeController_;
+  IBOutlet NSTreeController* blockedTreeController_;
+  IBOutlet NSOutlineView* allowedOutlineView_;
+  IBOutlet NSOutlineView* blockedOutlineView_;
+  IBOutlet VerticalGradientView* infoBar_;
+  IBOutlet NSImageView* infoBarIcon_;
+  IBOutlet NSTextField* infoBarText_;
+  IBOutlet NSSplitView* splitView_;
+  IBOutlet NSScrollView* lowerScrollView_;
+  IBOutlet NSTextField* blockedCookiesText_;
+
+  scoped_nsobject<NSViewAnimation> animation_;
+
+  TabContents* tabContents_;  // weak
+
+  BOOL infoBarVisible_;
+}
+@property(readonly, nonatomic) NSTreeController* allowedTreeController;
+@property(readonly, nonatomic) NSTreeController* blockedTreeController;
+
+@property(assign, nonatomic) BOOL allowedCookiesButtonsEnabled;
+@property(assign, nonatomic) BOOL blockedCookiesButtonsEnabled;
+
+// Designated initializer. TabContents cannot be NULL.
+- (id)initWithTabContents:(TabContents*)tabContents;
+
+// Closes the sheet and ends the modal loop. This will also cleanup the memory.
+- (IBAction)closeSheet:(id)sender;
+
+- (IBAction)allowOrigin:(id)sender;
+- (IBAction)allowForSessionFromOrigin:(id)sender;
+- (IBAction)blockOrigin:(id)sender;
+
+// NSSplitView delegate methods:
+- (CGFloat)    splitView:(NSSplitView *)sender
+  constrainMinCoordinate:(CGFloat)proposedMin
+             ofSubviewAt:(NSInteger)offset;
+- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview;
+
+// Returns the cocoaAllowedTreeModel_ and cocoaBlockedTreeModel_.
+- (CocoaCookieTreeNode*)cocoaAllowedTreeModel;
+- (CocoaCookieTreeNode*)cocoaBlockedTreeModel;
+- (void)setCocoaAllowedTreeModel:(CocoaCookieTreeNode*)model;
+- (void)setCocoaBlockedTreeModel:(CocoaCookieTreeNode*)model;
+
+// Returns the allowedTreeModel_ and blockedTreeModel_.
+- (CookiesTreeModel*)allowedTreeModel;
+- (CookiesTreeModel*)blockedTreeModel;
+
+- (void)loadTreeModelFromTabContents;
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm
new file mode 100644
index 0000000..3c94801
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.mm
@@ -0,0 +1,500 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h"
+
+#include <vector>
+
+#import "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "third_party/apple/ImageAndTextCell.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+// Colors for the infobar.
+const double kBannerGradientColorTop[3] =
+    {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
+const double kBannerGradientColorBottom[3] =
+    {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
+const double kBannerStrokeColor = 135.0 / 255.0;
+
+// Minimal height for the collected cookies dialog.
+const CGFloat kMinCollectedCookiesViewHeight = 116;
+} // namespace
+
+#pragma mark Bridge between the constrained window delegate and the sheet
+
+// The delegate used to forward the events from the sheet to the constrained
+// window delegate.
+@interface CollectedCookiesSheetBridge : NSObject {
+  CollectedCookiesMac* collectedCookies_;  // weak
+}
+- (id)initWithCollectedCookiesMac:(CollectedCookiesMac*)collectedCookies;
+- (void)sheetDidEnd:(NSWindow*)sheet
+         returnCode:(int)returnCode
+        contextInfo:(void*)contextInfo;
+@end
+
+@implementation CollectedCookiesSheetBridge
+- (id)initWithCollectedCookiesMac:(CollectedCookiesMac*)collectedCookies {
+  if ((self = [super init])) {
+    collectedCookies_ = collectedCookies;
+  }
+  return self;
+}
+
+- (void)sheetDidEnd:(NSWindow*)sheet
+         returnCode:(int)returnCode
+        contextInfo:(void*)contextInfo {
+  collectedCookies_->OnSheetDidEnd(sheet);
+}
+@end
+
+#pragma mark Constrained window delegate
+
+CollectedCookiesMac::CollectedCookiesMac(NSWindow* parent,
+                                         TabContents* tab_contents)
+    : ConstrainedWindowMacDelegateCustomSheet(
+        [[[CollectedCookiesSheetBridge alloc]
+            initWithCollectedCookiesMac:this] autorelease],
+        @selector(sheetDidEnd:returnCode:contextInfo:)),
+      tab_contents_(tab_contents) {
+  TabSpecificContentSettings* content_settings =
+      tab_contents->GetTabSpecificContentSettings();
+  registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN,
+                 Source<TabSpecificContentSettings>(content_settings));
+
+  sheet_controller_ = [[CollectedCookiesWindowController alloc]
+      initWithTabContents:tab_contents];
+
+  set_sheet([sheet_controller_ window]);
+
+  window_ = tab_contents->CreateConstrainedDialog(this);
+}
+
+CollectedCookiesMac::~CollectedCookiesMac() {
+  NSWindow* window = [sheet_controller_ window];
+  if (window_ && window && is_sheet_open()) {
+    window_ = NULL;
+    [NSApp endSheet:window];
+  }
+}
+
+void CollectedCookiesMac::DeleteDelegate() {
+  delete this;
+}
+
+void CollectedCookiesMac::Observe(NotificationType type,
+                                  const NotificationSource& source,
+                                  const NotificationDetails& details) {
+  DCHECK(type == NotificationType::COLLECTED_COOKIES_SHOWN);
+  DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(),
+            tab_contents_->GetTabSpecificContentSettings());
+  window_->CloseConstrainedWindow();
+}
+
+void CollectedCookiesMac::OnSheetDidEnd(NSWindow* sheet) {
+  [sheet orderOut:sheet_controller_];
+  if (window_)
+    window_->CloseConstrainedWindow();
+}
+
+#pragma mark Window Controller
+
+@interface CollectedCookiesWindowController(Private)
+-(void)showInfoBarForDomain:(const string16&)domain
+                    setting:(ContentSetting)setting;
+-(void)showInfoBarForMultipleDomainsAndSetting:(ContentSetting)setting;
+-(void)animateInfoBar;
+@end
+
+@implementation CollectedCookiesWindowController
+
+@synthesize allowedCookiesButtonsEnabled =
+    allowedCookiesButtonsEnabled_;
+@synthesize blockedCookiesButtonsEnabled =
+    blockedCookiesButtonsEnabled_;
+
+@synthesize allowedTreeController = allowedTreeController_;
+@synthesize blockedTreeController = blockedTreeController_;
+
+- (id)initWithTabContents:(TabContents*)tabContents {
+  DCHECK(tabContents);
+  infoBarVisible_ = NO;
+  tabContents_ = tabContents;
+
+  NSString* nibpath =
+      [base::mac::MainAppBundle() pathForResource:@"CollectedCookies"
+                                          ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    [self loadTreeModelFromTabContents];
+
+    animation_.reset([[NSViewAnimation alloc] init]);
+    [animation_ setAnimationBlockingMode:NSAnimationNonblocking];
+  }
+  return self;
+}
+
+- (void)awakeFromNib {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  NSImage* infoIcon = rb.GetNativeImageNamed(IDR_INFO);
+  DCHECK(infoIcon);
+  [infoBarIcon_ setImage:infoIcon];
+
+  // Initialize the banner gradient and stroke color.
+  NSColor* bannerStartingColor =
+      [NSColor colorWithCalibratedRed:kBannerGradientColorTop[0]
+                                green:kBannerGradientColorTop[1]
+                                 blue:kBannerGradientColorTop[2]
+                                alpha:1.0];
+  NSColor* bannerEndingColor =
+      [NSColor colorWithCalibratedRed:kBannerGradientColorBottom[0]
+                                green:kBannerGradientColorBottom[1]
+                                 blue:kBannerGradientColorBottom[2]
+                                alpha:1.0];
+  scoped_nsobject<NSGradient> bannerGradient(
+      [[NSGradient alloc] initWithStartingColor:bannerStartingColor
+                                    endingColor:bannerEndingColor]);
+  [infoBar_ setGradient:bannerGradient];
+
+  NSColor* bannerStrokeColor =
+      [NSColor colorWithCalibratedWhite:kBannerStrokeColor
+                                  alpha:1.0];
+  [infoBar_ setStrokeColor:bannerStrokeColor];
+
+  // Change the label of the blocked cookies part if necessary.
+  if (tabContents_->profile()->GetHostContentSettingsMap()->
+      BlockThirdPartyCookies()) {
+    [blockedCookiesText_ setStringValue:l10n_util::GetNSString(
+        IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED)];
+    CGFloat textDeltaY = [GTMUILocalizerAndLayoutTweaker
+        sizeToFitFixedWidthTextField:blockedCookiesText_];
+
+    // Shrink the upper custom view.
+    NSView* upperContentView = [[splitView_ subviews] objectAtIndex:0];
+    NSRect frame = [upperContentView frame];
+    [splitView_ setPosition:(frame.size.height - textDeltaY/2.0)
+           ofDividerAtIndex:0];
+
+    // Shrink the lower outline view.
+    frame = [lowerScrollView_ frame];
+    frame.size.height -= textDeltaY;
+    [lowerScrollView_ setFrame:frame];
+
+    // Move the label down so it actually fits.
+    frame = [blockedCookiesText_ frame];
+    frame.origin.y -= textDeltaY;
+    [blockedCookiesText_ setFrame:frame];
+  }
+}
+
+- (void)windowWillClose:(NSNotification*)notif {
+  [allowedOutlineView_ setDelegate:nil];
+  [blockedOutlineView_ setDelegate:nil];
+  [animation_ stopAnimation];
+  [self autorelease];
+}
+
+- (IBAction)closeSheet:(id)sender {
+  [NSApp endSheet:[self window]];
+}
+
+- (void)addException:(ContentSetting)setting
+   forTreeController:(NSTreeController*)controller {
+  NSArray* nodes = [controller selectedNodes];
+  BOOL multipleDomainsChanged = NO;
+  string16 lastDomain;
+  for (NSTreeNode* treeNode in nodes) {
+    CocoaCookieTreeNode* node = [treeNode representedObject];
+    CookieTreeNode* cookie = static_cast<CookieTreeNode*>([node treeNode]);
+    if (cookie->GetDetailedInfo().node_type !=
+        CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
+      continue;
+    }
+    CookieTreeOriginNode* origin_node =
+        static_cast<CookieTreeOriginNode*>(cookie);
+    origin_node->CreateContentException(
+        tabContents_->profile()->GetHostContentSettingsMap(),
+        setting);
+    if (!lastDomain.empty())
+      multipleDomainsChanged = YES;
+    lastDomain = origin_node->GetTitle();
+  }
+  if (multipleDomainsChanged)
+    [self showInfoBarForMultipleDomainsAndSetting:setting];
+  else
+    [self showInfoBarForDomain:lastDomain setting:setting];
+}
+
+- (IBAction)allowOrigin:(id)sender {
+  [self    addException:CONTENT_SETTING_ALLOW
+      forTreeController:blockedTreeController_];
+}
+
+- (IBAction)allowForSessionFromOrigin:(id)sender {
+  [self    addException:CONTENT_SETTING_SESSION_ONLY
+      forTreeController:blockedTreeController_];
+}
+
+- (IBAction)blockOrigin:(id)sender {
+  [self    addException:CONTENT_SETTING_BLOCK
+      forTreeController:allowedTreeController_];
+}
+
+- (CGFloat)    splitView:(NSSplitView *)sender
+  constrainMinCoordinate:(CGFloat)proposedMin
+             ofSubviewAt:(NSInteger)offset {
+  return proposedMin + kMinCollectedCookiesViewHeight;
+}
+- (CGFloat)    splitView:(NSSplitView *)sender
+  constrainMaxCoordinate:(CGFloat)proposedMax
+             ofSubviewAt:(NSInteger)offset {
+  return proposedMax - kMinCollectedCookiesViewHeight;
+}
+- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview {
+  return YES;
+}
+
+- (CocoaCookieTreeNode*)cocoaAllowedTreeModel {
+  return cocoaAllowedTreeModel_.get();
+}
+- (void)setCocoaAllowedTreeModel:(CocoaCookieTreeNode*)model {
+  cocoaAllowedTreeModel_.reset([model retain]);
+}
+
+- (CookiesTreeModel*)allowedTreeModel {
+  return allowedTreeModel_.get();
+}
+
+- (CocoaCookieTreeNode*)cocoaBlockedTreeModel {
+  return cocoaBlockedTreeModel_.get();
+}
+- (void)setCocoaBlockedTreeModel:(CocoaCookieTreeNode*)model {
+  cocoaBlockedTreeModel_.reset([model retain]);
+}
+
+- (CookiesTreeModel*)blockedTreeModel {
+  return blockedTreeModel_.get();
+}
+
+- (void)outlineView:(NSOutlineView*)outlineView
+    willDisplayCell:(id)cell
+     forTableColumn:(NSTableColumn*)tableColumn
+               item:(id)item {
+  CocoaCookieTreeNode* node = [item representedObject];
+  int index;
+  if (outlineView == allowedOutlineView_)
+    index = allowedTreeModel_->GetIconIndex([node treeNode]);
+  else
+    index = blockedTreeModel_->GetIconIndex([node treeNode]);
+  NSImage* icon = nil;
+  if (index >= 0)
+    icon = [icons_ objectAtIndex:index];
+  else
+    icon = [icons_ lastObject];
+  DCHECK([cell isKindOfClass:[ImageAndTextCell class]]);
+  [static_cast<ImageAndTextCell*>(cell) setImage:icon];
+}
+
+- (void)outlineViewSelectionDidChange:(NSNotification*)notif {
+  BOOL isAllowedOutlineView;
+  if ([notif object] == allowedOutlineView_) {
+    isAllowedOutlineView = YES;
+  } else if ([notif object] == blockedOutlineView_) {
+    isAllowedOutlineView = NO;
+  } else {
+    NOTREACHED();
+    return;
+  }
+  NSTreeController* controller =
+      isAllowedOutlineView ? allowedTreeController_ : blockedTreeController_;
+
+  NSArray* nodes = [controller selectedNodes];
+  for (NSTreeNode* treeNode in nodes) {
+    CocoaCookieTreeNode* node = [treeNode representedObject];
+    CookieTreeNode* cookie = static_cast<CookieTreeNode*>([node treeNode]);
+    if (cookie->GetDetailedInfo().node_type !=
+        CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
+      continue;
+    }
+   CookieTreeOriginNode* origin_node =
+       static_cast<CookieTreeOriginNode*>(cookie);
+   if (origin_node->CanCreateContentException()) {
+      if (isAllowedOutlineView) {
+        [self setAllowedCookiesButtonsEnabled:YES];
+      } else {
+        [self setBlockedCookiesButtonsEnabled:YES];
+      }
+      return;
+    }
+  }
+  if (isAllowedOutlineView) {
+    [self setAllowedCookiesButtonsEnabled:NO];
+  } else {
+    [self setBlockedCookiesButtonsEnabled:NO];
+  }
+}
+
+// Initializes the |allowedTreeModel_| and |blockedTreeModel_|, and builds
+// the |cocoaAllowedTreeModel_| and |cocoaBlockedTreeModel_|.
+- (void)loadTreeModelFromTabContents {
+  TabSpecificContentSettings* content_settings =
+      tabContents_->GetTabSpecificContentSettings();
+  allowedTreeModel_.reset(content_settings->GetAllowedCookiesTreeModel());
+  blockedTreeModel_.reset(content_settings->GetBlockedCookiesTreeModel());
+
+  // Convert the model's icons from Skia to Cocoa.
+  std::vector<SkBitmap> skiaIcons;
+  allowedTreeModel_->GetIcons(&skiaIcons);
+  icons_.reset([[NSMutableArray alloc] init]);
+  for (std::vector<SkBitmap>::iterator it = skiaIcons.begin();
+       it != skiaIcons.end(); ++it) {
+    [icons_ addObject:gfx::SkBitmapToNSImage(*it)];
+  }
+
+  // Default icon will be the last item in the array.
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  // TODO(rsesek): Rename this resource now that it's in multiple places.
+  [icons_ addObject:rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER)];
+
+  // Create the Cocoa model.
+  CookieTreeNode* root =
+      static_cast<CookieTreeNode*>(allowedTreeModel_->GetRoot());
+  scoped_nsobject<CocoaCookieTreeNode> model(
+      [[CocoaCookieTreeNode alloc] initWithNode:root]);
+  [self setCocoaAllowedTreeModel:model.get()];  // Takes ownership.
+  root = static_cast<CookieTreeNode*>(blockedTreeModel_->GetRoot());
+  model.reset(
+      [[CocoaCookieTreeNode alloc] initWithNode:root]);
+  [self setCocoaBlockedTreeModel:model.get()];  // Takes ownership.
+}
+
+-(void)showInfoBarForMultipleDomainsAndSetting:(ContentSetting)setting {
+  NSString* label;
+  switch (setting) {
+    case CONTENT_SETTING_BLOCK:
+      label = l10n_util::GetNSString(
+          IDS_COLLECTED_COOKIES_MULTIPLE_BLOCK_RULES_CREATED);
+      break;
+
+    case CONTENT_SETTING_ALLOW:
+      label = l10n_util::GetNSString(
+          IDS_COLLECTED_COOKIES_MULTIPLE_ALLOW_RULES_CREATED);
+      break;
+
+    case CONTENT_SETTING_SESSION_ONLY:
+      label = l10n_util::GetNSString(
+          IDS_COLLECTED_COOKIES_MULTIPLE_SESSION_RULES_CREATED);
+      break;
+
+    default:
+      NOTREACHED();
+      label = [[[NSString alloc] init] autorelease];
+  }
+  [infoBarText_ setStringValue:label];
+  [self animateInfoBar];
+}
+
+-(void)showInfoBarForDomain:(const string16&)domain
+                    setting:(ContentSetting)setting {
+  NSString* label;
+  switch (setting) {
+    case CONTENT_SETTING_BLOCK:
+      label = l10n_util::GetNSStringF(
+          IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED,
+          domain);
+      break;
+
+    case CONTENT_SETTING_ALLOW:
+      label = l10n_util::GetNSStringF(
+          IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED,
+          domain);
+      break;
+
+    case CONTENT_SETTING_SESSION_ONLY:
+      label = l10n_util::GetNSStringF(
+          IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED,
+          domain);
+      break;
+
+    default:
+      NOTREACHED();
+      label = [[[NSString alloc] init] autorelease];
+  }
+  [infoBarText_ setStringValue:label];
+  [self animateInfoBar];
+}
+
+-(void)animateInfoBar {
+  if (infoBarVisible_)
+    return;
+
+  infoBarVisible_ = YES;
+
+  NSMutableArray* animations = [NSMutableArray arrayWithCapacity:3];
+
+  NSWindow* sheet = [self window];
+  NSRect sheetFrame = [sheet frame];
+  NSRect infoBarFrame = [infoBar_ frame];
+  NSRect splitViewFrame = [splitView_ frame];
+
+  // Calculate the end position of the info bar and set it to its start
+  // position.
+  infoBarFrame.origin.y = NSHeight(sheetFrame);
+  infoBarFrame.size.width = NSWidth(sheetFrame);
+  NSRect infoBarStartFrame = infoBarFrame;
+  infoBarStartFrame.origin.y += NSHeight(infoBarFrame);
+  infoBarStartFrame.size.height = 0.0;
+  [infoBar_ setFrame:infoBarStartFrame];
+  [[[self window] contentView] addSubview:infoBar_];
+
+  // Calculate the new position of the sheet.
+  sheetFrame.origin.y -= NSHeight(infoBarFrame);
+  sheetFrame.size.height += NSHeight(infoBarFrame);
+
+  // Slide the infobar in.
+  [animations addObject:
+      [NSDictionary dictionaryWithObjectsAndKeys:
+          infoBar_, NSViewAnimationTargetKey,
+          [NSValue valueWithRect:infoBarFrame],
+              NSViewAnimationEndFrameKey,
+          [NSValue valueWithRect:infoBarStartFrame],
+              NSViewAnimationStartFrameKey,
+          nil]];
+  // Make sure the split view ends up in the right position.
+  [animations addObject:
+      [NSDictionary dictionaryWithObjectsAndKeys:
+          splitView_, NSViewAnimationTargetKey,
+          [NSValue valueWithRect:splitViewFrame],
+              NSViewAnimationEndFrameKey,
+          nil]];
+
+  // Grow the sheet.
+  [animations addObject:
+      [NSDictionary dictionaryWithObjectsAndKeys:
+          sheet, NSViewAnimationTargetKey,
+          [NSValue valueWithRect:sheetFrame],
+              NSViewAnimationEndFrameKey,
+          nil]];
+  [animation_ setViewAnimations:animations];
+  // The default duration is 0.5s, which actually feels slow in here, so speed
+  // it up a bit.
+  [animation_ gtm_setDuration:0.2
+                    eventMask:NSLeftMouseUpMask];
+  [animation_ startAnimation];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac_unittest.mm b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac_unittest.mm
new file mode 100644
index 0000000..b28db89
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/collected_cookies_mac_unittest.mm
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/ref_counted.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/browser/tab_contents/test_tab_contents.h"
+#import "chrome/browser/ui/cocoa/content_settings/collected_cookies_mac.h"
+#include "chrome/test/testing_profile.h"
+
+namespace {
+
+class CollectedCookiesWindowControllerTest : public RenderViewHostTestHarness {
+};
+
+TEST_F(CollectedCookiesWindowControllerTest, Construction) {
+  BrowserThread ui_thread(BrowserThread::UI, MessageLoop::current());
+  // Create a test tab.  SiteInstance will be deleted when tabContents is
+  // deleted.
+  SiteInstance* instance =
+      SiteInstance::CreateSiteInstance(profile_.get());
+  TestTabContents* tabContents = new TestTabContents(profile_.get(),
+                                                      instance);
+  CollectedCookiesWindowController* controller =
+      [[CollectedCookiesWindowController alloc]
+          initWithTabContents:tabContents];
+
+  [controller release];
+
+  delete tabContents;
+}
+
+}  // namespace
+
diff --git a/chrome/browser/ui/cocoa/content_setting_bubble_cocoa.h b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
similarity index 100%
rename from chrome/browser/ui/cocoa/content_setting_bubble_cocoa.h
rename to chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
new file mode 100644
index 0000000..08970b8
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
@@ -0,0 +1,489 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/blocked_content_container.h"
+#include "chrome/browser/content_setting_bubble_model.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/plugin_updater.h"
+#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
+#import "chrome/browser/ui/cocoa/info_bubble_view.h"
+#import "chrome/browser/ui/cocoa/l10n_util.h"
+#import "chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h"
+#include "grit/generated_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+namespace {
+
+// Must match the tag of the unblock radio button in the xib files.
+const int kAllowTag = 1;
+
+// Must match the tag of the block radio button in the xib files.
+const int kBlockTag = 2;
+
+// Height of one link in the popup list.
+const int kLinkHeight = 16;
+
+// Space between two popup links.
+const int kLinkPadding = 4;
+
+// Space taken in total by one popup link.
+const int kLinkLineHeight = kLinkHeight + kLinkPadding;
+
+// Space between popup list and surrounding UI elements.
+const int kLinkOuterPadding = 8;
+
+// Height of each of the labels in the geolocation bubble.
+const int kGeoLabelHeight = 14;
+
+// Height of the "Clear" button in the geolocation bubble.
+const int kGeoClearButtonHeight = 17;
+
+// Padding between radio buttons and "Load all plugins" button
+// in the plugin bubble.
+const int kLoadAllPluginsButtonVerticalPadding = 8;
+
+// General padding between elements in the geolocation bubble.
+const int kGeoPadding = 8;
+
+// Padding between host names in the geolocation bubble.
+const int kGeoHostPadding = 4;
+
+// Minimal padding between "Manage" and "Done" buttons.
+const int kManageDonePadding = 8;
+
+void SetControlSize(NSControl* control, NSControlSize controlSize) {
+  CGFloat fontSize = [NSFont systemFontSizeForControlSize:controlSize];
+  NSCell* cell = [control cell];
+  NSFont* font = [NSFont fontWithName:[[cell font] fontName] size:fontSize];
+  [cell setFont:font];
+  [cell setControlSize:controlSize];
+}
+
+// Returns an autoreleased NSTextField that is configured to look like a Label
+// looks in Interface Builder.
+NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
+  NSTextField* label = [[NSTextField alloc] initWithFrame:frame];
+  [label setStringValue:text];
+  [label setSelectable:NO];
+  [label setBezeled:NO];
+  return [label autorelease];
+}
+
+}  // namespace
+
+@interface ContentSettingBubbleController(Private)
+- (id)initWithModel:(ContentSettingBubbleModel*)settingsBubbleModel
+       parentWindow:(NSWindow*)parentWindow
+         anchoredAt:(NSPoint)anchoredAt;
+- (NSButton*)hyperlinkButtonWithFrame:(NSRect)frame
+                                title:(NSString*)title
+                                 icon:(NSImage*)icon
+                       referenceFrame:(NSRect)referenceFrame;
+- (void)initializeBlockedPluginsList;
+- (void)initializeTitle;
+- (void)initializeRadioGroup;
+- (void)initializePopupList;
+- (void)initializeGeoLists;
+- (void)sizeToFitLoadPluginsButton;
+- (void)sizeToFitManageDoneButtons;
+- (void)removeInfoButton;
+- (void)popupLinkClicked:(id)sender;
+- (void)clearGeolocationForCurrentHost:(id)sender;
+@end
+
+@implementation ContentSettingBubbleController
+
++ (ContentSettingBubbleController*)
+    showForModel:(ContentSettingBubbleModel*)contentSettingBubbleModel
+    parentWindow:(NSWindow*)parentWindow
+      anchoredAt:(NSPoint)anchor {
+  // Autoreleases itself on bubble close.
+  return [[ContentSettingBubbleController alloc]
+             initWithModel:contentSettingBubbleModel
+              parentWindow:parentWindow
+                anchoredAt:anchor];
+}
+
+- (id)initWithModel:(ContentSettingBubbleModel*)contentSettingBubbleModel
+       parentWindow:(NSWindow*)parentWindow
+         anchoredAt:(NSPoint)anchoredAt {
+  // This method takes ownership of |contentSettingBubbleModel| in all cases.
+  scoped_ptr<ContentSettingBubbleModel> model(contentSettingBubbleModel);
+  DCHECK(model.get());
+
+  NSString* const nibPaths[] = {
+    @"ContentBlockedCookies",
+    @"ContentBlockedImages",
+    @"ContentBlockedJavaScript",
+    @"ContentBlockedPlugins",
+    @"ContentBlockedPopups",
+    @"ContentBubbleGeolocation",
+    @"",  // Notifications do not have a bubble.
+  };
+  COMPILE_ASSERT(arraysize(nibPaths) == CONTENT_SETTINGS_NUM_TYPES,
+                 nibPaths_requires_an_entry_for_every_setting_type);
+  const int settingsType = model->content_type();
+  // Nofifications do not have a bubble.
+  CHECK_NE(settingsType, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
+  DCHECK_LT(settingsType, CONTENT_SETTINGS_NUM_TYPES);
+  if ((self = [super initWithWindowNibPath:nibPaths[settingsType]
+                              parentWindow:parentWindow
+                                anchoredAt:anchoredAt])) {
+    contentSettingBubbleModel_.reset(model.release());
+    [self showWindow:nil];
+  }
+  return self;
+}
+
+- (void)initializeTitle {
+  if (!titleLabel_)
+    return;
+
+  NSString* label = base::SysUTF8ToNSString(
+      contentSettingBubbleModel_->bubble_content().title);
+  [titleLabel_ setStringValue:label];
+
+  // Layout title post-localization.
+  CGFloat deltaY = [GTMUILocalizerAndLayoutTweaker
+      sizeToFitFixedWidthTextField:titleLabel_];
+  NSRect windowFrame = [[self window] frame];
+  windowFrame.size.height += deltaY;
+  [[self window] setFrame:windowFrame display:NO];
+  NSRect titleFrame = [titleLabel_ frame];
+  titleFrame.origin.y -= deltaY;
+  [titleLabel_ setFrame:titleFrame];
+}
+
+- (void)initializeRadioGroup {
+  // Configure the radio group. For now, only deal with the
+  // strictly needed case of group containing 2 radio buttons.
+  const ContentSettingBubbleModel::RadioGroup& radio_group =
+      contentSettingBubbleModel_->bubble_content().radio_group;
+
+  // Select appropriate radio button.
+  [allowBlockRadioGroup_ selectCellWithTag:
+      radio_group.default_item == 0 ? kAllowTag : kBlockTag];
+
+  const ContentSettingBubbleModel::RadioItems& radio_items =
+      radio_group.radio_items;
+  DCHECK_EQ(2u, radio_items.size()) << "Only 2 radio items per group supported";
+  // Set radio group labels from model.
+  NSCell* radioCell = [allowBlockRadioGroup_ cellWithTag:kAllowTag];
+  [radioCell setTitle:base::SysUTF8ToNSString(radio_items[0])];
+
+  radioCell = [allowBlockRadioGroup_ cellWithTag:kBlockTag];
+  [radioCell setTitle:base::SysUTF8ToNSString(radio_items[1])];
+
+  // Layout radio group labels post-localization.
+  [GTMUILocalizerAndLayoutTweaker
+      wrapRadioGroupForWidth:allowBlockRadioGroup_];
+  CGFloat radioDeltaY = [GTMUILocalizerAndLayoutTweaker
+      sizeToFitView:allowBlockRadioGroup_].height;
+  NSRect windowFrame = [[self window] frame];
+  windowFrame.size.height += radioDeltaY;
+  [[self window] setFrame:windowFrame display:NO];
+}
+
+- (NSButton*)hyperlinkButtonWithFrame:(NSRect)frame
+                                title:(NSString*)title
+                                 icon:(NSImage*)icon
+                       referenceFrame:(NSRect)referenceFrame {
+  scoped_nsobject<HyperlinkButtonCell> cell([[HyperlinkButtonCell alloc]
+      initTextCell:title]);
+  [cell.get() setAlignment:NSNaturalTextAlignment];
+  if (icon) {
+    [cell.get() setImagePosition:NSImageLeft];
+    [cell.get() setImage:icon];
+  } else {
+    [cell.get() setImagePosition:NSNoImage];
+  }
+  [cell.get() setControlSize:NSSmallControlSize];
+
+  NSButton* button = [[[NSButton alloc] initWithFrame:frame] autorelease];
+  // Cell must be set immediately after construction.
+  [button setCell:cell.get()];
+
+  // If the link text is too long, clamp it.
+  [button sizeToFit];
+  int maxWidth = NSWidth([[self bubble] frame]) - 2 * NSMinX(referenceFrame);
+  NSRect buttonFrame = [button frame];
+  if (NSWidth(buttonFrame) > maxWidth) {
+    buttonFrame.size.width = maxWidth;
+    [button setFrame:buttonFrame];
+  }
+
+  [button setTarget:self];
+  [button setAction:@selector(popupLinkClicked:)];
+  return button;
+}
+
+- (void)initializeBlockedPluginsList {
+  NSMutableArray* pluginArray = [NSMutableArray array];
+  const std::set<std::string>& plugins =
+      contentSettingBubbleModel_->bubble_content().resource_identifiers;
+  if (plugins.empty()) {
+    int delta = NSMinY([titleLabel_ frame]) -
+                NSMinY([blockedResourcesField_ frame]);
+    [blockedResourcesField_ removeFromSuperview];
+    NSRect frame = [[self window] frame];
+    frame.size.height -= delta;
+    [[self window] setFrame:frame display:NO];
+  } else {
+    for (std::set<std::string>::iterator it = plugins.begin();
+         it != plugins.end(); ++it) {
+      NSString* name = SysUTF16ToNSString(
+          NPAPI::PluginList::Singleton()->GetPluginGroupName(*it));
+      if ([name length] == 0)
+        name = base::SysUTF8ToNSString(*it);
+      [pluginArray addObject:name];
+    }
+    [blockedResourcesField_
+        setStringValue:[pluginArray componentsJoinedByString:@"\n"]];
+    [GTMUILocalizerAndLayoutTweaker
+        sizeToFitFixedWidthTextField:blockedResourcesField_];
+  }
+}
+
+- (void)initializePopupList {
+  // I didn't put the buttons into a NSMatrix because then they are only one
+  // entity in the key view loop. This way, one can tab through all of them.
+  const ContentSettingBubbleModel::PopupItems& popupItems =
+      contentSettingBubbleModel_->bubble_content().popup_items;
+
+  // Get the pre-resize frame of the radio group. Its origin is where the
+  // popup list should go.
+  NSRect radioFrame = [allowBlockRadioGroup_ frame];
+
+  // Make room for the popup list. The bubble view and its subviews autosize
+  // themselves when the window is enlarged.
+  // Heading and radio box are already 1 * kLinkOuterPadding apart in the nib,
+  // so only 1 * kLinkOuterPadding more is needed.
+  int delta = popupItems.size() * kLinkLineHeight - kLinkPadding +
+              kLinkOuterPadding;
+  NSSize deltaSize = NSMakeSize(0, delta);
+  deltaSize = [[[self window] contentView] convertSize:deltaSize toView:nil];
+  NSRect windowFrame = [[self window] frame];
+  windowFrame.size.height += deltaSize.height;
+  [[self window] setFrame:windowFrame display:NO];
+
+  // Create popup list.
+  int topLinkY = NSMaxY(radioFrame) + delta - kLinkHeight;
+  int row = 0;
+  for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
+       it(popupItems.begin()); it != popupItems.end(); ++it, ++row) {
+    const SkBitmap& icon = it->bitmap;
+    NSImage* image = nil;
+    if (!icon.empty())
+      image = gfx::SkBitmapToNSImage(icon);
+
+    std::string title(it->title);
+    // The popup may not have committed a load yet, in which case it won't
+    // have a URL or title.
+    if (title.empty())
+      title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
+
+    NSRect linkFrame =
+        NSMakeRect(NSMinX(radioFrame), topLinkY - kLinkLineHeight * row,
+                   200, kLinkHeight);
+    NSButton* button = [self
+        hyperlinkButtonWithFrame:linkFrame
+                           title:base::SysUTF8ToNSString(title)
+                            icon:image
+                  referenceFrame:radioFrame];
+    [[self bubble] addSubview:button];
+    popupLinks_[button] = row;
+  }
+}
+
+- (void)initializeGeoLists {
+  // Cocoa has its origin in the lower left corner. This means elements are
+  // added from bottom to top, which explains why loops run backwards and the
+  // order of operations is the other way than on Linux/Windows.
+  const ContentSettingBubbleModel::BubbleContent& content =
+      contentSettingBubbleModel_->bubble_content();
+  NSRect containerFrame = [contentsContainer_ frame];
+  NSRect frame = NSMakeRect(0, 0, NSWidth(containerFrame), kGeoLabelHeight);
+
+  // "Clear" button / text field.
+  if (!content.custom_link.empty()) {
+    scoped_nsobject<NSControl> control;
+    if(content.custom_link_enabled) {
+      NSRect buttonFrame = NSMakeRect(0, 0,
+                                      NSWidth(containerFrame),
+                                      kGeoClearButtonHeight);
+      NSButton* button = [[NSButton alloc] initWithFrame:buttonFrame];
+      control.reset(button);
+      [button setTitle:base::SysUTF8ToNSString(content.custom_link)];
+      [button setTarget:self];
+      [button setAction:@selector(clearGeolocationForCurrentHost:)];
+      [button setBezelStyle:NSRoundRectBezelStyle];
+      SetControlSize(button, NSSmallControlSize);
+      [button sizeToFit];
+    } else {
+      // Add the notification that settings will be cleared on next reload.
+      control.reset([LabelWithFrame(
+          base::SysUTF8ToNSString(content.custom_link), frame) retain]);
+      SetControlSize(control.get(), NSSmallControlSize);
+    }
+
+    // If the new control is wider than the container, widen the window.
+    CGFloat controlWidth = NSWidth([control frame]);
+    if (controlWidth > NSWidth(containerFrame)) {
+      NSRect windowFrame = [[self window] frame];
+      windowFrame.size.width += controlWidth - NSWidth(containerFrame);
+      [[self window] setFrame:windowFrame display:NO];
+      // Fetch the updated sizes.
+      containerFrame = [contentsContainer_ frame];
+      frame = NSMakeRect(0, 0, NSWidth(containerFrame), kGeoLabelHeight);
+    }
+
+    DCHECK(control);
+    [contentsContainer_ addSubview:control];
+    frame.origin.y = NSMaxY([control frame]) + kGeoPadding;
+  }
+
+  typedef
+      std::vector<ContentSettingBubbleModel::DomainList>::const_reverse_iterator
+      GeolocationGroupIterator;
+  for (GeolocationGroupIterator i = content.domain_lists.rbegin();
+       i != content.domain_lists.rend(); ++i) {
+    // Add all hosts in the current domain list.
+    for (std::set<std::string>::const_reverse_iterator j = i->hosts.rbegin();
+         j != i->hosts.rend(); ++j) {
+      NSTextField* title = LabelWithFrame(base::SysUTF8ToNSString(*j), frame);
+      SetControlSize(title, NSSmallControlSize);
+      [contentsContainer_ addSubview:title];
+
+      frame.origin.y = NSMaxY(frame) + kGeoHostPadding +
+          [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
+    }
+    if (!i->hosts.empty())
+      frame.origin.y += kGeoPadding - kGeoHostPadding;
+
+    // Add the domain list's title.
+    NSTextField* title =
+        LabelWithFrame(base::SysUTF8ToNSString(i->title), frame);
+    SetControlSize(title, NSSmallControlSize);
+    [contentsContainer_ addSubview:title];
+
+    frame.origin.y = NSMaxY(frame) + kGeoPadding +
+        [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
+  }
+
+  CGFloat containerHeight = frame.origin.y;
+  // Undo last padding.
+  if (!content.domain_lists.empty())
+    containerHeight -= kGeoPadding;
+
+  // Resize container to fit its subviews, and window to fit the container.
+  NSRect windowFrame = [[self window] frame];
+  windowFrame.size.height += containerHeight - NSHeight(containerFrame);
+  [[self window] setFrame:windowFrame display:NO];
+  containerFrame.size.height = containerHeight;
+  [contentsContainer_ setFrame:containerFrame];
+}
+
+- (void)sizeToFitLoadPluginsButton {
+  const ContentSettingBubbleModel::BubbleContent& content =
+      contentSettingBubbleModel_->bubble_content();
+  [loadAllPluginsButton_ setEnabled:content.custom_link_enabled];
+
+  // Resize horizontally to fit button if necessary.
+  NSRect windowFrame = [[self window] frame];
+  int widthNeeded = NSWidth([loadAllPluginsButton_ frame]) +
+      2 * NSMinX([loadAllPluginsButton_ frame]);
+  if (NSWidth(windowFrame) < widthNeeded) {
+    windowFrame.size.width = widthNeeded;
+    [[self window] setFrame:windowFrame display:NO];
+  }
+}
+
+- (void)sizeToFitManageDoneButtons {
+  CGFloat actualWidth = NSWidth([[[self window] contentView] frame]);
+  CGFloat requiredWidth = NSMaxX([manageButton_ frame]) + kManageDonePadding +
+      NSWidth([[doneButton_ superview] frame]) - NSMinX([doneButton_ frame]);
+  if (requiredWidth <= actualWidth || !doneButton_ || !manageButton_)
+    return;
+
+  // Resize window, autoresizing takes care of the rest.
+  NSSize size = NSMakeSize(requiredWidth - actualWidth, 0);
+  size = [[[self window] contentView] convertSize:size toView:nil];
+  NSRect frame = [[self window] frame];
+  frame.origin.x -= size.width;
+  frame.size.width += size.width;
+  [[self window] setFrame:frame display:NO];
+}
+
+- (void)awakeFromNib {
+  [super awakeFromNib];
+
+  [[self bubble] setArrowLocation:info_bubble::kTopRight];
+
+  // Adapt window size to bottom buttons. Do this before all other layouting.
+  [self sizeToFitManageDoneButtons];
+
+  [self initializeTitle];
+
+  ContentSettingsType type = contentSettingBubbleModel_->content_type();
+  if (type == CONTENT_SETTINGS_TYPE_PLUGINS) {
+    [self sizeToFitLoadPluginsButton];
+    [self initializeBlockedPluginsList];
+  }
+  if (allowBlockRadioGroup_)  // not bound in cookie bubble xib
+    [self initializeRadioGroup];
+
+  if (type == CONTENT_SETTINGS_TYPE_POPUPS)
+    [self initializePopupList];
+  if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION)
+    [self initializeGeoLists];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Actual application logic
+
+- (IBAction)allowBlockToggled:(id)sender {
+  NSButtonCell *selectedCell = [sender selectedCell];
+  contentSettingBubbleModel_->OnRadioClicked(
+      [selectedCell tag] == kAllowTag ? 0 : 1);
+}
+
+- (void)popupLinkClicked:(id)sender {
+  content_setting_bubble::PopupLinks::iterator i(popupLinks_.find(sender));
+  DCHECK(i != popupLinks_.end());
+  contentSettingBubbleModel_->OnPopupClicked(i->second);
+}
+
+- (void)clearGeolocationForCurrentHost:(id)sender {
+  contentSettingBubbleModel_->OnCustomLinkClicked();
+  [self close];
+}
+
+- (IBAction)showMoreInfo:(id)sender {
+  contentSettingBubbleModel_->OnCustomLinkClicked();
+  [self close];
+}
+
+- (IBAction)loadAllPlugins:(id)sender {
+  contentSettingBubbleModel_->OnCustomLinkClicked();
+  [self close];
+}
+
+- (IBAction)manageBlocking:(id)sender {
+  contentSettingBubbleModel_->OnManageLinkClicked();
+}
+
+- (IBAction)closeBubble:(id)sender {
+  [self close];
+}
+
+@end  // ContentSettingBubbleController
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm
new file mode 100644
index 0000000..88d485b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_unittest.mm
@@ -0,0 +1,63 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/debug/debugger.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/content_setting_bubble_model.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "chrome/common/content_settings_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class DummyContentSettingBubbleModel : public ContentSettingBubbleModel {
+ public:
+  DummyContentSettingBubbleModel(ContentSettingsType content_type)
+      : ContentSettingBubbleModel(NULL, NULL, content_type) {
+    RadioGroup radio_group;
+    radio_group.default_item = 0;
+    radio_group.radio_items.resize(2);
+    set_radio_group(radio_group);
+  }
+};
+
+class ContentSettingBubbleControllerTest : public CocoaTest {
+};
+
+// Check that the bubble doesn't crash or leak for any settings type
+TEST_F(ContentSettingBubbleControllerTest, Init) {
+  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+    if (i == CONTENT_SETTINGS_TYPE_NOTIFICATIONS)
+      continue;  // Notifications have no bubble.
+
+    ContentSettingsType settingsType = static_cast<ContentSettingsType>(i);
+
+    scoped_nsobject<NSWindow> parent([[NSWindow alloc]
+        initWithContentRect:NSMakeRect(0, 0, 800, 600)
+                  styleMask:NSBorderlessWindowMask
+                    backing:NSBackingStoreBuffered
+           defer:NO]);
+    [parent setReleasedWhenClosed:NO];
+    if (base::debug::BeingDebugged())
+      [parent.get() orderFront:nil];
+    else
+      [parent.get() orderBack:nil];
+
+    ContentSettingBubbleController* controller = [ContentSettingBubbleController
+        showForModel:new DummyContentSettingBubbleModel(settingsType)
+        parentWindow:parent
+         anchoredAt:NSMakePoint(50, 20)];
+    EXPECT_TRUE(controller != nil);
+    EXPECT_TRUE([[controller window] isVisible]);
+    [parent.get() close];
+  }
+}
+
+}  // namespace
+
+
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details.h b/chrome/browser/ui/cocoa/content_settings/cookie_details.h
new file mode 100644
index 0000000..050e379
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details.h
@@ -0,0 +1,224 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data_indexed_db_helper.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "base/scoped_nsobject.h"
+#include "net/base/cookie_monster.h"
+#include "webkit/appcache/appcache_service.h"
+
+class CookieTreeNode;
+class CookiePromptModalDialog;
+
+// This enum specifies the type of information contained in the
+// cookie details.
+enum CocoaCookieDetailsType {
+  // Represents grouping of cookie data, used in the cookie tree.
+  kCocoaCookieDetailsTypeFolder = 0,
+
+  // Detailed information about a cookie, used both in the cookie
+  // tree and the cookie prompt.
+  kCocoaCookieDetailsTypeCookie,
+
+  // Detailed information about a web database used for
+  // display in the cookie tree.
+  kCocoaCookieDetailsTypeTreeDatabase,
+
+  // Detailed information about local storage used for
+  // display in the cookie tree.
+  kCocoaCookieDetailsTypeTreeLocalStorage,
+
+  // Detailed information about an appcache used for display in the
+  // cookie tree.
+  kCocoaCookieDetailsTypeTreeAppCache,
+
+  // Detailed information about an IndexedDB used for display in the
+  // cookie tree.
+  kCocoaCookieDetailsTypeTreeIndexedDB,
+
+  // Detailed information about a web database used for display
+  // in the cookie prompt dialog.
+  kCocoaCookieDetailsTypePromptDatabase,
+
+  // Detailed information about local storage used for display
+  // in the cookie prompt dialog.
+  kCocoaCookieDetailsTypePromptLocalStorage,
+
+  // Detailed information about app caches used for display
+  // in the cookie prompt dialog.
+  kCocoaCookieDetailsTypePromptAppCache
+};
+
+// This class contains all of the information that can be displayed in
+// a cookie details view. Because the view uses bindings to display
+// the cookie information, the methods that provide that information
+// for display must be implemented directly on this class and not on any
+// of its subclasses.
+// If this system is rewritten to not use bindings, this class should be
+// subclassed and specialized, rather than using an enum to determine type.
+@interface CocoaCookieDetails : NSObject {
+ @private
+  CocoaCookieDetailsType type_;
+
+  // Used for type kCocoaCookieDetailsTypeCookie to indicate whether
+  // it should be possible to edit the expiration.
+  BOOL canEditExpiration_;
+
+  // Indicates whether a cookie has an explcit expiration. If not
+  // it will expire with the session.
+  BOOL hasExpiration_;
+
+  // Only set for type kCocoaCookieDetailsTypeCookie.
+  scoped_nsobject<NSString> content_;
+  scoped_nsobject<NSString> path_;
+  scoped_nsobject<NSString> sendFor_;
+  // Stringifed dates.
+  scoped_nsobject<NSString> expires_;
+
+  // Only set for type kCocoaCookieDetailsTypeCookie and
+  // kCocoaCookieDetailsTypeTreeAppCache nodes.
+  scoped_nsobject<NSString> created_;
+
+  // Only set for types kCocoaCookieDetailsTypeCookie, and
+  // kCocoaCookieDetailsTypePromptDatabase nodes.
+  scoped_nsobject<NSString> name_;
+
+  // Only set for type kCocoaCookieDetailsTypeTreeLocalStorage,
+  // kCocoaCookieDetailsTypeTreeDatabase,
+  // kCocoaCookieDetailsTypePromptDatabase,
+  // kCocoaCookieDetailsTypeTreeIndexedDB, and
+  // kCocoaCookieDetailsTypeTreeAppCache nodes.
+  scoped_nsobject<NSString> fileSize_;
+
+  // Only set for types kCocoaCookieDetailsTypeTreeLocalStorage,
+  // kCocoaCookieDetailsTypeTreeDatabase, and
+  // kCocoaCookieDetailsTypeTreeIndexedDB nodes.
+  scoped_nsobject<NSString> lastModified_;
+
+  // Only set for type kCocoaCookieDetailsTypeTreeAppCache nodes.
+  scoped_nsobject<NSString> lastAccessed_;
+
+  // Only set for type kCocoaCookieDetailsTypeCookie,
+  // kCocoaCookieDetailsTypePromptDatabase,
+  // kCocoaCookieDetailsTypePromptLocalStorage, and
+  // kCocoaCookieDetailsTypeTreeIndexedDB nodes.
+  scoped_nsobject<NSString> domain_;
+
+  // Only set for type kCocoaCookieTreeNodeTypeDatabaseStorage and
+  // kCocoaCookieDetailsTypePromptDatabase nodes.
+  scoped_nsobject<NSString> databaseDescription_;
+
+  // Only set for type kCocoaCookieDetailsTypePromptLocalStorage.
+  scoped_nsobject<NSString> localStorageKey_;
+  scoped_nsobject<NSString> localStorageValue_;
+
+  // Only set for type kCocoaCookieDetailsTypeTreeAppCache and
+  // kCocoaCookieDetailsTypePromptAppCache.
+  scoped_nsobject<NSString> manifestURL_;
+}
+
+@property(nonatomic, readonly) BOOL canEditExpiration;
+@property(nonatomic) BOOL hasExpiration;
+@property(nonatomic, readonly) CocoaCookieDetailsType type;
+
+// The following methods are used in the bindings of subviews inside
+// the cookie detail view. Note that the method that tests the
+// visibility of the subview for cookie-specific information has a different
+// polarity than the other visibility testing methods. This ensures that
+// this subview is shown when there is no selection in the cookie tree,
+// because a hidden value of |false| is generated when the key value binding
+// is evaluated through a nil object. The other methods are bound using a
+// |NSNegateBoolean| transformer, so that when there is a empty selection the
+// hidden value is |true|.
+- (BOOL)shouldHideCookieDetailsView;
+- (BOOL)shouldShowLocalStorageTreeDetailsView;
+- (BOOL)shouldShowLocalStoragePromptDetailsView;
+- (BOOL)shouldShowDatabaseTreeDetailsView;
+- (BOOL)shouldShowDatabasePromptDetailsView;
+- (BOOL)shouldShowAppCachePromptDetailsView;
+- (BOOL)shouldShowAppCacheTreeDetailsView;
+- (BOOL)shouldShowIndexedDBTreeDetailsView;
+
+- (NSString*)name;
+- (NSString*)content;
+- (NSString*)domain;
+- (NSString*)path;
+- (NSString*)sendFor;
+- (NSString*)created;
+- (NSString*)expires;
+- (NSString*)fileSize;
+- (NSString*)lastModified;
+- (NSString*)lastAccessed;
+- (NSString*)databaseDescription;
+- (NSString*)localStorageKey;
+- (NSString*)localStorageValue;
+- (NSString*)manifestURL;
+
+// Used for folders in the cookie tree.
+- (id)initAsFolder;
+
+// Used for cookie details in both the cookie tree and the cookie prompt dialog.
+- (id)initWithCookie:(const net::CookieMonster::CanonicalCookie*)treeNode
+              origin:(NSString*)origin
+   canEditExpiration:(BOOL)canEditExpiration;
+
+// Used for database details in the cookie tree.
+- (id)initWithDatabase:
+    (const BrowsingDataDatabaseHelper::DatabaseInfo*)databaseInfo;
+
+// Used for local storage details in the cookie tree.
+- (id)initWithLocalStorage:
+    (const BrowsingDataLocalStorageHelper::LocalStorageInfo*)localStorageInfo;
+
+// Used for database details in the cookie prompt dialog.
+- (id)initWithDatabase:(const std::string&)domain
+          databaseName:(const string16&)databaseName
+   databaseDescription:(const string16&)databaseDescription
+              fileSize:(unsigned long)fileSize;
+
+// -initWithAppCacheInfo: creates a cookie details with the manifest URL plus
+// all of this additional information that is available after an appcache is
+// actually created, including it's creation date, size and last accessed time.
+- (id)initWithAppCacheInfo:(const appcache::AppCacheInfo*)appcacheInfo;
+
+// Used for local storage details in the cookie prompt dialog.
+- (id)initWithLocalStorage:(const std::string&)domain
+                       key:(const string16&)key
+                     value:(const string16&)value;
+
+// -initWithAppCacheManifestURL: is called when the cookie prompt is displayed
+// for an appcache, at that time only the manifest URL of the appcache is known.
+- (id)initWithAppCacheManifestURL:(const std::string&)manifestURL;
+
+// Used for IndexedDB details in the cookie tree.
+- (id)initWithIndexedDBInfo:
+    (const BrowsingDataIndexedDBHelper::IndexedDBInfo*)indexedDB;
+
+// A factory method to create a configured instance given a node from
+// the cookie tree in |treeNode|.
++ (CocoaCookieDetails*)createFromCookieTreeNode:(CookieTreeNode*)treeNode;
+
+@end
+
+// The subpanes of the cookie details view expect to be able to bind to methods
+// through a key path in the form |content.details.xxxx|. This class serves as
+// an adapter that simply wraps a |CocoaCookieDetails| object. An instance of
+// this class is set as the content object for cookie details view's object
+// controller so that key paths are properly resolved through to the
+// |CocoaCookieDetails| object for the cookie prompt.
+@interface CookiePromptContentDetailsAdapter : NSObject {
+ @private
+  scoped_nsobject<CocoaCookieDetails> details_;
+}
+
+- (CocoaCookieDetails*)details;
+
+// The adapter assumes ownership of the details object
+// in its initializer.
+- (id)initWithDetails:(CocoaCookieDetails*)details;
+@end
+
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details.mm b/chrome/browser/ui/cocoa/content_settings/cookie_details.mm
new file mode 100644
index 0000000..6b87412
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details.mm
@@ -0,0 +1,299 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/content_settings/cookie_details.h"
+
+#import "base/i18n/time_formatting.h"
+#include "base/sys_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "webkit/appcache/appcache_service.h"
+
+#pragma mark Cocoa Cookie Details
+
+@implementation CocoaCookieDetails
+
+@synthesize canEditExpiration = canEditExpiration_;
+@synthesize hasExpiration = hasExpiration_;
+@synthesize type = type_;
+
+- (BOOL)shouldHideCookieDetailsView {
+  return type_ != kCocoaCookieDetailsTypeFolder &&
+      type_ != kCocoaCookieDetailsTypeCookie;
+}
+
+- (BOOL)shouldShowLocalStorageTreeDetailsView {
+  return type_ == kCocoaCookieDetailsTypeTreeLocalStorage;
+}
+
+- (BOOL)shouldShowLocalStoragePromptDetailsView {
+  return type_ == kCocoaCookieDetailsTypePromptLocalStorage;
+}
+
+- (BOOL)shouldShowDatabaseTreeDetailsView {
+  return type_ == kCocoaCookieDetailsTypeTreeDatabase;
+}
+
+- (BOOL)shouldShowAppCacheTreeDetailsView {
+  return type_ == kCocoaCookieDetailsTypeTreeAppCache;
+}
+
+- (BOOL)shouldShowDatabasePromptDetailsView {
+  return type_ == kCocoaCookieDetailsTypePromptDatabase;
+}
+
+- (BOOL)shouldShowAppCachePromptDetailsView {
+  return type_ == kCocoaCookieDetailsTypePromptAppCache;
+}
+
+- (BOOL)shouldShowIndexedDBTreeDetailsView {
+  return type_ == kCocoaCookieDetailsTypeTreeIndexedDB;
+}
+
+- (NSString*)name {
+  return name_.get();
+}
+
+- (NSString*)content {
+  return content_.get();
+}
+
+- (NSString*)domain {
+  return domain_.get();
+}
+
+- (NSString*)path {
+  return path_.get();
+}
+
+- (NSString*)sendFor {
+  return sendFor_.get();
+}
+
+- (NSString*)created {
+  return created_.get();
+}
+
+- (NSString*)expires {
+  return expires_.get();
+}
+
+- (NSString*)fileSize {
+  return fileSize_.get();
+}
+
+- (NSString*)lastModified {
+  return lastModified_.get();
+}
+
+- (NSString*)lastAccessed {
+  return lastAccessed_.get();
+}
+
+- (NSString*)databaseDescription {
+  return databaseDescription_.get();
+}
+
+- (NSString*)localStorageKey {
+  return localStorageKey_.get();
+}
+
+- (NSString*)localStorageValue {
+  return localStorageValue_.get();
+}
+
+- (NSString*)manifestURL {
+  return manifestURL_.get();
+}
+
+- (id)initAsFolder {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypeFolder;
+  }
+  return self;
+}
+
+- (id)initWithCookie:(const net::CookieMonster::CanonicalCookie*)cookie
+              origin:(NSString*)origin
+   canEditExpiration:(BOOL)canEditExpiration {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypeCookie;
+    hasExpiration_ = cookie->DoesExpire();
+    canEditExpiration_ = canEditExpiration && hasExpiration_;
+    name_.reset([base::SysUTF8ToNSString(cookie->Name()) retain]);
+    content_.reset([base::SysUTF8ToNSString(cookie->Value()) retain]);
+    path_.reset([base::SysUTF8ToNSString(cookie->Path()) retain]);
+    domain_.reset([origin retain]);
+
+    if (cookie->DoesExpire()) {
+      expires_.reset([base::SysUTF16ToNSString(
+          base::TimeFormatFriendlyDateAndTime(cookie->ExpiryDate())) retain]);
+    } else {
+      expires_.reset([l10n_util::GetNSStringWithFixup(
+          IDS_COOKIES_COOKIE_EXPIRES_SESSION) retain]);
+    }
+
+    created_.reset([base::SysUTF16ToNSString(
+        base::TimeFormatFriendlyDateAndTime(cookie->CreationDate())) retain]);
+
+    if (cookie->IsSecure()) {
+      sendFor_.reset([l10n_util::GetNSStringWithFixup(
+          IDS_COOKIES_COOKIE_SENDFOR_SECURE) retain]);
+    } else {
+      sendFor_.reset([l10n_util::GetNSStringWithFixup(
+          IDS_COOKIES_COOKIE_SENDFOR_ANY) retain]);
+    }
+  }
+  return self;
+}
+
+- (id)initWithDatabase:(const BrowsingDataDatabaseHelper::DatabaseInfo*)
+    databaseInfo {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypeTreeDatabase;
+    canEditExpiration_ = NO;
+    databaseDescription_.reset([base::SysUTF8ToNSString(
+        databaseInfo->description) retain]);
+    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(databaseInfo->size,
+        GetByteDisplayUnits(databaseInfo->size), true)) retain]);
+    lastModified_.reset([base::SysUTF16ToNSString(
+        base::TimeFormatFriendlyDateAndTime(
+            databaseInfo->last_modified)) retain]);
+  }
+  return self;
+}
+
+- (id)initWithLocalStorage:(
+    const BrowsingDataLocalStorageHelper::LocalStorageInfo*)storageInfo {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypeTreeLocalStorage;
+    canEditExpiration_ = NO;
+    domain_.reset([base::SysUTF8ToNSString(storageInfo->origin) retain]);
+    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(storageInfo->size,
+        GetByteDisplayUnits(storageInfo->size), true)) retain]);
+    lastModified_.reset([base::SysUTF16ToNSString(
+        base::TimeFormatFriendlyDateAndTime(
+            storageInfo->last_modified)) retain]);
+  }
+  return self;
+}
+
+- (id)initWithAppCacheInfo:(const appcache::AppCacheInfo*)appcacheInfo {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypeTreeAppCache;
+    canEditExpiration_ = NO;
+    manifestURL_.reset([base::SysUTF8ToNSString(
+        appcacheInfo->manifest_url.spec()) retain]);
+    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(appcacheInfo->size,
+        GetByteDisplayUnits(appcacheInfo->size), true)) retain]);
+    created_.reset([base::SysUTF16ToNSString(
+        base::TimeFormatFriendlyDateAndTime(
+            appcacheInfo->creation_time)) retain]);
+    lastAccessed_.reset([base::SysUTF16ToNSString(
+        base::TimeFormatFriendlyDateAndTime(
+            appcacheInfo->last_access_time)) retain]);
+  }
+  return self;
+}
+
+- (id)initWithDatabase:(const std::string&)domain
+          databaseName:(const string16&)databaseName
+   databaseDescription:(const string16&)databaseDescription
+              fileSize:(unsigned long)fileSize {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypePromptDatabase;
+    canEditExpiration_ = NO;
+    name_.reset([base::SysUTF16ToNSString(databaseName) retain]);
+    domain_.reset([base::SysUTF8ToNSString(domain) retain]);
+    databaseDescription_.reset(
+        [base::SysUTF16ToNSString(databaseDescription) retain]);
+    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(fileSize,
+        GetByteDisplayUnits(fileSize), true)) retain]);
+  }
+  return self;
+}
+
+- (id)initWithLocalStorage:(const std::string&)domain
+                       key:(const string16&)key
+                     value:(const string16&)value {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypePromptLocalStorage;
+    canEditExpiration_ = NO;
+    domain_.reset([base::SysUTF8ToNSString(domain) retain]);
+    localStorageKey_.reset([base::SysUTF16ToNSString(key) retain]);
+    localStorageValue_.reset([base::SysUTF16ToNSString(value) retain]);
+  }
+  return self;
+}
+
+- (id)initWithAppCacheManifestURL:(const std::string&)manifestURL {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypePromptAppCache;
+    canEditExpiration_ = NO;
+    manifestURL_.reset([base::SysUTF8ToNSString(manifestURL) retain]);
+  }
+  return self;
+}
+
+- (id)initWithIndexedDBInfo:
+    (const BrowsingDataIndexedDBHelper::IndexedDBInfo*)indexedDBInfo {
+  if ((self = [super init])) {
+    type_ = kCocoaCookieDetailsTypeTreeIndexedDB;
+    canEditExpiration_ = NO;
+    domain_.reset([base::SysUTF8ToNSString(indexedDBInfo->origin) retain]);
+    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(indexedDBInfo->size,
+        GetByteDisplayUnits(indexedDBInfo->size), true)) retain]);
+    lastModified_.reset([base::SysUTF16ToNSString(
+        base::TimeFormatFriendlyDateAndTime(
+            indexedDBInfo->last_modified)) retain]);
+  }
+  return self;
+}
+
++ (CocoaCookieDetails*)createFromCookieTreeNode:(CookieTreeNode*)treeNode {
+  CookieTreeNode::DetailedInfo info = treeNode->GetDetailedInfo();
+  CookieTreeNode::DetailedInfo::NodeType nodeType = info.node_type;
+  NSString* origin;
+  switch (nodeType) {
+    case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
+      origin = base::SysWideToNSString(info.origin.c_str());
+      return [[[CocoaCookieDetails alloc] initWithCookie:info.cookie
+                                                  origin:origin
+                                       canEditExpiration:NO] autorelease];
+    case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
+      return [[[CocoaCookieDetails alloc]
+          initWithDatabase:info.database_info] autorelease];
+    case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
+      return [[[CocoaCookieDetails alloc]
+          initWithLocalStorage:info.local_storage_info] autorelease];
+    case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
+      return [[[CocoaCookieDetails alloc]
+          initWithAppCacheInfo:info.appcache_info] autorelease];
+    case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
+      return [[[CocoaCookieDetails alloc]
+          initWithIndexedDBInfo:info.indexed_db_info] autorelease];
+    default:
+      return [[[CocoaCookieDetails alloc] initAsFolder] autorelease];
+  }
+}
+
+@end
+
+#pragma mark Content Object Adapter
+
+@implementation CookiePromptContentDetailsAdapter
+
+- (id)initWithDetails:(CocoaCookieDetails*)details {
+  if ((self = [super init])) {
+    details_.reset([details retain]);
+  }
+  return self;
+}
+
+- (CocoaCookieDetails*)details {
+  return details_.get();
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm b/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm
new file mode 100644
index 0000000..4169c2a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details_unittest.mm
@@ -0,0 +1,247 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/ui/cocoa/content_settings/cookie_details.h"
+#include "googleurl/src/gurl.h"
+#import "testing/gtest_mac.h"
+
+namespace {
+
+class CookiesDetailsTest : public CocoaTest {
+};
+
+TEST_F(CookiesDetailsTest, CreateForFolder) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  details.reset([[CocoaCookieDetails alloc] initAsFolder]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeFolder);
+}
+
+TEST_F(CookiesDetailsTest, CreateForCookie) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  GURL url("http://chromium.org");
+  std::string cookieLine(
+      "PHPSESSID=0123456789abcdef0123456789abcdef; path=/");
+  net::CookieMonster::ParsedCookie pc(cookieLine);
+  net::CookieMonster::CanonicalCookie cookie(url, pc);
+  NSString* origin = base::SysUTF8ToNSString("http://chromium.org");
+  details.reset([[CocoaCookieDetails alloc] initWithCookie:&cookie
+                                                    origin:origin
+                                         canEditExpiration:NO]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeCookie);
+  EXPECT_NSEQ(@"PHPSESSID", [details.get() name]);
+  EXPECT_NSEQ(@"0123456789abcdef0123456789abcdef",
+      [details.get() content]);
+  EXPECT_NSEQ(@"http://chromium.org", [details.get() domain]);
+  EXPECT_NSEQ(@"/", [details.get() path]);
+  EXPECT_NSNE(@"", [details.get() lastModified]);
+  EXPECT_NSNE(@"", [details.get() created]);
+  EXPECT_NSNE(@"", [details.get() sendFor]);
+
+  EXPECT_FALSE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForTreeDatabase) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  std::string host("http://chromium.org");
+  std::string database_name("sassolungo");
+  std::string origin_identifier("dolomites");
+  std::string description("a great place to climb");
+  int64 size = 1234;
+  base::Time last_modified = base::Time::Now();
+  BrowsingDataDatabaseHelper::DatabaseInfo info(host, database_name,
+      origin_identifier, description, host, size, last_modified);
+  details.reset([[CocoaCookieDetails alloc] initWithDatabase:&info]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeDatabase);
+  EXPECT_NSEQ(@"a great place to climb", [details.get() databaseDescription]);
+  EXPECT_NSEQ(@"1234 B", [details.get() fileSize]);
+  EXPECT_NSNE(@"", [details.get() lastModified]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForTreeLocalStorage) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  std::string protocol("http");
+  std::string host("chromium.org");
+  unsigned short port = 80;
+  std::string database_identifier("id");
+  std::string origin("chromium.org");
+  FilePath file_path(FILE_PATH_LITERAL("/"));
+  int64 size = 1234;
+  base::Time last_modified = base::Time::Now();
+  BrowsingDataLocalStorageHelper::LocalStorageInfo info(protocol, host, port,
+      database_identifier, origin, file_path, size, last_modified);
+  details.reset([[CocoaCookieDetails alloc] initWithLocalStorage:&info]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeLocalStorage);
+  EXPECT_NSEQ(@"chromium.org", [details.get() domain]);
+  EXPECT_NSEQ(@"1234 B", [details.get() fileSize]);
+  EXPECT_NSNE(@"", [details.get() lastModified]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForTreeAppCache) {
+  scoped_nsobject<CocoaCookieDetails> details;
+
+  GURL url("http://chromium.org/stuff.manifest");
+  appcache::AppCacheInfo info;
+  info.creation_time = base::Time::Now();
+  info.last_update_time = base::Time::Now();
+  info.last_access_time = base::Time::Now();
+  info.size=2678;
+  info.manifest_url = url;
+  details.reset([[CocoaCookieDetails alloc] initWithAppCacheInfo:&info]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeAppCache);
+  EXPECT_NSEQ(@"http://chromium.org/stuff.manifest",
+              [details.get() manifestURL]);
+  EXPECT_NSEQ(@"2678 B", [details.get() fileSize]);
+  EXPECT_NSNE(@"", [details.get() lastAccessed]);
+  EXPECT_NSNE(@"", [details.get() created]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForTreeIndexedDB) {
+  scoped_nsobject<CocoaCookieDetails> details;
+
+  std::string protocol("http");
+  std::string host("moose.org");
+  unsigned short port = 80;
+  std::string database_identifier("id");
+  std::string origin("moose.org");
+  FilePath file_path(FILE_PATH_LITERAL("/"));
+  int64 size = 1234;
+  base::Time last_modified = base::Time::Now();
+  BrowsingDataIndexedDBHelper::IndexedDBInfo info(protocol,
+                                                  host,
+                                                  port,
+                                                  database_identifier,
+                                                  origin,
+                                                  file_path,
+                                                  size,
+                                                  last_modified);
+
+  details.reset([[CocoaCookieDetails alloc] initWithIndexedDBInfo:&info]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeIndexedDB);
+  EXPECT_NSEQ(@"moose.org", [details.get() domain]);
+  EXPECT_NSEQ(@"1234 B", [details.get() fileSize]);
+  EXPECT_NSNE(@"", [details.get() lastModified]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForPromptDatabase) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  std::string domain("chromium.org");
+  string16 name(base::SysNSStringToUTF16(@"wicked_name"));
+  string16 desc(base::SysNSStringToUTF16(@"desc"));
+  details.reset([[CocoaCookieDetails alloc] initWithDatabase:domain
+                                                databaseName:name
+                                         databaseDescription:desc
+                                                    fileSize:94]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypePromptDatabase);
+  EXPECT_NSEQ(@"chromium.org", [details.get() domain]);
+  EXPECT_NSEQ(@"wicked_name", [details.get() name]);
+  EXPECT_NSEQ(@"desc", [details.get() databaseDescription]);
+  EXPECT_NSEQ(@"94 B", [details.get() fileSize]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForPromptLocalStorage) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  std::string domain("chromium.org");
+  string16 key(base::SysNSStringToUTF16(@"testKey"));
+  string16 value(base::SysNSStringToUTF16(@"testValue"));
+  details.reset([[CocoaCookieDetails alloc] initWithLocalStorage:domain
+                                                             key:key
+                                                           value:value]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypePromptLocalStorage);
+  EXPECT_NSEQ(@"chromium.org", [details.get() domain]);
+  EXPECT_NSEQ(@"testKey", [details.get() localStorageKey]);
+  EXPECT_NSEQ(@"testValue", [details.get() localStorageValue]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+TEST_F(CookiesDetailsTest, CreateForPromptAppCache) {
+  scoped_nsobject<CocoaCookieDetails> details;
+  std::string manifestURL("http://html5demos.com/html5demo.manifest");
+  details.reset([[CocoaCookieDetails alloc]
+      initWithAppCacheManifestURL:manifestURL.c_str()]);
+
+  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypePromptAppCache);
+  EXPECT_NSEQ(@"http://html5demos.com/html5demo.manifest",
+              [details.get() manifestURL]);
+
+  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
+  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
+  EXPECT_TRUE([details.get() shouldShowAppCachePromptDetailsView]);
+}
+
+}
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.h b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.h
new file mode 100644
index 0000000..89a1354
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.h
@@ -0,0 +1,56 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "net/base/cookie_monster.h"
+
+@class CocoaCookieTreeNode;
+@class GTMUILocalizerAndLayoutTweaker;
+
+// Controller for the view that displays the details of a cookie,
+// used both in the cookie prompt dialog as well as the
+// show cookies preference sheet of content settings preferences.
+@interface CookieDetailsViewController : NSViewController {
+ @private
+  // Allows direct access to the object controller for
+  // the displayed cookie information.
+  IBOutlet NSObjectController* objectController_;
+
+  // This explicit reference to the layout tweaker is
+  // required because it's necessary to reformat the view when
+  // the content object changes, since the content object may
+  // alter the widths of some of the fields displayed in the view.
+  IBOutlet GTMUILocalizerAndLayoutTweaker* tweaker_;
+}
+
+@property(nonatomic, readonly) BOOL hasExpiration;
+
+- (id)init;
+
+// Configures the cookie detail view that is managed by the controller
+// to display the information about a single cookie, the information
+// for which is explicitly passed in the parameter |content|.
+- (void)setContentObject:(id)content;
+
+// Adjust the size of the view to exactly fix the information text fields
+// that are visible inside it.
+- (void)shrinkViewToFit;
+
+// Called by the cookie tree dialog to establish a binding between
+// the the detail view's object controller and the tree controller.
+// This binding allows the cookie tree to use the detail view unmodified.
+- (void)configureBindingsForTreeController:(NSTreeController*)controller;
+
+// Action sent by the expiration date popup when the user
+// selects the menu item "When I close my browser".
+- (IBAction)setCookieDoesntHaveExplicitExpiration:(id)sender;
+
+// Action sent by the expiration date popup when the user
+// selects the menu item with an explicit date/time of expiration.
+- (IBAction)setCookieHasExplicitExpiration:(id)sender;
+
+@end
+
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.mm b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.mm
new file mode 100644
index 0000000..73e570f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.mm
@@ -0,0 +1,110 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.h"
+
+#import "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+static const int kExtraMarginBelowWhenExpirationEditable = 5;
+}
+
+#pragma mark View Controller
+
+@implementation CookieDetailsViewController
+@dynamic hasExpiration;
+
+- (id)init {
+  return [super initWithNibName:@"CookieDetailsView"
+                         bundle:base::mac::MainAppBundle()];
+}
+
+- (void)awakeFromNib {
+  DCHECK(objectController_);
+}
+
+// Finds and returns the y offset of the lowest-most non-hidden
+// text field in the view. This is used to shrink the view
+// appropriately so that it just fits its visible content.
+- (void)getLowestLabelVerticalPosition:(NSView*)view
+                   lowestLabelPosition:(float&)lowestLabelPosition {
+  if (![view isHidden]) {
+    if ([view isKindOfClass:[NSTextField class]]) {
+      NSRect frame = [view frame];
+      if (frame.origin.y < lowestLabelPosition) {
+        lowestLabelPosition = frame.origin.y;
+      }
+    }
+    for (NSView* subview in [view subviews]) {
+      [self getLowestLabelVerticalPosition:subview
+                       lowestLabelPosition:lowestLabelPosition];
+    }
+  }
+}
+
+- (void)setContentObject:(id)content {
+  // Make sure the view is loaded before we set the content object,
+  // otherwise, the KVO notifications to update the content don't
+  // reach the view and all of the detail values are default
+  // strings.
+  NSView* view = [self view];
+
+  [objectController_ setValue:content forKey:@"content"];
+
+  // View needs to be re-tweaked after setting the content object,
+  // since the expiration date may have changed, changing the
+  // size of the expiration popup.
+  [tweaker_ tweakUI:view];
+}
+
+- (void)shrinkViewToFit {
+  // Adjust the information pane to be exactly the right size
+  // to hold the visible text information fields.
+  NSView* view = [self view];
+  NSRect frame = [view frame];
+  float lowestLabelPosition = frame.origin.y + frame.size.height;
+  [self getLowestLabelVerticalPosition:view
+                   lowestLabelPosition:lowestLabelPosition];
+  float verticalDelta = lowestLabelPosition - frame.origin.y;
+
+  // Popup menu for the expiration is taller than the plain
+  // text, give it some more room.
+  if ([[[objectController_ content] details] canEditExpiration]) {
+    verticalDelta -= kExtraMarginBelowWhenExpirationEditable;
+  }
+
+  frame.origin.y += verticalDelta;
+  frame.size.height -= verticalDelta;
+  [[self view] setFrame:frame];
+}
+
+- (void)configureBindingsForTreeController:(NSTreeController*)treeController {
+  // There seems to be a bug in the binding logic that it's not possible
+  // to bind to the selection of the tree controller, the bind seems to
+  // require an additional path segment in the key, thus the use of
+  // selection.self rather than just selection below.
+  [objectController_ bind:@"contentObject"
+                 toObject:treeController
+              withKeyPath:@"selection.self"
+                  options:nil];
+}
+
+- (IBAction)setCookieDoesntHaveExplicitExpiration:(id)sender {
+  [[[objectController_ content] details] setHasExpiration:NO];
+}
+
+- (IBAction)setCookieHasExplicitExpiration:(id)sender {
+  [[[objectController_ content] details] setHasExpiration:YES];
+}
+
+- (BOOL)hasExpiration {
+  return [[[objectController_ content] details] hasExpiration];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm
new file mode 100644
index 0000000..0965f7d
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller_unittest.mm
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/ui/cocoa/content_settings/cookie_details.h"
+#include "chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.h"
+
+namespace {
+
+class CookieDetailsViewControllerTest : public CocoaTest {
+};
+
+static CocoaCookieDetails* CreateTestCookieDetails(BOOL canEditExpiration) {
+  GURL url("http://chromium.org");
+  std::string cookieLine(
+      "PHPSESSID=0123456789abcdef0123456789abcdef; path=/");
+  net::CookieMonster::ParsedCookie pc(cookieLine);
+  net::CookieMonster::CanonicalCookie cookie(url, pc);
+  NSString* origin = base::SysUTF8ToNSString("http://chromium.org");
+  CocoaCookieDetails* details = [CocoaCookieDetails alloc];
+  [details initWithCookie:&cookie
+                   origin:origin
+        canEditExpiration:canEditExpiration];
+  return [details autorelease];
+}
+
+static CookiePromptContentDetailsAdapter* CreateCookieTestContent(
+    BOOL canEditExpiration) {
+  CocoaCookieDetails* details = CreateTestCookieDetails(canEditExpiration);
+  return [[[CookiePromptContentDetailsAdapter alloc] initWithDetails:details]
+      autorelease];
+}
+
+static CocoaCookieDetails* CreateTestDatabaseDetails() {
+  std::string domain("chromium.org");
+  string16 name(base::SysNSStringToUTF16(@"wicked_name"));
+  string16 desc(base::SysNSStringToUTF16(@"wicked_desc"));
+  CocoaCookieDetails* details = [CocoaCookieDetails alloc];
+  [details initWithDatabase:domain
+               databaseName:name
+        databaseDescription:desc
+                   fileSize:2222];
+  return [details autorelease];
+}
+
+static CookiePromptContentDetailsAdapter* CreateDatabaseTestContent() {
+  CocoaCookieDetails* details = CreateTestDatabaseDetails();
+  return [[[CookiePromptContentDetailsAdapter alloc] initWithDetails:details]
+          autorelease];
+}
+
+TEST_F(CookieDetailsViewControllerTest, Create) {
+  scoped_nsobject<CookieDetailsViewController> detailsViewController(
+      [[CookieDetailsViewController alloc] init]);
+}
+
+TEST_F(CookieDetailsViewControllerTest, ShrinkToFit) {
+  scoped_nsobject<CookieDetailsViewController> detailsViewController(
+      [[CookieDetailsViewController alloc] init]);
+  scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
+      [CreateDatabaseTestContent() retain]);
+  [detailsViewController.get() setContentObject:adapter.get()];
+  NSRect beforeFrame = [[detailsViewController.get() view] frame];
+  [detailsViewController.get() shrinkViewToFit];
+  NSRect afterFrame = [[detailsViewController.get() view] frame];
+
+  EXPECT_TRUE(afterFrame.size.height < beforeFrame.size.width);
+}
+
+TEST_F(CookieDetailsViewControllerTest, ExpirationEditability) {
+  scoped_nsobject<CookieDetailsViewController> detailsViewController(
+      [[CookieDetailsViewController alloc] init]);
+  [detailsViewController view];
+  scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
+      [CreateCookieTestContent(YES) retain]);
+  [detailsViewController.get() setContentObject:adapter.get()];
+
+  EXPECT_FALSE([detailsViewController.get() hasExpiration]);
+  [detailsViewController.get() setCookieHasExplicitExpiration:adapter.get()];
+  EXPECT_TRUE([detailsViewController.get() hasExpiration]);
+  [detailsViewController.get()
+      setCookieDoesntHaveExplicitExpiration:adapter.get()];
+  EXPECT_FALSE([detailsViewController.get() hasExpiration]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h
new file mode 100644
index 0000000..175a1b5
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h
@@ -0,0 +1,37 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "chrome/browser/ui/cocoa/content_settings/cookie_details.h"
+
+@interface CocoaCookieTreeNode : NSObject {
+  scoped_nsobject<NSString> title_;
+  scoped_nsobject<NSMutableArray> children_;
+  scoped_nsobject<CocoaCookieDetails> details_;
+  CookieTreeNode* treeNode_;  // weak
+}
+
+// Designated initializer.
+- (id)initWithNode:(CookieTreeNode*)node;
+
+// Re-sets all the members of the node based on |treeNode_|.
+- (void)rebuild;
+
+// Common getters..
+- (NSString*)title;
+- (CocoaCookieDetailsType)nodeType;
+- (ui::TreeModelNode*)treeNode;
+
+// |-mutableChildren| exists so that the CookiesTreeModelObserverBridge can
+// operate on the children. Note that this lazily creates children.
+- (NSMutableArray*)mutableChildren;
+- (NSArray*)children;
+- (BOOL)isLeaf;
+
+- (CocoaCookieDetails*)details;
+
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm
new file mode 100644
index 0000000..e6a08bd
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/cookie_tree_node.mm
@@ -0,0 +1,73 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h"
+
+#include "base/sys_string_conversions.h"
+
+@implementation CocoaCookieTreeNode
+
+- (id)initWithNode:(CookieTreeNode*)node {
+  if ((self = [super init])) {
+    DCHECK(node);
+    treeNode_ = node;
+    [self rebuild];
+  }
+  return self;
+}
+
+- (void)rebuild {
+  title_.reset([base::SysUTF16ToNSString(treeNode_->GetTitle()) retain]);
+  children_.reset();
+  // The tree node assumes ownership of the cookie details object
+  details_.reset([[CocoaCookieDetails createFromCookieTreeNode:(treeNode_)]
+      retain]);
+}
+
+- (NSString*)title {
+  return title_.get();
+}
+
+- (CocoaCookieDetailsType)nodeType {
+  return [details_.get() type];
+}
+
+- (ui::TreeModelNode*)treeNode {
+  return treeNode_;
+}
+
+- (NSMutableArray*)mutableChildren {
+  if (!children_.get()) {
+    const int childCount = treeNode_->GetChildCount();
+    children_.reset([[NSMutableArray alloc] initWithCapacity:childCount]);
+    for (int i = 0; i < childCount; ++i) {
+      CookieTreeNode* child = treeNode_->GetChild(i);
+      scoped_nsobject<CocoaCookieTreeNode> childNode(
+          [[CocoaCookieTreeNode alloc] initWithNode:child]);
+      [children_ addObject:childNode.get()];
+    }
+  }
+  return children_.get();
+}
+
+- (NSArray*)children {
+  return [self mutableChildren];
+}
+
+- (BOOL)isLeaf {
+  return [self nodeType] != kCocoaCookieDetailsTypeFolder;
+};
+
+- (NSString*)description {
+  NSString* format =
+      @"<CocoaCookieTreeNode @ %p (title=%@, nodeType=%d, childCount=%u)";
+  return [NSString stringWithFormat:format, self, [self title],
+      [self nodeType], [[self children] count]];
+}
+
+- (CocoaCookieDetails*)details {
+  return details_;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.h b/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.h
similarity index 100%
rename from chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.h
rename to chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.h
diff --git a/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.mm b/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.mm
new file mode 100644
index 0000000..b78b269
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.mm
@@ -0,0 +1,125 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.h"
+
+#include "base/logging.h"
+#import "base/mac/mac_util.h"
+#import "base/scoped_nsobject.h"
+#include "base/sys_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/models/table_model_observer.h"
+
+@interface SimpleContentExceptionsWindowController (Private)
+- (id)initWithTableModel:(RemoveRowsTableModel*)model;
+@end
+
+namespace  {
+
+const CGFloat kButtonBarHeight = 35.0;
+
+SimpleContentExceptionsWindowController* g_exceptionWindow = nil;
+
+}  // namespace
+
+@implementation SimpleContentExceptionsWindowController
+
++ (id)controllerWithTableModel:(RemoveRowsTableModel*)model {
+  if (!g_exceptionWindow) {
+    g_exceptionWindow = [[SimpleContentExceptionsWindowController alloc]
+        initWithTableModel:model];
+  }
+  return g_exceptionWindow;
+}
+
+- (id)initWithTableModel:(RemoveRowsTableModel*)model {
+  NSString* nibpath = [base::mac::MainAppBundle()
+      pathForResource:@"SimpleContentExceptionsWindow"
+               ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    model_.reset(model);
+
+    // TODO(thakis): autoremember window rect.
+    // TODO(thakis): sorting support.
+  }
+  return self;
+}
+
+- (void)awakeFromNib {
+  DCHECK([self window]);
+  DCHECK_EQ(self, [[self window] delegate]);
+  DCHECK(tableView_);
+  DCHECK(arrayController_);
+
+  CGFloat minWidth = [[removeButton_ superview] bounds].size.width +
+                     [[doneButton_ superview] bounds].size.width;
+  [[self window] setMinSize:NSMakeSize(minWidth,
+                                       [[self window] minSize].height)];
+  NSDictionary* columns = [NSDictionary dictionaryWithObjectsAndKeys:
+      [NSNumber numberWithInt:IDS_EXCEPTIONS_HOSTNAME_HEADER], @"hostname",
+      [NSNumber numberWithInt:IDS_EXCEPTIONS_ACTION_HEADER], @"action",
+      nil];
+  [arrayController_ bindToTableModel:model_.get()
+                         withColumns:columns
+                    groupTitleColumn:@"hostname"];
+}
+
+- (void)setMinWidth:(CGFloat)minWidth {
+  NSWindow* window = [self window];
+  [window setMinSize:NSMakeSize(minWidth, [window minSize].height)];
+  if ([window frame].size.width < minWidth) {
+    NSRect frame = [window frame];
+    frame.size.width = minWidth;
+    [window setFrame:frame display:NO];
+  }
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+  g_exceptionWindow = nil;
+  [self autorelease];
+}
+
+// Let esc close the window.
+- (void)cancel:(id)sender {
+  [self closeSheet:self];
+}
+
+- (void)keyDown:(NSEvent*)event {
+  NSString* chars = [event charactersIgnoringModifiers];
+  if ([chars length] == 1) {
+    switch ([chars characterAtIndex:0]) {
+      case NSDeleteCharacter:
+      case NSDeleteFunctionKey:
+        // Delete deletes.
+        if ([[tableView_ selectedRowIndexes] count] > 0)
+          [arrayController_ remove:event];
+        return;
+    }
+  }
+  [super keyDown:event];
+}
+
+- (void)attachSheetTo:(NSWindow*)window {
+  [NSApp beginSheet:[self window]
+     modalForWindow:window
+      modalDelegate:self
+     didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
+        contextInfo:nil];
+}
+
+- (void)sheetDidEnd:(NSWindow*)sheet
+         returnCode:(NSInteger)returnCode
+        contextInfo:(void*)context {
+  [sheet close];
+  [sheet orderOut:self];
+}
+
+- (IBAction)closeSheet:(id)sender {
+  [NSApp endSheet:[self window]];
+}
+
+
+@end
diff --git a/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller_unittest.mm b/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller_unittest.mm
new file mode 100644
index 0000000..ec5b2f5
--- /dev/null
+++ b/chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller_unittest.mm
@@ -0,0 +1,94 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.h"
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
+#include "chrome/browser/plugin_exceptions_table_model.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface SimpleContentExceptionsWindowController (Testing)
+
+@property(readonly, nonatomic) TableModelArrayController* arrayController;
+
+@end
+
+@implementation SimpleContentExceptionsWindowController (Testing)
+
+- (TableModelArrayController*)arrayController {
+  return arrayController_;
+}
+
+@end
+
+
+namespace {
+
+class SimpleContentExceptionsWindowControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    TestingProfile* profile = browser_helper_.profile();
+    geolocation_settings_ = new GeolocationContentSettingsMap(profile);
+    content_settings_ = new HostContentSettingsMap(profile);
+  }
+
+  SimpleContentExceptionsWindowController* GetController() {
+    GeolocationExceptionsTableModel* model =  // Freed by window controller.
+        new GeolocationExceptionsTableModel(geolocation_settings_.get());
+    id controller = [SimpleContentExceptionsWindowController
+        controllerWithTableModel:model];
+    [controller showWindow:nil];
+    return controller;
+  }
+
+  void ClickRemoveAll(SimpleContentExceptionsWindowController* controller) {
+    [controller.arrayController removeAll:nil];
+  }
+
+ protected:
+  BrowserTestHelper browser_helper_;
+  scoped_refptr<GeolocationContentSettingsMap> geolocation_settings_;
+  scoped_refptr<HostContentSettingsMap> content_settings_;
+};
+
+TEST_F(SimpleContentExceptionsWindowControllerTest, Construction) {
+  GeolocationExceptionsTableModel* model =  // Freed by window controller.
+      new GeolocationExceptionsTableModel(geolocation_settings_.get());
+  SimpleContentExceptionsWindowController* controller =
+      [SimpleContentExceptionsWindowController controllerWithTableModel:model];
+  [controller showWindow:nil];
+  [controller close];  // Should autorelease.
+}
+
+TEST_F(SimpleContentExceptionsWindowControllerTest, ShowPluginExceptions) {
+  PluginExceptionsTableModel* model =  // Freed by window controller.
+      new PluginExceptionsTableModel(content_settings_.get(), NULL);
+  SimpleContentExceptionsWindowController* controller =
+      [SimpleContentExceptionsWindowController controllerWithTableModel:model];
+  [controller showWindow:nil];
+  [controller close];  // Should autorelease.
+}
+
+TEST_F(SimpleContentExceptionsWindowControllerTest, AddExistingEditAdd) {
+  geolocation_settings_->SetContentSetting(
+      GURL("http://myhost"), GURL(), CONTENT_SETTING_BLOCK);
+
+  SimpleContentExceptionsWindowController* controller = GetController();
+  ClickRemoveAll(controller);
+
+  [controller close];
+
+  EXPECT_EQ(0u, geolocation_settings_->GetAllOriginsSettings().size());
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/content_settings_dialog_controller.mm b/chrome/browser/ui/cocoa/content_settings_dialog_controller.mm
deleted file mode 100644
index 1fb432e..0000000
--- a/chrome/browser/ui/cocoa/content_settings_dialog_controller.mm
+++ /dev/null
@@ -1,646 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/content_settings_dialog_controller.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include "app/l10n_util.h"
-#include "base/command_line.h"
-#include "base/mac/mac_util.h"
-#import "chrome/browser/content_settings/content_settings_details.h"
-#import "chrome/browser/content_settings/host_content_settings_map.h"
-#import "chrome/browser/geolocation/geolocation_content_settings_map.h"
-#import "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
-#import "chrome/browser/notifications/desktop_notification_service.h"
-#import "chrome/browser/notifications/notification_exceptions_table_model.h"
-#include "chrome/browser/plugin_exceptions_table_model.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#import "chrome/browser/ui/cocoa/content_exceptions_window_controller.h"
-#import "chrome/browser/ui/cocoa/cookies_window_controller.h"
-#import "chrome/browser/ui/cocoa/l10n_util.h"
-#import "chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.h"
-#import "chrome/browser/ui/cocoa/tab_view_picker_table.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "grit/locale_settings.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Stores the currently visible content settings dialog, if any.
-ContentSettingsDialogController* g_instance = nil;
-
-}  // namespace
-
-
-@interface ContentSettingsDialogController(Private)
-- (id)initWithProfile:(Profile*)profile;
-- (void)selectTab:(ContentSettingsType)settingsType;
-- (void)showExceptionsForType:(ContentSettingsType)settingsType;
-
-// Callback when preferences are changed. |prefName| is the name of the
-// pref that has changed.
-- (void)prefChanged:(const std::string&)prefName;
-
-// Callback when content settings are changed.
-- (void)contentSettingsChanged:(ContentSettingsDetails*)details;
-
-@end
-
-namespace ContentSettingsDialogControllerInternal {
-
-// A C++ class registered for changes in preferences.
-class PrefObserverBridge : public NotificationObserver {
- public:
-  PrefObserverBridge(ContentSettingsDialogController* controller)
-      : controller_(controller), disabled_(false) {}
-
-  virtual ~PrefObserverBridge() {}
-
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    if (disabled_)
-      return;
-
-    // This is currently used by most notifications.
-    if (type == NotificationType::PREF_CHANGED) {
-      std::string* detail = Details<std::string>(details).ptr();
-      if (detail)
-        [controller_ prefChanged:*detail];
-    }
-
-    // This is sent when the "is managed" state changes.
-    // TODO(markusheintz): Move all content settings to this notification.
-    if (type == NotificationType::CONTENT_SETTINGS_CHANGED) {
-      ContentSettingsDetails* settings_details =
-          Details<ContentSettingsDetails>(details).ptr();
-      [controller_ contentSettingsChanged:settings_details];
-    }
-  }
-
-  void SetDisabled(bool disabled) {
-    disabled_ = disabled;
-  }
-
- private:
-  ContentSettingsDialogController* controller_;  // weak, owns us
-  bool disabled_;  // true if notifications should be ignored.
-};
-
-// A C++ utility class to disable notifications for PrefsObserverBridge.
-// The intended usage is to create this on the stack.
-class PrefObserverDisabler {
- public:
-  PrefObserverDisabler(PrefObserverBridge *bridge) : bridge_(bridge) {
-    bridge_->SetDisabled(true);
-  }
-
-  ~PrefObserverDisabler() {
-    bridge_->SetDisabled(false);
-  }
-
- private:
-  PrefObserverBridge *bridge_;
-};
-
-}  // ContentSettingsDialogControllerInternal
-
-@implementation ContentSettingsDialogController
-
-+ (id)showContentSettingsForType:(ContentSettingsType)settingsType
-                         profile:(Profile*)profile {
-  profile = profile->GetOriginalProfile();
-  if (!g_instance)
-    g_instance = [[self alloc] initWithProfile:profile];
-
-  // The code doesn't expect multiple profiles. Check that support for that
-  // hasn't been added.
-  DCHECK(g_instance->profile_ == profile);
-
-  // Select desired tab.
-  if (settingsType == CONTENT_SETTINGS_TYPE_DEFAULT) {
-    // Remember the last visited page from local state.
-    int value = g_instance->lastSelectedTab_.GetValue();
-    if (value >= 0 && value < CONTENT_SETTINGS_NUM_TYPES)
-      settingsType = static_cast<ContentSettingsType>(value);
-    if (settingsType == CONTENT_SETTINGS_TYPE_DEFAULT)
-      settingsType = CONTENT_SETTINGS_TYPE_COOKIES;
-  }
-  // TODO(thakis): Autosave window pos.
-
-  [g_instance selectTab:settingsType];
-  [g_instance showWindow:nil];
-  [g_instance closeExceptionsSheet];
-  return g_instance;
-}
-
-- (id)initWithProfile:(Profile*)profile {
-  DCHECK(profile);
-  NSString* nibpath =
-      [base::mac::MainAppBundle() pathForResource:@"ContentSettings"
-                                          ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    profile_ = profile;
-
-    observer_.reset(
-        new ContentSettingsDialogControllerInternal::PrefObserverBridge(self));
-    clearSiteDataOnExit_.Init(prefs::kClearSiteDataOnExit,
-                              profile_->GetPrefs(), observer_.get());
-
-    // Manually observe notifications for preferences that are grouped in
-    // the HostContentSettingsMap or GeolocationContentSettingsMap.
-    PrefService* prefs = profile_->GetPrefs();
-    registrar_.Init(prefs);
-    registrar_.Add(prefs::kBlockThirdPartyCookies, observer_.get());
-    registrar_.Add(prefs::kBlockNonsandboxedPlugins, observer_.get());
-    registrar_.Add(prefs::kDefaultContentSettings, observer_.get());
-    registrar_.Add(prefs::kGeolocationDefaultContentSetting, observer_.get());
-
-    // We don't need to observe changes in this value.
-    lastSelectedTab_.Init(prefs::kContentSettingsWindowLastTabIndex,
-                          profile_->GetPrefs(), NULL);
-  }
-  return self;
-}
-
-- (void)closeExceptionsSheet {
-  NSWindow* attachedSheet = [[self window] attachedSheet];
-  if (attachedSheet) {
-    [NSApp endSheet:attachedSheet];
-  }
-}
-
-- (void)awakeFromNib {
-  DCHECK([self window]);
-  DCHECK(tabView_);
-  DCHECK(tabViewPicker_);
-  DCHECK_EQ(self, [[self window] delegate]);
-
-  // Adapt views to potentially long localized strings.
-  CGFloat windowDelta = 0;
-  for (NSTabViewItem* tab in [tabView_ tabViewItems]) {
-    NSArray* subviews = [[tab view] subviews];
-    windowDelta = MAX(windowDelta,
-                      cocoa_l10n_util::VerticallyReflowGroup(subviews));
-
-    for (NSView* view in subviews) {
-      // Since the tab pane is in a horizontal resizer in IB, it's convenient
-      // to give all the subviews flexible width so that their sizes are
-      // autoupdated in IB. However, in chrome, the subviews shouldn't have
-      // flexible widths as this looks weird.
-      [view setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
-    }
-  }
-
-  NSString* label =
-      l10n_util::GetNSStringWithFixup(IDS_CONTENT_SETTINGS_FEATURES_LABEL);
-  label = [label stringByReplacingOccurrencesOfString:@":" withString:@""];
-  [tabViewPicker_ setHeading:label];
-
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableClickToPlay)) {
-    // The |pluginsEnabledIndex| property is bound to the selected *tag*,
-    // so we don't have to worry about index shifts when removing a row
-    // from the matrix.
-    [pluginDefaultSettingMatrix_ removeRow:kPluginsAskIndex];
-    NSArray* siblingViews = [[pluginDefaultSettingMatrix_ superview] subviews];
-    for (NSView* view in siblingViews) {
-      NSRect frame = [view frame];
-      if (frame.origin.y < [pluginDefaultSettingMatrix_ frame].origin.y) {
-        frame.origin.y +=
-            ([pluginDefaultSettingMatrix_ cellSize].height +
-             [pluginDefaultSettingMatrix_ intercellSpacing].height);
-        [view setFrame:frame];
-      }
-    }
-  }
-
-  NSRect frame = [[self window] frame];
-  frame.origin.y -= windowDelta;
-  frame.size.height += windowDelta;
-  [[self window] setFrame:frame display:NO];
-}
-
-// NSWindowDelegate method.
-- (void)windowWillClose:(NSNotification*)notification {
-  [self autorelease];
-  g_instance = nil;
-}
-
-- (void)selectTab:(ContentSettingsType)settingsType {
-  [self window];  // Make sure the nib file is loaded.
-  DCHECK(tabView_);
-  [tabView_ selectTabViewItemAtIndex:settingsType];
-}
-
-// NSTabViewDelegate method.
-- (void)         tabView:(NSTabView*)tabView
-    didSelectTabViewItem:(NSTabViewItem*)tabViewItem {
-  DCHECK_EQ(tabView_, tabView);
-  NSInteger index = [tabView indexOfTabViewItem:tabViewItem];
-  DCHECK_GT(index, CONTENT_SETTINGS_TYPE_DEFAULT);
-  DCHECK_LT(index, CONTENT_SETTINGS_NUM_TYPES);
-  if (index > CONTENT_SETTINGS_TYPE_DEFAULT &&
-       index < CONTENT_SETTINGS_NUM_TYPES)
-    lastSelectedTab_.SetValue(index);
-}
-
-// Let esc close the window.
-- (void)cancel:(id)sender {
-  [self close];
-}
-
-- (void)setCookieSettingIndex:(NSInteger)value {
-  ContentSetting setting = CONTENT_SETTING_DEFAULT;
-  switch (value) {
-    case kCookieEnabledIndex:  setting = CONTENT_SETTING_ALLOW; break;
-    case kCookieDisabledIndex: setting = CONTENT_SETTING_BLOCK; break;
-    default:
-      NOTREACHED();
-  }
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_COOKIES,
-      setting);
-}
-
-- (NSInteger)cookieSettingIndex {
-  switch (profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_COOKIES)) {
-    case CONTENT_SETTING_ALLOW:        return kCookieEnabledIndex;
-    case CONTENT_SETTING_BLOCK:        return kCookieDisabledIndex;
-    default:
-      NOTREACHED();
-      return kCookieEnabledIndex;
-  }
-}
-
-- (BOOL)cookieSettingsManaged {
-  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
-      CONTENT_SETTINGS_TYPE_COOKIES);
-}
-
-- (BOOL)blockThirdPartyCookies {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  return settingsMap->BlockThirdPartyCookies();
-}
-
-- (void)setBlockThirdPartyCookies:(BOOL)value {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  settingsMap->SetBlockThirdPartyCookies(value);
-}
-
-- (BOOL)blockThirdPartyCookiesManaged {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  return settingsMap->IsBlockThirdPartyCookiesManaged();
-}
-
-- (BOOL)clearSiteDataOnExit {
-  return clearSiteDataOnExit_.GetValue();
-}
-
-- (void)setClearSiteDataOnExit:(BOOL)value {
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  clearSiteDataOnExit_.SetValue(value);
-}
-
-// Shows the cookies controller.
-- (IBAction)showCookies:(id)sender {
-  // The cookie controller will autorelease itself when it's closed.
-  BrowsingDataDatabaseHelper* databaseHelper =
-      new BrowsingDataDatabaseHelper(profile_);
-  BrowsingDataLocalStorageHelper* storageHelper =
-      new BrowsingDataLocalStorageHelper(profile_);
-  BrowsingDataAppCacheHelper* appcacheHelper =
-      new BrowsingDataAppCacheHelper(profile_);
-  BrowsingDataIndexedDBHelper* indexedDBHelper =
-      BrowsingDataIndexedDBHelper::Create(profile_);
-  CookiesWindowController* controller =
-      [[CookiesWindowController alloc] initWithProfile:profile_
-                                        databaseHelper:databaseHelper
-                                         storageHelper:storageHelper
-                                        appcacheHelper:appcacheHelper
-                                       indexedDBHelper:indexedDBHelper];
-  [controller attachSheetTo:[self window]];
-}
-
-// Called when the user clicks the "Flash Player storage settings" button.
-- (IBAction)openFlashPlayerSettings:(id)sender {
-  Browser* browser = Browser::Create(profile_);
-  browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)),
-                   GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
-  browser->window()->Show();
-}
-
-// Called when the user clicks the "Disable individual plug-ins..." button.
-- (IBAction)openPluginsPage:(id)sender {
-  Browser* browser = Browser::Create(profile_);
-  browser->OpenURL(GURL(chrome::kChromeUIPluginsURL),
-                   GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
-  browser->window()->Show();
-}
-
-- (IBAction)showCookieExceptions:(id)sender {
-  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_COOKIES];
-}
-
-- (IBAction)showImagesExceptions:(id)sender {
-  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_IMAGES];
-}
-
-- (IBAction)showJavaScriptExceptions:(id)sender {
-  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_JAVASCRIPT];
-}
-
-- (IBAction)showPluginsExceptions:(id)sender {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableResourceContentSettings)) {
-    HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-    HostContentSettingsMap* offTheRecordSettingsMap =
-        profile_->HasOffTheRecordProfile() ?
-            profile_->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
-            NULL;
-    PluginExceptionsTableModel* model =
-        new PluginExceptionsTableModel(settingsMap, offTheRecordSettingsMap);
-    model->LoadSettings();
-    [[SimpleContentExceptionsWindowController controllerWithTableModel:model]
-        attachSheetTo:[self window]];
-  } else {
-    [self showExceptionsForType:CONTENT_SETTINGS_TYPE_PLUGINS];
-  }
-}
-
-- (IBAction)showPopupsExceptions:(id)sender {
-  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_POPUPS];
-}
-
-- (IBAction)showGeolocationExceptions:(id)sender {
-  GeolocationContentSettingsMap* settingsMap =
-      profile_->GetGeolocationContentSettingsMap();
-  GeolocationExceptionsTableModel* model =  // Freed by window controller.
-      new GeolocationExceptionsTableModel(settingsMap);
-  [[SimpleContentExceptionsWindowController controllerWithTableModel:model]
-      attachSheetTo:[self window]];
-}
-
-- (IBAction)showNotificationsExceptions:(id)sender {
-  DesktopNotificationService* service =
-      profile_->GetDesktopNotificationService();
-  NotificationExceptionsTableModel* model =  // Freed by window controller.
-      new NotificationExceptionsTableModel(service);
-  [[SimpleContentExceptionsWindowController controllerWithTableModel:model]
-      attachSheetTo:[self window]];
-}
-
-- (void)showExceptionsForType:(ContentSettingsType)settingsType {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  HostContentSettingsMap* offTheRecordSettingsMap =
-      profile_->HasOffTheRecordProfile() ?
-          profile_->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
-          NULL;
-  [[ContentExceptionsWindowController controllerForType:settingsType
-                                            settingsMap:settingsMap
-                                         otrSettingsMap:offTheRecordSettingsMap]
-      attachSheetTo:[self window]];
-}
-
-- (void)setImagesEnabledIndex:(NSInteger)value {
-  ContentSetting setting = value == kContentSettingsEnabledIndex ?
-      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_IMAGES, setting);
-}
-
-- (NSInteger)imagesEnabledIndex {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  bool enabled =
-      settingsMap->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES) ==
-      CONTENT_SETTING_ALLOW;
-  return enabled ? kContentSettingsEnabledIndex : kContentSettingsDisabledIndex;
-}
-
-- (BOOL)imagesSettingsManaged {
-  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
-      CONTENT_SETTINGS_TYPE_IMAGES);
-}
-
-- (void)setJavaScriptEnabledIndex:(NSInteger)value {
-  ContentSetting setting = value == kContentSettingsEnabledIndex ?
-      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_JAVASCRIPT, setting);
-}
-
-- (NSInteger)javaScriptEnabledIndex {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  bool enabled =
-      settingsMap->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT) ==
-      CONTENT_SETTING_ALLOW;
-  return enabled ? kContentSettingsEnabledIndex : kContentSettingsDisabledIndex;
-}
-
-- (BOOL)javaScriptSettingsManaged {
-  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
-      CONTENT_SETTINGS_TYPE_JAVASCRIPT);
-}
-
-- (void)setPluginsEnabledIndex:(NSInteger)value {
-  ContentSetting setting = CONTENT_SETTING_DEFAULT;
-  switch (value) {
-    case kPluginsAllowIndex:
-      setting = CONTENT_SETTING_ALLOW;
-      break;
-    case kPluginsAskIndex:
-      setting = CONTENT_SETTING_ASK;
-      break;
-    case kPluginsBlockIndex:
-      setting = CONTENT_SETTING_BLOCK;
-      break;
-    default:
-      NOTREACHED();
-  }
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_PLUGINS, setting);
-}
-
-- (NSInteger)pluginsEnabledIndex {
-  HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
-  ContentSetting setting =
-      map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
-  switch (setting) {
-    case CONTENT_SETTING_ALLOW:
-      return kPluginsAllowIndex;
-    case CONTENT_SETTING_ASK:
-      if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableClickToPlay))
-        return kPluginsAskIndex;
-      // Fall through to the next case.
-    case CONTENT_SETTING_BLOCK:
-      return kPluginsBlockIndex;
-    default:
-      NOTREACHED();
-      return kPluginsAllowIndex;
-  }
-}
-
-- (BOOL)pluginsSettingsManaged {
-  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
-      CONTENT_SETTINGS_TYPE_PLUGINS);
-}
-
-- (void)setPopupsEnabledIndex:(NSInteger)value {
-  ContentSetting setting = value == kContentSettingsEnabledIndex ?
-      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
-      CONTENT_SETTINGS_TYPE_POPUPS, setting);
-}
-
-- (NSInteger)popupsEnabledIndex {
-  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
-  bool enabled =
-      settingsMap->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS) ==
-      CONTENT_SETTING_ALLOW;
-  return enabled ? kContentSettingsEnabledIndex : kContentSettingsDisabledIndex;
-}
-
-- (BOOL)popupsSettingsManaged {
-  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
-      CONTENT_SETTINGS_TYPE_POPUPS);
-}
-
-- (void)setGeolocationSettingIndex:(NSInteger)value {
-  ContentSetting setting = CONTENT_SETTING_DEFAULT;
-  switch (value) {
-    case kGeolocationEnabledIndex:  setting = CONTENT_SETTING_ALLOW; break;
-    case kGeolocationAskIndex:      setting = CONTENT_SETTING_ASK;   break;
-    case kGeolocationDisabledIndex: setting = CONTENT_SETTING_BLOCK; break;
-    default:
-      NOTREACHED();
-  }
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetGeolocationContentSettingsMap()->SetDefaultContentSetting(
-      setting);
-}
-
-- (NSInteger)geolocationSettingIndex {
-  ContentSetting setting =
-      profile_->GetGeolocationContentSettingsMap()->GetDefaultContentSetting();
-  switch (setting) {
-    case CONTENT_SETTING_ALLOW: return kGeolocationEnabledIndex;
-    case CONTENT_SETTING_ASK:   return kGeolocationAskIndex;
-    case CONTENT_SETTING_BLOCK: return kGeolocationDisabledIndex;
-    default:
-      NOTREACHED();
-      return kGeolocationAskIndex;
-  }
-}
-
-- (void)setNotificationsSettingIndex:(NSInteger)value {
-  ContentSetting setting = CONTENT_SETTING_DEFAULT;
-  switch (value) {
-    case kNotificationsEnabledIndex:  setting = CONTENT_SETTING_ALLOW; break;
-    case kNotificationsAskIndex:      setting = CONTENT_SETTING_ASK;   break;
-    case kNotificationsDisabledIndex: setting = CONTENT_SETTING_BLOCK; break;
-    default:
-      NOTREACHED();
-  }
-  ContentSettingsDialogControllerInternal::PrefObserverDisabler
-      disabler(observer_.get());
-  profile_->GetDesktopNotificationService()->SetDefaultContentSetting(
-      setting);
-}
-
-- (NSInteger)notificationsSettingIndex {
-  ContentSetting setting =
-      profile_->GetDesktopNotificationService()->GetDefaultContentSetting();
-  switch (setting) {
-    case CONTENT_SETTING_ALLOW: return kNotificationsEnabledIndex;
-    case CONTENT_SETTING_ASK:   return kNotificationsAskIndex;
-    case CONTENT_SETTING_BLOCK: return kNotificationsDisabledIndex;
-    default:
-      NOTREACHED();
-      return kGeolocationAskIndex;
-  }
-}
-
-// Callback when preferences are changed. |prefName| is the name of the
-// pref that has changed and should not be NULL.
-- (void)prefChanged:(const std::string&)prefName {
-  if (prefName == prefs::kClearSiteDataOnExit) {
-    [self willChangeValueForKey:@"clearSiteDataOnExit"];
-    [self didChangeValueForKey:@"clearSiteDataOnExit"];
-  }
-  if (prefName == prefs::kBlockThirdPartyCookies) {
-    [self willChangeValueForKey:@"blockThirdPartyCookies"];
-    [self didChangeValueForKey:@"blockThirdPartyCookies"];
-    [self willChangeValueForKey:@"blockThirdPartyCookiesManaged"];
-    [self didChangeValueForKey:@"blockThirdPartyCookiesManaged"];
-  }
-  if (prefName == prefs::kBlockNonsandboxedPlugins) {
-    [self willChangeValueForKey:@"pluginsEnabledIndex"];
-    [self didChangeValueForKey:@"pluginsEnabledIndex"];
-  }
-  if (prefName == prefs::kDefaultContentSettings) {
-    // We don't know exactly which setting has changed, so we'll tickle all
-    // of the properties that apply to kDefaultContentSettings.  This will
-    // keep the UI up-to-date.
-    [self willChangeValueForKey:@"cookieSettingIndex"];
-    [self didChangeValueForKey:@"cookieSettingIndex"];
-    [self willChangeValueForKey:@"imagesEnabledIndex"];
-    [self didChangeValueForKey:@"imagesEnabledIndex"];
-    [self willChangeValueForKey:@"javaScriptEnabledIndex"];
-    [self didChangeValueForKey:@"javaScriptEnabledIndex"];
-    [self willChangeValueForKey:@"pluginsEnabledIndex"];
-    [self didChangeValueForKey:@"pluginsEnabledIndex"];
-    [self willChangeValueForKey:@"popupsEnabledIndex"];
-    [self didChangeValueForKey:@"popupsEnabledIndex"];
-
-    // Updates the "Enable" state of the radio groups and the exception buttons.
-    [self willChangeValueForKey:@"cookieSettingsManaged"];
-    [self didChangeValueForKey:@"cookieSettingsManaged"];
-    [self willChangeValueForKey:@"imagesSettingsManaged"];
-    [self didChangeValueForKey:@"imagesSettingsManaged"];
-    [self willChangeValueForKey:@"javaScriptSettingsManaged"];
-    [self didChangeValueForKey:@"javaScriptSettingsManaged"];
-    [self willChangeValueForKey:@"pluginsSettingsManaged"];
-    [self didChangeValueForKey:@"pluginsSettingsManaged"];
-    [self willChangeValueForKey:@"popupsSettingsManaged"];
-    [self didChangeValueForKey:@"popupsSettingsManaged"];
-  }
-  if (prefName == prefs::kGeolocationDefaultContentSetting) {
-    [self willChangeValueForKey:@"geolocationSettingIndex"];
-    [self didChangeValueForKey:@"geolocationSettingIndex"];
-  }
-  if (prefName == prefs::kDesktopNotificationDefaultContentSetting) {
-    [self willChangeValueForKey:@"notificationsSettingIndex"];
-    [self didChangeValueForKey:@"notificationsSettingIndex"];
-  }
-}
-
-- (void)contentSettingsChanged:(ContentSettingsDetails*)details {
-  [self prefChanged:prefs::kBlockNonsandboxedPlugins];
-  [self prefChanged:prefs::kDefaultContentSettings];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/content_settings_dialog_controller_unittest.mm b/chrome/browser/ui/cocoa/content_settings_dialog_controller_unittest.mm
deleted file mode 100644
index 1d48509..0000000
--- a/chrome/browser/ui/cocoa/content_settings_dialog_controller_unittest.mm
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/content_settings_dialog_controller.h"
-
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#import "base/scoped_nsobject.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
-#include "chrome/browser/notifications/desktop_notification_service.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/chrome_switches.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class ContentSettingsDialogControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    TestingProfile* profile = browser_helper_.profile();
-    settingsMap_ = new HostContentSettingsMap(profile);
-    geoSettingsMap_ = new GeolocationContentSettingsMap(profile);
-    notificationsService_.reset(new DesktopNotificationService(profile, NULL));
-    controller_ = [ContentSettingsDialogController
-                   showContentSettingsForType:CONTENT_SETTINGS_TYPE_DEFAULT
-                   profile:browser_helper_.profile()];
-  }
-
-  virtual void TearDown() {
-    [controller_ close];
-    CocoaTest::TearDown();
-  }
-
- protected:
-  ContentSettingsDialogController* controller_;
-  BrowserTestHelper browser_helper_;
-  scoped_refptr<HostContentSettingsMap> settingsMap_;
-  scoped_refptr<GeolocationContentSettingsMap> geoSettingsMap_;
-  scoped_ptr<DesktopNotificationService> notificationsService_;
-};
-
-// Test that +showContentSettingsDialogForProfile brings up the existing editor
-// and doesn't leak or crash.
-TEST_F(ContentSettingsDialogControllerTest, CreateDialog) {
-  EXPECT_TRUE(controller_);
-}
-
-TEST_F(ContentSettingsDialogControllerTest, CookieSetting) {
-  // Change setting, check dialog property.
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
-                                         CONTENT_SETTING_ALLOW);
-  EXPECT_EQ([controller_ cookieSettingIndex], kCookieEnabledIndex);
-
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
-                                         CONTENT_SETTING_BLOCK);
-  EXPECT_EQ([controller_ cookieSettingIndex], kCookieDisabledIndex);
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setCookieSettingIndex:kCookieEnabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
-  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
-
-  [controller_ setCookieSettingIndex:kCookieDisabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
-  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
-}
-
-TEST_F(ContentSettingsDialogControllerTest, BlockThirdPartyCookiesSetting) {
-  // Change setting, check dialog property.
-  settingsMap_->SetBlockThirdPartyCookies(YES);
-  EXPECT_TRUE([controller_ blockThirdPartyCookies]);
-
-  settingsMap_->SetBlockThirdPartyCookies(NO);
-  EXPECT_FALSE([controller_ blockThirdPartyCookies]);
-
-  // Change dialog property, check setting.
-  [controller_ setBlockThirdPartyCookies:YES];
-  EXPECT_TRUE(settingsMap_->BlockThirdPartyCookies());
-
-  [controller_ setBlockThirdPartyCookies:NO];
-  EXPECT_FALSE(settingsMap_->BlockThirdPartyCookies());
-}
-
-TEST_F(ContentSettingsDialogControllerTest, ClearSiteDataOnExitSetting) {
-  TestingProfile* profile = browser_helper_.profile();
-
-  // Change setting, check dialog property.
-  profile->GetPrefs()->SetBoolean(prefs::kClearSiteDataOnExit, true);
-  EXPECT_TRUE([controller_ clearSiteDataOnExit]);
-
-  profile->GetPrefs()->SetBoolean(prefs::kClearSiteDataOnExit, false);
-  EXPECT_FALSE([controller_ clearSiteDataOnExit]);
-
-  // Change dialog property, check setting.
-  [controller_ setClearSiteDataOnExit:YES];
-  EXPECT_TRUE(profile->GetPrefs()->GetBoolean(prefs::kClearSiteDataOnExit));
-
-  [controller_ setClearSiteDataOnExit:NO];
-  EXPECT_FALSE(profile->GetPrefs()->GetBoolean(prefs::kClearSiteDataOnExit));
-}
-
-TEST_F(ContentSettingsDialogControllerTest, ImagesSetting) {
-  // Change setting, check dialog property.
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES,
-                                         CONTENT_SETTING_ALLOW);
-  EXPECT_EQ([controller_ imagesEnabledIndex], kContentSettingsEnabledIndex);
-
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES,
-                                         CONTENT_SETTING_BLOCK);
-  EXPECT_EQ([controller_ imagesEnabledIndex], kContentSettingsDisabledIndex);
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setImagesEnabledIndex:kContentSettingsEnabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES);
-  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
-
-  [controller_ setImagesEnabledIndex:kContentSettingsDisabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES);
-  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
-}
-
-TEST_F(ContentSettingsDialogControllerTest, JavaScriptSetting) {
-  // Change setting, check dialog property.
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT,
-                                         CONTENT_SETTING_ALLOW);
-  EXPECT_EQ([controller_ javaScriptEnabledIndex], kContentSettingsEnabledIndex);
-
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT,
-                                         CONTENT_SETTING_BLOCK);
-  EXPECT_EQ([controller_ javaScriptEnabledIndex],
-            kContentSettingsDisabledIndex);
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setJavaScriptEnabledIndex:kContentSettingsEnabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
-  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
-
-  [controller_ setJavaScriptEnabledIndex:kContentSettingsDisabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
-  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
-}
-
-TEST_F(ContentSettingsDialogControllerTest, PluginsSetting) {
-  // Change setting, check dialog property.
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                         CONTENT_SETTING_ALLOW);
-  EXPECT_EQ(kPluginsAllowIndex, [controller_ pluginsEnabledIndex]);
-
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                         CONTENT_SETTING_BLOCK);
-  EXPECT_EQ(kPluginsBlockIndex, [controller_ pluginsEnabledIndex]);
-
-  {
-    // Click-to-play needs to be enabled to set the content setting to ASK.
-    CommandLine* cmd = CommandLine::ForCurrentProcess();
-    AutoReset<CommandLine> auto_reset(cmd, *cmd);
-    cmd->AppendSwitch(switches::kEnableClickToPlay);
-
-    settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                           CONTENT_SETTING_ASK);
-    EXPECT_EQ(kPluginsAskIndex, [controller_ pluginsEnabledIndex]);
-  }
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setPluginsEnabledIndex:kPluginsAllowIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
-  EXPECT_EQ(CONTENT_SETTING_ALLOW, setting);
-
-  [controller_ setPluginsEnabledIndex:kPluginsBlockIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
-  EXPECT_EQ(CONTENT_SETTING_BLOCK, setting);
-
-  {
-    CommandLine* cmd = CommandLine::ForCurrentProcess();
-    AutoReset<CommandLine> auto_reset(cmd, *cmd);
-    cmd->AppendSwitch(switches::kEnableClickToPlay);
-
-    [controller_ setPluginsEnabledIndex:kPluginsAskIndex];
-    setting =
-        settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
-    EXPECT_EQ(CONTENT_SETTING_ASK, setting);
-  }
-}
-
-TEST_F(ContentSettingsDialogControllerTest, PopupsSetting) {
-  // Change setting, check dialog property.
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS,
-                                         CONTENT_SETTING_ALLOW);
-  EXPECT_EQ([controller_ popupsEnabledIndex], kContentSettingsEnabledIndex);
-
-  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS,
-                                         CONTENT_SETTING_BLOCK);
-  EXPECT_EQ([controller_ popupsEnabledIndex], kContentSettingsDisabledIndex);
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setPopupsEnabledIndex:kContentSettingsEnabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS);
-  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
-
-  [controller_ setPopupsEnabledIndex:kContentSettingsDisabledIndex];
-  setting =
-      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS);
-  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
-}
-
-TEST_F(ContentSettingsDialogControllerTest, GeolocationSetting) {
-  // Change setting, check dialog property.
-  geoSettingsMap_->SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
-  EXPECT_EQ([controller_ geolocationSettingIndex], kGeolocationEnabledIndex);
-
-  geoSettingsMap_->SetDefaultContentSetting(CONTENT_SETTING_ASK);
-  EXPECT_EQ([controller_ geolocationSettingIndex], kGeolocationAskIndex);
-
-  geoSettingsMap_->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
-  EXPECT_EQ([controller_ geolocationSettingIndex], kGeolocationDisabledIndex);
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setGeolocationSettingIndex:kGeolocationEnabledIndex];
-  setting =
-      geoSettingsMap_->GetDefaultContentSetting();
-  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
-
-  [controller_ setGeolocationSettingIndex:kGeolocationAskIndex];
-  setting =
-      geoSettingsMap_->GetDefaultContentSetting();
-  EXPECT_EQ(setting, CONTENT_SETTING_ASK);
-
-  [controller_ setGeolocationSettingIndex:kGeolocationDisabledIndex];
-  setting =
-      geoSettingsMap_->GetDefaultContentSetting();
-  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
-}
-
-TEST_F(ContentSettingsDialogControllerTest, NotificationsSetting) {
-  // Change setting, check dialog property.
-  notificationsService_->SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
-  EXPECT_EQ([controller_ notificationsSettingIndex],
-             kNotificationsEnabledIndex);
-
-  notificationsService_->SetDefaultContentSetting(CONTENT_SETTING_ASK);
-  EXPECT_EQ([controller_ notificationsSettingIndex], kNotificationsAskIndex);
-
-  notificationsService_->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
-  EXPECT_EQ([controller_ notificationsSettingIndex],
-            kNotificationsDisabledIndex);
-
-  // Change dialog property, check setting.
-  NSInteger setting;
-  [controller_ setNotificationsSettingIndex:kNotificationsEnabledIndex];
-  setting =
-      notificationsService_->GetDefaultContentSetting();
-  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
-
-  [controller_ setNotificationsSettingIndex:kNotificationsAskIndex];
-  setting =
-      notificationsService_->GetDefaultContentSetting();
-  EXPECT_EQ(setting, CONTENT_SETTING_ASK);
-
-  [controller_ setNotificationsSettingIndex:kNotificationsDisabledIndex];
-  setting =
-      notificationsService_->GetDefaultContentSetting();
-  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
-}
-
-}  // namespace
-
diff --git a/chrome/browser/ui/cocoa/cookie_details.h b/chrome/browser/ui/cocoa/cookie_details.h
deleted file mode 100644
index 614c87c..0000000
--- a/chrome/browser/ui/cocoa/cookie_details.h
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "chrome/browser/browsing_data_database_helper.h"
-#include "chrome/browser/browsing_data_indexed_db_helper.h"
-#include "chrome/browser/browsing_data_local_storage_helper.h"
-#include "base/scoped_nsobject.h"
-#include "net/base/cookie_monster.h"
-#include "webkit/appcache/appcache_service.h"
-
-class CookieTreeNode;
-class CookiePromptModalDialog;
-
-// This enum specifies the type of information contained in the
-// cookie details.
-enum CocoaCookieDetailsType {
-  // Represents grouping of cookie data, used in the cookie tree.
-  kCocoaCookieDetailsTypeFolder = 0,
-
-  // Detailed information about a cookie, used both in the cookie
-  // tree and the cookie prompt.
-  kCocoaCookieDetailsTypeCookie,
-
-  // Detailed information about a web database used for
-  // display in the cookie tree.
-  kCocoaCookieDetailsTypeTreeDatabase,
-
-  // Detailed information about local storage used for
-  // display in the cookie tree.
-  kCocoaCookieDetailsTypeTreeLocalStorage,
-
-  // Detailed information about an appcache used for display in the
-  // cookie tree.
-  kCocoaCookieDetailsTypeTreeAppCache,
-
-  // Detailed information about an IndexedDB used for display in the
-  // cookie tree.
-  kCocoaCookieDetailsTypeTreeIndexedDB,
-
-  // Detailed information about a web database used for display
-  // in the cookie prompt dialog.
-  kCocoaCookieDetailsTypePromptDatabase,
-
-  // Detailed information about local storage used for display
-  // in the cookie prompt dialog.
-  kCocoaCookieDetailsTypePromptLocalStorage,
-
-  // Detailed information about app caches used for display
-  // in the cookie prompt dialog.
-  kCocoaCookieDetailsTypePromptAppCache
-};
-
-// This class contains all of the information that can be displayed in
-// a cookie details view. Because the view uses bindings to display
-// the cookie information, the methods that provide that information
-// for display must be implemented directly on this class and not on any
-// of its subclasses.
-// If this system is rewritten to not use bindings, this class should be
-// subclassed and specialized, rather than using an enum to determine type.
-@interface CocoaCookieDetails : NSObject {
- @private
-  CocoaCookieDetailsType type_;
-
-  // Used for type kCocoaCookieDetailsTypeCookie to indicate whether
-  // it should be possible to edit the expiration.
-  BOOL canEditExpiration_;
-
-  // Indicates whether a cookie has an explcit expiration. If not
-  // it will expire with the session.
-  BOOL hasExpiration_;
-
-  // Only set for type kCocoaCookieDetailsTypeCookie.
-  scoped_nsobject<NSString> content_;
-  scoped_nsobject<NSString> path_;
-  scoped_nsobject<NSString> sendFor_;
-  // Stringifed dates.
-  scoped_nsobject<NSString> expires_;
-
-  // Only set for type kCocoaCookieDetailsTypeCookie and
-  // kCocoaCookieDetailsTypeTreeAppCache nodes.
-  scoped_nsobject<NSString> created_;
-
-  // Only set for types kCocoaCookieDetailsTypeCookie, and
-  // kCocoaCookieDetailsTypePromptDatabase nodes.
-  scoped_nsobject<NSString> name_;
-
-  // Only set for type kCocoaCookieDetailsTypeTreeLocalStorage,
-  // kCocoaCookieDetailsTypeTreeDatabase,
-  // kCocoaCookieDetailsTypePromptDatabase,
-  // kCocoaCookieDetailsTypeTreeIndexedDB, and
-  // kCocoaCookieDetailsTypeTreeAppCache nodes.
-  scoped_nsobject<NSString> fileSize_;
-
-  // Only set for types kCocoaCookieDetailsTypeTreeLocalStorage,
-  // kCocoaCookieDetailsTypeTreeDatabase, and
-  // kCocoaCookieDetailsTypeTreeIndexedDB nodes.
-  scoped_nsobject<NSString> lastModified_;
-
-  // Only set for type kCocoaCookieDetailsTypeTreeAppCache nodes.
-  scoped_nsobject<NSString> lastAccessed_;
-
-  // Only set for type kCocoaCookieDetailsTypeCookie,
-  // kCocoaCookieDetailsTypePromptDatabase,
-  // kCocoaCookieDetailsTypePromptLocalStorage, and
-  // kCocoaCookieDetailsTypeTreeIndexedDB nodes.
-  scoped_nsobject<NSString> domain_;
-
-  // Only set for type kCocoaCookieTreeNodeTypeDatabaseStorage and
-  // kCocoaCookieDetailsTypePromptDatabase nodes.
-  scoped_nsobject<NSString> databaseDescription_;
-
-  // Only set for type kCocoaCookieDetailsTypePromptLocalStorage.
-  scoped_nsobject<NSString> localStorageKey_;
-  scoped_nsobject<NSString> localStorageValue_;
-
-  // Only set for type kCocoaCookieDetailsTypeTreeAppCache and
-  // kCocoaCookieDetailsTypePromptAppCache.
-  scoped_nsobject<NSString> manifestURL_;
-}
-
-@property (nonatomic, readonly) BOOL canEditExpiration;
-@property (nonatomic) BOOL hasExpiration;
-@property (nonatomic, readonly) CocoaCookieDetailsType type;
-
-// The following methods are used in the bindings of subviews inside
-// the cookie detail view. Note that the method that tests the
-// visibility of the subview for cookie-specific information has a different
-// polarity than the other visibility testing methods. This ensures that
-// this subview is shown when there is no selection in the cookie tree,
-// because a hidden value of |false| is generated when the key value binding
-// is evaluated through a nil object. The other methods are bound using a
-// |NSNegateBoolean| transformer, so that when there is a empty selection the
-// hidden value is |true|.
-- (BOOL)shouldHideCookieDetailsView;
-- (BOOL)shouldShowLocalStorageTreeDetailsView;
-- (BOOL)shouldShowLocalStoragePromptDetailsView;
-- (BOOL)shouldShowDatabaseTreeDetailsView;
-- (BOOL)shouldShowDatabasePromptDetailsView;
-- (BOOL)shouldShowAppCachePromptDetailsView;
-- (BOOL)shouldShowAppCacheTreeDetailsView;
-- (BOOL)shouldShowIndexedDBTreeDetailsView;
-
-- (NSString*)name;
-- (NSString*)content;
-- (NSString*)domain;
-- (NSString*)path;
-- (NSString*)sendFor;
-- (NSString*)created;
-- (NSString*)expires;
-- (NSString*)fileSize;
-- (NSString*)lastModified;
-- (NSString*)lastAccessed;
-- (NSString*)databaseDescription;
-- (NSString*)localStorageKey;
-- (NSString*)localStorageValue;
-- (NSString*)manifestURL;
-
-// Used for folders in the cookie tree.
-- (id)initAsFolder;
-
-// Used for cookie details in both the cookie tree and the cookie prompt dialog.
-- (id)initWithCookie:(const net::CookieMonster::CanonicalCookie*)treeNode
-              origin:(NSString*)origin
-   canEditExpiration:(BOOL)canEditExpiration;
-
-// Used for database details in the cookie tree.
-- (id)initWithDatabase:
-    (const BrowsingDataDatabaseHelper::DatabaseInfo*)databaseInfo;
-
-// Used for local storage details in the cookie tree.
-- (id)initWithLocalStorage:
-    (const BrowsingDataLocalStorageHelper::LocalStorageInfo*)localStorageInfo;
-
-// Used for database details in the cookie prompt dialog.
-- (id)initWithDatabase:(const std::string&)domain
-          databaseName:(const string16&)databaseName
-   databaseDescription:(const string16&)databaseDescription
-              fileSize:(unsigned long)fileSize;
-
-// -initWithAppCacheInfo: creates a cookie details with the manifest URL plus
-// all of this additional information that is available after an appcache is
-// actually created, including it's creation date, size and last accessed time.
-- (id)initWithAppCacheInfo:(const appcache::AppCacheInfo*)appcacheInfo;
-
-// Used for local storage details in the cookie prompt dialog.
-- (id)initWithLocalStorage:(const std::string&)domain
-                       key:(const string16&)key
-                     value:(const string16&)value;
-
-// -initWithAppCacheManifestURL: is called when the cookie prompt is displayed
-// for an appcache, at that time only the manifest URL of the appcache is known.
-- (id)initWithAppCacheManifestURL:(const std::string&)manifestURL;
-
-// Used for IndexedDB details in the cookie tree.
-- (id)initWithIndexedDBInfo:
-    (const BrowsingDataIndexedDBHelper::IndexedDBInfo*)indexedDB;
-
-// A factory method to create a configured instance given a node from
-// the cookie tree in |treeNode|.
-+ (CocoaCookieDetails*)createFromCookieTreeNode:(CookieTreeNode*)treeNode;
-
-@end
-
-// The subpanes of the cookie details view expect to be able to bind to methods
-// through a key path in the form |content.details.xxxx|. This class serves as
-// an adapter that simply wraps a |CocoaCookieDetails| object. An instance of
-// this class is set as the content object for cookie details view's object
-// controller so that key paths are properly resolved through to the
-// |CocoaCookieDetails| object for the cookie prompt.
-@interface CookiePromptContentDetailsAdapter : NSObject {
- @private
-  scoped_nsobject<CocoaCookieDetails> details_;
-}
-
-- (CocoaCookieDetails*)details;
-
-// The adapter assumes ownership of the details object
-// in its initializer.
-- (id)initWithDetails:(CocoaCookieDetails*)details;
-@end
-
diff --git a/chrome/browser/ui/cocoa/cookie_details.mm b/chrome/browser/ui/cocoa/cookie_details.mm
deleted file mode 100644
index e88cf27..0000000
--- a/chrome/browser/ui/cocoa/cookie_details.mm
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/cookie_details.h"
-
-#include "app/l10n_util_mac.h"
-#import "base/i18n/time_formatting.h"
-#include "base/sys_string_conversions.h"
-#include "grit/generated_resources.h"
-#include "chrome/browser/cookies_tree_model.h"
-#include "webkit/appcache/appcache_service.h"
-
-#pragma mark Cocoa Cookie Details
-
-@implementation CocoaCookieDetails
-
-@synthesize canEditExpiration = canEditExpiration_;
-@synthesize hasExpiration = hasExpiration_;
-@synthesize type = type_;
-
-- (BOOL)shouldHideCookieDetailsView {
-  return type_ != kCocoaCookieDetailsTypeFolder &&
-      type_ != kCocoaCookieDetailsTypeCookie;
-}
-
-- (BOOL)shouldShowLocalStorageTreeDetailsView {
-  return type_ == kCocoaCookieDetailsTypeTreeLocalStorage;
-}
-
-- (BOOL)shouldShowLocalStoragePromptDetailsView {
-  return type_ == kCocoaCookieDetailsTypePromptLocalStorage;
-}
-
-- (BOOL)shouldShowDatabaseTreeDetailsView {
-  return type_ == kCocoaCookieDetailsTypeTreeDatabase;
-}
-
-- (BOOL)shouldShowAppCacheTreeDetailsView {
-  return type_ == kCocoaCookieDetailsTypeTreeAppCache;
-}
-
-- (BOOL)shouldShowDatabasePromptDetailsView {
-  return type_ == kCocoaCookieDetailsTypePromptDatabase;
-}
-
-- (BOOL)shouldShowAppCachePromptDetailsView {
-  return type_ == kCocoaCookieDetailsTypePromptAppCache;
-}
-
-- (BOOL)shouldShowIndexedDBTreeDetailsView {
-  return type_ == kCocoaCookieDetailsTypeTreeIndexedDB;
-}
-
-- (NSString*)name {
-  return name_.get();
-}
-
-- (NSString*)content {
-  return content_.get();
-}
-
-- (NSString*)domain {
-  return domain_.get();
-}
-
-- (NSString*)path {
-  return path_.get();
-}
-
-- (NSString*)sendFor {
-  return sendFor_.get();
-}
-
-- (NSString*)created {
-  return created_.get();
-}
-
-- (NSString*)expires {
-  return expires_.get();
-}
-
-- (NSString*)fileSize {
-  return fileSize_.get();
-}
-
-- (NSString*)lastModified {
-  return lastModified_.get();
-}
-
-- (NSString*)lastAccessed {
-  return lastAccessed_.get();
-}
-
-- (NSString*)databaseDescription {
-  return databaseDescription_.get();
-}
-
-- (NSString*)localStorageKey {
-  return localStorageKey_.get();
-}
-
-- (NSString*)localStorageValue {
-  return localStorageValue_.get();
-}
-
-- (NSString*)manifestURL {
-  return manifestURL_.get();
-}
-
-- (id)initAsFolder {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypeFolder;
-  }
-  return self;
-}
-
-- (id)initWithCookie:(const net::CookieMonster::CanonicalCookie*)cookie
-              origin:(NSString*)origin
-   canEditExpiration:(BOOL)canEditExpiration {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypeCookie;
-    hasExpiration_ = cookie->DoesExpire();
-    canEditExpiration_ = canEditExpiration && hasExpiration_;
-    name_.reset([base::SysUTF8ToNSString(cookie->Name()) retain]);
-    content_.reset([base::SysUTF8ToNSString(cookie->Value()) retain]);
-    path_.reset([base::SysUTF8ToNSString(cookie->Path()) retain]);
-    domain_.reset([origin retain]);
-
-    if (cookie->DoesExpire()) {
-      expires_.reset([base::SysUTF16ToNSString(
-          base::TimeFormatFriendlyDateAndTime(cookie->ExpiryDate())) retain]);
-    } else {
-      expires_.reset([l10n_util::GetNSStringWithFixup(
-          IDS_COOKIES_COOKIE_EXPIRES_SESSION) retain]);
-    }
-
-    created_.reset([base::SysUTF16ToNSString(
-        base::TimeFormatFriendlyDateAndTime(cookie->CreationDate())) retain]);
-
-    if (cookie->IsSecure()) {
-      sendFor_.reset([l10n_util::GetNSStringWithFixup(
-          IDS_COOKIES_COOKIE_SENDFOR_SECURE) retain]);
-    } else {
-      sendFor_.reset([l10n_util::GetNSStringWithFixup(
-          IDS_COOKIES_COOKIE_SENDFOR_ANY) retain]);
-    }
-  }
-  return self;
-}
-
-- (id)initWithDatabase:(const BrowsingDataDatabaseHelper::DatabaseInfo*)
-    databaseInfo {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypeTreeDatabase;
-    canEditExpiration_ = NO;
-    databaseDescription_.reset([base::SysUTF8ToNSString(
-        databaseInfo->description) retain]);
-    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(databaseInfo->size,
-        GetByteDisplayUnits(databaseInfo->size), true)) retain]);
-    lastModified_.reset([base::SysUTF16ToNSString(
-        base::TimeFormatFriendlyDateAndTime(
-            databaseInfo->last_modified)) retain]);
-  }
-  return self;
-}
-
-- (id)initWithLocalStorage:(
-    const BrowsingDataLocalStorageHelper::LocalStorageInfo*)storageInfo {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypeTreeLocalStorage;
-    canEditExpiration_ = NO;
-    domain_.reset([base::SysUTF8ToNSString(storageInfo->origin) retain]);
-    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(storageInfo->size,
-        GetByteDisplayUnits(storageInfo->size), true)) retain]);
-    lastModified_.reset([base::SysUTF16ToNSString(
-        base::TimeFormatFriendlyDateAndTime(
-            storageInfo->last_modified)) retain]);
-  }
-  return self;
-}
-
-- (id)initWithAppCacheInfo:(const appcache::AppCacheInfo*)appcacheInfo {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypeTreeAppCache;
-    canEditExpiration_ = NO;
-    manifestURL_.reset([base::SysUTF8ToNSString(
-        appcacheInfo->manifest_url.spec()) retain]);
-    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(appcacheInfo->size,
-        GetByteDisplayUnits(appcacheInfo->size), true)) retain]);
-    created_.reset([base::SysUTF16ToNSString(
-        base::TimeFormatFriendlyDateAndTime(
-            appcacheInfo->creation_time)) retain]);
-    lastAccessed_.reset([base::SysUTF16ToNSString(
-        base::TimeFormatFriendlyDateAndTime(
-            appcacheInfo->last_access_time)) retain]);
-  }
-  return self;
-}
-
-- (id)initWithDatabase:(const std::string&)domain
-          databaseName:(const string16&)databaseName
-   databaseDescription:(const string16&)databaseDescription
-              fileSize:(unsigned long)fileSize {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypePromptDatabase;
-    canEditExpiration_ = NO;
-    name_.reset([base::SysUTF16ToNSString(databaseName) retain]);
-    domain_.reset([base::SysUTF8ToNSString(domain) retain]);
-    databaseDescription_.reset(
-        [base::SysUTF16ToNSString(databaseDescription) retain]);
-    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(fileSize,
-        GetByteDisplayUnits(fileSize), true)) retain]);
-  }
-  return self;
-}
-
-- (id)initWithLocalStorage:(const std::string&)domain
-                       key:(const string16&)key
-                     value:(const string16&)value {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypePromptLocalStorage;
-    canEditExpiration_ = NO;
-    domain_.reset([base::SysUTF8ToNSString(domain) retain]);
-    localStorageKey_.reset([base::SysUTF16ToNSString(key) retain]);
-    localStorageValue_.reset([base::SysUTF16ToNSString(value) retain]);
-  }
-  return self;
-}
-
-- (id)initWithAppCacheManifestURL:(const std::string&)manifestURL {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypePromptAppCache;
-    canEditExpiration_ = NO;
-    manifestURL_.reset([base::SysUTF8ToNSString(manifestURL) retain]);
-  }
-  return self;
-}
-
-- (id)initWithIndexedDBInfo:
-    (const BrowsingDataIndexedDBHelper::IndexedDBInfo*)indexedDBInfo {
-  if ((self = [super init])) {
-    type_ = kCocoaCookieDetailsTypeTreeIndexedDB;
-    canEditExpiration_ = NO;
-    domain_.reset([base::SysUTF8ToNSString(indexedDBInfo->origin) retain]);
-    fileSize_.reset([base::SysUTF16ToNSString(FormatBytes(indexedDBInfo->size,
-        GetByteDisplayUnits(indexedDBInfo->size), true)) retain]);
-    lastModified_.reset([base::SysUTF16ToNSString(
-        base::TimeFormatFriendlyDateAndTime(
-            indexedDBInfo->last_modified)) retain]);
-  }
-  return self;
-}
-
-+ (CocoaCookieDetails*)createFromCookieTreeNode:(CookieTreeNode*)treeNode {
-  CookieTreeNode::DetailedInfo info = treeNode->GetDetailedInfo();
-  CookieTreeNode::DetailedInfo::NodeType nodeType = info.node_type;
-  NSString* origin;
-  switch (nodeType) {
-    case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
-      origin = base::SysWideToNSString(info.origin.c_str());
-      return [[[CocoaCookieDetails alloc] initWithCookie:info.cookie
-                                                  origin:origin
-                                       canEditExpiration:NO] autorelease];
-    case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
-      return [[[CocoaCookieDetails alloc]
-          initWithDatabase:info.database_info] autorelease];
-    case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
-      return [[[CocoaCookieDetails alloc]
-          initWithLocalStorage:info.local_storage_info] autorelease];
-    case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
-      return [[[CocoaCookieDetails alloc]
-          initWithAppCacheInfo:info.appcache_info] autorelease];
-    case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
-      return [[[CocoaCookieDetails alloc]
-          initWithIndexedDBInfo:info.indexed_db_info] autorelease];
-    default:
-      return [[[CocoaCookieDetails alloc] initAsFolder] autorelease];
-  }
-}
-
-@end
-
-#pragma mark Content Object Adapter
-
-@implementation CookiePromptContentDetailsAdapter
-
-- (id)initWithDetails:(CocoaCookieDetails*)details {
-  if ((self = [super init])) {
-    details_.reset([details retain]);
-  }
-  return self;
-}
-
-- (CocoaCookieDetails*)details {
-  return details_.get();
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/cookie_details_unittest.mm b/chrome/browser/ui/cocoa/cookie_details_unittest.mm
deleted file mode 100644
index 0f7d711..0000000
--- a/chrome/browser/ui/cocoa/cookie_details_unittest.mm
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/sys_string_conversions.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "chrome/browser/ui/cocoa/cookie_details.h"
-#include "googleurl/src/gurl.h"
-#import "testing/gtest_mac.h"
-
-namespace {
-
-class CookiesDetailsTest : public CocoaTest {
-};
-
-TEST_F(CookiesDetailsTest, CreateForFolder) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  details.reset([[CocoaCookieDetails alloc] initAsFolder]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeFolder);
-}
-
-TEST_F(CookiesDetailsTest, CreateForCookie) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  GURL url("http://chromium.org");
-  std::string cookieLine(
-      "PHPSESSID=0123456789abcdef0123456789abcdef; path=/");
-  net::CookieMonster::ParsedCookie pc(cookieLine);
-  net::CookieMonster::CanonicalCookie cookie(url, pc);
-  NSString* origin = base::SysUTF8ToNSString("http://chromium.org");
-  details.reset([[CocoaCookieDetails alloc] initWithCookie:&cookie
-                                                    origin:origin
-                                         canEditExpiration:NO]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeCookie);
-  EXPECT_NSEQ(@"PHPSESSID", [details.get() name]);
-  EXPECT_NSEQ(@"0123456789abcdef0123456789abcdef",
-      [details.get() content]);
-  EXPECT_NSEQ(@"http://chromium.org", [details.get() domain]);
-  EXPECT_NSEQ(@"/", [details.get() path]);
-  EXPECT_NSNE(@"", [details.get() lastModified]);
-  EXPECT_NSNE(@"", [details.get() created]);
-  EXPECT_NSNE(@"", [details.get() sendFor]);
-
-  EXPECT_FALSE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForTreeDatabase) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  std::string host("http://chromium.org");
-  std::string database_name("sassolungo");
-  std::string origin_identifier("dolomites");
-  std::string description("a great place to climb");
-  int64 size = 1234;
-  base::Time last_modified = base::Time::Now();
-  BrowsingDataDatabaseHelper::DatabaseInfo info(host, database_name,
-      origin_identifier, description, host, size, last_modified);
-  details.reset([[CocoaCookieDetails alloc] initWithDatabase:&info]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeDatabase);
-  EXPECT_NSEQ(@"a great place to climb", [details.get() databaseDescription]);
-  EXPECT_NSEQ(@"1234 B", [details.get() fileSize]);
-  EXPECT_NSNE(@"", [details.get() lastModified]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForTreeLocalStorage) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  std::string protocol("http");
-  std::string host("chromium.org");
-  unsigned short port = 80;
-  std::string database_identifier("id");
-  std::string origin("chromium.org");
-  FilePath file_path(FILE_PATH_LITERAL("/"));
-  int64 size = 1234;
-  base::Time last_modified = base::Time::Now();
-  BrowsingDataLocalStorageHelper::LocalStorageInfo info(protocol, host, port,
-      database_identifier, origin, file_path, size, last_modified);
-  details.reset([[CocoaCookieDetails alloc] initWithLocalStorage:&info]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeLocalStorage);
-  EXPECT_NSEQ(@"chromium.org", [details.get() domain]);
-  EXPECT_NSEQ(@"1234 B", [details.get() fileSize]);
-  EXPECT_NSNE(@"", [details.get() lastModified]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForTreeAppCache) {
-  scoped_nsobject<CocoaCookieDetails> details;
-
-  GURL url("http://chromium.org/stuff.manifest");
-  appcache::AppCacheInfo info;
-  info.creation_time = base::Time::Now();
-  info.last_update_time = base::Time::Now();
-  info.last_access_time = base::Time::Now();
-  info.size=2678;
-  info.manifest_url = url;
-  details.reset([[CocoaCookieDetails alloc] initWithAppCacheInfo:&info]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeAppCache);
-  EXPECT_NSEQ(@"http://chromium.org/stuff.manifest",
-              [details.get() manifestURL]);
-  EXPECT_NSEQ(@"2678 B", [details.get() fileSize]);
-  EXPECT_NSNE(@"", [details.get() lastAccessed]);
-  EXPECT_NSNE(@"", [details.get() created]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForTreeIndexedDB) {
-  scoped_nsobject<CocoaCookieDetails> details;
-
-  std::string protocol("http");
-  std::string host("moose.org");
-  unsigned short port = 80;
-  std::string database_identifier("id");
-  std::string origin("moose.org");
-  FilePath file_path(FILE_PATH_LITERAL("/"));
-  int64 size = 1234;
-  base::Time last_modified = base::Time::Now();
-  BrowsingDataIndexedDBHelper::IndexedDBInfo info(protocol,
-                                                  host,
-                                                  port,
-                                                  database_identifier,
-                                                  origin,
-                                                  file_path,
-                                                  size,
-                                                  last_modified);
-
-  details.reset([[CocoaCookieDetails alloc] initWithIndexedDBInfo:&info]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypeTreeIndexedDB);
-  EXPECT_NSEQ(@"moose.org", [details.get() domain]);
-  EXPECT_NSEQ(@"1234 B", [details.get() fileSize]);
-  EXPECT_NSNE(@"", [details.get() lastModified]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForPromptDatabase) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  std::string domain("chromium.org");
-  string16 name(base::SysNSStringToUTF16(@"wicked_name"));
-  string16 desc(base::SysNSStringToUTF16(@"desc"));
-  details.reset([[CocoaCookieDetails alloc] initWithDatabase:domain
-                                                databaseName:name
-                                         databaseDescription:desc
-                                                    fileSize:94]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypePromptDatabase);
-  EXPECT_NSEQ(@"chromium.org", [details.get() domain]);
-  EXPECT_NSEQ(@"wicked_name", [details.get() name]);
-  EXPECT_NSEQ(@"desc", [details.get() databaseDescription]);
-  EXPECT_NSEQ(@"94 B", [details.get() fileSize]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForPromptLocalStorage) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  std::string domain("chromium.org");
-  string16 key(base::SysNSStringToUTF16(@"testKey"));
-  string16 value(base::SysNSStringToUTF16(@"testValue"));
-  details.reset([[CocoaCookieDetails alloc] initWithLocalStorage:domain
-                                                             key:key
-                                                           value:value]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypePromptLocalStorage);
-  EXPECT_NSEQ(@"chromium.org", [details.get() domain]);
-  EXPECT_NSEQ(@"testKey", [details.get() localStorageKey]);
-  EXPECT_NSEQ(@"testValue", [details.get() localStorageValue]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-TEST_F(CookiesDetailsTest, CreateForPromptAppCache) {
-  scoped_nsobject<CocoaCookieDetails> details;
-  std::string manifestURL("http://html5demos.com/html5demo.manifest");
-  details.reset([[CocoaCookieDetails alloc]
-      initWithAppCacheManifestURL:manifestURL.c_str()]);
-
-  EXPECT_EQ([details.get() type], kCocoaCookieDetailsTypePromptAppCache);
-  EXPECT_NSEQ(@"http://html5demos.com/html5demo.manifest",
-              [details.get() manifestURL]);
-
-  EXPECT_TRUE([details.get() shouldHideCookieDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStorageTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabaseTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowAppCacheTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowIndexedDBTreeDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowLocalStoragePromptDetailsView]);
-  EXPECT_FALSE([details.get() shouldShowDatabasePromptDetailsView]);
-  EXPECT_TRUE([details.get() shouldShowAppCachePromptDetailsView]);
-}
-
-}
diff --git a/chrome/browser/ui/cocoa/cookie_details_view_controller.h b/chrome/browser/ui/cocoa/cookie_details_view_controller.h
deleted file mode 100644
index 63fff93..0000000
--- a/chrome/browser/ui/cocoa/cookie_details_view_controller.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "net/base/cookie_monster.h"
-
-@class CocoaCookieTreeNode;
-@class GTMUILocalizerAndLayoutTweaker;
-
-// Controller for the view that displays the details of a cookie,
-// used both in the cookie prompt dialog as well as the
-// show cookies preference sheet of content settings preferences.
-@interface CookieDetailsViewController : NSViewController {
- @private
-  // Allows direct access to the object controller for
-  // the displayed cookie information.
-  IBOutlet NSObjectController* objectController_;
-
-  // This explicit reference to the layout tweaker is
-  // required because it's necessary to reformat the view when
-  // the content object changes, since the content object may
-  // alter the widths of some of the fields displayed in the view.
-  IBOutlet GTMUILocalizerAndLayoutTweaker* tweaker_;
-}
-
-@property (nonatomic, readonly) BOOL hasExpiration;
-
-- (id)init;
-
-// Configures the cookie detail view that is managed by the controller
-// to display the information about a single cookie, the information
-// for which is explicitly passed in the parameter |content|.
-- (void)setContentObject:(id)content;
-
-// Adjust the size of the view to exactly fix the information text fields
-// that are visible inside it.
-- (void)shrinkViewToFit;
-
-// Called by the cookie tree dialog to establish a binding between
-// the the detail view's object controller and the tree controller.
-// This binding allows the cookie tree to use the detail view unmodified.
-- (void)configureBindingsForTreeController:(NSTreeController*)controller;
-
-// Action sent by the expiration date popup when the user
-// selects the menu item "When I close my browser".
-- (IBAction)setCookieDoesntHaveExplicitExpiration:(id)sender;
-
-// Action sent by the expiration date popup when the user
-// selects the menu item with an explicit date/time of expiration.
-- (IBAction)setCookieHasExplicitExpiration:(id)sender;
-
-@end
-
diff --git a/chrome/browser/ui/cocoa/cookie_details_view_controller.mm b/chrome/browser/ui/cocoa/cookie_details_view_controller.mm
deleted file mode 100644
index d3e1ea5..0000000
--- a/chrome/browser/ui/cocoa/cookie_details_view_controller.mm
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/cookie_details_view_controller.h"
-
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#import "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#import "chrome/browser/ui/cocoa/cookie_tree_node.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-namespace {
-static const int kExtraMarginBelowWhenExpirationEditable = 5;
-}
-
-#pragma mark View Controller
-
-@implementation CookieDetailsViewController
-@dynamic hasExpiration;
-
-- (id)init {
-  return [super initWithNibName:@"CookieDetailsView"
-                         bundle:base::mac::MainAppBundle()];
-}
-
-- (void)awakeFromNib {
-  DCHECK(objectController_);
-}
-
-// Finds and returns the y offset of the lowest-most non-hidden
-// text field in the view. This is used to shrink the view
-// appropriately so that it just fits its visible content.
-- (void)getLowestLabelVerticalPosition:(NSView*)view
-                   lowestLabelPosition:(float&)lowestLabelPosition {
-  if (![view isHidden]) {
-    if ([view isKindOfClass:[NSTextField class]]) {
-      NSRect frame = [view frame];
-      if (frame.origin.y < lowestLabelPosition) {
-        lowestLabelPosition = frame.origin.y;
-      }
-    }
-    for (NSView* subview in [view subviews]) {
-      [self getLowestLabelVerticalPosition:subview
-                       lowestLabelPosition:lowestLabelPosition];
-    }
-  }
-}
-
-- (void)setContentObject:(id)content {
-  // Make sure the view is loaded before we set the content object,
-  // otherwise, the KVO notifications to update the content don't
-  // reach the view and all of the detail values are default
-  // strings.
-  NSView* view = [self view];
-
-  [objectController_ setValue:content forKey:@"content"];
-
-  // View needs to be re-tweaked after setting the content object,
-  // since the expiration date may have changed, changing the
-  // size of the expiration popup.
-  [tweaker_ tweakUI:view];
-}
-
-- (void)shrinkViewToFit {
-  // Adjust the information pane to be exactly the right size
-  // to hold the visible text information fields.
-  NSView* view = [self view];
-  NSRect frame = [view frame];
-  float lowestLabelPosition = frame.origin.y + frame.size.height;
-  [self getLowestLabelVerticalPosition:view
-                   lowestLabelPosition:lowestLabelPosition];
-  float verticalDelta = lowestLabelPosition - frame.origin.y;
-
-  // Popup menu for the expiration is taller than the plain
-  // text, give it some more room.
-  if ([[[objectController_ content] details] canEditExpiration]) {
-    verticalDelta -= kExtraMarginBelowWhenExpirationEditable;
-  }
-
-  frame.origin.y += verticalDelta;
-  frame.size.height -= verticalDelta;
-  [[self view] setFrame:frame];
-}
-
-- (void)configureBindingsForTreeController:(NSTreeController*)treeController {
-  // There seems to be a bug in the binding logic that it's not possible
-  // to bind to the selection of the tree controller, the bind seems to
-  // require an additional path segment in the key, thus the use of
-  // selection.self rather than just selection below.
-  [objectController_ bind:@"contentObject"
-                 toObject:treeController
-              withKeyPath:@"selection.self"
-                  options:nil];
-}
-
-- (IBAction)setCookieDoesntHaveExplicitExpiration:(id)sender {
-  [[[objectController_ content] details] setHasExpiration:NO];
-}
-
-- (IBAction)setCookieHasExplicitExpiration:(id)sender {
-  [[[objectController_ content] details] setHasExpiration:YES];
-}
-
-- (BOOL)hasExpiration {
-  return [[[objectController_ content] details] hasExpiration];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/cookie_details_view_controller_unittest.mm b/chrome/browser/ui/cocoa/cookie_details_view_controller_unittest.mm
deleted file mode 100644
index 4a7e5da..0000000
--- a/chrome/browser/ui/cocoa/cookie_details_view_controller_unittest.mm
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "chrome/browser/ui/cocoa/cookie_details.h"
-#include "chrome/browser/ui/cocoa/cookie_details_view_controller.h"
-
-namespace {
-
-class CookieDetailsViewControllerTest : public CocoaTest {
-};
-
-static CocoaCookieDetails* CreateTestCookieDetails(BOOL canEditExpiration) {
-  GURL url("http://chromium.org");
-  std::string cookieLine(
-      "PHPSESSID=0123456789abcdef0123456789abcdef; path=/");
-  net::CookieMonster::ParsedCookie pc(cookieLine);
-  net::CookieMonster::CanonicalCookie cookie(url, pc);
-  NSString* origin = base::SysUTF8ToNSString("http://chromium.org");
-  CocoaCookieDetails* details = [CocoaCookieDetails alloc];
-  [details initWithCookie:&cookie
-                   origin:origin
-        canEditExpiration:canEditExpiration];
-  return [details autorelease];
-}
-
-static CookiePromptContentDetailsAdapter* CreateCookieTestContent(
-    BOOL canEditExpiration) {
-  CocoaCookieDetails* details = CreateTestCookieDetails(canEditExpiration);
-  return [[[CookiePromptContentDetailsAdapter alloc] initWithDetails:details]
-      autorelease];
-}
-
-static CocoaCookieDetails* CreateTestDatabaseDetails() {
-  std::string domain("chromium.org");
-  string16 name(base::SysNSStringToUTF16(@"wicked_name"));
-  string16 desc(base::SysNSStringToUTF16(@"wicked_desc"));
-  CocoaCookieDetails* details = [CocoaCookieDetails alloc];
-  [details initWithDatabase:domain
-               databaseName:name
-        databaseDescription:desc
-                   fileSize:2222];
-  return [details autorelease];
-}
-
-static CookiePromptContentDetailsAdapter* CreateDatabaseTestContent() {
-  CocoaCookieDetails* details = CreateTestDatabaseDetails();
-  return [[[CookiePromptContentDetailsAdapter alloc] initWithDetails:details]
-          autorelease];
-}
-
-TEST_F(CookieDetailsViewControllerTest, Create) {
-  scoped_nsobject<CookieDetailsViewController> detailsViewController(
-      [[CookieDetailsViewController alloc] init]);
-}
-
-TEST_F(CookieDetailsViewControllerTest, ShrinkToFit) {
-  scoped_nsobject<CookieDetailsViewController> detailsViewController(
-      [[CookieDetailsViewController alloc] init]);
-  scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
-      [CreateDatabaseTestContent() retain]);
-  [detailsViewController.get() setContentObject:adapter.get()];
-  NSRect beforeFrame = [[detailsViewController.get() view] frame];
-  [detailsViewController.get() shrinkViewToFit];
-  NSRect afterFrame = [[detailsViewController.get() view] frame];
-
-  EXPECT_TRUE(afterFrame.size.height < beforeFrame.size.width);
-}
-
-TEST_F(CookieDetailsViewControllerTest, ExpirationEditability) {
-  scoped_nsobject<CookieDetailsViewController> detailsViewController(
-      [[CookieDetailsViewController alloc] init]);
-  [detailsViewController view];
-  scoped_nsobject<CookiePromptContentDetailsAdapter> adapter(
-      [CreateCookieTestContent(YES) retain]);
-  [detailsViewController.get() setContentObject:adapter.get()];
-
-  EXPECT_FALSE([detailsViewController.get() hasExpiration]);
-  [detailsViewController.get() setCookieHasExplicitExpiration:adapter.get()];
-  EXPECT_TRUE([detailsViewController.get() hasExpiration]);
-  [detailsViewController.get()
-      setCookieDoesntHaveExplicitExpiration:adapter.get()];
-  EXPECT_FALSE([detailsViewController.get() hasExpiration]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/cookie_tree_node.h b/chrome/browser/ui/cocoa/cookie_tree_node.h
deleted file mode 100644
index ec1b2d2..0000000
--- a/chrome/browser/ui/cocoa/cookie_tree_node.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/cookies_tree_model.h"
-#include "chrome/browser/ui/cocoa/cookie_details.h"
-
-@interface CocoaCookieTreeNode : NSObject {
-  scoped_nsobject<NSString> title_;
-  scoped_nsobject<NSMutableArray> children_;
-  scoped_nsobject<CocoaCookieDetails> details_;
-  CookieTreeNode* treeNode_;  // weak
-}
-
-// Designated initializer.
-- (id)initWithNode:(CookieTreeNode*)node;
-
-// Re-sets all the members of the node based on |treeNode_|.
-- (void)rebuild;
-
-// Common getters..
-- (NSString*)title;
-- (CocoaCookieDetailsType)nodeType;
-- (TreeModelNode*)treeNode;
-
-// |-mutableChildren| exists so that the CookiesTreeModelObserverBridge can
-// operate on the children. Note that this lazily creates children.
-- (NSMutableArray*)mutableChildren;
-- (NSArray*)children;
-- (BOOL)isLeaf;
-
-- (CocoaCookieDetails*)details;
-
-@end
diff --git a/chrome/browser/ui/cocoa/cookie_tree_node.mm b/chrome/browser/ui/cocoa/cookie_tree_node.mm
deleted file mode 100644
index fa4da84..0000000
--- a/chrome/browser/ui/cocoa/cookie_tree_node.mm
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/cookie_tree_node.h"
-
-#include "base/sys_string_conversions.h"
-
-@implementation CocoaCookieTreeNode
-
-- (id)initWithNode:(CookieTreeNode*)node {
-  if ((self = [super init])) {
-    DCHECK(node);
-    treeNode_ = node;
-    [self rebuild];
-  }
-  return self;
-}
-
-- (void)rebuild {
-  title_.reset([base::SysUTF16ToNSString(treeNode_->GetTitle()) retain]);
-  children_.reset();
-  // The tree node assumes ownership of the cookie details object
-  details_.reset([[CocoaCookieDetails createFromCookieTreeNode:(treeNode_)]
-      retain]);
-}
-
-- (NSString*)title {
-  return title_.get();
-}
-
-- (CocoaCookieDetailsType)nodeType {
-  return [details_.get() type];
-}
-
-- (TreeModelNode*)treeNode {
-  return treeNode_;
-}
-
-- (NSMutableArray*)mutableChildren {
-  if (!children_.get()) {
-    const int childCount = treeNode_->GetChildCount();
-    children_.reset([[NSMutableArray alloc] initWithCapacity:childCount]);
-    for (int i = 0; i < childCount; ++i) {
-      CookieTreeNode* child = treeNode_->GetChild(i);
-      scoped_nsobject<CocoaCookieTreeNode> childNode(
-          [[CocoaCookieTreeNode alloc] initWithNode:child]);
-      [children_ addObject:childNode.get()];
-    }
-  }
-  return children_.get();
-}
-
-- (NSArray*)children {
-  return [self mutableChildren];
-}
-
-- (BOOL)isLeaf {
-  return [self nodeType] != kCocoaCookieDetailsTypeFolder;
-};
-
-- (NSString*)description {
-  NSString* format =
-      @"<CocoaCookieTreeNode @ %p (title=%@, nodeType=%d, childCount=%u)";
-  return [NSString stringWithFormat:format, self, [self title],
-      [self nodeType], [[self children] count]];
-}
-
-- (CocoaCookieDetails*)details {
-  return details_;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/cookies_window_controller.h b/chrome/browser/ui/cocoa/cookies_window_controller.h
deleted file mode 100644
index 658bfa7..0000000
--- a/chrome/browser/ui/cocoa/cookies_window_controller.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/cookies_tree_model.h"
-#import "chrome/browser/ui/cocoa/cookie_tree_node.h"
-#include "net/base/cookie_monster.h"
-
-@class CookiesWindowController;
-@class CookieDetailsViewController;
-class Profile;
-class TreeModel;
-class TreeModelNode;
-
-namespace {
-class CookiesWindowControllerTest;
-}
-
-// Thin bridge to the window controller that performs model update actions
-// directly on the treeController_.
-class CookiesTreeModelObserverBridge : public CookiesTreeModel::Observer {
- public:
-  explicit CookiesTreeModelObserverBridge(CookiesWindowController* controller);
-
-  // Begin TreeModelObserver implementation.
-  virtual void TreeNodesAdded(TreeModel* model,
-                              TreeModelNode* parent,
-                              int start,
-                              int count);
-  virtual void TreeNodesRemoved(TreeModel* model,
-                                TreeModelNode* parent,
-                                int start,
-                                int count);
-  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node);
-  // End TreeModelObserver implementation.
-
-  virtual void TreeModelBeginBatch(CookiesTreeModel* model);
-  virtual void TreeModelEndBatch(CookiesTreeModel* model);
-
-  // Invalidates the Cocoa model. This is used to tear down the Cocoa model
-  // when we're about to entirely rebuild it.
-  void InvalidateCocoaModel();
-
- private:
-  friend class ::CookiesWindowControllerTest;
-
-  // Creates a CocoaCookieTreeNode from a platform-independent one.
-  // Return value is autoreleased. This creates child nodes recusively.
-  CocoaCookieTreeNode* CocoaNodeFromTreeNode(TreeModelNode* node);
-
-  // Finds the Cocoa model node based on a platform-independent one. This is
-  // done by comparing the treeNode pointers. |start| is the node to start
-  // searching at. If |start| is nil, the root is used.
-  CocoaCookieTreeNode* FindCocoaNode(TreeModelNode* node,
-                                     CocoaCookieTreeNode* start);
-
-  // Returns whether or not the Cocoa tree model is built.
-  bool HasCocoaModel();
-
-  CookiesWindowController* window_controller_;  // weak, owns us.
-
-  // If this is true, then the Model has informed us that it is batching
-  // updates. Rather than updating the Cocoa side of the model, we ignore those
-  // small changes and rebuild once at the end.
-  bool batch_update_;
-};
-
-// Controller for the cookies manager. This class stores an internal copy of
-// the CookiesTreeModel but with Cocoa-converted values (NSStrings and NSImages
-// instead of std::strings and SkBitmaps). Doing this allows us to use bindings
-// for the interface. Changes are pushed to this internal model via a very thin
-// bridge (see above).
-@interface CookiesWindowController : NSWindowController
-                                     <NSOutlineViewDelegate,
-                                      NSWindowDelegate> {
- @private
-  // Platform-independent model and C++/Obj-C bridge components.
-  scoped_ptr<CookiesTreeModel> treeModel_;
-  scoped_ptr<CookiesTreeModelObserverBridge> modelObserver_;
-
-  // Cached array of icons.
-  scoped_nsobject<NSMutableArray> icons_;
-
-  // Our Cocoa copy of the model.
-  scoped_nsobject<CocoaCookieTreeNode> cocoaTreeModel_;
-
-  // A flag indicating whether or not the "Remove" button should be enabled.
-  BOOL removeButtonEnabled_;
-
-  IBOutlet NSTreeController* treeController_;
-  IBOutlet NSOutlineView* outlineView_;
-  IBOutlet NSSearchField* searchField_;
-  IBOutlet NSView* cookieDetailsViewPlaceholder_;
-  IBOutlet NSButton* removeButton_;
-
-  scoped_nsobject<CookieDetailsViewController> detailsViewController_;
-  Profile* profile_;  // weak
-  BrowsingDataDatabaseHelper* databaseHelper_;  // weak
-  BrowsingDataLocalStorageHelper* storageHelper_;  // weak
-  BrowsingDataAppCacheHelper* appcacheHelper_;  // weak
-  BrowsingDataIndexedDBHelper* indexedDBHelper_;  // weak
-}
-@property (assign, nonatomic) BOOL removeButtonEnabled;
-@property (readonly, nonatomic) NSTreeController* treeController;
-
-// Designated initializer. Profile cannot be NULL.
-- (id)initWithProfile:(Profile*)profile
-       databaseHelper:(BrowsingDataDatabaseHelper*)databaseHelper
-        storageHelper:(BrowsingDataLocalStorageHelper*)storageHelper
-       appcacheHelper:(BrowsingDataAppCacheHelper*)appcacheHelper
-      indexedDBHelper:(BrowsingDataIndexedDBHelper*)indexedDBHelper;
-
-// Shows the cookies window as a modal sheet attached to |window|.
-- (void)attachSheetTo:(NSWindow*)window;
-
-// Updates the filter from the search field.
-- (IBAction)updateFilter:(id)sender;
-
-// Delete cookie actions.
-- (IBAction)deleteCookie:(id)sender;
-- (IBAction)deleteAllCookies:(id)sender;
-
-// Closes the sheet and ends the modal loop. This will also cleanup the memory.
-- (IBAction)closeSheet:(id)sender;
-
-// Returns the cocoaTreeModel_.
-- (CocoaCookieTreeNode*)cocoaTreeModel;
-- (void)setCocoaTreeModel:(CocoaCookieTreeNode*)model;
-
-// Returns the treeModel_.
-- (CookiesTreeModel*)treeModel;
-
-@end
-
-@interface CookiesWindowController (UnitTesting)
-- (void)deleteNodeAtIndexPath:(NSIndexPath*)path;
-- (void)clearBrowsingDataNotification:(NSNotification*)notif;
-- (CookiesTreeModelObserverBridge*)modelObserver;
-- (NSArray*)icons;
-- (void)loadTreeModelFromProfile;
-@end
diff --git a/chrome/browser/ui/cocoa/cookies_window_controller.mm b/chrome/browser/ui/cocoa/cookies_window_controller.mm
deleted file mode 100644
index 5e5f74f..0000000
--- a/chrome/browser/ui/cocoa/cookies_window_controller.mm
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/cookies_window_controller.h"
-
-#include <queue>
-#include <vector>
-
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#import "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/browsing_data_remover.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
-#include "chrome/browser/ui/cocoa/cookie_details_view_controller.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/apple/ImageAndTextCell.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-// Key path used for notifying KVO.
-static NSString* const kCocoaTreeModel = @"cocoaTreeModel";
-
-CookiesTreeModelObserverBridge::CookiesTreeModelObserverBridge(
-    CookiesWindowController* controller)
-    : window_controller_(controller),
-      batch_update_(false) {
-}
-
-// Notification that nodes were added to the specified parent.
-void CookiesTreeModelObserverBridge::TreeNodesAdded(TreeModel* model,
-                                                    TreeModelNode* parent,
-                                                    int start,
-                                                    int count) {
-  // We're in for a major rebuild. Ignore this request.
-  if (batch_update_ || !HasCocoaModel())
-    return;
-
-  CocoaCookieTreeNode* cocoa_parent = FindCocoaNode(parent, nil);
-  NSMutableArray* cocoa_children = [cocoa_parent mutableChildren];
-
-  [window_controller_ willChangeValueForKey:kCocoaTreeModel];
-  CookieTreeNode* cookie_parent = static_cast<CookieTreeNode*>(parent);
-  for (int i = 0; i < count; ++i) {
-    CookieTreeNode* cookie_child = cookie_parent->GetChild(start + i);
-    CocoaCookieTreeNode* new_child = CocoaNodeFromTreeNode(cookie_child);
-    [cocoa_children addObject:new_child];
-  }
-  [window_controller_ didChangeValueForKey:kCocoaTreeModel];
-}
-
-// Notification that nodes were removed from the specified parent.
-void CookiesTreeModelObserverBridge::TreeNodesRemoved(TreeModel* model,
-                                                      TreeModelNode* parent,
-                                                      int start,
-                                                      int count) {
-  // We're in for a major rebuild. Ignore this request.
-  if (batch_update_ || !HasCocoaModel())
-    return;
-
-  CocoaCookieTreeNode* cocoa_parent = FindCocoaNode(parent, nil);
-  [window_controller_ willChangeValueForKey:kCocoaTreeModel];
-  NSMutableArray* cocoa_children = [cocoa_parent mutableChildren];
-  for (int i = start + count - 1; i >= start; --i) {
-    [cocoa_children removeObjectAtIndex:i];
-  }
-  [window_controller_ didChangeValueForKey:kCocoaTreeModel];
-}
-
-// Notification that the contents of a node has changed.
-void CookiesTreeModelObserverBridge::TreeNodeChanged(TreeModel* model,
-                                                     TreeModelNode* node) {
-  // If we don't have a Cocoa model, only let the root node change.
-  if (batch_update_ || (!HasCocoaModel() && model->GetRoot() != node))
-    return;
-
-  if (HasCocoaModel()) {
-    // We still have a Cocoa model, so just rebuild the node.
-    [window_controller_ willChangeValueForKey:kCocoaTreeModel];
-    CocoaCookieTreeNode* changed_node = FindCocoaNode(node, nil);
-    [changed_node rebuild];
-    [window_controller_ didChangeValueForKey:kCocoaTreeModel];
-  } else {
-    // Full rebuild.
-    [window_controller_ setCocoaTreeModel:CocoaNodeFromTreeNode(node)];
-  }
-}
-
-void CookiesTreeModelObserverBridge::TreeModelBeginBatch(
-    CookiesTreeModel* model) {
-  batch_update_ = true;
-}
-
-void CookiesTreeModelObserverBridge::TreeModelEndBatch(
-    CookiesTreeModel* model) {
-  DCHECK(batch_update_);
-  CocoaCookieTreeNode* root = CocoaNodeFromTreeNode(model->GetRoot());
-  [window_controller_ setCocoaTreeModel:root];
-  batch_update_ = false;
-}
-
-void CookiesTreeModelObserverBridge::InvalidateCocoaModel() {
-  [[[window_controller_ cocoaTreeModel] mutableChildren] removeAllObjects];
-}
-
-CocoaCookieTreeNode* CookiesTreeModelObserverBridge::CocoaNodeFromTreeNode(
-    TreeModelNode* node) {
-  CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
-  return [[[CocoaCookieTreeNode alloc] initWithNode:cookie_node] autorelease];
-}
-
-// Does breadth-first search on the tree to find |node|. This method is most
-// commonly used to find origin/folder nodes, which are at the first level off
-// the root (hence breadth-first search).
-CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode(
-    TreeModelNode* target, CocoaCookieTreeNode* start) {
-  if (!start) {
-    start = [window_controller_ cocoaTreeModel];
-  }
-  if ([start treeNode] == target) {
-    return start;
-  }
-
-  // Enqueue the root node of the search (sub-)tree.
-  std::queue<CocoaCookieTreeNode*> horizon;
-  horizon.push(start);
-
-  // Loop until we've looked at every node or we found the target.
-  while (!horizon.empty()) {
-    // Dequeue the item at the front.
-    CocoaCookieTreeNode* node = horizon.front();
-    horizon.pop();
-
-    // If this is the droid we're looking for, report it.
-    if ([node treeNode] == target)
-      return node;
-
-    // "Move along, move along." by adding all child nodes to the queue.
-    if (![node isLeaf]) {
-      NSArray* children = [node children];
-      for (CocoaCookieTreeNode* child in children) {
-        horizon.push(child);
-      }
-    }
-  }
-
-  return nil;  // We couldn't find the node.
-}
-
-// Returns whether or not the Cocoa tree model is built.
-bool CookiesTreeModelObserverBridge::HasCocoaModel() {
-  return ([[[window_controller_ cocoaTreeModel] children] count] > 0U);
-}
-
-#pragma mark Window Controller
-
-@implementation CookiesWindowController
-
-@synthesize removeButtonEnabled = removeButtonEnabled_;
-@synthesize treeController = treeController_;
-
-- (id)initWithProfile:(Profile*)profile
-       databaseHelper:(BrowsingDataDatabaseHelper*)databaseHelper
-        storageHelper:(BrowsingDataLocalStorageHelper*)storageHelper
-       appcacheHelper:(BrowsingDataAppCacheHelper*)appcacheHelper
-      indexedDBHelper:(BrowsingDataIndexedDBHelper*)indexedDBHelper {
-  DCHECK(profile);
-  NSString* nibpath = [base::mac::MainAppBundle() pathForResource:@"Cookies"
-                                                          ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    profile_ = profile;
-    databaseHelper_ = databaseHelper;
-    storageHelper_ = storageHelper;
-    appcacheHelper_ = appcacheHelper;
-    indexedDBHelper_ = indexedDBHelper;
-
-    [self loadTreeModelFromProfile];
-
-    // Register for Clear Browsing Data controller so we update appropriately.
-    ClearBrowsingDataController* clearingController =
-        [ClearBrowsingDataController controllerForProfile:profile_];
-    if (clearingController) {
-      NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-      [center addObserver:self
-                 selector:@selector(clearBrowsingDataNotification:)
-                     name:kClearBrowsingDataControllerDidDelete
-                   object:clearingController];
-    }
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [super dealloc];
-}
-
-- (void)awakeFromNib {
-  DCHECK([self window]);
-  DCHECK_EQ(self, [[self window] delegate]);
-
-  detailsViewController_.reset([[CookieDetailsViewController alloc] init]);
-
-  NSView* detailView = [detailsViewController_.get() view];
-  NSRect viewFrameRect = [cookieDetailsViewPlaceholder_ frame];
-  [[detailsViewController_.get() view] setFrame:viewFrameRect];
-  [[cookieDetailsViewPlaceholder_ superview]
-      replaceSubview:cookieDetailsViewPlaceholder_
-                with:detailView];
-
-  [detailsViewController_ configureBindingsForTreeController:treeController_];
-}
-
-- (void)windowWillClose:(NSNotification*)notif {
-  [searchField_ setTarget:nil];
-  [outlineView_ setDelegate:nil];
-  [self autorelease];
-}
-
-- (void)attachSheetTo:(NSWindow*)window {
-  [NSApp beginSheet:[self window]
-     modalForWindow:window
-      modalDelegate:self
-     didEndSelector:@selector(sheetEndSheet:returnCode:contextInfo:)
-        contextInfo:nil];
-}
-
-- (void)sheetEndSheet:(NSWindow*)sheet
-          returnCode:(NSInteger)returnCode
-         contextInfo:(void*)context {
-  [sheet close];
-  [sheet orderOut:self];
-}
-
-- (IBAction)updateFilter:(id)sender {
-  DCHECK([sender isKindOfClass:[NSSearchField class]]);
-  NSString* string = [sender stringValue];
-  // Invalidate the model here because all the nodes are going to be removed
-  // in UpdateSearchResults(). This could lead to there temporarily being
-  // invalid pointers in the Cocoa model.
-  modelObserver_->InvalidateCocoaModel();
-  treeModel_->UpdateSearchResults(base::SysNSStringToWide(string));
-}
-
-- (IBAction)deleteCookie:(id)sender {
-  DCHECK_EQ(1U, [[treeController_ selectedObjects] count]);
-  [self deleteNodeAtIndexPath:[treeController_ selectionIndexPath]];
-}
-
-// This will delete the Cocoa model node as well as the backing model object at
-// the specified index path in the Cocoa model. If the node that was deleted
-// was the sole child of the parent node, this will be called recursively to
-// delete empty parents.
-- (void)deleteNodeAtIndexPath:(NSIndexPath*)path {
-  NSTreeNode* treeNode =
-      [[treeController_ arrangedObjects] descendantNodeAtIndexPath:path];
-  if (!treeNode)
-    return;
-
-  CocoaCookieTreeNode* node = [treeNode representedObject];
-  CookieTreeNode* cookie = static_cast<CookieTreeNode*>([node treeNode]);
-  treeModel_->DeleteCookieNode(cookie);
-  // If there is a next cookie, this will select it because items will slide
-  // up. If there is no next cookie, this is a no-op.
-  [treeController_ setSelectionIndexPath:path];
-  // If the above setting of the selection was in fact a no-op, find the next
-  // node to select.
-  if (![[treeController_ selectedObjects] count]) {
-    NSUInteger lastIndex = [path indexAtPosition:[path length] - 1];
-    if (lastIndex != 0) {
-      // If there any nodes remaining, select the node that is in the list
-      // before this one.
-      path = [path indexPathByRemovingLastIndex];
-      path = [path indexPathByAddingIndex:lastIndex - 1];
-      [treeController_ setSelectionIndexPath:path];
-    }
-  }
-}
-
-- (IBAction)deleteAllCookies:(id)sender {
-  // Preemptively delete all cookies in the Cocoa model.
-  modelObserver_->InvalidateCocoaModel();
-  treeModel_->DeleteAllStoredObjects();
-}
-
-- (IBAction)closeSheet:(id)sender {
-  [NSApp endSheet:[self window]];
-}
-
-- (void)clearBrowsingDataNotification:(NSNotification*)notif {
-  NSNumber* removeMask =
-      [[notif userInfo] objectForKey:kClearBrowsingDataControllerRemoveMask];
-  if ([removeMask intValue] & BrowsingDataRemover::REMOVE_COOKIES) {
-    [self loadTreeModelFromProfile];
-  }
-}
-
-// Override keyDown on the controller (which is the first responder) to allow
-// both backspace and delete to be captured by the Remove button.
-- (void)keyDown:(NSEvent*)theEvent {
-  NSString* keys = [theEvent characters];
-  if ([keys length]) {
-    unichar key = [keys characterAtIndex:0];
-    // The button has a key equivalent of backspace, so examine this event for
-    // forward delete.
-    if ((key == NSDeleteCharacter || key == NSDeleteFunctionKey) &&
-        [self removeButtonEnabled]) {
-      [removeButton_ performClick:self];
-      return;
-    }
-  }
-  [super keyDown:theEvent];
-}
-
-#pragma mark Getters and Setters
-
-- (CocoaCookieTreeNode*)cocoaTreeModel {
-  return cocoaTreeModel_.get();
-}
-- (void)setCocoaTreeModel:(CocoaCookieTreeNode*)model {
-  cocoaTreeModel_.reset([model retain]);
-}
-
-- (CookiesTreeModel*)treeModel {
-  return treeModel_.get();
-}
-
-#pragma mark Outline View Delegate
-
-- (void)outlineView:(NSOutlineView*)outlineView
-    willDisplayCell:(id)cell
-     forTableColumn:(NSTableColumn*)tableColumn
-               item:(id)item {
-  CocoaCookieTreeNode* node = [item representedObject];
-  int index = treeModel_->GetIconIndex([node treeNode]);
-  NSImage* icon = nil;
-  if (index >= 0)
-    icon = [icons_ objectAtIndex:index];
-  else
-    icon = [icons_ lastObject];
-  [(ImageAndTextCell*)cell setImage:icon];
-}
-
-- (void)outlineViewItemDidExpand:(NSNotification*)notif {
-  NSTreeNode* item = [[notif userInfo] objectForKey:@"NSObject"];
-  CocoaCookieTreeNode* node = [item representedObject];
-  NSArray* children = [node children];
-  if ([children count] == 1U) {
-    // The node that will expand has one child. Do the user a favor and expand
-    // that node (saving her a click) if it is non-leaf.
-    CocoaCookieTreeNode* child = [children lastObject];
-    if (![child isLeaf]) {
-      NSOutlineView* outlineView = [notif object];
-      // Tell the OutlineView to expand the NSTreeNode, not the model object.
-      children = [item childNodes];
-      DCHECK_EQ([children count], 1U);
-      [outlineView expandItem:[children lastObject]];
-      // Select the first node in that child set.
-      NSTreeNode* folderChild = [children lastObject];
-      if ([[folderChild childNodes] count] > 0) {
-        NSTreeNode* firstCookieChild =
-            [[folderChild childNodes] objectAtIndex:0];
-        [treeController_ setSelectionIndexPath:[firstCookieChild indexPath]];
-      }
-    }
-  }
-}
-
-- (void)outlineViewSelectionDidChange:(NSNotification*)notif {
-  // Multi-selection should be disabled in the UI, but for sanity, double-check
-  // that they can't do it here.
-  NSArray* selectedObjects = [treeController_ selectedObjects];
-  NSUInteger count = [selectedObjects count];
-  if (count != 1U) {
-    DCHECK_LT(count, 1U) << "User was able to select more than 1 cookie node!";
-    [self setRemoveButtonEnabled:NO];
-    return;
-  }
-
-  // Go through the selection's indexPath and make sure that the node that is
-  // being referenced actually exists in the Cocoa model.
-  NSIndexPath* selection = [treeController_ selectionIndexPath];
-  NSUInteger length = [selection length];
-  CocoaCookieTreeNode* node = [self cocoaTreeModel];
-  for (NSUInteger i = 0; i < length; ++i) {
-    NSUInteger childIndex = [selection indexAtPosition:i];
-    if (childIndex >= [[node children] count]) {
-      [self setRemoveButtonEnabled:NO];
-      return;
-    }
-    node = [[node children] objectAtIndex:childIndex];
-  }
-
-  // If there is a valid selection, make sure that the remove
-  // button is enabled.
-  [self setRemoveButtonEnabled:YES];
-}
-
-#pragma mark Unit Testing
-
-- (CookiesTreeModelObserverBridge*)modelObserver {
-  return modelObserver_.get();
-}
-
-- (NSArray*)icons {
-  return icons_.get();
-}
-
-// Re-initializes the |treeModel_|, creates a new observer for it, and re-
-// builds the |cocoaTreeModel_|. We use this to initialize the controller and
-// to rebuild after the user clears browsing data. Because the models get
-// clobbered, we rebuild the icon cache for safety (though they do not change).
-- (void)loadTreeModelFromProfile {
-  treeModel_.reset(new CookiesTreeModel(
-      profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(),
-      databaseHelper_,
-      storageHelper_,
-      NULL,
-      appcacheHelper_,
-      indexedDBHelper_));
-  modelObserver_.reset(new CookiesTreeModelObserverBridge(self));
-  treeModel_->AddObserver(modelObserver_.get());
-
-  // Convert the model's icons from Skia to Cocoa.
-  std::vector<SkBitmap> skiaIcons;
-  treeModel_->GetIcons(&skiaIcons);
-  icons_.reset([[NSMutableArray alloc] init]);
-  for (std::vector<SkBitmap>::iterator it = skiaIcons.begin();
-       it != skiaIcons.end(); ++it) {
-    [icons_ addObject:gfx::SkBitmapToNSImage(*it)];
-  }
-
-  // Default icon will be the last item in the array.
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  // TODO(rsesek): Rename this resource now that it's in multiple places.
-  [icons_ addObject:rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER)];
-
-  // Create the Cocoa model.
-  CookieTreeNode* root = static_cast<CookieTreeNode*>(treeModel_->GetRoot());
-  scoped_nsobject<CocoaCookieTreeNode> model(
-      [[CocoaCookieTreeNode alloc] initWithNode:root]);
-  [self setCocoaTreeModel:model.get()];  // Takes ownership.
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/cookies_window_controller_unittest.mm b/chrome/browser/ui/cocoa/cookies_window_controller_unittest.mm
deleted file mode 100644
index 5272cd2..0000000
--- a/chrome/browser/ui/cocoa/cookies_window_controller_unittest.mm
+++ /dev/null
@@ -1,687 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "app/l10n_util_mac.h"
-#include "app/tree_model.h"
-#import "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browsing_data_remover.h"
-#include "chrome/browser/cookies_tree_model.h"
-#include "chrome/browser/mock_browsing_data_database_helper.h"
-#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
-#include "chrome/browser/mock_browsing_data_appcache_helper.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/cookies_window_controller.h"
-#include "chrome/common/net/url_request_context_getter.h"
-#include "chrome/test/testing_profile.h"
-#include "googleurl/src/gurl.h"
-#include "grit/generated_resources.h"
-#include "net/url_request/url_request_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-
-// Used to test FindCocoaNode. This only sets the title and node, without
-// initializing any other members.
-@interface FakeCocoaCookieTreeNode : CocoaCookieTreeNode {
-  TreeModelNode* testNode_;
-}
-- (id)initWithTreeNode:(TreeModelNode*)node;
-@end
-@implementation FakeCocoaCookieTreeNode
-- (id)initWithTreeNode:(TreeModelNode*)node {
-  if ((self = [super init])) {
-    testNode_ = node;
-    children_.reset([[NSMutableArray alloc] init]);
-  }
-  return self;
-}
-- (TreeModelNode*)treeNode {
-  return testNode_;
-}
-@end
-
-namespace {
-
-class CookiesWindowControllerTest : public CocoaTest {
- public:
-
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    TestingProfile* profile = browser_helper_.profile();
-    profile->CreateRequestContext();
-    database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
-    local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
-    appcache_helper_ = new MockBrowsingDataAppCacheHelper(profile);
-    controller_.reset(
-        [[CookiesWindowController alloc] initWithProfile:profile
-                                          databaseHelper:database_helper_
-                                           storageHelper:local_storage_helper_
-                                          appcacheHelper:appcache_helper_]
-    );
-  }
-
-  virtual void TearDown() {
-    CocoaTest::TearDown();
-  }
-
-  CocoaCookieTreeNode* CocoaNodeFromTreeNode(TreeModelNode* node) {
-    return [controller_ modelObserver]->CocoaNodeFromTreeNode(node);
-  }
-
-  CocoaCookieTreeNode* FindCocoaNode(TreeModelNode* node,
-                                     CocoaCookieTreeNode* start) {
-    return [controller_ modelObserver]->FindCocoaNode(node, start);
-  }
-
- protected:
-  BrowserTestHelper browser_helper_;
-  scoped_nsobject<CookiesWindowController> controller_;
-  MockBrowsingDataDatabaseHelper* database_helper_;
-  MockBrowsingDataLocalStorageHelper* local_storage_helper_;
-  MockBrowsingDataAppCacheHelper* appcache_helper_;
-};
-
-TEST_F(CookiesWindowControllerTest, Construction) {
-  std::vector<SkBitmap> skia_icons;
-  [controller_ treeModel]->GetIcons(&skia_icons);
-
-  EXPECT_EQ([[controller_ icons] count], skia_icons.size() + 1U);
-}
-
-TEST_F(CookiesWindowControllerTest, FindCocoaNodeRoot) {
-  scoped_ptr< TreeNodeWithValue<int> > search(new TreeNodeWithValue<int>(42));
-  scoped_nsobject<FakeCocoaCookieTreeNode> node(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:search.get()]);
-  EXPECT_EQ(node.get(), FindCocoaNode(search.get(), node.get()));
-}
-
-TEST_F(CookiesWindowControllerTest, FindCocoaNodeImmediateChild) {
-  scoped_ptr< TreeNodeWithValue<int> > parent(new TreeNodeWithValue<int>(100));
-  scoped_ptr< TreeNodeWithValue<int> > child1(new TreeNodeWithValue<int>(10));
-  scoped_ptr< TreeNodeWithValue<int> > child2(new TreeNodeWithValue<int>(20));
-  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaParent(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:parent.get()]);
-  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild1(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child1.get()]);
-  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild2(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child2.get()]);
-  [[cocoaParent mutableChildren] addObject:cocoaChild1.get()];
-  [[cocoaParent mutableChildren] addObject:cocoaChild2.get()];
-
-  EXPECT_EQ(cocoaChild2.get(), FindCocoaNode(child2.get(), cocoaParent.get()));
-}
-
-TEST_F(CookiesWindowControllerTest, FindCocoaNodeRecursive) {
-  scoped_ptr< TreeNodeWithValue<int> > parent(new TreeNodeWithValue<int>(100));
-  scoped_ptr< TreeNodeWithValue<int> > child1(new TreeNodeWithValue<int>(10));
-  scoped_ptr< TreeNodeWithValue<int> > child2(new TreeNodeWithValue<int>(20));
-  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaParent(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:parent.get()]);
-  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild1(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child1.get()]);
-  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild2(
-      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child2.get()]);
-  [[cocoaParent mutableChildren] addObject:cocoaChild1.get()];
-  [[cocoaChild1 mutableChildren] addObject:cocoaChild2.get()];
-
-  EXPECT_EQ(cocoaChild2.get(), FindCocoaNode(child2.get(), cocoaParent.get()));
-}
-
-TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeCookie) {
-  net::CookieMonster* cm = browser_helper_.profile()->GetCookieMonster();
-  cm->SetCookie(GURL("http://foo.com"), "A=B");
-  CookiesTreeModel model(cm, database_helper_, local_storage_helper_, nil, nil);
-
-  // Root --> foo.com --> Cookies --> A. Create node for 'A'.
-  TreeModelNode* node = model.GetRoot()->GetChild(0)->GetChild(0)->GetChild(0);
-  CocoaCookieTreeNode* cookie = CocoaNodeFromTreeNode(node);
-
-  CocoaCookieDetails* details = [cookie details];
-  EXPECT_NSEQ(@"B", [details content]);
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_EXPIRES_SESSION),
-              [details expires]);
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_SENDFOR_ANY),
-              [details sendFor]);
-  EXPECT_NSEQ(@"A", [cookie title]);
-  EXPECT_NSEQ(@"A", [details name]);
-  EXPECT_NSEQ(@"/", [details path]);
-  EXPECT_EQ(0U, [[cookie children] count]);
-  EXPECT_TRUE([details created]);
-  EXPECT_TRUE([cookie isLeaf]);
-  EXPECT_EQ(node, [cookie treeNode]);
-}
-
-TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeRecursive) {
-  net::CookieMonster* cm = browser_helper_.profile()->GetCookieMonster();
-  cm->SetCookie(GURL("http://foo.com"), "A=B");
-  CookiesTreeModel model(cm, database_helper_, local_storage_helper_, nil, nil);
-
-  // Root --> foo.com --> Cookies --> A. Create node for 'foo.com'.
-  CookieTreeNode* node = model.GetRoot()->GetChild(0);
-  CocoaCookieTreeNode* domain = CocoaNodeFromTreeNode(node);
-  CocoaCookieTreeNode* cookies = [[domain children] objectAtIndex:0];
-  CocoaCookieTreeNode* cookie = [[cookies children] objectAtIndex:0];
-
-  // Test domain-level node.
-  EXPECT_NSEQ(@"foo.com", [domain title]);
-
-  EXPECT_FALSE([domain isLeaf]);
-  EXPECT_EQ(1U, [[domain children] count]);
-  EXPECT_EQ(node, [domain treeNode]);
-
-  // Test "Cookies" folder node.
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIES), [cookies title]);
-  EXPECT_FALSE([cookies isLeaf]);
-  EXPECT_EQ(1U, [[cookies children] count]);
-  EXPECT_EQ(node->GetChild(0), [cookies treeNode]);
-
-  // Test cookie node. This is the same as CocoaNodeFromTreeNodeCookie.
-  CocoaCookieDetails* details = [cookie details];
-  EXPECT_NSEQ(@"B", [details content]);
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_EXPIRES_SESSION),
-              [details expires]);
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_SENDFOR_ANY),
-              [details sendFor]);
-  EXPECT_NSEQ(@"A", [cookie title]);
-  EXPECT_NSEQ(@"A", [details name]);
-  EXPECT_NSEQ(@"/", [details path]);
-  EXPECT_NSEQ(@"foo.com", [details domain]);
-  EXPECT_EQ(0U, [[cookie children] count]);
-  EXPECT_TRUE([details created]);
-  EXPECT_TRUE([cookie isLeaf]);
-  EXPECT_EQ(node->GetChild(0)->GetChild(0), [cookie treeNode]);
-}
-
-TEST_F(CookiesWindowControllerTest, TreeNodesAdded) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-
-  // Root --> foo.com --> Cookies.
-  NSMutableArray* cocoa_children =
-      [[[[[[controller_ cocoaTreeModel] children] objectAtIndex:0]
-          children] objectAtIndex:0] mutableChildren];
-  EXPECT_EQ(1U, [cocoa_children count]);
-
-  // Create some cookies.
-  cm->SetCookie(url, "C=D");
-  cm->SetCookie(url, "E=F");
-
-  net::CookieList list = cm->GetAllCookies();
-  CookiesTreeModel* model = [controller_ treeModel];
-  // Root --> foo.com --> Cookies.
-  CookieTreeNode* parent = model->GetRoot()->GetChild(0)->GetChild(0);
-
-  ASSERT_EQ(3U, list.size());
-
-  // Add the cookie nodes.
-  CookieTreeCookieNode* cnode = new CookieTreeCookieNode(&list[1]);
-  parent->Add(1, cnode);  // |parent| takes ownership.
-  cnode = new CookieTreeCookieNode(&list[2]);
-  parent->Add(2, cnode);
-
-  // Manually notify the observer.
-  [controller_ modelObserver]->TreeNodesAdded(model, parent, 1, 2);
-
-  // Check that we have created 2 more Cocoa nodes.
-  EXPECT_EQ(3U, [cocoa_children count]);
-}
-
-TEST_F(CookiesWindowControllerTest, TreeNodesRemoved) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-  cm->SetCookie(url, "C=D");
-  cm->SetCookie(url, "E=F");
-
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-
-  // Root --> foo.com --> Cookies.
-  NSMutableArray* cocoa_children =
-      [[[[[[controller_ cocoaTreeModel] children] objectAtIndex:0]
-          children] objectAtIndex:0] mutableChildren];
-  EXPECT_EQ(3U, [cocoa_children count]);
-
-  CookiesTreeModel* model = [controller_ treeModel];
-  // Root --> foo.com --> Cookies.
-  CookieTreeNode* parent = model->GetRoot()->GetChild(0)->GetChild(0);
-
-  // Pretend to remove the nodes.
-  [controller_ modelObserver]->TreeNodesRemoved(model, parent, 1, 2);
-
-  EXPECT_EQ(1U, [cocoa_children count]);
-
-  NSString* title = [[[cocoa_children objectAtIndex:0] details] name];
-  EXPECT_NSEQ(@"A", title);
-}
-
-TEST_F(CookiesWindowControllerTest, TreeNodeChanged) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-
-  CookiesTreeModel* model = [controller_ treeModel];
-  // Root --> foo.com --> Cookies.
-  CookieTreeNode* node = model->GetRoot()->GetChild(0)->GetChild(0);
-
-  // Root --> foo.com --> Cookies.
-  CocoaCookieTreeNode* cocoa_node =
-      [[[[[controller_ cocoaTreeModel] children] objectAtIndex:0]
-          children] objectAtIndex:0];
-
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIES),
-              [cocoa_node title]);
-
-  // Fake update the cookie folder's title. This would never happen in reality,
-  // but it tests the code path that ultimately calls CocoaNodeFromTreeNode,
-  // which is tested elsewhere.
-  node->SetTitle(ASCIIToUTF16("Silly Change"));
-  [controller_ modelObserver]->TreeNodeChanged(model, node);
-
-  EXPECT_NSEQ(@"Silly Change", [cocoa_node title]);
-}
-
-TEST_F(CookiesWindowControllerTest, DeleteCookie) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-  cm->SetCookie(url, "C=D");
-  cm->SetCookie(GURL("http://google.com"), "E=F");
-
-  // This will clean itself up when we call |-closeSheet:|. If we reset the
-  // scoper, we'd get a double-free.
-  CookiesWindowController* controller =
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_];
-  [controller attachSheetTo:test_window()];
-  NSTreeController* treeController = [controller treeController];
-
-  // Select cookie A.
-  NSUInteger pathA[3] = {0, 0, 0};
-  NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:pathA length:3];
-  [treeController setSelectionIndexPath:indexPath];
-
-  // Press the "Delete" button.
-  [controller deleteCookie:nil];
-
-  // Root --> foo.com --> Cookies.
-  NSArray* cookies = [[[[[[controller cocoaTreeModel] children]
-      objectAtIndex:0] children] objectAtIndex:0] children];
-  EXPECT_EQ(1U, [cookies count]);
-  EXPECT_NSEQ(@"C", [[cookies lastObject] title]);
-  EXPECT_NSEQ(indexPath, [treeController selectionIndexPath]);
-
-  // Select cookie E.
-  NSUInteger pathE[3] = {1, 0, 0};
-  indexPath = [NSIndexPath indexPathWithIndexes:pathE length:3];
-  [treeController setSelectionIndexPath:indexPath];
-
-  // Perform delete.
-  [controller deleteCookie:nil];
-
-  // Make sure that both the domain level node and the Cookies folder node got
-  // deleted because there was only one leaf node.
-  EXPECT_EQ(1U, [[[controller cocoaTreeModel] children] count]);
-
-  // Select cookie C.
-  NSUInteger pathC[3] = {0, 0, 0};
-  indexPath = [NSIndexPath indexPathWithIndexes:pathC length:3];
-  [treeController setSelectionIndexPath:indexPath];
-
-  // Perform delete.
-  [controller deleteCookie:nil];
-
-  // Make sure the world didn't explode and that there's nothing in the tree.
-  EXPECT_EQ(0U, [[[controller cocoaTreeModel] children] count]);
-
-  [controller closeSheet:nil];
-}
-
-TEST_F(CookiesWindowControllerTest, DidExpandItem) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-  cm->SetCookie(url, "C=D");
-
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-
-  // Root --> foo.com.
-  CocoaCookieTreeNode* foo =
-      [[[controller_ cocoaTreeModel] children] objectAtIndex:0];
-
-  // Create the objects we are going to be testing with.
-  id outlineView = [OCMockObject mockForClass:[NSOutlineView class]];
-  id treeNode = [OCMockObject mockForClass:[NSTreeNode class]];
-  NSTreeNode* childTreeNode =
-      [NSTreeNode treeNodeWithRepresentedObject:[[foo children] lastObject]];
-  NSArray* fakeChildren = [NSArray arrayWithObject:childTreeNode];
-
-  // Set up the mock object.
-  [[[treeNode stub] andReturn:foo] representedObject];
-  [[[treeNode stub] andReturn:fakeChildren] childNodes];
-
-  // Create a fake "ItemDidExpand" notification.
-  NSDictionary* userInfo = [NSDictionary dictionaryWithObject:treeNode
-                                                       forKey:@"NSObject"];
-  NSNotification* notif =
-      [NSNotification notificationWithName:@"ItemDidExpandNotification"
-                                    object:outlineView
-                                  userInfo:userInfo];
-
-  // Make sure we work correctly.
-  [[outlineView expect] expandItem:childTreeNode];
-  [controller_ outlineViewItemDidExpand:notif];
-  [outlineView verify];
-}
-
-TEST_F(CookiesWindowControllerTest, ClearBrowsingData) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-  cm->SetCookie(url, "C=D");
-  cm->SetCookie(url, "E=F");
-
-  id mock = [OCMockObject partialMockForObject:controller_.get()];
-  [[mock expect] loadTreeModelFromProfile];
-
-  NSNumber* mask =
-      [NSNumber numberWithInt:BrowsingDataRemover::REMOVE_COOKIES];
-  NSDictionary* userInfo =
-      [NSDictionary dictionaryWithObject:mask
-                                forKey:kClearBrowsingDataControllerRemoveMask];
-  NSNotification* notif =
-    [NSNotification notificationWithName:kClearBrowsingDataControllerDidDelete
-                                  object:nil
-                                userInfo:userInfo];
-  [controller_ clearBrowsingDataNotification:notif];
-
-  [mock verify];
-}
-
-// This test has been flaky under Valgrind and turns the bot red since r38504.
-// Under Mac Tests 10.5, it occasionally reports:
-//   malloc: *** error for object 0x31e0468: Non-aligned pointer being freed
-//   *** set a breakpoint in malloc_error_break to debug
-// Attempts to reproduce locally were not successful. This code is likely
-// changing in the future, so it's marked flaky for now. http://crbug.com/35327
-TEST_F(CookiesWindowControllerTest, FLAKY_RemoveButtonEnabled) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(url, "A=B");
-  cm->SetCookie(url, "C=D");
-
-  // This will clean itself up when we call |-closeSheet:|. If we reset the
-  // scoper, we'd get a double-free.
-  database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
-  local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
-  local_storage_helper_->AddLocalStorageSamples();
-  CookiesWindowController* controller =
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_];
-  local_storage_helper_->Notify();
-  [controller attachSheetTo:test_window()];
-
-  // Nothing should be selected right now.
-  EXPECT_FALSE([controller removeButtonEnabled]);
-
-  {
-    // Pretend to select cookie A.
-    NSUInteger path[3] = {0, 0, 0};
-    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
-    [[controller treeController] setSelectionIndexPath:indexPath];
-    [controller outlineViewSelectionDidChange:nil];
-    EXPECT_TRUE([controller removeButtonEnabled]);
-  }
-
-  {
-    // Pretend to select cookie C.
-    NSUInteger path[3] = {0, 0, 1};
-    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
-    [[controller treeController] setSelectionIndexPath:indexPath];
-    [controller outlineViewSelectionDidChange:nil];
-    EXPECT_TRUE([controller removeButtonEnabled]);
-  }
-
-  {
-    // Select a local storage node.
-    NSUInteger path[3] = {2, 0, 0};
-    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
-    [[controller treeController] setSelectionIndexPath:indexPath];
-    [controller outlineViewSelectionDidChange:nil];
-    EXPECT_TRUE([controller removeButtonEnabled]);
-  }
-
-  {
-    // Pretend to select something that isn't there!
-    NSUInteger path[3] = {0, 0, 2};
-    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
-    [[controller treeController] setSelectionIndexPath:indexPath];
-    [controller outlineViewSelectionDidChange:nil];
-    EXPECT_FALSE([controller removeButtonEnabled]);
-  }
-
-  {
-    // Try selecting something that doesn't exist again.
-    NSUInteger path[3] = {7, 1, 4};
-    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
-    [[controller treeController] setSelectionIndexPath:indexPath];
-    [controller outlineViewSelectionDidChange:nil];
-    EXPECT_FALSE([controller removeButtonEnabled]);
-  }
-
-  [controller closeSheet:nil];
-}
-
-TEST_F(CookiesWindowControllerTest, UpdateFilter) {
-  const GURL url = GURL("http://foo.com");
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(GURL("http://a.com"), "A=B");
-  cm->SetCookie(GURL("http://aa.com"), "C=D");
-  cm->SetCookie(GURL("http://b.com"), "E=F");
-  cm->SetCookie(GURL("http://d.com"), "G=H");
-  cm->SetCookie(GURL("http://dd.com"), "I=J");
-
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-
-  // Make sure we registered all five cookies.
-  EXPECT_EQ(5U, [[[controller_ cocoaTreeModel] children] count]);
-
-  NSSearchField* field =
-      [[NSSearchField alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
-
-  // Make sure we still have five cookies.
-  [field setStringValue:@""];
-  [controller_ updateFilter:field];
-  EXPECT_EQ(5U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Search for "a".
-  [field setStringValue:@"a"];
-  [controller_ updateFilter:field];
-  EXPECT_EQ(2U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Search for "b".
-  [field setStringValue:@"b"];
-  [controller_ updateFilter:field];
-  EXPECT_EQ(1U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Search for "d".
-  [field setStringValue:@"d"];
-  [controller_ updateFilter:field];
-  EXPECT_EQ(2U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Search for "e".
-  [field setStringValue:@"e"];
-  [controller_ updateFilter:field];
-  EXPECT_EQ(0U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Search for "aa".
-  [field setStringValue:@"aa"];
-  [controller_ updateFilter:field];
-  EXPECT_EQ(1U, [[[controller_ cocoaTreeModel] children] count]);
-}
-
-TEST_F(CookiesWindowControllerTest, CreateDatabaseStorageNodes) {
-  TestingProfile* profile = browser_helper_.profile();
-  database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
-  local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
-  database_helper_->AddDatabaseSamples();
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-  database_helper_->Notify();
-
-  ASSERT_EQ(2U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Root --> gdbhost1.
-  CocoaCookieTreeNode* node =
-      [[[controller_ cocoaTreeModel] children] objectAtIndex:0];
-  EXPECT_NSEQ(@"gdbhost1", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // host1 --> Web Databases.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_WEB_DATABASES), [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // Database Storage --> db1.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(@"db1", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeTreeDatabase, [node nodeType]);
-  CocoaCookieDetails* details = [node details];
-  EXPECT_NSEQ(@"description 1", [details databaseDescription]);
-  EXPECT_TRUE([details lastModified]);
-  EXPECT_TRUE([details fileSize]);
-
-  // Root --> gdbhost2.
-  node =
-      [[[controller_ cocoaTreeModel] children] objectAtIndex:1];
-  EXPECT_NSEQ(@"gdbhost2", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // host1 --> Web Databases.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_WEB_DATABASES), [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // Database Storage --> db2.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(@"db2", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeTreeDatabase, [node nodeType]);
-  details = [node details];
-  EXPECT_NSEQ(@"description 2", [details databaseDescription]);
-  EXPECT_TRUE([details lastModified]);
-  EXPECT_TRUE([details fileSize]);
-}
-
-TEST_F(CookiesWindowControllerTest, CreateLocalStorageNodes) {
-  TestingProfile* profile = browser_helper_.profile();
-  net::CookieMonster* cm = profile->GetCookieMonster();
-  cm->SetCookie(GURL("http://google.com"), "A=B");
-  cm->SetCookie(GURL("http://dev.chromium.org"), "C=D");
-  database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
-  local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
-  local_storage_helper_->AddLocalStorageSamples();
-  controller_.reset(
-      [[CookiesWindowController alloc] initWithProfile:profile
-                                        databaseHelper:database_helper_
-                                         storageHelper:local_storage_helper_
-                                        appcacheHelper:appcache_helper_]);
-  local_storage_helper_->Notify();
-
-  ASSERT_EQ(4U, [[[controller_ cocoaTreeModel] children] count]);
-
-  // Root --> host1.
-  CocoaCookieTreeNode* node =
-      [[[controller_ cocoaTreeModel] children] objectAtIndex:2];
-  EXPECT_NSEQ(@"host1", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // host1 --> Local Storage.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_LOCAL_STORAGE), [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // Local Storage --> http://host1:1/.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(@"http://host1:1/", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeTreeLocalStorage, [node nodeType]);
-  EXPECT_NSEQ(@"http://host1:1/", [[node details] domain]);
-  EXPECT_TRUE([[node details] lastModified]);
-  EXPECT_TRUE([[node details] fileSize]);
-
-  // Root --> host2.
-  node =
-      [[[controller_ cocoaTreeModel] children] objectAtIndex:3];
-  EXPECT_NSEQ(@"host2", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // host2 --> Local Storage.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_LOCAL_STORAGE), [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
-  EXPECT_EQ(1U, [[node children] count]);
-
-  // Local Storage --> http://host2:2/.
-  node = [[node children] lastObject];
-  EXPECT_NSEQ(@"http://host2:2/", [node title]);
-  EXPECT_EQ(kCocoaCookieDetailsTypeTreeLocalStorage, [node nodeType]);
-  EXPECT_NSEQ(@"http://host2:2/", [[node details] domain]);
-  EXPECT_TRUE([[node details] lastModified]);
-  EXPECT_TRUE([[node details] fileSize]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/custom_home_pages_model.h b/chrome/browser/ui/cocoa/custom_home_pages_model.h
deleted file mode 100644
index 2bb94d8..0000000
--- a/chrome/browser/ui/cocoa/custom_home_pages_model.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_CUSTOM_HOME_PAGES_MODEL_H_
-#define CHROME_BROWSER_UI_COCOA_CUSTOM_HOME_PAGES_MODEL_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include <vector>
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/history/history.h"
-#include "googleurl/src/gurl.h"
-
-class Profile;
-
-// The model for the "custom home pages" table in preferences. Contains a list
-// of CustomHomePageEntry objects. This is intended to be used with Cocoa
-// bindings.
-//
-// The supported binding is |customHomePages|, a to-many relationship which
-// can be observed with an array controller.
-
-@interface CustomHomePagesModel : NSObject {
- @private
-  scoped_nsobject<NSMutableArray> entries_;
-  Profile* profile_;  // weak, used for loading favicons
-}
-
-// Initialize with |profile|, which must not be NULL. The profile is used for
-// loading favicons for urls.
-- (id)initWithProfile:(Profile*)profile;
-
-// Get/set the urls the model currently contains as a group. Only one change
-// notification will be sent.
-- (std::vector<GURL>)URLs;
-- (void)setURLs:(const std::vector<GURL>&)urls;
-
-// Reloads the URLs from their stored state. This will notify using KVO
-// |customHomePages|.
-- (void)reloadURLs;
-
-// Validates the set of URLs stored in the model. The user may have input bad
-// data. This function removes invalid entries from the model, which will result
-// in anyone observing being updated.
-- (void)validateURLs;
-
-// For binding |customHomePages| to a mutable array controller.
-- (NSUInteger)countOfCustomHomePages;
-- (id)objectInCustomHomePagesAtIndex:(NSUInteger)index;
-- (void)insertObject:(id)object inCustomHomePagesAtIndex:(NSUInteger)index;
-- (void)removeObjectFromCustomHomePagesAtIndex:(NSUInteger)index;
-@end
-
-////////////////////////////////////////////////////////////////////////////////
-
-// An entry representing a single item in the custom home page model. Stores
-// a url and a favicon.
-@interface CustomHomePageEntry : NSObject {
- @private
-  scoped_nsobject<NSString> url_;
-  scoped_nsobject<NSImage> icon_;
-
-  // If non-zero, indicates we're loading the favicon for the page.
-  HistoryService::Handle icon_handle_;
-}
-
-@property(nonatomic, copy) NSString* URL;
-@property(nonatomic, retain) NSImage* image;
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////
-
-@interface CustomHomePagesModel (InternalOrTestingAPI)
-
-// Clears the URL string at the specified index. This constitutes bad data. The
-// validator should scrub the entry from the list the next time it is run.
-- (void)setURLStringEmptyAt:(NSUInteger)index;
-
-@end
-
-// A notification that fires when the URL of one of the entries changes.
-// Prevents interested parties from having to observe all model objects in order
-// to persist changes to a single entry. Changes to the number of items in the
-// model can be observed by watching |customHomePages| via KVO so an additional
-// notification is not sent.
-extern NSString* const kHomepageEntryChangedNotification;
-
-#endif  // CHROME_BROWSER_UI_COCOA_CUSTOM_HOME_PAGES_MODEL_H_
diff --git a/chrome/browser/ui/cocoa/custom_home_pages_model.mm b/chrome/browser/ui/cocoa/custom_home_pages_model.mm
deleted file mode 100644
index 2e0be88..0000000
--- a/chrome/browser/ui/cocoa/custom_home_pages_model.mm
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/custom_home_pages_model.h"
-
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-
-NSString* const kHomepageEntryChangedNotification =
-    @"kHomepageEntryChangedNotification";
-
-@interface CustomHomePagesModel (Private)
-- (void)setURLsInternal:(const std::vector<GURL>&)urls;
-@end
-
-@implementation CustomHomePagesModel
-
-- (id)initWithProfile:(Profile*)profile {
-  if ((self = [super init])) {
-    profile_ = profile;
-    entries_.reset([[NSMutableArray alloc] init]);
-  }
-  return self;
-}
-
-- (NSUInteger)countOfCustomHomePages {
-  return [entries_ count];
-}
-
-- (id)objectInCustomHomePagesAtIndex:(NSUInteger)index {
-  return [entries_ objectAtIndex:index];
-}
-
-- (void)insertObject:(id)object inCustomHomePagesAtIndex:(NSUInteger)index {
-  [entries_ insertObject:object atIndex:index];
-}
-
-- (void)removeObjectFromCustomHomePagesAtIndex:(NSUInteger)index {
-  [entries_ removeObjectAtIndex:index];
-  // Force a save.
-  [self validateURLs];
-}
-
-// Get/set the urls the model currently contains as a group. These will weed
-// out any URLs that are empty and not add them to the model. As a result,
-// the next time they're persisted to the prefs backend, they'll disappear.
-- (std::vector<GURL>)URLs {
-  std::vector<GURL> urls;
-  for (CustomHomePageEntry* entry in entries_.get()) {
-    const char* urlString = [[entry URL] UTF8String];
-    if (urlString && std::strlen(urlString)) {
-      urls.push_back(GURL(std::string(urlString)));
-    }
-  }
-  return urls;
-}
-
-- (void)setURLs:(const std::vector<GURL>&)urls {
-  [self willChangeValueForKey:@"customHomePages"];
-  [self setURLsInternal:urls];
-  SessionStartupPref pref(SessionStartupPref::GetStartupPref(profile_));
-  pref.urls = urls;
-  SessionStartupPref::SetStartupPref(profile_, pref);
-  [self didChangeValueForKey:@"customHomePages"];
-}
-
-// Converts the C++ URLs to Cocoa objects without notifying KVO.
-- (void)setURLsInternal:(const std::vector<GURL>&)urls {
-  [entries_ removeAllObjects];
-  for (size_t i = 0; i < urls.size(); ++i) {
-    scoped_nsobject<CustomHomePageEntry> entry(
-        [[CustomHomePageEntry alloc] init]);
-    const char* urlString = urls[i].spec().c_str();
-    if (urlString && std::strlen(urlString)) {
-      [entry setURL:[NSString stringWithCString:urlString
-                                       encoding:NSUTF8StringEncoding]];
-      [entries_ addObject:entry];
-    }
-  }
-}
-
-- (void)reloadURLs {
-  [self willChangeValueForKey:@"customHomePages"];
-  SessionStartupPref pref(SessionStartupPref::GetStartupPref(profile_));
-  [self setURLsInternal:pref.urls];
-  [self didChangeValueForKey:@"customHomePages"];
-}
-
-- (void)validateURLs {
-  [self setURLs:[self URLs]];
-}
-
-- (void)setURLStringEmptyAt:(NSUInteger)index {
-  // This replaces the data at |index| with an empty (invalid) URL string.
-  CustomHomePageEntry* entry = [entries_ objectAtIndex:index];
-  [entry setURL:[NSString stringWithString:@""]];
-}
-
-@end
-
-//---------------------------------------------------------------------------
-
-@implementation CustomHomePageEntry
-
-- (void)setURL:(NSString*)url {
-  // |url| can be nil if the user cleared the text from the edit field.
-  if (!url)
-    url = [NSString stringWithString:@""];
-
-  // Make sure the url is valid before setting it by fixing it up.
-  std::string fixedUrl(URLFixerUpper::FixupURL(
-      base::SysNSStringToUTF8(url), std::string()).possibly_invalid_spec());
-  url_.reset([base::SysUTF8ToNSString(fixedUrl) retain]);
-
-  // Broadcast that an individual item has changed.
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:kHomepageEntryChangedNotification object:nil];
-
-  // TODO(pinkerton): fetch favicon, convert to NSImage http://crbug.com/34642
-}
-
-- (NSString*)URL {
-  return url_.get();
-}
-
-- (void)setImage:(NSImage*)image {
-  icon_.reset(image);
-}
-
-- (NSImage*)image {
-  return icon_.get();
-}
-
-- (NSString*)description {
-  return url_.get();
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/custom_home_pages_model_unittest.mm b/chrome/browser/ui/cocoa/custom_home_pages_model_unittest.mm
deleted file mode 100644
index c744775..0000000
--- a/chrome/browser/ui/cocoa/custom_home_pages_model_unittest.mm
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/custom_home_pages_model.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-// A helper for KVO and NSNotifications. Makes a note that it's been called
-// back.
-@interface CustomHomePageHelper : NSObject {
- @public
-  BOOL sawNotification_;
-}
-@end
-
-@implementation CustomHomePageHelper
-- (void)observeValueForKeyPath:(NSString*)keyPath
-                      ofObject:(id)object
-                        change:(NSDictionary*)change
-                       context:(void*)context {
-  sawNotification_ = YES;
-}
-
-- (void)entryChanged:(NSNotification*)notify {
-  sawNotification_ = YES;
-}
-@end
-
-@interface NSObject ()
-- (void)setURL:(NSString*)url;
-@end
-
-namespace {
-
-// Helper that creates an autoreleased entry.
-CustomHomePageEntry* MakeEntry(NSString* url) {
-  CustomHomePageEntry* entry = [[[CustomHomePageEntry alloc] init] autorelease];
-  [entry setURL:url];
-  return entry;
-}
-
-// Helper that casts from |id| to the Entry type and returns the URL string.
-NSString* EntryURL(id entry) {
-  return [static_cast<CustomHomePageEntry*>(entry) URL];
-}
-
-class CustomHomePagesModelTest : public PlatformTest {
- public:
-  CustomHomePagesModelTest() {
-    model_.reset([[CustomHomePagesModel alloc]
-                    initWithProfile:helper_.profile()]);
-   }
-  ~CustomHomePagesModelTest() { }
-
-  BrowserTestHelper helper_;
-  scoped_nsobject<CustomHomePagesModel> model_;
-};
-
-TEST_F(CustomHomePagesModelTest, Init) {
-  scoped_nsobject<CustomHomePagesModel> model(
-      [[CustomHomePagesModel alloc] initWithProfile:helper_.profile()]);
-}
-
-TEST_F(CustomHomePagesModelTest, GetSetURLs) {
-  // Basic test.
-  std::vector<GURL> urls;
-  urls.push_back(GURL("http://www.google.com"));
-  [model_ setURLs:urls];
-  std::vector<GURL> received_urls = [model_.get() URLs];
-  EXPECT_EQ(received_urls.size(), 1U);
-  EXPECT_TRUE(urls[0] == received_urls[0]);
-
-  // Set an empty list, make sure we get back an empty list.
-  std::vector<GURL> empty;
-  [model_ setURLs:empty];
-  received_urls = [model_.get() URLs];
-  EXPECT_EQ(received_urls.size(), 0U);
-
-  // Give it a list with not well-formed URLs and make sure we get back.
-  // only the good ones.
-  std::vector<GURL> poorly_formed;
-  poorly_formed.push_back(GURL("http://www.google.com"));  // good
-  poorly_formed.push_back(GURL("www.google.com"));  // bad
-  poorly_formed.push_back(GURL("www.yahoo."));  // bad
-  poorly_formed.push_back(GURL("http://www.yahoo.com"));  // good
-  [model_ setURLs:poorly_formed];
-  received_urls = [model_.get() URLs];
-  EXPECT_EQ(received_urls.size(), 2U);
-}
-
-// Test that we get a KVO notification when called setURLs.
-TEST_F(CustomHomePagesModelTest, KVOObserveWhenListChanges) {
-  scoped_nsobject<CustomHomePageHelper> kvo_helper(
-      [[CustomHomePageHelper alloc] init]);
-  [model_ addObserver:kvo_helper
-           forKeyPath:@"customHomePages"
-              options:0L
-              context:NULL];
-  EXPECT_FALSE(kvo_helper.get()->sawNotification_);
-
-  std::vector<GURL> urls;
-  urls.push_back(GURL("http://www.google.com"));
-  [model_ setURLs:urls];  // Should send kvo change notification.
-  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
-
-  [model_ removeObserver:kvo_helper forKeyPath:@"customHomePages"];
-}
-
-// Test the KVO "to-many" bindings for |customHomePages| and the KVO
-// notifiation when items are added to and removed from the list.
-TEST_F(CustomHomePagesModelTest, KVO) {
-  EXPECT_EQ([model_ countOfCustomHomePages], 0U);
-
-  scoped_nsobject<CustomHomePageHelper> kvo_helper(
-      [[CustomHomePageHelper alloc] init]);
-  [model_ addObserver:kvo_helper
-           forKeyPath:@"customHomePages"
-              options:0L
-              context:NULL];
-  EXPECT_FALSE(kvo_helper.get()->sawNotification_);
-
-  // Cheat and insert NSString objects into the array. As long as we don't
-  // call -URLs, we'll be ok.
-  [model_ insertObject:MakeEntry(@"www.google.com") inCustomHomePagesAtIndex:0];
-  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
-  [model_ insertObject:MakeEntry(@"www.yahoo.com") inCustomHomePagesAtIndex:1];
-  [model_ insertObject:MakeEntry(@"dev.chromium.org")
-      inCustomHomePagesAtIndex:2];
-  EXPECT_EQ([model_ countOfCustomHomePages], 3U);
-
-  EXPECT_NSEQ(@"http://www.yahoo.com/",
-              EntryURL([model_ objectInCustomHomePagesAtIndex:1]));
-
-  kvo_helper.get()->sawNotification_ = NO;
-  [model_ removeObjectFromCustomHomePagesAtIndex:1];
-  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
-  EXPECT_EQ([model_ countOfCustomHomePages], 2U);
-  EXPECT_NSEQ(@"http://dev.chromium.org/",
-              EntryURL([model_ objectInCustomHomePagesAtIndex:1]));
-  EXPECT_NSEQ(@"http://www.google.com/",
-              EntryURL([model_ objectInCustomHomePagesAtIndex:0]));
-
-  [model_ removeObserver:kvo_helper forKeyPath:@"customHomePages"];
-}
-
-// Test that when individual items are changed that they broadcast a message.
-TEST_F(CustomHomePagesModelTest, ModelChangedNotification) {
-  scoped_nsobject<CustomHomePageHelper> kvo_helper(
-      [[CustomHomePageHelper alloc] init]);
-  [[NSNotificationCenter defaultCenter]
-      addObserver:kvo_helper
-         selector:@selector(entryChanged:)
-             name:kHomepageEntryChangedNotification
-            object:nil];
-
-  std::vector<GURL> urls;
-  urls.push_back(GURL("http://www.google.com"));
-  [model_ setURLs:urls];
-  NSObject* entry = [model_ objectInCustomHomePagesAtIndex:0];
-  [entry setURL:@"http://www.foo.bar"];
-  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
-  [[NSNotificationCenter defaultCenter] removeObserver:kvo_helper];
-}
-
-TEST_F(CustomHomePagesModelTest, ReloadURLs) {
-  scoped_nsobject<CustomHomePageHelper> kvo_helper(
-      [[CustomHomePageHelper alloc] init]);
-  [model_ addObserver:kvo_helper
-           forKeyPath:@"customHomePages"
-              options:0L
-              context:NULL];
-  EXPECT_FALSE(kvo_helper.get()->sawNotification_);
-  EXPECT_EQ([model_ countOfCustomHomePages], 0U);
-
-  std::vector<GURL> urls;
-  urls.push_back(GURL("http://www.google.com"));
-  SessionStartupPref pref;
-  pref.urls = urls;
-  SessionStartupPref::SetStartupPref(helper_.profile(), pref);
-
-  [model_ reloadURLs];
-
-  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
-  EXPECT_EQ([model_ countOfCustomHomePages], 1U);
-  EXPECT_NSEQ(@"http://www.google.com/",
-              EntryURL([model_ objectInCustomHomePagesAtIndex:0]));
-
-  [model_ removeObserver:kvo_helper.get() forKeyPath:@"customHomePages"];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.h b/chrome/browser/ui/cocoa/dev_tools_controller.h
index c89a9f8..e8fa567 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.h
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.h
@@ -9,16 +9,17 @@
 #import <Foundation/Foundation.h>
 
 #include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
 
 @class NSSplitView;
 @class NSView;
 
+class Profile;
 class TabContents;
 
 // A class that handles updates of the devTools view within a browser window.
 // It swaps in the relevant devTools contents for a given TabContents or removes
-// the vew, if there's no devTools contents to show.
+// the view, if there's no devTools contents to show.
 @interface DevToolsController : NSObject {
  @private
   // A view hosting docked devTools contents.
@@ -40,7 +41,8 @@
 // Depending on |contents|'s state, decides whether the docked web inspector
 // should be shown or hidden and adjusts its height (|delegate_| handles
 // the actual resize).
-- (void)updateDevToolsForTabContents:(TabContents*)contents;
+- (void)updateDevToolsForTabContents:(TabContents*)contents
+                         withProfile:(Profile*)profile;
 
 // Call when the devTools view is properly sized and the render widget host view
 // should be put into the view hierarchy.
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.mm b/chrome/browser/ui/cocoa/dev_tools_controller.mm
index 596bdae..617d773 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.mm
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.mm
@@ -11,8 +11,8 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/debugger/devtools_window.h"
 #include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "chrome/common/pref_names.h"
 
@@ -29,7 +29,8 @@
 
 
 @interface DevToolsController (Private)
-- (void)showDevToolsContents:(TabContents*)devToolsContents;
+- (void)showDevToolsContents:(TabContents*)devToolsContents
+                 withProfile:(Profile*)profile;
 - (void)resizeDevToolsToNewHeight:(CGFloat)height;
 @end
 
@@ -64,19 +65,21 @@
   return splitView_.get();
 }
 
-- (void)updateDevToolsForTabContents:(TabContents*)contents {
+- (void)updateDevToolsForTabContents:(TabContents*)contents
+                         withProfile:(Profile*)profile {
   // Get current devtools content.
   TabContents* devToolsContents = contents ?
       DevToolsWindow::GetDevToolsContents(contents) : NULL;
 
-  [self showDevToolsContents:devToolsContents];
+  [self showDevToolsContents:devToolsContents withProfile:profile];
 }
 
 - (void)ensureContentsVisible {
   [contentsController_ ensureContentsVisible];
 }
 
-- (void)showDevToolsContents:(TabContents*)devToolsContents {
+- (void)showDevToolsContents:(TabContents*)devToolsContents
+                 withProfile:(Profile*)profile {
   [contentsController_ ensureContentsSizeDoesNotChange];
 
   NSArray* subviews = [splitView_ subviews];
@@ -92,8 +95,8 @@
     CGFloat splitOffset = 0;
     if ([subviews count] == 1) {
       // Load the default split offset.
-      splitOffset = g_browser_process->local_state()->GetInteger(
-          prefs::kDevToolsSplitLocation);
+      splitOffset = profile->GetPrefs()->
+          GetInteger(prefs::kDevToolsSplitLocation);
       if (splitOffset < 0) {
         // Initial load, set to default value.
         splitOffset = kDefaultContentsSplitOffset;
@@ -118,7 +121,8 @@
       NSView* oldDevToolsContentsView = [subviews objectAtIndex:1];
       // Store split offset when hiding devtools window only.
       int splitOffset = NSHeight([oldDevToolsContentsView frame]);
-      g_browser_process->local_state()->SetInteger(
+
+      profile->GetPrefs()->SetInteger(
           prefs::kDevToolsSplitLocation, splitOffset);
       [oldDevToolsContentsView removeFromSuperview];
       [splitView_ adjustSubviews];
diff --git a/chrome/browser/ui/cocoa/download/OWNERS b/chrome/browser/ui/cocoa/download/OWNERS
new file mode 100644
index 0000000..7487122
--- /dev/null
+++ b/chrome/browser/ui/cocoa/download/OWNERS
@@ -0,0 +1 @@
+thakis@chromium.org
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell.h b/chrome/browser/ui/cocoa/download/download_item_cell.h
index a5ffaeb..32415e0 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell.h
+++ b/chrome/browser/ui/cocoa/download/download_item_cell.h
@@ -45,13 +45,13 @@
   CGFloat statusAlpha_;
   scoped_nsobject<NSAnimation> hideStatusAnimation_;
 
-  scoped_ptr<ThemeProvider> themeProvider_;
+  scoped_ptr<ui::ThemeProvider> themeProvider_;
 }
 
-- (void)setStateFromDownload:(BaseDownloadItemModel*)downloadModel;
+@property(nonatomic, copy) NSString* secondaryTitle;
+@property(nonatomic, retain) NSFont* secondaryFont;
 
-@property (nonatomic, copy) NSString* secondaryTitle;
-@property (nonatomic, retain) NSFont* secondaryFont;
+- (void)setStateFromDownload:(BaseDownloadItemModel*)downloadModel;
 
 // Returns if the mouse is over the button part of the cell.
 - (BOOL)isMouseOverButtonPart;
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell.mm b/chrome/browser/ui/cocoa/download/download_item_cell.mm
index db5d5fa..37e300a 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_cell.mm
@@ -4,8 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/download/download_item_cell.h"
 
-#include "app/l10n_util.h"
-#include "app/text_elider.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_item_model.h"
@@ -15,10 +13,12 @@
 #import "chrome/browser/ui/cocoa/download/download_item_cell.h"
 #import "chrome/browser/ui/cocoa/image_utils.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
-#include "gfx/canvas_skia_paint.h"
 #include "grit/theme_resources.h"
 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas_skia_paint.h"
 
 namespace {
 
@@ -85,9 +85,9 @@
                 animationCurve:(NSAnimationCurve)animationCurve;
 @end
 
-class BackgroundTheme : public ThemeProvider {
+class BackgroundTheme : public ui::ThemeProvider {
 public:
-  BackgroundTheme(ThemeProvider* provider);
+  BackgroundTheme(ui::ThemeProvider* provider);
 
   virtual void Init(Profile* profile) { }
   virtual SkBitmap* GetBitmapNamed(int id) const { return nil; }
@@ -103,13 +103,13 @@
   virtual NSGradient* GetNSGradient(int id) const;
 
 private:
-  ThemeProvider* provider_;
+  ui::ThemeProvider* provider_;
   scoped_nsobject<NSGradient> buttonGradient_;
   scoped_nsobject<NSGradient> buttonPressedGradient_;
   scoped_nsobject<NSColor> borderColor_;
 };
 
-BackgroundTheme::BackgroundTheme(ThemeProvider* provider) :
+BackgroundTheme::BackgroundTheme(ui::ThemeProvider* provider) :
     provider_(provider) {
   NSColor* bgColor = [NSColor colorWithCalibratedRed:241/255.0
                                                green:245/255.0
@@ -168,7 +168,7 @@
        progressed:(NSAnimationProgress)progress;
 - (NSString*)elideTitle:(int)availableWidth;
 - (NSString*)elideStatus:(int)availableWidth;
-- (ThemeProvider*)backgroundThemeWrappingProvider:(ThemeProvider*)provider;
+- (ui::ThemeProvider*)backgroundThemeWrappingProvider:(ui::ThemeProvider*)provider;
 - (BOOL)pressedWithDefaultThemeOnPart:(DownloadItemMousePosition)part;
 - (NSColor*)titleColorForPart:(DownloadItemMousePosition)part;
 - (void)drawSecondaryTitleInRect:(NSRect)innerFrame;
@@ -394,26 +394,26 @@
 
 - (NSString*)elideTitle:(int)availableWidth {
   NSFont* font = [self font];
-  gfx::Font font_chr(base::SysNSStringToWide([font fontName]),
+  gfx::Font font_chr(base::SysNSStringToUTF16([font fontName]),
                      [font pointSize]);
 
   return base::SysUTF16ToNSString(
-      ElideFilename(downloadPath_, font_chr, availableWidth));
+      ui::ElideFilename(downloadPath_, font_chr, availableWidth));
 }
 
 - (NSString*)elideStatus:(int)availableWidth {
   NSFont* font = [self secondaryFont];
-  gfx::Font font_chr(base::SysNSStringToWide([font fontName]),
+  gfx::Font font_chr(base::SysNSStringToUTF16([font fontName]),
                      [font pointSize]);
 
-  return base::SysUTF16ToNSString(ElideText(
+  return base::SysUTF16ToNSString(ui::ElideText(
       base::SysNSStringToUTF16([self secondaryTitle]),
       font_chr,
       availableWidth,
       false));
 }
 
-- (ThemeProvider*)backgroundThemeWrappingProvider:(ThemeProvider*)provider {
+- (ui::ThemeProvider*)backgroundThemeWrappingProvider:(ui::ThemeProvider*)provider {
   if (!themeProvider_.get()) {
     themeProvider_.reset(new BackgroundTheme(provider));
   }
@@ -423,7 +423,8 @@
 
 // Returns if |part| was pressed while the default theme was active.
 - (BOOL)pressedWithDefaultThemeOnPart:(DownloadItemMousePosition)part {
-  ThemeProvider* themeProvider = [[[self controlView] window] themeProvider];
+  ui::ThemeProvider* themeProvider =
+      [[[self controlView] window] themeProvider];
   bool isDefaultTheme =
       !themeProvider->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND);
   return isDefaultTheme && [self isHighlighted] && mousePosition_ == part;
@@ -431,7 +432,8 @@
 
 // Returns the text color that should be used to draw text on |part|.
 - (NSColor*)titleColorForPart:(DownloadItemMousePosition)part {
-  ThemeProvider* themeProvider = [[[self controlView] window] themeProvider];
+  ui::ThemeProvider* themeProvider =
+      [[[self controlView] window] themeProvider];
   NSColor* themeTextColor =
       themeProvider->GetNSColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT,
                                 true);
@@ -480,7 +482,8 @@
   // with a background that looks like windows (some transparent white) if a
   // theme is used. Use custom theme object with a white color gradient to trick
   // the superclass into drawing what we want.
-  ThemeProvider* themeProvider = [[[self controlView] window] themeProvider];
+  ui::ThemeProvider* themeProvider =
+      [[[self controlView] window] themeProvider];
   bool isDefaultTheme =
       !themeProvider->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND);
 
diff --git a/chrome/browser/ui/cocoa/download/download_item_controller.mm b/chrome/browser/ui/cocoa/download/download_item_controller.mm
index 23603f8..d8ab8ad 100644
--- a/chrome/browser/ui/cocoa/download/download_item_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_controller.mm
@@ -4,9 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/download/download_item_controller.h"
 
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
 #include "base/mac/mac_util.h"
 #include "base/metrics/histogram.h"
 #include "base/string16.h"
@@ -27,6 +24,9 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
 
 namespace {
 
@@ -87,7 +87,7 @@
 
 @interface DownloadItemController (Private)
 - (void)themeDidChangeNotification:(NSNotification*)aNotification;
-- (void)updateTheme:(ThemeProvider*)themeProvider;
+- (void)updateTheme:(ui::ThemeProvider*)themeProvider;
 - (void)setState:(DownoadItemState)state;
 @end
 
@@ -191,15 +191,15 @@
       // Elide giant extensions.
       if (extension.length() > kFileNameMaxLength / 2) {
         std::wstring wide_extension;
-        gfx::ElideString(UTF8ToWide(extension), kFileNameMaxLength / 2,
-                       &wide_extension);
+        ui::ElideString(UTF8ToWide(extension), kFileNameMaxLength / 2,
+                        &wide_extension);
         extension = WideToUTF8(wide_extension);
       }
 
       // Rebuild the filename.extension.
       std::wstring rootname = UTF8ToWide(filename.RemoveExtension().value());
-      gfx::ElideString(rootname, kFileNameMaxLength - extension.length(),
-                       &rootname);
+      ui::ElideString(rootname, kFileNameMaxLength - extension.length(),
+                      &rootname);
       std::string new_filename = WideToUTF8(rootname);
       if (extension.length())
         new_filename += std::string(".") + extension;
@@ -269,7 +269,7 @@
 }
 
 - (void)updateToolTip {
-  string16 elidedFilename = gfx::ElideFilename(
+  string16 elidedFilename = ui::ElideFilename(
       [self download]->GetFileNameToReportUser(),
       gfx::Font(), kToolTipMaxWidth);
   [progressView_ setToolTip:base::SysUTF16ToNSString(elidedFilename)];
@@ -306,14 +306,14 @@
 
 // Called after the current theme has changed.
 - (void)themeDidChangeNotification:(NSNotification*)aNotification {
-  ThemeProvider* themeProvider =
-      static_cast<ThemeProvider*>([[aNotification object] pointerValue]);
+  ui::ThemeProvider* themeProvider =
+      static_cast<ui::ThemeProvider*>([[aNotification object] pointerValue]);
   [self updateTheme:themeProvider];
 }
 
 // Adapt appearance to the current theme. Called after theme changes and before
 // this is shown for the first time.
-- (void)updateTheme:(ThemeProvider*)themeProvider {
+- (void)updateTheme:(ui::ThemeProvider*)themeProvider {
   NSColor* color =
       themeProvider->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT, true);
   [dangerousDownloadLabel_ setTextColor:color];
diff --git a/chrome/browser/ui/cocoa/download/download_item_mac.mm b/chrome/browser/ui/cocoa/download/download_item_mac.mm
index f39cb96..ab756ce 100644
--- a/chrome/browser/ui/cocoa/download/download_item_mac.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_mac.mm
@@ -35,7 +35,7 @@
   }
 
   if (download->GetUserVerifiedFilePath() != lastFilePath_) {
-    // Turns out the file path is "unconfirmed %d.crdownload" for dangerous
+    // Turns out the file path is "Unconfirmed %d.crdownload" for dangerous
     // downloads. When the download is confirmed, the file is renamed on
     // another thread, so reload the icon if the download filename changes.
     LoadIcon();
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
index f88071f..fea1940 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
@@ -4,8 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/download/download_item.h"
@@ -23,6 +21,8 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Download shelf autoclose behavior:
 //
@@ -161,7 +161,8 @@
   NSColor* color = nil;
 
   if (bridge_.get() && bridge_->browser() && bridge_->browser()->profile()) {
-    ThemeProvider* provider = bridge_->browser()->profile()->GetThemeProvider();
+    ui::ThemeProvider* provider =
+        bridge_->browser()->profile()->GetThemeProvider();
 
     color =
         provider->GetNSColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, false);
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_view.mm b/chrome/browser/ui/cocoa/download/download_shelf_view.mm
index f3840ef..55b88d5 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_view.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_view.mm
@@ -14,7 +14,7 @@
 
 - (NSColor*)strokeColor {
   BOOL isKey = [[self window] isKeyWindow];
-  ThemeProvider* themeProvider = [[self window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[self window] themeProvider];
   return themeProvider ? themeProvider->GetNSColor(
       isKey ? BrowserThemeProvider::COLOR_TOOLBAR_STROKE :
               BrowserThemeProvider::COLOR_TOOLBAR_STROKE_INACTIVE, true) :
@@ -23,7 +23,7 @@
 
 - (void)drawRect:(NSRect)rect {
   BOOL isKey = [[self window] isKeyWindow];
-  ThemeProvider* themeProvider = [[self window] themeProvider];
+  ui::ThemeProvider* themeProvider = [[self window] themeProvider];
   if (!themeProvider)
     return;
 
diff --git a/chrome/browser/ui/cocoa/download/download_started_animation_mac.mm b/chrome/browser/ui/cocoa/download/download_started_animation_mac.mm
index d95b732..beff0a6 100644
--- a/chrome/browser/ui/cocoa/download/download_started_animation_mac.mm
+++ b/chrome/browser/ui/cocoa/download/download_started_animation_mac.mm
@@ -11,7 +11,6 @@
 
 #import <QuartzCore/QuartzCore.h>
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view_mac.h"
 #include "chrome/common/notification_registrar.h"
@@ -21,6 +20,7 @@
 #include "grit/theme_resources.h"
 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class DownloadAnimationTabObserver;
 
diff --git a/chrome/browser/ui/cocoa/download/download_util_mac.mm b/chrome/browser/ui/cocoa/download/download_util_mac.mm
index baafbbf..1c6808f 100644
--- a/chrome/browser/ui/cocoa/download/download_util_mac.mm
+++ b/chrome/browser/ui/cocoa/download/download_util_mac.mm
@@ -10,8 +10,8 @@
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 #import "chrome/browser/ui/cocoa/dock_icon.h"
-#include "gfx/native_widget_types.h"
 #include "skia/ext/skia_utils_mac.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace download_util {
 
@@ -47,7 +47,7 @@
   NSImage* dragImage = gfx::SkBitmapToNSImage(*icon);
 
   // Synthesize a drag event, since we don't have access to the actual event
-  // that initiated a drag (possibly consumed by the DOM UI, for example).
+  // that initiated a drag (possibly consumed by the Web UI, for example).
   NSPoint position = [[view window] mouseLocationOutsideOfEventStream];
   NSTimeInterval eventTime = [[NSApp currentEvent] timestamp];
   NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
diff --git a/chrome/browser/ui/cocoa/draggable_button.h b/chrome/browser/ui/cocoa/draggable_button.h
index 2e166b7..7f58255 100644
--- a/chrome/browser/ui/cocoa/draggable_button.h
+++ b/chrome/browser/ui/cocoa/draggable_button.h
@@ -13,7 +13,7 @@
 }
 
 // Enable or disable dragability for special buttons like "Other Bookmarks".
-@property (nonatomic) BOOL draggable;
+@property(nonatomic) BOOL draggable;
 
 // Called when a drag should start. Subclasses must override this to do any
 // pasteboard manipulation and begin the drag, usually with
diff --git a/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.mm b/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.mm
deleted file mode 100644
index 7d83c74..0000000
--- a/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.mm
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.h"
-
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#include "base/logging.h"
-#import "base/mac/mac_util.h"
-#include "base/string16.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-namespace {
-
-void ShiftOriginY(NSView* view, CGFloat amount) {
-  NSPoint origin = [view frame].origin;
-  origin.y += amount;
-  [view setFrameOrigin:origin];
-}
-
-}  // namespace
-
-@implementation EditSearchEngineCocoaController
-
-- (id)initWithProfile:(Profile*)profile
-             delegate:(EditSearchEngineControllerDelegate*)delegate
-          templateURL:(const TemplateURL*)url {
-  DCHECK(profile);
-  NSString* nibpath = [base::mac::MainAppBundle()
-                        pathForResource:@"EditSearchEngine"
-                                 ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    profile_ = profile;
-    templateURL_ = url;
-    controller_.reset(
-        new EditSearchEngineController(templateURL_, delegate, profile_));
-  }
-  return self;
-}
-
-- (void)awakeFromNib {
-  DCHECK([self window]);
-  DCHECK_EQ(self, [[self window] delegate]);
-
-  // Make sure the url description field fits the text in it.
-  CGFloat descriptionShift = [GTMUILocalizerAndLayoutTweaker
-      sizeToFitFixedWidthTextField:urlDescriptionField_];
-
-  // Move the label container above the url description.
-  ShiftOriginY(labelContainer_, descriptionShift);
-  // There was no way via view containment to use a helper view to move all
-  // the textfields and images at once, most move them all on their own so
-  // they stay above the url description.
-  ShiftOriginY(nameField_, descriptionShift);
-  ShiftOriginY(keywordField_, descriptionShift);
-  ShiftOriginY(urlField_, descriptionShift);
-  ShiftOriginY(nameImage_, descriptionShift);
-  ShiftOriginY(keywordImage_, descriptionShift);
-  ShiftOriginY(urlImage_, descriptionShift);
-
-  // Resize the containing box for the name/keyword/url fields/images since it
-  // also contains the url description (which just grew).
-  [[fieldAndImageContainer_ contentView] setAutoresizesSubviews:NO];
-  NSRect rect = [fieldAndImageContainer_ frame];
-  rect.size.height += descriptionShift;
-  [fieldAndImageContainer_ setFrame:rect];
-  [[fieldAndImageContainer_ contentView] setAutoresizesSubviews:YES];
-
-  // Resize the window.
-  NSWindow* window = [self window];
-  NSSize windowDelta = NSMakeSize(0, descriptionShift);
-  [GTMUILocalizerAndLayoutTweaker
-      resizeWindowWithoutAutoResizingSubViews:window
-                                        delta:windowDelta];
-
-  ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
-  goodImage_.reset([bundle.GetNativeImageNamed(IDR_INPUT_GOOD) retain]);
-  badImage_.reset([bundle.GetNativeImageNamed(IDR_INPUT_ALERT) retain]);
-  if (templateURL_) {
-    // Defaults to |..._NEW_WINDOW_TITLE|.
-    [window setTitle:l10n_util::GetNSString(
-      IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE)];
-    [nameField_ setStringValue:
-        base::SysWideToNSString(templateURL_->short_name())];
-    [keywordField_ setStringValue:
-        base::SysWideToNSString(templateURL_->keyword())];
-    [urlField_ setStringValue:
-        base::SysWideToNSString(templateURL_->url()->DisplayURL())];
-    [urlField_ setEnabled:(templateURL_->prepopulate_id() == 0)];
-  }
-  // When creating a new keyword, this will mark the fields as "invalid" and
-  // will not let the user save. If this is an edit, then this will set all
-  // the images to the "valid" state.
-  [self validateFields];
-}
-
-// When the window closes, clean ourselves up.
-- (void)windowWillClose:(NSNotification*)notif {
-  [self autorelease];
-}
-
-// Performs the logic of closing the window. If we are a sheet, then it ends the
-// modal session; otherwise, it closes the window.
-- (void)doClose {
-  if ([[self window] isSheet]) {
-    [NSApp endSheet:[self window]];
-  } else {
-    [[self window] close];
-  }
-}
-
-- (IBAction)cancel:(id)sender {
-  [self doClose];
-}
-
-- (IBAction)save:(id)sender {
-  DCHECK([self validateFields]);
-  string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
-  string16 keyword = base::SysNSStringToUTF16([keywordField_ stringValue]);
-  std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
-  controller_->AcceptAddOrEdit(title, keyword, url);
-  [self doClose];
-}
-
-// Delegate method for the text fields.
-
-- (void)controlTextDidChange:(NSNotification*)notif {
-  [self validateFields];
-}
-
-- (void)controlTextDidEndEditing:(NSNotification*)notif {
-  [self validateFields];
-}
-
-// Private --------------------------------------------------------------------
-
-// Sets the appropriate image and tooltip based on a boolean |valid|.
-- (void)setIsValid:(BOOL)valid
-           toolTip:(int)messageID
-      forImageView:(NSImageView*)imageView
-         textField:(NSTextField*)textField {
-  NSImage* image = (valid) ? goodImage_ : badImage_;
-  [imageView setImage:image];
-
-  NSString* toolTip = nil;
-  if (!valid)
-    toolTip = l10n_util::GetNSString(messageID);
-  [textField setToolTip:toolTip];
-  [imageView setToolTip:toolTip];
-}
-
-// This sets the image state for all the controls and enables or disables the
-// done button. Returns YES if all the fields are valid.
-- (BOOL)validateFields {
-  string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
-  BOOL titleValid = controller_->IsTitleValid(title);
-  [self setIsValid:titleValid
-           toolTip:IDS_SEARCH_ENGINES_INVALID_TITLE_TT
-      forImageView:nameImage_
-         textField:nameField_];
-
-  string16 keyword = base::SysNSStringToUTF16([keywordField_ stringValue]);
-  BOOL keywordValid = controller_->IsKeywordValid(keyword);
-  [self setIsValid:keywordValid
-           toolTip:IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT
-      forImageView:keywordImage_
-         textField:keywordField_];
-
-  std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
-  BOOL urlValid = controller_->IsURLValid(url);
-  [self setIsValid:urlValid
-           toolTip:IDS_SEARCH_ENGINES_INVALID_URL_TT
-      forImageView:urlImage_
-         textField:urlField_];
-
-  BOOL isValid = (titleValid && keywordValid && urlValid);
-  [doneButton_ setEnabled:isValid];
-  return isValid;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller_unittest.mm
deleted file mode 100644
index 72bfe7b..0000000
--- a/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller_unittest.mm
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/l10n_util_mac.h"
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.h"
-#include "chrome/test/testing_profile.h"
-#include "grit/generated_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-@interface FakeEditSearchEngineController : EditSearchEngineCocoaController {
-}
-@property (nonatomic, readonly) NSTextField* nameField;
-@property (nonatomic, readonly) NSTextField* keywordField;
-@property (nonatomic, readonly) NSTextField* urlField;
-@property (nonatomic, readonly) NSImageView* nameImage;
-@property (nonatomic, readonly) NSImageView* keywordImage;
-@property (nonatomic, readonly) NSImageView* urlImage;
-@property (nonatomic, readonly) NSButton* doneButton;
-@property (nonatomic, readonly) NSImage* goodImage;
-@property (nonatomic, readonly) NSImage* badImage;
-@end
-
-@implementation FakeEditSearchEngineController
-@synthesize nameField = nameField_;
-@synthesize keywordField = keywordField_;
-@synthesize urlField = urlField_;
-@synthesize nameImage = nameImage_;
-@synthesize keywordImage = keywordImage_;
-@synthesize urlImage = urlImage_;
-@synthesize doneButton = doneButton_;
-- (NSImage*)goodImage {
-  return goodImage_.get();
-}
-- (NSImage*)badImage {
-  return badImage_.get();
-}
-@end
-
-namespace {
-
-class EditSearchEngineControllerTest : public CocoaTest {
- public:
-   virtual void SetUp() {
-     CocoaTest::SetUp();
-     TestingProfile* profile =
-        static_cast<TestingProfile*>(browser_helper_.profile());
-     profile->CreateTemplateURLModel();
-     controller_ = [[FakeEditSearchEngineController alloc]
-                    initWithProfile:profile
-                    delegate:nil
-                    templateURL:nil];
-   }
-
-  virtual void TearDown() {
-    // Force the window to load so we hit |-awakeFromNib| to register as the
-    // window's delegate so that the controller can clean itself up in
-    // |-windowWillClose:|.
-    ASSERT_TRUE([controller_ window]);
-
-    [controller_ close];
-    CocoaTest::TearDown();
-  }
-
-  BrowserTestHelper browser_helper_;
-  FakeEditSearchEngineController* controller_;
-};
-
-TEST_F(EditSearchEngineControllerTest, ValidImageOriginals) {
-  EXPECT_FALSE([controller_ goodImage]);
-  EXPECT_FALSE([controller_ badImage]);
-
-  EXPECT_TRUE([controller_ window]);  // Force the window to load.
-
-  EXPECT_TRUE([[controller_ goodImage] isKindOfClass:[NSImage class]]);
-  EXPECT_TRUE([[controller_ badImage] isKindOfClass:[NSImage class]]);
-
-  // Test window title is set correctly.
-  NSString* title = l10n_util::GetNSString(
-      IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE);
-  EXPECT_NSEQ(title, [[controller_ window] title]);
-}
-
-TEST_F(EditSearchEngineControllerTest, SetImageViews) {
-  EXPECT_TRUE([controller_ window]);  // Force the window to load.
-  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
-  // An empty keyword is not OK.
-  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
-  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
-}
-
-// This test ensures that on creating a new keyword, we are in an "invalid"
-// state that cannot save.
-TEST_F(EditSearchEngineControllerTest, InvalidState) {
-  EXPECT_TRUE([controller_ window]);  // Force window to load.
-  NSString* toolTip = nil;
-  EXPECT_FALSE([controller_ validateFields]);
-
-  EXPECT_NSEQ(@"", [[controller_ nameField] stringValue]);
-  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
-  toolTip = l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
-  EXPECT_NSEQ(toolTip, [[controller_ nameField] toolTip]);
-  EXPECT_NSEQ(toolTip, [[controller_ nameImage] toolTip]);
-
-  // Keywords can not be empty strings.
-  EXPECT_NSEQ(@"", [[controller_ keywordField] stringValue]);
-  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
-  EXPECT_TRUE([[controller_ keywordField] toolTip]);
-  EXPECT_TRUE([[controller_ keywordImage] toolTip]);
-
-  EXPECT_NSEQ(@"", [[controller_ urlField] stringValue]);
-  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
-  toolTip = l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_URL_TT);
-  EXPECT_NSEQ(toolTip, [[controller_ urlField] toolTip]);
-  EXPECT_NSEQ(toolTip, [[controller_ urlImage] toolTip]);
-}
-
-// Tests that the single name field validates.
-TEST_F(EditSearchEngineControllerTest, ValidateName) {
-  EXPECT_TRUE([controller_ window]);  // Force window to load.
-
-  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
-  EXPECT_FALSE([controller_ validateFields]);
-  NSString* toolTip =
-      l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
-  EXPECT_NSEQ(toolTip, [[controller_ nameField] toolTip]);
-  EXPECT_NSEQ(toolTip, [[controller_ nameImage] toolTip]);
-  [[controller_ nameField] setStringValue:@"Test Name"];
-  EXPECT_FALSE([controller_ validateFields]);
-  EXPECT_EQ([controller_ goodImage], [[controller_ nameImage] image]);
-  EXPECT_FALSE([[controller_ nameField] toolTip]);
-  EXPECT_FALSE([[controller_ nameImage] toolTip]);
-  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
-}
-
-// The keyword field is not valid if it is empty.
-TEST_F(EditSearchEngineControllerTest, ValidateKeyword) {
-  EXPECT_TRUE([controller_ window]);  // Force window load.
-
-  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
-  EXPECT_FALSE([controller_ validateFields]);
-  EXPECT_TRUE([[controller_ keywordField] toolTip]);
-  EXPECT_TRUE([[controller_ keywordImage] toolTip]);
-  [[controller_ keywordField] setStringValue:@"foobar"];
-  EXPECT_FALSE([controller_ validateFields]);
-  EXPECT_EQ([controller_ goodImage], [[controller_ keywordImage] image]);
-  EXPECT_FALSE([[controller_ keywordField] toolTip]);
-  EXPECT_FALSE([[controller_ keywordImage] toolTip]);
-  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
-}
-
-// Tests that the URL field validates.
-TEST_F(EditSearchEngineControllerTest, ValidateURL) {
-  EXPECT_TRUE([controller_ window]);  // Force window to load.
-
-  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
-  EXPECT_FALSE([controller_ validateFields]);
-  NSString* toolTip =
-      l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_URL_TT);
-  EXPECT_NSEQ(toolTip, [[controller_ urlField] toolTip]);
-  EXPECT_NSEQ(toolTip, [[controller_ urlImage] toolTip]);
-  [[controller_ urlField] setStringValue:@"http://foo-bar.com"];
-  EXPECT_FALSE([controller_ validateFields]);
-  EXPECT_EQ([controller_ goodImage], [[controller_ urlImage] image]);
-  EXPECT_FALSE([[controller_ urlField] toolTip]);
-  EXPECT_FALSE([[controller_ urlImage] toolTip]);
-  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
-}
-
-// Tests that if the user enters all valid data that the UI reflects that
-// and that they can save.
-TEST_F(EditSearchEngineControllerTest, ValidateFields) {
-  EXPECT_TRUE([controller_ window]);  // Force window to load.
-
-  // State before entering data.
-  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
-  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
-  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
-  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
-  EXPECT_FALSE([controller_ validateFields]);
-
-  [[controller_ nameField] setStringValue:@"Test Name"];
-  EXPECT_FALSE([controller_ validateFields]);
-  EXPECT_EQ([controller_ goodImage], [[controller_ nameImage] image]);
-  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
-
-  [[controller_ keywordField] setStringValue:@"foobar"];
-  EXPECT_FALSE([controller_ validateFields]);
-  EXPECT_EQ([controller_ goodImage], [[controller_ keywordImage] image]);
-  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
-
-  // Once the URL is entered, we should have all 3 valid fields.
-  [[controller_ urlField] setStringValue:@"http://foo-bar.com"];
-  EXPECT_TRUE([controller_ validateFields]);
-  EXPECT_EQ([controller_ goodImage], [[controller_ urlImage] image]);
-  EXPECT_TRUE([[controller_ doneButton] isEnabled]);
-}
-
-// Tests editing an existing TemplateURL.
-TEST_F(EditSearchEngineControllerTest, EditTemplateURL) {
-  TemplateURL url;
-  url.set_short_name(L"Foobar");
-  url.set_keyword(L"keyword");
-  std::string urlString = TemplateURLRef::DisplayURLToURLRef(
-      L"http://foo-bar.com");
-  url.SetURL(urlString, 0, 1);
-  TestingProfile* profile = browser_helper_.profile();
-  FakeEditSearchEngineController *controller =
-      [[FakeEditSearchEngineController alloc] initWithProfile:profile
-                                                     delegate:nil
-                                                  templateURL:&url];
-  EXPECT_TRUE([controller window]);
-  NSString* title = l10n_util::GetNSString(
-      IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE);
-  EXPECT_NSEQ(title, [[controller window] title]);
-  NSString* nameString = [[controller nameField] stringValue];
-  EXPECT_NSEQ(@"Foobar", nameString);
-  NSString* keywordString = [[controller keywordField] stringValue];
-  EXPECT_NSEQ(@"keyword", keywordString);
-  NSString* urlValueString = [[controller urlField] stringValue];
-  EXPECT_NSEQ(@"http://foo-bar.com", urlValueString);
-  EXPECT_TRUE([controller validateFields]);
-  [controller close];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.mm b/chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.mm
index 775ffdc..fabc392 100644
--- a/chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.mm
@@ -10,7 +10,6 @@
 #include "base/sys_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
 
 namespace {
diff --git a/chrome/browser/ui/cocoa/event_utils.mm b/chrome/browser/ui/cocoa/event_utils.mm
index ec475b5..d471398 100644
--- a/chrome/browser/ui/cocoa/event_utils.mm
+++ b/chrome/browser/ui/cocoa/event_utils.mm
@@ -4,6 +4,8 @@
 
 #import "chrome/browser/ui/cocoa/event_utils.h"
 
+#include "chrome/browser/disposition_utils.h"
+
 namespace event_utils {
 
 WindowOpenDisposition WindowOpenDispositionFromNSEvent(NSEvent* event) {
@@ -13,9 +15,12 @@
 
 WindowOpenDisposition WindowOpenDispositionFromNSEventWithFlags(
     NSEvent* event, NSUInteger flags) {
-  if ([event buttonNumber] == 2 || flags & NSCommandKeyMask)
-    return flags & NSShiftKeyMask ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
-  return flags & NSShiftKeyMask ? NEW_WINDOW : CURRENT_TAB;
+  return disposition_utils::DispositionFromClick(
+      [event buttonNumber] == 2,
+      flags & NSAlternateKeyMask,
+      flags & NSControlKeyMask,
+      flags & NSCommandKeyMask,
+      flags & NSShiftKeyMask);
 }
 
 }  // namespace event_utils
diff --git a/chrome/browser/ui/cocoa/extension_install_prompt.mm b/chrome/browser/ui/cocoa/extension_install_prompt.mm
deleted file mode 100644
index 3306806..0000000
--- a/chrome/browser/ui/cocoa/extension_install_prompt.mm
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include <string>
-
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#include "base/sys_string_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/extensions/extension_install_ui.h"
-#include "chrome/common/extensions/extension.h"
-#include "grit/browser_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-
-class Profile;
-
-void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl(
-    Profile* profile,
-    Delegate* delegate,
-    const Extension* extension,
-    SkBitmap* icon,
-    ExtensionInstallUI::PromptType type) {
-  NSAlert* alert = [[[NSAlert alloc] init] autorelease];
-
-  NSButton* continueButton = [alert addButtonWithTitle:l10n_util::GetNSString(
-      ExtensionInstallUI::kButtonIds[type])];
-  // Clear the key equivalent (currently 'Return') because cancel is the default
-  // button.
-  [continueButton setKeyEquivalent:@""];
-
-  NSButton* cancelButton = [alert addButtonWithTitle:l10n_util::GetNSString(
-      IDS_CANCEL)];
-  [cancelButton setKeyEquivalent:@"\r"];
-
-  [alert setMessageText:l10n_util::GetNSStringF(
-       ExtensionInstallUI::kHeadingIds[type],
-       UTF8ToUTF16(extension->name()))];
-  [alert setAlertStyle:NSWarningAlertStyle];
-  [alert setIcon:gfx::SkBitmapToNSImage(*icon)];
-
-  if ([alert runModal] == NSAlertFirstButtonReturn) {
-    delegate->InstallUIProceed();
-  } else {
-    delegate->InstallUIAbort();
-  }
-}
diff --git a/chrome/browser/ui/cocoa/extension_installed_bubble_bridge.h b/chrome/browser/ui/cocoa/extension_installed_bubble_bridge.h
deleted file mode 100644
index 62d72c3..0000000
--- a/chrome/browser/ui/cocoa/extension_installed_bubble_bridge.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// C++ bridge function to connect ExtensionInstallUI to the Cocoa-based
-// extension installed bubble.
-
-#ifndef CHROME_BROWSER_UI_COCOA_EXTENSION_INSTALLED_BUBBLE_BRIDGE_H_
-#define CHROME_BROWSER_UI_COCOA_EXTENSION_INSTALLED_BUBBLE_BRIDGE_H_
-#pragma once
-
-#include "gfx/native_widget_types.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-class Browser;
-class Extension;
-
-namespace ExtensionInstalledBubbleCocoa {
-
-// This function is called by the ExtensionInstallUI when an extension has been
-// installed.
-void ShowExtensionInstalledBubble(gfx::NativeWindow window,
-                                  const Extension* extension,
-                                  Browser* browser,
-                                  SkBitmap icon);
-}
-
-#endif  // CHROME_BROWSER_UI_COCOA_EXTENSION_INSTALLED_BUBBLE_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/extension_installed_bubble_bridge.mm b/chrome/browser/ui/cocoa/extension_installed_bubble_bridge.mm
deleted file mode 100644
index d439899..0000000
--- a/chrome/browser/ui/cocoa/extension_installed_bubble_bridge.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "extension_installed_bubble_bridge.h"
-
-#import "chrome/browser/ui/cocoa/extension_installed_bubble_controller.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/extensions/extension.h"
-
-void ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble(
-    gfx::NativeWindow window,
-    const Extension* extension,
-    Browser* browser,
-    SkBitmap icon) {
-  // The controller is deallocated when the window is closed, so no need to
-  // worry about it here.
-  [[ExtensionInstalledBubbleController alloc]
-      initWithParentWindow:window
-                 extension:extension
-                   browser:browser
-                      icon:icon];
-}
diff --git a/chrome/browser/ui/cocoa/extension_installed_bubble_controller.h b/chrome/browser/ui/cocoa/extension_installed_bubble_controller.h
deleted file mode 100644
index 63dfc22..0000000
--- a/chrome/browser/ui/cocoa/extension_installed_bubble_controller.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_ptr.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-class Browser;
-class Extension;
-class ExtensionLoadedNotificationObserver;
-@class HoverCloseButton;
-@class InfoBubbleView;
-
-namespace extension_installed_bubble {
-
-// Maximum height or width of extension's icon (corresponds to Windows & GTK).
-const int kIconSize = 43;
-
-// Outer vertical margin for text, icon, and closing x.
-const int kOuterVerticalMargin = 15;
-
-// Inner vertical margin for text messages.
-const int kInnerVerticalMargin = 10;
-
-// We use a different kind of notification for each of these extension types.
-typedef enum {
-  kBrowserAction,
-  kGeneric,
-  kOmniboxKeyword,
-  kPageAction
-} ExtensionType;
-
-}
-
-// Controller for the extension installed bubble.  This bubble pops up after
-// an extension has been installed to inform the user that the install happened
-// properly, and to let the user know how to manage this extension in the
-// future.
-@interface ExtensionInstalledBubbleController :
-    NSWindowController<NSWindowDelegate> {
- @private
-  NSWindow* parentWindow_;  // weak
-  const Extension* extension_;  // weak
-  Browser* browser_;  // weak
-  scoped_nsobject<NSImage> icon_;
-
-  extension_installed_bubble::ExtensionType type_;
-
-  // We need to remove the page action immediately when the browser window
-  // closes while this bubble is still open, so the bubble's closing animation
-  // doesn't overlap browser destruction.
-  BOOL pageActionRemoved_;
-
-  // Lets us register for EXTENSION_LOADED notifications.  The actual
-  // notifications are sent to the observer object, which proxies them
-  // back to the controller.
-  scoped_ptr<ExtensionLoadedNotificationObserver> extensionObserver_;
-
-  // References below are weak, being obtained from the nib.
-  IBOutlet InfoBubbleView* infoBubbleView_;
-  IBOutlet HoverCloseButton* closeButton_;
-  IBOutlet NSImageView* iconImage_;
-  IBOutlet NSTextField* extensionInstalledMsg_;
-  // Only shown for page actions and omnibox keywords.
-  IBOutlet NSTextField* extraInfoMsg_;
-  IBOutlet NSTextField* extensionInstalledInfoMsg_;
-}
-
-@property (nonatomic, readonly) const Extension* extension;
-@property (nonatomic) BOOL pageActionRemoved;
-
-// Initialize the window, and then create observers to wait for the extension
-// to complete loading, or the browser window to close.
-- (id)initWithParentWindow:(NSWindow*)parentWindow
-                 extension:(const Extension*)extension
-                   browser:(Browser*)browser
-                      icon:(SkBitmap)icon;
-
-// Action for close button.
-- (IBAction)closeWindow:(id)sender;
-
-// Displays the extension installed bubble. This callback is triggered by
-// the extensionObserver when the extension has completed loading.
-- (void)showWindow:(id)sender;
-
-// Clears our weak pointer to the Extension. This callback is triggered by
-// the extensionObserver when the extension is unloaded.
-- (void)extensionUnloaded:(id)sender;
-
-@end
-
-@interface ExtensionInstalledBubbleController(ExposedForTesting)
-
-- (void)removePageActionPreviewIfNecessary;
-- (NSWindow*)initializeWindow;
-- (int)calculateWindowHeight;
-- (void)setMessageFrames:(int)newWindowHeight;
-- (NSRect)getExtensionInstalledMsgFrame;
-- (NSRect)getExtraInfoMsgFrame;
-- (NSRect)getExtensionInstalledInfoMsgFrame;
-
-@end  // ExtensionInstalledBubbleController(ExposedForTesting)
-
-#endif  // CHROME_BROWSER_UI_COCOA_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extension_installed_bubble_controller.mm
deleted file mode 100644
index ad30096..0000000
--- a/chrome/browser/ui/cocoa/extension_installed_bubble_controller.mm
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "extension_installed_bubble_controller.h"
-
-#include "app/l10n_util.h"
-#include "base/i18n/rtl.h"
-#include "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
-#include "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
-#include "chrome/browser/ui/cocoa/hover_close_button.h"
-#include "chrome/browser/ui/cocoa/info_bubble_view.h"
-#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#include "chrome/browser/ui/cocoa/toolbar_controller.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_action.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_source.h"
-#include "grit/generated_resources.h"
-#import "skia/ext/skia_utils_mac.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-
-// C++ class that receives EXTENSION_LOADED notifications and proxies them back
-// to |controller|.
-class ExtensionLoadedNotificationObserver : public NotificationObserver {
- public:
-  ExtensionLoadedNotificationObserver(
-      ExtensionInstalledBubbleController* controller, Profile* profile)
-          : controller_(controller) {
-    registrar_.Add(this, NotificationType::EXTENSION_LOADED,
-        Source<Profile>(profile));
-    registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
-        Source<Profile>(profile));
-  }
-
- private:
-  // NotificationObserver implementation. Tells the controller to start showing
-  // its window on the main thread when the extension has finished loading.
-  void Observe(NotificationType type,
-               const NotificationSource& source,
-               const NotificationDetails& details) {
-    if (type == NotificationType::EXTENSION_LOADED) {
-      const Extension* extension = Details<const Extension>(details).ptr();
-      if (extension == [controller_ extension]) {
-        [controller_ performSelectorOnMainThread:@selector(showWindow:)
-                                      withObject:controller_
-                                   waitUntilDone:NO];
-      }
-    } else if (type == NotificationType::EXTENSION_UNLOADED) {
-      const Extension* extension = Details<const Extension>(details).ptr();
-      if (extension == [controller_ extension]) {
-        [controller_ performSelectorOnMainThread:@selector(extensionUnloaded:)
-                                      withObject:controller_
-                                   waitUntilDone:NO];
-      }
-    } else {
-      NOTREACHED() << "Received unexpected notification.";
-    }
-  }
-
-  NotificationRegistrar registrar_;
-  ExtensionInstalledBubbleController* controller_;  // weak, owns us
-};
-
-@implementation ExtensionInstalledBubbleController
-
-@synthesize extension = extension_;
-@synthesize pageActionRemoved = pageActionRemoved_;  // Exposed for unit test.
-
-- (id)initWithParentWindow:(NSWindow*)parentWindow
-                 extension:(const Extension*)extension
-                   browser:(Browser*)browser
-                      icon:(SkBitmap)icon {
-  NSString* nibPath =
-      [base::mac::MainAppBundle() pathForResource:@"ExtensionInstalledBubble"
-                                          ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
-    DCHECK(parentWindow);
-    parentWindow_ = parentWindow;
-    DCHECK(extension);
-    extension_ = extension;
-    DCHECK(browser);
-    browser_ = browser;
-    icon_.reset([gfx::SkBitmapToNSImage(icon) retain]);
-    pageActionRemoved_ = NO;
-
-    if (!extension->omnibox_keyword().empty()) {
-      type_ = extension_installed_bubble::kOmniboxKeyword;
-    } else if (extension->browser_action()) {
-      type_ = extension_installed_bubble::kBrowserAction;
-    } else if (extension->page_action() &&
-               !extension->page_action()->default_icon_path().empty()) {
-      type_ = extension_installed_bubble::kPageAction;
-    } else {
-      NOTREACHED();  // kGeneric installs handled in the extension_install_ui.
-    }
-
-    // Start showing window only after extension has fully loaded.
-    extensionObserver_.reset(new ExtensionLoadedNotificationObserver(
-        self, browser->profile()));
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [super dealloc];
-}
-
-- (void)close {
-  [parentWindow_ removeChildWindow:[self window]];
-  [super close];
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
-  // Turn off page action icon preview when the window closes, unless we
-  // already removed it when the window resigned key status.
-  [self removePageActionPreviewIfNecessary];
-  extension_ = NULL;
-  browser_ = NULL;
-  parentWindow_ = nil;
-  // We caught a close so we don't need to watch for the parent closing.
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [self autorelease];
-}
-
-// The controller is the delegate of the window, so it receives "did resign
-// key" notifications.  When key is resigned, close the window.
-- (void)windowDidResignKey:(NSNotification*)notification {
-  NSWindow* window = [self window];
-  DCHECK_EQ([notification object], window);
-  DCHECK([window isVisible]);
-
-  // If the browser window is closing, we need to remove the page action
-  // immediately, otherwise the closing animation may overlap with
-  // browser destruction.
-  [self removePageActionPreviewIfNecessary];
-  [self close];
-}
-
-- (IBAction)closeWindow:(id)sender {
-  DCHECK([[self window] isVisible]);
-  [self close];
-}
-
-// Extracted to a function here so that it can be overwritten for unit
-// testing.
-- (void)removePageActionPreviewIfNecessary {
-  if (!extension_ || !extension_->page_action() || pageActionRemoved_)
-    return;
-  pageActionRemoved_ = YES;
-
-  BrowserWindowCocoa* window =
-      static_cast<BrowserWindowCocoa*>(browser_->window());
-  LocationBarViewMac* locationBarView =
-      [window->cocoa_controller() locationBarBridge];
-  locationBarView->SetPreviewEnabledPageAction(extension_->page_action(),
-                                               false);  // disables preview.
-}
-
-// The extension installed bubble points at the browser action icon or the
-// page action icon (shown as a preview), depending on the extension type.
-// We need to calculate the location of these icons and the size of the
-// message itself (which varies with the title of the extension) in order
-// to figure out the origin point for the extension installed bubble.
-// TODO(mirandac): add framework to easily test extension UI components!
-- (NSPoint)calculateArrowPoint {
-  BrowserWindowCocoa* window =
-      static_cast<BrowserWindowCocoa*>(browser_->window());
-  NSPoint arrowPoint = NSZeroPoint;
-
-  switch(type_) {
-    case extension_installed_bubble::kOmniboxKeyword: {
-      LocationBarViewMac* locationBarView =
-          [window->cocoa_controller() locationBarBridge];
-      arrowPoint = locationBarView->GetPageInfoBubblePoint();
-      break;
-    }
-    case extension_installed_bubble::kBrowserAction: {
-      BrowserActionsController* controller =
-          [[window->cocoa_controller() toolbarController]
-              browserActionsController];
-      arrowPoint = [controller popupPointForBrowserAction:extension_];
-      break;
-    }
-    case extension_installed_bubble::kPageAction: {
-      LocationBarViewMac* locationBarView =
-          [window->cocoa_controller() locationBarBridge];
-
-      // Tell the location bar to show a preview of the page action icon, which
-      // would ordinarily only be displayed on a page of the appropriate type.
-      // We remove this preview when the extension installed bubble closes.
-      locationBarView->SetPreviewEnabledPageAction(extension_->page_action(),
-                                                   true);
-
-      // Find the center of the bottom of the page action icon.
-      arrowPoint =
-          locationBarView->GetPageActionBubblePoint(extension_->page_action());
-      break;
-    }
-    default: {
-      NOTREACHED() << "Generic extension type not allowed in install bubble.";
-    }
-  }
-  return arrowPoint;
-}
-
-// We want this to be a child of a browser window.  addChildWindow:
-// (called from this function) will bring the window on-screen;
-// unfortunately, [NSWindowController showWindow:] will also bring it
-// on-screen (but will cause unexpected changes to the window's
-// position).  We cannot have an addChildWindow: and a subsequent
-// showWindow:. Thus, we have our own version.
-- (void)showWindow:(id)sender {
-  // Generic extensions get an infobar rather than a bubble.
-  DCHECK(type_ != extension_installed_bubble::kGeneric);
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  // Load nib and calculate height based on messages to be shown.
-  NSWindow* window = [self initializeWindow];
-  int newWindowHeight = [self calculateWindowHeight];
-  [infoBubbleView_ setFrameSize:NSMakeSize(
-      NSWidth([[window contentView] bounds]), newWindowHeight)];
-  NSSize windowDelta = NSMakeSize(
-      0, newWindowHeight - NSHeight([[window contentView] bounds]));
-  windowDelta = [[window contentView] convertSize:windowDelta toView:nil];
-  NSRect newFrame = [window frame];
-  newFrame.size.height += windowDelta.height;
-  [window setFrame:newFrame display:NO];
-
-  // Now that we have resized the window, adjust y pos of the messages.
-  [self setMessageFrames:newWindowHeight];
-
-  // Find window origin, taking into account bubble size and arrow location.
-  NSPoint origin =
-      [parentWindow_ convertBaseToScreen:[self calculateArrowPoint]];
-  NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset +
-                              info_bubble::kBubbleArrowWidth / 2.0, 0);
-  offsets = [[window contentView] convertSize:offsets toView:nil];
-  if ([infoBubbleView_ arrowLocation] == info_bubble::kTopRight)
-    origin.x -= NSWidth([window frame]) - offsets.width;
-  origin.y -= NSHeight([window frame]);
-  [window setFrameOrigin:origin];
-
-  [parentWindow_ addChildWindow:window
-                        ordered:NSWindowAbove];
-  [window makeKeyAndOrderFront:self];
-}
-
-// Finish nib loading, set arrow location and load icon into window.  This
-// function is exposed for unit testing.
-- (NSWindow*)initializeWindow {
-  NSWindow* window = [self window];  // completes nib load
-
-  if (type_ == extension_installed_bubble::kOmniboxKeyword) {
-    [infoBubbleView_ setArrowLocation:info_bubble::kTopLeft];
-  } else {
-    [infoBubbleView_ setArrowLocation:info_bubble::kTopRight];
-  }
-
-  // Set appropriate icon, resizing if necessary.
-  if ([icon_ size].width > extension_installed_bubble::kIconSize) {
-    [icon_ setSize:NSMakeSize(extension_installed_bubble::kIconSize,
-                              extension_installed_bubble::kIconSize)];
-  }
-  [iconImage_ setImage:icon_];
-  [iconImage_ setNeedsDisplay:YES];
-  return window;
- }
-
-// Calculate the height of each install message, resizing messages in their
-// frames to fit window width.  Return the new window height, based on the
-// total of all message heights.
-- (int)calculateWindowHeight {
-  // Adjust the window height to reflect the sum height of all messages
-  // and vertical padding.
-  int newWindowHeight = 2 * extension_installed_bubble::kOuterVerticalMargin;
-
-  // First part of extension installed message.
-  string16 extension_name = UTF8ToUTF16(extension_->name().c_str());
-  base::i18n::AdjustStringForLocaleDirection(&extension_name);
-  [extensionInstalledMsg_ setStringValue:l10n_util::GetNSStringF(
-      IDS_EXTENSION_INSTALLED_HEADING, extension_name)];
-  [GTMUILocalizerAndLayoutTweaker
-      sizeToFitFixedWidthTextField:extensionInstalledMsg_];
-  newWindowHeight += [extensionInstalledMsg_ frame].size.height +
-      extension_installed_bubble::kInnerVerticalMargin;
-
-  // If type is page action, include a special message about page actions.
-  if (type_ == extension_installed_bubble::kPageAction) {
-    [extraInfoMsg_ setHidden:NO];
-    [[extraInfoMsg_ cell]
-        setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-    [GTMUILocalizerAndLayoutTweaker
-        sizeToFitFixedWidthTextField:extraInfoMsg_];
-    newWindowHeight += [extraInfoMsg_ frame].size.height +
-        extension_installed_bubble::kInnerVerticalMargin;
-  }
-
-  // If type is omnibox keyword, include a special message about the keyword.
-  if (type_ == extension_installed_bubble::kOmniboxKeyword) {
-    [extraInfoMsg_ setStringValue:l10n_util::GetNSStringF(
-        IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
-        UTF8ToUTF16(extension_->omnibox_keyword()))];
-    [extraInfoMsg_ setHidden:NO];
-    [[extraInfoMsg_ cell]
-        setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-    [GTMUILocalizerAndLayoutTweaker
-        sizeToFitFixedWidthTextField:extraInfoMsg_];
-    newWindowHeight += [extraInfoMsg_ frame].size.height +
-        extension_installed_bubble::kInnerVerticalMargin;
-  }
-
-  // Second part of extension installed message.
-  [[extensionInstalledInfoMsg_ cell]
-      setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-  [GTMUILocalizerAndLayoutTweaker
-      sizeToFitFixedWidthTextField:extensionInstalledInfoMsg_];
-  newWindowHeight += [extensionInstalledInfoMsg_ frame].size.height;
-
-  return newWindowHeight;
-}
-
-// Adjust y-position of messages to sit properly in new window height.
-- (void)setMessageFrames:(int)newWindowHeight {
-  // The extension messages will always be shown.
-  NSRect extensionMessageFrame1 = [extensionInstalledMsg_ frame];
-  NSRect extensionMessageFrame2 = [extensionInstalledInfoMsg_ frame];
-
-  extensionMessageFrame1.origin.y = newWindowHeight - (
-      extensionMessageFrame1.size.height +
-      extension_installed_bubble::kOuterVerticalMargin);
-  [extensionInstalledMsg_ setFrame:extensionMessageFrame1];
-  if (type_ == extension_installed_bubble::kPageAction ||
-      type_ == extension_installed_bubble::kOmniboxKeyword) {
-    // The extra message is only shown when appropriate.
-    NSRect extraMessageFrame = [extraInfoMsg_ frame];
-    extraMessageFrame.origin.y = extensionMessageFrame1.origin.y - (
-        extraMessageFrame.size.height +
-        extension_installed_bubble::kInnerVerticalMargin);
-    [extraInfoMsg_ setFrame:extraMessageFrame];
-    extensionMessageFrame2.origin.y = extraMessageFrame.origin.y - (
-        extensionMessageFrame2.size.height +
-        extension_installed_bubble::kInnerVerticalMargin);
-  } else {
-    extensionMessageFrame2.origin.y = extensionMessageFrame1.origin.y - (
-        extensionMessageFrame2.size.height +
-        extension_installed_bubble::kInnerVerticalMargin);
-  }
-  [extensionInstalledInfoMsg_ setFrame:extensionMessageFrame2];
-}
-
-// Exposed for unit testing.
-- (NSRect)getExtensionInstalledMsgFrame {
-  return [extensionInstalledMsg_ frame];
-}
-
-- (NSRect)getExtraInfoMsgFrame {
-  return [extraInfoMsg_ frame];
-}
-
-- (NSRect)getExtensionInstalledInfoMsgFrame {
-  return [extensionInstalledInfoMsg_ frame];
-}
-
-- (void)extensionUnloaded:(id)sender {
-  extension_ = NULL;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/extension_installed_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/extension_installed_bubble_controller_unittest.mm
deleted file mode 100644
index f1171d1..0000000
--- a/chrome/browser/ui/cocoa/extension_installed_bubble_controller_unittest.mm
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/basictypes.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/scoped_ptr.h"
-#include "base/values.h"
-#import "chrome/browser/browser_window.h"
-#import "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/extension_installed_bubble_controller.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "webkit/glue/image_decoder.h"
-
-// ExtensionInstalledBubbleController with removePageActionPreview overridden
-// to a no-op, because pageActions are not yet hooked up in the test browser.
-@interface ExtensionInstalledBubbleControllerForTest :
-    ExtensionInstalledBubbleController {
-}
-
-// Do nothing, because browser window is not set up with page actions
-// for unit testing.
-- (void)removePageActionPreview;
-
-@end
-
-@implementation ExtensionInstalledBubbleControllerForTest
-
-- (void)removePageActionPreview { }
-
-@end
-
-namespace keys = extension_manifest_keys;
-
-class ExtensionInstalledBubbleControllerTest : public CocoaTest {
-
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    browser_ = helper_.browser();
-    window_ = helper_.CreateBrowserWindow()->GetNativeHandle();
-    icon_ = LoadTestIcon();
-  }
-
-  virtual void TearDown() {
-    helper_.CloseBrowserWindow();
-    CocoaTest::TearDown();
-  }
-
-  // Load test icon from extension test directory.
-  SkBitmap LoadTestIcon() {
-    FilePath path;
-    PathService::Get(chrome::DIR_TEST_DATA, &path);
-    path = path.AppendASCII("extensions").AppendASCII("icon1.png");
-
-    std::string file_contents;
-    file_util::ReadFileToString(path, &file_contents);
-    const unsigned char* data =
-        reinterpret_cast<const unsigned char*>(file_contents.data());
-
-    SkBitmap bitmap;
-    webkit_glue::ImageDecoder decoder;
-    bitmap = decoder.Decode(data, file_contents.length());
-
-    return bitmap;
-  }
-
-  // Create a skeletal framework of either page action or browser action
-  // type.  This extension only needs to have a type and a name to initialize
-  // the ExtensionInstalledBubble for unit testing.
-  scoped_refptr<Extension> CreateExtension(
-        extension_installed_bubble::ExtensionType type) {
-    FilePath path;
-    PathService::Get(chrome::DIR_TEST_DATA, &path);
-    path = path.AppendASCII("extensions").AppendASCII("dummy");
-
-    DictionaryValue extension_input_value;
-    extension_input_value.SetString(keys::kVersion, "1.0.0.0");
-    if (type == extension_installed_bubble::kPageAction) {
-      extension_input_value.SetString(keys::kName, "page action extension");
-      DictionaryValue* action = new DictionaryValue;
-      action->SetString(keys::kPageActionId, "ExtensionActionId");
-      action->SetString(keys::kPageActionDefaultTitle, "ExtensionActionTitle");
-      action->SetString(keys::kPageActionDefaultIcon, "image1.png");
-      ListValue* action_list = new ListValue;
-      action_list->Append(action);
-      extension_input_value.Set(keys::kPageActions, action_list);
-    } else {
-      extension_input_value.SetString(keys::kName, "browser action extension");
-      DictionaryValue* browser_action = new DictionaryValue;
-      // An empty dictionary is enough to create a Browser Action.
-      extension_input_value.Set(keys::kBrowserAction, browser_action);
-    }
-
-    std::string error;
-    return Extension::Create(
-        path, Extension::INVALID, extension_input_value, false, &error);
-  }
-
-  // Allows us to create the window and browser for testing.
-  BrowserTestHelper helper_;
-
-  // Required to initialize the extension installed bubble.
-  NSWindow* window_;  // weak, owned by BrowserTestHelper.
-
-  // Required to initialize the extension installed bubble.
-  Browser* browser_;  // weak, owned by BrowserTestHelper.
-
-  // Skeleton extension to be tested; reinitialized for each test.
-  scoped_refptr<Extension> extension_;
-
-  // The icon_ to be loaded into the bubble window.
-  SkBitmap icon_;
-};
-
-// Confirm that window sizes are set correctly for a page action extension.
-TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) {
-  extension_ = CreateExtension(extension_installed_bubble::kPageAction);
-  ExtensionInstalledBubbleControllerForTest* controller =
-      [[ExtensionInstalledBubbleControllerForTest alloc]
-          initWithParentWindow:window_
-                     extension:extension_.get()
-                       browser:browser_
-                          icon:icon_];
-  EXPECT_TRUE(controller);
-
-  // Initialize window without having to calculate tabstrip locations.
-  [controller initializeWindow];
-  EXPECT_TRUE([controller window]);
-
-  int height = [controller calculateWindowHeight];
-  // Height should equal the vertical padding + height of all messages.
-  int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
-      2 * extension_installed_bubble::kInnerVerticalMargin +
-      [controller getExtensionInstalledMsgFrame].size.height +
-      [controller getExtensionInstalledInfoMsgFrame].size.height +
-      [controller getExtraInfoMsgFrame].size.height;
-  EXPECT_EQ(height, correctHeight);
-
-  [controller setMessageFrames:height];
-  NSRect msg3Frame = [controller getExtensionInstalledInfoMsgFrame];
-  // Bottom message should be kOuterVerticalMargin pixels above window edge.
-  EXPECT_EQ(msg3Frame.origin.y,
-      extension_installed_bubble::kOuterVerticalMargin);
-  NSRect msg2Frame = [controller getExtraInfoMsgFrame];
-  // Pageaction message should be kInnerVerticalMargin pixels above bottom msg.
-  EXPECT_EQ(msg2Frame.origin.y,
-            msg3Frame.origin.y + msg3Frame.size.height +
-            extension_installed_bubble::kInnerVerticalMargin);
-  NSRect msg1Frame = [controller getExtensionInstalledMsgFrame];
-  // Top message should be kInnerVerticalMargin pixels above Pageaction msg.
-  EXPECT_EQ(msg1Frame.origin.y,
-            msg2Frame.origin.y + msg2Frame.size.height +
-            extension_installed_bubble::kInnerVerticalMargin);
-
-  [controller setPageActionRemoved:YES];
-  [controller close];
-}
-
-TEST_F(ExtensionInstalledBubbleControllerTest, BrowserActionTest) {
-  extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
-  ExtensionInstalledBubbleControllerForTest* controller =
-      [[ExtensionInstalledBubbleControllerForTest alloc]
-          initWithParentWindow:window_
-                     extension:extension_.get()
-                       browser:browser_
-                          icon:icon_];
-  EXPECT_TRUE(controller);
-
-  // Initialize window without having to calculate tabstrip locations.
-  [controller initializeWindow];
-  EXPECT_TRUE([controller window]);
-
-  int height = [controller calculateWindowHeight];
-  // Height should equal the vertical padding + height of all messages.
-  int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
-      extension_installed_bubble::kInnerVerticalMargin +
-      [controller getExtensionInstalledMsgFrame].size.height +
-      [controller getExtensionInstalledInfoMsgFrame].size.height;
-  EXPECT_EQ(height, correctHeight);
-
-  [controller setMessageFrames:height];
-  NSRect msg3Frame = [controller getExtensionInstalledInfoMsgFrame];
-  // Bottom message should start kOuterVerticalMargin pixels above window edge.
-  EXPECT_EQ(msg3Frame.origin.y,
-      extension_installed_bubble::kOuterVerticalMargin);
-  NSRect msg1Frame = [controller getExtensionInstalledMsgFrame];
-  // Top message should start kInnerVerticalMargin pixels above top of
-  //  extensionInstalled message, because page action message is hidden.
-  EXPECT_EQ(msg1Frame.origin.y,
-            msg3Frame.origin.y + msg3Frame.size.height +
-                extension_installed_bubble::kInnerVerticalMargin);
-
-  [controller close];
-}
diff --git a/chrome/browser/ui/cocoa/extension_view_mac.h b/chrome/browser/ui/cocoa/extension_view_mac.h
deleted file mode 100644
index 43e9058..0000000
--- a/chrome/browser/ui/cocoa/extension_view_mac.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_EXTENSION_VIEW_MAC_H_
-#define CHROME_BROWSER_UI_COCOA_EXTENSION_VIEW_MAC_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/size.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-class Browser;
-class ExtensionHost;
-class RenderViewHost;
-class RenderWidgetHostViewMac;
-class SkBitmap;
-
-// This class represents extension views. An extension view internally contains
-// a bridge to an extension process, which draws to the extension view's
-// native view object through IPC.
-class ExtensionViewMac {
- public:
-  ExtensionViewMac(ExtensionHost* extension_host, Browser* browser);
-  ~ExtensionViewMac();
-
-  // Starts the extension process and creates the native view. You must call
-  // this method before calling any of this class's other methods.
-  void Init();
-
-  // Returns the extension's native view.
-  gfx::NativeView native_view();
-
-  // Returns the browser the extension belongs to.
-  Browser* browser() const { return browser_; }
-
-  // Does this extension live as a toolstrip in an extension shelf?
-  bool is_toolstrip() const { return is_toolstrip_; }
-  void set_is_toolstrip(bool is_toolstrip) { is_toolstrip_ = is_toolstrip; }
-
-  // Sets the extensions's background image.
-  void SetBackground(const SkBitmap& background);
-
-  // Method for the ExtensionHost to notify us about the correct size for
-  // extension contents.
-  void UpdatePreferredSize(const gfx::Size& new_size);
-
-  // Method for the ExtensionHost to notify us when the RenderViewHost has a
-  // connection.
-  void RenderViewCreated();
-
-  // Informs the view that its containing window's frame changed.
-  void WindowFrameChanged();
-
-  // The minimum/maximum dimensions of the popup.
-  // The minimum is just a little larger than the size of the button itself.
-  // The maximum is an arbitrary number that should be smaller than most
-  // screens.
-  static const CGFloat kMinWidth;
-  static const CGFloat kMinHeight;
-  static const CGFloat kMaxWidth;
-  static const CGFloat kMaxHeight;
-
- private:
-  RenderViewHost* render_view_host() const;
-
-  void CreateWidgetHostView();
-
-  // True if the contents are being displayed inside the extension shelf.
-  bool is_toolstrip_;
-
-  Browser* browser_;  // weak
-
-  ExtensionHost* extension_host_;  // weak
-
-  // Created by us, but owned by its |native_view()|. We |release| the
-  // rwhv's native view in our destructor, effectively freeing this.
-  RenderWidgetHostViewMac* render_widget_host_view_;
-
-  // The background the view should have once it is initialized. This is set
-  // when the view has a custom background, but hasn't been initialized yet.
-  SkBitmap pending_background_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionViewMac);
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_EXTENSION_VIEW_MAC_H_
diff --git a/chrome/browser/ui/cocoa/extension_view_mac.mm b/chrome/browser/ui/cocoa/extension_view_mac.mm
deleted file mode 100644
index d3a10e7..0000000
--- a/chrome/browser/ui/cocoa/extension_view_mac.mm
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/extension_view_mac.h"
-
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
-
-// The minimum/maximum dimensions of the popup.
-const CGFloat ExtensionViewMac::kMinWidth = 25.0;
-const CGFloat ExtensionViewMac::kMinHeight = 25.0;
-const CGFloat ExtensionViewMac::kMaxWidth = 800.0;
-const CGFloat ExtensionViewMac::kMaxHeight = 600.0;
-
-ExtensionViewMac::ExtensionViewMac(ExtensionHost* extension_host,
-                                   Browser* browser)
-    : is_toolstrip_(true),
-      browser_(browser),
-      extension_host_(extension_host),
-      render_widget_host_view_(NULL) {
-  DCHECK(extension_host_);
-}
-
-ExtensionViewMac::~ExtensionViewMac() {
-  if (render_widget_host_view_)
-    [render_widget_host_view_->native_view() release];
-}
-
-void ExtensionViewMac::Init() {
-  CreateWidgetHostView();
-}
-
-gfx::NativeView ExtensionViewMac::native_view() {
-  DCHECK(render_widget_host_view_);
-  return render_widget_host_view_->native_view();
-}
-
-RenderViewHost* ExtensionViewMac::render_view_host() const {
-  return extension_host_->render_view_host();
-}
-
-void ExtensionViewMac::SetBackground(const SkBitmap& background) {
-  DCHECK(render_widget_host_view_);
-  if (render_view_host()->IsRenderViewLive()) {
-    render_widget_host_view_->SetBackground(background);
-  } else {
-    pending_background_ = background;
-  }
-}
-
-void ExtensionViewMac::UpdatePreferredSize(const gfx::Size& new_size) {
-  // TODO(thakis, erikkay): Windows does some tricks to resize the extension
-  // view not before it's visible. Do something similar here.
-
-  // No need to use CA here, our caller calls us repeatedly to animate the
-  // resizing.
-  NSView* view = native_view();
-  NSRect frame = [view frame];
-  frame.size.width = new_size.width();
-  frame.size.height = new_size.height();
-
-  // On first display of some extensions, this function is called with zero
-  // width after the correct size has been set. Bail if zero is seen, assuming
-  // that an extension's view doesn't want any dimensions to ever be zero.
-  // TODO(andybons): Verify this assumption and look into WebCore's
-  // |contentesPreferredWidth| to see why this is occurring.
-  if (NSIsEmptyRect(frame))
-    return;
-
-  DCHECK([view isKindOfClass:[RenderWidgetHostViewCocoa class]]);
-  RenderWidgetHostViewCocoa* hostView = (RenderWidgetHostViewCocoa*)view;
-
-  // RenderWidgetHostViewCocoa overrides setFrame but not setFrameSize.
-  // We need to defer the update back to the RenderWidgetHost so we don't
-  // get the flickering effect on 10.5 of http://crbug.com/31970
-  [hostView setFrameWithDeferredUpdate:frame];
-  [hostView setNeedsDisplay:YES];
-}
-
-void ExtensionViewMac::RenderViewCreated() {
-  // Do not allow webkit to draw scroll bars on views smaller than
-  // the largest size view allowed.  The view will be resized to make
-  // scroll bars unnecessary.  Scroll bars change the height of the
-  // view, so not drawing them is necessary to avoid infinite resizing.
-  gfx::Size largest_popup_size(
-      CGSizeMake(ExtensionViewMac::kMaxWidth, ExtensionViewMac::kMaxHeight));
-  extension_host_->DisableScrollbarsForSmallWindows(largest_popup_size);
-
-  if (!pending_background_.empty() && render_view_host()->view()) {
-    render_widget_host_view_->SetBackground(pending_background_);
-    pending_background_.reset();
-  }
-}
-
-void ExtensionViewMac::WindowFrameChanged() {
-  if (render_widget_host_view_)
-    render_widget_host_view_->WindowFrameChanged();
-}
-
-void ExtensionViewMac::CreateWidgetHostView() {
-  DCHECK(!render_widget_host_view_);
-  render_widget_host_view_ = new RenderWidgetHostViewMac(render_view_host());
-
-  // The RenderWidgetHostViewMac is owned by its native view, which is created
-  // in an autoreleased state. retain it, so that it doesn't immediately
-  // disappear.
-  [render_widget_host_view_->native_view() retain];
-
-  extension_host_->CreateRenderViewSoon(render_widget_host_view_);
-}
diff --git a/chrome/browser/ui/cocoa/extensions/OWNERS b/chrome/browser/ui/cocoa/extensions/OWNERS
new file mode 100644
index 0000000..3afc873
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/OWNERS
@@ -0,0 +1 @@
+andybons@chromium.org
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
index 14701c8..6023a41 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
@@ -19,11 +19,11 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 NSString* const kBrowserActionButtonUpdatedNotification =
     @"BrowserActionButtonUpdatedNotification";
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
index 0e68252..e0d0a09 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
@@ -360,7 +360,7 @@
     // Migration code to the new VisibleIconCount pref.
     // TODO(mpcomplete): remove this at some point.
     double predefinedWidth =
-        profile_->GetPrefs()->GetReal(prefs::kBrowserActionContainerWidth);
+        profile_->GetPrefs()->GetDouble(prefs::kBrowserActionContainerWidth);
     if (predefinedWidth != 0) {
       int iconWidth = kBrowserActionWidth + kBrowserActionButtonPadding;
       int extraWidth = kChevronWidth;
@@ -419,7 +419,7 @@
 }
 
 + (void)registerUserPrefs:(PrefService*)prefs {
-  prefs->RegisterRealPref(prefs::kBrowserActionContainerWidth, 0);
+  prefs->RegisterDoublePref(prefs::kBrowserActionContainerWidth, 0);
 }
 
 #pragma mark -
@@ -741,7 +741,8 @@
                         arrowLocation:info_bubble::kTopRight
                               devMode:NO];
   } else {
-    ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
+    ExtensionService* service = profile_->GetExtensionService();
+    service->browser_event_router()->BrowserActionExecuted(
        profile_, action->extension_id(), browser_);
   }
 }
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
index e40388f..9af03e1 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
@@ -21,6 +21,7 @@
 namespace extension_action_context_menu {
 
 class DevmodeObserver;
+class ProfileObserverBridge;
 
 }  // namespace extension_action_context_menu
 
@@ -42,6 +43,10 @@
   // The observer used to listen for pref changed notifications.
   scoped_ptr<extension_action_context_menu::DevmodeObserver> observer_;
 
+  // The observer used to reset |observer_| when the profile is destroyed.
+  scoped_ptr<extension_action_context_menu::ProfileObserverBridge>
+      profile_observer_;
+
   // Used to load the extension icon asynchronously on the I/O thread then show
   // the uninstall confirmation dialog.
   scoped_ptr<AsyncUninstaller> uninstaller_;
@@ -55,6 +60,10 @@
 // Show or hide the inspector menu item.
 - (void)updateInspectorItem;
 
+// Notifies the ExtensionActionContextMenu that the profile is is being
+// destroyed.
+- (void)invalidateProfile;
+
 @end
 
 typedef ExtensionActionContextMenu ExtensionActionContextMenuMac;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm
index 5317f17..b8475ea 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/sys_string_conversions.h"
 #include "base/task.h"
 #include "chrome/browser/browser_list.h"
@@ -20,16 +19,18 @@
 #include "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
 #include "chrome/browser/ui/cocoa/info_bubble_view.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#include "chrome/browser/ui/cocoa/toolbar_controller.h"
+#include "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 // A class that loads the extension icon on the I/O thread before showing the
 // confirmation dialog to uninstall the given extension.
@@ -92,6 +93,34 @@
   PrefChangeRegistrar registrar_;
 };
 
+class ProfileObserverBridge : public NotificationObserver {
+ public:
+  ProfileObserverBridge(ExtensionActionContextMenu* owner,
+                        const Profile* profile)
+      : owner_(owner),
+        profile_(profile) {
+    registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
+                   Source<Profile>(profile));
+  }
+
+  ~ProfileObserverBridge() {}
+
+  // Overridden from NotificationObserver
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    if (type == NotificationType::PROFILE_DESTROYED &&
+        source == Source<Profile>(profile_)) {
+      [owner_ invalidateProfile];
+    }
+  }
+
+ private:
+  ExtensionActionContextMenu* owner_;
+  const Profile* profile_;
+  NotificationRegistrar registrar_;
+};
+
 }  // namespace extension_action_context_menu
 
 @interface ExtensionActionContextMenu(Private)
@@ -177,6 +206,9 @@
     PrefService* service = profile_->GetPrefs();
     observer_.reset(
         new extension_action_context_menu::DevmodeObserver(self, service));
+    profile_observer_.reset(
+        new extension_action_context_menu::ProfileObserverBridge(self,
+                                                                 profile));
 
     [self updateInspectorItem];
     return self;
@@ -275,4 +307,9 @@
   return YES;
 }
 
+- (void)invalidateProfile {
+  observer_.reset();
+  profile_ = NULL;
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.h b/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.h
index b2c9a8e..d160782 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INFOBAR_CONTROLLER_H_
 #pragma once
 
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
 
 #import <Cocoa/Cocoa.h>
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.mm
index 833b1a7..c018dff 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_infobar_controller.mm
@@ -6,20 +6,20 @@
 
 #include <cmath>
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #import "chrome/browser/ui/cocoa/animatable_view.h"
 #import "chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h"
 #import "chrome/browser/ui/cocoa/menu_button.h"
-#include "chrome/browser/ui/cocoa/infobar.h"
+#include "chrome/browser/ui/cocoa/infobars/infobar.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/extension_resource.h"
-#include "gfx/canvas_skia.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 
 namespace {
 const CGFloat kAnimationDuration = 0.12;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_prompt.mm b/chrome/browser/ui/cocoa/extensions/extension_install_prompt.mm
new file mode 100644
index 0000000..5d607d2
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_prompt.mm
@@ -0,0 +1,51 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include <string>
+
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+class Profile;
+
+void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl(
+    Profile* profile,
+    Delegate* delegate,
+    const Extension* extension,
+    SkBitmap* icon,
+    ExtensionInstallUI::PromptType type) {
+  NSAlert* alert = [[[NSAlert alloc] init] autorelease];
+
+  NSButton* continueButton = [alert addButtonWithTitle:l10n_util::GetNSString(
+      ExtensionInstallUI::kButtonIds[type])];
+  // Clear the key equivalent (currently 'Return') because cancel is the default
+  // button.
+  [continueButton setKeyEquivalent:@""];
+
+  NSButton* cancelButton = [alert addButtonWithTitle:l10n_util::GetNSString(
+      IDS_CANCEL)];
+  [cancelButton setKeyEquivalent:@"\r"];
+
+  [alert setMessageText:l10n_util::GetNSStringF(
+       ExtensionInstallUI::kHeadingIds[type],
+       UTF8ToUTF16(extension->name()))];
+  [alert setAlertStyle:NSWarningAlertStyle];
+  [alert setIcon:gfx::SkBitmapToNSImage(*icon)];
+
+  if ([alert runModal] == NSAlertFirstButtonReturn) {
+    delegate->InstallUIProceed();
+  } else {
+    delegate->InstallUIAbort();
+  }
+}
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.h
index 6ae5884..c24878d 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.h
@@ -39,13 +39,13 @@
   SkBitmap icon_;
 }
 
-@property (nonatomic, readonly) NSImageView* iconView;
-@property (nonatomic, readonly) NSTextField* titleField;
-@property (nonatomic, readonly) NSTextField* subtitleField;
-@property (nonatomic, readonly) NSTextField* warningsField;
-@property (nonatomic, readonly) NSBox* warningsBox;
-@property (nonatomic, readonly) NSButton* cancelButton;
-@property (nonatomic, readonly) NSButton* okButton;
+@property(nonatomic, readonly) NSImageView* iconView;
+@property(nonatomic, readonly) NSTextField* titleField;
+@property(nonatomic, readonly) NSTextField* subtitleField;
+@property(nonatomic, readonly) NSTextField* warningsField;
+@property(nonatomic, readonly) NSBox* warningsBox;
+@property(nonatomic, readonly) NSButton* cancelButton;
+@property(nonatomic, readonly) NSButton* okButton;
 
 - (id)initWithParentWindow:(NSWindow*)window
                    profile:(Profile*)profile
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.mm
index 09dc927..6a8fb2b 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.mm
@@ -4,8 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/mac/mac_util.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
@@ -16,6 +14,8 @@
 #include "chrome/common/extensions/extension.h"
 #include "grit/generated_resources.h"
 #include "skia/ext/skia_utils_mac.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_bridge.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_bridge.mm
new file mode 100644
index 0000000..bd93bd2
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_bridge.mm
@@ -0,0 +1,68 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/i18n/rtl.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_action.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// When an extension is installed on Mac with neither browser action nor
+// page action icons, show an infobar instead of a popup bubble.
+static void ShowGenericExtensionInstalledInfoBar(
+    const Extension* new_extension,
+    SkBitmap icon,
+    Profile* profile) {
+  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
+  if (!browser)
+    return;
+
+  TabContents* tab_contents = browser->GetSelectedTabContents();
+  if (!tab_contents)
+    return;
+
+  string16 extension_name = UTF8ToUTF16(new_extension->name());
+  base::i18n::AdjustStringForLocaleDirection(&extension_name);
+  string16 msg =
+      l10n_util::GetStringFUTF16(IDS_EXTENSION_INSTALLED_HEADING,
+                                 extension_name) +
+      UTF8ToUTF16(" ") +
+      l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALLED_MANAGE_INFO_MAC);
+  InfoBarDelegate* delegate = new SimpleAlertInfoBarDelegate(tab_contents,
+      new SkBitmap(icon), msg, true);
+  tab_contents->AddInfoBar(delegate);
+}
+
+namespace browser {
+
+void ShowExtensionInstalledBubble(
+    const Extension* extension,
+    Browser* browser,
+    SkBitmap icon,
+    Profile* profile) {
+  if ((extension->browser_action()) || !extension->omnibox_keyword().empty() ||
+      (extension->page_action() &&
+      !extension->page_action()->default_icon_path().empty())) {
+    // The controller is deallocated when the window is closed, so no need to
+    // worry about it here.
+    [[ExtensionInstalledBubbleController alloc]
+        initWithParentWindow:browser->window()->GetNativeHandle()
+                   extension:extension
+                     browser:browser
+                        icon:icon];
+  } else {
+    // If the extension is of type GENERIC, meaning it doesn't have a UI
+    // surface to display for this window, launch infobar instead of popup
+    // bubble, because we have no guaranteed wrench menu button to point to.
+    ShowGenericExtensionInstalledInfoBar(extension, icon, profile);
+  }
+}
+
+} // namespace browser
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h
new file mode 100644
index 0000000..ad95fba
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_ptr.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+class Browser;
+class Extension;
+class ExtensionLoadedNotificationObserver;
+@class HoverCloseButton;
+@class InfoBubbleView;
+
+namespace extension_installed_bubble {
+
+// Maximum height or width of extension's icon (corresponds to Windows & GTK).
+const int kIconSize = 43;
+
+// Outer vertical margin for text, icon, and closing x.
+const int kOuterVerticalMargin = 15;
+
+// Inner vertical margin for text messages.
+const int kInnerVerticalMargin = 10;
+
+// We use a different kind of notification for each of these extension types.
+typedef enum {
+  kBrowserAction,
+  kGeneric,
+  kOmniboxKeyword,
+  kPageAction
+} ExtensionType;
+
+}
+
+// Controller for the extension installed bubble.  This bubble pops up after
+// an extension has been installed to inform the user that the install happened
+// properly, and to let the user know how to manage this extension in the
+// future.
+@interface ExtensionInstalledBubbleController :
+    NSWindowController<NSWindowDelegate> {
+ @private
+  NSWindow* parentWindow_;  // weak
+  const Extension* extension_;  // weak
+  Browser* browser_;  // weak
+  scoped_nsobject<NSImage> icon_;
+
+  extension_installed_bubble::ExtensionType type_;
+
+  // We need to remove the page action immediately when the browser window
+  // closes while this bubble is still open, so the bubble's closing animation
+  // doesn't overlap browser destruction.
+  BOOL pageActionRemoved_;
+
+  // Lets us register for EXTENSION_LOADED notifications.  The actual
+  // notifications are sent to the observer object, which proxies them
+  // back to the controller.
+  scoped_ptr<ExtensionLoadedNotificationObserver> extensionObserver_;
+
+  // References below are weak, being obtained from the nib.
+  IBOutlet InfoBubbleView* infoBubbleView_;
+  IBOutlet HoverCloseButton* closeButton_;
+  IBOutlet NSImageView* iconImage_;
+  IBOutlet NSTextField* extensionInstalledMsg_;
+  // Only shown for page actions and omnibox keywords.
+  IBOutlet NSTextField* extraInfoMsg_;
+  IBOutlet NSTextField* extensionInstalledInfoMsg_;
+}
+
+@property(nonatomic, readonly) const Extension* extension;
+@property(nonatomic) BOOL pageActionRemoved;
+
+// Initialize the window, and then create observers to wait for the extension
+// to complete loading, or the browser window to close.
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+                 extension:(const Extension*)extension
+                   browser:(Browser*)browser
+                      icon:(SkBitmap)icon;
+
+// Action for close button.
+- (IBAction)closeWindow:(id)sender;
+
+// Displays the extension installed bubble. This callback is triggered by
+// the extensionObserver when the extension has completed loading.
+- (void)showWindow:(id)sender;
+
+// Clears our weak pointer to the Extension. This callback is triggered by
+// the extensionObserver when the extension is unloaded.
+- (void)extensionUnloaded:(id)sender;
+
+@end
+
+@interface ExtensionInstalledBubbleController(ExposedForTesting)
+
+- (void)removePageActionPreviewIfNecessary;
+- (NSWindow*)initializeWindow;
+- (int)calculateWindowHeight;
+- (void)setMessageFrames:(int)newWindowHeight;
+- (NSRect)getExtensionInstalledMsgFrame;
+- (NSRect)getExtraInfoMsgFrame;
+- (NSRect)getExtensionInstalledInfoMsgFrame;
+
+@end  // ExtensionInstalledBubbleController(ExposedForTesting)
+
+#endif  // CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
new file mode 100644
index 0000000..ec558f2
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
@@ -0,0 +1,378 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
+
+#include "base/i18n/rtl.h"
+#include "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
+#include "chrome/browser/ui/cocoa/browser_window_controller.h"
+#include "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
+#include "chrome/browser/ui/cocoa/hover_close_button.h"
+#include "chrome/browser/ui/cocoa/info_bubble_view.h"
+#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
+#include "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "grit/generated_resources.h"
+#import "skia/ext/skia_utils_mac.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
+
+
+// C++ class that receives EXTENSION_LOADED notifications and proxies them back
+// to |controller|.
+class ExtensionLoadedNotificationObserver : public NotificationObserver {
+ public:
+  ExtensionLoadedNotificationObserver(
+      ExtensionInstalledBubbleController* controller, Profile* profile)
+          : controller_(controller) {
+    registrar_.Add(this, NotificationType::EXTENSION_LOADED,
+        Source<Profile>(profile));
+    registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+        Source<Profile>(profile));
+  }
+
+ private:
+  // NotificationObserver implementation. Tells the controller to start showing
+  // its window on the main thread when the extension has finished loading.
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    if (type == NotificationType::EXTENSION_LOADED) {
+      const Extension* extension = Details<const Extension>(details).ptr();
+      if (extension == [controller_ extension]) {
+        [controller_ performSelectorOnMainThread:@selector(showWindow:)
+                                      withObject:controller_
+                                   waitUntilDone:NO];
+      }
+    } else if (type == NotificationType::EXTENSION_UNLOADED) {
+      const Extension* extension = Details<const Extension>(details).ptr();
+      if (extension == [controller_ extension]) {
+        [controller_ performSelectorOnMainThread:@selector(extensionUnloaded:)
+                                      withObject:controller_
+                                   waitUntilDone:NO];
+      }
+    } else {
+      NOTREACHED() << "Received unexpected notification.";
+    }
+  }
+
+  NotificationRegistrar registrar_;
+  ExtensionInstalledBubbleController* controller_;  // weak, owns us
+};
+
+@implementation ExtensionInstalledBubbleController
+
+@synthesize extension = extension_;
+@synthesize pageActionRemoved = pageActionRemoved_;  // Exposed for unit test.
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+                 extension:(const Extension*)extension
+                   browser:(Browser*)browser
+                      icon:(SkBitmap)icon {
+  NSString* nibPath =
+      [base::mac::MainAppBundle() pathForResource:@"ExtensionInstalledBubble"
+                                          ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
+    DCHECK(parentWindow);
+    parentWindow_ = parentWindow;
+    DCHECK(extension);
+    extension_ = extension;
+    DCHECK(browser);
+    browser_ = browser;
+    icon_.reset([gfx::SkBitmapToNSImage(icon) retain]);
+    pageActionRemoved_ = NO;
+
+    if (!extension->omnibox_keyword().empty()) {
+      type_ = extension_installed_bubble::kOmniboxKeyword;
+    } else if (extension->browser_action()) {
+      type_ = extension_installed_bubble::kBrowserAction;
+    } else if (extension->page_action() &&
+               !extension->page_action()->default_icon_path().empty()) {
+      type_ = extension_installed_bubble::kPageAction;
+    } else {
+      NOTREACHED();  // kGeneric installs handled in the extension_install_ui.
+    }
+
+    // Start showing window only after extension has fully loaded.
+    extensionObserver_.reset(new ExtensionLoadedNotificationObserver(
+        self, browser->profile()));
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
+- (void)close {
+  [parentWindow_ removeChildWindow:[self window]];
+  [super close];
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+  // Turn off page action icon preview when the window closes, unless we
+  // already removed it when the window resigned key status.
+  [self removePageActionPreviewIfNecessary];
+  extension_ = NULL;
+  browser_ = NULL;
+  parentWindow_ = nil;
+  // We caught a close so we don't need to watch for the parent closing.
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [self autorelease];
+}
+
+// The controller is the delegate of the window, so it receives "did resign
+// key" notifications.  When key is resigned, close the window.
+- (void)windowDidResignKey:(NSNotification*)notification {
+  NSWindow* window = [self window];
+  DCHECK_EQ([notification object], window);
+  DCHECK([window isVisible]);
+
+  // If the browser window is closing, we need to remove the page action
+  // immediately, otherwise the closing animation may overlap with
+  // browser destruction.
+  [self removePageActionPreviewIfNecessary];
+  [self close];
+}
+
+- (IBAction)closeWindow:(id)sender {
+  DCHECK([[self window] isVisible]);
+  [self close];
+}
+
+// Extracted to a function here so that it can be overwritten for unit
+// testing.
+- (void)removePageActionPreviewIfNecessary {
+  if (!extension_ || !extension_->page_action() || pageActionRemoved_)
+    return;
+  pageActionRemoved_ = YES;
+
+  BrowserWindowCocoa* window =
+      static_cast<BrowserWindowCocoa*>(browser_->window());
+  LocationBarViewMac* locationBarView =
+      [window->cocoa_controller() locationBarBridge];
+  locationBarView->SetPreviewEnabledPageAction(extension_->page_action(),
+                                               false);  // disables preview.
+}
+
+// The extension installed bubble points at the browser action icon or the
+// page action icon (shown as a preview), depending on the extension type.
+// We need to calculate the location of these icons and the size of the
+// message itself (which varies with the title of the extension) in order
+// to figure out the origin point for the extension installed bubble.
+// TODO(mirandac): add framework to easily test extension UI components!
+- (NSPoint)calculateArrowPoint {
+  BrowserWindowCocoa* window =
+      static_cast<BrowserWindowCocoa*>(browser_->window());
+  NSPoint arrowPoint = NSZeroPoint;
+
+  switch(type_) {
+    case extension_installed_bubble::kOmniboxKeyword: {
+      LocationBarViewMac* locationBarView =
+          [window->cocoa_controller() locationBarBridge];
+      arrowPoint = locationBarView->GetPageInfoBubblePoint();
+      break;
+    }
+    case extension_installed_bubble::kBrowserAction: {
+      BrowserActionsController* controller =
+          [[window->cocoa_controller() toolbarController]
+              browserActionsController];
+      arrowPoint = [controller popupPointForBrowserAction:extension_];
+      break;
+    }
+    case extension_installed_bubble::kPageAction: {
+      LocationBarViewMac* locationBarView =
+          [window->cocoa_controller() locationBarBridge];
+
+      // Tell the location bar to show a preview of the page action icon, which
+      // would ordinarily only be displayed on a page of the appropriate type.
+      // We remove this preview when the extension installed bubble closes.
+      locationBarView->SetPreviewEnabledPageAction(extension_->page_action(),
+                                                   true);
+
+      // Find the center of the bottom of the page action icon.
+      arrowPoint =
+          locationBarView->GetPageActionBubblePoint(extension_->page_action());
+      break;
+    }
+    default: {
+      NOTREACHED() << "Generic extension type not allowed in install bubble.";
+    }
+  }
+  return arrowPoint;
+}
+
+// We want this to be a child of a browser window.  addChildWindow:
+// (called from this function) will bring the window on-screen;
+// unfortunately, [NSWindowController showWindow:] will also bring it
+// on-screen (but will cause unexpected changes to the window's
+// position).  We cannot have an addChildWindow: and a subsequent
+// showWindow:. Thus, we have our own version.
+- (void)showWindow:(id)sender {
+  // Generic extensions get an infobar rather than a bubble.
+  DCHECK(type_ != extension_installed_bubble::kGeneric);
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // Load nib and calculate height based on messages to be shown.
+  NSWindow* window = [self initializeWindow];
+  int newWindowHeight = [self calculateWindowHeight];
+  [infoBubbleView_ setFrameSize:NSMakeSize(
+      NSWidth([[window contentView] bounds]), newWindowHeight)];
+  NSSize windowDelta = NSMakeSize(
+      0, newWindowHeight - NSHeight([[window contentView] bounds]));
+  windowDelta = [[window contentView] convertSize:windowDelta toView:nil];
+  NSRect newFrame = [window frame];
+  newFrame.size.height += windowDelta.height;
+  [window setFrame:newFrame display:NO];
+
+  // Now that we have resized the window, adjust y pos of the messages.
+  [self setMessageFrames:newWindowHeight];
+
+  // Find window origin, taking into account bubble size and arrow location.
+  NSPoint origin =
+      [parentWindow_ convertBaseToScreen:[self calculateArrowPoint]];
+  NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset +
+                              info_bubble::kBubbleArrowWidth / 2.0, 0);
+  offsets = [[window contentView] convertSize:offsets toView:nil];
+  if ([infoBubbleView_ arrowLocation] == info_bubble::kTopRight)
+    origin.x -= NSWidth([window frame]) - offsets.width;
+  origin.y -= NSHeight([window frame]);
+  [window setFrameOrigin:origin];
+
+  [parentWindow_ addChildWindow:window
+                        ordered:NSWindowAbove];
+  [window makeKeyAndOrderFront:self];
+}
+
+// Finish nib loading, set arrow location and load icon into window.  This
+// function is exposed for unit testing.
+- (NSWindow*)initializeWindow {
+  NSWindow* window = [self window];  // completes nib load
+
+  if (type_ == extension_installed_bubble::kOmniboxKeyword) {
+    [infoBubbleView_ setArrowLocation:info_bubble::kTopLeft];
+  } else {
+    [infoBubbleView_ setArrowLocation:info_bubble::kTopRight];
+  }
+
+  // Set appropriate icon, resizing if necessary.
+  if ([icon_ size].width > extension_installed_bubble::kIconSize) {
+    [icon_ setSize:NSMakeSize(extension_installed_bubble::kIconSize,
+                              extension_installed_bubble::kIconSize)];
+  }
+  [iconImage_ setImage:icon_];
+  [iconImage_ setNeedsDisplay:YES];
+  return window;
+ }
+
+// Calculate the height of each install message, resizing messages in their
+// frames to fit window width.  Return the new window height, based on the
+// total of all message heights.
+- (int)calculateWindowHeight {
+  // Adjust the window height to reflect the sum height of all messages
+  // and vertical padding.
+  int newWindowHeight = 2 * extension_installed_bubble::kOuterVerticalMargin;
+
+  // First part of extension installed message.
+  string16 extension_name = UTF8ToUTF16(extension_->name().c_str());
+  base::i18n::AdjustStringForLocaleDirection(&extension_name);
+  [extensionInstalledMsg_ setStringValue:l10n_util::GetNSStringF(
+      IDS_EXTENSION_INSTALLED_HEADING, extension_name)];
+  [GTMUILocalizerAndLayoutTweaker
+      sizeToFitFixedWidthTextField:extensionInstalledMsg_];
+  newWindowHeight += [extensionInstalledMsg_ frame].size.height +
+      extension_installed_bubble::kInnerVerticalMargin;
+
+  // If type is page action, include a special message about page actions.
+  if (type_ == extension_installed_bubble::kPageAction) {
+    [extraInfoMsg_ setHidden:NO];
+    [[extraInfoMsg_ cell]
+        setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+    [GTMUILocalizerAndLayoutTweaker
+        sizeToFitFixedWidthTextField:extraInfoMsg_];
+    newWindowHeight += [extraInfoMsg_ frame].size.height +
+        extension_installed_bubble::kInnerVerticalMargin;
+  }
+
+  // If type is omnibox keyword, include a special message about the keyword.
+  if (type_ == extension_installed_bubble::kOmniboxKeyword) {
+    [extraInfoMsg_ setStringValue:l10n_util::GetNSStringF(
+        IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
+        UTF8ToUTF16(extension_->omnibox_keyword()))];
+    [extraInfoMsg_ setHidden:NO];
+    [[extraInfoMsg_ cell]
+        setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+    [GTMUILocalizerAndLayoutTweaker
+        sizeToFitFixedWidthTextField:extraInfoMsg_];
+    newWindowHeight += [extraInfoMsg_ frame].size.height +
+        extension_installed_bubble::kInnerVerticalMargin;
+  }
+
+  // Second part of extension installed message.
+  [[extensionInstalledInfoMsg_ cell]
+      setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+  [GTMUILocalizerAndLayoutTweaker
+      sizeToFitFixedWidthTextField:extensionInstalledInfoMsg_];
+  newWindowHeight += [extensionInstalledInfoMsg_ frame].size.height;
+
+  return newWindowHeight;
+}
+
+// Adjust y-position of messages to sit properly in new window height.
+- (void)setMessageFrames:(int)newWindowHeight {
+  // The extension messages will always be shown.
+  NSRect extensionMessageFrame1 = [extensionInstalledMsg_ frame];
+  NSRect extensionMessageFrame2 = [extensionInstalledInfoMsg_ frame];
+
+  extensionMessageFrame1.origin.y = newWindowHeight - (
+      extensionMessageFrame1.size.height +
+      extension_installed_bubble::kOuterVerticalMargin);
+  [extensionInstalledMsg_ setFrame:extensionMessageFrame1];
+  if (type_ == extension_installed_bubble::kPageAction ||
+      type_ == extension_installed_bubble::kOmniboxKeyword) {
+    // The extra message is only shown when appropriate.
+    NSRect extraMessageFrame = [extraInfoMsg_ frame];
+    extraMessageFrame.origin.y = extensionMessageFrame1.origin.y - (
+        extraMessageFrame.size.height +
+        extension_installed_bubble::kInnerVerticalMargin);
+    [extraInfoMsg_ setFrame:extraMessageFrame];
+    extensionMessageFrame2.origin.y = extraMessageFrame.origin.y - (
+        extensionMessageFrame2.size.height +
+        extension_installed_bubble::kInnerVerticalMargin);
+  } else {
+    extensionMessageFrame2.origin.y = extensionMessageFrame1.origin.y - (
+        extensionMessageFrame2.size.height +
+        extension_installed_bubble::kInnerVerticalMargin);
+  }
+  [extensionInstalledInfoMsg_ setFrame:extensionMessageFrame2];
+}
+
+// Exposed for unit testing.
+- (NSRect)getExtensionInstalledMsgFrame {
+  return [extensionInstalledMsg_ frame];
+}
+
+- (NSRect)getExtraInfoMsgFrame {
+  return [extraInfoMsg_ frame];
+}
+
+- (NSRect)getExtensionInstalledInfoMsgFrame {
+  return [extensionInstalledInfoMsg_ frame];
+}
+
+- (void)extensionUnloaded:(id)sender {
+  extension_ = NULL;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
new file mode 100644
index 0000000..1cafd26
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
@@ -0,0 +1,202 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#import "chrome/browser/browser_window.h"
+#import "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "webkit/glue/image_decoder.h"
+
+// ExtensionInstalledBubbleController with removePageActionPreview overridden
+// to a no-op, because pageActions are not yet hooked up in the test browser.
+@interface ExtensionInstalledBubbleControllerForTest :
+    ExtensionInstalledBubbleController {
+}
+
+// Do nothing, because browser window is not set up with page actions
+// for unit testing.
+- (void)removePageActionPreview;
+
+@end
+
+@implementation ExtensionInstalledBubbleControllerForTest
+
+- (void)removePageActionPreview { }
+
+@end
+
+namespace keys = extension_manifest_keys;
+
+class ExtensionInstalledBubbleControllerTest : public CocoaTest {
+
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    browser_ = helper_.browser();
+    window_ = helper_.CreateBrowserWindow()->GetNativeHandle();
+    icon_ = LoadTestIcon();
+  }
+
+  virtual void TearDown() {
+    helper_.CloseBrowserWindow();
+    CocoaTest::TearDown();
+  }
+
+  // Load test icon from extension test directory.
+  SkBitmap LoadTestIcon() {
+    FilePath path;
+    PathService::Get(chrome::DIR_TEST_DATA, &path);
+    path = path.AppendASCII("extensions").AppendASCII("icon1.png");
+
+    std::string file_contents;
+    file_util::ReadFileToString(path, &file_contents);
+    const unsigned char* data =
+        reinterpret_cast<const unsigned char*>(file_contents.data());
+
+    SkBitmap bitmap;
+    webkit_glue::ImageDecoder decoder;
+    bitmap = decoder.Decode(data, file_contents.length());
+
+    return bitmap;
+  }
+
+  // Create a skeletal framework of either page action or browser action
+  // type.  This extension only needs to have a type and a name to initialize
+  // the ExtensionInstalledBubble for unit testing.
+  scoped_refptr<Extension> CreateExtension(
+        extension_installed_bubble::ExtensionType type) {
+    FilePath path;
+    PathService::Get(chrome::DIR_TEST_DATA, &path);
+    path = path.AppendASCII("extensions").AppendASCII("dummy");
+
+    DictionaryValue extension_input_value;
+    extension_input_value.SetString(keys::kVersion, "1.0.0.0");
+    if (type == extension_installed_bubble::kPageAction) {
+      extension_input_value.SetString(keys::kName, "page action extension");
+      DictionaryValue* action = new DictionaryValue;
+      action->SetString(keys::kPageActionId, "ExtensionActionId");
+      action->SetString(keys::kPageActionDefaultTitle, "ExtensionActionTitle");
+      action->SetString(keys::kPageActionDefaultIcon, "image1.png");
+      ListValue* action_list = new ListValue;
+      action_list->Append(action);
+      extension_input_value.Set(keys::kPageActions, action_list);
+    } else {
+      extension_input_value.SetString(keys::kName, "browser action extension");
+      DictionaryValue* browser_action = new DictionaryValue;
+      // An empty dictionary is enough to create a Browser Action.
+      extension_input_value.Set(keys::kBrowserAction, browser_action);
+    }
+
+    std::string error;
+    return Extension::Create(
+        path, Extension::INVALID, extension_input_value, false, &error);
+  }
+
+  // Allows us to create the window and browser for testing.
+  BrowserTestHelper helper_;
+
+  // Required to initialize the extension installed bubble.
+  NSWindow* window_;  // weak, owned by BrowserTestHelper.
+
+  // Required to initialize the extension installed bubble.
+  Browser* browser_;  // weak, owned by BrowserTestHelper.
+
+  // Skeleton extension to be tested; reinitialized for each test.
+  scoped_refptr<Extension> extension_;
+
+  // The icon_ to be loaded into the bubble window.
+  SkBitmap icon_;
+};
+
+// Confirm that window sizes are set correctly for a page action extension.
+TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) {
+  extension_ = CreateExtension(extension_installed_bubble::kPageAction);
+  ExtensionInstalledBubbleControllerForTest* controller =
+      [[ExtensionInstalledBubbleControllerForTest alloc]
+          initWithParentWindow:window_
+                     extension:extension_.get()
+                       browser:browser_
+                          icon:icon_];
+  EXPECT_TRUE(controller);
+
+  // Initialize window without having to calculate tabstrip locations.
+  [controller initializeWindow];
+  EXPECT_TRUE([controller window]);
+
+  int height = [controller calculateWindowHeight];
+  // Height should equal the vertical padding + height of all messages.
+  int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
+      2 * extension_installed_bubble::kInnerVerticalMargin +
+      [controller getExtensionInstalledMsgFrame].size.height +
+      [controller getExtensionInstalledInfoMsgFrame].size.height +
+      [controller getExtraInfoMsgFrame].size.height;
+  EXPECT_EQ(height, correctHeight);
+
+  [controller setMessageFrames:height];
+  NSRect msg3Frame = [controller getExtensionInstalledInfoMsgFrame];
+  // Bottom message should be kOuterVerticalMargin pixels above window edge.
+  EXPECT_EQ(msg3Frame.origin.y,
+      extension_installed_bubble::kOuterVerticalMargin);
+  NSRect msg2Frame = [controller getExtraInfoMsgFrame];
+  // Pageaction message should be kInnerVerticalMargin pixels above bottom msg.
+  EXPECT_EQ(msg2Frame.origin.y,
+            msg3Frame.origin.y + msg3Frame.size.height +
+            extension_installed_bubble::kInnerVerticalMargin);
+  NSRect msg1Frame = [controller getExtensionInstalledMsgFrame];
+  // Top message should be kInnerVerticalMargin pixels above Pageaction msg.
+  EXPECT_EQ(msg1Frame.origin.y,
+            msg2Frame.origin.y + msg2Frame.size.height +
+            extension_installed_bubble::kInnerVerticalMargin);
+
+  [controller setPageActionRemoved:YES];
+  [controller close];
+}
+
+TEST_F(ExtensionInstalledBubbleControllerTest, BrowserActionTest) {
+  extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
+  ExtensionInstalledBubbleControllerForTest* controller =
+      [[ExtensionInstalledBubbleControllerForTest alloc]
+          initWithParentWindow:window_
+                     extension:extension_.get()
+                       browser:browser_
+                          icon:icon_];
+  EXPECT_TRUE(controller);
+
+  // Initialize window without having to calculate tabstrip locations.
+  [controller initializeWindow];
+  EXPECT_TRUE([controller window]);
+
+  int height = [controller calculateWindowHeight];
+  // Height should equal the vertical padding + height of all messages.
+  int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
+      extension_installed_bubble::kInnerVerticalMargin +
+      [controller getExtensionInstalledMsgFrame].size.height +
+      [controller getExtensionInstalledInfoMsgFrame].size.height;
+  EXPECT_EQ(height, correctHeight);
+
+  [controller setMessageFrames:height];
+  NSRect msg3Frame = [controller getExtensionInstalledInfoMsgFrame];
+  // Bottom message should start kOuterVerticalMargin pixels above window edge.
+  EXPECT_EQ(msg3Frame.origin.y,
+      extension_installed_bubble::kOuterVerticalMargin);
+  NSRect msg1Frame = [controller getExtensionInstalledMsgFrame];
+  // Top message should start kInnerVerticalMargin pixels above top of
+  //  extensionInstalled message, because page action message is hidden.
+  EXPECT_EQ(msg1Frame.origin.y,
+            msg3Frame.origin.y + msg3Frame.size.height +
+                extension_installed_bubble::kInnerVerticalMargin);
+
+  [controller close];
+}
diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
index 7404c3d..0a188ae 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
@@ -12,7 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #import "chrome/browser/ui/cocoa/browser_window_cocoa.h"
-#import "chrome/browser/ui/cocoa/extension_view_mac.h"
+#import "chrome/browser/ui/cocoa/extensions/extension_view_mac.h"
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_registrar.h"
diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm
index 992dd2c..a0b5614 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm
@@ -1,10 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/message_loop.h"
 #include "base/scoped_nsobject.h"
-#include "chrome/browser/extensions/extension_pref_store.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -28,10 +28,10 @@
     DCHECK(!GetExtensionService());
 
     manager_.reset(ExtensionProcessManager::Create(this));
-    ExtensionPrefStore* pref_store = new ExtensionPrefStore;
+    extension_pref_value_map_.reset(new ExtensionPrefValueMap);
     extension_prefs_.reset(new ExtensionPrefs(GetPrefs(),
                                               GetExtensionsInstallDir(),
-                                              pref_store));
+                                              extension_pref_value_map_.get()));
     service_ = new ExtensionService(this,
                                      CommandLine::ForCurrentProcess(),
                                      GetExtensionsInstallDir(),
@@ -61,6 +61,7 @@
   scoped_ptr<ExtensionProcessManager> manager_;
   scoped_ptr<ExtensionPrefs> extension_prefs_;
   scoped_refptr<ExtensionService> service_;
+  scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionTestingProfile);
 };
diff --git a/chrome/browser/ui/cocoa/extensions/extension_view_mac.h b/chrome/browser/ui/cocoa/extensions/extension_view_mac.h
new file mode 100644
index 0000000..bb87ebf
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_view_mac.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_VIEW_MAC_H_
+#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_VIEW_MAC_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+
+class Browser;
+class ExtensionHost;
+class RenderViewHost;
+class RenderWidgetHostViewMac;
+class SkBitmap;
+
+// This class represents extension views. An extension view internally contains
+// a bridge to an extension process, which draws to the extension view's
+// native view object through IPC.
+class ExtensionViewMac {
+ public:
+  ExtensionViewMac(ExtensionHost* extension_host, Browser* browser);
+  ~ExtensionViewMac();
+
+  // Starts the extension process and creates the native view. You must call
+  // this method before calling any of this class's other methods.
+  void Init();
+
+  // Returns the extension's native view.
+  gfx::NativeView native_view();
+
+  // Returns the browser the extension belongs to.
+  Browser* browser() const { return browser_; }
+
+  // Does this extension live as a toolstrip in an extension shelf?
+  bool is_toolstrip() const { return is_toolstrip_; }
+  void set_is_toolstrip(bool is_toolstrip) { is_toolstrip_ = is_toolstrip; }
+
+  // Sets the extensions's background image.
+  void SetBackground(const SkBitmap& background);
+
+  // Method for the ExtensionHost to notify us about the correct size for
+  // extension contents.
+  void UpdatePreferredSize(const gfx::Size& new_size);
+
+  // Method for the ExtensionHost to notify us when the RenderViewHost has a
+  // connection.
+  void RenderViewCreated();
+
+  // Informs the view that its containing window's frame changed.
+  void WindowFrameChanged();
+
+  // The minimum/maximum dimensions of the popup.
+  // The minimum is just a little larger than the size of the button itself.
+  // The maximum is an arbitrary number that should be smaller than most
+  // screens.
+  static const CGFloat kMinWidth;
+  static const CGFloat kMinHeight;
+  static const CGFloat kMaxWidth;
+  static const CGFloat kMaxHeight;
+
+ private:
+  RenderViewHost* render_view_host() const;
+
+  void CreateWidgetHostView();
+
+  // True if the contents are being displayed inside the extension shelf.
+  bool is_toolstrip_;
+
+  Browser* browser_;  // weak
+
+  ExtensionHost* extension_host_;  // weak
+
+  // Created by us, but owned by its |native_view()|. We |release| the
+  // rwhv's native view in our destructor, effectively freeing this.
+  RenderWidgetHostViewMac* render_widget_host_view_;
+
+  // The background the view should have once it is initialized. This is set
+  // when the view has a custom background, but hasn't been initialized yet.
+  SkBitmap pending_background_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionViewMac);
+};
+
+#endif  // CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_VIEW_MAC_H_
diff --git a/chrome/browser/ui/cocoa/extensions/extension_view_mac.mm b/chrome/browser/ui/cocoa/extensions/extension_view_mac.mm
new file mode 100644
index 0000000..dae9fc7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/extensions/extension_view_mac.mm
@@ -0,0 +1,115 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h"
+
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
+
+// The minimum/maximum dimensions of the popup.
+const CGFloat ExtensionViewMac::kMinWidth = 25.0;
+const CGFloat ExtensionViewMac::kMinHeight = 25.0;
+const CGFloat ExtensionViewMac::kMaxWidth = 800.0;
+const CGFloat ExtensionViewMac::kMaxHeight = 600.0;
+
+ExtensionViewMac::ExtensionViewMac(ExtensionHost* extension_host,
+                                   Browser* browser)
+    : is_toolstrip_(true),
+      browser_(browser),
+      extension_host_(extension_host),
+      render_widget_host_view_(NULL) {
+  DCHECK(extension_host_);
+}
+
+ExtensionViewMac::~ExtensionViewMac() {
+  if (render_widget_host_view_)
+    [render_widget_host_view_->native_view() release];
+}
+
+void ExtensionViewMac::Init() {
+  CreateWidgetHostView();
+}
+
+gfx::NativeView ExtensionViewMac::native_view() {
+  DCHECK(render_widget_host_view_);
+  return render_widget_host_view_->native_view();
+}
+
+RenderViewHost* ExtensionViewMac::render_view_host() const {
+  return extension_host_->render_view_host();
+}
+
+void ExtensionViewMac::SetBackground(const SkBitmap& background) {
+  DCHECK(render_widget_host_view_);
+  if (render_view_host()->IsRenderViewLive()) {
+    render_widget_host_view_->SetBackground(background);
+  } else {
+    pending_background_ = background;
+  }
+}
+
+void ExtensionViewMac::UpdatePreferredSize(const gfx::Size& new_size) {
+  // TODO(thakis, erikkay): Windows does some tricks to resize the extension
+  // view not before it's visible. Do something similar here.
+
+  // No need to use CA here, our caller calls us repeatedly to animate the
+  // resizing.
+  NSView* view = native_view();
+  NSRect frame = [view frame];
+  frame.size.width = new_size.width();
+  frame.size.height = new_size.height();
+
+  // |new_size| is in pixels. Convert to view units.
+  frame.size = [view convertSize:frame.size fromView:nil];
+
+  // On first display of some extensions, this function is called with zero
+  // width after the correct size has been set. Bail if zero is seen, assuming
+  // that an extension's view doesn't want any dimensions to ever be zero.
+  // TODO(andybons): Verify this assumption and look into WebCore's
+  // |contentesPreferredWidth| to see why this is occurring.
+  if (NSIsEmptyRect(frame))
+    return;
+
+  DCHECK([view isKindOfClass:[RenderWidgetHostViewCocoa class]]);
+  RenderWidgetHostViewCocoa* hostView = (RenderWidgetHostViewCocoa*)view;
+
+  // RenderWidgetHostViewCocoa overrides setFrame but not setFrameSize.
+  // We need to defer the update back to the RenderWidgetHost so we don't
+  // get the flickering effect on 10.5 of http://crbug.com/31970
+  [hostView setFrameWithDeferredUpdate:frame];
+  [hostView setNeedsDisplay:YES];
+}
+
+void ExtensionViewMac::RenderViewCreated() {
+  // Do not allow webkit to draw scroll bars on views smaller than
+  // the largest size view allowed.  The view will be resized to make
+  // scroll bars unnecessary.  Scroll bars change the height of the
+  // view, so not drawing them is necessary to avoid infinite resizing.
+  gfx::Size largest_popup_size(
+      CGSizeMake(ExtensionViewMac::kMaxWidth, ExtensionViewMac::kMaxHeight));
+  extension_host_->DisableScrollbarsForSmallWindows(largest_popup_size);
+
+  if (!pending_background_.empty() && render_view_host()->view()) {
+    render_widget_host_view_->SetBackground(pending_background_);
+    pending_background_.reset();
+  }
+}
+
+void ExtensionViewMac::WindowFrameChanged() {
+  if (render_widget_host_view_)
+    render_widget_host_view_->WindowFrameChanged();
+}
+
+void ExtensionViewMac::CreateWidgetHostView() {
+  DCHECK(!render_widget_host_view_);
+  render_widget_host_view_ = new RenderWidgetHostViewMac(render_view_host());
+
+  // The RenderWidgetHostViewMac is owned by its native view, which is created
+  // in an autoreleased state. retain it, so that it doesn't immediately
+  // disappear.
+  [render_widget_host_view_->native_view() retain];
+
+  extension_host_->CreateRenderViewSoon(render_widget_host_view_);
+}
diff --git a/chrome/browser/ui/cocoa/external_protocol_dialog.mm b/chrome/browser/ui/cocoa/external_protocol_dialog.mm
index e72394b..d288ec1 100644
--- a/chrome/browser/ui/cocoa/external_protocol_dialog.mm
+++ b/chrome/browser/ui/cocoa/external_protocol_dialog.mm
@@ -4,8 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/external_protocol_dialog.h"
 
-#include "app/l10n_util_mac.h"
-#include "app/text_elider.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/string_util.h"
@@ -14,6 +12,8 @@
 #include "chrome/browser/external_protocol_handler.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/text/text_elider.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // ExternalProtocolHandler
@@ -62,8 +62,8 @@
 
   const int kMaxUrlWithoutSchemeSize = 256;
   std::wstring elided_url_without_scheme;
-  gfx::ElideString(ASCIIToWide(url_.possibly_invalid_spec()),
-                   kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
+  ui::ElideString(ASCIIToWide(url_.possibly_invalid_spec()),
+                  kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
 
   NSString* urlString = l10n_util::GetNSStringFWithFixup(
       IDS_EXTERNAL_PROTOCOL_INFORMATION,
diff --git a/chrome/browser/ui/cocoa/find_bar/OWNERS b/chrome/browser/ui/cocoa/find_bar/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h b/chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h
new file mode 100644
index 0000000..217c2cb
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_FIND_BAR_FIND_BAR_BRIDGE_H_
+#define CHROME_BROWSER_UI_COCOA_FIND_BAR_FIND_BAR_BRIDGE_H_
+#pragma once
+
+#include "base/logging.h"
+#include "chrome/browser/ui/find_bar/find_bar.h"
+
+class BrowserWindowCocoa;
+class FindBarController;
+
+// This class is included by find_bar_host_browsertest.cc, so it has to be
+// objc-free.
+#ifdef __OBJC__
+@class FindBarCocoaController;
+#else
+class FindBarCocoaController;
+#endif
+
+// Implementation of FindBar for the Mac.  This class simply passes
+// each message along to |cocoa_controller_|.
+//
+// The initialization here is a bit complicated.  FindBarBridge is
+// created by a static method in BrowserWindow.  The FindBarBridge
+// constructor creates a FindBarCocoaController, which in turn loads a
+// FindBarView from a nib file.  All of this is happening outside of
+// the main view hierarchy, so the static method also calls
+// BrowserWindowCocoa::AddFindBar() in order to add its FindBarView to
+// the cocoa views hierarchy.
+//
+// Memory ownership is relatively straightforward.  The FindBarBridge
+// object is owned by the Browser.  FindBarCocoaController is retained
+// by bother FindBarBridge and BrowserWindowController, since both use it.
+
+class FindBarBridge : public FindBar,
+                      public FindBarTesting {
+ public:
+  FindBarBridge();
+  virtual ~FindBarBridge();
+
+  FindBarCocoaController* find_bar_cocoa_controller() {
+    return cocoa_controller_;
+  }
+
+  virtual void SetFindBarController(FindBarController* find_bar_controller) {
+    find_bar_controller_ = find_bar_controller;
+  }
+
+  virtual FindBarController* GetFindBarController() const {
+    DCHECK(find_bar_controller_);
+    return find_bar_controller_;
+  }
+
+  virtual FindBarTesting* GetFindBarTesting() {
+    return this;
+  }
+
+  // Methods from FindBar.
+  virtual void Show(bool animate);
+  virtual void Hide(bool animate);
+  virtual void SetFocusAndSelection();
+  virtual void ClearResults(const FindNotificationDetails& results);
+  virtual void StopAnimation();
+  virtual void SetFindText(const string16& find_text);
+  virtual void UpdateUIForFindResult(const FindNotificationDetails& result,
+                                     const string16& find_text);
+  virtual void AudibleAlert();
+  virtual bool IsFindBarVisible();
+  virtual void RestoreSavedFocus();
+  virtual void MoveWindowIfNecessary(const gfx::Rect& selection_rect,
+                                     bool no_redraw);
+
+  // Methods from FindBarTesting.
+  virtual bool GetFindBarWindowInfo(gfx::Point* position,
+                                    bool* fully_visible);
+  virtual string16 GetFindText();
+  virtual string16 GetFindSelectedText();
+  virtual string16 GetMatchCountText();
+
+  // Used to disable find bar animations when testing.
+  static bool disable_animations_during_testing_;
+
+ private:
+  // Pointer to the cocoa controller which manages the cocoa view.  Is
+  // never nil.
+  FindBarCocoaController* cocoa_controller_;
+
+  // Pointer back to the owning controller.
+  FindBarController* find_bar_controller_;  // weak, owns us
+
+  DISALLOW_COPY_AND_ASSIGN(FindBarBridge);
+};
+
+#endif  // CHROME_BROWSER_UI_COCOA_FIND_BAR_FIND_BAR_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_bridge.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_bridge.mm
new file mode 100644
index 0000000..3384b2c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_bridge.mm
@@ -0,0 +1,114 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
+
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
+
+// static
+bool FindBarBridge::disable_animations_during_testing_ = false;
+
+FindBarBridge::FindBarBridge()
+    : find_bar_controller_(NULL) {
+  cocoa_controller_ = [[FindBarCocoaController alloc] init];
+  [cocoa_controller_ setFindBarBridge:this];
+}
+
+FindBarBridge::~FindBarBridge() {
+  [cocoa_controller_ release];
+}
+
+void FindBarBridge::Show(bool animate) {
+  bool really_animate = animate && !disable_animations_during_testing_;
+  [cocoa_controller_ showFindBar:(really_animate ? YES : NO)];
+}
+
+void FindBarBridge::Hide(bool animate) {
+  bool really_animate = animate && !disable_animations_during_testing_;
+  [cocoa_controller_ hideFindBar:(really_animate ? YES : NO)];
+}
+
+void FindBarBridge::SetFocusAndSelection() {
+  [cocoa_controller_ setFocusAndSelection];
+}
+
+void FindBarBridge::ClearResults(const FindNotificationDetails& results) {
+  [cocoa_controller_ clearResults:results];
+}
+
+void FindBarBridge::SetFindText(const string16& find_text) {
+  [cocoa_controller_ setFindText:base::SysUTF16ToNSString(find_text)];
+}
+
+void FindBarBridge::UpdateUIForFindResult(const FindNotificationDetails& result,
+                                          const string16& find_text) {
+  [cocoa_controller_ updateUIForFindResult:result withText:find_text];
+}
+
+void FindBarBridge::AudibleAlert() {
+  // Beep beep, beep beep, Yeah!
+  NSBeep();
+}
+
+bool FindBarBridge::IsFindBarVisible() {
+  return [cocoa_controller_ isFindBarVisible] ? true : false;
+}
+
+void FindBarBridge::MoveWindowIfNecessary(const gfx::Rect& selection_rect,
+                                          bool no_redraw) {
+  // http://crbug.com/11084
+  // http://crbug.com/22036
+}
+
+void FindBarBridge::StopAnimation() {
+  [cocoa_controller_ stopAnimation];
+}
+
+void FindBarBridge::RestoreSavedFocus() {
+  [cocoa_controller_ restoreSavedFocus];
+}
+
+bool FindBarBridge::GetFindBarWindowInfo(gfx::Point* position,
+                                         bool* fully_visible) {
+  // TODO(rohitrao): Return the proper position.  http://crbug.com/22036
+  if (position)
+    *position = gfx::Point(0, 0);
+
+  NSWindow* window = [[cocoa_controller_ view] window];
+  bool window_visible = [window isVisible] ? true : false;
+  if (fully_visible) {
+    *fully_visible = window_visible &&
+        [cocoa_controller_ isFindBarVisible] &&
+        ![cocoa_controller_ isFindBarAnimating];
+  }
+  return window_visible;
+}
+
+string16 FindBarBridge::GetFindText() {
+  // This function is currently only used in Windows and Linux specific browser
+  // tests (testing prepopulate values that Mac's don't rely on), but if we add
+  // more tests that are non-platform specific, we need to flesh out this
+  // function.
+  NOTIMPLEMENTED();
+  return string16();
+}
+
+string16 FindBarBridge::GetFindSelectedText() {
+  // This function is currently only used in Windows and Linux specific browser
+  // tests (testing prepopulate values that Mac's don't rely on), but if we add
+  // more tests that are non-platform specific, we need to flesh out this
+  // function.
+  NOTIMPLEMENTED();
+  return string16();
+}
+
+string16 FindBarBridge::GetMatchCountText() {
+  // This function is currently only used in Windows and Linux specific browser
+  // tests (testing prepopulate values that Mac's don't rely on), but if we add
+  // more tests that are non-platform specific, we need to flesh out this
+  // function.
+  NOTIMPLEMENTED();
+  return string16();
+}
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_bridge_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_bridge_unittest.mm
new file mode 100644
index 0000000..10c13bd
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_bridge_unittest.mm
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+
+namespace {
+
+class FindBarBridgeTest : public CocoaTest {
+};
+
+TEST_F(FindBarBridgeTest, Creation) {
+  // Make sure the FindBarBridge constructor doesn't crash and
+  // properly initializes its FindBarCocoaController.
+  FindBarBridge bridge;
+  EXPECT_TRUE(bridge.find_bar_cocoa_controller() != NULL);
+}
+
+TEST_F(FindBarBridgeTest, Accessors) {
+  // Get/SetFindBarController are virtual methods implemented in
+  // FindBarBridge, so we test them here.
+  FindBarBridge* bridge = new FindBarBridge();
+  FindBarController controller(bridge);  // takes ownership of |bridge|.
+  bridge->SetFindBarController(&controller);
+
+  EXPECT_EQ(&controller, bridge->GetFindBarController());
+}
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h
new file mode 100644
index 0000000..548b1ba
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
+
+#include "base/scoped_nsobject.h"
+#include "base/string16.h"
+
+class BrowserWindowCocoa;
+class FindBarBridge;
+@class FindBarTextField;
+class FindNotificationDetails;
+@class FocusTracker;
+
+// A controller for the find bar in the browser window.  Manages
+// updating the state of the find bar and provides a target for the
+// next/previous/close buttons.  Certain operations require a pointer
+// to the cross-platform FindBarController, so be sure to call
+// setFindBarBridge: after creating this controller.
+
+@interface FindBarCocoaController : NSViewController {
+ @private
+  IBOutlet NSView* findBarView_;
+  IBOutlet FindBarTextField* findText_;
+  IBOutlet NSButton* nextButton_;
+  IBOutlet NSButton* previousButton_;
+
+  // Needed to call methods on FindBarController.
+  FindBarBridge* findBarBridge_;  // weak
+
+  scoped_nsobject<FocusTracker> focusTracker_;
+
+  // The currently-running animation.  This is defined to be non-nil if an
+  // animation is running, and is always nil otherwise.  The
+  // FindBarCocoaController should not be deallocated while an animation is
+  // running (stopAnimation is currently called before the last tab in a
+  // window is removed).
+  scoped_nsobject<NSViewAnimation> currentAnimation_;
+
+  // If YES, do nothing as a result of find pasteboard update notifications.
+  BOOL suppressPboardUpdateActions_;
+};
+
+// Initializes a new FindBarCocoaController.
+- (id)init;
+
+- (void)setFindBarBridge:(FindBarBridge*)findBar;
+
+- (IBAction)close:(id)sender;
+
+- (IBAction)nextResult:(id)sender;
+
+- (IBAction)previousResult:(id)sender;
+
+// Position the find bar at the given maximum y-coordinate (the min-y of the
+// bar -- toolbar + possibly bookmark bar, but not including the infobars) with
+// the given maximum width (i.e., the find bar should fit between 0 and
+// |maxWidth|).
+- (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth;
+
+// Methods called from FindBarBridge.
+- (void)showFindBar:(BOOL)animate;
+- (void)hideFindBar:(BOOL)animate;
+- (void)stopAnimation;
+- (void)setFocusAndSelection;
+- (void)restoreSavedFocus;
+- (void)setFindText:(NSString*)findText;
+
+- (void)clearResults:(const FindNotificationDetails&)results;
+- (void)updateUIForFindResult:(const FindNotificationDetails&)results
+                     withText:(const string16&)findText;
+- (BOOL)isFindBarVisible;
+- (BOOL)isFindBarAnimating;
+
+@end
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
new file mode 100644
index 0000000..b6bb951
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
@@ -0,0 +1,395 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
+#import "chrome/browser/ui/cocoa/find_pasteboard.h"
+#import "chrome/browser/ui/cocoa/focus_tracker.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+
+namespace {
+const float kFindBarOpenDuration = 0.2;
+const float kFindBarCloseDuration = 0.15;
+}
+
+@interface FindBarCocoaController (PrivateMethods)
+// Returns the appropriate frame for a hidden find bar.
+- (NSRect)hiddenFindBarFrame;
+
+// Sets the frame of |findBarView_|.  |duration| is ignored if |animate| is NO.
+- (void)setFindBarFrame:(NSRect)endFrame
+                animate:(BOOL)animate
+               duration:(float)duration;
+
+// Optionally stops the current search, puts |text| into the find bar, and
+// enables the buttons, but doesn't start a new search for |text|.
+- (void)prepopulateText:(NSString*)text stopSearch:(BOOL)stopSearch;
+@end
+
+@implementation FindBarCocoaController
+
+- (id)init {
+  if ((self = [super initWithNibName:@"FindBar"
+                              bundle:base::mac::MainAppBundle()])) {
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(findPboardUpdated:)
+               name:kFindPasteboardChangedNotification
+             object:[FindPasteboard sharedInstance]];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  // All animations should be explicitly stopped by the TabContents before a tab
+  // is closed.
+  DCHECK(!currentAnimation_.get());
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
+- (void)setFindBarBridge:(FindBarBridge*)findBarBridge {
+  DCHECK(!findBarBridge_);  // should only be called once.
+  findBarBridge_ = findBarBridge;
+}
+
+- (void)awakeFromNib {
+  [findBarView_ setFrame:[self hiddenFindBarFrame]];
+
+  // Stopping the search requires a findbar controller, which isn't valid yet
+  // during setup. Furthermore, there is no active search yet anyway.
+  [self prepopulateText:[[FindPasteboard sharedInstance] findText]
+             stopSearch:NO];
+}
+
+- (IBAction)close:(id)sender {
+  if (findBarBridge_)
+    findBarBridge_->GetFindBarController()->EndFindSession(
+        FindBarController::kKeepSelection);
+}
+
+- (IBAction)previousResult:(id)sender {
+  if (findBarBridge_) {
+    FindManager* find_manager = findBarBridge_->
+        GetFindBarController()->tab_contents()->GetFindManager();
+    find_manager->StartFinding(
+        base::SysNSStringToUTF16([findText_ stringValue]),
+        false, false);
+  }
+}
+
+- (IBAction)nextResult:(id)sender {
+  if (findBarBridge_) {
+    FindManager* find_manager = findBarBridge_->
+        GetFindBarController()->tab_contents()->GetFindManager();
+    find_manager->StartFinding(
+        base::SysNSStringToUTF16([findText_ stringValue]),
+        true, false);
+  }
+}
+
+- (void)findPboardUpdated:(NSNotification*)notification {
+  if (suppressPboardUpdateActions_)
+    return;
+  [self prepopulateText:[[FindPasteboard sharedInstance] findText]
+             stopSearch:YES];
+}
+
+- (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth {
+  static const CGFloat kRightEdgeOffset = 25;
+  NSView* containerView = [self view];
+  CGFloat containerHeight = NSHeight([containerView frame]);
+  CGFloat containerWidth = NSWidth([containerView frame]);
+
+  // Adjust where we'll actually place the find bar.
+  CGFloat maxX = maxWidth - kRightEdgeOffset;
+  DLOG_IF(WARNING, maxX < 0) << "Window too narrow for find bar";
+  maxY += 1;
+
+  NSRect newFrame = NSMakeRect(maxX - containerWidth, maxY - containerHeight,
+                               containerWidth, containerHeight);
+  [containerView setFrame:newFrame];
+}
+
+// NSControl delegate method.
+- (void)controlTextDidChange:(NSNotification *)aNotification {
+  if (!findBarBridge_)
+    return;
+
+  TabContentsWrapper* tab_contents =
+      findBarBridge_->GetFindBarController()->tab_contents();
+  if (!tab_contents)
+    return;
+  FindManager* find_manager = tab_contents->GetFindManager();
+
+  NSString* findText = [findText_ stringValue];
+  suppressPboardUpdateActions_ = YES;
+  [[FindPasteboard sharedInstance] setFindText:findText];
+  suppressPboardUpdateActions_ = NO;
+
+  if ([findText length] > 0) {
+    find_manager->StartFinding(base::SysNSStringToUTF16(findText), true, false);
+  } else {
+    // The textbox is empty so we reset.
+    find_manager->StopFinding(FindBarController::kClearSelection);
+    [self updateUIForFindResult:find_manager->find_result()
+                       withText:string16()];
+  }
+}
+
+// NSControl delegate method
+- (BOOL)control:(NSControl*)control
+    textView:(NSTextView*)textView
+    doCommandBySelector:(SEL)command {
+  if (command == @selector(insertNewline:)) {
+    // Pressing Return
+    NSEvent* event = [NSApp currentEvent];
+
+    if ([event modifierFlags] & NSShiftKeyMask)
+      [previousButton_ performClick:nil];
+    else
+      [nextButton_ performClick:nil];
+
+    return YES;
+  } else if (command == @selector(insertLineBreak:)) {
+    // Pressing Ctrl-Return
+    if (findBarBridge_) {
+      findBarBridge_->GetFindBarController()->EndFindSession(
+          FindBarController::kActivateSelection);
+    }
+    return YES;
+  } else if (command == @selector(pageUp:) ||
+             command == @selector(pageUpAndModifySelection:) ||
+             command == @selector(scrollPageUp:) ||
+             command == @selector(pageDown:) ||
+             command == @selector(pageDownAndModifySelection:) ||
+             command == @selector(scrollPageDown:) ||
+             command == @selector(scrollToBeginningOfDocument:) ||
+             command == @selector(scrollToEndOfDocument:) ||
+             command == @selector(moveUp:) ||
+             command == @selector(moveDown:)) {
+    TabContentsWrapper* contents =
+        findBarBridge_->GetFindBarController()->tab_contents();
+    if (!contents)
+      return NO;
+
+    // Sanity-check to make sure we got a keyboard event.
+    NSEvent* event = [NSApp currentEvent];
+    if ([event type] != NSKeyDown && [event type] != NSKeyUp)
+      return NO;
+
+    // Forward the event to the renderer.
+    // TODO(rohitrao): Should this call -[BaseView keyEvent:]?  Is there code in
+    // that function that we want to keep or avoid? Calling
+    // |ForwardKeyboardEvent()| directly ignores edit commands, which breaks
+    // cmd-up/down if we ever decide to include |moveToBeginningOfDocument:| in
+    // the list above.
+    RenderViewHost* render_view_host = contents->render_view_host();
+    render_view_host->ForwardKeyboardEvent(NativeWebKeyboardEvent(event));
+    return YES;
+  }
+
+  return NO;
+}
+
+// Methods from FindBar
+- (void)showFindBar:(BOOL)animate {
+  // Save the currently-focused view.  |findBarView_| is in the view
+  // hierarchy by now.  showFindBar can be called even when the
+  // findbar is already open, so do not overwrite an already saved
+  // view.
+  if (!focusTracker_.get())
+    focusTracker_.reset(
+        [[FocusTracker alloc] initWithWindow:[findBarView_ window]]);
+
+  // Animate the view into place.
+  NSRect frame = [findBarView_ frame];
+  frame.origin = NSMakePoint(0, 0);
+  [self setFindBarFrame:frame animate:animate duration:kFindBarOpenDuration];
+}
+
+- (void)hideFindBar:(BOOL)animate {
+  NSRect frame = [self hiddenFindBarFrame];
+  [self setFindBarFrame:frame animate:animate duration:kFindBarCloseDuration];
+}
+
+- (void)stopAnimation {
+  if (currentAnimation_.get()) {
+    [currentAnimation_ stopAnimation];
+    currentAnimation_.reset(nil);
+  }
+}
+
+- (void)setFocusAndSelection {
+  [[findText_ window] makeFirstResponder:findText_];
+
+  // Enable the buttons if the find text is non-empty.
+  BOOL buttonsEnabled = ([[findText_ stringValue] length] > 0) ? YES : NO;
+  [previousButton_ setEnabled:buttonsEnabled];
+  [nextButton_ setEnabled:buttonsEnabled];
+}
+
+- (void)restoreSavedFocus {
+  if (!(focusTracker_.get() &&
+        [focusTracker_ restoreFocusInWindow:[findBarView_ window]])) {
+    // Fall back to giving focus to the tab contents.
+    findBarBridge_->
+        GetFindBarController()->tab_contents()->tab_contents()->Focus();
+  }
+  focusTracker_.reset(nil);
+}
+
+- (void)setFindText:(NSString*)findText {
+  [findText_ setStringValue:findText];
+
+  // Make sure the text in the find bar always ends up in the find pasteboard
+  // (and, via notifications, in the other find bars too).
+  [[FindPasteboard sharedInstance] setFindText:findText];
+}
+
+- (void)clearResults:(const FindNotificationDetails&)results {
+  // Just call updateUIForFindResult, which will take care of clearing
+  // the search text and the results label.
+  [self updateUIForFindResult:results withText:string16()];
+}
+
+- (void)updateUIForFindResult:(const FindNotificationDetails&)result
+                     withText:(const string16&)findText {
+  // If we don't have any results and something was passed in, then
+  // that means someone pressed Cmd-G while the Find box was
+  // closed. In that case we need to repopulate the Find box with what
+  // was passed in.
+  if ([[findText_ stringValue] length] == 0 && !findText.empty()) {
+    [findText_ setStringValue:base::SysUTF16ToNSString(findText)];
+    [findText_ selectText:self];
+  }
+
+  // Make sure Find Next and Find Previous are enabled if we found any matches.
+  BOOL buttonsEnabled = result.number_of_matches() > 0 ? YES : NO;
+  [previousButton_ setEnabled:buttonsEnabled];
+  [nextButton_ setEnabled:buttonsEnabled];
+
+  // Update the results label.
+  BOOL validRange = result.active_match_ordinal() != -1 &&
+                    result.number_of_matches() != -1;
+  NSString* searchString = [findText_ stringValue];
+  if ([searchString length] > 0 && validRange) {
+    [[findText_ findBarTextFieldCell]
+        setActiveMatch:result.active_match_ordinal()
+                    of:result.number_of_matches()];
+  } else {
+    // If there was no text entered, we don't show anything in the results area.
+    [[findText_ findBarTextFieldCell] clearResults];
+  }
+
+  [findText_ resetFieldEditorFrameIfNeeded];
+
+  // If we found any results, reset the focus tracker, so we always
+  // restore focus to the tab contents.
+  if (result.number_of_matches() > 0)
+    focusTracker_.reset(nil);
+}
+
+- (BOOL)isFindBarVisible {
+  // Find bar is visible if any part of it is on the screen.
+  return NSIntersectsRect([[self view] bounds], [findBarView_ frame]);
+}
+
+- (BOOL)isFindBarAnimating {
+  return (currentAnimation_.get() != nil);
+}
+
+// NSAnimation delegate methods.
+- (void)animationDidEnd:(NSAnimation*)animation {
+  // Autorelease the animation (cannot use release because the animation object
+  // is still on the stack.
+  DCHECK(animation == currentAnimation_.get());
+  [currentAnimation_.release() autorelease];
+
+  // If the find bar is not visible, make it actually hidden, so it'll no longer
+  // respond to key events.
+  [findBarView_ setHidden:![self isFindBarVisible]];
+}
+
+@end
+
+@implementation FindBarCocoaController (PrivateMethods)
+
+- (NSRect)hiddenFindBarFrame {
+  NSRect frame = [findBarView_ frame];
+  NSRect containerBounds = [[self view] bounds];
+  frame.origin = NSMakePoint(NSMinX(containerBounds), NSMaxY(containerBounds));
+  return frame;
+}
+
+- (void)setFindBarFrame:(NSRect)endFrame
+                animate:(BOOL)animate
+               duration:(float)duration {
+  // Save the current frame.
+  NSRect startFrame = [findBarView_ frame];
+
+  // Stop any existing animations.
+  [currentAnimation_ stopAnimation];
+
+  if (!animate) {
+    [findBarView_ setFrame:endFrame];
+    [findBarView_ setHidden:![self isFindBarVisible]];
+    currentAnimation_.reset(nil);
+    return;
+  }
+
+  // If animating, ensure that the find bar is not hidden. Hidden status will be
+  // updated at the end of the animation.
+  [findBarView_ setHidden:NO];
+
+  // Reset the frame to what was saved above.
+  [findBarView_ setFrame:startFrame];
+  NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
+      findBarView_, NSViewAnimationTargetKey,
+      [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil];
+
+  currentAnimation_.reset(
+      [[NSViewAnimation alloc]
+        initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]);
+  [currentAnimation_ gtm_setDuration:duration
+                           eventMask:NSLeftMouseUpMask];
+  [currentAnimation_ setDelegate:self];
+  [currentAnimation_ startAnimation];
+}
+
+- (void)prepopulateText:(NSString*)text stopSearch:(BOOL)stopSearch{
+  [self setFindText:text];
+
+  // End the find session, hide the "x of y" text and disable the
+  // buttons, but do not close the find bar or raise the window here.
+  if (stopSearch && findBarBridge_) {
+    TabContentsWrapper* contents =
+        findBarBridge_->GetFindBarController()->tab_contents();
+    if (contents) {
+      FindManager* find_manager = contents->GetFindManager();
+      find_manager->StopFinding(FindBarController::kClearSelection);
+      findBarBridge_->ClearResults(find_manager->find_result());
+    }
+  }
+
+  // Has to happen after |ClearResults()| above.
+  BOOL buttonsEnabled = [text length] > 0 ? YES : NO;
+  [previousButton_ setEnabled:buttonsEnabled];
+  [nextButton_ setEnabled:buttonsEnabled];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm
new file mode 100644
index 0000000..b3a6389
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm
@@ -0,0 +1,138 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/browser_window.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/find_pasteboard.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h"
+#include "chrome/browser/ui/find_bar/find_notification_details.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+// Expose private variables to make testing easier.
+@interface FindBarCocoaController(Testing)
+- (NSView*)findBarView;
+- (NSString*)findText;
+- (FindBarTextField*)findTextField;
+@end
+
+@implementation FindBarCocoaController(Testing)
+- (NSView*)findBarView {
+  return findBarView_;
+}
+
+- (NSString*)findText {
+  return [findText_ stringValue];
+}
+
+- (FindBarTextField*)findTextField {
+  return findText_;
+}
+
+- (NSButton*)nextButton {
+  return nextButton_;
+}
+
+- (NSButton*)previousButton {
+  return previousButton_;
+}
+@end
+
+namespace {
+
+class FindBarCocoaControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    controller_.reset([[FindBarCocoaController alloc] init]);
+    [[test_window() contentView] addSubview:[controller_ view]];
+  }
+
+ protected:
+  scoped_nsobject<FindBarCocoaController> controller_;
+};
+
+TEST_VIEW(FindBarCocoaControllerTest, [controller_ view])
+
+TEST_F(FindBarCocoaControllerTest, ImagesLoadedProperly) {
+  EXPECT_TRUE([[[controller_ nextButton] image] isValid]);
+  EXPECT_TRUE([[[controller_ previousButton] image] isValid]);
+}
+
+TEST_F(FindBarCocoaControllerTest, ShowAndHide) {
+  NSView* findBarView = [controller_ findBarView];
+
+  ASSERT_GT([findBarView frame].origin.y, 0);
+  ASSERT_FALSE([controller_ isFindBarVisible]);
+
+  [controller_ showFindBar:NO];
+  EXPECT_EQ([findBarView frame].origin.y, 0);
+  EXPECT_TRUE([controller_ isFindBarVisible]);
+
+  [controller_ hideFindBar:NO];
+  EXPECT_GT([findBarView frame].origin.y, 0);
+  EXPECT_FALSE([controller_ isFindBarVisible]);
+}
+
+TEST_F(FindBarCocoaControllerTest, SetFindText) {
+  NSTextField* findTextField = [controller_ findTextField];
+
+  // Start by making the find bar visible.
+  [controller_ showFindBar:NO];
+  EXPECT_TRUE([controller_ isFindBarVisible]);
+
+  // Set the find text.
+  NSString* const kFindText = @"Google";
+  [controller_ setFindText:kFindText];
+  EXPECT_EQ(
+      NSOrderedSame,
+      [[findTextField stringValue] compare:kFindText]);
+
+  // Call clearResults, which doesn't actually clear the find text but
+  // simply sets it back to what it was before.  This is silly, but
+  // matches the behavior on other platforms.  |details| isn't used by
+  // our implementation of clearResults, so it's ok to pass in an
+  // empty |details|.
+  FindNotificationDetails details;
+  [controller_ clearResults:details];
+  EXPECT_EQ(
+      NSOrderedSame,
+      [[findTextField stringValue] compare:kFindText]);
+}
+
+TEST_F(FindBarCocoaControllerTest, ResultLabelUpdatesCorrectly) {
+  // TODO(rohitrao): Test this.  It may involve creating some dummy
+  // FindNotificationDetails objects.
+}
+
+TEST_F(FindBarCocoaControllerTest, FindTextIsGlobal) {
+  scoped_nsobject<FindBarCocoaController> otherController(
+      [[FindBarCocoaController alloc] init]);
+  [[test_window() contentView] addSubview:[otherController view]];
+
+  // Setting the text in one controller should update the other controller's
+  // text as well.
+  NSString* const kFindText = @"Respect to the man in the ice cream van";
+  [controller_ setFindText:kFindText];
+  EXPECT_EQ(
+      NSOrderedSame,
+      [[controller_ findText] compare:kFindText]);
+  EXPECT_EQ(
+      NSOrderedSame,
+      [[otherController.get() findText] compare:kFindText]);
+}
+
+TEST_F(FindBarCocoaControllerTest, SettingFindTextUpdatesFindPboard) {
+  NSString* const kFindText =
+      @"It's not a bird, it's not a plane, it must be Dave who's on the train";
+  [controller_ setFindText:kFindText];
+  EXPECT_EQ(
+      NSOrderedSame,
+      [[[FindPasteboard sharedInstance] findText] compare:kFindText]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar_text_field.h b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h
similarity index 100%
rename from chrome/browser/ui/cocoa/find_bar_text_field.h
rename to chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field.mm
new file mode 100644
index 0000000..eabfc70
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field.mm
@@ -0,0 +1,40 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h"
+
+#include "base/logging.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+
+@implementation FindBarTextField
+
++ (Class)cellClass {
+  return [FindBarTextFieldCell class];
+}
+
+- (void)awakeFromNib {
+  DCHECK([[self cell] isKindOfClass:[FindBarTextFieldCell class]]);
+
+  [self registerForDraggedTypes:
+          [NSArray arrayWithObjects:NSStringPboardType, nil]];
+}
+
+- (FindBarTextFieldCell*)findBarTextFieldCell {
+  DCHECK([[self cell] isKindOfClass:[FindBarTextFieldCell class]]);
+  return static_cast<FindBarTextFieldCell*>([self cell]);
+}
+
+- (ViewID)viewID {
+  return VIEW_ID_FIND_IN_PAGE_TEXT_FIELD;
+}
+
+- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
+  // When a drag enters the text field, focus the field.  This will swap in the
+  // field editor, which will then handle the drag itself.
+  [[self window] makeFirstResponder:self];
+  return NSDragOperationNone;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/find_bar_text_field_cell.h b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h
similarity index 100%
rename from chrome/browser/ui/cocoa/find_bar_text_field_cell.h
rename to chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm
new file mode 100644
index 0000000..cf29031
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.mm
@@ -0,0 +1,119 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+const CGFloat kBaselineAdjust = 1.0;
+
+// How far to offset the keyword token into the field.
+const NSInteger kResultsXOffset = 3;
+
+// How much width (beyond text) to add to the keyword token on each
+// side.
+const NSInteger kResultsTokenInset = 3;
+
+// How far to shift bounding box of hint down from top of field.
+// Assumes -setFlipped:YES.
+const NSInteger kResultsYOffset = 4;
+
+// How far the editor insets itself, for purposes of determining if
+// decorations need to be trimmed.
+const CGFloat kEditorHorizontalInset = 3.0;
+
+// Conveniences to centralize width+offset calculations.
+CGFloat WidthForResults(NSAttributedString* resultsString) {
+  return kResultsXOffset + ceil([resultsString size].width) +
+      2 * kResultsTokenInset;
+}
+
+}  // namespace
+
+@implementation FindBarTextFieldCell
+
+- (CGFloat)baselineAdjust {
+  return kBaselineAdjust;
+}
+
+- (CGFloat)cornerRadius {
+  return 4.0;
+}
+
+- (StyledTextFieldCellRoundedFlags)roundedFlags {
+  return StyledTextFieldCellRoundedLeft;
+}
+
+// @synthesize doesn't seem to compile for this transition.
+- (NSAttributedString*)resultsString {
+  return resultsString_.get();
+}
+
+// Convenience for the attributes used in the right-justified info
+// cells.  Sets the background color to red if |foundMatches| is YES.
+- (NSDictionary*)resultsAttributes:(BOOL)foundMatches {
+  scoped_nsobject<NSMutableParagraphStyle> style(
+      [[NSMutableParagraphStyle alloc] init]);
+  [style setAlignment:NSRightTextAlignment];
+
+  return [NSDictionary dictionaryWithObjectsAndKeys:
+              [self font], NSFontAttributeName,
+              [NSColor lightGrayColor], NSForegroundColorAttributeName,
+              [NSColor whiteColor], NSBackgroundColorAttributeName,
+              style.get(), NSParagraphStyleAttributeName,
+              nil];
+}
+
+- (void)setActiveMatch:(NSInteger)current of:(NSInteger)total {
+  NSString* results =
+      base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
+          IDS_FIND_IN_PAGE_COUNT,
+          base::IntToString16(current),
+          base::IntToString16(total)));
+  resultsString_.reset([[NSAttributedString alloc]
+                         initWithString:results
+                         attributes:[self resultsAttributes:(total > 0)]]);
+}
+
+- (void)clearResults {
+  resultsString_.reset(nil);
+}
+
+- (NSRect)textFrameForFrame:(NSRect)cellFrame {
+  NSRect textFrame([super textFrameForFrame:cellFrame]);
+  if (resultsString_)
+    textFrame.size.width -= WidthForResults(resultsString_);
+  return textFrame;
+}
+
+// Do not show the I-beam cursor over the results label.
+- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame {
+  return [self textFrameForFrame:cellFrame];
+}
+
+- (void)drawResultsWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+  DCHECK(resultsString_);
+
+  NSRect textFrame = [self textFrameForFrame:cellFrame];
+  NSRect infoFrame(NSMakeRect(NSMaxX(textFrame),
+                              cellFrame.origin.y + kResultsYOffset,
+                              ceil([resultsString_ size].width),
+                              cellFrame.size.height - kResultsYOffset));
+  [resultsString_.get() drawInRect:infoFrame];
+}
+
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+  if (resultsString_)
+    [self drawResultsWithFrame:cellFrame inView:controlView];
+  [super drawInteriorWithFrame:cellFrame inView:controlView];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm
new file mode 100644
index 0000000..c65431c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell_unittest.mm
@@ -0,0 +1,135 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface FindBarTextFieldCell (ExposedForTesting)
+- (NSAttributedString*)resultsString;
+@end
+
+@implementation FindBarTextFieldCell (ExposedForTesting)
+- (NSAttributedString*)resultsString {
+  return resultsString_.get();
+}
+@end
+
+namespace {
+
+// Width of the field so that we don't have to ask |field_| for it all
+// the time.
+const CGFloat kWidth(300.0);
+
+// A narrow width for tests which test things that don't fit.
+const CGFloat kNarrowWidth(5.0);
+
+class FindBarTextFieldCellTest : public CocoaTest {
+ public:
+  FindBarTextFieldCellTest() {
+    // Make sure this is wide enough to play games with the cell
+    // decorations.
+    const NSRect frame = NSMakeRect(0, 0, kWidth, 30);
+
+    scoped_nsobject<FindBarTextFieldCell> cell(
+        [[FindBarTextFieldCell alloc] initTextCell:@"Testing"]);
+    cell_ = cell;
+    [cell_ setEditable:YES];
+    [cell_ setBordered:YES];
+
+    scoped_nsobject<NSTextField> view(
+        [[NSTextField alloc] initWithFrame:frame]);
+    view_ = view;
+    [view_ setCell:cell_];
+
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  NSTextField* view_;
+  FindBarTextFieldCell* cell_;
+};
+
+// Basic view tests (AddRemove, Display).
+TEST_VIEW(FindBarTextFieldCellTest, view_);
+
+// Test drawing, mostly to ensure nothing leaks or crashes.
+TEST_F(FindBarTextFieldCellTest, FocusedDisplay) {
+  [view_ display];
+
+  // Test focused drawing.
+  [test_window() makePretendKeyWindowAndSetFirstResponder:view_];
+  [view_ display];
+  [test_window() clearPretendKeyWindowAndFirstResponder];
+
+  // Test display of various cell configurations.
+  [cell_ setActiveMatch:4 of:30];
+  [view_ display];
+
+  [cell_ setActiveMatch:0 of:0];
+  [view_ display];
+
+  [cell_ clearResults];
+  [view_ display];
+}
+
+// Verify that setting and clearing the find results changes the results string
+// appropriately.
+TEST_F(FindBarTextFieldCellTest, SetAndClearFindResults) {
+  [cell_ setActiveMatch:10 of:30];
+  scoped_nsobject<NSAttributedString> tenString([[cell_ resultsString] copy]);
+  EXPECT_GT([tenString length], 0U);
+
+  [cell_ setActiveMatch:0 of:0];
+  scoped_nsobject<NSAttributedString> zeroString([[cell_ resultsString] copy]);
+  EXPECT_GT([zeroString length], 0U);
+  EXPECT_FALSE([tenString isEqualToAttributedString:zeroString]);
+
+  [cell_ clearResults];
+  EXPECT_EQ(0U, [[cell_ resultsString] length]);
+}
+
+TEST_F(FindBarTextFieldCellTest, TextFrame) {
+  const NSRect bounds = [view_ bounds];
+  NSRect textFrame = [cell_ textFrameForFrame:bounds];
+  NSRect cursorFrame = [cell_ textCursorFrameForFrame:bounds];
+
+  // At default settings, everything goes to the text area.
+  EXPECT_FALSE(NSIsEmptyRect(textFrame));
+  EXPECT_TRUE(NSContainsRect(bounds, textFrame));
+  EXPECT_EQ(NSMinX(bounds), NSMinX(textFrame));
+  EXPECT_EQ(NSMaxX(bounds), NSMaxX(textFrame));
+  EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame));
+
+  // Setting an active match leaves text frame to left.
+  [cell_ setActiveMatch:4 of:5];
+  textFrame = [cell_ textFrameForFrame:bounds];
+  cursorFrame = [cell_ textCursorFrameForFrame:bounds];
+  EXPECT_FALSE(NSIsEmptyRect(textFrame));
+  EXPECT_TRUE(NSContainsRect(bounds, textFrame));
+  EXPECT_LT(NSMaxX(textFrame), NSMaxX(bounds));
+  EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame));
+
+}
+
+// The editor frame should be slightly inset from the text frame.
+TEST_F(FindBarTextFieldCellTest, DrawingRectForBounds) {
+  const NSRect bounds = [view_ bounds];
+  NSRect textFrame = [cell_ textFrameForFrame:bounds];
+  NSRect drawingRect = [cell_ drawingRectForBounds:bounds];
+
+  EXPECT_FALSE(NSIsEmptyRect(drawingRect));
+  EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1)));
+
+  [cell_ setActiveMatch:4 of:5];
+  textFrame = [cell_ textFrameForFrame:bounds];
+  drawingRect = [cell_ drawingRectForBounds:bounds];
+  EXPECT_FALSE(NSIsEmptyRect(drawingRect));
+  EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1)));
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm
new file mode 100644
index 0000000..836a82b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_text_field_unittest.mm
@@ -0,0 +1,92 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+
+// OCMock wants to mock a concrete class or protocol.  This should
+// provide a correct protocol for newer versions of the SDK, while
+// providing something mockable for older versions.
+
+@protocol MockTextEditingDelegate<NSControlTextEditingDelegate>
+- (void)controlTextDidBeginEditing:(NSNotification*)aNotification;
+- (BOOL)control:(NSControl*)control textShouldEndEditing:(NSText*)fieldEditor;
+@end
+
+namespace {
+
+// Width of the field so that we don't have to ask |field_| for it all
+// the time.
+static const CGFloat kWidth(300.0);
+
+class FindBarTextFieldTest : public CocoaTest {
+ public:
+  FindBarTextFieldTest() {
+    // Make sure this is wide enough to play games with the cell
+    // decorations.
+    NSRect frame = NSMakeRect(0, 0, kWidth, 30);
+    scoped_nsobject<FindBarTextField> field(
+        [[FindBarTextField alloc] initWithFrame:frame]);
+    field_ = field.get();
+
+    [field_ setStringValue:@"Test test"];
+    [[test_window() contentView] addSubview:field_];
+  }
+
+  FindBarTextField* field_;
+};
+
+// Basic view tests (AddRemove, Display).
+TEST_VIEW(FindBarTextFieldTest, field_);
+
+// Test that we have the right cell class.
+TEST_F(FindBarTextFieldTest, CellClass) {
+  EXPECT_TRUE([[field_ cell] isKindOfClass:[FindBarTextFieldCell class]]);
+}
+
+// Test that we get the same cell from -cell and
+// -findBarTextFieldCell.
+TEST_F(FindBarTextFieldTest, Cell) {
+  FindBarTextFieldCell* cell = [field_ findBarTextFieldCell];
+  EXPECT_EQ(cell, [field_ cell]);
+  EXPECT_TRUE(cell != nil);
+}
+
+// Test that becoming first responder sets things up correctly.
+TEST_F(FindBarTextFieldTest, FirstResponder) {
+  EXPECT_EQ(nil, [field_ currentEditor]);
+  EXPECT_EQ([[field_ subviews] count], 0U);
+  [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
+  EXPECT_FALSE(nil == [field_ currentEditor]);
+  EXPECT_EQ([[field_ subviews] count], 1U);
+  EXPECT_TRUE([[field_ currentEditor] isDescendantOf:field_]);
+}
+
+// Test drawing, mostly to ensure nothing leaks or crashes.
+TEST_F(FindBarTextFieldTest, Display) {
+  [field_ display];
+
+  // Test focussed drawing.
+  [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
+  [field_ display];
+  [test_window() clearPretendKeyWindowAndFirstResponder];
+
+  // Test display of various cell configurations.
+  FindBarTextFieldCell* cell = [field_ findBarTextFieldCell];
+  [cell setActiveMatch:4 of:5];
+  [field_ display];
+
+  [cell clearResults];
+  [field_ display];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_view.h b/chrome/browser/ui/cocoa/find_bar/find_bar_view.h
new file mode 100644
index 0000000..a3cc96b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_view.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_FIND_BAR_FIND_BAR_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_FIND_BAR_FIND_BAR_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/ui/cocoa/background_gradient_view.h"
+
+// A view that handles painting the border for the FindBar.
+
+@interface FindBarView : BackgroundGradientView {
+}
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_FIND_BAR_FIND_BAR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_view.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_view.mm
new file mode 100644
index 0000000..7883a1f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_view.mm
@@ -0,0 +1,131 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_view.h"
+
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/browser/ui/cocoa/url_drop_target.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+
+namespace {
+CGFloat kCurveSize = 8;
+}  // end namespace
+
+@implementation FindBarView
+
+- (void)awakeFromNib {
+  // Register for all the drag types handled by the RWHVCocoa.
+  [self registerForDraggedTypes:[URLDropTargetHandler handledDragTypes]];
+}
+
+- (void)drawRect:(NSRect)rect {
+  // TODO(rohitrao): Make this prettier.
+  rect = NSInsetRect([self bounds], 0.5, 0.5);
+  rect = NSOffsetRect(rect, 0, 1.0);
+
+  NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
+  NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
+  NSPoint midLeft1 =
+      NSMakePoint(NSMinX(rect) + kCurveSize, NSMaxY(rect) - kCurveSize);
+  NSPoint midLeft2 =
+      NSMakePoint(NSMinX(rect) + kCurveSize, NSMinY(rect) + kCurveSize);
+  NSPoint midRight1 =
+      NSMakePoint(NSMaxX(rect) - kCurveSize, NSMinY(rect) + kCurveSize);
+  NSPoint midRight2 =
+      NSMakePoint(NSMaxX(rect) - kCurveSize, NSMaxY(rect) - kCurveSize);
+  NSPoint bottomLeft =
+      NSMakePoint(NSMinX(rect) + (2 * kCurveSize), NSMinY(rect));
+  NSPoint bottomRight =
+      NSMakePoint(NSMaxX(rect) - (2 * kCurveSize), NSMinY(rect));
+
+  NSBezierPath* path = [NSBezierPath bezierPath];
+  [path moveToPoint:topLeft];
+  [path curveToPoint:midLeft1
+        controlPoint1:NSMakePoint(midLeft1.x, topLeft.y)
+        controlPoint2:NSMakePoint(midLeft1.x, topLeft.y)];
+  [path lineToPoint:midLeft2];
+  [path curveToPoint:bottomLeft
+        controlPoint1:NSMakePoint(midLeft2.x, bottomLeft.y)
+        controlPoint2:NSMakePoint(midLeft2.x, bottomLeft.y)];
+
+  [path lineToPoint:bottomRight];
+  [path curveToPoint:midRight1
+        controlPoint1:NSMakePoint(midRight1.x, bottomLeft.y)
+        controlPoint2:NSMakePoint(midRight1.x, bottomLeft.y)];
+  [path lineToPoint:midRight2];
+  [path curveToPoint:topRight
+        controlPoint1:NSMakePoint(midRight2.x, topLeft.y)
+        controlPoint2:NSMakePoint(midRight2.x, topLeft.y)];
+  NSGraphicsContext* context = [NSGraphicsContext currentContext];
+  [context saveGraphicsState];
+  [path addClip];
+
+  // Set the pattern phase
+  NSPoint phase = [[self window] themePatternPhase];
+
+  [context setPatternPhase:phase];
+  [super drawBackground];
+  [context restoreGraphicsState];
+
+  [[self strokeColor] set];
+  [path stroke];
+}
+
+// The findbar is mostly opaque, but has an 8px transparent border on the left
+// and right sides (see |kCurveSize|).  This is an artifact of the way it is
+// drawn.  We override hitTest to return nil for points in this transparent
+// area.
+- (NSView*)hitTest:(NSPoint)point {
+  NSView* hitView = [super hitTest:point];
+  if (hitView == self) {
+    // |rect| is approximately equivalent to the opaque area of the findbar.
+    NSRect rect = NSInsetRect([self bounds], kCurveSize, 0);
+    if (!NSMouseInRect(point, rect, [self isFlipped]))
+      return nil;
+  }
+
+  return hitView;
+}
+
+// Eat all mouse events, to prevent clicks from falling through to views below.
+- (void)mouseDown:(NSEvent *)theEvent {
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent {
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent {
+}
+
+- (void)mouseUp:(NSEvent *)theEvent {
+}
+
+- (void)rightMouseUp:(NSEvent *)theEvent {
+}
+
+- (void)otherMouseUp:(NSEvent *)theEvent {
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent {
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent {
+}
+
+- (void)rightMouseDragged:(NSEvent *)theEvent {
+}
+
+- (void)otherMouseDragged:(NSEvent *)theEvent {
+}
+
+// Eat drag operations, to prevent drags from going through to the views below.
+- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
+  return NSDragOperationNone;
+}
+
+- (ViewID)viewID {
+  return VIEW_ID_FIND_IN_PAGE;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm
new file mode 100644
index 0000000..ce80bec
--- /dev/null
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_view_unittest.mm
@@ -0,0 +1,90 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/find_bar/find_bar_view.h"
+#include "chrome/browser/ui/cocoa/test_event_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface MouseDownViewPong : NSView {
+  BOOL pong_;
+}
+@property (nonatomic, assign) BOOL pong;
+@end
+
+@implementation MouseDownViewPong
+@synthesize pong = pong_;
+- (void)mouseDown:(NSEvent*)event {
+  pong_ = YES;
+}
+@end
+
+
+namespace {
+
+class FindBarViewTest : public CocoaTest {
+ public:
+  FindBarViewTest() {
+    NSRect frame = NSMakeRect(0, 0, 100, 30);
+    scoped_nsobject<FindBarView> view(
+        [[FindBarView alloc] initWithFrame:frame]);
+    view_ = view.get();
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  FindBarView* view_;
+};
+
+TEST_VIEW(FindBarViewTest, view_)
+
+TEST_F(FindBarViewTest, FindBarEatsMouseClicksInBackgroundArea) {
+  scoped_nsobject<MouseDownViewPong> pongView(
+      [[MouseDownViewPong alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
+
+  // Remove all of the subviews of the findbar, to make sure we don't
+  // accidentally hit a subview when trying to simulate a click in the
+  // background area.
+  [view_ setSubviews:[NSArray array]];
+  [view_ setFrame:NSMakeRect(0, 0, 200, 200)];
+
+  // Add the pong view as a sibling of the findbar.
+  [[test_window() contentView] addSubview:pongView.get()
+                               positioned:NSWindowBelow
+                               relativeTo:view_];
+
+  // Synthesize a mousedown event and send it to the window.  The event is
+  // placed in the center of the find bar.
+  NSPoint pointInCenterOfFindBar = NSMakePoint(100, 100);
+  [pongView setPong:NO];
+  [test_window()
+      sendEvent:test_event_utils::LeftMouseDownAtPoint(pointInCenterOfFindBar)];
+  // Click gets eaten by findbar, not passed through to underlying view.
+  EXPECT_FALSE([pongView pong]);
+}
+
+TEST_F(FindBarViewTest, FindBarPassesThroughClicksInTransparentArea) {
+  scoped_nsobject<MouseDownViewPong> pongView(
+      [[MouseDownViewPong alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
+  [view_ setFrame:NSMakeRect(0, 0, 200, 200)];
+
+  // Add the pong view as a sibling of the findbar.
+  [[test_window() contentView] addSubview:pongView.get()
+                               positioned:NSWindowBelow
+                               relativeTo:view_];
+
+  // Synthesize a mousedown event and send it to the window.  The event is inset
+  // a few pixels from the lower left corner of the window, which places it in
+  // the transparent area surrounding the findbar.
+  NSPoint pointInTransparentArea = NSMakePoint(2, 2);
+  [pongView setPong:NO];
+  [test_window()
+      sendEvent:test_event_utils::LeftMouseDownAtPoint(pointInTransparentArea)];
+  // Click is ignored by findbar, passed through to underlying view.
+  EXPECT_TRUE([pongView pong]);
+}
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar_bridge.h b/chrome/browser/ui/cocoa/find_bar_bridge.h
deleted file mode 100644
index 2b8d83b..0000000
--- a/chrome/browser/ui/cocoa/find_bar_bridge.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_FIND_BAR_BRIDGE_H_
-#define CHROME_BROWSER_UI_COCOA_FIND_BAR_BRIDGE_H_
-#pragma once
-
-#include "base/logging.h"
-#include "chrome/browser/ui/find_bar/find_bar.h"
-
-class BrowserWindowCocoa;
-class FindBarController;
-
-// This class is included by find_bar_host_browsertest.cc, so it has to be
-// objc-free.
-#ifdef __OBJC__
-@class FindBarCocoaController;
-#else
-class FindBarCocoaController;
-#endif
-
-// Implementation of FindBar for the Mac.  This class simply passes
-// each message along to |cocoa_controller_|.
-//
-// The initialization here is a bit complicated.  FindBarBridge is
-// created by a static method in BrowserWindow.  The FindBarBridge
-// constructor creates a FindBarCocoaController, which in turn loads a
-// FindBarView from a nib file.  All of this is happening outside of
-// the main view hierarchy, so the static method also calls
-// BrowserWindowCocoa::AddFindBar() in order to add its FindBarView to
-// the cocoa views hierarchy.
-//
-// Memory ownership is relatively straightforward.  The FindBarBridge
-// object is owned by the Browser.  FindBarCocoaController is retained
-// by bother FindBarBridge and BrowserWindowController, since both use it.
-
-class FindBarBridge : public FindBar,
-                      public FindBarTesting {
- public:
-  FindBarBridge();
-  virtual ~FindBarBridge();
-
-  FindBarCocoaController* find_bar_cocoa_controller() {
-    return cocoa_controller_;
-  }
-
-  virtual void SetFindBarController(FindBarController* find_bar_controller) {
-    find_bar_controller_ = find_bar_controller;
-  }
-
-  virtual FindBarController* GetFindBarController() const {
-    DCHECK(find_bar_controller_);
-    return find_bar_controller_;
-  }
-
-  virtual FindBarTesting* GetFindBarTesting() {
-    return this;
-  }
-
-  // Methods from FindBar.
-  virtual void Show(bool animate);
-  virtual void Hide(bool animate);
-  virtual void SetFocusAndSelection();
-  virtual void ClearResults(const FindNotificationDetails& results);
-  virtual void StopAnimation();
-  virtual void SetFindText(const string16& find_text);
-  virtual void UpdateUIForFindResult(const FindNotificationDetails& result,
-                                     const string16& find_text);
-  virtual void AudibleAlert();
-  virtual bool IsFindBarVisible();
-  virtual void RestoreSavedFocus();
-  virtual void MoveWindowIfNecessary(const gfx::Rect& selection_rect,
-                                     bool no_redraw);
-
-  // Methods from FindBarTesting.
-  virtual bool GetFindBarWindowInfo(gfx::Point* position,
-                                    bool* fully_visible);
-  virtual string16 GetFindText();
-  virtual string16 GetFindSelectedText();
-  virtual string16 GetMatchCountText();
-
-  // Used to disable find bar animations when testing.
-  static bool disable_animations_during_testing_;
-
- private:
-  // Pointer to the cocoa controller which manages the cocoa view.  Is
-  // never nil.
-  FindBarCocoaController* cocoa_controller_;
-
-  // Pointer back to the owning controller.
-  FindBarController* find_bar_controller_;  // weak, owns us
-
-  DISALLOW_COPY_AND_ASSIGN(FindBarBridge);
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_FIND_BAR_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/find_bar_bridge.mm b/chrome/browser/ui/cocoa/find_bar_bridge.mm
deleted file mode 100644
index 9481b54..0000000
--- a/chrome/browser/ui/cocoa/find_bar_bridge.mm
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/find_bar_bridge.h"
-
-#include "base/sys_string_conversions.h"
-#import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
-
-// static
-bool FindBarBridge::disable_animations_during_testing_ = false;
-
-FindBarBridge::FindBarBridge()
-    : find_bar_controller_(NULL) {
-  cocoa_controller_ = [[FindBarCocoaController alloc] init];
-  [cocoa_controller_ setFindBarBridge:this];
-}
-
-FindBarBridge::~FindBarBridge() {
-  [cocoa_controller_ release];
-}
-
-void FindBarBridge::Show(bool animate) {
-  bool really_animate = animate && !disable_animations_during_testing_;
-  [cocoa_controller_ showFindBar:(really_animate ? YES : NO)];
-}
-
-void FindBarBridge::Hide(bool animate) {
-  bool really_animate = animate && !disable_animations_during_testing_;
-  [cocoa_controller_ hideFindBar:(really_animate ? YES : NO)];
-}
-
-void FindBarBridge::SetFocusAndSelection() {
-  [cocoa_controller_ setFocusAndSelection];
-}
-
-void FindBarBridge::ClearResults(const FindNotificationDetails& results) {
-  [cocoa_controller_ clearResults:results];
-}
-
-void FindBarBridge::SetFindText(const string16& find_text) {
-  [cocoa_controller_ setFindText:base::SysUTF16ToNSString(find_text)];
-}
-
-void FindBarBridge::UpdateUIForFindResult(const FindNotificationDetails& result,
-                                          const string16& find_text) {
-  [cocoa_controller_ updateUIForFindResult:result withText:find_text];
-}
-
-void FindBarBridge::AudibleAlert() {
-  // Beep beep, beep beep, Yeah!
-  NSBeep();
-}
-
-bool FindBarBridge::IsFindBarVisible() {
-  return [cocoa_controller_ isFindBarVisible] ? true : false;
-}
-
-void FindBarBridge::MoveWindowIfNecessary(const gfx::Rect& selection_rect,
-                                          bool no_redraw) {
-  // http://crbug.com/11084
-  // http://crbug.com/22036
-}
-
-void FindBarBridge::StopAnimation() {
-  [cocoa_controller_ stopAnimation];
-}
-
-void FindBarBridge::RestoreSavedFocus() {
-  [cocoa_controller_ restoreSavedFocus];
-}
-
-bool FindBarBridge::GetFindBarWindowInfo(gfx::Point* position,
-                                         bool* fully_visible) {
-  // TODO(rohitrao): Return the proper position.  http://crbug.com/22036
-  if (position)
-    *position = gfx::Point(0, 0);
-
-  NSWindow* window = [[cocoa_controller_ view] window];
-  bool window_visible = [window isVisible] ? true : false;
-  if (fully_visible) {
-    *fully_visible = window_visible &&
-        [cocoa_controller_ isFindBarVisible] &&
-        ![cocoa_controller_ isFindBarAnimating];
-  }
-  return window_visible;
-}
-
-string16 FindBarBridge::GetFindText() {
-  // This function is currently only used in Windows and Linux specific browser
-  // tests (testing prepopulate values that Mac's don't rely on), but if we add
-  // more tests that are non-platform specific, we need to flesh out this
-  // function.
-  NOTIMPLEMENTED();
-  return string16();
-}
-
-string16 FindBarBridge::GetFindSelectedText() {
-  // This function is currently only used in Windows and Linux specific browser
-  // tests (testing prepopulate values that Mac's don't rely on), but if we add
-  // more tests that are non-platform specific, we need to flesh out this
-  // function.
-  NOTIMPLEMENTED();
-  return string16();
-}
-
-string16 FindBarBridge::GetMatchCountText() {
-  // This function is currently only used in Windows and Linux specific browser
-  // tests (testing prepopulate values that Mac's don't rely on), but if we add
-  // more tests that are non-platform specific, we need to flesh out this
-  // function.
-  NOTIMPLEMENTED();
-  return string16();
-}
diff --git a/chrome/browser/ui/cocoa/find_bar_bridge_unittest.mm b/chrome/browser/ui/cocoa/find_bar_bridge_unittest.mm
deleted file mode 100644
index 421cb80..0000000
--- a/chrome/browser/ui/cocoa/find_bar_bridge_unittest.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "chrome/browser/ui/cocoa/find_bar_bridge.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
-
-namespace {
-
-class FindBarBridgeTest : public CocoaTest {
-};
-
-TEST_F(FindBarBridgeTest, Creation) {
-  // Make sure the FindBarBridge constructor doesn't crash and
-  // properly initializes its FindBarCocoaController.
-  FindBarBridge bridge;
-  EXPECT_TRUE(bridge.find_bar_cocoa_controller() != NULL);
-}
-
-TEST_F(FindBarBridgeTest, Accessors) {
-  // Get/SetFindBarController are virtual methods implemented in
-  // FindBarBridge, so we test them here.
-  FindBarBridge* bridge = new FindBarBridge();
-  FindBarController controller(bridge);  // takes ownership of |bridge|.
-  bridge->SetFindBarController(&controller);
-
-  EXPECT_EQ(&controller, bridge->GetFindBarController());
-}
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar_cocoa_controller.h b/chrome/browser/ui/cocoa/find_bar_cocoa_controller.h
deleted file mode 100644
index 289d89c..0000000
--- a/chrome/browser/ui/cocoa/find_bar_cocoa_controller.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
-
-#include "base/scoped_nsobject.h"
-#include "base/string16.h"
-
-class BrowserWindowCocoa;
-class FindBarBridge;
-@class FindBarTextField;
-class FindNotificationDetails;
-@class FocusTracker;
-
-// A controller for the find bar in the browser window.  Manages
-// updating the state of the find bar and provides a target for the
-// next/previous/close buttons.  Certain operations require a pointer
-// to the cross-platform FindBarController, so be sure to call
-// setFindBarBridge: after creating this controller.
-
-@interface FindBarCocoaController : NSViewController {
- @private
-  IBOutlet NSView* findBarView_;
-  IBOutlet FindBarTextField* findText_;
-  IBOutlet NSButton* nextButton_;
-  IBOutlet NSButton* previousButton_;
-
-  // Needed to call methods on FindBarController.
-  FindBarBridge* findBarBridge_;  // weak
-
-  scoped_nsobject<FocusTracker> focusTracker_;
-
-  // The currently-running animation.  This is defined to be non-nil if an
-  // animation is running, and is always nil otherwise.  The
-  // FindBarCocoaController should not be deallocated while an animation is
-  // running (stopAnimation is currently called before the last tab in a
-  // window is removed).
-  scoped_nsobject<NSViewAnimation> currentAnimation_;
-
-  // If YES, do nothing as a result of find pasteboard update notifications.
-  BOOL suppressPboardUpdateActions_;
-};
-
-// Initializes a new FindBarCocoaController.
-- (id)init;
-
-- (void)setFindBarBridge:(FindBarBridge*)findBar;
-
-- (IBAction)close:(id)sender;
-
-- (IBAction)nextResult:(id)sender;
-
-- (IBAction)previousResult:(id)sender;
-
-// Position the find bar at the given maximum y-coordinate (the min-y of the
-// bar -- toolbar + possibly bookmark bar, but not including the infobars) with
-// the given maximum width (i.e., the find bar should fit between 0 and
-// |maxWidth|).
-- (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth;
-
-// Methods called from FindBarBridge.
-- (void)showFindBar:(BOOL)animate;
-- (void)hideFindBar:(BOOL)animate;
-- (void)stopAnimation;
-- (void)setFocusAndSelection;
-- (void)restoreSavedFocus;
-- (void)setFindText:(NSString*)findText;
-
-- (void)clearResults:(const FindNotificationDetails&)results;
-- (void)updateUIForFindResult:(const FindNotificationDetails&)results
-                     withText:(const string16&)findText;
-- (BOOL)isFindBarVisible;
-- (BOOL)isFindBarAnimating;
-
-@end
diff --git a/chrome/browser/ui/cocoa/find_bar_cocoa_controller.mm b/chrome/browser/ui/cocoa/find_bar_cocoa_controller.mm
deleted file mode 100644
index f8a4044..0000000
--- a/chrome/browser/ui/cocoa/find_bar_cocoa_controller.mm
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
-#import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
-#import "chrome/browser/ui/cocoa/find_bar_bridge.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field_cell.h"
-#import "chrome/browser/ui/cocoa/find_pasteboard.h"
-#import "chrome/browser/ui/cocoa/focus_tracker.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
-
-namespace {
-const float kFindBarOpenDuration = 0.2;
-const float kFindBarCloseDuration = 0.15;
-}
-
-@interface FindBarCocoaController (PrivateMethods)
-// Returns the appropriate frame for a hidden find bar.
-- (NSRect)hiddenFindBarFrame;
-
-// Sets the frame of |findBarView_|.  |duration| is ignored if |animate| is NO.
-- (void)setFindBarFrame:(NSRect)endFrame
-                animate:(BOOL)animate
-               duration:(float)duration;
-
-// Optionally stops the current search, puts |text| into the find bar, and
-// enables the buttons, but doesn't start a new search for |text|.
-- (void)prepopulateText:(NSString*)text stopSearch:(BOOL)stopSearch;
-@end
-
-@implementation FindBarCocoaController
-
-- (id)init {
-  if ((self = [super initWithNibName:@"FindBar"
-                              bundle:base::mac::MainAppBundle()])) {
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(findPboardUpdated:)
-               name:kFindPasteboardChangedNotification
-             object:[FindPasteboard sharedInstance]];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  // All animations should be explicitly stopped by the TabContents before a tab
-  // is closed.
-  DCHECK(!currentAnimation_.get());
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [super dealloc];
-}
-
-- (void)setFindBarBridge:(FindBarBridge*)findBarBridge {
-  DCHECK(!findBarBridge_);  // should only be called once.
-  findBarBridge_ = findBarBridge;
-}
-
-- (void)awakeFromNib {
-  [findBarView_ setFrame:[self hiddenFindBarFrame]];
-
-  // Stopping the search requires a findbar controller, which isn't valid yet
-  // during setup. Furthermore, there is no active search yet anyway.
-  [self prepopulateText:[[FindPasteboard sharedInstance] findText]
-             stopSearch:NO];
-}
-
-- (IBAction)close:(id)sender {
-  if (findBarBridge_)
-    findBarBridge_->GetFindBarController()->EndFindSession(
-        FindBarController::kKeepSelection);
-}
-
-- (IBAction)previousResult:(id)sender {
-  if (findBarBridge_)
-    findBarBridge_->GetFindBarController()->tab_contents()->StartFinding(
-        base::SysNSStringToUTF16([findText_ stringValue]),
-        false, false);
-}
-
-- (IBAction)nextResult:(id)sender {
-  if (findBarBridge_)
-    findBarBridge_->GetFindBarController()->tab_contents()->StartFinding(
-        base::SysNSStringToUTF16([findText_ stringValue]),
-        true, false);
-}
-
-- (void)findPboardUpdated:(NSNotification*)notification {
-  if (suppressPboardUpdateActions_)
-    return;
-  [self prepopulateText:[[FindPasteboard sharedInstance] findText]
-             stopSearch:YES];
-}
-
-- (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth {
-  static const CGFloat kRightEdgeOffset = 25;
-  NSView* containerView = [self view];
-  CGFloat containerHeight = NSHeight([containerView frame]);
-  CGFloat containerWidth = NSWidth([containerView frame]);
-
-  // Adjust where we'll actually place the find bar.
-  CGFloat maxX = maxWidth - kRightEdgeOffset;
-  DLOG_IF(WARNING, maxX < 0) << "Window too narrow for find bar";
-  maxY += 1;
-
-  NSRect newFrame = NSMakeRect(maxX - containerWidth, maxY - containerHeight,
-                               containerWidth, containerHeight);
-  [containerView setFrame:newFrame];
-}
-
-// NSControl delegate method.
-- (void)controlTextDidChange:(NSNotification *)aNotification {
-  if (!findBarBridge_)
-    return;
-
-  TabContents* tab_contents =
-      findBarBridge_->GetFindBarController()->tab_contents();
-  if (!tab_contents)
-    return;
-
-  NSString* findText = [findText_ stringValue];
-  suppressPboardUpdateActions_ = YES;
-  [[FindPasteboard sharedInstance] setFindText:findText];
-  suppressPboardUpdateActions_ = NO;
-
-  if ([findText length] > 0) {
-    tab_contents->StartFinding(base::SysNSStringToUTF16(findText), true, false);
-  } else {
-    // The textbox is empty so we reset.
-    tab_contents->StopFinding(FindBarController::kClearSelection);
-    [self updateUIForFindResult:tab_contents->find_result()
-                       withText:string16()];
-  }
-}
-
-// NSControl delegate method
-- (BOOL)control:(NSControl*)control
-    textView:(NSTextView*)textView
-    doCommandBySelector:(SEL)command {
-  if (command == @selector(insertNewline:)) {
-    // Pressing Return
-    NSEvent* event = [NSApp currentEvent];
-
-    if ([event modifierFlags] & NSShiftKeyMask)
-      [previousButton_ performClick:nil];
-    else
-      [nextButton_ performClick:nil];
-
-    return YES;
-  } else if (command == @selector(insertLineBreak:)) {
-    // Pressing Ctrl-Return
-    if (findBarBridge_) {
-      findBarBridge_->GetFindBarController()->EndFindSession(
-          FindBarController::kActivateSelection);
-    }
-    return YES;
-  } else if (command == @selector(pageUp:) ||
-             command == @selector(pageUpAndModifySelection:) ||
-             command == @selector(scrollPageUp:) ||
-             command == @selector(pageDown:) ||
-             command == @selector(pageDownAndModifySelection:) ||
-             command == @selector(scrollPageDown:) ||
-             command == @selector(scrollToBeginningOfDocument:) ||
-             command == @selector(scrollToEndOfDocument:) ||
-             command == @selector(moveUp:) ||
-             command == @selector(moveDown:)) {
-    TabContents* contents =
-        findBarBridge_->GetFindBarController()->tab_contents();
-    if (!contents)
-      return NO;
-
-    // Sanity-check to make sure we got a keyboard event.
-    NSEvent* event = [NSApp currentEvent];
-    if ([event type] != NSKeyDown && [event type] != NSKeyUp)
-      return NO;
-
-    // Forward the event to the renderer.
-    // TODO(rohitrao): Should this call -[BaseView keyEvent:]?  Is there code in
-    // that function that we want to keep or avoid? Calling
-    // |ForwardKeyboardEvent()| directly ignores edit commands, which breaks
-    // cmd-up/down if we ever decide to include |moveToBeginningOfDocument:| in
-    // the list above.
-    RenderViewHost* render_view_host = contents->render_view_host();
-    render_view_host->ForwardKeyboardEvent(NativeWebKeyboardEvent(event));
-    return YES;
-  }
-
-  return NO;
-}
-
-// Methods from FindBar
-- (void)showFindBar:(BOOL)animate {
-  // Save the currently-focused view.  |findBarView_| is in the view
-  // hierarchy by now.  showFindBar can be called even when the
-  // findbar is already open, so do not overwrite an already saved
-  // view.
-  if (!focusTracker_.get())
-    focusTracker_.reset(
-        [[FocusTracker alloc] initWithWindow:[findBarView_ window]]);
-
-  // Animate the view into place.
-  NSRect frame = [findBarView_ frame];
-  frame.origin = NSMakePoint(0, 0);
-  [self setFindBarFrame:frame animate:animate duration:kFindBarOpenDuration];
-}
-
-- (void)hideFindBar:(BOOL)animate {
-  NSRect frame = [self hiddenFindBarFrame];
-  [self setFindBarFrame:frame animate:animate duration:kFindBarCloseDuration];
-}
-
-- (void)stopAnimation {
-  if (currentAnimation_.get()) {
-    [currentAnimation_ stopAnimation];
-    currentAnimation_.reset(nil);
-  }
-}
-
-- (void)setFocusAndSelection {
-  [[findText_ window] makeFirstResponder:findText_];
-
-  // Enable the buttons if the find text is non-empty.
-  BOOL buttonsEnabled = ([[findText_ stringValue] length] > 0) ? YES : NO;
-  [previousButton_ setEnabled:buttonsEnabled];
-  [nextButton_ setEnabled:buttonsEnabled];
-}
-
-- (void)restoreSavedFocus {
-  if (!(focusTracker_.get() &&
-        [focusTracker_ restoreFocusInWindow:[findBarView_ window]])) {
-    // Fall back to giving focus to the tab contents.
-    findBarBridge_->GetFindBarController()->tab_contents()->Focus();
-  }
-  focusTracker_.reset(nil);
-}
-
-- (void)setFindText:(NSString*)findText {
-  [findText_ setStringValue:findText];
-
-  // Make sure the text in the find bar always ends up in the find pasteboard
-  // (and, via notifications, in the other find bars too).
-  [[FindPasteboard sharedInstance] setFindText:findText];
-}
-
-- (void)clearResults:(const FindNotificationDetails&)results {
-  // Just call updateUIForFindResult, which will take care of clearing
-  // the search text and the results label.
-  [self updateUIForFindResult:results withText:string16()];
-}
-
-- (void)updateUIForFindResult:(const FindNotificationDetails&)result
-                     withText:(const string16&)findText {
-  // If we don't have any results and something was passed in, then
-  // that means someone pressed Cmd-G while the Find box was
-  // closed. In that case we need to repopulate the Find box with what
-  // was passed in.
-  if ([[findText_ stringValue] length] == 0 && !findText.empty()) {
-    [findText_ setStringValue:base::SysUTF16ToNSString(findText)];
-    [findText_ selectText:self];
-  }
-
-  // Make sure Find Next and Find Previous are enabled if we found any matches.
-  BOOL buttonsEnabled = result.number_of_matches() > 0 ? YES : NO;
-  [previousButton_ setEnabled:buttonsEnabled];
-  [nextButton_ setEnabled:buttonsEnabled];
-
-  // Update the results label.
-  BOOL validRange = result.active_match_ordinal() != -1 &&
-                    result.number_of_matches() != -1;
-  NSString* searchString = [findText_ stringValue];
-  if ([searchString length] > 0 && validRange) {
-    [[findText_ findBarTextFieldCell]
-        setActiveMatch:result.active_match_ordinal()
-                    of:result.number_of_matches()];
-  } else {
-    // If there was no text entered, we don't show anything in the results area.
-    [[findText_ findBarTextFieldCell] clearResults];
-  }
-
-  [findText_ resetFieldEditorFrameIfNeeded];
-
-  // If we found any results, reset the focus tracker, so we always
-  // restore focus to the tab contents.
-  if (result.number_of_matches() > 0)
-    focusTracker_.reset(nil);
-}
-
-- (BOOL)isFindBarVisible {
-  // Find bar is visible if any part of it is on the screen.
-  return NSIntersectsRect([[self view] bounds], [findBarView_ frame]);
-}
-
-- (BOOL)isFindBarAnimating {
-  return (currentAnimation_.get() != nil);
-}
-
-// NSAnimation delegate methods.
-- (void)animationDidEnd:(NSAnimation*)animation {
-  // Autorelease the animation (cannot use release because the animation object
-  // is still on the stack.
-  DCHECK(animation == currentAnimation_.get());
-  [currentAnimation_.release() autorelease];
-
-  // If the find bar is not visible, make it actually hidden, so it'll no longer
-  // respond to key events.
-  [findBarView_ setHidden:![self isFindBarVisible]];
-}
-
-@end
-
-@implementation FindBarCocoaController (PrivateMethods)
-
-- (NSRect)hiddenFindBarFrame {
-  NSRect frame = [findBarView_ frame];
-  NSRect containerBounds = [[self view] bounds];
-  frame.origin = NSMakePoint(NSMinX(containerBounds), NSMaxY(containerBounds));
-  return frame;
-}
-
-- (void)setFindBarFrame:(NSRect)endFrame
-                animate:(BOOL)animate
-               duration:(float)duration {
-  // Save the current frame.
-  NSRect startFrame = [findBarView_ frame];
-
-  // Stop any existing animations.
-  [currentAnimation_ stopAnimation];
-
-  if (!animate) {
-    [findBarView_ setFrame:endFrame];
-    [findBarView_ setHidden:![self isFindBarVisible]];
-    currentAnimation_.reset(nil);
-    return;
-  }
-
-  // If animating, ensure that the find bar is not hidden. Hidden status will be
-  // updated at the end of the animation.
-  [findBarView_ setHidden:NO];
-
-  // Reset the frame to what was saved above.
-  [findBarView_ setFrame:startFrame];
-  NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
-      findBarView_, NSViewAnimationTargetKey,
-      [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil];
-
-  currentAnimation_.reset(
-      [[NSViewAnimation alloc]
-        initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]);
-  [currentAnimation_ gtm_setDuration:duration
-                           eventMask:NSLeftMouseUpMask];
-  [currentAnimation_ setDelegate:self];
-  [currentAnimation_ startAnimation];
-}
-
-- (void)prepopulateText:(NSString*)text stopSearch:(BOOL)stopSearch{
-  [self setFindText:text];
-
-  // End the find session, hide the "x of y" text and disable the
-  // buttons, but do not close the find bar or raise the window here.
-  if (stopSearch && findBarBridge_) {
-    TabContents* contents =
-        findBarBridge_->GetFindBarController()->tab_contents();
-    if (contents) {
-      contents->StopFinding(FindBarController::kClearSelection);
-      findBarBridge_->ClearResults(contents->find_result());
-    }
-  }
-
-  // Has to happen after |ClearResults()| above.
-  BOOL buttonsEnabled = [text length] > 0 ? YES : NO;
-  [previousButton_ setEnabled:buttonsEnabled];
-  [nextButton_ setEnabled:buttonsEnabled];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/find_bar_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/find_bar_cocoa_controller_unittest.mm
deleted file mode 100644
index d7869c2..0000000
--- a/chrome/browser/ui/cocoa/find_bar_cocoa_controller_unittest.mm
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/browser_window.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
-#import "chrome/browser/ui/cocoa/find_pasteboard.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field.h"
-#include "chrome/browser/ui/find_bar/find_notification_details.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-// Expose private variables to make testing easier.
-@interface FindBarCocoaController(Testing)
-- (NSView*)findBarView;
-- (NSString*)findText;
-- (FindBarTextField*)findTextField;
-@end
-
-@implementation FindBarCocoaController(Testing)
-- (NSView*)findBarView {
-  return findBarView_;
-}
-
-- (NSString*)findText {
-  return [findText_ stringValue];
-}
-
-- (FindBarTextField*)findTextField {
-  return findText_;
-}
-
-- (NSButton*)nextButton {
-  return nextButton_;
-}
-
-- (NSButton*)previousButton {
-  return previousButton_;
-}
-@end
-
-namespace {
-
-class FindBarCocoaControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    controller_.reset([[FindBarCocoaController alloc] init]);
-    [[test_window() contentView] addSubview:[controller_ view]];
-  }
-
- protected:
-  scoped_nsobject<FindBarCocoaController> controller_;
-};
-
-TEST_VIEW(FindBarCocoaControllerTest, [controller_ view])
-
-TEST_F(FindBarCocoaControllerTest, ImagesLoadedProperly) {
-  EXPECT_TRUE([[[controller_ nextButton] image] isValid]);
-  EXPECT_TRUE([[[controller_ previousButton] image] isValid]);
-}
-
-TEST_F(FindBarCocoaControllerTest, ShowAndHide) {
-  NSView* findBarView = [controller_ findBarView];
-
-  ASSERT_GT([findBarView frame].origin.y, 0);
-  ASSERT_FALSE([controller_ isFindBarVisible]);
-
-  [controller_ showFindBar:NO];
-  EXPECT_EQ([findBarView frame].origin.y, 0);
-  EXPECT_TRUE([controller_ isFindBarVisible]);
-
-  [controller_ hideFindBar:NO];
-  EXPECT_GT([findBarView frame].origin.y, 0);
-  EXPECT_FALSE([controller_ isFindBarVisible]);
-}
-
-TEST_F(FindBarCocoaControllerTest, SetFindText) {
-  NSTextField* findTextField = [controller_ findTextField];
-
-  // Start by making the find bar visible.
-  [controller_ showFindBar:NO];
-  EXPECT_TRUE([controller_ isFindBarVisible]);
-
-  // Set the find text.
-  NSString* const kFindText = @"Google";
-  [controller_ setFindText:kFindText];
-  EXPECT_EQ(
-      NSOrderedSame,
-      [[findTextField stringValue] compare:kFindText]);
-
-  // Call clearResults, which doesn't actually clear the find text but
-  // simply sets it back to what it was before.  This is silly, but
-  // matches the behavior on other platforms.  |details| isn't used by
-  // our implementation of clearResults, so it's ok to pass in an
-  // empty |details|.
-  FindNotificationDetails details;
-  [controller_ clearResults:details];
-  EXPECT_EQ(
-      NSOrderedSame,
-      [[findTextField stringValue] compare:kFindText]);
-}
-
-TEST_F(FindBarCocoaControllerTest, ResultLabelUpdatesCorrectly) {
-  // TODO(rohitrao): Test this.  It may involve creating some dummy
-  // FindNotificationDetails objects.
-}
-
-TEST_F(FindBarCocoaControllerTest, FindTextIsGlobal) {
-  scoped_nsobject<FindBarCocoaController> otherController(
-      [[FindBarCocoaController alloc] init]);
-  [[test_window() contentView] addSubview:[otherController view]];
-
-  // Setting the text in one controller should update the other controller's
-  // text as well.
-  NSString* const kFindText = @"Respect to the man in the ice cream van";
-  [controller_ setFindText:kFindText];
-  EXPECT_EQ(
-      NSOrderedSame,
-      [[controller_ findText] compare:kFindText]);
-  EXPECT_EQ(
-      NSOrderedSame,
-      [[otherController.get() findText] compare:kFindText]);
-}
-
-TEST_F(FindBarCocoaControllerTest, SettingFindTextUpdatesFindPboard) {
-  NSString* const kFindText =
-      @"It's not a bird, it's not a plane, it must be Dave who's on the train";
-  [controller_ setFindText:kFindText];
-  EXPECT_EQ(
-      NSOrderedSame,
-      [[[FindPasteboard sharedInstance] findText] compare:kFindText]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar_text_field.mm b/chrome/browser/ui/cocoa/find_bar_text_field.mm
deleted file mode 100644
index 805fca3..0000000
--- a/chrome/browser/ui/cocoa/find_bar_text_field.mm
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/find_bar_text_field.h"
-
-#include "base/logging.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field_cell.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-
-@implementation FindBarTextField
-
-+ (Class)cellClass {
-  return [FindBarTextFieldCell class];
-}
-
-- (void)awakeFromNib {
-  DCHECK([[self cell] isKindOfClass:[FindBarTextFieldCell class]]);
-
-  [self registerForDraggedTypes:
-          [NSArray arrayWithObjects:NSStringPboardType, nil]];
-}
-
-- (FindBarTextFieldCell*)findBarTextFieldCell {
-  DCHECK([[self cell] isKindOfClass:[FindBarTextFieldCell class]]);
-  return static_cast<FindBarTextFieldCell*>([self cell]);
-}
-
-- (ViewID)viewID {
-  return VIEW_ID_FIND_IN_PAGE_TEXT_FIELD;
-}
-
-- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
-  // When a drag enters the text field, focus the field.  This will swap in the
-  // field editor, which will then handle the drag itself.
-  [[self window] makeFirstResponder:self];
-  return NSDragOperationNone;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/find_bar_text_field_cell.mm b/chrome/browser/ui/cocoa/find_bar_text_field_cell.mm
deleted file mode 100644
index 3f93766..0000000
--- a/chrome/browser/ui/cocoa/find_bar_text_field_cell.mm
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/find_bar_text_field_cell.h"
-
-#include "app/l10n_util.h"
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-const CGFloat kBaselineAdjust = 1.0;
-
-// How far to offset the keyword token into the field.
-const NSInteger kResultsXOffset = 3;
-
-// How much width (beyond text) to add to the keyword token on each
-// side.
-const NSInteger kResultsTokenInset = 3;
-
-// How far to shift bounding box of hint down from top of field.
-// Assumes -setFlipped:YES.
-const NSInteger kResultsYOffset = 4;
-
-// How far the editor insets itself, for purposes of determining if
-// decorations need to be trimmed.
-const CGFloat kEditorHorizontalInset = 3.0;
-
-// Conveniences to centralize width+offset calculations.
-CGFloat WidthForResults(NSAttributedString* resultsString) {
-  return kResultsXOffset + ceil([resultsString size].width) +
-      2 * kResultsTokenInset;
-}
-
-}  // namespace
-
-@implementation FindBarTextFieldCell
-
-- (CGFloat)baselineAdjust {
-  return kBaselineAdjust;
-}
-
-- (CGFloat)cornerRadius {
-  return 4.0;
-}
-
-- (StyledTextFieldCellRoundedFlags)roundedFlags {
-  return StyledTextFieldCellRoundedLeft;
-}
-
-// @synthesize doesn't seem to compile for this transition.
-- (NSAttributedString*)resultsString {
-  return resultsString_.get();
-}
-
-// Convenience for the attributes used in the right-justified info
-// cells.  Sets the background color to red if |foundMatches| is YES.
-- (NSDictionary*)resultsAttributes:(BOOL)foundMatches {
-  scoped_nsobject<NSMutableParagraphStyle> style(
-      [[NSMutableParagraphStyle alloc] init]);
-  [style setAlignment:NSRightTextAlignment];
-
-  return [NSDictionary dictionaryWithObjectsAndKeys:
-              [self font], NSFontAttributeName,
-              [NSColor lightGrayColor], NSForegroundColorAttributeName,
-              [NSColor whiteColor], NSBackgroundColorAttributeName,
-              style.get(), NSParagraphStyleAttributeName,
-              nil];
-}
-
-- (void)setActiveMatch:(NSInteger)current of:(NSInteger)total {
-  NSString* results =
-      base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
-          IDS_FIND_IN_PAGE_COUNT,
-          base::IntToString16(current),
-          base::IntToString16(total)));
-  resultsString_.reset([[NSAttributedString alloc]
-                         initWithString:results
-                         attributes:[self resultsAttributes:(total > 0)]]);
-}
-
-- (void)clearResults {
-  resultsString_.reset(nil);
-}
-
-- (NSRect)textFrameForFrame:(NSRect)cellFrame {
-  NSRect textFrame([super textFrameForFrame:cellFrame]);
-  if (resultsString_)
-    textFrame.size.width -= WidthForResults(resultsString_);
-  return textFrame;
-}
-
-// Do not show the I-beam cursor over the results label.
-- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame {
-  return [self textFrameForFrame:cellFrame];
-}
-
-- (void)drawResultsWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
-  DCHECK(resultsString_);
-
-  NSRect textFrame = [self textFrameForFrame:cellFrame];
-  NSRect infoFrame(NSMakeRect(NSMaxX(textFrame),
-                              cellFrame.origin.y + kResultsYOffset,
-                              ceil([resultsString_ size].width),
-                              cellFrame.size.height - kResultsYOffset));
-  [resultsString_.get() drawInRect:infoFrame];
-}
-
-- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
-  if (resultsString_)
-    [self drawResultsWithFrame:cellFrame inView:controlView];
-  [super drawInteriorWithFrame:cellFrame inView:controlView];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/find_bar_text_field_cell_unittest.mm b/chrome/browser/ui/cocoa/find_bar_text_field_cell_unittest.mm
deleted file mode 100644
index 1448632..0000000
--- a/chrome/browser/ui/cocoa/find_bar_text_field_cell_unittest.mm
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field_cell.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface FindBarTextFieldCell (ExposedForTesting)
-- (NSAttributedString*)resultsString;
-@end
-
-@implementation FindBarTextFieldCell (ExposedForTesting)
-- (NSAttributedString*)resultsString {
-  return resultsString_.get();
-}
-@end
-
-namespace {
-
-// Width of the field so that we don't have to ask |field_| for it all
-// the time.
-const CGFloat kWidth(300.0);
-
-// A narrow width for tests which test things that don't fit.
-const CGFloat kNarrowWidth(5.0);
-
-class FindBarTextFieldCellTest : public CocoaTest {
- public:
-  FindBarTextFieldCellTest() {
-    // Make sure this is wide enough to play games with the cell
-    // decorations.
-    const NSRect frame = NSMakeRect(0, 0, kWidth, 30);
-
-    scoped_nsobject<FindBarTextFieldCell> cell(
-        [[FindBarTextFieldCell alloc] initTextCell:@"Testing"]);
-    cell_ = cell;
-    [cell_ setEditable:YES];
-    [cell_ setBordered:YES];
-
-    scoped_nsobject<NSTextField> view(
-        [[NSTextField alloc] initWithFrame:frame]);
-    view_ = view;
-    [view_ setCell:cell_];
-
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  NSTextField* view_;
-  FindBarTextFieldCell* cell_;
-};
-
-// Basic view tests (AddRemove, Display).
-TEST_VIEW(FindBarTextFieldCellTest, view_);
-
-// Test drawing, mostly to ensure nothing leaks or crashes.
-TEST_F(FindBarTextFieldCellTest, FocusedDisplay) {
-  [view_ display];
-
-  // Test focused drawing.
-  [test_window() makePretendKeyWindowAndSetFirstResponder:view_];
-  [view_ display];
-  [test_window() clearPretendKeyWindowAndFirstResponder];
-
-  // Test display of various cell configurations.
-  [cell_ setActiveMatch:4 of:30];
-  [view_ display];
-
-  [cell_ setActiveMatch:0 of:0];
-  [view_ display];
-
-  [cell_ clearResults];
-  [view_ display];
-}
-
-// Verify that setting and clearing the find results changes the results string
-// appropriately.
-TEST_F(FindBarTextFieldCellTest, SetAndClearFindResults) {
-  [cell_ setActiveMatch:10 of:30];
-  scoped_nsobject<NSAttributedString> tenString([[cell_ resultsString] copy]);
-  EXPECT_GT([tenString length], 0U);
-
-  [cell_ setActiveMatch:0 of:0];
-  scoped_nsobject<NSAttributedString> zeroString([[cell_ resultsString] copy]);
-  EXPECT_GT([zeroString length], 0U);
-  EXPECT_FALSE([tenString isEqualToAttributedString:zeroString]);
-
-  [cell_ clearResults];
-  EXPECT_EQ(0U, [[cell_ resultsString] length]);
-}
-
-TEST_F(FindBarTextFieldCellTest, TextFrame) {
-  const NSRect bounds = [view_ bounds];
-  NSRect textFrame = [cell_ textFrameForFrame:bounds];
-  NSRect cursorFrame = [cell_ textCursorFrameForFrame:bounds];
-
-  // At default settings, everything goes to the text area.
-  EXPECT_FALSE(NSIsEmptyRect(textFrame));
-  EXPECT_TRUE(NSContainsRect(bounds, textFrame));
-  EXPECT_EQ(NSMinX(bounds), NSMinX(textFrame));
-  EXPECT_EQ(NSMaxX(bounds), NSMaxX(textFrame));
-  EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame));
-
-  // Setting an active match leaves text frame to left.
-  [cell_ setActiveMatch:4 of:5];
-  textFrame = [cell_ textFrameForFrame:bounds];
-  cursorFrame = [cell_ textCursorFrameForFrame:bounds];
-  EXPECT_FALSE(NSIsEmptyRect(textFrame));
-  EXPECT_TRUE(NSContainsRect(bounds, textFrame));
-  EXPECT_LT(NSMaxX(textFrame), NSMaxX(bounds));
-  EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame));
-
-}
-
-// The editor frame should be slightly inset from the text frame.
-TEST_F(FindBarTextFieldCellTest, DrawingRectForBounds) {
-  const NSRect bounds = [view_ bounds];
-  NSRect textFrame = [cell_ textFrameForFrame:bounds];
-  NSRect drawingRect = [cell_ drawingRectForBounds:bounds];
-
-  EXPECT_FALSE(NSIsEmptyRect(drawingRect));
-  EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1)));
-
-  [cell_ setActiveMatch:4 of:5];
-  textFrame = [cell_ textFrameForFrame:bounds];
-  drawingRect = [cell_ drawingRectForBounds:bounds];
-  EXPECT_FALSE(NSIsEmptyRect(drawingRect));
-  EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1)));
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar_text_field_unittest.mm b/chrome/browser/ui/cocoa/find_bar_text_field_unittest.mm
deleted file mode 100644
index 382a870..0000000
--- a/chrome/browser/ui/cocoa/find_bar_text_field_unittest.mm
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field.h"
-#import "chrome/browser/ui/cocoa/find_bar_text_field_cell.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-
-// OCMock wants to mock a concrete class or protocol.  This should
-// provide a correct protocol for newer versions of the SDK, while
-// providing something mockable for older versions.
-
-@protocol MockTextEditingDelegate<NSControlTextEditingDelegate>
-- (void)controlTextDidBeginEditing:(NSNotification*)aNotification;
-- (BOOL)control:(NSControl*)control textShouldEndEditing:(NSText*)fieldEditor;
-@end
-
-namespace {
-
-// Width of the field so that we don't have to ask |field_| for it all
-// the time.
-static const CGFloat kWidth(300.0);
-
-class FindBarTextFieldTest : public CocoaTest {
- public:
-  FindBarTextFieldTest() {
-    // Make sure this is wide enough to play games with the cell
-    // decorations.
-    NSRect frame = NSMakeRect(0, 0, kWidth, 30);
-    scoped_nsobject<FindBarTextField> field(
-        [[FindBarTextField alloc] initWithFrame:frame]);
-    field_ = field.get();
-
-    [field_ setStringValue:@"Test test"];
-    [[test_window() contentView] addSubview:field_];
-  }
-
-  FindBarTextField* field_;
-};
-
-// Basic view tests (AddRemove, Display).
-TEST_VIEW(FindBarTextFieldTest, field_);
-
-// Test that we have the right cell class.
-TEST_F(FindBarTextFieldTest, CellClass) {
-  EXPECT_TRUE([[field_ cell] isKindOfClass:[FindBarTextFieldCell class]]);
-}
-
-// Test that we get the same cell from -cell and
-// -findBarTextFieldCell.
-TEST_F(FindBarTextFieldTest, Cell) {
-  FindBarTextFieldCell* cell = [field_ findBarTextFieldCell];
-  EXPECT_EQ(cell, [field_ cell]);
-  EXPECT_TRUE(cell != nil);
-}
-
-// Test that becoming first responder sets things up correctly.
-TEST_F(FindBarTextFieldTest, FirstResponder) {
-  EXPECT_EQ(nil, [field_ currentEditor]);
-  EXPECT_EQ([[field_ subviews] count], 0U);
-  [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
-  EXPECT_FALSE(nil == [field_ currentEditor]);
-  EXPECT_EQ([[field_ subviews] count], 1U);
-  EXPECT_TRUE([[field_ currentEditor] isDescendantOf:field_]);
-}
-
-// Test drawing, mostly to ensure nothing leaks or crashes.
-TEST_F(FindBarTextFieldTest, Display) {
-  [field_ display];
-
-  // Test focussed drawing.
-  [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
-  [field_ display];
-  [test_window() clearPretendKeyWindowAndFirstResponder];
-
-  // Test display of various cell configurations.
-  FindBarTextFieldCell* cell = [field_ findBarTextFieldCell];
-  [cell setActiveMatch:4 of:5];
-  [field_ display];
-
-  [cell clearResults];
-  [field_ display];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/find_bar_view.h b/chrome/browser/ui/cocoa/find_bar_view.h
deleted file mode 100644
index ff5753d..0000000
--- a/chrome/browser/ui/cocoa/find_bar_view.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_FIND_BAR_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_FIND_BAR_VIEW_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "chrome/browser/ui/cocoa/background_gradient_view.h"
-
-// A view that handles painting the border for the FindBar.
-
-@interface FindBarView : BackgroundGradientView {
-}
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_FIND_BAR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/find_bar_view.mm b/chrome/browser/ui/cocoa/find_bar_view.mm
deleted file mode 100644
index 5e1ce21..0000000
--- a/chrome/browser/ui/cocoa/find_bar_view.mm
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/find_bar_view.h"
-
-#import "chrome/browser/ui/cocoa/themed_window.h"
-#import "chrome/browser/ui/cocoa/url_drop_target.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-
-namespace {
-CGFloat kCurveSize = 8;
-}  // end namespace
-
-@implementation FindBarView
-
-- (void)awakeFromNib {
-  // Register for all the drag types handled by the RWHVCocoa.
-  [self registerForDraggedTypes:[URLDropTargetHandler handledDragTypes]];
-}
-
-- (void)drawRect:(NSRect)rect {
-  // TODO(rohitrao): Make this prettier.
-  rect = NSInsetRect([self bounds], 0.5, 0.5);
-  rect = NSOffsetRect(rect, 0, 1.0);
-
-  NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
-  NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
-  NSPoint midLeft1 =
-      NSMakePoint(NSMinX(rect) + kCurveSize, NSMaxY(rect) - kCurveSize);
-  NSPoint midLeft2 =
-      NSMakePoint(NSMinX(rect) + kCurveSize, NSMinY(rect) + kCurveSize);
-  NSPoint midRight1 =
-      NSMakePoint(NSMaxX(rect) - kCurveSize, NSMinY(rect) + kCurveSize);
-  NSPoint midRight2 =
-      NSMakePoint(NSMaxX(rect) - kCurveSize, NSMaxY(rect) - kCurveSize);
-  NSPoint bottomLeft =
-      NSMakePoint(NSMinX(rect) + (2 * kCurveSize), NSMinY(rect));
-  NSPoint bottomRight =
-      NSMakePoint(NSMaxX(rect) - (2 * kCurveSize), NSMinY(rect));
-
-  NSBezierPath* path = [NSBezierPath bezierPath];
-  [path moveToPoint:topLeft];
-  [path curveToPoint:midLeft1
-        controlPoint1:NSMakePoint(midLeft1.x, topLeft.y)
-        controlPoint2:NSMakePoint(midLeft1.x, topLeft.y)];
-  [path lineToPoint:midLeft2];
-  [path curveToPoint:bottomLeft
-        controlPoint1:NSMakePoint(midLeft2.x, bottomLeft.y)
-        controlPoint2:NSMakePoint(midLeft2.x, bottomLeft.y)];
-
-  [path lineToPoint:bottomRight];
-  [path curveToPoint:midRight1
-        controlPoint1:NSMakePoint(midRight1.x, bottomLeft.y)
-        controlPoint2:NSMakePoint(midRight1.x, bottomLeft.y)];
-  [path lineToPoint:midRight2];
-  [path curveToPoint:topRight
-        controlPoint1:NSMakePoint(midRight2.x, topLeft.y)
-        controlPoint2:NSMakePoint(midRight2.x, topLeft.y)];
-  NSGraphicsContext* context = [NSGraphicsContext currentContext];
-  [context saveGraphicsState];
-  [path addClip];
-
-  // Set the pattern phase
-  NSPoint phase = [[self window] themePatternPhase];
-
-  [context setPatternPhase:phase];
-  [super drawBackground];
-  [context restoreGraphicsState];
-
-  [[self strokeColor] set];
-  [path stroke];
-}
-
-// The findbar is mostly opaque, but has an 8px transparent border on the left
-// and right sides (see |kCurveSize|).  This is an artifact of the way it is
-// drawn.  We override hitTest to return nil for points in this transparent
-// area.
-- (NSView*)hitTest:(NSPoint)point {
-  NSView* hitView = [super hitTest:point];
-  if (hitView == self) {
-    // |rect| is approximately equivalent to the opaque area of the findbar.
-    NSRect rect = NSInsetRect([self bounds], kCurveSize, 0);
-    if (!NSMouseInRect(point, rect, [self isFlipped]))
-      return nil;
-  }
-
-  return hitView;
-}
-
-// Eat all mouse events, to prevent clicks from falling through to views below.
-- (void)mouseDown:(NSEvent *)theEvent {
-}
-
-- (void)rightMouseDown:(NSEvent *)theEvent {
-}
-
-- (void)otherMouseDown:(NSEvent *)theEvent {
-}
-
-- (void)mouseUp:(NSEvent *)theEvent {
-}
-
-- (void)rightMouseUp:(NSEvent *)theEvent {
-}
-
-- (void)otherMouseUp:(NSEvent *)theEvent {
-}
-
-- (void)mouseMoved:(NSEvent *)theEvent {
-}
-
-- (void)mouseDragged:(NSEvent *)theEvent {
-}
-
-- (void)rightMouseDragged:(NSEvent *)theEvent {
-}
-
-- (void)otherMouseDragged:(NSEvent *)theEvent {
-}
-
-// Eat drag operations, to prevent drags from going through to the views below.
-- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
-  return NSDragOperationNone;
-}
-
-- (ViewID)viewID {
-  return VIEW_ID_FIND_IN_PAGE;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/find_bar_view_unittest.mm b/chrome/browser/ui/cocoa/find_bar_view_unittest.mm
deleted file mode 100644
index 639b5ef..0000000
--- a/chrome/browser/ui/cocoa/find_bar_view_unittest.mm
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/find_bar_view.h"
-#include "chrome/browser/ui/cocoa/test_event_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface MouseDownViewPong : NSView {
-  BOOL pong_;
-}
-@property (nonatomic, assign) BOOL pong;
-@end
-
-@implementation MouseDownViewPong
-@synthesize pong = pong_;
-- (void)mouseDown:(NSEvent*)event {
-  pong_ = YES;
-}
-@end
-
-
-namespace {
-
-class FindBarViewTest : public CocoaTest {
- public:
-  FindBarViewTest() {
-    NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<FindBarView> view(
-        [[FindBarView alloc] initWithFrame:frame]);
-    view_ = view.get();
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  FindBarView* view_;
-};
-
-TEST_VIEW(FindBarViewTest, view_)
-
-TEST_F(FindBarViewTest, FindBarEatsMouseClicksInBackgroundArea) {
-  scoped_nsobject<MouseDownViewPong> pongView(
-      [[MouseDownViewPong alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
-
-  // Remove all of the subviews of the findbar, to make sure we don't
-  // accidentally hit a subview when trying to simulate a click in the
-  // background area.
-  [view_ setSubviews:[NSArray array]];
-  [view_ setFrame:NSMakeRect(0, 0, 200, 200)];
-
-  // Add the pong view as a sibling of the findbar.
-  [[test_window() contentView] addSubview:pongView.get()
-                               positioned:NSWindowBelow
-                               relativeTo:view_];
-
-  // Synthesize a mousedown event and send it to the window.  The event is
-  // placed in the center of the find bar.
-  NSPoint pointInCenterOfFindBar = NSMakePoint(100, 100);
-  [pongView setPong:NO];
-  [test_window()
-      sendEvent:test_event_utils::LeftMouseDownAtPoint(pointInCenterOfFindBar)];
-  // Click gets eaten by findbar, not passed through to underlying view.
-  EXPECT_FALSE([pongView pong]);
-}
-
-TEST_F(FindBarViewTest, FindBarPassesThroughClicksInTransparentArea) {
-  scoped_nsobject<MouseDownViewPong> pongView(
-      [[MouseDownViewPong alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
-  [view_ setFrame:NSMakeRect(0, 0, 200, 200)];
-
-  // Add the pong view as a sibling of the findbar.
-  [[test_window() contentView] addSubview:pongView.get()
-                               positioned:NSWindowBelow
-                               relativeTo:view_];
-
-  // Synthesize a mousedown event and send it to the window.  The event is inset
-  // a few pixels from the lower left corner of the window, which places it in
-  // the transparent area surrounding the findbar.
-  NSPoint pointInTransparentArea = NSMakePoint(2, 2);
-  [pongView setPong:NO];
-  [test_window()
-      sendEvent:test_event_utils::LeftMouseDownAtPoint(pointInTransparentArea)];
-  // Click is ignored by findbar, passed through to underlying view.
-  EXPECT_TRUE([pongView pong]);
-}
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/first_run_bubble_controller.mm b/chrome/browser/ui/cocoa/first_run_bubble_controller.mm
index d4fa202..2c68cdc 100644
--- a/chrome/browser/ui/cocoa/first_run_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/first_run_bubble_controller.mm
@@ -4,13 +4,13 @@
 
 #import "chrome/browser/ui/cocoa/first_run_bubble_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/search_engines/util.h"
 #import "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 @interface FirstRunBubbleController(Private)
 - (id)initRelativeToView:(NSView*)view
diff --git a/chrome/browser/ui/cocoa/first_run_dialog.mm b/chrome/browser/ui/cocoa/first_run_dialog.mm
index dae3e4e..2771dea 100644
--- a/chrome/browser/ui/cocoa/first_run_dialog.mm
+++ b/chrome/browser/ui/cocoa/first_run_dialog.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/first_run_dialog.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/mac/mac_util.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
@@ -14,6 +13,7 @@
 #include "googleurl/src/gurl.h"
 #include "grit/locale_settings.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @interface FirstRunDialogController (PrivateMethods)
 // Show the dialog.
diff --git a/chrome/browser/ui/cocoa/font_language_settings_controller.mm b/chrome/browser/ui/cocoa/font_language_settings_controller.mm
deleted file mode 100644
index 9bb9c6b..0000000
--- a/chrome/browser/ui/cocoa/font_language_settings_controller.mm
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/font_language_settings_controller.h"
-
-#import <Cocoa/Cocoa.h>
-#import "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/character_encoding.h"
-#include "chrome/browser/fonts_languages_window.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-
-NSString* const kCharacterInfoEncoding = @"encoding";
-NSString* const kCharacterInfoName = @"name";
-NSString* const kCharacterInfoID = @"id";
-
-void ShowFontsLanguagesWindow(gfx::NativeWindow window,
-                              FontsLanguagesPage page,
-                              Profile* profile) {
-  NOTIMPLEMENTED();
-}
-
-@interface FontLanguageSettingsController (Private)
-- (void)updateDisplayField:(NSTextField*)field
-                  withFont:(NSFont*)font
-                 withLabel:(NSTextField*)label;
-@end
-
-@implementation FontLanguageSettingsController
-
-- (id)initWithProfile:(Profile*)profile {
-  DCHECK(profile);
-  NSString* nibpath = [base::mac::MainAppBundle()
-                        pathForResource:@"FontLanguageSettings"
-                                 ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    profile_ = profile;
-
-    // Convert the name/size preference values to NSFont objects.
-    serifName_.Init(prefs::kWebKitSerifFontFamily, profile->GetPrefs(), NULL);
-    serifSize_.Init(prefs::kWebKitDefaultFontSize, profile->GetPrefs(), NULL);
-    NSString* serif = base::SysUTF8ToNSString(serifName_.GetValue());
-    serifFont_.reset(
-        [[NSFont fontWithName:serif size:serifSize_.GetValue()] retain]);
-
-    sansSerifName_.Init(prefs::kWebKitSansSerifFontFamily, profile->GetPrefs(),
-                        NULL);
-    sansSerifSize_.Init(prefs::kWebKitDefaultFontSize, profile->GetPrefs(),
-                        NULL);
-    NSString* sansSerif = base::SysUTF8ToNSString(sansSerifName_.GetValue());
-    sansSerifFont_.reset(
-        [[NSFont fontWithName:sansSerif
-                         size:sansSerifSize_.GetValue()] retain]);
-
-    fixedWidthName_.Init(prefs::kWebKitFixedFontFamily, profile->GetPrefs(),
-                         NULL);
-    fixedWidthSize_.Init(prefs::kWebKitDefaultFixedFontSize,
-                         profile->GetPrefs(), NULL);
-    NSString* fixedWidth = base::SysUTF8ToNSString(fixedWidthName_.GetValue());
-    fixedWidthFont_.reset(
-        [[NSFont fontWithName:fixedWidth
-                         size:fixedWidthSize_.GetValue()] retain]);
-
-    // Generate a list of encodings.
-    NSInteger count = CharacterEncoding::GetSupportCanonicalEncodingCount();
-    NSMutableArray* encodings = [NSMutableArray arrayWithCapacity:count];
-    for (NSInteger i = 0; i < count; ++i) {
-      int commandId = CharacterEncoding::GetEncodingCommandIdByIndex(i);
-      string16 name = CharacterEncoding::\
-          GetCanonicalEncodingDisplayNameByCommandId(commandId);
-      std::string encoding =
-          CharacterEncoding::GetCanonicalEncodingNameByCommandId(commandId);
-      NSDictionary* strings = [NSDictionary dictionaryWithObjectsAndKeys:
-          base::SysUTF16ToNSString(name), kCharacterInfoName,
-          base::SysUTF8ToNSString(encoding), kCharacterInfoEncoding,
-          [NSNumber numberWithInt:commandId], kCharacterInfoID,
-          nil
-      ];
-      [encodings addObject:strings];
-    }
-
-    // Sort the encodings.
-    scoped_nsobject<NSSortDescriptor> sorter(
-        [[NSSortDescriptor alloc] initWithKey:kCharacterInfoName
-                                    ascending:YES]);
-    NSArray* sorterArray = [NSArray arrayWithObject:sorter.get()];
-    encodings_.reset(
-        [[encodings sortedArrayUsingDescriptors:sorterArray] retain]);
-
-    // Find and set the default encoding.
-    defaultEncoding_.Init(prefs::kDefaultCharset, profile->GetPrefs(), NULL);
-    NSString* defaultEncoding =
-        base::SysUTF8ToNSString(defaultEncoding_.GetValue());
-    NSUInteger index = 0;
-    for (NSDictionary* entry in encodings_.get()) {
-      NSString* encoding = [entry objectForKey:kCharacterInfoEncoding];
-      if ([encoding isEqualToString:defaultEncoding]) {
-        defaultEncodingIndex_ = index;
-        break;
-      }
-      ++index;
-    }
-
-    // Register as a KVO observer so we can receive updates when the encoding
-    // changes.
-    [self addObserver:self
-           forKeyPath:@"defaultEncodingIndex_"
-              options:NSKeyValueObservingOptionNew
-              context:NULL];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [self removeObserver:self forKeyPath:@"defaultEncodingIndex_"];
-  [super dealloc];
-}
-
-- (void)awakeFromNib {
-  DCHECK([self window]);
-  [[self window] setDelegate:self];
-
-  // Set up the font display.
-  [self updateDisplayField:serifField_
-                  withFont:serifFont_.get()
-                 withLabel:serifLabel_];
-  [self updateDisplayField:sansSerifField_
-                  withFont:sansSerifFont_.get()
-                 withLabel:sansSerifLabel_];
-  [self updateDisplayField:fixedWidthField_
-                  withFont:fixedWidthFont_.get()
-                 withLabel:fixedWidthLabel_];
-}
-
-- (void)windowWillClose:(NSNotification*)notif {
-  [self autorelease];
-}
-
-- (IBAction)selectFont:(id)sender {
-  if (sender == serifButton_) {
-    currentFont_ = serifFont_.get();
-    currentType_ = FontSettingSerif;
-  } else if (sender == sansSerifButton_) {
-    currentFont_ = sansSerifFont_.get();
-    currentType_ = FontSettingSansSerif;
-  } else if (sender == fixedWidthButton_) {
-    currentFont_ = fixedWidthFont_.get();
-    currentType_ = FontSettingFixed;
-  } else {
-    NOTREACHED();
-  }
-
-  // Validate whatever editing is currently happening.
-  if ([[self window] makeFirstResponder:nil]) {
-    NSFontManager* manager = [NSFontManager sharedFontManager];
-    [manager setTarget:self];
-    [manager setSelectedFont:currentFont_ isMultiple:NO];
-    [manager orderFrontFontPanel:self];
-  }
-}
-
-// Called by the font manager when the user has selected a new font. We should
-// then persist those changes into the preference system.
-- (void)changeFont:(id)fontManager {
-  switch (currentType_) {
-    case FontSettingSerif:
-      serifFont_.reset([[fontManager convertFont:serifFont_] retain]);
-      [self updateDisplayField:serifField_
-                      withFont:serifFont_.get()
-                     withLabel:serifLabel_];
-      changedSerif_ = YES;
-      break;
-    case FontSettingSansSerif:
-      sansSerifFont_.reset([[fontManager convertFont:sansSerifFont_] retain]);
-      [self updateDisplayField:sansSerifField_
-                      withFont:sansSerifFont_.get()
-                     withLabel:sansSerifLabel_];
-      changedSansSerif_ = YES;
-      break;
-    case FontSettingFixed:
-      fixedWidthFont_.reset(
-          [[fontManager convertFont:fixedWidthFont_] retain]);
-      [self updateDisplayField:fixedWidthField_
-                      withFont:fixedWidthFont_.get()
-                     withLabel:fixedWidthLabel_];
-      changedFixedWidth_ = YES;
-      break;
-    default:
-      NOTREACHED();
-  }
-}
-
-- (IBAction)closeSheet:(id)sender {
-  NSFontPanel* panel = [[NSFontManager sharedFontManager] fontPanel:NO];
-  [panel close];
-  [NSApp endSheet:[self window]];
-}
-
-- (IBAction)save:(id)sender {
-  if (changedSerif_) {
-    serifName_.SetValue(base::SysNSStringToUTF8([serifFont_ fontName]));
-    serifSize_.SetValue([serifFont_ pointSize]);
-  }
-  if (changedSansSerif_) {
-    sansSerifName_.SetValue(
-        base::SysNSStringToUTF8([sansSerifFont_ fontName]));
-    sansSerifSize_.SetValue([sansSerifFont_ pointSize]);
-  }
-  if (changedFixedWidth_) {
-    fixedWidthName_.SetValue(
-        base::SysNSStringToUTF8([fixedWidthFont_ fontName]));
-    fixedWidthSize_.SetValue([fixedWidthFont_ pointSize]);
-  }
-  if (changedEncoding_) {
-    NSDictionary* object = [encodings_ objectAtIndex:defaultEncodingIndex_];
-    NSString* newEncoding = [object objectForKey:kCharacterInfoEncoding];
-    std::string encoding = base::SysNSStringToUTF8(newEncoding);
-    defaultEncoding_.SetValue(encoding);
-  }
-  [self closeSheet:sender];
-}
-
-- (NSArray*)encodings {
-  return encodings_.get();
-}
-
-// KVO notification.
-- (void)observeValueForKeyPath:(NSString*)keyPath
-                      ofObject:(id)object
-                        change:(NSDictionary*)change
-                       context:(void*)context {
-  // If this is the default encoding, then set the flag to persist the value.
-  if ([keyPath isEqual:@"defaultEncodingIndex_"]) {
-    changedEncoding_ = YES;
-    return;
-  }
-
-  [super observeValueForKeyPath:keyPath
-                       ofObject:object
-                         change:change
-                        context:context];
-}
-
-#pragma mark Private
-
-// Set the baseline for the font field to be aligned with the baseline
-// of its corresponding label.
-- (NSPoint)getFontFieldOrigin:(NSTextField*)field
-                     forLabel:(NSTextField*)label {
-  [field sizeToFit];
-  NSRect labelFrame = [label frame];
-  NSPoint newOrigin =
-      [[label superview] convertPoint:labelFrame.origin
-                               toView:[field superview]];
-  newOrigin.x = 0;  // Left-align font field.
-  newOrigin.y += [[field font] descender] - [[label font] descender];
-  return newOrigin;
-}
-
-// This will set the font on |field| to be |font|, and will set the string
-// value to something human-readable.
-- (void)updateDisplayField:(NSTextField*)field
-                  withFont:(NSFont*)font
-                 withLabel:(NSTextField*)label {
-  if (!font) {
-    // Something has gone really wrong. Don't make things worse by showing the
-    // user "(null)".
-    return;
-  }
-  [field setFont:font];
-  NSString* value =
-      [NSString stringWithFormat:@"%@, %g", [font fontName], [font pointSize]];
-  [field setStringValue:value];
-  [field setFrameOrigin:[self getFontFieldOrigin:field forLabel:label]];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/font_language_settings_controller_unittest.mm b/chrome/browser/ui/cocoa/font_language_settings_controller_unittest.mm
deleted file mode 100644
index 48e4a24..0000000
--- a/chrome/browser/ui/cocoa/font_language_settings_controller_unittest.mm
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/character_encoding.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/font_language_settings_controller.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-// The FontLanguageSettingsControllerForTest overrides the getFontFieldOrigin
-// method to provide a dummy point, so we don't have to actually display the
-// window to test the controller.
-@interface FontLanguageSettingsControllerForTest :
-    FontLanguageSettingsController {
-}
-
-- (NSPoint)getFontFieldOrigin:(NSTextField*)field
-                     forLabel:(NSTextField*)label;
-
-@end
-
-@implementation FontLanguageSettingsControllerForTest
-
-- (NSPoint)getFontFieldOrigin:(NSTextField*)field
-                     forLabel:(NSTextField*)label {
-  return NSMakePoint(10, 10);
-}
-
-@end
-
-@interface FontLanguageSettingsController (Testing)
-- (void)updateDisplayField:(NSTextField*)field
-                  withFont:(NSFont*)font
-                 withLabel:(NSTextField*)label;
-@end
-
-class FontLanguageSettingsControllerTest : public CocoaTest {
- public:
-  FontLanguageSettingsControllerTest() {
-    Profile* profile = helper_.profile();
-    font_controller_.reset(
-        [[FontLanguageSettingsControllerForTest alloc] initWithProfile:profile]);
-   }
-  ~FontLanguageSettingsControllerTest() {}
-
-  BrowserTestHelper helper_;
-  scoped_nsobject<FontLanguageSettingsController> font_controller_;
-};
-
-TEST_F(FontLanguageSettingsControllerTest, Init) {
-  ASSERT_EQ(CharacterEncoding::GetSupportCanonicalEncodingCount(),
-      static_cast<int>([[font_controller_ encodings] count]));
-}
-
-TEST_F(FontLanguageSettingsControllerTest, UpdateDisplayField) {
-  NSFont* font = [NSFont fontWithName:@"Times-Roman" size:12.0];
-  scoped_nsobject<NSTextField> field(
-      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
-  scoped_nsobject<NSTextField> label(
-      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
-  [font_controller_ updateDisplayField:field.get()
-                              withFont:font
-                             withLabel:label];
-
-  ASSERT_NSEQ([font fontName], [[field font] fontName]);
-  ASSERT_NSEQ(@"Times-Roman, 12", [field stringValue]);
-}
-
-TEST_F(FontLanguageSettingsControllerTest, UpdateDisplayFieldNilFont) {
-  scoped_nsobject<NSTextField> field(
-      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
-  scoped_nsobject<NSTextField> label(
-      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
-  [field setStringValue:@"foo"];
-  [font_controller_ updateDisplayField:field.get()
-                              withFont:nil
-                             withLabel:label];
-
-  ASSERT_NSEQ(@"foo", [field stringValue]);
-}
-
-TEST_F(FontLanguageSettingsControllerTest, UpdateDisplayFieldNilField) {
-  // Don't crash.
-  NSFont* font = [NSFont fontWithName:@"Times-Roman" size:12.0];
-  [font_controller_ updateDisplayField:nil withFont:font withLabel:nil];
-}
diff --git a/chrome/browser/ui/cocoa/framed_browser_window.h b/chrome/browser/ui/cocoa/framed_browser_window.h
index d3fd68b..719799d 100644
--- a/chrome/browser/ui/cocoa/framed_browser_window.h
+++ b/chrome/browser/ui/cocoa/framed_browser_window.h
@@ -13,8 +13,8 @@
 
 // Offsets from the top/left of the window frame to the top of the window
 // controls (zoom, close, miniaturize) for a window with a tabstrip.
-const NSInteger kFramedWindowButtonsWithTabStripOffsetFromTop = 10;
-const NSInteger kFramedWindowButtonsWithTabStripOffsetFromLeft = 10;
+const NSInteger kFramedWindowButtonsWithTabStripOffsetFromTop = 11;
+const NSInteger kFramedWindowButtonsWithTabStripOffsetFromLeft = 11;
 
 // Offsets from the top/left of the window frame to the top of the window
 // controls (zoom, close, miniaturize) for a window without a tabstrip.
diff --git a/chrome/browser/ui/cocoa/framed_browser_window.mm b/chrome/browser/ui/cocoa/framed_browser_window.mm
index bf46c08..30064cb 100644
--- a/chrome/browser/ui/cocoa/framed_browser_window.mm
+++ b/chrome/browser/ui/cocoa/framed_browser_window.mm
@@ -8,7 +8,7 @@
 #include "chrome/browser/global_keyboard_shortcuts_mac.h"
 #import "chrome/browser/ui/cocoa/browser_frame_view.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
 #import "chrome/browser/renderer_host/render_widget_host_view_mac.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
diff --git a/chrome/browser/ui/cocoa/fullscreen_controller.mm b/chrome/browser/ui/cocoa/fullscreen_controller.mm
index 186ea78..57a515a 100644
--- a/chrome/browser/ui/cocoa/fullscreen_controller.mm
+++ b/chrome/browser/ui/cocoa/fullscreen_controller.mm
@@ -165,7 +165,7 @@
 @synthesize isFullscreen = isFullscreen_;
 
 - (id)initWithBrowserController:(BrowserWindowController*)controller {
-  if ((self == [super init])) {
+  if ((self = [super init])) {
     browserController_ = controller;
     currentFullscreenMode_ = base::mac::kFullScreenModeNormal;
   }
diff --git a/chrome/browser/ui/cocoa/gradient_button_cell.h b/chrome/browser/ui/cocoa/gradient_button_cell.h
index a1e905f..48929b5 100644
--- a/chrome/browser/ui/cocoa/gradient_button_cell.h
+++ b/chrome/browser/ui/cocoa/gradient_button_cell.h
@@ -10,7 +10,9 @@
 
 #include "base/scoped_nsobject.h"
 
+namespace ui {
 class ThemeProvider;
+}
 
 // Base class for button cells for toolbar and bookmark bar.
 //
@@ -68,7 +70,7 @@
 // Turn off theming.  Temporary work-around.
 - (void)setShouldTheme:(BOOL)shouldTheme;
 
-- (void)drawBorderAndFillForTheme:(ThemeProvider*)themeProvider
+- (void)drawBorderAndFillForTheme:(ui::ThemeProvider*)themeProvider
                       controlView:(NSView*)controlView
                         innerPath:(NSBezierPath*)innerPath
               showClickedGradient:(BOOL)showClickedGradient
diff --git a/chrome/browser/ui/cocoa/gradient_button_cell.mm b/chrome/browser/ui/cocoa/gradient_button_cell.mm
index 459aa8e..ce2ea01 100644
--- a/chrome/browser/ui/cocoa/gradient_button_cell.mm
+++ b/chrome/browser/ui/cocoa/gradient_button_cell.mm
@@ -336,7 +336,7 @@
 }
 
 // TODO(viettrungluu): clean up/reorganize.
-- (void)drawBorderAndFillForTheme:(ThemeProvider*)themeProvider
+- (void)drawBorderAndFillForTheme:(ui::ThemeProvider*)themeProvider
                       controlView:(NSView*)controlView
                         innerPath:(NSBezierPath*)innerPath
               showClickedGradient:(BOOL)showClickedGradient
@@ -516,7 +516,7 @@
   BOOL pressed = ([((NSControl*)[self controlView]) isEnabled] &&
                   [self isHighlighted]);
   NSWindow* window = [controlView window];
-  ThemeProvider* themeProvider = [window themeProvider];
+  ui::ThemeProvider* themeProvider = [window themeProvider];
   BOOL active = [window isKeyWindow] || [window isMainWindow];
 
   // Stroke the borders and appropriate fill gradient. If we're borderless, the
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm
index 8e34024..ea5a8b5 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/stl_util-inl.h"
 #include "base/string_number_conversions.h"
@@ -20,12 +18,14 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
index 843e964..c292d5c 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -12,14 +12,13 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/cancelable_request.h"
 #include "chrome/browser/sessions/tab_restore_service.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/cocoa/browser_test_helper.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
-#include "gfx/codec/png_codec.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm
index 26f7388..7edc34b 100644
--- a/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm
@@ -11,7 +11,6 @@
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/history_menu_cocoa_controller.h"
-#include "chrome/browser/ui/browser.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 @interface FakeHistoryMenuController : HistoryMenuCocoaController {
diff --git a/chrome/browser/ui/cocoa/hover_close_button.mm b/chrome/browser/ui/cocoa/hover_close_button.mm
index f8e29e2..c276eee 100644
--- a/chrome/browser/ui/cocoa/hover_close_button.mm
+++ b/chrome/browser/ui/cocoa/hover_close_button.mm
@@ -4,10 +4,10 @@
 
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 
-#include "app/l10n_util.h"
 #include "base/scoped_nsobject.h"
 #include "grit/generated_resources.h"
 #import "third_party/molokocacao/NSBezierPath+MCAdditions.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace  {
 // Convenience function to return the middle point of the given |rect|.
diff --git a/chrome/browser/ui/cocoa/hover_image_button.mm b/chrome/browser/ui/cocoa/hover_image_button.mm
index c5bdbf4..a6ae41e 100644
--- a/chrome/browser/ui/cocoa/hover_image_button.mm
+++ b/chrome/browser/ui/cocoa/hover_image_button.mm
@@ -4,9 +4,9 @@
 
 #import "chrome/browser/ui/cocoa/hover_image_button.h"
 
-#include "app/l10n_util.h"
 #include "base/scoped_nsobject.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 @implementation HoverImageButton
 
diff --git a/chrome/browser/ui/cocoa/hover_image_button_unittest.mm b/chrome/browser/ui/cocoa/hover_image_button_unittest.mm
index d2db766..6d68d0f 100644
--- a/chrome/browser/ui/cocoa/hover_image_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/hover_image_button_unittest.mm
@@ -4,13 +4,13 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/resource_bundle.h"
 #include "base/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/hover_image_button.h"
+#include "grit/theme_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/html_dialog_window_controller.mm b/chrome/browser/ui/cocoa/html_dialog_window_controller.mm
index 611ecdd..11d700c 100644
--- a/chrome/browser/ui/cocoa/html_dialog_window_controller.mm
+++ b/chrome/browser/ui/cocoa/html_dialog_window_controller.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/html_dialog_window_controller.h"
 
-#include "app/keyboard_codes.h"
 #include "base/logging.h"
 #include "base/scoped_nsobject.h"
 #include "base/sys_string_conversions.h"
@@ -12,11 +11,13 @@
 #include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#import "chrome/browser/ui/browser_dialogs.h"
 #import "chrome/browser/ui/cocoa/browser_command_executor.h"
 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
 #include "chrome/common/native_web_keyboard_event.h"
-#include "gfx/size.h"
 #include "ipc/ipc_message.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/gfx/size.h"
 
 // Thin bridge that routes notifications to
 // HtmlDialogWindowController's member variables.
@@ -38,8 +39,8 @@
   virtual bool IsDialogModal() const;
   virtual std::wstring GetDialogTitle() const;
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
@@ -73,10 +74,11 @@
 
 @end
 
-namespace html_dialog_window_controller {
+namespace browser {
 
-gfx::NativeWindow ShowHtmlDialog(
-    HtmlDialogUIDelegate* delegate, Profile* profile) {
+gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile,
+                                 HtmlDialogUIDelegate* delegate) {
+  // NOTE: Use the parent parameter once we implement modal dialogs.
   return [HtmlDialogWindowController showHtmlDialog:delegate profile:profile];
 }
 
@@ -131,10 +133,10 @@
   return delegate_ ? delegate_->GetDialogContentURL() : GURL();
 }
 
-void HtmlDialogWindowDelegateBridge::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void HtmlDialogWindowDelegateBridge::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   if (delegate_) {
-    delegate_->GetDOMMessageHandlers(handlers);
+    delegate_->GetWebUIMessageHandlers(handlers);
   } else {
     // TODO(akalin): Add this clause in the windows version.  Also
     // make sure that everything expects handlers to be non-NULL and
@@ -195,8 +197,8 @@
   // TODO(thakis): It would be nice to get cancel: to work somehow.
   // Bug: http://code.google.com/p/chromium/issues/detail?id=32828 .
   if (event.type == NativeWebKeyboardEvent::RawKeyDown &&
-      ((event.windowsKeyCode == app::VKEY_ESCAPE) ||
-       (event.windowsKeyCode == app::VKEY_OEM_PERIOD &&
+      ((event.windowsKeyCode == ui::VKEY_ESCAPE) ||
+       (event.windowsKeyCode == ui::VKEY_OEM_PERIOD &&
         event.modifiers == NativeWebKeyboardEvent::MetaKey))) {
     [controller_ close];
     return;
diff --git a/chrome/browser/ui/cocoa/html_dialog_window_controller_cppsafe.h b/chrome/browser/ui/cocoa/html_dialog_window_controller_cppsafe.h
deleted file mode 100644
index dd3b809..0000000
--- a/chrome/browser/ui/cocoa/html_dialog_window_controller_cppsafe.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_HTML_DIALOG_WINDOW_CONTROLLER_CPPSAFE_H_
-#define CHROME_BROWSER_UI_COCOA_HTML_DIALOG_WINDOW_CONTROLLER_CPPSAFE_H_
-#pragma once
-
-#include "gfx/native_widget_types.h"
-
-// We declare this in a separate file that is safe for including in C++ code.
-
-// TODO(akalin): It would be nice if there were a platform-agnostic way to
-// create a browser-independent HTML dialog.  However, this would require
-// some invasive changes on the Windows/Linux side.  Remove this file once
-// We have this platform-agnostic API.
-
-namespace html_dialog_window_controller {
-
-// Creates and shows an HtmlDialogWindowController with the given
-// delegate and profile. The window is automatically destroyed when it is
-// closed.  Returns the created window.
-//
-// Make sure to use the returned window only when you know it is safe
-// to do so, i.e. before OnDialogClosed() is called on the delegate.
-gfx::NativeWindow ShowHtmlDialog(
-    HtmlDialogUIDelegate* delegate, Profile* profile);
-
-}  // namespace html_dialog_window_controller
-
-#endif  // CHROME_BROWSER_UI_COCOA_HTML_DIALOG_WINDOW_CONTROLLER_CPPSAFE_H_
-
diff --git a/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm b/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm
index 7bbeb31..0cd6164 100644
--- a/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,15 +11,16 @@
 
 #import "base/mac/scoped_nsautorelease_pool.h"
 #include "base/sys_string_conversions.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/web_ui.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/testing_profile.h"
-#include "gfx/size.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/size.h"
 
 namespace {
 
@@ -28,8 +29,8 @@
   MOCK_CONST_METHOD0(IsDialogModal, bool());
   MOCK_CONST_METHOD0(GetDialogTitle, std::wstring());
   MOCK_CONST_METHOD0(GetDialogContentURL, GURL());
-  MOCK_CONST_METHOD1(GetDOMMessageHandlers,
-                     void(std::vector<DOMMessageHandler*>*));
+  MOCK_CONST_METHOD1(GetWebUIMessageHandlers,
+                     void(std::vector<WebUIMessageHandler*>*));
   MOCK_CONST_METHOD1(GetDialogSize, void(gfx::Size*));
   MOCK_CONST_METHOD0(GetDialogArgs, std::string());
   MOCK_METHOD1(OnDialogClosed, void(const std::string& json_retval));
@@ -62,8 +63,8 @@
 using ::testing::SetArgumentPointee;
 
 // TODO(akalin): We can't test much more than the below without a real browser.
-// In particular, GetDOMMessageHandlers() and GetDialogArgs() are never called.
-// This should be fixed.
+// In particular, GetWebUIMessageHandlers() and GetDialogArgs() are never
+// called. This should be fixed.
 
 TEST_F(HtmlDialogWindowControllerTest, showDialog) {
   // We want to make sure html_dialog_window_controller below gets
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.mm b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
index 2c9d337..2853658 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller.mm
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
@@ -6,8 +6,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/resource_bundle.h"
-#include "app/l10n_util_mac.h"
 #include "base/mac/mac_util.h"
 #include "base/process_util.h"
 #include "base/sys_string_conversions.h"
@@ -25,6 +23,8 @@
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 // We only support showing one of these at a time per app.  The
diff --git a/chrome/browser/ui/cocoa/hyperlink_button_cell.h b/chrome/browser/ui/cocoa/hyperlink_button_cell.h
index c4d27ff..fd9ec0c 100644
--- a/chrome/browser/ui/cocoa/hyperlink_button_cell.h
+++ b/chrome/browser/ui/cocoa/hyperlink_button_cell.h
@@ -18,7 +18,7 @@
 @interface HyperlinkButtonCell : NSButtonCell {
   scoped_nsobject<NSColor> textColor_;
 }
-@property (nonatomic, retain) NSColor* textColor;
+@property(nonatomic, retain) NSColor* textColor;
 
 + (NSColor*)defaultTextColor;
 
diff --git a/chrome/browser/ui/cocoa/import_progress_dialog.h b/chrome/browser/ui/cocoa/import_progress_dialog.h
deleted file mode 100644
index c1b405b..0000000
--- a/chrome/browser/ui/cocoa/import_progress_dialog.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_IMPORT_PROGRESS_DIALOG_H_
-#define CHROME_BROWSER_IMPORT_PROGRESS_DIALOG_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "chrome/browser/importer/importer.h"
-#include "chrome/browser/importer/importer_data_types.h"
-
-class ImporterObserverBridge;
-
-// Class that acts as a controller for the dialog that shows progress for an
-// import operation.
-// Lifetime: This object is responsible for deleting itself.
-@interface ImportProgressDialogController : NSWindowController {
-  scoped_ptr<ImporterObserverBridge> import_host_observer_bridge_;
-  ImporterHost* importer_host_;  // (weak)
-  ImportObserver* observer_;  // (weak)
-
-  // Strings bound to static labels in the UI dialog.
-  NSString* explanatory_text_;
-  NSString* favorites_status_text_;
-  NSString* search_status_text_;
-  NSString* saved_password_status_text_;
-  NSString* history_status_text_;
-
-  // Bound to the color of the status text (this is the easiest way to disable
-  // progress items that aren't supported by the current browser we're importing
-  // from).
-  NSColor* favorites_import_enabled_;
-  NSColor* search_import_enabled_;
-  NSColor* password_import_enabled_;
-  NSColor* history_import_enabled_;
-
-  // Placeholders for "Importing..." and "Done" text.
-  NSString* progress_text_;
-  NSString* done_text_;
-}
-
-// Cancel button calls this.
-- (IBAction)cancel:(id)sender;
-
-// Closes the dialog.
-- (void)closeDialog;
-
-// Methods called by importer_host via ImporterObserverBridge.
-- (void)ImportItemStarted:(importer::ImportItem)item;
-- (void)ImportItemEnded:(importer::ImportItem)item;
-- (void)ImportEnded;
-
-@property (nonatomic, retain) NSString* explanatoryText;
-@property (nonatomic, retain) NSString* favoritesStatusText;
-@property (nonatomic, retain) NSString* searchStatusText;
-@property (nonatomic, retain) NSString* savedPasswordStatusText;
-@property (nonatomic, retain) NSString* historyStatusText;
-
-@property (nonatomic, retain) NSColor* favoritesImportEnabled;
-@property (nonatomic, retain) NSColor* searchImportEnabled;
-@property (nonatomic, retain) NSColor* passwordImportEnabled;
-@property (nonatomic, retain) NSColor* historyImportEnabled;
-
-@end
-
-// C++ -> objc bridge for import status notifications.
-class ImporterObserverBridge : public ImporterHost::Observer {
- public:
-  ImporterObserverBridge(ImportProgressDialogController* owner)
-      : owner_(owner) {}
-  virtual ~ImporterObserverBridge() {}
-
-  // Invoked when data for the specified item is about to be collected.
-  virtual void ImportItemStarted(importer::ImportItem item) {
-    [owner_ ImportItemStarted:item];
-  }
-
-  // Invoked when data for the specified item has been collected from the
-  // source profile and is now ready for further processing.
-  virtual void ImportItemEnded(importer::ImportItem item) {
-    [owner_ ImportItemEnded:item];
-  }
-
-  // Invoked when the import begins.
-  virtual void ImportStarted() {
-    // Not needed for out of process import.
-  }
-
-  // Invoked when the source profile has been imported.
-  virtual void ImportEnded() {
-    [owner_ ImportEnded];
-  }
-
- private:
-  ImportProgressDialogController* owner_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImporterObserverBridge);
-};
-
-#endif  // CHROME_BROWSER_IMPORT_PROGRESS_DIALOG_H_
diff --git a/chrome/browser/ui/cocoa/import_progress_dialog.mm b/chrome/browser/ui/cocoa/import_progress_dialog.mm
deleted file mode 100644
index fe82f1f..0000000
--- a/chrome/browser/ui/cocoa/import_progress_dialog.mm
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/import_progress_dialog.h"
-
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/message_loop.h"
-#import "base/scoped_nsobject.h"
-#import "base/sys_string_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Convert ImportItem enum into the name of the ImportProgressDialogController
-// property corresponding to the text for that item, this makes the code to
-// change the values for said properties much more readable.
-NSString* keyForImportItem(importer::ImportItem item) {
-  switch(item) {
-    case importer::HISTORY:
-      return @"historyStatusText";
-    case importer::FAVORITES:
-      return @"favoritesStatusText";
-    case importer::PASSWORDS:
-      return @"savedPasswordStatusText";
-    case importer::SEARCH_ENGINES:
-      return @"searchStatusText";
-    default:
-      DCHECK(false);
-      break;
-  }
-  return nil;
-}
-
-}  // namespace
-
-@implementation ImportProgressDialogController
-
-@synthesize explanatoryText = explanatory_text_;
-@synthesize favoritesStatusText = favorites_status_text_;
-@synthesize searchStatusText = search_status_text_;
-@synthesize savedPasswordStatusText = saved_password_status_text_;
-@synthesize historyStatusText = history_status_text_;
-
-@synthesize favoritesImportEnabled = favorites_import_enabled_;
-@synthesize searchImportEnabled = search_import_enabled_;
-@synthesize passwordImportEnabled = password_import_enabled_;
-@synthesize historyImportEnabled = history_import_enabled_;
-
-- (id)initWithImporterHost:(ImporterHost*)host
-               browserName:(string16)browserName
-                  observer:(ImportObserver*)observer
-              itemsEnabled:(int16)items {
-  NSString* nib_path =
-      [base::mac::MainAppBundle() pathForResource:@"ImportProgressDialog"
-                                          ofType:@"nib"];
-  self = [super initWithWindowNibPath:nib_path owner:self];
-  if (self != nil) {
-    importer_host_ = host;
-    observer_ = observer;
-    import_host_observer_bridge_.reset(new ImporterObserverBridge(self));
-    importer_host_->SetObserver(import_host_observer_bridge_.get());
-
-    string16 productName = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
-    NSString* explanatory_text = l10n_util::GetNSStringF(
-        IDS_IMPORT_PROGRESS_EXPLANATORY_TEXT_MAC,
-        productName,
-        browserName);
-    [self setExplanatoryText:explanatory_text];
-
-    progress_text_ =
-        [l10n_util::GetNSStringWithFixup(IDS_IMPORT_IMPORTING_PROGRESS_TEXT_MAC)
-        retain];
-    done_text_ =
-        [l10n_util::GetNSStringWithFixup(IDS_IMPORT_IMPORTING_DONE_TEXT_MAC)
-         retain];
-
-    // Enable/disable item titles.
-    NSColor* disabled = [NSColor disabledControlTextColor];
-    NSColor* active = [NSColor textColor];
-    [self setFavoritesImportEnabled:items & importer::FAVORITES ? active :
-        disabled];
-    [self setSearchImportEnabled:items & importer::SEARCH_ENGINES ? active :
-        disabled];
-    [self setPasswordImportEnabled:items & importer::PASSWORDS ? active :
-        disabled];
-    [self setHistoryImportEnabled:items & importer::HISTORY ? active :
-        disabled];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [explanatory_text_ release];
-  [favorites_status_text_ release];
-  [search_status_text_ release];
-  [saved_password_status_text_ release];
-  [history_status_text_ release];
-
-  [favorites_import_enabled_ release];
-  [search_import_enabled_ release];
-  [password_import_enabled_ release];
-  [history_import_enabled_ release];
-
-  [progress_text_ release];
-  [done_text_ release];
-
-  [super dealloc];
-}
-
-- (IBAction)showWindow:(id)sender {
-  NSWindow* win = [self window];
-  [win center];
-  [super showWindow:nil];
-}
-
-- (void)closeDialog {
-  if ([[self window] isVisible]) {
-    [[self window] close];
-  }
-}
-
-- (IBAction)cancel:(id)sender {
-  // The ImporterHost will notify import_host_observer_bridge_ that import has
-  // ended, which will trigger the ImportEnded method, in which this object is
-  // released.
-  importer_host_->Cancel();
-}
-
-- (void)ImportItemStarted:(importer::ImportItem)item {
-  [self setValue:progress_text_ forKey:keyForImportItem(item)];
-}
-
-- (void)ImportItemEnded:(importer::ImportItem)item {
-  [self setValue:done_text_ forKey:keyForImportItem(item)];
-}
-
-- (void)ImportEnded {
-  importer_host_->SetObserver(NULL);
-  if (observer_)
-    observer_->ImportComplete();
-  [self closeDialog];
-  [self release];
-
-  // Break out of modal event loop.
-  [NSApp stopModal];
-}
-
-@end
-
-void StartImportingWithUI(gfx::NativeWindow parent_window,
-                          uint16 items,
-                          ImporterHost* coordinator,
-                          const importer::ProfileInfo& source_profile,
-                          Profile* target_profile,
-                          ImportObserver* observer,
-                          bool first_run) {
-  DCHECK(items != 0);
-
-  // Retrieve name of browser we're importing from and do a little dance to
-  // convert wstring -> string16.
-  string16 import_browser_name = WideToUTF16Hack(source_profile.description);
-
-  // progress_dialog_ is responsible for deleting itself.
-  ImportProgressDialogController* progress_dialog_ =
-      [[ImportProgressDialogController alloc]
-          initWithImporterHost:coordinator
-                  browserName:import_browser_name
-                      observer:observer
-                  itemsEnabled:items];
-   // Call is async.
-  coordinator->StartImportSettings(source_profile, target_profile, items,
-                                   new ProfileWriter(target_profile),
-                                   first_run);
-
-  // Display the window while spinning a message loop.
-  // For details on why we need a modal message loop see http://crbug.com/19169
-  NSWindow* progress_window = [progress_dialog_ window];
-  NSModalSession session = [NSApp beginModalSessionForWindow:progress_window];
-  [progress_dialog_ showWindow:nil];
-  while (true) {
-    if ([NSApp runModalSession:session] != NSRunContinuesResponse)
-        break;
-    MessageLoop::current()->RunAllPending();
-  }
-  [NSApp endModalSession:session];
-}
diff --git a/chrome/browser/ui/cocoa/import_settings_dialog.h b/chrome/browser/ui/cocoa/import_settings_dialog.h
deleted file mode 100644
index a9ff7f4..0000000
--- a/chrome/browser/ui/cocoa/import_settings_dialog.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_IMPORT_SETTINGS_DIALOG_H_
-#define CHROME_BROWSER_UI_COCOA_IMPORT_SETTINGS_DIALOG_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/importer/importer.h"
-
-class Profile;
-
-// Controller for the Import Bookmarks and Settings dialog.  This controller
-// automatically autoreleases itself when its associated dialog is dismissed.
-@interface ImportSettingsDialogController : NSWindowController {
- @private
-  NSWindow* parentWindow_;  // weak
-  Profile* profile_;  // weak
-  scoped_refptr<ImporterList> importerList_;
-  scoped_nsobject<NSArray> sourceBrowsersList_;
-  NSUInteger sourceBrowserIndex_;
-  // The following are all bound via the properties below.
-  BOOL importHistory_;
-  BOOL importFavorites_;
-  BOOL importPasswords_;
-  BOOL importSearchEngines_;
-  BOOL historyAvailable_;
-  BOOL favoritesAvailable_;
-  BOOL passwordsAvailable_;
-  BOOL searchEnginesAvailable_;
-}
-
-// Show the import settings window.  Window is displayed as an app modal dialog.
-// If the dialog is already being displayed, this method whill return with
-// no error.
-+ (void)showImportSettingsDialogForProfile:(Profile*)profile;
-
-// Called when the "Import" button is pressed.
-- (IBAction)ok:(id)sender;
-
-// Cancel button calls this.
-- (IBAction)cancel:(id)sender;
-
-// An array of ImportSettingsProfiles, provide the list of browser profiles
-// available for importing. Bound to the Browser List array controller.
-- (NSArray*)sourceBrowsersList;
-
-// Properties for bindings.
-@property(assign, nonatomic) NSUInteger sourceBrowserIndex;
-@property(assign, readonly, nonatomic) BOOL importSomething;
-// Bindings for the value of the import checkboxes.
-@property(assign, nonatomic) BOOL importHistory;
-@property(assign, nonatomic) BOOL importFavorites;
-@property(assign, nonatomic) BOOL importPasswords;
-@property(assign, nonatomic) BOOL importSearchEngines;
-// Bindings for enabling/disabling the checkboxes.
-@property(assign, readonly, nonatomic) BOOL historyAvailable;
-@property(assign, readonly, nonatomic) BOOL favoritesAvailable;
-@property(assign, readonly, nonatomic) BOOL passwordsAvailable;
-@property(assign, readonly, nonatomic) BOOL searchEnginesAvailable;
-
-@end
-
-@interface ImportSettingsDialogController (TestingAPI)
-
-// Initialize by providing an array of profile dictionaries. Exposed for
-// unit testing but also called by -[initWithProfile:].
-- (id)initWithProfiles:(NSArray*)profiles;
-
-// Return selected services to import as mapped by the ImportItem enum.
-- (uint16)servicesToImport;
-
-@end
-
-// Utility class used as array elements for sourceBrowsersList, above.
-@interface ImportSettingsProfile : NSObject {
- @private
-  NSString* browserName_;
-  uint16 services_;  // Services as defined by enum ImportItem.
-}
-
-// Convenience creator. |services| is a bitfield of enum ImportItems.
-+ (id)importSettingsProfileWithBrowserName:(NSString*)browserName
-                                  services:(uint16)services;
-
-// Designated initializer. |services| is a bitfield of enum ImportItems.
-- (id)initWithBrowserName:(NSString*)browserName
-                 services:(uint16)services;  // Bitfield of enum ImportItems.
-
-@property(copy, nonatomic) NSString* browserName;
-@property(assign, nonatomic) uint16 services;  // Bitfield of enum ImportItems.
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_IMPORT_SETTINGS_DIALOG_H_
diff --git a/chrome/browser/ui/cocoa/import_settings_dialog.mm b/chrome/browser/ui/cocoa/import_settings_dialog.mm
deleted file mode 100644
index d395999..0000000
--- a/chrome/browser/ui/cocoa/import_settings_dialog.mm
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
-
-#include "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/importer/importer_data_types.h"
-#include "chrome/browser/importer/importer_list.h"
-#include "chrome/browser/profiles/profile.h"
-
-namespace {
-
-bool importSettingsDialogVisible = false;
-
-}  // namespace
-
-@interface ImportSettingsDialogController ()
-
-@property(assign, readwrite, nonatomic) BOOL historyAvailable;
-@property(assign, readwrite, nonatomic) BOOL favoritesAvailable;
-@property(assign, readwrite, nonatomic) BOOL passwordsAvailable;
-@property(assign, readwrite, nonatomic) BOOL searchEnginesAvailable;
-
-@end
-
-@implementation ImportSettingsProfile
-
-@synthesize browserName = browserName_;
-@synthesize services = services_;
-
-+ (id)importSettingsProfileWithBrowserName:(NSString*)browserName
-                                  services:(uint16)services {
-  id settingsProfile = [[[ImportSettingsProfile alloc]
-                        initWithBrowserName:browserName
-                         services:services] autorelease];
-  return settingsProfile;
-}
-
-- (id)initWithBrowserName:(NSString*)browserName
-                 services:(uint16)services {
-  DCHECK(browserName && services);
-  if ((self = [super init])) {
-    if (browserName && services != 0) {
-      browserName_ = [browserName retain];
-      services_ = services;
-    } else {
-      [self release];
-      self = nil;
-    }
-  }
-  return self;
-}
-
-- (id)init {
-  NOTREACHED();  // Should never be called.
-  return [self initWithBrowserName:NULL services:0];
-}
-
-- (void)dealloc {
-  [browserName_ release];
-  [super dealloc];
-}
-
-@end
-
-@interface ImportSettingsDialogController (Private)
-
-// Initialize the dialog controller with either the default profile or
-// the profile for the current browser.
-- (id)initWithProfile:(Profile*)profile;
-
-// Present the app modal dialog.
-- (void)runModalDialog;
-
-// Close the modal dialog.
-- (void)closeDialog;
-
-@end
-
-@implementation ImportSettingsDialogController
-
-@synthesize sourceBrowserIndex = sourceBrowserIndex_;
-@synthesize importHistory = importHistory_;
-@synthesize importFavorites = importFavorites_;
-@synthesize importPasswords = importPasswords_;
-@synthesize importSearchEngines = importSearchEngines_;
-@synthesize historyAvailable = historyAvailable_;
-@synthesize favoritesAvailable = favoritesAvailable_;
-@synthesize passwordsAvailable = passwordsAvailable_;
-@synthesize searchEnginesAvailable = searchEnginesAvailable_;
-
-// Set bindings dependencies for importSomething property.
-+ (NSSet*)keyPathsForValuesAffectingImportSomething {
-  return [NSSet setWithObjects:@"importHistory", @"importFavorites",
-          @"importPasswords", @"importSearchEngines", nil];
-}
-
-+ (void)showImportSettingsDialogForProfile:(Profile*)profile {
-  // Don't display if already visible.
-  if (importSettingsDialogVisible)
-    return;
-  ImportSettingsDialogController* controller =
-      [[ImportSettingsDialogController alloc] initWithProfile:profile];
-  [controller runModalDialog];
-}
-
-- (id)initWithProfile:(Profile*)profile {
-  // Collect profile information (profile name and the services which can
-  // be imported from each) into an array of ImportSettingsProfile which
-  // are bound to the Browser List array controller and the popup name
-  // presentation.  The services element is used to indirectly control
-  // checkbox enabling.
-  importerList_ = new ImporterList;
-  ImporterList& importerList(*(importerList_.get()));
-  importerList.DetectSourceProfilesHack();
-  int profilesCount = importerList.GetAvailableProfileCount();
-  // There shoule be at least the default profile so this should never be zero.
-  DCHECK(profilesCount > 0);
-  NSMutableArray* browserProfiles =
-      [NSMutableArray arrayWithCapacity:profilesCount];
-  for (int i = 0; i < profilesCount; ++i) {
-    const importer::ProfileInfo& sourceProfile =
-        importerList.GetSourceProfileInfoAt(i);
-    NSString* browserName =
-        base::SysWideToNSString(sourceProfile.description);
-    uint16 browserServices = sourceProfile.services_supported;
-    ImportSettingsProfile* settingsProfile =
-        [ImportSettingsProfile
-         importSettingsProfileWithBrowserName:browserName
-                                     services:browserServices];
-    [browserProfiles addObject:settingsProfile];
-  }
-  if ((self = [self initWithProfiles:browserProfiles])) {
-    profile_ = profile;
-  }
-  return self;
-}
-
-- (id)initWithProfiles:(NSArray*)profiles {
-  NSString* nibpath =
-      [base::mac::MainAppBundle() pathForResource:@"ImportSettingsDialog"
-                                          ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    sourceBrowsersList_.reset([profiles retain]);
-    // Create and initialize an importerList_ when running unit tests.
-    if (!importerList_.get()) {
-      importerList_ = new ImporterList;
-      ImporterList& importerList(*(importerList_.get()));
-      importerList.DetectSourceProfilesHack();
-    }
-  }
-  return self;
-}
-
-- (id)init {
-  return [self initWithProfile:NULL];
-}
-
-- (void)awakeFromNib {
-  // Force an update of the checkbox enabled states.
-  [self setSourceBrowserIndex:0];
-}
-
-// Run application modal.
-- (void)runModalDialog {
-  importSettingsDialogVisible = true;
-  [NSApp runModalForWindow:[self window]];
-}
-
-- (IBAction)ok:(id)sender {
-  [self closeDialog];
-  const importer::ProfileInfo& sourceProfile =
-      importerList_.get()->GetSourceProfileInfoAt([self sourceBrowserIndex]);
-  uint16 items = sourceProfile.services_supported;
-  uint16 servicesToImport = items & [self servicesToImport];
-  if (servicesToImport) {
-    if (profile_) {
-      ImporterHost* importerHost = new ExternalProcessImporterHost;
-      // Note that a side effect of the following call is to cause the
-      // importerHost to be disposed once the import has completed.
-      StartImportingWithUI(nil, servicesToImport, importerHost,
-                           sourceProfile, profile_, nil, false);
-    }
-  } else {
-    LOG(WARNING) << "There were no settings to import from '"
-                 << sourceProfile.description << "'.";
-  }
-}
-
-- (IBAction)cancel:(id)sender {
-  [self closeDialog];
-}
-
-- (void)closeDialog {
-  importSettingsDialogVisible = false;
-  [[self window] orderOut:self];
-  [NSApp stopModal];
-  [self autorelease];
-}
-
-#pragma mark Accessors
-
-- (NSArray*)sourceBrowsersList {
-  return sourceBrowsersList_.get();
-}
-
-// Accessor which cascades selected-browser changes into a re-evaluation of the
-// available services and the associated checkbox enable and checked states.
-- (void)setSourceBrowserIndex:(NSUInteger)browserIndex {
-  sourceBrowserIndex_ = browserIndex;
-  ImportSettingsProfile* profile =
-      [sourceBrowsersList_.get() objectAtIndex:browserIndex];
-  uint16 items = [profile services];
-  [self setHistoryAvailable:(items & importer::HISTORY) ? YES : NO];
-  [self setImportHistory:[self historyAvailable]];
-  [self setFavoritesAvailable:(items & importer::FAVORITES) ? YES : NO];
-  [self setImportFavorites:[self favoritesAvailable]];
-  [self setPasswordsAvailable:(items & importer::PASSWORDS) ? YES : NO];
-  [self setImportPasswords:[self passwordsAvailable]];
-  [self setSearchEnginesAvailable:(items & importer::SEARCH_ENGINES) ?
-      YES : NO];
-  [self setImportSearchEngines:[self searchEnginesAvailable]];
-}
-
-- (uint16)servicesToImport {
-  uint16 servicesToImport = 0;
-  if ([self importHistory]) servicesToImport |= importer::HISTORY;
-  if ([self importFavorites]) servicesToImport |= importer::FAVORITES;
-  if ([self importPasswords]) servicesToImport |= importer::PASSWORDS;
-  if ([self importSearchEngines]) servicesToImport |=
-      importer::SEARCH_ENGINES;
-  return servicesToImport;
-}
-
-// KVO accessor which returns YES if at least one of the services
-// provided by the selected profile has been marked for importing
-// and bound to the OK button's enable property.
-- (BOOL)importSomething {
-  return [self importHistory] || [self importFavorites] ||
-      [self importPasswords] || [self importSearchEngines];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/import_settings_dialog_unittest.mm b/chrome/browser/ui/cocoa/import_settings_dialog_unittest.mm
deleted file mode 100644
index f9399c2..0000000
--- a/chrome/browser/ui/cocoa/import_settings_dialog_unittest.mm
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/importer/importer.h"
-#import "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-using importer::HISTORY;
-using importer::FAVORITES;
-using importer::COOKIES;
-using importer::PASSWORDS;
-using importer::SEARCH_ENGINES;
-using importer::NONE;
-
-class ImportSettingsDialogTest : public CocoaTest {
- public:
-  ImportSettingsDialogController* controller_;
-
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    unsigned int safariServices =
-        HISTORY | FAVORITES | COOKIES | PASSWORDS | SEARCH_ENGINES;
-    ImportSettingsProfile* mockSafari =
-        [ImportSettingsProfile
-         importSettingsProfileWithBrowserName:@"MockSafari"
-                                     services:safariServices];
-    unsigned int firefoxServices = HISTORY | FAVORITES | COOKIES | PASSWORDS;
-    ImportSettingsProfile* mockFirefox =
-        [ImportSettingsProfile
-         importSettingsProfileWithBrowserName:@"MockFirefox"
-                                     services:firefoxServices];
-    unsigned int caminoServices = HISTORY | COOKIES | SEARCH_ENGINES;
-    ImportSettingsProfile* mockCamino =
-        [ImportSettingsProfile
-         importSettingsProfileWithBrowserName:@"MockCamino"
-                                     services:caminoServices];
-    NSArray* browsers = [NSArray arrayWithObjects:
-                         mockSafari, mockFirefox, mockCamino, nil];
-    controller_ = [[ImportSettingsDialogController alloc]
-                   initWithProfiles:browsers];
-  }
-
-  virtual void TearDown() {
-    controller_ = NULL;
-    CocoaTest::TearDown();
-  }
-};
-
-TEST_F(ImportSettingsDialogTest, CancelDialog) {
-  [controller_ cancel:nil];
-}
-
-TEST_F(ImportSettingsDialogTest, ChooseVariousBrowsers) {
-  // Initial choice should already be MockSafari with all items enabled.
-  [controller_ setSourceBrowserIndex:0];
-  EXPECT_TRUE([controller_ importHistory]);
-  EXPECT_TRUE([controller_ historyAvailable]);
-  EXPECT_TRUE([controller_ importFavorites]);
-  EXPECT_TRUE([controller_ favoritesAvailable]);
-  EXPECT_TRUE([controller_ importPasswords]);
-  EXPECT_TRUE([controller_ passwordsAvailable]);
-  EXPECT_TRUE([controller_ importSearchEngines]);
-  EXPECT_TRUE([controller_ searchEnginesAvailable]);
-  EXPECT_EQ(HISTORY | FAVORITES | PASSWORDS | SEARCH_ENGINES,
-            [controller_ servicesToImport]);
-
-  // Next choice we test is MockCamino.
-  [controller_ setSourceBrowserIndex:2];
-  EXPECT_TRUE([controller_ importHistory]);
-  EXPECT_TRUE([controller_ historyAvailable]);
-  EXPECT_FALSE([controller_ importFavorites]);
-  EXPECT_FALSE([controller_ favoritesAvailable]);
-  EXPECT_FALSE([controller_ importPasswords]);
-  EXPECT_FALSE([controller_ passwordsAvailable]);
-  EXPECT_TRUE([controller_ importSearchEngines]);
-  EXPECT_TRUE([controller_ searchEnginesAvailable]);
-  EXPECT_EQ(HISTORY | SEARCH_ENGINES, [controller_ servicesToImport]);
-
-  // Next choice we test is MockFirefox.
-  [controller_ setSourceBrowserIndex:1];
-  EXPECT_TRUE([controller_ importHistory]);
-  EXPECT_TRUE([controller_ historyAvailable]);
-  EXPECT_TRUE([controller_ importFavorites]);
-  EXPECT_TRUE([controller_ favoritesAvailable]);
-  EXPECT_TRUE([controller_ importPasswords]);
-  EXPECT_TRUE([controller_ passwordsAvailable]);
-  EXPECT_FALSE([controller_ importSearchEngines]);
-  EXPECT_FALSE([controller_ searchEnginesAvailable]);
-  EXPECT_EQ(HISTORY | FAVORITES | PASSWORDS, [controller_ servicesToImport]);
-
-  [controller_ cancel:nil];
-}
-
-TEST_F(ImportSettingsDialogTest, SetVariousSettings) {
-  // Leave the choice MockSafari, but toggle the settings.
-  [controller_ setImportHistory:NO];
-  [controller_ setImportFavorites:NO];
-  [controller_ setImportPasswords:NO];
-  [controller_ setImportSearchEngines:NO];
-  EXPECT_EQ(NONE, [controller_ servicesToImport]);
-  EXPECT_FALSE([controller_ importSomething]);
-
-  [controller_ setImportHistory:YES];
-  EXPECT_EQ(HISTORY, [controller_ servicesToImport]);
-  EXPECT_TRUE([controller_ importSomething]);
-
-  [controller_ setImportHistory:NO];
-  [controller_ setImportFavorites:YES];
-  EXPECT_EQ(FAVORITES, [controller_ servicesToImport]);
-  EXPECT_TRUE([controller_ importSomething]);
-  [controller_ setImportFavorites:NO];
-
-  [controller_ setImportPasswords:YES];
-  EXPECT_EQ(PASSWORDS, [controller_ servicesToImport]);
-  EXPECT_TRUE([controller_ importSomething]);
-
-  [controller_ setImportPasswords:NO];
-  [controller_ setImportSearchEngines:YES];
-  EXPECT_EQ(SEARCH_ENGINES, [controller_ servicesToImport]);
-  EXPECT_TRUE([controller_ importSomething]);
-
-  [controller_ cancel:nil];
-}
diff --git a/chrome/browser/ui/cocoa/importer/OWNERS b/chrome/browser/ui/cocoa/importer/OWNERS
new file mode 100644
index 0000000..d76d5ad
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/OWNERS
@@ -0,0 +1 @@
+mirandac@chromium.org
diff --git a/chrome/browser/ui/cocoa/importer/import_progress_dialog.h b/chrome/browser/ui/cocoa/importer/import_progress_dialog.h
new file mode 100644
index 0000000..da4480a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/import_progress_dialog.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_IMPORTER_IMPORT_PROGRESS_DIALOG_H_
+#define CHROME_BROWSER_IMPORTER_IMPORT_PROGRESS_DIALOG_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/importer/importer_data_types.h"
+
+class ImporterObserverBridge;
+
+// Class that acts as a controller for the dialog that shows progress for an
+// import operation.
+// Lifetime: This object is responsible for deleting itself.
+@interface ImportProgressDialogController : NSWindowController {
+  scoped_ptr<ImporterObserverBridge> import_host_observer_bridge_;
+  ImporterHost* importer_host_;  // (weak)
+  ImportObserver* observer_;  // (weak)
+
+  // Strings bound to static labels in the UI dialog.
+  NSString* explanatory_text_;
+  NSString* favorites_status_text_;
+  NSString* search_status_text_;
+  NSString* saved_password_status_text_;
+  NSString* history_status_text_;
+
+  // Bound to the color of the status text (this is the easiest way to disable
+  // progress items that aren't supported by the current browser we're importing
+  // from).
+  NSColor* favorites_import_enabled_;
+  NSColor* search_import_enabled_;
+  NSColor* password_import_enabled_;
+  NSColor* history_import_enabled_;
+
+  // Placeholders for "Importing..." and "Done" text.
+  NSString* progress_text_;
+  NSString* done_text_;
+}
+
+@property(nonatomic, retain) NSString* explanatoryText;
+@property(nonatomic, retain) NSString* favoritesStatusText;
+@property(nonatomic, retain) NSString* searchStatusText;
+@property(nonatomic, retain) NSString* savedPasswordStatusText;
+@property(nonatomic, retain) NSString* historyStatusText;
+
+@property(nonatomic, retain) NSColor* favoritesImportEnabled;
+@property(nonatomic, retain) NSColor* searchImportEnabled;
+@property(nonatomic, retain) NSColor* passwordImportEnabled;
+@property(nonatomic, retain) NSColor* historyImportEnabled;
+
+// Cancel button calls this.
+- (IBAction)cancel:(id)sender;
+
+// Closes the dialog.
+- (void)closeDialog;
+
+// Methods called by importer_host via ImporterObserverBridge.
+- (void)ImportItemStarted:(importer::ImportItem)item;
+- (void)ImportItemEnded:(importer::ImportItem)item;
+- (void)ImportEnded;
+
+@end
+
+// C++ -> objc bridge for import status notifications.
+class ImporterObserverBridge : public ImporterHost::Observer {
+ public:
+  ImporterObserverBridge(ImportProgressDialogController* owner)
+      : owner_(owner) {}
+  virtual ~ImporterObserverBridge() {}
+
+  // Invoked when data for the specified item is about to be collected.
+  virtual void ImportItemStarted(importer::ImportItem item) {
+    [owner_ ImportItemStarted:item];
+  }
+
+  // Invoked when data for the specified item has been collected from the
+  // source profile and is now ready for further processing.
+  virtual void ImportItemEnded(importer::ImportItem item) {
+    [owner_ ImportItemEnded:item];
+  }
+
+  // Invoked when the import begins.
+  virtual void ImportStarted() {
+    // Not needed for out of process import.
+  }
+
+  // Invoked when the source profile has been imported.
+  virtual void ImportEnded() {
+    [owner_ ImportEnded];
+  }
+
+ private:
+  ImportProgressDialogController* owner_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImporterObserverBridge);
+};
+
+#endif  // CHROME_BROWSER_IMPORTER_IMPORT_PROGRESS_DIALOG_H_
diff --git a/chrome/browser/ui/cocoa/importer/import_progress_dialog.mm b/chrome/browser/ui/cocoa/importer/import_progress_dialog.mm
new file mode 100644
index 0000000..eed979f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/import_progress_dialog.mm
@@ -0,0 +1,192 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/importer/import_progress_dialog.h"
+
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "base/message_loop.h"
+#import "base/scoped_nsobject.h"
+#import "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+namespace {
+
+// Convert ImportItem enum into the name of the ImportProgressDialogController
+// property corresponding to the text for that item, this makes the code to
+// change the values for said properties much more readable.
+NSString* keyForImportItem(importer::ImportItem item) {
+  switch(item) {
+    case importer::HISTORY:
+      return @"historyStatusText";
+    case importer::FAVORITES:
+      return @"favoritesStatusText";
+    case importer::PASSWORDS:
+      return @"savedPasswordStatusText";
+    case importer::SEARCH_ENGINES:
+      return @"searchStatusText";
+    default:
+      DCHECK(false);
+      break;
+  }
+  return nil;
+}
+
+}  // namespace
+
+@implementation ImportProgressDialogController
+
+@synthesize explanatoryText = explanatory_text_;
+@synthesize favoritesStatusText = favorites_status_text_;
+@synthesize searchStatusText = search_status_text_;
+@synthesize savedPasswordStatusText = saved_password_status_text_;
+@synthesize historyStatusText = history_status_text_;
+
+@synthesize favoritesImportEnabled = favorites_import_enabled_;
+@synthesize searchImportEnabled = search_import_enabled_;
+@synthesize passwordImportEnabled = password_import_enabled_;
+@synthesize historyImportEnabled = history_import_enabled_;
+
+- (id)initWithImporterHost:(ImporterHost*)host
+               browserName:(string16)browserName
+                  observer:(ImportObserver*)observer
+              itemsEnabled:(int16)items {
+  NSString* nib_path =
+      [base::mac::MainAppBundle() pathForResource:@"ImportProgressDialog"
+                                          ofType:@"nib"];
+  self = [super initWithWindowNibPath:nib_path owner:self];
+  if (self != nil) {
+    importer_host_ = host;
+    observer_ = observer;
+    import_host_observer_bridge_.reset(new ImporterObserverBridge(self));
+    importer_host_->SetObserver(import_host_observer_bridge_.get());
+
+    string16 productName = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
+    NSString* explanatory_text = l10n_util::GetNSStringF(
+        IDS_IMPORT_PROGRESS_EXPLANATORY_TEXT_MAC,
+        productName,
+        browserName);
+    [self setExplanatoryText:explanatory_text];
+
+    progress_text_ =
+        [l10n_util::GetNSStringWithFixup(IDS_IMPORT_IMPORTING_PROGRESS_TEXT_MAC)
+        retain];
+    done_text_ =
+        [l10n_util::GetNSStringWithFixup(IDS_IMPORT_IMPORTING_DONE_TEXT_MAC)
+         retain];
+
+    // Enable/disable item titles.
+    NSColor* disabled = [NSColor disabledControlTextColor];
+    NSColor* active = [NSColor textColor];
+    [self setFavoritesImportEnabled:items & importer::FAVORITES ? active :
+        disabled];
+    [self setSearchImportEnabled:items & importer::SEARCH_ENGINES ? active :
+        disabled];
+    [self setPasswordImportEnabled:items & importer::PASSWORDS ? active :
+        disabled];
+    [self setHistoryImportEnabled:items & importer::HISTORY ? active :
+        disabled];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [explanatory_text_ release];
+  [favorites_status_text_ release];
+  [search_status_text_ release];
+  [saved_password_status_text_ release];
+  [history_status_text_ release];
+
+  [favorites_import_enabled_ release];
+  [search_import_enabled_ release];
+  [password_import_enabled_ release];
+  [history_import_enabled_ release];
+
+  [progress_text_ release];
+  [done_text_ release];
+
+  [super dealloc];
+}
+
+- (IBAction)showWindow:(id)sender {
+  NSWindow* win = [self window];
+  [win center];
+  [super showWindow:nil];
+}
+
+- (void)closeDialog {
+  if ([[self window] isVisible]) {
+    [[self window] close];
+  }
+}
+
+- (IBAction)cancel:(id)sender {
+  // The ImporterHost will notify import_host_observer_bridge_ that import has
+  // ended, which will trigger the ImportEnded method, in which this object is
+  // released.
+  importer_host_->Cancel();
+}
+
+- (void)ImportItemStarted:(importer::ImportItem)item {
+  [self setValue:progress_text_ forKey:keyForImportItem(item)];
+}
+
+- (void)ImportItemEnded:(importer::ImportItem)item {
+  [self setValue:done_text_ forKey:keyForImportItem(item)];
+}
+
+- (void)ImportEnded {
+  importer_host_->SetObserver(NULL);
+  if (observer_)
+    observer_->ImportComplete();
+  [self closeDialog];
+  [self release];
+
+  // Break out of modal event loop.
+  [NSApp stopModal];
+}
+
+@end
+
+void StartImportingWithUI(gfx::NativeWindow parent_window,
+                          uint16 items,
+                          ImporterHost* coordinator,
+                          const importer::ProfileInfo& source_profile,
+                          Profile* target_profile,
+                          ImportObserver* observer,
+                          bool first_run) {
+  DCHECK(items != 0);
+
+  // Retrieve name of browser we're importing from and do a little dance to
+  // convert wstring -> string16.
+  string16 import_browser_name = WideToUTF16Hack(source_profile.description);
+
+  // progress_dialog_ is responsible for deleting itself.
+  ImportProgressDialogController* progress_dialog_ =
+      [[ImportProgressDialogController alloc]
+          initWithImporterHost:coordinator
+                  browserName:import_browser_name
+                      observer:observer
+                  itemsEnabled:items];
+   // Call is async.
+  coordinator->StartImportSettings(source_profile, target_profile, items,
+                                   new ProfileWriter(target_profile),
+                                   first_run);
+
+  // Display the window while spinning a message loop.
+  // For details on why we need a modal message loop see http://crbug.com/19169
+  NSWindow* progress_window = [progress_dialog_ window];
+  NSModalSession session = [NSApp beginModalSessionForWindow:progress_window];
+  [progress_dialog_ showWindow:nil];
+  while (true) {
+    if ([NSApp runModalSession:session] != NSRunContinuesResponse)
+        break;
+    MessageLoop::current()->RunAllPending();
+  }
+  [NSApp endModalSession:session];
+}
diff --git a/chrome/browser/ui/cocoa/importer/import_settings_dialog.h b/chrome/browser/ui/cocoa/importer/import_settings_dialog.h
new file mode 100644
index 0000000..c2f922e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/import_settings_dialog.h
@@ -0,0 +1,104 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_COCOA_IMPORTER_IMPORT_SETTINGS_DIALOG_H_
+#define CHROME_BROWSER_UI_COCOA_IMPORTER_IMPORT_SETTINGS_DIALOG_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/importer/importer.h"
+
+class Profile;
+class ImporterListObserverBridge;
+
+// Controller for the Import Bookmarks and Settings dialog.  This controller
+// automatically autoreleases itself when its associated dialog is dismissed.
+@interface ImportSettingsDialogController : NSWindowController {
+ @private
+  NSWindow* parentWindow_;  // weak
+  Profile* profile_;  // weak
+  scoped_refptr<ImporterList> importerList_;
+  scoped_ptr<ImporterListObserverBridge> importerListObserver_;
+  scoped_nsobject<NSArray> sourceBrowsersList_;
+  NSUInteger sourceBrowserIndex_;
+  // The following are all bound via the properties below.
+  BOOL importHistory_;
+  BOOL importFavorites_;
+  BOOL importPasswords_;
+  BOOL importSearchEngines_;
+  BOOL historyAvailable_;
+  BOOL favoritesAvailable_;
+  BOOL passwordsAvailable_;
+  BOOL searchEnginesAvailable_;
+  IBOutlet NSPopUpButton* sourceProfilePopUpButton_;
+}
+
+// Show the import settings window.  Window is displayed as an app modal dialog.
+// If the dialog is already being displayed, this method whill return with
+// no error.
++ (void)showImportSettingsDialogForProfile:(Profile*)profile;
+
+// Called when the "Import" button is pressed.
+- (IBAction)ok:(id)sender;
+
+// Cancel button calls this.
+- (IBAction)cancel:(id)sender;
+
+// An array of ImportSettingsProfiles, provide the list of browser profiles
+// available for importing. Bound to the Browser List array controller.
+- (NSArray*)sourceBrowsersList;
+
+// Called when source profiles have been loaded.
+- (void)sourceProfilesLoaded;
+
+// Properties for bindings.
+@property(assign, nonatomic) NSUInteger sourceBrowserIndex;
+@property(assign, readonly, nonatomic) BOOL importSomething;
+// Bindings for the value of the import checkboxes.
+@property(assign, nonatomic) BOOL importHistory;
+@property(assign, nonatomic) BOOL importFavorites;
+@property(assign, nonatomic) BOOL importPasswords;
+@property(assign, nonatomic) BOOL importSearchEngines;
+// Bindings for enabling/disabling the checkboxes.
+@property(assign, readonly, nonatomic) BOOL historyAvailable;
+@property(assign, readonly, nonatomic) BOOL favoritesAvailable;
+@property(assign, readonly, nonatomic) BOOL passwordsAvailable;
+@property(assign, readonly, nonatomic) BOOL searchEnginesAvailable;
+
+@end
+
+@interface ImportSettingsDialogController (TestingAPI)
+
+// Initialize by providing an array of source profile dictionaries. Exposed for
+// unit testing but also called by -[initWithProfile:].
+- (id)initWithSourceProfiles:(NSArray*)profiles;
+
+// Return selected services to import as mapped by the ImportItem enum.
+- (uint16)servicesToImport;
+
+@end
+
+// Utility class used as array elements for sourceBrowsersList, above.
+@interface ImportSettingsProfile : NSObject {
+ @private
+  NSString* browserName_;
+  uint16 services_;  // Services as defined by enum ImportItem.
+}
+
+// Convenience creator. |services| is a bitfield of enum ImportItems.
++ (id)importSettingsProfileWithBrowserName:(NSString*)browserName
+                                  services:(uint16)services;
+
+// Designated initializer. |services| is a bitfield of enum ImportItems.
+- (id)initWithBrowserName:(NSString*)browserName
+                 services:(uint16)services;  // Bitfield of enum ImportItems.
+
+@property(copy, nonatomic) NSString* browserName;
+@property(assign, nonatomic) uint16 services;  // Bitfield of enum ImportItems.
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_IMPORTER_IMPORT_SETTINGS_DIALOG_H_
diff --git a/chrome/browser/ui/cocoa/importer/import_settings_dialog.mm b/chrome/browser/ui/cocoa/importer/import_settings_dialog.mm
new file mode 100644
index 0000000..c5822f7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/import_settings_dialog.mm
@@ -0,0 +1,301 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/importer/import_settings_dialog.h"
+
+#include "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/importer/importer_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+// Bridge to receive observer messages from an ImporterList and relay
+// them to the ImportSettingsDialogController.
+class ImporterListObserverBridge : public ImporterList::Observer {
+ public:
+  explicit ImporterListObserverBridge(
+      ImportSettingsDialogController *controller);
+
+  virtual void SourceProfilesLoaded();
+
+ private:
+  ImportSettingsDialogController* window_controller_;  // weak, owns us.
+};
+
+ImporterListObserverBridge::ImporterListObserverBridge(
+    ImportSettingsDialogController *controller)
+  : window_controller_(controller) {
+}
+
+void ImporterListObserverBridge::SourceProfilesLoaded() {
+  [window_controller_ sourceProfilesLoaded];
+}
+
+namespace {
+
+bool importSettingsDialogVisible = false;
+
+}  // namespace
+
+@interface ImportSettingsDialogController ()
+
+@property(assign, readwrite, nonatomic) BOOL historyAvailable;
+@property(assign, readwrite, nonatomic) BOOL favoritesAvailable;
+@property(assign, readwrite, nonatomic) BOOL passwordsAvailable;
+@property(assign, readwrite, nonatomic) BOOL searchEnginesAvailable;
+
+@end
+
+@implementation ImportSettingsProfile
+
+@synthesize browserName = browserName_;
+@synthesize services = services_;
+
++ (id)importSettingsProfileWithBrowserName:(NSString*)browserName
+                                  services:(uint16)services {
+  id settingsProfile = [[[ImportSettingsProfile alloc]
+                        initWithBrowserName:browserName
+                         services:services] autorelease];
+  return settingsProfile;
+}
+
+- (id)initWithBrowserName:(NSString*)browserName
+                 services:(uint16)services {
+  DCHECK(browserName);
+  if ((self = [super init])) {
+    if (browserName) {
+      browserName_ = [browserName retain];
+      services_ = services;
+    } else {
+      [self release];
+      self = nil;
+    }
+  }
+  return self;
+}
+
+- (id)init {
+  NOTREACHED();  // Should never be called.
+  return [self initWithBrowserName:NULL services:0];
+}
+
+- (void)dealloc {
+  [browserName_ release];
+  [super dealloc];
+}
+
+@end
+
+@interface ImportSettingsDialogController (Private)
+
+// Initialize the dialog controller with either the default profile or
+// the profile for the current browser.
+- (id)initWithProfile:(Profile*)profile;
+
+// Present the app modal dialog.
+- (void)runModalDialog;
+
+// Close the modal dialog.
+- (void)closeDialog;
+
+@end
+
+@implementation ImportSettingsDialogController
+
+@synthesize sourceBrowserIndex = sourceBrowserIndex_;
+@synthesize importHistory = importHistory_;
+@synthesize importFavorites = importFavorites_;
+@synthesize importPasswords = importPasswords_;
+@synthesize importSearchEngines = importSearchEngines_;
+@synthesize historyAvailable = historyAvailable_;
+@synthesize favoritesAvailable = favoritesAvailable_;
+@synthesize passwordsAvailable = passwordsAvailable_;
+@synthesize searchEnginesAvailable = searchEnginesAvailable_;
+
+// Set bindings dependencies for importSomething property.
++ (NSSet*)keyPathsForValuesAffectingImportSomething {
+  return [NSSet setWithObjects:@"importHistory", @"importFavorites",
+          @"importPasswords", @"importSearchEngines", nil];
+}
+
++ (void)showImportSettingsDialogForProfile:(Profile*)profile {
+  // Don't display if already visible.
+  if (importSettingsDialogVisible)
+    return;
+  ImportSettingsDialogController* controller =
+      [[ImportSettingsDialogController alloc] initWithProfile:profile];
+  [controller runModalDialog];
+}
+
+- (id)initWithProfile:(Profile*)profile {
+  // Collect profile information (profile name and the services which can
+  // be imported from each) into an array of ImportSettingsProfile which
+  // are bound to the Browser List array controller and the popup name
+  // presentation.  The services element is used to indirectly control
+  // checkbox enabling.
+  importerList_ = new ImporterList;
+  ImporterList& importerList(*(importerList_.get()));
+  importerListObserver_.reset(new ImporterListObserverBridge(self));
+  importerList.DetectSourceProfiles(importerListObserver_.get());
+
+  if ((self = [self initWithSourceProfiles:nil])) {
+    profile_ = profile;
+  }
+  return self;
+}
+
+- (id)initWithSourceProfiles:(NSArray*)profiles {
+  NSString* nibpath =
+      [base::mac::MainAppBundle() pathForResource:@"ImportSettingsDialog"
+                                          ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self]) && profiles)
+    sourceBrowsersList_.reset([profiles retain]);
+
+  return self;
+}
+
+- (id)init {
+  return [self initWithProfile:nil];
+}
+
+- (void)dealloc {
+  if (importerList_)
+    importerList_->SetObserver(NULL);
+  [super dealloc];
+}
+
+- (void)awakeFromNib {
+  // Force an update of the checkbox enabled states.
+  [self setSourceBrowserIndex:0];
+}
+
+// Run application modal.
+- (void)runModalDialog {
+  importSettingsDialogVisible = true;
+  [NSApp runModalForWindow:[self window]];
+}
+
+- (IBAction)ok:(id)sender {
+  [self closeDialog];
+  const importer::ProfileInfo& sourceProfile =
+      importerList_.get()->GetSourceProfileInfoAt([self sourceBrowserIndex]);
+  uint16 items = sourceProfile.services_supported;
+  uint16 servicesToImport = items & [self servicesToImport];
+  if (servicesToImport) {
+    if (profile_) {
+      ImporterHost* importerHost = new ExternalProcessImporterHost;
+      // Note that a side effect of the following call is to cause the
+      // importerHost to be disposed once the import has completed.
+      StartImportingWithUI(nil, servicesToImport, importerHost,
+                           sourceProfile, profile_, nil, false);
+    }
+  } else {
+    LOG(WARNING) << "There were no settings to import from '"
+                 << sourceProfile.description << "'.";
+  }
+}
+
+- (IBAction)cancel:(id)sender {
+  [self closeDialog];
+}
+
+- (void)closeDialog {
+  importSettingsDialogVisible = false;
+  [[self window] orderOut:self];
+  [NSApp stopModal];
+  [self autorelease];
+}
+
+- (void)sourceProfilesLoaded {
+  NSMutableArray* browserProfiles;
+  ImporterList& importerList(*(importerList_.get()));
+  int profilesCount = importerList.GetAvailableProfileCount();
+  if (profilesCount) {
+    browserProfiles =
+        [[NSMutableArray alloc] initWithCapacity:profilesCount];
+    for (int i = 0; i < profilesCount; ++i) {
+      const importer::ProfileInfo& sourceProfile =
+          importerList.GetSourceProfileInfoAt(i);
+      NSString* browserName =
+          base::SysWideToNSString(sourceProfile.description);
+      uint16 browserServices = sourceProfile.services_supported;
+      ImportSettingsProfile* settingsProfile =
+          [ImportSettingsProfile
+              importSettingsProfileWithBrowserName:browserName
+                                          services:browserServices];
+      [browserProfiles addObject:settingsProfile];
+    }
+  } else {
+    browserProfiles =
+        [[NSMutableArray alloc] initWithCapacity:1];
+    NSString* dummyName = l10n_util::GetNSString(IDS_IMPORT_NO_PROFILE_FOUND);
+    ImportSettingsProfile* dummySourceProfile =
+        [ImportSettingsProfile importSettingsProfileWithBrowserName:dummyName
+                                                           services:0];
+    [browserProfiles addObject:dummySourceProfile];
+  }
+
+  [self willChangeValueForKey:@"sourceBrowsersList"];
+  sourceBrowsersList_.reset(browserProfiles);
+  [self didChangeValueForKey:@"sourceBrowsersList"];
+
+  // Force an update of the checkbox enabled states.
+  [self setSourceBrowserIndex:0];
+
+  // Resize and show the popup button.
+  [sourceProfilePopUpButton_ sizeToFit];
+  [sourceProfilePopUpButton_ setHidden:NO];
+}
+
+#pragma mark Accessors
+
+- (NSArray*)sourceBrowsersList {
+  return sourceBrowsersList_.get();
+}
+
+// Accessor which cascades selected-browser changes into a re-evaluation of the
+// available services and the associated checkbox enable and checked states.
+- (void)setSourceBrowserIndex:(NSUInteger)browserIndex {
+  uint16 items = 0;
+  if ([sourceBrowsersList_.get() count]) {
+    [self willChangeValueForKey:@"sourceBrowserIndex"];
+    sourceBrowserIndex_ = browserIndex;
+    [self didChangeValueForKey:@"sourceBrowserIndex"];
+
+    ImportSettingsProfile* profile =
+        [sourceBrowsersList_.get() objectAtIndex:browserIndex];
+    items = [profile services];
+  }
+  [self setHistoryAvailable:(items & importer::HISTORY) ? YES : NO];
+  [self setImportHistory:[self historyAvailable]];
+  [self setFavoritesAvailable:(items & importer::FAVORITES) ? YES : NO];
+  [self setImportFavorites:[self favoritesAvailable]];
+  [self setPasswordsAvailable:(items & importer::PASSWORDS) ? YES : NO];
+  [self setImportPasswords:[self passwordsAvailable]];
+  [self setSearchEnginesAvailable:(items & importer::SEARCH_ENGINES) ?
+      YES : NO];
+  [self setImportSearchEngines:[self searchEnginesAvailable]];
+}
+
+- (uint16)servicesToImport {
+  uint16 servicesToImport = 0;
+  if ([self importHistory]) servicesToImport |= importer::HISTORY;
+  if ([self importFavorites]) servicesToImport |= importer::FAVORITES;
+  if ([self importPasswords]) servicesToImport |= importer::PASSWORDS;
+  if ([self importSearchEngines]) servicesToImport |=
+      importer::SEARCH_ENGINES;
+  return servicesToImport;
+}
+
+// KVO accessor which returns YES if at least one of the services
+// provided by the selected profile has been marked for importing
+// and bound to the OK button's enable property.
+- (BOOL)importSomething {
+  return [self importHistory] || [self importFavorites] ||
+      [self importPasswords] || [self importSearchEngines];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/importer/import_settings_dialog_unittest.mm b/chrome/browser/ui/cocoa/importer/import_settings_dialog_unittest.mm
new file mode 100644
index 0000000..4fa15af
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/import_settings_dialog_unittest.mm
@@ -0,0 +1,130 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/importer/importer.h"
+#import "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/importer/import_settings_dialog.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+using importer::HISTORY;
+using importer::FAVORITES;
+using importer::COOKIES;
+using importer::PASSWORDS;
+using importer::SEARCH_ENGINES;
+using importer::NONE;
+
+class ImportSettingsDialogTest : public CocoaTest {
+ public:
+  ImportSettingsDialogController* controller_;
+
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    unsigned int safariServices =
+        HISTORY | FAVORITES | COOKIES | PASSWORDS | SEARCH_ENGINES;
+    ImportSettingsProfile* mockSafari =
+        [ImportSettingsProfile
+         importSettingsProfileWithBrowserName:@"MockSafari"
+                                     services:safariServices];
+    unsigned int firefoxServices = HISTORY | FAVORITES | COOKIES | PASSWORDS;
+    ImportSettingsProfile* mockFirefox =
+        [ImportSettingsProfile
+         importSettingsProfileWithBrowserName:@"MockFirefox"
+                                     services:firefoxServices];
+    unsigned int caminoServices = HISTORY | COOKIES | SEARCH_ENGINES;
+    ImportSettingsProfile* mockCamino =
+        [ImportSettingsProfile
+         importSettingsProfileWithBrowserName:@"MockCamino"
+                                     services:caminoServices];
+    NSArray* browsers = [NSArray arrayWithObjects:
+                         mockSafari, mockFirefox, mockCamino, nil];
+    controller_ = [[ImportSettingsDialogController alloc]
+                   initWithSourceProfiles:browsers];
+  }
+
+  virtual void TearDown() {
+    controller_ = NULL;
+    CocoaTest::TearDown();
+  }
+};
+
+TEST_F(ImportSettingsDialogTest, CancelDialog) {
+  [controller_ cancel:nil];
+}
+
+TEST_F(ImportSettingsDialogTest, ChooseVariousBrowsers) {
+  // Initial choice should already be MockSafari with all items enabled.
+  [controller_ setSourceBrowserIndex:0];
+  EXPECT_TRUE([controller_ importHistory]);
+  EXPECT_TRUE([controller_ historyAvailable]);
+  EXPECT_TRUE([controller_ importFavorites]);
+  EXPECT_TRUE([controller_ favoritesAvailable]);
+  EXPECT_TRUE([controller_ importPasswords]);
+  EXPECT_TRUE([controller_ passwordsAvailable]);
+  EXPECT_TRUE([controller_ importSearchEngines]);
+  EXPECT_TRUE([controller_ searchEnginesAvailable]);
+  EXPECT_EQ(HISTORY | FAVORITES | PASSWORDS | SEARCH_ENGINES,
+            [controller_ servicesToImport]);
+
+  // Next choice we test is MockCamino.
+  [controller_ setSourceBrowserIndex:2];
+  EXPECT_TRUE([controller_ importHistory]);
+  EXPECT_TRUE([controller_ historyAvailable]);
+  EXPECT_FALSE([controller_ importFavorites]);
+  EXPECT_FALSE([controller_ favoritesAvailable]);
+  EXPECT_FALSE([controller_ importPasswords]);
+  EXPECT_FALSE([controller_ passwordsAvailable]);
+  EXPECT_TRUE([controller_ importSearchEngines]);
+  EXPECT_TRUE([controller_ searchEnginesAvailable]);
+  EXPECT_EQ(HISTORY | SEARCH_ENGINES, [controller_ servicesToImport]);
+
+  // Next choice we test is MockFirefox.
+  [controller_ setSourceBrowserIndex:1];
+  EXPECT_TRUE([controller_ importHistory]);
+  EXPECT_TRUE([controller_ historyAvailable]);
+  EXPECT_TRUE([controller_ importFavorites]);
+  EXPECT_TRUE([controller_ favoritesAvailable]);
+  EXPECT_TRUE([controller_ importPasswords]);
+  EXPECT_TRUE([controller_ passwordsAvailable]);
+  EXPECT_FALSE([controller_ importSearchEngines]);
+  EXPECT_FALSE([controller_ searchEnginesAvailable]);
+  EXPECT_EQ(HISTORY | FAVORITES | PASSWORDS, [controller_ servicesToImport]);
+
+  [controller_ cancel:nil];
+}
+
+TEST_F(ImportSettingsDialogTest, SetVariousSettings) {
+  // Leave the choice MockSafari, but toggle the settings.
+  [controller_ setImportHistory:NO];
+  [controller_ setImportFavorites:NO];
+  [controller_ setImportPasswords:NO];
+  [controller_ setImportSearchEngines:NO];
+  EXPECT_EQ(NONE, [controller_ servicesToImport]);
+  EXPECT_FALSE([controller_ importSomething]);
+
+  [controller_ setImportHistory:YES];
+  EXPECT_EQ(HISTORY, [controller_ servicesToImport]);
+  EXPECT_TRUE([controller_ importSomething]);
+
+  [controller_ setImportHistory:NO];
+  [controller_ setImportFavorites:YES];
+  EXPECT_EQ(FAVORITES, [controller_ servicesToImport]);
+  EXPECT_TRUE([controller_ importSomething]);
+  [controller_ setImportFavorites:NO];
+
+  [controller_ setImportPasswords:YES];
+  EXPECT_EQ(PASSWORDS, [controller_ servicesToImport]);
+  EXPECT_TRUE([controller_ importSomething]);
+
+  [controller_ setImportPasswords:NO];
+  [controller_ setImportSearchEngines:YES];
+  EXPECT_EQ(SEARCH_ENGINES, [controller_ servicesToImport]);
+  EXPECT_TRUE([controller_ importSomething]);
+
+  [controller_ cancel:nil];
+}
diff --git a/chrome/browser/ui/cocoa/importer/importer_lock_dialog.mm b/chrome/browser/ui/cocoa/importer/importer_lock_dialog.mm
new file mode 100644
index 0000000..aca152c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/importer/importer_lock_dialog.mm
@@ -0,0 +1,38 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/message_loop.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+namespace browser {
+
+void ShowImportLockDialog(gfx::NativeWindow parent,
+                          ImporterHost* importer_host) {
+  scoped_nsobject<NSAlert> lock_alert([[NSAlert alloc] init]);
+  [lock_alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
+      IDS_IMPORTER_LOCK_OK)];
+  [lock_alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
+      IDS_IMPORTER_LOCK_CANCEL)];
+  [lock_alert setInformativeText:l10n_util::GetNSStringWithFixup(
+      IDS_IMPORTER_LOCK_TEXT)];
+  [lock_alert setMessageText:l10n_util::GetNSStringWithFixup(
+      IDS_IMPORTER_LOCK_TITLE)];
+
+  if ([lock_alert runModal] == NSAlertFirstButtonReturn) {
+    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+        importer_host, &ImporterHost::OnLockViewEnd, true));
+  } else {
+    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+        importer_host, &ImporterHost::OnLockViewEnd, false));
+  }
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/cocoa/importer_lock_dialog.h b/chrome/browser/ui/cocoa/importer_lock_dialog.h
deleted file mode 100644
index ade74e2..0000000
--- a/chrome/browser/ui/cocoa/importer_lock_dialog.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_IMPORTER_LOCK_DIALOG_H_
-#define CHROME_BROWSER_UI_COCOA_IMPORTER_LOCK_DIALOG_H_
-#pragma once
-
-class ImporterHost;
-
-namespace ImportLockDialogCocoa {
-
-// This function is called by an ImporterHost, and displays the Firefox profile
-// locked warning by creating a modal NSAlert.  On the closing of the alert
-// box, the ImportHost receives a callback with the message either to skip the
-// import, or to try again.
-void ShowWarning(ImporterHost* importer);
-
-}
-
-#endif  // CHROME_BROWSER_UI_COCOA_IMPORTER_LOCK_DIALOG_H_
diff --git a/chrome/browser/ui/cocoa/importer_lock_dialog.mm b/chrome/browser/ui/cocoa/importer_lock_dialog.mm
deleted file mode 100644
index 2a140ae..0000000
--- a/chrome/browser/ui/cocoa/importer_lock_dialog.mm
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "importer_lock_dialog.h"
-
-#include "app/l10n_util_mac.h"
-#include "base/message_loop.h"
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/importer/importer.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-void ImportLockDialogCocoa::ShowWarning(ImporterHost* importer) {
-  scoped_nsobject<NSAlert> lock_alert([[NSAlert alloc] init]);
-  [lock_alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
-      IDS_IMPORTER_LOCK_OK)];
-  [lock_alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
-      IDS_IMPORTER_LOCK_CANCEL)];
-  [lock_alert setInformativeText:l10n_util::GetNSStringWithFixup(
-      IDS_IMPORTER_LOCK_TEXT)];
-  [lock_alert setMessageText:l10n_util::GetNSStringWithFixup(
-      IDS_IMPORTER_LOCK_TITLE)];
-
-  if ([lock_alert runModal] == NSAlertFirstButtonReturn) {
-    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-        importer, &ImporterHost::OnLockViewEnd, true));
-  } else {
-    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-        importer, &ImporterHost::OnLockViewEnd, false));
-  }
-}
diff --git a/chrome/browser/ui/cocoa/info_bubble_view.h b/chrome/browser/ui/cocoa/info_bubble_view.h
index e1238d2..fcdca2e 100644
--- a/chrome/browser/ui/cocoa/info_bubble_view.h
+++ b/chrome/browser/ui/cocoa/info_bubble_view.h
@@ -29,7 +29,7 @@
   info_bubble::BubbleArrowLocation arrowLocation_;
 }
 
-@property (assign, nonatomic) info_bubble::BubbleArrowLocation arrowLocation;
+@property(assign, nonatomic) info_bubble::BubbleArrowLocation arrowLocation;
 
 // Returns the point location in view coordinates of the tip of the arrow.
 - (NSPoint)arrowTip;
diff --git a/chrome/browser/ui/cocoa/info_bubble_window.h b/chrome/browser/ui/cocoa/info_bubble_window.h
index 38ae44d..ee91794 100644
--- a/chrome/browser/ui/cocoa/info_bubble_window.h
+++ b/chrome/browser/ui/cocoa/info_bubble_window.h
@@ -22,11 +22,11 @@
   scoped_ptr<AppNotificationBridge> notificationBridge_;
 }
 
+@property(nonatomic) BOOL delayOnClose;
+
 // Returns YES if the window is in the process of closing.
 // Can't use "windowWillClose" notification because that will be sent
 // after the closing animation has completed.
 - (BOOL)isClosing;
 
-@property (nonatomic) BOOL delayOnClose;
-
 @end
diff --git a/chrome/browser/ui/cocoa/infobar.h b/chrome/browser/ui/cocoa/infobar.h
deleted file mode 100644
index fc51da7..0000000
--- a/chrome/browser/ui/cocoa/infobar.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_INFOBAR_H_
-#define CHROME_BROWSER_UI_COCOA_INFOBAR_H_
-#pragma once
-
-#include "base/logging.h"  // for DCHECK
-
-@class InfoBarController;
-
-// A C++ wrapper around an Objective-C InfoBarController.  This class
-// exists solely to be the return value for InfoBarDelegate::CreateInfoBar(),
-// as defined in chrome/browser/tab_contents/infobar_delegate.h.  This
-// class would be analogous to the various bridge classes we already
-// have, but since there is no pre-defined InfoBar interface, it is
-// easier to simply throw away this object and deal with the
-// controller directly rather than pass messages through a bridge.
-//
-// Callers should delete the returned InfoBar immediately after
-// calling CreateInfoBar(), as the returned InfoBar* object is not
-// pointed to by anyone.  Expected usage:
-//
-// scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar());
-// InfoBarController* controller = infobar->controller();
-// // Do something with the controller, and save a pointer so it can be
-// // deleted later.  |infobar| will be deleted automatically.
-
-class InfoBar {
- public:
-  InfoBar(InfoBarController* controller) {
-    DCHECK(controller);
-    controller_ = controller;
-  }
-
-  InfoBarController* controller() {
-    return controller_;
-  }
-
- private:
-  // Pointer to the infobar controller.  Is never null.
-  InfoBarController* controller_;  // weak
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBar);
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_INFOBAR_H_
diff --git a/chrome/browser/ui/cocoa/infobar_container_controller.h b/chrome/browser/ui/cocoa/infobar_container_controller.h
deleted file mode 100644
index 82a7e52..0000000
--- a/chrome/browser/ui/cocoa/infobar_container_controller.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_INFOBAR_CONTAINER_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_INFOBAR_CONTAINER_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-#import "chrome/browser/ui/cocoa/view_resizer.h"
-#include "chrome/common/notification_registrar.h"
-
-@class InfoBarController;
-class InfoBarDelegate;
-class InfoBarNotificationObserver;
-class TabContents;
-class TabStripModel;
-
-// Protocol for basic container methods, as needed by an InfoBarController.
-// This protocol exists to make mocking easier in unittests.
-@protocol InfoBarContainer
-- (void)removeDelegate:(InfoBarDelegate*)delegate;
-- (void)removeController:(InfoBarController*)controller;
-@end
-
-// Controller for the infobar container view, which is the superview
-// of all the infobar views.  This class owns zero or more
-// InfoBarControllers, which manage the infobar views.  This class
-// also receives tab strip model notifications and handles
-// adding/removing infobars when needed.
-@interface InfoBarContainerController : NSViewController <ViewResizer,
-                                                          InfoBarContainer> {
- @private
-  // Needed to send resize messages when infobars are added or removed.
-  id<ViewResizer> resizeDelegate_;  // weak
-
-  // The TabContents we are currently showing infobars for.
-  TabContents* currentTabContents_;  // weak
-
-  // Holds the InfoBarControllers currently owned by this container.
-  scoped_nsobject<NSMutableArray> infobarControllers_;
-
-  // Lets us registers for INFOBAR_ADDED/INFOBAR_REMOVED
-  // notifications.  The actual notifications are sent to the
-  // InfoBarNotificationObserver object, which proxies them back to us.
-  NotificationRegistrar registrar_;
-  scoped_ptr<InfoBarNotificationObserver> infoBarObserver_;
-}
-
-- (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate;
-
-// Informs the selected TabContents that the infobars for the given
-// |delegate| need to be removed.  Does not remove any infobar views
-// directly, as they will be removed when handling the subsequent
-// INFOBAR_REMOVED notification.  Does not notify |delegate| that the
-// infobar was closed.
-- (void)removeDelegate:(InfoBarDelegate*)delegate;
-
-// Removes |controller| from the list of controllers in this container and
-// removes its view from the view hierarchy.  This method is safe to call while
-// |controller| is still on the call stack.
-- (void)removeController:(InfoBarController*)controller;
-
-// Modifies this container to display infobars for the given
-// |contents|.  Registers for INFOBAR_ADDED and INFOBAR_REMOVED
-// notifications for |contents|.  If we are currently showing any
-// infobars, removes them first and deregisters for any
-// notifications.  |contents| can be NULL, in which case no infobars
-// are shown and no notifications are registered for.
-- (void)changeTabContents:(TabContents*)contents;
-
-// Stripped down version of TabStripModelObserverBridge:tabDetachedWithContents.
-// Forwarded by BWC. Removes all infobars and deregisters for any notifications
-// if |contents| is the current tab contents.
-- (void)tabDetachedWithContents:(TabContents*)contents;
-
-@end
-
-
-@interface InfoBarContainerController (ForTheObserverAndTesting)
-
-// Adds an infobar view for the given delegate.
-- (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate;
-
-// Closes all the infobar views for a given delegate, either immediately or by
-// starting a close animation.
-- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate
-                         animate:(BOOL)animate;
-
-// Replaces all info bars for the delegate with a new info bar.
-// This simply calls closeInfoBarsForDelegate: and then addInfoBar:.
-- (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate
-                              with:(InfoBarDelegate*)new_delegate;
-
-// Positions the infobar views in the container view and notifies
-// |browser_controller_| that it needs to resize the container view.
-- (void)positionInfoBarsAndRedraw;
-
-@end
-
-
-@interface InfoBarContainerController (JustForTesting)
-
-// Removes all infobar views.  Callers must call
-// positionInfoBarsAndRedraw() after calling this method.
-- (void)removeAllInfoBars;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_INFOBAR_CONTAINER_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/infobar_container_controller.mm b/chrome/browser/ui/cocoa/infobar_container_controller.mm
deleted file mode 100644
index 3eb29dc..0000000
--- a/chrome/browser/ui/cocoa/infobar_container_controller.mm
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#import "chrome/browser/ui/cocoa/animatable_view.h"
-#include "chrome/browser/ui/cocoa/infobar.h"
-#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "skia/ext/skia_utils_mac.h"
-
-// C++ class that receives INFOBAR_ADDED and INFOBAR_REMOVED
-// notifications and proxies them back to |controller|.
-class InfoBarNotificationObserver : public NotificationObserver {
- public:
-  InfoBarNotificationObserver(InfoBarContainerController* controller)
-      : controller_(controller) {
-  }
-
- private:
-  // NotificationObserver implementation
-  void Observe(NotificationType type,
-               const NotificationSource& source,
-               const NotificationDetails& details) {
-    switch (type.value) {
-      case NotificationType::TAB_CONTENTS_INFOBAR_ADDED:
-        [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr()
-                        animate:YES];
-        break;
-      case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
-        [controller_
-          closeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr()
-                           animate:YES];
-        break;
-      case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: {
-        typedef std::pair<InfoBarDelegate*, InfoBarDelegate*>
-            InfoBarDelegatePair;
-        InfoBarDelegatePair* delegates =
-            Details<InfoBarDelegatePair>(details).ptr();
-        [controller_
-         replaceInfoBarsForDelegate:delegates->first with:delegates->second];
-        break;
-      }
-      default:
-        NOTREACHED();  // we don't ask for anything else!
-        break;
-    }
-
-    [controller_ positionInfoBarsAndRedraw];
-  }
-
-  InfoBarContainerController* controller_;  // weak, owns us.
-};
-
-
-@interface InfoBarContainerController (PrivateMethods)
-// Returns the desired height of the container view, computed by
-// adding together the heights of all its subviews.
-- (CGFloat)desiredHeight;
-
-@end
-
-
-@implementation InfoBarContainerController
-- (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate {
-  DCHECK(resizeDelegate);
-  if ((self = [super initWithNibName:@"InfoBarContainer"
-                              bundle:base::mac::MainAppBundle()])) {
-    resizeDelegate_ = resizeDelegate;
-    infoBarObserver_.reset(new InfoBarNotificationObserver(self));
-
-    // NSMutableArray needs an initial capacity, and we rarely ever see
-    // more than two infobars at a time, so that seems like a good choice.
-    infobarControllers_.reset([[NSMutableArray alloc] initWithCapacity:2]);
-  }
-  return self;
-}
-
-- (void)dealloc {
-  DCHECK([infobarControllers_ count] == 0);
-  view_id_util::UnsetID([self view]);
-  [super dealloc];
-}
-
-- (void)awakeFromNib {
-  // The info bar container view is an ordinary NSView object, so we set its
-  // ViewID here.
-  view_id_util::SetID([self view], VIEW_ID_INFO_BAR_CONTAINER);
-}
-
-- (void)removeDelegate:(InfoBarDelegate*)delegate {
-  DCHECK(currentTabContents_);
-  currentTabContents_->RemoveInfoBar(delegate);
-}
-
-- (void)removeController:(InfoBarController*)controller {
-  if (![infobarControllers_ containsObject:controller])
-    return;
-
-  // This code can be executed while InfoBarController is still on the stack, so
-  // we retain and autorelease the controller to prevent it from being
-  // dealloc'ed too early.
-  [[controller retain] autorelease];
-  [[controller view] removeFromSuperview];
-  [infobarControllers_ removeObject:controller];
-  [self positionInfoBarsAndRedraw];
-}
-
-- (void)changeTabContents:(TabContents*)contents {
-  registrar_.RemoveAll();
-  [self removeAllInfoBars];
-
-  currentTabContents_ = contents;
-  if (currentTabContents_) {
-    for (int i = 0; i < currentTabContents_->infobar_delegate_count(); ++i) {
-      [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i)
-               animate:NO];
-    }
-
-    Source<TabContents> source(currentTabContents_);
-    registrar_.Add(infoBarObserver_.get(),
-                   NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source);
-    registrar_.Add(infoBarObserver_.get(),
-                   NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source);
-    registrar_.Add(infoBarObserver_.get(),
-                   NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, source);
-  }
-
-  [self positionInfoBarsAndRedraw];
-}
-
-- (void)tabDetachedWithContents:(TabContents*)contents {
-  if (currentTabContents_ == contents)
-    [self changeTabContents:NULL];
-}
-
-- (void)resizeView:(NSView*)view newHeight:(CGFloat)height {
-  NSRect frame = [view frame];
-  frame.size.height = height;
-  [view setFrame:frame];
-  [self positionInfoBarsAndRedraw];
-}
-
-- (void)setAnimationInProgress:(BOOL)inProgress {
-  if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
-    [resizeDelegate_ setAnimationInProgress:inProgress];
-}
-
-@end
-
-@implementation InfoBarContainerController (PrivateMethods)
-
-- (CGFloat)desiredHeight {
-  CGFloat height = 0;
-  for (InfoBarController* controller in infobarControllers_.get())
-    height += NSHeight([[controller view] frame]);
-  return height;
-}
-
-- (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate {
-  scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar());
-  InfoBarController* controller = infobar->controller();
-  [controller setContainerController:self];
-  [[controller animatableView] setResizeDelegate:self];
-  [[self view] addSubview:[controller view]];
-  [infobarControllers_ addObject:[controller autorelease]];
-
-  if (animate)
-    [controller animateOpen];
-  else
-    [controller open];
-}
-
-- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate
-                         animate:(BOOL)animate {
-  for (InfoBarController* controller in
-       [NSArray arrayWithArray:infobarControllers_.get()]) {
-    if ([controller delegate] == delegate) {
-      if (animate)
-        [controller animateClosed];
-      else
-        [controller close];
-    }
-  }
-}
-
-- (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate
-                              with:(InfoBarDelegate*)new_delegate {
-  [self closeInfoBarsForDelegate:old_delegate animate:NO];
-  [self addInfoBar:new_delegate animate:NO];
-}
-
-- (void)removeAllInfoBars {
-  for (InfoBarController* controller in infobarControllers_.get()) {
-    [[controller animatableView] stopAnimation];
-    [[controller view] removeFromSuperview];
-  }
-  [infobarControllers_ removeAllObjects];
-}
-
-- (void)positionInfoBarsAndRedraw {
-  NSRect containerBounds = [[self view] bounds];
-  int minY = 0;
-
-  // Stack the infobars at the bottom of the view, starting with the
-  // last infobar and working our way to the front of the array.  This
-  // way we ensure that the first infobar added shows up on top, with
-  // the others below.
-  for (InfoBarController* controller in
-           [infobarControllers_ reverseObjectEnumerator]) {
-    NSView* view = [controller view];
-    NSRect frame = [view frame];
-    frame.origin.x = NSMinX(containerBounds);
-    frame.size.width = NSWidth(containerBounds);
-    frame.origin.y = minY;
-    minY += frame.size.height;
-    [view setFrame:frame];
-  }
-
-  [resizeDelegate_ resizeView:[self view] newHeight:[self desiredHeight]];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/infobar_container_controller_unittest.mm b/chrome/browser/ui/cocoa/infobar_container_controller_unittest.mm
deleted file mode 100644
index f04b1c1..0000000
--- a/chrome/browser/ui/cocoa/infobar_container_controller_unittest.mm
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
-#include "chrome/browser/ui/cocoa/infobar_test_helper.h"
-#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class InfoBarContainerControllerTest : public CocoaTest {
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    resizeDelegate_.reset([[ViewResizerPong alloc] init]);
-    ViewResizerPong *viewResizer = resizeDelegate_.get();
-    controller_ =
-        [[InfoBarContainerController alloc] initWithResizeDelegate:viewResizer];
-    NSView* view = [controller_ view];
-    [[test_window() contentView] addSubview:view];
-  }
-
-  virtual void TearDown() {
-    [[controller_ view] removeFromSuperviewWithoutNeedingDisplay];
-    [controller_ release];
-    CocoaTest::TearDown();
-  }
-
- public:
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
-  InfoBarContainerController* controller_;
-};
-
-TEST_VIEW(InfoBarContainerControllerTest, [controller_ view])
-
-TEST_F(InfoBarContainerControllerTest, BWCPong) {
-  // Call positionInfoBarsAndResize and check that |resizeDelegate_| got a
-  // resize message.
-  [resizeDelegate_ setHeight:-1];
-  [controller_ positionInfoBarsAndRedraw];
-  EXPECT_NE(-1, [resizeDelegate_ height]);
-}
-
-TEST_F(InfoBarContainerControllerTest, AddAndRemoveInfoBars) {
-  NSView* view = [controller_ view];
-
-  // Add three infobars, one of each type, and then remove them.
-  // After each step check to make sure we have the correct number of
-  // infobar subviews.
-  MockAlertInfoBarDelegate alertDelegate;
-  MockLinkInfoBarDelegate linkDelegate;
-  MockConfirmInfoBarDelegate confirmDelegate;
-
-  [controller_ addInfoBar:&alertDelegate animate:NO];
-  EXPECT_EQ(1U, [[view subviews] count]);
-
-  [controller_ addInfoBar:&linkDelegate animate:NO];
-  EXPECT_EQ(2U, [[view subviews] count]);
-
-  [controller_ addInfoBar:&confirmDelegate animate:NO];
-  EXPECT_EQ(3U, [[view subviews] count]);
-
-  // Just to mix things up, remove them in a different order.
-  [controller_ closeInfoBarsForDelegate:&linkDelegate animate:NO];
-  EXPECT_EQ(2U, [[view subviews] count]);
-
-  [controller_ closeInfoBarsForDelegate:&confirmDelegate animate:NO];
-  EXPECT_EQ(1U, [[view subviews] count]);
-
-  [controller_ closeInfoBarsForDelegate:&alertDelegate animate:NO];
-  EXPECT_EQ(0U, [[view subviews] count]);
-}
-
-TEST_F(InfoBarContainerControllerTest, RemoveAllInfoBars) {
-  NSView* view = [controller_ view];
-
-  // Add three infobars and then remove them all.
-  MockAlertInfoBarDelegate alertDelegate;
-  MockLinkInfoBarDelegate linkDelegate;
-  MockConfirmInfoBarDelegate confirmDelegate;
-
-  [controller_ addInfoBar:&alertDelegate animate:NO];
-  [controller_ addInfoBar:&linkDelegate animate:NO];
-  [controller_ addInfoBar:&confirmDelegate animate:NO];
-  EXPECT_EQ(3U, [[view subviews] count]);
-
-  [controller_ removeAllInfoBars];
-  EXPECT_EQ(0U, [[view subviews] count]);
-}
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/infobar_controller.h b/chrome/browser/ui/cocoa/infobar_controller.h
deleted file mode 100644
index e13d211..0000000
--- a/chrome/browser/ui/cocoa/infobar_controller.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_nsobject.h"
-
-@class AnimatableView;
-@class HoverCloseButton;
-@protocol InfoBarContainer;
-class InfoBarDelegate;
-@class InfoBarGradientView;
-
-// A controller for an infobar in the browser window.  There is one
-// controller per infobar view.  The base InfoBarController is able to
-// draw an icon, a text message, and a close button.  Subclasses can
-// override addAdditionalControls to customize the UI.
-@interface InfoBarController : NSViewController<NSTextViewDelegate> {
- @private
-  id<InfoBarContainer> containerController_;  // weak, owns us
-  BOOL infoBarClosing_;
-
- @protected
-  IBOutlet InfoBarGradientView* infoBarView_;
-  IBOutlet NSImageView* image_;
-  IBOutlet NSTextField* labelPlaceholder_;
-  IBOutlet NSButton* okButton_;
-  IBOutlet NSButton* cancelButton_;
-  IBOutlet HoverCloseButton* closeButton_;
-
-  // In rare instances, it can be possible for |delegate_| to delete itself
-  // while this controller is still alive.  Always check |delegate_| against
-  // NULL before using it.
-  InfoBarDelegate* delegate_;  // weak, can be NULL
-
-  // Text fields don't work as well with embedded links as text views, but
-  // text views cannot conveniently be created in IB. The xib file contains
-  // a text field |labelPlaceholder_| that's replaced by this text view |label_|
-  // in -awakeFromNib.
-  scoped_nsobject<NSTextView> label_;
-};
-
-// Initializes a new InfoBarController.
-- (id)initWithDelegate:(InfoBarDelegate*)delegate;
-
-// Called when someone clicks on the OK or Cancel buttons.  Subclasses
-// must override if they do not hide the buttons.
-- (void)ok:(id)sender;
-- (void)cancel:(id)sender;
-
-// Called when someone clicks on the close button.  Dismisses the
-// infobar without taking any action.
-- (IBAction)dismiss:(id)sender;
-
-// Returns a pointer to this controller's view, cast as an AnimatableView.
-- (AnimatableView*)animatableView;
-
-// Open or animate open the infobar.
-- (void)open;
-- (void)animateOpen;
-
-// Close or animate close the infobar.
-- (void)close;
-- (void)animateClosed;
-
-// Subclasses can override this method to add additional controls to
-// the infobar view.  This method is called by awakeFromNib.  The
-// default implementation does nothing.
-- (void)addAdditionalControls;
-
-// Sets the info bar message to the specified |message|.
-- (void)setLabelToMessage:(NSString*)message;
-
-// Removes the OK and Cancel buttons and resizes the textfield to use the
-// space.
-- (void)removeButtons;
-
-@property(nonatomic, assign) id<InfoBarContainer> containerController;
-@property(nonatomic, readonly) InfoBarDelegate* delegate;
-
-@end
-
-/////////////////////////////////////////////////////////////////////////
-// InfoBarController subclasses, one for each InfoBarDelegate
-// subclass.  Each of these subclasses overrides addAdditionalControls to
-// configure its view as necessary.
-
-@interface AlertInfoBarController : InfoBarController
-@end
-
-
-@interface LinkInfoBarController : InfoBarController
-// Called when there is a click on the link in the infobar.
-- (void)linkClicked;
-@end
-
-
-@interface ConfirmInfoBarController : InfoBarController
-// Called when the OK and Cancel buttons are clicked.
-- (IBAction)ok:(id)sender;
-- (IBAction)cancel:(id)sender;
-// Called when there is a click on the link in the infobar.
-- (void)linkClicked;
-@end
diff --git a/chrome/browser/ui/cocoa/infobar_controller.mm b/chrome/browser/ui/cocoa/infobar_controller.mm
deleted file mode 100644
index 432c00b..0000000
--- a/chrome/browser/ui/cocoa/infobar_controller.mm
+++ /dev/null
@@ -1,533 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/logging.h"  // for NOTREACHED()
-#include "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#import "chrome/browser/ui/cocoa/animatable_view.h"
-#include "chrome/browser/ui/cocoa/event_utils.h"
-#include "chrome/browser/ui/cocoa/infobar.h"
-#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#include "webkit/glue/window_open_disposition.h"
-
-namespace {
-// Durations set to match the default SlideAnimation duration.
-const float kAnimateOpenDuration = 0.12;
-const float kAnimateCloseDuration = 0.12;
-}
-
-// This simple subclass of |NSTextView| just doesn't show the (text) cursor
-// (|NSTextView| displays the cursor with full keyboard accessibility enabled).
-@interface InfoBarTextView : NSTextView
-- (void)fixupCursor;
-@end
-
-@implementation InfoBarTextView
-
-// Never draw the insertion point (otherwise, it shows up without any user
-// action if full keyboard accessibility is enabled).
-- (BOOL)shouldDrawInsertionPoint {
-  return NO;
-}
-
-- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
-                              granularity:(NSSelectionGranularity)granularity {
-  // Do not allow selections.
-  return NSMakeRange(0, 0);
-}
-
-// Convince NSTextView to not show an I-Beam cursor when the cursor is over the
-// text view but not over actual text.
-//
-// http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
-// "NSTextView sets the cursor over itself dynamically, based on considerations
-// including the text under the cursor. It does so in -mouseEntered:,
-// -mouseMoved:, and -cursorUpdate:, so those would be points to consider
-// overriding."
-- (void)mouseMoved:(NSEvent*)e {
-  [super mouseMoved:e];
-  [self fixupCursor];
-}
-
-- (void)mouseEntered:(NSEvent*)e {
-  [super mouseEntered:e];
-  [self fixupCursor];
-}
-
-- (void)cursorUpdate:(NSEvent*)e {
-  [super cursorUpdate:e];
-  [self fixupCursor];
-}
-
-- (void)fixupCursor {
-  if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
-    [[NSCursor arrowCursor] set];
-}
-
-@end
-
-@interface InfoBarController (PrivateMethods)
-// Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil.
-- (void)initializeLabel;
-
-// Asks the container controller to remove the infobar for this delegate.  This
-// call will trigger a notification that starts the infobar animating closed.
-- (void)removeInfoBar;
-
-// Performs final cleanup after an animation is finished or stopped, including
-// notifying the InfoBarDelegate that the infobar was closed and removing the
-// infobar from its container, if necessary.
-- (void)cleanUpAfterAnimation:(BOOL)finished;
-
-// Sets the info bar message to the specified |message|, with a hypertext
-// style link. |link| will be inserted into message at |linkOffset|.
-- (void)setLabelToMessage:(NSString*)message
-                 withLink:(NSString*)link
-                 atOffset:(NSUInteger)linkOffset;
-@end
-
-@implementation InfoBarController
-
-@synthesize containerController = containerController_;
-@synthesize delegate = delegate_;
-
-- (id)initWithDelegate:(InfoBarDelegate*)delegate {
-  DCHECK(delegate);
-  if ((self = [super initWithNibName:@"InfoBar"
-                              bundle:base::mac::MainAppBundle()])) {
-    delegate_ = delegate;
-  }
-  return self;
-}
-
-// All infobars have an icon, so we set up the icon in the base class
-// awakeFromNib.
-- (void)awakeFromNib {
-  DCHECK(delegate_);
-  if (delegate_->GetIcon()) {
-    [image_ setImage:gfx::SkBitmapToNSImage(*(delegate_->GetIcon()))];
-  } else {
-    // No icon, remove it from the view and grow the textfield to include the
-    // space.
-    NSRect imageFrame = [image_ frame];
-    NSRect labelFrame = [labelPlaceholder_ frame];
-    labelFrame.size.width += NSMinX(imageFrame) - NSMinX(labelFrame);
-    labelFrame.origin.x = imageFrame.origin.x;
-    [image_ removeFromSuperview];
-    [labelPlaceholder_ setFrame:labelFrame];
-  }
-  [self initializeLabel];
-
-  [self addAdditionalControls];
-}
-
-// Called when someone clicks on the embedded link.
-- (BOOL) textView:(NSTextView*)textView
-    clickedOnLink:(id)link
-          atIndex:(NSUInteger)charIndex {
-  if ([self respondsToSelector:@selector(linkClicked)])
-    [self performSelector:@selector(linkClicked)];
-  return YES;
-}
-
-// Called when someone clicks on the ok button.
-- (void)ok:(id)sender {
-  // Subclasses must override this method if they do not hide the ok button.
-  NOTREACHED();
-}
-
-// Called when someone clicks on the cancel button.
-- (void)cancel:(id)sender {
-  // Subclasses must override this method if they do not hide the cancel button.
-  NOTREACHED();
-}
-
-// Called when someone clicks on the close button.
-- (void)dismiss:(id)sender {
-  [self removeInfoBar];
-}
-
-- (AnimatableView*)animatableView {
-  return static_cast<AnimatableView*>([self view]);
-}
-
-- (void)open {
-  // Simply reset the frame size to its opened size, forcing a relayout.
-  CGFloat finalHeight = [[self view] frame].size.height;
-  [[self animatableView] setHeight:finalHeight];
-}
-
-- (void)animateOpen {
-  // Force the frame size to be 0 and then start an animation.
-  NSRect frame = [[self view] frame];
-  CGFloat finalHeight = frame.size.height;
-  frame.size.height = 0;
-  [[self view] setFrame:frame];
-  [[self animatableView] animateToNewHeight:finalHeight
-                                   duration:kAnimateOpenDuration];
-}
-
-- (void)close {
-  // Stop any running animations.
-  [[self animatableView] stopAnimation];
-  infoBarClosing_ = YES;
-  [self cleanUpAfterAnimation:YES];
-}
-
-- (void)animateClosed {
-  // Start animating closed.  We will receive a notification when the animation
-  // is done, at which point we can remove our view from the hierarchy and
-  // notify the delegate that the infobar was closed.
-  [[self animatableView] animateToNewHeight:0 duration:kAnimateCloseDuration];
-
-  // The above call may trigger an animationDidStop: notification for any
-  // currently-running animations, so do not set |infoBarClosing_| until after
-  // starting the animation.
-  infoBarClosing_ = YES;
-}
-
-- (void)addAdditionalControls {
-  // Default implementation does nothing.
-}
-
-- (void)setLabelToMessage:(NSString*)message {
-  NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
-  NSFont* font = [NSFont labelFontOfSize:
-      [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
-  [attributes setObject:font
-                 forKey:NSFontAttributeName];
-  [attributes setObject:[NSCursor arrowCursor]
-                 forKey:NSCursorAttributeName];
-  scoped_nsobject<NSAttributedString> attributedString(
-      [[NSAttributedString alloc] initWithString:message
-                                      attributes:attributes]);
-  [[label_.get() textStorage] setAttributedString:attributedString];
-}
-
-- (void)removeButtons {
-  // Extend the label all the way across.
-  NSRect labelFrame = [label_.get() frame];
-  labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame);
-  [okButton_ removeFromSuperview];
-  [cancelButton_ removeFromSuperview];
-  [label_.get() setFrame:labelFrame];
-}
-
-@end
-
-@implementation InfoBarController (PrivateMethods)
-
-- (void)initializeLabel {
-  // Replace the label placeholder NSTextField with the real label NSTextView.
-  // The former doesn't show links in a nice way, but the latter can't be added
-  // in IB without a containing scroll view, so create the NSTextView
-  // programmatically.
-  label_.reset([[InfoBarTextView alloc]
-      initWithFrame:[labelPlaceholder_ frame]]);
-  [label_.get() setAutoresizingMask:[labelPlaceholder_ autoresizingMask]];
-  [[labelPlaceholder_ superview]
-      replaceSubview:labelPlaceholder_ with:label_.get()];
-  labelPlaceholder_ = nil;  // Now released.
-  [label_.get() setDelegate:self];
-  [label_.get() setEditable:NO];
-  [label_.get() setDrawsBackground:NO];
-  [label_.get() setHorizontallyResizable:NO];
-  [label_.get() setVerticallyResizable:NO];
-}
-
-- (void)removeInfoBar {
-  // TODO(rohitrao): This method can be called even if the infobar has already
-  // been removed and |delegate_| is NULL.  Is there a way to rewrite the code
-  // so that inner event loops don't cause us to try and remove the infobar
-  // twice?  http://crbug.com/54253
-  [containerController_ removeDelegate:delegate_];
-}
-
-- (void)cleanUpAfterAnimation:(BOOL)finished {
-  // Don't need to do any cleanup if the bar was animating open.
-  if (!infoBarClosing_)
-    return;
-
-  // Notify the delegate that the infobar was closed.  The delegate may delete
-  // itself as a result of InfoBarClosed(), so we null out its pointer.
-  if (delegate_) {
-    delegate_->InfoBarClosed();
-    delegate_ = NULL;
-  }
-
-  // If the animation ran to completion, then we need to remove ourselves from
-  // the container.  If the animation was interrupted, then the container will
-  // take care of removing us.
-  // TODO(rohitrao): UGH!  This works for now, but should be cleaner.
-  if (finished)
-    [containerController_ removeController:self];
-}
-
-- (void)animationDidStop:(NSAnimation*)animation {
-  [self cleanUpAfterAnimation:NO];
-}
-
-- (void)animationDidEnd:(NSAnimation*)animation {
-  [self cleanUpAfterAnimation:YES];
-}
-
-// TODO(joth): This method factors out some common functionality between the
-// various derived infobar classes, however the class hierarchy itself could
-// use refactoring to reduce this duplication. http://crbug.com/38924
-- (void)setLabelToMessage:(NSString*)message
-                 withLink:(NSString*)link
-                 atOffset:(NSUInteger)linkOffset {
-  if (linkOffset == std::wstring::npos) {
-    // linkOffset == std::wstring::npos means the link should be right-aligned,
-    // which is not supported on Mac (http://crbug.com/47728).
-    NOTIMPLEMENTED();
-    linkOffset = [message length];
-  }
-  // Create an attributes dictionary for the entire message.  We have
-  // to expicitly set the font the control's font.  We also override
-  // the cursor to give us the normal cursor rather than the text
-  // insertion cursor.
-  NSMutableDictionary* linkAttributes = [NSMutableDictionary dictionary];
-  [linkAttributes setObject:[NSCursor arrowCursor]
-                     forKey:NSCursorAttributeName];
-  NSFont* font = [NSFont labelFontOfSize:
-      [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
-  [linkAttributes setObject:font
-                     forKey:NSFontAttributeName];
-
-  // Create the attributed string for the main message text.
-  scoped_nsobject<NSMutableAttributedString> infoText(
-      [[NSMutableAttributedString alloc] initWithString:message]);
-  [infoText.get() addAttributes:linkAttributes
-                    range:NSMakeRange(0, [infoText.get() length])];
-  // Add additional attributes to style the link text appropriately as
-  // well as linkify it.
-  [linkAttributes setObject:[NSColor blueColor]
-                     forKey:NSForegroundColorAttributeName];
-  [linkAttributes setObject:[NSNumber numberWithBool:YES]
-                     forKey:NSUnderlineStyleAttributeName];
-  [linkAttributes setObject:[NSCursor pointingHandCursor]
-                     forKey:NSCursorAttributeName];
-  [linkAttributes setObject:[NSNumber numberWithInt:NSSingleUnderlineStyle]
-                     forKey:NSUnderlineStyleAttributeName];
-  [linkAttributes setObject:[NSString string]  // dummy value
-                     forKey:NSLinkAttributeName];
-
-  // Insert the link text into the string at the appropriate offset.
-  scoped_nsobject<NSAttributedString> attributedString(
-      [[NSAttributedString alloc] initWithString:link
-                                      attributes:linkAttributes]);
-  [infoText.get() insertAttributedString:attributedString.get()
-                                 atIndex:linkOffset];
-  // Update the label view with the new text.
-  [[label_.get() textStorage] setAttributedString:infoText];
-}
-
-@end
-
-
-/////////////////////////////////////////////////////////////////////////
-// AlertInfoBarController implementation
-
-@implementation AlertInfoBarController
-
-// Alert infobars have a text message.
-- (void)addAdditionalControls {
-  // No buttons.
-  [self removeButtons];
-
-  // Insert the text.
-  AlertInfoBarDelegate* delegate = delegate_->AsAlertInfoBarDelegate();
-  DCHECK(delegate);
-  [self setLabelToMessage:base::SysUTF16ToNSString(delegate->GetMessageText())];
-}
-
-@end
-
-
-/////////////////////////////////////////////////////////////////////////
-// LinkInfoBarController implementation
-
-@implementation LinkInfoBarController
-
-// Link infobars have a text message, of which part is linkified.  We
-// use an NSAttributedString to display styled text, and we set a
-// NSLink attribute on the hyperlink portion of the message.  Infobars
-// use a custom NSTextField subclass, which allows us to override
-// textView:clickedOnLink:atIndex: and intercept clicks.
-//
-- (void)addAdditionalControls {
-  // No buttons.
-  [self removeButtons];
-
-  LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate();
-  DCHECK(delegate);
-  size_t offset = std::wstring::npos;
-  string16 message = delegate->GetMessageTextWithOffset(&offset);
-  [self setLabelToMessage:base::SysUTF16ToNSString(message)
-                 withLink:base::SysUTF16ToNSString(delegate->GetLinkText())
-                 atOffset:offset];
-}
-
-// Called when someone clicks on the link in the infobar.  This method
-// is called by the InfobarTextField on its delegate (the
-// LinkInfoBarController).
-- (void)linkClicked {
-  WindowOpenDisposition disposition =
-      event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
-  if (delegate_ && delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition))
-    [self removeInfoBar];
-}
-
-@end
-
-
-/////////////////////////////////////////////////////////////////////////
-// ConfirmInfoBarController implementation
-
-@implementation ConfirmInfoBarController
-
-// Called when someone clicks on the "OK" button.
-- (IBAction)ok:(id)sender {
-  if (delegate_ && delegate_->AsConfirmInfoBarDelegate()->Accept())
-    [self removeInfoBar];
-}
-
-// Called when someone clicks on the "Cancel" button.
-- (IBAction)cancel:(id)sender {
-  if (delegate_ && delegate_->AsConfirmInfoBarDelegate()->Cancel())
-    [self removeInfoBar];
-}
-
-// Confirm infobars can have OK and/or cancel buttons, depending on
-// the return value of GetButtons().  We create each button if
-// required and position them to the left of the close button.
-- (void)addAdditionalControls {
-  ConfirmInfoBarDelegate* delegate = delegate_->AsConfirmInfoBarDelegate();
-  DCHECK(delegate);
-  int visibleButtons = delegate->GetButtons();
-
-  NSRect okButtonFrame = [okButton_ frame];
-  NSRect cancelButtonFrame = [cancelButton_ frame];
-
-  DCHECK(NSMaxX(okButtonFrame) < NSMinX(cancelButtonFrame))
-      << "Cancel button expected to be on the right of the Ok button in nib";
-
-  CGFloat rightEdge = NSMaxX(cancelButtonFrame);
-  CGFloat spaceBetweenButtons =
-      NSMinX(cancelButtonFrame) - NSMaxX(okButtonFrame);
-  CGFloat spaceBeforeButtons =
-      NSMinX(okButtonFrame) - NSMaxX([label_.get() frame]);
-
-  // Update and position the Cancel button if needed.  Otherwise, hide it.
-  if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
-    [cancelButton_ setTitle:base::SysUTF16ToNSString(
-          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))];
-    [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_];
-    cancelButtonFrame = [cancelButton_ frame];
-
-    // Position the cancel button to the left of the Close button.
-    cancelButtonFrame.origin.x = rightEdge - cancelButtonFrame.size.width;
-    [cancelButton_ setFrame:cancelButtonFrame];
-
-    // Update the rightEdge
-    rightEdge = NSMinX(cancelButtonFrame);
-  } else {
-    [cancelButton_ removeFromSuperview];
-  }
-
-  // Update and position the OK button if needed.  Otherwise, hide it.
-  if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
-    [okButton_ setTitle:base::SysUTF16ToNSString(
-          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))];
-    [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_];
-    okButtonFrame = [okButton_ frame];
-
-    // If we had a Cancel button, leave space between the buttons.
-    if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
-      rightEdge -= spaceBetweenButtons;
-    }
-
-    // Position the OK button on our current right edge.
-    okButtonFrame.origin.x = rightEdge - okButtonFrame.size.width;
-    [okButton_ setFrame:okButtonFrame];
-
-
-    // Update the rightEdge
-    rightEdge = NSMinX(okButtonFrame);
-  } else {
-    [okButton_ removeFromSuperview];
-  }
-
-  // If we had either button, leave space before the edge of the textfield.
-  if ((visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) ||
-      (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK)) {
-    rightEdge -= spaceBeforeButtons;
-  }
-
-  NSRect frame = [label_.get() frame];
-  DCHECK(rightEdge > NSMinX(frame))
-      << "Need to make the xib larger to handle buttons with text this long";
-  frame.size.width = rightEdge - NSMinX(frame);
-  [label_.get() setFrame:frame];
-
-  // Set the text and link.
-  NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText());
-  string16 link = delegate->GetLinkText();
-  if (link.empty()) {
-    // Simple case: no link, so just set the message directly.
-    [self setLabelToMessage:message];
-  } else {
-    // Inserting the link unintentionally causes the text to have a slightly
-    // different result to the simple case above: text is truncated on word
-    // boundaries (if needed) rather than elided with ellipses.
-
-    // Add spacing between the label and the link.
-    message = [message stringByAppendingString:@"   "];
-    [self setLabelToMessage:message
-                   withLink:base::SysUTF16ToNSString(link)
-                   atOffset:[message length]];
-  }
-}
-
-// Called when someone clicks on the link in the infobar.  This method
-// is called by the InfobarTextField on its delegate (the
-// LinkInfoBarController).
-- (void)linkClicked {
-  WindowOpenDisposition disposition =
-      event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
-  if (delegate_ &&
-      delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition))
-    [self removeInfoBar];
-}
-
-@end
-
-
-//////////////////////////////////////////////////////////////////////////
-// CreateInfoBar() implementations
-
-InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
-  AlertInfoBarController* controller =
-      [[AlertInfoBarController alloc] initWithDelegate:this];
-  return new InfoBar(controller);
-}
-
-InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
-  LinkInfoBarController* controller =
-      [[LinkInfoBarController alloc] initWithDelegate:this];
-  return new InfoBar(controller);
-}
-
-InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
-  ConfirmInfoBarController* controller =
-      [[ConfirmInfoBarController alloc] initWithDelegate:this];
-  return new InfoBar(controller);
-}
diff --git a/chrome/browser/ui/cocoa/infobar_controller_unittest.mm b/chrome/browser/ui/cocoa/infobar_controller_unittest.mm
deleted file mode 100644
index 4dfcd51..0000000
--- a/chrome/browser/ui/cocoa/infobar_controller_unittest.mm
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
-#include "chrome/browser/ui/cocoa/infobar_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface InfoBarController (ExposedForTesting)
-- (NSString*)labelString;
-- (NSRect)labelFrame;
-@end
-
-@implementation InfoBarController (ExposedForTesting)
-- (NSString*)labelString {
-  return [label_.get() string];
-}
-- (NSRect)labelFrame {
-  return [label_.get() frame];
-}
-@end
-
-
-// Calls to removeDelegate: normally start an animation, which removes the
-// infobar completely when finished.  For unittesting purposes, we create a mock
-// container which calls close: immediately, rather than kicking off an
-// animation.
-@interface InfoBarContainerTest : NSObject <InfoBarContainer> {
-  InfoBarController* controller_;
-}
-- (id)initWithController:(InfoBarController*)controller;
-- (void)removeDelegate:(InfoBarDelegate*)delegate;
-- (void)removeController:(InfoBarController*)controller;
-@end
-
-@implementation InfoBarContainerTest
-- (id)initWithController:(InfoBarController*)controller {
-  if ((self = [super init])) {
-    controller_ = controller;
-  }
-  return self;
-}
-
-- (void)removeDelegate:(InfoBarDelegate*)delegate {
-  [controller_ close];
-}
-
-- (void)removeController:(InfoBarController*)controller {
-  DCHECK(controller_ == controller);
-  controller_ = nil;
-}
-@end
-
-namespace {
-
-///////////////////////////////////////////////////////////////////////////
-// Test fixtures
-
-class AlertInfoBarControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-
-    controller_.reset(
-        [[AlertInfoBarController alloc] initWithDelegate:&delegate_]);
-    container_.reset(
-        [[InfoBarContainerTest alloc] initWithController:controller_]);
-    [controller_ setContainerController:container_];
-    [[test_window() contentView] addSubview:[controller_ view]];
-  }
-
- protected:
-  MockAlertInfoBarDelegate delegate_;
-  scoped_nsobject<id> container_;
-  scoped_nsobject<AlertInfoBarController> controller_;
-};
-
-class LinkInfoBarControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-
-    controller_.reset(
-        [[LinkInfoBarController alloc] initWithDelegate:&delegate_]);
-    container_.reset(
-        [[InfoBarContainerTest alloc] initWithController:controller_]);
-    [controller_ setContainerController:container_];
-    [[test_window() contentView] addSubview:[controller_ view]];
-  }
-
- protected:
-  MockLinkInfoBarDelegate delegate_;
-  scoped_nsobject<id> container_;
-  scoped_nsobject<LinkInfoBarController> controller_;
-};
-
-class ConfirmInfoBarControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-
-    controller_.reset(
-        [[ConfirmInfoBarController alloc] initWithDelegate:&delegate_]);
-    container_.reset(
-        [[InfoBarContainerTest alloc] initWithController:controller_]);
-    [controller_ setContainerController:container_];
-    [[test_window() contentView] addSubview:[controller_ view]];
-  }
-
- protected:
-  MockConfirmInfoBarDelegate delegate_;
-  scoped_nsobject<id> container_;
-  scoped_nsobject<ConfirmInfoBarController> controller_;
-};
-
-
-////////////////////////////////////////////////////////////////////////////
-// Tests
-
-TEST_VIEW(AlertInfoBarControllerTest, [controller_ view]);
-
-TEST_F(AlertInfoBarControllerTest, ShowAndDismiss) {
-  // Make sure someone looked at the message and icon.
-  EXPECT_TRUE(delegate_.message_text_accessed);
-  EXPECT_TRUE(delegate_.icon_accessed);
-
-  // Check to make sure the infobar message was set properly.
-  EXPECT_EQ(kMockAlertInfoBarMessage,
-            base::SysNSStringToUTF8([controller_.get() labelString]));
-
-  // Check that dismissing the infobar calls InfoBarClosed() on the delegate.
-  [controller_ dismiss:nil];
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(AlertInfoBarControllerTest, DeallocController) {
-  // Test that dealloc'ing the controller does not send an
-  // InfoBarClosed() message to the delegate.
-  controller_.reset(nil);
-  EXPECT_FALSE(delegate_.closed);
-}
-
-TEST_F(AlertInfoBarControllerTest, ResizeView) {
-  NSRect originalLabelFrame = [controller_ labelFrame];
-
-  // Expand the view by 20 pixels and make sure the label frame changes
-  // accordingly.
-  const CGFloat width = 20;
-  NSRect newViewFrame = [[controller_ view] frame];
-  newViewFrame.size.width += width;
-  [[controller_ view] setFrame:newViewFrame];
-
-  NSRect newLabelFrame = [controller_ labelFrame];
-  EXPECT_EQ(NSWidth(newLabelFrame), NSWidth(originalLabelFrame) + width);
-}
-
-TEST_VIEW(LinkInfoBarControllerTest, [controller_ view]);
-
-TEST_F(LinkInfoBarControllerTest, ShowAndDismiss) {
-  // Make sure someone looked at the message, link, and icon.
-  EXPECT_TRUE(delegate_.message_text_accessed);
-  EXPECT_TRUE(delegate_.link_text_accessed);
-  EXPECT_TRUE(delegate_.icon_accessed);
-
-  // Check that dismissing the infobar calls InfoBarClosed() on the delegate.
-  [controller_ dismiss:nil];
-  EXPECT_FALSE(delegate_.link_clicked);
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(LinkInfoBarControllerTest, ShowAndClickLink) {
-  // Check that clicking on the link calls LinkClicked() on the
-  // delegate.  It should also close the infobar.
-  [controller_ linkClicked];
-  EXPECT_TRUE(delegate_.link_clicked);
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(LinkInfoBarControllerTest, ShowAndClickLinkWithoutClosing) {
-  delegate_.closes_on_action = false;
-
-  // Check that clicking on the link calls LinkClicked() on the
-  // delegate.  It should not close the infobar.
-  [controller_ linkClicked];
-  EXPECT_TRUE(delegate_.link_clicked);
-  EXPECT_FALSE(delegate_.closed);
-}
-
-TEST_VIEW(ConfirmInfoBarControllerTest, [controller_ view]);
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndDismiss) {
-  // Make sure someone looked at the message, link, and icon.
-  EXPECT_TRUE(delegate_.message_text_accessed);
-  EXPECT_TRUE(delegate_.link_text_accessed);
-  EXPECT_TRUE(delegate_.icon_accessed);
-
-  // Check to make sure the infobar message was set properly.
-  EXPECT_EQ(kMockConfirmInfoBarMessage,
-            base::SysNSStringToUTF8([controller_.get() labelString]));
-
-  // Check that dismissing the infobar calls InfoBarClosed() on the delegate.
-  [controller_ dismiss:nil];
-  EXPECT_FALSE(delegate_.ok_clicked);
-  EXPECT_FALSE(delegate_.cancel_clicked);
-  EXPECT_FALSE(delegate_.link_clicked);
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndClickOK) {
-  // Check that clicking the OK button calls Accept() and then closes
-  // the infobar.
-  [controller_ ok:nil];
-  EXPECT_TRUE(delegate_.ok_clicked);
-  EXPECT_FALSE(delegate_.cancel_clicked);
-  EXPECT_FALSE(delegate_.link_clicked);
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndClickOKWithoutClosing) {
-  delegate_.closes_on_action = false;
-
-  // Check that clicking the OK button calls Accept() but does not close
-  // the infobar.
-  [controller_ ok:nil];
-  EXPECT_TRUE(delegate_.ok_clicked);
-  EXPECT_FALSE(delegate_.cancel_clicked);
-  EXPECT_FALSE(delegate_.link_clicked);
-  EXPECT_FALSE(delegate_.closed);
-}
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndClickCancel) {
-  // Check that clicking the cancel button calls Cancel() and closes
-  // the infobar.
-  [controller_ cancel:nil];
-  EXPECT_FALSE(delegate_.ok_clicked);
-  EXPECT_TRUE(delegate_.cancel_clicked);
-  EXPECT_FALSE(delegate_.link_clicked);
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndClickCancelWithoutClosing) {
-  delegate_.closes_on_action = false;
-
-  // Check that clicking the cancel button calls Cancel() but does not close
-  // the infobar.
-  [controller_ cancel:nil];
-  EXPECT_FALSE(delegate_.ok_clicked);
-  EXPECT_TRUE(delegate_.cancel_clicked);
-  EXPECT_FALSE(delegate_.link_clicked);
-  EXPECT_FALSE(delegate_.closed);
-}
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndClickLink) {
-  // Check that clicking on the link calls LinkClicked() on the
-  // delegate.  It should also close the infobar.
-  [controller_ linkClicked];
-  EXPECT_FALSE(delegate_.ok_clicked);
-  EXPECT_FALSE(delegate_.cancel_clicked);
-  EXPECT_TRUE(delegate_.link_clicked);
-  EXPECT_TRUE(delegate_.closed);
-}
-
-TEST_F(ConfirmInfoBarControllerTest, ShowAndClickLinkWithoutClosing) {
-  delegate_.closes_on_action = false;
-
-  // Check that clicking on the link calls LinkClicked() on the
-  // delegate.  It should not close the infobar.
-  [controller_ linkClicked];
-  EXPECT_FALSE(delegate_.ok_clicked);
-  EXPECT_FALSE(delegate_.cancel_clicked);
-  EXPECT_TRUE(delegate_.link_clicked);
-  EXPECT_FALSE(delegate_.closed);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/infobar_gradient_view.h b/chrome/browser/ui/cocoa/infobar_gradient_view.h
deleted file mode 100644
index e0e0037..0000000
--- a/chrome/browser/ui/cocoa/infobar_gradient_view.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_INFOBAR_GRADIENT_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_INFOBAR_GRADIENT_VIEW_H_
-#pragma once
-
-#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
-
-#import <Cocoa/Cocoa.h>
-
-// A custom view that draws the background gradient for an infobar.
-@interface InfoBarGradientView : VerticalGradientView {
-}
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_INFOBAR_GRADIENT_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/infobar_gradient_view.mm b/chrome/browser/ui/cocoa/infobar_gradient_view.mm
deleted file mode 100644
index cd2b1ee..0000000
--- a/chrome/browser/ui/cocoa/infobar_gradient_view.mm
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/infobar_gradient_view.h"
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/themes/browser_theme_provider.h"
-#import "chrome/browser/ui/cocoa/themed_window.h"
-
-namespace {
-
-const double kBackgroundColorTop[3] =
-    {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
-const double kBackgroundColorBottom[3] =
-    {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
-}
-
-@implementation InfoBarGradientView
-
-- (id)initWithFrame:(NSRect)frameRect {
-  if ((self = [super initWithFrame:frameRect])) {
-    NSColor* startingColor =
-        [NSColor colorWithCalibratedRed:kBackgroundColorTop[0]
-                                  green:kBackgroundColorTop[1]
-                                   blue:kBackgroundColorTop[2]
-                                  alpha:1.0];
-    NSColor* endingColor =
-        [NSColor colorWithCalibratedRed:kBackgroundColorBottom[0]
-                                  green:kBackgroundColorBottom[1]
-                                   blue:kBackgroundColorBottom[2]
-                                  alpha:1.0];
-    scoped_nsobject<NSGradient> gradient(
-        [[NSGradient alloc] initWithStartingColor:startingColor
-                                       endingColor:endingColor]);
-    [self setGradient:gradient];
-  }
-  return self;
-}
-
-- (NSColor*)strokeColor {
-  ThemeProvider* themeProvider = [[self window] themeProvider];
-  if (!themeProvider)
-    return [NSColor blackColor];
-
-  BOOL active = [[self window] isMainWindow];
-  return themeProvider->GetNSColor(
-      active ? BrowserThemeProvider::COLOR_TOOLBAR_STROKE :
-               BrowserThemeProvider::COLOR_TOOLBAR_STROKE_INACTIVE,
-      true);
-}
-
-- (BOOL)mouseDownCanMoveWindow {
-  return NO;
-}
-
-// This view is intentionally not opaque because it overlaps with the findbar.
-
-- (BOOL)accessibilityIsIgnored {
-  return NO;
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attribute {
-  if ([attribute isEqual:NSAccessibilityRoleAttribute])
-    return NSAccessibilityGroupRole;
-
-  return [super accessibilityAttributeValue:attribute];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/infobar_gradient_view_unittest.mm b/chrome/browser/ui/cocoa/infobar_gradient_view_unittest.mm
deleted file mode 100644
index 2e4d01b..0000000
--- a/chrome/browser/ui/cocoa/infobar_gradient_view_unittest.mm
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/infobar_gradient_view.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-
-namespace {
-
-class InfoBarGradientViewTest : public CocoaTest {
- public:
-  InfoBarGradientViewTest() {
-    NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<InfoBarGradientView> view(
-        [[InfoBarGradientView alloc] initWithFrame:frame]);
-    view_ = view.get();
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  InfoBarGradientView* view_;  // Weak. Retained by view hierarchy.
-};
-
-TEST_VIEW(InfoBarGradientViewTest, view_);
-
-// Assert that the view is non-opaque, because otherwise we will end
-// up with findbar painting issues.
-TEST_F(InfoBarGradientViewTest, AssertViewNonOpaque) {
-  EXPECT_FALSE([view_ isOpaque]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/infobar_test_helper.h b/chrome/browser/ui/cocoa/infobar_test_helper.h
deleted file mode 100644
index d01a71b..0000000
--- a/chrome/browser/ui/cocoa/infobar_test_helper.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-
-#include "base/utf_string_conversions.h"
-
-namespace {
-const char kMockAlertInfoBarMessage[] = "MockAlertInfoBarMessage";
-const char kMockLinkInfoBarMessage[] = "MockLinkInfoBarMessage";
-const char kMockLinkInfoBarLink[] = "http://dev.chromium.org";
-const char kMockConfirmInfoBarMessage[] = "MockConfirmInfoBarMessage";
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Mock InfoBarDelgates
-
-class MockAlertInfoBarDelegate : public AlertInfoBarDelegate {
- public:
-  explicit MockAlertInfoBarDelegate()
-      : AlertInfoBarDelegate(NULL),
-        message_text_accessed(false),
-        icon_accessed(false),
-        closed(false) {
-  }
-
-  virtual string16 GetMessageText() const {
-    message_text_accessed = true;
-    return ASCIIToUTF16(kMockAlertInfoBarMessage);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    icon_accessed = true;
-    return NULL;
-  }
-
-  virtual void InfoBarClosed() {
-    closed = true;
-  }
-
-  // These are declared mutable to get around const-ness issues.
-  mutable bool message_text_accessed;
-  mutable bool icon_accessed;
-  bool closed;
-};
-
-class MockLinkInfoBarDelegate : public LinkInfoBarDelegate {
- public:
-  explicit MockLinkInfoBarDelegate()
-      : LinkInfoBarDelegate(NULL),
-        message_text_accessed(false),
-        link_text_accessed(false),
-        icon_accessed(false),
-        link_clicked(false),
-        closed(false),
-        closes_on_action(true) {
-  }
-
-  virtual string16 GetMessageTextWithOffset(size_t* link_offset) const {
-    message_text_accessed = true;
-    return ASCIIToUTF16(kMockLinkInfoBarMessage);
-  }
-
-  virtual string16 GetLinkText() const {
-    link_text_accessed = true;
-    return ASCIIToUTF16(kMockLinkInfoBarLink);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    icon_accessed = true;
-    return NULL;
-  }
-
-  virtual bool LinkClicked(WindowOpenDisposition disposition) {
-    link_clicked = true;
-    return closes_on_action;
-  }
-
-  virtual void InfoBarClosed() {
-    closed = true;
-  }
-
-  // These are declared mutable to get around const-ness issues.
-  mutable bool message_text_accessed;
-  mutable bool link_text_accessed;
-  mutable bool icon_accessed;
-  bool link_clicked;
-  bool closed;
-
-  // Determines whether the infobar closes when an action is taken or not.
-  bool closes_on_action;
-};
-
-class MockConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
- public:
-  explicit MockConfirmInfoBarDelegate()
-      : ConfirmInfoBarDelegate(NULL),
-        message_text_accessed(false),
-        link_text_accessed(false),
-        icon_accessed(false),
-        ok_clicked(false),
-        cancel_clicked(false),
-        link_clicked(false),
-        closed(false),
-        closes_on_action(true) {
-  }
-
-  virtual int GetButtons() const {
-    return (BUTTON_OK | BUTTON_CANCEL);
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    if (button == BUTTON_OK)
-      return ASCIIToUTF16("OK");
-    else
-      return ASCIIToUTF16("Cancel");
-  }
-
-  virtual bool Accept() {
-    ok_clicked = true;
-    return closes_on_action;
-  }
-
-  virtual bool Cancel() {
-    cancel_clicked = true;
-    return closes_on_action;
-  }
-
-  virtual string16 GetMessageText() const {
-    message_text_accessed = true;
-    return ASCIIToUTF16(kMockConfirmInfoBarMessage);
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    icon_accessed = true;
-    return NULL;
-  }
-
-  virtual void InfoBarClosed() {
-    closed = true;
-  }
-
-  virtual string16 GetLinkText() {
-    link_text_accessed = true;
-    return string16();
-  }
-
-  virtual bool LinkClicked(WindowOpenDisposition disposition) {
-    link_clicked = true;
-    return closes_on_action;
-  }
-
-  // These are declared mutable to get around const-ness issues.
-  mutable bool message_text_accessed;
-  mutable bool link_text_accessed;
-  mutable bool icon_accessed;
-  bool ok_clicked;
-  bool cancel_clicked;
-  bool link_clicked;
-  bool closed;
-
-  // Determines whether the infobar closes when an action is taken or not.
-  bool closes_on_action;
-};
diff --git a/chrome/browser/ui/cocoa/infobars/OWNERS b/chrome/browser/ui/cocoa/infobars/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/chrome/browser/ui/cocoa/infobars/infobar.h b/chrome/browser/ui/cocoa/infobars/infobar.h
new file mode 100644
index 0000000..b17ce2e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_H_
+#define CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_H_
+#pragma once
+
+#include "base/logging.h"  // for DCHECK
+
+@class InfoBarController;
+
+// A C++ wrapper around an Objective-C InfoBarController.  This class
+// exists solely to be the return value for InfoBarDelegate::CreateInfoBar(),
+// as defined in chrome/browser/tab_contents/infobar_delegate.h.  This
+// class would be analogous to the various bridge classes we already
+// have, but since there is no pre-defined InfoBar interface, it is
+// easier to simply throw away this object and deal with the
+// controller directly rather than pass messages through a bridge.
+//
+// Callers should delete the returned InfoBar immediately after
+// calling CreateInfoBar(), as the returned InfoBar* object is not
+// pointed to by anyone.  Expected usage:
+//
+// scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar());
+// InfoBarController* controller = infobar->controller();
+// // Do something with the controller, and save a pointer so it can be
+// // deleted later.  |infobar| will be deleted automatically.
+
+class InfoBar {
+ public:
+  InfoBar(InfoBarController* controller) {
+    DCHECK(controller);
+    controller_ = controller;
+  }
+
+  InfoBarController* controller() {
+    return controller_;
+  }
+
+ private:
+  // Pointer to the infobar controller.  Is never null.
+  InfoBarController* controller_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_H_
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h
new file mode 100644
index 0000000..34e4d74
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.h
@@ -0,0 +1,139 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_CONTAINER_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_CONTAINER_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#import "chrome/browser/ui/cocoa/view_resizer.h"
+#include "chrome/common/notification_registrar.h"
+
+@class InfoBarController;
+class InfoBarDelegate;
+class InfoBarNotificationObserver;
+class TabContents;
+class TabStripModel;
+
+// Protocol for basic container methods, as needed by an InfoBarController.
+// This protocol exists to make mocking easier in unittests.
+@protocol InfoBarContainer
+- (void)removeDelegate:(InfoBarDelegate*)delegate;
+- (void)willRemoveController:(InfoBarController*)controller;
+- (void)removeController:(InfoBarController*)controller;
+@end
+
+
+namespace infobars {
+
+// How tall the tip is on a normal infobar.
+const CGFloat kAntiSpoofHeight = 9.0;
+
+};  // namespace infobars
+
+
+// Controller for the infobar container view, which is the superview
+// of all the infobar views.  This class owns zero or more
+// InfoBarControllers, which manage the infobar views.  This class
+// also receives tab strip model notifications and handles
+// adding/removing infobars when needed.
+@interface InfoBarContainerController : NSViewController <ViewResizer,
+                                                          InfoBarContainer> {
+ @private
+  // Needed to send resize messages when infobars are added or removed.
+  id<ViewResizer> resizeDelegate_;  // weak
+
+  // The TabContents we are currently showing infobars for.
+  TabContents* currentTabContents_;  // weak
+
+  // Holds the InfoBarControllers currently owned by this container.
+  scoped_nsobject<NSMutableArray> infobarControllers_;
+
+  // Holds InfoBarControllers when they are in the process of animating out.
+  scoped_nsobject<NSMutableSet> closingInfoBars_;
+
+  // Lets us registers for INFOBAR_ADDED/INFOBAR_REMOVED
+  // notifications.  The actual notifications are sent to the
+  // InfoBarNotificationObserver object, which proxies them back to us.
+  NotificationRegistrar registrar_;
+  scoped_ptr<InfoBarNotificationObserver> infoBarObserver_;
+}
+
+- (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate;
+
+// Informs the selected TabContents that the infobars for the given
+// |delegate| need to be removed.  Does not remove any infobar views
+// directly, as they will be removed when handling the subsequent
+// INFOBAR_REMOVED notification.  Does not notify |delegate| that the
+// infobar was closed.
+- (void)removeDelegate:(InfoBarDelegate*)delegate;
+
+// Informs the container that the |controller| is going to close. It adds the
+// controller to |closingInfoBars_|. Once the animation is complete, the
+// controller calls |-removeController:| to finalize cleanup.
+- (void)willRemoveController:(InfoBarController*)controller;
+
+// Removes |controller| from the list of controllers in this container and
+// removes its view from the view hierarchy.  This method is safe to call while
+// |controller| is still on the call stack.
+- (void)removeController:(InfoBarController*)controller;
+
+// Modifies this container to display infobars for the given
+// |contents|.  Registers for INFOBAR_ADDED and INFOBAR_REMOVED
+// notifications for |contents|.  If we are currently showing any
+// infobars, removes them first and deregisters for any
+// notifications.  |contents| can be NULL, in which case no infobars
+// are shown and no notifications are registered for.
+- (void)changeTabContents:(TabContents*)contents;
+
+// Stripped down version of TabStripModelObserverBridge:tabDetachedWithContents.
+// Forwarded by BWC. Removes all infobars and deregisters for any notifications
+// if |contents| is the current tab contents.
+- (void)tabDetachedWithContents:(TabContents*)contents;
+
+// Returns the number of active infobars. This is
+// |infobarControllers_ - closingInfoBars_|.
+- (NSUInteger)infobarCount;
+
+// Returns the amount of additional height the container view needs to draw the
+// anti-spoofing bulge. This will return 0 if |-infobarCount| is 0.
+- (CGFloat)antiSpoofHeight;
+
+@end
+
+
+@interface InfoBarContainerController (ForTheObserverAndTesting)
+
+// Adds an infobar view for the given delegate.
+- (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate;
+
+// Closes all the infobar views for a given delegate, either immediately or by
+// starting a close animation.
+- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate
+                         animate:(BOOL)animate;
+
+// Replaces all info bars for the delegate with a new info bar.
+// This simply calls closeInfoBarsForDelegate: and then addInfoBar:.
+- (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate
+                              with:(InfoBarDelegate*)new_delegate;
+
+// Positions the infobar views in the container view and notifies
+// |browser_controller_| that it needs to resize the container view.
+- (void)positionInfoBarsAndRedraw;
+
+@end
+
+
+@interface InfoBarContainerController (JustForTesting)
+
+// Removes all infobar views.  Callers must call
+// positionInfoBarsAndRedraw() after calling this method.
+- (void)removeAllInfoBars;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_CONTAINER_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm
new file mode 100644
index 0000000..3d65217
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller.mm
@@ -0,0 +1,247 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#import "chrome/browser/ui/cocoa/animatable_view.h"
+#include "chrome/browser/ui/cocoa/infobars/infobar.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "skia/ext/skia_utils_mac.h"
+
+// C++ class that receives INFOBAR_ADDED and INFOBAR_REMOVED
+// notifications and proxies them back to |controller|.
+class InfoBarNotificationObserver : public NotificationObserver {
+ public:
+  InfoBarNotificationObserver(InfoBarContainerController* controller)
+      : controller_(controller) {
+  }
+
+ private:
+  // NotificationObserver implementation
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    switch (type.value) {
+      case NotificationType::TAB_CONTENTS_INFOBAR_ADDED:
+        [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr()
+                        animate:YES];
+        break;
+      case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
+        [controller_
+          closeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr()
+                           animate:YES];
+        break;
+      case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: {
+        typedef std::pair<InfoBarDelegate*, InfoBarDelegate*>
+            InfoBarDelegatePair;
+        InfoBarDelegatePair* delegates =
+            Details<InfoBarDelegatePair>(details).ptr();
+        [controller_
+         replaceInfoBarsForDelegate:delegates->first with:delegates->second];
+        break;
+      }
+      default:
+        NOTREACHED();  // we don't ask for anything else!
+        break;
+    }
+
+    [controller_ positionInfoBarsAndRedraw];
+  }
+
+  InfoBarContainerController* controller_;  // weak, owns us.
+};
+
+
+@interface InfoBarContainerController (PrivateMethods)
+// Returns the desired height of the container view, computed by
+// adding together the heights of all its subviews.
+- (CGFloat)desiredHeight;
+
+@end
+
+
+@implementation InfoBarContainerController
+
+- (id)initWithResizeDelegate:(id<ViewResizer>)resizeDelegate {
+  DCHECK(resizeDelegate);
+  if ((self = [super initWithNibName:@"InfoBarContainer"
+                              bundle:base::mac::MainAppBundle()])) {
+    resizeDelegate_ = resizeDelegate;
+    infoBarObserver_.reset(new InfoBarNotificationObserver(self));
+
+    // NSMutableArray needs an initial capacity, and we rarely ever see
+    // more than two infobars at a time, so that seems like a good choice.
+    infobarControllers_.reset([[NSMutableArray alloc] initWithCapacity:2]);
+    closingInfoBars_.reset([[NSMutableSet alloc] initWithCapacity:2]);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  DCHECK_EQ([infobarControllers_ count], 0U);
+  DCHECK_EQ([closingInfoBars_ count], 0U);
+  view_id_util::UnsetID([self view]);
+  [super dealloc];
+}
+
+- (void)awakeFromNib {
+  // The info bar container view is an ordinary NSView object, so we set its
+  // ViewID here.
+  view_id_util::SetID([self view], VIEW_ID_INFO_BAR_CONTAINER);
+}
+
+- (void)removeDelegate:(InfoBarDelegate*)delegate {
+  DCHECK(currentTabContents_);
+  currentTabContents_->RemoveInfoBar(delegate);
+}
+
+- (void)willRemoveController:(InfoBarController*)controller {
+  [closingInfoBars_ addObject:controller];
+}
+
+- (void)removeController:(InfoBarController*)controller {
+  if (![infobarControllers_ containsObject:controller])
+    return;
+
+  // This code can be executed while InfoBarController is still on the stack, so
+  // we retain and autorelease the controller to prevent it from being
+  // dealloc'ed too early.
+  [[controller retain] autorelease];
+  [[controller view] removeFromSuperview];
+  [infobarControllers_ removeObject:controller];
+  [closingInfoBars_ removeObject:controller];
+  [self positionInfoBarsAndRedraw];
+}
+
+- (void)changeTabContents:(TabContents*)contents {
+  registrar_.RemoveAll();
+  [self removeAllInfoBars];
+
+  currentTabContents_ = contents;
+  if (currentTabContents_) {
+    for (size_t i = 0; i < currentTabContents_->infobar_count(); ++i) {
+      [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i)
+               animate:NO];
+    }
+
+    Source<TabContents> source(currentTabContents_);
+    registrar_.Add(infoBarObserver_.get(),
+                   NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source);
+    registrar_.Add(infoBarObserver_.get(),
+                   NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, source);
+    registrar_.Add(infoBarObserver_.get(),
+                   NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, source);
+  }
+
+  [self positionInfoBarsAndRedraw];
+}
+
+- (void)tabDetachedWithContents:(TabContents*)contents {
+  if (currentTabContents_ == contents)
+    [self changeTabContents:NULL];
+}
+
+- (NSUInteger)infobarCount {
+  return [infobarControllers_ count] - [closingInfoBars_ count];
+}
+
+- (CGFloat)antiSpoofHeight {
+  return [self infobarCount] ? infobars::kAntiSpoofHeight : 0;
+}
+
+- (void)resizeView:(NSView*)view newHeight:(CGFloat)height {
+  NSRect frame = [view frame];
+  frame.size.height = height;
+  [view setFrame:frame];
+  [self positionInfoBarsAndRedraw];
+}
+
+- (void)setAnimationInProgress:(BOOL)inProgress {
+  if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
+    [resizeDelegate_ setAnimationInProgress:inProgress];
+}
+
+@end
+
+@implementation InfoBarContainerController (PrivateMethods)
+
+- (CGFloat)desiredHeight {
+  CGFloat height = [self antiSpoofHeight];
+  for (InfoBarController* controller in infobarControllers_.get())
+    height += NSHeight([[controller view] frame]) - infobars::kAntiSpoofHeight;
+  return height;
+}
+
+- (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate {
+  scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar());
+  InfoBarController* controller = infobar->controller();
+  [controller setContainerController:self];
+  [[controller animatableView] setResizeDelegate:self];
+  [[self view] addSubview:[controller view]];
+  [infobarControllers_ addObject:[controller autorelease]];
+
+  if (animate)
+    [controller animateOpen];
+  else
+    [controller open];
+}
+
+- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate
+                         animate:(BOOL)animate {
+  for (InfoBarController* controller in
+       [NSArray arrayWithArray:infobarControllers_.get()]) {
+    if ([controller delegate] == delegate) {
+      [controller infobarWillClose];
+      if (animate)
+        [controller animateClosed];
+      else
+        [controller close];
+    }
+  }
+}
+
+- (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate
+                              with:(InfoBarDelegate*)new_delegate {
+  [self closeInfoBarsForDelegate:old_delegate animate:NO];
+  [self addInfoBar:new_delegate animate:NO];
+}
+
+- (void)removeAllInfoBars {
+  for (InfoBarController* controller in infobarControllers_.get()) {
+    [[controller animatableView] stopAnimation];
+    [[controller view] removeFromSuperview];
+  }
+  [infobarControllers_ removeAllObjects];
+  [closingInfoBars_ removeAllObjects];
+}
+
+- (void)positionInfoBarsAndRedraw {
+  NSRect containerBounds = [[self view] bounds];
+  int minY = 0;
+
+  // Stack the infobars at the bottom of the view, starting with the
+  // last infobar and working our way to the front of the array.  This
+  // way we ensure that the first infobar added shows up on top, with
+  // the others below.
+  for (InfoBarController* controller in
+           [infobarControllers_ reverseObjectEnumerator]) {
+    NSView* view = [controller view];
+    NSRect frame = [view frame];
+    frame.origin.x = NSMinX(containerBounds);
+    frame.size.width = NSWidth(containerBounds);
+    frame.origin.y = minY;
+    minY += frame.size.height - infobars::kAntiSpoofHeight;
+    [view setFrame:frame];
+  }
+
+  [resizeDelegate_ resizeView:[self view] newHeight:[self desiredHeight]];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm b/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm
new file mode 100644
index 0000000..b39d48c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_container_controller_unittest.mm
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#include "chrome/browser/ui/cocoa/infobars/infobar_test_helper.h"
+#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class InfoBarContainerControllerTest : public CocoaTest {
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    resizeDelegate_.reset([[ViewResizerPong alloc] init]);
+    ViewResizerPong *viewResizer = resizeDelegate_.get();
+    controller_ =
+        [[InfoBarContainerController alloc] initWithResizeDelegate:viewResizer];
+    NSView* view = [controller_ view];
+    [[test_window() contentView] addSubview:view];
+  }
+
+  virtual void TearDown() {
+    [[controller_ view] removeFromSuperviewWithoutNeedingDisplay];
+    [controller_ release];
+    CocoaTest::TearDown();
+  }
+
+ public:
+  scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  InfoBarContainerController* controller_;
+};
+
+TEST_VIEW(InfoBarContainerControllerTest, [controller_ view])
+
+TEST_F(InfoBarContainerControllerTest, BWCPong) {
+  // Call positionInfoBarsAndResize and check that |resizeDelegate_| got a
+  // resize message.
+  [resizeDelegate_ setHeight:-1];
+  [controller_ positionInfoBarsAndRedraw];
+  EXPECT_NE(-1, [resizeDelegate_ height]);
+}
+
+TEST_F(InfoBarContainerControllerTest, AddAndRemoveInfoBars) {
+  NSView* view = [controller_ view];
+
+  // Add three infobars and then remove them.
+  // After each step check to make sure we have the correct number of
+  // infobar subviews.
+  MockLinkInfoBarDelegate linkDelegate, linkDelegate2;
+  MockConfirmInfoBarDelegate confirmDelegate;
+
+  [controller_ addInfoBar:&linkDelegate animate:NO];
+  EXPECT_EQ(1U, [[view subviews] count]);
+
+  [controller_ addInfoBar:&confirmDelegate animate:NO];
+  EXPECT_EQ(2U, [[view subviews] count]);
+
+  [controller_ addInfoBar:&linkDelegate2 animate:NO];
+  EXPECT_EQ(3U, [[view subviews] count]);
+
+  // Just to mix things up, remove them in a different order.
+  [controller_ closeInfoBarsForDelegate:&confirmDelegate animate:NO];
+  EXPECT_EQ(2U, [[view subviews] count]);
+
+  [controller_ closeInfoBarsForDelegate:&linkDelegate animate:NO];
+  EXPECT_EQ(1U, [[view subviews] count]);
+
+  [controller_ closeInfoBarsForDelegate:&linkDelegate2 animate:NO];
+  EXPECT_EQ(0U, [[view subviews] count]);
+}
+
+TEST_F(InfoBarContainerControllerTest, RemoveAllInfoBars) {
+  NSView* view = [controller_ view];
+
+  // Add three infobars and then remove them all.
+  MockLinkInfoBarDelegate linkDelegate;
+  MockConfirmInfoBarDelegate confirmDelegate, confirmDelegate2;
+
+  [controller_ addInfoBar:&linkDelegate animate:NO];
+  [controller_ addInfoBar:&confirmDelegate animate:NO];
+  [controller_ addInfoBar:&confirmDelegate2 animate:NO];
+  EXPECT_EQ(3U, [[view subviews] count]);
+
+  [controller_ removeAllInfoBars];
+  EXPECT_EQ(0U, [[view subviews] count]);
+}
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_controller.h b/chrome/browser/ui/cocoa/infobars/infobar_controller.h
new file mode 100644
index 0000000..6214a42
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_controller.h
@@ -0,0 +1,106 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_nsobject.h"
+
+@class AnimatableView;
+@class HoverCloseButton;
+@protocol InfoBarContainer;
+class InfoBarDelegate;
+@class InfoBarGradientView;
+
+// A controller for an infobar in the browser window.  There is one
+// controller per infobar view.  The base InfoBarController is able to
+// draw an icon, a text message, and a close button.  Subclasses can
+// override addAdditionalControls to customize the UI.
+@interface InfoBarController : NSViewController<NSTextViewDelegate> {
+ @private
+  id<InfoBarContainer> containerController_;  // weak, owns us
+  BOOL infoBarClosing_;
+
+ @protected
+  IBOutlet InfoBarGradientView* infoBarView_;
+  IBOutlet NSImageView* image_;
+  IBOutlet NSTextField* labelPlaceholder_;
+  IBOutlet NSButton* okButton_;
+  IBOutlet NSButton* cancelButton_;
+  IBOutlet HoverCloseButton* closeButton_;
+
+  // In rare instances, it can be possible for |delegate_| to delete itself
+  // while this controller is still alive.  Always check |delegate_| against
+  // NULL before using it.
+  InfoBarDelegate* delegate_;  // weak, can be NULL
+
+  // Text fields don't work as well with embedded links as text views, but
+  // text views cannot conveniently be created in IB. The xib file contains
+  // a text field |labelPlaceholder_| that's replaced by this text view |label_|
+  // in -awakeFromNib.
+  scoped_nsobject<NSTextView> label_;
+};
+
+// Initializes a new InfoBarController.
+- (id)initWithDelegate:(InfoBarDelegate*)delegate;
+
+// Called when someone clicks on the OK or Cancel buttons.  Subclasses
+// must override if they do not hide the buttons.
+- (void)ok:(id)sender;
+- (void)cancel:(id)sender;
+
+// Called when someone clicks on the close button.  Dismisses the
+// infobar without taking any action.
+- (IBAction)dismiss:(id)sender;
+
+// Returns a pointer to this controller's view, cast as an AnimatableView.
+- (AnimatableView*)animatableView;
+
+// Open or animate open the infobar.
+- (void)open;
+- (void)animateOpen;
+
+// Close or animate close the infobar.
+- (void)close;
+- (void)animateClosed;
+
+// Subclasses can override this method to add additional controls to
+// the infobar view.  This method is called by awakeFromNib.  The
+// default implementation does nothing.
+- (void)addAdditionalControls;
+
+// Subclasses must override this method to perform cleanup just before the
+// infobar closes.
+- (void)infobarWillClose;
+
+// Sets the info bar message to the specified |message|.
+- (void)setLabelToMessage:(NSString*)message;
+
+// Removes the OK and Cancel buttons and resizes the textfield to use the
+// space.
+- (void)removeButtons;
+
+@property(nonatomic, assign) id<InfoBarContainer> containerController;
+@property(nonatomic, readonly) InfoBarDelegate* delegate;
+
+@end
+
+/////////////////////////////////////////////////////////////////////////
+// InfoBarController subclasses, one for each InfoBarDelegate
+// subclass.  Each of these subclasses overrides addAdditionalControls to
+// configure its view as necessary.
+
+@interface LinkInfoBarController : InfoBarController
+// Called when there is a click on the link in the infobar.
+- (void)linkClicked;
+@end
+
+
+@interface ConfirmInfoBarController : InfoBarController
+// Called when the OK and Cancel buttons are clicked.
+- (IBAction)ok:(id)sender;
+- (IBAction)cancel:(id)sender;
+// Called when there is a click on the link in the infobar.
+- (void)linkClicked;
+@end
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_controller.mm b/chrome/browser/ui/cocoa/infobars/infobar_controller.mm
new file mode 100644
index 0000000..a2c565f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_controller.mm
@@ -0,0 +1,523 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/logging.h"  // for NOTREACHED()
+#include "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#import "chrome/browser/ui/cocoa/animatable_view.h"
+#include "chrome/browser/ui/cocoa/event_utils.h"
+#include "chrome/browser/ui/cocoa/infobars/infobar.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "webkit/glue/window_open_disposition.h"
+
+namespace {
+// Durations set to match the default SlideAnimation duration.
+const float kAnimateOpenDuration = 0.12;
+const float kAnimateCloseDuration = 0.12;
+}
+
+// This simple subclass of |NSTextView| just doesn't show the (text) cursor
+// (|NSTextView| displays the cursor with full keyboard accessibility enabled).
+@interface InfoBarTextView : NSTextView
+- (void)fixupCursor;
+@end
+
+@implementation InfoBarTextView
+
+// Never draw the insertion point (otherwise, it shows up without any user
+// action if full keyboard accessibility is enabled).
+- (BOOL)shouldDrawInsertionPoint {
+  return NO;
+}
+
+- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
+                              granularity:(NSSelectionGranularity)granularity {
+  // Do not allow selections.
+  return NSMakeRange(0, 0);
+}
+
+// Convince NSTextView to not show an I-Beam cursor when the cursor is over the
+// text view but not over actual text.
+//
+// http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
+// "NSTextView sets the cursor over itself dynamically, based on considerations
+// including the text under the cursor. It does so in -mouseEntered:,
+// -mouseMoved:, and -cursorUpdate:, so those would be points to consider
+// overriding."
+- (void)mouseMoved:(NSEvent*)e {
+  [super mouseMoved:e];
+  [self fixupCursor];
+}
+
+- (void)mouseEntered:(NSEvent*)e {
+  [super mouseEntered:e];
+  [self fixupCursor];
+}
+
+- (void)cursorUpdate:(NSEvent*)e {
+  [super cursorUpdate:e];
+  [self fixupCursor];
+}
+
+- (void)fixupCursor {
+  if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
+    [[NSCursor arrowCursor] set];
+}
+
+@end
+
+@interface InfoBarController (PrivateMethods)
+// Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil.
+- (void)initializeLabel;
+
+// Asks the container controller to remove the infobar for this delegate.  This
+// call will trigger a notification that starts the infobar animating closed.
+- (void)removeInfoBar;
+
+// Performs final cleanup after an animation is finished or stopped, including
+// notifying the InfoBarDelegate that the infobar was closed and removing the
+// infobar from its container, if necessary.
+- (void)cleanUpAfterAnimation:(BOOL)finished;
+
+// Sets the info bar message to the specified |message|, with a hypertext
+// style link. |link| will be inserted into message at |linkOffset|.
+- (void)setLabelToMessage:(NSString*)message
+                 withLink:(NSString*)link
+                 atOffset:(NSUInteger)linkOffset;
+@end
+
+@implementation InfoBarController
+
+@synthesize containerController = containerController_;
+@synthesize delegate = delegate_;
+
+- (id)initWithDelegate:(InfoBarDelegate*)delegate {
+  DCHECK(delegate);
+  if ((self = [super initWithNibName:@"InfoBar"
+                              bundle:base::mac::MainAppBundle()])) {
+    delegate_ = delegate;
+  }
+  return self;
+}
+
+// All infobars have an icon, so we set up the icon in the base class
+// awakeFromNib.
+- (void)awakeFromNib {
+  DCHECK(delegate_);
+  if (delegate_->GetIcon()) {
+    [image_ setImage:gfx::SkBitmapToNSImage(*(delegate_->GetIcon()))];
+  } else {
+    // No icon, remove it from the view and grow the textfield to include the
+    // space.
+    NSRect imageFrame = [image_ frame];
+    NSRect labelFrame = [labelPlaceholder_ frame];
+    labelFrame.size.width += NSMinX(imageFrame) - NSMinX(labelFrame);
+    labelFrame.origin.x = imageFrame.origin.x;
+    [image_ removeFromSuperview];
+    [labelPlaceholder_ setFrame:labelFrame];
+  }
+  [self initializeLabel];
+
+  [self addAdditionalControls];
+}
+
+// Called when someone clicks on the embedded link.
+- (BOOL) textView:(NSTextView*)textView
+    clickedOnLink:(id)link
+          atIndex:(NSUInteger)charIndex {
+  if ([self respondsToSelector:@selector(linkClicked)])
+    [self performSelector:@selector(linkClicked)];
+  return YES;
+}
+
+// Called when someone clicks on the ok button.
+- (void)ok:(id)sender {
+  // Subclasses must override this method if they do not hide the ok button.
+  NOTREACHED();
+}
+
+// Called when someone clicks on the cancel button.
+- (void)cancel:(id)sender {
+  // Subclasses must override this method if they do not hide the cancel button.
+  NOTREACHED();
+}
+
+// Called when someone clicks on the close button.
+- (void)dismiss:(id)sender {
+  [self removeInfoBar];
+}
+
+- (AnimatableView*)animatableView {
+  return static_cast<AnimatableView*>([self view]);
+}
+
+- (void)open {
+  // Simply reset the frame size to its opened size, forcing a relayout.
+  CGFloat finalHeight = [[self view] frame].size.height;
+  [[self animatableView] setHeight:finalHeight];
+}
+
+- (void)animateOpen {
+  // Force the frame size to be 0 and then start an animation.
+  NSRect frame = [[self view] frame];
+  // Slide the origin down so it doesn't animate on top of the toolbar, but
+  // rather just in the content area.
+  frame.origin.y -= infobars::kAntiSpoofHeight;
+  CGFloat finalHeight = frame.size.height;
+  frame.size.height = 0;
+  [[self view] setFrame:frame];
+  [[self animatableView] animateToNewHeight:finalHeight
+                                   duration:kAnimateOpenDuration];
+}
+
+- (void)close {
+  // Stop any running animations.
+  [[self animatableView] stopAnimation];
+  infoBarClosing_ = YES;
+  [self cleanUpAfterAnimation:YES];
+}
+
+- (void)animateClosed {
+  // Notify the container of our intentions.
+  [containerController_ willRemoveController:self];
+
+  // Take out the anti-spoof height so that the animation does not jump.
+  NSRect frame = [[self view] frame];
+  frame.size.height -= infobars::kAntiSpoofHeight;
+  [[self view] setFrame:frame];
+
+  // Start animating closed.  We will receive a notification when the animation
+  // is done, at which point we can remove our view from the hierarchy and
+  // notify the delegate that the infobar was closed.
+  [[self animatableView] animateToNewHeight:0 duration:kAnimateCloseDuration];
+
+  // The above call may trigger an animationDidStop: notification for any
+  // currently-running animations, so do not set |infoBarClosing_| until after
+  // starting the animation.
+  infoBarClosing_ = YES;
+}
+
+- (void)addAdditionalControls {
+  // Default implementation does nothing.
+}
+
+- (void)infobarWillClose {
+  // Default implementation does nothing.
+}
+
+- (void)setLabelToMessage:(NSString*)message {
+  NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
+  NSFont* font = [NSFont labelFontOfSize:
+      [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+  [attributes setObject:font
+                 forKey:NSFontAttributeName];
+  [attributes setObject:[NSCursor arrowCursor]
+                 forKey:NSCursorAttributeName];
+  scoped_nsobject<NSAttributedString> attributedString(
+      [[NSAttributedString alloc] initWithString:message
+                                      attributes:attributes]);
+  [[label_.get() textStorage] setAttributedString:attributedString];
+}
+
+- (void)removeButtons {
+  // Extend the label all the way across.
+  NSRect labelFrame = [label_.get() frame];
+  labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame);
+  [okButton_ removeFromSuperview];
+  [cancelButton_ removeFromSuperview];
+  [label_.get() setFrame:labelFrame];
+}
+
+@end
+
+@implementation InfoBarController (PrivateMethods)
+
+- (void)initializeLabel {
+  // Replace the label placeholder NSTextField with the real label NSTextView.
+  // The former doesn't show links in a nice way, but the latter can't be added
+  // in IB without a containing scroll view, so create the NSTextView
+  // programmatically.
+  label_.reset([[InfoBarTextView alloc]
+      initWithFrame:[labelPlaceholder_ frame]]);
+  [label_.get() setAutoresizingMask:[labelPlaceholder_ autoresizingMask]];
+  [[labelPlaceholder_ superview]
+      replaceSubview:labelPlaceholder_ with:label_.get()];
+  labelPlaceholder_ = nil;  // Now released.
+  [label_.get() setDelegate:self];
+  [label_.get() setEditable:NO];
+  [label_.get() setDrawsBackground:NO];
+  [label_.get() setHorizontallyResizable:NO];
+  [label_.get() setVerticallyResizable:NO];
+}
+
+- (void)removeInfoBar {
+  // TODO(rohitrao): This method can be called even if the infobar has already
+  // been removed and |delegate_| is NULL.  Is there a way to rewrite the code
+  // so that inner event loops don't cause us to try and remove the infobar
+  // twice?  http://crbug.com/54253
+  [containerController_ removeDelegate:delegate_];
+}
+
+- (void)cleanUpAfterAnimation:(BOOL)finished {
+  // Don't need to do any cleanup if the bar was animating open.
+  if (!infoBarClosing_)
+    return;
+
+  // Notify the delegate that the infobar was closed.  The delegate may delete
+  // itself as a result of InfoBarClosed(), so we null out its pointer.
+  if (delegate_) {
+    delegate_->InfoBarClosed();
+    delegate_ = NULL;
+  }
+
+  // If the animation ran to completion, then we need to remove ourselves from
+  // the container.  If the animation was interrupted, then the container will
+  // take care of removing us.
+  // TODO(rohitrao): UGH!  This works for now, but should be cleaner.
+  if (finished)
+    [containerController_ removeController:self];
+}
+
+- (void)animationDidStop:(NSAnimation*)animation {
+  [self cleanUpAfterAnimation:NO];
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+  [self cleanUpAfterAnimation:YES];
+}
+
+// TODO(joth): This method factors out some common functionality between the
+// various derived infobar classes, however the class hierarchy itself could
+// use refactoring to reduce this duplication. http://crbug.com/38924
+- (void)setLabelToMessage:(NSString*)message
+                 withLink:(NSString*)link
+                 atOffset:(NSUInteger)linkOffset {
+  if (linkOffset == std::wstring::npos) {
+    // linkOffset == std::wstring::npos means the link should be right-aligned,
+    // which is not supported on Mac (http://crbug.com/47728).
+    NOTIMPLEMENTED();
+    linkOffset = [message length];
+  }
+  // Create an attributes dictionary for the entire message.  We have
+  // to expicitly set the font the control's font.  We also override
+  // the cursor to give us the normal cursor rather than the text
+  // insertion cursor.
+  NSMutableDictionary* linkAttributes = [NSMutableDictionary dictionary];
+  [linkAttributes setObject:[NSCursor arrowCursor]
+                     forKey:NSCursorAttributeName];
+  NSFont* font = [NSFont labelFontOfSize:
+      [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+  [linkAttributes setObject:font
+                     forKey:NSFontAttributeName];
+
+  // Create the attributed string for the main message text.
+  scoped_nsobject<NSMutableAttributedString> infoText(
+      [[NSMutableAttributedString alloc] initWithString:message]);
+  [infoText.get() addAttributes:linkAttributes
+                    range:NSMakeRange(0, [infoText.get() length])];
+  // Add additional attributes to style the link text appropriately as
+  // well as linkify it.
+  [linkAttributes setObject:[NSColor blueColor]
+                     forKey:NSForegroundColorAttributeName];
+  [linkAttributes setObject:[NSNumber numberWithBool:YES]
+                     forKey:NSUnderlineStyleAttributeName];
+  [linkAttributes setObject:[NSCursor pointingHandCursor]
+                     forKey:NSCursorAttributeName];
+  [linkAttributes setObject:[NSNumber numberWithInt:NSSingleUnderlineStyle]
+                     forKey:NSUnderlineStyleAttributeName];
+  [linkAttributes setObject:[NSString string]  // dummy value
+                     forKey:NSLinkAttributeName];
+
+  // Insert the link text into the string at the appropriate offset.
+  scoped_nsobject<NSAttributedString> attributedString(
+      [[NSAttributedString alloc] initWithString:link
+                                      attributes:linkAttributes]);
+  [infoText.get() insertAttributedString:attributedString.get()
+                                 atIndex:linkOffset];
+  // Update the label view with the new text.
+  [[label_.get() textStorage] setAttributedString:infoText];
+}
+
+@end
+
+
+/////////////////////////////////////////////////////////////////////////
+// LinkInfoBarController implementation
+
+@implementation LinkInfoBarController
+
+// Link infobars have a text message, of which part is linkified.  We
+// use an NSAttributedString to display styled text, and we set a
+// NSLink attribute on the hyperlink portion of the message.  Infobars
+// use a custom NSTextField subclass, which allows us to override
+// textView:clickedOnLink:atIndex: and intercept clicks.
+//
+- (void)addAdditionalControls {
+  // No buttons.
+  [self removeButtons];
+
+  LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate();
+  DCHECK(delegate);
+  size_t offset = std::wstring::npos;
+  string16 message = delegate->GetMessageTextWithOffset(&offset);
+  [self setLabelToMessage:base::SysUTF16ToNSString(message)
+                 withLink:base::SysUTF16ToNSString(delegate->GetLinkText())
+                 atOffset:offset];
+}
+
+// Called when someone clicks on the link in the infobar.  This method
+// is called by the InfobarTextField on its delegate (the
+// LinkInfoBarController).
+- (void)linkClicked {
+  WindowOpenDisposition disposition =
+      event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
+  if (delegate_ && delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition))
+    [self removeInfoBar];
+}
+
+@end
+
+
+/////////////////////////////////////////////////////////////////////////
+// ConfirmInfoBarController implementation
+
+@implementation ConfirmInfoBarController
+
+// Called when someone clicks on the "OK" button.
+- (IBAction)ok:(id)sender {
+  if (delegate_ && delegate_->AsConfirmInfoBarDelegate()->Accept())
+    [self removeInfoBar];
+}
+
+// Called when someone clicks on the "Cancel" button.
+- (IBAction)cancel:(id)sender {
+  if (delegate_ && delegate_->AsConfirmInfoBarDelegate()->Cancel())
+    [self removeInfoBar];
+}
+
+// Confirm infobars can have OK and/or cancel buttons, depending on
+// the return value of GetButtons().  We create each button if
+// required and position them to the left of the close button.
+- (void)addAdditionalControls {
+  ConfirmInfoBarDelegate* delegate = delegate_->AsConfirmInfoBarDelegate();
+  DCHECK(delegate);
+  int visibleButtons = delegate->GetButtons();
+
+  NSRect okButtonFrame = [okButton_ frame];
+  NSRect cancelButtonFrame = [cancelButton_ frame];
+
+  DCHECK(NSMaxX(okButtonFrame) < NSMinX(cancelButtonFrame))
+      << "Cancel button expected to be on the right of the Ok button in nib";
+
+  CGFloat rightEdge = NSMaxX(cancelButtonFrame);
+  CGFloat spaceBetweenButtons =
+      NSMinX(cancelButtonFrame) - NSMaxX(okButtonFrame);
+  CGFloat spaceBeforeButtons =
+      NSMinX(okButtonFrame) - NSMaxX([label_.get() frame]);
+
+  // Update and position the Cancel button if needed.  Otherwise, hide it.
+  if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
+    [cancelButton_ setTitle:base::SysUTF16ToNSString(
+          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))];
+    [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_];
+    cancelButtonFrame = [cancelButton_ frame];
+
+    // Position the cancel button to the left of the Close button.
+    cancelButtonFrame.origin.x = rightEdge - cancelButtonFrame.size.width;
+    [cancelButton_ setFrame:cancelButtonFrame];
+
+    // Update the rightEdge
+    rightEdge = NSMinX(cancelButtonFrame);
+  } else {
+    [cancelButton_ removeFromSuperview];
+  }
+
+  // Update and position the OK button if needed.  Otherwise, hide it.
+  if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
+    [okButton_ setTitle:base::SysUTF16ToNSString(
+          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))];
+    [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_];
+    okButtonFrame = [okButton_ frame];
+
+    // If we had a Cancel button, leave space between the buttons.
+    if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
+      rightEdge -= spaceBetweenButtons;
+    }
+
+    // Position the OK button on our current right edge.
+    okButtonFrame.origin.x = rightEdge - okButtonFrame.size.width;
+    [okButton_ setFrame:okButtonFrame];
+
+
+    // Update the rightEdge
+    rightEdge = NSMinX(okButtonFrame);
+  } else {
+    [okButton_ removeFromSuperview];
+  }
+
+  // If we had either button, leave space before the edge of the textfield.
+  if ((visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) ||
+      (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK)) {
+    rightEdge -= spaceBeforeButtons;
+  }
+
+  NSRect frame = [label_.get() frame];
+  DCHECK(rightEdge > NSMinX(frame))
+      << "Need to make the xib larger to handle buttons with text this long";
+  frame.size.width = rightEdge - NSMinX(frame);
+  [label_.get() setFrame:frame];
+
+  // Set the text and link.
+  NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText());
+  string16 link = delegate->GetLinkText();
+  if (link.empty()) {
+    // Simple case: no link, so just set the message directly.
+    [self setLabelToMessage:message];
+  } else {
+    // Inserting the link unintentionally causes the text to have a slightly
+    // different result to the simple case above: text is truncated on word
+    // boundaries (if needed) rather than elided with ellipses.
+
+    // Add spacing between the label and the link.
+    message = [message stringByAppendingString:@"   "];
+    [self setLabelToMessage:message
+                   withLink:base::SysUTF16ToNSString(link)
+                   atOffset:[message length]];
+  }
+}
+
+// Called when someone clicks on the link in the infobar.  This method
+// is called by the InfobarTextField on its delegate (the
+// LinkInfoBarController).
+- (void)linkClicked {
+  WindowOpenDisposition disposition =
+      event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
+  if (delegate_ &&
+      delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition))
+    [self removeInfoBar];
+}
+
+@end
+
+
+//////////////////////////////////////////////////////////////////////////
+// CreateInfoBar() implementations
+
+InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
+  LinkInfoBarController* controller =
+      [[LinkInfoBarController alloc] initWithDelegate:this];
+  return new InfoBar(controller);
+}
+
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
+  ConfirmInfoBarController* controller =
+      [[ConfirmInfoBarController alloc] initWithDelegate:this];
+  return new InfoBar(controller);
+}
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_controller_unittest.mm b/chrome/browser/ui/cocoa/infobars/infobar_controller_unittest.mm
new file mode 100644
index 0000000..666969f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_controller_unittest.mm
@@ -0,0 +1,253 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
+#include "chrome/browser/ui/cocoa/infobars/infobar_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface InfoBarController (ExposedForTesting)
+- (NSString*)labelString;
+- (NSRect)labelFrame;
+@end
+
+@implementation InfoBarController (ExposedForTesting)
+- (NSString*)labelString {
+  return [label_.get() string];
+}
+- (NSRect)labelFrame {
+  return [label_.get() frame];
+}
+@end
+
+
+// Calls to removeDelegate: normally start an animation, which removes the
+// infobar completely when finished.  For unittesting purposes, we create a mock
+// container which calls close: immediately, rather than kicking off an
+// animation.
+@interface InfoBarContainerTest : NSObject<InfoBarContainer> {
+  InfoBarController* controller_;
+}
+- (id)initWithController:(InfoBarController*)controller;
+- (void)removeDelegate:(InfoBarDelegate*)delegate;
+- (void)willRemoveController:(InfoBarController*)controller;
+- (void)removeController:(InfoBarController*)controller;
+@end
+
+@implementation InfoBarContainerTest
+- (id)initWithController:(InfoBarController*)controller {
+  if ((self = [super init])) {
+    controller_ = controller;
+  }
+  return self;
+}
+
+- (void)removeDelegate:(InfoBarDelegate*)delegate {
+  [controller_ close];
+}
+
+- (void)willRemoveController:(InfoBarController*)controller {
+}
+
+- (void)removeController:(InfoBarController*)controller {
+  DCHECK(controller_ == controller);
+  controller_ = nil;
+}
+@end
+
+namespace {
+
+///////////////////////////////////////////////////////////////////////////
+// Test fixtures
+
+class LinkInfoBarControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+
+    controller_.reset(
+        [[LinkInfoBarController alloc] initWithDelegate:&delegate_]);
+    container_.reset(
+        [[InfoBarContainerTest alloc] initWithController:controller_]);
+    [controller_ setContainerController:container_];
+    [[test_window() contentView] addSubview:[controller_ view]];
+  }
+
+ protected:
+  MockLinkInfoBarDelegate delegate_;
+  scoped_nsobject<id> container_;
+  scoped_nsobject<LinkInfoBarController> controller_;
+};
+
+class ConfirmInfoBarControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+
+    controller_.reset(
+        [[ConfirmInfoBarController alloc] initWithDelegate:&delegate_]);
+    container_.reset(
+        [[InfoBarContainerTest alloc] initWithController:controller_]);
+    [controller_ setContainerController:container_];
+    [[test_window() contentView] addSubview:[controller_ view]];
+  }
+
+ protected:
+  MockConfirmInfoBarDelegate delegate_;
+  scoped_nsobject<id> container_;
+  scoped_nsobject<ConfirmInfoBarController> controller_;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// Tests
+
+TEST_VIEW(LinkInfoBarControllerTest, [controller_ view]);
+
+TEST_F(LinkInfoBarControllerTest, ShowAndDismiss) {
+  // Make sure someone looked at the message, link, and icon.
+  EXPECT_TRUE(delegate_.message_text_accessed());
+  EXPECT_TRUE(delegate_.link_text_accessed());
+  EXPECT_TRUE(delegate_.icon_accessed());
+
+  // Check that dismissing the infobar calls InfoBarClosed() on the delegate.
+  [controller_ dismiss:nil];
+  EXPECT_FALSE(delegate_.link_clicked());
+  EXPECT_TRUE(delegate_.closed());
+}
+
+TEST_F(LinkInfoBarControllerTest, ShowAndClickLink) {
+  // Check that clicking on the link calls LinkClicked() on the
+  // delegate.  It should also close the infobar.
+  [controller_ linkClicked];
+  EXPECT_TRUE(delegate_.link_clicked());
+  EXPECT_TRUE(delegate_.closed());
+}
+
+TEST_F(LinkInfoBarControllerTest, ShowAndClickLinkWithoutClosing) {
+  delegate_.set_dont_close_on_action();
+
+  // Check that clicking on the link calls LinkClicked() on the
+  // delegate.  It should not close the infobar.
+  [controller_ linkClicked];
+  EXPECT_TRUE(delegate_.link_clicked());
+  EXPECT_FALSE(delegate_.closed());
+}
+
+TEST_F(LinkInfoBarControllerTest, DeallocController) {
+  // Test that dealloc'ing the controller does not send an
+  // InfoBarClosed() message to the delegate.
+  controller_.reset(nil);
+  EXPECT_FALSE(delegate_.closed());
+}
+
+TEST_VIEW(ConfirmInfoBarControllerTest, [controller_ view]);
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndDismiss) {
+  // Make sure someone looked at the message, link, and icon.
+  EXPECT_TRUE(delegate_.message_text_accessed());
+  EXPECT_TRUE(delegate_.link_text_accessed());
+  EXPECT_TRUE(delegate_.icon_accessed());
+
+  // Check to make sure the infobar message was set properly.
+  EXPECT_EQ(MockConfirmInfoBarDelegate::kMessage,
+            base::SysNSStringToUTF8([controller_.get() labelString]));
+
+  // Check that dismissing the infobar calls InfoBarClosed() on the delegate.
+  [controller_ dismiss:nil];
+  EXPECT_FALSE(delegate_.ok_clicked());
+  EXPECT_FALSE(delegate_.cancel_clicked());
+  EXPECT_FALSE(delegate_.link_clicked());
+  EXPECT_TRUE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickOK) {
+  // Check that clicking the OK button calls Accept() and then closes
+  // the infobar.
+  [controller_ ok:nil];
+  EXPECT_TRUE(delegate_.ok_clicked());
+  EXPECT_FALSE(delegate_.cancel_clicked());
+  EXPECT_FALSE(delegate_.link_clicked());
+  EXPECT_TRUE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickOKWithoutClosing) {
+  delegate_.set_dont_close_on_action();
+
+  // Check that clicking the OK button calls Accept() but does not close
+  // the infobar.
+  [controller_ ok:nil];
+  EXPECT_TRUE(delegate_.ok_clicked());
+  EXPECT_FALSE(delegate_.cancel_clicked());
+  EXPECT_FALSE(delegate_.link_clicked());
+  EXPECT_FALSE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickCancel) {
+  // Check that clicking the cancel button calls Cancel() and closes
+  // the infobar.
+  [controller_ cancel:nil];
+  EXPECT_FALSE(delegate_.ok_clicked());
+  EXPECT_TRUE(delegate_.cancel_clicked());
+  EXPECT_FALSE(delegate_.link_clicked());
+  EXPECT_TRUE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickCancelWithoutClosing) {
+  delegate_.set_dont_close_on_action();
+
+  // Check that clicking the cancel button calls Cancel() but does not close
+  // the infobar.
+  [controller_ cancel:nil];
+  EXPECT_FALSE(delegate_.ok_clicked());
+  EXPECT_TRUE(delegate_.cancel_clicked());
+  EXPECT_FALSE(delegate_.link_clicked());
+  EXPECT_FALSE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickLink) {
+  // Check that clicking on the link calls LinkClicked() on the
+  // delegate.  It should also close the infobar.
+  [controller_ linkClicked];
+  EXPECT_FALSE(delegate_.ok_clicked());
+  EXPECT_FALSE(delegate_.cancel_clicked());
+  EXPECT_TRUE(delegate_.link_clicked());
+  EXPECT_TRUE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickLinkWithoutClosing) {
+  delegate_.set_dont_close_on_action();
+
+  // Check that clicking on the link calls LinkClicked() on the
+  // delegate.  It should not close the infobar.
+  [controller_ linkClicked];
+  EXPECT_FALSE(delegate_.ok_clicked());
+  EXPECT_FALSE(delegate_.cancel_clicked());
+  EXPECT_TRUE(delegate_.link_clicked());
+  EXPECT_FALSE(delegate_.closed());
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ResizeView) {
+  NSRect originalLabelFrame = [controller_ labelFrame];
+
+  // Expand the view by 20 pixels and make sure the label frame changes
+  // accordingly.
+  const CGFloat width = 20;
+  NSRect newViewFrame = [[controller_ view] frame];
+  newViewFrame.size.width += width;
+  [[controller_ view] setFrame:newViewFrame];
+
+  NSRect newLabelFrame = [controller_ labelFrame];
+  EXPECT_EQ(NSWidth(newLabelFrame), NSWidth(originalLabelFrame) + width);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h
new file mode 100644
index 0000000..f5b4f9e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_GRADIENT_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_GRADIENT_VIEW_H_
+#pragma once
+
+#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
+
+#import <Cocoa/Cocoa.h>
+
+// A custom view that draws the background gradient for an infobar.
+@interface InfoBarGradientView : VerticalGradientView
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_GRADIENT_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm
new file mode 100644
index 0000000..0e7fb74
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view.mm
@@ -0,0 +1,159 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/themes/browser_theme_provider.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+
+namespace {
+
+const double kBackgroundColorTop[3] =
+    {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
+const double kBackgroundColorBottom[3] =
+    {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
+}
+
+@interface InfoBarGradientView (Private)
+- (void)strokePath:(NSBezierPath*)path;
+@end
+
+@implementation InfoBarGradientView
+
+- (id)initWithFrame:(NSRect)frameRect {
+  if ((self = [super initWithFrame:frameRect])) {
+    NSColor* startingColor =
+        [NSColor colorWithCalibratedRed:kBackgroundColorTop[0]
+                                  green:kBackgroundColorTop[1]
+                                   blue:kBackgroundColorTop[2]
+                                  alpha:1.0];
+    NSColor* endingColor =
+        [NSColor colorWithCalibratedRed:kBackgroundColorBottom[0]
+                                  green:kBackgroundColorBottom[1]
+                                   blue:kBackgroundColorBottom[2]
+                                  alpha:1.0];
+    scoped_nsobject<NSGradient> gradient(
+        [[NSGradient alloc] initWithStartingColor:startingColor
+                                       endingColor:endingColor]);
+    [self setGradient:gradient];
+  }
+  return self;
+}
+
+- (NSColor*)strokeColor {
+  ui::ThemeProvider* themeProvider = [[self window] themeProvider];
+  if (!themeProvider)
+    return [NSColor blackColor];
+
+  BOOL active = [[self window] isMainWindow];
+  return themeProvider->GetNSColor(
+      active ? BrowserThemeProvider::COLOR_TOOLBAR_STROKE :
+               BrowserThemeProvider::COLOR_TOOLBAR_STROKE_INACTIVE,
+      true);
+}
+
+- (void)drawRect:(NSRect)rect {
+  NSRect bounds = [self bounds];
+  bounds.size.height -= infobars::kAntiSpoofHeight;
+
+  const CGFloat tipHeight = infobars::kAntiSpoofHeight;
+  const CGFloat curveDistance = 13.0;
+  const CGFloat iconWidth = 29.0;
+  const CGFloat tipPadding = 4.0;
+  const CGFloat pathJoinShift = 3.0;
+
+  // Draw the tab bulge that acts as the anti-spoofing countermeasure.
+  NSBezierPath* bulgePath = [NSBezierPath bezierPath];
+  NSPoint startPoint = NSMakePoint(0, NSMaxY([self frame]) - tipHeight);
+  [bulgePath moveToPoint:startPoint];
+  [bulgePath relativeCurveToPoint:NSMakePoint(curveDistance, tipHeight)
+                    // Fuzz the points by 0.5 pixels to get perfect alignment.
+                    controlPoint1:NSMakePoint(curveDistance/2, 0.5)
+                    controlPoint2:NSMakePoint(curveDistance/2,
+                                              tipHeight - 0.5)];
+
+  // The height is too small and the control points too close for the stroke
+  // across this straight line to have enough definition. Save off the points
+  // for later to create a separate line to stroke.
+  NSPoint topStrokeStart = [bulgePath currentPoint];
+  [bulgePath relativeLineToPoint:NSMakePoint(tipPadding + iconWidth, 0)];
+  NSPoint topStrokeEnd = [bulgePath currentPoint];
+
+  [bulgePath relativeCurveToPoint:NSMakePoint(curveDistance, -tipHeight)
+                    // Fuzz the points by 0.5 pixels to get perfect alignment.
+                    controlPoint1:NSMakePoint(curveDistance/2, 0.5)
+                    controlPoint2:NSMakePoint(curveDistance/2,
+                                              -tipHeight + 0.5)];
+
+  // Around the bounds of the infobar, continue drawing the path into which the
+  // gradient will be drawn.
+  scoped_nsobject<NSBezierPath> infoBarPath([bulgePath copy]);
+  [infoBarPath lineToPoint:NSMakePoint(NSMaxX(bounds), startPoint.y)];
+  [infoBarPath lineToPoint:NSMakePoint(NSMaxX(bounds), NSMinY(bounds))];
+  [infoBarPath lineToPoint:NSMakePoint(NSMinX(bounds), NSMinY(bounds))];
+  [infoBarPath lineToPoint:NSMakePoint(NSMinX(bounds), startPoint.y)];
+  [infoBarPath lineToPoint:startPoint];
+  [infoBarPath closePath];
+
+  // Stroke the bulge.
+  [bulgePath setLineCapStyle:NSSquareLineCapStyle];
+  [self strokePath:bulgePath];
+
+  // Draw the gradient.
+  [[self gradient] drawInBezierPath:infoBarPath angle:270];
+
+  // Stroke the bottom.
+  NSColor* strokeColor = [self strokeColor];
+  if (strokeColor) {
+    [strokeColor set];
+    NSRect borderRect, contentRect;
+    NSDivideRect(bounds, &borderRect, &contentRect, 1, NSMinYEdge);
+    NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+  }
+
+  // Stroke the horizontal line to ensure it has enough definition.
+  topStrokeStart.x -= pathJoinShift;
+  topStrokeEnd.x += pathJoinShift;
+  NSBezierPath* topStroke = [NSBezierPath bezierPath];
+  [topStroke moveToPoint:topStrokeStart];
+  [topStroke lineToPoint:topStrokeEnd];
+  [self strokePath:topStroke];
+}
+
+- (BOOL)mouseDownCanMoveWindow {
+  return NO;
+}
+
+// This view is intentionally not opaque because it overlaps with the findbar.
+
+- (BOOL)accessibilityIsIgnored {
+  return NO;
+}
+
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+  if ([attribute isEqual:NSAccessibilityRoleAttribute])
+    return NSAccessibilityGroupRole;
+
+  return [super accessibilityAttributeValue:attribute];
+}
+
+// Private /////////////////////////////////////////////////////////////////////
+
+// Stroking paths with just |-strokeColor| will blend with the color underneath
+// it and will make it appear lighter than it should. Stroke with black first to
+// have the stroke color come out right.
+- (void)strokePath:(NSBezierPath*)path {
+  [[NSGraphicsContext currentContext] saveGraphicsState];
+
+  [[NSColor blackColor] set];
+  [path stroke];
+  [[self strokeColor] set];
+  [path stroke];
+
+  [[NSGraphicsContext currentContext] restoreGraphicsState];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm
new file mode 100644
index 0000000..f7a6756
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_gradient_view_unittest.mm
@@ -0,0 +1,32 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+
+namespace {
+
+class InfoBarGradientViewTest : public CocoaTest {
+ public:
+  InfoBarGradientViewTest() {
+    NSRect frame = NSMakeRect(0, 0, 100, 30);
+    scoped_nsobject<InfoBarGradientView> view(
+        [[InfoBarGradientView alloc] initWithFrame:frame]);
+    view_ = view.get();
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  InfoBarGradientView* view_;  // Weak. Retained by view hierarchy.
+};
+
+TEST_VIEW(InfoBarGradientViewTest, view_);
+
+// Assert that the view is non-opaque, because otherwise we will end
+// up with findbar painting issues.
+TEST_F(InfoBarGradientViewTest, AssertViewNonOpaque) {
+  EXPECT_FALSE([view_ isOpaque]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_test_helper.h b/chrome/browser/ui/cocoa/infobars/infobar_test_helper.h
new file mode 100644
index 0000000..aca76f9
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_test_helper.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_TEST_HELPER_H_
+#define CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_TEST_HELPER_H_
+#pragma once
+
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+
+
+// MockLinkInfoBarDelegate ----------------------------------------------------
+
+class MockLinkInfoBarDelegate : public LinkInfoBarDelegate {
+ public:
+  MockLinkInfoBarDelegate();
+  virtual ~MockLinkInfoBarDelegate();
+
+  void set_dont_close_on_action() { closes_on_action_ = false; }
+
+  bool icon_accessed() const { return icon_accessed_; }
+  bool message_text_accessed() const { return message_text_accessed_; }
+  bool link_text_accessed() const { return link_text_accessed_; }
+  bool link_clicked() const { return link_clicked_; }
+  bool closed() const { return closed_; }
+
+  static const char kMessage[];
+  static const char kLink[];
+
+ private:
+  // LinkInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual string16 GetMessageTextWithOffset(size_t* link_offset) const;
+  virtual string16 GetLinkText() const;
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
+  // Determines whether the infobar closes when an action is taken or not.
+  bool closes_on_action_;
+
+  mutable bool icon_accessed_;
+  mutable bool message_text_accessed_;
+  mutable bool link_text_accessed_;
+  bool link_clicked_;
+  bool closed_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockLinkInfoBarDelegate);
+};
+
+
+// MockConfirmInfoBarDelegate -------------------------------------------------
+
+class MockConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  MockConfirmInfoBarDelegate();
+  virtual ~MockConfirmInfoBarDelegate();
+
+  void set_dont_close_on_action() { closes_on_action_ = false; }
+
+  bool icon_accessed() const { return icon_accessed_; }
+  bool message_text_accessed() const { return message_text_accessed_; }
+  bool link_text_accessed() const { return link_text_accessed_; }
+  bool ok_clicked() const { return ok_clicked_; }
+  bool cancel_clicked() const { return cancel_clicked_; }
+  bool link_clicked() const { return link_clicked_; }
+  bool closed() const { return closed_; }
+
+  static const char kMessage[];
+
+ private:
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
+  virtual string16 GetLinkText();
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
+  // Determines whether the infobar closes when an action is taken or not.
+  bool closes_on_action_;
+
+  mutable bool icon_accessed_;
+  mutable bool message_text_accessed_;
+  mutable bool link_text_accessed_;
+  bool ok_clicked_;
+  bool cancel_clicked_;
+  bool link_clicked_;
+  bool closed_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockConfirmInfoBarDelegate);
+};
+
+#endif  // CHROME_BROWSER_UI_COCOA_INFOBARS_INFOBAR_TEST_HELPER_H_
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_test_helper.mm b/chrome/browser/ui/cocoa/infobars/infobar_test_helper.mm
new file mode 100644
index 0000000..f9b7c62
--- /dev/null
+++ b/chrome/browser/ui/cocoa/infobars/infobar_test_helper.mm
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/cocoa/infobars/infobar_test_helper.h"
+
+#include "base/utf_string_conversions.h"
+
+
+// MockLinkInfoBarDelegate ----------------------------------------------------
+
+const char MockLinkInfoBarDelegate::kMessage[] = "MockLinkInfoBarMessage";
+const char MockLinkInfoBarDelegate::kLink[] = "http://dev.chromium.org";
+
+MockLinkInfoBarDelegate::MockLinkInfoBarDelegate()
+    : LinkInfoBarDelegate(NULL),
+      closes_on_action_(true),
+      icon_accessed_(false),
+      message_text_accessed_(false),
+      link_text_accessed_(false),
+      link_clicked_(false),
+      closed_(false) {
+}
+
+MockLinkInfoBarDelegate::~MockLinkInfoBarDelegate() {
+}
+
+void MockLinkInfoBarDelegate::InfoBarClosed() {
+  closed_ = true;
+}
+
+SkBitmap* MockLinkInfoBarDelegate::GetIcon() const {
+  icon_accessed_ = true;
+  return NULL;
+}
+
+string16 MockLinkInfoBarDelegate::GetMessageTextWithOffset(
+    size_t* link_offset) const {
+  message_text_accessed_ = true;
+  return ASCIIToUTF16(kMessage);
+}
+
+string16 MockLinkInfoBarDelegate::GetLinkText() const {
+  link_text_accessed_ = true;
+  return ASCIIToUTF16(kLink);
+}
+
+bool MockLinkInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
+  link_clicked_ = true;
+  return closes_on_action_;
+}
+
+
+// MockConfirmInfoBarDelegate -------------------------------------------------
+
+const char MockConfirmInfoBarDelegate::kMessage[] = "MockConfirmInfoBarMessage";
+
+MockConfirmInfoBarDelegate::MockConfirmInfoBarDelegate()
+    : ConfirmInfoBarDelegate(NULL),
+      closes_on_action_(true),
+      icon_accessed_(false),
+      message_text_accessed_(false),
+      link_text_accessed_(false),
+      ok_clicked_(false),
+      cancel_clicked_(false),
+      link_clicked_(false),
+      closed_(false) {
+}
+
+MockConfirmInfoBarDelegate::~MockConfirmInfoBarDelegate() {
+}
+
+void MockConfirmInfoBarDelegate::InfoBarClosed() {
+  closed_ = true;
+}
+
+SkBitmap* MockConfirmInfoBarDelegate::GetIcon() const {
+  icon_accessed_ = true;
+  return NULL;
+}
+
+string16 MockConfirmInfoBarDelegate::GetMessageText() const {
+  message_text_accessed_ = true;
+  return ASCIIToUTF16(kMessage);
+}
+
+string16 MockConfirmInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return ASCIIToUTF16((button == BUTTON_OK) ? "OK" : "Cancel");
+}
+
+bool MockConfirmInfoBarDelegate::Accept() {
+  ok_clicked_ = true;
+  return closes_on_action_;
+}
+
+bool MockConfirmInfoBarDelegate::Cancel() {
+  cancel_clicked_ = true;
+  return closes_on_action_;
+}
+
+string16 MockConfirmInfoBarDelegate::GetLinkText() {
+  link_text_accessed_ = true;
+  return string16();
+}
+
+bool MockConfirmInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  link_clicked_ = true;
+  return closes_on_action_;
+}
diff --git a/chrome/browser/ui/cocoa/install_from_dmg.h b/chrome/browser/ui/cocoa/install_from_dmg.h
deleted file mode 100644
index 0343cd0..0000000
--- a/chrome/browser/ui/cocoa/install_from_dmg.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_INSTALL_FROM_DMG_H_
-#define CHROME_BROWSER_UI_COCOA_INSTALL_FROM_DMG_H_
-#pragma once
-
-// If the application is running from a read-only disk image, prompts the user
-// to install it to the hard drive.  If the user approves, the application
-// will be installed and launched, and MaybeInstallFromDiskImage will return
-// true.  In that case, the caller must exit expeditiously.
-bool MaybeInstallFromDiskImage();
-
-#endif  // CHROME_BROWSER_UI_COCOA_INSTALL_FROM_DMG_H_
diff --git a/chrome/browser/ui/cocoa/install_from_dmg.mm b/chrome/browser/ui/cocoa/install_from_dmg.mm
deleted file mode 100644
index aa892cf..0000000
--- a/chrome/browser/ui/cocoa/install_from_dmg.mm
+++ /dev/null
@@ -1,438 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/install_from_dmg.h"
-
-#include <ApplicationServices/ApplicationServices.h>
-#import <AppKit/AppKit.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreServices/CoreServices.h>
-#include <IOKit/IOKitLib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-
-#include "app/l10n_util.h"
-#import "app/l10n_util_mac.h"
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#import "base/mac/mac_util.h"
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "chrome/browser/ui/cocoa/authorization_util.h"
-#include "chrome/browser/ui/cocoa/scoped_authorizationref.h"
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-// When C++ exceptions are disabled, the C++ library defines |try| and
-// |catch| so as to allow exception-expecting C++ code to build properly when
-// language support for exceptions is not present.  These macros interfere
-// with the use of |@try| and |@catch| in Objective-C files such as this one.
-// Undefine these macros here, after everything has been #included, since
-// there will be no C++ uses and only Objective-C uses from this point on.
-#undef try
-#undef catch
-
-namespace {
-
-// Just like ScopedCFTypeRef but for io_object_t and subclasses.
-template<typename IOT>
-class scoped_ioobject {
- public:
-  typedef IOT element_type;
-
-  explicit scoped_ioobject(IOT object = NULL)
-      : object_(object) {
-  }
-
-  ~scoped_ioobject() {
-    if (object_)
-      IOObjectRelease(object_);
-  }
-
-  void reset(IOT object = NULL) {
-    if (object_)
-      IOObjectRelease(object_);
-    object_ = object;
-  }
-
-  bool operator==(IOT that) const {
-    return object_ == that;
-  }
-
-  bool operator!=(IOT that) const {
-    return object_ != that;
-  }
-
-  operator IOT() const {
-    return object_;
-  }
-
-  IOT get() const {
-    return object_;
-  }
-
-  void swap(scoped_ioobject& that) {
-    IOT temp = that.object_;
-    that.object_ = object_;
-    object_ = temp;
-  }
-
-  IOT release() {
-    IOT temp = object_;
-    object_ = NULL;
-    return temp;
-  }
-
- private:
-  IOT object_;
-
-  DISALLOW_COPY_AND_ASSIGN(scoped_ioobject);
-};
-
-// Returns true if |path| is located on a read-only filesystem of a disk
-// image.  Returns false if not, or in the event of an error.
-bool IsPathOnReadOnlyDiskImage(const char path[]) {
-  struct statfs statfs_buf;
-  if (statfs(path, &statfs_buf) != 0) {
-    PLOG(ERROR) << "statfs " << path;
-    return false;
-  }
-
-  if (!(statfs_buf.f_flags & MNT_RDONLY)) {
-    // Not on a read-only filesystem.
-    return false;
-  }
-
-  const char dev_root[] = "/dev/";
-  const int dev_root_length = arraysize(dev_root) - 1;
-  if (strncmp(statfs_buf.f_mntfromname, dev_root, dev_root_length) != 0) {
-    // Not rooted at dev_root, no BSD name to search on.
-    return false;
-  }
-
-  // BSD names in IOKit don't include dev_root.
-  const char* bsd_device_name = statfs_buf.f_mntfromname + dev_root_length;
-
-  const mach_port_t master_port = kIOMasterPortDefault;
-
-  // IOBSDNameMatching gives ownership of match_dict to the caller, but
-  // IOServiceGetMatchingServices will assume that reference.
-  CFMutableDictionaryRef match_dict = IOBSDNameMatching(master_port,
-                                                        0,
-                                                        bsd_device_name);
-  if (!match_dict) {
-    LOG(ERROR) << "IOBSDNameMatching " << bsd_device_name;
-    return false;
-  }
-
-  io_iterator_t iterator_ref;
-  kern_return_t kr = IOServiceGetMatchingServices(master_port,
-                                                  match_dict,
-                                                  &iterator_ref);
-  if (kr != KERN_SUCCESS) {
-    LOG(ERROR) << "IOServiceGetMatchingServices " << bsd_device_name
-               << ": kernel error " << kr;
-    return false;
-  }
-  scoped_ioobject<io_iterator_t> iterator(iterator_ref);
-  iterator_ref = NULL;
-
-  // There needs to be exactly one matching service.
-  scoped_ioobject<io_service_t> filesystem_service(IOIteratorNext(iterator));
-  if (!filesystem_service) {
-    LOG(ERROR) << "IOIteratorNext " << bsd_device_name << ": no service";
-    return false;
-  }
-  scoped_ioobject<io_service_t> unexpected_service(IOIteratorNext(iterator));
-  if (unexpected_service) {
-    LOG(ERROR) << "IOIteratorNext " << bsd_device_name << ": too many services";
-    return false;
-  }
-
-  iterator.reset();
-
-  const char disk_image_class[] = "IOHDIXController";
-
-  // This is highly unlikely.  The filesystem service is expected to be of
-  // class IOMedia.  Since the filesystem service's entire ancestor chain
-  // will be checked, though, check the filesystem service's class itself.
-  if (IOObjectConformsTo(filesystem_service, disk_image_class)) {
-    return true;
-  }
-
-  kr = IORegistryEntryCreateIterator(filesystem_service,
-                                     kIOServicePlane,
-                                     kIORegistryIterateRecursively |
-                                         kIORegistryIterateParents,
-                                     &iterator_ref);
-  if (kr != KERN_SUCCESS) {
-    LOG(ERROR) << "IORegistryEntryCreateIterator " << bsd_device_name
-               << ": kernel error " << kr;
-    return false;
-  }
-  iterator.reset(iterator_ref);
-  iterator_ref = NULL;
-
-  // Look at each of the filesystem service's ancestor services, beginning
-  // with the parent, iterating all the way up to the device tree's root.  If
-  // any ancestor service matches the class used for disk images, the
-  // filesystem resides on a disk image.
-  for(scoped_ioobject<io_service_t> ancestor_service(IOIteratorNext(iterator));
-      ancestor_service;
-      ancestor_service.reset(IOIteratorNext(iterator))) {
-    if (IOObjectConformsTo(ancestor_service, disk_image_class)) {
-      return true;
-    }
-  }
-
-  // The filesystem does not reside on a disk image.
-  return false;
-}
-
-// Returns true if the application is located on a read-only filesystem of a
-// disk image.  Returns false if not, or in the event of an error.
-bool IsAppRunningFromReadOnlyDiskImage() {
-  return IsPathOnReadOnlyDiskImage(
-      [[[NSBundle mainBundle] bundlePath] fileSystemRepresentation]);
-}
-
-// Shows a dialog asking the user whether or not to install from the disk
-// image.  Returns true if the user approves installation.
-bool ShouldInstallDialog() {
-  NSString* title = l10n_util::GetNSStringFWithFixup(
-      IDS_INSTALL_FROM_DMG_TITLE, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  NSString* prompt = l10n_util::GetNSStringFWithFixup(
-      IDS_INSTALL_FROM_DMG_PROMPT, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  NSString* yes = l10n_util::GetNSStringWithFixup(IDS_INSTALL_FROM_DMG_YES);
-  NSString* no = l10n_util::GetNSStringWithFixup(IDS_INSTALL_FROM_DMG_NO);
-
-  NSAlert* alert = [[[NSAlert alloc] init] autorelease];
-
-  [alert setAlertStyle:NSInformationalAlertStyle];
-  [alert setMessageText:title];
-  [alert setInformativeText:prompt];
-  [alert addButtonWithTitle:yes];
-  NSButton* cancel_button = [alert addButtonWithTitle:no];
-  [cancel_button setKeyEquivalent:@"\e"];
-
-  NSInteger result = [alert runModal];
-
-  return result == NSAlertFirstButtonReturn;
-}
-
-// Potentially shows an authorization dialog to request authentication to
-// copy.  If application_directory appears to be unwritable, attempts to
-// obtain authorization, which may result in the display of the dialog.
-// Returns NULL if authorization is not performed because it does not appear
-// to be necessary because the user has permission to write to
-// application_directory.  Returns NULL if authorization fails.
-AuthorizationRef MaybeShowAuthorizationDialog(NSString* application_directory) {
-  NSFileManager* file_manager = [NSFileManager defaultManager];
-  if ([file_manager isWritableFileAtPath:application_directory]) {
-    return NULL;
-  }
-
-  NSString* prompt = l10n_util::GetNSStringFWithFixup(
-      IDS_INSTALL_FROM_DMG_AUTHENTICATION_PROMPT,
-      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  return authorization_util::AuthorizationCreateToRunAsRoot(
-      reinterpret_cast<CFStringRef>(prompt));
-}
-
-// Invokes the installer program at installer_path to copy source_path to
-// target_path and perform any additional on-disk bookkeeping needed to be
-// able to launch target_path properly.  If authorization_arg is non-NULL,
-// function will assume ownership of it, will invoke the installer with that
-// authorization reference, and will attempt Keystone ticket promotion.
-bool InstallFromDiskImage(AuthorizationRef authorization_arg,
-                          NSString* installer_path,
-                          NSString* source_path,
-                          NSString* target_path) {
-  scoped_AuthorizationRef authorization(authorization_arg);
-  authorization_arg = NULL;
-  int exit_status;
-  if (authorization) {
-    const char* installer_path_c = [installer_path fileSystemRepresentation];
-    const char* source_path_c = [source_path fileSystemRepresentation];
-    const char* target_path_c = [target_path fileSystemRepresentation];
-    const char* arguments[] = {source_path_c, target_path_c, NULL};
-
-    OSStatus status = authorization_util::ExecuteWithPrivilegesAndWait(
-        authorization,
-        installer_path_c,
-        kAuthorizationFlagDefaults,
-        arguments,
-        NULL,  // pipe
-        &exit_status);
-    if (status != errAuthorizationSuccess) {
-      LOG(ERROR) << "AuthorizationExecuteWithPrivileges install: " << status;
-      return false;
-    }
-  } else {
-    NSArray* arguments = [NSArray arrayWithObjects:source_path,
-                                                   target_path,
-                                                   nil];
-
-    NSTask* task;
-    @try {
-      task = [NSTask launchedTaskWithLaunchPath:installer_path
-                                      arguments:arguments];
-    } @catch(NSException* exception) {
-      LOG(ERROR) << "+[NSTask launchedTaskWithLaunchPath:arguments:]: "
-                 << [[exception description] UTF8String];
-      return false;
-    }
-
-    [task waitUntilExit];
-    exit_status = [task terminationStatus];
-  }
-
-  if (exit_status != 0) {
-    LOG(ERROR) << "install.sh: exit status " << exit_status;
-    return false;
-  }
-
-  if (authorization) {
-    // As long as an AuthorizationRef is available, promote the Keystone
-    // ticket.  Inform KeystoneGlue of the new path to use.
-    KeystoneGlue* keystone_glue = [KeystoneGlue defaultKeystoneGlue];
-    [keystone_glue setAppPath:target_path];
-    [keystone_glue promoteTicketWithAuthorization:authorization.release()
-                                      synchronous:YES];
-  }
-
-  return true;
-}
-
-// Launches the application at app_path.  The arguments passed to app_path
-// will be the same as the arguments used to invoke this process, except any
-// arguments beginning with -psn_ will be stripped.
-bool LaunchInstalledApp(NSString* app_path) {
-  const UInt8* app_path_c =
-      reinterpret_cast<const UInt8*>([app_path fileSystemRepresentation]);
-  FSRef app_fsref;
-  OSStatus err = FSPathMakeRef(app_path_c, &app_fsref, NULL);
-  if (err != noErr) {
-    LOG(ERROR) << "FSPathMakeRef: " << err;
-    return false;
-  }
-
-  const std::vector<std::string>& argv =
-      CommandLine::ForCurrentProcess()->argv();
-  NSMutableArray* arguments =
-      [NSMutableArray arrayWithCapacity:argv.size() - 1];
-  // Start at argv[1].  LSOpenApplication adds its own argv[0] as the path of
-  // the launched executable.
-  for (size_t index = 1; index < argv.size(); ++index) {
-    std::string argument = argv[index];
-    const char psn_flag[] = "-psn_";
-    const int psn_flag_length = arraysize(psn_flag) - 1;
-    if (argument.compare(0, psn_flag_length, psn_flag) != 0) {
-      // Strip any -psn_ arguments, as they apply to a specific process.
-      [arguments addObject:[NSString stringWithUTF8String:argument.c_str()]];
-    }
-  }
-
-  struct LSApplicationParameters parameters = {0};
-  parameters.flags = kLSLaunchDefaults;
-  parameters.application = &app_fsref;
-  parameters.argv = reinterpret_cast<CFArrayRef>(arguments);
-
-  err = LSOpenApplication(&parameters, NULL);
-  if (err != noErr) {
-    LOG(ERROR) << "LSOpenApplication: " << err;
-    return false;
-  }
-
-  return true;
-}
-
-void ShowErrorDialog() {
-  NSString* title = l10n_util::GetNSStringWithFixup(
-      IDS_INSTALL_FROM_DMG_ERROR_TITLE);
-  NSString* error = l10n_util::GetNSStringFWithFixup(
-      IDS_INSTALL_FROM_DMG_ERROR, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  NSString* ok = l10n_util::GetNSStringWithFixup(IDS_OK);
-
-  NSAlert* alert = [[[NSAlert alloc] init] autorelease];
-
-  [alert setAlertStyle:NSWarningAlertStyle];
-  [alert setMessageText:title];
-  [alert setInformativeText:error];
-  [alert addButtonWithTitle:ok];
-
-  [alert runModal];
-}
-
-}  // namespace
-
-bool MaybeInstallFromDiskImage() {
-  base::mac::ScopedNSAutoreleasePool autorelease_pool;
-
-  if (!IsAppRunningFromReadOnlyDiskImage()) {
-    return false;
-  }
-
-  NSArray* application_directories =
-      NSSearchPathForDirectoriesInDomains(NSApplicationDirectory,
-                                          NSLocalDomainMask,
-                                          YES);
-  if ([application_directories count] == 0) {
-    LOG(ERROR) << "NSSearchPathForDirectoriesInDomains: "
-               << "no local application directories";
-    return false;
-  }
-  NSString* application_directory = [application_directories objectAtIndex:0];
-
-  NSFileManager* file_manager = [NSFileManager defaultManager];
-
-  BOOL is_directory;
-  if (![file_manager fileExistsAtPath:application_directory
-                          isDirectory:&is_directory] ||
-      !is_directory) {
-    VLOG(1) << "No application directory at "
-            << [application_directory UTF8String];
-    return false;
-  }
-
-  NSString* source_path = [[NSBundle mainBundle] bundlePath];
-  NSString* application_name = [source_path lastPathComponent];
-  NSString* target_path =
-      [application_directory stringByAppendingPathComponent:application_name];
-
-  if ([file_manager fileExistsAtPath:target_path]) {
-    VLOG(1) << "Something already exists at " << [target_path UTF8String];
-    return false;
-  }
-
-  NSString* installer_path =
-      [base::mac::MainAppBundle() pathForResource:@"install" ofType:@"sh"];
-  if (!installer_path) {
-    VLOG(1) << "Could not locate install.sh";
-    return false;
-  }
-
-  if (!ShouldInstallDialog()) {
-    return false;
-  }
-
-  scoped_AuthorizationRef authorization(
-      MaybeShowAuthorizationDialog(application_directory));
-  // authorization will be NULL if it's deemed unnecessary or if
-  // authentication fails.  In either case, try to install without privilege
-  // escalation.
-
-  if (!InstallFromDiskImage(authorization.release(),
-                            installer_path,
-                            source_path,
-                            target_path) ||
-      !LaunchInstalledApp(target_path)) {
-    ShowErrorDialog();
-    return false;
-  }
-
-  return true;
-}
diff --git a/chrome/browser/ui/cocoa/instant_confirm_window_controller.mm b/chrome/browser/ui/cocoa/instant_confirm_window_controller.mm
index 07405d6..c98d3f0 100644
--- a/chrome/browser/ui/cocoa/instant_confirm_window_controller.mm
+++ b/chrome/browser/ui/cocoa/instant_confirm_window_controller.mm
@@ -10,9 +10,9 @@
 #include "chrome/browser/instant/instant_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/options/show_options_url.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace browser {
 
diff --git a/chrome/browser/ui/cocoa/js_modal_dialog_cocoa.mm b/chrome/browser/ui/cocoa/js_modal_dialog_cocoa.mm
index 219c448..62825d5 100644
--- a/chrome/browser/ui/cocoa/js_modal_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/js_modal_dialog_cocoa.mm
@@ -6,8 +6,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/l10n_util_mac.h"
-#include "app/message_box_flags.h"
 #include "base/logging.h"
 #import "base/mac/cocoa_protocols.h"
 #include "base/sys_string_conversions.h"
@@ -15,6 +13,8 @@
 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
 #include "grit/app_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/message_box_flags.h"
 
 // Helper object that receives the notification that the dialog/sheet is
 // going away. Is responsible for cleaning itself up.
@@ -106,10 +106,10 @@
   bool text_field = false;
   bool one_button = false;
   switch (dialog_->dialog_flags()) {
-    case MessageBoxFlags::kIsJavascriptAlert:
+    case ui::MessageBoxFlags::kIsJavascriptAlert:
       one_button = true;
       break;
-    case MessageBoxFlags::kIsJavascriptConfirm:
+    case ui::MessageBoxFlags::kIsJavascriptConfirm:
       if (dialog_->is_before_unload_dialog()) {
         default_button = l10n_util::GetNSStringWithFixup(
             IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL);
@@ -117,7 +117,7 @@
             IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL);
       }
       break;
-    case MessageBoxFlags::kIsJavascriptPrompt:
+    case ui::MessageBoxFlags::kIsJavascriptPrompt:
       text_field = true;
       break;
 
@@ -166,10 +166,10 @@
   int num_buttons = [[alert_ buttons] count];
   switch (num_buttons) {
     case 1:
-      return MessageBoxFlags::DIALOGBUTTON_OK;
+      return ui::MessageBoxFlags::DIALOGBUTTON_OK;
     case 2:
-      return MessageBoxFlags::DIALOGBUTTON_OK |
-             MessageBoxFlags::DIALOGBUTTON_CANCEL;
+      return ui::MessageBoxFlags::DIALOGBUTTON_OK |
+             ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
     default:
       NOTREACHED();
       return 0;
diff --git a/chrome/browser/ui/cocoa/keystone_glue.h b/chrome/browser/ui/cocoa/keystone_glue.h
deleted file mode 100644
index c20bdb4..0000000
--- a/chrome/browser/ui/cocoa/keystone_glue.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_KEYSTONE_GLUE_H_
-#define CHROME_BROWSER_UI_COCOA_KEYSTONE_GLUE_H_
-#pragma once
-
-#include "base/string16.h"
-
-#if defined(__OBJC__)
-
-#import <Foundation/Foundation.h>
-
-#import "base/scoped_nsobject.h"
-#include "chrome/browser/ui/cocoa/scoped_authorizationref.h"
-
-// Possible outcomes of various operations.  A version may accompany some of
-// these, but beware: a version is never required.  For statuses that can be
-// accompanied by a version, the comment indicates what version is referenced.
-// A notification posted containing an asynchronous status will always be
-// followed by a notification with a terminal status.
-enum AutoupdateStatus {
-  kAutoupdateNone = 0,        // no version (initial state only)
-  kAutoupdateRegistering,     // no version (asynchronous operation in progress)
-  kAutoupdateRegistered,      // no version
-  kAutoupdateChecking,        // no version (asynchronous operation in progress)
-  kAutoupdateCurrent,         // version of the running application
-  kAutoupdateAvailable,       // version of the update that is available
-  kAutoupdateInstalling,      // no version (asynchronous operation in progress)
-  kAutoupdateInstalled,       // version of the update that was installed
-  kAutoupdatePromoting,       // no version (asynchronous operation in progress)
-  kAutoupdatePromoted,        // no version
-  kAutoupdateRegisterFailed,  // no version
-  kAutoupdateCheckFailed,     // no version
-  kAutoupdateInstallFailed,   // no version
-  kAutoupdatePromoteFailed,   // no version
-};
-
-// kAutoupdateStatusNotification is the name of the notification posted when
-// -checkForUpdate and -installUpdate complete.  This notification will be
-// sent with with its sender object set to the KeystoneGlue instance sending
-// the notification.  Its userInfo dictionary will contain an AutoupdateStatus
-// value as an intValue at key kAutoupdateStatusStatus.  If a version is
-// available (see AutoupdateStatus), it will be present at key
-// kAutoupdateStatusVersion.
-extern NSString* const kAutoupdateStatusNotification;
-extern NSString* const kAutoupdateStatusStatus;
-extern NSString* const kAutoupdateStatusVersion;
-
-namespace {
-
-enum BrandFileType {
-  kBrandFileTypeNotDetermined = 0,
-  kBrandFileTypeNone,
-  kBrandFileTypeUser,
-  kBrandFileTypeSystem,
-};
-
-} // namespace
-
-// KeystoneGlue is an adapter around the KSRegistration class, allowing it to
-// be used without linking directly against its containing KeystoneRegistration
-// framework.  This is used in an environment where most builds (such as
-// developer builds) don't want or need Keystone support and might not even
-// have the framework available.  Enabling Keystone support in an application
-// that uses KeystoneGlue is as simple as dropping
-// KeystoneRegistration.framework in the application's Frameworks directory
-// and providing the relevant information in its Info.plist.  KeystoneGlue
-// requires that the KSUpdateURL key be set in the application's Info.plist,
-// and that it contain a string identifying the update URL to be used by
-// Keystone.
-
-@class KSRegistration;
-
-@interface KeystoneGlue : NSObject {
- @protected
-
-  // Data for Keystone registration
-  NSString* productID_;
-  NSString* appPath_;
-  NSString* url_;
-  NSString* version_;
-  NSString* channel_;  // Logically: Dev, Beta, or Stable.
-  BrandFileType brandFileType_;
-
-  // And the Keystone registration itself, with the active timer
-  KSRegistration* registration_;  // strong
-  NSTimer* timer_;  // strong
-
-  // The most recent kAutoupdateStatusNotification notification posted.
-  scoped_nsobject<NSNotification> recentNotification_;
-
-  // The authorization object, when it needs to persist because it's being
-  // carried across threads.
-  scoped_AuthorizationRef authorization_;
-
-  // YES if a synchronous promotion operation is in progress (promotion during
-  // installation).
-  BOOL synchronousPromotion_;
-
-  // YES if an update was ever successfully installed by -installUpdate.
-  BOOL updateSuccessfullyInstalled_;
-}
-
-// Return the default Keystone Glue object.
-+ (id)defaultKeystoneGlue;
-
-// Load KeystoneRegistration.framework if present, call into it to register
-// with Keystone, and set up periodic activity pings.
-- (void)registerWithKeystone;
-
-// -checkForUpdate launches a check for updates, and -installUpdate begins
-// installing an available update.  For each, status will be communicated via
-// a kAutoupdateStatusNotification notification, and will also be available
-// through -recentNotification.
-- (void)checkForUpdate;
-- (void)installUpdate;
-
-// Accessor for recentNotification_.  Returns an autoreleased NSNotification.
-- (NSNotification*)recentNotification;
-
-// Accessor for the kAutoupdateStatusStatus field of recentNotification_'s
-// userInfo dictionary.
-- (AutoupdateStatus)recentStatus;
-
-// Returns YES if an asynchronous operation is pending: if an update check or
-// installation attempt is currently in progress.
-- (BOOL)asyncOperationPending;
-
-// Returns YES if the application is running from a read-only filesystem,
-// such as a disk image.
-- (BOOL)isOnReadOnlyFilesystem;
-
-// -needsPromotion is YES if the application needs its ticket promoted to
-// a system ticket.  This will be YES when the application is on a user
-// ticket and determines that the current user does not have sufficient
-// permission to perform the update.
-//
-// -wantsPromotion is YES if the application wants its ticket promoted to
-// a system ticket, even if it doesn't need it as determined by
-// -needsPromotion.  -wantsPromotion will always be YES if -needsPromotion is,
-// and it will additionally be YES when the application is on a user ticket
-// and appears to be installed in a system-wide location such as
-// /Applications.
-//
-// Use -needsPromotion to decide whether to show any update UI at all.  If
-// it's YES, there's no sense in asking the user to "update now" because it
-// will fail given the rights and permissions involved.  On the other hand,
-// when -needsPromotion is YES, the application can encourage the user to
-// promote the ticket so that updates will work properly.
-//
-// Use -wantsPromotion to decide whether to allow the user to promote.  The
-// user shouldn't be nagged about promotion on the basis of -wantsPromotion,
-// but if it's YES, the user should be allowed to promote the ticket.
-- (BOOL)needsPromotion;
-- (BOOL)wantsPromotion;
-
-// Promotes the Keystone ticket into the system store.  System Keystone will
-// be installed if necessary.  If synchronous is NO, the promotion may occur
-// in the background.  synchronous should be YES for promotion during
-// installation. The KeystoneGlue object assumes ownership of
-// authorization_arg.
-- (void)promoteTicketWithAuthorization:(AuthorizationRef)authorization_arg
-                           synchronous:(BOOL)synchronous;
-
-// Requests authorization and calls -promoteTicketWithAuthorization: in
-// asynchronous mode.
-- (void)promoteTicket;
-
-// Sets a new value for appPath.  Used during installation to point a ticket
-// at the installed copy.
-- (void)setAppPath:(NSString*)appPath;
-
-@end  // @interface KeystoneGlue
-
-@interface KeystoneGlue(ExposedForTesting)
-
-// Load any params we need for configuring Keystone.
-- (void)loadParameters;
-
-// Load the Keystone registration object.
-// Return NO on failure.
-- (BOOL)loadKeystoneRegistration;
-
-- (void)stopTimer;
-
-// Called when a checkForUpdate: notification completes.
-- (void)checkForUpdateComplete:(NSNotification*)notification;
-
-// Called when an installUpdate: notification completes.
-- (void)installUpdateComplete:(NSNotification*)notification;
-
-@end  // @interface KeystoneGlue(ExposedForTesting)
-
-#endif  // __OBJC__
-
-// Functions that may be accessed from non-Objective-C C/C++ code.
-namespace keystone_glue {
-
-// True if Keystone is enabled.
-bool KeystoneEnabled();
-
-// The version of the application currently installed on disk.
-string16 CurrentlyInstalledVersion();
-
-}  // namespace keystone_glue
-
-#endif  // CHROME_BROWSER_UI_COCOA_KEYSTONE_GLUE_H_
diff --git a/chrome/browser/ui/cocoa/keystone_glue.mm b/chrome/browser/ui/cocoa/keystone_glue.mm
deleted file mode 100644
index 8ac3daf..0000000
--- a/chrome/browser/ui/cocoa/keystone_glue.mm
+++ /dev/null
@@ -1,957 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
-
-#include <sys/param.h>
-#include <sys/mount.h>
-
-#include <vector>
-
-#include "app/l10n_util.h"
-#import "app/l10n_util_mac.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/sys_string_conversions.h"
-#include "base/ref_counted.h"
-#include "base/task.h"
-#include "base/threading/worker_pool.h"
-#include "chrome/browser/ui/cocoa/authorization_util.h"
-#include "chrome/common/chrome_constants.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-// Provide declarations of the Keystone registration bits needed here.  From
-// KSRegistration.h.
-typedef enum {
-  kKSPathExistenceChecker,
-} KSExistenceCheckerType;
-
-typedef enum {
-  kKSRegistrationUserTicket,
-  kKSRegistrationSystemTicket,
-  kKSRegistrationDontKnowWhatKindOfTicket,
-} KSRegistrationTicketType;
-
-NSString* const KSRegistrationVersionKey = @"Version";
-NSString* const KSRegistrationExistenceCheckerTypeKey = @"ExistenceCheckerType";
-NSString* const KSRegistrationExistenceCheckerStringKey =
-    @"ExistenceCheckerString";
-NSString* const KSRegistrationServerURLStringKey = @"URLString";
-NSString* const KSRegistrationPreserveTrustedTesterTokenKey = @"PreserveTTT";
-NSString* const KSRegistrationTagKey = @"Tag";
-NSString* const KSRegistrationTagPathKey = @"TagPath";
-NSString* const KSRegistrationTagKeyKey = @"TagKey";
-NSString* const KSRegistrationBrandPathKey = @"BrandPath";
-NSString* const KSRegistrationBrandKeyKey = @"BrandKey";
-
-NSString* const KSRegistrationDidCompleteNotification =
-    @"KSRegistrationDidCompleteNotification";
-NSString* const KSRegistrationPromotionDidCompleteNotification =
-    @"KSRegistrationPromotionDidCompleteNotification";
-
-NSString* const KSRegistrationCheckForUpdateNotification =
-    @"KSRegistrationCheckForUpdateNotification";
-NSString* KSRegistrationStatusKey = @"Status";
-NSString* KSRegistrationUpdateCheckErrorKey = @"Error";
-
-NSString* const KSRegistrationStartUpdateNotification =
-    @"KSRegistrationStartUpdateNotification";
-NSString* const KSUpdateCheckSuccessfulKey = @"CheckSuccessful";
-NSString* const KSUpdateCheckSuccessfullyInstalledKey =
-    @"SuccessfullyInstalled";
-
-NSString* const KSRegistrationRemoveExistingTag = @"";
-#define KSRegistrationPreserveExistingTag nil
-
-// Constants for the brand file (uses an external file so it can survive updates
-// to Chrome.
-
-#if defined(GOOGLE_CHROME_BUILD)
-#define kBrandFileName @"Google Chrome Brand.plist";
-#elif defined(CHROMIUM_BUILD)
-#define kBrandFileName @"Chromium Brand.plist";
-#else
-#error Unknown branding
-#endif
-
-// These directories are hardcoded in Keystone promotion preflight and the
-// Keystone install script, so NSSearchPathForDirectoriesInDomains isn't used
-// since the scripts couldn't use anything like that.
-NSString* kBrandUserFile = @"~/Library/Google/" kBrandFileName;
-NSString* kBrandSystemFile = @"/Library/Google/" kBrandFileName;
-
-NSString* UserBrandFilePath() {
-  return [kBrandUserFile stringByStandardizingPath];
-}
-NSString* SystemBrandFilePath() {
-  return [kBrandSystemFile stringByStandardizingPath];
-}
-
-// Adaptor for scheduling an Objective-C method call on a |WorkerPool|
-// thread.
-class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> {
- public:
-
-  // Call |sel| on |target| with |arg| in a WorkerPool thread.
-  // |target| and |arg| are retained, |arg| may be |nil|.
-  static void PostPerform(id target, SEL sel, id arg) {
-    DCHECK(target);
-    DCHECK(sel);
-
-    scoped_refptr<PerformBridge> op = new PerformBridge(target, sel, arg);
-    base::WorkerPool::PostTask(
-        FROM_HERE, NewRunnableMethod(op.get(), &PerformBridge::Run), true);
-  }
-
-  // Convenience for the no-argument case.
-  static void PostPerform(id target, SEL sel) {
-    PostPerform(target, sel, nil);
-  }
-
- private:
-  // Allow RefCountedThreadSafe<> to delete.
-  friend class base::RefCountedThreadSafe<PerformBridge>;
-
-  PerformBridge(id target, SEL sel, id arg)
-      : target_([target retain]),
-        sel_(sel),
-        arg_([arg retain]) {
-  }
-
-  ~PerformBridge() {}
-
-  // Happens on a WorkerPool thread.
-  void Run() {
-    base::mac::ScopedNSAutoreleasePool pool;
-    [target_ performSelector:sel_ withObject:arg_];
-  }
-
-  scoped_nsobject<id> target_;
-  SEL sel_;
-  scoped_nsobject<id> arg_;
-};
-
-}  // namespace
-
-@interface KSRegistration : NSObject
-
-+ (id)registrationWithProductID:(NSString*)productID;
-
-- (BOOL)registerWithParameters:(NSDictionary*)args;
-
-- (BOOL)promoteWithParameters:(NSDictionary*)args
-                authorization:(AuthorizationRef)authorization;
-
-- (void)setActive;
-- (void)checkForUpdate;
-- (void)startUpdate;
-- (KSRegistrationTicketType)ticketType;
-
-@end  // @interface KSRegistration
-
-@interface KeystoneGlue(Private)
-
-// Returns the path to the application's Info.plist file.  This returns the
-// outer application bundle's Info.plist, not the framework's Info.plist.
-- (NSString*)appInfoPlistPath;
-
-// Returns a dictionary containing parameters to be used for a KSRegistration
-// -registerWithParameters: or -promoteWithParameters:authorization: call.
-- (NSDictionary*)keystoneParameters;
-
-// Called when Keystone registration completes.
-- (void)registrationComplete:(NSNotification*)notification;
-
-// Called periodically to announce activity by pinging the Keystone server.
-- (void)markActive:(NSTimer*)timer;
-
-// Called when an update check or update installation is complete.  Posts the
-// kAutoupdateStatusNotification notification to the default notification
-// center.
-- (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version;
-
-// Returns the version of the currently-installed application on disk.
-- (NSString*)currentlyInstalledVersion;
-
-// These three methods are used to determine the version of the application
-// currently installed on disk, compare that to the currently-running version,
-// decide whether any updates have been installed, and call
-// -updateStatus:version:.
-//
-// In order to check the version on disk, the installed application's
-// Info.plist dictionary must be read; in order to see changes as updates are
-// applied, the dictionary must be read each time, bypassing any caches such
-// as the one that NSBundle might be maintaining.  Reading files can be a
-// blocking operation, and blocking operations are to be avoided on the main
-// thread.  I'm not quite sure what jank means, but I bet that a blocked main
-// thread would cause some of it.
-//
-// -determineUpdateStatusAsync is called on the main thread to initiate the
-// operation.  It performs initial set-up work that must be done on the main
-// thread and arranges for -determineUpdateStatus to be called on a work queue
-// thread managed by WorkerPool.
-// -determineUpdateStatus then reads the Info.plist, gets the version from the
-// CFBundleShortVersionString key, and performs
-// -determineUpdateStatusForVersion: on the main thread.
-// -determineUpdateStatusForVersion: does the actual comparison of the version
-// on disk with the running version and calls -updateStatus:version: with the
-// results of its analysis.
-- (void)determineUpdateStatusAsync;
-- (void)determineUpdateStatus;
-- (void)determineUpdateStatusForVersion:(NSString*)version;
-
-// Returns YES if registration_ is definitely on a user ticket.  If definitely
-// on a system ticket, or uncertain of ticket type (due to an older version
-// of Keystone being used), returns NO.
-- (BOOL)isUserTicket;
-
-// Called when ticket promotion completes.
-- (void)promotionComplete:(NSNotification*)notification;
-
-// Changes the application's ownership and permissions so that all files are
-// owned by root:wheel and all files and directories are writable only by
-// root, but readable and executable as needed by everyone.
-// -changePermissionsForPromotionAsync is called on the main thread by
-// -promotionComplete.  That routine calls
-// -changePermissionsForPromotionWithTool: on a work queue thread.  When done,
-// -changePermissionsForPromotionComplete is called on the main thread.
-- (void)changePermissionsForPromotionAsync;
-- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath;
-- (void)changePermissionsForPromotionComplete;
-
-// Returns the brand file path to use for Keystone.
-- (NSString*)brandFilePath;
-
-@end  // @interface KeystoneGlue(Private)
-
-NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification";
-NSString* const kAutoupdateStatusStatus = @"status";
-NSString* const kAutoupdateStatusVersion = @"version";
-
-namespace {
-
-NSString* const kChannelKey = @"KSChannelID";
-NSString* const kBrandKey = @"KSBrandID";
-
-}  // namespace
-
-@implementation KeystoneGlue
-
-+ (id)defaultKeystoneGlue {
-  static bool sTriedCreatingDefaultKeystoneGlue = false;
-  // TODO(jrg): use base::SingletonObjC<KeystoneGlue>
-  static KeystoneGlue* sDefaultKeystoneGlue = nil;  // leaked
-
-  if (!sTriedCreatingDefaultKeystoneGlue) {
-    sTriedCreatingDefaultKeystoneGlue = true;
-
-    sDefaultKeystoneGlue = [[KeystoneGlue alloc] init];
-    [sDefaultKeystoneGlue loadParameters];
-    if (![sDefaultKeystoneGlue loadKeystoneRegistration]) {
-      [sDefaultKeystoneGlue release];
-      sDefaultKeystoneGlue = nil;
-    }
-  }
-  return sDefaultKeystoneGlue;
-}
-
-- (id)init {
-  if ((self = [super init])) {
-    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-
-    [center addObserver:self
-               selector:@selector(registrationComplete:)
-                   name:KSRegistrationDidCompleteNotification
-                 object:nil];
-
-    [center addObserver:self
-               selector:@selector(promotionComplete:)
-                   name:KSRegistrationPromotionDidCompleteNotification
-                 object:nil];
-
-    [center addObserver:self
-               selector:@selector(checkForUpdateComplete:)
-                   name:KSRegistrationCheckForUpdateNotification
-                 object:nil];
-
-    [center addObserver:self
-               selector:@selector(installUpdateComplete:)
-                   name:KSRegistrationStartUpdateNotification
-                 object:nil];
-  }
-
-  return self;
-}
-
-- (void)dealloc {
-  [productID_ release];
-  [appPath_ release];
-  [url_ release];
-  [version_ release];
-  [channel_ release];
-  [registration_ release];
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [super dealloc];
-}
-
-- (NSDictionary*)infoDictionary {
-  // Use [NSBundle mainBundle] to get the application's own bundle identifier
-  // and path, not the framework's.  For auto-update, the application is
-  // what's significant here: it's used to locate the outermost part of the
-  // application for the existence checker and other operations that need to
-  // see the entire application bundle.
-  return [[NSBundle mainBundle] infoDictionary];
-}
-
-- (void)loadParameters {
-  NSBundle* appBundle = [NSBundle mainBundle];
-  NSDictionary* infoDictionary = [self infoDictionary];
-
-  NSString* productID = [infoDictionary objectForKey:@"KSProductID"];
-  if (productID == nil) {
-    productID = [appBundle bundleIdentifier];
-  }
-
-  NSString* appPath = [appBundle bundlePath];
-  NSString* url = [infoDictionary objectForKey:@"KSUpdateURL"];
-  NSString* version = [infoDictionary objectForKey:@"KSVersion"];
-
-  if (!productID || !appPath || !url || !version) {
-    // If parameters required for Keystone are missing, don't use it.
-    return;
-  }
-
-  NSString* channel = [infoDictionary objectForKey:kChannelKey];
-  // The stable channel has no tag.  If updating to stable, remove the
-  // dev and beta tags since we've been "promoted".
-  if (channel == nil)
-    channel = KSRegistrationRemoveExistingTag;
-
-  productID_ = [productID retain];
-  appPath_ = [appPath retain];
-  url_ = [url retain];
-  version_ = [version retain];
-  channel_ = [channel retain];
-}
-
-- (NSString*)brandFilePath {
-  DCHECK(version_ != nil) << "-loadParameters must be called first";
-
-  if (brandFileType_ == kBrandFileTypeNotDetermined) {
-
-    // Default to none.
-    brandFileType_ = kBrandFileTypeNone;
-
-    // Having a channel means Dev/Beta, so there is no brand code to go with
-    // those.
-    if ([channel_ length] == 0) {
-
-      NSString* userBrandFile = UserBrandFilePath();
-      NSString* systemBrandFile = SystemBrandFilePath();
-
-      NSFileManager* fm = [NSFileManager defaultManager];
-
-      // If there is a system brand file, use it.
-      if ([fm fileExistsAtPath:systemBrandFile]) {
-        // System
-
-        // Use the system file that is there.
-        brandFileType_ = kBrandFileTypeSystem;
-
-        // Clean up any old user level file.
-        if ([fm fileExistsAtPath:userBrandFile]) {
-          [fm removeItemAtPath:userBrandFile error:NULL];
-        }
-
-      } else {
-        // User
-
-        NSDictionary* infoDictionary = [self infoDictionary];
-        NSString* appBundleBrandID = [infoDictionary objectForKey:kBrandKey];
-
-        NSString* storedBrandID = nil;
-        if ([fm fileExistsAtPath:userBrandFile]) {
-          NSDictionary* storedBrandDict =
-              [NSDictionary dictionaryWithContentsOfFile:userBrandFile];
-          storedBrandID = [storedBrandDict objectForKey:kBrandKey];
-        }
-
-        if ((appBundleBrandID != nil) &&
-            (![storedBrandID isEqualTo:appBundleBrandID])) {
-          // App and store don't match, update store and use it.
-          NSDictionary* storedBrandDict =
-              [NSDictionary dictionaryWithObject:appBundleBrandID
-                                          forKey:kBrandKey];
-          // If Keystone hasn't been installed yet, the location the brand file
-          // is written to won't exist, so manually create the directory.
-          NSString *userBrandFileDirectory =
-              [userBrandFile stringByDeletingLastPathComponent];
-          if (![fm fileExistsAtPath:userBrandFileDirectory]) {
-            if (![fm createDirectoryAtPath:userBrandFileDirectory
-               withIntermediateDirectories:YES
-                                attributes:nil
-                                     error:NULL]) {
-              LOG(ERROR) << "Failed to create the directory for the brand file";
-            }
-          }
-          if ([storedBrandDict writeToFile:userBrandFile atomically:YES]) {
-            brandFileType_ = kBrandFileTypeUser;
-          }
-        } else if (storedBrandID) {
-          // Had stored brand, use it.
-          brandFileType_ = kBrandFileTypeUser;
-        }
-      }
-    }
-
-  }
-
-  NSString* result = nil;
-  switch (brandFileType_) {
-    case kBrandFileTypeUser:
-      result = UserBrandFilePath();
-      break;
-
-    case kBrandFileTypeSystem:
-      result = SystemBrandFilePath();
-      break;
-
-    case kBrandFileTypeNotDetermined:
-      NOTIMPLEMENTED();
-      // Fall through
-    case kBrandFileTypeNone:
-      // Clear the value.
-      result = @"";
-      break;
-
-  }
-  return result;
-}
-
-- (BOOL)loadKeystoneRegistration {
-  if (!productID_ || !appPath_ || !url_ || !version_)
-    return NO;
-
-  // Load the KeystoneRegistration framework bundle if present.  It lives
-  // inside the framework, so use base::mac::MainAppBundle();
-  NSString* ksrPath =
-      [[base::mac::MainAppBundle() privateFrameworksPath]
-          stringByAppendingPathComponent:@"KeystoneRegistration.framework"];
-  NSBundle* ksrBundle = [NSBundle bundleWithPath:ksrPath];
-  [ksrBundle load];
-
-  // Harness the KSRegistration class.
-  Class ksrClass = [ksrBundle classNamed:@"KSRegistration"];
-  KSRegistration* ksr = [ksrClass registrationWithProductID:productID_];
-  if (!ksr)
-    return NO;
-
-  registration_ = [ksr retain];
-  return YES;
-}
-
-- (NSString*)appInfoPlistPath {
-  // NSBundle ought to have a way to access this path directly, but it
-  // doesn't.
-  return [[appPath_ stringByAppendingPathComponent:@"Contents"]
-             stringByAppendingPathComponent:@"Info.plist"];
-}
-
-- (NSDictionary*)keystoneParameters {
-  NSNumber* xcType = [NSNumber numberWithInt:kKSPathExistenceChecker];
-  NSNumber* preserveTTToken = [NSNumber numberWithBool:YES];
-  NSString* tagPath = [self appInfoPlistPath];
-
-  NSString* brandKey = kBrandKey;
-  NSString* brandPath = [self brandFilePath];
-
-  if ([brandPath length] == 0) {
-    // Brand path and brand key must be cleared together or ksadmin seems
-    // to throw an error.
-    brandKey = @"";
-  }
-
-  return [NSDictionary dictionaryWithObjectsAndKeys:
-             version_, KSRegistrationVersionKey,
-             xcType, KSRegistrationExistenceCheckerTypeKey,
-             appPath_, KSRegistrationExistenceCheckerStringKey,
-             url_, KSRegistrationServerURLStringKey,
-             preserveTTToken, KSRegistrationPreserveTrustedTesterTokenKey,
-             channel_, KSRegistrationTagKey,
-             tagPath, KSRegistrationTagPathKey,
-             kChannelKey, KSRegistrationTagKeyKey,
-             brandPath, KSRegistrationBrandPathKey,
-             brandKey, KSRegistrationBrandKeyKey,
-             nil];
-}
-
-- (void)registerWithKeystone {
-  [self updateStatus:kAutoupdateRegistering version:nil];
-
-  NSDictionary* parameters = [self keystoneParameters];
-  if (![registration_ registerWithParameters:parameters]) {
-    [self updateStatus:kAutoupdateRegisterFailed version:nil];
-    return;
-  }
-
-  // Upon completion, KSRegistrationDidCompleteNotification will be posted,
-  // and -registrationComplete: will be called.
-
-  // Mark an active RIGHT NOW; don't wait an hour for the first one.
-  [registration_ setActive];
-
-  // Set up hourly activity pings.
-  timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60  // One hour
-                                            target:self
-                                          selector:@selector(markActive:)
-                                          userInfo:registration_
-                                           repeats:YES];
-}
-
-- (void)registrationComplete:(NSNotification*)notification {
-  NSDictionary* userInfo = [notification userInfo];
-  if ([[userInfo objectForKey:KSRegistrationStatusKey] boolValue]) {
-    [self updateStatus:kAutoupdateRegistered version:nil];
-  } else {
-    // Dump registration_?
-    [self updateStatus:kAutoupdateRegisterFailed version:nil];
-  }
-}
-
-- (void)stopTimer {
-  [timer_ invalidate];
-}
-
-- (void)markActive:(NSTimer*)timer {
-  KSRegistration* ksr = [timer userInfo];
-  [ksr setActive];
-}
-
-- (void)checkForUpdate {
-  DCHECK(![self asyncOperationPending]);
-
-  if (!registration_) {
-    [self updateStatus:kAutoupdateCheckFailed version:nil];
-    return;
-  }
-
-  [self updateStatus:kAutoupdateChecking version:nil];
-
-  [registration_ checkForUpdate];
-
-  // Upon completion, KSRegistrationCheckForUpdateNotification will be posted,
-  // and -checkForUpdateComplete: will be called.
-}
-
-- (void)checkForUpdateComplete:(NSNotification*)notification {
-  NSDictionary* userInfo = [notification userInfo];
-
-  if ([[userInfo objectForKey:KSRegistrationUpdateCheckErrorKey] boolValue]) {
-    [self updateStatus:kAutoupdateCheckFailed version:nil];
-  } else if ([[userInfo objectForKey:KSRegistrationStatusKey] boolValue]) {
-    // If an update is known to be available, go straight to
-    // -updateStatus:version:.  It doesn't matter what's currently on disk.
-    NSString* version = [userInfo objectForKey:KSRegistrationVersionKey];
-    [self updateStatus:kAutoupdateAvailable version:version];
-  } else {
-    // If no updates are available, check what's on disk, because an update
-    // may have already been installed.  This check happens on another thread,
-    // and -updateStatus:version: will be called on the main thread when done.
-    [self determineUpdateStatusAsync];
-  }
-}
-
-- (void)installUpdate {
-  DCHECK(![self asyncOperationPending]);
-
-  if (!registration_) {
-    [self updateStatus:kAutoupdateInstallFailed version:nil];
-    return;
-  }
-
-  [self updateStatus:kAutoupdateInstalling version:nil];
-
-  [registration_ startUpdate];
-
-  // Upon completion, KSRegistrationStartUpdateNotification will be posted,
-  // and -installUpdateComplete: will be called.
-}
-
-- (void)installUpdateComplete:(NSNotification*)notification {
-  NSDictionary* userInfo = [notification userInfo];
-
-  if (![[userInfo objectForKey:KSUpdateCheckSuccessfulKey] boolValue] ||
-      ![[userInfo objectForKey:KSUpdateCheckSuccessfullyInstalledKey]
-          intValue]) {
-    [self updateStatus:kAutoupdateInstallFailed version:nil];
-  } else {
-    updateSuccessfullyInstalled_ = YES;
-
-    // Nothing in the notification dictionary reports the version that was
-    // installed.  Figure it out based on what's on disk.
-    [self determineUpdateStatusAsync];
-  }
-}
-
-- (NSString*)currentlyInstalledVersion {
-  NSString* appInfoPlistPath = [self appInfoPlistPath];
-  NSDictionary* infoPlist =
-      [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath];
-  return [infoPlist objectForKey:@"CFBundleShortVersionString"];
-}
-
-// Runs on the main thread.
-- (void)determineUpdateStatusAsync {
-  DCHECK([NSThread isMainThread]);
-
-  PerformBridge::PostPerform(self, @selector(determineUpdateStatus));
-}
-
-// Runs on a thread managed by WorkerPool.
-- (void)determineUpdateStatus {
-  DCHECK(![NSThread isMainThread]);
-
-  NSString* version = [self currentlyInstalledVersion];
-
-  [self performSelectorOnMainThread:@selector(determineUpdateStatusForVersion:)
-                         withObject:version
-                      waitUntilDone:NO];
-}
-
-// Runs on the main thread.
-- (void)determineUpdateStatusForVersion:(NSString*)version {
-  DCHECK([NSThread isMainThread]);
-
-  AutoupdateStatus status;
-  if (updateSuccessfullyInstalled_) {
-    // If an update was successfully installed and this object saw it happen,
-    // then don't even bother comparing versions.
-    status = kAutoupdateInstalled;
-  } else {
-    NSString* currentVersion =
-        [NSString stringWithUTF8String:chrome::kChromeVersion];
-    if (!version) {
-      // If the version on disk could not be determined, assume that
-      // whatever's running is current.
-      version = currentVersion;
-      status = kAutoupdateCurrent;
-    } else if ([version isEqualToString:currentVersion]) {
-      status = kAutoupdateCurrent;
-    } else {
-      // If the version on disk doesn't match what's currently running, an
-      // update must have been applied in the background, without this app's
-      // direct participation.  Leave updateSuccessfullyInstalled_ alone
-      // because there's no direct knowledge of what actually happened.
-      status = kAutoupdateInstalled;
-    }
-  }
-
-  [self updateStatus:status version:version];
-}
-
-- (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version {
-  NSNumber* statusNumber = [NSNumber numberWithInt:status];
-  NSMutableDictionary* dictionary =
-      [NSMutableDictionary dictionaryWithObject:statusNumber
-                                         forKey:kAutoupdateStatusStatus];
-  if (version) {
-    [dictionary setObject:version forKey:kAutoupdateStatusVersion];
-  }
-
-  NSNotification* notification =
-      [NSNotification notificationWithName:kAutoupdateStatusNotification
-                                    object:self
-                                  userInfo:dictionary];
-  recentNotification_.reset([notification retain]);
-
-  [[NSNotificationCenter defaultCenter] postNotification:notification];
-}
-
-- (NSNotification*)recentNotification {
-  return [[recentNotification_ retain] autorelease];
-}
-
-- (AutoupdateStatus)recentStatus {
-  NSDictionary* dictionary = [recentNotification_ userInfo];
-  return static_cast<AutoupdateStatus>(
-      [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
-}
-
-- (BOOL)asyncOperationPending {
-  AutoupdateStatus status = [self recentStatus];
-  return status == kAutoupdateRegistering ||
-         status == kAutoupdateChecking ||
-         status == kAutoupdateInstalling ||
-         status == kAutoupdatePromoting;
-}
-
-- (BOOL)isUserTicket {
-  return [registration_ ticketType] == kKSRegistrationUserTicket;
-}
-
-- (BOOL)isOnReadOnlyFilesystem {
-  const char* appPathC = [appPath_ fileSystemRepresentation];
-  struct statfs statfsBuf;
-
-  if (statfs(appPathC, &statfsBuf) != 0) {
-    PLOG(ERROR) << "statfs";
-    // Be optimistic about the filesystem's writability.
-    return NO;
-  }
-
-  return (statfsBuf.f_flags & MNT_RDONLY) != 0;
-}
-
-- (BOOL)needsPromotion {
-  if (![self isUserTicket] || [self isOnReadOnlyFilesystem]) {
-    return NO;
-  }
-
-  // Check the outermost bundle directory, the main executable path, and the
-  // framework directory.  It may be enough to just look at the outermost
-  // bundle directory, but checking an interior file and directory can be
-  // helpful in case permissions are set differently only on the outermost
-  // directory.  An interior file and directory are both checked because some
-  // file operations, such as Snow Leopard's Finder's copy operation when
-  // authenticating, may actually result in different ownership being applied
-  // to files and directories.
-  NSFileManager* fileManager = [NSFileManager defaultManager];
-  NSString* executablePath = [[NSBundle mainBundle] executablePath];
-  NSString* frameworkPath = [base::mac::MainAppBundle() bundlePath];
-  return ![fileManager isWritableFileAtPath:appPath_] ||
-         ![fileManager isWritableFileAtPath:executablePath] ||
-         ![fileManager isWritableFileAtPath:frameworkPath];
-}
-
-- (BOOL)wantsPromotion {
-  // -needsPromotion checks these too, but this method doesn't necessarily
-  // return NO just becuase -needsPromotion returns NO, so another check is
-  // needed here.
-  if (![self isUserTicket] || [self isOnReadOnlyFilesystem]) {
-    return NO;
-  }
-
-  if ([self needsPromotion]) {
-    return YES;
-  }
-
-  return [appPath_ hasPrefix:@"/Applications/"];
-}
-
-- (void)promoteTicket {
-  if ([self asyncOperationPending] || ![self wantsPromotion]) {
-    // Because there are multiple ways of reaching promoteTicket that might
-    // not lock each other out, it may be possible to arrive here while an
-    // asynchronous operation is pending, or even after promotion has already
-    // occurred.  Just quietly return without doing anything.
-    return;
-  }
-
-  NSString* prompt = l10n_util::GetNSStringFWithFixup(
-      IDS_PROMOTE_AUTHENTICATION_PROMPT,
-      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  scoped_AuthorizationRef authorization(
-      authorization_util::AuthorizationCreateToRunAsRoot(
-          reinterpret_cast<CFStringRef>(prompt)));
-  if (!authorization.get()) {
-    return;
-  }
-
-  [self promoteTicketWithAuthorization:authorization.release() synchronous:NO];
-}
-
-- (void)promoteTicketWithAuthorization:(AuthorizationRef)authorization_arg
-                           synchronous:(BOOL)synchronous {
-  scoped_AuthorizationRef authorization(authorization_arg);
-  authorization_arg = NULL;
-
-  if ([self asyncOperationPending]) {
-    // Starting a synchronous operation while an asynchronous one is pending
-    // could be trouble.
-    return;
-  }
-  if (!synchronous && ![self wantsPromotion]) {
-    // If operating synchronously, the call came from the installer, which
-    // means that a system ticket is required.  Otherwise, only allow
-    // promotion if it's wanted.
-    return;
-  }
-
-  synchronousPromotion_ = synchronous;
-
-  [self updateStatus:kAutoupdatePromoting version:nil];
-
-  // TODO(mark): Remove when able!
-  //
-  // keystone_promote_preflight will copy the current brand information out to
-  // the system level so all users can share the data as part of the ticket
-  // promotion.
-  //
-  // It will also ensure that the Keystone system ticket store is in a usable
-  // state for all users on the system.  Ideally, Keystone's installer or
-  // another part of Keystone would handle this.  The underlying problem is
-  // http://b/2285921, and it causes http://b/2289908, which this workaround
-  // addresses.
-  //
-  // This is run synchronously, which isn't optimal, but
-  // -[KSRegistration promoteWithParameters:authorization:] is currently
-  // synchronous too, and this operation needs to happen before that one.
-  //
-  // TODO(mark): Make asynchronous.  That only makes sense if the promotion
-  // operation itself is asynchronous too.  http://b/2290009.  Hopefully,
-  // the Keystone promotion code will just be changed to do what preflight
-  // now does, and then the preflight script can be removed instead.
-  // However, preflight operation (and promotion) should only be asynchronous
-  // if the synchronous parameter is NO.
-  NSString* preflightPath =
-      [base::mac::MainAppBundle() pathForResource:@"keystone_promote_preflight"
-                                          ofType:@"sh"];
-  const char* preflightPathC = [preflightPath fileSystemRepresentation];
-  const char* userBrandFile = NULL;
-  const char* systemBrandFile = NULL;
-  if (brandFileType_ == kBrandFileTypeUser) {
-    // Running with user level brand file, promote to the system level.
-    userBrandFile = [UserBrandFilePath() fileSystemRepresentation];
-    systemBrandFile = [SystemBrandFilePath() fileSystemRepresentation];
-  }
-  const char* arguments[] = {userBrandFile, systemBrandFile, NULL};
-
-  int exit_status;
-  OSStatus status = authorization_util::ExecuteWithPrivilegesAndWait(
-      authorization,
-      preflightPathC,
-      kAuthorizationFlagDefaults,
-      arguments,
-      NULL,  // pipe
-      &exit_status);
-  if (status != errAuthorizationSuccess) {
-    LOG(ERROR) << "AuthorizationExecuteWithPrivileges preflight: " << status;
-    [self updateStatus:kAutoupdatePromoteFailed version:nil];
-    return;
-  }
-  if (exit_status != 0) {
-    LOG(ERROR) << "keystone_promote_preflight status " << exit_status;
-    [self updateStatus:kAutoupdatePromoteFailed version:nil];
-    return;
-  }
-
-  // Hang on to the AuthorizationRef so that it can be used once promotion is
-  // complete.  Do this before asking Keystone to promote the ticket, because
-  // -promotionComplete: may be called from inside the Keystone promotion
-  // call.
-  authorization_.swap(authorization);
-
-  NSDictionary* parameters = [self keystoneParameters];
-
-  // If the brand file is user level, update parameters to point to the new
-  // system level file during promotion.
-  if (brandFileType_ == kBrandFileTypeUser) {
-    NSMutableDictionary* temp_parameters =
-        [[parameters mutableCopy] autorelease];
-    [temp_parameters setObject:SystemBrandFilePath()
-                        forKey:KSRegistrationBrandPathKey];
-    parameters = temp_parameters;
-  }
-
-  if (![registration_ promoteWithParameters:parameters
-                              authorization:authorization_]) {
-    [self updateStatus:kAutoupdatePromoteFailed version:nil];
-    authorization_.reset();
-    return;
-  }
-
-  // Upon completion, KSRegistrationPromotionDidCompleteNotification will be
-  // posted, and -promotionComplete: will be called.
-}
-
-- (void)promotionComplete:(NSNotification*)notification {
-  NSDictionary* userInfo = [notification userInfo];
-  if ([[userInfo objectForKey:KSRegistrationStatusKey] boolValue]) {
-    if (synchronousPromotion_) {
-      // Short-circuit: if performing a synchronous promotion, the promotion
-      // came from the installer, which already set the permissions properly.
-      // Rather than run a duplicate permission-changing operation, jump
-      // straight to "done."
-      [self changePermissionsForPromotionComplete];
-    } else {
-      [self changePermissionsForPromotionAsync];
-    }
-  } else {
-    authorization_.reset();
-    [self updateStatus:kAutoupdatePromoteFailed version:nil];
-  }
-}
-
-- (void)changePermissionsForPromotionAsync {
-  // NSBundle is not documented as being thread-safe.  Do NSBundle operations
-  // on the main thread before jumping over to a WorkerPool-managed
-  // thread to run the tool.
-  DCHECK([NSThread isMainThread]);
-
-  SEL selector = @selector(changePermissionsForPromotionWithTool:);
-  NSString* toolPath =
-      [base::mac::MainAppBundle() pathForResource:@"keystone_promote_postflight"
-                                          ofType:@"sh"];
-
-  PerformBridge::PostPerform(self, selector, toolPath);
-}
-
-- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath {
-  const char* toolPathC = [toolPath fileSystemRepresentation];
-
-  const char* appPathC = [appPath_ fileSystemRepresentation];
-  const char* arguments[] = {appPathC, NULL};
-
-  int exit_status;
-  OSStatus status = authorization_util::ExecuteWithPrivilegesAndWait(
-      authorization_,
-      toolPathC,
-      kAuthorizationFlagDefaults,
-      arguments,
-      NULL,  // pipe
-      &exit_status);
-  if (status != errAuthorizationSuccess) {
-    LOG(ERROR) << "AuthorizationExecuteWithPrivileges postflight: " << status;
-  } else if (exit_status != 0) {
-    LOG(ERROR) << "keystone_promote_postflight status " << exit_status;
-  }
-
-  SEL selector = @selector(changePermissionsForPromotionComplete);
-  [self performSelectorOnMainThread:selector
-                         withObject:nil
-                      waitUntilDone:NO];
-}
-
-- (void)changePermissionsForPromotionComplete {
-  authorization_.reset();
-
-  [self updateStatus:kAutoupdatePromoted version:nil];
-}
-
-- (void)setAppPath:(NSString*)appPath {
-  if (appPath != appPath_) {
-    [appPath_ release];
-    appPath_ = [appPath copy];
-  }
-}
-
-@end  // @implementation KeystoneGlue
-
-namespace keystone_glue {
-
-bool KeystoneEnabled() {
-  return [KeystoneGlue defaultKeystoneGlue] != nil;
-}
-
-string16 CurrentlyInstalledVersion() {
-  KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
-  NSString* version = [keystoneGlue currentlyInstalledVersion];
-  return base::SysNSStringToUTF16(version);
-}
-
-}  // namespace keystone_glue
diff --git a/chrome/browser/ui/cocoa/keystone_glue_unittest.mm b/chrome/browser/ui/cocoa/keystone_glue_unittest.mm
deleted file mode 100644
index c4a26f4..0000000
--- a/chrome/browser/ui/cocoa/keystone_glue_unittest.mm
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Foundation/Foundation.h>
-#import <objc/objc-class.h>
-
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface FakeGlueRegistration : NSObject
-@end
-
-
-@implementation FakeGlueRegistration
-
-// Send the notifications that a real KeystoneGlue object would send.
-
-- (void)checkForUpdate {
-  NSNumber* yesNumber = [NSNumber numberWithBool:YES];
-  NSString* statusKey = @"Status";
-  NSDictionary* dictionary = [NSDictionary dictionaryWithObject:yesNumber
-                                                         forKey:statusKey];
-  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-  [center postNotificationName:@"KSRegistrationCheckForUpdateNotification"
-                        object:nil
-                      userInfo:dictionary];
-}
-
-- (void)startUpdate {
-  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-  [center postNotificationName:@"KSRegistrationStartUpdateNotification"
-                        object:nil];
-}
-
-@end
-
-
-@interface FakeKeystoneGlue : KeystoneGlue {
- @public
-  BOOL upToDate_;
-  NSString *latestVersion_;
-  BOOL successful_;
-  int installs_;
-}
-
-- (void)fakeAboutWindowCallback:(NSNotification*)notification;
-@end
-
-
-@implementation FakeKeystoneGlue
-
-- (id)init {
-  if ((self = [super init])) {
-    // some lies
-    upToDate_ = YES;
-    latestVersion_ = @"foo bar";
-    successful_ = YES;
-    installs_ = 1010101010;
-
-    // Set up an observer that takes the notification that the About window
-    // listens for.
-    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-    [center addObserver:self
-               selector:@selector(fakeAboutWindowCallback:)
-                   name:kAutoupdateStatusNotification
-                 object:nil];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [super dealloc];
-}
-
-// For mocking
-- (NSDictionary*)infoDictionary {
-  NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
-                                     @"http://foo.bar", @"KSUpdateURL",
-                                     @"com.google.whatever", @"KSProductID",
-                                     @"0.0.0.1", @"KSVersion",
-                                     nil];
-  return dict;
-}
-
-// For mocking
-- (BOOL)loadKeystoneRegistration {
-  return YES;
-}
-
-// Confirms certain things are happy
-- (BOOL)dictReadCorrectly {
-  return ([url_ isEqual:@"http://foo.bar"] &&
-          [productID_ isEqual:@"com.google.whatever"] &&
-          [version_ isEqual:@"0.0.0.1"]);
-}
-
-// Confirms certain things are happy
-- (BOOL)hasATimer {
-  return timer_ ? YES : NO;
-}
-
-- (void)addFakeRegistration {
-  registration_ = [[FakeGlueRegistration alloc] init];
-}
-
-- (void)fakeAboutWindowCallback:(NSNotification*)notification {
-  NSDictionary* dictionary = [notification userInfo];
-  AutoupdateStatus status = static_cast<AutoupdateStatus>(
-      [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
-
-  if (status == kAutoupdateAvailable) {
-    upToDate_ = NO;
-    latestVersion_ = [dictionary objectForKey:kAutoupdateStatusVersion];
-  } else if (status == kAutoupdateInstallFailed) {
-    successful_ = NO;
-    installs_ = 0;
-  }
-}
-
-// Confirm we look like callbacks with nil NSNotifications
-- (BOOL)confirmCallbacks {
-  return (!upToDate_ &&
-          (latestVersion_ == nil) &&
-          !successful_ &&
-          (installs_ == 0));
-}
-
-@end
-
-
-namespace {
-
-class KeystoneGlueTest : public PlatformTest {
-};
-
-// DISABLED because the mocking isn't currently working.
-TEST_F(KeystoneGlueTest, DISABLED_BasicGlobalCreate) {
-  // Allow creation of a KeystoneGlue by mocking out a few calls
-  SEL ids = @selector(infoDictionary);
-  IMP oldInfoImp_ = [[KeystoneGlue class] instanceMethodForSelector:ids];
-  IMP newInfoImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:ids];
-  Method infoMethod_ = class_getInstanceMethod([KeystoneGlue class], ids);
-  method_setImplementation(infoMethod_, newInfoImp_);
-
-  SEL lks = @selector(loadKeystoneRegistration);
-  IMP oldLoadImp_ = [[KeystoneGlue class] instanceMethodForSelector:lks];
-  IMP newLoadImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:lks];
-  Method loadMethod_ = class_getInstanceMethod([KeystoneGlue class], lks);
-  method_setImplementation(loadMethod_, newLoadImp_);
-
-  KeystoneGlue *glue = [KeystoneGlue defaultKeystoneGlue];
-  ASSERT_TRUE(glue);
-
-  // Fix back up the class to the way we found it.
-  method_setImplementation(infoMethod_, oldInfoImp_);
-  method_setImplementation(loadMethod_, oldLoadImp_);
-}
-
-// DISABLED because the mocking isn't currently working.
-TEST_F(KeystoneGlueTest, DISABLED_BasicUse) {
-  FakeKeystoneGlue* glue = [[[FakeKeystoneGlue alloc] init] autorelease];
-  [glue loadParameters];
-  ASSERT_TRUE([glue dictReadCorrectly]);
-
-  // Likely returns NO in the unit test, but call it anyway to make
-  // sure it doesn't crash.
-  [glue loadKeystoneRegistration];
-
-  // Confirm we start up an active timer
-  [glue registerWithKeystone];
-  ASSERT_TRUE([glue hasATimer]);
-  [glue stopTimer];
-
-  // Brief exercise of callbacks
-  [glue addFakeRegistration];
-  [glue checkForUpdate];
-  [glue installUpdate];
-  ASSERT_TRUE([glue confirmCallbacks]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/keystone_infobar.mm b/chrome/browser/ui/cocoa/keystone_infobar.mm
index 09c0d8c..e71a401 100644
--- a/chrome/browser/ui/cocoa/keystone_infobar.mm
+++ b/chrome/browser/ui/cocoa/keystone_infobar.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,11 +8,10 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/task.h"
+#import "chrome/browser/cocoa/keystone_glue.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -21,85 +20,40 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
-#import "chrome/browser/ui/cocoa/keystone_glue.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class SkBitmap;
 
 namespace {
 
+// KeystonePromotionInfoBarDelegate -------------------------------------------
+
 class KeystonePromotionInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
-  KeystonePromotionInfoBarDelegate(TabContents* tab_contents)
-      : ConfirmInfoBarDelegate(tab_contents),
-        profile_(tab_contents->profile()),
-        can_expire_(false),
-        ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
-    const int kCanExpireOnNavigationAfterMilliseconds = 8 * 1000;
-    MessageLoop::current()->PostDelayedTask(
-        FROM_HERE,
-        method_factory_.NewRunnableMethod(
-            &KeystonePromotionInfoBarDelegate::SetCanExpire),
-        kCanExpireOnNavigationAfterMilliseconds);
-  }
-
-  virtual ~KeystonePromotionInfoBarDelegate() {}
-
-  // Inherited from InfoBarDelegate and overridden.
-
-  virtual bool ShouldExpire(
-    const NavigationController::LoadCommittedDetails& details) {
-    return can_expire_;
-  }
-
-  virtual void InfoBarClosed() {
-    delete this;
-  }
-
-  // Inherited from AlertInfoBarDelegate and overridden.
-
-  virtual string16 GetMessageText() const {
-    return l10n_util::GetStringFUTF16(IDS_PROMOTE_INFOBAR_TEXT,
-        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  }
-
-  virtual SkBitmap* GetIcon() const {
-    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
-        IDR_PRODUCT_ICON_32);
-  }
-
-  // Inherited from ConfirmInfoBarDelegate and overridden.
-
-  virtual int GetButtons() const {
-    return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
-  }
-
-  virtual string16 GetButtonLabel(InfoBarButton button) const {
-    return button == BUTTON_OK ?
-        l10n_util::GetStringUTF16(IDS_PROMOTE_INFOBAR_PROMOTE_BUTTON) :
-        l10n_util::GetStringUTF16(IDS_PROMOTE_INFOBAR_DONT_ASK_BUTTON);
-  }
-
-  virtual bool Accept() {
-    [[KeystoneGlue defaultKeystoneGlue] promoteTicket];
-    return true;
-  }
-
-  virtual bool Cancel() {
-    profile_->GetPrefs()->SetBoolean(prefs::kShowUpdatePromotionInfoBar, false);
-    return true;
-  }
+  explicit KeystonePromotionInfoBarDelegate(TabContents* tab_contents);
 
  private:
+  virtual ~KeystonePromotionInfoBarDelegate();
+
   // Sets this info bar to be able to expire.  Called a predetermined amount
   // of time after this object is created.
-  void SetCanExpire() {
-    can_expire_ = true;
-  }
+  void SetCanExpire() { can_expire_ = true; }
+
+  // ConfirmInfoBarDelegate
+  virtual bool ShouldExpire(
+      const NavigationController::LoadCommittedDetails& details) const;
+  virtual void InfoBarClosed();
+  virtual SkBitmap* GetIcon() const;
+  virtual string16 GetMessageText() const;
+  virtual string16 GetButtonLabel(InfoBarButton button) const;
+  virtual bool Accept();
+  virtual bool Cancel();
 
   // The TabContents' profile.
   Profile* profile_;  // weak
@@ -113,8 +67,62 @@
   DISALLOW_COPY_AND_ASSIGN(KeystonePromotionInfoBarDelegate);
 };
 
+KeystonePromotionInfoBarDelegate::KeystonePromotionInfoBarDelegate(
+    TabContents* tab_contents)
+    : ConfirmInfoBarDelegate(tab_contents),
+      profile_(tab_contents->profile()),
+      can_expire_(false),
+      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+  const int kCanExpireOnNavigationAfterMilliseconds = 8 * 1000;
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &KeystonePromotionInfoBarDelegate::SetCanExpire),
+      kCanExpireOnNavigationAfterMilliseconds);
+}
+
+KeystonePromotionInfoBarDelegate::~KeystonePromotionInfoBarDelegate() {
+}
+
+bool KeystonePromotionInfoBarDelegate::ShouldExpire(
+    const NavigationController::LoadCommittedDetails& details) const {
+  return can_expire_;
+}
+
+void KeystonePromotionInfoBarDelegate::InfoBarClosed() {
+  delete this;
+}
+
+SkBitmap* KeystonePromotionInfoBarDelegate::GetIcon() const {
+  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_PRODUCT_ICON_32);
+}
+
+string16 KeystonePromotionInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_PROMOTE_INFOBAR_TEXT,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+}
+
+string16 KeystonePromotionInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_PROMOTE_INFOBAR_PROMOTE_BUTTON : IDS_PROMOTE_INFOBAR_DONT_ASK_BUTTON);
+}
+
+bool KeystonePromotionInfoBarDelegate::Accept() {
+  [[KeystoneGlue defaultKeystoneGlue] promoteTicket];
+  return true;
+}
+
+bool KeystonePromotionInfoBarDelegate::Cancel() {
+  profile_->GetPrefs()->SetBoolean(prefs::kShowUpdatePromotionInfoBar, false);
+  return true;
+}
+
 }  // namespace
 
+
+// KeystonePromotionInfoBar ---------------------------------------------------
+
 @interface KeystonePromotionInfoBar : NSObject
 - (void)checkAndShowInfoBarForProfile:(Profile*)profile;
 - (void)updateStatus:(NSNotification*)notification;
@@ -187,7 +195,7 @@
 
       // Only show if no other info bars are showing, because that's how the
       // default browser info bar works.
-      if (tabContents && tabContents->infobar_delegate_count() == 0) {
+      if (tabContents && tabContents->infobar_count() == 0) {
         tabContents->AddInfoBar(
             new KeystonePromotionInfoBarDelegate(tabContents));
       }
diff --git a/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h b/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h
deleted file mode 100644
index 6acc829..0000000
--- a/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "app/table_model_observer.h"
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_ptr.h"
-#include "base/string16.h"
-#include "chrome/browser/search_engines/edit_search_engine_controller.h"
-#include "chrome/browser/search_engines/keyword_editor_controller.h"
-#include "chrome/browser/search_engines/template_url_model_observer.h"
-#include "chrome/browser/ui/cocoa/table_row_nsimage_cache.h"
-
-class EditSearchEngineControllerDelegate;
-@class KeywordEditorCocoaController;
-class Profile;
-@class WindowSizeAutosaver;
-
-// Very thin bridge that simply pushes notifications from C++ to ObjC.
-class KeywordEditorModelObserver : public TemplateURLModelObserver,
-                                   public EditSearchEngineControllerDelegate,
-                                   public TableModelObserver,
-                                   public TableRowNSImageCache::Table {
- public:
-  explicit KeywordEditorModelObserver(KeywordEditorCocoaController* controller);
-  virtual ~KeywordEditorModelObserver();
-
-  // Notification that the template url model has changed in some way.
-  virtual void OnTemplateURLModelChanged();
-
-  // Invoked from the EditSearchEngineController when the user accepts the
-  // edits. NOTE: |template_url| is the value supplied to
-  // EditSearchEngineController's constructor, and may be NULL. A NULL value
-  // indicates a new TemplateURL should be created rather than modifying an
-  // existing TemplateURL.
-  virtual void OnEditedKeyword(const TemplateURL* template_url,
-                               const string16& title,
-                               const string16& keyword,
-                               const std::string& url);
-
-  // TableModelObserver overrides. Invalidate icon cache.
-  virtual void OnModelChanged();
-  virtual void OnItemsChanged(int start, int length);
-  virtual void OnItemsAdded(int start, int length);
-  virtual void OnItemsRemoved(int start, int length);
-
-  // TableRowNSImageCache::Table
-  virtual int RowCount() const;
-  virtual SkBitmap GetIcon(int row) const;
-
-  // Lazily converts the image at the given row and caches it in |icon_cache_|.
-  NSImage* GetImageForRow(int row);
-
- private:
-  KeywordEditorCocoaController* controller_;
-
-  TableRowNSImageCache icon_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeywordEditorModelObserver);
-};
-
-// This controller manages a window with a table view of search engines. It
-// acts as |tableView_|'s data source and delegate, feeding it data from the
-// KeywordEditorController's |table_model()|.
-
-@interface KeywordEditorCocoaController : NSWindowController
-                                          <NSWindowDelegate,
-                                           NSTableViewDataSource,
-                                           NSTableViewDelegate> {
-  IBOutlet NSTableView* tableView_;
-  IBOutlet NSButton* addButton_;
-  IBOutlet NSButton* removeButton_;
-  IBOutlet NSButton* makeDefaultButton_;
-
-  scoped_nsobject<NSTextFieldCell> groupCell_;
-
-  Profile* profile_;  // weak
-  scoped_ptr<KeywordEditorController> controller_;
-  scoped_ptr<KeywordEditorModelObserver> observer_;
-
-  scoped_nsobject<WindowSizeAutosaver> sizeSaver_;
-}
-@property (nonatomic, readonly) KeywordEditorController* controller;
-
-// Show the keyword editor associated with the given profile (or the
-// original profile if this is an incognito profile).  If no keyword
-// editor exists for this profile, create one and show it.  Any
-// resulting editor releases itself when closed.
-+ (void)showKeywordEditor:(Profile*)profile;
-
-- (KeywordEditorController*)controller;
-
-// Message forwarded by KeywordEditorModelObserver.
-- (void)modelChanged;
-
-- (IBAction)addKeyword:(id)sender;
-- (IBAction)deleteKeyword:(id)sender;
-- (IBAction)makeDefault:(id)sender;
-
-@end
-
-@interface KeywordEditorCocoaController (TestingAPI)
-
-// Instances of this class are managed, use +showKeywordEditor:.
-- (id)initWithProfile:(Profile*)profile;
-
-// Returns a reference to the shared instance for the given profile,
-// or nil if there is none.
-+ (KeywordEditorCocoaController*)sharedInstanceForProfile:(Profile*)profile;
-
-// Converts a row index in our table view (which has group header rows) into
-// one in the |controller_|'s model, which does not have them.
-- (int)indexInModelForRow:(NSUInteger)row;
-
-@end
diff --git a/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.mm b/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.mm
deleted file mode 100644
index 2ae0fa6..0000000
--- a/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.mm
+++ /dev/null
@@ -1,425 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h"
-
-#import "base/mac/mac_util.h"
-#include "base/lazy_instance.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/search_engines/template_url_table_model.h"
-#import "chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.h"
-#import "chrome/browser/ui/cocoa/window_size_autosaver.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-const CGFloat kButtonBarHeight = 35.0;
-
-}  // namespace
-
-@interface KeywordEditorCocoaController (Private)
-- (void)adjustEditingButtons;
-- (void)editKeyword:(id)sender;
-- (int)indexInModelForRow:(NSUInteger)row;
-@end
-
-// KeywordEditorModelObserver -------------------------------------------------
-
-KeywordEditorModelObserver::KeywordEditorModelObserver(
-    KeywordEditorCocoaController* controller)
-    : controller_(controller),
-      icon_cache_(this) {
-}
-
-KeywordEditorModelObserver::~KeywordEditorModelObserver() {
-}
-
-// Notification that the template url model has changed in some way.
-void KeywordEditorModelObserver::OnTemplateURLModelChanged() {
-  [controller_ modelChanged];
-}
-
-void KeywordEditorModelObserver::OnEditedKeyword(
-    const TemplateURL* template_url,
-    const string16& title,
-    const string16& keyword,
-    const std::string& url) {
-  KeywordEditorController* controller = [controller_ controller];
-  if (template_url) {
-    controller->ModifyTemplateURL(template_url, title, keyword, url);
-  } else {
-    controller->AddTemplateURL(title, keyword, url);
-  }
-}
-
-void KeywordEditorModelObserver::OnModelChanged() {
-  icon_cache_.OnModelChanged();
-  [controller_ modelChanged];
-}
-
-void KeywordEditorModelObserver::OnItemsChanged(int start, int length) {
-  icon_cache_.OnItemsChanged(start, length);
-  [controller_ modelChanged];
-}
-
-void KeywordEditorModelObserver::OnItemsAdded(int start, int length) {
-  icon_cache_.OnItemsAdded(start, length);
-  [controller_ modelChanged];
-}
-
-void KeywordEditorModelObserver::OnItemsRemoved(int start, int length) {
-  icon_cache_.OnItemsRemoved(start, length);
-  [controller_ modelChanged];
-}
-
-int KeywordEditorModelObserver::RowCount() const {
-  return [controller_ controller]->table_model()->RowCount();
-}
-
-SkBitmap KeywordEditorModelObserver::GetIcon(int row) const {
-  return [controller_ controller]->table_model()->GetIcon(row);
-}
-
-NSImage* KeywordEditorModelObserver::GetImageForRow(int row) {
-  return icon_cache_.GetImageForRow(row);
-}
-
-// KeywordEditorCocoaController -----------------------------------------------
-
-namespace {
-
-typedef std::map<Profile*,KeywordEditorCocoaController*> ProfileControllerMap;
-
-static base::LazyInstance<ProfileControllerMap> g_profile_controller_map(
-    base::LINKER_INITIALIZED);
-
-}  // namespace
-
-@implementation KeywordEditorCocoaController
-
-+ (KeywordEditorCocoaController*)sharedInstanceForProfile:(Profile*)profile {
-  ProfileControllerMap* map = g_profile_controller_map.Pointer();
-  DCHECK(map != NULL);
-  ProfileControllerMap::iterator it = map->find(profile);
-  if (it != map->end()) {
-    return it->second;
-  }
-  return nil;
-}
-
-// TODO(shess): The Windows code watches a single global window which
-// is not distinguished by profile.  This code could distinguish by
-// profile by checking the controller's class and profile.
-+ (void)showKeywordEditor:(Profile*)profile {
-  // http://crbug.com/23359 describes a case where this panel is
-  // opened from an incognito window, which can leave the panel
-  // holding onto a stale profile.  Since the same panel is used
-  // either way, arrange to use the original profile instead.
-  profile = profile->GetOriginalProfile();
-
-  ProfileControllerMap* map = g_profile_controller_map.Pointer();
-  DCHECK(map != NULL);
-  ProfileControllerMap::iterator it = map->find(profile);
-  if (it == map->end()) {
-    // Since we don't currently support multiple profiles, this class
-    // has not been tested against them, so document that assumption.
-    DCHECK_EQ(map->size(), 0U);
-
-    KeywordEditorCocoaController* controller =
-        [[self alloc] initWithProfile:profile];
-    it = map->insert(std::make_pair(profile, controller)).first;
-  }
-
-  [it->second showWindow:nil];
-}
-
-- (id)initWithProfile:(Profile*)profile {
-  DCHECK(profile);
-  NSString* nibpath = [base::mac::MainAppBundle()
-                        pathForResource:@"KeywordEditor"
-                                 ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    profile_ = profile;
-    controller_.reset(new KeywordEditorController(profile_));
-    observer_.reset(new KeywordEditorModelObserver(self));
-    controller_->table_model()->SetObserver(observer_.get());
-    controller_->url_model()->AddObserver(observer_.get());
-    groupCell_.reset([[NSTextFieldCell alloc] init]);
-
-    if (g_browser_process && g_browser_process->local_state()) {
-      sizeSaver_.reset([[WindowSizeAutosaver alloc]
-          initWithWindow:[self window]
-             prefService:g_browser_process->local_state()
-                    path:prefs::kKeywordEditorWindowPlacement]);
-    }
-  }
-  return self;
-}
-
-- (void)dealloc {
-  controller_->table_model()->SetObserver(NULL);
-  controller_->url_model()->RemoveObserver(observer_.get());
-  [tableView_ setDataSource:nil];
-  observer_.reset();
-  [super dealloc];
-}
-
-- (void)awakeFromNib {
-  // Make sure the button fits its label, but keep it the same height as the
-  // other two buttons.
-  [GTMUILocalizerAndLayoutTweaker sizeToFitView:makeDefaultButton_];
-  NSSize size = [makeDefaultButton_ frame].size;
-  size.height = NSHeight([addButton_ frame]);
-  [makeDefaultButton_ setFrameSize:size];
-
-  [[self window] setAutorecalculatesContentBorderThickness:NO
-                                                   forEdge:NSMinYEdge];
-  [[self window] setContentBorderThickness:kButtonBarHeight
-                                   forEdge:NSMinYEdge];
-
-  [self adjustEditingButtons];
-  [tableView_ setDoubleAction:@selector(editKeyword:)];
-  [tableView_ setTarget:self];
-}
-
-// When the window closes, clean ourselves up.
-- (void)windowWillClose:(NSNotification*)notif {
-  [self autorelease];
-
-  ProfileControllerMap* map = g_profile_controller_map.Pointer();
-  ProfileControllerMap::iterator it = map->find(profile_);
-  // It should not be possible for this to be missing.
-  // TODO(shess): Except that the unit test reaches in directly.
-  // Consider circling around and refactoring that.
-  //DCHECK(it != map->end());
-  if (it != map->end()) {
-    map->erase(it);
-  }
-}
-
-- (void)modelChanged {
-  [tableView_ reloadData];
-  [self adjustEditingButtons];
-}
-
-- (KeywordEditorController*)controller {
-  return controller_.get();
-}
-
-- (void)sheetDidEnd:(NSWindow*)sheet
-         returnCode:(NSInteger)code
-            context:(void*)context {
-  [sheet orderOut:self];
-}
-
-- (IBAction)addKeyword:(id)sender {
-  // The controller will release itself when the window closes.
-  EditSearchEngineCocoaController* editor =
-      [[EditSearchEngineCocoaController alloc] initWithProfile:profile_
-                                                      delegate:observer_.get()
-                                                   templateURL:NULL];
-  [NSApp beginSheet:[editor window]
-     modalForWindow:[self window]
-      modalDelegate:self
-     didEndSelector:@selector(sheetDidEnd:returnCode:context:)
-        contextInfo:NULL];
-}
-
-- (void)editKeyword:(id)sender {
-  const NSInteger clickedRow = [tableView_ clickedRow];
-  if (clickedRow < 0 || [self tableView:tableView_ isGroupRow:clickedRow])
-    return;
-  const TemplateURL* url = controller_->GetTemplateURL(
-      [self indexInModelForRow:clickedRow]);
-  // The controller will release itself when the window closes.
-  EditSearchEngineCocoaController* editor =
-      [[EditSearchEngineCocoaController alloc] initWithProfile:profile_
-                                                      delegate:observer_.get()
-                                                   templateURL:url];
-  [NSApp beginSheet:[editor window]
-     modalForWindow:[self window]
-      modalDelegate:self
-     didEndSelector:@selector(sheetDidEnd:returnCode:context:)
-        contextInfo:NULL];
-}
-
-- (IBAction)deleteKeyword:(id)sender {
-  NSIndexSet* selection = [tableView_ selectedRowIndexes];
-  DCHECK_GT([selection count], 0U);
-  NSUInteger index = [selection lastIndex];
-  while (index != NSNotFound) {
-    controller_->RemoveTemplateURL([self indexInModelForRow:index]);
-    index = [selection indexLessThanIndex:index];
-  }
-}
-
-- (IBAction)makeDefault:(id)sender {
-  NSIndexSet* selection = [tableView_ selectedRowIndexes];
-  DCHECK_EQ([selection count], 1U);
-  int row = [self indexInModelForRow:[selection firstIndex]];
-  controller_->MakeDefaultTemplateURL(row);
-}
-
-// Called when the user hits the escape key. Closes the window.
-- (void)cancel:(id)sender {
-  [[self window] performClose:self];
-}
-
-// Table View Data Source -----------------------------------------------------
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView*)table {
-  int rowCount = controller_->table_model()->RowCount();
-  int numGroups = controller_->table_model()->GetGroups().size();
-  if ([self tableView:table isGroupRow:rowCount + numGroups - 1]) {
-    // Don't show a group header with no rows underneath it.
-    --numGroups;
-  }
-  return rowCount + numGroups;
-}
-
-- (id)tableView:(NSTableView*)tv
-    objectValueForTableColumn:(NSTableColumn*)tableColumn
-                          row:(NSInteger)row {
-  if ([self tableView:tv isGroupRow:row]) {
-    DCHECK(!tableColumn);
-    TableModel::Groups groups = controller_->table_model()->GetGroups();
-    if (row == 0) {
-      return base::SysUTF16ToNSString(groups[0].title);
-    } else {
-      return base::SysUTF16ToNSString(groups[1].title);
-    }
-  }
-
-  NSString* identifier = [tableColumn identifier];
-  if ([identifier isEqualToString:@"name"]) {
-    // The name column is an NSButtonCell so we can have text and image in the
-    // same cell. As such, the "object value" for a button cell is either on
-    // or off, so we always return off so we don't act like a button.
-    return [NSNumber numberWithInt:NSOffState];
-  }
-  if ([identifier isEqualToString:@"keyword"]) {
-    // The keyword object value is a normal string.
-    int index = [self indexInModelForRow:row];
-    int columnID = IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN;
-    string16 text = controller_->table_model()->GetText(index, columnID);
-    return base::SysUTF16ToNSString(text);
-  }
-
-  // And we shouldn't have any other columns...
-  NOTREACHED();
-  return nil;
-}
-
-// Table View Delegate --------------------------------------------------------
-
-// When the selection in the table view changes, we need to adjust buttons.
-- (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
-  [self adjustEditingButtons];
-}
-
-// Disallow selection of the group header rows.
-- (BOOL)tableView:(NSTableView*)table shouldSelectRow:(NSInteger)row {
-  return ![self tableView:table isGroupRow:row];
-}
-
-- (BOOL)tableView:(NSTableView*)table isGroupRow:(NSInteger)row {
-  int otherGroupRow =
-      controller_->table_model()->last_search_engine_index() + 1;
-  return (row == 0 || row == otherGroupRow);
-}
-
-- (NSCell*)tableView:(NSTableView*)tableView
-    dataCellForTableColumn:(NSTableColumn*)tableColumn
-                       row:(NSInteger)row {
-  static const CGFloat kCellFontSize = 12.0;
-
-  // Check to see if we are a grouped row.
-  if ([self tableView:tableView isGroupRow:row]) {
-    DCHECK(!tableColumn);  // This would violate the group row contract.
-    return groupCell_.get();
-  }
-
-  NSCell* cell = [tableColumn dataCellForRow:row];
-  int offsetRow = [self indexInModelForRow:row];
-
-  // Set the favicon and title for the search engine in the name column.
-  if ([[tableColumn identifier] isEqualToString:@"name"]) {
-    DCHECK([cell isKindOfClass:[NSButtonCell class]]);
-    NSButtonCell* buttonCell = static_cast<NSButtonCell*>(cell);
-    string16 title = controller_->table_model()->GetText(offsetRow,
-        IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN);
-    [buttonCell setTitle:base::SysUTF16ToNSString(title)];
-    [buttonCell setImage:observer_->GetImageForRow(offsetRow)];
-    [buttonCell setRefusesFirstResponder:YES];  // Don't push in like a button.
-    [buttonCell setHighlightsBy:NSNoCellMask];
-  }
-
-  // The default search engine should be in bold font.
-  const TemplateURL* defaultEngine =
-      controller_->url_model()->GetDefaultSearchProvider();
-  int rowIndex = controller_->table_model()->IndexOfTemplateURL(defaultEngine);
-  if (rowIndex == offsetRow) {
-    [cell setFont:[NSFont boldSystemFontOfSize:kCellFontSize]];
-  } else {
-    [cell setFont:[NSFont systemFontOfSize:kCellFontSize]];
-  }
-  return cell;
-}
-
-// Private --------------------------------------------------------------------
-
-// This function appropriately sets the enabled states on the table's editing
-// buttons.
-- (void)adjustEditingButtons {
-  NSIndexSet* selection = [tableView_ selectedRowIndexes];
-  BOOL canRemove = ([selection count] > 0);
-  NSUInteger index = [selection firstIndex];
-
-  // Delete button.
-  while (canRemove && index != NSNotFound) {
-    int modelIndex = [self indexInModelForRow:index];
-    const TemplateURL& url =
-        controller_->table_model()->GetTemplateURL(modelIndex);
-    if (!controller_->CanRemove(&url))
-      canRemove = NO;
-    index = [selection indexGreaterThanIndex:index];
-  }
-  [removeButton_ setEnabled:canRemove];
-
-  // Make default button.
-  if ([selection count] != 1) {
-    [makeDefaultButton_ setEnabled:NO];
-  } else {
-    int row = [self indexInModelForRow:[selection firstIndex]];
-    const TemplateURL& url =
-        controller_->table_model()->GetTemplateURL(row);
-    [makeDefaultButton_ setEnabled:controller_->CanMakeDefault(&url)];
-  }
-}
-
-// This converts a row index in our table view to an index in the model by
-// computing the group offsets.
-- (int)indexInModelForRow:(NSUInteger)row {
-  DCHECK_GT(row, 0U);
-  unsigned otherGroupId =
-      controller_->table_model()->last_search_engine_index() + 1;
-  DCHECK_NE(row, otherGroupId);
-  if (row >= otherGroupId) {
-    return row - 2;  // Other group.
-  } else {
-    return row - 1;  // Default group.
-  }
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller_unittest.mm
deleted file mode 100644
index eb5c264..0000000
--- a/chrome/browser/ui/cocoa/keyword_editor_cocoa_controller_unittest.mm
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface FakeKeywordEditorController : KeywordEditorCocoaController {
- @public
-  BOOL modelChanged_;
-}
-- (void)modelChanged;
-- (BOOL)hasModelChanged;
-- (KeywordEditorModelObserver*)observer;
-@end
-
-@implementation FakeKeywordEditorController
-
-- (void)modelChanged {
-  modelChanged_ = YES;
-}
-
-- (BOOL)hasModelChanged {
-  return modelChanged_;
-}
-
-- (KeywordEditorModelObserver*)observer {
-  return observer_.get();
-}
-
-- (NSTableView*)tableView {
-  return tableView_;
-}
-
-@end
-
-// TODO(rsesek): Figure out a good way to test this class (crbug.com/21640).
-
-namespace {
-
-class KeywordEditorCocoaControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    TestingProfile* profile =
-        static_cast<TestingProfile*>(browser_helper_.profile());
-    profile->CreateTemplateURLModel();
-
-    controller_ =
-        [[FakeKeywordEditorController alloc] initWithProfile:profile];
-  }
-
-  virtual void TearDown() {
-    // Force the window to load so we hit |-awakeFromNib| to register as the
-    // window's delegate so that the controller can clean itself up in
-    // |-windowWillClose:|.
-    ASSERT_TRUE([controller_ window]);
-
-    [controller_ close];
-    CocoaTest::TearDown();
-  }
-
-  // Helper to count the keyword editors.
-  NSUInteger CountKeywordEditors() {
-    base::mac::ScopedNSAutoreleasePool pool;
-    NSUInteger count = 0;
-    for (NSWindow* window in [NSApp windows]) {
-      id controller = [window windowController];
-      if ([controller isKindOfClass:[KeywordEditorCocoaController class]]) {
-        ++count;
-      }
-    }
-    return count;
-  }
-
-  BrowserTestHelper browser_helper_;
-  FakeKeywordEditorController* controller_;
-};
-
-TEST_F(KeywordEditorCocoaControllerTest, TestModelChanged) {
-  EXPECT_FALSE([controller_ hasModelChanged]);
-  KeywordEditorModelObserver* observer = [controller_ observer];
-  observer->OnTemplateURLModelChanged();
-  EXPECT_TRUE([controller_ hasModelChanged]);
-}
-
-// Test that +showKeywordEditor brings up the existing editor and
-// creates one if needed.
-TEST_F(KeywordEditorCocoaControllerTest, ShowKeywordEditor) {
-  // No outstanding editors.
-  Profile* profile(browser_helper_.profile());
-  KeywordEditorCocoaController* sharedInstance =
-      [KeywordEditorCocoaController sharedInstanceForProfile:profile];
-  EXPECT_TRUE(nil == sharedInstance);
-  EXPECT_EQ(CountKeywordEditors(), 0U);
-
-  const NSUInteger initial_window_count([[NSApp windows] count]);
-
-  // The window unwinds using -autorelease, so we need to introduce an
-  // autorelease pool to really test whether it went away or not.
-  {
-    base::mac::ScopedNSAutoreleasePool pool;
-
-    // +showKeywordEditor: creates a new controller.
-    [KeywordEditorCocoaController showKeywordEditor:profile];
-    sharedInstance =
-        [KeywordEditorCocoaController sharedInstanceForProfile:profile];
-    EXPECT_TRUE(sharedInstance);
-    EXPECT_EQ(CountKeywordEditors(), 1U);
-
-    // Another call doesn't create another controller.
-    [KeywordEditorCocoaController showKeywordEditor:profile];
-    EXPECT_TRUE(sharedInstance ==
-        [KeywordEditorCocoaController sharedInstanceForProfile:profile]);
-    EXPECT_EQ(CountKeywordEditors(), 1U);
-
-    [sharedInstance close];
-  }
-
-  // No outstanding editors.
-  sharedInstance =
-      [KeywordEditorCocoaController sharedInstanceForProfile:profile];
-  EXPECT_TRUE(nil == sharedInstance);
-  EXPECT_EQ(CountKeywordEditors(), 0U);
-
-  // Windows we created should be gone.
-  EXPECT_EQ([[NSApp windows] count], initial_window_count);
-
-  // Get a new editor, should be different from the previous one.
-  [KeywordEditorCocoaController showKeywordEditor:profile];
-  KeywordEditorCocoaController* newSharedInstance =
-      [KeywordEditorCocoaController sharedInstanceForProfile:profile];
-  EXPECT_TRUE(sharedInstance != newSharedInstance);
-  EXPECT_EQ(CountKeywordEditors(), 1U);
-  [newSharedInstance close];
-}
-
-TEST_F(KeywordEditorCocoaControllerTest, IndexInModelForRowMixed) {
-  [controller_ window];  // Force |-awakeFromNib|.
-  TemplateURLModel* template_model = [controller_ controller]->url_model();
-
-  // Add a default engine.
-  TemplateURL* t_url = new TemplateURL();
-  t_url->SetURL("http://test1/{searchTerms}", 0, 0);
-  t_url->set_keyword(L"test1");
-  t_url->set_short_name(L"Test1");
-  t_url->set_show_in_default_list(true);
-  template_model->Add(t_url);
-
-  // Add a non-default engine.
-  t_url = new TemplateURL();
-  t_url->SetURL("http://test2/{searchTerms}", 0, 0);
-  t_url->set_keyword(L"test2");
-  t_url->set_short_name(L"Test2");
-  t_url->set_show_in_default_list(false);
-  template_model->Add(t_url);
-
-  // Two headers with a single row underneath each.
-  NSTableView* table = [controller_ tableView];
-  [table reloadData];
-  ASSERT_EQ(4, [[controller_ tableView] numberOfRows]);
-
-  // Index 0 is the group header, index 1 should be the first engine.
-  ASSERT_EQ(0, [controller_ indexInModelForRow:1]);
-
-  // Index 2 should be the group header, so index 3 should be the non-default
-  // engine.
-  ASSERT_EQ(1, [controller_ indexInModelForRow:3]);
-
-  ASSERT_TRUE([controller_ tableView:table isGroupRow:0]);
-  ASSERT_FALSE([controller_ tableView:table isGroupRow:1]);
-  ASSERT_TRUE([controller_ tableView:table isGroupRow:2]);
-  ASSERT_FALSE([controller_ tableView:table isGroupRow:3]);
-
-  ASSERT_FALSE([controller_ tableView:table shouldSelectRow:0]);
-  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:1]);
-  ASSERT_FALSE([controller_ tableView:table shouldSelectRow:2]);
-  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:3]);
-}
-
-TEST_F(KeywordEditorCocoaControllerTest, IndexInModelForDefault) {
-  [controller_ window];  // Force |-awakeFromNib|.
-  TemplateURLModel* template_model = [controller_ controller]->url_model();
-
-  // Add 2 default engines.
-  TemplateURL* t_url = new TemplateURL();
-  t_url->SetURL("http://test1/{searchTerms}", 0, 0);
-  t_url->set_keyword(L"test1");
-  t_url->set_short_name(L"Test1");
-  t_url->set_show_in_default_list(true);
-  template_model->Add(t_url);
-
-  t_url = new TemplateURL();
-  t_url->SetURL("http://test2/{searchTerms}", 0, 0);
-  t_url->set_keyword(L"test2");
-  t_url->set_short_name(L"Test2");
-  t_url->set_show_in_default_list(true);
-  template_model->Add(t_url);
-
-  // One header and two rows.
-  NSTableView* table = [controller_ tableView];
-  [table reloadData];
-  ASSERT_EQ(3, [[controller_ tableView] numberOfRows]);
-
-  // Index 0 is the group header, index 1 should be the first engine.
-  ASSERT_EQ(0, [controller_ indexInModelForRow:1]);
-  ASSERT_EQ(1, [controller_ indexInModelForRow:2]);
-
-  ASSERT_TRUE([controller_ tableView:table isGroupRow:0]);
-  ASSERT_FALSE([controller_ tableView:table isGroupRow:1]);
-  ASSERT_FALSE([controller_ tableView:table isGroupRow:2]);
-
-  ASSERT_FALSE([controller_ tableView:table shouldSelectRow:0]);
-  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:1]);
-  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:2]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/location_bar/OWNERS b/chrome/browser/ui/cocoa/location_bar/OWNERS
new file mode 100644
index 0000000..37b85af
--- /dev/null
+++ b/chrome/browser/ui/cocoa/location_bar/OWNERS
@@ -0,0 +1,3 @@
+isherman@chromium.org
+rohitrao@chromium.org
+shess@chromium.org
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
index fa8bd42..c55173e 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
@@ -117,7 +117,7 @@
   scoped_nsobject<NSMutableArray> currentToolTips_;
 }
 
-@property (nonatomic) AutocompleteTextFieldObserver* observer;
+@property(nonatomic) AutocompleteTextFieldObserver* observer;
 
 // Convenience method to return the cell, casted appropriately.
 - (AutocompleteTextFieldCell*)cell;
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
index 33c34cf..7077e1a 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
@@ -8,7 +8,7 @@
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
index 845835a..1bc2eee 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/resource_bundle.h"
 #include "base/scoped_nsobject.h"
 #include "base/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
@@ -21,6 +20,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "ui/base/resource/resource_bundle.h"
 
 using ::testing::Return;
 using ::testing::StrictMock;
@@ -102,7 +102,7 @@
 
   SelectedKeywordDecoration selected_keyword_decoration([view_ font]);
   selected_keyword_decoration.SetVisible(true);
-  selected_keyword_decoration.SetKeyword(std::wstring(L"Google"), false);
+  selected_keyword_decoration.SetKeyword(ASCIIToUTF16("Google"), false);
   [cell addLeftDecoration:&selected_keyword_decoration];
   EXPECT_NE(selected_keyword_decoration.GetWidthForSpace(kVeryWide),
             LocationBarDecoration::kOmittedWidth);
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.mm
index 37b6029..0b89491 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.mm
@@ -4,7 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/string_util.h"
 #include "grit/generated_resources.h"
 #include "base/sys_string_conversions.h"
@@ -13,7 +12,8 @@
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @implementation AutocompleteTextFieldEditor
 
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm
index c85c738..a86e8ce 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest.mm
@@ -4,7 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/resource_bundle.h"
 #import "base/mac/cocoa_protocols.h"
 #include "base/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
@@ -18,6 +17,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
+#include "ui/base/resource/resource_bundle.h"
 
 using ::testing::A;
 using ::testing::InSequence;
diff --git a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
index 48abf2e..da3475d 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -17,11 +15,13 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#import "chrome/browser/ui/cocoa/content_setting_bubble_cocoa.h"
+#import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm
index ad384f9..54b0fce 100644
--- a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm
@@ -4,12 +4,12 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h"
 
-#include "app/text_elider.h"
 #import "base/logging.h"
 #include "base/sys_string_conversions.h"
 #import "chrome/browser/ui/cocoa/image_utils.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
-#include "gfx/font.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/font.h"
 
 namespace {
 
@@ -89,10 +89,11 @@
 
   // Middle-elide the label to fit |width_left|.  This leaves the
   // prefix and the trailing country code in place.
-  gfx::Font font(base::SysNSStringToWide([font_ fontName]),
+  gfx::Font font(base::SysNSStringToUTF16([font_ fontName]),
                  [font_ pointSize]);
   NSString* elided_label = base::SysUTF16ToNSString(
-      ElideText(base::SysNSStringToUTF16(full_label_), font, width_left, true));
+      ui::ElideText(base::SysNSStringToUTF16(full_label_), font, width_left,
+                    true));
 
   // Use the elided label.
   SetLabel(elided_label);
diff --git a/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.mm b/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.mm
index 767092b..d9c620a 100644
--- a/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.mm
@@ -6,8 +6,6 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
@@ -15,6 +13,8 @@
 #include "grit/theme_resources.h"
 #include "grit/generated_resources.h"
 #include "skia/ext/skia_utils_mac.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
index f492aeb..7b06b91 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -132,9 +132,8 @@
   virtual void OnAutocompleteWillClosePopup();
   virtual void OnAutocompleteLosingFocus(gfx::NativeView unused);
   virtual void OnAutocompleteWillAccept();
-  virtual bool OnCommitSuggestedText(const std::wstring& typed_text);
+  virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete);
   virtual bool AcceptCurrentInstantPreview();
-  virtual void OnSetSuggestedSearchText(const string16& suggested_text);
   virtual void OnPopupBoundsChanged(const gfx::Rect& bounds);
   virtual void OnAutocompleteAccept(const GURL& url,
       WindowOpenDisposition disposition,
@@ -146,9 +145,9 @@
   virtual void OnKillFocus();
   virtual void OnSetFocus();
   virtual SkBitmap GetFavIcon() const;
-  virtual std::wstring GetTitle() const;
+  virtual string16 GetTitle() const;
 
-  NSImage* GetKeywordImage(const std::wstring& keyword);
+  NSImage* GetKeywordImage(const string16& keyword);
 
   AutocompleteTextField* GetAutocompleteTextField() { return field_; }
 
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
index 91753c3..3a1746b 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
@@ -29,7 +27,7 @@
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#import "chrome/browser/ui/cocoa/content_setting_bubble_cocoa.h"
+#import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
 #include "chrome/browser/ui/cocoa/event_utils.h"
 #import "chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h"
 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
@@ -48,12 +46,13 @@
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
 #include "net/base/net_util.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -140,8 +139,14 @@
 }
 
 void LocationBarViewMac::SetSuggestedText(const string16& text) {
-  edit_view_->SetSuggestText(
-      edit_view_->model()->UseVerbatimInstant() ? string16() : text);
+  // This method is internally invoked to reset suggest text, so we only do
+  // anything if the text isn't empty.
+  // TODO: if we keep autocomplete, make it so this isn't invoked with empty
+  // text.
+  if (!text.empty()) {
+    edit_view_->model()->FinalizeInstantQuery(edit_view_->GetText(), text,
+                                              false);
+  }
 }
 
 WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const {
@@ -249,19 +254,23 @@
   update_instant_ = false;
 }
 
-bool LocationBarViewMac::OnCommitSuggestedText(const std::wstring& typed_text) {
-  return edit_view_->CommitSuggestText();
+bool LocationBarViewMac::OnCommitSuggestedText(bool skip_inline_autocomplete) {
+  if (!browser_->instant())
+    return false;
+
+  const string16 suggestion = edit_view_->GetInstantSuggestion();
+  if (suggestion.empty())
+    return false;
+
+  edit_view_->model()->FinalizeInstantQuery(
+      edit_view_->GetText(), suggestion, skip_inline_autocomplete);
+  return true;
 }
 
 bool LocationBarViewMac::AcceptCurrentInstantPreview() {
   return InstantController::CommitIfCurrent(browser_->instant());
 }
 
-void LocationBarViewMac::OnSetSuggestedSearchText(
-    const string16& suggested_text) {
-  SetSuggestedText(suggested_text);
-}
-
 void LocationBarViewMac::OnPopupBoundsChanged(const gfx::Rect& bounds) {
   InstantController* instant = browser_->instant();
   if (instant)
@@ -323,17 +332,17 @@
       instant->Update
           (browser_->GetSelectedTabContentsWrapper(),
            edit_view_->model()->CurrentMatch(),
-           WideToUTF16(edit_view_->GetText()),
+           edit_view_->GetText(),
            edit_view_->model()->UseVerbatimInstant(),
            &suggested_text);
       if (!instant->MightSupportInstant()) {
-        edit_view_->model()->FinalizeInstantQuery(std::wstring(),
-                                                  std::wstring());
+        edit_view_->model()->FinalizeInstantQuery(
+            string16(), string16(), false);
       }
     } else {
       instant->DestroyPreviewContents();
-      edit_view_->model()->FinalizeInstantQuery(std::wstring(),
-                                                std::wstring());
+      edit_view_->model()->FinalizeInstantQuery(
+          string16(), string16(), false);
     }
   }
 
@@ -363,9 +372,9 @@
   return SkBitmap();
 }
 
-std::wstring LocationBarViewMac::GetTitle() const {
+string16 LocationBarViewMac::GetTitle() const {
   NOTIMPLEMENTED();
-  return std::wstring();
+  return string16();
 }
 
 void LocationBarViewMac::Revert() {
@@ -526,7 +535,7 @@
   }
 }
 
-NSImage* LocationBarViewMac::GetKeywordImage(const std::wstring& keyword) {
+NSImage* LocationBarViewMac::GetKeywordImage(const string16& keyword) {
   const TemplateURL* template_url =
       profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
   if (template_url && template_url->IsExtensionKeyword()) {
@@ -656,8 +665,8 @@
   keyword_hint_decoration_->SetVisible(false);
 
   // Get the keyword to use for keyword-search and hinting.
-  const std::wstring keyword(edit_view_->model()->keyword());
-  std::wstring short_name;
+  const string16 keyword = edit_view_->model()->keyword();
+  string16 short_name;
   bool is_extension_keyword = false;
   if (!keyword.empty()) {
     short_name = profile_->GetTemplateURLModel()->
@@ -680,7 +689,7 @@
     std::wstring label(toolbar_model_->GetEVCertName());
     ev_bubble_decoration_->SetFullLabel(base::SysWideToNSString(label));
   } else if (!keyword.empty() && is_keyword_hint) {
-    keyword_hint_decoration_->SetKeyword(WideToUTF16Hack(short_name),
+    keyword_hint_decoration_->SetKeyword(short_name,
                                          is_extension_keyword);
     keyword_hint_decoration_->SetVisible(true);
   }
diff --git a/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h b/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h
index 920d4d3..5c3f2bc 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -35,11 +35,15 @@
   // Show the page info panel on click.
   virtual bool OnMousePressed(NSRect frame);
   virtual bool AcceptsMousePress() { return true; }
+  virtual NSString* GetToolTip();
 
  private:
   // The location bar view that owns us.
   LocationBarViewMac* owner_;
 
+  // The string to show for a tooltip.
+  scoped_nsobject<NSString> tooltip_;
+
   DISALLOW_COPY_AND_ASSIGN(LocationIconDecoration);
 };
 
diff --git a/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.mm b/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.mm
index 808a45f..efe8128 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,9 @@
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
+#include "grit/generated_resources.h"
 #import "third_party/mozilla/NSPasteboard+Utils.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 // The info-bubble point should look like it points to the bottom of the lock
 // icon. Determined with Pixie.app.
@@ -17,7 +19,10 @@
 
 LocationIconDecoration::LocationIconDecoration(LocationBarViewMac* owner)
     : owner_(owner) {
+  tooltip_.reset(
+      [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_LOCATION_ICON) retain]);
 }
+
 LocationIconDecoration::~LocationIconDecoration() {
 }
 
@@ -70,3 +75,7 @@
   tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
   return true;
 }
+
+NSString* LocationIconDecoration::GetToolTip() {
+  return tooltip_.get();
+}
diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm
index 5ab186b..221c7f8 100644
--- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm
@@ -97,7 +97,8 @@
                         arrowLocation:info_bubble::kTopRight
                               devMode:NO];
   } else {
-    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+    ExtensionService* service = profile_->GetExtensionService();
+    service->browser_event_router()->PageActionExecuted(
         profile_, page_action_->extension_id(), page_action_->id(),
         current_tab_id_, current_url_.spec(),
         1);
diff --git a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
index 3c9cf30..f64f354 100644
--- a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
@@ -10,6 +10,7 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "base/string16.h"
 #include "chrome/browser/ui/cocoa/location_bar/bubble_decoration.h"
 
 class SelectedKeywordDecoration : public BubbleDecoration {
@@ -18,7 +19,7 @@
 
   // Calculates appropriate full and partial label strings based on
   // inputs.
-  void SetKeyword(const std::wstring& keyword, bool is_extension_keyword);
+  void SetKeyword(const string16& keyword, bool is_extension_keyword);
 
   // Determines what combination of labels and image will best fit
   // within |width|, makes those current for |BubbleDecoration|, and
diff --git a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm
index 6aa6505..7d90eeb 100644
--- a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm
@@ -4,13 +4,13 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/utf_string_conversions.h"
 #import "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
 #import "chrome/browser/ui/cocoa/image_utils.h"
 #include "chrome/browser/ui/omnibox/location_bar_util.h"
 #include "grit/theme_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 SelectedKeywordDecoration::SelectedKeywordDecoration(NSFont* font)
     : BubbleDecoration(font) {
@@ -46,23 +46,23 @@
   return GetWidthForImageAndLabel(nil, partial_string_);
 }
 
-void SelectedKeywordDecoration::SetKeyword(const std::wstring& short_name,
+void SelectedKeywordDecoration::SetKeyword(const string16& short_name,
                                            bool is_extension_keyword) {
-  const std::wstring min_name(
-      location_bar_util::CalculateMinString(short_name));
+  const string16 min_name(WideToUTF16Hack(
+      location_bar_util::CalculateMinString(UTF16ToWideHack(short_name))));
   const int message_id = is_extension_keyword ?
       IDS_OMNIBOX_EXTENSION_KEYWORD_TEXT : IDS_OMNIBOX_KEYWORD_TEXT;
 
   // The text will be like "Search <name>:".  "<name>" is a parameter
   // derived from |short_name|.
   full_string_.reset(
-      [l10n_util::GetNSStringF(message_id, WideToUTF16(short_name)) copy]);
+      [l10n_util::GetNSStringF(message_id, short_name) copy]);
 
   if (min_name.empty()) {
     partial_string_.reset();
   } else {
     partial_string_.reset(
-        [l10n_util::GetNSStringF(message_id, WideToUTF16(min_name)) copy]);
+        [l10n_util::GetNSStringF(message_id, min_name) copy]);
   }
 }
 
diff --git a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm
index 5536fda..9112272 100644
--- a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm
@@ -4,6 +4,7 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "base/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +33,7 @@
 // not enough room.
 TEST_F(SelectedKeywordDecorationTest, UsesPartialKeywordIfNarrow) {
 
-  const std::wstring kKeyword(L"Engine");
+  const string16 kKeyword = ASCIIToUTF16("Engine");
   NSString* const kFullString = @"Search Engine:";
   NSString* const kPartialString = @"Search En\u2026:";  // ellipses
 
diff --git a/chrome/browser/ui/cocoa/location_bar/star_decoration.mm b/chrome/browser/ui/cocoa/location_bar/star_decoration.mm
index 2ac3450..d089e7b 100644
--- a/chrome/browser/ui/cocoa/location_bar/star_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/star_decoration.mm
@@ -4,12 +4,12 @@
 
 #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h"
 
-#include "app/l10n_util_mac.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
 #include "chrome/browser/command_updater.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/menu_button.h b/chrome/browser/ui/cocoa/menu_button.h
index 93b1116..0b463db 100644
--- a/chrome/browser/ui/cocoa/menu_button.h
+++ b/chrome/browser/ui/cocoa/menu_button.h
@@ -36,11 +36,11 @@
 // in the button. This might change if we ever switch to a pop-up. Our direct
 // use of the given NSMenu object means that the one can set and use NSMenu's
 // delegate as usual.)
-@property (retain, nonatomic) IBOutlet NSMenu* attachedMenu;
+@property(retain, nonatomic) IBOutlet NSMenu* attachedMenu;
 
 // Whether or not to open the menu when the button is clicked. Otherwise, the
 // menu will only be opened when clicked and held.
-@property (assign, nonatomic) BOOL openMenuOnClick;
+@property(assign, nonatomic) BOOL openMenuOnClick;
 
 @end  // @interface MenuButton
 
diff --git a/chrome/browser/ui/cocoa/menu_controller.h b/chrome/browser/ui/cocoa/menu_controller.h
index c198c70..e842ac1 100644
--- a/chrome/browser/ui/cocoa/menu_controller.h
+++ b/chrome/browser/ui/cocoa/menu_controller.h
@@ -8,9 +8,10 @@
 
 #import <Cocoa/Cocoa.h>
 
+#import "base/mac/cocoa_protocols.h"
 #include "base/scoped_nsobject.h"
 
-namespace menus {
+namespace ui {
 class MenuModel;
 }
 
@@ -20,17 +21,17 @@
 // allow for hierarchical menus). The tag is the index into that model for
 // that particular item. It is important that the model outlives this object
 // as it only maintains weak references.
-@interface MenuController : NSObject {
+@interface MenuController : NSObject<NSMenuDelegate> {
  @protected
-  menus::MenuModel* model_;  // weak
+  ui::MenuModel* model_;  // weak
   scoped_nsobject<NSMenu> menu_;
   BOOL useWithPopUpButtonCell_;  // If YES, 0th item is blank
 }
 
-@property (nonatomic, assign) menus::MenuModel* model;
+@property(nonatomic, assign) ui::MenuModel* model;
 // Note that changing this will have no effect if you use
 // |-initWithModel:useWithPopUpButtonCell:| or after the first call to |-menu|.
-@property (nonatomic) BOOL useWithPopUpButtonCell;
+@property(nonatomic) BOOL useWithPopUpButtonCell;
 
 // NIB-based initializer. This does not create a menu. Clients can set the
 // properties of the object and the menu will be created upon the first call to
@@ -42,7 +43,7 @@
 // the menu will be displayed by a NSPopUpButtonCell, it needs to be of a
 // slightly different form (0th item is empty). Note this attribute of the menu
 // cannot be changed after it has been created.
-- (id)initWithModel:(menus::MenuModel*)model
+- (id)initWithModel:(ui::MenuModel*)model
     useWithPopUpButtonCell:(BOOL)useWithCell;
 
 // Access to the constructed menu if the complex initializer was used. If the
@@ -60,7 +61,7 @@
 @interface MenuController (Protected)
 - (void)addItemToMenu:(NSMenu*)menu
               atIndex:(NSInteger)index
-            fromModel:(menus::MenuModel*)model
+            fromModel:(ui::MenuModel*)model
            modelIndex:(int)modelIndex;
 @end
 
diff --git a/chrome/browser/ui/cocoa/menu_controller.mm b/chrome/browser/ui/cocoa/menu_controller.mm
index a6d314d..8e58ae7 100644
--- a/chrome/browser/ui/cocoa/menu_controller.mm
+++ b/chrome/browser/ui/cocoa/menu_controller.mm
@@ -4,16 +4,16 @@
 
 #import "chrome/browser/ui/cocoa/menu_controller.h"
 
-#include "app/l10n_util_mac.h"
-#include "app/menus/accelerator_cocoa.h"
-#include "app/menus/simple_menu_model.h"
 #include "base/logging.h"
 #include "base/sys_string_conversions.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/models/accelerator_cocoa.h"
+#include "ui/base/models/simple_menu_model.h"
 
 @interface MenuController (Private)
-- (NSMenu*)menuFromModel:(menus::MenuModel*)model;
+- (NSMenu*)menuFromModel:(ui::MenuModel*)model;
 - (void)addSeparatorToMenu:(NSMenu*)menu
                    atIndex:(int)index;
 @end
@@ -28,7 +28,7 @@
   return self;
 }
 
-- (id)initWithModel:(menus::MenuModel*)model
+- (id)initWithModel:(ui::MenuModel*)model
     useWithPopUpButtonCell:(BOOL)useWithCell {
   if ((self = [super init])) {
     model_ = model;
@@ -45,7 +45,7 @@
 
 // Creates a NSMenu from the given model. If the model has submenus, this can
 // be invoked recursively.
-- (NSMenu*)menuFromModel:(menus::MenuModel*)model {
+- (NSMenu*)menuFromModel:(ui::MenuModel*)model {
   NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
 
   // The indices may not always start at zero (the windows system menu is one
@@ -56,7 +56,7 @@
   const int count = model->GetItemCount();
   for (int index = firstItemIndex; index < firstItemIndex + count; index++) {
     int modelIndex = index - firstItemIndex;
-    if (model->GetTypeAt(modelIndex) == menus::MenuModel::TYPE_SEPARATOR) {
+    if (model->GetTypeAt(modelIndex) == ui::MenuModel::TYPE_SEPARATOR) {
       [self addSeparatorToMenu:menu atIndex:index];
     } else {
       [self addItemToMenu:menu atIndex:index fromModel:model
@@ -80,7 +80,7 @@
 // associated with the entry in the model indentifed by |modelIndex|.
 - (void)addItemToMenu:(NSMenu*)menu
               atIndex:(NSInteger)index
-            fromModel:(menus::MenuModel*)model
+            fromModel:(ui::MenuModel*)model
            modelIndex:(int)modelIndex {
   NSString* label =
       l10n_util::FixUpWindowsStyleLabel(model->GetLabelAt(modelIndex));
@@ -98,14 +98,14 @@
     }
   }
 
-  menus::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
-  if (type == menus::MenuModel::TYPE_SUBMENU) {
+  ui::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
+  if (type == ui::MenuModel::TYPE_SUBMENU) {
     // Recursively build a submenu from the sub-model at this index.
     [item setTarget:nil];
     [item setAction:nil];
-    menus::MenuModel* submenuModel = model->GetSubmenuModelAt(modelIndex);
+    ui::MenuModel* submenuModel = model->GetSubmenuModelAt(modelIndex);
     NSMenu* submenu =
-        [self menuFromModel:(menus::SimpleMenuModel*)submenuModel];
+        [self menuFromModel:(ui::SimpleMenuModel*)submenuModel];
     [item setSubmenu:submenu];
   } else {
     // The MenuModel works on indexes so we can't just set the command id as the
@@ -117,7 +117,7 @@
     [item setTarget:self];
     NSValue* modelObject = [NSValue valueWithPointer:model];
     [item setRepresentedObject:modelObject];  // Retains |modelObject|.
-    menus::AcceleratorCocoa accelerator;
+    ui::AcceleratorCocoa accelerator;
     if (model->GetAcceleratorAt(modelIndex, &accelerator)) {
       [item setKeyEquivalent:accelerator.characters()];
       [item setKeyEquivalentModifierMask:accelerator.modifiers()];
@@ -135,8 +135,8 @@
     return NO;
 
   NSInteger modelIndex = [item tag];
-  menus::MenuModel* model =
-      static_cast<menus::MenuModel*>(
+  ui::MenuModel* model =
+      static_cast<ui::MenuModel*>(
           [[(id)item representedObject] pointerValue]);
   DCHECK(model);
   if (model) {
@@ -164,8 +164,8 @@
 // item chosen.
 - (void)itemSelected:(id)sender {
   NSInteger modelIndex = [sender tag];
-  menus::MenuModel* model =
-      static_cast<menus::MenuModel*>(
+  ui::MenuModel* model =
+      static_cast<ui::MenuModel*>(
           [[sender representedObject] pointerValue]);
   DCHECK(model);
   if (model)
@@ -175,6 +175,7 @@
 - (NSMenu*)menu {
   if (!menu_ && model_) {
     menu_.reset([[self menuFromModel:model_] retain]);
+    [menu_ setDelegate:self];
     // If this is to be used with a NSPopUpButtonCell, add an item at the 0th
     // position that's empty. Doing it after the menu has been constructed won't
     // complicate creation logic, and since the tags are model indexes, they
@@ -188,4 +189,8 @@
   return menu_.get();
 }
 
+- (void)menuDidClose:(NSMenu*)menu {
+  model_->MenuClosed();
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/menu_controller_unittest.mm b/chrome/browser/ui/cocoa/menu_controller_unittest.mm
index 8e00c53..04dc3b5 100644
--- a/chrome/browser/ui/cocoa/menu_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/menu_controller_unittest.mm
@@ -4,8 +4,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/menus/simple_menu_model.h"
-#include "app/resource_bundle.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
@@ -13,13 +11,15 @@
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class MenuControllerTest : public CocoaTest {
 };
 
 // A menu delegate that counts the number of times certain things are called
 // to make sure things are hooked up properly.
-class Delegate : public menus::SimpleMenuModel::Delegate {
+class Delegate : public ui::SimpleMenuModel::Delegate {
  public:
   Delegate() : execute_count_(0), enable_count_(0) { }
 
@@ -30,7 +30,7 @@
   }
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) { return false; }
+      ui::Accelerator* accelerator) { return false; }
   virtual void ExecuteCommand(int command_id) { ++execute_count_; }
 
   int execute_count_;
@@ -62,7 +62,7 @@
 
 TEST_F(MenuControllerTest, EmptyMenu) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   scoped_nsobject<MenuController> menu(
       [[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
   EXPECT_EQ([[menu menu] numberOfItems], 0);
@@ -70,7 +70,7 @@
 
 TEST_F(MenuControllerTest, BasicCreation) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
   model.AddItem(2, ASCIIToUTF16("two"));
   model.AddItem(3, ASCIIToUTF16("three"));
@@ -95,9 +95,9 @@
 
 TEST_F(MenuControllerTest, Submenus) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
-  menus::SimpleMenuModel submodel(&delegate);
+  ui::SimpleMenuModel submodel(&delegate);
   submodel.AddItem(2, ASCIIToUTF16("sub-one"));
   submodel.AddItem(3, ASCIIToUTF16("sub-two"));
   submodel.AddItem(4, ASCIIToUTF16("sub-three"));
@@ -132,9 +132,9 @@
 
 TEST_F(MenuControllerTest, EmptySubmenu) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
-  menus::SimpleMenuModel submodel(&delegate);
+  ui::SimpleMenuModel submodel(&delegate);
   model.AddSubMenuWithStringId(2, IDS_ZOOM_MENU, &submodel);
 
   scoped_nsobject<MenuController> menu(
@@ -144,7 +144,7 @@
 
 TEST_F(MenuControllerTest, PopUpButton) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
   model.AddItem(2, ASCIIToUTF16("two"));
   model.AddItem(3, ASCIIToUTF16("three"));
@@ -164,7 +164,7 @@
 
 TEST_F(MenuControllerTest, Execute) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
   scoped_nsobject<MenuController> menu(
       [[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
@@ -188,10 +188,10 @@
 
 TEST_F(MenuControllerTest, Validate) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
   model.AddItem(2, ASCIIToUTF16("two"));
-  menus::SimpleMenuModel submodel(&delegate);
+  ui::SimpleMenuModel submodel(&delegate);
   submodel.AddItem(2, ASCIIToUTF16("sub-one"));
   model.AddSubMenuWithStringId(3, IDS_ZOOM_MENU, &submodel);
 
@@ -204,7 +204,7 @@
 
 TEST_F(MenuControllerTest, DefaultInitializer) {
   Delegate delegate;
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("one"));
   model.AddItem(2, ASCIIToUTF16("two"));
   model.AddItem(3, ASCIIToUTF16("three"));
@@ -230,7 +230,7 @@
   // no icon.
   string16 initial = ASCIIToUTF16("initial");
   delegate.SetDynamicLabel(initial);
-  menus::SimpleMenuModel model(&delegate);
+  ui::SimpleMenuModel model(&delegate);
   model.AddItem(1, ASCIIToUTF16("foo"));
   scoped_nsobject<MenuController> menu(
       [[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
diff --git a/chrome/browser/ui/cocoa/menu_tracked_button.h b/chrome/browser/ui/cocoa/menu_tracked_button.h
deleted file mode 100644
index 3ac9bd0..0000000
--- a/chrome/browser/ui/cocoa/menu_tracked_button.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_MENU_TRACKED_BUTTON_H_
-#define CHROME_BROWSER_UI_COCOA_MENU_TRACKED_BUTTON_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-// A MenuTrackedButton is meant to be used whenever a button is placed inside
-// the custom view of an NSMenuItem. If the user opens the menu in a non-sticky
-// fashion (i.e. clicks, holds, and drags) and then releases the mouse over
-// a MenuTrackedButton, it will |-performClick:| itself.
-//
-// To create the hover state effects, there are two code paths.  When the menu
-// is opened sticky, a tracking rect produces mouse entered/exit events that
-// allow for setting the cell's highlight property.  When in a drag cycle,
-// however, the only event received is |-mouseDragged:|.  Therefore, a
-// delayed selector is scheduled to poll the mouse location after each drag
-// event.  This checks if the user is still over the button after the drag
-// events stop being sent, indicating either the user is hovering without
-// movement or that the mouse is no longer over the receiver.
-@interface MenuTrackedButton : NSButton {
- @private
-  // If the button received a |-mouseEntered:| event. This short-circuits the
-  // custom drag tracking logic.
-  BOOL didEnter_;
-
-  // Whether or not the user is in a click-drag-release event sequence. If so
-  // and this receives a |-mouseUp:|, then this will click itself.
-  BOOL tracking_;
-
-  // In order to get hover effects when the menu is sticky-opened, a tracking
-  // rect needs to be installed on the button.
-  NSTrackingRectTag trackingTag_;
-}
-
-@property (nonatomic, readonly, getter=isTracking) BOOL tracking;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_MENU_TRACKED_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/menu_tracked_button.mm b/chrome/browser/ui/cocoa/menu_tracked_button.mm
deleted file mode 100644
index 37a79bb..0000000
--- a/chrome/browser/ui/cocoa/menu_tracked_button.mm
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/menu_tracked_button.h"
-
-#include <cmath>
-
-@interface MenuTrackedButton (Private)
-- (void)doHighlight:(BOOL)highlight;
-- (void)checkMouseInRect;
-- (NSRect)insetBounds;
-- (BOOL)shouldHighlightOnHover;
-@end
-
-@implementation MenuTrackedButton
-
-@synthesize tracking = tracking_;
-
-- (void)updateTrackingAreas {
-  [super updateTrackingAreas];
-  [self removeTrackingRect:trackingTag_];
-  trackingTag_ = [self addTrackingRect:NSInsetRect([self bounds], 1, 1)
-                                 owner:self
-                              userData:NULL
-                          assumeInside:NO];
-}
-
-- (void)viewDidMoveToWindow {
-  [self updateTrackingAreas];
-  [self doHighlight:NO];
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent {
-  if (!tracking_) {
-    didEnter_ = YES;
-  }
-  [self doHighlight:YES];
-  [super mouseEntered:theEvent];
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
-  didEnter_ = NO;
-  tracking_ = NO;
-  [self doHighlight:NO];
-  [super mouseExited:theEvent];
-}
-
-- (void)mouseDragged:(NSEvent*)theEvent {
-  tracking_ = !didEnter_;
-
-  NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
-  BOOL highlight = NSPointInRect(point, [self insetBounds]);
-  [self doHighlight:highlight];
-
-  // If tracking in non-sticky mode, poll the mouse cursor to see if it is still
-  // over the button and thus needs to be highlighted.  The delay is the
-  // smallest that still produces the effect while minimizing jank. Smaller
-  // values make the selector fire too close to immediately/now for the mouse to
-  // have moved off the receiver, and larger values produce lag.
-  if (tracking_ && [self shouldHighlightOnHover]) {
-    [self performSelector:@selector(checkMouseInRect)
-               withObject:nil
-               afterDelay:0.05
-                  inModes:[NSArray arrayWithObject:NSEventTrackingRunLoopMode]];
-  }
-  [super mouseDragged:theEvent];
-}
-
-- (void)mouseUp:(NSEvent*)theEvent {
-  [self doHighlight:NO];
-  if (!tracking_) {
-    return [super mouseUp:theEvent];
-  }
-  [self performClick:self];
-  tracking_ = NO;
-}
-
-- (void)doHighlight:(BOOL)highlight {
-  if (![self shouldHighlightOnHover]) {
-    return;
-  }
-  [[self cell] setHighlighted:highlight];
-  [self setNeedsDisplay];
-}
-
-// Checks if the user's current mouse location is over this button.  If it is,
-// the user is merely hovering here.  If it is not, then disable the highlight.
-// If the menu is opened in non-sticky mode, the button does not receive enter/
-// exit mouse events and thus polling is necessary.
-- (void)checkMouseInRect {
-  NSPoint point = [NSEvent mouseLocation];
-  point = [[self window] convertScreenToBase:point];
-  point = [self convertPoint:point fromView:nil];
-  if (!NSPointInRect(point, [self insetBounds])) {
-    [self doHighlight:NO];
-  }
-}
-
-// Returns the bounds of the receiver slightly inset to avoid highlighting both
-// buttons in a pair that overlap.
-- (NSRect)insetBounds {
-  return NSInsetRect([self bounds], 2, 1);
-}
-
-- (BOOL)shouldHighlightOnHover {
-  // Apple does not define NSAppKitVersionNumber10_5 when using the 10.5 SDK.
-  // The Internets have come up with this solution.
-  #ifndef NSAppKitVersionNumber10_5
-  #define NSAppKitVersionNumber10_5 949
-  #endif
-
-  // There's a cell drawing bug in 10.5 that was fixed on 10.6.  Hover states
-  // look terrible due to this, so disable highlighting on 10.5.
-  return std::floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/menu_tracked_button_unittest.mm b/chrome/browser/ui/cocoa/menu_tracked_button_unittest.mm
deleted file mode 100644
index 9b6f77a..0000000
--- a/chrome/browser/ui/cocoa/menu_tracked_button_unittest.mm
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/menu_tracked_button.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-// This test does not test what you'd think it does. Testing around event
-// tracking run loops is probably not worh the effort when the size of the
-// helper MakeEvent() is larger than the class being tested. If we ever figure
-// out a good way to test event tracking, this should be revisited.
-
-@interface MenuTrackedButtonTestReceiver : NSObject {
- @public
-  BOOL didThat_;
-}
-- (void)doThat:(id)sender;
-@end
-@implementation MenuTrackedButtonTestReceiver
-- (void)doThat:(id)sender {
-  didThat_ = YES;
-}
-@end
-
-
-class MenuTrackedButtonTest : public CocoaTest {
- public:
-  MenuTrackedButtonTest() : event_number_(0) {}
-
-  void SetUp() {
-    listener_.reset([[MenuTrackedButtonTestReceiver alloc] init]);
-    button_.reset(
-        [[MenuTrackedButton alloc] initWithFrame:NSMakeRect(10, 10, 50, 50)]);
-    [[test_window() contentView] addSubview:button()];
-    [button_ setTarget:listener()];
-    [button_ setAction:@selector(doThat:)];
-  }
-
-  // Creates an event of |type|, with |location| in test_window()'s coordinates.
-  NSEvent* MakeEvent(NSEventType type, NSPoint location) {
-    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
-    location = [test_window() convertBaseToScreen:location];
-    if (type == NSMouseEntered || type == NSMouseExited) {
-      return [NSEvent enterExitEventWithType:type
-                                    location:location
-                               modifierFlags:0
-                                   timestamp:now
-                                windowNumber:[test_window() windowNumber]
-                                     context:nil
-                                 eventNumber:event_number_++
-                              trackingNumber:0
-                                    userData:nil];
-    } else {
-      return [NSEvent mouseEventWithType:type
-                                location:location
-                           modifierFlags:0
-                               timestamp:now
-                            windowNumber:[test_window() windowNumber]
-                                 context:nil
-                             eventNumber:event_number_++
-                              clickCount:1
-                                pressure:1.0];
-    }
-  }
-
-  MenuTrackedButtonTestReceiver* listener() { return listener_.get(); }
-  NSButton* button() { return button_.get(); }
-
-  scoped_nsobject<MenuTrackedButtonTestReceiver> listener_;
-  scoped_nsobject<MenuTrackedButton> button_;
-  NSInteger event_number_;
-};
-
-// User mouses over and then off.
-TEST_F(MenuTrackedButtonTest, DISABLED_EnterExit) {
-  [NSApp postEvent:MakeEvent(NSMouseEntered, NSMakePoint(11, 11)) atStart:YES];
-  [NSApp postEvent:MakeEvent(NSMouseExited, NSMakePoint(9, 9)) atStart:YES];
-  EXPECT_FALSE(listener()->didThat_);
-}
-
-// User mouses over, clicks, drags, and exits.
-TEST_F(MenuTrackedButtonTest, DISABLED_EnterDragExit) {
-  [NSApp postEvent:MakeEvent(NSMouseEntered, NSMakePoint(11, 11)) atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseDown, NSMakePoint(12, 12)) atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(13, 11))
-           atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(13, 10))
-           atStart:YES];
-  [NSApp postEvent:MakeEvent(NSMouseExited, NSMakePoint(13, 9)) atStart:YES];
-  EXPECT_FALSE(listener()->didThat_);
-}
-
-// User mouses over, clicks, drags, and releases.
-TEST_F(MenuTrackedButtonTest, DISABLED_EnterDragUp) {
-  [NSApp postEvent:MakeEvent(NSMouseEntered, NSMakePoint(11, 11)) atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseDown, NSMakePoint(12, 12)) atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(13, 13))
-           atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseUp, NSMakePoint(14, 14)) atStart:YES];
-  EXPECT_TRUE(listener()->didThat_);
-}
-
-// User drags in and releases.
-TEST_F(MenuTrackedButtonTest, DISABLED_DragUp) {
-  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(11, 11))
-           atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(12, 12))
-           atStart:YES];
-  [NSApp postEvent:MakeEvent(NSLeftMouseUp, NSMakePoint(13, 13))
-           atStart:YES];
-  EXPECT_TRUE(listener()->didThat_);
-}
diff --git a/chrome/browser/ui/cocoa/menu_tracked_root_view.h b/chrome/browser/ui/cocoa/menu_tracked_root_view.h
deleted file mode 100644
index c475783..0000000
--- a/chrome/browser/ui/cocoa/menu_tracked_root_view.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_MENU_TRACKED_ROOT_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_MENU_TRACKED_ROOT_VIEW_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-// An instance of MenuTrackedRootView should be the root of the view hierarchy
-// of the custom view of NSMenuItems. If the user opens the menu in a non-
-// sticky fashion (i.e. clicks, holds, and drags) and then releases the mouse
-// over the menu item, it will cancel tracking on the |[menuItem_ menu]|.
-@interface MenuTrackedRootView : NSView {
- @private
-  // The menu item whose custom view's root view is an instance of this class.
-  NSMenuItem* menuItem_;  // weak
-}
-
-@property (assign, nonatomic) NSMenuItem* menuItem;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_MENU_TRACKED_ROOT_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/menu_tracked_root_view.mm b/chrome/browser/ui/cocoa/menu_tracked_root_view.mm
deleted file mode 100644
index 29dd93d..0000000
--- a/chrome/browser/ui/cocoa/menu_tracked_root_view.mm
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/menu_tracked_root_view.h"
-
-@implementation MenuTrackedRootView
-
-@synthesize menuItem = menuItem_;
-
-- (void)mouseUp:(NSEvent*)theEvent {
-  [[menuItem_ menu] cancelTracking];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/menu_tracked_root_view_unittest.mm b/chrome/browser/ui/cocoa/menu_tracked_root_view_unittest.mm
deleted file mode 100644
index cb3eab1..0000000
--- a/chrome/browser/ui/cocoa/menu_tracked_root_view_unittest.mm
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/menu_tracked_root_view.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-
-class MenuTrackedRootViewTest : public CocoaTest {
- public:
-  void SetUp() {
-    CocoaTest::SetUp();
-    view_.reset([[MenuTrackedRootView alloc] init]);
-  }
-
-  scoped_nsobject<MenuTrackedRootView> view_;
-};
-
-TEST_F(MenuTrackedRootViewTest, MouseUp) {
-  id menu = [OCMockObject mockForClass:[NSMenu class]];
-  [[menu expect] cancelTracking];
-
-  id menuItem = [OCMockObject mockForClass:[NSMenuItem class]];
-  [[[menuItem stub] andReturn:menu] menu];
-
-  [view_ setMenuItem:menuItem];
-  NSEvent* event = [NSEvent mouseEventWithType:NSLeftMouseUp
-                                      location:NSMakePoint(42, 42)
-                                 modifierFlags:0
-                                     timestamp:0
-                                  windowNumber:[test_window() windowNumber]
-                                       context:nil
-                                   eventNumber:1
-                                    clickCount:1
-                                      pressure:1.0];
-  [view_ mouseUp:event];
-
-  [menu verify];
-  [menuItem verify];
-}
diff --git a/chrome/browser/ui/cocoa/notifications/OWNERS b/chrome/browser/ui/cocoa/notifications/OWNERS
new file mode 100644
index 0000000..967c65c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/notifications/OWNERS
@@ -0,0 +1 @@
+johnnyg@chromium.org
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller.h b/chrome/browser/ui/cocoa/notifications/balloon_controller.h
index fadd35a..e346f42 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_controller.h
+++ b/chrome/browser/ui/cocoa/notifications/balloon_controller.h
@@ -52,6 +52,10 @@
 
   // The host for the renderer of the HTML contents.
   scoped_ptr<BalloonViewHost> htmlContents_;
+
+  // Variables to delay close requested by script while showing modal menu.
+  BOOL optionMenuIsActive_;
+  BOOL delayedClose_;
 }
 
 // Initialize with a balloon object containing the notification data.
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller.mm b/chrome/browser/ui/cocoa/notifications/balloon_controller.mm
index 6fca0a1..eef62d3 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_controller.mm
+++ b/chrome/browser/ui/cocoa/notifications/balloon_controller.mm
@@ -4,9 +4,7 @@
 
 #include "chrome/browser/ui/cocoa/notifications/balloon_controller.h"
 
-#include "app/l10n_util.h"
 #include "app/mac/nsimage_cache.h"
-#include "app/resource_bundle.h"
 #import "base/mac/cocoa_protocols.h"
 #include "base/mac/mac_util.h"
 #import "base/scoped_nsobject.h"
@@ -23,6 +21,8 @@
 #include "chrome/browser/ui/cocoa/notifications/balloon_view_host_mac.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -121,10 +121,25 @@
   [[closeButton_ cell] setHighlighted:NO];
 }
 
+- (void)closeBalloonNow:(bool)byUser {
+  if (!balloon_)
+    return;
+  [self close];
+  if (htmlContents_.get())
+    htmlContents_->Shutdown();
+  if (balloon_)
+    balloon_->OnClose(byUser);
+  balloon_ = NULL;
+}
+
 - (IBAction)optionsButtonPressed:(id)sender {
+  optionMenuIsActive_ = YES;
   [NSMenu popUpContextMenu:[menuController_ menu]
                  withEvent:[NSApp currentEvent]
                    forView:optionsButton_];
+  optionMenuIsActive_ = NO;
+  if (delayedClose_)
+    [self closeBalloonNow: false]; // always by script.
 }
 
 - (IBAction)permissionRevoked:(id)sender {
@@ -146,14 +161,14 @@
 }
 
 - (void)closeBalloon:(bool)byUser {
-  if (!balloon_)
+  // Keep alive while user is interacting with popup menu.
+  // Otherwise the script can close the notification and underlying balloon
+  // will be destroyed while user select a menu command.
+  if (!byUser && optionMenuIsActive_) {
+    delayedClose_ = YES;
     return;
-  [self close];
-  if (htmlContents_.get())
-    htmlContents_->Shutdown();
-  if (balloon_)
-    balloon_->OnClose(byUser);
-  balloon_ = NULL;
+  }
+  [self closeBalloonNow: byUser];
 }
 
 - (void)updateContents {
diff --git a/chrome/browser/ui/cocoa/notifications/balloon_view_bridge.mm b/chrome/browser/ui/cocoa/notifications/balloon_view_bridge.mm
index cea53b1..802929c 100644
--- a/chrome/browser/ui/cocoa/notifications/balloon_view_bridge.mm
+++ b/chrome/browser/ui/cocoa/notifications/balloon_view_bridge.mm
@@ -6,7 +6,7 @@
 
 #include "chrome/browser/ui/cocoa/notifications/balloon_controller.h"
 #import "chrome/browser/ui/cocoa/notifications/balloon_view_host_mac.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 #import <Cocoa/Cocoa.h>
 
diff --git a/chrome/browser/ui/cocoa/nswindow_additions.h b/chrome/browser/ui/cocoa/nswindow_additions.h
deleted file mode 100644
index 9d79464..0000000
--- a/chrome/browser/ui/cocoa/nswindow_additions.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_NSWINDOW_ADDITIONS_H_
-#define CHROME_BROWSER_UI_COCOA_NSWINDOW_ADDITIONS_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-// ID of a Space. Starts at 1.
-typedef int CGSWorkspaceID;
-
-@interface NSWindow(ChromeAdditions)
-
-// Gets the Space that the window is currently on. YES on success, NO on
-// failure.
-- (BOOL)cr_workspace:(CGSWorkspaceID*)outWorkspace;
-
-// Moves the window to the given Space. YES on success, NO on failure.
-- (BOOL)cr_moveToWorkspace:(CGSWorkspaceID)workspace;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_NSWINDOW_ADDITIONS_H_
diff --git a/chrome/browser/ui/cocoa/nswindow_additions.mm b/chrome/browser/ui/cocoa/nswindow_additions.mm
deleted file mode 100644
index f06af0d..0000000
--- a/chrome/browser/ui/cocoa/nswindow_additions.mm
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/nswindow_additions.h"
-
-#include <dlfcn.h>
-
-#include "base/logging.h"
-
-typedef void* CGSConnectionID;
-typedef int CGSWindowID;
-typedef int CGSError;
-typedef int CGSWorkspaceID;
-
-// These are private APIs we look up at run time.
-typedef CGSConnectionID (*CGSDefaultConnectionFunc)(void);
-typedef CGSError (*CGSGetWindowWorkspaceFunc)(const CGSConnectionID cid,
-                                              CGSWindowID wid,
-                                              CGSWorkspaceID* workspace);
-typedef CGSError (*CGSMoveWorkspaceWindowListFunc)(const CGSConnectionID cid,
-                                                   CGSWindowID* wids,
-                                                   int count,
-                                                   CGSWorkspaceID workspace);
-
-static CGSDefaultConnectionFunc sCGSDefaultConnection;
-static CGSGetWindowWorkspaceFunc sCGSGetWindowWorkspace;
-static CGSMoveWorkspaceWindowListFunc sCGSMoveWorkspaceWindowList;
-
-@implementation NSWindow(ChromeAdditions)
-
-// Looks up private Spaces APIs using dlsym.
-- (BOOL)cr_initializeWorkspaceAPIs {
-  static BOOL shouldInitialize = YES;
-  if (shouldInitialize) {
-    shouldInitialize = NO;
-
-    NSBundle* coreGraphicsBundle =
-          [NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"];
-    NSString* coreGraphicsPath = [[coreGraphicsBundle bundlePath]
-          stringByAppendingPathComponent:@"CoreGraphics"];
-    void* coreGraphicsLibrary = dlopen([coreGraphicsPath UTF8String],
-                                        RTLD_GLOBAL | RTLD_LAZY);
-
-    if (coreGraphicsLibrary) {
-      sCGSDefaultConnection =
-        (CGSDefaultConnectionFunc)dlsym(coreGraphicsLibrary,
-                                        "_CGSDefaultConnection");
-      if (!sCGSDefaultConnection) {
-        LOG(ERROR) << "Failed to lookup _CGSDefaultConnection API" << dlerror();
-      }
-      sCGSGetWindowWorkspace =
-        (CGSGetWindowWorkspaceFunc)dlsym(coreGraphicsLibrary,
-                                         "CGSGetWindowWorkspace");
-      if (!sCGSGetWindowWorkspace) {
-        LOG(ERROR) << "Failed to lookup CGSGetWindowWorkspace API" << dlerror();
-      }
-      sCGSMoveWorkspaceWindowList =
-        (CGSMoveWorkspaceWindowListFunc)dlsym(coreGraphicsLibrary,
-                                              "CGSMoveWorkspaceWindowList");
-      if (!sCGSMoveWorkspaceWindowList) {
-        LOG(ERROR) << "Failed to lookup CGSMoveWorkspaceWindowList API"
-                   << dlerror();
-      }
-    } else {
-      LOG(ERROR) << "Failed to load CoreGraphics lib" << dlerror();
-    }
-  }
-
-  return sCGSDefaultConnection != NULL &&
-         sCGSGetWindowWorkspace != NULL &&
-         sCGSMoveWorkspaceWindowList != NULL;
-}
-
-- (BOOL)cr_workspace:(CGSWorkspaceID*)outWorkspace {
-  if (![self cr_initializeWorkspaceAPIs]) {
-    return NO;
-  }
-
-  // If this ASSERT fails then consider using CGSDefaultConnectionForThread()
-  // instead of CGSDefaultConnection().
-  DCHECK([NSThread isMainThread]);
-  CGSConnectionID cid = sCGSDefaultConnection();
-  CGSWindowID wid = [self windowNumber];
-  CGSError err = sCGSGetWindowWorkspace(cid, wid, outWorkspace);
-  return err == 0;
-}
-
-- (BOOL)cr_moveToWorkspace:(CGSWorkspaceID)workspace {
-  if (![self cr_initializeWorkspaceAPIs]) {
-    return NO;
-  }
-
-  // If this ASSERT fails then consider using CGSDefaultConnectionForThread()
-  // instead of CGSDefaultConnection().
-  DCHECK([NSThread isMainThread]);
-  CGSConnectionID cid = sCGSDefaultConnection();
-  CGSWindowID wid = [self windowNumber];
-  // CGSSetWorkspaceForWindow doesn't seem to work for some reason.
-  CGSError err = sCGSMoveWorkspaceWindowList(cid, &wid, 1, workspace);
-  return err == 0;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/objc_zombie.mm b/chrome/browser/ui/cocoa/objc_zombie.mm
index 5cf6469..31d2a62 100644
--- a/chrome/browser/ui/cocoa/objc_zombie.mm
+++ b/chrome/browser/ui/cocoa/objc_zombie.mm
@@ -10,8 +10,8 @@
 
 #import <objc/objc-class.h>
 
-#include "base/lock.h"
 #include "base/logging.h"
+#include "base/synchronization/lock.h"
 #import "chrome/app/breakpad_mac.h"
 #import "chrome/browser/ui/cocoa/objc_method_swizzle.h"
 
@@ -56,7 +56,7 @@
 BOOL g_zombieAllObjects = NO;
 
 // Protects |g_zombieCount|, |g_zombieIndex|, and |g_zombies|.
-Lock lock_;
+base::Lock lock_;
 
 // How many zombies to keep before freeing, and the current head of
 // the circular buffer.
@@ -147,7 +147,7 @@
 
   // Don't involve the lock when creating zombies without a treadmill.
   if (g_zombieCount > 0) {
-    AutoLock pin(lock_);
+    base::AutoLock pin(lock_);
 
     // Check the count again in a thread-safe manner.
     if (g_zombieCount > 0) {
@@ -175,7 +175,7 @@
 
   // For instances which weren't big enough to store |wasa|, check if
   // the object is still on the treadmill.
-  AutoLock pin(lock_);
+  base::AutoLock pin(lock_);
   for (size_t i=0; i < g_zombieCount; ++i) {
     if (g_zombies[i].object == object)
       return g_zombies[i].wasa;
@@ -325,7 +325,7 @@
   ZombieRecord* oldZombies = g_zombies;
 
   {
-    AutoLock pin(lock_);
+    base::AutoLock pin(lock_);
 
     // Save the old index in case zombies need to be transferred.
     size_t oldIndex = g_zombieIndex;
@@ -396,7 +396,7 @@
   ZombieRecord* oldZombies = g_zombies;
 
   {
-    AutoLock pin(lock_);  // In case any |-dealloc| are in-progress.
+    base::AutoLock pin(lock_);  // In case any |-dealloc| are in-progress.
     g_zombieCount = 0;
     g_zombies = NULL;
   }
diff --git a/chrome/browser/ui/cocoa/options/OWNERS b/chrome/browser/ui/cocoa/options/OWNERS
new file mode 100644
index 0000000..7d8d85f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/OWNERS
@@ -0,0 +1,3 @@
+pinkerton@chromium.org
+rsesek@chromium.org
+thomasvl@chromium.org
diff --git a/chrome/browser/ui/cocoa/content_exceptions_window_controller.h b/chrome/browser/ui/cocoa/options/content_exceptions_window_controller.h
similarity index 100%
rename from chrome/browser/ui/cocoa/content_exceptions_window_controller.h
rename to chrome/browser/ui/cocoa/options/content_exceptions_window_controller.h
diff --git a/chrome/browser/ui/cocoa/options/content_exceptions_window_controller.mm b/chrome/browser/ui/cocoa/options/content_exceptions_window_controller.mm
new file mode 100644
index 0000000..a5141de
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/content_exceptions_window_controller.mm
@@ -0,0 +1,488 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/content_exceptions_window_controller.h"
+
+#include "base/command_line.h"
+#import "base/mac/mac_util.h"
+#import "base/scoped_nsobject.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/content_exceptions_table_model.h"
+#include "chrome/browser/content_setting_combo_model.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
+#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/models/table_model_observer.h"
+
+@interface ContentExceptionsWindowController (Private)
+- (id)initWithType:(ContentSettingsType)settingsType
+       settingsMap:(HostContentSettingsMap*)settingsMap
+    otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap;
+- (void)updateRow:(NSInteger)row
+        withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry
+           forOtr:(BOOL)isOtr;
+- (void)adjustEditingButtons;
+- (void)modelDidChange;
+- (NSString*)titleForIndex:(size_t)index;
+@end
+
+////////////////////////////////////////////////////////////////////////////////
+// PatternFormatter
+
+// A simple formatter that accepts text that vaguely looks like a pattern.
+@interface PatternFormatter : NSFormatter
+@end
+
+@implementation PatternFormatter
+- (NSString*)stringForObjectValue:(id)object {
+  if (![object isKindOfClass:[NSString class]])
+    return nil;
+  return object;
+}
+
+- (BOOL)getObjectValue:(id*)object
+             forString:(NSString*)string
+      errorDescription:(NSString**)error {
+  if ([string length]) {
+      if (ContentSettingsPattern(
+          base::SysNSStringToUTF8(string)).IsValid()) {
+      *object = string;
+      return YES;
+    }
+  }
+  if (error)
+    *error = @"Invalid pattern";
+  return NO;
+}
+
+- (NSAttributedString*)attributedStringForObjectValue:(id)object
+                                withDefaultAttributes:(NSDictionary*)attribs {
+  return nil;
+}
+@end
+
+////////////////////////////////////////////////////////////////////////////////
+// UpdatingContentSettingsObserver
+
+// UpdatingContentSettingsObserver is a notification observer that tells a
+// window controller to update its data on every notification.
+class UpdatingContentSettingsObserver : public NotificationObserver {
+ public:
+  UpdatingContentSettingsObserver(ContentExceptionsWindowController* controller)
+      : controller_(controller) {
+    // One would think one could register a TableModelObserver to be notified of
+    // changes to ContentExceptionsTableModel. One would be wrong: The table
+    // model only sends out changes that are made through the model, not for
+    // changes made directly to its backing HostContentSettings object (that
+    // happens e.g. if the user uses the cookie confirmation dialog). Hence,
+    // observe the CONTENT_SETTINGS_CHANGED notification directly.
+    registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
+                   NotificationService::AllSources());
+  }
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+ private:
+  NotificationRegistrar registrar_;
+  ContentExceptionsWindowController* controller_;
+};
+
+void UpdatingContentSettingsObserver::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  [controller_ modelDidChange];
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Static functions
+
+namespace  {
+
+NSString* GetWindowTitle(ContentSettingsType settingsType) {
+  switch (settingsType) {
+    case CONTENT_SETTINGS_TYPE_COOKIES:
+      return l10n_util::GetNSStringWithFixup(IDS_COOKIE_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_IMAGES:
+      return l10n_util::GetNSStringWithFixup(IDS_IMAGES_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
+      return l10n_util::GetNSStringWithFixup(IDS_JS_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_PLUGINS:
+      return l10n_util::GetNSStringWithFixup(IDS_PLUGINS_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_POPUPS:
+      return l10n_util::GetNSStringWithFixup(IDS_POPUP_EXCEPTION_TITLE);
+    default:
+      NOTREACHED();
+  }
+  return @"";
+}
+
+const CGFloat kButtonBarHeight = 35.0;
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// ContentExceptionsWindowController implementation
+
+static ContentExceptionsWindowController*
+    g_exceptionWindows[CONTENT_SETTINGS_NUM_TYPES] = { nil };
+
+@implementation ContentExceptionsWindowController
+
++ (id)controllerForType:(ContentSettingsType)settingsType
+            settingsMap:(HostContentSettingsMap*)settingsMap
+         otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap {
+  if (!g_exceptionWindows[settingsType]) {
+    g_exceptionWindows[settingsType] =
+        [[ContentExceptionsWindowController alloc]
+            initWithType:settingsType
+             settingsMap:settingsMap
+          otrSettingsMap:otrSettingsMap];
+  }
+  return g_exceptionWindows[settingsType];
+}
+
+- (id)initWithType:(ContentSettingsType)settingsType
+       settingsMap:(HostContentSettingsMap*)settingsMap
+    otrSettingsMap:(HostContentSettingsMap*)otrSettingsMap {
+  NSString* nibpath =
+      [base::mac::MainAppBundle() pathForResource:@"ContentExceptionsWindow"
+                                          ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    settingsType_ = settingsType;
+    settingsMap_ = settingsMap;
+    otrSettingsMap_ = otrSettingsMap;
+    model_.reset(new ContentExceptionsTableModel(
+        settingsMap_, otrSettingsMap_, settingsType_));
+    popup_model_.reset(new ContentSettingComboModel(settingsType_));
+    otrAllowed_ = otrSettingsMap != NULL;
+    tableObserver_.reset(new UpdatingContentSettingsObserver(self));
+    updatesEnabled_ = YES;
+
+    // TODO(thakis): autoremember window rect.
+    // TODO(thakis): sorting support.
+  }
+  return self;
+}
+
+- (void)awakeFromNib {
+  DCHECK([self window]);
+  DCHECK_EQ(self, [[self window] delegate]);
+  DCHECK(tableView_);
+  DCHECK_EQ(self, [tableView_ dataSource]);
+  DCHECK_EQ(self, [tableView_ delegate]);
+
+  [[self window] setTitle:GetWindowTitle(settingsType_)];
+
+  CGFloat minWidth = [[addButton_ superview] bounds].size.width +
+                     [[doneButton_ superview] bounds].size.width;
+  [self setMinWidth:minWidth];
+
+  [self adjustEditingButtons];
+
+  // Initialize menu for the data cell in the "action" column.
+  scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"exceptionMenu"]);
+  for (int i = 0; i < popup_model_->GetItemCount(); ++i) {
+    NSString* title =
+        l10n_util::FixUpWindowsStyleLabel(popup_model_->GetItemAt(i));
+    scoped_nsobject<NSMenuItem> allowItem(
+        [[NSMenuItem alloc] initWithTitle:title action:NULL keyEquivalent:@""]);
+    [allowItem.get() setTag:popup_model_->SettingForIndex(i)];
+    [menu.get() addItem:allowItem.get()];
+  }
+  NSCell* menuCell =
+      [[tableView_ tableColumnWithIdentifier:@"action"] dataCell];
+  [menuCell setMenu:menu.get()];
+
+  NSCell* patternCell =
+      [[tableView_ tableColumnWithIdentifier:@"pattern"] dataCell];
+  [patternCell setFormatter:[[[PatternFormatter alloc] init] autorelease]];
+
+  if (!otrAllowed_) {
+    [tableView_
+        removeTableColumn:[tableView_ tableColumnWithIdentifier:@"otr"]];
+  }
+}
+
+- (void)setMinWidth:(CGFloat)minWidth {
+  NSWindow* window = [self window];
+  [window setMinSize:NSMakeSize(minWidth, [window minSize].height)];
+  if ([window frame].size.width < minWidth) {
+    NSRect frame = [window frame];
+    frame.size.width = minWidth;
+    [window setFrame:frame display:NO];
+  }
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+  // Without this, some of the unit tests fail on 10.6:
+  [tableView_ setDataSource:nil];
+
+  g_exceptionWindows[settingsType_] = nil;
+  [self autorelease];
+}
+
+- (BOOL)editingNewException {
+  return newException_.get() != NULL;
+}
+
+// Let esc cancel editing if the user is currently editing a pattern. Else, let
+// esc close the window.
+- (void)cancel:(id)sender {
+  if ([tableView_ currentEditor] != nil) {
+    [tableView_ abortEditing];
+    [[self window] makeFirstResponder:tableView_];  // Re-gain focus.
+
+    if ([tableView_ selectedRow] == model_->RowCount()) {
+      // Cancel addition of new row.
+      [self removeException:self];
+    }
+  } else {
+    [self closeSheet:self];
+  }
+}
+
+- (void)keyDown:(NSEvent*)event {
+  NSString* chars = [event charactersIgnoringModifiers];
+  if ([chars length] == 1) {
+    switch ([chars characterAtIndex:0]) {
+      case NSDeleteCharacter:
+      case NSDeleteFunctionKey:
+        // Delete deletes.
+        if ([[tableView_ selectedRowIndexes] count] > 0)
+          [self removeException:self];
+        return;
+      case NSCarriageReturnCharacter:
+      case NSEnterCharacter:
+        // Return enters rename mode.
+        if ([[tableView_ selectedRowIndexes] count] == 1) {
+          [tableView_ editColumn:0
+                             row:[[tableView_ selectedRowIndexes] lastIndex]
+                       withEvent:nil
+                          select:YES];
+        }
+        return;
+    }
+  }
+  [super keyDown:event];
+}
+
+- (void)attachSheetTo:(NSWindow*)window {
+  [NSApp beginSheet:[self window]
+     modalForWindow:window
+      modalDelegate:self
+     didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
+        contextInfo:nil];
+}
+
+- (void)sheetDidEnd:(NSWindow*)sheet
+         returnCode:(NSInteger)returnCode
+        contextInfo:(void*)context {
+  [sheet close];
+  [sheet orderOut:self];
+}
+
+- (IBAction)addException:(id)sender {
+  if (newException_.get()) {
+    // The invariant is that |newException_| is non-NULL exactly if the pattern
+    // of a new exception is currently being edited - so there's nothing to do
+    // in that case.
+    return;
+  }
+  newException_.reset(new HostContentSettingsMap::PatternSettingPair);
+  newException_->first = ContentSettingsPattern(
+      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_SAMPLE_PATTERN));
+  newException_->second = CONTENT_SETTING_BLOCK;
+  [tableView_ reloadData];
+
+  [self adjustEditingButtons];
+  int index = model_->RowCount();
+  NSIndexSet* selectedSet = [NSIndexSet indexSetWithIndex:index];
+  [tableView_ selectRowIndexes:selectedSet byExtendingSelection:NO];
+  [tableView_ editColumn:0 row:index withEvent:nil select:YES];
+}
+
+- (IBAction)removeException:(id)sender {
+  updatesEnabled_ = NO;
+  NSIndexSet* selection = [tableView_ selectedRowIndexes];
+  [tableView_ deselectAll:self];  // Else we'll get a -setObjectValue: later.
+  DCHECK_GT([selection count], 0U);
+  NSUInteger index = [selection lastIndex];
+  while (index != NSNotFound) {
+    if (index == static_cast<NSUInteger>(model_->RowCount()))
+      newException_.reset();
+    else
+      model_->RemoveException(index);
+    index = [selection indexLessThanIndex:index];
+  }
+  updatesEnabled_ = YES;
+  [self modelDidChange];
+}
+
+- (IBAction)removeAllExceptions:(id)sender {
+  updatesEnabled_ = NO;
+  [tableView_ deselectAll:self];  // Else we'll get a -setObjectValue: later.
+  newException_.reset();
+  model_->RemoveAll();
+  updatesEnabled_ = YES;
+  [self modelDidChange];
+}
+
+- (IBAction)closeSheet:(id)sender {
+  [NSApp endSheet:[self window]];
+}
+
+// Table View Data Source -----------------------------------------------------
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView*)table {
+  return model_->RowCount() + (newException_.get() ? 1 : 0);
+}
+
+- (id)tableView:(NSTableView*)tv
+    objectValueForTableColumn:(NSTableColumn*)tableColumn
+                          row:(NSInteger)row {
+  const HostContentSettingsMap::PatternSettingPair* entry;
+  int isOtr;
+  if (newException_.get() && row >= model_->RowCount()) {
+    entry = newException_.get();
+    isOtr = 0;
+  } else {
+    entry = &model_->entry_at(row);
+    isOtr = model_->entry_is_off_the_record(row) ? 1 : 0;
+  }
+
+  NSObject* result = nil;
+  NSString* identifier = [tableColumn identifier];
+  if ([identifier isEqualToString:@"pattern"]) {
+    result = base::SysUTF8ToNSString(entry->first.AsString());
+  } else if ([identifier isEqualToString:@"action"]) {
+    result =
+        [NSNumber numberWithInt:popup_model_->IndexForSetting(entry->second)];
+  } else if ([identifier isEqualToString:@"otr"]) {
+    result = [NSNumber numberWithInt:isOtr];
+  } else {
+    NOTREACHED();
+  }
+  return result;
+}
+
+// Updates exception at |row| to contain the data in |entry|.
+- (void)updateRow:(NSInteger)row
+        withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry
+           forOtr:(BOOL)isOtr {
+  // TODO(thakis): This apparently moves an edited row to the back of the list.
+  // It's what windows and linux do, but it's kinda sucky. Fix.
+  // http://crbug.com/36904
+  updatesEnabled_ = NO;
+  if (row < model_->RowCount())
+    model_->RemoveException(row);
+  model_->AddException(entry.first, entry.second, isOtr);
+  updatesEnabled_ = YES;
+  [self modelDidChange];
+
+  // For now, at least re-select the edited element.
+  int newIndex = model_->IndexOfExceptionByPattern(entry.first, isOtr);
+  DCHECK(newIndex != -1);
+  [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex]
+          byExtendingSelection:NO];
+}
+
+- (void) tableView:(NSTableView*)tv
+    setObjectValue:(id)object
+    forTableColumn:(NSTableColumn*)tableColumn
+               row:(NSInteger)row {
+  // -remove: and -removeAll: both call |tableView_|'s -deselectAll:, which
+  // calls this method if a cell is currently being edited. Do not commit edits
+  // of rows that are about to be deleted.
+  if (!updatesEnabled_) {
+    // If this method gets called, the pattern filed of the new exception can no
+    // longer be being edited. Reset |newException_| to keep the invariant true.
+    newException_.reset();
+    return;
+  }
+
+  // Get model object.
+  bool isNewRow = newException_.get() && row >= model_->RowCount();
+  HostContentSettingsMap::PatternSettingPair originalEntry =
+      isNewRow ? *newException_ : model_->entry_at(row);
+  HostContentSettingsMap::PatternSettingPair entry = originalEntry;
+  bool isOtr =
+      isNewRow ? 0 : model_->entry_is_off_the_record(row);
+  bool wasOtr = isOtr;
+
+  // Modify it.
+  NSString* identifier = [tableColumn identifier];
+  if ([identifier isEqualToString:@"pattern"]) {
+    entry.first = ContentSettingsPattern(base::SysNSStringToUTF8(object));
+  }
+  if ([identifier isEqualToString:@"action"]) {
+    int index = [object intValue];
+    entry.second = popup_model_->SettingForIndex(index);
+  }
+  if ([identifier isEqualToString:@"otr"]) {
+    isOtr = [object intValue] != 0;
+  }
+
+  // Commit modification, if any.
+  if (isNewRow) {
+    newException_.reset();
+    if (![identifier isEqualToString:@"pattern"]) {
+      [tableView_ reloadData];
+      [self adjustEditingButtons];
+      return;  // Commit new rows only when the pattern has been set.
+    }
+    int newIndex = model_->IndexOfExceptionByPattern(entry.first, false);
+    if (newIndex != -1) {
+      // The new pattern was already in the table. Focus existing row instead of
+      // overwriting it with a new one.
+      [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex]
+              byExtendingSelection:NO];
+      [tableView_ reloadData];
+      [self adjustEditingButtons];
+      return;
+    }
+  }
+  if (entry != originalEntry || wasOtr != isOtr || isNewRow)
+    [self updateRow:row withEntry:entry forOtr:isOtr];
+}
+
+
+// Table View Delegate --------------------------------------------------------
+
+// When the selection in the table view changes, we need to adjust buttons.
+- (void)tableViewSelectionDidChange:(NSNotification*)notification {
+  [self adjustEditingButtons];
+}
+
+// Private --------------------------------------------------------------------
+
+// This method appropriately sets the enabled states on the table's editing
+// buttons.
+- (void)adjustEditingButtons {
+  NSIndexSet* selection = [tableView_ selectedRowIndexes];
+  [removeButton_ setEnabled:([selection count] > 0)];
+  [removeAllButton_ setEnabled:([tableView_ numberOfRows] > 0)];
+}
+
+- (void)modelDidChange {
+  // Some calls on |model_|, e.g. RemoveException(), change something on the
+  // backing content settings map object (which sends a notification) and then
+  // change more stuff in |model_|. If |model_| is deleted when the notification
+  // is sent, this second access causes a segmentation violation. Hence, disable
+  // resetting |model_| while updates can be in progress.
+  if (!updatesEnabled_)
+    return;
+
+  // The model caches its data, meaning we need to recreate it on every change.
+  model_.reset(new ContentExceptionsTableModel(
+      settingsMap_, otrSettingsMap_, settingsType_));
+
+  [tableView_ reloadData];
+  [self adjustEditingButtons];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/content_exceptions_window_controller_unittest.mm b/chrome/browser/ui/cocoa/options/content_exceptions_window_controller_unittest.mm
new file mode 100644
index 0000000..3118101
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/content_exceptions_window_controller_unittest.mm
@@ -0,0 +1,252 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/content_exceptions_window_controller.h"
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+void ProcessEvents() {
+  for (;;) {
+    base::mac::ScopedNSAutoreleasePool pool;
+    NSEvent* next_event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                             untilDate:nil
+                                                inMode:NSDefaultRunLoopMode
+                                               dequeue:YES];
+    if (!next_event)
+      break;
+    [NSApp sendEvent:next_event];
+  }
+}
+
+void SendKeyEvents(NSString* characters) {
+  for (NSUInteger i = 0; i < [characters length]; ++i) {
+    unichar character = [characters characterAtIndex:i];
+    NSString* charString = [NSString stringWithCharacters:&character length:1];
+    NSEvent* event = [NSEvent keyEventWithType:NSKeyDown
+                                      location:NSZeroPoint
+                                 modifierFlags:0
+                                     timestamp:0.0
+                                  windowNumber:0
+                                       context:nil
+                                    characters:charString
+                   charactersIgnoringModifiers:charString
+                                     isARepeat:NO
+                                       keyCode:0];
+    [NSApp sendEvent:event];
+  }
+}
+
+class ContentExceptionsWindowControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    TestingProfile* profile = browser_helper_.profile();
+    settingsMap_ = new HostContentSettingsMap(profile);
+  }
+
+  ContentExceptionsWindowController* GetController(ContentSettingsType type) {
+    id controller = [ContentExceptionsWindowController
+        controllerForType:type
+              settingsMap:settingsMap_.get()
+           otrSettingsMap:NULL];
+    [controller showWindow:nil];
+    return controller;
+  }
+
+  void ClickAdd(ContentExceptionsWindowController* controller) {
+    [controller addException:nil];
+    ProcessEvents();
+  }
+
+  void ClickRemove(ContentExceptionsWindowController* controller) {
+    [controller removeException:nil];
+    ProcessEvents();
+  }
+
+  void ClickRemoveAll(ContentExceptionsWindowController* controller) {
+    [controller removeAllExceptions:nil];
+    ProcessEvents();
+  }
+
+  void EnterText(NSString* str) {
+    SendKeyEvents(str);
+    ProcessEvents();
+  }
+
+  void HitEscape(ContentExceptionsWindowController* controller) {
+    [controller cancel:nil];
+    ProcessEvents();
+  }
+
+ protected:
+  BrowserTestHelper browser_helper_;
+  scoped_refptr<HostContentSettingsMap> settingsMap_;
+};
+
+TEST_F(ContentExceptionsWindowControllerTest, Construction) {
+  ContentExceptionsWindowController* controller =
+      [ContentExceptionsWindowController
+          controllerForType:CONTENT_SETTINGS_TYPE_PLUGINS
+                settingsMap:settingsMap_.get()
+             otrSettingsMap:NULL];
+  [controller showWindow:nil];
+  [controller close];  // Should autorelease.
+}
+
+// Regression test for http://crbug.com/37137
+TEST_F(ContentExceptionsWindowControllerTest, AddRemove) {
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
+
+  HostContentSettingsMap::SettingsForOneType settings;
+
+  ClickAdd(controller);
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(0u, settings.size());
+
+  ClickRemove(controller);
+
+  EXPECT_FALSE([controller editingNewException]);
+  [controller close];
+
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(0u, settings.size());
+}
+
+// Regression test for http://crbug.com/37137
+TEST_F(ContentExceptionsWindowControllerTest, AddRemoveAll) {
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
+
+  ClickAdd(controller);
+  ClickRemoveAll(controller);
+
+  EXPECT_FALSE([controller editingNewException]);
+  [controller close];
+
+  HostContentSettingsMap::SettingsForOneType settings;
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(0u, settings.size());
+}
+
+TEST_F(ContentExceptionsWindowControllerTest, Add) {
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
+
+  ClickAdd(controller);
+  EnterText(@"addedhost\n");
+
+  EXPECT_FALSE([controller editingNewException]);
+  [controller close];
+
+  HostContentSettingsMap::SettingsForOneType settings;
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(1u, settings.size());
+  EXPECT_EQ(ContentSettingsPattern("addedhost"), settings[0].first);
+}
+
+TEST_F(ContentExceptionsWindowControllerTest, AddEscDoesNotAdd) {
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
+
+  ClickAdd(controller);
+  EnterText(@"addedhost");  // but do not press enter
+  HitEscape(controller);
+
+  HostContentSettingsMap::SettingsForOneType settings;
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(0u, settings.size());
+  EXPECT_FALSE([controller editingNewException]);
+
+  [controller close];
+}
+
+// Regression test for http://crbug.com/37208
+TEST_F(ContentExceptionsWindowControllerTest, AddEditAddAdd) {
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
+
+  ClickAdd(controller);
+  EnterText(@"testtesttest");  // but do not press enter
+  ClickAdd(controller);
+  ClickAdd(controller);
+
+  EXPECT_TRUE([controller editingNewException]);
+  [controller close];
+
+  HostContentSettingsMap::SettingsForOneType settings;
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(0u, settings.size());
+}
+
+TEST_F(ContentExceptionsWindowControllerTest, AddExistingEditAdd) {
+  settingsMap_->SetContentSetting(ContentSettingsPattern("myhost"),
+                                  CONTENT_SETTINGS_TYPE_PLUGINS,
+                                  "",
+                                  CONTENT_SETTING_BLOCK);
+
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
+
+  ClickAdd(controller);
+  EnterText(@"myhost");  // but do not press enter
+  ClickAdd(controller);
+
+  EXPECT_TRUE([controller editingNewException]);
+  [controller close];
+
+
+  HostContentSettingsMap::SettingsForOneType settings;
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(1u, settings.size());
+}
+
+TEST_F(ContentExceptionsWindowControllerTest, AddExistingDoesNotOverwrite) {
+  settingsMap_->SetContentSetting(ContentSettingsPattern("myhost"),
+                                  CONTENT_SETTINGS_TYPE_COOKIES,
+                                  "",
+                                  CONTENT_SETTING_SESSION_ONLY);
+
+  ContentExceptionsWindowController* controller =
+      GetController(CONTENT_SETTINGS_TYPE_COOKIES);
+
+  ClickAdd(controller);
+  EnterText(@"myhost\n");
+
+  EXPECT_FALSE([controller editingNewException]);
+  [controller close];
+
+  HostContentSettingsMap::SettingsForOneType settings;
+  settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES,
+                                      "",
+                                      &settings);
+  EXPECT_EQ(1u, settings.size());
+  EXPECT_EQ(CONTENT_SETTING_SESSION_ONLY, settings[0].second);
+}
+
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/content_settings_dialog_controller.h b/chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h
similarity index 100%
rename from chrome/browser/ui/cocoa/content_settings_dialog_controller.h
rename to chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h
diff --git a/chrome/browser/ui/cocoa/options/content_settings_dialog_controller.mm b/chrome/browser/ui/cocoa/options/content_settings_dialog_controller.mm
new file mode 100644
index 0000000..5186bcb
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/content_settings_dialog_controller.mm
@@ -0,0 +1,646 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/command_line.h"
+#include "base/mac/mac_util.h"
+#import "chrome/browser/content_settings/content_settings_details.h"
+#import "chrome/browser/content_settings/host_content_settings_map.h"
+#import "chrome/browser/geolocation/geolocation_content_settings_map.h"
+#import "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
+#import "chrome/browser/notifications/desktop_notification_service.h"
+#import "chrome/browser/notifications/notification_exceptions_table_model.h"
+#include "chrome/browser/plugin_exceptions_table_model.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#import "chrome/browser/ui/cocoa/l10n_util.h"
+#import "chrome/browser/ui/cocoa/content_settings/simple_content_exceptions_window_controller.h"
+#import "chrome/browser/ui/cocoa/options/content_exceptions_window_controller.h"
+#import "chrome/browser/ui/cocoa/options/cookies_window_controller.h"
+#import "chrome/browser/ui/cocoa/tab_view_picker_table.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "grit/locale_settings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Stores the currently visible content settings dialog, if any.
+ContentSettingsDialogController* g_instance = nil;
+
+}  // namespace
+
+
+@interface ContentSettingsDialogController(Private)
+- (id)initWithProfile:(Profile*)profile;
+- (void)selectTab:(ContentSettingsType)settingsType;
+- (void)showExceptionsForType:(ContentSettingsType)settingsType;
+
+// Callback when preferences are changed. |prefName| is the name of the
+// pref that has changed.
+- (void)prefChanged:(const std::string&)prefName;
+
+// Callback when content settings are changed.
+- (void)contentSettingsChanged:(ContentSettingsDetails*)details;
+
+@end
+
+namespace ContentSettingsDialogControllerInternal {
+
+// A C++ class registered for changes in preferences.
+class PrefObserverBridge : public NotificationObserver {
+ public:
+  PrefObserverBridge(ContentSettingsDialogController* controller)
+      : controller_(controller), disabled_(false) {}
+
+  virtual ~PrefObserverBridge() {}
+
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) {
+    if (disabled_)
+      return;
+
+    // This is currently used by most notifications.
+    if (type == NotificationType::PREF_CHANGED) {
+      std::string* detail = Details<std::string>(details).ptr();
+      if (detail)
+        [controller_ prefChanged:*detail];
+    }
+
+    // This is sent when the "is managed" state changes.
+    // TODO(markusheintz): Move all content settings to this notification.
+    if (type == NotificationType::CONTENT_SETTINGS_CHANGED) {
+      ContentSettingsDetails* settings_details =
+          Details<ContentSettingsDetails>(details).ptr();
+      [controller_ contentSettingsChanged:settings_details];
+    }
+  }
+
+  void SetDisabled(bool disabled) {
+    disabled_ = disabled;
+  }
+
+ private:
+  ContentSettingsDialogController* controller_;  // weak, owns us
+  bool disabled_;  // true if notifications should be ignored.
+};
+
+// A C++ utility class to disable notifications for PrefsObserverBridge.
+// The intended usage is to create this on the stack.
+class PrefObserverDisabler {
+ public:
+  PrefObserverDisabler(PrefObserverBridge *bridge) : bridge_(bridge) {
+    bridge_->SetDisabled(true);
+  }
+
+  ~PrefObserverDisabler() {
+    bridge_->SetDisabled(false);
+  }
+
+ private:
+  PrefObserverBridge *bridge_;
+};
+
+}  // ContentSettingsDialogControllerInternal
+
+@implementation ContentSettingsDialogController
+
++ (id)showContentSettingsForType:(ContentSettingsType)settingsType
+                         profile:(Profile*)profile {
+  profile = profile->GetOriginalProfile();
+  if (!g_instance)
+    g_instance = [[self alloc] initWithProfile:profile];
+
+  // The code doesn't expect multiple profiles. Check that support for that
+  // hasn't been added.
+  DCHECK(g_instance->profile_ == profile);
+
+  // Select desired tab.
+  if (settingsType == CONTENT_SETTINGS_TYPE_DEFAULT) {
+    // Remember the last visited page from local state.
+    int value = g_instance->lastSelectedTab_.GetValue();
+    if (value >= 0 && value < CONTENT_SETTINGS_NUM_TYPES)
+      settingsType = static_cast<ContentSettingsType>(value);
+    if (settingsType == CONTENT_SETTINGS_TYPE_DEFAULT)
+      settingsType = CONTENT_SETTINGS_TYPE_COOKIES;
+  }
+  // TODO(thakis): Autosave window pos.
+
+  [g_instance selectTab:settingsType];
+  [g_instance showWindow:nil];
+  [g_instance closeExceptionsSheet];
+  return g_instance;
+}
+
+- (id)initWithProfile:(Profile*)profile {
+  DCHECK(profile);
+  NSString* nibpath =
+      [base::mac::MainAppBundle() pathForResource:@"ContentSettings"
+                                          ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    profile_ = profile;
+
+    observer_.reset(
+        new ContentSettingsDialogControllerInternal::PrefObserverBridge(self));
+    clearSiteDataOnExit_.Init(prefs::kClearSiteDataOnExit,
+                              profile_->GetPrefs(), observer_.get());
+
+    // Manually observe notifications for preferences that are grouped in
+    // the HostContentSettingsMap or GeolocationContentSettingsMap.
+    PrefService* prefs = profile_->GetPrefs();
+    registrar_.Init(prefs);
+    registrar_.Add(prefs::kBlockThirdPartyCookies, observer_.get());
+    registrar_.Add(prefs::kBlockNonsandboxedPlugins, observer_.get());
+    registrar_.Add(prefs::kDefaultContentSettings, observer_.get());
+    registrar_.Add(prefs::kGeolocationDefaultContentSetting, observer_.get());
+
+    // We don't need to observe changes in this value.
+    lastSelectedTab_.Init(prefs::kContentSettingsWindowLastTabIndex,
+                          profile_->GetPrefs(), NULL);
+  }
+  return self;
+}
+
+- (void)closeExceptionsSheet {
+  NSWindow* attachedSheet = [[self window] attachedSheet];
+  if (attachedSheet) {
+    [NSApp endSheet:attachedSheet];
+  }
+}
+
+- (void)awakeFromNib {
+  DCHECK([self window]);
+  DCHECK(tabView_);
+  DCHECK(tabViewPicker_);
+  DCHECK_EQ(self, [[self window] delegate]);
+
+  // Adapt views to potentially long localized strings.
+  CGFloat windowDelta = 0;
+  for (NSTabViewItem* tab in [tabView_ tabViewItems]) {
+    NSArray* subviews = [[tab view] subviews];
+    windowDelta = MAX(windowDelta,
+                      cocoa_l10n_util::VerticallyReflowGroup(subviews));
+
+    for (NSView* view in subviews) {
+      // Since the tab pane is in a horizontal resizer in IB, it's convenient
+      // to give all the subviews flexible width so that their sizes are
+      // autoupdated in IB. However, in chrome, the subviews shouldn't have
+      // flexible widths as this looks weird.
+      [view setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
+    }
+  }
+
+  NSString* label =
+      l10n_util::GetNSStringWithFixup(IDS_CONTENT_SETTINGS_FEATURES_LABEL);
+  label = [label stringByReplacingOccurrencesOfString:@":" withString:@""];
+  [tabViewPicker_ setHeading:label];
+
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableClickToPlay)) {
+    // The |pluginsEnabledIndex| property is bound to the selected *tag*,
+    // so we don't have to worry about index shifts when removing a row
+    // from the matrix.
+    [pluginDefaultSettingMatrix_ removeRow:kPluginsAskIndex];
+    NSArray* siblingViews = [[pluginDefaultSettingMatrix_ superview] subviews];
+    for (NSView* view in siblingViews) {
+      NSRect frame = [view frame];
+      if (frame.origin.y < [pluginDefaultSettingMatrix_ frame].origin.y) {
+        frame.origin.y +=
+            ([pluginDefaultSettingMatrix_ cellSize].height +
+             [pluginDefaultSettingMatrix_ intercellSpacing].height);
+        [view setFrame:frame];
+      }
+    }
+  }
+
+  NSRect frame = [[self window] frame];
+  frame.origin.y -= windowDelta;
+  frame.size.height += windowDelta;
+  [[self window] setFrame:frame display:NO];
+}
+
+// NSWindowDelegate method.
+- (void)windowWillClose:(NSNotification*)notification {
+  [self autorelease];
+  g_instance = nil;
+}
+
+- (void)selectTab:(ContentSettingsType)settingsType {
+  [self window];  // Make sure the nib file is loaded.
+  DCHECK(tabView_);
+  [tabView_ selectTabViewItemAtIndex:settingsType];
+}
+
+// NSTabViewDelegate method.
+- (void)         tabView:(NSTabView*)tabView
+    didSelectTabViewItem:(NSTabViewItem*)tabViewItem {
+  DCHECK_EQ(tabView_, tabView);
+  NSInteger index = [tabView indexOfTabViewItem:tabViewItem];
+  DCHECK_GT(index, CONTENT_SETTINGS_TYPE_DEFAULT);
+  DCHECK_LT(index, CONTENT_SETTINGS_NUM_TYPES);
+  if (index > CONTENT_SETTINGS_TYPE_DEFAULT &&
+       index < CONTENT_SETTINGS_NUM_TYPES)
+    lastSelectedTab_.SetValue(index);
+}
+
+// Let esc close the window.
+- (void)cancel:(id)sender {
+  [self close];
+}
+
+- (void)setCookieSettingIndex:(NSInteger)value {
+  ContentSetting setting = CONTENT_SETTING_DEFAULT;
+  switch (value) {
+    case kCookieEnabledIndex:  setting = CONTENT_SETTING_ALLOW; break;
+    case kCookieDisabledIndex: setting = CONTENT_SETTING_BLOCK; break;
+    default:
+      NOTREACHED();
+  }
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_COOKIES,
+      setting);
+}
+
+- (NSInteger)cookieSettingIndex {
+  switch (profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_COOKIES)) {
+    case CONTENT_SETTING_ALLOW:        return kCookieEnabledIndex;
+    case CONTENT_SETTING_BLOCK:        return kCookieDisabledIndex;
+    default:
+      NOTREACHED();
+      return kCookieEnabledIndex;
+  }
+}
+
+- (BOOL)cookieSettingsManaged {
+  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
+      CONTENT_SETTINGS_TYPE_COOKIES);
+}
+
+- (BOOL)blockThirdPartyCookies {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  return settingsMap->BlockThirdPartyCookies();
+}
+
+- (void)setBlockThirdPartyCookies:(BOOL)value {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  settingsMap->SetBlockThirdPartyCookies(value);
+}
+
+- (BOOL)blockThirdPartyCookiesManaged {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  return settingsMap->IsBlockThirdPartyCookiesManaged();
+}
+
+- (BOOL)clearSiteDataOnExit {
+  return clearSiteDataOnExit_.GetValue();
+}
+
+- (void)setClearSiteDataOnExit:(BOOL)value {
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  clearSiteDataOnExit_.SetValue(value);
+}
+
+// Shows the cookies controller.
+- (IBAction)showCookies:(id)sender {
+  // The cookie controller will autorelease itself when it's closed.
+  BrowsingDataDatabaseHelper* databaseHelper =
+      new BrowsingDataDatabaseHelper(profile_);
+  BrowsingDataLocalStorageHelper* storageHelper =
+      new BrowsingDataLocalStorageHelper(profile_);
+  BrowsingDataAppCacheHelper* appcacheHelper =
+      new BrowsingDataAppCacheHelper(profile_);
+  BrowsingDataIndexedDBHelper* indexedDBHelper =
+      BrowsingDataIndexedDBHelper::Create(profile_);
+  CookiesWindowController* controller =
+      [[CookiesWindowController alloc] initWithProfile:profile_
+                                        databaseHelper:databaseHelper
+                                         storageHelper:storageHelper
+                                        appcacheHelper:appcacheHelper
+                                       indexedDBHelper:indexedDBHelper];
+  [controller attachSheetTo:[self window]];
+}
+
+// Called when the user clicks the "Flash Player storage settings" button.
+- (IBAction)openFlashPlayerSettings:(id)sender {
+  Browser* browser = Browser::Create(profile_);
+  browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)),
+                   GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+  browser->window()->Show();
+}
+
+// Called when the user clicks the "Disable individual plug-ins..." button.
+- (IBAction)openPluginsPage:(id)sender {
+  Browser* browser = Browser::Create(profile_);
+  browser->OpenURL(GURL(chrome::kChromeUIPluginsURL),
+                   GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+  browser->window()->Show();
+}
+
+- (IBAction)showCookieExceptions:(id)sender {
+  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_COOKIES];
+}
+
+- (IBAction)showImagesExceptions:(id)sender {
+  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_IMAGES];
+}
+
+- (IBAction)showJavaScriptExceptions:(id)sender {
+  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_JAVASCRIPT];
+}
+
+- (IBAction)showPluginsExceptions:(id)sender {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableResourceContentSettings)) {
+    HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+    HostContentSettingsMap* offTheRecordSettingsMap =
+        profile_->HasOffTheRecordProfile() ?
+            profile_->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
+            NULL;
+    PluginExceptionsTableModel* model =
+        new PluginExceptionsTableModel(settingsMap, offTheRecordSettingsMap);
+    model->LoadSettings();
+    [[SimpleContentExceptionsWindowController controllerWithTableModel:model]
+        attachSheetTo:[self window]];
+  } else {
+    [self showExceptionsForType:CONTENT_SETTINGS_TYPE_PLUGINS];
+  }
+}
+
+- (IBAction)showPopupsExceptions:(id)sender {
+  [self showExceptionsForType:CONTENT_SETTINGS_TYPE_POPUPS];
+}
+
+- (IBAction)showGeolocationExceptions:(id)sender {
+  GeolocationContentSettingsMap* settingsMap =
+      profile_->GetGeolocationContentSettingsMap();
+  GeolocationExceptionsTableModel* model =  // Freed by window controller.
+      new GeolocationExceptionsTableModel(settingsMap);
+  [[SimpleContentExceptionsWindowController controllerWithTableModel:model]
+      attachSheetTo:[self window]];
+}
+
+- (IBAction)showNotificationsExceptions:(id)sender {
+  DesktopNotificationService* service =
+      profile_->GetDesktopNotificationService();
+  NotificationExceptionsTableModel* model =  // Freed by window controller.
+      new NotificationExceptionsTableModel(service);
+  [[SimpleContentExceptionsWindowController controllerWithTableModel:model]
+      attachSheetTo:[self window]];
+}
+
+- (void)showExceptionsForType:(ContentSettingsType)settingsType {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  HostContentSettingsMap* offTheRecordSettingsMap =
+      profile_->HasOffTheRecordProfile() ?
+          profile_->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
+          NULL;
+  [[ContentExceptionsWindowController controllerForType:settingsType
+                                            settingsMap:settingsMap
+                                         otrSettingsMap:offTheRecordSettingsMap]
+      attachSheetTo:[self window]];
+}
+
+- (void)setImagesEnabledIndex:(NSInteger)value {
+  ContentSetting setting = value == kContentSettingsEnabledIndex ?
+      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_IMAGES, setting);
+}
+
+- (NSInteger)imagesEnabledIndex {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  bool enabled =
+      settingsMap->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES) ==
+      CONTENT_SETTING_ALLOW;
+  return enabled ? kContentSettingsEnabledIndex : kContentSettingsDisabledIndex;
+}
+
+- (BOOL)imagesSettingsManaged {
+  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
+      CONTENT_SETTINGS_TYPE_IMAGES);
+}
+
+- (void)setJavaScriptEnabledIndex:(NSInteger)value {
+  ContentSetting setting = value == kContentSettingsEnabledIndex ?
+      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_JAVASCRIPT, setting);
+}
+
+- (NSInteger)javaScriptEnabledIndex {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  bool enabled =
+      settingsMap->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT) ==
+      CONTENT_SETTING_ALLOW;
+  return enabled ? kContentSettingsEnabledIndex : kContentSettingsDisabledIndex;
+}
+
+- (BOOL)javaScriptSettingsManaged {
+  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
+      CONTENT_SETTINGS_TYPE_JAVASCRIPT);
+}
+
+- (void)setPluginsEnabledIndex:(NSInteger)value {
+  ContentSetting setting = CONTENT_SETTING_DEFAULT;
+  switch (value) {
+    case kPluginsAllowIndex:
+      setting = CONTENT_SETTING_ALLOW;
+      break;
+    case kPluginsAskIndex:
+      setting = CONTENT_SETTING_ASK;
+      break;
+    case kPluginsBlockIndex:
+      setting = CONTENT_SETTING_BLOCK;
+      break;
+    default:
+      NOTREACHED();
+  }
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_PLUGINS, setting);
+}
+
+- (NSInteger)pluginsEnabledIndex {
+  HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
+  ContentSetting setting =
+      map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
+  switch (setting) {
+    case CONTENT_SETTING_ALLOW:
+      return kPluginsAllowIndex;
+    case CONTENT_SETTING_ASK:
+      if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableClickToPlay))
+        return kPluginsAskIndex;
+      // Fall through to the next case.
+    case CONTENT_SETTING_BLOCK:
+      return kPluginsBlockIndex;
+    default:
+      NOTREACHED();
+      return kPluginsAllowIndex;
+  }
+}
+
+- (BOOL)pluginsSettingsManaged {
+  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
+      CONTENT_SETTINGS_TYPE_PLUGINS);
+}
+
+- (void)setPopupsEnabledIndex:(NSInteger)value {
+  ContentSetting setting = value == kContentSettingsEnabledIndex ?
+      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_POPUPS, setting);
+}
+
+- (NSInteger)popupsEnabledIndex {
+  HostContentSettingsMap* settingsMap = profile_->GetHostContentSettingsMap();
+  bool enabled =
+      settingsMap->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS) ==
+      CONTENT_SETTING_ALLOW;
+  return enabled ? kContentSettingsEnabledIndex : kContentSettingsDisabledIndex;
+}
+
+- (BOOL)popupsSettingsManaged {
+  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
+      CONTENT_SETTINGS_TYPE_POPUPS);
+}
+
+- (void)setGeolocationSettingIndex:(NSInteger)value {
+  ContentSetting setting = CONTENT_SETTING_DEFAULT;
+  switch (value) {
+    case kGeolocationEnabledIndex:  setting = CONTENT_SETTING_ALLOW; break;
+    case kGeolocationAskIndex:      setting = CONTENT_SETTING_ASK;   break;
+    case kGeolocationDisabledIndex: setting = CONTENT_SETTING_BLOCK; break;
+    default:
+      NOTREACHED();
+  }
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetGeolocationContentSettingsMap()->SetDefaultContentSetting(
+      setting);
+}
+
+- (NSInteger)geolocationSettingIndex {
+  ContentSetting setting =
+      profile_->GetGeolocationContentSettingsMap()->GetDefaultContentSetting();
+  switch (setting) {
+    case CONTENT_SETTING_ALLOW: return kGeolocationEnabledIndex;
+    case CONTENT_SETTING_ASK:   return kGeolocationAskIndex;
+    case CONTENT_SETTING_BLOCK: return kGeolocationDisabledIndex;
+    default:
+      NOTREACHED();
+      return kGeolocationAskIndex;
+  }
+}
+
+- (void)setNotificationsSettingIndex:(NSInteger)value {
+  ContentSetting setting = CONTENT_SETTING_DEFAULT;
+  switch (value) {
+    case kNotificationsEnabledIndex:  setting = CONTENT_SETTING_ALLOW; break;
+    case kNotificationsAskIndex:      setting = CONTENT_SETTING_ASK;   break;
+    case kNotificationsDisabledIndex: setting = CONTENT_SETTING_BLOCK; break;
+    default:
+      NOTREACHED();
+  }
+  ContentSettingsDialogControllerInternal::PrefObserverDisabler
+      disabler(observer_.get());
+  profile_->GetDesktopNotificationService()->SetDefaultContentSetting(
+      setting);
+}
+
+- (NSInteger)notificationsSettingIndex {
+  ContentSetting setting =
+      profile_->GetDesktopNotificationService()->GetDefaultContentSetting();
+  switch (setting) {
+    case CONTENT_SETTING_ALLOW: return kNotificationsEnabledIndex;
+    case CONTENT_SETTING_ASK:   return kNotificationsAskIndex;
+    case CONTENT_SETTING_BLOCK: return kNotificationsDisabledIndex;
+    default:
+      NOTREACHED();
+      return kGeolocationAskIndex;
+  }
+}
+
+// Callback when preferences are changed. |prefName| is the name of the
+// pref that has changed and should not be NULL.
+- (void)prefChanged:(const std::string&)prefName {
+  if (prefName == prefs::kClearSiteDataOnExit) {
+    [self willChangeValueForKey:@"clearSiteDataOnExit"];
+    [self didChangeValueForKey:@"clearSiteDataOnExit"];
+  }
+  if (prefName == prefs::kBlockThirdPartyCookies) {
+    [self willChangeValueForKey:@"blockThirdPartyCookies"];
+    [self didChangeValueForKey:@"blockThirdPartyCookies"];
+    [self willChangeValueForKey:@"blockThirdPartyCookiesManaged"];
+    [self didChangeValueForKey:@"blockThirdPartyCookiesManaged"];
+  }
+  if (prefName == prefs::kBlockNonsandboxedPlugins) {
+    [self willChangeValueForKey:@"pluginsEnabledIndex"];
+    [self didChangeValueForKey:@"pluginsEnabledIndex"];
+  }
+  if (prefName == prefs::kDefaultContentSettings) {
+    // We don't know exactly which setting has changed, so we'll tickle all
+    // of the properties that apply to kDefaultContentSettings.  This will
+    // keep the UI up-to-date.
+    [self willChangeValueForKey:@"cookieSettingIndex"];
+    [self didChangeValueForKey:@"cookieSettingIndex"];
+    [self willChangeValueForKey:@"imagesEnabledIndex"];
+    [self didChangeValueForKey:@"imagesEnabledIndex"];
+    [self willChangeValueForKey:@"javaScriptEnabledIndex"];
+    [self didChangeValueForKey:@"javaScriptEnabledIndex"];
+    [self willChangeValueForKey:@"pluginsEnabledIndex"];
+    [self didChangeValueForKey:@"pluginsEnabledIndex"];
+    [self willChangeValueForKey:@"popupsEnabledIndex"];
+    [self didChangeValueForKey:@"popupsEnabledIndex"];
+
+    // Updates the "Enable" state of the radio groups and the exception buttons.
+    [self willChangeValueForKey:@"cookieSettingsManaged"];
+    [self didChangeValueForKey:@"cookieSettingsManaged"];
+    [self willChangeValueForKey:@"imagesSettingsManaged"];
+    [self didChangeValueForKey:@"imagesSettingsManaged"];
+    [self willChangeValueForKey:@"javaScriptSettingsManaged"];
+    [self didChangeValueForKey:@"javaScriptSettingsManaged"];
+    [self willChangeValueForKey:@"pluginsSettingsManaged"];
+    [self didChangeValueForKey:@"pluginsSettingsManaged"];
+    [self willChangeValueForKey:@"popupsSettingsManaged"];
+    [self didChangeValueForKey:@"popupsSettingsManaged"];
+  }
+  if (prefName == prefs::kGeolocationDefaultContentSetting) {
+    [self willChangeValueForKey:@"geolocationSettingIndex"];
+    [self didChangeValueForKey:@"geolocationSettingIndex"];
+  }
+  if (prefName == prefs::kDesktopNotificationDefaultContentSetting) {
+    [self willChangeValueForKey:@"notificationsSettingIndex"];
+    [self didChangeValueForKey:@"notificationsSettingIndex"];
+  }
+}
+
+- (void)contentSettingsChanged:(ContentSettingsDetails*)details {
+  [self prefChanged:prefs::kBlockNonsandboxedPlugins];
+  [self prefChanged:prefs::kDefaultContentSettings];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/content_settings_dialog_controller_unittest.mm b/chrome/browser/ui/cocoa/options/content_settings_dialog_controller_unittest.mm
new file mode 100644
index 0000000..fc29386
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/content_settings_dialog_controller_unittest.mm
@@ -0,0 +1,289 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h"
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#import "base/scoped_nsobject.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/chrome_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class ContentSettingsDialogControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    TestingProfile* profile = browser_helper_.profile();
+    settingsMap_ = new HostContentSettingsMap(profile);
+    geoSettingsMap_ = new GeolocationContentSettingsMap(profile);
+    notificationsService_.reset(new DesktopNotificationService(profile, NULL));
+    controller_ = [ContentSettingsDialogController
+                   showContentSettingsForType:CONTENT_SETTINGS_TYPE_DEFAULT
+                   profile:browser_helper_.profile()];
+  }
+
+  virtual void TearDown() {
+    [controller_ close];
+    CocoaTest::TearDown();
+  }
+
+ protected:
+  ContentSettingsDialogController* controller_;
+  BrowserTestHelper browser_helper_;
+  scoped_refptr<HostContentSettingsMap> settingsMap_;
+  scoped_refptr<GeolocationContentSettingsMap> geoSettingsMap_;
+  scoped_ptr<DesktopNotificationService> notificationsService_;
+};
+
+// Test that +showContentSettingsDialogForProfile brings up the existing editor
+// and doesn't leak or crash.
+TEST_F(ContentSettingsDialogControllerTest, CreateDialog) {
+  EXPECT_TRUE(controller_);
+}
+
+TEST_F(ContentSettingsDialogControllerTest, CookieSetting) {
+  // Change setting, check dialog property.
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
+                                         CONTENT_SETTING_ALLOW);
+  EXPECT_EQ([controller_ cookieSettingIndex], kCookieEnabledIndex);
+
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
+                                         CONTENT_SETTING_BLOCK);
+  EXPECT_EQ([controller_ cookieSettingIndex], kCookieDisabledIndex);
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setCookieSettingIndex:kCookieEnabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
+  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+
+  [controller_ setCookieSettingIndex:kCookieDisabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
+  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+}
+
+TEST_F(ContentSettingsDialogControllerTest, BlockThirdPartyCookiesSetting) {
+  // Change setting, check dialog property.
+  settingsMap_->SetBlockThirdPartyCookies(YES);
+  EXPECT_TRUE([controller_ blockThirdPartyCookies]);
+
+  settingsMap_->SetBlockThirdPartyCookies(NO);
+  EXPECT_FALSE([controller_ blockThirdPartyCookies]);
+
+  // Change dialog property, check setting.
+  [controller_ setBlockThirdPartyCookies:YES];
+  EXPECT_TRUE(settingsMap_->BlockThirdPartyCookies());
+
+  [controller_ setBlockThirdPartyCookies:NO];
+  EXPECT_FALSE(settingsMap_->BlockThirdPartyCookies());
+}
+
+TEST_F(ContentSettingsDialogControllerTest, ClearSiteDataOnExitSetting) {
+  TestingProfile* profile = browser_helper_.profile();
+
+  // Change setting, check dialog property.
+  profile->GetPrefs()->SetBoolean(prefs::kClearSiteDataOnExit, true);
+  EXPECT_TRUE([controller_ clearSiteDataOnExit]);
+
+  profile->GetPrefs()->SetBoolean(prefs::kClearSiteDataOnExit, false);
+  EXPECT_FALSE([controller_ clearSiteDataOnExit]);
+
+  // Change dialog property, check setting.
+  [controller_ setClearSiteDataOnExit:YES];
+  EXPECT_TRUE(profile->GetPrefs()->GetBoolean(prefs::kClearSiteDataOnExit));
+
+  [controller_ setClearSiteDataOnExit:NO];
+  EXPECT_FALSE(profile->GetPrefs()->GetBoolean(prefs::kClearSiteDataOnExit));
+}
+
+TEST_F(ContentSettingsDialogControllerTest, ImagesSetting) {
+  // Change setting, check dialog property.
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES,
+                                         CONTENT_SETTING_ALLOW);
+  EXPECT_EQ([controller_ imagesEnabledIndex], kContentSettingsEnabledIndex);
+
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES,
+                                         CONTENT_SETTING_BLOCK);
+  EXPECT_EQ([controller_ imagesEnabledIndex], kContentSettingsDisabledIndex);
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setImagesEnabledIndex:kContentSettingsEnabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES);
+  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+
+  [controller_ setImagesEnabledIndex:kContentSettingsDisabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_IMAGES);
+  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+}
+
+TEST_F(ContentSettingsDialogControllerTest, JavaScriptSetting) {
+  // Change setting, check dialog property.
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT,
+                                         CONTENT_SETTING_ALLOW);
+  EXPECT_EQ([controller_ javaScriptEnabledIndex], kContentSettingsEnabledIndex);
+
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT,
+                                         CONTENT_SETTING_BLOCK);
+  EXPECT_EQ([controller_ javaScriptEnabledIndex],
+            kContentSettingsDisabledIndex);
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setJavaScriptEnabledIndex:kContentSettingsEnabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
+  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+
+  [controller_ setJavaScriptEnabledIndex:kContentSettingsDisabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
+  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+}
+
+TEST_F(ContentSettingsDialogControllerTest, PluginsSetting) {
+  // Change setting, check dialog property.
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                         CONTENT_SETTING_ALLOW);
+  EXPECT_EQ(kPluginsAllowIndex, [controller_ pluginsEnabledIndex]);
+
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                         CONTENT_SETTING_BLOCK);
+  EXPECT_EQ(kPluginsBlockIndex, [controller_ pluginsEnabledIndex]);
+
+  {
+    // Click-to-play needs to be enabled to set the content setting to ASK.
+    CommandLine* cmd = CommandLine::ForCurrentProcess();
+    AutoReset<CommandLine> auto_reset(cmd, *cmd);
+    cmd->AppendSwitch(switches::kEnableClickToPlay);
+
+    settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
+                                           CONTENT_SETTING_ASK);
+    EXPECT_EQ(kPluginsAskIndex, [controller_ pluginsEnabledIndex]);
+  }
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setPluginsEnabledIndex:kPluginsAllowIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW, setting);
+
+  [controller_ setPluginsEnabledIndex:kPluginsBlockIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
+  EXPECT_EQ(CONTENT_SETTING_BLOCK, setting);
+
+  {
+    CommandLine* cmd = CommandLine::ForCurrentProcess();
+    AutoReset<CommandLine> auto_reset(cmd, *cmd);
+    cmd->AppendSwitch(switches::kEnableClickToPlay);
+
+    [controller_ setPluginsEnabledIndex:kPluginsAskIndex];
+    setting =
+        settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
+    EXPECT_EQ(CONTENT_SETTING_ASK, setting);
+  }
+}
+
+TEST_F(ContentSettingsDialogControllerTest, PopupsSetting) {
+  // Change setting, check dialog property.
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS,
+                                         CONTENT_SETTING_ALLOW);
+  EXPECT_EQ([controller_ popupsEnabledIndex], kContentSettingsEnabledIndex);
+
+  settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS,
+                                         CONTENT_SETTING_BLOCK);
+  EXPECT_EQ([controller_ popupsEnabledIndex], kContentSettingsDisabledIndex);
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setPopupsEnabledIndex:kContentSettingsEnabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS);
+  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+
+  [controller_ setPopupsEnabledIndex:kContentSettingsDisabledIndex];
+  setting =
+      settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS);
+  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+}
+
+TEST_F(ContentSettingsDialogControllerTest, GeolocationSetting) {
+  // Change setting, check dialog property.
+  geoSettingsMap_->SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
+  EXPECT_EQ([controller_ geolocationSettingIndex], kGeolocationEnabledIndex);
+
+  geoSettingsMap_->SetDefaultContentSetting(CONTENT_SETTING_ASK);
+  EXPECT_EQ([controller_ geolocationSettingIndex], kGeolocationAskIndex);
+
+  geoSettingsMap_->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
+  EXPECT_EQ([controller_ geolocationSettingIndex], kGeolocationDisabledIndex);
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setGeolocationSettingIndex:kGeolocationEnabledIndex];
+  setting =
+      geoSettingsMap_->GetDefaultContentSetting();
+  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+
+  [controller_ setGeolocationSettingIndex:kGeolocationAskIndex];
+  setting =
+      geoSettingsMap_->GetDefaultContentSetting();
+  EXPECT_EQ(setting, CONTENT_SETTING_ASK);
+
+  [controller_ setGeolocationSettingIndex:kGeolocationDisabledIndex];
+  setting =
+      geoSettingsMap_->GetDefaultContentSetting();
+  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+}
+
+TEST_F(ContentSettingsDialogControllerTest, NotificationsSetting) {
+  // Change setting, check dialog property.
+  notificationsService_->SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
+  EXPECT_EQ([controller_ notificationsSettingIndex],
+             kNotificationsEnabledIndex);
+
+  notificationsService_->SetDefaultContentSetting(CONTENT_SETTING_ASK);
+  EXPECT_EQ([controller_ notificationsSettingIndex], kNotificationsAskIndex);
+
+  notificationsService_->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
+  EXPECT_EQ([controller_ notificationsSettingIndex],
+            kNotificationsDisabledIndex);
+
+  // Change dialog property, check setting.
+  NSInteger setting;
+  [controller_ setNotificationsSettingIndex:kNotificationsEnabledIndex];
+  setting =
+      notificationsService_->GetDefaultContentSetting();
+  EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+
+  [controller_ setNotificationsSettingIndex:kNotificationsAskIndex];
+  setting =
+      notificationsService_->GetDefaultContentSetting();
+  EXPECT_EQ(setting, CONTENT_SETTING_ASK);
+
+  [controller_ setNotificationsSettingIndex:kNotificationsDisabledIndex];
+  setting =
+      notificationsService_->GetDefaultContentSetting();
+  EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+}
+
+}  // namespace
+
diff --git a/chrome/browser/ui/cocoa/options/cookies_window_controller.h b/chrome/browser/ui/cocoa/options/cookies_window_controller.h
new file mode 100644
index 0000000..62d2507
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/cookies_window_controller.h
@@ -0,0 +1,149 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/cookies_tree_model.h"
+#import "chrome/browser/ui/cocoa/content_settings/cookie_tree_node.h"
+#include "net/base/cookie_monster.h"
+
+@class CookiesWindowController;
+@class CookieDetailsViewController;
+class Profile;
+
+namespace {
+class CookiesWindowControllerTest;
+}
+
+namespace ui {
+class TreeModel;
+class TreeModelNode;
+}
+
+// Thin bridge to the window controller that performs model update actions
+// directly on the treeController_.
+class CookiesTreeModelObserverBridge : public CookiesTreeModel::Observer {
+ public:
+  explicit CookiesTreeModelObserverBridge(CookiesWindowController* controller);
+
+  // Begin TreeModelObserver implementation.
+  virtual void TreeNodesAdded(ui::TreeModel* model,
+                              ui::TreeModelNode* parent,
+                              int start,
+                              int count);
+  virtual void TreeNodesRemoved(ui::TreeModel* model,
+                                ui::TreeModelNode* parent,
+                                int start,
+                                int count);
+  virtual void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node);
+  // End TreeModelObserver implementation.
+
+  virtual void TreeModelBeginBatch(CookiesTreeModel* model);
+  virtual void TreeModelEndBatch(CookiesTreeModel* model);
+
+  // Invalidates the Cocoa model. This is used to tear down the Cocoa model
+  // when we're about to entirely rebuild it.
+  void InvalidateCocoaModel();
+
+ private:
+  friend class ::CookiesWindowControllerTest;
+
+  // Creates a CocoaCookieTreeNode from a platform-independent one.
+  // Return value is autoreleased. This creates child nodes recusively.
+  CocoaCookieTreeNode* CocoaNodeFromTreeNode(ui::TreeModelNode* node);
+
+  // Finds the Cocoa model node based on a platform-independent one. This is
+  // done by comparing the treeNode pointers. |start| is the node to start
+  // searching at. If |start| is nil, the root is used.
+  CocoaCookieTreeNode* FindCocoaNode(ui::TreeModelNode* node,
+                                     CocoaCookieTreeNode* start);
+
+  // Returns whether or not the Cocoa tree model is built.
+  bool HasCocoaModel();
+
+  CookiesWindowController* window_controller_;  // weak, owns us.
+
+  // If this is true, then the Model has informed us that it is batching
+  // updates. Rather than updating the Cocoa side of the model, we ignore those
+  // small changes and rebuild once at the end.
+  bool batch_update_;
+};
+
+// Controller for the cookies manager. This class stores an internal copy of
+// the CookiesTreeModel but with Cocoa-converted values (NSStrings and NSImages
+// instead of std::strings and SkBitmaps). Doing this allows us to use bindings
+// for the interface. Changes are pushed to this internal model via a very thin
+// bridge (see above).
+@interface CookiesWindowController : NSWindowController
+                                     <NSOutlineViewDelegate,
+                                      NSWindowDelegate> {
+ @private
+  // Platform-independent model and C++/Obj-C bridge components.
+  scoped_ptr<CookiesTreeModel> treeModel_;
+  scoped_ptr<CookiesTreeModelObserverBridge> modelObserver_;
+
+  // Cached array of icons.
+  scoped_nsobject<NSMutableArray> icons_;
+
+  // Our Cocoa copy of the model.
+  scoped_nsobject<CocoaCookieTreeNode> cocoaTreeModel_;
+
+  // A flag indicating whether or not the "Remove" button should be enabled.
+  BOOL removeButtonEnabled_;
+
+  IBOutlet NSTreeController* treeController_;
+  IBOutlet NSOutlineView* outlineView_;
+  IBOutlet NSSearchField* searchField_;
+  IBOutlet NSView* cookieDetailsViewPlaceholder_;
+  IBOutlet NSButton* removeButton_;
+
+  scoped_nsobject<CookieDetailsViewController> detailsViewController_;
+  Profile* profile_;  // weak
+  BrowsingDataDatabaseHelper* databaseHelper_;  // weak
+  BrowsingDataLocalStorageHelper* storageHelper_;  // weak
+  BrowsingDataAppCacheHelper* appcacheHelper_;  // weak
+  BrowsingDataIndexedDBHelper* indexedDBHelper_;  // weak
+}
+@property(assign, nonatomic) BOOL removeButtonEnabled;
+@property(readonly, nonatomic) NSTreeController* treeController;
+
+// Designated initializer. Profile cannot be NULL.
+- (id)initWithProfile:(Profile*)profile
+       databaseHelper:(BrowsingDataDatabaseHelper*)databaseHelper
+        storageHelper:(BrowsingDataLocalStorageHelper*)storageHelper
+       appcacheHelper:(BrowsingDataAppCacheHelper*)appcacheHelper
+      indexedDBHelper:(BrowsingDataIndexedDBHelper*)indexedDBHelper;
+
+// Shows the cookies window as a modal sheet attached to |window|.
+- (void)attachSheetTo:(NSWindow*)window;
+
+// Updates the filter from the search field.
+- (IBAction)updateFilter:(id)sender;
+
+// Delete cookie actions.
+- (IBAction)deleteCookie:(id)sender;
+- (IBAction)deleteAllCookies:(id)sender;
+
+// Closes the sheet and ends the modal loop. This will also cleanup the memory.
+- (IBAction)closeSheet:(id)sender;
+
+// Returns the cocoaTreeModel_.
+- (CocoaCookieTreeNode*)cocoaTreeModel;
+- (void)setCocoaTreeModel:(CocoaCookieTreeNode*)model;
+
+// Returns the treeModel_.
+- (CookiesTreeModel*)treeModel;
+
+@end
+
+@interface CookiesWindowController (UnitTesting)
+- (void)deleteNodeAtIndexPath:(NSIndexPath*)path;
+- (void)clearBrowsingDataNotification:(NSNotification*)notif;
+- (CookiesTreeModelObserverBridge*)modelObserver;
+- (NSArray*)icons;
+- (void)loadTreeModelFromProfile;
+@end
diff --git a/chrome/browser/ui/cocoa/options/cookies_window_controller.mm b/chrome/browser/ui/cocoa/options/cookies_window_controller.mm
new file mode 100644
index 0000000..b6a1a92
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/cookies_window_controller.mm
@@ -0,0 +1,448 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/cookies_window_controller.h"
+
+#include <queue>
+#include <vector>
+
+#import "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
+#include "chrome/browser/ui/cocoa/content_settings/cookie_details_view_controller.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "third_party/apple/ImageAndTextCell.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+// Key path used for notifying KVO.
+static NSString* const kCocoaTreeModel = @"cocoaTreeModel";
+
+CookiesTreeModelObserverBridge::CookiesTreeModelObserverBridge(
+    CookiesWindowController* controller)
+    : window_controller_(controller),
+      batch_update_(false) {
+}
+
+// Notification that nodes were added to the specified parent.
+void CookiesTreeModelObserverBridge::TreeNodesAdded(ui::TreeModel* model,
+                                                    ui::TreeModelNode* parent,
+                                                    int start,
+                                                    int count) {
+  // We're in for a major rebuild. Ignore this request.
+  if (batch_update_ || !HasCocoaModel())
+    return;
+
+  CocoaCookieTreeNode* cocoa_parent = FindCocoaNode(parent, nil);
+  NSMutableArray* cocoa_children = [cocoa_parent mutableChildren];
+
+  [window_controller_ willChangeValueForKey:kCocoaTreeModel];
+  CookieTreeNode* cookie_parent = static_cast<CookieTreeNode*>(parent);
+  for (int i = 0; i < count; ++i) {
+    CookieTreeNode* cookie_child = cookie_parent->GetChild(start + i);
+    CocoaCookieTreeNode* new_child = CocoaNodeFromTreeNode(cookie_child);
+    [cocoa_children addObject:new_child];
+  }
+  [window_controller_ didChangeValueForKey:kCocoaTreeModel];
+}
+
+// Notification that nodes were removed from the specified parent.
+void CookiesTreeModelObserverBridge::TreeNodesRemoved(ui::TreeModel* model,
+                                                      ui::TreeModelNode* parent,
+                                                      int start,
+                                                      int count) {
+  // We're in for a major rebuild. Ignore this request.
+  if (batch_update_ || !HasCocoaModel())
+    return;
+
+  CocoaCookieTreeNode* cocoa_parent = FindCocoaNode(parent, nil);
+  [window_controller_ willChangeValueForKey:kCocoaTreeModel];
+  NSMutableArray* cocoa_children = [cocoa_parent mutableChildren];
+  for (int i = start + count - 1; i >= start; --i) {
+    [cocoa_children removeObjectAtIndex:i];
+  }
+  [window_controller_ didChangeValueForKey:kCocoaTreeModel];
+}
+
+// Notification that the contents of a node has changed.
+void CookiesTreeModelObserverBridge::TreeNodeChanged(ui::TreeModel* model,
+                                                     ui::TreeModelNode* node) {
+  // If we don't have a Cocoa model, only let the root node change.
+  if (batch_update_ || (!HasCocoaModel() && model->GetRoot() != node))
+    return;
+
+  if (HasCocoaModel()) {
+    // We still have a Cocoa model, so just rebuild the node.
+    [window_controller_ willChangeValueForKey:kCocoaTreeModel];
+    CocoaCookieTreeNode* changed_node = FindCocoaNode(node, nil);
+    [changed_node rebuild];
+    [window_controller_ didChangeValueForKey:kCocoaTreeModel];
+  } else {
+    // Full rebuild.
+    [window_controller_ setCocoaTreeModel:CocoaNodeFromTreeNode(node)];
+  }
+}
+
+void CookiesTreeModelObserverBridge::TreeModelBeginBatch(
+    CookiesTreeModel* model) {
+  batch_update_ = true;
+}
+
+void CookiesTreeModelObserverBridge::TreeModelEndBatch(
+    CookiesTreeModel* model) {
+  DCHECK(batch_update_);
+  CocoaCookieTreeNode* root = CocoaNodeFromTreeNode(model->GetRoot());
+  [window_controller_ setCocoaTreeModel:root];
+  batch_update_ = false;
+}
+
+void CookiesTreeModelObserverBridge::InvalidateCocoaModel() {
+  [[[window_controller_ cocoaTreeModel] mutableChildren] removeAllObjects];
+}
+
+CocoaCookieTreeNode* CookiesTreeModelObserverBridge::CocoaNodeFromTreeNode(
+    ui::TreeModelNode* node) {
+  CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
+  return [[[CocoaCookieTreeNode alloc] initWithNode:cookie_node] autorelease];
+}
+
+// Does breadth-first search on the tree to find |node|. This method is most
+// commonly used to find origin/folder nodes, which are at the first level off
+// the root (hence breadth-first search).
+CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode(
+    ui::TreeModelNode* target, CocoaCookieTreeNode* start) {
+  if (!start) {
+    start = [window_controller_ cocoaTreeModel];
+  }
+  if ([start treeNode] == target) {
+    return start;
+  }
+
+  // Enqueue the root node of the search (sub-)tree.
+  std::queue<CocoaCookieTreeNode*> horizon;
+  horizon.push(start);
+
+  // Loop until we've looked at every node or we found the target.
+  while (!horizon.empty()) {
+    // Dequeue the item at the front.
+    CocoaCookieTreeNode* node = horizon.front();
+    horizon.pop();
+
+    // If this is the droid we're looking for, report it.
+    if ([node treeNode] == target)
+      return node;
+
+    // "Move along, move along." by adding all child nodes to the queue.
+    if (![node isLeaf]) {
+      NSArray* children = [node children];
+      for (CocoaCookieTreeNode* child in children) {
+        horizon.push(child);
+      }
+    }
+  }
+
+  return nil;  // We couldn't find the node.
+}
+
+// Returns whether or not the Cocoa tree model is built.
+bool CookiesTreeModelObserverBridge::HasCocoaModel() {
+  return ([[[window_controller_ cocoaTreeModel] children] count] > 0U);
+}
+
+#pragma mark Window Controller
+
+@implementation CookiesWindowController
+
+@synthesize removeButtonEnabled = removeButtonEnabled_;
+@synthesize treeController = treeController_;
+
+- (id)initWithProfile:(Profile*)profile
+       databaseHelper:(BrowsingDataDatabaseHelper*)databaseHelper
+        storageHelper:(BrowsingDataLocalStorageHelper*)storageHelper
+       appcacheHelper:(BrowsingDataAppCacheHelper*)appcacheHelper
+      indexedDBHelper:(BrowsingDataIndexedDBHelper*)indexedDBHelper {
+  DCHECK(profile);
+  NSString* nibpath = [base::mac::MainAppBundle() pathForResource:@"Cookies"
+                                                          ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    profile_ = profile;
+    databaseHelper_ = databaseHelper;
+    storageHelper_ = storageHelper;
+    appcacheHelper_ = appcacheHelper;
+    indexedDBHelper_ = indexedDBHelper;
+
+    [self loadTreeModelFromProfile];
+
+    // Register for Clear Browsing Data controller so we update appropriately.
+    ClearBrowsingDataController* clearingController =
+        [ClearBrowsingDataController controllerForProfile:profile_];
+    if (clearingController) {
+      NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+      [center addObserver:self
+                 selector:@selector(clearBrowsingDataNotification:)
+                     name:kClearBrowsingDataControllerDidDelete
+                   object:clearingController];
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
+- (void)awakeFromNib {
+  DCHECK([self window]);
+  DCHECK_EQ(self, [[self window] delegate]);
+
+  detailsViewController_.reset([[CookieDetailsViewController alloc] init]);
+
+  NSView* detailView = [detailsViewController_.get() view];
+  NSRect viewFrameRect = [cookieDetailsViewPlaceholder_ frame];
+  [[detailsViewController_.get() view] setFrame:viewFrameRect];
+  [[cookieDetailsViewPlaceholder_ superview]
+      replaceSubview:cookieDetailsViewPlaceholder_
+                with:detailView];
+
+  [detailsViewController_ configureBindingsForTreeController:treeController_];
+}
+
+- (void)windowWillClose:(NSNotification*)notif {
+  [searchField_ setTarget:nil];
+  [outlineView_ setDelegate:nil];
+  [self autorelease];
+}
+
+- (void)attachSheetTo:(NSWindow*)window {
+  [NSApp beginSheet:[self window]
+     modalForWindow:window
+      modalDelegate:self
+     didEndSelector:@selector(sheetEndSheet:returnCode:contextInfo:)
+        contextInfo:nil];
+}
+
+- (void)sheetEndSheet:(NSWindow*)sheet
+          returnCode:(NSInteger)returnCode
+         contextInfo:(void*)context {
+  [sheet close];
+  [sheet orderOut:self];
+}
+
+- (IBAction)updateFilter:(id)sender {
+  DCHECK([sender isKindOfClass:[NSSearchField class]]);
+  NSString* string = [sender stringValue];
+  // Invalidate the model here because all the nodes are going to be removed
+  // in UpdateSearchResults(). This could lead to there temporarily being
+  // invalid pointers in the Cocoa model.
+  modelObserver_->InvalidateCocoaModel();
+  treeModel_->UpdateSearchResults(base::SysNSStringToWide(string));
+}
+
+- (IBAction)deleteCookie:(id)sender {
+  DCHECK_EQ(1U, [[treeController_ selectedObjects] count]);
+  [self deleteNodeAtIndexPath:[treeController_ selectionIndexPath]];
+}
+
+// This will delete the Cocoa model node as well as the backing model object at
+// the specified index path in the Cocoa model. If the node that was deleted
+// was the sole child of the parent node, this will be called recursively to
+// delete empty parents.
+- (void)deleteNodeAtIndexPath:(NSIndexPath*)path {
+  NSTreeNode* treeNode =
+      [[treeController_ arrangedObjects] descendantNodeAtIndexPath:path];
+  if (!treeNode)
+    return;
+
+  CocoaCookieTreeNode* node = [treeNode representedObject];
+  CookieTreeNode* cookie = static_cast<CookieTreeNode*>([node treeNode]);
+  treeModel_->DeleteCookieNode(cookie);
+  // If there is a next cookie, this will select it because items will slide
+  // up. If there is no next cookie, this is a no-op.
+  [treeController_ setSelectionIndexPath:path];
+  // If the above setting of the selection was in fact a no-op, find the next
+  // node to select.
+  if (![[treeController_ selectedObjects] count]) {
+    NSUInteger lastIndex = [path indexAtPosition:[path length] - 1];
+    if (lastIndex != 0) {
+      // If there any nodes remaining, select the node that is in the list
+      // before this one.
+      path = [path indexPathByRemovingLastIndex];
+      path = [path indexPathByAddingIndex:lastIndex - 1];
+      [treeController_ setSelectionIndexPath:path];
+    }
+  }
+}
+
+- (IBAction)deleteAllCookies:(id)sender {
+  // Preemptively delete all cookies in the Cocoa model.
+  modelObserver_->InvalidateCocoaModel();
+  treeModel_->DeleteAllStoredObjects();
+}
+
+- (IBAction)closeSheet:(id)sender {
+  [NSApp endSheet:[self window]];
+}
+
+- (void)clearBrowsingDataNotification:(NSNotification*)notif {
+  NSNumber* removeMask =
+      [[notif userInfo] objectForKey:kClearBrowsingDataControllerRemoveMask];
+  if ([removeMask intValue] & BrowsingDataRemover::REMOVE_COOKIES) {
+    [self loadTreeModelFromProfile];
+  }
+}
+
+// Override keyDown on the controller (which is the first responder) to allow
+// both backspace and delete to be captured by the Remove button.
+- (void)keyDown:(NSEvent*)theEvent {
+  NSString* keys = [theEvent characters];
+  if ([keys length]) {
+    unichar key = [keys characterAtIndex:0];
+    // The button has a key equivalent of backspace, so examine this event for
+    // forward delete.
+    if ((key == NSDeleteCharacter || key == NSDeleteFunctionKey) &&
+        [self removeButtonEnabled]) {
+      [removeButton_ performClick:self];
+      return;
+    }
+  }
+  [super keyDown:theEvent];
+}
+
+#pragma mark Getters and Setters
+
+- (CocoaCookieTreeNode*)cocoaTreeModel {
+  return cocoaTreeModel_.get();
+}
+- (void)setCocoaTreeModel:(CocoaCookieTreeNode*)model {
+  cocoaTreeModel_.reset([model retain]);
+}
+
+- (CookiesTreeModel*)treeModel {
+  return treeModel_.get();
+}
+
+#pragma mark Outline View Delegate
+
+- (void)outlineView:(NSOutlineView*)outlineView
+    willDisplayCell:(id)cell
+     forTableColumn:(NSTableColumn*)tableColumn
+               item:(id)item {
+  CocoaCookieTreeNode* node = [item representedObject];
+  int index = treeModel_->GetIconIndex([node treeNode]);
+  NSImage* icon = nil;
+  if (index >= 0)
+    icon = [icons_ objectAtIndex:index];
+  else
+    icon = [icons_ lastObject];
+  [(ImageAndTextCell*)cell setImage:icon];
+}
+
+- (void)outlineViewItemDidExpand:(NSNotification*)notif {
+  NSTreeNode* item = [[notif userInfo] objectForKey:@"NSObject"];
+  CocoaCookieTreeNode* node = [item representedObject];
+  NSArray* children = [node children];
+  if ([children count] == 1U) {
+    // The node that will expand has one child. Do the user a favor and expand
+    // that node (saving her a click) if it is non-leaf.
+    CocoaCookieTreeNode* child = [children lastObject];
+    if (![child isLeaf]) {
+      NSOutlineView* outlineView = [notif object];
+      // Tell the OutlineView to expand the NSTreeNode, not the model object.
+      children = [item childNodes];
+      DCHECK_EQ([children count], 1U);
+      [outlineView expandItem:[children lastObject]];
+      // Select the first node in that child set.
+      NSTreeNode* folderChild = [children lastObject];
+      if ([[folderChild childNodes] count] > 0) {
+        NSTreeNode* firstCookieChild =
+            [[folderChild childNodes] objectAtIndex:0];
+        [treeController_ setSelectionIndexPath:[firstCookieChild indexPath]];
+      }
+    }
+  }
+}
+
+- (void)outlineViewSelectionDidChange:(NSNotification*)notif {
+  // Multi-selection should be disabled in the UI, but for sanity, double-check
+  // that they can't do it here.
+  NSArray* selectedObjects = [treeController_ selectedObjects];
+  NSUInteger count = [selectedObjects count];
+  if (count != 1U) {
+    DCHECK_LT(count, 1U) << "User was able to select more than 1 cookie node!";
+    [self setRemoveButtonEnabled:NO];
+    return;
+  }
+
+  // Go through the selection's indexPath and make sure that the node that is
+  // being referenced actually exists in the Cocoa model.
+  NSIndexPath* selection = [treeController_ selectionIndexPath];
+  NSUInteger length = [selection length];
+  CocoaCookieTreeNode* node = [self cocoaTreeModel];
+  for (NSUInteger i = 0; i < length; ++i) {
+    NSUInteger childIndex = [selection indexAtPosition:i];
+    if (childIndex >= [[node children] count]) {
+      [self setRemoveButtonEnabled:NO];
+      return;
+    }
+    node = [[node children] objectAtIndex:childIndex];
+  }
+
+  // If there is a valid selection, make sure that the remove
+  // button is enabled.
+  [self setRemoveButtonEnabled:YES];
+}
+
+#pragma mark Unit Testing
+
+- (CookiesTreeModelObserverBridge*)modelObserver {
+  return modelObserver_.get();
+}
+
+- (NSArray*)icons {
+  return icons_.get();
+}
+
+// Re-initializes the |treeModel_|, creates a new observer for it, and re-
+// builds the |cocoaTreeModel_|. We use this to initialize the controller and
+// to rebuild after the user clears browsing data. Because the models get
+// clobbered, we rebuild the icon cache for safety (though they do not change).
+- (void)loadTreeModelFromProfile {
+  treeModel_.reset(new CookiesTreeModel(
+      profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(),
+      databaseHelper_,
+      storageHelper_,
+      NULL,
+      appcacheHelper_,
+      indexedDBHelper_));
+  modelObserver_.reset(new CookiesTreeModelObserverBridge(self));
+  treeModel_->AddCookiesTreeObserver(modelObserver_.get());
+
+  // Convert the model's icons from Skia to Cocoa.
+  std::vector<SkBitmap> skiaIcons;
+  treeModel_->GetIcons(&skiaIcons);
+  icons_.reset([[NSMutableArray alloc] init]);
+  for (std::vector<SkBitmap>::iterator it = skiaIcons.begin();
+       it != skiaIcons.end(); ++it) {
+    [icons_ addObject:gfx::SkBitmapToNSImage(*it)];
+  }
+
+  // Default icon will be the last item in the array.
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  // TODO(rsesek): Rename this resource now that it's in multiple places.
+  [icons_ addObject:rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER)];
+
+  // Create the Cocoa model.
+  CookieTreeNode* root = static_cast<CookieTreeNode*>(treeModel_->GetRoot());
+  scoped_nsobject<CocoaCookieTreeNode> model(
+      [[CocoaCookieTreeNode alloc] initWithNode:root]);
+  [self setCocoaTreeModel:model.get()];  // Takes ownership.
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/cookies_window_controller_unittest.mm b/chrome/browser/ui/cocoa/options/cookies_window_controller_unittest.mm
new file mode 100644
index 0000000..119f67b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/cookies_window_controller_unittest.mm
@@ -0,0 +1,710 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "chrome/browser/mock_browsing_data_appcache_helper.h"
+#include "chrome/browser/mock_browsing_data_database_helper.h"
+#include "chrome/browser/mock_browsing_data_indexed_db_helper.h"
+#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/cookies_window_controller.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "chrome/test/testing_profile.h"
+#include "googleurl/src/gurl.h"
+#include "grit/generated_resources.h"
+#include "net/url_request/url_request_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/models/tree_model.h"
+
+// Used to test FindCocoaNode. This only sets the title and node, without
+// initializing any other members.
+@interface FakeCocoaCookieTreeNode : CocoaCookieTreeNode {
+  ui::TreeModelNode* testNode_;
+}
+- (id)initWithTreeNode:(ui::TreeModelNode*)node;
+@end
+@implementation FakeCocoaCookieTreeNode
+- (id)initWithTreeNode:(ui::TreeModelNode*)node {
+  if ((self = [super init])) {
+    testNode_ = node;
+    children_.reset([[NSMutableArray alloc] init]);
+  }
+  return self;
+}
+- (ui::TreeModelNode*)treeNode {
+  return testNode_;
+}
+@end
+
+namespace {
+
+class CookiesWindowControllerTest : public CocoaTest {
+ public:
+
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    TestingProfile* profile = browser_helper_.profile();
+    profile->CreateRequestContext();
+    database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
+    local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
+    appcache_helper_ = new MockBrowsingDataAppCacheHelper(profile);
+    indexed_db_helper_ = new MockBrowsingDataIndexedDBHelper(profile);
+    controller_.reset(
+        [[CookiesWindowController alloc] initWithProfile:profile
+                                          databaseHelper:database_helper_
+                                           storageHelper:local_storage_helper_
+                                          appcacheHelper:appcache_helper_
+                                         indexedDBHelper:indexed_db_helper_]
+    );
+  }
+
+  virtual void TearDown() {
+    CocoaTest::TearDown();
+  }
+
+  CocoaCookieTreeNode* CocoaNodeFromTreeNode(ui::TreeModelNode* node) {
+    return [controller_ modelObserver]->CocoaNodeFromTreeNode(node);
+  }
+
+  CocoaCookieTreeNode* FindCocoaNode(ui::TreeModelNode* node,
+                                     CocoaCookieTreeNode* start) {
+    return [controller_ modelObserver]->FindCocoaNode(node, start);
+  }
+
+ protected:
+  BrowserTestHelper browser_helper_;
+  scoped_nsobject<CookiesWindowController> controller_;
+  MockBrowsingDataDatabaseHelper* database_helper_;
+  MockBrowsingDataLocalStorageHelper* local_storage_helper_;
+  MockBrowsingDataAppCacheHelper* appcache_helper_;
+  MockBrowsingDataIndexedDBHelper* indexed_db_helper_;
+};
+
+TEST_F(CookiesWindowControllerTest, Construction) {
+  std::vector<SkBitmap> skia_icons;
+  [controller_ treeModel]->GetIcons(&skia_icons);
+
+  EXPECT_EQ([[controller_ icons] count], skia_icons.size() + 1U);
+}
+
+TEST_F(CookiesWindowControllerTest, FindCocoaNodeRoot) {
+  scoped_ptr< ui::TreeNodeWithValue<int> > search(
+      new ui::TreeNodeWithValue<int>(42));
+  scoped_nsobject<FakeCocoaCookieTreeNode> node(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:search.get()]);
+  EXPECT_EQ(node.get(), FindCocoaNode(search.get(), node.get()));
+}
+
+TEST_F(CookiesWindowControllerTest, FindCocoaNodeImmediateChild) {
+  scoped_ptr< ui::TreeNodeWithValue<int> > parent(
+      new ui::TreeNodeWithValue<int>(100));
+  scoped_ptr< ui::TreeNodeWithValue<int> > child1(
+      new ui::TreeNodeWithValue<int>(10));
+  scoped_ptr< ui::TreeNodeWithValue<int> > child2(
+      new ui::TreeNodeWithValue<int>(20));
+  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaParent(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:parent.get()]);
+  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild1(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child1.get()]);
+  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild2(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child2.get()]);
+  [[cocoaParent mutableChildren] addObject:cocoaChild1.get()];
+  [[cocoaParent mutableChildren] addObject:cocoaChild2.get()];
+
+  EXPECT_EQ(cocoaChild2.get(), FindCocoaNode(child2.get(), cocoaParent.get()));
+}
+
+TEST_F(CookiesWindowControllerTest, FindCocoaNodeRecursive) {
+  scoped_ptr< ui::TreeNodeWithValue<int> > parent(
+      new ui::TreeNodeWithValue<int>(100));
+  scoped_ptr< ui::TreeNodeWithValue<int> > child1(
+      new ui::TreeNodeWithValue<int>(10));
+  scoped_ptr< ui::TreeNodeWithValue<int> > child2(
+      new ui::TreeNodeWithValue<int>(20));
+  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaParent(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:parent.get()]);
+  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild1(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child1.get()]);
+  scoped_nsobject<FakeCocoaCookieTreeNode> cocoaChild2(
+      [[FakeCocoaCookieTreeNode alloc] initWithTreeNode:child2.get()]);
+  [[cocoaParent mutableChildren] addObject:cocoaChild1.get()];
+  [[cocoaChild1 mutableChildren] addObject:cocoaChild2.get()];
+
+  EXPECT_EQ(cocoaChild2.get(), FindCocoaNode(child2.get(), cocoaParent.get()));
+}
+
+TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeCookie) {
+  net::CookieMonster* cm = browser_helper_.profile()->GetCookieMonster();
+  cm->SetCookie(GURL("http://foo.com"), "A=B");
+  CookiesTreeModel model(cm, database_helper_, local_storage_helper_, nil, nil,
+      nil);
+
+  // Root --> foo.com --> Cookies --> A. Create node for 'A'.
+  ui::TreeModelNode* node =
+      model.GetRoot()->GetChild(0)->GetChild(0)->GetChild(0);
+  CocoaCookieTreeNode* cookie = CocoaNodeFromTreeNode(node);
+
+  CocoaCookieDetails* details = [cookie details];
+  EXPECT_NSEQ(@"B", [details content]);
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_EXPIRES_SESSION),
+              [details expires]);
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_SENDFOR_ANY),
+              [details sendFor]);
+  EXPECT_NSEQ(@"A", [cookie title]);
+  EXPECT_NSEQ(@"A", [details name]);
+  EXPECT_NSEQ(@"/", [details path]);
+  EXPECT_EQ(0U, [[cookie children] count]);
+  EXPECT_TRUE([details created]);
+  EXPECT_TRUE([cookie isLeaf]);
+  EXPECT_EQ(node, [cookie treeNode]);
+}
+
+TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeRecursive) {
+  net::CookieMonster* cm = browser_helper_.profile()->GetCookieMonster();
+  cm->SetCookie(GURL("http://foo.com"), "A=B");
+  CookiesTreeModel model(cm, database_helper_, local_storage_helper_, nil, nil,
+      nil);
+
+  // Root --> foo.com --> Cookies --> A. Create node for 'foo.com'.
+  CookieTreeNode* node = model.GetRoot()->GetChild(0);
+  CocoaCookieTreeNode* domain = CocoaNodeFromTreeNode(node);
+  CocoaCookieTreeNode* cookies = [[domain children] objectAtIndex:0];
+  CocoaCookieTreeNode* cookie = [[cookies children] objectAtIndex:0];
+
+  // Test domain-level node.
+  EXPECT_NSEQ(@"foo.com", [domain title]);
+
+  EXPECT_FALSE([domain isLeaf]);
+  EXPECT_EQ(1U, [[domain children] count]);
+  EXPECT_EQ(node, [domain treeNode]);
+
+  // Test "Cookies" folder node.
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIES), [cookies title]);
+  EXPECT_FALSE([cookies isLeaf]);
+  EXPECT_EQ(1U, [[cookies children] count]);
+  EXPECT_EQ(node->GetChild(0), [cookies treeNode]);
+
+  // Test cookie node. This is the same as CocoaNodeFromTreeNodeCookie.
+  CocoaCookieDetails* details = [cookie details];
+  EXPECT_NSEQ(@"B", [details content]);
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_EXPIRES_SESSION),
+              [details expires]);
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIE_SENDFOR_ANY),
+              [details sendFor]);
+  EXPECT_NSEQ(@"A", [cookie title]);
+  EXPECT_NSEQ(@"A", [details name]);
+  EXPECT_NSEQ(@"/", [details path]);
+  EXPECT_NSEQ(@"foo.com", [details domain]);
+  EXPECT_EQ(0U, [[cookie children] count]);
+  EXPECT_TRUE([details created]);
+  EXPECT_TRUE([cookie isLeaf]);
+  EXPECT_EQ(node->GetChild(0)->GetChild(0), [cookie treeNode]);
+}
+
+TEST_F(CookiesWindowControllerTest, TreeNodesAdded) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+
+  // Root --> foo.com --> Cookies.
+  NSMutableArray* cocoa_children =
+      [[[[[[controller_ cocoaTreeModel] children] objectAtIndex:0]
+          children] objectAtIndex:0] mutableChildren];
+  EXPECT_EQ(1U, [cocoa_children count]);
+
+  // Create some cookies.
+  cm->SetCookie(url, "C=D");
+  cm->SetCookie(url, "E=F");
+
+  net::CookieList list = cm->GetAllCookies();
+  CookiesTreeModel* model = [controller_ treeModel];
+  // Root --> foo.com --> Cookies.
+  CookieTreeNode* parent = model->GetRoot()->GetChild(0)->GetChild(0);
+
+  ASSERT_EQ(3U, list.size());
+
+  // Add the cookie nodes.
+  CookieTreeCookieNode* cnode = new CookieTreeCookieNode(&list[1]);
+  parent->Add(1, cnode);  // |parent| takes ownership.
+  cnode = new CookieTreeCookieNode(&list[2]);
+  parent->Add(2, cnode);
+
+  // Manually notify the observer.
+  [controller_ modelObserver]->TreeNodesAdded(model, parent, 1, 2);
+
+  // Check that we have created 2 more Cocoa nodes.
+  EXPECT_EQ(3U, [cocoa_children count]);
+}
+
+TEST_F(CookiesWindowControllerTest, TreeNodesRemoved) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+  cm->SetCookie(url, "C=D");
+  cm->SetCookie(url, "E=F");
+
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+
+  // Root --> foo.com --> Cookies.
+  NSMutableArray* cocoa_children =
+      [[[[[[controller_ cocoaTreeModel] children] objectAtIndex:0]
+          children] objectAtIndex:0] mutableChildren];
+  EXPECT_EQ(3U, [cocoa_children count]);
+
+  CookiesTreeModel* model = [controller_ treeModel];
+  // Root --> foo.com --> Cookies.
+  CookieTreeNode* parent = model->GetRoot()->GetChild(0)->GetChild(0);
+
+  // Pretend to remove the nodes.
+  [controller_ modelObserver]->TreeNodesRemoved(model, parent, 1, 2);
+
+  EXPECT_EQ(1U, [cocoa_children count]);
+
+  NSString* title = [[[cocoa_children objectAtIndex:0] details] name];
+  EXPECT_NSEQ(@"A", title);
+}
+
+TEST_F(CookiesWindowControllerTest, TreeNodeChanged) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+
+  CookiesTreeModel* model = [controller_ treeModel];
+  // Root --> foo.com --> Cookies.
+  CookieTreeNode* node = model->GetRoot()->GetChild(0)->GetChild(0);
+
+  // Root --> foo.com --> Cookies.
+  CocoaCookieTreeNode* cocoa_node =
+      [[[[[controller_ cocoaTreeModel] children] objectAtIndex:0]
+          children] objectAtIndex:0];
+
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_COOKIES),
+              [cocoa_node title]);
+
+  // Fake update the cookie folder's title. This would never happen in reality,
+  // but it tests the code path that ultimately calls CocoaNodeFromTreeNode,
+  // which is tested elsewhere.
+  node->SetTitle(ASCIIToUTF16("Silly Change"));
+  [controller_ modelObserver]->TreeNodeChanged(model, node);
+
+  EXPECT_NSEQ(@"Silly Change", [cocoa_node title]);
+}
+
+TEST_F(CookiesWindowControllerTest, DeleteCookie) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+  cm->SetCookie(url, "C=D");
+  cm->SetCookie(GURL("http://google.com"), "E=F");
+
+  // This will clean itself up when we call |-closeSheet:|. If we reset the
+  // scoper, we'd get a double-free.
+  CookiesWindowController* controller =
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_];
+  [controller attachSheetTo:test_window()];
+  NSTreeController* treeController = [controller treeController];
+
+  // Select cookie A.
+  NSUInteger pathA[3] = {0, 0, 0};
+  NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:pathA length:3];
+  [treeController setSelectionIndexPath:indexPath];
+
+  // Press the "Delete" button.
+  [controller deleteCookie:nil];
+
+  // Root --> foo.com --> Cookies.
+  NSArray* cookies = [[[[[[controller cocoaTreeModel] children]
+      objectAtIndex:0] children] objectAtIndex:0] children];
+  EXPECT_EQ(1U, [cookies count]);
+  EXPECT_NSEQ(@"C", [[cookies lastObject] title]);
+  EXPECT_NSEQ(indexPath, [treeController selectionIndexPath]);
+
+  // Select cookie E.
+  NSUInteger pathE[3] = {1, 0, 0};
+  indexPath = [NSIndexPath indexPathWithIndexes:pathE length:3];
+  [treeController setSelectionIndexPath:indexPath];
+
+  // Perform delete.
+  [controller deleteCookie:nil];
+
+  // Make sure that both the domain level node and the Cookies folder node got
+  // deleted because there was only one leaf node.
+  EXPECT_EQ(1U, [[[controller cocoaTreeModel] children] count]);
+
+  // Select cookie C.
+  NSUInteger pathC[3] = {0, 0, 0};
+  indexPath = [NSIndexPath indexPathWithIndexes:pathC length:3];
+  [treeController setSelectionIndexPath:indexPath];
+
+  // Perform delete.
+  [controller deleteCookie:nil];
+
+  // Make sure the world didn't explode and that there's nothing in the tree.
+  EXPECT_EQ(0U, [[[controller cocoaTreeModel] children] count]);
+
+  [controller closeSheet:nil];
+}
+
+TEST_F(CookiesWindowControllerTest, DidExpandItem) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+  cm->SetCookie(url, "C=D");
+
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+
+  // Root --> foo.com.
+  CocoaCookieTreeNode* foo =
+      [[[controller_ cocoaTreeModel] children] objectAtIndex:0];
+
+  // Create the objects we are going to be testing with.
+  id outlineView = [OCMockObject mockForClass:[NSOutlineView class]];
+  id treeNode = [OCMockObject mockForClass:[NSTreeNode class]];
+  NSTreeNode* childTreeNode =
+      [NSTreeNode treeNodeWithRepresentedObject:[[foo children] lastObject]];
+  NSArray* fakeChildren = [NSArray arrayWithObject:childTreeNode];
+
+  // Set up the mock object.
+  [[[treeNode stub] andReturn:foo] representedObject];
+  [[[treeNode stub] andReturn:fakeChildren] childNodes];
+
+  // Create a fake "ItemDidExpand" notification.
+  NSDictionary* userInfo = [NSDictionary dictionaryWithObject:treeNode
+                                                       forKey:@"NSObject"];
+  NSNotification* notif =
+      [NSNotification notificationWithName:@"ItemDidExpandNotification"
+                                    object:outlineView
+                                  userInfo:userInfo];
+
+  // Make sure we work correctly.
+  [[outlineView expect] expandItem:childTreeNode];
+  [controller_ outlineViewItemDidExpand:notif];
+  [outlineView verify];
+}
+
+TEST_F(CookiesWindowControllerTest, ClearBrowsingData) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+  cm->SetCookie(url, "C=D");
+  cm->SetCookie(url, "E=F");
+
+  id mock = [OCMockObject partialMockForObject:controller_.get()];
+  [[mock expect] loadTreeModelFromProfile];
+
+  NSNumber* mask =
+      [NSNumber numberWithInt:BrowsingDataRemover::REMOVE_COOKIES];
+  NSDictionary* userInfo =
+      [NSDictionary dictionaryWithObject:mask
+                                forKey:kClearBrowsingDataControllerRemoveMask];
+  NSNotification* notif =
+    [NSNotification notificationWithName:kClearBrowsingDataControllerDidDelete
+                                  object:nil
+                                userInfo:userInfo];
+  [controller_ clearBrowsingDataNotification:notif];
+
+  [mock verify];
+}
+
+// This test has been flaky under Valgrind and turns the bot red since r38504.
+// Under Mac Tests 10.5, it occasionally reports:
+//   malloc: *** error for object 0x31e0468: Non-aligned pointer being freed
+//   *** set a breakpoint in malloc_error_break to debug
+// Attempts to reproduce locally were not successful. This code is likely
+// changing in the future, so it's marked flaky for now. http://crbug.com/35327
+TEST_F(CookiesWindowControllerTest, FLAKY_RemoveButtonEnabled) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(url, "A=B");
+  cm->SetCookie(url, "C=D");
+
+  // This will clean itself up when we call |-closeSheet:|. If we reset the
+  // scoper, we'd get a double-free.
+  database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
+  local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
+  local_storage_helper_->AddLocalStorageSamples();
+  CookiesWindowController* controller =
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_];
+  local_storage_helper_->Notify();
+  [controller attachSheetTo:test_window()];
+
+  // Nothing should be selected right now.
+  EXPECT_FALSE([controller removeButtonEnabled]);
+
+  {
+    // Pretend to select cookie A.
+    NSUInteger path[3] = {0, 0, 0};
+    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
+    [[controller treeController] setSelectionIndexPath:indexPath];
+    [controller outlineViewSelectionDidChange:nil];
+    EXPECT_TRUE([controller removeButtonEnabled]);
+  }
+
+  {
+    // Pretend to select cookie C.
+    NSUInteger path[3] = {0, 0, 1};
+    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
+    [[controller treeController] setSelectionIndexPath:indexPath];
+    [controller outlineViewSelectionDidChange:nil];
+    EXPECT_TRUE([controller removeButtonEnabled]);
+  }
+
+  {
+    // Select a local storage node.
+    NSUInteger path[3] = {2, 0, 0};
+    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
+    [[controller treeController] setSelectionIndexPath:indexPath];
+    [controller outlineViewSelectionDidChange:nil];
+    EXPECT_TRUE([controller removeButtonEnabled]);
+  }
+
+  {
+    // Pretend to select something that isn't there!
+    NSUInteger path[3] = {0, 0, 2};
+    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
+    [[controller treeController] setSelectionIndexPath:indexPath];
+    [controller outlineViewSelectionDidChange:nil];
+    EXPECT_FALSE([controller removeButtonEnabled]);
+  }
+
+  {
+    // Try selecting something that doesn't exist again.
+    NSUInteger path[3] = {7, 1, 4};
+    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:path length:3];
+    [[controller treeController] setSelectionIndexPath:indexPath];
+    [controller outlineViewSelectionDidChange:nil];
+    EXPECT_FALSE([controller removeButtonEnabled]);
+  }
+
+  [controller closeSheet:nil];
+}
+
+TEST_F(CookiesWindowControllerTest, UpdateFilter) {
+  const GURL url = GURL("http://foo.com");
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(GURL("http://a.com"), "A=B");
+  cm->SetCookie(GURL("http://aa.com"), "C=D");
+  cm->SetCookie(GURL("http://b.com"), "E=F");
+  cm->SetCookie(GURL("http://d.com"), "G=H");
+  cm->SetCookie(GURL("http://dd.com"), "I=J");
+
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+
+  // Make sure we registered all five cookies.
+  EXPECT_EQ(5U, [[[controller_ cocoaTreeModel] children] count]);
+
+  NSSearchField* field =
+      [[NSSearchField alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+
+  // Make sure we still have five cookies.
+  [field setStringValue:@""];
+  [controller_ updateFilter:field];
+  EXPECT_EQ(5U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Search for "a".
+  [field setStringValue:@"a"];
+  [controller_ updateFilter:field];
+  EXPECT_EQ(2U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Search for "b".
+  [field setStringValue:@"b"];
+  [controller_ updateFilter:field];
+  EXPECT_EQ(1U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Search for "d".
+  [field setStringValue:@"d"];
+  [controller_ updateFilter:field];
+  EXPECT_EQ(2U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Search for "e".
+  [field setStringValue:@"e"];
+  [controller_ updateFilter:field];
+  EXPECT_EQ(0U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Search for "aa".
+  [field setStringValue:@"aa"];
+  [controller_ updateFilter:field];
+  EXPECT_EQ(1U, [[[controller_ cocoaTreeModel] children] count]);
+}
+
+TEST_F(CookiesWindowControllerTest, CreateDatabaseStorageNodes) {
+  TestingProfile* profile = browser_helper_.profile();
+  database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
+  local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
+  database_helper_->AddDatabaseSamples();
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+  database_helper_->Notify();
+
+  ASSERT_EQ(2U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Root --> gdbhost1.
+  CocoaCookieTreeNode* node =
+      [[[controller_ cocoaTreeModel] children] objectAtIndex:0];
+  EXPECT_NSEQ(@"gdbhost1", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // host1 --> Web Databases.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_WEB_DATABASES), [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // Database Storage --> db1.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(@"db1", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeTreeDatabase, [node nodeType]);
+  CocoaCookieDetails* details = [node details];
+  EXPECT_NSEQ(@"description 1", [details databaseDescription]);
+  EXPECT_TRUE([details lastModified]);
+  EXPECT_TRUE([details fileSize]);
+
+  // Root --> gdbhost2.
+  node =
+      [[[controller_ cocoaTreeModel] children] objectAtIndex:1];
+  EXPECT_NSEQ(@"gdbhost2", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // host1 --> Web Databases.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_WEB_DATABASES), [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // Database Storage --> db2.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(@"db2", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeTreeDatabase, [node nodeType]);
+  details = [node details];
+  EXPECT_NSEQ(@"description 2", [details databaseDescription]);
+  EXPECT_TRUE([details lastModified]);
+  EXPECT_TRUE([details fileSize]);
+}
+
+TEST_F(CookiesWindowControllerTest, CreateLocalStorageNodes) {
+  TestingProfile* profile = browser_helper_.profile();
+  net::CookieMonster* cm = profile->GetCookieMonster();
+  cm->SetCookie(GURL("http://google.com"), "A=B");
+  cm->SetCookie(GURL("http://dev.chromium.org"), "C=D");
+  database_helper_ = new MockBrowsingDataDatabaseHelper(profile);
+  local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
+  local_storage_helper_->AddLocalStorageSamples();
+  controller_.reset(
+      [[CookiesWindowController alloc] initWithProfile:profile
+                                        databaseHelper:database_helper_
+                                         storageHelper:local_storage_helper_
+                                        appcacheHelper:appcache_helper_
+                                       indexedDBHelper:indexed_db_helper_]);
+  local_storage_helper_->Notify();
+
+  ASSERT_EQ(4U, [[[controller_ cocoaTreeModel] children] count]);
+
+  // Root --> host1.
+  CocoaCookieTreeNode* node =
+      [[[controller_ cocoaTreeModel] children] objectAtIndex:2];
+  EXPECT_NSEQ(@"host1", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // host1 --> Local Storage.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_LOCAL_STORAGE), [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // Local Storage --> http://host1:1/.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(@"http://host1:1/", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeTreeLocalStorage, [node nodeType]);
+  EXPECT_NSEQ(@"http://host1:1/", [[node details] domain]);
+  EXPECT_TRUE([[node details] lastModified]);
+  EXPECT_TRUE([[node details] fileSize]);
+
+  // Root --> host2.
+  node =
+      [[[controller_ cocoaTreeModel] children] objectAtIndex:3];
+  EXPECT_NSEQ(@"host2", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // host2 --> Local Storage.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_COOKIES_LOCAL_STORAGE), [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeFolder, [node nodeType]);
+  EXPECT_EQ(1U, [[node children] count]);
+
+  // Local Storage --> http://host2:2/.
+  node = [[node children] lastObject];
+  EXPECT_NSEQ(@"http://host2:2/", [node title]);
+  EXPECT_EQ(kCocoaCookieDetailsTypeTreeLocalStorage, [node nodeType]);
+  EXPECT_NSEQ(@"http://host2:2/", [[node details] domain]);
+  EXPECT_TRUE([[node details] lastModified]);
+  EXPECT_TRUE([[node details] fileSize]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/options/custom_home_pages_model.h b/chrome/browser/ui/cocoa/options/custom_home_pages_model.h
new file mode 100644
index 0000000..1b4385a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/custom_home_pages_model.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_OPTIONS_CUSTOM_HOME_PAGES_MODEL_H_
+#define CHROME_BROWSER_UI_COCOA_OPTIONS_CUSTOM_HOME_PAGES_MODEL_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include <vector>
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/history/history.h"
+#include "googleurl/src/gurl.h"
+
+class Profile;
+
+// The model for the "custom home pages" table in preferences. Contains a list
+// of CustomHomePageEntry objects. This is intended to be used with Cocoa
+// bindings.
+//
+// The supported binding is |customHomePages|, a to-many relationship which
+// can be observed with an array controller.
+
+@interface CustomHomePagesModel : NSObject {
+ @private
+  scoped_nsobject<NSMutableArray> entries_;
+  Profile* profile_;  // weak, used for loading favicons
+}
+
+// Initialize with |profile|, which must not be NULL. The profile is used for
+// loading favicons for urls.
+- (id)initWithProfile:(Profile*)profile;
+
+// Get/set the urls the model currently contains as a group. Only one change
+// notification will be sent.
+- (std::vector<GURL>)URLs;
+- (void)setURLs:(const std::vector<GURL>&)urls;
+
+// Reloads the URLs from their stored state. This will notify using KVO
+// |customHomePages|.
+- (void)reloadURLs;
+
+// Validates the set of URLs stored in the model. The user may have input bad
+// data. This function removes invalid entries from the model, which will result
+// in anyone observing being updated.
+- (void)validateURLs;
+
+// For binding |customHomePages| to a mutable array controller.
+- (NSUInteger)countOfCustomHomePages;
+- (id)objectInCustomHomePagesAtIndex:(NSUInteger)index;
+- (void)insertObject:(id)object inCustomHomePagesAtIndex:(NSUInteger)index;
+- (void)removeObjectFromCustomHomePagesAtIndex:(NSUInteger)index;
+@end
+
+////////////////////////////////////////////////////////////////////////////////
+
+// An entry representing a single item in the custom home page model. Stores
+// a url and a favicon.
+@interface CustomHomePageEntry : NSObject {
+ @private
+  scoped_nsobject<NSString> url_;
+  scoped_nsobject<NSImage> icon_;
+
+  // If non-zero, indicates we're loading the favicon for the page.
+  HistoryService::Handle icon_handle_;
+}
+
+@property(nonatomic, copy) NSString* URL;
+@property(nonatomic, retain) NSImage* image;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////
+
+@interface CustomHomePagesModel (InternalOrTestingAPI)
+
+// Clears the URL string at the specified index. This constitutes bad data. The
+// validator should scrub the entry from the list the next time it is run.
+- (void)setURLStringEmptyAt:(NSUInteger)index;
+
+@end
+
+// A notification that fires when the URL of one of the entries changes.
+// Prevents interested parties from having to observe all model objects in order
+// to persist changes to a single entry. Changes to the number of items in the
+// model can be observed by watching |customHomePages| via KVO so an additional
+// notification is not sent.
+extern NSString* const kHomepageEntryChangedNotification;
+
+#endif  // CHROME_BROWSER_UI_COCOA_OPTIONS_CUSTOM_HOME_PAGES_MODEL_H_
diff --git a/chrome/browser/ui/cocoa/options/custom_home_pages_model.mm b/chrome/browser/ui/cocoa/options/custom_home_pages_model.mm
new file mode 100644
index 0000000..6ee80b6
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/custom_home_pages_model.mm
@@ -0,0 +1,140 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/custom_home_pages_model.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+
+NSString* const kHomepageEntryChangedNotification =
+    @"kHomepageEntryChangedNotification";
+
+@interface CustomHomePagesModel (Private)
+- (void)setURLsInternal:(const std::vector<GURL>&)urls;
+@end
+
+@implementation CustomHomePagesModel
+
+- (id)initWithProfile:(Profile*)profile {
+  if ((self = [super init])) {
+    profile_ = profile;
+    entries_.reset([[NSMutableArray alloc] init]);
+  }
+  return self;
+}
+
+- (NSUInteger)countOfCustomHomePages {
+  return [entries_ count];
+}
+
+- (id)objectInCustomHomePagesAtIndex:(NSUInteger)index {
+  return [entries_ objectAtIndex:index];
+}
+
+- (void)insertObject:(id)object inCustomHomePagesAtIndex:(NSUInteger)index {
+  [entries_ insertObject:object atIndex:index];
+}
+
+- (void)removeObjectFromCustomHomePagesAtIndex:(NSUInteger)index {
+  [entries_ removeObjectAtIndex:index];
+  // Force a save.
+  [self validateURLs];
+}
+
+// Get/set the urls the model currently contains as a group. These will weed
+// out any URLs that are empty and not add them to the model. As a result,
+// the next time they're persisted to the prefs backend, they'll disappear.
+- (std::vector<GURL>)URLs {
+  std::vector<GURL> urls;
+  for (CustomHomePageEntry* entry in entries_.get()) {
+    const char* urlString = [[entry URL] UTF8String];
+    if (urlString && std::strlen(urlString)) {
+      urls.push_back(GURL(std::string(urlString)));
+    }
+  }
+  return urls;
+}
+
+- (void)setURLs:(const std::vector<GURL>&)urls {
+  [self willChangeValueForKey:@"customHomePages"];
+  [self setURLsInternal:urls];
+  SessionStartupPref pref(SessionStartupPref::GetStartupPref(profile_));
+  pref.urls = urls;
+  SessionStartupPref::SetStartupPref(profile_, pref);
+  [self didChangeValueForKey:@"customHomePages"];
+}
+
+// Converts the C++ URLs to Cocoa objects without notifying KVO.
+- (void)setURLsInternal:(const std::vector<GURL>&)urls {
+  [entries_ removeAllObjects];
+  for (size_t i = 0; i < urls.size(); ++i) {
+    scoped_nsobject<CustomHomePageEntry> entry(
+        [[CustomHomePageEntry alloc] init]);
+    const char* urlString = urls[i].spec().c_str();
+    if (urlString && std::strlen(urlString)) {
+      [entry setURL:[NSString stringWithCString:urlString
+                                       encoding:NSUTF8StringEncoding]];
+      [entries_ addObject:entry];
+    }
+  }
+}
+
+- (void)reloadURLs {
+  [self willChangeValueForKey:@"customHomePages"];
+  SessionStartupPref pref(SessionStartupPref::GetStartupPref(profile_));
+  [self setURLsInternal:pref.urls];
+  [self didChangeValueForKey:@"customHomePages"];
+}
+
+- (void)validateURLs {
+  [self setURLs:[self URLs]];
+}
+
+- (void)setURLStringEmptyAt:(NSUInteger)index {
+  // This replaces the data at |index| with an empty (invalid) URL string.
+  CustomHomePageEntry* entry = [entries_ objectAtIndex:index];
+  [entry setURL:[NSString stringWithString:@""]];
+}
+
+@end
+
+//---------------------------------------------------------------------------
+
+@implementation CustomHomePageEntry
+
+- (void)setURL:(NSString*)url {
+  // |url| can be nil if the user cleared the text from the edit field.
+  if (!url)
+    url = [NSString stringWithString:@""];
+
+  // Make sure the url is valid before setting it by fixing it up.
+  std::string fixedUrl(URLFixerUpper::FixupURL(
+      base::SysNSStringToUTF8(url), std::string()).possibly_invalid_spec());
+  url_.reset([base::SysUTF8ToNSString(fixedUrl) retain]);
+
+  // Broadcast that an individual item has changed.
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kHomepageEntryChangedNotification object:nil];
+
+  // TODO(pinkerton): fetch favicon, convert to NSImage http://crbug.com/34642
+}
+
+- (NSString*)URL {
+  return url_.get();
+}
+
+- (void)setImage:(NSImage*)image {
+  icon_.reset(image);
+}
+
+- (NSImage*)image {
+  return icon_.get();
+}
+
+- (NSString*)description {
+  return url_.get();
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/custom_home_pages_model_unittest.mm b/chrome/browser/ui/cocoa/options/custom_home_pages_model_unittest.mm
new file mode 100644
index 0000000..a79615b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/custom_home_pages_model_unittest.mm
@@ -0,0 +1,196 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/custom_home_pages_model.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+// A helper for KVO and NSNotifications. Makes a note that it's been called
+// back.
+@interface CustomHomePageHelper : NSObject {
+ @public
+  BOOL sawNotification_;
+}
+@end
+
+@implementation CustomHomePageHelper
+- (void)observeValueForKeyPath:(NSString*)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary*)change
+                       context:(void*)context {
+  sawNotification_ = YES;
+}
+
+- (void)entryChanged:(NSNotification*)notify {
+  sawNotification_ = YES;
+}
+@end
+
+@interface NSObject ()
+- (void)setURL:(NSString*)url;
+@end
+
+namespace {
+
+// Helper that creates an autoreleased entry.
+CustomHomePageEntry* MakeEntry(NSString* url) {
+  CustomHomePageEntry* entry = [[[CustomHomePageEntry alloc] init] autorelease];
+  [entry setURL:url];
+  return entry;
+}
+
+// Helper that casts from |id| to the Entry type and returns the URL string.
+NSString* EntryURL(id entry) {
+  return [static_cast<CustomHomePageEntry*>(entry) URL];
+}
+
+class CustomHomePagesModelTest : public PlatformTest {
+ public:
+  CustomHomePagesModelTest() {
+    model_.reset([[CustomHomePagesModel alloc]
+                    initWithProfile:helper_.profile()]);
+   }
+  ~CustomHomePagesModelTest() { }
+
+  BrowserTestHelper helper_;
+  scoped_nsobject<CustomHomePagesModel> model_;
+};
+
+TEST_F(CustomHomePagesModelTest, Init) {
+  scoped_nsobject<CustomHomePagesModel> model(
+      [[CustomHomePagesModel alloc] initWithProfile:helper_.profile()]);
+}
+
+TEST_F(CustomHomePagesModelTest, GetSetURLs) {
+  // Basic test.
+  std::vector<GURL> urls;
+  urls.push_back(GURL("http://www.google.com"));
+  [model_ setURLs:urls];
+  std::vector<GURL> received_urls = [model_.get() URLs];
+  EXPECT_EQ(received_urls.size(), 1U);
+  EXPECT_TRUE(urls[0] == received_urls[0]);
+
+  // Set an empty list, make sure we get back an empty list.
+  std::vector<GURL> empty;
+  [model_ setURLs:empty];
+  received_urls = [model_.get() URLs];
+  EXPECT_EQ(received_urls.size(), 0U);
+
+  // Give it a list with not well-formed URLs and make sure we get back.
+  // only the good ones.
+  std::vector<GURL> poorly_formed;
+  poorly_formed.push_back(GURL("http://www.google.com"));  // good
+  poorly_formed.push_back(GURL("www.google.com"));  // bad
+  poorly_formed.push_back(GURL("www.yahoo."));  // bad
+  poorly_formed.push_back(GURL("http://www.yahoo.com"));  // good
+  [model_ setURLs:poorly_formed];
+  received_urls = [model_.get() URLs];
+  EXPECT_EQ(received_urls.size(), 2U);
+}
+
+// Test that we get a KVO notification when called setURLs.
+TEST_F(CustomHomePagesModelTest, KVOObserveWhenListChanges) {
+  scoped_nsobject<CustomHomePageHelper> kvo_helper(
+      [[CustomHomePageHelper alloc] init]);
+  [model_ addObserver:kvo_helper
+           forKeyPath:@"customHomePages"
+              options:0L
+              context:NULL];
+  EXPECT_FALSE(kvo_helper.get()->sawNotification_);
+
+  std::vector<GURL> urls;
+  urls.push_back(GURL("http://www.google.com"));
+  [model_ setURLs:urls];  // Should send kvo change notification.
+  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
+
+  [model_ removeObserver:kvo_helper forKeyPath:@"customHomePages"];
+}
+
+// Test the KVO "to-many" bindings for |customHomePages| and the KVO
+// notifiation when items are added to and removed from the list.
+TEST_F(CustomHomePagesModelTest, KVO) {
+  EXPECT_EQ([model_ countOfCustomHomePages], 0U);
+
+  scoped_nsobject<CustomHomePageHelper> kvo_helper(
+      [[CustomHomePageHelper alloc] init]);
+  [model_ addObserver:kvo_helper
+           forKeyPath:@"customHomePages"
+              options:0L
+              context:NULL];
+  EXPECT_FALSE(kvo_helper.get()->sawNotification_);
+
+  // Cheat and insert NSString objects into the array. As long as we don't
+  // call -URLs, we'll be ok.
+  [model_ insertObject:MakeEntry(@"www.google.com") inCustomHomePagesAtIndex:0];
+  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
+  [model_ insertObject:MakeEntry(@"www.yahoo.com") inCustomHomePagesAtIndex:1];
+  [model_ insertObject:MakeEntry(@"dev.chromium.org")
+      inCustomHomePagesAtIndex:2];
+  EXPECT_EQ([model_ countOfCustomHomePages], 3U);
+
+  EXPECT_NSEQ(@"http://www.yahoo.com/",
+              EntryURL([model_ objectInCustomHomePagesAtIndex:1]));
+
+  kvo_helper.get()->sawNotification_ = NO;
+  [model_ removeObjectFromCustomHomePagesAtIndex:1];
+  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
+  EXPECT_EQ([model_ countOfCustomHomePages], 2U);
+  EXPECT_NSEQ(@"http://dev.chromium.org/",
+              EntryURL([model_ objectInCustomHomePagesAtIndex:1]));
+  EXPECT_NSEQ(@"http://www.google.com/",
+              EntryURL([model_ objectInCustomHomePagesAtIndex:0]));
+
+  [model_ removeObserver:kvo_helper forKeyPath:@"customHomePages"];
+}
+
+// Test that when individual items are changed that they broadcast a message.
+TEST_F(CustomHomePagesModelTest, ModelChangedNotification) {
+  scoped_nsobject<CustomHomePageHelper> kvo_helper(
+      [[CustomHomePageHelper alloc] init]);
+  [[NSNotificationCenter defaultCenter]
+      addObserver:kvo_helper
+         selector:@selector(entryChanged:)
+             name:kHomepageEntryChangedNotification
+            object:nil];
+
+  std::vector<GURL> urls;
+  urls.push_back(GURL("http://www.google.com"));
+  [model_ setURLs:urls];
+  NSObject* entry = [model_ objectInCustomHomePagesAtIndex:0];
+  [entry setURL:@"http://www.foo.bar"];
+  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
+  [[NSNotificationCenter defaultCenter] removeObserver:kvo_helper];
+}
+
+TEST_F(CustomHomePagesModelTest, ReloadURLs) {
+  scoped_nsobject<CustomHomePageHelper> kvo_helper(
+      [[CustomHomePageHelper alloc] init]);
+  [model_ addObserver:kvo_helper
+           forKeyPath:@"customHomePages"
+              options:0L
+              context:NULL];
+  EXPECT_FALSE(kvo_helper.get()->sawNotification_);
+  EXPECT_EQ([model_ countOfCustomHomePages], 0U);
+
+  std::vector<GURL> urls;
+  urls.push_back(GURL("http://www.google.com"));
+  SessionStartupPref pref;
+  pref.urls = urls;
+  SessionStartupPref::SetStartupPref(helper_.profile(), pref);
+
+  [model_ reloadURLs];
+
+  EXPECT_TRUE(kvo_helper.get()->sawNotification_);
+  EXPECT_EQ([model_ countOfCustomHomePages], 1U);
+  EXPECT_NSEQ(@"http://www.google.com/",
+              EntryURL([model_ objectInCustomHomePagesAtIndex:0]));
+
+  [model_ removeObserver:kvo_helper.get() forKeyPath:@"customHomePages"];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.h b/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.h
similarity index 100%
rename from chrome/browser/ui/cocoa/edit_search_engine_cocoa_controller.h
rename to chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.h
diff --git a/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.mm b/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.mm
new file mode 100644
index 0000000..a77d2ae
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.mm
@@ -0,0 +1,187 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.h"
+
+#include "base/logging.h"
+#import "base/mac/mac_util.h"
+#include "base/string16.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+void ShiftOriginY(NSView* view, CGFloat amount) {
+  NSPoint origin = [view frame].origin;
+  origin.y += amount;
+  [view setFrameOrigin:origin];
+}
+
+}  // namespace
+
+@implementation EditSearchEngineCocoaController
+
+- (id)initWithProfile:(Profile*)profile
+             delegate:(EditSearchEngineControllerDelegate*)delegate
+          templateURL:(const TemplateURL*)url {
+  DCHECK(profile);
+  NSString* nibpath = [base::mac::MainAppBundle()
+                        pathForResource:@"EditSearchEngine"
+                                 ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    profile_ = profile;
+    templateURL_ = url;
+    controller_.reset(
+        new EditSearchEngineController(templateURL_, delegate, profile_));
+  }
+  return self;
+}
+
+- (void)awakeFromNib {
+  DCHECK([self window]);
+  DCHECK_EQ(self, [[self window] delegate]);
+
+  // Make sure the url description field fits the text in it.
+  CGFloat descriptionShift = [GTMUILocalizerAndLayoutTweaker
+      sizeToFitFixedWidthTextField:urlDescriptionField_];
+
+  // Move the label container above the url description.
+  ShiftOriginY(labelContainer_, descriptionShift);
+  // There was no way via view containment to use a helper view to move all
+  // the textfields and images at once, most move them all on their own so
+  // they stay above the url description.
+  ShiftOriginY(nameField_, descriptionShift);
+  ShiftOriginY(keywordField_, descriptionShift);
+  ShiftOriginY(urlField_, descriptionShift);
+  ShiftOriginY(nameImage_, descriptionShift);
+  ShiftOriginY(keywordImage_, descriptionShift);
+  ShiftOriginY(urlImage_, descriptionShift);
+
+  // Resize the containing box for the name/keyword/url fields/images since it
+  // also contains the url description (which just grew).
+  [[fieldAndImageContainer_ contentView] setAutoresizesSubviews:NO];
+  NSRect rect = [fieldAndImageContainer_ frame];
+  rect.size.height += descriptionShift;
+  [fieldAndImageContainer_ setFrame:rect];
+  [[fieldAndImageContainer_ contentView] setAutoresizesSubviews:YES];
+
+  // Resize the window.
+  NSWindow* window = [self window];
+  NSSize windowDelta = NSMakeSize(0, descriptionShift);
+  [GTMUILocalizerAndLayoutTweaker
+      resizeWindowWithoutAutoResizingSubViews:window
+                                        delta:windowDelta];
+
+  ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
+  goodImage_.reset([bundle.GetNativeImageNamed(IDR_INPUT_GOOD) retain]);
+  badImage_.reset([bundle.GetNativeImageNamed(IDR_INPUT_ALERT) retain]);
+  if (templateURL_) {
+    // Defaults to |..._NEW_WINDOW_TITLE|.
+    [window setTitle:l10n_util::GetNSString(
+      IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE)];
+    [nameField_ setStringValue:
+        base::SysUTF16ToNSString(templateURL_->short_name())];
+    [keywordField_ setStringValue:
+        base::SysUTF16ToNSString(templateURL_->keyword())];
+    [urlField_ setStringValue:
+        base::SysUTF16ToNSString(templateURL_->url()->DisplayURL())];
+    [urlField_ setEnabled:(templateURL_->prepopulate_id() == 0)];
+  }
+  // When creating a new keyword, this will mark the fields as "invalid" and
+  // will not let the user save. If this is an edit, then this will set all
+  // the images to the "valid" state.
+  [self validateFields];
+}
+
+// When the window closes, clean ourselves up.
+- (void)windowWillClose:(NSNotification*)notif {
+  [self autorelease];
+}
+
+// Performs the logic of closing the window. If we are a sheet, then it ends the
+// modal session; otherwise, it closes the window.
+- (void)doClose {
+  if ([[self window] isSheet]) {
+    [NSApp endSheet:[self window]];
+  } else {
+    [[self window] close];
+  }
+}
+
+- (IBAction)cancel:(id)sender {
+  [self doClose];
+}
+
+- (IBAction)save:(id)sender {
+  DCHECK([self validateFields]);
+  string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
+  string16 keyword = base::SysNSStringToUTF16([keywordField_ stringValue]);
+  std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
+  controller_->AcceptAddOrEdit(title, keyword, url);
+  [self doClose];
+}
+
+// Delegate method for the text fields.
+
+- (void)controlTextDidChange:(NSNotification*)notif {
+  [self validateFields];
+}
+
+- (void)controlTextDidEndEditing:(NSNotification*)notif {
+  [self validateFields];
+}
+
+// Private --------------------------------------------------------------------
+
+// Sets the appropriate image and tooltip based on a boolean |valid|.
+- (void)setIsValid:(BOOL)valid
+           toolTip:(int)messageID
+      forImageView:(NSImageView*)imageView
+         textField:(NSTextField*)textField {
+  NSImage* image = (valid) ? goodImage_ : badImage_;
+  [imageView setImage:image];
+
+  NSString* toolTip = nil;
+  if (!valid)
+    toolTip = l10n_util::GetNSString(messageID);
+  [textField setToolTip:toolTip];
+  [imageView setToolTip:toolTip];
+}
+
+// This sets the image state for all the controls and enables or disables the
+// done button. Returns YES if all the fields are valid.
+- (BOOL)validateFields {
+  string16 title = base::SysNSStringToUTF16([nameField_ stringValue]);
+  BOOL titleValid = controller_->IsTitleValid(title);
+  [self setIsValid:titleValid
+           toolTip:IDS_SEARCH_ENGINES_INVALID_TITLE_TT
+      forImageView:nameImage_
+         textField:nameField_];
+
+  string16 keyword = base::SysNSStringToUTF16([keywordField_ stringValue]);
+  BOOL keywordValid = controller_->IsKeywordValid(keyword);
+  [self setIsValid:keywordValid
+           toolTip:IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT
+      forImageView:keywordImage_
+         textField:keywordField_];
+
+  std::string url = base::SysNSStringToUTF8([urlField_ stringValue]);
+  BOOL urlValid = controller_->IsURLValid(url);
+  [self setIsValid:urlValid
+           toolTip:IDS_SEARCH_ENGINES_INVALID_URL_TT
+      forImageView:urlImage_
+         textField:urlField_];
+
+  BOOL isValid = (titleValid && keywordValid && urlValid);
+  [doneButton_ setEnabled:isValid];
+  return isValid;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller_unittest.mm
new file mode 100644
index 0000000..90e0a49
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller_unittest.mm
@@ -0,0 +1,233 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.h"
+#include "chrome/test/testing_profile.h"
+#include "grit/generated_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+@interface FakeEditSearchEngineController : EditSearchEngineCocoaController {
+}
+@property (nonatomic, readonly) NSTextField* nameField;
+@property (nonatomic, readonly) NSTextField* keywordField;
+@property (nonatomic, readonly) NSTextField* urlField;
+@property (nonatomic, readonly) NSImageView* nameImage;
+@property (nonatomic, readonly) NSImageView* keywordImage;
+@property (nonatomic, readonly) NSImageView* urlImage;
+@property (nonatomic, readonly) NSButton* doneButton;
+@property (nonatomic, readonly) NSImage* goodImage;
+@property (nonatomic, readonly) NSImage* badImage;
+@end
+
+@implementation FakeEditSearchEngineController
+@synthesize nameField = nameField_;
+@synthesize keywordField = keywordField_;
+@synthesize urlField = urlField_;
+@synthesize nameImage = nameImage_;
+@synthesize keywordImage = keywordImage_;
+@synthesize urlImage = urlImage_;
+@synthesize doneButton = doneButton_;
+- (NSImage*)goodImage {
+  return goodImage_.get();
+}
+- (NSImage*)badImage {
+  return badImage_.get();
+}
+@end
+
+namespace {
+
+class EditSearchEngineControllerTest : public CocoaTest {
+ public:
+   virtual void SetUp() {
+     CocoaTest::SetUp();
+     TestingProfile* profile =
+        static_cast<TestingProfile*>(browser_helper_.profile());
+     profile->CreateTemplateURLModel();
+     controller_ = [[FakeEditSearchEngineController alloc]
+                    initWithProfile:profile
+                    delegate:nil
+                    templateURL:nil];
+   }
+
+  virtual void TearDown() {
+    // Force the window to load so we hit |-awakeFromNib| to register as the
+    // window's delegate so that the controller can clean itself up in
+    // |-windowWillClose:|.
+    ASSERT_TRUE([controller_ window]);
+
+    [controller_ close];
+    CocoaTest::TearDown();
+  }
+
+  BrowserTestHelper browser_helper_;
+  FakeEditSearchEngineController* controller_;
+};
+
+TEST_F(EditSearchEngineControllerTest, ValidImageOriginals) {
+  EXPECT_FALSE([controller_ goodImage]);
+  EXPECT_FALSE([controller_ badImage]);
+
+  EXPECT_TRUE([controller_ window]);  // Force the window to load.
+
+  EXPECT_TRUE([[controller_ goodImage] isKindOfClass:[NSImage class]]);
+  EXPECT_TRUE([[controller_ badImage] isKindOfClass:[NSImage class]]);
+
+  // Test window title is set correctly.
+  NSString* title = l10n_util::GetNSString(
+      IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE);
+  EXPECT_NSEQ(title, [[controller_ window] title]);
+}
+
+TEST_F(EditSearchEngineControllerTest, SetImageViews) {
+  EXPECT_TRUE([controller_ window]);  // Force the window to load.
+  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
+  // An empty keyword is not OK.
+  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
+  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
+}
+
+// This test ensures that on creating a new keyword, we are in an "invalid"
+// state that cannot save.
+TEST_F(EditSearchEngineControllerTest, InvalidState) {
+  EXPECT_TRUE([controller_ window]);  // Force window to load.
+  NSString* toolTip = nil;
+  EXPECT_FALSE([controller_ validateFields]);
+
+  EXPECT_NSEQ(@"", [[controller_ nameField] stringValue]);
+  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
+  toolTip = l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
+  EXPECT_NSEQ(toolTip, [[controller_ nameField] toolTip]);
+  EXPECT_NSEQ(toolTip, [[controller_ nameImage] toolTip]);
+
+  // Keywords can not be empty strings.
+  EXPECT_NSEQ(@"", [[controller_ keywordField] stringValue]);
+  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
+  EXPECT_TRUE([[controller_ keywordField] toolTip]);
+  EXPECT_TRUE([[controller_ keywordImage] toolTip]);
+
+  EXPECT_NSEQ(@"", [[controller_ urlField] stringValue]);
+  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
+  toolTip = l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_URL_TT);
+  EXPECT_NSEQ(toolTip, [[controller_ urlField] toolTip]);
+  EXPECT_NSEQ(toolTip, [[controller_ urlImage] toolTip]);
+}
+
+// Tests that the single name field validates.
+TEST_F(EditSearchEngineControllerTest, ValidateName) {
+  EXPECT_TRUE([controller_ window]);  // Force window to load.
+
+  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
+  EXPECT_FALSE([controller_ validateFields]);
+  NSString* toolTip =
+      l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
+  EXPECT_NSEQ(toolTip, [[controller_ nameField] toolTip]);
+  EXPECT_NSEQ(toolTip, [[controller_ nameImage] toolTip]);
+  [[controller_ nameField] setStringValue:@"Test Name"];
+  EXPECT_FALSE([controller_ validateFields]);
+  EXPECT_EQ([controller_ goodImage], [[controller_ nameImage] image]);
+  EXPECT_FALSE([[controller_ nameField] toolTip]);
+  EXPECT_FALSE([[controller_ nameImage] toolTip]);
+  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
+}
+
+// The keyword field is not valid if it is empty.
+TEST_F(EditSearchEngineControllerTest, ValidateKeyword) {
+  EXPECT_TRUE([controller_ window]);  // Force window load.
+
+  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
+  EXPECT_FALSE([controller_ validateFields]);
+  EXPECT_TRUE([[controller_ keywordField] toolTip]);
+  EXPECT_TRUE([[controller_ keywordImage] toolTip]);
+  [[controller_ keywordField] setStringValue:@"foobar"];
+  EXPECT_FALSE([controller_ validateFields]);
+  EXPECT_EQ([controller_ goodImage], [[controller_ keywordImage] image]);
+  EXPECT_FALSE([[controller_ keywordField] toolTip]);
+  EXPECT_FALSE([[controller_ keywordImage] toolTip]);
+  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
+}
+
+// Tests that the URL field validates.
+TEST_F(EditSearchEngineControllerTest, ValidateURL) {
+  EXPECT_TRUE([controller_ window]);  // Force window to load.
+
+  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
+  EXPECT_FALSE([controller_ validateFields]);
+  NSString* toolTip =
+      l10n_util::GetNSString(IDS_SEARCH_ENGINES_INVALID_URL_TT);
+  EXPECT_NSEQ(toolTip, [[controller_ urlField] toolTip]);
+  EXPECT_NSEQ(toolTip, [[controller_ urlImage] toolTip]);
+  [[controller_ urlField] setStringValue:@"http://foo-bar.com"];
+  EXPECT_FALSE([controller_ validateFields]);
+  EXPECT_EQ([controller_ goodImage], [[controller_ urlImage] image]);
+  EXPECT_FALSE([[controller_ urlField] toolTip]);
+  EXPECT_FALSE([[controller_ urlImage] toolTip]);
+  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
+}
+
+// Tests that if the user enters all valid data that the UI reflects that
+// and that they can save.
+TEST_F(EditSearchEngineControllerTest, ValidateFields) {
+  EXPECT_TRUE([controller_ window]);  // Force window to load.
+
+  // State before entering data.
+  EXPECT_EQ([controller_ badImage], [[controller_ nameImage] image]);
+  EXPECT_EQ([controller_ badImage], [[controller_ keywordImage] image]);
+  EXPECT_EQ([controller_ badImage], [[controller_ urlImage] image]);
+  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
+  EXPECT_FALSE([controller_ validateFields]);
+
+  [[controller_ nameField] setStringValue:@"Test Name"];
+  EXPECT_FALSE([controller_ validateFields]);
+  EXPECT_EQ([controller_ goodImage], [[controller_ nameImage] image]);
+  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
+
+  [[controller_ keywordField] setStringValue:@"foobar"];
+  EXPECT_FALSE([controller_ validateFields]);
+  EXPECT_EQ([controller_ goodImage], [[controller_ keywordImage] image]);
+  EXPECT_FALSE([[controller_ doneButton] isEnabled]);
+
+  // Once the URL is entered, we should have all 3 valid fields.
+  [[controller_ urlField] setStringValue:@"http://foo-bar.com"];
+  EXPECT_TRUE([controller_ validateFields]);
+  EXPECT_EQ([controller_ goodImage], [[controller_ urlImage] image]);
+  EXPECT_TRUE([[controller_ doneButton] isEnabled]);
+}
+
+// Tests editing an existing TemplateURL.
+TEST_F(EditSearchEngineControllerTest, EditTemplateURL) {
+  TemplateURL url;
+  url.set_short_name(ASCIIToUTF16("Foobar"));
+  url.set_keyword(ASCIIToUTF16("keyword"));
+  std::string urlString = TemplateURLRef::DisplayURLToURLRef(
+      ASCIIToUTF16("http://foo-bar.com"));
+  url.SetURL(urlString, 0, 1);
+  TestingProfile* profile = browser_helper_.profile();
+  FakeEditSearchEngineController *controller =
+      [[FakeEditSearchEngineController alloc] initWithProfile:profile
+                                                     delegate:nil
+                                                  templateURL:&url];
+  EXPECT_TRUE([controller window]);
+  NSString* title = l10n_util::GetNSString(
+      IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE);
+  EXPECT_NSEQ(title, [[controller window] title]);
+  NSString* nameString = [[controller nameField] stringValue];
+  EXPECT_NSEQ(@"Foobar", nameString);
+  NSString* keywordString = [[controller keywordField] stringValue];
+  EXPECT_NSEQ(@"keyword", keywordString);
+  NSString* urlValueString = [[controller urlField] stringValue];
+  EXPECT_NSEQ(@"http://foo-bar.com", urlValueString);
+  EXPECT_TRUE([controller validateFields]);
+  [controller close];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/font_language_settings_controller.h b/chrome/browser/ui/cocoa/options/font_language_settings_controller.h
similarity index 100%
rename from chrome/browser/ui/cocoa/font_language_settings_controller.h
rename to chrome/browser/ui/cocoa/options/font_language_settings_controller.h
diff --git a/chrome/browser/ui/cocoa/options/font_language_settings_controller.mm b/chrome/browser/ui/cocoa/options/font_language_settings_controller.mm
new file mode 100644
index 0000000..7ee6c29
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/font_language_settings_controller.mm
@@ -0,0 +1,280 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/options/font_language_settings_controller.h"
+
+#import <Cocoa/Cocoa.h>
+#import "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/character_encoding.h"
+#include "chrome/browser/fonts_languages_window.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+
+NSString* const kCharacterInfoEncoding = @"encoding";
+NSString* const kCharacterInfoName = @"name";
+NSString* const kCharacterInfoID = @"id";
+
+void ShowFontsLanguagesWindow(gfx::NativeWindow window,
+                              FontsLanguagesPage page,
+                              Profile* profile) {
+  NOTIMPLEMENTED();
+}
+
+@interface FontLanguageSettingsController (Private)
+- (void)updateDisplayField:(NSTextField*)field
+                  withFont:(NSFont*)font
+                 withLabel:(NSTextField*)label;
+@end
+
+@implementation FontLanguageSettingsController
+
+- (id)initWithProfile:(Profile*)profile {
+  DCHECK(profile);
+  NSString* nibpath = [base::mac::MainAppBundle()
+                        pathForResource:@"FontLanguageSettings"
+                                 ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    profile_ = profile;
+
+    // Convert the name/size preference values to NSFont objects.
+    serifName_.Init(prefs::kWebKitSerifFontFamily, profile->GetPrefs(), NULL);
+    serifSize_.Init(prefs::kWebKitDefaultFontSize, profile->GetPrefs(), NULL);
+    NSString* serif = base::SysUTF8ToNSString(serifName_.GetValue());
+    serifFont_.reset(
+        [[NSFont fontWithName:serif size:serifSize_.GetValue()] retain]);
+
+    sansSerifName_.Init(prefs::kWebKitSansSerifFontFamily, profile->GetPrefs(),
+                        NULL);
+    sansSerifSize_.Init(prefs::kWebKitDefaultFontSize, profile->GetPrefs(),
+                        NULL);
+    NSString* sansSerif = base::SysUTF8ToNSString(sansSerifName_.GetValue());
+    sansSerifFont_.reset(
+        [[NSFont fontWithName:sansSerif
+                         size:sansSerifSize_.GetValue()] retain]);
+
+    fixedWidthName_.Init(prefs::kWebKitFixedFontFamily, profile->GetPrefs(),
+                         NULL);
+    fixedWidthSize_.Init(prefs::kWebKitDefaultFixedFontSize,
+                         profile->GetPrefs(), NULL);
+    NSString* fixedWidth = base::SysUTF8ToNSString(fixedWidthName_.GetValue());
+    fixedWidthFont_.reset(
+        [[NSFont fontWithName:fixedWidth
+                         size:fixedWidthSize_.GetValue()] retain]);
+
+    // Generate a list of encodings.
+    NSInteger count = CharacterEncoding::GetSupportCanonicalEncodingCount();
+    NSMutableArray* encodings = [NSMutableArray arrayWithCapacity:count];
+    for (NSInteger i = 0; i < count; ++i) {
+      int commandId = CharacterEncoding::GetEncodingCommandIdByIndex(i);
+      string16 name = CharacterEncoding::\
+          GetCanonicalEncodingDisplayNameByCommandId(commandId);
+      std::string encoding =
+          CharacterEncoding::GetCanonicalEncodingNameByCommandId(commandId);
+      NSDictionary* strings = [NSDictionary dictionaryWithObjectsAndKeys:
+          base::SysUTF16ToNSString(name), kCharacterInfoName,
+          base::SysUTF8ToNSString(encoding), kCharacterInfoEncoding,
+          [NSNumber numberWithInt:commandId], kCharacterInfoID,
+          nil
+      ];
+      [encodings addObject:strings];
+    }
+
+    // Sort the encodings.
+    scoped_nsobject<NSSortDescriptor> sorter(
+        [[NSSortDescriptor alloc] initWithKey:kCharacterInfoName
+                                    ascending:YES]);
+    NSArray* sorterArray = [NSArray arrayWithObject:sorter.get()];
+    encodings_.reset(
+        [[encodings sortedArrayUsingDescriptors:sorterArray] retain]);
+
+    // Find and set the default encoding.
+    defaultEncoding_.Init(prefs::kDefaultCharset, profile->GetPrefs(), NULL);
+    NSString* defaultEncoding =
+        base::SysUTF8ToNSString(defaultEncoding_.GetValue());
+    NSUInteger index = 0;
+    for (NSDictionary* entry in encodings_.get()) {
+      NSString* encoding = [entry objectForKey:kCharacterInfoEncoding];
+      if ([encoding isEqualToString:defaultEncoding]) {
+        defaultEncodingIndex_ = index;
+        break;
+      }
+      ++index;
+    }
+
+    // Register as a KVO observer so we can receive updates when the encoding
+    // changes.
+    [self addObserver:self
+           forKeyPath:@"defaultEncodingIndex_"
+              options:NSKeyValueObservingOptionNew
+              context:NULL];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self removeObserver:self forKeyPath:@"defaultEncodingIndex_"];
+  [super dealloc];
+}
+
+- (void)awakeFromNib {
+  DCHECK([self window]);
+  [[self window] setDelegate:self];
+
+  // Set up the font display.
+  [self updateDisplayField:serifField_
+                  withFont:serifFont_.get()
+                 withLabel:serifLabel_];
+  [self updateDisplayField:sansSerifField_
+                  withFont:sansSerifFont_.get()
+                 withLabel:sansSerifLabel_];
+  [self updateDisplayField:fixedWidthField_
+                  withFont:fixedWidthFont_.get()
+                 withLabel:fixedWidthLabel_];
+}
+
+- (void)windowWillClose:(NSNotification*)notif {
+  [self autorelease];
+}
+
+- (IBAction)selectFont:(id)sender {
+  if (sender == serifButton_) {
+    currentFont_ = serifFont_.get();
+    currentType_ = FontSettingSerif;
+  } else if (sender == sansSerifButton_) {
+    currentFont_ = sansSerifFont_.get();
+    currentType_ = FontSettingSansSerif;
+  } else if (sender == fixedWidthButton_) {
+    currentFont_ = fixedWidthFont_.get();
+    currentType_ = FontSettingFixed;
+  } else {
+    NOTREACHED();
+  }
+
+  // Validate whatever editing is currently happening.
+  if ([[self window] makeFirstResponder:nil]) {
+    NSFontManager* manager = [NSFontManager sharedFontManager];
+    [manager setTarget:self];
+    [manager setSelectedFont:currentFont_ isMultiple:NO];
+    [manager orderFrontFontPanel:self];
+  }
+}
+
+// Called by the font manager when the user has selected a new font. We should
+// then persist those changes into the preference system.
+- (void)changeFont:(id)fontManager {
+  switch (currentType_) {
+    case FontSettingSerif:
+      serifFont_.reset([[fontManager convertFont:serifFont_] retain]);
+      [self updateDisplayField:serifField_
+                      withFont:serifFont_.get()
+                     withLabel:serifLabel_];
+      changedSerif_ = YES;
+      break;
+    case FontSettingSansSerif:
+      sansSerifFont_.reset([[fontManager convertFont:sansSerifFont_] retain]);
+      [self updateDisplayField:sansSerifField_
+                      withFont:sansSerifFont_.get()
+                     withLabel:sansSerifLabel_];
+      changedSansSerif_ = YES;
+      break;
+    case FontSettingFixed:
+      fixedWidthFont_.reset(
+          [[fontManager convertFont:fixedWidthFont_] retain]);
+      [self updateDisplayField:fixedWidthField_
+                      withFont:fixedWidthFont_.get()
+                     withLabel:fixedWidthLabel_];
+      changedFixedWidth_ = YES;
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
+- (IBAction)closeSheet:(id)sender {
+  NSFontPanel* panel = [[NSFontManager sharedFontManager] fontPanel:NO];
+  [panel close];
+  [NSApp endSheet:[self window]];
+}
+
+- (IBAction)save:(id)sender {
+  if (changedSerif_) {
+    serifName_.SetValue(base::SysNSStringToUTF8([serifFont_ fontName]));
+    serifSize_.SetValue([serifFont_ pointSize]);
+  }
+  if (changedSansSerif_) {
+    sansSerifName_.SetValue(
+        base::SysNSStringToUTF8([sansSerifFont_ fontName]));
+    sansSerifSize_.SetValue([sansSerifFont_ pointSize]);
+  }
+  if (changedFixedWidth_) {
+    fixedWidthName_.SetValue(
+        base::SysNSStringToUTF8([fixedWidthFont_ fontName]));
+    fixedWidthSize_.SetValue([fixedWidthFont_ pointSize]);
+  }
+  if (changedEncoding_) {
+    NSDictionary* object = [encodings_ objectAtIndex:defaultEncodingIndex_];
+    NSString* newEncoding = [object objectForKey:kCharacterInfoEncoding];
+    std::string encoding = base::SysNSStringToUTF8(newEncoding);
+    defaultEncoding_.SetValue(encoding);
+  }
+  [self closeSheet:sender];
+}
+
+- (NSArray*)encodings {
+  return encodings_.get();
+}
+
+// KVO notification.
+- (void)observeValueForKeyPath:(NSString*)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary*)change
+                       context:(void*)context {
+  // If this is the default encoding, then set the flag to persist the value.
+  if ([keyPath isEqual:@"defaultEncodingIndex_"]) {
+    changedEncoding_ = YES;
+    return;
+  }
+
+  [super observeValueForKeyPath:keyPath
+                       ofObject:object
+                         change:change
+                        context:context];
+}
+
+#pragma mark Private
+
+// Set the baseline for the font field to be aligned with the baseline
+// of its corresponding label.
+- (NSPoint)getFontFieldOrigin:(NSTextField*)field
+                     forLabel:(NSTextField*)label {
+  [field sizeToFit];
+  NSRect labelFrame = [label frame];
+  NSPoint newOrigin =
+      [[label superview] convertPoint:labelFrame.origin
+                               toView:[field superview]];
+  newOrigin.x = 0;  // Left-align font field.
+  newOrigin.y += [[field font] descender] - [[label font] descender];
+  return newOrigin;
+}
+
+// This will set the font on |field| to be |font|, and will set the string
+// value to something human-readable.
+- (void)updateDisplayField:(NSTextField*)field
+                  withFont:(NSFont*)font
+                 withLabel:(NSTextField*)label {
+  if (!font) {
+    // Something has gone really wrong. Don't make things worse by showing the
+    // user "(null)".
+    return;
+  }
+  [field setFont:font];
+  NSString* value =
+      [NSString stringWithFormat:@"%@, %g", [font fontName], [font pointSize]];
+  [field setStringValue:value];
+  [field setFrameOrigin:[self getFontFieldOrigin:field forLabel:label]];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/font_language_settings_controller_unittest.mm b/chrome/browser/ui/cocoa/options/font_language_settings_controller_unittest.mm
new file mode 100644
index 0000000..1cac9a0
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/font_language_settings_controller_unittest.mm
@@ -0,0 +1,91 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/character_encoding.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/font_language_settings_controller.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+// The FontLanguageSettingsControllerForTest overrides the getFontFieldOrigin
+// method to provide a dummy point, so we don't have to actually display the
+// window to test the controller.
+@interface FontLanguageSettingsControllerForTest :
+    FontLanguageSettingsController {
+}
+
+- (NSPoint)getFontFieldOrigin:(NSTextField*)field
+                     forLabel:(NSTextField*)label;
+
+@end
+
+@implementation FontLanguageSettingsControllerForTest
+
+- (NSPoint)getFontFieldOrigin:(NSTextField*)field
+                     forLabel:(NSTextField*)label {
+  return NSMakePoint(10, 10);
+}
+
+@end
+
+@interface FontLanguageSettingsController (Testing)
+- (void)updateDisplayField:(NSTextField*)field
+                  withFont:(NSFont*)font
+                 withLabel:(NSTextField*)label;
+@end
+
+class FontLanguageSettingsControllerTest : public CocoaTest {
+ public:
+  FontLanguageSettingsControllerTest() {
+    Profile* profile = helper_.profile();
+    font_controller_.reset([[FontLanguageSettingsControllerForTest alloc]
+        initWithProfile:profile]);
+   }
+  ~FontLanguageSettingsControllerTest() {}
+
+  BrowserTestHelper helper_;
+  scoped_nsobject<FontLanguageSettingsController> font_controller_;
+};
+
+TEST_F(FontLanguageSettingsControllerTest, Init) {
+  ASSERT_EQ(CharacterEncoding::GetSupportCanonicalEncodingCount(),
+      static_cast<int>([[font_controller_ encodings] count]));
+}
+
+TEST_F(FontLanguageSettingsControllerTest, UpdateDisplayField) {
+  NSFont* font = [NSFont fontWithName:@"Times-Roman" size:12.0];
+  scoped_nsobject<NSTextField> field(
+      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
+  scoped_nsobject<NSTextField> label(
+      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
+  [font_controller_ updateDisplayField:field.get()
+                              withFont:font
+                             withLabel:label];
+
+  ASSERT_NSEQ([font fontName], [[field font] fontName]);
+  ASSERT_NSEQ(@"Times-Roman, 12", [field stringValue]);
+}
+
+TEST_F(FontLanguageSettingsControllerTest, UpdateDisplayFieldNilFont) {
+  scoped_nsobject<NSTextField> field(
+      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
+  scoped_nsobject<NSTextField> label(
+      [[NSTextField alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]);
+  [field setStringValue:@"foo"];
+  [font_controller_ updateDisplayField:field.get()
+                              withFont:nil
+                             withLabel:label];
+
+  ASSERT_NSEQ(@"foo", [field stringValue]);
+}
+
+TEST_F(FontLanguageSettingsControllerTest, UpdateDisplayFieldNilField) {
+  // Don't crash.
+  NSFont* font = [NSFont fontWithName:@"Times-Roman" size:12.0];
+  [font_controller_ updateDisplayField:nil withFont:font withLabel:nil];
+}
diff --git a/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h b/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h
new file mode 100644
index 0000000..7a9d519
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h
@@ -0,0 +1,117 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "chrome/browser/search_engines/edit_search_engine_controller.h"
+#include "chrome/browser/search_engines/keyword_editor_controller.h"
+#include "chrome/browser/search_engines/template_url_model_observer.h"
+#include "chrome/browser/ui/cocoa/table_row_nsimage_cache.h"
+#include "ui/base/models/table_model_observer.h"
+
+class EditSearchEngineControllerDelegate;
+@class KeywordEditorCocoaController;
+class Profile;
+@class WindowSizeAutosaver;
+
+// Very thin bridge that simply pushes notifications from C++ to ObjC.
+class KeywordEditorModelObserver : public TemplateURLModelObserver,
+                                   public EditSearchEngineControllerDelegate,
+                                   public ui::TableModelObserver,
+                                   public TableRowNSImageCache::Table {
+ public:
+  explicit KeywordEditorModelObserver(KeywordEditorCocoaController* controller);
+  virtual ~KeywordEditorModelObserver();
+
+  // Notification that the template url model has changed in some way.
+  virtual void OnTemplateURLModelChanged();
+
+  // Invoked from the EditSearchEngineController when the user accepts the
+  // edits. NOTE: |template_url| is the value supplied to
+  // EditSearchEngineController's constructor, and may be NULL. A NULL value
+  // indicates a new TemplateURL should be created rather than modifying an
+  // existing TemplateURL.
+  virtual void OnEditedKeyword(const TemplateURL* template_url,
+                               const string16& title,
+                               const string16& keyword,
+                               const std::string& url);
+
+  // ui::TableModelObserver overrides. Invalidate icon cache.
+  virtual void OnModelChanged();
+  virtual void OnItemsChanged(int start, int length);
+  virtual void OnItemsAdded(int start, int length);
+  virtual void OnItemsRemoved(int start, int length);
+
+  // TableRowNSImageCache::Table
+  virtual int RowCount() const;
+  virtual SkBitmap GetIcon(int row) const;
+
+  // Lazily converts the image at the given row and caches it in |icon_cache_|.
+  NSImage* GetImageForRow(int row);
+
+ private:
+  KeywordEditorCocoaController* controller_;
+
+  TableRowNSImageCache icon_cache_;
+
+  DISALLOW_COPY_AND_ASSIGN(KeywordEditorModelObserver);
+};
+
+// This controller manages a window with a table view of search engines. It
+// acts as |tableView_|'s data source and delegate, feeding it data from the
+// KeywordEditorController's |table_model()|.
+
+@interface KeywordEditorCocoaController : NSWindowController
+                                          <NSWindowDelegate,
+                                           NSTableViewDataSource,
+                                           NSTableViewDelegate> {
+  IBOutlet NSTableView* tableView_;
+  IBOutlet NSButton* addButton_;
+  IBOutlet NSButton* removeButton_;
+  IBOutlet NSButton* makeDefaultButton_;
+
+  scoped_nsobject<NSTextFieldCell> groupCell_;
+
+  Profile* profile_;  // weak
+  scoped_ptr<KeywordEditorController> controller_;
+  scoped_ptr<KeywordEditorModelObserver> observer_;
+
+  scoped_nsobject<WindowSizeAutosaver> sizeSaver_;
+}
+@property(nonatomic, readonly) KeywordEditorController* controller;
+
+// Show the keyword editor associated with the given profile (or the
+// original profile if this is an incognito profile).  If no keyword
+// editor exists for this profile, create one and show it.  Any
+// resulting editor releases itself when closed.
++ (void)showKeywordEditor:(Profile*)profile;
+
+- (KeywordEditorController*)controller;
+
+// Message forwarded by KeywordEditorModelObserver.
+- (void)modelChanged;
+
+- (IBAction)addKeyword:(id)sender;
+- (IBAction)deleteKeyword:(id)sender;
+- (IBAction)makeDefault:(id)sender;
+
+@end
+
+@interface KeywordEditorCocoaController (TestingAPI)
+
+// Instances of this class are managed, use +showKeywordEditor:.
+- (id)initWithProfile:(Profile*)profile;
+
+// Returns a reference to the shared instance for the given profile,
+// or nil if there is none.
++ (KeywordEditorCocoaController*)sharedInstanceForProfile:(Profile*)profile;
+
+// Converts a row index in our table view (which has group header rows) into
+// one in the |controller_|'s model, which does not have them.
+- (int)indexInModelForRow:(NSUInteger)row;
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.mm b/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.mm
new file mode 100644
index 0000000..119a69d
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.mm
@@ -0,0 +1,425 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h"
+
+#import "base/mac/mac_util.h"
+#include "base/lazy_instance.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/template_url_table_model.h"
+#import "chrome/browser/ui/cocoa/options/edit_search_engine_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/window_size_autosaver.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace {
+
+const CGFloat kButtonBarHeight = 35.0;
+
+}  // namespace
+
+@interface KeywordEditorCocoaController (Private)
+- (void)adjustEditingButtons;
+- (void)editKeyword:(id)sender;
+- (int)indexInModelForRow:(NSUInteger)row;
+@end
+
+// KeywordEditorModelObserver -------------------------------------------------
+
+KeywordEditorModelObserver::KeywordEditorModelObserver(
+    KeywordEditorCocoaController* controller)
+    : controller_(controller),
+      icon_cache_(this) {
+}
+
+KeywordEditorModelObserver::~KeywordEditorModelObserver() {
+}
+
+// Notification that the template url model has changed in some way.
+void KeywordEditorModelObserver::OnTemplateURLModelChanged() {
+  [controller_ modelChanged];
+}
+
+void KeywordEditorModelObserver::OnEditedKeyword(
+    const TemplateURL* template_url,
+    const string16& title,
+    const string16& keyword,
+    const std::string& url) {
+  KeywordEditorController* controller = [controller_ controller];
+  if (template_url) {
+    controller->ModifyTemplateURL(template_url, title, keyword, url);
+  } else {
+    controller->AddTemplateURL(title, keyword, url);
+  }
+}
+
+void KeywordEditorModelObserver::OnModelChanged() {
+  icon_cache_.OnModelChanged();
+  [controller_ modelChanged];
+}
+
+void KeywordEditorModelObserver::OnItemsChanged(int start, int length) {
+  icon_cache_.OnItemsChanged(start, length);
+  [controller_ modelChanged];
+}
+
+void KeywordEditorModelObserver::OnItemsAdded(int start, int length) {
+  icon_cache_.OnItemsAdded(start, length);
+  [controller_ modelChanged];
+}
+
+void KeywordEditorModelObserver::OnItemsRemoved(int start, int length) {
+  icon_cache_.OnItemsRemoved(start, length);
+  [controller_ modelChanged];
+}
+
+int KeywordEditorModelObserver::RowCount() const {
+  return [controller_ controller]->table_model()->RowCount();
+}
+
+SkBitmap KeywordEditorModelObserver::GetIcon(int row) const {
+  return [controller_ controller]->table_model()->GetIcon(row);
+}
+
+NSImage* KeywordEditorModelObserver::GetImageForRow(int row) {
+  return icon_cache_.GetImageForRow(row);
+}
+
+// KeywordEditorCocoaController -----------------------------------------------
+
+namespace {
+
+typedef std::map<Profile*,KeywordEditorCocoaController*> ProfileControllerMap;
+
+static base::LazyInstance<ProfileControllerMap> g_profile_controller_map(
+    base::LINKER_INITIALIZED);
+
+}  // namespace
+
+@implementation KeywordEditorCocoaController
+
++ (KeywordEditorCocoaController*)sharedInstanceForProfile:(Profile*)profile {
+  ProfileControllerMap* map = g_profile_controller_map.Pointer();
+  DCHECK(map != NULL);
+  ProfileControllerMap::iterator it = map->find(profile);
+  if (it != map->end()) {
+    return it->second;
+  }
+  return nil;
+}
+
+// TODO(shess): The Windows code watches a single global window which
+// is not distinguished by profile.  This code could distinguish by
+// profile by checking the controller's class and profile.
++ (void)showKeywordEditor:(Profile*)profile {
+  // http://crbug.com/23359 describes a case where this panel is
+  // opened from an incognito window, which can leave the panel
+  // holding onto a stale profile.  Since the same panel is used
+  // either way, arrange to use the original profile instead.
+  profile = profile->GetOriginalProfile();
+
+  ProfileControllerMap* map = g_profile_controller_map.Pointer();
+  DCHECK(map != NULL);
+  ProfileControllerMap::iterator it = map->find(profile);
+  if (it == map->end()) {
+    // Since we don't currently support multiple profiles, this class
+    // has not been tested against them, so document that assumption.
+    DCHECK_EQ(map->size(), 0U);
+
+    KeywordEditorCocoaController* controller =
+        [[self alloc] initWithProfile:profile];
+    it = map->insert(std::make_pair(profile, controller)).first;
+  }
+
+  [it->second showWindow:nil];
+}
+
+- (id)initWithProfile:(Profile*)profile {
+  DCHECK(profile);
+  NSString* nibpath = [base::mac::MainAppBundle()
+                        pathForResource:@"KeywordEditor"
+                                 ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+    profile_ = profile;
+    controller_.reset(new KeywordEditorController(profile_));
+    observer_.reset(new KeywordEditorModelObserver(self));
+    controller_->table_model()->SetObserver(observer_.get());
+    controller_->url_model()->AddObserver(observer_.get());
+    groupCell_.reset([[NSTextFieldCell alloc] init]);
+
+    if (g_browser_process && g_browser_process->local_state()) {
+      sizeSaver_.reset([[WindowSizeAutosaver alloc]
+          initWithWindow:[self window]
+             prefService:g_browser_process->local_state()
+                    path:prefs::kKeywordEditorWindowPlacement]);
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  controller_->table_model()->SetObserver(NULL);
+  controller_->url_model()->RemoveObserver(observer_.get());
+  [tableView_ setDataSource:nil];
+  observer_.reset();
+  [super dealloc];
+}
+
+- (void)awakeFromNib {
+  // Make sure the button fits its label, but keep it the same height as the
+  // other two buttons.
+  [GTMUILocalizerAndLayoutTweaker sizeToFitView:makeDefaultButton_];
+  NSSize size = [makeDefaultButton_ frame].size;
+  size.height = NSHeight([addButton_ frame]);
+  [makeDefaultButton_ setFrameSize:size];
+
+  [[self window] setAutorecalculatesContentBorderThickness:NO
+                                                   forEdge:NSMinYEdge];
+  [[self window] setContentBorderThickness:kButtonBarHeight
+                                   forEdge:NSMinYEdge];
+
+  [self adjustEditingButtons];
+  [tableView_ setDoubleAction:@selector(editKeyword:)];
+  [tableView_ setTarget:self];
+}
+
+// When the window closes, clean ourselves up.
+- (void)windowWillClose:(NSNotification*)notif {
+  [self autorelease];
+
+  ProfileControllerMap* map = g_profile_controller_map.Pointer();
+  ProfileControllerMap::iterator it = map->find(profile_);
+  // It should not be possible for this to be missing.
+  // TODO(shess): Except that the unit test reaches in directly.
+  // Consider circling around and refactoring that.
+  //DCHECK(it != map->end());
+  if (it != map->end()) {
+    map->erase(it);
+  }
+}
+
+- (void)modelChanged {
+  [tableView_ reloadData];
+  [self adjustEditingButtons];
+}
+
+- (KeywordEditorController*)controller {
+  return controller_.get();
+}
+
+- (void)sheetDidEnd:(NSWindow*)sheet
+         returnCode:(NSInteger)code
+            context:(void*)context {
+  [sheet orderOut:self];
+}
+
+- (IBAction)addKeyword:(id)sender {
+  // The controller will release itself when the window closes.
+  EditSearchEngineCocoaController* editor =
+      [[EditSearchEngineCocoaController alloc] initWithProfile:profile_
+                                                      delegate:observer_.get()
+                                                   templateURL:NULL];
+  [NSApp beginSheet:[editor window]
+     modalForWindow:[self window]
+      modalDelegate:self
+     didEndSelector:@selector(sheetDidEnd:returnCode:context:)
+        contextInfo:NULL];
+}
+
+- (void)editKeyword:(id)sender {
+  const NSInteger clickedRow = [tableView_ clickedRow];
+  if (clickedRow < 0 || [self tableView:tableView_ isGroupRow:clickedRow])
+    return;
+  const TemplateURL* url = controller_->GetTemplateURL(
+      [self indexInModelForRow:clickedRow]);
+  // The controller will release itself when the window closes.
+  EditSearchEngineCocoaController* editor =
+      [[EditSearchEngineCocoaController alloc] initWithProfile:profile_
+                                                      delegate:observer_.get()
+                                                   templateURL:url];
+  [NSApp beginSheet:[editor window]
+     modalForWindow:[self window]
+      modalDelegate:self
+     didEndSelector:@selector(sheetDidEnd:returnCode:context:)
+        contextInfo:NULL];
+}
+
+- (IBAction)deleteKeyword:(id)sender {
+  NSIndexSet* selection = [tableView_ selectedRowIndexes];
+  DCHECK_GT([selection count], 0U);
+  NSUInteger index = [selection lastIndex];
+  while (index != NSNotFound) {
+    controller_->RemoveTemplateURL([self indexInModelForRow:index]);
+    index = [selection indexLessThanIndex:index];
+  }
+}
+
+- (IBAction)makeDefault:(id)sender {
+  NSIndexSet* selection = [tableView_ selectedRowIndexes];
+  DCHECK_EQ([selection count], 1U);
+  int row = [self indexInModelForRow:[selection firstIndex]];
+  controller_->MakeDefaultTemplateURL(row);
+}
+
+// Called when the user hits the escape key. Closes the window.
+- (void)cancel:(id)sender {
+  [[self window] performClose:self];
+}
+
+// Table View Data Source -----------------------------------------------------
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView*)table {
+  int rowCount = controller_->table_model()->RowCount();
+  int numGroups = controller_->table_model()->GetGroups().size();
+  if ([self tableView:table isGroupRow:rowCount + numGroups - 1]) {
+    // Don't show a group header with no rows underneath it.
+    --numGroups;
+  }
+  return rowCount + numGroups;
+}
+
+- (id)tableView:(NSTableView*)tv
+    objectValueForTableColumn:(NSTableColumn*)tableColumn
+                          row:(NSInteger)row {
+  if ([self tableView:tv isGroupRow:row]) {
+    DCHECK(!tableColumn);
+    ui::TableModel::Groups groups = controller_->table_model()->GetGroups();
+    if (row == 0) {
+      return base::SysUTF16ToNSString(groups[0].title);
+    } else {
+      return base::SysUTF16ToNSString(groups[1].title);
+    }
+  }
+
+  NSString* identifier = [tableColumn identifier];
+  if ([identifier isEqualToString:@"name"]) {
+    // The name column is an NSButtonCell so we can have text and image in the
+    // same cell. As such, the "object value" for a button cell is either on
+    // or off, so we always return off so we don't act like a button.
+    return [NSNumber numberWithInt:NSOffState];
+  }
+  if ([identifier isEqualToString:@"keyword"]) {
+    // The keyword object value is a normal string.
+    int index = [self indexInModelForRow:row];
+    int columnID = IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN;
+    string16 text = controller_->table_model()->GetText(index, columnID);
+    return base::SysUTF16ToNSString(text);
+  }
+
+  // And we shouldn't have any other columns...
+  NOTREACHED();
+  return nil;
+}
+
+// Table View Delegate --------------------------------------------------------
+
+// When the selection in the table view changes, we need to adjust buttons.
+- (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
+  [self adjustEditingButtons];
+}
+
+// Disallow selection of the group header rows.
+- (BOOL)tableView:(NSTableView*)table shouldSelectRow:(NSInteger)row {
+  return ![self tableView:table isGroupRow:row];
+}
+
+- (BOOL)tableView:(NSTableView*)table isGroupRow:(NSInteger)row {
+  int otherGroupRow =
+      controller_->table_model()->last_search_engine_index() + 1;
+  return (row == 0 || row == otherGroupRow);
+}
+
+- (NSCell*)tableView:(NSTableView*)tableView
+    dataCellForTableColumn:(NSTableColumn*)tableColumn
+                       row:(NSInteger)row {
+  static const CGFloat kCellFontSize = 12.0;
+
+  // Check to see if we are a grouped row.
+  if ([self tableView:tableView isGroupRow:row]) {
+    DCHECK(!tableColumn);  // This would violate the group row contract.
+    return groupCell_.get();
+  }
+
+  NSCell* cell = [tableColumn dataCellForRow:row];
+  int offsetRow = [self indexInModelForRow:row];
+
+  // Set the favicon and title for the search engine in the name column.
+  if ([[tableColumn identifier] isEqualToString:@"name"]) {
+    DCHECK([cell isKindOfClass:[NSButtonCell class]]);
+    NSButtonCell* buttonCell = static_cast<NSButtonCell*>(cell);
+    string16 title = controller_->table_model()->GetText(offsetRow,
+        IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN);
+    [buttonCell setTitle:base::SysUTF16ToNSString(title)];
+    [buttonCell setImage:observer_->GetImageForRow(offsetRow)];
+    [buttonCell setRefusesFirstResponder:YES];  // Don't push in like a button.
+    [buttonCell setHighlightsBy:NSNoCellMask];
+  }
+
+  // The default search engine should be in bold font.
+  const TemplateURL* defaultEngine =
+      controller_->url_model()->GetDefaultSearchProvider();
+  int rowIndex = controller_->table_model()->IndexOfTemplateURL(defaultEngine);
+  if (rowIndex == offsetRow) {
+    [cell setFont:[NSFont boldSystemFontOfSize:kCellFontSize]];
+  } else {
+    [cell setFont:[NSFont systemFontOfSize:kCellFontSize]];
+  }
+  return cell;
+}
+
+// Private --------------------------------------------------------------------
+
+// This function appropriately sets the enabled states on the table's editing
+// buttons.
+- (void)adjustEditingButtons {
+  NSIndexSet* selection = [tableView_ selectedRowIndexes];
+  BOOL canRemove = ([selection count] > 0);
+  NSUInteger index = [selection firstIndex];
+
+  // Delete button.
+  while (canRemove && index != NSNotFound) {
+    int modelIndex = [self indexInModelForRow:index];
+    const TemplateURL& url =
+        controller_->table_model()->GetTemplateURL(modelIndex);
+    if (!controller_->CanRemove(&url))
+      canRemove = NO;
+    index = [selection indexGreaterThanIndex:index];
+  }
+  [removeButton_ setEnabled:canRemove];
+
+  // Make default button.
+  if ([selection count] != 1) {
+    [makeDefaultButton_ setEnabled:NO];
+  } else {
+    int row = [self indexInModelForRow:[selection firstIndex]];
+    const TemplateURL& url =
+        controller_->table_model()->GetTemplateURL(row);
+    [makeDefaultButton_ setEnabled:controller_->CanMakeDefault(&url)];
+  }
+}
+
+// This converts a row index in our table view to an index in the model by
+// computing the group offsets.
+- (int)indexInModelForRow:(NSUInteger)row {
+  DCHECK_GT(row, 0U);
+  unsigned otherGroupId =
+      controller_->table_model()->last_search_engine_index() + 1;
+  DCHECK_NE(row, otherGroupId);
+  if (row >= otherGroupId) {
+    return row - 2;  // Other group.
+  } else {
+    return row - 1;  // Default group.
+  }
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller_unittest.mm b/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller_unittest.mm
new file mode 100644
index 0000000..8810992
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller_unittest.mm
@@ -0,0 +1,227 @@
+// Copyright (c) 2011 The Chromium 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/mac/scoped_nsautorelease_pool.h"
+#include "base/scoped_nsobject.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface FakeKeywordEditorController : KeywordEditorCocoaController {
+ @public
+  BOOL modelChanged_;
+}
+- (void)modelChanged;
+- (BOOL)hasModelChanged;
+- (KeywordEditorModelObserver*)observer;
+@end
+
+@implementation FakeKeywordEditorController
+
+- (void)modelChanged {
+  modelChanged_ = YES;
+}
+
+- (BOOL)hasModelChanged {
+  return modelChanged_;
+}
+
+- (KeywordEditorModelObserver*)observer {
+  return observer_.get();
+}
+
+- (NSTableView*)tableView {
+  return tableView_;
+}
+
+@end
+
+// TODO(rsesek): Figure out a good way to test this class (crbug.com/21640).
+
+namespace {
+
+class KeywordEditorCocoaControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    TestingProfile* profile =
+        static_cast<TestingProfile*>(browser_helper_.profile());
+    profile->CreateTemplateURLModel();
+
+    controller_ =
+        [[FakeKeywordEditorController alloc] initWithProfile:profile];
+  }
+
+  virtual void TearDown() {
+    // Force the window to load so we hit |-awakeFromNib| to register as the
+    // window's delegate so that the controller can clean itself up in
+    // |-windowWillClose:|.
+    ASSERT_TRUE([controller_ window]);
+
+    [controller_ close];
+    CocoaTest::TearDown();
+  }
+
+  // Helper to count the keyword editors.
+  NSUInteger CountKeywordEditors() {
+    base::mac::ScopedNSAutoreleasePool pool;
+    NSUInteger count = 0;
+    for (NSWindow* window in [NSApp windows]) {
+      id controller = [window windowController];
+      if ([controller isKindOfClass:[KeywordEditorCocoaController class]]) {
+        ++count;
+      }
+    }
+    return count;
+  }
+
+  BrowserTestHelper browser_helper_;
+  FakeKeywordEditorController* controller_;
+};
+
+TEST_F(KeywordEditorCocoaControllerTest, TestModelChanged) {
+  EXPECT_FALSE([controller_ hasModelChanged]);
+  KeywordEditorModelObserver* observer = [controller_ observer];
+  observer->OnTemplateURLModelChanged();
+  EXPECT_TRUE([controller_ hasModelChanged]);
+}
+
+// Test that +showKeywordEditor brings up the existing editor and
+// creates one if needed.
+TEST_F(KeywordEditorCocoaControllerTest, ShowKeywordEditor) {
+  // No outstanding editors.
+  Profile* profile(browser_helper_.profile());
+  KeywordEditorCocoaController* sharedInstance =
+      [KeywordEditorCocoaController sharedInstanceForProfile:profile];
+  EXPECT_TRUE(nil == sharedInstance);
+  EXPECT_EQ(CountKeywordEditors(), 0U);
+
+  const NSUInteger initial_window_count([[NSApp windows] count]);
+
+  // The window unwinds using -autorelease, so we need to introduce an
+  // autorelease pool to really test whether it went away or not.
+  {
+    base::mac::ScopedNSAutoreleasePool pool;
+
+    // +showKeywordEditor: creates a new controller.
+    [KeywordEditorCocoaController showKeywordEditor:profile];
+    sharedInstance =
+        [KeywordEditorCocoaController sharedInstanceForProfile:profile];
+    EXPECT_TRUE(sharedInstance);
+    EXPECT_EQ(CountKeywordEditors(), 1U);
+
+    // Another call doesn't create another controller.
+    [KeywordEditorCocoaController showKeywordEditor:profile];
+    EXPECT_TRUE(sharedInstance ==
+        [KeywordEditorCocoaController sharedInstanceForProfile:profile]);
+    EXPECT_EQ(CountKeywordEditors(), 1U);
+
+    [sharedInstance close];
+  }
+
+  // No outstanding editors.
+  sharedInstance =
+      [KeywordEditorCocoaController sharedInstanceForProfile:profile];
+  EXPECT_TRUE(nil == sharedInstance);
+  EXPECT_EQ(CountKeywordEditors(), 0U);
+
+  // Windows we created should be gone.
+  EXPECT_EQ([[NSApp windows] count], initial_window_count);
+
+  // Get a new editor, should be different from the previous one.
+  [KeywordEditorCocoaController showKeywordEditor:profile];
+  KeywordEditorCocoaController* newSharedInstance =
+      [KeywordEditorCocoaController sharedInstanceForProfile:profile];
+  EXPECT_TRUE(sharedInstance != newSharedInstance);
+  EXPECT_EQ(CountKeywordEditors(), 1U);
+  [newSharedInstance close];
+}
+
+TEST_F(KeywordEditorCocoaControllerTest, IndexInModelForRowMixed) {
+  [controller_ window];  // Force |-awakeFromNib|.
+  TemplateURLModel* template_model = [controller_ controller]->url_model();
+
+  // Add a default engine.
+  TemplateURL* t_url = new TemplateURL();
+  t_url->SetURL("http://test1/{searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("test1"));
+  t_url->set_short_name(ASCIIToUTF16("Test1"));
+  t_url->set_show_in_default_list(true);
+  template_model->Add(t_url);
+
+  // Add a non-default engine.
+  t_url = new TemplateURL();
+  t_url->SetURL("http://test2/{searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("test2"));
+  t_url->set_short_name(ASCIIToUTF16("Test2"));
+  t_url->set_show_in_default_list(false);
+  template_model->Add(t_url);
+
+  // Two headers with a single row underneath each.
+  NSTableView* table = [controller_ tableView];
+  [table reloadData];
+  ASSERT_EQ(4, [[controller_ tableView] numberOfRows]);
+
+  // Index 0 is the group header, index 1 should be the first engine.
+  ASSERT_EQ(0, [controller_ indexInModelForRow:1]);
+
+  // Index 2 should be the group header, so index 3 should be the non-default
+  // engine.
+  ASSERT_EQ(1, [controller_ indexInModelForRow:3]);
+
+  ASSERT_TRUE([controller_ tableView:table isGroupRow:0]);
+  ASSERT_FALSE([controller_ tableView:table isGroupRow:1]);
+  ASSERT_TRUE([controller_ tableView:table isGroupRow:2]);
+  ASSERT_FALSE([controller_ tableView:table isGroupRow:3]);
+
+  ASSERT_FALSE([controller_ tableView:table shouldSelectRow:0]);
+  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:1]);
+  ASSERT_FALSE([controller_ tableView:table shouldSelectRow:2]);
+  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:3]);
+}
+
+TEST_F(KeywordEditorCocoaControllerTest, IndexInModelForDefault) {
+  [controller_ window];  // Force |-awakeFromNib|.
+  TemplateURLModel* template_model = [controller_ controller]->url_model();
+
+  // Add 2 default engines.
+  TemplateURL* t_url = new TemplateURL();
+  t_url->SetURL("http://test1/{searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("test1"));
+  t_url->set_short_name(ASCIIToUTF16("Test1"));
+  t_url->set_show_in_default_list(true);
+  template_model->Add(t_url);
+
+  t_url = new TemplateURL();
+  t_url->SetURL("http://test2/{searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("test2"));
+  t_url->set_short_name(ASCIIToUTF16("Test2"));
+  t_url->set_show_in_default_list(true);
+  template_model->Add(t_url);
+
+  // One header and two rows.
+  NSTableView* table = [controller_ tableView];
+  [table reloadData];
+  ASSERT_EQ(3, [[controller_ tableView] numberOfRows]);
+
+  // Index 0 is the group header, index 1 should be the first engine.
+  ASSERT_EQ(0, [controller_ indexInModelForRow:1]);
+  ASSERT_EQ(1, [controller_ indexInModelForRow:2]);
+
+  ASSERT_TRUE([controller_ tableView:table isGroupRow:0]);
+  ASSERT_FALSE([controller_ tableView:table isGroupRow:1]);
+  ASSERT_FALSE([controller_ tableView:table isGroupRow:2]);
+
+  ASSERT_FALSE([controller_ tableView:table shouldSelectRow:0]);
+  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:1]);
+  ASSERT_TRUE([controller_ tableView:table shouldSelectRow:2]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/options/preferences_window_controller.h b/chrome/browser/ui/cocoa/options/preferences_window_controller.h
new file mode 100644
index 0000000..3815beb
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/preferences_window_controller.h
@@ -0,0 +1,242 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_ptr.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/prefs/pref_set_observer.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/ui/options/options_window.h"
+
+namespace PreferencesWindowControllerInternal {
+class PrefObserverBridge;
+class ManagedPrefsBannerState;
+}
+
+@class CustomHomePagesModel;
+@class FontLanguageSettingsController;
+class PrefService;
+class Profile;
+class ProfileSyncService;
+@class SearchEngineListModel;
+@class VerticalGradientView;
+@class WindowSizeAutosaver;
+
+// A window controller that handles the preferences window. The bulk of the
+// work is handled via Cocoa Bindings and getter/setter methods that wrap
+// cross-platform PrefMember objects. When prefs change in the back-end
+// (that is, outside of this UI), our observer receives a notification and can
+// tickle the KVO to update the UI so we are always in sync. The bindings are
+// specified in the nib file. Preferences are persisted into the back-end
+// as they are changed in the UI, and are thus immediately available even while
+// the window is still open. When the window closes, a notification is sent
+// via the system NotificationCenter. This can be used as a signal to
+// release this controller, as it's likely the client wants to enforce there
+// only being one (we don't do that internally as it makes it very difficult
+// to unit test).
+@interface PreferencesWindowController : NSWindowController {
+ @private
+  Profile* profile_;  // weak ref
+  OptionsPage initialPage_;
+  PrefService* prefs_;  // weak ref - Obtained from profile_ for convenience.
+  // weak ref - Also obtained from profile_ for convenience.  May be NULL.
+  ProfileSyncService* syncService_;
+  scoped_ptr<PreferencesWindowControllerInternal::PrefObserverBridge>
+      observer_;  // Watches for pref changes.
+  PrefChangeRegistrar registrar_;  // Manages pref change observer registration.
+  scoped_nsobject<WindowSizeAutosaver> sizeSaver_;
+  NSView* currentPrefsView_;  // weak ref - current prefs page view.
+  scoped_ptr<PreferencesWindowControllerInternal::ManagedPrefsBannerState>
+      bannerState_;
+  BOOL managedPrefsBannerVisible_;
+
+  IBOutlet NSToolbar* toolbar_;
+  IBOutlet VerticalGradientView* managedPrefsBannerView_;
+  IBOutlet NSImageView* managedPrefsBannerWarningImage_;
+
+  // The views we'll rotate through
+  IBOutlet NSView* basicsView_;
+  IBOutlet NSView* personalStuffView_;
+  IBOutlet NSView* underTheHoodView_;
+  // The last page the user was on when they opened the Options window.
+  IntegerPrefMember lastSelectedPage_;
+
+  // The groups of the Basics view for layout fixup.
+  IBOutlet NSArray* basicsGroupStartup_;
+  IBOutlet NSArray* basicsGroupHomePage_;
+  IBOutlet NSArray* basicsGroupToolbar_;
+  IBOutlet NSArray* basicsGroupSearchEngine_;
+  IBOutlet NSArray* basicsGroupDefaultBrowser_;
+
+  // The groups of the Personal Stuff view for layout fixup.
+  IBOutlet NSArray* personalStuffGroupSync_;
+  IBOutlet NSArray* personalStuffGroupPasswords_;
+  IBOutlet NSArray* personalStuffGroupAutofill_;
+  IBOutlet NSArray* personalStuffGroupBrowserData_;
+  IBOutlet NSArray* personalStuffGroupThemes_;
+
+  // Having two animations around is bad (they fight), so just use one.
+  scoped_nsobject<NSViewAnimation> animation_;
+
+  IBOutlet NSArrayController* customPagesArrayController_;
+
+  // Basics panel
+  IntegerPrefMember restoreOnStartup_;
+  scoped_nsobject<CustomHomePagesModel> customPagesSource_;
+  BooleanPrefMember newTabPageIsHomePage_;
+  StringPrefMember homepage_;
+  BooleanPrefMember showHomeButton_;
+  BooleanPrefMember instantEnabled_;
+  IBOutlet NSButton* instantCheckbox_;
+  scoped_nsobject<SearchEngineListModel> searchEngineModel_;
+  BooleanPrefMember default_browser_policy_;
+  // Used when creating a new home page url to make the new cell editable.
+  BOOL pendingSelectForEdit_;
+  BOOL restoreButtonsEnabled_;
+  BOOL restoreURLsEnabled_;
+  BOOL showHomeButtonEnabled_;
+  BOOL defaultSearchEngineEnabled_;
+
+  // User Data panel
+  BooleanPrefMember askSavePasswords_;
+  BooleanPrefMember autoFillEnabled_;
+  IBOutlet NSButton* autoFillSettingsButton_;
+  IBOutlet NSButton* syncButton_;
+  IBOutlet NSButton* syncCustomizeButton_;
+  IBOutlet NSTextField* syncStatus_;
+  IBOutlet NSButton* syncLink_;
+  IBOutlet NSButton* privacyDashboardLink_;
+  scoped_nsobject<NSColor> syncStatusNoErrorBackgroundColor_;
+  scoped_nsobject<NSColor> syncLinkNoErrorBackgroundColor_;
+  scoped_nsobject<NSColor> syncErrorBackgroundColor_;
+  BOOL passwordManagerChoiceEnabled_;
+  BOOL passwordManagerButtonEnabled_;
+  BOOL autoFillSettingsButtonEnabled_;
+
+  // Under the hood panel
+  IBOutlet NSView* underTheHoodContentView_;
+  IBOutlet NSScrollView* underTheHoodScroller_;
+  IBOutlet NSButton* contentSettingsButton_;
+  IBOutlet NSButton* clearDataButton_;
+  BooleanPrefMember alternateErrorPages_;
+  BooleanPrefMember useSuggest_;
+  BooleanPrefMember dnsPrefetch_;
+  BooleanPrefMember safeBrowsing_;
+  BooleanPrefMember metricsReporting_;
+  IBOutlet NSPathControl* downloadLocationControl_;
+  IBOutlet NSButton* downloadLocationButton_;
+  StringPrefMember defaultDownloadLocation_;
+  BooleanPrefMember askForSaveLocation_;
+  IBOutlet NSButton* resetFileHandlersButton_;
+  StringPrefMember autoOpenFiles_;
+  BooleanPrefMember translateEnabled_;
+  BooleanPrefMember tabsToLinks_;
+  FontLanguageSettingsController* fontLanguageSettings_;
+  StringPrefMember currentTheme_;
+  IBOutlet NSButton* enableLoggingCheckbox_;
+  scoped_ptr<PrefSetObserver> proxyPrefs_;
+  BOOL showAlternateErrorPagesEnabled_;
+  BOOL useSuggestEnabled_;
+  BOOL dnsPrefetchEnabled_;
+  BOOL safeBrowsingEnabled_;
+  BOOL metricsReportingEnabled_;
+  BOOL proxiesConfigureButtonEnabled_;
+}
+
+// Usable from cocoa bindings to hook up the custom home pages table.
+@property(nonatomic, readonly) CustomHomePagesModel* customPagesSource;
+
+// Properties for the enabled state of various UI elements. Keep these ordered
+// by occurrence on the dialog.
+@property(nonatomic) BOOL restoreButtonsEnabled;
+@property(nonatomic) BOOL restoreURLsEnabled;
+@property(nonatomic) BOOL showHomeButtonEnabled;
+@property(nonatomic) BOOL defaultSearchEngineEnabled;
+@property(nonatomic) BOOL passwordManagerChoiceEnabled;
+@property(nonatomic) BOOL passwordManagerButtonEnabled;
+@property(nonatomic) BOOL autoFillSettingsButtonEnabled;
+@property(nonatomic) BOOL showAlternateErrorPagesEnabled;
+@property(nonatomic) BOOL useSuggestEnabled;
+@property(nonatomic) BOOL dnsPrefetchEnabled;
+@property(nonatomic) BOOL safeBrowsingEnabled;
+@property(nonatomic) BOOL metricsReportingEnabled;
+@property(nonatomic) BOOL proxiesConfigureButtonEnabled;
+
+// Designated initializer. |profile| should not be NULL.
+- (id)initWithProfile:(Profile*)profile initialPage:(OptionsPage)initialPage;
+
+// Show the preferences window.
+- (void)showPreferences:(id)sender;
+
+// Switch to the given preference page.
+- (void)switchToPage:(OptionsPage)page animate:(BOOL)animate;
+
+// Enables or disables the restoreOnStartup elements
+- (void) setEnabledStateOfRestoreOnStartup;
+
+// IBAction methods for responding to user actions.
+
+// Basics panel
+- (IBAction)addHomepage:(id)sender;
+- (IBAction)removeSelectedHomepages:(id)sender;
+- (IBAction)useCurrentPagesAsHomepage:(id)sender;
+- (IBAction)manageSearchEngines:(id)sender;
+- (IBAction)toggleInstant:(id)sender;
+- (IBAction)learnMoreAboutInstant:(id)sender;
+- (IBAction)makeDefaultBrowser:(id)sender;
+
+// User Data panel
+- (IBAction)doSyncAction:(id)sender;
+- (IBAction)doSyncCustomize:(id)sender;
+- (IBAction)doSyncReauthentication:(id)sender;
+- (IBAction)showPrivacyDashboard:(id)sender;
+- (IBAction)showSavedPasswords:(id)sender;
+- (IBAction)showAutoFillSettings:(id)sender;
+- (IBAction)importData:(id)sender;
+- (IBAction)resetThemeToDefault:(id)sender;
+- (IBAction)themesGallery:(id)sender;
+
+// Under the hood
+- (IBAction)showContentSettings:(id)sender;
+- (IBAction)clearData:(id)sender;
+- (IBAction)privacyLearnMore:(id)sender;
+- (IBAction)browseDownloadLocation:(id)sender;
+- (IBAction)resetAutoOpenFiles:(id)sender;
+- (IBAction)changeFontAndLanguageSettings:(id)sender;
+- (IBAction)openProxyPreferences:(id)sender;
+- (IBAction)showCertificates:(id)sender;
+- (IBAction)resetToDefaults:(id)sender;
+
+// When a toolbar button is clicked
+- (IBAction)toolbarButtonSelected:(id)sender;
+
+@end
+
+@interface PreferencesWindowController(Testing)
+
+- (IntegerPrefMember*)lastSelectedPage;
+- (NSToolbar*)toolbar;
+- (NSView*)basicsView;
+- (NSView*)personalStuffView;
+- (NSView*)underTheHoodView;
+
+// Converts the given OptionsPage value (which may be OPTIONS_PAGE_DEFAULT)
+// into a concrete OptionsPage value.
+- (OptionsPage)normalizePage:(OptionsPage)page;
+
+// Returns the toolbar item corresponding to the given page.  Should be
+// called only after awakeFromNib is.
+- (NSToolbarItem*)getToolbarItemForPage:(OptionsPage)page;
+
+// Returns the (normalized) page corresponding to the given toolbar item.
+// Should be called only after awakeFromNib is.
+- (OptionsPage)getPageForToolbarItem:(NSToolbarItem*)toolbarItem;
+
+// Returns the view corresponding to the given page.  Should be called
+// only after awakeFromNib is.
+- (NSView*)getPrefsViewForPage:(OptionsPage)page;
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/preferences_window_controller.mm b/chrome/browser/ui/cocoa/options/preferences_window_controller.mm
new file mode 100644
index 0000000..1de5ada
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/preferences_window_controller.mm
@@ -0,0 +1,2184 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/options/preferences_window_controller.h"
+
+#include <algorithm>
+
+#include "ui/base/l10n/l10n_util.h"
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_aedesc.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/autofill/autofill_dialog.h"
+#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/instant/instant_confirm_dialog.h"
+#include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/metrics/metrics_service.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/policy/managed_prefs_banner_base.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/sync_ui_util.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#import "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
+#import "chrome/browser/ui/cocoa/importer/import_settings_dialog.h"
+#import "chrome/browser/ui/cocoa/l10n_util.h"
+#import "chrome/browser/ui/cocoa/options/content_settings_dialog_controller.h"
+#import "chrome/browser/ui/cocoa/options/custom_home_pages_model.h"
+#import "chrome/browser/ui/cocoa/options/font_language_settings_controller.h"
+#import "chrome/browser/ui/cocoa/options/keyword_editor_cocoa_controller.h"
+#import "chrome/browser/ui/cocoa/options/search_engine_list_model.h"
+#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
+#import "chrome/browser/ui/cocoa/window_size_autosaver.h"
+#include "chrome/browser/ui/options/options_util.h"
+#include "chrome/browser/ui/options/options_window.h"
+#include "chrome/browser/ui/options/show_options_url.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+// Colors for the managed preferences warning banner.
+static const double kBannerGradientColorTop[3] =
+    {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
+static const double kBannerGradientColorBottom[3] =
+    {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
+static const double kBannerStrokeColor = 135.0 / 255.0;
+
+// Tag id for retrieval via viewWithTag in NSView (from IB).
+static const uint32 kBasicsStartupPageTableTag = 1000;
+
+bool IsNewTabUIURLString(const GURL& url) {
+  return url == GURL(chrome::kChromeUINewTabURL);
+}
+
+// Helper that sizes two buttons to fit in a row keeping their spacing, returns
+// the total horizontal size change.
+CGFloat SizeToFitButtonPair(NSButton* leftButton, NSButton* rightButton) {
+  CGFloat widthShift = 0.0;
+
+  NSSize delta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:leftButton];
+  DCHECK_EQ(delta.height, 0.0) << "Height changes unsupported";
+  widthShift += delta.width;
+
+  if (widthShift != 0.0) {
+    NSPoint origin = [rightButton frame].origin;
+    origin.x += widthShift;
+    [rightButton setFrameOrigin:origin];
+  }
+  delta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:rightButton];
+  DCHECK_EQ(delta.height, 0.0) << "Height changes unsupported";
+  widthShift += delta.width;
+
+  return widthShift;
+}
+
+// The different behaviors for the "pref group" auto sizing.
+enum AutoSizeGroupBehavior {
+  kAutoSizeGroupBehaviorVerticalToFit,
+  kAutoSizeGroupBehaviorVerticalFirstToFit,
+  kAutoSizeGroupBehaviorHorizontalToFit,
+  kAutoSizeGroupBehaviorHorizontalFirstGrows,
+  kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit
+};
+
+// Helper to tweak the layout of the "pref groups" and also ripple any height
+// changes from one group to the next groups' origins.
+// |views| is an ordered list of views with first being the label for the
+// group and the rest being top down or left to right ordering of the views.
+// The label is assumed to already be the same height as all the views it is
+// next too.
+CGFloat AutoSizeGroup(NSArray* views, AutoSizeGroupBehavior behavior,
+                      CGFloat verticalShift) {
+  DCHECK_GE([views count], 2U) << "Should be at least a label and a control";
+  NSTextField* label = [views objectAtIndex:0];
+  DCHECK([label isKindOfClass:[NSTextField class]])
+      << "First view should be the label for the group";
+
+  // Auto size the label to see if we need more vertical space for its localized
+  // string.
+  CGFloat labelHeightChange =
+      [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:label];
+
+  CGFloat localVerticalShift = 0.0;
+  switch (behavior) {
+    case kAutoSizeGroupBehaviorVerticalToFit: {
+      // Walk bottom up doing the sizing and moves.
+      for (NSUInteger index = [views count] - 1; index > 0; --index) {
+        NSView* view = [views objectAtIndex:index];
+        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+        if (localVerticalShift) {
+          NSPoint origin = [view frame].origin;
+          origin.y += localVerticalShift;
+          [view setFrameOrigin:origin];
+        }
+        localVerticalShift += delta.height;
+      }
+      break;
+    }
+    case kAutoSizeGroupBehaviorVerticalFirstToFit: {
+      // Just size the top one.
+      NSView* view = [views objectAtIndex:1];
+      NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+      DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+      localVerticalShift += delta.height;
+      break;
+    }
+    case kAutoSizeGroupBehaviorHorizontalToFit: {
+      // Walk left to right doing the sizing and moves.
+      // NOTE: Don't worry about vertical, assume it always fits.
+      CGFloat horizontalShift = 0.0;
+      NSUInteger count = [views count];
+      for (NSUInteger index = 1; index < count; ++index) {
+        NSView* view = [views objectAtIndex:index];
+        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+        if (horizontalShift) {
+          NSPoint origin = [view frame].origin;
+          origin.x += horizontalShift;
+          [view setFrameOrigin:origin];
+        }
+        horizontalShift += delta.width;
+      }
+      break;
+    }
+    case kAutoSizeGroupBehaviorHorizontalFirstGrows: {
+      // Walk right to left doing the sizing and moves, then apply the space
+      // collected into the first.
+      // NOTE: Don't worry about vertical, assume it always all fits.
+      CGFloat horizontalShift = 0.0;
+      for (NSUInteger index = [views count] - 1; index > 1; --index) {
+        NSView* view = [views objectAtIndex:index];
+        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+        horizontalShift -= delta.width;
+        NSPoint origin = [view frame].origin;
+        origin.x += horizontalShift;
+        [view setFrameOrigin:origin];
+      }
+      if (horizontalShift) {
+        NSView* view = [views objectAtIndex:1];
+        NSSize delta = NSMakeSize(horizontalShift, 0.0);
+        [GTMUILocalizerAndLayoutTweaker
+            resizeViewWithoutAutoResizingSubViews:view
+                                            delta:delta];
+      }
+      break;
+    }
+    case kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit: {
+      // Start out like kAutoSizeGroupBehaviorVerticalToFit but don't do
+      // the first two.  Then handle the two as a row, but apply any
+      // vertical shift.
+      // All but the first two (in the row); walk bottom up.
+      for (NSUInteger index = [views count] - 1; index > 2; --index) {
+        NSView* view = [views objectAtIndex:index];
+        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+        if (localVerticalShift) {
+          NSPoint origin = [view frame].origin;
+          origin.y += localVerticalShift;
+          [view setFrameOrigin:origin];
+        }
+        localVerticalShift += delta.height;
+      }
+      // Deal with the two for the horizontal row.  Size the second one.
+      CGFloat horizontalShift = 0.0;
+      NSView* view = [views objectAtIndex:2];
+      NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+      DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+      horizontalShift -= delta.width;
+      NSPoint origin = [view frame].origin;
+      origin.x += horizontalShift;
+      if (localVerticalShift) {
+        origin.y += localVerticalShift;
+      }
+      [view setFrameOrigin:origin];
+      // Now expand the first item in the row to consume the space opened up.
+      view = [views objectAtIndex:1];
+      if (horizontalShift) {
+        NSSize delta = NSMakeSize(horizontalShift, 0.0);
+        [GTMUILocalizerAndLayoutTweaker
+         resizeViewWithoutAutoResizingSubViews:view
+                                         delta:delta];
+      }
+      // And move it up by any amount needed from the previous items.
+      if (localVerticalShift) {
+        NSPoint origin = [view frame].origin;
+        origin.y += localVerticalShift;
+        [view setFrameOrigin:origin];
+      }
+      break;
+    }
+    default:
+      NOTREACHED();
+      break;
+  }
+
+  // If the label grew more then the views, the other views get an extra shift.
+  // Otherwise, move the label to its top is aligned with the other views.
+  CGFloat nonLabelShift = 0.0;
+  if (labelHeightChange > localVerticalShift) {
+    // Since the lable is taller, centering the other views looks best, just
+    // shift the views by 1/2 of the size difference.
+    nonLabelShift = (labelHeightChange - localVerticalShift) / 2.0;
+  } else {
+    NSPoint origin = [label frame].origin;
+    origin.y += localVerticalShift - labelHeightChange;
+    [label setFrameOrigin:origin];
+  }
+
+  // Apply the input shift requested along with any the shift from label being
+  // taller then the rest of the group.
+  for (NSView* view in views) {
+    NSPoint origin = [view frame].origin;
+    origin.y += verticalShift;
+    if (view != label) {
+      origin.y += nonLabelShift;
+    }
+    [view setFrameOrigin:origin];
+  }
+
+  // Return how much the group grew.
+  return localVerticalShift + nonLabelShift;
+}
+
+// Helper to remove a view and move everything above it down to take over the
+// space.
+void RemoveViewFromView(NSView* view, NSView* toRemove) {
+  // Sort bottom up so we can spin over what is above it.
+  NSArray* views =
+      [[view subviews] sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
+                                        context:NULL];
+
+  // Find where |toRemove| was.
+  NSUInteger index = [views indexOfObject:toRemove];
+  DCHECK_NE(index, NSNotFound);
+  NSUInteger count = [views count];
+  CGFloat shrinkHeight = 0;
+  if (index < (count - 1)) {
+    // If we're not the topmost control, the amount to shift is the bottom of
+    // |toRemove| to the bottom of the view above it.
+    CGFloat shiftDown =
+        NSMinY([[views objectAtIndex:index + 1] frame]) -
+        NSMinY([toRemove frame]);
+
+    // Now cycle over the views above it moving them down.
+    for (++index; index < count; ++index) {
+      NSView* view = [views objectAtIndex:index];
+      NSPoint origin = [view frame].origin;
+      origin.y -= shiftDown;
+      [view setFrameOrigin:origin];
+    }
+
+    shrinkHeight = shiftDown;
+  } else if (index > 0) {
+    // If we're the topmost control, there's nothing to shift but we want to
+    // shrink until the top edge of the second-topmost control, unless it is
+    // actually higher than the topmost control (since we're sorting by the
+    // bottom edge).
+    shrinkHeight = std::max(0.f,
+        NSMaxY([toRemove frame]) -
+        NSMaxY([[views objectAtIndex:index - 1] frame]));
+  }
+  // If we only have one control, don't do any resizing (for now).
+
+  // Remove |toRemove|.
+  [toRemove removeFromSuperview];
+
+  [GTMUILocalizerAndLayoutTweaker
+      resizeViewWithoutAutoResizingSubViews:view
+                                      delta:NSMakeSize(0, -shrinkHeight)];
+}
+
+// Simply removes all the views in |toRemove|.
+void RemoveGroupFromView(NSView* view, NSArray* toRemove) {
+  for (NSView* viewToRemove in toRemove) {
+    RemoveViewFromView(view, viewToRemove);
+  }
+}
+
+// Helper to tweak the layout of the "Under the Hood" content by autosizing all
+// the views and moving things up vertically.  Special case the two controls for
+// download location as they are horizontal, and should fill the row. Special
+// case "Content Settings" and "Clear browsing data" as they are horizontal as
+// well.
+CGFloat AutoSizeUnderTheHoodContent(NSView* view,
+                                    NSPathControl* downloadLocationControl,
+                                    NSButton* downloadLocationButton) {
+  CGFloat verticalShift = 0.0;
+
+  // Loop bottom up through the views sizing and shifting.
+  NSArray* views =
+      [[view subviews] sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
+                                        context:NULL];
+  for (NSView* view in views) {
+    NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
+    DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
+    if (verticalShift) {
+      NSPoint origin = [view frame].origin;
+      origin.y += verticalShift;
+      [view setFrameOrigin:origin];
+    }
+    verticalShift += delta.height;
+
+    // The Download Location controls go in a row with the button aligned to the
+    // right edge and the path control using all the rest of the space.
+    if (view == downloadLocationButton) {
+      NSPoint origin = [downloadLocationButton frame].origin;
+      origin.x -= delta.width;
+      [downloadLocationButton setFrameOrigin:origin];
+      NSSize controlSize = [downloadLocationControl frame].size;
+      controlSize.width -= delta.width;
+      [downloadLocationControl setFrameSize:controlSize];
+    }
+  }
+
+  return verticalShift;
+}
+
+}  // namespace
+
+//-------------------------------------------------------------------------
+
+@interface PreferencesWindowController(Private)
+// Callback when preferences are changed. |prefName| is the name of the
+// pref that has changed.
+- (void)prefChanged:(std::string*)prefName;
+// Callback when sync state has changed.  syncService_ needs to be
+// queried to find out what happened.
+- (void)syncStateChanged;
+// Record the user performed a certain action and save the preferences.
+- (void)recordUserAction:(const UserMetricsAction&) action;
+- (void)registerPrefObservers;
+- (void)configureInstant;
+
+// KVC setter methods.
+- (void)setNewTabPageIsHomePageIndex:(NSInteger)val;
+- (void)setHomepageURL:(NSString*)urlString;
+- (void)setRestoreOnStartupIndex:(NSInteger)type;
+- (void)setShowHomeButton:(BOOL)value;
+- (void)setPasswordManagerEnabledIndex:(NSInteger)value;
+- (void)setIsUsingDefaultTheme:(BOOL)value;
+- (void)setShowAlternateErrorPages:(BOOL)value;
+- (void)setUseSuggest:(BOOL)value;
+- (void)setDnsPrefetch:(BOOL)value;
+- (void)setSafeBrowsing:(BOOL)value;
+- (void)setMetricsReporting:(BOOL)value;
+- (void)setAskForSaveLocation:(BOOL)value;
+- (void)setFileHandlerUIEnabled:(BOOL)value;
+- (void)setTranslateEnabled:(BOOL)value;
+- (void)setTabsToLinks:(BOOL)value;
+- (void)displayPreferenceViewForPage:(OptionsPage)page
+                             animate:(BOOL)animate;
+- (void)resetSubViews;
+- (void)initBannerStateForPage:(OptionsPage)page;
+
+// KVC getter methods.
+- (BOOL)fileHandlerUIEnabled;
+- (BOOL)canChangeDefaultBrowser;
+@end
+
+namespace PreferencesWindowControllerInternal {
+
+// A C++ class registered for changes in preferences. Bridges the
+// notification back to the PWC.
+class PrefObserverBridge : public NotificationObserver,
+                           public ProfileSyncServiceObserver {
+ public:
+  PrefObserverBridge(PreferencesWindowController* controller)
+      : controller_(controller) {}
+
+  virtual ~PrefObserverBridge() {}
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) {
+    if (type == NotificationType::PREF_CHANGED)
+      [controller_ prefChanged:Details<std::string>(details).ptr()];
+  }
+
+  // Overridden from ProfileSyncServiceObserver.
+  virtual void OnStateChanged() {
+    [controller_ syncStateChanged];
+  }
+
+ private:
+  PreferencesWindowController* controller_;  // weak, owns us
+};
+
+// Tracks state for a managed prefs banner and triggers UI updates through the
+// PreferencesWindowController as appropriate.
+class ManagedPrefsBannerState : public policy::ManagedPrefsBannerBase {
+ public:
+  virtual ~ManagedPrefsBannerState() { }
+
+  explicit ManagedPrefsBannerState(PreferencesWindowController* controller,
+                                   OptionsPage page,
+                                   PrefService* local_state,
+                                   PrefService* prefs)
+    : policy::ManagedPrefsBannerBase(local_state, prefs, page),
+        controller_(controller),
+        page_(page) { }
+
+  BOOL IsVisible() {
+    return DetermineVisibility();
+  }
+
+ protected:
+  // Overridden from ManagedPrefsBannerBase.
+  virtual void OnUpdateVisibility() {
+    [controller_ switchToPage:page_ animate:YES];
+  }
+
+ private:
+  PreferencesWindowController* controller_;  // weak, owns us
+  OptionsPage page_;  // current options page
+};
+
+}  // namespace PreferencesWindowControllerInternal
+
+@implementation PreferencesWindowController
+
+@synthesize restoreButtonsEnabled = restoreButtonsEnabled_;
+@synthesize restoreURLsEnabled = restoreURLsEnabled_;
+@synthesize showHomeButtonEnabled = showHomeButtonEnabled_;
+@synthesize defaultSearchEngineEnabled = defaultSearchEngineEnabled_;
+@synthesize passwordManagerChoiceEnabled = passwordManagerChoiceEnabled_;
+@synthesize passwordManagerButtonEnabled = passwordManagerButtonEnabled_;
+@synthesize autoFillSettingsButtonEnabled = autoFillSettingsButtonEnabled_;
+@synthesize showAlternateErrorPagesEnabled = showAlternateErrorPagesEnabled_;
+@synthesize useSuggestEnabled = useSuggestEnabled_;
+@synthesize dnsPrefetchEnabled = dnsPrefetchEnabled_;
+@synthesize safeBrowsingEnabled = safeBrowsingEnabled_;
+@synthesize metricsReportingEnabled = metricsReportingEnabled_;
+@synthesize proxiesConfigureButtonEnabled = proxiesConfigureButtonEnabled_;
+
+- (id)initWithProfile:(Profile*)profile initialPage:(OptionsPage)initialPage {
+  DCHECK(profile);
+  // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we
+  // can override it in a unit test.
+  NSString* nibPath = [base::mac::MainAppBundle()
+                        pathForResource:@"Preferences"
+                                 ofType:@"nib"];
+  if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
+    profile_ = profile->GetOriginalProfile();
+    initialPage_ = initialPage;
+    prefs_ = profile->GetPrefs();
+    DCHECK(prefs_);
+    observer_.reset(
+        new PreferencesWindowControllerInternal::PrefObserverBridge(self));
+
+    // Set up the model for the custom home page table. The KVO observation
+    // tells us when the number of items in the array changes. The normal
+    // observation tells us when one of the URLs of an item changes.
+    customPagesSource_.reset([[CustomHomePagesModel alloc]
+                                initWithProfile:profile_]);
+    const SessionStartupPref startupPref =
+        SessionStartupPref::GetStartupPref(prefs_);
+    [customPagesSource_ setURLs:startupPref.urls];
+
+    // Set up the model for the default search popup. Register for notifications
+    // about when the model changes so we can update the selection in the view.
+    searchEngineModel_.reset(
+        [[SearchEngineListModel alloc]
+            initWithModel:profile->GetTemplateURLModel()]);
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(searchEngineModelChanged:)
+               name:kSearchEngineListModelChangedNotification
+             object:searchEngineModel_.get()];
+
+    // This needs to be done before awakeFromNib: because the bindings set up
+    // in the nib rely on it.
+    [self registerPrefObservers];
+
+    // Use one animation so we can stop it if the user clicks quickly, and
+    // start the new animation.
+    animation_.reset([[NSViewAnimation alloc] init]);
+    // Make this the delegate so it can remove the old view at the end of the
+    // animation (once it is faded out).
+    [animation_ setDelegate:self];
+    [animation_ setAnimationBlockingMode:NSAnimationNonblocking];
+
+    // TODO(akalin): handle incognito profiles?  The windows version of this
+    // (in chrome/browser/ui/views/options/content_page_view.cc) just does what
+    // we do below.
+    syncService_ = profile_->GetProfileSyncService();
+
+    // TODO(akalin): This color is taken from kSyncLabelErrorBgColor in
+    // content_page_view.cc.  Either decomp that color out into a
+    // function/variable that is referenced by both this file and
+    // content_page_view.cc, or maybe pick a more suitable color.
+    syncErrorBackgroundColor_.reset(
+        [[NSColor colorWithDeviceRed:0xff/255.0
+                               green:0x9a/255.0
+                                blue:0x9a/255.0
+                               alpha:1.0] retain]);
+
+    // Disable the |autoFillSettingsButton_| if we have no
+    // |personalDataManager|.
+    PersonalDataManager* personalDataManager =
+        profile_->GetPersonalDataManager();
+    [autoFillSettingsButton_ setHidden:(personalDataManager == NULL)];
+    bool autofill_disabled_by_policy =
+        autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue();
+    [self setAutoFillSettingsButtonEnabled:!autofill_disabled_by_policy];
+    [self setPasswordManagerChoiceEnabled:!askSavePasswords_.IsManaged()];
+    [self setPasswordManagerButtonEnabled:
+        !askSavePasswords_.IsManaged() || askSavePasswords_.GetValue()];
+
+    // Initialize the enabled state of the elements on the general tab.
+    [self setShowHomeButtonEnabled:!showHomeButton_.IsManaged()];
+    [self setEnabledStateOfRestoreOnStartup];
+    [self setDefaultSearchEngineEnabled:![searchEngineModel_ isDefaultManaged]];
+
+    // Initialize UI state for the advanced page.
+    [self setShowAlternateErrorPagesEnabled:!alternateErrorPages_.IsManaged()];
+    [self setUseSuggestEnabled:!useSuggest_.IsManaged()];
+    [self setDnsPrefetchEnabled:!dnsPrefetch_.IsManaged()];
+    [self setSafeBrowsingEnabled:!safeBrowsing_.IsManaged()];
+    [self setMetricsReportingEnabled:!metricsReporting_.IsManaged()];
+    proxyPrefs_.reset(
+        PrefSetObserver::CreateProxyPrefSetObserver(prefs_, observer_.get()));
+    [self setProxiesConfigureButtonEnabled:!proxyPrefs_->IsManaged()];
+  }
+  return self;
+}
+
+- (void)awakeFromNib {
+
+  // Validate some assumptions in debug builds.
+
+  // "Basics", "Personal Stuff", and "Under the Hood" views should be the same
+  // width.  They should be the same width so they are laid out to look as good
+  // as possible at that width with controls just having to wrap if their text
+  // is too long.
+  DCHECK_EQ(NSWidth([basicsView_ frame]), NSWidth([personalStuffView_ frame]))
+      << "Basics and Personal Stuff should be the same widths";
+  DCHECK_EQ(NSWidth([basicsView_ frame]), NSWidth([underTheHoodView_ frame]))
+      << "Basics and Under the Hood should be the same widths";
+  // "Under the Hood" content should always be skinnier than the scroller it
+  // goes into (we resize it).
+  DCHECK_LE(NSWidth([underTheHoodContentView_ frame]),
+            [underTheHoodScroller_ contentSize].width)
+      << "The Under the Hood content should be narrower than the content "
+         "of the scroller it goes into";
+
+#if !defined(GOOGLE_CHROME_BUILD)
+  // "Enable logging" (breakpad and stats) is only in Google Chrome builds,
+  // remove the checkbox and slide everything above it down.
+  RemoveViewFromView(underTheHoodContentView_, enableLoggingCheckbox_);
+#endif  // !defined(GOOGLE_CHROME_BUILD)
+
+  // There are four problem children within the groups:
+  //   Basics - Default Browser
+  //   Personal Stuff - Sync
+  //   Personal Stuff - Themes
+  //   Personal Stuff - Browser Data
+  // These four have buttons that with some localizations are wider then the
+  // view.  So the four get manually laid out before doing the general work so
+  // the views/window can be made wide enough to fit them.  The layout in the
+  // general pass is a noop for these buttons (since they are already sized).
+
+  // Size the default browser button.
+  const NSUInteger kDefaultBrowserGroupCount = 3;
+  const NSUInteger kDefaultBrowserButtonIndex = 1;
+  DCHECK_EQ([basicsGroupDefaultBrowser_ count], kDefaultBrowserGroupCount)
+      << "Expected only two items in Default Browser group";
+  NSButton* defaultBrowserButton =
+      [basicsGroupDefaultBrowser_ objectAtIndex:kDefaultBrowserButtonIndex];
+  NSSize defaultBrowserChange =
+      [GTMUILocalizerAndLayoutTweaker sizeToFitView:defaultBrowserButton];
+  DCHECK_EQ(defaultBrowserChange.height, 0.0)
+      << "Button should have been right height in nib";
+
+  [self configureInstant];
+
+  // Size the sync row.
+  CGFloat syncRowChange = SizeToFitButtonPair(syncButton_,
+                                              syncCustomizeButton_);
+
+  // Size the themes row.
+  const NSUInteger kThemeGroupCount = 3;
+  const NSUInteger kThemeResetButtonIndex = 1;
+  const NSUInteger kThemeThemesButtonIndex = 2;
+  DCHECK_EQ([personalStuffGroupThemes_ count], kThemeGroupCount)
+      << "Expected only two items in Themes group";
+  CGFloat themeRowChange = SizeToFitButtonPair(
+      [personalStuffGroupThemes_ objectAtIndex:kThemeResetButtonIndex],
+      [personalStuffGroupThemes_ objectAtIndex:kThemeThemesButtonIndex]);
+
+  // Size the Privacy and Clear buttons that make a row in Under the Hood.
+  CGFloat privacyRowChange = SizeToFitButtonPair(contentSettingsButton_,
+                                                 clearDataButton_);
+  // Under the Hood view is narrower (then the other panes) in the nib, subtract
+  // out the amount it was already going to grow to match the other panes when
+  // calculating how much the row needs things to grow.
+  privacyRowChange -=
+    ([underTheHoodScroller_ contentSize].width -
+     NSWidth([underTheHoodContentView_ frame]));
+
+  // Find the most any row changed in size.
+  CGFloat maxWidthChange = std::max(defaultBrowserChange.width, syncRowChange);
+  maxWidthChange = std::max(maxWidthChange, themeRowChange);
+  maxWidthChange = std::max(maxWidthChange, privacyRowChange);
+
+  // If any grew wider, make the views wider. If they all shrank, they fit the
+  // existing view widths, so no change is needed//.
+  if (maxWidthChange > 0.0) {
+    NSSize viewSize = [basicsView_ frame].size;
+    viewSize.width += maxWidthChange;
+    [basicsView_ setFrameSize:viewSize];
+    viewSize = [personalStuffView_ frame].size;
+    viewSize.width += maxWidthChange;
+    [personalStuffView_ setFrameSize:viewSize];
+  }
+
+  // Now that we have the width needed for Basics and Personal Stuff, lay out
+  // those pages bottom up making sure the strings fit and moving things up as
+  // needed.
+
+  CGFloat newWidth = NSWidth([basicsView_ frame]);
+  CGFloat verticalShift = 0.0;
+  verticalShift += AutoSizeGroup(basicsGroupDefaultBrowser_,
+                                 kAutoSizeGroupBehaviorVerticalFirstToFit,
+                                 verticalShift);
+  verticalShift += AutoSizeGroup(
+      basicsGroupSearchEngine_,
+      kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit,
+      verticalShift);
+  verticalShift += AutoSizeGroup(basicsGroupToolbar_,
+                                 kAutoSizeGroupBehaviorVerticalToFit,
+                                 verticalShift);
+  verticalShift += AutoSizeGroup(basicsGroupHomePage_,
+                                 kAutoSizeGroupBehaviorVerticalToFit,
+                                 verticalShift);
+  verticalShift += AutoSizeGroup(basicsGroupStartup_,
+                                 kAutoSizeGroupBehaviorVerticalFirstToFit,
+                                 verticalShift);
+  [GTMUILocalizerAndLayoutTweaker
+      resizeViewWithoutAutoResizingSubViews:basicsView_
+                                      delta:NSMakeSize(0.0, verticalShift)];
+
+  verticalShift = 0.0;
+  verticalShift += AutoSizeGroup(personalStuffGroupThemes_,
+                                 kAutoSizeGroupBehaviorHorizontalToFit,
+                                 verticalShift);
+  verticalShift += AutoSizeGroup(personalStuffGroupBrowserData_,
+                                 kAutoSizeGroupBehaviorVerticalToFit,
+                                 verticalShift);
+  verticalShift += AutoSizeGroup(personalStuffGroupAutofill_,
+                                 kAutoSizeGroupBehaviorVerticalToFit,
+                                 verticalShift);
+  verticalShift += AutoSizeGroup(personalStuffGroupPasswords_,
+                                 kAutoSizeGroupBehaviorVerticalToFit,
+                                 verticalShift);
+  // TODO(akalin): Here we rely on the initial contents of the sync
+  // group's text field/link field to be large enough to hold all
+  // possible messages so that we don't have to re-layout when sync
+  // state changes.  This isn't perfect, since e.g. some sync messages
+  // use the user's e-mail address (which may be really long), and the
+  // link field is usually not shown (leaving a big empty space).
+  // Rethink sync preferences UI for Mac.
+  verticalShift += AutoSizeGroup(personalStuffGroupSync_,
+                                 kAutoSizeGroupBehaviorVerticalToFit,
+                                 verticalShift);
+  [GTMUILocalizerAndLayoutTweaker
+      resizeViewWithoutAutoResizingSubViews:personalStuffView_
+                                      delta:NSMakeSize(0.0, verticalShift)];
+
+  if (syncService_) {
+    syncService_->AddObserver(observer_.get());
+    // Update the controls according to the initial state.
+    [self syncStateChanged];
+  } else {
+    // If sync is disabled we don't want to show the sync controls at all.
+    RemoveGroupFromView(personalStuffView_, personalStuffGroupSync_);
+  }
+
+  // Make the window as wide as the views.
+  NSWindow* prefsWindow = [self window];
+  NSView* prefsContentView = [prefsWindow contentView];
+  NSRect frame = [prefsContentView convertRect:[prefsWindow frame]
+                                      fromView:nil];
+  frame.size.width = newWidth;
+  frame = [prefsContentView convertRect:frame toView:nil];
+  [prefsWindow setFrame:frame display:NO];
+
+  // The Under the Hood prefs is a scroller, it shouldn't get any border, so it
+  // gets resized to be as wide as the window ended up.
+  NSSize underTheHoodSize = [underTheHoodView_ frame].size;
+  underTheHoodSize.width = newWidth;
+  [underTheHoodView_ setFrameSize:underTheHoodSize];
+
+  // Widen the Under the Hood content so things can rewrap to the full width.
+  NSSize underTheHoodContentSize = [underTheHoodContentView_ frame].size;
+  underTheHoodContentSize.width = [underTheHoodScroller_ contentSize].width;
+  [underTheHoodContentView_ setFrameSize:underTheHoodContentSize];
+
+  // Now that Under the Hood is the right width, auto-size to the new width to
+  // get the final height.
+  verticalShift = AutoSizeUnderTheHoodContent(underTheHoodContentView_,
+                                              downloadLocationControl_,
+                                              downloadLocationButton_);
+  [GTMUILocalizerAndLayoutTweaker
+      resizeViewWithoutAutoResizingSubViews:underTheHoodContentView_
+                                      delta:NSMakeSize(0.0, verticalShift)];
+  underTheHoodContentSize = [underTheHoodContentView_ frame].size;
+
+  // Put the Under the Hood content view into the scroller and scroll it to the
+  // top.
+  [underTheHoodScroller_ setDocumentView:underTheHoodContentView_];
+  [underTheHoodContentView_ scrollPoint:
+      NSMakePoint(0, underTheHoodContentSize.height)];
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  NSImage* alertIcon = rb.GetNativeImageNamed(IDR_WARNING);
+  DCHECK(alertIcon);
+  [managedPrefsBannerWarningImage_ setImage:alertIcon];
+
+  [self initBannerStateForPage:initialPage_];
+  [self switchToPage:initialPage_ animate:NO];
+
+  // Save/restore position based on prefs.
+  if (g_browser_process && g_browser_process->local_state()) {
+    sizeSaver_.reset([[WindowSizeAutosaver alloc]
+       initWithWindow:[self window]
+          prefService:profile_->GetPrefs()
+                 path:prefs::kPreferencesWindowPlacement]);
+  }
+
+  // Initialize the banner gradient and stroke color.
+  NSColor* bannerStartingColor =
+      [NSColor colorWithCalibratedRed:kBannerGradientColorTop[0]
+                                green:kBannerGradientColorTop[1]
+                                 blue:kBannerGradientColorTop[2]
+                                alpha:1.0];
+  NSColor* bannerEndingColor =
+      [NSColor colorWithCalibratedRed:kBannerGradientColorBottom[0]
+                                green:kBannerGradientColorBottom[1]
+                                 blue:kBannerGradientColorBottom[2]
+                                alpha:1.0];
+  scoped_nsobject<NSGradient> bannerGradient(
+      [[NSGradient alloc] initWithStartingColor:bannerStartingColor
+                                    endingColor:bannerEndingColor]);
+  [managedPrefsBannerView_ setGradient:bannerGradient];
+
+  NSColor* bannerStrokeColor =
+      [NSColor colorWithCalibratedWhite:kBannerStrokeColor
+                                  alpha:1.0];
+  [managedPrefsBannerView_ setStrokeColor:bannerStrokeColor];
+
+  // Set accessibility related attributes.
+  NSTableView* tableView = [basicsView_ viewWithTag:kBasicsStartupPageTableTag];
+  NSString* description =
+      l10n_util::GetNSStringWithFixup(IDS_OPTIONS_STARTUP_SHOW_PAGES);
+  [tableView accessibilitySetOverrideValue:description
+                              forAttribute:NSAccessibilityDescriptionAttribute];
+}
+
+- (void)dealloc {
+  if (syncService_) {
+    syncService_->RemoveObserver(observer_.get());
+  }
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [animation_ setDelegate:nil];
+  [animation_ stopAnimation];
+  [super dealloc];
+}
+
+// Xcode 3.1.x version of Interface Builder doesn't do a lot for editing
+// toolbars in XIB.  So the toolbar's delegate is set to the controller so it
+// can tell the toolbar what items are selectable.
+- (NSArray*)toolbarSelectableItemIdentifiers:(NSToolbar*)toolbar {
+  DCHECK(toolbar == toolbar_);
+  return [[toolbar_ items] valueForKey:@"itemIdentifier"];
+}
+
+// Register our interest in the preferences we're displaying so if anything
+// else in the UI changes them we will be updated.
+- (void)registerPrefObservers {
+  if (!prefs_) return;
+
+  // During unit tests, there is no local state object, so we fall back to
+  // the prefs object (where we've explicitly registered this pref so we
+  // know it's there).
+  PrefService* local = g_browser_process->local_state();
+  if (!local)
+    local = prefs_;
+
+  // Basics panel
+  registrar_.Init(prefs_);
+  registrar_.Add(prefs::kURLsToRestoreOnStartup, observer_.get());
+  restoreOnStartup_.Init(prefs::kRestoreOnStartup, prefs_, observer_.get());
+  newTabPageIsHomePage_.Init(prefs::kHomePageIsNewTabPage,
+                             prefs_, observer_.get());
+  homepage_.Init(prefs::kHomePage, prefs_, observer_.get());
+  showHomeButton_.Init(prefs::kShowHomeButton, prefs_, observer_.get());
+  instantEnabled_.Init(prefs::kInstantEnabled, prefs_, observer_.get());
+  default_browser_policy_.Init(prefs::kDefaultBrowserSettingEnabled,
+                               local, observer_.get());
+
+  // Personal Stuff panel
+  askSavePasswords_.Init(prefs::kPasswordManagerEnabled,
+                         prefs_, observer_.get());
+  autoFillEnabled_.Init(prefs::kAutoFillEnabled, prefs_, observer_.get());
+  currentTheme_.Init(prefs::kCurrentThemeID, prefs_, observer_.get());
+
+  // Under the hood panel
+  alternateErrorPages_.Init(prefs::kAlternateErrorPagesEnabled,
+                            prefs_, observer_.get());
+  useSuggest_.Init(prefs::kSearchSuggestEnabled, prefs_, observer_.get());
+  dnsPrefetch_.Init(prefs::kDnsPrefetchingEnabled, prefs_, observer_.get());
+  safeBrowsing_.Init(prefs::kSafeBrowsingEnabled, prefs_, observer_.get());
+  autoOpenFiles_.Init(
+      prefs::kDownloadExtensionsToOpen, prefs_, observer_.get());
+  translateEnabled_.Init(prefs::kEnableTranslate, prefs_, observer_.get());
+  tabsToLinks_.Init(prefs::kWebkitTabsToLinks, prefs_, observer_.get());
+
+  metricsReporting_.Init(prefs::kMetricsReportingEnabled,
+                         local, observer_.get());
+  defaultDownloadLocation_.Init(prefs::kDownloadDefaultDirectory, prefs_,
+                                observer_.get());
+  askForSaveLocation_.Init(prefs::kPromptForDownload, prefs_, observer_.get());
+
+  // We don't need to observe changes in this value.
+  lastSelectedPage_.Init(prefs::kOptionsWindowLastTabIndex, local, NULL);
+}
+
+// Called when the window wants to be closed.
+- (BOOL)windowShouldClose:(id)sender {
+  // Stop any animation and clear the delegate to avoid stale pointers.
+  [animation_ setDelegate:nil];
+  [animation_ stopAnimation];
+
+  return YES;
+}
+
+// Called when the user hits the escape key. Closes the window.
+- (void)cancel:(id)sender {
+  [[self window] performClose:self];
+}
+
+// Record the user performed a certain action and save the preferences.
+- (void)recordUserAction:(const UserMetricsAction &)action {
+  UserMetrics::RecordAction(action, profile_);
+  if (prefs_)
+    prefs_->ScheduleSavePersistentPrefs();
+}
+
+// Returns the set of keys that |key| depends on for its value so it can be
+// re-computed when any of those change as well.
++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key {
+  NSSet* paths = [super keyPathsForValuesAffectingValueForKey:key];
+  if ([key isEqualToString:@"isHomepageURLEnabled"]) {
+    paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
+    paths = [paths setByAddingObject:@"homepageURL"];
+  } else if ([key isEqualToString:@"restoreURLsEnabled"]) {
+    paths = [paths setByAddingObject:@"restoreOnStartupIndex"];
+  } else if ([key isEqualToString:@"isHomepageChoiceEnabled"]) {
+    paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
+    paths = [paths setByAddingObject:@"homepageURL"];
+  } else if ([key isEqualToString:@"newTabPageIsHomePageIndex"]) {
+    paths = [paths setByAddingObject:@"homepageURL"];
+  } else if ([key isEqualToString:@"hompageURL"]) {
+    paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
+  } else if ([key isEqualToString:@"canChangeDefaultBrowser"]) {
+    paths = [paths setByAddingObject:@"defaultBrowser"];
+  } else if ([key isEqualToString:@"defaultBrowserTextColor"]) {
+    paths = [paths setByAddingObject:@"defaultBrowser"];
+  } else if ([key isEqualToString:@"defaultBrowserText"]) {
+    paths = [paths setByAddingObject:@"defaultBrowser"];
+  }
+  return paths;
+}
+
+// Launch the Keychain Access app.
+- (void)launchKeychainAccess {
+  NSString* const kKeychainBundleId = @"com.apple.keychainaccess";
+  [[NSWorkspace sharedWorkspace]
+      launchAppWithBundleIdentifier:kKeychainBundleId
+                            options:0L
+     additionalEventParamDescriptor:nil
+                   launchIdentifier:nil];
+}
+
+//-------------------------------------------------------------------------
+// Basics panel
+
+// Sets the home page preferences for kNewTabPageIsHomePage and kHomePage. If a
+// blank or null-host URL is passed in we revert to using NewTab page
+// as the Home page. Note: using SetValue() causes the observers not to fire,
+// which is actually a good thing as we could end up in a state where setting
+// the homepage to an empty url would automatically reset the prefs back to
+// using the NTP, so we'd be never be able to change it.
+- (void)setHomepage:(const GURL&)homepage {
+  if (IsNewTabUIURLString(homepage)) {
+    newTabPageIsHomePage_.SetValueIfNotManaged(true);
+    homepage_.SetValueIfNotManaged(std::string());
+  } else if (!homepage.is_valid()) {
+    newTabPageIsHomePage_.SetValueIfNotManaged(true);
+    if (!homepage.has_host())
+      homepage_.SetValueIfNotManaged(std::string());
+  } else {
+    homepage_.SetValueIfNotManaged(homepage.spec());
+  }
+}
+
+// Callback when preferences are changed by someone modifying the prefs backend
+// externally. |prefName| is the name of the pref that has changed. Unlike on
+// Windows, we don't need to use this method for initializing, that's handled by
+// Cocoa Bindings.
+// Handles prefs for the "Basics" panel.
+- (void)basicsPrefChanged:(std::string*)prefName {
+  if (*prefName == prefs::kRestoreOnStartup) {
+    const SessionStartupPref startupPref =
+        SessionStartupPref::GetStartupPref(prefs_);
+    [self setRestoreOnStartupIndex:startupPref.type];
+    [self setEnabledStateOfRestoreOnStartup];
+  } else if (*prefName == prefs::kURLsToRestoreOnStartup) {
+    [customPagesSource_ reloadURLs];
+    [self setEnabledStateOfRestoreOnStartup];
+  } else if (*prefName == prefs::kHomePageIsNewTabPage) {
+    NSInteger useNewTabPage = newTabPageIsHomePage_.GetValue() ? 0 : 1;
+    [self setNewTabPageIsHomePageIndex:useNewTabPage];
+  } else if (*prefName == prefs::kHomePage) {
+    NSString* value = base::SysUTF8ToNSString(homepage_.GetValue());
+    [self setHomepageURL:value];
+  } else if (*prefName == prefs::kShowHomeButton) {
+    [self setShowHomeButton:showHomeButton_.GetValue() ? YES : NO];
+    [self setShowHomeButtonEnabled:!showHomeButton_.IsManaged()];
+  } else if (*prefName == prefs::kInstantEnabled) {
+    [self configureInstant];
+  } else if (*prefName == prefs::kDefaultBrowserSettingEnabled) {
+    [self willChangeValueForKey:@"defaultBrowser"];
+    [self didChangeValueForKey:@"defaultBrowser"];
+  }
+}
+
+// Returns the index of the selected cell in the "on startup" matrix based
+// on the "restore on startup" pref. The ordering of the cells is in the
+// same order as the pref.
+- (NSInteger)restoreOnStartupIndex {
+  const SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs_);
+  return pref.type;
+}
+
+// A helper function that takes the startup session type, grabs the URLs to
+// restore, and saves it all in prefs.
+- (void)saveSessionStartupWithType:(SessionStartupPref::Type)type {
+  SessionStartupPref pref;
+  pref.type = type;
+  pref.urls = [customPagesSource_.get() URLs];
+  SessionStartupPref::SetStartupPref(prefs_, pref);
+}
+
+// Sets the pref based on the index of the selected cell in the matrix and
+// marks the appropriate user metric.
+- (void)setRestoreOnStartupIndex:(NSInteger)type {
+  SessionStartupPref::Type startupType =
+      static_cast<SessionStartupPref::Type>(type);
+  switch (startupType) {
+    case SessionStartupPref::DEFAULT:
+      [self recordUserAction:UserMetricsAction("Options_Startup_Homepage")];
+      break;
+    case SessionStartupPref::LAST:
+      [self recordUserAction:UserMetricsAction("Options_Startup_LastSession")];
+      break;
+    case SessionStartupPref::URLS:
+      [self recordUserAction:UserMetricsAction("Options_Startup_Custom")];
+      break;
+    default:
+      NOTREACHED();
+  }
+  [self saveSessionStartupWithType:startupType];
+}
+
+// Enables or disables the restoreOnStartup elements
+- (void) setEnabledStateOfRestoreOnStartup {
+  const SessionStartupPref startupPref =
+      SessionStartupPref::GetStartupPref(prefs_);
+  [self setRestoreButtonsEnabled:!SessionStartupPref::TypeIsManaged(prefs_)];
+  [self setRestoreURLsEnabled:!SessionStartupPref::URLsAreManaged(prefs_) &&
+      [self restoreOnStartupIndex] == SessionStartupPref::URLS];
+}
+
+// Getter for the |customPagesSource| property for bindings.
+- (CustomHomePagesModel*)customPagesSource {
+  return customPagesSource_.get();
+}
+
+// Called when the selection in the table changes. If a flag is set indicating
+// that we're waiting for a special select message, edit the cell. Otherwise
+// just ignore it, we don't normally care.
+- (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
+  if (pendingSelectForEdit_) {
+    NSTableView* table = [aNotification object];
+    NSUInteger selectedRow = [table selectedRow];
+    [table editColumn:0 row:selectedRow withEvent:nil select:YES];
+    pendingSelectForEdit_ = NO;
+  }
+}
+
+// Called when the user hits the (+) button for adding a new homepage to the
+// list. This will also attempt to make the new item editable so the user can
+// just start typing.
+- (IBAction)addHomepage:(id)sender {
+  [customPagesArrayController_ add:sender];
+
+  // When the new item is added to the model, the array controller will select
+  // it. We'll watch for that notification (because we are the table view's
+  // delegate) and then make the cell editable. Note that this can't be
+  // accomplished simply by subclassing the array controller's add method (I
+  // did try). The update of the table is asynchronous with the controller
+  // updating the model.
+  pendingSelectForEdit_ = YES;
+}
+
+// Called when the user hits the (-) button for removing the selected items in
+// the homepage table. The controller does all the work.
+- (IBAction)removeSelectedHomepages:(id)sender {
+  [customPagesArrayController_ remove:sender];
+}
+
+// Add all entries for all open browsers with our profile.
+- (IBAction)useCurrentPagesAsHomepage:(id)sender {
+  std::vector<GURL> urls;
+  for (BrowserList::const_iterator browserIter = BrowserList::begin();
+       browserIter != BrowserList::end(); ++browserIter) {
+    Browser* browser = *browserIter;
+    if (browser->profile() != profile_)
+      continue;  // Only want entries for open profile.
+
+    for (int tabIndex = 0; tabIndex < browser->tab_count(); ++tabIndex) {
+      TabContents* tab = browser->GetTabContentsAt(tabIndex);
+      if (tab->ShouldDisplayURL()) {
+        const GURL url = browser->GetTabContentsAt(tabIndex)->GetURL();
+        if (!url.is_empty())
+          urls.push_back(url);
+      }
+    }
+  }
+  [customPagesSource_ setURLs:urls];
+}
+
+enum { kHomepageNewTabPage, kHomepageURL };
+
+// Here's a table describing the desired characteristics of the homepage choice
+// radio value, it's enabled state and the URL field enabled state. They depend
+// on the values of the managed bits for homepage (m_hp) and
+// homepageIsNewTabPage (m_ntp) preferences, as well as the value of the
+// homepageIsNewTabPage preference (ntp) and whether the homepage preference
+// is equal to the new tab page URL (hpisntp).
+//
+// m_hp m_ntp ntp hpisntp | choice value | choice enabled | URL field enabled
+// --------------------------------------------------------------------------
+// 0    0     0   0       | homepage     | 1              | 1
+// 0    0     0   1       | new tab page | 1              | 0
+// 0    0     1   0       | new tab page | 1              | 0
+// 0    0     1   1       | new tab page | 1              | 0
+// 0    1     0   0       | homepage     | 0              | 1
+// 0    1     0   1       | homepage     | 0              | 1
+// 0    1     1   0       | new tab page | 0              | 0
+// 0    1     1   1       | new tab page | 0              | 0
+// 1    0     0   0       | homepage     | 1              | 0
+// 1    0     0   1       | new tab page | 0              | 0
+// 1    0     1   0       | new tab page | 1              | 0
+// 1    0     1   1       | new tab page | 0              | 0
+// 1    1     0   0       | homepage     | 0              | 0
+// 1    1     0   1       | new tab page | 0              | 0
+// 1    1     1   0       | new tab page | 0              | 0
+// 1    1     1   1       | new tab page | 0              | 0
+//
+// thus, we have:
+//
+//    choice value is new tab page === ntp || (hpisntp && (m_hp || !m_ntp))
+//    choice enabled === !m_ntp && !(m_hp && hpisntp)
+//    URL field enabled === !ntp && !mhp && !(hpisntp && !m_ntp)
+//
+// which also make sense if you think about them.
+
+// Checks whether the homepage URL refers to the new tab page.
+- (BOOL)isHomepageNewTabUIURL {
+  return IsNewTabUIURLString(GURL(homepage_.GetValue().c_str()));
+}
+
+// Returns the index of the selected cell in the "home page" marix based on
+// the "new tab is home page" pref. Sadly, the ordering is reversed from the
+// pref value.
+- (NSInteger)newTabPageIsHomePageIndex {
+  return newTabPageIsHomePage_.GetValue() ||
+      ([self isHomepageNewTabUIURL] &&
+          (homepage_.IsManaged() || !newTabPageIsHomePage_.IsManaged())) ?
+      kHomepageNewTabPage : kHomepageURL;
+}
+
+// Sets the pref based on the given index into the matrix and marks the
+// appropriate user metric.
+- (void)setNewTabPageIsHomePageIndex:(NSInteger)index {
+  bool useNewTabPage = index == kHomepageNewTabPage ? true : false;
+  if (useNewTabPage) {
+    [self recordUserAction:UserMetricsAction("Options_Homepage_UseNewTab")];
+  } else {
+    [self recordUserAction:UserMetricsAction("Options_Homepage_UseURL")];
+    if ([self isHomepageNewTabUIURL])
+      homepage_.SetValueIfNotManaged(std::string());
+  }
+  newTabPageIsHomePage_.SetValueIfNotManaged(useNewTabPage);
+}
+
+// Check whether the new tab and URL homepage radios should be enabled, i.e. if
+// the corresponding preference is not managed through configuration policy.
+- (BOOL)isHomepageChoiceEnabled {
+  return !newTabPageIsHomePage_.IsManaged() &&
+      !(homepage_.IsManaged() && [self isHomepageNewTabUIURL]);
+}
+
+// Returns whether or not the homepage URL text field should be enabled
+// based on if the new tab page is the home page.
+- (BOOL)isHomepageURLEnabled {
+  return !newTabPageIsHomePage_.GetValue() && !homepage_.IsManaged() &&
+      !([self isHomepageNewTabUIURL] && !newTabPageIsHomePage_.IsManaged());
+}
+
+// Returns the homepage URL.
+- (NSString*)homepageURL {
+  NSString* value = base::SysUTF8ToNSString(homepage_.GetValue());
+  return [self isHomepageNewTabUIURL] ? nil : value;
+}
+
+// Sets the homepage URL to |urlString| with some fixing up.
+- (void)setHomepageURL:(NSString*)urlString {
+  // If the text field contains a valid URL, sync it to prefs. We run it
+  // through the fixer upper to allow input like "google.com" to be converted
+  // to something valid ("http://google.com").
+  std::string unfixedURL = urlString ? base::SysNSStringToUTF8(urlString) :
+                                       chrome::kChromeUINewTabURL;
+  [self setHomepage:URLFixerUpper::FixupURL(unfixedURL, std::string())];
+}
+
+// Returns whether the home button should be checked based on the preference.
+- (BOOL)showHomeButton {
+  return showHomeButton_.GetValue() ? YES : NO;
+}
+
+// Sets the backend pref for whether or not the home button should be displayed
+// based on |value|.
+- (void)setShowHomeButton:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_Homepage_ShowHomeButton")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_Homepage_HideHomeButton")];
+  showHomeButton_.SetValueIfNotManaged(value ? true : false);
+}
+
+// Getter for the |searchEngineModel| property for bindings.
+- (id)searchEngineModel {
+  return searchEngineModel_.get();
+}
+
+// Bindings for the search engine popup. We not binding directly to the model
+// in order to siphon off the setter so we can record the metric. If we're
+// doing it with one, might as well do it with both.
+- (NSUInteger)searchEngineSelectedIndex {
+  return [searchEngineModel_ defaultIndex];
+}
+
+- (void)setSearchEngineSelectedIndex:(NSUInteger)index {
+  [self recordUserAction:UserMetricsAction("Options_SearchEngineChanged")];
+  [searchEngineModel_ setDefaultIndex:index];
+}
+
+// Called when the search engine model changes. Update the selection in the
+// popup by tickling the bindings with the new value.
+- (void)searchEngineModelChanged:(NSNotification*)notify {
+  [self setSearchEngineSelectedIndex:[self searchEngineSelectedIndex]];
+  [self setDefaultSearchEngineEnabled:![searchEngineModel_ isDefaultManaged]];
+
+}
+
+- (IBAction)manageSearchEngines:(id)sender {
+  [KeywordEditorCocoaController showKeywordEditor:profile_];
+}
+
+- (IBAction)toggleInstant:(id)sender {
+  if (instantEnabled_.GetValue()) {
+    InstantController::Disable(profile_);
+  } else {
+    [instantCheckbox_ setState:NSOffState];
+    browser::ShowInstantConfirmDialogIfNecessary([self window], profile_);
+  }
+}
+
+// Sets the state of the Instant checkbox and adds the type information to the
+// label.
+- (void)configureInstant {
+  bool enabled = instantEnabled_.GetValue();
+  NSInteger state = enabled ? NSOnState : NSOffState;
+  [instantCheckbox_ setState:state];
+}
+
+- (IBAction)learnMoreAboutInstant:(id)sender {
+  browser::ShowOptionsURL(profile_, browser::InstantLearnMoreURL());
+}
+
+// Called when the user clicks the button to make Chromium the default
+// browser. Registers http and https.
+- (IBAction)makeDefaultBrowser:(id)sender {
+  [self willChangeValueForKey:@"defaultBrowser"];
+
+  ShellIntegration::SetAsDefaultBrowser();
+  [self recordUserAction:UserMetricsAction("Options_SetAsDefaultBrowser")];
+  // If the user made Chrome the default browser, then he/she arguably wants
+  // to be notified when that changes.
+  prefs_->SetBoolean(prefs::kCheckDefaultBrowser, true);
+
+  // Tickle KVO so that the UI updates.
+  [self didChangeValueForKey:@"defaultBrowser"];
+}
+
+// Returns the Chromium default browser state and whether this is user
+// controlled or locked by a policy.
+- (BOOL)canChangeDefaultBrowser {
+  return !default_browser_policy_.IsManaged() &&
+         ShellIntegration::IsDefaultBrowser() !=
+             ShellIntegration::IS_DEFAULT_BROWSER;
+}
+
+// Returns the text color of the "chromium is your default browser" text (green
+// for yes, red for no).
+- (NSColor*)defaultBrowserTextColor {
+  ShellIntegration::DefaultBrowserState state =
+      ShellIntegration::IsDefaultBrowser();
+  return (state == ShellIntegration::IS_DEFAULT_BROWSER) ?
+    [NSColor colorWithCalibratedRed:0.0 green:135.0/255.0 blue:0 alpha:1.0] :
+    [NSColor colorWithCalibratedRed:135.0/255.0 green:0 blue:0 alpha:1.0];
+}
+
+// Returns the text for the "chromium is your default browser" string dependent
+// on if Chromium actually is or not.
+- (NSString*)defaultBrowserText {
+  ShellIntegration::DefaultBrowserState state =
+      ShellIntegration::IsDefaultBrowser();
+  int stringId;
+  if (state == ShellIntegration::IS_DEFAULT_BROWSER)
+    stringId = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
+  else if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
+    stringId = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
+  else
+    stringId = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
+  string16 text =
+      l10n_util::GetStringFUTF16(stringId,
+                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  return base::SysUTF16ToNSString(text);
+}
+
+//-------------------------------------------------------------------------
+// User Data panel
+
+// Since passwords and forms are radio groups, 'enabled' is index 0 and
+// 'disabled' is index 1. Yay.
+const int kEnabledIndex = 0;
+const int kDisabledIndex = 1;
+
+// Callback when preferences are changed. |prefName| is the name of the pref
+// that has changed. Unlike on Windows, we don't need to use this method for
+// initializing, that's handled by Cocoa Bindings.
+// Handles prefs for the "Personal Stuff" panel.
+- (void)userDataPrefChanged:(std::string*)prefName {
+  if (*prefName == prefs::kPasswordManagerEnabled) {
+    [self setPasswordManagerEnabledIndex:askSavePasswords_.GetValue() ?
+        kEnabledIndex : kDisabledIndex];
+    [self setPasswordManagerChoiceEnabled:!askSavePasswords_.IsManaged()];
+    [self setPasswordManagerButtonEnabled:
+        !askSavePasswords_.IsManaged() || askSavePasswords_.GetValue()];
+  }
+  if (*prefName == prefs::kAutoFillEnabled) {
+    bool autofill_disabled_by_policy =
+        autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue();
+    [self setAutoFillSettingsButtonEnabled:!autofill_disabled_by_policy];
+  }
+  if (*prefName == prefs::kCurrentThemeID) {
+    [self setIsUsingDefaultTheme:currentTheme_.GetValue().length() == 0];
+  }
+}
+
+// Called to launch the Keychain Access app to show the user's stored
+// passwords.
+- (IBAction)showSavedPasswords:(id)sender {
+  [self recordUserAction:UserMetricsAction("Options_ShowPasswordsExceptions")];
+  [self launchKeychainAccess];
+}
+
+// Called to show the Auto Fill Settings dialog.
+- (IBAction)showAutoFillSettings:(id)sender {
+  [self recordUserAction:UserMetricsAction("Options_ShowAutoFillSettings")];
+
+  PersonalDataManager* personalDataManager = profile_->GetPersonalDataManager();
+  if (!personalDataManager) {
+    // Should not reach here because button is disabled when
+    // |personalDataManager| is NULL.
+    NOTREACHED();
+    return;
+  }
+
+  ShowAutoFillDialog(NULL, personalDataManager, profile_);
+}
+
+// Called to import data from other browsers (Safari, Firefox, etc).
+- (IBAction)importData:(id)sender {
+  UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"), profile_);
+  [ImportSettingsDialogController showImportSettingsDialogForProfile:profile_];
+}
+
+- (IBAction)resetThemeToDefault:(id)sender {
+  [self recordUserAction:UserMetricsAction("Options_ThemesReset")];
+  profile_->ClearTheme();
+}
+
+- (IBAction)themesGallery:(id)sender {
+  [self recordUserAction:UserMetricsAction("Options_ThemesGallery")];
+  Browser* browser = BrowserList::GetLastActive();
+
+  if (!browser || !browser->GetSelectedTabContents())
+    browser = Browser::Create(profile_);
+  browser->OpenThemeGalleryTabAndActivate();
+}
+
+// Called when the "stop syncing" confirmation dialog started by
+// doSyncAction is finished.  Stop syncing only If the user clicked
+// OK.
+- (void)stopSyncAlertDidEnd:(NSAlert*)alert
+                 returnCode:(int)returnCode
+                contextInfo:(void*)contextInfo {
+  DCHECK(syncService_ && !syncService_->IsManaged());
+  if (returnCode == NSAlertFirstButtonReturn) {
+    syncService_->DisableForUser();
+    ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
+  }
+}
+
+// Called when the user clicks the multi-purpose sync button in the
+// "Personal Stuff" pane.
+- (IBAction)doSyncAction:(id)sender {
+  DCHECK(syncService_ && !syncService_->IsManaged());
+  if (syncService_->HasSyncSetupCompleted()) {
+    // If sync setup has completed that means the sync button was a
+    // "stop syncing" button.  Bring up a confirmation dialog before
+    // actually stopping syncing (see stopSyncAlertDidEnd).
+    scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
+    [alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
+        IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL)];
+    [alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
+        IDS_CANCEL)];
+    [alert setMessageText:l10n_util::GetNSStringWithFixup(
+        IDS_SYNC_STOP_SYNCING_DIALOG_TITLE)];
+    [alert setInformativeText:l10n_util::GetNSStringWithFixup(
+        IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL)];
+    [alert setAlertStyle:NSWarningAlertStyle];
+    const SEL kEndSelector =
+        @selector(stopSyncAlertDidEnd:returnCode:contextInfo:);
+    [alert beginSheetModalForWindow:[self window]
+                      modalDelegate:self
+                     didEndSelector:kEndSelector
+                        contextInfo:NULL];
+  } else {
+    // Otherwise, the sync button was a "sync my bookmarks" button.
+    // Kick off the sync setup process.
+    syncService_->ShowLoginDialog(NULL);
+    ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
+  }
+}
+
+// Called when the user clicks on the link to the privacy dashboard.
+- (IBAction)showPrivacyDashboard:(id)sender {
+  Browser* browser = BrowserList::GetLastActive();
+
+  if (!browser || !browser->GetSelectedTabContents())
+    browser = Browser::Create(profile_);
+  browser->OpenPrivacyDashboardTabAndActivate();
+}
+
+// Called when the user clicks the "Customize Sync" button in the
+// "Personal Stuff" pane.  Spawns a dialog-modal sheet that cleans
+// itself up on close.
+- (IBAction)doSyncCustomize:(id)sender {
+  syncService_->ShowConfigure(NULL);
+}
+
+// Called when the user clicks on the multi-purpose 'sync problem'
+// link.
+- (IBAction)doSyncReauthentication:(id)sender {
+  DCHECK(syncService_ && !syncService_->IsManaged());
+  syncService_->ShowErrorUI(NULL);
+}
+
+- (void)setPasswordManagerEnabledIndex:(NSInteger)value {
+  if (value == kEnabledIndex)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_PasswordManager_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_PasswordManager_Disable")];
+  askSavePasswords_.SetValueIfNotManaged(value == kEnabledIndex ? true : false);
+}
+
+- (NSInteger)passwordManagerEnabledIndex {
+  return askSavePasswords_.GetValue() ? kEnabledIndex : kDisabledIndex;
+}
+
+- (void)setIsUsingDefaultTheme:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_IsUsingDefaultTheme_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_IsUsingDefaultTheme_Disable")];
+}
+
+- (BOOL)isUsingDefaultTheme {
+  return currentTheme_.GetValue().length() == 0;
+}
+
+//-------------------------------------------------------------------------
+// Under the hood panel
+
+// Callback when preferences are changed. |prefName| is the name of the pref
+// that has changed. Unlike on Windows, we don't need to use this method for
+// initializing, that's handled by Cocoa Bindings.
+// Handles prefs for the "Under the hood" panel.
+- (void)underHoodPrefChanged:(std::string*)prefName {
+  if (*prefName == prefs::kAlternateErrorPagesEnabled) {
+    [self setShowAlternateErrorPages:
+        alternateErrorPages_.GetValue() ? YES : NO];
+    [self setShowAlternateErrorPagesEnabled:!alternateErrorPages_.IsManaged()];
+  }
+  else if (*prefName == prefs::kSearchSuggestEnabled) {
+    [self setUseSuggest:useSuggest_.GetValue() ? YES : NO];
+    [self setUseSuggestEnabled:!useSuggest_.IsManaged()];
+  }
+  else if (*prefName == prefs::kDnsPrefetchingEnabled) {
+    [self setDnsPrefetch:dnsPrefetch_.GetValue() ? YES : NO];
+    [self setDnsPrefetchEnabled:!dnsPrefetch_.IsManaged()];
+  }
+  else if (*prefName == prefs::kSafeBrowsingEnabled) {
+    [self setSafeBrowsing:safeBrowsing_.GetValue() ? YES : NO];
+    [self setSafeBrowsingEnabled:!safeBrowsing_.IsManaged()];
+  }
+  else if (*prefName == prefs::kMetricsReportingEnabled) {
+    [self setMetricsReporting:metricsReporting_.GetValue() ? YES : NO];
+    [self setMetricsReportingEnabled:!metricsReporting_.IsManaged()];
+  }
+  else if (*prefName == prefs::kDownloadDefaultDirectory) {
+    // Poke KVO.
+    [self willChangeValueForKey:@"defaultDownloadLocation"];
+    [self didChangeValueForKey:@"defaultDownloadLocation"];
+  }
+  else if (*prefName == prefs::kPromptForDownload) {
+    [self setAskForSaveLocation:askForSaveLocation_.GetValue() ? YES : NO];
+  }
+  else if (*prefName == prefs::kEnableTranslate) {
+    [self setTranslateEnabled:translateEnabled_.GetValue() ? YES : NO];
+  }
+  else if (*prefName == prefs::kWebkitTabsToLinks) {
+    [self setTabsToLinks:tabsToLinks_.GetValue() ? YES : NO];
+  }
+  else if (*prefName == prefs::kDownloadExtensionsToOpen) {
+    // Poke KVC.
+    [self setFileHandlerUIEnabled:[self fileHandlerUIEnabled]];
+  }
+  else if (proxyPrefs_->IsObserved(*prefName)) {
+    [self setProxiesConfigureButtonEnabled:!proxyPrefs_->IsManaged()];
+  }
+}
+
+// Set the new download path and notify the UI via KVO.
+- (void)downloadPathPanelDidEnd:(NSOpenPanel*)panel
+                           code:(NSInteger)returnCode
+                        context:(void*)context {
+  if (returnCode == NSOKButton) {
+    [self recordUserAction:UserMetricsAction("Options_SetDownloadDirectory")];
+    NSURL* path = [[panel URLs] lastObject];  // We only allow 1 item.
+    [self willChangeValueForKey:@"defaultDownloadLocation"];
+    defaultDownloadLocation_.SetValue(base::SysNSStringToUTF8([path path]));
+    [self didChangeValueForKey:@"defaultDownloadLocation"];
+  }
+}
+
+// Bring up an open panel to allow the user to set a new downloads location.
+- (void)browseDownloadLocation:(id)sender {
+  NSOpenPanel* panel = [NSOpenPanel openPanel];
+  [panel setAllowsMultipleSelection:NO];
+  [panel setCanChooseFiles:NO];
+  [panel setCanChooseDirectories:YES];
+  NSString* path = base::SysUTF8ToNSString(defaultDownloadLocation_.GetValue());
+  [panel beginSheetForDirectory:path
+                           file:nil
+                          types:nil
+                 modalForWindow:[self window]
+                  modalDelegate:self
+                 didEndSelector:@selector(downloadPathPanelDidEnd:code:context:)
+                    contextInfo:NULL];
+}
+
+// Called to clear user's browsing data. This puts up an application-modal
+// dialog to guide the user through clearing the data.
+- (IBAction)clearData:(id)sender {
+  [ClearBrowsingDataController
+      showClearBrowsingDialogForProfile:profile_];
+}
+
+// Opens the "Content Settings" dialog.
+- (IBAction)showContentSettings:(id)sender {
+  [ContentSettingsDialogController
+      showContentSettingsForType:CONTENT_SETTINGS_TYPE_DEFAULT
+                         profile:profile_];
+}
+
+- (IBAction)privacyLearnMore:(id)sender {
+  GURL url = google_util::AppendGoogleLocaleParam(
+      GURL(chrome::kPrivacyLearnMoreURL));
+  // We open a new browser window so the Options dialog doesn't get lost
+  // behind other windows.
+  browser::ShowOptionsURL(profile_, url);
+}
+
+- (IBAction)resetAutoOpenFiles:(id)sender {
+  profile_->GetDownloadManager()->download_prefs()->ResetAutoOpen();
+  [self recordUserAction:UserMetricsAction("Options_ResetAutoOpenFiles")];
+}
+
+- (IBAction)openProxyPreferences:(id)sender {
+  NSArray* itemsToOpen = [NSArray arrayWithObject:[NSURL fileURLWithPath:
+      @"/System/Library/PreferencePanes/Network.prefPane"]];
+
+  const char* proxyPrefCommand = "Proxies";
+  base::mac::ScopedAEDesc<> openParams;
+  OSStatus status = AECreateDesc('ptru',
+                                 proxyPrefCommand,
+                                 strlen(proxyPrefCommand),
+                                 openParams.OutPointer());
+  LOG_IF(ERROR, status != noErr) << "Failed to create open params: " << status;
+
+  LSLaunchURLSpec launchSpec = { 0 };
+  launchSpec.itemURLs = (CFArrayRef)itemsToOpen;
+  launchSpec.passThruParams = openParams;
+  launchSpec.launchFlags = kLSLaunchAsync | kLSLaunchDontAddToRecents;
+  LSOpenFromURLSpec(&launchSpec, NULL);
+}
+
+// Returns whether the alternate error page checkbox should be checked based
+// on the preference.
+- (BOOL)showAlternateErrorPages {
+  return alternateErrorPages_.GetValue() ? YES : NO;
+}
+
+// Sets the backend pref for whether or not the alternate error page checkbox
+// should be displayed based on |value|.
+- (void)setShowAlternateErrorPages:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_LinkDoctorCheckbox_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_LinkDoctorCheckbox_Disable")];
+  alternateErrorPages_.SetValueIfNotManaged(value ? true : false);
+}
+
+// Returns whether the suggest checkbox should be checked based on the
+// preference.
+- (BOOL)useSuggest {
+  return useSuggest_.GetValue() ? YES : NO;
+}
+
+// Sets the backend pref for whether or not the suggest checkbox should be
+// displayed based on |value|.
+- (void)setUseSuggest:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_UseSuggestCheckbox_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_UseSuggestCheckbox_Disable")];
+  useSuggest_.SetValueIfNotManaged(value ? true : false);
+}
+
+// Returns whether the DNS prefetch checkbox should be checked based on the
+// preference.
+- (BOOL)dnsPrefetch {
+  return dnsPrefetch_.GetValue() ? YES : NO;
+}
+
+// Sets the backend pref for whether or not the DNS prefetch checkbox should be
+// displayed based on |value|.
+- (void)setDnsPrefetch:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_DnsPrefetchCheckbox_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_DnsPrefetchCheckbox_Disable")];
+  dnsPrefetch_.SetValueIfNotManaged(value ? true : false);
+}
+
+// Returns whether the safe browsing checkbox should be checked based on the
+// preference.
+- (BOOL)safeBrowsing {
+  return safeBrowsing_.GetValue() ? YES : NO;
+}
+
+// Sets the backend pref for whether or not the safe browsing checkbox should be
+// displayed based on |value|.
+- (void)setSafeBrowsing:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_SafeBrowsingCheckbox_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_SafeBrowsingCheckbox_Disable")];
+  safeBrowsing_.SetValueIfNotManaged(value ? true : false);
+  SafeBrowsingService* safeBrowsingService =
+      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(safeBrowsingService,
+                        &SafeBrowsingService::OnEnable,
+                        safeBrowsing_.GetValue()));
+}
+
+// Returns whether the metrics reporting checkbox should be checked based on the
+// preference.
+- (BOOL)metricsReporting {
+  return metricsReporting_.GetValue() ? YES : NO;
+}
+
+// Sets the backend pref for whether or not the metrics reporting checkbox
+// should be displayed based on |value|.
+- (void)setMetricsReporting:(BOOL)value {
+  if (value)
+    [self recordUserAction:UserMetricsAction(
+                           "Options_MetricsReportingCheckbox_Enable")];
+  else
+    [self recordUserAction:UserMetricsAction(
+                           "Options_MetricsReportingCheckbox_Disable")];
+
+  // TODO(pinkerton): windows shows a dialog here telling the user they need to
+  // restart for this to take effect. http://crbug.com/34653
+  metricsReporting_.SetValueIfNotManaged(value ? true : false);
+
+  bool enabled = metricsReporting_.GetValue();
+  GoogleUpdateSettings::SetCollectStatsConsent(enabled);
+  bool update_pref = GoogleUpdateSettings::GetCollectStatsConsent();
+  if (enabled != update_pref) {
+    DVLOG(1) << "GENERAL SECTION: Unable to set crash report status to "
+             << enabled;
+  }
+  // Only change the pref if GoogleUpdateSettings::GetCollectStatsConsent
+  // succeeds.
+  enabled = update_pref;
+
+  MetricsService* metrics = g_browser_process->metrics_service();
+  DCHECK(metrics);
+  if (metrics) {
+    metrics->SetUserPermitsUpload(enabled);
+    if (enabled)
+      metrics->Start();
+    else
+      metrics->Stop();
+  }
+}
+
+- (NSURL*)defaultDownloadLocation {
+  NSString* pathString =
+      base::SysUTF8ToNSString(defaultDownloadLocation_.GetValue());
+  return [NSURL fileURLWithPath:pathString];
+}
+
+- (BOOL)askForSaveLocation {
+  return askForSaveLocation_.GetValue();
+}
+
+- (void)setAskForSaveLocation:(BOOL)value {
+  if (value) {
+    [self recordUserAction:UserMetricsAction(
+                           "Options_AskForSaveLocation_Enable")];
+  } else {
+    [self recordUserAction:UserMetricsAction(
+                           "Options_AskForSaveLocation_Disable")];
+  }
+  askForSaveLocation_.SetValue(value);
+}
+
+- (BOOL)fileHandlerUIEnabled {
+  if (!profile_->GetDownloadManager())  // Not set in unit tests.
+    return NO;
+  return profile_->GetDownloadManager()->download_prefs()->IsAutoOpenUsed();
+}
+
+- (void)setFileHandlerUIEnabled:(BOOL)value {
+  [resetFileHandlersButton_ setEnabled:value];
+}
+
+- (BOOL)translateEnabled {
+  return translateEnabled_.GetValue();
+}
+
+- (void)setTranslateEnabled:(BOOL)value {
+  if (value) {
+    [self recordUserAction:UserMetricsAction("Options_Translate_Enable")];
+  } else {
+    [self recordUserAction:UserMetricsAction("Options_Translate_Disable")];
+  }
+  translateEnabled_.SetValue(value);
+}
+
+- (BOOL)tabsToLinks {
+  return tabsToLinks_.GetValue();
+}
+
+- (void)setTabsToLinks:(BOOL)value {
+  if (value) {
+    [self recordUserAction:UserMetricsAction("Options_TabsToLinks_Enable")];
+  } else {
+    [self recordUserAction:UserMetricsAction("Options_TabsToLinks_Disable")];
+  }
+  tabsToLinks_.SetValue(value);
+}
+
+- (void)fontAndLanguageEndSheet:(NSWindow*)sheet
+                     returnCode:(NSInteger)returnCode
+                    contextInfo:(void*)context {
+  [sheet close];
+  [sheet orderOut:self];
+  fontLanguageSettings_ = nil;
+}
+
+- (IBAction)changeFontAndLanguageSettings:(id)sender {
+  // Intentionally leak the controller as it will clean itself up when the
+  // sheet closes.
+  fontLanguageSettings_ =
+      [[FontLanguageSettingsController alloc] initWithProfile:profile_];
+  [NSApp beginSheet:[fontLanguageSettings_ window]
+     modalForWindow:[self window]
+      modalDelegate:self
+     didEndSelector:@selector(fontAndLanguageEndSheet:returnCode:contextInfo:)
+        contextInfo:nil];
+}
+
+// Called to launch the Keychain Access app to show the user's stored
+// certificates. Note there's no way to script the app to auto-select the
+// certificates.
+- (IBAction)showCertificates:(id)sender {
+  [self recordUserAction:UserMetricsAction("Options_ManagerCerts")];
+  [self launchKeychainAccess];
+}
+
+- (IBAction)resetToDefaults:(id)sender {
+  // The alert will clean itself up in the did-end selector.
+  NSAlert* alert = [[NSAlert alloc] init];
+  [alert setMessageText:l10n_util::GetNSString(IDS_OPTIONS_RESET_MESSAGE)];
+  NSButton* resetButton = [alert addButtonWithTitle:
+      l10n_util::GetNSString(IDS_OPTIONS_RESET_OKLABEL)];
+  [resetButton setKeyEquivalent:@""];
+  NSButton* cancelButton = [alert addButtonWithTitle:
+      l10n_util::GetNSString(IDS_OPTIONS_RESET_CANCELLABEL)];
+  [cancelButton setKeyEquivalent:@"\r"];
+
+  [alert beginSheetModalForWindow:[self window]
+                    modalDelegate:self
+                   didEndSelector:@selector(resetToDefaults:returned:context:)
+                      contextInfo:nil];
+}
+
+- (void)resetToDefaults:(NSAlert*)alert
+               returned:(NSInteger)code
+                context:(void*)context {
+  if (code == NSAlertFirstButtonReturn) {
+    OptionsUtil::ResetToDefaults(profile_);
+  }
+  [alert autorelease];
+}
+
+//-------------------------------------------------------------------------
+
+// Callback when preferences are changed. |prefName| is the name of the
+// pref that has changed and should not be NULL.
+- (void)prefChanged:(std::string*)prefName {
+  DCHECK(prefName);
+  if (!prefName) return;
+  [self basicsPrefChanged:prefName];
+  [self userDataPrefChanged:prefName];
+  [self underHoodPrefChanged:prefName];
+}
+
+// Callback when sync service state has changed.
+//
+// TODO(akalin): Decomp this out since a lot of it is copied from the
+// Windows version.
+// TODO(akalin): Change the background of the status label/link on error.
+- (void)syncStateChanged {
+  DCHECK(syncService_);
+
+  string16 statusLabel, linkLabel;
+  sync_ui_util::MessageType status =
+      sync_ui_util::GetStatusLabels(syncService_, &statusLabel, &linkLabel);
+  bool managed = syncService_->IsManaged();
+
+  [syncButton_ setEnabled:!syncService_->WizardIsVisible()];
+  NSString* buttonLabel;
+  if (syncService_->HasSyncSetupCompleted()) {
+    buttonLabel = l10n_util::GetNSStringWithFixup(
+        IDS_SYNC_STOP_SYNCING_BUTTON_LABEL);
+    [syncCustomizeButton_ setHidden:false];
+  } else if (syncService_->SetupInProgress()) {
+    buttonLabel = l10n_util::GetNSStringWithFixup(
+        IDS_SYNC_NTP_SETUP_IN_PROGRESS);
+    [syncCustomizeButton_ setHidden:true];
+  } else {
+    buttonLabel = l10n_util::GetNSStringWithFixup(
+        IDS_SYNC_START_SYNC_BUTTON_LABEL);
+    [syncCustomizeButton_ setHidden:true];
+  }
+  [syncCustomizeButton_ setEnabled:!managed];
+  [syncButton_ setTitle:buttonLabel];
+  [syncButton_ setEnabled:!managed];
+
+  [syncStatus_ setStringValue:base::SysUTF16ToNSString(statusLabel)];
+  [syncLink_ setHidden:linkLabel.empty()];
+  [syncLink_ setTitle:base::SysUTF16ToNSString(linkLabel)];
+  [syncLink_ setEnabled:!managed];
+
+  NSButtonCell* syncLinkCell = static_cast<NSButtonCell*>([syncLink_ cell]);
+  if (!syncStatusNoErrorBackgroundColor_) {
+    DCHECK(!syncLinkNoErrorBackgroundColor_);
+    // We assume that the sync controls start off in a non-error
+    // state.
+    syncStatusNoErrorBackgroundColor_.reset(
+        [[syncStatus_ backgroundColor] retain]);
+    syncLinkNoErrorBackgroundColor_.reset(
+        [[syncLinkCell backgroundColor] retain]);
+  }
+  if (status == sync_ui_util::SYNC_ERROR) {
+    [syncStatus_ setBackgroundColor:syncErrorBackgroundColor_];
+    [syncLinkCell setBackgroundColor:syncErrorBackgroundColor_];
+  } else {
+    [syncStatus_ setBackgroundColor:syncStatusNoErrorBackgroundColor_];
+    [syncLinkCell setBackgroundColor:syncLinkNoErrorBackgroundColor_];
+  }
+}
+
+// Show the preferences window.
+- (IBAction)showPreferences:(id)sender {
+  [self showWindow:sender];
+}
+
+- (IBAction)toolbarButtonSelected:(id)sender {
+  DCHECK([sender isKindOfClass:[NSToolbarItem class]]);
+  OptionsPage page = [self getPageForToolbarItem:sender];
+  [self displayPreferenceViewForPage:page animate:YES];
+}
+
+// Helper to update the window to display a preferences view for a page.
+- (void)displayPreferenceViewForPage:(OptionsPage)page
+                             animate:(BOOL)animate {
+  NSWindow* prefsWindow = [self window];
+
+  // Needs to go *after* the call to [self window], which triggers
+  // awakeFromNib if necessary.
+  NSView* prefsView = [self getPrefsViewForPage:page];
+  NSView* contentView = [prefsWindow contentView];
+
+  // Make sure we aren't being told to display the same thing again.
+  if (currentPrefsView_ == prefsView &&
+      managedPrefsBannerVisible_ == bannerState_->IsVisible()) {
+    return;
+  }
+
+  // Remember new options page as current page.
+  if (page != OPTIONS_PAGE_DEFAULT)
+    lastSelectedPage_.SetValue(page);
+
+  // Stop any running animation, and reset the subviews to the new state. We
+  // re-add any views we need for animation later.
+  [animation_ stopAnimation];
+  NSView* oldPrefsView = currentPrefsView_;
+  currentPrefsView_ = prefsView;
+  [self resetSubViews];
+
+  // Update the banner state.
+  [self initBannerStateForPage:page];
+  BOOL showBanner = bannerState_->IsVisible();
+
+  // Update the window title.
+  NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page];
+  [prefsWindow setTitle:[toolbarItem label]];
+
+  // Calculate new frames for the subviews.
+  NSRect prefsViewFrame = [prefsView frame];
+  NSRect contentViewFrame = [contentView frame];
+  NSRect bannerViewFrame = [managedPrefsBannerView_ frame];
+
+  // Determine what height the managed prefs banner will use.
+  CGFloat bannerViewHeight = showBanner ? NSHeight(bannerViewFrame) : 0.0;
+
+  if (animate) {
+    // NSViewAnimation doesn't seem to honor subview resizing as it animates the
+    // Window's frame.  So instead of trying to get the top in the right place,
+    // just set the origin where it should be at the end, and let the fade/size
+    // slide things into the right spot.
+    prefsViewFrame.origin.y = 0.0;
+  } else {
+    // The prefView is anchored to the top of its parent, so set its origin so
+    // that the top is where it should be.  When the window's frame is set, the
+    // origin will be adjusted to keep it in the right spot.
+    prefsViewFrame.origin.y = NSHeight(contentViewFrame) -
+        NSHeight(prefsViewFrame) - bannerViewHeight;
+  }
+  bannerViewFrame.origin.y = NSHeight(prefsViewFrame);
+  bannerViewFrame.size.width = NSWidth(contentViewFrame);
+  [prefsView setFrame:prefsViewFrame];
+
+  // Figure out the size of the window.
+  NSRect windowFrame = [contentView convertRect:[prefsWindow frame]
+                                       fromView:nil];
+  CGFloat titleToolbarHeight =
+      NSHeight(windowFrame) - NSHeight(contentViewFrame);
+  windowFrame.size.height =
+      NSHeight(prefsViewFrame) + titleToolbarHeight + bannerViewHeight;
+  DCHECK_GE(NSWidth(windowFrame), NSWidth(prefsViewFrame))
+      << "Initial width set wasn't wide enough.";
+  windowFrame = [contentView convertRect:windowFrame toView:nil];
+  windowFrame.origin.y = NSMaxY([prefsWindow frame]) - NSHeight(windowFrame);
+
+  // Now change the size.
+  if (animate) {
+    NSMutableArray* animations = [NSMutableArray arrayWithCapacity:4];
+    if (oldPrefsView != prefsView) {
+      // Fade between prefs views if they change.
+      [contentView addSubview:oldPrefsView
+                   positioned:NSWindowBelow
+                   relativeTo:nil];
+      [animations addObject:
+          [NSDictionary dictionaryWithObjectsAndKeys:
+              oldPrefsView, NSViewAnimationTargetKey,
+              NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey,
+              nil]];
+      [animations addObject:
+          [NSDictionary dictionaryWithObjectsAndKeys:
+              prefsView, NSViewAnimationTargetKey,
+              NSViewAnimationFadeInEffect, NSViewAnimationEffectKey,
+              nil]];
+    } else {
+      // Make sure the prefs pane ends up in the right position in case we
+      // manipulate the banner.
+      [animations addObject:
+          [NSDictionary dictionaryWithObjectsAndKeys:
+              prefsView, NSViewAnimationTargetKey,
+              [NSValue valueWithRect:prefsViewFrame],
+                  NSViewAnimationEndFrameKey,
+              nil]];
+    }
+    if (showBanner != managedPrefsBannerVisible_) {
+      // Slide the warning banner in or out of view.
+      [animations addObject:
+          [NSDictionary dictionaryWithObjectsAndKeys:
+              managedPrefsBannerView_, NSViewAnimationTargetKey,
+              [NSValue valueWithRect:bannerViewFrame],
+                  NSViewAnimationEndFrameKey,
+              nil]];
+    }
+    // Window resize animation.
+    [animations addObject:
+        [NSDictionary dictionaryWithObjectsAndKeys:
+            prefsWindow, NSViewAnimationTargetKey,
+            [NSValue valueWithRect:windowFrame], NSViewAnimationEndFrameKey,
+            nil]];
+    [animation_ setViewAnimations:animations];
+    // The default duration is 0.5s, which actually feels slow in here, so speed
+    // it up a bit.
+    [animation_ gtm_setDuration:0.2
+                      eventMask:NSLeftMouseUpMask];
+    [animation_ startAnimation];
+  } else {
+    // If not animating, odds are we don't want to display either (because it
+    // is initial window setup).
+    [prefsWindow setFrame:windowFrame display:NO];
+    [managedPrefsBannerView_ setFrame:bannerViewFrame];
+  }
+
+  managedPrefsBannerVisible_ = showBanner;
+}
+
+- (void)resetSubViews {
+  // Reset subviews to current prefs view and banner, remove any views that
+  // might have been left over from previous state or animation.
+  NSArray* subviews = [NSArray arrayWithObjects:
+                          currentPrefsView_, managedPrefsBannerView_, nil];
+  [[[self window] contentView] setSubviews:subviews];
+  [[self window] setInitialFirstResponder:currentPrefsView_];
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+  DCHECK_EQ(animation_.get(), animation);
+  // Animation finished, reset subviews to current prefs view and the banner.
+  [self resetSubViews];
+}
+
+// Reinitializes the banner state tracker object to watch for managed bits of
+// preferences relevant to the given options |page|.
+- (void)initBannerStateForPage:(OptionsPage)page {
+  page = [self normalizePage:page];
+
+  // During unit tests, there is no local state object, so we fall back to
+  // the prefs object (where we've explicitly registered this pref so we
+  // know it's there).
+  PrefService* local = g_browser_process->local_state();
+  if (!local)
+    local = prefs_;
+  bannerState_.reset(
+      new PreferencesWindowControllerInternal::ManagedPrefsBannerState(
+          self, page, local, prefs_));
+}
+
+- (void)switchToPage:(OptionsPage)page animate:(BOOL)animate {
+  [self displayPreferenceViewForPage:page animate:animate];
+  NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page];
+  [toolbar_ setSelectedItemIdentifier:[toolbarItem itemIdentifier]];
+}
+
+// Called when the window is being closed. Send out a notification that the user
+// is done editing preferences. Make sure there are no pending field editors
+// by clearing the first responder.
+- (void)windowWillClose:(NSNotification*)notification {
+  // Setting the first responder to the window ends any in-progress field
+  // editor. This will update the model appropriately so there's nothing left
+  // to do.
+  if (![[self window] makeFirstResponder:[self window]]) {
+    // We've hit a recalcitrant field editor, force it to go away.
+    [[self window] endEditingFor:nil];
+  }
+  [self autorelease];
+}
+
+- (void)controlTextDidEndEditing:(NSNotification*)notification {
+  [customPagesSource_ validateURLs];
+}
+
+@end
+
+@implementation PreferencesWindowController(Testing)
+
+- (IntegerPrefMember*)lastSelectedPage {
+  return &lastSelectedPage_;
+}
+
+- (NSToolbar*)toolbar {
+  return toolbar_;
+}
+
+- (NSView*)basicsView {
+  return basicsView_;
+}
+
+- (NSView*)personalStuffView {
+  return personalStuffView_;
+}
+
+- (NSView*)underTheHoodView {
+  return underTheHoodView_;
+}
+
+- (OptionsPage)normalizePage:(OptionsPage)page {
+  if (page == OPTIONS_PAGE_DEFAULT) {
+    // Get the last visited page from local state.
+    page = static_cast<OptionsPage>(lastSelectedPage_.GetValue());
+    if (page == OPTIONS_PAGE_DEFAULT) {
+      page = OPTIONS_PAGE_GENERAL;
+    }
+  }
+  return page;
+}
+
+- (NSToolbarItem*)getToolbarItemForPage:(OptionsPage)page {
+  NSUInteger pageIndex = (NSUInteger)[self normalizePage:page];
+  NSArray* items = [toolbar_ items];
+  NSUInteger itemCount = [items count];
+  DCHECK_GE(pageIndex, 0U);
+  if (pageIndex >= itemCount) {
+    NOTIMPLEMENTED();
+    pageIndex = 0;
+  }
+  DCHECK_GT(itemCount, 0U);
+  return [items objectAtIndex:pageIndex];
+}
+
+- (OptionsPage)getPageForToolbarItem:(NSToolbarItem*)toolbarItem {
+  // Tags are set in the nib file.
+  switch ([toolbarItem tag]) {
+    case 0:  // Basics
+      return OPTIONS_PAGE_GENERAL;
+    case 1:  // Personal Stuff
+      return OPTIONS_PAGE_CONTENT;
+    case 2:  // Under the Hood
+      return OPTIONS_PAGE_ADVANCED;
+    default:
+      NOTIMPLEMENTED();
+      return OPTIONS_PAGE_GENERAL;
+  }
+}
+
+- (NSView*)getPrefsViewForPage:(OptionsPage)page {
+  // The views will be NULL if this is mistakenly called before awakeFromNib.
+  DCHECK(basicsView_);
+  DCHECK(personalStuffView_);
+  DCHECK(underTheHoodView_);
+  page = [self normalizePage:page];
+  switch (page) {
+    case OPTIONS_PAGE_GENERAL:
+      return basicsView_;
+    case OPTIONS_PAGE_CONTENT:
+      return personalStuffView_;
+    case OPTIONS_PAGE_ADVANCED:
+      return underTheHoodView_;
+    case OPTIONS_PAGE_DEFAULT:
+    case OPTIONS_PAGE_COUNT:
+      LOG(DFATAL) << "Invalid page value " << page;
+  }
+  return basicsView_;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/options/preferences_window_controller_unittest.mm b/chrome/browser/ui/cocoa/options/preferences_window_controller_unittest.mm
new file mode 100644
index 0000000..5411022
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/preferences_window_controller_unittest.mm
@@ -0,0 +1,241 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/options/preferences_window_controller.h"
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/custom_home_pages_model.h"
+#include "chrome/browser/ui/options/options_window.h"
+#include "chrome/common/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+// Helper Objective-C object that sets a BOOL when we get a particular
+// callback from the prefs window.
+@interface PrefsClosedObserver : NSObject {
+ @public
+  BOOL gotNotification_;
+}
+- (void)prefsWindowClosed:(NSNotification*)notify;
+@end
+
+@implementation PrefsClosedObserver
+- (void)prefsWindowClosed:(NSNotification*)notify {
+  gotNotification_ = YES;
+}
+@end
+
+namespace {
+
+class PrefsControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    // The metrics reporting pref is registerd on the local state object in
+    // real builds, but we don't have one of those for unit tests. Register
+    // it on prefs so we'll find it when we go looking.
+    PrefService* prefs = browser_helper_.profile()->GetPrefs();
+    prefs->RegisterBooleanPref(prefs::kMetricsReportingEnabled, false);
+
+    pref_controller_ = [[PreferencesWindowController alloc]
+                         initWithProfile:browser_helper_.profile()
+                             initialPage:OPTIONS_PAGE_DEFAULT];
+    EXPECT_TRUE(pref_controller_);
+  }
+
+  virtual void TearDown() {
+    [pref_controller_ close];
+    CocoaTest::TearDown();
+  }
+
+  BrowserTestHelper browser_helper_;
+  PreferencesWindowController* pref_controller_;
+};
+
+// Test showing the preferences window and making sure it's visible, then
+// making sure we get the notification when it's closed.
+TEST_F(PrefsControllerTest, ShowAndClose) {
+  [pref_controller_ showPreferences:nil];
+  EXPECT_TRUE([[pref_controller_ window] isVisible]);
+
+  scoped_nsobject<PrefsClosedObserver> observer(
+      [[PrefsClosedObserver alloc] init]);
+  NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
+  [defaultCenter addObserver:observer.get()
+                    selector:@selector(prefsWindowClosed:)
+                        name:NSWindowWillCloseNotification
+                      object:[pref_controller_ window]];
+  [[pref_controller_ window] performClose:observer];
+  EXPECT_TRUE(observer.get()->gotNotification_);
+  [defaultCenter removeObserver:observer.get()];
+
+  // Prevent pref_controller_ from being closed again in TearDown()
+  pref_controller_ = nil;
+}
+
+TEST_F(PrefsControllerTest, ValidateCustomHomePagesTable) {
+  // First, insert two valid URLs into the CustomHomePagesModel.
+  GURL url1("http://www.google.com/");
+  GURL url2("http://maps.google.com/");
+  std::vector<GURL> urls;
+  urls.push_back(url1);
+  urls.push_back(url2);
+  [[pref_controller_ customPagesSource] setURLs:urls];
+  EXPECT_EQ(2U, [[pref_controller_ customPagesSource] countOfCustomHomePages]);
+
+  // Now insert a bad (empty) URL into the model.
+  [[pref_controller_ customPagesSource] setURLStringEmptyAt:1];
+
+  // Send a notification to simulate the end of editing on a cell in the table
+  // which should trigger validation.
+  [pref_controller_ controlTextDidEndEditing:[NSNotification
+      notificationWithName:NSControlTextDidEndEditingNotification
+                    object:nil]];
+  EXPECT_EQ(1U, [[pref_controller_ customPagesSource] countOfCustomHomePages]);
+}
+
+TEST_F(PrefsControllerTest, NormalizePage) {
+  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
+            [pref_controller_ normalizePage:OPTIONS_PAGE_GENERAL]);
+  EXPECT_EQ(OPTIONS_PAGE_CONTENT,
+            [pref_controller_ normalizePage:OPTIONS_PAGE_CONTENT]);
+  EXPECT_EQ(OPTIONS_PAGE_ADVANCED,
+            [pref_controller_ normalizePage:OPTIONS_PAGE_ADVANCED]);
+
+  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_ADVANCED);
+  EXPECT_EQ(OPTIONS_PAGE_ADVANCED,
+            [pref_controller_ normalizePage:OPTIONS_PAGE_DEFAULT]);
+
+  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_DEFAULT);
+  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
+            [pref_controller_ normalizePage:OPTIONS_PAGE_DEFAULT]);
+}
+
+TEST_F(PrefsControllerTest, GetToolbarItemForPage) {
+  // Trigger awakeFromNib.
+  [pref_controller_ window];
+
+  NSArray* toolbarItems = [[pref_controller_ toolbar] items];
+  EXPECT_EQ([toolbarItems objectAtIndex:0],
+            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_GENERAL]);
+  EXPECT_EQ([toolbarItems objectAtIndex:1],
+            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_CONTENT]);
+  EXPECT_EQ([toolbarItems objectAtIndex:2],
+            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_ADVANCED]);
+
+  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_ADVANCED);
+  EXPECT_EQ([toolbarItems objectAtIndex:2],
+            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_DEFAULT]);
+
+  // Out-of-range argument.
+  EXPECT_EQ([toolbarItems objectAtIndex:0],
+            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_COUNT]);
+}
+
+TEST_F(PrefsControllerTest, GetPageForToolbarItem) {
+  scoped_nsobject<NSToolbarItem> toolbarItem(
+      [[NSToolbarItem alloc] initWithItemIdentifier:@""]);
+  [toolbarItem setTag:0];
+  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
+            [pref_controller_ getPageForToolbarItem:toolbarItem]);
+  [toolbarItem setTag:1];
+  EXPECT_EQ(OPTIONS_PAGE_CONTENT,
+            [pref_controller_ getPageForToolbarItem:toolbarItem]);
+  [toolbarItem setTag:2];
+  EXPECT_EQ(OPTIONS_PAGE_ADVANCED,
+            [pref_controller_ getPageForToolbarItem:toolbarItem]);
+
+  // Out-of-range argument.
+  [toolbarItem setTag:3];
+  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
+            [pref_controller_ getPageForToolbarItem:toolbarItem]);
+}
+
+TEST_F(PrefsControllerTest, GetPrefsViewForPage) {
+  // Trigger awakeFromNib.
+  [pref_controller_ window];
+
+  EXPECT_EQ([pref_controller_ basicsView],
+            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_GENERAL]);
+  EXPECT_EQ([pref_controller_ personalStuffView],
+            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_CONTENT]);
+  EXPECT_EQ([pref_controller_ underTheHoodView],
+            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_ADVANCED]);
+
+  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_ADVANCED);
+  EXPECT_EQ([pref_controller_ underTheHoodView],
+            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_DEFAULT]);
+}
+
+TEST_F(PrefsControllerTest, SwitchToPage) {
+  // Trigger awakeFromNib.
+  NSWindow* window = [pref_controller_ window];
+
+  NSView* contentView = [window contentView];
+  NSView* basicsView = [pref_controller_ basicsView];
+  NSView* personalStuffView = [pref_controller_ personalStuffView];
+  NSView* underTheHoodView = [pref_controller_ underTheHoodView];
+  NSToolbar* toolbar = [pref_controller_ toolbar];
+  NSToolbarItem* basicsToolbarItem =
+      [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_GENERAL];
+  NSToolbarItem* personalStuffToolbarItem =
+      [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_CONTENT];
+  NSToolbarItem* underTheHoodToolbarItem =
+      [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_ADVANCED];
+  NSString* basicsIdentifier = [basicsToolbarItem itemIdentifier];
+  NSString* personalStuffIdentifier = [personalStuffToolbarItem itemIdentifier];
+  NSString* underTheHoodIdentifier = [underTheHoodToolbarItem itemIdentifier];
+  IntegerPrefMember* lastSelectedPage = [pref_controller_ lastSelectedPage];
+
+  // Test without animation.
+
+  [pref_controller_ switchToPage:OPTIONS_PAGE_GENERAL animate:NO];
+  EXPECT_TRUE([basicsView isDescendantOf:contentView]);
+  EXPECT_FALSE([personalStuffView isDescendantOf:contentView]);
+  EXPECT_FALSE([underTheHoodView isDescendantOf:contentView]);
+  EXPECT_NSEQ(basicsIdentifier, [toolbar selectedItemIdentifier]);
+  EXPECT_EQ(OPTIONS_PAGE_GENERAL, lastSelectedPage->GetValue());
+  EXPECT_NSEQ([basicsToolbarItem label], [window title]);
+
+  [pref_controller_ switchToPage:OPTIONS_PAGE_CONTENT animate:NO];
+  EXPECT_FALSE([basicsView isDescendantOf:contentView]);
+  EXPECT_TRUE([personalStuffView isDescendantOf:contentView]);
+  EXPECT_FALSE([underTheHoodView isDescendantOf:contentView]);
+  EXPECT_NSEQ([toolbar selectedItemIdentifier], personalStuffIdentifier);
+  EXPECT_EQ(OPTIONS_PAGE_CONTENT, lastSelectedPage->GetValue());
+  EXPECT_NSEQ([personalStuffToolbarItem label], [window title]);
+
+  [pref_controller_ switchToPage:OPTIONS_PAGE_ADVANCED animate:NO];
+  EXPECT_FALSE([basicsView isDescendantOf:contentView]);
+  EXPECT_FALSE([personalStuffView isDescendantOf:contentView]);
+  EXPECT_TRUE([underTheHoodView isDescendantOf:contentView]);
+  EXPECT_NSEQ([toolbar selectedItemIdentifier], underTheHoodIdentifier);
+  EXPECT_EQ(OPTIONS_PAGE_ADVANCED, lastSelectedPage->GetValue());
+  EXPECT_NSEQ([underTheHoodToolbarItem label], [window title]);
+
+  // Test OPTIONS_PAGE_DEFAULT.
+
+  lastSelectedPage->SetValue(OPTIONS_PAGE_CONTENT);
+  [pref_controller_ switchToPage:OPTIONS_PAGE_DEFAULT animate:NO];
+  EXPECT_FALSE([basicsView isDescendantOf:contentView]);
+  EXPECT_TRUE([personalStuffView isDescendantOf:contentView]);
+  EXPECT_FALSE([underTheHoodView isDescendantOf:contentView]);
+  EXPECT_NSEQ(personalStuffIdentifier, [toolbar selectedItemIdentifier]);
+  EXPECT_EQ(OPTIONS_PAGE_CONTENT, lastSelectedPage->GetValue());
+  EXPECT_NSEQ([personalStuffToolbarItem label], [window title]);
+
+  // TODO(akalin): Figure out how to test animation; we'll need everything
+  // to stick around until the animation finishes.
+}
+
+// TODO(akalin): Figure out how to test sync controls.
+// TODO(akalin): Figure out how to test that sync controls are not shown
+// when there isn't a sync service.
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/options/search_engine_list_model.h b/chrome/browser/ui/cocoa/options/search_engine_list_model.h
new file mode 100644
index 0000000..a83d83c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/search_engine_list_model.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_OPTIONS_SEARCH_ENGINE_LIST_MODEL_H_
+#define CHROME_BROWSER_UI_COCOA_OPTIONS_SEARCH_ENGINE_LIST_MODEL_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+
+class TemplateURLModel;
+class SearchEngineObserver;
+
+// The model for the "default search engine" combobox in preferences. Bridges
+// between the cross-platform TemplateURLModel and Cocoa while watching for
+// changes to the cross-platform model.
+
+@interface SearchEngineListModel : NSObject {
+ @private
+  TemplateURLModel* model_;  // weak, owned by Profile
+  scoped_ptr<SearchEngineObserver> observer_;  // watches for model changes
+  scoped_nsobject<NSArray> engines_;
+}
+
+// Initialize with the given template model.
+- (id)initWithModel:(TemplateURLModel*)model;
+
+// Returns an array of NSString's corresponding to the user-visible names of the
+// search engines.
+- (NSArray*)searchEngines;
+
+// The index into |-searchEngines| of the current default search engine. If
+// there is no default search engine, the value is -1. The setter changes the
+// back-end preference.
+- (NSInteger)defaultIndex;
+- (void)setDefaultIndex:(NSInteger)index;
+// Return TRUE if the default is managed via policy.
+- (BOOL)isDefaultManaged;
+@end
+
+// Broadcast when the cross-platform model changes. This can be used to update
+// any view state that may rely on the position of items in the list.
+extern NSString* const kSearchEngineListModelChangedNotification;
+
+#endif  // CHROME_BROWSER_UI_COCOA_OPTIONS_SEARCH_ENGINE_LIST_MODEL_H_
diff --git a/chrome/browser/ui/cocoa/options/search_engine_list_model.mm b/chrome/browser/ui/cocoa/options/search_engine_list_model.mm
new file mode 100644
index 0000000..b46e571
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/search_engine_list_model.mm
@@ -0,0 +1,136 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/options/search_engine_list_model.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/template_url_model_observer.h"
+
+NSString* const kSearchEngineListModelChangedNotification =
+    @"kSearchEngineListModelChangedNotification";
+
+@interface SearchEngineListModel(Private)
+- (void)buildEngineList;
+@end
+
+// C++ bridge from TemplateURLModel to our Obj-C model. When it's told about
+// model changes, notifies us to rebuild the list.
+class SearchEngineObserver : public TemplateURLModelObserver {
+ public:
+  SearchEngineObserver(SearchEngineListModel* notify)
+      : notify_(notify) { }
+  virtual ~SearchEngineObserver() { };
+
+ private:
+  // TemplateURLModelObserver methods.
+  virtual void OnTemplateURLModelChanged() { [notify_ buildEngineList]; }
+
+  SearchEngineListModel* notify_;  // weak, owns us
+};
+
+@implementation SearchEngineListModel
+
+// The windows code allows for a NULL |model| and checks for it throughout
+// the code, though I'm not sure why. We follow suit.
+- (id)initWithModel:(TemplateURLModel*)model {
+  if ((self = [super init])) {
+    model_ = model;
+    if (model_) {
+      observer_.reset(new SearchEngineObserver(self));
+      model_->Load();
+      model_->AddObserver(observer_.get());
+      [self buildEngineList];
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if (model_)
+    model_->RemoveObserver(observer_.get());
+  [super dealloc];
+}
+
+// Returns an array of NSString's corresponding to the user-visible names of the
+// search engines.
+- (NSArray*)searchEngines {
+  return engines_.get();
+}
+
+- (void)setSearchEngines:(NSArray*)engines {
+  engines_.reset([engines retain]);
+
+  // Tell anyone who's listening that something has changed so they need to
+  // adjust the UI.
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kSearchEngineListModelChangedNotification
+                    object:nil];
+}
+
+// Walks the model and builds an array of NSStrings to display to the user.
+// Assumes there is a non-NULL model.
+- (void)buildEngineList {
+  scoped_nsobject<NSMutableArray> engines([[NSMutableArray alloc] init]);
+
+  typedef std::vector<const TemplateURL*> TemplateURLs;
+  TemplateURLs modelURLs = model_->GetTemplateURLs();
+  for (size_t i = 0; i < modelURLs.size(); ++i) {
+    if (modelURLs[i]->ShowInDefaultList())
+      [engines addObject:base::SysUTF16ToNSString(modelURLs[i]->short_name())];
+  }
+
+  [self setSearchEngines:engines.get()];
+}
+
+// The index into |-searchEngines| of the current default search engine.
+// -1 if there is no default.
+- (NSInteger)defaultIndex {
+  if (!model_) return -1;
+
+  NSInteger index = 0;
+  const TemplateURL* defaultSearchProvider = model_->GetDefaultSearchProvider();
+  if (defaultSearchProvider) {
+    typedef std::vector<const TemplateURL*> TemplateURLs;
+    TemplateURLs urls = model_->GetTemplateURLs();
+    for (std::vector<const TemplateURL*>::iterator it = urls.begin();
+         it != urls.end(); ++it) {
+      const TemplateURL* url = *it;
+      // Skip all the URLs not shown on the default list.
+      if (!url->ShowInDefaultList())
+        continue;
+      if (url->id() == defaultSearchProvider->id())
+        return index;
+      ++index;
+    }
+  }
+  return -1;
+}
+
+- (void)setDefaultIndex:(NSInteger)index {
+  if (model_) {
+    typedef std::vector<const TemplateURL*> TemplateURLs;
+    TemplateURLs urls = model_->GetTemplateURLs();
+    for (std::vector<const TemplateURL*>::iterator it = urls.begin();
+         it != urls.end(); ++it) {
+      const TemplateURL* url = *it;
+      // Skip all the URLs not shown on the default list.
+      if (!url->ShowInDefaultList())
+        continue;
+      if (0 == index) {
+        model_->SetDefaultSearchProvider(url);
+        return;
+      }
+      --index;
+    }
+    DCHECK(false);
+  }
+}
+
+// Return TRUE if the default is managed via policy.
+- (BOOL)isDefaultManaged {
+  return model_->is_default_search_managed();
+}
+@end
diff --git a/chrome/browser/ui/cocoa/options/search_engine_list_model_unittest.mm b/chrome/browser/ui/cocoa/options/search_engine_list_model_unittest.mm
new file mode 100644
index 0000000..b82f095
--- /dev/null
+++ b/chrome/browser/ui/cocoa/options/search_engine_list_model_unittest.mm
@@ -0,0 +1,153 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/options/search_engine_list_model.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+// A helper for NSNotifications. Makes a note that it's been called back.
+@interface SearchEngineListHelper : NSObject {
+ @public
+  BOOL sawNotification_;
+}
+@end
+
+@implementation SearchEngineListHelper
+- (void)entryChanged:(NSNotification*)notify {
+  sawNotification_ = YES;
+}
+@end
+
+class SearchEngineListModelTest : public PlatformTest {
+ public:
+  SearchEngineListModelTest() {
+    // Build a fake set of template urls.
+    template_model_.reset(new TemplateURLModel(helper_.profile()));
+    TemplateURL* t_url = new TemplateURL();
+    t_url->SetURL("http://www.google.com/?q={searchTerms}", 0, 0);
+    t_url->set_keyword(ASCIIToUTF16("keyword"));
+    t_url->set_short_name(ASCIIToUTF16("google"));
+    t_url->set_show_in_default_list(true);
+    template_model_->Add(t_url);
+    t_url = new TemplateURL();
+    t_url->SetURL("http://www.google2.com/?q={searchTerms}", 0, 0);
+    t_url->set_keyword(ASCIIToUTF16("keyword2"));
+    t_url->set_short_name(ASCIIToUTF16("google2"));
+    t_url->set_show_in_default_list(true);
+    template_model_->Add(t_url);
+    EXPECT_EQ(template_model_->GetTemplateURLs().size(), 2U);
+
+    model_.reset([[SearchEngineListModel alloc]
+                    initWithModel:template_model_.get()]);
+    notification_helper_.reset([[SearchEngineListHelper alloc] init]);
+    [[NSNotificationCenter defaultCenter]
+        addObserver:notification_helper_.get()
+           selector:@selector(entryChanged:)
+              name:kSearchEngineListModelChangedNotification
+            object:nil];
+   }
+  ~SearchEngineListModelTest() {
+    [[NSNotificationCenter defaultCenter]
+        removeObserver:notification_helper_.get()];
+  }
+
+  BrowserTestHelper helper_;
+  scoped_ptr<TemplateURLModel> template_model_;
+  scoped_nsobject<SearchEngineListModel> model_;
+  scoped_nsobject<SearchEngineListHelper> notification_helper_;
+};
+
+TEST_F(SearchEngineListModelTest, Init) {
+  scoped_nsobject<SearchEngineListModel> model(
+      [[SearchEngineListModel alloc] initWithModel:template_model_.get()]);
+}
+
+TEST_F(SearchEngineListModelTest, Engines) {
+  NSArray* engines = [model_ searchEngines];
+  EXPECT_EQ([engines count], 2U);
+}
+
+TEST_F(SearchEngineListModelTest, Default) {
+  EXPECT_EQ([model_ defaultIndex], -1);
+
+  [model_ setDefaultIndex:1];
+  EXPECT_EQ([model_ defaultIndex], 1);
+
+  // Add two more URLs, neither of which are shown in the default list.
+  TemplateURL* t_url = new TemplateURL();
+  t_url->SetURL("http://www.google3.com/?q={searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("keyword3"));
+  t_url->set_short_name(ASCIIToUTF16("google3 not eligible"));
+  t_url->set_show_in_default_list(false);
+  template_model_->Add(t_url);
+  t_url = new TemplateURL();
+  t_url->SetURL("http://www.google4.com/?q={searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("keyword4"));
+  t_url->set_short_name(ASCIIToUTF16("google4"));
+  t_url->set_show_in_default_list(false);
+  template_model_->Add(t_url);
+
+  // Still should only have 2 engines and not these newly added ones.
+  EXPECT_EQ([[model_ searchEngines] count], 2U);
+
+  // Since keyword3 is not in the default list, the 2nd index in the default
+  // keyword list should be keyword4. Test for http://crbug.com/21898.
+  template_model_->SetDefaultSearchProvider(t_url);
+  EXPECT_EQ([[model_ searchEngines] count], 3U);
+  EXPECT_EQ([model_ defaultIndex], 2);
+
+  NSString* defaultString = [[model_ searchEngines] objectAtIndex:2];
+  EXPECT_NSEQ(@"google4", defaultString);
+}
+
+TEST_F(SearchEngineListModelTest, DefaultChosenFromUI) {
+  EXPECT_EQ([model_ defaultIndex], -1);
+
+  [model_ setDefaultIndex:1];
+  EXPECT_EQ([model_ defaultIndex], 1);
+
+  // Add two more URLs, the first one not shown in the default list.
+  TemplateURL* t_url = new TemplateURL();
+  t_url->SetURL("http://www.google3.com/?q={searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("keyword3"));
+  t_url->set_short_name(ASCIIToUTF16("google3 not eligible"));
+  t_url->set_show_in_default_list(false);
+  template_model_->Add(t_url);
+  t_url = new TemplateURL();
+  t_url->SetURL("http://www.google4.com/?q={searchTerms}", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("keyword4"));
+  t_url->set_short_name(ASCIIToUTF16("google4"));
+  t_url->set_show_in_default_list(true);
+  template_model_->Add(t_url);
+
+  // We should have 3 engines.
+  EXPECT_EQ([[model_ searchEngines] count], 3U);
+
+  // Simulate the UI setting the default to the third entry.
+  [model_ setDefaultIndex:2];
+  EXPECT_EQ([model_ defaultIndex], 2);
+
+  // The default search provider should be google4.
+  EXPECT_EQ(template_model_->GetDefaultSearchProvider(), t_url);
+}
+
+// Make sure that when the back-end model changes that we get a notification.
+TEST_F(SearchEngineListModelTest, Notification) {
+  // Add one more item to force a notification.
+  TemplateURL* t_url = new TemplateURL();
+  t_url->SetURL("http://www.google3.com/foo/bar", 0, 0);
+  t_url->set_keyword(ASCIIToUTF16("keyword3"));
+  t_url->set_short_name(ASCIIToUTF16("google3"));
+  t_url->set_show_in_default_list(true);
+  template_model_->Add(t_url);
+
+  EXPECT_TRUE(notification_helper_.get()->sawNotification_);
+}
diff --git a/chrome/browser/ui/cocoa/page_info_bubble_controller.h b/chrome/browser/ui/cocoa/page_info_bubble_controller.h
index 10909c6..1b21215 100644
--- a/chrome/browser/ui/cocoa/page_info_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/page_info_bubble_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,11 +23,12 @@
   int certID_;
 }
 
-@property (nonatomic, assign) int certID;
+@property(nonatomic, assign) int certID;
 
 // Designated initializer. The new instance will take ownership of |model| and
 // |bridge|. There should be a 1:1 mapping of models to bridges. The
-// controller will release itself when the bubble is closed.
+// controller will release itself when the bubble is closed. |parentWindow|
+// cannot be nil.
 - (id)initWithPageInfoModel:(PageInfoModel*)model
               modelObserver:(PageInfoModel::PageInfoModelObserver*)bridge
                parentWindow:(NSWindow*)parentWindow;
diff --git a/chrome/browser/ui/cocoa/page_info_bubble_controller.mm b/chrome/browser/ui/cocoa/page_info_bubble_controller.mm
index e0a13f6..d79ef5c 100644
--- a/chrome/browser/ui/cocoa/page_info_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/page_info_bubble_controller.mm
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import "chrome/browser/ui/cocoa/page_info_bubble_controller.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/message_loop.h"
 #include "base/sys_string_conversions.h"
 #include "base/task.h"
@@ -25,6 +23,8 @@
 #include "net/base/cert_status_flags.h"
 #include "net/base/x509_certificate.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 @interface PageInfoBubbleController (Private)
 - (PageInfoModel*)model;
@@ -53,8 +53,7 @@
 // bubble's window's contentView. Drawing is flipped so that layout of the
 // sections is easier. Apple recommends flipping the coordinate origin when
 // doing a lot of text layout because it's more natural.
-@interface PageInfoContentView : NSView {
-}
+@interface PageInfoContentView : NSView
 @end
 @implementation PageInfoContentView
 - (BOOL)isFlipped {
@@ -66,19 +65,19 @@
 
 // The width of the window, in view coordinates. The height will be determined
 // by the content.
-const NSInteger kWindowWidth = 380;
+const CGFloat kWindowWidth = 380;
 
 // Spacing in between sections.
-const NSInteger kVerticalSpacing = 10;
+const CGFloat kVerticalSpacing = 10;
 
 // Padding along on the X-axis between the window frame and content.
-const NSInteger kFramePadding = 10;
+const CGFloat kFramePadding = 10;
 
 // Spacing between the optional headline and description text views.
-const NSInteger kHeadlineSpacing = 2;
+const CGFloat kHeadlineSpacing = 2;
 
 // Spacing between the image and the text.
-const NSInteger kImageSpacing = 10;
+const CGFloat kImageSpacing = 10;
 
 // Square size of the image.
 const CGFloat kImageSize = 30;
@@ -135,6 +134,8 @@
 
   // Factory that vends RunnableMethod tasks for scheduling layout.
   ScopedRunnableMethodFactory<PageInfoModelBubbleBridge> task_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(PageInfoModelBubbleBridge);
 };
 
 }  // namespace
@@ -167,6 +168,8 @@
 - (id)initWithPageInfoModel:(PageInfoModel*)model
               modelObserver:(PageInfoModel::PageInfoModelObserver*)bridge
                parentWindow:(NSWindow*)parentWindow {
+  DCHECK(parentWindow);
+
   // Use an arbitrary height because it will be changed by the bridge.
   NSRect contentRect = NSMakeRect(0, 0, kWindowWidth, 0);
   // Create an empty window into which content is placed.
@@ -394,8 +397,8 @@
 - (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info
                  toSubviews:(NSMutableArray*)subviews
                    atOffset:(CGFloat)offset {
-  NSRect frame = NSMakeRect(kFramePadding, offset, kImageSize,
-      kImageSize);
+  NSRect frame =
+      NSMakeRect(kFramePadding, offset, kImageSize, kImageSize);
   scoped_nsobject<NSImageView> imageView(
       [[NSImageView alloc] initWithFrame:frame]);
   [imageView setImageFrameStyle:NSImageFrameNone];
diff --git a/chrome/browser/ui/cocoa/page_info_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/page_info_bubble_controller_unittest.mm
index 50281fe..cc640d0 100644
--- a/chrome/browser/ui/cocoa/page_info_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/page_info_bubble_controller_unittest.mm
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/scoped_nsobject.h"
 #include "base/string_util.h"
 #include "base/string_number_conversions.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/ui/cocoa/browser_test_helper.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -186,7 +186,6 @@
       description,
       PageInfoModel::SECTION_INFO_CONNECTION);
 
-
   CreateBubble();
   [controller_ setCertID:1];
   [controller_ performLayout];
diff --git a/chrome/browser/ui/cocoa/preferences_window_controller.h b/chrome/browser/ui/cocoa/preferences_window_controller.h
deleted file mode 100644
index eed4af6..0000000
--- a/chrome/browser/ui/cocoa/preferences_window_controller.h
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_ptr.h"
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/prefs/pref_set_observer.h"
-#include "chrome/browser/prefs/pref_change_registrar.h"
-#include "chrome/browser/ui/options/options_window.h"
-
-namespace PreferencesWindowControllerInternal {
-class PrefObserverBridge;
-class ManagedPrefsBannerState;
-}
-
-@class CustomHomePagesModel;
-@class FontLanguageSettingsController;
-class PrefService;
-class Profile;
-class ProfileSyncService;
-@class SearchEngineListModel;
-@class VerticalGradientView;
-@class WindowSizeAutosaver;
-
-// A window controller that handles the preferences window. The bulk of the
-// work is handled via Cocoa Bindings and getter/setter methods that wrap
-// cross-platform PrefMember objects. When prefs change in the back-end
-// (that is, outside of this UI), our observer receives a notification and can
-// tickle the KVO to update the UI so we are always in sync. The bindings are
-// specified in the nib file. Preferences are persisted into the back-end
-// as they are changed in the UI, and are thus immediately available even while
-// the window is still open. When the window closes, a notification is sent
-// via the system NotificationCenter. This can be used as a signal to
-// release this controller, as it's likely the client wants to enforce there
-// only being one (we don't do that internally as it makes it very difficult
-// to unit test).
-@interface PreferencesWindowController : NSWindowController {
- @private
-  Profile* profile_;  // weak ref
-  OptionsPage initialPage_;
-  PrefService* prefs_;  // weak ref - Obtained from profile_ for convenience.
-  // weak ref - Also obtained from profile_ for convenience.  May be NULL.
-  ProfileSyncService* syncService_;
-  scoped_ptr<PreferencesWindowControllerInternal::PrefObserverBridge>
-      observer_;  // Watches for pref changes.
-  PrefChangeRegistrar registrar_;  // Manages pref change observer registration.
-  scoped_nsobject<WindowSizeAutosaver> sizeSaver_;
-  NSView* currentPrefsView_;  // weak ref - current prefs page view.
-  scoped_ptr<PreferencesWindowControllerInternal::ManagedPrefsBannerState>
-      bannerState_;
-  BOOL managedPrefsBannerVisible_;
-
-  IBOutlet NSToolbar* toolbar_;
-  IBOutlet VerticalGradientView* managedPrefsBannerView_;
-  IBOutlet NSImageView* managedPrefsBannerWarningImage_;
-
-  // The views we'll rotate through
-  IBOutlet NSView* basicsView_;
-  IBOutlet NSView* personalStuffView_;
-  IBOutlet NSView* underTheHoodView_;
-  // The last page the user was on when they opened the Options window.
-  IntegerPrefMember lastSelectedPage_;
-
-  // The groups of the Basics view for layout fixup.
-  IBOutlet NSArray* basicsGroupStartup_;
-  IBOutlet NSArray* basicsGroupHomePage_;
-  IBOutlet NSArray* basicsGroupToolbar_;
-  IBOutlet NSArray* basicsGroupSearchEngine_;
-  IBOutlet NSArray* basicsGroupDefaultBrowser_;
-
-  // The groups of the Personal Stuff view for layout fixup.
-  IBOutlet NSArray* personalStuffGroupSync_;
-  IBOutlet NSArray* personalStuffGroupPasswords_;
-  IBOutlet NSArray* personalStuffGroupAutofill_;
-  IBOutlet NSArray* personalStuffGroupBrowserData_;
-  IBOutlet NSArray* personalStuffGroupThemes_;
-
-  // Having two animations around is bad (they fight), so just use one.
-  scoped_nsobject<NSViewAnimation> animation_;
-
-  IBOutlet NSArrayController* customPagesArrayController_;
-
-  // Basics panel
-  IntegerPrefMember restoreOnStartup_;
-  scoped_nsobject<CustomHomePagesModel> customPagesSource_;
-  BooleanPrefMember newTabPageIsHomePage_;
-  StringPrefMember homepage_;
-  BooleanPrefMember showHomeButton_;
-  BooleanPrefMember instantEnabled_;
-  IBOutlet NSButton* instantCheckbox_;
-  scoped_nsobject<SearchEngineListModel> searchEngineModel_;
-  // Used when creating a new home page url to make the new cell editable.
-  BOOL pendingSelectForEdit_;
-  BOOL restoreButtonsEnabled_;
-  BOOL restoreURLsEnabled_;
-  BOOL showHomeButtonEnabled_;
-  BOOL defaultSearchEngineEnabled_;
-
-  // User Data panel
-  BooleanPrefMember askSavePasswords_;
-  BooleanPrefMember autoFillEnabled_;
-  IBOutlet NSButton* autoFillSettingsButton_;
-  IBOutlet NSButton* syncButton_;
-  IBOutlet NSButton* syncCustomizeButton_;
-  IBOutlet NSTextField* syncStatus_;
-  IBOutlet NSButton* syncLink_;
-  IBOutlet NSButton* privacyDashboardLink_;
-  scoped_nsobject<NSColor> syncStatusNoErrorBackgroundColor_;
-  scoped_nsobject<NSColor> syncLinkNoErrorBackgroundColor_;
-  scoped_nsobject<NSColor> syncErrorBackgroundColor_;
-  BOOL passwordManagerChoiceEnabled_;
-  BOOL passwordManagerButtonEnabled_;
-  BOOL autoFillSettingsButtonEnabled_;
-
-  // Under the hood panel
-  IBOutlet NSView* underTheHoodContentView_;
-  IBOutlet NSScrollView* underTheHoodScroller_;
-  IBOutlet NSButton* contentSettingsButton_;
-  IBOutlet NSButton* clearDataButton_;
-  BooleanPrefMember alternateErrorPages_;
-  BooleanPrefMember useSuggest_;
-  BooleanPrefMember dnsPrefetch_;
-  BooleanPrefMember safeBrowsing_;
-  BooleanPrefMember metricsReporting_;
-  IBOutlet NSPathControl* downloadLocationControl_;
-  IBOutlet NSButton* downloadLocationButton_;
-  StringPrefMember defaultDownloadLocation_;
-  BooleanPrefMember askForSaveLocation_;
-  IBOutlet NSButton* resetFileHandlersButton_;
-  StringPrefMember autoOpenFiles_;
-  BooleanPrefMember translateEnabled_;
-  BooleanPrefMember tabsToLinks_;
-  FontLanguageSettingsController* fontLanguageSettings_;
-  StringPrefMember currentTheme_;
-  IBOutlet NSButton* enableLoggingCheckbox_;
-  scoped_ptr<PrefSetObserver> proxyPrefs_;
-  BOOL showAlternateErrorPagesEnabled_;
-  BOOL useSuggestEnabled_;
-  BOOL dnsPrefetchEnabled_;
-  BOOL safeBrowsingEnabled_;
-  BOOL metricsReportingEnabled_;
-  BOOL proxiesConfigureButtonEnabled_;
-}
-
-// Designated initializer. |profile| should not be NULL.
-- (id)initWithProfile:(Profile*)profile initialPage:(OptionsPage)initialPage;
-
-// Show the preferences window.
-- (void)showPreferences:(id)sender;
-
-// Switch to the given preference page.
-- (void)switchToPage:(OptionsPage)page animate:(BOOL)animate;
-
-// Enables or disables the restoreOnStartup elements
-- (void) setEnabledStateOfRestoreOnStartup;
-
-// IBAction methods for responding to user actions.
-
-// Basics panel
-- (IBAction)addHomepage:(id)sender;
-- (IBAction)removeSelectedHomepages:(id)sender;
-- (IBAction)useCurrentPagesAsHomepage:(id)sender;
-- (IBAction)manageSearchEngines:(id)sender;
-- (IBAction)toggleInstant:(id)sender;
-- (IBAction)learnMoreAboutInstant:(id)sender;
-- (IBAction)makeDefaultBrowser:(id)sender;
-
-// User Data panel
-- (IBAction)doSyncAction:(id)sender;
-- (IBAction)doSyncCustomize:(id)sender;
-- (IBAction)doSyncReauthentication:(id)sender;
-- (IBAction)showPrivacyDashboard:(id)sender;
-- (IBAction)showSavedPasswords:(id)sender;
-- (IBAction)showAutoFillSettings:(id)sender;
-- (IBAction)importData:(id)sender;
-- (IBAction)resetThemeToDefault:(id)sender;
-- (IBAction)themesGallery:(id)sender;
-
-// Under the hood
-- (IBAction)showContentSettings:(id)sender;
-- (IBAction)clearData:(id)sender;
-- (IBAction)privacyLearnMore:(id)sender;
-- (IBAction)browseDownloadLocation:(id)sender;
-- (IBAction)resetAutoOpenFiles:(id)sender;
-- (IBAction)changeFontAndLanguageSettings:(id)sender;
-- (IBAction)openProxyPreferences:(id)sender;
-- (IBAction)showCertificates:(id)sender;
-- (IBAction)resetToDefaults:(id)sender;
-
-// When a toolbar button is clicked
-- (IBAction)toolbarButtonSelected:(id)sender;
-
-// Usable from cocoa bindings to hook up the custom home pages table.
-@property (nonatomic, readonly) CustomHomePagesModel* customPagesSource;
-
-// Properties for the enabled state of various UI elements. Keep these ordered
-// by occurrence on the dialog.
-@property (nonatomic) BOOL restoreButtonsEnabled;
-@property (nonatomic) BOOL restoreURLsEnabled;
-@property (nonatomic) BOOL showHomeButtonEnabled;
-@property (nonatomic) BOOL defaultSearchEngineEnabled;
-@property (nonatomic) BOOL passwordManagerChoiceEnabled;
-@property (nonatomic) BOOL passwordManagerButtonEnabled;
-@property (nonatomic) BOOL autoFillSettingsButtonEnabled;
-@property (nonatomic) BOOL showAlternateErrorPagesEnabled;
-@property (nonatomic) BOOL useSuggestEnabled;
-@property (nonatomic) BOOL dnsPrefetchEnabled;
-@property (nonatomic) BOOL safeBrowsingEnabled;
-@property (nonatomic) BOOL metricsReportingEnabled;
-@property (nonatomic) BOOL proxiesConfigureButtonEnabled;
-@end
-
-@interface PreferencesWindowController(Testing)
-
-- (IntegerPrefMember*)lastSelectedPage;
-- (NSToolbar*)toolbar;
-- (NSView*)basicsView;
-- (NSView*)personalStuffView;
-- (NSView*)underTheHoodView;
-
-// Converts the given OptionsPage value (which may be OPTIONS_PAGE_DEFAULT)
-// into a concrete OptionsPage value.
-- (OptionsPage)normalizePage:(OptionsPage)page;
-
-// Returns the toolbar item corresponding to the given page.  Should be
-// called only after awakeFromNib is.
-- (NSToolbarItem*)getToolbarItemForPage:(OptionsPage)page;
-
-// Returns the (normalized) page corresponding to the given toolbar item.
-// Should be called only after awakeFromNib is.
-- (OptionsPage)getPageForToolbarItem:(NSToolbarItem*)toolbarItem;
-
-// Returns the view corresponding to the given page.  Should be called
-// only after awakeFromNib is.
-- (NSView*)getPrefsViewForPage:(OptionsPage)page;
-
-@end
diff --git a/chrome/browser/ui/cocoa/preferences_window_controller.mm b/chrome/browser/ui/cocoa/preferences_window_controller.mm
deleted file mode 100644
index 950ec7b..0000000
--- a/chrome/browser/ui/cocoa/preferences_window_controller.mm
+++ /dev/null
@@ -1,2172 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/preferences_window_controller.h"
-
-#include <algorithm>
-
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_aedesc.h"
-#include "base/string16.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/autofill/autofill_dialog.h"
-#include "chrome/browser/autofill/autofill_type.h"
-#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/download/download_prefs.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/instant/instant_confirm_dialog.h"
-#include "chrome/browser/instant/instant_controller.h"
-#include "chrome/browser/metrics/metrics_service.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/policy/managed_prefs_banner_base.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/browser/shell_integration.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#import "chrome/browser/ui/cocoa/clear_browsing_data_controller.h"
-#import "chrome/browser/ui/cocoa/content_settings_dialog_controller.h"
-#import "chrome/browser/ui/cocoa/custom_home_pages_model.h"
-#import "chrome/browser/ui/cocoa/font_language_settings_controller.h"
-#import "chrome/browser/ui/cocoa/import_settings_dialog.h"
-#import "chrome/browser/ui/cocoa/keyword_editor_cocoa_controller.h"
-#import "chrome/browser/ui/cocoa/l10n_util.h"
-#import "chrome/browser/ui/cocoa/search_engine_list_model.h"
-#import "chrome/browser/ui/cocoa/vertical_gradient_view.h"
-#import "chrome/browser/ui/cocoa/window_size_autosaver.h"
-#include "chrome/browser/ui/options/options_util.h"
-#include "chrome/browser/ui/options/options_window.h"
-#include "chrome/browser/ui/options/show_options_url.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-namespace {
-
-// Colors for the managed preferences warning banner.
-static const double kBannerGradientColorTop[3] =
-    {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0};
-static const double kBannerGradientColorBottom[3] =
-    {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0};
-static const double kBannerStrokeColor = 135.0 / 255.0;
-
-// Tag id for retrieval via viewWithTag in NSView (from IB).
-static const uint32 kBasicsStartupPageTableTag = 1000;
-
-bool IsNewTabUIURLString(const GURL& url) {
-  return url == GURL(chrome::kChromeUINewTabURL);
-}
-
-// Helper that sizes two buttons to fit in a row keeping their spacing, returns
-// the total horizontal size change.
-CGFloat SizeToFitButtonPair(NSButton* leftButton, NSButton* rightButton) {
-  CGFloat widthShift = 0.0;
-
-  NSSize delta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:leftButton];
-  DCHECK_EQ(delta.height, 0.0) << "Height changes unsupported";
-  widthShift += delta.width;
-
-  if (widthShift != 0.0) {
-    NSPoint origin = [rightButton frame].origin;
-    origin.x += widthShift;
-    [rightButton setFrameOrigin:origin];
-  }
-  delta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:rightButton];
-  DCHECK_EQ(delta.height, 0.0) << "Height changes unsupported";
-  widthShift += delta.width;
-
-  return widthShift;
-}
-
-// The different behaviors for the "pref group" auto sizing.
-enum AutoSizeGroupBehavior {
-  kAutoSizeGroupBehaviorVerticalToFit,
-  kAutoSizeGroupBehaviorVerticalFirstToFit,
-  kAutoSizeGroupBehaviorHorizontalToFit,
-  kAutoSizeGroupBehaviorHorizontalFirstGrows,
-  kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit
-};
-
-// Helper to tweak the layout of the "pref groups" and also ripple any height
-// changes from one group to the next groups' origins.
-// |views| is an ordered list of views with first being the label for the
-// group and the rest being top down or left to right ordering of the views.
-// The label is assumed to already be the same height as all the views it is
-// next too.
-CGFloat AutoSizeGroup(NSArray* views, AutoSizeGroupBehavior behavior,
-                      CGFloat verticalShift) {
-  DCHECK_GE([views count], 2U) << "Should be at least a label and a control";
-  NSTextField* label = [views objectAtIndex:0];
-  DCHECK([label isKindOfClass:[NSTextField class]])
-      << "First view should be the label for the group";
-
-  // Auto size the label to see if we need more vertical space for its localized
-  // string.
-  CGFloat labelHeightChange =
-      [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:label];
-
-  CGFloat localVerticalShift = 0.0;
-  switch (behavior) {
-    case kAutoSizeGroupBehaviorVerticalToFit: {
-      // Walk bottom up doing the sizing and moves.
-      for (NSUInteger index = [views count] - 1; index > 0; --index) {
-        NSView* view = [views objectAtIndex:index];
-        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-        if (localVerticalShift) {
-          NSPoint origin = [view frame].origin;
-          origin.y += localVerticalShift;
-          [view setFrameOrigin:origin];
-        }
-        localVerticalShift += delta.height;
-      }
-      break;
-    }
-    case kAutoSizeGroupBehaviorVerticalFirstToFit: {
-      // Just size the top one.
-      NSView* view = [views objectAtIndex:1];
-      NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-      DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-      localVerticalShift += delta.height;
-      break;
-    }
-    case kAutoSizeGroupBehaviorHorizontalToFit: {
-      // Walk left to right doing the sizing and moves.
-      // NOTE: Don't worry about vertical, assume it always fits.
-      CGFloat horizontalShift = 0.0;
-      NSUInteger count = [views count];
-      for (NSUInteger index = 1; index < count; ++index) {
-        NSView* view = [views objectAtIndex:index];
-        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-        if (horizontalShift) {
-          NSPoint origin = [view frame].origin;
-          origin.x += horizontalShift;
-          [view setFrameOrigin:origin];
-        }
-        horizontalShift += delta.width;
-      }
-      break;
-    }
-    case kAutoSizeGroupBehaviorHorizontalFirstGrows: {
-      // Walk right to left doing the sizing and moves, then apply the space
-      // collected into the first.
-      // NOTE: Don't worry about vertical, assume it always all fits.
-      CGFloat horizontalShift = 0.0;
-      for (NSUInteger index = [views count] - 1; index > 1; --index) {
-        NSView* view = [views objectAtIndex:index];
-        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-        horizontalShift -= delta.width;
-        NSPoint origin = [view frame].origin;
-        origin.x += horizontalShift;
-        [view setFrameOrigin:origin];
-      }
-      if (horizontalShift) {
-        NSView* view = [views objectAtIndex:1];
-        NSSize delta = NSMakeSize(horizontalShift, 0.0);
-        [GTMUILocalizerAndLayoutTweaker
-            resizeViewWithoutAutoResizingSubViews:view
-                                            delta:delta];
-      }
-      break;
-    }
-    case kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit: {
-      // Start out like kAutoSizeGroupBehaviorVerticalToFit but don't do
-      // the first two.  Then handle the two as a row, but apply any
-      // vertical shift.
-      // All but the first two (in the row); walk bottom up.
-      for (NSUInteger index = [views count] - 1; index > 2; --index) {
-        NSView* view = [views objectAtIndex:index];
-        NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-        DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-        if (localVerticalShift) {
-          NSPoint origin = [view frame].origin;
-          origin.y += localVerticalShift;
-          [view setFrameOrigin:origin];
-        }
-        localVerticalShift += delta.height;
-      }
-      // Deal with the two for the horizontal row.  Size the second one.
-      CGFloat horizontalShift = 0.0;
-      NSView* view = [views objectAtIndex:2];
-      NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-      DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-      horizontalShift -= delta.width;
-      NSPoint origin = [view frame].origin;
-      origin.x += horizontalShift;
-      if (localVerticalShift) {
-        origin.y += localVerticalShift;
-      }
-      [view setFrameOrigin:origin];
-      // Now expand the first item in the row to consume the space opened up.
-      view = [views objectAtIndex:1];
-      if (horizontalShift) {
-        NSSize delta = NSMakeSize(horizontalShift, 0.0);
-        [GTMUILocalizerAndLayoutTweaker
-         resizeViewWithoutAutoResizingSubViews:view
-                                         delta:delta];
-      }
-      // And move it up by any amount needed from the previous items.
-      if (localVerticalShift) {
-        NSPoint origin = [view frame].origin;
-        origin.y += localVerticalShift;
-        [view setFrameOrigin:origin];
-      }
-      break;
-    }
-    default:
-      NOTREACHED();
-      break;
-  }
-
-  // If the label grew more then the views, the other views get an extra shift.
-  // Otherwise, move the label to its top is aligned with the other views.
-  CGFloat nonLabelShift = 0.0;
-  if (labelHeightChange > localVerticalShift) {
-    // Since the lable is taller, centering the other views looks best, just
-    // shift the views by 1/2 of the size difference.
-    nonLabelShift = (labelHeightChange - localVerticalShift) / 2.0;
-  } else {
-    NSPoint origin = [label frame].origin;
-    origin.y += localVerticalShift - labelHeightChange;
-    [label setFrameOrigin:origin];
-  }
-
-  // Apply the input shift requested along with any the shift from label being
-  // taller then the rest of the group.
-  for (NSView* view in views) {
-    NSPoint origin = [view frame].origin;
-    origin.y += verticalShift;
-    if (view != label) {
-      origin.y += nonLabelShift;
-    }
-    [view setFrameOrigin:origin];
-  }
-
-  // Return how much the group grew.
-  return localVerticalShift + nonLabelShift;
-}
-
-// Helper to remove a view and move everything above it down to take over the
-// space.
-void RemoveViewFromView(NSView* view, NSView* toRemove) {
-  // Sort bottom up so we can spin over what is above it.
-  NSArray* views =
-      [[view subviews] sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
-                                        context:NULL];
-
-  // Find where |toRemove| was.
-  NSUInteger index = [views indexOfObject:toRemove];
-  DCHECK_NE(index, NSNotFound);
-  NSUInteger count = [views count];
-  CGFloat shrinkHeight = 0;
-  if (index < (count - 1)) {
-    // If we're not the topmost control, the amount to shift is the bottom of
-    // |toRemove| to the bottom of the view above it.
-    CGFloat shiftDown =
-        NSMinY([[views objectAtIndex:index + 1] frame]) -
-        NSMinY([toRemove frame]);
-
-    // Now cycle over the views above it moving them down.
-    for (++index; index < count; ++index) {
-      NSView* view = [views objectAtIndex:index];
-      NSPoint origin = [view frame].origin;
-      origin.y -= shiftDown;
-      [view setFrameOrigin:origin];
-    }
-
-    shrinkHeight = shiftDown;
-  } else if (index > 0) {
-    // If we're the topmost control, there's nothing to shift but we want to
-    // shrink until the top edge of the second-topmost control, unless it is
-    // actually higher than the topmost control (since we're sorting by the
-    // bottom edge).
-    shrinkHeight = std::max(0.f,
-        NSMaxY([toRemove frame]) -
-        NSMaxY([[views objectAtIndex:index - 1] frame]));
-  }
-  // If we only have one control, don't do any resizing (for now).
-
-  // Remove |toRemove|.
-  [toRemove removeFromSuperview];
-
-  [GTMUILocalizerAndLayoutTweaker
-      resizeViewWithoutAutoResizingSubViews:view
-                                      delta:NSMakeSize(0, -shrinkHeight)];
-}
-
-// Simply removes all the views in |toRemove|.
-void RemoveGroupFromView(NSView* view, NSArray* toRemove) {
-  for (NSView* viewToRemove in toRemove) {
-    RemoveViewFromView(view, viewToRemove);
-  }
-}
-
-// Helper to tweak the layout of the "Under the Hood" content by autosizing all
-// the views and moving things up vertically.  Special case the two controls for
-// download location as they are horizontal, and should fill the row. Special
-// case "Content Settings" and "Clear browsing data" as they are horizontal as
-// well.
-CGFloat AutoSizeUnderTheHoodContent(NSView* view,
-                                    NSPathControl* downloadLocationControl,
-                                    NSButton* downloadLocationButton) {
-  CGFloat verticalShift = 0.0;
-
-  // Loop bottom up through the views sizing and shifting.
-  NSArray* views =
-      [[view subviews] sortedArrayUsingFunction:cocoa_l10n_util::CompareFrameY
-                                        context:NULL];
-  for (NSView* view in views) {
-    NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view);
-    DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height";
-    if (verticalShift) {
-      NSPoint origin = [view frame].origin;
-      origin.y += verticalShift;
-      [view setFrameOrigin:origin];
-    }
-    verticalShift += delta.height;
-
-    // The Download Location controls go in a row with the button aligned to the
-    // right edge and the path control using all the rest of the space.
-    if (view == downloadLocationButton) {
-      NSPoint origin = [downloadLocationButton frame].origin;
-      origin.x -= delta.width;
-      [downloadLocationButton setFrameOrigin:origin];
-      NSSize controlSize = [downloadLocationControl frame].size;
-      controlSize.width -= delta.width;
-      [downloadLocationControl setFrameSize:controlSize];
-    }
-  }
-
-  return verticalShift;
-}
-
-}  // namespace
-
-//-------------------------------------------------------------------------
-
-@interface PreferencesWindowController(Private)
-// Callback when preferences are changed. |prefName| is the name of the
-// pref that has changed.
-- (void)prefChanged:(std::string*)prefName;
-// Callback when sync state has changed.  syncService_ needs to be
-// queried to find out what happened.
-- (void)syncStateChanged;
-// Record the user performed a certain action and save the preferences.
-- (void)recordUserAction:(const UserMetricsAction&) action;
-- (void)registerPrefObservers;
-- (void)configureInstant;
-
-// KVC setter methods.
-- (void)setNewTabPageIsHomePageIndex:(NSInteger)val;
-- (void)setHomepageURL:(NSString*)urlString;
-- (void)setRestoreOnStartupIndex:(NSInteger)type;
-- (void)setShowHomeButton:(BOOL)value;
-- (void)setPasswordManagerEnabledIndex:(NSInteger)value;
-- (void)setIsUsingDefaultTheme:(BOOL)value;
-- (void)setShowAlternateErrorPages:(BOOL)value;
-- (void)setUseSuggest:(BOOL)value;
-- (void)setDnsPrefetch:(BOOL)value;
-- (void)setSafeBrowsing:(BOOL)value;
-- (void)setMetricsReporting:(BOOL)value;
-- (void)setAskForSaveLocation:(BOOL)value;
-- (void)setFileHandlerUIEnabled:(BOOL)value;
-- (void)setTranslateEnabled:(BOOL)value;
-- (void)setTabsToLinks:(BOOL)value;
-- (void)displayPreferenceViewForPage:(OptionsPage)page
-                             animate:(BOOL)animate;
-- (void)resetSubViews;
-- (void)initBannerStateForPage:(OptionsPage)page;
-
-// KVC getter methods.
-- (BOOL)fileHandlerUIEnabled;
-@end
-
-namespace PreferencesWindowControllerInternal {
-
-// A C++ class registered for changes in preferences. Bridges the
-// notification back to the PWC.
-class PrefObserverBridge : public NotificationObserver,
-                           public ProfileSyncServiceObserver {
- public:
-  PrefObserverBridge(PreferencesWindowController* controller)
-      : controller_(controller) {}
-
-  virtual ~PrefObserverBridge() {}
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    if (type == NotificationType::PREF_CHANGED)
-      [controller_ prefChanged:Details<std::string>(details).ptr()];
-  }
-
-  // Overridden from ProfileSyncServiceObserver.
-  virtual void OnStateChanged() {
-    [controller_ syncStateChanged];
-  }
-
- private:
-  PreferencesWindowController* controller_;  // weak, owns us
-};
-
-// Tracks state for a managed prefs banner and triggers UI updates through the
-// PreferencesWindowController as appropriate.
-class ManagedPrefsBannerState : public policy::ManagedPrefsBannerBase {
- public:
-  virtual ~ManagedPrefsBannerState() { }
-
-  explicit ManagedPrefsBannerState(PreferencesWindowController* controller,
-                                   OptionsPage page,
-                                   PrefService* local_state,
-                                   PrefService* prefs)
-    : policy::ManagedPrefsBannerBase(local_state, prefs, page),
-        controller_(controller),
-        page_(page) { }
-
-  BOOL IsVisible() {
-    return DetermineVisibility();
-  }
-
- protected:
-  // Overridden from ManagedPrefsBannerBase.
-  virtual void OnUpdateVisibility() {
-    [controller_ switchToPage:page_ animate:YES];
-  }
-
- private:
-  PreferencesWindowController* controller_;  // weak, owns us
-  OptionsPage page_;  // current options page
-};
-
-}  // namespace PreferencesWindowControllerInternal
-
-@implementation PreferencesWindowController
-
-@synthesize restoreButtonsEnabled = restoreButtonsEnabled_;
-@synthesize restoreURLsEnabled = restoreURLsEnabled_;
-@synthesize showHomeButtonEnabled = showHomeButtonEnabled_;
-@synthesize defaultSearchEngineEnabled = defaultSearchEngineEnabled_;
-@synthesize passwordManagerChoiceEnabled = passwordManagerChoiceEnabled_;
-@synthesize passwordManagerButtonEnabled = passwordManagerButtonEnabled_;
-@synthesize autoFillSettingsButtonEnabled = autoFillSettingsButtonEnabled_;
-@synthesize showAlternateErrorPagesEnabled = showAlternateErrorPagesEnabled_;
-@synthesize useSuggestEnabled = useSuggestEnabled_;
-@synthesize dnsPrefetchEnabled = dnsPrefetchEnabled_;
-@synthesize safeBrowsingEnabled = safeBrowsingEnabled_;
-@synthesize metricsReportingEnabled = metricsReportingEnabled_;
-@synthesize proxiesConfigureButtonEnabled = proxiesConfigureButtonEnabled_;
-
-- (id)initWithProfile:(Profile*)profile initialPage:(OptionsPage)initialPage {
-  DCHECK(profile);
-  // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we
-  // can override it in a unit test.
-  NSString* nibPath = [base::mac::MainAppBundle()
-                        pathForResource:@"Preferences"
-                                 ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
-    profile_ = profile->GetOriginalProfile();
-    initialPage_ = initialPage;
-    prefs_ = profile->GetPrefs();
-    DCHECK(prefs_);
-    observer_.reset(
-        new PreferencesWindowControllerInternal::PrefObserverBridge(self));
-
-    // Set up the model for the custom home page table. The KVO observation
-    // tells us when the number of items in the array changes. The normal
-    // observation tells us when one of the URLs of an item changes.
-    customPagesSource_.reset([[CustomHomePagesModel alloc]
-                                initWithProfile:profile_]);
-    const SessionStartupPref startupPref =
-        SessionStartupPref::GetStartupPref(prefs_);
-    [customPagesSource_ setURLs:startupPref.urls];
-
-    // Set up the model for the default search popup. Register for notifications
-    // about when the model changes so we can update the selection in the view.
-    searchEngineModel_.reset(
-        [[SearchEngineListModel alloc]
-            initWithModel:profile->GetTemplateURLModel()]);
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(searchEngineModelChanged:)
-               name:kSearchEngineListModelChangedNotification
-             object:searchEngineModel_.get()];
-
-    // This needs to be done before awakeFromNib: because the bindings set up
-    // in the nib rely on it.
-    [self registerPrefObservers];
-
-    // Use one animation so we can stop it if the user clicks quickly, and
-    // start the new animation.
-    animation_.reset([[NSViewAnimation alloc] init]);
-    // Make this the delegate so it can remove the old view at the end of the
-    // animation (once it is faded out).
-    [animation_ setDelegate:self];
-    [animation_ setAnimationBlockingMode:NSAnimationNonblocking];
-
-    // TODO(akalin): handle incognito profiles?  The windows version of this
-    // (in chrome/browser/views/options/content_page_view.cc) just does what
-    // we do below.
-    syncService_ = profile_->GetProfileSyncService();
-
-    // TODO(akalin): This color is taken from kSyncLabelErrorBgColor in
-    // content_page_view.cc.  Either decomp that color out into a
-    // function/variable that is referenced by both this file and
-    // content_page_view.cc, or maybe pick a more suitable color.
-    syncErrorBackgroundColor_.reset(
-        [[NSColor colorWithDeviceRed:0xff/255.0
-                               green:0x9a/255.0
-                                blue:0x9a/255.0
-                               alpha:1.0] retain]);
-
-    // Disable the |autoFillSettingsButton_| if we have no
-    // |personalDataManager|.
-    PersonalDataManager* personalDataManager =
-        profile_->GetPersonalDataManager();
-    [autoFillSettingsButton_ setHidden:(personalDataManager == NULL)];
-    bool autofill_disabled_by_policy =
-        autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue();
-    [self setAutoFillSettingsButtonEnabled:!autofill_disabled_by_policy];
-    [self setPasswordManagerChoiceEnabled:!askSavePasswords_.IsManaged()];
-    [self setPasswordManagerButtonEnabled:
-        !askSavePasswords_.IsManaged() || askSavePasswords_.GetValue()];
-
-    // Initialize the enabled state of the elements on the general tab.
-    [self setShowHomeButtonEnabled:!showHomeButton_.IsManaged()];
-    [self setEnabledStateOfRestoreOnStartup];
-    [self setDefaultSearchEngineEnabled:![searchEngineModel_ isDefaultManaged]];
-
-    // Initialize UI state for the advanced page.
-    [self setShowAlternateErrorPagesEnabled:!alternateErrorPages_.IsManaged()];
-    [self setUseSuggestEnabled:!useSuggest_.IsManaged()];
-    [self setDnsPrefetchEnabled:!dnsPrefetch_.IsManaged()];
-    [self setSafeBrowsingEnabled:!safeBrowsing_.IsManaged()];
-    [self setMetricsReportingEnabled:!metricsReporting_.IsManaged()];
-    proxyPrefs_.reset(
-        PrefSetObserver::CreateProxyPrefSetObserver(prefs_, observer_.get()));
-    [self setProxiesConfigureButtonEnabled:!proxyPrefs_->IsManaged()];
-  }
-  return self;
-}
-
-- (void)awakeFromNib {
-
-  // Validate some assumptions in debug builds.
-
-  // "Basics", "Personal Stuff", and "Under the Hood" views should be the same
-  // width.  They should be the same width so they are laid out to look as good
-  // as possible at that width with controls just having to wrap if their text
-  // is too long.
-  DCHECK_EQ(NSWidth([basicsView_ frame]), NSWidth([personalStuffView_ frame]))
-      << "Basics and Personal Stuff should be the same widths";
-  DCHECK_EQ(NSWidth([basicsView_ frame]), NSWidth([underTheHoodView_ frame]))
-      << "Basics and Under the Hood should be the same widths";
-  // "Under the Hood" content should always be skinnier than the scroller it
-  // goes into (we resize it).
-  DCHECK_LE(NSWidth([underTheHoodContentView_ frame]),
-            [underTheHoodScroller_ contentSize].width)
-      << "The Under the Hood content should be narrower than the content "
-         "of the scroller it goes into";
-
-#if !defined(GOOGLE_CHROME_BUILD)
-  // "Enable logging" (breakpad and stats) is only in Google Chrome builds,
-  // remove the checkbox and slide everything above it down.
-  RemoveViewFromView(underTheHoodContentView_, enableLoggingCheckbox_);
-#endif  // !defined(GOOGLE_CHROME_BUILD)
-
-  // There are four problem children within the groups:
-  //   Basics - Default Browser
-  //   Personal Stuff - Sync
-  //   Personal Stuff - Themes
-  //   Personal Stuff - Browser Data
-  // These four have buttons that with some localizations are wider then the
-  // view.  So the four get manually laid out before doing the general work so
-  // the views/window can be made wide enough to fit them.  The layout in the
-  // general pass is a noop for these buttons (since they are already sized).
-
-  // Size the default browser button.
-  const NSUInteger kDefaultBrowserGroupCount = 3;
-  const NSUInteger kDefaultBrowserButtonIndex = 1;
-  DCHECK_EQ([basicsGroupDefaultBrowser_ count], kDefaultBrowserGroupCount)
-      << "Expected only two items in Default Browser group";
-  NSButton* defaultBrowserButton =
-      [basicsGroupDefaultBrowser_ objectAtIndex:kDefaultBrowserButtonIndex];
-  NSSize defaultBrowserChange =
-      [GTMUILocalizerAndLayoutTweaker sizeToFitView:defaultBrowserButton];
-  DCHECK_EQ(defaultBrowserChange.height, 0.0)
-      << "Button should have been right height in nib";
-
-  [self configureInstant];
-
-  // Size the sync row.
-  CGFloat syncRowChange = SizeToFitButtonPair(syncButton_,
-                                              syncCustomizeButton_);
-
-  // Size the themes row.
-  const NSUInteger kThemeGroupCount = 3;
-  const NSUInteger kThemeResetButtonIndex = 1;
-  const NSUInteger kThemeThemesButtonIndex = 2;
-  DCHECK_EQ([personalStuffGroupThemes_ count], kThemeGroupCount)
-      << "Expected only two items in Themes group";
-  CGFloat themeRowChange = SizeToFitButtonPair(
-      [personalStuffGroupThemes_ objectAtIndex:kThemeResetButtonIndex],
-      [personalStuffGroupThemes_ objectAtIndex:kThemeThemesButtonIndex]);
-
-  // Size the Privacy and Clear buttons that make a row in Under the Hood.
-  CGFloat privacyRowChange = SizeToFitButtonPair(contentSettingsButton_,
-                                                 clearDataButton_);
-  // Under the Hood view is narrower (then the other panes) in the nib, subtract
-  // out the amount it was already going to grow to match the other panes when
-  // calculating how much the row needs things to grow.
-  privacyRowChange -=
-    ([underTheHoodScroller_ contentSize].width -
-     NSWidth([underTheHoodContentView_ frame]));
-
-  // Find the most any row changed in size.
-  CGFloat maxWidthChange = std::max(defaultBrowserChange.width, syncRowChange);
-  maxWidthChange = std::max(maxWidthChange, themeRowChange);
-  maxWidthChange = std::max(maxWidthChange, privacyRowChange);
-
-  // If any grew wider, make the views wider. If they all shrank, they fit the
-  // existing view widths, so no change is needed//.
-  if (maxWidthChange > 0.0) {
-    NSSize viewSize = [basicsView_ frame].size;
-    viewSize.width += maxWidthChange;
-    [basicsView_ setFrameSize:viewSize];
-    viewSize = [personalStuffView_ frame].size;
-    viewSize.width += maxWidthChange;
-    [personalStuffView_ setFrameSize:viewSize];
-  }
-
-  // Now that we have the width needed for Basics and Personal Stuff, lay out
-  // those pages bottom up making sure the strings fit and moving things up as
-  // needed.
-
-  CGFloat newWidth = NSWidth([basicsView_ frame]);
-  CGFloat verticalShift = 0.0;
-  verticalShift += AutoSizeGroup(basicsGroupDefaultBrowser_,
-                                 kAutoSizeGroupBehaviorVerticalFirstToFit,
-                                 verticalShift);
-  verticalShift += AutoSizeGroup(
-      basicsGroupSearchEngine_,
-      kAutoSizeGroupBehaviorFirstTwoAsRowVerticalToFit,
-      verticalShift);
-  verticalShift += AutoSizeGroup(basicsGroupToolbar_,
-                                 kAutoSizeGroupBehaviorVerticalToFit,
-                                 verticalShift);
-  verticalShift += AutoSizeGroup(basicsGroupHomePage_,
-                                 kAutoSizeGroupBehaviorVerticalToFit,
-                                 verticalShift);
-  verticalShift += AutoSizeGroup(basicsGroupStartup_,
-                                 kAutoSizeGroupBehaviorVerticalFirstToFit,
-                                 verticalShift);
-  [GTMUILocalizerAndLayoutTweaker
-      resizeViewWithoutAutoResizingSubViews:basicsView_
-                                      delta:NSMakeSize(0.0, verticalShift)];
-
-  verticalShift = 0.0;
-  verticalShift += AutoSizeGroup(personalStuffGroupThemes_,
-                                 kAutoSizeGroupBehaviorHorizontalToFit,
-                                 verticalShift);
-  verticalShift += AutoSizeGroup(personalStuffGroupBrowserData_,
-                                 kAutoSizeGroupBehaviorVerticalToFit,
-                                 verticalShift);
-  verticalShift += AutoSizeGroup(personalStuffGroupAutofill_,
-                                 kAutoSizeGroupBehaviorVerticalToFit,
-                                 verticalShift);
-  verticalShift += AutoSizeGroup(personalStuffGroupPasswords_,
-                                 kAutoSizeGroupBehaviorVerticalToFit,
-                                 verticalShift);
-  // TODO(akalin): Here we rely on the initial contents of the sync
-  // group's text field/link field to be large enough to hold all
-  // possible messages so that we don't have to re-layout when sync
-  // state changes.  This isn't perfect, since e.g. some sync messages
-  // use the user's e-mail address (which may be really long), and the
-  // link field is usually not shown (leaving a big empty space).
-  // Rethink sync preferences UI for Mac.
-  verticalShift += AutoSizeGroup(personalStuffGroupSync_,
-                                 kAutoSizeGroupBehaviorVerticalToFit,
-                                 verticalShift);
-  [GTMUILocalizerAndLayoutTweaker
-      resizeViewWithoutAutoResizingSubViews:personalStuffView_
-                                      delta:NSMakeSize(0.0, verticalShift)];
-
-  if (syncService_) {
-    syncService_->AddObserver(observer_.get());
-    // Update the controls according to the initial state.
-    [self syncStateChanged];
-  } else {
-    // If sync is disabled we don't want to show the sync controls at all.
-    RemoveGroupFromView(personalStuffView_, personalStuffGroupSync_);
-  }
-
-  // Make the window as wide as the views.
-  NSWindow* prefsWindow = [self window];
-  NSView* prefsContentView = [prefsWindow contentView];
-  NSRect frame = [prefsContentView convertRect:[prefsWindow frame]
-                                      fromView:nil];
-  frame.size.width = newWidth;
-  frame = [prefsContentView convertRect:frame toView:nil];
-  [prefsWindow setFrame:frame display:NO];
-
-  // The Under the Hood prefs is a scroller, it shouldn't get any border, so it
-  // gets resized to be as wide as the window ended up.
-  NSSize underTheHoodSize = [underTheHoodView_ frame].size;
-  underTheHoodSize.width = newWidth;
-  [underTheHoodView_ setFrameSize:underTheHoodSize];
-
-  // Widen the Under the Hood content so things can rewrap to the full width.
-  NSSize underTheHoodContentSize = [underTheHoodContentView_ frame].size;
-  underTheHoodContentSize.width = [underTheHoodScroller_ contentSize].width;
-  [underTheHoodContentView_ setFrameSize:underTheHoodContentSize];
-
-  // Now that Under the Hood is the right width, auto-size to the new width to
-  // get the final height.
-  verticalShift = AutoSizeUnderTheHoodContent(underTheHoodContentView_,
-                                              downloadLocationControl_,
-                                              downloadLocationButton_);
-  [GTMUILocalizerAndLayoutTweaker
-      resizeViewWithoutAutoResizingSubViews:underTheHoodContentView_
-                                      delta:NSMakeSize(0.0, verticalShift)];
-  underTheHoodContentSize = [underTheHoodContentView_ frame].size;
-
-  // Put the Under the Hood content view into the scroller and scroll it to the
-  // top.
-  [underTheHoodScroller_ setDocumentView:underTheHoodContentView_];
-  [underTheHoodContentView_ scrollPoint:
-      NSMakePoint(0, underTheHoodContentSize.height)];
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  NSImage* alertIcon = rb.GetNativeImageNamed(IDR_WARNING);
-  DCHECK(alertIcon);
-  [managedPrefsBannerWarningImage_ setImage:alertIcon];
-
-  [self initBannerStateForPage:initialPage_];
-  [self switchToPage:initialPage_ animate:NO];
-
-  // Save/restore position based on prefs.
-  if (g_browser_process && g_browser_process->local_state()) {
-    sizeSaver_.reset([[WindowSizeAutosaver alloc]
-       initWithWindow:[self window]
-          prefService:g_browser_process->local_state()
-                 path:prefs::kPreferencesWindowPlacement]);
-  }
-
-  // Initialize the banner gradient and stroke color.
-  NSColor* bannerStartingColor =
-      [NSColor colorWithCalibratedRed:kBannerGradientColorTop[0]
-                                green:kBannerGradientColorTop[1]
-                                 blue:kBannerGradientColorTop[2]
-                                alpha:1.0];
-  NSColor* bannerEndingColor =
-      [NSColor colorWithCalibratedRed:kBannerGradientColorBottom[0]
-                                green:kBannerGradientColorBottom[1]
-                                 blue:kBannerGradientColorBottom[2]
-                                alpha:1.0];
-  scoped_nsobject<NSGradient> bannerGradient(
-      [[NSGradient alloc] initWithStartingColor:bannerStartingColor
-                                    endingColor:bannerEndingColor]);
-  [managedPrefsBannerView_ setGradient:bannerGradient];
-
-  NSColor* bannerStrokeColor =
-      [NSColor colorWithCalibratedWhite:kBannerStrokeColor
-                                  alpha:1.0];
-  [managedPrefsBannerView_ setStrokeColor:bannerStrokeColor];
-
-  // Set accessibility related attributes.
-  NSTableView* tableView = [basicsView_ viewWithTag:kBasicsStartupPageTableTag];
-  NSString* description =
-      l10n_util::GetNSStringWithFixup(IDS_OPTIONS_STARTUP_SHOW_PAGES);
-  [tableView accessibilitySetOverrideValue:description
-                              forAttribute:NSAccessibilityDescriptionAttribute];
-}
-
-- (void)dealloc {
-  if (syncService_) {
-    syncService_->RemoveObserver(observer_.get());
-  }
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [animation_ setDelegate:nil];
-  [animation_ stopAnimation];
-  [super dealloc];
-}
-
-// Xcode 3.1.x version of Interface Builder doesn't do a lot for editing
-// toolbars in XIB.  So the toolbar's delegate is set to the controller so it
-// can tell the toolbar what items are selectable.
-- (NSArray*)toolbarSelectableItemIdentifiers:(NSToolbar*)toolbar {
-  DCHECK(toolbar == toolbar_);
-  return [[toolbar_ items] valueForKey:@"itemIdentifier"];
-}
-
-// Register our interest in the preferences we're displaying so if anything
-// else in the UI changes them we will be updated.
-- (void)registerPrefObservers {
-  if (!prefs_) return;
-
-  // Basics panel
-  registrar_.Init(prefs_);
-  registrar_.Add(prefs::kURLsToRestoreOnStartup, observer_.get());
-  restoreOnStartup_.Init(prefs::kRestoreOnStartup, prefs_, observer_.get());
-  newTabPageIsHomePage_.Init(prefs::kHomePageIsNewTabPage,
-                             prefs_, observer_.get());
-  homepage_.Init(prefs::kHomePage, prefs_, observer_.get());
-  showHomeButton_.Init(prefs::kShowHomeButton, prefs_, observer_.get());
-  instantEnabled_.Init(prefs::kInstantEnabled, prefs_, observer_.get());
-
-  // Personal Stuff panel
-  askSavePasswords_.Init(prefs::kPasswordManagerEnabled,
-                         prefs_, observer_.get());
-  autoFillEnabled_.Init(prefs::kAutoFillEnabled, prefs_, observer_.get());
-  currentTheme_.Init(prefs::kCurrentThemeID, prefs_, observer_.get());
-
-  // Under the hood panel
-  alternateErrorPages_.Init(prefs::kAlternateErrorPagesEnabled,
-                            prefs_, observer_.get());
-  useSuggest_.Init(prefs::kSearchSuggestEnabled, prefs_, observer_.get());
-  dnsPrefetch_.Init(prefs::kDnsPrefetchingEnabled, prefs_, observer_.get());
-  safeBrowsing_.Init(prefs::kSafeBrowsingEnabled, prefs_, observer_.get());
-  autoOpenFiles_.Init(
-      prefs::kDownloadExtensionsToOpen, prefs_, observer_.get());
-  translateEnabled_.Init(prefs::kEnableTranslate, prefs_, observer_.get());
-  tabsToLinks_.Init(prefs::kWebkitTabsToLinks, prefs_, observer_.get());
-
-  // During unit tests, there is no local state object, so we fall back to
-  // the prefs object (where we've explicitly registered this pref so we
-  // know it's there).
-  PrefService* local = g_browser_process->local_state();
-  if (!local)
-    local = prefs_;
-  metricsReporting_.Init(prefs::kMetricsReportingEnabled,
-                         local, observer_.get());
-  defaultDownloadLocation_.Init(prefs::kDownloadDefaultDirectory, prefs_,
-                                observer_.get());
-  askForSaveLocation_.Init(prefs::kPromptForDownload, prefs_, observer_.get());
-
-  // We don't need to observe changes in this value.
-  lastSelectedPage_.Init(prefs::kOptionsWindowLastTabIndex, local, NULL);
-}
-
-// Called when the window wants to be closed.
-- (BOOL)windowShouldClose:(id)sender {
-  // Stop any animation and clear the delegate to avoid stale pointers.
-  [animation_ setDelegate:nil];
-  [animation_ stopAnimation];
-
-  return YES;
-}
-
-// Called when the user hits the escape key. Closes the window.
-- (void)cancel:(id)sender {
-  [[self window] performClose:self];
-}
-
-// Record the user performed a certain action and save the preferences.
-- (void)recordUserAction:(const UserMetricsAction &)action {
-  UserMetrics::RecordAction(action, profile_);
-  if (prefs_)
-    prefs_->ScheduleSavePersistentPrefs();
-}
-
-// Returns the set of keys that |key| depends on for its value so it can be
-// re-computed when any of those change as well.
-+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key {
-  NSSet* paths = [super keyPathsForValuesAffectingValueForKey:key];
-  if ([key isEqualToString:@"isHomepageURLEnabled"]) {
-    paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
-    paths = [paths setByAddingObject:@"homepageURL"];
-  } else if ([key isEqualToString:@"restoreURLsEnabled"]) {
-    paths = [paths setByAddingObject:@"restoreOnStartupIndex"];
-  } else if ([key isEqualToString:@"isHomepageChoiceEnabled"]) {
-    paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
-    paths = [paths setByAddingObject:@"homepageURL"];
-  } else if ([key isEqualToString:@"newTabPageIsHomePageIndex"]) {
-    paths = [paths setByAddingObject:@"homepageURL"];
-  } else if ([key isEqualToString:@"hompageURL"]) {
-    paths = [paths setByAddingObject:@"newTabPageIsHomePageIndex"];
-  } else if ([key isEqualToString:@"isDefaultBrowser"]) {
-    paths = [paths setByAddingObject:@"defaultBrowser"];
-  } else if ([key isEqualToString:@"defaultBrowserTextColor"]) {
-    paths = [paths setByAddingObject:@"defaultBrowser"];
-  } else if ([key isEqualToString:@"defaultBrowserText"]) {
-    paths = [paths setByAddingObject:@"defaultBrowser"];
-  }
-  return paths;
-}
-
-// Launch the Keychain Access app.
-- (void)launchKeychainAccess {
-  NSString* const kKeychainBundleId = @"com.apple.keychainaccess";
-  [[NSWorkspace sharedWorkspace]
-      launchAppWithBundleIdentifier:kKeychainBundleId
-                            options:0L
-     additionalEventParamDescriptor:nil
-                   launchIdentifier:nil];
-}
-
-//-------------------------------------------------------------------------
-// Basics panel
-
-// Sets the home page preferences for kNewTabPageIsHomePage and kHomePage. If a
-// blank or null-host URL is passed in we revert to using NewTab page
-// as the Home page. Note: using SetValue() causes the observers not to fire,
-// which is actually a good thing as we could end up in a state where setting
-// the homepage to an empty url would automatically reset the prefs back to
-// using the NTP, so we'd be never be able to change it.
-- (void)setHomepage:(const GURL&)homepage {
-  if (IsNewTabUIURLString(homepage)) {
-    newTabPageIsHomePage_.SetValueIfNotManaged(true);
-    homepage_.SetValueIfNotManaged(std::string());
-  } else if (!homepage.is_valid()) {
-    newTabPageIsHomePage_.SetValueIfNotManaged(true);
-    if (!homepage.has_host())
-      homepage_.SetValueIfNotManaged(std::string());
-  } else {
-    homepage_.SetValueIfNotManaged(homepage.spec());
-  }
-}
-
-// Callback when preferences are changed by someone modifying the prefs backend
-// externally. |prefName| is the name of the pref that has changed. Unlike on
-// Windows, we don't need to use this method for initializing, that's handled by
-// Cocoa Bindings.
-// Handles prefs for the "Basics" panel.
-- (void)basicsPrefChanged:(std::string*)prefName {
-  if (*prefName == prefs::kRestoreOnStartup) {
-    const SessionStartupPref startupPref =
-        SessionStartupPref::GetStartupPref(prefs_);
-    [self setRestoreOnStartupIndex:startupPref.type];
-    [self setEnabledStateOfRestoreOnStartup];
-  } else if (*prefName == prefs::kURLsToRestoreOnStartup) {
-    [customPagesSource_ reloadURLs];
-    [self setEnabledStateOfRestoreOnStartup];
-  } else if (*prefName == prefs::kHomePageIsNewTabPage) {
-    NSInteger useNewTabPage = newTabPageIsHomePage_.GetValue() ? 0 : 1;
-    [self setNewTabPageIsHomePageIndex:useNewTabPage];
-  } else if (*prefName == prefs::kHomePage) {
-    NSString* value = base::SysUTF8ToNSString(homepage_.GetValue());
-    [self setHomepageURL:value];
-  } else if (*prefName == prefs::kShowHomeButton) {
-    [self setShowHomeButton:showHomeButton_.GetValue() ? YES : NO];
-    [self setShowHomeButtonEnabled:!showHomeButton_.IsManaged()];
-  } else if (*prefName == prefs::kInstantEnabled) {
-    [self configureInstant];
-  }
-}
-
-// Returns the index of the selected cell in the "on startup" matrix based
-// on the "restore on startup" pref. The ordering of the cells is in the
-// same order as the pref.
-- (NSInteger)restoreOnStartupIndex {
-  const SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs_);
-  return pref.type;
-}
-
-// A helper function that takes the startup session type, grabs the URLs to
-// restore, and saves it all in prefs.
-- (void)saveSessionStartupWithType:(SessionStartupPref::Type)type {
-  SessionStartupPref pref;
-  pref.type = type;
-  pref.urls = [customPagesSource_.get() URLs];
-  SessionStartupPref::SetStartupPref(prefs_, pref);
-}
-
-// Sets the pref based on the index of the selected cell in the matrix and
-// marks the appropriate user metric.
-- (void)setRestoreOnStartupIndex:(NSInteger)type {
-  SessionStartupPref::Type startupType =
-      static_cast<SessionStartupPref::Type>(type);
-  switch (startupType) {
-    case SessionStartupPref::DEFAULT:
-      [self recordUserAction:UserMetricsAction("Options_Startup_Homepage")];
-      break;
-    case SessionStartupPref::LAST:
-      [self recordUserAction:UserMetricsAction("Options_Startup_LastSession")];
-      break;
-    case SessionStartupPref::URLS:
-      [self recordUserAction:UserMetricsAction("Options_Startup_Custom")];
-      break;
-    default:
-      NOTREACHED();
-  }
-  [self saveSessionStartupWithType:startupType];
-}
-
-// Enables or disables the restoreOnStartup elements
-- (void) setEnabledStateOfRestoreOnStartup {
-  const SessionStartupPref startupPref =
-      SessionStartupPref::GetStartupPref(prefs_);
-  [self setRestoreButtonsEnabled:!SessionStartupPref::TypeIsManaged(prefs_)];
-  [self setRestoreURLsEnabled:!SessionStartupPref::URLsAreManaged(prefs_) &&
-      [self restoreOnStartupIndex] == SessionStartupPref::URLS];
-}
-
-// Getter for the |customPagesSource| property for bindings.
-- (CustomHomePagesModel*)customPagesSource {
-  return customPagesSource_.get();
-}
-
-// Called when the selection in the table changes. If a flag is set indicating
-// that we're waiting for a special select message, edit the cell. Otherwise
-// just ignore it, we don't normally care.
-- (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
-  if (pendingSelectForEdit_) {
-    NSTableView* table = [aNotification object];
-    NSUInteger selectedRow = [table selectedRow];
-    [table editColumn:0 row:selectedRow withEvent:nil select:YES];
-    pendingSelectForEdit_ = NO;
-  }
-}
-
-// Called when the user hits the (+) button for adding a new homepage to the
-// list. This will also attempt to make the new item editable so the user can
-// just start typing.
-- (IBAction)addHomepage:(id)sender {
-  [customPagesArrayController_ add:sender];
-
-  // When the new item is added to the model, the array controller will select
-  // it. We'll watch for that notification (because we are the table view's
-  // delegate) and then make the cell editable. Note that this can't be
-  // accomplished simply by subclassing the array controller's add method (I
-  // did try). The update of the table is asynchronous with the controller
-  // updating the model.
-  pendingSelectForEdit_ = YES;
-}
-
-// Called when the user hits the (-) button for removing the selected items in
-// the homepage table. The controller does all the work.
-- (IBAction)removeSelectedHomepages:(id)sender {
-  [customPagesArrayController_ remove:sender];
-}
-
-// Add all entries for all open browsers with our profile.
-- (IBAction)useCurrentPagesAsHomepage:(id)sender {
-  std::vector<GURL> urls;
-  for (BrowserList::const_iterator browserIter = BrowserList::begin();
-       browserIter != BrowserList::end(); ++browserIter) {
-    Browser* browser = *browserIter;
-    if (browser->profile() != profile_)
-      continue;  // Only want entries for open profile.
-
-    for (int tabIndex = 0; tabIndex < browser->tab_count(); ++tabIndex) {
-      TabContents* tab = browser->GetTabContentsAt(tabIndex);
-      if (tab->ShouldDisplayURL()) {
-        const GURL url = browser->GetTabContentsAt(tabIndex)->GetURL();
-        if (!url.is_empty())
-          urls.push_back(url);
-      }
-    }
-  }
-  [customPagesSource_ setURLs:urls];
-}
-
-enum { kHomepageNewTabPage, kHomepageURL };
-
-// Here's a table describing the desired characteristics of the homepage choice
-// radio value, it's enabled state and the URL field enabled state. They depend
-// on the values of the managed bits for homepage (m_hp) and
-// homepageIsNewTabPage (m_ntp) preferences, as well as the value of the
-// homepageIsNewTabPage preference (ntp) and whether the homepage preference
-// is equal to the new tab page URL (hpisntp).
-//
-// m_hp m_ntp ntp hpisntp | choice value | choice enabled | URL field enabled
-// --------------------------------------------------------------------------
-// 0    0     0   0       | homepage     | 1              | 1
-// 0    0     0   1       | new tab page | 1              | 0
-// 0    0     1   0       | new tab page | 1              | 0
-// 0    0     1   1       | new tab page | 1              | 0
-// 0    1     0   0       | homepage     | 0              | 1
-// 0    1     0   1       | homepage     | 0              | 1
-// 0    1     1   0       | new tab page | 0              | 0
-// 0    1     1   1       | new tab page | 0              | 0
-// 1    0     0   0       | homepage     | 1              | 0
-// 1    0     0   1       | new tab page | 0              | 0
-// 1    0     1   0       | new tab page | 1              | 0
-// 1    0     1   1       | new tab page | 0              | 0
-// 1    1     0   0       | homepage     | 0              | 0
-// 1    1     0   1       | new tab page | 0              | 0
-// 1    1     1   0       | new tab page | 0              | 0
-// 1    1     1   1       | new tab page | 0              | 0
-//
-// thus, we have:
-//
-//    choice value is new tab page === ntp || (hpisntp && (m_hp || !m_ntp))
-//    choice enabled === !m_ntp && !(m_hp && hpisntp)
-//    URL field enabled === !ntp && !mhp && !(hpisntp && !m_ntp)
-//
-// which also make sense if you think about them.
-
-// Checks whether the homepage URL refers to the new tab page.
-- (BOOL)isHomepageNewTabUIURL {
-  return IsNewTabUIURLString(GURL(homepage_.GetValue().c_str()));
-}
-
-// Returns the index of the selected cell in the "home page" marix based on
-// the "new tab is home page" pref. Sadly, the ordering is reversed from the
-// pref value.
-- (NSInteger)newTabPageIsHomePageIndex {
-  return newTabPageIsHomePage_.GetValue() ||
-      ([self isHomepageNewTabUIURL] &&
-          (homepage_.IsManaged() || !newTabPageIsHomePage_.IsManaged())) ?
-      kHomepageNewTabPage : kHomepageURL;
-}
-
-// Sets the pref based on the given index into the matrix and marks the
-// appropriate user metric.
-- (void)setNewTabPageIsHomePageIndex:(NSInteger)index {
-  bool useNewTabPage = index == kHomepageNewTabPage ? true : false;
-  if (useNewTabPage) {
-    [self recordUserAction:UserMetricsAction("Options_Homepage_UseNewTab")];
-  } else {
-    [self recordUserAction:UserMetricsAction("Options_Homepage_UseURL")];
-    if ([self isHomepageNewTabUIURL])
-      homepage_.SetValueIfNotManaged(std::string());
-  }
-  newTabPageIsHomePage_.SetValueIfNotManaged(useNewTabPage);
-}
-
-// Check whether the new tab and URL homepage radios should be enabled, i.e. if
-// the corresponding preference is not managed through configuration policy.
-- (BOOL)isHomepageChoiceEnabled {
-  return !newTabPageIsHomePage_.IsManaged() &&
-      !(homepage_.IsManaged() && [self isHomepageNewTabUIURL]);
-}
-
-// Returns whether or not the homepage URL text field should be enabled
-// based on if the new tab page is the home page.
-- (BOOL)isHomepageURLEnabled {
-  return !newTabPageIsHomePage_.GetValue() && !homepage_.IsManaged() &&
-      !([self isHomepageNewTabUIURL] && !newTabPageIsHomePage_.IsManaged());
-}
-
-// Returns the homepage URL.
-- (NSString*)homepageURL {
-  NSString* value = base::SysUTF8ToNSString(homepage_.GetValue());
-  return [self isHomepageNewTabUIURL] ? nil : value;
-}
-
-// Sets the homepage URL to |urlString| with some fixing up.
-- (void)setHomepageURL:(NSString*)urlString {
-  // If the text field contains a valid URL, sync it to prefs. We run it
-  // through the fixer upper to allow input like "google.com" to be converted
-  // to something valid ("http://google.com").
-  std::string unfixedURL = urlString ? base::SysNSStringToUTF8(urlString) :
-                                       chrome::kChromeUINewTabURL;
-  [self setHomepage:URLFixerUpper::FixupURL(unfixedURL, std::string())];
-}
-
-// Returns whether the home button should be checked based on the preference.
-- (BOOL)showHomeButton {
-  return showHomeButton_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the home button should be displayed
-// based on |value|.
-- (void)setShowHomeButton:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_Homepage_ShowHomeButton")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_Homepage_HideHomeButton")];
-  showHomeButton_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Getter for the |searchEngineModel| property for bindings.
-- (id)searchEngineModel {
-  return searchEngineModel_.get();
-}
-
-// Bindings for the search engine popup. We not binding directly to the model
-// in order to siphon off the setter so we can record the metric. If we're
-// doing it with one, might as well do it with both.
-- (NSUInteger)searchEngineSelectedIndex {
-  return [searchEngineModel_ defaultIndex];
-}
-
-- (void)setSearchEngineSelectedIndex:(NSUInteger)index {
-  [self recordUserAction:UserMetricsAction("Options_SearchEngineChanged")];
-  [searchEngineModel_ setDefaultIndex:index];
-}
-
-// Called when the search engine model changes. Update the selection in the
-// popup by tickling the bindings with the new value.
-- (void)searchEngineModelChanged:(NSNotification*)notify {
-  [self setSearchEngineSelectedIndex:[self searchEngineSelectedIndex]];
-  [self setDefaultSearchEngineEnabled:![searchEngineModel_ isDefaultManaged]];
-
-}
-
-- (IBAction)manageSearchEngines:(id)sender {
-  [KeywordEditorCocoaController showKeywordEditor:profile_];
-}
-
-- (IBAction)toggleInstant:(id)sender {
-  if (instantEnabled_.GetValue()) {
-    InstantController::Disable(profile_);
-  } else {
-    [instantCheckbox_ setState:NSOffState];
-    browser::ShowInstantConfirmDialogIfNecessary([self window], profile_);
-  }
-}
-
-// Sets the state of the Instant checkbox and adds the type information to the
-// label.
-- (void)configureInstant {
-  bool enabled = instantEnabled_.GetValue();
-  NSInteger state = enabled ? NSOnState : NSOffState;
-  [instantCheckbox_ setState:state];
-}
-
-- (IBAction)learnMoreAboutInstant:(id)sender {
-  browser::ShowOptionsURL(profile_, browser::InstantLearnMoreURL());
-}
-
-// Called when the user clicks the button to make Chromium the default
-// browser. Registers http and https.
-- (IBAction)makeDefaultBrowser:(id)sender {
-  [self willChangeValueForKey:@"defaultBrowser"];
-
-  ShellIntegration::SetAsDefaultBrowser();
-  [self recordUserAction:UserMetricsAction("Options_SetAsDefaultBrowser")];
-  // If the user made Chrome the default browser, then he/she arguably wants
-  // to be notified when that changes.
-  prefs_->SetBoolean(prefs::kCheckDefaultBrowser, true);
-
-  // Tickle KVO so that the UI updates.
-  [self didChangeValueForKey:@"defaultBrowser"];
-}
-
-// Returns the Chromium default browser state.
-- (ShellIntegration::DefaultBrowserState)isDefaultBrowser {
-  return ShellIntegration::IsDefaultBrowser();
-}
-
-// Returns the text color of the "chromium is your default browser" text (green
-// for yes, red for no).
-- (NSColor*)defaultBrowserTextColor {
-  ShellIntegration::DefaultBrowserState state = [self isDefaultBrowser];
-  return (state == ShellIntegration::IS_DEFAULT_BROWSER) ?
-    [NSColor colorWithCalibratedRed:0.0 green:135.0/255.0 blue:0 alpha:1.0] :
-    [NSColor colorWithCalibratedRed:135.0/255.0 green:0 blue:0 alpha:1.0];
-}
-
-// Returns the text for the "chromium is your default browser" string dependent
-// on if Chromium actually is or not.
-- (NSString*)defaultBrowserText {
-  ShellIntegration::DefaultBrowserState state = [self isDefaultBrowser];
-  int stringId;
-  if (state == ShellIntegration::IS_DEFAULT_BROWSER)
-    stringId = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
-  else if (state == ShellIntegration::NOT_DEFAULT_BROWSER)
-    stringId = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
-  else
-    stringId = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
-  string16 text =
-      l10n_util::GetStringFUTF16(stringId,
-                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
-  return base::SysUTF16ToNSString(text);
-}
-
-//-------------------------------------------------------------------------
-// User Data panel
-
-// Since passwords and forms are radio groups, 'enabled' is index 0 and
-// 'disabled' is index 1. Yay.
-const int kEnabledIndex = 0;
-const int kDisabledIndex = 1;
-
-// Callback when preferences are changed. |prefName| is the name of the pref
-// that has changed. Unlike on Windows, we don't need to use this method for
-// initializing, that's handled by Cocoa Bindings.
-// Handles prefs for the "Personal Stuff" panel.
-- (void)userDataPrefChanged:(std::string*)prefName {
-  if (*prefName == prefs::kPasswordManagerEnabled) {
-    [self setPasswordManagerEnabledIndex:askSavePasswords_.GetValue() ?
-        kEnabledIndex : kDisabledIndex];
-    [self setPasswordManagerChoiceEnabled:!askSavePasswords_.IsManaged()];
-    [self setPasswordManagerButtonEnabled:
-        !askSavePasswords_.IsManaged() || askSavePasswords_.GetValue()];
-  }
-  if (*prefName == prefs::kAutoFillEnabled) {
-    bool autofill_disabled_by_policy =
-        autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue();
-    [self setAutoFillSettingsButtonEnabled:!autofill_disabled_by_policy];
-  }
-  if (*prefName == prefs::kCurrentThemeID) {
-    [self setIsUsingDefaultTheme:currentTheme_.GetValue().length() == 0];
-  }
-}
-
-// Called to launch the Keychain Access app to show the user's stored
-// passwords.
-- (IBAction)showSavedPasswords:(id)sender {
-  [self recordUserAction:UserMetricsAction("Options_ShowPasswordsExceptions")];
-  [self launchKeychainAccess];
-}
-
-// Called to show the Auto Fill Settings dialog.
-- (IBAction)showAutoFillSettings:(id)sender {
-  [self recordUserAction:UserMetricsAction("Options_ShowAutoFillSettings")];
-
-  PersonalDataManager* personalDataManager = profile_->GetPersonalDataManager();
-  if (!personalDataManager) {
-    // Should not reach here because button is disabled when
-    // |personalDataManager| is NULL.
-    NOTREACHED();
-    return;
-  }
-
-  ShowAutoFillDialog(NULL, personalDataManager, profile_);
-}
-
-// Called to import data from other browsers (Safari, Firefox, etc).
-- (IBAction)importData:(id)sender {
-  UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"), profile_);
-  [ImportSettingsDialogController showImportSettingsDialogForProfile:profile_];
-}
-
-- (IBAction)resetThemeToDefault:(id)sender {
-  [self recordUserAction:UserMetricsAction("Options_ThemesReset")];
-  profile_->ClearTheme();
-}
-
-- (IBAction)themesGallery:(id)sender {
-  [self recordUserAction:UserMetricsAction("Options_ThemesGallery")];
-  Browser* browser = BrowserList::GetLastActive();
-
-  if (!browser || !browser->GetSelectedTabContents())
-    browser = Browser::Create(profile_);
-  browser->OpenThemeGalleryTabAndActivate();
-}
-
-// Called when the "stop syncing" confirmation dialog started by
-// doSyncAction is finished.  Stop syncing only If the user clicked
-// OK.
-- (void)stopSyncAlertDidEnd:(NSAlert*)alert
-                 returnCode:(int)returnCode
-                contextInfo:(void*)contextInfo {
-  DCHECK(syncService_ && !syncService_->IsManaged());
-  if (returnCode == NSAlertFirstButtonReturn) {
-    syncService_->DisableForUser();
-    ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
-  }
-}
-
-// Called when the user clicks the multi-purpose sync button in the
-// "Personal Stuff" pane.
-- (IBAction)doSyncAction:(id)sender {
-  DCHECK(syncService_ && !syncService_->IsManaged());
-  if (syncService_->HasSyncSetupCompleted()) {
-    // If sync setup has completed that means the sync button was a
-    // "stop syncing" button.  Bring up a confirmation dialog before
-    // actually stopping syncing (see stopSyncAlertDidEnd).
-    scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
-    [alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
-        IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL)];
-    [alert addButtonWithTitle:l10n_util::GetNSStringWithFixup(
-        IDS_CANCEL)];
-    [alert setMessageText:l10n_util::GetNSStringWithFixup(
-        IDS_SYNC_STOP_SYNCING_DIALOG_TITLE)];
-    [alert setInformativeText:l10n_util::GetNSStringFWithFixup(
-        IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL,
-        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))];
-    [alert setAlertStyle:NSWarningAlertStyle];
-    const SEL kEndSelector =
-        @selector(stopSyncAlertDidEnd:returnCode:contextInfo:);
-    [alert beginSheetModalForWindow:[self window]
-                      modalDelegate:self
-                     didEndSelector:kEndSelector
-                        contextInfo:NULL];
-  } else {
-    // Otherwise, the sync button was a "sync my bookmarks" button.
-    // Kick off the sync setup process.
-    syncService_->ShowLoginDialog(NULL);
-    ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
-  }
-}
-
-// Called when the user clicks on the link to the privacy dashboard.
-- (IBAction)showPrivacyDashboard:(id)sender {
-  Browser* browser = BrowserList::GetLastActive();
-
-  if (!browser || !browser->GetSelectedTabContents())
-    browser = Browser::Create(profile_);
-  browser->OpenPrivacyDashboardTabAndActivate();
-}
-
-// Called when the user clicks the "Customize Sync" button in the
-// "Personal Stuff" pane.  Spawns a dialog-modal sheet that cleans
-// itself up on close.
-- (IBAction)doSyncCustomize:(id)sender {
-  syncService_->ShowConfigure(NULL);
-}
-
-- (IBAction)doSyncReauthentication:(id)sender {
-  DCHECK(syncService_ && !syncService_->IsManaged());
-  syncService_->ShowLoginDialog(NULL);
-}
-
-- (void)setPasswordManagerEnabledIndex:(NSInteger)value {
-  if (value == kEnabledIndex)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_PasswordManager_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_PasswordManager_Disable")];
-  askSavePasswords_.SetValueIfNotManaged(value == kEnabledIndex ? true : false);
-}
-
-- (NSInteger)passwordManagerEnabledIndex {
-  return askSavePasswords_.GetValue() ? kEnabledIndex : kDisabledIndex;
-}
-
-- (void)setIsUsingDefaultTheme:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_IsUsingDefaultTheme_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_IsUsingDefaultTheme_Disable")];
-}
-
-- (BOOL)isUsingDefaultTheme {
-  return currentTheme_.GetValue().length() == 0;
-}
-
-//-------------------------------------------------------------------------
-// Under the hood panel
-
-// Callback when preferences are changed. |prefName| is the name of the pref
-// that has changed. Unlike on Windows, we don't need to use this method for
-// initializing, that's handled by Cocoa Bindings.
-// Handles prefs for the "Under the hood" panel.
-- (void)underHoodPrefChanged:(std::string*)prefName {
-  if (*prefName == prefs::kAlternateErrorPagesEnabled) {
-    [self setShowAlternateErrorPages:
-        alternateErrorPages_.GetValue() ? YES : NO];
-    [self setShowAlternateErrorPagesEnabled:!alternateErrorPages_.IsManaged()];
-  }
-  else if (*prefName == prefs::kSearchSuggestEnabled) {
-    [self setUseSuggest:useSuggest_.GetValue() ? YES : NO];
-    [self setUseSuggestEnabled:!useSuggest_.IsManaged()];
-  }
-  else if (*prefName == prefs::kDnsPrefetchingEnabled) {
-    [self setDnsPrefetch:dnsPrefetch_.GetValue() ? YES : NO];
-    [self setDnsPrefetchEnabled:!dnsPrefetch_.IsManaged()];
-  }
-  else if (*prefName == prefs::kSafeBrowsingEnabled) {
-    [self setSafeBrowsing:safeBrowsing_.GetValue() ? YES : NO];
-    [self setSafeBrowsingEnabled:!safeBrowsing_.IsManaged()];
-  }
-  else if (*prefName == prefs::kMetricsReportingEnabled) {
-    [self setMetricsReporting:metricsReporting_.GetValue() ? YES : NO];
-    [self setMetricsReportingEnabled:!metricsReporting_.IsManaged()];
-  }
-  else if (*prefName == prefs::kDownloadDefaultDirectory) {
-    // Poke KVO.
-    [self willChangeValueForKey:@"defaultDownloadLocation"];
-    [self didChangeValueForKey:@"defaultDownloadLocation"];
-  }
-  else if (*prefName == prefs::kPromptForDownload) {
-    [self setAskForSaveLocation:askForSaveLocation_.GetValue() ? YES : NO];
-  }
-  else if (*prefName == prefs::kEnableTranslate) {
-    [self setTranslateEnabled:translateEnabled_.GetValue() ? YES : NO];
-  }
-  else if (*prefName == prefs::kWebkitTabsToLinks) {
-    [self setTabsToLinks:tabsToLinks_.GetValue() ? YES : NO];
-  }
-  else if (*prefName == prefs::kDownloadExtensionsToOpen) {
-    // Poke KVC.
-    [self setFileHandlerUIEnabled:[self fileHandlerUIEnabled]];
-  }
-  else if (proxyPrefs_->IsObserved(*prefName)) {
-    [self setProxiesConfigureButtonEnabled:!proxyPrefs_->IsManaged()];
-  }
-}
-
-// Set the new download path and notify the UI via KVO.
-- (void)downloadPathPanelDidEnd:(NSOpenPanel*)panel
-                           code:(NSInteger)returnCode
-                        context:(void*)context {
-  if (returnCode == NSOKButton) {
-    [self recordUserAction:UserMetricsAction("Options_SetDownloadDirectory")];
-    NSURL* path = [[panel URLs] lastObject];  // We only allow 1 item.
-    [self willChangeValueForKey:@"defaultDownloadLocation"];
-    defaultDownloadLocation_.SetValue(base::SysNSStringToUTF8([path path]));
-    [self didChangeValueForKey:@"defaultDownloadLocation"];
-  }
-}
-
-// Bring up an open panel to allow the user to set a new downloads location.
-- (void)browseDownloadLocation:(id)sender {
-  NSOpenPanel* panel = [NSOpenPanel openPanel];
-  [panel setAllowsMultipleSelection:NO];
-  [panel setCanChooseFiles:NO];
-  [panel setCanChooseDirectories:YES];
-  NSString* path = base::SysUTF8ToNSString(defaultDownloadLocation_.GetValue());
-  [panel beginSheetForDirectory:path
-                           file:nil
-                          types:nil
-                 modalForWindow:[self window]
-                  modalDelegate:self
-                 didEndSelector:@selector(downloadPathPanelDidEnd:code:context:)
-                    contextInfo:NULL];
-}
-
-// Called to clear user's browsing data. This puts up an application-modal
-// dialog to guide the user through clearing the data.
-- (IBAction)clearData:(id)sender {
-  [ClearBrowsingDataController
-      showClearBrowsingDialogForProfile:profile_];
-}
-
-// Opens the "Content Settings" dialog.
-- (IBAction)showContentSettings:(id)sender {
-  [ContentSettingsDialogController
-      showContentSettingsForType:CONTENT_SETTINGS_TYPE_DEFAULT
-                         profile:profile_];
-}
-
-- (IBAction)privacyLearnMore:(id)sender {
-  GURL url = google_util::AppendGoogleLocaleParam(
-      GURL(chrome::kPrivacyLearnMoreURL));
-  // We open a new browser window so the Options dialog doesn't get lost
-  // behind other windows.
-  browser::ShowOptionsURL(profile_, url);
-}
-
-- (IBAction)resetAutoOpenFiles:(id)sender {
-  profile_->GetDownloadManager()->download_prefs()->ResetAutoOpen();
-  [self recordUserAction:UserMetricsAction("Options_ResetAutoOpenFiles")];
-}
-
-- (IBAction)openProxyPreferences:(id)sender {
-  NSArray* itemsToOpen = [NSArray arrayWithObject:[NSURL fileURLWithPath:
-      @"/System/Library/PreferencePanes/Network.prefPane"]];
-
-  const char* proxyPrefCommand = "Proxies";
-  base::mac::ScopedAEDesc<> openParams;
-  OSStatus status = AECreateDesc('ptru',
-                                 proxyPrefCommand,
-                                 strlen(proxyPrefCommand),
-                                 openParams.OutPointer());
-  LOG_IF(ERROR, status != noErr) << "Failed to create open params: " << status;
-
-  LSLaunchURLSpec launchSpec = { 0 };
-  launchSpec.itemURLs = (CFArrayRef)itemsToOpen;
-  launchSpec.passThruParams = openParams;
-  launchSpec.launchFlags = kLSLaunchAsync | kLSLaunchDontAddToRecents;
-  LSOpenFromURLSpec(&launchSpec, NULL);
-}
-
-// Returns whether the alternate error page checkbox should be checked based
-// on the preference.
-- (BOOL)showAlternateErrorPages {
-  return alternateErrorPages_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the alternate error page checkbox
-// should be displayed based on |value|.
-- (void)setShowAlternateErrorPages:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_LinkDoctorCheckbox_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_LinkDoctorCheckbox_Disable")];
-  alternateErrorPages_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Returns whether the suggest checkbox should be checked based on the
-// preference.
-- (BOOL)useSuggest {
-  return useSuggest_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the suggest checkbox should be
-// displayed based on |value|.
-- (void)setUseSuggest:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_UseSuggestCheckbox_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_UseSuggestCheckbox_Disable")];
-  useSuggest_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Returns whether the DNS prefetch checkbox should be checked based on the
-// preference.
-- (BOOL)dnsPrefetch {
-  return dnsPrefetch_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the DNS prefetch checkbox should be
-// displayed based on |value|.
-- (void)setDnsPrefetch:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_DnsPrefetchCheckbox_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_DnsPrefetchCheckbox_Disable")];
-  dnsPrefetch_.SetValueIfNotManaged(value ? true : false);
-}
-
-// Returns whether the safe browsing checkbox should be checked based on the
-// preference.
-- (BOOL)safeBrowsing {
-  return safeBrowsing_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the safe browsing checkbox should be
-// displayed based on |value|.
-- (void)setSafeBrowsing:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_SafeBrowsingCheckbox_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_SafeBrowsingCheckbox_Disable")];
-  safeBrowsing_.SetValueIfNotManaged(value ? true : false);
-  SafeBrowsingService* safeBrowsingService =
-      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      NewRunnableMethod(safeBrowsingService,
-                        &SafeBrowsingService::OnEnable,
-                        safeBrowsing_.GetValue()));
-}
-
-// Returns whether the metrics reporting checkbox should be checked based on the
-// preference.
-- (BOOL)metricsReporting {
-  return metricsReporting_.GetValue() ? YES : NO;
-}
-
-// Sets the backend pref for whether or not the metrics reporting checkbox
-// should be displayed based on |value|.
-- (void)setMetricsReporting:(BOOL)value {
-  if (value)
-    [self recordUserAction:UserMetricsAction(
-                           "Options_MetricsReportingCheckbox_Enable")];
-  else
-    [self recordUserAction:UserMetricsAction(
-                           "Options_MetricsReportingCheckbox_Disable")];
-
-  // TODO(pinkerton): windows shows a dialog here telling the user they need to
-  // restart for this to take effect. http://crbug.com/34653
-  metricsReporting_.SetValueIfNotManaged(value ? true : false);
-
-  bool enabled = metricsReporting_.GetValue();
-  GoogleUpdateSettings::SetCollectStatsConsent(enabled);
-  bool update_pref = GoogleUpdateSettings::GetCollectStatsConsent();
-  if (enabled != update_pref) {
-    DVLOG(1) << "GENERAL SECTION: Unable to set crash report status to "
-             << enabled;
-  }
-  // Only change the pref if GoogleUpdateSettings::GetCollectStatsConsent
-  // succeeds.
-  enabled = update_pref;
-
-  MetricsService* metrics = g_browser_process->metrics_service();
-  DCHECK(metrics);
-  if (metrics) {
-    metrics->SetUserPermitsUpload(enabled);
-    if (enabled)
-      metrics->Start();
-    else
-      metrics->Stop();
-  }
-}
-
-- (NSURL*)defaultDownloadLocation {
-  NSString* pathString =
-      base::SysUTF8ToNSString(defaultDownloadLocation_.GetValue());
-  return [NSURL fileURLWithPath:pathString];
-}
-
-- (BOOL)askForSaveLocation {
-  return askForSaveLocation_.GetValue();
-}
-
-- (void)setAskForSaveLocation:(BOOL)value {
-  if (value) {
-    [self recordUserAction:UserMetricsAction(
-                           "Options_AskForSaveLocation_Enable")];
-  } else {
-    [self recordUserAction:UserMetricsAction(
-                           "Options_AskForSaveLocation_Disable")];
-  }
-  askForSaveLocation_.SetValue(value);
-}
-
-- (BOOL)fileHandlerUIEnabled {
-  if (!profile_->GetDownloadManager())  // Not set in unit tests.
-    return NO;
-  return profile_->GetDownloadManager()->download_prefs()->IsAutoOpenUsed();
-}
-
-- (void)setFileHandlerUIEnabled:(BOOL)value {
-  [resetFileHandlersButton_ setEnabled:value];
-}
-
-- (BOOL)translateEnabled {
-  return translateEnabled_.GetValue();
-}
-
-- (void)setTranslateEnabled:(BOOL)value {
-  if (value) {
-    [self recordUserAction:UserMetricsAction("Options_Translate_Enable")];
-  } else {
-    [self recordUserAction:UserMetricsAction("Options_Translate_Disable")];
-  }
-  translateEnabled_.SetValue(value);
-}
-
-- (BOOL)tabsToLinks {
-  return tabsToLinks_.GetValue();
-}
-
-- (void)setTabsToLinks:(BOOL)value {
-  if (value) {
-    [self recordUserAction:UserMetricsAction("Options_TabsToLinks_Enable")];
-  } else {
-    [self recordUserAction:UserMetricsAction("Options_TabsToLinks_Disable")];
-  }
-  tabsToLinks_.SetValue(value);
-}
-
-- (void)fontAndLanguageEndSheet:(NSWindow*)sheet
-                     returnCode:(NSInteger)returnCode
-                    contextInfo:(void*)context {
-  [sheet close];
-  [sheet orderOut:self];
-  fontLanguageSettings_ = nil;
-}
-
-- (IBAction)changeFontAndLanguageSettings:(id)sender {
-  // Intentionally leak the controller as it will clean itself up when the
-  // sheet closes.
-  fontLanguageSettings_ =
-      [[FontLanguageSettingsController alloc] initWithProfile:profile_];
-  [NSApp beginSheet:[fontLanguageSettings_ window]
-     modalForWindow:[self window]
-      modalDelegate:self
-     didEndSelector:@selector(fontAndLanguageEndSheet:returnCode:contextInfo:)
-        contextInfo:nil];
-}
-
-// Called to launch the Keychain Access app to show the user's stored
-// certificates. Note there's no way to script the app to auto-select the
-// certificates.
-- (IBAction)showCertificates:(id)sender {
-  [self recordUserAction:UserMetricsAction("Options_ManagerCerts")];
-  [self launchKeychainAccess];
-}
-
-- (IBAction)resetToDefaults:(id)sender {
-  // The alert will clean itself up in the did-end selector.
-  NSAlert* alert = [[NSAlert alloc] init];
-  [alert setMessageText:l10n_util::GetNSString(IDS_OPTIONS_RESET_MESSAGE)];
-  NSButton* resetButton = [alert addButtonWithTitle:
-      l10n_util::GetNSString(IDS_OPTIONS_RESET_OKLABEL)];
-  [resetButton setKeyEquivalent:@""];
-  NSButton* cancelButton = [alert addButtonWithTitle:
-      l10n_util::GetNSString(IDS_OPTIONS_RESET_CANCELLABEL)];
-  [cancelButton setKeyEquivalent:@"\r"];
-
-  [alert beginSheetModalForWindow:[self window]
-                    modalDelegate:self
-                   didEndSelector:@selector(resetToDefaults:returned:context:)
-                      contextInfo:nil];
-}
-
-- (void)resetToDefaults:(NSAlert*)alert
-               returned:(NSInteger)code
-                context:(void*)context {
-  if (code == NSAlertFirstButtonReturn) {
-    OptionsUtil::ResetToDefaults(profile_);
-  }
-  [alert autorelease];
-}
-
-//-------------------------------------------------------------------------
-
-// Callback when preferences are changed. |prefName| is the name of the
-// pref that has changed and should not be NULL.
-- (void)prefChanged:(std::string*)prefName {
-  DCHECK(prefName);
-  if (!prefName) return;
-  [self basicsPrefChanged:prefName];
-  [self userDataPrefChanged:prefName];
-  [self underHoodPrefChanged:prefName];
-}
-
-// Callback when sync service state has changed.
-//
-// TODO(akalin): Decomp this out since a lot of it is copied from the
-// Windows version.
-// TODO(akalin): Change the background of the status label/link on error.
-- (void)syncStateChanged {
-  DCHECK(syncService_);
-
-  string16 statusLabel, linkLabel;
-  sync_ui_util::MessageType status =
-      sync_ui_util::GetStatusLabels(syncService_, &statusLabel, &linkLabel);
-  bool managed = syncService_->IsManaged();
-
-  [syncButton_ setEnabled:!syncService_->WizardIsVisible()];
-  NSString* buttonLabel;
-  if (syncService_->HasSyncSetupCompleted()) {
-    buttonLabel = l10n_util::GetNSStringWithFixup(
-        IDS_SYNC_STOP_SYNCING_BUTTON_LABEL);
-    [syncCustomizeButton_ setHidden:false];
-  } else if (syncService_->SetupInProgress()) {
-    buttonLabel = l10n_util::GetNSStringWithFixup(
-        IDS_SYNC_NTP_SETUP_IN_PROGRESS);
-    [syncCustomizeButton_ setHidden:true];
-  } else {
-    buttonLabel = l10n_util::GetNSStringWithFixup(
-        IDS_SYNC_START_SYNC_BUTTON_LABEL);
-    [syncCustomizeButton_ setHidden:true];
-  }
-  [syncCustomizeButton_ setEnabled:!managed];
-  [syncButton_ setTitle:buttonLabel];
-  [syncButton_ setEnabled:!managed];
-
-  [syncStatus_ setStringValue:base::SysUTF16ToNSString(statusLabel)];
-  [syncLink_ setHidden:linkLabel.empty()];
-  [syncLink_ setTitle:base::SysUTF16ToNSString(linkLabel)];
-  [syncLink_ setEnabled:!managed];
-
-  NSButtonCell* syncLinkCell = static_cast<NSButtonCell*>([syncLink_ cell]);
-  if (!syncStatusNoErrorBackgroundColor_) {
-    DCHECK(!syncLinkNoErrorBackgroundColor_);
-    // We assume that the sync controls start off in a non-error
-    // state.
-    syncStatusNoErrorBackgroundColor_.reset(
-        [[syncStatus_ backgroundColor] retain]);
-    syncLinkNoErrorBackgroundColor_.reset(
-        [[syncLinkCell backgroundColor] retain]);
-  }
-  if (status == sync_ui_util::SYNC_ERROR) {
-    [syncStatus_ setBackgroundColor:syncErrorBackgroundColor_];
-    [syncLinkCell setBackgroundColor:syncErrorBackgroundColor_];
-  } else {
-    [syncStatus_ setBackgroundColor:syncStatusNoErrorBackgroundColor_];
-    [syncLinkCell setBackgroundColor:syncLinkNoErrorBackgroundColor_];
-  }
-}
-
-// Show the preferences window.
-- (IBAction)showPreferences:(id)sender {
-  [self showWindow:sender];
-}
-
-- (IBAction)toolbarButtonSelected:(id)sender {
-  DCHECK([sender isKindOfClass:[NSToolbarItem class]]);
-  OptionsPage page = [self getPageForToolbarItem:sender];
-  [self displayPreferenceViewForPage:page animate:YES];
-}
-
-// Helper to update the window to display a preferences view for a page.
-- (void)displayPreferenceViewForPage:(OptionsPage)page
-                             animate:(BOOL)animate {
-  NSWindow* prefsWindow = [self window];
-
-  // Needs to go *after* the call to [self window], which triggers
-  // awakeFromNib if necessary.
-  NSView* prefsView = [self getPrefsViewForPage:page];
-  NSView* contentView = [prefsWindow contentView];
-
-  // Make sure we aren't being told to display the same thing again.
-  if (currentPrefsView_ == prefsView &&
-      managedPrefsBannerVisible_ == bannerState_->IsVisible()) {
-    return;
-  }
-
-  // Remember new options page as current page.
-  if (page != OPTIONS_PAGE_DEFAULT)
-    lastSelectedPage_.SetValue(page);
-
-  // Stop any running animation, and reset the subviews to the new state. We
-  // re-add any views we need for animation later.
-  [animation_ stopAnimation];
-  NSView* oldPrefsView = currentPrefsView_;
-  currentPrefsView_ = prefsView;
-  [self resetSubViews];
-
-  // Update the banner state.
-  [self initBannerStateForPage:page];
-  BOOL showBanner = bannerState_->IsVisible();
-
-  // Update the window title.
-  NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page];
-  [prefsWindow setTitle:[toolbarItem label]];
-
-  // Calculate new frames for the subviews.
-  NSRect prefsViewFrame = [prefsView frame];
-  NSRect contentViewFrame = [contentView frame];
-  NSRect bannerViewFrame = [managedPrefsBannerView_ frame];
-
-  // Determine what height the managed prefs banner will use.
-  CGFloat bannerViewHeight = showBanner ? NSHeight(bannerViewFrame) : 0.0;
-
-  if (animate) {
-    // NSViewAnimation doesn't seem to honor subview resizing as it animates the
-    // Window's frame.  So instead of trying to get the top in the right place,
-    // just set the origin where it should be at the end, and let the fade/size
-    // slide things into the right spot.
-    prefsViewFrame.origin.y = 0.0;
-  } else {
-    // The prefView is anchored to the top of its parent, so set its origin so
-    // that the top is where it should be.  When the window's frame is set, the
-    // origin will be adjusted to keep it in the right spot.
-    prefsViewFrame.origin.y = NSHeight(contentViewFrame) -
-        NSHeight(prefsViewFrame) - bannerViewHeight;
-  }
-  bannerViewFrame.origin.y = NSHeight(prefsViewFrame);
-  bannerViewFrame.size.width = NSWidth(contentViewFrame);
-  [prefsView setFrame:prefsViewFrame];
-
-  // Figure out the size of the window.
-  NSRect windowFrame = [contentView convertRect:[prefsWindow frame]
-                                       fromView:nil];
-  CGFloat titleToolbarHeight =
-      NSHeight(windowFrame) - NSHeight(contentViewFrame);
-  windowFrame.size.height =
-      NSHeight(prefsViewFrame) + titleToolbarHeight + bannerViewHeight;
-  DCHECK_GE(NSWidth(windowFrame), NSWidth(prefsViewFrame))
-      << "Initial width set wasn't wide enough.";
-  windowFrame = [contentView convertRect:windowFrame toView:nil];
-  windowFrame.origin.y = NSMaxY([prefsWindow frame]) - NSHeight(windowFrame);
-
-  // Now change the size.
-  if (animate) {
-    NSMutableArray* animations = [NSMutableArray arrayWithCapacity:4];
-    if (oldPrefsView != prefsView) {
-      // Fade between prefs views if they change.
-      [contentView addSubview:oldPrefsView
-                   positioned:NSWindowBelow
-                   relativeTo:nil];
-      [animations addObject:
-          [NSDictionary dictionaryWithObjectsAndKeys:
-              oldPrefsView, NSViewAnimationTargetKey,
-              NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey,
-              nil]];
-      [animations addObject:
-          [NSDictionary dictionaryWithObjectsAndKeys:
-              prefsView, NSViewAnimationTargetKey,
-              NSViewAnimationFadeInEffect, NSViewAnimationEffectKey,
-              nil]];
-    } else {
-      // Make sure the prefs pane ends up in the right position in case we
-      // manipulate the banner.
-      [animations addObject:
-          [NSDictionary dictionaryWithObjectsAndKeys:
-              prefsView, NSViewAnimationTargetKey,
-              [NSValue valueWithRect:prefsViewFrame],
-                  NSViewAnimationEndFrameKey,
-              nil]];
-    }
-    if (showBanner != managedPrefsBannerVisible_) {
-      // Slide the warning banner in or out of view.
-      [animations addObject:
-          [NSDictionary dictionaryWithObjectsAndKeys:
-              managedPrefsBannerView_, NSViewAnimationTargetKey,
-              [NSValue valueWithRect:bannerViewFrame],
-                  NSViewAnimationEndFrameKey,
-              nil]];
-    }
-    // Window resize animation.
-    [animations addObject:
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            prefsWindow, NSViewAnimationTargetKey,
-            [NSValue valueWithRect:windowFrame], NSViewAnimationEndFrameKey,
-            nil]];
-    [animation_ setViewAnimations:animations];
-    // The default duration is 0.5s, which actually feels slow in here, so speed
-    // it up a bit.
-    [animation_ gtm_setDuration:0.2
-                      eventMask:NSLeftMouseUpMask];
-    [animation_ startAnimation];
-  } else {
-    // If not animating, odds are we don't want to display either (because it
-    // is initial window setup).
-    [prefsWindow setFrame:windowFrame display:NO];
-    [managedPrefsBannerView_ setFrame:bannerViewFrame];
-  }
-
-  managedPrefsBannerVisible_ = showBanner;
-}
-
-- (void)resetSubViews {
-  // Reset subviews to current prefs view and banner, remove any views that
-  // might have been left over from previous state or animation.
-  NSArray* subviews = [NSArray arrayWithObjects:
-                          currentPrefsView_, managedPrefsBannerView_, nil];
-  [[[self window] contentView] setSubviews:subviews];
-  [[self window] setInitialFirstResponder:currentPrefsView_];
-}
-
-- (void)animationDidEnd:(NSAnimation*)animation {
-  DCHECK_EQ(animation_.get(), animation);
-  // Animation finished, reset subviews to current prefs view and the banner.
-  [self resetSubViews];
-}
-
-// Reinitializes the banner state tracker object to watch for managed bits of
-// preferences relevant to the given options |page|.
-- (void)initBannerStateForPage:(OptionsPage)page {
-  page = [self normalizePage:page];
-
-  // During unit tests, there is no local state object, so we fall back to
-  // the prefs object (where we've explicitly registered this pref so we
-  // know it's there).
-  PrefService* local = g_browser_process->local_state();
-  if (!local)
-    local = prefs_;
-  bannerState_.reset(
-      new PreferencesWindowControllerInternal::ManagedPrefsBannerState(
-          self, page, local, prefs_));
-}
-
-- (void)switchToPage:(OptionsPage)page animate:(BOOL)animate {
-  [self displayPreferenceViewForPage:page animate:animate];
-  NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page];
-  [toolbar_ setSelectedItemIdentifier:[toolbarItem itemIdentifier]];
-}
-
-// Called when the window is being closed. Send out a notification that the user
-// is done editing preferences. Make sure there are no pending field editors
-// by clearing the first responder.
-- (void)windowWillClose:(NSNotification*)notification {
-  // Setting the first responder to the window ends any in-progress field
-  // editor. This will update the model appropriately so there's nothing left
-  // to do.
-  if (![[self window] makeFirstResponder:[self window]]) {
-    // We've hit a recalcitrant field editor, force it to go away.
-    [[self window] endEditingFor:nil];
-  }
-  [self autorelease];
-}
-
-- (void)controlTextDidEndEditing:(NSNotification*)notification {
-  [customPagesSource_ validateURLs];
-}
-
-@end
-
-@implementation PreferencesWindowController(Testing)
-
-- (IntegerPrefMember*)lastSelectedPage {
-  return &lastSelectedPage_;
-}
-
-- (NSToolbar*)toolbar {
-  return toolbar_;
-}
-
-- (NSView*)basicsView {
-  return basicsView_;
-}
-
-- (NSView*)personalStuffView {
-  return personalStuffView_;
-}
-
-- (NSView*)underTheHoodView {
-  return underTheHoodView_;
-}
-
-- (OptionsPage)normalizePage:(OptionsPage)page {
-  if (page == OPTIONS_PAGE_DEFAULT) {
-    // Get the last visited page from local state.
-    page = static_cast<OptionsPage>(lastSelectedPage_.GetValue());
-    if (page == OPTIONS_PAGE_DEFAULT) {
-      page = OPTIONS_PAGE_GENERAL;
-    }
-  }
-  return page;
-}
-
-- (NSToolbarItem*)getToolbarItemForPage:(OptionsPage)page {
-  NSUInteger pageIndex = (NSUInteger)[self normalizePage:page];
-  NSArray* items = [toolbar_ items];
-  NSUInteger itemCount = [items count];
-  DCHECK_GE(pageIndex, 0U);
-  if (pageIndex >= itemCount) {
-    NOTIMPLEMENTED();
-    pageIndex = 0;
-  }
-  DCHECK_GT(itemCount, 0U);
-  return [items objectAtIndex:pageIndex];
-}
-
-- (OptionsPage)getPageForToolbarItem:(NSToolbarItem*)toolbarItem {
-  // Tags are set in the nib file.
-  switch ([toolbarItem tag]) {
-    case 0:  // Basics
-      return OPTIONS_PAGE_GENERAL;
-    case 1:  // Personal Stuff
-      return OPTIONS_PAGE_CONTENT;
-    case 2:  // Under the Hood
-      return OPTIONS_PAGE_ADVANCED;
-    default:
-      NOTIMPLEMENTED();
-      return OPTIONS_PAGE_GENERAL;
-  }
-}
-
-- (NSView*)getPrefsViewForPage:(OptionsPage)page {
-  // The views will be NULL if this is mistakenly called before awakeFromNib.
-  DCHECK(basicsView_);
-  DCHECK(personalStuffView_);
-  DCHECK(underTheHoodView_);
-  page = [self normalizePage:page];
-  switch (page) {
-    case OPTIONS_PAGE_GENERAL:
-      return basicsView_;
-    case OPTIONS_PAGE_CONTENT:
-      return personalStuffView_;
-    case OPTIONS_PAGE_ADVANCED:
-      return underTheHoodView_;
-    case OPTIONS_PAGE_DEFAULT:
-    case OPTIONS_PAGE_COUNT:
-      LOG(DFATAL) << "Invalid page value " << page;
-  }
-  return basicsView_;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/preferences_window_controller_unittest.mm b/chrome/browser/ui/cocoa/preferences_window_controller_unittest.mm
deleted file mode 100644
index bbb1746..0000000
--- a/chrome/browser/ui/cocoa/preferences_window_controller_unittest.mm
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/preferences_window_controller.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/custom_home_pages_model.h"
-#include "chrome/browser/ui/options/options_window.h"
-#include "chrome/common/pref_names.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-// Helper Objective-C object that sets a BOOL when we get a particular
-// callback from the prefs window.
-@interface PrefsClosedObserver : NSObject {
- @public
-  BOOL gotNotification_;
-}
-- (void)prefsWindowClosed:(NSNotification*)notify;
-@end
-
-@implementation PrefsClosedObserver
-- (void)prefsWindowClosed:(NSNotification*)notify {
-  gotNotification_ = YES;
-}
-@end
-
-namespace {
-
-class PrefsControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    // The metrics reporting pref is registerd on the local state object in
-    // real builds, but we don't have one of those for unit tests. Register
-    // it on prefs so we'll find it when we go looking.
-    PrefService* prefs = browser_helper_.profile()->GetPrefs();
-    prefs->RegisterBooleanPref(prefs::kMetricsReportingEnabled, false);
-
-    pref_controller_ = [[PreferencesWindowController alloc]
-                         initWithProfile:browser_helper_.profile()
-                             initialPage:OPTIONS_PAGE_DEFAULT];
-    EXPECT_TRUE(pref_controller_);
-  }
-
-  virtual void TearDown() {
-    [pref_controller_ close];
-    CocoaTest::TearDown();
-  }
-
-  BrowserTestHelper browser_helper_;
-  PreferencesWindowController* pref_controller_;
-};
-
-// Test showing the preferences window and making sure it's visible, then
-// making sure we get the notification when it's closed.
-TEST_F(PrefsControllerTest, ShowAndClose) {
-  [pref_controller_ showPreferences:nil];
-  EXPECT_TRUE([[pref_controller_ window] isVisible]);
-
-  scoped_nsobject<PrefsClosedObserver> observer(
-      [[PrefsClosedObserver alloc] init]);
-  NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
-  [defaultCenter addObserver:observer.get()
-                    selector:@selector(prefsWindowClosed:)
-                        name:NSWindowWillCloseNotification
-                      object:[pref_controller_ window]];
-  [[pref_controller_ window] performClose:observer];
-  EXPECT_TRUE(observer.get()->gotNotification_);
-  [defaultCenter removeObserver:observer.get()];
-
-  // Prevent pref_controller_ from being closed again in TearDown()
-  pref_controller_ = nil;
-}
-
-TEST_F(PrefsControllerTest, ValidateCustomHomePagesTable) {
-  // First, insert two valid URLs into the CustomHomePagesModel.
-  GURL url1("http://www.google.com/");
-  GURL url2("http://maps.google.com/");
-  std::vector<GURL> urls;
-  urls.push_back(url1);
-  urls.push_back(url2);
-  [[pref_controller_ customPagesSource] setURLs:urls];
-  EXPECT_EQ(2U, [[pref_controller_ customPagesSource] countOfCustomHomePages]);
-
-  // Now insert a bad (empty) URL into the model.
-  [[pref_controller_ customPagesSource] setURLStringEmptyAt:1];
-
-  // Send a notification to simulate the end of editing on a cell in the table
-  // which should trigger validation.
-  [pref_controller_ controlTextDidEndEditing:[NSNotification
-      notificationWithName:NSControlTextDidEndEditingNotification
-                    object:nil]];
-  EXPECT_EQ(1U, [[pref_controller_ customPagesSource] countOfCustomHomePages]);
-}
-
-TEST_F(PrefsControllerTest, NormalizePage) {
-  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
-            [pref_controller_ normalizePage:OPTIONS_PAGE_GENERAL]);
-  EXPECT_EQ(OPTIONS_PAGE_CONTENT,
-            [pref_controller_ normalizePage:OPTIONS_PAGE_CONTENT]);
-  EXPECT_EQ(OPTIONS_PAGE_ADVANCED,
-            [pref_controller_ normalizePage:OPTIONS_PAGE_ADVANCED]);
-
-  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_ADVANCED);
-  EXPECT_EQ(OPTIONS_PAGE_ADVANCED,
-            [pref_controller_ normalizePage:OPTIONS_PAGE_DEFAULT]);
-
-  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_DEFAULT);
-  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
-            [pref_controller_ normalizePage:OPTIONS_PAGE_DEFAULT]);
-}
-
-TEST_F(PrefsControllerTest, GetToolbarItemForPage) {
-  // Trigger awakeFromNib.
-  [pref_controller_ window];
-
-  NSArray* toolbarItems = [[pref_controller_ toolbar] items];
-  EXPECT_EQ([toolbarItems objectAtIndex:0],
-            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_GENERAL]);
-  EXPECT_EQ([toolbarItems objectAtIndex:1],
-            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_CONTENT]);
-  EXPECT_EQ([toolbarItems objectAtIndex:2],
-            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_ADVANCED]);
-
-  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_ADVANCED);
-  EXPECT_EQ([toolbarItems objectAtIndex:2],
-            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_DEFAULT]);
-
-  // Out-of-range argument.
-  EXPECT_EQ([toolbarItems objectAtIndex:0],
-            [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_COUNT]);
-}
-
-TEST_F(PrefsControllerTest, GetPageForToolbarItem) {
-  scoped_nsobject<NSToolbarItem> toolbarItem(
-      [[NSToolbarItem alloc] initWithItemIdentifier:@""]);
-  [toolbarItem setTag:0];
-  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
-            [pref_controller_ getPageForToolbarItem:toolbarItem]);
-  [toolbarItem setTag:1];
-  EXPECT_EQ(OPTIONS_PAGE_CONTENT,
-            [pref_controller_ getPageForToolbarItem:toolbarItem]);
-  [toolbarItem setTag:2];
-  EXPECT_EQ(OPTIONS_PAGE_ADVANCED,
-            [pref_controller_ getPageForToolbarItem:toolbarItem]);
-
-  // Out-of-range argument.
-  [toolbarItem setTag:3];
-  EXPECT_EQ(OPTIONS_PAGE_GENERAL,
-            [pref_controller_ getPageForToolbarItem:toolbarItem]);
-}
-
-TEST_F(PrefsControllerTest, GetPrefsViewForPage) {
-  // Trigger awakeFromNib.
-  [pref_controller_ window];
-
-  EXPECT_EQ([pref_controller_ basicsView],
-            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_GENERAL]);
-  EXPECT_EQ([pref_controller_ personalStuffView],
-            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_CONTENT]);
-  EXPECT_EQ([pref_controller_ underTheHoodView],
-            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_ADVANCED]);
-
-  [pref_controller_ lastSelectedPage]->SetValue(OPTIONS_PAGE_ADVANCED);
-  EXPECT_EQ([pref_controller_ underTheHoodView],
-            [pref_controller_ getPrefsViewForPage:OPTIONS_PAGE_DEFAULT]);
-}
-
-TEST_F(PrefsControllerTest, SwitchToPage) {
-  // Trigger awakeFromNib.
-  NSWindow* window = [pref_controller_ window];
-
-  NSView* contentView = [window contentView];
-  NSView* basicsView = [pref_controller_ basicsView];
-  NSView* personalStuffView = [pref_controller_ personalStuffView];
-  NSView* underTheHoodView = [pref_controller_ underTheHoodView];
-  NSToolbar* toolbar = [pref_controller_ toolbar];
-  NSToolbarItem* basicsToolbarItem =
-      [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_GENERAL];
-  NSToolbarItem* personalStuffToolbarItem =
-      [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_CONTENT];
-  NSToolbarItem* underTheHoodToolbarItem =
-      [pref_controller_ getToolbarItemForPage:OPTIONS_PAGE_ADVANCED];
-  NSString* basicsIdentifier = [basicsToolbarItem itemIdentifier];
-  NSString* personalStuffIdentifier = [personalStuffToolbarItem itemIdentifier];
-  NSString* underTheHoodIdentifier = [underTheHoodToolbarItem itemIdentifier];
-  IntegerPrefMember* lastSelectedPage = [pref_controller_ lastSelectedPage];
-
-  // Test without animation.
-
-  [pref_controller_ switchToPage:OPTIONS_PAGE_GENERAL animate:NO];
-  EXPECT_TRUE([basicsView isDescendantOf:contentView]);
-  EXPECT_FALSE([personalStuffView isDescendantOf:contentView]);
-  EXPECT_FALSE([underTheHoodView isDescendantOf:contentView]);
-  EXPECT_NSEQ(basicsIdentifier, [toolbar selectedItemIdentifier]);
-  EXPECT_EQ(OPTIONS_PAGE_GENERAL, lastSelectedPage->GetValue());
-  EXPECT_NSEQ([basicsToolbarItem label], [window title]);
-
-  [pref_controller_ switchToPage:OPTIONS_PAGE_CONTENT animate:NO];
-  EXPECT_FALSE([basicsView isDescendantOf:contentView]);
-  EXPECT_TRUE([personalStuffView isDescendantOf:contentView]);
-  EXPECT_FALSE([underTheHoodView isDescendantOf:contentView]);
-  EXPECT_NSEQ([toolbar selectedItemIdentifier], personalStuffIdentifier);
-  EXPECT_EQ(OPTIONS_PAGE_CONTENT, lastSelectedPage->GetValue());
-  EXPECT_NSEQ([personalStuffToolbarItem label], [window title]);
-
-  [pref_controller_ switchToPage:OPTIONS_PAGE_ADVANCED animate:NO];
-  EXPECT_FALSE([basicsView isDescendantOf:contentView]);
-  EXPECT_FALSE([personalStuffView isDescendantOf:contentView]);
-  EXPECT_TRUE([underTheHoodView isDescendantOf:contentView]);
-  EXPECT_NSEQ([toolbar selectedItemIdentifier], underTheHoodIdentifier);
-  EXPECT_EQ(OPTIONS_PAGE_ADVANCED, lastSelectedPage->GetValue());
-  EXPECT_NSEQ([underTheHoodToolbarItem label], [window title]);
-
-  // Test OPTIONS_PAGE_DEFAULT.
-
-  lastSelectedPage->SetValue(OPTIONS_PAGE_CONTENT);
-  [pref_controller_ switchToPage:OPTIONS_PAGE_DEFAULT animate:NO];
-  EXPECT_FALSE([basicsView isDescendantOf:contentView]);
-  EXPECT_TRUE([personalStuffView isDescendantOf:contentView]);
-  EXPECT_FALSE([underTheHoodView isDescendantOf:contentView]);
-  EXPECT_NSEQ(personalStuffIdentifier, [toolbar selectedItemIdentifier]);
-  EXPECT_EQ(OPTIONS_PAGE_CONTENT, lastSelectedPage->GetValue());
-  EXPECT_NSEQ([personalStuffToolbarItem label], [window title]);
-
-  // TODO(akalin): Figure out how to test animation; we'll need everything
-  // to stick around until the animation finishes.
-}
-
-// TODO(akalin): Figure out how to test sync controls.
-// TODO(akalin): Figure out how to test that sync controls are not shown
-// when there isn't a sync service.
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/previewable_contents_controller.h b/chrome/browser/ui/cocoa/previewable_contents_controller.h
deleted file mode 100644
index 01643f0..0000000
--- a/chrome/browser/ui/cocoa/previewable_contents_controller.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_PREVIEWABLE_CONTENTS_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_PREVIEWABLE_CONTENTS_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-class TabContents;
-
-// PreviewableContentsController manages the display of up to two tab contents
-// views.  It is primarily for use with Instant results.  This class supports
-// the notion of an "active" view vs. a "preview" tab contents view.
-//
-// The "active" view is a container view that can be retrieved using
-// |-activeContainer|.  Its contents are meant to be managed by an external
-// class.
-//
-// The "preview" can be set using |-showPreview:| and |-hidePreview|.  When a
-// preview is set, the active view is hidden (but stays in the view hierarchy).
-// When the preview is removed, the active view is reshown.
-@interface PreviewableContentsController : NSViewController {
- @private
-  // Container view for the "active" contents.
-  IBOutlet NSView* activeContainer_;
-
-  // The preview TabContents.  Will be NULL if no preview is currently showing.
-  TabContents* previewContents_;  // weak
-}
-
-@property(readonly, nonatomic) NSView* activeContainer;
-
-// Sets the current preview and installs its TabContentsView into the view
-// hierarchy.  Hides the active view.  |preview| must not be NULL.
-- (void)showPreview:(TabContents*)preview;
-
-// Closes the current preview and shows the active view.
-- (void)hidePreview;
-
-// Returns YES if the preview contents is currently showing.
-- (BOOL)isShowingPreview;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_PREVIEWABLE_CONTENTS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/previewable_contents_controller.mm b/chrome/browser/ui/cocoa/previewable_contents_controller.mm
deleted file mode 100644
index 74e29b0..0000000
--- a/chrome/browser/ui/cocoa/previewable_contents_controller.mm
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/previewable_contents_controller.h"
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-
-@implementation PreviewableContentsController
-
-@synthesize activeContainer = activeContainer_;
-
-- (id)init {
-  if ((self = [super initWithNibName:@"PreviewableContents"
-                              bundle:base::mac::MainAppBundle()])) {
-  }
-  return self;
-}
-
-- (void)showPreview:(TabContents*)preview {
-  DCHECK(preview);
-
-  // Remove any old preview contents before showing the new one.
-  if (previewContents_)
-    [previewContents_->GetNativeView() removeFromSuperview];
-
-  previewContents_ = preview;
-  NSView* previewView = previewContents_->GetNativeView();
-  [previewView setFrame:[[self view] bounds]];
-
-  // Hide the active container and add the preview contents.
-  [activeContainer_ setHidden:YES];
-  [[self view] addSubview:previewView];
-}
-
-- (void)hidePreview {
-  DCHECK(previewContents_);
-
-  // Remove the preview contents and reshow the active container.
-  [previewContents_->GetNativeView() removeFromSuperview];
-  [activeContainer_ setHidden:NO];
-
-  previewContents_ = nil;
-}
-
-- (BOOL)isShowingPreview {
-  return previewContents_ != nil;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/previewable_contents_controller_unittest.mm b/chrome/browser/ui/cocoa/previewable_contents_controller_unittest.mm
deleted file mode 100644
index a2d9263..0000000
--- a/chrome/browser/ui/cocoa/previewable_contents_controller_unittest.mm
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/previewable_contents_controller.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class PreviewableContentsControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    controller_.reset([[PreviewableContentsController alloc] init]);
-    [[test_window() contentView] addSubview:[controller_ view]];
-  }
-
-  scoped_nsobject<PreviewableContentsController> controller_;
-};
-
-TEST_VIEW(PreviewableContentsControllerTest, [controller_ view])
-
-// TODO(rohitrao): Test showing and hiding the preview.  This may require
-// changing the interface to take in a TabContentsView* instead of a
-// TabContents*.
-
-}  // namespace
-
diff --git a/chrome/browser/ui/cocoa/reload_button.h b/chrome/browser/ui/cocoa/reload_button.h
deleted file mode 100644
index f955590..0000000
--- a/chrome/browser/ui/cocoa/reload_button.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_RELOAD_BUTTON_H_
-#define CHROME_BROWSER_UI_COCOA_RELOAD_BUTTON_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-
-// NSButton subclass which defers certain state changes when the mouse
-// is hovering over it.
-
-@interface ReloadButton : NSButton {
- @private
-  // Tracks whether the mouse is hovering for purposes of not making
-  // unexpected state changes.
-  BOOL isMouseInside_;
-  scoped_nsobject<NSTrackingArea> trackingArea_;
-
-  // Timer used when setting reload mode while the mouse is hovered.
-  scoped_nsobject<NSTimer> pendingReloadTimer_;
-}
-
-// Returns YES if the mouse is currently inside the bounds.
-- (BOOL)isMouseInside;
-
-// Update the tag, and the image and tooltip to match.  If |anInt|
-// matches the current tag, no action is taken.  |anInt| must be
-// either |IDC_STOP| or |IDC_RELOAD|.
-- (void)updateTag:(NSInteger)anInt;
-
-// Update the button to be a reload button or stop button depending on
-// |isLoading|.  If |force|, always sets the indicated mode.  If
-// |!force|, and the mouse is over the button, defer the transition
-// from stop button to reload button until the mouse has left the
-// button, or until |pendingReloadTimer_| fires.  This prevents an
-// inadvertent click _just_ as the state changes.
-- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force;
-
-@end
-
-@interface ReloadButton (PrivateTestingMethods)
-+ (void)setPendingReloadTimeout:(NSTimeInterval)seconds;
-- (NSTrackingArea*)trackingArea;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_RELOAD_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/reload_button.mm b/chrome/browser/ui/cocoa/reload_button.mm
deleted file mode 100644
index a2a60af..0000000
--- a/chrome/browser/ui/cocoa/reload_button.mm
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/reload_button.h"
-
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "app/mac/nsimage_cache.h"
-#include "chrome/app/chrome_command_ids.h"
-#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-NSString* const kReloadImageName = @"reload_Template.pdf";
-NSString* const kStopImageName = @"stop_Template.pdf";
-
-// Constant matches Windows.
-NSTimeInterval kPendingReloadTimeout = 1.35;
-
-}  // namespace
-
-@implementation ReloadButton
-
-- (void)dealloc {
-  if (trackingArea_) {
-    [self removeTrackingArea:trackingArea_];
-    trackingArea_.reset();
-  }
-  [super dealloc];
-}
-
-- (void)updateTrackingAreas {
-  // If the mouse is hovering when the tracking area is updated, the
-  // control could end up locked into inappropriate behavior for
-  // awhile, so unwind state.
-  if (isMouseInside_)
-    [self mouseExited:nil];
-
-  if (trackingArea_) {
-    [self removeTrackingArea:trackingArea_];
-    trackingArea_.reset();
-  }
-  trackingArea_.reset([[NSTrackingArea alloc]
-                        initWithRect:[self bounds]
-                             options:(NSTrackingMouseEnteredAndExited |
-                                      NSTrackingActiveInActiveApp)
-                               owner:self
-                            userInfo:nil]);
-  [self addTrackingArea:trackingArea_];
-}
-
-- (void)awakeFromNib {
-  [self updateTrackingAreas];
-
-  // Don't allow multi-clicks, because the user probably wouldn't ever
-  // want to stop+reload or reload+stop.
-  [self setIgnoresMultiClick:YES];
-}
-
-- (void)updateTag:(NSInteger)anInt {
-  if ([self tag] == anInt)
-    return;
-
-  // Forcibly remove any stale tooltip which is being displayed.
-  [self removeAllToolTips];
-
-  [self setTag:anInt];
-  if (anInt == IDC_RELOAD) {
-    [self setImage:app::mac::GetCachedImageWithName(kReloadImageName)];
-    [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_RELOAD)];
-  } else if (anInt == IDC_STOP) {
-    [self setImage:app::mac::GetCachedImageWithName(kStopImageName)];
-    [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STOP)];
-  } else {
-    NOTREACHED();
-  }
-}
-
-- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force {
-  // Can always transition to stop mode.  Only transition to reload
-  // mode if forced or if the mouse isn't hovering.  Otherwise, note
-  // that reload mode is desired and disable the button.
-  if (isLoading) {
-    pendingReloadTimer_.reset();
-    [self updateTag:IDC_STOP];
-    [self setEnabled:YES];
-  } else if (force || ![self isMouseInside]) {
-    pendingReloadTimer_.reset();
-    [self updateTag:IDC_RELOAD];
-
-    // This button's cell may not have received a mouseExited event, and
-    // therefore it could still think that the mouse is inside the button.  Make
-    // sure the cell's sense of mouse-inside matches the local sense, to prevent
-    // drawing artifacts.
-    id cell = [self cell];
-    if ([cell respondsToSelector:@selector(setMouseInside:animate:)])
-      [cell setMouseInside:[self isMouseInside] animate:NO];
-    [self setEnabled:YES];
-  } else if ([self tag] == IDC_STOP && !pendingReloadTimer_) {
-    [self setEnabled:NO];
-    pendingReloadTimer_.reset(
-        [[NSTimer scheduledTimerWithTimeInterval:kPendingReloadTimeout
-                                          target:self
-                                        selector:@selector(forceReloadState)
-                                        userInfo:nil
-                                         repeats:NO] retain]);
-  }
-}
-
-- (void)forceReloadState {
-  [self setIsLoading:NO force:YES];
-}
-
-- (BOOL)sendAction:(SEL)theAction to:(id)theTarget {
-  if ([self tag] == IDC_STOP) {
-    // When the timer is started, the button is disabled, so this
-    // should not be possible.
-    DCHECK(!pendingReloadTimer_.get());
-
-    // When the stop is processed, immediately change to reload mode,
-    // even though the IPC still has to bounce off the renderer and
-    // back before the regular |-setIsLoaded:force:| will be called.
-    // [This is how views and gtk do it.]
-    const BOOL ret = [super sendAction:theAction to:theTarget];
-    if (ret)
-      [self forceReloadState];
-    return ret;
-  }
-
-  return [super sendAction:theAction to:theTarget];
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent {
-  isMouseInside_ = YES;
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
-  isMouseInside_ = NO;
-
-  // Reload mode was requested during the hover.
-  if (pendingReloadTimer_)
-    [self forceReloadState];
-}
-
-- (BOOL)isMouseInside {
-  return isMouseInside_;
-}
-
-- (ViewID)viewID {
-  return VIEW_ID_RELOAD_BUTTON;
-}
-
-@end  // ReloadButton
-
-@implementation ReloadButton (Testing)
-
-+ (void)setPendingReloadTimeout:(NSTimeInterval)seconds {
-  kPendingReloadTimeout = seconds;
-}
-
-- (NSTrackingArea*)trackingArea {
-  return trackingArea_;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/reload_button_unittest.mm b/chrome/browser/ui/cocoa/reload_button_unittest.mm
deleted file mode 100644
index 386a503..0000000
--- a/chrome/browser/ui/cocoa/reload_button_unittest.mm
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/ui/cocoa/reload_button.h"
-
-#include "base/scoped_nsobject.h"
-#include "chrome/app/chrome_command_ids.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/test_event_utils.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-
-@protocol TargetActionMock <NSObject>
-- (void)anAction:(id)sender;
-@end
-
-namespace {
-
-class ReloadButtonTest : public CocoaTest {
- public:
-  ReloadButtonTest() {
-    NSRect frame = NSMakeRect(0, 0, 20, 20);
-    scoped_nsobject<ReloadButton> button(
-        [[ReloadButton alloc] initWithFrame:frame]);
-    button_ = button.get();
-
-    // Set things up so unit tests have a reliable baseline.
-    [button_ setTag:IDC_RELOAD];
-    [button_ awakeFromNib];
-
-    [[test_window() contentView] addSubview:button_];
-  }
-
-  ReloadButton* button_;
-};
-
-TEST_VIEW(ReloadButtonTest, button_)
-
-// Test that mouse-tracking is setup and does the right thing.
-TEST_F(ReloadButtonTest, IsMouseInside) {
-  EXPECT_TRUE([[button_ trackingAreas] containsObject:[button_ trackingArea]]);
-
-  EXPECT_FALSE([button_ isMouseInside]);
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ mouseExited:nil];
-}
-
-// Verify that multiple clicks do not result in multiple messages to
-// the target.
-TEST_F(ReloadButtonTest, IgnoredMultiClick) {
-  id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)];
-  [button_ setTarget:mock_target];
-  [button_ setAction:@selector(anAction:)];
-
-  // Expect the action once.
-  [[mock_target expect] anAction:button_];
-
-  const std::pair<NSEvent*,NSEvent*> click_one =
-      test_event_utils::MouseClickInView(button_, 1);
-  const std::pair<NSEvent*,NSEvent*> click_two =
-      test_event_utils::MouseClickInView(button_, 2);
-  [NSApp postEvent:click_one.second atStart:YES];
-  [button_ mouseDown:click_one.first];
-  [NSApp postEvent:click_two.second atStart:YES];
-  [button_ mouseDown:click_two.first];
-
-  [button_ setTarget:nil];
-}
-
-TEST_F(ReloadButtonTest, UpdateTag) {
-  [button_ setTag:IDC_STOP];
-
-  [button_ updateTag:IDC_RELOAD];
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-  NSImage* reloadImage = [button_ image];
-  NSString* const reloadToolTip = [button_ toolTip];
-
-  [button_ updateTag:IDC_STOP];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  NSImage* stopImage = [button_ image];
-  NSString* const stopToolTip = [button_ toolTip];
-  EXPECT_NSNE(reloadImage, stopImage);
-  EXPECT_NSNE(reloadToolTip, stopToolTip);
-
-  [button_ updateTag:IDC_RELOAD];
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-  EXPECT_NSEQ(reloadImage, [button_ image]);
-  EXPECT_NSEQ(reloadToolTip, [button_ toolTip]);
-}
-
-// Test that when forcing the mode, it takes effect immediately,
-// regardless of whether the mouse is hovering.
-TEST_F(ReloadButtonTest, SetIsLoadingForce) {
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-
-  // Changes to stop immediately.
-  [button_ setIsLoading:YES force:YES];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-
-  // Changes to reload immediately.
-  [button_ setIsLoading:NO force:YES];
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-
-  // Changes to stop immediately when the mouse is hovered, and
-  // doesn't change when the mouse exits.
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:YES force:YES];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  [button_ mouseExited:nil];
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-
-  // Changes to reload immediately when the mouse is hovered, and
-  // doesn't change when the mouse exits.
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:NO force:YES];
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-  [button_ mouseExited:nil];
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-}
-
-// Test that without force, stop mode is set immediately, but reload
-// is affected by the hover status.
-TEST_F(ReloadButtonTest, SetIsLoadingNoForceUnHover) {
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-
-  // Changes to stop immediately when the mouse is not hovering.
-  [button_ setIsLoading:YES force:NO];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-
-  // Changes to reload immediately when the mouse is not hovering.
-  [button_ setIsLoading:NO force:NO];
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-
-  // Changes to stop immediately when the mouse is hovered, and
-  // doesn't change when the mouse exits.
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:YES force:NO];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  [button_ mouseExited:nil];
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-
-  // Does not change to reload immediately when the mouse is hovered,
-  // changes when the mouse exits.
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:NO force:NO];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  [button_ mouseExited:nil];
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-}
-
-// Test that without force, stop mode is set immediately, and reload
-// will be set after a timeout.
-// TODO(shess): Reenable, http://crbug.com/61485
-TEST_F(ReloadButtonTest, DISABLED_SetIsLoadingNoForceTimeout) {
-  // When the event loop first spins, some delayed tracking-area setup
-  // is done, which causes -mouseExited: to be called.  Spin it at
-  // least once, and dequeue any pending events.
-  // TODO(shess): It would be more reasonable to have an MockNSTimer
-  // factory for the class to use, which this code could fire
-  // directly.
-  while ([NSApp nextEventMatchingMask:NSAnyEventMask
-                            untilDate:nil
-                               inMode:NSDefaultRunLoopMode
-                              dequeue:YES]) {
-  }
-
-  const NSTimeInterval kShortTimeout = 0.1;
-  [ReloadButton setPendingReloadTimeout:kShortTimeout];
-
-  EXPECT_FALSE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-
-  // Move the mouse into the button and press it.
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:YES force:NO];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-
-  // Does not change to reload immediately when the mouse is hovered.
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:NO force:NO];
-  EXPECT_TRUE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  EXPECT_TRUE([button_ isMouseInside]);
-
-  // Spin event loop until the timeout passes.
-  NSDate* pastTimeout = [NSDate dateWithTimeIntervalSinceNow:2 * kShortTimeout];
-  [NSApp nextEventMatchingMask:NSAnyEventMask
-                     untilDate:pastTimeout
-                        inMode:NSDefaultRunLoopMode
-                       dequeue:NO];
-
-  // Mouse is still hovered, button is in reload mode.  If the mouse
-  // is no longer hovered, see comment at top of function.
-  EXPECT_TRUE([button_ isMouseInside]);
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-}
-
-// Test that pressing stop after reload mode has been requested
-// doesn't forward the stop message.
-TEST_F(ReloadButtonTest, StopAfterReloadSet) {
-  id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)];
-  [button_ setTarget:mock_target];
-  [button_ setAction:@selector(anAction:)];
-
-  EXPECT_FALSE([button_ isMouseInside]);
-
-  // Get to stop mode.
-  [button_ setIsLoading:YES force:YES];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  EXPECT_TRUE([button_ isEnabled]);
-
-  // Expect the action once.
-  [[mock_target expect] anAction:button_];
-
-  // Clicking in stop mode should send the action and transition to
-  // reload mode.
-  const std::pair<NSEvent*,NSEvent*> click =
-      test_event_utils::MouseClickInView(button_, 1);
-  [NSApp postEvent:click.second atStart:YES];
-  [button_ mouseDown:click.first];
-  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
-  EXPECT_TRUE([button_ isEnabled]);
-
-  // Get back to stop mode.
-  [button_ setIsLoading:YES force:YES];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  EXPECT_TRUE([button_ isEnabled]);
-
-  // If hover prevented reload mode immediately taking effect, clicks should do
-  // nothing, because the button should be disabled.
-  [button_ mouseEntered:nil];
-  EXPECT_TRUE([button_ isMouseInside]);
-  [button_ setIsLoading:NO force:NO];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-  EXPECT_FALSE([button_ isEnabled]);
-  [NSApp postEvent:click.second atStart:YES];
-  [button_ mouseDown:click.first];
-  EXPECT_EQ(IDC_STOP, [button_ tag]);
-
-  [button_ setTarget:nil];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/repost_form_warning_mac.mm b/chrome/browser/ui/cocoa/repost_form_warning_mac.mm
index 71f292b..3bcbaf1 100644
--- a/chrome/browser/ui/cocoa/repost_form_warning_mac.mm
+++ b/chrome/browser/ui/cocoa/repost_form_warning_mac.mm
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/ui/cocoa/repost_form_warning_mac.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/scoped_nsobject.h"
 #include "chrome/browser/repost_form_warning_controller.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 // The delegate of the NSAlert used to display the dialog. Forwards the alert's
 // completion event to the C++ class |RepostFormWarningController|.
diff --git a/chrome/browser/ui/cocoa/restart_browser.h b/chrome/browser/ui/cocoa/restart_browser.h
index 27bdd35..d7e4ec1 100644
--- a/chrome/browser/ui/cocoa/restart_browser.h
+++ b/chrome/browser/ui/cocoa/restart_browser.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-// This is a functional match for chrome/browser/views/restart_message_box
+// This is a functional match for chrome/browser/ui/views/restart_message_box
 // so any code that needs to ask for a browser restart has something like what
 // the Windows code has.
 namespace restart_browser {
diff --git a/chrome/browser/ui/cocoa/restart_browser.mm b/chrome/browser/ui/cocoa/restart_browser.mm
index c88715a..7f0bd7a 100644
--- a/chrome/browser/ui/cocoa/restart_browser.mm
+++ b/chrome/browser/ui/cocoa/restart_browser.mm
@@ -4,8 +4,6 @@
 
 #import "chrome/browser/ui/cocoa/restart_browser.h"
 
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_service.h"
@@ -13,6 +11,8 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/app_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 // Helper to clean up after the notification that the alert was dismissed.
 @interface RestartHelper : NSObject {
@@ -59,14 +59,14 @@
 
 void RequestRestart(NSWindow* parent) {
   NSString* title =
-      l10n_util::GetNSStringFWithFixup(IDS_PLEASE_RESTART_BROWSER,
+      l10n_util::GetNSStringFWithFixup(IDS_PLEASE_RELAUNCH_BROWSER,
           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
   NSString* text =
       l10n_util::GetNSStringFWithFixup(IDS_UPDATE_RECOMMENDED,
           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
   NSString* notNowButtin = l10n_util::GetNSStringWithFixup(IDS_NOT_NOW);
   NSString* restartButton =
-      l10n_util::GetNSStringWithFixup(IDS_RESTART_AND_UPDATE);
+      l10n_util::GetNSStringWithFixup(IDS_RELAUNCH_AND_UPDATE);
 
   RestartHelper* helper = [[RestartHelper alloc] init];
 
@@ -77,10 +77,19 @@
   [alert addButtonWithTitle:notNowButtin];
   [alert addButtonWithTitle:restartButton];
 
-  [alert beginSheetModalForWindow:parent
-                    modalDelegate:helper
-                   didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
-                      contextInfo:nil];
+  if (parent) {
+    [alert beginSheetModalForWindow:parent
+                      modalDelegate:helper
+                     didEndSelector:@selector(alertDidEnd:
+                                               returnCode:
+                                              contextInfo:)
+                        contextInfo:nil];
+  } else {
+    NSInteger returnCode = [alert runModal];
+    [helper alertDidEnd:alert
+             returnCode:returnCode
+            contextInfo:NULL];
+  }
 }
 
 }  // namespace restart_browser
diff --git a/chrome/browser/ui/cocoa/sad_tab_controller.h b/chrome/browser/ui/cocoa/sad_tab_controller.h
deleted file mode 100644
index 35e9aaf..0000000
--- a/chrome/browser/ui/cocoa/sad_tab_controller.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_SAD_TAB_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_SAD_TAB_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-class TabContents;
-
-// A controller class that manages the SadTabView (aka "Aw Snap" or crash page).
-@interface SadTabController : NSViewController {
- @private
-  TabContents* tabContents_;  // Weak reference.
-}
-
-// Designated initializer is initWithTabContents.
-- (id)initWithTabContents:(TabContents*)someTabContents
-                superview:(NSView*)superview;
-
-// This action just calls the NSApp sendAction to get it into the standard
-// Cocoa action processing.
-- (IBAction)openLearnMoreAboutCrashLink:(id)sender;
-
-// Returns a weak reference to the TabContents whose TabContentsView created
-// this SadTabController.
-- (TabContents*)tabContents;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_SAD_TAB_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/sad_tab_controller.mm b/chrome/browser/ui/cocoa/sad_tab_controller.mm
deleted file mode 100644
index e340a9c..0000000
--- a/chrome/browser/ui/cocoa/sad_tab_controller.mm
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/sad_tab_controller.h"
-
-#include "base/mac/mac_util.h"
-#import "chrome/browser/ui/cocoa/sad_tab_view.h"
-
-@implementation SadTabController
-
-- (id)initWithTabContents:(TabContents*)someTabContents
-                superview:(NSView*)superview {
-  if ((self = [super initWithNibName:@"SadTab"
-                              bundle:base::mac::MainAppBundle()])) {
-    tabContents_ = someTabContents;
-
-    NSView* view = [self view];
-    [superview addSubview:view];
-    [view setFrame:[superview bounds]];
-  }
-
-  return self;
-}
-
-- (void)awakeFromNib {
-  // If tab_contents_ is nil, ask view to remove link.
-  if (!tabContents_) {
-    SadTabView* sad_view = static_cast<SadTabView*>([self view]);
-    [sad_view removeLinkButton];
-  }
-}
-
-- (void)dealloc {
-  [[self view] removeFromSuperview];
-  [super dealloc];
-}
-
-- (TabContents*)tabContents {
-  return tabContents_;
-}
-
-- (void)openLearnMoreAboutCrashLink:(id)sender {
-  // Send the action up through the responder chain.
-  [NSApp sendAction:@selector(openLearnMoreAboutCrashLink:) to:nil from:self];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/sad_tab_controller_unittest.mm b/chrome/browser/ui/cocoa/sad_tab_controller_unittest.mm
deleted file mode 100644
index 15839a8..0000000
--- a/chrome/browser/ui/cocoa/sad_tab_controller_unittest.mm
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/debug/debugger.h"
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/sad_tab_controller.h"
-#import "chrome/browser/ui/cocoa/sad_tab_view.h"
-#include "chrome/browser/renderer_host/test/test_render_view_host.h"
-#include "chrome/browser/tab_contents/test_tab_contents.h"
-#include "chrome/test/testing_profile.h"
-
-@interface SadTabView (ExposedForTesting)
-// Implementation is below.
-- (NSButton*)linkButton;
-@end
-
-@implementation SadTabView (ExposedForTesting)
-- (NSButton*)linkButton {
-  return linkButton_;
-}
-@end
-
-namespace {
-
-class SadTabControllerTest : public RenderViewHostTestHarness {
- public:
-  SadTabControllerTest() : test_window_(nil) {
-    link_clicked_ = false;
-  }
-
-  virtual void SetUp() {
-    RenderViewHostTestHarness::SetUp();
-    // Inherting from RenderViewHostTestHarness means we can't inherit from
-    // from CocoaTest, so do a bootstrap and create test window.
-    CocoaTest::BootstrapCocoa();
-    test_window_ = [[CocoaTestHelperWindow alloc] init];
-    if (base::debug::BeingDebugged()) {
-      [test_window_ orderFront:nil];
-    } else {
-      [test_window_ orderBack:nil];
-    }
-  }
-
-  virtual void TearDown() {
-    [test_window_ close];
-    test_window_ = nil;
-    RenderViewHostTestHarness::TearDown();
-  }
-
-  // Creates the controller and adds its view to contents, caller has ownership.
-  SadTabController* CreateController() {
-    NSView* contentView = [test_window_ contentView];
-    SadTabController* controller =
-        [[SadTabController alloc] initWithTabContents:contents()
-                                            superview:contentView];
-    EXPECT_TRUE(controller);
-    NSView* view = [controller view];
-    EXPECT_TRUE(view);
-
-    return controller;
-  }
-
-  NSButton* GetLinkButton(SadTabController* controller) {
-    SadTabView* view = static_cast<SadTabView*>([controller view]);
-    return ([view linkButton]);
-  }
-
-  static bool link_clicked_;
-  CocoaTestHelperWindow* test_window_;
-};
-
-// static
-bool SadTabControllerTest::link_clicked_;
-
-TEST_F(SadTabControllerTest, WithTabContents) {
-  scoped_nsobject<SadTabController> controller(CreateController());
-  EXPECT_TRUE(controller);
-  NSButton* link = GetLinkButton(controller);
-  EXPECT_TRUE(link);
-}
-
-TEST_F(SadTabControllerTest, WithoutTabContents) {
-  contents_.reset();
-  scoped_nsobject<SadTabController> controller(CreateController());
-  EXPECT_TRUE(controller);
-  NSButton* link = GetLinkButton(controller);
-  EXPECT_FALSE(link);
-}
-
-TEST_F(SadTabControllerTest, ClickOnLink) {
-  scoped_nsobject<SadTabController> controller(CreateController());
-  NSButton* link = GetLinkButton(controller);
-  EXPECT_TRUE(link);
-  EXPECT_FALSE(link_clicked_);
-  [link performClick:link];
-  EXPECT_TRUE(link_clicked_);
-}
-
-}  // namespace
-
-@implementation NSApplication (SadTabControllerUnitTest)
-// Add handler for the openLearnMoreAboutCrashLink: action to NSApp for testing
-// purposes. Normally this would be sent up the responder tree correctly, but
-// since tests run in the background, key window and main window are never set
-// on NSApplication. Adding it to NSApplication directly removes the need for
-// worrying about what the current window with focus is.
-- (void)openLearnMoreAboutCrashLink:(id)sender {
-  SadTabControllerTest::link_clicked_ = true;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/sad_tab_view.h b/chrome/browser/ui/cocoa/sad_tab_view.h
deleted file mode 100644
index 0f304eb..0000000
--- a/chrome/browser/ui/cocoa/sad_tab_view.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_SAD_TAB_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_SAD_TAB_VIEW_H_
-#pragma once
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/ui/cocoa/base_view.h"
-
-#import <Cocoa/Cocoa.h>
-
-@class HyperlinkButtonCell;
-
-// A view that displays the "sad tab" (aka crash page).
-@interface SadTabView : BaseView {
- @private
-  IBOutlet NSImageView* image_;
-  IBOutlet NSTextField* title_;
-  IBOutlet NSTextField* message_;
-  IBOutlet NSButton* linkButton_;
-  IBOutlet HyperlinkButtonCell* linkCell_;
-
-  scoped_nsobject<NSColor> backgroundColor_;
-  NSSize messageSize_;
-}
-
-// Designated initializer is -initWithFrame: .
-
-// Called by SadTabController to remove link button.
-- (void)removeLinkButton;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_SAD_TAB_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/sad_tab_view.mm b/chrome/browser/ui/cocoa/sad_tab_view.mm
deleted file mode 100644
index 2c9f9e2..0000000
--- a/chrome/browser/ui/cocoa/sad_tab_view.mm
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/sad_tab_view.h"
-
-#include "app/resource_bundle.h"
-#include "base/logging.h"
-#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
-#include "grit/theme_resources.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-// Offset above vertical middle of page where contents of page start.
-static const CGFloat kSadTabOffset = -64;
-// Padding between icon and title.
-static const CGFloat kIconTitleSpacing = 20;
-// Padding between title and message.
-static const CGFloat kTitleMessageSpacing = 15;
-// Padding between message and link.
-static const CGFloat kMessageLinkSpacing = 15;
-// Paddings on left and right of page.
-static const CGFloat kTabHorzMargin = 13;
-
-@implementation SadTabView
-
-- (void)awakeFromNib {
-  // Load resource for image and set it.
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  NSImage* image = rb.GetNativeImageNamed(IDR_SAD_TAB);
-  DCHECK(image);
-  [image_ setImage:image];
-
-  // Set font for title.
-  NSFont* titleFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
-  [title_ setFont:titleFont];
-
-  // Set font for message.
-  NSFont* messageFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
-  [message_ setFont:messageFont];
-
-  // If necessary, set font and color for link.
-  if (linkButton_) {
-    [linkButton_ setFont:messageFont];
-    [linkCell_ setTextColor:[NSColor whiteColor]];
-  }
-
-  // Initialize background color.
-  NSColor* backgroundColor = [[NSColor colorWithCalibratedRed:(35.0f/255.0f)
-                                                        green:(48.0f/255.0f)
-                                                         blue:(64.0f/255.0f)
-                                                        alpha:1.0] retain];
-  backgroundColor_.reset(backgroundColor);
-}
-
-- (void)drawRect:(NSRect)dirtyRect {
-  // Paint background.
-  [backgroundColor_ set];
-  NSRectFill(dirtyRect);
-}
-
-- (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
-  NSRect newBounds = [self bounds];
-  CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2);
-  BOOL callSizeToFit = (messageSize_.width == 0);
-
-  // Set new frame origin for image.
-  NSRect iconFrame = [image_ frame];
-  CGFloat iconX = (maxWidth - NSWidth(iconFrame)) / 2;
-  CGFloat iconY =
-      MIN(((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) - kSadTabOffset,
-          NSHeight(newBounds) - NSHeight(iconFrame));
-  iconX = floor(iconX);
-  iconY = floor(iconY);
-  [image_ setFrameOrigin:NSMakePoint(iconX, iconY)];
-
-  // Set new frame origin for title.
-  if (callSizeToFit)
-    [title_ sizeToFit];
-  NSRect titleFrame = [title_ frame];
-  CGFloat titleX = (maxWidth - NSWidth(titleFrame)) / 2;
-  CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame);
-  [title_ setFrameOrigin:NSMakePoint(titleX, titleY)];
-
-  // Set new frame for message, wrapping or unwrapping the text if necessary.
-  if (callSizeToFit) {
-    [message_ sizeToFit];
-    messageSize_ = [message_ frame].size;
-  }
-  NSRect messageFrame = [message_ frame];
-  if (messageSize_.width > maxWidth) {  // Need to wrap message.
-    [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)];
-    CGFloat heightChange =
-        [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
-    messageFrame.size.width = maxWidth;
-    messageFrame.size.height = messageSize_.height + heightChange;
-    messageFrame.origin.x = kTabHorzMargin;
-  } else {
-    if (!callSizeToFit) {
-      [message_ sizeToFit];
-      messageFrame = [message_ frame];
-    }
-    messageFrame.origin.x = (maxWidth - NSWidth(messageFrame)) / 2;
-  }
-  messageFrame.origin.y =
-      titleY - kTitleMessageSpacing - NSHeight(messageFrame);
-  [message_ setFrame:messageFrame];
-
-  if (linkButton_) {
-    if (callSizeToFit)
-      [linkButton_ sizeToFit];
-    // Set new frame origin for link.
-    NSRect linkFrame = [linkButton_ frame];
-    CGFloat linkX = (maxWidth - NSWidth(linkFrame)) / 2;
-    CGFloat linkY =
-        NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(linkFrame);
-    [linkButton_ setFrameOrigin:NSMakePoint(linkX, linkY)];
-  }
-}
-
-- (void)removeLinkButton {
-  if (linkButton_) {
-    [linkButton_ removeFromSuperview];
-    linkButton_ = nil;
-  }
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/sad_tab_view_unittest.mm b/chrome/browser/ui/cocoa/sad_tab_view_unittest.mm
deleted file mode 100644
index 2321dd3..0000000
--- a/chrome/browser/ui/cocoa/sad_tab_view_unittest.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/sad_tab_view.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-
-namespace {
-
-class SadTabViewTest : public CocoaTest {
- public:
-  SadTabViewTest() {
-    NSRect content_frame = [[test_window() contentView] frame];
-    scoped_nsobject<SadTabView> view([[SadTabView alloc]
-                                      initWithFrame:content_frame]);
-    view_ = view.get();
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  SadTabView* view_;  // Weak. Owned by the view hierarchy.
-};
-
-TEST_VIEW(SadTabViewTest, view_);
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/scoped_authorizationref.h b/chrome/browser/ui/cocoa/scoped_authorizationref.h
deleted file mode 100644
index ae7edb3..0000000
--- a/chrome/browser/ui/cocoa/scoped_authorizationref.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_SCOPED_AUTHORIZATIONREF_H_
-#define CHROME_BROWSER_UI_COCOA_SCOPED_AUTHORIZATIONREF_H_
-#pragma once
-
-#include <Security/Authorization.h>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-
-// scoped_AuthorizationRef maintains ownership of an AuthorizationRef.  It is
-// patterned after the scoped_ptr interface.
-
-class scoped_AuthorizationRef {
- public:
-  explicit scoped_AuthorizationRef(AuthorizationRef authorization = NULL)
-      : authorization_(authorization) {
-  }
-
-  ~scoped_AuthorizationRef() {
-    if (authorization_) {
-      AuthorizationFree(authorization_, kAuthorizationFlagDestroyRights);
-    }
-  }
-
-  void reset(AuthorizationRef authorization = NULL) {
-    if (authorization_ != authorization) {
-      if (authorization_) {
-        AuthorizationFree(authorization_, kAuthorizationFlagDestroyRights);
-      }
-      authorization_ = authorization;
-    }
-  }
-
-  bool operator==(AuthorizationRef that) const {
-    return authorization_ == that;
-  }
-
-  bool operator!=(AuthorizationRef that) const {
-    return authorization_ != that;
-  }
-
-  operator AuthorizationRef() const {
-    return authorization_;
-  }
-
-  AuthorizationRef* operator&() {
-    return &authorization_;
-  }
-
-  AuthorizationRef get() const {
-    return authorization_;
-  }
-
-  void swap(scoped_AuthorizationRef& that) {
-    AuthorizationRef temp = that.authorization_;
-    that.authorization_ = authorization_;
-    authorization_ = temp;
-  }
-
-  // scoped_AuthorizationRef::release() is like scoped_ptr<>::release.  It is
-  // NOT a wrapper for AuthorizationFree().  To force a
-  // scoped_AuthorizationRef object to call AuthorizationFree(), use
-  // scoped_AuthorizaitonRef::reset().
-  AuthorizationRef release() WARN_UNUSED_RESULT {
-    AuthorizationRef temp = authorization_;
-    authorization_ = NULL;
-    return temp;
-  }
-
- private:
-  AuthorizationRef authorization_;
-
-  DISALLOW_COPY_AND_ASSIGN(scoped_AuthorizationRef);
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_SCOPED_AUTHORIZATIONREF_H_
diff --git a/chrome/browser/ui/cocoa/search_engine_dialog_controller.mm b/chrome/browser/ui/cocoa/search_engine_dialog_controller.mm
index fa53295..6c5757e 100644
--- a/chrome/browser/ui/cocoa/search_engine_dialog_controller.mm
+++ b/chrome/browser/ui/cocoa/search_engine_dialog_controller.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "base/time.h"
@@ -18,6 +16,8 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // Horizontal spacing between search engine choices.
 const int kSearchEngineSpacing = 20;
@@ -205,7 +205,7 @@
     [logoView setEditable:NO];
 
     // Tooltip text provides accessibility.
-    [logoView setToolTip:base::SysWideToNSString(engine->short_name())];
+    [logoView setToolTip:base::SysUTF16ToNSString(engine->short_name())];
     engineIdentifier = logoView;
   } else {
     // No logo -- we must show a text label.
@@ -224,7 +224,7 @@
         paragraphStyle.get(), NSParagraphStyleAttributeName,
         nil];
 
-    NSString* value = base::SysWideToNSString(engine->short_name());
+    NSString* value = base::SysUTF16ToNSString(engine->short_name());
     scoped_nsobject<NSAttributedString> attrValue(
         [[NSAttributedString alloc] initWithString:value
                                         attributes:attrs]);
diff --git a/chrome/browser/ui/cocoa/search_engine_list_model.h b/chrome/browser/ui/cocoa/search_engine_list_model.h
deleted file mode 100644
index f42fe35..0000000
--- a/chrome/browser/ui/cocoa/search_engine_list_model.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_SEARCH_ENGINE_LIST_MODEL_H_
-#define CHROME_BROWSER_UI_COCOA_SEARCH_ENGINE_LIST_MODEL_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-
-class TemplateURLModel;
-class SearchEngineObserver;
-
-// The model for the "default search engine" combobox in preferences. Bridges
-// between the cross-platform TemplateURLModel and Cocoa while watching for
-// changes to the cross-platform model.
-
-@interface SearchEngineListModel : NSObject {
- @private
-  TemplateURLModel* model_;  // weak, owned by Profile
-  scoped_ptr<SearchEngineObserver> observer_;  // watches for model changes
-  scoped_nsobject<NSArray> engines_;
-}
-
-// Initialize with the given template model.
-- (id)initWithModel:(TemplateURLModel*)model;
-
-// Returns an array of NSString's corresponding to the user-visible names of the
-// search engines.
-- (NSArray*)searchEngines;
-
-// The index into |-searchEngines| of the current default search engine. If
-// there is no default search engine, the value is -1. The setter changes the
-// back-end preference.
-- (NSInteger)defaultIndex;
-- (void)setDefaultIndex:(NSInteger)index;
-// Return TRUE if the default is managed via policy.
-- (BOOL)isDefaultManaged;
-@end
-
-// Broadcast when the cross-platform model changes. This can be used to update
-// any view state that may rely on the position of items in the list.
-extern NSString* const kSearchEngineListModelChangedNotification;
-
-#endif  // CHROME_BROWSER_UI_COCOA_SEARCH_ENGINE_LIST_MODEL_H_
diff --git a/chrome/browser/ui/cocoa/search_engine_list_model.mm b/chrome/browser/ui/cocoa/search_engine_list_model.mm
deleted file mode 100644
index b79c882..0000000
--- a/chrome/browser/ui/cocoa/search_engine_list_model.mm
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/search_engine_list_model.h"
-
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/search_engines/template_url_model_observer.h"
-
-NSString* const kSearchEngineListModelChangedNotification =
-    @"kSearchEngineListModelChangedNotification";
-
-@interface SearchEngineListModel(Private)
-- (void)buildEngineList;
-@end
-
-// C++ bridge from TemplateURLModel to our Obj-C model. When it's told about
-// model changes, notifies us to rebuild the list.
-class SearchEngineObserver : public TemplateURLModelObserver {
- public:
-  SearchEngineObserver(SearchEngineListModel* notify)
-      : notify_(notify) { }
-  virtual ~SearchEngineObserver() { };
-
- private:
-  // TemplateURLModelObserver methods.
-  virtual void OnTemplateURLModelChanged() { [notify_ buildEngineList]; }
-
-  SearchEngineListModel* notify_;  // weak, owns us
-};
-
-@implementation SearchEngineListModel
-
-// The windows code allows for a NULL |model| and checks for it throughout
-// the code, though I'm not sure why. We follow suit.
-- (id)initWithModel:(TemplateURLModel*)model {
-  if ((self = [super init])) {
-    model_ = model;
-    if (model_) {
-      observer_.reset(new SearchEngineObserver(self));
-      model_->Load();
-      model_->AddObserver(observer_.get());
-      [self buildEngineList];
-    }
-  }
-  return self;
-}
-
-- (void)dealloc {
-  if (model_)
-    model_->RemoveObserver(observer_.get());
-  [super dealloc];
-}
-
-// Returns an array of NSString's corresponding to the user-visible names of the
-// search engines.
-- (NSArray*)searchEngines {
-  return engines_.get();
-}
-
-- (void)setSearchEngines:(NSArray*)engines {
-  engines_.reset([engines retain]);
-
-  // Tell anyone who's listening that something has changed so they need to
-  // adjust the UI.
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:kSearchEngineListModelChangedNotification
-                    object:nil];
-}
-
-// Walks the model and builds an array of NSStrings to display to the user.
-// Assumes there is a non-NULL model.
-- (void)buildEngineList {
-  scoped_nsobject<NSMutableArray> engines([[NSMutableArray alloc] init]);
-
-  typedef std::vector<const TemplateURL*> TemplateURLs;
-  TemplateURLs modelURLs = model_->GetTemplateURLs();
-  for (size_t i = 0; i < modelURLs.size(); ++i) {
-    if (modelURLs[i]->ShowInDefaultList())
-      [engines addObject:base::SysWideToNSString(modelURLs[i]->short_name())];
-  }
-
-  [self setSearchEngines:engines.get()];
-}
-
-// The index into |-searchEngines| of the current default search engine.
-// -1 if there is no default.
-- (NSInteger)defaultIndex {
-  if (!model_) return -1;
-
-  NSInteger index = 0;
-  const TemplateURL* defaultSearchProvider = model_->GetDefaultSearchProvider();
-  if (defaultSearchProvider) {
-    typedef std::vector<const TemplateURL*> TemplateURLs;
-    TemplateURLs urls = model_->GetTemplateURLs();
-    for (std::vector<const TemplateURL*>::iterator it = urls.begin();
-         it != urls.end(); ++it) {
-      const TemplateURL* url = *it;
-      // Skip all the URLs not shown on the default list.
-      if (!url->ShowInDefaultList())
-        continue;
-      if (url->id() == defaultSearchProvider->id())
-        return index;
-      ++index;
-    }
-  }
-  return -1;
-}
-
-- (void)setDefaultIndex:(NSInteger)index {
-  if (model_) {
-    typedef std::vector<const TemplateURL*> TemplateURLs;
-    TemplateURLs urls = model_->GetTemplateURLs();
-    for (std::vector<const TemplateURL*>::iterator it = urls.begin();
-         it != urls.end(); ++it) {
-      const TemplateURL* url = *it;
-      // Skip all the URLs not shown on the default list.
-      if (!url->ShowInDefaultList())
-        continue;
-      if (0 == index) {
-        model_->SetDefaultSearchProvider(url);
-        return;
-      }
-      --index;
-    }
-    DCHECK(false);
-  }
-}
-
-// Return TRUE if the default is managed via policy.
-- (BOOL)isDefaultManaged {
-  return model_->is_default_search_managed();
-}
-@end
diff --git a/chrome/browser/ui/cocoa/search_engine_list_model_unittest.mm b/chrome/browser/ui/cocoa/search_engine_list_model_unittest.mm
deleted file mode 100644
index a59bcec..0000000
--- a/chrome/browser/ui/cocoa/search_engine_list_model_unittest.mm
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/search_engine_list_model.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-// A helper for NSNotifications. Makes a note that it's been called back.
-@interface SearchEngineListHelper : NSObject {
- @public
-  BOOL sawNotification_;
-}
-@end
-
-@implementation SearchEngineListHelper
-- (void)entryChanged:(NSNotification*)notify {
-  sawNotification_ = YES;
-}
-@end
-
-class SearchEngineListModelTest : public PlatformTest {
- public:
-  SearchEngineListModelTest() {
-    // Build a fake set of template urls.
-    template_model_.reset(new TemplateURLModel(helper_.profile()));
-    TemplateURL* t_url = new TemplateURL();
-    t_url->SetURL("http://www.google.com/?q={searchTerms}", 0, 0);
-    t_url->set_keyword(L"keyword");
-    t_url->set_short_name(L"google");
-    t_url->set_show_in_default_list(true);
-    template_model_->Add(t_url);
-    t_url = new TemplateURL();
-    t_url->SetURL("http://www.google2.com/?q={searchTerms}", 0, 0);
-    t_url->set_keyword(L"keyword2");
-    t_url->set_short_name(L"google2");
-    t_url->set_show_in_default_list(true);
-    template_model_->Add(t_url);
-    EXPECT_EQ(template_model_->GetTemplateURLs().size(), 2U);
-
-    model_.reset([[SearchEngineListModel alloc]
-                    initWithModel:template_model_.get()]);
-    notification_helper_.reset([[SearchEngineListHelper alloc] init]);
-    [[NSNotificationCenter defaultCenter]
-        addObserver:notification_helper_.get()
-           selector:@selector(entryChanged:)
-              name:kSearchEngineListModelChangedNotification
-            object:nil];
-   }
-  ~SearchEngineListModelTest() {
-    [[NSNotificationCenter defaultCenter]
-        removeObserver:notification_helper_.get()];
-  }
-
-  BrowserTestHelper helper_;
-  scoped_ptr<TemplateURLModel> template_model_;
-  scoped_nsobject<SearchEngineListModel> model_;
-  scoped_nsobject<SearchEngineListHelper> notification_helper_;
-};
-
-TEST_F(SearchEngineListModelTest, Init) {
-  scoped_nsobject<SearchEngineListModel> model(
-      [[SearchEngineListModel alloc] initWithModel:template_model_.get()]);
-}
-
-TEST_F(SearchEngineListModelTest, Engines) {
-  NSArray* engines = [model_ searchEngines];
-  EXPECT_EQ([engines count], 2U);
-}
-
-TEST_F(SearchEngineListModelTest, Default) {
-  EXPECT_EQ([model_ defaultIndex], -1);
-
-  [model_ setDefaultIndex:1];
-  EXPECT_EQ([model_ defaultIndex], 1);
-
-  // Add two more URLs, neither of which are shown in the default list.
-  TemplateURL* t_url = new TemplateURL();
-  t_url->SetURL("http://www.google3.com/?q={searchTerms}", 0, 0);
-  t_url->set_keyword(L"keyword3");
-  t_url->set_short_name(L"google3 not eligible");
-  t_url->set_show_in_default_list(false);
-  template_model_->Add(t_url);
-  t_url = new TemplateURL();
-  t_url->SetURL("http://www.google4.com/?q={searchTerms}", 0, 0);
-  t_url->set_keyword(L"keyword4");
-  t_url->set_short_name(L"google4");
-  t_url->set_show_in_default_list(false);
-  template_model_->Add(t_url);
-
-  // Still should only have 2 engines and not these newly added ones.
-  EXPECT_EQ([[model_ searchEngines] count], 2U);
-
-  // Since keyword3 is not in the default list, the 2nd index in the default
-  // keyword list should be keyword4. Test for http://crbug.com/21898.
-  template_model_->SetDefaultSearchProvider(t_url);
-  EXPECT_EQ([[model_ searchEngines] count], 3U);
-  EXPECT_EQ([model_ defaultIndex], 2);
-
-  NSString* defaultString = [[model_ searchEngines] objectAtIndex:2];
-  EXPECT_NSEQ(@"google4", defaultString);
-}
-
-TEST_F(SearchEngineListModelTest, DefaultChosenFromUI) {
-  EXPECT_EQ([model_ defaultIndex], -1);
-
-  [model_ setDefaultIndex:1];
-  EXPECT_EQ([model_ defaultIndex], 1);
-
-  // Add two more URLs, the first one not shown in the default list.
-  TemplateURL* t_url = new TemplateURL();
-  t_url->SetURL("http://www.google3.com/?q={searchTerms}", 0, 0);
-  t_url->set_keyword(L"keyword3");
-  t_url->set_short_name(L"google3 not eligible");
-  t_url->set_show_in_default_list(false);
-  template_model_->Add(t_url);
-  t_url = new TemplateURL();
-  t_url->SetURL("http://www.google4.com/?q={searchTerms}", 0, 0);
-  t_url->set_keyword(L"keyword4");
-  t_url->set_short_name(L"google4");
-  t_url->set_show_in_default_list(true);
-  template_model_->Add(t_url);
-
-  // We should have 3 engines.
-  EXPECT_EQ([[model_ searchEngines] count], 3U);
-
-  // Simulate the UI setting the default to the third entry.
-  [model_ setDefaultIndex:2];
-  EXPECT_EQ([model_ defaultIndex], 2);
-
-  // The default search provider should be google4.
-  EXPECT_EQ(template_model_->GetDefaultSearchProvider(), t_url);
-}
-
-// Make sure that when the back-end model changes that we get a notification.
-TEST_F(SearchEngineListModelTest, Notification) {
-  // Add one more item to force a notification.
-  TemplateURL* t_url = new TemplateURL();
-  t_url->SetURL("http://www.google3.com/foo/bar", 0, 0);
-  t_url->set_keyword(L"keyword3");
-  t_url->set_short_name(L"google3");
-  t_url->set_show_in_default_list(true);
-  template_model_->Add(t_url);
-
-  EXPECT_TRUE(notification_helper_.get()->sawNotification_);
-}
diff --git a/chrome/browser/ui/cocoa/shell_dialogs_mac.mm b/chrome/browser/ui/cocoa/shell_dialogs_mac.mm
index 24b1bc9..93e031c 100644
--- a/chrome/browser/ui/cocoa/shell_dialogs_mac.mm
+++ b/chrome/browser/ui/cocoa/shell_dialogs_mac.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 
 #import <Cocoa/Cocoa.h>
 #include <CoreServices/CoreServices.h>
@@ -11,7 +11,6 @@
 #include <set>
 #include <vector>
 
-#include "app/l10n_util_mac.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #import "base/mac/cocoa_protocols.h"
@@ -21,6 +20,7 @@
 #include "base/sys_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 static const int kFileTypePopupTag = 1234;
 
diff --git a/chrome/browser/ui/cocoa/side_tab_strip_controller.h b/chrome/browser/ui/cocoa/side_tab_strip_controller.h
deleted file mode 100644
index 07f5551..0000000
--- a/chrome/browser/ui/cocoa/side_tab_strip_controller.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-
-// A controller for the tab strip when side tabs are enabled.
-//
-// TODO(pinkerton): I'm expecting there are more things here that need
-// overriding rather than just tweaking a couple of settings, so I'm creating
-// a full-blown subclass. Clearly, very little is actually necessary at this
-// point for it to work.
-
-@interface SideTabStripController : TabStripController {
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/side_tab_strip_controller.mm b/chrome/browser/ui/cocoa/side_tab_strip_controller.mm
deleted file mode 100644
index 16a835f..0000000
--- a/chrome/browser/ui/cocoa/side_tab_strip_controller.mm
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/side_tab_strip_controller.h"
-
-@implementation SideTabStripController
-
-// TODO(pinkerton): Still need to figure out several things:
-//   - new tab button placement and layout
-//   - animating tabs in and out
-//   - being able to drop a tab elsewhere besides the 1st position
-//   - how to load a different tab view nib for each tab.
-
-- (id)initWithView:(TabStripView*)view
-        switchView:(NSView*)switchView
-           browser:(Browser*)browser
-          delegate:(id<TabStripControllerDelegate>)delegate {
-  self = [super initWithView:view
-                  switchView:switchView
-                     browser:browser
-                    delegate:delegate];
-  if (self) {
-    // Side tabs have no indent since they are not sharing space with the
-    // window controls.
-    [self setIndentForControls:0.0];
-    verticalLayout_ = YES;
-  }
-  return self;
-}
-
-@end
-
diff --git a/chrome/browser/ui/cocoa/side_tab_strip_view.h b/chrome/browser/ui/cocoa/side_tab_strip_view.h
deleted file mode 100644
index 9f8d056..0000000
--- a/chrome/browser/ui/cocoa/side_tab_strip_view.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-
-// A class that handles drawing the background of the tab strip when side tabs
-// are enabled.
-
-@interface SideTabStripView : TabStripView {
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/side_tab_strip_view.mm b/chrome/browser/ui/cocoa/side_tab_strip_view.mm
deleted file mode 100644
index 2c60604..0000000
--- a/chrome/browser/ui/cocoa/side_tab_strip_view.mm
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/side_tab_strip_view.h"
-
-#include "base/scoped_nsobject.h"
-#import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
-
-@implementation SideTabStripView
-
-- (void)drawBorder:(NSRect)bounds {
-  // Draw a border on the right side.
-  NSRect borderRect, contentRect;
-  NSDivideRect(bounds, &borderRect, &contentRect, 1, NSMaxXEdge);
-  [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
-  NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
-}
-
-// Override to prevent double-clicks from minimizing the window. The side
-// tab strip doesn't have that behavior (since it's in the window content
-// area).
-- (BOOL)doubleClickMinimizesWindow {
-  return NO;
-}
-
-- (void)drawRect:(NSRect)rect {
-  // BOOL isKey = [[self window] isKeyWindow];
-  NSColor* aColor =
-      [NSColor colorWithCalibratedRed:0.506 green:0.660 blue:0.985 alpha:1.000];
-  NSColor* bColor =
-      [NSColor colorWithCalibratedRed:0.099 green:0.140 blue:0.254 alpha:1.000];
-  scoped_nsobject<NSGradient> gradient(
-      [[NSGradient alloc] initWithStartingColor:aColor endingColor:bColor]);
-
-  NSRect gradientRect = [self bounds];
-  [gradient drawInRect:gradientRect angle:270.0];
-
-  // Draw borders and any drop feedback.
-  [super drawRect:rect];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/side_tab_strip_view_unittest.mm b/chrome/browser/ui/cocoa/side_tab_strip_view_unittest.mm
deleted file mode 100644
index ba7acc2..0000000
--- a/chrome/browser/ui/cocoa/side_tab_strip_view_unittest.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/side_tab_strip_view.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class SideTabStripViewTest : public CocoaTest {
- public:
-  SideTabStripViewTest() {
-    NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<SideTabStripView> view(
-        [[SideTabStripView alloc] initWithFrame:frame]);
-    view_ = view.get();
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  SideTabStripView* view_;
-};
-
-TEST_VIEW(SideTabStripViewTest, view_)
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/sidebar_controller.h b/chrome/browser/ui/cocoa/sidebar_controller.h
index dcafddb..65955d5 100644
--- a/chrome/browser/ui/cocoa/sidebar_controller.h
+++ b/chrome/browser/ui/cocoa/sidebar_controller.h
@@ -9,7 +9,7 @@
 #import <Foundation/Foundation.h>
 
 #include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
 
 @class NSSplitView;
 @class NSView;
diff --git a/chrome/browser/ui/cocoa/sidebar_controller.mm b/chrome/browser/ui/cocoa/sidebar_controller.mm
index f20deaa..8c3d83f 100644
--- a/chrome/browser/ui/cocoa/sidebar_controller.mm
+++ b/chrome/browser/ui/cocoa/sidebar_controller.mm
@@ -12,7 +12,6 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/sidebar/sidebar_manager.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "chrome/common/pref_names.h"
 
diff --git a/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.mm b/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.mm
deleted file mode 100644
index 7b4c1f8..0000000
--- a/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.mm
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.h"
-
-#include "app/l10n_util_mac.h"
-#include "app/table_model_observer.h"
-#include "base/logging.h"
-#import "base/mac/mac_util.h"
-#import "base/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
-#include "grit/generated_resources.h"
-#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-
-@interface SimpleContentExceptionsWindowController (Private)
-- (id)initWithTableModel:(RemoveRowsTableModel*)model;
-@end
-
-namespace  {
-
-const CGFloat kButtonBarHeight = 35.0;
-
-SimpleContentExceptionsWindowController* g_exceptionWindow = nil;
-
-}  // namespace
-
-@implementation SimpleContentExceptionsWindowController
-
-+ (id)controllerWithTableModel:(RemoveRowsTableModel*)model {
-  if (!g_exceptionWindow) {
-    g_exceptionWindow = [[SimpleContentExceptionsWindowController alloc]
-        initWithTableModel:model];
-  }
-  return g_exceptionWindow;
-}
-
-- (id)initWithTableModel:(RemoveRowsTableModel*)model {
-  NSString* nibpath = [base::mac::MainAppBundle()
-      pathForResource:@"SimpleContentExceptionsWindow"
-               ofType:@"nib"];
-  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
-    model_.reset(model);
-
-    // TODO(thakis): autoremember window rect.
-    // TODO(thakis): sorting support.
-  }
-  return self;
-}
-
-- (void)awakeFromNib {
-  DCHECK([self window]);
-  DCHECK_EQ(self, [[self window] delegate]);
-  DCHECK(tableView_);
-  DCHECK(arrayController_);
-
-  CGFloat minWidth = [[removeButton_ superview] bounds].size.width +
-                     [[doneButton_ superview] bounds].size.width;
-  [[self window] setMinSize:NSMakeSize(minWidth,
-                                       [[self window] minSize].height)];
-  NSDictionary* columns = [NSDictionary dictionaryWithObjectsAndKeys:
-      [NSNumber numberWithInt:IDS_EXCEPTIONS_HOSTNAME_HEADER], @"hostname",
-      [NSNumber numberWithInt:IDS_EXCEPTIONS_ACTION_HEADER], @"action",
-      nil];
-  [arrayController_ bindToTableModel:model_.get()
-                         withColumns:columns
-                    groupTitleColumn:@"hostname"];
-}
-
-- (void)setMinWidth:(CGFloat)minWidth {
-  NSWindow* window = [self window];
-  [window setMinSize:NSMakeSize(minWidth, [window minSize].height)];
-  if ([window frame].size.width < minWidth) {
-    NSRect frame = [window frame];
-    frame.size.width = minWidth;
-    [window setFrame:frame display:NO];
-  }
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
-  g_exceptionWindow = nil;
-  [self autorelease];
-}
-
-// Let esc close the window.
-- (void)cancel:(id)sender {
-  [self closeSheet:self];
-}
-
-- (void)keyDown:(NSEvent*)event {
-  NSString* chars = [event charactersIgnoringModifiers];
-  if ([chars length] == 1) {
-    switch ([chars characterAtIndex:0]) {
-      case NSDeleteCharacter:
-      case NSDeleteFunctionKey:
-        // Delete deletes.
-        if ([[tableView_ selectedRowIndexes] count] > 0)
-          [arrayController_ remove:event];
-        return;
-    }
-  }
-  [super keyDown:event];
-}
-
-- (void)attachSheetTo:(NSWindow*)window {
-  [NSApp beginSheet:[self window]
-     modalForWindow:window
-      modalDelegate:self
-     didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
-        contextInfo:nil];
-}
-
-- (void)sheetDidEnd:(NSWindow*)sheet
-         returnCode:(NSInteger)returnCode
-        contextInfo:(void*)context {
-  [sheet close];
-  [sheet orderOut:self];
-}
-
-- (IBAction)closeSheet:(id)sender {
-  [NSApp endSheet:[self window]];
-}
-
-
-@end
diff --git a/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller_unittest.mm b/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller_unittest.mm
deleted file mode 100644
index 58d1c84..0000000
--- a/chrome/browser/ui/cocoa/simple_content_exceptions_window_controller_unittest.mm
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/simple_content_exceptions_window_controller.h"
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-#include "base/ref_counted.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
-#include "chrome/browser/plugin_exceptions_table_model.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface SimpleContentExceptionsWindowController (Testing)
-
-@property(readonly, nonatomic) TableModelArrayController* arrayController;
-
-@end
-
-@implementation SimpleContentExceptionsWindowController (Testing)
-
-- (TableModelArrayController*)arrayController {
-  return arrayController_;
-}
-
-@end
-
-
-namespace {
-
-class SimpleContentExceptionsWindowControllerTest : public CocoaTest {
- public:
-  virtual void SetUp() {
-    CocoaTest::SetUp();
-    TestingProfile* profile = browser_helper_.profile();
-    geolocation_settings_ = new GeolocationContentSettingsMap(profile);
-    content_settings_ = new HostContentSettingsMap(profile);
-  }
-
-  SimpleContentExceptionsWindowController* GetController() {
-    GeolocationExceptionsTableModel* model =  // Freed by window controller.
-        new GeolocationExceptionsTableModel(geolocation_settings_.get());
-    id controller = [SimpleContentExceptionsWindowController
-        controllerWithTableModel:model];
-    [controller showWindow:nil];
-    return controller;
-  }
-
-  void ClickRemoveAll(SimpleContentExceptionsWindowController* controller) {
-    [controller.arrayController removeAll:nil];
-  }
-
- protected:
-  BrowserTestHelper browser_helper_;
-  scoped_refptr<GeolocationContentSettingsMap> geolocation_settings_;
-  scoped_refptr<HostContentSettingsMap> content_settings_;
-};
-
-TEST_F(SimpleContentExceptionsWindowControllerTest, Construction) {
-  GeolocationExceptionsTableModel* model =  // Freed by window controller.
-      new GeolocationExceptionsTableModel(geolocation_settings_.get());
-  SimpleContentExceptionsWindowController* controller =
-      [SimpleContentExceptionsWindowController controllerWithTableModel:model];
-  [controller showWindow:nil];
-  [controller close];  // Should autorelease.
-}
-
-TEST_F(SimpleContentExceptionsWindowControllerTest, ShowPluginExceptions) {
-  PluginExceptionsTableModel* model =  // Freed by window controller.
-      new PluginExceptionsTableModel(content_settings_.get(), NULL);
-  SimpleContentExceptionsWindowController* controller =
-      [SimpleContentExceptionsWindowController controllerWithTableModel:model];
-  [controller showWindow:nil];
-  [controller close];  // Should autorelease.
-}
-
-TEST_F(SimpleContentExceptionsWindowControllerTest, AddExistingEditAdd) {
-  geolocation_settings_->SetContentSetting(
-      GURL("http://myhost"), GURL(), CONTENT_SETTING_BLOCK);
-
-  SimpleContentExceptionsWindowController* controller = GetController();
-  ClickRemoveAll(controller);
-
-  [controller close];
-
-  EXPECT_EQ(0u, geolocation_settings_->GetAllOriginsSettings().size());
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/speech_input_window_controller.mm b/chrome/browser/ui/cocoa/speech_input_window_controller.mm
index abb9128..000424d 100644
--- a/chrome/browser/ui/cocoa/speech_input_window_controller.mm
+++ b/chrome/browser/ui/cocoa/speech_input_window_controller.mm
@@ -4,8 +4,6 @@
 
 #import "speech_input_window_controller.h"
 
-#include "app/l10n_util_mac.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/ui/cocoa/info_bubble_view.h"
@@ -13,6 +11,8 @@
 #include "grit/theme_resources.h"
 #import "skia/ext/skia_utils_mac.h"
 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
 
 const int kBubbleControlVerticalSpacing = 10;  // Space between controls.
 const int kBubbleHorizontalMargin = 5;  // Space on either sides of controls.
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector.mm
index 3f0a2f5..729ce1c 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector.mm
@@ -8,7 +8,6 @@
 
 #include <vector>
 
-#import "app/l10n_util_mac.h"
 #include "base/logging.h"
 #include "base/ref_counted.h"
 #import "base/scoped_nsobject.h"
@@ -21,6 +20,7 @@
 #import "chrome/browser/ui/cocoa/constrained_window_mac.h"
 #include "grit/generated_resources.h"
 #include "net/base/x509_certificate.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/status_bubble_mac.mm b/chrome/browser/ui/cocoa/status_bubble_mac.mm
index 685096d..13f9d48 100644
--- a/chrome/browser/ui/cocoa/status_bubble_mac.mm
+++ b/chrome/browser/ui/cocoa/status_bubble_mac.mm
@@ -6,18 +6,18 @@
 
 #include <limits>
 
-#include "app/text_elider.h"
 #include "base/compiler_specific.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/bubble_view.h"
-#include "gfx/point.h"
 #include "net/base/net_util.h"
 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/point.h"
 
 namespace {
 
@@ -148,11 +148,11 @@
   scaled_width = [[parent_ contentView] convertSize:scaled_width fromView:nil];
   text_width = static_cast<int>(scaled_width.width);
   NSFont* font = [[window_ contentView] font];
-  gfx::Font font_chr(base::SysNSStringToWide([font fontName]),
+  gfx::Font font_chr(base::SysNSStringToUTF16([font fontName]),
                      [font pointSize]);
 
   string16 original_url_text = net::FormatUrl(url, UTF16ToUTF8(languages));
-  string16 status = gfx::ElideUrl(url, font_chr, text_width,
+  string16 status = ui::ElideUrl(url, font_chr, text_width,
       UTF16ToWideHack(languages));
 
   SetText(status, true);
@@ -606,9 +606,9 @@
 
   // Generate the URL string that fits in the expanded bubble.
   NSFont* font = [[window_ contentView] font];
-  gfx::Font font_chr(base::SysNSStringToWide([font fontName]),
+  gfx::Font font_chr(base::SysNSStringToUTF16([font fontName]),
       [font pointSize]);
-  string16 expanded_url = gfx::ElideUrl(url_, font_chr,
+  string16 expanded_url = ui::ElideUrl(url_, font_chr,
       max_bubble_width, UTF16ToWideHack(languages_));
 
   // Scale width from gfx::Font in view coordinates to window coordinates.
diff --git a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h
index c414ec9..7c2c84e 100644
--- a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h
+++ b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h
@@ -28,7 +28,7 @@
 
  protected:
   // Overridden from StatusIcon.
-  virtual void UpdatePlatformContextMenu(menus::MenuModel* menu);
+  virtual void UpdatePlatformContextMenu(ui::MenuModel* menu);
 
  private:
   // Getter for item_ that allows lazy initialization.
diff --git a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm
index 3f3d5a1..9ac39bf 100644
--- a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm
+++ b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm
@@ -76,7 +76,7 @@
   [item() setToolTip:base::SysUTF16ToNSString(tool_tip)];
 }
 
-void StatusIconMac::UpdatePlatformContextMenu(menus::MenuModel* menu) {
+void StatusIconMac::UpdatePlatformContextMenu(ui::MenuModel* menu) {
   // TODO(atwilson): Add support for context menus for Mac when actually needed
   // (not yet used by anything) - http://crbug.com/37375.
 }
diff --git a/chrome/browser/ui/cocoa/status_icons/status_icon_mac_unittest.mm b/chrome/browser/ui/cocoa/status_icons/status_icon_mac_unittest.mm
index 45d1950..2f6ae84 100644
--- a/chrome/browser/ui/cocoa/status_icons/status_icon_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/status_icons/status_icon_mac_unittest.mm
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/resource_bundle.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
@@ -11,6 +10,7 @@
 #include "grit/theme_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class SkBitmap;
 
diff --git a/chrome/browser/ui/cocoa/styled_text_field_cell.mm b/chrome/browser/ui/cocoa/styled_text_field_cell.mm
index 56b0cf3..46fcd8b 100644
--- a/chrome/browser/ui/cocoa/styled_text_field_cell.mm
+++ b/chrome/browser/ui/cocoa/styled_text_field_cell.mm
@@ -4,13 +4,13 @@
 
 #import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
-#include "gfx/font.h"
 #include "grit/theme_resources.h"
 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/font.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/styled_text_field_test_helper.h b/chrome/browser/ui/cocoa/styled_text_field_test_helper.h
index eb90cbf..8ece572 100644
--- a/chrome/browser/ui/cocoa/styled_text_field_test_helper.h
+++ b/chrome/browser/ui/cocoa/styled_text_field_test_helper.h
@@ -11,6 +11,6 @@
   CGFloat leftMargin_;
   CGFloat rightMargin_;
 }
-@property (nonatomic, assign) CGFloat leftMargin;
-@property (nonatomic, assign) CGFloat rightMargin;
+@property(nonatomic, assign) CGFloat leftMargin;
+@property(nonatomic, assign) CGFloat rightMargin;
 @end
diff --git a/chrome/browser/ui/cocoa/tab_contents/OWNERS b/chrome/browser/ui/cocoa/tab_contents/OWNERS
new file mode 100644
index 0000000..377ad51
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/OWNERS
@@ -0,0 +1,3 @@
+avi@chromium.org
+pinkerton@chromium.org
+thakis@chromium.org
diff --git a/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h
new file mode 100644
index 0000000..215d096
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_PREVIEWABLE_CONTENTS_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_PREVIEWABLE_CONTENTS_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+class TabContents;
+
+// PreviewableContentsController manages the display of up to two tab contents
+// views.  It is primarily for use with Instant results.  This class supports
+// the notion of an "active" view vs. a "preview" tab contents view.
+//
+// The "active" view is a container view that can be retrieved using
+// |-activeContainer|.  Its contents are meant to be managed by an external
+// class.
+//
+// The "preview" can be set using |-showPreview:| and |-hidePreview|.  When a
+// preview is set, the active view is hidden (but stays in the view hierarchy).
+// When the preview is removed, the active view is reshown.
+@interface PreviewableContentsController : NSViewController {
+ @private
+  // Container view for the "active" contents.
+  IBOutlet NSView* activeContainer_;
+
+  // The preview TabContents.  Will be NULL if no preview is currently showing.
+  TabContents* previewContents_;  // weak
+}
+
+@property(readonly, nonatomic) NSView* activeContainer;
+
+// Sets the current preview and installs its TabContentsView into the view
+// hierarchy.  Hides the active view.  |preview| must not be NULL.
+- (void)showPreview:(TabContents*)preview;
+
+// Closes the current preview and shows the active view.
+- (void)hidePreview;
+
+// Returns YES if the preview contents is currently showing.
+- (BOOL)isShowingPreview;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_PREVIEWABLE_CONTENTS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.mm
new file mode 100644
index 0000000..08aa315
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.mm
@@ -0,0 +1,52 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h"
+
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+
+@implementation PreviewableContentsController
+
+@synthesize activeContainer = activeContainer_;
+
+- (id)init {
+  if ((self = [super initWithNibName:@"PreviewableContents"
+                              bundle:base::mac::MainAppBundle()])) {
+  }
+  return self;
+}
+
+- (void)showPreview:(TabContents*)preview {
+  DCHECK(preview);
+
+  // Remove any old preview contents before showing the new one.
+  if (previewContents_)
+    [previewContents_->GetNativeView() removeFromSuperview];
+
+  previewContents_ = preview;
+  NSView* previewView = previewContents_->GetNativeView();
+  [previewView setFrame:[[self view] bounds]];
+
+  // Hide the active container and add the preview contents.
+  [activeContainer_ setHidden:YES];
+  [[self view] addSubview:previewView];
+}
+
+- (void)hidePreview {
+  DCHECK(previewContents_);
+
+  // Remove the preview contents and reshow the active container.
+  [previewContents_->GetNativeView() removeFromSuperview];
+  [activeContainer_ setHidden:NO];
+
+  previewContents_ = nil;
+}
+
+- (BOOL)isShowingPreview {
+  return previewContents_ != nil;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller_unittest.mm
new file mode 100644
index 0000000..3e5ea6f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller_unittest.mm
@@ -0,0 +1,34 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class PreviewableContentsControllerTest : public CocoaTest {
+ public:
+  virtual void SetUp() {
+    CocoaTest::SetUp();
+    controller_.reset([[PreviewableContentsController alloc] init]);
+    [[test_window() contentView] addSubview:[controller_ view]];
+  }
+
+  scoped_nsobject<PreviewableContentsController> controller_;
+};
+
+TEST_VIEW(PreviewableContentsControllerTest, [controller_ view])
+
+// TODO(rohitrao): Test showing and hiding the preview.  This may require
+// changing the interface to take in a TabContentsView* instead of a
+// TabContents*.
+
+}  // namespace
+
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h
new file mode 100644
index 0000000..48a97f6
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+class TabContents;
+
+// A controller class that manages the SadTabView (aka "Aw Snap" or crash page).
+@interface SadTabController : NSViewController {
+ @private
+  TabContents* tabContents_;  // Weak reference.
+}
+
+// Designated initializer is initWithTabContents.
+- (id)initWithTabContents:(TabContents*)someTabContents
+                superview:(NSView*)superview;
+
+// This action just calls the NSApp sendAction to get it into the standard
+// Cocoa action processing.
+- (IBAction)openLearnMoreAboutCrashLink:(id)sender;
+
+// Returns a weak reference to the TabContents whose TabContentsView created
+// this SadTabController.
+- (TabContents*)tabContents;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm
new file mode 100644
index 0000000..3b11c14
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
+
+#include "base/mac/mac_util.h"
+#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h"
+
+@implementation SadTabController
+
+- (id)initWithTabContents:(TabContents*)someTabContents
+                superview:(NSView*)superview {
+  if ((self = [super initWithNibName:@"SadTab"
+                              bundle:base::mac::MainAppBundle()])) {
+    tabContents_ = someTabContents;
+
+    NSView* view = [self view];
+    [superview addSubview:view];
+    [view setFrame:[superview bounds]];
+  }
+
+  return self;
+}
+
+- (void)awakeFromNib {
+  // If tab_contents_ is nil, ask view to remove link.
+  if (!tabContents_) {
+    SadTabView* sad_view = static_cast<SadTabView*>([self view]);
+    [sad_view removeLinkButton];
+  }
+}
+
+- (void)dealloc {
+  [[self view] removeFromSuperview];
+  [super dealloc];
+}
+
+- (TabContents*)tabContents {
+  return tabContents_;
+}
+
+- (void)openLearnMoreAboutCrashLink:(id)sender {
+  // Send the action up through the responder chain.
+  [NSApp sendAction:@selector(openLearnMoreAboutCrashLink:) to:nil from:self];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm
new file mode 100644
index 0000000..84276a3
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm
@@ -0,0 +1,113 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/debugger.h"
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
+#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/browser/tab_contents/test_tab_contents.h"
+#include "chrome/test/testing_profile.h"
+
+@interface SadTabView (ExposedForTesting)
+// Implementation is below.
+- (NSButton*)linkButton;
+@end
+
+@implementation SadTabView (ExposedForTesting)
+- (NSButton*)linkButton {
+  return linkButton_;
+}
+@end
+
+namespace {
+
+class SadTabControllerTest : public RenderViewHostTestHarness {
+ public:
+  SadTabControllerTest() : test_window_(nil) {
+    link_clicked_ = false;
+  }
+
+  virtual void SetUp() {
+    RenderViewHostTestHarness::SetUp();
+    // Inherting from RenderViewHostTestHarness means we can't inherit from
+    // from CocoaTest, so do a bootstrap and create test window.
+    CocoaTest::BootstrapCocoa();
+    test_window_ = [[CocoaTestHelperWindow alloc] init];
+    if (base::debug::BeingDebugged()) {
+      [test_window_ orderFront:nil];
+    } else {
+      [test_window_ orderBack:nil];
+    }
+  }
+
+  virtual void TearDown() {
+    [test_window_ close];
+    test_window_ = nil;
+    RenderViewHostTestHarness::TearDown();
+  }
+
+  // Creates the controller and adds its view to contents, caller has ownership.
+  SadTabController* CreateController() {
+    NSView* contentView = [test_window_ contentView];
+    SadTabController* controller =
+        [[SadTabController alloc] initWithTabContents:contents()
+                                            superview:contentView];
+    EXPECT_TRUE(controller);
+    NSView* view = [controller view];
+    EXPECT_TRUE(view);
+
+    return controller;
+  }
+
+  NSButton* GetLinkButton(SadTabController* controller) {
+    SadTabView* view = static_cast<SadTabView*>([controller view]);
+    return ([view linkButton]);
+  }
+
+  static bool link_clicked_;
+  CocoaTestHelperWindow* test_window_;
+};
+
+// static
+bool SadTabControllerTest::link_clicked_;
+
+TEST_F(SadTabControllerTest, WithTabContents) {
+  scoped_nsobject<SadTabController> controller(CreateController());
+  EXPECT_TRUE(controller);
+  NSButton* link = GetLinkButton(controller);
+  EXPECT_TRUE(link);
+}
+
+TEST_F(SadTabControllerTest, WithoutTabContents) {
+  contents_.reset();
+  scoped_nsobject<SadTabController> controller(CreateController());
+  EXPECT_TRUE(controller);
+  NSButton* link = GetLinkButton(controller);
+  EXPECT_FALSE(link);
+}
+
+TEST_F(SadTabControllerTest, ClickOnLink) {
+  scoped_nsobject<SadTabController> controller(CreateController());
+  NSButton* link = GetLinkButton(controller);
+  EXPECT_TRUE(link);
+  EXPECT_FALSE(link_clicked_);
+  [link performClick:link];
+  EXPECT_TRUE(link_clicked_);
+}
+
+}  // namespace
+
+@implementation NSApplication (SadTabControllerUnitTest)
+// Add handler for the openLearnMoreAboutCrashLink: action to NSApp for testing
+// purposes. Normally this would be sent up the responder tree correctly, but
+// since tests run in the background, key window and main window are never set
+// on NSApplication. Adding it to NSApplication directly removes the need for
+// worrying about what the current window with focus is.
+- (void)openLearnMoreAboutCrashLink:(id)sender {
+  SadTabControllerTest::link_clicked_ = true;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h
new file mode 100644
index 0000000..8f782af
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_VIEW_H_
+#pragma once
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/base_view.h"
+
+#import <Cocoa/Cocoa.h>
+
+@class HyperlinkButtonCell;
+
+// A view that displays the "sad tab" (aka crash page).
+@interface SadTabView : BaseView {
+ @private
+  IBOutlet NSImageView* image_;
+  IBOutlet NSTextField* title_;
+  IBOutlet NSTextField* message_;
+  IBOutlet NSButton* linkButton_;
+  IBOutlet HyperlinkButtonCell* linkCell_;
+
+  scoped_nsobject<NSColor> backgroundColor_;
+  NSSize messageSize_;
+}
+
+// Designated initializer is -initWithFrame: .
+
+// Called by SadTabController to remove link button.
+- (void)removeLinkButton;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_SAD_TAB_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.mm
new file mode 100644
index 0000000..666ebff
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.mm
@@ -0,0 +1,127 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h"
+
+#include "base/logging.h"
+#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
+#include "grit/theme_resources.h"
+#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/resource/resource_bundle.h"
+
+// Offset above vertical middle of page where contents of page start.
+static const CGFloat kSadTabOffset = -64;
+// Padding between icon and title.
+static const CGFloat kIconTitleSpacing = 20;
+// Padding between title and message.
+static const CGFloat kTitleMessageSpacing = 15;
+// Padding between message and link.
+static const CGFloat kMessageLinkSpacing = 15;
+// Paddings on left and right of page.
+static const CGFloat kTabHorzMargin = 13;
+
+@implementation SadTabView
+
+- (void)awakeFromNib {
+  // Load resource for image and set it.
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  NSImage* image = rb.GetNativeImageNamed(IDR_SAD_TAB);
+  DCHECK(image);
+  [image_ setImage:image];
+
+  // Set font for title.
+  NSFont* titleFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
+  [title_ setFont:titleFont];
+
+  // Set font for message.
+  NSFont* messageFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
+  [message_ setFont:messageFont];
+
+  // If necessary, set font and color for link.
+  if (linkButton_) {
+    [linkButton_ setFont:messageFont];
+    [linkCell_ setTextColor:[NSColor whiteColor]];
+  }
+
+  // Initialize background color.
+  NSColor* backgroundColor = [[NSColor colorWithCalibratedRed:(35.0f/255.0f)
+                                                        green:(48.0f/255.0f)
+                                                         blue:(64.0f/255.0f)
+                                                        alpha:1.0] retain];
+  backgroundColor_.reset(backgroundColor);
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
+  // Paint background.
+  [backgroundColor_ set];
+  NSRectFill(dirtyRect);
+}
+
+- (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
+  NSRect newBounds = [self bounds];
+  CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2);
+  BOOL callSizeToFit = (messageSize_.width == 0);
+
+  // Set new frame origin for image.
+  NSRect iconFrame = [image_ frame];
+  CGFloat iconX = (maxWidth - NSWidth(iconFrame)) / 2;
+  CGFloat iconY =
+      MIN(((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) - kSadTabOffset,
+          NSHeight(newBounds) - NSHeight(iconFrame));
+  iconX = floor(iconX);
+  iconY = floor(iconY);
+  [image_ setFrameOrigin:NSMakePoint(iconX, iconY)];
+
+  // Set new frame origin for title.
+  if (callSizeToFit)
+    [title_ sizeToFit];
+  NSRect titleFrame = [title_ frame];
+  CGFloat titleX = (maxWidth - NSWidth(titleFrame)) / 2;
+  CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame);
+  [title_ setFrameOrigin:NSMakePoint(titleX, titleY)];
+
+  // Set new frame for message, wrapping or unwrapping the text if necessary.
+  if (callSizeToFit) {
+    [message_ sizeToFit];
+    messageSize_ = [message_ frame].size;
+  }
+  NSRect messageFrame = [message_ frame];
+  if (messageSize_.width > maxWidth) {  // Need to wrap message.
+    [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)];
+    CGFloat heightChange =
+        [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
+    messageFrame.size.width = maxWidth;
+    messageFrame.size.height = messageSize_.height + heightChange;
+    messageFrame.origin.x = kTabHorzMargin;
+  } else {
+    if (!callSizeToFit) {
+      [message_ sizeToFit];
+      messageFrame = [message_ frame];
+    }
+    messageFrame.origin.x = (maxWidth - NSWidth(messageFrame)) / 2;
+  }
+  messageFrame.origin.y =
+      titleY - kTitleMessageSpacing - NSHeight(messageFrame);
+  [message_ setFrame:messageFrame];
+
+  if (linkButton_) {
+    if (callSizeToFit)
+      [linkButton_ sizeToFit];
+    // Set new frame origin for link.
+    NSRect linkFrame = [linkButton_ frame];
+    CGFloat linkX = (maxWidth - NSWidth(linkFrame)) / 2;
+    CGFloat linkY =
+        NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(linkFrame);
+    [linkButton_ setFrameOrigin:NSMakePoint(linkX, linkY)];
+  }
+}
+
+- (void)removeLinkButton {
+  if (linkButton_) {
+    [linkButton_ removeFromSuperview];
+    linkButton_ = nil;
+  }
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm
new file mode 100644
index 0000000..76808cf
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm
@@ -0,0 +1,25 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+
+namespace {
+
+class SadTabViewTest : public CocoaTest {
+ public:
+  SadTabViewTest() {
+    NSRect content_frame = [[test_window() contentView] frame];
+    scoped_nsobject<SadTabView> view([[SadTabView alloc]
+                                      initWithFrame:content_frame]);
+    view_ = view.get();
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  SadTabView* view_;  // Weak. Owned by the view hierarchy.
+};
+
+TEST_VIEW(SadTabViewTest, view_);
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
new file mode 100644
index 0000000..a327e4b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_TAB_CONTENTS_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_TAB_CONTENTS_CONTROLLER_H_
+#pragma once
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/scoped_ptr.h"
+
+class TabContents;
+class TabContentsNotificationBridge;
+@class TabContentsController;
+
+// The interface for the tab contents view controller's delegate.
+
+@protocol TabContentsControllerDelegate
+
+// Tells the delegate when the tab contents view's frame is about to change.
+- (void)tabContentsViewFrameWillChange:(TabContentsController*)source
+                             frameRect:(NSRect)frameRect;
+
+@end
+
+// A class that controls the TabContents view. It manages displaying the
+// native view for a given TabContents.
+// Note that just creating the class does not display the view. We defer
+// inserting it until the box is the correct size to avoid multiple resize
+// messages to the renderer. You must call |-ensureContentsVisible| to display
+// the render widget host view.
+
+@interface TabContentsController : NSViewController {
+ @private
+  TabContents* contents_;  // weak
+  // Delegate to be notified about size changes.
+  id<TabContentsControllerDelegate> delegate_;  // weak
+  scoped_ptr<TabContentsNotificationBridge> tabContentsBridge_;
+}
+@property(readonly, nonatomic) TabContents* tabContents;
+
+- (id)initWithContents:(TabContents*)contents
+              delegate:(id<TabContentsControllerDelegate>)delegate;
+
+// Call when the tab contents is about to be replaced with the currently
+// selected tab contents to do not trigger unnecessary content relayout.
+- (void)ensureContentsSizeDoesNotChange;
+
+// Call when the tab view is properly sized and the render widget host view
+// should be put into the view hierarchy.
+- (void)ensureContentsVisible;
+
+// Call to change the underlying tab contents object. View is not changed,
+// call |-ensureContentsVisible| to display the |newContents|'s render widget
+// host view.
+- (void)changeTabContents:(TabContents*)newContents;
+
+// Called when the tab contents is the currently selected tab and is about to be
+// removed from the view hierarchy.
+- (void)willBecomeUnselectedTab;
+
+// Called when the tab contents is about to be put into the view hierarchy as
+// the selected tab. Handles things such as ensuring the toolbar is correctly
+// enabled.
+- (void)willBecomeSelectedTab;
+
+// Called when the tab contents is updated in some non-descript way (the
+// notification from the model isn't specific). |updatedContents| could reflect
+// an entirely new tab contents object.
+- (void)tabDidChange:(TabContents*)updatedContents;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_TAB_CONTENTS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
new file mode 100644
index 0000000..68f8d07
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -0,0 +1,211 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+
+
+@interface TabContentsController(Private)
+// Forwards frame update to |delegate_| (ResizeNotificationView calls it).
+- (void)tabContentsViewFrameWillChange:(NSRect)frameRect;
+// Notification from TabContents (forwarded by TabContentsNotificationBridge).
+- (void)tabContentsRenderViewHostChanged:(RenderViewHost*)oldHost
+                                 newHost:(RenderViewHost*)newHost;
+@end
+
+
+// A supporting C++ bridge object to register for TabContents notifications.
+
+class TabContentsNotificationBridge : public NotificationObserver {
+ public:
+  explicit TabContentsNotificationBridge(TabContentsController* controller);
+
+  // Overriden from NotificationObserver.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+  // Register for |contents|'s notifications, remove all prior registrations.
+  void ChangeTabContents(TabContents* contents);
+ private:
+  NotificationRegistrar registrar_;
+  TabContentsController* controller_;  // weak, owns us
+};
+
+TabContentsNotificationBridge::TabContentsNotificationBridge(
+    TabContentsController* controller)
+    : controller_(controller) {
+}
+
+void TabContentsNotificationBridge::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  if (type == NotificationType::RENDER_VIEW_HOST_CHANGED) {
+    RenderViewHostSwitchedDetails* switched_details =
+        Details<RenderViewHostSwitchedDetails>(details).ptr();
+    [controller_ tabContentsRenderViewHostChanged:switched_details->old_host
+                                          newHost:switched_details->new_host];
+  } else {
+    NOTREACHED();
+  }
+}
+
+void TabContentsNotificationBridge::ChangeTabContents(TabContents* contents) {
+  registrar_.RemoveAll();
+  if (contents) {
+    registrar_.Add(this,
+                   NotificationType::RENDER_VIEW_HOST_CHANGED,
+                   Source<NavigationController>(&contents->controller()));
+  }
+}
+
+
+// A custom view that notifies |controller| that view's frame is changing.
+
+@interface ResizeNotificationView : NSView {
+  TabContentsController* controller_;
+}
+- (id)initWithController:(TabContentsController*)controller;
+@end
+
+@implementation ResizeNotificationView
+
+- (id)initWithController:(TabContentsController*)controller {
+  if ((self = [super initWithFrame:NSZeroRect])) {
+    controller_ = controller;
+  }
+  return self;
+}
+
+- (void)setFrame:(NSRect)frameRect {
+  [controller_ tabContentsViewFrameWillChange:frameRect];
+  [super setFrame:frameRect];
+}
+
+@end
+
+
+@implementation TabContentsController
+@synthesize tabContents = contents_;
+
+- (id)initWithContents:(TabContents*)contents
+              delegate:(id<TabContentsControllerDelegate>)delegate {
+  if ((self = [super initWithNibName:nil bundle:nil])) {
+    contents_ = contents;
+    delegate_ = delegate;
+    tabContentsBridge_.reset(new TabContentsNotificationBridge(self));
+    tabContentsBridge_->ChangeTabContents(contents);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  // make sure our contents have been removed from the window
+  [[self view] removeFromSuperview];
+  [super dealloc];
+}
+
+- (void)loadView {
+  scoped_nsobject<ResizeNotificationView> view(
+      [[ResizeNotificationView alloc] initWithController:self]);
+  [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable];
+  [self setView:view];
+}
+
+- (void)ensureContentsSizeDoesNotChange {
+  if (contents_) {
+    NSView* contentsContainer = [self view];
+    NSArray* subviews = [contentsContainer subviews];
+    if ([subviews count] > 0)
+      [contents_->GetNativeView() setAutoresizingMask:NSViewNotSizable];
+  }
+}
+
+// Call when the tab view is properly sized and the render widget host view
+// should be put into the view hierarchy.
+- (void)ensureContentsVisible {
+  if (!contents_)
+    return;
+  NSView* contentsContainer = [self view];
+  NSArray* subviews = [contentsContainer subviews];
+  NSView* contentsNativeView = contents_->GetNativeView();
+
+  NSRect contentsNativeViewFrame = [contentsContainer frame];
+  contentsNativeViewFrame.origin = NSZeroPoint;
+
+  [delegate_ tabContentsViewFrameWillChange:self
+                                  frameRect:contentsNativeViewFrame];
+
+  // Native view is resized to the actual size before it becomes visible
+  // to avoid flickering.
+  [contentsNativeView setFrame:contentsNativeViewFrame];
+  if ([subviews count] == 0) {
+    [contentsContainer addSubview:contentsNativeView];
+  } else if ([subviews objectAtIndex:0] != contentsNativeView) {
+    [contentsContainer replaceSubview:[subviews objectAtIndex:0]
+                                 with:contentsNativeView];
+  }
+  // Restore autoresizing properties possibly stripped by
+  // ensureContentsSizeDoesNotChange call.
+  [contentsNativeView setAutoresizingMask:NSViewWidthSizable|
+                                          NSViewHeightSizable];
+}
+
+- (void)changeTabContents:(TabContents*)newContents {
+  contents_ = newContents;
+  tabContentsBridge_->ChangeTabContents(contents_);
+}
+
+- (void)tabContentsViewFrameWillChange:(NSRect)frameRect {
+  [delegate_ tabContentsViewFrameWillChange:self frameRect:frameRect];
+}
+
+- (void)tabContentsRenderViewHostChanged:(RenderViewHost*)oldHost
+                                 newHost:(RenderViewHost*)newHost {
+  if (oldHost && newHost && oldHost->view() && newHost->view()) {
+    newHost->view()->set_reserved_contents_rect(
+        oldHost->view()->reserved_contents_rect());
+  } else {
+    [delegate_ tabContentsViewFrameWillChange:self
+                                    frameRect:[[self view] frame]];
+  }
+}
+
+- (void)willBecomeUnselectedTab {
+  // The RWHV is ripped out of the view hierarchy on tab switches, so it never
+  // formally resigns first responder status.  Handle this by explicitly sending
+  // a Blur() message to the renderer, but only if the RWHV currently has focus.
+  RenderViewHost* rvh = [self tabContents]->render_view_host();
+  if (rvh && rvh->view() && rvh->view()->HasFocus())
+    rvh->Blur();
+}
+
+- (void)willBecomeSelectedTab {
+  // Do not explicitly call Focus() here, as the RWHV may not actually have
+  // focus (for example, if the omnibox has focus instead).  The TabContents
+  // logic will restore focus to the appropriate view.
+}
+
+- (void)tabDidChange:(TabContents*)updatedContents {
+  // Calling setContentView: here removes any first responder status
+  // the view may have, so avoid changing the view hierarchy unless
+  // the view is different.
+  if ([self tabContents] != updatedContents) {
+    [self changeTabContents:updatedContents];
+    if ([self tabContents])
+      [self ensureContentsVisible];
+  }
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.h b/chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.h
new file mode 100644
index 0000000..e611f4c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_WEB_CONTENTS_DRAG_SOURCE_H_
+#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_WEB_CONTENTS_DRAG_SOURCE_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/bookmarks/bookmark_node_data.h"
+
+@class TabContentsViewCocoa;
+
+// A class that handles tracking and event processing for a drag and drop
+// originating from the content area.  Subclasses should implement
+// fillClipboard and dragImage.
+@interface WebContentsDragSource : NSObject {
+ @private
+  // Our tab. Weak reference (owns or co-owns us).
+  TabContentsViewCocoa* contentsView_;
+
+  // Our pasteboard.
+  scoped_nsobject<NSPasteboard> pasteboard_;
+
+  // A mask of the allowed drag operations.
+  NSDragOperation dragOperationMask_;
+}
+
+// Initialize a DragDataSource object for a drag (originating on the given
+// contentsView and with the given dropData and pboard). Fill the pasteboard
+// with data types appropriate for dropData.
+- (id)initWithContentsView:(TabContentsViewCocoa*)contentsView
+                pasteboard:(NSPasteboard*)pboard
+         dragOperationMask:(NSDragOperation)dragOperationMask;
+
+// Creates the drag image.  Implemented by the subclass.
+- (NSImage*)dragImage;
+
+// Put the data being dragged onto the pasteboard.  Implemented by the
+// subclass.
+- (void)fillPasteboard;
+
+// Returns a mask of the allowed drag operations.
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
+
+// Start the drag (on the originally provided contentsView); can do this right
+// after -initWithContentsView:....
+- (void)startDrag;
+
+// End the drag and clear the pasteboard; hook up to
+// -draggedImage:endedAt:operation:.
+- (void)endDragAt:(NSPoint)screenPoint
+        operation:(NSDragOperation)operation;
+
+// Drag moved; hook up to -draggedImage:movedTo:.
+- (void)moveDragTo:(NSPoint)screenPoint;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_WEB_CONTENTS_DRAG_SOURCE_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.mm b/chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.mm
new file mode 100644
index 0000000..2cd67b3
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.mm
@@ -0,0 +1,130 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/tab_contents/web_contents_drag_source.h"
+
+#include "app/mac/nsimage_cache.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view_mac.h"
+
+namespace {
+
+// Make a drag image from the drop data.
+// TODO(feldstein): Make this work
+NSImage* MakeDragImage() {
+  // TODO(feldstein): Just a stub for now. Make it do something (see, e.g.,
+  // WebKit/WebKit/mac/Misc/WebNSViewExtras.m: |-_web_DragImageForElement:...|).
+
+  // Default to returning a generic image.
+  return app::mac::GetCachedImageWithName(@"nav.pdf");
+}
+
+// Flips screen and point coordinates over the y axis to work with webkit
+// coordinate systems.
+void FlipPointCoordinates(NSPoint& screenPoint,
+                          NSPoint& localPoint,
+                          NSView* view) {
+  NSRect viewFrame = [view frame];
+  localPoint.y = NSHeight(viewFrame) - localPoint.y;
+  // Flip |screenPoint|.
+  NSRect screenFrame = [[[view window] screen] frame];
+  screenPoint.y = NSHeight(screenFrame) - screenPoint.y;
+}
+
+}  // namespace
+
+
+@implementation WebContentsDragSource
+
+- (id)initWithContentsView:(TabContentsViewCocoa*)contentsView
+                pasteboard:(NSPasteboard*)pboard
+         dragOperationMask:(NSDragOperation)dragOperationMask {
+  if ((self = [super init])) {
+    contentsView_ = contentsView;
+    DCHECK(contentsView_);
+
+    pasteboard_.reset([pboard retain]);
+    DCHECK(pasteboard_.get());
+
+    dragOperationMask_ = dragOperationMask;
+  }
+
+  return self;
+}
+
+- (NSImage*)dragImage {
+  return MakeDragImage();
+}
+
+- (void)fillPasteboard {
+  NOTIMPLEMENTED() << "Subclasses should implement fillPasteboard";
+}
+
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
+  return dragOperationMask_;
+}
+
+- (void)startDrag {
+  [self fillPasteboard];
+  NSEvent* currentEvent = [NSApp currentEvent];
+
+  // Synthesize an event for dragging, since we can't be sure that
+  // [NSApp currentEvent] will return a valid dragging event.
+  NSWindow* window = [contentsView_ window];
+  NSPoint position = [window mouseLocationOutsideOfEventStream];
+  NSTimeInterval eventTime = [currentEvent timestamp];
+  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
+                                          location:position
+                                     modifierFlags:NSLeftMouseDraggedMask
+                                         timestamp:eventTime
+                                      windowNumber:[window windowNumber]
+                                           context:nil
+                                       eventNumber:0
+                                        clickCount:1
+                                          pressure:1.0];
+  [window dragImage:[self dragImage]
+                 at:position
+             offset:NSZeroSize
+              event:dragEvent
+         pasteboard:pasteboard_
+             source:self
+          slideBack:YES];
+}
+
+- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint
+  operation:(NSDragOperation)operation {
+}
+
+- (void)endDragAt:(NSPoint)screenPoint
+        operation:(NSDragOperation)operation {
+  [contentsView_ tabContents]->SystemDragEnded();
+
+  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
+  if (rvh) {
+    NSPoint localPoint = [contentsView_ convertPoint:screenPoint fromView: nil];
+    FlipPointCoordinates(screenPoint, localPoint, contentsView_);
+    rvh->DragSourceEndedAt(localPoint.x, localPoint.y,
+                           screenPoint.x, screenPoint.y,
+                           static_cast<WebKit::WebDragOperation>(operation));
+  }
+
+  // Make sure the pasteboard owner isn't us.
+  [pasteboard_ declareTypes:[NSArray array] owner:nil];
+}
+
+- (void)moveDragTo:(NSPoint)screenPoint {
+  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
+  if (rvh) {
+    NSPoint localPoint = [contentsView_ convertPoint:screenPoint fromView:nil];
+    FlipPointCoordinates(screenPoint, localPoint, contentsView_);
+    rvh->DragSourceMovedTo(localPoint.x, localPoint.y,
+                           screenPoint.x, screenPoint.y);
+  }
+}
+
+@end  // @implementation WebContentsDragSource
+
diff --git a/chrome/browser/ui/cocoa/web_drag_source.h b/chrome/browser/ui/cocoa/tab_contents/web_drag_source.h
similarity index 100%
rename from chrome/browser/ui/cocoa/web_drag_source.h
rename to chrome/browser/ui/cocoa/tab_contents/web_drag_source.h
diff --git a/chrome/browser/ui/cocoa/tab_contents/web_drag_source.mm b/chrome/browser/ui/cocoa/tab_contents/web_drag_source.mm
new file mode 100644
index 0000000..84335a5
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/web_drag_source.mm
@@ -0,0 +1,419 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tab_contents/web_drag_source.h"
+
+#include "app/mac/nsimage_cache.h"
+#include "base/file_path.h"
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "base/task.h"
+#include "base/threading/thread.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/drag_download_file.h"
+#include "chrome/browser/download/drag_download_util.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view_mac.h"
+#include "net/base/file_stream.h"
+#include "net/base/net_util.h"
+#import "third_party/mozilla/NSPasteboard+Utils.h"
+#include "webkit/glue/webdropdata.h"
+
+using base::SysNSStringToUTF8;
+using base::SysUTF8ToNSString;
+using base::SysUTF16ToNSString;
+using net::FileStream;
+
+
+namespace {
+
+// An unofficial standard pasteboard title type to be provided alongside the
+// |NSURLPboardType|.
+NSString* const kNSURLTitlePboardType = @"public.url-name";
+
+// Returns a filename appropriate for the drop data
+// TODO(viettrungluu): Refactor to make it common across platforms,
+// and move it somewhere sensible.
+FilePath GetFileNameFromDragData(const WebDropData& drop_data) {
+  // Images without ALT text will only have a file extension so we need to
+  // synthesize one from the provided extension and URL.
+  FilePath file_name([SysUTF16ToNSString(drop_data.file_description_filename)
+          fileSystemRepresentation]);
+  file_name = file_name.BaseName().RemoveExtension();
+
+  if (file_name.empty()) {
+    // Retrieve the name from the URL.
+    string16 suggested_filename =
+        net::GetSuggestedFilename(drop_data.url, "", "", string16());
+    file_name = FilePath(
+        [SysUTF16ToNSString(suggested_filename) fileSystemRepresentation]);
+  }
+
+  file_name = file_name.ReplaceExtension([SysUTF16ToNSString(
+          drop_data.file_extension) fileSystemRepresentation]);
+
+  return file_name;
+}
+
+// This class's sole task is to write out data for a promised file; the caller
+// is responsible for opening the file.
+class PromiseWriterTask : public Task {
+ public:
+  // Assumes ownership of file_stream.
+  PromiseWriterTask(const WebDropData& drop_data,
+                    FileStream* file_stream);
+  virtual ~PromiseWriterTask();
+  virtual void Run();
+
+ private:
+  WebDropData drop_data_;
+
+  // This class takes ownership of file_stream_ and will close and delete it.
+  scoped_ptr<FileStream> file_stream_;
+};
+
+// Takes the drop data and an open file stream (which it takes ownership of and
+// will close and delete).
+PromiseWriterTask::PromiseWriterTask(const WebDropData& drop_data,
+                                     FileStream* file_stream) :
+    drop_data_(drop_data) {
+  file_stream_.reset(file_stream);
+  DCHECK(file_stream_.get());
+}
+
+PromiseWriterTask::~PromiseWriterTask() {
+  DCHECK(file_stream_.get());
+  if (file_stream_.get())
+    file_stream_->Close();
+}
+
+void PromiseWriterTask::Run() {
+  CHECK(file_stream_.get());
+  file_stream_->Write(drop_data_.file_contents.data(),
+                      drop_data_.file_contents.length(),
+                      NULL);
+
+  // Let our destructor take care of business.
+}
+
+}  // namespace
+
+
+@interface WebDragSource(Private)
+
+- (void)fillPasteboard;
+- (NSImage*)dragImage;
+
+@end  // @interface WebDragSource(Private)
+
+
+@implementation WebDragSource
+
+- (id)initWithContentsView:(TabContentsViewCocoa*)contentsView
+                  dropData:(const WebDropData*)dropData
+                     image:(NSImage*)image
+                    offset:(NSPoint)offset
+                pasteboard:(NSPasteboard*)pboard
+         dragOperationMask:(NSDragOperation)dragOperationMask {
+  if ((self = [super init])) {
+    contentsView_ = contentsView;
+    DCHECK(contentsView_);
+
+    dropData_.reset(new WebDropData(*dropData));
+    DCHECK(dropData_.get());
+
+    dragImage_.reset([image retain]);
+    imageOffset_ = offset;
+
+    pasteboard_.reset([pboard retain]);
+    DCHECK(pasteboard_.get());
+
+    dragOperationMask_ = dragOperationMask;
+
+    [self fillPasteboard];
+  }
+
+  return self;
+}
+
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
+  return dragOperationMask_;
+}
+
+- (void)lazyWriteToPasteboard:(NSPasteboard*)pboard forType:(NSString*)type {
+  // NSHTMLPboardType requires the character set to be declared. Otherwise, it
+  // assumes US-ASCII. Awesome.
+  static const string16 kHtmlHeader =
+      ASCIIToUTF16("<meta http-equiv=\"Content-Type\" "
+                   "content=\"text/html;charset=UTF-8\">");
+
+  // Be extra paranoid; avoid crashing.
+  if (!dropData_.get()) {
+    NOTREACHED() << "No drag-and-drop data available for lazy write.";
+    return;
+  }
+
+  // HTML.
+  if ([type isEqualToString:NSHTMLPboardType]) {
+    DCHECK(!dropData_->text_html.empty());
+    // See comment on |kHtmlHeader| above.
+    [pboard setString:SysUTF16ToNSString(kHtmlHeader + dropData_->text_html)
+              forType:NSHTMLPboardType];
+
+  // URL.
+  } else if ([type isEqualToString:NSURLPboardType]) {
+    DCHECK(dropData_->url.is_valid());
+    NSURL* url = [NSURL URLWithString:SysUTF8ToNSString(dropData_->url.spec())];
+    [url writeToPasteboard:pboard];
+
+  // URL title.
+  } else if ([type isEqualToString:kNSURLTitlePboardType]) {
+    [pboard setString:SysUTF16ToNSString(dropData_->url_title)
+              forType:kNSURLTitlePboardType];
+
+  // File contents.
+  } else if ([type isEqualToString:NSFileContentsPboardType] ||
+      [type isEqualToString:NSCreateFileContentsPboardType(
+              SysUTF16ToNSString(dropData_->file_extension))]) {
+    // TODO(viettrungluu: find something which is known to accept
+    // NSFileContentsPboardType to check that this actually works!
+    scoped_nsobject<NSFileWrapper> file_wrapper(
+        [[NSFileWrapper alloc] initRegularFileWithContents:[NSData
+                dataWithBytes:dropData_->file_contents.data()
+                       length:dropData_->file_contents.length()]]);
+    [file_wrapper setPreferredFilename:SysUTF8ToNSString(
+            GetFileNameFromDragData(*dropData_).value())];
+    [pboard writeFileWrapper:file_wrapper];
+
+  // TIFF.
+  } else if ([type isEqualToString:NSTIFFPboardType]) {
+    // TODO(viettrungluu): This is a bit odd since we rely on Cocoa to render
+    // our image into a TIFF. This is also suboptimal since this is all done
+    // synchronously. I'm not sure there's much we can easily do about it.
+    scoped_nsobject<NSImage> image(
+        [[NSImage alloc] initWithData:[NSData
+                dataWithBytes:dropData_->file_contents.data()
+                       length:dropData_->file_contents.length()]]);
+    [pboard setData:[image TIFFRepresentation] forType:NSTIFFPboardType];
+
+  // Plain text.
+  } else if ([type isEqualToString:NSStringPboardType]) {
+    DCHECK(!dropData_->plain_text.empty());
+    [pboard setString:SysUTF16ToNSString(dropData_->plain_text)
+              forType:NSStringPboardType];
+
+  // Oops!
+  } else {
+    NOTREACHED() << "Asked for a drag pasteboard type we didn't offer.";
+  }
+}
+
+- (NSPoint)convertScreenPoint:(NSPoint)screenPoint {
+  DCHECK([contentsView_ window]);
+  NSPoint basePoint = [[contentsView_ window] convertScreenToBase:screenPoint];
+  return [contentsView_ convertPoint:basePoint fromView:nil];
+}
+
+- (void)startDrag {
+  NSEvent* currentEvent = [NSApp currentEvent];
+
+  // Synthesize an event for dragging, since we can't be sure that
+  // [NSApp currentEvent] will return a valid dragging event.
+  NSWindow* window = [contentsView_ window];
+  NSPoint position = [window mouseLocationOutsideOfEventStream];
+  NSTimeInterval eventTime = [currentEvent timestamp];
+  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
+                                          location:position
+                                     modifierFlags:NSLeftMouseDraggedMask
+                                         timestamp:eventTime
+                                      windowNumber:[window windowNumber]
+                                           context:nil
+                                       eventNumber:0
+                                        clickCount:1
+                                          pressure:1.0];
+
+  if (dragImage_) {
+    position.x -= imageOffset_.x;
+    // Deal with Cocoa's flipped coordinate system.
+    position.y -= [dragImage_.get() size].height - imageOffset_.y;
+  }
+  // Per kwebster, offset arg is ignored, see -_web_DragImageForElement: in
+  // third_party/WebKit/Source/WebKit/mac/Misc/WebNSViewExtras.m.
+  [window dragImage:[self dragImage]
+                 at:position
+             offset:NSZeroSize
+              event:dragEvent
+         pasteboard:pasteboard_
+             source:contentsView_
+          slideBack:YES];
+}
+
+- (void)endDragAt:(NSPoint)screenPoint
+        operation:(NSDragOperation)operation {
+  [contentsView_ tabContents]->SystemDragEnded();
+
+  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
+  if (rvh) {
+    // Convert |screenPoint| to view coordinates and flip it.
+    NSPoint localPoint = NSMakePoint(0, 0);
+    if ([contentsView_ window])
+      localPoint = [self convertScreenPoint:screenPoint];
+    NSRect viewFrame = [contentsView_ frame];
+    localPoint.y = viewFrame.size.height - localPoint.y;
+    // Flip |screenPoint|.
+    NSRect screenFrame = [[[contentsView_ window] screen] frame];
+    screenPoint.y = screenFrame.size.height - screenPoint.y;
+
+    rvh->DragSourceEndedAt(localPoint.x, localPoint.y,
+                           screenPoint.x, screenPoint.y,
+                           static_cast<WebKit::WebDragOperation>(operation));
+  }
+
+  // Make sure the pasteboard owner isn't us.
+  [pasteboard_ declareTypes:[NSArray array] owner:nil];
+}
+
+- (void)moveDragTo:(NSPoint)screenPoint {
+  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
+  if (rvh) {
+    // Convert |screenPoint| to view coordinates and flip it.
+    NSPoint localPoint = NSMakePoint(0, 0);
+    if ([contentsView_ window])
+      localPoint = [self convertScreenPoint:screenPoint];
+    NSRect viewFrame = [contentsView_ frame];
+    localPoint.y = viewFrame.size.height - localPoint.y;
+    // Flip |screenPoint|.
+    NSRect screenFrame = [[[contentsView_ window] screen] frame];
+    screenPoint.y = screenFrame.size.height - screenPoint.y;
+
+    rvh->DragSourceMovedTo(localPoint.x, localPoint.y,
+                           screenPoint.x, screenPoint.y);
+  }
+}
+
+- (NSString*)dragPromisedFileTo:(NSString*)path {
+  // Be extra paranoid; avoid crashing.
+  if (!dropData_.get()) {
+    NOTREACHED() << "No drag-and-drop data available for promised file.";
+    return nil;
+  }
+
+  FilePath fileName = downloadFileName_.empty() ?
+      GetFileNameFromDragData(*dropData_) : downloadFileName_;
+  FilePath filePath(SysNSStringToUTF8(path));
+  filePath = filePath.Append(fileName);
+  FileStream* fileStream =
+      drag_download_util::CreateFileStreamForDrop(&filePath);
+  if (!fileStream)
+    return nil;
+
+  if (downloadURL_.is_valid()) {
+    TabContents* tabContents = [contentsView_ tabContents];
+    scoped_refptr<DragDownloadFile> dragFileDownloader(new DragDownloadFile(
+        filePath,
+        linked_ptr<net::FileStream>(fileStream),
+        downloadURL_,
+        tabContents->GetURL(),
+        tabContents->encoding(),
+        tabContents));
+
+    // The finalizer will take care of closing and deletion.
+    dragFileDownloader->Start(
+        new drag_download_util::PromiseFileFinalizer(dragFileDownloader));
+  } else {
+    // The writer will take care of closing and deletion.
+    g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
+        new PromiseWriterTask(*dropData_, fileStream));
+  }
+
+  // Once we've created the file, we should return the file name.
+  return SysUTF8ToNSString(filePath.BaseName().value());
+}
+
+@end  // @implementation WebDragSource
+
+
+@implementation WebDragSource (Private)
+
+- (void)fillPasteboard {
+  DCHECK(pasteboard_.get());
+
+  [pasteboard_ declareTypes:[NSArray array] owner:contentsView_];
+
+  // HTML.
+  if (!dropData_->text_html.empty())
+    [pasteboard_ addTypes:[NSArray arrayWithObject:NSHTMLPboardType]
+                    owner:contentsView_];
+
+  // URL (and title).
+  if (dropData_->url.is_valid())
+    [pasteboard_ addTypes:[NSArray arrayWithObjects:NSURLPboardType,
+                                                    kNSURLTitlePboardType, nil]
+                    owner:contentsView_];
+
+  // File.
+  if (!dropData_->file_contents.empty() ||
+      !dropData_->download_metadata.empty()) {
+    NSString* fileExtension = 0;
+
+    if (dropData_->download_metadata.empty()) {
+      // |dropData_->file_extension| comes with the '.', which we must strip.
+      fileExtension = (dropData_->file_extension.length() > 0) ?
+          SysUTF16ToNSString(dropData_->file_extension.substr(1)) : @"";
+    } else {
+      string16 mimeType;
+      FilePath fileName;
+      if (drag_download_util::ParseDownloadMetadata(
+              dropData_->download_metadata,
+              &mimeType,
+              &fileName,
+              &downloadURL_)) {
+        std::string contentDisposition =
+            "attachment; filename=" + fileName.value();
+        download_util::GenerateFileName(downloadURL_,
+                                        contentDisposition,
+                                        std::string(),
+                                        UTF16ToUTF8(mimeType),
+                                        &downloadFileName_);
+        fileExtension = SysUTF8ToNSString(downloadFileName_.Extension());
+      }
+    }
+
+    if (fileExtension) {
+      // File contents (with and without specific type), file (HFS) promise,
+      // TIFF.
+      // TODO(viettrungluu): others?
+      [pasteboard_ addTypes:[NSArray arrayWithObjects:
+                                  NSFileContentsPboardType,
+                                  NSCreateFileContentsPboardType(fileExtension),
+                                  NSFilesPromisePboardType,
+                                  NSTIFFPboardType,
+                                  nil]
+                      owner:contentsView_];
+
+      // For the file promise, we need to specify the extension.
+      [pasteboard_ setPropertyList:[NSArray arrayWithObject:fileExtension]
+                           forType:NSFilesPromisePboardType];
+    }
+  }
+
+  // Plain text.
+  if (!dropData_->plain_text.empty())
+    [pasteboard_ addTypes:[NSArray arrayWithObject:NSStringPboardType]
+                    owner:contentsView_];
+}
+
+- (NSImage*)dragImage {
+  if (dragImage_)
+    return dragImage_;
+
+  // Default to returning a generic image.
+  return app::mac::GetCachedImageWithName(@"nav.pdf");
+}
+
+@end  // @implementation WebDragSource (Private)
diff --git a/chrome/browser/ui/cocoa/web_drop_target.h b/chrome/browser/ui/cocoa/tab_contents/web_drop_target.h
similarity index 100%
rename from chrome/browser/ui/cocoa/web_drop_target.h
rename to chrome/browser/ui/cocoa/tab_contents/web_drop_target.h
diff --git a/chrome/browser/ui/cocoa/tab_contents/web_drop_target.mm b/chrome/browser/ui/cocoa/tab_contents/web_drop_target.mm
new file mode 100644
index 0000000..af1226a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/web_drop_target.mm
@@ -0,0 +1,283 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tab_contents/web_drop_target.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_node_data.h"
+#include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#import "third_party/mozilla/NSPasteboard+Utils.h"
+#include "webkit/glue/webdropdata.h"
+#include "webkit/glue/window_open_disposition.h"
+
+using WebKit::WebDragOperationsMask;
+
+@implementation WebDropTarget
+
+// |contents| is the TabContents representing this tab, used to communicate
+// drag&drop messages to WebCore and handle navigation on a successful drop
+// (if necessary).
+- (id)initWithTabContents:(TabContents*)contents {
+  if ((self = [super init])) {
+    tabContents_ = contents;
+  }
+  return self;
+}
+
+// Call to set whether or not we should allow the drop. Takes effect the
+// next time |-draggingUpdated:| is called.
+- (void)setCurrentOperation: (NSDragOperation)operation {
+  current_operation_ = operation;
+}
+
+// Given a point in window coordinates and a view in that window, return a
+// flipped point in the coordinate system of |view|.
+- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint
+                            view:(NSView*)view {
+  DCHECK(view);
+  NSPoint viewPoint =  [view convertPoint:windowPoint fromView:nil];
+  NSRect viewFrame = [view frame];
+  viewPoint.y = viewFrame.size.height - viewPoint.y;
+  return viewPoint;
+}
+
+// Given a point in window coordinates and a view in that window, return a
+// flipped point in screen coordinates.
+- (NSPoint)flipWindowPointToScreen:(const NSPoint&)windowPoint
+                              view:(NSView*)view {
+  DCHECK(view);
+  NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
+  NSScreen* screen = [[view window] screen];
+  NSRect screenFrame = [screen frame];
+  screenPoint.y = screenFrame.size.height - screenPoint.y;
+  return screenPoint;
+}
+
+// Return YES if the drop site only allows drops that would navigate.  If this
+// is the case, we don't want to pass messages to the renderer because there's
+// really no point (i.e., there's nothing that cares about the mouse position or
+// entering and exiting).  One example is an interstitial page (e.g., safe
+// browsing warning).
+- (BOOL)onlyAllowsNavigation {
+  return tabContents_->showing_interstitial_page();
+}
+
+// Messages to send during the tracking of a drag, ususally upon recieving
+// calls from the view system. Communicates the drag messages to WebCore.
+
+- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info
+                              view:(NSView*)view {
+  // Save off the RVH so we can tell if it changes during a drag. If it does,
+  // we need to send a new enter message in draggingUpdated:.
+  currentRVH_ = tabContents_->render_view_host();
+
+  if ([self onlyAllowsNavigation]) {
+    if ([[info draggingPasteboard] containsURLData])
+      return NSDragOperationCopy;
+    return NSDragOperationNone;
+  }
+
+  // If the tab is showing the boomark manager, send BookmarkDrag events
+  RenderViewHostDelegate::BookmarkDrag* dragDelegate =
+      tabContents_->GetBookmarkDragDelegate();
+  BookmarkNodeData dragData;
+  if(dragDelegate && dragData.ReadFromDragClipboard())
+    dragDelegate->OnDragEnter(dragData);
+
+  // Fill out a WebDropData from pasteboard.
+  WebDropData data;
+  [self populateWebDropData:&data fromPasteboard:[info draggingPasteboard]];
+
+  // Create the appropriate mouse locations for WebCore. The draggingLocation
+  // is in window coordinates. Both need to be flipped.
+  NSPoint windowPoint = [info draggingLocation];
+  NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+  NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+  NSDragOperation mask = [info draggingSourceOperationMask];
+  tabContents_->render_view_host()->DragTargetDragEnter(data,
+      gfx::Point(viewPoint.x, viewPoint.y),
+      gfx::Point(screenPoint.x, screenPoint.y),
+      static_cast<WebDragOperationsMask>(mask));
+
+  // We won't know the true operation (whether the drag is allowed) until we
+  // hear back from the renderer. For now, be optimistic:
+  current_operation_ = NSDragOperationCopy;
+  return current_operation_;
+}
+
+- (void)draggingExited:(id<NSDraggingInfo>)info {
+  DCHECK(currentRVH_);
+  if (currentRVH_ != tabContents_->render_view_host())
+    return;
+
+  // Nothing to do in the interstitial case.
+
+  tabContents_->render_view_host()->DragTargetDragLeave();
+}
+
+- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
+                              view:(NSView*)view {
+  DCHECK(currentRVH_);
+  if (currentRVH_ != tabContents_->render_view_host())
+    [self draggingEntered:info view:view];
+
+  if ([self onlyAllowsNavigation]) {
+    if ([[info draggingPasteboard] containsURLData])
+      return NSDragOperationCopy;
+    return NSDragOperationNone;
+  }
+
+  // Create the appropriate mouse locations for WebCore. The draggingLocation
+  // is in window coordinates.
+  NSPoint windowPoint = [info draggingLocation];
+  NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+  NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+  NSDragOperation mask = [info draggingSourceOperationMask];
+  tabContents_->render_view_host()->DragTargetDragOver(
+      gfx::Point(viewPoint.x, viewPoint.y),
+      gfx::Point(screenPoint.x, screenPoint.y),
+      static_cast<WebDragOperationsMask>(mask));
+
+  // If the tab is showing the boomark manager, send BookmarkDrag events
+  RenderViewHostDelegate::BookmarkDrag* dragDelegate =
+      tabContents_->GetBookmarkDragDelegate();
+  BookmarkNodeData dragData;
+  if(dragDelegate && dragData.ReadFromDragClipboard())
+    dragDelegate->OnDragOver(dragData);
+  return current_operation_;
+}
+
+- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
+                              view:(NSView*)view {
+  if (currentRVH_ != tabContents_->render_view_host())
+    [self draggingEntered:info view:view];
+
+  // Check if we only allow navigation and navigate to a url on the pasteboard.
+  if ([self onlyAllowsNavigation]) {
+    NSPasteboard* pboard = [info draggingPasteboard];
+    if ([pboard containsURLData]) {
+      GURL url;
+      [self populateURL:&url
+          andTitle:NULL
+          fromPasteboard:pboard
+          convertingFilenames:YES];
+      tabContents_->OpenURL(url, GURL(), CURRENT_TAB,
+                            PageTransition::AUTO_BOOKMARK);
+      return YES;
+    }
+    return NO;
+  }
+
+  // If the tab is showing the boomark manager, send BookmarkDrag events
+  RenderViewHostDelegate::BookmarkDrag* dragDelegate =
+      tabContents_->GetBookmarkDragDelegate();
+  BookmarkNodeData dragData;
+  if(dragDelegate && dragData.ReadFromDragClipboard())
+    dragDelegate->OnDrop(dragData);
+
+  currentRVH_ = NULL;
+
+  // Create the appropriate mouse locations for WebCore. The draggingLocation
+  // is in window coordinates. Both need to be flipped.
+  NSPoint windowPoint = [info draggingLocation];
+  NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+  NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+  tabContents_->render_view_host()->DragTargetDrop(
+      gfx::Point(viewPoint.x, viewPoint.y),
+      gfx::Point(screenPoint.x, screenPoint.y));
+
+  return YES;
+}
+
+// Populate the |url| and |title| with URL data in |pboard|. There may be more
+// than one, but we only handle dropping the first. |url| must not be |NULL|;
+// |title| is an optional parameter. Returns |YES| if URL data was obtained from
+// the pasteboard, |NO| otherwise. If |convertFilenames| is |YES|, the function
+// will also attempt to convert filenames in |pboard| to file URLs.
+- (BOOL)populateURL:(GURL*)url
+    andTitle:(string16*)title
+    fromPasteboard:(NSPasteboard*)pboard
+    convertingFilenames:(BOOL)convertFilenames {
+  DCHECK(url);
+  DCHECK(title);
+
+  // Bail out early if there's no URL data.
+  if (![pboard containsURLData])
+    return NO;
+
+  // |-getURLs:andTitles:convertingFilenames:| will already validate URIs so we
+  // don't need to again. The arrays returned are both of NSString's.
+  NSArray* urls = nil;
+  NSArray* titles = nil;
+  [pboard getURLs:&urls andTitles:&titles convertingFilenames:convertFilenames];
+  DCHECK_EQ([urls count], [titles count]);
+  // It's possible that no URLs were actually provided!
+  if (![urls count])
+    return NO;
+  NSString* urlString = [urls objectAtIndex:0];
+  if ([urlString length]) {
+    // Check again just to make sure to not assign NULL into a std::string,
+    // which throws an exception.
+    const char* utf8Url = [urlString UTF8String];
+    if (utf8Url) {
+      *url = GURL(utf8Url);
+      // Extra paranoia check.
+      if (title && [titles count])
+        *title = base::SysNSStringToUTF16([titles objectAtIndex:0]);
+    }
+  }
+  return YES;
+}
+
+// Given |data|, which should not be nil, fill it in using the contents of the
+// given pasteboard.
+- (void)populateWebDropData:(WebDropData*)data
+             fromPasteboard:(NSPasteboard*)pboard {
+  DCHECK(data);
+  DCHECK(pboard);
+  NSArray* types = [pboard types];
+
+  // Get URL if possible. To avoid exposing file system paths to web content,
+  // filenames in the drag are not converted to file URLs.
+  [self populateURL:&data->url
+      andTitle:&data->url_title
+      fromPasteboard:pboard
+      convertingFilenames:NO];
+
+  // Get plain text.
+  if ([types containsObject:NSStringPboardType]) {
+    data->plain_text =
+        base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]);
+  }
+
+  // Get HTML. If there's no HTML, try RTF.
+  if ([types containsObject:NSHTMLPboardType]) {
+    data->text_html =
+        base::SysNSStringToUTF16([pboard stringForType:NSHTMLPboardType]);
+  } else if ([types containsObject:NSRTFPboardType]) {
+    NSString* html = [pboard htmlFromRtf];
+    data->text_html = base::SysNSStringToUTF16(html);
+  }
+
+  // Get files.
+  if ([types containsObject:NSFilenamesPboardType]) {
+    NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
+    if ([files isKindOfClass:[NSArray class]] && [files count]) {
+      for (NSUInteger i = 0; i < [files count]; i++) {
+        NSString* filename = [files objectAtIndex:i];
+        BOOL isDir = NO;
+        BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:filename
+                                                           isDirectory:&isDir];
+        if (exists && !isDir)
+          data->filenames.push_back(base::SysNSStringToUTF16(filename));
+      }
+    }
+  }
+
+  // TODO(pinkerton): Get file contents. http://crbug.com/34661
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/web_drop_target_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/web_drop_target_unittest.mm
new file mode 100644
index 0000000..c10e22c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tab_contents/web_drop_target_unittest.mm
@@ -0,0 +1,166 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/browser/tab_contents/test_tab_contents.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/tab_contents/web_drop_target.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "third_party/mozilla/NSPasteboard+Utils.h"
+#include "webkit/glue/webdropdata.h"
+
+class WebDropTargetTest : public RenderViewHostTestHarness {
+ public:
+  virtual void SetUp() {
+    RenderViewHostTestHarness::SetUp();
+    CocoaTest::BootstrapCocoa();
+    drop_target_.reset([[WebDropTarget alloc] initWithTabContents:contents()]);
+  }
+
+  void PutURLOnPasteboard(NSString* urlString, NSPasteboard* pboard) {
+    [pboard declareTypes:[NSArray arrayWithObject:NSURLPboardType]
+                   owner:nil];
+    NSURL* url = [NSURL URLWithString:urlString];
+    EXPECT_TRUE(url);
+    [url writeToPasteboard:pboard];
+  }
+
+  void PutCoreURLAndTitleOnPasteboard(NSString* urlString, NSString* title,
+                                      NSPasteboard* pboard) {
+    [pboard
+        declareTypes:[NSArray arrayWithObjects:kCorePasteboardFlavorType_url,
+                                               kCorePasteboardFlavorType_urln,
+                                               nil]
+               owner:nil];
+    [pboard setString:urlString
+              forType:kCorePasteboardFlavorType_url];
+    [pboard setString:title
+              forType:kCorePasteboardFlavorType_urln];
+  }
+
+  base::mac::ScopedNSAutoreleasePool pool_;
+  scoped_nsobject<WebDropTarget> drop_target_;
+};
+
+// Make sure nothing leaks.
+TEST_F(WebDropTargetTest, Init) {
+  EXPECT_TRUE(drop_target_);
+}
+
+// Test flipping of coordinates given a point in window coordinates.
+TEST_F(WebDropTargetTest, Flip) {
+  NSPoint windowPoint = NSZeroPoint;
+  scoped_nsobject<NSWindow> window([[CocoaTestHelperWindow alloc] init]);
+  NSPoint viewPoint =
+      [drop_target_ flipWindowPointToView:windowPoint
+                                     view:[window contentView]];
+  NSPoint screenPoint =
+      [drop_target_ flipWindowPointToScreen:windowPoint
+                               view:[window contentView]];
+  EXPECT_EQ(0, viewPoint.x);
+  EXPECT_EQ(600, viewPoint.y);
+  EXPECT_EQ(0, screenPoint.x);
+  // We can't put a value on the screen size since everyone will have a
+  // different one.
+  EXPECT_NE(0, screenPoint.y);
+}
+
+TEST_F(WebDropTargetTest, URL) {
+  NSPasteboard* pboard = nil;
+  NSString* url = nil;
+  NSString* title = nil;
+  GURL result_url;
+  string16 result_title;
+
+  // Put a URL on the pasteboard and check it.
+  pboard = [NSPasteboard pasteboardWithUniqueName];
+  url = @"http://www.google.com/";
+  PutURLOnPasteboard(url, pboard);
+  EXPECT_TRUE([drop_target_ populateURL:&result_url
+                               andTitle:&result_title
+                         fromPasteboard:pboard
+                    convertingFilenames:NO]);
+  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
+  [pboard releaseGlobally];
+
+  // Put a 'url ' and 'urln' on the pasteboard and check it.
+  pboard = [NSPasteboard pasteboardWithUniqueName];
+  url = @"http://www.google.com/";
+  title = @"Title of Awesomeness!",
+  PutCoreURLAndTitleOnPasteboard(url, title, pboard);
+  EXPECT_TRUE([drop_target_ populateURL:&result_url
+                               andTitle:&result_title
+                         fromPasteboard:pboard
+                    convertingFilenames:NO]);
+  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
+  EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
+  [pboard releaseGlobally];
+
+  // Also check that it passes file:// via 'url '/'urln' properly.
+  pboard = [NSPasteboard pasteboardWithUniqueName];
+  url = @"file:///tmp/dont_delete_me.txt";
+  title = @"very important";
+  PutCoreURLAndTitleOnPasteboard(url, title, pboard);
+  EXPECT_TRUE([drop_target_ populateURL:&result_url
+                               andTitle:&result_title
+                         fromPasteboard:pboard
+                    convertingFilenames:NO]);
+  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
+  EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
+  [pboard releaseGlobally];
+
+  // And javascript:.
+  pboard = [NSPasteboard pasteboardWithUniqueName];
+  url = @"javascript:open('http://www.youtube.com/')";
+  title = @"kill some time";
+  PutCoreURLAndTitleOnPasteboard(url, title, pboard);
+  EXPECT_TRUE([drop_target_ populateURL:&result_url
+                               andTitle:&result_title
+                         fromPasteboard:pboard
+                    convertingFilenames:NO]);
+  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
+  EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
+  [pboard releaseGlobally];
+
+  pboard = [NSPasteboard pasteboardWithUniqueName];
+  url = @"/bin/sh";
+  [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
+                 owner:nil];
+  [pboard setPropertyList:[NSArray arrayWithObject:url]
+                  forType:NSFilenamesPboardType];
+  EXPECT_FALSE([drop_target_ populateURL:&result_url
+                                andTitle:&result_title
+                          fromPasteboard:pboard
+                    convertingFilenames:NO]);
+  EXPECT_TRUE([drop_target_ populateURL:&result_url
+                               andTitle:&result_title
+                         fromPasteboard:pboard
+                    convertingFilenames:YES]);
+  EXPECT_EQ("file://localhost/bin/sh", result_url.spec());
+  EXPECT_EQ("sh", UTF16ToUTF8(result_title));
+  [pboard releaseGlobally];
+}
+
+TEST_F(WebDropTargetTest, Data) {
+  WebDropData data;
+  NSPasteboard* pboard = [NSPasteboard pasteboardWithUniqueName];
+
+  PutURLOnPasteboard(@"http://www.google.com", pboard);
+  [pboard addTypes:[NSArray arrayWithObjects:NSHTMLPboardType,
+                              NSStringPboardType, nil]
+             owner:nil];
+  NSString* htmlString = @"<html><body><b>hi there</b></body></html>";
+  NSString* textString = @"hi there";
+  [pboard setString:htmlString forType:NSHTMLPboardType];
+  [pboard setString:textString forType:NSStringPboardType];
+  [drop_target_ populateWebDropData:&data fromPasteboard:pboard];
+  EXPECT_EQ(data.url.spec(), "http://www.google.com/");
+  EXPECT_EQ(base::SysNSStringToUTF16(textString), data.plain_text);
+  EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.text_html);
+
+  [pboard releaseGlobally];
+}
diff --git a/chrome/browser/ui/cocoa/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents_controller.h
deleted file mode 100644
index f821ea4..0000000
--- a/chrome/browser/ui/cocoa/tab_contents_controller.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_CONTROLLER_H_
-#pragma once
-
-#include <Cocoa/Cocoa.h>
-
-#include "base/scoped_ptr.h"
-
-class TabContents;
-class TabContentsNotificationBridge;
-@class TabContentsController;
-
-// The interface for the tab contents view controller's delegate.
-
-@protocol TabContentsControllerDelegate
-
-// Tells the delegate when the tab contents view's frame is about to change.
-- (void)tabContentsViewFrameWillChange:(TabContentsController*)source
-                             frameRect:(NSRect)frameRect;
-
-@end
-
-// A class that controls the TabContents view. It manages displaying the
-// native view for a given TabContents.
-// Note that just creating the class does not display the view. We defer
-// inserting it until the box is the correct size to avoid multiple resize
-// messages to the renderer. You must call |-ensureContentsVisible| to display
-// the render widget host view.
-
-@interface TabContentsController : NSViewController {
- @private
-  TabContents* contents_;  // weak
-  // Delegate to be notified about size changes.
-  id<TabContentsControllerDelegate> delegate_;  // weak
-  scoped_ptr<TabContentsNotificationBridge> tabContentsBridge_;
-}
-@property(readonly, nonatomic) TabContents* tabContents;
-
-- (id)initWithContents:(TabContents*)contents
-              delegate:(id<TabContentsControllerDelegate>)delegate;
-
-// Call when the tab contents is about to be replaced with the currently
-// selected tab contents to do not trigger unnecessary content relayout.
-- (void)ensureContentsSizeDoesNotChange;
-
-// Call when the tab view is properly sized and the render widget host view
-// should be put into the view hierarchy.
-- (void)ensureContentsVisible;
-
-// Call to change the underlying tab contents object. View is not changed,
-// call |-ensureContentsVisible| to display the |newContents|'s render widget
-// host view.
-- (void)changeTabContents:(TabContents*)newContents;
-
-// Called when the tab contents is the currently selected tab and is about to be
-// removed from the view hierarchy.
-- (void)willBecomeUnselectedTab;
-
-// Called when the tab contents is about to be put into the view hierarchy as
-// the selected tab. Handles things such as ensuring the toolbar is correctly
-// enabled.
-- (void)willBecomeSelectedTab;
-
-// Called when the tab contents is updated in some non-descript way (the
-// notification from the model isn't specific). |updatedContents| could reflect
-// an entirely new tab contents object.
-- (void)tabDidChange:(TabContents*)updatedContents;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents_controller.mm
deleted file mode 100644
index f710755..0000000
--- a/chrome/browser/ui/cocoa/tab_contents_controller.mm
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-
-
-@interface TabContentsController(Private)
-// Forwards frame update to |delegate_| (ResizeNotificationView calls it).
-- (void)tabContentsViewFrameWillChange:(NSRect)frameRect;
-// Notification from TabContents (forwarded by TabContentsNotificationBridge).
-- (void)tabContentsRenderViewHostChanged:(RenderViewHost*)oldHost
-                                 newHost:(RenderViewHost*)newHost;
-@end
-
-
-// A supporting C++ bridge object to register for TabContents notifications.
-
-class TabContentsNotificationBridge : public NotificationObserver {
- public:
-  explicit TabContentsNotificationBridge(TabContentsController* controller);
-
-  // Overriden from NotificationObserver.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-  // Register for |contents|'s notifications, remove all prior registrations.
-  void ChangeTabContents(TabContents* contents);
- private:
-  NotificationRegistrar registrar_;
-  TabContentsController* controller_;  // weak, owns us
-};
-
-TabContentsNotificationBridge::TabContentsNotificationBridge(
-    TabContentsController* controller)
-    : controller_(controller) {
-}
-
-void TabContentsNotificationBridge::Observe(
-    NotificationType type,
-    const NotificationSource& source,
-    const NotificationDetails& details) {
-  if (type == NotificationType::RENDER_VIEW_HOST_CHANGED) {
-    RenderViewHostSwitchedDetails* switched_details =
-        Details<RenderViewHostSwitchedDetails>(details).ptr();
-    [controller_ tabContentsRenderViewHostChanged:switched_details->old_host
-                                          newHost:switched_details->new_host];
-  } else {
-    NOTREACHED();
-  }
-}
-
-void TabContentsNotificationBridge::ChangeTabContents(TabContents* contents) {
-  registrar_.RemoveAll();
-  if (contents) {
-    registrar_.Add(this,
-                   NotificationType::RENDER_VIEW_HOST_CHANGED,
-                   Source<NavigationController>(&contents->controller()));
-  }
-}
-
-
-// A custom view that notifies |controller| that view's frame is changing.
-
-@interface ResizeNotificationView : NSView {
-  TabContentsController* controller_;
-}
-- (id)initWithController:(TabContentsController*)controller;
-@end
-
-@implementation ResizeNotificationView
-
-- (id)initWithController:(TabContentsController*)controller {
-  if ((self = [super initWithFrame:NSZeroRect])) {
-    controller_ = controller;
-  }
-  return self;
-}
-
-- (void)setFrame:(NSRect)frameRect {
-  [controller_ tabContentsViewFrameWillChange:frameRect];
-  [super setFrame:frameRect];
-}
-
-@end
-
-
-@implementation TabContentsController
-@synthesize tabContents = contents_;
-
-- (id)initWithContents:(TabContents*)contents
-              delegate:(id<TabContentsControllerDelegate>)delegate {
-  if ((self = [super initWithNibName:nil bundle:nil])) {
-    contents_ = contents;
-    delegate_ = delegate;
-    tabContentsBridge_.reset(new TabContentsNotificationBridge(self));
-    tabContentsBridge_->ChangeTabContents(contents);
-  }
-  return self;
-}
-
-- (void)dealloc {
-  // make sure our contents have been removed from the window
-  [[self view] removeFromSuperview];
-  [super dealloc];
-}
-
-- (void)loadView {
-  scoped_nsobject<ResizeNotificationView> view(
-      [[ResizeNotificationView alloc] initWithController:self]);
-  [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable];
-  [self setView:view];
-}
-
-- (void)ensureContentsSizeDoesNotChange {
-  if (contents_) {
-    NSView* contentsContainer = [self view];
-    NSArray* subviews = [contentsContainer subviews];
-    if ([subviews count] > 0)
-      [contents_->GetNativeView() setAutoresizingMask:NSViewNotSizable];
-  }
-}
-
-// Call when the tab view is properly sized and the render widget host view
-// should be put into the view hierarchy.
-- (void)ensureContentsVisible {
-  if (!contents_)
-    return;
-  NSView* contentsContainer = [self view];
-  NSArray* subviews = [contentsContainer subviews];
-  NSView* contentsNativeView = contents_->GetNativeView();
-
-  NSRect contentsNativeViewFrame = [contentsContainer frame];
-  contentsNativeViewFrame.origin = NSZeroPoint;
-
-  [delegate_ tabContentsViewFrameWillChange:self
-                                  frameRect:contentsNativeViewFrame];
-
-  // Native view is resized to the actual size before it becomes visible
-  // to avoid flickering.
-  [contentsNativeView setFrame:contentsNativeViewFrame];
-  if ([subviews count] == 0) {
-    [contentsContainer addSubview:contentsNativeView];
-  } else if ([subviews objectAtIndex:0] != contentsNativeView) {
-    [contentsContainer replaceSubview:[subviews objectAtIndex:0]
-                                 with:contentsNativeView];
-  }
-  // Restore autoresizing properties possibly stripped by
-  // ensureContentsSizeDoesNotChange call.
-  [contentsNativeView setAutoresizingMask:NSViewWidthSizable|
-                                          NSViewHeightSizable];
-}
-
-- (void)changeTabContents:(TabContents*)newContents {
-  contents_ = newContents;
-  tabContentsBridge_->ChangeTabContents(contents_);
-}
-
-- (void)tabContentsViewFrameWillChange:(NSRect)frameRect {
-  [delegate_ tabContentsViewFrameWillChange:self frameRect:frameRect];
-}
-
-- (void)tabContentsRenderViewHostChanged:(RenderViewHost*)oldHost
-                                 newHost:(RenderViewHost*)newHost {
-  if (oldHost && newHost && oldHost->view() && newHost->view()) {
-    newHost->view()->set_reserved_contents_rect(
-        oldHost->view()->reserved_contents_rect());
-  } else {
-    [delegate_ tabContentsViewFrameWillChange:self
-                                    frameRect:[[self view] frame]];
-  }
-}
-
-- (void)willBecomeUnselectedTab {
-  // The RWHV is ripped out of the view hierarchy on tab switches, so it never
-  // formally resigns first responder status.  Handle this by explicitly sending
-  // a Blur() message to the renderer, but only if the RWHV currently has focus.
-  RenderViewHost* rvh = [self tabContents]->render_view_host();
-  if (rvh && rvh->view() && rvh->view()->HasFocus())
-    rvh->Blur();
-}
-
-- (void)willBecomeSelectedTab {
-  // Do not explicitly call Focus() here, as the RWHV may not actually have
-  // focus (for example, if the omnibox has focus instead).  The TabContents
-  // logic will restore focus to the appropriate view.
-}
-
-- (void)tabDidChange:(TabContents*)updatedContents {
-  // Calling setContentView: here removes any first responder status
-  // the view may have, so avoid changing the view hierarchy unless
-  // the view is different.
-  if ([self tabContents] != updatedContents) {
-    [self changeTabContents:updatedContents];
-    if ([self tabContents])
-      [self ensureContentsVisible];
-  }
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/tab_controller.h b/chrome/browser/ui/cocoa/tab_controller.h
deleted file mode 100644
index 8ed49eb..0000000
--- a/chrome/browser/ui/cocoa/tab_controller.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-#import "chrome/browser/ui/cocoa/hover_close_button.h"
-#include "chrome/browser/ui/tabs/tab_menu_model.h"
-
-// The loading/waiting state of the tab.
-enum TabLoadingState {
-  kTabDone,
-  kTabLoading,
-  kTabWaiting,
-  kTabCrashed,
-};
-
-@class MenuController;
-namespace TabControllerInternal {
-class MenuDelegate;
-}
-@class TabView;
-@protocol TabControllerTarget;
-
-// A class that manages a single tab in the tab strip. Set its target/action
-// to be sent a message when the tab is selected by the user clicking. Setting
-// the |loading| property to YES visually indicates that this tab is currently
-// loading content via a spinner.
-//
-// The tab has the notion of an "icon view" which can be used to display
-// identifying characteristics such as a favicon, or since it's a full-fledged
-// view, something with state and animation such as a throbber for illustrating
-// progress. The default in the nib is an image view so nothing special is
-// required if that's all you need.
-
-@interface TabController : NSViewController {
- @private
-  IBOutlet NSView* iconView_;
-  IBOutlet NSTextField* titleView_;
-  IBOutlet HoverCloseButton* closeButton_;
-
-  NSRect originalIconFrame_;  // frame of iconView_ as loaded from nib
-  BOOL isIconShowing_;  // last state of iconView_ in updateVisibility
-
-  BOOL app_;
-  BOOL mini_;
-  BOOL pinned_;
-  BOOL selected_;
-  TabLoadingState loadingState_;
-  CGFloat iconTitleXOffset_;  // between left edges of icon and title
-  id<TabControllerTarget> target_;  // weak, where actions are sent
-  SEL action_;  // selector sent when tab is selected by clicking
-  scoped_ptr<TabMenuModel> contextMenuModel_;
-  scoped_ptr<TabControllerInternal::MenuDelegate> contextMenuDelegate_;
-  scoped_nsobject<MenuController> contextMenuController_;
-}
-
-@property(assign, nonatomic) TabLoadingState loadingState;
-
-@property(assign, nonatomic) SEL action;
-@property(assign, nonatomic) BOOL app;
-@property(assign, nonatomic) BOOL mini;
-@property(assign, nonatomic) BOOL pinned;
-@property(assign, nonatomic) BOOL selected;
-@property(assign, nonatomic) id target;
-@property(assign, nonatomic) NSView* iconView;
-@property(assign, nonatomic) NSTextField* titleView;
-@property(assign, nonatomic) HoverCloseButton* closeButton;
-
-// Minimum and maximum allowable tab width. The minimum width does not show
-// the icon or the close button. The selected tab always has at least a close
-// button so it has a different minimum width.
-+ (CGFloat)minTabWidth;
-+ (CGFloat)maxTabWidth;
-+ (CGFloat)minSelectedTabWidth;
-+ (CGFloat)miniTabWidth;
-+ (CGFloat)appTabWidth;
-
-// The view associated with this controller, pre-casted as a TabView
-- (TabView*)tabView;
-
-// Closes the associated TabView by relaying the message to |target_| to
-// perform the close.
-- (IBAction)closeTab:(id)sender;
-
-// Replace the current icon view with the given view. |iconView| will be
-// resized to the size of the current icon view.
-- (void)setIconView:(NSView*)iconView;
-- (NSView*)iconView;
-
-// Called by the tabs to determine whether we are in rapid (tab) closure mode.
-// In this mode, we handle clicks slightly differently due to animation.
-// Ideally, tabs would know about their own animation and wouldn't need this.
-- (BOOL)inRapidClosureMode;
-
-// Updates the visibility of certain subviews, such as the icon and close
-// button, based on criteria such as the tab's selected state and its current
-// width.
-- (void)updateVisibility;
-
-// Update the title color to match the tabs current state.
-- (void)updateTitleColor;
-@end
-
-@interface TabController(TestingAPI)
-- (NSString*)toolTip;
-- (int)iconCapacity;
-- (BOOL)shouldShowIcon;
-- (BOOL)shouldShowCloseButton;
-@end  // TabController(TestingAPI)
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_controller.mm b/chrome/browser/ui/cocoa/tab_controller.mm
deleted file mode 100644
index f05bb21..0000000
--- a/chrome/browser/ui/cocoa/tab_controller.mm
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/l10n_util_mac.h"
-#include "base/mac/mac_util.h"
-#import "chrome/browser/themes/browser_theme_provider.h"
-#import "chrome/browser/ui/cocoa/menu_controller.h"
-#import "chrome/browser/ui/cocoa/tab_controller.h"
-#import "chrome/browser/ui/cocoa/tab_controller_target.h"
-#import "chrome/browser/ui/cocoa/tab_view.h"
-#import "chrome/browser/ui/cocoa/themed_window.h"
-#import "chrome/common/extensions/extension.h"
-#include "grit/generated_resources.h"
-
-@implementation TabController
-
-@synthesize action = action_;
-@synthesize app = app_;
-@synthesize loadingState = loadingState_;
-@synthesize mini = mini_;
-@synthesize pinned = pinned_;
-@synthesize target = target_;
-@synthesize iconView = iconView_;
-@synthesize titleView = titleView_;
-@synthesize closeButton = closeButton_;
-
-namespace TabControllerInternal {
-
-// A C++ delegate that handles enabling/disabling menu items and handling when
-// a menu command is chosen. Also fixes up the menu item label for "pin/unpin
-// tab".
-class MenuDelegate : public menus::SimpleMenuModel::Delegate {
- public:
-  explicit MenuDelegate(id<TabControllerTarget> target, TabController* owner)
-      : target_(target),
-        owner_(owner) {}
-
-  // Overridden from menus::SimpleMenuModel::Delegate
-  virtual bool IsCommandIdChecked(int command_id) const { return false; }
-  virtual bool IsCommandIdEnabled(int command_id) const {
-    TabStripModel::ContextMenuCommand command =
-        static_cast<TabStripModel::ContextMenuCommand>(command_id);
-    return [target_ isCommandEnabled:command forController:owner_];
-  }
-  virtual bool GetAcceleratorForCommandId(
-      int command_id,
-      menus::Accelerator* accelerator) { return false; }
-  virtual void ExecuteCommand(int command_id) {
-    TabStripModel::ContextMenuCommand command =
-        static_cast<TabStripModel::ContextMenuCommand>(command_id);
-    [target_ commandDispatch:command forController:owner_];
-  }
-
- private:
-  id<TabControllerTarget> target_;  // weak
-  TabController* owner_;  // weak, owns me
-};
-
-}  // TabControllerInternal namespace
-
-// The min widths match the windows values and are sums of left + right
-// padding, of which we have no comparable constants (we draw using paths, not
-// images). The selected tab width includes the close button width.
-+ (CGFloat)minTabWidth { return 31; }
-+ (CGFloat)minSelectedTabWidth { return 46; }
-+ (CGFloat)maxTabWidth { return 220; }
-+ (CGFloat)miniTabWidth { return 53; }
-+ (CGFloat)appTabWidth { return 66; }
-
-- (TabView*)tabView {
-  return static_cast<TabView*>([self view]);
-}
-
-- (id)init {
-  self = [super initWithNibName:@"TabView" bundle:base::mac::MainAppBundle()];
-  if (self != nil) {
-    isIconShowing_ = YES;
-    NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
-    [defaultCenter addObserver:self
-                      selector:@selector(viewResized:)
-                          name:NSViewFrameDidChangeNotification
-                        object:[self view]];
-    [defaultCenter addObserver:self
-                      selector:@selector(themeChangedNotification:)
-                          name:kBrowserThemeDidChangeNotification
-                        object:nil];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [[self tabView] setController:nil];
-  [super dealloc];
-}
-
-// The internals of |-setSelected:| but doesn't check if we're already set
-// to |selected|. Pass the selection change to the subviews that need it and
-// mark ourselves as needing a redraw.
-- (void)internalSetSelected:(BOOL)selected {
-  selected_ = selected;
-  TabView* tabView = static_cast<TabView*>([self view]);
-  DCHECK([tabView isKindOfClass:[TabView class]]);
-  [tabView setState:selected];
-  [tabView cancelAlert];
-  [self updateVisibility];
-  [self updateTitleColor];
-}
-
-// Called when the tab's nib is done loading and all outlets are hooked up.
-- (void)awakeFromNib {
-  // Remember the icon's frame, so that if the icon is ever removed, a new
-  // one can later replace it in the proper location.
-  originalIconFrame_ = [iconView_ frame];
-
-  // When the icon is removed, the title expands to the left to fill the space
-  // left by the icon.  When the close button is removed, the title expands to
-  // the right to fill its space.  These are the amounts to expand and contract
-  // titleView_ under those conditions. We don't have to explicilty save the
-  // offset between the title and the close button since we can just get that
-  // value for the close button's frame.
-  NSRect titleFrame = [titleView_ frame];
-  iconTitleXOffset_ = NSMinX(titleFrame) - NSMinX(originalIconFrame_);
-
-  [self internalSetSelected:selected_];
-}
-
-// Called when Cocoa wants to display the context menu. Lazily instantiate
-// the menu based off of the cross-platform model. Re-create the menu and
-// model every time to get the correct labels and enabling.
-- (NSMenu*)menu {
-  contextMenuDelegate_.reset(
-      new TabControllerInternal::MenuDelegate(target_, self));
-  contextMenuModel_.reset(new TabMenuModel(contextMenuDelegate_.get(),
-                                           [self pinned]));
-  contextMenuController_.reset(
-      [[MenuController alloc] initWithModel:contextMenuModel_.get()
-                     useWithPopUpButtonCell:NO]);
-  return [contextMenuController_ menu];
-}
-
-- (IBAction)closeTab:(id)sender {
-  if ([[self target] respondsToSelector:@selector(closeTab:)]) {
-    [[self target] performSelector:@selector(closeTab:)
-                        withObject:[self view]];
-  }
-}
-
-- (void)setTitle:(NSString*)title {
-  [[self view] setToolTip:title];
-  if ([self mini] && ![self selected]) {
-    TabView* tabView = static_cast<TabView*>([self view]);
-    DCHECK([tabView isKindOfClass:[TabView class]]);
-    [tabView startAlert];
-  }
-  [super setTitle:title];
-}
-
-- (void)setSelected:(BOOL)selected {
-  if (selected_ != selected)
-    [self internalSetSelected:selected];
-}
-
-- (BOOL)selected {
-  return selected_;
-}
-
-- (void)setIconView:(NSView*)iconView {
-  [iconView_ removeFromSuperview];
-  iconView_ = iconView;
-  if ([self app]) {
-    NSRect appIconFrame = [iconView frame];
-    appIconFrame.origin = originalIconFrame_.origin;
-    // Center the icon.
-    appIconFrame.origin.x = ([TabController appTabWidth] -
-        NSWidth(appIconFrame)) / 2.0;
-    [iconView setFrame:appIconFrame];
-  } else {
-    [iconView_ setFrame:originalIconFrame_];
-  }
-  // Ensure that the icon is suppressed if no icon is set or if the tab is too
-  // narrow to display one.
-  [self updateVisibility];
-
-  if (iconView_)
-    [[self view] addSubview:iconView_];
-}
-
-- (NSString*)toolTip {
-  return [[self view] toolTip];
-}
-
-// Return a rough approximation of the number of icons we could fit in the
-// tab. We never actually do this, but it's a helpful guide for determining
-// how much space we have available.
-- (int)iconCapacity {
-  CGFloat width = NSMaxX([closeButton_ frame]) - NSMinX(originalIconFrame_);
-  CGFloat iconWidth = NSWidth(originalIconFrame_);
-
-  return width / iconWidth;
-}
-
-// Returns YES if we should show the icon. When tabs get too small, we clip
-// the favicon before the close button for selected tabs, and prefer the
-// favicon for unselected tabs.  The icon can also be suppressed more directly
-// by clearing iconView_.
-- (BOOL)shouldShowIcon {
-  if (!iconView_)
-    return NO;
-
-  if ([self mini])
-    return YES;
-
-  int iconCapacity = [self iconCapacity];
-  if ([self selected])
-    return iconCapacity >= 2;
-  return iconCapacity >= 1;
-}
-
-// Returns YES if we should be showing the close button. The selected tab
-// always shows the close button.
-- (BOOL)shouldShowCloseButton {
-  if ([self mini])
-    return NO;
-  return ([self selected] || [self iconCapacity] >= 3);
-}
-
-- (void)updateVisibility {
-  // iconView_ may have been replaced or it may be nil, so [iconView_ isHidden]
-  // won't work.  Instead, the state of the icon is tracked separately in
-  // isIconShowing_.
-  BOOL newShowIcon = [self shouldShowIcon];
-
-  [iconView_ setHidden:!newShowIcon];
-  isIconShowing_ = newShowIcon;
-
-  // If the tab is a mini-tab, hide the title.
-  [titleView_ setHidden:[self mini]];
-
-  BOOL newShowCloseButton = [self shouldShowCloseButton];
-
-  [closeButton_ setHidden:!newShowCloseButton];
-
-  // Adjust the title view based on changes to the icon's and close button's
-  // visibility.
-  NSRect oldTitleFrame = [titleView_ frame];
-  NSRect newTitleFrame;
-  newTitleFrame.size.height = oldTitleFrame.size.height;
-  newTitleFrame.origin.y = oldTitleFrame.origin.y;
-
-  if (newShowIcon) {
-    newTitleFrame.origin.x = originalIconFrame_.origin.x + iconTitleXOffset_;
-  } else {
-    newTitleFrame.origin.x = originalIconFrame_.origin.x;
-  }
-
-  if (newShowCloseButton) {
-    newTitleFrame.size.width = NSMinX([closeButton_ frame]) -
-                               newTitleFrame.origin.x;
-  } else {
-    newTitleFrame.size.width = NSMaxX([closeButton_ frame]) -
-                               newTitleFrame.origin.x;
-  }
-
-  [titleView_ setFrame:newTitleFrame];
-}
-
-- (void)updateTitleColor {
-  NSColor* titleColor = nil;
-  ThemeProvider* theme = [[[self view] window] themeProvider];
-  if (theme && ![self selected]) {
-    titleColor =
-        theme->GetNSColor(BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT,
-                          true);
-  }
-  // Default to the selected text color unless told otherwise.
-  if (theme && !titleColor) {
-    titleColor = theme->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT,
-                                   true);
-  }
-  [titleView_ setTextColor:titleColor ? titleColor : [NSColor textColor]];
-}
-
-// Called when our view is resized. If it gets too small, start by hiding
-// the close button and only show it if tab is selected. Eventually, hide the
-// icon as well. We know that this is for our view because we only registered
-// for notifications from our specific view.
-- (void)viewResized:(NSNotification*)info {
-  [self updateVisibility];
-}
-
-- (void)themeChangedNotification:(NSNotification*)notification {
-  [self updateTitleColor];
-}
-
-// Called by the tabs to determine whether we are in rapid (tab) closure mode.
-- (BOOL)inRapidClosureMode {
-  if ([[self target] respondsToSelector:@selector(inRapidClosureMode)]) {
-    return [[self target] performSelector:@selector(inRapidClosureMode)] ?
-        YES : NO;
-  }
-  return NO;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/tab_controller_target.h b/chrome/browser/ui/cocoa/tab_controller_target.h
deleted file mode 100644
index 6eec01a..0000000
--- a/chrome/browser/ui/cocoa/tab_controller_target.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_CONTROLLER_TARGET_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_CONTROLLER_TARGET_H_
-#pragma once
-
-#include "chrome/browser/tabs/tab_strip_model.h"
-
-@class TabController;
-
-// A protocol to be implemented by a TabController's target.
-@protocol TabControllerTarget
-- (void)selectTab:(id)sender;
-- (void)closeTab:(id)sender;
-
-// Dispatch context menu commands for the given tab controller.
-- (void)commandDispatch:(TabStripModel::ContextMenuCommand)command
-          forController:(TabController*)controller;
-// Returns YES if the specificed command should be enabled for the given
-// controller.
-- (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command
-           forController:(TabController*)controller;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_CONTROLLER_TARGET_H_
diff --git a/chrome/browser/ui/cocoa/tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tab_controller_unittest.mm
deleted file mode 100644
index 93331ac..0000000
--- a/chrome/browser/ui/cocoa/tab_controller_unittest.mm
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/tab_controller.h"
-#import "chrome/browser/ui/cocoa/tab_controller_target.h"
-#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-// Implements the target interface for the tab, which gets sent messages when
-// the tab is clicked on by the user and when its close box is clicked.
-@interface TabControllerTestTarget : NSObject<TabControllerTarget> {
- @private
-  bool selected_;
-  bool closed_;
-}
-- (bool)selected;
-- (bool)closed;
-@end
-
-@implementation TabControllerTestTarget
-- (bool)selected {
-  return selected_;
-}
-- (bool)closed {
-  return closed_;
-}
-- (void)selectTab:(id)sender {
-  selected_ = true;
-}
-- (void)closeTab:(id)sender {
-  closed_ = true;
-}
-- (void)mouseTimer:(NSTimer*)timer {
-  // Fire the mouseUp to break the TabView drag loop.
-  NSEvent* current = [NSApp currentEvent];
-  NSWindow* window = [timer userInfo];
-  NSEvent* up = [NSEvent mouseEventWithType:NSLeftMouseUp
-                                   location:[current locationInWindow]
-                              modifierFlags:0
-                                  timestamp:[current timestamp]
-                               windowNumber:[window windowNumber]
-                                    context:nil
-                                eventNumber:0
-                                 clickCount:1
-                                   pressure:1.0];
-  [window postEvent:up atStart:YES];
-}
-- (void)commandDispatch:(TabStripModel::ContextMenuCommand)command
-          forController:(TabController*)controller {
-}
-- (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command
-           forController:(TabController*)controller {
-  return NO;
-}
-@end
-
-namespace {
-
-CGFloat LeftMargin(NSRect superFrame, NSRect subFrame) {
-  return NSMinX(subFrame) - NSMinX(superFrame);
-}
-
-CGFloat RightMargin(NSRect superFrame, NSRect subFrame) {
-  return NSMaxX(superFrame) - NSMaxX(subFrame);
-}
-
-// The dragging code in TabView makes heavy use of autorelease pools so
-// inherit from CocoaTest to have one created for us.
-class TabControllerTest : public CocoaTest {
- public:
-  TabControllerTest() { }
-};
-
-// Tests creating the controller, sticking it in a window, and removing it.
-TEST_F(TabControllerTest, Creation) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-  EXPECT_TRUE([controller tabView]);
-  EXPECT_EQ([[controller view] window], window);
-  [[controller view] display];  // Test drawing to ensure nothing leaks/crashes.
-  [[controller view] removeFromSuperview];
-}
-
-// Tests sending it a close message and ensuring that the target/action get
-// called. Mimics the user clicking on the close button in the tab.
-TEST_F(TabControllerTest, Close) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-
-  scoped_nsobject<TabControllerTestTarget> target(
-      [[TabControllerTestTarget alloc] init]);
-  EXPECT_FALSE([target closed]);
-  [controller setTarget:target];
-  EXPECT_EQ(target.get(), [controller target]);
-
-  [controller closeTab:nil];
-  EXPECT_TRUE([target closed]);
-
-  [[controller view] removeFromSuperview];
-}
-
-// Tests setting the |selected| property via code.
-TEST_F(TabControllerTest, APISelection) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-
-  EXPECT_FALSE([controller selected]);
-  [controller setSelected:YES];
-  EXPECT_TRUE([controller selected]);
-
-  [[controller view] removeFromSuperview];
-}
-
-// Tests that setting the title of a tab sets the tooltip as well.
-TEST_F(TabControllerTest, ToolTip) {
-  NSWindow* window = test_window();
-
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-
-  EXPECT_TRUE([[controller toolTip] length] == 0);
-  NSString *tooltip_string = @"Some text to use as a tab title";
-  [controller setTitle:tooltip_string];
-  EXPECT_NSEQ(tooltip_string, [controller toolTip]);
-}
-
-// Tests setting the |loading| property via code.
-TEST_F(TabControllerTest, Loading) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-
-  EXPECT_EQ(kTabDone, [controller loadingState]);
-  [controller setLoadingState:kTabWaiting];
-  EXPECT_EQ(kTabWaiting, [controller loadingState]);
-  [controller setLoadingState:kTabLoading];
-  EXPECT_EQ(kTabLoading, [controller loadingState]);
-  [controller setLoadingState:kTabDone];
-  EXPECT_EQ(kTabDone, [controller loadingState]);
-
-  [[controller view] removeFromSuperview];
-}
-
-// Tests selecting the tab with the mouse click and ensuring the target/action
-// get called.
-TEST_F(TabControllerTest, UserSelection) {
-  NSWindow* window = test_window();
-
-  // Create a tab at a known location in the window that we can click on
-  // to activate selection.
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-  NSRect frame = [[controller view] frame];
-  frame.size.width = [TabController minTabWidth];
-  frame.origin = NSMakePoint(0, 0);
-  [[controller view] setFrame:frame];
-
-  // Set the target and action.
-  scoped_nsobject<TabControllerTestTarget> target(
-      [[TabControllerTestTarget alloc] init]);
-  EXPECT_FALSE([target selected]);
-  [controller setTarget:target];
-  [controller setAction:@selector(selectTab:)];
-  EXPECT_EQ(target.get(), [controller target]);
-  EXPECT_EQ(@selector(selectTab:), [controller action]);
-
-  // In order to track a click, we have to fake a mouse down and a mouse
-  // up, but the down goes into a tight drag loop. To break the loop, we have
-  // to fire a timer that sends a mouse up event while the "drag" is ongoing.
-  [NSTimer scheduledTimerWithTimeInterval:0.1
-                                   target:target.get()
-                                 selector:@selector(mouseTimer:)
-                                 userInfo:window
-                                  repeats:NO];
-  NSEvent* current = [NSApp currentEvent];
-  NSPoint click_point = NSMakePoint(frame.size.width / 2,
-                                    frame.size.height / 2);
-  NSEvent* down = [NSEvent mouseEventWithType:NSLeftMouseDown
-                                     location:click_point
-                                modifierFlags:0
-                                    timestamp:[current timestamp]
-                                 windowNumber:[window windowNumber]
-                                      context:nil
-                                  eventNumber:0
-                                   clickCount:1
-                                     pressure:1.0];
-  [[controller view] mouseDown:down];
-
-  // Check our target was told the tab got selected.
-  EXPECT_TRUE([target selected]);
-
-  [[controller view] removeFromSuperview];
-}
-
-TEST_F(TabControllerTest, IconCapacity) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-  int cap = [controller iconCapacity];
-  EXPECT_GE(cap, 1);
-
-  NSRect frame = [[controller view] frame];
-  frame.size.width += 500;
-  [[controller view] setFrame:frame];
-  int newcap = [controller iconCapacity];
-  EXPECT_GT(newcap, cap);
-}
-
-TEST_F(TabControllerTest, ShouldShowIcon) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-  int cap = [controller iconCapacity];
-  EXPECT_GT(cap, 0);
-
-  // Tab is minimum width, both icon and close box should be hidden.
-  NSRect frame = [[controller view] frame];
-  frame.size.width = [TabController minTabWidth];
-  [[controller view] setFrame:frame];
-  EXPECT_FALSE([controller shouldShowIcon]);
-  EXPECT_FALSE([controller shouldShowCloseButton]);
-
-  // Setting the icon when tab is at min width should not show icon (bug 18359).
-  scoped_nsobject<NSView> newIcon(
-      [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)]);
-  [controller setIconView:newIcon.get()];
-  EXPECT_TRUE([newIcon isHidden]);
-
-  // Tab is at selected minimum width. Since it's selected, the close box
-  // should be visible.
-  [controller setSelected:YES];
-  frame = [[controller view] frame];
-  frame.size.width = [TabController minSelectedTabWidth];
-  [[controller view] setFrame:frame];
-  EXPECT_FALSE([controller shouldShowIcon]);
-  EXPECT_TRUE([newIcon isHidden]);
-  EXPECT_TRUE([controller shouldShowCloseButton]);
-
-  // Test expanding the tab to max width and ensure the icon and close box
-  // get put back, even when de-selected.
-  frame.size.width = [TabController maxTabWidth];
-  [[controller view] setFrame:frame];
-  EXPECT_TRUE([controller shouldShowIcon]);
-  EXPECT_FALSE([newIcon isHidden]);
-  EXPECT_TRUE([controller shouldShowCloseButton]);
-  [controller setSelected:NO];
-  EXPECT_TRUE([controller shouldShowIcon]);
-  EXPECT_TRUE([controller shouldShowCloseButton]);
-
-  cap = [controller iconCapacity];
-  EXPECT_GT(cap, 0);
-}
-
-TEST_F(TabControllerTest, Menu) {
-  NSWindow* window = test_window();
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-  int cap = [controller iconCapacity];
-  EXPECT_GT(cap, 0);
-
-  // Asking the view for its menu should yield a valid menu.
-  NSMenu* menu = [[controller view] menu];
-  EXPECT_TRUE(menu);
-  EXPECT_GT([menu numberOfItems], 0);
-}
-
-// Tests that the title field is correctly positioned and sized when the
-// view is resized.
-TEST_F(TabControllerTest, TitleViewLayout) {
-  NSWindow* window = test_window();
-
-  scoped_nsobject<TabController> controller([[TabController alloc] init]);
-  [[window contentView] addSubview:[controller view]];
-  NSRect tabFrame = [[controller view] frame];
-  tabFrame.size.width = [TabController maxTabWidth];
-  [[controller view] setFrame:tabFrame];
-
-  const NSRect originalTabFrame = [[controller view] frame];
-  const NSRect originalIconFrame = [[controller iconView] frame];
-  const NSRect originalCloseFrame = [[controller closeButton] frame];
-  const NSRect originalTitleFrame = [[controller titleView] frame];
-
-  // Sanity check the start state.
-  EXPECT_FALSE([[controller iconView] isHidden]);
-  EXPECT_FALSE([[controller closeButton] isHidden]);
-  EXPECT_GT(NSWidth([[controller view] frame]),
-            NSWidth([[controller titleView] frame]));
-
-  // Resize the tab so that that the it shrinks.
-  tabFrame.size.width = [TabController minTabWidth];
-  [[controller view] setFrame:tabFrame];
-
-  // The icon view and close button should be hidden and the title view should
-  // be resize to take up their space.
-  EXPECT_TRUE([[controller iconView] isHidden]);
-  EXPECT_TRUE([[controller closeButton] isHidden]);
-  EXPECT_GT(NSWidth([[controller view] frame]),
-            NSWidth([[controller titleView] frame]));
-  EXPECT_EQ(LeftMargin(originalTabFrame, originalIconFrame),
-            LeftMargin([[controller view] frame],
-                       [[controller titleView] frame]));
-  EXPECT_EQ(RightMargin(originalTabFrame, originalCloseFrame),
-            RightMargin([[controller view] frame],
-                        [[controller titleView] frame]));
-
-  // Resize the tab so that that the it grows.
-  tabFrame.size.width = [TabController maxTabWidth] * 0.75;
-  [[controller view] setFrame:tabFrame];
-
-  // The icon view and close button should be visible again and the title view
-  // should be resized to make room for them.
-  EXPECT_FALSE([[controller iconView] isHidden]);
-  EXPECT_FALSE([[controller closeButton] isHidden]);
-  EXPECT_GT(NSWidth([[controller view] frame]),
-            NSWidth([[controller titleView] frame]));
-  EXPECT_EQ(LeftMargin(originalTabFrame, originalTitleFrame),
-            LeftMargin([[controller view] frame],
-                       [[controller titleView] frame]));
-  EXPECT_EQ(RightMargin(originalTabFrame, originalTitleFrame),
-            RightMargin([[controller view] frame],
-                        [[controller titleView] frame]));
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/tab_strip_controller.h b/chrome/browser/ui/cocoa/tab_strip_controller.h
deleted file mode 100644
index 1dda86c..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_controller.h
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_STRIP_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_STRIP_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "base/scoped_ptr.h"
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
-#import "chrome/browser/ui/cocoa/tab_controller_target.h"
-#import "chrome/browser/ui/cocoa/url_drop_target.h"
-#import "third_party/GTM/AppKit/GTMWindowSheetController.h"
-
-@class NewTabButton;
-@class TabContentsController;
-@class TabView;
-@class TabStripView;
-
-class Browser;
-class ConstrainedWindowMac;
-class TabStripModelObserverBridge;
-class TabStripModel;
-class TabContents;
-class ToolbarModel;
-
-// The interface for the tab strip controller's delegate.
-// Delegating TabStripModelObserverBridge's events (in lieu of directly
-// subscribing to TabStripModelObserverBridge events, as TabStripController
-// does) is necessary to guarantee a proper order of subviews layout updates,
-// otherwise it might trigger unnesessary content relayout, UI flickering etc.
-@protocol TabStripControllerDelegate
-
-// Stripped down version of TabStripModelObserverBridge:selectTabWithContents.
-- (void)onSelectTabWithContents:(TabContents*)contents;
-
-// Stripped down version of TabStripModelObserverBridge:tabReplacedWithContents.
-- (void)onReplaceTabWithContents:(TabContents*)contents;
-
-// Stripped down version of TabStripModelObserverBridge:tabChangedWithContents.
-- (void)onSelectedTabChange:(TabStripModelObserver::TabChangeType)change;
-
-// Stripped down version of TabStripModelObserverBridge:tabDetachedWithContents.
-- (void)onTabDetachedWithContents:(TabContents*)contents;
-
-@end
-
-// A class that handles managing the tab strip in a browser window. It uses
-// a supporting C++ bridge object to register for notifications from the
-// TabStripModel. The Obj-C part of this class handles drag and drop and all
-// the other Cocoa-y aspects.
-//
-// For a full description of the design, see
-// http://www.chromium.org/developers/design-documents/tab-strip-mac
-@interface TabStripController :
-  NSObject<TabControllerTarget,
-           URLDropTargetController,
-           GTMWindowSheetControllerDelegate,
-           TabContentsControllerDelegate> {
- @protected
-  // YES if tabs are to be laid out vertically instead of horizontally.
-  BOOL verticalLayout_;
-
- @private
-  scoped_nsobject<TabStripView> tabStripView_;
-  NSView* switchView_;  // weak
-  scoped_nsobject<NSView> dragBlockingView_;  // avoid bad window server drags
-  NewTabButton* newTabButton_;  // weak, obtained from the nib.
-
-  // Tracks the newTabButton_ for rollovers.
-  scoped_nsobject<NSTrackingArea> newTabTrackingArea_;
-  scoped_ptr<TabStripModelObserverBridge> bridge_;
-  Browser* browser_;  // weak
-  TabStripModel* tabStripModel_;  // weak
-  // Delegate that is informed about tab state changes.
-  id<TabStripControllerDelegate> delegate_;  // weak
-
-  // YES if the new tab button is currently displaying the hover image (if the
-  // mouse is currently over the button).
-  BOOL newTabButtonShowingHoverImage_;
-
-  // Access to the TabContentsControllers (which own the parent view
-  // for the toolbar and associated tab contents) given an index. Call
-  // |indexFromModelIndex:| to convert a |tabStripModel_| index to a
-  // |tabContentsArray_| index. Do NOT assume that the indices of
-  // |tabStripModel_| and this array are identical, this is e.g. not true while
-  // tabs are animating closed (closed tabs are removed from |tabStripModel_|
-  // immediately, but from |tabContentsArray_| only after their close animation
-  // has completed).
-  scoped_nsobject<NSMutableArray> tabContentsArray_;
-  // An array of TabControllers which manage the actual tab views. See note
-  // above |tabContentsArray_|. |tabContentsArray_| and |tabArray_| always
-  // contain objects belonging to the same tabs at the same indices.
-  scoped_nsobject<NSMutableArray> tabArray_;
-
-  // Set of TabControllers that are currently animating closed.
-  scoped_nsobject<NSMutableSet> closingControllers_;
-
-  // These values are only used during a drag, and override tab positioning.
-  TabView* placeholderTab_;  // weak. Tab being dragged
-  NSRect placeholderFrame_;  // Frame to use
-  CGFloat placeholderStretchiness_; // Vertical force shown by streching tab.
-  NSRect droppedTabFrame_;  // Initial frame of a dropped tab, for animation.
-  // Frame targets for all the current views.
-  // target frames are used because repeated requests to [NSView animator].
-  // aren't coalesced, so we store frames to avoid redundant calls.
-  scoped_nsobject<NSMutableDictionary> targetFrames_;
-  NSRect newTabTargetFrame_;
-  // If YES, do not show the new tab button during layout.
-  BOOL forceNewTabButtonHidden_;
-  // YES if we've successfully completed the initial layout. When this is
-  // NO, we probably don't want to do any animation because we're just coming
-  // into being.
-  BOOL initialLayoutComplete_;
-
-  // Width available for resizing the tabs (doesn't include the new tab
-  // button). Used to restrict the available width when closing many tabs at
-  // once to prevent them from resizing to fit the full width. If the entire
-  // width should be used, this will have a value of |kUseFullAvailableWidth|.
-  float availableResizeWidth_;
-  // A tracking area that's the size of the tab strip used to be notified
-  // when the mouse moves in the tab strip
-  scoped_nsobject<NSTrackingArea> trackingArea_;
-  TabView* hoveredTab_;  // weak. Tab that the mouse is hovering over
-
-  // Array of subviews which are permanent (and which should never be removed),
-  // such as the new-tab button, but *not* the tabs themselves.
-  scoped_nsobject<NSMutableArray> permanentSubviews_;
-
-  // The default favicon, so we can use one copy for all buttons.
-  scoped_nsobject<NSImage> defaultFavIcon_;
-
-  // The amount by which to indent the tabs on the left (to make room for the
-  // red/yellow/green buttons).
-  CGFloat indentForControls_;
-
-  // Manages per-tab sheets.
-  scoped_nsobject<GTMWindowSheetController> sheetController_;
-
-  // Is the mouse currently inside the strip;
-  BOOL mouseInside_;
-}
-
-@property(nonatomic) CGFloat indentForControls;
-
-// Initialize the controller with a view and browser that contains
-// everything else we'll need. |switchView| is the view whose contents get
-// "switched" every time the user switches tabs. The children of this view
-// will be released, so if you want them to stay around, make sure
-// you have retained them.
-// |delegate| is the one listening to filtered TabStripModelObserverBridge's
-// events (see TabStripControllerDelegate for more details).
-- (id)initWithView:(TabStripView*)view
-        switchView:(NSView*)switchView
-           browser:(Browser*)browser
-          delegate:(id<TabStripControllerDelegate>)delegate;
-
-// Return the view for the currently selected tab.
-- (NSView*)selectedTabView;
-
-// Set the frame of the selected tab, also updates the internal frame dict.
-- (void)setFrameOfSelectedTab:(NSRect)frame;
-
-// Move the given tab at index |from| in this window to the location of the
-// current placeholder.
-- (void)moveTabFromIndex:(NSInteger)from;
-
-// Drop a given TabContents at the location of the current placeholder. If there
-// is no placeholder, it will go at the end. Used when dragging from another
-// window when we don't have access to the TabContents as part of our strip.
-// |frame| is in the coordinate system of the tab strip view and represents
-// where the user dropped the new tab so it can be animated into its correct
-// location when the tab is added to the model. If the tab was pinned in its
-// previous window, setting |pinned| to YES will propagate that state to the
-// new window. Mini-tabs are either app or pinned tabs; the app state is stored
-// by the |contents|, but the |pinned| state is the caller's responsibility.
-- (void)dropTabContents:(TabContentsWrapper*)contents
-              withFrame:(NSRect)frame
-            asPinnedTab:(BOOL)pinned;
-
-// Returns the index of the subview |view|. Returns -1 if not present. Takes
-// closing tabs into account such that this index will correctly match the tab
-// model. If |view| is in the process of closing, returns -1, as closing tabs
-// are no longer in the model.
-- (NSInteger)modelIndexForTabView:(NSView*)view;
-
-// Return the view at a given index.
-- (NSView*)viewAtIndex:(NSUInteger)index;
-
-// Return the number of tab views in the tab strip. It's same as number of tabs
-// in the model, except when a tab is closing, which will be counted in views
-// count, but no longer in the model.
-- (NSUInteger)viewsCount;
-
-// Set the placeholder for a dragged tab, allowing the |frame| and |strechiness|
-// to be specified. This causes this tab to be rendered in an arbitrary position
-- (void)insertPlaceholderForTab:(TabView*)tab
-                          frame:(NSRect)frame
-                  yStretchiness:(CGFloat)yStretchiness;
-
-// Returns whether a tab is being dragged within the tab strip.
-- (BOOL)isDragSessionActive;
-
-// Returns whether or not |tab| can still be fully seen in the tab strip or if
-// its current position would cause it be obscured by things such as the edge
-// of the window or the window decorations. Returns YES only if the entire tab
-// is visible.
-- (BOOL)isTabFullyVisible:(TabView*)tab;
-
-// Show or hide the new tab button. The button is hidden immediately, but
-// waits until the next call to |-layoutTabs| to show it again.
-- (void)showNewTabButton:(BOOL)show;
-
-// Force the tabs to rearrange themselves to reflect the current model.
-- (void)layoutTabs;
-
-// Are we in rapid (tab) closure mode? I.e., is a full layout deferred (while
-// the user closes tabs)? Needed to overcome missing clicks during rapid tab
-// closure.
-- (BOOL)inRapidClosureMode;
-
-// Returns YES if the user is allowed to drag tabs on the strip at this moment.
-// For example, this returns NO if there are any pending tab close animtations.
-- (BOOL)tabDraggingAllowed;
-
-// Default height for tabs.
-+ (CGFloat)defaultTabHeight;
-
-// Default indentation for tabs (see |indentForControls_|).
-+ (CGFloat)defaultIndentForControls;
-
-// Returns the (lazily created) window sheet controller of this window. Used
-// for the per-tab sheets.
-- (GTMWindowSheetController*)sheetController;
-
-// Destroys the window sheet controller of this window, if it exists.  The sheet
-// controller can be recreated by a subsequent call to |-sheetController|.  Must
-// not be called if any sheets are currently open.
-// TODO(viettrungluu): This is temporary code needed to allow sheets to work
-// (read: not crash) in fullscreen mode.  Once GTMWindowSheetController is
-// modified to support moving sheets between windows, this code can go away.
-// http://crbug.com/19093.
-- (void)destroySheetController;
-
-// Returns the currently active TabContentsController.
-- (TabContentsController*)activeTabContentsController;
-
-  // See comments in browser_window_controller.h for documentation about these
-  // functions.
-- (void)attachConstrainedWindow:(ConstrainedWindowMac*)window;
-- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window;
-
-@end
-
-// Notification sent when the number of tabs changes. The object will be this
-// controller.
-extern NSString* const kTabStripNumberOfTabsChanged;
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_STRIP_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tab_strip_controller.mm
deleted file mode 100644
index d9fb6fc..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_controller.mm
+++ /dev/null
@@ -1,1899 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-
-#import <QuartzCore/QuartzCore.h>
-
-#include <limits>
-#include <string>
-
-#include "app/l10n_util.h"
-#include "app/mac/nsimage_cache.h"
-#include "app/resource_bundle.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/autocomplete/autocomplete.h"
-#include "chrome/browser/autocomplete/autocomplete_classifier.h"
-#include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/debugger/devtools_window.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/sidebar/sidebar_container.h"
-#include "chrome/browser/sidebar/sidebar_manager.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_navigator.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/constrained_window_mac.h"
-#import "chrome/browser/ui/cocoa/new_tab_button.h"
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-#import "chrome/browser/ui/cocoa/tab_contents_controller.h"
-#import "chrome/browser/ui/cocoa/tab_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h"
-#import "chrome/browser/ui/cocoa/tab_view.h"
-#import "chrome/browser/ui/cocoa/throbber_view.h"
-#include "chrome/browser/ui/find_bar/find_bar.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
-
-NSString* const kTabStripNumberOfTabsChanged = @"kTabStripNumberOfTabsChanged";
-
-namespace {
-
-// The images names used for different states of the new tab button.
-NSString* const kNewTabHoverImage = @"newtab_h.pdf";
-NSString* const kNewTabImage = @"newtab.pdf";
-NSString* const kNewTabPressedImage = @"newtab_p.pdf";
-
-// A value to indicate tab layout should use the full available width of the
-// view.
-const CGFloat kUseFullAvailableWidth = -1.0;
-
-// The amount by which tabs overlap.
-const CGFloat kTabOverlap = 20.0;
-
-// The width and height for a tab's icon.
-const CGFloat kIconWidthAndHeight = 16.0;
-
-// The amount by which the new tab button is offset (from the tabs).
-const CGFloat kNewTabButtonOffset = 8.0;
-
-// The amount by which to shrink the tab strip (on the right) when the
-// incognito badge is present.
-const CGFloat kIncognitoBadgeTabStripShrink = 18;
-
-// Time (in seconds) in which tabs animate to their final position.
-const NSTimeInterval kAnimationDuration = 0.125;
-
-// Helper class for doing NSAnimationContext calls that takes a bool to disable
-// all the work.  Useful for code that wants to conditionally animate.
-class ScopedNSAnimationContextGroup {
- public:
-  explicit ScopedNSAnimationContextGroup(bool animate)
-      : animate_(animate) {
-    if (animate_) {
-      [NSAnimationContext beginGrouping];
-    }
-  }
-
-  ~ScopedNSAnimationContextGroup() {
-    if (animate_) {
-      [NSAnimationContext endGrouping];
-    }
-  }
-
-  void SetCurrentContextDuration(NSTimeInterval duration) {
-    if (animate_) {
-      [[NSAnimationContext currentContext] gtm_setDuration:duration
-                                                 eventMask:NSLeftMouseUpMask];
-    }
-  }
-
-  void SetCurrentContextShortestDuration() {
-    if (animate_) {
-      // The minimum representable time interval.  This used to stop an
-      // in-progress animation as quickly as possible.
-      const NSTimeInterval kMinimumTimeInterval =
-          std::numeric_limits<NSTimeInterval>::min();
-      // Directly set the duration to be short, avoiding the Steve slowmotion
-      // ettect the gtm_setDuration: provides.
-      [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval];
-    }
-  }
-
-private:
-  bool animate_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedNSAnimationContextGroup);
-};
-
-}  // namespace
-
-@interface TabStripController (Private)
-- (void)installTrackingArea;
-- (void)addSubviewToPermanentList:(NSView*)aView;
-- (void)regenerateSubviewList;
-- (NSInteger)indexForContentsView:(NSView*)view;
-- (void)updateFavIconForContents:(TabContents*)contents
-                         atIndex:(NSInteger)modelIndex;
-- (void)layoutTabsWithAnimation:(BOOL)animate
-             regenerateSubviews:(BOOL)doUpdate;
-- (void)animationDidStopForController:(TabController*)controller
-                             finished:(BOOL)finished;
-- (NSInteger)indexFromModelIndex:(NSInteger)index;
-- (NSInteger)numberOfOpenTabs;
-- (NSInteger)numberOfOpenMiniTabs;
-- (NSInteger)numberOfOpenNonMiniTabs;
-- (void)mouseMoved:(NSEvent*)event;
-- (void)setTabTrackingAreasEnabled:(BOOL)enabled;
-- (void)droppingURLsAt:(NSPoint)point
-            givesIndex:(NSInteger*)index
-           disposition:(WindowOpenDisposition*)disposition;
-- (void)setNewTabButtonHoverState:(BOOL)showHover;
-@end
-
-// A simple view class that prevents the Window Server from dragging the area
-// behind tabs. Sometimes core animation confuses it. Unfortunately, it can also
-// falsely pick up clicks during rapid tab closure, so we have to account for
-// that.
-@interface TabStripControllerDragBlockingView : NSView {
-  TabStripController* controller_;  // weak; owns us
-}
-
-- (id)initWithFrame:(NSRect)frameRect
-         controller:(TabStripController*)controller;
-@end
-
-@implementation TabStripControllerDragBlockingView
-- (BOOL)mouseDownCanMoveWindow {return NO;}
-- (void)drawRect:(NSRect)rect {}
-
-- (id)initWithFrame:(NSRect)frameRect
-         controller:(TabStripController*)controller {
-  if ((self = [super initWithFrame:frameRect]))
-    controller_ = controller;
-  return self;
-}
-
-// In "rapid tab closure" mode (i.e., the user is clicking close tab buttons in
-// rapid succession), the animations confuse Cocoa's hit testing (which appears
-// to use cached results, among other tricks), so this view can somehow end up
-// getting a mouse down event. Thus we do an explicit hit test during rapid tab
-// closure, and if we find that we got a mouse down we shouldn't have, we send
-// it off to the appropriate view.
-- (void)mouseDown:(NSEvent*)event {
-  if ([controller_ inRapidClosureMode]) {
-    NSView* superview = [self superview];
-    NSPoint hitLocation =
-        [[superview superview] convertPoint:[event locationInWindow]
-                                   fromView:nil];
-    NSView* hitView = [superview hitTest:hitLocation];
-    if (hitView != self) {
-      [hitView mouseDown:event];
-      return;
-    }
-  }
-  [super mouseDown:event];
-}
-@end
-
-#pragma mark -
-
-// A delegate, owned by the CAAnimation system, that is alerted when the
-// animation to close a tab is completed. Calls back to the given tab strip
-// to let it know that |controller_| is ready to be removed from the model.
-// Since we only maintain weak references, the tab strip must call -invalidate:
-// to prevent the use of dangling pointers.
-@interface TabCloseAnimationDelegate : NSObject {
- @private
-  TabStripController* strip_;  // weak; owns us indirectly
-  TabController* controller_;  // weak
-}
-
-// Will tell |strip| when the animation for |controller|'s view has completed.
-// These should not be nil, and will not be retained.
-- (id)initWithTabStrip:(TabStripController*)strip
-         tabController:(TabController*)controller;
-
-// Invalidates this object so that no further calls will be made to
-// |strip_|.  This should be called when |strip_| is released, to
-// prevent attempts to call into the released object.
-- (void)invalidate;
-
-// CAAnimation delegate method
-- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished;
-
-@end
-
-@implementation TabCloseAnimationDelegate
-
-- (id)initWithTabStrip:(TabStripController*)strip
-         tabController:(TabController*)controller {
-  if ((self == [super init])) {
-    DCHECK(strip && controller);
-    strip_ = strip;
-    controller_ = controller;
-  }
-  return self;
-}
-
-- (void)invalidate {
-  strip_ = nil;
-  controller_ = nil;
-}
-
-- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
-  [strip_ animationDidStopForController:controller_ finished:finished];
-}
-
-@end
-
-#pragma mark -
-
-// In general, there is a one-to-one correspondence between TabControllers,
-// TabViews, TabContentsControllers, and the TabContents in the TabStripModel.
-// In the steady-state, the indices line up so an index coming from the model
-// is directly mapped to the same index in the parallel arrays holding our
-// views and controllers. This is also true when new tabs are created (even
-// though there is a small period of animation) because the tab is present
-// in the model while the TabView is animating into place. As a result, nothing
-// special need be done to handle "new tab" animation.
-//
-// This all goes out the window with the "close tab" animation. The animation
-// kicks off in |-tabDetachedWithContents:atIndex:| with the notification that
-// the tab has been removed from the model. The simplest solution at this
-// point would be to remove the views and controllers as well, however once
-// the TabView is removed from the view list, the tab z-order code takes care of
-// removing it from the tab strip and we'll get no animation. That means if
-// there is to be any visible animation, the TabView needs to stay around until
-// its animation is complete. In order to maintain consistency among the
-// internal parallel arrays, this means all structures are kept around until
-// the animation completes. At this point, though, the model and our internal
-// structures are out of sync: the indices no longer line up. As a result,
-// there is a concept of a "model index" which represents an index valid in
-// the TabStripModel. During steady-state, the "model index" is just the same
-// index as our parallel arrays (as above), but during tab close animations,
-// it is different, offset by the number of tabs preceding the index which
-// are undergoing tab closing animation. As a result, the caller needs to be
-// careful to use the available conversion routines when accessing the internal
-// parallel arrays (e.g., -indexFromModelIndex:). Care also needs to be taken
-// during tab layout to ignore closing tabs in the total width calculations and
-// in individual tab positioning (to avoid moving them right back to where they
-// were).
-//
-// In order to prevent actions being taken on tabs which are closing, the tab
-// itself gets marked as such so it no longer will send back its select action
-// or allow itself to be dragged. In addition, drags on the tab strip as a
-// whole are disabled while there are tabs closing.
-
-@implementation TabStripController
-
-@synthesize indentForControls = indentForControls_;
-
-- (id)initWithView:(TabStripView*)view
-        switchView:(NSView*)switchView
-           browser:(Browser*)browser
-          delegate:(id<TabStripControllerDelegate>)delegate {
-  DCHECK(view && switchView && browser && delegate);
-  if ((self = [super init])) {
-    tabStripView_.reset([view retain]);
-    switchView_ = switchView;
-    browser_ = browser;
-    tabStripModel_ = browser_->tabstrip_model();
-    delegate_ = delegate;
-    bridge_.reset(new TabStripModelObserverBridge(tabStripModel_, self));
-    tabContentsArray_.reset([[NSMutableArray alloc] init]);
-    tabArray_.reset([[NSMutableArray alloc] init]);
-
-    // Important note: any non-tab subviews not added to |permanentSubviews_|
-    // (see |-addSubviewToPermanentList:|) will be wiped out.
-    permanentSubviews_.reset([[NSMutableArray alloc] init]);
-
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    defaultFavIcon_.reset([rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON) retain]);
-
-    [self setIndentForControls:[[self class] defaultIndentForControls]];
-
-    // TODO(viettrungluu): WTF? "For some reason, if the view is present in the
-    // nib a priori, it draws correctly. If we create it in code and add it to
-    // the tab view, it draws with all sorts of crazy artifacts."
-    newTabButton_ = [view newTabButton];
-    [self addSubviewToPermanentList:newTabButton_];
-    [newTabButton_ setTarget:nil];
-    [newTabButton_ setAction:@selector(commandDispatch:)];
-    [newTabButton_ setTag:IDC_NEW_TAB];
-    // Set the images from code because Cocoa fails to find them in our sub
-    // bundle during tests.
-    [newTabButton_ setImage:app::mac::GetCachedImageWithName(kNewTabImage)];
-    [newTabButton_ setAlternateImage:
-        app::mac::GetCachedImageWithName(kNewTabPressedImage)];
-    newTabButtonShowingHoverImage_ = NO;
-    newTabTrackingArea_.reset(
-        [[NSTrackingArea alloc] initWithRect:[newTabButton_ bounds]
-                                     options:(NSTrackingMouseEnteredAndExited |
-                                              NSTrackingActiveAlways)
-                                       owner:self
-                                    userInfo:nil]);
-    [newTabButton_ addTrackingArea:newTabTrackingArea_.get()];
-    targetFrames_.reset([[NSMutableDictionary alloc] init]);
-
-    dragBlockingView_.reset(
-        [[TabStripControllerDragBlockingView alloc] initWithFrame:NSZeroRect
-                                                       controller:self]);
-    [self addSubviewToPermanentList:dragBlockingView_];
-
-    newTabTargetFrame_ = NSMakeRect(0, 0, 0, 0);
-    availableResizeWidth_ = kUseFullAvailableWidth;
-
-    closingControllers_.reset([[NSMutableSet alloc] init]);
-
-    // Install the permanent subviews.
-    [self regenerateSubviewList];
-
-    // Watch for notifications that the tab strip view has changed size so
-    // we can tell it to layout for the new size.
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(tabViewFrameChanged:)
-               name:NSViewFrameDidChangeNotification
-             object:tabStripView_];
-
-    trackingArea_.reset([[NSTrackingArea alloc]
-        initWithRect:NSZeroRect  // Ignored by NSTrackingInVisibleRect
-             options:NSTrackingMouseEnteredAndExited |
-                     NSTrackingMouseMoved |
-                     NSTrackingActiveAlways |
-                     NSTrackingInVisibleRect
-               owner:self
-            userInfo:nil]);
-    [tabStripView_ addTrackingArea:trackingArea_.get()];
-
-    // Check to see if the mouse is currently in our bounds so we can
-    // enable the tracking areas.  Otherwise we won't get hover states
-    // or tab gradients if we load the window up under the mouse.
-    NSPoint mouseLoc = [[view window] mouseLocationOutsideOfEventStream];
-    mouseLoc = [view convertPoint:mouseLoc fromView:nil];
-    if (NSPointInRect(mouseLoc, [view bounds])) {
-      [self setTabTrackingAreasEnabled:YES];
-      mouseInside_ = YES;
-    }
-
-    // Set accessibility descriptions. http://openradar.appspot.com/7496255
-    NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_NEWTAB);
-    [[newTabButton_ cell]
-        accessibilitySetOverrideValue:description
-                         forAttribute:NSAccessibilityDescriptionAttribute];
-
-    // Controller may have been (re-)created by switching layout modes, which
-    // means the tab model is already fully formed with tabs. Need to walk the
-    // list and create the UI for each.
-    const int existingTabCount = tabStripModel_->count();
-    const TabContentsWrapper* selection =
-        tabStripModel_->GetSelectedTabContents();
-    for (int i = 0; i < existingTabCount; ++i) {
-      TabContentsWrapper* currentContents = tabStripModel_->GetTabContentsAt(i);
-      [self insertTabWithContents:currentContents
-                          atIndex:i
-                     inForeground:NO];
-      if (selection == currentContents) {
-        // Must manually force a selection since the model won't send
-        // selection messages in this scenario.
-        [self selectTabWithContents:currentContents
-                   previousContents:NULL
-                            atIndex:i
-                        userGesture:NO];
-      }
-    }
-    // Don't lay out the tabs until after the controller has been fully
-    // constructed. The |verticalLayout_| flag has not been initialized by
-    // subclasses at this point, which would cause layout to potentially use
-    // the wrong mode.
-    if (existingTabCount) {
-      [self performSelectorOnMainThread:@selector(layoutTabs)
-                             withObject:nil
-                          waitUntilDone:NO];
-    }
-  }
-  return self;
-}
-
-- (void)dealloc {
-  if (trackingArea_.get())
-    [tabStripView_ removeTrackingArea:trackingArea_.get()];
-
-  [newTabButton_ removeTrackingArea:newTabTrackingArea_.get()];
-  // Invalidate all closing animations so they don't call back to us after
-  // we're gone.
-  for (TabController* controller in closingControllers_.get()) {
-    NSView* view = [controller view];
-    [[[view animationForKey:@"frameOrigin"] delegate] invalidate];
-  }
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-  [super dealloc];
-}
-
-+ (CGFloat)defaultTabHeight {
-  return 25.0;
-}
-
-+ (CGFloat)defaultIndentForControls {
-  // Default indentation leaves enough room so tabs don't overlap with the
-  // window controls.
-  return 68.0;
-}
-
-// Finds the TabContentsController associated with the given index into the tab
-// model and swaps out the sole child of the contentArea to display its
-// contents.
-- (void)swapInTabAtIndex:(NSInteger)modelIndex {
-  DCHECK(modelIndex >= 0 && modelIndex < tabStripModel_->count());
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-  TabContentsController* controller = [tabContentsArray_ objectAtIndex:index];
-
-  // Resize the new view to fit the window. Calling |view| may lazily
-  // instantiate the TabContentsController from the nib. Until we call
-  // |-ensureContentsVisible|, the controller doesn't install the RWHVMac into
-  // the view hierarchy. This is in order to avoid sending the renderer a
-  // spurious default size loaded from the nib during the call to |-view|.
-  NSView* newView = [controller view];
-
-  // Turns content autoresizing off, so removing and inserting views won't
-  // trigger unnecessary content relayout.
-  [controller ensureContentsSizeDoesNotChange];
-
-  // Remove the old view from the view hierarchy. We know there's only one
-  // child of |switchView_| because we're the one who put it there. There
-  // may not be any children in the case of a tab that's been closed, in
-  // which case there's no swapping going on.
-  NSArray* subviews = [switchView_ subviews];
-  if ([subviews count]) {
-    NSView* oldView = [subviews objectAtIndex:0];
-    // Set newView frame to the oldVew frame to prevent NSSplitView hosting
-    // sidebar and tab content from resizing sidebar's content view.
-    // ensureContentsVisible (see below) sets content size and autoresizing
-    // properties.
-    [newView setFrame:[oldView frame]];
-    [switchView_ replaceSubview:oldView with:newView];
-  } else {
-    [newView setFrame:[switchView_ bounds]];
-    [switchView_ addSubview:newView];
-  }
-
-  // New content is in place, delegate should adjust itself accordingly.
-  [delegate_ onSelectTabWithContents:[controller tabContents]];
-
-  // It also restores content autoresizing properties.
-  [controller ensureContentsVisible];
-
-  // Make sure the new tabs's sheets are visible (necessary when a background
-  // tab opened a sheet while it was in the background and now becomes active).
-  TabContentsWrapper* newTab = tabStripModel_->GetTabContentsAt(modelIndex);
-  DCHECK(newTab);
-  if (newTab) {
-    TabContents::ConstrainedWindowList::iterator it, end;
-    end = newTab->tab_contents()->constrained_window_end();
-    NSWindowController* controller = [[newView window] windowController];
-    DCHECK([controller isKindOfClass:[BrowserWindowController class]]);
-
-    for (it = newTab->tab_contents()->constrained_window_begin();
-         it != end;
-         ++it) {
-      ConstrainedWindow* constrainedWindow = *it;
-      static_cast<ConstrainedWindowMac*>(constrainedWindow)->Realize(
-          static_cast<BrowserWindowController*>(controller));
-    }
-  }
-
-  // Tell per-tab sheet manager about currently selected tab.
-  if (sheetController_.get()) {
-    [sheetController_ setActiveView:newView];
-  }
-}
-
-// Create a new tab view and set its cell correctly so it draws the way we want
-// it to. It will be sized and positioned by |-layoutTabs| so there's no need to
-// set the frame here. This also creates the view as hidden, it will be
-// shown during layout.
-- (TabController*)newTab {
-  TabController* controller = [[[TabController alloc] init] autorelease];
-  [controller setTarget:self];
-  [controller setAction:@selector(selectTab:)];
-  [[controller view] setHidden:YES];
-
-  return controller;
-}
-
-// (Private) Returns the number of open tabs in the tab strip. This is the
-// number of TabControllers we know about (as there's a 1-to-1 mapping from
-// these controllers to a tab) less the number of closing tabs.
-- (NSInteger)numberOfOpenTabs {
-  return static_cast<NSInteger>(tabStripModel_->count());
-}
-
-// (Private) Returns the number of open, mini-tabs.
-- (NSInteger)numberOfOpenMiniTabs {
-  // Ask the model for the number of mini tabs. Note that tabs which are in
-  // the process of closing (i.e., whose controllers are in
-  // |closingControllers_|) have already been removed from the model.
-  return tabStripModel_->IndexOfFirstNonMiniTab();
-}
-
-// (Private) Returns the number of open, non-mini tabs.
-- (NSInteger)numberOfOpenNonMiniTabs {
-  NSInteger number = [self numberOfOpenTabs] - [self numberOfOpenMiniTabs];
-  DCHECK_GE(number, 0);
-  return number;
-}
-
-// Given an index into the tab model, returns the index into the tab controller
-// or tab contents controller array accounting for tabs that are currently
-// closing. For example, if there are two tabs in the process of closing before
-// |index|, this returns |index| + 2. If there are no closing tabs, this will
-// return |index|.
-- (NSInteger)indexFromModelIndex:(NSInteger)index {
-  DCHECK(index >= 0);
-  if (index < 0)
-    return index;
-
-  NSInteger i = 0;
-  for (TabController* controller in tabArray_.get()) {
-    if ([closingControllers_ containsObject:controller]) {
-      DCHECK([(TabView*)[controller view] isClosing]);
-      ++index;
-    }
-    if (i == index)  // No need to check anything after, it has no effect.
-      break;
-    ++i;
-  }
-  return index;
-}
-
-
-// Returns the index of the subview |view|. Returns -1 if not present. Takes
-// closing tabs into account such that this index will correctly match the tab
-// model. If |view| is in the process of closing, returns -1, as closing tabs
-// are no longer in the model.
-- (NSInteger)modelIndexForTabView:(NSView*)view {
-  NSInteger index = 0;
-  for (TabController* current in tabArray_.get()) {
-    // If |current| is closing, skip it.
-    if ([closingControllers_ containsObject:current])
-      continue;
-    else if ([current view] == view)
-      return index;
-    ++index;
-  }
-  return -1;
-}
-
-// Returns the index of the contents subview |view|. Returns -1 if not present.
-// Takes closing tabs into account such that this index will correctly match the
-// tab model. If |view| is in the process of closing, returns -1, as closing
-// tabs are no longer in the model.
-- (NSInteger)modelIndexForContentsView:(NSView*)view {
-  NSInteger index = 0;
-  NSInteger i = 0;
-  for (TabContentsController* current in tabContentsArray_.get()) {
-    // If the TabController corresponding to |current| is closing, skip it.
-    TabController* controller = [tabArray_ objectAtIndex:i];
-    if ([closingControllers_ containsObject:controller]) {
-      ++i;
-      continue;
-    } else if ([current view] == view) {
-      return index;
-    }
-    ++index;
-    ++i;
-  }
-  return -1;
-}
-
-
-// Returns the view at the given index, using the array of TabControllers to
-// get the associated view. Returns nil if out of range.
-- (NSView*)viewAtIndex:(NSUInteger)index {
-  if (index >= [tabArray_ count])
-    return NULL;
-  return [[tabArray_ objectAtIndex:index] view];
-}
-
-- (NSUInteger)viewsCount {
-  return [tabArray_ count];
-}
-
-// Called when the user clicks a tab. Tell the model the selection has changed,
-// which feeds back into us via a notification.
-- (void)selectTab:(id)sender {
-  DCHECK([sender isKindOfClass:[NSView class]]);
-  int index = [self modelIndexForTabView:sender];
-  if (tabStripModel_->ContainsIndex(index))
-    tabStripModel_->SelectTabContentsAt(index, true);
-}
-
-// Called when the user closes a tab. Asks the model to close the tab. |sender|
-// is the TabView that is potentially going away.
-- (void)closeTab:(id)sender {
-  DCHECK([sender isKindOfClass:[TabView class]]);
-  if ([hoveredTab_ isEqual:sender]) {
-    hoveredTab_ = nil;
-  }
-
-  NSInteger index = [self modelIndexForTabView:sender];
-  if (!tabStripModel_->ContainsIndex(index))
-    return;
-
-  TabContentsWrapper* contents = tabStripModel_->GetTabContentsAt(index);
-  if (contents)
-    UserMetrics::RecordAction(UserMetricsAction("CloseTab_Mouse"),
-                              contents->tab_contents()->profile());
-  const NSInteger numberOfOpenTabs = [self numberOfOpenTabs];
-  if (numberOfOpenTabs > 1) {
-    bool isClosingLastTab = index == numberOfOpenTabs - 1;
-    if (!isClosingLastTab) {
-      // Limit the width available for laying out tabs so that tabs are not
-      // resized until a later time (when the mouse leaves the tab strip).
-      // However, if the tab being closed is a pinned tab, break out of
-      // rapid-closure mode since the mouse is almost guaranteed not to be over
-      // the closebox of the adjacent tab (due to the difference in widths).
-      // TODO(pinkerton): re-visit when handling tab overflow.
-      // http://crbug.com/188
-      if (tabStripModel_->IsTabPinned(index)) {
-        availableResizeWidth_ = kUseFullAvailableWidth;
-      } else {
-        NSView* penultimateTab = [self viewAtIndex:numberOfOpenTabs - 2];
-        availableResizeWidth_ = NSMaxX([penultimateTab frame]);
-      }
-    } else {
-      // If the rightmost tab is closed, change the available width so that
-      // another tab's close button lands below the cursor (assuming the tabs
-      // are currently below their maximum width and can grow).
-      NSView* lastTab = [self viewAtIndex:numberOfOpenTabs - 1];
-      availableResizeWidth_ = NSMaxX([lastTab frame]);
-    }
-    tabStripModel_->CloseTabContentsAt(
-        index,
-        TabStripModel::CLOSE_USER_GESTURE |
-        TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
-  } else {
-    // Use the standard window close if this is the last tab
-    // this prevents the tab from being removed from the model until after
-    // the window dissapears
-    [[tabStripView_ window] performClose:nil];
-  }
-}
-
-// Dispatch context menu commands for the given tab controller.
-- (void)commandDispatch:(TabStripModel::ContextMenuCommand)command
-          forController:(TabController*)controller {
-  int index = [self modelIndexForTabView:[controller view]];
-  if (tabStripModel_->ContainsIndex(index))
-    tabStripModel_->ExecuteContextMenuCommand(index, command);
-}
-
-// Returns YES if the specificed command should be enabled for the given
-// controller.
-- (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command
-           forController:(TabController*)controller {
-  int index = [self modelIndexForTabView:[controller view]];
-  if (!tabStripModel_->ContainsIndex(index))
-    return NO;
-  return tabStripModel_->IsContextMenuCommandEnabled(index, command) ? YES : NO;
-}
-
-- (void)insertPlaceholderForTab:(TabView*)tab
-                          frame:(NSRect)frame
-                  yStretchiness:(CGFloat)yStretchiness {
-  placeholderTab_ = tab;
-  placeholderFrame_ = frame;
-  placeholderStretchiness_ = yStretchiness;
-  [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:NO];
-}
-
-- (BOOL)isDragSessionActive {
-  return placeholderTab_ != nil;
-}
-
-- (BOOL)isTabFullyVisible:(TabView*)tab {
-  NSRect frame = [tab frame];
-  return NSMinX(frame) >= [self indentForControls] &&
-      NSMaxX(frame) <= NSMaxX([tabStripView_ frame]);
-}
-
-- (void)showNewTabButton:(BOOL)show {
-  forceNewTabButtonHidden_ = show ? NO : YES;
-  if (forceNewTabButtonHidden_)
-    [newTabButton_ setHidden:YES];
-}
-
-// Lay out all tabs in the order of their TabContentsControllers, which matches
-// the ordering in the TabStripModel. This call isn't that expensive, though
-// it is O(n) in the number of tabs. Tabs will animate to their new position
-// if the window is visible and |animate| is YES.
-// TODO(pinkerton): Note this doesn't do too well when the number of min-sized
-// tabs would cause an overflow. http://crbug.com/188
-- (void)layoutTabsWithAnimation:(BOOL)animate
-             regenerateSubviews:(BOOL)doUpdate {
-  DCHECK([NSThread isMainThread]);
-  if (![tabArray_ count])
-    return;
-
-  const CGFloat kMaxTabWidth = [TabController maxTabWidth];
-  const CGFloat kMinTabWidth = [TabController minTabWidth];
-  const CGFloat kMinSelectedTabWidth = [TabController minSelectedTabWidth];
-  const CGFloat kMiniTabWidth = [TabController miniTabWidth];
-  const CGFloat kAppTabWidth = [TabController appTabWidth];
-
-  NSRect enclosingRect = NSZeroRect;
-  ScopedNSAnimationContextGroup mainAnimationGroup(animate);
-  mainAnimationGroup.SetCurrentContextDuration(kAnimationDuration);
-
-  // Update the current subviews and their z-order if requested.
-  if (doUpdate)
-    [self regenerateSubviewList];
-
-  // Compute the base width of tabs given how much room we're allowed. Note that
-  // mini-tabs have a fixed width. We may not be able to use the entire width
-  // if the user is quickly closing tabs. This may be negative, but that's okay
-  // (taken care of by |MAX()| when calculating tab sizes).
-  CGFloat availableSpace = 0;
-  if (verticalLayout_) {
-    availableSpace = NSHeight([tabStripView_ bounds]);
-  } else {
-    if ([self inRapidClosureMode]) {
-      availableSpace = availableResizeWidth_;
-    } else {
-      availableSpace = NSWidth([tabStripView_ frame]);
-      // Account for the new tab button and the incognito badge.
-      availableSpace -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset;
-      if (browser_->profile()->IsOffTheRecord())
-        availableSpace -= kIncognitoBadgeTabStripShrink;
-    }
-    availableSpace -= [self indentForControls];
-  }
-
-  // This may be negative, but that's okay (taken care of by |MAX()| when
-  // calculating tab sizes). "mini" tabs in horizontal mode just get a special
-  // section, they don't change size.
-  CGFloat availableSpaceForNonMini = availableSpace;
-  if (!verticalLayout_) {
-      availableSpaceForNonMini -=
-          [self numberOfOpenMiniTabs] * (kMiniTabWidth - kTabOverlap);
-  }
-
-  // Initialize |nonMiniTabWidth| in case there aren't any non-mini-tabs; this
-  // value shouldn't actually be used.
-  CGFloat nonMiniTabWidth = kMaxTabWidth;
-  const NSInteger numberOfOpenNonMiniTabs = [self numberOfOpenNonMiniTabs];
-  if (!verticalLayout_ && numberOfOpenNonMiniTabs) {
-    // Find the width of a non-mini-tab. This only applies to horizontal
-    // mode. Add in the amount we "get back" from the tabs overlapping.
-    availableSpaceForNonMini += (numberOfOpenNonMiniTabs - 1) * kTabOverlap;
-
-    // Divide up the space between the non-mini-tabs.
-    nonMiniTabWidth = availableSpaceForNonMini / numberOfOpenNonMiniTabs;
-
-    // Clamp the width between the max and min.
-    nonMiniTabWidth = MAX(MIN(nonMiniTabWidth, kMaxTabWidth), kMinTabWidth);
-  }
-
-  BOOL visible = [[tabStripView_ window] isVisible];
-
-  CGFloat offset = [self indentForControls];
-  bool hasPlaceholderGap = false;
-  for (TabController* tab in tabArray_.get()) {
-    // Ignore a tab that is going through a close animation.
-    if ([closingControllers_ containsObject:tab])
-      continue;
-
-    BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_];
-    NSRect tabFrame = [[tab view] frame];
-    tabFrame.size.height = [[self class] defaultTabHeight] + 1;
-    if (verticalLayout_) {
-      tabFrame.origin.y = availableSpace - tabFrame.size.height - offset;
-      tabFrame.origin.x = 0;
-    } else {
-      tabFrame.origin.y = 0;
-      tabFrame.origin.x = offset;
-    }
-    // If the tab is hidden, we consider it a new tab. We make it visible
-    // and animate it in.
-    BOOL newTab = [[tab view] isHidden];
-    if (newTab)
-      [[tab view] setHidden:NO];
-
-    if (isPlaceholder) {
-      // Move the current tab to the correct location instantly.
-      // We need a duration or else it doesn't cancel an inflight animation.
-      ScopedNSAnimationContextGroup localAnimationGroup(animate);
-      localAnimationGroup.SetCurrentContextShortestDuration();
-      if (verticalLayout_)
-        tabFrame.origin.y = availableSpace - tabFrame.size.height - offset;
-      else
-        tabFrame.origin.x = placeholderFrame_.origin.x;
-      // TODO(alcor): reenable this
-      //tabFrame.size.height += 10.0 * placeholderStretchiness_;
-      id target = animate ? [[tab view] animator] : [tab view];
-      [target setFrame:tabFrame];
-
-      // Store the frame by identifier to aviod redundant calls to animator.
-      NSValue* identifier = [NSValue valueWithPointer:[tab view]];
-      [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
-                        forKey:identifier];
-      continue;
-    }
-
-    if (placeholderTab_ && !hasPlaceholderGap) {
-      const CGFloat placeholderMin =
-          verticalLayout_ ? NSMinY(placeholderFrame_) :
-                            NSMinX(placeholderFrame_);
-      if (verticalLayout_) {
-        if (NSMidY(tabFrame) > placeholderMin) {
-          hasPlaceholderGap = true;
-          offset += NSHeight(placeholderFrame_);
-          tabFrame.origin.y = availableSpace - tabFrame.size.height - offset;
-        }
-      } else {
-        // If the left edge is to the left of the placeholder's left, but the
-        // mid is to the right of it slide over to make space for it.
-        if (NSMidX(tabFrame) > placeholderMin) {
-          hasPlaceholderGap = true;
-          offset += NSWidth(placeholderFrame_);
-          offset -= kTabOverlap;
-          tabFrame.origin.x = offset;
-        }
-      }
-    }
-
-    // Set the width. Selected tabs are slightly wider when things get really
-    // small and thus we enforce a different minimum width.
-    tabFrame.size.width = [tab mini] ?
-        ([tab app] ? kAppTabWidth : kMiniTabWidth) : nonMiniTabWidth;
-    if ([tab selected])
-      tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth);
-
-    // Animate a new tab in by putting it below the horizon unless told to put
-    // it in a specific location (i.e., from a drop).
-    // TODO(pinkerton): figure out vertical tab animations.
-    if (newTab && visible && animate) {
-      if (NSEqualRects(droppedTabFrame_, NSZeroRect)) {
-        [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))];
-      } else {
-        [[tab view] setFrame:droppedTabFrame_];
-        droppedTabFrame_ = NSZeroRect;
-      }
-    }
-
-    // Check the frame by identifier to avoid redundant calls to animator.
-    id frameTarget = visible && animate ? [[tab view] animator] : [tab view];
-    NSValue* identifier = [NSValue valueWithPointer:[tab view]];
-    NSValue* oldTargetValue = [targetFrames_ objectForKey:identifier];
-    if (!oldTargetValue ||
-        !NSEqualRects([oldTargetValue rectValue], tabFrame)) {
-      [frameTarget setFrame:tabFrame];
-      [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
-                        forKey:identifier];
-    }
-
-    enclosingRect = NSUnionRect(tabFrame, enclosingRect);
-
-    if (verticalLayout_) {
-      offset += NSHeight(tabFrame);
-    } else {
-      offset += NSWidth(tabFrame);
-      offset -= kTabOverlap;
-    }
-  }
-
-  // Hide the new tab button if we're explicitly told to. It may already
-  // be hidden, doing it again doesn't hurt. Otherwise position it
-  // appropriately, showing it if necessary.
-  if (forceNewTabButtonHidden_) {
-    [newTabButton_ setHidden:YES];
-  } else {
-    NSRect newTabNewFrame = [newTabButton_ frame];
-    // We've already ensured there's enough space for the new tab button
-    // so we don't have to check it against the available space. We do need
-    // to make sure we put it after any placeholder.
-    CGFloat maxTabX = MAX(offset, NSMaxX(placeholderFrame_) - kTabOverlap);
-    newTabNewFrame.origin = NSMakePoint(maxTabX + kNewTabButtonOffset, 0);
-    if ([tabContentsArray_ count])
-      [newTabButton_ setHidden:NO];
-
-    if (!NSEqualRects(newTabTargetFrame_, newTabNewFrame)) {
-      // Set the new tab button image correctly based on where the cursor is.
-      NSWindow* window = [tabStripView_ window];
-      NSPoint currentMouse = [window mouseLocationOutsideOfEventStream];
-      currentMouse = [tabStripView_ convertPoint:currentMouse fromView:nil];
-
-      BOOL shouldShowHover = [newTabButton_ pointIsOverButton:currentMouse];
-      [self setNewTabButtonHoverState:shouldShowHover];
-
-      // Move the new tab button into place. We want to animate the new tab
-      // button if it's moving to the left (closing a tab), but not when it's
-      // moving to the right (inserting a new tab). If moving right, we need
-      // to use a very small duration to make sure we cancel any in-flight
-      // animation to the left.
-      if (visible && animate) {
-        ScopedNSAnimationContextGroup localAnimationGroup(true);
-        BOOL movingLeft = NSMinX(newTabNewFrame) < NSMinX(newTabTargetFrame_);
-        if (!movingLeft) {
-          localAnimationGroup.SetCurrentContextShortestDuration();
-        }
-        [[newTabButton_ animator] setFrame:newTabNewFrame];
-        newTabTargetFrame_ = newTabNewFrame;
-      } else {
-        [newTabButton_ setFrame:newTabNewFrame];
-        newTabTargetFrame_ = newTabNewFrame;
-      }
-    }
-  }
-
-  [dragBlockingView_ setFrame:enclosingRect];
-
-  // Mark that we've successfully completed layout of at least one tab.
-  initialLayoutComplete_ = YES;
-}
-
-// When we're told to layout from the public API we usually want to animate,
-// except when it's the first time.
-- (void)layoutTabs {
-  [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:YES];
-}
-
-// Handles setting the title of the tab based on the given |contents|. Uses
-// a canned string if |contents| is NULL.
-- (void)setTabTitle:(NSViewController*)tab withContents:(TabContents*)contents {
-  NSString* titleString = nil;
-  if (contents)
-    titleString = base::SysUTF16ToNSString(contents->GetTitle());
-  if (![titleString length]) {
-    titleString = l10n_util::GetNSString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
-  }
-  [tab setTitle:titleString];
-}
-
-// Called when a notification is received from the model to insert a new tab
-// at |modelIndex|.
-- (void)insertTabWithContents:(TabContentsWrapper*)contents
-                      atIndex:(NSInteger)modelIndex
-                 inForeground:(bool)inForeground {
-  DCHECK(contents);
-  DCHECK(modelIndex == TabStripModel::kNoTab ||
-         tabStripModel_->ContainsIndex(modelIndex));
-
-  // Take closing tabs into account.
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-
-  // Make a new tab. Load the contents of this tab from the nib and associate
-  // the new controller with |contents| so it can be looked up later.
-  scoped_nsobject<TabContentsController> contentsController(
-      [[TabContentsController alloc] initWithContents:contents->tab_contents()
-                                             delegate:self]);
-  [tabContentsArray_ insertObject:contentsController atIndex:index];
-
-  // Make a new tab and add it to the strip. Keep track of its controller.
-  TabController* newController = [self newTab];
-  [newController setMini:tabStripModel_->IsMiniTab(modelIndex)];
-  [newController setPinned:tabStripModel_->IsTabPinned(modelIndex)];
-  [newController setApp:tabStripModel_->IsAppTab(modelIndex)];
-  [tabArray_ insertObject:newController atIndex:index];
-  NSView* newView = [newController view];
-
-  // Set the originating frame to just below the strip so that it animates
-  // upwards as it's being initially layed out. Oddly, this works while doing
-  // something similar in |-layoutTabs| confuses the window server.
-  [newView setFrame:NSOffsetRect([newView frame],
-                                 0, -[[self class] defaultTabHeight])];
-
-  [self setTabTitle:newController withContents:contents->tab_contents()];
-
-  // If a tab is being inserted, we can again use the entire tab strip width
-  // for layout.
-  availableResizeWidth_ = kUseFullAvailableWidth;
-
-  // We don't need to call |-layoutTabs| if the tab will be in the foreground
-  // because it will get called when the new tab is selected by the tab model.
-  // Whenever |-layoutTabs| is called, it'll also add the new subview.
-  if (!inForeground) {
-    [self layoutTabs];
-  }
-
-  // During normal loading, we won't yet have a favicon and we'll get
-  // subsequent state change notifications to show the throbber, but when we're
-  // dragging a tab out into a new window, we have to put the tab's favicon
-  // into the right state up front as we won't be told to do it from anywhere
-  // else.
-  [self updateFavIconForContents:contents->tab_contents() atIndex:modelIndex];
-
-  // Send a broadcast that the number of tabs have changed.
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:kTabStripNumberOfTabsChanged
-                    object:self];
-}
-
-// Called when a notification is received from the model to select a particular
-// tab. Swaps in the toolbar and content area associated with |newContents|.
-- (void)selectTabWithContents:(TabContentsWrapper*)newContents
-             previousContents:(TabContentsWrapper*)oldContents
-                      atIndex:(NSInteger)modelIndex
-                  userGesture:(bool)wasUserGesture {
-  // Take closing tabs into account.
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-
-  if (oldContents) {
-    int oldModelIndex =
-        browser_->GetIndexOfController(&(oldContents->controller()));
-    if (oldModelIndex != -1) {  // When closing a tab, the old tab may be gone.
-      NSInteger oldIndex = [self indexFromModelIndex:oldModelIndex];
-      TabContentsController* oldController =
-          [tabContentsArray_ objectAtIndex:oldIndex];
-      [oldController willBecomeUnselectedTab];
-      oldContents->view()->StoreFocus();
-      oldContents->tab_contents()->WasHidden();
-    }
-  }
-
-  // De-select all other tabs and select the new tab.
-  int i = 0;
-  for (TabController* current in tabArray_.get()) {
-    [current setSelected:(i == index) ? YES : NO];
-    ++i;
-  }
-
-  // Tell the new tab contents it is about to become the selected tab. Here it
-  // can do things like make sure the toolbar is up to date.
-  TabContentsController* newController =
-      [tabContentsArray_ objectAtIndex:index];
-  [newController willBecomeSelectedTab];
-
-  // Relayout for new tabs and to let the selected tab grow to be larger in
-  // size than surrounding tabs if the user has many. This also raises the
-  // selected tab to the top.
-  [self layoutTabs];
-
-  // Swap in the contents for the new tab.
-  [self swapInTabAtIndex:modelIndex];
-
-  if (newContents) {
-    newContents->tab_contents()->DidBecomeSelected();
-    newContents->view()->RestoreFocus();
-
-    if (newContents->tab_contents()->find_ui_active())
-      browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
-  }
-}
-
-- (void)tabReplacedWithContents:(TabContentsWrapper*)newContents
-               previousContents:(TabContentsWrapper*)oldContents
-                        atIndex:(NSInteger)modelIndex {
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-  TabContentsController* oldController =
-      [tabContentsArray_ objectAtIndex:index];
-  DCHECK_EQ(oldContents->tab_contents(), [oldController tabContents]);
-
-  // Simply create a new TabContentsController for |newContents| and place it
-  // into the array, replacing |oldContents|.  A TabSelectedAt notification will
-  // follow, at which point we will install the new view.
-  scoped_nsobject<TabContentsController> newController(
-      [[TabContentsController alloc]
-          initWithContents:newContents->tab_contents()
-                  delegate:self]);
-
-  // Bye bye, |oldController|.
-  [tabContentsArray_ replaceObjectAtIndex:index withObject:newController];
-
-  [delegate_ onReplaceTabWithContents:newContents->tab_contents()];
-
-  // Fake a tab changed notification to force tab titles and favicons to update.
-  [self tabChangedWithContents:newContents
-                       atIndex:modelIndex
-                    changeType:TabStripModelObserver::ALL];
-}
-
-// Remove all knowledge about this tab and its associated controller, and remove
-// the view from the strip.
-- (void)removeTab:(TabController*)controller {
-  NSUInteger index = [tabArray_ indexOfObject:controller];
-
-  // Release the tab contents controller so those views get destroyed. This
-  // will remove all the tab content Cocoa views from the hierarchy. A
-  // subsequent "select tab" notification will follow from the model. To
-  // tell us what to swap in in its absence.
-  [tabContentsArray_ removeObjectAtIndex:index];
-
-  // Remove the view from the tab strip.
-  NSView* tab = [controller view];
-  [tab removeFromSuperview];
-
-  // Remove ourself as an observer.
-  [[NSNotificationCenter defaultCenter]
-      removeObserver:self
-                name:NSViewDidUpdateTrackingAreasNotification
-              object:tab];
-
-  // Clear the tab controller's target.
-  // TODO(viettrungluu): [crbug.com/23829] Find a better way to handle the tab
-  // controller's target.
-  [controller setTarget:nil];
-
-  if ([hoveredTab_ isEqual:tab])
-    hoveredTab_ = nil;
-
-  NSValue* identifier = [NSValue valueWithPointer:tab];
-  [targetFrames_ removeObjectForKey:identifier];
-
-  // Once we're totally done with the tab, delete its controller
-  [tabArray_ removeObjectAtIndex:index];
-}
-
-// Called by the CAAnimation delegate when the tab completes the closing
-// animation.
-- (void)animationDidStopForController:(TabController*)controller
-                             finished:(BOOL)finished {
-  [closingControllers_ removeObject:controller];
-  [self removeTab:controller];
-}
-
-// Save off which TabController is closing and tell its view's animator
-// where to move the tab to. Registers a delegate to call back when the
-// animation is complete in order to remove the tab from the model.
-- (void)startClosingTabWithAnimation:(TabController*)closingTab {
-  DCHECK([NSThread isMainThread]);
-  // Save off the controller into the set of animating tabs. This alerts
-  // the layout method to not do anything with it and allows us to correctly
-  // calculate offsets when working with indices into the model.
-  [closingControllers_ addObject:closingTab];
-
-  // Mark the tab as closing. This prevents it from generating any drags or
-  // selections while it's animating closed.
-  [(TabView*)[closingTab view] setClosing:YES];
-
-  // Register delegate (owned by the animation system).
-  NSView* tabView = [closingTab view];
-  CAAnimation* animation = [[tabView animationForKey:@"frameOrigin"] copy];
-  [animation autorelease];
-  scoped_nsobject<TabCloseAnimationDelegate> delegate(
-    [[TabCloseAnimationDelegate alloc] initWithTabStrip:self
-                                          tabController:closingTab]);
-  [animation setDelegate:delegate.get()];  // Retains delegate.
-  NSMutableDictionary* animationDictionary =
-      [NSMutableDictionary dictionaryWithDictionary:[tabView animations]];
-  [animationDictionary setObject:animation forKey:@"frameOrigin"];
-  [tabView setAnimations:animationDictionary];
-
-  // Periscope down! Animate the tab.
-  NSRect newFrame = [tabView frame];
-  newFrame = NSOffsetRect(newFrame, 0, -newFrame.size.height);
-  ScopedNSAnimationContextGroup animationGroup(true);
-  animationGroup.SetCurrentContextDuration(kAnimationDuration);
-  [[tabView animator] setFrame:newFrame];
-}
-
-// Called when a notification is received from the model that the given tab
-// has gone away. Start an animation then force a layout to put everything
-// in motion.
-- (void)tabDetachedWithContents:(TabContentsWrapper*)contents
-                        atIndex:(NSInteger)modelIndex {
-  // Take closing tabs into account.
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-
-  TabController* tab = [tabArray_ objectAtIndex:index];
-  if (tabStripModel_->count() > 0) {
-    [self startClosingTabWithAnimation:tab];
-    [self layoutTabs];
-  } else {
-    [self removeTab:tab];
-  }
-
-  // Send a broadcast that the number of tabs have changed.
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:kTabStripNumberOfTabsChanged
-                    object:self];
-
-  [delegate_ onTabDetachedWithContents:contents->tab_contents()];
-}
-
-// A helper routine for creating an NSImageView to hold the fav icon or app icon
-// for |contents|.
-- (NSImageView*)iconImageViewForContents:(TabContents*)contents {
-  BOOL isApp = contents->is_app();
-  NSImage* image = nil;
-  if (isApp) {
-    SkBitmap* icon = contents->GetExtensionAppIcon();
-    if (icon)
-      image = gfx::SkBitmapToNSImage(*icon);
-  } else {
-    image = gfx::SkBitmapToNSImage(contents->GetFavIcon());
-  }
-
-  // Either we don't have a valid favicon or there was some issue converting it
-  // from an SkBitmap. Either way, just show the default.
-  if (!image)
-    image = defaultFavIcon_.get();
-  NSRect frame = NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
-  NSImageView* view = [[[NSImageView alloc] initWithFrame:frame] autorelease];
-  [view setImage:image];
-  return view;
-}
-
-// Updates the current loading state, replacing the icon view with a favicon,
-// a throbber, the default icon, or nothing at all.
-- (void)updateFavIconForContents:(TabContents*)contents
-                         atIndex:(NSInteger)modelIndex {
-  if (!contents)
-    return;
-
-  static NSImage* throbberWaitingImage =
-      [ResourceBundle::GetSharedInstance().GetNativeImageNamed(
-          IDR_THROBBER_WAITING) retain];
-  static NSImage* throbberLoadingImage =
-      [ResourceBundle::GetSharedInstance().GetNativeImageNamed(IDR_THROBBER)
-        retain];
-  static NSImage* sadFaviconImage =
-      [ResourceBundle::GetSharedInstance().GetNativeImageNamed(IDR_SAD_FAVICON)
-        retain];
-
-  // Take closing tabs into account.
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-  TabController* tabController = [tabArray_ objectAtIndex:index];
-
-  bool oldHasIcon = [tabController iconView] != nil;
-  bool newHasIcon = contents->ShouldDisplayFavIcon() ||
-      tabStripModel_->IsMiniTab(modelIndex);  // Always show icon if mini.
-
-  TabLoadingState oldState = [tabController loadingState];
-  TabLoadingState newState = kTabDone;
-  NSImage* throbberImage = nil;
-  if (contents->is_crashed()) {
-    newState = kTabCrashed;
-    newHasIcon = true;
-  } else if (contents->waiting_for_response()) {
-    newState = kTabWaiting;
-    throbberImage = throbberWaitingImage;
-  } else if (contents->is_loading()) {
-    newState = kTabLoading;
-    throbberImage = throbberLoadingImage;
-  }
-
-  if (oldState != newState)
-    [tabController setLoadingState:newState];
-
-  // While loading, this function is called repeatedly with the same state.
-  // To avoid expensive unnecessary view manipulation, only make changes when
-  // the state is actually changing.  When loading is complete (kTabDone),
-  // every call to this function is significant.
-  if (newState == kTabDone || oldState != newState ||
-      oldHasIcon != newHasIcon) {
-    NSView* iconView = nil;
-    if (newHasIcon) {
-      if (newState == kTabDone) {
-        iconView = [self iconImageViewForContents:contents];
-      } else if (newState == kTabCrashed) {
-        NSImage* oldImage = [[self iconImageViewForContents:contents] image];
-        NSRect frame =
-            NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
-        iconView = [ThrobberView toastThrobberViewWithFrame:frame
-                                                beforeImage:oldImage
-                                                 afterImage:sadFaviconImage];
-      } else {
-        NSRect frame =
-            NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
-        iconView = [ThrobberView filmstripThrobberViewWithFrame:frame
-                                                          image:throbberImage];
-      }
-    }
-
-    [tabController setIconView:iconView];
-  }
-}
-
-// Called when a notification is received from the model that the given tab
-// has been updated. |loading| will be YES when we only want to update the
-// throbber state, not anything else about the (partially) loading tab.
-- (void)tabChangedWithContents:(TabContentsWrapper*)contents
-                       atIndex:(NSInteger)modelIndex
-                    changeType:(TabStripModelObserver::TabChangeType)change {
-  // Take closing tabs into account.
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-
-  if (modelIndex == tabStripModel_->selected_index())
-    [delegate_ onSelectedTabChange:change];
-
-  if (change == TabStripModelObserver::TITLE_NOT_LOADING) {
-    // TODO(sky): make this work.
-    // We'll receive another notification of the change asynchronously.
-    return;
-  }
-
-  TabController* tabController = [tabArray_ objectAtIndex:index];
-
-  if (change != TabStripModelObserver::LOADING_ONLY)
-    [self setTabTitle:tabController withContents:contents->tab_contents()];
-
-  [self updateFavIconForContents:contents->tab_contents() atIndex:modelIndex];
-
-  TabContentsController* updatedController =
-      [tabContentsArray_ objectAtIndex:index];
-  [updatedController tabDidChange:contents->tab_contents()];
-}
-
-// Called when a tab is moved (usually by drag&drop). Keep our parallel arrays
-// in sync with the tab strip model. It can also be pinned/unpinned
-// simultaneously, so we need to take care of that.
-- (void)tabMovedWithContents:(TabContentsWrapper*)contents
-                   fromIndex:(NSInteger)modelFrom
-                     toIndex:(NSInteger)modelTo {
-  // Take closing tabs into account.
-  NSInteger from = [self indexFromModelIndex:modelFrom];
-  NSInteger to = [self indexFromModelIndex:modelTo];
-
-  scoped_nsobject<TabContentsController> movedTabContentsController(
-      [[tabContentsArray_ objectAtIndex:from] retain]);
-  [tabContentsArray_ removeObjectAtIndex:from];
-  [tabContentsArray_ insertObject:movedTabContentsController.get()
-                          atIndex:to];
-  scoped_nsobject<TabController> movedTabController(
-      [[tabArray_ objectAtIndex:from] retain]);
-  DCHECK([movedTabController isKindOfClass:[TabController class]]);
-  [tabArray_ removeObjectAtIndex:from];
-  [tabArray_ insertObject:movedTabController.get() atIndex:to];
-
-  // The tab moved, which means that the mini-tab state may have changed.
-  if (tabStripModel_->IsMiniTab(modelTo) != [movedTabController mini])
-    [self tabMiniStateChangedWithContents:contents atIndex:modelTo];
-
-  [self layoutTabs];
-}
-
-// Called when a tab is pinned or unpinned without moving.
-- (void)tabMiniStateChangedWithContents:(TabContentsWrapper*)contents
-                                atIndex:(NSInteger)modelIndex {
-  // Take closing tabs into account.
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-
-  TabController* tabController = [tabArray_ objectAtIndex:index];
-  DCHECK([tabController isKindOfClass:[TabController class]]);
-
-  // Don't do anything if the change was already picked up by the move event.
-  if (tabStripModel_->IsMiniTab(modelIndex) == [tabController mini])
-    return;
-
-  [tabController setMini:tabStripModel_->IsMiniTab(modelIndex)];
-  [tabController setPinned:tabStripModel_->IsTabPinned(modelIndex)];
-  [tabController setApp:tabStripModel_->IsAppTab(modelIndex)];
-  [self updateFavIconForContents:contents->tab_contents() atIndex:modelIndex];
-  // If the tab is being restored and it's pinned, the mini state is set after
-  // the tab has already been rendered, so re-layout the tabstrip. In all other
-  // cases, the state is set before the tab is rendered so this isn't needed.
-  [self layoutTabs];
-}
-
-- (void)setFrameOfSelectedTab:(NSRect)frame {
-  NSView* view = [self selectedTabView];
-  NSValue* identifier = [NSValue valueWithPointer:view];
-  [targetFrames_ setObject:[NSValue valueWithRect:frame]
-                    forKey:identifier];
-  [view setFrame:frame];
-}
-
-- (NSView*)selectedTabView {
-  int selectedIndex = tabStripModel_->selected_index();
-  // Take closing tabs into account. They can't ever be selected.
-  selectedIndex = [self indexFromModelIndex:selectedIndex];
-  return [self viewAtIndex:selectedIndex];
-}
-
-// Find the model index based on the x coordinate of the placeholder. If there
-// is no placeholder, this returns the end of the tab strip. Closing tabs are
-// not considered in computing the index.
-- (int)indexOfPlaceholder {
-  double placeholderX = placeholderFrame_.origin.x;
-  int index = 0;
-  int location = 0;
-  // Use |tabArray_| here instead of the tab strip count in order to get the
-  // correct index when there are closing tabs to the left of the placeholder.
-  const int count = [tabArray_ count];
-  while (index < count) {
-    // Ignore closing tabs for simplicity. The only drawback of this is that
-    // if the placeholder is placed right before one or several contiguous
-    // currently closing tabs, the associated TabController will start at the
-    // end of the closing tabs.
-    if ([closingControllers_ containsObject:[tabArray_ objectAtIndex:index]]) {
-      index++;
-      continue;
-    }
-    NSView* curr = [self viewAtIndex:index];
-    // The placeholder tab works by changing the frame of the tab being dragged
-    // to be the bounds of the placeholder, so we need to skip it while we're
-    // iterating, otherwise we'll end up off by one.  Note This only effects
-    // dragging to the right, not to the left.
-    if (curr == placeholderTab_) {
-      index++;
-      continue;
-    }
-    if (placeholderX <= NSMinX([curr frame]))
-      break;
-    index++;
-    location++;
-  }
-  return location;
-}
-
-// Move the given tab at index |from| in this window to the location of the
-// current placeholder.
-- (void)moveTabFromIndex:(NSInteger)from {
-  int toIndex = [self indexOfPlaceholder];
-  tabStripModel_->MoveTabContentsAt(from, toIndex, true);
-}
-
-// Drop a given TabContents at the location of the current placeholder. If there
-// is no placeholder, it will go at the end. Used when dragging from another
-// window when we don't have access to the TabContents as part of our strip.
-// |frame| is in the coordinate system of the tab strip view and represents
-// where the user dropped the new tab so it can be animated into its correct
-// location when the tab is added to the model. If the tab was pinned in its
-// previous window, setting |pinned| to YES will propagate that state to the
-// new window. Mini-tabs are either app or pinned tabs; the app state is stored
-// by the |contents|, but the |pinned| state is the caller's responsibility.
-- (void)dropTabContents:(TabContentsWrapper*)contents
-              withFrame:(NSRect)frame
-            asPinnedTab:(BOOL)pinned {
-  int modelIndex = [self indexOfPlaceholder];
-
-  // Mark that the new tab being created should start at |frame|. It will be
-  // reset as soon as the tab has been positioned.
-  droppedTabFrame_ = frame;
-
-  // Insert it into this tab strip. We want it in the foreground and to not
-  // inherit the current tab's group.
-  tabStripModel_->InsertTabContentsAt(
-      modelIndex, contents,
-      TabStripModel::ADD_SELECTED | (pinned ? TabStripModel::ADD_PINNED : 0));
-}
-
-// Called when the tab strip view changes size. As we only registered for
-// changes on our view, we know it's only for our view. Layout w/out
-// animations since they are blocked by the resize nested runloop. We need
-// the views to adjust immediately. Neither the tabs nor their z-order are
-// changed, so we don't need to update the subviews.
-- (void)tabViewFrameChanged:(NSNotification*)info {
-  [self layoutTabsWithAnimation:NO regenerateSubviews:NO];
-}
-
-// Called when the tracking areas for any given tab are updated. This allows
-// the individual tabs to update their hover states correctly.
-// Only generates the event if the cursor is in the tab strip.
-- (void)tabUpdateTracking:(NSNotification*)notification {
-  DCHECK([[notification object] isKindOfClass:[TabView class]]);
-  DCHECK(mouseInside_);
-  NSWindow* window = [tabStripView_ window];
-  NSPoint location = [window mouseLocationOutsideOfEventStream];
-  if (NSPointInRect(location, [tabStripView_ frame])) {
-    NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved
-                                             location:location
-                                        modifierFlags:0
-                                            timestamp:0
-                                         windowNumber:[window windowNumber]
-                                              context:nil
-                                          eventNumber:0
-                                           clickCount:0
-                                             pressure:0];
-    [self mouseMoved:mouseEvent];
-  }
-}
-
-- (BOOL)inRapidClosureMode {
-  return availableResizeWidth_ != kUseFullAvailableWidth;
-}
-
-// Disable tab dragging when there are any pending animations.
-- (BOOL)tabDraggingAllowed {
-  return [closingControllers_ count] == 0;
-}
-
-- (void)mouseMoved:(NSEvent*)event {
-  // Use hit test to figure out what view we are hovering over.
-  NSView* targetView = [tabStripView_ hitTest:[event locationInWindow]];
-
-  // Set the new tab button hover state iff the mouse is over the button.
-  BOOL shouldShowHoverImage = [targetView isKindOfClass:[NewTabButton class]];
-  [self setNewTabButtonHoverState:shouldShowHoverImage];
-
-  TabView* tabView = (TabView*)targetView;
-  if (![tabView isKindOfClass:[TabView class]]) {
-    if ([[tabView superview] isKindOfClass:[TabView class]]) {
-      tabView = (TabView*)[targetView superview];
-    } else {
-      tabView = nil;
-    }
-  }
-
-  if (hoveredTab_ != tabView) {
-    [hoveredTab_ mouseExited:nil];  // We don't pass event because moved events
-    [tabView mouseEntered:nil];  // don't have valid tracking areas
-    hoveredTab_ = tabView;
-  } else {
-    [hoveredTab_ mouseMoved:event];
-  }
-}
-
-- (void)mouseEntered:(NSEvent*)event {
-  NSTrackingArea* area = [event trackingArea];
-  if ([area isEqual:trackingArea_]) {
-    mouseInside_ = YES;
-    [self setTabTrackingAreasEnabled:YES];
-    [self mouseMoved:event];
-  }
-}
-
-// Called when the tracking area is in effect which means we're tracking to
-// see if the user leaves the tab strip with their mouse. When they do,
-// reset layout to use all available width.
-- (void)mouseExited:(NSEvent*)event {
-  NSTrackingArea* area = [event trackingArea];
-  if ([area isEqual:trackingArea_]) {
-    mouseInside_ = NO;
-    [self setTabTrackingAreasEnabled:NO];
-    availableResizeWidth_ = kUseFullAvailableWidth;
-    [hoveredTab_ mouseExited:event];
-    hoveredTab_ = nil;
-    [self layoutTabs];
-  } else if ([area isEqual:newTabTrackingArea_]) {
-    // If the mouse is moved quickly enough, it is possible for the mouse to
-    // leave the tabstrip without sending any mouseMoved: messages at all.
-    // Since this would result in the new tab button incorrectly staying in the
-    // hover state, disable the hover image on every mouse exit.
-    [self setNewTabButtonHoverState:NO];
-  }
-}
-
-// Enable/Disable the tracking areas for the tabs. They are only enabled
-// when the mouse is in the tabstrip.
-- (void)setTabTrackingAreasEnabled:(BOOL)enabled {
-  NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
-  for (TabController* controller in tabArray_.get()) {
-    TabView* tabView = [controller tabView];
-    if (enabled) {
-      // Set self up to observe tabs so hover states will be correct.
-      [defaultCenter addObserver:self
-                        selector:@selector(tabUpdateTracking:)
-                            name:NSViewDidUpdateTrackingAreasNotification
-                          object:tabView];
-    } else {
-      [defaultCenter removeObserver:self
-                               name:NSViewDidUpdateTrackingAreasNotification
-                             object:tabView];
-    }
-    [tabView setTrackingEnabled:enabled];
-  }
-}
-
-// Sets the new tab button's image based on the current hover state.  Does
-// nothing if the hover state is already correct.
-- (void)setNewTabButtonHoverState:(BOOL)shouldShowHover {
-  if (shouldShowHover && !newTabButtonShowingHoverImage_) {
-    newTabButtonShowingHoverImage_ = YES;
-    [newTabButton_ setImage:
-        app::mac::GetCachedImageWithName(kNewTabHoverImage)];
-  } else if (!shouldShowHover && newTabButtonShowingHoverImage_) {
-    newTabButtonShowingHoverImage_ = NO;
-    [newTabButton_ setImage:app::mac::GetCachedImageWithName(kNewTabImage)];
-  }
-}
-
-// Adds the given subview to (the end of) the list of permanent subviews
-// (specified from bottom up). These subviews will always be below the
-// transitory subviews (tabs). |-regenerateSubviewList| must be called to
-// effectuate the addition.
-- (void)addSubviewToPermanentList:(NSView*)aView {
-  if (aView)
-    [permanentSubviews_ addObject:aView];
-}
-
-// Update the subviews, keeping the permanent ones (or, more correctly, putting
-// in the ones listed in permanentSubviews_), and putting in the current tabs in
-// the correct z-order. Any current subviews which is neither in the permanent
-// list nor a (current) tab will be removed. So if you add such a subview, you
-// should call |-addSubviewToPermanentList:| (or better yet, call that and then
-// |-regenerateSubviewList| to actually add it).
-- (void)regenerateSubviewList {
-  // Remove self as an observer from all the old tabs before a new set of
-  // potentially different tabs is put in place.
-  [self setTabTrackingAreasEnabled:NO];
-
-  // Subviews to put in (in bottom-to-top order), beginning with the permanent
-  // ones.
-  NSMutableArray* subviews = [NSMutableArray arrayWithArray:permanentSubviews_];
-
-  NSView* selectedTabView = nil;
-  // Go through tabs in reverse order, since |subviews| is bottom-to-top.
-  for (TabController* tab in [tabArray_ reverseObjectEnumerator]) {
-    NSView* tabView = [tab view];
-    if ([tab selected]) {
-      DCHECK(!selectedTabView);
-      selectedTabView = tabView;
-    } else {
-      [subviews addObject:tabView];
-    }
-  }
-  if (selectedTabView) {
-    [subviews addObject:selectedTabView];
-  }
-  [tabStripView_ setSubviews:subviews];
-  [self setTabTrackingAreasEnabled:mouseInside_];
-}
-
-// Get the index and disposition for a potential URL(s) drop given a point (in
-// the |TabStripView|'s coordinates). It considers only the x-coordinate of the
-// given point. If it's in the "middle" of a tab, it drops on that tab. If it's
-// to the left, it inserts to the left, and similarly for the right.
-- (void)droppingURLsAt:(NSPoint)point
-            givesIndex:(NSInteger*)index
-           disposition:(WindowOpenDisposition*)disposition {
-  // Proportion of the tab which is considered the "middle" (and causes things
-  // to drop on that tab).
-  const double kMiddleProportion = 0.5;
-  const double kLRProportion = (1.0 - kMiddleProportion) / 2.0;
-
-  DCHECK(index && disposition);
-  NSInteger i = 0;
-  for (TabController* tab in tabArray_.get()) {
-    NSView* view = [tab view];
-    DCHECK([view isKindOfClass:[TabView class]]);
-
-    // Recall that |-[NSView frame]| is in its superview's coordinates, so a
-    // |TabView|'s frame is in the coordinates of the |TabStripView| (which
-    // matches the coordinate system of |point|).
-    NSRect frame = [view frame];
-
-    // Modify the frame to make it "unoverlapped".
-    frame.origin.x += kTabOverlap / 2.0;
-    frame.size.width -= kTabOverlap;
-    if (frame.size.width < 1.0)
-      frame.size.width = 1.0;  // try to avoid complete failure
-
-    // Drop in a new tab to the left of tab |i|?
-    if (point.x < (frame.origin.x + kLRProportion * frame.size.width)) {
-      *index = i;
-      *disposition = NEW_FOREGROUND_TAB;
-      return;
-    }
-
-    // Drop on tab |i|?
-    if (point.x <= (frame.origin.x +
-                       (1.0 - kLRProportion) * frame.size.width)) {
-      *index = i;
-      *disposition = CURRENT_TAB;
-      return;
-    }
-
-    // (Dropping in a new tab to the right of tab |i| will be taken care of in
-    // the next iteration.)
-    i++;
-  }
-
-  // If we've made it here, we want to append a new tab to the end.
-  *index = -1;
-  *disposition = NEW_FOREGROUND_TAB;
-}
-
-- (void)openURL:(GURL*)url inView:(NSView*)view at:(NSPoint)point {
-  // Get the index and disposition.
-  NSInteger index;
-  WindowOpenDisposition disposition;
-  [self droppingURLsAt:point
-            givesIndex:&index
-           disposition:&disposition];
-
-  // Either insert a new tab or open in a current tab.
-  switch (disposition) {
-    case NEW_FOREGROUND_TAB: {
-      UserMetrics::RecordAction(UserMetricsAction("Tab_DropURLBetweenTabs"),
-                                browser_->profile());
-      browser::NavigateParams params(browser_, *url, PageTransition::TYPED);
-      params.disposition = disposition;
-      params.tabstrip_index = index;
-      params.tabstrip_add_types =
-          TabStripModel::ADD_SELECTED | TabStripModel::ADD_FORCE_INDEX;
-      browser::Navigate(&params);
-      break;
-    }
-    case CURRENT_TAB:
-      UserMetrics::RecordAction(UserMetricsAction("Tab_DropURLOnTab"),
-                                browser_->profile());
-      tabStripModel_->GetTabContentsAt(index)
-          ->tab_contents()->OpenURL(*url, GURL(), CURRENT_TAB,
-                                    PageTransition::TYPED);
-      tabStripModel_->SelectTabContentsAt(index, true);
-      break;
-    default:
-      NOTIMPLEMENTED();
-  }
-}
-
-// (URLDropTargetController protocol)
-- (void)dropURLs:(NSArray*)urls inView:(NSView*)view at:(NSPoint)point {
-  DCHECK_EQ(view, tabStripView_.get());
-
-  if ([urls count] < 1) {
-    NOTREACHED();
-    return;
-  }
-
-  //TODO(viettrungluu): dropping multiple URLs.
-  if ([urls count] > 1)
-    NOTIMPLEMENTED();
-
-  // Get the first URL and fix it up.
-  GURL url(GURL(URLFixerUpper::FixupURL(
-      base::SysNSStringToUTF8([urls objectAtIndex:0]), std::string())));
-
-  [self openURL:&url inView:view at:point];
-}
-
-// (URLDropTargetController protocol)
-- (void)dropText:(NSString*)text inView:(NSView*)view at:(NSPoint)point {
-  DCHECK_EQ(view, tabStripView_.get());
-
-  // If the input is plain text, classify the input and make the URL.
-  AutocompleteMatch match;
-  browser_->profile()->GetAutocompleteClassifier()->Classify(
-      base::SysNSStringToWide(text),
-      std::wstring(), false, &match, NULL);
-  GURL url(match.destination_url);
-
-  [self openURL:&url inView:view at:point];
-}
-
-// (URLDropTargetController protocol)
-- (void)indicateDropURLsInView:(NSView*)view at:(NSPoint)point {
-  DCHECK_EQ(view, tabStripView_.get());
-
-  // The minimum y-coordinate at which one should consider place the arrow.
-  const CGFloat arrowBaseY = 25;
-
-  NSInteger index;
-  WindowOpenDisposition disposition;
-  [self droppingURLsAt:point
-            givesIndex:&index
-           disposition:&disposition];
-
-  NSPoint arrowPos = NSMakePoint(0, arrowBaseY);
-  if (index == -1) {
-    // Append a tab at the end.
-    DCHECK(disposition == NEW_FOREGROUND_TAB);
-    NSInteger lastIndex = [tabArray_ count] - 1;
-    NSRect overRect = [[[tabArray_ objectAtIndex:lastIndex] view] frame];
-    arrowPos.x = overRect.origin.x + overRect.size.width - kTabOverlap / 2.0;
-  } else {
-    NSRect overRect = [[[tabArray_ objectAtIndex:index] view] frame];
-    switch (disposition) {
-      case NEW_FOREGROUND_TAB:
-        // Insert tab (to the left of the given tab).
-        arrowPos.x = overRect.origin.x + kTabOverlap / 2.0;
-        break;
-      case CURRENT_TAB:
-        // Overwrite the given tab.
-        arrowPos.x = overRect.origin.x + overRect.size.width / 2.0;
-        break;
-      default:
-        NOTREACHED();
-    }
-  }
-
-  [tabStripView_ setDropArrowPosition:arrowPos];
-  [tabStripView_ setDropArrowShown:YES];
-  [tabStripView_ setNeedsDisplay:YES];
-}
-
-// (URLDropTargetController protocol)
-- (void)hideDropURLsIndicatorInView:(NSView*)view {
-  DCHECK_EQ(view, tabStripView_.get());
-
-  if ([tabStripView_ dropArrowShown]) {
-    [tabStripView_ setDropArrowShown:NO];
-    [tabStripView_ setNeedsDisplay:YES];
-  }
-}
-
-- (GTMWindowSheetController*)sheetController {
-  if (!sheetController_.get())
-    sheetController_.reset([[GTMWindowSheetController alloc]
-        initWithWindow:[switchView_ window] delegate:self]);
-  return sheetController_.get();
-}
-
-- (void)destroySheetController {
-  // Make sure there are no open sheets.
-  DCHECK_EQ(0U, [[sheetController_ viewsWithAttachedSheets] count]);
-  sheetController_.reset();
-}
-
-// TabContentsControllerDelegate protocol.
-- (void)tabContentsViewFrameWillChange:(TabContentsController*)source
-                             frameRect:(NSRect)frameRect {
-  id<TabContentsControllerDelegate> controller =
-      [[switchView_ window] windowController];
-  [controller tabContentsViewFrameWillChange:source frameRect:frameRect];
-}
-
-- (TabContentsController*)activeTabContentsController {
-  int modelIndex = tabStripModel_->selected_index();
-  if (modelIndex < 0)
-    return nil;
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-  if (index < 0 ||
-      index >= (NSInteger)[tabContentsArray_ count])
-    return nil;
-  return [tabContentsArray_ objectAtIndex:index];
-}
-
-- (void)gtm_systemRequestsVisibilityForView:(NSView*)view {
-  // This implementation is required by GTMWindowSheetController.
-
-  // Raise window...
-  [[switchView_ window] makeKeyAndOrderFront:self];
-
-  // ...and raise a tab with a sheet.
-  NSInteger index = [self modelIndexForContentsView:view];
-  DCHECK(index >= 0);
-  if (index >= 0)
-    tabStripModel_->SelectTabContentsAt(index, false /* not a user gesture */);
-}
-
-- (void)attachConstrainedWindow:(ConstrainedWindowMac*)window {
-  // TODO(thakis, avi): Figure out how to make this work when tabs are dragged
-  // out or if fullscreen mode is toggled.
-
-  // View hierarchy of the contents view:
-  // NSView  -- switchView, same for all tabs
-  // +- NSView  -- TabContentsController's view
-  //    +- TabContentsViewCocoa
-  // Changing it? Do not forget to modify removeConstrainedWindow too.
-  // We use the TabContentsController's view in |swapInTabAtIndex|, so we have
-  // to pass it to the sheet controller here.
-  NSView* tabContentsView = [window->owner()->GetNativeView() superview];
-  window->delegate()->RunSheet([self sheetController], tabContentsView);
-
-  // TODO(avi, thakis): GTMWindowSheetController has no api to move tabsheets
-  // between windows. Until then, we have to prevent having to move a tabsheet
-  // between windows, e.g. no tearing off of tabs.
-  NSInteger modelIndex = [self modelIndexForContentsView:tabContentsView];
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-  BrowserWindowController* controller =
-      (BrowserWindowController*)[[switchView_ window] windowController];
-  DCHECK(controller != nil);
-  DCHECK(index >= 0);
-  if (index >= 0) {
-    [controller setTab:[self viewAtIndex:index] isDraggable:NO];
-  }
-}
-
-- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window {
-  NSView* tabContentsView = [window->owner()->GetNativeView() superview];
-
-  // TODO(avi, thakis): GTMWindowSheetController has no api to move tabsheets
-  // between windows. Until then, we have to prevent having to move a tabsheet
-  // between windows, e.g. no tearing off of tabs.
-  NSInteger modelIndex = [self modelIndexForContentsView:tabContentsView];
-  NSInteger index = [self indexFromModelIndex:modelIndex];
-  BrowserWindowController* controller =
-      (BrowserWindowController*)[[switchView_ window] windowController];
-  DCHECK(index >= 0);
-  if (index >= 0) {
-    [controller setTab:[self viewAtIndex:index] isDraggable:YES];
-  }
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/tab_strip_controller_unittest.mm b/chrome/browser/ui/cocoa/tab_strip_controller_unittest.mm
deleted file mode 100644
index 189e57b..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_controller_unittest.mm
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/browser_window.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/renderer_host/site_instance.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/new_tab_button.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface TestTabStripControllerDelegate :
-  NSObject<TabStripControllerDelegate> {
-}
-@end
-
-@implementation TestTabStripControllerDelegate
-- (void)onSelectTabWithContents:(TabContents*)contents {
-}
-- (void)onReplaceTabWithContents:(TabContents*)contents {
-}
-- (void)onSelectedTabChange:(TabStripModelObserver::TabChangeType)change {
-}
-- (void)onTabDetachedWithContents:(TabContents*)contents {
-}
-@end
-
-namespace {
-
-// Stub model delegate
-class TestTabStripDelegate : public TabStripModelDelegate {
- public:
-  virtual TabContentsWrapper* AddBlankTab(bool foreground) {
-    return NULL;
-  }
-  virtual TabContentsWrapper* AddBlankTabAt(int index, bool foreground) {
-    return NULL;
-  }
-  virtual Browser* CreateNewStripWithContents(TabContentsWrapper* contents,
-                                              const gfx::Rect& window_bounds,
-                                              const DockInfo& dock_info,
-                                              bool maximize) {
-    return NULL;
-  }
-  virtual void ContinueDraggingDetachedTab(TabContentsWrapper* contents,
-                                           const gfx::Rect& window_bounds,
-                                           const gfx::Rect& tab_bounds) {
-  }
-  virtual int GetDragActions() const {
-    return 0;
-  }
-  virtual TabContentsWrapper* CreateTabContentsForURL(
-      const GURL& url,
-      const GURL& referrer,
-      Profile* profile,
-      PageTransition::Type transition,
-      bool defer_load,
-      SiteInstance* instance) const {
-    return NULL;
-  }
-  virtual bool CanDuplicateContentsAt(int index) { return true; }
-  virtual void DuplicateContentsAt(int index) { }
-  virtual void CloseFrameAfterDragSession() { }
-  virtual void CreateHistoricalTab(TabContentsWrapper* contents) { }
-  virtual bool RunUnloadListenerBeforeClosing(TabContentsWrapper* contents) {
-    return true;
-  }
-  virtual bool CanRestoreTab() {
-    return true;
-  }
-  virtual void RestoreTab() {}
-
-  virtual bool CanCloseContentsAt(int index) { return true; }
-
-  virtual bool CanBookmarkAllTabs() const { return false; }
-
-  virtual bool CanCloseTab() const { return true; }
-
-  virtual void BookmarkAllTabs() {}
-
-  virtual bool UseVerticalTabs() const { return false; }
-
-  virtual void ToggleUseVerticalTabs() {}
-
-  virtual bool LargeIconsPermitted() const { return true; }
-};
-
-class TabStripControllerTest : public CocoaTest {
- public:
-  TabStripControllerTest() {
-    Browser* browser = browser_helper_.browser();
-    BrowserWindow* browser_window = browser_helper_.CreateBrowserWindow();
-    NSWindow* window = browser_window->GetNativeHandle();
-    NSView* parent = [window contentView];
-    NSRect content_frame = [parent frame];
-
-    // Create the "switch view" (view that gets changed out when a tab
-    // switches).
-    NSRect switch_frame = NSMakeRect(0, 0, content_frame.size.width, 500);
-    scoped_nsobject<NSView> switch_view(
-        [[NSView alloc] initWithFrame:switch_frame]);
-    [parent addSubview:switch_view.get()];
-
-    // Create the tab strip view. It's expected to have a child button in it
-    // already as the "new tab" button so create that too.
-    NSRect strip_frame = NSMakeRect(0, NSMaxY(switch_frame),
-                                    content_frame.size.width, 30);
-    scoped_nsobject<TabStripView> tab_strip(
-        [[TabStripView alloc] initWithFrame:strip_frame]);
-    [parent addSubview:tab_strip.get()];
-    NSRect button_frame = NSMakeRect(0, 0, 15, 15);
-    scoped_nsobject<NewTabButton> new_tab_button(
-        [[NewTabButton alloc] initWithFrame:button_frame]);
-    [tab_strip addSubview:new_tab_button.get()];
-    [tab_strip setNewTabButton:new_tab_button.get()];
-
-    delegate_.reset(new TestTabStripDelegate());
-    model_ = browser->tabstrip_model();
-    controller_delegate_.reset([TestTabStripControllerDelegate alloc]);
-    controller_.reset([[TabStripController alloc]
-                        initWithView:static_cast<TabStripView*>(tab_strip.get())
-                          switchView:switch_view.get()
-                             browser:browser
-                            delegate:controller_delegate_.get()]);
-  }
-
-  virtual void TearDown() {
-    browser_helper_.CloseBrowserWindow();
-    // The call to CocoaTest::TearDown() deletes the Browser and TabStripModel
-    // objects, so we first have to delete the controller, which refers to them.
-    controller_.reset(nil);
-    model_ = NULL;
-    CocoaTest::TearDown();
-  }
-
-  BrowserTestHelper browser_helper_;
-  scoped_ptr<TestTabStripDelegate> delegate_;
-  TabStripModel* model_;
-  scoped_nsobject<TestTabStripControllerDelegate> controller_delegate_;
-  scoped_nsobject<TabStripController> controller_;
-};
-
-// Test adding and removing tabs and making sure that views get added to
-// the tab strip.
-TEST_F(TabStripControllerTest, AddRemoveTabs) {
-  EXPECT_TRUE(model_->empty());
-  SiteInstance* instance =
-      SiteInstance::CreateSiteInstance(browser_helper_.profile());
-  TabContentsWrapper* tab_contents =
-      Browser::TabContentsFactory(browser_helper_.profile(), instance,
-          MSG_ROUTING_NONE, NULL, NULL);
-  model_->AppendTabContents(tab_contents, true);
-  EXPECT_EQ(model_->count(), 1);
-}
-
-TEST_F(TabStripControllerTest, SelectTab) {
-  // TODO(pinkerton): Implement http://crbug.com/10899
-}
-
-TEST_F(TabStripControllerTest, RearrangeTabs) {
-  // TODO(pinkerton): Implement http://crbug.com/10899
-}
-
-// Test that changing the number of tabs broadcasts a
-// kTabStripNumberOfTabsChanged notifiction.
-TEST_F(TabStripControllerTest, Notifications) {
-  // TODO(pinkerton): Implement http://crbug.com/10899
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h b/chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h
deleted file mode 100644
index 534fcfb..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
-#pragma once
-
-#import <Foundation/Foundation.h>
-
-#include "chrome/browser/tabs/tab_strip_model_observer.h"
-
-class TabContentsWrapper;
-class TabStripModel;
-
-// A C++ bridge class to handle receiving notifications from the C++ tab strip
-// model. When the caller allocates a bridge, it automatically registers for
-// notifications from |model| and passes messages to |controller| via the
-// informal protocol below. The owner of this object is responsible for deleting
-// it (and thus unhooking notifications) before |controller| is destroyed.
-class TabStripModelObserverBridge : public TabStripModelObserver {
- public:
-  TabStripModelObserverBridge(TabStripModel* model, id controller);
-  virtual ~TabStripModelObserverBridge();
-
-  // Overridden from TabStripModelObserver
-  virtual void TabInsertedAt(TabContentsWrapper* contents,
-                             int index,
-                             bool foreground);
-  virtual void TabClosingAt(TabStripModel* tab_strip_model,
-                            TabContentsWrapper* contents,
-                            int index);
-  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
-  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* new_contents,
-                             int index,
-                             bool user_gesture);
-  virtual void TabMoved(TabContentsWrapper* contents,
-                        int from_index,
-                        int to_index);
-  virtual void TabChangedAt(TabContentsWrapper* contents, int index,
-                            TabChangeType change_type);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* new_contents,
-                             int index);
-  virtual void TabMiniStateChanged(TabContentsWrapper* contents, int index);
-  virtual void TabStripEmpty();
-  virtual void TabStripModelDeleted();
-
- private:
-  id controller_;  // weak, owns me
-  TabStripModel* model_;  // weak, owned by Browser
-};
-
-// A collection of methods which can be selectively implemented by any
-// Cocoa object to receive updates about changes to a tab strip model. It is
-// ok to not implement them, the calling code checks before calling.
-@interface NSObject(TabStripModelBridge)
-- (void)insertTabWithContents:(TabContentsWrapper*)contents
-                      atIndex:(NSInteger)index
-                 inForeground:(bool)inForeground;
-- (void)tabClosingWithContents:(TabContentsWrapper*)contents
-                       atIndex:(NSInteger)index;
-- (void)tabDetachedWithContents:(TabContentsWrapper*)contents
-                        atIndex:(NSInteger)index;
-- (void)selectTabWithContents:(TabContentsWrapper*)newContents
-             previousContents:(TabContentsWrapper*)oldContents
-                      atIndex:(NSInteger)index
-                  userGesture:(bool)wasUserGesture;
-- (void)tabMovedWithContents:(TabContentsWrapper*)contents
-                    fromIndex:(NSInteger)from
-                      toIndex:(NSInteger)to;
-- (void)tabChangedWithContents:(TabContentsWrapper*)contents
-                       atIndex:(NSInteger)index
-                    changeType:(TabStripModelObserver::TabChangeType)change;
-- (void)tabReplacedWithContents:(TabContentsWrapper*)newContents
-               previousContents:(TabContentsWrapper*)oldContents
-                        atIndex:(NSInteger)index;
-- (void)tabMiniStateChangedWithContents:(TabContentsWrapper*)contents
-                                atIndex:(NSInteger)index;
-- (void)tabStripEmpty;
-- (void)tabStripModelDeleted;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.mm b/chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.mm
deleted file mode 100644
index a998d23..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.mm
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h"
-
-#include "chrome/browser/tabs/tab_strip_model.h"
-
-TabStripModelObserverBridge::TabStripModelObserverBridge(TabStripModel* model,
-                                                         id controller)
-    : controller_(controller), model_(model) {
-  DCHECK(model && controller);
-  // Register to be a listener on the model so we can get updates and tell
-  // |controller_| about them in the future.
-  model_->AddObserver(this);
-}
-
-TabStripModelObserverBridge::~TabStripModelObserverBridge() {
-  // Remove ourselves from receiving notifications.
-  model_->RemoveObserver(this);
-}
-
-void TabStripModelObserverBridge::TabInsertedAt(TabContentsWrapper* contents,
-                                                int index,
-                                                bool foreground) {
-  if ([controller_ respondsToSelector:
-          @selector(insertTabWithContents:atIndex:inForeground:)]) {
-    [controller_ insertTabWithContents:contents
-                               atIndex:index
-                          inForeground:foreground];
-  }
-}
-
-void TabStripModelObserverBridge::TabClosingAt(TabStripModel* tab_strip_model,
-                                               TabContentsWrapper* contents,
-                                               int index) {
-  if ([controller_ respondsToSelector:
-          @selector(tabClosingWithContents:atIndex:)]) {
-    [controller_ tabClosingWithContents:contents atIndex:index];
-  }
-}
-
-void TabStripModelObserverBridge::TabDetachedAt(TabContentsWrapper* contents,
-                                                int index) {
-  if ([controller_ respondsToSelector:
-          @selector(tabDetachedWithContents:atIndex:)]) {
-    [controller_ tabDetachedWithContents:contents atIndex:index];
-  }
-}
-
-void TabStripModelObserverBridge::TabSelectedAt(
-    TabContentsWrapper* old_contents,
-    TabContentsWrapper* new_contents,
-    int index,
-    bool user_gesture) {
-  if ([controller_ respondsToSelector:
-          @selector(selectTabWithContents:previousContents:atIndex:
-                    userGesture:)]) {
-    [controller_ selectTabWithContents:new_contents
-                      previousContents:old_contents
-                               atIndex:index
-                           userGesture:user_gesture];
-  }
-}
-
-void TabStripModelObserverBridge::TabMoved(TabContentsWrapper* contents,
-                                           int from_index,
-                                           int to_index) {
-  if ([controller_ respondsToSelector:
-       @selector(tabMovedWithContents:fromIndex:toIndex:)]) {
-    [controller_ tabMovedWithContents:contents
-                            fromIndex:from_index
-                              toIndex:to_index];
-  }
-}
-
-void TabStripModelObserverBridge::TabChangedAt(TabContentsWrapper* contents,
-                                               int index,
-                                               TabChangeType change_type) {
-  if ([controller_ respondsToSelector:
-          @selector(tabChangedWithContents:atIndex:changeType:)]) {
-    [controller_ tabChangedWithContents:contents
-                                atIndex:index
-                             changeType:change_type];
-  }
-}
-
-void TabStripModelObserverBridge::TabReplacedAt(
-    TabContentsWrapper* old_contents,
-    TabContentsWrapper* new_contents,
-    int index) {
-  if ([controller_ respondsToSelector:
-          @selector(tabReplacedWithContents:previousContents:atIndex:)]) {
-    [controller_ tabReplacedWithContents:new_contents
-                        previousContents:old_contents
-                                 atIndex:index];
-  } else {
-    TabChangedAt(new_contents, index, ALL);
-  }
-}
-
-void TabStripModelObserverBridge::TabMiniStateChanged(
-    TabContentsWrapper* contents, int index) {
-  if ([controller_ respondsToSelector:
-          @selector(tabMiniStateChangedWithContents:atIndex:)]) {
-    [controller_ tabMiniStateChangedWithContents:contents atIndex:index];
-  }
-}
-
-void TabStripModelObserverBridge::TabStripEmpty() {
-  if ([controller_ respondsToSelector:@selector(tabStripEmpty)])
-    [controller_ tabStripEmpty];
-}
-
-void TabStripModelObserverBridge::TabStripModelDeleted() {
-  if ([controller_ respondsToSelector:@selector(tabStripModelDeleted)])
-    [controller_ tabStripModelDeleted];
-}
diff --git a/chrome/browser/ui/cocoa/tab_strip_view.h b/chrome/browser/ui/cocoa/tab_strip_view.h
deleted file mode 100644
index f504ff4..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_view.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_STRIP_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_STRIP_VIEW_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/url_drop_target.h"
-
-@class NewTabButton;
-
-// A view class that handles rendering the tab strip and drops of URLS with
-// a positioning locator for drop feedback.
-
-@interface TabStripView : NSView<URLDropTarget> {
- @private
-  NSTimeInterval lastMouseUp_;
-
-  // Handles being a drag-and-drop target.
-  scoped_nsobject<URLDropTargetHandler> dropHandler_;
-
-  // Weak; the following come from the nib.
-  NewTabButton* newTabButton_;
-
-  // Whether the drop-indicator arrow is shown, and if it is, the coordinate of
-  // its tip.
-  BOOL dropArrowShown_;
-  NSPoint dropArrowPosition_;
-}
-
-@property(assign, nonatomic) IBOutlet NewTabButton* newTabButton;
-@property(assign, nonatomic) BOOL dropArrowShown;
-@property(assign, nonatomic) NSPoint dropArrowPosition;
-
-@end
-
-// Protected methods subclasses can override to alter behavior. Clients should
-// not call these directly.
-@interface TabStripView(Protected)
-- (void)drawBottomBorder:(NSRect)bounds;
-- (BOOL)doubleClickMinimizesWindow;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_STRIP_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tab_strip_view.mm b/chrome/browser/ui/cocoa/tab_strip_view.mm
deleted file mode 100644
index 857da65..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_view.mm
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-
-@implementation TabStripView
-
-@synthesize newTabButton = newTabButton_;
-@synthesize dropArrowShown = dropArrowShown_;
-@synthesize dropArrowPosition = dropArrowPosition_;
-
-- (id)initWithFrame:(NSRect)frame {
-  self = [super initWithFrame:frame];
-  if (self) {
-    // Set lastMouseUp_ = -1000.0 so that timestamp-lastMouseUp_ is big unless
-    // lastMouseUp_ has been reset.
-    lastMouseUp_ = -1000.0;
-
-    // Register to be an URL drop target.
-    dropHandler_.reset([[URLDropTargetHandler alloc] initWithView:self]);
-  }
-  return self;
-}
-
-// Draw bottom border (a dark border and light highlight). Each tab is
-// responsible for mimicking this bottom border, unless it's the selected
-// tab.
-- (void)drawBorder:(NSRect)bounds {
-  NSRect borderRect, contentRect;
-
-  borderRect = bounds;
-  borderRect.origin.y = 1;
-  borderRect.size.height = 1;
-  [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
-  NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
-  NSDivideRect(bounds, &borderRect, &contentRect, 1, NSMinYEdge);
-
-  BrowserThemeProvider* themeProvider =
-      static_cast<BrowserThemeProvider*>([[self window] themeProvider]);
-  if (!themeProvider)
-    return;
-
-  NSColor* bezelColor = themeProvider->GetNSColor(
-      themeProvider->UsingDefaultTheme() ?
-          BrowserThemeProvider::COLOR_TOOLBAR_BEZEL :
-          BrowserThemeProvider::COLOR_TOOLBAR, true);
-  [bezelColor set];
-  NSRectFill(borderRect);
-  NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
-}
-
-- (void)drawRect:(NSRect)rect {
-  NSRect boundsRect = [self bounds];
-
-  [self drawBorder:boundsRect];
-
-  // Draw drop-indicator arrow (if appropriate).
-  // TODO(viettrungluu): this is all a stop-gap measure.
-  if ([self dropArrowShown]) {
-    // Programmer art: an arrow parametrized by many knobs. Note that the arrow
-    // points downwards (so understand "width" and "height" accordingly).
-
-    // How many (pixels) to inset on the top/bottom.
-    const CGFloat kArrowTopInset = 1.5;
-    const CGFloat kArrowBottomInset = 1;
-
-    // What proportion of the vertical space is dedicated to the arrow tip,
-    // i.e., (arrow tip height)/(amount of vertical space).
-    const CGFloat kArrowTipProportion = 0.5;
-
-    // This is a slope, i.e., (arrow tip height)/(0.5 * arrow tip width).
-    const CGFloat kArrowTipSlope = 1.2;
-
-    // What proportion of the arrow tip width is the stem, i.e., (stem
-    // width)/(arrow tip width).
-    const CGFloat kArrowStemProportion = 0.33;
-
-    NSPoint arrowTipPos = [self dropArrowPosition];
-    arrowTipPos.y += kArrowBottomInset;  // Inset on the bottom.
-
-    // Height we have to work with (insetting on the top).
-    CGFloat availableHeight =
-        NSMaxY(boundsRect) - arrowTipPos.y - kArrowTopInset;
-    DCHECK(availableHeight >= 5);
-
-    // Based on the knobs above, calculate actual dimensions which we'll need
-    // for drawing.
-    CGFloat arrowTipHeight = kArrowTipProportion * availableHeight;
-    CGFloat arrowTipWidth = 2 * arrowTipHeight / kArrowTipSlope;
-    CGFloat arrowStemHeight = availableHeight - arrowTipHeight;
-    CGFloat arrowStemWidth = kArrowStemProportion * arrowTipWidth;
-    CGFloat arrowStemInset = (arrowTipWidth - arrowStemWidth) / 2;
-
-    // The line width is arbitrary, but our path really should be mitered.
-    NSBezierPath* arrow = [NSBezierPath bezierPath];
-    [arrow setLineJoinStyle:NSMiterLineJoinStyle];
-    [arrow setLineWidth:1];
-
-    // Define the arrow's shape! We start from the tip and go clockwise.
-    [arrow moveToPoint:arrowTipPos];
-    [arrow relativeLineToPoint:NSMakePoint(-arrowTipWidth / 2, arrowTipHeight)];
-    [arrow relativeLineToPoint:NSMakePoint(arrowStemInset, 0)];
-    [arrow relativeLineToPoint:NSMakePoint(0, arrowStemHeight)];
-    [arrow relativeLineToPoint:NSMakePoint(arrowStemWidth, 0)];
-    [arrow relativeLineToPoint:NSMakePoint(0, -arrowStemHeight)];
-    [arrow relativeLineToPoint:NSMakePoint(arrowStemInset, 0)];
-    [arrow closePath];
-
-    // Draw and fill the arrow.
-    [[NSColor colorWithCalibratedWhite:0 alpha:0.67] set];
-    [arrow stroke];
-    [[NSColor colorWithCalibratedWhite:1 alpha:0.67] setFill];
-    [arrow fill];
-  }
-}
-
-// YES if a double-click in the background of the tab strip minimizes the
-// window.
-- (BOOL)doubleClickMinimizesWindow {
-  return YES;
-}
-
-// We accept first mouse so clicks onto close/zoom/miniaturize buttons and
-// title bar double-clicks are properly detected even when the window is in the
-// background.
-- (BOOL)acceptsFirstMouse:(NSEvent*)event {
-  return YES;
-}
-
-// Trap double-clicks and make them miniaturize the browser window.
-- (void)mouseUp:(NSEvent*)event {
-  // Bail early if double-clicks are disabled.
-  if (![self doubleClickMinimizesWindow]) {
-    [super mouseUp:event];
-    return;
-  }
-
-  NSInteger clickCount = [event clickCount];
-  NSTimeInterval timestamp = [event timestamp];
-
-  // Double-clicks on Zoom/Close/Mininiaturize buttons shouldn't cause
-  // miniaturization. For those, we miss the first click but get the second
-  // (with clickCount == 2!). We thus check that we got a first click shortly
-  // before (measured up-to-up) a double-click. Cocoa doesn't have a documented
-  // way of getting the proper interval (= (double-click-threshold) +
-  // (drag-threshold); the former is Carbon GetDblTime()/60.0 or
-  // com.apple.mouse.doubleClickThreshold [undocumented]). So we hard-code
-  // "short" as 0.8 seconds. (Measuring up-to-up isn't enough to properly
-  // detect double-clicks, but we're actually using Cocoa for that.)
-  if (clickCount == 2 && (timestamp - lastMouseUp_) < 0.8) {
-    if (base::mac::ShouldWindowsMiniaturizeOnDoubleClick())
-      [[self window] performMiniaturize:self];
-  } else {
-    [super mouseUp:event];
-  }
-
-  // If clickCount is 0, the drag threshold was passed.
-  lastMouseUp_ = (clickCount == 1) ? timestamp : -1000.0;
-}
-
-// (URLDropTarget protocol)
-- (id<URLDropTargetController>)urlDropController {
-  BrowserWindowController* windowController = [[self window] windowController];
-  DCHECK([windowController isKindOfClass:[BrowserWindowController class]]);
-  return [windowController tabStripController];
-}
-
-// (URLDropTarget protocol)
-- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
-  return [dropHandler_ draggingEntered:sender];
-}
-
-// (URLDropTarget protocol)
-- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
-  return [dropHandler_ draggingUpdated:sender];
-}
-
-// (URLDropTarget protocol)
-- (void)draggingExited:(id<NSDraggingInfo>)sender {
-  return [dropHandler_ draggingExited:sender];
-}
-
-// (URLDropTarget protocol)
-- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
-  return [dropHandler_ performDragOperation:sender];
-}
-
-- (BOOL)accessibilityIsIgnored {
-  return NO;
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attribute {
-  if ([attribute isEqual:NSAccessibilityRoleAttribute])
-    return NSAccessibilityGroupRole;
-
-  return [super accessibilityAttributeValue:attribute];
-}
-
-- (ViewID)viewID {
-  return VIEW_ID_TAB_STRIP;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/tab_strip_view_unittest.mm b/chrome/browser/ui/cocoa/tab_strip_view_unittest.mm
deleted file mode 100644
index 2fde99c..0000000
--- a/chrome/browser/ui/cocoa/tab_strip_view_unittest.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class TabStripViewTest : public CocoaTest {
- public:
-  TabStripViewTest() {
-    NSRect frame = NSMakeRect(0, 0, 100, 30);
-    scoped_nsobject<TabStripView> view(
-        [[TabStripView alloc] initWithFrame:frame]);
-    view_ = view.get();
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  TabStripView* view_;
-};
-
-TEST_VIEW(TabStripViewTest, view_)
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/tab_view.h b/chrome/browser/ui/cocoa/tab_view.h
deleted file mode 100644
index f351650..0000000
--- a/chrome/browser/ui/cocoa/tab_view.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_VIEW_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-#include <ApplicationServices/ApplicationServices.h>
-
-#include <map>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/background_gradient_view.h"
-#import "chrome/browser/ui/cocoa/hover_close_button.h"
-
-namespace tabs {
-
-// Nomenclature:
-// Tabs _glow_ under two different circumstances, when they are _hovered_ (by
-// the mouse) and when they are _alerted_ (to show that the tab's title has
-// changed).
-
-// The state of alerting (to show a title change on an unselected, pinned tab).
-// This is more complicated than a simple on/off since we want to allow the
-// alert glow to go through a full rise-hold-fall cycle to avoid flickering (or
-// always holding).
-enum AlertState {
-  kAlertNone = 0,  // Obj-C initializes to this.
-  kAlertRising,
-  kAlertHolding,
-  kAlertFalling
-};
-
-}  // namespace tabs
-
-@class TabController, TabWindowController;
-
-// A view that handles the event tracking (clicking and dragging) for a tab
-// on the tab strip. Relies on an associated TabController to provide a
-// target/action for selecting the tab.
-
-@interface TabView : BackgroundGradientView {
- @private
-  IBOutlet TabController* controller_;
-  // TODO(rohitrao): Add this button to a CoreAnimation layer so we can fade it
-  // in and out on mouseovers.
-  IBOutlet HoverCloseButton* closeButton_;
-
-  // See awakeFromNib for purpose.
-  scoped_nsobject<HoverCloseButton> closeButtonRetainer_;
-
-  BOOL closing_;
-
-  // Tracking area for close button mouseover images.
-  scoped_nsobject<NSTrackingArea> closeTrackingArea_;
-
-  BOOL isMouseInside_;  // Is the mouse hovering over?
-  tabs::AlertState alertState_;
-
-  CGFloat hoverAlpha_;  // How strong the hover glow is.
-  NSTimeInterval hoverHoldEndTime_;  // When the hover glow will begin dimming.
-
-  CGFloat alertAlpha_;  // How strong the alert glow is.
-  NSTimeInterval alertHoldEndTime_;  // When the hover glow will begin dimming.
-
-  NSTimeInterval lastGlowUpdate_;  // Time either glow was last updated.
-
-  NSPoint hoverPoint_;  // Current location of hover in view coords.
-
-  // All following variables are valid for the duration of a drag.
-  // These are released on mouseUp:
-  BOOL moveWindowOnDrag_;  // Set if the only tab of a window is dragged.
-  BOOL tabWasDragged_;  // Has the tab been dragged?
-  BOOL draggingWithinTabStrip_;  // Did drag stay in the current tab strip?
-  BOOL chromeIsVisible_;
-
-  NSTimeInterval tearTime_;  // Time since tear happened
-  NSPoint tearOrigin_;  // Origin of the tear rect
-  NSPoint dragOrigin_;  // Origin point of the drag
-  // TODO(alcor): these references may need to be strong to avoid crashes
-  // due to JS closing windows
-  TabWindowController* sourceController_;  // weak. controller starting the drag
-  NSWindow* sourceWindow_;  // weak. The window starting the drag
-  NSRect sourceWindowFrame_;
-  NSRect sourceTabFrame_;
-
-  TabWindowController* draggedController_;  // weak. Controller being dragged.
-  NSWindow* dragWindow_;  // weak. The window being dragged
-  NSWindow* dragOverlay_;  // weak. The overlay being dragged
-  // Cache workspace IDs per-drag because computing them on 10.5 with
-  // CGWindowListCreateDescriptionFromArray is expensive.
-  // resetDragControllers clears this cache.
-  //
-  // TODO(davidben): When 10.5 becomes unsupported, remove this.
-  std::map<CGWindowID, int> workspaceIDCache_;
-
-  TabWindowController* targetController_;  // weak. Controller being targeted
-  NSCellStateValue state_;
-}
-
-@property(assign, nonatomic) NSCellStateValue state;
-@property(assign, nonatomic) CGFloat hoverAlpha;
-@property(assign, nonatomic) CGFloat alertAlpha;
-
-// Determines if the tab is in the process of animating closed. It may still
-// be visible on-screen, but should not respond to/initiate any events. Upon
-// setting to NO, clears the target/action of the close button to prevent
-// clicks inside it from sending messages.
-@property(assign, nonatomic, getter=isClosing) BOOL closing;
-
-// Enables/Disables tracking regions for the tab.
-- (void)setTrackingEnabled:(BOOL)enabled;
-
-// Begin showing an "alert" glow (shown to call attention to an unselected
-// pinned tab whose title changed).
-- (void)startAlert;
-
-// Stop showing the "alert" glow; this won't immediately wipe out any glow, but
-// will make it fade away.
-- (void)cancelAlert;
-
-@end
-
-// The TabController |controller_| is not the only owner of this view. If the
-// controller is released before this view, then we could be hanging onto a
-// garbage pointer. To prevent this, the TabController uses this interface to
-// clear the |controller_| pointer when it is dying.
-@interface TabView (TabControllerInterface)
-- (void)setController:(TabController*)controller;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tab_view.mm b/chrome/browser/ui/cocoa/tab_view.mm
deleted file mode 100644
index 0a655ad..0000000
--- a/chrome/browser/ui/cocoa/tab_view.mm
+++ /dev/null
@@ -1,1056 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_view.h"
-
-#include "base/logging.h"
-#import "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "chrome/browser/accessibility/browser_accessibility_state.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#import "chrome/browser/ui/cocoa/tab_controller.h"
-#import "chrome/browser/ui/cocoa/tab_window_controller.h"
-#import "chrome/browser/ui/cocoa/themed_window.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// Constants for inset and control points for tab shape.
-const CGFloat kInsetMultiplier = 2.0/3.0;
-const CGFloat kControlPoint1Multiplier = 1.0/3.0;
-const CGFloat kControlPoint2Multiplier = 3.0/8.0;
-
-// The amount of time in seconds during which each type of glow increases, holds
-// steady, and decreases, respectively.
-const NSTimeInterval kHoverShowDuration = 0.2;
-const NSTimeInterval kHoverHoldDuration = 0.02;
-const NSTimeInterval kHoverHideDuration = 0.4;
-const NSTimeInterval kAlertShowDuration = 0.4;
-const NSTimeInterval kAlertHoldDuration = 0.4;
-const NSTimeInterval kAlertHideDuration = 0.4;
-
-// The default time interval in seconds between glow updates (when
-// increasing/decreasing).
-const NSTimeInterval kGlowUpdateInterval = 0.025;
-
-const CGFloat kTearDistance = 36.0;
-const NSTimeInterval kTearDuration = 0.333;
-
-// This is used to judge whether the mouse has moved during rapid closure; if it
-// has moved less than the threshold, we want to close the tab.
-const CGFloat kRapidCloseDist = 2.5;
-
-}  // namespace
-
-@interface TabView(Private)
-
-- (void)resetLastGlowUpdateTime;
-- (NSTimeInterval)timeElapsedSinceLastGlowUpdate;
-- (void)adjustGlowValue;
-// TODO(davidben): When we stop supporting 10.5, this can be removed.
-- (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache;
-- (NSBezierPath*)bezierPathForRect:(NSRect)rect;
-
-@end  // TabView(Private)
-
-@implementation TabView
-
-@synthesize state = state_;
-@synthesize hoverAlpha = hoverAlpha_;
-@synthesize alertAlpha = alertAlpha_;
-@synthesize closing = closing_;
-
-- (id)initWithFrame:(NSRect)frame {
-  self = [super initWithFrame:frame];
-  if (self) {
-    [self setShowsDivider:NO];
-    // TODO(alcor): register for theming
-  }
-  return self;
-}
-
-- (void)awakeFromNib {
-  [self setShowsDivider:NO];
-
-  // It is desirable for us to remove the close button from the cocoa hierarchy,
-  // so that VoiceOver does not encounter it.
-  // TODO(dtseng): crbug.com/59978.
-  // Retain in case we remove it from its superview.
-  closeButtonRetainer_.reset([closeButton_ retain]);
-  if (BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) {
-    // The superview gives up ownership of the closeButton here.
-    [closeButton_ removeFromSuperview];
-  }
-}
-
-- (void)dealloc {
-  // Cancel any delayed requests that may still be pending (drags or hover).
-  [NSObject cancelPreviousPerformRequestsWithTarget:self];
-  [super dealloc];
-}
-
-// Called to obtain the context menu for when the user hits the right mouse
-// button (or control-clicks). (Note that -rightMouseDown: is *not* called for
-// control-click.)
-- (NSMenu*)menu {
-  if ([self isClosing])
-    return nil;
-
-  // Sheets, being window-modal, should block contextual menus. For some reason
-  // they do not. Disallow them ourselves.
-  if ([[self window] attachedSheet])
-    return nil;
-
-  return [controller_ menu];
-}
-
-// Overridden so that mouse clicks come to this view (the parent of the
-// hierarchy) first. We want to handle clicks and drags in this class and
-// leave the background button for display purposes only.
-- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent {
-  return YES;
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent {
-  isMouseInside_ = YES;
-  [self resetLastGlowUpdateTime];
-  [self adjustGlowValue];
-}
-
-- (void)mouseMoved:(NSEvent*)theEvent {
-  hoverPoint_ = [self convertPoint:[theEvent locationInWindow]
-                          fromView:nil];
-  [self setNeedsDisplay:YES];
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
-  isMouseInside_ = NO;
-  hoverHoldEndTime_ =
-      [NSDate timeIntervalSinceReferenceDate] + kHoverHoldDuration;
-  [self resetLastGlowUpdateTime];
-  [self adjustGlowValue];
-}
-
-- (void)setTrackingEnabled:(BOOL)enabled {
-  [closeButton_ setTrackingEnabled:enabled];
-}
-
-// Determines which view a click in our frame actually hit. It's either this
-// view or our child close button.
-- (NSView*)hitTest:(NSPoint)aPoint {
-  NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]];
-  NSRect frame = [self frame];
-
-  // Reduce the width of the hit rect slightly to remove the overlap
-  // between adjacent tabs.  The drawing code in TabCell has the top
-  // corners of the tab inset by height*2/3, so we inset by half of
-  // that here.  This doesn't completely eliminate the overlap, but it
-  // works well enough.
-  NSRect hitRect = NSInsetRect(frame, frame.size.height / 3.0f, 0);
-  if (![closeButton_ isHidden])
-    if (NSPointInRect(viewPoint, [closeButton_ frame])) return closeButton_;
-  if (NSPointInRect(aPoint, hitRect)) return self;
-  return nil;
-}
-
-// Returns |YES| if this tab can be torn away into a new window.
-- (BOOL)canBeDragged {
-  if ([self isClosing])
-    return NO;
-  NSWindowController* controller = [sourceWindow_ windowController];
-  if ([controller isKindOfClass:[TabWindowController class]]) {
-    TabWindowController* realController =
-        static_cast<TabWindowController*>(controller);
-    return [realController isTabDraggable:self];
-  }
-  return YES;
-}
-
-// Returns an array of controllers that could be a drop target, ordered front to
-// back. It has to be of the appropriate class, and visible (obviously). Note
-// that the window cannot be a target for itself.
-- (NSArray*)dropTargetsForController:(TabWindowController*)dragController {
-  NSMutableArray* targets = [NSMutableArray array];
-  NSWindow* dragWindow = [dragController window];
-  for (NSWindow* window in [NSApp orderedWindows]) {
-    if (window == dragWindow) continue;
-    if (![window isVisible]) continue;
-    // Skip windows on the wrong space.
-    if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
-      if (![window performSelector:@selector(isOnActiveSpace)])
-        continue;
-    } else {
-      // TODO(davidben): When we stop supporting 10.5, this can be
-      // removed.
-      //
-      // We don't cache the workspace of |dragWindow| because it may
-      // move around spaces.
-      if ([self getWorkspaceID:dragWindow useCache:NO] !=
-          [self getWorkspaceID:window useCache:YES])
-        continue;
-    }
-    NSWindowController* controller = [window windowController];
-    if ([controller isKindOfClass:[TabWindowController class]]) {
-      TabWindowController* realController =
-          static_cast<TabWindowController*>(controller);
-      if ([realController canReceiveFrom:dragController])
-        [targets addObject:controller];
-    }
-  }
-  return targets;
-}
-
-// Call to clear out transient weak references we hold during drags.
-- (void)resetDragControllers {
-  draggedController_ = nil;
-  dragWindow_ = nil;
-  dragOverlay_ = nil;
-  sourceController_ = nil;
-  sourceWindow_ = nil;
-  targetController_ = nil;
-  workspaceIDCache_.clear();
-}
-
-// Sets whether the window background should be visible or invisible when
-// dragging a tab. The background should be invisible when the mouse is over a
-// potential drop target for the tab (the tab strip). It should be visible when
-// there's no drop target so the window looks more fully realized and ready to
-// become a stand-alone window.
-- (void)setWindowBackgroundVisibility:(BOOL)shouldBeVisible {
-  if (chromeIsVisible_ == shouldBeVisible)
-    return;
-
-  // There appears to be a race-condition in CoreAnimation where if we use
-  // animators to set the alpha values, we can't guarantee that we cancel them.
-  // This has the side effect of sometimes leaving the dragged window
-  // translucent or invisible. As a result, don't animate the alpha change.
-  [[draggedController_ overlayWindow] setAlphaValue:1.0];
-  if (targetController_) {
-    [dragWindow_ setAlphaValue:0.0];
-    [[draggedController_ overlayWindow] setHasShadow:YES];
-    [[targetController_ window] makeMainWindow];
-  } else {
-    [dragWindow_ setAlphaValue:0.5];
-    [[draggedController_ overlayWindow] setHasShadow:NO];
-    [[draggedController_ window] makeMainWindow];
-  }
-  chromeIsVisible_ = shouldBeVisible;
-}
-
-// Handle clicks and drags in this button. We get here because we have
-// overridden acceptsFirstMouse: and the click is within our bounds.
-- (void)mouseDown:(NSEvent*)theEvent {
-  if ([self isClosing])
-    return;
-
-  NSPoint downLocation = [theEvent locationInWindow];
-
-  // Record the state of the close button here, because selecting the tab will
-  // unhide it.
-  BOOL closeButtonActive = [closeButton_ isHidden] ? NO : YES;
-
-  // During the tab closure animation (in particular, during rapid tab closure),
-  // we may get incorrectly hit with a mouse down. If it should have gone to the
-  // close button, we send it there -- it should then track the mouse, so we
-  // don't have to worry about mouse ups.
-  if (closeButtonActive && [controller_ inRapidClosureMode]) {
-    NSPoint hitLocation = [[self superview] convertPoint:downLocation
-                                                fromView:nil];
-    if ([self hitTest:hitLocation] == closeButton_) {
-      [closeButton_ mouseDown:theEvent];
-      return;
-    }
-  }
-
-  // Fire the action to select the tab.
-  if ([[controller_ target] respondsToSelector:[controller_ action]])
-    [[controller_ target] performSelector:[controller_ action]
-                               withObject:self];
-
-  [self resetDragControllers];
-
-  // Resolve overlay back to original window.
-  sourceWindow_ = [self window];
-  if ([sourceWindow_ isKindOfClass:[NSPanel class]]) {
-    sourceWindow_ = [sourceWindow_ parentWindow];
-  }
-
-  sourceWindowFrame_ = [sourceWindow_ frame];
-  sourceTabFrame_ = [self frame];
-  sourceController_ = [sourceWindow_ windowController];
-  tabWasDragged_ = NO;
-  tearTime_ = 0.0;
-  draggingWithinTabStrip_ = YES;
-  chromeIsVisible_ = NO;
-
-  // If there's more than one potential window to be a drop target, we want to
-  // treat a drag of a tab just like dragging around a tab that's already
-  // detached. Note that unit tests might have |-numberOfTabs| reporting zero
-  // since the model won't be fully hooked up. We need to be prepared for that
-  // and not send them into the "magnetic" codepath.
-  NSArray* targets = [self dropTargetsForController:sourceController_];
-  moveWindowOnDrag_ =
-      ([sourceController_ numberOfTabs] < 2 && ![targets count]) ||
-      ![self canBeDragged] ||
-      ![sourceController_ tabDraggingAllowed];
-  // If we are dragging a tab, a window with a single tab should immediately
-  // snap off and not drag within the tab strip.
-  if (!moveWindowOnDrag_)
-    draggingWithinTabStrip_ = [sourceController_ numberOfTabs] > 1;
-
-  dragOrigin_ = [NSEvent mouseLocation];
-
-  // If the tab gets torn off, the tab controller will be removed from the tab
-  // strip and then deallocated. This will also result in *us* being
-  // deallocated. Both these are bad, so we prevent this by retaining the
-  // controller.
-  scoped_nsobject<TabController> controller([controller_ retain]);
-
-  // Because we move views between windows, we need to handle the event loop
-  // ourselves. Ideally we should use the standard event loop.
-  while (1) {
-    theEvent =
-        [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask
-                           untilDate:[NSDate distantFuture]
-                              inMode:NSDefaultRunLoopMode dequeue:YES];
-    NSEventType type = [theEvent type];
-    if (type == NSLeftMouseDragged) {
-      [self mouseDragged:theEvent];
-    } else if (type == NSLeftMouseUp) {
-      NSPoint upLocation = [theEvent locationInWindow];
-      CGFloat dx = upLocation.x - downLocation.x;
-      CGFloat dy = upLocation.y - downLocation.y;
-
-      // During rapid tab closure (mashing tab close buttons), we may get hit
-      // with a mouse down. As long as the mouse up is over the close button,
-      // and the mouse hasn't moved too much, we close the tab.
-      if (closeButtonActive &&
-          (dx*dx + dy*dy) <= kRapidCloseDist*kRapidCloseDist &&
-          [controller inRapidClosureMode]) {
-        NSPoint hitLocation =
-            [[self superview] convertPoint:[theEvent locationInWindow]
-                                  fromView:nil];
-        if ([self hitTest:hitLocation] == closeButton_) {
-          [controller closeTab:self];
-          break;
-        }
-      }
-
-      [self mouseUp:theEvent];
-      break;
-    } else {
-      // TODO(viettrungluu): [crbug.com/23830] We can receive right-mouse-ups
-      // (and maybe even others?) for reasons I don't understand. So we
-      // explicitly check for both events we're expecting, and log others. We
-      // should figure out what's going on.
-      LOG(WARNING) << "Spurious event received of type " << type << ".";
-    }
-  }
-}
-
-- (void)mouseDragged:(NSEvent*)theEvent {
-  // Special-case this to keep the logic below simpler.
-  if (moveWindowOnDrag_) {
-    if ([sourceController_ windowMovementAllowed]) {
-      NSPoint thisPoint = [NSEvent mouseLocation];
-      NSPoint origin = sourceWindowFrame_.origin;
-      origin.x += (thisPoint.x - dragOrigin_.x);
-      origin.y += (thisPoint.y - dragOrigin_.y);
-      [sourceWindow_ setFrameOrigin:NSMakePoint(origin.x, origin.y)];
-    }  // else do nothing.
-    return;
-  }
-
-  // First, go through the magnetic drag cycle. We break out of this if
-  // "stretchiness" ever exceeds a set amount.
-  tabWasDragged_ = YES;
-
-  if (draggingWithinTabStrip_) {
-    NSPoint thisPoint = [NSEvent mouseLocation];
-    CGFloat stretchiness = thisPoint.y - dragOrigin_.y;
-    stretchiness = copysign(sqrtf(fabs(stretchiness))/sqrtf(kTearDistance),
-                            stretchiness) / 2.0;
-    CGFloat offset = thisPoint.x - dragOrigin_.x;
-    if (fabsf(offset) > 100) stretchiness = 0;
-    [sourceController_ insertPlaceholderForTab:self
-                                         frame:NSOffsetRect(sourceTabFrame_,
-                                                            offset, 0)
-                                 yStretchiness:stretchiness];
-    // Check that we haven't pulled the tab too far to start a drag. This
-    // can include either pulling it too far down, or off the side of the tab
-    // strip that would cause it to no longer be fully visible.
-    BOOL stillVisible = [sourceController_ isTabFullyVisible:self];
-    CGFloat tearForce = fabs(thisPoint.y - dragOrigin_.y);
-    if ([sourceController_ tabTearingAllowed] &&
-        (tearForce > kTearDistance || !stillVisible)) {
-      draggingWithinTabStrip_ = NO;
-      // When you finally leave the strip, we treat that as the origin.
-      dragOrigin_.x = thisPoint.x;
-    } else {
-      // Still dragging within the tab strip, wait for the next drag event.
-      return;
-    }
-  }
-
-  // Do not start dragging until the user has "torn" the tab off by
-  // moving more than 3 pixels.
-  NSDate* targetDwellDate = nil;  // The date this target was first chosen.
-
-  NSPoint thisPoint = [NSEvent mouseLocation];
-
-  // Iterate over possible targets checking for the one the mouse is in.
-  // If the tab is just in the frame, bring the window forward to make it
-  // easier to drop something there. If it's in the tab strip, set the new
-  // target so that it pops into that window. We can't cache this because we
-  // need the z-order to be correct.
-  NSArray* targets = [self dropTargetsForController:draggedController_];
-  TabWindowController* newTarget = nil;
-  for (TabWindowController* target in targets) {
-    NSRect windowFrame = [[target window] frame];
-    if (NSPointInRect(thisPoint, windowFrame)) {
-      [[target window] orderFront:self];
-      NSRect tabStripFrame = [[target tabStripView] frame];
-      tabStripFrame.origin = [[target window]
-                              convertBaseToScreen:tabStripFrame.origin];
-      if (NSPointInRect(thisPoint, tabStripFrame)) {
-        newTarget = target;
-      }
-      break;
-    }
-  }
-
-  // If we're now targeting a new window, re-layout the tabs in the old
-  // target and reset how long we've been hovering over this new one.
-  if (targetController_ != newTarget) {
-    targetDwellDate = [NSDate date];
-    [targetController_ removePlaceholder];
-    targetController_ = newTarget;
-    if (!newTarget) {
-      tearTime_ = [NSDate timeIntervalSinceReferenceDate];
-      tearOrigin_ = [dragWindow_ frame].origin;
-    }
-  }
-
-  // Create or identify the dragged controller.
-  if (!draggedController_) {
-    // Get rid of any placeholder remaining in the original source window.
-    [sourceController_ removePlaceholder];
-
-    // Detach from the current window and put it in a new window. If there are
-    // no more tabs remaining after detaching, the source window is about to
-    // go away (it's been autoreleased) so we need to ensure we don't reference
-    // it any more. In that case the new controller becomes our source
-    // controller.
-    draggedController_ = [sourceController_ detachTabToNewWindow:self];
-    dragWindow_ = [draggedController_ window];
-    [dragWindow_ setAlphaValue:0.0];
-    if (![sourceController_ hasLiveTabs]) {
-      sourceController_ = draggedController_;
-      sourceWindow_ = dragWindow_;
-    }
-
-    // If dragging the tab only moves the current window, do not show overlay
-    // so that sheets stay on top of the window.
-    // Bring the target window to the front and make sure it has a border.
-    [dragWindow_ setLevel:NSFloatingWindowLevel];
-    [dragWindow_ setHasShadow:YES];
-    [dragWindow_ orderFront:nil];
-    [dragWindow_ makeMainWindow];
-    [draggedController_ showOverlay];
-    dragOverlay_ = [draggedController_ overlayWindow];
-    // Force the new tab button to be hidden. We'll reset it on mouse up.
-    [draggedController_ showNewTabButton:NO];
-    tearTime_ = [NSDate timeIntervalSinceReferenceDate];
-    tearOrigin_ = sourceWindowFrame_.origin;
-  }
-
-  // TODO(pinkerton): http://crbug.com/25682 demonstrates a way to get here by
-  // some weird circumstance that doesn't first go through mouseDown:. We
-  // really shouldn't go any farther.
-  if (!draggedController_ || !sourceController_)
-    return;
-
-  // When the user first tears off the window, we want slide the window to
-  // the current mouse location (to reduce the jarring appearance). We do this
-  // by calling ourselves back with additional mouseDragged calls (not actual
-  // events). |tearProgress| is a normalized measure of how far through this
-  // tear "animation" (of length kTearDuration) we are and has values [0..1].
-  // We use sqrt() so the animation is non-linear (slow down near the end
-  // point).
-  NSTimeInterval tearProgress =
-      [NSDate timeIntervalSinceReferenceDate] - tearTime_;
-  tearProgress /= kTearDuration;  // Normalize.
-  tearProgress = sqrtf(MAX(MIN(tearProgress, 1.0), 0.0));
-
-  // Move the dragged window to the right place on the screen.
-  NSPoint origin = sourceWindowFrame_.origin;
-  origin.x += (thisPoint.x - dragOrigin_.x);
-  origin.y += (thisPoint.y - dragOrigin_.y);
-
-  if (tearProgress < 1) {
-    // If the tear animation is not complete, call back to ourself with the
-    // same event to animate even if the mouse isn't moving. We need to make
-    // sure these get cancelled in mouseUp:.
-    [NSObject cancelPreviousPerformRequestsWithTarget:self];
-    [self performSelector:@selector(mouseDragged:)
-               withObject:theEvent
-               afterDelay:1.0f/30.0f];
-
-    // Set the current window origin based on how far we've progressed through
-    // the tear animation.
-    origin.x = (1 - tearProgress) * tearOrigin_.x + tearProgress * origin.x;
-    origin.y = (1 - tearProgress) * tearOrigin_.y + tearProgress * origin.y;
-  }
-
-  if (targetController_) {
-    // In order to "snap" two windows of different sizes together at their
-    // toolbar, we can't just use the origin of the target frame. We also have
-    // to take into consideration the difference in height.
-    NSRect targetFrame = [[targetController_ window] frame];
-    NSRect sourceFrame = [dragWindow_ frame];
-    origin.y = NSMinY(targetFrame) +
-                (NSHeight(targetFrame) - NSHeight(sourceFrame));
-  }
-  [dragWindow_ setFrameOrigin:NSMakePoint(origin.x, origin.y)];
-
-  // If we're not hovering over any window, make the window fully
-  // opaque. Otherwise, find where the tab might be dropped and insert
-  // a placeholder so it appears like it's part of that window.
-  if (targetController_) {
-    if (![[targetController_ window] isKeyWindow]) {
-      // && ([targetDwellDate timeIntervalSinceNow] < -REQUIRED_DWELL)) {
-      [[targetController_ window] orderFront:nil];
-      targetDwellDate = nil;
-    }
-
-    // Compute where placeholder should go and insert it into the
-    // destination tab strip.
-    TabView* draggedTabView = (TabView*)[draggedController_ selectedTabView];
-    NSRect tabFrame = [draggedTabView frame];
-    tabFrame.origin = [dragWindow_ convertBaseToScreen:tabFrame.origin];
-    tabFrame.origin = [[targetController_ window]
-                        convertScreenToBase:tabFrame.origin];
-    tabFrame = [[targetController_ tabStripView]
-                convertRect:tabFrame fromView:nil];
-    [targetController_ insertPlaceholderForTab:self
-                                         frame:tabFrame
-                                 yStretchiness:0];
-    [targetController_ layoutTabs];
-  } else {
-    [dragWindow_ makeKeyAndOrderFront:nil];
-  }
-
-  // Adjust the visibility of the window background. If there is a drop target,
-  // we want to hide the window background so the tab stands out for
-  // positioning. If not, we want to show it so it looks like a new window will
-  // be realized.
-  BOOL chromeShouldBeVisible = targetController_ == nil;
-  [self setWindowBackgroundVisibility:chromeShouldBeVisible];
-}
-
-- (void)mouseUp:(NSEvent*)theEvent {
-  // The drag/click is done. If the user dragged the mouse, finalize the drag
-  // and clean up.
-
-  // Special-case this to keep the logic below simpler.
-  if (moveWindowOnDrag_)
-    return;
-
-  // Cancel any delayed -mouseDragged: requests that may still be pending.
-  [NSObject cancelPreviousPerformRequestsWithTarget:self];
-
-  // TODO(pinkerton): http://crbug.com/25682 demonstrates a way to get here by
-  // some weird circumstance that doesn't first go through mouseDown:. We
-  // really shouldn't go any farther.
-  if (!sourceController_)
-    return;
-
-  // We are now free to re-display the new tab button in the window we're
-  // dragging. It will show when the next call to -layoutTabs (which happens
-  // indrectly by several of the calls below, such as removing the placeholder).
-  [draggedController_ showNewTabButton:YES];
-
-  if (draggingWithinTabStrip_) {
-    if (tabWasDragged_) {
-      // Move tab to new location.
-      DCHECK([sourceController_ numberOfTabs]);
-      TabWindowController* dropController = sourceController_;
-      [dropController moveTabView:[dropController selectedTabView]
-                   fromController:nil];
-    }
-  } else if (targetController_) {
-    // Move between windows. If |targetController_| is nil, we're not dropping
-    // into any existing window.
-    NSView* draggedTabView = [draggedController_ selectedTabView];
-    [targetController_ moveTabView:draggedTabView
-                    fromController:draggedController_];
-    // Force redraw to avoid flashes of old content before returning to event
-    // loop.
-    [[targetController_ window] display];
-    [targetController_ showWindow:nil];
-    [draggedController_ removeOverlay];
-  } else {
-    // Only move the window around on screen. Make sure it's set back to
-    // normal state (fully opaque, has shadow, has key, etc).
-    [draggedController_ removeOverlay];
-    // Don't want to re-show the window if it was closed during the drag.
-    if ([dragWindow_ isVisible]) {
-      [dragWindow_ setAlphaValue:1.0];
-      [dragOverlay_ setHasShadow:NO];
-      [dragWindow_ setHasShadow:YES];
-      [dragWindow_ makeKeyAndOrderFront:nil];
-    }
-    [[draggedController_ window] setLevel:NSNormalWindowLevel];
-    [draggedController_ removePlaceholder];
-  }
-  [sourceController_ removePlaceholder];
-  chromeIsVisible_ = YES;
-
-  [self resetDragControllers];
-}
-
-- (void)otherMouseUp:(NSEvent*)theEvent {
-  if ([self isClosing])
-    return;
-
-  // Support middle-click-to-close.
-  if ([theEvent buttonNumber] == 2) {
-    // |-hitTest:| takes a location in the superview's coordinates.
-    NSPoint upLocation =
-        [[self superview] convertPoint:[theEvent locationInWindow]
-                              fromView:nil];
-    // If the mouse up occurred in our view or over the close button, then
-    // close.
-    if ([self hitTest:upLocation])
-      [controller_ closeTab:self];
-  }
-}
-
-- (void)drawRect:(NSRect)dirtyRect {
-  NSGraphicsContext* context = [NSGraphicsContext currentContext];
-  [context saveGraphicsState];
-
-  BrowserThemeProvider* themeProvider =
-      static_cast<BrowserThemeProvider*>([[self window] themeProvider]);
-  [context setPatternPhase:[[self window] themePatternPhase]];
-
-  NSRect rect = [self bounds];
-  NSBezierPath* path = [self bezierPathForRect:rect];
-
-  BOOL selected = [self state];
-  // Don't draw the window/tab bar background when selected, since the tab
-  // background overlay drawn over it (see below) will be fully opaque.
-  BOOL hasBackgroundImage = NO;
-  if (!selected) {
-    // ThemeProvider::HasCustomImage is true only if the theme provides the
-    // image. However, even if the theme doesn't provide a tab background, the
-    // theme machinery will make one if given a frame image. See
-    // BrowserThemePack::GenerateTabBackgroundImages for details.
-    hasBackgroundImage = themeProvider &&
-        (themeProvider->HasCustomImage(IDR_THEME_TAB_BACKGROUND) ||
-         themeProvider->HasCustomImage(IDR_THEME_FRAME));
-
-    NSColor* backgroundImageColor = hasBackgroundImage ?
-        themeProvider->GetNSImageColorNamed(IDR_THEME_TAB_BACKGROUND, true) :
-        nil;
-
-    if (backgroundImageColor) {
-      [backgroundImageColor set];
-      [path fill];
-    } else {
-      // Use the window's background color rather than |[NSColor
-      // windowBackgroundColor]|, which gets confused by the fullscreen window.
-      // (The result is the same for normal, non-fullscreen windows.)
-      [[[self window] backgroundColor] set];
-      [path fill];
-      [[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set];
-      [path fill];
-    }
-  }
-
-  [context saveGraphicsState];
-  [path addClip];
-
-  // Use the same overlay for the selected state and for hover and alert glows;
-  // for the selected state, it's fully opaque.
-  CGFloat hoverAlpha = [self hoverAlpha];
-  CGFloat alertAlpha = [self alertAlpha];
-  if (selected || hoverAlpha > 0 || alertAlpha > 0) {
-    // Draw the selected background / glow overlay.
-    [context saveGraphicsState];
-    CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
-    CGContextBeginTransparencyLayer(cgContext, 0);
-    if (!selected) {
-      // The alert glow overlay is like the selected state but at most at most
-      // 80% opaque. The hover glow brings up the overlay's opacity at most 50%.
-      CGFloat backgroundAlpha = 0.8 * alertAlpha;
-      backgroundAlpha += (1 - backgroundAlpha) * 0.5 * hoverAlpha;
-      CGContextSetAlpha(cgContext, backgroundAlpha);
-    }
-    [path addClip];
-    [context saveGraphicsState];
-    [super drawBackground];
-    [context restoreGraphicsState];
-
-    // Draw a mouse hover gradient for the default themes.
-    if (!selected && hoverAlpha > 0) {
-      if (themeProvider && !hasBackgroundImage) {
-        scoped_nsobject<NSGradient> glow([NSGradient alloc]);
-        [glow initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0
-                                        alpha:1.0 * hoverAlpha]
-                        endingColor:[NSColor colorWithCalibratedWhite:1.0
-                                                                alpha:0.0]];
-
-        NSPoint point = hoverPoint_;
-        point.y = NSHeight(rect);
-        [glow drawFromCenter:point
-                      radius:0.0
-                    toCenter:point
-                      radius:NSWidth(rect) / 3.0
-                     options:NSGradientDrawsBeforeStartingLocation];
-
-        [glow drawInBezierPath:path relativeCenterPosition:hoverPoint_];
-      }
-    }
-
-    CGContextEndTransparencyLayer(cgContext);
-    [context restoreGraphicsState];
-  }
-
-  BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow];
-  CGFloat borderAlpha = selected ? (active ? 0.3 : 0.2) : 0.2;
-  NSColor* borderColor = [NSColor colorWithDeviceWhite:0.0 alpha:borderAlpha];
-  NSColor* highlightColor = themeProvider ? themeProvider->GetNSColor(
-      themeProvider->UsingDefaultTheme() ?
-          BrowserThemeProvider::COLOR_TOOLBAR_BEZEL :
-          BrowserThemeProvider::COLOR_TOOLBAR, true) : nil;
-
-  // Draw the top inner highlight within the currently selected tab if using
-  // the default theme.
-  if (selected && themeProvider && themeProvider->UsingDefaultTheme()) {
-    NSAffineTransform* highlightTransform = [NSAffineTransform transform];
-    [highlightTransform translateXBy:1.0 yBy:-1.0];
-    scoped_nsobject<NSBezierPath> highlightPath([path copy]);
-    [highlightPath transformUsingAffineTransform:highlightTransform];
-    [highlightColor setStroke];
-    [highlightPath setLineWidth:1.0];
-    [highlightPath stroke];
-    highlightTransform = [NSAffineTransform transform];
-    [highlightTransform translateXBy:-2.0 yBy:0.0];
-    [highlightPath transformUsingAffineTransform:highlightTransform];
-    [highlightPath stroke];
-  }
-
-  [context restoreGraphicsState];
-
-  // Draw the top stroke.
-  [context saveGraphicsState];
-  [borderColor set];
-  [path setLineWidth:1.0];
-  [path stroke];
-  [context restoreGraphicsState];
-
-  // Mimic the tab strip's bottom border, which consists of a dark border
-  // and light highlight.
-  if (!selected) {
-    [path addClip];
-    NSRect borderRect = rect;
-    borderRect.origin.y = 1;
-    borderRect.size.height = 1;
-    [borderColor set];
-    NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
-
-    borderRect.origin.y = 0;
-    [highlightColor set];
-    NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
-  }
-
-  [context restoreGraphicsState];
-}
-
-- (void)viewDidMoveToWindow {
-  [super viewDidMoveToWindow];
-  if ([self window]) {
-    [controller_ updateTitleColor];
-  }
-}
-
-- (void)setClosing:(BOOL)closing {
-  closing_ = closing;  // Safe because the property is nonatomic.
-  // When closing, ensure clicks to the close button go nowhere.
-  if (closing) {
-    [closeButton_ setTarget:nil];
-    [closeButton_ setAction:nil];
-  }
-}
-
-- (void)startAlert {
-  // Do not start a new alert while already alerting or while in a decay cycle.
-  if (alertState_ == tabs::kAlertNone) {
-    alertState_ = tabs::kAlertRising;
-    [self resetLastGlowUpdateTime];
-    [self adjustGlowValue];
-  }
-}
-
-- (void)cancelAlert {
-  if (alertState_ != tabs::kAlertNone) {
-    alertState_ = tabs::kAlertFalling;
-    alertHoldEndTime_ =
-        [NSDate timeIntervalSinceReferenceDate] + kGlowUpdateInterval;
-    [self resetLastGlowUpdateTime];
-    [self adjustGlowValue];
-  }
-}
-
-- (BOOL)accessibilityIsIgnored {
-  return NO;
-}
-
-- (NSArray*)accessibilityActionNames {
-  NSArray* parentActions = [super accessibilityActionNames];
-
-  return [parentActions arrayByAddingObject:NSAccessibilityPressAction];
-}
-
-- (NSArray*)accessibilityAttributeNames {
-  NSMutableArray* attributes =
-      [[super accessibilityAttributeNames] mutableCopy];
-  [attributes addObject:NSAccessibilityTitleAttribute];
-  [attributes addObject:NSAccessibilityEnabledAttribute];
-
-  return attributes;
-}
-
-- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
-  if ([attribute isEqual:NSAccessibilityTitleAttribute])
-    return NO;
-
-  if ([attribute isEqual:NSAccessibilityEnabledAttribute])
-    return NO;
-
-  return [super accessibilityIsAttributeSettable:attribute];
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attribute {
-  if ([attribute isEqual:NSAccessibilityRoleAttribute])
-    return NSAccessibilityButtonRole;
-
-  if ([attribute isEqual:NSAccessibilityTitleAttribute])
-    return [controller_ title];
-
-  if ([attribute isEqual:NSAccessibilityEnabledAttribute])
-    return [NSNumber numberWithBool:YES];
-
-  if ([attribute isEqual:NSAccessibilityChildrenAttribute]) {
-    // The subviews (icon and text) are clutter; filter out everything but
-    // useful controls.
-    NSArray* children = [super accessibilityAttributeValue:attribute];
-    NSMutableArray* okChildren = [NSMutableArray array];
-    for (id child in children) {
-      if ([child isKindOfClass:[NSButtonCell class]])
-        [okChildren addObject:child];
-    }
-
-    return okChildren;
-  }
-
-  return [super accessibilityAttributeValue:attribute];
-}
-
-- (ViewID)viewID {
-  return VIEW_ID_TAB;
-}
-
-@end  // @implementation TabView
-
-@implementation TabView (TabControllerInterface)
-
-- (void)setController:(TabController*)controller {
-  controller_ = controller;
-}
-
-@end  // @implementation TabView (TabControllerInterface)
-
-@implementation TabView(Private)
-
-- (void)resetLastGlowUpdateTime {
-  lastGlowUpdate_ = [NSDate timeIntervalSinceReferenceDate];
-}
-
-- (NSTimeInterval)timeElapsedSinceLastGlowUpdate {
-  return [NSDate timeIntervalSinceReferenceDate] - lastGlowUpdate_;
-}
-
-- (void)adjustGlowValue {
-  // A time interval long enough to represent no update.
-  const NSTimeInterval kNoUpdate = 1000000;
-
-  // Time until next update for either glow.
-  NSTimeInterval nextUpdate = kNoUpdate;
-
-  NSTimeInterval elapsed = [self timeElapsedSinceLastGlowUpdate];
-  NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
-
-  // TODO(viettrungluu): <http://crbug.com/30617> -- split off the stuff below
-  // into a pure function and add a unit test.
-
-  CGFloat hoverAlpha = [self hoverAlpha];
-  if (isMouseInside_) {
-    // Increase hover glow until it's 1.
-    if (hoverAlpha < 1) {
-      hoverAlpha = MIN(hoverAlpha + elapsed / kHoverShowDuration, 1);
-      [self setHoverAlpha:hoverAlpha];
-      nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-    }  // Else already 1 (no update needed).
-  } else {
-    if (currentTime >= hoverHoldEndTime_) {
-      // No longer holding, so decrease hover glow until it's 0.
-      if (hoverAlpha > 0) {
-        hoverAlpha = MAX(hoverAlpha - elapsed / kHoverHideDuration, 0);
-        [self setHoverAlpha:hoverAlpha];
-        nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-      }  // Else already 0 (no update needed).
-    } else {
-      // Schedule update for end of hold time.
-      nextUpdate = MIN(hoverHoldEndTime_ - currentTime, nextUpdate);
-    }
-  }
-
-  CGFloat alertAlpha = [self alertAlpha];
-  if (alertState_ == tabs::kAlertRising) {
-    // Increase alert glow until it's 1 ...
-    alertAlpha = MIN(alertAlpha + elapsed / kAlertShowDuration, 1);
-    [self setAlertAlpha:alertAlpha];
-
-    // ... and having reached 1, switch to holding.
-    if (alertAlpha >= 1) {
-      alertState_ = tabs::kAlertHolding;
-      alertHoldEndTime_ = currentTime + kAlertHoldDuration;
-      nextUpdate = MIN(kAlertHoldDuration, nextUpdate);
-    } else {
-      nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-    }
-  } else if (alertState_ != tabs::kAlertNone) {
-    if (alertAlpha > 0) {
-      if (currentTime >= alertHoldEndTime_) {
-        // Stop holding, then decrease alert glow (until it's 0).
-        if (alertState_ == tabs::kAlertHolding) {
-          alertState_ = tabs::kAlertFalling;
-          nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-        } else {
-          DCHECK_EQ(tabs::kAlertFalling, alertState_);
-          alertAlpha = MAX(alertAlpha - elapsed / kAlertHideDuration, 0);
-          [self setAlertAlpha:alertAlpha];
-          nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-        }
-      } else {
-        // Schedule update for end of hold time.
-        nextUpdate = MIN(alertHoldEndTime_ - currentTime, nextUpdate);
-      }
-    } else {
-      // Done the alert decay cycle.
-      alertState_ = tabs::kAlertNone;
-    }
-  }
-
-  if (nextUpdate < kNoUpdate)
-    [self performSelector:_cmd withObject:nil afterDelay:nextUpdate];
-
-  [self resetLastGlowUpdateTime];
-  [self setNeedsDisplay:YES];
-}
-
-// Returns the workspace id of |window|. If |useCache|, then lookup
-// and remember the value in |workspaceIDCache_| until the end of the
-// current drag.
-- (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache {
-  CGWindowID windowID = [window windowNumber];
-  if (useCache) {
-    std::map<CGWindowID, int>::iterator iter =
-        workspaceIDCache_.find(windowID);
-    if (iter != workspaceIDCache_.end())
-      return iter->second;
-  }
-
-  int workspace = -1;
-  // It's possible to query in bulk, but probably not necessary.
-  base::mac::ScopedCFTypeRef<CFArrayRef> windowIDs(CFArrayCreate(
-      NULL, reinterpret_cast<const void **>(&windowID), 1, NULL));
-  base::mac::ScopedCFTypeRef<CFArrayRef> descriptions(
-      CGWindowListCreateDescriptionFromArray(windowIDs));
-  DCHECK(CFArrayGetCount(descriptions.get()) <= 1);
-  if (CFArrayGetCount(descriptions.get()) > 0) {
-    CFDictionaryRef dict = static_cast<CFDictionaryRef>(
-        CFArrayGetValueAtIndex(descriptions.get(), 0));
-    DCHECK(CFGetTypeID(dict) == CFDictionaryGetTypeID());
-
-    // Sanity check the ID.
-    CFNumberRef otherIDRef = (CFNumberRef)base::mac::GetValueFromDictionary(
-        dict, kCGWindowNumber, CFNumberGetTypeID());
-    CGWindowID otherID;
-    if (otherIDRef &&
-        CFNumberGetValue(otherIDRef, kCGWindowIDCFNumberType, &otherID) &&
-        otherID == windowID) {
-      // And then get the workspace.
-      CFNumberRef workspaceRef = (CFNumberRef)base::mac::GetValueFromDictionary(
-          dict, kCGWindowWorkspace, CFNumberGetTypeID());
-      if (!workspaceRef ||
-          !CFNumberGetValue(workspaceRef, kCFNumberIntType, &workspace)) {
-        workspace = -1;
-      }
-    } else {
-      NOTREACHED();
-    }
-  }
-  if (useCache) {
-    workspaceIDCache_[windowID] = workspace;
-  }
-  return workspace;
-}
-
-// Returns the bezier path used to draw the tab given the bounds to draw it in.
-- (NSBezierPath*)bezierPathForRect:(NSRect)rect {
-  // Outset by 0.5 in order to draw on pixels rather than on borders (which
-  // would cause blurry pixels). Subtract 1px of height to compensate, otherwise
-  // clipping will occur.
-  rect = NSInsetRect(rect, -0.5, -0.5);
-  rect.size.height -= 1.0;
-
-  NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect) + 2);
-  NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect) + 2);
-  NSPoint topRight =
-      NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect),
-                  NSMaxY(rect));
-  NSPoint topLeft =
-      NSMakePoint(NSMinX(rect)  + kInsetMultiplier * NSHeight(rect),
-                  NSMaxY(rect));
-
-  CGFloat baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier;
-  CGFloat bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier;
-
-  // Outset many of these values by 1 to cause the fill to bleed outside the
-  // clip area.
-  NSBezierPath* path = [NSBezierPath bezierPath];
-  [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y - 2)];
-  [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)];
-  [path lineToPoint:bottomLeft];
-  [path curveToPoint:topLeft
-       controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset,
-                                 bottomLeft.y)
-       controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset,
-                                 topLeft.y)];
-  [path lineToPoint:topRight];
-  [path curveToPoint:bottomRight
-       controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset,
-                                 topRight.y)
-       controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset,
-                                 bottomRight.y)];
-  [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)];
-  [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y - 2)];
-  return path;
-}
-
-@end  // @implementation TabView(Private)
diff --git a/chrome/browser/ui/cocoa/tab_view_picker_table.h b/chrome/browser/ui/cocoa/tab_view_picker_table.h
index b6b80b0..5de51f4 100644
--- a/chrome/browser/ui/cocoa/tab_view_picker_table.h
+++ b/chrome/browser/ui/cocoa/tab_view_picker_table.h
@@ -25,5 +25,5 @@
   // Shown above all the tab names. May be |nil|.
   scoped_nsobject<NSString> heading_;
 }
-@property (nonatomic, copy) NSString* heading;
+@property(nonatomic, copy) NSString* heading;
 @end
diff --git a/chrome/browser/ui/cocoa/tab_view_unittest.mm b/chrome/browser/ui/cocoa/tab_view_unittest.mm
deleted file mode 100644
index 961c3a6..0000000
--- a/chrome/browser/ui/cocoa/tab_view_unittest.mm
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/tab_view.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class TabViewTest : public CocoaTest {
- public:
-  TabViewTest() {
-    NSRect frame = NSMakeRect(0, 0, 50, 30);
-    scoped_nsobject<TabView> view([[TabView alloc] initWithFrame:frame]);
-    view_ = view.get();
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  TabView* view_;
-};
-
-TEST_VIEW(TabViewTest, view_)
-
-// Test drawing, mostly to ensure nothing leaks or crashes.
-TEST_F(TabViewTest, Display) {
-  for (int i = 0; i < 5; i++) {
-    for (int j = 0; j < 5; j++) {
-      [view_ setHoverAlpha:i*0.2];
-      [view_ setAlertAlpha:j*0.2];
-      [view_ display];
-    }
-  }
-}
-
-// Test it doesn't crash when asked for its menu with no TabController set.
-TEST_F(TabViewTest, Menu) {
-  EXPECT_FALSE([view_ menu]);
-}
-
-TEST_F(TabViewTest, Glow) {
-  // TODO(viettrungluu): Figure out how to test this, which is timing-sensitive
-  // and which moreover uses |-performSelector:withObject:afterDelay:|.
-
-  // Call |-startAlert|/|-cancelAlert| and make sure it doesn't crash.
-  for (int i = 0; i < 5; i++) {
-    [view_ startAlert];
-    [view_ cancelAlert];
-  }
-  [view_ startAlert];
-  [view_ startAlert];
-  [view_ cancelAlert];
-  [view_ cancelAlert];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/tab_window_controller.h b/chrome/browser/ui/cocoa/tab_window_controller.h
deleted file mode 100644
index ea3527c..0000000
--- a/chrome/browser/ui/cocoa/tab_window_controller.h
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TAB_WINDOW_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TAB_WINDOW_CONTROLLER_H_
-#pragma once
-
-// A class acting as the Objective-C window controller for a window that has
-// tabs which can be dragged around. Tabs can be re-arranged within the same
-// window or dragged into other TabWindowController windows. This class doesn't
-// know anything about the actual tab implementation or model, as that is fairly
-// application-specific. It only provides an API to be overridden by subclasses
-// to fill in the details.
-//
-// This assumes that there will be a view in the nib, connected to
-// |tabContentArea_|, that indicates the content that it switched when switching
-// between tabs. It needs to be a regular NSView, not something like an NSBox
-// because the TabStripController makes certain assumptions about how it can
-// swap out subviews.
-//
-// The tab strip can exist in different orientations and window locations,
-// depending on the return value of -usesVerticalTabs. If NO (the default),
-// the tab strip is placed outside the window's content area, overlapping the
-// title area and window controls and will be stretched to fill the width
-// of the window. If YES, the tab strip is vertical and lives within the
-// window's content area. It will be stretched to fill the window's height.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_nsobject.h"
-
-@class FastResizeView;
-@class FocusTracker;
-@class TabStripView;
-@class TabView;
-
-@interface TabWindowController : NSWindowController<NSWindowDelegate> {
- @private
-  IBOutlet FastResizeView* tabContentArea_;
-  // TODO(pinkerton): Figure out a better way to initialize one or the other
-  // w/out needing both to be in the nib.
-  IBOutlet TabStripView* topTabStripView_;
-  IBOutlet TabStripView* sideTabStripView_;
-  NSWindow* overlayWindow_;  // Used during dragging for window opacity tricks
-  NSView* cachedContentView_;  // Used during dragging for identifying which
-                               // view is the proper content area in the overlay
-                               // (weak)
-  scoped_nsobject<FocusTracker> focusBeforeOverlay_;
-  scoped_nsobject<NSMutableSet> lockedTabs_;
-  BOOL closeDeferred_;  // If YES, call performClose: in removeOverlay:.
-  // Difference between height of window content area and height of the
-  // |tabContentArea_|. Calculated when the window is loaded from the nib and
-  // cached in order to restore the delta when switching tab modes.
-  CGFloat contentAreaHeightDelta_;
-}
-@property(readonly, nonatomic) TabStripView* tabStripView;
-@property(readonly, nonatomic) FastResizeView* tabContentArea;
-
-// Used during tab dragging to turn on/off the overlay window when a tab
-// is torn off. If -deferPerformClose (below) is used, -removeOverlay will
-// cause the controller to be autoreleased before returning.
-- (void)showOverlay;
-- (void)removeOverlay;
-- (NSWindow*)overlayWindow;
-
-// Returns YES if it is ok to constrain the window's frame to fit the screen.
-- (BOOL)shouldConstrainFrameRect;
-
-// A collection of methods, stubbed out in this base class, that provide
-// the implementation of tab dragging based on whatever model is most
-// appropriate.
-
-// Layout the tabs based on the current ordering of the model.
-- (void)layoutTabs;
-
-// Creates a new window by pulling the given tab out and placing it in
-// the new window. Returns the controller for the new window. The size of the
-// new window will be the same size as this window.
-- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView;
-
-// Make room in the tab strip for |tab| at the given x coordinate. Will hide the
-// new tab button while there's a placeholder. Subclasses need to call the
-// superclass implementation.
-- (void)insertPlaceholderForTab:(TabView*)tab
-                          frame:(NSRect)frame
-                  yStretchiness:(CGFloat)yStretchiness;
-
-// Removes the placeholder installed by |-insertPlaceholderForTab:atLocation:|
-// and restores the new tab button. Subclasses need to call the superclass
-// implementation.
-- (void)removePlaceholder;
-
-// Returns whether one of the window's tabs is being dragged.
-- (BOOL)isDragSessionActive;
-
-// The follow return YES if tab dragging/tab tearing (off the tab strip)/window
-// movement is currently allowed. Any number of things can choose to disable it,
-// such as pending animations. The default implementations always return YES.
-// Subclasses should override as appropriate.
-- (BOOL)tabDraggingAllowed;
-- (BOOL)tabTearingAllowed;
-- (BOOL)windowMovementAllowed;
-
-// Show or hide the new tab button. The button is hidden immediately, but
-// waits until the next call to |-layoutTabs| to show it again.
-- (void)showNewTabButton:(BOOL)show;
-
-// Returns whether or not |tab| can still be fully seen in the tab strip or if
-// its current position would cause it be obscured by things such as the edge
-// of the window or the window decorations. Returns YES only if the entire tab
-// is visible. The default implementation always returns YES.
-- (BOOL)isTabFullyVisible:(TabView*)tab;
-
-// Called to check if the receiver can receive dragged tabs from
-// source.  Return YES if so.  The default implementation returns NO.
-- (BOOL)canReceiveFrom:(TabWindowController*)source;
-
-// Move a given tab view to the location of the current placeholder. If there is
-// no placeholder, it will go at the end. |controller| is the window controller
-// of a tab being dropped from a different window. It will be nil if the drag is
-// within the window, otherwise the tab is removed from that window before being
-// placed into this one. The implementation will call |-removePlaceholder| since
-// the drag is now complete.  This also calls |-layoutTabs| internally so
-// clients do not need to call it again.
-- (void)moveTabView:(NSView*)view
-     fromController:(TabWindowController*)controller;
-
-// Number of tabs in the tab strip. Useful, for example, to know if we're
-// dragging the only tab in the window. This includes pinned tabs (both live
-// and not).
-- (NSInteger)numberOfTabs;
-
-// YES if there are tabs in the tab strip which have content, allowing for
-// the notion of tabs in the tab strip that are placeholders but currently have
-// no content.
-- (BOOL)hasLiveTabs;
-
-// Return the view of the selected tab.
-- (NSView *)selectedTabView;
-
-// The title of the selected tab.
-- (NSString*)selectedTabTitle;
-
-// Called to check whether or not this controller's window has a tab strip (YES
-// if it does, NO otherwise). The default implementation returns YES.
-- (BOOL)hasTabStrip;
-
-// Returns YES if the tab strip lives in the window content area alongside the
-// tab contents. Returns NO if the tab strip is outside the window content
-// area, along the top of the window.
-- (BOOL)useVerticalTabs;
-
-// Get/set whether a particular tab is draggable between windows.
-- (BOOL)isTabDraggable:(NSView*)tabView;
-- (void)setTab:(NSView*)tabView isDraggable:(BOOL)draggable;
-
-// Tell the window that it needs to call performClose: as soon as the current
-// drag is complete. This prevents a window (and its overlay) from going away
-// during a drag.
-- (void)deferPerformClose;
-
-@end
-
-@interface TabWindowController(ProtectedMethods)
-// Tells the tab strip to forget about this tab in preparation for it being
-// put into a different tab strip, such as during a drop on another window.
-- (void)detachTabView:(NSView*)view;
-
-// Toggles from one display mode of the tab strip to another. Will automatically
-// call -layoutSubviews to reposition other content.
-- (void)toggleTabStripDisplayMode;
-
-// Called when the size of the window content area has changed. Override to
-// position specific views. Base class implementation does nothing.
-- (void)layoutSubviews;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TAB_WINDOW_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_window_controller.mm b/chrome/browser/ui/cocoa/tab_window_controller.mm
deleted file mode 100644
index c3de82f..0000000
--- a/chrome/browser/ui/cocoa/tab_window_controller.mm
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/tab_window_controller.h"
-
-#include "app/theme_provider.h"
-#include "base/logging.h"
-#import "chrome/browser/ui/cocoa/focus_tracker.h"
-#import "chrome/browser/ui/cocoa/tab_strip_view.h"
-#import "chrome/browser/ui/cocoa/themed_window.h"
-
-@interface TabWindowController(PRIVATE)
-- (void)setUseOverlay:(BOOL)useOverlay;
-@end
-
-@interface TabWindowOverlayWindow : NSWindow
-@end
-
-@implementation TabWindowOverlayWindow
-
-- (ThemeProvider*)themeProvider {
-  if ([self parentWindow])
-    return [[[self parentWindow] windowController] themeProvider];
-  return NULL;
-}
-
-- (ThemedWindowStyle)themedWindowStyle {
-  if ([self parentWindow])
-    return [[[self parentWindow] windowController] themedWindowStyle];
-  return NO;
-}
-
-- (NSPoint)themePatternPhase {
-  if ([self parentWindow])
-    return [[[self parentWindow] windowController] themePatternPhase];
-  return NSZeroPoint;
-}
-
-@end
-
-@implementation TabWindowController
-@synthesize tabContentArea = tabContentArea_;
-
-- (id)initWithWindow:(NSWindow*)window {
-  if ((self = [super initWithWindow:window]) != nil) {
-    lockedTabs_.reset([[NSMutableSet alloc] initWithCapacity:10]);
-  }
-  return self;
-}
-
-// Add the side tab strip to the left side of the window's content area,
-// making it fill the full height of the content area.
-- (void)addSideTabStripToWindow {
-  NSView* contentView = [[self window] contentView];
-  NSRect contentFrame = [contentView frame];
-  NSRect sideStripFrame =
-      NSMakeRect(0, 0,
-                 NSWidth([sideTabStripView_ frame]),
-                 NSHeight(contentFrame));
-  [sideTabStripView_ setFrame:sideStripFrame];
-  [contentView addSubview:sideTabStripView_];
-}
-
-// Add the top tab strop to the window, above the content box and add it to the
-// view hierarchy as a sibling of the content view so it can overlap with the
-// window frame.
-- (void)addTopTabStripToWindow {
-  NSRect contentFrame = [tabContentArea_ frame];
-  NSRect tabFrame =
-      NSMakeRect(0, NSMaxY(contentFrame),
-                 NSWidth(contentFrame),
-                 NSHeight([topTabStripView_ frame]));
-  [topTabStripView_ setFrame:tabFrame];
-  NSView* contentParent = [[[self window] contentView] superview];
-  [contentParent addSubview:topTabStripView_];
-}
-
-- (void)windowDidLoad {
-  // Cache the difference in height between the window content area and the
-  // tab content area.
-  NSRect tabFrame = [tabContentArea_ frame];
-  NSRect contentFrame = [[[self window] contentView] frame];
-  contentAreaHeightDelta_ = NSHeight(contentFrame) - NSHeight(tabFrame);
-
-  if ([self hasTabStrip]) {
-    if ([self useVerticalTabs]) {
-      // No top tabstrip so remove the tabContentArea offset.
-      tabFrame.size.height = contentFrame.size.height;
-      [tabContentArea_ setFrame:tabFrame];
-      [self addSideTabStripToWindow];
-    } else {
-      [self addTopTabStripToWindow];
-    }
-  } else {
-    // No top tabstrip so remove the tabContentArea offset.
-    tabFrame.size.height = contentFrame.size.height;
-    [tabContentArea_ setFrame:tabFrame];
-  }
-}
-
-// Toggles from one display mode of the tab strip to another. Will automatically
-// call -layoutSubviews to reposition other content.
-- (void)toggleTabStripDisplayMode {
-  // Adjust the size of the tab contents to either use more or less space,
-  // depending on the direction of the toggle. This needs to be done prior to
-  // adding back in the top tab strip as its position is based off the MaxY
-  // of the tab content area.
-  BOOL useVertical = [self useVerticalTabs];
-  NSRect tabContentsFrame = [tabContentArea_ frame];
-  tabContentsFrame.size.height += useVertical ?
-      contentAreaHeightDelta_ : -contentAreaHeightDelta_;
-  [tabContentArea_ setFrame:tabContentsFrame];
-
-  if (useVertical) {
-    // Remove the top tab strip and add the sidebar in.
-    [topTabStripView_ removeFromSuperview];
-    [self addSideTabStripToWindow];
-  } else {
-    // Remove the side tab strip and add the top tab strip as a sibling of the
-    // window's content area.
-    [sideTabStripView_ removeFromSuperview];
-    NSRect tabContentsFrame = [tabContentArea_ frame];
-    tabContentsFrame.size.height -= contentAreaHeightDelta_;
-    [tabContentArea_ setFrame:tabContentsFrame];
-    [self addTopTabStripToWindow];
-  }
-
-  [self layoutSubviews];
-}
-
-// Return the appropriate tab strip based on whether or not side tabs are
-// enabled.
-- (TabStripView*)tabStripView {
-  if ([self useVerticalTabs])
-    return sideTabStripView_;
-  return topTabStripView_;
-}
-
-- (void)removeOverlay {
-  [self setUseOverlay:NO];
-  if (closeDeferred_) {
-    // See comment in BrowserWindowCocoa::Close() about orderOut:.
-    [[self window] orderOut:self];
-    [[self window] performClose:self];  // Autoreleases the controller.
-  }
-}
-
-- (void)showOverlay {
-  [self setUseOverlay:YES];
-}
-
-// if |useOverlay| is true, we're moving views into the overlay's content
-// area. If false, we're moving out of the overlay back into the window's
-// content.
-- (void)moveViewsBetweenWindowAndOverlay:(BOOL)useOverlay {
-  if (useOverlay) {
-    [[[overlayWindow_ contentView] superview] addSubview:[self tabStripView]];
-    // Add the original window's content view as a subview of the overlay
-    // window's content view.  We cannot simply use setContentView: here because
-    // the overlay window has a different content size (due to it being
-    // borderless).
-    [[overlayWindow_ contentView] addSubview:cachedContentView_];
-  } else {
-    [[self window] setContentView:cachedContentView_];
-    // The TabStripView always needs to be in front of the window's content
-    // view and therefore it should always be added after the content view is
-    // set.
-    [[[[self window] contentView] superview] addSubview:[self tabStripView]];
-    [[[[self window] contentView] superview] updateTrackingAreas];
-  }
-}
-
-// If |useOverlay| is YES, creates a new overlay window and puts the tab strip
-// and the content area inside of it. This allows it to have a different opacity
-// from the title bar. If NO, returns everything to the previous state and
-// destroys the overlay window until it's needed again. The tab strip and window
-// contents are returned to the original window.
-- (void)setUseOverlay:(BOOL)useOverlay {
-  [NSObject cancelPreviousPerformRequestsWithTarget:self
-                                           selector:@selector(removeOverlay)
-                                             object:nil];
-  NSWindow* window = [self window];
-  if (useOverlay && !overlayWindow_) {
-    DCHECK(!cachedContentView_);
-    overlayWindow_ = [[TabWindowOverlayWindow alloc]
-                         initWithContentRect:[window frame]
-                                   styleMask:NSBorderlessWindowMask
-                                     backing:NSBackingStoreBuffered
-                                       defer:YES];
-    [overlayWindow_ setTitle:@"overlay"];
-    [overlayWindow_ setBackgroundColor:[NSColor clearColor]];
-    [overlayWindow_ setOpaque:NO];
-    [overlayWindow_ setDelegate:self];
-    cachedContentView_ = [window contentView];
-    [window addChildWindow:overlayWindow_ ordered:NSWindowAbove];
-    // Sets explictly nil to the responder and then restores it.
-    // Leaving the first responder non-null here
-    // causes [RenderWidgethostViewCocoa resignFirstResponder] and
-    // following RenderWidgetHost::Blur(), which results unexpected
-    // focus lost.
-    focusBeforeOverlay_.reset([[FocusTracker alloc] initWithWindow:window]);
-    [window makeFirstResponder:nil];
-    [self moveViewsBetweenWindowAndOverlay:useOverlay];
-    [overlayWindow_ orderFront:nil];
-  } else if (!useOverlay && overlayWindow_) {
-    DCHECK(cachedContentView_);
-    [window setContentView:cachedContentView_];
-    [self moveViewsBetweenWindowAndOverlay:useOverlay];
-    [focusBeforeOverlay_ restoreFocusInWindow:window];
-    focusBeforeOverlay_.reset(nil);
-    [window display];
-    [window removeChildWindow:overlayWindow_];
-    [overlayWindow_ orderOut:nil];
-    [overlayWindow_ release];
-    overlayWindow_ = nil;
-    cachedContentView_ = nil;
-  } else {
-    NOTREACHED();
-  }
-}
-
-- (NSWindow*)overlayWindow {
-  return overlayWindow_;
-}
-
-- (BOOL)shouldConstrainFrameRect {
-  // If we currently have an overlay window, do not attempt to change the
-  // window's size, as our overlay window doesn't know how to resize properly.
-  return overlayWindow_ == nil;
-}
-
-- (BOOL)canReceiveFrom:(TabWindowController*)source {
-  // subclass must implement
-  NOTIMPLEMENTED();
-  return NO;
-}
-
-- (void)moveTabView:(NSView*)view
-     fromController:(TabWindowController*)dragController {
-  NOTIMPLEMENTED();
-}
-
-- (NSView*)selectedTabView {
-  NOTIMPLEMENTED();
-  return nil;
-}
-
-- (void)layoutTabs {
-  // subclass must implement
-  NOTIMPLEMENTED();
-}
-
-- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView {
-  // subclass must implement
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-- (void)insertPlaceholderForTab:(TabView*)tab
-                          frame:(NSRect)frame
-                  yStretchiness:(CGFloat)yStretchiness {
-  [self showNewTabButton:NO];
-}
-
-- (void)removePlaceholder {
-  [self showNewTabButton:YES];
-}
-
-- (BOOL)isDragSessionActive {
-  NOTIMPLEMENTED();
-  return NO;
-}
-
-- (BOOL)tabDraggingAllowed {
-  return YES;
-}
-
-- (BOOL)tabTearingAllowed {
-  return YES;
-}
-
-- (BOOL)windowMovementAllowed {
-  return YES;
-}
-
-- (BOOL)isTabFullyVisible:(TabView*)tab {
-  // Subclasses should implement this, but it's not necessary.
-  return YES;
-}
-
-- (void)showNewTabButton:(BOOL)show {
-  // subclass must implement
-  NOTIMPLEMENTED();
-}
-
-- (void)detachTabView:(NSView*)view {
-  // subclass must implement
-  NOTIMPLEMENTED();
-}
-
-- (NSInteger)numberOfTabs {
-  // subclass must implement
-  NOTIMPLEMENTED();
-  return 0;
-}
-
-- (BOOL)hasLiveTabs {
-  // subclass must implement
-  NOTIMPLEMENTED();
-  return NO;
-}
-
-- (NSString*)selectedTabTitle {
-  // subclass must implement
-  NOTIMPLEMENTED();
-  return @"";
-}
-
-- (BOOL)hasTabStrip {
-  // Subclasses should implement this.
-  NOTIMPLEMENTED();
-  return YES;
-}
-
-- (BOOL)useVerticalTabs {
-  // Subclasses should implement this.
-  NOTIMPLEMENTED();
-  return NO;
-}
-
-- (BOOL)isTabDraggable:(NSView*)tabView {
-  return ![lockedTabs_ containsObject:tabView];
-}
-
-- (void)setTab:(NSView*)tabView isDraggable:(BOOL)draggable {
-  if (draggable)
-    [lockedTabs_ removeObject:tabView];
-  else
-    [lockedTabs_ addObject:tabView];
-}
-
-// Tell the window that it needs to call performClose: as soon as the current
-// drag is complete. This prevents a window (and its overlay) from going away
-// during a drag.
-- (void)deferPerformClose {
-  closeDeferred_ = YES;
-}
-
-// Called when the size of the window content area has changed. Override to
-// position specific views. Base class implementation does nothing.
-- (void)layoutSubviews {
-  NOTIMPLEMENTED();
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/table_model_array_controller.h b/chrome/browser/ui/cocoa/table_model_array_controller.h
index b9b227e..850bf6d 100644
--- a/chrome/browser/ui/cocoa/table_model_array_controller.h
+++ b/chrome/browser/ui/cocoa/table_model_array_controller.h
@@ -8,17 +8,16 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "app/table_model_observer.h"
 #import "base/mac/cocoa_protocols.h"
 #include "base/scoped_nsobject.h"
 #include "base/scoped_ptr.h"
+#include "ui/base/models/table_model_observer.h"
 
 class RemoveRowsObserverBridge;
 class RemoveRowsTableModel;
 @class TableModelArrayController;
 
-// This class functions as an adapter from a RemoveRowsTableModel to a Cocoa
-// NSArrayController, to be used with bindings.
+// This class allows you to use a RemoveRowsTableModel with Cocoa bindings.
 // It maps the CanRemoveRows method to its canRemove property, and exposes
 // RemoveRows and RemoveAll as actions (remove: and removeAll:).
 // If the table model has groups, these are inserted into the list of arranged
@@ -52,3 +51,4 @@
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_TABLE_MODEL_ARRAY_CONTROLLER_H_
+
diff --git a/chrome/browser/ui/cocoa/table_model_array_controller.mm b/chrome/browser/ui/cocoa/table_model_array_controller.mm
index 02e573d..8678fa8 100644
--- a/chrome/browser/ui/cocoa/table_model_array_controller.mm
+++ b/chrome/browser/ui/cocoa/table_model_array_controller.mm
@@ -4,12 +4,12 @@
 
 #import "chrome/browser/ui/cocoa/table_model_array_controller.h"
 
-#include "app/table_model.h"
 #include "base/logging.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/remove_rows_table_model.h"
+#include "ui/base/models/table_model.h"
 
-@interface TableModelArrayController (PrivateMethods)
+@interface TableModelArrayController ()
 
 - (NSUInteger)offsetForGroupID:(int)groupID;
 - (NSUInteger)offsetForGroupID:(int)groupID startingOffset:(NSUInteger)offset;
@@ -24,13 +24,13 @@
 @end
 
 // Observer for a RemoveRowsTableModel.
-class RemoveRowsObserverBridge : public TableModelObserver {
+class RemoveRowsObserverBridge : public ui::TableModelObserver {
  public:
   RemoveRowsObserverBridge(TableModelArrayController* controller)
       : controller_(controller) {}
   virtual ~RemoveRowsObserverBridge() {}
 
-  // TableModelObserver methods
+  // ui::TableModelObserver methods
   virtual void OnModelChanged();
   virtual void OnItemsChanged(int start, int length);
   virtual void OnItemsAdded(int start, int length);
@@ -78,9 +78,9 @@
       NSMakeRange(0, [[self arrangedObjects] count])];
   [self removeObjectsAtArrangedObjectIndexes:indexes];
   if (model_->HasGroups()) {
-    const TableModel::Groups& groups = model_->GetGroups();
+    const ui::TableModel::Groups& groups = model_->GetGroups();
     DCHECK(groupTitle_.get());
-    for (TableModel::Groups::const_iterator it = groups.begin();
+    for (ui::TableModel::Groups::const_iterator it = groups.begin();
          it != groups.end(); ++it) {
       NSDictionary* group = [NSDictionary dictionaryWithObjectsAndKeys:
           base::SysUTF16ToNSString(it->title), groupTitle_.get(),
@@ -93,7 +93,7 @@
 }
 
 - (NSUInteger)offsetForGroupID:(int)groupID startingOffset:(NSUInteger)offset {
-  const TableModel::Groups& groups = model_->GetGroups();
+  const ui::TableModel::Groups& groups = model_->GetGroups();
   DCHECK_GT(offset, 0u);
   for (NSUInteger i = offset - 1; i < groups.size(); ++i) {
     if (groups[i].id == groupID)
@@ -150,14 +150,18 @@
 }
 
 - (void)modelDidAddItemsInRange:(NSRange)range {
+  if (range.length == 0)
+    return;
   NSMutableArray* rows = [NSMutableArray arrayWithCapacity:range.length];
-  for (NSUInteger i=range.location; i<NSMaxRange(range); ++i)
+  for (NSUInteger i = range.location; i < NSMaxRange(range); ++i)
     [rows addObject:[self columnValuesForRow:i]];
-  [self insertObjects:rows
-      atArrangedObjectIndexes:[self controllerRowsForModelRowsInRange:range]];
+  NSIndexSet* indexes = [self controllerRowsForModelRowsInRange:range];
+  [self insertObjects:rows atArrangedObjectIndexes:indexes];
 }
 
 - (void)modelDidRemoveItemsInRange:(NSRange)range {
+  if (range.length == 0)
+    return;
   NSMutableIndexSet* indexes =
       [NSMutableIndexSet indexSetWithIndexesInRange:range];
   if (model_->HasGroups()) {
@@ -197,7 +201,7 @@
   return dict;
 }
 
-// Overridden from NSArrayController -----------------------------------------
+#pragma mark Overridden from NSArrayController
 
 - (BOOL)canRemove {
   if (!model_)
@@ -213,9 +217,9 @@
   model_->RemoveRows(rows);
 }
 
-// Table View Delegate --------------------------------------------------------
+#pragma mark NSTableView delegate methods
 
-- (BOOL)tableView:(NSTableView*)tv isGroupRow:(NSInteger)row {
+- (BOOL)tableView:(NSTableView*)tableView isGroupRow:(NSInteger)row {
   NSDictionary* values = [[self arrangedObjects] objectAtIndex:row];
   return [[values objectForKey:kIsGroupRow] boolValue];
 }
@@ -237,10 +241,11 @@
   return indexes;
 }
 
-// Actions --------------------------------------------------------------------
+#pragma mark Actions
 
 - (IBAction)removeAll:(id)sender {
   model_->RemoveAll();
 }
 
 @end
+
diff --git a/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm b/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm
index 746d8a1..65a1491 100644
--- a/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm
@@ -54,21 +54,24 @@
     webkit::npapi::WebPluginInfo foo_plugin;
     foo_plugin.path = FilePath(FILE_PATH_LITERAL("a-foo"));
     foo_plugin.name = ASCIIToUTF16("FooPlugin");
-    foo_plugin.enabled = true;
+    foo_plugin.enabled =
+        webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
     scoped_ptr<webkit::npapi::PluginGroup> foo_group(
         webkit::npapi::PluginGroup::FromWebPluginInfo(foo_plugin));
     plugins.push_back(*foo_group);
     webkit::npapi::WebPluginInfo bar_plugin;
     bar_plugin.path = FilePath(FILE_PATH_LITERAL("b-bar"));
     bar_plugin.name = ASCIIToUTF16("BarPlugin");
-    bar_plugin.enabled = true;
+    bar_plugin.enabled =
+        webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
     scoped_ptr<webkit::npapi::PluginGroup> bar_group(
         webkit::npapi::PluginGroup::FromWebPluginInfo(bar_plugin));
     plugins.push_back(*bar_group);
     webkit::npapi::WebPluginInfo blurp_plugin;
     blurp_plugin.path = FilePath(FILE_PATH_LITERAL("c-blurp"));
     blurp_plugin.name = ASCIIToUTF16("BlurpPlugin");
-    blurp_plugin.enabled = true;
+    blurp_plugin.enabled =
+        webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
     scoped_ptr<webkit::npapi::PluginGroup> blurp_group(
         webkit::npapi::PluginGroup::FromWebPluginInfo(blurp_plugin));
     plugins.push_back(*blurp_group);
@@ -169,3 +172,4 @@
               @")",
               [titles description]);
 }
+
diff --git a/chrome/browser/ui/cocoa/tabpose_window.h b/chrome/browser/ui/cocoa/tabpose_window.h
index b798bcc..d8ec0a2 100644
--- a/chrome/browser/ui/cocoa/tabpose_window.h
+++ b/chrome/browser/ui/cocoa/tabpose_window.h
@@ -73,6 +73,13 @@
 
   // Informs us of added/removed/updated tabs.
   scoped_ptr<TabStripModelObserverBridge> tabStripModelObserverBridge_;
+
+  // The icon used for the closebutton layers.
+  base::mac::ScopedCFTypeRef<CGImageRef> closeIcon_;
+
+  // True if all close layers should be shown (as opposed to just the close
+  // layer of the currently selected thumbnail).
+  BOOL showAllCloseLayers_;
 }
 
 // Shows a TabposeWindow on top of |parent|, with |rect| being the active area.
diff --git a/chrome/browser/ui/cocoa/tabpose_window.mm b/chrome/browser/ui/cocoa/tabpose_window.mm
index b9e4a3d..22aa6ad 100644
--- a/chrome/browser/ui/cocoa/tabpose_window.mm
+++ b/chrome/browser/ui/cocoa/tabpose_window.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,8 @@
 
 #import <QuartzCore/QuartzCore.h>
 
-#include "app/resource_bundle.h"
+#include <algorithm>
+
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/scoped_callback_factory.h"
@@ -23,14 +24,16 @@
 #include "chrome/browser/tab_contents/thumbnail_generator.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/scoped_cg_context_state_mac.h"
 #include "grit/app_resources.h"
+#include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/scoped_cg_context_state_mac.h"
 
 const int kTopGradientHeight  = 15;
 
@@ -40,7 +43,8 @@
 
 const CGFloat kDefaultAnimationDuration = 0.25;  // In seconds.
 const CGFloat kSlomoFactor = 4;
-const CGFloat kObserverChangeAnimationDuration = 0.75;  // In seconds.
+const CGFloat kObserverChangeAnimationDuration = 0.25;  // In seconds.
+const CGFloat kSelectionInset = 5;
 
 // CAGradientLayer is 10.6-only -- roll our own.
 @interface DarkGradientLayer : CALayer
@@ -116,11 +120,7 @@
   }
 
   void ResetPaintingObserver() {
-    if (rwh_->painting_observer() != NULL) {
-      DCHECK(rwh_->painting_observer() ==
-             g_browser_process->GetThumbnailGenerator());
-      rwh_->set_painting_observer(NULL);
-    }
+    g_browser_process->GetThumbnailGenerator()->MonitorRenderer(rwh_, false);
   }
 
   gfx::Size size_;
@@ -145,9 +145,7 @@
   gfx::Size page_size(size_);  // Logical size the renderer renders at.
   gfx::Size pixel_size(size_);  // Physical pixel size the image is rendered at.
 
-  DCHECK(rwh_->painting_observer() == NULL ||
-         rwh_->painting_observer() == generator);
-  rwh_->set_painting_observer(generator);
+  generator->MonitorRenderer(rwh_, true);
 
   // Will send an IPC to the renderer on the IO thread.
   generator->AskForSnapshot(
@@ -177,8 +175,9 @@
 
 - (void)setThumbnail:(const SkBitmap&)bitmap {
   // SkCreateCGImageRef() holds on to |bitmaps|'s memory, so this doesn't
-  // create a copy.
-  thumbnail_.reset(SkCreateCGImageRef(bitmap));
+  // create a copy. The renderer always draws data in the system colorspace.
+  thumbnail_.reset(SkCreateCGImageRefWithColorspace(
+      bitmap, base::mac::GetSystemColorSpace()));
   loader_ = NULL;
   [self setNeedsDisplay];
 }
@@ -190,7 +189,7 @@
   // means I need to create InfoBarControllers here. At that point, we can get
   // the height from that controller. Until then, hardcode. :-/
   const int kInfoBarHeight = 31;
-  topOffset += contents_->infobar_delegate_count() * kInfoBarHeight;
+  topOffset += contents_->infobar_count() * kInfoBarHeight;
 
   bool always_show_bookmark_bar =
       contents_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
@@ -702,22 +701,6 @@
       tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y);
     }
   }
-
-  // Go through last row and center it:
-  // X X X X
-  // X X X X
-  //   X X
-  int last_row_empty_tiles_x = count_x() - last_row_count_x();
-  CGFloat small_last_row_shift_x =
-      last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2;
-  CGFloat big_last_row_shift_x =
-      last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2;
-  for (int i = tile_count - last_row_count_x(); i < tile_count; ++i) {
-    tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x;
-    tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x;
-    tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x;
-    tiles_[i]->title_rect_.origin.x += small_last_row_shift_x;
-  }
 }
 
 void TileSet::set_selected_index(int index) {
@@ -914,9 +897,21 @@
                rect:(NSRect)rect
               slomo:(BOOL)slomo
       tabStripModel:(TabStripModel*)tabStripModel;
+
+// Creates and initializes the CALayer in the background and all the CALayers
+// for the thumbnails, favicons, and titles.
 - (void)setUpLayersInSlomo:(BOOL)slomo;
-- (void)fadeAway:(BOOL)slomo;
-- (void)selectTileAtIndex:(int)newIndex;
+
+// Tells the browser to make the tab corresponding to currently selected
+// thumbnail the current tab and starts the tabpose exit animmation.
+- (void)fadeAwayInSlomo:(BOOL)slomo;
+
+// Returns the CALayer for the close button belonging to the thumbnail at
+// index |index|.
+- (CALayer*)closebuttonLayerAtIndex:(NSUInteger)index;
+
+// Updates the visibility of all closebutton layers.
+- (void)updateClosebuttonLayersVisibility;
 @end
 
 @implementation TabposeWindow
@@ -945,6 +940,10 @@
     tileSet_.reset(new tabpose::TileSet);
     tabStripModelObserverBridge_.reset(
         new TabStripModelObserverBridge(tabStripModel_, self));
+    NSImage* nsCloseIcon =
+        ResourceBundle::GetSharedInstance().GetNativeImageNamed(
+            IDR_TABPOSE_CLOSE);
+    closeIcon_.reset(base::mac::CopyNSImageToCGImage(nsCloseIcon));
     [self setReleasedWhenClosed:YES];
     [self setOpaque:NO];
     [self setBackgroundColor:[NSColor clearColor]];
@@ -960,16 +959,15 @@
   return [allThumbnailLayers_ objectAtIndex:tileSet_->selected_index()];
 }
 
-- (void)selectTileAtIndex:(int)newIndex {
-  const tabpose::Tile& tile = tileSet_->tile_at(newIndex);
-  selectionHighlight_.frame =
-      NSRectToCGRect(NSInsetRect(tile.thumb_rect(), -5, -5));
-  tileSet_->set_selected_index(newIndex);
-}
-
 - (void)selectTileAtIndexWithoutAnimation:(int)newIndex {
   ScopedCAActionDisabler disabler;
-  [self selectTileAtIndex:newIndex];
+  const tabpose::Tile& tile = tileSet_->tile_at(newIndex);
+  selectionHighlight_.frame =
+      NSRectToCGRect(NSInsetRect(tile.thumb_rect(),
+                     -kSelectionInset, -kSelectionInset));
+  tileSet_->set_selected_index(newIndex);
+
+  [self updateClosebuttonLayersVisibility];
 }
 
 - (void)addLayersForTile:(tabpose::Tile&)tile
@@ -1003,6 +1001,27 @@
   if (state_ == tabpose::kFadedIn)
     layer.get().shadowOpacity = 0.5;
 
+  // Add a close button to the thumb layer.
+  CALayer* closeLayer = [CALayer layer];
+  closeLayer.contents = reinterpret_cast<id>(closeIcon_.get());
+  CGRect closeBounds = {};
+  closeBounds.size.width = CGImageGetWidth(closeIcon_);
+  closeBounds.size.height = CGImageGetHeight(closeIcon_);
+  closeLayer.bounds = closeBounds;
+  closeLayer.hidden = YES;
+
+  [closeLayer addConstraint:
+      [CAConstraint constraintWithAttribute:kCAConstraintMidX
+                                 relativeTo:@"superlayer"
+                                  attribute:kCAConstraintMinX]];
+  [closeLayer addConstraint:
+      [CAConstraint constraintWithAttribute:kCAConstraintMidY
+                                 relativeTo:@"superlayer"
+                                  attribute:kCAConstraintMaxY]];
+
+  layer.get().layoutManager = [CAConstraintLayoutManager layoutManager];
+  [layer.get() addSublayer:closeLayer];
+
   [bgLayer_ addSublayer:layer];
   [allThumbnailLayers_ addObject:layer];
 
@@ -1199,11 +1218,11 @@
     case NSNewlineCharacter:
     case NSCarriageReturnCharacter:
     case ' ':
-      [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
+      [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
       break;
     case '\e':  // Escape
       tileSet_->set_selected_index(tabStripModel_->selected_index());
-      [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
+      [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
       break;
   }
 }
@@ -1222,7 +1241,7 @@
           character == '9' ? tabStripModel_->count() - 1 : character - '1';
       if (index < tabStripModel_->count()) {
         tileSet_->set_selected_index(index);
-        [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
+        [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
         return YES;
       }
     }
@@ -1230,7 +1249,12 @@
   return NO;
 }
 
--(void)selectTileFromMouseEvent:(NSEvent*)event {
+- (void)flagsChanged:(NSEvent*)event {
+  showAllCloseLayers_ = ([event modifierFlags] & NSAlternateKeyMask) != 0;
+  [self updateClosebuttonLayersVisibility];
+}
+
+- (void)selectTileFromMouseEvent:(NSEvent*)event {
   int newIndex = -1;
   CGPoint p = NSPointToCGPoint([event locationInWindow]);
   for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
@@ -1247,16 +1271,46 @@
   [self selectTileFromMouseEvent:event];
 }
 
+- (CALayer*)closebuttonLayerAtIndex:(NSUInteger)index {
+  CALayer* layer = [allThumbnailLayers_ objectAtIndex:index];
+  return [[layer sublayers] objectAtIndex:0];
+}
+
+- (void)updateClosebuttonLayersVisibility {
+  for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
+    CALayer* layer = [self closebuttonLayerAtIndex:i];
+    BOOL isSelectedTile = static_cast<int>(i) == tileSet_->selected_index();
+    BOOL isVisible = state_ == tabpose::kFadedIn &&
+                     (isSelectedTile || showAllCloseLayers_);
+    layer.hidden = !isVisible;
+  }
+}
+
 - (void)mouseDown:(NSEvent*)event {
   // Just in case the user clicked without ever moving the mouse.
   [self selectTileFromMouseEvent:event];
 
-  [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
+  // If the click occurred in a close box, close that tab and don't do anything
+  // else.
+  CGPoint p = NSPointToCGPoint([event locationInWindow]);
+  for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
+    CALayer* layer = [self closebuttonLayerAtIndex:i];
+    CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_];
+    if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp] &&
+        !layer.hidden) {
+      tabStripModel_->CloseTabContentsAt(i,
+          TabStripModel::CLOSE_USER_GESTURE |
+          TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
+      return;
+    }
+  }
+
+  [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
 }
 
 - (void)swipeWithEvent:(NSEvent*)event {
   if (abs([event deltaY]) > 0.5)  // Swipe up or down.
-    [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
+    [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
 }
 
 - (void)close {
@@ -1272,7 +1326,7 @@
 
 - (void)commandDispatch:(id)sender {
   if ([sender tag] == IDC_TABPOSE)
-    [self fadeAway:NO];
+    [self fadeAwayInSlomo:NO];
 }
 
 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
@@ -1328,7 +1382,7 @@
   titleLayer.opacity = 0;
 }
 
-- (void)fadeAway:(BOOL)slomo {
+- (void)fadeAwayInSlomo:(BOOL)slomo {
   if (state_ == tabpose::kFadingOut)
     return;
 
@@ -1354,6 +1408,8 @@
     // running the exit animation.
     for (CALayer* layer in allThumbnailLayers_.get())
       layer.shadowOpacity = 0.0;
+
+    [self updateClosebuttonLayersVisibility];
   }
 
   // Animate layers out, all in one transaction.
@@ -1379,6 +1435,8 @@
       ScopedCAActionDisabler disableCAActions;
       for (CALayer* layer in allThumbnailLayers_.get())
         layer.shadowOpacity = 0.5;
+
+      [self updateClosebuttonLayersVisibility];
     }
   } else if ([animationId isEqualToString:kAnimationIdFadeOut]) {
     DCHECK_EQ(tabpose::kFadingOut, state_);
@@ -1399,12 +1457,50 @@
 - (void)refreshLayerFramesAtIndex:(int)i {
   const tabpose::Tile& tile = tileSet_->tile_at(i);
 
-  CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i];
-  faviconLayer.frame = NSRectToCGRect(tile.favicon_rect());
-  CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i];
-  titleLayer.frame = NSRectToCGRect(tile.title_rect());
   CALayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:i];
-  thumbLayer.frame = NSRectToCGRect(tile.thumb_rect());
+
+  if (i == tileSet_->selected_index()) {
+    AnimateCALayerFrameFromTo(
+        selectionHighlight_,
+        NSInsetRect(NSRectFromCGRect(thumbLayer.frame),
+                    -kSelectionInset, -kSelectionInset),
+        NSInsetRect(tile.thumb_rect(),
+                    -kSelectionInset, -kSelectionInset),
+        kObserverChangeAnimationDuration,
+        nil);
+  }
+
+  // Repaint layer if necessary.
+  if (!NSEqualSizes(NSRectFromCGRect(thumbLayer.frame).size,
+                    tile.thumb_rect().size)) {
+    [thumbLayer setNeedsDisplay];
+  }
+
+  // Use AnimateCALayerFrameFromTo() instead of just setting |frame| to let
+  // the animation match the selection animation --
+  // |kCAMediaTimingFunctionDefault| is 10.6-only.
+  AnimateCALayerFrameFromTo(
+      thumbLayer,
+      NSRectFromCGRect(thumbLayer.frame),
+      tile.thumb_rect(),
+      kObserverChangeAnimationDuration,
+      nil);
+
+  CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i];
+  AnimateCALayerFrameFromTo(
+      faviconLayer,
+      NSRectFromCGRect(faviconLayer.frame),
+      tile.favicon_rect(),
+      kObserverChangeAnimationDuration,
+      nil);
+
+  CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i];
+  AnimateCALayerFrameFromTo(
+      titleLayer,
+      NSRectFromCGRect(titleLayer.frame),
+      tile.title_rect(),
+      kObserverChangeAnimationDuration,
+      nil);
 }
 
 - (void)insertTabWithContents:(TabContentsWrapper*)contents
@@ -1430,17 +1526,18 @@
   DCHECK_EQ(tabStripModel_->count(),
             static_cast<int>([allFaviconLayers_ count]));
 
+  // Update selection.
+  int selectedIndex = tileSet_->selected_index();
+  if (selectedIndex >= index)
+    selectedIndex++;
+  [self selectTileAtIndexWithoutAnimation:selectedIndex];
+
+  // Animate everything into its new place.
   for (int i = 0; i < tabStripModel_->count(); ++i) {
     if (i == index)  // The new layer.
       continue;
     [self refreshLayerFramesAtIndex:i];
   }
-
-  // Update selection.
-  int selectedIndex = tileSet_->selected_index();
-  if (selectedIndex >= index)
-    selectedIndex++;
-  [self selectTileAtIndex:selectedIndex];
 }
 
 - (void)tabClosingWithContents:(TabContentsWrapper*)contents
@@ -1457,12 +1554,15 @@
   tileSet_->RemoveTileAt(index);
   tileSet_->Layout(containingRect_);
 
-  [[allThumbnailLayers_ objectAtIndex:index] removeFromSuperlayer];
-  [allThumbnailLayers_ removeObjectAtIndex:index];
-  [[allTitleLayers_ objectAtIndex:index] removeFromSuperlayer];
-  [allTitleLayers_ removeObjectAtIndex:index];
-  [[allFaviconLayers_ objectAtIndex:index] removeFromSuperlayer];
-  [allFaviconLayers_ removeObjectAtIndex:index];
+  {
+    ScopedCAActionDisabler disabler;
+    [[allThumbnailLayers_ objectAtIndex:index] removeFromSuperlayer];
+    [allThumbnailLayers_ removeObjectAtIndex:index];
+    [[allTitleLayers_ objectAtIndex:index] removeFromSuperlayer];
+    [allTitleLayers_ removeObjectAtIndex:index];
+    [[allFaviconLayers_ objectAtIndex:index] removeFromSuperlayer];
+    [allFaviconLayers_ removeObjectAtIndex:index];
+  }
 
   // Update old layers.
   DCHECK_EQ(tabStripModel_->count(),
@@ -1475,15 +1575,16 @@
   if (tabStripModel_->count() == 0)
     [self close];
 
-  for (int i = 0; i < tabStripModel_->count(); ++i)
-    [self refreshLayerFramesAtIndex:i];
-
   // Update selection.
   int selectedIndex = tileSet_->selected_index();
-  if (selectedIndex >= index)
+  if (selectedIndex > index || selectedIndex >= tabStripModel_->count())
     selectedIndex--;
   if (selectedIndex >= 0)
-    [self selectTileAtIndex:selectedIndex];
+    [self selectTileAtIndexWithoutAnimation:selectedIndex];
+
+  // Animate everything into its new place.
+  for (int i = 0; i < tabStripModel_->count(); ++i)
+    [self refreshLayerFramesAtIndex:i];
 }
 
 - (void)tabMovedWithContents:(TabContentsWrapper*)contents
@@ -1508,10 +1609,6 @@
   [allTitleLayers_ removeObjectAtIndex:from];
   [allTitleLayers_ insertObject:titleLayer.get() atIndex:to];
 
-  // Update frames of the layers.
-  for (int i = std::min(from, to); i <= std::max(from, to); ++i)
-    [self refreshLayerFramesAtIndex:i];
-
   // Update selection.
   int selectedIndex = tileSet_->selected_index();
   if (from == selectedIndex)
@@ -1520,7 +1617,11 @@
     selectedIndex--;
   else if (to <= selectedIndex && selectedIndex < from)
     selectedIndex++;
-  [self selectTileAtIndex:selectedIndex];
+  [self selectTileAtIndexWithoutAnimation:selectedIndex];
+
+  // Update frames of the layers.
+  for (int i = std::min(from, to); i <= std::max(from, to); ++i)
+    [self refreshLayerFramesAtIndex:i];
 }
 
 - (void)tabChangedWithContents:(TabContentsWrapper*)contents
diff --git a/chrome/browser/ui/cocoa/tabs/OWNERS b/chrome/browser/ui/cocoa/tabs/OWNERS
new file mode 100644
index 0000000..30d99dc
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/OWNERS
@@ -0,0 +1,4 @@
+avi@chromium.org
+pinkerton@chromium.org
+rohitrao@chromium.org
+viettrungluu@chromium.org
diff --git a/chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.h b/chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.h
new file mode 100644
index 0000000..bd52ad9
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+
+// A controller for the tab strip when side tabs are enabled.
+//
+// TODO(pinkerton): I'm expecting there are more things here that need
+// overriding rather than just tweaking a couple of settings, so I'm creating
+// a full-blown subclass. Clearly, very little is actually necessary at this
+// point for it to work.
+
+@interface SideTabStripController : TabStripController {
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.mm
new file mode 100644
index 0000000..80c3a15
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.mm
@@ -0,0 +1,33 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tabs/side_tab_strip_controller.h"
+
+@implementation SideTabStripController
+
+// TODO(pinkerton): Still need to figure out several things:
+//   - new tab button placement and layout
+//   - animating tabs in and out
+//   - being able to drop a tab elsewhere besides the 1st position
+//   - how to load a different tab view nib for each tab.
+
+- (id)initWithView:(TabStripView*)view
+        switchView:(NSView*)switchView
+           browser:(Browser*)browser
+          delegate:(id<TabStripControllerDelegate>)delegate {
+  self = [super initWithView:view
+                  switchView:switchView
+                     browser:browser
+                    delegate:delegate];
+  if (self) {
+    // Side tabs have no indent since they are not sharing space with the
+    // window controls.
+    [self setIndentForControls:0.0];
+    verticalLayout_ = YES;
+  }
+  return self;
+}
+
+@end
+
diff --git a/chrome/browser/ui/cocoa/tabs/side_tab_strip_view.h b/chrome/browser/ui/cocoa/tabs/side_tab_strip_view.h
new file mode 100644
index 0000000..8128f7f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/side_tab_strip_view.h
@@ -0,0 +1,15 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+
+// A class that handles drawing the background of the tab strip when side tabs
+// are enabled.
+
+@interface SideTabStripView : TabStripView {
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/side_tab_strip_view.mm b/chrome/browser/ui/cocoa/tabs/side_tab_strip_view.mm
new file mode 100644
index 0000000..80cefc1
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/side_tab_strip_view.mm
@@ -0,0 +1,43 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tabs/side_tab_strip_view.h"
+
+#include "base/scoped_nsobject.h"
+#import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
+
+@implementation SideTabStripView
+
+- (void)drawBorder:(NSRect)bounds {
+  // Draw a border on the right side.
+  NSRect borderRect, contentRect;
+  NSDivideRect(bounds, &borderRect, &contentRect, 1, NSMaxXEdge);
+  [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
+  NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+}
+
+// Override to prevent double-clicks from minimizing the window. The side
+// tab strip doesn't have that behavior (since it's in the window content
+// area).
+- (BOOL)doubleClickMinimizesWindow {
+  return NO;
+}
+
+- (void)drawRect:(NSRect)rect {
+  // BOOL isKey = [[self window] isKeyWindow];
+  NSColor* aColor =
+      [NSColor colorWithCalibratedRed:0.506 green:0.660 blue:0.985 alpha:1.000];
+  NSColor* bColor =
+      [NSColor colorWithCalibratedRed:0.099 green:0.140 blue:0.254 alpha:1.000];
+  scoped_nsobject<NSGradient> gradient(
+      [[NSGradient alloc] initWithStartingColor:aColor endingColor:bColor]);
+
+  NSRect gradientRect = [self bounds];
+  [gradient drawInRect:gradientRect angle:270.0];
+
+  // Draw borders and any drop feedback.
+  [super drawRect:rect];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/side_tab_strip_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/side_tab_strip_view_unittest.mm
new file mode 100644
index 0000000..1cc5572
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/side_tab_strip_view_unittest.mm
@@ -0,0 +1,30 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/tabs/side_tab_strip_view.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class SideTabStripViewTest : public CocoaTest {
+ public:
+  SideTabStripViewTest() {
+    NSRect frame = NSMakeRect(0, 0, 100, 30);
+    scoped_nsobject<SideTabStripView> view(
+        [[SideTabStripView alloc] initWithFrame:frame]);
+    view_ = view.get();
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  SideTabStripView* view_;
+};
+
+TEST_VIEW(SideTabStripViewTest, view_)
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.h b/chrome/browser/ui/cocoa/tabs/tab_controller.h
new file mode 100644
index 0000000..581b82c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.h
@@ -0,0 +1,115 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+#import "chrome/browser/ui/cocoa/hover_close_button.h"
+#include "chrome/browser/ui/tabs/tab_menu_model.h"
+
+// The loading/waiting state of the tab.
+enum TabLoadingState {
+  kTabDone,
+  kTabLoading,
+  kTabWaiting,
+  kTabCrashed,
+};
+
+@class MenuController;
+namespace TabControllerInternal {
+class MenuDelegate;
+}
+@class TabView;
+@protocol TabControllerTarget;
+
+// A class that manages a single tab in the tab strip. Set its target/action
+// to be sent a message when the tab is selected by the user clicking. Setting
+// the |loading| property to YES visually indicates that this tab is currently
+// loading content via a spinner.
+//
+// The tab has the notion of an "icon view" which can be used to display
+// identifying characteristics such as a favicon, or since it's a full-fledged
+// view, something with state and animation such as a throbber for illustrating
+// progress. The default in the nib is an image view so nothing special is
+// required if that's all you need.
+
+@interface TabController : NSViewController {
+ @private
+  IBOutlet NSView* iconView_;
+  IBOutlet NSTextField* titleView_;
+  IBOutlet HoverCloseButton* closeButton_;
+
+  NSRect originalIconFrame_;  // frame of iconView_ as loaded from nib
+  BOOL isIconShowing_;  // last state of iconView_ in updateVisibility
+
+  BOOL app_;
+  BOOL mini_;
+  BOOL pinned_;
+  BOOL selected_;
+  TabLoadingState loadingState_;
+  CGFloat iconTitleXOffset_;  // between left edges of icon and title
+  id<TabControllerTarget> target_;  // weak, where actions are sent
+  SEL action_;  // selector sent when tab is selected by clicking
+  scoped_ptr<TabMenuModel> contextMenuModel_;
+  scoped_ptr<TabControllerInternal::MenuDelegate> contextMenuDelegate_;
+  scoped_nsobject<MenuController> contextMenuController_;
+}
+
+@property(assign, nonatomic) TabLoadingState loadingState;
+
+@property(assign, nonatomic) SEL action;
+@property(assign, nonatomic) BOOL app;
+@property(assign, nonatomic) BOOL mini;
+@property(assign, nonatomic) BOOL pinned;
+@property(assign, nonatomic) BOOL selected;
+@property(assign, nonatomic) id target;
+@property(assign, nonatomic) NSView* iconView;
+@property(assign, nonatomic) NSTextField* titleView;
+@property(assign, nonatomic) HoverCloseButton* closeButton;
+
+// Minimum and maximum allowable tab width. The minimum width does not show
+// the icon or the close button. The selected tab always has at least a close
+// button so it has a different minimum width.
++ (CGFloat)minTabWidth;
++ (CGFloat)maxTabWidth;
++ (CGFloat)minSelectedTabWidth;
++ (CGFloat)miniTabWidth;
++ (CGFloat)appTabWidth;
+
+// The view associated with this controller, pre-casted as a TabView
+- (TabView*)tabView;
+
+// Closes the associated TabView by relaying the message to |target_| to
+// perform the close.
+- (IBAction)closeTab:(id)sender;
+
+// Replace the current icon view with the given view. |iconView| will be
+// resized to the size of the current icon view.
+- (void)setIconView:(NSView*)iconView;
+- (NSView*)iconView;
+
+// Called by the tabs to determine whether we are in rapid (tab) closure mode.
+// In this mode, we handle clicks slightly differently due to animation.
+// Ideally, tabs would know about their own animation and wouldn't need this.
+- (BOOL)inRapidClosureMode;
+
+// Updates the visibility of certain subviews, such as the icon and close
+// button, based on criteria such as the tab's selected state and its current
+// width.
+- (void)updateVisibility;
+
+// Update the title color to match the tabs current state.
+- (void)updateTitleColor;
+@end
+
+@interface TabController(TestingAPI)
+- (NSString*)toolTip;
+- (int)iconCapacity;
+- (BOOL)shouldShowIcon;
+- (BOOL)shouldShowCloseButton;
+@end  // TabController(TestingAPI)
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
new file mode 100644
index 0000000..5f53ab5
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -0,0 +1,313 @@
+// Copyright (c) 2011 The Chromium 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/mac/mac_util.h"
+#include "chrome/browser/accessibility/browser_accessibility_state.h"
+#import "chrome/browser/themes/browser_theme_provider.h"
+#import "chrome/browser/ui/cocoa/menu_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_view.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/common/extensions/extension.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+@implementation TabController
+
+@synthesize action = action_;
+@synthesize app = app_;
+@synthesize loadingState = loadingState_;
+@synthesize mini = mini_;
+@synthesize pinned = pinned_;
+@synthesize target = target_;
+@synthesize iconView = iconView_;
+@synthesize titleView = titleView_;
+@synthesize closeButton = closeButton_;
+
+namespace TabControllerInternal {
+
+// A C++ delegate that handles enabling/disabling menu items and handling when
+// a menu command is chosen. Also fixes up the menu item label for "pin/unpin
+// tab".
+class MenuDelegate : public ui::SimpleMenuModel::Delegate {
+ public:
+  explicit MenuDelegate(id<TabControllerTarget> target, TabController* owner)
+      : target_(target),
+        owner_(owner) {}
+
+  // Overridden from ui::SimpleMenuModel::Delegate
+  virtual bool IsCommandIdChecked(int command_id) const { return false; }
+  virtual bool IsCommandIdEnabled(int command_id) const {
+    TabStripModel::ContextMenuCommand command =
+        static_cast<TabStripModel::ContextMenuCommand>(command_id);
+    return [target_ isCommandEnabled:command forController:owner_];
+  }
+  virtual bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator) { return false; }
+  virtual void ExecuteCommand(int command_id) {
+    TabStripModel::ContextMenuCommand command =
+        static_cast<TabStripModel::ContextMenuCommand>(command_id);
+    [target_ commandDispatch:command forController:owner_];
+  }
+
+ private:
+  id<TabControllerTarget> target_;  // weak
+  TabController* owner_;  // weak, owns me
+};
+
+}  // TabControllerInternal namespace
+
+// The min widths match the windows values and are sums of left + right
+// padding, of which we have no comparable constants (we draw using paths, not
+// images). The selected tab width includes the close button width.
++ (CGFloat)minTabWidth { return 31; }
++ (CGFloat)minSelectedTabWidth { return 46; }
++ (CGFloat)maxTabWidth { return 220; }
++ (CGFloat)miniTabWidth { return 53; }
++ (CGFloat)appTabWidth { return 66; }
+
+- (TabView*)tabView {
+  return static_cast<TabView*>([self view]);
+}
+
+- (id)init {
+  self = [super initWithNibName:@"TabView" bundle:base::mac::MainAppBundle()];
+  if (self != nil) {
+    isIconShowing_ = YES;
+    NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
+    [defaultCenter addObserver:self
+                      selector:@selector(viewResized:)
+                          name:NSViewFrameDidChangeNotification
+                        object:[self view]];
+    [defaultCenter addObserver:self
+                      selector:@selector(themeChangedNotification:)
+                          name:kBrowserThemeDidChangeNotification
+                        object:nil];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [[self tabView] setController:nil];
+  [super dealloc];
+}
+
+// The internals of |-setSelected:| but doesn't check if we're already set
+// to |selected|. Pass the selection change to the subviews that need it and
+// mark ourselves as needing a redraw.
+- (void)internalSetSelected:(BOOL)selected {
+  selected_ = selected;
+  TabView* tabView = static_cast<TabView*>([self view]);
+  DCHECK([tabView isKindOfClass:[TabView class]]);
+  [tabView setState:selected];
+  [tabView cancelAlert];
+  [self updateVisibility];
+  [self updateTitleColor];
+}
+
+// Called when the tab's nib is done loading and all outlets are hooked up.
+- (void)awakeFromNib {
+  // Remember the icon's frame, so that if the icon is ever removed, a new
+  // one can later replace it in the proper location.
+  originalIconFrame_ = [iconView_ frame];
+
+  // When the icon is removed, the title expands to the left to fill the space
+  // left by the icon.  When the close button is removed, the title expands to
+  // the right to fill its space.  These are the amounts to expand and contract
+  // titleView_ under those conditions. We don't have to explicilty save the
+  // offset between the title and the close button since we can just get that
+  // value for the close button's frame.
+  NSRect titleFrame = [titleView_ frame];
+  iconTitleXOffset_ = NSMinX(titleFrame) - NSMinX(originalIconFrame_);
+
+  [self internalSetSelected:selected_];
+}
+
+// Called when Cocoa wants to display the context menu. Lazily instantiate
+// the menu based off of the cross-platform model. Re-create the menu and
+// model every time to get the correct labels and enabling.
+- (NSMenu*)menu {
+  contextMenuDelegate_.reset(
+      new TabControllerInternal::MenuDelegate(target_, self));
+  contextMenuModel_.reset(new TabMenuModel(contextMenuDelegate_.get(),
+                                           [self pinned]));
+  contextMenuController_.reset(
+      [[MenuController alloc] initWithModel:contextMenuModel_.get()
+                     useWithPopUpButtonCell:NO]);
+  return [contextMenuController_ menu];
+}
+
+- (IBAction)closeTab:(id)sender {
+  if ([[self target] respondsToSelector:@selector(closeTab:)]) {
+    [[self target] performSelector:@selector(closeTab:)
+                        withObject:[self view]];
+  }
+}
+
+- (void)setTitle:(NSString*)title {
+  [[self view] setToolTip:title];
+  if ([self mini] && ![self selected]) {
+    TabView* tabView = static_cast<TabView*>([self view]);
+    DCHECK([tabView isKindOfClass:[TabView class]]);
+    [tabView startAlert];
+  }
+  [super setTitle:title];
+}
+
+- (void)setSelected:(BOOL)selected {
+  if (selected_ != selected)
+    [self internalSetSelected:selected];
+}
+
+- (BOOL)selected {
+  return selected_;
+}
+
+- (void)setIconView:(NSView*)iconView {
+  [iconView_ removeFromSuperview];
+  iconView_ = iconView;
+  if ([self app]) {
+    NSRect appIconFrame = [iconView frame];
+    appIconFrame.origin = originalIconFrame_.origin;
+    // Center the icon.
+    appIconFrame.origin.x = ([TabController appTabWidth] -
+        NSWidth(appIconFrame)) / 2.0;
+    [iconView setFrame:appIconFrame];
+  } else {
+    [iconView_ setFrame:originalIconFrame_];
+  }
+  // Ensure that the icon is suppressed if no icon is set or if the tab is too
+  // narrow to display one.
+  [self updateVisibility];
+
+  if (iconView_)
+    [[self view] addSubview:iconView_];
+}
+
+- (NSString*)toolTip {
+  return [[self view] toolTip];
+}
+
+// Return a rough approximation of the number of icons we could fit in the
+// tab. We never actually do this, but it's a helpful guide for determining
+// how much space we have available.
+- (int)iconCapacity {
+  CGFloat width = NSMaxX([closeButton_ frame]) - NSMinX(originalIconFrame_);
+  CGFloat iconWidth = NSWidth(originalIconFrame_);
+
+  return width / iconWidth;
+}
+
+// Returns YES if we should show the icon. When tabs get too small, we clip
+// the favicon before the close button for selected tabs, and prefer the
+// favicon for unselected tabs.  The icon can also be suppressed more directly
+// by clearing iconView_.
+- (BOOL)shouldShowIcon {
+  if (!iconView_)
+    return NO;
+
+  if ([self mini])
+    return YES;
+
+  int iconCapacity = [self iconCapacity];
+  if ([self selected])
+    return iconCapacity >= 2;
+  return iconCapacity >= 1;
+}
+
+// Returns YES if we should be showing the close button. The selected tab
+// always shows the close button.
+- (BOOL)shouldShowCloseButton {
+  // Accessibility: When VoiceOver is active, it is desirable for us to hide the
+  // close button, so that VoiceOver does not encounter it.
+  // TODO(dtseng): http://crbug.com/59978
+  if (BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser())
+    return NO;
+
+  if ([self mini])
+    return NO;
+  return ([self selected] || [self iconCapacity] >= 3);
+}
+
+- (void)updateVisibility {
+  // iconView_ may have been replaced or it may be nil, so [iconView_ isHidden]
+  // won't work.  Instead, the state of the icon is tracked separately in
+  // isIconShowing_.
+  BOOL newShowIcon = [self shouldShowIcon];
+
+  [iconView_ setHidden:!newShowIcon];
+  isIconShowing_ = newShowIcon;
+
+  // If the tab is a mini-tab, hide the title.
+  [titleView_ setHidden:[self mini]];
+
+  BOOL newShowCloseButton = [self shouldShowCloseButton];
+
+  [closeButton_ setHidden:!newShowCloseButton];
+
+  // Adjust the title view based on changes to the icon's and close button's
+  // visibility.
+  NSRect oldTitleFrame = [titleView_ frame];
+  NSRect newTitleFrame;
+  newTitleFrame.size.height = oldTitleFrame.size.height;
+  newTitleFrame.origin.y = oldTitleFrame.origin.y;
+
+  if (newShowIcon) {
+    newTitleFrame.origin.x = originalIconFrame_.origin.x + iconTitleXOffset_;
+  } else {
+    newTitleFrame.origin.x = originalIconFrame_.origin.x;
+  }
+
+  if (newShowCloseButton) {
+    newTitleFrame.size.width = NSMinX([closeButton_ frame]) -
+                               newTitleFrame.origin.x;
+  } else {
+    newTitleFrame.size.width = NSMaxX([closeButton_ frame]) -
+                               newTitleFrame.origin.x;
+  }
+
+  [titleView_ setFrame:newTitleFrame];
+}
+
+- (void)updateTitleColor {
+  NSColor* titleColor = nil;
+  ui::ThemeProvider* theme = [[[self view] window] themeProvider];
+  if (theme && ![self selected]) {
+    titleColor =
+        theme->GetNSColor(BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT,
+                          true);
+  }
+  // Default to the selected text color unless told otherwise.
+  if (theme && !titleColor) {
+    titleColor = theme->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT,
+                                   true);
+  }
+  [titleView_ setTextColor:titleColor ? titleColor : [NSColor textColor]];
+}
+
+// Called when our view is resized. If it gets too small, start by hiding
+// the close button and only show it if tab is selected. Eventually, hide the
+// icon as well. We know that this is for our view because we only registered
+// for notifications from our specific view.
+- (void)viewResized:(NSNotification*)info {
+  [self updateVisibility];
+}
+
+- (void)themeChangedNotification:(NSNotification*)notification {
+  [self updateTitleColor];
+}
+
+// Called by the tabs to determine whether we are in rapid (tab) closure mode.
+- (BOOL)inRapidClosureMode {
+  if ([[self target] respondsToSelector:@selector(inRapidClosureMode)]) {
+    return [[self target] performSelector:@selector(inRapidClosureMode)] ?
+        YES : NO;
+  }
+  return NO;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller_target.h b/chrome/browser/ui/cocoa/tabs/tab_controller_target.h
new file mode 100644
index 0000000..7044552
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller_target.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_CONTROLLER_TARGET_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_CONTROLLER_TARGET_H_
+#pragma once
+
+#include "chrome/browser/tabs/tab_strip_model.h"
+
+@class TabController;
+
+// A protocol to be implemented by a TabController's target.
+@protocol TabControllerTarget
+- (void)selectTab:(id)sender;
+- (void)closeTab:(id)sender;
+
+// Dispatch context menu commands for the given tab controller.
+- (void)commandDispatch:(TabStripModel::ContextMenuCommand)command
+          forController:(TabController*)controller;
+// Returns YES if the specificed command should be enabled for the given
+// controller.
+- (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command
+           forController:(TabController*)controller;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_CONTROLLER_TARGET_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
new file mode 100644
index 0000000..ef49850
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
@@ -0,0 +1,333 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+// Implements the target interface for the tab, which gets sent messages when
+// the tab is clicked on by the user and when its close box is clicked.
+@interface TabControllerTestTarget : NSObject<TabControllerTarget> {
+ @private
+  bool selected_;
+  bool closed_;
+}
+- (bool)selected;
+- (bool)closed;
+@end
+
+@implementation TabControllerTestTarget
+- (bool)selected {
+  return selected_;
+}
+- (bool)closed {
+  return closed_;
+}
+- (void)selectTab:(id)sender {
+  selected_ = true;
+}
+- (void)closeTab:(id)sender {
+  closed_ = true;
+}
+- (void)mouseTimer:(NSTimer*)timer {
+  // Fire the mouseUp to break the TabView drag loop.
+  NSEvent* current = [NSApp currentEvent];
+  NSWindow* window = [timer userInfo];
+  NSEvent* up = [NSEvent mouseEventWithType:NSLeftMouseUp
+                                   location:[current locationInWindow]
+                              modifierFlags:0
+                                  timestamp:[current timestamp]
+                               windowNumber:[window windowNumber]
+                                    context:nil
+                                eventNumber:0
+                                 clickCount:1
+                                   pressure:1.0];
+  [window postEvent:up atStart:YES];
+}
+- (void)commandDispatch:(TabStripModel::ContextMenuCommand)command
+          forController:(TabController*)controller {
+}
+- (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command
+           forController:(TabController*)controller {
+  return NO;
+}
+@end
+
+namespace {
+
+CGFloat LeftMargin(NSRect superFrame, NSRect subFrame) {
+  return NSMinX(subFrame) - NSMinX(superFrame);
+}
+
+CGFloat RightMargin(NSRect superFrame, NSRect subFrame) {
+  return NSMaxX(superFrame) - NSMaxX(subFrame);
+}
+
+// The dragging code in TabView makes heavy use of autorelease pools so
+// inherit from CocoaTest to have one created for us.
+class TabControllerTest : public CocoaTest {
+ public:
+  TabControllerTest() { }
+};
+
+// Tests creating the controller, sticking it in a window, and removing it.
+TEST_F(TabControllerTest, Creation) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+  EXPECT_TRUE([controller tabView]);
+  EXPECT_EQ([[controller view] window], window);
+  [[controller view] display];  // Test drawing to ensure nothing leaks/crashes.
+  [[controller view] removeFromSuperview];
+}
+
+// Tests sending it a close message and ensuring that the target/action get
+// called. Mimics the user clicking on the close button in the tab.
+TEST_F(TabControllerTest, Close) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+
+  scoped_nsobject<TabControllerTestTarget> target(
+      [[TabControllerTestTarget alloc] init]);
+  EXPECT_FALSE([target closed]);
+  [controller setTarget:target];
+  EXPECT_EQ(target.get(), [controller target]);
+
+  [controller closeTab:nil];
+  EXPECT_TRUE([target closed]);
+
+  [[controller view] removeFromSuperview];
+}
+
+// Tests setting the |selected| property via code.
+TEST_F(TabControllerTest, APISelection) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+
+  EXPECT_FALSE([controller selected]);
+  [controller setSelected:YES];
+  EXPECT_TRUE([controller selected]);
+
+  [[controller view] removeFromSuperview];
+}
+
+// Tests that setting the title of a tab sets the tooltip as well.
+TEST_F(TabControllerTest, ToolTip) {
+  NSWindow* window = test_window();
+
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+
+  EXPECT_TRUE([[controller toolTip] length] == 0);
+  NSString *tooltip_string = @"Some text to use as a tab title";
+  [controller setTitle:tooltip_string];
+  EXPECT_NSEQ(tooltip_string, [controller toolTip]);
+}
+
+// Tests setting the |loading| property via code.
+TEST_F(TabControllerTest, Loading) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+
+  EXPECT_EQ(kTabDone, [controller loadingState]);
+  [controller setLoadingState:kTabWaiting];
+  EXPECT_EQ(kTabWaiting, [controller loadingState]);
+  [controller setLoadingState:kTabLoading];
+  EXPECT_EQ(kTabLoading, [controller loadingState]);
+  [controller setLoadingState:kTabDone];
+  EXPECT_EQ(kTabDone, [controller loadingState]);
+
+  [[controller view] removeFromSuperview];
+}
+
+// Tests selecting the tab with the mouse click and ensuring the target/action
+// get called.
+TEST_F(TabControllerTest, UserSelection) {
+  NSWindow* window = test_window();
+
+  // Create a tab at a known location in the window that we can click on
+  // to activate selection.
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+  NSRect frame = [[controller view] frame];
+  frame.size.width = [TabController minTabWidth];
+  frame.origin = NSMakePoint(0, 0);
+  [[controller view] setFrame:frame];
+
+  // Set the target and action.
+  scoped_nsobject<TabControllerTestTarget> target(
+      [[TabControllerTestTarget alloc] init]);
+  EXPECT_FALSE([target selected]);
+  [controller setTarget:target];
+  [controller setAction:@selector(selectTab:)];
+  EXPECT_EQ(target.get(), [controller target]);
+  EXPECT_EQ(@selector(selectTab:), [controller action]);
+
+  // In order to track a click, we have to fake a mouse down and a mouse
+  // up, but the down goes into a tight drag loop. To break the loop, we have
+  // to fire a timer that sends a mouse up event while the "drag" is ongoing.
+  [NSTimer scheduledTimerWithTimeInterval:0.1
+                                   target:target.get()
+                                 selector:@selector(mouseTimer:)
+                                 userInfo:window
+                                  repeats:NO];
+  NSEvent* current = [NSApp currentEvent];
+  NSPoint click_point = NSMakePoint(frame.size.width / 2,
+                                    frame.size.height / 2);
+  NSEvent* down = [NSEvent mouseEventWithType:NSLeftMouseDown
+                                     location:click_point
+                                modifierFlags:0
+                                    timestamp:[current timestamp]
+                                 windowNumber:[window windowNumber]
+                                      context:nil
+                                  eventNumber:0
+                                   clickCount:1
+                                     pressure:1.0];
+  [[controller view] mouseDown:down];
+
+  // Check our target was told the tab got selected.
+  EXPECT_TRUE([target selected]);
+
+  [[controller view] removeFromSuperview];
+}
+
+TEST_F(TabControllerTest, IconCapacity) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+  int cap = [controller iconCapacity];
+  EXPECT_GE(cap, 1);
+
+  NSRect frame = [[controller view] frame];
+  frame.size.width += 500;
+  [[controller view] setFrame:frame];
+  int newcap = [controller iconCapacity];
+  EXPECT_GT(newcap, cap);
+}
+
+TEST_F(TabControllerTest, ShouldShowIcon) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+  int cap = [controller iconCapacity];
+  EXPECT_GT(cap, 0);
+
+  // Tab is minimum width, both icon and close box should be hidden.
+  NSRect frame = [[controller view] frame];
+  frame.size.width = [TabController minTabWidth];
+  [[controller view] setFrame:frame];
+  EXPECT_FALSE([controller shouldShowIcon]);
+  EXPECT_FALSE([controller shouldShowCloseButton]);
+
+  // Setting the icon when tab is at min width should not show icon (bug 18359).
+  scoped_nsobject<NSView> newIcon(
+      [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)]);
+  [controller setIconView:newIcon.get()];
+  EXPECT_TRUE([newIcon isHidden]);
+
+  // Tab is at selected minimum width. Since it's selected, the close box
+  // should be visible.
+  [controller setSelected:YES];
+  frame = [[controller view] frame];
+  frame.size.width = [TabController minSelectedTabWidth];
+  [[controller view] setFrame:frame];
+  EXPECT_FALSE([controller shouldShowIcon]);
+  EXPECT_TRUE([newIcon isHidden]);
+  EXPECT_TRUE([controller shouldShowCloseButton]);
+
+  // Test expanding the tab to max width and ensure the icon and close box
+  // get put back, even when de-selected.
+  frame.size.width = [TabController maxTabWidth];
+  [[controller view] setFrame:frame];
+  EXPECT_TRUE([controller shouldShowIcon]);
+  EXPECT_FALSE([newIcon isHidden]);
+  EXPECT_TRUE([controller shouldShowCloseButton]);
+  [controller setSelected:NO];
+  EXPECT_TRUE([controller shouldShowIcon]);
+  EXPECT_TRUE([controller shouldShowCloseButton]);
+
+  cap = [controller iconCapacity];
+  EXPECT_GT(cap, 0);
+}
+
+TEST_F(TabControllerTest, Menu) {
+  NSWindow* window = test_window();
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+  int cap = [controller iconCapacity];
+  EXPECT_GT(cap, 0);
+
+  // Asking the view for its menu should yield a valid menu.
+  NSMenu* menu = [[controller view] menu];
+  EXPECT_TRUE(menu);
+  EXPECT_GT([menu numberOfItems], 0);
+}
+
+// Tests that the title field is correctly positioned and sized when the
+// view is resized.
+TEST_F(TabControllerTest, TitleViewLayout) {
+  NSWindow* window = test_window();
+
+  scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  [[window contentView] addSubview:[controller view]];
+  NSRect tabFrame = [[controller view] frame];
+  tabFrame.size.width = [TabController maxTabWidth];
+  [[controller view] setFrame:tabFrame];
+
+  const NSRect originalTabFrame = [[controller view] frame];
+  const NSRect originalIconFrame = [[controller iconView] frame];
+  const NSRect originalCloseFrame = [[controller closeButton] frame];
+  const NSRect originalTitleFrame = [[controller titleView] frame];
+
+  // Sanity check the start state.
+  EXPECT_FALSE([[controller iconView] isHidden]);
+  EXPECT_FALSE([[controller closeButton] isHidden]);
+  EXPECT_GT(NSWidth([[controller view] frame]),
+            NSWidth([[controller titleView] frame]));
+
+  // Resize the tab so that that the it shrinks.
+  tabFrame.size.width = [TabController minTabWidth];
+  [[controller view] setFrame:tabFrame];
+
+  // The icon view and close button should be hidden and the title view should
+  // be resize to take up their space.
+  EXPECT_TRUE([[controller iconView] isHidden]);
+  EXPECT_TRUE([[controller closeButton] isHidden]);
+  EXPECT_GT(NSWidth([[controller view] frame]),
+            NSWidth([[controller titleView] frame]));
+  EXPECT_EQ(LeftMargin(originalTabFrame, originalIconFrame),
+            LeftMargin([[controller view] frame],
+                       [[controller titleView] frame]));
+  EXPECT_EQ(RightMargin(originalTabFrame, originalCloseFrame),
+            RightMargin([[controller view] frame],
+                        [[controller titleView] frame]));
+
+  // Resize the tab so that that the it grows.
+  tabFrame.size.width = [TabController maxTabWidth] * 0.75;
+  [[controller view] setFrame:tabFrame];
+
+  // The icon view and close button should be visible again and the title view
+  // should be resized to make room for them.
+  EXPECT_FALSE([[controller iconView] isHidden]);
+  EXPECT_FALSE([[controller closeButton] isHidden]);
+  EXPECT_GT(NSWidth([[controller view] frame]),
+            NSWidth([[controller titleView] frame]));
+  EXPECT_EQ(LeftMargin(originalTabFrame, originalTitleFrame),
+            LeftMargin([[controller view] frame],
+                       [[controller titleView] frame]));
+  EXPECT_EQ(RightMargin(originalTabFrame, originalTitleFrame),
+            RightMargin([[controller view] frame],
+                        [[controller titleView] frame]));
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
new file mode 100644
index 0000000..96a8e6b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
@@ -0,0 +1,262 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
+#import "chrome/browser/ui/cocoa/url_drop_target.h"
+#import "third_party/GTM/AppKit/GTMWindowSheetController.h"
+
+@class NewTabButton;
+@class TabContentsController;
+@class TabView;
+@class TabStripView;
+
+class Browser;
+class ConstrainedWindowMac;
+class TabStripModelObserverBridge;
+class TabStripModel;
+class TabContents;
+class ToolbarModel;
+
+// The interface for the tab strip controller's delegate.
+// Delegating TabStripModelObserverBridge's events (in lieu of directly
+// subscribing to TabStripModelObserverBridge events, as TabStripController
+// does) is necessary to guarantee a proper order of subviews layout updates,
+// otherwise it might trigger unnesessary content relayout, UI flickering etc.
+@protocol TabStripControllerDelegate
+
+// Stripped down version of TabStripModelObserverBridge:selectTabWithContents.
+- (void)onSelectTabWithContents:(TabContents*)contents;
+
+// Stripped down version of TabStripModelObserverBridge:tabReplacedWithContents.
+- (void)onReplaceTabWithContents:(TabContents*)contents;
+
+// Stripped down version of TabStripModelObserverBridge:tabChangedWithContents.
+- (void)onSelectedTabChange:(TabStripModelObserver::TabChangeType)change;
+
+// Stripped down version of TabStripModelObserverBridge:tabDetachedWithContents.
+- (void)onTabDetachedWithContents:(TabContents*)contents;
+
+@end
+
+// A class that handles managing the tab strip in a browser window. It uses
+// a supporting C++ bridge object to register for notifications from the
+// TabStripModel. The Obj-C part of this class handles drag and drop and all
+// the other Cocoa-y aspects.
+//
+// For a full description of the design, see
+// http://www.chromium.org/developers/design-documents/tab-strip-mac
+@interface TabStripController :
+  NSObject<TabControllerTarget,
+           URLDropTargetController,
+           GTMWindowSheetControllerDelegate,
+           TabContentsControllerDelegate> {
+ @protected
+  // YES if tabs are to be laid out vertically instead of horizontally.
+  BOOL verticalLayout_;
+
+ @private
+  scoped_nsobject<TabStripView> tabStripView_;
+  NSView* switchView_;  // weak
+  scoped_nsobject<NSView> dragBlockingView_;  // avoid bad window server drags
+  NewTabButton* newTabButton_;  // weak, obtained from the nib.
+
+  // Tracks the newTabButton_ for rollovers.
+  scoped_nsobject<NSTrackingArea> newTabTrackingArea_;
+  scoped_ptr<TabStripModelObserverBridge> bridge_;
+  Browser* browser_;  // weak
+  TabStripModel* tabStripModel_;  // weak
+  // Delegate that is informed about tab state changes.
+  id<TabStripControllerDelegate> delegate_;  // weak
+
+  // YES if the new tab button is currently displaying the hover image (if the
+  // mouse is currently over the button).
+  BOOL newTabButtonShowingHoverImage_;
+
+  // Access to the TabContentsControllers (which own the parent view
+  // for the toolbar and associated tab contents) given an index. Call
+  // |indexFromModelIndex:| to convert a |tabStripModel_| index to a
+  // |tabContentsArray_| index. Do NOT assume that the indices of
+  // |tabStripModel_| and this array are identical, this is e.g. not true while
+  // tabs are animating closed (closed tabs are removed from |tabStripModel_|
+  // immediately, but from |tabContentsArray_| only after their close animation
+  // has completed).
+  scoped_nsobject<NSMutableArray> tabContentsArray_;
+  // An array of TabControllers which manage the actual tab views. See note
+  // above |tabContentsArray_|. |tabContentsArray_| and |tabArray_| always
+  // contain objects belonging to the same tabs at the same indices.
+  scoped_nsobject<NSMutableArray> tabArray_;
+
+  // Set of TabControllers that are currently animating closed.
+  scoped_nsobject<NSMutableSet> closingControllers_;
+
+  // These values are only used during a drag, and override tab positioning.
+  TabView* placeholderTab_;  // weak. Tab being dragged
+  NSRect placeholderFrame_;  // Frame to use
+  CGFloat placeholderStretchiness_; // Vertical force shown by streching tab.
+  NSRect droppedTabFrame_;  // Initial frame of a dropped tab, for animation.
+  // Frame targets for all the current views.
+  // target frames are used because repeated requests to [NSView animator].
+  // aren't coalesced, so we store frames to avoid redundant calls.
+  scoped_nsobject<NSMutableDictionary> targetFrames_;
+  NSRect newTabTargetFrame_;
+  // If YES, do not show the new tab button during layout.
+  BOOL forceNewTabButtonHidden_;
+  // YES if we've successfully completed the initial layout. When this is
+  // NO, we probably don't want to do any animation because we're just coming
+  // into being.
+  BOOL initialLayoutComplete_;
+
+  // Width available for resizing the tabs (doesn't include the new tab
+  // button). Used to restrict the available width when closing many tabs at
+  // once to prevent them from resizing to fit the full width. If the entire
+  // width should be used, this will have a value of |kUseFullAvailableWidth|.
+  float availableResizeWidth_;
+  // A tracking area that's the size of the tab strip used to be notified
+  // when the mouse moves in the tab strip
+  scoped_nsobject<NSTrackingArea> trackingArea_;
+  TabView* hoveredTab_;  // weak. Tab that the mouse is hovering over
+
+  // Array of subviews which are permanent (and which should never be removed),
+  // such as the new-tab button, but *not* the tabs themselves.
+  scoped_nsobject<NSMutableArray> permanentSubviews_;
+
+  // The default favicon, so we can use one copy for all buttons.
+  scoped_nsobject<NSImage> defaultFavIcon_;
+
+  // The amount by which to indent the tabs on the left (to make room for the
+  // red/yellow/green buttons).
+  CGFloat indentForControls_;
+
+  // Manages per-tab sheets.
+  scoped_nsobject<GTMWindowSheetController> sheetController_;
+
+  // Is the mouse currently inside the strip;
+  BOOL mouseInside_;
+}
+
+@property(nonatomic) CGFloat indentForControls;
+
+// Initialize the controller with a view and browser that contains
+// everything else we'll need. |switchView| is the view whose contents get
+// "switched" every time the user switches tabs. The children of this view
+// will be released, so if you want them to stay around, make sure
+// you have retained them.
+// |delegate| is the one listening to filtered TabStripModelObserverBridge's
+// events (see TabStripControllerDelegate for more details).
+- (id)initWithView:(TabStripView*)view
+        switchView:(NSView*)switchView
+           browser:(Browser*)browser
+          delegate:(id<TabStripControllerDelegate>)delegate;
+
+// Return the view for the currently selected tab.
+- (NSView*)selectedTabView;
+
+// Set the frame of the selected tab, also updates the internal frame dict.
+- (void)setFrameOfSelectedTab:(NSRect)frame;
+
+// Move the given tab at index |from| in this window to the location of the
+// current placeholder.
+- (void)moveTabFromIndex:(NSInteger)from;
+
+// Drop a given TabContents at the location of the current placeholder. If there
+// is no placeholder, it will go at the end. Used when dragging from another
+// window when we don't have access to the TabContents as part of our strip.
+// |frame| is in the coordinate system of the tab strip view and represents
+// where the user dropped the new tab so it can be animated into its correct
+// location when the tab is added to the model. If the tab was pinned in its
+// previous window, setting |pinned| to YES will propagate that state to the
+// new window. Mini-tabs are either app or pinned tabs; the app state is stored
+// by the |contents|, but the |pinned| state is the caller's responsibility.
+- (void)dropTabContents:(TabContentsWrapper*)contents
+              withFrame:(NSRect)frame
+            asPinnedTab:(BOOL)pinned;
+
+// Returns the index of the subview |view|. Returns -1 if not present. Takes
+// closing tabs into account such that this index will correctly match the tab
+// model. If |view| is in the process of closing, returns -1, as closing tabs
+// are no longer in the model.
+- (NSInteger)modelIndexForTabView:(NSView*)view;
+
+// Return the view at a given index.
+- (NSView*)viewAtIndex:(NSUInteger)index;
+
+// Return the number of tab views in the tab strip. It's same as number of tabs
+// in the model, except when a tab is closing, which will be counted in views
+// count, but no longer in the model.
+- (NSUInteger)viewsCount;
+
+// Set the placeholder for a dragged tab, allowing the |frame| and |strechiness|
+// to be specified. This causes this tab to be rendered in an arbitrary position
+- (void)insertPlaceholderForTab:(TabView*)tab
+                          frame:(NSRect)frame
+                  yStretchiness:(CGFloat)yStretchiness;
+
+// Returns whether a tab is being dragged within the tab strip.
+- (BOOL)isDragSessionActive;
+
+// Returns whether or not |tab| can still be fully seen in the tab strip or if
+// its current position would cause it be obscured by things such as the edge
+// of the window or the window decorations. Returns YES only if the entire tab
+// is visible.
+- (BOOL)isTabFullyVisible:(TabView*)tab;
+
+// Show or hide the new tab button. The button is hidden immediately, but
+// waits until the next call to |-layoutTabs| to show it again.
+- (void)showNewTabButton:(BOOL)show;
+
+// Force the tabs to rearrange themselves to reflect the current model.
+- (void)layoutTabs;
+
+// Are we in rapid (tab) closure mode? I.e., is a full layout deferred (while
+// the user closes tabs)? Needed to overcome missing clicks during rapid tab
+// closure.
+- (BOOL)inRapidClosureMode;
+
+// Returns YES if the user is allowed to drag tabs on the strip at this moment.
+// For example, this returns NO if there are any pending tab close animtations.
+- (BOOL)tabDraggingAllowed;
+
+// Default height for tabs.
++ (CGFloat)defaultTabHeight;
+
+// Default indentation for tabs (see |indentForControls_|).
++ (CGFloat)defaultIndentForControls;
+
+// Returns the (lazily created) window sheet controller of this window. Used
+// for the per-tab sheets.
+- (GTMWindowSheetController*)sheetController;
+
+// Destroys the window sheet controller of this window, if it exists.  The sheet
+// controller can be recreated by a subsequent call to |-sheetController|.  Must
+// not be called if any sheets are currently open.
+// TODO(viettrungluu): This is temporary code needed to allow sheets to work
+// (read: not crash) in fullscreen mode.  Once GTMWindowSheetController is
+// modified to support moving sheets between windows, this code can go away.
+// http://crbug.com/19093.
+- (void)destroySheetController;
+
+// Returns the currently active TabContentsController.
+- (TabContentsController*)activeTabContentsController;
+
+  // See comments in browser_window_controller.h for documentation about these
+  // functions.
+- (void)attachConstrainedWindow:(ConstrainedWindowMac*)window;
+- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window;
+
+@end
+
+// Notification sent when the number of tabs changes. The object will be this
+// controller.
+extern NSString* const kTabStripNumberOfTabsChanged;
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
new file mode 100644
index 0000000..93048d4
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -0,0 +1,1903 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+
+#import <QuartzCore/QuartzCore.h>
+
+#include <limits>
+#include <string>
+
+#include "app/mac/nsimage_cache.h"
+#include "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/debugger/devtools_window.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/sidebar/sidebar_container.h"
+#include "chrome/browser/sidebar/sidebar_manager.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/constrained_window_mac.h"
+#import "chrome/browser/ui/cocoa/new_tab_button.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_view.h"
+#import "chrome/browser/ui/cocoa/tabs/throbber_view.h"
+#include "chrome/browser/ui/find_bar/find_bar.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+NSString* const kTabStripNumberOfTabsChanged = @"kTabStripNumberOfTabsChanged";
+
+namespace {
+
+// The images names used for different states of the new tab button.
+NSString* const kNewTabHoverImage = @"newtab_h.pdf";
+NSString* const kNewTabImage = @"newtab.pdf";
+NSString* const kNewTabPressedImage = @"newtab_p.pdf";
+
+// A value to indicate tab layout should use the full available width of the
+// view.
+const CGFloat kUseFullAvailableWidth = -1.0;
+
+// The amount by which tabs overlap.
+const CGFloat kTabOverlap = 20.0;
+
+// The width and height for a tab's icon.
+const CGFloat kIconWidthAndHeight = 16.0;
+
+// The amount by which the new tab button is offset (from the tabs).
+const CGFloat kNewTabButtonOffset = 8.0;
+
+// The amount by which to shrink the tab strip (on the right) when the
+// incognito badge is present.
+const CGFloat kIncognitoBadgeTabStripShrink = 18;
+
+// Time (in seconds) in which tabs animate to their final position.
+const NSTimeInterval kAnimationDuration = 0.125;
+
+// Helper class for doing NSAnimationContext calls that takes a bool to disable
+// all the work.  Useful for code that wants to conditionally animate.
+class ScopedNSAnimationContextGroup {
+ public:
+  explicit ScopedNSAnimationContextGroup(bool animate)
+      : animate_(animate) {
+    if (animate_) {
+      [NSAnimationContext beginGrouping];
+    }
+  }
+
+  ~ScopedNSAnimationContextGroup() {
+    if (animate_) {
+      [NSAnimationContext endGrouping];
+    }
+  }
+
+  void SetCurrentContextDuration(NSTimeInterval duration) {
+    if (animate_) {
+      [[NSAnimationContext currentContext] gtm_setDuration:duration
+                                                 eventMask:NSLeftMouseUpMask];
+    }
+  }
+
+  void SetCurrentContextShortestDuration() {
+    if (animate_) {
+      // The minimum representable time interval.  This used to stop an
+      // in-progress animation as quickly as possible.
+      const NSTimeInterval kMinimumTimeInterval =
+          std::numeric_limits<NSTimeInterval>::min();
+      // Directly set the duration to be short, avoiding the Steve slowmotion
+      // ettect the gtm_setDuration: provides.
+      [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval];
+    }
+  }
+
+private:
+  bool animate_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedNSAnimationContextGroup);
+};
+
+}  // namespace
+
+@interface TabStripController (Private)
+- (void)installTrackingArea;
+- (void)addSubviewToPermanentList:(NSView*)aView;
+- (void)regenerateSubviewList;
+- (NSInteger)indexForContentsView:(NSView*)view;
+- (void)updateFavIconForContents:(TabContents*)contents
+                         atIndex:(NSInteger)modelIndex;
+- (void)layoutTabsWithAnimation:(BOOL)animate
+             regenerateSubviews:(BOOL)doUpdate;
+- (void)animationDidStopForController:(TabController*)controller
+                             finished:(BOOL)finished;
+- (NSInteger)indexFromModelIndex:(NSInteger)index;
+- (NSInteger)numberOfOpenTabs;
+- (NSInteger)numberOfOpenMiniTabs;
+- (NSInteger)numberOfOpenNonMiniTabs;
+- (void)mouseMoved:(NSEvent*)event;
+- (void)setTabTrackingAreasEnabled:(BOOL)enabled;
+- (void)droppingURLsAt:(NSPoint)point
+            givesIndex:(NSInteger*)index
+           disposition:(WindowOpenDisposition*)disposition;
+- (void)setNewTabButtonHoverState:(BOOL)showHover;
+@end
+
+// A simple view class that prevents the Window Server from dragging the area
+// behind tabs. Sometimes core animation confuses it. Unfortunately, it can also
+// falsely pick up clicks during rapid tab closure, so we have to account for
+// that.
+@interface TabStripControllerDragBlockingView : NSView {
+  TabStripController* controller_;  // weak; owns us
+}
+
+- (id)initWithFrame:(NSRect)frameRect
+         controller:(TabStripController*)controller;
+@end
+
+@implementation TabStripControllerDragBlockingView
+- (BOOL)mouseDownCanMoveWindow {return NO;}
+- (void)drawRect:(NSRect)rect {}
+
+- (id)initWithFrame:(NSRect)frameRect
+         controller:(TabStripController*)controller {
+  if ((self = [super initWithFrame:frameRect]))
+    controller_ = controller;
+  return self;
+}
+
+// In "rapid tab closure" mode (i.e., the user is clicking close tab buttons in
+// rapid succession), the animations confuse Cocoa's hit testing (which appears
+// to use cached results, among other tricks), so this view can somehow end up
+// getting a mouse down event. Thus we do an explicit hit test during rapid tab
+// closure, and if we find that we got a mouse down we shouldn't have, we send
+// it off to the appropriate view.
+- (void)mouseDown:(NSEvent*)event {
+  if ([controller_ inRapidClosureMode]) {
+    NSView* superview = [self superview];
+    NSPoint hitLocation =
+        [[superview superview] convertPoint:[event locationInWindow]
+                                   fromView:nil];
+    NSView* hitView = [superview hitTest:hitLocation];
+    if (hitView != self) {
+      [hitView mouseDown:event];
+      return;
+    }
+  }
+  [super mouseDown:event];
+}
+@end
+
+#pragma mark -
+
+// A delegate, owned by the CAAnimation system, that is alerted when the
+// animation to close a tab is completed. Calls back to the given tab strip
+// to let it know that |controller_| is ready to be removed from the model.
+// Since we only maintain weak references, the tab strip must call -invalidate:
+// to prevent the use of dangling pointers.
+@interface TabCloseAnimationDelegate : NSObject {
+ @private
+  TabStripController* strip_;  // weak; owns us indirectly
+  TabController* controller_;  // weak
+}
+
+// Will tell |strip| when the animation for |controller|'s view has completed.
+// These should not be nil, and will not be retained.
+- (id)initWithTabStrip:(TabStripController*)strip
+         tabController:(TabController*)controller;
+
+// Invalidates this object so that no further calls will be made to
+// |strip_|.  This should be called when |strip_| is released, to
+// prevent attempts to call into the released object.
+- (void)invalidate;
+
+// CAAnimation delegate method
+- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished;
+
+@end
+
+@implementation TabCloseAnimationDelegate
+
+- (id)initWithTabStrip:(TabStripController*)strip
+         tabController:(TabController*)controller {
+  if ((self = [super init])) {
+    DCHECK(strip && controller);
+    strip_ = strip;
+    controller_ = controller;
+  }
+  return self;
+}
+
+- (void)invalidate {
+  strip_ = nil;
+  controller_ = nil;
+}
+
+- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
+  [strip_ animationDidStopForController:controller_ finished:finished];
+}
+
+@end
+
+#pragma mark -
+
+// In general, there is a one-to-one correspondence between TabControllers,
+// TabViews, TabContentsControllers, and the TabContents in the TabStripModel.
+// In the steady-state, the indices line up so an index coming from the model
+// is directly mapped to the same index in the parallel arrays holding our
+// views and controllers. This is also true when new tabs are created (even
+// though there is a small period of animation) because the tab is present
+// in the model while the TabView is animating into place. As a result, nothing
+// special need be done to handle "new tab" animation.
+//
+// This all goes out the window with the "close tab" animation. The animation
+// kicks off in |-tabDetachedWithContents:atIndex:| with the notification that
+// the tab has been removed from the model. The simplest solution at this
+// point would be to remove the views and controllers as well, however once
+// the TabView is removed from the view list, the tab z-order code takes care of
+// removing it from the tab strip and we'll get no animation. That means if
+// there is to be any visible animation, the TabView needs to stay around until
+// its animation is complete. In order to maintain consistency among the
+// internal parallel arrays, this means all structures are kept around until
+// the animation completes. At this point, though, the model and our internal
+// structures are out of sync: the indices no longer line up. As a result,
+// there is a concept of a "model index" which represents an index valid in
+// the TabStripModel. During steady-state, the "model index" is just the same
+// index as our parallel arrays (as above), but during tab close animations,
+// it is different, offset by the number of tabs preceding the index which
+// are undergoing tab closing animation. As a result, the caller needs to be
+// careful to use the available conversion routines when accessing the internal
+// parallel arrays (e.g., -indexFromModelIndex:). Care also needs to be taken
+// during tab layout to ignore closing tabs in the total width calculations and
+// in individual tab positioning (to avoid moving them right back to where they
+// were).
+//
+// In order to prevent actions being taken on tabs which are closing, the tab
+// itself gets marked as such so it no longer will send back its select action
+// or allow itself to be dragged. In addition, drags on the tab strip as a
+// whole are disabled while there are tabs closing.
+
+@implementation TabStripController
+
+@synthesize indentForControls = indentForControls_;
+
+- (id)initWithView:(TabStripView*)view
+        switchView:(NSView*)switchView
+           browser:(Browser*)browser
+          delegate:(id<TabStripControllerDelegate>)delegate {
+  DCHECK(view && switchView && browser && delegate);
+  if ((self = [super init])) {
+    tabStripView_.reset([view retain]);
+    switchView_ = switchView;
+    browser_ = browser;
+    tabStripModel_ = browser_->tabstrip_model();
+    delegate_ = delegate;
+    bridge_.reset(new TabStripModelObserverBridge(tabStripModel_, self));
+    tabContentsArray_.reset([[NSMutableArray alloc] init]);
+    tabArray_.reset([[NSMutableArray alloc] init]);
+
+    // Important note: any non-tab subviews not added to |permanentSubviews_|
+    // (see |-addSubviewToPermanentList:|) will be wiped out.
+    permanentSubviews_.reset([[NSMutableArray alloc] init]);
+
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    defaultFavIcon_.reset([rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON) retain]);
+
+    [self setIndentForControls:[[self class] defaultIndentForControls]];
+
+    // TODO(viettrungluu): WTF? "For some reason, if the view is present in the
+    // nib a priori, it draws correctly. If we create it in code and add it to
+    // the tab view, it draws with all sorts of crazy artifacts."
+    newTabButton_ = [view newTabButton];
+    [self addSubviewToPermanentList:newTabButton_];
+    [newTabButton_ setTarget:nil];
+    [newTabButton_ setAction:@selector(commandDispatch:)];
+    [newTabButton_ setTag:IDC_NEW_TAB];
+    // Set the images from code because Cocoa fails to find them in our sub
+    // bundle during tests.
+    [newTabButton_ setImage:app::mac::GetCachedImageWithName(kNewTabImage)];
+    [newTabButton_ setAlternateImage:
+        app::mac::GetCachedImageWithName(kNewTabPressedImage)];
+    newTabButtonShowingHoverImage_ = NO;
+    newTabTrackingArea_.reset(
+        [[NSTrackingArea alloc] initWithRect:[newTabButton_ bounds]
+                                     options:(NSTrackingMouseEnteredAndExited |
+                                              NSTrackingActiveAlways)
+                                       owner:self
+                                    userInfo:nil]);
+    [newTabButton_ addTrackingArea:newTabTrackingArea_.get()];
+    targetFrames_.reset([[NSMutableDictionary alloc] init]);
+
+    dragBlockingView_.reset(
+        [[TabStripControllerDragBlockingView alloc] initWithFrame:NSZeroRect
+                                                       controller:self]);
+    [self addSubviewToPermanentList:dragBlockingView_];
+
+    newTabTargetFrame_ = NSMakeRect(0, 0, 0, 0);
+    availableResizeWidth_ = kUseFullAvailableWidth;
+
+    closingControllers_.reset([[NSMutableSet alloc] init]);
+
+    // Install the permanent subviews.
+    [self regenerateSubviewList];
+
+    // Watch for notifications that the tab strip view has changed size so
+    // we can tell it to layout for the new size.
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(tabViewFrameChanged:)
+               name:NSViewFrameDidChangeNotification
+             object:tabStripView_];
+
+    trackingArea_.reset([[NSTrackingArea alloc]
+        initWithRect:NSZeroRect  // Ignored by NSTrackingInVisibleRect
+             options:NSTrackingMouseEnteredAndExited |
+                     NSTrackingMouseMoved |
+                     NSTrackingActiveAlways |
+                     NSTrackingInVisibleRect
+               owner:self
+            userInfo:nil]);
+    [tabStripView_ addTrackingArea:trackingArea_.get()];
+
+    // Check to see if the mouse is currently in our bounds so we can
+    // enable the tracking areas.  Otherwise we won't get hover states
+    // or tab gradients if we load the window up under the mouse.
+    NSPoint mouseLoc = [[view window] mouseLocationOutsideOfEventStream];
+    mouseLoc = [view convertPoint:mouseLoc fromView:nil];
+    if (NSPointInRect(mouseLoc, [view bounds])) {
+      [self setTabTrackingAreasEnabled:YES];
+      mouseInside_ = YES;
+    }
+
+    // Set accessibility descriptions. http://openradar.appspot.com/7496255
+    NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_NEWTAB);
+    [[newTabButton_ cell]
+        accessibilitySetOverrideValue:description
+                         forAttribute:NSAccessibilityDescriptionAttribute];
+
+    // Controller may have been (re-)created by switching layout modes, which
+    // means the tab model is already fully formed with tabs. Need to walk the
+    // list and create the UI for each.
+    const int existingTabCount = tabStripModel_->count();
+    const TabContentsWrapper* selection =
+        tabStripModel_->GetSelectedTabContents();
+    for (int i = 0; i < existingTabCount; ++i) {
+      TabContentsWrapper* currentContents = tabStripModel_->GetTabContentsAt(i);
+      [self insertTabWithContents:currentContents
+                          atIndex:i
+                     inForeground:NO];
+      if (selection == currentContents) {
+        // Must manually force a selection since the model won't send
+        // selection messages in this scenario.
+        [self selectTabWithContents:currentContents
+                   previousContents:NULL
+                            atIndex:i
+                        userGesture:NO];
+      }
+    }
+    // Don't lay out the tabs until after the controller has been fully
+    // constructed. The |verticalLayout_| flag has not been initialized by
+    // subclasses at this point, which would cause layout to potentially use
+    // the wrong mode.
+    if (existingTabCount) {
+      [self performSelectorOnMainThread:@selector(layoutTabs)
+                             withObject:nil
+                          waitUntilDone:NO];
+    }
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if (trackingArea_.get())
+    [tabStripView_ removeTrackingArea:trackingArea_.get()];
+
+  [newTabButton_ removeTrackingArea:newTabTrackingArea_.get()];
+  // Invalidate all closing animations so they don't call back to us after
+  // we're gone.
+  for (TabController* controller in closingControllers_.get()) {
+    NSView* view = [controller view];
+    [[[view animationForKey:@"frameOrigin"] delegate] invalidate];
+  }
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
++ (CGFloat)defaultTabHeight {
+  return 25.0;
+}
+
++ (CGFloat)defaultIndentForControls {
+  // Default indentation leaves enough room so tabs don't overlap with the
+  // window controls.
+  return 70.0;
+}
+
+// Finds the TabContentsController associated with the given index into the tab
+// model and swaps out the sole child of the contentArea to display its
+// contents.
+- (void)swapInTabAtIndex:(NSInteger)modelIndex {
+  DCHECK(modelIndex >= 0 && modelIndex < tabStripModel_->count());
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+  TabContentsController* controller = [tabContentsArray_ objectAtIndex:index];
+
+  // Resize the new view to fit the window. Calling |view| may lazily
+  // instantiate the TabContentsController from the nib. Until we call
+  // |-ensureContentsVisible|, the controller doesn't install the RWHVMac into
+  // the view hierarchy. This is in order to avoid sending the renderer a
+  // spurious default size loaded from the nib during the call to |-view|.
+  NSView* newView = [controller view];
+
+  // Turns content autoresizing off, so removing and inserting views won't
+  // trigger unnecessary content relayout.
+  [controller ensureContentsSizeDoesNotChange];
+
+  // Remove the old view from the view hierarchy. We know there's only one
+  // child of |switchView_| because we're the one who put it there. There
+  // may not be any children in the case of a tab that's been closed, in
+  // which case there's no swapping going on.
+  NSArray* subviews = [switchView_ subviews];
+  if ([subviews count]) {
+    NSView* oldView = [subviews objectAtIndex:0];
+    // Set newView frame to the oldVew frame to prevent NSSplitView hosting
+    // sidebar and tab content from resizing sidebar's content view.
+    // ensureContentsVisible (see below) sets content size and autoresizing
+    // properties.
+    [newView setFrame:[oldView frame]];
+    [switchView_ replaceSubview:oldView with:newView];
+  } else {
+    [newView setFrame:[switchView_ bounds]];
+    [switchView_ addSubview:newView];
+  }
+
+  // New content is in place, delegate should adjust itself accordingly.
+  [delegate_ onSelectTabWithContents:[controller tabContents]];
+
+  // It also restores content autoresizing properties.
+  [controller ensureContentsVisible];
+
+  // Make sure the new tabs's sheets are visible (necessary when a background
+  // tab opened a sheet while it was in the background and now becomes active).
+  TabContentsWrapper* newTab = tabStripModel_->GetTabContentsAt(modelIndex);
+  DCHECK(newTab);
+  if (newTab) {
+    TabContents::ConstrainedWindowList::iterator it, end;
+    end = newTab->tab_contents()->constrained_window_end();
+    NSWindowController* controller = [[newView window] windowController];
+    DCHECK([controller isKindOfClass:[BrowserWindowController class]]);
+
+    for (it = newTab->tab_contents()->constrained_window_begin();
+         it != end;
+         ++it) {
+      ConstrainedWindow* constrainedWindow = *it;
+      static_cast<ConstrainedWindowMac*>(constrainedWindow)->Realize(
+          static_cast<BrowserWindowController*>(controller));
+    }
+  }
+
+  // Tell per-tab sheet manager about currently selected tab.
+  if (sheetController_.get()) {
+    [sheetController_ setActiveView:newView];
+  }
+}
+
+// Create a new tab view and set its cell correctly so it draws the way we want
+// it to. It will be sized and positioned by |-layoutTabs| so there's no need to
+// set the frame here. This also creates the view as hidden, it will be
+// shown during layout.
+- (TabController*)newTab {
+  TabController* controller = [[[TabController alloc] init] autorelease];
+  [controller setTarget:self];
+  [controller setAction:@selector(selectTab:)];
+  [[controller view] setHidden:YES];
+
+  return controller;
+}
+
+// (Private) Returns the number of open tabs in the tab strip. This is the
+// number of TabControllers we know about (as there's a 1-to-1 mapping from
+// these controllers to a tab) less the number of closing tabs.
+- (NSInteger)numberOfOpenTabs {
+  return static_cast<NSInteger>(tabStripModel_->count());
+}
+
+// (Private) Returns the number of open, mini-tabs.
+- (NSInteger)numberOfOpenMiniTabs {
+  // Ask the model for the number of mini tabs. Note that tabs which are in
+  // the process of closing (i.e., whose controllers are in
+  // |closingControllers_|) have already been removed from the model.
+  return tabStripModel_->IndexOfFirstNonMiniTab();
+}
+
+// (Private) Returns the number of open, non-mini tabs.
+- (NSInteger)numberOfOpenNonMiniTabs {
+  NSInteger number = [self numberOfOpenTabs] - [self numberOfOpenMiniTabs];
+  DCHECK_GE(number, 0);
+  return number;
+}
+
+// Given an index into the tab model, returns the index into the tab controller
+// or tab contents controller array accounting for tabs that are currently
+// closing. For example, if there are two tabs in the process of closing before
+// |index|, this returns |index| + 2. If there are no closing tabs, this will
+// return |index|.
+- (NSInteger)indexFromModelIndex:(NSInteger)index {
+  DCHECK(index >= 0);
+  if (index < 0)
+    return index;
+
+  NSInteger i = 0;
+  for (TabController* controller in tabArray_.get()) {
+    if ([closingControllers_ containsObject:controller]) {
+      DCHECK([(TabView*)[controller view] isClosing]);
+      ++index;
+    }
+    if (i == index)  // No need to check anything after, it has no effect.
+      break;
+    ++i;
+  }
+  return index;
+}
+
+
+// Returns the index of the subview |view|. Returns -1 if not present. Takes
+// closing tabs into account such that this index will correctly match the tab
+// model. If |view| is in the process of closing, returns -1, as closing tabs
+// are no longer in the model.
+- (NSInteger)modelIndexForTabView:(NSView*)view {
+  NSInteger index = 0;
+  for (TabController* current in tabArray_.get()) {
+    // If |current| is closing, skip it.
+    if ([closingControllers_ containsObject:current])
+      continue;
+    else if ([current view] == view)
+      return index;
+    ++index;
+  }
+  return -1;
+}
+
+// Returns the index of the contents subview |view|. Returns -1 if not present.
+// Takes closing tabs into account such that this index will correctly match the
+// tab model. If |view| is in the process of closing, returns -1, as closing
+// tabs are no longer in the model.
+- (NSInteger)modelIndexForContentsView:(NSView*)view {
+  NSInteger index = 0;
+  NSInteger i = 0;
+  for (TabContentsController* current in tabContentsArray_.get()) {
+    // If the TabController corresponding to |current| is closing, skip it.
+    TabController* controller = [tabArray_ objectAtIndex:i];
+    if ([closingControllers_ containsObject:controller]) {
+      ++i;
+      continue;
+    } else if ([current view] == view) {
+      return index;
+    }
+    ++index;
+    ++i;
+  }
+  return -1;
+}
+
+
+// Returns the view at the given index, using the array of TabControllers to
+// get the associated view. Returns nil if out of range.
+- (NSView*)viewAtIndex:(NSUInteger)index {
+  if (index >= [tabArray_ count])
+    return NULL;
+  return [[tabArray_ objectAtIndex:index] view];
+}
+
+- (NSUInteger)viewsCount {
+  return [tabArray_ count];
+}
+
+// Called when the user clicks a tab. Tell the model the selection has changed,
+// which feeds back into us via a notification.
+- (void)selectTab:(id)sender {
+  DCHECK([sender isKindOfClass:[NSView class]]);
+  int index = [self modelIndexForTabView:sender];
+  if (tabStripModel_->ContainsIndex(index))
+    tabStripModel_->SelectTabContentsAt(index, true);
+}
+
+// Called when the user closes a tab. Asks the model to close the tab. |sender|
+// is the TabView that is potentially going away.
+- (void)closeTab:(id)sender {
+  DCHECK([sender isKindOfClass:[TabView class]]);
+  if ([hoveredTab_ isEqual:sender]) {
+    hoveredTab_ = nil;
+  }
+
+  NSInteger index = [self modelIndexForTabView:sender];
+  if (!tabStripModel_->ContainsIndex(index))
+    return;
+
+  TabContentsWrapper* contents = tabStripModel_->GetTabContentsAt(index);
+  if (contents)
+    UserMetrics::RecordAction(UserMetricsAction("CloseTab_Mouse"),
+                              contents->tab_contents()->profile());
+  const NSInteger numberOfOpenTabs = [self numberOfOpenTabs];
+  if (numberOfOpenTabs > 1) {
+    bool isClosingLastTab = index == numberOfOpenTabs - 1;
+    if (!isClosingLastTab) {
+      // Limit the width available for laying out tabs so that tabs are not
+      // resized until a later time (when the mouse leaves the tab strip).
+      // However, if the tab being closed is a pinned tab, break out of
+      // rapid-closure mode since the mouse is almost guaranteed not to be over
+      // the closebox of the adjacent tab (due to the difference in widths).
+      // TODO(pinkerton): re-visit when handling tab overflow.
+      // http://crbug.com/188
+      if (tabStripModel_->IsTabPinned(index)) {
+        availableResizeWidth_ = kUseFullAvailableWidth;
+      } else {
+        NSView* penultimateTab = [self viewAtIndex:numberOfOpenTabs - 2];
+        availableResizeWidth_ = NSMaxX([penultimateTab frame]);
+      }
+    } else {
+      // If the rightmost tab is closed, change the available width so that
+      // another tab's close button lands below the cursor (assuming the tabs
+      // are currently below their maximum width and can grow).
+      NSView* lastTab = [self viewAtIndex:numberOfOpenTabs - 1];
+      availableResizeWidth_ = NSMaxX([lastTab frame]);
+    }
+    tabStripModel_->CloseTabContentsAt(
+        index,
+        TabStripModel::CLOSE_USER_GESTURE |
+        TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
+  } else {
+    // Use the standard window close if this is the last tab
+    // this prevents the tab from being removed from the model until after
+    // the window dissapears
+    [[tabStripView_ window] performClose:nil];
+  }
+}
+
+// Dispatch context menu commands for the given tab controller.
+- (void)commandDispatch:(TabStripModel::ContextMenuCommand)command
+          forController:(TabController*)controller {
+  int index = [self modelIndexForTabView:[controller view]];
+  if (tabStripModel_->ContainsIndex(index))
+    tabStripModel_->ExecuteContextMenuCommand(index, command);
+}
+
+// Returns YES if the specificed command should be enabled for the given
+// controller.
+- (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command
+           forController:(TabController*)controller {
+  int index = [self modelIndexForTabView:[controller view]];
+  if (!tabStripModel_->ContainsIndex(index))
+    return NO;
+  return tabStripModel_->IsContextMenuCommandEnabled(index, command) ? YES : NO;
+}
+
+- (void)insertPlaceholderForTab:(TabView*)tab
+                          frame:(NSRect)frame
+                  yStretchiness:(CGFloat)yStretchiness {
+  placeholderTab_ = tab;
+  placeholderFrame_ = frame;
+  placeholderStretchiness_ = yStretchiness;
+  [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:NO];
+}
+
+- (BOOL)isDragSessionActive {
+  return placeholderTab_ != nil;
+}
+
+- (BOOL)isTabFullyVisible:(TabView*)tab {
+  NSRect frame = [tab frame];
+  return NSMinX(frame) >= [self indentForControls] &&
+      NSMaxX(frame) <= NSMaxX([tabStripView_ frame]);
+}
+
+- (void)showNewTabButton:(BOOL)show {
+  forceNewTabButtonHidden_ = show ? NO : YES;
+  if (forceNewTabButtonHidden_)
+    [newTabButton_ setHidden:YES];
+}
+
+// Lay out all tabs in the order of their TabContentsControllers, which matches
+// the ordering in the TabStripModel. This call isn't that expensive, though
+// it is O(n) in the number of tabs. Tabs will animate to their new position
+// if the window is visible and |animate| is YES.
+// TODO(pinkerton): Note this doesn't do too well when the number of min-sized
+// tabs would cause an overflow. http://crbug.com/188
+- (void)layoutTabsWithAnimation:(BOOL)animate
+             regenerateSubviews:(BOOL)doUpdate {
+  DCHECK([NSThread isMainThread]);
+  if (![tabArray_ count])
+    return;
+
+  const CGFloat kMaxTabWidth = [TabController maxTabWidth];
+  const CGFloat kMinTabWidth = [TabController minTabWidth];
+  const CGFloat kMinSelectedTabWidth = [TabController minSelectedTabWidth];
+  const CGFloat kMiniTabWidth = [TabController miniTabWidth];
+  const CGFloat kAppTabWidth = [TabController appTabWidth];
+
+  NSRect enclosingRect = NSZeroRect;
+  ScopedNSAnimationContextGroup mainAnimationGroup(animate);
+  mainAnimationGroup.SetCurrentContextDuration(kAnimationDuration);
+
+  // Update the current subviews and their z-order if requested.
+  if (doUpdate)
+    [self regenerateSubviewList];
+
+  // Compute the base width of tabs given how much room we're allowed. Note that
+  // mini-tabs have a fixed width. We may not be able to use the entire width
+  // if the user is quickly closing tabs. This may be negative, but that's okay
+  // (taken care of by |MAX()| when calculating tab sizes).
+  CGFloat availableSpace = 0;
+  if (verticalLayout_) {
+    availableSpace = NSHeight([tabStripView_ bounds]);
+  } else {
+    if ([self inRapidClosureMode]) {
+      availableSpace = availableResizeWidth_;
+    } else {
+      availableSpace = NSWidth([tabStripView_ frame]);
+      // Account for the new tab button and the incognito badge.
+      availableSpace -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset;
+      if (browser_->profile()->IsOffTheRecord())
+        availableSpace -= kIncognitoBadgeTabStripShrink;
+    }
+    availableSpace -= [self indentForControls];
+  }
+
+  // This may be negative, but that's okay (taken care of by |MAX()| when
+  // calculating tab sizes). "mini" tabs in horizontal mode just get a special
+  // section, they don't change size.
+  CGFloat availableSpaceForNonMini = availableSpace;
+  if (!verticalLayout_) {
+      availableSpaceForNonMini -=
+          [self numberOfOpenMiniTabs] * (kMiniTabWidth - kTabOverlap);
+  }
+
+  // Initialize |nonMiniTabWidth| in case there aren't any non-mini-tabs; this
+  // value shouldn't actually be used.
+  CGFloat nonMiniTabWidth = kMaxTabWidth;
+  const NSInteger numberOfOpenNonMiniTabs = [self numberOfOpenNonMiniTabs];
+  if (!verticalLayout_ && numberOfOpenNonMiniTabs) {
+    // Find the width of a non-mini-tab. This only applies to horizontal
+    // mode. Add in the amount we "get back" from the tabs overlapping.
+    availableSpaceForNonMini += (numberOfOpenNonMiniTabs - 1) * kTabOverlap;
+
+    // Divide up the space between the non-mini-tabs.
+    nonMiniTabWidth = availableSpaceForNonMini / numberOfOpenNonMiniTabs;
+
+    // Clamp the width between the max and min.
+    nonMiniTabWidth = MAX(MIN(nonMiniTabWidth, kMaxTabWidth), kMinTabWidth);
+  }
+
+  BOOL visible = [[tabStripView_ window] isVisible];
+
+  CGFloat offset = [self indentForControls];
+  bool hasPlaceholderGap = false;
+  for (TabController* tab in tabArray_.get()) {
+    // Ignore a tab that is going through a close animation.
+    if ([closingControllers_ containsObject:tab])
+      continue;
+
+    BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_];
+    NSRect tabFrame = [[tab view] frame];
+    tabFrame.size.height = [[self class] defaultTabHeight] + 1;
+    if (verticalLayout_) {
+      tabFrame.origin.y = availableSpace - tabFrame.size.height - offset;
+      tabFrame.origin.x = 0;
+    } else {
+      tabFrame.origin.y = 0;
+      tabFrame.origin.x = offset;
+    }
+    // If the tab is hidden, we consider it a new tab. We make it visible
+    // and animate it in.
+    BOOL newTab = [[tab view] isHidden];
+    if (newTab)
+      [[tab view] setHidden:NO];
+
+    if (isPlaceholder) {
+      // Move the current tab to the correct location instantly.
+      // We need a duration or else it doesn't cancel an inflight animation.
+      ScopedNSAnimationContextGroup localAnimationGroup(animate);
+      localAnimationGroup.SetCurrentContextShortestDuration();
+      if (verticalLayout_)
+        tabFrame.origin.y = availableSpace - tabFrame.size.height - offset;
+      else
+        tabFrame.origin.x = placeholderFrame_.origin.x;
+      // TODO(alcor): reenable this
+      //tabFrame.size.height += 10.0 * placeholderStretchiness_;
+      id target = animate ? [[tab view] animator] : [tab view];
+      [target setFrame:tabFrame];
+
+      // Store the frame by identifier to aviod redundant calls to animator.
+      NSValue* identifier = [NSValue valueWithPointer:[tab view]];
+      [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
+                        forKey:identifier];
+      continue;
+    }
+
+    if (placeholderTab_ && !hasPlaceholderGap) {
+      const CGFloat placeholderMin =
+          verticalLayout_ ? NSMinY(placeholderFrame_) :
+                            NSMinX(placeholderFrame_);
+      if (verticalLayout_) {
+        if (NSMidY(tabFrame) > placeholderMin) {
+          hasPlaceholderGap = true;
+          offset += NSHeight(placeholderFrame_);
+          tabFrame.origin.y = availableSpace - tabFrame.size.height - offset;
+        }
+      } else {
+        // If the left edge is to the left of the placeholder's left, but the
+        // mid is to the right of it slide over to make space for it.
+        if (NSMidX(tabFrame) > placeholderMin) {
+          hasPlaceholderGap = true;
+          offset += NSWidth(placeholderFrame_);
+          offset -= kTabOverlap;
+          tabFrame.origin.x = offset;
+        }
+      }
+    }
+
+    // Set the width. Selected tabs are slightly wider when things get really
+    // small and thus we enforce a different minimum width.
+    tabFrame.size.width = [tab mini] ?
+        ([tab app] ? kAppTabWidth : kMiniTabWidth) : nonMiniTabWidth;
+    if ([tab selected])
+      tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth);
+
+    // Animate a new tab in by putting it below the horizon unless told to put
+    // it in a specific location (i.e., from a drop).
+    // TODO(pinkerton): figure out vertical tab animations.
+    if (newTab && visible && animate) {
+      if (NSEqualRects(droppedTabFrame_, NSZeroRect)) {
+        [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))];
+      } else {
+        [[tab view] setFrame:droppedTabFrame_];
+        droppedTabFrame_ = NSZeroRect;
+      }
+    }
+
+    // Check the frame by identifier to avoid redundant calls to animator.
+    id frameTarget = visible && animate ? [[tab view] animator] : [tab view];
+    NSValue* identifier = [NSValue valueWithPointer:[tab view]];
+    NSValue* oldTargetValue = [targetFrames_ objectForKey:identifier];
+    if (!oldTargetValue ||
+        !NSEqualRects([oldTargetValue rectValue], tabFrame)) {
+      [frameTarget setFrame:tabFrame];
+      [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
+                        forKey:identifier];
+    }
+
+    enclosingRect = NSUnionRect(tabFrame, enclosingRect);
+
+    if (verticalLayout_) {
+      offset += NSHeight(tabFrame);
+    } else {
+      offset += NSWidth(tabFrame);
+      offset -= kTabOverlap;
+    }
+  }
+
+  // Hide the new tab button if we're explicitly told to. It may already
+  // be hidden, doing it again doesn't hurt. Otherwise position it
+  // appropriately, showing it if necessary.
+  if (forceNewTabButtonHidden_) {
+    [newTabButton_ setHidden:YES];
+  } else {
+    NSRect newTabNewFrame = [newTabButton_ frame];
+    // We've already ensured there's enough space for the new tab button
+    // so we don't have to check it against the available space. We do need
+    // to make sure we put it after any placeholder.
+    CGFloat maxTabX = MAX(offset, NSMaxX(placeholderFrame_) - kTabOverlap);
+    newTabNewFrame.origin = NSMakePoint(maxTabX + kNewTabButtonOffset, 0);
+    if ([tabContentsArray_ count])
+      [newTabButton_ setHidden:NO];
+
+    if (!NSEqualRects(newTabTargetFrame_, newTabNewFrame)) {
+      // Set the new tab button image correctly based on where the cursor is.
+      NSWindow* window = [tabStripView_ window];
+      NSPoint currentMouse = [window mouseLocationOutsideOfEventStream];
+      currentMouse = [tabStripView_ convertPoint:currentMouse fromView:nil];
+
+      BOOL shouldShowHover = [newTabButton_ pointIsOverButton:currentMouse];
+      [self setNewTabButtonHoverState:shouldShowHover];
+
+      // Move the new tab button into place. We want to animate the new tab
+      // button if it's moving to the left (closing a tab), but not when it's
+      // moving to the right (inserting a new tab). If moving right, we need
+      // to use a very small duration to make sure we cancel any in-flight
+      // animation to the left.
+      if (visible && animate) {
+        ScopedNSAnimationContextGroup localAnimationGroup(true);
+        BOOL movingLeft = NSMinX(newTabNewFrame) < NSMinX(newTabTargetFrame_);
+        if (!movingLeft) {
+          localAnimationGroup.SetCurrentContextShortestDuration();
+        }
+        [[newTabButton_ animator] setFrame:newTabNewFrame];
+        newTabTargetFrame_ = newTabNewFrame;
+      } else {
+        [newTabButton_ setFrame:newTabNewFrame];
+        newTabTargetFrame_ = newTabNewFrame;
+      }
+    }
+  }
+
+  [dragBlockingView_ setFrame:enclosingRect];
+
+  // Mark that we've successfully completed layout of at least one tab.
+  initialLayoutComplete_ = YES;
+}
+
+// When we're told to layout from the public API we usually want to animate,
+// except when it's the first time.
+- (void)layoutTabs {
+  [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:YES];
+}
+
+// Handles setting the title of the tab based on the given |contents|. Uses
+// a canned string if |contents| is NULL.
+- (void)setTabTitle:(NSViewController*)tab withContents:(TabContents*)contents {
+  NSString* titleString = nil;
+  if (contents)
+    titleString = base::SysUTF16ToNSString(contents->GetTitle());
+  if (![titleString length]) {
+    titleString = l10n_util::GetNSString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
+  }
+  [tab setTitle:titleString];
+}
+
+// Called when a notification is received from the model to insert a new tab
+// at |modelIndex|.
+- (void)insertTabWithContents:(TabContentsWrapper*)contents
+                      atIndex:(NSInteger)modelIndex
+                 inForeground:(bool)inForeground {
+  DCHECK(contents);
+  DCHECK(modelIndex == TabStripModel::kNoTab ||
+         tabStripModel_->ContainsIndex(modelIndex));
+
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+
+  // Make a new tab. Load the contents of this tab from the nib and associate
+  // the new controller with |contents| so it can be looked up later.
+  scoped_nsobject<TabContentsController> contentsController(
+      [[TabContentsController alloc] initWithContents:contents->tab_contents()
+                                             delegate:self]);
+  [tabContentsArray_ insertObject:contentsController atIndex:index];
+
+  // Make a new tab and add it to the strip. Keep track of its controller.
+  TabController* newController = [self newTab];
+  [newController setMini:tabStripModel_->IsMiniTab(modelIndex)];
+  [newController setPinned:tabStripModel_->IsTabPinned(modelIndex)];
+  [newController setApp:tabStripModel_->IsAppTab(modelIndex)];
+  [tabArray_ insertObject:newController atIndex:index];
+  NSView* newView = [newController view];
+
+  // Set the originating frame to just below the strip so that it animates
+  // upwards as it's being initially layed out. Oddly, this works while doing
+  // something similar in |-layoutTabs| confuses the window server.
+  [newView setFrame:NSOffsetRect([newView frame],
+                                 0, -[[self class] defaultTabHeight])];
+
+  [self setTabTitle:newController withContents:contents->tab_contents()];
+
+  // If a tab is being inserted, we can again use the entire tab strip width
+  // for layout.
+  availableResizeWidth_ = kUseFullAvailableWidth;
+
+  // We don't need to call |-layoutTabs| if the tab will be in the foreground
+  // because it will get called when the new tab is selected by the tab model.
+  // Whenever |-layoutTabs| is called, it'll also add the new subview.
+  if (!inForeground) {
+    [self layoutTabs];
+  }
+
+  // During normal loading, we won't yet have a favicon and we'll get
+  // subsequent state change notifications to show the throbber, but when we're
+  // dragging a tab out into a new window, we have to put the tab's favicon
+  // into the right state up front as we won't be told to do it from anywhere
+  // else.
+  [self updateFavIconForContents:contents->tab_contents() atIndex:modelIndex];
+
+  // Send a broadcast that the number of tabs have changed.
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kTabStripNumberOfTabsChanged
+                    object:self];
+}
+
+// Called when a notification is received from the model to select a particular
+// tab. Swaps in the toolbar and content area associated with |newContents|.
+- (void)selectTabWithContents:(TabContentsWrapper*)newContents
+             previousContents:(TabContentsWrapper*)oldContents
+                      atIndex:(NSInteger)modelIndex
+                  userGesture:(bool)wasUserGesture {
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+
+  if (oldContents) {
+    int oldModelIndex =
+        browser_->GetIndexOfController(&(oldContents->controller()));
+    if (oldModelIndex != -1) {  // When closing a tab, the old tab may be gone.
+      NSInteger oldIndex = [self indexFromModelIndex:oldModelIndex];
+      TabContentsController* oldController =
+          [tabContentsArray_ objectAtIndex:oldIndex];
+      [oldController willBecomeUnselectedTab];
+      oldContents->view()->StoreFocus();
+      oldContents->tab_contents()->WasHidden();
+    }
+  }
+
+  // De-select all other tabs and select the new tab.
+  int i = 0;
+  for (TabController* current in tabArray_.get()) {
+    [current setSelected:(i == index) ? YES : NO];
+    ++i;
+  }
+
+  // Tell the new tab contents it is about to become the selected tab. Here it
+  // can do things like make sure the toolbar is up to date.
+  TabContentsController* newController =
+      [tabContentsArray_ objectAtIndex:index];
+  [newController willBecomeSelectedTab];
+
+  // Relayout for new tabs and to let the selected tab grow to be larger in
+  // size than surrounding tabs if the user has many. This also raises the
+  // selected tab to the top.
+  [self layoutTabs];
+
+  // Swap in the contents for the new tab.
+  [self swapInTabAtIndex:modelIndex];
+
+  if (newContents) {
+    newContents->tab_contents()->DidBecomeSelected();
+    newContents->view()->RestoreFocus();
+
+    if (newContents->GetFindManager()->find_ui_active())
+      browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
+  }
+}
+
+- (void)tabReplacedWithContents:(TabContentsWrapper*)newContents
+               previousContents:(TabContentsWrapper*)oldContents
+                        atIndex:(NSInteger)modelIndex {
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+  TabContentsController* oldController =
+      [tabContentsArray_ objectAtIndex:index];
+  DCHECK_EQ(oldContents->tab_contents(), [oldController tabContents]);
+
+  // Simply create a new TabContentsController for |newContents| and place it
+  // into the array, replacing |oldContents|.  A TabSelectedAt notification will
+  // follow, at which point we will install the new view.
+  scoped_nsobject<TabContentsController> newController(
+      [[TabContentsController alloc]
+          initWithContents:newContents->tab_contents()
+                  delegate:self]);
+
+  // Bye bye, |oldController|.
+  [tabContentsArray_ replaceObjectAtIndex:index withObject:newController];
+
+  [delegate_ onReplaceTabWithContents:newContents->tab_contents()];
+
+  // Fake a tab changed notification to force tab titles and favicons to update.
+  [self tabChangedWithContents:newContents
+                       atIndex:modelIndex
+                    changeType:TabStripModelObserver::ALL];
+}
+
+// Remove all knowledge about this tab and its associated controller, and remove
+// the view from the strip.
+- (void)removeTab:(TabController*)controller {
+  NSUInteger index = [tabArray_ indexOfObject:controller];
+
+  // Release the tab contents controller so those views get destroyed. This
+  // will remove all the tab content Cocoa views from the hierarchy. A
+  // subsequent "select tab" notification will follow from the model. To
+  // tell us what to swap in in its absence.
+  [tabContentsArray_ removeObjectAtIndex:index];
+
+  // Remove the view from the tab strip.
+  NSView* tab = [controller view];
+  [tab removeFromSuperview];
+
+  // Remove ourself as an observer.
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:NSViewDidUpdateTrackingAreasNotification
+              object:tab];
+
+  // Clear the tab controller's target.
+  // TODO(viettrungluu): [crbug.com/23829] Find a better way to handle the tab
+  // controller's target.
+  [controller setTarget:nil];
+
+  if ([hoveredTab_ isEqual:tab])
+    hoveredTab_ = nil;
+
+  NSValue* identifier = [NSValue valueWithPointer:tab];
+  [targetFrames_ removeObjectForKey:identifier];
+
+  // Once we're totally done with the tab, delete its controller
+  [tabArray_ removeObjectAtIndex:index];
+}
+
+// Called by the CAAnimation delegate when the tab completes the closing
+// animation.
+- (void)animationDidStopForController:(TabController*)controller
+                             finished:(BOOL)finished {
+  [closingControllers_ removeObject:controller];
+  [self removeTab:controller];
+}
+
+// Save off which TabController is closing and tell its view's animator
+// where to move the tab to. Registers a delegate to call back when the
+// animation is complete in order to remove the tab from the model.
+- (void)startClosingTabWithAnimation:(TabController*)closingTab {
+  DCHECK([NSThread isMainThread]);
+  // Save off the controller into the set of animating tabs. This alerts
+  // the layout method to not do anything with it and allows us to correctly
+  // calculate offsets when working with indices into the model.
+  [closingControllers_ addObject:closingTab];
+
+  // Mark the tab as closing. This prevents it from generating any drags or
+  // selections while it's animating closed.
+  [(TabView*)[closingTab view] setClosing:YES];
+
+  // Register delegate (owned by the animation system).
+  NSView* tabView = [closingTab view];
+  CAAnimation* animation = [[tabView animationForKey:@"frameOrigin"] copy];
+  [animation autorelease];
+  scoped_nsobject<TabCloseAnimationDelegate> delegate(
+    [[TabCloseAnimationDelegate alloc] initWithTabStrip:self
+                                          tabController:closingTab]);
+  [animation setDelegate:delegate.get()];  // Retains delegate.
+  NSMutableDictionary* animationDictionary =
+      [NSMutableDictionary dictionaryWithDictionary:[tabView animations]];
+  [animationDictionary setObject:animation forKey:@"frameOrigin"];
+  [tabView setAnimations:animationDictionary];
+
+  // Periscope down! Animate the tab.
+  NSRect newFrame = [tabView frame];
+  newFrame = NSOffsetRect(newFrame, 0, -newFrame.size.height);
+  ScopedNSAnimationContextGroup animationGroup(true);
+  animationGroup.SetCurrentContextDuration(kAnimationDuration);
+  [[tabView animator] setFrame:newFrame];
+}
+
+// Called when a notification is received from the model that the given tab
+// has gone away. Start an animation then force a layout to put everything
+// in motion.
+- (void)tabDetachedWithContents:(TabContentsWrapper*)contents
+                        atIndex:(NSInteger)modelIndex {
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+
+  TabController* tab = [tabArray_ objectAtIndex:index];
+  if (tabStripModel_->count() > 0) {
+    [self startClosingTabWithAnimation:tab];
+    [self layoutTabs];
+  } else {
+    [self removeTab:tab];
+  }
+
+  // Send a broadcast that the number of tabs have changed.
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kTabStripNumberOfTabsChanged
+                    object:self];
+
+  [delegate_ onTabDetachedWithContents:contents->tab_contents()];
+}
+
+// A helper routine for creating an NSImageView to hold the fav icon or app icon
+// for |contents|.
+- (NSImageView*)iconImageViewForContents:(TabContents*)contents {
+  BOOL isApp = contents->is_app();
+  NSImage* image = nil;
+  // Favicons come from the renderer, and the renderer draws everything in the
+  // system color space.
+  CGColorSpaceRef colorSpace = base::mac::GetSystemColorSpace();
+  if (isApp) {
+    SkBitmap* icon = contents->GetExtensionAppIcon();
+    if (icon)
+      image = gfx::SkBitmapToNSImageWithColorSpace(*icon, colorSpace);
+  } else {
+    image = gfx::SkBitmapToNSImageWithColorSpace(contents->GetFavIcon(),
+                                                 colorSpace);
+  }
+
+  // Either we don't have a valid favicon or there was some issue converting it
+  // from an SkBitmap. Either way, just show the default.
+  if (!image)
+    image = defaultFavIcon_.get();
+  NSRect frame = NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
+  NSImageView* view = [[[NSImageView alloc] initWithFrame:frame] autorelease];
+  [view setImage:image];
+  return view;
+}
+
+// Updates the current loading state, replacing the icon view with a favicon,
+// a throbber, the default icon, or nothing at all.
+- (void)updateFavIconForContents:(TabContents*)contents
+                         atIndex:(NSInteger)modelIndex {
+  if (!contents)
+    return;
+
+  static NSImage* throbberWaitingImage =
+      [ResourceBundle::GetSharedInstance().GetNativeImageNamed(
+          IDR_THROBBER_WAITING) retain];
+  static NSImage* throbberLoadingImage =
+      [ResourceBundle::GetSharedInstance().GetNativeImageNamed(IDR_THROBBER)
+        retain];
+  static NSImage* sadFaviconImage =
+      [ResourceBundle::GetSharedInstance().GetNativeImageNamed(IDR_SAD_FAVICON)
+        retain];
+
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+  TabController* tabController = [tabArray_ objectAtIndex:index];
+
+  bool oldHasIcon = [tabController iconView] != nil;
+  bool newHasIcon = contents->ShouldDisplayFavIcon() ||
+      tabStripModel_->IsMiniTab(modelIndex);  // Always show icon if mini.
+
+  TabLoadingState oldState = [tabController loadingState];
+  TabLoadingState newState = kTabDone;
+  NSImage* throbberImage = nil;
+  if (contents->is_crashed()) {
+    newState = kTabCrashed;
+    newHasIcon = true;
+  } else if (contents->waiting_for_response()) {
+    newState = kTabWaiting;
+    throbberImage = throbberWaitingImage;
+  } else if (contents->is_loading()) {
+    newState = kTabLoading;
+    throbberImage = throbberLoadingImage;
+  }
+
+  if (oldState != newState)
+    [tabController setLoadingState:newState];
+
+  // While loading, this function is called repeatedly with the same state.
+  // To avoid expensive unnecessary view manipulation, only make changes when
+  // the state is actually changing.  When loading is complete (kTabDone),
+  // every call to this function is significant.
+  if (newState == kTabDone || oldState != newState ||
+      oldHasIcon != newHasIcon) {
+    NSView* iconView = nil;
+    if (newHasIcon) {
+      if (newState == kTabDone) {
+        iconView = [self iconImageViewForContents:contents];
+      } else if (newState == kTabCrashed) {
+        NSImage* oldImage = [[self iconImageViewForContents:contents] image];
+        NSRect frame =
+            NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
+        iconView = [ThrobberView toastThrobberViewWithFrame:frame
+                                                beforeImage:oldImage
+                                                 afterImage:sadFaviconImage];
+      } else {
+        NSRect frame =
+            NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
+        iconView = [ThrobberView filmstripThrobberViewWithFrame:frame
+                                                          image:throbberImage];
+      }
+    }
+
+    [tabController setIconView:iconView];
+  }
+}
+
+// Called when a notification is received from the model that the given tab
+// has been updated. |loading| will be YES when we only want to update the
+// throbber state, not anything else about the (partially) loading tab.
+- (void)tabChangedWithContents:(TabContentsWrapper*)contents
+                       atIndex:(NSInteger)modelIndex
+                    changeType:(TabStripModelObserver::TabChangeType)change {
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+
+  if (modelIndex == tabStripModel_->selected_index())
+    [delegate_ onSelectedTabChange:change];
+
+  if (change == TabStripModelObserver::TITLE_NOT_LOADING) {
+    // TODO(sky): make this work.
+    // We'll receive another notification of the change asynchronously.
+    return;
+  }
+
+  TabController* tabController = [tabArray_ objectAtIndex:index];
+
+  if (change != TabStripModelObserver::LOADING_ONLY)
+    [self setTabTitle:tabController withContents:contents->tab_contents()];
+
+  [self updateFavIconForContents:contents->tab_contents() atIndex:modelIndex];
+
+  TabContentsController* updatedController =
+      [tabContentsArray_ objectAtIndex:index];
+  [updatedController tabDidChange:contents->tab_contents()];
+}
+
+// Called when a tab is moved (usually by drag&drop). Keep our parallel arrays
+// in sync with the tab strip model. It can also be pinned/unpinned
+// simultaneously, so we need to take care of that.
+- (void)tabMovedWithContents:(TabContentsWrapper*)contents
+                   fromIndex:(NSInteger)modelFrom
+                     toIndex:(NSInteger)modelTo {
+  // Take closing tabs into account.
+  NSInteger from = [self indexFromModelIndex:modelFrom];
+  NSInteger to = [self indexFromModelIndex:modelTo];
+
+  scoped_nsobject<TabContentsController> movedTabContentsController(
+      [[tabContentsArray_ objectAtIndex:from] retain]);
+  [tabContentsArray_ removeObjectAtIndex:from];
+  [tabContentsArray_ insertObject:movedTabContentsController.get()
+                          atIndex:to];
+  scoped_nsobject<TabController> movedTabController(
+      [[tabArray_ objectAtIndex:from] retain]);
+  DCHECK([movedTabController isKindOfClass:[TabController class]]);
+  [tabArray_ removeObjectAtIndex:from];
+  [tabArray_ insertObject:movedTabController.get() atIndex:to];
+
+  // The tab moved, which means that the mini-tab state may have changed.
+  if (tabStripModel_->IsMiniTab(modelTo) != [movedTabController mini])
+    [self tabMiniStateChangedWithContents:contents atIndex:modelTo];
+
+  [self layoutTabs];
+}
+
+// Called when a tab is pinned or unpinned without moving.
+- (void)tabMiniStateChangedWithContents:(TabContentsWrapper*)contents
+                                atIndex:(NSInteger)modelIndex {
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+
+  TabController* tabController = [tabArray_ objectAtIndex:index];
+  DCHECK([tabController isKindOfClass:[TabController class]]);
+
+  // Don't do anything if the change was already picked up by the move event.
+  if (tabStripModel_->IsMiniTab(modelIndex) == [tabController mini])
+    return;
+
+  [tabController setMini:tabStripModel_->IsMiniTab(modelIndex)];
+  [tabController setPinned:tabStripModel_->IsTabPinned(modelIndex)];
+  [tabController setApp:tabStripModel_->IsAppTab(modelIndex)];
+  [self updateFavIconForContents:contents->tab_contents() atIndex:modelIndex];
+  // If the tab is being restored and it's pinned, the mini state is set after
+  // the tab has already been rendered, so re-layout the tabstrip. In all other
+  // cases, the state is set before the tab is rendered so this isn't needed.
+  [self layoutTabs];
+}
+
+- (void)setFrameOfSelectedTab:(NSRect)frame {
+  NSView* view = [self selectedTabView];
+  NSValue* identifier = [NSValue valueWithPointer:view];
+  [targetFrames_ setObject:[NSValue valueWithRect:frame]
+                    forKey:identifier];
+  [view setFrame:frame];
+}
+
+- (NSView*)selectedTabView {
+  int selectedIndex = tabStripModel_->selected_index();
+  // Take closing tabs into account. They can't ever be selected.
+  selectedIndex = [self indexFromModelIndex:selectedIndex];
+  return [self viewAtIndex:selectedIndex];
+}
+
+// Find the model index based on the x coordinate of the placeholder. If there
+// is no placeholder, this returns the end of the tab strip. Closing tabs are
+// not considered in computing the index.
+- (int)indexOfPlaceholder {
+  double placeholderX = placeholderFrame_.origin.x;
+  int index = 0;
+  int location = 0;
+  // Use |tabArray_| here instead of the tab strip count in order to get the
+  // correct index when there are closing tabs to the left of the placeholder.
+  const int count = [tabArray_ count];
+  while (index < count) {
+    // Ignore closing tabs for simplicity. The only drawback of this is that
+    // if the placeholder is placed right before one or several contiguous
+    // currently closing tabs, the associated TabController will start at the
+    // end of the closing tabs.
+    if ([closingControllers_ containsObject:[tabArray_ objectAtIndex:index]]) {
+      index++;
+      continue;
+    }
+    NSView* curr = [self viewAtIndex:index];
+    // The placeholder tab works by changing the frame of the tab being dragged
+    // to be the bounds of the placeholder, so we need to skip it while we're
+    // iterating, otherwise we'll end up off by one.  Note This only effects
+    // dragging to the right, not to the left.
+    if (curr == placeholderTab_) {
+      index++;
+      continue;
+    }
+    if (placeholderX <= NSMinX([curr frame]))
+      break;
+    index++;
+    location++;
+  }
+  return location;
+}
+
+// Move the given tab at index |from| in this window to the location of the
+// current placeholder.
+- (void)moveTabFromIndex:(NSInteger)from {
+  int toIndex = [self indexOfPlaceholder];
+  tabStripModel_->MoveTabContentsAt(from, toIndex, true);
+}
+
+// Drop a given TabContents at the location of the current placeholder. If there
+// is no placeholder, it will go at the end. Used when dragging from another
+// window when we don't have access to the TabContents as part of our strip.
+// |frame| is in the coordinate system of the tab strip view and represents
+// where the user dropped the new tab so it can be animated into its correct
+// location when the tab is added to the model. If the tab was pinned in its
+// previous window, setting |pinned| to YES will propagate that state to the
+// new window. Mini-tabs are either app or pinned tabs; the app state is stored
+// by the |contents|, but the |pinned| state is the caller's responsibility.
+- (void)dropTabContents:(TabContentsWrapper*)contents
+              withFrame:(NSRect)frame
+            asPinnedTab:(BOOL)pinned {
+  int modelIndex = [self indexOfPlaceholder];
+
+  // Mark that the new tab being created should start at |frame|. It will be
+  // reset as soon as the tab has been positioned.
+  droppedTabFrame_ = frame;
+
+  // Insert it into this tab strip. We want it in the foreground and to not
+  // inherit the current tab's group.
+  tabStripModel_->InsertTabContentsAt(
+      modelIndex, contents,
+      TabStripModel::ADD_SELECTED | (pinned ? TabStripModel::ADD_PINNED : 0));
+}
+
+// Called when the tab strip view changes size. As we only registered for
+// changes on our view, we know it's only for our view. Layout w/out
+// animations since they are blocked by the resize nested runloop. We need
+// the views to adjust immediately. Neither the tabs nor their z-order are
+// changed, so we don't need to update the subviews.
+- (void)tabViewFrameChanged:(NSNotification*)info {
+  [self layoutTabsWithAnimation:NO regenerateSubviews:NO];
+}
+
+// Called when the tracking areas for any given tab are updated. This allows
+// the individual tabs to update their hover states correctly.
+// Only generates the event if the cursor is in the tab strip.
+- (void)tabUpdateTracking:(NSNotification*)notification {
+  DCHECK([[notification object] isKindOfClass:[TabView class]]);
+  DCHECK(mouseInside_);
+  NSWindow* window = [tabStripView_ window];
+  NSPoint location = [window mouseLocationOutsideOfEventStream];
+  if (NSPointInRect(location, [tabStripView_ frame])) {
+    NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved
+                                             location:location
+                                        modifierFlags:0
+                                            timestamp:0
+                                         windowNumber:[window windowNumber]
+                                              context:nil
+                                          eventNumber:0
+                                           clickCount:0
+                                             pressure:0];
+    [self mouseMoved:mouseEvent];
+  }
+}
+
+- (BOOL)inRapidClosureMode {
+  return availableResizeWidth_ != kUseFullAvailableWidth;
+}
+
+// Disable tab dragging when there are any pending animations.
+- (BOOL)tabDraggingAllowed {
+  return [closingControllers_ count] == 0;
+}
+
+- (void)mouseMoved:(NSEvent*)event {
+  // Use hit test to figure out what view we are hovering over.
+  NSView* targetView = [tabStripView_ hitTest:[event locationInWindow]];
+
+  // Set the new tab button hover state iff the mouse is over the button.
+  BOOL shouldShowHoverImage = [targetView isKindOfClass:[NewTabButton class]];
+  [self setNewTabButtonHoverState:shouldShowHoverImage];
+
+  TabView* tabView = (TabView*)targetView;
+  if (![tabView isKindOfClass:[TabView class]]) {
+    if ([[tabView superview] isKindOfClass:[TabView class]]) {
+      tabView = (TabView*)[targetView superview];
+    } else {
+      tabView = nil;
+    }
+  }
+
+  if (hoveredTab_ != tabView) {
+    [hoveredTab_ mouseExited:nil];  // We don't pass event because moved events
+    [tabView mouseEntered:nil];  // don't have valid tracking areas
+    hoveredTab_ = tabView;
+  } else {
+    [hoveredTab_ mouseMoved:event];
+  }
+}
+
+- (void)mouseEntered:(NSEvent*)event {
+  NSTrackingArea* area = [event trackingArea];
+  if ([area isEqual:trackingArea_]) {
+    mouseInside_ = YES;
+    [self setTabTrackingAreasEnabled:YES];
+    [self mouseMoved:event];
+  }
+}
+
+// Called when the tracking area is in effect which means we're tracking to
+// see if the user leaves the tab strip with their mouse. When they do,
+// reset layout to use all available width.
+- (void)mouseExited:(NSEvent*)event {
+  NSTrackingArea* area = [event trackingArea];
+  if ([area isEqual:trackingArea_]) {
+    mouseInside_ = NO;
+    [self setTabTrackingAreasEnabled:NO];
+    availableResizeWidth_ = kUseFullAvailableWidth;
+    [hoveredTab_ mouseExited:event];
+    hoveredTab_ = nil;
+    [self layoutTabs];
+  } else if ([area isEqual:newTabTrackingArea_]) {
+    // If the mouse is moved quickly enough, it is possible for the mouse to
+    // leave the tabstrip without sending any mouseMoved: messages at all.
+    // Since this would result in the new tab button incorrectly staying in the
+    // hover state, disable the hover image on every mouse exit.
+    [self setNewTabButtonHoverState:NO];
+  }
+}
+
+// Enable/Disable the tracking areas for the tabs. They are only enabled
+// when the mouse is in the tabstrip.
+- (void)setTabTrackingAreasEnabled:(BOOL)enabled {
+  NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
+  for (TabController* controller in tabArray_.get()) {
+    TabView* tabView = [controller tabView];
+    if (enabled) {
+      // Set self up to observe tabs so hover states will be correct.
+      [defaultCenter addObserver:self
+                        selector:@selector(tabUpdateTracking:)
+                            name:NSViewDidUpdateTrackingAreasNotification
+                          object:tabView];
+    } else {
+      [defaultCenter removeObserver:self
+                               name:NSViewDidUpdateTrackingAreasNotification
+                             object:tabView];
+    }
+    [tabView setTrackingEnabled:enabled];
+  }
+}
+
+// Sets the new tab button's image based on the current hover state.  Does
+// nothing if the hover state is already correct.
+- (void)setNewTabButtonHoverState:(BOOL)shouldShowHover {
+  if (shouldShowHover && !newTabButtonShowingHoverImage_) {
+    newTabButtonShowingHoverImage_ = YES;
+    [newTabButton_ setImage:
+        app::mac::GetCachedImageWithName(kNewTabHoverImage)];
+  } else if (!shouldShowHover && newTabButtonShowingHoverImage_) {
+    newTabButtonShowingHoverImage_ = NO;
+    [newTabButton_ setImage:app::mac::GetCachedImageWithName(kNewTabImage)];
+  }
+}
+
+// Adds the given subview to (the end of) the list of permanent subviews
+// (specified from bottom up). These subviews will always be below the
+// transitory subviews (tabs). |-regenerateSubviewList| must be called to
+// effectuate the addition.
+- (void)addSubviewToPermanentList:(NSView*)aView {
+  if (aView)
+    [permanentSubviews_ addObject:aView];
+}
+
+// Update the subviews, keeping the permanent ones (or, more correctly, putting
+// in the ones listed in permanentSubviews_), and putting in the current tabs in
+// the correct z-order. Any current subviews which is neither in the permanent
+// list nor a (current) tab will be removed. So if you add such a subview, you
+// should call |-addSubviewToPermanentList:| (or better yet, call that and then
+// |-regenerateSubviewList| to actually add it).
+- (void)regenerateSubviewList {
+  // Remove self as an observer from all the old tabs before a new set of
+  // potentially different tabs is put in place.
+  [self setTabTrackingAreasEnabled:NO];
+
+  // Subviews to put in (in bottom-to-top order), beginning with the permanent
+  // ones.
+  NSMutableArray* subviews = [NSMutableArray arrayWithArray:permanentSubviews_];
+
+  NSView* selectedTabView = nil;
+  // Go through tabs in reverse order, since |subviews| is bottom-to-top.
+  for (TabController* tab in [tabArray_ reverseObjectEnumerator]) {
+    NSView* tabView = [tab view];
+    if ([tab selected]) {
+      DCHECK(!selectedTabView);
+      selectedTabView = tabView;
+    } else {
+      [subviews addObject:tabView];
+    }
+  }
+  if (selectedTabView) {
+    [subviews addObject:selectedTabView];
+  }
+  [tabStripView_ setSubviews:subviews];
+  [self setTabTrackingAreasEnabled:mouseInside_];
+}
+
+// Get the index and disposition for a potential URL(s) drop given a point (in
+// the |TabStripView|'s coordinates). It considers only the x-coordinate of the
+// given point. If it's in the "middle" of a tab, it drops on that tab. If it's
+// to the left, it inserts to the left, and similarly for the right.
+- (void)droppingURLsAt:(NSPoint)point
+            givesIndex:(NSInteger*)index
+           disposition:(WindowOpenDisposition*)disposition {
+  // Proportion of the tab which is considered the "middle" (and causes things
+  // to drop on that tab).
+  const double kMiddleProportion = 0.5;
+  const double kLRProportion = (1.0 - kMiddleProportion) / 2.0;
+
+  DCHECK(index && disposition);
+  NSInteger i = 0;
+  for (TabController* tab in tabArray_.get()) {
+    NSView* view = [tab view];
+    DCHECK([view isKindOfClass:[TabView class]]);
+
+    // Recall that |-[NSView frame]| is in its superview's coordinates, so a
+    // |TabView|'s frame is in the coordinates of the |TabStripView| (which
+    // matches the coordinate system of |point|).
+    NSRect frame = [view frame];
+
+    // Modify the frame to make it "unoverlapped".
+    frame.origin.x += kTabOverlap / 2.0;
+    frame.size.width -= kTabOverlap;
+    if (frame.size.width < 1.0)
+      frame.size.width = 1.0;  // try to avoid complete failure
+
+    // Drop in a new tab to the left of tab |i|?
+    if (point.x < (frame.origin.x + kLRProportion * frame.size.width)) {
+      *index = i;
+      *disposition = NEW_FOREGROUND_TAB;
+      return;
+    }
+
+    // Drop on tab |i|?
+    if (point.x <= (frame.origin.x +
+                       (1.0 - kLRProportion) * frame.size.width)) {
+      *index = i;
+      *disposition = CURRENT_TAB;
+      return;
+    }
+
+    // (Dropping in a new tab to the right of tab |i| will be taken care of in
+    // the next iteration.)
+    i++;
+  }
+
+  // If we've made it here, we want to append a new tab to the end.
+  *index = -1;
+  *disposition = NEW_FOREGROUND_TAB;
+}
+
+- (void)openURL:(GURL*)url inView:(NSView*)view at:(NSPoint)point {
+  // Get the index and disposition.
+  NSInteger index;
+  WindowOpenDisposition disposition;
+  [self droppingURLsAt:point
+            givesIndex:&index
+           disposition:&disposition];
+
+  // Either insert a new tab or open in a current tab.
+  switch (disposition) {
+    case NEW_FOREGROUND_TAB: {
+      UserMetrics::RecordAction(UserMetricsAction("Tab_DropURLBetweenTabs"),
+                                browser_->profile());
+      browser::NavigateParams params(browser_, *url, PageTransition::TYPED);
+      params.disposition = disposition;
+      params.tabstrip_index = index;
+      params.tabstrip_add_types =
+          TabStripModel::ADD_SELECTED | TabStripModel::ADD_FORCE_INDEX;
+      browser::Navigate(&params);
+      break;
+    }
+    case CURRENT_TAB:
+      UserMetrics::RecordAction(UserMetricsAction("Tab_DropURLOnTab"),
+                                browser_->profile());
+      tabStripModel_->GetTabContentsAt(index)
+          ->tab_contents()->OpenURL(*url, GURL(), CURRENT_TAB,
+                                    PageTransition::TYPED);
+      tabStripModel_->SelectTabContentsAt(index, true);
+      break;
+    default:
+      NOTIMPLEMENTED();
+  }
+}
+
+// (URLDropTargetController protocol)
+- (void)dropURLs:(NSArray*)urls inView:(NSView*)view at:(NSPoint)point {
+  DCHECK_EQ(view, tabStripView_.get());
+
+  if ([urls count] < 1) {
+    NOTREACHED();
+    return;
+  }
+
+  //TODO(viettrungluu): dropping multiple URLs.
+  if ([urls count] > 1)
+    NOTIMPLEMENTED();
+
+  // Get the first URL and fix it up.
+  GURL url(GURL(URLFixerUpper::FixupURL(
+      base::SysNSStringToUTF8([urls objectAtIndex:0]), std::string())));
+
+  [self openURL:&url inView:view at:point];
+}
+
+// (URLDropTargetController protocol)
+- (void)dropText:(NSString*)text inView:(NSView*)view at:(NSPoint)point {
+  DCHECK_EQ(view, tabStripView_.get());
+
+  // If the input is plain text, classify the input and make the URL.
+  AutocompleteMatch match;
+  browser_->profile()->GetAutocompleteClassifier()->Classify(
+      base::SysNSStringToUTF16(text), string16(), false, &match, NULL);
+  GURL url(match.destination_url);
+
+  [self openURL:&url inView:view at:point];
+}
+
+// (URLDropTargetController protocol)
+- (void)indicateDropURLsInView:(NSView*)view at:(NSPoint)point {
+  DCHECK_EQ(view, tabStripView_.get());
+
+  // The minimum y-coordinate at which one should consider place the arrow.
+  const CGFloat arrowBaseY = 25;
+
+  NSInteger index;
+  WindowOpenDisposition disposition;
+  [self droppingURLsAt:point
+            givesIndex:&index
+           disposition:&disposition];
+
+  NSPoint arrowPos = NSMakePoint(0, arrowBaseY);
+  if (index == -1) {
+    // Append a tab at the end.
+    DCHECK(disposition == NEW_FOREGROUND_TAB);
+    NSInteger lastIndex = [tabArray_ count] - 1;
+    NSRect overRect = [[[tabArray_ objectAtIndex:lastIndex] view] frame];
+    arrowPos.x = overRect.origin.x + overRect.size.width - kTabOverlap / 2.0;
+  } else {
+    NSRect overRect = [[[tabArray_ objectAtIndex:index] view] frame];
+    switch (disposition) {
+      case NEW_FOREGROUND_TAB:
+        // Insert tab (to the left of the given tab).
+        arrowPos.x = overRect.origin.x + kTabOverlap / 2.0;
+        break;
+      case CURRENT_TAB:
+        // Overwrite the given tab.
+        arrowPos.x = overRect.origin.x + overRect.size.width / 2.0;
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+
+  [tabStripView_ setDropArrowPosition:arrowPos];
+  [tabStripView_ setDropArrowShown:YES];
+  [tabStripView_ setNeedsDisplay:YES];
+}
+
+// (URLDropTargetController protocol)
+- (void)hideDropURLsIndicatorInView:(NSView*)view {
+  DCHECK_EQ(view, tabStripView_.get());
+
+  if ([tabStripView_ dropArrowShown]) {
+    [tabStripView_ setDropArrowShown:NO];
+    [tabStripView_ setNeedsDisplay:YES];
+  }
+}
+
+- (GTMWindowSheetController*)sheetController {
+  if (!sheetController_.get())
+    sheetController_.reset([[GTMWindowSheetController alloc]
+        initWithWindow:[switchView_ window] delegate:self]);
+  return sheetController_.get();
+}
+
+- (void)destroySheetController {
+  // Make sure there are no open sheets.
+  DCHECK_EQ(0U, [[sheetController_ viewsWithAttachedSheets] count]);
+  sheetController_.reset();
+}
+
+// TabContentsControllerDelegate protocol.
+- (void)tabContentsViewFrameWillChange:(TabContentsController*)source
+                             frameRect:(NSRect)frameRect {
+  id<TabContentsControllerDelegate> controller =
+      [[switchView_ window] windowController];
+  [controller tabContentsViewFrameWillChange:source frameRect:frameRect];
+}
+
+- (TabContentsController*)activeTabContentsController {
+  int modelIndex = tabStripModel_->selected_index();
+  if (modelIndex < 0)
+    return nil;
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+  if (index < 0 ||
+      index >= (NSInteger)[tabContentsArray_ count])
+    return nil;
+  return [tabContentsArray_ objectAtIndex:index];
+}
+
+- (void)gtm_systemRequestsVisibilityForView:(NSView*)view {
+  // This implementation is required by GTMWindowSheetController.
+
+  // Raise window...
+  [[switchView_ window] makeKeyAndOrderFront:self];
+
+  // ...and raise a tab with a sheet.
+  NSInteger index = [self modelIndexForContentsView:view];
+  DCHECK(index >= 0);
+  if (index >= 0)
+    tabStripModel_->SelectTabContentsAt(index, false /* not a user gesture */);
+}
+
+- (void)attachConstrainedWindow:(ConstrainedWindowMac*)window {
+  // TODO(thakis, avi): Figure out how to make this work when tabs are dragged
+  // out or if fullscreen mode is toggled.
+
+  // View hierarchy of the contents view:
+  // NSView  -- switchView, same for all tabs
+  // +- NSView  -- TabContentsController's view
+  //    +- TabContentsViewCocoa
+  // Changing it? Do not forget to modify removeConstrainedWindow too.
+  // We use the TabContentsController's view in |swapInTabAtIndex|, so we have
+  // to pass it to the sheet controller here.
+  NSView* tabContentsView = [window->owner()->GetNativeView() superview];
+  window->delegate()->RunSheet([self sheetController], tabContentsView);
+
+  // TODO(avi, thakis): GTMWindowSheetController has no api to move tabsheets
+  // between windows. Until then, we have to prevent having to move a tabsheet
+  // between windows, e.g. no tearing off of tabs.
+  NSInteger modelIndex = [self modelIndexForContentsView:tabContentsView];
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+  BrowserWindowController* controller =
+      (BrowserWindowController*)[[switchView_ window] windowController];
+  DCHECK(controller != nil);
+  DCHECK(index >= 0);
+  if (index >= 0) {
+    [controller setTab:[self viewAtIndex:index] isDraggable:NO];
+  }
+}
+
+- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window {
+  NSView* tabContentsView = [window->owner()->GetNativeView() superview];
+
+  // TODO(avi, thakis): GTMWindowSheetController has no api to move tabsheets
+  // between windows. Until then, we have to prevent having to move a tabsheet
+  // between windows, e.g. no tearing off of tabs.
+  NSInteger modelIndex = [self modelIndexForContentsView:tabContentsView];
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+  BrowserWindowController* controller =
+      (BrowserWindowController*)[[switchView_ window] windowController];
+  DCHECK(index >= 0);
+  if (index >= 0) {
+    [controller setTab:[self viewAtIndex:index] isDraggable:YES];
+  }
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
new file mode 100644
index 0000000..605da57
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
@@ -0,0 +1,177 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/browser_window.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/new_tab_button.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface TestTabStripControllerDelegate :
+  NSObject<TabStripControllerDelegate> {
+}
+@end
+
+@implementation TestTabStripControllerDelegate
+- (void)onSelectTabWithContents:(TabContents*)contents {
+}
+- (void)onReplaceTabWithContents:(TabContents*)contents {
+}
+- (void)onSelectedTabChange:(TabStripModelObserver::TabChangeType)change {
+}
+- (void)onTabDetachedWithContents:(TabContents*)contents {
+}
+@end
+
+namespace {
+
+// Stub model delegate
+class TestTabStripDelegate : public TabStripModelDelegate {
+ public:
+  virtual TabContentsWrapper* AddBlankTab(bool foreground) {
+    return NULL;
+  }
+  virtual TabContentsWrapper* AddBlankTabAt(int index, bool foreground) {
+    return NULL;
+  }
+  virtual Browser* CreateNewStripWithContents(TabContentsWrapper* contents,
+                                              const gfx::Rect& window_bounds,
+                                              const DockInfo& dock_info,
+                                              bool maximize) {
+    return NULL;
+  }
+  virtual void ContinueDraggingDetachedTab(TabContentsWrapper* contents,
+                                           const gfx::Rect& window_bounds,
+                                           const gfx::Rect& tab_bounds) {
+  }
+  virtual int GetDragActions() const {
+    return 0;
+  }
+  virtual TabContentsWrapper* CreateTabContentsForURL(
+      const GURL& url,
+      const GURL& referrer,
+      Profile* profile,
+      PageTransition::Type transition,
+      bool defer_load,
+      SiteInstance* instance) const {
+    return NULL;
+  }
+  virtual bool CanDuplicateContentsAt(int index) { return true; }
+  virtual void DuplicateContentsAt(int index) { }
+  virtual void CloseFrameAfterDragSession() { }
+  virtual void CreateHistoricalTab(TabContentsWrapper* contents) { }
+  virtual bool RunUnloadListenerBeforeClosing(TabContentsWrapper* contents) {
+    return true;
+  }
+  virtual bool CanRestoreTab() {
+    return true;
+  }
+  virtual void RestoreTab() {}
+
+  virtual bool CanCloseContentsAt(int index) { return true; }
+
+  virtual bool CanBookmarkAllTabs() const { return false; }
+
+  virtual bool CanCloseTab() const { return true; }
+
+  virtual void BookmarkAllTabs() {}
+
+  virtual bool UseVerticalTabs() const { return false; }
+
+  virtual void ToggleUseVerticalTabs() {}
+
+  virtual bool LargeIconsPermitted() const { return true; }
+};
+
+class TabStripControllerTest : public CocoaTest {
+ public:
+  TabStripControllerTest() {
+    Browser* browser = browser_helper_.browser();
+    BrowserWindow* browser_window = browser_helper_.CreateBrowserWindow();
+    NSWindow* window = browser_window->GetNativeHandle();
+    NSView* parent = [window contentView];
+    NSRect content_frame = [parent frame];
+
+    // Create the "switch view" (view that gets changed out when a tab
+    // switches).
+    NSRect switch_frame = NSMakeRect(0, 0, content_frame.size.width, 500);
+    scoped_nsobject<NSView> switch_view(
+        [[NSView alloc] initWithFrame:switch_frame]);
+    [parent addSubview:switch_view.get()];
+
+    // Create the tab strip view. It's expected to have a child button in it
+    // already as the "new tab" button so create that too.
+    NSRect strip_frame = NSMakeRect(0, NSMaxY(switch_frame),
+                                    content_frame.size.width, 30);
+    scoped_nsobject<TabStripView> tab_strip(
+        [[TabStripView alloc] initWithFrame:strip_frame]);
+    [parent addSubview:tab_strip.get()];
+    NSRect button_frame = NSMakeRect(0, 0, 15, 15);
+    scoped_nsobject<NewTabButton> new_tab_button(
+        [[NewTabButton alloc] initWithFrame:button_frame]);
+    [tab_strip addSubview:new_tab_button.get()];
+    [tab_strip setNewTabButton:new_tab_button.get()];
+
+    delegate_.reset(new TestTabStripDelegate());
+    model_ = browser->tabstrip_model();
+    controller_delegate_.reset([TestTabStripControllerDelegate alloc]);
+    controller_.reset([[TabStripController alloc]
+                        initWithView:static_cast<TabStripView*>(tab_strip.get())
+                          switchView:switch_view.get()
+                             browser:browser
+                            delegate:controller_delegate_.get()]);
+  }
+
+  virtual void TearDown() {
+    browser_helper_.CloseBrowserWindow();
+    // The call to CocoaTest::TearDown() deletes the Browser and TabStripModel
+    // objects, so we first have to delete the controller, which refers to them.
+    controller_.reset(nil);
+    model_ = NULL;
+    CocoaTest::TearDown();
+  }
+
+  BrowserTestHelper browser_helper_;
+  scoped_ptr<TestTabStripDelegate> delegate_;
+  TabStripModel* model_;
+  scoped_nsobject<TestTabStripControllerDelegate> controller_delegate_;
+  scoped_nsobject<TabStripController> controller_;
+};
+
+// Test adding and removing tabs and making sure that views get added to
+// the tab strip.
+TEST_F(TabStripControllerTest, AddRemoveTabs) {
+  EXPECT_TRUE(model_->empty());
+  SiteInstance* instance =
+      SiteInstance::CreateSiteInstance(browser_helper_.profile());
+  TabContentsWrapper* tab_contents =
+      Browser::TabContentsFactory(browser_helper_.profile(), instance,
+          MSG_ROUTING_NONE, NULL, NULL);
+  model_->AppendTabContents(tab_contents, true);
+  EXPECT_EQ(model_->count(), 1);
+}
+
+TEST_F(TabStripControllerTest, SelectTab) {
+  // TODO(pinkerton): Implement http://crbug.com/10899
+}
+
+TEST_F(TabStripControllerTest, RearrangeTabs) {
+  // TODO(pinkerton): Implement http://crbug.com/10899
+}
+
+// Test that changing the number of tabs broadcasts a
+// kTabStripNumberOfTabsChanged notifiction.
+TEST_F(TabStripControllerTest, Notifications) {
+  // TODO(pinkerton): Implement http://crbug.com/10899
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
new file mode 100644
index 0000000..111e7f9
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
+#pragma once
+
+#import <Foundation/Foundation.h>
+
+#include "chrome/browser/tabs/tab_strip_model_observer.h"
+
+class TabContentsWrapper;
+class TabStripModel;
+
+// A C++ bridge class to handle receiving notifications from the C++ tab strip
+// model. When the caller allocates a bridge, it automatically registers for
+// notifications from |model| and passes messages to |controller| via the
+// informal protocol below. The owner of this object is responsible for deleting
+// it (and thus unhooking notifications) before |controller| is destroyed.
+class TabStripModelObserverBridge : public TabStripModelObserver {
+ public:
+  TabStripModelObserverBridge(TabStripModel* model, id controller);
+  virtual ~TabStripModelObserverBridge();
+
+  // Overridden from TabStripModelObserver
+  virtual void TabInsertedAt(TabContentsWrapper* contents,
+                             int index,
+                             bool foreground);
+  virtual void TabClosingAt(TabStripModel* tab_strip_model,
+                            TabContentsWrapper* contents,
+                            int index);
+  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
+  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index,
+                             bool user_gesture);
+  virtual void TabMoved(TabContentsWrapper* contents,
+                        int from_index,
+                        int to_index);
+  virtual void TabChangedAt(TabContentsWrapper* contents, int index,
+                            TabChangeType change_type);
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index);
+  virtual void TabMiniStateChanged(TabContentsWrapper* contents, int index);
+  virtual void TabStripEmpty();
+  virtual void TabStripModelDeleted();
+
+ private:
+  id controller_;  // weak, owns me
+  TabStripModel* model_;  // weak, owned by Browser
+};
+
+// A collection of methods which can be selectively implemented by any
+// Cocoa object to receive updates about changes to a tab strip model. It is
+// ok to not implement them, the calling code checks before calling.
+@interface NSObject(TabStripModelBridge)
+- (void)insertTabWithContents:(TabContentsWrapper*)contents
+                      atIndex:(NSInteger)index
+                 inForeground:(bool)inForeground;
+- (void)tabClosingWithContents:(TabContentsWrapper*)contents
+                       atIndex:(NSInteger)index;
+- (void)tabDetachedWithContents:(TabContentsWrapper*)contents
+                        atIndex:(NSInteger)index;
+- (void)selectTabWithContents:(TabContentsWrapper*)newContents
+             previousContents:(TabContentsWrapper*)oldContents
+                      atIndex:(NSInteger)index
+                  userGesture:(bool)wasUserGesture;
+- (void)tabMovedWithContents:(TabContentsWrapper*)contents
+                    fromIndex:(NSInteger)from
+                      toIndex:(NSInteger)to;
+- (void)tabChangedWithContents:(TabContentsWrapper*)contents
+                       atIndex:(NSInteger)index
+                    changeType:(TabStripModelObserver::TabChangeType)change;
+- (void)tabReplacedWithContents:(TabContentsWrapper*)newContents
+               previousContents:(TabContentsWrapper*)oldContents
+                        atIndex:(NSInteger)index;
+- (void)tabMiniStateChangedWithContents:(TabContentsWrapper*)contents
+                                atIndex:(NSInteger)index;
+- (void)tabStripEmpty;
+- (void)tabStripModelDeleted;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm
new file mode 100644
index 0000000..8e56296
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm
@@ -0,0 +1,119 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
+
+#include "chrome/browser/tabs/tab_strip_model.h"
+
+TabStripModelObserverBridge::TabStripModelObserverBridge(TabStripModel* model,
+                                                         id controller)
+    : controller_(controller), model_(model) {
+  DCHECK(model && controller);
+  // Register to be a listener on the model so we can get updates and tell
+  // |controller_| about them in the future.
+  model_->AddObserver(this);
+}
+
+TabStripModelObserverBridge::~TabStripModelObserverBridge() {
+  // Remove ourselves from receiving notifications.
+  model_->RemoveObserver(this);
+}
+
+void TabStripModelObserverBridge::TabInsertedAt(TabContentsWrapper* contents,
+                                                int index,
+                                                bool foreground) {
+  if ([controller_ respondsToSelector:
+          @selector(insertTabWithContents:atIndex:inForeground:)]) {
+    [controller_ insertTabWithContents:contents
+                               atIndex:index
+                          inForeground:foreground];
+  }
+}
+
+void TabStripModelObserverBridge::TabClosingAt(TabStripModel* tab_strip_model,
+                                               TabContentsWrapper* contents,
+                                               int index) {
+  if ([controller_ respondsToSelector:
+          @selector(tabClosingWithContents:atIndex:)]) {
+    [controller_ tabClosingWithContents:contents atIndex:index];
+  }
+}
+
+void TabStripModelObserverBridge::TabDetachedAt(TabContentsWrapper* contents,
+                                                int index) {
+  if ([controller_ respondsToSelector:
+          @selector(tabDetachedWithContents:atIndex:)]) {
+    [controller_ tabDetachedWithContents:contents atIndex:index];
+  }
+}
+
+void TabStripModelObserverBridge::TabSelectedAt(
+    TabContentsWrapper* old_contents,
+    TabContentsWrapper* new_contents,
+    int index,
+    bool user_gesture) {
+  if ([controller_ respondsToSelector:
+          @selector(selectTabWithContents:previousContents:atIndex:
+                    userGesture:)]) {
+    [controller_ selectTabWithContents:new_contents
+                      previousContents:old_contents
+                               atIndex:index
+                           userGesture:user_gesture];
+  }
+}
+
+void TabStripModelObserverBridge::TabMoved(TabContentsWrapper* contents,
+                                           int from_index,
+                                           int to_index) {
+  if ([controller_ respondsToSelector:
+       @selector(tabMovedWithContents:fromIndex:toIndex:)]) {
+    [controller_ tabMovedWithContents:contents
+                            fromIndex:from_index
+                              toIndex:to_index];
+  }
+}
+
+void TabStripModelObserverBridge::TabChangedAt(TabContentsWrapper* contents,
+                                               int index,
+                                               TabChangeType change_type) {
+  if ([controller_ respondsToSelector:
+          @selector(tabChangedWithContents:atIndex:changeType:)]) {
+    [controller_ tabChangedWithContents:contents
+                                atIndex:index
+                             changeType:change_type];
+  }
+}
+
+void TabStripModelObserverBridge::TabReplacedAt(
+    TabStripModel* tab_strip_model,
+    TabContentsWrapper* old_contents,
+    TabContentsWrapper* new_contents,
+    int index) {
+  if ([controller_ respondsToSelector:
+          @selector(tabReplacedWithContents:previousContents:atIndex:)]) {
+    [controller_ tabReplacedWithContents:new_contents
+                        previousContents:old_contents
+                                 atIndex:index];
+  } else {
+    TabChangedAt(new_contents, index, ALL);
+  }
+}
+
+void TabStripModelObserverBridge::TabMiniStateChanged(
+    TabContentsWrapper* contents, int index) {
+  if ([controller_ respondsToSelector:
+          @selector(tabMiniStateChangedWithContents:atIndex:)]) {
+    [controller_ tabMiniStateChangedWithContents:contents atIndex:index];
+  }
+}
+
+void TabStripModelObserverBridge::TabStripEmpty() {
+  if ([controller_ respondsToSelector:@selector(tabStripEmpty)])
+    [controller_ tabStripEmpty];
+}
+
+void TabStripModelObserverBridge::TabStripModelDeleted() {
+  if ([controller_ respondsToSelector:@selector(tabStripModelDeleted)])
+    [controller_ tabStripModelDeleted];
+}
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_view.h b/chrome/browser/ui/cocoa/tabs/tab_strip_view.h
new file mode 100644
index 0000000..704136e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_view.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/url_drop_target.h"
+
+@class NewTabButton;
+
+// A view class that handles rendering the tab strip and drops of URLS with
+// a positioning locator for drop feedback.
+
+@interface TabStripView : NSView<URLDropTarget> {
+ @private
+  NSTimeInterval lastMouseUp_;
+
+  // Handles being a drag-and-drop target.
+  scoped_nsobject<URLDropTargetHandler> dropHandler_;
+
+  // Weak; the following come from the nib.
+  NewTabButton* newTabButton_;
+
+  // Whether the drop-indicator arrow is shown, and if it is, the coordinate of
+  // its tip.
+  BOOL dropArrowShown_;
+  NSPoint dropArrowPosition_;
+}
+
+@property(assign, nonatomic) IBOutlet NewTabButton* newTabButton;
+@property(assign, nonatomic) BOOL dropArrowShown;
+@property(assign, nonatomic) NSPoint dropArrowPosition;
+
+@end
+
+// Protected methods subclasses can override to alter behavior. Clients should
+// not call these directly.
+@interface TabStripView(Protected)
+- (void)drawBottomBorder:(NSRect)bounds;
+- (BOOL)doubleClickMinimizesWindow;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_view.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_view.mm
new file mode 100644
index 0000000..a8a15a4
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_view.mm
@@ -0,0 +1,211 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+
+@implementation TabStripView
+
+@synthesize newTabButton = newTabButton_;
+@synthesize dropArrowShown = dropArrowShown_;
+@synthesize dropArrowPosition = dropArrowPosition_;
+
+- (id)initWithFrame:(NSRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    // Set lastMouseUp_ = -1000.0 so that timestamp-lastMouseUp_ is big unless
+    // lastMouseUp_ has been reset.
+    lastMouseUp_ = -1000.0;
+
+    // Register to be an URL drop target.
+    dropHandler_.reset([[URLDropTargetHandler alloc] initWithView:self]);
+  }
+  return self;
+}
+
+// Draw bottom border (a dark border and light highlight). Each tab is
+// responsible for mimicking this bottom border, unless it's the selected
+// tab.
+- (void)drawBorder:(NSRect)bounds {
+  NSRect borderRect, contentRect;
+
+  borderRect = bounds;
+  borderRect.origin.y = 1;
+  borderRect.size.height = 1;
+  [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
+  NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+  NSDivideRect(bounds, &borderRect, &contentRect, 1, NSMinYEdge);
+
+  BrowserThemeProvider* themeProvider =
+      static_cast<BrowserThemeProvider*>([[self window] themeProvider]);
+  if (!themeProvider)
+    return;
+
+  NSColor* bezelColor = themeProvider->GetNSColor(
+      themeProvider->UsingDefaultTheme() ?
+          BrowserThemeProvider::COLOR_TOOLBAR_BEZEL :
+          BrowserThemeProvider::COLOR_TOOLBAR, true);
+  [bezelColor set];
+  NSRectFill(borderRect);
+  NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+}
+
+- (void)drawRect:(NSRect)rect {
+  NSRect boundsRect = [self bounds];
+
+  [self drawBorder:boundsRect];
+
+  // Draw drop-indicator arrow (if appropriate).
+  // TODO(viettrungluu): this is all a stop-gap measure.
+  if ([self dropArrowShown]) {
+    // Programmer art: an arrow parametrized by many knobs. Note that the arrow
+    // points downwards (so understand "width" and "height" accordingly).
+
+    // How many (pixels) to inset on the top/bottom.
+    const CGFloat kArrowTopInset = 1.5;
+    const CGFloat kArrowBottomInset = 1;
+
+    // What proportion of the vertical space is dedicated to the arrow tip,
+    // i.e., (arrow tip height)/(amount of vertical space).
+    const CGFloat kArrowTipProportion = 0.5;
+
+    // This is a slope, i.e., (arrow tip height)/(0.5 * arrow tip width).
+    const CGFloat kArrowTipSlope = 1.2;
+
+    // What proportion of the arrow tip width is the stem, i.e., (stem
+    // width)/(arrow tip width).
+    const CGFloat kArrowStemProportion = 0.33;
+
+    NSPoint arrowTipPos = [self dropArrowPosition];
+    arrowTipPos.y += kArrowBottomInset;  // Inset on the bottom.
+
+    // Height we have to work with (insetting on the top).
+    CGFloat availableHeight =
+        NSMaxY(boundsRect) - arrowTipPos.y - kArrowTopInset;
+    DCHECK(availableHeight >= 5);
+
+    // Based on the knobs above, calculate actual dimensions which we'll need
+    // for drawing.
+    CGFloat arrowTipHeight = kArrowTipProportion * availableHeight;
+    CGFloat arrowTipWidth = 2 * arrowTipHeight / kArrowTipSlope;
+    CGFloat arrowStemHeight = availableHeight - arrowTipHeight;
+    CGFloat arrowStemWidth = kArrowStemProportion * arrowTipWidth;
+    CGFloat arrowStemInset = (arrowTipWidth - arrowStemWidth) / 2;
+
+    // The line width is arbitrary, but our path really should be mitered.
+    NSBezierPath* arrow = [NSBezierPath bezierPath];
+    [arrow setLineJoinStyle:NSMiterLineJoinStyle];
+    [arrow setLineWidth:1];
+
+    // Define the arrow's shape! We start from the tip and go clockwise.
+    [arrow moveToPoint:arrowTipPos];
+    [arrow relativeLineToPoint:NSMakePoint(-arrowTipWidth / 2, arrowTipHeight)];
+    [arrow relativeLineToPoint:NSMakePoint(arrowStemInset, 0)];
+    [arrow relativeLineToPoint:NSMakePoint(0, arrowStemHeight)];
+    [arrow relativeLineToPoint:NSMakePoint(arrowStemWidth, 0)];
+    [arrow relativeLineToPoint:NSMakePoint(0, -arrowStemHeight)];
+    [arrow relativeLineToPoint:NSMakePoint(arrowStemInset, 0)];
+    [arrow closePath];
+
+    // Draw and fill the arrow.
+    [[NSColor colorWithCalibratedWhite:0 alpha:0.67] set];
+    [arrow stroke];
+    [[NSColor colorWithCalibratedWhite:1 alpha:0.67] setFill];
+    [arrow fill];
+  }
+}
+
+// YES if a double-click in the background of the tab strip minimizes the
+// window.
+- (BOOL)doubleClickMinimizesWindow {
+  return YES;
+}
+
+// We accept first mouse so clicks onto close/zoom/miniaturize buttons and
+// title bar double-clicks are properly detected even when the window is in the
+// background.
+- (BOOL)acceptsFirstMouse:(NSEvent*)event {
+  return YES;
+}
+
+// Trap double-clicks and make them miniaturize the browser window.
+- (void)mouseUp:(NSEvent*)event {
+  // Bail early if double-clicks are disabled.
+  if (![self doubleClickMinimizesWindow]) {
+    [super mouseUp:event];
+    return;
+  }
+
+  NSInteger clickCount = [event clickCount];
+  NSTimeInterval timestamp = [event timestamp];
+
+  // Double-clicks on Zoom/Close/Mininiaturize buttons shouldn't cause
+  // miniaturization. For those, we miss the first click but get the second
+  // (with clickCount == 2!). We thus check that we got a first click shortly
+  // before (measured up-to-up) a double-click. Cocoa doesn't have a documented
+  // way of getting the proper interval (= (double-click-threshold) +
+  // (drag-threshold); the former is Carbon GetDblTime()/60.0 or
+  // com.apple.mouse.doubleClickThreshold [undocumented]). So we hard-code
+  // "short" as 0.8 seconds. (Measuring up-to-up isn't enough to properly
+  // detect double-clicks, but we're actually using Cocoa for that.)
+  if (clickCount == 2 && (timestamp - lastMouseUp_) < 0.8) {
+    if (base::mac::ShouldWindowsMiniaturizeOnDoubleClick())
+      [[self window] performMiniaturize:self];
+  } else {
+    [super mouseUp:event];
+  }
+
+  // If clickCount is 0, the drag threshold was passed.
+  lastMouseUp_ = (clickCount == 1) ? timestamp : -1000.0;
+}
+
+// (URLDropTarget protocol)
+- (id<URLDropTargetController>)urlDropController {
+  BrowserWindowController* windowController = [[self window] windowController];
+  DCHECK([windowController isKindOfClass:[BrowserWindowController class]]);
+  return [windowController tabStripController];
+}
+
+// (URLDropTarget protocol)
+- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
+  return [dropHandler_ draggingEntered:sender];
+}
+
+// (URLDropTarget protocol)
+- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
+  return [dropHandler_ draggingUpdated:sender];
+}
+
+// (URLDropTarget protocol)
+- (void)draggingExited:(id<NSDraggingInfo>)sender {
+  return [dropHandler_ draggingExited:sender];
+}
+
+// (URLDropTarget protocol)
+- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
+  return [dropHandler_ performDragOperation:sender];
+}
+
+- (BOOL)accessibilityIsIgnored {
+  return NO;
+}
+
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+  if ([attribute isEqual:NSAccessibilityRoleAttribute])
+    return NSAccessibilityGroupRole;
+
+  return [super accessibilityAttributeValue:attribute];
+}
+
+- (ViewID)viewID {
+  return VIEW_ID_TAB_STRIP;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm
new file mode 100644
index 0000000..349774b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_view_unittest.mm
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class TabStripViewTest : public CocoaTest {
+ public:
+  TabStripViewTest() {
+    NSRect frame = NSMakeRect(0, 0, 100, 30);
+    scoped_nsobject<TabStripView> view(
+        [[TabStripView alloc] initWithFrame:frame]);
+    view_ = view.get();
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  TabStripView* view_;
+};
+
+TEST_VIEW(TabStripViewTest, view_)
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.h b/chrome/browser/ui/cocoa/tabs/tab_view.h
new file mode 100644
index 0000000..9a86c20
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.h
@@ -0,0 +1,131 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_COCOA_TABS_TAB_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <map>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/background_gradient_view.h"
+#import "chrome/browser/ui/cocoa/hover_close_button.h"
+
+namespace tabs {
+
+// Nomenclature:
+// Tabs _glow_ under two different circumstances, when they are _hovered_ (by
+// the mouse) and when they are _alerted_ (to show that the tab's title has
+// changed).
+
+// The state of alerting (to show a title change on an unselected, pinned tab).
+// This is more complicated than a simple on/off since we want to allow the
+// alert glow to go through a full rise-hold-fall cycle to avoid flickering (or
+// always holding).
+enum AlertState {
+  kAlertNone = 0,  // Obj-C initializes to this.
+  kAlertRising,
+  kAlertHolding,
+  kAlertFalling
+};
+
+}  // namespace tabs
+
+@class TabController, TabWindowController;
+
+// A view that handles the event tracking (clicking and dragging) for a tab
+// on the tab strip. Relies on an associated TabController to provide a
+// target/action for selecting the tab.
+
+@interface TabView : BackgroundGradientView {
+ @private
+  IBOutlet TabController* controller_;
+  // TODO(rohitrao): Add this button to a CoreAnimation layer so we can fade it
+  // in and out on mouseovers.
+  IBOutlet HoverCloseButton* closeButton_;
+
+  BOOL closing_;
+
+  // Tracking area for close button mouseover images.
+  scoped_nsobject<NSTrackingArea> closeTrackingArea_;
+
+  BOOL isMouseInside_;  // Is the mouse hovering over?
+  tabs::AlertState alertState_;
+
+  CGFloat hoverAlpha_;  // How strong the hover glow is.
+  NSTimeInterval hoverHoldEndTime_;  // When the hover glow will begin dimming.
+
+  CGFloat alertAlpha_;  // How strong the alert glow is.
+  NSTimeInterval alertHoldEndTime_;  // When the hover glow will begin dimming.
+
+  NSTimeInterval lastGlowUpdate_;  // Time either glow was last updated.
+
+  NSPoint hoverPoint_;  // Current location of hover in view coords.
+
+  // All following variables are valid for the duration of a drag.
+  // These are released on mouseUp:
+  BOOL moveWindowOnDrag_;  // Set if the only tab of a window is dragged.
+  BOOL tabWasDragged_;  // Has the tab been dragged?
+  BOOL draggingWithinTabStrip_;  // Did drag stay in the current tab strip?
+  BOOL chromeIsVisible_;
+
+  NSTimeInterval tearTime_;  // Time since tear happened
+  NSPoint tearOrigin_;  // Origin of the tear rect
+  NSPoint dragOrigin_;  // Origin point of the drag
+  // TODO(alcor): these references may need to be strong to avoid crashes
+  // due to JS closing windows
+  TabWindowController* sourceController_;  // weak. controller starting the drag
+  NSWindow* sourceWindow_;  // weak. The window starting the drag
+  NSRect sourceWindowFrame_;
+  NSRect sourceTabFrame_;
+
+  TabWindowController* draggedController_;  // weak. Controller being dragged.
+  NSWindow* dragWindow_;  // weak. The window being dragged
+  NSWindow* dragOverlay_;  // weak. The overlay being dragged
+  // Cache workspace IDs per-drag because computing them on 10.5 with
+  // CGWindowListCreateDescriptionFromArray is expensive.
+  // resetDragControllers clears this cache.
+  //
+  // TODO(davidben): When 10.5 becomes unsupported, remove this.
+  std::map<CGWindowID, int> workspaceIDCache_;
+
+  TabWindowController* targetController_;  // weak. Controller being targeted
+  NSCellStateValue state_;
+}
+
+@property(assign, nonatomic) NSCellStateValue state;
+@property(assign, nonatomic) CGFloat hoverAlpha;
+@property(assign, nonatomic) CGFloat alertAlpha;
+
+// Determines if the tab is in the process of animating closed. It may still
+// be visible on-screen, but should not respond to/initiate any events. Upon
+// setting to NO, clears the target/action of the close button to prevent
+// clicks inside it from sending messages.
+@property(assign, nonatomic, getter=isClosing) BOOL closing;
+
+// Enables/Disables tracking regions for the tab.
+- (void)setTrackingEnabled:(BOOL)enabled;
+
+// Begin showing an "alert" glow (shown to call attention to an unselected
+// pinned tab whose title changed).
+- (void)startAlert;
+
+// Stop showing the "alert" glow; this won't immediately wipe out any glow, but
+// will make it fade away.
+- (void)cancelAlert;
+
+@end
+
+// The TabController |controller_| is not the only owner of this view. If the
+// controller is released before this view, then we could be hanging onto a
+// garbage pointer. To prevent this, the TabController uses this interface to
+// clear the |controller_| pointer when it is dying.
+@interface TabView (TabControllerInterface)
+- (void)setController:(TabController*)controller;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm
new file mode 100644
index 0000000..ba5d18c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -0,0 +1,1047 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/tabs/tab_view.h"
+
+#include "base/logging.h"
+#import "base/mac/mac_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+#include "grit/theme_resources.h"
+
+namespace {
+
+// Constants for inset and control points for tab shape.
+const CGFloat kInsetMultiplier = 2.0/3.0;
+const CGFloat kControlPoint1Multiplier = 1.0/3.0;
+const CGFloat kControlPoint2Multiplier = 3.0/8.0;
+
+// The amount of time in seconds during which each type of glow increases, holds
+// steady, and decreases, respectively.
+const NSTimeInterval kHoverShowDuration = 0.2;
+const NSTimeInterval kHoverHoldDuration = 0.02;
+const NSTimeInterval kHoverHideDuration = 0.4;
+const NSTimeInterval kAlertShowDuration = 0.4;
+const NSTimeInterval kAlertHoldDuration = 0.4;
+const NSTimeInterval kAlertHideDuration = 0.4;
+
+// The default time interval in seconds between glow updates (when
+// increasing/decreasing).
+const NSTimeInterval kGlowUpdateInterval = 0.025;
+
+const CGFloat kTearDistance = 36.0;
+const NSTimeInterval kTearDuration = 0.333;
+
+// This is used to judge whether the mouse has moved during rapid closure; if it
+// has moved less than the threshold, we want to close the tab.
+const CGFloat kRapidCloseDist = 2.5;
+
+}  // namespace
+
+@interface TabView(Private)
+
+- (void)resetLastGlowUpdateTime;
+- (NSTimeInterval)timeElapsedSinceLastGlowUpdate;
+- (void)adjustGlowValue;
+// TODO(davidben): When we stop supporting 10.5, this can be removed.
+- (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache;
+- (NSBezierPath*)bezierPathForRect:(NSRect)rect;
+
+@end  // TabView(Private)
+
+@implementation TabView
+
+@synthesize state = state_;
+@synthesize hoverAlpha = hoverAlpha_;
+@synthesize alertAlpha = alertAlpha_;
+@synthesize closing = closing_;
+
+- (id)initWithFrame:(NSRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self setShowsDivider:NO];
+    // TODO(alcor): register for theming
+  }
+  return self;
+}
+
+- (void)awakeFromNib {
+  [self setShowsDivider:NO];
+}
+
+- (void)dealloc {
+  // Cancel any delayed requests that may still be pending (drags or hover).
+  [NSObject cancelPreviousPerformRequestsWithTarget:self];
+  [super dealloc];
+}
+
+// Called to obtain the context menu for when the user hits the right mouse
+// button (or control-clicks). (Note that -rightMouseDown: is *not* called for
+// control-click.)
+- (NSMenu*)menu {
+  if ([self isClosing])
+    return nil;
+
+  // Sheets, being window-modal, should block contextual menus. For some reason
+  // they do not. Disallow them ourselves.
+  if ([[self window] attachedSheet])
+    return nil;
+
+  return [controller_ menu];
+}
+
+// Overridden so that mouse clicks come to this view (the parent of the
+// hierarchy) first. We want to handle clicks and drags in this class and
+// leave the background button for display purposes only.
+- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent {
+  return YES;
+}
+
+- (void)mouseEntered:(NSEvent*)theEvent {
+  isMouseInside_ = YES;
+  [self resetLastGlowUpdateTime];
+  [self adjustGlowValue];
+}
+
+- (void)mouseMoved:(NSEvent*)theEvent {
+  hoverPoint_ = [self convertPoint:[theEvent locationInWindow]
+                          fromView:nil];
+  [self setNeedsDisplay:YES];
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+  isMouseInside_ = NO;
+  hoverHoldEndTime_ =
+      [NSDate timeIntervalSinceReferenceDate] + kHoverHoldDuration;
+  [self resetLastGlowUpdateTime];
+  [self adjustGlowValue];
+}
+
+- (void)setTrackingEnabled:(BOOL)enabled {
+  if (![closeButton_ isHidden]) {
+    [closeButton_ setTrackingEnabled:enabled];
+  }
+}
+
+// Determines which view a click in our frame actually hit. It's either this
+// view or our child close button.
+- (NSView*)hitTest:(NSPoint)aPoint {
+  NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]];
+  NSRect frame = [self frame];
+
+  // Reduce the width of the hit rect slightly to remove the overlap
+  // between adjacent tabs.  The drawing code in TabCell has the top
+  // corners of the tab inset by height*2/3, so we inset by half of
+  // that here.  This doesn't completely eliminate the overlap, but it
+  // works well enough.
+  NSRect hitRect = NSInsetRect(frame, frame.size.height / 3.0f, 0);
+  if (![closeButton_ isHidden])
+    if (NSPointInRect(viewPoint, [closeButton_ frame])) return closeButton_;
+  if (NSPointInRect(aPoint, hitRect)) return self;
+  return nil;
+}
+
+// Returns |YES| if this tab can be torn away into a new window.
+- (BOOL)canBeDragged {
+  if ([self isClosing])
+    return NO;
+  NSWindowController* controller = [sourceWindow_ windowController];
+  if ([controller isKindOfClass:[TabWindowController class]]) {
+    TabWindowController* realController =
+        static_cast<TabWindowController*>(controller);
+    return [realController isTabDraggable:self];
+  }
+  return YES;
+}
+
+// Returns an array of controllers that could be a drop target, ordered front to
+// back. It has to be of the appropriate class, and visible (obviously). Note
+// that the window cannot be a target for itself.
+- (NSArray*)dropTargetsForController:(TabWindowController*)dragController {
+  NSMutableArray* targets = [NSMutableArray array];
+  NSWindow* dragWindow = [dragController window];
+  for (NSWindow* window in [NSApp orderedWindows]) {
+    if (window == dragWindow) continue;
+    if (![window isVisible]) continue;
+    // Skip windows on the wrong space.
+    if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
+      if (![window performSelector:@selector(isOnActiveSpace)])
+        continue;
+    } else {
+      // TODO(davidben): When we stop supporting 10.5, this can be
+      // removed.
+      //
+      // We don't cache the workspace of |dragWindow| because it may
+      // move around spaces.
+      if ([self getWorkspaceID:dragWindow useCache:NO] !=
+          [self getWorkspaceID:window useCache:YES])
+        continue;
+    }
+    NSWindowController* controller = [window windowController];
+    if ([controller isKindOfClass:[TabWindowController class]]) {
+      TabWindowController* realController =
+          static_cast<TabWindowController*>(controller);
+      if ([realController canReceiveFrom:dragController])
+        [targets addObject:controller];
+    }
+  }
+  return targets;
+}
+
+// Call to clear out transient weak references we hold during drags.
+- (void)resetDragControllers {
+  draggedController_ = nil;
+  dragWindow_ = nil;
+  dragOverlay_ = nil;
+  sourceController_ = nil;
+  sourceWindow_ = nil;
+  targetController_ = nil;
+  workspaceIDCache_.clear();
+}
+
+// Sets whether the window background should be visible or invisible when
+// dragging a tab. The background should be invisible when the mouse is over a
+// potential drop target for the tab (the tab strip). It should be visible when
+// there's no drop target so the window looks more fully realized and ready to
+// become a stand-alone window.
+- (void)setWindowBackgroundVisibility:(BOOL)shouldBeVisible {
+  if (chromeIsVisible_ == shouldBeVisible)
+    return;
+
+  // There appears to be a race-condition in CoreAnimation where if we use
+  // animators to set the alpha values, we can't guarantee that we cancel them.
+  // This has the side effect of sometimes leaving the dragged window
+  // translucent or invisible. As a result, don't animate the alpha change.
+  [[draggedController_ overlayWindow] setAlphaValue:1.0];
+  if (targetController_) {
+    [dragWindow_ setAlphaValue:0.0];
+    [[draggedController_ overlayWindow] setHasShadow:YES];
+    [[targetController_ window] makeMainWindow];
+  } else {
+    [dragWindow_ setAlphaValue:0.5];
+    [[draggedController_ overlayWindow] setHasShadow:NO];
+    [[draggedController_ window] makeMainWindow];
+  }
+  chromeIsVisible_ = shouldBeVisible;
+}
+
+// Handle clicks and drags in this button. We get here because we have
+// overridden acceptsFirstMouse: and the click is within our bounds.
+- (void)mouseDown:(NSEvent*)theEvent {
+  if ([self isClosing])
+    return;
+
+  NSPoint downLocation = [theEvent locationInWindow];
+
+  // Record the state of the close button here, because selecting the tab will
+  // unhide it.
+  BOOL closeButtonActive = [closeButton_ isHidden] ? NO : YES;
+
+  // During the tab closure animation (in particular, during rapid tab closure),
+  // we may get incorrectly hit with a mouse down. If it should have gone to the
+  // close button, we send it there -- it should then track the mouse, so we
+  // don't have to worry about mouse ups.
+  if (closeButtonActive && [controller_ inRapidClosureMode]) {
+    NSPoint hitLocation = [[self superview] convertPoint:downLocation
+                                                fromView:nil];
+    if ([self hitTest:hitLocation] == closeButton_) {
+      [closeButton_ mouseDown:theEvent];
+      return;
+    }
+  }
+
+  // Fire the action to select the tab.
+  if ([[controller_ target] respondsToSelector:[controller_ action]])
+    [[controller_ target] performSelector:[controller_ action]
+                               withObject:self];
+
+  [self resetDragControllers];
+
+  // Resolve overlay back to original window.
+  sourceWindow_ = [self window];
+  if ([sourceWindow_ isKindOfClass:[NSPanel class]]) {
+    sourceWindow_ = [sourceWindow_ parentWindow];
+  }
+
+  sourceWindowFrame_ = [sourceWindow_ frame];
+  sourceTabFrame_ = [self frame];
+  sourceController_ = [sourceWindow_ windowController];
+  tabWasDragged_ = NO;
+  tearTime_ = 0.0;
+  draggingWithinTabStrip_ = YES;
+  chromeIsVisible_ = NO;
+
+  // If there's more than one potential window to be a drop target, we want to
+  // treat a drag of a tab just like dragging around a tab that's already
+  // detached. Note that unit tests might have |-numberOfTabs| reporting zero
+  // since the model won't be fully hooked up. We need to be prepared for that
+  // and not send them into the "magnetic" codepath.
+  NSArray* targets = [self dropTargetsForController:sourceController_];
+  moveWindowOnDrag_ =
+      ([sourceController_ numberOfTabs] < 2 && ![targets count]) ||
+      ![self canBeDragged] ||
+      ![sourceController_ tabDraggingAllowed];
+  // If we are dragging a tab, a window with a single tab should immediately
+  // snap off and not drag within the tab strip.
+  if (!moveWindowOnDrag_)
+    draggingWithinTabStrip_ = [sourceController_ numberOfTabs] > 1;
+
+  dragOrigin_ = [NSEvent mouseLocation];
+
+  // If the tab gets torn off, the tab controller will be removed from the tab
+  // strip and then deallocated. This will also result in *us* being
+  // deallocated. Both these are bad, so we prevent this by retaining the
+  // controller.
+  scoped_nsobject<TabController> controller([controller_ retain]);
+
+  // Because we move views between windows, we need to handle the event loop
+  // ourselves. Ideally we should use the standard event loop.
+  while (1) {
+    theEvent =
+        [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask
+                           untilDate:[NSDate distantFuture]
+                              inMode:NSDefaultRunLoopMode dequeue:YES];
+    NSEventType type = [theEvent type];
+    if (type == NSLeftMouseDragged) {
+      [self mouseDragged:theEvent];
+    } else if (type == NSLeftMouseUp) {
+      NSPoint upLocation = [theEvent locationInWindow];
+      CGFloat dx = upLocation.x - downLocation.x;
+      CGFloat dy = upLocation.y - downLocation.y;
+
+      // During rapid tab closure (mashing tab close buttons), we may get hit
+      // with a mouse down. As long as the mouse up is over the close button,
+      // and the mouse hasn't moved too much, we close the tab.
+      if (closeButtonActive &&
+          (dx*dx + dy*dy) <= kRapidCloseDist*kRapidCloseDist &&
+          [controller inRapidClosureMode]) {
+        NSPoint hitLocation =
+            [[self superview] convertPoint:[theEvent locationInWindow]
+                                  fromView:nil];
+        if ([self hitTest:hitLocation] == closeButton_) {
+          [controller closeTab:self];
+          break;
+        }
+      }
+
+      [self mouseUp:theEvent];
+      break;
+    } else {
+      // TODO(viettrungluu): [crbug.com/23830] We can receive right-mouse-ups
+      // (and maybe even others?) for reasons I don't understand. So we
+      // explicitly check for both events we're expecting, and log others. We
+      // should figure out what's going on.
+      LOG(WARNING) << "Spurious event received of type " << type << ".";
+    }
+  }
+}
+
+- (void)mouseDragged:(NSEvent*)theEvent {
+  // Special-case this to keep the logic below simpler.
+  if (moveWindowOnDrag_) {
+    if ([sourceController_ windowMovementAllowed]) {
+      NSPoint thisPoint = [NSEvent mouseLocation];
+      NSPoint origin = sourceWindowFrame_.origin;
+      origin.x += (thisPoint.x - dragOrigin_.x);
+      origin.y += (thisPoint.y - dragOrigin_.y);
+      [sourceWindow_ setFrameOrigin:NSMakePoint(origin.x, origin.y)];
+    }  // else do nothing.
+    return;
+  }
+
+  // First, go through the magnetic drag cycle. We break out of this if
+  // "stretchiness" ever exceeds a set amount.
+  tabWasDragged_ = YES;
+
+  if (draggingWithinTabStrip_) {
+    NSPoint thisPoint = [NSEvent mouseLocation];
+    CGFloat stretchiness = thisPoint.y - dragOrigin_.y;
+    stretchiness = copysign(sqrtf(fabs(stretchiness))/sqrtf(kTearDistance),
+                            stretchiness) / 2.0;
+    CGFloat offset = thisPoint.x - dragOrigin_.x;
+    if (fabsf(offset) > 100) stretchiness = 0;
+    [sourceController_ insertPlaceholderForTab:self
+                                         frame:NSOffsetRect(sourceTabFrame_,
+                                                            offset, 0)
+                                 yStretchiness:stretchiness];
+    // Check that we haven't pulled the tab too far to start a drag. This
+    // can include either pulling it too far down, or off the side of the tab
+    // strip that would cause it to no longer be fully visible.
+    BOOL stillVisible = [sourceController_ isTabFullyVisible:self];
+    CGFloat tearForce = fabs(thisPoint.y - dragOrigin_.y);
+    if ([sourceController_ tabTearingAllowed] &&
+        (tearForce > kTearDistance || !stillVisible)) {
+      draggingWithinTabStrip_ = NO;
+      // When you finally leave the strip, we treat that as the origin.
+      dragOrigin_.x = thisPoint.x;
+    } else {
+      // Still dragging within the tab strip, wait for the next drag event.
+      return;
+    }
+  }
+
+  // Do not start dragging until the user has "torn" the tab off by
+  // moving more than 3 pixels.
+  NSDate* targetDwellDate = nil;  // The date this target was first chosen.
+
+  NSPoint thisPoint = [NSEvent mouseLocation];
+
+  // Iterate over possible targets checking for the one the mouse is in.
+  // If the tab is just in the frame, bring the window forward to make it
+  // easier to drop something there. If it's in the tab strip, set the new
+  // target so that it pops into that window. We can't cache this because we
+  // need the z-order to be correct.
+  NSArray* targets = [self dropTargetsForController:draggedController_];
+  TabWindowController* newTarget = nil;
+  for (TabWindowController* target in targets) {
+    NSRect windowFrame = [[target window] frame];
+    if (NSPointInRect(thisPoint, windowFrame)) {
+      [[target window] orderFront:self];
+      NSRect tabStripFrame = [[target tabStripView] frame];
+      tabStripFrame.origin = [[target window]
+                              convertBaseToScreen:tabStripFrame.origin];
+      if (NSPointInRect(thisPoint, tabStripFrame)) {
+        newTarget = target;
+      }
+      break;
+    }
+  }
+
+  // If we're now targeting a new window, re-layout the tabs in the old
+  // target and reset how long we've been hovering over this new one.
+  if (targetController_ != newTarget) {
+    targetDwellDate = [NSDate date];
+    [targetController_ removePlaceholder];
+    targetController_ = newTarget;
+    if (!newTarget) {
+      tearTime_ = [NSDate timeIntervalSinceReferenceDate];
+      tearOrigin_ = [dragWindow_ frame].origin;
+    }
+  }
+
+  // Create or identify the dragged controller.
+  if (!draggedController_) {
+    // Get rid of any placeholder remaining in the original source window.
+    [sourceController_ removePlaceholder];
+
+    // Detach from the current window and put it in a new window. If there are
+    // no more tabs remaining after detaching, the source window is about to
+    // go away (it's been autoreleased) so we need to ensure we don't reference
+    // it any more. In that case the new controller becomes our source
+    // controller.
+    draggedController_ = [sourceController_ detachTabToNewWindow:self];
+    dragWindow_ = [draggedController_ window];
+    [dragWindow_ setAlphaValue:0.0];
+    if (![sourceController_ hasLiveTabs]) {
+      sourceController_ = draggedController_;
+      sourceWindow_ = dragWindow_;
+    }
+
+    // If dragging the tab only moves the current window, do not show overlay
+    // so that sheets stay on top of the window.
+    // Bring the target window to the front and make sure it has a border.
+    [dragWindow_ setLevel:NSFloatingWindowLevel];
+    [dragWindow_ setHasShadow:YES];
+    [dragWindow_ orderFront:nil];
+    [dragWindow_ makeMainWindow];
+    [draggedController_ showOverlay];
+    dragOverlay_ = [draggedController_ overlayWindow];
+    // Force the new tab button to be hidden. We'll reset it on mouse up.
+    [draggedController_ showNewTabButton:NO];
+    tearTime_ = [NSDate timeIntervalSinceReferenceDate];
+    tearOrigin_ = sourceWindowFrame_.origin;
+  }
+
+  // TODO(pinkerton): http://crbug.com/25682 demonstrates a way to get here by
+  // some weird circumstance that doesn't first go through mouseDown:. We
+  // really shouldn't go any farther.
+  if (!draggedController_ || !sourceController_)
+    return;
+
+  // When the user first tears off the window, we want slide the window to
+  // the current mouse location (to reduce the jarring appearance). We do this
+  // by calling ourselves back with additional mouseDragged calls (not actual
+  // events). |tearProgress| is a normalized measure of how far through this
+  // tear "animation" (of length kTearDuration) we are and has values [0..1].
+  // We use sqrt() so the animation is non-linear (slow down near the end
+  // point).
+  NSTimeInterval tearProgress =
+      [NSDate timeIntervalSinceReferenceDate] - tearTime_;
+  tearProgress /= kTearDuration;  // Normalize.
+  tearProgress = sqrtf(MAX(MIN(tearProgress, 1.0), 0.0));
+
+  // Move the dragged window to the right place on the screen.
+  NSPoint origin = sourceWindowFrame_.origin;
+  origin.x += (thisPoint.x - dragOrigin_.x);
+  origin.y += (thisPoint.y - dragOrigin_.y);
+
+  if (tearProgress < 1) {
+    // If the tear animation is not complete, call back to ourself with the
+    // same event to animate even if the mouse isn't moving. We need to make
+    // sure these get cancelled in mouseUp:.
+    [NSObject cancelPreviousPerformRequestsWithTarget:self];
+    [self performSelector:@selector(mouseDragged:)
+               withObject:theEvent
+               afterDelay:1.0f/30.0f];
+
+    // Set the current window origin based on how far we've progressed through
+    // the tear animation.
+    origin.x = (1 - tearProgress) * tearOrigin_.x + tearProgress * origin.x;
+    origin.y = (1 - tearProgress) * tearOrigin_.y + tearProgress * origin.y;
+  }
+
+  if (targetController_) {
+    // In order to "snap" two windows of different sizes together at their
+    // toolbar, we can't just use the origin of the target frame. We also have
+    // to take into consideration the difference in height.
+    NSRect targetFrame = [[targetController_ window] frame];
+    NSRect sourceFrame = [dragWindow_ frame];
+    origin.y = NSMinY(targetFrame) +
+                (NSHeight(targetFrame) - NSHeight(sourceFrame));
+  }
+  [dragWindow_ setFrameOrigin:NSMakePoint(origin.x, origin.y)];
+
+  // If we're not hovering over any window, make the window fully
+  // opaque. Otherwise, find where the tab might be dropped and insert
+  // a placeholder so it appears like it's part of that window.
+  if (targetController_) {
+    if (![[targetController_ window] isKeyWindow]) {
+      // && ([targetDwellDate timeIntervalSinceNow] < -REQUIRED_DWELL)) {
+      [[targetController_ window] orderFront:nil];
+      targetDwellDate = nil;
+    }
+
+    // Compute where placeholder should go and insert it into the
+    // destination tab strip.
+    TabView* draggedTabView = (TabView*)[draggedController_ selectedTabView];
+    NSRect tabFrame = [draggedTabView frame];
+    tabFrame.origin = [dragWindow_ convertBaseToScreen:tabFrame.origin];
+    tabFrame.origin = [[targetController_ window]
+                        convertScreenToBase:tabFrame.origin];
+    tabFrame = [[targetController_ tabStripView]
+                convertRect:tabFrame fromView:nil];
+    [targetController_ insertPlaceholderForTab:self
+                                         frame:tabFrame
+                                 yStretchiness:0];
+    [targetController_ layoutTabs];
+  } else {
+    [dragWindow_ makeKeyAndOrderFront:nil];
+  }
+
+  // Adjust the visibility of the window background. If there is a drop target,
+  // we want to hide the window background so the tab stands out for
+  // positioning. If not, we want to show it so it looks like a new window will
+  // be realized.
+  BOOL chromeShouldBeVisible = targetController_ == nil;
+  [self setWindowBackgroundVisibility:chromeShouldBeVisible];
+}
+
+- (void)mouseUp:(NSEvent*)theEvent {
+  // The drag/click is done. If the user dragged the mouse, finalize the drag
+  // and clean up.
+
+  // Special-case this to keep the logic below simpler.
+  if (moveWindowOnDrag_)
+    return;
+
+  // Cancel any delayed -mouseDragged: requests that may still be pending.
+  [NSObject cancelPreviousPerformRequestsWithTarget:self];
+
+  // TODO(pinkerton): http://crbug.com/25682 demonstrates a way to get here by
+  // some weird circumstance that doesn't first go through mouseDown:. We
+  // really shouldn't go any farther.
+  if (!sourceController_)
+    return;
+
+  // We are now free to re-display the new tab button in the window we're
+  // dragging. It will show when the next call to -layoutTabs (which happens
+  // indrectly by several of the calls below, such as removing the placeholder).
+  [draggedController_ showNewTabButton:YES];
+
+  if (draggingWithinTabStrip_) {
+    if (tabWasDragged_) {
+      // Move tab to new location.
+      DCHECK([sourceController_ numberOfTabs]);
+      TabWindowController* dropController = sourceController_;
+      [dropController moveTabView:[dropController selectedTabView]
+                   fromController:nil];
+    }
+  } else if (targetController_) {
+    // Move between windows. If |targetController_| is nil, we're not dropping
+    // into any existing window.
+    NSView* draggedTabView = [draggedController_ selectedTabView];
+    [targetController_ moveTabView:draggedTabView
+                    fromController:draggedController_];
+    // Force redraw to avoid flashes of old content before returning to event
+    // loop.
+    [[targetController_ window] display];
+    [targetController_ showWindow:nil];
+    [draggedController_ removeOverlay];
+  } else {
+    // Only move the window around on screen. Make sure it's set back to
+    // normal state (fully opaque, has shadow, has key, etc).
+    [draggedController_ removeOverlay];
+    // Don't want to re-show the window if it was closed during the drag.
+    if ([dragWindow_ isVisible]) {
+      [dragWindow_ setAlphaValue:1.0];
+      [dragOverlay_ setHasShadow:NO];
+      [dragWindow_ setHasShadow:YES];
+      [dragWindow_ makeKeyAndOrderFront:nil];
+    }
+    [[draggedController_ window] setLevel:NSNormalWindowLevel];
+    [draggedController_ removePlaceholder];
+  }
+  [sourceController_ removePlaceholder];
+  chromeIsVisible_ = YES;
+
+  [self resetDragControllers];
+}
+
+- (void)otherMouseUp:(NSEvent*)theEvent {
+  if ([self isClosing])
+    return;
+
+  // Support middle-click-to-close.
+  if ([theEvent buttonNumber] == 2) {
+    // |-hitTest:| takes a location in the superview's coordinates.
+    NSPoint upLocation =
+        [[self superview] convertPoint:[theEvent locationInWindow]
+                              fromView:nil];
+    // If the mouse up occurred in our view or over the close button, then
+    // close.
+    if ([self hitTest:upLocation])
+      [controller_ closeTab:self];
+  }
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
+  NSGraphicsContext* context = [NSGraphicsContext currentContext];
+  [context saveGraphicsState];
+
+  BrowserThemeProvider* themeProvider =
+      static_cast<BrowserThemeProvider*>([[self window] themeProvider]);
+  [context setPatternPhase:[[self window] themePatternPhase]];
+
+  NSRect rect = [self bounds];
+  NSBezierPath* path = [self bezierPathForRect:rect];
+
+  BOOL selected = [self state];
+  // Don't draw the window/tab bar background when selected, since the tab
+  // background overlay drawn over it (see below) will be fully opaque.
+  BOOL hasBackgroundImage = NO;
+  if (!selected) {
+    // ui::ThemeProvider::HasCustomImage is true only if the theme provides the
+    // image. However, even if the theme doesn't provide a tab background, the
+    // theme machinery will make one if given a frame image. See
+    // BrowserThemePack::GenerateTabBackgroundImages for details.
+    hasBackgroundImage = themeProvider &&
+        (themeProvider->HasCustomImage(IDR_THEME_TAB_BACKGROUND) ||
+         themeProvider->HasCustomImage(IDR_THEME_FRAME));
+
+    NSColor* backgroundImageColor = hasBackgroundImage ?
+        themeProvider->GetNSImageColorNamed(IDR_THEME_TAB_BACKGROUND, true) :
+        nil;
+
+    if (backgroundImageColor) {
+      [backgroundImageColor set];
+      [path fill];
+    } else {
+      // Use the window's background color rather than |[NSColor
+      // windowBackgroundColor]|, which gets confused by the fullscreen window.
+      // (The result is the same for normal, non-fullscreen windows.)
+      [[[self window] backgroundColor] set];
+      [path fill];
+      [[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set];
+      [path fill];
+    }
+  }
+
+  [context saveGraphicsState];
+  [path addClip];
+
+  // Use the same overlay for the selected state and for hover and alert glows;
+  // for the selected state, it's fully opaque.
+  CGFloat hoverAlpha = [self hoverAlpha];
+  CGFloat alertAlpha = [self alertAlpha];
+  if (selected || hoverAlpha > 0 || alertAlpha > 0) {
+    // Draw the selected background / glow overlay.
+    [context saveGraphicsState];
+    CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
+    CGContextBeginTransparencyLayer(cgContext, 0);
+    if (!selected) {
+      // The alert glow overlay is like the selected state but at most at most
+      // 80% opaque. The hover glow brings up the overlay's opacity at most 50%.
+      CGFloat backgroundAlpha = 0.8 * alertAlpha;
+      backgroundAlpha += (1 - backgroundAlpha) * 0.5 * hoverAlpha;
+      CGContextSetAlpha(cgContext, backgroundAlpha);
+    }
+    [path addClip];
+    [context saveGraphicsState];
+    [super drawBackground];
+    [context restoreGraphicsState];
+
+    // Draw a mouse hover gradient for the default themes.
+    if (!selected && hoverAlpha > 0) {
+      if (themeProvider && !hasBackgroundImage) {
+        scoped_nsobject<NSGradient> glow([NSGradient alloc]);
+        [glow initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0
+                                        alpha:1.0 * hoverAlpha]
+                        endingColor:[NSColor colorWithCalibratedWhite:1.0
+                                                                alpha:0.0]];
+
+        NSPoint point = hoverPoint_;
+        point.y = NSHeight(rect);
+        [glow drawFromCenter:point
+                      radius:0.0
+                    toCenter:point
+                      radius:NSWidth(rect) / 3.0
+                     options:NSGradientDrawsBeforeStartingLocation];
+
+        [glow drawInBezierPath:path relativeCenterPosition:hoverPoint_];
+      }
+    }
+
+    CGContextEndTransparencyLayer(cgContext);
+    [context restoreGraphicsState];
+  }
+
+  BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow];
+  CGFloat borderAlpha = selected ? (active ? 0.3 : 0.2) : 0.2;
+  NSColor* borderColor = [NSColor colorWithDeviceWhite:0.0 alpha:borderAlpha];
+  NSColor* highlightColor = themeProvider ? themeProvider->GetNSColor(
+      themeProvider->UsingDefaultTheme() ?
+          BrowserThemeProvider::COLOR_TOOLBAR_BEZEL :
+          BrowserThemeProvider::COLOR_TOOLBAR, true) : nil;
+
+  // Draw the top inner highlight within the currently selected tab if using
+  // the default theme.
+  if (selected && themeProvider && themeProvider->UsingDefaultTheme()) {
+    NSAffineTransform* highlightTransform = [NSAffineTransform transform];
+    [highlightTransform translateXBy:1.0 yBy:-1.0];
+    scoped_nsobject<NSBezierPath> highlightPath([path copy]);
+    [highlightPath transformUsingAffineTransform:highlightTransform];
+    [highlightColor setStroke];
+    [highlightPath setLineWidth:1.0];
+    [highlightPath stroke];
+    highlightTransform = [NSAffineTransform transform];
+    [highlightTransform translateXBy:-2.0 yBy:0.0];
+    [highlightPath transformUsingAffineTransform:highlightTransform];
+    [highlightPath stroke];
+  }
+
+  [context restoreGraphicsState];
+
+  // Draw the top stroke.
+  [context saveGraphicsState];
+  [borderColor set];
+  [path setLineWidth:1.0];
+  [path stroke];
+  [context restoreGraphicsState];
+
+  // Mimic the tab strip's bottom border, which consists of a dark border
+  // and light highlight.
+  if (!selected) {
+    [path addClip];
+    NSRect borderRect = rect;
+    borderRect.origin.y = 1;
+    borderRect.size.height = 1;
+    [borderColor set];
+    NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+
+    borderRect.origin.y = 0;
+    [highlightColor set];
+    NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
+  }
+
+  [context restoreGraphicsState];
+}
+
+- (void)viewDidMoveToWindow {
+  [super viewDidMoveToWindow];
+  if ([self window]) {
+    [controller_ updateTitleColor];
+  }
+}
+
+- (void)setClosing:(BOOL)closing {
+  closing_ = closing;  // Safe because the property is nonatomic.
+  // When closing, ensure clicks to the close button go nowhere.
+  if (closing) {
+    [closeButton_ setTarget:nil];
+    [closeButton_ setAction:nil];
+  }
+}
+
+- (void)startAlert {
+  // Do not start a new alert while already alerting or while in a decay cycle.
+  if (alertState_ == tabs::kAlertNone) {
+    alertState_ = tabs::kAlertRising;
+    [self resetLastGlowUpdateTime];
+    [self adjustGlowValue];
+  }
+}
+
+- (void)cancelAlert {
+  if (alertState_ != tabs::kAlertNone) {
+    alertState_ = tabs::kAlertFalling;
+    alertHoldEndTime_ =
+        [NSDate timeIntervalSinceReferenceDate] + kGlowUpdateInterval;
+    [self resetLastGlowUpdateTime];
+    [self adjustGlowValue];
+  }
+}
+
+- (BOOL)accessibilityIsIgnored {
+  return NO;
+}
+
+- (NSArray*)accessibilityActionNames {
+  NSArray* parentActions = [super accessibilityActionNames];
+
+  return [parentActions arrayByAddingObject:NSAccessibilityPressAction];
+}
+
+- (NSArray*)accessibilityAttributeNames {
+  NSMutableArray* attributes =
+      [[super accessibilityAttributeNames] mutableCopy];
+  [attributes addObject:NSAccessibilityTitleAttribute];
+  [attributes addObject:NSAccessibilityEnabledAttribute];
+
+  return attributes;
+}
+
+- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
+  if ([attribute isEqual:NSAccessibilityTitleAttribute])
+    return NO;
+
+  if ([attribute isEqual:NSAccessibilityEnabledAttribute])
+    return NO;
+
+  return [super accessibilityIsAttributeSettable:attribute];
+}
+
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+  if ([attribute isEqual:NSAccessibilityRoleAttribute])
+    return NSAccessibilityButtonRole;
+
+  if ([attribute isEqual:NSAccessibilityTitleAttribute])
+    return [controller_ title];
+
+  if ([attribute isEqual:NSAccessibilityEnabledAttribute])
+    return [NSNumber numberWithBool:YES];
+
+  if ([attribute isEqual:NSAccessibilityChildrenAttribute]) {
+    // The subviews (icon and text) are clutter; filter out everything but
+    // useful controls.
+    NSArray* children = [super accessibilityAttributeValue:attribute];
+    NSMutableArray* okChildren = [NSMutableArray array];
+    for (id child in children) {
+      if ([child isKindOfClass:[NSButtonCell class]])
+        [okChildren addObject:child];
+    }
+
+    return okChildren;
+  }
+
+  return [super accessibilityAttributeValue:attribute];
+}
+
+- (ViewID)viewID {
+  return VIEW_ID_TAB;
+}
+
+@end  // @implementation TabView
+
+@implementation TabView (TabControllerInterface)
+
+- (void)setController:(TabController*)controller {
+  controller_ = controller;
+}
+
+@end  // @implementation TabView (TabControllerInterface)
+
+@implementation TabView(Private)
+
+- (void)resetLastGlowUpdateTime {
+  lastGlowUpdate_ = [NSDate timeIntervalSinceReferenceDate];
+}
+
+- (NSTimeInterval)timeElapsedSinceLastGlowUpdate {
+  return [NSDate timeIntervalSinceReferenceDate] - lastGlowUpdate_;
+}
+
+- (void)adjustGlowValue {
+  // A time interval long enough to represent no update.
+  const NSTimeInterval kNoUpdate = 1000000;
+
+  // Time until next update for either glow.
+  NSTimeInterval nextUpdate = kNoUpdate;
+
+  NSTimeInterval elapsed = [self timeElapsedSinceLastGlowUpdate];
+  NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
+
+  // TODO(viettrungluu): <http://crbug.com/30617> -- split off the stuff below
+  // into a pure function and add a unit test.
+
+  CGFloat hoverAlpha = [self hoverAlpha];
+  if (isMouseInside_) {
+    // Increase hover glow until it's 1.
+    if (hoverAlpha < 1) {
+      hoverAlpha = MIN(hoverAlpha + elapsed / kHoverShowDuration, 1);
+      [self setHoverAlpha:hoverAlpha];
+      nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+    }  // Else already 1 (no update needed).
+  } else {
+    if (currentTime >= hoverHoldEndTime_) {
+      // No longer holding, so decrease hover glow until it's 0.
+      if (hoverAlpha > 0) {
+        hoverAlpha = MAX(hoverAlpha - elapsed / kHoverHideDuration, 0);
+        [self setHoverAlpha:hoverAlpha];
+        nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+      }  // Else already 0 (no update needed).
+    } else {
+      // Schedule update for end of hold time.
+      nextUpdate = MIN(hoverHoldEndTime_ - currentTime, nextUpdate);
+    }
+  }
+
+  CGFloat alertAlpha = [self alertAlpha];
+  if (alertState_ == tabs::kAlertRising) {
+    // Increase alert glow until it's 1 ...
+    alertAlpha = MIN(alertAlpha + elapsed / kAlertShowDuration, 1);
+    [self setAlertAlpha:alertAlpha];
+
+    // ... and having reached 1, switch to holding.
+    if (alertAlpha >= 1) {
+      alertState_ = tabs::kAlertHolding;
+      alertHoldEndTime_ = currentTime + kAlertHoldDuration;
+      nextUpdate = MIN(kAlertHoldDuration, nextUpdate);
+    } else {
+      nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+    }
+  } else if (alertState_ != tabs::kAlertNone) {
+    if (alertAlpha > 0) {
+      if (currentTime >= alertHoldEndTime_) {
+        // Stop holding, then decrease alert glow (until it's 0).
+        if (alertState_ == tabs::kAlertHolding) {
+          alertState_ = tabs::kAlertFalling;
+          nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+        } else {
+          DCHECK_EQ(tabs::kAlertFalling, alertState_);
+          alertAlpha = MAX(alertAlpha - elapsed / kAlertHideDuration, 0);
+          [self setAlertAlpha:alertAlpha];
+          nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+        }
+      } else {
+        // Schedule update for end of hold time.
+        nextUpdate = MIN(alertHoldEndTime_ - currentTime, nextUpdate);
+      }
+    } else {
+      // Done the alert decay cycle.
+      alertState_ = tabs::kAlertNone;
+    }
+  }
+
+  if (nextUpdate < kNoUpdate)
+    [self performSelector:_cmd withObject:nil afterDelay:nextUpdate];
+
+  [self resetLastGlowUpdateTime];
+  [self setNeedsDisplay:YES];
+}
+
+// Returns the workspace id of |window|. If |useCache|, then lookup
+// and remember the value in |workspaceIDCache_| until the end of the
+// current drag.
+- (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache {
+  CGWindowID windowID = [window windowNumber];
+  if (useCache) {
+    std::map<CGWindowID, int>::iterator iter =
+        workspaceIDCache_.find(windowID);
+    if (iter != workspaceIDCache_.end())
+      return iter->second;
+  }
+
+  int workspace = -1;
+  // It's possible to query in bulk, but probably not necessary.
+  base::mac::ScopedCFTypeRef<CFArrayRef> windowIDs(CFArrayCreate(
+      NULL, reinterpret_cast<const void **>(&windowID), 1, NULL));
+  base::mac::ScopedCFTypeRef<CFArrayRef> descriptions(
+      CGWindowListCreateDescriptionFromArray(windowIDs));
+  DCHECK(CFArrayGetCount(descriptions.get()) <= 1);
+  if (CFArrayGetCount(descriptions.get()) > 0) {
+    CFDictionaryRef dict = static_cast<CFDictionaryRef>(
+        CFArrayGetValueAtIndex(descriptions.get(), 0));
+    DCHECK(CFGetTypeID(dict) == CFDictionaryGetTypeID());
+
+    // Sanity check the ID.
+    CFNumberRef otherIDRef = (CFNumberRef)base::mac::GetValueFromDictionary(
+        dict, kCGWindowNumber, CFNumberGetTypeID());
+    CGWindowID otherID;
+    if (otherIDRef &&
+        CFNumberGetValue(otherIDRef, kCGWindowIDCFNumberType, &otherID) &&
+        otherID == windowID) {
+      // And then get the workspace.
+      CFNumberRef workspaceRef = (CFNumberRef)base::mac::GetValueFromDictionary(
+          dict, kCGWindowWorkspace, CFNumberGetTypeID());
+      if (!workspaceRef ||
+          !CFNumberGetValue(workspaceRef, kCFNumberIntType, &workspace)) {
+        workspace = -1;
+      }
+    } else {
+      NOTREACHED();
+    }
+  }
+  if (useCache) {
+    workspaceIDCache_[windowID] = workspace;
+  }
+  return workspace;
+}
+
+// Returns the bezier path used to draw the tab given the bounds to draw it in.
+- (NSBezierPath*)bezierPathForRect:(NSRect)rect {
+  // Outset by 0.5 in order to draw on pixels rather than on borders (which
+  // would cause blurry pixels). Subtract 1px of height to compensate, otherwise
+  // clipping will occur.
+  rect = NSInsetRect(rect, -0.5, -0.5);
+  rect.size.height -= 1.0;
+
+  NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect) + 2);
+  NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect) + 2);
+  NSPoint topRight =
+      NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect),
+                  NSMaxY(rect));
+  NSPoint topLeft =
+      NSMakePoint(NSMinX(rect)  + kInsetMultiplier * NSHeight(rect),
+                  NSMaxY(rect));
+
+  CGFloat baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier;
+  CGFloat bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier;
+
+  // Outset many of these values by 1 to cause the fill to bleed outside the
+  // clip area.
+  NSBezierPath* path = [NSBezierPath bezierPath];
+  [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y - 2)];
+  [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)];
+  [path lineToPoint:bottomLeft];
+  [path curveToPoint:topLeft
+       controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset,
+                                 bottomLeft.y)
+       controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset,
+                                 topLeft.y)];
+  [path lineToPoint:topRight];
+  [path curveToPoint:bottomRight
+       controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset,
+                                 topRight.y)
+       controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset,
+                                 bottomRight.y)];
+  [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)];
+  [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y - 2)];
+  return path;
+}
+
+@end  // @implementation TabView(Private)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
new file mode 100644
index 0000000..548dd0f
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
@@ -0,0 +1,60 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_view.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class TabViewTest : public CocoaTest {
+ public:
+  TabViewTest() {
+    NSRect frame = NSMakeRect(0, 0, 50, 30);
+    scoped_nsobject<TabView> view([[TabView alloc] initWithFrame:frame]);
+    view_ = view.get();
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  TabView* view_;
+};
+
+TEST_VIEW(TabViewTest, view_)
+
+// Test drawing, mostly to ensure nothing leaks or crashes.
+TEST_F(TabViewTest, Display) {
+  for (int i = 0; i < 5; i++) {
+    for (int j = 0; j < 5; j++) {
+      [view_ setHoverAlpha:i*0.2];
+      [view_ setAlertAlpha:j*0.2];
+      [view_ display];
+    }
+  }
+}
+
+// Test it doesn't crash when asked for its menu with no TabController set.
+TEST_F(TabViewTest, Menu) {
+  EXPECT_FALSE([view_ menu]);
+}
+
+TEST_F(TabViewTest, Glow) {
+  // TODO(viettrungluu): Figure out how to test this, which is timing-sensitive
+  // and which moreover uses |-performSelector:withObject:afterDelay:|.
+
+  // Call |-startAlert|/|-cancelAlert| and make sure it doesn't crash.
+  for (int i = 0; i < 5; i++) {
+    [view_ startAlert];
+    [view_ cancelAlert];
+  }
+  [view_ startAlert];
+  [view_ startAlert];
+  [view_ cancelAlert];
+  [view_ cancelAlert];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/tabs/tab_window_controller.h b/chrome/browser/ui/cocoa/tabs/tab_window_controller.h
new file mode 100644
index 0000000..db4092e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_window_controller.h
@@ -0,0 +1,180 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_TAB_WINDOW_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_TAB_WINDOW_CONTROLLER_H_
+#pragma once
+
+// A class acting as the Objective-C window controller for a window that has
+// tabs which can be dragged around. Tabs can be re-arranged within the same
+// window or dragged into other TabWindowController windows. This class doesn't
+// know anything about the actual tab implementation or model, as that is fairly
+// application-specific. It only provides an API to be overridden by subclasses
+// to fill in the details.
+//
+// This assumes that there will be a view in the nib, connected to
+// |tabContentArea_|, that indicates the content that it switched when switching
+// between tabs. It needs to be a regular NSView, not something like an NSBox
+// because the TabStripController makes certain assumptions about how it can
+// swap out subviews.
+//
+// The tab strip can exist in different orientations and window locations,
+// depending on the return value of -usesVerticalTabs. If NO (the default),
+// the tab strip is placed outside the window's content area, overlapping the
+// title area and window controls and will be stretched to fill the width
+// of the window. If YES, the tab strip is vertical and lives within the
+// window's content area. It will be stretched to fill the window's height.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_nsobject.h"
+
+@class FastResizeView;
+@class FocusTracker;
+@class TabStripView;
+@class TabView;
+
+@interface TabWindowController : NSWindowController<NSWindowDelegate> {
+ @private
+  IBOutlet FastResizeView* tabContentArea_;
+  // TODO(pinkerton): Figure out a better way to initialize one or the other
+  // w/out needing both to be in the nib.
+  IBOutlet TabStripView* topTabStripView_;
+  IBOutlet TabStripView* sideTabStripView_;
+  NSWindow* overlayWindow_;  // Used during dragging for window opacity tricks
+  NSView* cachedContentView_;  // Used during dragging for identifying which
+                               // view is the proper content area in the overlay
+                               // (weak)
+  scoped_nsobject<FocusTracker> focusBeforeOverlay_;
+  scoped_nsobject<NSMutableSet> lockedTabs_;
+  BOOL closeDeferred_;  // If YES, call performClose: in removeOverlay:.
+  // Difference between height of window content area and height of the
+  // |tabContentArea_|. Calculated when the window is loaded from the nib and
+  // cached in order to restore the delta when switching tab modes.
+  CGFloat contentAreaHeightDelta_;
+}
+@property(readonly, nonatomic) TabStripView* tabStripView;
+@property(readonly, nonatomic) FastResizeView* tabContentArea;
+
+// Used during tab dragging to turn on/off the overlay window when a tab
+// is torn off. If -deferPerformClose (below) is used, -removeOverlay will
+// cause the controller to be autoreleased before returning.
+- (void)showOverlay;
+- (void)removeOverlay;
+- (NSWindow*)overlayWindow;
+
+// Returns YES if it is ok to constrain the window's frame to fit the screen.
+- (BOOL)shouldConstrainFrameRect;
+
+// A collection of methods, stubbed out in this base class, that provide
+// the implementation of tab dragging based on whatever model is most
+// appropriate.
+
+// Layout the tabs based on the current ordering of the model.
+- (void)layoutTabs;
+
+// Creates a new window by pulling the given tab out and placing it in
+// the new window. Returns the controller for the new window. The size of the
+// new window will be the same size as this window.
+- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView;
+
+// Make room in the tab strip for |tab| at the given x coordinate. Will hide the
+// new tab button while there's a placeholder. Subclasses need to call the
+// superclass implementation.
+- (void)insertPlaceholderForTab:(TabView*)tab
+                          frame:(NSRect)frame
+                  yStretchiness:(CGFloat)yStretchiness;
+
+// Removes the placeholder installed by |-insertPlaceholderForTab:atLocation:|
+// and restores the new tab button. Subclasses need to call the superclass
+// implementation.
+- (void)removePlaceholder;
+
+// Returns whether one of the window's tabs is being dragged.
+- (BOOL)isDragSessionActive;
+
+// The follow return YES if tab dragging/tab tearing (off the tab strip)/window
+// movement is currently allowed. Any number of things can choose to disable it,
+// such as pending animations. The default implementations always return YES.
+// Subclasses should override as appropriate.
+- (BOOL)tabDraggingAllowed;
+- (BOOL)tabTearingAllowed;
+- (BOOL)windowMovementAllowed;
+
+// Show or hide the new tab button. The button is hidden immediately, but
+// waits until the next call to |-layoutTabs| to show it again.
+- (void)showNewTabButton:(BOOL)show;
+
+// Returns whether or not |tab| can still be fully seen in the tab strip or if
+// its current position would cause it be obscured by things such as the edge
+// of the window or the window decorations. Returns YES only if the entire tab
+// is visible. The default implementation always returns YES.
+- (BOOL)isTabFullyVisible:(TabView*)tab;
+
+// Called to check if the receiver can receive dragged tabs from
+// source.  Return YES if so.  The default implementation returns NO.
+- (BOOL)canReceiveFrom:(TabWindowController*)source;
+
+// Move a given tab view to the location of the current placeholder. If there is
+// no placeholder, it will go at the end. |controller| is the window controller
+// of a tab being dropped from a different window. It will be nil if the drag is
+// within the window, otherwise the tab is removed from that window before being
+// placed into this one. The implementation will call |-removePlaceholder| since
+// the drag is now complete.  This also calls |-layoutTabs| internally so
+// clients do not need to call it again.
+- (void)moveTabView:(NSView*)view
+     fromController:(TabWindowController*)controller;
+
+// Number of tabs in the tab strip. Useful, for example, to know if we're
+// dragging the only tab in the window. This includes pinned tabs (both live
+// and not).
+- (NSInteger)numberOfTabs;
+
+// YES if there are tabs in the tab strip which have content, allowing for
+// the notion of tabs in the tab strip that are placeholders but currently have
+// no content.
+- (BOOL)hasLiveTabs;
+
+// Return the view of the selected tab.
+- (NSView *)selectedTabView;
+
+// The title of the selected tab.
+- (NSString*)selectedTabTitle;
+
+// Called to check whether or not this controller's window has a tab strip (YES
+// if it does, NO otherwise). The default implementation returns YES.
+- (BOOL)hasTabStrip;
+
+// Returns YES if the tab strip lives in the window content area alongside the
+// tab contents. Returns NO if the tab strip is outside the window content
+// area, along the top of the window.
+- (BOOL)useVerticalTabs;
+
+// Get/set whether a particular tab is draggable between windows.
+- (BOOL)isTabDraggable:(NSView*)tabView;
+- (void)setTab:(NSView*)tabView isDraggable:(BOOL)draggable;
+
+// Tell the window that it needs to call performClose: as soon as the current
+// drag is complete. This prevents a window (and its overlay) from going away
+// during a drag.
+- (void)deferPerformClose;
+
+@end
+
+@interface TabWindowController(ProtectedMethods)
+// Tells the tab strip to forget about this tab in preparation for it being
+// put into a different tab strip, such as during a drop on another window.
+- (void)detachTabView:(NSView*)view;
+
+// Toggles from one display mode of the tab strip to another. Will automatically
+// call -layoutSubviews to reposition other content.
+- (void)toggleTabStripDisplayMode;
+
+// Called when the size of the window content area has changed. Override to
+// position specific views. Base class implementation does nothing.
+- (void)layoutSubviews;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_WINDOW_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
new file mode 100644
index 0000000..5497eda
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
@@ -0,0 +1,356 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
+
+#include "base/logging.h"
+#import "chrome/browser/ui/cocoa/focus_tracker.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#include "ui/base/theme_provider.h"
+
+@interface TabWindowController(PRIVATE)
+- (void)setUseOverlay:(BOOL)useOverlay;
+@end
+
+@interface TabWindowOverlayWindow : NSWindow
+@end
+
+@implementation TabWindowOverlayWindow
+
+- (ui::ThemeProvider*)themeProvider {
+  if ([self parentWindow])
+    return [[[self parentWindow] windowController] themeProvider];
+  return NULL;
+}
+
+- (ThemedWindowStyle)themedWindowStyle {
+  if ([self parentWindow])
+    return [[[self parentWindow] windowController] themedWindowStyle];
+  return NO;
+}
+
+- (NSPoint)themePatternPhase {
+  if ([self parentWindow])
+    return [[[self parentWindow] windowController] themePatternPhase];
+  return NSZeroPoint;
+}
+
+@end
+
+@implementation TabWindowController
+@synthesize tabContentArea = tabContentArea_;
+
+- (id)initWithWindow:(NSWindow*)window {
+  if ((self = [super initWithWindow:window]) != nil) {
+    lockedTabs_.reset([[NSMutableSet alloc] initWithCapacity:10]);
+  }
+  return self;
+}
+
+// Add the side tab strip to the left side of the window's content area,
+// making it fill the full height of the content area.
+- (void)addSideTabStripToWindow {
+  NSView* contentView = [[self window] contentView];
+  NSRect contentFrame = [contentView frame];
+  NSRect sideStripFrame =
+      NSMakeRect(0, 0,
+                 NSWidth([sideTabStripView_ frame]),
+                 NSHeight(contentFrame));
+  [sideTabStripView_ setFrame:sideStripFrame];
+  [contentView addSubview:sideTabStripView_];
+}
+
+// Add the top tab strop to the window, above the content box and add it to the
+// view hierarchy as a sibling of the content view so it can overlap with the
+// window frame.
+- (void)addTopTabStripToWindow {
+  NSRect contentFrame = [tabContentArea_ frame];
+  NSRect tabFrame =
+      NSMakeRect(0, NSMaxY(contentFrame),
+                 NSWidth(contentFrame),
+                 NSHeight([topTabStripView_ frame]));
+  [topTabStripView_ setFrame:tabFrame];
+  NSView* contentParent = [[[self window] contentView] superview];
+  [contentParent addSubview:topTabStripView_];
+}
+
+- (void)windowDidLoad {
+  // Cache the difference in height between the window content area and the
+  // tab content area.
+  NSRect tabFrame = [tabContentArea_ frame];
+  NSRect contentFrame = [[[self window] contentView] frame];
+  contentAreaHeightDelta_ = NSHeight(contentFrame) - NSHeight(tabFrame);
+
+  if ([self hasTabStrip]) {
+    if ([self useVerticalTabs]) {
+      // No top tabstrip so remove the tabContentArea offset.
+      tabFrame.size.height = contentFrame.size.height;
+      [tabContentArea_ setFrame:tabFrame];
+      [self addSideTabStripToWindow];
+    } else {
+      [self addTopTabStripToWindow];
+    }
+  } else {
+    // No top tabstrip so remove the tabContentArea offset.
+    tabFrame.size.height = contentFrame.size.height;
+    [tabContentArea_ setFrame:tabFrame];
+  }
+}
+
+// Toggles from one display mode of the tab strip to another. Will automatically
+// call -layoutSubviews to reposition other content.
+- (void)toggleTabStripDisplayMode {
+  // Adjust the size of the tab contents to either use more or less space,
+  // depending on the direction of the toggle. This needs to be done prior to
+  // adding back in the top tab strip as its position is based off the MaxY
+  // of the tab content area.
+  BOOL useVertical = [self useVerticalTabs];
+  NSRect tabContentsFrame = [tabContentArea_ frame];
+  tabContentsFrame.size.height += useVertical ?
+      contentAreaHeightDelta_ : -contentAreaHeightDelta_;
+  [tabContentArea_ setFrame:tabContentsFrame];
+
+  if (useVertical) {
+    // Remove the top tab strip and add the sidebar in.
+    [topTabStripView_ removeFromSuperview];
+    [self addSideTabStripToWindow];
+  } else {
+    // Remove the side tab strip and add the top tab strip as a sibling of the
+    // window's content area.
+    [sideTabStripView_ removeFromSuperview];
+    NSRect tabContentsFrame = [tabContentArea_ frame];
+    tabContentsFrame.size.height -= contentAreaHeightDelta_;
+    [tabContentArea_ setFrame:tabContentsFrame];
+    [self addTopTabStripToWindow];
+  }
+
+  [self layoutSubviews];
+}
+
+// Return the appropriate tab strip based on whether or not side tabs are
+// enabled.
+- (TabStripView*)tabStripView {
+  if ([self useVerticalTabs])
+    return sideTabStripView_;
+  return topTabStripView_;
+}
+
+- (void)removeOverlay {
+  [self setUseOverlay:NO];
+  if (closeDeferred_) {
+    // See comment in BrowserWindowCocoa::Close() about orderOut:.
+    [[self window] orderOut:self];
+    [[self window] performClose:self];  // Autoreleases the controller.
+  }
+}
+
+- (void)showOverlay {
+  [self setUseOverlay:YES];
+}
+
+// if |useOverlay| is true, we're moving views into the overlay's content
+// area. If false, we're moving out of the overlay back into the window's
+// content.
+- (void)moveViewsBetweenWindowAndOverlay:(BOOL)useOverlay {
+  if (useOverlay) {
+    [[[overlayWindow_ contentView] superview] addSubview:[self tabStripView]];
+    // Add the original window's content view as a subview of the overlay
+    // window's content view.  We cannot simply use setContentView: here because
+    // the overlay window has a different content size (due to it being
+    // borderless).
+    [[overlayWindow_ contentView] addSubview:cachedContentView_];
+  } else {
+    [[self window] setContentView:cachedContentView_];
+    // The TabStripView always needs to be in front of the window's content
+    // view and therefore it should always be added after the content view is
+    // set.
+    [[[[self window] contentView] superview] addSubview:[self tabStripView]];
+    [[[[self window] contentView] superview] updateTrackingAreas];
+  }
+}
+
+// If |useOverlay| is YES, creates a new overlay window and puts the tab strip
+// and the content area inside of it. This allows it to have a different opacity
+// from the title bar. If NO, returns everything to the previous state and
+// destroys the overlay window until it's needed again. The tab strip and window
+// contents are returned to the original window.
+- (void)setUseOverlay:(BOOL)useOverlay {
+  [NSObject cancelPreviousPerformRequestsWithTarget:self
+                                           selector:@selector(removeOverlay)
+                                             object:nil];
+  NSWindow* window = [self window];
+  if (useOverlay && !overlayWindow_) {
+    DCHECK(!cachedContentView_);
+    overlayWindow_ = [[TabWindowOverlayWindow alloc]
+                         initWithContentRect:[window frame]
+                                   styleMask:NSBorderlessWindowMask
+                                     backing:NSBackingStoreBuffered
+                                       defer:YES];
+    [overlayWindow_ setTitle:@"overlay"];
+    [overlayWindow_ setBackgroundColor:[NSColor clearColor]];
+    [overlayWindow_ setOpaque:NO];
+    [overlayWindow_ setDelegate:self];
+    cachedContentView_ = [window contentView];
+    [window addChildWindow:overlayWindow_ ordered:NSWindowAbove];
+    // Sets explictly nil to the responder and then restores it.
+    // Leaving the first responder non-null here
+    // causes [RenderWidgethostViewCocoa resignFirstResponder] and
+    // following RenderWidgetHost::Blur(), which results unexpected
+    // focus lost.
+    focusBeforeOverlay_.reset([[FocusTracker alloc] initWithWindow:window]);
+    [window makeFirstResponder:nil];
+    [self moveViewsBetweenWindowAndOverlay:useOverlay];
+    [overlayWindow_ orderFront:nil];
+  } else if (!useOverlay && overlayWindow_) {
+    DCHECK(cachedContentView_);
+    [window setContentView:cachedContentView_];
+    [self moveViewsBetweenWindowAndOverlay:useOverlay];
+    [focusBeforeOverlay_ restoreFocusInWindow:window];
+    focusBeforeOverlay_.reset(nil);
+    [window display];
+    [window removeChildWindow:overlayWindow_];
+    [overlayWindow_ orderOut:nil];
+    [overlayWindow_ release];
+    overlayWindow_ = nil;
+    cachedContentView_ = nil;
+  } else {
+    NOTREACHED();
+  }
+}
+
+- (NSWindow*)overlayWindow {
+  return overlayWindow_;
+}
+
+- (BOOL)shouldConstrainFrameRect {
+  // If we currently have an overlay window, do not attempt to change the
+  // window's size, as our overlay window doesn't know how to resize properly.
+  return overlayWindow_ == nil;
+}
+
+- (BOOL)canReceiveFrom:(TabWindowController*)source {
+  // subclass must implement
+  NOTIMPLEMENTED();
+  return NO;
+}
+
+- (void)moveTabView:(NSView*)view
+     fromController:(TabWindowController*)dragController {
+  NOTIMPLEMENTED();
+}
+
+- (NSView*)selectedTabView {
+  NOTIMPLEMENTED();
+  return nil;
+}
+
+- (void)layoutTabs {
+  // subclass must implement
+  NOTIMPLEMENTED();
+}
+
+- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView {
+  // subclass must implement
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+- (void)insertPlaceholderForTab:(TabView*)tab
+                          frame:(NSRect)frame
+                  yStretchiness:(CGFloat)yStretchiness {
+  [self showNewTabButton:NO];
+}
+
+- (void)removePlaceholder {
+  [self showNewTabButton:YES];
+}
+
+- (BOOL)isDragSessionActive {
+  NOTIMPLEMENTED();
+  return NO;
+}
+
+- (BOOL)tabDraggingAllowed {
+  return YES;
+}
+
+- (BOOL)tabTearingAllowed {
+  return YES;
+}
+
+- (BOOL)windowMovementAllowed {
+  return YES;
+}
+
+- (BOOL)isTabFullyVisible:(TabView*)tab {
+  // Subclasses should implement this, but it's not necessary.
+  return YES;
+}
+
+- (void)showNewTabButton:(BOOL)show {
+  // subclass must implement
+  NOTIMPLEMENTED();
+}
+
+- (void)detachTabView:(NSView*)view {
+  // subclass must implement
+  NOTIMPLEMENTED();
+}
+
+- (NSInteger)numberOfTabs {
+  // subclass must implement
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+- (BOOL)hasLiveTabs {
+  // subclass must implement
+  NOTIMPLEMENTED();
+  return NO;
+}
+
+- (NSString*)selectedTabTitle {
+  // subclass must implement
+  NOTIMPLEMENTED();
+  return @"";
+}
+
+- (BOOL)hasTabStrip {
+  // Subclasses should implement this.
+  NOTIMPLEMENTED();
+  return YES;
+}
+
+- (BOOL)useVerticalTabs {
+  // Subclasses should implement this.
+  NOTIMPLEMENTED();
+  return NO;
+}
+
+- (BOOL)isTabDraggable:(NSView*)tabView {
+  return ![lockedTabs_ containsObject:tabView];
+}
+
+- (void)setTab:(NSView*)tabView isDraggable:(BOOL)draggable {
+  if (draggable)
+    [lockedTabs_ removeObject:tabView];
+  else
+    [lockedTabs_ addObject:tabView];
+}
+
+// Tell the window that it needs to call performClose: as soon as the current
+// drag is complete. This prevents a window (and its overlay) from going away
+// during a drag.
+- (void)deferPerformClose {
+  closeDeferred_ = YES;
+}
+
+// Called when the size of the window content area has changed. Override to
+// position specific views. Base class implementation does nothing.
+- (void)layoutSubviews {
+  NOTIMPLEMENTED();
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/throbber_view.h b/chrome/browser/ui/cocoa/tabs/throbber_view.h
new file mode 100644
index 0000000..6cbd9f8
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/throbber_view.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TABS_THROBBER_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_TABS_THROBBER_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+
+@protocol ThrobberDataDelegate;
+
+// A class that knows how to draw an animated state to indicate progress.
+// Creating the class starts the animation, destroying it stops it. There are
+// two types:
+//
+// - Filmstrip: Draws via a sequence of frames in an image. There is no state
+//   where the class is frozen on an image and not animating. The image needs to
+//   be made of squares such that the height divides evenly into the width.
+//
+// - Toast: Draws an image animating down to the bottom and then another image
+//   animating up from the bottom. Stops once the animation is complete.
+
+@interface ThrobberView : NSView {
+ @private
+  id<ThrobberDataDelegate> dataDelegate_;
+}
+
+// Creates a filmstrip view with |frame| and image |image|.
++ (id)filmstripThrobberViewWithFrame:(NSRect)frame
+                               image:(NSImage*)image;
+
+// Creates a toast view with |frame| and specified images.
++ (id)toastThrobberViewWithFrame:(NSRect)frame
+                     beforeImage:(NSImage*)beforeImage
+                      afterImage:(NSImage*)afterImage;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TABS_THROBBER_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/tabs/throbber_view.mm b/chrome/browser/ui/cocoa/tabs/throbber_view.mm
new file mode 100644
index 0000000..29cc6df
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/throbber_view.mm
@@ -0,0 +1,372 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/tabs/throbber_view.h"
+
+#include <set>
+
+#include "base/logging.h"
+
+static const float kAnimationIntervalSeconds = 0.03;  // 30ms, same as windows
+
+@interface ThrobberView(PrivateMethods)
+- (id)initWithFrame:(NSRect)frame delegate:(id<ThrobberDataDelegate>)delegate;
+- (void)maintainTimer;
+- (void)animate;
+@end
+
+@protocol ThrobberDataDelegate <NSObject>
+// Is the current frame the last frame of the animation?
+- (BOOL)animationIsComplete;
+
+// Draw the current frame into the current graphics context.
+- (void)drawFrameInRect:(NSRect)rect;
+
+// Update the frame counter.
+- (void)advanceFrame;
+@end
+
+@interface ThrobberFilmstripDelegate : NSObject
+                                       <ThrobberDataDelegate> {
+  scoped_nsobject<NSImage> image_;
+  unsigned int numFrames_;  // Number of frames in this animation.
+  unsigned int animationFrame_;  // Current frame of the animation,
+                                 // [0..numFrames_)
+}
+
+- (id)initWithImage:(NSImage*)image;
+
+@end
+
+@implementation ThrobberFilmstripDelegate
+
+- (id)initWithImage:(NSImage*)image {
+  if ((self = [super init])) {
+    // Reset the animation counter so there's no chance we are off the end.
+    animationFrame_ = 0;
+
+    // Ensure that the height divides evenly into the width. Cache the
+    // number of frames in the animation for later.
+    NSSize imageSize = [image size];
+    DCHECK(imageSize.height && imageSize.width);
+    if (!imageSize.height)
+      return nil;
+    DCHECK((int)imageSize.width % (int)imageSize.height == 0);
+    numFrames_ = (int)imageSize.width / (int)imageSize.height;
+    DCHECK(numFrames_);
+    image_.reset([image retain]);
+  }
+  return self;
+}
+
+- (BOOL)animationIsComplete {
+  return NO;
+}
+
+- (void)drawFrameInRect:(NSRect)rect {
+  float imageDimension = [image_ size].height;
+  float xOffset = animationFrame_ * imageDimension;
+  NSRect sourceImageRect =
+      NSMakeRect(xOffset, 0, imageDimension, imageDimension);
+  [image_ drawInRect:rect
+            fromRect:sourceImageRect
+           operation:NSCompositeSourceOver
+            fraction:1.0];
+}
+
+- (void)advanceFrame {
+  animationFrame_ = ++animationFrame_ % numFrames_;
+}
+
+@end
+
+@interface ThrobberToastDelegate : NSObject
+                                   <ThrobberDataDelegate> {
+  scoped_nsobject<NSImage> image1_;
+  scoped_nsobject<NSImage> image2_;
+  NSSize image1Size_;
+  NSSize image2Size_;
+  int animationFrame_;  // Current frame of the animation,
+}
+
+- (id)initWithImage1:(NSImage*)image1 image2:(NSImage*)image2;
+
+@end
+
+@implementation ThrobberToastDelegate
+
+- (id)initWithImage1:(NSImage*)image1 image2:(NSImage*)image2 {
+  if ((self = [super init])) {
+    image1_.reset([image1 retain]);
+    image2_.reset([image2 retain]);
+    image1Size_ = [image1 size];
+    image2Size_ = [image2 size];
+    animationFrame_ = 0;
+  }
+  return self;
+}
+
+- (BOOL)animationIsComplete {
+  if (animationFrame_ >= image1Size_.height + image2Size_.height)
+    return YES;
+
+  return NO;
+}
+
+// From [0..image1Height) we draw image1, at image1Height we draw nothing, and
+// from [image1Height+1..image1Hight+image2Height] we draw the second image.
+- (void)drawFrameInRect:(NSRect)rect {
+  NSImage* image = nil;
+  NSSize srcSize;
+  NSRect destRect;
+
+  if (animationFrame_ < image1Size_.height) {
+    image = image1_.get();
+    srcSize = image1Size_;
+    destRect = NSMakeRect(0, -animationFrame_,
+                          image1Size_.width, image1Size_.height);
+  } else if (animationFrame_ == image1Size_.height) {
+    // nothing; intermediate blank frame
+  } else {
+    image = image2_.get();
+    srcSize = image2Size_;
+    destRect = NSMakeRect(0, animationFrame_ -
+                                 (image1Size_.height + image2Size_.height),
+                          image2Size_.width, image2Size_.height);
+  }
+
+  if (image) {
+    NSRect sourceImageRect =
+        NSMakeRect(0, 0, srcSize.width, srcSize.height);
+    [image drawInRect:destRect
+             fromRect:sourceImageRect
+            operation:NSCompositeSourceOver
+             fraction:1.0];
+  }
+}
+
+- (void)advanceFrame {
+  ++animationFrame_;
+}
+
+@end
+
+typedef std::set<ThrobberView*> ThrobberSet;
+
+// ThrobberTimer manages the animation of a set of ThrobberViews.  It allows
+// a single timer instance to be shared among as many ThrobberViews as needed.
+@interface ThrobberTimer : NSObject {
+ @private
+  // A set of weak references to each ThrobberView that should be notified
+  // whenever the timer fires.
+  ThrobberSet throbbers_;
+
+  // Weak reference to the timer that calls back to this object.  The timer
+  // retains this object.
+  NSTimer* timer_;
+
+  // Whether the timer is actively running.  To avoid timer construction
+  // and destruction overhead, the timer is not invalidated when it is not
+  // needed, but its next-fire date is set to [NSDate distantFuture].
+  // It is not possible to determine whether the timer has been suspended by
+  // comparing its fireDate to [NSDate distantFuture], though, so a separate
+  // variable is used to track this state.
+  BOOL timerRunning_;
+
+  // The thread that created this object.  Used to validate that ThrobberViews
+  // are only added and removed on the same thread that the fire action will
+  // be performed on.
+  NSThread* validThread_;
+}
+
+// Returns a shared ThrobberTimer.  Everyone is expected to use the same
+// instance.
++ (ThrobberTimer*)sharedThrobberTimer;
+
+// Invalidates the timer, which will cause it to remove itself from the run
+// loop.  This causes the timer to be released, and it should then release
+// this object.
+- (void)invalidate;
+
+// Adds or removes ThrobberView objects from the throbbers_ set.
+- (void)addThrobber:(ThrobberView*)throbber;
+- (void)removeThrobber:(ThrobberView*)throbber;
+@end
+
+@interface ThrobberTimer(PrivateMethods)
+// Starts or stops the timer as needed as ThrobberViews are added and removed
+// from the throbbers_ set.
+- (void)maintainTimer;
+
+// Calls animate on each ThrobberView in the throbbers_ set.
+- (void)fire:(NSTimer*)timer;
+@end
+
+@implementation ThrobberTimer
+- (id)init {
+  if ((self = [super init])) {
+    // Start out with a timer that fires at the appropriate interval, but
+    // prevent it from firing by setting its next-fire date to the distant
+    // future.  Once a ThrobberView is added, the timer will be allowed to
+    // start firing.
+    timer_ = [NSTimer scheduledTimerWithTimeInterval:kAnimationIntervalSeconds
+                                              target:self
+                                            selector:@selector(fire:)
+                                            userInfo:nil
+                                             repeats:YES];
+    [timer_ setFireDate:[NSDate distantFuture]];
+    timerRunning_ = NO;
+
+    validThread_ = [NSThread currentThread];
+  }
+  return self;
+}
+
++ (ThrobberTimer*)sharedThrobberTimer {
+  // Leaked.  That's OK, it's scoped to the lifetime of the application.
+  static ThrobberTimer* sharedInstance = [[ThrobberTimer alloc] init];
+  return sharedInstance;
+}
+
+- (void)invalidate {
+  [timer_ invalidate];
+}
+
+- (void)addThrobber:(ThrobberView*)throbber {
+  DCHECK([NSThread currentThread] == validThread_);
+  throbbers_.insert(throbber);
+  [self maintainTimer];
+}
+
+- (void)removeThrobber:(ThrobberView*)throbber {
+  DCHECK([NSThread currentThread] == validThread_);
+  throbbers_.erase(throbber);
+  [self maintainTimer];
+}
+
+- (void)maintainTimer {
+  BOOL oldRunning = timerRunning_;
+  BOOL newRunning = throbbers_.empty() ? NO : YES;
+
+  if (oldRunning == newRunning)
+    return;
+
+  // To start the timer, set its next-fire date to an appropriate interval from
+  // now.  To suspend the timer, set its next-fire date to a preposterous time
+  // in the future.
+  NSDate* fireDate;
+  if (newRunning)
+    fireDate = [NSDate dateWithTimeIntervalSinceNow:kAnimationIntervalSeconds];
+  else
+    fireDate = [NSDate distantFuture];
+
+  [timer_ setFireDate:fireDate];
+  timerRunning_ = newRunning;
+}
+
+- (void)fire:(NSTimer*)timer {
+  // The call to [throbber animate] may result in the ThrobberView calling
+  // removeThrobber: if it decides it's done animating.  That would invalidate
+  // the iterator, making it impossible to correctly get to the next element
+  // in the set.  To prevent that from happening, a second iterator is used
+  // and incremented before calling [throbber animate].
+  ThrobberSet::const_iterator current = throbbers_.begin();
+  ThrobberSet::const_iterator next = current;
+  while (current != throbbers_.end()) {
+    ++next;
+    ThrobberView* throbber = *current;
+    [throbber animate];
+    current = next;
+  }
+}
+@end
+
+@implementation ThrobberView
+
++ (id)filmstripThrobberViewWithFrame:(NSRect)frame
+                               image:(NSImage*)image {
+  ThrobberFilmstripDelegate* delegate =
+      [[[ThrobberFilmstripDelegate alloc] initWithImage:image] autorelease];
+  if (!delegate)
+    return nil;
+
+  return [[[ThrobberView alloc] initWithFrame:frame
+                                     delegate:delegate] autorelease];
+}
+
++ (id)toastThrobberViewWithFrame:(NSRect)frame
+                     beforeImage:(NSImage*)beforeImage
+                      afterImage:(NSImage*)afterImage {
+  ThrobberToastDelegate* delegate =
+      [[[ThrobberToastDelegate alloc] initWithImage1:beforeImage
+                                              image2:afterImage] autorelease];
+  if (!delegate)
+    return nil;
+
+  return [[[ThrobberView alloc] initWithFrame:frame
+                                     delegate:delegate] autorelease];
+}
+
+- (id)initWithFrame:(NSRect)frame delegate:(id<ThrobberDataDelegate>)delegate {
+  if ((self = [super initWithFrame:frame])) {
+    dataDelegate_ = [delegate retain];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [dataDelegate_ release];
+  [[ThrobberTimer sharedThrobberTimer] removeThrobber:self];
+
+  [super dealloc];
+}
+
+// Manages this ThrobberView's membership in the shared throbber timer set on
+// the basis of its visibility and whether its animation needs to continue
+// running.
+- (void)maintainTimer {
+  ThrobberTimer* throbberTimer = [ThrobberTimer sharedThrobberTimer];
+
+  if ([self window] && ![self isHidden] && ![dataDelegate_ animationIsComplete])
+    [throbberTimer addThrobber:self];
+  else
+    [throbberTimer removeThrobber:self];
+}
+
+// A ThrobberView added to a window may need to begin animating; a ThrobberView
+// removed from a window should stop.
+- (void)viewDidMoveToWindow {
+  [self maintainTimer];
+  [super viewDidMoveToWindow];
+}
+
+// A hidden ThrobberView should stop animating.
+- (void)viewDidHide {
+  [self maintainTimer];
+  [super viewDidHide];
+}
+
+// A visible ThrobberView may need to start animating.
+- (void)viewDidUnhide {
+  [self maintainTimer];
+  [super viewDidUnhide];
+}
+
+// Called when the timer fires. Advance the frame, dirty the display, and remove
+// the throbber if it's no longer needed.
+- (void)animate {
+  [dataDelegate_ advanceFrame];
+  [self setNeedsDisplay:YES];
+
+  if ([dataDelegate_ animationIsComplete]) {
+    [[ThrobberTimer sharedThrobberTimer] removeThrobber:self];
+  }
+}
+
+// Overridden to draw the appropriate frame in the image strip.
+- (void)drawRect:(NSRect)rect {
+  [dataDelegate_ drawFrameInRect:[self bounds]];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm
new file mode 100644
index 0000000..e09ef42
--- /dev/null
+++ b/chrome/browser/ui/cocoa/tabs/throbber_view_unittest.mm
@@ -0,0 +1,32 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/tabs/throbber_view.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "grit/app_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+class ThrobberViewTest : public CocoaTest {
+ public:
+  ThrobberViewTest() {
+    NSRect frame = NSMakeRect(10, 10, 16, 16);
+    NSImage* image =
+        ResourceBundle::GetSharedInstance().GetNativeImageNamed(IDR_THROBBER);
+    view_ = [ThrobberView filmstripThrobberViewWithFrame:frame image:image];
+    [[test_window() contentView] addSubview:view_];
+  }
+
+  ThrobberView* view_;
+};
+
+TEST_VIEW(ThrobberViewTest, view_)
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/task_helpers.h b/chrome/browser/ui/cocoa/task_helpers.h
deleted file mode 100644
index e29c068..0000000
--- a/chrome/browser/ui/cocoa/task_helpers.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TASK_HELPERS_H_
-#define CHROME_BROWSER_UI_COCOA_TASK_HELPERS_H_
-#pragma once
-
-class Task;
-
-namespace tracked_objects {
-class Location;
-}  // namespace tracked_objects
-
-namespace cocoa_utils {
-
-// This can be used in place of BrowserThread::PostTask(BrowserThread::UI, ...).
-// The purpose of this function is to be able to execute Task work alongside
-// native work when a MessageLoop is blocked by a nested run loop. This function
-// will run the Task in both NSEventTrackingRunLoopMode and NSDefaultRunLoopMode
-// for the purpose of executing work while a menu is open. See
-// http://crbug.com/48679 for the full rationale.
-bool PostTaskInEventTrackingRunLoopMode(
-    const tracked_objects::Location& from_here,
-    Task* task);
-
-}  // namespace cocoa_utils
-
-#endif  // CHROME_BROWSER_UI_COCOA_TASK_HELPERS_H_
diff --git a/chrome/browser/ui/cocoa/task_helpers.mm b/chrome/browser/ui/cocoa/task_helpers.mm
deleted file mode 100644
index 2f8df18..0000000
--- a/chrome/browser/ui/cocoa/task_helpers.mm
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/task_helpers.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-
-// This is a wrapper for running Task objects from within a native run loop.
-// This can run specific tasks in that nested loop.  This owns the task and will
-// delete it and itself when done.
-@interface NativeTaskRunner : NSObject {
- @private
-  scoped_ptr<Task> task_;
-}
-- (id)initWithTask:(Task*)task;
-- (void)runTask;
-@end
-
-@implementation NativeTaskRunner
-- (id)initWithTask:(Task*)task {
-  if ((self = [super init])) {
-    task_.reset(task);
-  }
-  return self;
-}
-
-- (void)runTask {
-  task_->Run();
-  [self autorelease];
-}
-@end
-
-namespace cocoa_utils {
-
-bool PostTaskInEventTrackingRunLoopMode(
-    const tracked_objects::Location& from_here,
-    Task* task) {
-  // This deletes itself and the task after the task runs.
-  NativeTaskRunner* runner = [[NativeTaskRunner alloc] initWithTask:task];
-
-  // Schedule the selector in multiple modes in case this was called while a
-  // menu was not running.
-  NSArray* modes = [NSArray arrayWithObjects:NSEventTrackingRunLoopMode,
-                                             NSDefaultRunLoopMode,
-                                             nil];
-  [runner performSelectorOnMainThread:@selector(runTask)
-                           withObject:nil
-                        waitUntilDone:NO
-                                modes:modes];
-  return true;
-}
-
-}  // namespace cocoa_utils
diff --git a/chrome/browser/ui/cocoa/task_manager_mac.h b/chrome/browser/ui/cocoa/task_manager_mac.h
index 75c9811..211a86d 100644
--- a/chrome/browser/ui/cocoa/task_manager_mac.h
+++ b/chrome/browser/ui/cocoa/task_manager_mac.h
@@ -29,6 +29,7 @@
   TaskManagerMac* taskManagerObserver_;  // weak
   TaskManager* taskManager_;  // weak
   TaskManagerModel* model_;  // weak
+  bool highlightBackgroundResources_;
 
   scoped_nsobject<WindowSizeAutosaver> size_saver_;
 
@@ -39,10 +40,14 @@
 
   // Descriptor of the current sort column.
   scoped_nsobject<NSSortDescriptor> currentSortDescriptor_;
+
+  // Color we use for background resources.
+  scoped_nsobject<NSColor> backgroundResourceColor_;
 }
 
 // Creates and shows the task manager's window.
-- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver;
+- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver
+     highlightBackgroundResources:(bool)highlightBackgroundResources;
 
 // Refreshes all data in the task manager table.
 - (void)reloadData;
@@ -65,7 +70,7 @@
 class TaskManagerMac : public TaskManagerModelObserver,
                        public TableRowNSImageCache::Table {
  public:
-  TaskManagerMac(TaskManager* task_manager);
+  TaskManagerMac(TaskManager* task_manager, bool highlight_background);
   virtual ~TaskManagerMac();
 
   // TaskManagerModelObserver
@@ -83,8 +88,9 @@
   virtual SkBitmap GetIcon(int r) const;
 
   // Creates the task manager if it doesn't exist; otherwise, it activates the
-  // existing task manager window.
-  static void Show();
+  // existing task manager window. Highlights background resources if
+  // |highlight_background_resources| is true.
+  static void Show(bool highlight_background_resources);
 
   // Returns the TaskManager observed by |this|.
   TaskManager* task_manager() { return task_manager_; }
@@ -94,6 +100,9 @@
 
   // Returns the cocoa object. Used for testing.
   TaskManagerWindowController* cocoa_controller() { return window_controller_; }
+
+  // Returns true if the resource at this location is a background resource.
+  bool IsBackgroundRow(int row) const;
  private:
   // The task manager.
   TaskManager* const task_manager_;  // weak
@@ -108,6 +117,9 @@
   // Caches favicons for all rows. Needs to be initalized after |model_|.
   TableRowNSImageCache icon_cache_;
 
+  // If true, highlight background resources.
+  bool highlight_background_resources_;
+
   // An open task manager window. There can only be one open at a time. This
   // is reset to NULL when the window is closed.
   static TaskManagerMac* instance_;
diff --git a/chrome/browser/ui/cocoa/task_manager_mac.mm b/chrome/browser/ui/cocoa/task_manager_mac.mm
index 28cbba0..f9222bf 100644
--- a/chrome/browser/ui/cocoa/task_manager_mac.mm
+++ b/chrome/browser/ui/cocoa/task_manager_mac.mm
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <vector>
 
-#include "app/l10n_util_mac.h"
 #include "base/mac/mac_util.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/browser/browser_process.h"
@@ -15,6 +14,7 @@
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
@@ -102,7 +102,8 @@
 
 @implementation TaskManagerWindowController
 
-- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver {
+- (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver
+     highlightBackgroundResources:(bool)highlightBackgroundResources {
   NSString* nibpath = [base::mac::MainAppBundle()
                         pathForResource:@"TaskManager"
                                  ofType:@"nib"];
@@ -110,6 +111,15 @@
     taskManagerObserver_ = taskManagerObserver;
     taskManager_ = taskManagerObserver_->task_manager();
     model_ = taskManager_->model();
+    highlightBackgroundResources_ = highlightBackgroundResources;
+    if (highlightBackgroundResources_) {
+      // Highlight background resources with a yellow background.
+      backgroundResourceColor_.reset(
+          [[NSColor colorWithDeviceRed:0xff/255.0
+                                 green:0xfa/255.0
+                                  blue:0xcd/255.0
+                                 alpha:1.0] retain]);
+    }
 
     if (g_browser_process && g_browser_process->local_state()) {
       size_saver_.reset([[WindowSizeAutosaver alloc]
@@ -192,6 +202,7 @@
   [self adjustSelectionAndEndProcessButton];
 
   [tableView_ setDoubleAction:@selector(selectDoubleClickedTab:)];
+  [tableView_ setIntercellSpacing:NSMakeSize(0.0, 0.0)];
   [tableView_ sizeToFit];
 }
 
@@ -370,6 +381,29 @@
   [self autorelease];
 }
 
+// Delegate method invoked before each cell in the table is displayed. We
+// override this to provide highlighting of background resources.
+- (void)  tableView:(NSTableView*)tableView
+    willDisplayCell:(id)cell
+     forTableColumn:(NSTableColumn*)tableColumn
+                row:(NSInteger)row {
+  if (!highlightBackgroundResources_)
+    return;
+
+  bool isBackground =
+      taskManagerObserver_->IsBackgroundRow(viewToModelMap_[row]);
+  DCHECK([cell respondsToSelector:@selector(setBackgroundColor:)]);
+  if ([cell respondsToSelector:@selector(setBackgroundColor:)]) {
+    if (isBackground && ![tableView isRowSelected:row]) {
+      [cell setDrawsBackground:YES];
+      [cell setBackgroundColor:backgroundResourceColor_];
+    } else {
+      [cell setBackgroundColor:nil];
+      [cell setDrawsBackground:NO];
+    }
+  }
+}
+
 @end
 
 @implementation TaskManagerWindowController (NSTableDataSource)
@@ -502,12 +536,16 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TaskManagerMac implementation:
 
-TaskManagerMac::TaskManagerMac(TaskManager* task_manager)
+TaskManagerMac::TaskManagerMac(TaskManager* task_manager,
+                               bool highlight_background_resources)
   : task_manager_(task_manager),
     model_(task_manager->model()),
-    icon_cache_(this) {
+    icon_cache_(this),
+    highlight_background_resources_(highlight_background_resources) {
   window_controller_ =
-      [[TaskManagerWindowController alloc] initWithTaskManagerObserver:this];
+      [[TaskManagerWindowController alloc]
+           initWithTaskManagerObserver:this
+          highlightBackgroundResources:highlight_background_resources];
   model_->AddObserver(this);
 }
 
@@ -569,14 +607,28 @@
   return model_->GetResourceIcon(r);
 }
 
+bool TaskManagerMac::IsBackgroundRow(int row) const {
+  return model_->IsBackgroundResource(row);
+}
+
 // static
-void TaskManagerMac::Show() {
+void TaskManagerMac::Show(bool highlight_background_resources) {
   if (instance_) {
-    // If there's a Task manager window open already, just activate it.
-    [[instance_->window_controller_ window]
+    if (instance_->highlight_background_resources_ ==
+        highlight_background_resources) {
+      // There's a Task manager window open already, so just activate it.
+      [[instance_->window_controller_ window]
         makeKeyAndOrderFront:instance_->window_controller_];
-  } else {
-    instance_ = new TaskManagerMac(TaskManager::GetInstance());
-    instance_->model_->StartUpdating();
+      return;
+    } else {
+      // The user is switching between "View Background Pages" and
+      // "Task Manager" so close the existing window and fall through to
+      // open a new one.
+      [[instance_->window_controller_ window] close];
+    }
   }
+  // Create a new instance.
+  instance_ = new TaskManagerMac(TaskManager::GetInstance(),
+                                 highlight_background_resources);
+  instance_->model_->StartUpdating();
 }
diff --git a/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm b/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm
index 2a7aae3..f5d9b2a 100644
--- a/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/task_manager_mac_unittest.mm
@@ -1,9 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import <Cocoa/Cocoa.h>
 
+#include "base/compiler_specific.h"
 #include "base/scoped_nsobject.h"
 #include "base/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/task_manager_mac.h"
@@ -19,13 +20,13 @@
 class TestResource : public TaskManager::Resource {
  public:
   TestResource(const string16& title, pid_t pid) : title_(title), pid_(pid) {}
-  virtual std::wstring GetTitle() const { return UTF16ToWide(title_); }
-  virtual SkBitmap GetIcon() const { return SkBitmap(); }
-  virtual base::ProcessHandle GetProcess() const { return pid_; }
-  virtual Type GetType() const { return RENDERER; }
-  virtual bool SupportNetworkUsage() const { return false; }
-  virtual void SetSupportNetworkUsage() { NOTREACHED(); }
-  virtual void Refresh() {}
+  virtual string16 GetTitle() const OVERRIDE { return title_; }
+  virtual SkBitmap GetIcon() const OVERRIDE { return SkBitmap(); }
+  virtual base::ProcessHandle GetProcess() const OVERRIDE { return pid_; }
+  virtual Type GetType() const OVERRIDE { return RENDERER; }
+  virtual bool SupportNetworkUsage() const OVERRIDE { return false; }
+  virtual void SetSupportNetworkUsage() OVERRIDE { NOTREACHED(); }
+  virtual void Refresh() OVERRIDE {}
   string16 title_;
   pid_t pid_;
 };
@@ -38,7 +39,7 @@
 // Test creation, to ensure nothing leaks or crashes.
 TEST_F(TaskManagerWindowControllerTest, Init) {
   TaskManager task_manager;
-  TaskManagerMac* bridge(new TaskManagerMac(&task_manager));
+  TaskManagerMac* bridge(new TaskManagerMac(&task_manager, false));
   TaskManagerWindowController* controller = bridge->cocoa_controller();
 
   // Releases the controller, which in turn deletes |bridge|.
@@ -56,7 +57,7 @@
   task_manager.AddResource(&resource2);
   task_manager.AddResource(&resource3);  // Will be in the same group as 2.
 
-  TaskManagerMac* bridge(new TaskManagerMac(&task_manager));
+  TaskManagerMac* bridge(new TaskManagerMac(&task_manager, false));
   TaskManagerWindowController* controller = bridge->cocoa_controller();
   NSTableView* table = [controller tableView];
   ASSERT_EQ(3, [controller numberOfRowsInTableView:table]);
@@ -89,7 +90,7 @@
   task_manager.AddResource(&resource1);
   task_manager.AddResource(&resource2);
 
-  TaskManagerMac* bridge(new TaskManagerMac(&task_manager));
+  TaskManagerMac* bridge(new TaskManagerMac(&task_manager, false));
   TaskManagerWindowController* controller = bridge->cocoa_controller();
   NSTableView* table = [controller tableView];
   ASSERT_EQ(2, [controller numberOfRowsInTableView:table]);
diff --git a/chrome/browser/ui/cocoa/theme_install_bubble_view.mm b/chrome/browser/ui/cocoa/theme_install_bubble_view.mm
index 9841230..076aabd 100644
--- a/chrome/browser/ui/cocoa/theme_install_bubble_view.mm
+++ b/chrome/browser/ui/cocoa/theme_install_bubble_view.mm
@@ -6,10 +6,10 @@
 
 #import "chrome/browser/ui/cocoa/theme_install_bubble_view.h"
 
-#include "app/l10n_util_mac.h"
 #include "base/scoped_nsobject.h"
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/themed_window.h b/chrome/browser/ui/cocoa/themed_window.h
index d35bfa3..4da0d53 100644
--- a/chrome/browser/ui/cocoa/themed_window.h
+++ b/chrome/browser/ui/cocoa/themed_window.h
@@ -8,7 +8,10 @@
 
 #import <Cocoa/Cocoa.h>
 
+namespace ui {
 class ThemeProvider;
+}
+using ui::ThemeProvider;
 
 // Bit flags; mix-and-match as necessary.
 enum {
diff --git a/chrome/browser/ui/cocoa/throbber_view.h b/chrome/browser/ui/cocoa/throbber_view.h
deleted file mode 100644
index a680222..0000000
--- a/chrome/browser/ui/cocoa/throbber_view.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_THROBBER_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_THROBBER_VIEW_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-
-@protocol ThrobberDataDelegate;
-
-// A class that knows how to draw an animated state to indicate progress.
-// Creating the class starts the animation, destroying it stops it. There are
-// two types:
-//
-// - Filmstrip: Draws via a sequence of frames in an image. There is no state
-//   where the class is frozen on an image and not animating. The image needs to
-//   be made of squares such that the height divides evenly into the width.
-//
-// - Toast: Draws an image animating down to the bottom and then another image
-//   animating up from the bottom. Stops once the animation is complete.
-
-@interface ThrobberView : NSView {
- @private
-  id<ThrobberDataDelegate> dataDelegate_;
-}
-
-// Creates a filmstrip view with |frame| and image |image|.
-+ (id)filmstripThrobberViewWithFrame:(NSRect)frame
-                               image:(NSImage*)image;
-
-// Creates a toast view with |frame| and specified images.
-+ (id)toastThrobberViewWithFrame:(NSRect)frame
-                     beforeImage:(NSImage*)beforeImage
-                      afterImage:(NSImage*)afterImage;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_THROBBER_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/throbber_view.mm b/chrome/browser/ui/cocoa/throbber_view.mm
deleted file mode 100644
index c0e5dd3..0000000
--- a/chrome/browser/ui/cocoa/throbber_view.mm
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/throbber_view.h"
-
-#include <set>
-
-#include "base/logging.h"
-
-static const float kAnimationIntervalSeconds = 0.03;  // 30ms, same as windows
-
-@interface ThrobberView(PrivateMethods)
-- (id)initWithFrame:(NSRect)frame delegate:(id<ThrobberDataDelegate>)delegate;
-- (void)maintainTimer;
-- (void)animate;
-@end
-
-@protocol ThrobberDataDelegate <NSObject>
-// Is the current frame the last frame of the animation?
-- (BOOL)animationIsComplete;
-
-// Draw the current frame into the current graphics context.
-- (void)drawFrameInRect:(NSRect)rect;
-
-// Update the frame counter.
-- (void)advanceFrame;
-@end
-
-@interface ThrobberFilmstripDelegate : NSObject
-                                       <ThrobberDataDelegate> {
-  scoped_nsobject<NSImage> image_;
-  unsigned int numFrames_;  // Number of frames in this animation.
-  unsigned int animationFrame_;  // Current frame of the animation,
-                                 // [0..numFrames_)
-}
-
-- (id)initWithImage:(NSImage*)image;
-
-@end
-
-@implementation ThrobberFilmstripDelegate
-
-- (id)initWithImage:(NSImage*)image {
-  if ((self = [super init])) {
-    // Reset the animation counter so there's no chance we are off the end.
-    animationFrame_ = 0;
-
-    // Ensure that the height divides evenly into the width. Cache the
-    // number of frames in the animation for later.
-    NSSize imageSize = [image size];
-    DCHECK(imageSize.height && imageSize.width);
-    if (!imageSize.height)
-      return nil;
-    DCHECK((int)imageSize.width % (int)imageSize.height == 0);
-    numFrames_ = (int)imageSize.width / (int)imageSize.height;
-    DCHECK(numFrames_);
-    image_.reset([image retain]);
-  }
-  return self;
-}
-
-- (BOOL)animationIsComplete {
-  return NO;
-}
-
-- (void)drawFrameInRect:(NSRect)rect {
-  float imageDimension = [image_ size].height;
-  float xOffset = animationFrame_ * imageDimension;
-  NSRect sourceImageRect =
-      NSMakeRect(xOffset, 0, imageDimension, imageDimension);
-  [image_ drawInRect:rect
-            fromRect:sourceImageRect
-           operation:NSCompositeSourceOver
-            fraction:1.0];
-}
-
-- (void)advanceFrame {
-  animationFrame_ = ++animationFrame_ % numFrames_;
-}
-
-@end
-
-@interface ThrobberToastDelegate : NSObject
-                                   <ThrobberDataDelegate> {
-  scoped_nsobject<NSImage> image1_;
-  scoped_nsobject<NSImage> image2_;
-  NSSize image1Size_;
-  NSSize image2Size_;
-  int animationFrame_;  // Current frame of the animation,
-}
-
-- (id)initWithImage1:(NSImage*)image1 image2:(NSImage*)image2;
-
-@end
-
-@implementation ThrobberToastDelegate
-
-- (id)initWithImage1:(NSImage*)image1 image2:(NSImage*)image2 {
-  if ((self = [super init])) {
-    image1_.reset([image1 retain]);
-    image2_.reset([image2 retain]);
-    image1Size_ = [image1 size];
-    image2Size_ = [image2 size];
-    animationFrame_ = 0;
-  }
-  return self;
-}
-
-- (BOOL)animationIsComplete {
-  if (animationFrame_ >= image1Size_.height + image2Size_.height)
-    return YES;
-
-  return NO;
-}
-
-// From [0..image1Height) we draw image1, at image1Height we draw nothing, and
-// from [image1Height+1..image1Hight+image2Height] we draw the second image.
-- (void)drawFrameInRect:(NSRect)rect {
-  NSImage* image = nil;
-  NSSize srcSize;
-  NSRect destRect;
-
-  if (animationFrame_ < image1Size_.height) {
-    image = image1_.get();
-    srcSize = image1Size_;
-    destRect = NSMakeRect(0, -animationFrame_,
-                          image1Size_.width, image1Size_.height);
-  } else if (animationFrame_ == image1Size_.height) {
-    // nothing; intermediate blank frame
-  } else {
-    image = image2_.get();
-    srcSize = image2Size_;
-    destRect = NSMakeRect(0, animationFrame_ -
-                                 (image1Size_.height + image2Size_.height),
-                          image2Size_.width, image2Size_.height);
-  }
-
-  if (image) {
-    NSRect sourceImageRect =
-        NSMakeRect(0, 0, srcSize.width, srcSize.height);
-    [image drawInRect:destRect
-             fromRect:sourceImageRect
-            operation:NSCompositeSourceOver
-             fraction:1.0];
-  }
-}
-
-- (void)advanceFrame {
-  ++animationFrame_;
-}
-
-@end
-
-typedef std::set<ThrobberView*> ThrobberSet;
-
-// ThrobberTimer manages the animation of a set of ThrobberViews.  It allows
-// a single timer instance to be shared among as many ThrobberViews as needed.
-@interface ThrobberTimer : NSObject {
- @private
-  // A set of weak references to each ThrobberView that should be notified
-  // whenever the timer fires.
-  ThrobberSet throbbers_;
-
-  // Weak reference to the timer that calls back to this object.  The timer
-  // retains this object.
-  NSTimer* timer_;
-
-  // Whether the timer is actively running.  To avoid timer construction
-  // and destruction overhead, the timer is not invalidated when it is not
-  // needed, but its next-fire date is set to [NSDate distantFuture].
-  // It is not possible to determine whether the timer has been suspended by
-  // comparing its fireDate to [NSDate distantFuture], though, so a separate
-  // variable is used to track this state.
-  BOOL timerRunning_;
-
-  // The thread that created this object.  Used to validate that ThrobberViews
-  // are only added and removed on the same thread that the fire action will
-  // be performed on.
-  NSThread* validThread_;
-}
-
-// Returns a shared ThrobberTimer.  Everyone is expected to use the same
-// instance.
-+ (ThrobberTimer*)sharedThrobberTimer;
-
-// Invalidates the timer, which will cause it to remove itself from the run
-// loop.  This causes the timer to be released, and it should then release
-// this object.
-- (void)invalidate;
-
-// Adds or removes ThrobberView objects from the throbbers_ set.
-- (void)addThrobber:(ThrobberView*)throbber;
-- (void)removeThrobber:(ThrobberView*)throbber;
-@end
-
-@interface ThrobberTimer(PrivateMethods)
-// Starts or stops the timer as needed as ThrobberViews are added and removed
-// from the throbbers_ set.
-- (void)maintainTimer;
-
-// Calls animate on each ThrobberView in the throbbers_ set.
-- (void)fire:(NSTimer*)timer;
-@end
-
-@implementation ThrobberTimer
-- (id)init {
-  if ((self = [super init])) {
-    // Start out with a timer that fires at the appropriate interval, but
-    // prevent it from firing by setting its next-fire date to the distant
-    // future.  Once a ThrobberView is added, the timer will be allowed to
-    // start firing.
-    timer_ = [NSTimer scheduledTimerWithTimeInterval:kAnimationIntervalSeconds
-                                              target:self
-                                            selector:@selector(fire:)
-                                            userInfo:nil
-                                             repeats:YES];
-    [timer_ setFireDate:[NSDate distantFuture]];
-    timerRunning_ = NO;
-
-    validThread_ = [NSThread currentThread];
-  }
-  return self;
-}
-
-+ (ThrobberTimer*)sharedThrobberTimer {
-  // Leaked.  That's OK, it's scoped to the lifetime of the application.
-  static ThrobberTimer* sharedInstance = [[ThrobberTimer alloc] init];
-  return sharedInstance;
-}
-
-- (void)invalidate {
-  [timer_ invalidate];
-}
-
-- (void)addThrobber:(ThrobberView*)throbber {
-  DCHECK([NSThread currentThread] == validThread_);
-  throbbers_.insert(throbber);
-  [self maintainTimer];
-}
-
-- (void)removeThrobber:(ThrobberView*)throbber {
-  DCHECK([NSThread currentThread] == validThread_);
-  throbbers_.erase(throbber);
-  [self maintainTimer];
-}
-
-- (void)maintainTimer {
-  BOOL oldRunning = timerRunning_;
-  BOOL newRunning = throbbers_.empty() ? NO : YES;
-
-  if (oldRunning == newRunning)
-    return;
-
-  // To start the timer, set its next-fire date to an appropriate interval from
-  // now.  To suspend the timer, set its next-fire date to a preposterous time
-  // in the future.
-  NSDate* fireDate;
-  if (newRunning)
-    fireDate = [NSDate dateWithTimeIntervalSinceNow:kAnimationIntervalSeconds];
-  else
-    fireDate = [NSDate distantFuture];
-
-  [timer_ setFireDate:fireDate];
-  timerRunning_ = newRunning;
-}
-
-- (void)fire:(NSTimer*)timer {
-  // The call to [throbber animate] may result in the ThrobberView calling
-  // removeThrobber: if it decides it's done animating.  That would invalidate
-  // the iterator, making it impossible to correctly get to the next element
-  // in the set.  To prevent that from happening, a second iterator is used
-  // and incremented before calling [throbber animate].
-  ThrobberSet::const_iterator current = throbbers_.begin();
-  ThrobberSet::const_iterator next = current;
-  while (current != throbbers_.end()) {
-    ++next;
-    ThrobberView* throbber = *current;
-    [throbber animate];
-    current = next;
-  }
-}
-@end
-
-@implementation ThrobberView
-
-+ (id)filmstripThrobberViewWithFrame:(NSRect)frame
-                               image:(NSImage*)image {
-  ThrobberFilmstripDelegate* delegate =
-      [[[ThrobberFilmstripDelegate alloc] initWithImage:image] autorelease];
-  if (!delegate)
-    return nil;
-
-  return [[[ThrobberView alloc] initWithFrame:frame
-                                     delegate:delegate] autorelease];
-}
-
-+ (id)toastThrobberViewWithFrame:(NSRect)frame
-                     beforeImage:(NSImage*)beforeImage
-                      afterImage:(NSImage*)afterImage {
-  ThrobberToastDelegate* delegate =
-      [[[ThrobberToastDelegate alloc] initWithImage1:beforeImage
-                                              image2:afterImage] autorelease];
-  if (!delegate)
-    return nil;
-
-  return [[[ThrobberView alloc] initWithFrame:frame
-                                     delegate:delegate] autorelease];
-}
-
-- (id)initWithFrame:(NSRect)frame delegate:(id<ThrobberDataDelegate>)delegate {
-  if ((self = [super initWithFrame:frame])) {
-    dataDelegate_ = [delegate retain];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [dataDelegate_ release];
-  [[ThrobberTimer sharedThrobberTimer] removeThrobber:self];
-
-  [super dealloc];
-}
-
-// Manages this ThrobberView's membership in the shared throbber timer set on
-// the basis of its visibility and whether its animation needs to continue
-// running.
-- (void)maintainTimer {
-  ThrobberTimer* throbberTimer = [ThrobberTimer sharedThrobberTimer];
-
-  if ([self window] && ![self isHidden] && ![dataDelegate_ animationIsComplete])
-    [throbberTimer addThrobber:self];
-  else
-    [throbberTimer removeThrobber:self];
-}
-
-// A ThrobberView added to a window may need to begin animating; a ThrobberView
-// removed from a window should stop.
-- (void)viewDidMoveToWindow {
-  [self maintainTimer];
-  [super viewDidMoveToWindow];
-}
-
-// A hidden ThrobberView should stop animating.
-- (void)viewDidHide {
-  [self maintainTimer];
-  [super viewDidHide];
-}
-
-// A visible ThrobberView may need to start animating.
-- (void)viewDidUnhide {
-  [self maintainTimer];
-  [super viewDidUnhide];
-}
-
-// Called when the timer fires. Advance the frame, dirty the display, and remove
-// the throbber if it's no longer needed.
-- (void)animate {
-  [dataDelegate_ advanceFrame];
-  [self setNeedsDisplay:YES];
-
-  if ([dataDelegate_ animationIsComplete]) {
-    [[ThrobberTimer sharedThrobberTimer] removeThrobber:self];
-  }
-}
-
-// Overridden to draw the appropriate frame in the image strip.
-- (void)drawRect:(NSRect)rect {
-  [dataDelegate_ drawFrameInRect:[self bounds]];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/throbber_view_unittest.mm b/chrome/browser/ui/cocoa/throbber_view_unittest.mm
deleted file mode 100644
index b1a2ce4..0000000
--- a/chrome/browser/ui/cocoa/throbber_view_unittest.mm
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "app/resource_bundle.h"
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/throbber_view.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "grit/app_resources.h"
-
-namespace {
-
-class ThrobberViewTest : public CocoaTest {
- public:
-  ThrobberViewTest() {
-    NSRect frame = NSMakeRect(10, 10, 16, 16);
-    NSImage* image =
-        ResourceBundle::GetSharedInstance().GetNativeImageNamed(IDR_THROBBER);
-    view_ = [ThrobberView filmstripThrobberViewWithFrame:frame image:image];
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  ThrobberView* view_;
-};
-
-TEST_VIEW(ThrobberViewTest, view_)
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/toolbar/OWNERS b/chrome/browser/ui/cocoa/toolbar/OWNERS
new file mode 100644
index 0000000..5d0c2e4
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/OWNERS
@@ -0,0 +1,5 @@
+avi@chromium.org
+pinkerton@chromium.org
+rohitrao@chromium.org
+shess@chromium.org
+viettrungluu@chromium.org
diff --git a/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h b/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h
new file mode 100644
index 0000000..4a978b5
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TOOLBAR_BACK_FORWARD_MENU_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TOOLBAR_BACK_FORWARD_MENU_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
+
+@class MenuButton;
+
+typedef BackForwardMenuModel::ModelType BackForwardMenuType;
+const BackForwardMenuType BACK_FORWARD_MENU_TYPE_BACK =
+    BackForwardMenuModel::BACKWARD_MENU;
+const BackForwardMenuType BACK_FORWARD_MENU_TYPE_FORWARD =
+    BackForwardMenuModel::FORWARD_MENU;
+
+// A class that manages the back/forward menu (and delayed-menu button, and
+// model).
+
+@interface BackForwardMenuController : NSObject {
+ @private
+  BackForwardMenuType type_;
+  MenuButton* button_;  // Weak; comes from nib.
+  scoped_ptr<BackForwardMenuModel> model_;
+  scoped_nsobject<NSMenu> backForwardMenu_;
+}
+
+// Type (back or forwards); can only be set on initialization.
+@property(readonly, nonatomic) BackForwardMenuType type;
+
+- (id)initWithBrowser:(Browser*)browser
+            modelType:(BackForwardMenuType)type
+               button:(MenuButton*)button;
+
+@end  // @interface BackForwardMenuController
+
+#endif  // CHROME_BROWSER_UI_COCOA_TOOLBAR_BACK_FORWARD_MENU_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.mm b/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.mm
new file mode 100644
index 0000000..63bab2a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.mm
@@ -0,0 +1,102 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h"
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/sys_string_conversions.h"
+#import "chrome/browser/ui/cocoa/event_utils.h"
+#import "chrome/browser/ui/cocoa/menu_button.h"
+#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+using base::SysUTF16ToNSString;
+using gfx::SkBitmapToNSImage;
+
+@implementation BackForwardMenuController
+
+// Accessors and mutators:
+
+@synthesize type = type_;
+
+// Own methods:
+
+- (id)initWithBrowser:(Browser*)browser
+            modelType:(BackForwardMenuType)type
+               button:(MenuButton*)button {
+  if ((self = [super init])) {
+    type_ = type;
+    button_ = button;
+    model_.reset(new BackForwardMenuModel(browser, type_));
+    DCHECK(model_.get());
+    backForwardMenu_.reset([[NSMenu alloc] initWithTitle:@""]);
+    DCHECK(backForwardMenu_.get());
+    [backForwardMenu_ setDelegate:self];
+
+    [button_ setAttachedMenu:backForwardMenu_];
+    [button_ setOpenMenuOnClick:NO];
+  }
+  return self;
+}
+
+// Methods as delegate:
+
+// Called by backForwardMenu_ just before tracking begins.
+//TODO(viettrungluu): should we do anything for chapter stops (see model)?
+- (void)menuNeedsUpdate:(NSMenu*)menu {
+  DCHECK(menu == backForwardMenu_);
+
+  // Remove old menu items (backwards order is as good as any).
+  for (NSInteger i = [menu numberOfItems]; i > 0; i--)
+    [menu removeItemAtIndex:(i - 1)];
+
+  // 0-th item must be blank. (This is because we use a pulldown list, for which
+  // Cocoa uses the 0-th item as "title" in the button.)
+  [menu insertItemWithTitle:@""
+                     action:nil
+              keyEquivalent:@""
+                    atIndex:0];
+  for (int menuID = 0; menuID < model_->GetItemCount(); menuID++) {
+    if (model_->IsSeparator(menuID)) {
+      [menu insertItem:[NSMenuItem separatorItem]
+               atIndex:(menuID + 1)];
+    } else {
+      // Create a menu item with the right label.
+      NSMenuItem* menuItem = [[NSMenuItem alloc]
+              initWithTitle:SysUTF16ToNSString(model_->GetLabelAt(menuID))
+                     action:nil
+              keyEquivalent:@""];
+      [menuItem autorelease];
+
+      SkBitmap icon;
+      // Icon (if it has one).
+      if (model_->GetIconAt(menuID, &icon))
+        [menuItem setImage:SkBitmapToNSImage(icon)];
+
+      // This will make it call our |-executeMenuItem:| method. We store the
+      // |menuID| (or |menu_id|) in the tag.
+      [menuItem setTag:menuID];
+      [menuItem setTarget:self];
+      [menuItem setAction:@selector(executeMenuItem:)];
+
+      // Put it in the menu!
+      [menu insertItem:menuItem
+               atIndex:(menuID + 1)];
+    }
+  }
+}
+
+// Action methods:
+
+- (void)executeMenuItem:(id)sender {
+  DCHECK([sender isKindOfClass:[NSMenuItem class]]);
+  int menuID = [sender tag];
+  model_->ActivatedAtWithDisposition(
+      menuID,
+      event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
+}
+
+@end  // @implementation BackForwardMenuController
diff --git a/chrome/browser/ui/cocoa/toolbar/reload_button.h b/chrome/browser/ui/cocoa/toolbar/reload_button.h
new file mode 100644
index 0000000..e42e58c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/reload_button.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TOOLBAR_RELOAD_BUTTON_H_
+#define CHROME_BROWSER_UI_COCOA_TOOLBAR_RELOAD_BUTTON_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+
+// NSButton subclass which defers certain state changes when the mouse
+// is hovering over it.
+
+@interface ReloadButton : NSButton {
+ @private
+  // Tracks whether the mouse is hovering for purposes of not making
+  // unexpected state changes.
+  BOOL isMouseInside_;
+  scoped_nsobject<NSTrackingArea> trackingArea_;
+
+  // Timer used when setting reload mode while the mouse is hovered.
+  scoped_nsobject<NSTimer> pendingReloadTimer_;
+}
+
+// Returns YES if the mouse is currently inside the bounds.
+- (BOOL)isMouseInside;
+
+// Update the tag, and the image and tooltip to match.  If |anInt|
+// matches the current tag, no action is taken.  |anInt| must be
+// either |IDC_STOP| or |IDC_RELOAD|.
+- (void)updateTag:(NSInteger)anInt;
+
+// Update the button to be a reload button or stop button depending on
+// |isLoading|.  If |force|, always sets the indicated mode.  If
+// |!force|, and the mouse is over the button, defer the transition
+// from stop button to reload button until the mouse has left the
+// button, or until |pendingReloadTimer_| fires.  This prevents an
+// inadvertent click _just_ as the state changes.
+- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force;
+
+@end
+
+@interface ReloadButton (PrivateTestingMethods)
++ (void)setPendingReloadTimeout:(NSTimeInterval)seconds;
+- (NSTrackingArea*)trackingArea;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TOOLBAR_RELOAD_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/toolbar/reload_button.mm b/chrome/browser/ui/cocoa/toolbar/reload_button.mm
new file mode 100644
index 0000000..a00ee25
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/reload_button.mm
@@ -0,0 +1,168 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/toolbar/reload_button.h"
+
+#include "ui/base/l10n/l10n_util.h"
+#include "app/mac/nsimage_cache.h"
+#include "chrome/app/chrome_command_ids.h"
+#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+namespace {
+
+NSString* const kReloadImageName = @"reload_Template.pdf";
+NSString* const kStopImageName = @"stop_Template.pdf";
+
+// Constant matches Windows.
+NSTimeInterval kPendingReloadTimeout = 1.35;
+
+}  // namespace
+
+@implementation ReloadButton
+
+- (void)dealloc {
+  if (trackingArea_) {
+    [self removeTrackingArea:trackingArea_];
+    trackingArea_.reset();
+  }
+  [super dealloc];
+}
+
+- (void)updateTrackingAreas {
+  // If the mouse is hovering when the tracking area is updated, the
+  // control could end up locked into inappropriate behavior for
+  // awhile, so unwind state.
+  if (isMouseInside_)
+    [self mouseExited:nil];
+
+  if (trackingArea_) {
+    [self removeTrackingArea:trackingArea_];
+    trackingArea_.reset();
+  }
+  trackingArea_.reset([[NSTrackingArea alloc]
+                        initWithRect:[self bounds]
+                             options:(NSTrackingMouseEnteredAndExited |
+                                      NSTrackingActiveInActiveApp)
+                               owner:self
+                            userInfo:nil]);
+  [self addTrackingArea:trackingArea_];
+}
+
+- (void)awakeFromNib {
+  [self updateTrackingAreas];
+
+  // Don't allow multi-clicks, because the user probably wouldn't ever
+  // want to stop+reload or reload+stop.
+  [self setIgnoresMultiClick:YES];
+}
+
+- (void)updateTag:(NSInteger)anInt {
+  if ([self tag] == anInt)
+    return;
+
+  // Forcibly remove any stale tooltip which is being displayed.
+  [self removeAllToolTips];
+
+  [self setTag:anInt];
+  if (anInt == IDC_RELOAD) {
+    [self setImage:app::mac::GetCachedImageWithName(kReloadImageName)];
+    [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_RELOAD)];
+  } else if (anInt == IDC_STOP) {
+    [self setImage:app::mac::GetCachedImageWithName(kStopImageName)];
+    [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STOP)];
+  } else {
+    NOTREACHED();
+  }
+}
+
+- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force {
+  // Can always transition to stop mode.  Only transition to reload
+  // mode if forced or if the mouse isn't hovering.  Otherwise, note
+  // that reload mode is desired and disable the button.
+  if (isLoading) {
+    pendingReloadTimer_.reset();
+    [self updateTag:IDC_STOP];
+    [self setEnabled:YES];
+  } else if (force || ![self isMouseInside]) {
+    pendingReloadTimer_.reset();
+    [self updateTag:IDC_RELOAD];
+
+    // This button's cell may not have received a mouseExited event, and
+    // therefore it could still think that the mouse is inside the button.  Make
+    // sure the cell's sense of mouse-inside matches the local sense, to prevent
+    // drawing artifacts.
+    id cell = [self cell];
+    if ([cell respondsToSelector:@selector(setMouseInside:animate:)])
+      [cell setMouseInside:[self isMouseInside] animate:NO];
+    [self setEnabled:YES];
+  } else if ([self tag] == IDC_STOP && !pendingReloadTimer_) {
+    [self setEnabled:NO];
+    pendingReloadTimer_.reset(
+        [[NSTimer scheduledTimerWithTimeInterval:kPendingReloadTimeout
+                                          target:self
+                                        selector:@selector(forceReloadState)
+                                        userInfo:nil
+                                         repeats:NO] retain]);
+  }
+}
+
+- (void)forceReloadState {
+  [self setIsLoading:NO force:YES];
+}
+
+- (BOOL)sendAction:(SEL)theAction to:(id)theTarget {
+  if ([self tag] == IDC_STOP) {
+    // When the timer is started, the button is disabled, so this
+    // should not be possible.
+    DCHECK(!pendingReloadTimer_.get());
+
+    // When the stop is processed, immediately change to reload mode,
+    // even though the IPC still has to bounce off the renderer and
+    // back before the regular |-setIsLoaded:force:| will be called.
+    // [This is how views and gtk do it.]
+    const BOOL ret = [super sendAction:theAction to:theTarget];
+    if (ret)
+      [self forceReloadState];
+    return ret;
+  }
+
+  return [super sendAction:theAction to:theTarget];
+}
+
+- (void)mouseEntered:(NSEvent*)theEvent {
+  isMouseInside_ = YES;
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+  isMouseInside_ = NO;
+
+  // Reload mode was requested during the hover.
+  if (pendingReloadTimer_)
+    [self forceReloadState];
+}
+
+- (BOOL)isMouseInside {
+  return isMouseInside_;
+}
+
+- (ViewID)viewID {
+  return VIEW_ID_RELOAD_BUTTON;
+}
+
+@end  // ReloadButton
+
+@implementation ReloadButton (Testing)
+
++ (void)setPendingReloadTimeout:(NSTimeInterval)seconds {
+  kPendingReloadTimeout = seconds;
+}
+
+- (NSTrackingArea*)trackingArea {
+  return trackingArea_;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm b/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm
new file mode 100644
index 0000000..a7f7dd1
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm
@@ -0,0 +1,259 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "chrome/browser/ui/cocoa/toolbar/reload_button.h"
+
+#include "base/scoped_nsobject.h"
+#include "chrome/app/chrome_command_ids.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/test_event_utils.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+
+@protocol TargetActionMock <NSObject>
+- (void)anAction:(id)sender;
+@end
+
+namespace {
+
+class ReloadButtonTest : public CocoaTest {
+ public:
+  ReloadButtonTest() {
+    NSRect frame = NSMakeRect(0, 0, 20, 20);
+    scoped_nsobject<ReloadButton> button(
+        [[ReloadButton alloc] initWithFrame:frame]);
+    button_ = button.get();
+
+    // Set things up so unit tests have a reliable baseline.
+    [button_ setTag:IDC_RELOAD];
+    [button_ awakeFromNib];
+
+    [[test_window() contentView] addSubview:button_];
+  }
+
+  ReloadButton* button_;
+};
+
+TEST_VIEW(ReloadButtonTest, button_)
+
+// Test that mouse-tracking is setup and does the right thing.
+TEST_F(ReloadButtonTest, IsMouseInside) {
+  EXPECT_TRUE([[button_ trackingAreas] containsObject:[button_ trackingArea]]);
+
+  EXPECT_FALSE([button_ isMouseInside]);
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ mouseExited:nil];
+}
+
+// Verify that multiple clicks do not result in multiple messages to
+// the target.
+TEST_F(ReloadButtonTest, IgnoredMultiClick) {
+  id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)];
+  [button_ setTarget:mock_target];
+  [button_ setAction:@selector(anAction:)];
+
+  // Expect the action once.
+  [[mock_target expect] anAction:button_];
+
+  const std::pair<NSEvent*,NSEvent*> click_one =
+      test_event_utils::MouseClickInView(button_, 1);
+  const std::pair<NSEvent*,NSEvent*> click_two =
+      test_event_utils::MouseClickInView(button_, 2);
+  [NSApp postEvent:click_one.second atStart:YES];
+  [button_ mouseDown:click_one.first];
+  [NSApp postEvent:click_two.second atStart:YES];
+  [button_ mouseDown:click_two.first];
+
+  [button_ setTarget:nil];
+}
+
+TEST_F(ReloadButtonTest, UpdateTag) {
+  [button_ setTag:IDC_STOP];
+
+  [button_ updateTag:IDC_RELOAD];
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+  NSImage* reloadImage = [button_ image];
+  NSString* const reloadToolTip = [button_ toolTip];
+
+  [button_ updateTag:IDC_STOP];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  NSImage* stopImage = [button_ image];
+  NSString* const stopToolTip = [button_ toolTip];
+  EXPECT_NSNE(reloadImage, stopImage);
+  EXPECT_NSNE(reloadToolTip, stopToolTip);
+
+  [button_ updateTag:IDC_RELOAD];
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+  EXPECT_NSEQ(reloadImage, [button_ image]);
+  EXPECT_NSEQ(reloadToolTip, [button_ toolTip]);
+}
+
+// Test that when forcing the mode, it takes effect immediately,
+// regardless of whether the mouse is hovering.
+TEST_F(ReloadButtonTest, SetIsLoadingForce) {
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+
+  // Changes to stop immediately.
+  [button_ setIsLoading:YES force:YES];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+
+  // Changes to reload immediately.
+  [button_ setIsLoading:NO force:YES];
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+
+  // Changes to stop immediately when the mouse is hovered, and
+  // doesn't change when the mouse exits.
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:YES force:YES];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  [button_ mouseExited:nil];
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+
+  // Changes to reload immediately when the mouse is hovered, and
+  // doesn't change when the mouse exits.
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:NO force:YES];
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+  [button_ mouseExited:nil];
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+}
+
+// Test that without force, stop mode is set immediately, but reload
+// is affected by the hover status.
+TEST_F(ReloadButtonTest, SetIsLoadingNoForceUnHover) {
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+
+  // Changes to stop immediately when the mouse is not hovering.
+  [button_ setIsLoading:YES force:NO];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+
+  // Changes to reload immediately when the mouse is not hovering.
+  [button_ setIsLoading:NO force:NO];
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+
+  // Changes to stop immediately when the mouse is hovered, and
+  // doesn't change when the mouse exits.
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:YES force:NO];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  [button_ mouseExited:nil];
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+
+  // Does not change to reload immediately when the mouse is hovered,
+  // changes when the mouse exits.
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:NO force:NO];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  [button_ mouseExited:nil];
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+}
+
+// Test that without force, stop mode is set immediately, and reload
+// will be set after a timeout.
+// TODO(shess): Reenable, http://crbug.com/61485
+TEST_F(ReloadButtonTest, DISABLED_SetIsLoadingNoForceTimeout) {
+  // When the event loop first spins, some delayed tracking-area setup
+  // is done, which causes -mouseExited: to be called.  Spin it at
+  // least once, and dequeue any pending events.
+  // TODO(shess): It would be more reasonable to have an MockNSTimer
+  // factory for the class to use, which this code could fire
+  // directly.
+  while ([NSApp nextEventMatchingMask:NSAnyEventMask
+                            untilDate:nil
+                               inMode:NSDefaultRunLoopMode
+                              dequeue:YES]) {
+  }
+
+  const NSTimeInterval kShortTimeout = 0.1;
+  [ReloadButton setPendingReloadTimeout:kShortTimeout];
+
+  EXPECT_FALSE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+
+  // Move the mouse into the button and press it.
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:YES force:NO];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+
+  // Does not change to reload immediately when the mouse is hovered.
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:NO force:NO];
+  EXPECT_TRUE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  EXPECT_TRUE([button_ isMouseInside]);
+
+  // Spin event loop until the timeout passes.
+  NSDate* pastTimeout = [NSDate dateWithTimeIntervalSinceNow:2 * kShortTimeout];
+  [NSApp nextEventMatchingMask:NSAnyEventMask
+                     untilDate:pastTimeout
+                        inMode:NSDefaultRunLoopMode
+                       dequeue:NO];
+
+  // Mouse is still hovered, button is in reload mode.  If the mouse
+  // is no longer hovered, see comment at top of function.
+  EXPECT_TRUE([button_ isMouseInside]);
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+}
+
+// Test that pressing stop after reload mode has been requested
+// doesn't forward the stop message.
+TEST_F(ReloadButtonTest, StopAfterReloadSet) {
+  id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)];
+  [button_ setTarget:mock_target];
+  [button_ setAction:@selector(anAction:)];
+
+  EXPECT_FALSE([button_ isMouseInside]);
+
+  // Get to stop mode.
+  [button_ setIsLoading:YES force:YES];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  EXPECT_TRUE([button_ isEnabled]);
+
+  // Expect the action once.
+  [[mock_target expect] anAction:button_];
+
+  // Clicking in stop mode should send the action and transition to
+  // reload mode.
+  const std::pair<NSEvent*,NSEvent*> click =
+      test_event_utils::MouseClickInView(button_, 1);
+  [NSApp postEvent:click.second atStart:YES];
+  [button_ mouseDown:click.first];
+  EXPECT_EQ(IDC_RELOAD, [button_ tag]);
+  EXPECT_TRUE([button_ isEnabled]);
+
+  // Get back to stop mode.
+  [button_ setIsLoading:YES force:YES];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  EXPECT_TRUE([button_ isEnabled]);
+
+  // If hover prevented reload mode immediately taking effect, clicks should do
+  // nothing, because the button should be disabled.
+  [button_ mouseEntered:nil];
+  EXPECT_TRUE([button_ isMouseInside]);
+  [button_ setIsLoading:NO force:NO];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+  EXPECT_FALSE([button_ isEnabled]);
+  [NSApp postEvent:click.second atStart:YES];
+  [button_ mouseDown:click.first];
+  EXPECT_EQ(IDC_STOP, [button_ tag]);
+
+  [button_ setTarget:nil];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
new file mode 100644
index 0000000..f95a060
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
@@ -0,0 +1,187 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_ptr.h"
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/command_observer_bridge.h"
+#import "chrome/browser/ui/cocoa/url_drop_target.h"
+#import "chrome/browser/ui/cocoa/view_resizer.h"
+#include "chrome/browser/prefs/pref_member.h"
+
+@class AutocompleteTextField;
+@class AutocompleteTextFieldEditor;
+@class BrowserActionsContainerView;
+@class BackForwardMenuController;
+class Browser;
+@class BrowserActionsController;
+class CommandUpdater;
+class LocationBar;
+class LocationBarViewMac;
+@class MenuButton;
+namespace ToolbarControllerInternal {
+class NotificationBridge;
+class WrenchAcceleratorDelegate;
+}  // namespace ToolbarControllerInternal
+class Profile;
+@class ReloadButton;
+class TabContents;
+class ToolbarModel;
+@class WrenchMenuController;
+class WrenchMenuModel;
+
+// A controller for the toolbar in the browser window. Manages
+// updating the state for location bar and back/fwd/reload/go buttons.
+// Manages the bookmark bar and its position in the window relative to
+// the web content view.
+
+@interface ToolbarController : NSViewController<CommandObserverProtocol,
+                                                URLDropTargetController> {
+ @protected
+  // The ordering is important for unit tests. If new items are added or the
+  // ordering is changed, make sure to update |-toolbarViews| and the
+  // corresponding enum in the unit tests.
+  IBOutlet MenuButton* backButton_;
+  IBOutlet MenuButton* forwardButton_;
+  IBOutlet ReloadButton* reloadButton_;
+  IBOutlet NSButton* homeButton_;
+  IBOutlet MenuButton* wrenchButton_;
+  IBOutlet AutocompleteTextField* locationBar_;
+  IBOutlet BrowserActionsContainerView* browserActionsContainerView_;
+  IBOutlet WrenchMenuController* wrenchMenuController_;
+
+ @private
+  ToolbarModel* toolbarModel_;  // weak, one per window
+  CommandUpdater* commands_;  // weak, one per window
+  Profile* profile_;  // weak, one per window
+  Browser* browser_;  // weak, one per window
+  scoped_ptr<CommandObserverBridge> commandObserver_;
+  scoped_ptr<LocationBarViewMac> locationBarView_;
+  scoped_nsobject<AutocompleteTextFieldEditor> autocompleteTextFieldEditor_;
+  id<ViewResizer> resizeDelegate_;  // weak
+  scoped_nsobject<BackForwardMenuController> backMenuController_;
+  scoped_nsobject<BackForwardMenuController> forwardMenuController_;
+  scoped_nsobject<BrowserActionsController> browserActionsController_;
+
+  // Lazily-instantiated model and delegate for the menu on the
+  // wrench button.  Once visible, it will be non-null, but will not
+  // reaped when the menu is hidden once it is initially shown.
+  scoped_ptr<ToolbarControllerInternal::WrenchAcceleratorDelegate>
+      acceleratorDelegate_;
+  scoped_ptr<WrenchMenuModel> wrenchMenuModel_;
+
+  // Used for monitoring the optional toolbar button prefs.
+  scoped_ptr<ToolbarControllerInternal::NotificationBridge> notificationBridge_;
+  BooleanPrefMember showHomeButton_;
+  BooleanPrefMember showPageOptionButtons_;
+  BOOL hasToolbar_;  // If NO, we may have only the location bar.
+  BOOL hasLocationBar_;  // If |hasToolbar_| is YES, this must also be YES.
+  BOOL locationBarAtMinSize_; // If the location bar is at the minimum size.
+
+  // We have an extra retain in the locationBar_.
+  // See comments in awakeFromNib for more info.
+  scoped_nsobject<AutocompleteTextField> locationBarRetainer_;
+
+  // Tracking area for mouse enter/exit/moved in the toolbar.
+  scoped_nsobject<NSTrackingArea> trackingArea_;
+
+  // We retain/release the hover button since interaction with the
+  // button may make it go away (e.g. delete menu option over a
+  // bookmark button).  Thus this variable is not weak.  The
+  // hoveredButton_ is required to have an NSCell that responds to
+  // setMouseInside:animate:.
+  NSButton* hoveredButton_;
+}
+
+// Initialize the toolbar and register for command updates. The profile is
+// needed for initializing the location bar. The browser is needed for
+// initializing the back/forward menus.
+- (id)initWithModel:(ToolbarModel*)model
+           commands:(CommandUpdater*)commands
+            profile:(Profile*)profile
+            browser:(Browser*)browser
+     resizeDelegate:(id<ViewResizer>)resizeDelegate;
+
+// Get the C++ bridge object representing the location bar for this tab.
+- (LocationBarViewMac*)locationBarBridge;
+
+// Called by the Window delegate so we can provide a custom field editor if
+// needed.
+// Note that this may be called for objects unrelated to the toolbar.
+// returns nil if we don't want to override the custom field editor for |obj|.
+- (id)customFieldEditorForObject:(id)obj;
+
+// Make the location bar the first responder, if possible.
+- (void)focusLocationBar:(BOOL)selectAll;
+
+// Updates the toolbar (and transitively the location bar) with the states of
+// the specified |tab|.  If |shouldRestore| is true, we're switching
+// (back?) to this tab and should restore any previous location bar state
+// (such as user editing) as well.
+- (void)updateToolbarWithContents:(TabContents*)tabForRestoring
+               shouldRestoreState:(BOOL)shouldRestore;
+
+// Sets whether or not the current page in the frontmost tab is bookmarked.
+- (void)setStarredState:(BOOL)isStarred;
+
+// Called to update the loading state. Handles updating the go/stop
+// button state.  |force| is set if the update is due to changing
+// tabs, as opposed to the page-load finishing.  See comment in
+// reload_button.h.
+- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force;
+
+// Allow turning off the toolbar (but we may keep the location bar without a
+// surrounding toolbar). If |toolbar| is YES, the value of |hasLocationBar| is
+// ignored. This changes the behavior of other methods, like |-view|.
+- (void)setHasToolbar:(BOOL)toolbar hasLocationBar:(BOOL)locBar;
+
+// Point on the star icon for the bookmark bubble to be - in the
+// associated window's coordinate system.
+- (NSPoint)bookmarkBubblePoint;
+
+// Returns the desired toolbar height for the given compression factor.
+- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight;
+
+// Set the opacity of the divider (the line at the bottom) *if* we have a
+// |ToolbarView| (0 means don't show it); no-op otherwise.
+- (void)setDividerOpacity:(CGFloat)opacity;
+
+// Create and add the Browser Action buttons to the toolbar view.
+- (void)createBrowserActionButtons;
+
+// Return the BrowserActionsController for this toolbar.
+- (BrowserActionsController*)browserActionsController;
+
+@end
+
+// A set of private methods used by subclasses. Do not call these directly
+// unless a subclass of ToolbarController.
+@interface ToolbarController(ProtectedMethods)
+// Designated initializer which takes a nib name in order to allow subclasses
+// to load a different nib file.
+- (id)initWithModel:(ToolbarModel*)model
+           commands:(CommandUpdater*)commands
+            profile:(Profile*)profile
+            browser:(Browser*)browser
+     resizeDelegate:(id<ViewResizer>)resizeDelegate
+       nibFileNamed:(NSString*)nibName;
+@end
+
+// A set of private methods used by tests, in the absence of "friends" in ObjC.
+@interface ToolbarController(PrivateTestMethods)
+// Returns an array of views in the order of the outlets above.
+- (NSArray*)toolbarViews;
+- (void)showOptionalHomeButton;
+- (void)installWrenchMenu;
+- (WrenchMenuController*)wrenchMenuController;
+// Return a hover button for the current event.
+- (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
new file mode 100644
index 0000000..bc0de9a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -0,0 +1,807 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+
+#include <algorithm>
+
+#include "ui/base/l10n/l10n_util.h"
+#include "app/mac/nsimage_cache.h"
+#include "base/mac/mac_util.h"
+#include "base/singleton.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "chrome/browser/background_page_tracker.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/upgrade_detector.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#import "chrome/browser/ui/cocoa/accelerators_cocoa.h"
+#import "chrome/browser/ui/cocoa/background_gradient_view.h"
+#import "chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.h"
+#import "chrome/browser/ui/cocoa/extensions/browser_action_button.h"
+#import "chrome/browser/ui/cocoa/extensions/browser_actions_container_view.h"
+#import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
+#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
+#import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
+#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
+#import "chrome/browser/ui/cocoa/menu_button.h"
+#import "chrome/browser/ui/cocoa/menu_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/back_forward_menu_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/reload_button.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_view.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+#import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h"
+#include "chrome/browser/ui/toolbar/toolbar_model.h"
+#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/models/accelerator_cocoa.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/rect.h"
+
+namespace {
+
+// Names of images in the bundle for buttons.
+NSString* const kBackButtonImageName = @"back_Template.pdf";
+NSString* const kForwardButtonImageName = @"forward_Template.pdf";
+NSString* const kReloadButtonReloadImageName = @"reload_Template.pdf";
+NSString* const kReloadButtonStopImageName = @"stop_Template.pdf";
+NSString* const kHomeButtonImageName = @"home_Template.pdf";
+NSString* const kWrenchButtonImageName = @"tools_Template.pdf";
+
+// Height of the toolbar in pixels when the bookmark bar is closed.
+const CGFloat kBaseToolbarHeight = 35.0;
+
+// The minimum width of the location bar in pixels.
+const CGFloat kMinimumLocationBarWidth = 100.0;
+
+// The duration of any animation that occurs within the toolbar in seconds.
+const CGFloat kAnimationDuration = 0.2;
+
+// The amount of left padding that the wrench menu should have.
+const CGFloat kWrenchMenuLeftPadding = 3.0;
+
+}  // namespace
+
+@interface ToolbarController(Private)
+- (void)addAccessibilityDescriptions;
+- (void)initCommandStatus:(CommandUpdater*)commands;
+- (void)prefChanged:(std::string*)prefName;
+- (BackgroundGradientView*)backgroundGradientView;
+- (void)toolbarFrameChanged;
+- (void)pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:(BOOL)animate;
+- (void)maintainMinimumLocationBarWidth;
+- (void)adjustBrowserActionsContainerForNewWindow:(NSNotification*)notification;
+- (void)browserActionsContainerDragged:(NSNotification*)notification;
+- (void)browserActionsContainerDragFinished:(NSNotification*)notification;
+- (void)browserActionsVisibilityChanged:(NSNotification*)notification;
+- (void)adjustLocationSizeBy:(CGFloat)dX animate:(BOOL)animate;
+- (void)badgeWrenchMenuIfNeeded;
+@end
+
+namespace ToolbarControllerInternal {
+
+// A C++ delegate that handles the accelerators in the wrench menu.
+class WrenchAcceleratorDelegate : public ui::AcceleratorProvider {
+ public:
+  virtual bool GetAcceleratorForCommandId(int command_id,
+      ui::Accelerator* accelerator_generic) {
+    // Downcast so that when the copy constructor is invoked below, the key
+    // string gets copied, too.
+    ui::AcceleratorCocoa* out_accelerator =
+        static_cast<ui::AcceleratorCocoa*>(accelerator_generic);
+    AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance();
+    const ui::AcceleratorCocoa* accelerator =
+        keymap->GetAcceleratorForCommand(command_id);
+    if (accelerator) {
+      *out_accelerator = *accelerator;
+      return true;
+    }
+    return false;
+  }
+};
+
+// A class registered for C++ notifications. This is used to detect changes in
+// preferences and upgrade available notifications. Bridges the notification
+// back to the ToolbarController.
+class NotificationBridge : public NotificationObserver {
+ public:
+  explicit NotificationBridge(ToolbarController* controller)
+      : controller_(controller) {
+    registrar_.Add(this, NotificationType::UPGRADE_RECOMMENDED,
+                   NotificationService::AllSources());
+    registrar_.Add(this,
+                   NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED,
+                   NotificationService::AllSources());
+  }
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) {
+    switch (type.value) {
+      case NotificationType::PREF_CHANGED:
+        [controller_ prefChanged:Details<std::string>(details).ptr()];
+        break;
+      case NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED:
+        // fall-through
+      case NotificationType::UPGRADE_RECOMMENDED:
+        [controller_ badgeWrenchMenuIfNeeded];
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+
+ private:
+  ToolbarController* controller_;  // weak, owns us
+
+  NotificationRegistrar registrar_;
+};
+
+}  // namespace ToolbarControllerInternal
+
+@implementation ToolbarController
+
+- (id)initWithModel:(ToolbarModel*)model
+           commands:(CommandUpdater*)commands
+            profile:(Profile*)profile
+            browser:(Browser*)browser
+     resizeDelegate:(id<ViewResizer>)resizeDelegate
+       nibFileNamed:(NSString*)nibName {
+  DCHECK(model && commands && profile && [nibName length]);
+  if ((self = [super initWithNibName:nibName
+                              bundle:base::mac::MainAppBundle()])) {
+    toolbarModel_ = model;
+    commands_ = commands;
+    profile_ = profile;
+    browser_ = browser;
+    resizeDelegate_ = resizeDelegate;
+    hasToolbar_ = YES;
+    hasLocationBar_ = YES;
+
+    // Register for notifications about state changes for the toolbar buttons
+    commandObserver_.reset(new CommandObserverBridge(self, commands));
+    commandObserver_->ObserveCommand(IDC_BACK);
+    commandObserver_->ObserveCommand(IDC_FORWARD);
+    commandObserver_->ObserveCommand(IDC_RELOAD);
+    commandObserver_->ObserveCommand(IDC_HOME);
+    commandObserver_->ObserveCommand(IDC_BOOKMARK_PAGE);
+  }
+  return self;
+}
+
+- (id)initWithModel:(ToolbarModel*)model
+           commands:(CommandUpdater*)commands
+            profile:(Profile*)profile
+            browser:(Browser*)browser
+     resizeDelegate:(id<ViewResizer>)resizeDelegate {
+  if ((self = [self initWithModel:model
+                         commands:commands
+                          profile:profile
+                          browser:browser
+                   resizeDelegate:resizeDelegate
+                     nibFileNamed:@"Toolbar"])) {
+  }
+  return self;
+}
+
+
+- (void)dealloc {
+  // Unset ViewIDs of toolbar elements.
+  // ViewIDs of |toolbarView|, |reloadButton_|, |locationBar_| and
+  // |browserActionsContainerView_| are handled by themselves.
+  view_id_util::UnsetID(backButton_);
+  view_id_util::UnsetID(forwardButton_);
+  view_id_util::UnsetID(homeButton_);
+  view_id_util::UnsetID(wrenchButton_);
+
+  // Make sure any code in the base class which assumes [self view] is
+  // the "parent" view continues to work.
+  hasToolbar_ = YES;
+  hasLocationBar_ = YES;
+
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+  if (trackingArea_.get())
+    [[self view] removeTrackingArea:trackingArea_.get()];
+  [super dealloc];
+}
+
+// Called after the view is done loading and the outlets have been hooked up.
+// Now we can hook up bridges that rely on UI objects such as the location
+// bar and button state.
+- (void)awakeFromNib {
+  // A bug in AppKit (<rdar://7298597>, <http://openradar.me/7298597>) causes
+  // images loaded directly from nibs in a framework to not get their "template"
+  // flags set properly. Thus, despite the images being set on the buttons in
+  // the xib, we must set them in code.
+  [backButton_ setImage:app::mac::GetCachedImageWithName(kBackButtonImageName)];
+  [forwardButton_ setImage:
+      app::mac::GetCachedImageWithName(kForwardButtonImageName)];
+  [reloadButton_ setImage:
+      app::mac::GetCachedImageWithName(kReloadButtonReloadImageName)];
+  [homeButton_ setImage:
+      app::mac::GetCachedImageWithName(kHomeButtonImageName)];
+  [wrenchButton_ setImage:
+      app::mac::GetCachedImageWithName(kWrenchButtonImageName)];
+  [self badgeWrenchMenuIfNeeded];
+
+  [wrenchButton_ setOpenMenuOnClick:YES];
+
+  [backButton_ setShowsBorderOnlyWhileMouseInside:YES];
+  [forwardButton_ setShowsBorderOnlyWhileMouseInside:YES];
+  [reloadButton_ setShowsBorderOnlyWhileMouseInside:YES];
+  [homeButton_ setShowsBorderOnlyWhileMouseInside:YES];
+  [wrenchButton_ setShowsBorderOnlyWhileMouseInside:YES];
+
+  [self initCommandStatus:commands_];
+  locationBarView_.reset(new LocationBarViewMac(locationBar_,
+                                                commands_, toolbarModel_,
+                                                profile_, browser_));
+  [locationBar_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
+  // Register pref observers for the optional home and page/options buttons
+  // and then add them to the toolbar based on those prefs.
+  notificationBridge_.reset(
+      new ToolbarControllerInternal::NotificationBridge(self));
+  PrefService* prefs = profile_->GetPrefs();
+  showHomeButton_.Init(prefs::kShowHomeButton, prefs,
+                       notificationBridge_.get());
+  showPageOptionButtons_.Init(prefs::kShowPageOptionsButtons, prefs,
+                              notificationBridge_.get());
+  [self showOptionalHomeButton];
+  [self installWrenchMenu];
+
+  // Create the controllers for the back/forward menus.
+  backMenuController_.reset([[BackForwardMenuController alloc]
+          initWithBrowser:browser_
+                modelType:BACK_FORWARD_MENU_TYPE_BACK
+                   button:backButton_]);
+  forwardMenuController_.reset([[BackForwardMenuController alloc]
+          initWithBrowser:browser_
+                modelType:BACK_FORWARD_MENU_TYPE_FORWARD
+                   button:forwardButton_]);
+
+  // For a popup window, the toolbar is really just a location bar
+  // (see override for [ToolbarController view], below).  When going
+  // fullscreen, we remove the toolbar controller's view from the view
+  // hierarchy.  Calling [locationBar_ removeFromSuperview] when going
+  // fullscreen causes it to get released, making us unhappy
+  // (http://crbug.com/18551).  We avoid the problem by incrementing
+  // the retain count of the location bar; use of the scoped object
+  // helps us remember to release it.
+  locationBarRetainer_.reset([locationBar_ retain]);
+  trackingArea_.reset(
+      [[NSTrackingArea alloc] initWithRect:NSZeroRect // Ignored
+                                   options:NSTrackingMouseMoved |
+                                           NSTrackingInVisibleRect |
+                                           NSTrackingMouseEnteredAndExited |
+                                           NSTrackingActiveAlways
+                                     owner:self
+                                  userInfo:nil]);
+  NSView* toolbarView = [self view];
+  [toolbarView addTrackingArea:trackingArea_.get()];
+
+  // If the user has any Browser Actions installed, the container view for them
+  // may have to be resized depending on the width of the toolbar frame.
+  [toolbarView setPostsFrameChangedNotifications:YES];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(toolbarFrameChanged)
+             name:NSViewFrameDidChangeNotification
+           object:toolbarView];
+
+  // Set ViewIDs for toolbar elements which don't have their dedicated class.
+  // ViewIDs of |toolbarView|, |reloadButton_|, |locationBar_| and
+  // |browserActionsContainerView_| are handled by themselves.
+  view_id_util::SetID(backButton_, VIEW_ID_BACK_BUTTON);
+  view_id_util::SetID(forwardButton_, VIEW_ID_FORWARD_BUTTON);
+  view_id_util::SetID(homeButton_, VIEW_ID_HOME_BUTTON);
+  view_id_util::SetID(wrenchButton_, VIEW_ID_APP_MENU);
+
+  [self addAccessibilityDescriptions];
+}
+
+- (void)addAccessibilityDescriptions {
+  // Set accessibility descriptions. http://openradar.appspot.com/7496255
+  NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_BACK);
+  [[backButton_ cell]
+      accessibilitySetOverrideValue:description
+                       forAttribute:NSAccessibilityDescriptionAttribute];
+  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_FORWARD);
+  [[forwardButton_ cell]
+      accessibilitySetOverrideValue:description
+                       forAttribute:NSAccessibilityDescriptionAttribute];
+  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_RELOAD);
+  [[reloadButton_ cell]
+      accessibilitySetOverrideValue:description
+                       forAttribute:NSAccessibilityDescriptionAttribute];
+  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_HOME);
+  [[homeButton_ cell]
+      accessibilitySetOverrideValue:description
+                       forAttribute:NSAccessibilityDescriptionAttribute];
+  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_LOCATION);
+  [[locationBar_ cell]
+      accessibilitySetOverrideValue:description
+                       forAttribute:NSAccessibilityDescriptionAttribute];
+  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_APP);
+  [[wrenchButton_ cell]
+      accessibilitySetOverrideValue:description
+                       forAttribute:NSAccessibilityDescriptionAttribute];
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+  [[hoveredButton_ cell] setMouseInside:NO animate:YES];
+  [hoveredButton_ release];
+  hoveredButton_ = nil;
+}
+
+- (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent {
+  NSButton* targetView = (NSButton*)[[self view]
+                                     hitTest:[theEvent locationInWindow]];
+
+  // Only interpret the view as a hoverButton_ if it's both button and has a
+  // button cell that cares.  GradientButtonCell derived cells care.
+  if (([targetView isKindOfClass:[NSButton class]]) &&
+      ([[targetView cell]
+         respondsToSelector:@selector(setMouseInside:animate:)]))
+    return targetView;
+  return nil;
+}
+
+- (void)mouseMoved:(NSEvent*)theEvent {
+  NSButton* targetView = [self hoverButtonForEvent:theEvent];
+  if (hoveredButton_ != targetView) {
+    [[hoveredButton_ cell] setMouseInside:NO animate:YES];
+    [[targetView cell] setMouseInside:YES animate:YES];
+    [hoveredButton_ release];
+    hoveredButton_ = [targetView retain];
+  }
+}
+
+- (void)mouseEntered:(NSEvent*)event {
+  [self mouseMoved:event];
+}
+
+- (LocationBarViewMac*)locationBarBridge {
+  return locationBarView_.get();
+}
+
+- (void)focusLocationBar:(BOOL)selectAll {
+  if (locationBarView_.get())
+    locationBarView_->FocusLocation(selectAll ? true : false);
+}
+
+// Called when the state for a command changes to |enabled|. Update the
+// corresponding UI element.
+- (void)enabledStateChangedForCommand:(NSInteger)command enabled:(BOOL)enabled {
+  NSButton* button = nil;
+  switch (command) {
+    case IDC_BACK:
+      button = backButton_;
+      break;
+    case IDC_FORWARD:
+      button = forwardButton_;
+      break;
+    case IDC_HOME:
+      button = homeButton_;
+      break;
+  }
+  [button setEnabled:enabled];
+}
+
+// Init the enabled state of the buttons on the toolbar to match the state in
+// the controller.
+- (void)initCommandStatus:(CommandUpdater*)commands {
+  [backButton_ setEnabled:commands->IsCommandEnabled(IDC_BACK) ? YES : NO];
+  [forwardButton_
+      setEnabled:commands->IsCommandEnabled(IDC_FORWARD) ? YES : NO];
+  [reloadButton_ setEnabled:YES];
+  [homeButton_ setEnabled:commands->IsCommandEnabled(IDC_HOME) ? YES : NO];
+}
+
+- (void)updateToolbarWithContents:(TabContents*)tab
+               shouldRestoreState:(BOOL)shouldRestore {
+  locationBarView_->Update(tab, shouldRestore ? true : false);
+
+  [locationBar_ updateCursorAndToolTipRects];
+
+  if (browserActionsController_.get()) {
+    [browserActionsController_ update];
+  }
+}
+
+- (void)setStarredState:(BOOL)isStarred {
+  locationBarView_->SetStarred(isStarred ? true : false);
+}
+
+- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force {
+  [reloadButton_ setIsLoading:isLoading force:force];
+}
+
+- (void)setHasToolbar:(BOOL)toolbar hasLocationBar:(BOOL)locBar {
+  [self view];  // Force nib loading.
+
+  hasToolbar_ = toolbar;
+
+  // If there's a toolbar, there must be a location bar.
+  DCHECK((toolbar && locBar) || !toolbar);
+  hasLocationBar_ = toolbar ? YES : locBar;
+
+  // Decide whether to hide/show based on whether there's a location bar.
+  [[self view] setHidden:!hasLocationBar_];
+
+  // Make location bar not editable when in a pop-up.
+  locationBarView_->SetEditable(toolbar);
+}
+
+- (NSView*)view {
+  if (hasToolbar_)
+    return [super view];
+  return locationBar_;
+}
+
+// (Private) Returns the backdrop to the toolbar.
+- (BackgroundGradientView*)backgroundGradientView {
+  // We really do mean |[super view]|; see our override of |-view|.
+  DCHECK([[super view] isKindOfClass:[BackgroundGradientView class]]);
+  return (BackgroundGradientView*)[super view];
+}
+
+- (id)customFieldEditorForObject:(id)obj {
+  if (obj == locationBar_) {
+    // Lazilly construct Field editor, Cocoa UI code always runs on the
+    // same thread, so there shoudn't be a race condition here.
+    if (autocompleteTextFieldEditor_.get() == nil) {
+      autocompleteTextFieldEditor_.reset(
+          [[AutocompleteTextFieldEditor alloc] init]);
+    }
+
+    // This needs to be called every time, otherwise notifications
+    // aren't sent correctly.
+    DCHECK(autocompleteTextFieldEditor_.get());
+    [autocompleteTextFieldEditor_.get() setFieldEditor:YES];
+    return autocompleteTextFieldEditor_.get();
+  }
+  return nil;
+}
+
+// Returns an array of views in the order of the outlets above.
+- (NSArray*)toolbarViews {
+  return [NSArray arrayWithObjects:backButton_, forwardButton_, reloadButton_,
+             homeButton_, wrenchButton_, locationBar_,
+             browserActionsContainerView_, nil];
+}
+
+// Moves |rect| to the right by |delta|, keeping the right side fixed by
+// shrinking the width to compensate. Passing a negative value for |deltaX|
+// moves to the left and increases the width.
+- (NSRect)adjustRect:(NSRect)rect byAmount:(CGFloat)deltaX {
+  NSRect frame = NSOffsetRect(rect, deltaX, 0);
+  frame.size.width -= deltaX;
+  return frame;
+}
+
+// Show or hide the home button based on the pref.
+- (void)showOptionalHomeButton {
+  // Ignore this message if only showing the URL bar.
+  if (!hasToolbar_)
+    return;
+  BOOL hide = showHomeButton_.GetValue() ? NO : YES;
+  if (hide == [homeButton_ isHidden])
+    return;  // Nothing to do, view state matches pref state.
+
+  // Always shift the text field by the width of the home button minus one pixel
+  // since the frame edges of each button are right on top of each other. When
+  // hiding the button, reverse the direction of the movement (to the left).
+  CGFloat moveX = [homeButton_ frame].size.width - 1.0;
+  if (hide)
+    moveX *= -1;  // Reverse the direction of the move.
+
+  [locationBar_ setFrame:[self adjustRect:[locationBar_ frame]
+                                 byAmount:moveX]];
+  [homeButton_ setHidden:hide];
+}
+
+// Install the menu wrench buttons. Calling this repeatedly is inexpensive so it
+// can be done every time the buttons are shown.
+- (void)installWrenchMenu {
+  if (wrenchMenuModel_.get())
+    return;
+  acceleratorDelegate_.reset(
+      new ToolbarControllerInternal::WrenchAcceleratorDelegate());
+
+  wrenchMenuModel_.reset(new WrenchMenuModel(
+      acceleratorDelegate_.get(), browser_));
+  [wrenchMenuController_ setModel:wrenchMenuModel_.get()];
+  [wrenchMenuController_ setUseWithPopUpButtonCell:YES];
+  [wrenchButton_ setAttachedMenu:[wrenchMenuController_ menu]];
+}
+
+- (WrenchMenuController*)wrenchMenuController {
+  return wrenchMenuController_;
+}
+
+- (void)badgeWrenchMenuIfNeeded {
+
+  int badgeResource = 0;
+  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
+    badgeResource = IDR_UPDATE_BADGE;
+  } else if (BackgroundPageTracker::GetInstance()->
+             GetUnacknowledgedBackgroundPageCount() > 0) {
+    badgeResource = IDR_BACKGROUND_BADGE;
+  } else {
+    // No badge - clear the badge if one is already set.
+    if ([[wrenchButton_ cell] overlayImage])
+      [[wrenchButton_ cell] setOverlayImage:nil];
+    return;
+  }
+
+  NSImage* badge =
+      ResourceBundle::GetSharedInstance().GetNativeImageNamed(badgeResource);
+  NSImage* wrenchImage =
+      app::mac::GetCachedImageWithName(kWrenchButtonImageName);
+  NSSize wrenchImageSize = [wrenchImage size];
+  NSSize badgeSize = [badge size];
+
+  scoped_nsobject<NSImage> overlayImage(
+      [[NSImage alloc] initWithSize:wrenchImageSize]);
+
+  // Draw badge in the upper right corner of the button.
+  NSPoint overlayPosition =
+      NSMakePoint(wrenchImageSize.width - badgeSize.width,
+                  wrenchImageSize.height - badgeSize.height);
+
+  [overlayImage lockFocus];
+  [badge drawAtPoint:overlayPosition
+            fromRect:NSZeroRect
+           operation:NSCompositeSourceOver
+            fraction:1.0];
+  [overlayImage unlockFocus];
+
+  [[wrenchButton_ cell] setOverlayImage:overlayImage];
+}
+
+- (void)prefChanged:(std::string*)prefName {
+  if (!prefName) return;
+  if (*prefName == prefs::kShowHomeButton) {
+    [self showOptionalHomeButton];
+  }
+}
+
+- (void)createBrowserActionButtons {
+  if (!browserActionsController_.get()) {
+    browserActionsController_.reset([[BrowserActionsController alloc]
+            initWithBrowser:browser_
+              containerView:browserActionsContainerView_]);
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(browserActionsContainerDragged:)
+               name:kBrowserActionGrippyDraggingNotification
+             object:browserActionsController_];
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(browserActionsContainerDragFinished:)
+               name:kBrowserActionGrippyDragFinishedNotification
+             object:browserActionsController_];
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(browserActionsVisibilityChanged:)
+               name:kBrowserActionVisibilityChangedNotification
+             object:browserActionsController_];
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(adjustBrowserActionsContainerForNewWindow:)
+               name:NSWindowDidBecomeKeyNotification
+             object:[[self view] window]];
+  }
+  CGFloat containerWidth = [browserActionsContainerView_ isHidden] ? 0.0 :
+      NSWidth([browserActionsContainerView_ frame]);
+  if (containerWidth > 0.0)
+    [self adjustLocationSizeBy:(containerWidth * -1) animate:NO];
+}
+
+- (void)adjustBrowserActionsContainerForNewWindow:
+    (NSNotification*)notification {
+  [self toolbarFrameChanged];
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:NSWindowDidBecomeKeyNotification
+              object:[[self view] window]];
+}
+
+- (void)browserActionsContainerDragged:(NSNotification*)notification {
+  CGFloat locationBarWidth = NSWidth([locationBar_ frame]);
+  locationBarAtMinSize_ = locationBarWidth <= kMinimumLocationBarWidth;
+  [browserActionsContainerView_ setCanDragLeft:!locationBarAtMinSize_];
+  [browserActionsContainerView_ setGrippyPinned:locationBarAtMinSize_];
+  [self adjustLocationSizeBy:
+      [browserActionsContainerView_ resizeDeltaX] animate:NO];
+}
+
+- (void)browserActionsContainerDragFinished:(NSNotification*)notification {
+  [browserActionsController_ resizeContainerAndAnimate:YES];
+  [self pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:YES];
+}
+
+- (void)browserActionsVisibilityChanged:(NSNotification*)notification {
+  [self pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:NO];
+}
+
+- (void)pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:(BOOL)animate {
+  CGFloat locationBarXPos = NSMaxX([locationBar_ frame]);
+  CGFloat leftDistance;
+
+  if ([browserActionsContainerView_ isHidden]) {
+    CGFloat edgeXPos = [wrenchButton_ frame].origin.x;
+    leftDistance = edgeXPos - locationBarXPos - kWrenchMenuLeftPadding;
+  } else {
+    NSRect containerFrame = animate ?
+        [browserActionsContainerView_ animationEndFrame] :
+        [browserActionsContainerView_ frame];
+
+    leftDistance = containerFrame.origin.x - locationBarXPos;
+  }
+  if (leftDistance != 0.0)
+    [self adjustLocationSizeBy:leftDistance animate:animate];
+}
+
+- (void)maintainMinimumLocationBarWidth {
+  CGFloat locationBarWidth = NSWidth([locationBar_ frame]);
+  locationBarAtMinSize_ = locationBarWidth <= kMinimumLocationBarWidth;
+  if (locationBarAtMinSize_) {
+    CGFloat dX = kMinimumLocationBarWidth - locationBarWidth;
+    [self adjustLocationSizeBy:dX animate:NO];
+  }
+}
+
+- (void)toolbarFrameChanged {
+  // Do nothing if the frame changes but no Browser Action Controller is
+  // present.
+  if (!browserActionsController_.get())
+    return;
+
+  [self maintainMinimumLocationBarWidth];
+
+  if (locationBarAtMinSize_) {
+    // Once the grippy is pinned, leave it until it is explicity un-pinned.
+    [browserActionsContainerView_ setGrippyPinned:YES];
+    NSRect containerFrame = [browserActionsContainerView_ frame];
+    // Determine how much the container needs to move in case it's overlapping
+    // with the location bar.
+    CGFloat dX = NSMaxX([locationBar_ frame]) - containerFrame.origin.x;
+    containerFrame = NSOffsetRect(containerFrame, dX, 0);
+    containerFrame.size.width -= dX;
+    [browserActionsContainerView_ setFrame:containerFrame];
+  } else if (!locationBarAtMinSize_ &&
+      [browserActionsContainerView_ grippyPinned]) {
+    // Expand out the container until it hits the saved size, then unpin the
+    // grippy.
+    // Add 0.1 pixel so that it doesn't hit the minimum width codepath above.
+    CGFloat dX = NSWidth([locationBar_ frame]) -
+        (kMinimumLocationBarWidth + 0.1);
+    NSRect containerFrame = [browserActionsContainerView_ frame];
+    containerFrame = NSOffsetRect(containerFrame, -dX, 0);
+    containerFrame.size.width += dX;
+    CGFloat savedContainerWidth = [browserActionsController_ savedWidth];
+    if (NSWidth(containerFrame) >= savedContainerWidth) {
+      containerFrame = NSOffsetRect(containerFrame,
+          NSWidth(containerFrame) - savedContainerWidth, 0);
+      containerFrame.size.width = savedContainerWidth;
+      [browserActionsContainerView_ setGrippyPinned:NO];
+    }
+    [browserActionsContainerView_ setFrame:containerFrame];
+    [self pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:NO];
+  }
+}
+
+- (void)adjustLocationSizeBy:(CGFloat)dX animate:(BOOL)animate {
+  // Ensure that the location bar is in its proper place.
+  NSRect locationFrame = [locationBar_ frame];
+  locationFrame.size.width += dX;
+
+  if (!animate) {
+    [locationBar_ setFrame:locationFrame];
+    return;
+  }
+
+  [NSAnimationContext beginGrouping];
+  [[NSAnimationContext currentContext] setDuration:kAnimationDuration];
+  [[locationBar_ animator] setFrame:locationFrame];
+  [NSAnimationContext endGrouping];
+}
+
+- (NSPoint)bookmarkBubblePoint {
+  return locationBarView_->GetBookmarkBubblePoint();
+}
+
+- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight {
+  // With no toolbar, just ignore the compression.
+  return hasToolbar_ ? kBaseToolbarHeight - compressByHeight :
+                       NSHeight([locationBar_ frame]);
+}
+
+- (void)setDividerOpacity:(CGFloat)opacity {
+  BackgroundGradientView* view = [self backgroundGradientView];
+  [view setShowsDivider:(opacity > 0 ? YES : NO)];
+
+  // We may not have a toolbar view (e.g., popup windows only have a location
+  // bar).
+  if ([view isKindOfClass:[ToolbarView class]]) {
+    ToolbarView* toolbarView = (ToolbarView*)view;
+    [toolbarView setDividerOpacity:opacity];
+  }
+}
+
+- (BrowserActionsController*)browserActionsController {
+  return browserActionsController_.get();
+}
+
+// (URLDropTargetController protocol)
+- (void)dropURLs:(NSArray*)urls inView:(NSView*)view at:(NSPoint)point {
+  // TODO(viettrungluu): This code is more or less copied from the code in
+  // |TabStripController|. I'll refactor this soon to make it common and expand
+  // its capabilities (e.g., allow text DnD).
+  if ([urls count] < 1) {
+    NOTREACHED();
+    return;
+  }
+
+  // TODO(viettrungluu): dropping multiple URLs?
+  if ([urls count] > 1)
+    NOTIMPLEMENTED();
+
+  // Get the first URL and fix it up.
+  GURL url(URLFixerUpper::FixupURL(
+      base::SysNSStringToUTF8([urls objectAtIndex:0]), std::string()));
+
+  browser_->GetSelectedTabContents()->OpenURL(url, GURL(), CURRENT_TAB,
+                                              PageTransition::TYPED);
+}
+
+// (URLDropTargetController protocol)
+- (void)dropText:(NSString*)text inView:(NSView*)view at:(NSPoint)point {
+  // TODO(viettrungluu): This code is more or less copied from the code in
+  // |TabStripController|. I'll refactor this soon to make it common and expand
+  // its capabilities (e.g., allow text DnD).
+
+  // If the input is plain text, classify the input and make the URL.
+  AutocompleteMatch match;
+  browser_->profile()->GetAutocompleteClassifier()->Classify(
+      base::SysNSStringToUTF16(text), string16(), false, &match, NULL);
+  GURL url(match.destination_url);
+
+  browser_->GetSelectedTabContents()->OpenURL(url, GURL(), CURRENT_TAB,
+                                              PageTransition::TYPED);
+}
+
+// (URLDropTargetController protocol)
+- (void)indicateDropURLsInView:(NSView*)view at:(NSPoint)point {
+  // Do nothing.
+}
+
+// (URLDropTargetController protocol)
+- (void)hideDropURLsIndicatorInView:(NSView*)view {
+  // Do nothing.
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
new file mode 100644
index 0000000..1b778d9
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -0,0 +1,237 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/scoped_nsobject.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+// An NSView that fakes out hitTest:.
+@interface HitView : NSView {
+  id hitTestReturn_;
+}
+@end
+
+@implementation HitView
+
+- (void)setHitTestReturn:(id)rtn {
+  hitTestReturn_ = rtn;
+}
+
+- (NSView *)hitTest:(NSPoint)aPoint {
+  return hitTestReturn_;
+}
+
+@end
+
+
+namespace {
+
+class ToolbarControllerTest : public CocoaTest {
+ public:
+
+  // Indexes that match the ordering returned by the private ToolbarController
+  // |-toolbarViews| method.
+  enum {
+    kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex,
+    kWrenchIndex, kLocationIndex, kBrowserActionContainerViewIndex
+  };
+
+  ToolbarControllerTest() {
+    Browser* browser = helper_.browser();
+    CommandUpdater* updater = browser->command_updater();
+    // The default state for the commands is true, set a couple to false to
+    // ensure they get picked up correct on initialization
+    updater->UpdateCommandEnabled(IDC_BACK, false);
+    updater->UpdateCommandEnabled(IDC_FORWARD, false);
+    resizeDelegate_.reset([[ViewResizerPong alloc] init]);
+    bar_.reset(
+        [[ToolbarController alloc] initWithModel:browser->toolbar_model()
+                                        commands:browser->command_updater()
+                                         profile:helper_.profile()
+                                         browser:browser
+                                  resizeDelegate:resizeDelegate_.get()]);
+    EXPECT_TRUE([bar_ view]);
+    NSView* parent = [test_window() contentView];
+    [parent addSubview:[bar_ view]];
+  }
+
+  // Make sure the enabled state of the view is the same as the corresponding
+  // command in the updater. The views are in the declaration order of outlets.
+  void CompareState(CommandUpdater* updater, NSArray* views) {
+    EXPECT_EQ(updater->IsCommandEnabled(IDC_BACK),
+              [[views objectAtIndex:kBackIndex] isEnabled] ? true : false);
+    EXPECT_EQ(updater->IsCommandEnabled(IDC_FORWARD),
+              [[views objectAtIndex:kForwardIndex] isEnabled] ? true : false);
+    EXPECT_EQ(updater->IsCommandEnabled(IDC_RELOAD),
+              [[views objectAtIndex:kReloadIndex] isEnabled] ? true : false);
+    EXPECT_EQ(updater->IsCommandEnabled(IDC_HOME),
+              [[views objectAtIndex:kHomeIndex] isEnabled] ? true : false);
+  }
+
+  BrowserTestHelper helper_;
+  scoped_nsobject<ViewResizerPong> resizeDelegate_;
+  scoped_nsobject<ToolbarController> bar_;
+};
+
+TEST_VIEW(ToolbarControllerTest, [bar_ view])
+
+// Test the initial state that everything is sync'd up
+TEST_F(ToolbarControllerTest, InitialState) {
+  CommandUpdater* updater = helper_.browser()->command_updater();
+  CompareState(updater, [bar_ toolbarViews]);
+}
+
+// Make sure a "titlebar only" toolbar with location bar works.
+TEST_F(ToolbarControllerTest, TitlebarOnly) {
+  NSView* view = [bar_ view];
+
+  [bar_ setHasToolbar:NO hasLocationBar:YES];
+  EXPECT_NE(view, [bar_ view]);
+
+  // Simulate a popup going fullscreen and back by performing the reparenting
+  // that happens during fullscreen transitions
+  NSView* superview = [view superview];
+  [view removeFromSuperview];
+  [superview addSubview:view];
+
+  [bar_ setHasToolbar:YES hasLocationBar:YES];
+  EXPECT_EQ(view, [bar_ view]);
+
+  // Leave it off to make sure that's fine
+  [bar_ setHasToolbar:NO hasLocationBar:YES];
+}
+
+// Make sure it works in the completely undecorated case.
+TEST_F(ToolbarControllerTest, NoLocationBar) {
+  NSView* view = [bar_ view];
+
+  [bar_ setHasToolbar:NO hasLocationBar:NO];
+  EXPECT_NE(view, [bar_ view]);
+  EXPECT_TRUE([[bar_ view] isHidden]);
+
+  // Simulate a popup going fullscreen and back by performing the reparenting
+  // that happens during fullscreen transitions
+  NSView* superview = [view superview];
+  [view removeFromSuperview];
+  [superview addSubview:view];
+}
+
+// Make some changes to the enabled state of a few of the buttons and ensure
+// that we're still in sync.
+TEST_F(ToolbarControllerTest, UpdateEnabledState) {
+  CommandUpdater* updater = helper_.browser()->command_updater();
+  EXPECT_FALSE(updater->IsCommandEnabled(IDC_BACK));
+  EXPECT_FALSE(updater->IsCommandEnabled(IDC_FORWARD));
+  updater->UpdateCommandEnabled(IDC_BACK, true);
+  updater->UpdateCommandEnabled(IDC_FORWARD, true);
+  CompareState(updater, [bar_ toolbarViews]);
+}
+
+// Focus the location bar and make sure that it's the first responder.
+TEST_F(ToolbarControllerTest, FocusLocation) {
+  NSWindow* window = test_window();
+  [window makeFirstResponder:[window contentView]];
+  EXPECT_EQ([window firstResponder], [window contentView]);
+  [bar_ focusLocationBar:YES];
+  EXPECT_NE([window firstResponder], [window contentView]);
+  NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
+  EXPECT_EQ([window firstResponder], [(id)locationBar currentEditor]);
+}
+
+TEST_F(ToolbarControllerTest, LoadingState) {
+  // In its initial state, the reload button has a tag of
+  // IDC_RELOAD. When loading, it should be IDC_STOP.
+  NSButton* reload = [[bar_ toolbarViews] objectAtIndex:kReloadIndex];
+  EXPECT_EQ([reload tag], IDC_RELOAD);
+  [bar_ setIsLoading:YES force:YES];
+  EXPECT_EQ([reload tag], IDC_STOP);
+  [bar_ setIsLoading:NO force:YES];
+  EXPECT_EQ([reload tag], IDC_RELOAD);
+}
+
+// Check that toggling the state of the home button changes the visible
+// state of the home button and moves the other items accordingly.
+TEST_F(ToolbarControllerTest, ToggleHome) {
+  PrefService* prefs = helper_.profile()->GetPrefs();
+  bool showHome = prefs->GetBoolean(prefs::kShowHomeButton);
+  NSView* homeButton = [[bar_ toolbarViews] objectAtIndex:kHomeIndex];
+  EXPECT_EQ(showHome, ![homeButton isHidden]);
+
+  NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
+  NSRect originalLocationBarFrame = [locationBar frame];
+
+  // Toggle the pref and make sure the button changed state and the other
+  // views moved.
+  prefs->SetBoolean(prefs::kShowHomeButton, !showHome);
+  EXPECT_EQ(showHome, [homeButton isHidden]);
+  EXPECT_NE(NSMinX(originalLocationBarFrame), NSMinX([locationBar frame]));
+  EXPECT_NE(NSWidth(originalLocationBarFrame), NSWidth([locationBar frame]));
+}
+
+// Ensure that we don't toggle the buttons when we have a strip marked as not
+// having the full toolbar. Also ensure that the location bar doesn't change
+// size.
+TEST_F(ToolbarControllerTest, DontToggleWhenNoToolbar) {
+  [bar_ setHasToolbar:NO hasLocationBar:YES];
+  NSView* homeButton = [[bar_ toolbarViews] objectAtIndex:kHomeIndex];
+  NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
+  NSRect locationBarFrame = [locationBar frame];
+  EXPECT_EQ([homeButton isHidden], YES);
+  [bar_ showOptionalHomeButton];
+  EXPECT_EQ([homeButton isHidden], YES);
+  NSRect newLocationBarFrame = [locationBar frame];
+  EXPECT_TRUE(NSEqualRects(locationBarFrame, newLocationBarFrame));
+  newLocationBarFrame = [locationBar frame];
+  EXPECT_TRUE(NSEqualRects(locationBarFrame, newLocationBarFrame));
+}
+
+TEST_F(ToolbarControllerTest, BookmarkBubblePoint) {
+  const NSPoint starPoint = [bar_ bookmarkBubblePoint];
+  const NSRect barFrame =
+      [[bar_ view] convertRect:[[bar_ view] bounds] toView:nil];
+
+  // Make sure the star is completely inside the location bar.
+  EXPECT_TRUE(NSPointInRect(starPoint, barFrame));
+}
+
+TEST_F(ToolbarControllerTest, HoverButtonForEvent) {
+  scoped_nsobject<HitView> view([[HitView alloc]
+                                  initWithFrame:NSMakeRect(0,0,100,100)]);
+  [bar_ setView:view];
+  NSEvent* event = [NSEvent mouseEventWithType:NSMouseMoved
+                                      location:NSMakePoint(10,10)
+                                 modifierFlags:0
+                                     timestamp:0
+                                  windowNumber:0
+                                       context:nil
+                                   eventNumber:0
+                                    clickCount:0
+                                      pressure:0.0];
+
+  // NOT a match.
+  [view setHitTestReturn:bar_.get()];
+  EXPECT_FALSE([bar_ hoverButtonForEvent:event]);
+
+  // Not yet...
+  scoped_nsobject<NSButton> button([[NSButton alloc] init]);
+  [view setHitTestReturn:button];
+  EXPECT_FALSE([bar_ hoverButtonForEvent:event]);
+
+  // Now!
+  scoped_nsobject<GradientButtonCell> cell([[GradientButtonCell alloc] init]);
+  [button setCell:cell.get()];
+  EXPECT_TRUE([bar_ hoverButtonForEvent:nil]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_view.h b/chrome/browser/ui/cocoa/toolbar/toolbar_view.h
new file mode 100644
index 0000000..c5b6f6c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_view.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+#import "chrome/browser/ui/cocoa/background_gradient_view.h"
+
+// A view that handles any special rendering of the toolbar bar.  At
+// this time it only draws a gradient.  Future changes (e.g. themes)
+// may require new functionality here.
+
+@interface ToolbarView : BackgroundGradientView {
+ @private
+  // The opacity of the divider line (at the bottom of the toolbar); used when
+  // the detached bookmark bar is morphing to the normal bar and vice versa.
+  CGFloat dividerOpacity_;
+}
+
+@property(assign, nonatomic) CGFloat dividerOpacity;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_view.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_view.mm
new file mode 100644
index 0000000..9f1b879
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_view.mm
@@ -0,0 +1,47 @@
+  // Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_view.h"
+
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+
+@implementation ToolbarView
+
+@synthesize dividerOpacity = dividerOpacity_;
+
+// Prevent mouse down events from moving the parent window around.
+- (BOOL)mouseDownCanMoveWindow {
+  return NO;
+}
+
+- (void)drawRect:(NSRect)rect {
+  // The toolbar's background pattern is phased relative to the
+  // tab strip view's background pattern.
+  NSPoint phase = [[self window] themePatternPhase];
+  [[NSGraphicsContext currentContext] setPatternPhase:phase];
+  [self drawBackground];
+}
+
+// Override of |-[BackgroundGradientView strokeColor]|; make it respect opacity.
+- (NSColor*)strokeColor {
+  return [[super strokeColor] colorWithAlphaComponent:[self dividerOpacity]];
+}
+
+- (BOOL)accessibilityIsIgnored {
+  return NO;
+}
+
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+  if ([attribute isEqual:NSAccessibilityRoleAttribute])
+    return NSAccessibilityToolbarRole;
+
+  return [super accessibilityAttributeValue:attribute];
+}
+
+- (ViewID)viewID {
+  return VIEW_ID_TOOLBAR;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm
new file mode 100644
index 0000000..34994d8
--- /dev/null
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_view_unittest.mm
@@ -0,0 +1,23 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_view.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class ToolbarViewTest : public CocoaTest {
+};
+
+// This class only needs to do one thing: prevent mouse down events from moving
+// the parent window around.
+TEST_F(ToolbarViewTest, CanDragWindow) {
+  scoped_nsobject<ToolbarView> view([[ToolbarView alloc] init]);
+  EXPECT_FALSE([view mouseDownCanMoveWindow]);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/toolbar_controller.h b/chrome/browser/ui/cocoa/toolbar_controller.h
deleted file mode 100644
index 4a815e6..0000000
--- a/chrome/browser/ui/cocoa/toolbar_controller.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TOOLBAR_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TOOLBAR_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_ptr.h"
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/command_observer_bridge.h"
-#import "chrome/browser/ui/cocoa/url_drop_target.h"
-#import "chrome/browser/ui/cocoa/view_resizer.h"
-#include "chrome/browser/prefs/pref_member.h"
-
-@class AutocompleteTextField;
-@class AutocompleteTextFieldEditor;
-@class BrowserActionsContainerView;
-@class BackForwardMenuController;
-class Browser;
-@class BrowserActionsController;
-class CommandUpdater;
-class LocationBar;
-class LocationBarViewMac;
-@class MenuButton;
-namespace ToolbarControllerInternal {
-class NotificationBridge;
-class WrenchAcceleratorDelegate;
-}  // namespace ToolbarControllerInternal
-class Profile;
-@class ReloadButton;
-class TabContents;
-class ToolbarModel;
-@class WrenchMenuController;
-class WrenchMenuModel;
-
-// A controller for the toolbar in the browser window. Manages
-// updating the state for location bar and back/fwd/reload/go buttons.
-// Manages the bookmark bar and its position in the window relative to
-// the web content view.
-
-@interface ToolbarController : NSViewController<CommandObserverProtocol,
-                                                URLDropTargetController> {
- @protected
-  // The ordering is important for unit tests. If new items are added or the
-  // ordering is changed, make sure to update |-toolbarViews| and the
-  // corresponding enum in the unit tests.
-  IBOutlet MenuButton* backButton_;
-  IBOutlet MenuButton* forwardButton_;
-  IBOutlet ReloadButton* reloadButton_;
-  IBOutlet NSButton* homeButton_;
-  IBOutlet MenuButton* wrenchButton_;
-  IBOutlet AutocompleteTextField* locationBar_;
-  IBOutlet BrowserActionsContainerView* browserActionsContainerView_;
-  IBOutlet WrenchMenuController* wrenchMenuController_;
-
- @private
-  ToolbarModel* toolbarModel_;  // weak, one per window
-  CommandUpdater* commands_;  // weak, one per window
-  Profile* profile_;  // weak, one per window
-  Browser* browser_;  // weak, one per window
-  scoped_ptr<CommandObserverBridge> commandObserver_;
-  scoped_ptr<LocationBarViewMac> locationBarView_;
-  scoped_nsobject<AutocompleteTextFieldEditor> autocompleteTextFieldEditor_;
-  id<ViewResizer> resizeDelegate_;  // weak
-  scoped_nsobject<BackForwardMenuController> backMenuController_;
-  scoped_nsobject<BackForwardMenuController> forwardMenuController_;
-  scoped_nsobject<BrowserActionsController> browserActionsController_;
-
-  // Lazily-instantiated model and delegate for the menu on the
-  // wrench button.  Once visible, it will be non-null, but will not
-  // reaped when the menu is hidden once it is initially shown.
-  scoped_ptr<ToolbarControllerInternal::WrenchAcceleratorDelegate>
-      acceleratorDelegate_;
-  scoped_ptr<WrenchMenuModel> wrenchMenuModel_;
-
-  // Used for monitoring the optional toolbar button prefs.
-  scoped_ptr<ToolbarControllerInternal::NotificationBridge> notificationBridge_;
-  BooleanPrefMember showHomeButton_;
-  BooleanPrefMember showPageOptionButtons_;
-  BOOL hasToolbar_;  // If NO, we may have only the location bar.
-  BOOL hasLocationBar_;  // If |hasToolbar_| is YES, this must also be YES.
-  BOOL locationBarAtMinSize_; // If the location bar is at the minimum size.
-
-  // We have an extra retain in the locationBar_.
-  // See comments in awakeFromNib for more info.
-  scoped_nsobject<AutocompleteTextField> locationBarRetainer_;
-
-  // Tracking area for mouse enter/exit/moved in the toolbar.
-  scoped_nsobject<NSTrackingArea> trackingArea_;
-
-  // We retain/release the hover button since interaction with the
-  // button may make it go away (e.g. delete menu option over a
-  // bookmark button).  Thus this variable is not weak.  The
-  // hoveredButton_ is required to have an NSCell that responds to
-  // setMouseInside:animate:.
-  NSButton* hoveredButton_;
-}
-
-// Initialize the toolbar and register for command updates. The profile is
-// needed for initializing the location bar. The browser is needed for
-// initializing the back/forward menus.
-- (id)initWithModel:(ToolbarModel*)model
-           commands:(CommandUpdater*)commands
-            profile:(Profile*)profile
-            browser:(Browser*)browser
-     resizeDelegate:(id<ViewResizer>)resizeDelegate;
-
-// Get the C++ bridge object representing the location bar for this tab.
-- (LocationBarViewMac*)locationBarBridge;
-
-// Called by the Window delegate so we can provide a custom field editor if
-// needed.
-// Note that this may be called for objects unrelated to the toolbar.
-// returns nil if we don't want to override the custom field editor for |obj|.
-- (id)customFieldEditorForObject:(id)obj;
-
-// Make the location bar the first responder, if possible.
-- (void)focusLocationBar:(BOOL)selectAll;
-
-// Updates the toolbar (and transitively the location bar) with the states of
-// the specified |tab|.  If |shouldRestore| is true, we're switching
-// (back?) to this tab and should restore any previous location bar state
-// (such as user editing) as well.
-- (void)updateToolbarWithContents:(TabContents*)tabForRestoring
-               shouldRestoreState:(BOOL)shouldRestore;
-
-// Sets whether or not the current page in the frontmost tab is bookmarked.
-- (void)setStarredState:(BOOL)isStarred;
-
-// Called to update the loading state. Handles updating the go/stop
-// button state.  |force| is set if the update is due to changing
-// tabs, as opposed to the page-load finishing.  See comment in
-// reload_button.h.
-- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force;
-
-// Allow turning off the toolbar (but we may keep the location bar without a
-// surrounding toolbar). If |toolbar| is YES, the value of |hasLocationBar| is
-// ignored. This changes the behavior of other methods, like |-view|.
-- (void)setHasToolbar:(BOOL)toolbar hasLocationBar:(BOOL)locBar;
-
-// Point on the star icon for the bookmark bubble to be - in the
-// associated window's coordinate system.
-- (NSPoint)bookmarkBubblePoint;
-
-// Returns the desired toolbar height for the given compression factor.
-- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight;
-
-// Set the opacity of the divider (the line at the bottom) *if* we have a
-// |ToolbarView| (0 means don't show it); no-op otherwise.
-- (void)setDividerOpacity:(CGFloat)opacity;
-
-// Create and add the Browser Action buttons to the toolbar view.
-- (void)createBrowserActionButtons;
-
-// Return the BrowserActionsController for this toolbar.
-- (BrowserActionsController*)browserActionsController;
-
-@end
-
-// A set of private methods used by subclasses. Do not call these directly
-// unless a subclass of ToolbarController.
-@interface ToolbarController(ProtectedMethods)
-// Designated initializer which takes a nib name in order to allow subclasses
-// to load a different nib file.
-- (id)initWithModel:(ToolbarModel*)model
-           commands:(CommandUpdater*)commands
-            profile:(Profile*)profile
-            browser:(Browser*)browser
-     resizeDelegate:(id<ViewResizer>)resizeDelegate
-       nibFileNamed:(NSString*)nibName;
-@end
-
-// A set of private methods used by tests, in the absence of "friends" in ObjC.
-@interface ToolbarController(PrivateTestMethods)
-// Returns an array of views in the order of the outlets above.
-- (NSArray*)toolbarViews;
-- (void)showOptionalHomeButton;
-- (void)installWrenchMenu;
-- (WrenchMenuController*)wrenchMenuController;
-// Return a hover button for the current event.
-- (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TOOLBAR_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar_controller.mm
deleted file mode 100644
index 3147738..0000000
--- a/chrome/browser/ui/cocoa/toolbar_controller.mm
+++ /dev/null
@@ -1,808 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
-
-#include <algorithm>
-
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
-#include "app/mac/nsimage_cache.h"
-#include "app/menus/accelerator_cocoa.h"
-#include "app/menus/menu_model.h"
-#include "app/resource_bundle.h"
-#include "base/mac/mac_util.h"
-#include "base/singleton.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/autocomplete/autocomplete.h"
-#include "chrome/browser/autocomplete/autocomplete_classifier.h"
-#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
-#include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/background_page_tracker.h"
-#include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/upgrade_detector.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#import "chrome/browser/ui/cocoa/accelerators_cocoa.h"
-#import "chrome/browser/ui/cocoa/back_forward_menu_controller.h"
-#import "chrome/browser/ui/cocoa/background_gradient_view.h"
-#import "chrome/browser/ui/cocoa/encoding_menu_controller_delegate_mac.h"
-#import "chrome/browser/ui/cocoa/extensions/browser_action_button.h"
-#import "chrome/browser/ui/cocoa/extensions/browser_actions_container_view.h"
-#import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
-#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
-#import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
-#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#import "chrome/browser/ui/cocoa/menu_button.h"
-#import "chrome/browser/ui/cocoa/menu_controller.h"
-#import "chrome/browser/ui/cocoa/reload_button.h"
-#import "chrome/browser/ui/cocoa/toolbar_view.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-#import "chrome/browser/ui/cocoa/wrench_menu_controller.h"
-#include "chrome/browser/ui/toolbar/toolbar_model.h"
-#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/rect.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-namespace {
-
-// Names of images in the bundle for buttons.
-NSString* const kBackButtonImageName = @"back_Template.pdf";
-NSString* const kForwardButtonImageName = @"forward_Template.pdf";
-NSString* const kReloadButtonReloadImageName = @"reload_Template.pdf";
-NSString* const kReloadButtonStopImageName = @"stop_Template.pdf";
-NSString* const kHomeButtonImageName = @"home_Template.pdf";
-NSString* const kWrenchButtonImageName = @"tools_Template.pdf";
-
-// Height of the toolbar in pixels when the bookmark bar is closed.
-const CGFloat kBaseToolbarHeight = 35.0;
-
-// The minimum width of the location bar in pixels.
-const CGFloat kMinimumLocationBarWidth = 100.0;
-
-// The duration of any animation that occurs within the toolbar in seconds.
-const CGFloat kAnimationDuration = 0.2;
-
-// The amount of left padding that the wrench menu should have.
-const CGFloat kWrenchMenuLeftPadding = 3.0;
-
-}  // namespace
-
-@interface ToolbarController(Private)
-- (void)addAccessibilityDescriptions;
-- (void)initCommandStatus:(CommandUpdater*)commands;
-- (void)prefChanged:(std::string*)prefName;
-- (BackgroundGradientView*)backgroundGradientView;
-- (void)toolbarFrameChanged;
-- (void)pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:(BOOL)animate;
-- (void)maintainMinimumLocationBarWidth;
-- (void)adjustBrowserActionsContainerForNewWindow:(NSNotification*)notification;
-- (void)browserActionsContainerDragged:(NSNotification*)notification;
-- (void)browserActionsContainerDragFinished:(NSNotification*)notification;
-- (void)browserActionsVisibilityChanged:(NSNotification*)notification;
-- (void)adjustLocationSizeBy:(CGFloat)dX animate:(BOOL)animate;
-- (void)badgeWrenchMenuIfNeeded;
-@end
-
-namespace ToolbarControllerInternal {
-
-// A C++ delegate that handles the accelerators in the wrench menu.
-class WrenchAcceleratorDelegate : public menus::AcceleratorProvider {
- public:
-  virtual bool GetAcceleratorForCommandId(int command_id,
-      menus::Accelerator* accelerator_generic) {
-    // Downcast so that when the copy constructor is invoked below, the key
-    // string gets copied, too.
-    menus::AcceleratorCocoa* out_accelerator =
-        static_cast<menus::AcceleratorCocoa*>(accelerator_generic);
-    AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance();
-    const menus::AcceleratorCocoa* accelerator =
-        keymap->GetAcceleratorForCommand(command_id);
-    if (accelerator) {
-      *out_accelerator = *accelerator;
-      return true;
-    }
-    return false;
-  }
-};
-
-// A class registered for C++ notifications. This is used to detect changes in
-// preferences and upgrade available notifications. Bridges the notification
-// back to the ToolbarController.
-class NotificationBridge : public NotificationObserver {
- public:
-  explicit NotificationBridge(ToolbarController* controller)
-      : controller_(controller) {
-    registrar_.Add(this, NotificationType::UPGRADE_RECOMMENDED,
-                   NotificationService::AllSources());
-    registrar_.Add(this,
-                   NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED,
-                   NotificationService::AllSources());
-  }
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) {
-    switch (type.value) {
-      case NotificationType::PREF_CHANGED:
-        [controller_ prefChanged:Details<std::string>(details).ptr()];
-        break;
-      case NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED:
-        // fall-through
-      case NotificationType::UPGRADE_RECOMMENDED:
-        [controller_ badgeWrenchMenuIfNeeded];
-        break;
-      default:
-        NOTREACHED();
-    }
-  }
-
- private:
-  ToolbarController* controller_;  // weak, owns us
-
-  NotificationRegistrar registrar_;
-};
-
-}  // namespace ToolbarControllerInternal
-
-@implementation ToolbarController
-
-- (id)initWithModel:(ToolbarModel*)model
-           commands:(CommandUpdater*)commands
-            profile:(Profile*)profile
-            browser:(Browser*)browser
-     resizeDelegate:(id<ViewResizer>)resizeDelegate
-       nibFileNamed:(NSString*)nibName {
-  DCHECK(model && commands && profile && [nibName length]);
-  if ((self = [super initWithNibName:nibName
-                              bundle:base::mac::MainAppBundle()])) {
-    toolbarModel_ = model;
-    commands_ = commands;
-    profile_ = profile;
-    browser_ = browser;
-    resizeDelegate_ = resizeDelegate;
-    hasToolbar_ = YES;
-    hasLocationBar_ = YES;
-
-    // Register for notifications about state changes for the toolbar buttons
-    commandObserver_.reset(new CommandObserverBridge(self, commands));
-    commandObserver_->ObserveCommand(IDC_BACK);
-    commandObserver_->ObserveCommand(IDC_FORWARD);
-    commandObserver_->ObserveCommand(IDC_RELOAD);
-    commandObserver_->ObserveCommand(IDC_HOME);
-    commandObserver_->ObserveCommand(IDC_BOOKMARK_PAGE);
-  }
-  return self;
-}
-
-- (id)initWithModel:(ToolbarModel*)model
-           commands:(CommandUpdater*)commands
-            profile:(Profile*)profile
-            browser:(Browser*)browser
-     resizeDelegate:(id<ViewResizer>)resizeDelegate {
-  if ((self = [self initWithModel:model
-                         commands:commands
-                          profile:profile
-                          browser:browser
-                   resizeDelegate:resizeDelegate
-                     nibFileNamed:@"Toolbar"])) {
-  }
-  return self;
-}
-
-
-- (void)dealloc {
-  // Unset ViewIDs of toolbar elements.
-  // ViewIDs of |toolbarView|, |reloadButton_|, |locationBar_| and
-  // |browserActionsContainerView_| are handled by themselves.
-  view_id_util::UnsetID(backButton_);
-  view_id_util::UnsetID(forwardButton_);
-  view_id_util::UnsetID(homeButton_);
-  view_id_util::UnsetID(wrenchButton_);
-
-  // Make sure any code in the base class which assumes [self view] is
-  // the "parent" view continues to work.
-  hasToolbar_ = YES;
-  hasLocationBar_ = YES;
-
-  [[NSNotificationCenter defaultCenter] removeObserver:self];
-
-  if (trackingArea_.get())
-    [[self view] removeTrackingArea:trackingArea_.get()];
-  [super dealloc];
-}
-
-// Called after the view is done loading and the outlets have been hooked up.
-// Now we can hook up bridges that rely on UI objects such as the location
-// bar and button state.
-- (void)awakeFromNib {
-  // A bug in AppKit (<rdar://7298597>, <http://openradar.me/7298597>) causes
-  // images loaded directly from nibs in a framework to not get their "template"
-  // flags set properly. Thus, despite the images being set on the buttons in
-  // the xib, we must set them in code.
-  [backButton_ setImage:app::mac::GetCachedImageWithName(kBackButtonImageName)];
-  [forwardButton_ setImage:
-      app::mac::GetCachedImageWithName(kForwardButtonImageName)];
-  [reloadButton_ setImage:
-      app::mac::GetCachedImageWithName(kReloadButtonReloadImageName)];
-  [homeButton_ setImage:
-      app::mac::GetCachedImageWithName(kHomeButtonImageName)];
-  [wrenchButton_ setImage:
-      app::mac::GetCachedImageWithName(kWrenchButtonImageName)];
-  [self badgeWrenchMenuIfNeeded];
-
-  [wrenchButton_ setOpenMenuOnClick:YES];
-
-  [backButton_ setShowsBorderOnlyWhileMouseInside:YES];
-  [forwardButton_ setShowsBorderOnlyWhileMouseInside:YES];
-  [reloadButton_ setShowsBorderOnlyWhileMouseInside:YES];
-  [homeButton_ setShowsBorderOnlyWhileMouseInside:YES];
-  [wrenchButton_ setShowsBorderOnlyWhileMouseInside:YES];
-
-  [self initCommandStatus:commands_];
-  locationBarView_.reset(new LocationBarViewMac(locationBar_,
-                                                commands_, toolbarModel_,
-                                                profile_, browser_));
-  [locationBar_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
-  // Register pref observers for the optional home and page/options buttons
-  // and then add them to the toolbar based on those prefs.
-  notificationBridge_.reset(
-      new ToolbarControllerInternal::NotificationBridge(self));
-  PrefService* prefs = profile_->GetPrefs();
-  showHomeButton_.Init(prefs::kShowHomeButton, prefs,
-                       notificationBridge_.get());
-  showPageOptionButtons_.Init(prefs::kShowPageOptionsButtons, prefs,
-                              notificationBridge_.get());
-  [self showOptionalHomeButton];
-  [self installWrenchMenu];
-
-  // Create the controllers for the back/forward menus.
-  backMenuController_.reset([[BackForwardMenuController alloc]
-          initWithBrowser:browser_
-                modelType:BACK_FORWARD_MENU_TYPE_BACK
-                   button:backButton_]);
-  forwardMenuController_.reset([[BackForwardMenuController alloc]
-          initWithBrowser:browser_
-                modelType:BACK_FORWARD_MENU_TYPE_FORWARD
-                   button:forwardButton_]);
-
-  // For a popup window, the toolbar is really just a location bar
-  // (see override for [ToolbarController view], below).  When going
-  // fullscreen, we remove the toolbar controller's view from the view
-  // hierarchy.  Calling [locationBar_ removeFromSuperview] when going
-  // fullscreen causes it to get released, making us unhappy
-  // (http://crbug.com/18551).  We avoid the problem by incrementing
-  // the retain count of the location bar; use of the scoped object
-  // helps us remember to release it.
-  locationBarRetainer_.reset([locationBar_ retain]);
-  trackingArea_.reset(
-      [[NSTrackingArea alloc] initWithRect:NSZeroRect // Ignored
-                                   options:NSTrackingMouseMoved |
-                                           NSTrackingInVisibleRect |
-                                           NSTrackingMouseEnteredAndExited |
-                                           NSTrackingActiveAlways
-                                     owner:self
-                                  userInfo:nil]);
-  NSView* toolbarView = [self view];
-  [toolbarView addTrackingArea:trackingArea_.get()];
-
-  // If the user has any Browser Actions installed, the container view for them
-  // may have to be resized depending on the width of the toolbar frame.
-  [toolbarView setPostsFrameChangedNotifications:YES];
-  [[NSNotificationCenter defaultCenter]
-      addObserver:self
-         selector:@selector(toolbarFrameChanged)
-             name:NSViewFrameDidChangeNotification
-           object:toolbarView];
-
-  // Set ViewIDs for toolbar elements which don't have their dedicated class.
-  // ViewIDs of |toolbarView|, |reloadButton_|, |locationBar_| and
-  // |browserActionsContainerView_| are handled by themselves.
-  view_id_util::SetID(backButton_, VIEW_ID_BACK_BUTTON);
-  view_id_util::SetID(forwardButton_, VIEW_ID_FORWARD_BUTTON);
-  view_id_util::SetID(homeButton_, VIEW_ID_HOME_BUTTON);
-  view_id_util::SetID(wrenchButton_, VIEW_ID_APP_MENU);
-
-  [self addAccessibilityDescriptions];
-}
-
-- (void)addAccessibilityDescriptions {
-  // Set accessibility descriptions. http://openradar.appspot.com/7496255
-  NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_BACK);
-  [[backButton_ cell]
-      accessibilitySetOverrideValue:description
-                       forAttribute:NSAccessibilityDescriptionAttribute];
-  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_FORWARD);
-  [[forwardButton_ cell]
-      accessibilitySetOverrideValue:description
-                       forAttribute:NSAccessibilityDescriptionAttribute];
-  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_RELOAD);
-  [[reloadButton_ cell]
-      accessibilitySetOverrideValue:description
-                       forAttribute:NSAccessibilityDescriptionAttribute];
-  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_HOME);
-  [[homeButton_ cell]
-      accessibilitySetOverrideValue:description
-                       forAttribute:NSAccessibilityDescriptionAttribute];
-  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_LOCATION);
-  [[locationBar_ cell]
-      accessibilitySetOverrideValue:description
-                       forAttribute:NSAccessibilityDescriptionAttribute];
-  description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_APP);
-  [[wrenchButton_ cell]
-      accessibilitySetOverrideValue:description
-                       forAttribute:NSAccessibilityDescriptionAttribute];
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
-  [[hoveredButton_ cell] setMouseInside:NO animate:YES];
-  [hoveredButton_ release];
-  hoveredButton_ = nil;
-}
-
-- (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent {
-  NSButton* targetView = (NSButton*)[[self view]
-                                     hitTest:[theEvent locationInWindow]];
-
-  // Only interpret the view as a hoverButton_ if it's both button and has a
-  // button cell that cares.  GradientButtonCell derived cells care.
-  if (([targetView isKindOfClass:[NSButton class]]) &&
-      ([[targetView cell]
-         respondsToSelector:@selector(setMouseInside:animate:)]))
-    return targetView;
-  return nil;
-}
-
-- (void)mouseMoved:(NSEvent*)theEvent {
-  NSButton* targetView = [self hoverButtonForEvent:theEvent];
-  if (hoveredButton_ != targetView) {
-    [[hoveredButton_ cell] setMouseInside:NO animate:YES];
-    [[targetView cell] setMouseInside:YES animate:YES];
-    [hoveredButton_ release];
-    hoveredButton_ = [targetView retain];
-  }
-}
-
-- (void)mouseEntered:(NSEvent*)event {
-  [self mouseMoved:event];
-}
-
-- (LocationBarViewMac*)locationBarBridge {
-  return locationBarView_.get();
-}
-
-- (void)focusLocationBar:(BOOL)selectAll {
-  if (locationBarView_.get())
-    locationBarView_->FocusLocation(selectAll ? true : false);
-}
-
-// Called when the state for a command changes to |enabled|. Update the
-// corresponding UI element.
-- (void)enabledStateChangedForCommand:(NSInteger)command enabled:(BOOL)enabled {
-  NSButton* button = nil;
-  switch (command) {
-    case IDC_BACK:
-      button = backButton_;
-      break;
-    case IDC_FORWARD:
-      button = forwardButton_;
-      break;
-    case IDC_HOME:
-      button = homeButton_;
-      break;
-  }
-  [button setEnabled:enabled];
-}
-
-// Init the enabled state of the buttons on the toolbar to match the state in
-// the controller.
-- (void)initCommandStatus:(CommandUpdater*)commands {
-  [backButton_ setEnabled:commands->IsCommandEnabled(IDC_BACK) ? YES : NO];
-  [forwardButton_
-      setEnabled:commands->IsCommandEnabled(IDC_FORWARD) ? YES : NO];
-  [reloadButton_ setEnabled:YES];
-  [homeButton_ setEnabled:commands->IsCommandEnabled(IDC_HOME) ? YES : NO];
-}
-
-- (void)updateToolbarWithContents:(TabContents*)tab
-               shouldRestoreState:(BOOL)shouldRestore {
-  locationBarView_->Update(tab, shouldRestore ? true : false);
-
-  [locationBar_ updateCursorAndToolTipRects];
-
-  if (browserActionsController_.get()) {
-    [browserActionsController_ update];
-  }
-}
-
-- (void)setStarredState:(BOOL)isStarred {
-  locationBarView_->SetStarred(isStarred ? true : false);
-}
-
-- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force {
-  [reloadButton_ setIsLoading:isLoading force:force];
-}
-
-- (void)setHasToolbar:(BOOL)toolbar hasLocationBar:(BOOL)locBar {
-  [self view];  // Force nib loading.
-
-  hasToolbar_ = toolbar;
-
-  // If there's a toolbar, there must be a location bar.
-  DCHECK((toolbar && locBar) || !toolbar);
-  hasLocationBar_ = toolbar ? YES : locBar;
-
-  // Decide whether to hide/show based on whether there's a location bar.
-  [[self view] setHidden:!hasLocationBar_];
-
-  // Make location bar not editable when in a pop-up.
-  locationBarView_->SetEditable(toolbar);
-}
-
-- (NSView*)view {
-  if (hasToolbar_)
-    return [super view];
-  return locationBar_;
-}
-
-// (Private) Returns the backdrop to the toolbar.
-- (BackgroundGradientView*)backgroundGradientView {
-  // We really do mean |[super view]|; see our override of |-view|.
-  DCHECK([[super view] isKindOfClass:[BackgroundGradientView class]]);
-  return (BackgroundGradientView*)[super view];
-}
-
-- (id)customFieldEditorForObject:(id)obj {
-  if (obj == locationBar_) {
-    // Lazilly construct Field editor, Cocoa UI code always runs on the
-    // same thread, so there shoudn't be a race condition here.
-    if (autocompleteTextFieldEditor_.get() == nil) {
-      autocompleteTextFieldEditor_.reset(
-          [[AutocompleteTextFieldEditor alloc] init]);
-    }
-
-    // This needs to be called every time, otherwise notifications
-    // aren't sent correctly.
-    DCHECK(autocompleteTextFieldEditor_.get());
-    [autocompleteTextFieldEditor_.get() setFieldEditor:YES];
-    return autocompleteTextFieldEditor_.get();
-  }
-  return nil;
-}
-
-// Returns an array of views in the order of the outlets above.
-- (NSArray*)toolbarViews {
-  return [NSArray arrayWithObjects:backButton_, forwardButton_, reloadButton_,
-             homeButton_, wrenchButton_, locationBar_,
-             browserActionsContainerView_, nil];
-}
-
-// Moves |rect| to the right by |delta|, keeping the right side fixed by
-// shrinking the width to compensate. Passing a negative value for |deltaX|
-// moves to the left and increases the width.
-- (NSRect)adjustRect:(NSRect)rect byAmount:(CGFloat)deltaX {
-  NSRect frame = NSOffsetRect(rect, deltaX, 0);
-  frame.size.width -= deltaX;
-  return frame;
-}
-
-// Show or hide the home button based on the pref.
-- (void)showOptionalHomeButton {
-  // Ignore this message if only showing the URL bar.
-  if (!hasToolbar_)
-    return;
-  BOOL hide = showHomeButton_.GetValue() ? NO : YES;
-  if (hide == [homeButton_ isHidden])
-    return;  // Nothing to do, view state matches pref state.
-
-  // Always shift the text field by the width of the home button minus one pixel
-  // since the frame edges of each button are right on top of each other. When
-  // hiding the button, reverse the direction of the movement (to the left).
-  CGFloat moveX = [homeButton_ frame].size.width - 1.0;
-  if (hide)
-    moveX *= -1;  // Reverse the direction of the move.
-
-  [locationBar_ setFrame:[self adjustRect:[locationBar_ frame]
-                                 byAmount:moveX]];
-  [homeButton_ setHidden:hide];
-}
-
-// Install the menu wrench buttons. Calling this repeatedly is inexpensive so it
-// can be done every time the buttons are shown.
-- (void)installWrenchMenu {
-  if (wrenchMenuModel_.get())
-    return;
-  acceleratorDelegate_.reset(
-      new ToolbarControllerInternal::WrenchAcceleratorDelegate());
-
-  wrenchMenuModel_.reset(new WrenchMenuModel(
-      acceleratorDelegate_.get(), browser_));
-  [wrenchMenuController_ setModel:wrenchMenuModel_.get()];
-  [wrenchMenuController_ setUseWithPopUpButtonCell:YES];
-  [wrenchButton_ setAttachedMenu:[wrenchMenuController_ menu]];
-}
-
-- (WrenchMenuController*)wrenchMenuController {
-  return wrenchMenuController_;
-}
-
-- (void)badgeWrenchMenuIfNeeded {
-
-  int badgeResource = 0;
-  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
-    badgeResource = IDR_UPDATE_BADGE;
-  } else if (BackgroundPageTracker::GetInstance()->
-             GetUnacknowledgedBackgroundPageCount() > 0) {
-    badgeResource = IDR_BACKGROUND_BADGE;
-  } else {
-    // No badge - clear the badge if one is already set.
-    if ([[wrenchButton_ cell] overlayImage])
-      [[wrenchButton_ cell] setOverlayImage:nil];
-    return;
-  }
-
-  NSImage* badge =
-      ResourceBundle::GetSharedInstance().GetNativeImageNamed(badgeResource);
-  NSImage* wrenchImage =
-      app::mac::GetCachedImageWithName(kWrenchButtonImageName);
-  NSSize wrenchImageSize = [wrenchImage size];
-  NSSize badgeSize = [badge size];
-
-  scoped_nsobject<NSImage> overlayImage(
-      [[NSImage alloc] initWithSize:wrenchImageSize]);
-
-  // Draw badge in the upper right corner of the button.
-  NSPoint overlayPosition =
-      NSMakePoint(wrenchImageSize.width - badgeSize.width,
-                  wrenchImageSize.height - badgeSize.height);
-
-  [overlayImage lockFocus];
-  [badge drawAtPoint:overlayPosition
-            fromRect:NSZeroRect
-           operation:NSCompositeSourceOver
-            fraction:1.0];
-  [overlayImage unlockFocus];
-
-  [[wrenchButton_ cell] setOverlayImage:overlayImage];
-}
-
-- (void)prefChanged:(std::string*)prefName {
-  if (!prefName) return;
-  if (*prefName == prefs::kShowHomeButton) {
-    [self showOptionalHomeButton];
-  }
-}
-
-- (void)createBrowserActionButtons {
-  if (!browserActionsController_.get()) {
-    browserActionsController_.reset([[BrowserActionsController alloc]
-            initWithBrowser:browser_
-              containerView:browserActionsContainerView_]);
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(browserActionsContainerDragged:)
-               name:kBrowserActionGrippyDraggingNotification
-             object:browserActionsController_];
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(browserActionsContainerDragFinished:)
-               name:kBrowserActionGrippyDragFinishedNotification
-             object:browserActionsController_];
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(browserActionsVisibilityChanged:)
-               name:kBrowserActionVisibilityChangedNotification
-             object:browserActionsController_];
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(adjustBrowserActionsContainerForNewWindow:)
-               name:NSWindowDidBecomeKeyNotification
-             object:[[self view] window]];
-  }
-  CGFloat containerWidth = [browserActionsContainerView_ isHidden] ? 0.0 :
-      NSWidth([browserActionsContainerView_ frame]);
-  if (containerWidth > 0.0)
-    [self adjustLocationSizeBy:(containerWidth * -1) animate:NO];
-}
-
-- (void)adjustBrowserActionsContainerForNewWindow:
-    (NSNotification*)notification {
-  [self toolbarFrameChanged];
-  [[NSNotificationCenter defaultCenter]
-      removeObserver:self
-                name:NSWindowDidBecomeKeyNotification
-              object:[[self view] window]];
-}
-
-- (void)browserActionsContainerDragged:(NSNotification*)notification {
-  CGFloat locationBarWidth = NSWidth([locationBar_ frame]);
-  locationBarAtMinSize_ = locationBarWidth <= kMinimumLocationBarWidth;
-  [browserActionsContainerView_ setCanDragLeft:!locationBarAtMinSize_];
-  [browserActionsContainerView_ setGrippyPinned:locationBarAtMinSize_];
-  [self adjustLocationSizeBy:
-      [browserActionsContainerView_ resizeDeltaX] animate:NO];
-}
-
-- (void)browserActionsContainerDragFinished:(NSNotification*)notification {
-  [browserActionsController_ resizeContainerAndAnimate:YES];
-  [self pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:YES];
-}
-
-- (void)browserActionsVisibilityChanged:(NSNotification*)notification {
-  [self pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:NO];
-}
-
-- (void)pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:(BOOL)animate {
-  CGFloat locationBarXPos = NSMaxX([locationBar_ frame]);
-  CGFloat leftDistance;
-
-  if ([browserActionsContainerView_ isHidden]) {
-    CGFloat edgeXPos = [wrenchButton_ frame].origin.x;
-    leftDistance = edgeXPos - locationBarXPos - kWrenchMenuLeftPadding;
-  } else {
-    NSRect containerFrame = animate ?
-        [browserActionsContainerView_ animationEndFrame] :
-        [browserActionsContainerView_ frame];
-
-    leftDistance = containerFrame.origin.x - locationBarXPos;
-  }
-  if (leftDistance != 0.0)
-    [self adjustLocationSizeBy:leftDistance animate:animate];
-}
-
-- (void)maintainMinimumLocationBarWidth {
-  CGFloat locationBarWidth = NSWidth([locationBar_ frame]);
-  locationBarAtMinSize_ = locationBarWidth <= kMinimumLocationBarWidth;
-  if (locationBarAtMinSize_) {
-    CGFloat dX = kMinimumLocationBarWidth - locationBarWidth;
-    [self adjustLocationSizeBy:dX animate:NO];
-  }
-}
-
-- (void)toolbarFrameChanged {
-  // Do nothing if the frame changes but no Browser Action Controller is
-  // present.
-  if (!browserActionsController_.get())
-    return;
-
-  [self maintainMinimumLocationBarWidth];
-
-  if (locationBarAtMinSize_) {
-    // Once the grippy is pinned, leave it until it is explicity un-pinned.
-    [browserActionsContainerView_ setGrippyPinned:YES];
-    NSRect containerFrame = [browserActionsContainerView_ frame];
-    // Determine how much the container needs to move in case it's overlapping
-    // with the location bar.
-    CGFloat dX = NSMaxX([locationBar_ frame]) - containerFrame.origin.x;
-    containerFrame = NSOffsetRect(containerFrame, dX, 0);
-    containerFrame.size.width -= dX;
-    [browserActionsContainerView_ setFrame:containerFrame];
-  } else if (!locationBarAtMinSize_ &&
-      [browserActionsContainerView_ grippyPinned]) {
-    // Expand out the container until it hits the saved size, then unpin the
-    // grippy.
-    // Add 0.1 pixel so that it doesn't hit the minimum width codepath above.
-    CGFloat dX = NSWidth([locationBar_ frame]) -
-        (kMinimumLocationBarWidth + 0.1);
-    NSRect containerFrame = [browserActionsContainerView_ frame];
-    containerFrame = NSOffsetRect(containerFrame, -dX, 0);
-    containerFrame.size.width += dX;
-    CGFloat savedContainerWidth = [browserActionsController_ savedWidth];
-    if (NSWidth(containerFrame) >= savedContainerWidth) {
-      containerFrame = NSOffsetRect(containerFrame,
-          NSWidth(containerFrame) - savedContainerWidth, 0);
-      containerFrame.size.width = savedContainerWidth;
-      [browserActionsContainerView_ setGrippyPinned:NO];
-    }
-    [browserActionsContainerView_ setFrame:containerFrame];
-    [self pinLocationBarToLeftOfBrowserActionsContainerAndAnimate:NO];
-  }
-}
-
-- (void)adjustLocationSizeBy:(CGFloat)dX animate:(BOOL)animate {
-  // Ensure that the location bar is in its proper place.
-  NSRect locationFrame = [locationBar_ frame];
-  locationFrame.size.width += dX;
-
-  if (!animate) {
-    [locationBar_ setFrame:locationFrame];
-    return;
-  }
-
-  [NSAnimationContext beginGrouping];
-  [[NSAnimationContext currentContext] setDuration:kAnimationDuration];
-  [[locationBar_ animator] setFrame:locationFrame];
-  [NSAnimationContext endGrouping];
-}
-
-- (NSPoint)bookmarkBubblePoint {
-  return locationBarView_->GetBookmarkBubblePoint();
-}
-
-- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight {
-  // With no toolbar, just ignore the compression.
-  return hasToolbar_ ? kBaseToolbarHeight - compressByHeight :
-                       NSHeight([locationBar_ frame]);
-}
-
-- (void)setDividerOpacity:(CGFloat)opacity {
-  BackgroundGradientView* view = [self backgroundGradientView];
-  [view setShowsDivider:(opacity > 0 ? YES : NO)];
-
-  // We may not have a toolbar view (e.g., popup windows only have a location
-  // bar).
-  if ([view isKindOfClass:[ToolbarView class]]) {
-    ToolbarView* toolbarView = (ToolbarView*)view;
-    [toolbarView setDividerOpacity:opacity];
-  }
-}
-
-- (BrowserActionsController*)browserActionsController {
-  return browserActionsController_.get();
-}
-
-// (URLDropTargetController protocol)
-- (void)dropURLs:(NSArray*)urls inView:(NSView*)view at:(NSPoint)point {
-  // TODO(viettrungluu): This code is more or less copied from the code in
-  // |TabStripController|. I'll refactor this soon to make it common and expand
-  // its capabilities (e.g., allow text DnD).
-  if ([urls count] < 1) {
-    NOTREACHED();
-    return;
-  }
-
-  // TODO(viettrungluu): dropping multiple URLs?
-  if ([urls count] > 1)
-    NOTIMPLEMENTED();
-
-  // Get the first URL and fix it up.
-  GURL url(URLFixerUpper::FixupURL(
-      base::SysNSStringToUTF8([urls objectAtIndex:0]), std::string()));
-
-  browser_->GetSelectedTabContents()->OpenURL(url, GURL(), CURRENT_TAB,
-                                              PageTransition::TYPED);
-}
-
-// (URLDropTargetController protocol)
-- (void)dropText:(NSString*)text inView:(NSView*)view at:(NSPoint)point {
-  // TODO(viettrungluu): This code is more or less copied from the code in
-  // |TabStripController|. I'll refactor this soon to make it common and expand
-  // its capabilities (e.g., allow text DnD).
-
-  // If the input is plain text, classify the input and make the URL.
-  AutocompleteMatch match;
-  browser_->profile()->GetAutocompleteClassifier()->Classify(
-      base::SysNSStringToWide(text),
-      std::wstring(), false, &match, NULL);
-  GURL url(match.destination_url);
-
-  browser_->GetSelectedTabContents()->OpenURL(url, GURL(), CURRENT_TAB,
-                                              PageTransition::TYPED);
-}
-
-// (URLDropTargetController protocol)
-- (void)indicateDropURLsInView:(NSView*)view at:(NSPoint)point {
-  // Do nothing.
-}
-
-// (URLDropTargetController protocol)
-- (void)hideDropURLsIndicatorInView:(NSView*)view {
-  // Do nothing.
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar_controller_unittest.mm
deleted file mode 100644
index b57fdf8..0000000
--- a/chrome/browser/ui/cocoa/toolbar_controller_unittest.mm
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/scoped_nsobject.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/gradient_button_cell.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
-#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/common/pref_names.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-// An NSView that fakes out hitTest:.
-@interface HitView : NSView {
-  id hitTestReturn_;
-}
-@end
-
-@implementation HitView
-
-- (void)setHitTestReturn:(id)rtn {
-  hitTestReturn_ = rtn;
-}
-
-- (NSView *)hitTest:(NSPoint)aPoint {
-  return hitTestReturn_;
-}
-
-@end
-
-
-namespace {
-
-class ToolbarControllerTest : public CocoaTest {
- public:
-
-  // Indexes that match the ordering returned by the private ToolbarController
-  // |-toolbarViews| method.
-  enum {
-    kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex,
-    kWrenchIndex, kLocationIndex, kBrowserActionContainerViewIndex
-  };
-
-  ToolbarControllerTest() {
-    Browser* browser = helper_.browser();
-    CommandUpdater* updater = browser->command_updater();
-    // The default state for the commands is true, set a couple to false to
-    // ensure they get picked up correct on initialization
-    updater->UpdateCommandEnabled(IDC_BACK, false);
-    updater->UpdateCommandEnabled(IDC_FORWARD, false);
-    resizeDelegate_.reset([[ViewResizerPong alloc] init]);
-    bar_.reset(
-        [[ToolbarController alloc] initWithModel:browser->toolbar_model()
-                                        commands:browser->command_updater()
-                                         profile:helper_.profile()
-                                         browser:browser
-                                  resizeDelegate:resizeDelegate_.get()]);
-    EXPECT_TRUE([bar_ view]);
-    NSView* parent = [test_window() contentView];
-    [parent addSubview:[bar_ view]];
-  }
-
-  // Make sure the enabled state of the view is the same as the corresponding
-  // command in the updater. The views are in the declaration order of outlets.
-  void CompareState(CommandUpdater* updater, NSArray* views) {
-    EXPECT_EQ(updater->IsCommandEnabled(IDC_BACK),
-              [[views objectAtIndex:kBackIndex] isEnabled] ? true : false);
-    EXPECT_EQ(updater->IsCommandEnabled(IDC_FORWARD),
-              [[views objectAtIndex:kForwardIndex] isEnabled] ? true : false);
-    EXPECT_EQ(updater->IsCommandEnabled(IDC_RELOAD),
-              [[views objectAtIndex:kReloadIndex] isEnabled] ? true : false);
-    EXPECT_EQ(updater->IsCommandEnabled(IDC_HOME),
-              [[views objectAtIndex:kHomeIndex] isEnabled] ? true : false);
-  }
-
-  BrowserTestHelper helper_;
-  scoped_nsobject<ViewResizerPong> resizeDelegate_;
-  scoped_nsobject<ToolbarController> bar_;
-};
-
-TEST_VIEW(ToolbarControllerTest, [bar_ view])
-
-// Test the initial state that everything is sync'd up
-TEST_F(ToolbarControllerTest, InitialState) {
-  CommandUpdater* updater = helper_.browser()->command_updater();
-  CompareState(updater, [bar_ toolbarViews]);
-}
-
-// Make sure a "titlebar only" toolbar with location bar works.
-TEST_F(ToolbarControllerTest, TitlebarOnly) {
-  NSView* view = [bar_ view];
-
-  [bar_ setHasToolbar:NO hasLocationBar:YES];
-  EXPECT_NE(view, [bar_ view]);
-
-  // Simulate a popup going fullscreen and back by performing the reparenting
-  // that happens during fullscreen transitions
-  NSView* superview = [view superview];
-  [view removeFromSuperview];
-  [superview addSubview:view];
-
-  [bar_ setHasToolbar:YES hasLocationBar:YES];
-  EXPECT_EQ(view, [bar_ view]);
-
-  // Leave it off to make sure that's fine
-  [bar_ setHasToolbar:NO hasLocationBar:YES];
-}
-
-// Make sure it works in the completely undecorated case.
-TEST_F(ToolbarControllerTest, NoLocationBar) {
-  NSView* view = [bar_ view];
-
-  [bar_ setHasToolbar:NO hasLocationBar:NO];
-  EXPECT_NE(view, [bar_ view]);
-  EXPECT_TRUE([[bar_ view] isHidden]);
-
-  // Simulate a popup going fullscreen and back by performing the reparenting
-  // that happens during fullscreen transitions
-  NSView* superview = [view superview];
-  [view removeFromSuperview];
-  [superview addSubview:view];
-}
-
-// Make some changes to the enabled state of a few of the buttons and ensure
-// that we're still in sync.
-TEST_F(ToolbarControllerTest, UpdateEnabledState) {
-  CommandUpdater* updater = helper_.browser()->command_updater();
-  EXPECT_FALSE(updater->IsCommandEnabled(IDC_BACK));
-  EXPECT_FALSE(updater->IsCommandEnabled(IDC_FORWARD));
-  updater->UpdateCommandEnabled(IDC_BACK, true);
-  updater->UpdateCommandEnabled(IDC_FORWARD, true);
-  CompareState(updater, [bar_ toolbarViews]);
-}
-
-// Focus the location bar and make sure that it's the first responder.
-TEST_F(ToolbarControllerTest, FocusLocation) {
-  NSWindow* window = test_window();
-  [window makeFirstResponder:[window contentView]];
-  EXPECT_EQ([window firstResponder], [window contentView]);
-  [bar_ focusLocationBar:YES];
-  EXPECT_NE([window firstResponder], [window contentView]);
-  NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
-  EXPECT_EQ([window firstResponder], [(id)locationBar currentEditor]);
-}
-
-TEST_F(ToolbarControllerTest, LoadingState) {
-  // In its initial state, the reload button has a tag of
-  // IDC_RELOAD. When loading, it should be IDC_STOP.
-  NSButton* reload = [[bar_ toolbarViews] objectAtIndex:kReloadIndex];
-  EXPECT_EQ([reload tag], IDC_RELOAD);
-  [bar_ setIsLoading:YES force:YES];
-  EXPECT_EQ([reload tag], IDC_STOP);
-  [bar_ setIsLoading:NO force:YES];
-  EXPECT_EQ([reload tag], IDC_RELOAD);
-}
-
-// Check that toggling the state of the home button changes the visible
-// state of the home button and moves the other items accordingly.
-TEST_F(ToolbarControllerTest, ToggleHome) {
-  PrefService* prefs = helper_.profile()->GetPrefs();
-  bool showHome = prefs->GetBoolean(prefs::kShowHomeButton);
-  NSView* homeButton = [[bar_ toolbarViews] objectAtIndex:kHomeIndex];
-  EXPECT_EQ(showHome, ![homeButton isHidden]);
-
-  NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
-  NSRect originalLocationBarFrame = [locationBar frame];
-
-  // Toggle the pref and make sure the button changed state and the other
-  // views moved.
-  prefs->SetBoolean(prefs::kShowHomeButton, !showHome);
-  EXPECT_EQ(showHome, [homeButton isHidden]);
-  EXPECT_NE(NSMinX(originalLocationBarFrame), NSMinX([locationBar frame]));
-  EXPECT_NE(NSWidth(originalLocationBarFrame), NSWidth([locationBar frame]));
-}
-
-// Ensure that we don't toggle the buttons when we have a strip marked as not
-// having the full toolbar. Also ensure that the location bar doesn't change
-// size.
-TEST_F(ToolbarControllerTest, DontToggleWhenNoToolbar) {
-  [bar_ setHasToolbar:NO hasLocationBar:YES];
-  NSView* homeButton = [[bar_ toolbarViews] objectAtIndex:kHomeIndex];
-  NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
-  NSRect locationBarFrame = [locationBar frame];
-  EXPECT_EQ([homeButton isHidden], YES);
-  [bar_ showOptionalHomeButton];
-  EXPECT_EQ([homeButton isHidden], YES);
-  NSRect newLocationBarFrame = [locationBar frame];
-  EXPECT_TRUE(NSEqualRects(locationBarFrame, newLocationBarFrame));
-  newLocationBarFrame = [locationBar frame];
-  EXPECT_TRUE(NSEqualRects(locationBarFrame, newLocationBarFrame));
-}
-
-TEST_F(ToolbarControllerTest, BookmarkBubblePoint) {
-  const NSPoint starPoint = [bar_ bookmarkBubblePoint];
-  const NSRect barFrame =
-      [[bar_ view] convertRect:[[bar_ view] bounds] toView:nil];
-
-  // Make sure the star is completely inside the location bar.
-  EXPECT_TRUE(NSPointInRect(starPoint, barFrame));
-}
-
-TEST_F(ToolbarControllerTest, HoverButtonForEvent) {
-  scoped_nsobject<HitView> view([[HitView alloc]
-                                  initWithFrame:NSMakeRect(0,0,100,100)]);
-  [bar_ setView:view];
-  NSEvent* event = [NSEvent mouseEventWithType:NSMouseMoved
-                                      location:NSMakePoint(10,10)
-                                 modifierFlags:0
-                                     timestamp:0
-                                  windowNumber:0
-                                       context:nil
-                                   eventNumber:0
-                                    clickCount:0
-                                      pressure:0.0];
-
-  // NOT a match.
-  [view setHitTestReturn:bar_.get()];
-  EXPECT_FALSE([bar_ hoverButtonForEvent:event]);
-
-  // Not yet...
-  scoped_nsobject<NSButton> button([[NSButton alloc] init]);
-  [view setHitTestReturn:button];
-  EXPECT_FALSE([bar_ hoverButtonForEvent:event]);
-
-  // Now!
-  scoped_nsobject<GradientButtonCell> cell([[GradientButtonCell alloc] init]);
-  [button setCell:cell.get()];
-  EXPECT_TRUE([bar_ hoverButtonForEvent:nil]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/toolbar_view.h b/chrome/browser/ui/cocoa/toolbar_view.h
deleted file mode 100644
index 54f3135..0000000
--- a/chrome/browser/ui/cocoa/toolbar_view.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TOOLBAR_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_TOOLBAR_VIEW_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-#import "chrome/browser/ui/cocoa/background_gradient_view.h"
-
-// A view that handles any special rendering of the toolbar bar.  At
-// this time it only draws a gradient.  Future changes (e.g. themes)
-// may require new functionality here.
-
-@interface ToolbarView : BackgroundGradientView {
- @private
-  // The opacity of the divider line (at the bottom of the toolbar); used when
-  // the detached bookmark bar is morphing to the normal bar and vice versa.
-  CGFloat dividerOpacity_;
-}
-
-@property(assign, nonatomic) CGFloat dividerOpacity;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TOOLBAR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/toolbar_view.mm b/chrome/browser/ui/cocoa/toolbar_view.mm
deleted file mode 100644
index fb4bbdd..0000000
--- a/chrome/browser/ui/cocoa/toolbar_view.mm
+++ /dev/null
@@ -1,47 +0,0 @@
-  // Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/toolbar_view.h"
-
-#import "chrome/browser/ui/cocoa/themed_window.h"
-#import "chrome/browser/ui/cocoa/view_id_util.h"
-
-@implementation ToolbarView
-
-@synthesize dividerOpacity = dividerOpacity_;
-
-// Prevent mouse down events from moving the parent window around.
-- (BOOL)mouseDownCanMoveWindow {
-  return NO;
-}
-
-- (void)drawRect:(NSRect)rect {
-  // The toolbar's background pattern is phased relative to the
-  // tab strip view's background pattern.
-  NSPoint phase = [[self window] themePatternPhase];
-  [[NSGraphicsContext currentContext] setPatternPhase:phase];
-  [self drawBackground];
-}
-
-// Override of |-[BackgroundGradientView strokeColor]|; make it respect opacity.
-- (NSColor*)strokeColor {
-  return [[super strokeColor] colorWithAlphaComponent:[self dividerOpacity]];
-}
-
-- (BOOL)accessibilityIsIgnored {
-  return NO;
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attribute {
-  if ([attribute isEqual:NSAccessibilityRoleAttribute])
-    return NSAccessibilityToolbarRole;
-
-  return [super accessibilityAttributeValue:attribute];
-}
-
-- (ViewID)viewID {
-  return VIEW_ID_TOOLBAR;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/toolbar_view_unittest.mm b/chrome/browser/ui/cocoa/toolbar_view_unittest.mm
deleted file mode 100644
index 242b618..0000000
--- a/chrome/browser/ui/cocoa/toolbar_view_unittest.mm
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/toolbar_view.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class ToolbarViewTest : public CocoaTest {
-};
-
-// This class only needs to do one thing: prevent mouse down events from moving
-// the parent window around.
-TEST_F(ToolbarViewTest, CanDragWindow) {
-  scoped_nsobject<ToolbarView> view([[ToolbarView alloc] init]);
-  EXPECT_FALSE([view mouseDownCanMoveWindow]);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.mm b/chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.mm
index 0beedad..35c2bf4 100644
--- a/chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.mm
+++ b/chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.mm
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/sys_string_conversions.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using TranslateInfoBarUtilities::MoveControl;
 using TranslateInfoBarUtilities::VerifyControlOrderAndSpacing;
diff --git a/chrome/browser/ui/cocoa/translate/translate_infobar_base.h b/chrome/browser/ui/cocoa/translate/translate_infobar_base.h
index 1dff159..66612eb 100644
--- a/chrome/browser/ui/cocoa/translate/translate_infobar_base.h
+++ b/chrome/browser/ui/cocoa/translate/translate_infobar_base.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #import <Cocoa/Cocoa.h>
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
 
 #import "base/mac/cocoa_protocols.h"
 #import "base/scoped_nsobject.h"
diff --git a/chrome/browser/ui/cocoa/translate/translate_infobar_base.mm b/chrome/browser/ui/cocoa/translate/translate_infobar_base.mm
index a91cd11..5cac0a9 100644
--- a/chrome/browser/ui/cocoa/translate/translate_infobar_base.mm
+++ b/chrome/browser/ui/cocoa/translate/translate_infobar_base.mm
@@ -1,25 +1,26 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #import <Cocoa/Cocoa.h>
 #import "chrome/browser/ui/cocoa/translate/translate_infobar_base.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/sys_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/translate/translate_infobar_delegate.h"
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
-#include "chrome/browser/ui/cocoa/infobar.h"
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
-#import "chrome/browser/ui/cocoa/infobar_gradient_view.h"
+#include "chrome/browser/ui/cocoa/infobars/infobar.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
 #include "chrome/browser/ui/cocoa/translate/after_translate_infobar_controller.h"
 #import "chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.h"
 #include "chrome/browser/ui/cocoa/translate/translate_message_infobar_controller.h"
 #include "grit/generated_resources.h"
 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using TranslateInfoBarUtilities::MoveControl;
 using TranslateInfoBarUtilities::VerticallyCenterView;
@@ -61,11 +62,17 @@
 }
 
 // Vertically center |toMove| in its container.
-void VerticallyCenterView(NSView *toMove) {
+void VerticallyCenterView(NSView* toMove) {
   NSRect superViewFrame = [[toMove superview] frame];
   NSRect viewFrame = [toMove frame];
+  // If the superview is the infobar view, then subtract out the anti-spoof
+  // height so that the content is centered in the content area of the infobar,
+  // rather than in the total height (which includes the bulge).
+  CGFloat superHeight = NSHeight(superViewFrame);
+  if ([[toMove superview] isKindOfClass:[InfoBarGradientView class]])
+    superHeight -= infobars::kAntiSpoofHeight;
   viewFrame.origin.y =
-      floor((NSHeight(superViewFrame) - NSHeight(viewFrame))/2.0);
+      floor((superHeight - NSHeight(viewFrame)) / 2.0);
   [toMove setFrame:viewFrame];
 }
 
@@ -209,20 +216,22 @@
 }
 
 - (void)sourceLanguageModified:(NSInteger)newLanguageIdx {
-  DCHECK_GT(newLanguageIdx, -1);
-  if (newLanguageIdx == [self delegate]->original_language_index())
+  size_t newLanguageIdxSizeT = static_cast<size_t>(newLanguageIdx);
+  DCHECK_NE(TranslateInfoBarDelegate::kNoIndex, newLanguageIdxSizeT);
+  if (newLanguageIdxSizeT == [self delegate]->original_language_index())
     return;
-  [self delegate]->SetOriginalLanguage(newLanguageIdx);
+  [self delegate]->SetOriginalLanguage(newLanguageIdxSizeT);
   int commandId = IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE + newLanguageIdx;
   int newMenuIdx = [fromLanguagePopUp_ indexOfItemWithTag:commandId];
   [fromLanguagePopUp_ selectItemAtIndex:newMenuIdx];
 }
 
 - (void)targetLanguageModified:(NSInteger)newLanguageIdx {
-  DCHECK_GT(newLanguageIdx, -1);
-  if (newLanguageIdx == [self delegate]->target_language_index())
+  size_t newLanguageIdxSizeT = static_cast<size_t>(newLanguageIdx);
+  DCHECK_NE(TranslateInfoBarDelegate::kNoIndex, newLanguageIdxSizeT);
+  if (newLanguageIdxSizeT == [self delegate]->target_language_index())
     return;
-  [self delegate]->SetTargetLanguage(newLanguageIdx);
+  [self delegate]->SetTargetLanguage(newLanguageIdxSizeT);
   int commandId = IDC_TRANSLATE_TARGET_LANGUAGE_BASE + newLanguageIdx;
   int newMenuIdx = [toLanguagePopUp_ indexOfItemWithTag:commandId];
   [toLanguagePopUp_ selectItemAtIndex:newMenuIdx];
@@ -348,7 +357,8 @@
   NSMenu* originalLanguageMenu = [fromLanguagePopUp_ menu];
   [originalLanguageMenu setAutoenablesItems:NO];
   int selectedMenuIndex = 0;
-  int selectedLangIndex = [self delegate]->original_language_index();
+  int selectedLangIndex =
+      static_cast<int>([self delegate]->original_language_index());
   for (int i = 0; i < originalLanguageMenuModel_->GetItemCount(); ++i) {
     NSString* title = base::SysUTF16ToNSString(
         originalLanguageMenuModel_->GetLabelAt(i));
@@ -370,7 +380,8 @@
 
   NSMenu* targetLanguageMenu = [toLanguagePopUp_ menu];
   [targetLanguageMenu setAutoenablesItems:NO];
-  selectedLangIndex = [self delegate]->target_language_index();
+  selectedLangIndex =
+      static_cast<int>([self delegate]->target_language_index());
   for (int i = 0; i < targetLanguageMenuModel_->GetItemCount(); ++i) {
     NSString* title = base::SysUTF16ToNSString(
         targetLanguageMenuModel_->GetLabelAt(i));
@@ -473,6 +484,11 @@
   [self updateState];
 }
 
+- (void)infobarWillClose {
+  [[optionsPopUp_ menu] cancelTracking];
+  [super infobarWillClose];
+}
+
 - (void)adjustOptionsButtonSizeAndVisibilityForView:(NSView*)lastView {
   [optionsPopUp_ setHidden:NO];
   [self rebuildOptionsMenu:NO];
diff --git a/chrome/browser/ui/cocoa/translate/translate_infobar_unittest.mm b/chrome/browser/ui/cocoa/translate/translate_infobar_unittest.mm
index 9ee57a4..9cec792 100644
--- a/chrome/browser/ui/cocoa/translate/translate_infobar_unittest.mm
+++ b/chrome/browser/ui/cocoa/translate/translate_infobar_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,7 @@
 #import "chrome/browser/translate/translate_infobar_delegate.h"
 #import "chrome/browser/ui/cocoa/browser_test_helper.h"
 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/infobar.h"
+#import "chrome/browser/ui/cocoa/infobars/infobar.h"
 #import "chrome/browser/ui/cocoa/translate/translate_infobar_base.h"
 #import "chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.h"
 #import "testing/gmock/include/gmock/gmock.h"
@@ -97,7 +97,8 @@
     infobar_delegate.reset(
         new MockTranslateInfoBarDelegate(type, error, tab_contents.get()));
     [[infobar_controller view] removeFromSuperview];
-    scoped_ptr<InfoBar> infobar(infobar_delegate->CreateInfoBar());
+    scoped_ptr<InfoBar> infobar(
+        static_cast<InfoBarDelegate*>(infobar_delegate.get())->CreateInfoBar());
     infobar_controller.reset(
         reinterpret_cast<TranslateInfoBarControllerBase*>(
             infobar->controller()));
diff --git a/chrome/browser/ui/cocoa/ui_localizer.mm b/chrome/browser/ui/cocoa/ui_localizer.mm
index fc2e97e..5268319 100644
--- a/chrome/browser/ui/cocoa/ui_localizer.mm
+++ b/chrome/browser/ui/cocoa/ui_localizer.mm
@@ -7,13 +7,13 @@
 #import <Foundation/Foundation.h>
 
 #include <stdlib.h>
-#include "app/l10n_util.h"
-#include "app/l10n_util_mac.h"
 #include "base/sys_string_conversions.h"
 #include "base/logging.h"
 #include "grit/app_strings.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 struct UILocalizerResourceMap {
   const char* const name;
diff --git a/chrome/browser/ui/cocoa/view_id_util.h b/chrome/browser/ui/cocoa/view_id_util.h
index 6ea9524..a350164 100644
--- a/chrome/browser/ui/cocoa/view_id_util.h
+++ b/chrome/browser/ui/cocoa/view_id_util.h
@@ -8,8 +8,8 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "gfx/native_widget_types.h"
 #include "chrome/browser/ui/view_ids.h"
+#include "ui/gfx/native_widget_types.h"
 
 // ViewIDs are a system that indexes important views in the browser window by a
 // ViewID identifier (integer). This is a useful compatibility for finding a
diff --git a/chrome/browser/ui/cocoa/view_id_util.mm b/chrome/browser/ui/cocoa/view_id_util.mm
index ea0e859..f3396a9 100644
--- a/chrome/browser/ui/cocoa/view_id_util.mm
+++ b/chrome/browser/ui/cocoa/view_id_util.mm
@@ -12,7 +12,7 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/tab_strip_controller.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/view_resizer_pong.h b/chrome/browser/ui/cocoa/view_resizer_pong.h
index 628c0d5..7eb658c 100644
--- a/chrome/browser/ui/cocoa/view_resizer_pong.h
+++ b/chrome/browser/ui/cocoa/view_resizer_pong.h
@@ -14,7 +14,7 @@
  @private
   CGFloat height_;
 }
-@property (nonatomic) CGFloat height;
+@property(nonatomic) CGFloat height;
 
 - (void)resizeView:(NSView*)view newHeight:(CGFloat)height;
 @end
diff --git a/chrome/browser/ui/cocoa/web_contents_drag_source.h b/chrome/browser/ui/cocoa/web_contents_drag_source.h
deleted file mode 100644
index aa9dd73..0000000
--- a/chrome/browser/ui/cocoa/web_contents_drag_source.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_WEB_CONTENTS_DRAG_SOURCE_H_
-#define CHROME_BROWSER_UI_COCOA_WEB_CONTENTS_DRAG_SOURCE_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/scoped_nsobject.h"
-#include "chrome/browser/bookmarks/bookmark_node_data.h"
-
-@class TabContentsViewCocoa;
-
-// A class that handles tracking and event processing for a drag and drop
-// originating from the content area.  Subclasses should implement
-// fillClipboard and dragImage.
-@interface WebContentsDragSource : NSObject {
- @private
-  // Our tab. Weak reference (owns or co-owns us).
-  TabContentsViewCocoa* contentsView_;
-
-  // Our pasteboard.
-  scoped_nsobject<NSPasteboard> pasteboard_;
-
-  // A mask of the allowed drag operations.
-  NSDragOperation dragOperationMask_;
-}
-
-// Initialize a DragDataSource object for a drag (originating on the given
-// contentsView and with the given dropData and pboard). Fill the pasteboard
-// with data types appropriate for dropData.
-- (id)initWithContentsView:(TabContentsViewCocoa*)contentsView
-                pasteboard:(NSPasteboard*)pboard
-         dragOperationMask:(NSDragOperation)dragOperationMask;
-
-// Creates the drag image.  Implemented by the subclass.
-- (NSImage*)dragImage;
-
-// Put the data being dragged onto the pasteboard.  Implemented by the
-// subclass.
-- (void)fillPasteboard;
-
-// Returns a mask of the allowed drag operations.
-- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
-
-// Start the drag (on the originally provided contentsView); can do this right
-// after -initWithContentsView:....
-- (void)startDrag;
-
-// End the drag and clear the pasteboard; hook up to
-// -draggedImage:endedAt:operation:.
-- (void)endDragAt:(NSPoint)screenPoint
-        operation:(NSDragOperation)operation;
-
-// Drag moved; hook up to -draggedImage:movedTo:.
-- (void)moveDragTo:(NSPoint)screenPoint;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_WEB_CONTENTS_DRAG_SOURCE_H_
diff --git a/chrome/browser/ui/cocoa/web_contents_drag_source.mm b/chrome/browser/ui/cocoa/web_contents_drag_source.mm
deleted file mode 100644
index 68cfcfd..0000000
--- a/chrome/browser/ui/cocoa/web_contents_drag_source.mm
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/web_contents_drag_source.h"
-
-#include "app/mac/nsimage_cache.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view_mac.h"
-
-namespace {
-
-// Make a drag image from the drop data.
-// TODO(feldstein): Make this work
-NSImage* MakeDragImage() {
-  // TODO(feldstein): Just a stub for now. Make it do something (see, e.g.,
-  // WebKit/WebKit/mac/Misc/WebNSViewExtras.m: |-_web_DragImageForElement:...|).
-
-  // Default to returning a generic image.
-  return app::mac::GetCachedImageWithName(@"nav.pdf");
-}
-
-// Flips screen and point coordinates over the y axis to work with webkit
-// coordinate systems.
-void FlipPointCoordinates(NSPoint& screenPoint,
-                          NSPoint& localPoint,
-                          NSView* view) {
-  NSRect viewFrame = [view frame];
-  localPoint.y = NSHeight(viewFrame) - localPoint.y;
-  // Flip |screenPoint|.
-  NSRect screenFrame = [[[view window] screen] frame];
-  screenPoint.y = NSHeight(screenFrame) - screenPoint.y;
-}
-
-}  // namespace
-
-
-@implementation WebContentsDragSource
-
-- (id)initWithContentsView:(TabContentsViewCocoa*)contentsView
-                pasteboard:(NSPasteboard*)pboard
-         dragOperationMask:(NSDragOperation)dragOperationMask {
-  if ((self = [super init])) {
-    contentsView_ = contentsView;
-    DCHECK(contentsView_);
-
-    pasteboard_.reset([pboard retain]);
-    DCHECK(pasteboard_.get());
-
-    dragOperationMask_ = dragOperationMask;
-  }
-
-  return self;
-}
-
-- (NSImage*)dragImage {
-  return MakeDragImage();
-}
-
-- (void)fillPasteboard {
-  NOTIMPLEMENTED() << "Subclasses should implement fillPasteboard";
-}
-
-- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
-  return dragOperationMask_;
-}
-
-- (void)startDrag {
-  [self fillPasteboard];
-  NSEvent* currentEvent = [NSApp currentEvent];
-
-  // Synthesize an event for dragging, since we can't be sure that
-  // [NSApp currentEvent] will return a valid dragging event.
-  NSWindow* window = [contentsView_ window];
-  NSPoint position = [window mouseLocationOutsideOfEventStream];
-  NSTimeInterval eventTime = [currentEvent timestamp];
-  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
-                                          location:position
-                                     modifierFlags:NSLeftMouseDraggedMask
-                                         timestamp:eventTime
-                                      windowNumber:[window windowNumber]
-                                           context:nil
-                                       eventNumber:0
-                                        clickCount:1
-                                          pressure:1.0];
-  [window dragImage:[self dragImage]
-                 at:position
-             offset:NSZeroSize
-              event:dragEvent
-         pasteboard:pasteboard_
-             source:self
-          slideBack:YES];
-}
-
-- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint
-  operation:(NSDragOperation)operation {
-}
-
-- (void)endDragAt:(NSPoint)screenPoint
-        operation:(NSDragOperation)operation {
-  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
-  if (rvh) {
-    rvh->DragSourceSystemDragEnded();
-
-    NSPoint localPoint = [contentsView_ convertPoint:screenPoint fromView: nil];
-    FlipPointCoordinates(screenPoint, localPoint, contentsView_);
-    rvh->DragSourceEndedAt(localPoint.x, localPoint.y,
-                           screenPoint.x, screenPoint.y,
-                           static_cast<WebKit::WebDragOperation>(operation));
-  }
-
-  // Make sure the pasteboard owner isn't us.
-  [pasteboard_ declareTypes:[NSArray array] owner:nil];
-}
-
-- (void)moveDragTo:(NSPoint)screenPoint {
-  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
-  if (rvh) {
-    NSPoint localPoint = [contentsView_ convertPoint:screenPoint fromView:nil];
-    FlipPointCoordinates(screenPoint, localPoint, contentsView_);
-    rvh->DragSourceMovedTo(localPoint.x, localPoint.y,
-                           screenPoint.x, screenPoint.y);
-  }
-}
-
-@end  // @implementation WebContentsDragSource
-
diff --git a/chrome/browser/ui/cocoa/web_drag_source.mm b/chrome/browser/ui/cocoa/web_drag_source.mm
deleted file mode 100644
index 24c121a..0000000
--- a/chrome/browser/ui/cocoa/web_drag_source.mm
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/web_drag_source.h"
-
-#include "app/mac/nsimage_cache.h"
-#include "base/file_path.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "base/task.h"
-#include "base/threading/thread.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/download/download_util.h"
-#include "chrome/browser/download/drag_download_file.h"
-#include "chrome/browser/download/drag_download_util.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view_mac.h"
-#include "net/base/file_stream.h"
-#include "net/base/net_util.h"
-#import "third_party/mozilla/NSPasteboard+Utils.h"
-#include "webkit/glue/webdropdata.h"
-
-using base::SysNSStringToUTF8;
-using base::SysUTF8ToNSString;
-using base::SysUTF16ToNSString;
-using net::FileStream;
-
-
-namespace {
-
-// An unofficial standard pasteboard title type to be provided alongside the
-// |NSURLPboardType|.
-NSString* const kNSURLTitlePboardType = @"public.url-name";
-
-// Returns a filename appropriate for the drop data
-// TODO(viettrungluu): Refactor to make it common across platforms,
-// and move it somewhere sensible.
-FilePath GetFileNameFromDragData(const WebDropData& drop_data) {
-  // Images without ALT text will only have a file extension so we need to
-  // synthesize one from the provided extension and URL.
-  FilePath file_name([SysUTF16ToNSString(drop_data.file_description_filename)
-          fileSystemRepresentation]);
-  file_name = file_name.BaseName().RemoveExtension();
-
-  if (file_name.empty()) {
-    // Retrieve the name from the URL.
-    file_name = net::GetSuggestedFilename(drop_data.url, "", "", FilePath());
-  }
-
-  file_name = file_name.ReplaceExtension([SysUTF16ToNSString(
-          drop_data.file_extension) fileSystemRepresentation]);
-
-  return file_name;
-}
-
-// This class's sole task is to write out data for a promised file; the caller
-// is responsible for opening the file.
-class PromiseWriterTask : public Task {
- public:
-  // Assumes ownership of file_stream.
-  PromiseWriterTask(const WebDropData& drop_data,
-                    FileStream* file_stream);
-  virtual ~PromiseWriterTask();
-  virtual void Run();
-
- private:
-  WebDropData drop_data_;
-
-  // This class takes ownership of file_stream_ and will close and delete it.
-  scoped_ptr<FileStream> file_stream_;
-};
-
-// Takes the drop data and an open file stream (which it takes ownership of and
-// will close and delete).
-PromiseWriterTask::PromiseWriterTask(const WebDropData& drop_data,
-                                     FileStream* file_stream) :
-    drop_data_(drop_data) {
-  file_stream_.reset(file_stream);
-  DCHECK(file_stream_.get());
-}
-
-PromiseWriterTask::~PromiseWriterTask() {
-  DCHECK(file_stream_.get());
-  if (file_stream_.get())
-    file_stream_->Close();
-}
-
-void PromiseWriterTask::Run() {
-  CHECK(file_stream_.get());
-  file_stream_->Write(drop_data_.file_contents.data(),
-                      drop_data_.file_contents.length(),
-                      NULL);
-
-  // Let our destructor take care of business.
-}
-
-}  // namespace
-
-
-@interface WebDragSource(Private)
-
-- (void)fillPasteboard;
-- (NSImage*)dragImage;
-
-@end  // @interface WebDragSource(Private)
-
-
-@implementation WebDragSource
-
-- (id)initWithContentsView:(TabContentsViewCocoa*)contentsView
-                  dropData:(const WebDropData*)dropData
-                     image:(NSImage*)image
-                    offset:(NSPoint)offset
-                pasteboard:(NSPasteboard*)pboard
-         dragOperationMask:(NSDragOperation)dragOperationMask {
-  if ((self = [super init])) {
-    contentsView_ = contentsView;
-    DCHECK(contentsView_);
-
-    dropData_.reset(new WebDropData(*dropData));
-    DCHECK(dropData_.get());
-
-    dragImage_.reset([image retain]);
-    imageOffset_ = offset;
-
-    pasteboard_.reset([pboard retain]);
-    DCHECK(pasteboard_.get());
-
-    dragOperationMask_ = dragOperationMask;
-
-    [self fillPasteboard];
-  }
-
-  return self;
-}
-
-- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
-  return dragOperationMask_;
-}
-
-- (void)lazyWriteToPasteboard:(NSPasteboard*)pboard forType:(NSString*)type {
-  // NSHTMLPboardType requires the character set to be declared. Otherwise, it
-  // assumes US-ASCII. Awesome.
-  static const string16 kHtmlHeader =
-      ASCIIToUTF16("<meta http-equiv=\"Content-Type\" "
-                   "content=\"text/html;charset=UTF-8\">");
-
-  // Be extra paranoid; avoid crashing.
-  if (!dropData_.get()) {
-    NOTREACHED() << "No drag-and-drop data available for lazy write.";
-    return;
-  }
-
-  // HTML.
-  if ([type isEqualToString:NSHTMLPboardType]) {
-    DCHECK(!dropData_->text_html.empty());
-    // See comment on |kHtmlHeader| above.
-    [pboard setString:SysUTF16ToNSString(kHtmlHeader + dropData_->text_html)
-              forType:NSHTMLPboardType];
-
-  // URL.
-  } else if ([type isEqualToString:NSURLPboardType]) {
-    DCHECK(dropData_->url.is_valid());
-    NSURL* url = [NSURL URLWithString:SysUTF8ToNSString(dropData_->url.spec())];
-    [url writeToPasteboard:pboard];
-
-  // URL title.
-  } else if ([type isEqualToString:kNSURLTitlePboardType]) {
-    [pboard setString:SysUTF16ToNSString(dropData_->url_title)
-              forType:kNSURLTitlePboardType];
-
-  // File contents.
-  } else if ([type isEqualToString:NSFileContentsPboardType] ||
-      [type isEqualToString:NSCreateFileContentsPboardType(
-              SysUTF16ToNSString(dropData_->file_extension))]) {
-    // TODO(viettrungluu: find something which is known to accept
-    // NSFileContentsPboardType to check that this actually works!
-    scoped_nsobject<NSFileWrapper> file_wrapper(
-        [[NSFileWrapper alloc] initRegularFileWithContents:[NSData
-                dataWithBytes:dropData_->file_contents.data()
-                       length:dropData_->file_contents.length()]]);
-    [file_wrapper setPreferredFilename:SysUTF8ToNSString(
-            GetFileNameFromDragData(*dropData_).value())];
-    [pboard writeFileWrapper:file_wrapper];
-
-  // TIFF.
-  } else if ([type isEqualToString:NSTIFFPboardType]) {
-    // TODO(viettrungluu): This is a bit odd since we rely on Cocoa to render
-    // our image into a TIFF. This is also suboptimal since this is all done
-    // synchronously. I'm not sure there's much we can easily do about it.
-    scoped_nsobject<NSImage> image(
-        [[NSImage alloc] initWithData:[NSData
-                dataWithBytes:dropData_->file_contents.data()
-                       length:dropData_->file_contents.length()]]);
-    [pboard setData:[image TIFFRepresentation] forType:NSTIFFPboardType];
-
-  // Plain text.
-  } else if ([type isEqualToString:NSStringPboardType]) {
-    DCHECK(!dropData_->plain_text.empty());
-    [pboard setString:SysUTF16ToNSString(dropData_->plain_text)
-              forType:NSStringPboardType];
-
-  // Oops!
-  } else {
-    NOTREACHED() << "Asked for a drag pasteboard type we didn't offer.";
-  }
-}
-
-- (NSPoint)convertScreenPoint:(NSPoint)screenPoint {
-  DCHECK([contentsView_ window]);
-  NSPoint basePoint = [[contentsView_ window] convertScreenToBase:screenPoint];
-  return [contentsView_ convertPoint:basePoint fromView:nil];
-}
-
-- (void)startDrag {
-  NSEvent* currentEvent = [NSApp currentEvent];
-
-  // Synthesize an event for dragging, since we can't be sure that
-  // [NSApp currentEvent] will return a valid dragging event.
-  NSWindow* window = [contentsView_ window];
-  NSPoint position = [window mouseLocationOutsideOfEventStream];
-  NSTimeInterval eventTime = [currentEvent timestamp];
-  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
-                                          location:position
-                                     modifierFlags:NSLeftMouseDraggedMask
-                                         timestamp:eventTime
-                                      windowNumber:[window windowNumber]
-                                           context:nil
-                                       eventNumber:0
-                                        clickCount:1
-                                          pressure:1.0];
-
-  if (dragImage_) {
-    position.x -= imageOffset_.x;
-    // Deal with Cocoa's flipped coordinate system.
-    position.y -= [dragImage_.get() size].height - imageOffset_.y;
-  }
-  // Per kwebster, offset arg is ignored, see -_web_DragImageForElement: in
-  // third_party/WebKit/WebKit/mac/Misc/WebNSViewExtras.m.
-  [window dragImage:[self dragImage]
-                 at:position
-             offset:NSZeroSize
-              event:dragEvent
-         pasteboard:pasteboard_
-             source:contentsView_
-          slideBack:YES];
-}
-
-- (void)endDragAt:(NSPoint)screenPoint
-        operation:(NSDragOperation)operation {
-  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
-  if (rvh) {
-    rvh->DragSourceSystemDragEnded();
-
-    // Convert |screenPoint| to view coordinates and flip it.
-    NSPoint localPoint = [self convertScreenPoint:screenPoint];
-    NSRect viewFrame = [contentsView_ frame];
-    localPoint.y = viewFrame.size.height - localPoint.y;
-    // Flip |screenPoint|.
-    NSRect screenFrame = [[[contentsView_ window] screen] frame];
-    screenPoint.y = screenFrame.size.height - screenPoint.y;
-
-    rvh->DragSourceEndedAt(localPoint.x, localPoint.y,
-                           screenPoint.x, screenPoint.y,
-                           static_cast<WebKit::WebDragOperation>(operation));
-  }
-
-  // Make sure the pasteboard owner isn't us.
-  [pasteboard_ declareTypes:[NSArray array] owner:nil];
-}
-
-- (void)moveDragTo:(NSPoint)screenPoint {
-  RenderViewHost* rvh = [contentsView_ tabContents]->render_view_host();
-  if (rvh) {
-    // Convert |screenPoint| to view coordinates and flip it.
-    NSPoint localPoint = [self convertScreenPoint:screenPoint];
-    NSRect viewFrame = [contentsView_ frame];
-    localPoint.y = viewFrame.size.height - localPoint.y;
-    // Flip |screenPoint|.
-    NSRect screenFrame = [[[contentsView_ window] screen] frame];
-    screenPoint.y = screenFrame.size.height - screenPoint.y;
-
-    rvh->DragSourceMovedTo(localPoint.x, localPoint.y,
-                           screenPoint.x, screenPoint.y);
-  }
-}
-
-- (NSString*)dragPromisedFileTo:(NSString*)path {
-  // Be extra paranoid; avoid crashing.
-  if (!dropData_.get()) {
-    NOTREACHED() << "No drag-and-drop data available for promised file.";
-    return nil;
-  }
-
-  FilePath fileName = downloadFileName_.empty() ?
-      GetFileNameFromDragData(*dropData_) : downloadFileName_;
-  FilePath filePath(SysNSStringToUTF8(path));
-  filePath = filePath.Append(fileName);
-  FileStream* fileStream =
-      drag_download_util::CreateFileStreamForDrop(&filePath);
-  if (!fileStream)
-    return nil;
-
-  if (downloadURL_.is_valid()) {
-    TabContents* tabContents = [contentsView_ tabContents];
-    scoped_refptr<DragDownloadFile> dragFileDownloader(new DragDownloadFile(
-        filePath,
-        linked_ptr<net::FileStream>(fileStream),
-        downloadURL_,
-        tabContents->GetURL(),
-        tabContents->encoding(),
-        tabContents));
-
-    // The finalizer will take care of closing and deletion.
-    dragFileDownloader->Start(
-        new drag_download_util::PromiseFileFinalizer(dragFileDownloader));
-  } else {
-    // The writer will take care of closing and deletion.
-    g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
-        new PromiseWriterTask(*dropData_, fileStream));
-  }
-
-  // Once we've created the file, we should return the file name.
-  return SysUTF8ToNSString(filePath.BaseName().value());
-}
-
-@end  // @implementation WebDragSource
-
-
-@implementation WebDragSource (Private)
-
-- (void)fillPasteboard {
-  DCHECK(pasteboard_.get());
-
-  [pasteboard_ declareTypes:[NSArray array] owner:contentsView_];
-
-  // HTML.
-  if (!dropData_->text_html.empty())
-    [pasteboard_ addTypes:[NSArray arrayWithObject:NSHTMLPboardType]
-                    owner:contentsView_];
-
-  // URL (and title).
-  if (dropData_->url.is_valid())
-    [pasteboard_ addTypes:[NSArray arrayWithObjects:NSURLPboardType,
-                                                    kNSURLTitlePboardType, nil]
-                    owner:contentsView_];
-
-  // File.
-  if (!dropData_->file_contents.empty() ||
-      !dropData_->download_metadata.empty()) {
-    NSString* fileExtension = 0;
-
-    if (dropData_->download_metadata.empty()) {
-      // |dropData_->file_extension| comes with the '.', which we must strip.
-      fileExtension = (dropData_->file_extension.length() > 0) ?
-          SysUTF16ToNSString(dropData_->file_extension.substr(1)) : @"";
-    } else {
-      string16 mimeType;
-      FilePath fileName;
-      if (drag_download_util::ParseDownloadMetadata(
-              dropData_->download_metadata,
-              &mimeType,
-              &fileName,
-              &downloadURL_)) {
-        std::string contentDisposition =
-            "attachment; filename=" + fileName.value();
-        download_util::GenerateFileName(downloadURL_,
-                                        contentDisposition,
-                                        std::string(),
-                                        UTF16ToUTF8(mimeType),
-                                        &downloadFileName_);
-        fileExtension = SysUTF8ToNSString(downloadFileName_.Extension());
-      }
-    }
-
-    if (fileExtension) {
-      // File contents (with and without specific type), file (HFS) promise,
-      // TIFF.
-      // TODO(viettrungluu): others?
-      [pasteboard_ addTypes:[NSArray arrayWithObjects:
-                                  NSFileContentsPboardType,
-                                  NSCreateFileContentsPboardType(fileExtension),
-                                  NSFilesPromisePboardType,
-                                  NSTIFFPboardType,
-                                  nil]
-                      owner:contentsView_];
-
-      // For the file promise, we need to specify the extension.
-      [pasteboard_ setPropertyList:[NSArray arrayWithObject:fileExtension]
-                           forType:NSFilesPromisePboardType];
-    }
-  }
-
-  // Plain text.
-  if (!dropData_->plain_text.empty())
-    [pasteboard_ addTypes:[NSArray arrayWithObject:NSStringPboardType]
-                    owner:contentsView_];
-}
-
-- (NSImage*)dragImage {
-  if (dragImage_)
-    return dragImage_;
-
-  // Default to returning a generic image.
-  return app::mac::GetCachedImageWithName(@"nav.pdf");
-}
-
-@end  // @implementation WebDragSource (Private)
diff --git a/chrome/browser/ui/cocoa/web_drop_target.mm b/chrome/browser/ui/cocoa/web_drop_target.mm
deleted file mode 100644
index 08174b5..0000000
--- a/chrome/browser/ui/cocoa/web_drop_target.mm
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/web_drop_target.h"
-
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#import "third_party/mozilla/NSPasteboard+Utils.h"
-#include "webkit/glue/webdropdata.h"
-#include "webkit/glue/window_open_disposition.h"
-
-using WebKit::WebDragOperationsMask;
-
-@implementation WebDropTarget
-
-// |contents| is the TabContents representing this tab, used to communicate
-// drag&drop messages to WebCore and handle navigation on a successful drop
-// (if necessary).
-- (id)initWithTabContents:(TabContents*)contents {
-  if ((self = [super init])) {
-    tabContents_ = contents;
-  }
-  return self;
-}
-
-// Call to set whether or not we should allow the drop. Takes effect the
-// next time |-draggingUpdated:| is called.
-- (void)setCurrentOperation: (NSDragOperation)operation {
-  current_operation_ = operation;
-}
-
-// Given a point in window coordinates and a view in that window, return a
-// flipped point in the coordinate system of |view|.
-- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint
-                            view:(NSView*)view {
-  DCHECK(view);
-  NSPoint viewPoint =  [view convertPoint:windowPoint fromView:nil];
-  NSRect viewFrame = [view frame];
-  viewPoint.y = viewFrame.size.height - viewPoint.y;
-  return viewPoint;
-}
-
-// Given a point in window coordinates and a view in that window, return a
-// flipped point in screen coordinates.
-- (NSPoint)flipWindowPointToScreen:(const NSPoint&)windowPoint
-                              view:(NSView*)view {
-  DCHECK(view);
-  NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
-  NSScreen* screen = [[view window] screen];
-  NSRect screenFrame = [screen frame];
-  screenPoint.y = screenFrame.size.height - screenPoint.y;
-  return screenPoint;
-}
-
-// Return YES if the drop site only allows drops that would navigate.  If this
-// is the case, we don't want to pass messages to the renderer because there's
-// really no point (i.e., there's nothing that cares about the mouse position or
-// entering and exiting).  One example is an interstitial page (e.g., safe
-// browsing warning).
-- (BOOL)onlyAllowsNavigation {
-  return tabContents_->showing_interstitial_page();
-}
-
-// Messages to send during the tracking of a drag, ususally upon recieving
-// calls from the view system. Communicates the drag messages to WebCore.
-
-- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info
-                              view:(NSView*)view {
-  // Save off the RVH so we can tell if it changes during a drag. If it does,
-  // we need to send a new enter message in draggingUpdated:.
-  currentRVH_ = tabContents_->render_view_host();
-
-  if ([self onlyAllowsNavigation]) {
-    if ([[info draggingPasteboard] containsURLData])
-      return NSDragOperationCopy;
-    return NSDragOperationNone;
-  }
-
-  // If the tab is showing the boomark manager, send BookmarkDrag events
-  RenderViewHostDelegate::BookmarkDrag* dragDelegate =
-      tabContents_->GetBookmarkDragDelegate();
-  BookmarkNodeData dragData;
-  if(dragDelegate && dragData.ReadFromDragClipboard())
-    dragDelegate->OnDragEnter(dragData);
-
-  // Fill out a WebDropData from pasteboard.
-  WebDropData data;
-  [self populateWebDropData:&data fromPasteboard:[info draggingPasteboard]];
-
-  // Create the appropriate mouse locations for WebCore. The draggingLocation
-  // is in window coordinates. Both need to be flipped.
-  NSPoint windowPoint = [info draggingLocation];
-  NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
-  NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
-  NSDragOperation mask = [info draggingSourceOperationMask];
-  tabContents_->render_view_host()->DragTargetDragEnter(data,
-      gfx::Point(viewPoint.x, viewPoint.y),
-      gfx::Point(screenPoint.x, screenPoint.y),
-      static_cast<WebDragOperationsMask>(mask));
-
-  // We won't know the true operation (whether the drag is allowed) until we
-  // hear back from the renderer. For now, be optimistic:
-  current_operation_ = NSDragOperationCopy;
-  return current_operation_;
-}
-
-- (void)draggingExited:(id<NSDraggingInfo>)info {
-  DCHECK(currentRVH_);
-  if (currentRVH_ != tabContents_->render_view_host())
-    return;
-
-  // Nothing to do in the interstitial case.
-
-  tabContents_->render_view_host()->DragTargetDragLeave();
-}
-
-- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
-                              view:(NSView*)view {
-  DCHECK(currentRVH_);
-  if (currentRVH_ != tabContents_->render_view_host())
-    [self draggingEntered:info view:view];
-
-  if ([self onlyAllowsNavigation]) {
-    if ([[info draggingPasteboard] containsURLData])
-      return NSDragOperationCopy;
-    return NSDragOperationNone;
-  }
-
-  // Create the appropriate mouse locations for WebCore. The draggingLocation
-  // is in window coordinates.
-  NSPoint windowPoint = [info draggingLocation];
-  NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
-  NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
-  NSDragOperation mask = [info draggingSourceOperationMask];
-  tabContents_->render_view_host()->DragTargetDragOver(
-      gfx::Point(viewPoint.x, viewPoint.y),
-      gfx::Point(screenPoint.x, screenPoint.y),
-      static_cast<WebDragOperationsMask>(mask));
-
-  // If the tab is showing the boomark manager, send BookmarkDrag events
-  RenderViewHostDelegate::BookmarkDrag* dragDelegate =
-      tabContents_->GetBookmarkDragDelegate();
-  BookmarkNodeData dragData;
-  if(dragDelegate && dragData.ReadFromDragClipboard())
-    dragDelegate->OnDragOver(dragData);
-  return current_operation_;
-}
-
-- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
-                              view:(NSView*)view {
-  if (currentRVH_ != tabContents_->render_view_host())
-    [self draggingEntered:info view:view];
-
-  // Check if we only allow navigation and navigate to a url on the pasteboard.
-  if ([self onlyAllowsNavigation]) {
-    NSPasteboard* pboard = [info draggingPasteboard];
-    if ([pboard containsURLData]) {
-      GURL url;
-      [self populateURL:&url
-          andTitle:NULL
-          fromPasteboard:pboard
-          convertingFilenames:YES];
-      tabContents_->OpenURL(url, GURL(), CURRENT_TAB,
-                            PageTransition::AUTO_BOOKMARK);
-      return YES;
-    }
-    return NO;
-  }
-
-  // If the tab is showing the boomark manager, send BookmarkDrag events
-  RenderViewHostDelegate::BookmarkDrag* dragDelegate =
-      tabContents_->GetBookmarkDragDelegate();
-  BookmarkNodeData dragData;
-  if(dragDelegate && dragData.ReadFromDragClipboard())
-    dragDelegate->OnDrop(dragData);
-
-  currentRVH_ = NULL;
-
-  // Create the appropriate mouse locations for WebCore. The draggingLocation
-  // is in window coordinates. Both need to be flipped.
-  NSPoint windowPoint = [info draggingLocation];
-  NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
-  NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
-  tabContents_->render_view_host()->DragTargetDrop(
-      gfx::Point(viewPoint.x, viewPoint.y),
-      gfx::Point(screenPoint.x, screenPoint.y));
-
-  return YES;
-}
-
-// Populate the |url| and |title| with URL data in |pboard|. There may be more
-// than one, but we only handle dropping the first. |url| must not be |NULL|;
-// |title| is an optional parameter. Returns |YES| if URL data was obtained from
-// the pasteboard, |NO| otherwise. If |convertFilenames| is |YES|, the function
-// will also attempt to convert filenames in |pboard| to file URLs.
-- (BOOL)populateURL:(GURL*)url
-    andTitle:(string16*)title
-    fromPasteboard:(NSPasteboard*)pboard
-    convertingFilenames:(BOOL)convertFilenames {
-  DCHECK(url);
-  DCHECK(title);
-
-  // Bail out early if there's no URL data.
-  if (![pboard containsURLData])
-    return NO;
-
-  // |-getURLs:andTitles:convertingFilenames:| will already validate URIs so we
-  // don't need to again. The arrays returned are both of NSString's.
-  NSArray* urls = nil;
-  NSArray* titles = nil;
-  [pboard getURLs:&urls andTitles:&titles convertingFilenames:convertFilenames];
-  DCHECK_EQ([urls count], [titles count]);
-  // It's possible that no URLs were actually provided!
-  if (![urls count])
-    return NO;
-  NSString* urlString = [urls objectAtIndex:0];
-  if ([urlString length]) {
-    // Check again just to make sure to not assign NULL into a std::string,
-    // which throws an exception.
-    const char* utf8Url = [urlString UTF8String];
-    if (utf8Url) {
-      *url = GURL(utf8Url);
-      // Extra paranoia check.
-      if (title && [titles count])
-        *title = base::SysNSStringToUTF16([titles objectAtIndex:0]);
-    }
-  }
-  return YES;
-}
-
-// Given |data|, which should not be nil, fill it in using the contents of the
-// given pasteboard.
-- (void)populateWebDropData:(WebDropData*)data
-             fromPasteboard:(NSPasteboard*)pboard {
-  DCHECK(data);
-  DCHECK(pboard);
-  NSArray* types = [pboard types];
-
-  // Get URL if possible. To avoid exposing file system paths to web content,
-  // filenames in the drag are not converted to file URLs.
-  [self populateURL:&data->url
-      andTitle:&data->url_title
-      fromPasteboard:pboard
-      convertingFilenames:NO];
-
-  // Get plain text.
-  if ([types containsObject:NSStringPboardType]) {
-    data->plain_text =
-        base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]);
-  }
-
-  // Get HTML. If there's no HTML, try RTF.
-  if ([types containsObject:NSHTMLPboardType]) {
-    data->text_html =
-        base::SysNSStringToUTF16([pboard stringForType:NSHTMLPboardType]);
-  } else if ([types containsObject:NSRTFPboardType]) {
-    NSString* html = [pboard htmlFromRtf];
-    data->text_html = base::SysNSStringToUTF16(html);
-  }
-
-  // Get files.
-  if ([types containsObject:NSFilenamesPboardType]) {
-    NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
-    if ([files isKindOfClass:[NSArray class]] && [files count]) {
-      for (NSUInteger i = 0; i < [files count]; i++) {
-        NSString* filename = [files objectAtIndex:i];
-        BOOL isDir = NO;
-        BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:filename
-                                                           isDirectory:&isDir];
-        if (exists && !isDir)
-          data->filenames.push_back(base::SysNSStringToUTF16(filename));
-      }
-    }
-  }
-
-  // TODO(pinkerton): Get file contents. http://crbug.com/34661
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/web_drop_target_unittest.mm b/chrome/browser/ui/cocoa/web_drop_target_unittest.mm
deleted file mode 100644
index 0261e89..0000000
--- a/chrome/browser/ui/cocoa/web_drop_target_unittest.mm
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/sys_string_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/renderer_host/test/test_render_view_host.h"
-#include "chrome/browser/tab_contents/test_tab_contents.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/web_drop_target.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "third_party/mozilla/NSPasteboard+Utils.h"
-#include "webkit/glue/webdropdata.h"
-
-class WebDropTargetTest : public RenderViewHostTestHarness {
- public:
-  virtual void SetUp() {
-    RenderViewHostTestHarness::SetUp();
-    CocoaTest::BootstrapCocoa();
-    drop_target_.reset([[WebDropTarget alloc] initWithTabContents:contents()]);
-  }
-
-  void PutURLOnPasteboard(NSString* urlString, NSPasteboard* pboard) {
-    [pboard declareTypes:[NSArray arrayWithObject:NSURLPboardType]
-                   owner:nil];
-    NSURL* url = [NSURL URLWithString:urlString];
-    EXPECT_TRUE(url);
-    [url writeToPasteboard:pboard];
-  }
-
-  void PutCoreURLAndTitleOnPasteboard(NSString* urlString, NSString* title,
-                                      NSPasteboard* pboard) {
-    [pboard
-        declareTypes:[NSArray arrayWithObjects:kCorePasteboardFlavorType_url,
-                                               kCorePasteboardFlavorType_urln,
-                                               nil]
-               owner:nil];
-    [pboard setString:urlString
-              forType:kCorePasteboardFlavorType_url];
-    [pboard setString:title
-              forType:kCorePasteboardFlavorType_urln];
-  }
-
-  base::mac::ScopedNSAutoreleasePool pool_;
-  scoped_nsobject<WebDropTarget> drop_target_;
-};
-
-// Make sure nothing leaks.
-TEST_F(WebDropTargetTest, Init) {
-  EXPECT_TRUE(drop_target_);
-}
-
-// Test flipping of coordinates given a point in window coordinates.
-TEST_F(WebDropTargetTest, Flip) {
-  NSPoint windowPoint = NSZeroPoint;
-  scoped_nsobject<NSWindow> window([[CocoaTestHelperWindow alloc] init]);
-  NSPoint viewPoint =
-      [drop_target_ flipWindowPointToView:windowPoint
-                                     view:[window contentView]];
-  NSPoint screenPoint =
-      [drop_target_ flipWindowPointToScreen:windowPoint
-                               view:[window contentView]];
-  EXPECT_EQ(0, viewPoint.x);
-  EXPECT_EQ(600, viewPoint.y);
-  EXPECT_EQ(0, screenPoint.x);
-  // We can't put a value on the screen size since everyone will have a
-  // different one.
-  EXPECT_NE(0, screenPoint.y);
-}
-
-TEST_F(WebDropTargetTest, URL) {
-  NSPasteboard* pboard = nil;
-  NSString* url = nil;
-  NSString* title = nil;
-  GURL result_url;
-  string16 result_title;
-
-  // Put a URL on the pasteboard and check it.
-  pboard = [NSPasteboard pasteboardWithUniqueName];
-  url = @"http://www.google.com/";
-  PutURLOnPasteboard(url, pboard);
-  EXPECT_TRUE([drop_target_ populateURL:&result_url
-                               andTitle:&result_title
-                         fromPasteboard:pboard
-                    convertingFilenames:NO]);
-  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
-  [pboard releaseGlobally];
-
-  // Put a 'url ' and 'urln' on the pasteboard and check it.
-  pboard = [NSPasteboard pasteboardWithUniqueName];
-  url = @"http://www.google.com/";
-  title = @"Title of Awesomeness!",
-  PutCoreURLAndTitleOnPasteboard(url, title, pboard);
-  EXPECT_TRUE([drop_target_ populateURL:&result_url
-                               andTitle:&result_title
-                         fromPasteboard:pboard
-                    convertingFilenames:NO]);
-  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
-  EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
-  [pboard releaseGlobally];
-
-  // Also check that it passes file:// via 'url '/'urln' properly.
-  pboard = [NSPasteboard pasteboardWithUniqueName];
-  url = @"file:///tmp/dont_delete_me.txt";
-  title = @"very important";
-  PutCoreURLAndTitleOnPasteboard(url, title, pboard);
-  EXPECT_TRUE([drop_target_ populateURL:&result_url
-                               andTitle:&result_title
-                         fromPasteboard:pboard
-                    convertingFilenames:NO]);
-  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
-  EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
-  [pboard releaseGlobally];
-
-  // And javascript:.
-  pboard = [NSPasteboard pasteboardWithUniqueName];
-  url = @"javascript:open('http://www.youtube.com/')";
-  title = @"kill some time";
-  PutCoreURLAndTitleOnPasteboard(url, title, pboard);
-  EXPECT_TRUE([drop_target_ populateURL:&result_url
-                               andTitle:&result_title
-                         fromPasteboard:pboard
-                    convertingFilenames:NO]);
-  EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
-  EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
-  [pboard releaseGlobally];
-
-  pboard = [NSPasteboard pasteboardWithUniqueName];
-  url = @"/bin/sh";
-  [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
-                 owner:nil];
-  [pboard setPropertyList:[NSArray arrayWithObject:url]
-                  forType:NSFilenamesPboardType];
-  EXPECT_FALSE([drop_target_ populateURL:&result_url
-                                andTitle:&result_title
-                          fromPasteboard:pboard
-                    convertingFilenames:NO]);
-  EXPECT_TRUE([drop_target_ populateURL:&result_url
-                               andTitle:&result_title
-                         fromPasteboard:pboard
-                    convertingFilenames:YES]);
-  EXPECT_EQ("file://localhost/bin/sh", result_url.spec());
-  EXPECT_EQ("sh", UTF16ToUTF8(result_title));
-  [pboard releaseGlobally];
-}
-
-TEST_F(WebDropTargetTest, Data) {
-  WebDropData data;
-  NSPasteboard* pboard = [NSPasteboard pasteboardWithUniqueName];
-
-  PutURLOnPasteboard(@"http://www.google.com", pboard);
-  [pboard addTypes:[NSArray arrayWithObjects:NSHTMLPboardType,
-                              NSStringPboardType, nil]
-             owner:nil];
-  NSString* htmlString = @"<html><body><b>hi there</b></body></html>";
-  NSString* textString = @"hi there";
-  [pboard setString:htmlString forType:NSHTMLPboardType];
-  [pboard setString:textString forType:NSStringPboardType];
-  [drop_target_ populateWebDropData:&data fromPasteboard:pboard];
-  EXPECT_EQ(data.url.spec(), "http://www.google.com/");
-  EXPECT_EQ(base::SysNSStringToUTF16(textString), data.plain_text);
-  EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.text_html);
-
-  [pboard releaseGlobally];
-}
diff --git a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
index c3b33ed..3b95440 100644
--- a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
+++ b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -44,7 +44,9 @@
   ASSERT_TRUE(pref != NULL);
 
   // Check to make sure there is no existing pref for window placement.
-  ASSERT_TRUE(pref->GetDictionary(path_) == NULL);
+  const DictionaryValue* placement = pref->GetDictionary(path_);
+  ASSERT_TRUE(placement);
+  EXPECT_TRUE(placement->empty());
 
   // Replace the window with one that doesn't have resize controls.
   [window_ close];
@@ -109,7 +111,9 @@
   ASSERT_TRUE(pref != NULL);
 
   // Check to make sure there is no existing pref for window placement.
-  ASSERT_TRUE(pref->GetDictionary(path_) == NULL);
+  const DictionaryValue* placement = pref->GetDictionary(path_);
+  ASSERT_TRUE(placement);
+  EXPECT_TRUE(placement->empty());
 
   // Ask the window to save its position, then check that a preference
   // exists.  We're technically passing in a pointer to the user prefs
diff --git a/chrome/browser/ui/cocoa/wrench_menu/OWNERS b/chrome/browser/ui/cocoa/wrench_menu/OWNERS
new file mode 100644
index 0000000..14fce2a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/OWNERS
@@ -0,0 +1 @@
+rsesek@chromium.org
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.h b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.h
new file mode 100644
index 0000000..b99ecee
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_WRENCH_MENU_MENU_TRACKED_BUTTON_H_
+#define CHROME_BROWSER_UI_COCOA_WRENCH_MENU_MENU_TRACKED_BUTTON_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+// A MenuTrackedButton is meant to be used whenever a button is placed inside
+// the custom view of an NSMenuItem. If the user opens the menu in a non-sticky
+// fashion (i.e. clicks, holds, and drags) and then releases the mouse over
+// a MenuTrackedButton, it will |-performClick:| itself.
+//
+// To create the hover state effects, there are two code paths.  When the menu
+// is opened sticky, a tracking rect produces mouse entered/exit events that
+// allow for setting the cell's highlight property.  When in a drag cycle,
+// however, the only event received is |-mouseDragged:|.  Therefore, a
+// delayed selector is scheduled to poll the mouse location after each drag
+// event.  This checks if the user is still over the button after the drag
+// events stop being sent, indicating either the user is hovering without
+// movement or that the mouse is no longer over the receiver.
+@interface MenuTrackedButton : NSButton {
+ @private
+  // If the button received a |-mouseEntered:| event. This short-circuits the
+  // custom drag tracking logic.
+  BOOL didEnter_;
+
+  // Whether or not the user is in a click-drag-release event sequence. If so
+  // and this receives a |-mouseUp:|, then this will click itself.
+  BOOL tracking_;
+
+  // In order to get hover effects when the menu is sticky-opened, a tracking
+  // rect needs to be installed on the button.
+  NSTrackingRectTag trackingTag_;
+}
+
+@property(nonatomic, readonly, getter=isTracking) BOOL tracking;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_WRENCH_MENU_MENU_TRACKED_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.mm b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.mm
new file mode 100644
index 0000000..3f65b36
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.mm
@@ -0,0 +1,118 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.h"
+
+#include <cmath>
+
+@interface MenuTrackedButton (Private)
+- (void)doHighlight:(BOOL)highlight;
+- (void)checkMouseInRect;
+- (NSRect)insetBounds;
+- (BOOL)shouldHighlightOnHover;
+@end
+
+@implementation MenuTrackedButton
+
+@synthesize tracking = tracking_;
+
+- (void)updateTrackingAreas {
+  [super updateTrackingAreas];
+  [self removeTrackingRect:trackingTag_];
+  trackingTag_ = [self addTrackingRect:NSInsetRect([self bounds], 1, 1)
+                                 owner:self
+                              userData:NULL
+                          assumeInside:NO];
+}
+
+- (void)viewDidMoveToWindow {
+  [self updateTrackingAreas];
+  [self doHighlight:NO];
+}
+
+- (void)mouseEntered:(NSEvent*)theEvent {
+  if (!tracking_) {
+    didEnter_ = YES;
+  }
+  [self doHighlight:YES];
+  [super mouseEntered:theEvent];
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+  didEnter_ = NO;
+  tracking_ = NO;
+  [self doHighlight:NO];
+  [super mouseExited:theEvent];
+}
+
+- (void)mouseDragged:(NSEvent*)theEvent {
+  tracking_ = !didEnter_;
+
+  NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+  BOOL highlight = NSPointInRect(point, [self insetBounds]);
+  [self doHighlight:highlight];
+
+  // If tracking in non-sticky mode, poll the mouse cursor to see if it is still
+  // over the button and thus needs to be highlighted.  The delay is the
+  // smallest that still produces the effect while minimizing jank. Smaller
+  // values make the selector fire too close to immediately/now for the mouse to
+  // have moved off the receiver, and larger values produce lag.
+  if (tracking_ && [self shouldHighlightOnHover]) {
+    [self performSelector:@selector(checkMouseInRect)
+               withObject:nil
+               afterDelay:0.05
+                  inModes:[NSArray arrayWithObject:NSEventTrackingRunLoopMode]];
+  }
+  [super mouseDragged:theEvent];
+}
+
+- (void)mouseUp:(NSEvent*)theEvent {
+  [self doHighlight:NO];
+  if (!tracking_) {
+    return [super mouseUp:theEvent];
+  }
+  [self performClick:self];
+  tracking_ = NO;
+}
+
+- (void)doHighlight:(BOOL)highlight {
+  if (![self shouldHighlightOnHover]) {
+    return;
+  }
+  [[self cell] setHighlighted:highlight];
+  [self setNeedsDisplay];
+}
+
+// Checks if the user's current mouse location is over this button.  If it is,
+// the user is merely hovering here.  If it is not, then disable the highlight.
+// If the menu is opened in non-sticky mode, the button does not receive enter/
+// exit mouse events and thus polling is necessary.
+- (void)checkMouseInRect {
+  NSPoint point = [NSEvent mouseLocation];
+  point = [[self window] convertScreenToBase:point];
+  point = [self convertPoint:point fromView:nil];
+  if (!NSPointInRect(point, [self insetBounds])) {
+    [self doHighlight:NO];
+  }
+}
+
+// Returns the bounds of the receiver slightly inset to avoid highlighting both
+// buttons in a pair that overlap.
+- (NSRect)insetBounds {
+  return NSInsetRect([self bounds], 2, 1);
+}
+
+- (BOOL)shouldHighlightOnHover {
+  // Apple does not define NSAppKitVersionNumber10_5 when using the 10.5 SDK.
+  // The Internets have come up with this solution.
+  #ifndef NSAppKitVersionNumber10_5
+  #define NSAppKitVersionNumber10_5 949
+  #endif
+
+  // There's a cell drawing bug in 10.5 that was fixed on 10.6.  Hover states
+  // look terrible due to this, so disable highlighting on 10.5.
+  return std::floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5;
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button_unittest.mm
new file mode 100644
index 0000000..16a529a
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button_unittest.mm
@@ -0,0 +1,117 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_button.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+// This test does not test what you'd think it does. Testing around event
+// tracking run loops is probably not worh the effort when the size of the
+// helper MakeEvent() is larger than the class being tested. If we ever figure
+// out a good way to test event tracking, this should be revisited.
+
+@interface MenuTrackedButtonTestReceiver : NSObject {
+ @public
+  BOOL didThat_;
+}
+- (void)doThat:(id)sender;
+@end
+@implementation MenuTrackedButtonTestReceiver
+- (void)doThat:(id)sender {
+  didThat_ = YES;
+}
+@end
+
+
+class MenuTrackedButtonTest : public CocoaTest {
+ public:
+  MenuTrackedButtonTest() : event_number_(0) {}
+
+  void SetUp() {
+    listener_.reset([[MenuTrackedButtonTestReceiver alloc] init]);
+    button_.reset(
+        [[MenuTrackedButton alloc] initWithFrame:NSMakeRect(10, 10, 50, 50)]);
+    [[test_window() contentView] addSubview:button()];
+    [button_ setTarget:listener()];
+    [button_ setAction:@selector(doThat:)];
+  }
+
+  // Creates an event of |type|, with |location| in test_window()'s coordinates.
+  NSEvent* MakeEvent(NSEventType type, NSPoint location) {
+    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
+    location = [test_window() convertBaseToScreen:location];
+    if (type == NSMouseEntered || type == NSMouseExited) {
+      return [NSEvent enterExitEventWithType:type
+                                    location:location
+                               modifierFlags:0
+                                   timestamp:now
+                                windowNumber:[test_window() windowNumber]
+                                     context:nil
+                                 eventNumber:event_number_++
+                              trackingNumber:0
+                                    userData:nil];
+    } else {
+      return [NSEvent mouseEventWithType:type
+                                location:location
+                           modifierFlags:0
+                               timestamp:now
+                            windowNumber:[test_window() windowNumber]
+                                 context:nil
+                             eventNumber:event_number_++
+                              clickCount:1
+                                pressure:1.0];
+    }
+  }
+
+  MenuTrackedButtonTestReceiver* listener() { return listener_.get(); }
+  NSButton* button() { return button_.get(); }
+
+  scoped_nsobject<MenuTrackedButtonTestReceiver> listener_;
+  scoped_nsobject<MenuTrackedButton> button_;
+  NSInteger event_number_;
+};
+
+// User mouses over and then off.
+TEST_F(MenuTrackedButtonTest, DISABLED_EnterExit) {
+  [NSApp postEvent:MakeEvent(NSMouseEntered, NSMakePoint(11, 11)) atStart:YES];
+  [NSApp postEvent:MakeEvent(NSMouseExited, NSMakePoint(9, 9)) atStart:YES];
+  EXPECT_FALSE(listener()->didThat_);
+}
+
+// User mouses over, clicks, drags, and exits.
+TEST_F(MenuTrackedButtonTest, DISABLED_EnterDragExit) {
+  [NSApp postEvent:MakeEvent(NSMouseEntered, NSMakePoint(11, 11)) atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseDown, NSMakePoint(12, 12)) atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(13, 11))
+           atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(13, 10))
+           atStart:YES];
+  [NSApp postEvent:MakeEvent(NSMouseExited, NSMakePoint(13, 9)) atStart:YES];
+  EXPECT_FALSE(listener()->didThat_);
+}
+
+// User mouses over, clicks, drags, and releases.
+TEST_F(MenuTrackedButtonTest, DISABLED_EnterDragUp) {
+  [NSApp postEvent:MakeEvent(NSMouseEntered, NSMakePoint(11, 11)) atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseDown, NSMakePoint(12, 12)) atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(13, 13))
+           atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseUp, NSMakePoint(14, 14)) atStart:YES];
+  EXPECT_TRUE(listener()->didThat_);
+}
+
+// User drags in and releases.
+TEST_F(MenuTrackedButtonTest, DISABLED_DragUp) {
+  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(11, 11))
+           atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseDragged, NSMakePoint(12, 12))
+           atStart:YES];
+  [NSApp postEvent:MakeEvent(NSLeftMouseUp, NSMakePoint(13, 13))
+           atStart:YES];
+  EXPECT_TRUE(listener()->didThat_);
+}
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h
new file mode 100644
index 0000000..f2aecbc
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_WRENCH_MENU_MENU_TRACKED_ROOT_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_WRENCH_MENU_MENU_TRACKED_ROOT_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+// An instance of MenuTrackedRootView should be the root of the view hierarchy
+// of the custom view of NSMenuItems. If the user opens the menu in a non-
+// sticky fashion (i.e. clicks, holds, and drags) and then releases the mouse
+// over the menu item, it will cancel tracking on the |[menuItem_ menu]|.
+@interface MenuTrackedRootView : NSView {
+ @private
+  // The menu item whose custom view's root view is an instance of this class.
+  NSMenuItem* menuItem_;  // weak
+}
+
+@property(assign, nonatomic) NSMenuItem* menuItem;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_WRENCH_MENU_MENU_TRACKED_ROOT_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.mm b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.mm
new file mode 100644
index 0000000..96b3b26
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.mm
@@ -0,0 +1,15 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h"
+
+@implementation MenuTrackedRootView
+
+@synthesize menuItem = menuItem_;
+
+- (void)mouseUp:(NSEvent*)theEvent {
+  [[menuItem_ menu] cancelTracking];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm
new file mode 100644
index 0000000..a853824
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view_unittest.mm
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+
+class MenuTrackedRootViewTest : public CocoaTest {
+ public:
+  void SetUp() {
+    CocoaTest::SetUp();
+    view_.reset([[MenuTrackedRootView alloc] init]);
+  }
+
+  scoped_nsobject<MenuTrackedRootView> view_;
+};
+
+TEST_F(MenuTrackedRootViewTest, MouseUp) {
+  id menu = [OCMockObject mockForClass:[NSMenu class]];
+  [[menu expect] cancelTracking];
+
+  id menuItem = [OCMockObject mockForClass:[NSMenuItem class]];
+  [[[menuItem stub] andReturn:menu] menu];
+
+  [view_ setMenuItem:menuItem];
+  NSEvent* event = [NSEvent mouseEventWithType:NSLeftMouseUp
+                                      location:NSMakePoint(42, 42)
+                                 modifierFlags:0
+                                     timestamp:0
+                                  windowNumber:[test_window() windowNumber]
+                                       context:nil
+                                   eventNumber:1
+                                    clickCount:1
+                                      pressure:1.0];
+  [view_ mouseUp:event];
+
+  [menu verify];
+  [menuItem verify];
+}
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h
new file mode 100644
index 0000000..4c40059
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_WRENCH_MENU_WRENCH_MENU_BUTTON_CELL_H_
+#define CHROME_BROWSER_UI_COCOA_WRENCH_MENU_WRENCH_MENU_BUTTON_CELL_H_
+
+#import <Cocoa/Cocoa.h>
+
+// The WrenchMenuButtonCell overrides drawing the background gradient to use
+// the same colors as NSSmallSquareBezelStyle but as a smooth gradient, rather
+// than two blocks of colors.  This also uses the blue menu highlight color for
+// the pressed state.
+@interface WrenchMenuButtonCell : NSButtonCell {
+}
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_WRENCH_MENU_WRENCH_MENU_BUTTON_CELL_H_
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm
new file mode 100644
index 0000000..d042989
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.mm
@@ -0,0 +1,48 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h"
+
+#include "base/scoped_nsobject.h"
+
+@implementation WrenchMenuButtonCell
+
+- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
+  [NSGraphicsContext saveGraphicsState];
+
+  // Inset the rect to match the appearance of the layout of interface builder.
+  // The bounding rect of buttons is actually larger than the display rect shown
+  // there.
+  frame = NSInsetRect(frame, 0.0, 1.0);
+
+  // Stroking the rect gives a weak stroke.  Filling and insetting gives a
+  // strong, un-anti-aliased border.
+  [[NSColor colorWithDeviceWhite:0.663 alpha:1.0] set];
+  NSRectFill(frame);
+  frame = NSInsetRect(frame, 1.0, 1.0);
+
+  // The default state should be a subtle gray gradient.
+  if (![self isHighlighted]) {
+    NSColor* end = [NSColor colorWithDeviceWhite:0.922 alpha:1.0];
+    scoped_nsobject<NSGradient> gradient(
+        [[NSGradient alloc] initWithStartingColor:[NSColor whiteColor]
+                                      endingColor:end]);
+    [gradient drawInRect:frame angle:90.0];
+  } else {
+    // |+selectedMenuItemColor| appears to be a gradient, so just filling the
+    // rect with that color produces the desired effect.
+    [[NSColor selectedMenuItemColor] set];
+    NSRectFill(frame);
+  }
+
+  [NSGraphicsContext restoreGraphicsState];
+}
+
+- (NSBackgroundStyle)interiorBackgroundStyle {
+  if ([self isHighlighted])
+    return NSBackgroundStyleDark;
+  return [super interiorBackgroundStyle];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm
new file mode 100644
index 0000000..fc9e403
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell_unittest.mm
@@ -0,0 +1,51 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#include "chrome/app/chrome_command_ids.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_button_cell.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+@interface TestWrenchMenuButton : NSButton
+@end
+@implementation TestWrenchMenuButton
++ (Class)cellClass {
+  return [WrenchMenuButtonCell class];
+}
+@end
+
+namespace {
+
+class WrenchMenuButtonCellTest : public CocoaTest {
+ public:
+  void SetUp() {
+    CocoaTest::SetUp();
+
+    NSRect frame = NSMakeRect(10, 10, 50, 19);
+    button_.reset([[TestWrenchMenuButton alloc] initWithFrame:frame]);
+    [button_ setBezelStyle:NSSmallSquareBezelStyle];
+    [[button_ cell] setControlSize:NSSmallControlSize];
+    [button_ setTitle:@"Allays"];
+    [button_ setButtonType:NSMomentaryPushInButton];
+  }
+
+  scoped_nsobject<NSButton> button_;
+};
+
+TEST_F(WrenchMenuButtonCellTest, Draw) {
+  ASSERT_TRUE(button_.get());
+  [[test_window() contentView] addSubview:button_.get()];
+  [button_ setNeedsDisplay:YES];
+}
+
+TEST_F(WrenchMenuButtonCellTest, DrawHighlight) {
+  ASSERT_TRUE(button_.get());
+  [[test_window() contentView] addSubview:button_.get()];
+  [button_ highlight:YES];
+  [button_ setNeedsDisplay:YES];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h
new file mode 100644
index 0000000..ec68120
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_WRENCH_MENU_WRENCH_MENU_CONTROLLER_H_
+#define CHROME_BROWSER_UI_COCOA_WRENCH_MENU_WRENCH_MENU_CONTROLLER_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/scoped_ptr.h"
+#import "chrome/browser/ui/cocoa/menu_controller.h"
+
+@class MenuTrackedRootView;
+@class ToolbarController;
+class WrenchMenuModel;
+
+namespace WrenchMenuControllerInternal {
+class ZoomLevelObserver;
+}  // namespace WrenchMenuControllerInternal
+
+// The Wrench menu has a creative layout, with buttons in menu items. There is
+// a cross-platform model for this special menu, but on the Mac it's easier to
+// get spacing and alignment precisely right using a NIB. To do that, we
+// subclass the generic MenuController implementation and special-case the two
+// items that require specific layout and load them from the NIB.
+//
+// This object is instantiated in Toolbar.xib and is configured by the
+// ToolbarController.
+@interface WrenchMenuController : MenuController<NSMenuDelegate> {
+  IBOutlet MenuTrackedRootView* editItem_;
+  IBOutlet NSButton* editCut_;
+  IBOutlet NSButton* editCopy_;
+  IBOutlet NSButton* editPaste_;
+
+  IBOutlet MenuTrackedRootView* zoomItem_;
+  IBOutlet NSButton* zoomPlus_;
+  IBOutlet NSButton* zoomDisplay_;
+  IBOutlet NSButton* zoomMinus_;
+  IBOutlet NSButton* zoomFullScreen_;
+
+  scoped_ptr<WrenchMenuControllerInternal::ZoomLevelObserver> observer_;
+}
+
+// Designated initializer; called within the NIB.
+- (id)init;
+
+// Used to dispatch commands from the Wrench menu. The custom items within the
+// menu cannot be hooked up directly to First Responder because the window in
+// which the controls reside is not the BrowserWindowController, but a
+// NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system.
+- (IBAction)dispatchWrenchMenuCommand:(id)sender;
+
+// Returns the weak reference to the WrenchMenuModel.
+- (WrenchMenuModel*)wrenchMenuModel;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////
+
+@interface WrenchMenuController (UnitTesting)
+// |-dispatchWrenchMenuCommand:| calls this after it has determined the tag of
+// the sender. The default implementation executes the command on the outermost
+// run loop using |-performSelector...withDelay:|. This is not desirable in
+// unit tests because it's hard to test around run loops in a deterministic
+// manner. To avoid those headaches, tests should provide an alternative
+// implementation.
+- (void)dispatchCommandInternal:(NSInteger)tag;
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_WRENCH_MENU_WRENCH_MENU_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm
new file mode 100644
index 0000000..d4167bf
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm
@@ -0,0 +1,222 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/background_page_tracker.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/wrench_menu/menu_tracked_root_view.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/menu_model.h"
+
+@interface WrenchMenuController (Private)
+- (void)adjustPositioning;
+- (void)performCommandDispatch:(NSNumber*)tag;
+- (NSButton*)zoomDisplay;
+@end
+
+namespace WrenchMenuControllerInternal {
+
+class ZoomLevelObserver : public NotificationObserver {
+ public:
+  explicit ZoomLevelObserver(WrenchMenuController* controller)
+      : controller_(controller) {
+    registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
+                   NotificationService::AllSources());
+  }
+
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    DCHECK_EQ(type.value, NotificationType::ZOOM_LEVEL_CHANGED);
+    WrenchMenuModel* wrenchMenuModel = [controller_ wrenchMenuModel];
+    wrenchMenuModel->UpdateZoomControls();
+    const string16 level =
+        wrenchMenuModel->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY);
+    [[controller_ zoomDisplay] setTitle:SysUTF16ToNSString(level)];
+  }
+
+ private:
+  NotificationRegistrar registrar_;
+  WrenchMenuController* controller_;  // Weak; owns this.
+};
+
+}  // namespace WrenchMenuControllerInternal
+
+@implementation WrenchMenuController
+
+- (id)init {
+  if ((self = [super init])) {
+    observer_.reset(new WrenchMenuControllerInternal::ZoomLevelObserver(self));
+  }
+  return self;
+}
+
+- (void)addItemToMenu:(NSMenu*)menu
+              atIndex:(NSInteger)index
+            fromModel:(ui::MenuModel*)model
+           modelIndex:(int)modelIndex {
+  // Non-button item types should be built as normal items.
+  ui::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
+  if (type != ui::MenuModel::TYPE_BUTTON_ITEM) {
+    [super addItemToMenu:menu
+                 atIndex:index
+               fromModel:model
+              modelIndex:modelIndex];
+    return;
+  }
+
+  // Handle the special-cased menu items.
+  int command_id = model->GetCommandIdAt(modelIndex);
+  scoped_nsobject<NSMenuItem> customItem(
+      [[NSMenuItem alloc] initWithTitle:@""
+                                 action:nil
+                          keyEquivalent:@""]);
+  switch (command_id) {
+    case IDC_EDIT_MENU:
+      DCHECK(editItem_);
+      [customItem setView:editItem_];
+      [editItem_ setMenuItem:customItem];
+      break;
+    case IDC_ZOOM_MENU:
+      DCHECK(zoomItem_);
+      [customItem setView:zoomItem_];
+      [zoomItem_ setMenuItem:customItem];
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  [self adjustPositioning];
+  [menu insertItem:customItem.get() atIndex:index];
+}
+
+- (NSMenu*)menu {
+  NSMenu* menu = [super menu];
+  if (![menu delegate]) {
+    [menu setDelegate:self];
+  }
+  return menu;
+}
+
+- (void)menuWillOpen:(NSMenu*)menu {
+  NSString* title = base::SysUTF16ToNSString(
+      [self wrenchMenuModel]->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY));
+  [[zoomItem_ viewWithTag:IDC_ZOOM_PERCENT_DISPLAY] setTitle:title];
+  UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu"));
+
+  NSImage* icon = [self wrenchMenuModel]->browser()->window()->IsFullscreen() ?
+      [NSImage imageNamed:NSImageNameExitFullScreenTemplate] :
+          [NSImage imageNamed:NSImageNameEnterFullScreenTemplate];
+  [zoomFullScreen_ setImage:icon];
+}
+
+- (void)menuDidClose:(NSMenu*)menu {
+  // When the menu is closed, acknowledge the background pages so the badges go
+  // away.
+  BackgroundPageTracker::GetInstance()->AcknowledgeBackgroundPages();
+}
+
+// Used to dispatch commands from the Wrench menu. The custom items within the
+// menu cannot be hooked up directly to First Responder because the window in
+// which the controls reside is not the BrowserWindowController, but a
+// NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system.
+- (IBAction)dispatchWrenchMenuCommand:(id)sender {
+  NSInteger tag = [sender tag];
+  if (sender == zoomPlus_ || sender == zoomMinus_) {
+    // Do a direct dispatch rather than scheduling on the outermost run loop,
+    // which would not get hit until after the menu had closed.
+    [self performCommandDispatch:[NSNumber numberWithInt:tag]];
+
+    // The zoom buttons should not close the menu if opened sticky.
+    if ([sender respondsToSelector:@selector(isTracking)] &&
+        [sender performSelector:@selector(isTracking)]) {
+      [menu_ cancelTracking];
+    }
+  } else {
+    // The custom views within the Wrench menu are abnormal and keep the menu
+    // open after a target-action.  Close the menu manually.
+    [menu_ cancelTracking];
+    [self dispatchCommandInternal:tag];
+  }
+}
+
+- (void)dispatchCommandInternal:(NSInteger)tag {
+  // Executing certain commands from the nested run loop of the menu can lead
+  // to wonky behavior (e.g. http://crbug.com/49716). To avoid this, schedule
+  // the dispatch on the outermost run loop.
+  [self performSelector:@selector(performCommandDispatch:)
+             withObject:[NSNumber numberWithInt:tag]
+             afterDelay:0.0];
+}
+
+// Used to perform the actual dispatch on the outermost runloop.
+- (void)performCommandDispatch:(NSNumber*)tag {
+  [self wrenchMenuModel]->ExecuteCommand([tag intValue]);
+}
+
+- (WrenchMenuModel*)wrenchMenuModel {
+  return static_cast<WrenchMenuModel*>(model_);
+}
+
+// Fit the localized strings into the Cut/Copy/Paste control, then resize the
+// whole menu item accordingly.
+- (void)adjustPositioning {
+  const CGFloat kButtonPadding = 12;
+  CGFloat delta = 0;
+
+  // Go through the three buttons from right-to-left, adjusting the size to fit
+  // the localized strings while keeping them all aligned on their horizontal
+  // edges.
+  const size_t kAdjustViewCount = 3;
+  NSButton* views[kAdjustViewCount] = { editPaste_, editCopy_, editCut_ };
+  for (size_t i = 0; i < kAdjustViewCount; ++i) {
+    NSButton* button = views[i];
+    CGFloat originalWidth = NSWidth([button frame]);
+
+    // Do not let |-sizeToFit| change the height of the button.
+    NSSize size = [button frame].size;
+    [button sizeToFit];
+    size.width = [button frame].size.width + kButtonPadding;
+    [button setFrameSize:size];
+
+    CGFloat newWidth = size.width;
+    delta += newWidth - originalWidth;
+
+    NSRect frame = [button frame];
+    frame.origin.x -= delta;
+    [button setFrame:frame];
+  }
+
+  // Resize the menu item by the total amound the buttons changed so that the
+  // spacing between the buttons and the title remains the same.
+  NSRect itemFrame = [editItem_ frame];
+  itemFrame.size.width += delta;
+  [editItem_ setFrame:itemFrame];
+
+  // Also resize the superview of the buttons, which is an NSView used to slide
+  // when the item title is too big and GTM resizes it.
+  NSRect parentFrame = [[editCut_ superview] frame];
+  parentFrame.size.width += delta;
+  parentFrame.origin.x -= delta;
+  [[editCut_ superview] setFrame:parentFrame];
+}
+
+- (NSButton*)zoomDisplay {
+  return zoomDisplay_;
+}
+
+@end  // @implementation WrenchMenuController
diff --git a/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm
new file mode 100644
index 0000000..62a2475
--- /dev/null
+++ b/chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller_unittest.mm
@@ -0,0 +1,84 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_nsobject.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/cocoa/browser_test_helper.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
+#import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h"
+#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+// Override to avoid dealing with run loops in the testing environment.
+@implementation WrenchMenuController (UnitTesting)
+- (void)dispatchCommandInternal:(NSInteger)tag {
+  [self wrenchMenuModel]->ExecuteCommand(tag);
+}
+@end
+
+
+namespace {
+
+class MockWrenchMenuModel : public WrenchMenuModel {
+ public:
+  MockWrenchMenuModel() : WrenchMenuModel() {}
+  ~MockWrenchMenuModel() {
+    // This dirty, ugly hack gets around a bug in the test. In
+    // ~WrenchMenuModel(), there's a call to TabstripModel::RemoveObserver(this)
+    // which mysteriously leads to this crash: http://crbug.com/49206 .  It
+    // seems that the vector of observers is getting hosed somewhere between
+    // |-[ToolbarController dealloc]| and ~MockWrenchMenuModel(). This line
+    // short-circuits the parent destructor to avoid this crash.
+    tabstrip_model_ = NULL;
+  }
+  MOCK_METHOD1(ExecuteCommand, void(int command_id));
+};
+
+class WrenchMenuControllerTest : public CocoaTest {
+ public:
+  void SetUp() {
+    Browser* browser = helper_.browser();
+    resize_delegate_.reset([[ViewResizerPong alloc] init]);
+    toolbar_controller_.reset(
+        [[ToolbarController alloc] initWithModel:browser->toolbar_model()
+                                        commands:browser->command_updater()
+                                         profile:helper_.profile()
+                                         browser:browser
+                                  resizeDelegate:resize_delegate_.get()]);
+    EXPECT_TRUE([toolbar_controller_ view]);
+    NSView* parent = [test_window() contentView];
+    [parent addSubview:[toolbar_controller_ view]];
+  }
+
+  WrenchMenuController* controller() {
+    return [toolbar_controller_ wrenchMenuController];
+  }
+
+  BrowserTestHelper helper_;
+  scoped_nsobject<ViewResizerPong> resize_delegate_;
+  MockWrenchMenuModel fake_model_;
+  scoped_nsobject<ToolbarController> toolbar_controller_;
+};
+
+TEST_F(WrenchMenuControllerTest, Initialized) {
+  EXPECT_TRUE([controller() menu]);
+  EXPECT_GE([[controller() menu] numberOfItems], 5);
+}
+
+TEST_F(WrenchMenuControllerTest, DispatchSimple) {
+  scoped_nsobject<NSButton> button([[NSButton alloc] init]);
+  [button setTag:IDC_ZOOM_PLUS];
+
+  // Set fake model to test dispatching.
+  EXPECT_CALL(fake_model_, ExecuteCommand(IDC_ZOOM_PLUS));
+  [controller() setModel:&fake_model_];
+
+  [controller() dispatchWrenchMenuCommand:button.get()];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/cocoa/wrench_menu_button_cell.h b/chrome/browser/ui/cocoa/wrench_menu_button_cell.h
deleted file mode 100644
index c2d3432..0000000
--- a/chrome/browser/ui/cocoa/wrench_menu_button_cell.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_WRENCH_MENU_BUTTON_CELL_H_
-#define CHROME_BROWSER_UI_COCOA_WRENCH_MENU_BUTTON_CELL_H_
-
-#import <Cocoa/Cocoa.h>
-
-// The WrenchMenuButtonCell overrides drawing the background gradient to use
-// the same colors as NSSmallSquareBezelStyle but as a smooth gradient, rather
-// than two blocks of colors.  This also uses the blue menu highlight color for
-// the pressed state.
-@interface WrenchMenuButtonCell : NSButtonCell {
-}
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_WRENCH_MENU_BUTTON_CELL_H_
diff --git a/chrome/browser/ui/cocoa/wrench_menu_button_cell.mm b/chrome/browser/ui/cocoa/wrench_menu_button_cell.mm
deleted file mode 100644
index c2a15b7..0000000
--- a/chrome/browser/ui/cocoa/wrench_menu_button_cell.mm
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/wrench_menu_button_cell.h"
-
-#include "base/scoped_nsobject.h"
-
-@implementation WrenchMenuButtonCell
-
-- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
-  [NSGraphicsContext saveGraphicsState];
-
-  // Inset the rect to match the appearance of the layout of interface builder.
-  // The bounding rect of buttons is actually larger than the display rect shown
-  // there.
-  frame = NSInsetRect(frame, 0.0, 1.0);
-
-  // Stroking the rect gives a weak stroke.  Filling and insetting gives a
-  // strong, un-anti-aliased border.
-  [[NSColor colorWithDeviceWhite:0.663 alpha:1.0] set];
-  NSRectFill(frame);
-  frame = NSInsetRect(frame, 1.0, 1.0);
-
-  // The default state should be a subtle gray gradient.
-  if (![self isHighlighted]) {
-    NSColor* end = [NSColor colorWithDeviceWhite:0.922 alpha:1.0];
-    scoped_nsobject<NSGradient> gradient(
-        [[NSGradient alloc] initWithStartingColor:[NSColor whiteColor]
-                                      endingColor:end]);
-    [gradient drawInRect:frame angle:90.0];
-  } else {
-    // |+selectedMenuItemColor| appears to be a gradient, so just filling the
-    // rect with that color produces the desired effect.
-    [[NSColor selectedMenuItemColor] set];
-    NSRectFill(frame);
-  }
-
-  [NSGraphicsContext restoreGraphicsState];
-}
-
-- (NSBackgroundStyle)interiorBackgroundStyle {
-  if ([self isHighlighted])
-    return NSBackgroundStyleDark;
-  return [super interiorBackgroundStyle];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/wrench_menu_button_cell_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu_button_cell_unittest.mm
deleted file mode 100644
index 7ab1588..0000000
--- a/chrome/browser/ui/cocoa/wrench_menu_button_cell_unittest.mm
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#include "chrome/app/chrome_command_ids.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/wrench_menu_button_cell.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-@interface TestWrenchMenuButton : NSButton
-@end
-@implementation TestWrenchMenuButton
-+ (Class)cellClass {
-  return [WrenchMenuButtonCell class];
-}
-@end
-
-namespace {
-
-class WrenchMenuButtonCellTest : public CocoaTest {
- public:
-  void SetUp() {
-    CocoaTest::SetUp();
-
-    NSRect frame = NSMakeRect(10, 10, 50, 19);
-    button_.reset([[TestWrenchMenuButton alloc] initWithFrame:frame]);
-    [button_ setBezelStyle:NSSmallSquareBezelStyle];
-    [[button_ cell] setControlSize:NSSmallControlSize];
-    [button_ setTitle:@"Allays"];
-    [button_ setButtonType:NSMomentaryPushInButton];
-  }
-
-  scoped_nsobject<NSButton> button_;
-};
-
-TEST_F(WrenchMenuButtonCellTest, Draw) {
-  ASSERT_TRUE(button_.get());
-  [[test_window() contentView] addSubview:button_.get()];
-  [button_ setNeedsDisplay:YES];
-}
-
-TEST_F(WrenchMenuButtonCellTest, DrawHighlight) {
-  ASSERT_TRUE(button_.get());
-  [[test_window() contentView] addSubview:button_.get()];
-  [button_ highlight:YES];
-  [button_ setNeedsDisplay:YES];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/wrench_menu_controller.h b/chrome/browser/ui/cocoa/wrench_menu_controller.h
deleted file mode 100644
index f2dea7a..0000000
--- a/chrome/browser/ui/cocoa/wrench_menu_controller.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_WRENCH_MENU_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_WRENCH_MENU_CONTROLLER_H_
-#pragma once
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/cocoa_protocols.h"
-#include "base/scoped_ptr.h"
-#import "chrome/browser/ui/cocoa/menu_controller.h"
-
-@class MenuTrackedRootView;
-@class ToolbarController;
-class WrenchMenuModel;
-
-namespace WrenchMenuControllerInternal {
-class ZoomLevelObserver;
-}  // namespace WrenchMenuControllerInternal
-
-// The Wrench menu has a creative layout, with buttons in menu items. There is
-// a cross-platform model for this special menu, but on the Mac it's easier to
-// get spacing and alignment precisely right using a NIB. To do that, we
-// subclass the generic MenuController implementation and special-case the two
-// items that require specific layout and load them from the NIB.
-//
-// This object is instantiated in Toolbar.xib and is configured by the
-// ToolbarController.
-@interface WrenchMenuController : MenuController<NSMenuDelegate> {
-  IBOutlet MenuTrackedRootView* editItem_;
-  IBOutlet NSButton* editCut_;
-  IBOutlet NSButton* editCopy_;
-  IBOutlet NSButton* editPaste_;
-
-  IBOutlet MenuTrackedRootView* zoomItem_;
-  IBOutlet NSButton* zoomPlus_;
-  IBOutlet NSButton* zoomDisplay_;
-  IBOutlet NSButton* zoomMinus_;
-  IBOutlet NSButton* zoomFullScreen_;
-
-  scoped_ptr<WrenchMenuControllerInternal::ZoomLevelObserver> observer_;
-}
-
-// Designated initializer; called within the NIB.
-- (id)init;
-
-// Used to dispatch commands from the Wrench menu. The custom items within the
-// menu cannot be hooked up directly to First Responder because the window in
-// which the controls reside is not the BrowserWindowController, but a
-// NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system.
-- (IBAction)dispatchWrenchMenuCommand:(id)sender;
-
-// Returns the weak reference to the WrenchMenuModel.
-- (WrenchMenuModel*)wrenchMenuModel;
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////
-
-@interface WrenchMenuController (UnitTesting)
-// |-dispatchWrenchMenuCommand:| calls this after it has determined the tag of
-// the sender. The default implementation executes the command on the outermost
-// run loop using |-performSelector...withDelay:|. This is not desirable in
-// unit tests because it's hard to test around run loops in a deterministic
-// manner. To avoid those headaches, tests should provide an alternative
-// implementation.
-- (void)dispatchCommandInternal:(NSInteger)tag;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_WRENCH_MENU_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/wrench_menu_controller.mm b/chrome/browser/ui/cocoa/wrench_menu_controller.mm
deleted file mode 100644
index fcbada6..0000000
--- a/chrome/browser/ui/cocoa/wrench_menu_controller.mm
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/wrench_menu_controller.h"
-
-#include "app/l10n_util.h"
-#include "app/menus/menu_model.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/background_page_tracker.h"
-#import "chrome/browser/ui/cocoa/menu_tracked_root_view.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-
-@interface WrenchMenuController (Private)
-- (void)adjustPositioning;
-- (void)performCommandDispatch:(NSNumber*)tag;
-- (NSButton*)zoomDisplay;
-@end
-
-namespace WrenchMenuControllerInternal {
-
-class ZoomLevelObserver : public NotificationObserver {
- public:
-  explicit ZoomLevelObserver(WrenchMenuController* controller)
-      : controller_(controller) {
-    registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
-                   NotificationService::AllSources());
-  }
-
-  void Observe(NotificationType type,
-               const NotificationSource& source,
-               const NotificationDetails& details) {
-    DCHECK_EQ(type.value, NotificationType::ZOOM_LEVEL_CHANGED);
-    WrenchMenuModel* wrenchMenuModel = [controller_ wrenchMenuModel];
-    wrenchMenuModel->UpdateZoomControls();
-    const string16 level =
-        wrenchMenuModel->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY);
-    [[controller_ zoomDisplay] setTitle:SysUTF16ToNSString(level)];
-  }
-
- private:
-  NotificationRegistrar registrar_;
-  WrenchMenuController* controller_;  // Weak; owns this.
-};
-
-}  // namespace WrenchMenuControllerInternal
-
-@implementation WrenchMenuController
-
-- (id)init {
-  if ((self = [super init])) {
-    observer_.reset(new WrenchMenuControllerInternal::ZoomLevelObserver(self));
-  }
-  return self;
-}
-
-- (void)addItemToMenu:(NSMenu*)menu
-              atIndex:(NSInteger)index
-            fromModel:(menus::MenuModel*)model
-           modelIndex:(int)modelIndex {
-  // Non-button item types should be built as normal items.
-  menus::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
-  if (type != menus::MenuModel::TYPE_BUTTON_ITEM) {
-    [super addItemToMenu:menu
-                 atIndex:index
-               fromModel:model
-              modelIndex:modelIndex];
-    return;
-  }
-
-  // Handle the special-cased menu items.
-  int command_id = model->GetCommandIdAt(modelIndex);
-  scoped_nsobject<NSMenuItem> customItem(
-      [[NSMenuItem alloc] initWithTitle:@""
-                                 action:nil
-                          keyEquivalent:@""]);
-  switch (command_id) {
-    case IDC_EDIT_MENU:
-      DCHECK(editItem_);
-      [customItem setView:editItem_];
-      [editItem_ setMenuItem:customItem];
-      break;
-    case IDC_ZOOM_MENU:
-      DCHECK(zoomItem_);
-      [customItem setView:zoomItem_];
-      [zoomItem_ setMenuItem:customItem];
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  [self adjustPositioning];
-  [menu insertItem:customItem.get() atIndex:index];
-}
-
-- (NSMenu*)menu {
-  NSMenu* menu = [super menu];
-  if (![menu delegate]) {
-    [menu setDelegate:self];
-  }
-  return menu;
-}
-
-- (void)menuWillOpen:(NSMenu*)menu {
-  NSString* title = base::SysUTF16ToNSString(
-      [self wrenchMenuModel]->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY));
-  [[zoomItem_ viewWithTag:IDC_ZOOM_PERCENT_DISPLAY] setTitle:title];
-
-  NSImage* icon = [self wrenchMenuModel]->browser()->window()->IsFullscreen() ?
-      [NSImage imageNamed:NSImageNameExitFullScreenTemplate] :
-          [NSImage imageNamed:NSImageNameEnterFullScreenTemplate];
-  [zoomFullScreen_ setImage:icon];
-}
-
-- (void)menuDidClose:(NSMenu*)menu {
-  // When the menu is closed, acknowledge the background pages so the badges go
-  // away.
-  BackgroundPageTracker::GetInstance()->AcknowledgeBackgroundPages();
-}
-
-// Used to dispatch commands from the Wrench menu. The custom items within the
-// menu cannot be hooked up directly to First Responder because the window in
-// which the controls reside is not the BrowserWindowController, but a
-// NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system.
-- (IBAction)dispatchWrenchMenuCommand:(id)sender {
-  NSInteger tag = [sender tag];
-  if (sender == zoomPlus_ || sender == zoomMinus_) {
-    // Do a direct dispatch rather than scheduling on the outermost run loop,
-    // which would not get hit until after the menu had closed.
-    [self performCommandDispatch:[NSNumber numberWithInt:tag]];
-
-    // The zoom buttons should not close the menu if opened sticky.
-    if ([sender respondsToSelector:@selector(isTracking)] &&
-        [sender performSelector:@selector(isTracking)]) {
-      [menu_ cancelTracking];
-    }
-  } else {
-    // The custom views within the Wrench menu are abnormal and keep the menu
-    // open after a target-action.  Close the menu manually.
-    [menu_ cancelTracking];
-    [self dispatchCommandInternal:tag];
-  }
-}
-
-- (void)dispatchCommandInternal:(NSInteger)tag {
-  // Executing certain commands from the nested run loop of the menu can lead
-  // to wonky behavior (e.g. http://crbug.com/49716). To avoid this, schedule
-  // the dispatch on the outermost run loop.
-  [self performSelector:@selector(performCommandDispatch:)
-             withObject:[NSNumber numberWithInt:tag]
-             afterDelay:0.0];
-}
-
-// Used to perform the actual dispatch on the outermost runloop.
-- (void)performCommandDispatch:(NSNumber*)tag {
-  [self wrenchMenuModel]->ExecuteCommand([tag intValue]);
-}
-
-- (WrenchMenuModel*)wrenchMenuModel {
-  return static_cast<WrenchMenuModel*>(model_);
-}
-
-// Fit the localized strings into the Cut/Copy/Paste control, then resize the
-// whole menu item accordingly.
-- (void)adjustPositioning {
-  const CGFloat kButtonPadding = 12;
-  CGFloat delta = 0;
-
-  // Go through the three buttons from right-to-left, adjusting the size to fit
-  // the localized strings while keeping them all aligned on their horizontal
-  // edges.
-  const size_t kAdjustViewCount = 3;
-  NSButton* views[kAdjustViewCount] = { editPaste_, editCopy_, editCut_ };
-  for (size_t i = 0; i < kAdjustViewCount; ++i) {
-    NSButton* button = views[i];
-    CGFloat originalWidth = NSWidth([button frame]);
-
-    // Do not let |-sizeToFit| change the height of the button.
-    NSSize size = [button frame].size;
-    [button sizeToFit];
-    size.width = [button frame].size.width + kButtonPadding;
-    [button setFrameSize:size];
-
-    CGFloat newWidth = size.width;
-    delta += newWidth - originalWidth;
-
-    NSRect frame = [button frame];
-    frame.origin.x -= delta;
-    [button setFrame:frame];
-  }
-
-  // Resize the menu item by the total amound the buttons changed so that the
-  // spacing between the buttons and the title remains the same.
-  NSRect itemFrame = [editItem_ frame];
-  itemFrame.size.width += delta;
-  [editItem_ setFrame:itemFrame];
-
-  // Also resize the superview of the buttons, which is an NSView used to slide
-  // when the item title is too big and GTM resizes it.
-  NSRect parentFrame = [[editCut_ superview] frame];
-  parentFrame.size.width += delta;
-  parentFrame.origin.x -= delta;
-  [[editCut_ superview] setFrame:parentFrame];
-}
-
-- (NSButton*)zoomDisplay {
-  return zoomDisplay_;
-}
-
-@end  // @implementation WrenchMenuController
diff --git a/chrome/browser/ui/cocoa/wrench_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/wrench_menu_controller_unittest.mm
deleted file mode 100644
index 42be865..0000000
--- a/chrome/browser/ui/cocoa/wrench_menu_controller_unittest.mm
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/scoped_nsobject.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/ui/cocoa/browser_test_helper.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/toolbar_controller.h"
-#import "chrome/browser/ui/cocoa/wrench_menu_controller.h"
-#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
-#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-// Override to avoid dealing with run loops in the testing environment.
-@implementation WrenchMenuController (UnitTesting)
-- (void)dispatchCommandInternal:(NSInteger)tag {
-  [self wrenchMenuModel]->ExecuteCommand(tag);
-}
-@end
-
-
-namespace {
-
-class MockWrenchMenuModel : public WrenchMenuModel {
- public:
-  MockWrenchMenuModel() : WrenchMenuModel() {}
-  ~MockWrenchMenuModel() {
-    // This dirty, ugly hack gets around a bug in the test. In
-    // ~WrenchMenuModel(), there's a call to TabstripModel::RemoveObserver(this)
-    // which mysteriously leads to this crash: http://crbug.com/49206 .  It
-    // seems that the vector of observers is getting hosed somewhere between
-    // |-[ToolbarController dealloc]| and ~MockWrenchMenuModel(). This line
-    // short-circuits the parent destructor to avoid this crash.
-    tabstrip_model_ = NULL;
-  }
-  MOCK_METHOD1(ExecuteCommand, void(int command_id));
-};
-
-class WrenchMenuControllerTest : public CocoaTest {
- public:
-  void SetUp() {
-    Browser* browser = helper_.browser();
-    resize_delegate_.reset([[ViewResizerPong alloc] init]);
-    toolbar_controller_.reset(
-        [[ToolbarController alloc] initWithModel:browser->toolbar_model()
-                                        commands:browser->command_updater()
-                                         profile:helper_.profile()
-                                         browser:browser
-                                  resizeDelegate:resize_delegate_.get()]);
-    EXPECT_TRUE([toolbar_controller_ view]);
-    NSView* parent = [test_window() contentView];
-    [parent addSubview:[toolbar_controller_ view]];
-  }
-
-  WrenchMenuController* controller() {
-    return [toolbar_controller_ wrenchMenuController];
-  }
-
-  BrowserTestHelper helper_;
-  scoped_nsobject<ViewResizerPong> resize_delegate_;
-  MockWrenchMenuModel fake_model_;
-  scoped_nsobject<ToolbarController> toolbar_controller_;
-};
-
-TEST_F(WrenchMenuControllerTest, Initialized) {
-  EXPECT_TRUE([controller() menu]);
-  EXPECT_GE([[controller() menu] numberOfItems], 5);
-}
-
-TEST_F(WrenchMenuControllerTest, DispatchSimple) {
-  scoped_nsobject<NSButton> button([[NSButton alloc] init]);
-  [button setTag:IDC_ZOOM_PLUS];
-
-  // Set fake model to test dispatching.
-  EXPECT_CALL(fake_model_, ExecuteCommand(IDC_ZOOM_PLUS));
-  [controller() setModel:&fake_model_];
-
-  [controller() dispatchWrenchMenuCommand:button.get()];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/crypto_module_password_dialog.h b/chrome/browser/ui/crypto_module_password_dialog.h
new file mode 100644
index 0000000..a6d9052
--- /dev/null
+++ b/chrome/browser/ui/crypto_module_password_dialog.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_CRYPTO_MODULE_PASSWORD_DIALOG_H_
+#define CHROME_BROWSER_UI_CRYPTO_MODULE_PASSWORD_DIALOG_H_
+#pragma once
+
+#include <string>
+
+#include "base/callback.h"
+
+namespace base {
+class CryptoModuleBlockingPasswordDelegate;
+}
+
+namespace net {
+class CryptoModule;
+class X509Certificate;
+}
+
+namespace browser {
+
+// An enum to describe the reason for the password request.
+enum CryptoModulePasswordReason {
+  kCryptoModulePasswordKeygen,
+  kCryptoModulePasswordCertEnrollment,
+  kCryptoModulePasswordClientAuth,
+  kCryptoModulePasswordCertImport,
+  kCryptoModulePasswordCertExport,
+};
+
+typedef Callback1<const char*>::Type CryptoModulePasswordCallback;
+
+// Display a dialog, prompting the user to authenticate to unlock
+// |module|. |reason| describes the purpose of the authentication and
+// affects the message displayed in the dialog. |server| is the name
+// of the server which requested the access.
+void ShowCryptoModulePasswordDialog(const std::string& module_name,
+                            bool retry,
+                            CryptoModulePasswordReason reason,
+                            const std::string& server,
+                            CryptoModulePasswordCallback* callback);
+
+// Returns a CryptoModuleBlockingPasswordDelegate to open a dialog and block
+// until returning. Should only be used on a worker thread.
+base::CryptoModuleBlockingPasswordDelegate*
+    NewCryptoModuleBlockingDialogDelegate(
+        CryptoModulePasswordReason reason,
+        const std::string& server);
+
+// Asynchronously unlock |module|, if necessary.  |callback| is called when done
+// (regardless if module was successfully unlocked or not).  Should only be
+// called on UI thread.
+void UnlockSlotIfNecessary(net::CryptoModule* module,
+                           browser::CryptoModulePasswordReason reason,
+                           const std::string& server,
+                           Callback0::Type* callback);
+
+// Asynchronously unlock the |cert|'s module, if necessary.  |callback| is
+// called when done (regardless if module was successfully unlocked or not).
+// Should only be called on UI thread.
+void UnlockCertSlotIfNecessary(net::X509Certificate* cert,
+                               browser::CryptoModulePasswordReason reason,
+                               const std::string& server,
+                               Callback0::Type* callback);
+
+}  // namespace browser
+
+#endif  // CHROME_BROWSER_UI_CRYPTO_MODULE_PASSWORD_DIALOG_H_
diff --git a/chrome/browser/ui/crypto_module_password_dialog_nss.cc b/chrome/browser/ui/crypto_module_password_dialog_nss.cc
new file mode 100644
index 0000000..d0b1357
--- /dev/null
+++ b/chrome/browser/ui/crypto_module_password_dialog_nss.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/crypto_module_password_dialog.h"
+
+#include <pk11pub.h>
+
+#include "base/logging.h"
+#include "chrome/browser/browser_thread.h"
+#include "net/base/crypto_module.h"
+#include "net/base/x509_certificate.h"
+
+namespace {
+
+// Basically an asynchronous implementation of NSS's PK11_DoPassword.
+// Note: This currently handles only the simple case.  See the TODOs in
+// GotPassword for what is yet unimplemented.
+class SlotUnlocker {
+ public:
+  SlotUnlocker(net::CryptoModule* module,
+               browser::CryptoModulePasswordReason reason,
+               const std::string& host,
+               Callback0::Type* callback);
+
+  void Start();
+
+ private:
+  void GotPassword(const char* password);
+  void Done();
+
+  scoped_refptr<net::CryptoModule> module_;
+  browser::CryptoModulePasswordReason reason_;
+  std::string host_;
+  Callback0::Type* callback_;
+  PRBool retry_;
+};
+
+SlotUnlocker::SlotUnlocker(net::CryptoModule* module,
+                           browser::CryptoModulePasswordReason reason,
+                           const std::string& host,
+                           Callback0::Type* callback)
+    : module_(module),
+      reason_(reason),
+      host_(host),
+      callback_(callback),
+      retry_(PR_FALSE) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+void SlotUnlocker::Start() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  ShowCryptoModulePasswordDialog(
+      module_->GetTokenName(),
+      retry_,
+      reason_,
+      host_,
+      NewCallback(this, &SlotUnlocker::GotPassword));
+}
+
+void SlotUnlocker::GotPassword(const char* password) {
+  // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass.
+  // Do we need it?
+  // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c#577
+
+  if (!password) {
+    // User cancelled entering password.  Oh well.
+    Done();
+    return;
+  }
+
+  // TODO(mattm): handle protectedAuthPath
+  SECStatus rv = PK11_CheckUserPassword(module_->os_module_handle(),
+                                        password);
+  if (rv == SECWouldBlock) {
+    // Incorrect password.  Try again.
+    retry_ = PR_TRUE;
+    Start();
+    return;
+  }
+
+  // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on
+  // non-friendly slots.  How important is that?
+
+  // Correct password (SECSuccess) or too many attempts/other failure
+  // (SECFailure).  Either way we're done.
+  Done();
+}
+
+void SlotUnlocker::Done() {
+  callback_->Run();
+  delete this;
+}
+
+}  // namespace
+
+namespace browser {
+
+void UnlockSlotIfNecessary(net::CryptoModule* module,
+                           browser::CryptoModulePasswordReason reason,
+                           const std::string& host,
+                           Callback0::Type* callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
+  if (PK11_NeedLogin(module->os_module_handle()) &&
+      !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */)) {
+    (new SlotUnlocker(module, reason, host, callback))->Start();
+  } else {
+    callback->Run();
+  }
+}
+
+void UnlockCertSlotIfNecessary(net::X509Certificate* cert,
+                               browser::CryptoModulePasswordReason reason,
+                               const std::string& host,
+                               Callback0::Type* callback) {
+  scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle(
+      cert->os_cert_handle()->slot));
+  UnlockSlotIfNecessary(module.get(), reason, host, callback);
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/crypto_module_password_dialog_openssl.cc b/chrome/browser/ui/crypto_module_password_dialog_openssl.cc
new file mode 100644
index 0000000..b5c40c5
--- /dev/null
+++ b/chrome/browser/ui/crypto_module_password_dialog_openssl.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/crypto_module_password_dialog.h"
+
+#include "base/logging.h"
+
+namespace browser {
+
+void UnlockSlotIfNecessary(net::CryptoModule* module,
+                           browser::CryptoModulePasswordReason reason,
+                           const std::string& host,
+                           Callback0::Type* callback) {
+  // TODO(bulach): implement me.
+  NOTREACHED();
+}
+
+void UnlockCertSlotIfNecessary(net::X509Certificate* cert,
+                               browser::CryptoModulePasswordReason reason,
+                               const std::string& host,
+                               Callback0::Type* callback) {
+  // TODO(bulach): implement me.
+  NOTREACHED();
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/find_bar/find_backend_unittest.cc b/chrome/browser/ui/find_bar/find_backend_unittest.cc
index c4ec58b..d40a968 100644
--- a/chrome/browser/ui/find_bar/find_backend_unittest.cc
+++ b/chrome/browser/ui/find_bar/find_backend_unittest.cc
@@ -5,13 +5,15 @@
 #include "base/string16.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/renderer_host/test/test_render_view_host.h"
 #include "chrome/browser/tab_contents/test_tab_contents.h"
 #include "chrome/browser/ui/find_bar/find_bar_state.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/testing_profile.h"
 
-typedef RenderViewHostTestHarness FindBackendTest;
+typedef TabContentsWrapperTestHarness FindBackendTest;
 
 namespace {
 
@@ -24,18 +26,21 @@
 // This test takes two TabContents objects, searches in both of them and
 // tests the internal state for find_text and find_prepopulate_text.
 TEST_F(FindBackendTest, InternalState) {
+  FindManager* find_manager = contents_wrapper()->GetFindManager();
   // Initial state for the TabContents is blank strings.
   EXPECT_EQ(string16(), FindPrepopulateText(contents()));
-  EXPECT_EQ(string16(), contents()->find_text());
+  EXPECT_EQ(string16(), find_manager->find_text());
 
   // Get another TabContents object ready.
-  TestTabContents contents2(profile_.get(), NULL);
+  TestTabContents* contents2 = new TestTabContents(profile_.get(), NULL);
+  TabContentsWrapper wrapper2(contents2);
+  FindManager* find_manager2 = wrapper2.GetFindManager();
 
   // No search has still been issued, strings should be blank.
   EXPECT_EQ(string16(), FindPrepopulateText(contents()));
-  EXPECT_EQ(string16(), contents()->find_text());
-  EXPECT_EQ(string16(), FindPrepopulateText(&contents2));
-  EXPECT_EQ(string16(), contents2.find_text());
+  EXPECT_EQ(string16(), find_manager->find_text());
+  EXPECT_EQ(string16(), FindPrepopulateText(contents2));
+  EXPECT_EQ(string16(), find_manager2->find_text());
 
   string16 search_term1 = ASCIIToUTF16(" I had a 401K    ");
   string16 search_term2 = ASCIIToUTF16(" but the economy ");
@@ -43,34 +48,34 @@
 
   // Start searching in the first TabContents, searching forwards but not case
   // sensitive (as indicated by the last two params).
-  contents()->StartFinding(search_term1, true, false);
+  find_manager->StartFinding(search_term1, true, false);
 
   // Pre-populate string should always match between the two, but find_text
   // should not.
   EXPECT_EQ(search_term1, FindPrepopulateText(contents()));
-  EXPECT_EQ(search_term1, contents()->find_text());
-  EXPECT_EQ(search_term1, FindPrepopulateText(&contents2));
-  EXPECT_EQ(string16(), contents2.find_text());
+  EXPECT_EQ(search_term1, find_manager->find_text());
+  EXPECT_EQ(search_term1, FindPrepopulateText(contents2));
+  EXPECT_EQ(string16(), find_manager2->find_text());
 
   // Now search in the other TabContents, searching forwards but not case
   // sensitive (as indicated by the last two params).
-  contents2.StartFinding(search_term2, true, false);
+  find_manager2->StartFinding(search_term2, true, false);
 
   // Again, pre-populate string should always match between the two, but
   // find_text should not.
   EXPECT_EQ(search_term2, FindPrepopulateText(contents()));
-  EXPECT_EQ(search_term1, contents()->find_text());
-  EXPECT_EQ(search_term2, FindPrepopulateText(&contents2));
-  EXPECT_EQ(search_term2, contents2.find_text());
+  EXPECT_EQ(search_term1, find_manager->find_text());
+  EXPECT_EQ(search_term2, FindPrepopulateText(contents2));
+  EXPECT_EQ(search_term2, find_manager2->find_text());
 
   // Search again in the first TabContents, searching forwards but not case
   // sensitive (as indicated by the last two params).
-  contents()->StartFinding(search_term3, true, false);
+  find_manager->StartFinding(search_term3, true, false);
 
   // Once more, pre-populate string should always match between the two, but
   // find_text should not.
   EXPECT_EQ(search_term3, FindPrepopulateText(contents()));
-  EXPECT_EQ(search_term3, contents()->find_text());
-  EXPECT_EQ(search_term3, FindPrepopulateText(&contents2));
-  EXPECT_EQ(search_term2, contents2.find_text());
+  EXPECT_EQ(search_term3, find_manager->find_text());
+  EXPECT_EQ(search_term3, FindPrepopulateText(contents2));
+  EXPECT_EQ(search_term2, find_manager2->find_text());
 }
diff --git a/chrome/browser/ui/find_bar/find_bar.h b/chrome/browser/ui/find_bar/find_bar.h
index 66d6618..c8d0f15 100644
--- a/chrome/browser/ui/find_bar/find_bar.h
+++ b/chrome/browser/ui/find_bar/find_bar.h
@@ -11,7 +11,7 @@
 #pragma once
 
 #include "base/string16.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class FindBarController;
 class FindBarTesting;
diff --git a/chrome/browser/ui/find_bar/find_bar_controller.cc b/chrome/browser/ui/find_bar/find_bar_controller.cc
index 4f637e8..b030a0f 100644
--- a/chrome/browser/ui/find_bar/find_bar_controller.cc
+++ b/chrome/browser/ui/find_bar/find_bar_controller.cc
@@ -11,10 +11,11 @@
 #include "chrome/browser/tab_contents/navigation_entry.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_state.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 // The minimum space between the FindInPage window and the search result.
 static const int kMinFindWndDistanceFromSelection = 5;
@@ -30,12 +31,14 @@
 }
 
 void FindBarController::Show() {
+  FindManager* find_manager = tab_contents_->GetFindManager();
+
   // Only show the animation if we're not already showing a find bar for the
   // selected TabContents.
-  if (!tab_contents_->find_ui_active()) {
+  if (!find_manager->find_ui_active()) {
     MaybeSetPrepopulateText();
 
-    tab_contents_->set_find_ui_active(true);
+    find_manager->set_find_ui_active(true);
     find_bar_->Show(true);
   }
   find_bar_->SetFocusAndSelection();
@@ -47,20 +50,22 @@
   // |tab_contents_| can be NULL for a number of reasons, for example when the
   // tab is closing. We must guard against that case. See issue 8030.
   if (tab_contents_) {
+    FindManager* find_manager = tab_contents_->GetFindManager();
+
     // When we hide the window, we need to notify the renderer that we are done
     // for now, so that we can abort the scoping effort and clear all the
     // tickmarks and highlighting.
-    tab_contents_->StopFinding(action);
+    find_manager->StopFinding(action);
 
     if (action != kKeepSelection)
-      find_bar_->ClearResults(tab_contents_->find_result());
+      find_bar_->ClearResults(find_manager->find_result());
 
     // When we get dismissed we restore the focus to where it belongs.
     find_bar_->RestoreSavedFocus();
   }
 }
 
-void FindBarController::ChangeTabContents(TabContents* contents) {
+void FindBarController::ChangeTabContents(TabContentsWrapper* contents) {
   if (tab_contents_) {
     registrar_.RemoveAll();
     find_bar_->StopAnimation();
@@ -71,7 +76,7 @@
   // Hide any visible find window from the previous tab if NULL |tab_contents|
   // is passed in or if the find UI is not active in the new tab.
   if (find_bar_->IsFindBarVisible() &&
-      (!tab_contents_ || !tab_contents_->find_ui_active())) {
+      (!tab_contents_ || !tab_contents_->GetFindManager()->find_ui_active())) {
     find_bar_->Hide(false);
   }
 
@@ -79,13 +84,13 @@
     return;
 
   registrar_.Add(this, NotificationType::FIND_RESULT_AVAILABLE,
-                 Source<TabContents>(tab_contents_));
+                 Source<TabContents>(tab_contents_->tab_contents()));
   registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
                  Source<NavigationController>(&tab_contents_->controller()));
 
   MaybeSetPrepopulateText();
 
-  if (tab_contents_->find_ui_active()) {
+  if (tab_contents_->GetFindManager()->find_ui_active()) {
     // A tab with a visible find bar just got selected and we need to show the
     // find bar but without animation since it was already animated into its
     // visible state. We also want to reset the window location so that
@@ -103,15 +108,16 @@
 void FindBarController::Observe(NotificationType type,
                                 const NotificationSource& source,
                                 const NotificationDetails& details) {
+  FindManager* find_manager = tab_contents_->GetFindManager();
   if (type == NotificationType::FIND_RESULT_AVAILABLE) {
     // Don't update for notifications from TabContentses other than the one we
     // are actively tracking.
-    if (Source<TabContents>(source).ptr() == tab_contents_) {
+    if (Source<TabContents>(source).ptr() == tab_contents_->tab_contents()) {
       UpdateFindBarForCurrentResult();
-      if (tab_contents_->find_result().final_update() &&
-          tab_contents_->find_result().number_of_matches() == 0) {
-        const string16& last_search = tab_contents_->previous_find_text();
-        const string16& current_search = tab_contents_->find_text();
+      if (find_manager->find_result().final_update() &&
+          find_manager->find_result().number_of_matches() == 0) {
+        const string16& last_search = find_manager->previous_find_text();
+        const string16& current_search = find_manager->find_text();
         if (last_search.find(current_search) != 0)
           find_bar_->AudibleAlert();
       }
@@ -133,7 +139,7 @@
         } else {
           // On Reload we want to make sure FindNext is converted to a full Find
           // to make sure highlights for inactive matches are repainted.
-          tab_contents_->set_find_op_aborted(true);
+          find_manager->set_find_op_aborted(true);
         }
       }
     }
@@ -181,7 +187,8 @@
 }
 
 void FindBarController::UpdateFindBarForCurrentResult() {
-  const FindNotificationDetails& find_result = tab_contents_->find_result();
+  FindManager* find_manager = tab_contents_->GetFindManager();
+  const FindNotificationDetails& find_result = find_manager->find_result();
 
   // Avoid bug 894389: When a new search starts (and finds something) it reports
   // an interim match count result of 1 before the scoping effort starts. This
@@ -198,7 +205,7 @@
     last_reported_matchcount_ = find_result.number_of_matches();
   }
 
-  find_bar_->UpdateUIForFindResult(find_result, tab_contents_->find_text());
+  find_bar_->UpdateUIForFindResult(find_result, find_manager->find_text());
 }
 
 void FindBarController::MaybeSetPrepopulateText() {
@@ -206,9 +213,10 @@
   // Find out what we should show in the find text box. Usually, this will be
   // the last search in this tab, but if no search has been issued in this tab
   // we use the last search string (from any tab).
-  string16 find_string = tab_contents_->find_text();
+  FindManager* find_manager = tab_contents_->GetFindManager();
+  string16 find_string = find_manager->find_text();
   if (find_string.empty())
-    find_string = tab_contents_->previous_find_text();
+    find_string = find_manager->previous_find_text();
   if (find_string.empty()) {
     find_string =
         FindBarState::GetLastPrepopulateText(tab_contents_->profile());
diff --git a/chrome/browser/ui/find_bar/find_bar_controller.h b/chrome/browser/ui/find_bar/find_bar_controller.h
index 1c3a1d6..75dce1f 100644
--- a/chrome/browser/ui/find_bar/find_bar_controller.h
+++ b/chrome/browser/ui/find_bar/find_bar_controller.h
@@ -16,7 +16,7 @@
 }
 
 class FindBar;
-class TabContents;
+class TabContentsWrapper;
 
 class FindBarController : public NotificationObserver {
  public:
@@ -38,12 +38,12 @@
   // Ends the current session.
   void EndFindSession(SelectionAction action);
 
-  // Accessor for the attached TabContents.
-  TabContents* tab_contents() const { return tab_contents_; }
+  // Accessor for the attached TabContentsWrapper.
+  TabContentsWrapper* tab_contents() const { return tab_contents_; }
 
   // Changes the TabContents that this FindBar is attached to. This occurs when
   // the user switches tabs in the Browser window. |contents| can be NULL.
-  void ChangeTabContents(TabContents* contents);
+  void ChangeTabContents(TabContentsWrapper* contents);
 
   // Overridden from NotificationObserver:
   virtual void Observe(NotificationType type,
@@ -76,8 +76,8 @@
 
   scoped_ptr<FindBar> find_bar_;
 
-  // The TabContents we are currently associated with.  Can be NULL.
-  TabContents* tab_contents_;
+  // The TabContentsWrapper we are currently associated with.  Can be NULL.
+  TabContentsWrapper* tab_contents_;
 
   // The last match count we reported to the user. This is used by
   // UpdateFindBarForCurrentResult to avoid flickering.
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index 4923ea7..5329bda 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/keyboard_codes.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -16,18 +15,21 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/test/test_server.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/find_bar_host.h"
+#include "chrome/browser/ui/views/find_bar_host.h"
 #include "views/focus/focus_manager.h"
 #elif defined(TOOLKIT_GTK)
-#include "chrome/browser/gtk/slide_animator_gtk.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
 #elif defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/find_bar_bridge.h"
+#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
 #endif
 
 const std::string kSimplePage = "404_is_enough_for_us.html";
@@ -36,6 +38,7 @@
 const std::string kUserSelectPage = "files/find_in_page/user-select.html";
 const std::string kCrashPage = "files/find_in_page/crash_1341577.html";
 const std::string kTooFewMatchesPage = "files/find_in_page/bug_1155639.html";
+const std::string kLongTextareaPage = "files/find_in_page/large_textarea.html";
 const std::string kEndState = "files/find_in_page/end_state.html";
 const std::string kPrematureEnd = "files/find_in_page/premature_end.html";
 const std::string kMoveIfOver = "files/find_in_page/move_if_obscuring.html";
@@ -115,7 +118,7 @@
 
 // Platform independent FindInPage that takes |const wchar_t*|
 // as an input.
-int FindInPageWchar(TabContents* tab,
+int FindInPageWchar(TabContentsWrapper* tab,
                     const wchar_t* search_str,
                     bool forward,
                     bool case_sensitive,
@@ -135,7 +138,7 @@
 
   // Try incremental search (mimicking user typing in).
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(18, FindInPageWchar(tab, L"g",
                                 kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(1, ordinal);
@@ -227,12 +230,12 @@
   GURL url = test_server()->GetURL(kEndState);
   ui_test_utils::NavigateToURL(browser(), url);
 
-  TabContents* tab_contents = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab_contents = browser()->GetSelectedTabContentsWrapper();
   ASSERT_TRUE(NULL != tab_contents);
 
   // Verify that nothing has focus.
   std::string result;
-  ASSERT_TRUE(FocusedOnPage(tab_contents, &result));
+  ASSERT_TRUE(FocusedOnPage(tab_contents->tab_contents(), &result));
   ASSERT_STREQ("{nothing focused}", result.c_str());
 
   // Search for a text that exists within a link on the page.
@@ -242,10 +245,11 @@
   EXPECT_EQ(1, ordinal);
 
   // End the find session, which should set focus to the link.
-  tab_contents->StopFinding(FindBarController::kKeepSelection);
+  tab_contents->
+      GetFindManager()->StopFinding(FindBarController::kKeepSelection);
 
   // Verify that the link is focused.
-  ASSERT_TRUE(FocusedOnPage(tab_contents, &result));
+  ASSERT_TRUE(FocusedOnPage(tab_contents->tab_contents(), &result));
   EXPECT_STREQ("link1", result.c_str());
 
   // Search for a text that exists within a link on the page.
@@ -261,10 +265,11 @@
       &result));
 
   // End the find session.
-  tab_contents->StopFinding(FindBarController::kKeepSelection);
+  tab_contents->
+      GetFindManager()->StopFinding(FindBarController::kKeepSelection);
 
   // Verify that link2 is not focused.
-  ASSERT_TRUE(FocusedOnPage(tab_contents, &result));
+  ASSERT_TRUE(FocusedOnPage(tab_contents->tab_contents(), &result));
   EXPECT_STREQ("", result.c_str());
 }
 
@@ -279,7 +284,7 @@
 
   // Search for 'o', which should make the first item active and return
   // '1 in 3' (1st ordinal of a total of 3 matches).
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   int ordinal = 0;
   EXPECT_EQ(3, FindInPageWchar(tab, L"o",
                                kFwd, kIgnoreCase, &ordinal));
@@ -316,13 +321,11 @@
   GURL url = test_server()->GetURL(kSelectChangesOrdinal);
   ui_test_utils::NavigateToURL(browser(), url);
 
-  TabContents* tab_contents = browser()->GetSelectedTabContents();
-  ASSERT_TRUE(NULL != tab_contents);
-
   // Search for a text that exists within a link on the page.
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
+  ASSERT_TRUE(NULL != tab);
   int ordinal = 0;
-  EXPECT_EQ(4, FindInPageWchar(tab_contents,
+  EXPECT_EQ(4, FindInPageWchar(tab,
                                L"google",
                                kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(1, ordinal);
@@ -330,7 +333,7 @@
   // Move the selection to link 1, after searching.
   std::string result;
   ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
-      tab_contents->render_view_host(),
+      tab->render_view_host(),
       L"",
       L"window.domAutomationController.send(selectLink1());",
       &result));
@@ -343,7 +346,7 @@
   EXPECT_EQ(3, ordinal);
 
   // End the find session.
-  tab_contents->StopFinding(FindBarController::kKeepSelection);
+  tab->GetFindManager()->StopFinding(FindBarController::kKeepSelection);
 }
 
 // This test loads a page with frames and makes sure the ordinal returned makes
@@ -357,7 +360,7 @@
 
   // Search for 'a', which should make the first item active and return
   // '1 in 7' (1st ordinal of a total of 7 matches).
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   int ordinal = 0;
   EXPECT_EQ(7,
             FindInPageWchar(tab, L"a", kFwd, kIgnoreCase, &ordinal));
@@ -408,7 +411,7 @@
 
   // Search for 'goa' three times (6 matches on page).
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(6, FindInPageWchar(tab, L"goa",
                                kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(1, ordinal);
@@ -429,7 +432,7 @@
 }
 
 // Load a page with no selectable text and make sure we don't crash.
-IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindUnSelectableText) {
+IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindUnselectableText) {
   ASSERT_TRUE(test_server()->Start());
 
   // First we navigate to our page.
@@ -437,12 +440,9 @@
   ui_test_utils::NavigateToURL(browser(), url);
 
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
-  // The search string is present but doesn't qualify to be found
-  EXPECT_EQ(0, FindInPageWchar(tab, L"text",
-                               kFwd, kIgnoreCase, &ordinal));
-  // With zero results there should be no current selection.
-  EXPECT_EQ(0, ordinal);
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
+  EXPECT_EQ(1, FindInPageWchar(tab, L"text", kFwd, kIgnoreCase, &ordinal));
+  EXPECT_EQ(1, ordinal);
 }
 
 // Try to reproduce the crash seen in issue 1341577.
@@ -463,7 +463,7 @@
   // TODO(jungshik): According to a native Malayalam speaker, it's ok not
   // to find U+0D4C. Still need to investigate further this issue.
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   FindInPageWchar(tab, L"\u0D4C", kFwd, kIgnoreCase, &ordinal);
   FindInPageWchar(tab, L"\u0D4C", kFwd, kIgnoreCase, &ordinal);
 
@@ -487,7 +487,7 @@
 
   // This used to crash the tab.
   int ordinal = 0;
-  EXPECT_EQ(0, FindInPageWchar(browser()->GetSelectedTabContents(),
+  EXPECT_EQ(0, FindInPageWchar(browser()->GetSelectedTabContentsWrapper(),
                                L"s", kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(0, ordinal);
 }
@@ -510,12 +510,31 @@
   // This string appears 5 times at the bottom of a long page. If Find restarts
   // properly after a timeout, it will find 5 matches, not just 1.
   int ordinal = 0;
-  EXPECT_EQ(5, FindInPageWchar(browser()->GetSelectedTabContents(),
+  EXPECT_EQ(5, FindInPageWchar(browser()->GetSelectedTabContentsWrapper(),
                                L"008.xml",
                                kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(1, ordinal);
 }
 
+// Make sure we don't get into an infinite loop when text box contains very
+// large amount of text.
+IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindRestarts_Issue70505) {
+  ASSERT_TRUE(test_server()->Start());
+
+  // First we navigate to our page.
+  GURL url = test_server()->GetURL(kLongTextareaPage);
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // If this test hangs on the FindInPage call, then it might be a regression
+  // such as the one found in issue http://crbug.com/70505.
+  int ordinal = 0;
+  FindInPageWchar(browser()->GetSelectedTabContentsWrapper(),
+                  L"a", kFwd, kIgnoreCase, &ordinal);
+  EXPECT_EQ(1, ordinal);
+  // TODO(finnur): We cannot reliably get the matchcount for this Find call
+  // until we fix issue http://crbug.com/71176.
+}
+
 // This tests bug 11761: FindInPage terminates search prematurely.
 // This test is not expected to pass until bug 11761 is fixed.
 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest,
@@ -526,7 +545,7 @@
   GURL url = test_server()->GetURL(kPrematureEnd);
   ui_test_utils::NavigateToURL(browser(), url);
 
-  TabContents* tab_contents = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab_contents = browser()->GetSelectedTabContentsWrapper();
   ASSERT_TRUE(NULL != tab_contents);
 
   // Search for a text that exists within a link on the page.
@@ -644,7 +663,7 @@
 
   // Search for 'Chromium' which the Find box is obscuring.
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   int index = 0;
   for (; index < kMoveIterations; ++index) {
     EXPECT_EQ(kMoveIterations, FindInPageWchar(tab, L"Chromium",
@@ -690,7 +709,7 @@
 
   // Search for 'no_match'. No matches should be found.
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(0, FindInPageWchar(tab, L"no_match",
                                kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(0, ordinal);
@@ -739,7 +758,7 @@
           browser()->window()->GetNativeHandle());
 
   // See where Escape is registered.
-  views::Accelerator escape(app::VKEY_ESCAPE, false, false, false);
+  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
   views::AcceleratorTarget* old_target =
       focus_manager->GetCurrentTargetForAccelerator(escape);
   EXPECT_TRUE(old_target != NULL);
@@ -778,13 +797,14 @@
   // simulating keypresses here for searching for something and pressing
   // backspace, but that's been proven flaky in the past, so we go straight to
   // tab_contents.
-  TabContents* tab_contents = browser()->GetSelectedTabContents();
+  FindManager* find_manager =
+      browser()->GetSelectedTabContentsWrapper()->GetFindManager();
   // Stop the (non-existing) find operation, and clear the selection (which
   // signals the UI is still active).
-  tab_contents->StopFinding(FindBarController::kClearSelection);
+  find_manager->StopFinding(FindBarController::kClearSelection);
   // Make sure the Find UI flag hasn't been cleared, it must be so that the UI
   // still responds to browser window resizing.
-  ASSERT_TRUE(tab_contents->find_ui_active());
+  ASSERT_TRUE(find_manager->find_ui_active());
 }
 
 // Make sure F3 works after you FindNext a couple of times and end the Find
@@ -798,7 +818,7 @@
 
   // Search for 'page'. Should have 1 match.
   int ordinal = 0;
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(tab, L"page", kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(1, ordinal);
 
@@ -829,7 +849,7 @@
 
   // Find "Default".
   int ordinal = 0;
-  TabContents* tab1 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab1 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(tab1, L"Default", kFwd, kIgnoreCase, &ordinal));
 
   // Create a second tab.
@@ -841,7 +861,7 @@
   params.tabstrip_add_types = TabStripModel::ADD_NONE;
   browser::Navigate(&params);
   browser()->SelectTabContentsAt(1, false);
-  TabContents* tab2 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab2 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_NE(tab1, tab2);
 
   // Find "given".
@@ -853,7 +873,7 @@
       FindBarController::kKeepSelection);
   // Simulate F3.
   ui_test_utils::FindInPage(tab1, string16(), kFwd, kIgnoreCase, &ordinal);
-  EXPECT_EQ(tab1->find_text(), WideToUTF16(L"Default"));
+  EXPECT_EQ(tab1->GetFindManager()->find_text(), WideToUTF16(L"Default"));
 }
 
 // This tests that whenever you close and reopen the Find bar, it should show
@@ -872,7 +892,7 @@
 
   // Search for the word "page".
   int ordinal = 0;
-  TabContents* tab1 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab1 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(tab1, L"page", kFwd, kIgnoreCase, &ordinal));
 
   // Open the Find box.
@@ -911,13 +931,13 @@
 
   // Search for the word "page".
   int ordinal = 0;
-  TabContents* tab1 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab1 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(tab1, L"page", kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(ASCIIToUTF16("1 of 1"), GetMatchCountText());
 
   // Now create a second tab and load the same page.
   browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
-  TabContents* tab2 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab2 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_NE(tab1, tab2);
 
   // Open the Find box.
@@ -947,7 +967,7 @@
 
   // Search for the word "page".
   int ordinal = 0;
-  TabContents* tab1 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab1 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(tab1, L"page", kFwd, kIgnoreCase, &ordinal));
 
   // Open the Find box.
@@ -965,7 +985,7 @@
   params.tabstrip_add_types = TabStripModel::ADD_NONE;
   browser::Navigate(&params);
   browser()->SelectTabContentsAt(1, false);
-  TabContents* tab2 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab2 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_NE(tab1, tab2);
 
   // Search for the word "text".
@@ -1021,7 +1041,7 @@
 
   // Search for the word "page" in the normal browser tab.
   int ordinal = 0;
-  TabContents* tab1 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab1 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(tab1, L"page", kFwd, kIgnoreCase, &ordinal));
 
   // Open the Find box.
@@ -1045,7 +1065,8 @@
   EXPECT_EQ(ASCIIToUTF16("page"), GetFindBarTextForBrowser(incognito_browser));
 
   // Search for the word "text" in the incognito tab.
-  TabContents* incognito_tab = incognito_browser->GetSelectedTabContents();
+  TabContentsWrapper* incognito_tab =
+      incognito_browser->GetSelectedTabContentsWrapper();
   EXPECT_EQ(1, FindInPageWchar(incognito_tab, L"text",
                                kFwd, kIgnoreCase, &ordinal));
   EXPECT_EQ(ASCIIToUTF16("text"), GetFindBarTextForBrowser(incognito_browser));
@@ -1056,7 +1077,7 @@
 
   // Now open a new tab in the original (non-incognito) browser.
   browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
-  TabContents* tab2 = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab2 = browser()->GetSelectedTabContentsWrapper();
   EXPECT_NE(tab1, tab2);
 
   // Open the Find box and make sure it is prepopulated with the search term
@@ -1073,12 +1094,12 @@
   GURL url = test_server()->GetURL(kLinkPage);
   ui_test_utils::NavigateToURL(browser(), url);
 
-  TabContents* tab = browser()->GetSelectedTabContents();
+  TabContentsWrapper* tab = browser()->GetSelectedTabContentsWrapper();
   int ordinal = 0;
   FindInPageWchar(tab, L"link", kFwd, kIgnoreCase, &ordinal);
   EXPECT_EQ(ordinal, 1);
 
   // End the find session, click on the link.
-  tab->StopFinding(FindBarController::kActivateSelection);
+  tab->GetFindManager()->StopFinding(FindBarController::kActivateSelection);
   EXPECT_TRUE(ui_test_utils::WaitForNavigationInCurrentTab(browser()));
 }
diff --git a/chrome/browser/ui/find_bar/find_manager.cc b/chrome/browser/ui/find_bar/find_manager.cc
new file mode 100644
index 0000000..b02bad6
--- /dev/null
+++ b/chrome/browser/ui/find_bar/find_manager.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/find_bar/find_manager.h"
+
+#include <vector>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/ui/find_bar/find_bar_state.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/render_messages.h"
+
+// static
+int FindManager::find_request_id_counter_ = -1;
+
+FindManager::FindManager(TabContentsWrapper* tab_contents)
+    : tab_contents_(tab_contents),
+      find_ui_active_(false),
+      find_op_aborted_(false),
+      current_find_request_id_(find_request_id_counter_++),
+      last_search_case_sensitive_(false),
+      last_search_result_() {
+  DCHECK(tab_contents_);
+}
+
+FindManager::~FindManager() {
+}
+
+void FindManager::StartFinding(string16 search_string,
+                               bool forward_direction,
+                               bool case_sensitive) {
+  // If search_string is empty, it means FindNext was pressed with a keyboard
+  // shortcut so unless we have something to search for we return early.
+  if (search_string.empty() && find_text_.empty()) {
+    string16 last_search_prepopulate_text =
+        FindBarState::GetLastPrepopulateText(tab_contents_->profile());
+
+    // Try the last thing we searched for on this tab, then the last thing
+    // searched for on any tab.
+    if (!previous_find_text_.empty())
+      search_string = previous_find_text_;
+    else if (!last_search_prepopulate_text.empty())
+      search_string = last_search_prepopulate_text;
+    else
+      return;
+  }
+
+  // Keep track of the previous search.
+  previous_find_text_ = find_text_;
+
+  // This is a FindNext operation if we are searching for the same text again,
+  // or if the passed in search text is empty (FindNext keyboard shortcut). The
+  // exception to this is if the Find was aborted (then we don't want FindNext
+  // because the highlighting has been cleared and we need it to reappear). We
+  // therefore treat FindNext after an aborted Find operation as a full fledged
+  // Find.
+  bool find_next = (find_text_ == search_string || search_string.empty()) &&
+                   (last_search_case_sensitive_ == case_sensitive) &&
+                   !find_op_aborted_;
+  if (!find_next)
+    current_find_request_id_ = find_request_id_counter_++;
+
+  if (!search_string.empty())
+    find_text_ = search_string;
+  last_search_case_sensitive_ = case_sensitive;
+
+  find_op_aborted_ = false;
+
+  // Keep track of what the last search was across the tabs.
+  FindBarState* find_bar_state = tab_contents_->profile()->GetFindBarState();
+  find_bar_state->set_last_prepopulate_text(find_text_);
+  tab_contents_->render_view_host()->StartFinding(current_find_request_id_,
+                                                  find_text_,
+                                                  forward_direction,
+                                                  case_sensitive,
+                                                  find_next);
+}
+
+void FindManager::StopFinding(
+    FindBarController::SelectionAction selection_action) {
+  if (selection_action == FindBarController::kClearSelection) {
+    // kClearSelection means the find string has been cleared by the user, but
+    // the UI has not been dismissed. In that case we want to clear the
+    // previously remembered search (http://crbug.com/42639).
+    previous_find_text_ = string16();
+  } else {
+    find_ui_active_ = false;
+    if (!find_text_.empty())
+      previous_find_text_ = find_text_;
+  }
+  find_text_.clear();
+  find_op_aborted_ = true;
+  last_search_result_ = FindNotificationDetails();
+  tab_contents_->render_view_host()->StopFinding(selection_action);
+}
+
+bool FindManager::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(FindManager, message)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void FindManager::OnFindReply(int request_id,
+                              int number_of_matches,
+                              const gfx::Rect& selection_rect,
+                              int active_match_ordinal,
+                              bool final_update) {
+  // Ignore responses for requests that have been aborted.
+  // Ignore responses for requests other than the one we have most recently
+  // issued. That way we won't act on stale results when the user has
+  // already typed in another query.
+  if (!find_op_aborted_ && request_id == current_find_request_id_) {
+    if (number_of_matches == -1)
+      number_of_matches = last_search_result_.number_of_matches();
+    if (active_match_ordinal == -1)
+      active_match_ordinal = last_search_result_.active_match_ordinal();
+
+    gfx::Rect selection = selection_rect;
+    if (selection.IsEmpty())
+      selection = last_search_result_.selection_rect();
+
+    // Notify the UI, automation and any other observers that a find result was
+    // found.
+    last_search_result_ = FindNotificationDetails(
+        request_id, number_of_matches, selection, active_match_ordinal,
+        final_update);
+    NotificationService::current()->Notify(
+        NotificationType::FIND_RESULT_AVAILABLE,
+        Source<TabContents>(tab_contents_->tab_contents()),
+        Details<FindNotificationDetails>(&last_search_result_));
+  }
+
+  // Send a notification to the renderer that we are ready to receive more
+  // results from the scoping effort of the Find operation. The FindInPage
+  // scoping is asynchronous and periodically sends results back up to the
+  // browser using IPC. In an effort to not spam the browser we have the
+  // browser send an ACK for each FindReply message and have the renderer
+  // queue up the latest status message while waiting for this ACK.
+  tab_contents_->render_view_host()->Send(new ViewMsg_FindReplyACK(
+      tab_contents_->render_view_host()->routing_id()));
+}
diff --git a/chrome/browser/ui/find_bar/find_manager.h b/chrome/browser/ui/find_bar/find_manager.h
new file mode 100644
index 0000000..2a210f3
--- /dev/null
+++ b/chrome/browser/ui/find_bar/find_manager.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_FIND_BAR_FIND_MANAGER_H_
+#define CHROME_BROWSER_UI_FIND_BAR_FIND_MANAGER_H_
+#pragma once
+
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_notification_details.h"
+
+class TabContentsWrapper;
+
+// Per-tab find manager. Handles dealing with the life cycle of find sessions.
+class FindManager : public TabContentsObserver {
+ public:
+  explicit FindManager(TabContentsWrapper* tab_contents);
+  virtual ~FindManager();
+
+  // Starts the Find operation by calling StartFinding on the Tab. This function
+  // can be called from the outside as a result of hot-keys, so it uses the
+  // last remembered search string as specified with set_find_string(). This
+  // function does not block while a search is in progress. The controller will
+  // receive the results through the notification mechanism. See Observe(...)
+  // for details.
+  void StartFinding(string16 search_string,
+                    bool forward_direction,
+                    bool case_sensitive);
+
+  // Stops the current Find operation.
+  void StopFinding(FindBarController::SelectionAction selection_action);
+
+  // Accessors/Setters for find_ui_active_.
+  bool find_ui_active() const { return find_ui_active_; }
+  void set_find_ui_active(bool find_ui_active) {
+      find_ui_active_ = find_ui_active;
+  }
+
+  // Setter for find_op_aborted_.
+  void set_find_op_aborted(bool find_op_aborted) {
+    find_op_aborted_ = find_op_aborted;
+  }
+
+  // Used _only_ by testing to get or set the current request ID.
+  int current_find_request_id() { return current_find_request_id_; }
+  void set_current_find_request_id(int current_find_request_id) {
+    current_find_request_id_ = current_find_request_id;
+  }
+
+  // Accessor for find_text_. Used to determine if this TabContents has any
+  // active searches.
+  string16 find_text() const { return find_text_; }
+
+  // Accessor for the previous search we issued.
+  string16 previous_find_text() const { return previous_find_text_; }
+
+  // Accessor for find_result_.
+  const FindNotificationDetails& find_result() const {
+    return last_search_result_;
+  }
+
+  // TabContentsObserver overrides.
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  void OnFindReply(int request_id,
+                   int number_of_matches,
+                   const gfx::Rect& selection_rect,
+                   int active_match_ordinal,
+                   bool final_update);
+
+ private:
+  TabContentsWrapper* tab_contents_;
+
+  // Each time a search request comes in we assign it an id before passing it
+  // over the IPC so that when the results come in we can evaluate whether we
+  // still care about the results of the search (in some cases we don't because
+  // the user has issued a new search).
+  static int find_request_id_counter_;
+
+  // True if the Find UI is active for this Tab.
+  bool find_ui_active_;
+
+  // True if a Find operation was aborted. This can happen if the Find box is
+  // closed or if the search term inside the Find box is erased while a search
+  // is in progress. This can also be set if a page has been reloaded, and will
+  // on FindNext result in a full Find operation so that the highlighting for
+  // inactive matches can be repainted.
+  bool find_op_aborted_;
+
+  // This variable keeps track of what the most recent request id is.
+  int current_find_request_id_;
+
+  // The current string we are/just finished searching for. This is used to
+  // figure out if this is a Find or a FindNext operation (FindNext should not
+  // increase the request id).
+  string16 find_text_;
+
+  // The string we searched for before |find_text_|.
+  string16 previous_find_text_;
+
+  // Whether the last search was case sensitive or not.
+  bool last_search_case_sensitive_;
+
+  // The last find result. This object contains details about the number of
+  // matches, the find selection rectangle, etc. The UI can access this
+  // information to build its presentation.
+  FindNotificationDetails last_search_result_;
+
+  DISALLOW_COPY_AND_ASSIGN(FindManager);
+};
+
+#endif  // CHROME_BROWSER_UI_FIND_BAR_FIND_MANAGER_H_
diff --git a/chrome/browser/ui/find_bar/find_notification_details.h b/chrome/browser/ui/find_bar/find_notification_details.h
index d553782..360d953 100644
--- a/chrome/browser/ui/find_bar/find_notification_details.h
+++ b/chrome/browser/ui/find_bar/find_notification_details.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class FindNotificationDetails {
  public:
diff --git a/chrome/browser/ui/gtk/OWNERS b/chrome/browser/ui/gtk/OWNERS
new file mode 100644
index 0000000..0573e6b
--- /dev/null
+++ b/chrome/browser/ui/gtk/OWNERS
@@ -0,0 +1,2 @@
+erg@chromium.org
+estade@chromium.org
diff --git a/chrome/browser/ui/gtk/about_chrome_dialog.cc b/chrome/browser/ui/gtk/about_chrome_dialog.cc
new file mode 100644
index 0000000..4bd9bcf
--- /dev/null
+++ b/chrome/browser/ui/gtk/about_chrome_dialog.cc
@@ -0,0 +1,287 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/about_chrome_dialog.h"
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "webkit/glue/webkit_glue.h"
+
+namespace {
+
+// Left or right margin.
+const int kPanelHorizMargin = 13;
+
+// Top or bottom margin.
+const int kPanelVertMargin = 20;
+
+// Extra spacing between product name and version number.
+const int kExtraLineSpacing = 5;
+
+// These are used as placeholder text around the links in the text in the about
+// dialog.
+const char* kBeginLinkChr = "BEGIN_LINK_CHR";
+const char* kBeginLinkOss = "BEGIN_LINK_OSS";
+// We don't actually use this one.
+// const char* kEndLinkChr = "END_LINK_CHR";
+const char* kEndLinkOss = "END_LINK_OSS";
+const char* kBeginLink = "BEGIN_LINK";
+const char* kEndLink = "END_LINK";
+
+void OnDialogResponse(GtkDialog* dialog, int response_id) {
+  // We're done.
+  gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+GtkWidget* MakeMarkupLabel(const char* format, const std::string& str) {
+  GtkWidget* label = gtk_label_new(NULL);
+  char* markup = g_markup_printf_escaped(format, str.c_str());
+  gtk_label_set_markup(GTK_LABEL(label), markup);
+  g_free(markup);
+
+  // Left align it.
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+
+  return label;
+}
+
+void OnLinkButtonClick(GtkWidget* button, const char* url) {
+  BrowserList::GetLastActive()->
+      OpenURL(GURL(url), GURL(), NEW_WINDOW, PageTransition::LINK);
+}
+
+const char* GetChromiumUrl() {
+  static GURL url = google_util::AppendGoogleLocaleParam(
+      GURL(chrome::kChromiumProjectURL));
+  return url.spec().c_str();
+}
+
+gboolean OnEventBoxExpose(GtkWidget* event_box,
+                          GdkEventExpose* expose,
+                          gboolean user_data) {
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(event_box->window));
+  gdk_cairo_rectangle(cr, &expose->area);
+  cairo_clip(cr);
+  GtkThemeProvider* theme_provider =
+      GtkThemeProvider::GetFrom(BrowserList::GetLastActive()->profile());
+  CairoCachedSurface* background = theme_provider->GetSurfaceNamed(
+      IDR_ABOUT_BACKGROUND_COLOR, event_box);
+
+  background->SetSource(cr, 0, 0);
+  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+  gdk_cairo_rectangle(cr, &expose->area);
+  cairo_fill(cr);
+  cairo_destroy(cr);
+  return FALSE;
+}
+
+}  // namespace
+
+void ShowAboutDialogForProfile(GtkWindow* parent, Profile* profile) {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  static GdkPixbuf* background = rb.GetPixbufNamed(IDR_ABOUT_BACKGROUND);
+  chrome::VersionInfo version_info;
+  std::string current_version = version_info.Version();
+#if !defined(GOOGLE_CHROME_BUILD)
+  current_version += " (";
+  current_version += version_info.LastChange();
+  current_version += ")";
+#endif
+  std::string channel = platform_util::GetVersionStringModifier();
+  if (!channel.empty())
+    current_version += " " + channel;
+
+  // Build the dialog.
+  GtkWidget* dialog = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_ABOUT_CHROME_TITLE).c_str(),
+      parent,
+      GTK_DIALOG_MODAL,
+      NULL);
+  // Pick up the style set in gtk_util.cc:InitRCStyles().
+  // The layout of this dialog is special because the logo should be flush
+  // with the edges of the window.
+  gtk_widget_set_name(dialog, "about-dialog");
+  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+
+  GtkWidget* close_button = gtk_dialog_add_button(GTK_DIALOG(dialog),
+      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+
+  GtkWidget* content_area = GTK_DIALOG(dialog)->vbox;
+
+  // Use an event box to get the background painting correctly
+  GtkWidget* ebox = gtk_event_box_new();
+  gtk_widget_set_app_paintable(ebox, TRUE);
+  g_signal_connect(ebox, "expose-event", G_CALLBACK(OnEventBoxExpose), NULL);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+
+  GtkWidget* text_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(text_alignment),
+                            kPanelVertMargin, kPanelVertMargin,
+                            kPanelHorizMargin, kPanelHorizMargin);
+
+  GtkWidget* text_vbox = gtk_vbox_new(FALSE, kExtraLineSpacing);
+
+  GdkColor black = gtk_util::kGdkBlack;
+  GtkWidget* product_label = MakeMarkupLabel(
+      "<span font_desc=\"18\" style=\"normal\">%s</span>",
+      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
+  gtk_widget_modify_fg(product_label, GTK_STATE_NORMAL, &black);
+  gtk_box_pack_start(GTK_BOX(text_vbox), product_label, FALSE, FALSE, 0);
+
+  GtkWidget* version_label = gtk_label_new(current_version.c_str());
+  gtk_misc_set_alignment(GTK_MISC(version_label), 0.0, 0.5);
+  gtk_label_set_selectable(GTK_LABEL(version_label), TRUE);
+  gtk_widget_modify_fg(version_label, GTK_STATE_NORMAL, &black);
+  gtk_box_pack_start(GTK_BOX(text_vbox), version_label, FALSE, FALSE, 0);
+
+  gtk_container_add(GTK_CONTAINER(text_alignment), text_vbox);
+  gtk_box_pack_start(GTK_BOX(hbox), text_alignment, TRUE, TRUE, 0);
+
+  GtkWidget* image_vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(image_vbox),
+                   gtk_image_new_from_pixbuf(background),
+                   FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(hbox), image_vbox, FALSE, FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(ebox), hbox);
+  gtk_box_pack_start(GTK_BOX(content_area), ebox, TRUE, TRUE, 0);
+
+  // We use a separate box for the licensing etc. text.  See the comment near
+  // the top of this function about using a special layout for this dialog.
+  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+
+  GtkWidget* copyright_label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_COPYRIGHT).c_str());
+  gtk_misc_set_alignment(GTK_MISC(copyright_label), 0.0, 0.5);
+  gtk_box_pack_start(GTK_BOX(vbox), copyright_label, FALSE, FALSE, 5);
+
+  std::string license = l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_LICENSE);
+  bool chromium_url_appears_first =
+      license.find(kBeginLinkChr) < license.find(kBeginLinkOss);
+  size_t link1 = license.find(kBeginLink);
+  DCHECK(link1 != std::string::npos);
+  size_t link1_end = license.find(kEndLink, link1);
+  DCHECK(link1_end != std::string::npos);
+  size_t link2 = license.find(kBeginLink, link1_end);
+  DCHECK(link2 != std::string::npos);
+  size_t link2_end = license.find(kEndLink, link2);
+  DCHECK(link1_end != std::string::npos);
+
+  GtkWidget* license_chunk1 = gtk_label_new(license.substr(0, link1).c_str());
+  gtk_misc_set_alignment(GTK_MISC(license_chunk1), 0.0, 0.5);
+  GtkWidget* license_chunk2 = gtk_label_new(
+      license.substr(link1_end + strlen(kEndLinkOss),
+                     link2 - link1_end - strlen(kEndLinkOss)).c_str());
+  gtk_misc_set_alignment(GTK_MISC(license_chunk2), 0.0, 0.5);
+  GtkWidget* license_chunk3 = gtk_label_new(
+      license.substr(link2_end + strlen(kEndLinkOss)).c_str());
+  gtk_misc_set_alignment(GTK_MISC(license_chunk3), 0.0, 0.5);
+
+  std::string first_link_text =
+      license.substr(link1 + strlen(kBeginLinkOss),
+                     link1_end - link1 - strlen(kBeginLinkOss));
+  std::string second_link_text =
+      license.substr(link2 + strlen(kBeginLinkOss),
+                     link2_end - link2 - strlen(kBeginLinkOss));
+
+  GtkWidget* first_link = gtk_chrome_link_button_new(first_link_text.c_str());
+  GtkWidget* second_link = gtk_chrome_link_button_new(second_link_text.c_str());
+  if (!chromium_url_appears_first) {
+    GtkWidget* swap = second_link;
+    second_link = first_link;
+    first_link = swap;
+  }
+
+  g_signal_connect(chromium_url_appears_first ? first_link : second_link,
+                   "clicked", G_CALLBACK(OnLinkButtonClick),
+                   const_cast<char*>(GetChromiumUrl()));
+  g_signal_connect(chromium_url_appears_first ? second_link : first_link,
+                   "clicked", G_CALLBACK(OnLinkButtonClick),
+                   const_cast<char*>(chrome::kAboutCreditsURL));
+
+  GtkWidget* license_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_hbox), license_chunk1,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_hbox), first_link,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_hbox), license_chunk2,
+                     FALSE, FALSE, 0);
+
+  // Since there's no good way to dynamically wrap the license block, force
+  // a line break right before the second link (which matches en-US Windows
+  // chromium).
+  GtkWidget* license_hbox2 = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_hbox2), second_link,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_hbox2), license_chunk3,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* license_vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_vbox), license_hbox, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(license_vbox), license_hbox2, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), license_vbox, FALSE, FALSE, 0);
+
+#if defined(GOOGLE_CHROME_BUILD)
+  // Spacing line.
+  gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new(""), FALSE, FALSE, 0);
+
+  std::vector<size_t> url_offsets;
+  string16 text = l10n_util::GetStringFUTF16(IDS_ABOUT_TERMS_OF_SERVICE,
+                                             string16(),
+                                             string16(),
+                                             &url_offsets);
+
+  GtkWidget* tos_chunk1 = gtk_label_new(
+      UTF16ToUTF8(text.substr(0, url_offsets[0])).c_str());
+  gtk_misc_set_alignment(GTK_MISC(tos_chunk1), 0.0, 0.5);
+  GtkWidget* tos_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_TERMS_OF_SERVICE).c_str());
+  GtkWidget* tos_chunk2 = gtk_label_new(
+      UTF16ToUTF8(text.substr(url_offsets[0])).c_str());
+  gtk_misc_set_alignment(GTK_MISC(tos_chunk2), 0.0, 0.5);
+
+  GtkWidget* tos_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tos_hbox), tos_chunk1, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tos_hbox), tos_link, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tos_hbox), tos_chunk2, FALSE, FALSE, 0);
+
+  g_signal_connect(tos_link, "clicked", G_CALLBACK(OnLinkButtonClick),
+    const_cast<char*>(chrome::kAboutTermsURL));
+  gtk_box_pack_start(GTK_BOX(vbox), tos_hbox, TRUE, TRUE, 0);
+#endif
+
+  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+      gtk_util::kContentAreaBorder, 0,
+      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
+  gtk_container_add(GTK_CONTAINER(alignment), vbox);
+  gtk_box_pack_start(GTK_BOX(content_area), alignment, FALSE, FALSE, 0);
+
+  g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), NULL);
+  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
+  gtk_widget_show_all(dialog);
+  gtk_widget_grab_focus(close_button);
+}
diff --git a/chrome/browser/ui/gtk/about_chrome_dialog.h b/chrome/browser/ui/gtk/about_chrome_dialog.h
new file mode 100644
index 0000000..11817ec
--- /dev/null
+++ b/chrome/browser/ui/gtk/about_chrome_dialog.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_ABOUT_CHROME_DIALOG_H_
+#define CHROME_BROWSER_UI_GTK_ABOUT_CHROME_DIALOG_H_
+#pragma once
+
+class Profile;
+typedef struct _GtkWindow GtkWindow;
+
+// Displays the about box, using data copied from |profile|.
+void ShowAboutDialogForProfile(GtkWindow* parent, Profile* profile);
+
+#endif  // CHROME_BROWSER_UI_GTK_ABOUT_CHROME_DIALOG_H_
diff --git a/chrome/browser/ui/gtk/accelerators_gtk.cc b/chrome/browser/ui/gtk/accelerators_gtk.cc
new file mode 100644
index 0000000..fbec557
--- /dev/null
+++ b/chrome/browser/ui/gtk/accelerators_gtk.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/accelerators_gtk.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include <X11/XF86keysym.h>
+
+#include "base/singleton.h"
+#include "chrome/app/chrome_command_ids.h"
+
+namespace {
+
+// A mostly complete list of chrome's accelerators. When one command has
+// multiple shortcuts, the first one in this list is considered "primary",
+// meaning that it will be displayed in context menus.
+const struct AcceleratorMapping {
+  guint keyval;
+  int command_id;
+  GdkModifierType modifier_type;
+} kAcceleratorMap[] = {
+  // Focus.
+  { GDK_k, IDC_FOCUS_SEARCH, GDK_CONTROL_MASK },
+  { GDK_e, IDC_FOCUS_SEARCH, GDK_CONTROL_MASK },
+  { XF86XK_Search, IDC_FOCUS_SEARCH, GdkModifierType(0) },
+  { GDK_l, IDC_FOCUS_LOCATION, GDK_CONTROL_MASK },
+  { GDK_d, IDC_FOCUS_LOCATION, GDK_MOD1_MASK },
+  { GDK_F6, IDC_FOCUS_LOCATION, GdkModifierType(0) },
+  { XF86XK_OpenURL, IDC_FOCUS_LOCATION, GdkModifierType(0) },
+  { XF86XK_Go, IDC_FOCUS_LOCATION, GdkModifierType(0) },
+
+  // Tab/window controls.
+  { GDK_Page_Down, IDC_SELECT_NEXT_TAB, GDK_CONTROL_MASK },
+  { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK },
+  { GDK_Page_Down, IDC_MOVE_TAB_NEXT,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_Page_Up, IDC_MOVE_TAB_PREVIOUS,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK },
+  { GDK_w, IDC_CLOSE_TAB, GDK_CONTROL_MASK },
+  { GDK_t, IDC_RESTORE_TAB,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_t, IDC_NEW_TAB, GDK_CONTROL_MASK },
+  { GDK_n, IDC_NEW_WINDOW, GDK_CONTROL_MASK },
+  { GDK_n, IDC_NEW_INCOGNITO_WINDOW,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+
+  { GDK_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK },
+  { GDK_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK },
+  { GDK_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK },
+  { GDK_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK },
+  { GDK_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK },
+  { GDK_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK },
+  { GDK_7, IDC_SELECT_TAB_6, GDK_CONTROL_MASK },
+  { GDK_8, IDC_SELECT_TAB_7, GDK_CONTROL_MASK },
+  { GDK_9, IDC_SELECT_LAST_TAB, GDK_CONTROL_MASK },
+
+  { GDK_1, IDC_SELECT_TAB_0, GDK_MOD1_MASK },
+  { GDK_2, IDC_SELECT_TAB_1, GDK_MOD1_MASK },
+  { GDK_3, IDC_SELECT_TAB_2, GDK_MOD1_MASK },
+  { GDK_4, IDC_SELECT_TAB_3, GDK_MOD1_MASK },
+  { GDK_5, IDC_SELECT_TAB_4, GDK_MOD1_MASK },
+  { GDK_6, IDC_SELECT_TAB_5, GDK_MOD1_MASK },
+  { GDK_7, IDC_SELECT_TAB_6, GDK_MOD1_MASK },
+  { GDK_8, IDC_SELECT_TAB_7, GDK_MOD1_MASK },
+  { GDK_9, IDC_SELECT_LAST_TAB, GDK_MOD1_MASK },
+
+  { GDK_KP_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK },
+  { GDK_KP_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK },
+  { GDK_KP_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK },
+  { GDK_KP_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK },
+  { GDK_KP_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK },
+  { GDK_KP_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK },
+  { GDK_KP_7, IDC_SELECT_TAB_6, GDK_CONTROL_MASK },
+  { GDK_KP_8, IDC_SELECT_TAB_7, GDK_CONTROL_MASK },
+  { GDK_KP_9, IDC_SELECT_LAST_TAB, GDK_CONTROL_MASK },
+
+  { GDK_KP_1, IDC_SELECT_TAB_0, GDK_MOD1_MASK },
+  { GDK_KP_2, IDC_SELECT_TAB_1, GDK_MOD1_MASK },
+  { GDK_KP_3, IDC_SELECT_TAB_2, GDK_MOD1_MASK },
+  { GDK_KP_4, IDC_SELECT_TAB_3, GDK_MOD1_MASK },
+  { GDK_KP_5, IDC_SELECT_TAB_4, GDK_MOD1_MASK },
+  { GDK_KP_6, IDC_SELECT_TAB_5, GDK_MOD1_MASK },
+  { GDK_KP_7, IDC_SELECT_TAB_6, GDK_MOD1_MASK },
+  { GDK_KP_8, IDC_SELECT_TAB_7, GDK_MOD1_MASK },
+  { GDK_KP_9, IDC_SELECT_LAST_TAB, GDK_MOD1_MASK },
+
+  { GDK_F4, IDC_CLOSE_TAB, GDK_CONTROL_MASK },
+  { GDK_F4, IDC_CLOSE_WINDOW, GDK_MOD1_MASK },
+
+  // Zoom level.
+  { GDK_KP_Add, IDC_ZOOM_PLUS, GDK_CONTROL_MASK },
+  { GDK_plus, IDC_ZOOM_PLUS,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_equal, IDC_ZOOM_PLUS, GDK_CONTROL_MASK },
+  { XF86XK_ZoomIn, IDC_ZOOM_PLUS, GdkModifierType(0) },
+  { GDK_KP_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK },
+  { GDK_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK },
+  { GDK_KP_Subtract, IDC_ZOOM_MINUS, GDK_CONTROL_MASK },
+  { GDK_minus, IDC_ZOOM_MINUS, GDK_CONTROL_MASK },
+  { GDK_underscore, IDC_ZOOM_MINUS,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { XF86XK_ZoomOut, IDC_ZOOM_MINUS, GdkModifierType(0) },
+
+  // Find in page.
+  { GDK_g, IDC_FIND_NEXT, GDK_CONTROL_MASK },
+  { GDK_F3, IDC_FIND_NEXT, GdkModifierType(0) },
+  { GDK_g, IDC_FIND_PREVIOUS,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_F3, IDC_FIND_PREVIOUS, GDK_SHIFT_MASK },
+
+  // Navigation / toolbar buttons.
+  { GDK_Home, IDC_HOME, GDK_MOD1_MASK },
+  { XF86XK_HomePage, IDC_HOME, GdkModifierType(0) },
+  { GDK_Escape, IDC_STOP, GdkModifierType(0) },
+  { XF86XK_Stop, IDC_STOP, GdkModifierType(0) },
+  { GDK_Left, IDC_BACK, GDK_MOD1_MASK },
+  { XF86XK_Back, IDC_BACK, GdkModifierType(0) },
+  { GDK_Right, IDC_FORWARD, GDK_MOD1_MASK },
+  { XF86XK_Forward, IDC_FORWARD, GdkModifierType(0) },
+  { GDK_r, IDC_RELOAD, GDK_CONTROL_MASK },
+  { GDK_r, IDC_RELOAD_IGNORING_CACHE,
+    GdkModifierType(GDK_CONTROL_MASK|GDK_SHIFT_MASK) },
+  { GDK_F5, IDC_RELOAD, GdkModifierType(0) },
+  { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_CONTROL_MASK },
+  { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_SHIFT_MASK },
+  { XF86XK_Reload, IDC_RELOAD, GdkModifierType(0) },
+  { XF86XK_Refresh, IDC_RELOAD, GdkModifierType(0) },
+
+  // Dev tools.
+  { GDK_u, IDC_VIEW_SOURCE, GDK_CONTROL_MASK },
+  { GDK_i, IDC_DEV_TOOLS,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_j, IDC_DEV_TOOLS_CONSOLE,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_c, IDC_DEV_TOOLS_INSPECT,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_Escape, IDC_TASK_MANAGER, GDK_SHIFT_MASK },
+
+  // Editing.
+  { GDK_c, IDC_COPY, GDK_CONTROL_MASK },
+  { GDK_x, IDC_CUT, GDK_CONTROL_MASK },
+  { GDK_v, IDC_PASTE, GDK_CONTROL_MASK },
+
+  // AutoFill.
+  { GDK_a, IDC_AUTOFILL_DEFAULT,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+
+  // Miscellany.
+  { GDK_d, IDC_BOOKMARK_ALL_TABS,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_d, IDC_BOOKMARK_PAGE, GDK_CONTROL_MASK },
+  { GDK_o, IDC_OPEN_FILE, GDK_CONTROL_MASK },
+  { GDK_f, IDC_FIND, GDK_CONTROL_MASK },
+  { GDK_p, IDC_PRINT, GDK_CONTROL_MASK },
+  { GDK_b, IDC_SHOW_BOOKMARK_BAR,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_F11, IDC_FULLSCREEN, GdkModifierType(0) },
+  { GDK_Delete, IDC_CLEAR_BROWSING_DATA,
+    GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_h, IDC_SHOW_HISTORY, GDK_CONTROL_MASK },
+  { GDK_j, IDC_SHOW_DOWNLOADS, GDK_CONTROL_MASK },
+  { GDK_F1, IDC_HELP_PAGE, GdkModifierType(0) },
+  { XF86XK_AddFavorite, IDC_BOOKMARK_PAGE, GdkModifierType(0) },
+  { XF86XK_Favorites, IDC_SHOW_BOOKMARK_BAR, GdkModifierType(0) },
+  { XF86XK_History, IDC_SHOW_HISTORY, GdkModifierType(0) },
+  { GDK_q, IDC_EXIT, GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
+  { GDK_s, IDC_SAVE_PAGE, GDK_CONTROL_MASK },
+  { GDK_e, IDC_SHOW_APP_MENU, GDK_MOD1_MASK },
+  { GDK_f, IDC_SHOW_APP_MENU, GDK_MOD1_MASK },
+};
+
+}  // namespace
+
+AcceleratorsGtk::AcceleratorsGtk() {
+  for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) {
+    int command_id = kAcceleratorMap[i].command_id;
+    ui::AcceleratorGtk accelerator(kAcceleratorMap[i].keyval,
+                                      kAcceleratorMap[i].modifier_type);
+    all_accelerators_.push_back(
+        std::pair<int, ui::AcceleratorGtk>(command_id, accelerator));
+
+    if (primary_accelerators_.find(command_id) ==
+        primary_accelerators_.end()) {
+      primary_accelerators_[command_id] = accelerator;
+    }
+  }
+}
+
+AcceleratorsGtk::~AcceleratorsGtk() {}
+
+// static
+AcceleratorsGtk* AcceleratorsGtk::GetInstance() {
+  return Singleton<AcceleratorsGtk>::get();
+}
+
+const ui::AcceleratorGtk* AcceleratorsGtk::GetPrimaryAcceleratorForCommand(
+    int command_id) {
+  base::hash_map<int, ui::AcceleratorGtk>::const_iterator iter =
+      primary_accelerators_.find(command_id);
+
+  if (iter == primary_accelerators_.end())
+    return NULL;
+
+  return &iter->second;
+}
diff --git a/chrome/browser/ui/gtk/accelerators_gtk.h b/chrome/browser/ui/gtk/accelerators_gtk.h
new file mode 100644
index 0000000..bf5a0ff
--- /dev/null
+++ b/chrome/browser/ui/gtk/accelerators_gtk.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_ACCELERATORS_GTK_H_
+#define CHROME_BROWSER_UI_GTK_ACCELERATORS_GTK_H_
+#pragma once
+
+#include "base/hash_tables.h"
+#include "ui/base/models/accelerator_gtk.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+class AcceleratorsGtk {
+ public:
+  typedef std::vector<std::pair<int, ui::AcceleratorGtk> >
+      AcceleratorGtkList;
+  typedef AcceleratorGtkList::const_iterator const_iterator;
+
+  // Returns the singleton instance.
+  static AcceleratorsGtk* GetInstance();
+
+  const_iterator const begin() {
+    return all_accelerators_.begin();
+  }
+
+  const_iterator const end() {
+    return all_accelerators_.end();
+  }
+
+  // Returns NULL if there is no accelerator for the command.
+  const ui::AcceleratorGtk* GetPrimaryAcceleratorForCommand(int command_id);
+
+ private:
+  friend struct DefaultSingletonTraits<AcceleratorsGtk>;
+
+  AcceleratorsGtk();
+  ~AcceleratorsGtk();
+
+  base::hash_map<int, ui::AcceleratorGtk> primary_accelerators_;
+
+  AcceleratorGtkList all_accelerators_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_ACCELERATORS_GTK_H_
diff --git a/chrome/browser/ui/gtk/accessibility_event_router_gtk.cc b/chrome/browser/ui/gtk/accessibility_event_router_gtk.cc
new file mode 100644
index 0000000..04061c6
--- /dev/null
+++ b/chrome/browser/ui/gtk/accessibility_event_router_gtk.cc
@@ -0,0 +1,658 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/accessibility_event_router_gtk.h"
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/extensions/extension_accessibility_api.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/common/notification_type.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "views/controls/textfield/gtk_views_entry.h"
+#include "views/controls/textfield/gtk_views_textview.h"
+#include "views/controls/textfield/native_textfield_gtk.h"
+#endif
+
+namespace {
+
+//
+// Callbacks triggered by signals on gtk widgets.
+//
+
+gboolean OnWidgetFocused(GSignalInvocationHint *ihint,
+                         guint n_param_values,
+                         const GValue* param_values,
+                         gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      DispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
+  return TRUE;
+}
+
+gboolean OnButtonClicked(GSignalInvocationHint *ihint,
+                         guint n_param_values,
+                         const GValue* param_values,
+                         gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  // Skip toggle buttons because we're also listening on "toggle" events.
+  if (GTK_IS_TOGGLE_BUTTON(widget))
+    return true;
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      DispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
+  return TRUE;
+}
+
+gboolean OnButtonToggled(GSignalInvocationHint *ihint,
+                         guint n_param_values,
+                         const GValue* param_values,
+                         gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  // Skip propagating an "uncheck" event for a radio button because it's
+  // redundant; there will always be a corresponding "check" event for
+  // a different radio button the group.
+  if (GTK_IS_RADIO_BUTTON(widget) && !checked)
+    return true;
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      DispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
+  return TRUE;
+}
+
+gboolean OnPageSwitched(GSignalInvocationHint *ihint,
+                        guint n_param_values,
+                        const GValue* param_values,
+                        gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  // The page hasn't switched yet, so defer calling
+  // DispatchAccessibilityNotification.
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      PostDispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
+  return TRUE;
+}
+
+gboolean OnComboBoxChanged(GSignalInvocationHint *ihint,
+                           guint n_param_values,
+                           const GValue* param_values,
+                           gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  if (!GTK_IS_COMBO_BOX(widget))
+    return true;
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      DispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
+  return TRUE;
+}
+
+gboolean OnTreeViewCursorChanged(GSignalInvocationHint *ihint,
+                                 guint n_param_values,
+                                 const GValue* param_values,
+                                 gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  if (!GTK_IS_TREE_VIEW(widget)) {
+    return true;
+  }
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      DispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
+  return TRUE;
+}
+
+gboolean OnEntryChanged(GSignalInvocationHint *ihint,
+                        guint n_param_values,
+                        const GValue* param_values,
+                        gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  if (!GTK_IS_ENTRY(widget)) {
+    return TRUE;
+  }
+  // The text hasn't changed yet, so defer calling
+  // DispatchAccessibilityNotification.
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      PostDispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
+  return TRUE;
+}
+
+gboolean OnTextBufferChanged(GSignalInvocationHint *ihint,
+                             guint n_param_values,
+                             const GValue* param_values,
+                             gpointer user_data) {
+  // The text hasn't changed yet, so defer calling
+  // DispatchAccessibilityNotification.
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      PostDispatchAccessibilityNotification(
+          NULL, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
+  return TRUE;
+}
+
+gboolean OnTextViewChanged(GSignalInvocationHint *ihint,
+                           guint n_param_values,
+                           const GValue* param_values,
+                           gpointer user_data) {
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+  if (!GTK_IS_TEXT_VIEW(widget)) {
+    return TRUE;
+  }
+  // The text hasn't changed yet, so defer calling
+  // DispatchAccessibilityNotification.
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      PostDispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
+  return TRUE;
+}
+
+gboolean OnMenuMoveCurrent(GSignalInvocationHint *ihint,
+                           guint n_param_values,
+                           const GValue* param_values,
+                           gpointer user_data) {
+  // Get the widget (the GtkMenu).
+  GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
+
+  // Moving may move us into or out of a submenu, so after the menu
+  // item moves, |widget| may not be valid anymore. To be safe, then,
+  // find the topmost ancestor of this menu and post the notification
+  // dispatch on that menu. Then the dispatcher will recurse into submenus
+  // as necessary to figure out which item is focused.
+  while (GTK_MENU_SHELL(widget)->parent_menu_shell)
+    widget = GTK_MENU_SHELL(widget)->parent_menu_shell;
+
+  // The menu item hasn't moved yet, so we want to defer calling
+  // DispatchAccessibilityNotification until after it does.
+  reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
+      PostDispatchAccessibilityNotification(
+          widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
+  return TRUE;
+}
+
+}  // anonymous namespace
+
+AccessibilityEventRouterGtk::AccessibilityEventRouterGtk()
+    : listening_(false),
+      most_recent_profile_(NULL),
+      most_recent_widget_(NULL),
+      method_factory_(this) {
+  // We don't want our event listeners to be installed if accessibility is
+  // disabled. Install listeners so we can install and uninstall them as
+  // needed, then install them now if it's currently enabled.
+  ExtensionAccessibilityEventRouter *extension_event_router =
+      ExtensionAccessibilityEventRouter::GetInstance();
+  extension_event_router->AddOnEnabledListener(
+      NewCallback(this,
+                  &AccessibilityEventRouterGtk::InstallEventListeners));
+  extension_event_router->AddOnDisabledListener(
+      NewCallback(this,
+                  &AccessibilityEventRouterGtk::RemoveEventListeners));
+  if (extension_event_router->IsAccessibilityEnabled()) {
+    InstallEventListeners();
+  }
+}
+
+AccessibilityEventRouterGtk::~AccessibilityEventRouterGtk() {
+  RemoveEventListeners();
+}
+
+// static
+AccessibilityEventRouterGtk* AccessibilityEventRouterGtk::GetInstance() {
+  return Singleton<AccessibilityEventRouterGtk>::get();
+}
+
+void AccessibilityEventRouterGtk::InstallEventListener(
+    const char* signal_name,
+    GType widget_type,
+    GSignalEmissionHook hook_func) {
+  guint signal_id = g_signal_lookup(signal_name, widget_type);
+  gulong hook_id = g_signal_add_emission_hook(
+      signal_id, 0, hook_func, reinterpret_cast<gpointer>(this), NULL);
+  installed_hooks_.push_back(InstalledHook(signal_id, hook_id));
+}
+
+bool AccessibilityEventRouterGtk::IsPassword(GtkWidget* widget) {
+  bool is_password = false;
+#if defined (TOOLKIT_VIEWS)
+  is_password = (GTK_IS_VIEWS_ENTRY(widget) &&
+                 GTK_VIEWS_ENTRY(widget)->host != NULL &&
+                 GTK_VIEWS_ENTRY(widget)->host->IsPassword()) ||
+                (GTK_IS_VIEWS_TEXTVIEW(widget) &&
+                 GTK_VIEWS_TEXTVIEW(widget)->host != NULL &&
+                 GTK_VIEWS_TEXTVIEW(widget)->host->IsPassword());
+#endif
+  return is_password;
+}
+
+
+void AccessibilityEventRouterGtk::InstallEventListeners() {
+  // Create and destroy each type of widget we need signals for,
+  // to ensure their modules are loaded, otherwise g_signal_lookup
+  // might fail.
+  g_object_unref(g_object_ref_sink(gtk_combo_box_new()));
+  g_object_unref(g_object_ref_sink(gtk_entry_new()));
+  g_object_unref(g_object_ref_sink(gtk_notebook_new()));
+  g_object_unref(g_object_ref_sink(gtk_toggle_button_new()));
+  g_object_unref(g_object_ref_sink(gtk_tree_view_new()));
+  g_object_unref(g_object_ref_sink(gtk_text_view_new()));
+  g_object_unref(g_object_ref_sink(gtk_text_buffer_new(NULL)));
+
+  // Add signal emission hooks for the events we're interested in.
+  InstallEventListener("clicked", GTK_TYPE_BUTTON, OnButtonClicked);
+  InstallEventListener("changed", GTK_TYPE_COMBO_BOX, OnComboBoxChanged);
+  InstallEventListener("cursor-changed", GTK_TYPE_TREE_VIEW,
+                       OnTreeViewCursorChanged);
+  InstallEventListener("changed", GTK_TYPE_ENTRY, OnEntryChanged);
+  InstallEventListener("insert-text", GTK_TYPE_ENTRY, OnEntryChanged);
+  InstallEventListener("delete-text", GTK_TYPE_ENTRY, OnEntryChanged);
+  InstallEventListener("move-cursor", GTK_TYPE_ENTRY, OnEntryChanged);
+  InstallEventListener("focus-in-event", GTK_TYPE_WIDGET, OnWidgetFocused);
+  InstallEventListener("switch-page", GTK_TYPE_NOTEBOOK, OnPageSwitched);
+  InstallEventListener("toggled", GTK_TYPE_TOGGLE_BUTTON, OnButtonToggled);
+  InstallEventListener("move-current", GTK_TYPE_MENU, OnMenuMoveCurrent);
+  InstallEventListener("changed", GTK_TYPE_TEXT_BUFFER, OnTextBufferChanged);
+  InstallEventListener("move-cursor", GTK_TYPE_TEXT_VIEW, OnTextViewChanged);
+
+  listening_ = true;
+}
+
+void AccessibilityEventRouterGtk::RemoveEventListeners() {
+  for (size_t i = 0; i < installed_hooks_.size(); i++) {
+    g_signal_remove_emission_hook(
+        installed_hooks_[i].signal_id,
+        installed_hooks_[i].hook_id);
+  }
+  installed_hooks_.clear();
+
+  listening_ = false;
+}
+
+void AccessibilityEventRouterGtk::AddRootWidget(
+    GtkWidget* root_widget, Profile* profile) {
+  root_widget_info_map_[root_widget].refcount++;
+  root_widget_info_map_[root_widget].profile = profile;
+}
+
+void AccessibilityEventRouterGtk::RemoveRootWidget(GtkWidget* root_widget) {
+  DCHECK(root_widget_info_map_.find(root_widget) !=
+         root_widget_info_map_.end());
+  root_widget_info_map_[root_widget].refcount--;
+  if (root_widget_info_map_[root_widget].refcount == 0) {
+    root_widget_info_map_.erase(root_widget);
+  }
+}
+
+void AccessibilityEventRouterGtk::AddWidgetNameOverride(
+    GtkWidget* widget, std::string name) {
+  widget_info_map_[widget].name = name;
+  widget_info_map_[widget].refcount++;
+}
+
+void AccessibilityEventRouterGtk::RemoveWidgetNameOverride(GtkWidget* widget) {
+  DCHECK(widget_info_map_.find(widget) != widget_info_map_.end());
+  widget_info_map_[widget].refcount--;
+  if (widget_info_map_[widget].refcount == 0) {
+    widget_info_map_.erase(widget);
+  }
+}
+
+void AccessibilityEventRouterGtk::FindWidget(
+    GtkWidget* widget, Profile** profile, bool* is_accessible) {
+  *is_accessible = false;
+
+  for (base::hash_map<GtkWidget*, RootWidgetInfo>::const_iterator iter =
+           root_widget_info_map_.begin();
+       iter != root_widget_info_map_.end();
+       ++iter) {
+    if (widget == iter->first || gtk_widget_is_ancestor(widget, iter->first)) {
+      *is_accessible = true;
+      if (profile)
+        *profile = iter->second.profile;
+      break;
+    }
+  }
+}
+
+std::string AccessibilityEventRouterGtk::GetWidgetName(GtkWidget* widget) {
+  base::hash_map<GtkWidget*, WidgetInfo>::const_iterator iter =
+      widget_info_map_.find(widget);
+  if (iter != widget_info_map_.end()) {
+    return iter->second.name;
+  } else {
+    return "";
+  }
+}
+
+void AccessibilityEventRouterGtk::StartListening() {
+  listening_ = true;
+}
+
+void AccessibilityEventRouterGtk::StopListening() {
+  listening_ = false;
+}
+
+void AccessibilityEventRouterGtk::DispatchAccessibilityNotification(
+    GtkWidget* widget, NotificationType type) {
+  // If there's no message loop, we must be about to shutdown or we're
+  // running inside a test; either way, there's no reason to do any
+  // further processing.
+  if (!MessageLoop::current())
+    return;
+
+  if (!listening_)
+    return;
+
+  Profile* profile = NULL;
+  bool is_accessible;
+
+  // Special case: when we get ACCESSIBILITY_TEXT_CHANGED, we don't get
+  // a pointer to the widget, so we try to retrieve it from the most recent
+  // widget.
+  if (widget == NULL &&
+      type == NotificationType::ACCESSIBILITY_TEXT_CHANGED &&
+      most_recent_widget_ &&
+      GTK_IS_TEXT_VIEW(most_recent_widget_)) {
+    widget = most_recent_widget_;
+  }
+
+  if (!widget)
+    return;
+
+  most_recent_widget_ = widget;
+  FindWidget(widget, &profile, &is_accessible);
+  if (profile)
+    most_recent_profile_ = profile;
+
+  // Special case: a GtkMenu isn't associated with any particular
+  // toplevel window, so menu events get routed to the profile of
+  // the most recent event that was associated with a window.
+  if (GTK_IS_MENU_SHELL(widget) && most_recent_profile_) {
+    SendMenuItemNotification(widget, type, most_recent_profile_);
+    return;
+  }
+
+  // In all other cases, return if this widget wasn't marked as accessible.
+  if (!is_accessible)
+    return;
+
+  // The order of these checks matters, because, for example, a radio button
+  // is a subclass of button, and a combo box is a composite control where
+  // the focus event goes to the button that's a child of the combo box.
+  GtkWidget* parent = gtk_widget_get_parent(widget);
+  if (parent && GTK_IS_BUTTON(widget) && GTK_IS_TREE_VIEW(parent)) {
+    // This is a list box column header.  Currently not supported.
+    return;
+  } else if (GTK_IS_COMBO_BOX(widget)) {
+    SendComboBoxNotification(widget, type, profile);
+  } else if (parent && GTK_IS_COMBO_BOX(parent)) {
+    SendComboBoxNotification(parent, type, profile);
+  } else if (GTK_IS_RADIO_BUTTON(widget)) {
+    SendRadioButtonNotification(widget, type, profile);
+  } else if (GTK_IS_TOGGLE_BUTTON(widget)) {
+    SendCheckboxNotification(widget, type, profile);
+  } else if (GTK_IS_BUTTON(widget)) {
+    SendButtonNotification(widget, type, profile);
+  } else if (GTK_IS_ENTRY(widget)) {
+    SendEntryNotification(widget, type, profile);
+  } else if (GTK_IS_TEXT_VIEW(widget)) {
+    SendTextViewNotification(widget, type, profile);
+  } else if (GTK_IS_NOTEBOOK(widget)) {
+    SendTabNotification(widget, type, profile);
+  } else if (GTK_IS_TREE_VIEW(widget)) {
+    SendListBoxNotification(widget, type, profile);
+  } else {
+    // If we have no idea what this control is, return and skip the
+    // temporary pause in event listening.
+    return;
+  }
+
+  // After this method returns, additional signal handlers will run,
+  // which will sometimes generate additional signals.  To avoid
+  // generating redundant accessibility notifications for the same
+  // initial event, stop listening to all signals generated from now
+  // until this posted task runs.
+  StopListening();
+  MessageLoop::current()->PostTask(
+      FROM_HERE, method_factory_.NewRunnableMethod(
+          &AccessibilityEventRouterGtk::StartListening));
+}
+
+void AccessibilityEventRouterGtk::PostDispatchAccessibilityNotification(
+    GtkWidget* widget, NotificationType type) {
+  if (!MessageLoop::current())
+    return;
+
+  MessageLoop::current()->PostTask(
+      FROM_HERE, method_factory_.NewRunnableMethod(
+          &AccessibilityEventRouterGtk::DispatchAccessibilityNotification,
+          widget,
+          type));
+}
+
+void AccessibilityEventRouterGtk::SendRadioButtonNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  // Get the radio button name
+  std::string button_name = GetWidgetName(widget);
+  if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
+    button_name = gtk_button_get_label(GTK_BUTTON(widget));
+
+  // Get its state
+  bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+
+  // Get the index of this radio button and the total number of
+  // radio buttons in the group.
+  int item_count = 0;
+  int item_index = -1;
+  for (GSList* group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(widget));
+       group;
+       group = group->next) {
+    if (group->data == widget) {
+      item_index = item_count;
+    }
+    item_count++;
+  }
+  item_index = item_count - 1 - item_index;
+
+  AccessibilityRadioButtonInfo info(
+      profile, button_name, checked, item_index, item_count);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendCheckboxNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  std::string button_name = GetWidgetName(widget);
+  if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
+    button_name = gtk_button_get_label(GTK_BUTTON(widget));
+  bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  AccessibilityCheckboxInfo info(profile, button_name, checked);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendButtonNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  std::string button_name = GetWidgetName(widget);
+  if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
+    button_name = gtk_button_get_label(GTK_BUTTON(widget));
+  AccessibilityButtonInfo info(profile, button_name);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendEntryNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  std::string name = GetWidgetName(widget);
+  std::string value = gtk_entry_get_text(GTK_ENTRY(widget));
+  gint start_pos;
+  gint end_pos;
+  gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start_pos, &end_pos);
+  AccessibilityTextBoxInfo info(profile, name, IsPassword(widget));
+  info.SetValue(value, start_pos, end_pos);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendTextViewNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  std::string name = GetWidgetName(widget);
+  GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+  GtkTextIter start, end;
+  gtk_text_buffer_get_bounds(buffer, &start, &end);
+  gchar* text = gtk_text_buffer_get_text(buffer, &start, &end, false);
+  std::string value = text;
+  g_free(text);
+  GtkTextIter sel_start, sel_end;
+  gtk_text_buffer_get_selection_bounds(buffer, &sel_start, &sel_end);
+  int start_pos = gtk_text_iter_get_offset(&sel_start);
+  int end_pos = gtk_text_iter_get_offset(&sel_end);
+  AccessibilityTextBoxInfo info(profile, name, IsPassword(widget));
+  info.SetValue(value, start_pos, end_pos);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendTabNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
+  int page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget));
+  GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget), index);
+  GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(widget), page);
+  std::string name = GetWidgetName(widget);
+  if (name.empty() && gtk_label_get_text(GTK_LABEL(label))) {
+    name = gtk_label_get_text(GTK_LABEL(label));
+  }
+  AccessibilityTabInfo info(profile, name, index, page_count);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendComboBoxNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  // Get the index of the selected item.  Will return -1 if no item is
+  // active, which matches the semantics of the extension API.
+  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
+
+  // Get the number of items.
+  GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
+  int count = gtk_tree_model_iter_n_children(model, NULL);
+
+  // Get the value of the current item, if possible.  Note that the
+  // model behind the combo box could be arbitrarily complex in theory,
+  // but this code just handles flat lists where the first string column
+  // contains the display value.
+  std::string value;
+  int string_column_index = -1;
+  for (int i = 0; i < gtk_tree_model_get_n_columns(model); i++) {
+    if (gtk_tree_model_get_column_type(model, i) == G_TYPE_STRING) {
+      string_column_index = i;
+      break;
+    }
+  }
+  if (string_column_index) {
+    GtkTreeIter iter;
+    if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) {
+      GValue gvalue = { 0 };
+      gtk_tree_model_get_value(model, &iter, string_column_index, &gvalue);
+      const char* string_value = g_value_get_string(&gvalue);
+      if (string_value) {
+        value = string_value;
+      }
+      g_value_unset(&gvalue);
+    }
+  } else {
+    // Otherwise this must be a gtk_combo_box_text, in which case this
+    // function will return the value of the current item, instead.
+    value = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
+  }
+
+  // Get the name of this combo box.
+  std::string name = GetWidgetName(widget);
+
+  // Send the notification.
+  AccessibilityComboBoxInfo info(profile, name, value, index, count);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendListBoxNotification(
+    GtkWidget* widget, NotificationType type, Profile* profile) {
+  // Get the number of items.
+  GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
+  int count = gtk_tree_model_iter_n_children(model, NULL);
+
+  // Get the current selected index and its value.
+  int index = -1;
+  std::string value;
+  GtkTreePath* path;
+  gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &path, NULL);
+  if (path != NULL) {
+    gint* indices = gtk_tree_path_get_indices(path);
+    if (indices)
+      index = indices[0];
+
+    GtkTreeIter iter;
+    if (gtk_tree_model_get_iter(model, &iter, path)) {
+      for (int i = 0; i < gtk_tree_model_get_n_columns(model); i++) {
+        if (gtk_tree_model_get_column_type(model, i) == G_TYPE_STRING) {
+          GValue gvalue = { 0 };
+          gtk_tree_model_get_value(model, &iter, i, &gvalue);
+          const char* string_value = g_value_get_string(&gvalue);
+          if (string_value) {
+            if (!value.empty())
+              value += " ";
+            value += string_value;
+          }
+          g_value_unset(&gvalue);
+        }
+      }
+    }
+
+    gtk_tree_path_free(path);
+  }
+
+  // Get the name of this control.
+  std::string name = GetWidgetName(widget);
+
+  // Send the notification.
+  AccessibilityListBoxInfo info(profile, name, value, index, count);
+  SendAccessibilityNotification(type, &info);
+}
+
+void AccessibilityEventRouterGtk::SendMenuItemNotification(
+    GtkWidget* menu, NotificationType type, Profile* profile) {
+  // Find the focused menu item, recursing into submenus as needed.
+  GtkWidget* menu_item = GTK_MENU_SHELL(menu)->active_menu_item;
+  if (!menu_item)
+    return;
+  GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item));
+  while (submenu && GTK_MENU_SHELL(submenu)->active_menu_item) {
+    menu = submenu;
+    menu_item = GTK_MENU_SHELL(menu)->active_menu_item;
+    if (!menu_item)
+      return;
+    submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item));
+  }
+
+  // Figure out the item index and total number of items.
+  GList* items = gtk_container_get_children(GTK_CONTAINER(menu));
+  guint count = g_list_length(items);
+  int index = g_list_index(items, static_cast<gconstpointer>(menu_item));
+
+  // Get the menu item's label.
+  std::string name;
+#if GTK_CHECK_VERSION(2, 16, 0)
+  name = gtk_menu_item_get_label(GTK_MENU_ITEM(menu_item));
+#else
+  GList* children = gtk_container_get_children(GTK_CONTAINER(menu_item));
+  for (GList* l = g_list_first(children); l != NULL; l = g_list_next(l)) {
+    GtkWidget* child = static_cast<GtkWidget*>(l->data);
+    if (GTK_IS_LABEL(child)) {
+      name = gtk_label_get_label(GTK_LABEL(child));
+      break;
+    }
+  }
+#endif
+
+  // Send the event.
+  AccessibilityMenuItemInfo info(profile, name, submenu != NULL, index, count);
+  SendAccessibilityNotification(type, &info);
+}
diff --git a/chrome/browser/ui/gtk/accessibility_event_router_gtk.h b/chrome/browser/ui/gtk/accessibility_event_router_gtk.h
new file mode 100644
index 0000000..d8ca832
--- /dev/null
+++ b/chrome/browser/ui/gtk/accessibility_event_router_gtk.h
@@ -0,0 +1,208 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_ACCESSIBILITY_EVENT_ROUTER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_ACCESSIBILITY_EVENT_ROUTER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/hash_tables.h"
+#include "base/singleton.h"
+#include "base/task.h"
+#include "chrome/browser/accessibility_events.h"
+
+class Profile;
+#if defined (TOOLKIT_VIEWS)
+namespace views {
+class NativeTextfieldGtk;
+}
+#endif
+
+// Allows us to use (GtkWidget*) in a hash_map with gcc.
+namespace __gnu_cxx {
+template<>
+struct hash<GtkWidget*> {
+  size_t operator()(GtkWidget* widget) const {
+    return reinterpret_cast<size_t>(widget);
+  }
+};
+}  // namespace __gnu_cxx
+
+// Struct to keep track of event listener hook ids to remove them later.
+struct InstalledHook {
+  InstalledHook(guint _signal_id, gulong _hook_id)
+      : signal_id(_signal_id), hook_id(_hook_id) { }
+  guint signal_id;
+  gulong hook_id;
+};
+
+// NOTE: This class is part of the Accessibility Extension API, which lets
+// extensions receive accessibility events. It's distinct from code that
+// implements platform accessibility APIs like MSAA or ATK.
+//
+// Singleton class that adds a signal emission hook to many gtk events, and
+// then sends an accessibility notification whenever a relevant event is
+// sent to an accessible control.
+//
+// Gtk widgets are not accessible by default. When you register a root widget,
+// that widget and all of its descendants will start sending accessibility
+// event notifications. You can then override the default behavior for
+// specific descendants using other methods.
+//
+// You can use Profile::PauseAccessibilityEvents to prevent a flurry
+// of accessibility events when a window is being created or initialized.
+class AccessibilityEventRouterGtk {
+ public:
+  // Internal information about a particular widget to override the
+  // information we get directly from gtk.
+  struct WidgetInfo {
+    WidgetInfo() : refcount(0) { }
+
+    // The number of times that AddWidgetNameOverride has been called on this
+    // widget. When RemoveWidget has been called an equal number of
+    // times and the refcount reaches zero, this entry will be deleted.
+    int refcount;
+
+    // If nonempty, will use this name instead of the widget's label.
+    std::string name;
+  };
+
+  // Internal information about a root widget
+  struct RootWidgetInfo {
+    RootWidgetInfo() : refcount(0), profile(NULL) { }
+
+    // The number of times that AddRootWidget has been called on this
+    // widget. When RemoveRootWidget has been called an equal number of
+    // times and the refcount reaches zero, this entry will be deleted.
+    int refcount;
+
+    // The profile associated with this root widget; accessibility
+    // notifications for any descendant of this root widget will get routed
+    // to this profile.
+    Profile* profile;
+  };
+
+  // Get the single instance of this class.
+  static AccessibilityEventRouterGtk* GetInstance();
+
+  // Start sending accessibility events for this widget and all of its
+  // descendants.  Notifications will go to the specified profile.
+  // Uses reference counting, so it's safe to call this twice on the
+  // same widget, as long as each call is paired with a call to
+  // RemoveRootWidget.
+  void AddRootWidget(GtkWidget* root_widget, Profile* profile);
+
+  // Stop sending accessibility events for this widget and all of its
+  // descendants.
+  void RemoveRootWidget(GtkWidget* root_widget);
+
+  // Use the following string as the name of this widget, instead of the
+  // gtk label associated with the widget. Must be paired with a call to
+  // RemoveWidgetNameOverride.
+  void AddWidgetNameOverride(GtkWidget* widget, std::string name);
+
+  // Forget widget name override. Must be paired with a call to
+  // AddWidgetNameOverride (uses reference counting).
+  void RemoveWidgetNameOverride(GtkWidget* widget);
+
+  //
+  // The following methods are only for use by gtk signal handlers.
+  //
+
+  // Called by the signal handler.  Checks the type of the widget and
+  // calls one of the more specific Send*Notification methods, below.
+  void DispatchAccessibilityNotification(
+      GtkWidget* widget, NotificationType type);
+
+  // Post a task to call DispatchAccessibilityNotification the next time
+  // through the event loop.
+  void PostDispatchAccessibilityNotification(
+      GtkWidget* widget, NotificationType type);
+
+ private:
+  AccessibilityEventRouterGtk();
+  virtual ~AccessibilityEventRouterGtk();
+
+  // Given a widget, determine if it's the descendant of a root widget
+  // that's mapped to a profile and if so, if it's marked as accessible.
+  void FindWidget(GtkWidget* widget, Profile** profile, bool* is_accessible);
+
+  // Return the name of a widget.
+  std::string GetWidgetName(GtkWidget* widget);
+
+  // Each of these methods constructs an AccessibilityControlInfo object
+  // and sends a notification of a specific accessibility event.
+  void SendButtonNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendCheckboxNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendComboBoxNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendListBoxNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendMenuItemNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendRadioButtonNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendTabNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendEntryNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+  void SendTextViewNotification(
+      GtkWidget* widget, NotificationType type, Profile* profile);
+
+  bool IsPassword(GtkWidget* widget);
+  void InstallEventListeners();
+  void RemoveEventListeners();
+
+  // Start and stop listening to signals.
+  void StartListening();
+  void StopListening();
+
+  // Add a signal emission hook for one particular signal name and
+  // widget type, and save the hook_id in installed_hooks so we can
+  // remove it later.
+  void InstallEventListener(
+      const char *signal_name,
+      GType widget_type,
+      GSignalEmissionHook hook_func);
+
+  friend struct DefaultSingletonTraits<AccessibilityEventRouterGtk>;
+
+  // The set of all root widgets; only descendants of these will generate
+  // accessibility notifications.
+  base::hash_map<GtkWidget*, RootWidgetInfo> root_widget_info_map_;
+
+  // Extra information about specific widgets.
+  base::hash_map<GtkWidget*, WidgetInfo> widget_info_map_;
+
+  // Installed event listener hook ids so we can remove them later.
+  std::vector<InstalledHook> installed_hooks_;
+
+  // True if we are currently listening to signals.
+  bool listening_;
+
+  // The profile associated with the most recent window event  - used to
+  // figure out where to route a few events that can't be directly traced
+  // to a window with a profile (like menu events).
+  Profile* most_recent_profile_;
+
+  // The most recent focused widget.
+  GtkWidget* most_recent_widget_;
+
+  // Used to schedule invocations of StartListening() and to defer handling
+  // of some events until the next time through the event loop.
+  ScopedRunnableMethodFactory<AccessibilityEventRouterGtk> method_factory_;
+
+  friend class AccessibilityEventRouterGtkTest;
+  FRIEND_TEST_ALL_PREFIXES(AccessibilityEventRouterGtkTest, AddRootWidgetTwice);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_ACCESSIBILITY_EVENT_ROUTER_GTK_H_
diff --git a/chrome/browser/ui/gtk/accessibility_event_router_gtk_unittest.cc b/chrome/browser/ui/gtk/accessibility_event_router_gtk_unittest.cc
new file mode 100644
index 0000000..3b99980
--- /dev/null
+++ b/chrome/browser/ui/gtk/accessibility_event_router_gtk_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/accessibility_event_router_gtk.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class AccessibilityEventRouterGtkTest : public testing::Test {
+ protected:
+  AccessibilityEventRouterGtkTest() { }
+};
+
+TEST_F(AccessibilityEventRouterGtkTest, AddRootWidgetTwice) {
+  AccessibilityEventRouterGtk* event_router =
+      AccessibilityEventRouterGtk::GetInstance();
+  TestingProfile profile;
+
+  GtkWidget* widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+  bool found = false;
+  event_router->FindWidget(widget, NULL, &found);
+  EXPECT_FALSE(found);
+
+  event_router->AddRootWidget(widget, &profile);
+  event_router->FindWidget(widget, NULL, &found);
+  EXPECT_TRUE(found);
+
+  event_router->AddRootWidget(widget, &profile);
+  event_router->FindWidget(widget, NULL, &found);
+  EXPECT_TRUE(found);
+
+  event_router->RemoveRootWidget(widget);
+  event_router->FindWidget(widget, NULL, &found);
+  EXPECT_TRUE(found);
+
+  event_router->RemoveRootWidget(widget);
+  event_router->FindWidget(widget, NULL, &found);
+  EXPECT_FALSE(found);
+
+  gtk_widget_destroy(widget);
+};
diff --git a/chrome/browser/ui/gtk/accessible_widget_helper_gtk.cc b/chrome/browser/ui/gtk/accessible_widget_helper_gtk.cc
new file mode 100644
index 0000000..eb449ef
--- /dev/null
+++ b/chrome/browser/ui/gtk/accessible_widget_helper_gtk.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+
+#include "chrome/browser/accessibility_events.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/notification_service.h"
+#include "ui/base/l10n/l10n_util.h"
+
+AccessibleWidgetHelper::AccessibleWidgetHelper(
+    GtkWidget* root_widget, Profile* profile)
+    : accessibility_event_router_(AccessibilityEventRouterGtk::GetInstance()),
+      profile_(profile),
+      root_widget_(root_widget) {
+  CHECK(profile_);
+  accessibility_event_router_->AddRootWidget(root_widget_, profile_);
+}
+
+AccessibleWidgetHelper::~AccessibleWidgetHelper() {
+  if (!window_title_.empty()) {
+    AccessibilityWindowInfo info(profile_, window_title_);
+    NotificationService::current()->Notify(
+        NotificationType::ACCESSIBILITY_WINDOW_CLOSED,
+        Source<Profile>(profile_),
+        Details<AccessibilityWindowInfo>(&info));
+  }
+
+  if (root_widget_)
+    accessibility_event_router_->RemoveRootWidget(root_widget_);
+  for (std::set<GtkWidget*>::iterator it = managed_widgets_.begin();
+       it != managed_widgets_.end();
+       ++it) {
+    accessibility_event_router_->RemoveWidgetNameOverride(*it);
+  }
+}
+
+void AccessibleWidgetHelper::SendOpenWindowNotification(
+    const std::string& window_title) {
+  window_title_ = window_title;
+  AccessibilityWindowInfo info(profile_, window_title);
+  NotificationService::current()->Notify(
+      NotificationType::ACCESSIBILITY_WINDOW_OPENED,
+      Source<Profile>(profile_),
+      Details<AccessibilityWindowInfo>(&info));
+}
+
+void AccessibleWidgetHelper::SetWidgetName(
+    GtkWidget* widget, std::string name) {
+  if (managed_widgets_.find(widget) != managed_widgets_.end()) {
+    // AccessibilityEventRouterGtk reference-counts its widgets, but we
+    // don't. In order to avoid a memory leak, tell the event router
+    // to deref first, so the resulting refcount is unchanged after we
+    // call SetWidgetName.
+    accessibility_event_router_->RemoveWidgetNameOverride(widget);
+  }
+
+  accessibility_event_router_->AddWidgetNameOverride(widget, name);
+  managed_widgets_.insert(widget);
+}
+
+void AccessibleWidgetHelper::SetWidgetName(
+    GtkWidget* widget, int string_id) {
+  SetWidgetName(widget, l10n_util::GetStringUTF8(string_id));
+}
diff --git a/chrome/browser/ui/gtk/accessible_widget_helper_gtk.h b/chrome/browser/ui/gtk/accessible_widget_helper_gtk.h
new file mode 100644
index 0000000..6cff59c
--- /dev/null
+++ b/chrome/browser/ui/gtk/accessible_widget_helper_gtk.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_ACCESSIBLE_WIDGET_HELPER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_ACCESSIBLE_WIDGET_HELPER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/singleton.h"
+#include "chrome/browser/accessibility_events.h"
+#include "chrome/browser/ui/gtk/accessibility_event_router_gtk.h"
+
+class Profile;
+
+// NOTE: This class is part of the Accessibility Extension API, which lets
+// extensions receive accessibility events. It's distinct from code that
+// implements platform accessibility APIs like MSAA or ATK.
+//
+// Helper class that helps to manage the accessibility information for all
+// of the widgets in a container.  Create an instance of this class for
+// each container GtkWidget (like a dialog) that should send accessibility
+// events for all of its descendants.
+//
+// Most controls have default behavior for accessibility; when this needs
+// to be augmented, call one of the methods below to change its details.
+//
+// All of the information managed by this class is registered with the
+// (global) AccessibilityEventRouterGtk and unregistered when this object is
+// destroyed.
+class AccessibleWidgetHelper {
+ public:
+  // Contruct an AccessibleWidgetHelper that makes the given root widget
+  // accessible for the lifetime of this object, sending accessibility
+  // notifications to the given profile.
+  AccessibleWidgetHelper(GtkWidget* root_widget, Profile* profile);
+
+  virtual ~AccessibleWidgetHelper();
+
+  // Send a notification that a new window was opened now, and a
+  // corresponding close window notification when this object
+  // goes out of scope.
+  void SendOpenWindowNotification(const std::string& window_title);
+
+  // Use the following string as the name of this widget, instead of the
+  // gtk label associated with the widget.
+  void SetWidgetName(GtkWidget* widget, std::string name);
+
+  // Use the following string as the name of this widget, instead of the
+  // gtk label associated with the widget.
+  void SetWidgetName(GtkWidget* widget, int string_id);
+
+ private:
+  AccessibilityEventRouterGtk* accessibility_event_router_;
+  Profile* profile_;
+  GtkWidget* root_widget_;
+  std::string window_title_;
+  std::set<GtkWidget*> managed_widgets_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_ACCESSIBLE_WIDGET_HELPER_GTK_H_
diff --git a/chrome/browser/ui/gtk/back_forward_button_gtk.cc b/chrome/browser/ui/gtk/back_forward_button_gtk.cc
new file mode 100644
index 0000000..2810126
--- /dev/null
+++ b/chrome/browser/ui/gtk/back_forward_button_gtk.cc
@@ -0,0 +1,129 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/back_forward_button_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/message_loop.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// The time in milliseconds between when the user clicks and the menu appears.
+static const int kMenuTimerDelay = 500;
+
+BackForwardButtonGtk::BackForwardButtonGtk(Browser* browser, bool is_forward)
+    : browser_(browser),
+      is_forward_(is_forward),
+      show_menu_factory_(this) {
+  int normal, pushed, hover, disabled, tooltip;
+  const char* stock;
+  if (is_forward) {
+    normal = IDR_FORWARD;
+    pushed = IDR_FORWARD_P;
+    hover = IDR_FORWARD_H;
+    disabled = IDR_FORWARD_D;
+    tooltip = IDS_TOOLTIP_FORWARD;
+    stock = GTK_STOCK_GO_FORWARD;
+  } else {
+    normal = IDR_BACK;
+    pushed = IDR_BACK_P;
+    hover = IDR_BACK_H;
+    disabled = IDR_BACK_D;
+    tooltip = IDS_TOOLTIP_BACK;
+    stock = GTK_STOCK_GO_BACK;
+  }
+  button_.reset(new CustomDrawButton(
+      GtkThemeProvider::GetFrom(browser_->profile()),
+      normal, pushed, hover, disabled, stock, GTK_ICON_SIZE_SMALL_TOOLBAR));
+  gtk_widget_set_tooltip_text(widget(),
+                              l10n_util::GetStringUTF8(tooltip).c_str());
+  menu_model_.reset(new BackForwardMenuModel(browser, is_forward ?
+      BackForwardMenuModel::FORWARD_MENU :
+      BackForwardMenuModel::BACKWARD_MENU));
+
+  g_signal_connect(widget(), "clicked",
+                   G_CALLBACK(OnClickThunk), this);
+  g_signal_connect(widget(), "button-press-event",
+                   G_CALLBACK(OnButtonPressThunk), this);
+  gtk_widget_add_events(widget(), GDK_POINTER_MOTION_MASK);
+  g_signal_connect(widget(), "motion-notify-event",
+                   G_CALLBACK(OnMouseMoveThunk), this);
+
+  // Popup the menu as left-aligned relative to this widget rather than the
+  // default of right aligned.
+  g_object_set_data(G_OBJECT(widget()), "left-align-popup",
+                    reinterpret_cast<void*>(true));
+
+  gtk_util::SetButtonTriggersNavigation(widget());
+}
+
+BackForwardButtonGtk::~BackForwardButtonGtk() {
+}
+
+void BackForwardButtonGtk::StoppedShowing() {
+  button_->UnsetPaintOverride();
+}
+
+bool BackForwardButtonGtk::AlwaysShowIconForCmd(int command_id) const {
+  return true;
+}
+
+void BackForwardButtonGtk::ShowBackForwardMenu(int button, guint32 event_time) {
+  menu_.reset(new MenuGtk(this, menu_model_.get()));
+  button_->SetPaintOverride(GTK_STATE_ACTIVE);
+  menu_->PopupForWidget(widget(), button, event_time);
+}
+
+void BackForwardButtonGtk::OnClick(GtkWidget* widget) {
+  show_menu_factory_.RevokeAll();
+
+  browser_->ExecuteCommandWithDisposition(
+      is_forward_ ? IDC_FORWARD : IDC_BACK,
+      gtk_util::DispositionForCurrentButtonPressEvent());
+}
+
+gboolean BackForwardButtonGtk::OnButtonPress(GtkWidget* widget,
+                                             GdkEventButton* event) {
+  if (event->button == 3)
+    ShowBackForwardMenu(event->button, event->time);
+
+  if (event->button != 1)
+    return FALSE;
+
+  y_position_of_last_press_ = static_cast<int>(event->y);
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      show_menu_factory_.NewRunnableMethod(
+          &BackForwardButtonGtk::ShowBackForwardMenu,
+          event->button, event->time),
+      kMenuTimerDelay);
+  return FALSE;
+}
+
+gboolean BackForwardButtonGtk::OnMouseMove(GtkWidget* widget,
+                                           GdkEventMotion* event) {
+  // If we aren't waiting to show the back forward menu, do nothing.
+  if (show_menu_factory_.empty())
+    return FALSE;
+
+  // We only count moves about a certain threshold.
+  GtkSettings* settings = gtk_widget_get_settings(widget);
+  int drag_min_distance;
+  g_object_get(settings, "gtk-dnd-drag-threshold", &drag_min_distance, NULL);
+  if (event->y - y_position_of_last_press_ < drag_min_distance)
+    return FALSE;
+
+  // We will show the menu now. Cancel the delayed event.
+  show_menu_factory_.RevokeAll();
+  ShowBackForwardMenu(/* button */ 1, event->time);
+  return FALSE;
+}
diff --git a/chrome/browser/ui/gtk/back_forward_button_gtk.h b/chrome/browser/ui/gtk/back_forward_button_gtk.h
new file mode 100644
index 0000000..6a5806a
--- /dev/null
+++ b/chrome/browser/ui/gtk/back_forward_button_gtk.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_BACK_FORWARD_BUTTON_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BACK_FORWARD_BUTTON_GTK_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class BackForwardMenuModel;
+class Browser;
+
+typedef struct _GtkWidget GtkWidget;
+
+// When clicked, these buttons will navigate forward or backward. When
+// pressed and held, they show a dropdown menu of recent web sites.
+class BackForwardButtonGtk : MenuGtk::Delegate {
+ public:
+  BackForwardButtonGtk(Browser* browser, bool is_forward);
+  virtual ~BackForwardButtonGtk();
+
+  // MenuGtk::Delegate implementation.
+  virtual void StoppedShowing();
+  virtual bool AlwaysShowIconForCmd(int command_id) const;
+
+  GtkWidget* widget() { return button_->widget(); }
+
+ private:
+  // Executes the browser command.
+  CHROMEGTK_CALLBACK_0(BackForwardButtonGtk, void, OnClick);
+
+  // Starts a timer to show the dropdown menu.
+  CHROMEGTK_CALLBACK_1(BackForwardButtonGtk, gboolean, OnButtonPress,
+                       GdkEventButton*);
+
+  // If there is a timer to show the dropdown menu, and the mouse has moved
+  // sufficiently down the screen, cancel the timer and immediately show the
+  // menu.
+  CHROMEGTK_CALLBACK_1(BackForwardButtonGtk, gboolean, OnMouseMove,
+                       GdkEventMotion*);
+
+  // Shows the dropdown menu.
+  void ShowBackForwardMenu(int button, guint32 event_time);
+
+  // The menu gets reset every time it is shown.
+  scoped_ptr<MenuGtk> menu_;
+
+  scoped_ptr<CustomDrawButton> button_;
+
+  // The browser to which we will send commands.
+  Browser* browser_;
+
+  // Whether this button is a forward button.
+  bool is_forward_;
+
+  // The dropdown menu model.
+  scoped_ptr<BackForwardMenuModel> menu_model_;
+
+  // The y position of the last mouse down event.
+  int y_position_of_last_press_;
+
+  ScopedRunnableMethodFactory<BackForwardButtonGtk> show_menu_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackForwardButtonGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BACK_FORWARD_BUTTON_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_bar_gtk.cc b/chrome/browser/ui/gtk/bookmark_bar_gtk.cc
new file mode 100644
index 0000000..b3d7417
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bar_gtk.cc
@@ -0,0 +1,1428 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_bar_gtk.h"
+
+#include <vector>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_node_data.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/ntp_background_util.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/sync_ui_util.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/bookmark_menu_controller_gtk.h"
+#include "chrome/browser/ui/gtk/bookmark_tree_model.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/hover_controller_gtk.h"
+#include "chrome/browser/ui/gtk/import_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+#include "chrome/browser/ui/gtk/tabstrip_origin_provider.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// The showing height of the bar.
+const int kBookmarkBarHeight = 29;
+
+// Padding for when the bookmark bar is floating.
+const int kTopBottomNTPPadding = 12;
+const int kLeftRightNTPPadding = 8;
+
+// Padding around the bar's content area when the bookmark bar is floating.
+const int kNTPPadding = 2;
+
+// The number of pixels of rounding on the corners of the bookmark bar content
+// area when in floating mode.
+const int kNTPRoundedness = 3;
+
+// The height of the bar when it is "hidden". It is usually not completely
+// hidden because even when it is closed it forms the bottom few pixels of
+// the toolbar.
+const int kBookmarkBarMinimumHeight = 3;
+
+// Left-padding for the instructional text.
+const int kInstructionsPadding = 6;
+
+// Padding around the "Other Bookmarks" button.
+const int kOtherBookmarksPaddingHorizontal = 2;
+const int kOtherBookmarksPaddingVertical = 1;
+
+// The targets accepted by the toolbar and folder buttons for DnD.
+const int kDestTargetList[] = { ui::CHROME_BOOKMARK_ITEM,
+                                ui::CHROME_NAMED_URL,
+                                ui::TEXT_URI_LIST,
+                                ui::NETSCAPE_URL,
+                                ui::TEXT_PLAIN, -1 };
+
+// Acceptable drag actions for the bookmark bar drag destinations.
+const GdkDragAction kDragAction =
+    GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY);
+
+void SetToolBarStyle() {
+  static bool style_was_set = false;
+
+  if (style_was_set)
+    return;
+  style_was_set = true;
+
+  gtk_rc_parse_string(
+      "style \"chrome-bookmark-toolbar\" {"
+      "  xthickness = 0\n"
+      "  ythickness = 0\n"
+      "  GtkWidget::focus-padding = 0\n"
+      "  GtkContainer::border-width = 0\n"
+      "  GtkToolbar::internal-padding = 1\n"
+      "  GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
+      "}\n"
+      "widget \"*chrome-bookmark-toolbar\" style \"chrome-bookmark-toolbar\"");
+}
+
+}  // namespace
+
+const int BookmarkBarGtk::kBookmarkBarNTPHeight = 57;
+
+BookmarkBarGtk::BookmarkBarGtk(BrowserWindowGtk* window,
+                               Profile* profile, Browser* browser,
+                               TabstripOriginProvider* tabstrip_origin_provider)
+    : profile_(NULL),
+      page_navigator_(NULL),
+      browser_(browser),
+      window_(window),
+      tabstrip_origin_provider_(tabstrip_origin_provider),
+      model_(NULL),
+      instructions_(NULL),
+      sync_service_(NULL),
+      dragged_node_(NULL),
+      drag_icon_(NULL),
+      toolbar_drop_item_(NULL),
+      theme_provider_(GtkThemeProvider::GetFrom(profile)),
+      show_instructions_(true),
+      menu_bar_helper_(this),
+      floating_(false),
+      last_allocation_width_(-1),
+      throbbing_widget_(NULL),
+      method_factory_(this) {
+  if (profile->GetProfileSyncService()) {
+    // Obtain a pointer to the profile sync service and add our instance as an
+    // observer.
+    sync_service_ = profile->GetProfileSyncService();
+    sync_service_->AddObserver(this);
+  }
+
+  Init(profile);
+  SetProfile(profile);
+  // Force an update by simulating being in the wrong state.
+  floating_ = !ShouldBeFloating();
+  UpdateFloatingState();
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+BookmarkBarGtk::~BookmarkBarGtk() {
+  RemoveAllBookmarkButtons();
+  bookmark_toolbar_.Destroy();
+  event_box_.Destroy();
+}
+
+void BookmarkBarGtk::SetProfile(Profile* profile) {
+  DCHECK(profile);
+  if (profile_ == profile)
+    return;
+
+  RemoveAllBookmarkButtons();
+
+  profile_ = profile;
+
+  if (model_)
+    model_->RemoveObserver(this);
+
+  // TODO(erg): Handle extensions
+
+  model_ = profile_->GetBookmarkModel();
+  model_->AddObserver(this);
+  if (model_->IsLoaded())
+    Loaded(model_);
+
+  // else case: we'll receive notification back from the BookmarkModel when done
+  // loading, then we'll populate the bar.
+}
+
+void BookmarkBarGtk::SetPageNavigator(PageNavigator* navigator) {
+  page_navigator_ = navigator;
+}
+
+void BookmarkBarGtk::Init(Profile* profile) {
+  event_box_.Own(gtk_event_box_new());
+  g_signal_connect(event_box_.get(), "destroy",
+                   G_CALLBACK(&OnEventBoxDestroyThunk), this);
+  g_signal_connect(event_box_.get(), "button-press-event",
+                   G_CALLBACK(&OnButtonPressedThunk), this);
+
+  ntp_padding_box_ = gtk_alignment_new(0, 0, 1, 1);
+  gtk_container_add(GTK_CONTAINER(event_box_.get()), ntp_padding_box_);
+
+  paint_box_ = gtk_event_box_new();
+  gtk_container_add(GTK_CONTAINER(ntp_padding_box_), paint_box_);
+  GdkColor paint_box_color =
+      theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
+  gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
+  gtk_widget_add_events(paint_box_, GDK_POINTER_MOTION_MASK |
+                                    GDK_BUTTON_PRESS_MASK);
+
+  bookmark_hbox_ = gtk_hbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(paint_box_), bookmark_hbox_);
+
+  instructions_ = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(instructions_), 0, 0,
+                            kInstructionsPadding, 0);
+  instructions_gtk_.reset(new BookmarkBarInstructionsGtk(this, profile));
+  gtk_container_add(GTK_CONTAINER(instructions_), instructions_gtk_->widget());
+  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), instructions_,
+                     TRUE, TRUE, 0);
+
+  gtk_drag_dest_set(instructions_,
+      GtkDestDefaults(GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION),
+      NULL, 0, kDragAction);
+  ui::SetDestTargetList(instructions_, kDestTargetList);
+  g_signal_connect(instructions_, "drag-data-received",
+                   G_CALLBACK(&OnDragReceivedThunk), this);
+
+  g_signal_connect(event_box_.get(), "expose-event",
+                   G_CALLBACK(&OnEventBoxExposeThunk), this);
+  UpdateEventBoxPaintability();
+
+  bookmark_toolbar_.Own(gtk_toolbar_new());
+  SetToolBarStyle();
+  gtk_widget_set_name(bookmark_toolbar_.get(), "chrome-bookmark-toolbar");
+  gtk_util::SuppressDefaultPainting(bookmark_toolbar_.get());
+  g_signal_connect(bookmark_toolbar_.get(), "size-allocate",
+                   G_CALLBACK(&OnToolbarSizeAllocateThunk), this);
+  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), bookmark_toolbar_.get(),
+                     TRUE, TRUE, 0);
+
+  overflow_button_ = theme_provider_->BuildChromeButton();
+  g_object_set_data(G_OBJECT(overflow_button_), "left-align-popup",
+                    reinterpret_cast<void*>(true));
+  SetOverflowButtonAppearance();
+  ConnectFolderButtonEvents(overflow_button_, false);
+  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), overflow_button_,
+                     FALSE, FALSE, 0);
+
+  gtk_drag_dest_set(bookmark_toolbar_.get(), GTK_DEST_DEFAULT_DROP,
+                    NULL, 0, kDragAction);
+  ui::SetDestTargetList(bookmark_toolbar_.get(), kDestTargetList);
+  g_signal_connect(bookmark_toolbar_.get(), "drag-motion",
+                   G_CALLBACK(&OnToolbarDragMotionThunk), this);
+  g_signal_connect(bookmark_toolbar_.get(), "drag-leave",
+                   G_CALLBACK(&OnDragLeaveThunk), this);
+  g_signal_connect(bookmark_toolbar_.get(), "drag-data-received",
+                   G_CALLBACK(&OnDragReceivedThunk), this);
+
+  GtkWidget* vseparator = theme_provider_->CreateToolbarSeparator();
+  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), vseparator,
+                     FALSE, FALSE, 0);
+
+  // We pack the button manually (rather than using gtk_button_set_*) so that
+  // we can have finer control over its label.
+  other_bookmarks_button_ = theme_provider_->BuildChromeButton();
+  ConnectFolderButtonEvents(other_bookmarks_button_, false);
+  GtkWidget* other_padding = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(other_padding),
+                            kOtherBookmarksPaddingVertical,
+                            kOtherBookmarksPaddingVertical,
+                            kOtherBookmarksPaddingHorizontal,
+                            kOtherBookmarksPaddingHorizontal);
+  gtk_container_add(GTK_CONTAINER(other_padding), other_bookmarks_button_);
+  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_padding,
+                     FALSE, FALSE, 0);
+
+  sync_error_button_ = theme_provider_->BuildChromeButton();
+  gtk_button_set_image(
+      GTK_BUTTON(sync_error_button_),
+      gtk_image_new_from_pixbuf(
+          ResourceBundle::GetSharedInstance().GetPixbufNamed(IDR_WARNING)));
+  g_signal_connect(sync_error_button_, "button-press-event",
+                   G_CALLBACK(OnSyncErrorButtonPressedThunk), this);
+  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), sync_error_button_,
+                     FALSE, FALSE, 0);
+
+  gtk_widget_set_size_request(event_box_.get(), -1, kBookmarkBarMinimumHeight);
+
+  slide_animation_.reset(new ui::SlideAnimation(this));
+
+  ViewIDUtil::SetID(other_bookmarks_button_, VIEW_ID_OTHER_BOOKMARKS);
+  ViewIDUtil::SetID(widget(), VIEW_ID_BOOKMARK_BAR);
+
+  gtk_widget_show_all(widget());
+  gtk_widget_hide(widget());
+}
+
+void BookmarkBarGtk::Show(bool animate) {
+  gtk_widget_show_all(widget());
+  bool old_floating = floating_;
+  UpdateFloatingState();
+  // TODO(estade): animate the transition between floating and non.
+  animate = animate && (old_floating == floating_);
+  if (animate) {
+    slide_animation_->Show();
+  } else {
+    slide_animation_->Reset(1);
+    AnimationProgressed(slide_animation_.get());
+  }
+
+  // Hide out behind the findbar. This is rather fragile code, it could
+  // probably be improved.
+  if (floating_) {
+    if (theme_provider_->UseGtkTheme()) {
+      if (GTK_WIDGET_REALIZED(event_box_->parent))
+        gdk_window_lower(event_box_->parent->window);
+      if (GTK_WIDGET_REALIZED(event_box_.get()))
+        gdk_window_lower(event_box_->window);
+    } else {  // Chromium theme mode.
+      if (GTK_WIDGET_REALIZED(paint_box_)) {
+        gdk_window_lower(paint_box_->window);
+        // The event box won't stay below its children's GdkWindows unless we
+        // toggle the above-child property here. If the event box doesn't stay
+        // below its children then events will be routed to it rather than the
+        // children.
+        gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), TRUE);
+        gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), FALSE);
+      }
+    }
+  }
+
+  if (sync_ui_util::ShouldShowSyncErrorButton(sync_service_)) {
+    gtk_widget_show(sync_error_button_);
+  } else {
+    gtk_widget_hide(sync_error_button_);
+  }
+
+  // Maybe show the instructions
+  if (show_instructions_) {
+    gtk_widget_hide(bookmark_toolbar_.get());
+    gtk_widget_show(instructions_);
+  } else {
+    gtk_widget_hide(instructions_);
+    gtk_widget_show(bookmark_toolbar_.get());
+  }
+
+  SetChevronState();
+}
+
+void BookmarkBarGtk::Hide(bool animate) {
+  UpdateFloatingState();
+
+  // After coming out of fullscreen, the browser window sets the bookmark bar
+  // to the "hidden" state, which means we need to show our minimum height.
+  gtk_widget_show(widget());
+  // Sometimes we get called without a matching call to open. If that happens
+  // then force hide.
+  if (slide_animation_->IsShowing() && animate) {
+    slide_animation_->Hide();
+  } else {
+    gtk_widget_hide(bookmark_hbox_);
+    slide_animation_->Reset(0);
+    AnimationProgressed(slide_animation_.get());
+  }
+}
+
+void BookmarkBarGtk::OnStateChanged() {
+  if (sync_ui_util::ShouldShowSyncErrorButton(sync_service_)) {
+    gtk_widget_show(sync_error_button_);
+  } else {
+    gtk_widget_hide(sync_error_button_);
+  }
+}
+
+void BookmarkBarGtk::ShowImportDialog() {
+  ImportDialogGtk::Show(window_->window(), browser_->profile(),
+                        importer::FAVORITES);
+}
+
+void BookmarkBarGtk::EnterFullscreen() {
+  if (ShouldBeFloating())
+    Show(false);
+  else
+    gtk_widget_hide(widget());
+}
+
+int BookmarkBarGtk::GetHeight() {
+  return event_box_->allocation.height - kBookmarkBarMinimumHeight;
+}
+
+bool BookmarkBarGtk::IsAnimating() {
+  return slide_animation_->is_animating();
+}
+
+bool BookmarkBarGtk::OnNewTabPage() {
+  return (browser_ && browser_->GetSelectedTabContents() &&
+          browser_->GetSelectedTabContents()->ShouldShowBookmarkBar());
+}
+
+void BookmarkBarGtk::Loaded(BookmarkModel* model) {
+  // If |instructions_| has been nulled, we are in the middle of browser
+  // shutdown. Do nothing.
+  if (!instructions_)
+    return;
+
+  RemoveAllBookmarkButtons();
+  CreateAllBookmarkButtons();
+}
+
+void BookmarkBarGtk::BookmarkModelBeingDeleted(BookmarkModel* model) {
+  // The bookmark model should never be deleted before us. This code exists
+  // to check for regressions in shutdown code and not crash.
+  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
+    NOTREACHED();
+
+  // Do minimal cleanup, presumably we'll be deleted shortly.
+  model_->RemoveObserver(this);
+  model_ = NULL;
+}
+
+void BookmarkBarGtk::BookmarkNodeMoved(BookmarkModel* model,
+                                       const BookmarkNode* old_parent,
+                                       int old_index,
+                                       const BookmarkNode* new_parent,
+                                       int new_index) {
+  const BookmarkNode* node = new_parent->GetChild(new_index);
+  BookmarkNodeRemoved(model, old_parent, old_index, node);
+  BookmarkNodeAdded(model, new_parent, new_index);
+}
+
+void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model,
+                                       const BookmarkNode* parent,
+                                       int index) {
+  const BookmarkNode* node = parent->GetChild(index);
+  if (parent != model_->GetBookmarkBarNode()) {
+    StartThrobbing(node);
+    return;
+  }
+  DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
+
+  GtkToolItem* item = CreateBookmarkToolItem(node);
+  gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()),
+                     item, index);
+  if (node->is_folder())
+    menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
+
+  SetInstructionState();
+  SetChevronState();
+
+  StartThrobbingAfterAllocation(GTK_WIDGET(item));
+}
+
+void BookmarkBarGtk::BookmarkNodeRemoved(BookmarkModel* model,
+                                         const BookmarkNode* parent,
+                                         int old_index,
+                                         const BookmarkNode* node) {
+  if (parent != model_->GetBookmarkBarNode()) {
+    // We only care about nodes on the bookmark bar.
+    return;
+  }
+  DCHECK(old_index >= 0 && old_index < GetBookmarkButtonCount());
+
+  GtkWidget* to_remove = GTK_WIDGET(gtk_toolbar_get_nth_item(
+      GTK_TOOLBAR(bookmark_toolbar_.get()), old_index));
+  if (node->is_folder())
+    menu_bar_helper_.Remove(gtk_bin_get_child(GTK_BIN(to_remove)));
+  gtk_container_remove(GTK_CONTAINER(bookmark_toolbar_.get()),
+                       to_remove);
+
+  SetInstructionState();
+  SetChevronState();
+}
+
+void BookmarkBarGtk::BookmarkNodeChanged(BookmarkModel* model,
+                                         const BookmarkNode* node) {
+  if (node->GetParent() != model_->GetBookmarkBarNode()) {
+    // We only care about nodes on the bookmark bar.
+    return;
+  }
+  int index = model_->GetBookmarkBarNode()->IndexOfChild(node);
+  DCHECK(index != -1);
+
+  GtkToolItem* item = gtk_toolbar_get_nth_item(
+      GTK_TOOLBAR(bookmark_toolbar_.get()), index);
+  GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
+  bookmark_utils::ConfigureButtonForNode(node, model, button, theme_provider_);
+  SetChevronState();
+}
+
+void BookmarkBarGtk::BookmarkNodeFavIconLoaded(BookmarkModel* model,
+                                               const BookmarkNode* node) {
+  BookmarkNodeChanged(model, node);
+}
+
+void BookmarkBarGtk::BookmarkNodeChildrenReordered(BookmarkModel* model,
+                                                   const BookmarkNode* node) {
+  if (node != model_->GetBookmarkBarNode())
+    return;  // We only care about reordering of the bookmark bar node.
+
+  // Purge and rebuild the bar.
+  RemoveAllBookmarkButtons();
+  CreateAllBookmarkButtons();
+}
+
+void BookmarkBarGtk::CreateAllBookmarkButtons() {
+  const BookmarkNode* bar = model_->GetBookmarkBarNode();
+  DCHECK(bar && model_->other_node());
+
+  // Create a button for each of the children on the bookmark bar.
+  for (int i = 0; i < bar->GetChildCount(); ++i) {
+    const BookmarkNode* node = bar->GetChild(i);
+    GtkToolItem* item = CreateBookmarkToolItem(node);
+    gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1);
+    if (node->is_folder())
+      menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
+  }
+
+  bookmark_utils::ConfigureButtonForNode(model_->other_node(),
+      model_, other_bookmarks_button_, theme_provider_);
+
+  SetInstructionState();
+  SetChevronState();
+}
+
+void BookmarkBarGtk::SetInstructionState() {
+  show_instructions_ = (model_->GetBookmarkBarNode()->GetChildCount() == 0);
+  if (show_instructions_) {
+    gtk_widget_hide(bookmark_toolbar_.get());
+    gtk_widget_show_all(instructions_);
+  } else {
+    gtk_widget_hide(instructions_);
+    gtk_widget_show(bookmark_toolbar_.get());
+  }
+}
+
+void BookmarkBarGtk::SetChevronState() {
+  if (!GTK_WIDGET_VISIBLE(bookmark_hbox_))
+    return;
+
+  if (show_instructions_) {
+    gtk_widget_hide(overflow_button_);
+    return;
+  }
+
+  int extra_space = 0;
+  if (GTK_WIDGET_VISIBLE(overflow_button_))
+    extra_space = overflow_button_->allocation.width;
+
+  int overflow_idx = GetFirstHiddenBookmark(extra_space, NULL);
+  if (overflow_idx == -1)
+    gtk_widget_hide(overflow_button_);
+  else
+    gtk_widget_show_all(overflow_button_);
+}
+
+void BookmarkBarGtk::RemoveAllBookmarkButtons() {
+  gtk_util::RemoveAllChildren(bookmark_toolbar_.get());
+  menu_bar_helper_.Clear();
+  menu_bar_helper_.Add(other_bookmarks_button_);
+  menu_bar_helper_.Add(overflow_button_);
+}
+
+int BookmarkBarGtk::GetBookmarkButtonCount() {
+  GList* children = gtk_container_get_children(
+      GTK_CONTAINER(bookmark_toolbar_.get()));
+  int count = g_list_length(children);
+  g_list_free(children);
+  return count;
+}
+
+void BookmarkBarGtk::SetOverflowButtonAppearance() {
+  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(overflow_button_));
+  if (former_child)
+    gtk_widget_destroy(former_child);
+
+  GtkWidget* new_child = theme_provider_->UseGtkTheme() ?
+      gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE) :
+      gtk_image_new_from_pixbuf(ResourceBundle::GetSharedInstance().
+          GetRTLEnabledPixbufNamed(IDR_BOOKMARK_BAR_CHEVRONS));
+
+  gtk_container_add(GTK_CONTAINER(overflow_button_), new_child);
+  SetChevronState();
+}
+
+int BookmarkBarGtk::GetFirstHiddenBookmark(
+    int extra_space, std::vector<GtkWidget*>* showing_folders) {
+  int rv = 0;
+  bool overflow = false;
+  GList* toolbar_items =
+      gtk_container_get_children(GTK_CONTAINER(bookmark_toolbar_.get()));
+  for (GList* iter = toolbar_items; iter; iter = g_list_next(iter)) {
+    GtkWidget* tool_item = reinterpret_cast<GtkWidget*>(iter->data);
+    if (gtk_widget_get_direction(tool_item) == GTK_TEXT_DIR_RTL) {
+      overflow = (tool_item->allocation.x + tool_item->style->xthickness <
+                  bookmark_toolbar_.get()->allocation.x - extra_space);
+    } else {
+      overflow =
+        (tool_item->allocation.x + tool_item->allocation.width +
+         tool_item->style->xthickness >
+         bookmark_toolbar_.get()->allocation.width +
+         bookmark_toolbar_.get()->allocation.x + extra_space);
+    }
+    overflow = overflow || tool_item->allocation.x == -1;
+
+    if (overflow)
+      break;
+
+    if (showing_folders &&
+        model_->GetBookmarkBarNode()->GetChild(rv)->is_folder()) {
+      showing_folders->push_back(gtk_bin_get_child(GTK_BIN(tool_item)));
+    }
+    rv++;
+  }
+
+  g_list_free(toolbar_items);
+
+  if (!overflow)
+    return -1;
+
+  return rv;
+}
+
+bool BookmarkBarGtk::ShouldBeFloating() {
+  return (!IsAlwaysShown() || (window_ && window_->IsFullscreen())) &&
+      window_ && window_->GetDisplayedTabContents() &&
+      window_->GetDisplayedTabContents()->ShouldShowBookmarkBar();
+}
+
+void BookmarkBarGtk::UpdateFloatingState() {
+  bool old_floating = floating_;
+  floating_ = ShouldBeFloating();
+  if (floating_ == old_floating)
+    return;
+
+  if (floating_) {
+#if !defined(OS_CHROMEOS)
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), TRUE);
+#endif
+    GdkColor stroke_color = theme_provider_->UseGtkTheme() ?
+        theme_provider_->GetBorderColor() :
+        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_NTP_HEADER);
+    gtk_util::ActAsRoundedWindow(paint_box_, stroke_color, kNTPRoundedness,
+                                 gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
+
+    gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_),
+        kTopBottomNTPPadding, kTopBottomNTPPadding,
+        kLeftRightNTPPadding, kLeftRightNTPPadding);
+    gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), kNTPPadding);
+  } else {
+    gtk_util::StopActingAsRoundedWindow(paint_box_);
+#if !defined(OS_CHROMEOS)
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), FALSE);
+#endif
+    gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_), 0, 0, 0, 0);
+    gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), 0);
+  }
+
+  UpdateEventBoxPaintability();
+  // |window_| can be NULL during testing.
+  if (window_) {
+    window_->BookmarkBarIsFloating(floating_);
+
+    // Listen for parent size allocations.
+    if (floating_ && widget()->parent) {
+      // Only connect once.
+      if (g_signal_handler_find(widget()->parent, G_SIGNAL_MATCH_FUNC,
+          0, 0, NULL, reinterpret_cast<gpointer>(OnParentSizeAllocateThunk),
+          NULL) == 0) {
+        g_signal_connect(widget()->parent, "size-allocate",
+                         G_CALLBACK(OnParentSizeAllocateThunk), this);
+      }
+    }
+  }
+}
+
+void BookmarkBarGtk::UpdateEventBoxPaintability() {
+  gtk_widget_set_app_paintable(event_box_.get(),
+                               !theme_provider_->UseGtkTheme() || floating_);
+  // When using the GTK+ theme, we need to have the event box be visible so
+  // buttons don't get a halo color from the background.  When using Chromium
+  // themes, we want to let the background show through the toolbar.
+
+#if !defined(OS_CHROMEOS)
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()),
+                                   theme_provider_->UseGtkTheme());
+#endif
+}
+
+void BookmarkBarGtk::PaintEventBox() {
+  gfx::Size tab_contents_size;
+  if (GetTabContentsSize(&tab_contents_size) &&
+      tab_contents_size != last_tab_contents_size_) {
+    last_tab_contents_size_ = tab_contents_size;
+    gtk_widget_queue_draw(event_box_.get());
+  }
+}
+
+bool BookmarkBarGtk::GetTabContentsSize(gfx::Size* size) {
+  Browser* browser = browser_;
+  if (!browser) {
+    NOTREACHED();
+    return false;
+  }
+  TabContents* tab_contents = browser->GetSelectedTabContents();
+  if (!tab_contents) {
+    // It is possible to have a browser but no TabContents while under testing,
+    // so don't NOTREACHED() and error the program.
+    return false;
+  }
+  if (!tab_contents->view()) {
+    NOTREACHED();
+    return false;
+  }
+  *size = tab_contents->view()->GetContainerSize();
+  return true;
+}
+
+void BookmarkBarGtk::StartThrobbing(const BookmarkNode* node) {
+  const BookmarkNode* parent_on_bb = NULL;
+  for (const BookmarkNode* parent = node; parent;
+       parent = parent->GetParent()) {
+    if (parent->GetParent() == model_->GetBookmarkBarNode()) {
+      parent_on_bb = parent;
+      break;
+    }
+  }
+
+  GtkWidget* widget_to_throb = NULL;
+
+  if (!parent_on_bb) {
+    // Descendant of "Other Bookmarks".
+    widget_to_throb = other_bookmarks_button_;
+  } else {
+    int hidden = GetFirstHiddenBookmark(0, NULL);
+    int idx = model_->GetBookmarkBarNode()->IndexOfChild(parent_on_bb);
+
+    if (hidden >= 0 && hidden <= idx) {
+      widget_to_throb = overflow_button_;
+    } else {
+      widget_to_throb = gtk_bin_get_child(GTK_BIN(gtk_toolbar_get_nth_item(
+          GTK_TOOLBAR(bookmark_toolbar_.get()), idx)));
+    }
+  }
+
+  SetThrobbingWidget(widget_to_throb);
+}
+
+void BookmarkBarGtk::SetThrobbingWidget(GtkWidget* widget) {
+  if (throbbing_widget_) {
+    HoverControllerGtk* hover_controller =
+        HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
+    if (hover_controller)
+      hover_controller->StartThrobbing(0);
+
+    g_signal_handlers_disconnect_by_func(
+        throbbing_widget_,
+        reinterpret_cast<gpointer>(OnThrobbingWidgetDestroyThunk),
+        this);
+    g_object_unref(throbbing_widget_);
+    throbbing_widget_ = NULL;
+  }
+
+  if (widget) {
+    throbbing_widget_ = widget;
+    g_object_ref(throbbing_widget_);
+    g_signal_connect(throbbing_widget_, "destroy",
+                     G_CALLBACK(OnThrobbingWidgetDestroyThunk), this);
+
+    HoverControllerGtk* hover_controller =
+        HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
+    if (hover_controller)
+      hover_controller->StartThrobbing(4);
+  }
+}
+
+void BookmarkBarGtk::OnItemAllocate(GtkWidget* item,
+                                    GtkAllocation* allocation) {
+  // We only want to fire on the item's first allocation.
+  g_signal_handlers_disconnect_by_func(
+      item, reinterpret_cast<gpointer>(&OnItemAllocateThunk), this);
+
+  GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
+  const BookmarkNode* node = GetNodeForToolButton(button);
+  if (node)
+    StartThrobbing(node);
+}
+
+void BookmarkBarGtk::StartThrobbingAfterAllocation(GtkWidget* item) {
+  g_signal_connect_after(
+      item, "size-allocate", G_CALLBACK(OnItemAllocateThunk), this);
+}
+
+bool BookmarkBarGtk::IsAlwaysShown() {
+  return profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
+}
+
+void BookmarkBarGtk::AnimationProgressed(const ui::Animation* animation) {
+  DCHECK_EQ(animation, slide_animation_.get());
+
+  int max_height = ShouldBeFloating() ?
+                   kBookmarkBarNTPHeight : kBookmarkBarHeight;
+  gint height =
+      static_cast<gint>(animation->GetCurrentValue() *
+                        (max_height - kBookmarkBarMinimumHeight)) +
+      kBookmarkBarMinimumHeight;
+  gtk_widget_set_size_request(event_box_.get(), -1, height);
+}
+
+void BookmarkBarGtk::AnimationEnded(const ui::Animation* animation) {
+  DCHECK_EQ(animation, slide_animation_.get());
+
+  if (!slide_animation_->IsShowing()) {
+    gtk_widget_hide(bookmark_hbox_);
+
+    // We can be windowless during unit tests.
+    if (window_) {
+      // Because of our constant resizing and our toolbar/bookmark bar overlap
+      // shenanigans, gtk+ gets confused, partially draws parts of the bookmark
+      // bar into the toolbar and than doesn't queue a redraw to fix it. So do
+      // it manually by telling the toolbar area to redraw itself.
+      window_->QueueToolbarRedraw();
+    }
+  }
+}
+
+void BookmarkBarGtk::Observe(NotificationType type,
+                             const NotificationSource& source,
+                             const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    if (model_ && model_->IsLoaded()) {
+      // Regenerate the bookmark bar with all new objects with their theme
+      // properties set correctly for the new theme.
+      RemoveAllBookmarkButtons();
+      CreateAllBookmarkButtons();
+    }
+
+    UpdateEventBoxPaintability();
+
+    GdkColor paint_box_color =
+        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
+    gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
+
+    if (floating_) {
+      GdkColor stroke_color = theme_provider_->UseGtkTheme() ?
+          theme_provider_->GetBorderColor() :
+          theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_NTP_HEADER);
+      gtk_util::SetRoundedWindowBorderColor(paint_box_, stroke_color);
+    }
+
+    SetOverflowButtonAppearance();
+  }
+}
+
+GtkWidget* BookmarkBarGtk::CreateBookmarkButton(const BookmarkNode* node) {
+  GtkWidget* button = theme_provider_->BuildChromeButton();
+  bookmark_utils::ConfigureButtonForNode(node, model_, button, theme_provider_);
+
+  // The tool item is also a source for dragging
+  gtk_drag_source_set(button, GDK_BUTTON1_MASK, NULL, 0,
+      static_cast<GdkDragAction>(GDK_ACTION_MOVE | GDK_ACTION_COPY));
+  int target_mask = bookmark_utils::GetCodeMask(node->is_folder());
+  ui::SetSourceTargetListFromCodeMask(button, target_mask);
+  g_signal_connect(button, "drag-begin",
+                   G_CALLBACK(&OnButtonDragBeginThunk), this);
+  g_signal_connect(button, "drag-end",
+                   G_CALLBACK(&OnButtonDragEndThunk), this);
+  g_signal_connect(button, "drag-data-get",
+                   G_CALLBACK(&OnButtonDragGetThunk), this);
+  // We deliberately don't connect to "drag-data-delete" because the action of
+  // moving a button will regenerate all the contents of the bookmarks bar
+  // anyway.
+
+  if (node->is_url()) {
+    // Connect to 'button-release-event' instead of 'clicked' because we need
+    // access to the modifier keys and we do different things on each
+    // button.
+    g_signal_connect(button, "button-press-event",
+                     G_CALLBACK(OnButtonPressedThunk), this);
+    g_signal_connect(button, "clicked",
+                     G_CALLBACK(OnClickedThunk), this);
+    gtk_util::SetButtonTriggersNavigation(button);
+  } else {
+    ConnectFolderButtonEvents(button, true);
+  }
+
+  return button;
+}
+
+GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) {
+  GtkWidget* button = CreateBookmarkButton(node);
+  g_object_set_data(G_OBJECT(button), "left-align-popup",
+                    reinterpret_cast<void*>(true));
+
+  GtkToolItem* item = gtk_tool_item_new();
+  gtk_container_add(GTK_CONTAINER(item), button);
+  gtk_widget_show_all(GTK_WIDGET(item));
+
+  return item;
+}
+
+void BookmarkBarGtk::ConnectFolderButtonEvents(GtkWidget* widget,
+                                               bool is_tool_item) {
+  // For toolbar items (i.e. not the overflow button or other bookmarks
+  // button), we handle motion and highlighting manually.
+  gtk_drag_dest_set(widget,
+                    is_tool_item ? GTK_DEST_DEFAULT_DROP :
+                                   GTK_DEST_DEFAULT_ALL,
+                    NULL,
+                    0,
+                    kDragAction);
+  ui::SetDestTargetList(widget, kDestTargetList);
+  g_signal_connect(widget, "drag-data-received",
+                   G_CALLBACK(&OnDragReceivedThunk), this);
+  if (is_tool_item) {
+    g_signal_connect(widget, "drag-motion",
+                     G_CALLBACK(&OnFolderDragMotionThunk), this);
+    g_signal_connect(widget, "drag-leave",
+                     G_CALLBACK(&OnDragLeaveThunk), this);
+  }
+
+  g_signal_connect(widget, "button-press-event",
+                   G_CALLBACK(OnButtonPressedThunk), this);
+  g_signal_connect(widget, "clicked",
+                   G_CALLBACK(OnFolderClickedThunk), this);
+
+  // Accept middle mouse clicking (which opens all). This must be called after
+  // connecting to "button-press-event" because the handler it attaches stops
+  // the propagation of that signal.
+  gtk_util::SetButtonClickableByMouseButtons(widget, true, true, false);
+}
+
+const BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* widget) {
+  // First check to see if |button| is special cased.
+  if (widget == other_bookmarks_button_)
+    return model_->other_node();
+  else if (widget == event_box_.get() || widget == overflow_button_)
+    return model_->GetBookmarkBarNode();
+
+  // Search the contents of |bookmark_toolbar_| for the corresponding widget
+  // and find its index.
+  GtkWidget* item_to_find = gtk_widget_get_parent(widget);
+  int index_to_use = -1;
+  int index = 0;
+  GList* children = gtk_container_get_children(
+      GTK_CONTAINER(bookmark_toolbar_.get()));
+  for (GList* item = children; item; item = item->next, index++) {
+    if (item->data == item_to_find) {
+      index_to_use = index;
+      break;
+    }
+  }
+  g_list_free(children);
+
+  if (index_to_use != -1)
+    return model_->GetBookmarkBarNode()->GetChild(index_to_use);
+
+  return NULL;
+}
+
+void BookmarkBarGtk::PopupMenuForNode(GtkWidget* sender,
+                                      const BookmarkNode* node,
+                                      GdkEventButton* event) {
+  if (!model_->IsLoaded()) {
+    // Don't do anything if the model isn't loaded.
+    return;
+  }
+
+  const BookmarkNode* parent = NULL;
+  std::vector<const BookmarkNode*> nodes;
+  if (sender == other_bookmarks_button_) {
+    nodes.push_back(node);
+    parent = model_->GetBookmarkBarNode();
+  } else if (sender != bookmark_toolbar_.get()) {
+    nodes.push_back(node);
+    parent = node->GetParent();
+  } else {
+    parent = model_->GetBookmarkBarNode();
+    nodes.push_back(parent);
+  }
+
+  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(sender));
+  current_context_menu_controller_.reset(
+      new BookmarkContextMenuController(
+          window, this, profile_, page_navigator_, parent, nodes));
+  current_context_menu_.reset(
+      new MenuGtk(NULL, current_context_menu_controller_->menu_model()));
+  current_context_menu_->PopupAsContext(
+      gfx::Point(event->x_root, event->y_root),
+      event->time);
+}
+
+gboolean BookmarkBarGtk::OnButtonPressed(GtkWidget* sender,
+                                         GdkEventButton* event) {
+  last_pressed_coordinates_ = gfx::Point(event->x, event->y);
+
+  if (event->button == 3 && GTK_WIDGET_VISIBLE(bookmark_hbox_)) {
+    const BookmarkNode* node = GetNodeForToolButton(sender);
+    DCHECK(node);
+    DCHECK(page_navigator_);
+    PopupMenuForNode(sender, node, event);
+  }
+
+  return FALSE;
+}
+
+gboolean BookmarkBarGtk::OnSyncErrorButtonPressed(GtkWidget* sender,
+                                                  GdkEventButton* event) {
+  if (sender == sync_error_button_) {
+    DCHECK(sync_service_ && !sync_service_->IsManaged());
+    sync_service_->ShowErrorUI(NULL);
+  }
+
+  return FALSE;
+}
+
+void BookmarkBarGtk::OnClicked(GtkWidget* sender) {
+  const BookmarkNode* node = GetNodeForToolButton(sender);
+  DCHECK(node);
+  DCHECK(node->is_url());
+  DCHECK(page_navigator_);
+
+  page_navigator_->OpenURL(
+      node->GetURL(), GURL(),
+      gtk_util::DispositionForCurrentButtonPressEvent(),
+      PageTransition::AUTO_BOOKMARK);
+
+  UserMetrics::RecordAction(UserMetricsAction("ClickedBookmarkBarURLButton"),
+                            profile_);
+}
+
+void BookmarkBarGtk::OnButtonDragBegin(GtkWidget* button,
+                                       GdkDragContext* drag_context) {
+  // The parent tool item might be removed during the drag. Ref it so |button|
+  // won't get destroyed.
+  g_object_ref(button->parent);
+
+  const BookmarkNode* node = GetNodeForToolButton(button);
+  DCHECK(!dragged_node_);
+  dragged_node_ = node;
+  DCHECK(dragged_node_);
+
+  drag_icon_ = bookmark_utils::GetDragRepresentationForNode(
+      node, model_, theme_provider_);
+
+  // We have to jump through some hoops to get the drag icon to line up because
+  // it is a different size than the button.
+  GtkRequisition req;
+  gtk_widget_size_request(drag_icon_, &req);
+  gfx::Rect button_rect = gtk_util::WidgetBounds(button);
+  gfx::Point drag_icon_relative =
+      gfx::Rect(req.width, req.height).CenterPoint().Add(
+          (last_pressed_coordinates_.Subtract(button_rect.CenterPoint())));
+  gtk_drag_set_icon_widget(drag_context, drag_icon_,
+                           drag_icon_relative.x(),
+                           drag_icon_relative.y());
+
+  // Hide our node, but reserve space for it on the toolbar.
+  int index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
+                                         GTK_TOOL_ITEM(button->parent));
+  gtk_widget_hide(button);
+  toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
+  g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
+  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
+                                      GTK_TOOL_ITEM(toolbar_drop_item_), index);
+  // Make sure it stays hidden for the duration of the drag.
+  gtk_widget_set_no_show_all(button, TRUE);
+}
+
+void BookmarkBarGtk::OnButtonDragEnd(GtkWidget* button,
+                                     GdkDragContext* drag_context) {
+  gtk_widget_show(button);
+  gtk_widget_set_no_show_all(button, FALSE);
+
+  ClearToolbarDropHighlighting();
+
+  DCHECK(dragged_node_);
+  dragged_node_ = NULL;
+
+  DCHECK(drag_icon_);
+  gtk_widget_destroy(drag_icon_);
+  drag_icon_ = NULL;
+
+  g_object_unref(button->parent);
+}
+
+void BookmarkBarGtk::OnButtonDragGet(GtkWidget* widget, GdkDragContext* context,
+                                     GtkSelectionData* selection_data,
+                                     guint target_type, guint time) {
+  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
+  bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
+                                           profile_);
+}
+
+void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender) {
+  // Stop its throbbing, if any.
+  HoverControllerGtk* hover_controller =
+      HoverControllerGtk::GetHoverControllerGtk(sender);
+  if (hover_controller)
+    hover_controller->StartThrobbing(0);
+
+  GdkEvent* event = gtk_get_current_event();
+  if (event->button.button == 1) {
+    PopupForButton(sender);
+  } else if (event->button.button == 2) {
+    const BookmarkNode* node = GetNodeForToolButton(sender);
+    bookmark_utils::OpenAll(window_->GetNativeHandle(),
+                            profile_, page_navigator_,
+                            node, NEW_BACKGROUND_TAB);
+  }
+}
+
+gboolean BookmarkBarGtk::ItemDraggedOverToolbar(GdkDragContext* context,
+                                                int index,
+                                                guint time) {
+  GdkAtom target_type =
+      gtk_drag_dest_find_target(bookmark_toolbar_.get(), context, NULL);
+  if (target_type == GDK_NONE) {
+    // We shouldn't act like a drop target when something that we can't deal
+    // with is dragged over the toolbar.
+    return FALSE;
+  }
+
+  if (!toolbar_drop_item_) {
+    if (dragged_node_) {
+      toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
+      g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
+    } else {
+      // Create a fake item the size of other_node().
+      //
+      // TODO(erg): Maybe somehow figure out the real size for the drop target?
+      toolbar_drop_item_ =
+          CreateBookmarkToolItem(model_->other_node());
+      g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
+    }
+  }
+
+  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
+                                      GTK_TOOL_ITEM(toolbar_drop_item_),
+                                      index);
+  if (target_type == ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM)) {
+    gdk_drag_status(context, GDK_ACTION_MOVE, time);
+  } else {
+    gdk_drag_status(context, GDK_ACTION_COPY, time);
+  }
+
+  return TRUE;
+}
+
+gboolean BookmarkBarGtk::OnToolbarDragMotion(GtkWidget* toolbar,
+                                             GdkDragContext* context,
+                                             gint x,
+                                             gint y,
+                                             guint time) {
+  gint index = gtk_toolbar_get_drop_index(GTK_TOOLBAR(toolbar), x, y);
+  return ItemDraggedOverToolbar(context, index, time);
+}
+
+int BookmarkBarGtk::GetToolbarIndexForDragOverFolder(
+    GtkWidget* button, gint x) {
+  int margin = std::min(15, static_cast<int>(0.3 * button->allocation.width));
+  if (x > margin && x < (button->allocation.width - margin))
+    return -1;
+
+  gint index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
+                                          GTK_TOOL_ITEM(button->parent));
+  if (x > margin)
+    index++;
+  return index;
+}
+
+gboolean BookmarkBarGtk::OnFolderDragMotion(GtkWidget* button,
+                                            GdkDragContext* context,
+                                            gint x,
+                                            gint y,
+                                            guint time) {
+  GdkAtom target_type = gtk_drag_dest_find_target(button, context, NULL);
+  if (target_type == GDK_NONE)
+    return FALSE;
+
+  int index = GetToolbarIndexForDragOverFolder(button, x);
+  if (index < 0) {
+    ClearToolbarDropHighlighting();
+
+    // Drag is over middle of folder.
+    gtk_drag_highlight(button);
+    if (target_type == ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM)) {
+      gdk_drag_status(context, GDK_ACTION_MOVE, time);
+    } else {
+      gdk_drag_status(context, GDK_ACTION_COPY, time);
+    }
+
+    return TRUE;
+  }
+
+  // Remove previous highlighting.
+  gtk_drag_unhighlight(button);
+  return ItemDraggedOverToolbar(context, index, time);
+}
+
+void BookmarkBarGtk::ClearToolbarDropHighlighting() {
+  if (toolbar_drop_item_) {
+    g_object_unref(toolbar_drop_item_);
+    toolbar_drop_item_ = NULL;
+  }
+
+  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
+                                      NULL, 0);
+}
+
+void BookmarkBarGtk::OnDragLeave(GtkWidget* sender,
+                                 GdkDragContext* context,
+                                 guint time) {
+  if (GTK_IS_BUTTON(sender))
+    gtk_drag_unhighlight(sender);
+
+  ClearToolbarDropHighlighting();
+}
+
+void BookmarkBarGtk::OnToolbarSizeAllocate(GtkWidget* widget,
+                                           GtkAllocation* allocation) {
+  if (bookmark_toolbar_.get()->allocation.width ==
+      last_allocation_width_) {
+    // If the width hasn't changed, then the visibility of the chevron
+    // doesn't need to change. This check prevents us from getting stuck in a
+    // loop where allocates are queued indefinitely while the visibility of
+    // overflow chevron toggles without actual resizes of the toolbar.
+    return;
+  }
+  last_allocation_width_ = bookmark_toolbar_.get()->allocation.width;
+
+  SetChevronState();
+}
+
+void BookmarkBarGtk::OnDragReceived(GtkWidget* widget,
+                                    GdkDragContext* context,
+                                    gint x, gint y,
+                                    GtkSelectionData* selection_data,
+                                    guint target_type, guint time) {
+  gboolean dnd_success = FALSE;
+  gboolean delete_selection_data = FALSE;
+
+  const BookmarkNode* dest_node = model_->GetBookmarkBarNode();
+  gint index;
+  if (widget == bookmark_toolbar_.get()) {
+    index = gtk_toolbar_get_drop_index(
+      GTK_TOOLBAR(bookmark_toolbar_.get()), x, y);
+  } else if (widget == instructions_) {
+    dest_node = model_->GetBookmarkBarNode();
+    index = 0;
+  } else {
+    index = GetToolbarIndexForDragOverFolder(widget, x);
+    if (index < 0) {
+      dest_node = GetNodeForToolButton(widget);
+      index = dest_node->GetChildCount();
+    }
+  }
+
+  switch (target_type) {
+    case ui::CHROME_BOOKMARK_ITEM: {
+      std::vector<const BookmarkNode*> nodes =
+          bookmark_utils::GetNodesFromSelection(context, selection_data,
+                                                target_type,
+                                                profile_,
+                                                &delete_selection_data,
+                                                &dnd_success);
+      DCHECK(!nodes.empty());
+      for (std::vector<const BookmarkNode*>::iterator it = nodes.begin();
+           it != nodes.end(); ++it) {
+        model_->Move(*it, dest_node, index);
+        index = dest_node->IndexOfChild(*it) + 1;
+      }
+      break;
+    }
+
+    case ui::CHROME_NAMED_URL: {
+      dnd_success = bookmark_utils::CreateNewBookmarkFromNamedUrl(
+          selection_data, model_, dest_node, index);
+      break;
+    }
+
+    case ui::TEXT_URI_LIST: {
+      dnd_success = bookmark_utils::CreateNewBookmarksFromURIList(
+          selection_data, model_, dest_node, index);
+      break;
+    }
+
+    case ui::NETSCAPE_URL: {
+      dnd_success = bookmark_utils::CreateNewBookmarkFromNetscapeURL(
+          selection_data, model_, dest_node, index);
+      break;
+    }
+
+    case ui::TEXT_PLAIN: {
+      guchar* text = gtk_selection_data_get_text(selection_data);
+      if (!text)
+        break;
+      GURL url(reinterpret_cast<char*>(text));
+      g_free(text);
+      // TODO(estade): It would be nice to head this case off at drag motion,
+      // so that it doesn't look like we can drag onto the bookmark bar.
+      if (!url.is_valid())
+        break;
+      string16 title = bookmark_utils::GetNameForURL(url);
+      model_->AddURL(dest_node, index, title, url);
+      dnd_success = TRUE;
+      break;
+    }
+  }
+
+  gtk_drag_finish(context, dnd_success, delete_selection_data, time);
+}
+
+gboolean BookmarkBarGtk::OnEventBoxExpose(GtkWidget* widget,
+                                          GdkEventExpose* event) {
+  GtkThemeProvider* theme_provider = theme_provider_;
+
+  // We don't need to render the toolbar image in GTK mode, except when
+  // detached.
+  if (theme_provider->UseGtkTheme() && !floating_)
+    return FALSE;
+
+  if (!floating_) {
+    cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+    gdk_cairo_rectangle(cr, &event->area);
+    cairo_clip(cr);
+
+    // Paint the background theme image.
+    gfx::Point tabstrip_origin =
+        tabstrip_origin_provider_->GetTabStripOriginForWidget(widget);
+    gtk_util::DrawThemedToolbarBackground(widget, cr, event, tabstrip_origin,
+                                          theme_provider);
+
+    cairo_destroy(cr);
+  } else {
+    gfx::Size tab_contents_size;
+    if (!GetTabContentsSize(&tab_contents_size))
+      return FALSE;
+    gfx::CanvasSkiaPaint canvas(event, true);
+
+    gfx::Rect area = GTK_WIDGET_NO_WINDOW(widget) ?
+        gfx::Rect(widget->allocation) :
+        gfx::Rect(0, 0, widget->allocation.width, widget->allocation.height);
+    NtpBackgroundUtil::PaintBackgroundDetachedMode(theme_provider, &canvas,
+        area, tab_contents_size.height());
+  }
+
+  return FALSE;  // Propagate expose to children.
+}
+
+void BookmarkBarGtk::OnEventBoxDestroy(GtkWidget* widget) {
+  if (model_)
+    model_->RemoveObserver(this);
+
+  if (sync_service_)
+    sync_service_->RemoveObserver(this);
+}
+
+void BookmarkBarGtk::OnParentSizeAllocate(GtkWidget* widget,
+                                          GtkAllocation* allocation) {
+  // In floating mode, our layout depends on the size of the tab contents.
+  // We get the size-allocate signal before the tab contents does, hence we
+  // need to post a delayed task so we will paint correctly. Note that
+  // gtk_widget_queue_draw by itself does not work, despite that it claims to
+  // be asynchronous.
+  if (floating_) {
+    MessageLoop::current()->PostTask(FROM_HERE,
+        method_factory_.NewRunnableMethod(
+            &BookmarkBarGtk::PaintEventBox));
+  }
+}
+
+void BookmarkBarGtk::OnThrobbingWidgetDestroy(GtkWidget* widget) {
+  SetThrobbingWidget(NULL);
+}
+
+// MenuBarHelper::Delegate implementation --------------------------------------
+void BookmarkBarGtk::PopupForButton(GtkWidget* button) {
+  const BookmarkNode* node = GetNodeForToolButton(button);
+  DCHECK(node);
+  DCHECK(page_navigator_);
+
+  int first_hidden = GetFirstHiddenBookmark(0, NULL);
+  if (first_hidden == -1) {
+    // No overflow exists: don't show anything for the overflow button.
+    if (button == overflow_button_)
+      return;
+  } else {
+    // Overflow exists: don't show anything for an overflowed folder button.
+    if (button != overflow_button_ && button != other_bookmarks_button_ &&
+        node->GetParent()->IndexOfChild(node) >= first_hidden) {
+      return;
+    }
+  }
+
+  current_menu_.reset(
+      new BookmarkMenuController(browser_, profile_, page_navigator_,
+                                 GTK_WINDOW(gtk_widget_get_toplevel(button)),
+                                 node,
+                                 button == overflow_button_ ?
+                                     first_hidden : 0));
+  menu_bar_helper_.MenuStartedShowing(button, current_menu_->widget());
+  GdkEvent* event = gtk_get_current_event();
+  current_menu_->Popup(button, event->button.button, event->button.time);
+  gdk_event_free(event);
+}
+
+void BookmarkBarGtk::PopupForButtonNextTo(GtkWidget* button,
+                                          GtkMenuDirectionType dir) {
+  const BookmarkNode* relative_node = GetNodeForToolButton(button);
+  DCHECK(relative_node);
+
+  // Find out the order of the buttons.
+  std::vector<GtkWidget*> folder_list;
+  const int first_hidden = GetFirstHiddenBookmark(0, &folder_list);
+  if (first_hidden != -1)
+    folder_list.push_back(overflow_button_);
+  folder_list.push_back(other_bookmarks_button_);
+
+  // Find the position of |button|.
+  int button_idx = -1;
+  for (size_t i = 0; i < folder_list.size(); ++i) {
+    if (folder_list[i] == button) {
+      button_idx = i;
+      break;
+    }
+  }
+  DCHECK_NE(button_idx, -1);
+
+  // Find the GtkWidget* for the actual target button.
+  int shift = dir == GTK_MENU_DIR_PARENT ? -1 : 1;
+  button_idx = (button_idx + shift + folder_list.size()) % folder_list.size();
+  PopupForButton(folder_list[button_idx]);
+}
+
+void BookmarkBarGtk::CloseMenu() {
+  current_context_menu_->Cancel();
+}
diff --git a/chrome/browser/ui/gtk/bookmark_bar_gtk.h b/chrome/browser/ui/gtk/bookmark_bar_gtk.h
new file mode 100644
index 0000000..3ac4298
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bar_gtk.h
@@ -0,0 +1,410 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BOOKMARK_BAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_BAR_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
+#include "chrome/browser/bookmarks/bookmark_model_observer.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.h"
+#include "chrome/browser/ui/gtk/menu_bar_helper.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/size.h"
+
+class BookmarkMenuController;
+class Browser;
+class BrowserWindowGtk;
+class CustomContainerButton;
+class GtkThemeProvider;
+class MenuGtk;
+class PageNavigator;
+class Profile;
+class TabstripOriginProvider;
+
+namespace ui {
+class SlideAnimation;
+}
+
+class BookmarkBarGtk : public ui::AnimationDelegate,
+                       public ProfileSyncServiceObserver,
+                       public BookmarkModelObserver,
+                       public MenuBarHelper::Delegate,
+                       public NotificationObserver,
+                       public BookmarkBarInstructionsGtk::Delegate,
+                       public BookmarkContextMenuControllerDelegate {
+ public:
+  BookmarkBarGtk(BrowserWindowGtk* window,
+                 Profile* profile,
+                 Browser* browser,
+                 TabstripOriginProvider* tabstrip_origin_provider);
+  virtual ~BookmarkBarGtk();
+
+  // Resets the profile. This removes any buttons for the current profile and
+  // recreates the models.
+  void SetProfile(Profile* profile);
+
+  // Returns the current profile.
+  Profile* GetProfile() { return profile_; }
+
+  // Returns the current browser.
+  Browser* browser() const { return browser_; }
+
+  // Returns the top level widget.
+  GtkWidget* widget() const { return event_box_.get(); }
+
+  // Sets the PageNavigator that is used when the user selects an entry on
+  // the bookmark bar.
+  void SetPageNavigator(PageNavigator* navigator);
+
+  // Create the contents of the bookmark bar.
+  void Init(Profile* profile);
+
+  // Whether the current page is the New Tag Page (which requires different
+  // rendering).
+  bool OnNewTabPage();
+
+  // Change the visibility of the bookmarks bar. (Starts out hidden, per GTK's
+  // default behaviour). There are three visiblity states:
+  //
+  //   Showing    - bookmark bar is fully visible.
+  //   Hidden     - bookmark bar is hidden except for a few pixels that give
+  //                extra padding to the bottom of the toolbar. Buttons are not
+  //                clickable.
+  //   Fullscreen - bookmark bar is fully hidden.
+  void Show(bool animate);
+  void Hide(bool animate);
+  void EnterFullscreen();
+
+  // Get the current height of the bookmark bar.
+  int GetHeight();
+
+  // Returns true if the bookmark bar is showing an animation.
+  bool IsAnimating();
+
+  // Returns true if the bookmarks bar preference is set to 'always show'.
+  bool IsAlwaysShown();
+
+  // ui::AnimationDelegate implementation --------------------------------------
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationEnded(const ui::Animation* animation);
+
+  // MenuBarHelper::Delegate implementation ------------------------------------
+  virtual void PopupForButton(GtkWidget* button);
+  virtual void PopupForButtonNextTo(GtkWidget* button,
+                                    GtkMenuDirectionType dir);
+
+  // The NTP needs to have access to this.
+  static const int kBookmarkBarNTPHeight;
+
+  // BookmarkContextMenuController::Delegate implementation --------------------
+  virtual void CloseMenu();
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, DisplaysHelpMessageOnEmpty);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest,
+                           HidesHelpMessageWithBookmark);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, BuildsButtons);
+
+  // Helper function which generates GtkToolItems for |bookmark_toolbar_|.
+  void CreateAllBookmarkButtons();
+
+  // Sets the visibility of the instructional text based on whether there are
+  // any bookmarks in the bookmark bar node.
+  void SetInstructionState();
+
+  // Sets the visibility of the overflow chevron.
+  void SetChevronState();
+
+  // Helper function which destroys all the bookmark buttons in the GtkToolbar.
+  void RemoveAllBookmarkButtons();
+
+  // Returns the number of buttons corresponding to starred urls/groups. This
+  // is equivalent to the number of children the bookmark bar node from the
+  // bookmark bar model has.
+  int GetBookmarkButtonCount();
+
+  // Set the appearance of the overflow button appropriately (either chromium
+  // style or GTK style).
+  void SetOverflowButtonAppearance();
+
+  // Returns the index of the first bookmark that is not visible on the bar.
+  // Returns -1 if they are all visible.
+  // |extra_space| is how much extra space to give the toolbar during the
+  // calculation (for the purposes of determining if ditching the chevron
+  // would be a good idea).
+  // If non-NULL, |showing_folders| will be packed with all the folders that are
+  // showing on the bar.
+  int GetFirstHiddenBookmark(int extra_space,
+                             std::vector<GtkWidget*>* showing_folders);
+
+  // Returns true if the bookmark bar should be floating on the page (for
+  // NTP).
+  bool ShouldBeFloating();
+  // Update the floating state (either enable or disable it, or do nothing).
+  void UpdateFloatingState();
+
+  // Turns on or off the app_paintable flag on |event_box_|, depending on our
+  // state.
+  void UpdateEventBoxPaintability();
+
+  // Queue a paint on the event box.
+  void PaintEventBox();
+
+  // Finds the size of the current tab contents, if it exists and sets |size|
+  // to the correct value. Returns false if there isn't a TabContents, a
+  // condition that can happen during testing.
+  bool GetTabContentsSize(gfx::Size* size);
+
+  // Connects to the "size-allocate" signal on the given widget, and causes it
+  // to throb after allocation. This is called when a new item is added to the
+  // bar. We can't call StartThrobbing directly because we don't know if it's
+  // visible or not until after the widget is allocated.
+  void StartThrobbingAfterAllocation(GtkWidget* item);
+
+  // Used by StartThrobbingAfterAllocation.
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnItemAllocate, GtkAllocation*);
+
+  // Makes the appropriate widget on the bookmark bar stop throbbing
+  // (a folder, the overflow chevron, or nothing).
+  void StartThrobbing(const BookmarkNode* node);
+
+  // Set |throbbing_widget_| to |widget|. Also makes sure that
+  // |throbbing_widget_| doesn't become stale.
+  void SetThrobbingWidget(GtkWidget* widget);
+
+  // An item has been dragged over the toolbar, update the drag context
+  // and toolbar UI appropriately.
+  gboolean ItemDraggedOverToolbar(
+      GdkDragContext* context, int index, guint time);
+
+  // When dragging in the middle of a folder, assume the user wants to drop
+  // on the folder. Towards the edges, assume the user wants to drop on the
+  // toolbar. This makes it possible to drop between two folders. This function
+  // returns the index on the toolbar the drag should target, or -1 if the
+  // drag should hit the folder.
+  int GetToolbarIndexForDragOverFolder(GtkWidget* button, gint x);
+
+  void ClearToolbarDropHighlighting();
+
+  // Overridden from BookmarkModelObserver:
+
+  // Invoked when the bookmark model has finished loading. Creates a button
+  // for each of the children of the root node from the model.
+  virtual void Loaded(BookmarkModel* model);
+
+  // Invoked when the model is being deleted.
+  virtual void BookmarkModelBeingDeleted(BookmarkModel* model);
+
+  // Invoked when a node has moved.
+  virtual void BookmarkNodeMoved(BookmarkModel* model,
+                                 const BookmarkNode* old_parent,
+                                 int old_index,
+                                 const BookmarkNode* new_parent,
+                                 int new_index);
+  virtual void BookmarkNodeAdded(BookmarkModel* model,
+                                 const BookmarkNode* parent,
+                                 int index);
+  virtual void BookmarkNodeRemoved(BookmarkModel* model,
+                                   const BookmarkNode* parent,
+                                   int old_index,
+                                   const BookmarkNode* node);
+  virtual void BookmarkNodeChanged(BookmarkModel* model,
+                                   const BookmarkNode* node);
+  // Invoked when a favicon has finished loading.
+  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
+                                         const BookmarkNode* node);
+  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
+                                             const BookmarkNode* node);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  GtkWidget* CreateBookmarkButton(const BookmarkNode* node);
+  GtkToolItem* CreateBookmarkToolItem(const BookmarkNode* node);
+
+  void ConnectFolderButtonEvents(GtkWidget* widget, bool is_tool_item);
+
+  // Finds the BookmarkNode from the model associated with |button|.
+  const BookmarkNode* GetNodeForToolButton(GtkWidget* button);
+
+  // Creates and displays a popup menu for BookmarkNode |node|.
+  void PopupMenuForNode(GtkWidget* sender, const BookmarkNode* node,
+                        GdkEventButton* event);
+
+  // GtkButton callbacks.
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnButtonPressed,
+                       GdkEventButton*);
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnSyncErrorButtonPressed,
+                       GdkEventButton*);
+  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnClicked);
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragBegin,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragEnd, GdkDragContext*);
+  CHROMEGTK_CALLBACK_4(BookmarkBarGtk, void, OnButtonDragGet,
+                       GdkDragContext*, GtkSelectionData*, guint, guint);
+
+  // GtkButton callbacks for folder buttons.
+  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnFolderClicked);
+
+  // GtkToolbar callbacks.
+  CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnToolbarDragMotion,
+                       GdkDragContext*, gint, gint, guint);
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnToolbarSizeAllocate,
+                       GtkAllocation*);
+
+  // Used for both folder buttons and the toolbar.
+  CHROMEGTK_CALLBACK_6(BookmarkBarGtk, void, OnDragReceived,
+                       GdkDragContext*, gint, gint, GtkSelectionData*,
+                       guint, guint);
+  CHROMEGTK_CALLBACK_2(BookmarkBarGtk, void, OnDragLeave,
+                       GdkDragContext*, guint);
+
+  // Used for folder buttons.
+  CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnFolderDragMotion,
+                       GdkDragContext*, gint, gint, guint);
+
+  // GtkEventBox callbacks.
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnEventBoxExpose,
+                       GdkEventExpose*);
+  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnEventBoxDestroy);
+
+  // Callbacks on our parent widget.
+  CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnParentSizeAllocate,
+                       GtkAllocation*);
+
+  // |throbbing_widget_| callback.
+  CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnThrobbingWidgetDestroy);
+
+  // ProfileSyncServiceObserver method.
+  virtual void OnStateChanged();
+
+  // Overriden from BookmarkBarInstructionsGtk::Delegate.
+  virtual void ShowImportDialog();
+
+  Profile* profile_;
+
+  // Used for opening urls.
+  PageNavigator* page_navigator_;
+
+  Browser* browser_;
+  BrowserWindowGtk* window_;
+
+  // Provides us with the offset into the background theme image.
+  TabstripOriginProvider* tabstrip_origin_provider_;
+
+  // Model providing details as to the starred entries/groups that should be
+  // shown. This is owned by the Profile.
+  BookmarkModel* model_;
+
+  // Contains |bookmark_hbox_|. Event box exists to prevent leakage of
+  // background color from the toplevel application window's GDK window.
+  OwnedWidgetGtk event_box_;
+
+  // Used to float the bookmark bar when on the NTP.
+  GtkWidget* ntp_padding_box_;
+
+  // Used to paint the background of the bookmark bar when in floating mode.
+  GtkWidget* paint_box_;
+
+  // Used to position all children.
+  GtkWidget* bookmark_hbox_;
+
+  // Alignment widget that is visible if there are no bookmarks on
+  // the bookmar bar.
+  GtkWidget* instructions_;
+
+  // BookmarkBarInstructionsGtk that holds the label and the link for importing
+  // bookmarks when there are no bookmarks on the bookmark bar.
+  scoped_ptr<BookmarkBarInstructionsGtk> instructions_gtk_;
+
+  // GtkToolbar which contains all the bookmark buttons.
+  OwnedWidgetGtk bookmark_toolbar_;
+
+  // The button that shows extra bookmarks that don't fit on the bookmark
+  // bar.
+  GtkWidget* overflow_button_;
+
+  // The other bookmarks button.
+  GtkWidget* other_bookmarks_button_;
+
+  // The sync error button.
+  GtkWidget* sync_error_button_;
+
+  // A pointer to the ProfileSyncService instance if one exists.
+  ProfileSyncService* sync_service_;
+
+  // The BookmarkNode from the model being dragged. NULL when we aren't
+  // dragging.
+  const BookmarkNode* dragged_node_;
+
+  // The visual representation that follows the cursor during drags.
+  GtkWidget* drag_icon_;
+
+  // We create a GtkToolbarItem from |dragged_node_| ;or display.
+  GtkToolItem* toolbar_drop_item_;
+
+  // Theme provider for building buttons.
+  GtkThemeProvider* theme_provider_;
+
+  // Whether we should show the instructional text in the bookmark bar.
+  bool show_instructions_;
+
+  MenuBarHelper menu_bar_helper_;
+
+  // The last displayed right click menu, or NULL if no menus have been
+  // displayed yet.
+  // The controller.
+  scoped_ptr<BookmarkContextMenuController> current_context_menu_controller_;
+  // The view.
+  scoped_ptr<MenuGtk> current_context_menu_;
+
+  // The last displayed left click menu, or NULL if no menus have been
+  // displayed yet.
+  scoped_ptr<BookmarkMenuController> current_menu_;
+
+  scoped_ptr<ui::SlideAnimation> slide_animation_;
+
+  // Whether we are currently configured as floating (detached from the
+  // toolbar). This reflects our actual state, and can be out of sync with
+  // what ShouldShowFloating() returns.
+  bool floating_;
+
+  // Used to optimize out |bookmark_toolbar_| size-allocate events we don't
+  // need to respond to.
+  int last_allocation_width_;
+
+  NotificationRegistrar registrar_;
+
+  // The size of the tab contents last time we forced a paint. We keep track
+  // of this so we don't force too many paints.
+  gfx::Size last_tab_contents_size_;
+
+  // The last coordinates recorded by OnButtonPress; used to line up the
+  // drag icon during bookmark drags.
+  gfx::Point last_pressed_coordinates_;
+
+  // The currently throbbing widget. This is NULL if no widget is throbbing.
+  // We track it because we only want to allow one widget to throb at a time.
+  GtkWidget* throbbing_widget_;
+
+  ScopedRunnableMethodFactory<BookmarkBarGtk> method_factory_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_BAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_bar_gtk_interactive_uitest.cc b/chrome/browser/ui/gtk/bookmark_bar_gtk_interactive_uitest.cc
new file mode 100644
index 0000000..3518825
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bar_gtk_interactive_uitest.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "net/test/test_server.h"
+
+namespace {
+
+const char kSimplePage[] = "404_is_enough_for_us.html";
+
+void OnClicked(GtkWidget* widget, bool* clicked_bit) {
+  *clicked_bit = true;
+}
+
+}  // namespace
+
+class BookmarkBarGtkInteractiveUITest : public InProcessBrowserTest {
+};
+
+// Makes sure that when you switch back to an NTP with an active findbar,
+// the findbar is above the floating bookmark bar.
+IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, FindBarTest) {
+  ASSERT_TRUE(test_server()->Start());
+
+  // Create new tab; open findbar.
+  browser()->NewTab();
+  browser()->Find();
+
+  // Create new tab with an arbitrary URL.
+  GURL url = test_server()->GetURL(kSimplePage);
+  browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
+
+  // Switch back to the NTP with the active findbar.
+  browser()->SelectTabContentsAt(1, false);
+
+  // Wait for the findbar to show.
+  MessageLoop::current()->RunAllPending();
+
+  // Set focus somewhere else, so that we can test clicking on the findbar
+  // works.
+  browser()->FocusLocationBar();
+  ui_test_utils::ClickOnView(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
+  ui_test_utils::IsViewFocused(browser(), VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
+}
+
+// Makes sure that you can click on the floating bookmark bar.
+IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, ClickOnFloatingTest) {
+  ASSERT_TRUE(test_server()->Start());
+
+  GtkWidget* other_bookmarks =
+      ViewIDUtil::GetWidget(GTK_WIDGET(browser()->window()->GetNativeHandle()),
+      VIEW_ID_OTHER_BOOKMARKS);
+  bool has_been_clicked = false;
+  g_signal_connect(other_bookmarks, "clicked",
+                   G_CALLBACK(OnClicked), &has_been_clicked);
+
+  // Create new tab.
+  browser()->NewTab();
+
+  // Wait for the floating bar to appear.
+  MessageLoop::current()->RunAllPending();
+
+  // This is kind of a hack. Calling this just once doesn't seem to send a click
+  // event, but doing it twice works.
+  // http://crbug.com/35581
+  ui_test_utils::ClickOnView(browser(), VIEW_ID_OTHER_BOOKMARKS);
+  ui_test_utils::ClickOnView(browser(), VIEW_ID_OTHER_BOOKMARKS);
+
+  EXPECT_TRUE(has_been_clicked);
+}
diff --git a/chrome/browser/ui/gtk/bookmark_bar_gtk_unittest.cc b/chrome/browser/ui/gtk/bookmark_bar_gtk_unittest.cc
new file mode 100644
index 0000000..9581d50
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bar_gtk_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_bar_gtk.h"
+
+#include "base/task.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/ui/gtk/tabstrip_origin_provider.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Dummy implementation that's good enough for the tests; we don't test
+// rendering here so all we need is a non-NULL object.
+class EmptyTabstripOriginProvider : public TabstripOriginProvider {
+ public:
+  virtual gfx::Point GetTabStripOriginForWidget(GtkWidget* widget) {
+    return gfx::Point(0, 0);
+  }
+};
+
+class BookmarkBarGtkUnittest : public ::testing::Test {
+ protected:
+  BookmarkBarGtkUnittest()
+      : ui_thread_(BrowserThread::UI, &message_loop_),
+        file_thread_(BrowserThread::FILE, &message_loop_) {
+  }
+
+  virtual void SetUp() {
+    profile_.reset(new TestingProfile());
+    profile_->CreateBookmarkModel(true);
+    profile_->BlockUntilBookmarkModelLoaded();
+    browser_.reset(new Browser(Browser::TYPE_NORMAL, profile_.get()));
+
+    origin_provider_.reset(new EmptyTabstripOriginProvider);
+    bookmark_bar_.reset(new BookmarkBarGtk(NULL, profile_.get(), browser_.get(),
+                                           origin_provider_.get()));
+  }
+
+  virtual void TearDown() {
+    message_loop_.RunAllPending();
+
+    bookmark_bar_.reset();
+    origin_provider_.reset();
+    browser_.reset();
+    profile_.reset();
+  }
+
+  MessageLoopForUI message_loop_;
+  BrowserThread ui_thread_;
+  BrowserThread file_thread_;
+
+  scoped_ptr<TestingProfile> profile_;
+  scoped_ptr<Browser> browser_;
+  scoped_ptr<TabstripOriginProvider> origin_provider_;
+  scoped_ptr<BookmarkBarGtk> bookmark_bar_;
+};
+
+TEST_F(BookmarkBarGtkUnittest, DisplaysHelpMessageOnEmpty) {
+  BookmarkModel* model = profile_->GetBookmarkModel();
+  bookmark_bar_->Loaded(model);
+
+  // There are no bookmarks in the model by default. Expect that the
+  // |instructions_label| is shown.
+  EXPECT_TRUE(bookmark_bar_->show_instructions_);
+}
+
+TEST_F(BookmarkBarGtkUnittest, HidesHelpMessageWithBookmark) {
+  BookmarkModel* model = profile_->GetBookmarkModel();
+
+  const BookmarkNode* parent = model->GetBookmarkBarNode();
+  model->AddURL(parent, parent->GetChildCount(),
+                ASCIIToUTF16("title"), GURL("http://one.com"));
+
+  bookmark_bar_->Loaded(model);
+  EXPECT_FALSE(bookmark_bar_->show_instructions_);
+}
+
+TEST_F(BookmarkBarGtkUnittest, BuildsButtons) {
+  BookmarkModel* model = profile_->GetBookmarkModel();
+
+  const BookmarkNode* parent = model->GetBookmarkBarNode();
+  model->AddURL(parent, parent->GetChildCount(),
+                ASCIIToUTF16("title"), GURL("http://one.com"));
+  model->AddURL(parent, parent->GetChildCount(),
+                ASCIIToUTF16("other"), GURL("http://two.com"));
+
+  bookmark_bar_->Loaded(model);
+
+  // We should expect two children to the bookmark bar's toolbar.
+  GList* children = gtk_container_get_children(
+      GTK_CONTAINER(bookmark_bar_->bookmark_toolbar_.get()));
+  EXPECT_EQ(2U, g_list_length(children));
+  g_list_free(children);
+}
diff --git a/chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.cc b/chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.cc
new file mode 100644
index 0000000..522861e
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.h"
+
+#include "base/observer_list.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+BookmarkBarInstructionsGtk::BookmarkBarInstructionsGtk(Delegate* delegate,
+                                                       Profile* profile)
+    : delegate_(delegate),
+      profile_(profile),
+      theme_provider_(GtkThemeProvider::GetFrom(profile_)) {
+  instructions_hbox_ = gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, 0);
+  gtk_widget_set_size_request(instructions_hbox_, 0, -1);
+
+  instructions_label_ = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_BOOKMARKS_NO_ITEMS).c_str());
+  gtk_misc_set_alignment(GTK_MISC(instructions_label_), 0, 0.5);
+  gtk_util::CenterWidgetInHBox(instructions_hbox_, instructions_label_,
+                               false, 1);
+  g_signal_connect(instructions_label_, "map",
+                   G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
+                   NULL);
+
+  instructions_link_ = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_BOOKMARK_BAR_IMPORT_LINK).c_str());
+  gtk_misc_set_alignment(
+      GTK_MISC(GTK_CHROME_LINK_BUTTON(instructions_link_)->label), 0, 0.5);
+  g_signal_connect(instructions_link_, "clicked",
+                   G_CALLBACK(OnButtonClickThunk), this);
+  gtk_util::SetButtonTriggersNavigation(instructions_link_);
+  // Until we switch to vector graphics, force the font size.
+  // 13.4px == 10pt @ 96dpi
+  gtk_util::ForceFontSizePixels(
+      GTK_CHROME_LINK_BUTTON(instructions_link_)->label, 13.4);
+  gtk_util::CenterWidgetInHBox(instructions_hbox_, instructions_link_,
+                               false, 6);
+  g_signal_connect(GTK_CHROME_LINK_BUTTON(instructions_link_)->label, "map",
+                   G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
+                   NULL);
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_->InitThemesFor(this);
+}
+
+void BookmarkBarInstructionsGtk::Observe(NotificationType type,
+                                         const NotificationSource& source,
+                                         const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED)
+    UpdateColors();
+}
+
+void BookmarkBarInstructionsGtk::OnButtonClick(GtkWidget* button) {
+  delegate_->ShowImportDialog();
+}
+
+void BookmarkBarInstructionsGtk::UpdateColors() {
+  gtk_chrome_link_button_set_use_gtk_theme(
+      GTK_CHROME_LINK_BUTTON(instructions_link_),
+      theme_provider_->UseGtkTheme());
+
+  GdkColor bookmark_color = theme_provider_->GetGdkColor(
+      BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+  if (theme_provider_->UseGtkTheme()) {
+    gtk_util::SetLabelColor(instructions_label_, NULL);
+    gtk_chrome_link_button_set_normal_color(
+        GTK_CHROME_LINK_BUTTON(instructions_link_), NULL);
+  } else {
+    gtk_util::SetLabelColor(instructions_label_, &bookmark_color);
+
+    // When using a non-standard, non-gtk theme, we make the link color match
+    // the bookmark text color. Otherwise, standard link blue can look very
+    // bad for some dark themes.
+    if (theme_provider_->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT) ==
+        BrowserThemeProvider::GetDefaultColor(
+            BrowserThemeProvider::COLOR_BOOKMARK_TEXT)) {
+      gtk_chrome_link_button_set_normal_color(
+          GTK_CHROME_LINK_BUTTON(instructions_link_), NULL);
+    } else {
+      gtk_chrome_link_button_set_normal_color(
+          GTK_CHROME_LINK_BUTTON(instructions_link_), &bookmark_color);
+    }
+  }
+}
diff --git a/chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.h b/chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.h
new file mode 100644
index 0000000..3cea2d6
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bar_instructions_gtk.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+typedef struct _GtkWidget GtkWidget;
+class GtkThemeProvider;
+class Profile;
+
+class BookmarkBarInstructionsGtk : public NotificationObserver {
+ public:
+  // The delegate is notified once the user clicks on the link to import
+  // bookmarks.
+  class Delegate {
+   public:
+    virtual void ShowImportDialog() = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  explicit BookmarkBarInstructionsGtk(Delegate* delegate, Profile* profile);
+
+  // Get the native widget.
+  GtkWidget* widget() const { return instructions_hbox_; }
+
+ private:
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  CHROMEGTK_CALLBACK_0(BookmarkBarInstructionsGtk, void, OnButtonClick);
+
+  // Sets the correct color for |instructions_label_| and |instructions_link_|.
+  void UpdateColors();
+
+  Delegate* delegate_;
+
+  Profile* profile_;
+
+  GtkThemeProvider* theme_provider_;
+
+  // HBox that holds the the label and link of bookmark bar import promotion.
+  GtkWidget* instructions_hbox_;
+  GtkWidget* instructions_label_;
+  GtkWidget* instructions_link_;
+
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkBarInstructionsGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_BAR_INSTRUCTIONS_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_bubble_gtk.cc b/chrome/browser/ui/gtk/bookmark_bubble_gtk.cc
new file mode 100644
index 0000000..307953b
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bubble_gtk.cc
@@ -0,0 +1,346 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_bubble_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_editor.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/recently_used_folders_combo_model.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// We basically have a singleton, since a bubble is sort of app-modal.  This
+// keeps track of the currently open bubble, or NULL if none is open.
+BookmarkBubbleGtk* g_bubble = NULL;
+
+// Padding between content and edge of info bubble.
+const int kContentBorder = 7;
+
+
+}  // namespace
+
+// static
+void BookmarkBubbleGtk::Show(GtkWidget* anchor,
+                             Profile* profile,
+                             const GURL& url,
+                             bool newly_bookmarked) {
+  DCHECK(!g_bubble);
+  g_bubble = new BookmarkBubbleGtk(anchor, profile, url, newly_bookmarked);
+}
+
+void BookmarkBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                          bool closed_by_escape) {
+  if (closed_by_escape) {
+    remove_bookmark_ = newly_bookmarked_;
+    apply_edits_ = false;
+  }
+
+  NotificationService::current()->Notify(
+      NotificationType::BOOKMARK_BUBBLE_HIDDEN,
+      Source<Profile>(profile_->GetOriginalProfile()),
+      NotificationService::NoDetails());
+}
+
+void BookmarkBubbleGtk::Observe(NotificationType type,
+                                const NotificationSource& source,
+                                const NotificationDetails& details) {
+  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+
+  gtk_chrome_link_button_set_use_gtk_theme(
+      GTK_CHROME_LINK_BUTTON(remove_button_),
+      theme_provider_->UseGtkTheme());
+
+  if (theme_provider_->UseGtkTheme()) {
+    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
+         it != labels_.end(); ++it) {
+      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
+    }
+  } else {
+    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
+         it != labels_.end(); ++it) {
+      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+    }
+  }
+}
+
+BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWidget* anchor,
+                                     Profile* profile,
+                                     const GURL& url,
+                                     bool newly_bookmarked)
+    : url_(url),
+      profile_(profile),
+      theme_provider_(GtkThemeProvider::GetFrom(profile_)),
+      anchor_(anchor),
+      content_(NULL),
+      name_entry_(NULL),
+      folder_combo_(NULL),
+      bubble_(NULL),
+      factory_(this),
+      newly_bookmarked_(newly_bookmarked),
+      apply_edits_(true),
+      remove_bookmark_(false) {
+  GtkWidget* label = gtk_label_new(l10n_util::GetStringUTF8(
+      newly_bookmarked_ ? IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED :
+                          IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK).c_str());
+  labels_.push_back(label);
+  remove_button_ = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_REMOVE_BOOKMARK).c_str());
+  GtkWidget* edit_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_OPTIONS).c_str());
+  GtkWidget* close_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DONE).c_str());
+
+  // Our content is arranged in 3 rows.  |top| contains a left justified
+  // message, and a right justified remove link button.  |table| is the middle
+  // portion with the name entry and the folder combo.  |bottom| is the final
+  // row with a spacer, and the edit... and close buttons on the right.
+  GtkWidget* content = gtk_vbox_new(FALSE, 5);
+  gtk_container_set_border_width(GTK_CONTAINER(content), kContentBorder);
+  GtkWidget* top = gtk_hbox_new(FALSE, 0);
+
+  gtk_misc_set_alignment(GTK_MISC(label), 0, 1);
+  gtk_box_pack_start(GTK_BOX(top), label,
+                     TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(top), remove_button_,
+                     FALSE, FALSE, 0);
+
+  folder_combo_ = gtk_combo_box_new_text();
+  InitFolderComboModel();
+
+  // Create the edit entry for updating the bookmark name / title.
+  name_entry_ = gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(name_entry_), GetTitle().c_str());
+
+  // We use a table to allow the labels to line up with each other, along
+  // with the entry and folder combo lining up.
+  GtkWidget* table = gtk_util::CreateLabeledControlsGroup(
+      &labels_,
+      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_TITLE_TEXT).c_str(),
+      name_entry_,
+      l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_FOLDER_TEXT).c_str(),
+      folder_combo_,
+      NULL);
+
+  GtkWidget* bottom = gtk_hbox_new(FALSE, 0);
+  // We want the buttons on the right, so just use an expanding label to fill
+  // all of the extra space on the right.
+  gtk_box_pack_start(GTK_BOX(bottom), gtk_label_new(""),
+                     TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(bottom), edit_button,
+                     FALSE, FALSE, 4);
+  gtk_box_pack_start(GTK_BOX(bottom), close_button,
+                     FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(content), top, TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(content), table, TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(content), bottom, TRUE, TRUE, 0);
+  // We want the focus to start on the entry, not on the remove button.
+  gtk_container_set_focus_child(GTK_CONTAINER(content), table);
+
+  InfoBubbleGtk::ArrowLocationGtk arrow_location =
+      base::i18n::IsRTL() ?
+      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
+      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
+  bubble_ = InfoBubbleGtk::Show(anchor_,
+                                NULL,
+                                content,
+                                arrow_location,
+                                true,  // match_system_theme
+                                true,  // grab_input
+                                theme_provider_,
+                                this);  // delegate
+  if (!bubble_) {
+    NOTREACHED();
+    return;
+  }
+
+  g_signal_connect(content, "destroy",
+                   G_CALLBACK(&OnDestroyThunk), this);
+  g_signal_connect(name_entry_, "activate",
+                   G_CALLBACK(&OnNameActivateThunk), this);
+  g_signal_connect(folder_combo_, "changed",
+                   G_CALLBACK(&OnFolderChangedThunk), this);
+  g_signal_connect(folder_combo_, "notify::popup-shown",
+                   G_CALLBACK(&OnFolderPopupShownThunk), this);
+  g_signal_connect(edit_button, "clicked",
+                   G_CALLBACK(&OnEditClickedThunk), this);
+  g_signal_connect(close_button, "clicked",
+                   G_CALLBACK(&OnCloseClickedThunk), this);
+  g_signal_connect(remove_button_, "clicked",
+                   G_CALLBACK(&OnRemoveClickedThunk), this);
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_->InitThemesFor(this);
+}
+
+BookmarkBubbleGtk::~BookmarkBubbleGtk() {
+  DCHECK(!content_);  // |content_| should have already been destroyed.
+
+  DCHECK(g_bubble);
+  g_bubble = NULL;
+
+  if (apply_edits_) {
+    ApplyEdits();
+  } else if (remove_bookmark_) {
+    BookmarkModel* model = profile_->GetBookmarkModel();
+    const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
+    if (node)
+      model->Remove(node->GetParent(), node->GetParent()->IndexOfChild(node));
+  }
+}
+
+void BookmarkBubbleGtk::OnDestroy(GtkWidget* widget) {
+  // We are self deleting, we have a destroy signal setup to catch when we
+  // destroyed (via the InfoBubble being destroyed), and delete ourself.
+  content_ = NULL;  // We are being destroyed.
+  delete this;
+}
+
+void BookmarkBubbleGtk::OnNameActivate(GtkWidget* widget) {
+  bubble_->Close();
+}
+
+void BookmarkBubbleGtk::OnFolderChanged(GtkWidget* widget) {
+  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(folder_combo_));
+  if (index == folder_combo_model_->GetItemCount() - 1) {
+    UserMetrics::RecordAction(
+        UserMetricsAction("BookmarkBubble_EditFromCombobox"), profile_);
+    // GTK doesn't handle having the combo box destroyed from the changed
+    // signal.  Since showing the editor also closes the bubble, delay this
+    // so that GTK can unwind.  Specifically gtk_menu_shell_button_release
+    // will run, and we need to keep the combo box alive until then.
+    MessageLoop::current()->PostTask(FROM_HERE,
+        factory_.NewRunnableMethod(&BookmarkBubbleGtk::ShowEditor));
+  }
+}
+
+void BookmarkBubbleGtk::OnFolderPopupShown(GtkWidget* widget,
+                                           GParamSpec* property) {
+  // GtkComboBox grabs the keyboard and pointer when it displays its popup,
+  // which steals the grabs that InfoBubbleGtk had installed.  When the popup is
+  // hidden, we notify InfoBubbleGtk so it can try to reacquire the grabs
+  // (otherwise, GTK won't activate our widgets when the user clicks in them).
+  gboolean popup_shown = FALSE;
+  g_object_get(G_OBJECT(folder_combo_), "popup-shown", &popup_shown, NULL);
+  if (!popup_shown)
+    bubble_->HandlePointerAndKeyboardUngrabbedByContent();
+}
+
+void BookmarkBubbleGtk::OnEditClicked(GtkWidget* widget) {
+  UserMetrics::RecordAction(UserMetricsAction("BookmarkBubble_Edit"),
+                            profile_);
+  ShowEditor();
+}
+
+void BookmarkBubbleGtk::OnCloseClicked(GtkWidget* widget) {
+  bubble_->Close();
+}
+
+void BookmarkBubbleGtk::OnRemoveClicked(GtkWidget* widget) {
+  UserMetrics::RecordAction(UserMetricsAction("BookmarkBubble_Unstar"),
+                            profile_);
+
+  apply_edits_ = false;
+  remove_bookmark_ = true;
+  bubble_->Close();
+}
+
+void BookmarkBubbleGtk::ApplyEdits() {
+  // Set this to make sure we don't attempt to apply edits again.
+  apply_edits_ = false;
+
+  BookmarkModel* model = profile_->GetBookmarkModel();
+  const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
+  if (node) {
+    const string16 new_title(
+        UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(name_entry_))));
+
+    if (new_title != node->GetTitle()) {
+      model->SetTitle(node, new_title);
+      UserMetrics::RecordAction(
+          UserMetricsAction("BookmarkBubble_ChangeTitleInBubble"),
+          profile_);
+    }
+
+    int index = gtk_combo_box_get_active(GTK_COMBO_BOX(folder_combo_));
+
+    // Last index means 'Choose another folder...'
+    if (index < folder_combo_model_->GetItemCount() - 1) {
+      const BookmarkNode* new_parent = folder_combo_model_->GetNodeAt(index);
+      if (new_parent != node->GetParent()) {
+        UserMetrics::RecordAction(
+            UserMetricsAction("BookmarkBubble_ChangeParent"), profile_);
+        model->Move(node, new_parent, new_parent->GetChildCount());
+      }
+    }
+  }
+}
+
+std::string BookmarkBubbleGtk::GetTitle() {
+  BookmarkModel* bookmark_model= profile_->GetBookmarkModel();
+  const BookmarkNode* node =
+      bookmark_model->GetMostRecentlyAddedNodeForURL(url_);
+  if (!node) {
+    NOTREACHED();
+    return std::string();
+  }
+
+  return UTF16ToUTF8(node->GetTitle());
+}
+
+void BookmarkBubbleGtk::ShowEditor() {
+  const BookmarkNode* node =
+      profile_->GetBookmarkModel()->GetMostRecentlyAddedNodeForURL(url_);
+
+  // Commit any edits now.
+  ApplyEdits();
+
+  // Closing might delete us, so we'll cache what we need on the stack.
+  Profile* profile = profile_;
+  GtkWindow* toplevel = GTK_WINDOW(gtk_widget_get_toplevel(anchor_));
+
+  // Close the bubble, deleting the C++ objects, etc.
+  bubble_->Close();
+
+  if (node) {
+    BookmarkEditor::Show(toplevel, profile, NULL,
+                         BookmarkEditor::EditDetails(node),
+                         BookmarkEditor::SHOW_TREE);
+  }
+}
+
+void BookmarkBubbleGtk::InitFolderComboModel() {
+  folder_combo_model_.reset(new RecentlyUsedFoldersComboModel(
+      profile_->GetBookmarkModel(),
+      profile_->GetBookmarkModel()->GetMostRecentlyAddedNodeForURL(url_)));
+
+  // We always have nodes + 1 entries in the combo.  The last entry will be
+  // the 'Select another folder...' entry that opens the bookmark editor.
+  for (int i = 0; i < folder_combo_model_->GetItemCount(); ++i) {
+    gtk_combo_box_append_text(GTK_COMBO_BOX(folder_combo_),
+        UTF16ToUTF8(folder_combo_model_->GetItemAt(i)).c_str());
+  }
+
+  gtk_combo_box_set_active(GTK_COMBO_BOX(folder_combo_),
+                           folder_combo_model_->node_parent_index());
+}
diff --git a/chrome/browser/ui/gtk/bookmark_bubble_gtk.h b/chrome/browser/ui/gtk/bookmark_bubble_gtk.h
new file mode 100644
index 0000000..1b40759
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_bubble_gtk.h
@@ -0,0 +1,129 @@
+// Copyright (c) 2011 The Chromium 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 the GTK implementation of the bookmark bubble, the dialog box
+// presented to create or edit a bookmark.  There can only ever be a single
+// bubble open, so the class presents only static methods, and handles the
+// singleton behavior for you.  It also handles the object and widget
+// lifetimes, destroying everything and possibly committing any changes when
+// the bubble is closed.
+
+#ifndef CHROME_BROWSER_UI_GTK_BOOKMARK_BUBBLE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_BUBBLE_GTK_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "googleurl/src/gurl.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class BookmarkNode;
+class Profile;
+class RecentlyUsedFoldersComboModel;
+
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GParamSpec GParamSpec;
+
+class BookmarkBubbleGtk : public InfoBubbleGtkDelegate,
+                          public NotificationObserver {
+ public:
+  // Shows the bookmark bubble, pointing at |anchor_widget|.
+  static void Show(GtkWidget* anchor_widget,
+                   Profile* profile,
+                   const GURL& url,
+                   bool newly_bookmarked);
+
+  // Implements the InfoBubbleGtkDelegate.  We are notified when the bubble
+  // is about to be closed, so we have a chance to save any state / input in
+  // our widgets before they are destroyed.
+  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                 bool closed_by_escape);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  BookmarkBubbleGtk(GtkWidget* anchor,
+                    Profile* profile,
+                    const GURL& url,
+                    bool newly_bookmarked);
+  ~BookmarkBubbleGtk();
+
+  // Notified when |content_| is destroyed so we can delete our instance.
+  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnDestroy);
+  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnNameActivate);
+  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnFolderChanged);
+  CHROMEGTK_CALLBACK_1(BookmarkBubbleGtk, void, OnFolderPopupShown,
+                       GParamSpec*);
+  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnEditClicked);
+  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnCloseClicked);
+  CHROMEGTK_CALLBACK_0(BookmarkBubbleGtk, void, OnRemoveClicked);
+
+  // Update the bookmark with any edits that have been made.
+  void ApplyEdits();
+
+  // Open the bookmark editor for the current url and close the bubble.
+  void ShowEditor();
+
+  // Return the UTF8 encoded title for the current |url_|.
+  std::string GetTitle();
+
+  void InitFolderComboModel();
+
+  // The URL of the bookmark.
+  GURL url_;
+  // Our current profile (used to access the bookmark system).
+  Profile* profile_;
+
+  // Provides colors and stuff.
+  GtkThemeProvider* theme_provider_;
+
+  // The widget relative to which we are positioned.
+  GtkWidget* anchor_;
+
+  // We let the InfoBubble own our content, and then we delete ourself
+  // when the widget is destroyed (when the InfoBubble is destroyed).
+  GtkWidget* content_;
+
+  // The button that removes the bookmark.
+  GtkWidget* remove_button_;
+
+  // The various labels in the interface. We keep track of them for theme
+  // changes.
+  std::vector<GtkWidget*> labels_;
+
+  // The GtkEntry for editing the bookmark name / title.
+  GtkWidget* name_entry_;
+
+  // The combo box for selecting the bookmark folder.
+  GtkWidget* folder_combo_;
+  scoped_ptr<RecentlyUsedFoldersComboModel> folder_combo_model_;
+
+  InfoBubbleGtk* bubble_;
+
+  // We need to push some things on the back of the message loop, so we have
+  // a factory attached to our instance to manage task lifetimes.
+  ScopedRunnableMethodFactory<BookmarkBubbleGtk> factory_;
+
+  // Whether the bubble is creating or editing an existing bookmark.
+  bool newly_bookmarked_;
+  // When closing the window, whether we should update or remove the bookmark.
+  bool apply_edits_;
+  bool remove_bookmark_;
+
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkBubbleGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_BUBBLE_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_editor_gtk.cc b/chrome/browser/ui/gtk/bookmark_editor_gtk.cc
new file mode 100644
index 0000000..b4c3429
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_editor_gtk.cc
@@ -0,0 +1,584 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_editor_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/bookmark_tree_model.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "googleurl/src/gurl.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/point.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "views/controls/menu/menu_2.h"
+#else
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#endif
+
+namespace {
+
+// Background color of text field when URL is invalid.
+const GdkColor kErrorColor = GDK_COLOR_RGB(0xFF, 0xBC, 0xBC);
+
+// Preferred initial dimensions, in pixels, of the folder tree.
+static const int kTreeWidth = 300;
+static const int kTreeHeight = 150;
+
+}  // namespace
+
+class BookmarkEditorGtk::ContextMenuController
+    : public ui::SimpleMenuModel::Delegate {
+ public:
+  explicit ContextMenuController(BookmarkEditorGtk* editor)
+      : editor_(editor),
+        running_menu_for_root_(false) {
+    menu_model_.reset(new ui::SimpleMenuModel(this));
+    menu_model_->AddItemWithStringId(COMMAND_EDIT, IDS_EDIT);
+    menu_model_->AddItemWithStringId(
+        COMMAND_NEW_FOLDER,
+        IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM);
+#if defined(TOOLKIT_VIEWS)
+    menu_.reset(new views::Menu2(menu_model_.get()));
+#else
+    menu_.reset(new MenuGtk(NULL, menu_model_.get()));
+#endif
+  }
+  virtual ~ContextMenuController() {}
+
+  void RunMenu(const gfx::Point& point, guint32 event_time) {
+    const BookmarkNode* selected_node = GetSelectedNode();
+    if (selected_node)
+      running_menu_for_root_ = selected_node->GetParent()->IsRoot();
+#if defined(TOOLKIT_VIEWS)
+    menu_->RunContextMenuAt(point);
+#else
+    menu_->PopupAsContext(point, event_time);
+#endif
+  }
+
+  void Cancel() {
+    editor_ = NULL;
+#if defined(TOOLKIT_VIEWS)
+    menu_->CancelMenu();
+#else
+    menu_->Cancel();
+#endif
+  }
+
+ private:
+  enum ContextMenuCommand {
+    COMMAND_EDIT,
+    COMMAND_NEW_FOLDER
+  };
+
+  // Overridden from ui::SimpleMenuModel::Delegate:
+  virtual bool IsCommandIdEnabled(int command_id) const {
+    return !(command_id == COMMAND_EDIT && running_menu_for_root_) &&
+        (editor_ != NULL);
+  }
+
+  virtual bool IsCommandIdChecked(int command_id) const {
+    return false;
+  }
+
+  virtual bool GetAcceleratorForCommandId(int command_id,
+                                          ui::Accelerator* accelerator) {
+    return false;
+  }
+
+  virtual void ExecuteCommand(int command_id) {
+    if (!editor_)
+      return;
+
+    switch (command_id) {
+      case COMMAND_EDIT: {
+        GtkTreeIter iter;
+        if (!gtk_tree_selection_get_selected(editor_->tree_selection_,
+                                             NULL,
+                                             &iter)) {
+          return;
+        }
+
+        GtkTreePath* path = gtk_tree_model_get_path(
+            GTK_TREE_MODEL(editor_->tree_store_), &iter);
+        gtk_tree_view_expand_to_path(GTK_TREE_VIEW(editor_->tree_view_), path);
+
+        // Make the folder name editable.
+        gtk_tree_view_set_cursor(GTK_TREE_VIEW(editor_->tree_view_), path,
+            gtk_tree_view_get_column(GTK_TREE_VIEW(editor_->tree_view_), 0),
+            TRUE);
+
+        gtk_tree_path_free(path);
+        break;
+      }
+      case COMMAND_NEW_FOLDER:
+        editor_->NewFolder();
+        break;
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+
+  int64 GetRowIdAt(GtkTreeModel* model, GtkTreeIter* iter) {
+    GValue value = { 0, };
+    gtk_tree_model_get_value(model, iter, bookmark_utils::ITEM_ID, &value);
+    int64 id = g_value_get_int64(&value);
+    g_value_unset(&value);
+    return id;
+  }
+
+  const BookmarkNode* GetNodeAt(GtkTreeModel* model, GtkTreeIter* iter) {
+    int64 id = GetRowIdAt(model, iter);
+    return (id > 0) ? editor_->bb_model_->GetNodeByID(id) : NULL;
+  }
+
+  const BookmarkNode* GetSelectedNode() {
+    GtkTreeModel* model;
+    GtkTreeIter iter;
+    if (!gtk_tree_selection_get_selected(editor_->tree_selection_,
+                                         &model,
+                                         &iter)) {
+      return NULL;
+    }
+
+    return GetNodeAt(model, &iter);
+  }
+
+  // The model and view for the right click context menu.
+  scoped_ptr<ui::SimpleMenuModel> menu_model_;
+#if defined(TOOLKIT_VIEWS)
+  scoped_ptr<views::Menu2> menu_;
+#else
+  scoped_ptr<MenuGtk> menu_;
+#endif
+
+  // The context menu was brought up for. Set to NULL when the menu is canceled.
+  BookmarkEditorGtk* editor_;
+
+  // If true, we're running the menu for the bookmark bar or other bookmarks
+  // nodes.
+  bool running_menu_for_root_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
+};
+
+// static
+void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
+                          Profile* profile,
+                          const BookmarkNode* parent,
+                          const EditDetails& details,
+                          Configuration configuration) {
+  DCHECK(profile);
+  BookmarkEditorGtk* editor =
+      new BookmarkEditorGtk(parent_hwnd, profile, parent, details,
+                            configuration);
+  editor->Show();
+}
+
+BookmarkEditorGtk::BookmarkEditorGtk(
+    GtkWindow* window,
+    Profile* profile,
+    const BookmarkNode* parent,
+    const EditDetails& details,
+    BookmarkEditor::Configuration configuration)
+    : profile_(profile),
+      dialog_(NULL),
+      parent_(parent),
+      details_(details),
+      running_menu_for_root_(false),
+      show_tree_(configuration == SHOW_TREE) {
+  DCHECK(profile);
+  Init(window);
+}
+
+BookmarkEditorGtk::~BookmarkEditorGtk() {
+  // The tree model is deleted before the view. Reset the model otherwise the
+  // tree will reference a deleted model.
+
+  bb_model_->RemoveObserver(this);
+}
+
+void BookmarkEditorGtk::Init(GtkWindow* parent_window) {
+  bb_model_ = profile_->GetBookmarkModel();
+  DCHECK(bb_model_);
+  bb_model_->AddObserver(this);
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_TITLE).c_str(),
+      parent_window,
+      GTK_DIALOG_MODAL,
+      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+      NULL);
+  gtk_dialog_set_has_separator(GTK_DIALOG(dialog_), FALSE);
+
+  if (show_tree_) {
+    GtkWidget* action_area = GTK_DIALOG(dialog_)->action_area;
+    new_folder_button_ = gtk_button_new_with_label(
+        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_BUTTON).c_str());
+    g_signal_connect(new_folder_button_, "clicked",
+                     G_CALLBACK(OnNewFolderClickedThunk), this);
+    gtk_container_add(GTK_CONTAINER(action_area), new_folder_button_);
+    gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(action_area),
+                                       new_folder_button_, TRUE);
+  }
+
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
+
+  // The GTK dialog content area layout (overview)
+  //
+  // +- GtkVBox |vbox| ----------------------------------------------+
+  // |+- GtkTable |table| ------------------------------------------+|
+  // ||+- GtkLabel ------+ +- GtkEntry |name_entry_| --------------+||
+  // |||                 | |                                       |||
+  // ||+-----------------+ +---------------------------------------+||
+  // ||+- GtkLabel ------+ +- GtkEntry |url_entry_| ---------------+|| *
+  // |||                 | |                                       |||
+  // ||+-----------------+ +---------------------------------------+||
+  // |+-------------------------------------------------------------+|
+  // |+- GtkScrollWindow |scroll_window| ---------------------------+|
+  // ||+- GtkTreeView |tree_view_| --------------------------------+||
+  // |||+- GtkTreeViewColumn |name_column| -----------------------+|||
+  // ||||                                                         ||||
+  // ||||                                                         ||||
+  // ||||                                                         ||||
+  // ||||                                                         ||||
+  // |||+---------------------------------------------------------+|||
+  // ||+-----------------------------------------------------------+||
+  // |+-------------------------------------------------------------+|
+  // +---------------------------------------------------------------+
+  //
+  // * The url and corresponding label are not shown if creating a new folder.
+  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, 12);
+
+  name_entry_ = gtk_entry_new();
+  std::string title;
+  if (details_.type == EditDetails::EXISTING_NODE) {
+    title = UTF16ToUTF8(details_.existing_node->GetTitle());
+  } else if (details_.type == EditDetails::NEW_FOLDER) {
+    title = l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME);
+  }
+  gtk_entry_set_text(GTK_ENTRY(name_entry_), title.c_str());
+  g_signal_connect(name_entry_, "changed",
+                   G_CALLBACK(OnEntryChangedThunk), this);
+  gtk_entry_set_activates_default(GTK_ENTRY(name_entry_), TRUE);
+
+  GtkWidget* table;
+  if (details_.type != EditDetails::NEW_FOLDER) {
+    url_entry_ = gtk_entry_new();
+    std::string url_spec;
+    if (details_.type == EditDetails::EXISTING_NODE)
+      url_spec = details_.existing_node->GetURL().spec();
+    gtk_entry_set_text(GTK_ENTRY(url_entry_), url_spec.c_str());
+    g_signal_connect(url_entry_, "changed",
+                     G_CALLBACK(OnEntryChangedThunk), this);
+    gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
+    table = gtk_util::CreateLabeledControlsGroup(NULL,
+        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str(),
+        name_entry_,
+        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_URL_LABEL).c_str(),
+        url_entry_,
+        NULL);
+
+  } else {
+    url_entry_ = NULL;
+    table = gtk_util::CreateLabeledControlsGroup(NULL,
+        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str(),
+        name_entry_,
+        NULL);
+  }
+
+  gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+
+  if (show_tree_) {
+    GtkTreeIter selected_iter;
+    int64 selected_id = 0;
+    if (details_.type == EditDetails::EXISTING_NODE)
+      selected_id = details_.existing_node->GetParent()->id();
+    else if (parent_)
+      selected_id = parent_->id();
+    tree_store_ = bookmark_utils::MakeFolderTreeStore();
+    bookmark_utils::AddToTreeStore(bb_model_, selected_id, tree_store_,
+                                   &selected_iter);
+    tree_view_ = bookmark_utils::MakeTreeViewForStore(tree_store_);
+    gtk_widget_set_size_request(tree_view_, kTreeWidth, kTreeHeight);
+    tree_selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_));
+    g_signal_connect(tree_view_, "button-press-event",
+                     G_CALLBACK(OnTreeViewButtonPressEventThunk), this);
+
+    GtkTreePath* path = NULL;
+    if (selected_id) {
+      path = gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store_),
+                                     &selected_iter);
+    } else {
+      // We don't have a selected parent (Probably because we're making a new
+      // bookmark). Select the first item in the list.
+      path = gtk_tree_path_new_from_string("0");
+    }
+
+    gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_view_), path);
+    gtk_tree_selection_select_path(tree_selection_, path);
+    gtk_tree_path_free(path);
+
+    GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                    GTK_POLICY_NEVER,
+                                   GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                        GTK_SHADOW_ETCHED_IN);
+    gtk_container_add(GTK_CONTAINER(scroll_window), tree_view_);
+
+    gtk_box_pack_start(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 0);
+
+    g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_)),
+                     "changed", G_CALLBACK(OnSelectionChangedThunk), this);
+  }
+
+  gtk_box_pack_start(GTK_BOX(content_area), vbox, TRUE, TRUE, 0);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnResponseThunk), this);
+  g_signal_connect(dialog_, "delete-event",
+                   G_CALLBACK(OnWindowDeleteEventThunk), this);
+  g_signal_connect(dialog_, "destroy",
+                   G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+void BookmarkEditorGtk::Show() {
+  // Manually call our OnEntryChanged handler to set the initial state.
+  OnEntryChanged(NULL);
+
+  gtk_util::ShowDialog(dialog_);
+}
+
+void BookmarkEditorGtk::Close() {
+  // Under the model that we've inherited from Windows, dialogs can receive
+  // more than one Close() call inside the current message loop event.
+  if (dialog_) {
+    gtk_widget_destroy(dialog_);
+    dialog_ = NULL;
+  }
+}
+
+void BookmarkEditorGtk::BookmarkNodeMoved(BookmarkModel* model,
+                                          const BookmarkNode* old_parent,
+                                          int old_index,
+                                          const BookmarkNode* new_parent,
+                                          int new_index) {
+  Reset();
+}
+
+void BookmarkEditorGtk::BookmarkNodeAdded(BookmarkModel* model,
+                                          const BookmarkNode* parent,
+                                          int index) {
+  Reset();
+}
+
+void BookmarkEditorGtk::BookmarkNodeRemoved(BookmarkModel* model,
+                                            const BookmarkNode* parent,
+                                            int index,
+                                            const BookmarkNode* node) {
+  if ((details_.type == EditDetails::EXISTING_NODE &&
+       details_.existing_node->HasAncestor(node)) ||
+      (parent_ && parent_->HasAncestor(node))) {
+    // The node, or its parent was removed. Close the dialog.
+    Close();
+  } else {
+    Reset();
+  }
+}
+
+void BookmarkEditorGtk::BookmarkNodeChildrenReordered(
+    BookmarkModel* model, const BookmarkNode* node) {
+  Reset();
+}
+
+void BookmarkEditorGtk::Reset() {
+  // TODO(erg): The windows implementation tries to be smart. For now, just
+  // close the window.
+  Close();
+}
+
+GURL BookmarkEditorGtk::GetInputURL() const {
+  if (!url_entry_)
+    return GURL();  // Happens when we're editing a folder.
+  return URLFixerUpper::FixupURL(gtk_entry_get_text(GTK_ENTRY(url_entry_)),
+                                 std::string());
+}
+
+string16 BookmarkEditorGtk::GetInputTitle() const {
+  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(name_entry_)));
+}
+
+void BookmarkEditorGtk::ApplyEdits() {
+  DCHECK(bb_model_->IsLoaded());
+
+  GtkTreeIter currently_selected_iter;
+  if (show_tree_) {
+    if (!gtk_tree_selection_get_selected(tree_selection_, NULL,
+                                         &currently_selected_iter)) {
+      ApplyEdits(NULL);
+      return;
+    }
+  }
+
+  ApplyEdits(&currently_selected_iter);
+}
+
+void BookmarkEditorGtk::ApplyEdits(GtkTreeIter* selected_parent) {
+  // We're going to apply edits to the bookmark bar model, which will call us
+  // back. Normally when a structural edit occurs we reset the tree model.
+  // We don't want to do that here, so we remove ourselves as an observer.
+  bb_model_->RemoveObserver(this);
+
+  GURL new_url(GetInputURL());
+  string16 new_title(GetInputTitle());
+
+  if (!show_tree_ || !selected_parent) {
+    bookmark_utils::ApplyEditsWithNoGroupChange(
+        bb_model_, parent_, details_, new_title, new_url);
+    return;
+  }
+
+  // Create the new groups and update the titles.
+  const BookmarkNode* new_parent =
+      bookmark_utils::CommitTreeStoreDifferencesBetween(
+      bb_model_, tree_store_, selected_parent);
+
+  if (!new_parent) {
+    // Bookmarks must be parented.
+    NOTREACHED();
+    return;
+  }
+
+  bookmark_utils::ApplyEditsWithPossibleGroupChange(
+      bb_model_, new_parent, details_, new_title, new_url);
+}
+
+void BookmarkEditorGtk::AddNewGroup(GtkTreeIter* parent, GtkTreeIter* child) {
+  gtk_tree_store_append(tree_store_, child, parent);
+  gtk_tree_store_set(
+      tree_store_, child,
+      bookmark_utils::FOLDER_ICON, GtkThemeProvider::GetFolderIcon(true),
+      bookmark_utils::FOLDER_NAME,
+          l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME).c_str(),
+      bookmark_utils::ITEM_ID, static_cast<int64>(0),
+      bookmark_utils::IS_EDITABLE, TRUE,
+      -1);
+}
+
+void BookmarkEditorGtk::OnSelectionChanged(GtkWidget* selection) {
+  if (!gtk_tree_selection_get_selected(tree_selection_, NULL, NULL))
+    gtk_widget_set_sensitive(new_folder_button_, FALSE);
+  else
+    gtk_widget_set_sensitive(new_folder_button_, TRUE);
+}
+
+void BookmarkEditorGtk::OnResponse(GtkWidget* dialog, int response_id) {
+  if (response_id == GTK_RESPONSE_ACCEPT)
+    ApplyEdits();
+
+  Close();
+}
+
+gboolean BookmarkEditorGtk::OnWindowDeleteEvent(GtkWidget* widget,
+                                                GdkEvent* event) {
+  Close();
+
+  // Return true to prevent the gtk dialog from being destroyed. Close will
+  // destroy it for us and the default gtk_dialog_delete_event_handler() will
+  // force the destruction without us being able to stop it.
+  return TRUE;
+}
+
+void BookmarkEditorGtk::OnWindowDestroy(GtkWidget* widget) {
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void BookmarkEditorGtk::OnEntryChanged(GtkWidget* entry) {
+  gboolean can_close = TRUE;
+  if (details_.type == EditDetails::NEW_FOLDER) {
+    if (GetInputTitle().empty()) {
+      gtk_widget_modify_base(name_entry_, GTK_STATE_NORMAL,
+                             &kErrorColor);
+      can_close = FALSE;
+    } else {
+      gtk_widget_modify_base(name_entry_, GTK_STATE_NORMAL, NULL);
+    }
+  } else {
+    GURL url(GetInputURL());
+    if (!url.is_valid()) {
+      gtk_widget_modify_base(url_entry_, GTK_STATE_NORMAL,
+                             &kErrorColor);
+      can_close = FALSE;
+    } else {
+      gtk_widget_modify_base(url_entry_, GTK_STATE_NORMAL, NULL);
+    }
+  }
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
+                                    GTK_RESPONSE_ACCEPT, can_close);
+}
+
+void BookmarkEditorGtk::OnNewFolderClicked(GtkWidget* button) {
+  NewFolder();
+}
+
+gboolean BookmarkEditorGtk::OnTreeViewButtonPressEvent(GtkWidget* widget,
+                                                       GdkEventButton* event) {
+  if (event->button == 3) {
+    if (!menu_controller_.get())
+      menu_controller_.reset(new ContextMenuController(this));
+    menu_controller_->RunMenu(gfx::Point(event->x_root, event->y_root),
+                              event->time);
+  }
+
+  return FALSE;
+}
+
+void BookmarkEditorGtk::NewFolder() {
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(tree_selection_,
+                                       NULL,
+                                       &iter)) {
+    NOTREACHED() << "Something should always be selected if New Folder " <<
+                    "is clicked";
+    return;
+  }
+
+  GtkTreeIter new_item_iter;
+  AddNewGroup(&iter, &new_item_iter);
+
+  GtkTreePath* path = gtk_tree_model_get_path(
+      GTK_TREE_MODEL(tree_store_), &new_item_iter);
+  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_view_), path);
+
+  // Make the folder name editable.
+  gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view_), path,
+      gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view_), 0),
+      TRUE);
+
+  gtk_tree_path_free(path);
+}
diff --git a/chrome/browser/ui/gtk/bookmark_editor_gtk.h b/chrome/browser/ui/gtk/bookmark_editor_gtk.h
new file mode 100644
index 0000000..cba0c95
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_editor_gtk.h
@@ -0,0 +1,165 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BOOKMARK_EDITOR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_EDITOR_GTK_H_
+#pragma once
+
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "chrome/browser/bookmarks/bookmark_editor.h"
+#include "chrome/browser/bookmarks/bookmark_model_observer.h"
+#include "ui/base/gtk/gtk_integers.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class GURL;
+
+typedef union  _GdkEvent GdkEvent;
+typedef struct _GdkEventButton GdkEventButton;
+typedef struct _GtkTreeIter GtkTreeIter;
+typedef struct _GtkTreeSelection GtkTreeSelection;
+typedef struct _GtkTreeStore GtkTreeStore;
+typedef struct _GtkWidget GtkWidget;
+
+namespace gfx {
+class Point;
+}  // namespace gfx
+
+// GTK version of the bookmark editor dialog.
+class BookmarkEditorGtk : public BookmarkEditor,
+                          public BookmarkModelObserver {
+ public:
+  BookmarkEditorGtk(GtkWindow* window,
+                    Profile* profile,
+                    const BookmarkNode* parent,
+                    const EditDetails& details,
+                    BookmarkEditor::Configuration configuration);
+
+  virtual ~BookmarkEditorGtk();
+
+  void Show();
+  void Close();
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParent);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParentAndURL);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLToExistingURL);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditTitleKeepsPosition);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditURLKeepsPosition);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ModelsMatch);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, MoveToNewParent);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, NewURL);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLNoTree);
+  FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeTitleNoTree);
+
+  class ContextMenuController;
+  friend class ContextMenuController;
+
+  void Init(GtkWindow* parent_window);
+
+  // BookmarkModel observer methods. Any structural change results in
+  // resetting the tree model.
+  virtual void Loaded(BookmarkModel* model) { }
+  virtual void BookmarkNodeMoved(BookmarkModel* model,
+                                 const BookmarkNode* old_parent,
+                                 int old_index,
+                                 const BookmarkNode* new_parent,
+                                 int new_index);
+  virtual void BookmarkNodeAdded(BookmarkModel* model,
+                                 const BookmarkNode* parent,
+                                 int index);
+  virtual void BookmarkNodeRemoved(BookmarkModel* model,
+                                   const BookmarkNode* parent,
+                                   int old_index,
+                                   const BookmarkNode* node);
+  virtual void BookmarkNodeChanged(BookmarkModel* model,
+                                   const BookmarkNode* node) {}
+  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
+                                             const BookmarkNode* node);
+  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
+                                         const BookmarkNode* node) {}
+
+  // Resets the model of the tree and updates the various buttons appropriately.
+  void Reset();
+
+  // Returns the current url the user has input.
+  GURL GetInputURL() const;
+
+  // Returns the title the user has input.
+  string16 GetInputTitle() const;
+
+  // Invokes ApplyEdits with the selected node.
+  //
+  // TODO(erg): This was copied from the windows version. Both should be
+  // cleaned up so that we don't overload ApplyEdits.
+  void ApplyEdits();
+
+  // Applies the edits done by the user. |selected_parent| gives the parent of
+  // the URL being edited.
+  void ApplyEdits(GtkTreeIter* selected_parent);
+
+  // Adds a new group parented on |parent| and sets |child| to point to this
+  // new group.
+  void AddNewGroup(GtkTreeIter* parent, GtkTreeIter* child);
+
+  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnSelectionChanged);
+  CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, void, OnResponse, int);
+  CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, gboolean, OnWindowDeleteEvent,
+                       GdkEvent*);
+
+  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnWindowDestroy);
+  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnEntryChanged);
+
+  CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnNewFolderClicked);
+
+  CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, gboolean, OnTreeViewButtonPressEvent,
+                       GdkEventButton*);
+
+  void NewFolder();
+
+  // Profile the entry is from.
+  Profile* profile_;
+
+  // The dialog to display on screen.
+  GtkWidget* dialog_;
+  GtkWidget* name_entry_;
+  GtkWidget* url_entry_;  // This is NULL if IsEditingFolder.
+  GtkWidget* tree_view_;
+  GtkWidget* new_folder_button_;
+
+  // Helper object that manages the currently selected item in |tree_view_|.
+  GtkTreeSelection* tree_selection_;
+
+  // Our local copy of the bookmark data that we make from the BookmarkModel
+  // that we can modify as much as we want and still discard when the user
+  // clicks Cancel.
+  GtkTreeStore* tree_store_;
+
+  // TODO(erg): BookmarkEditorView has an EditorTreeModel object here; convert
+  // that into a GObject that implements the interface GtkTreeModel.
+
+  // Initial parent to select. Is only used if node_ is NULL.
+  const BookmarkNode* parent_;
+
+  // Details about the node we're editing.
+  const EditDetails details_;
+
+  // Mode used to create nodes from.
+  BookmarkModel* bb_model_;
+
+  // If true, we're running the menu for the bookmark bar or other bookmarks
+  // nodes.
+  bool running_menu_for_root_;
+
+  // Is the tree shown?
+  bool show_tree_;
+
+  // The context menu controller.
+  scoped_ptr<ContextMenuController> menu_controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkEditorGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_EDITOR_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_editor_gtk_unittest.cc b/chrome/browser/ui/gtk/bookmark_editor_gtk_unittest.cc
new file mode 100644
index 0000000..c628c69
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_editor_gtk_unittest.cc
@@ -0,0 +1,326 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+
+#include <string>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/ui/gtk/bookmark_editor_gtk.h"
+#include "chrome/browser/ui/gtk/bookmark_tree_model.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+using base::TimeDelta;
+using bookmark_utils::GetTitleFromTreeIter;
+
+// Base class for bookmark editor tests. This class is a copy from
+// bookmark_editor_view_unittest.cc, and all the tests in this file are
+// GTK-ifications of the corresponding views tests. Testing here is really
+// important because on Linux, we make round trip copies from chrome's
+// BookmarkModel class to GTK's native GtkTreeStore.
+class BookmarkEditorGtkTest : public testing::Test {
+ public:
+  BookmarkEditorGtkTest()
+      : ui_thread_(BrowserThread::UI, &message_loop_),
+        file_thread_(BrowserThread::FILE, &message_loop_),
+        model_(NULL) {
+  }
+
+  virtual void SetUp() {
+    profile_.reset(new TestingProfile());
+    profile_->set_has_history_service(true);
+    profile_->CreateBookmarkModel(true);
+    profile_->BlockUntilBookmarkModelLoaded();
+
+    model_ = profile_->GetBookmarkModel();
+
+    AddTestData();
+  }
+
+  virtual void TearDown() {
+  }
+
+ protected:
+  MessageLoopForUI message_loop_;
+  BrowserThread ui_thread_;
+  BrowserThread file_thread_;
+  BookmarkModel* model_;
+  scoped_ptr<TestingProfile> profile_;
+
+  std::string base_path() const { return "file:///c:/tmp/"; }
+
+  const BookmarkNode* GetNode(const std::string& name) {
+    return model_->GetMostRecentlyAddedNodeForURL(GURL(base_path() + name));
+  }
+
+ private:
+  // Creates the following structure:
+  // bookmark bar node
+  //   a
+  //   F1
+  //    f1a
+  //    F11
+  //     f11a
+  //   F2
+  // other node
+  //   oa
+  //   OF1
+  //     of1a
+  void AddTestData() {
+    std::string test_base = base_path();
+
+    model_->AddURL(model_->GetBookmarkBarNode(), 0, ASCIIToUTF16("a"),
+                   GURL(test_base + "a"));
+    const BookmarkNode* f1 =
+        model_->AddGroup(model_->GetBookmarkBarNode(), 1, ASCIIToUTF16("F1"));
+    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
+    const BookmarkNode* f11 = model_->AddGroup(f1, 1, ASCIIToUTF16("F11"));
+    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
+    model_->AddGroup(model_->GetBookmarkBarNode(), 2, ASCIIToUTF16("F2"));
+
+    // Children of the other node.
+    model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
+                   GURL(test_base + "oa"));
+    const BookmarkNode* of1 =
+        model_->AddGroup(model_->other_node(), 1, ASCIIToUTF16("OF1"));
+    model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
+  }
+};
+
+// Makes sure the tree model matches that of the bookmark bar model.
+TEST_F(BookmarkEditorGtkTest, ModelsMatch) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(),
+                           BookmarkEditor::SHOW_TREE);
+
+  // The root should have two children, one for the bookmark bar node,
+  // the other for the 'other bookmarks' folder.
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  GtkTreeIter toplevel;
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &toplevel));
+  GtkTreeIter bookmark_bar_node = toplevel;
+  ASSERT_TRUE(gtk_tree_model_iter_next(store, &toplevel));
+  GtkTreeIter other_node = toplevel;
+  ASSERT_FALSE(gtk_tree_model_iter_next(store, &toplevel));
+
+  // The bookmark bar should have 2 nodes: folder F1 and F2.
+  GtkTreeIter f1_iter;
+  GtkTreeIter child;
+  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
+  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &bookmark_bar_node));
+  f1_iter = child;
+  ASSERT_EQ("F1", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
+  ASSERT_TRUE(gtk_tree_model_iter_next(store, &child));
+  ASSERT_EQ("F2", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
+  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
+
+  // F1 should have one child, F11
+  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f1_iter));
+  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &f1_iter));
+  ASSERT_EQ("F11", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
+  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
+
+  // Other node should have one child (OF1).
+  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &other_node));
+  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &other_node));
+  ASSERT_EQ("OF1", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
+  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
+}
+
+// Changes the title and makes sure parent/visual order doesn't change.
+TEST_F(BookmarkEditorGtkTest, EditTitleKeepsPosition) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(GetNode("a")),
+                           BookmarkEditor::SHOW_TREE);
+  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
+
+  GtkTreeIter bookmark_bar_node;
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
+  editor.ApplyEdits(&bookmark_bar_node);
+
+  const BookmarkNode* bb_node =
+      profile_->GetBookmarkModel()->GetBookmarkBarNode();
+  ASSERT_EQ(ASCIIToUTF16("new_a"), bb_node->GetChild(0)->GetTitle());
+  // The URL shouldn't have changed.
+  ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->GetURL());
+}
+
+// Changes the url and makes sure parent/visual order doesn't change.
+TEST_F(BookmarkEditorGtkTest, EditURLKeepsPosition) {
+  Time node_time = GetNode("a")->date_added();
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(GetNode("a")),
+                           BookmarkEditor::SHOW_TREE);
+  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
+                     GURL(base_path() + "new_a").spec().c_str());
+
+  GtkTreeIter bookmark_bar_node;
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
+  editor.ApplyEdits(&bookmark_bar_node);
+
+  const BookmarkNode* bb_node =
+      profile_->GetBookmarkModel()->GetBookmarkBarNode();
+  ASSERT_EQ(ASCIIToUTF16("a"), bb_node->GetChild(0)->GetTitle());
+  // The URL should have changed.
+  ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->GetURL());
+  ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
+}
+
+// Moves 'a' to be a child of the other node.
+TEST_F(BookmarkEditorGtkTest, ChangeParent) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(GetNode("a")),
+                           BookmarkEditor::SHOW_TREE);
+
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  GtkTreeIter gtk_other_node;
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
+  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
+  editor.ApplyEdits(&gtk_other_node);
+
+  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
+  ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
+  ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->GetURL());
+}
+
+// Moves 'a' to be a child of the other node.
+// Moves 'a' to be a child of the other node and changes its url to new_a.
+TEST_F(BookmarkEditorGtkTest, ChangeParentAndURL) {
+  Time node_time = GetNode("a")->date_added();
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(GetNode("a")),
+                           BookmarkEditor::SHOW_TREE);
+
+  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
+                     GURL(base_path() + "new_a").spec().c_str());
+
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  GtkTreeIter gtk_other_node;
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
+  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
+  editor.ApplyEdits(&gtk_other_node);
+
+  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
+  ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
+  ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->GetURL());
+  ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
+}
+
+// Creates a new folder and moves a node to it.
+TEST_F(BookmarkEditorGtkTest, MoveToNewParent) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(GetNode("a")),
+                           BookmarkEditor::SHOW_TREE);
+
+  GtkTreeIter bookmark_bar_node;
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
+
+  // The bookmark bar should have 2 nodes: folder F1 and F2.
+  GtkTreeIter f2_iter;
+  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
+  ASSERT_TRUE(gtk_tree_model_iter_children(store, &f2_iter,
+                                           &bookmark_bar_node));
+  ASSERT_TRUE(gtk_tree_model_iter_next(store, &f2_iter));
+
+  // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
+  GtkTreeIter f21_iter;
+  editor.AddNewGroup(&f2_iter, &f21_iter);
+  gtk_tree_store_set(editor.tree_store_, &f21_iter,
+                     bookmark_utils::FOLDER_NAME, "F21", -1);
+  GtkTreeIter f211_iter;
+  editor.AddNewGroup(&f21_iter, &f211_iter);
+  gtk_tree_store_set(editor.tree_store_, &f211_iter,
+                     bookmark_utils::FOLDER_NAME, "F211", -1);
+
+  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f2_iter));
+
+  editor.ApplyEdits(&f2_iter);
+
+  const BookmarkNode* bb_node =
+      profile_->GetBookmarkModel()->GetBookmarkBarNode();
+  const BookmarkNode* mf2 = bb_node->GetChild(1);
+
+  // F2 in the model should have two children now: F21 and the node edited.
+  ASSERT_EQ(2, mf2->GetChildCount());
+  // F21 should be first.
+  ASSERT_EQ(ASCIIToUTF16("F21"), mf2->GetChild(0)->GetTitle());
+  // Then a.
+  ASSERT_EQ(ASCIIToUTF16("a"), mf2->GetChild(1)->GetTitle());
+
+  // F21 should have one child, F211.
+  const BookmarkNode* mf21 = mf2->GetChild(0);
+  ASSERT_EQ(1, mf21->GetChildCount());
+  ASSERT_EQ(ASCIIToUTF16("F211"), mf21->GetChild(0)->GetTitle());
+}
+
+// Brings up the editor, creating a new URL on the bookmark bar.
+TEST_F(BookmarkEditorGtkTest, NewURL) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(),
+                           BookmarkEditor::SHOW_TREE);
+
+  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
+                     GURL(base_path() + "a").spec().c_str());
+  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
+
+  GtkTreeIter bookmark_bar_node;
+  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
+  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
+  editor.ApplyEdits(&bookmark_bar_node);
+
+  const BookmarkNode* bb_node =
+      profile_->GetBookmarkModel()->GetBookmarkBarNode();
+  ASSERT_EQ(4, bb_node->GetChildCount());
+
+  const BookmarkNode* new_node = bb_node->GetChild(3);
+  EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
+  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
+}
+
+// Brings up the editor with no tree and modifies the url.
+TEST_F(BookmarkEditorGtkTest, ChangeURLNoTree) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(
+                               model_->other_node()->GetChild(0)),
+                           BookmarkEditor::NO_TREE);
+
+  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
+                     GURL(base_path() + "a").spec().c_str());
+  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
+
+  editor.ApplyEdits(NULL);
+
+  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
+  ASSERT_EQ(2, other_node->GetChildCount());
+
+  const BookmarkNode* new_node = other_node->GetChild(0);
+
+  EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
+  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
+}
+
+// Brings up the editor with no tree and modifies only the title.
+TEST_F(BookmarkEditorGtkTest, ChangeTitleNoTree) {
+  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
+                           BookmarkEditor::EditDetails(
+                               model_->other_node()->GetChild(0)),
+                           BookmarkEditor::NO_TREE);
+  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
+
+  editor.ApplyEdits();
+
+  const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
+  ASSERT_EQ(2, other_node->GetChildCount());
+
+  const BookmarkNode* new_node = other_node->GetChild(0);
+  EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
+}
diff --git a/chrome/browser/ui/gtk/bookmark_menu_controller_gtk.cc b/chrome/browser/ui/gtk/bookmark_menu_controller_gtk.cc
new file mode 100644
index 0000000..aaac8d8
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_menu_controller_gtk.cc
@@ -0,0 +1,376 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_menu_controller_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/page_navigator.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+#include "webkit/glue/window_open_disposition.h"
+
+namespace {
+
+// TODO(estade): It might be a good idea to vary this by locale.
+const int kMaxChars = 50;
+
+void SetImageMenuItem(GtkWidget* menu_item,
+                      const BookmarkNode* node,
+                      BookmarkModel* model) {
+  GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model, true);
+  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
+                                gtk_image_new_from_pixbuf(pixbuf));
+  g_object_unref(pixbuf);
+}
+
+const BookmarkNode* GetNodeFromMenuItem(GtkWidget* menu_item) {
+  return static_cast<const BookmarkNode*>(
+      g_object_get_data(G_OBJECT(menu_item), "bookmark-node"));
+}
+
+const BookmarkNode* GetParentNodeFromEmptyMenu(GtkWidget* menu) {
+  return static_cast<const BookmarkNode*>(
+      g_object_get_data(G_OBJECT(menu), "parent-node"));
+}
+
+void* AsVoid(const BookmarkNode* node) {
+  return const_cast<BookmarkNode*>(node);
+}
+
+// The context menu has been dismissed, restore the X and application grabs
+// to whichever menu last had them. (Assuming that menu is still showing.)
+void OnContextMenuHide(GtkWidget* context_menu, GtkWidget* grab_menu) {
+  gtk_util::GrabAllInput(grab_menu);
+
+  // Match the ref we took when connecting this signal.
+  g_object_unref(grab_menu);
+}
+
+}  // namespace
+
+BookmarkMenuController::BookmarkMenuController(Browser* browser,
+                                               Profile* profile,
+                                               PageNavigator* navigator,
+                                               GtkWindow* window,
+                                               const BookmarkNode* node,
+                                               int start_child_index)
+    : browser_(browser),
+      profile_(profile),
+      page_navigator_(navigator),
+      parent_window_(window),
+      model_(profile->GetBookmarkModel()),
+      node_(node),
+      drag_icon_(NULL),
+      ignore_button_release_(false),
+      triggering_widget_(NULL) {
+  menu_ = gtk_menu_new();
+  g_object_ref_sink(menu_);
+  BuildMenu(node, start_child_index, menu_);
+  signals_.Connect(menu_, "hide",
+                   G_CALLBACK(OnMenuHiddenThunk), this);
+  gtk_widget_show_all(menu_);
+}
+
+BookmarkMenuController::~BookmarkMenuController() {
+  profile_->GetBookmarkModel()->RemoveObserver(this);
+  // Make sure the hide handler runs.
+  gtk_widget_hide(menu_);
+  gtk_widget_destroy(menu_);
+  g_object_unref(menu_);
+}
+
+void BookmarkMenuController::Popup(GtkWidget* widget, gint button_type,
+                                   guint32 timestamp) {
+  profile_->GetBookmarkModel()->AddObserver(this);
+
+  triggering_widget_ = widget;
+  signals_.Connect(triggering_widget_, "destroy",
+                   G_CALLBACK(gtk_widget_destroyed), &triggering_widget_);
+  gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget),
+                                    GTK_STATE_ACTIVE);
+  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
+                 &MenuGtk::WidgetMenuPositionFunc,
+                 widget, button_type, timestamp);
+}
+
+void BookmarkMenuController::BookmarkModelChanged() {
+  gtk_menu_popdown(GTK_MENU(menu_));
+}
+
+void BookmarkMenuController::BookmarkNodeFavIconLoaded(
+    BookmarkModel* model, const BookmarkNode* node) {
+  std::map<const BookmarkNode*, GtkWidget*>::iterator it =
+      node_to_menu_widget_map_.find(node);
+  if (it != node_to_menu_widget_map_.end())
+    SetImageMenuItem(it->second, node, model);
+}
+
+void BookmarkMenuController::WillExecuteCommand() {
+  gtk_menu_popdown(GTK_MENU(menu_));
+}
+
+void BookmarkMenuController::CloseMenu() {
+  context_menu_->Cancel();
+}
+
+void BookmarkMenuController::NavigateToMenuItem(
+    GtkWidget* menu_item,
+    WindowOpenDisposition disposition) {
+  const BookmarkNode* node = GetNodeFromMenuItem(menu_item);
+  DCHECK(node);
+  DCHECK(page_navigator_);
+  page_navigator_->OpenURL(
+      node->GetURL(), GURL(), disposition, PageTransition::AUTO_BOOKMARK);
+}
+
+void BookmarkMenuController::BuildMenu(const BookmarkNode* parent,
+                                       int start_child_index,
+                                       GtkWidget* menu) {
+  DCHECK(!parent->GetChildCount() ||
+         start_child_index < parent->GetChildCount());
+
+  signals_.Connect(menu, "button-press-event",
+                   G_CALLBACK(OnMenuButtonPressedOrReleasedThunk), this);
+  signals_.Connect(menu, "button-release-event",
+                   G_CALLBACK(OnMenuButtonPressedOrReleasedThunk), this);
+
+  for (int i = start_child_index; i < parent->GetChildCount(); ++i) {
+    const BookmarkNode* node = parent->GetChild(i);
+
+    // This breaks on word boundaries. Ideally we would break on character
+    // boundaries.
+    string16 elided_name = l10n_util::TruncateString(node->GetTitle(),
+                                                     kMaxChars);
+    GtkWidget* menu_item =
+        gtk_image_menu_item_new_with_label(UTF16ToUTF8(elided_name).c_str());
+    g_object_set_data(G_OBJECT(menu_item), "bookmark-node", AsVoid(node));
+    SetImageMenuItem(menu_item, node, profile_->GetBookmarkModel());
+    gtk_util::SetAlwaysShowImage(menu_item);
+
+    signals_.Connect(menu_item, "button-release-event",
+                     G_CALLBACK(OnButtonReleasedThunk), this);
+    if (node->is_url()) {
+      signals_.Connect(menu_item, "activate",
+                       G_CALLBACK(OnMenuItemActivatedThunk), this);
+    } else if (node->is_folder()) {
+      GtkWidget* submenu = gtk_menu_new();
+      BuildMenu(node, 0, submenu);
+      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
+    } else {
+      NOTREACHED();
+    }
+
+    gtk_drag_source_set(menu_item, GDK_BUTTON1_MASK, NULL, 0,
+        static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_LINK));
+    int target_mask = ui::CHROME_BOOKMARK_ITEM;
+    if (node->is_url())
+      target_mask |= ui::TEXT_URI_LIST | ui::NETSCAPE_URL;
+    ui::SetSourceTargetListFromCodeMask(menu_item, target_mask);
+    signals_.Connect(menu_item, "drag-begin",
+                     G_CALLBACK(OnMenuItemDragBeginThunk), this);
+    signals_.Connect(menu_item, "drag-end",
+                     G_CALLBACK(OnMenuItemDragEndThunk), this);
+    signals_.Connect(menu_item, "drag-data-get",
+                     G_CALLBACK(OnMenuItemDragGetThunk), this);
+
+    // It is important to connect to this signal after setting up the drag
+    // source because we only want to stifle the menu's default handler and
+    // not the handler that the drag source uses.
+    if (node->is_folder()) {
+      signals_.Connect(menu_item, "button-press-event",
+                       G_CALLBACK(OnFolderButtonPressedThunk), this);
+    }
+
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+    node_to_menu_widget_map_[node] = menu_item;
+  }
+
+  if (parent->GetChildCount() == 0) {
+    GtkWidget* empty_menu = gtk_menu_item_new_with_label(
+        l10n_util::GetStringUTF8(IDS_MENU_EMPTY_SUBMENU).c_str());
+    gtk_widget_set_sensitive(empty_menu, FALSE);
+    g_object_set_data(G_OBJECT(menu), "parent-node", AsVoid(parent));
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), empty_menu);
+  }
+}
+
+gboolean BookmarkMenuController::OnMenuButtonPressedOrReleased(
+    GtkWidget* sender,
+    GdkEventButton* event) {
+  // Handle middle mouse downs and right mouse ups.
+  if (!((event->button == 2 && event->type == GDK_BUTTON_RELEASE) ||
+      (event->button == 3 && event->type == GDK_BUTTON_PRESS))) {
+    return FALSE;
+  }
+
+  ignore_button_release_ = false;
+  GtkMenuShell* menu_shell = GTK_MENU_SHELL(sender);
+  // If the cursor is outside our bounds, pass this event up to the parent.
+  if (!gtk_util::WidgetContainsCursor(sender)) {
+    if (menu_shell->parent_menu_shell) {
+      return OnMenuButtonPressedOrReleased(menu_shell->parent_menu_shell,
+                                           event);
+    } else {
+      // We are the top level menu; we can propagate no further.
+      return FALSE;
+    }
+  }
+
+  // This will return NULL if we are not an empty menu.
+  const BookmarkNode* parent = GetParentNodeFromEmptyMenu(sender);
+  bool is_empty_menu = !!parent;
+  // If there is no active menu item and we are not an empty menu, then do
+  // nothing. This can happen if the user has canceled a context menu while
+  // the cursor is hovering over a bookmark menu. Doing nothing is not optimal
+  // (the hovered item should be active), but it's a hopefully rare corner
+  // case.
+  GtkWidget* menu_item = menu_shell->active_menu_item;
+  if (!is_empty_menu && !menu_item)
+    return TRUE;
+  const BookmarkNode* node =
+      menu_item ? GetNodeFromMenuItem(menu_item) : NULL;
+
+  if (event->button == 2 && node && node->is_folder()) {
+    bookmark_utils::OpenAll(parent_window_,
+                            profile_, page_navigator_,
+                            node, NEW_BACKGROUND_TAB);
+    gtk_menu_popdown(GTK_MENU(menu_));
+    return TRUE;
+  } else if (event->button == 3) {
+    DCHECK_NE(is_empty_menu, !!node);
+    if (!is_empty_menu)
+      parent = node->GetParent();
+
+    // Show the right click menu and stop processing this button event.
+    std::vector<const BookmarkNode*> nodes;
+    if (node)
+      nodes.push_back(node);
+    context_menu_controller_.reset(
+        new BookmarkContextMenuController(
+            parent_window_, this, profile_,
+            page_navigator_, parent, nodes));
+    context_menu_.reset(
+        new MenuGtk(NULL, context_menu_controller_->menu_model()));
+
+    // Our bookmark folder menu loses the grab to the context menu. When the
+    // context menu is hidden, re-assert our grab.
+    GtkWidget* grabbing_menu = gtk_grab_get_current();
+    g_object_ref(grabbing_menu);
+    signals_.Connect(context_menu_->widget(), "hide",
+                     G_CALLBACK(OnContextMenuHide), grabbing_menu);
+
+    context_menu_->PopupAsContext(gfx::Point(event->x_root, event->y_root),
+                                  event->time);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+gboolean BookmarkMenuController::OnButtonReleased(
+    GtkWidget* sender,
+    GdkEventButton* event) {
+  if (ignore_button_release_) {
+    // Don't handle this message; it was a drag.
+    ignore_button_release_ = false;
+    return FALSE;
+  }
+
+  // Releasing either button 1 or 2 should trigger the bookmark.
+  if (!gtk_menu_item_get_submenu(GTK_MENU_ITEM(sender))) {
+    // The menu item is a link node.
+    if (event->button == 1 || event->button == 2) {
+      WindowOpenDisposition disposition =
+          event_utils::DispositionFromEventFlags(event->state);
+      NavigateToMenuItem(sender, disposition);
+
+      // We need to manually dismiss the popup menu because we're overriding
+      // button-release-event.
+      gtk_menu_popdown(GTK_MENU(menu_));
+      return TRUE;
+    }
+  } else {
+    // The menu item is a folder node.
+    if (event->button == 1) {
+      // Having overriden the normal handling, we need to manually activate
+      // the item.
+      gtk_menu_shell_select_item(GTK_MENU_SHELL(sender->parent), sender);
+      g_signal_emit_by_name(sender->parent, "activate-current");
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+gboolean BookmarkMenuController::OnFolderButtonPressed(
+    GtkWidget* sender, GdkEventButton* event) {
+  // The button press may start a drag; don't let the default handler run.
+  if (event->button == 1)
+    return TRUE;
+  return FALSE;
+}
+
+void BookmarkMenuController::OnMenuHidden(GtkWidget* menu) {
+  if (triggering_widget_)
+    gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(triggering_widget_));
+}
+
+void BookmarkMenuController::OnMenuItemActivated(GtkWidget* menu_item) {
+  NavigateToMenuItem(menu_item, CURRENT_TAB);
+}
+
+void BookmarkMenuController::OnMenuItemDragBegin(GtkWidget* menu_item,
+                                                 GdkDragContext* drag_context) {
+  // The parent menu item might be removed during the drag. Ref it so |button|
+  // won't get destroyed.
+  g_object_ref(menu_item->parent);
+
+  // Signal to any future OnButtonReleased calls that we're dragging instead of
+  // pressing.
+  ignore_button_release_ = true;
+
+  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(menu_item);
+  drag_icon_ = bookmark_utils::GetDragRepresentationForNode(
+      node, model_, GtkThemeProvider::GetFrom(profile_));
+  gint x, y;
+  gtk_widget_get_pointer(menu_item, &x, &y);
+  gtk_drag_set_icon_widget(drag_context, drag_icon_, x, y);
+
+  // Hide our node.
+  gtk_widget_hide(menu_item);
+}
+
+void BookmarkMenuController::OnMenuItemDragEnd(GtkWidget* menu_item,
+                                               GdkDragContext* drag_context) {
+  gtk_widget_show(menu_item);
+  g_object_unref(menu_item->parent);
+
+  gtk_widget_destroy(drag_icon_);
+  drag_icon_ = NULL;
+}
+
+void BookmarkMenuController::OnMenuItemDragGet(
+    GtkWidget* widget, GdkDragContext* context,
+    GtkSelectionData* selection_data,
+    guint target_type, guint time) {
+  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
+  bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
+                                           profile_);
+}
diff --git a/chrome/browser/ui/gtk/bookmark_menu_controller_gtk.h b/chrome/browser/ui/gtk/bookmark_menu_controller_gtk.h
new file mode 100644
index 0000000..e82f828
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_menu_controller_gtk.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BOOKMARK_MENU_CONTROLLER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_MENU_CONTROLLER_GTK_H_
+#pragma once
+
+#include <map>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
+#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "ui/base/gtk/gtk_integers.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "webkit/glue/window_open_disposition.h"
+
+class Browser;
+class Profile;
+class Profiler;
+class PageNavigator;
+class BookmarkModel;
+class BookmarkNode;
+class MenuGtk;
+
+typedef struct _GdkDragContext GdkDragContext;
+typedef struct _GdkEventButton GdkEventButton;
+typedef struct _GtkSelectionData GtkSelectionData;
+typedef struct _GtkWidget GtkWidget;
+
+class BookmarkMenuController : public BaseBookmarkModelObserver,
+                               public BookmarkContextMenuControllerDelegate {
+ public:
+  // Creates a BookmarkMenuController showing the children of |node| starting
+  // at index |start_child_index|.
+  BookmarkMenuController(Browser* browser,
+                         Profile* profile,
+                         PageNavigator* page_navigator,
+                         GtkWindow* window,
+                         const BookmarkNode* node,
+                         int start_child_index);
+  virtual ~BookmarkMenuController();
+
+  GtkWidget* widget() { return menu_; }
+
+  // Pops up the menu. |widget| must be a GtkChromeButton.
+  void Popup(GtkWidget* widget, gint button_type, guint32 timestamp);
+
+  // Overridden from BaseBookmarkModelObserver:
+  virtual void BookmarkModelChanged();
+  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
+                                         const BookmarkNode* node);
+
+  // Overridden from BookmarkContextMenuController::Delegate:
+  virtual void WillExecuteCommand();
+  virtual void CloseMenu();
+
+ private:
+  // Recursively change the bookmark hierarchy rooted in |parent| into a set of
+  // gtk menus rooted in |menu|.
+  void BuildMenu(const BookmarkNode* parent,
+                 int start_child_index,
+                 GtkWidget* menu);
+
+  // Calls the page navigator to navigate to the node represented by
+  // |menu_item|.
+  void NavigateToMenuItem(GtkWidget* menu_item,
+                          WindowOpenDisposition disposition);
+
+  // Button press and release events for a GtkMenu.
+  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean,
+                       OnMenuButtonPressedOrReleased, GdkEventButton*);
+
+  // Button release event for a GtkMenuItem.
+  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean, OnButtonReleased,
+                       GdkEventButton*);
+
+  // We connect this handler to the button-press-event signal for folder nodes.
+  // It suppresses the normal behavior (popping up the submenu) to allow these
+  // nodes to be draggable. The submenu is instead popped up on a
+  // button-release-event.
+  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean, OnFolderButtonPressed,
+                       GdkEventButton*);
+
+  // We have to stop drawing |triggering_widget_| as active when the menu
+  // closes.
+  CHROMEGTK_CALLBACK_0(BookmarkMenuController, void, OnMenuHidden)
+
+  // We respond to the activate signal because things other than mouse button
+  // events can trigger it.
+  CHROMEGTK_CALLBACK_0(BookmarkMenuController, void, OnMenuItemActivated);
+
+  // The individual GtkMenuItems in the BookmarkMenu are all drag sources.
+  CHROMEGTK_CALLBACK_1(BookmarkMenuController, void, OnMenuItemDragBegin,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_1(BookmarkMenuController, void, OnMenuItemDragEnd,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_4(BookmarkMenuController, void, OnMenuItemDragGet,
+                       GdkDragContext*, GtkSelectionData*, guint, guint);
+
+  Browser* browser_;
+  Profile* profile_;
+  PageNavigator* page_navigator_;
+
+  // Parent window of this menu.
+  GtkWindow* parent_window_;
+
+  // The bookmark model.
+  BookmarkModel* model_;
+
+  // The node we're showing the contents of.
+  const BookmarkNode* node_;
+
+  // Our bookmark menus. We don't use the MenuGtk class because we have to do
+  // all sorts of weird non-standard things with this menu, like:
+  // - The menu is a drag target
+  // - The menu items have context menus.
+  GtkWidget* menu_;
+
+  // The visual representation that follows the cursor during drags.
+  GtkWidget* drag_icon_;
+
+  // Whether we should ignore the next button release event (because we were
+  // dragging).
+  bool ignore_button_release_;
+
+  // The widget we are showing for (i.e. the bookmark bar folder button).
+  GtkWidget* triggering_widget_;
+
+  // Mapping from node to GtkMenuItem menu id. This only contains entries for
+  // nodes of type URL.
+  std::map<const BookmarkNode*, GtkWidget*> node_to_menu_widget_map_;
+
+  // The controller and view for the right click context menu.
+  scoped_ptr<BookmarkContextMenuController> context_menu_controller_;
+  scoped_ptr<MenuGtk> context_menu_;
+
+  ui::GtkSignalRegistrar signals_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkMenuController);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_MENU_CONTROLLER_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_tree_model.cc b/chrome/browser/ui/gtk/bookmark_tree_model.cc
new file mode 100644
index 0000000..8904976
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_tree_model.cc
@@ -0,0 +1,231 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_tree_model.h"
+
+#include <gtk/gtk.h>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+
+namespace {
+
+const char* kCellRendererTextKey = "__CELL_RENDERER_TEXT__";
+
+void AddSingleNodeToTreeStore(GtkTreeStore* store, const BookmarkNode* node,
+                              GtkTreeIter *iter, GtkTreeIter* parent) {
+  gtk_tree_store_append(store, iter, parent);
+  // It would be easy to show a different icon when the folder is open (as they
+  // do on Windows, for example), using pixbuf-expander-closed and
+  // pixbuf-expander-open. Unfortunately there is no GTK_STOCK_OPEN_DIRECTORY
+  // (and indeed, Nautilus does not render an expanded directory any
+  // differently).
+  gtk_tree_store_set(store, iter,
+      bookmark_utils::FOLDER_ICON, GtkThemeProvider::GetFolderIcon(true),
+      bookmark_utils::FOLDER_NAME,
+      UTF16ToUTF8(node->GetTitle()).c_str(),
+      bookmark_utils::ITEM_ID, node->id(),
+      // We don't want to use node->is_folder() because that would let the
+      // user edit "Bookmarks Bar" and "Other Bookmarks".
+      bookmark_utils::IS_EDITABLE, node->type() == BookmarkNode::FOLDER,
+      -1);
+}
+
+// Helper function for CommitTreeStoreDifferencesBetween() which recursively
+// merges changes back from a GtkTreeStore into a tree of BookmarkNodes. This
+// function only works on non-root nodes; our caller handles that special case.
+void RecursiveResolve(BookmarkModel* bb_model, const BookmarkNode* bb_node,
+                      GtkTreeModel* tree_model, GtkTreeIter* parent_iter,
+                      GtkTreePath* selected_path,
+                      const BookmarkNode** selected_node) {
+  GtkTreePath* current_path = gtk_tree_model_get_path(tree_model, parent_iter);
+  if (gtk_tree_path_compare(current_path, selected_path) == 0)
+    *selected_node = bb_node;
+  gtk_tree_path_free(current_path);
+
+  GtkTreeIter child_iter;
+  if (gtk_tree_model_iter_children(tree_model, &child_iter, parent_iter)) {
+    do {
+      int64 id = bookmark_utils::GetIdFromTreeIter(tree_model, &child_iter);
+      string16 title =
+          bookmark_utils::GetTitleFromTreeIter(tree_model, &child_iter);
+      const BookmarkNode* child_bb_node = NULL;
+      if (id == 0) {
+        child_bb_node = bb_model->AddGroup(bb_node, bb_node->GetChildCount(),
+                                           title);
+      } else {
+        // Existing node, reset the title (BBModel ignores changes if the title
+        // is the same).
+        for (int j = 0; j < bb_node->GetChildCount(); ++j) {
+          const BookmarkNode* node = bb_node->GetChild(j);
+          if (node->is_folder() && node->id() == id) {
+            child_bb_node = node;
+            break;
+          }
+        }
+        DCHECK(child_bb_node);
+        bb_model->SetTitle(child_bb_node, title);
+      }
+      RecursiveResolve(bb_model, child_bb_node,
+                       tree_model, &child_iter,
+                       selected_path, selected_node);
+    } while (gtk_tree_model_iter_next(tree_model, &child_iter));
+  }
+}
+
+// Update the folder name in the GtkTreeStore.
+void OnFolderNameEdited(GtkCellRendererText* render,
+    gchar* path, gchar* new_folder_name, GtkTreeStore* tree_store) {
+  GtkTreeIter folder_iter;
+  GtkTreePath* tree_path = gtk_tree_path_new_from_string(path);
+  gboolean rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store),
+                                        &folder_iter, tree_path);
+  DCHECK(rv);
+  gtk_tree_store_set(tree_store, &folder_iter,
+                     bookmark_utils::FOLDER_NAME, new_folder_name,
+                     -1);
+  gtk_tree_path_free(tree_path);
+}
+
+}  // namespace
+
+namespace bookmark_utils {
+
+GtkTreeStore* MakeFolderTreeStore() {
+  return gtk_tree_store_new(FOLDER_STORE_NUM_COLUMNS, GDK_TYPE_PIXBUF,
+                            G_TYPE_STRING, G_TYPE_INT64, G_TYPE_BOOLEAN);
+}
+
+void AddToTreeStore(BookmarkModel* model, int64 selected_id,
+                    GtkTreeStore* store, GtkTreeIter* selected_iter) {
+  const BookmarkNode* root_node = model->root_node();
+  for (int i = 0; i < root_node->GetChildCount(); ++i) {
+    AddToTreeStoreAt(root_node->GetChild(i), selected_id, store, selected_iter,
+                     NULL);
+  }
+}
+
+GtkWidget* MakeTreeViewForStore(GtkTreeStore* store) {
+  GtkTreeViewColumn* column = gtk_tree_view_column_new();
+  GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
+  gtk_tree_view_column_add_attribute(column, image_renderer,
+                                     "pixbuf", FOLDER_ICON);
+  GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
+  g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+  g_signal_connect(text_renderer, "edited", G_CALLBACK(OnFolderNameEdited),
+                   store);
+  gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
+  gtk_tree_view_column_set_attributes(column, text_renderer,
+                                      "text", FOLDER_NAME,
+                                      "editable", IS_EDITABLE,
+                                      NULL);
+
+  GtkWidget* tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+  // Let |tree_view| own the store.
+  g_object_unref(store);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+  g_object_set_data(G_OBJECT(tree_view), kCellRendererTextKey, text_renderer);
+  return tree_view;
+}
+
+GtkCellRenderer* GetCellRendererText(GtkTreeView* tree_view) {
+  return static_cast<GtkCellRenderer*>(
+      g_object_get_data(G_OBJECT(tree_view), kCellRendererTextKey));
+}
+
+void AddToTreeStoreAt(const BookmarkNode* node, int64 selected_id,
+                      GtkTreeStore* store, GtkTreeIter* selected_iter,
+                      GtkTreeIter* parent) {
+  if (!node->is_folder())
+    return;
+
+  GtkTreeIter iter;
+  AddSingleNodeToTreeStore(store, node, &iter, parent);
+  if (selected_iter && node->id() == selected_id) {
+     // Save the iterator. Since we're using a GtkTreeStore, we're
+     // guaranteed that the iterator will remain valid as long as the above
+     // appended item exists.
+     *selected_iter = iter;
+  }
+
+  for (int i = 0; i < node->GetChildCount(); ++i) {
+    AddToTreeStoreAt(node->GetChild(i), selected_id, store, selected_iter,
+                     &iter);
+  }
+}
+
+const BookmarkNode* CommitTreeStoreDifferencesBetween(
+    BookmarkModel* bb_model, GtkTreeStore* tree_store, GtkTreeIter* selected) {
+  const BookmarkNode* node_to_return = NULL;
+  GtkTreeModel* tree_model = GTK_TREE_MODEL(tree_store);
+
+  GtkTreePath* selected_path = gtk_tree_model_get_path(tree_model, selected);
+
+  GtkTreeIter tree_root;
+  if (!gtk_tree_model_get_iter_first(tree_model, &tree_root))
+    NOTREACHED() << "Impossible missing bookmarks case";
+
+  // The top level of this tree is weird and needs to be special cased. The
+  // BookmarksNode tree is rooted on a root node while the GtkTreeStore has a
+  // set of top level nodes that are the root BookmarksNode's children. These
+  // items in the top level are not editable and therefore don't need the extra
+  // complexity of trying to modify their title.
+  const BookmarkNode* root_node = bb_model->root_node();
+  do {
+    DCHECK(GetIdFromTreeIter(tree_model, &tree_root) != 0)
+        << "It should be impossible to add another toplevel node";
+
+    int64 id = GetIdFromTreeIter(tree_model, &tree_root);
+    const BookmarkNode* child_node = NULL;
+    for (int j = 0; j < root_node->GetChildCount(); ++j) {
+      const BookmarkNode* node = root_node->GetChild(j);
+      if (node->is_folder() && node->id() == id) {
+        child_node = node;
+        break;
+      }
+    }
+    DCHECK(child_node);
+
+    GtkTreeIter child_iter = tree_root;
+    RecursiveResolve(bb_model, child_node, tree_model, &child_iter,
+                     selected_path, &node_to_return);
+  } while (gtk_tree_model_iter_next(tree_model, &tree_root));
+
+  gtk_tree_path_free(selected_path);
+  return node_to_return;
+}
+
+int64 GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
+  GValue value = { 0, };
+  int64 ret_val = -1;
+  gtk_tree_model_get_value(model, iter, ITEM_ID, &value);
+  if (G_VALUE_HOLDS_INT64(&value))
+    ret_val = g_value_get_int64(&value);
+  else
+    NOTREACHED() << "Impossible type mismatch";
+
+  return ret_val;
+}
+
+string16 GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
+  GValue value = { 0, };
+  string16 ret_val;
+  gtk_tree_model_get_value(model, iter, FOLDER_NAME, &value);
+  if (G_VALUE_HOLDS_STRING(&value)) {
+    const gchar* utf8str = g_value_get_string(&value);
+    ret_val = UTF8ToUTF16(utf8str);
+    g_value_unset(&value);
+  } else {
+    NOTREACHED() << "Impossible type mismatch";
+  }
+
+  return ret_val;
+}
+
+}  // namespace bookmark_utils
diff --git a/chrome/browser/ui/gtk/bookmark_tree_model.h b/chrome/browser/ui/gtk/bookmark_tree_model.h
new file mode 100644
index 0000000..9b3a78b
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_tree_model.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BOOKMARK_TREE_MODEL_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_TREE_MODEL_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+class BookmarkModel;
+class BookmarkNode;
+
+typedef struct _GtkCellRenderer GtkCellRenderer;
+typedef struct _GtkTreeIter GtkTreeIter;
+typedef struct _GtkTreeModel GtkTreeModel;
+typedef struct _GtkTreeStore GtkTreeStore;
+typedef struct _GtkTreeView GtkTreeView;
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _GtkWidget GtkWidget;
+
+namespace bookmark_utils {
+
+enum FolderTreeStoreColumns {
+  FOLDER_ICON,
+  FOLDER_NAME,
+  ITEM_ID,
+  IS_EDITABLE,
+  FOLDER_STORE_NUM_COLUMNS
+};
+
+// Make a tree store that has two columns: name and id.
+GtkTreeStore* MakeFolderTreeStore();
+
+// Copies the folders in the model's root node into a GtkTreeStore. We
+// want the user to be able to modify the tree of folders, but to be able to
+// click Cancel and discard their modifications. |selected_id| is the
+// node->id() of the BookmarkNode that should selected on
+// node->screen. |selected_iter| is an out value that points to the
+// node->representation of the node associated with |selected_id| in |store|.
+// |recursive| indicates whether to recurse into sub-directories (if false,
+// the tree store will effectively be a list). |only_folders| indicates whether
+// to include bookmarks in the tree, or to only show folders.
+void AddToTreeStore(BookmarkModel* model, int64 selected_id,
+                    GtkTreeStore* store, GtkTreeIter* selected_iter);
+
+// As above, but inserts just the tree rooted at |node| as a child of |parent|.
+// If |parent| is NULL, add it at the top level.
+void AddToTreeStoreAt(const BookmarkNode* node, int64 selected_id,
+                      GtkTreeStore* store, GtkTreeIter* selected_iter,
+                      GtkTreeIter* parent);
+
+// Makes a tree view for the store. This will take ownership of |store| and the
+// returned widget has a floating reference.
+GtkWidget* MakeTreeViewForStore(GtkTreeStore* store);
+
+// A helper method for getting pointer back to the GtkCellRendererText used for
+// the folder names.
+GtkCellRenderer* GetCellRendererText(GtkTreeView* tree_view);
+
+// Commits changes to a GtkTreeStore built from BuildTreeStoreFrom() back
+// into the BookmarkModel it was generated from.  Returns the BookmarkNode that
+// represented by |selected|.
+const BookmarkNode* CommitTreeStoreDifferencesBetween(
+    BookmarkModel* model, GtkTreeStore* tree_store,
+    GtkTreeIter* selected);
+
+// Returns the id field of the row pointed to by |iter|.
+int64 GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter);
+
+// Returns the title field in utf8 of the row pointed to by |iter|.
+string16 GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter);
+
+}  // namespace bookmark_utils
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_TREE_MODEL_H_
diff --git a/chrome/browser/ui/gtk/bookmark_utils_gtk.cc b/chrome/browser/ui/gtk/bookmark_utils_gtk.cc
new file mode 100644
index 0000000..3b0b259
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_utils_gtk.cc
@@ -0,0 +1,440 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+
+#include "base/pickle.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_node_data.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Spacing between the favicon and the text.
+const int kBarButtonPadding = 4;
+
+// Used in gtk_selection_data_set(). (I assume from this parameter that gtk has
+// to some really exotic hardware...)
+const int kBitsInAByte = 8;
+
+// Maximum number of characters on a bookmark button.
+const size_t kMaxCharsOnAButton = 15;
+
+// Max size of each component of the button tooltips.
+const size_t kMaxTooltipTitleLength = 100;
+const size_t kMaxTooltipURLLength = 400;
+
+// Padding between the chrome button highlight border and the contents (favicon,
+// text).
+const int kButtonPaddingTop = 0;
+const int kButtonPaddingBottom = 0;
+const int kButtonPaddingLeft = 5;
+const int kButtonPaddingRight = 0;
+
+void* AsVoid(const BookmarkNode* node) {
+  return const_cast<BookmarkNode*>(node);
+}
+
+// Creates the widget hierarchy for a bookmark button.
+void PackButton(GdkPixbuf* pixbuf, const string16& title, bool ellipsize,
+                GtkThemeProvider* provider, GtkWidget* button) {
+  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
+  if (former_child)
+    gtk_container_remove(GTK_CONTAINER(button), former_child);
+
+  // We pack the button manually (rather than using gtk_button_set_*) so that
+  // we can have finer control over its label.
+  GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
+
+  GtkWidget* box = gtk_hbox_new(FALSE, kBarButtonPadding);
+  gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
+
+  std::string label_string = UTF16ToUTF8(title);
+  if (!label_string.empty()) {
+    GtkWidget* label = gtk_label_new(label_string.c_str());
+    // Until we switch to vector graphics, force the font size.
+    gtk_util::ForceFontSizePixels(label, 13.4);  // 13.4px == 10pt @ 96dpi
+
+    // Ellipsize long bookmark names.
+    if (ellipsize) {
+      gtk_label_set_max_width_chars(GTK_LABEL(label), kMaxCharsOnAButton);
+      gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
+    }
+
+    gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
+    bookmark_utils::SetButtonTextColors(label, provider);
+  }
+
+  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  // If we are not showing the label, don't set any padding, so that the icon
+  // will just be centered.
+  if (label_string.c_str()) {
+    gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+        kButtonPaddingTop, kButtonPaddingBottom,
+        kButtonPaddingLeft, kButtonPaddingRight);
+  }
+  gtk_container_add(GTK_CONTAINER(alignment), box);
+  gtk_container_add(GTK_CONTAINER(button), alignment);
+
+  gtk_widget_show_all(alignment);
+}
+
+const int kDragRepresentationWidth = 140;
+
+struct DragRepresentationData {
+ public:
+  GdkPixbuf* favicon;
+  string16 text;
+  SkColor text_color;
+
+  DragRepresentationData(GdkPixbuf* favicon,
+                         const string16& text,
+                         SkColor text_color)
+      : favicon(favicon),
+        text(text),
+        text_color(text_color) {
+    g_object_ref(favicon);
+  }
+
+  ~DragRepresentationData() {
+    g_object_unref(favicon);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DragRepresentationData);
+};
+
+gboolean OnDragIconExpose(GtkWidget* sender,
+                          GdkEventExpose* event,
+                          DragRepresentationData* data) {
+  // Clear the background.
+  cairo_t* cr = gdk_cairo_create(event->window);
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+  cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+  cairo_paint(cr);
+
+  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+  gdk_cairo_set_source_pixbuf(cr, data->favicon, 0, 0);
+  cairo_paint(cr);
+  cairo_destroy(cr);
+
+  // Paint the title text.
+  gfx::CanvasSkiaPaint canvas(event, false);
+  int text_x = gdk_pixbuf_get_width(data->favicon) + kBarButtonPadding;
+  int text_width = sender->allocation.width - text_x;
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
+  canvas.DrawStringInt(data->text, base_font, data->text_color,
+                       text_x, 0, text_width, sender->allocation.height);
+
+  return TRUE;
+}
+
+void OnDragIconDestroy(GtkWidget* drag_icon,
+                       DragRepresentationData* data) {
+  g_object_unref(drag_icon);
+  delete data;
+}
+
+}  // namespace
+
+namespace bookmark_utils {
+
+const char kBookmarkNode[] = "bookmark-node";
+
+GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model,
+                            bool native) {
+  GdkPixbuf* pixbuf;
+
+  if (node->is_url()) {
+    if (model->GetFavIcon(node).width() != 0) {
+      pixbuf = gfx::GdkPixbufFromSkBitmap(&model->GetFavIcon(node));
+    } else {
+      pixbuf = GtkThemeProvider::GetDefaultFavicon(native);
+      g_object_ref(pixbuf);
+    }
+  } else {
+    pixbuf = GtkThemeProvider::GetFolderIcon(native);
+    g_object_ref(pixbuf);
+  }
+
+  return pixbuf;
+}
+
+GtkWidget* GetDragRepresentation(GdkPixbuf* pixbuf,
+                                 const string16& title,
+                                 GtkThemeProvider* provider) {
+  GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
+
+  if (gtk_util::IsScreenComposited() &&
+      gtk_util::AddWindowAlphaChannel(window)) {
+    DragRepresentationData* data = new DragRepresentationData(
+        pixbuf, title,
+        provider->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT));
+    g_signal_connect(window, "expose-event", G_CALLBACK(OnDragIconExpose),
+                     data);
+    g_object_ref(window);
+    g_signal_connect(window, "destroy", G_CALLBACK(OnDragIconDestroy), data);
+
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
+    gtk_widget_set_size_request(window, kDragRepresentationWidth,
+                                base_font.GetHeight());
+  } else {
+    if (!provider->UseGtkTheme()) {
+      GdkColor color = provider->GetGdkColor(
+          BrowserThemeProvider::COLOR_TOOLBAR);
+      gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
+    }
+    gtk_widget_realize(window);
+
+    GtkWidget* frame = gtk_frame_new(NULL);
+    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+    gtk_container_add(GTK_CONTAINER(window), frame);
+
+    GtkWidget* floating_button = provider->BuildChromeButton();
+    PackButton(pixbuf, title, true, provider, floating_button);
+    gtk_container_add(GTK_CONTAINER(frame), floating_button);
+    gtk_widget_show_all(frame);
+  }
+
+  return window;
+}
+
+GtkWidget* GetDragRepresentationForNode(const BookmarkNode* node,
+                                        BookmarkModel* model,
+                                        GtkThemeProvider* provider) {
+  GdkPixbuf* pixbuf = GetPixbufForNode(node, model, provider->UseGtkTheme());
+  GtkWidget* widget = GetDragRepresentation(pixbuf, node->GetTitle(), provider);
+  g_object_unref(pixbuf);
+  return widget;
+}
+
+void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model,
+                            GtkWidget* button, GtkThemeProvider* provider) {
+  GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model,
+                                                       provider->UseGtkTheme());
+  PackButton(pixbuf, node->GetTitle(), node != model->other_node(), provider,
+             button);
+  g_object_unref(pixbuf);
+
+  std::string tooltip = BuildTooltipFor(node);
+  if (!tooltip.empty())
+    gtk_widget_set_tooltip_markup(button, tooltip.c_str());
+
+  g_object_set_data(G_OBJECT(button), bookmark_utils::kBookmarkNode,
+                    AsVoid(node));
+}
+
+std::string BuildTooltipFor(const BookmarkNode* node) {
+  const std::string& url = node->GetURL().possibly_invalid_spec();
+  const std::string& title = UTF16ToUTF8(node->GetTitle());
+
+  std::string truncated_url = UTF16ToUTF8(l10n_util::TruncateString(
+      UTF8ToUTF16(url), kMaxTooltipURLLength));
+  gchar* escaped_url_cstr = g_markup_escape_text(truncated_url.c_str(),
+                                                 truncated_url.size());
+  std::string escaped_url(escaped_url_cstr);
+  g_free(escaped_url_cstr);
+
+  std::string tooltip;
+  if (url == title || title.empty()) {
+    return escaped_url;
+  } else {
+    std::string truncated_title = UTF16ToUTF8(l10n_util::TruncateString(
+        node->GetTitle(), kMaxTooltipTitleLength));
+    gchar* escaped_title_cstr = g_markup_escape_text(truncated_title.c_str(),
+                                                     truncated_title.size());
+    std::string escaped_title(escaped_title_cstr);
+    g_free(escaped_title_cstr);
+
+    if (!escaped_url.empty())
+      return std::string("<b>") + escaped_title + "</b>\n" + escaped_url;
+    else
+      return std::string("<b>") + escaped_title + "</b>";
+  }
+}
+
+const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget) {
+  return reinterpret_cast<const BookmarkNode*>(
+      g_object_get_data(G_OBJECT(widget), bookmark_utils::kBookmarkNode));
+}
+
+void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) {
+  if (provider->UseGtkTheme()) {
+    gtk_util::SetLabelColor(label, NULL);
+  } else {
+    GdkColor color = provider->GetGdkColor(
+        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+    gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color);
+    gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, &color);
+
+    // Because the prelight state is a white image that doesn't change by the
+    // theme, force the text color to black when it would be used.
+    gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &gtk_util::kGdkBlack);
+    gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &gtk_util::kGdkBlack);
+  }
+}
+
+// DnD-related -----------------------------------------------------------------
+
+int GetCodeMask(bool folder) {
+  int rv = ui::CHROME_BOOKMARK_ITEM;
+  if (!folder) {
+    rv |= ui::TEXT_URI_LIST |
+          ui::TEXT_PLAIN |
+          ui::NETSCAPE_URL;
+  }
+  return rv;
+}
+
+void WriteBookmarkToSelection(const BookmarkNode* node,
+                              GtkSelectionData* selection_data,
+                              guint target_type,
+                              Profile* profile) {
+  DCHECK(node);
+  std::vector<const BookmarkNode*> nodes;
+  nodes.push_back(node);
+  WriteBookmarksToSelection(nodes, selection_data, target_type, profile);
+}
+
+void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
+                               GtkSelectionData* selection_data,
+                               guint target_type,
+                               Profile* profile) {
+  switch (target_type) {
+    case ui::CHROME_BOOKMARK_ITEM: {
+      BookmarkNodeData data(nodes);
+      Pickle pickle;
+      data.WriteToPickle(profile, &pickle);
+
+      gtk_selection_data_set(selection_data, selection_data->target,
+                             kBitsInAByte,
+                             static_cast<const guchar*>(pickle.data()),
+                             pickle.size());
+      break;
+    }
+    case ui::NETSCAPE_URL: {
+      // _NETSCAPE_URL format is URL + \n + title.
+      std::string utf8_text = nodes[0]->GetURL().spec() + "\n" +
+          UTF16ToUTF8(nodes[0]->GetTitle());
+      gtk_selection_data_set(selection_data,
+                             selection_data->target,
+                             kBitsInAByte,
+                             reinterpret_cast<const guchar*>(utf8_text.c_str()),
+                             utf8_text.length());
+      break;
+    }
+    case ui::TEXT_URI_LIST: {
+      gchar** uris = reinterpret_cast<gchar**>(malloc(sizeof(gchar*) *
+                                               (nodes.size() + 1)));
+      for (size_t i = 0; i < nodes.size(); ++i) {
+        // If the node is a folder, this will be empty. TODO(estade): figure out
+        // if there are any ramifications to passing an empty URI. After a
+        // little testing, it seems fine.
+        const GURL& url = nodes[i]->GetURL();
+        // This const cast should be safe as gtk_selection_data_set_uris()
+        // makes copies.
+        uris[i] = const_cast<gchar*>(url.spec().c_str());
+      }
+      uris[nodes.size()] = NULL;
+
+      gtk_selection_data_set_uris(selection_data, uris);
+      free(uris);
+      break;
+    }
+    case ui::TEXT_PLAIN: {
+      gtk_selection_data_set_text(selection_data,
+                                  nodes[0]->GetURL().spec().c_str(), -1);
+      break;
+    }
+    default: {
+      DLOG(ERROR) << "Unsupported drag get type!";
+    }
+  }
+}
+
+std::vector<const BookmarkNode*> GetNodesFromSelection(
+    GdkDragContext* context,
+    GtkSelectionData* selection_data,
+    guint target_type,
+    Profile* profile,
+    gboolean* delete_selection_data,
+    gboolean* dnd_success) {
+  if (delete_selection_data)
+    *delete_selection_data = FALSE;
+  if (dnd_success)
+    *dnd_success = FALSE;
+
+  if (selection_data && selection_data->length > 0) {
+    if (context && delete_selection_data && context->action == GDK_ACTION_MOVE)
+      *delete_selection_data = TRUE;
+
+    switch (target_type) {
+      case ui::CHROME_BOOKMARK_ITEM: {
+        if (dnd_success)
+          *dnd_success = TRUE;
+        Pickle pickle(reinterpret_cast<char*>(selection_data->data),
+                      selection_data->length);
+        BookmarkNodeData drag_data;
+        drag_data.ReadFromPickle(&pickle);
+        return drag_data.GetNodes(profile);
+      }
+      default: {
+        DLOG(ERROR) << "Unsupported drag received type: " << target_type;
+      }
+    }
+  }
+
+  return std::vector<const BookmarkNode*>();
+}
+
+bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data,
+    BookmarkModel* model, const BookmarkNode* parent, int idx) {
+  GURL url;
+  string16 title;
+  if (!ui::ExtractNamedURL(selection_data, &url, &title))
+    return false;
+
+  model->AddURL(parent, idx, title, url);
+  return true;
+}
+
+bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data,
+    BookmarkModel* model, const BookmarkNode* parent, int idx) {
+  std::vector<GURL> urls;
+  ui::ExtractURIList(selection_data, &urls);
+  for (size_t i = 0; i < urls.size(); ++i) {
+    string16 title = GetNameForURL(urls[i]);
+    model->AddURL(parent, idx++, title, urls[i]);
+  }
+  return true;
+}
+
+bool CreateNewBookmarkFromNetscapeURL(GtkSelectionData* selection_data,
+    BookmarkModel* model, const BookmarkNode* parent, int idx) {
+  GURL url;
+  string16 title;
+  if (!ui::ExtractNetscapeURL(selection_data, &url, &title))
+    return false;
+
+  model->AddURL(parent, idx, title, url);
+  return true;
+}
+
+}  // namespace bookmark_utils
diff --git a/chrome/browser/ui/gtk/bookmark_utils_gtk.h b/chrome/browser/ui/gtk/bookmark_utils_gtk.h
new file mode 100644
index 0000000..9654d9d
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_utils_gtk.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BOOKMARK_UTILS_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BOOKMARK_UTILS_GTK_H_
+#pragma once
+
+#include <vector>
+#include <string>
+
+#include "base/string16.h"
+#include "ui/base/gtk/gtk_integers.h"
+
+class BookmarkModel;
+class BookmarkNode;
+class GtkThemeProvider;
+class Profile;
+
+typedef struct _GdkDragContext GdkDragContext;
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _GtkSelectionData GtkSelectionData;
+typedef struct _GtkWidget GtkWidget;
+
+namespace bookmark_utils {
+
+extern const char kBookmarkNode[];
+
+// Get the image that is used to represent the node. This function adds a ref
+// to the returned pixbuf, so it requires a matching call to g_object_unref().
+GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model,
+                            bool native);
+
+// Returns a GtkWindow with a visual hierarchy for passing to
+// gtk_drag_set_icon_widget().
+GtkWidget* GetDragRepresentation(GdkPixbuf* pixbuf,
+                                 const string16& title,
+                                 GtkThemeProvider* provider);
+GtkWidget* GetDragRepresentationForNode(const BookmarkNode* node,
+                                        BookmarkModel* model,
+                                        GtkThemeProvider* provider);
+
+// Helper function that sets visual properties of GtkButton |button| to the
+// contents of |node|.
+void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model,
+                            GtkWidget* button, GtkThemeProvider* provider);
+
+// Returns the tooltip.
+std::string BuildTooltipFor(const BookmarkNode* node);
+
+// Returns the "bookmark-node" property of |widget| casted to the correct type.
+const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget);
+
+// Set the colors on |label| as per the theme.
+void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider);
+
+// Drag and drop. --------------------------------------------------------------
+
+// Get the DnD target mask for a bookmark drag. This will vary based on whether
+// the node in question is a folder.
+int GetCodeMask(bool folder);
+
+// Pickle a node into a GtkSelection.
+void WriteBookmarkToSelection(const BookmarkNode* node,
+                              GtkSelectionData* selection_data,
+                              guint target_type,
+                              Profile* profile);
+
+// Pickle a vector of nodes into a GtkSelection.
+void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
+                               GtkSelectionData* selection_data,
+                               guint target_type,
+                               Profile* profile);
+
+// Un-pickle node(s) from a GtkSelection.
+// The last two arguments are out parameters.
+std::vector<const BookmarkNode*> GetNodesFromSelection(
+    GdkDragContext* context,
+    GtkSelectionData* selection_data,
+    guint target_type,
+    Profile* profile,
+    gboolean* delete_selection_data,
+    gboolean* dnd_success);
+
+// Unpickle a new bookmark of the CHROME_NAMED_URL drag type, and put it in
+// the appropriate location in the model.
+bool CreateNewBookmarkFromNamedUrl(
+    GtkSelectionData* selection_data,
+    BookmarkModel* model,
+    const BookmarkNode* parent,
+    int idx);
+
+// Add the URIs in |selection_data| into the model at the given position. They
+// will be added whether or not the URL is valid.
+bool CreateNewBookmarksFromURIList(
+    GtkSelectionData* selection_data,
+    BookmarkModel* model,
+    const BookmarkNode* parent,
+    int idx);
+
+// Add the "url\ntitle" combination into the model at the given position.
+bool CreateNewBookmarkFromNetscapeURL(
+    GtkSelectionData* selection_data,
+    BookmarkModel* model,
+    const BookmarkNode* parent,
+    int idx);
+
+}  // namespace bookmark_utils
+
+#endif  // CHROME_BROWSER_UI_GTK_BOOKMARK_UTILS_GTK_H_
diff --git a/chrome/browser/ui/gtk/bookmark_utils_gtk_unittest.cc b/chrome/browser/ui/gtk/bookmark_utils_gtk_unittest.cc
new file mode 100644
index 0000000..ffef87c
--- /dev/null
+++ b/chrome/browser/ui/gtk/bookmark_utils_gtk_unittest.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+
+TEST(BookmarkUtilsGtkTest, GetNodesFromSelectionInvalid) {
+  std::vector<const BookmarkNode*> nodes;
+  nodes = bookmark_utils::GetNodesFromSelection(NULL, NULL, 0, NULL, NULL,
+                                                NULL);
+  EXPECT_EQ(0u, nodes.size());
+
+  GtkSelectionData data;
+  data.data = NULL;
+  data.length = 0;
+  nodes = bookmark_utils::GetNodesFromSelection(NULL, &data, 0, NULL, NULL,
+                                                NULL);
+  EXPECT_EQ(0u, nodes.size());
+
+  nodes = bookmark_utils::GetNodesFromSelection(NULL, NULL,
+      ui::CHROME_BOOKMARK_ITEM, NULL, NULL, NULL);
+  EXPECT_EQ(0u, nodes.size());
+
+  data.data = NULL;
+  data.length = 0;
+  nodes = bookmark_utils::GetNodesFromSelection(NULL, &data,
+      ui::CHROME_BOOKMARK_ITEM, NULL, NULL, NULL);
+  EXPECT_EQ(0u, nodes.size());
+
+  guchar test_data[] = "";
+  data.data = test_data;
+  data.length = 0;
+  nodes = bookmark_utils::GetNodesFromSelection(NULL, &data,
+      ui::CHROME_BOOKMARK_ITEM, NULL, NULL, NULL);
+  EXPECT_EQ(0u, nodes.size());
+}
diff --git a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
new file mode 100644
index 0000000..8c4455f
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
@@ -0,0 +1,961 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/i18n/rtl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extension_context_menu_model.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/extension_popup_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/hover_controller_gtk.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "grit/app_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// The width of the browser action buttons.
+const int kButtonWidth = 27;
+
+// The padding between browser action buttons.
+const int kButtonPadding = 4;
+
+// The padding to the right of the browser action buttons (between the buttons
+// and chevron if they are both showing).
+const int kButtonChevronPadding = 2;
+
+// The padding to the left, top and bottom of the browser actions toolbar
+// separator.
+const int kSeparatorPadding = 2;
+
+// Width of the invisible gripper for resizing the toolbar.
+const int kResizeGripperWidth = 4;
+
+const char* kDragTarget = "application/x-chrome-browseraction";
+
+GtkTargetEntry GetDragTargetEntry() {
+  static std::string drag_target_string(kDragTarget);
+  GtkTargetEntry drag_target;
+  drag_target.target = const_cast<char*>(drag_target_string.c_str());
+  drag_target.flags = GTK_TARGET_SAME_APP;
+  drag_target.info = 0;
+  return drag_target;
+}
+
+// The minimum width in pixels of the button hbox if |icon_count| icons are
+// showing.
+gint WidthForIconCount(gint icon_count) {
+  return std::max((kButtonWidth + kButtonPadding) * icon_count - kButtonPadding,
+                  0);
+}
+
+}  // namespace
+
+using ui::SimpleMenuModel;
+
+class BrowserActionButton : public NotificationObserver,
+                            public ImageLoadingTracker::Observer,
+                            public ExtensionContextMenuModel::PopupDelegate,
+                            public MenuGtk::Delegate {
+ public:
+  BrowserActionButton(BrowserActionsToolbarGtk* toolbar,
+                      const Extension* extension,
+                      GtkThemeProvider* theme_provider)
+      : toolbar_(toolbar),
+        extension_(extension),
+        image_(NULL),
+        tracker_(this),
+        tab_specific_icon_(NULL),
+        default_icon_(NULL) {
+    button_.reset(new CustomDrawButton(
+        theme_provider,
+        IDR_BROWSER_ACTION,
+        IDR_BROWSER_ACTION_P,
+        IDR_BROWSER_ACTION_H,
+        0,
+        NULL));
+    alignment_.Own(gtk_alignment_new(0, 0, 1, 1));
+    gtk_container_add(GTK_CONTAINER(alignment_.get()), button());
+    gtk_widget_show(button());
+
+    DCHECK(extension_->browser_action());
+
+    UpdateState();
+
+    // The Browser Action API does not allow the default icon path to be
+    // changed at runtime, so we can load this now and cache it.
+    std::string path = extension_->browser_action()->default_icon_path();
+    if (!path.empty()) {
+      tracker_.LoadImage(extension_, extension_->GetResource(path),
+                         gfx::Size(Extension::kBrowserActionIconMaxSize,
+                                   Extension::kBrowserActionIconMaxSize),
+                         ImageLoadingTracker::DONT_CACHE);
+    }
+
+    signals_.Connect(button(), "button-press-event",
+                     G_CALLBACK(OnButtonPress), this);
+    signals_.Connect(button(), "clicked",
+                     G_CALLBACK(OnClicked), this);
+    signals_.Connect(button(), "drag-begin",
+                     G_CALLBACK(&OnDragBegin), this);
+    signals_.ConnectAfter(widget(), "expose-event",
+                          G_CALLBACK(OnExposeEvent), this);
+
+    registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
+                   Source<ExtensionAction>(extension->browser_action()));
+  }
+
+  ~BrowserActionButton() {
+    if (tab_specific_icon_)
+      g_object_unref(tab_specific_icon_);
+
+    if (default_icon_)
+      g_object_unref(default_icon_);
+
+    alignment_.Destroy();
+  }
+
+  GtkWidget* button() { return button_->widget(); }
+
+  GtkWidget* widget() { return alignment_.get(); }
+
+  const Extension* extension() { return extension_; }
+
+  // NotificationObserver implementation.
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details) {
+    if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED)
+      UpdateState();
+    else
+      NOTREACHED();
+  }
+
+  // ImageLoadingTracker::Observer implementation.
+  void OnImageLoaded(SkBitmap* image, ExtensionResource resource, int index) {
+    if (image) {
+      default_skbitmap_ = *image;
+      default_icon_ = gfx::GdkPixbufFromSkBitmap(image);
+    }
+    UpdateState();
+  }
+
+  // Updates the button based on the latest state from the associated
+  // browser action.
+  void UpdateState() {
+    int tab_id = toolbar_->GetCurrentTabId();
+    if (tab_id < 0)
+      return;
+
+    std::string tooltip = extension_->browser_action()->GetTitle(tab_id);
+    if (tooltip.empty())
+      gtk_widget_set_has_tooltip(button(), FALSE);
+    else
+      gtk_widget_set_tooltip_text(button(), tooltip.c_str());
+
+    SkBitmap image = extension_->browser_action()->GetIcon(tab_id);
+    if (!image.isNull()) {
+      GdkPixbuf* previous_gdk_icon = tab_specific_icon_;
+      tab_specific_icon_ = gfx::GdkPixbufFromSkBitmap(&image);
+      SetImage(tab_specific_icon_);
+      if (previous_gdk_icon)
+        g_object_unref(previous_gdk_icon);
+    } else if (default_icon_) {
+      SetImage(default_icon_);
+    }
+    gtk_widget_queue_draw(button());
+  }
+
+  SkBitmap GetIcon() {
+    const SkBitmap& image = extension_->browser_action()->GetIcon(
+        toolbar_->GetCurrentTabId());
+    if (!image.isNull()) {
+      return image;
+    } else {
+      return default_skbitmap_;
+    }
+  }
+
+  MenuGtk* GetContextMenu() {
+    if (!extension_->ShowConfigureContextMenus())
+      return NULL;
+
+    context_menu_model_ =
+        new ExtensionContextMenuModel(extension_, toolbar_->browser(), this);
+    context_menu_.reset(
+        new MenuGtk(this, context_menu_model_.get()));
+    return context_menu_.get();
+  }
+
+ private:
+  // MenuGtk::Delegate implementation.
+  virtual void StoppedShowing() {
+    button_->UnsetPaintOverride();
+
+    // If the context menu was showing for the overflow menu, re-assert the
+    // grab that was shadowed.
+    if (toolbar_->overflow_menu_.get())
+      gtk_util::GrabAllInput(toolbar_->overflow_menu_->widget());
+  }
+
+  virtual void CommandWillBeExecuted() {
+    // If the context menu was showing for the overflow menu, and a command
+    // is executed, then stop showing the overflow menu.
+    if (toolbar_->overflow_menu_.get())
+      toolbar_->overflow_menu_->Cancel();
+  }
+
+  // Returns true to prevent further processing of the event that caused us to
+  // show the popup, or false to continue processing.
+  bool ShowPopup(bool devtools) {
+    ExtensionAction* browser_action = extension_->browser_action();
+
+    int tab_id = toolbar_->GetCurrentTabId();
+    if (tab_id < 0) {
+      NOTREACHED() << "No current tab.";
+      return true;
+    }
+
+    if (browser_action->HasPopup(tab_id)) {
+      ExtensionPopupGtk::Show(
+          browser_action->GetPopupUrl(tab_id), toolbar_->browser(),
+          widget(), devtools);
+      return true;
+    }
+
+    return false;
+  }
+
+  // ExtensionContextMenuModel::PopupDelegate implementation.
+  virtual void InspectPopup(ExtensionAction* action) {
+    ShowPopup(true);
+  }
+
+  void SetImage(GdkPixbuf* image) {
+    if (!image_) {
+      image_ = gtk_image_new_from_pixbuf(image);
+      gtk_button_set_image(GTK_BUTTON(button()), image_);
+    } else {
+      gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image);
+    }
+  }
+
+  static gboolean OnButtonPress(GtkWidget* widget,
+                                GdkEventButton* event,
+                                BrowserActionButton* action) {
+    if (event->button != 3)
+      return FALSE;
+
+    MenuGtk* menu = action->GetContextMenu();
+    if (!menu)
+      return FALSE;
+
+    action->button_->SetPaintOverride(GTK_STATE_ACTIVE);
+    menu->PopupForWidget(widget, event->button, event->time);
+
+    return TRUE;
+  }
+
+  static void OnClicked(GtkWidget* widget, BrowserActionButton* action) {
+    if (action->ShowPopup(false))
+      return;
+
+    ExtensionService* service =
+        action->toolbar_->browser()->profile()->GetExtensionService();
+    service->browser_event_router()->BrowserActionExecuted(
+        action->toolbar_->browser()->profile(), action->extension_->id(),
+        action->toolbar_->browser());
+  }
+
+  static gboolean OnExposeEvent(GtkWidget* widget,
+                                GdkEventExpose* event,
+                                BrowserActionButton* button) {
+    int tab_id = button->toolbar_->GetCurrentTabId();
+    if (tab_id < 0)
+      return FALSE;
+
+    ExtensionAction* action = button->extension_->browser_action();
+    if (action->GetBadgeText(tab_id).empty())
+      return FALSE;
+
+    gfx::CanvasSkiaPaint canvas(event, false);
+    gfx::Rect bounding_rect(widget->allocation);
+    action->PaintBadge(&canvas, bounding_rect, tab_id);
+    return FALSE;
+  }
+
+  static void OnDragBegin(GtkWidget* widget,
+                          GdkDragContext* drag_context,
+                          BrowserActionButton* button) {
+    // Simply pass along the notification to the toolbar. The point of this
+    // function is to tell the toolbar which BrowserActionButton initiated the
+    // drag.
+    button->toolbar_->DragStarted(button, drag_context);
+  }
+
+  // The toolbar containing this button.
+  BrowserActionsToolbarGtk* toolbar_;
+
+  // The extension that contains this browser action.
+  const Extension* extension_;
+
+  // The button for this browser action.
+  scoped_ptr<CustomDrawButton> button_;
+
+  // The top level widget (parent of |button_|).
+  OwnedWidgetGtk alignment_;
+
+  // The one image subwidget in |button_|. We keep this out so we don't alter
+  // the widget hierarchy while changing the button image because changing the
+  // GTK widget hierarchy invalidates all tooltips and several popular
+  // extensions change browser action icon in a loop.
+  GtkWidget* image_;
+
+  // Loads the button's icons for us on the file thread.
+  ImageLoadingTracker tracker_;
+
+  // If we are displaying a tab-specific icon, it will be here.
+  GdkPixbuf* tab_specific_icon_;
+
+  // If the browser action has a default icon, it will be here.
+  GdkPixbuf* default_icon_;
+
+  // Same as |default_icon_|, but stored as SkBitmap.
+  SkBitmap default_skbitmap_;
+
+  ui::GtkSignalRegistrar signals_;
+  NotificationRegistrar registrar_;
+
+  // The context menu view and model for this extension action.
+  scoped_ptr<MenuGtk> context_menu_;
+  scoped_refptr<ExtensionContextMenuModel> context_menu_model_;
+
+  friend class BrowserActionsToolbarGtk;
+};
+
+// BrowserActionsToolbarGtk ----------------------------------------------------
+
+BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser)
+    : browser_(browser),
+      profile_(browser->profile()),
+      theme_provider_(GtkThemeProvider::GetFrom(browser->profile())),
+      model_(NULL),
+      hbox_(gtk_hbox_new(FALSE, 0)),
+      button_hbox_(gtk_chrome_shrinkable_hbox_new(TRUE, FALSE, kButtonPadding)),
+      drag_button_(NULL),
+      drop_index_(-1),
+      resize_animation_(this),
+      desired_width_(0),
+      start_width_(0),
+      method_factory_(this) {
+  ExtensionService* extension_service = profile_->GetExtensionService();
+  // The |extension_service| can be NULL in Incognito.
+  if (!extension_service)
+    return;
+
+  overflow_button_.reset(new CustomDrawButton(
+      theme_provider_,
+      IDR_BROWSER_ACTIONS_OVERFLOW,
+      IDR_BROWSER_ACTIONS_OVERFLOW_P,
+      IDR_BROWSER_ACTIONS_OVERFLOW_H,
+      0,
+      gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)));
+
+  GtkWidget* gripper = gtk_button_new();
+  gtk_widget_set_size_request(gripper, kResizeGripperWidth, -1);
+  GTK_WIDGET_UNSET_FLAGS(gripper, GTK_CAN_FOCUS);
+  gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK);
+  signals_.Connect(gripper, "motion-notify-event",
+                   G_CALLBACK(OnGripperMotionNotifyThunk), this);
+  signals_.Connect(gripper, "expose-event",
+                   G_CALLBACK(OnGripperExposeThunk), this);
+  signals_.Connect(gripper, "enter-notify-event",
+                   G_CALLBACK(OnGripperEnterNotifyThunk), this);
+  signals_.Connect(gripper, "leave-notify-event",
+                   G_CALLBACK(OnGripperLeaveNotifyThunk), this);
+  signals_.Connect(gripper, "button-release-event",
+                   G_CALLBACK(OnGripperButtonReleaseThunk), this);
+  signals_.Connect(gripper, "button-press-event",
+                   G_CALLBACK(OnGripperButtonPressThunk), this);
+  signals_.Connect(chevron(), "button-press-event",
+                   G_CALLBACK(OnOverflowButtonPressThunk), this);
+
+  // |overflow_alignment| adds padding to the right of the browser action
+  // buttons, but only appears when the overflow menu is showing.
+  overflow_alignment_ = gtk_alignment_new(0, 0, 1, 1);
+  gtk_container_add(GTK_CONTAINER(overflow_alignment_), chevron());
+
+  // |overflow_area_| holds the overflow chevron and the separator, which
+  // is only shown in GTK+ theme mode.
+  overflow_area_ = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(overflow_area_), overflow_alignment_,
+                     FALSE, FALSE, 0);
+
+  separator_ = gtk_vseparator_new();
+  gtk_box_pack_start(GTK_BOX(overflow_area_), separator_,
+                     FALSE, FALSE, 0);
+  gtk_widget_set_no_show_all(separator_, TRUE);
+
+  gtk_widget_show_all(overflow_area_);
+  gtk_widget_set_no_show_all(overflow_area_, TRUE);
+
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_area_, FALSE, FALSE, 0);
+
+  model_ = extension_service->toolbar_model();
+  model_->AddObserver(this);
+  SetupDrags();
+
+  if (model_->extensions_initialized()) {
+    CreateAllButtons();
+    SetContainerWidth();
+  }
+
+  // We want to connect to "set-focus" on the toplevel window; we have to wait
+  // until we are added to a toplevel window to do so.
+  signals_.Connect(widget(), "hierarchy-changed",
+                   G_CALLBACK(OnHierarchyChangedThunk), this);
+
+  ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR);
+
+  registrar_.Add(this,
+                 NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_->InitThemesFor(this);
+}
+
+BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() {
+  if (model_)
+    model_->RemoveObserver(this);
+  button_hbox_.Destroy();
+  hbox_.Destroy();
+}
+
+int BrowserActionsToolbarGtk::GetCurrentTabId() {
+  TabContents* selected_tab = browser_->GetSelectedTabContents();
+  if (!selected_tab)
+    return -1;
+
+  return selected_tab->controller().session_id().id();
+}
+
+void BrowserActionsToolbarGtk::Update() {
+  for (ExtensionButtonMap::iterator iter = extension_button_map_.begin();
+       iter != extension_button_map_.end(); ++iter) {
+    iter->second->UpdateState();
+  }
+}
+
+void BrowserActionsToolbarGtk::Observe(NotificationType type,
+                                       const NotificationSource& source,
+                                       const NotificationDetails& details) {
+  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
+  if (theme_provider_->UseGtkTheme())
+    gtk_widget_show(separator_);
+  else
+    gtk_widget_hide(separator_);
+}
+
+void BrowserActionsToolbarGtk::SetupDrags() {
+  GtkTargetEntry drag_target = GetDragTargetEntry();
+  gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1,
+                    GDK_ACTION_MOVE);
+
+  signals_.Connect(button_hbox_.get(), "drag-motion",
+                   G_CALLBACK(OnDragMotionThunk), this);
+}
+
+void BrowserActionsToolbarGtk::CreateAllButtons() {
+  extension_button_map_.clear();
+
+  int i = 0;
+  for (ExtensionList::iterator iter = model_->begin();
+       iter != model_->end(); ++iter) {
+    CreateButtonForExtension(*iter, i++);
+  }
+}
+
+void BrowserActionsToolbarGtk::SetContainerWidth() {
+  int showing_actions = model_->GetVisibleIconCount();
+  if (showing_actions >= 0)
+    SetButtonHBoxWidth(WidthForIconCount(showing_actions));
+}
+
+void BrowserActionsToolbarGtk::CreateButtonForExtension(
+    const Extension* extension, int index) {
+  if (!ShouldDisplayBrowserAction(extension))
+    return;
+
+  if (profile_->IsOffTheRecord())
+    index = model_->OriginalIndexToIncognito(index);
+
+  RemoveButtonForExtension(extension);
+  linked_ptr<BrowserActionButton> button(
+      new BrowserActionButton(this, extension, theme_provider_));
+  gtk_chrome_shrinkable_hbox_pack_start(
+      GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0);
+  gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index);
+  extension_button_map_[extension->id()] = button;
+
+  GtkTargetEntry drag_target = GetDragTargetEntry();
+  gtk_drag_source_set(button->button(), GDK_BUTTON1_MASK, &drag_target, 1,
+                      GDK_ACTION_MOVE);
+  // We ignore whether the drag was a "success" or "failure" in Gtk's opinion.
+  signals_.Connect(button->button(), "drag-end",
+                   G_CALLBACK(&OnDragEndThunk), this);
+  signals_.Connect(button->button(), "drag-failed",
+                   G_CALLBACK(&OnDragFailedThunk), this);
+
+  // Any time a browser action button is shown or hidden we have to update
+  // the chevron state.
+  signals_.Connect(button->widget(), "show",
+                   G_CALLBACK(&OnButtonShowOrHideThunk), this);
+  signals_.Connect(button->widget(), "hide",
+                   G_CALLBACK(&OnButtonShowOrHideThunk), this);
+
+  gtk_widget_show(button->widget());
+
+  UpdateVisibility();
+}
+
+GtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget(
+    const Extension* extension) {
+  ExtensionButtonMap::iterator it = extension_button_map_.find(
+      extension->id());
+  if (it == extension_button_map_.end())
+    return NULL;
+
+  return it->second.get()->widget();
+}
+
+void BrowserActionsToolbarGtk::RemoveButtonForExtension(
+    const Extension* extension) {
+  if (extension_button_map_.erase(extension->id()))
+    UpdateVisibility();
+  UpdateChevronVisibility();
+}
+
+void BrowserActionsToolbarGtk::UpdateVisibility() {
+  if (button_count() == 0)
+    gtk_widget_hide(widget());
+  else
+    gtk_widget_show(widget());
+}
+
+bool BrowserActionsToolbarGtk::ShouldDisplayBrowserAction(
+    const Extension* extension) {
+  // Only display incognito-enabled extensions while in incognito mode.
+  return (!profile_->IsOffTheRecord() ||
+          profile_->GetExtensionService()->IsIncognitoEnabled(extension));
+}
+
+void BrowserActionsToolbarGtk::HidePopup() {
+  ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup();
+  if (popup)
+    popup->DestroyPopup();
+}
+
+void BrowserActionsToolbarGtk::AnimateToShowNIcons(int count) {
+  desired_width_ = WidthForIconCount(count);
+  start_width_ = button_hbox_->allocation.width;
+  resize_animation_.Reset();
+  resize_animation_.Show();
+}
+
+void BrowserActionsToolbarGtk::BrowserActionAdded(const Extension* extension,
+                                                  int index) {
+  overflow_menu_.reset();
+
+  CreateButtonForExtension(extension, index);
+
+  // If we are still initializing the container, don't bother animating.
+  if (!model_->extensions_initialized())
+    return;
+
+  // Animate the addition if we are showing all browser action buttons.
+  if (!GTK_WIDGET_VISIBLE(overflow_area_)) {
+    AnimateToShowNIcons(button_count());
+    model_->SetVisibleIconCount(button_count());
+  }
+}
+
+void BrowserActionsToolbarGtk::BrowserActionRemoved(
+    const Extension* extension) {
+  overflow_menu_.reset();
+
+  if (drag_button_ != NULL) {
+    // Break the current drag.
+    gtk_grab_remove(button_hbox_.get());
+  }
+
+  RemoveButtonForExtension(extension);
+
+  if (!GTK_WIDGET_VISIBLE(overflow_area_)) {
+    AnimateToShowNIcons(button_count());
+    model_->SetVisibleIconCount(button_count());
+  }
+}
+
+void BrowserActionsToolbarGtk::BrowserActionMoved(const Extension* extension,
+                                                  int index) {
+  // We initiated this move action, and have already moved the button.
+  if (drag_button_ != NULL)
+    return;
+
+  GtkWidget* button_widget = GetBrowserActionWidget(extension);
+  if (!button_widget) {
+    if (ShouldDisplayBrowserAction(extension))
+      NOTREACHED();
+    return;
+  }
+
+  if (profile_->IsOffTheRecord())
+    index = model_->OriginalIndexToIncognito(index);
+
+  gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button_widget, index);
+}
+
+void BrowserActionsToolbarGtk::ModelLoaded() {
+  SetContainerWidth();
+}
+
+void BrowserActionsToolbarGtk::AnimationProgressed(
+    const ui::Animation* animation) {
+  int width = start_width_ + (desired_width_ - start_width_) *
+      animation->GetCurrentValue();
+  gtk_widget_set_size_request(button_hbox_.get(), width, -1);
+
+  if (width == desired_width_)
+    resize_animation_.Reset();
+}
+
+void BrowserActionsToolbarGtk::AnimationEnded(const ui::Animation* animation) {
+  gtk_widget_set_size_request(button_hbox_.get(), desired_width_, -1);
+  UpdateChevronVisibility();
+}
+
+bool BrowserActionsToolbarGtk::IsCommandIdChecked(int command_id) const {
+  return false;
+}
+
+bool BrowserActionsToolbarGtk::IsCommandIdEnabled(int command_id) const {
+  return true;
+}
+
+bool BrowserActionsToolbarGtk::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) {
+  return false;
+}
+
+void BrowserActionsToolbarGtk::ExecuteCommand(int command_id) {
+  const Extension* extension = model_->GetExtensionByIndex(command_id);
+  ExtensionAction* browser_action = extension->browser_action();
+
+  int tab_id = GetCurrentTabId();
+  if (tab_id < 0) {
+    NOTREACHED() << "No current tab.";
+    return;
+  }
+
+  if (browser_action->HasPopup(tab_id)) {
+    ExtensionPopupGtk::Show(
+        browser_action->GetPopupUrl(tab_id), browser(),
+        chevron(),
+        false);
+  } else {
+    ExtensionService* service = browser()->profile()->GetExtensionService();
+    service->browser_event_router()->BrowserActionExecuted(
+        browser()->profile(), extension->id(), browser());
+  }
+}
+
+void BrowserActionsToolbarGtk::StoppedShowing() {
+  overflow_button_->UnsetPaintOverride();
+}
+
+bool BrowserActionsToolbarGtk::AlwaysShowIconForCmd(int command_id) const {
+  return true;
+}
+
+void BrowserActionsToolbarGtk::DragStarted(BrowserActionButton* button,
+                                           GdkDragContext* drag_context) {
+  // No representation of the widget following the cursor.
+  GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
+  gtk_drag_set_icon_pixbuf(drag_context, pixbuf, 0, 0);
+  g_object_unref(pixbuf);
+
+  DCHECK(!drag_button_);
+  drag_button_ = button;
+}
+
+void BrowserActionsToolbarGtk::SetButtonHBoxWidth(int new_width) {
+  gint max_width = WidthForIconCount(button_count());
+  new_width = std::min(max_width, new_width);
+  new_width = std::max(new_width, 0);
+  gtk_widget_set_size_request(button_hbox_.get(), new_width, -1);
+}
+
+void BrowserActionsToolbarGtk::UpdateChevronVisibility() {
+  int showing_icon_count =
+      gtk_chrome_shrinkable_hbox_get_visible_child_count(
+          GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
+  if (showing_icon_count == 0) {
+    gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0, 0, 0);
+  } else {
+    gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0,
+                              kButtonChevronPadding, 0);
+  }
+
+  if (button_count() > showing_icon_count) {
+    if (!GTK_WIDGET_VISIBLE(overflow_area_)) {
+      if (drag_button_) {
+        // During drags, when the overflow chevron shows for the first time,
+        // take that much space away from |button_hbox_| to make the drag look
+        // smoother.
+        GtkRequisition req;
+        gtk_widget_size_request(chevron(), &req);
+        gint overflow_width = req.width;
+        gtk_widget_size_request(button_hbox_.get(), &req);
+        gint button_hbox_width = req.width;
+        button_hbox_width = std::max(button_hbox_width - overflow_width, 0);
+        gtk_widget_set_size_request(button_hbox_.get(), button_hbox_width, -1);
+      }
+
+      gtk_widget_show(overflow_area_);
+    }
+  } else {
+    gtk_widget_hide(overflow_area_);
+  }
+}
+
+gboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget,
+                                                GdkDragContext* drag_context,
+                                                gint x, gint y, guint time) {
+  // Only handle drags we initiated.
+  if (!drag_button_)
+    return FALSE;
+
+  if (base::i18n::IsRTL())
+    x = widget->allocation.width - x;
+  drop_index_ = x < kButtonWidth ? 0 : x / (kButtonWidth + kButtonPadding);
+
+  // We will go ahead and reorder the child in order to provide visual feedback
+  // to the user. We don't inform the model that it has moved until the drag
+  // ends.
+  gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), drag_button_->widget(),
+                        drop_index_);
+
+  gdk_drag_status(drag_context, GDK_ACTION_MOVE, time);
+  return TRUE;
+}
+
+void BrowserActionsToolbarGtk::OnDragEnd(GtkWidget* button,
+                                         GdkDragContext* drag_context) {
+  if (drop_index_ != -1) {
+    if (profile_->IsOffTheRecord())
+      drop_index_ = model_->IncognitoIndexToOriginal(drop_index_);
+
+    model_->MoveBrowserAction(drag_button_->extension(), drop_index_);
+  }
+
+  drag_button_ = NULL;
+  drop_index_ = -1;
+}
+
+gboolean BrowserActionsToolbarGtk::OnDragFailed(GtkWidget* widget,
+                                                GdkDragContext* drag_context,
+                                                GtkDragResult result) {
+  // We connect to this signal and return TRUE so that the default failure
+  // animation (wherein the drag widget floats back to the start of the drag)
+  // does not show, and the drag-end signal is emitted immediately instead of
+  // several seconds later.
+  return TRUE;
+}
+
+void BrowserActionsToolbarGtk::OnHierarchyChanged(
+    GtkWidget* widget, GtkWidget* previous_toplevel) {
+  GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
+  if (!GTK_WIDGET_TOPLEVEL(toplevel))
+    return;
+
+  signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this);
+}
+
+void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget,
+                                          GtkWidget* focus_widget) {
+  ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup();
+  // The focus of the parent window has changed. Close the popup. Delay the hide
+  // because it will destroy the RenderViewHost, which may still be on the
+  // call stack.
+  if (!popup || popup->being_inspected())
+    return;
+  MessageLoop::current()->PostTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(&BrowserActionsToolbarGtk::HidePopup));
+}
+
+gboolean BrowserActionsToolbarGtk::OnGripperMotionNotify(
+    GtkWidget* widget, GdkEventMotion* event) {
+  if (!(event->state & GDK_BUTTON1_MASK))
+    return FALSE;
+
+  // Calculate how much the user dragged the gripper and subtract that off the
+  // button container's width.
+  int distance_dragged = base::i18n::IsRTL() ?
+      -event->x :
+      event->x - widget->allocation.width;
+  gint new_width = button_hbox_->allocation.width - distance_dragged;
+  SetButtonHBoxWidth(new_width);
+
+  return FALSE;
+}
+
+gboolean BrowserActionsToolbarGtk::OnGripperExpose(GtkWidget* gripper,
+                                                   GdkEventExpose* expose) {
+  return TRUE;
+}
+
+// These three signal handlers (EnterNotify, LeaveNotify, and ButtonRelease)
+// are used to give the gripper the resize cursor. Since it doesn't have its
+// own window, we have to set the cursor whenever the pointer moves into the
+// button or leaves the button, and be sure to leave it on when the user is
+// dragging.
+gboolean BrowserActionsToolbarGtk::OnGripperEnterNotify(
+    GtkWidget* gripper, GdkEventCrossing* event) {
+  gdk_window_set_cursor(gripper->window,
+                        gfx::GetCursor(GDK_SB_H_DOUBLE_ARROW));
+  return FALSE;
+}
+
+gboolean BrowserActionsToolbarGtk::OnGripperLeaveNotify(
+    GtkWidget* gripper, GdkEventCrossing* event) {
+  if (!(event->state & GDK_BUTTON1_MASK))
+    gdk_window_set_cursor(gripper->window, NULL);
+  return FALSE;
+}
+
+gboolean BrowserActionsToolbarGtk::OnGripperButtonRelease(
+    GtkWidget* gripper, GdkEventButton* event) {
+  gfx::Rect gripper_rect(0, 0,
+                         gripper->allocation.width, gripper->allocation.height);
+  gfx::Point release_point(event->x, event->y);
+  if (!gripper_rect.Contains(release_point))
+    gdk_window_set_cursor(gripper->window, NULL);
+
+  // After the user resizes the toolbar, we want to smartly resize it to be
+  // the perfect size to fit the buttons.
+  int visible_icon_count =
+      gtk_chrome_shrinkable_hbox_get_visible_child_count(
+          GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
+  AnimateToShowNIcons(visible_icon_count);
+  model_->SetVisibleIconCount(visible_icon_count);
+
+  return FALSE;
+}
+
+gboolean BrowserActionsToolbarGtk::OnGripperButtonPress(
+    GtkWidget* gripper, GdkEventButton* event) {
+  resize_animation_.Reset();
+
+  return FALSE;
+}
+
+gboolean BrowserActionsToolbarGtk::OnOverflowButtonPress(
+    GtkWidget* overflow, GdkEventButton* event) {
+  overflow_menu_model_.reset(new SimpleMenuModel(this));
+
+  int visible_icon_count =
+      gtk_chrome_shrinkable_hbox_get_visible_child_count(
+          GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
+  for (int i = visible_icon_count; i < button_count(); ++i) {
+    int model_index = i;
+    if (profile_->IsOffTheRecord())
+      model_index = model_->IncognitoIndexToOriginal(i);
+
+    const Extension* extension = model_->GetExtensionByIndex(model_index);
+    BrowserActionButton* button = extension_button_map_[extension->id()].get();
+
+    overflow_menu_model_->AddItem(model_index, UTF8ToUTF16(extension->name()));
+    overflow_menu_model_->SetIcon(overflow_menu_model_->GetItemCount() - 1,
+                                  button->GetIcon());
+
+    // TODO(estade): set the menu item's tooltip.
+  }
+
+  overflow_menu_.reset(new MenuGtk(this, overflow_menu_model_.get()));
+  signals_.Connect(overflow_menu_->widget(), "button-press-event",
+                   G_CALLBACK(OnOverflowMenuButtonPressThunk), this);
+
+  overflow_button_->SetPaintOverride(GTK_STATE_ACTIVE);
+  overflow_menu_->PopupAsFromKeyEvent(chevron());
+
+  return FALSE;
+}
+
+gboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress(
+    GtkWidget* overflow, GdkEventButton* event) {
+  if (event->button != 3)
+    return FALSE;
+
+  GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item;
+  if (!menu_item)
+    return FALSE;
+
+  int item_index = g_list_index(GTK_MENU_SHELL(overflow)->children, menu_item);
+  if (item_index == -1) {
+    NOTREACHED();
+    return FALSE;
+  }
+
+  item_index += gtk_chrome_shrinkable_hbox_get_visible_child_count(
+      GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
+  if (profile_->IsOffTheRecord())
+    item_index = model_->IncognitoIndexToOriginal(item_index);
+
+  const Extension* extension = model_->GetExtensionByIndex(item_index);
+  ExtensionButtonMap::iterator it = extension_button_map_.find(
+      extension->id());
+  if (it == extension_button_map_.end()) {
+    NOTREACHED();
+    return FALSE;
+  }
+
+  MenuGtk* menu = it->second.get()->GetContextMenu();
+  if (!menu)
+    return FALSE;
+
+  menu->PopupAsContext(gfx::Point(event->x_root, event->y_root),
+                       event->time);
+  return TRUE;
+}
+
+void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) {
+  if (!resize_animation_.is_animating())
+    UpdateChevronVisibility();
+}
diff --git a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h
new file mode 100644
index 0000000..93fa6d8
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h
@@ -0,0 +1,223 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BROWSER_ACTIONS_TOOLBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BROWSER_ACTIONS_TOOLBAR_GTK_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/linked_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/extensions/extension_toolbar_model.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/overflow_button.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "ui/base/models/simple_menu_model.h"
+
+class Browser;
+class BrowserActionButton;
+class Extension;
+class GtkThemeProvider;
+class Profile;
+
+typedef struct _GdkDragContext GdkDragContext;
+typedef struct _GtkWidget GtkWidget;
+
+class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer,
+                                 public ui::AnimationDelegate,
+                                 public MenuGtk::Delegate,
+                                 public ui::SimpleMenuModel::Delegate,
+                                 public NotificationObserver {
+ public:
+  explicit BrowserActionsToolbarGtk(Browser* browser);
+  virtual ~BrowserActionsToolbarGtk();
+
+  GtkWidget* widget() { return hbox_.get(); }
+  GtkWidget* chevron() { return overflow_button_->widget(); }
+
+  // Returns the widget in use by the BrowserActionButton corresponding to
+  // |extension|. Used in positioning the ExtensionInstalledBubble for
+  // BrowserActions.
+  GtkWidget* GetBrowserActionWidget(const Extension* extension);
+
+  int button_count() { return extension_button_map_.size(); }
+
+  Browser* browser() { return browser_; }
+
+  // Returns the currently selected tab ID, or -1 if there is none.
+  int GetCurrentTabId();
+
+  // Update the display of all buttons.
+  void Update();
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  bool animating() {
+    return resize_animation_.is_animating();
+  }
+
+ private:
+  friend class BrowserActionButton;
+
+  // Initialize drag and drop.
+  void SetupDrags();
+
+  // Query the extensions service for all extensions with browser actions,
+  // and create the UI for them.
+  void CreateAllButtons();
+
+  // Sets the width of the container and overflow state according to the model.
+  void SetContainerWidth();
+
+  // Create the UI for a single browser action. This will stick the button
+  // at the end of the toolbar.
+  void CreateButtonForExtension(const Extension* extension, int index);
+
+  // Delete resources associated with UI for a browser action.
+  void RemoveButtonForExtension(const Extension* extension);
+
+  // Change the visibility of widget() based on whether we have any buttons
+  // to show.
+  void UpdateVisibility();
+
+  // Hide the extension popup, if any.
+  void HidePopup();
+
+  // Animate the toolbar to show the given number of icons. This assumes the
+  // visibility of the overflow button will not change.
+  void AnimateToShowNIcons(int count);
+
+  // Returns true if this extension should be shown in this toolbar. This can
+  // return false if we are in an incognito window and the extension is disabled
+  // for incognito.
+  bool ShouldDisplayBrowserAction(const Extension* extension);
+
+  // ExtensionToolbarModel::Observer implementation.
+  virtual void BrowserActionAdded(const Extension* extension, int index);
+  virtual void BrowserActionRemoved(const Extension* extension);
+  virtual void BrowserActionMoved(const Extension* extension, int index);
+  virtual void ModelLoaded();
+
+  // ui::AnimationDelegate implementation.
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationEnded(const ui::Animation* animation);
+
+  // SimpleMenuModel::Delegate implementation.
+  // In our case, |command_id| is be the index into the model's extension list.
+  virtual bool IsCommandIdChecked(int command_id) const;
+  virtual bool IsCommandIdEnabled(int command_id) const;
+  virtual bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator);
+  virtual void ExecuteCommand(int command_id);
+
+  // MenuGtk::Delegate implementation.
+  virtual void StoppedShowing();
+  virtual bool AlwaysShowIconForCmd(int command_id) const;
+
+  // Called by the BrowserActionButton in response to drag-begin.
+  void DragStarted(BrowserActionButton* button, GdkDragContext* drag_context);
+
+  // Sets the width of the button area of the toolbar to |new_width|, clamping
+  // it to appropriate values.
+  void SetButtonHBoxWidth(int new_width);
+
+  // Shows or hides the chevron as appropriate.
+  void UpdateChevronVisibility();
+
+  CHROMEGTK_CALLBACK_4(BrowserActionsToolbarGtk, gboolean, OnDragMotion,
+                       GdkDragContext*, gint, gint, guint);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, void, OnDragEnd,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_2(BrowserActionsToolbarGtk, gboolean, OnDragFailed,
+                       GdkDragContext*, GtkDragResult);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, void, OnHierarchyChanged,
+                       GtkWidget*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, void, OnSetFocus, GtkWidget*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnGripperMotionNotify, GdkEventMotion*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean, OnGripperExpose,
+                       GdkEventExpose*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnGripperEnterNotify, GdkEventCrossing*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnGripperLeaveNotify, GdkEventCrossing*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnGripperButtonRelease, GdkEventButton*);
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnGripperButtonPress, GdkEventButton*);
+  // The overflow button is pressed.
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnOverflowButtonPress, GdkEventButton*);
+  // The user presses a mouse button over the popped up overflow menu.
+  CHROMEGTK_CALLBACK_1(BrowserActionsToolbarGtk, gboolean,
+                       OnOverflowMenuButtonPress, GdkEventButton*);
+  CHROMEGTK_CALLBACK_0(BrowserActionsToolbarGtk, void, OnButtonShowOrHide);
+
+  Browser* browser_;
+
+  Profile* profile_;
+  GtkThemeProvider* theme_provider_;
+
+  ExtensionToolbarModel* model_;
+
+  // Contains the drag gripper, browser action buttons, and overflow chevron.
+  OwnedWidgetGtk hbox_;
+
+  // Contains the browser action buttons.
+  OwnedWidgetGtk button_hbox_;
+
+  // The overflow button for chrome theme mode.
+  scoped_ptr<CustomDrawButton> overflow_button_;
+  // The separator just next to the overflow button. Only shown in GTK+ theme
+  // mode. In Chrome theme mode, the overflow button has a separator built in.
+  GtkWidget* separator_;
+  scoped_ptr<MenuGtk> overflow_menu_;
+  scoped_ptr<ui::SimpleMenuModel> overflow_menu_model_;
+  GtkWidget* overflow_area_;
+  // A widget for adding extra padding to the left of the overflow button.
+  GtkWidget* overflow_alignment_;
+
+  // The button that is currently being dragged, or NULL.
+  BrowserActionButton* drag_button_;
+
+  // The new position of the button in the drag, or -1.
+  int drop_index_;
+
+  // Map from extension ID to BrowserActionButton, which is a wrapper for
+  // a chrome button and related functionality. There should be one entry
+  // for every extension that has a browser action.
+  typedef std::map<std::string, linked_ptr<BrowserActionButton> >
+      ExtensionButtonMap;
+  ExtensionButtonMap extension_button_map_;
+
+  // We use this animation for the smart resizing of the toolbar.
+  ui::SlideAnimation resize_animation_;
+  // This is the final width we are animating towards.
+  int desired_width_;
+  // This is the width we were at when we started animating.
+  int start_width_;
+
+  ui::GtkSignalRegistrar signals_;
+
+  NotificationRegistrar registrar_;
+
+  ScopedRunnableMethodFactory<BrowserActionsToolbarGtk> method_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowserActionsToolbarGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BROWSER_ACTIONS_TOOLBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/browser_titlebar.cc b/chrome/browser/ui/gtk/browser_titlebar.cc
new file mode 100644
index 0000000..dab1f7f
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_titlebar.cc
@@ -0,0 +1,949 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/browser_titlebar.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/singleton.h"
+#include "base/string_piece.h"
+#include "base/string_tokenizer.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/accelerators_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#if defined(USE_GCONF)
+#include "chrome/browser/ui/gtk/gconf_titlebar_listener.h"
+#endif
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/nine_box.h"
+#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
+#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+namespace {
+
+// The space above the titlebars.
+const int kTitlebarHeight = 14;
+
+// The thickness in pixels of the tab border.
+const int kTabOuterThickness = 1;
+
+// Amount to offset the tab images relative to the background.
+const int kNormalVerticalOffset = kTitlebarHeight + kTabOuterThickness;
+
+// A linux specific menu item for toggling window decorations.
+const int kShowWindowDecorationsCommand = 200;
+
+const int kOTRBottomSpacing = 1;
+// There are 2 px on each side of the OTR avatar (between the frame border and
+// it on the left, and between it and the tabstrip on the right).
+const int kOTRSideSpacing = 2;
+
+// The thickness of the custom frame border; we need it here to enlarge the
+// close button whent the custom frame border isn't showing but the custom
+// titlebar is showing.
+const int kFrameBorderThickness = 4;
+
+// There is a 4px gap between the icon and the title text.
+const int kIconTitleSpacing = 4;
+
+// Padding around the icon when in app mode or popup mode.
+const int kAppModePaddingTop = 5;
+const int kAppModePaddingBottom = 4;
+const int kAppModePaddingLeft = 2;
+
+// The left padding of the tab strip.  In Views, the tab strip has a left
+// margin of FrameBorderThickness + kClientEdgeThickness.  This offset is to
+// account for kClientEdgeThickness.
+const int kTabStripLeftPadding = 1;
+
+// Spacing between buttons of the titlebar.
+const int kButtonSpacing = 2;
+
+// Spacing around outside of titlebar buttons.
+const int kButtonOuterPadding = 2;
+
+// Spacing between tabstrip and window control buttons (when the window is
+// maximized).
+const int kMaximizedTabstripPadding = 16;
+
+gboolean OnMouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
+                          BrowserWindowGtk* browser_window) {
+  // Reset to the default mouse cursor.
+  browser_window->ResetCustomFrameCursor();
+  return TRUE;
+}
+
+GdkPixbuf* GetOTRAvatar() {
+  static GdkPixbuf* otr_avatar = NULL;
+  if (!otr_avatar) {
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    otr_avatar = rb.GetRTLEnabledPixbufNamed(IDR_OTR_ICON);
+  }
+  return otr_avatar;
+}
+
+// Converts a GdkColor to a color_utils::HSL.
+color_utils::HSL GdkColorToHSL(const GdkColor* color) {
+  color_utils::HSL hsl;
+  color_utils::SkColorToHSL(SkColorSetRGB(color->red >> 8,
+                                          color->green >> 8,
+                                          color->blue >> 8), &hsl);
+  return hsl;
+}
+
+// Returns either |one| or |two| based on which has a greater difference in
+// luminosity.
+GdkColor PickLuminosityContrastingColor(const GdkColor* base,
+                                        const GdkColor* one,
+                                        const GdkColor* two) {
+  // Convert all GdkColors to color_utils::HSLs.
+  color_utils::HSL baseHSL = GdkColorToHSL(base);
+  color_utils::HSL oneHSL = GdkColorToHSL(one);
+  color_utils::HSL twoHSL = GdkColorToHSL(two);
+  double one_difference = fabs(baseHSL.l - oneHSL.l);
+  double two_difference = fabs(baseHSL.l - twoHSL.l);
+
+  // Be biased towards the first color presented.
+  if (two_difference > one_difference + 0.1)
+    return *two;
+  else
+    return *one;
+}
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// PopupPageMenuModel
+
+// A menu model that builds the contents of the menu shown for popups (when the
+// user clicks on the favicon) and all of its submenus.
+class PopupPageMenuModel : public ui::SimpleMenuModel {
+ public:
+  explicit PopupPageMenuModel(ui::SimpleMenuModel::Delegate* delegate,
+                              Browser* browser);
+  virtual ~PopupPageMenuModel() { }
+
+ private:
+  void Build();
+
+  // Models for submenus referenced by this model. SimpleMenuModel only uses
+  // weak references so these must be kept for the lifetime of the top-level
+  // model.
+  scoped_ptr<ZoomMenuModel> zoom_menu_model_;
+  scoped_ptr<EncodingMenuModel> encoding_menu_model_;
+  Browser* browser_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(PopupPageMenuModel);
+};
+
+PopupPageMenuModel::PopupPageMenuModel(
+    ui::SimpleMenuModel::Delegate* delegate,
+    Browser* browser)
+    : ui::SimpleMenuModel(delegate), browser_(browser) {
+  Build();
+}
+
+void PopupPageMenuModel::Build() {
+  AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
+  AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
+  AddItemWithStringId(IDC_RELOAD, IDS_APP_MENU_RELOAD);
+  AddSeparator();
+  AddItemWithStringId(IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB);
+  AddItemWithStringId(IDC_COPY_URL, IDS_APP_MENU_COPY_URL);
+  AddSeparator();
+  AddItemWithStringId(IDC_CUT, IDS_CUT);
+  AddItemWithStringId(IDC_COPY, IDS_COPY);
+  AddItemWithStringId(IDC_PASTE, IDS_PASTE);
+  AddSeparator();
+  AddItemWithStringId(IDC_FIND, IDS_FIND);
+  AddItemWithStringId(IDC_PRINT, IDS_PRINT);
+  zoom_menu_model_.reset(new ZoomMenuModel(delegate()));
+  AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU, zoom_menu_model_.get());
+
+  encoding_menu_model_.reset(new EncodingMenuModel(browser_));
+  AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
+                         encoding_menu_model_.get());
+
+  AddSeparator();
+  AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BrowserTitlebar
+
+// static
+const char BrowserTitlebar::kDefaultButtonString[] = ":minimize,maximize,close";
+
+BrowserTitlebar::BrowserTitlebar(BrowserWindowGtk* browser_window,
+                                 GtkWindow* window)
+    : browser_window_(browser_window),
+      window_(window),
+      titlebar_left_buttons_vbox_(NULL),
+      titlebar_right_buttons_vbox_(NULL),
+      titlebar_left_buttons_hbox_(NULL),
+      titlebar_right_buttons_hbox_(NULL),
+      titlebar_left_spy_frame_(NULL),
+      titlebar_right_spy_frame_(NULL),
+      top_padding_left_(NULL),
+      top_padding_right_(NULL),
+      app_mode_favicon_(NULL),
+      app_mode_title_(NULL),
+      using_custom_frame_(false),
+      window_has_focus_(false),
+      theme_provider_(NULL) {
+  Init();
+}
+
+void BrowserTitlebar::Init() {
+  // The widget hierarchy is shown below.
+  //
+  // +- EventBox (container_) ------------------------------------------------+
+  // +- HBox (container_hbox_) -----------------------------------------------+
+  // |+ VBox ---++- Algn. -++- Alignment --------------++- Algn. -++ VBox ---+|
+  // || titlebar||titlebar ||   (titlebar_alignment_)  ||titlebar || titlebar||
+  // || left    ||left     ||                          ||right    || right   ||
+  // || button  ||spy      ||                          ||spy      || button  ||
+  // || vbox    ||frame    ||+- TabStripGtk  ---------+||frame    || vbox    ||
+  // ||         ||         || tab   tab   tabclose    |||         ||         ||
+  // ||         ||         ||+------------------------+||         ||         ||
+  // |+---------++---------++--------------------------++---------++---------+|
+  // +------------------------------------------------------------------------+
+  //
+  // There are two vboxes on either side of |container_hbox_| because when the
+  // desktop is GNOME, the button placement is configurable based on a metacity
+  // gconf key. We can't just have one vbox and move it back and forth because
+  // the gconf language allows you to place buttons on both sides of the
+  // window.  This being Linux, I'm sure there's a bunch of people who have
+  // already configured their window manager to do so and we don't want to get
+  // confused when that happens. The actual contents of these vboxes are lazily
+  // generated so they don't interfere with alignment when everything is
+  // stuffed in the other box.
+  //
+  // Each vbox has the contains the following hierarchy if it contains buttons:
+  //
+  // +- VBox (titlebar_{l,r}_buttons_vbox_) ---------+
+  // |+- Fixed (top_padding_{l,r}_) ----------------+|
+  // ||+- HBox (titlebar_{l,r}_buttons_hbox_ ------+||
+  // ||| (buttons of a configurable layout)        |||
+  // ||+-------------------------------------------+||
+  // |+---------------------------------------------+|
+  // +-----------------------------------------------+
+  //
+  // The two spy alignments are only allocated if this window is an incognito
+  // window. Only one of them holds the spy image.
+  //
+  // If we're a popup window or in app mode, we don't display the spy guy or
+  // the tab strip.  Instead, put an hbox in titlebar_alignment_ in place of
+  // the tab strip.
+  // +- Alignment (titlebar_alignment_) -----------------------------------+
+  // |+ HBox -------------------------------------------------------------+|
+  // ||+- TabStripGtk -++- Image ----------------++- Label --------------+||
+  // ||| hidden        ++    (app_mode_favicon_) ||    (app_mode_title_) |||
+  // |||               ||  favicon               ||  page title          |||
+  // ||+---------------++------------------------++----------------------+||
+  // |+-------------------------------------------------------------------+|
+  // +---------------------------------------------------------------------+
+  container_hbox_ = gtk_hbox_new(FALSE, 0);
+
+  container_ = gtk_event_box_new();
+  gtk_widget_set_name(container_, "chrome-browser-titlebar");
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(container_), FALSE);
+  gtk_container_add(GTK_CONTAINER(container_), container_hbox_);
+
+  g_signal_connect(container_, "scroll-event", G_CALLBACK(OnScrollThunk), this);
+
+  g_signal_connect(window_, "window-state-event",
+                   G_CALLBACK(OnWindowStateChangedThunk), this);
+
+  // Allocate the two button boxes on the left and right parts of the bar, and
+  // spyguy frames in case of incognito mode.
+  titlebar_left_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_buttons_vbox_,
+                     FALSE, FALSE, 0);
+  if (browser_window_->browser()->profile()->IsOffTheRecord() &&
+      browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
+    titlebar_left_spy_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+    gtk_widget_set_no_show_all(titlebar_left_spy_frame_, TRUE);
+    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_left_spy_frame_), 0,
+        kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
+    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_spy_frame_,
+                       FALSE, FALSE, 0);
+
+    titlebar_right_spy_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+    gtk_widget_set_no_show_all(titlebar_right_spy_frame_, TRUE);
+    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_right_spy_frame_), 0,
+        kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
+    gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_spy_frame_,
+                     FALSE, FALSE, 0);
+  }
+  titlebar_right_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_buttons_vbox_,
+                   FALSE, FALSE, 0);
+
+#if defined(USE_GCONF)
+  // Either read the gconf database and register for updates (on GNOME), or use
+  // the default value (anywhere else).
+  GConfTitlebarListener::GetInstance()->SetTitlebarButtons(this);
+#else
+  BuildButtons(kDefaultButtonString);
+#endif
+
+  // We use an alignment to control the titlebar height.
+  titlebar_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  if (browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
+    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
+                       TRUE, 0);
+
+    // Put the tab strip in the titlebar.
+    gtk_container_add(GTK_CONTAINER(titlebar_alignment_),
+                      browser_window_->tabstrip()->widget());
+  } else {
+    // App mode specific widgets.
+    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
+                       TRUE, 0);
+    GtkWidget* app_mode_hbox = gtk_hbox_new(FALSE, kIconTitleSpacing);
+    gtk_container_add(GTK_CONTAINER(titlebar_alignment_), app_mode_hbox);
+
+    // Put the tab strip in the hbox even though we don't show it.  Sometimes
+    // we need the position of the tab strip so make sure it's in our widget
+    // hierarchy.
+    gtk_box_pack_start(GTK_BOX(app_mode_hbox),
+        browser_window_->tabstrip()->widget(), FALSE, FALSE, 0);
+
+    GtkWidget* favicon_event_box = gtk_event_box_new();
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(favicon_event_box), FALSE);
+    g_signal_connect(favicon_event_box, "button-press-event",
+                     G_CALLBACK(OnButtonPressedThunk), this);
+    gtk_box_pack_start(GTK_BOX(app_mode_hbox), favicon_event_box, FALSE,
+                       FALSE, 0);
+    // We use the app logo as a placeholder image so the title doesn't jump
+    // around.
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    app_mode_favicon_ = gtk_image_new_from_pixbuf(
+        rb.GetRTLEnabledPixbufNamed(IDR_PRODUCT_LOGO_16));
+    g_object_set_data(G_OBJECT(app_mode_favicon_), "left-align-popup",
+                      reinterpret_cast<void*>(true));
+    gtk_container_add(GTK_CONTAINER(favicon_event_box), app_mode_favicon_);
+
+    app_mode_title_ = gtk_label_new(NULL);
+    gtk_label_set_ellipsize(GTK_LABEL(app_mode_title_), PANGO_ELLIPSIZE_END);
+    gtk_misc_set_alignment(GTK_MISC(app_mode_title_), 0.0, 0.5);
+    gtk_box_pack_start(GTK_BOX(app_mode_hbox), app_mode_title_, TRUE, TRUE,
+                       0);
+
+    // Register with the theme provider to set the |app_mode_title_| label
+    // color.
+    theme_provider_ = GtkThemeProvider::GetFrom(
+        browser_window_->browser()->profile());
+    registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                   NotificationService::AllSources());
+    theme_provider_->InitThemesFor(this);
+    UpdateTitleAndIcon();
+  }
+
+  gtk_widget_show_all(container_);
+
+  ui::ActiveWindowWatcherX::AddObserver(this);
+}
+
+BrowserTitlebar::~BrowserTitlebar() {
+  ui::ActiveWindowWatcherX::RemoveObserver(this);
+#if defined(USE_GCONF)
+  GConfTitlebarListener::GetInstance()->RemoveObserver(this);
+#endif
+}
+
+void BrowserTitlebar::BuildButtons(const std::string& button_string) {
+  // Clear out all previous data.
+  close_button_.reset();
+  restore_button_.reset();
+  maximize_button_.reset();
+  minimize_button_.reset();
+  gtk_util::RemoveAllChildren(titlebar_left_buttons_vbox_);
+  gtk_util::RemoveAllChildren(titlebar_right_buttons_vbox_);
+  titlebar_left_buttons_hbox_ = NULL;
+  titlebar_right_buttons_hbox_ = NULL;
+  top_padding_left_ = NULL;
+  top_padding_right_ = NULL;
+
+  bool left_side = true;
+  StringTokenizer tokenizer(button_string, ":,");
+  tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
+  int left_count = 0;
+  int right_count = 0;
+  while (tokenizer.GetNext()) {
+    if (tokenizer.token_is_delim()) {
+      if (*tokenizer.token_begin() == ':')
+        left_side = false;
+    } else {
+      base::StringPiece token = tokenizer.token_piece();
+      if (token == "minimize") {
+        (left_side ? left_count : right_count)++;
+        GtkWidget* parent_box = GetButtonHBox(left_side);
+        minimize_button_.reset(
+            BuildTitlebarButton(IDR_MINIMIZE, IDR_MINIMIZE_P,
+                                IDR_MINIMIZE_H, parent_box,
+                                IDS_XPFRAME_MINIMIZE_TOOLTIP));
+
+        gtk_widget_size_request(minimize_button_->widget(),
+                                &minimize_button_req_);
+      } else if (token == "maximize") {
+        (left_side ? left_count : right_count)++;
+        GtkWidget* parent_box = GetButtonHBox(left_side);
+        restore_button_.reset(
+            BuildTitlebarButton(IDR_RESTORE, IDR_RESTORE_P,
+                                IDR_RESTORE_H, parent_box,
+                                IDS_XPFRAME_RESTORE_TOOLTIP));
+        maximize_button_.reset(
+            BuildTitlebarButton(IDR_MAXIMIZE, IDR_MAXIMIZE_P,
+                                IDR_MAXIMIZE_H, parent_box,
+                                IDS_XPFRAME_MAXIMIZE_TOOLTIP));
+
+        gtk_util::SetButtonClickableByMouseButtons(maximize_button_->widget(),
+                                                   true, true, true);
+        gtk_widget_size_request(restore_button_->widget(),
+                                &restore_button_req_);
+      } else if (token == "close") {
+        (left_side ? left_count : right_count)++;
+        GtkWidget* parent_box = GetButtonHBox(left_side);
+        close_button_.reset(
+            BuildTitlebarButton(IDR_CLOSE, IDR_CLOSE_P,
+                                IDR_CLOSE_H, parent_box,
+                                IDS_XPFRAME_CLOSE_TOOLTIP));
+        close_button_->set_flipped(left_side);
+
+        gtk_widget_size_request(close_button_->widget(), &close_button_req_);
+      }
+      // Ignore any other values like "pin" since we don't have images for
+      // those.
+    }
+  }
+
+  // If we are in incognito mode, add the spy guy to either the end of the left
+  // or the beginning of the right depending on which side has fewer buttons.
+  if (browser_window_->browser()->profile()->IsOffTheRecord() &&
+      browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
+    GtkWidget* spy_guy = gtk_image_new_from_pixbuf(GetOTRAvatar());
+    gtk_misc_set_alignment(GTK_MISC(spy_guy), 0.0, 1.0);
+    gtk_widget_set_size_request(spy_guy, -1, 0);
+    gtk_widget_show(spy_guy);
+
+    // Remove previous state.
+    gtk_util::RemoveAllChildren(titlebar_left_spy_frame_);
+    gtk_util::RemoveAllChildren(titlebar_right_spy_frame_);
+
+    if (right_count > left_count) {
+      gtk_container_add(GTK_CONTAINER(titlebar_left_spy_frame_), spy_guy);
+      gtk_widget_show(titlebar_left_spy_frame_);
+      gtk_widget_hide(titlebar_right_spy_frame_);
+    } else {
+      gtk_container_add(GTK_CONTAINER(titlebar_right_spy_frame_), spy_guy);
+      gtk_widget_show(titlebar_right_spy_frame_);
+      gtk_widget_hide(titlebar_left_spy_frame_);
+    }
+  }
+
+  // Now show the correct widgets in the two hierarchies.
+  if (using_custom_frame_) {
+    gtk_widget_show_all(titlebar_left_buttons_vbox_);
+    gtk_widget_show_all(titlebar_right_buttons_vbox_);
+  }
+  UpdateMaximizeRestoreVisibility();
+}
+
+GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) {
+  if (left_side && titlebar_left_buttons_hbox_)
+    return titlebar_left_buttons_hbox_;
+  else if (!left_side && titlebar_right_buttons_hbox_)
+    return titlebar_right_buttons_hbox_;
+
+  // We put the min/max/restore/close buttons in a vbox so they are top aligned
+  // (up to padding) and don't vertically stretch.
+  GtkWidget* vbox = left_side ? titlebar_left_buttons_vbox_ :
+                    titlebar_right_buttons_vbox_;
+
+  GtkWidget* top_padding = gtk_fixed_new();
+  gtk_widget_set_size_request(top_padding, -1, kButtonOuterPadding);
+  gtk_box_pack_start(GTK_BOX(vbox), top_padding, FALSE, FALSE, 0);
+
+  GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing);
+  gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0);
+
+  if (left_side) {
+    titlebar_left_buttons_hbox_ = buttons_hbox;
+    top_padding_left_ = top_padding;
+  } else {
+    titlebar_right_buttons_hbox_ = buttons_hbox;
+    top_padding_right_ = top_padding;
+  }
+
+  return buttons_hbox;
+}
+
+CustomDrawButton* BrowserTitlebar::BuildTitlebarButton(int image,
+    int image_pressed, int image_hot, GtkWidget* box, int tooltip) {
+  CustomDrawButton* button = new CustomDrawButton(image, image_pressed,
+                                                  image_hot, 0);
+  gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK);
+  g_signal_connect(button->widget(), "clicked",
+                   G_CALLBACK(OnButtonClickedThunk), this);
+  g_signal_connect(button->widget(), "motion-notify-event",
+                   G_CALLBACK(OnMouseMoveEvent), browser_window_);
+  std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip);
+  gtk_widget_set_tooltip_text(button->widget(),
+                              localized_tooltip.c_str());
+  gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0);
+  return button;
+}
+
+void BrowserTitlebar::UpdateCustomFrame(bool use_custom_frame) {
+  using_custom_frame_ = use_custom_frame;
+  if (use_custom_frame) {
+    if (titlebar_left_buttons_vbox_)
+      gtk_widget_show_all(titlebar_left_buttons_vbox_);
+    if (titlebar_right_buttons_vbox_)
+      gtk_widget_show_all(titlebar_right_buttons_vbox_);
+  } else {
+    if (titlebar_left_buttons_vbox_)
+      gtk_widget_hide(titlebar_left_buttons_vbox_);
+    if (titlebar_right_buttons_vbox_)
+      gtk_widget_hide(titlebar_right_buttons_vbox_);
+  }
+  UpdateTitlebarAlignment();
+}
+
+void BrowserTitlebar::UpdateTitleAndIcon() {
+  if (!app_mode_title_)
+    return;
+
+  // Get the page title and elide it to the available space.
+  string16 title = browser_window_->browser()->GetWindowTitleForCurrentTab();
+  gtk_label_set_text(GTK_LABEL(app_mode_title_), UTF16ToUTF8(title).c_str());
+
+  // Note: this isn't browser_window_->browser()->type() & Browser::TYPE_APP
+  // because we want to exclude Browser::TYPE_APP_POPUP.
+  if (browser_window_->browser()->type() == Browser::TYPE_APP ||
+      browser_window_->browser()->type() == Browser::TYPE_APP_PANEL) {
+    // Update the system app icon.  We don't need to update the icon in the top
+    // left of the custom frame, that will get updated when the throbber is
+    // updated.
+    SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon();
+    if (icon.empty()) {
+      gtk_util::SetWindowIcon(window_);
+    } else {
+      GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
+      gtk_window_set_icon(window_, icon_pixbuf);
+      g_object_unref(icon_pixbuf);
+    }
+  }
+}
+
+void BrowserTitlebar::UpdateThrobber(TabContents* tab_contents) {
+  DCHECK(app_mode_favicon_);
+
+  if (tab_contents && tab_contents->is_loading()) {
+    GdkPixbuf* icon_pixbuf =
+        throbber_.GetNextFrame(tab_contents->waiting_for_response());
+    gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
+  } else {
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+    // Note: this isn't browser_window_->browser()->type() & Browser::TYPE_APP
+    // because we want to exclude Browser::TYPE_APP_POPUP.
+    if (browser_window_->browser()->type() == Browser::TYPE_APP ||
+        browser_window_->browser()->type() == Browser::TYPE_APP_PANEL) {
+      SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon();
+      if (icon.empty()) {
+        // Fallback to the Chromium icon if the page has no icon.
+        gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
+            rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
+      } else {
+        GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
+        gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
+        g_object_unref(icon_pixbuf);
+      }
+    } else {
+      gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
+          rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
+    }
+    throbber_.Reset();
+  }
+}
+
+void BrowserTitlebar::UpdateTitlebarAlignment() {
+  if (browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
+    int top_padding = 0;
+    int side_padding = 0;
+    int vertical_offset = kNormalVerticalOffset;
+
+    if (using_custom_frame_) {
+      if (!browser_window_->IsMaximized()) {
+        top_padding = kTitlebarHeight;
+      } else if (using_custom_frame_ && browser_window_->IsMaximized()) {
+        vertical_offset = 0;
+        side_padding = kMaximizedTabstripPadding;
+      }
+    }
+
+    int right_padding = 0;
+    int left_padding = kTabStripLeftPadding;
+    if (titlebar_right_buttons_hbox_)
+      right_padding = side_padding;
+    if (titlebar_left_buttons_hbox_)
+      left_padding = side_padding;
+
+    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
+                              top_padding, 0,
+                              left_padding, right_padding);
+    browser_window_->tabstrip()->SetVerticalOffset(vertical_offset);
+  } else {
+    if (using_custom_frame_ && !browser_window_->IsFullscreen()) {
+      gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
+          kAppModePaddingTop, kAppModePaddingBottom, kAppModePaddingLeft, 0);
+      gtk_widget_show(titlebar_alignment_);
+    } else {
+      gtk_widget_hide(titlebar_alignment_);
+    }
+  }
+
+  // Resize the buttons so that the clickable area extends all the way to the
+  // edge of the browser window.
+  GtkRequisition close_button_req = close_button_req_;
+  GtkRequisition minimize_button_req = minimize_button_req_;
+  GtkRequisition restore_button_req = restore_button_req_;
+  if (using_custom_frame_ && browser_window_->IsMaximized()) {
+    close_button_req.width += kButtonOuterPadding;
+    close_button_req.height += kButtonOuterPadding;
+    minimize_button_req.height += kButtonOuterPadding;
+    restore_button_req.height += kButtonOuterPadding;
+    if (top_padding_left_)
+      gtk_widget_hide(top_padding_left_);
+    if (top_padding_right_)
+      gtk_widget_hide(top_padding_right_);
+  } else {
+    if (top_padding_left_)
+      gtk_widget_show(top_padding_left_);
+    if (top_padding_right_)
+      gtk_widget_show(top_padding_right_);
+  }
+  if (close_button_.get()) {
+    gtk_widget_set_size_request(close_button_->widget(),
+                                close_button_req.width,
+                                close_button_req.height);
+  }
+  if (minimize_button_.get()) {
+    gtk_widget_set_size_request(minimize_button_->widget(),
+                                minimize_button_req.width,
+                                minimize_button_req.height);
+  }
+  if (maximize_button_.get()) {
+    gtk_widget_set_size_request(restore_button_->widget(),
+                                restore_button_req.width,
+                                restore_button_req.height);
+  }
+}
+
+void BrowserTitlebar::UpdateTextColor() {
+  if (!app_mode_title_)
+    return;
+
+  if (theme_provider_ && theme_provider_->UseGtkTheme()) {
+    // We don't really have any good options here.
+    //
+    // Colors from window manager themes aren't exposed in GTK; the window
+    // manager is a separate component and when there is information sharing
+    // (in the case of metacity), it's one way where the window manager reads
+    // data from the GTK theme (which allows us to do a decent job with
+    // picking the frame color).
+    //
+    // We probably won't match in the majority of cases, but we can at the
+    // very least make things legible. The default metacity and xfwm themes
+    // on ubuntu have white text hardcoded. Determine whether black or white
+    // has more luminosity contrast and then set that color as the text
+    // color.
+    GdkColor frame_color;
+    if (window_has_focus_) {
+      frame_color = theme_provider_->GetGdkColor(
+          BrowserThemeProvider::COLOR_FRAME);
+    } else {
+      frame_color = theme_provider_->GetGdkColor(
+          BrowserThemeProvider::COLOR_FRAME_INACTIVE);
+    }
+    GdkColor text_color = PickLuminosityContrastingColor(
+        &frame_color, &gtk_util::kGdkWhite, &gtk_util::kGdkBlack);
+    gtk_util::SetLabelColor(app_mode_title_, &text_color);
+  } else {
+    gtk_util::SetLabelColor(app_mode_title_, &gtk_util::kGdkWhite);
+  }
+}
+
+void BrowserTitlebar::ShowFaviconMenu(GdkEventButton* event) {
+  if (!favicon_menu_model_.get()) {
+    favicon_menu_model_.reset(
+        new PopupPageMenuModel(this, browser_window_->browser()));
+
+    favicon_menu_.reset(new MenuGtk(NULL, favicon_menu_model_.get()));
+  }
+
+  favicon_menu_->PopupForWidget(app_mode_favicon_, event->button, event->time);
+}
+
+void BrowserTitlebar::MaximizeButtonClicked() {
+  GdkEvent* event = gtk_get_current_event();
+  if (event->button.button == 1) {
+    gtk_window_maximize(window_);
+  } else {
+    GtkWidget* widget = GTK_WIDGET(window_);
+    GdkScreen* screen = gtk_widget_get_screen(widget);
+    gint monitor = gdk_screen_get_monitor_at_window(screen, widget->window);
+    GdkRectangle screen_rect;
+    gdk_screen_get_monitor_geometry(screen, monitor, &screen_rect);
+
+    gint x, y;
+    gtk_window_get_position(window_, &x, &y);
+    gint width = widget->allocation.width;
+    gint height = widget->allocation.height;
+
+    if (event->button.button == 3) {
+      x = 0;
+      width = screen_rect.width;
+    } else if (event->button.button == 2) {
+      y = 0;
+      height = screen_rect.height;
+    }
+
+    browser_window_->SetBounds(gfx::Rect(x, y, width, height));
+  }
+  gdk_event_free(event);
+}
+
+void BrowserTitlebar::UpdateMaximizeRestoreVisibility() {
+  if (maximize_button_.get()) {
+    if (browser_window_->IsMaximized()) {
+      gtk_widget_hide(maximize_button_->widget());
+      gtk_widget_show(restore_button_->widget());
+    } else {
+      gtk_widget_hide(restore_button_->widget());
+      gtk_widget_show(maximize_button_->widget());
+    }
+  }
+}
+
+gboolean BrowserTitlebar::OnWindowStateChanged(GtkWindow* window,
+                                               GdkEventWindowState* event) {
+  UpdateMaximizeRestoreVisibility();
+  UpdateTitlebarAlignment();
+  UpdateTextColor();
+  return FALSE;
+}
+
+gboolean BrowserTitlebar::OnScroll(GtkWidget* widget, GdkEventScroll* event) {
+  TabStripModel* tabstrip_model = browser_window_->browser()->tabstrip_model();
+  int index = tabstrip_model->selected_index();
+  if (event->direction == GDK_SCROLL_LEFT ||
+      event->direction == GDK_SCROLL_UP) {
+    if (index != 0)
+      tabstrip_model->SelectPreviousTab();
+  } else if (index + 1 < tabstrip_model->count()) {
+    tabstrip_model->SelectNextTab();
+  }
+  return TRUE;
+}
+
+// static
+void BrowserTitlebar::OnButtonClicked(GtkWidget* button) {
+  if (close_button_.get() && close_button_->widget() == button) {
+    browser_window_->Close();
+  } else if (restore_button_.get() && restore_button_->widget() == button) {
+    browser_window_->UnMaximize();
+  } else if (maximize_button_.get() && maximize_button_->widget() == button) {
+    MaximizeButtonClicked();
+  } else if (minimize_button_.get() && minimize_button_->widget() == button) {
+    gtk_window_iconify(window_);
+  }
+}
+
+gboolean BrowserTitlebar::OnButtonPressed(GtkWidget* widget,
+                                          GdkEventButton* event) {
+  if (event->button != 1)
+    return FALSE;
+
+  ShowFaviconMenu(event);
+  return TRUE;
+}
+
+void BrowserTitlebar::ShowContextMenu(GdkEventButton* event) {
+  if (!context_menu_.get()) {
+    context_menu_model_.reset(new ContextMenuModel(this));
+    context_menu_.reset(new MenuGtk(NULL, context_menu_model_.get()));
+  }
+
+  context_menu_->PopupAsContext(gfx::Point(event->x_root, event->y_root),
+                                event->time);
+}
+
+bool BrowserTitlebar::IsCommandIdEnabled(int command_id) const {
+  if (command_id == kShowWindowDecorationsCommand)
+    return true;
+
+  return browser_window_->browser()->command_updater()->
+      IsCommandEnabled(command_id);
+}
+
+bool BrowserTitlebar::IsCommandIdChecked(int command_id) const {
+  if (command_id == kShowWindowDecorationsCommand) {
+    PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
+    return !prefs->GetBoolean(prefs::kUseCustomChromeFrame);
+  }
+
+  EncodingMenuController controller;
+  if (controller.DoesCommandBelongToEncodingMenu(command_id)) {
+    TabContents* tab_contents =
+        browser_window_->browser()->GetSelectedTabContents();
+    if (tab_contents) {
+      return controller.IsItemChecked(browser_window_->browser()->profile(),
+                                      tab_contents->encoding(),
+                                      command_id);
+    }
+    return false;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+void BrowserTitlebar::ExecuteCommand(int command_id) {
+  if (command_id == kShowWindowDecorationsCommand) {
+    PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
+    prefs->SetBoolean(prefs::kUseCustomChromeFrame,
+                  !prefs->GetBoolean(prefs::kUseCustomChromeFrame));
+    return;
+  }
+
+  browser_window_->browser()->ExecuteCommand(command_id);
+}
+
+bool BrowserTitlebar::GetAcceleratorForCommandId(
+    int command_id, ui::Accelerator* accelerator) {
+  const ui::AcceleratorGtk* accelerator_gtk =
+      AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(
+          command_id);
+  if (accelerator_gtk)
+    *accelerator = *accelerator_gtk;
+  return accelerator_gtk;
+}
+
+void BrowserTitlebar::Observe(NotificationType type,
+                              const NotificationSource& source,
+                              const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::BROWSER_THEME_CHANGED:
+      UpdateTextColor();
+      break;
+
+    default:
+      NOTREACHED();
+  }
+}
+
+void BrowserTitlebar::ActiveWindowChanged(GdkWindow* active_window) {
+  // Can be called during shutdown; BrowserWindowGtk will set our |window_|
+  // to NULL during that time.
+  if (!window_)
+    return;
+
+  window_has_focus_ = GTK_WIDGET(window_)->window == active_window;
+  UpdateTextColor();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BrowserTitlebar::Throbber implementation
+// TODO(tc): Handle anti-clockwise spinning when waiting for a connection.
+
+// We don't bother to clean up these or the pixbufs they contain when we exit.
+static std::vector<GdkPixbuf*>* g_throbber_frames = NULL;
+static std::vector<GdkPixbuf*>* g_throbber_waiting_frames = NULL;
+
+// Load |resource_id| from the ResourceBundle and split it into a series of
+// square GdkPixbufs that get stored in |frames|.
+static void MakeThrobberFrames(int resource_id,
+                               std::vector<GdkPixbuf*>* frames) {
+  ResourceBundle &rb = ResourceBundle::GetSharedInstance();
+  SkBitmap* frame_strip = rb.GetBitmapNamed(resource_id);
+
+  // Each frame of the animation is a square, so we use the height as the
+  // frame size.
+  int frame_size = frame_strip->height();
+  size_t num_frames = frame_strip->width() / frame_size;
+
+  // Make a separate GdkPixbuf for each frame of the animation.
+  for (size_t i = 0; i < num_frames; ++i) {
+    SkBitmap frame = SkBitmapOperations::CreateTiledBitmap(*frame_strip,
+        i * frame_size, 0, frame_size, frame_size);
+    frames->push_back(gfx::GdkPixbufFromSkBitmap(&frame));
+  }
+}
+
+GdkPixbuf* BrowserTitlebar::Throbber::GetNextFrame(bool is_waiting) {
+  Throbber::InitFrames();
+  if (is_waiting) {
+    return (*g_throbber_waiting_frames)[current_waiting_frame_++ %
+        g_throbber_waiting_frames->size()];
+  } else {
+    return (*g_throbber_frames)[current_frame_++ % g_throbber_frames->size()];
+  }
+}
+
+void BrowserTitlebar::Throbber::Reset() {
+  current_frame_ = 0;
+  current_waiting_frame_ = 0;
+}
+
+// static
+void BrowserTitlebar::Throbber::InitFrames() {
+  if (g_throbber_frames)
+    return;
+
+  // We load the light version of the throbber since it'll be in the titlebar.
+  g_throbber_frames = new std::vector<GdkPixbuf*>;
+  MakeThrobberFrames(IDR_THROBBER_LIGHT, g_throbber_frames);
+
+  g_throbber_waiting_frames = new std::vector<GdkPixbuf*>;
+  MakeThrobberFrames(IDR_THROBBER_WAITING_LIGHT, g_throbber_waiting_frames);
+}
+
+BrowserTitlebar::ContextMenuModel::ContextMenuModel(
+    ui::SimpleMenuModel::Delegate* delegate)
+    : SimpleMenuModel(delegate) {
+  AddItemWithStringId(IDC_NEW_TAB, IDS_TAB_CXMENU_NEWTAB);
+  AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
+  AddSeparator();
+  AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
+  AddSeparator();
+  AddCheckItemWithStringId(kShowWindowDecorationsCommand,
+                           IDS_SHOW_WINDOW_DECORATIONS_MENU);
+}
diff --git a/chrome/browser/ui/gtk/browser_titlebar.h b/chrome/browser/ui/gtk/browser_titlebar.h
new file mode 100644
index 0000000..7d841dd
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_titlebar.h
@@ -0,0 +1,239 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A helper class that contains the gtk widgets that make up the titlebar.  The
+// titlebar consists of the tabstrip and if the custom chrome frame is turned
+// on, it includes the taller titlebar and minimize, restore, maximize, and
+// close buttons.
+
+#ifndef CHROME_BROWSER_UI_GTK_BROWSER_TITLEBAR_H_
+#define CHROME_BROWSER_UI_GTK_BROWSER_TITLEBAR_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/x/active_window_watcher_x.h"
+
+class BrowserWindowGtk;
+class CustomDrawButton;
+class GtkThemeProvider;
+class MenuGtk;
+class PopupPageMenuModel;
+class TabContents;
+
+class BrowserTitlebar : public NotificationObserver,
+                        public ui::ActiveWindowWatcherX::Observer,
+                        public ui::SimpleMenuModel::Delegate {
+ public:
+  // A default button order string for when we aren't asking gconf for the
+  // metacity configuration.
+  static const char kDefaultButtonString[];
+
+  BrowserTitlebar(BrowserWindowGtk* browser_window, GtkWindow* window);
+  virtual ~BrowserTitlebar();
+
+  GtkWidget* widget() {
+    return container_;
+  }
+
+  void set_window(GtkWindow* window) { window_ = window; }
+
+  // Builds the buttons based on the metacity |button_string|.
+  void BuildButtons(const std::string& button_string);
+
+  // Update the appearance of the title bar based on whether we're showing a
+  // custom frame or not.  If |use_custom_frame| is true, we show an extra
+  // tall titlebar and the min/max/close buttons.
+  void UpdateCustomFrame(bool use_custom_frame);
+
+  // Updates the title and icon when in app or popup mode (no tabstrip).
+  void UpdateTitleAndIcon();
+
+  // Called by the browser asking us to update the loading throbber.
+  // |tab_contents| is the tab that is associated with the window throbber.
+  // |tab_contents| can be null.
+  void UpdateThrobber(TabContents* tab_contents);
+
+  // On Windows, right clicking in the titlebar background brings up the system
+  // menu.  There's no such thing on linux, so we just show the menu items we
+  // add to the menu.
+  void ShowContextMenu(GdkEventButton* event);
+
+ private:
+  // A helper class to keep track of which frame of the throbber animation
+  // we're showing.
+  class Throbber {
+   public:
+    Throbber() : current_frame_(0), current_waiting_frame_(0) {}
+
+    // Get the next frame in the animation. The image is owned by the throbber
+    // so the caller doesn't need to unref.  |is_waiting| is true if we're
+    // still waiting for a response.
+    GdkPixbuf* GetNextFrame(bool is_waiting);
+
+    // Reset back to the first frame.
+    void Reset();
+   private:
+    // Make sure the frames are loaded.
+    static void InitFrames();
+
+    int current_frame_;
+    int current_waiting_frame_;
+  };
+
+  class ContextMenuModel : public ui::SimpleMenuModel {
+   public:
+    explicit ContextMenuModel(ui::SimpleMenuModel::Delegate* delegate);
+  };
+
+  // Build the titlebar, the space above the tab
+  // strip, and (maybe) the min, max, close buttons.  |container| is the gtk
+  // continer that we put the widget into.
+  void Init();
+
+  // Lazily builds and returns |titlebar_{left,right}_buttons_vbox_| and their
+  // subtrees. We do this lazily because in most situations, only one of them
+  // is allocated (though the user can (and do) manually mess with their gconf
+  // settings to get absolutely horrid combinations of buttons on both sides.
+  GtkWidget* GetButtonHBox(bool left_side);
+
+  // Constructs a CustomDraw button given 3 image ids (IDR_), the box to place
+  // the button into, and a tooltip id (IDS_).
+  CustomDrawButton* BuildTitlebarButton(int image, int image_pressed,
+                                        int image_hot, GtkWidget* box,
+                                        int tooltip);
+
+  // Update the titlebar spacing based on the custom frame and maximized state.
+  void UpdateTitlebarAlignment();
+
+  // Updates the color of the title bar. Called whenever we have a state
+  // change in the window.
+  void UpdateTextColor();
+
+  // Show the menu that the user gets from left-clicking the favicon.
+  void ShowFaviconMenu(GdkEventButton* event);
+
+  // The maximize button was clicked, take an action depending on which mouse
+  // button the user pressed.
+  void MaximizeButtonClicked();
+
+  // Updates the visibility of the maximize and restore buttons; only one can
+  // be visible at a time.
+  void UpdateMaximizeRestoreVisibility();
+
+  // Callback for changes to window state.  This includes
+  // maximizing/restoring/minimizing the window.
+  CHROMEG_CALLBACK_1(BrowserTitlebar, gboolean, OnWindowStateChanged,
+                     GtkWindow*, GdkEventWindowState*);
+
+  // Callback for mousewheel events.
+  CHROMEGTK_CALLBACK_1(BrowserTitlebar, gboolean, OnScroll,
+                       GdkEventScroll*);
+
+  // Callback for min/max/close buttons.
+  CHROMEGTK_CALLBACK_0(BrowserTitlebar, void, OnButtonClicked);
+
+  // Callback for favicon.
+  CHROMEGTK_CALLBACK_1(BrowserTitlebar, gboolean, OnButtonPressed,
+                       GdkEventButton*);
+
+  // -- Context Menu -----------------------------------------------------------
+
+  // SimpleMenuModel::Delegate implementation:
+  virtual bool IsCommandIdEnabled(int command_id) const;
+  virtual bool IsCommandIdChecked(int command_id) const;
+  virtual void ExecuteCommand(int command_id);
+  virtual bool GetAcceleratorForCommandId(int command_id,
+                                          ui::Accelerator* accelerator);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Overriden from ActiveWindowWatcher::Observer.
+  virtual void ActiveWindowChanged(GdkWindow* active_window);
+
+  // Pointers to the browser window that owns us and it's GtkWindow.
+  BrowserWindowGtk* browser_window_;
+  GtkWindow* window_;
+
+  // The container widget the holds the hbox which contains the whole titlebar.
+  GtkWidget* container_;
+
+  // The hbox that contains the whole titlebar.
+  GtkWidget* container_hbox_;
+
+  // VBoxes that holds the min/max/close buttons box and an optional padding
+  // that defines the skyline if the user turns off window manager decorations.
+  // There is a left and right version of this box since we try to integrate
+  // with the recent Ubuntu theme changes which put the buttons on the left.
+  GtkWidget* titlebar_left_buttons_vbox_;
+  GtkWidget* titlebar_right_buttons_vbox_;
+
+  // HBoxes that contains the actual min/max/close buttons.
+  GtkWidget* titlebar_left_buttons_hbox_;
+  GtkWidget* titlebar_right_buttons_hbox_;
+
+  // Spy frame. One of these frames holds the spy guy in incognito mode. It's
+  // the side with the least buttons. These are NULL when we aren't in
+  // incognito mode.
+  GtkWidget* titlebar_left_spy_frame_;
+  GtkWidget* titlebar_right_spy_frame_;
+
+  // Padding between the titlebar buttons and the top of the screen. Only show
+  // when not maximized.
+  GtkWidget* top_padding_left_;
+  GtkWidget* top_padding_right_;
+
+  // Gtk alignment that contains the tab strip.  If the user turns off window
+  // manager decorations, we draw this taller.
+  GtkWidget* titlebar_alignment_;
+
+  // The favicon and page title used when in app mode or popup mode.
+  GtkWidget* app_mode_favicon_;
+  GtkWidget* app_mode_title_;
+
+  // Whether we are using a custom frame.
+  bool using_custom_frame_;
+
+  // Whether we have focus (gtk_window_is_active() sometimes returns the wrong
+  // value, so manually track the focus-in and focus-out events.)
+  bool window_has_focus_;
+
+  // We change the size of these three buttons when the window is maximized, so
+  // we use these structs to keep track of their original size.
+  GtkRequisition close_button_req_;
+  GtkRequisition minimize_button_req_;
+  GtkRequisition restore_button_req_;
+
+  // Maximize and restore widgets in the titlebar.
+  scoped_ptr<CustomDrawButton> minimize_button_;
+  scoped_ptr<CustomDrawButton> maximize_button_;
+  scoped_ptr<CustomDrawButton> restore_button_;
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  // The context menu view and model.
+  scoped_ptr<MenuGtk> context_menu_;
+  scoped_ptr<ContextMenuModel> context_menu_model_;
+
+  // The favicon menu view and model.
+  scoped_ptr<MenuGtk> favicon_menu_;
+  scoped_ptr<PopupPageMenuModel> favicon_menu_model_;
+
+  // The throbber used when the window is in app mode or popup window mode.
+  Throbber throbber_;
+
+  // Theme provider for building buttons.
+  GtkThemeProvider* theme_provider_;
+
+  NotificationRegistrar registrar_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BROWSER_TITLEBAR_H_
diff --git a/chrome/browser/ui/gtk/browser_toolbar_gtk.cc b/chrome/browser/ui/gtk/browser_toolbar_gtk.cc
new file mode 100644
index 0000000..d30c8c7
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_toolbar_gtk.cc
@@ -0,0 +1,660 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
+
+#include <X11/XF86keysym.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/singleton.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/background_page_tracker.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/accelerators_gtk.h"
+#include "chrome/browser/ui/gtk/back_forward_button_gtk.h"
+#include "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "chrome/browser/ui/gtk/reload_button_gtk.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
+#include "chrome/browser/upgrade_detector.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/accelerator_gtk.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+namespace {
+
+// Padding on left and right of the left toolbar buttons (back, forward, reload,
+// etc.).
+const int kToolbarLeftAreaPadding = 4;
+
+// Height of the toolbar in pixels (not counting padding).
+const int kToolbarHeight = 29;
+
+// Padding within the toolbar above the buttons and location bar.
+const int kTopBottomPadding = 3;
+
+// Height of the toolbar in pixels when we only show the location bar.
+const int kToolbarHeightLocationBarOnly = kToolbarHeight - 2;
+
+// Interior spacing between toolbar widgets.
+const int kToolbarWidgetSpacing = 1;
+
+// Amount of rounding on top corners of toolbar. Only used in Gtk theme mode.
+const int kToolbarCornerSize = 3;
+
+void SetWidgetHeightRequest(GtkWidget* widget, gpointer user_data) {
+  gtk_widget_set_size_request(widget, -1, GPOINTER_TO_INT(user_data));
+}
+
+}  // namespace
+
+// BrowserToolbarGtk, public ---------------------------------------------------
+
+BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window)
+    : toolbar_(NULL),
+      location_bar_(new LocationBarViewGtk(browser)),
+      model_(browser->toolbar_model()),
+      wrench_menu_model_(this, browser),
+      browser_(browser),
+      window_(window),
+      profile_(NULL) {
+  browser_->command_updater()->AddCommandObserver(IDC_BACK, this);
+  browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
+  browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
+  browser_->command_updater()->AddCommandObserver(IDC_BOOKMARK_PAGE, this);
+
+  registrar_.Add(this,
+                 NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  registrar_.Add(this,
+                 NotificationType::UPGRADE_RECOMMENDED,
+                 NotificationService::AllSources());
+  registrar_.Add(this,
+                 NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED,
+                 NotificationService::AllSources());
+}
+
+BrowserToolbarGtk::~BrowserToolbarGtk() {
+  browser_->command_updater()->RemoveCommandObserver(IDC_BACK, this);
+  browser_->command_updater()->RemoveCommandObserver(IDC_FORWARD, this);
+  browser_->command_updater()->RemoveCommandObserver(IDC_HOME, this);
+  browser_->command_updater()->RemoveCommandObserver(IDC_BOOKMARK_PAGE, this);
+
+  offscreen_entry_.Destroy();
+
+  wrench_menu_.reset();
+}
+
+void BrowserToolbarGtk::Init(Profile* profile,
+                             GtkWindow* top_level_window) {
+  // Make sure to tell the location bar the profile before calling its Init.
+  SetProfile(profile);
+
+  theme_provider_ = GtkThemeProvider::GetFrom(profile);
+  offscreen_entry_.Own(gtk_entry_new());
+
+  show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this);
+  home_page_.Init(prefs::kHomePage, profile->GetPrefs(), this);
+  home_page_is_new_tab_page_.Init(prefs::kHomePageIsNewTabPage,
+                                  profile->GetPrefs(), this);
+
+  event_box_ = gtk_event_box_new();
+  // Make the event box transparent so themes can use transparent toolbar
+  // backgrounds.
+  if (!theme_provider_->UseGtkTheme())
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
+
+  toolbar_ = gtk_hbox_new(FALSE, 0);
+  alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  UpdateForBookmarkBarVisibility(false);
+  g_signal_connect(alignment_, "expose-event",
+                   G_CALLBACK(&OnAlignmentExposeThunk), this);
+  gtk_container_add(GTK_CONTAINER(event_box_), alignment_);
+  gtk_container_add(GTK_CONTAINER(alignment_), toolbar_);
+
+  toolbar_left_ = gtk_hbox_new(FALSE, kToolbarWidgetSpacing);
+
+  back_.reset(new BackForwardButtonGtk(browser_, false));
+  g_signal_connect(back_->widget(), "clicked",
+                   G_CALLBACK(OnButtonClickThunk), this);
+  gtk_box_pack_start(GTK_BOX(toolbar_left_), back_->widget(), FALSE,
+                     FALSE, 0);
+
+  forward_.reset(new BackForwardButtonGtk(browser_, true));
+  g_signal_connect(forward_->widget(), "clicked",
+                   G_CALLBACK(OnButtonClickThunk), this);
+  gtk_box_pack_start(GTK_BOX(toolbar_left_), forward_->widget(), FALSE,
+                     FALSE, 0);
+
+  reload_.reset(new ReloadButtonGtk(location_bar_.get(), browser_));
+  gtk_box_pack_start(GTK_BOX(toolbar_left_), reload_->widget(), FALSE, FALSE,
+                     0);
+
+  home_.reset(new CustomDrawButton(GtkThemeProvider::GetFrom(profile_),
+      IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0, GTK_STOCK_HOME,
+      GTK_ICON_SIZE_SMALL_TOOLBAR));
+  gtk_widget_set_tooltip_text(home_->widget(),
+      l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME).c_str());
+  g_signal_connect(home_->widget(), "clicked",
+                   G_CALLBACK(OnButtonClickThunk), this);
+  gtk_box_pack_start(GTK_BOX(toolbar_left_), home_->widget(), FALSE, FALSE,
+                     kToolbarWidgetSpacing);
+  gtk_util::SetButtonTriggersNavigation(home_->widget());
+
+  gtk_box_pack_start(GTK_BOX(toolbar_), toolbar_left_, FALSE, FALSE,
+                     kToolbarLeftAreaPadding);
+
+  location_hbox_ = gtk_hbox_new(FALSE, 0);
+  location_bar_->Init(ShouldOnlyShowLocation());
+  gtk_box_pack_start(GTK_BOX(location_hbox_), location_bar_->widget(), TRUE,
+                     TRUE, 0);
+
+  g_signal_connect(location_hbox_, "expose-event",
+                   G_CALLBACK(OnLocationHboxExposeThunk), this);
+  gtk_box_pack_start(GTK_BOX(toolbar_), location_hbox_, TRUE, TRUE,
+      ShouldOnlyShowLocation() ? 1 : 0);
+
+  if (!ShouldOnlyShowLocation()) {
+    actions_toolbar_.reset(new BrowserActionsToolbarGtk(browser_));
+    gtk_box_pack_start(GTK_BOX(toolbar_), actions_toolbar_->widget(),
+                       FALSE, FALSE, 0);
+  }
+
+  wrench_menu_image_ = gtk_image_new_from_pixbuf(
+      theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS));
+  wrench_menu_button_.reset(new CustomDrawButton(
+      GtkThemeProvider::GetFrom(profile_),
+      IDR_TOOLS, IDR_TOOLS_P, IDR_TOOLS_H, 0,
+      wrench_menu_image_));
+  GtkWidget* wrench_button = wrench_menu_button_->widget();
+
+  gtk_widget_set_tooltip_text(
+      wrench_button,
+      l10n_util::GetStringFUTF8(IDS_APPMENU_TOOLTIP,
+          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
+  g_signal_connect(wrench_button, "button-press-event",
+                   G_CALLBACK(OnMenuButtonPressEventThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(wrench_button, GTK_CAN_FOCUS);
+
+  // Put the wrench button in a box so that we can paint the update notification
+  // over it.
+  GtkWidget* wrench_box = gtk_alignment_new(0, 0, 1, 1);
+  g_signal_connect_after(wrench_box, "expose-event",
+                         G_CALLBACK(OnWrenchMenuButtonExposeThunk), this);
+  gtk_container_add(GTK_CONTAINER(wrench_box), wrench_button);
+  gtk_box_pack_start(GTK_BOX(toolbar_), wrench_box, FALSE, FALSE, 4);
+
+  wrench_menu_.reset(new MenuGtk(this, &wrench_menu_model_));
+  registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
+                 Source<Profile>(browser_->profile()));
+
+  if (ShouldOnlyShowLocation()) {
+    gtk_widget_show(event_box_);
+    gtk_widget_show(alignment_);
+    gtk_widget_show(toolbar_);
+    gtk_widget_show_all(location_hbox_);
+    gtk_widget_hide(reload_->widget());
+  } else {
+    gtk_widget_show_all(event_box_);
+    if (actions_toolbar_->button_count() == 0)
+      gtk_widget_hide(actions_toolbar_->widget());
+  }
+  // Initialize pref-dependent UI state.
+  NotifyPrefChanged(NULL);
+
+  // Because the above does a recursive show all on all widgets we need to
+  // update the icon visibility to hide them.
+  location_bar_->UpdateContentSettingsIcons();
+
+  SetViewIDs();
+  theme_provider_->InitThemesFor(this);
+}
+
+void BrowserToolbarGtk::SetViewIDs() {
+  ViewIDUtil::SetID(widget(), VIEW_ID_TOOLBAR);
+  ViewIDUtil::SetID(back_->widget(), VIEW_ID_BACK_BUTTON);
+  ViewIDUtil::SetID(forward_->widget(), VIEW_ID_FORWARD_BUTTON);
+  ViewIDUtil::SetID(reload_->widget(), VIEW_ID_RELOAD_BUTTON);
+  ViewIDUtil::SetID(home_->widget(), VIEW_ID_HOME_BUTTON);
+  ViewIDUtil::SetID(location_bar_->widget(), VIEW_ID_LOCATION_BAR);
+  ViewIDUtil::SetID(wrench_menu_button_->widget(), VIEW_ID_APP_MENU);
+}
+
+void BrowserToolbarGtk::Show() {
+  gtk_widget_show(toolbar_);
+}
+
+void BrowserToolbarGtk::Hide() {
+  gtk_widget_hide(toolbar_);
+}
+
+LocationBar* BrowserToolbarGtk::GetLocationBar() const {
+  return location_bar_.get();
+}
+
+void BrowserToolbarGtk::UpdateForBookmarkBarVisibility(
+    bool show_bottom_padding) {
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_),
+      ShouldOnlyShowLocation() ? 0 : kTopBottomPadding,
+      !show_bottom_padding || ShouldOnlyShowLocation() ? 0 : kTopBottomPadding,
+      0, 0);
+}
+
+void BrowserToolbarGtk::ShowAppMenu() {
+  wrench_menu_->Cancel();
+  wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE);
+  UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu"));
+  wrench_menu_->PopupAsFromKeyEvent(wrench_menu_button_->widget());
+}
+
+// CommandUpdater::CommandObserver ---------------------------------------------
+
+void BrowserToolbarGtk::EnabledStateChangedForCommand(int id, bool enabled) {
+  GtkWidget* widget = NULL;
+  switch (id) {
+    case IDC_BACK:
+      widget = back_->widget();
+      break;
+    case IDC_FORWARD:
+      widget = forward_->widget();
+      break;
+    case IDC_HOME:
+      if (home_.get())
+        widget = home_->widget();
+      break;
+  }
+  if (widget) {
+    if (!enabled && GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) {
+      // If we're disabling a widget, GTK will helpfully restore it to its
+      // previous state when we re-enable it, even if that previous state
+      // is the prelight.  This looks bad.  See the bug for a simple repro.
+      // http://code.google.com/p/chromium/issues/detail?id=13729
+      gtk_widget_set_state(widget, GTK_STATE_NORMAL);
+    }
+    gtk_widget_set_sensitive(widget, enabled);
+  }
+}
+
+// MenuGtk::Delegate -----------------------------------------------------------
+
+void BrowserToolbarGtk::StoppedShowing() {
+  // Without these calls, the hover state can get stuck since the leave-notify
+  // event is not sent when clicking a button brings up the menu.
+  gtk_chrome_button_set_hover_state(
+      GTK_CHROME_BUTTON(wrench_menu_button_->widget()), 0.0);
+  wrench_menu_button_->UnsetPaintOverride();
+
+  // Stop showing the BG page badge when we close the wrench menu.
+  BackgroundPageTracker::GetInstance()->AcknowledgeBackgroundPages();
+}
+
+GtkIconSet* BrowserToolbarGtk::GetIconSetForId(int idr) {
+  return theme_provider_->GetIconSetForId(idr);
+}
+
+// Always show images because we desire that some icons always show
+// regardless of the system setting.
+bool BrowserToolbarGtk::AlwaysShowIconForCmd(int command_id) const {
+  return command_id == IDC_UPGRADE_DIALOG ||
+         command_id == IDC_VIEW_BACKGROUND_PAGES;
+}
+
+// ui::AcceleratorProvider
+
+bool BrowserToolbarGtk::GetAcceleratorForCommandId(
+    int id,
+    ui::Accelerator* accelerator) {
+  const ui::AcceleratorGtk* accelerator_gtk =
+      AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(id);
+  if (accelerator_gtk)
+    *accelerator = *accelerator_gtk;
+  return !!accelerator_gtk;
+}
+
+// NotificationObserver --------------------------------------------------------
+
+void BrowserToolbarGtk::Observe(NotificationType type,
+                                const NotificationSource& source,
+                                const NotificationDetails& details) {
+  if (type == NotificationType::PREF_CHANGED) {
+    NotifyPrefChanged(Details<std::string>(details).ptr());
+  } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    // Update the spacing around the menu buttons
+    bool use_gtk = theme_provider_->UseGtkTheme();
+    int border = use_gtk ? 0 : 2;
+    gtk_container_set_border_width(
+        GTK_CONTAINER(wrench_menu_button_->widget()), border);
+
+    // Force the height of the toolbar so we get the right amount of padding
+    // above and below the location bar. We always force the size of the widgets
+    // to either side of the location box, but we only force the location box
+    // size in chrome-theme mode because that's the only time we try to control
+    // the font size.
+    int toolbar_height = ShouldOnlyShowLocation() ?
+                         kToolbarHeightLocationBarOnly : kToolbarHeight;
+    gtk_container_foreach(GTK_CONTAINER(toolbar_), SetWidgetHeightRequest,
+                          GINT_TO_POINTER(toolbar_height));
+    gtk_widget_set_size_request(location_hbox_, -1,
+                                use_gtk ? -1 : toolbar_height);
+
+    // When using the GTK+ theme, we need to have the event box be visible so
+    // buttons don't get a halo color from the background.  When using Chromium
+    // themes, we want to let the background show through the toolbar.
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), use_gtk);
+
+    if (use_gtk) {
+      // We need to manually update the icon if we are in GTK mode. (Note that
+      // we set the initial value in Init()).
+      gtk_image_set_from_pixbuf(
+          GTK_IMAGE(wrench_menu_image_),
+          theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS));
+    }
+
+    UpdateRoundedness();
+  } else if (type == NotificationType::UPGRADE_RECOMMENDED ||
+             type == NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED) {
+    // Redraw the wrench menu to update the badge.
+    gtk_widget_queue_draw(wrench_menu_button_->widget());
+  } else if (type == NotificationType::ZOOM_LEVEL_CHANGED) {
+    // If our zoom level changed, we need to tell the menu to update its state,
+    // since the menu could still be open.
+    wrench_menu_->UpdateMenu();
+  } else {
+    NOTREACHED();
+  }
+}
+
+// BrowserToolbarGtk, public ---------------------------------------------------
+
+void BrowserToolbarGtk::SetProfile(Profile* profile) {
+  if (profile == profile_)
+    return;
+
+  profile_ = profile;
+  location_bar_->SetProfile(profile);
+}
+
+void BrowserToolbarGtk::UpdateTabContents(TabContents* contents,
+                                          bool should_restore_state) {
+  location_bar_->Update(should_restore_state ? contents : NULL);
+
+  if (actions_toolbar_.get())
+    actions_toolbar_->Update();
+}
+
+// BrowserToolbarGtk, private --------------------------------------------------
+
+void BrowserToolbarGtk::SetUpDragForHomeButton(bool enable) {
+  if (enable) {
+    gtk_drag_dest_set(home_->widget(), GTK_DEST_DEFAULT_ALL,
+                      NULL, 0, GDK_ACTION_COPY);
+    static const int targets[] = { ui::TEXT_PLAIN, ui::TEXT_URI_LIST, -1 };
+    ui::SetDestTargetList(home_->widget(), targets);
+
+    drop_handler_.reset(new ui::GtkSignalRegistrar());
+    drop_handler_->Connect(home_->widget(), "drag-data-received",
+                           G_CALLBACK(OnDragDataReceivedThunk), this);
+  } else {
+    gtk_drag_dest_unset(home_->widget());
+    drop_handler_.reset(NULL);
+  }
+}
+
+bool BrowserToolbarGtk::UpdateRoundedness() {
+  // We still round the corners if we are in chrome theme mode, but we do it by
+  // drawing theme resources rather than changing the physical shape of the
+  // widget.
+  bool should_be_rounded = theme_provider_->UseGtkTheme() &&
+      window_->ShouldDrawContentDropShadow();
+
+  if (should_be_rounded == gtk_util::IsActingAsRoundedWindow(alignment_))
+    return false;
+
+  if (should_be_rounded) {
+    gtk_util::ActAsRoundedWindow(alignment_, GdkColor(), kToolbarCornerSize,
+                                 gtk_util::ROUNDED_TOP,
+                                 gtk_util::BORDER_NONE);
+  } else {
+    gtk_util::StopActingAsRoundedWindow(alignment_);
+  }
+
+  return true;
+}
+
+gboolean BrowserToolbarGtk::OnAlignmentExpose(GtkWidget* widget,
+                                              GdkEventExpose* e) {
+  // We may need to update the roundedness of the toolbar's top corners. In
+  // this case, don't draw; we'll be called again soon enough.
+  if (UpdateRoundedness())
+    return TRUE;
+
+  // We don't need to render the toolbar image in GTK mode.
+  if (theme_provider_->UseGtkTheme())
+    return FALSE;
+
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+  gdk_cairo_rectangle(cr, &e->area);
+  cairo_clip(cr);
+
+  gfx::Point tabstrip_origin =
+      window_->tabstrip()->GetTabStripOriginForWidget(widget);
+  // Fill the entire region with the toolbar color.
+  GdkColor color = theme_provider_->GetGdkColor(
+      BrowserThemeProvider::COLOR_TOOLBAR);
+  gdk_cairo_set_source_color(cr, &color);
+  cairo_fill(cr);
+
+  // The horizontal size of the top left and right corner images.
+  const int kCornerWidth = 4;
+  // The thickness of the shadow outside the toolbar's bounds; the offset
+  // between the edge of the toolbar and where we anchor the corner images.
+  const int kShadowThickness = 2;
+
+  gfx::Rect area(e->area);
+  gfx::Rect right(widget->allocation.x + widget->allocation.width -
+                      kCornerWidth,
+                  widget->allocation.y - kShadowThickness,
+                  kCornerWidth,
+                  widget->allocation.height + kShadowThickness);
+  gfx::Rect left(widget->allocation.x - kShadowThickness,
+                 widget->allocation.y - kShadowThickness,
+                 kCornerWidth,
+                 widget->allocation.height + kShadowThickness);
+
+  if (window_->ShouldDrawContentDropShadow()) {
+    // Leave room to draw rounded corners.
+    area = area.Subtract(right).Subtract(left);
+  }
+
+  CairoCachedSurface* background = theme_provider_->GetSurfaceNamed(
+      IDR_THEME_TOOLBAR, widget);
+  background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
+  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+  cairo_rectangle(cr, area.x(), area.y(), area.width(), area.height());
+  cairo_fill(cr);
+
+  if (!window_->ShouldDrawContentDropShadow()) {
+    // The rest of this function is for rounded corners. Our work is done here.
+    cairo_destroy(cr);
+    return FALSE;
+  }
+
+  bool draw_left_corner = left.Intersects(gfx::Rect(e->area));
+  bool draw_right_corner = right.Intersects(gfx::Rect(e->area));
+
+  if (draw_left_corner || draw_right_corner) {
+    // Create a mask which is composed of the left and/or right corners.
+    cairo_surface_t* target = cairo_surface_create_similar(
+        cairo_get_target(cr),
+        CAIRO_CONTENT_COLOR_ALPHA,
+        widget->allocation.x + widget->allocation.width,
+        widget->allocation.y + widget->allocation.height);
+    cairo_t* copy_cr = cairo_create(target);
+
+    cairo_set_operator(copy_cr, CAIRO_OPERATOR_SOURCE);
+    if (draw_left_corner) {
+      CairoCachedSurface* left_corner = theme_provider_->GetSurfaceNamed(
+          IDR_CONTENT_TOP_LEFT_CORNER_MASK, widget);
+      left_corner->SetSource(copy_cr, left.x(), left.y());
+      cairo_paint(copy_cr);
+    }
+    if (draw_right_corner) {
+      CairoCachedSurface* right_corner = theme_provider_->GetSurfaceNamed(
+          IDR_CONTENT_TOP_RIGHT_CORNER_MASK, widget);
+      right_corner->SetSource(copy_cr, right.x(), right.y());
+      // We fill a path rather than just painting because we don't want to
+      // overwrite the left corner.
+      cairo_rectangle(copy_cr, right.x(), right.y(),
+                      right.width(), right.height());
+      cairo_fill(copy_cr);
+    }
+
+    // Draw the background. CAIRO_OPERATOR_IN uses the existing pixel data as
+    // an alpha mask.
+    background->SetSource(copy_cr, tabstrip_origin.x(), tabstrip_origin.y());
+    cairo_set_operator(copy_cr, CAIRO_OPERATOR_IN);
+    cairo_pattern_set_extend(cairo_get_source(copy_cr), CAIRO_EXTEND_REPEAT);
+    cairo_paint(copy_cr);
+    cairo_destroy(copy_cr);
+
+    // Copy the temporary surface to the screen.
+    cairo_set_source_surface(cr, target, 0, 0);
+    cairo_paint(cr);
+    cairo_surface_destroy(target);
+  }
+
+  cairo_destroy(cr);
+
+  return FALSE;  // Allow subwidgets to paint.
+}
+
+gboolean BrowserToolbarGtk::OnLocationHboxExpose(GtkWidget* location_hbox,
+                                                 GdkEventExpose* e) {
+  if (theme_provider_->UseGtkTheme()) {
+    gtk_util::DrawTextEntryBackground(offscreen_entry_.get(),
+                                      location_hbox, &e->area,
+                                      &location_hbox->allocation);
+  }
+
+  return FALSE;
+}
+
+void BrowserToolbarGtk::OnButtonClick(GtkWidget* button) {
+  if ((button == back_->widget()) || (button == forward_->widget())) {
+    if (gtk_util::DispositionForCurrentButtonPressEvent() == CURRENT_TAB)
+      location_bar_->Revert();
+    return;
+  }
+
+  DCHECK(home_.get() && button == home_->widget()) <<
+      "Unexpected button click callback";
+  browser_->Home(gtk_util::DispositionForCurrentButtonPressEvent());
+}
+
+gboolean BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button,
+                                                   GdkEventButton* event) {
+  if (event->button != 1)
+    return FALSE;
+
+  wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE);
+  wrench_menu_->PopupForWidget(button, event->button, event->time);
+
+  return TRUE;
+}
+
+void BrowserToolbarGtk::OnDragDataReceived(GtkWidget* widget,
+    GdkDragContext* drag_context, gint x, gint y,
+    GtkSelectionData* data, guint info, guint time) {
+  if (info != ui::TEXT_PLAIN) {
+    NOTIMPLEMENTED() << "Only support plain text drops for now, sorry!";
+    return;
+  }
+
+  GURL url(reinterpret_cast<char*>(data->data));
+  if (!url.is_valid())
+    return;
+
+  bool url_is_newtab = url.spec() == chrome::kChromeUINewTabURL;
+  home_page_is_new_tab_page_.SetValue(url_is_newtab);
+  if (!url_is_newtab)
+    home_page_.SetValue(url.spec());
+}
+
+void BrowserToolbarGtk::NotifyPrefChanged(const std::string* pref) {
+  if (!pref || *pref == prefs::kShowHomeButton) {
+    if (show_home_button_.GetValue() && !ShouldOnlyShowLocation()) {
+      gtk_widget_show(home_->widget());
+    } else {
+      gtk_widget_hide(home_->widget());
+    }
+  }
+
+  if (!pref ||
+      *pref == prefs::kHomePage ||
+      *pref == prefs::kHomePageIsNewTabPage)
+    SetUpDragForHomeButton(!home_page_.IsManaged() &&
+                           !home_page_is_new_tab_page_.IsManaged());
+}
+
+bool BrowserToolbarGtk::ShouldOnlyShowLocation() const {
+  // If we're a popup window, only show the location bar (omnibox).
+  return browser_->type() != Browser::TYPE_NORMAL;
+}
+
+gboolean BrowserToolbarGtk::OnWrenchMenuButtonExpose(GtkWidget* sender,
+                                                     GdkEventExpose* expose) {
+  const SkBitmap* badge = NULL;
+  if (UpgradeDetector::GetInstance()->notify_upgrade()) {
+    badge = theme_provider_->GetBitmapNamed(IDR_UPDATE_BADGE);
+  } else if (BackgroundPageTracker::GetInstance()->
+             GetUnacknowledgedBackgroundPageCount()) {
+    badge = theme_provider_->GetBitmapNamed(IDR_BACKGROUND_BADGE);
+  } else {
+    return FALSE;
+  }
+
+  // Draw the chrome app menu icon onto the canvas.
+  gfx::CanvasSkiaPaint canvas(expose, false);
+  int x_offset = base::i18n::IsRTL() ? 0 :
+      sender->allocation.width - badge->width();
+  int y_offset = 0;
+  canvas.DrawBitmapInt(
+      *badge,
+      sender->allocation.x + x_offset,
+      sender->allocation.y + y_offset);
+
+  return FALSE;
+}
diff --git a/chrome/browser/ui/gtk/browser_toolbar_gtk.h b/chrome/browser/ui/gtk/browser_toolbar_gtk.h
new file mode 100644
index 0000000..0a03c9b
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_toolbar_gtk.h
@@ -0,0 +1,218 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BROWSER_TOOLBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BROWSER_TOOLBAR_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "ui/base/models/accelerator.h"
+#include "ui/base/models/simple_menu_model.h"
+
+class BackForwardButtonGtk;
+class Browser;
+class BrowserActionsToolbarGtk;
+class BrowserWindowGtk;
+class CustomDrawButton;
+class GtkThemeProvider;
+class LocationBar;
+class LocationBarViewGtk;
+class Profile;
+class ReloadButtonGtk;
+class TabContents;
+class ToolbarModel;
+
+// View class that displays the GTK version of the toolbar and routes gtk
+// events back to the Browser.
+class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
+                          public ui::AcceleratorProvider,
+                          public MenuGtk::Delegate,
+                          public NotificationObserver {
+ public:
+  explicit BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window);
+  virtual ~BrowserToolbarGtk();
+
+  // Create the contents of the toolbar. |top_level_window| is the GtkWindow
+  // to which we attach our accelerators.
+  void Init(Profile* profile, GtkWindow* top_level_window);
+
+  // Set the various widgets' ViewIDs.
+  void SetViewIDs();
+
+  void Show();
+  void Hide();
+
+  // Getter for the containing widget.
+  GtkWidget* widget() {
+    return event_box_;
+  }
+
+  // Getter for associated browser object.
+  Browser* browser() {
+    return browser_;
+  }
+
+  virtual LocationBar* GetLocationBar() const;
+
+  ReloadButtonGtk* GetReloadButton() { return reload_.get(); }
+
+  GtkWidget* GetAppMenuButton() { return wrench_menu_button_->widget(); }
+
+  BrowserActionsToolbarGtk* GetBrowserActionsToolbar() {
+    return actions_toolbar_.get();
+  }
+
+  LocationBarViewGtk* GetLocationBarView() { return location_bar_.get(); }
+
+  // We have to show padding on the bottom of the toolbar when the bookmark
+  // is in floating mode. Otherwise the bookmark bar will paint it for us.
+  void UpdateForBookmarkBarVisibility(bool show_bottom_padding);
+
+  void ShowAppMenu();
+
+  // Overridden from CommandUpdater::CommandObserver:
+  virtual void EnabledStateChangedForCommand(int id, bool enabled);
+
+  // Overridden from MenuGtk::Delegate:
+  virtual void StoppedShowing();
+  virtual GtkIconSet* GetIconSetForId(int idr);
+  virtual bool AlwaysShowIconForCmd(int command_id) const;
+
+  // Overridden from ui::AcceleratorProvider:
+  virtual bool GetAcceleratorForCommandId(int id,
+                                          ui::Accelerator* accelerator);
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  Profile* profile() { return profile_; }
+  void SetProfile(Profile* profile);
+
+  // Message that we should react to a state change.
+  void UpdateTabContents(TabContents* contents, bool should_restore_state);
+
+ private:
+  // Connect/Disconnect signals for dragging a url onto the home button.
+  void SetUpDragForHomeButton(bool enable);
+
+  // Sets the top corners of the toolbar to rounded, or sets them to normal,
+  // depending on the state of the browser window. Returns false if no action
+  // was taken (the roundedness was already correct), true otherwise.
+  bool UpdateRoundedness();
+
+  // Gtk callback for the "expose-event" signal.
+  // The alignment contains the toolbar.
+  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnAlignmentExpose,
+                       GdkEventExpose*);
+  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnLocationHboxExpose,
+                       GdkEventExpose*);
+
+  // Gtk callback for the "clicked" signal.
+  CHROMEGTK_CALLBACK_0(BrowserToolbarGtk, void, OnButtonClick);
+
+  // Gtk callback to intercept mouse clicks to the menu buttons.
+  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnMenuButtonPressEvent,
+                       GdkEventButton*);
+
+  // Used for drags onto home button.
+  CHROMEGTK_CALLBACK_6(BrowserToolbarGtk, void, OnDragDataReceived,
+                       GdkDragContext*, gint, gint, GtkSelectionData*,
+                       guint, guint);
+
+  // Used to draw the upgrade notification badge.
+  CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnWrenchMenuButtonExpose,
+                       GdkEventExpose*);
+
+  // Updates preference-dependent state.
+  void NotifyPrefChanged(const std::string* pref);
+
+  static void SetSyncMenuLabel(GtkWidget* widget, gpointer userdata);
+
+  // Sometimes we only want to show the location w/o the toolbar buttons (e.g.,
+  // in a popup window).
+  bool ShouldOnlyShowLocation() const;
+
+  // An event box that holds |toolbar_|. We need the toolbar to have its own
+  // GdkWindow when we use the GTK drawing because otherwise the color from our
+  // parent GdkWindow will leak through with some theme engines (such as
+  // Clearlooks).
+  GtkWidget* event_box_;
+
+  // This widget handles padding around the outside of the toolbar.
+  GtkWidget* alignment_;
+
+  // Gtk widgets. The toolbar is an hbox with each of the other pieces of the
+  // toolbar placed side by side.
+  GtkWidget* toolbar_;
+
+  // All widgets to the left or right of the |location_hbox_|. We put the
+  // widgets on either side of location_hbox_ in their own toolbar so we can
+  // set their minimum sizes independently of |location_hbox_| which needs to
+  // grow/shrink in GTK+ mode.
+  GtkWidget* toolbar_left_;
+
+  // Contains all the widgets of the location bar.
+  GtkWidget* location_hbox_;
+
+  // The location bar view.
+  scoped_ptr<LocationBarViewGtk> location_bar_;
+
+  // All the buttons in the toolbar.
+  scoped_ptr<BackForwardButtonGtk> back_, forward_;
+  scoped_ptr<CustomDrawButton> home_;
+  scoped_ptr<ReloadButtonGtk> reload_;
+  scoped_ptr<BrowserActionsToolbarGtk> actions_toolbar_;
+  scoped_ptr<CustomDrawButton> wrench_menu_button_;
+
+  // The image shown in GTK+ mode in the wrench button.
+  GtkWidget* wrench_menu_image_;
+
+  // The model that contains the security level, text, icon to display...
+  ToolbarModel* model_;
+
+  GtkThemeProvider* theme_provider_;
+
+  scoped_ptr<MenuGtk> wrench_menu_;
+
+  WrenchMenuModel wrench_menu_model_;
+
+  Browser* browser_;
+  BrowserWindowGtk* window_;
+  Profile* profile_;
+
+  // Controls whether or not a home button should be shown on the toolbar.
+  BooleanPrefMember show_home_button_;
+
+  // Preferences controlling the configured home page.
+  StringPrefMember home_page_;
+  BooleanPrefMember home_page_is_new_tab_page_;
+
+  NotificationRegistrar registrar_;
+
+  // A GtkEntry that isn't part of the hierarchy. We keep this for native
+  // rendering.
+  OwnedWidgetGtk offscreen_entry_;
+
+  // Manages the home button drop signal handler.
+  scoped_ptr<ui::GtkSignalRegistrar> drop_handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowserToolbarGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BROWSER_TOOLBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/browser_window_factory_gtk.cc b/chrome/browser/ui/gtk/browser_window_factory_gtk.cc
new file mode 100644
index 0000000..97d1907
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_window_factory_gtk.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/browser_window.h"
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/find_bar_gtk.h"
+
+BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) {
+  return new BrowserWindowGtk(browser);
+}
+
+FindBar* BrowserWindow::CreateFindBar(Browser* browser) {
+  return new FindBarGtk(browser);
+}
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
new file mode 100644
index 0000000..3a6306b
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -0,0 +1,2256 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/browser_window_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include <string>
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/debugger/devtools_window.h"
+#include "chrome/browser/dom_ui/bug_report_ui.h"
+#include "chrome/browser/download/download_item_model.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/page_info_window.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/gtk/about_chrome_dialog.h"
+#include "chrome/browser/ui/gtk/accelerators_gtk.h"
+#include "chrome/browser/ui/gtk/bookmark_bar_gtk.h"
+#include "chrome/browser/ui/gtk/browser_titlebar.h"
+#include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/collected_cookies_gtk.h"
+#include "chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/download_in_progress_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/download_shelf_gtk.h"
+#include "chrome/browser/ui/gtk/edit_search_engine_dialog.h"
+#include "chrome/browser/ui/gtk/find_bar_gtk.h"
+#include "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_floating_container.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/import_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_container_gtk.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
+#include "chrome/browser/ui/gtk/keyword_editor_view.h"
+#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "chrome/browser/ui/gtk/nine_box.h"
+#include "chrome/browser/ui/gtk/options/content_settings_window_gtk.h"
+#include "chrome/browser/ui/gtk/reload_button_gtk.h"
+#include "chrome/browser/ui/gtk/repost_form_warning_gtk.h"
+#include "chrome/browser/ui/gtk/status_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
+#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+#include "chrome/browser/ui/gtk/task_manager_gtk.h"
+#include "chrome/browser/ui/gtk/theme_install_bubble_view_gtk.h"
+#include "chrome/browser/ui/gtk/update_recommended_dialog.h"
+#include "chrome/browser/ui/omnibox/location_bar.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/window_sizer.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/native_web_keyboard_event.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/skia_utils_gtk.h"
+
+namespace {
+
+// The number of milliseconds between loading animation frames.
+const int kLoadingAnimationFrameTimeMs = 30;
+
+// Default height of dev tools pane when docked to the browser window.  This
+// matches the value in Views.
+const int kDefaultDevToolsHeight = 200;
+
+const int kMinDevToolsHeight = 50;
+
+const char* kBrowserWindowKey = "__BROWSER_WINDOW_GTK__";
+
+// The frame border is only visible in restored mode and is hardcoded to 4 px
+// on each side regardless of the system window border size.
+const int kFrameBorderThickness = 4;
+// While resize areas on Windows are normally the same size as the window
+// borders, our top area is shrunk by 1 px to make it easier to move the window
+// around with our thinner top grabbable strip.  (Incidentally, our side and
+// bottom resize areas don't match the frame border thickness either -- they
+// span the whole nonclient area, so there's no "dead zone" for the mouse.)
+const int kTopResizeAdjust = 1;
+// In the window corners, the resize areas don't actually expand bigger, but
+// the 16 px at the end of each edge triggers diagonal resizing.
+const int kResizeAreaCornerSize = 16;
+// The thickness of the shadow around the toolbar+web content area.  There are
+// actually a couple pixels more that should overlap the toolbar and web
+// content area, but we don't use those pixels.
+const int kContentShadowThickness = 2;
+// The offset to the background when the custom frame is off.  We want the
+// window background to line up with the tab background regardless of whether
+// we're in custom frame mode or not.  Since themes are designed with the
+// custom frame in mind, we need to offset the background when the custom frame
+// is off.
+const int kCustomFrameBackgroundVerticalOffset = 15;
+
+// The timeout in milliseconds before we'll get the true window position with
+// gtk_window_get_position() after the last GTK configure-event signal.
+const int kDebounceTimeoutMilliseconds = 100;
+
+// Using gtk_window_get_position/size creates a race condition, so only use
+// this to get the initial bounds.  After window creation, we pick up the
+// normal bounds by connecting to the configure-event signal.
+gfx::Rect GetInitialWindowBounds(GtkWindow* window) {
+  gint x, y, width, height;
+  gtk_window_get_position(window, &x, &y);
+  gtk_window_get_size(window, &width, &height);
+  return gfx::Rect(x, y, width, height);
+}
+
+// Get the command ids of the key combinations that are not valid gtk
+// accelerators.
+int GetCustomCommandId(GdkEventKey* event) {
+  // Filter modifier to only include accelerator modifiers.
+  guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
+  switch (event->keyval) {
+    // Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see
+    // gtk_accelerator_valid), so we need to handle these accelerators
+    // manually.
+    // Some X clients (e.g. cygwin, NX client, etc.) also send GDK_KP_Tab when
+    // typing a tab key. We should also handle GDK_KP_Tab for such X clients as
+    // Firefox does.
+    case GDK_Tab:
+    case GDK_ISO_Left_Tab:
+    case GDK_KP_Tab:
+      if (GDK_CONTROL_MASK == modifier) {
+        return IDC_SELECT_NEXT_TAB;
+      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
+        return IDC_SELECT_PREVIOUS_TAB;
+      }
+      break;
+
+    default:
+      break;
+  }
+  return -1;
+}
+
+// Get the command ids of the accelerators that we don't want the native widget
+// to be able to override.
+int GetPreHandleCommandId(GdkEventKey* event) {
+  // Filter modifier to only include accelerator modifiers.
+  guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
+  switch (event->keyval) {
+    case GDK_Page_Down:
+      if (GDK_CONTROL_MASK == modifier) {
+        return IDC_SELECT_NEXT_TAB;
+      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
+        return IDC_MOVE_TAB_NEXT;
+      }
+      break;
+
+    case GDK_Page_Up:
+      if (GDK_CONTROL_MASK == modifier) {
+        return IDC_SELECT_PREVIOUS_TAB;
+      } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) {
+        return IDC_MOVE_TAB_PREVIOUS;
+      }
+      break;
+
+    default:
+      break;
+  }
+  return -1;
+}
+
+GdkCursorType GdkWindowEdgeToGdkCursorType(GdkWindowEdge edge) {
+  switch (edge) {
+    case GDK_WINDOW_EDGE_NORTH_WEST:
+      return GDK_TOP_LEFT_CORNER;
+    case GDK_WINDOW_EDGE_NORTH:
+      return GDK_TOP_SIDE;
+    case GDK_WINDOW_EDGE_NORTH_EAST:
+      return GDK_TOP_RIGHT_CORNER;
+    case GDK_WINDOW_EDGE_WEST:
+      return GDK_LEFT_SIDE;
+    case GDK_WINDOW_EDGE_EAST:
+      return GDK_RIGHT_SIDE;
+    case GDK_WINDOW_EDGE_SOUTH_WEST:
+      return GDK_BOTTOM_LEFT_CORNER;
+    case GDK_WINDOW_EDGE_SOUTH:
+      return GDK_BOTTOM_SIDE;
+    case GDK_WINDOW_EDGE_SOUTH_EAST:
+      return GDK_BOTTOM_RIGHT_CORNER;
+    default:
+      NOTREACHED();
+  }
+  return GDK_LAST_CURSOR;
+}
+
+// A helper method for setting the GtkWindow size that should be used in place
+// of calling gtk_window_resize directly.  This is done to avoid a WM "feature"
+// where setting the window size to the monitor size causes the WM to set the
+// EWMH for full screen mode.
+void SetWindowSize(GtkWindow* window, const gfx::Size& size) {
+  GdkScreen* screen = gtk_window_get_screen(window);
+  gint num_monitors = gdk_screen_get_n_monitors(screen);
+  // Make sure the window doesn't match any monitor size.  We compare against
+  // all monitors because we don't know which monitor the window is going to
+  // open on (the WM decides that).
+  for (gint i = 0; i < num_monitors; ++i) {
+    GdkRectangle monitor_size;
+    gdk_screen_get_monitor_geometry(screen, i, &monitor_size);
+    if (gfx::Size(monitor_size.width, monitor_size.height) == size) {
+      gtk_window_resize(window, size.width(), size.height() - 1);
+      return;
+    }
+  }
+  gtk_window_resize(window, size.width(), size.height());
+}
+
+GQuark GetBrowserWindowQuarkKey() {
+  static GQuark quark = g_quark_from_static_string(kBrowserWindowKey);
+  return quark;
+}
+
+}  // namespace
+
+std::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_;
+
+BrowserWindowGtk::BrowserWindowGtk(Browser* browser)
+    :  browser_(browser),
+       state_(GDK_WINDOW_STATE_WITHDRAWN),
+       bookmark_bar_is_floating_(false),
+       frame_cursor_(NULL),
+       is_active_(true),
+       last_click_time_(0),
+       maximize_after_show_(false),
+       suppress_window_raise_(false),
+       accel_group_(NULL),
+       infobar_arrow_model_(this) {
+  // We register first so that other views like the toolbar can use the
+  // is_active() function in their ActiveWindowChanged() handlers.
+  ui::ActiveWindowWatcherX::AddObserver(this);
+
+  use_custom_frame_pref_.Init(prefs::kUseCustomChromeFrame,
+      browser_->profile()->GetPrefs(), this);
+
+  // In some (older) versions of compiz, raising top-level windows when they
+  // are partially off-screen causes them to get snapped back on screen, not
+  // always even on the current virtual desktop.  If we are running under
+  // compiz, suppress such raises, as they are not necessary in compiz anyway.
+  std::string wm_name;
+  if (ui::GetWindowManagerName(&wm_name) && wm_name == "compiz")
+    suppress_window_raise_ = true;
+
+  window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
+  g_object_set_qdata(G_OBJECT(window_), GetBrowserWindowQuarkKey(), this);
+  gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK |
+                                             GDK_POINTER_MOTION_MASK);
+
+  // Add this window to its own unique window group to allow for
+  // window-to-parent modality.
+  gtk_window_group_add_window(gtk_window_group_new(), window_);
+  g_object_unref(gtk_window_get_group(window_));
+
+  // For popups, we initialize widgets then set the window geometry, because
+  // popups need the widgets inited before they can set the window size
+  // properly. For other windows, we set the geometry first to prevent resize
+  // flicker.
+  if (browser_->type() & Browser::TYPE_POPUP) {
+    InitWidgets();
+    SetGeometryHints();
+  } else {
+    SetGeometryHints();
+    InitWidgets();
+  }
+
+  ConnectAccelerators();
+
+  // Set the initial background color of widgets.
+  SetBackgroundColor();
+  HideUnsupportedWindowFeatures();
+
+  registrar_.Add(this, NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
+                 NotificationService::AllSources());
+}
+
+BrowserWindowGtk::~BrowserWindowGtk() {
+  ui::ActiveWindowWatcherX::RemoveObserver(this);
+
+  browser_->tabstrip_model()->RemoveObserver(this);
+}
+
+gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget,
+                                               GdkEventExpose* event) {
+  // Draw the default background.
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+
+  if (UsingCustomPopupFrame()) {
+    DrawPopupFrame(cr, widget, event);
+  } else {
+    DrawCustomFrame(cr, widget, event);
+  }
+
+  DrawContentShadow(cr);
+
+  cairo_destroy(cr);
+
+  if (UseCustomFrame() && !IsMaximized()) {
+    static NineBox custom_frame_border(
+        IDR_WINDOW_TOP_LEFT_CORNER,
+        IDR_WINDOW_TOP_CENTER,
+        IDR_WINDOW_TOP_RIGHT_CORNER,
+        IDR_WINDOW_LEFT_SIDE,
+        0,
+        IDR_WINDOW_RIGHT_SIDE,
+        IDR_WINDOW_BOTTOM_LEFT_CORNER,
+        IDR_WINDOW_BOTTOM_CENTER,
+        IDR_WINDOW_BOTTOM_RIGHT_CORNER);
+
+    custom_frame_border.RenderToWidget(widget);
+  }
+
+  return FALSE;  // Allow subwidgets to paint.
+}
+
+void BrowserWindowGtk::DrawContentShadow(cairo_t* cr) {
+  // Draw the shadow above the toolbar. Tabs on the tabstrip will draw over us.
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
+      browser()->profile());
+  int left_x, top_y;
+  gtk_widget_translate_coordinates(toolbar_->widget(),
+      GTK_WIDGET(window_), 0, 0, &left_x,
+      &top_y);
+  int center_width = window_vbox_->allocation.width;
+
+  CairoCachedSurface* top_center = theme_provider->GetSurfaceNamed(
+      IDR_CONTENT_TOP_CENTER, GTK_WIDGET(window_));
+  CairoCachedSurface* top_right = theme_provider->GetSurfaceNamed(
+      IDR_CONTENT_TOP_RIGHT_CORNER, GTK_WIDGET(window_));
+  CairoCachedSurface* top_left = theme_provider->GetSurfaceNamed(
+      IDR_CONTENT_TOP_LEFT_CORNER, GTK_WIDGET(window_));
+
+  int center_left_x = left_x;
+  if (ShouldDrawContentDropShadow()) {
+    // Don't draw over the corners.
+    center_left_x += top_left->Width() - kContentShadowThickness;
+    center_width -= (top_left->Width() + top_right->Width());
+    center_width += 2 * kContentShadowThickness;
+  }
+
+  top_center->SetSource(cr, center_left_x, top_y - kContentShadowThickness);
+  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+  cairo_rectangle(cr, center_left_x, top_y - kContentShadowThickness,
+                  center_width, top_center->Height());
+  cairo_fill(cr);
+
+  // Only draw the rest of the shadow if the user has the custom frame enabled
+  // and the browser is not maximized.
+  if (!ShouldDrawContentDropShadow())
+    return;
+
+  // The top left corner has a width of 3 pixels. On Windows, the last column
+  // of pixels overlap the toolbar. We just crop it off on Linux.  The top
+  // corners extend to the base of the toolbar (one pixel above the dividing
+  // line).
+  int right_x = center_left_x + center_width;
+  top_left->SetSource(
+      cr, left_x - kContentShadowThickness, top_y - kContentShadowThickness);
+  // The toolbar is shorter in location bar only mode so clip the image to the
+  // height of the toolbar + the amount of shadow above the toolbar.
+  cairo_rectangle(cr,
+      left_x - kContentShadowThickness,
+      top_y - kContentShadowThickness,
+      top_left->Width(),
+      top_left->Height());
+  cairo_fill(cr);
+
+  // Likewise, we crop off the left column of pixels for the top right corner.
+  top_right->SetSource(cr, right_x, top_y - kContentShadowThickness);
+  cairo_rectangle(cr,
+      right_x,
+      top_y - kContentShadowThickness,
+      top_right->Width(),
+      top_right->Height());
+  cairo_fill(cr);
+
+  // Fill in the sides.  As above, we only draw 2 of the 3 columns on Linux.
+  int bottom_y;
+  gtk_widget_translate_coordinates(window_vbox_,
+      GTK_WIDGET(window_),
+      0, window_vbox_->allocation.height,
+      NULL, &bottom_y);
+  // |side_y| is where to start drawing the side shadows.  The top corners draw
+  // the sides down to the bottom of the toolbar.
+  int side_y = top_y - kContentShadowThickness + top_right->Height();
+  // |side_height| is how many pixels to draw for the side borders.  We do one
+  // pixel before the bottom of the web contents because that extra pixel is
+  // drawn by the bottom corners.
+  int side_height = bottom_y - side_y - 1;
+  if (side_height > 0) {
+    CairoCachedSurface* left = theme_provider->GetSurfaceNamed(
+        IDR_CONTENT_LEFT_SIDE, GTK_WIDGET(window_));
+    left->SetSource(cr, left_x - kContentShadowThickness, side_y);
+    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(cr,
+        left_x - kContentShadowThickness,
+        side_y,
+        kContentShadowThickness,
+        side_height);
+    cairo_fill(cr);
+
+    CairoCachedSurface* right = theme_provider->GetSurfaceNamed(
+        IDR_CONTENT_RIGHT_SIDE, GTK_WIDGET(window_));
+    int right_side_x =
+        right_x + top_right->Width() - kContentShadowThickness - 1;
+    right->SetSource(cr, right_side_x, side_y);
+    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(cr,
+        right_side_x,
+        side_y,
+        kContentShadowThickness,
+        side_height);
+    cairo_fill(cr);
+  }
+
+  // Draw the bottom corners.  The bottom corners also draw the bottom row of
+  // pixels of the side shadows.
+  CairoCachedSurface* bottom_left = theme_provider->GetSurfaceNamed(
+      IDR_CONTENT_BOTTOM_LEFT_CORNER, GTK_WIDGET(window_));
+  bottom_left->SetSource(cr, left_x - kContentShadowThickness, bottom_y - 1);
+  cairo_paint(cr);
+
+  CairoCachedSurface* bottom_right = theme_provider->GetSurfaceNamed(
+      IDR_CONTENT_BOTTOM_RIGHT_CORNER, GTK_WIDGET(window_));
+  bottom_right->SetSource(cr, right_x - 1, bottom_y - 1);
+  cairo_paint(cr);
+
+  // Finally, draw the bottom row. Since we don't overlap the contents, we clip
+  // the top row of pixels.
+  CairoCachedSurface* bottom = theme_provider->GetSurfaceNamed(
+      IDR_CONTENT_BOTTOM_CENTER, GTK_WIDGET(window_));
+  bottom->SetSource(cr, left_x + 1, bottom_y - 1);
+  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+  cairo_rectangle(cr,
+      left_x + 1,
+      bottom_y,
+      window_vbox_->allocation.width - 2,
+      kContentShadowThickness);
+  cairo_fill(cr);
+}
+
+void BrowserWindowGtk::DrawPopupFrame(cairo_t* cr,
+                                      GtkWidget* widget,
+                                      GdkEventExpose* event) {
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
+      browser()->profile());
+
+  // Like DrawCustomFrame(), except that we use the unthemed resources to draw
+  // the background. We do this because we can't rely on sane images in the
+  // theme that we can draw text on. (We tried using the tab background, but
+  // that has inverse saturation from what the user usually expects).
+  int image_name = GetThemeFrameResource();
+  CairoCachedSurface* surface = theme_provider->GetUnthemedSurfaceNamed(
+      image_name, widget);
+  surface->SetSource(cr, 0, GetVerticalOffset());
+  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REFLECT);
+  cairo_rectangle(cr, event->area.x, event->area.y,
+                  event->area.width, event->area.height);
+  cairo_fill(cr);
+}
+
+void BrowserWindowGtk::DrawCustomFrame(cairo_t* cr,
+                                       GtkWidget* widget,
+                                       GdkEventExpose* event) {
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
+      browser()->profile());
+
+  int image_name = GetThemeFrameResource();
+
+  CairoCachedSurface* surface = theme_provider->GetSurfaceNamed(
+      image_name, widget);
+  if (event->area.y < surface->Height()) {
+    surface->SetSource(cr, 0, GetVerticalOffset());
+
+    // The frame background isn't tiled vertically.
+    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(cr, event->area.x, event->area.y,
+                    event->area.width, surface->Height() - event->area.y);
+    cairo_fill(cr);
+  }
+
+  if (theme_provider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
+      !browser()->profile()->IsOffTheRecord()) {
+    CairoCachedSurface* theme_overlay = theme_provider->GetSurfaceNamed(
+        IsActive() ? IDR_THEME_FRAME_OVERLAY
+        : IDR_THEME_FRAME_OVERLAY_INACTIVE, widget);
+    theme_overlay->SetSource(cr, 0, GetVerticalOffset());
+    cairo_paint(cr);
+  }
+}
+
+int BrowserWindowGtk::GetVerticalOffset() {
+  return (IsMaximized() || (!UseCustomFrame())) ?
+      -kCustomFrameBackgroundVerticalOffset : 0;
+}
+
+int BrowserWindowGtk::GetThemeFrameResource() {
+  bool off_the_record = browser()->profile()->IsOffTheRecord();
+  int image_name;
+  if (IsActive()) {
+    image_name = off_the_record ? IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
+  } else {
+    image_name = off_the_record ? IDR_THEME_FRAME_INCOGNITO_INACTIVE :
+                 IDR_THEME_FRAME_INACTIVE;
+  }
+
+  return image_name;
+}
+
+void BrowserWindowGtk::Show() {
+  // The Browser associated with this browser window must become the active
+  // browser at the time Show() is called. This is the natural behaviour under
+  // Windows, but gtk_widget_show won't show the widget (and therefore won't
+  // call OnFocusIn()) until we return to the runloop. Therefore any calls to
+  // BrowserList::GetLastActive() (for example, in bookmark_util), will return
+  // the previous browser instead if we don't explicitly set it here.
+  BrowserList::SetLastActive(browser());
+
+  gtk_window_present(window_);
+  if (maximize_after_show_) {
+    gtk_window_maximize(window_);
+    maximize_after_show_ = false;
+  }
+
+  // If we have sized the window by setting a size request for the render
+  // area, then undo it so that the render view can later adjust its own
+  // size.
+  gtk_widget_set_size_request(contents_container_->widget(), -1, -1);
+}
+
+void BrowserWindowGtk::SetBoundsImpl(const gfx::Rect& bounds,
+                                     bool exterior,
+                                     bool move) {
+  gint x = static_cast<gint>(bounds.x());
+  gint y = static_cast<gint>(bounds.y());
+  gint width = static_cast<gint>(bounds.width());
+  gint height = static_cast<gint>(bounds.height());
+
+  if (move)
+    gtk_window_move(window_, x, y);
+
+  if (exterior) {
+    SetWindowSize(window_, gfx::Size(width, height));
+  } else {
+    gtk_widget_set_size_request(contents_container_->widget(),
+                                width, height);
+  }
+}
+
+void BrowserWindowGtk::SetBounds(const gfx::Rect& bounds) {
+  if (IsFullscreen())
+    SetFullscreen(false);
+  SetBoundsImpl(bounds, true, true);
+}
+
+void BrowserWindowGtk::Close() {
+  // We're already closing.  Do nothing.
+  if (!window_)
+    return;
+
+  if (!CanClose())
+    return;
+
+  // We're going to destroy the window, make sure the tab strip isn't running
+  // any animations which may still reference GtkWidgets.
+  tabstrip_->StopAnimation();
+
+  SaveWindowPosition();
+
+  if (accel_group_) {
+    // Disconnecting the keys we connected to our accelerator group frees the
+    // closures allocated in ConnectAccelerators.
+    AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
+    for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
+         iter != accelerators->end(); ++iter) {
+      gtk_accel_group_disconnect_key(accel_group_,
+          iter->second.GetGdkKeyCode(),
+          static_cast<GdkModifierType>(iter->second.modifiers()));
+    }
+    gtk_window_remove_accel_group(window_, accel_group_);
+    g_object_unref(accel_group_);
+    accel_group_ = NULL;
+  }
+
+  // Cancel any pending callback from the window configure debounce timer.
+  window_configure_debounce_timer_.Stop();
+
+  // Likewise for the loading animation.
+  loading_animation_timer_.Stop();
+
+  GtkWidget* window = GTK_WIDGET(window_);
+  // To help catch bugs in any event handlers that might get fired during the
+  // destruction, set window_ to NULL before any handlers will run.
+  window_ = NULL;
+  titlebar_->set_window(NULL);
+  gtk_widget_destroy(window);
+}
+
+void BrowserWindowGtk::Activate() {
+  gtk_window_present(window_);
+}
+
+void BrowserWindowGtk::Deactivate() {
+  gdk_window_lower(GTK_WIDGET(window_)->window);
+}
+
+bool BrowserWindowGtk::IsActive() const {
+  return is_active_;
+}
+
+void BrowserWindowGtk::FlashFrame() {
+  // May not be respected by all window managers.
+  gtk_window_set_urgency_hint(window_, TRUE);
+}
+
+gfx::NativeWindow BrowserWindowGtk::GetNativeHandle() {
+  return window_;
+}
+
+BrowserWindowTesting* BrowserWindowGtk::GetBrowserWindowTesting() {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+StatusBubble* BrowserWindowGtk::GetStatusBubble() {
+  return status_bubble_.get();
+}
+
+void BrowserWindowGtk::SelectedTabToolbarSizeChanged(bool is_animating) {
+  // On Windows, this is used for a performance optimization.
+  // http://code.google.com/p/chromium/issues/detail?id=12291
+}
+
+void BrowserWindowGtk::UpdateTitleBar() {
+  string16 title = browser_->GetWindowTitleForCurrentTab();
+  gtk_window_set_title(window_, UTF16ToUTF8(title).c_str());
+  if (ShouldShowWindowIcon())
+    titlebar_->UpdateTitleAndIcon();
+}
+
+void BrowserWindowGtk::ShelfVisibilityChanged() {
+  MaybeShowBookmarkBar(false);
+}
+
+void BrowserWindowGtk::UpdateDevTools() {
+  UpdateDevToolsForContents(
+      browser_->GetSelectedTabContents());
+}
+
+void BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) {
+  if (should_animate) {
+    if (!loading_animation_timer_.IsRunning()) {
+      // Loads are happening, and the timer isn't running, so start it.
+      loading_animation_timer_.Start(
+          base::TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
+          &BrowserWindowGtk::LoadingAnimationCallback);
+    }
+  } else {
+    if (loading_animation_timer_.IsRunning()) {
+      loading_animation_timer_.Stop();
+      // Loads are now complete, update the state if a task was scheduled.
+      LoadingAnimationCallback();
+    }
+  }
+}
+
+void BrowserWindowGtk::LoadingAnimationCallback() {
+  if (browser_->type() == Browser::TYPE_NORMAL) {
+    // Loading animations are shown in the tab for tabbed windows.  We check the
+    // browser type instead of calling IsTabStripVisible() because the latter
+    // will return false for fullscreen windows, but we still need to update
+    // their animations (so that when they come out of fullscreen mode they'll
+    // be correct).
+    tabstrip_->UpdateLoadingAnimations();
+  } else if (ShouldShowWindowIcon()) {
+    // ... or in the window icon area for popups and app windows.
+    TabContents* tab_contents = browser_->GetSelectedTabContents();
+    // GetSelectedTabContents can return NULL for example under Purify when
+    // the animations are running slowly and this function is called on
+    // a timer through LoadingAnimationCallback.
+    titlebar_->UpdateThrobber(tab_contents);
+  }
+}
+
+void BrowserWindowGtk::SetStarredState(bool is_starred) {
+  toolbar_->GetLocationBarView()->SetStarred(is_starred);
+}
+
+gfx::Rect BrowserWindowGtk::GetRestoredBounds() const {
+  return restored_bounds_;
+}
+
+gfx::Rect BrowserWindowGtk::GetBounds() const {
+  return bounds_;
+}
+
+bool BrowserWindowGtk::IsMaximized() const {
+  return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
+}
+
+bool BrowserWindowGtk::ShouldDrawContentDropShadow() {
+  return !IsMaximized() && UseCustomFrame();
+}
+
+void BrowserWindowGtk::SetFullscreen(bool fullscreen) {
+  // gtk_window_(un)fullscreen asks the window manager to toggle the EWMH
+  // for fullscreen windows.  Not all window managers support this.
+  if (fullscreen) {
+    gtk_window_fullscreen(window_);
+  } else {
+    // Work around a bug where if we try to unfullscreen, metacity immediately
+    // fullscreens us again.  This is a little flickery and not necessary if
+    // there's a gnome-panel, but it's not easy to detect whether there's a
+    // panel or not.
+    std::string wm_name;
+    bool unmaximize_before_unfullscreen = IsMaximized() &&
+        ui::GetWindowManagerName(&wm_name) && wm_name == "Metacity";
+    if (unmaximize_before_unfullscreen)
+      UnMaximize();
+
+    gtk_window_unfullscreen(window_);
+
+    if (unmaximize_before_unfullscreen)
+      gtk_window_maximize(window_);
+  }
+}
+
+bool BrowserWindowGtk::IsFullscreen() const {
+  return (state_ & GDK_WINDOW_STATE_FULLSCREEN);
+}
+
+bool BrowserWindowGtk::IsFullscreenBubbleVisible() const {
+  return fullscreen_exit_bubble_.get() ? true : false;
+}
+
+LocationBar* BrowserWindowGtk::GetLocationBar() const {
+  return toolbar_->GetLocationBar();
+}
+
+void BrowserWindowGtk::SetFocusToLocationBar(bool select_all) {
+  if (!IsFullscreen())
+    GetLocationBar()->FocusLocation(select_all);
+}
+
+void BrowserWindowGtk::UpdateReloadStopState(bool is_loading, bool force) {
+  toolbar_->GetReloadButton()->ChangeMode(
+      is_loading ? ReloadButtonGtk::MODE_STOP : ReloadButtonGtk::MODE_RELOAD,
+      force);
+}
+
+void BrowserWindowGtk::UpdateToolbar(TabContentsWrapper* contents,
+                                     bool should_restore_state) {
+  toolbar_->UpdateTabContents(contents->tab_contents(), should_restore_state);
+}
+
+void BrowserWindowGtk::FocusToolbar() {
+  NOTIMPLEMENTED();
+}
+
+void BrowserWindowGtk::FocusAppMenu() {
+  NOTIMPLEMENTED();
+}
+
+void BrowserWindowGtk::FocusBookmarksToolbar() {
+  NOTIMPLEMENTED();
+}
+
+void BrowserWindowGtk::FocusChromeOSStatus() {
+  NOTIMPLEMENTED();
+}
+
+void BrowserWindowGtk::RotatePaneFocus(bool forwards) {
+  NOTIMPLEMENTED();
+}
+
+bool BrowserWindowGtk::IsBookmarkBarVisible() const {
+  return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR) &&
+      bookmark_bar_.get() &&
+      browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
+}
+
+bool BrowserWindowGtk::IsBookmarkBarAnimating() const {
+  if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
+    return true;
+  return false;
+}
+
+bool BrowserWindowGtk::IsTabStripEditable() const {
+  return !tabstrip()->IsDragSessionActive() &&
+      !tabstrip()->IsActiveDropTarget();
+}
+
+bool BrowserWindowGtk::IsToolbarVisible() const {
+  return IsToolbarSupported();
+}
+
+void BrowserWindowGtk::ConfirmAddSearchProvider(const TemplateURL* template_url,
+                                                Profile* profile) {
+  new EditSearchEngineDialog(window_, template_url, NULL, profile);
+}
+
+void BrowserWindowGtk::ToggleBookmarkBar() {
+  bookmark_utils::ToggleWhenVisible(browser_->profile());
+}
+
+views::Window* BrowserWindowGtk::ShowAboutChromeDialog() {
+  ShowAboutDialogForProfile(window_, browser_->profile());
+  return NULL;
+}
+
+void BrowserWindowGtk::ShowUpdateChromeDialog() {
+  UpdateRecommendedDialog::Show(window_);
+}
+
+void BrowserWindowGtk::ShowTaskManager() {
+  TaskManagerGtk::Show(false);
+}
+
+void BrowserWindowGtk::ShowBackgroundPages() {
+  TaskManagerGtk::Show(true);
+}
+
+void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
+                                          bool already_bookmarked) {
+  toolbar_->GetLocationBarView()->ShowStarBubble(url, !already_bookmarked);
+}
+
+bool BrowserWindowGtk::IsDownloadShelfVisible() const {
+  return download_shelf_.get() && download_shelf_->IsShowing();
+}
+
+DownloadShelf* BrowserWindowGtk::GetDownloadShelf() {
+  if (!download_shelf_.get())
+    download_shelf_.reset(new DownloadShelfGtk(browser_.get(),
+                                               render_area_vbox_));
+  return download_shelf_.get();
+}
+
+void BrowserWindowGtk::ShowClearBrowsingDataDialog() {
+  ClearBrowsingDataDialogGtk::Show(window_, browser_->profile());
+}
+
+void BrowserWindowGtk::ShowImportDialog() {
+  ImportDialogGtk::Show(window_, browser_->profile(), ALL);
+}
+
+void BrowserWindowGtk::ShowSearchEnginesDialog() {
+  KeywordEditorView::Show(browser_->profile());
+}
+
+void BrowserWindowGtk::ShowPasswordManager() {
+  NOTIMPLEMENTED();
+}
+
+void BrowserWindowGtk::ShowRepostFormWarningDialog(TabContents* tab_contents) {
+  new RepostFormWarningGtk(GetNativeHandle(), tab_contents);
+}
+
+void BrowserWindowGtk::ShowContentSettingsWindow(
+    ContentSettingsType content_type,
+    Profile* profile) {
+  ContentSettingsWindowGtk::Show(GetNativeHandle(), content_type, profile);
+}
+
+void BrowserWindowGtk::ShowCollectedCookiesDialog(TabContents* tab_contents) {
+  // Deletes itself on close.
+  new CollectedCookiesGtk(GetNativeHandle(), tab_contents);
+}
+
+void BrowserWindowGtk::ShowProfileErrorDialog(int message_id) {
+  std::string title = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
+  std::string message = l10n_util::GetStringUTF8(message_id);
+  GtkWidget* dialog = gtk_message_dialog_new(window_,
+      static_cast<GtkDialogFlags>(0), GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
+      "%s", message.c_str());
+  gtk_util::ApplyMessageDialogQuirks(dialog);
+  gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
+  g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+  gtk_widget_show_all(dialog);
+}
+
+void BrowserWindowGtk::ShowThemeInstallBubble() {
+  ThemeInstallBubbleViewGtk::Show(window_);
+}
+
+void BrowserWindowGtk::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
+                                      gfx::NativeWindow parent_window) {
+  browser::ShowHtmlDialog(parent_window, browser_->profile(), delegate);
+}
+
+void BrowserWindowGtk::UserChangedTheme() {
+  SetBackgroundColor();
+  gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
+      &GTK_WIDGET(window_)->allocation, TRUE);
+  UpdateWindowShape(bounds_.width(), bounds_.height());
+}
+
+int BrowserWindowGtk::GetExtraRenderViewHeight() const {
+  int sum = infobar_container_->TotalHeightOfAnimatingBars();
+  if (IsBookmarkBarSupported() && bookmark_bar_->IsAnimating())
+    sum += bookmark_bar_->GetHeight();
+  if (download_shelf_.get() && download_shelf_->IsClosing())
+    sum += download_shelf_->GetHeight();
+  return sum;
+}
+
+void BrowserWindowGtk::TabContentsFocused(TabContents* tab_contents) {
+  NOTIMPLEMENTED();
+}
+
+void BrowserWindowGtk::ShowPageInfo(Profile* profile,
+                                    const GURL& url,
+                                    const NavigationEntry::SSLStatus& ssl,
+                                    bool show_history) {
+  browser::ShowPageInfoBubble(window_, profile, url, ssl, show_history);
+}
+
+void BrowserWindowGtk::ShowAppMenu() {
+  toolbar_->ShowAppMenu();
+}
+
+bool BrowserWindowGtk::PreHandleKeyboardEvent(
+    const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
+  GdkEventKey* os_event = event.os_event;
+
+  if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown)
+    return false;
+
+  // We first find out the browser command associated to the |event|.
+  // Then if the command is a reserved one, and should be processed immediately
+  // according to the |event|, the command will be executed immediately.
+  // Otherwise we just set |*is_keyboard_shortcut| properly and return false.
+
+  // First check if it's a custom accelerator.
+  int id = GetCustomCommandId(os_event);
+
+  // Then check if it's a predefined accelerator bound to the window.
+  if (id == -1) {
+    // This piece of code is based on the fact that calling
+    // gtk_window_activate_key() method against |window_| may only trigger a
+    // browser command execution, by matching a global accelerator
+    // defined in above |kAcceleratorMap|.
+    //
+    // Here we need to retrieve the command id (if any) associated to the
+    // keyboard event. Instead of looking up the command id in above
+    // |kAcceleratorMap| table by ourselves, we block the command execution of
+    // the |browser_| object then send the keyboard event to the |window_| by
+    // calling gtk_window_activate_key() method, as if we are activating an
+    // accelerator key. Then we can retrieve the command id from the
+    // |browser_| object.
+    //
+    // Pros of this approach:
+    // 1. We don't need to care about keyboard layout problem, as
+    //    gtk_window_activate_key() method handles it for us.
+    //
+    // Cons:
+    // 1. The logic is a little complicated.
+    // 2. We should be careful not to introduce any accelerators that trigger
+    //    customized code instead of browser commands.
+    browser_->SetBlockCommandExecution(true);
+    gtk_window_activate_key(window_, os_event);
+    // We don't need to care about the WindowOpenDisposition value,
+    // because all commands executed in this path use the default value.
+    id = browser_->GetLastBlockedCommand(NULL);
+    browser_->SetBlockCommandExecution(false);
+  }
+
+  if (id == -1)
+    return false;
+
+  // Executing the command may cause |this| object to be destroyed.
+  if (browser_->IsReservedCommandOrKey(id, event) && !event.match_edit_command)
+    return browser_->ExecuteCommandIfEnabled(id);
+
+  // The |event| is a keyboard shortcut.
+  DCHECK(is_keyboard_shortcut != NULL);
+  *is_keyboard_shortcut = true;
+
+  return false;
+}
+
+void BrowserWindowGtk::HandleKeyboardEvent(
+    const NativeWebKeyboardEvent& event) {
+  GdkEventKey* os_event = event.os_event;
+
+  if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown)
+    return;
+
+  // Handles a key event in following sequence:
+  // 1. Our special key accelerators, such as ctrl-tab, etc.
+  // 2. Gtk accelerators.
+  // This sequence matches the default key press handler of GtkWindow.
+  //
+  // It's not necessary to care about the keyboard layout, as
+  // gtk_window_activate_key() takes care of it automatically.
+  int id = GetCustomCommandId(os_event);
+  if (id != -1)
+    browser_->ExecuteCommandIfEnabled(id);
+  else
+    gtk_window_activate_key(window_, os_event);
+}
+
+void BrowserWindowGtk::ShowCreateWebAppShortcutsDialog(
+    TabContents* tab_contents) {
+  CreateWebApplicationShortcutsDialogGtk::Show(window_, tab_contents);
+}
+
+void BrowserWindowGtk::ShowCreateChromeAppShortcutsDialog(
+    Profile* profile, const Extension* app) {
+  CreateChromeApplicationShortcutsDialogGtk::Show(window_, app);
+}
+
+void BrowserWindowGtk::Cut() {
+  gtk_util::DoCut(this);
+}
+
+void BrowserWindowGtk::Copy() {
+  gtk_util::DoCopy(this);
+}
+
+void BrowserWindowGtk::Paste() {
+  gtk_util::DoPaste(this);
+}
+
+void BrowserWindowGtk::PrepareForInstant() {
+  TabContents* contents = contents_container_->GetTabContents();
+  if (contents)
+    contents->FadeForInstant(true);
+}
+
+void BrowserWindowGtk::ShowInstant(TabContents* preview_contents) {
+  contents_container_->SetPreviewContents(preview_contents);
+  MaybeShowBookmarkBar(false);
+
+  TabContents* contents = contents_container_->GetTabContents();
+  if (contents)
+    contents->CancelInstantFade();
+}
+
+void BrowserWindowGtk::HideInstant(bool instant_is_active) {
+  contents_container_->PopPreviewContents();
+  MaybeShowBookmarkBar(false);
+
+  TabContents* contents = contents_container_->GetTabContents();
+  if (contents) {
+    if (instant_is_active)
+      contents->FadeForInstant(false);
+    else
+      contents->CancelInstantFade();
+  }
+}
+
+gfx::Rect BrowserWindowGtk::GetInstantBounds() {
+  return gtk_util::GetWidgetScreenBounds(contents_container_->widget());
+}
+
+void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
+  new DownloadInProgressDialogGtk(browser());
+}
+
+void BrowserWindowGtk::Observe(NotificationType type,
+                               const NotificationSource& source,
+                               const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED:
+      MaybeShowBookmarkBar(true);
+      break;
+
+    case NotificationType::PREF_CHANGED: {
+      std::string* pref_name = Details<std::string>(details).ptr();
+      if (*pref_name == prefs::kUseCustomChromeFrame) {
+        UpdateCustomFrame();
+      } else {
+        NOTREACHED() << "Got pref change notification we didn't register for!";
+      }
+      break;
+    }
+
+    default:
+      NOTREACHED() << "Got a notification we didn't register for!";
+  }
+}
+
+void BrowserWindowGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
+  // We use index here rather than comparing |contents| because by this time
+  // the model has already removed |contents| from its list, so
+  // browser_->GetSelectedTabContents() will return NULL or something else.
+  if (index == browser_->tabstrip_model()->selected_index())
+    infobar_container_->ChangeTabContents(NULL);
+  contents_container_->DetachTabContents(contents->tab_contents());
+  UpdateDevToolsForContents(NULL);
+}
+
+void BrowserWindowGtk::TabSelectedAt(TabContentsWrapper* old_contents,
+                                     TabContentsWrapper* new_contents,
+                                     int index,
+                                     bool user_gesture) {
+  DCHECK(old_contents != new_contents);
+
+  if (old_contents && !old_contents->tab_contents()->is_being_destroyed())
+    old_contents->view()->StoreFocus();
+
+  // Update various elements that are interested in knowing the current
+  // TabContents.
+  infobar_container_->ChangeTabContents(new_contents->tab_contents());
+  contents_container_->SetTabContents(new_contents->tab_contents());
+  UpdateDevToolsForContents(new_contents->tab_contents());
+
+  new_contents->tab_contents()->DidBecomeSelected();
+  // TODO(estade): after we manage browser activation, add a check to make sure
+  // we are the active browser before calling RestoreFocus().
+  if (!browser_->tabstrip_model()->closing_all()) {
+    new_contents->view()->RestoreFocus();
+    if (new_contents->GetFindManager()->find_ui_active())
+      browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
+  }
+
+  // Update all the UI bits.
+  UpdateTitleBar();
+  UpdateToolbar(new_contents, true);
+  MaybeShowBookmarkBar(false);
+}
+
+void BrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
+  // Do nothing if we're in the process of closing the browser window.
+  if (!window_)
+    return;
+
+  bool is_active = (GTK_WIDGET(window_)->window == active_window);
+  bool changed = (is_active != is_active_);
+
+  if (is_active && changed) {
+    // If there's an app modal dialog (e.g., JS alert), try to redirect
+    // the user's attention to the window owning the dialog.
+    if (AppModalDialogQueue::GetInstance()->HasActiveDialog()) {
+      AppModalDialogQueue::GetInstance()->ActivateModalDialog();
+      return;
+    }
+  }
+
+  is_active_ = is_active;
+  if (changed) {
+    SetBackgroundColor();
+    gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
+                               &GTK_WIDGET(window_)->allocation, TRUE);
+    // For some reason, the above two calls cause the window shape to be
+    // lost so reset it.
+    UpdateWindowShape(bounds_.width(), bounds_.height());
+  }
+}
+
+void BrowserWindowGtk::MaybeShowBookmarkBar(bool animate) {
+  if (!IsBookmarkBarSupported())
+    return;
+
+  TabContents* contents = GetDisplayedTabContents();
+  bool show_bar = false;
+
+  if (IsBookmarkBarSupported() && contents) {
+    bookmark_bar_->SetProfile(contents->profile());
+    bookmark_bar_->SetPageNavigator(contents);
+    show_bar = true;
+  }
+
+  if (show_bar && contents && !contents->ShouldShowBookmarkBar()) {
+    PrefService* prefs = contents->profile()->GetPrefs();
+    show_bar = prefs->GetBoolean(prefs::kShowBookmarkBar) && !IsFullscreen();
+  }
+
+  if (show_bar) {
+    bookmark_bar_->Show(animate);
+  } else if (IsFullscreen()) {
+    bookmark_bar_->EnterFullscreen();
+  } else {
+    bookmark_bar_->Hide(animate);
+  }
+}
+
+void BrowserWindowGtk::UpdateDevToolsForContents(TabContents* contents) {
+  TabContents* old_devtools = devtools_container_->GetTabContents();
+  TabContents* devtools_contents = contents ?
+      DevToolsWindow::GetDevToolsContents(contents) : NULL;
+  if (old_devtools == devtools_contents)
+    return;
+
+  if (old_devtools)
+    devtools_container_->DetachTabContents(old_devtools);
+
+  devtools_container_->SetTabContents(devtools_contents);
+  if (devtools_contents) {
+    // TabContentsViewGtk::WasShown is not called when tab contents is shown by
+    // anything other than user selecting a Tab.
+    // See TabContentsViewWin::OnWindowPosChanged for reference on how it should
+    // be implemented.
+    devtools_contents->ShowContents();
+  }
+
+  bool should_show = old_devtools == NULL && devtools_contents != NULL;
+  bool should_hide = old_devtools != NULL && devtools_contents == NULL;
+  if (should_show) {
+    gtk_widget_show(devtools_container_->widget());
+  } else if (should_hide) {
+    // Store split offset when hiding devtools window only.
+    gint divider_offset = gtk_paned_get_position(GTK_PANED(contents_split_));
+    browser_->profile()->GetPrefs()->
+        SetInteger(prefs::kDevToolsSplitLocation, divider_offset);
+    gtk_widget_hide(devtools_container_->widget());
+  }
+}
+
+void BrowserWindowGtk::DestroyBrowser() {
+  browser_.reset();
+}
+
+gboolean BrowserWindowGtk::OnConfigure(GtkWidget* widget,
+                                       GdkEventConfigure* event) {
+  gfx::Rect bounds(event->x, event->y, event->width, event->height);
+
+  // When the window moves, we'll get multiple configure-event signals. We can
+  // also get events when the bounds haven't changed, but the window's stacking
+  // has, which we aren't interested in. http://crbug.com/70125
+  if (bounds == bounds_)
+    return FALSE;
+
+  GetLocationBar()->location_entry()->ClosePopup();
+
+  TabContents* tab_contents = GetDisplayedTabContents();
+  if (tab_contents)
+    tab_contents->WindowMoveOrResizeStarted();
+
+  if (bounds_.size() != bounds.size())
+    OnSizeChanged(bounds.width(), bounds.height());
+
+  // We update |bounds_| but not |restored_bounds_| here.  The latter needs
+  // to be updated conditionally when the window is non-maximized and non-
+  // fullscreen, but whether those state updates have been processed yet is
+  // window-manager specific.  We update |restored_bounds_| in the debounced
+  // handler below, after the window state has been updated.
+  bounds_ = bounds;
+
+  // The GdkEventConfigure* we get here doesn't have quite the right
+  // coordinates though (they're relative to the drawable window area, rather
+  // than any window manager decorations, if enabled), so we need to call
+  // gtk_window_get_position() to get the right values.  (Otherwise session
+  // restore, if enabled, will restore windows to incorrect positions.)  That's
+  // a round trip to the X server though, so we set a debounce timer and only
+  // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a
+  // reconfigure event in a short while.
+  // We don't use Reset() because the timer may not yet be running.
+  // (In that case Stop() is a no-op.)
+  window_configure_debounce_timer_.Stop();
+  window_configure_debounce_timer_.Start(base::TimeDelta::FromMilliseconds(
+      kDebounceTimeoutMilliseconds), this,
+      &BrowserWindowGtk::OnDebouncedBoundsChanged);
+
+  return FALSE;
+}
+
+void BrowserWindowGtk::OnDebouncedBoundsChanged() {
+  gint x, y;
+  gtk_window_get_position(window_, &x, &y);
+  gfx::Point origin(x, y);
+  bounds_.set_origin(origin);
+  if (!IsFullscreen() && !IsMaximized())
+    restored_bounds_ = bounds_;
+  SaveWindowPosition();
+}
+
+gboolean BrowserWindowGtk::OnWindowState(GtkWidget* sender,
+                                         GdkEventWindowState* event) {
+  state_ = event->new_window_state;
+
+  if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+    bool is_fullscreen = state_ & GDK_WINDOW_STATE_FULLSCREEN;
+    browser_->UpdateCommandsForFullscreenMode(is_fullscreen);
+    if (is_fullscreen) {
+      UpdateCustomFrame();
+      toolbar_->Hide();
+      tabstrip_->Hide();
+      if (IsBookmarkBarSupported())
+        bookmark_bar_->EnterFullscreen();
+      bool is_kiosk =
+          CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
+      if (!is_kiosk) {
+        fullscreen_exit_bubble_.reset(new FullscreenExitBubbleGtk(
+            GTK_FLOATING_CONTAINER(render_area_floating_container_)));
+      }
+      gtk_widget_hide(toolbar_border_);
+    } else {
+      fullscreen_exit_bubble_.reset();
+      UpdateCustomFrame();
+      ShowSupportedWindowFeatures();
+    }
+  }
+
+  UpdateWindowShape(bounds_.width(), bounds_.height());
+  SaveWindowPosition();
+  return FALSE;
+}
+
+// Callback for the delete event.  This event is fired when the user tries to
+// close the window (e.g., clicking on the X in the window manager title bar).
+gboolean BrowserWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget,
+                                                   GdkEvent* event) {
+  Close();
+
+  // Return true to prevent the gtk window from being destroyed.  Close will
+  // destroy it for us.
+  return TRUE;
+}
+
+void BrowserWindowGtk::OnMainWindowDestroy(GtkWidget* widget) {
+  // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the
+  // signal right away, and we will be here (while Close() is still in the
+  // call stack).  In order to not reenter Close(), and to also follow the
+  // expectations of BrowserList, we should run the BrowserWindowGtk destructor
+  // not now, but after the run loop goes back to process messages.  Otherwise
+  // we will remove ourself from BrowserList while it's being iterated.
+  // Additionally, now that we know the window is gone, we need to make sure to
+  // set window_ to NULL, otherwise we will try to close the window again when
+  // we call Close() in the destructor.
+  //
+  // We don't want to use DeleteSoon() here since it won't work on a nested pump
+  // (like in UI tests).
+  MessageLoop::current()->PostTask(FROM_HERE,
+                                   new DeleteTask<BrowserWindowGtk>(this));
+}
+
+void BrowserWindowGtk::UnMaximize() {
+  gtk_window_unmaximize(window_);
+
+  // It can happen that you end up with a window whose restore size is the same
+  // as the size of the screen, so unmaximizing it merely remaximizes it due to
+  // the same WM feature that SetWindowSize() works around.  We try to detect
+  // this and resize the window to work around the issue.
+  if (bounds_.size() == restored_bounds_.size())
+    gtk_window_resize(window_, bounds_.width(), bounds_.height() - 1);
+}
+
+bool BrowserWindowGtk::CanClose() const {
+  // You cannot close a frame for which there is an active originating drag
+  // session.
+  if (tabstrip_->IsDragSessionActive())
+    return false;
+
+  // Give beforeunload handlers the chance to cancel the close before we hide
+  // the window below.
+  if (!browser_->ShouldCloseWindow())
+    return false;
+
+  if (!browser_->tabstrip_model()->empty()) {
+    // Tab strip isn't empty.  Hide the window (so it appears to have closed
+    // immediately) and close all the tabs, allowing the renderers to shut
+    // down. When the tab strip is empty we'll be called back again.
+    gtk_widget_hide(GTK_WIDGET(window_));
+    browser_->OnWindowClosing();
+    return false;
+  }
+
+  // Empty TabStripModel, it's now safe to allow the Window to be closed.
+  NotificationService::current()->Notify(
+      NotificationType::WINDOW_CLOSED,
+      Source<GtkWindow>(window_),
+      NotificationService::NoDetails());
+  return true;
+}
+
+bool BrowserWindowGtk::ShouldShowWindowIcon() const {
+  return browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
+}
+
+void BrowserWindowGtk::AddFindBar(FindBarGtk* findbar) {
+  gtk_floating_container_add_floating(
+      GTK_FLOATING_CONTAINER(render_area_floating_container_),
+      findbar->widget());
+}
+
+void BrowserWindowGtk::ResetCustomFrameCursor() {
+  if (!frame_cursor_)
+    return;
+
+  frame_cursor_ = NULL;
+  gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL);
+}
+
+// static
+BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow(
+    gfx::NativeWindow window) {
+  if (window) {
+    return static_cast<BrowserWindowGtk*>(
+        g_object_get_qdata(G_OBJECT(window), GetBrowserWindowQuarkKey()));
+  }
+
+  return NULL;
+}
+
+// static
+GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) {
+  std::map<XID, GtkWindow*>::iterator iter =
+      BrowserWindowGtk::xid_map_.find(xid);
+  return (iter != BrowserWindowGtk::xid_map_.end()) ? iter->second : NULL;
+}
+
+// static
+void BrowserWindowGtk::RegisterUserPrefs(PrefService* prefs) {
+  bool custom_frame_default = false;
+  // Avoid checking the window manager if we're not connected to an X server (as
+  // is the case in Valgrind tests).
+  if (ui::XDisplayExists() &&
+      !prefs->HasPrefPath(prefs::kUseCustomChromeFrame)) {
+    custom_frame_default = GetCustomFramePrefDefault();
+  }
+  prefs->RegisterBooleanPref(
+      prefs::kUseCustomChromeFrame, custom_frame_default);
+}
+
+void BrowserWindowGtk::BookmarkBarIsFloating(bool is_floating) {
+  bookmark_bar_is_floating_ = is_floating;
+  toolbar_->UpdateForBookmarkBarVisibility(is_floating);
+
+  // This can be NULL during initialization of the bookmark bar.
+  if (bookmark_bar_.get())
+    PlaceBookmarkBar(is_floating);
+}
+
+TabContents* BrowserWindowGtk::GetDisplayedTabContents() {
+  return contents_container_->GetVisibleTabContents();
+}
+
+void BrowserWindowGtk::QueueToolbarRedraw() {
+  gtk_widget_queue_draw(toolbar_->widget());
+}
+
+void BrowserWindowGtk::SetGeometryHints() {
+  // If we call gtk_window_maximize followed by gtk_window_present, compiz gets
+  // confused and maximizes the window, but doesn't set the
+  // GDK_WINDOW_STATE_MAXIMIZED bit.  So instead, we keep track of whether to
+  // maximize and call it after gtk_window_present.
+  maximize_after_show_ = browser_->GetSavedMaximizedState();
+
+  gfx::Rect bounds = browser_->GetSavedWindowBounds();
+  // We don't blindly call SetBounds here: that sets a forced position
+  // on the window and we intentionally *don't* do that for normal
+  // windows.  Most programs do not restore their window position on
+  // Linux, instead letting the window manager choose a position.
+  //
+  // However, in cases like dropping a tab where the bounds are
+  // specifically set, we do want to position explicitly.  We also
+  // force the position as part of session restore, as applications
+  // that restore other, similar state (for instance GIMP, audacity,
+  // pidgin, dia, and gkrellm) do tend to restore their positions.
+  //
+  // For popup windows, we assume that if x == y == 0, the opening page
+  // did not specify a position.  Let the WM position the popup instead.
+  bool is_popup = browser_->type() & Browser::TYPE_POPUP;
+  bool popup_without_position = is_popup &&
+      bounds.x() == 0 && bounds.y() == 0;
+  bool move = browser_->bounds_overridden() && !popup_without_position;
+  SetBoundsImpl(bounds, !is_popup, move);
+}
+
+void BrowserWindowGtk::ConnectHandlersToSignals() {
+  g_signal_connect(window_, "delete-event",
+                   G_CALLBACK(OnMainWindowDeleteEventThunk), this);
+  g_signal_connect(window_, "destroy",
+                   G_CALLBACK(OnMainWindowDestroyThunk), this);
+  g_signal_connect(window_, "configure-event",
+                   G_CALLBACK(OnConfigureThunk), this);
+  g_signal_connect(window_, "window-state-event",
+                   G_CALLBACK(OnWindowStateThunk), this);
+  g_signal_connect(window_, "map",
+                   G_CALLBACK(MainWindowMapped), NULL);
+  g_signal_connect(window_, "unmap",
+                   G_CALLBACK(MainWindowUnMapped), NULL);
+  g_signal_connect(window_, "key-press-event",
+                   G_CALLBACK(OnKeyPressThunk), this);
+  g_signal_connect(window_, "motion-notify-event",
+                   G_CALLBACK(OnMouseMoveEventThunk), this);
+  g_signal_connect(window_, "button-press-event",
+                   G_CALLBACK(OnButtonPressEventThunk), this);
+  g_signal_connect(window_, "focus-in-event",
+                   G_CALLBACK(OnFocusInThunk), this);
+  g_signal_connect(window_, "focus-out-event",
+                   G_CALLBACK(OnFocusOutThunk), this);
+}
+
+void BrowserWindowGtk::InitWidgets() {
+  ConnectHandlersToSignals();
+  bounds_ = restored_bounds_ = GetInitialWindowBounds(window_);
+
+  // This vbox encompasses all of the widgets within the browser.  This is
+  // everything except the custom frame border.
+  window_vbox_ = gtk_vbox_new(FALSE, 0);
+  gtk_widget_show(window_vbox_);
+
+  // The window container draws the custom browser frame.
+  window_container_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_widget_set_name(window_container_, "chrome-custom-frame-border");
+  gtk_widget_set_app_paintable(window_container_, TRUE);
+  gtk_widget_set_double_buffered(window_container_, FALSE);
+  gtk_widget_set_redraw_on_allocate(window_container_, TRUE);
+  g_signal_connect(window_container_, "expose-event",
+                   G_CALLBACK(OnCustomFrameExposeThunk), this);
+  gtk_container_add(GTK_CONTAINER(window_container_), window_vbox_);
+
+  tabstrip_.reset(new TabStripGtk(browser_->tabstrip_model(), this));
+  tabstrip_->Init();
+
+  // Build the titlebar (tabstrip + header space + min/max/close buttons).
+  titlebar_.reset(new BrowserTitlebar(this, window_));
+
+  // Insert the tabstrip into the window.
+  gtk_box_pack_start(GTK_BOX(window_vbox_), titlebar_->widget(), FALSE, FALSE,
+                     0);
+
+  toolbar_.reset(new BrowserToolbarGtk(browser_.get(), this));
+  toolbar_->Init(browser_->profile(), window_);
+  gtk_box_pack_start(GTK_BOX(window_vbox_), toolbar_->widget(),
+                     FALSE, FALSE, 0);
+  g_signal_connect_after(toolbar_->widget(), "expose-event",
+                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
+  // This vbox surrounds the render area: find bar, info bars and render view.
+  // The reason is that this area as a whole needs to be grouped in its own
+  // GdkWindow hierarchy so that animations originating inside it (infobar,
+  // download shelf, find bar) are all clipped to that area. This is why
+  // |render_area_vbox_| is packed in |render_area_event_box_|.
+  render_area_vbox_ = gtk_vbox_new(FALSE, 0);
+  gtk_widget_set_name(render_area_vbox_, "chrome-render-area-vbox");
+  render_area_floating_container_ = gtk_floating_container_new();
+  gtk_container_add(GTK_CONTAINER(render_area_floating_container_),
+                    render_area_vbox_);
+
+  GtkWidget* location_icon = toolbar_->GetLocationBarView()->
+      location_icon_widget();
+  g_signal_connect(location_icon, "size-allocate",
+                   G_CALLBACK(OnLocationIconSizeAllocateThunk), this);
+  g_signal_connect_after(location_icon, "expose-event",
+                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
+
+  toolbar_border_ = gtk_event_box_new();
+  gtk_box_pack_start(GTK_BOX(render_area_vbox_),
+                     toolbar_border_, FALSE, FALSE, 0);
+  gtk_widget_set_size_request(toolbar_border_, -1, 1);
+  gtk_widget_set_no_show_all(toolbar_border_, TRUE);
+  g_signal_connect_after(toolbar_border_, "expose-event",
+                         G_CALLBACK(OnExposeDrawInfobarBitsThunk), this);
+
+  if (IsToolbarSupported())
+    gtk_widget_show(toolbar_border_);
+
+  infobar_container_.reset(new InfoBarContainerGtk(browser_->profile()));
+  gtk_box_pack_start(GTK_BOX(render_area_vbox_),
+                     infobar_container_->widget(),
+                     FALSE, FALSE, 0);
+
+  status_bubble_.reset(new StatusBubbleGtk(browser_->profile()));
+
+  contents_container_.reset(new TabContentsContainerGtk(status_bubble_.get()));
+  devtools_container_.reset(new TabContentsContainerGtk(NULL));
+  ViewIDUtil::SetID(devtools_container_->widget(), VIEW_ID_DEV_TOOLS_DOCKED);
+  contents_split_ = gtk_vpaned_new();
+  gtk_paned_pack1(GTK_PANED(contents_split_), contents_container_->widget(),
+                  TRUE, TRUE);
+  gtk_paned_pack2(GTK_PANED(contents_split_), devtools_container_->widget(),
+                  FALSE, TRUE);
+  gtk_box_pack_end(GTK_BOX(render_area_vbox_), contents_split_, TRUE, TRUE, 0);
+  // Restore split offset.
+  int split_offset = browser_->profile()->GetPrefs()->
+      GetInteger(prefs::kDevToolsSplitLocation);
+  if (split_offset != -1) {
+    if (split_offset < kMinDevToolsHeight)
+      split_offset = kMinDevToolsHeight;
+    gtk_paned_set_position(GTK_PANED(contents_split_), split_offset);
+  } else {
+    gtk_widget_set_size_request(devtools_container_->widget(), -1,
+                                kDefaultDevToolsHeight);
+  }
+  gtk_widget_show_all(render_area_floating_container_);
+  gtk_widget_hide(devtools_container_->widget());
+  render_area_event_box_ = gtk_event_box_new();
+  // Set a white background so during startup the user sees white in the
+  // content area before we get a TabContents in place.
+  gtk_widget_modify_bg(render_area_event_box_, GTK_STATE_NORMAL,
+                       &gtk_util::kGdkWhite);
+  gtk_container_add(GTK_CONTAINER(render_area_event_box_),
+                    render_area_floating_container_);
+  gtk_widget_show(render_area_event_box_);
+  gtk_box_pack_end(GTK_BOX(window_vbox_), render_area_event_box_,
+                   TRUE, TRUE, 0);
+
+  if (IsBookmarkBarSupported()) {
+    bookmark_bar_.reset(new BookmarkBarGtk(this,
+                                           browser_->profile(),
+                                           browser_.get(),
+                                           tabstrip_.get()));
+    PlaceBookmarkBar(false);
+    gtk_widget_show(bookmark_bar_->widget());
+
+    g_signal_connect_after(bookmark_bar_->widget(), "expose-event",
+                           G_CALLBACK(OnBookmarkBarExposeThunk), this);
+    g_signal_connect(bookmark_bar_->widget(), "size-allocate",
+                     G_CALLBACK(OnBookmarkBarSizeAllocateThunk), this);
+  }
+
+  // We have to realize the window before we try to apply a window shape mask.
+  gtk_widget_realize(GTK_WIDGET(window_));
+  state_ = gdk_window_get_state(GTK_WIDGET(window_)->window);
+  // Note that calling this the first time is necessary to get the
+  // proper control layout.
+  UpdateCustomFrame();
+
+  gtk_container_add(GTK_CONTAINER(window_), window_container_);
+  gtk_widget_show(window_container_);
+  browser_->tabstrip_model()->AddObserver(this);
+}
+
+void BrowserWindowGtk::SetBackgroundColor() {
+  Profile* profile = browser()->profile();
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(profile);
+  int frame_color_id;
+  if (UsingCustomPopupFrame()) {
+    frame_color_id = BrowserThemeProvider::COLOR_TOOLBAR;
+  } else if (IsActive()) {
+    frame_color_id = browser()->profile()->IsOffTheRecord()
+       ? BrowserThemeProvider::COLOR_FRAME_INCOGNITO
+       : BrowserThemeProvider::COLOR_FRAME;
+  } else {
+    frame_color_id = browser()->profile()->IsOffTheRecord()
+       ? BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE
+       : BrowserThemeProvider::COLOR_FRAME_INACTIVE;
+  }
+
+  SkColor frame_color = theme_provider->GetColor(frame_color_id);
+
+  // Paint the frame color on the left, right and bottom.
+  GdkColor frame_color_gdk = gfx::SkColorToGdkColor(frame_color);
+  gtk_widget_modify_bg(GTK_WIDGET(window_), GTK_STATE_NORMAL,
+                       &frame_color_gdk);
+
+  // Set the color of the dev tools divider.
+  gtk_widget_modify_bg(contents_split_, GTK_STATE_NORMAL, &frame_color_gdk);
+
+  // When the cursor is over the divider, GTK+ normally lightens the background
+  // color by 1.3 (see LIGHTNESS_MULT in gtkstyle.c).  Since we're setting the
+  // color, override the prelight also.
+  color_utils::HSL hsl = { -1, 0.5, 0.65 };
+  SkColor frame_prelight_color = color_utils::HSLShift(frame_color, hsl);
+  GdkColor frame_prelight_color_gdk =
+      gfx::SkColorToGdkColor(frame_prelight_color);
+  gtk_widget_modify_bg(contents_split_, GTK_STATE_PRELIGHT,
+      &frame_prelight_color_gdk);
+
+  GdkColor border_color = theme_provider->GetBorderColor();
+  gtk_widget_modify_bg(toolbar_border_, GTK_STATE_NORMAL, &border_color);
+}
+
+void BrowserWindowGtk::OnSizeChanged(int width, int height) {
+  UpdateWindowShape(width, height);
+}
+
+void BrowserWindowGtk::UpdateWindowShape(int width, int height) {
+  if (UseCustomFrame() && !IsFullscreen() && !IsMaximized()) {
+    // Make the corners rounded.  We set a mask that includes most of the
+    // window except for a few pixels in each corner.
+    GdkRectangle top_top_rect = { 3, 0, width - 6, 1 };
+    GdkRectangle top_mid_rect = { 1, 1, width - 2, 2 };
+    GdkRectangle mid_rect = { 0, 3, width, height - 6 };
+    // The bottom two rects are mirror images of the top two rects.
+    GdkRectangle bot_mid_rect = top_mid_rect;
+    bot_mid_rect.y = height - 3;
+    GdkRectangle bot_bot_rect = top_top_rect;
+    bot_bot_rect.y = height - 1;
+    GdkRegion* mask = gdk_region_rectangle(&top_top_rect);
+    gdk_region_union_with_rect(mask, &top_mid_rect);
+    gdk_region_union_with_rect(mask, &mid_rect);
+    gdk_region_union_with_rect(mask, &bot_mid_rect);
+    gdk_region_union_with_rect(mask, &bot_bot_rect);
+    gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, mask, 0, 0);
+    gdk_region_destroy(mask);
+    gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 1,
+        kFrameBorderThickness, kFrameBorderThickness, kFrameBorderThickness);
+  } else {
+    // XFCE disables the system decorations if there's an xshape set.
+    if (UseCustomFrame()) {
+      // Disable rounded corners.  Simply passing in a NULL region doesn't
+      // seem to work on KWin, so manually set the shape to the whole window.
+      GdkRectangle rect = { 0, 0, width, height };
+      GdkRegion* mask = gdk_region_rectangle(&rect);
+      gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, mask, 0, 0);
+      gdk_region_destroy(mask);
+    } else {
+      gdk_window_shape_combine_region(GTK_WIDGET(window_)->window, NULL, 0, 0);
+    }
+    gtk_alignment_set_padding(GTK_ALIGNMENT(window_container_), 0, 0, 0, 0);
+  }
+}
+
+void BrowserWindowGtk::ConnectAccelerators() {
+  accel_group_ = gtk_accel_group_new();
+  gtk_window_add_accel_group(window_, accel_group_);
+
+  AcceleratorsGtk* accelerators = AcceleratorsGtk::GetInstance();
+  for (AcceleratorsGtk::const_iterator iter = accelerators->begin();
+       iter != accelerators->end(); ++iter) {
+    gtk_accel_group_connect(
+        accel_group_,
+        iter->second.GetGdkKeyCode(),
+        static_cast<GdkModifierType>(iter->second.modifiers()),
+        GtkAccelFlags(0),
+        g_cclosure_new(G_CALLBACK(OnGtkAccelerator),
+                       GINT_TO_POINTER(iter->first), NULL));
+  }
+}
+
+void BrowserWindowGtk::UpdateCustomFrame() {
+  gtk_window_set_decorated(window_, !UseCustomFrame());
+  titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen());
+  UpdateWindowShape(bounds_.width(), bounds_.height());
+}
+
+void BrowserWindowGtk::SaveWindowPosition() {
+  // Browser::SaveWindowPlacement is used for session restore.
+  if (browser_->ShouldSaveWindowPlacement())
+    browser_->SaveWindowPlacement(restored_bounds_, IsMaximized());
+
+  // We also need to save the placement for startup.
+  // This is a web of calls between views and delegates on Windows, but the
+  // crux of the logic follows.  See also cocoa/browser_window_controller.mm.
+  if (!browser_->profile()->GetPrefs())
+    return;
+
+  std::string window_name = browser_->GetWindowPlacementKey();
+  DictionaryValue* window_preferences =
+      browser_->profile()->GetPrefs()->
+          GetMutableDictionary(window_name.c_str());
+  // Note that we store left/top for consistency with Windows, but that we
+  // *don't* obey them; we only use them for computing width/height.  See
+  // comments in SetGeometryHints().
+  window_preferences->SetInteger("left", restored_bounds_.x());
+  window_preferences->SetInteger("top", restored_bounds_.y());
+  window_preferences->SetInteger("right", restored_bounds_.right());
+  window_preferences->SetInteger("bottom", restored_bounds_.bottom());
+  window_preferences->SetBoolean("maximized", IsMaximized());
+
+  scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_info_provider(
+      WindowSizer::CreateDefaultMonitorInfoProvider());
+  gfx::Rect work_area(
+      monitor_info_provider->GetMonitorWorkAreaMatching(restored_bounds_));
+  window_preferences->SetInteger("work_area_left", work_area.x());
+  window_preferences->SetInteger("work_area_top", work_area.y());
+  window_preferences->SetInteger("work_area_right", work_area.right());
+  window_preferences->SetInteger("work_area_bottom", work_area.bottom());
+}
+
+void BrowserWindowGtk::SetInfoBarShowing(InfoBar* bar, bool animate) {
+  infobar_arrow_model_.ShowArrowFor(bar, animate);
+}
+
+void BrowserWindowGtk::PaintStateChanged() {
+  InvalidateInfoBarBits();
+}
+
+void BrowserWindowGtk::InvalidateInfoBarBits() {
+  gtk_widget_queue_draw(toolbar_border_);
+  gtk_widget_queue_draw(toolbar_->widget());
+  if (bookmark_bar_.get() && !bookmark_bar_is_floating_)
+    gtk_widget_queue_draw(bookmark_bar_->widget());
+}
+
+int BrowserWindowGtk::GetXPositionOfLocationIcon(GtkWidget* relative_to) {
+  GtkWidget* location_icon = toolbar_->GetLocationBarView()->
+      location_icon_widget();
+  int x = 0;
+  gtk_widget_translate_coordinates(
+      location_icon, relative_to,
+      (location_icon->allocation.width + 1) / 2,
+      0, &x, NULL);
+
+  if (GTK_WIDGET_NO_WINDOW(relative_to))
+    x += relative_to->allocation.x;
+
+  return x;
+}
+
+void BrowserWindowGtk::OnLocationIconSizeAllocate(GtkWidget* sender,
+                                                  GtkAllocation* allocation) {
+  // The position of the arrow may have changed, so we'll have to redraw it.
+  InvalidateInfoBarBits();
+}
+
+gboolean BrowserWindowGtk::OnExposeDrawInfobarBits(GtkWidget* sender,
+                                                   GdkEventExpose* expose) {
+  if (!infobar_arrow_model_.NeedToDrawInfoBarArrow())
+    return FALSE;
+
+  int x = GetXPositionOfLocationIcon(sender);
+
+  gfx::Rect toolbar_border(toolbar_border_->allocation);
+  int y = 0;
+  gtk_widget_translate_coordinates(toolbar_border_, sender,
+                                   0, toolbar_border.bottom(),
+                                   NULL, &y);
+  if (GTK_WIDGET_NO_WINDOW(sender))
+    y += sender->allocation.y;
+
+  Profile* profile = browser()->profile();
+  infobar_arrow_model_.Paint(
+      sender, expose, gfx::Point(x, y),
+      GtkThemeProvider::GetFrom(profile)->GetBorderColor());
+  return FALSE;
+}
+
+gboolean BrowserWindowGtk::OnBookmarkBarExpose(GtkWidget* sender,
+                                               GdkEventExpose* expose) {
+  if (!infobar_arrow_model_.NeedToDrawInfoBarArrow())
+    return FALSE;
+
+  if (bookmark_bar_is_floating_)
+    return FALSE;
+
+  return OnExposeDrawInfobarBits(sender, expose);
+}
+
+void BrowserWindowGtk::OnBookmarkBarSizeAllocate(GtkWidget* sender,
+                                                 GtkAllocation* allocation) {
+  // The size of the bookmark bar affects how the infobar arrow is drawn on
+  // the toolbar.
+  if (infobar_arrow_model_.NeedToDrawInfoBarArrow())
+    gtk_widget_queue_draw(toolbar_->widget());
+}
+
+// static
+gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
+                                            GObject* acceleratable,
+                                            guint keyval,
+                                            GdkModifierType modifier,
+                                            void* user_data) {
+  int command_id = GPOINTER_TO_INT(user_data);
+  BrowserWindowGtk* browser_window =
+      GetBrowserWindowForNativeWindow(GTK_WINDOW(acceleratable));
+  DCHECK(browser_window != NULL);
+  return browser_window->browser()->ExecuteCommandIfEnabled(command_id);
+}
+
+// Let the focused widget have first crack at the key event so we don't
+// override their accelerators.
+gboolean BrowserWindowGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
+  // If a widget besides the native view is focused, we have to try to handle
+  // the custom accelerators before letting it handle them.
+  TabContents* current_tab_contents =
+      browser()->GetSelectedTabContents();
+  // The current tab might not have a render view if it crashed.
+  if (!current_tab_contents || !current_tab_contents->GetContentNativeView() ||
+      !gtk_widget_is_focus(current_tab_contents->GetContentNativeView())) {
+    int command_id = GetCustomCommandId(event);
+    if (command_id == -1)
+      command_id = GetPreHandleCommandId(event);
+
+    if (command_id != -1 && browser_->ExecuteCommandIfEnabled(command_id))
+      return TRUE;
+
+    // Propagate the key event to child widget first, so we don't override their
+    // accelerators.
+    if (!gtk_window_propagate_key_event(GTK_WINDOW(widget), event)) {
+      if (!gtk_window_activate_key(GTK_WINDOW(widget), event)) {
+        gtk_bindings_activate_event(GTK_OBJECT(widget), event);
+      }
+    }
+  } else {
+    bool rv = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
+    DCHECK(rv);
+  }
+
+  // Prevents the default handler from handling this event.
+  return TRUE;
+}
+
+gboolean BrowserWindowGtk::OnMouseMoveEvent(GtkWidget* widget,
+                                            GdkEventMotion* event) {
+  // This method is used to update the mouse cursor when over the edge of the
+  // custom frame.  If the custom frame is off or we're over some other widget,
+  // do nothing.
+  if (!UseCustomFrame() || event->window != widget->window) {
+    // Reset the cursor.
+    if (frame_cursor_) {
+      frame_cursor_ = NULL;
+      gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL);
+    }
+    return FALSE;
+  }
+
+  // Update the cursor if we're on the custom frame border.
+  GdkWindowEdge edge;
+  bool has_hit_edge = GetWindowEdge(static_cast<int>(event->x),
+                                    static_cast<int>(event->y), &edge);
+  GdkCursorType new_cursor = GDK_LAST_CURSOR;
+  if (has_hit_edge)
+    new_cursor = GdkWindowEdgeToGdkCursorType(edge);
+
+  GdkCursorType last_cursor = GDK_LAST_CURSOR;
+  if (frame_cursor_)
+    last_cursor = frame_cursor_->type;
+
+  if (last_cursor != new_cursor) {
+    if (has_hit_edge) {
+      frame_cursor_ = gfx::GetCursor(new_cursor);
+    } else {
+      frame_cursor_ = NULL;
+    }
+    gdk_window_set_cursor(GTK_WIDGET(window_)->window, frame_cursor_);
+  }
+  return FALSE;
+}
+
+gboolean BrowserWindowGtk::OnButtonPressEvent(GtkWidget* widget,
+                                              GdkEventButton* event) {
+  // Handle back/forward.
+  if (event->type == GDK_BUTTON_PRESS) {
+    if (event->button == 8) {
+      browser_->GoBack(CURRENT_TAB);
+      return TRUE;
+    } else if (event->button == 9) {
+      browser_->GoForward(CURRENT_TAB);
+      return TRUE;
+    }
+  }
+
+  // Handle left, middle and right clicks.  In particular, we care about clicks
+  // in the custom frame border and clicks in the titlebar.
+
+  // Make the button press coordinate relative to the browser window.
+  int win_x, win_y;
+  gdk_window_get_origin(GTK_WIDGET(window_)->window, &win_x, &win_y);
+
+  GdkWindowEdge edge;
+  gfx::Point point(static_cast<int>(event->x_root - win_x),
+                   static_cast<int>(event->y_root - win_y));
+  bool has_hit_edge = GetWindowEdge(point.x(), point.y(), &edge);
+
+  // Ignore clicks that are in/below the browser toolbar.
+  GtkWidget* toolbar = toolbar_->widget();
+  if (!GTK_WIDGET_VISIBLE(toolbar)) {
+    // If the toolbar is not showing, use the location of web contents as the
+    // boundary of where to ignore clicks.
+    toolbar = render_area_vbox_;
+  }
+  gint toolbar_y;
+  gtk_widget_get_pointer(toolbar, NULL, &toolbar_y);
+  bool has_hit_titlebar = !IsFullscreen() && (toolbar_y < 0)
+                          && !has_hit_edge;
+  if (event->button == 1) {
+    if (GDK_BUTTON_PRESS == event->type) {
+      guint32 last_click_time = last_click_time_;
+      gfx::Point last_click_position = last_click_position_;
+      last_click_time_ = event->time;
+      last_click_position_ = gfx::Point(static_cast<int>(event->x),
+                                        static_cast<int>(event->y));
+
+      // Raise the window after a click on either the titlebar or the border to
+      // match the behavior of most window managers, unless that behavior has
+      // been suppressed.
+      if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_)
+        gdk_window_raise(GTK_WIDGET(window_)->window);
+
+      if (has_hit_titlebar) {
+        // We want to start a move when the user single clicks, but not start a
+        // move when the user double clicks.  However, a double click sends the
+        // following GDK events: GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE,
+        // GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE.  If we
+        // start a gtk_window_begin_move_drag on the second GDK_BUTTON_PRESS,
+        // the call to gtk_window_maximize fails.  To work around this, we
+        // keep track of the last click and if it's going to be a double click,
+        // we don't call gtk_window_begin_move_drag.
+        static GtkSettings* settings = gtk_settings_get_default();
+        gint double_click_time = 250;
+        gint double_click_distance = 5;
+        g_object_get(G_OBJECT(settings),
+                     "gtk-double-click-time", &double_click_time,
+                     "gtk-double-click-distance", &double_click_distance,
+                     NULL);
+
+        guint32 click_time = event->time - last_click_time;
+        int click_move_x = abs(event->x - last_click_position.x());
+        int click_move_y = abs(event->y - last_click_position.y());
+
+        if (click_time > static_cast<guint32>(double_click_time) ||
+            click_move_x > double_click_distance ||
+            click_move_y > double_click_distance) {
+          // Ignore drag requests if the window is the size of the screen.
+          // We do this to avoid triggering fullscreen mode in metacity
+          // (without the --no-force-fullscreen flag) and in compiz (with
+          // Legacy Fullscreen Mode enabled).
+          if (!BoundsMatchMonitorSize()) {
+            gtk_window_begin_move_drag(window_, event->button,
+                                       static_cast<gint>(event->x_root),
+                                       static_cast<gint>(event->y_root),
+                                       event->time);
+          }
+          return TRUE;
+        }
+      } else if (has_hit_edge) {
+        gtk_window_begin_resize_drag(window_, edge, event->button,
+                                     static_cast<gint>(event->x_root),
+                                     static_cast<gint>(event->y_root),
+                                     event->time);
+        return TRUE;
+      }
+    } else if (GDK_2BUTTON_PRESS == event->type) {
+      if (has_hit_titlebar) {
+        // Maximize/restore on double click.
+        if (IsMaximized()) {
+          UnMaximize();
+        } else {
+          gtk_window_maximize(window_);
+        }
+        return TRUE;
+      }
+    }
+  } else if (event->button == 2) {
+    if (has_hit_titlebar || has_hit_edge) {
+      gdk_window_lower(GTK_WIDGET(window_)->window);
+    }
+    return TRUE;
+  } else if (event->button == 3) {
+    if (has_hit_titlebar) {
+      titlebar_->ShowContextMenu(event);
+      return TRUE;
+    }
+  }
+
+  return FALSE;  // Continue to propagate the event.
+}
+
+// static
+void BrowserWindowGtk::MainWindowMapped(GtkWidget* widget) {
+  // Map the X Window ID of the window to our window.
+  XID xid = ui::GetX11WindowFromGtkWidget(widget);
+  BrowserWindowGtk::xid_map_.insert(
+      std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget)));
+}
+
+// static
+void BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget) {
+  // Unmap the X Window ID.
+  XID xid = ui::GetX11WindowFromGtkWidget(widget);
+  BrowserWindowGtk::xid_map_.erase(xid);
+}
+
+gboolean BrowserWindowGtk::OnFocusIn(GtkWidget* widget,
+                                     GdkEventFocus* event) {
+  BrowserList::SetLastActive(browser_.get());
+  return FALSE;
+}
+
+gboolean BrowserWindowGtk::OnFocusOut(GtkWidget* widget,
+                                      GdkEventFocus* event) {
+  return FALSE;
+}
+
+void BrowserWindowGtk::ShowSupportedWindowFeatures() {
+  if (IsTabStripSupported())
+    tabstrip_->Show();
+
+  if (IsToolbarSupported()) {
+    toolbar_->Show();
+    gtk_widget_show(toolbar_border_);
+    gdk_window_lower(toolbar_border_->window);
+  }
+
+  if (IsBookmarkBarSupported())
+    MaybeShowBookmarkBar(false);
+}
+
+void BrowserWindowGtk::HideUnsupportedWindowFeatures() {
+  if (!IsTabStripSupported())
+    tabstrip_->Hide();
+
+  if (!IsToolbarSupported())
+    toolbar_->Hide();
+
+  // If the bookmark bar shelf is unsupported, then we never create it.
+}
+
+bool BrowserWindowGtk::IsTabStripSupported() const {
+  return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
+}
+
+bool BrowserWindowGtk::IsToolbarSupported() const {
+  return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
+         browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
+}
+
+bool BrowserWindowGtk::IsBookmarkBarSupported() const {
+  return browser_->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR);
+}
+
+bool BrowserWindowGtk::UsingCustomPopupFrame() const {
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
+      browser()->profile());
+  return !theme_provider->UseGtkTheme() &&
+      browser()->type() & Browser::TYPE_POPUP;
+}
+
+bool BrowserWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
+  if (!UseCustomFrame())
+    return false;
+
+  if (IsMaximized() || IsFullscreen())
+    return false;
+
+  if (x < kFrameBorderThickness) {
+    // Left edge.
+    if (y < kResizeAreaCornerSize - kTopResizeAdjust) {
+      *edge = GDK_WINDOW_EDGE_NORTH_WEST;
+    } else if (y < bounds_.height() - kResizeAreaCornerSize) {
+      *edge = GDK_WINDOW_EDGE_WEST;
+    } else {
+      *edge = GDK_WINDOW_EDGE_SOUTH_WEST;
+    }
+    return true;
+  } else if (x < bounds_.width() - kFrameBorderThickness) {
+    if (y < kFrameBorderThickness - kTopResizeAdjust) {
+      // Top edge.
+      if (x < kResizeAreaCornerSize) {
+        *edge = GDK_WINDOW_EDGE_NORTH_WEST;
+      } else if (x < bounds_.width() - kResizeAreaCornerSize) {
+        *edge = GDK_WINDOW_EDGE_NORTH;
+      } else {
+        *edge = GDK_WINDOW_EDGE_NORTH_EAST;
+      }
+    } else if (y < bounds_.height() - kFrameBorderThickness) {
+      // Ignore the middle content area.
+      return false;
+    } else {
+      // Bottom edge.
+      if (x < kResizeAreaCornerSize) {
+        *edge = GDK_WINDOW_EDGE_SOUTH_WEST;
+      } else if (x < bounds_.width() - kResizeAreaCornerSize) {
+        *edge = GDK_WINDOW_EDGE_SOUTH;
+      } else {
+        *edge = GDK_WINDOW_EDGE_SOUTH_EAST;
+      }
+    }
+    return true;
+  } else {
+    // Right edge.
+    if (y < kResizeAreaCornerSize - kTopResizeAdjust) {
+      *edge = GDK_WINDOW_EDGE_NORTH_EAST;
+    } else if (y < bounds_.height() - kResizeAreaCornerSize) {
+      *edge = GDK_WINDOW_EDGE_EAST;
+    } else {
+      *edge = GDK_WINDOW_EDGE_SOUTH_EAST;
+    }
+    return true;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+bool BrowserWindowGtk::UseCustomFrame() {
+  // We don't use the custom frame for app mode windows or app window popups.
+  return use_custom_frame_pref_.GetValue() &&
+      browser_->type() != Browser::TYPE_APP &&
+      browser_->type() != Browser::TYPE_APP_POPUP;
+}
+
+bool BrowserWindowGtk::BoundsMatchMonitorSize() {
+  // A screen can be composed of multiple monitors.
+  GdkScreen* screen = gtk_window_get_screen(window_);
+  gint monitor_num = gdk_screen_get_monitor_at_window(screen,
+      GTK_WIDGET(window_)->window);
+
+  GdkRectangle monitor_size;
+  gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor_size);
+  return bounds_.size() == gfx::Size(monitor_size.width, monitor_size.height);
+}
+
+void BrowserWindowGtk::PlaceBookmarkBar(bool is_floating) {
+  GtkWidget* parent = gtk_widget_get_parent(bookmark_bar_->widget());
+  if (parent)
+    gtk_container_remove(GTK_CONTAINER(parent), bookmark_bar_->widget());
+
+  if (!is_floating) {
+    // Place the bookmark bar at the end of |window_vbox_|; this happens after
+    // we have placed the render area at the end of |window_vbox_| so we will
+    // be above the render area.
+    gtk_box_pack_end(GTK_BOX(window_vbox_), bookmark_bar_->widget(),
+                     FALSE, FALSE, 0);
+  } else {
+    // Place the bookmark bar at the end of the render area; this happens after
+    // the tab contents container has been placed there so we will be
+    // above the webpage (in terms of y).
+    gtk_box_pack_end(GTK_BOX(render_area_vbox_), bookmark_bar_->widget(),
+                     FALSE, FALSE, 0);
+  }
+}
+
+// static
+bool BrowserWindowGtk::GetCustomFramePrefDefault() {
+  std::string wm_name;
+  if (!ui::GetWindowManagerName(&wm_name))
+    return false;
+
+  // Ideally, we'd use the custom frame by default and just fall back on using
+  // system decorations for the few (?) tiling window managers where the custom
+  // frame doesn't make sense (e.g. awesome, ion3, ratpoison, xmonad, etc.) or
+  // other WMs where it has issues (e.g. Fluxbox -- see issue 19130).  The EWMH
+  // _NET_SUPPORTING_WM property makes it easy to look up a name for the current
+  // WM, but at least some of the WMs in the latter group don't set it.
+  // Instead, we default to using system decorations for all WMs and
+  // special-case the ones where the custom frame should be used.  These names
+  // are taken from the WMs' source code.
+  return (wm_name == "Blackbox" ||
+          wm_name == "compiz" ||
+          wm_name == "e16" ||  // Enlightenment DR16
+          wm_name == "Metacity" ||
+          wm_name == "Mutter" ||
+          wm_name == "Openbox" ||
+          wm_name == "Xfwm4");
+}
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h
new file mode 100644
index 0000000..2152da7
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_window_gtk.h
@@ -0,0 +1,500 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_BROWSER_WINDOW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_BROWSER_WINDOW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <map>
+
+#include "base/scoped_ptr.h"
+#include "base/timer.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/tabs/tab_strip_model_observer.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_arrow_model.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/x/active_window_watcher_x.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/rect.h"
+
+class BookmarkBarGtk;
+class Browser;
+class BrowserTitlebar;
+class BrowserToolbarGtk;
+class CustomDrawButton;
+class DownloadShelfGtk;
+class FindBarGtk;
+class FullscreenExitBubbleGtk;
+class InfoBarContainerGtk;
+class LocationBar;
+class StatusBubbleGtk;
+class TabContentsContainerGtk;
+class TabStripGtk;
+
+// An implementation of BrowserWindow for GTK.
+// Cross-platform code will interact with this object when
+// it needs to manipulate the window.
+
+class BrowserWindowGtk : public BrowserWindow,
+                         public NotificationObserver,
+                         public TabStripModelObserver,
+                         public ui::ActiveWindowWatcherX::Observer,
+                         public InfoBarArrowModel::Observer {
+ public:
+  explicit BrowserWindowGtk(Browser* browser);
+  virtual ~BrowserWindowGtk();
+
+  // Overridden from BrowserWindow
+  virtual void Show();
+  virtual void SetBounds(const gfx::Rect& bounds);
+  virtual void Close();
+  virtual void Activate();
+  virtual void Deactivate();
+  virtual bool IsActive() const;
+  virtual void FlashFrame();
+  virtual gfx::NativeWindow GetNativeHandle();
+  virtual BrowserWindowTesting* GetBrowserWindowTesting();
+  virtual StatusBubble* GetStatusBubble();
+  virtual void SelectedTabToolbarSizeChanged(bool is_animating);
+  virtual void UpdateTitleBar();
+  virtual void ShelfVisibilityChanged();
+  virtual void UpdateDevTools();
+  virtual void UpdateLoadingAnimations(bool should_animate);
+  virtual void SetStarredState(bool is_starred);
+  virtual gfx::Rect GetRestoredBounds() const;
+  virtual gfx::Rect GetBounds() const;
+  virtual bool IsMaximized() const;
+  virtual void SetFullscreen(bool fullscreen);
+  virtual bool IsFullscreen() const;
+  virtual bool IsFullscreenBubbleVisible() const;
+  virtual LocationBar* GetLocationBar() const;
+  virtual void SetFocusToLocationBar(bool select_all);
+  virtual void UpdateReloadStopState(bool is_loading, bool force);
+  virtual void UpdateToolbar(TabContentsWrapper* contents,
+                             bool should_restore_state);
+  virtual void FocusToolbar();
+  virtual void FocusAppMenu();
+  virtual void FocusBookmarksToolbar();
+  virtual void FocusChromeOSStatus();
+  virtual void RotatePaneFocus(bool forwards);
+  virtual bool IsBookmarkBarVisible() const;
+  virtual bool IsBookmarkBarAnimating() const;
+  virtual bool IsTabStripEditable() const;
+  virtual bool IsToolbarVisible() const;
+  virtual void ConfirmAddSearchProvider(const TemplateURL* template_url,
+                                        Profile* profile);
+  virtual void ToggleBookmarkBar();
+  virtual views::Window* ShowAboutChromeDialog();
+  virtual void ShowUpdateChromeDialog();
+  virtual void ShowTaskManager();
+  virtual void ShowBackgroundPages();
+  virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
+  virtual bool IsDownloadShelfVisible() const;
+  virtual DownloadShelf* GetDownloadShelf();
+  virtual void ShowClearBrowsingDataDialog();
+  virtual void ShowImportDialog();
+  virtual void ShowSearchEnginesDialog();
+  virtual void ShowPasswordManager();
+  virtual void ShowRepostFormWarningDialog(TabContents* tab_contents);
+  virtual void ShowContentSettingsWindow(ContentSettingsType content_type,
+                                         Profile* profile);
+  virtual void ShowCollectedCookiesDialog(TabContents* tab_contents);
+  virtual void ShowProfileErrorDialog(int message_id);
+  virtual void ShowThemeInstallBubble();
+  virtual void ConfirmBrowserCloseWithPendingDownloads();
+  virtual void ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
+                              gfx::NativeWindow parent_window);
+  virtual void UserChangedTheme();
+  virtual int GetExtraRenderViewHeight() const;
+  virtual void TabContentsFocused(TabContents* tab_contents);
+  virtual void ShowPageInfo(Profile* profile,
+                            const GURL& url,
+                            const NavigationEntry::SSLStatus& ssl,
+                            bool show_history);
+  virtual void ShowAppMenu();
+  virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+                                      bool* is_keyboard_shortcut);
+  virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
+  virtual void ShowCreateWebAppShortcutsDialog(TabContents*  tab_contents);
+  virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile,
+                                                  const Extension* app);
+  virtual void Cut();
+  virtual void Copy();
+  virtual void Paste();
+  virtual void ToggleTabStripMode() {}
+  virtual void PrepareForInstant();
+  virtual void ShowInstant(TabContents* preview_contents);
+  virtual void HideInstant(bool instant_is_active);
+  virtual gfx::Rect GetInstantBounds();
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Overridden from TabStripModelObserver:
+  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
+  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index,
+                             bool user_gesture);
+
+  // Overridden from ActiveWindowWatcher::Observer.
+  virtual void ActiveWindowChanged(GdkWindow* active_window);
+
+  // Overridden from InfoBarArrowModel::Observer.
+  virtual void PaintStateChanged();
+
+  // Accessor for the tab strip.
+  TabStripGtk* tabstrip() const { return tabstrip_.get(); }
+
+  void UpdateDevToolsForContents(TabContents* contents);
+
+  void OnDebouncedBoundsChanged();
+
+  // Request the underlying window to unmaximize.  Also tries to work around
+  // a window manager "feature" that can prevent this in some edge cases.
+  void UnMaximize();
+
+  // Returns false if we're not ready to close yet.  E.g., a tab may have an
+  // onbeforeunload handler that prevents us from closing.
+  bool CanClose() const;
+
+  bool ShouldShowWindowIcon() const;
+
+  // Add the find bar widget to the window hierarchy.
+  void AddFindBar(FindBarGtk* findbar);
+
+  // Reset the mouse cursor to the default cursor if it was set to something
+  // else for the custom frame.
+  void ResetCustomFrameCursor();
+
+  // Toggles whether an infobar is showing.
+  // |animate| controls whether we animate to the new state set by |bar|.
+  void SetInfoBarShowing(InfoBar* bar, bool animate);
+
+  // Returns the BrowserWindowGtk registered with |window|.
+  static BrowserWindowGtk* GetBrowserWindowForNativeWindow(
+      gfx::NativeWindow window);
+
+  // Retrieves the GtkWindow associated with |xid|, which is the X Window
+  // ID of the top-level X window of this object.
+  static GtkWindow* GetBrowserWindowForXID(XID xid);
+
+  Browser* browser() const { return browser_.get(); }
+
+  GtkWindow* window() const { return window_; }
+
+  BrowserToolbarGtk* GetToolbar() { return toolbar_.get(); }
+
+  gfx::Rect bounds() const { return bounds_; }
+
+  // Make changes necessary when the floating state of the bookmark bar changes.
+  // This should only be called by the bookmark bar itself.
+  void BookmarkBarIsFloating(bool is_floating);
+
+  // Returns the tab contents we're currently displaying in the tab contents
+  // container.
+  TabContents* GetDisplayedTabContents();
+
+  static void RegisterUserPrefs(PrefService* prefs);
+
+  // Returns whether to draw the content drop shadow on the sides and bottom
+  // of the browser window. When false, we still draw a shadow on the top of
+  // the toolbar (under the tab strip), but do not round the top corners.
+  bool ShouldDrawContentDropShadow();
+
+  // Tells GTK that the toolbar area is invalidated and needs redrawing. We
+  // have this method as a hack because GTK doesn't queue the toolbar area for
+  // redraw when it should.
+  void QueueToolbarRedraw();
+
+  // Get the position where the infobar arrow should be anchored in
+  // |relative_to| coordinates. This is the middle of the omnibox location icon.
+  int GetXPositionOfLocationIcon(GtkWidget* relative_to);
+
+ protected:
+  virtual void DestroyBrowser();
+  // Top level window.
+  GtkWindow* window_;
+  // GtkAlignment that holds the interior components of the chromium window.
+  // This is used to draw the custom frame border and content shadow.
+  GtkWidget* window_container_;
+  // VBox that holds everything (tabs, toolbar, bookmarks bar, tab contents).
+  GtkWidget* window_vbox_;
+  // VBox that holds everything below the toolbar.
+  GtkWidget* render_area_vbox_;
+  // Floating container that holds the render area. It is needed to position
+  // the findbar.
+  GtkWidget* render_area_floating_container_;
+  // EventBox that holds render_area_floating_container_.
+  GtkWidget* render_area_event_box_;
+  // Border between toolbar and render area.
+  GtkWidget* toolbar_border_;
+
+  scoped_ptr<Browser> browser_;
+
+  // The download shelf view (view at the bottom of the page).
+  scoped_ptr<DownloadShelfGtk> download_shelf_;
+
+ private:
+  // Show or hide the bookmark bar.
+  void MaybeShowBookmarkBar(bool animate);
+
+  // Sets the default size for the window and the the way the user is allowed to
+  // resize it.
+  void SetGeometryHints();
+
+  // Connect to signals on |window_|.
+  void ConnectHandlersToSignals();
+
+  // Create the various UI components.
+  void InitWidgets();
+
+  // Set up background color of the window (depends on if we're incognito or
+  // not).
+  void SetBackgroundColor();
+
+  // Called when the window size changed.
+  void OnSizeChanged(int width, int height);
+
+  // Applies the window shape to if we're in custom drawing mode.
+  void UpdateWindowShape(int width, int height);
+
+  // Connect accelerators that aren't connected to menu items (like ctrl-o,
+  // ctrl-l, etc.).
+  void ConnectAccelerators();
+
+  // Change whether we're showing the custom blue frame.
+  // Must be called once at startup.
+  // Triggers relayout of the content.
+  void UpdateCustomFrame();
+
+  // Save the window position in the prefs.
+  void SaveWindowPosition();
+
+  // Set the bounds of the current window. If |exterior| is true, set the size
+  // of the window itself, otherwise set the bounds of the web contents.
+  // If |move| is true, set the position of the window, otherwise leave the
+  // position to the WM.
+  void SetBoundsImpl(const gfx::Rect& bounds, bool exterior, bool move);
+
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnConfigure,
+                       GdkEventConfigure*);
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnWindowState,
+                       GdkEventWindowState*);
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnMainWindowDeleteEvent,
+                       GdkEvent*);
+  CHROMEGTK_CALLBACK_0(BrowserWindowGtk, void, OnMainWindowDestroy);
+  // Callback for when the custom frame alignment needs to be redrawn.
+  // The content area includes the toolbar and web page but not the tab strip.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnCustomFrameExpose,
+                       GdkEventExpose*);
+
+  // A helper method that draws the shadow above the toolbar and in the frame
+  // border during an expose.
+  void DrawContentShadow(cairo_t* cr);
+
+  // Draws the tab image as the frame so we can write legible text.
+  void DrawPopupFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
+
+  // Draws the normal custom frame using theme_frame.
+  void DrawCustomFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
+
+  // The background frame image needs to be offset by the size of the top of
+  // the window to the top of the tabs when the full skyline isn't displayed
+  // for some reason.
+  int GetVerticalOffset();
+
+  // Returns which frame image we should use based on the window's current
+  // activation state / incognito state.
+  int GetThemeFrameResource();
+
+  // Invalidate all the widgets that need to redraw when the infobar draw state
+  // has changed.
+  void InvalidateInfoBarBits();
+
+  // When the location icon moves, we have to redraw the arrow.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, void, OnLocationIconSizeAllocate,
+                       GtkAllocation*);
+
+  // Used to draw the infobar arrow and drop shadow. This is connected to
+  // multiple widgets' expose events because it overlaps several widgets.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnExposeDrawInfobarBits,
+                       GdkEventExpose*);
+
+  // Used to draw the infobar bits for the bookmark bar. When the bookmark
+  // bar is in floating mode, it has to draw a drop shadow only; otherwise
+  // it is responsible for its portion of the arrow as well as some shadowing.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnBookmarkBarExpose,
+                       GdkEventExpose*);
+
+  // Callback for "size-allocate" signal on bookmark bar; this is relevant
+  // because when the bookmark bar changes dimensions, the infobar arrow has to
+  // change its shape, and we need to queue appropriate redraws.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, void, OnBookmarkBarSizeAllocate,
+                       GtkAllocation*);
+
+  // Callback for accelerator activation. |user_data| stores the command id
+  // of the matched accelerator.
+  static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group,
+                                   GObject* acceleratable,
+                                   guint keyval,
+                                   GdkModifierType modifier,
+                                   void* user_data);
+
+  // Key press event callback.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnKeyPress, GdkEventKey*);
+
+  // Mouse move and mouse button press callbacks.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnMouseMoveEvent,
+                       GdkEventMotion*);
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnButtonPressEvent,
+                       GdkEventButton*);
+
+  // Maps and Unmaps the xid of |widget| to |window|.
+  static void MainWindowMapped(GtkWidget* widget);
+  static void MainWindowUnMapped(GtkWidget* widget);
+
+  // Tracks focus state of browser.
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnFocusIn,
+                       GdkEventFocus*);
+  CHROMEGTK_CALLBACK_1(BrowserWindowGtk, gboolean, OnFocusOut,
+                       GdkEventFocus*);
+
+  // Callback for the loading animation(s) associated with this window.
+  void LoadingAnimationCallback();
+
+  // Shows UI elements for supported window features.
+  void ShowSupportedWindowFeatures();
+
+  // Hides UI elements for unsupported window features.
+  void HideUnsupportedWindowFeatures();
+
+  // Helper functions that query |browser_| concerning support for UI features
+  // in this window. (For example, a popup window might not support a tabstrip).
+  bool IsTabStripSupported() const;
+  bool IsToolbarSupported() const;
+  bool IsBookmarkBarSupported() const;
+
+  // Whether we should draw the tab background instead of the theme_frame
+  // background because this window is a popup.
+  bool UsingCustomPopupFrame() const;
+
+  // Checks to see if the mouse pointer at |x|, |y| is over the border of the
+  // custom frame (a spot that should trigger a window resize). Returns true if
+  // it should and sets |edge|.
+  bool GetWindowEdge(int x, int y, GdkWindowEdge* edge);
+
+  // Returns |true| if we should use the custom frame.
+  bool UseCustomFrame();
+
+  // Returns |true| if the window bounds match the monitor size.
+  bool BoundsMatchMonitorSize();
+
+  // Put the bookmark bar where it belongs.
+  void PlaceBookmarkBar(bool is_floating);
+
+  // Determine whether we use should default to native decorations or the custom
+  // frame based on the currently-running window manager.
+  static bool GetCustomFramePrefDefault();
+
+  NotificationRegistrar registrar_;
+
+  // The position and size of the current window.
+  gfx::Rect bounds_;
+
+  // The position and size of the non-maximized, non-fullscreen window.
+  gfx::Rect restored_bounds_;
+
+  GdkWindowState state_;
+
+  // The container for the titlebar + tab strip.
+  scoped_ptr<BrowserTitlebar> titlebar_;
+
+  // The object that manages all of the widgets in the toolbar.
+  scoped_ptr<BrowserToolbarGtk> toolbar_;
+
+  // The object that manages the bookmark bar. This will be NULL if the
+  // bookmark bar is not supported.
+  scoped_ptr<BookmarkBarGtk> bookmark_bar_;
+
+  // Caches the hover state of the bookmark bar.
+  bool bookmark_bar_is_floating_;
+
+  // The status bubble manager.  Always non-NULL.
+  scoped_ptr<StatusBubbleGtk> status_bubble_;
+
+  // A container that manages the GtkWidget*s that are the webpage display
+  // (along with associated infobars, shelves, and other things that are part
+  // of the content area).
+  scoped_ptr<TabContentsContainerGtk> contents_container_;
+
+  // A container that manages the GtkWidget*s of developer tools for the
+  // selected tab contents.
+  scoped_ptr<TabContentsContainerGtk> devtools_container_;
+
+  // Split pane containing the contents_container_ and the devtools_container_.
+  GtkWidget* contents_split_;
+
+  // The tab strip.  Always non-NULL.
+  scoped_ptr<TabStripGtk> tabstrip_;
+
+  // The container for info bars. Always non-NULL.
+  scoped_ptr<InfoBarContainerGtk> infobar_container_;
+
+  // The timer used to update frames for the Loading Animation.
+  base::RepeatingTimer<BrowserWindowGtk> loading_animation_timer_;
+
+  // The timer used to save the window position for session restore.
+  base::OneShotTimer<BrowserWindowGtk> window_configure_debounce_timer_;
+
+  // Whether the custom chrome frame pref is set.  Normally you want to use
+  // UseCustomFrame() above to determine whether to use the custom frame or
+  // not.
+  BooleanPrefMember use_custom_frame_pref_;
+
+  // A map which translates an X Window ID into its respective GtkWindow.
+  static std::map<XID, GtkWindow*> xid_map_;
+
+  // The current window cursor.  We set it to a resize cursor when over the
+  // custom frame border.  We set it to NULL if we want the default cursor.
+  GdkCursor* frame_cursor_;
+
+  // True if the window manager thinks the window is active.  Not all window
+  // managers keep track of this state (_NET_ACTIVE_WINDOW), in which case
+  // this will always be true.
+  bool is_active_;
+
+  // Keep track of the last click time and the last click position so we can
+  // filter out extra GDK_BUTTON_PRESS events when a double click happens.
+  guint32 last_click_time_;
+  gfx::Point last_click_position_;
+
+  // If true, maximize the window after we call BrowserWindow::Show for the
+  // first time.  This is to work around a compiz bug.
+  bool maximize_after_show_;
+
+  // If true, don't call gdk_window_raise() when we get a click in the title
+  // bar or window border.  This is to work around a compiz bug.
+  bool suppress_window_raise_;
+
+  // The accelerator group used to handle accelerators, owned by this object.
+  GtkAccelGroup* accel_group_;
+
+  scoped_ptr<FullscreenExitBubbleGtk> fullscreen_exit_bubble_;
+
+  // The model that tracks the paint state of the arrow for the infobar
+  // directly below the toolbar.
+  InfoBarArrowModel infobar_arrow_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_BROWSER_WINDOW_GTK_H_
diff --git a/chrome/browser/ui/gtk/cairo_cached_surface.cc b/chrome/browser/ui/gtk/cairo_cached_surface.cc
new file mode 100644
index 0000000..49ced4b
--- /dev/null
+++ b/chrome/browser/ui/gtk/cairo_cached_surface.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/cairo_cached_surface.h"
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+CairoCachedSurface::CairoCachedSurface() : pixbuf_(NULL), surface_(NULL) {
+}
+
+CairoCachedSurface::~CairoCachedSurface() {
+  if (surface_)
+    cairo_surface_destroy(surface_);
+
+  if (pixbuf_)
+    g_object_unref(pixbuf_);
+}
+
+int CairoCachedSurface::Width() const {
+  return pixbuf_ ? gdk_pixbuf_get_width(pixbuf_) : -1;
+}
+
+int CairoCachedSurface::Height() const {
+  return pixbuf_ ? gdk_pixbuf_get_height(pixbuf_) : -1;
+}
+
+void CairoCachedSurface::UsePixbuf(GdkPixbuf* pixbuf) {
+  if (surface_) {
+    cairo_surface_destroy(surface_);
+    surface_ = NULL;
+  }
+
+  if (pixbuf)
+    g_object_ref(pixbuf);
+
+  if (pixbuf_)
+    g_object_unref(pixbuf_);
+
+  pixbuf_ = pixbuf;
+}
+
+void CairoCachedSurface::SetSource(cairo_t* cr, int x, int y) {
+  DCHECK(pixbuf_);
+  DCHECK(cr);
+
+  if (!surface_) {
+    // First time here since last UsePixbuf call. Generate the surface.
+    cairo_surface_t* target = cairo_get_target(cr);
+    surface_ = cairo_surface_create_similar(
+        target,
+        CAIRO_CONTENT_COLOR_ALPHA,
+        gdk_pixbuf_get_width(pixbuf_),
+        gdk_pixbuf_get_height(pixbuf_));
+
+    DCHECK(surface_);
+#if !defined(NDEBUG)
+    int surface_type = cairo_surface_get_type(surface_);
+    DCHECK(surface_type == CAIRO_SURFACE_TYPE_XLIB ||
+           surface_type == CAIRO_SURFACE_TYPE_XCB ||
+           surface_type == CAIRO_SURFACE_TYPE_IMAGE);
+#endif
+
+    cairo_t* copy_cr = cairo_create(surface_);
+    gdk_cairo_set_source_pixbuf(copy_cr, pixbuf_, 0, 0);
+    cairo_paint(copy_cr);
+    cairo_destroy(copy_cr);
+  }
+
+  cairo_set_source_surface(cr, surface_, x, y);
+}
diff --git a/chrome/browser/ui/gtk/cairo_cached_surface.h b/chrome/browser/ui/gtk/cairo_cached_surface.h
new file mode 100644
index 0000000..da7fe67
--- /dev/null
+++ b/chrome/browser/ui/gtk/cairo_cached_surface.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_CAIRO_CACHED_SURFACE_H_
+#define CHROME_BROWSER_UI_GTK_CAIRO_CACHED_SURFACE_H_
+#pragma once
+
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _cairo cairo_t;
+typedef struct _cairo_surface cairo_surface_t;
+
+// A helper class that takes a GdkPixbuf* and renders it to the screen. Unlike
+// gdk_cairo_set_source_pixbuf(), CairoCachedSurface assumes that the pixbuf is
+// immutable after UsePixbuf() is called and can be sent to the X server
+// once. From then on, that cached version is used so we don't upload the same
+// image each and every time we expose.
+//
+// Most cached surfaces are owned by the GtkThemeProvider, which associates
+// them with a certain XDisplay. Some users of surfaces (CustomDrawButtonBase,
+// for example) own their surfaces instead since they interact with the
+// ResourceBundle instead of the GtkThemeProvider.
+class CairoCachedSurface {
+ public:
+  CairoCachedSurface();
+  ~CairoCachedSurface();
+
+  // Whether this CairoCachedSurface owns a GdkPixbuf.
+  bool valid() const {
+    return pixbuf_;
+  }
+
+  // The dimensions of the underlying pixbuf/surface. (or -1 if invalid.)
+  int Width() const;
+  int Height() const;
+
+  // Sets the pixbuf that we pass to cairo. Calling UsePixbuf() only derefs the
+  // current pixbuf and surface (if they exist). Actually transfering data to
+  // the X server occurs at SetSource() time. Calling UsePixbuf() should only
+  // be done once as it clears cached data from the X server.
+  void UsePixbuf(GdkPixbuf* pixbuf);
+
+  // Sets our pixbuf as the active surface starting at (x, y), uploading it in
+  // case we don't have an X backed surface cached.
+  void SetSource(cairo_t* cr, int x, int y);
+
+  // Raw access to the pixbuf. May be NULL. Used for a few gdk operations
+  // regarding window shaping.
+  GdkPixbuf* pixbuf() { return pixbuf_; }
+
+ private:
+  // The source pixbuf.
+  GdkPixbuf* pixbuf_;
+
+  // Our cached surface. This should be a xlib surface so the data lives on the
+  // server instead of on the client.
+  cairo_surface_t* surface_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_CAIRO_CACHED_SURFACE_H_
diff --git a/chrome/browser/ui/gtk/certificate_dialogs.cc b/chrome/browser/ui/gtk/certificate_dialogs.cc
new file mode 100644
index 0000000..5dc25a2
--- /dev/null
+++ b/chrome/browser/ui/gtk/certificate_dialogs.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(mattm): this isn't gtk specific, it shouldn't be under the gtk dir
+
+#include "chrome/browser/ui/gtk/certificate_dialogs.h"
+
+
+#include <vector>
+
+#include "base/base64.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/common/net/x509_certificate_model.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+// General utility functions.
+
+class Writer : public Task {
+ public:
+  Writer(const FilePath& path, const std::string& data)
+      : path_(path), data_(data) {
+  }
+
+  virtual void Run() {
+    int bytes_written = file_util::WriteFile(path_, data_.data(), data_.size());
+    if (bytes_written != static_cast<ssize_t>(data_.size())) {
+      LOG(ERROR) << "Writing " << path_.value() << " ("
+                 << data_.size() << "B) returned " << bytes_written;
+    }
+  }
+ private:
+  FilePath path_;
+  std::string data_;
+};
+
+void WriteFileOnFileThread(const FilePath& path, const std::string& data) {
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE, new Writer(path, data));
+}
+
+std::string WrapAt64(const std::string &str) {
+  std::string result;
+  for (size_t i = 0; i < str.size(); i += 64) {
+    result.append(str, i, 64);  // Append clamps the len arg internally.
+    result.append("\r\n");
+  }
+  return result;
+}
+
+std::string GetBase64String(net::X509Certificate::OSCertHandle cert) {
+  std::string base64;
+  if (!base::Base64Encode(
+      x509_certificate_model::GetDerString(cert), &base64)) {
+    LOG(ERROR) << "base64 encoding error";
+    return "";
+  }
+  return "-----BEGIN CERTIFICATE-----\r\n" +
+      WrapAt64(base64) +
+      "-----END CERTIFICATE-----\r\n";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// General utility functions.
+
+class Exporter : public SelectFileDialog::Listener {
+ public:
+  Exporter(gfx::NativeWindow parent, net::X509Certificate::OSCertHandle cert);
+  ~Exporter();
+
+  // SelectFileDialog::Listener implemenation.
+  virtual void FileSelected(const FilePath& path,
+                            int index, void* params);
+  virtual void FileSelectionCanceled(void* params);
+ private:
+  scoped_refptr<SelectFileDialog> select_file_dialog_;
+
+  // The certificate hierarchy (leaf cert first).
+  net::X509Certificate::OSCertHandles cert_chain_list_;
+};
+
+Exporter::Exporter(gfx::NativeWindow parent,
+                   net::X509Certificate::OSCertHandle cert)
+    : select_file_dialog_(SelectFileDialog::Create(this)) {
+  x509_certificate_model::GetCertChainFromCert(cert, &cert_chain_list_);
+
+  // TODO(mattm): should this default to some directory?
+  // Maybe SavePackage::GetSaveDirPreference? (Except that it's private.)
+  FilePath suggested_path("certificate");
+  std::string cert_title = x509_certificate_model::GetTitle(cert);
+  if (!cert_title.empty())
+    suggested_path = FilePath(cert_title);
+
+  ShowCertSelectFileDialog(select_file_dialog_.get(),
+                           SelectFileDialog::SELECT_SAVEAS_FILE,
+                           suggested_path,
+                           parent,
+                           NULL);
+}
+
+Exporter::~Exporter() {
+  x509_certificate_model::DestroyCertChain(&cert_chain_list_);
+}
+
+void Exporter::FileSelected(const FilePath& path, int index, void* params) {
+  std::string data;
+  switch (index) {
+    case 2:
+      for (size_t i = 0; i < cert_chain_list_.size(); ++i)
+        data += GetBase64String(cert_chain_list_[i]);
+      break;
+    case 3:
+      data = x509_certificate_model::GetDerString(cert_chain_list_[0]);
+      break;
+    case 4:
+      data = x509_certificate_model::GetCMSString(cert_chain_list_, 0, 1);
+      break;
+    case 5:
+      data = x509_certificate_model::GetCMSString(
+          cert_chain_list_, 0, cert_chain_list_.size());
+      break;
+    case 1:
+    default:
+      data = GetBase64String(cert_chain_list_[0]);
+      break;
+  }
+
+  if (!data.empty())
+    WriteFileOnFileThread(path, data);
+
+  delete this;
+}
+
+void Exporter::FileSelectionCanceled(void* params) {
+  delete this;
+}
+
+} // namespace
+
+void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog,
+                              SelectFileDialog::Type type,
+                              const FilePath& suggested_path,
+                              gfx::NativeWindow parent,
+                              void* params) {
+  SelectFileDialog::FileTypeInfo file_type_info;
+  file_type_info.extensions.resize(5);
+  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("pem"));
+  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("crt"));
+  file_type_info.extension_description_overrides.push_back(
+      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64));
+  file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("pem"));
+  file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("crt"));
+  file_type_info.extension_description_overrides.push_back(
+      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64_CHAIN));
+  file_type_info.extensions[2].push_back(FILE_PATH_LITERAL("der"));
+  file_type_info.extension_description_overrides.push_back(
+      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_DER));
+  file_type_info.extensions[3].push_back(FILE_PATH_LITERAL("p7c"));
+  file_type_info.extension_description_overrides.push_back(
+      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7));
+  file_type_info.extensions[4].push_back(FILE_PATH_LITERAL("p7c"));
+  file_type_info.extension_description_overrides.push_back(
+      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7_CHAIN));
+  file_type_info.include_all_files = true;
+  select_file_dialog->SelectFile(
+      type, string16(),
+      suggested_path, &file_type_info, 1,
+      FILE_PATH_LITERAL("crt"), parent,
+      params);
+}
+
+void ShowCertExportDialog(gfx::NativeWindow parent,
+                          net::X509Certificate::OSCertHandle cert) {
+  new Exporter(parent, cert);
+}
diff --git a/chrome/browser/ui/gtk/certificate_dialogs.h b/chrome/browser/ui/gtk/certificate_dialogs.h
new file mode 100644
index 0000000..a13bfca
--- /dev/null
+++ b/chrome/browser/ui/gtk/certificate_dialogs.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_CERTIFICATE_DIALOGS_H_
+#define CHROME_BROWSER_UI_GTK_CERTIFICATE_DIALOGS_H_
+#pragma once
+
+#include "chrome/browser/ui/shell_dialogs.h"
+#include "net/base/x509_certificate.h"
+
+void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog,
+                              SelectFileDialog::Type type,
+                              const FilePath& suggested_path,
+                              gfx::NativeWindow parent,
+                              void* params);
+
+void ShowCertExportDialog(gfx::NativeWindow parent,
+                          net::X509Certificate::OSCertHandle cert);
+
+#endif  // CHROME_BROWSER_UI_GTK_CERTIFICATE_DIALOGS_H_
diff --git a/chrome/browser/ui/gtk/certificate_viewer.cc b/chrome/browser/ui/gtk/certificate_viewer.cc
new file mode 100644
index 0000000..ab64d2a
--- /dev/null
+++ b/chrome/browser/ui/gtk/certificate_viewer.cc
@@ -0,0 +1,694 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/certificate_viewer.h"
+
+#include <gtk/gtk.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/i18n/time_formatting.h"
+#include "base/nss_util.h"
+#include "base/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/certificate_dialogs.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/net/x509_certificate_model.h"
+#include "grit/generated_resources.h"
+#include "net/base/x509_certificate.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+const char kDetailsFontFamily[] = "monospace";
+
+////////////////////////////////////////////////////////////////////////////////
+// Gtk utility functions.
+
+void AddTitle(GtkTable* table, int row, const std::string& text) {
+  gtk_table_attach_defaults(table,
+                            gtk_util::CreateBoldLabel(text),
+                            0, 2,
+                            row, row + 1);
+}
+
+void AddKeyValue(GtkTable* table, int row, const std::string& text,
+                 const std::string& value) {
+  gtk_table_attach_defaults(
+      table,
+      gtk_util::IndentWidget(
+          gtk_util::LeftAlignMisc(gtk_label_new(text.c_str()))),
+      0, 1, row, row + 1);
+  gtk_table_attach_defaults(
+      table,
+      gtk_util::LeftAlignMisc(gtk_label_new(value.c_str())),
+      1, 2, row, row + 1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CertificateViewer class definition.
+
+class CertificateViewer {
+ public:
+  CertificateViewer(gfx::NativeWindow parent,
+                    const net::X509Certificate::OSCertHandles& cert_chain_list);
+  ~CertificateViewer();
+
+  void InitGeneralPage();
+  void InitDetailsPage();
+
+  void Show();
+
+ private:
+  // Indices and column count for the certificate chain hierarchy tree store.
+  enum {
+    HIERARCHY_NAME,
+    HIERARCHY_OBJECT,
+    HIERARCHY_INDEX,
+    HIERARCHY_COLUMNS
+  };
+
+  // Indices and column count for the certificate fields tree store.
+  enum {
+    FIELDS_NAME,
+    FIELDS_VALUE,
+    FIELDS_COLUMNS
+  };
+
+  // Fill the tree store with the certificate hierarchy, and set |leaf| to the
+  // iter of the leaf node.
+  void FillHierarchyStore(GtkTreeStore* hierarchy_store,
+                          GtkTreeIter* leaf) const;
+
+  // Fill the tree store with the details of the given certificate.
+  static void FillTreeStoreWithCertFields(
+      GtkTreeStore* store, net::X509Certificate::OSCertHandle cert);
+
+  // Create a tree store filled with the details of the given certificate.
+  static GtkTreeStore* CreateFieldsTreeStore(
+      net::X509Certificate::OSCertHandle cert);
+
+  // Callbacks for user selecting elements in the trees.
+  static void OnHierarchySelectionChanged(GtkTreeSelection* selection,
+                                          CertificateViewer* viewer);
+  static void OnFieldsSelectionChanged(GtkTreeSelection* selection,
+                                       CertificateViewer* viewer);
+
+  // Callback for export button.
+  static void OnExportClicked(GtkButton *button, CertificateViewer* viewer);
+
+  // The certificate hierarchy (leaf cert first).
+  net::X509Certificate::OSCertHandles cert_chain_list_;
+
+  GtkWidget* dialog_;
+  GtkWidget* notebook_;
+  GtkWidget* general_page_vbox_;
+  GtkWidget* details_page_vbox_;
+  GtkTreeSelection* hierarchy_selection_;
+  GtkWidget* fields_tree_;
+  GtkTextBuffer* field_value_buffer_;
+  GtkWidget* export_button_;
+
+  DISALLOW_COPY_AND_ASSIGN(CertificateViewer);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// CertificateViewer implementation.
+
+// Close button callback.
+void OnDialogResponse(GtkDialog* dialog, gint response_id,
+                      gpointer user_data) {
+  // "Close" was clicked.
+  gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+void OnDestroy(GtkDialog* dialog, CertificateViewer* cert_viewer) {
+  delete cert_viewer;
+}
+
+CertificateViewer::CertificateViewer(
+    gfx::NativeWindow parent,
+    const net::X509Certificate::OSCertHandles& cert_chain_list)
+    : cert_chain_list_(cert_chain_list) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringFUTF8(
+          IDS_CERT_INFO_DIALOG_TITLE,
+          UTF8ToUTF16(
+              x509_certificate_model::GetTitle(
+                  cert_chain_list_.front()))).c_str(),
+      parent,
+      // Non-modal.
+      GTK_DIALOG_NO_SEPARATOR,
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  x509_certificate_model::RegisterDynamicOids();
+  InitGeneralPage();
+  InitDetailsPage();
+
+  notebook_ = gtk_notebook_new();
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      general_page_vbox_,
+      gtk_label_new_with_mnemonic(
+          gfx::ConvertAcceleratorsFromWindowsStyle(
+              l10n_util::GetStringUTF8(
+                  IDS_CERT_INFO_GENERAL_TAB_LABEL)).c_str()));
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      details_page_vbox_,
+      gtk_label_new_with_mnemonic(
+          gfx::ConvertAcceleratorsFromWindowsStyle(
+              l10n_util::GetStringUTF8(
+                  IDS_CERT_INFO_DETAILS_TAB_LABEL)).c_str()));
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponse), NULL);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this);
+}
+
+CertificateViewer::~CertificateViewer() {
+  x509_certificate_model::DestroyCertChain(&cert_chain_list_);
+}
+
+void CertificateViewer::InitGeneralPage() {
+  net::X509Certificate::OSCertHandle cert = cert_chain_list_.front();
+  general_page_vbox_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(general_page_vbox_),
+                                 gtk_util::kContentAreaBorder);
+
+  GtkWidget* uses_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(general_page_vbox_), uses_vbox, FALSE, FALSE, 0);
+  gtk_box_pack_start(
+      GTK_BOX(uses_vbox),
+      gtk_util::CreateBoldLabel(
+          l10n_util::GetStringUTF8(IDS_CERT_INFO_VERIFIED_USAGES_GROUP)),
+      FALSE, FALSE, 0);
+
+  std::vector<std::string> usages;
+  x509_certificate_model::GetUsageStrings(cert, &usages);
+  for (size_t i = 0; i < usages.size(); ++i)
+    gtk_box_pack_start(
+        GTK_BOX(uses_vbox),
+        gtk_util::IndentWidget(gtk_util::LeftAlignMisc(gtk_label_new(
+            usages[i].c_str()))),
+        FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(general_page_vbox_), gtk_hseparator_new(),
+                     FALSE, FALSE, 0);
+
+  const int num_rows = 21;
+  GtkTable* table = GTK_TABLE(gtk_table_new(num_rows, 2, FALSE));
+  gtk_table_set_col_spacing(table, 0, gtk_util::kLabelSpacing);
+  gtk_table_set_row_spacings(table, gtk_util::kControlSpacing);
+
+  gtk_box_pack_start(GTK_BOX(general_page_vbox_), GTK_WIDGET(table),
+                     FALSE, FALSE, 0);
+  int row = 0;
+  const std::string alternative_text =
+      l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT);
+  AddTitle(table, row++,
+           l10n_util::GetStringUTF8(IDS_CERT_INFO_SUBJECT_GROUP));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL),
+              x509_certificate_model::ProcessIDN(
+                  x509_certificate_model::GetSubjectCommonName(
+                      cert, alternative_text)));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATION_LABEL),
+              x509_certificate_model::GetSubjectOrgName(
+                  cert, alternative_text));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL),
+              x509_certificate_model::GetSubjectOrgUnitName(
+                  cert, alternative_text));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_SERIAL_NUMBER_LABEL),
+              x509_certificate_model::GetSerialNumberHexified(
+                  cert, alternative_text));
+
+  row += 2;  // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
+
+  AddTitle(table, row++,
+           l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUER_GROUP));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL),
+              x509_certificate_model::ProcessIDN(
+                  x509_certificate_model::GetIssuerCommonName(
+                      cert, alternative_text)));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATION_LABEL),
+              x509_certificate_model::GetIssuerOrgName(
+                  cert, alternative_text));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL),
+              x509_certificate_model::GetIssuerOrgUnitName(
+                  cert, alternative_text));
+
+  row += 2;  // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
+
+  base::Time issued, expires;
+  std::string issued_str, expires_str;
+  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
+    issued_str = UTF16ToUTF8(
+        base::TimeFormatShortDateNumeric(issued));
+    expires_str = UTF16ToUTF8(
+        base::TimeFormatShortDateNumeric(expires));
+  } else {
+    issued_str = alternative_text;
+    expires_str = alternative_text;
+  }
+  AddTitle(table, row++,
+           l10n_util::GetStringUTF8(IDS_CERT_INFO_VALIDITY_GROUP));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUED_ON_LABEL),
+              issued_str);
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_EXPIRES_ON_LABEL),
+              expires_str);
+
+  row += 2;  // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
+
+  AddTitle(table, row++,
+           l10n_util::GetStringUTF8(IDS_CERT_INFO_FINGERPRINTS_GROUP));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL),
+              x509_certificate_model::HashCertSHA256(cert));
+  AddKeyValue(table, row++,
+              l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL),
+              x509_certificate_model::HashCertSHA1(cert));
+
+  DCHECK_EQ(row, num_rows);
+}
+
+void CertificateViewer::FillHierarchyStore(GtkTreeStore* hierarchy_store,
+                                           GtkTreeIter* leaf) const {
+  GtkTreeIter parent;
+  GtkTreeIter* parent_ptr = NULL;
+  GtkTreeIter iter;
+  gint index = cert_chain_list_.size() - 1;
+  for (net::X509Certificate::OSCertHandles::const_reverse_iterator i =
+          cert_chain_list_.rbegin();
+       i != cert_chain_list_.rend(); ++i, --index) {
+    gtk_tree_store_append(hierarchy_store, &iter, parent_ptr);
+    GtkTreeStore* fields_store = CreateFieldsTreeStore(*i);
+    gtk_tree_store_set(
+        hierarchy_store, &iter,
+        HIERARCHY_NAME, x509_certificate_model::GetTitle(*i).c_str(),
+        HIERARCHY_OBJECT, fields_store,
+        HIERARCHY_INDEX, index,
+        -1);
+    g_object_unref(fields_store);
+    parent = iter;
+    parent_ptr = &parent;
+  }
+  *leaf = iter;
+}
+
+// static
+void CertificateViewer::FillTreeStoreWithCertFields(
+    GtkTreeStore* store, net::X509Certificate::OSCertHandle cert) {
+  GtkTreeIter top;
+  gtk_tree_store_append(store, &top, NULL);
+  gtk_tree_store_set(
+      store, &top,
+      FIELDS_NAME, x509_certificate_model::GetTitle(cert).c_str(),
+      FIELDS_VALUE, "",
+      -1);
+
+  GtkTreeIter cert_iter;
+  gtk_tree_store_append(store, &cert_iter, &top);
+  gtk_tree_store_set(
+      store, &cert_iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE).c_str(),
+      FIELDS_VALUE, "",
+      -1);
+
+  std::string version_str;
+  std::string version = x509_certificate_model::GetVersion(cert);
+  if (!version.empty())
+    version_str = l10n_util::GetStringFUTF8(IDS_CERT_DETAILS_VERSION_FORMAT,
+                                            UTF8ToUTF16(version));
+  GtkTreeIter iter;
+  gtk_tree_store_append(store, &iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VERSION).c_str(),
+      FIELDS_VALUE, version_str.c_str(),
+      -1);
+
+  gtk_tree_store_append(store, &iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SERIAL_NUMBER).c_str(),
+      FIELDS_VALUE,
+      x509_certificate_model::GetSerialNumberHexified(
+          cert,
+          l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT)).c_str(),
+      -1);
+
+  gtk_tree_store_append(store, &iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG).c_str(),
+      FIELDS_VALUE,
+      x509_certificate_model::ProcessSecAlgorithmSignature(cert).c_str(),
+      -1);
+
+  gtk_tree_store_append(store, &iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_ISSUER).c_str(),
+      FIELDS_VALUE, x509_certificate_model::GetIssuerName(cert).c_str(),
+      -1);
+
+  GtkTreeIter validity_iter;
+  gtk_tree_store_append(store, &validity_iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &validity_iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VALIDITY).c_str(),
+      FIELDS_VALUE, "",
+      -1);
+
+  base::Time issued, expires;
+  std::string issued_str, expires_str;
+  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
+    issued_str = UTF16ToUTF8(base::TimeFormatShortDateAndTime(issued));
+    expires_str = UTF16ToUTF8(base::TimeFormatShortDateAndTime(expires));
+  }
+  gtk_tree_store_append(store, &iter, &validity_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_BEFORE).c_str(),
+      FIELDS_VALUE, issued_str.c_str(),
+      -1);
+  gtk_tree_store_append(store, &iter, &validity_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_AFTER).c_str(),
+      FIELDS_VALUE, expires_str.c_str(),
+      -1);
+
+  gtk_tree_store_append(store, &iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT).c_str(),
+      FIELDS_VALUE, x509_certificate_model::GetSubjectName(cert).c_str(),
+      -1);
+
+  GtkTreeIter subject_public_key_iter;
+  gtk_tree_store_append(store, &subject_public_key_iter, &cert_iter);
+  gtk_tree_store_set(
+      store, &subject_public_key_iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_INFO).c_str(),
+      FIELDS_VALUE, "",
+      -1);
+
+  gtk_tree_store_append(store, &iter, &subject_public_key_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_ALG).c_str(),
+      FIELDS_VALUE,
+      x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(cert).c_str(),
+      -1);
+
+  gtk_tree_store_append(store, &iter, &subject_public_key_iter);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY).c_str(),
+      FIELDS_VALUE,
+      x509_certificate_model::ProcessSubjectPublicKeyInfo(cert).c_str(),
+      -1);
+
+  x509_certificate_model::Extensions extensions;
+  x509_certificate_model::GetExtensions(
+      l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL),
+      l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL),
+      cert, &extensions);
+
+  if (!extensions.empty()) {
+    GtkTreeIter extensions_iter;
+    gtk_tree_store_append(store, &extensions_iter, &cert_iter);
+    gtk_tree_store_set(
+        store, &extensions_iter,
+        FIELDS_NAME,
+        l10n_util::GetStringUTF8(IDS_CERT_DETAILS_EXTENSIONS).c_str(),
+        FIELDS_VALUE, "",
+        -1);
+
+    for (x509_certificate_model::Extensions::const_iterator i =
+         extensions.begin(); i != extensions.end(); ++i) {
+      gtk_tree_store_append(store, &iter, &extensions_iter);
+      gtk_tree_store_set(
+          store, &iter,
+          FIELDS_NAME, i->name.c_str(),
+          FIELDS_VALUE, i->value.c_str(),
+          -1);
+    }
+  }
+
+  gtk_tree_store_append(store, &iter, &top);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG).c_str(),
+      FIELDS_VALUE,
+      x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert).c_str(),
+      -1);
+
+  gtk_tree_store_append(store, &iter, &top);
+  gtk_tree_store_set(
+      store, &iter,
+      FIELDS_NAME,
+      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE).c_str(),
+      FIELDS_VALUE,
+      x509_certificate_model::ProcessRawBitsSignatureWrap(cert).c_str(),
+      -1);
+}
+
+// static
+GtkTreeStore* CertificateViewer::CreateFieldsTreeStore(
+    net::X509Certificate::OSCertHandle cert) {
+  GtkTreeStore* fields_store = gtk_tree_store_new(FIELDS_COLUMNS, G_TYPE_STRING,
+                                                  G_TYPE_STRING);
+  FillTreeStoreWithCertFields(fields_store, cert);
+  return fields_store;
+}
+
+void CertificateViewer::InitDetailsPage() {
+  details_page_vbox_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(details_page_vbox_),
+                                 gtk_util::kContentAreaBorder);
+
+  GtkWidget* hierarchy_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(details_page_vbox_), hierarchy_vbox,
+                     FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(hierarchy_vbox),
+                     gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
+                         IDS_CERT_DETAILS_CERTIFICATE_HIERARCHY_LABEL)),
+                     FALSE, FALSE, 0);
+
+  GtkTreeStore* hierarchy_store = gtk_tree_store_new(HIERARCHY_COLUMNS,
+                                                     G_TYPE_STRING,
+                                                     G_TYPE_OBJECT,
+                                                     G_TYPE_INT);
+  GtkTreeIter hierarchy_leaf_iter;
+  FillHierarchyStore(hierarchy_store, &hierarchy_leaf_iter);
+  GtkWidget* hierarchy_tree = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(hierarchy_store));
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(hierarchy_tree), FALSE);
+  gtk_tree_view_append_column(
+      GTK_TREE_VIEW(hierarchy_tree),
+      gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(),
+                                               "text", HIERARCHY_NAME,
+                                               NULL));
+  gtk_tree_view_expand_all(GTK_TREE_VIEW(hierarchy_tree));
+  hierarchy_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(hierarchy_tree));
+  gtk_tree_selection_set_mode(hierarchy_selection_, GTK_SELECTION_SINGLE);
+  g_signal_connect(hierarchy_selection_, "changed",
+                   G_CALLBACK(OnHierarchySelectionChanged), this);
+  GtkWidget* hierarchy_scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(hierarchy_scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_NEVER);
+  gtk_scrolled_window_set_shadow_type(
+      GTK_SCROLLED_WINDOW(hierarchy_scroll_window), GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(hierarchy_scroll_window), hierarchy_tree);
+  gtk_box_pack_start(GTK_BOX(hierarchy_vbox),
+                     hierarchy_scroll_window, FALSE, FALSE, 0);
+
+  GtkWidget* fields_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(details_page_vbox_), fields_vbox,
+                     TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(fields_vbox),
+                     gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
+                         IDS_CERT_DETAILS_CERTIFICATE_FIELDS_LABEL)),
+                     FALSE, FALSE, 0);
+
+  fields_tree_ = gtk_tree_view_new();
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(fields_tree_), FALSE);
+  gtk_tree_view_append_column(
+      GTK_TREE_VIEW(fields_tree_),
+      gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(),
+                                               "text", FIELDS_NAME,
+                                               NULL));
+  GtkTreeSelection* fields_selection = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(fields_tree_));
+  gtk_tree_selection_set_mode(fields_selection, GTK_SELECTION_SINGLE);
+  g_signal_connect(fields_selection, "changed",
+                   G_CALLBACK(OnFieldsSelectionChanged), this);
+  GtkWidget* fields_scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fields_scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(
+      GTK_SCROLLED_WINDOW(fields_scroll_window), GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(fields_scroll_window), fields_tree_);
+  gtk_box_pack_start(GTK_BOX(fields_vbox),
+                     fields_scroll_window, TRUE, TRUE, 0);
+
+  GtkWidget* value_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(details_page_vbox_), value_vbox,
+                     TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(value_vbox),
+                     gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
+                         IDS_CERT_DETAILS_CERTIFICATE_FIELD_VALUE_LABEL)),
+                     FALSE, FALSE, 0);
+
+  // TODO(mattm): fix text view coloring (should have grey background).
+  GtkWidget* field_value_view = gtk_text_view_new();
+  gtk_text_view_set_editable(GTK_TEXT_VIEW(field_value_view), FALSE);
+  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(field_value_view), GTK_WRAP_NONE);
+  field_value_buffer_ = gtk_text_view_get_buffer(
+      GTK_TEXT_VIEW(field_value_view));
+  GtkWidget* value_scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(value_scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(
+      GTK_SCROLLED_WINDOW(value_scroll_window), GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(value_scroll_window), field_value_view);
+  gtk_box_pack_start(GTK_BOX(value_vbox),
+                     value_scroll_window, TRUE, TRUE, 0);
+
+  gtk_widget_ensure_style(field_value_view);
+  PangoFontDescription* font_desc = pango_font_description_copy(
+      gtk_widget_get_style(field_value_view)->font_desc);
+  pango_font_description_set_family(font_desc, kDetailsFontFamily);
+  gtk_widget_modify_font(field_value_view, font_desc);
+  pango_font_description_free(font_desc);
+
+  GtkWidget* export_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(details_page_vbox_), export_hbox,
+                     FALSE, FALSE, 0);
+  export_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(
+              IDS_CERT_DETAILS_EXPORT_CERTIFICATE)).c_str());
+  g_signal_connect(export_button_, "clicked",
+                   G_CALLBACK(OnExportClicked), this);
+  gtk_box_pack_start(GTK_BOX(export_hbox), export_button_,
+                     FALSE, FALSE, 0);
+
+  // Select the initial certificate in the hierarchy.
+  gtk_tree_selection_select_iter(hierarchy_selection_, &hierarchy_leaf_iter);
+}
+
+// static
+void CertificateViewer::OnHierarchySelectionChanged(
+    GtkTreeSelection* selection, CertificateViewer* viewer) {
+  GtkTreeIter iter;
+  GtkTreeModel* model;
+  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+    GtkTreeStore* fields_store = NULL;
+    gtk_tree_model_get(model, &iter, HIERARCHY_OBJECT, &fields_store, -1);
+    gtk_tree_view_set_model(GTK_TREE_VIEW(viewer->fields_tree_),
+                            GTK_TREE_MODEL(fields_store));
+    gtk_tree_view_expand_all(GTK_TREE_VIEW(viewer->fields_tree_));
+    gtk_widget_set_sensitive(viewer->export_button_, TRUE);
+  } else {
+    gtk_tree_view_set_model(GTK_TREE_VIEW(viewer->fields_tree_), NULL);
+    gtk_widget_set_sensitive(viewer->export_button_, FALSE);
+  }
+}
+
+// static
+void CertificateViewer::OnFieldsSelectionChanged(GtkTreeSelection* selection,
+                                                 CertificateViewer* viewer) {
+  GtkTreeIter iter;
+  GtkTreeModel* model;
+  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+    gchar* value_string = NULL;
+    gtk_tree_model_get(model, &iter, FIELDS_VALUE, &value_string, -1);
+    if (value_string) {
+      gtk_text_buffer_set_text(viewer->field_value_buffer_, value_string, -1);
+      g_free(value_string);
+    } else {
+      gtk_text_buffer_set_text(viewer->field_value_buffer_, "", 0);
+    }
+  } else {
+    gtk_text_buffer_set_text(viewer->field_value_buffer_, "", 0);
+  }
+}
+
+// static
+void CertificateViewer::OnExportClicked(GtkButton *button,
+                                        CertificateViewer* viewer) {
+  GtkTreeIter iter;
+  GtkTreeModel* model;
+  if (!gtk_tree_selection_get_selected(viewer->hierarchy_selection_, &model,
+                                       &iter))
+    return;
+  gint cert_index = -1;
+  gtk_tree_model_get(model, &iter, HIERARCHY_INDEX, &cert_index, -1);
+
+  if (cert_index < 0) {
+    NOTREACHED();
+    return;
+  }
+
+  ShowCertExportDialog(GTK_WINDOW(viewer->dialog_),
+                       viewer->cert_chain_list_[cert_index]);
+}
+
+void CertificateViewer::Show() {
+  gtk_util::ShowDialog(dialog_);
+}
+
+} // namespace
+
+void ShowCertificateViewer(gfx::NativeWindow parent,
+                           net::X509Certificate::OSCertHandle cert) {
+  net::X509Certificate::OSCertHandles cert_chain;
+  x509_certificate_model::GetCertChainFromCert(cert, &cert_chain);
+  (new CertificateViewer(parent, cert_chain))->Show();
+}
+
+void ShowCertificateViewer(gfx::NativeWindow parent,
+                           net::X509Certificate* cert) {
+  ShowCertificateViewer(parent, cert->os_cert_handle());
+}
diff --git a/chrome/browser/ui/gtk/certificate_viewer.h b/chrome/browser/ui/gtk/certificate_viewer.h
new file mode 100644
index 0000000..c31477c
--- /dev/null
+++ b/chrome/browser/ui/gtk/certificate_viewer.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_CERTIFICATE_VIEWER_H_
+#define CHROME_BROWSER_UI_GTK_CERTIFICATE_VIEWER_H_
+#pragma once
+
+#include "chrome/browser/certificate_viewer.h"
+#include "net/base/x509_certificate.h"
+#include "ui/gfx/native_widget_types.h"
+
+void ShowCertificateViewer(gfx::NativeWindow parent,
+                           net::X509Certificate::OSCertHandle);
+
+#endif  // CHROME_BROWSER_UI_GTK_CERTIFICATE_VIEWER_H_
diff --git a/chrome/browser/ui/gtk/chrome_gtk_frame.cc b/chrome/browser/ui/gtk/chrome_gtk_frame.cc
new file mode 100644
index 0000000..d649ba7
--- /dev/null
+++ b/chrome/browser/ui/gtk/chrome_gtk_frame.cc
@@ -0,0 +1,155 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/chrome_gtk_frame.h"
+
+G_BEGIN_DECLS
+
+// MetaFrames declaration
+G_DEFINE_TYPE(MetaFrames, meta_frames, GTK_TYPE_WINDOW)
+
+static void meta_frames_class_init(MetaFramesClass* frames_class) {
+  // Noop since we don't declare anything.
+}
+
+static void meta_frames_init(MetaFrames* button) {
+}
+
+
+// ChromeGtkFrame declaration
+G_DEFINE_TYPE(ChromeGtkFrame, chrome_gtk_frame, meta_frames_get_type())
+
+static void chrome_gtk_frame_class_init(ChromeGtkFrameClass* frame_class) {
+  GtkWidgetClass* widget_class = reinterpret_cast<GtkWidgetClass*>(frame_class);
+
+  // Frame tints:
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "frame-color",
+          "Frame Color",
+          "The color that the chrome frame will be. (If unspecified, "
+            " Chrome will take ChromeGtkFrame::bg[SELECTED] and slightly darken"
+            " it.)",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "inactive-frame-color",
+          "Inactive Frame Color",
+          "The color that the inactive chrome frame will be. (If"
+            " unspecified, Chrome will take ChromeGtkFrame::bg[INSENSITIVE]"
+            " and slightly darken it.)",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "incognito-frame-color",
+          "Incognito Frame Color",
+          "The color that the incognito frame will be. (If unspecified,"
+            " Chrome will take the frame color and tint it by Chrome's default"
+            " incognito tint.)",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "incognito-inactive-frame-color",
+          "Incognito Inactive Frame Color",
+          "The color that the inactive incognito frame will be. (If"
+            " unspecified, Chrome will take the frame color and tint it by"
+            " Chrome's default incognito tint.)",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+
+  // Frame gradient control:
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_int(
+          "frame-gradient-size",
+          "Chrome Frame Gradient Size",
+          "The size of the gradient on top of the frame image. Specify 0 to"
+            " make the frame a solid color.",
+          0,      // 0 disables the gradient
+          128,    // The frame image is only up to 128 pixels tall.
+          16,     // By default, gradients are 16 pixels high.
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "frame-gradient-color",
+          "Frame Gradient Color",
+          "The top color of the chrome frame gradient. (If unspecified,"
+            " chrome will create a lighter tint of frame-color",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "inactive-frame-gradient-color",
+          "Inactive Frame Gradient Color",
+          "The top color of the inactive chrome frame gradient. (If"
+            " unspecified, chrome will create a lighter tint of frame-color",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "incognito-frame-gradient-color",
+          "Incognito Frame Gradient Color",
+          "The top color of the incognito chrome frame gradient. (If"
+            " unspecified, chrome will create a lighter tint of frame-color",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "incognito-inactive-frame-gradient-color",
+          "Incognito Inactive Frame Gradient Color",
+          "The top color of the incognito inactive chrome frame gradient. (If"
+            " unspecified, chrome will create a lighter tint of frame-color",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+
+  // Scrollbar color properties:
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "scrollbar-slider-prelight-color",
+          "Scrollbar Slider Prelight Color",
+          "The color applied to the mouse is above the tab",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "scrollbar-slider-normal-color",
+          "Scrollbar Slider Normal Color",
+          "The color applied to the slider normally",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+  gtk_widget_class_install_style_property(
+      widget_class,
+      g_param_spec_boxed(
+          "scrollbar-trough-color",
+          "Scrollbar Trough Color",
+          "The background color of the slider track",
+          GDK_TYPE_COLOR,
+          G_PARAM_READABLE));
+}
+
+static void chrome_gtk_frame_init(ChromeGtkFrame* frame) {
+}
+
+GtkWidget* chrome_gtk_frame_new(void) {
+  GtkWindow* window =
+      GTK_WINDOW(g_object_new(chrome_gtk_frame_get_type(), NULL));
+  window->type = GTK_WINDOW_TOPLEVEL;
+  return GTK_WIDGET(window);
+}
+
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/chrome_gtk_frame.h b/chrome/browser/ui/gtk/chrome_gtk_frame.h
new file mode 100644
index 0000000..bbcb2fa
--- /dev/null
+++ b/chrome/browser/ui/gtk/chrome_gtk_frame.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_CHROME_GTK_FRAME_H_
+#define CHROME_BROWSER_UI_GTK_CHROME_GTK_FRAME_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwindow.h>
+
+G_BEGIN_DECLS
+
+// This file declares two subclasses of GtkWindow for easier gtk+ theme
+// integration.
+//
+// The first is "MetaFrames," which is (was?) the name of a gobject class in
+// the metacity window manager. To actually get at those values, we need to
+// have an object whose gobject class name string matches the definitions in
+// the gtkrc file. MetaFrames derives from GtkWindow.
+//
+// Metaframes can not be instantiated. It has no constructor; instantiate
+// ChromeGtkFrame instead.
+typedef struct _MetaFrames       MetaFrames;
+typedef struct _MetaFramesClass  MetaFramesClass;
+
+struct _MetaFrames {
+  GtkWindow window;
+};
+
+struct _MetaFramesClass {
+  GtkWindowClass parent_class;
+};
+
+
+// The second is ChromeGtkFrame, which defines a number of optional style
+// properties so theme authors can control how chromium appears in gtk-theme
+// mode.  It derives from MetaFrames in chrome so older themes that declare a
+// MetaFrames theme will still work. New themes should target this class.
+typedef struct _ChromeGtkFrame       ChromeGtkFrame;
+typedef struct _ChromeGtkFrameClass  ChromeGtkFrameClass;
+
+struct _ChromeGtkFrame {
+  MetaFrames frames;
+};
+
+struct _ChromeGtkFrameClass {
+  MetaFramesClass frames_class;
+};
+
+// Creates a GtkWindow object the the class name "ChromeGtkFrame".
+GtkWidget* chrome_gtk_frame_new();
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_CHROME_GTK_FRAME_H_
diff --git a/chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.cc b/chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.cc
new file mode 100644
index 0000000..5cf1cbc
--- /dev/null
+++ b/chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.cc
@@ -0,0 +1,254 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h"
+
+#include <string>
+
+#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Returns true if the checkbox is checked.
+gboolean IsChecked(GtkWidget* widget) {
+  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
+}  // namespace
+
+// static
+void ClearBrowsingDataDialogGtk::Show(GtkWindow* parent, Profile* profile) {
+  new ClearBrowsingDataDialogGtk(parent, profile);
+}
+
+ClearBrowsingDataDialogGtk::ClearBrowsingDataDialogGtk(GtkWindow* parent,
+                                                       Profile* profile) :
+    profile_(profile), remover_(NULL) {
+  // Build the dialog.
+  std::string dialog_name = l10n_util::GetStringUTF8(
+      IDS_CLEAR_BROWSING_DATA_TITLE);
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      parent,
+      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      NULL);
+
+  GtkWidget* cancel_button = gtk_dialog_add_button(GTK_DIALOG(dialog_),
+      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+  gtk_widget_grab_focus(cancel_button);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(dialog_, profile));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(IDS_CLEAR_BROWSING_DATA_COMMIT).c_str(),
+      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
+
+  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(content_area), vbox);
+
+  // Label on top of the checkboxes.
+  GtkWidget* description = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_CLEAR_BROWSING_DATA_LABEL).c_str());
+  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);
+
+  // History checkbox.
+  del_history_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DEL_BROWSING_HISTORY_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), del_history_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_history_checkbox_),
+      profile_->GetPrefs()->GetBoolean(prefs::kDeleteBrowsingHistory));
+  g_signal_connect(del_history_checkbox_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Downloads checkbox.
+  del_downloads_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DEL_DOWNLOAD_HISTORY_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), del_downloads_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_downloads_checkbox_),
+      profile_->GetPrefs()->GetBoolean(prefs::kDeleteDownloadHistory));
+  g_signal_connect(del_downloads_checkbox_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Cache checkbox.
+  del_cache_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DEL_CACHE_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), del_cache_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_cache_checkbox_),
+      profile_->GetPrefs()->GetBoolean(prefs::kDeleteCache));
+  g_signal_connect(del_cache_checkbox_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Cookies checkbox.
+  del_cookies_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DEL_COOKIES_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), del_cookies_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_cookies_checkbox_),
+      profile_->GetPrefs()->GetBoolean(prefs::kDeleteCookies));
+  g_signal_connect(del_cookies_checkbox_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Passwords checkbox.
+  del_passwords_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DEL_PASSWORDS_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), del_passwords_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_passwords_checkbox_),
+      profile_->GetPrefs()->GetBoolean(prefs::kDeletePasswords));
+  g_signal_connect(del_passwords_checkbox_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Form data checkbox.
+  del_form_data_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DEL_FORM_DATA_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), del_form_data_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(del_form_data_checkbox_),
+      profile_->GetPrefs()->GetBoolean(prefs::kDeleteFormData));
+  g_signal_connect(del_form_data_checkbox_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Create a horizontal layout for the combo box and label.
+  GtkWidget* combo_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  GtkWidget* time_period_label_ = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_CLEAR_BROWSING_DATA_TIME_LABEL).c_str());
+  gtk_box_pack_start(GTK_BOX(combo_hbox), time_period_label_, FALSE, FALSE, 0);
+
+  // Time period combo box items.
+  time_period_combobox_ = gtk_combo_box_new_text();
+  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
+      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_HOUR).c_str());
+  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
+      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_DAY).c_str());
+  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
+      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_WEEK).c_str());
+  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
+      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_4WEEKS).c_str());
+  gtk_combo_box_append_text(GTK_COMBO_BOX(time_period_combobox_),
+      l10n_util::GetStringUTF8(IDS_CLEAR_DATA_EVERYTHING).c_str());
+  gtk_combo_box_set_active(GTK_COMBO_BOX(time_period_combobox_),
+      profile_->GetPrefs()->GetInteger(prefs::kDeleteTimePeriod));
+  gtk_box_pack_start(GTK_BOX(combo_hbox),
+                     time_period_combobox_, FALSE, FALSE, 0);
+  g_signal_connect(time_period_combobox_, "changed",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  // Add the combo/label time period box to the vertical layout.
+  gtk_box_pack_start(GTK_BOX(vbox), combo_hbox, FALSE, FALSE, 0);
+
+  // Add widgets for the area below the accept buttons.
+  GtkWidget* flash_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_SETTINGS).c_str());
+  g_signal_connect(G_OBJECT(flash_link), "clicked",
+                   G_CALLBACK(OnFlashLinkClickedThunk), this);
+  GtkWidget* flash_link_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(flash_link_hbox), flash_link, FALSE, FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(content_area), flash_link_hbox, FALSE, FALSE, 0);
+
+  GtkWidget* separator = gtk_hseparator_new();
+  gtk_box_pack_end(GTK_BOX(content_area), separator, FALSE, FALSE, 0);
+
+  // Make sure we can move things around.
+  DCHECK_EQ(GTK_DIALOG(dialog_)->action_area->parent, content_area);
+
+  // Now rearrange those because they're *above* the accept buttons...there's
+  // no way to place them in the correct position with gtk_box_pack_end() so
+  // manually move things into the correct order.
+  gtk_box_reorder_child(GTK_BOX(content_area), flash_link_hbox, -1);
+  gtk_box_reorder_child(GTK_BOX(content_area), separator, -1);
+  gtk_box_reorder_child(GTK_BOX(content_area), GTK_DIALOG(dialog_)->action_area,
+                        -1);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+
+  UpdateDialogButtons();
+
+  gtk_util::ShowModalDialogWithMinLocalizedWidth(dialog_,
+      IDS_CLEARDATA_DIALOG_WIDTH_CHARS);
+}
+
+ClearBrowsingDataDialogGtk::~ClearBrowsingDataDialogGtk() {
+}
+
+void ClearBrowsingDataDialogGtk::OnDialogResponse(GtkWidget* widget,
+                                                  int response) {
+  if (response == GTK_RESPONSE_ACCEPT) {
+    PrefService* prefs = profile_->GetPrefs();
+    prefs->SetBoolean(prefs::kDeleteBrowsingHistory,
+                      IsChecked(del_history_checkbox_));
+    prefs->SetBoolean(prefs::kDeleteDownloadHistory,
+                      IsChecked(del_downloads_checkbox_));
+    prefs->SetBoolean(prefs::kDeleteCache,
+                      IsChecked(del_cache_checkbox_));
+    prefs->SetBoolean(prefs::kDeleteCookies,
+                      IsChecked(del_cookies_checkbox_));
+    prefs->SetBoolean(prefs::kDeletePasswords,
+                      IsChecked(del_passwords_checkbox_));
+    prefs->SetBoolean(prefs::kDeleteFormData,
+                      IsChecked(del_form_data_checkbox_));
+    prefs->SetInteger(prefs::kDeleteTimePeriod,
+        gtk_combo_box_get_active(GTK_COMBO_BOX(time_period_combobox_)));
+
+    int period_selected = gtk_combo_box_get_active(
+        GTK_COMBO_BOX(time_period_combobox_));
+
+    // BrowsingDataRemover deletes itself when done.
+    remover_ = new BrowsingDataRemover(profile_,
+        static_cast<BrowsingDataRemover::TimePeriod>(period_selected),
+        base::Time());
+    remover_->Remove(GetCheckedItems());
+  }
+
+  delete this;
+  gtk_widget_destroy(GTK_WIDGET(widget));
+}
+
+void ClearBrowsingDataDialogGtk::OnDialogWidgetClicked(GtkWidget* widget) {
+  UpdateDialogButtons();
+}
+
+void ClearBrowsingDataDialogGtk::OnFlashLinkClicked(GtkWidget* button) {
+  // We open a new browser window so the Options dialog doesn't get lost
+  // behind other windows.
+  Browser* browser = Browser::Create(profile_);
+  browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)),
+                   GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+  browser->window()->Show();
+}
+
+void ClearBrowsingDataDialogGtk::UpdateDialogButtons() {
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT,
+                                    GetCheckedItems() != 0);
+}
+
+int ClearBrowsingDataDialogGtk::GetCheckedItems() {
+  int items = 0;
+  if (IsChecked(del_history_checkbox_))
+    items |= BrowsingDataRemover::REMOVE_HISTORY;
+  if (IsChecked(del_downloads_checkbox_))
+    items |= BrowsingDataRemover::REMOVE_DOWNLOADS;
+  if (IsChecked(del_cookies_checkbox_))
+    items |= BrowsingDataRemover::REMOVE_COOKIES;
+  if (IsChecked(del_passwords_checkbox_))
+    items |= BrowsingDataRemover::REMOVE_PASSWORDS;
+  if (IsChecked(del_form_data_checkbox_))
+    items |= BrowsingDataRemover::REMOVE_FORM_DATA;
+  if (IsChecked(del_cache_checkbox_))
+    items |= BrowsingDataRemover::REMOVE_CACHE;
+  return items;
+}
diff --git a/chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h b/chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h
new file mode 100644
index 0000000..567cb4b
--- /dev/null
+++ b/chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_CLEAR_BROWSING_DATA_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_CLEAR_BROWSING_DATA_DIALOG_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkWindow GtkWindow;
+
+class AccessibleWidgetHelper;
+class BrowsingDataRemover;
+class Profile;
+
+class ClearBrowsingDataDialogGtk {
+ public:
+  // Displays the dialog box to clear browsing data from |profile|.
+  static void Show(GtkWindow* parent, Profile* profile);
+
+ private:
+  ClearBrowsingDataDialogGtk(GtkWindow* parent, Profile* profile);
+  ~ClearBrowsingDataDialogGtk();
+
+  // Handler to respond to Ok and Cancel responses from the dialog.
+  CHROMEGTK_CALLBACK_1(ClearBrowsingDataDialogGtk, void, OnDialogResponse, int);
+
+  // Handler to respond to widget clicked actions from the dialog.
+  CHROMEGTK_CALLBACK_0(ClearBrowsingDataDialogGtk, void, OnDialogWidgetClicked);
+
+  CHROMEGTK_CALLBACK_0(ClearBrowsingDataDialogGtk, void, OnFlashLinkClicked);
+
+  // Enable or disable the dialog buttons depending on the state of the
+  // checkboxes.
+  void UpdateDialogButtons();
+
+  // Create a bitmask from the checkboxes of the dialog.
+  int GetCheckedItems();
+
+  // The dialog window.
+  GtkWidget* dialog_;
+
+  // UI elements.
+  GtkWidget* del_history_checkbox_;
+  GtkWidget* del_downloads_checkbox_;
+  GtkWidget* del_cache_checkbox_;
+  GtkWidget* del_cookies_checkbox_;
+  GtkWidget* del_passwords_checkbox_;
+  GtkWidget* del_form_data_checkbox_;
+  GtkWidget* time_period_combobox_;
+
+  // Our current profile.
+  Profile* profile_;
+
+  // If non-null it means removal is in progress. BrowsingDataRemover takes care
+  // of deleting itself when done.
+  BrowsingDataRemover* remover_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClearBrowsingDataDialogGtk);
+};
+
+
+#endif  // CHROME_BROWSER_UI_GTK_CLEAR_BROWSING_DATA_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/collected_cookies_gtk.cc b/chrome/browser/ui/gtk/collected_cookies_gtk.cc
new file mode 100644
index 0000000..2c2349e
--- /dev/null
+++ b/chrome/browser/ui/gtk/collected_cookies_gtk.cc
@@ -0,0 +1,401 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/collected_cookies_gtk.h"
+
+#include <string>
+
+#include "chrome/browser/cookies_tree_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_source.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+// Width and height of the cookie tree view.
+const int kTreeViewWidth = 450;
+const int kTreeViewHeight = 150;
+
+// Padding within the banner box.
+const int kBannerPadding = 3;
+
+// Returns the text to display in the info bar when content settings were
+// created.
+const std::string GetInfobarLabel(ContentSetting setting,
+                                  bool multiple_domains_added,
+                                  const string16& domain_name) {
+  if (multiple_domains_added) {
+    switch (setting) {
+      case CONTENT_SETTING_BLOCK:
+        return l10n_util::GetStringUTF8(
+            IDS_COLLECTED_COOKIES_MULTIPLE_BLOCK_RULES_CREATED);
+
+      case CONTENT_SETTING_ALLOW:
+        return l10n_util::GetStringUTF8(
+            IDS_COLLECTED_COOKIES_MULTIPLE_ALLOW_RULES_CREATED);
+
+      case CONTENT_SETTING_SESSION_ONLY:
+        return l10n_util::GetStringUTF8(
+            IDS_COLLECTED_COOKIES_MULTIPLE_SESSION_RULES_CREATED);
+
+      default:
+        NOTREACHED();
+        return std::string();
+    }
+  }
+
+  switch (setting) {
+    case CONTENT_SETTING_BLOCK:
+      return l10n_util::GetStringFUTF8(
+          IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name);
+
+    case CONTENT_SETTING_ALLOW:
+      return l10n_util::GetStringFUTF8(
+          IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name);
+
+    case CONTENT_SETTING_SESSION_ONLY:
+      return l10n_util::GetStringFUTF8(
+          IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name);
+
+    default:
+      NOTREACHED();
+      return std::string();
+  }
+}
+}  // namespace
+
+CollectedCookiesGtk::CollectedCookiesGtk(GtkWindow* parent,
+                                         TabContents* tab_contents)
+    : tab_contents_(tab_contents) {
+  TabSpecificContentSettings* content_settings =
+      tab_contents->GetTabSpecificContentSettings();
+  registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN,
+                 Source<TabSpecificContentSettings>(content_settings));
+
+  Init();
+}
+
+void CollectedCookiesGtk::Init() {
+  HostContentSettingsMap* host_content_settings_map =
+      tab_contents_->profile()->GetHostContentSettingsMap();
+
+  dialog_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_box_set_spacing(GTK_BOX(dialog_), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_DIALOG_TITLE).c_str());
+  gtk_box_pack_start(GTK_BOX(dialog_), label, TRUE, TRUE, 0);
+
+  // Allowed Cookie list.
+  GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(dialog_), cookie_list_vbox, TRUE, TRUE, 0);
+
+  label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL).
+          c_str());
+  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), label, FALSE, FALSE, 0);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
+
+  TabSpecificContentSettings* content_settings =
+      tab_contents_->GetTabSpecificContentSettings();
+
+  allowed_cookies_tree_model_.reset(
+      content_settings->GetAllowedCookiesTreeModel());
+  allowed_cookies_tree_adapter_.reset(
+      new gtk_tree::TreeAdapter(this, allowed_cookies_tree_model_.get()));
+  allowed_tree_ = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(allowed_cookies_tree_adapter_->tree_store()));
+  gtk_widget_set_size_request(allowed_tree_, kTreeViewWidth, kTreeViewHeight);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(allowed_tree_), FALSE);
+  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(allowed_tree_), TRUE);
+  gtk_container_add(GTK_CONTAINER(scroll_window), allowed_tree_);
+
+  GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
+  GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
+  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
+                                     gtk_tree::TreeAdapter::COL_ICON);
+  GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
+  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
+                                     gtk_tree::TreeAdapter::COL_TITLE);
+  gtk_tree_view_column_set_title(
+      title_column, l10n_util::GetStringUTF8(
+          IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
+  gtk_tree_view_append_column(GTK_TREE_VIEW(allowed_tree_), title_column);
+  g_signal_connect(allowed_tree_, "row-expanded",
+                   G_CALLBACK(OnTreeViewRowExpandedThunk), this);
+  allowed_selection_ =
+      gtk_tree_view_get_selection(GTK_TREE_VIEW(allowed_tree_));
+  gtk_tree_selection_set_mode(allowed_selection_, GTK_SELECTION_MULTIPLE);
+  g_signal_connect(allowed_selection_, "changed",
+                   G_CALLBACK(OnTreeViewSelectionChangeThunk), this);
+
+  GtkWidget* button_box = gtk_hbutton_box_new();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START);
+  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(dialog_), button_box, FALSE, FALSE, 0);
+  block_allowed_cookie_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_BLOCK_BUTTON).c_str());
+  g_signal_connect(block_allowed_cookie_button_, "clicked",
+                   G_CALLBACK(OnBlockAllowedButtonClickedThunk), this);
+  gtk_container_add(GTK_CONTAINER(button_box), block_allowed_cookie_button_);
+
+  GtkWidget* separator = gtk_hseparator_new();
+  gtk_box_pack_start(GTK_BOX(dialog_), separator, TRUE, TRUE, 0);
+
+  // Blocked Cookie list.
+  cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(dialog_), cookie_list_vbox, TRUE, TRUE, 0);
+
+  label = gtk_label_new(
+      l10n_util::GetStringUTF8(
+          host_content_settings_map->BlockThirdPartyCookies() ?
+              IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED :
+              IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL).c_str());
+  gtk_widget_set_size_request(label, kTreeViewWidth, -1);
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), label, TRUE, TRUE, 0);
+
+  scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
+
+  blocked_cookies_tree_model_.reset(
+      content_settings->GetBlockedCookiesTreeModel());
+  blocked_cookies_tree_adapter_.reset(
+      new gtk_tree::TreeAdapter(this, blocked_cookies_tree_model_.get()));
+  blocked_tree_ = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(blocked_cookies_tree_adapter_->tree_store()));
+  gtk_widget_set_size_request(blocked_tree_, kTreeViewWidth, kTreeViewHeight);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(blocked_tree_), FALSE);
+  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(blocked_tree_), TRUE);
+  gtk_container_add(GTK_CONTAINER(scroll_window), blocked_tree_);
+
+  title_column = gtk_tree_view_column_new();
+  pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
+  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
+                                     gtk_tree::TreeAdapter::COL_ICON);
+  title_renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
+  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
+                                     gtk_tree::TreeAdapter::COL_TITLE);
+  gtk_tree_view_column_set_title(
+      title_column, l10n_util::GetStringUTF8(
+          IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
+  gtk_tree_view_append_column(GTK_TREE_VIEW(blocked_tree_), title_column);
+  g_signal_connect(blocked_tree_, "row-expanded",
+                   G_CALLBACK(OnTreeViewRowExpandedThunk), this);
+  blocked_selection_ =
+      gtk_tree_view_get_selection(GTK_TREE_VIEW(blocked_tree_));
+  gtk_tree_selection_set_mode(blocked_selection_, GTK_SELECTION_MULTIPLE);
+  g_signal_connect(blocked_selection_, "changed",
+                   G_CALLBACK(OnTreeViewSelectionChangeThunk), this);
+
+  button_box = gtk_hbutton_box_new();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START);
+  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(dialog_), button_box, FALSE, FALSE, 0);
+  allow_blocked_cookie_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOW_BUTTON).c_str());
+  g_signal_connect(allow_blocked_cookie_button_, "clicked",
+                   G_CALLBACK(OnAllowBlockedButtonClickedThunk), this);
+  gtk_container_add(GTK_CONTAINER(button_box), allow_blocked_cookie_button_);
+  for_session_blocked_cookie_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON).
+          c_str());
+  g_signal_connect(for_session_blocked_cookie_button_, "clicked",
+                   G_CALLBACK(OnForSessionBlockedButtonClickedThunk), this);
+  gtk_container_add(GTK_CONTAINER(button_box),
+                    for_session_blocked_cookie_button_);
+
+  // Infobar.
+  infobar_ = gtk_frame_new(NULL);
+  GtkWidget* infobar_contents = gtk_hbox_new(FALSE, kBannerPadding);
+  gtk_container_set_border_width(GTK_CONTAINER(infobar_contents),
+                                 kBannerPadding);
+  gtk_container_add(GTK_CONTAINER(infobar_), infobar_contents);
+  GtkWidget* info_image =
+      gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,
+                               GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_box_pack_start(GTK_BOX(infobar_contents), info_image, FALSE, FALSE, 0);
+  infobar_label_ = gtk_label_new(NULL);
+  gtk_box_pack_start(
+      GTK_BOX(infobar_contents), infobar_label_, FALSE, FALSE, 0);
+  gtk_widget_show_all(infobar_);
+  gtk_widget_set_no_show_all(infobar_, TRUE);
+  gtk_widget_hide(infobar_);
+  gtk_box_pack_start(GTK_BOX(dialog_), infobar_, TRUE, TRUE, 0);
+
+  // Close button.
+  button_box = gtk_hbutton_box_new();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
+  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
+  gtk_box_pack_end(GTK_BOX(dialog_), button_box, FALSE, TRUE, 0);
+  GtkWidget* close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
+  gtk_button_set_label(GTK_BUTTON(close),
+                       l10n_util::GetStringUTF8(IDS_CLOSE).c_str());
+  g_signal_connect(close, "clicked", G_CALLBACK(OnCloseThunk), this);
+  gtk_box_pack_end(GTK_BOX(button_box), close, FALSE, TRUE, 0);
+
+  // Show the dialog.
+  allowed_cookies_tree_adapter_->Init();
+  blocked_cookies_tree_adapter_->Init();
+  EnableControls();
+  window_ = tab_contents_->CreateConstrainedDialog(this);
+}
+
+CollectedCookiesGtk::~CollectedCookiesGtk() {
+  gtk_widget_destroy(dialog_);
+}
+
+GtkWidget* CollectedCookiesGtk::GetWidgetRoot() {
+  return dialog_;
+}
+
+void CollectedCookiesGtk::DeleteDelegate() {
+  delete this;
+}
+
+bool CollectedCookiesGtk::SelectionContainsOriginNode(
+    GtkTreeSelection* selection, gtk_tree::TreeAdapter* adapter) {
+  // Check whether at least one "origin" node is selected.
+  GtkTreeModel* model;
+  GList* paths =
+      gtk_tree_selection_get_selected_rows(selection, &model);
+  bool contains_origin_node = false;
+  for (GList* item = paths; item; item = item->next) {
+    GtkTreeIter iter;
+    gtk_tree_model_get_iter(
+        model, &iter, reinterpret_cast<GtkTreePath*>(item->data));
+    CookieTreeNode* node =
+        static_cast<CookieTreeNode*>(adapter->GetNode(&iter));
+    if (node->GetDetailedInfo().node_type !=
+        CookieTreeNode::DetailedInfo::TYPE_ORIGIN)
+      continue;
+    CookieTreeOriginNode* origin_node = static_cast<CookieTreeOriginNode*>(
+        node);
+    if (!origin_node->CanCreateContentException())
+      continue;
+    contains_origin_node = true;
+  }
+  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
+  g_list_free(paths);
+  return contains_origin_node;
+}
+
+void CollectedCookiesGtk::EnableControls() {
+  // Update button states.
+  bool enable_for_allowed_cookies =
+      SelectionContainsOriginNode(allowed_selection_,
+                                  allowed_cookies_tree_adapter_.get());
+  gtk_widget_set_sensitive(block_allowed_cookie_button_,
+                           enable_for_allowed_cookies);
+
+  bool enable_for_blocked_cookies =
+      SelectionContainsOriginNode(blocked_selection_,
+                                  blocked_cookies_tree_adapter_.get());
+  gtk_widget_set_sensitive(allow_blocked_cookie_button_,
+                           enable_for_blocked_cookies);
+  gtk_widget_set_sensitive(for_session_blocked_cookie_button_,
+                           enable_for_blocked_cookies);
+}
+
+void CollectedCookiesGtk::Observe(NotificationType type,
+                                  const NotificationSource& source,
+                                  const NotificationDetails& details) {
+  DCHECK(type == NotificationType::COLLECTED_COOKIES_SHOWN);
+  DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(),
+            tab_contents_->GetTabSpecificContentSettings());
+  window_->CloseConstrainedWindow();
+}
+
+void CollectedCookiesGtk::OnClose(GtkWidget* close_button) {
+  window_->CloseConstrainedWindow();
+}
+
+void CollectedCookiesGtk::AddExceptions(GtkTreeSelection* selection,
+                                        gtk_tree::TreeAdapter* adapter,
+                                        ContentSetting setting) {
+  GtkTreeModel* model;
+  GList* paths =
+      gtk_tree_selection_get_selected_rows(selection, &model);
+  string16 last_domain_name;
+  bool multiple_domains_added = false;
+  for (GList* item = paths; item; item = item->next) {
+    GtkTreeIter iter;
+    gtk_tree_model_get_iter(
+        model, &iter, reinterpret_cast<GtkTreePath*>(item->data));
+    CookieTreeNode* node =
+        static_cast<CookieTreeNode*>(adapter->GetNode(&iter));
+    if (node->GetDetailedInfo().node_type !=
+        CookieTreeNode::DetailedInfo::TYPE_ORIGIN)
+      continue;
+    CookieTreeOriginNode* origin_node = static_cast<CookieTreeOriginNode*>(
+        node);
+    if (origin_node->CanCreateContentException()) {
+      if (!last_domain_name.empty())
+        multiple_domains_added = true;
+      last_domain_name = origin_node->GetTitle();
+      origin_node->CreateContentException(
+          tab_contents_->profile()->GetHostContentSettingsMap(), setting);
+    }
+  }
+  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
+  g_list_free(paths);
+  if (last_domain_name.empty()) {
+    gtk_widget_hide(infobar_);
+  } else {
+    gtk_label_set_text(
+        GTK_LABEL(infobar_label_), GetInfobarLabel(
+            setting, multiple_domains_added, last_domain_name).c_str());
+    gtk_widget_show(infobar_);
+  }
+}
+
+void CollectedCookiesGtk::OnBlockAllowedButtonClicked(GtkWidget* button) {
+  AddExceptions(allowed_selection_, allowed_cookies_tree_adapter_.get(),
+                CONTENT_SETTING_BLOCK);
+}
+
+void CollectedCookiesGtk::OnAllowBlockedButtonClicked(GtkWidget* button) {
+  AddExceptions(blocked_selection_, blocked_cookies_tree_adapter_.get(),
+                CONTENT_SETTING_ALLOW);
+}
+
+void CollectedCookiesGtk::OnForSessionBlockedButtonClicked(GtkWidget* button) {
+  AddExceptions(blocked_selection_, blocked_cookies_tree_adapter_.get(),
+                CONTENT_SETTING_SESSION_ONLY);
+}
+
+void CollectedCookiesGtk::OnTreeViewRowExpanded(GtkWidget* tree_view,
+                                        GtkTreeIter* iter,
+                                        GtkTreePath* path) {
+  // When a row in the tree is expanded, expand all the children too.
+  g_signal_handlers_block_by_func(
+      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
+  gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
+  g_signal_handlers_unblock_by_func(
+      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
+}
+
+void CollectedCookiesGtk::OnTreeViewSelectionChange(GtkWidget* selection) {
+  EnableControls();
+}
diff --git a/chrome/browser/ui/gtk/collected_cookies_gtk.h b/chrome/browser/ui/gtk/collected_cookies_gtk.h
new file mode 100644
index 0000000..afb56fe
--- /dev/null
+++ b/chrome/browser/ui/gtk/collected_cookies_gtk.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2011 The Chromium 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 the Gtk implementation of the collected Cookies dialog.
+
+#ifndef CHROME_BROWSER_UI_GTK_COLLECTED_COOKIES_GTK_H_
+#define CHROME_BROWSER_UI_GTK_COLLECTED_COOKIES_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class CookiesTreeModel;
+
+// CollectedCookiesGtk is a dialog that displays the allowed and blocked
+// cookies of the current tab contents.  To display the dialog, invoke
+// ShowCollectedCookiesDialog() on the delegate of the tab contents.
+
+class CollectedCookiesGtk : public ConstrainedDialogDelegate,
+                                   gtk_tree::TreeAdapter::Delegate,
+                                   NotificationObserver {
+ public:
+  CollectedCookiesGtk(GtkWindow* parent, TabContents* tab_contents);
+
+  // ConstrainedDialogDelegate methods.
+  virtual GtkWidget* GetWidgetRoot();
+  virtual void DeleteDelegate();
+
+ private:
+  virtual ~CollectedCookiesGtk();
+
+  // Initialize all widgets of this dialog.
+  void Init();
+
+  // True if the selection contains at least one origin node.
+  bool SelectionContainsOriginNode(GtkTreeSelection* selection,
+                                   gtk_tree::TreeAdapter* adapter);
+
+  // Enable the allow/block buttons if at least one origin node is selected.
+  void EnableControls();
+
+  // Add exceptions for all origin nodes within the selection.
+  void AddExceptions(GtkTreeSelection* selection,
+                     gtk_tree::TreeAdapter* adapter,
+                     ContentSetting setting);
+
+  // Notification Observer implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Callbacks.
+  CHROMEGTK_CALLBACK_2(CollectedCookiesGtk, void, OnTreeViewRowExpanded,
+                       GtkTreeIter*, GtkTreePath*);
+  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnTreeViewSelectionChange);
+  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnClose);
+  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnBlockAllowedButtonClicked);
+  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void, OnAllowBlockedButtonClicked);
+  CHROMEGTK_CALLBACK_0(CollectedCookiesGtk, void,
+                       OnForSessionBlockedButtonClicked);
+
+  NotificationRegistrar registrar_;
+
+  ConstrainedWindow* window_;
+
+  // Widgets of the dialog.
+  GtkWidget* dialog_;
+
+  GtkWidget* allowed_description_label_;
+  GtkWidget* blocked_description_label_;
+
+  GtkWidget* block_allowed_cookie_button_;
+
+  GtkWidget* allow_blocked_cookie_button_;
+  GtkWidget* for_session_blocked_cookie_button_;
+
+  // The table listing the cookies.
+  GtkWidget* allowed_tree_;
+  GtkWidget* blocked_tree_;
+
+  GtkTreeSelection* allowed_selection_;
+  GtkTreeSelection* blocked_selection_;
+
+  // The infobar widget.
+  GtkWidget* infobar_;
+  GtkWidget* infobar_label_;
+
+  // The tab contents.
+  TabContents* tab_contents_;
+
+  // The Cookies Table model.
+  scoped_ptr<CookiesTreeModel> allowed_cookies_tree_model_;
+  scoped_ptr<CookiesTreeModel> blocked_cookies_tree_model_;
+  scoped_ptr<gtk_tree::TreeAdapter> allowed_cookies_tree_adapter_;
+  scoped_ptr<gtk_tree::TreeAdapter> blocked_cookies_tree_adapter_;
+
+  DISALLOW_COPY_AND_ASSIGN(CollectedCookiesGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_COLLECTED_COOKIES_GTK_H_
diff --git a/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc b/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc
new file mode 100644
index 0000000..ed8d532
--- /dev/null
+++ b/chrome/browser/ui/gtk/constrained_html_delegate_gtk.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/dom_ui/constrained_html_ui.h"
+
+#include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
+#include "chrome/common/notification_source.h"
+#include "ipc/ipc_message.h"
+#include "ui/gfx/rect.h"
+
+class ConstrainedHtmlDelegateGtk : public ConstrainedWindowGtkDelegate,
+                                   public HtmlDialogTabContentsDelegate,
+                                   public ConstrainedHtmlUIDelegate {
+ public:
+  ConstrainedHtmlDelegateGtk(Profile* profile,
+                           HtmlDialogUIDelegate* delegate);
+
+  virtual ~ConstrainedHtmlDelegateGtk();
+
+  // ConstrainedWindowGtkDelegate ----------------------------------------------
+  virtual GtkWidget* GetWidgetRoot() {
+    return tab_contents_container_.widget();
+  }
+  virtual void DeleteDelegate() {
+    html_delegate_->OnDialogClosed("");
+    delete this;
+  }
+
+  // ConstrainedHtmlDelegate ---------------------------------------------
+  virtual HtmlDialogUIDelegate* GetHtmlDialogUIDelegate();
+  virtual void OnDialogClose();
+  virtual bool GetBackgroundColor(GdkColor* color) {
+    *color = gtk_util::kGdkWhite;
+    return true;
+  }
+
+  // HtmlDialogTabContentsDelegate ---------------------------------------------
+  void MoveContents(TabContents* source, const gfx::Rect& pos) {}
+  void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
+  void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {}
+
+  void set_window(ConstrainedWindow* window) {
+    window_ = window;
+  }
+
+ private:
+  TabContents tab_contents_;
+  TabContentsContainerGtk tab_contents_container_;
+  HtmlDialogUIDelegate* html_delegate_;
+
+  // The constrained window that owns |this|. It's saved here because it needs
+  // to be closed in response to the WebUI OnDialogClose callback.
+  ConstrainedWindow* window_;
+};
+
+ConstrainedHtmlDelegateGtk::ConstrainedHtmlDelegateGtk(
+    Profile* profile,
+    HtmlDialogUIDelegate* delegate)
+    : HtmlDialogTabContentsDelegate(profile),
+      tab_contents_(profile, NULL, MSG_ROUTING_NONE, NULL, NULL),
+      tab_contents_container_(NULL),
+      html_delegate_(delegate),
+      window_(NULL) {
+  tab_contents_.set_delegate(this);
+
+  // Set |this| as a property on the tab contents so that the ConstrainedHtmlUI
+  // can get a reference to |this|.
+  ConstrainedHtmlUI::GetPropertyAccessor().SetProperty(
+      tab_contents_.property_bag(), this);
+
+  tab_contents_.controller().LoadURL(delegate->GetDialogContentURL(),
+                                     GURL(), PageTransition::START_PAGE);
+  tab_contents_container_.SetTabContents(&tab_contents_);
+
+  gfx::Size dialog_size;
+  delegate->GetDialogSize(&dialog_size);
+  gtk_widget_set_size_request(GTK_WIDGET(tab_contents_container_.widget()),
+                              dialog_size.width(),
+                              dialog_size.height());
+
+  gtk_widget_show_all(GetWidgetRoot());
+}
+
+ConstrainedHtmlDelegateGtk::~ConstrainedHtmlDelegateGtk() {
+}
+
+HtmlDialogUIDelegate*
+    ConstrainedHtmlDelegateGtk::GetHtmlDialogUIDelegate() {
+  return html_delegate_;
+}
+
+void ConstrainedHtmlDelegateGtk::OnDialogClose() {
+  window_->CloseConstrainedWindow();
+}
+
+// static
+void ConstrainedHtmlUI::CreateConstrainedHtmlDialog(
+    Profile* profile,
+    HtmlDialogUIDelegate* delegate,
+    TabContents* overshadowed) {
+  ConstrainedHtmlDelegateGtk* constrained_delegate =
+      new ConstrainedHtmlDelegateGtk(profile, delegate);
+  ConstrainedWindow* constrained_window =
+      overshadowed->CreateConstrainedDialog(constrained_delegate);
+  constrained_delegate->set_window(constrained_window);
+}
diff --git a/chrome/browser/ui/gtk/constrained_window_gtk.cc b/chrome/browser/ui/gtk/constrained_window_gtk.cc
new file mode 100644
index 0000000..0579efc
--- /dev/null
+++ b/chrome/browser/ui/gtk/constrained_window_gtk.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/constrained_window_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+
+#if defined(TOUCH_UI)
+#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"
+#else
+#include "chrome/browser/tab_contents/tab_contents_view_gtk.h"
+#endif
+
+ConstrainedWindowGtkDelegate::~ConstrainedWindowGtkDelegate() {
+}
+
+bool ConstrainedWindowGtkDelegate::GetBackgroundColor(GdkColor* color) {
+  return false;
+}
+
+ConstrainedWindowGtk::ConstrainedWindowGtk(
+    TabContents* owner, ConstrainedWindowGtkDelegate* delegate)
+    : owner_(owner),
+      delegate_(delegate),
+      visible_(false),
+      factory_(this) {
+  DCHECK(owner);
+  DCHECK(delegate);
+  GtkWidget* dialog = delegate->GetWidgetRoot();
+
+  // Unlike other users of CreateBorderBin, we need a dedicated frame around
+  // our "window".
+  GtkWidget* ebox = gtk_event_box_new();
+  GtkWidget* frame = gtk_frame_new(NULL);
+  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+
+  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder,
+      gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
+  GdkColor background;
+  if (delegate->GetBackgroundColor(&background)) {
+    gtk_widget_modify_base(ebox, GTK_STATE_NORMAL, &background);
+    gtk_widget_modify_fg(ebox, GTK_STATE_NORMAL, &background);
+    gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &background);
+  }
+
+  if (gtk_widget_get_parent(dialog))
+    gtk_widget_reparent(dialog, alignment);
+  else
+    gtk_container_add(GTK_CONTAINER(alignment), dialog);
+
+  gtk_container_add(GTK_CONTAINER(frame), alignment);
+  gtk_container_add(GTK_CONTAINER(ebox), frame);
+  border_.Own(ebox);
+
+  gtk_widget_add_events(widget(), GDK_KEY_PRESS_MASK);
+  g_signal_connect(widget(), "key-press-event", G_CALLBACK(OnKeyPressThunk),
+                   this);
+}
+
+ConstrainedWindowGtk::~ConstrainedWindowGtk() {
+  border_.Destroy();
+}
+
+void ConstrainedWindowGtk::ShowConstrainedWindow() {
+  gtk_widget_show_all(border_.get());
+
+  // We collaborate with TabContentsView and stick ourselves in the
+  // TabContentsView's floating container.
+  ContainingView()->AttachConstrainedWindow(this);
+
+  visible_ = true;
+}
+
+void ConstrainedWindowGtk::CloseConstrainedWindow() {
+  if (visible_)
+    ContainingView()->RemoveConstrainedWindow(this);
+  delegate_->DeleteDelegate();
+  owner_->WillClose(this);
+
+  delete this;
+}
+
+ConstrainedWindowGtk::TabContentsViewType*
+    ConstrainedWindowGtk::ContainingView() {
+  return static_cast<TabContentsViewType*>(owner_->view());
+}
+
+gboolean ConstrainedWindowGtk::OnKeyPress(GtkWidget* sender,
+                                          GdkEventKey* key) {
+  if (key->keyval == GDK_Escape) {
+    // Let the stack unwind so the event handler can release its ref
+    // on widget().
+    MessageLoop::current()->PostTask(FROM_HERE,
+        factory_.NewRunnableMethod(
+            &ConstrainedWindowGtk::CloseConstrainedWindow));
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+// static
+ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
+    TabContents* parent,
+    ConstrainedWindowGtkDelegate* delegate) {
+  return new ConstrainedWindowGtk(parent, delegate);
+}
diff --git a/chrome/browser/ui/gtk/constrained_window_gtk.h b/chrome/browser/ui/gtk/constrained_window_gtk.h
new file mode 100644
index 0000000..2f01079
--- /dev/null
+++ b/chrome/browser/ui/gtk/constrained_window_gtk.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_CONSTRAINED_WINDOW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_CONSTRAINED_WINDOW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/task.h"
+#include "chrome/browser/tab_contents/constrained_window.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class TabContents;
+typedef struct _GdkColor GdkColor;
+#if defined(TOUCH_UI)
+class TabContentsViewViews;
+#else
+class TabContentsViewGtk;
+#endif
+
+class ConstrainedWindowGtkDelegate {
+ public:
+  // Returns the widget that will be put in the constrained window's container.
+  virtual GtkWidget* GetWidgetRoot() = 0;
+
+  // Tells the delegate to either delete itself or set up a task to delete
+  // itself later.
+  virtual void DeleteDelegate() = 0;
+
+  virtual bool GetBackgroundColor(GdkColor* color);
+
+ protected:
+  virtual ~ConstrainedWindowGtkDelegate();
+};
+
+// Constrained window implementation for the GTK port. Unlike the Win32 system,
+// ConstrainedWindowGtk doesn't draw draggable fake windows and instead just
+// centers the dialog. It is thus an order of magnitude simpler.
+class ConstrainedWindowGtk : public ConstrainedWindow {
+ public:
+#if defined(TOUCH_UI)
+   typedef TabContentsViewViews TabContentsViewType;
+#else
+   typedef TabContentsViewGtk TabContentsViewType;
+#endif
+
+  virtual ~ConstrainedWindowGtk();
+
+  // Overridden from ConstrainedWindow:
+  virtual void ShowConstrainedWindow();
+  virtual void CloseConstrainedWindow();
+
+  // Returns the TabContents that constrains this Constrained Window.
+  TabContents* owner() const { return owner_; }
+
+  // Returns the toplevel widget that displays this "window".
+  GtkWidget* widget() { return border_.get(); }
+
+  // Returns the View that we collaborate with to position ourselves.
+  TabContentsViewType* ContainingView();
+
+ private:
+  friend class ConstrainedWindow;
+
+  ConstrainedWindowGtk(TabContents* owner,
+                       ConstrainedWindowGtkDelegate* delegate);
+
+  // Handler for Escape.
+  CHROMEGTK_CALLBACK_1(ConstrainedWindowGtk, gboolean, OnKeyPress,
+                       GdkEventKey*);
+
+  // The TabContents that owns and constrains this ConstrainedWindow.
+  TabContents* owner_;
+
+  // The top level widget container that exports to our TabContentsView.
+  OwnedWidgetGtk border_;
+
+  // Delegate that provides the contents of this constrained window.
+  ConstrainedWindowGtkDelegate* delegate_;
+
+  // Stores if |ShowConstrainedWindow()| has been called.
+  bool visible_;
+
+  ScopedRunnableMethodFactory<ConstrainedWindowGtk> factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_CONSTRAINED_WINDOW_GTK_H_
diff --git a/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc b/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc
new file mode 100644
index 0000000..b47770e
--- /dev/null
+++ b/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc
@@ -0,0 +1,316 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/content_setting_bubble_gtk.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/i18n/rtl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/blocked_content_container.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_setting_bubble_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/content_settings_window_gtk.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/gtk_util.h"
+#include "webkit/plugins/npapi/plugin_list.h"
+
+namespace {
+
+// Padding between content and edge of info bubble.
+const int kContentBorder = 7;
+
+// The maximum width of a title entry in the content box. We elide anything
+// longer than this.
+const int kMaxLinkPixelSize = 500;
+
+std::string BuildElidedText(const std::string& input) {
+  return UTF16ToUTF8(ui::ElideText(
+      UTF8ToUTF16(input),
+      gfx::Font(),
+      kMaxLinkPixelSize,
+      false));
+}
+
+}  // namespace
+
+ContentSettingBubbleGtk::ContentSettingBubbleGtk(
+    GtkWidget* anchor,
+    InfoBubbleGtkDelegate* delegate,
+    ContentSettingBubbleModel* content_setting_bubble_model,
+    Profile* profile,
+    TabContents* tab_contents)
+    : anchor_(anchor),
+      profile_(profile),
+      tab_contents_(tab_contents),
+      delegate_(delegate),
+      content_setting_bubble_model_(content_setting_bubble_model),
+      info_bubble_(NULL) {
+  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                 Source<TabContents>(tab_contents));
+  BuildBubble();
+}
+
+ContentSettingBubbleGtk::~ContentSettingBubbleGtk() {
+}
+
+void ContentSettingBubbleGtk::Close() {
+  if (info_bubble_)
+    info_bubble_->Close();
+}
+
+void ContentSettingBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                                bool closed_by_escape) {
+  delegate_->InfoBubbleClosing(info_bubble, closed_by_escape);
+  delete this;
+}
+
+void ContentSettingBubbleGtk::Observe(NotificationType type,
+                                      const NotificationSource& source,
+                                      const NotificationDetails& details) {
+  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
+  DCHECK(source == Source<TabContents>(tab_contents_));
+  tab_contents_ = NULL;
+}
+
+void ContentSettingBubbleGtk::BuildBubble() {
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(profile_);
+
+  GtkWidget* bubble_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder);
+
+  const ContentSettingBubbleModel::BubbleContent& content =
+      content_setting_bubble_model_->bubble_content();
+  if (!content.title.empty()) {
+    // Add the content label.
+    GtkWidget* label = gtk_label_new(content.title.c_str());
+    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+    gtk_box_pack_start(GTK_BOX(bubble_content), label, FALSE, FALSE, 0);
+  }
+
+  const std::set<std::string>& plugins = content.resource_identifiers;
+  if (!plugins.empty()) {
+    GtkWidget* list_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+    for (std::set<std::string>::const_iterator it = plugins.begin();
+        it != plugins.end(); ++it) {
+      std::string name = UTF16ToUTF8(
+          webkit::npapi::PluginList::Singleton()->GetPluginGroupName(*it));
+      if (name.empty())
+        name = *it;
+
+      GtkWidget* label = gtk_label_new(BuildElidedText(name).c_str());
+      GtkWidget* label_box = gtk_hbox_new(FALSE, 0);
+      gtk_box_pack_start(GTK_BOX(label_box), label, FALSE, FALSE, 0);
+
+      gtk_box_pack_start(GTK_BOX(list_content),
+                         label_box,
+                         FALSE, FALSE, 0);
+    }
+    gtk_box_pack_start(GTK_BOX(bubble_content), list_content, FALSE, FALSE,
+                       gtk_util::kControlSpacing);
+  }
+
+  if (content_setting_bubble_model_->content_type() ==
+      CONTENT_SETTINGS_TYPE_POPUPS) {
+    const std::vector<ContentSettingBubbleModel::PopupItem>& popup_items =
+        content.popup_items;
+    GtkWidget* table = gtk_table_new(popup_items.size(), 2, FALSE);
+    int row = 0;
+    for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
+         i(popup_items.begin()); i != popup_items.end(); ++i, ++row) {
+      GtkWidget* image = gtk_image_new();
+      if (!i->bitmap.empty()) {
+        GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&i->bitmap);
+        gtk_image_set_from_pixbuf(GTK_IMAGE(image), icon_pixbuf);
+        g_object_unref(icon_pixbuf);
+
+        // We stuff the image in an event box so we can trap mouse clicks on the
+        // image (and launch the popup).
+        GtkWidget* event_box = gtk_event_box_new();
+        gtk_container_add(GTK_CONTAINER(event_box), image);
+
+        popup_icons_[event_box] = i -popup_items.begin();
+        g_signal_connect(event_box, "button_press_event",
+                         G_CALLBACK(OnPopupIconButtonPressThunk), this);
+        gtk_table_attach(GTK_TABLE(table), event_box, 0, 1, row, row + 1,
+                         GTK_FILL, GTK_FILL, gtk_util::kControlSpacing / 2,
+                         gtk_util::kControlSpacing / 2);
+      }
+
+      GtkWidget* button = gtk_chrome_link_button_new(
+          BuildElidedText(i->title).c_str());
+      popup_links_[button] = i -popup_items.begin();
+      g_signal_connect(button, "clicked", G_CALLBACK(OnPopupLinkClickedThunk),
+                       this);
+      gtk_table_attach(GTK_TABLE(table), button, 1, 2, row, row + 1,
+                       GTK_FILL, GTK_FILL, gtk_util::kControlSpacing / 2,
+                       gtk_util::kControlSpacing / 2);
+    }
+
+    gtk_box_pack_start(GTK_BOX(bubble_content), table, FALSE, FALSE, 0);
+  }
+
+  if (content_setting_bubble_model_->content_type() !=
+      CONTENT_SETTINGS_TYPE_COOKIES) {
+    const ContentSettingBubbleModel::RadioGroup& radio_group =
+        content.radio_group;
+    for (ContentSettingBubbleModel::RadioItems::const_iterator i =
+         radio_group.radio_items.begin();
+         i != radio_group.radio_items.end(); ++i) {
+      std::string elided = BuildElidedText(*i);
+      GtkWidget* radio =
+          radio_group_gtk_.empty() ?
+              gtk_radio_button_new_with_label(NULL, elided.c_str()) :
+              gtk_radio_button_new_with_label_from_widget(
+                  GTK_RADIO_BUTTON(radio_group_gtk_[0]),
+                  elided.c_str());
+      gtk_box_pack_start(GTK_BOX(bubble_content), radio, FALSE, FALSE, 0);
+      if (i - radio_group.radio_items.begin() == radio_group.default_item) {
+        // We must set the default value before we attach the signal handlers
+        // or pain occurs.
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
+      }
+      radio_group_gtk_.push_back(radio);
+    }
+    for (std::vector<GtkWidget*>::const_iterator i = radio_group_gtk_.begin();
+         i != radio_group_gtk_.end(); ++i) {
+      // We can attach signal handlers now that all defaults are set.
+      g_signal_connect(*i, "toggled", G_CALLBACK(OnRadioToggledThunk), this);
+    }
+  }
+
+  for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i =
+       content.domain_lists.begin();
+       i != content.domain_lists.end(); ++i) {
+    // Put each list into its own vbox to allow spacing between lists.
+    GtkWidget* list_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+    GtkWidget* label = gtk_label_new(BuildElidedText(i->title).c_str());
+    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+    GtkWidget* label_box = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(label_box), label, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(list_content), label_box, FALSE, FALSE, 0);
+    for (std::set<std::string>::const_iterator j = i->hosts.begin();
+         j != i->hosts.end(); ++j) {
+      gtk_box_pack_start(GTK_BOX(list_content),
+                         gtk_util::IndentWidget(gtk_util::CreateBoldLabel(*j)),
+                         FALSE, FALSE, 0);
+    }
+    gtk_box_pack_start(GTK_BOX(bubble_content), list_content, FALSE, FALSE,
+                       gtk_util::kControlSpacing);
+  }
+
+  if (!content.custom_link.empty()) {
+    GtkWidget* custom_link_box = gtk_hbox_new(FALSE, 0);
+    GtkWidget* custom_link = NULL;
+    if (content.custom_link_enabled) {
+      custom_link = gtk_chrome_link_button_new(content.custom_link.c_str());
+      g_signal_connect(custom_link, "clicked",
+                       G_CALLBACK(OnCustomLinkClickedThunk), this);
+    } else {
+      custom_link = gtk_label_new(content.custom_link.c_str());
+      gtk_misc_set_alignment(GTK_MISC(custom_link), 0, 0.5);
+    }
+    DCHECK(custom_link);
+    gtk_box_pack_start(GTK_BOX(custom_link_box), custom_link, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(bubble_content), custom_link_box,
+                       FALSE, FALSE, 0);
+  }
+
+  gtk_box_pack_start(GTK_BOX(bubble_content), gtk_hseparator_new(),
+                     FALSE, FALSE, 0);
+
+  GtkWidget* bottom_box = gtk_hbox_new(FALSE, 0);
+
+  GtkWidget* manage_link =
+      gtk_chrome_link_button_new(content.manage_link.c_str());
+  g_signal_connect(manage_link, "clicked", G_CALLBACK(OnManageLinkClickedThunk),
+                   this);
+  gtk_box_pack_start(GTK_BOX(bottom_box), manage_link, FALSE, FALSE, 0);
+
+  GtkWidget* button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_DONE).c_str());
+  g_signal_connect(button, "clicked", G_CALLBACK(OnCloseButtonClickedThunk),
+                   this);
+  gtk_box_pack_end(GTK_BOX(bottom_box), button, FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(bubble_content), bottom_box, FALSE, FALSE, 0);
+  gtk_widget_grab_focus(bottom_box);
+  gtk_widget_grab_focus(button);
+
+  InfoBubbleGtk::ArrowLocationGtk arrow_location =
+      !base::i18n::IsRTL() ?
+      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
+      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
+  info_bubble_ = InfoBubbleGtk::Show(
+      anchor_,
+      NULL,
+      bubble_content,
+      arrow_location,
+      true,  // match_system_theme
+      true,  // grab_input
+      theme_provider,
+      this);
+}
+
+void ContentSettingBubbleGtk::OnPopupIconButtonPress(
+    GtkWidget* icon_event_box,
+    GdkEventButton* event) {
+  PopupMap::iterator i(popup_icons_.find(icon_event_box));
+  DCHECK(i != popup_icons_.end());
+  content_setting_bubble_model_->OnPopupClicked(i->second);
+  // The views interface implicitly closes because of the launching of a new
+  // window; we need to do that explicitly.
+  Close();
+}
+
+void ContentSettingBubbleGtk::OnPopupLinkClicked(GtkWidget* button) {
+  PopupMap::iterator i(popup_links_.find(button));
+  DCHECK(i != popup_links_.end());
+  content_setting_bubble_model_->OnPopupClicked(i->second);
+  // The views interface implicitly closes because of the launching of a new
+  // window; we need to do that explicitly.
+  Close();
+}
+
+void ContentSettingBubbleGtk::OnRadioToggled(GtkWidget* widget) {
+  for (ContentSettingBubbleGtk::RadioGroupGtk::const_iterator i =
+       radio_group_gtk_.begin();
+       i != radio_group_gtk_.end(); ++i) {
+    if (widget == *i) {
+      content_setting_bubble_model_->OnRadioClicked(
+          i - radio_group_gtk_.begin());
+      return;
+    }
+  }
+  NOTREACHED() << "unknown radio toggled";
+}
+
+void ContentSettingBubbleGtk::OnCloseButtonClicked(GtkWidget *button) {
+  Close();
+}
+
+void ContentSettingBubbleGtk::OnCustomLinkClicked(GtkWidget* button) {
+  content_setting_bubble_model_->OnCustomLinkClicked();
+  Close();
+}
+
+void ContentSettingBubbleGtk::OnManageLinkClicked(GtkWidget* button) {
+  content_setting_bubble_model_->OnManageLinkClicked();
+  Close();
+}
diff --git a/chrome/browser/ui/gtk/content_setting_bubble_gtk.h b/chrome/browser/ui/gtk/content_setting_bubble_gtk.h
new file mode 100644
index 0000000..9427fc0
--- /dev/null
+++ b/chrome/browser/ui/gtk/content_setting_bubble_gtk.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_CONTENT_SETTING_BUBBLE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_CONTENT_SETTING_BUBBLE_GTK_H_
+#pragma once
+
+#include <map>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/common/content_settings_types.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class ContentSettingBubbleModel;
+class Profile;
+class TabContents;
+
+// ContentSettingBubbleGtk is used when the user turns on different kinds of
+// content blocking (e.g. "block images"). An icon appears in the location bar,
+// and when clicked, an instance of this class is created specialized for the
+// type of content being blocked.
+class ContentSettingBubbleGtk : public InfoBubbleGtkDelegate,
+                                public NotificationObserver {
+ public:
+   ContentSettingBubbleGtk(
+       GtkWidget* anchor,
+       InfoBubbleGtkDelegate* delegate,
+       ContentSettingBubbleModel* content_setting_bubble_model,
+       Profile* profile, TabContents* tab_contents);
+  virtual ~ContentSettingBubbleGtk();
+
+  // Dismisses the infobubble.
+  void Close();
+
+ private:
+  typedef std::map<GtkWidget*, int> PopupMap;
+
+  // InfoBubbleGtkDelegate:
+  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                 bool closed_by_escape);
+
+  // NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Builds the info bubble and all the widgets that it displays.
+  void BuildBubble();
+
+  // Widget callback methods.
+  CHROMEGTK_CALLBACK_1(ContentSettingBubbleGtk, void, OnPopupIconButtonPress,
+                       GdkEventButton*);
+  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnPopupLinkClicked);
+  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnRadioToggled);
+  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnCustomLinkClicked);
+  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnManageLinkClicked);
+  CHROMEGTK_CALLBACK_0(ContentSettingBubbleGtk, void, OnCloseButtonClicked);
+
+  // We position the bubble near this widget.
+  GtkWidget* anchor_;
+
+  // The active profile.
+  Profile* profile_;
+
+  // The active tab contents.
+  TabContents* tab_contents_;
+
+  // A registrar for listening for TAB_CONTENTS_DESTROYED notifications.
+  NotificationRegistrar registrar_;
+
+  // Pass on delegate messages to this.
+  InfoBubbleGtkDelegate* delegate_;
+
+  // Provides data for this bubble.
+  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model_;
+
+  // The info bubble.
+  InfoBubbleGtk* info_bubble_;
+
+  // Stored controls so we can figure out what was clicked.
+  PopupMap popup_links_;
+  PopupMap popup_icons_;
+
+  typedef std::vector<GtkWidget*> RadioGroupGtk;
+  RadioGroupGtk radio_group_gtk_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_CONTENT_SETTING_BUBBLE_GTK_H_
diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
new file mode 100644
index 0000000..c650d86
--- /dev/null
+++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
@@ -0,0 +1,328 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h"
+
+#include <string>
+
+#include "base/environment.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Size (in pixels) of the icon preview.
+const int kIconPreviewSizePixels = 32;
+
+// Height (in lines) of the shortcut description label.
+const int kDescriptionLabelHeightLines = 3;
+
+}  // namespace
+
+// static
+void CreateWebApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
+                                                  TabContents* tab_contents) {
+  new CreateWebApplicationShortcutsDialogGtk(parent, tab_contents);
+}
+
+void CreateChromeApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
+                                                     const Extension* app) {
+  new CreateChromeApplicationShortcutsDialogGtk(parent, app);
+}
+
+
+CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk(
+    GtkWindow* parent)
+  : parent_(parent),
+    error_dialog_(NULL) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // Will be balanced by Release later.
+  AddRef();
+}
+
+void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf(
+    const SkBitmap& bitmap) {
+  // Prepare the icon. Try to scale it if it's too small, otherwise it would
+  // look weird.
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&shortcut_info_.favicon);
+  int pixbuf_width = gdk_pixbuf_get_width(pixbuf);
+  int pixbuf_height = gdk_pixbuf_get_height(pixbuf);
+  if (pixbuf_width == pixbuf_height && pixbuf_width < kIconPreviewSizePixels) {
+    // Only scale the pixbuf if it's a square (for simplicity).
+    // Generally it should be square, if it's a favicon or app icon.
+    // Use the highest quality interpolation. The scaling is
+    // going to have low quality anyway, because the initial image
+    // is likely small.
+    favicon_pixbuf_ = gdk_pixbuf_scale_simple(pixbuf,
+                                              kIconPreviewSizePixels,
+                                              kIconPreviewSizePixels,
+                                              GDK_INTERP_HYPER);
+    g_object_unref(pixbuf);
+  } else {
+    favicon_pixbuf_ = pixbuf;
+  }
+}
+
+void CreateApplicationShortcutsDialogGtk::CreateDialogBox(GtkWindow* parent) {
+  // Build the dialog.
+  create_dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_TITLE).c_str(),
+      parent,
+      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_REJECT,
+      NULL);
+  gtk_widget_realize(create_dialog_);
+  gtk_window_set_resizable(GTK_WINDOW(create_dialog_), false);
+  gtk_util::AddButtonToDialog(create_dialog_,
+      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_COMMIT).c_str(),
+      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
+
+  GtkWidget* content_area = GTK_DIALOG(create_dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(content_area), vbox);
+
+  // Create a box containing basic information about the new shortcut: an image
+  // on the left, and a description on the right.
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(hbox),
+                                 gtk_util::kControlSpacing);
+
+  // Put the icon preview in place.
+  GtkWidget* favicon_image = gtk_image_new_from_pixbuf(favicon_pixbuf_);
+  gtk_box_pack_start(GTK_BOX(hbox), favicon_image, FALSE, FALSE, 0);
+
+  // Create the label with application shortcut description.
+  GtkWidget* description_label = gtk_label_new(NULL);
+  gtk_box_pack_start(GTK_BOX(hbox), description_label, FALSE, FALSE, 0);
+  gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
+  gtk_widget_realize(description_label);
+
+  // Set the size request on the label so it knows where to line wrap. The width
+  // is the desired size of the dialog less the space reserved for padding and
+  // the image.
+  int label_width;
+  gtk_util::GetWidgetSizeFromResources(
+      description_label,
+      IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS, -1, &label_width, NULL);
+  label_width -= gtk_util::kControlSpacing * 3 +
+      gdk_pixbuf_get_width(favicon_pixbuf_);
+  gtk_util::SetLabelWidth(description_label, label_width);
+
+  std::string description(UTF16ToUTF8(shortcut_info_.description));
+  std::string title(UTF16ToUTF8(shortcut_info_.title));
+  gtk_label_set_text(GTK_LABEL(description_label),
+                     (description.empty() ? title : description).c_str());
+
+  // Label on top of the checkboxes.
+  GtkWidget* checkboxes_label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_LABEL).c_str());
+  gtk_misc_set_alignment(GTK_MISC(checkboxes_label), 0, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), checkboxes_label, FALSE, FALSE, 0);
+
+  // Desktop checkbox.
+  desktop_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), desktop_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(desktop_checkbox_), true);
+  g_signal_connect(desktop_checkbox_, "toggled",
+                   G_CALLBACK(OnToggleCheckboxThunk), this);
+
+  // Menu checkbox.
+  menu_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_MENU_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), menu_checkbox_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(menu_checkbox_), false);
+  g_signal_connect(menu_checkbox_, "toggled",
+                   G_CALLBACK(OnToggleCheckboxThunk), this);
+
+  g_signal_connect(create_dialog_, "response",
+                   G_CALLBACK(OnCreateDialogResponseThunk), this);
+  gtk_widget_show_all(create_dialog_);
+}
+
+CreateApplicationShortcutsDialogGtk::~CreateApplicationShortcutsDialogGtk() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  gtk_widget_destroy(create_dialog_);
+
+  if (error_dialog_)
+    gtk_widget_destroy(error_dialog_);
+
+  g_object_unref(favicon_pixbuf_);
+}
+
+void CreateApplicationShortcutsDialogGtk::OnCreateDialogResponse(
+    GtkWidget* widget, int response) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (response == GTK_RESPONSE_ACCEPT) {
+    shortcut_info_.create_on_desktop =
+        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_));
+    shortcut_info_.create_in_applications_menu =
+        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_));
+    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+         NewRunnableMethod(this,
+             &CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut,
+             shortcut_info_));
+
+    OnCreatedShortcut();
+  } else {
+    Release();
+  }
+}
+
+void CreateApplicationShortcutsDialogGtk::OnErrorDialogResponse(
+    GtkWidget* widget, int response) {
+  Release();
+}
+
+void CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut(
+    const ShellIntegration::ShortcutInfo& shortcut_info) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+
+  std::string shortcut_template;
+  if (ShellIntegration::GetDesktopShortcutTemplate(env.get(),
+                                                   &shortcut_template)) {
+    ShellIntegration::CreateDesktopShortcut(shortcut_info,
+                                            shortcut_template);
+    Release();
+  } else {
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableMethod(this,
+            &CreateApplicationShortcutsDialogGtk::ShowErrorDialog));
+  }
+}
+
+void CreateApplicationShortcutsDialogGtk::ShowErrorDialog() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  // Hide the create dialog so that the user can no longer interact with it.
+  gtk_widget_hide(create_dialog_);
+
+  error_dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_ERROR_TITLE).c_str(),
+      NULL,
+      (GtkDialogFlags) (GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_OK,
+      GTK_RESPONSE_ACCEPT,
+      NULL);
+  gtk_widget_realize(error_dialog_);
+  gtk_util::SetWindowSizeFromResources(
+      GTK_WINDOW(error_dialog_),
+      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_WIDTH_CHARS,
+      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_HEIGHT_LINES,
+      false);  // resizable
+  GtkWidget* content_area = GTK_DIALOG(error_dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(content_area), vbox);
+
+  // Label on top of the checkboxes.
+  GtkWidget* description = gtk_label_new(
+      l10n_util::GetStringFUTF8(
+          IDS_CREATE_SHORTCUTS_ERROR_LABEL,
+          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
+  gtk_label_set_line_wrap(GTK_LABEL(description), TRUE);
+  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);
+
+  g_signal_connect(error_dialog_, "response",
+                   G_CALLBACK(OnErrorDialogResponseThunk), this);
+  gtk_widget_show_all(error_dialog_);
+}
+
+void CreateApplicationShortcutsDialogGtk::OnToggleCheckbox(GtkWidget* sender) {
+  gboolean can_accept = FALSE;
+
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_)) ||
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_))) {
+    can_accept = TRUE;
+  }
+
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(create_dialog_),
+                                    GTK_RESPONSE_ACCEPT,
+                                    can_accept);
+}
+
+CreateWebApplicationShortcutsDialogGtk::CreateWebApplicationShortcutsDialogGtk(
+    GtkWindow* parent,
+    TabContents* tab_contents)
+  : CreateApplicationShortcutsDialogGtk(parent),
+    tab_contents_(tab_contents) {
+
+  // Get shortcut information now, it's needed for our UI.
+  web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_);
+  CreateIconPixBuf(shortcut_info_.favicon);
+
+  CreateDialogBox(parent);
+}
+
+void CreateWebApplicationShortcutsDialogGtk::OnCreatedShortcut() {
+  if (tab_contents_->delegate())
+    tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_);
+}
+
+CreateChromeApplicationShortcutsDialogGtk::
+    CreateChromeApplicationShortcutsDialogGtk(
+        GtkWindow* parent,
+        const Extension* app)
+      : CreateApplicationShortcutsDialogGtk(parent),
+        app_(app),
+        ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this))  {
+
+  // Get shortcut information now, it's needed for our UI.
+  shortcut_info_.extension_id = UTF8ToUTF16(app_->id());
+  shortcut_info_.url = GURL(app_->launch_web_url());
+  shortcut_info_.title = UTF8ToUTF16(app_->name());
+  shortcut_info_.description = UTF8ToUTF16(app_->description());
+
+  // Get the icon.
+  const gfx::Size max_size(kIconPreviewSizePixels, kIconPreviewSizePixels);
+  ExtensionResource icon_resource = app_->GetIconResource(
+      kIconPreviewSizePixels, ExtensionIconSet::MATCH_BIGGER);
+
+  // If no icon exists that is the desired size or larger, get the
+  // largest icon available:
+  if (icon_resource.empty())
+    icon_resource = app_->GetIconResource(
+        kIconPreviewSizePixels, ExtensionIconSet::MATCH_SMALLER);
+
+  tracker_.LoadImage(app_,
+                     icon_resource,
+                     max_size,
+                     ImageLoadingTracker::DONT_CACHE);
+}
+
+// Called by tracker_ when the app's icon is loaded.
+void CreateChromeApplicationShortcutsDialogGtk::OnImageLoaded(
+    SkBitmap* image, ExtensionResource resource, int index) {
+  if (image->isNull()) {
+    NOTREACHED() << "Corrupt image in profile?";
+    return;
+  }
+  shortcut_info_.favicon = *image;
+
+  CreateIconPixBuf(*image);
+  CreateDialogBox(parent_);
+}
diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h
new file mode 100644
index 0000000..b8e2957
--- /dev/null
+++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h
@@ -0,0 +1,119 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/shell_integration.h"
+#include "googleurl/src/gurl.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkWindow GtkWindow;
+
+class Extension;
+class TabContents;
+
+class CreateApplicationShortcutsDialogGtk
+    : public base::RefCountedThreadSafe<CreateApplicationShortcutsDialogGtk,
+                                        BrowserThread::DeleteOnUIThread> {
+ protected:
+  explicit CreateApplicationShortcutsDialogGtk(GtkWindow* parent);
+  virtual ~CreateApplicationShortcutsDialogGtk();
+
+  CHROMEGTK_CALLBACK_1(CreateApplicationShortcutsDialogGtk, void,
+                       OnCreateDialogResponse, int);
+
+  CHROMEGTK_CALLBACK_1(CreateApplicationShortcutsDialogGtk, void,
+                       OnErrorDialogResponse, int);
+
+  CHROMEGTK_CALLBACK_0(CreateApplicationShortcutsDialogGtk, void,
+                       OnToggleCheckbox);
+
+  virtual void CreateDialogBox(GtkWindow* parent);
+  virtual void CreateIconPixBuf(const SkBitmap& bitmap);
+
+  // This method is called after a shortcut is created.
+  // Subclasses can override it to take some action at that time.
+  virtual void OnCreatedShortcut(void) {}
+
+  void CreateDesktopShortcut(
+      const ShellIntegration::ShortcutInfo& shortcut_info);
+  void ShowErrorDialog();
+
+  GtkWindow* parent_;
+
+  // UI elements.
+  GtkWidget* desktop_checkbox_;
+  GtkWidget* menu_checkbox_;
+
+  // ShortcutInfo for the new shortcut.
+  ShellIntegration::ShortcutInfo shortcut_info_;
+
+  // Image associated with the site.
+  GdkPixbuf* favicon_pixbuf_;
+
+  // Dialog box that allows the user to create an application shortcut.
+  GtkWidget* create_dialog_;
+
+  // Dialog box that shows the error message.
+  GtkWidget* error_dialog_;
+
+ private:
+  friend class BrowserThread;
+  friend class DeleteTask<CreateApplicationShortcutsDialogGtk>;
+  DISALLOW_COPY_AND_ASSIGN(CreateApplicationShortcutsDialogGtk);
+};
+
+class CreateWebApplicationShortcutsDialogGtk
+    : public CreateApplicationShortcutsDialogGtk {
+ public:
+  // Displays the dialog box to create application shortcuts for |tab_contents|.
+  static void Show(GtkWindow* parent, TabContents* tab_contents);
+
+  explicit CreateWebApplicationShortcutsDialogGtk(GtkWindow* parent,
+                                                  TabContents* tab_contents);
+  virtual ~CreateWebApplicationShortcutsDialogGtk() {}
+
+  virtual void OnCreatedShortcut(void);
+
+ private:
+
+  // TabContents for which the shortcut will be created.
+  TabContents* tab_contents_;
+
+  DISALLOW_COPY_AND_ASSIGN(CreateWebApplicationShortcutsDialogGtk);
+};
+
+class CreateChromeApplicationShortcutsDialogGtk
+  : public CreateApplicationShortcutsDialogGtk,
+    public ImageLoadingTracker::Observer {
+ public:
+  // Displays the dialog box to create application shortcuts for |app|.
+  static void Show(GtkWindow* parent, const Extension* app);
+
+  explicit CreateChromeApplicationShortcutsDialogGtk(GtkWindow* parent,
+                                                     const Extension* app);
+  virtual ~CreateChromeApplicationShortcutsDialogGtk() {}
+
+  // Implement ImageLoadingTracker::Observer.  |tracker_| is used to
+  // load the app's icon.  This method recieves the icon, and adds
+  // it to the "Create Shortcut" dailog box.
+  virtual void OnImageLoaded(SkBitmap* image,
+                             ExtensionResource resource,
+                             int index);
+
+ private:
+  const Extension* app_;
+  ImageLoadingTracker tracker_;
+  DISALLOW_COPY_AND_ASSIGN(CreateChromeApplicationShortcutsDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/crypto_module_password_dialog.cc b/chrome/browser/ui/gtk/crypto_module_password_dialog.cc
new file mode 100644
index 0000000..d36146b
--- /dev/null
+++ b/chrome/browser/ui/gtk/crypto_module_password_dialog.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/crypto_module_password_dialog.h"
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/crypto/crypto_module_blocking_password_delegate.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "googleurl/src/gurl.h"
+#include "grit/generated_resources.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+class CryptoModuleBlockingDialogDelegate
+    : public base::CryptoModuleBlockingPasswordDelegate {
+ public:
+  CryptoModuleBlockingDialogDelegate(browser::CryptoModulePasswordReason reason,
+                                     const std::string& server)
+      : event_(false, false),
+        reason_(reason),
+        server_(server),
+        password_(),
+        cancelled_(false) {
+  }
+
+  ~CryptoModuleBlockingDialogDelegate() {
+    password_.replace(0, password_.size(), password_.size(), 0);
+  }
+
+  // base::CryptoModuleBlockingDialogDelegate implementation.
+  virtual std::string RequestPassword(const std::string& slot_name, bool retry,
+                                      bool* cancelled) {
+    DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK(!event_.IsSignaled());
+    event_.Reset();
+    if (BrowserThread::PostTask(
+            BrowserThread::UI, FROM_HERE,
+            NewRunnableMethod(this,
+                              &CryptoModuleBlockingDialogDelegate::ShowDialog,
+                              slot_name,
+                              retry))) {
+      event_.Wait();
+    }
+    *cancelled = cancelled_;
+    return password_;
+  }
+
+ private:
+  void ShowDialog(const std::string& slot_name, bool retry) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    ShowCryptoModulePasswordDialog(
+        slot_name, retry, reason_, server_,
+        NewCallback(this, &CryptoModuleBlockingDialogDelegate::GotPassword));
+  }
+  void GotPassword(const char* password) {
+    if (password)
+      password_ = password;
+    else
+      cancelled_ = true;
+    event_.Signal();
+  }
+  base::WaitableEvent event_;
+  browser::CryptoModulePasswordReason reason_;
+  std::string server_;
+  std::string password_;
+  bool cancelled_;
+
+  DISALLOW_COPY_AND_ASSIGN(CryptoModuleBlockingDialogDelegate);
+};
+
+// TODO(mattm): change into a constrained dialog.
+class CryptoModulePasswordDialog {
+ public:
+  CryptoModulePasswordDialog(const std::string& slot_name,
+                             bool retry,
+                             browser::CryptoModulePasswordReason reason,
+                             const std::string& server,
+                             browser::CryptoModulePasswordCallback* callback);
+
+  void Show();
+
+ private:
+  CHROMEGTK_CALLBACK_1(CryptoModulePasswordDialog, void, OnResponse, int);
+  CHROMEGTK_CALLBACK_0(CryptoModulePasswordDialog, void, OnWindowDestroy);
+
+  scoped_ptr<browser::CryptoModulePasswordCallback> callback_;
+
+  GtkWidget* dialog_;
+  GtkWidget* password_entry_;
+
+  DISALLOW_COPY_AND_ASSIGN(CryptoModulePasswordDialog);
+};
+
+CryptoModulePasswordDialog::CryptoModulePasswordDialog(
+    const std::string& slot_name,
+    bool retry,
+    browser::CryptoModulePasswordReason reason,
+    const std::string& server,
+    browser::CryptoModulePasswordCallback* callback)
+    : callback_(callback) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_CRYPTO_MODULE_AUTH_DIALOG_TITLE).c_str(),
+      NULL,
+      GTK_DIALOG_NO_SEPARATOR,
+      NULL);  // Populate the buttons later, for control over the OK button.
+  gtk_dialog_add_button(GTK_DIALOG(dialog_),
+                        GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+  GtkWidget* ok_button = gtk_util::AddButtonToDialog(
+      dialog_,
+      l10n_util::GetStringUTF8(
+          IDS_CRYPTO_MODULE_AUTH_DIALOG_OK_BUTTON_LABEL).c_str(),
+      GTK_STOCK_OK,
+      GTK_RESPONSE_ACCEPT);
+  GTK_WIDGET_SET_FLAGS(ok_button, GTK_CAN_DEFAULT);
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
+
+  // Select an appropriate text for the reason.
+  std::string text;
+  const string16& server16 = UTF8ToUTF16(server);
+  const string16& slot16 = UTF8ToUTF16(slot_name);
+  switch (reason) {
+    case browser::kCryptoModulePasswordKeygen:
+      text = l10n_util::GetStringFUTF8(
+          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_KEYGEN, slot16, server16);
+      break;
+    case browser::kCryptoModulePasswordCertEnrollment:
+      text = l10n_util::GetStringFUTF8(
+          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_ENROLLMENT, slot16, server16);
+      break;
+    case browser::kCryptoModulePasswordClientAuth:
+      text = l10n_util::GetStringFUTF8(
+          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CLIENT_AUTH, slot16, server16);
+      break;
+    case browser::kCryptoModulePasswordCertImport:
+      text = l10n_util::GetStringFUTF8(
+          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_IMPORT, slot16);
+      break;
+    case browser::kCryptoModulePasswordCertExport:
+      text = l10n_util::GetStringFUTF8(
+          IDS_CRYPTO_MODULE_AUTH_DIALOG_TEXT_CERT_EXPORT, slot16);
+      break;
+    default:
+      NOTREACHED();
+  }
+  GtkWidget* label = gtk_label_new(text.c_str());
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_util::LeftAlignMisc(label);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), label,
+                     FALSE, FALSE, 0);
+
+  password_entry_ = gtk_entry_new();
+  gtk_entry_set_activates_default(GTK_ENTRY(password_entry_), TRUE);
+  gtk_entry_set_visibility(GTK_ENTRY(password_entry_), FALSE);
+
+  GtkWidget* password_box = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  gtk_box_pack_start(GTK_BOX(password_box),
+                     gtk_label_new(l10n_util::GetStringUTF8(
+                         IDS_CRYPTO_MODULE_AUTH_DIALOG_PASSWORD_FIELD).c_str()),
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(password_box), password_entry_,
+                     TRUE, TRUE, 0);
+
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), password_box,
+                     FALSE, FALSE, 0);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnResponseThunk), this);
+  g_signal_connect(dialog_, "destroy",
+                   G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+void CryptoModulePasswordDialog::Show() {
+  gtk_util::ShowDialog(dialog_);
+}
+
+void CryptoModulePasswordDialog::OnResponse(GtkWidget* dialog,
+                                            int response_id) {
+  if (response_id == GTK_RESPONSE_ACCEPT)
+    callback_->Run(gtk_entry_get_text(GTK_ENTRY(password_entry_)));
+  else
+    callback_->Run(static_cast<const char*>(NULL));
+
+  // This will cause gtk to zero out the buffer.  (see
+  // gtk_entry_buffer_normal_delete_text:
+  // http://git.gnome.org/browse/gtk+/tree/gtk/gtkentrybuffer.c#n187)
+  gtk_editable_delete_text(GTK_EDITABLE(password_entry_), 0, -1);
+  gtk_widget_destroy(GTK_WIDGET(dialog_));
+}
+
+void CryptoModulePasswordDialog::OnWindowDestroy(GtkWidget* widget) {
+  delete this;
+}
+
+}  // namespace
+
+// Every post-task we do blocks, so there's no need to ref-count.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(CryptoModuleBlockingDialogDelegate);
+
+namespace browser {
+
+void ShowCryptoModulePasswordDialog(const std::string& slot_name,
+                                    bool retry,
+                                    CryptoModulePasswordReason reason,
+                                    const std::string& server,
+                                    CryptoModulePasswordCallback* callback) {
+  (new CryptoModulePasswordDialog(slot_name, retry, reason, server,
+                                  callback))->Show();
+}
+
+base::CryptoModuleBlockingPasswordDelegate*
+    NewCryptoModuleBlockingDialogDelegate(
+        CryptoModulePasswordReason reason,
+        const std::string& server) {
+  return new CryptoModuleBlockingDialogDelegate(reason, server);
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/gtk/custom_button.cc b/chrome/browser/ui/gtk/custom_button.cc
new file mode 100644
index 0000000..05da776
--- /dev/null
+++ b/chrome/browser/ui/gtk/custom_button.cc
@@ -0,0 +1,345 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/custom_button.h"
+
+#include "base/basictypes.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_service.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+CustomDrawButtonBase::CustomDrawButtonBase(GtkThemeProvider* theme_provider,
+                                           int normal_id,
+                                           int pressed_id,
+                                           int hover_id,
+                                           int disabled_id)
+    : background_image_(NULL),
+      paint_override_(-1),
+      normal_id_(normal_id),
+      pressed_id_(pressed_id),
+      hover_id_(hover_id),
+      disabled_id_(disabled_id),
+      theme_provider_(theme_provider),
+      flipped_(false) {
+  for (int i = 0; i < (GTK_STATE_INSENSITIVE + 1); ++i)
+    surfaces_[i].reset(new CairoCachedSurface);
+  background_image_.reset(new CairoCachedSurface);
+
+  if (theme_provider) {
+    // Load images by pretending that we got a BROWSER_THEME_CHANGED
+    // notification.
+    theme_provider->InitThemesFor(this);
+
+    registrar_.Add(this,
+                   NotificationType::BROWSER_THEME_CHANGED,
+                   NotificationService::AllSources());
+  } else {
+    // Load the button images from the resource bundle.
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    surfaces_[GTK_STATE_NORMAL]->UsePixbuf(
+        normal_id_ ? rb.GetRTLEnabledPixbufNamed(normal_id_) : NULL);
+    surfaces_[GTK_STATE_ACTIVE]->UsePixbuf(
+        pressed_id_ ? rb.GetRTLEnabledPixbufNamed(pressed_id_) : NULL);
+    surfaces_[GTK_STATE_PRELIGHT]->UsePixbuf(
+        hover_id_ ? rb.GetRTLEnabledPixbufNamed(hover_id_) : NULL);
+    surfaces_[GTK_STATE_SELECTED]->UsePixbuf(NULL);
+    surfaces_[GTK_STATE_INSENSITIVE]->UsePixbuf(
+        disabled_id_ ? rb.GetRTLEnabledPixbufNamed(disabled_id_) : NULL);
+  }
+}
+
+CustomDrawButtonBase::~CustomDrawButtonBase() {
+}
+
+int CustomDrawButtonBase::Width() const {
+  return surfaces_[0]->Width();
+}
+
+int CustomDrawButtonBase::Height() const {
+  return surfaces_[0]->Height();
+}
+
+gboolean CustomDrawButtonBase::OnExpose(GtkWidget* widget,
+                                        GdkEventExpose* e,
+                                        gdouble hover_state) {
+  int paint_state = paint_override_ >= 0 ?
+                    paint_override_ : GTK_WIDGET_STATE(widget);
+
+  // If the paint state is PRELIGHT then set it to NORMAL (we will paint the
+  // hover state according to |hover_state_|).
+  if (paint_state == GTK_STATE_PRELIGHT)
+    paint_state = GTK_STATE_NORMAL;
+  bool animating_hover = hover_state > 0.0 &&
+      paint_state == GTK_STATE_NORMAL;
+  CairoCachedSurface* pixbuf = PixbufForState(paint_state);
+  CairoCachedSurface* hover_pixbuf = PixbufForState(GTK_STATE_PRELIGHT);
+
+  if (!pixbuf || !pixbuf->valid())
+    return FALSE;
+  if (animating_hover && (!hover_pixbuf || !hover_pixbuf->valid()))
+    return FALSE;
+
+  cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+  cairo_translate(cairo_context, widget->allocation.x, widget->allocation.y);
+
+  if (flipped_) {
+    // Horizontally flip the image for non-LTR/RTL reasons.
+    cairo_translate(cairo_context, widget->allocation.width, 0.0f);
+    cairo_scale(cairo_context, -1.0f, 1.0f);
+  }
+
+  // The widget might be larger than the pixbuf. Paint the pixbuf flush with the
+  // start of the widget (left for LTR, right for RTL) and its bottom.
+  gfx::Rect bounds = gfx::Rect(0, 0, pixbuf->Width(), 0);
+  int x = gtk_util::MirroredLeftPointForRect(widget, bounds);
+  int y = widget->allocation.height - pixbuf->Height();
+
+  if (background_image_->valid()) {
+    background_image_->SetSource(cairo_context, x, y);
+    cairo_paint(cairo_context);
+  }
+
+  pixbuf->SetSource(cairo_context, x, y);
+  cairo_paint(cairo_context);
+
+  if (animating_hover) {
+    hover_pixbuf->SetSource(cairo_context, x, y);
+    cairo_paint_with_alpha(cairo_context, hover_state);
+  }
+
+  cairo_destroy(cairo_context);
+
+  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
+  if (child)
+    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
+
+  return TRUE;
+}
+
+void CustomDrawButtonBase::SetBackground(SkColor color,
+                                         SkBitmap* image, SkBitmap* mask) {
+  if (!image || !mask) {
+    if (background_image_->valid()) {
+      background_image_->UsePixbuf(NULL);
+    }
+  } else {
+    SkBitmap img =
+        SkBitmapOperations::CreateButtonBackground(color, *image, *mask);
+
+    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&img);
+    background_image_->UsePixbuf(pixbuf);
+    g_object_unref(pixbuf);
+  }
+}
+
+void CustomDrawButtonBase::Observe(NotificationType type,
+    const NotificationSource& source, const NotificationDetails& details) {
+  DCHECK(theme_provider_);
+  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
+
+  surfaces_[GTK_STATE_NORMAL]->UsePixbuf(normal_id_ ?
+      theme_provider_->GetRTLEnabledPixbufNamed(normal_id_) : NULL);
+  surfaces_[GTK_STATE_ACTIVE]->UsePixbuf(pressed_id_ ?
+      theme_provider_->GetRTLEnabledPixbufNamed(pressed_id_) : NULL);
+  surfaces_[GTK_STATE_PRELIGHT]->UsePixbuf(hover_id_ ?
+      theme_provider_->GetRTLEnabledPixbufNamed(hover_id_) : NULL);
+  surfaces_[GTK_STATE_SELECTED]->UsePixbuf(NULL);
+  surfaces_[GTK_STATE_INSENSITIVE]->UsePixbuf(disabled_id_ ?
+      theme_provider_->GetRTLEnabledPixbufNamed(disabled_id_) : NULL);
+}
+
+CairoCachedSurface* CustomDrawButtonBase::PixbufForState(int state) {
+  CairoCachedSurface* pixbuf = surfaces_[state].get();
+
+  // Fall back to the default image if we don't have one for this state.
+  if (!pixbuf || !pixbuf->valid())
+    pixbuf = surfaces_[GTK_STATE_NORMAL].get();
+
+  return pixbuf;
+}
+
+// CustomDrawHoverController ---------------------------------------------------
+
+CustomDrawHoverController::CustomDrawHoverController(GtkWidget* widget)
+    : slide_animation_(this),
+      widget_(NULL) {
+  Init(widget);
+}
+
+CustomDrawHoverController::CustomDrawHoverController()
+    : slide_animation_(this),
+      widget_(NULL) {
+}
+
+CustomDrawHoverController::~CustomDrawHoverController() {
+}
+
+void CustomDrawHoverController::Init(GtkWidget* widget) {
+  DCHECK(widget_ == NULL);
+  widget_ = widget;
+  g_signal_connect(widget_, "enter-notify-event",
+                   G_CALLBACK(OnEnterThunk), this);
+  g_signal_connect(widget_, "leave-notify-event",
+                   G_CALLBACK(OnLeaveThunk), this);
+}
+
+void CustomDrawHoverController::AnimationProgressed(
+    const ui::Animation* animation) {
+  gtk_widget_queue_draw(widget_);
+}
+
+gboolean CustomDrawHoverController::OnEnter(
+    GtkWidget* widget,
+    GdkEventCrossing* event) {
+  slide_animation_.Show();
+  return FALSE;
+}
+
+gboolean CustomDrawHoverController::OnLeave(
+    GtkWidget* widget,
+    GdkEventCrossing* event) {
+  // When the user is holding a mouse button, we don't want to animate.
+  if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))
+    slide_animation_.Reset();
+  else
+    slide_animation_.Hide();
+  return FALSE;
+}
+
+// CustomDrawButton ------------------------------------------------------------
+
+CustomDrawButton::CustomDrawButton(int normal_id,
+                                   int pressed_id,
+                                   int hover_id,
+                                   int disabled_id)
+    : button_base_(NULL, normal_id, pressed_id, hover_id, disabled_id),
+      theme_provider_(NULL) {
+  Init();
+
+  // Initialize the theme stuff with no theme_provider.
+  SetBrowserTheme();
+}
+
+CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider,
+                                   int normal_id,
+                                   int pressed_id,
+                                   int hover_id,
+                                   int disabled_id,
+                                   const char* stock_id,
+                                   GtkIconSize stock_size)
+    : button_base_(theme_provider, normal_id, pressed_id, hover_id,
+                   disabled_id),
+      theme_provider_(theme_provider) {
+  native_widget_.Own(gtk_image_new_from_stock(stock_id, stock_size));
+
+  Init();
+
+  theme_provider_->InitThemesFor(this);
+  registrar_.Add(this,
+                 NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider,
+                                   int normal_id,
+                                   int pressed_id,
+                                   int hover_id,
+                                   int disabled_id,
+                                   GtkWidget* native_widget)
+    : button_base_(theme_provider, normal_id, pressed_id, hover_id,
+                   disabled_id),
+      native_widget_(native_widget),
+      theme_provider_(theme_provider) {
+  Init();
+
+  theme_provider_->InitThemesFor(this);
+  registrar_.Add(this,
+                 NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+CustomDrawButton::~CustomDrawButton() {
+  widget_.Destroy();
+  native_widget_.Destroy();
+}
+
+void CustomDrawButton::Init() {
+  widget_.Own(gtk_chrome_button_new());
+  GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS);
+  g_signal_connect(widget(), "expose-event",
+                   G_CALLBACK(OnCustomExposeThunk), this);
+  hover_controller_.Init(widget());
+}
+
+void CustomDrawButton::Observe(NotificationType type,
+    const NotificationSource& source, const NotificationDetails& details) {
+  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
+  SetBrowserTheme();
+}
+
+void CustomDrawButton::SetPaintOverride(GtkStateType state) {
+  button_base_.set_paint_override(state);
+  gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget()), state);
+  gtk_widget_queue_draw(widget());
+}
+
+void CustomDrawButton::UnsetPaintOverride() {
+  button_base_.set_paint_override(-1);
+  gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget()));
+  gtk_widget_queue_draw(widget());
+}
+
+void CustomDrawButton::SetBackground(SkColor color,
+                                     SkBitmap* image, SkBitmap* mask) {
+  button_base_.SetBackground(color, image, mask);
+}
+
+gboolean CustomDrawButton::OnCustomExpose(GtkWidget* sender,
+                                          GdkEventExpose* e) {
+  if (UseGtkTheme()) {
+    // Continue processing this expose event.
+    return FALSE;
+  } else {
+    double hover_state = hover_controller_.GetCurrentValue();
+    return button_base_.OnExpose(sender, e, hover_state);
+  }
+}
+
+// static
+CustomDrawButton* CustomDrawButton::CloseButton(
+    GtkThemeProvider* theme_provider) {
+  CustomDrawButton* button = new CustomDrawButton(theme_provider, IDR_CLOSE_BAR,
+      IDR_CLOSE_BAR_P, IDR_CLOSE_BAR_H, 0, GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+  return button;
+}
+
+void CustomDrawButton::SetBrowserTheme() {
+  if (UseGtkTheme()) {
+    if (native_widget_.get())
+      gtk_button_set_image(GTK_BUTTON(widget()), native_widget_.get());
+    gtk_widget_set_size_request(widget(), -1, -1);
+    gtk_widget_set_app_paintable(widget(), FALSE);
+  } else {
+    if (native_widget_.get())
+      gtk_button_set_image(GTK_BUTTON(widget()), NULL);
+    gtk_widget_set_size_request(widget(), button_base_.Width(),
+                                button_base_.Height());
+
+    gtk_widget_set_app_paintable(widget(), TRUE);
+  }
+
+  gtk_chrome_button_set_use_gtk_rendering(
+      GTK_CHROME_BUTTON(widget()), UseGtkTheme());
+}
+
+bool CustomDrawButton::UseGtkTheme() {
+  return theme_provider_ && theme_provider_->UseGtkTheme();
+}
diff --git a/chrome/browser/ui/gtk/custom_button.h b/chrome/browser/ui/gtk/custom_button.h
new file mode 100644
index 0000000..75f20a8
--- /dev/null
+++ b/chrome/browser/ui/gtk/custom_button.h
@@ -0,0 +1,227 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_CUSTOM_BUTTON_H_
+#define CHROME_BROWSER_UI_GTK_CUSTOM_BUTTON_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/rect.h"
+
+class CairoCachedSurface;
+class GtkThemeProvider;
+class SkBitmap;
+
+// These classes implement two kinds of custom-drawn buttons.  They're
+// used on the toolbar and the bookmarks bar.
+
+// CustomDrawButtonBase provides the base for building a custom drawn button.
+// It handles managing the pixbufs containing all the static images used to draw
+// the button.  It also manages painting these pixbufs.
+class CustomDrawButtonBase : public NotificationObserver {
+ public:
+  // If the images come from ResourceBundle rather than the theme provider,
+  // pass in NULL for |theme_provider|.
+  CustomDrawButtonBase(GtkThemeProvider* theme_provider,
+                       int normal_id,
+                       int pressed_id,
+                       int hover_id,
+                       int disabled_id);
+
+  ~CustomDrawButtonBase();
+
+  // Flip the image horizontally. Not to be used for RTL/LTR reasons. (In RTL
+  // mode, this will unflip the image.)
+  void set_flipped(bool flipped) { flipped_ = flipped; }
+
+  // Returns the dimensions of the first surface.
+  int Width() const;
+  int Height() const;
+
+  gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e, gdouble hover_state);
+
+  void set_paint_override(int state) { paint_override_ = state; }
+  int paint_override() const { return paint_override_; }
+
+  // Set the background details.
+  void SetBackground(SkColor color, SkBitmap* image, SkBitmap* mask);
+
+  // Provide NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  // Get the CairoCachedSurface from |surfaces_| for |state|.
+  CairoCachedSurface* PixbufForState(int state);
+
+  // We store one surface for each possible state of the button;
+  // INSENSITIVE is the last available state;
+  scoped_ptr<CairoCachedSurface> surfaces_[GTK_STATE_INSENSITIVE + 1];
+
+  // The background image.
+  scoped_ptr<CairoCachedSurface> background_image_;
+
+  // If non-negative, the state to paint the button.
+  int paint_override_;
+
+  // We need to remember the image ids that the user passes in and the theme
+  // provider so we can reload images if the user changes theme.
+  int normal_id_;
+  int pressed_id_;
+  int hover_id_;
+  int disabled_id_;
+  GtkThemeProvider* theme_provider_;
+
+  // Whether the button is flipped horizontally. Not used for RTL (we get
+  // flipped versions from the theme provider). Used for the flipped window
+  // buttons.
+  bool flipped_;
+
+  // Used to listen for theme change notifications.
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(CustomDrawButtonBase);
+};
+
+// CustomDrawHoverController is a convenience class that eases the common task
+// of controlling the hover state of a button. The "hover state" refers to the
+// percent opacity of a button's PRELIGHT. The PRELIGHT is animated such that
+// when a user moves a mouse over a button the PRELIGHT fades in.
+class CustomDrawHoverController : public ui::AnimationDelegate {
+ public:
+  explicit CustomDrawHoverController(GtkWidget* widget);
+  CustomDrawHoverController();
+
+  virtual ~CustomDrawHoverController();
+
+  void Init(GtkWidget* widget);
+
+  double GetCurrentValue() {
+    return slide_animation_.GetCurrentValue();
+  }
+
+ private:
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
+  CHROMEGTK_CALLBACK_1(CustomDrawHoverController, gboolean, OnEnter,
+                       GdkEventCrossing*);
+  CHROMEGTK_CALLBACK_1(CustomDrawHoverController, gboolean, OnLeave,
+                       GdkEventCrossing*);
+
+  ui::SlideAnimation slide_animation_;
+  GtkWidget* widget_;
+};
+
+// CustomDrawButton is a plain button where all its various states are drawn
+// with static images. In GTK rendering mode, it will show the standard button
+// with GTK |stock_id|.
+class CustomDrawButton : public NotificationObserver {
+ public:
+  // The constructor takes 4 resource ids.  If a resource doesn't exist for a
+  // button, pass in 0.
+  CustomDrawButton(int normal_id,
+                   int pressed_id,
+                   int hover_id,
+                   int disabled_id);
+
+  // Same as above, but uses themed (and possibly tinted) images. |stock_id| and
+  // |stock_size| are used for GTK+ theme mode.
+  CustomDrawButton(GtkThemeProvider* theme_provider,
+                   int normal_id,
+                   int pressed_id,
+                   int hover_id,
+                   int disabled_id,
+                   const char* stock_id,
+                   GtkIconSize stock_size);
+
+  // As above, but uses an arbitrary GtkImage rather than a stock icon. This
+  // constructor takes ownership of |native_widget|.
+  CustomDrawButton(GtkThemeProvider* theme_provider,
+                   int normal_id,
+                   int pressed_id,
+                   int hover_id,
+                   int disabled_id,
+                   GtkWidget* native_widget);
+
+  ~CustomDrawButton();
+
+  void Init();
+
+  // Flip the image horizontally. Not to be used for RTL/LTR reasons. (In RTL
+  // mode, this will unflip the image.)
+  void set_flipped(bool flipped) { button_base_.set_flipped(flipped); }
+
+  GtkWidget* widget() const { return widget_.get(); }
+
+  gfx::Rect bounds() const {
+      return gfx::Rect(widget_->allocation.x,
+                       widget_->allocation.y,
+                       widget_->allocation.width,
+                       widget_->allocation.height);
+  }
+
+  int width() const { return widget_->allocation.width; }
+  int height() const { return widget_->allocation.height; }
+
+  // Set the state to draw. We will paint the widget as if it were in this
+  // state.
+  void SetPaintOverride(GtkStateType state);
+
+  // Resume normal drawing of the widget's state.
+  void UnsetPaintOverride();
+
+  // Set the background details.
+  void SetBackground(SkColor color, SkBitmap* image, SkBitmap* mask);
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Returns a standard close button. Pass a |theme_provider| to use Gtk icons
+  // in Gtk rendering mode.
+  static CustomDrawButton* CloseButton(GtkThemeProvider* theme_provider);
+
+ private:
+  // Sets the button to themed or not.
+  void SetBrowserTheme();
+
+  // Whether to use the GTK+ theme. For this to be true, we have to be in GTK+
+  // theme mode and we must have a valid stock icon resource.
+  bool UseGtkTheme();
+
+  // Callback for custom button expose, used to draw the custom graphics.
+  CHROMEGTK_CALLBACK_1(CustomDrawButton, gboolean, OnCustomExpose,
+                       GdkEventExpose*);
+
+  // The actual button widget.
+  OwnedWidgetGtk widget_;
+
+  CustomDrawButtonBase button_base_;
+
+  CustomDrawHoverController hover_controller_;
+
+  // The widget to use when we are displaying in GTK+ theme mode.
+  OwnedWidgetGtk native_widget_;
+
+  // Our theme provider.
+  GtkThemeProvider* theme_provider_;
+
+  // Used to listen for theme change notifications.
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(CustomDrawButton);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_CUSTOM_BUTTON_H_
diff --git a/chrome/browser/ui/gtk/custom_drag.cc b/chrome/browser/ui/gtk/custom_drag.cc
new file mode 100644
index 0000000..8b8edb9
--- /dev/null
+++ b/chrome/browser/ui/gtk/custom_drag.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/custom_drag.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/download/download_item.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+const int kDownloadItemCodeMask = ui::TEXT_URI_LIST | ui::CHROME_NAMED_URL;
+const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY;
+const GdkDragAction kBookmarkDragAction =
+    static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+void OnDragDataGetForDownloadItem(GtkSelectionData* selection_data,
+                                  guint target_type,
+                                  const DownloadItem* download_item) {
+  GURL url = net::FilePathToFileURL(download_item->full_path());
+  ui::WriteURLWithName(selection_data, url,
+      UTF8ToUTF16(download_item->GetFileNameToReportUser().value()),
+      target_type);
+}
+
+void OnDragDataGetStandalone(GtkWidget* widget, GdkDragContext* context,
+                             GtkSelectionData* selection_data,
+                             guint target_type, guint time,
+                             const DownloadItem* item) {
+  OnDragDataGetForDownloadItem(selection_data, target_type, item);
+}
+
+}  // namespace
+
+// CustomDrag ------------------------------------------------------------------
+
+CustomDrag::CustomDrag(SkBitmap* icon, int code_mask, GdkDragAction action)
+    : drag_widget_(gtk_invisible_new()),
+      pixbuf_(icon ? gfx::GdkPixbufFromSkBitmap(icon) : NULL) {
+  g_signal_connect(drag_widget_, "drag-data-get",
+                   G_CALLBACK(OnDragDataGetThunk), this);
+  g_signal_connect(drag_widget_, "drag-begin",
+                   G_CALLBACK(OnDragBeginThunk), this);
+  g_signal_connect(drag_widget_, "drag-end",
+                   G_CALLBACK(OnDragEndThunk), this);
+
+  GtkTargetList* list = ui::GetTargetListFromCodeMask(code_mask);
+  GdkEvent* event = gtk_get_current_event();
+  gtk_drag_begin(drag_widget_, list, action, 1, event);
+  if (event)
+    gdk_event_free(event);
+  gtk_target_list_unref(list);
+}
+
+CustomDrag::~CustomDrag() {
+  if (pixbuf_)
+    g_object_unref(pixbuf_);
+  gtk_widget_destroy(drag_widget_);
+}
+
+void CustomDrag::OnDragBegin(GtkWidget* widget, GdkDragContext* drag_context) {
+  if (pixbuf_)
+    gtk_drag_set_icon_pixbuf(drag_context, pixbuf_, 0, 0);
+}
+
+void CustomDrag::OnDragEnd(GtkWidget* widget, GdkDragContext* drag_context) {
+  delete this;
+}
+
+// DownloadItemDrag ------------------------------------------------------------
+
+DownloadItemDrag::DownloadItemDrag(const DownloadItem* item,
+                                   SkBitmap* icon)
+    : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction),
+      download_item_(item) {
+}
+
+DownloadItemDrag::~DownloadItemDrag() {
+}
+
+void DownloadItemDrag::OnDragDataGet(
+    GtkWidget* widget, GdkDragContext* context,
+    GtkSelectionData* selection_data,
+    guint target_type, guint time) {
+  OnDragDataGetForDownloadItem(selection_data, target_type, download_item_);
+}
+
+// static
+void DownloadItemDrag::SetSource(GtkWidget* widget,
+                                 DownloadItem* item,
+                                 SkBitmap* icon) {
+  gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0,
+                      kDownloadItemDragAction);
+  ui::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask);
+
+  // Disconnect previous signal handlers, if any.
+  g_signal_handlers_disconnect_by_func(
+      widget,
+      reinterpret_cast<gpointer>(OnDragDataGetStandalone),
+      item);
+  // Connect new signal handlers.
+  g_signal_connect(widget, "drag-data-get",
+                   G_CALLBACK(OnDragDataGetStandalone), item);
+
+  GdkPixbuf* pixbuf = icon ? gfx::GdkPixbufFromSkBitmap(icon) : NULL;
+  if (pixbuf) {
+    gtk_drag_source_set_icon_pixbuf(widget, pixbuf);
+    g_object_unref(pixbuf);
+  }
+}
+
+// static
+void DownloadItemDrag::BeginDrag(const DownloadItem* item, SkBitmap* icon) {
+  new DownloadItemDrag(item, icon);
+}
+
+// BookmarkDrag ----------------------------------------------------------------
+
+BookmarkDrag::BookmarkDrag(Profile* profile,
+                           const std::vector<const BookmarkNode*>& nodes)
+    : CustomDrag(NULL,
+                 bookmark_utils::GetCodeMask(false),
+                 kBookmarkDragAction),
+      profile_(profile),
+      nodes_(nodes) {
+}
+
+BookmarkDrag::~BookmarkDrag() {
+}
+
+void BookmarkDrag::OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
+                                 GtkSelectionData* selection_data,
+                                 guint target_type, guint time) {
+  bookmark_utils::WriteBookmarksToSelection(nodes_, selection_data,
+                                            target_type, profile_);
+}
+
+// static
+void BookmarkDrag::BeginDrag(Profile* profile,
+                             const std::vector<const BookmarkNode*>& nodes) {
+  new BookmarkDrag(profile, nodes);
+}
diff --git a/chrome/browser/ui/gtk/custom_drag.h b/chrome/browser/ui/gtk/custom_drag.h
new file mode 100644
index 0000000..d3f893b
--- /dev/null
+++ b/chrome/browser/ui/gtk/custom_drag.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.
+
+#ifndef CHROME_BROWSER_UI_GTK_CUSTOM_DRAG_H_
+#define CHROME_BROWSER_UI_GTK_CUSTOM_DRAG_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class BookmarkNode;
+class DownloadItem;
+class Profile;
+class SkBitmap;
+
+// Base class for programatically generated drags.
+class CustomDrag {
+ protected:
+  explicit CustomDrag(SkBitmap* icon, int code_mask, GdkDragAction action);
+  virtual ~CustomDrag();
+
+  virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
+                             GtkSelectionData* selection_data,
+                             guint target_type, guint time) = 0;
+
+ private:
+  CHROMEGTK_CALLBACK_1(CustomDrag, void, OnDragBegin, GdkDragContext*);
+  CHROMEGTK_CALLBACK_1(CustomDrag, void, OnDragEnd, GdkDragContext*);
+
+  // Since this uses a virtual function, we can't use a macro.
+  static void OnDragDataGetThunk(GtkWidget* widget, GdkDragContext* context,
+                                 GtkSelectionData* selection_data,
+                                 guint target_type, guint time,
+                                 CustomDrag* custom_drag) {
+    return custom_drag->OnDragDataGet(widget, context, selection_data,
+                                      target_type, time);
+  }
+
+  // Can't use a OwnedWidgetGtk because the initialization of GtkInvisible
+  // sinks the reference.
+  GtkWidget* drag_widget_;
+
+  GdkPixbuf* pixbuf_;
+
+  DISALLOW_COPY_AND_ASSIGN(CustomDrag);
+};
+
+// Encapsulates functionality for drags of download items.
+class DownloadItemDrag : public CustomDrag {
+ public:
+  // Sets |widget| as a source for drags pertaining to |item|. No
+  // DownloadItemDrag object is created.
+  // It is safe to call this multiple times with different values of |icon|.
+  static void SetSource(GtkWidget* widget, DownloadItem* item, SkBitmap* icon);
+
+  // Creates a new DownloadItemDrag, the lifetime of which is tied to the
+  // system drag.
+  static void BeginDrag(const DownloadItem* item, SkBitmap* icon);
+
+ private:
+  DownloadItemDrag(const DownloadItem* item, SkBitmap* icon);
+  virtual ~DownloadItemDrag();
+
+  virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
+                             GtkSelectionData* selection_data,
+                             guint target_type, guint time);
+
+  const DownloadItem* download_item_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadItemDrag);
+};
+
+// Encapsulates functionality for drags of one or more bookmarks.
+class BookmarkDrag : public CustomDrag {
+ public:
+  // Creates a new BookmarkDrag, the lifetime of which is tied to the
+  // system drag.
+  static void BeginDrag(Profile* profile,
+                        const std::vector<const BookmarkNode*>& nodes);
+
+ private:
+  BookmarkDrag(Profile* profile,
+               const std::vector<const BookmarkNode*>& nodes);
+  virtual ~BookmarkDrag();
+
+  virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
+                             GtkSelectionData* selection_data,
+                             guint target_type, guint time);
+
+  Profile* profile_;
+  std::vector<const BookmarkNode*> nodes_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkDrag);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_CUSTOM_DRAG_H_
diff --git a/chrome/browser/ui/gtk/dialogs_gtk.cc b/chrome/browser/ui/gtk/dialogs_gtk.cc
new file mode 100644
index 0000000..19c1672
--- /dev/null
+++ b/chrome/browser/ui/gtk/dialogs_gtk.cc
@@ -0,0 +1,590 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+#include <map>
+#include <set>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/mime_util.h"
+#include "base/sys_string_conversions.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/ui/shell_dialogs.h"
+#include "grit/generated_resources.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// The size of the preview we display for selected image files. We set height
+// larger than width because generally there is more free space vertically
+// than horiztonally (setting the preview image will alway expand the width of
+// the dialog, but usually not the height). The image's aspect ratio will always
+// be preserved.
+static const int kPreviewWidth = 256;
+static const int kPreviewHeight = 512;
+
+// Implementation of SelectFileDialog that shows a Gtk common dialog for
+// choosing a file or folder. This acts as a modal dialog.
+class SelectFileDialogImpl : public SelectFileDialog {
+ public:
+  explicit SelectFileDialogImpl(Listener* listener);
+
+  // BaseShellDialog implementation.
+  virtual bool IsRunning(gfx::NativeWindow parent_window) const;
+  virtual void ListenerDestroyed();
+
+  // SelectFileDialog implementation.
+  // |params| is user data we pass back via the Listener interface.
+  virtual void SelectFile(Type type,
+                          const string16& title,
+                          const FilePath& default_path,
+                          const FileTypeInfo* file_types,
+                          int file_type_index,
+                          const FilePath::StringType& default_extension,
+                          gfx::NativeWindow owning_window,
+                          void* params);
+
+ private:
+  virtual ~SelectFileDialogImpl();
+
+  // Add the filters from |file_types_| to |chooser|.
+  void AddFilters(GtkFileChooser* chooser);
+
+  // Notifies the listener that a single file was chosen.
+  void FileSelected(GtkWidget* dialog, const FilePath& path);
+
+  // Notifies the listener that multiple files were chosen.
+  void MultiFilesSelected(GtkWidget* dialog,
+                          const std::vector<FilePath>& files);
+
+  // Notifies the listener that no file was chosen (the action was canceled).
+  // Dialog is passed so we can find that |params| pointer that was passed to
+  // us when we were told to show the dialog.
+  void FileNotSelected(GtkWidget* dialog);
+
+  GtkWidget* CreateSelectFolderDialog(const std::string& title,
+      const FilePath& default_path, gfx::NativeWindow parent);
+
+  GtkWidget* CreateFileOpenDialog(const std::string& title,
+      const FilePath& default_path, gfx::NativeWindow parent);
+
+  GtkWidget* CreateMultiFileOpenDialog(const std::string& title,
+      const FilePath& default_path, gfx::NativeWindow parent);
+
+  GtkWidget* CreateSaveAsDialog(const std::string& title,
+      const FilePath& default_path, gfx::NativeWindow parent);
+
+  // Removes and returns the |params| associated with |dialog| from
+  // |params_map_|.
+  void* PopParamsForDialog(GtkWidget* dialog);
+
+  // Take care of internal data structures when a file dialog is destroyed.
+  void FileDialogDestroyed(GtkWidget* dialog);
+
+  // Check whether response_id corresponds to the user cancelling/closing the
+  // dialog. Used as a helper for the below callbacks.
+  bool IsCancelResponse(gint response_id);
+
+  // Common function for OnSelectSingleFileDialogResponse and
+  // OnSelectSingleFolderDialogResponse.
+  void SelectSingleFileHelper(GtkWidget* dialog,
+                              gint response_id,
+                              bool allow_folder);
+
+  // Common function for CreateFileOpenDialog and CreateMultiFileOpenDialog.
+  GtkWidget* CreateFileOpenHelper(const std::string& title,
+                                  const FilePath& default_path,
+                                  gfx::NativeWindow parent);
+
+  // Wrapper for file_util::DirectoryExists() that allow access on the UI
+  // thread. Use this only in the file dialog functions, where it's ok
+  // because the file dialog has to do many stats anyway. One more won't
+  // hurt too badly and it's likely already cached.
+  bool CallDirectoryExistsOnUIThread(const FilePath& path);
+
+  // Callback for when the user responds to a Save As or Open File dialog.
+  CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
+                       OnSelectSingleFileDialogResponse, gint);
+
+  // Callback for when the user responds to a Select Folder dialog.
+  CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
+                       OnSelectSingleFolderDialogResponse, gint);
+
+  // Callback for when the user responds to a Open Multiple Files dialog.
+  CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
+                       OnSelectMultiFileDialogResponse, gint);
+
+  // Callback for when the file chooser gets destroyed.
+  CHROMEGTK_CALLBACK_0(SelectFileDialogImpl, void, OnFileChooserDestroy);
+
+  // Callback for when we update the preview for the selection.
+  CHROMEGTK_CALLBACK_0(SelectFileDialogImpl, void, OnUpdatePreview);
+
+  // The listener to be notified of selection completion.
+  Listener* listener_;
+
+  // A map from dialog windows to the |params| user data associated with them.
+  std::map<GtkWidget*, void*> params_map_;
+
+  // The file filters.
+  FileTypeInfo file_types_;
+
+  // The index of the default selected file filter.
+  // Note: This starts from 1, not 0.
+  size_t file_type_index_;
+
+  // The set of all parent windows for which we are currently running dialogs.
+  std::set<GtkWindow*> parents_;
+
+  // The type of dialog we are showing the user.
+  Type type_;
+
+  // These two variables track where the user last saved a file or opened a
+  // file so that we can display future dialogs with the same starting path.
+  static FilePath* last_saved_path_;
+  static FilePath* last_opened_path_;
+
+  // The GtkImage widget for showing previews of selected images.
+  GtkWidget* preview_;
+
+  // All our dialogs.
+  std::set<GtkWidget*> dialogs_;
+
+  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
+};
+
+FilePath* SelectFileDialogImpl::last_saved_path_ = NULL;
+FilePath* SelectFileDialogImpl::last_opened_path_ = NULL;
+
+// static
+SelectFileDialog* SelectFileDialog::Create(Listener* listener) {
+  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  return new SelectFileDialogImpl(listener);
+}
+
+SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener)
+    : listener_(listener),
+      file_type_index_(0),
+      type_(SELECT_NONE),
+      preview_(NULL) {
+  if (!last_saved_path_) {
+    last_saved_path_ = new FilePath();
+    last_opened_path_ = new FilePath();
+  }
+}
+
+SelectFileDialogImpl::~SelectFileDialogImpl() {
+  while (dialogs_.begin() != dialogs_.end()) {
+    gtk_widget_destroy(*(dialogs_.begin()));
+  }
+}
+
+bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
+  return parents_.find(parent_window) != parents_.end();
+}
+
+void SelectFileDialogImpl::ListenerDestroyed() {
+  listener_ = NULL;
+}
+
+// We ignore |default_extension|.
+void SelectFileDialogImpl::SelectFile(
+    Type type,
+    const string16& title,
+    const FilePath& default_path,
+    const FileTypeInfo* file_types,
+    int file_type_index,
+    const FilePath::StringType& default_extension,
+    gfx::NativeWindow owning_window,
+    void* params) {
+  type_ = type;
+  // |owning_window| can be null when user right-clicks on a downloadable item
+  // and chooses 'Open Link in New Tab' when 'Ask where to save each file
+  // before downloading.' preference is turned on. (http://crbug.com/29213)
+  if (owning_window)
+    parents_.insert(owning_window);
+
+  std::string title_string = UTF16ToUTF8(title);
+
+  file_type_index_ = file_type_index;
+  if (file_types)
+    file_types_ = *file_types;
+  else
+    file_types_.include_all_files = true;
+
+  GtkWidget* dialog = NULL;
+  switch (type) {
+    case SELECT_FOLDER:
+      dialog = CreateSelectFolderDialog(title_string, default_path,
+                                        owning_window);
+      break;
+    case SELECT_OPEN_FILE:
+      dialog = CreateFileOpenDialog(title_string, default_path, owning_window);
+      break;
+    case SELECT_OPEN_MULTI_FILE:
+      dialog = CreateMultiFileOpenDialog(title_string, default_path,
+                                         owning_window);
+      break;
+    case SELECT_SAVEAS_FILE:
+      dialog = CreateSaveAsDialog(title_string, default_path, owning_window);
+      break;
+    default:
+      NOTREACHED();
+      return;
+  }
+  dialogs_.insert(dialog);
+
+  preview_ = gtk_image_new();
+  g_signal_connect(dialog, "destroy",
+                   G_CALLBACK(OnFileChooserDestroyThunk), this);
+  g_signal_connect(dialog, "update-preview",
+                   G_CALLBACK(OnUpdatePreviewThunk), this);
+  gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_);
+
+  params_map_[dialog] = params;
+
+  // Set window-to-parent modality by adding the dialog to the same window
+  // group as the parent.
+  gtk_window_group_add_window(gtk_window_get_group(owning_window),
+                              GTK_WINDOW(dialog));
+  gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+
+  gtk_widget_show_all(dialog);
+}
+
+void SelectFileDialogImpl::AddFilters(GtkFileChooser* chooser) {
+  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
+    GtkFileFilter* filter = NULL;
+    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
+      if (!file_types_.extensions[i][j].empty()) {
+        if (!filter)
+          filter = gtk_file_filter_new();
+
+        // Allow IO in the file dialog. http://crbug.com/72637
+        base::ThreadRestrictions::ScopedAllowIO allow_io;
+        std::string mime_type = mime_util::GetFileMimeType(
+            FilePath("name").ReplaceExtension(file_types_.extensions[i][j]));
+        gtk_file_filter_add_mime_type(filter, mime_type.c_str());
+      }
+    }
+    // We didn't find any non-empty extensions to filter on.
+    if (!filter)
+      continue;
+
+    // The description vector may be blank, in which case we are supposed to
+    // use some sort of default description based on the filter.
+    if (i < file_types_.extension_description_overrides.size()) {
+      gtk_file_filter_set_name(filter, UTF16ToUTF8(
+          file_types_.extension_description_overrides[i]).c_str());
+    } else {
+      // There is no system default filter description so we use
+      // the MIME type itself if the description is blank.
+      std::string mime_type = mime_util::GetFileMimeType(
+          FilePath("name").ReplaceExtension(file_types_.extensions[i][0]));
+      gtk_file_filter_set_name(filter, mime_type.c_str());
+    }
+
+    gtk_file_chooser_add_filter(chooser, filter);
+    if (i == file_type_index_ - 1)
+      gtk_file_chooser_set_filter(chooser, filter);
+  }
+
+  // Add the *.* filter, but only if we have added other filters (otherwise it
+  // is implied).
+  if (file_types_.include_all_files && file_types_.extensions.size() > 0) {
+    GtkFileFilter* filter = gtk_file_filter_new();
+    gtk_file_filter_add_pattern(filter, "*");
+    gtk_file_filter_set_name(filter,
+        l10n_util::GetStringUTF8(IDS_SAVEAS_ALL_FILES).c_str());
+    gtk_file_chooser_add_filter(chooser, filter);
+  }
+}
+
+void SelectFileDialogImpl::FileSelected(GtkWidget* dialog,
+                                        const FilePath& path) {
+  if (type_ == SELECT_SAVEAS_FILE)
+    *last_saved_path_ = path.DirName();
+  else if (type_ == SELECT_OPEN_FILE)
+    *last_opened_path_ = path.DirName();
+  else if (type_ == SELECT_FOLDER)
+    *last_opened_path_ = path.DirName().DirName();
+  else
+    NOTREACHED();
+
+  if (listener_) {
+    GtkFileFilter* selected_filter =
+        gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
+    GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog));
+    int idx = g_slist_index(filters, selected_filter);
+    g_slist_free(filters);
+    listener_->FileSelected(path, idx + 1, PopParamsForDialog(dialog));
+  }
+  gtk_widget_destroy(dialog);
+}
+
+void SelectFileDialogImpl::MultiFilesSelected(GtkWidget* dialog,
+    const std::vector<FilePath>& files) {
+  *last_opened_path_ = files[0].DirName();
+
+  if (listener_)
+    listener_->MultiFilesSelected(files, PopParamsForDialog(dialog));
+  gtk_widget_destroy(dialog);
+}
+
+void SelectFileDialogImpl::FileNotSelected(GtkWidget* dialog) {
+  void* params = PopParamsForDialog(dialog);
+  if (listener_)
+    listener_->FileSelectionCanceled(params);
+  gtk_widget_destroy(dialog);
+}
+
+bool SelectFileDialogImpl::CallDirectoryExistsOnUIThread(const FilePath& path) {
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  return file_util::DirectoryExists(path);
+}
+
+GtkWidget* SelectFileDialogImpl::CreateFileOpenHelper(
+    const std::string& title,
+    const FilePath& default_path,
+    gfx::NativeWindow parent) {
+  GtkWidget* dialog =
+      gtk_file_chooser_dialog_new(title.c_str(), parent,
+                                  GTK_FILE_CHOOSER_ACTION_OPEN,
+                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                  NULL);
+  AddFilters(GTK_FILE_CHOOSER(dialog));
+
+  if (!default_path.empty()) {
+    if (CallDirectoryExistsOnUIThread(default_path)) {
+      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+                                          default_path.value().c_str());
+    } else {
+      // If the file doesn't exist, this will just switch to the correct
+      // directory. That's good enough.
+      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
+                                    default_path.value().c_str());
+    }
+  } else if (!last_opened_path_->empty()) {
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+                                        last_opened_path_->value().c_str());
+  }
+  return dialog;
+}
+
+GtkWidget* SelectFileDialogImpl::CreateSelectFolderDialog(
+    const std::string& title,
+    const FilePath& default_path,
+    gfx::NativeWindow parent) {
+  std::string title_string = !title.empty() ? title :
+        l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE);
+
+  GtkWidget* dialog =
+      gtk_file_chooser_dialog_new(title_string.c_str(), parent,
+                                  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                  NULL);
+
+  if (!default_path.empty()) {
+    gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
+                                  default_path.value().c_str());
+  } else if (!last_opened_path_->empty()) {
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+                                        last_opened_path_->value().c_str());
+  }
+  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
+  g_signal_connect(dialog, "response",
+                   G_CALLBACK(OnSelectSingleFolderDialogResponseThunk), this);
+  return dialog;
+}
+
+GtkWidget* SelectFileDialogImpl::CreateFileOpenDialog(
+    const std::string& title,
+    const FilePath& default_path,
+    gfx::NativeWindow parent) {
+  std::string title_string = !title.empty() ? title :
+        l10n_util::GetStringUTF8(IDS_OPEN_FILE_DIALOG_TITLE);
+  GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent);
+  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
+  g_signal_connect(dialog, "response",
+                   G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this);
+  return dialog;
+}
+
+GtkWidget* SelectFileDialogImpl::CreateMultiFileOpenDialog(
+    const std::string& title,
+    const FilePath& default_path,
+    gfx::NativeWindow parent) {
+  std::string title_string = !title.empty() ? title :
+        l10n_util::GetStringUTF8(IDS_OPEN_FILES_DIALOG_TITLE);
+  GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent);
+  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
+  g_signal_connect(dialog, "response",
+                   G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this);
+  return dialog;
+}
+
+GtkWidget* SelectFileDialogImpl::CreateSaveAsDialog(const std::string& title,
+    const FilePath& default_path, gfx::NativeWindow parent) {
+  std::string title_string = !title.empty() ? title :
+        l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE);
+
+  GtkWidget* dialog =
+      gtk_file_chooser_dialog_new(title_string.c_str(), parent,
+                                  GTK_FILE_CHOOSER_ACTION_SAVE,
+                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                  NULL);
+
+  AddFilters(GTK_FILE_CHOOSER(dialog));
+  if (!default_path.empty()) {
+    // Since the file may not already exist, we use
+    // set_current_folder() followed by set_current_name(), as per the
+    // recommendation of the GTK docs.
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+        default_path.DirName().value().c_str());
+    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
+        default_path.BaseName().value().c_str());
+  } else if (!last_saved_path_->empty()) {
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+                                        last_saved_path_->value().c_str());
+  }
+  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
+  gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog),
+                                                 TRUE);
+  g_signal_connect(dialog, "response",
+                   G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this);
+  return dialog;
+}
+
+void* SelectFileDialogImpl::PopParamsForDialog(GtkWidget* dialog) {
+  std::map<GtkWidget*, void*>::iterator iter = params_map_.find(dialog);
+  DCHECK(iter != params_map_.end());
+  void* params = iter->second;
+  params_map_.erase(iter);
+  return params;
+}
+
+void SelectFileDialogImpl::FileDialogDestroyed(GtkWidget* dialog) {
+  dialogs_.erase(dialog);
+
+  // Parent may be NULL in a few cases: 1) on shutdown when
+  // AllBrowsersClosed() trigger this handler after all the browser
+  // windows got destroyed, or 2) when the parent tab has been opened by
+  // 'Open Link in New Tab' context menu on a downloadable item and
+  // the tab has no content (see the comment in SelectFile as well).
+  GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog));
+  if (!parent)
+    return;
+  std::set<GtkWindow*>::iterator iter = parents_.find(parent);
+  if (iter != parents_.end())
+    parents_.erase(iter);
+  else
+    NOTREACHED();
+}
+
+bool SelectFileDialogImpl::IsCancelResponse(gint response_id) {
+  bool is_cancel = response_id == GTK_RESPONSE_CANCEL ||
+                   response_id == GTK_RESPONSE_DELETE_EVENT;
+  if (is_cancel)
+    return true;
+
+  DCHECK(response_id == GTK_RESPONSE_ACCEPT);
+  return false;
+}
+
+void SelectFileDialogImpl::SelectSingleFileHelper(GtkWidget* dialog,
+    gint response_id,
+    bool allow_folder) {
+  if (IsCancelResponse(response_id)) {
+    FileNotSelected(dialog);
+    return;
+  }
+
+  gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+  if (!filename) {
+    FileNotSelected(dialog);
+    return;
+  }
+
+  FilePath path(filename);
+  g_free(filename);
+
+  if (allow_folder) {
+    FileSelected(dialog, path);
+    return;
+  }
+
+  if (CallDirectoryExistsOnUIThread(path))
+    FileNotSelected(dialog);
+  else
+    FileSelected(dialog, path);
+}
+
+void SelectFileDialogImpl::OnSelectSingleFileDialogResponse(
+    GtkWidget* dialog, gint response_id) {
+  return SelectSingleFileHelper(dialog, response_id, false);
+}
+
+void SelectFileDialogImpl::OnSelectSingleFolderDialogResponse(
+    GtkWidget* dialog, gint response_id) {
+  return SelectSingleFileHelper(dialog, response_id, true);
+}
+
+void SelectFileDialogImpl::OnSelectMultiFileDialogResponse(
+    GtkWidget* dialog, gint response_id) {
+  if (IsCancelResponse(response_id)) {
+    FileNotSelected(dialog);
+    return;
+  }
+
+  GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
+  if (!filenames) {
+    FileNotSelected(dialog);
+    return;
+  }
+
+  std::vector<FilePath> filenames_fp;
+  for (GSList* iter = filenames; iter != NULL; iter = g_slist_next(iter)) {
+    FilePath path(static_cast<char*>(iter->data));
+    g_free(iter->data);
+    if (CallDirectoryExistsOnUIThread(path))
+      continue;
+    filenames_fp.push_back(path);
+  }
+  g_slist_free(filenames);
+
+  if (filenames_fp.empty()) {
+    FileNotSelected(dialog);
+    return;
+  }
+  MultiFilesSelected(dialog, filenames_fp);
+}
+
+void SelectFileDialogImpl::OnFileChooserDestroy(GtkWidget* dialog) {
+  FileDialogDestroyed(dialog);
+}
+
+void SelectFileDialogImpl::OnUpdatePreview(GtkWidget* chooser) {
+  gchar* filename = gtk_file_chooser_get_preview_filename(
+      GTK_FILE_CHOOSER(chooser));
+  if (!filename)
+    return;
+  // This will preserve the image's aspect ratio.
+  GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth,
+                                                       kPreviewHeight, NULL);
+  g_free(filename);
+  if (pixbuf) {
+    gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf);
+    g_object_unref(pixbuf);
+  }
+  gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser),
+                                             pixbuf ? TRUE : FALSE);
+}
diff --git a/chrome/browser/ui/gtk/download_in_progress_dialog_gtk.cc b/chrome/browser/ui/gtk/download_in_progress_dialog_gtk.cc
new file mode 100644
index 0000000..de3cb31
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_in_progress_dialog_gtk.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/download_in_progress_dialog_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+DownloadInProgressDialogGtk::DownloadInProgressDialogGtk(Browser* browser)
+    : browser_(browser) {
+  int download_count = browser->profile()->GetDownloadManager()->
+      in_progress_count();
+
+  std::string warning_text;
+  std::string explanation_text;
+  std::string ok_button_text;
+  std::string cancel_button_text;
+  string16 product_name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
+  if (download_count == 1) {
+    warning_text =
+        l10n_util::GetStringFUTF8(IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_WARNING,
+                                  product_name);
+    explanation_text =
+        l10n_util::GetStringFUTF8(
+            IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_EXPLANATION,
+            product_name);
+    ok_button_text = l10n_util::GetStringUTF8(
+        IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_OK_BUTTON_LABEL);
+    cancel_button_text = l10n_util::GetStringUTF8(
+        IDS_SINGLE_DOWNLOAD_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL);
+  } else {
+    warning_text =
+        l10n_util::GetStringFUTF8(IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_WARNING,
+                                  product_name,
+                                  base::IntToString16(download_count));
+    explanation_text =
+        l10n_util::GetStringFUTF8(
+            IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_EXPLANATION, product_name);
+    ok_button_text = l10n_util::GetStringUTF8(
+        IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_OK_BUTTON_LABEL);
+    cancel_button_text = l10n_util::GetStringUTF8(
+        IDS_MULTIPLE_DOWNLOADS_REMOVE_CONFIRM_CANCEL_BUTTON_LABEL);
+  }
+
+  GtkWidget* dialog = gtk_message_dialog_new(
+      browser_->window()->GetNativeHandle(),
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
+      GTK_MESSAGE_QUESTION,
+      GTK_BUTTONS_NONE,
+      "%s",
+      warning_text.c_str());
+  gtk_util::AddButtonToDialog(dialog,
+      cancel_button_text.c_str(),
+      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+  gtk_util::AddButtonToDialog(dialog,
+      ok_button_text.c_str(),
+      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+
+  gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+                                           "%s",
+                                           explanation_text.c_str());
+
+  g_signal_connect(dialog, "response", G_CALLBACK(OnResponseThunk), this);
+
+  gtk_widget_show_all(dialog);
+}
+
+void DownloadInProgressDialogGtk::OnResponse(GtkWidget* widget,
+                                             int response) {
+  gtk_widget_destroy(widget);
+  browser_->InProgressDownloadResponse(response == GTK_RESPONSE_ACCEPT);
+  delete this;
+}
diff --git a/chrome/browser/ui/gtk/download_in_progress_dialog_gtk.h b/chrome/browser/ui/gtk/download_in_progress_dialog_gtk.h
new file mode 100644
index 0000000..dd8fdb4
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_in_progress_dialog_gtk.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_DOWNLOAD_IN_PROGRESS_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_DOWNLOAD_IN_PROGRESS_DIALOG_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Browser;
+
+typedef struct _GtkWidget GtkWidget;
+
+class DownloadInProgressDialogGtk {
+ public:
+  explicit DownloadInProgressDialogGtk(Browser* browser);
+
+ protected:
+  virtual ~DownloadInProgressDialogGtk() {}
+
+ private:
+  CHROMEGTK_CALLBACK_1(DownloadInProgressDialogGtk, void, OnResponse, int);
+
+  Browser* browser_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadInProgressDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_DOWNLOAD_IN_PROGRESS_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/download_item_gtk.cc b/chrome/browser/ui/gtk/download_item_gtk.cc
new file mode 100644
index 0000000..27a2e06
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_item_gtk.cc
@@ -0,0 +1,880 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/download_item_gtk.h"
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/metrics/histogram.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_item.h"
+#include "chrome/browser/download/download_item_model.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_shelf.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/custom_drag.h"
+#include "chrome/browser/ui/gtk/download_shelf_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/nine_box.h"
+#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/skia_utils_gtk.h"
+
+namespace {
+
+// The width of the |menu_button_| widget. It has to be at least as wide as the
+// bitmap that we use to draw it, i.e. 16, but can be more.
+const int kMenuButtonWidth = 16;
+
+// Padding on left and right of items in dangerous download prompt.
+const int kDangerousElementPadding = 3;
+
+// Amount of space we allot to showing the filename. If the filename is too wide
+// it will be elided.
+const int kTextWidth = 140;
+
+// We only cap the size of the tooltip so we don't crash.
+const int kTooltipMaxWidth = 1000;
+
+// The minimum width we will ever draw the download item. Used as a lower bound
+// during animation. This number comes from the width of the images used to
+// make the download item.
+const int kMinDownloadItemWidth = download_util::kSmallProgressIconSize;
+
+// New download item animation speed in milliseconds.
+const int kNewItemAnimationDurationMs = 800;
+
+// How long the 'download complete' animation should last for.
+const int kCompleteAnimationDurationMs = 2500;
+
+// Width of the body area of the download item.
+// TODO(estade): get rid of the fudge factor. http://crbug.com/18692
+const int kBodyWidth = kTextWidth + 50 + download_util::kSmallProgressIconSize;
+
+// The font size of the text, and that size rounded down to the nearest integer
+// for the size of the arrow in GTK theme mode.
+const double kTextSize = 13.4;  // 13.4px == 10pt @ 96dpi
+
+// Darken light-on-dark download status text by 20% before drawing, thus
+// creating a "muted" version of title text for both dark-on-light and
+// light-on-dark themes.
+static const double kDownloadItemLuminanceMod = 0.8;
+
+}  // namespace
+
+// DownloadShelfContextMenuGtk -------------------------------------------------
+
+class DownloadShelfContextMenuGtk : public DownloadShelfContextMenu,
+                                    public MenuGtk::Delegate {
+ public:
+  // The constructor creates the menu and immediately pops it up.
+  // |model| is the download item model associated with this context menu,
+  // |widget| is the button that popped up this context menu, and |e| is
+  // the button press event that caused this menu to be created.
+  DownloadShelfContextMenuGtk(BaseDownloadItemModel* model,
+                              DownloadItemGtk* download_item)
+      : DownloadShelfContextMenu(model),
+        download_item_(download_item) {
+  }
+
+  ~DownloadShelfContextMenuGtk() {
+  }
+
+  void Popup(GtkWidget* widget, GdkEventButton* event) {
+    // Create the menu if we have not created it yet or we created it for
+    // an in-progress download that has since completed.
+    if (download_->state() == DownloadItem::COMPLETE)
+      menu_.reset(new MenuGtk(this, GetFinishedMenuModel()));
+    else
+      menu_.reset(new MenuGtk(this, GetInProgressMenuModel()));
+    menu_->PopupForWidget(widget, event->button, event->time);
+  }
+
+  // MenuGtk::Delegate implementation:
+  virtual void StoppedShowing() {
+    download_item_->menu_showing_ = false;
+    gtk_widget_queue_draw(download_item_->menu_button_);
+  }
+
+  virtual GtkWidget* GetImageForCommandId(int command_id) const {
+    const char* stock = NULL;
+    switch (command_id) {
+      case SHOW_IN_FOLDER:
+      case OPEN_WHEN_COMPLETE:
+        stock = GTK_STOCK_OPEN;
+        break;
+
+      case CANCEL:
+        stock = GTK_STOCK_CANCEL;
+        break;
+
+      case ALWAYS_OPEN_TYPE:
+      case TOGGLE_PAUSE:
+        stock = NULL;
+    }
+
+    return stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU) : NULL;
+  }
+
+ private:
+  // The menu we show on Popup(). We keep a pointer to it for a couple reasons:
+  //  * we don't want to have to recreate the menu every time it's popped up.
+  //  * we have to keep it in scope for longer than the duration of Popup(), or
+  //    completing the user-selected action races against the menu's
+  //    destruction.
+  scoped_ptr<MenuGtk> menu_;
+
+  // The download item that created us.
+  DownloadItemGtk* download_item_;
+};
+
+// DownloadItemGtk -------------------------------------------------------------
+
+NineBox* DownloadItemGtk::body_nine_box_normal_ = NULL;
+NineBox* DownloadItemGtk::body_nine_box_prelight_ = NULL;
+NineBox* DownloadItemGtk::body_nine_box_active_ = NULL;
+
+NineBox* DownloadItemGtk::menu_nine_box_normal_ = NULL;
+NineBox* DownloadItemGtk::menu_nine_box_prelight_ = NULL;
+NineBox* DownloadItemGtk::menu_nine_box_active_ = NULL;
+
+NineBox* DownloadItemGtk::dangerous_nine_box_ = NULL;
+
+DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf,
+                                 BaseDownloadItemModel* download_model)
+    : parent_shelf_(parent_shelf),
+      arrow_(NULL),
+      menu_showing_(false),
+      theme_provider_(GtkThemeProvider::GetFrom(
+                          parent_shelf->browser()->profile())),
+      progress_angle_(download_util::kStartAngleDegrees),
+      download_model_(download_model),
+      dangerous_prompt_(NULL),
+      dangerous_label_(NULL),
+      icon_small_(NULL),
+      icon_large_(NULL),
+      creation_time_(base::Time::Now()) {
+  LoadIcon();
+
+  body_.Own(gtk_button_new());
+  gtk_widget_set_app_paintable(body_.get(), TRUE);
+  UpdateTooltip();
+
+  g_signal_connect(body_.get(), "expose-event",
+                   G_CALLBACK(OnExposeThunk), this);
+  g_signal_connect(body_.get(), "clicked",
+                   G_CALLBACK(OnClickThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(body_.get(), GTK_CAN_FOCUS);
+  // Remove internal padding on the button.
+  GtkRcStyle* no_padding_style = gtk_rc_style_new();
+  no_padding_style->xthickness = 0;
+  no_padding_style->ythickness = 0;
+  gtk_widget_modify_style(body_.get(), no_padding_style);
+  g_object_unref(no_padding_style);
+
+  name_label_ = gtk_label_new(NULL);
+
+  UpdateNameLabel();
+
+  status_label_ = gtk_label_new(NULL);
+  g_signal_connect(status_label_, "destroy",
+                   G_CALLBACK(gtk_widget_destroyed), &status_label_);
+  // Left align and vertically center the labels.
+  gtk_misc_set_alignment(GTK_MISC(name_label_), 0, 0.5);
+  gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0.5);
+  // Until we switch to vector graphics, force the font size.
+  gtk_util::ForceFontSizePixels(name_label_, kTextSize);
+  gtk_util::ForceFontSizePixels(status_label_, kTextSize);
+
+  // Stack the labels on top of one another.
+  GtkWidget* text_stack = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(text_stack), name_label_, TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(text_stack), status_label_, FALSE, FALSE, 0);
+
+  // We use a GtkFixed because we don't want it to have its own window.
+  // This choice of widget is not critically important though.
+  progress_area_.Own(gtk_fixed_new());
+  gtk_widget_set_size_request(progress_area_.get(),
+      download_util::kSmallProgressIconSize,
+      download_util::kSmallProgressIconSize);
+  gtk_widget_set_app_paintable(progress_area_.get(), TRUE);
+  g_signal_connect(progress_area_.get(), "expose-event",
+                   G_CALLBACK(OnProgressAreaExposeThunk), this);
+
+  // Put the download progress icon on the left of the labels.
+  GtkWidget* body_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(body_.get()), body_hbox);
+  gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_.get(), FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(body_hbox), text_stack, TRUE, TRUE, 0);
+
+  menu_button_ = gtk_button_new();
+  gtk_widget_set_app_paintable(menu_button_, TRUE);
+  GTK_WIDGET_UNSET_FLAGS(menu_button_, GTK_CAN_FOCUS);
+  g_signal_connect(menu_button_, "expose-event",
+                   G_CALLBACK(OnExposeThunk), this);
+  g_signal_connect(menu_button_, "button-press-event",
+                   G_CALLBACK(OnMenuButtonPressEventThunk), this);
+  g_object_set_data(G_OBJECT(menu_button_), "left-align-popup",
+                    reinterpret_cast<void*>(true));
+
+  GtkWidget* shelf_hbox = parent_shelf->GetHBox();
+  hbox_.Own(gtk_hbox_new(FALSE, 0));
+  g_signal_connect(hbox_.get(), "expose-event",
+                   G_CALLBACK(OnHboxExposeThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), body_.get(), FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), menu_button_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(shelf_hbox), hbox_.get(), FALSE, FALSE, 0);
+  // Insert as the leftmost item.
+  gtk_box_reorder_child(GTK_BOX(shelf_hbox), hbox_.get(), 0);
+
+  get_download()->AddObserver(this);
+
+  new_item_animation_.reset(new ui::SlideAnimation(this));
+  new_item_animation_->SetSlideDuration(kNewItemAnimationDurationMs);
+  gtk_widget_show_all(hbox_.get());
+
+  if (IsDangerous()) {
+    // Hide the download item components for now.
+    gtk_widget_hide(body_.get());
+    gtk_widget_hide(menu_button_);
+
+    // Create an hbox to hold it all.
+    dangerous_hbox_ = gtk_hbox_new(FALSE, kDangerousElementPadding);
+
+    // Add padding at the beginning and end. The hbox will add padding between
+    // the empty labels and the other elements.
+    GtkWidget* empty_label_a = gtk_label_new(NULL);
+    GtkWidget* empty_label_b = gtk_label_new(NULL);
+    gtk_box_pack_start(GTK_BOX(dangerous_hbox_), empty_label_a,
+                       FALSE, FALSE, 0);
+    gtk_box_pack_end(GTK_BOX(dangerous_hbox_), empty_label_b,
+                     FALSE, FALSE, 0);
+
+    // Create the warning icon.
+    dangerous_image_ = gtk_image_new();
+    gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_image_,
+                       FALSE, FALSE, 0);
+
+    dangerous_label_ = gtk_label_new(NULL);
+    // We pass TRUE, TRUE so that the label will condense to less than its
+    // request when the animation is going on.
+    gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_label_,
+                       TRUE, TRUE, 0);
+
+    // Create the nevermind button.
+    GtkWidget* dangerous_decline = gtk_button_new_with_label(
+        l10n_util::GetStringUTF8(IDS_DISCARD_DOWNLOAD).c_str());
+    g_signal_connect(dangerous_decline, "clicked",
+                     G_CALLBACK(OnDangerousDeclineThunk), this);
+    gtk_util::CenterWidgetInHBox(dangerous_hbox_, dangerous_decline, false, 0);
+
+    // Create the ok button.
+    GtkWidget* dangerous_accept = gtk_button_new_with_label(
+        l10n_util::GetStringUTF8(
+            download_model->download()->is_extension_install() ?
+                IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_SAVE_DOWNLOAD).c_str());
+    g_signal_connect(dangerous_accept, "clicked",
+                     G_CALLBACK(OnDangerousAcceptThunk), this);
+    gtk_util::CenterWidgetInHBox(dangerous_hbox_, dangerous_accept, false, 0);
+
+    // Put it in an alignment so that padding will be added on the left and
+    // right.
+    dangerous_prompt_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+    gtk_alignment_set_padding(GTK_ALIGNMENT(dangerous_prompt_),
+        0, 0, kDangerousElementPadding, kDangerousElementPadding);
+    gtk_container_add(GTK_CONTAINER(dangerous_prompt_), dangerous_hbox_);
+    gtk_box_pack_start(GTK_BOX(hbox_.get()), dangerous_prompt_, FALSE, FALSE,
+                       0);
+    gtk_widget_set_app_paintable(dangerous_prompt_, TRUE);
+    gtk_widget_set_redraw_on_allocate(dangerous_prompt_, TRUE);
+    g_signal_connect(dangerous_prompt_, "expose-event",
+                     G_CALLBACK(OnDangerousPromptExposeThunk), this);
+    gtk_widget_show_all(dangerous_prompt_);
+  }
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_->InitThemesFor(this);
+
+  // Set the initial width of the widget to be animated.
+  if (IsDangerous()) {
+    gtk_widget_set_size_request(dangerous_hbox_,
+                                dangerous_hbox_start_width_, -1);
+  } else {
+    gtk_widget_set_size_request(body_.get(), kMinDownloadItemWidth, -1);
+  }
+
+  new_item_animation_->Show();
+}
+
+DownloadItemGtk::~DownloadItemGtk() {
+  icon_consumer_.CancelAllRequests();
+  StopDownloadProgress();
+  get_download()->RemoveObserver(this);
+
+  // We may free some shelf space for showing more download items.
+  parent_shelf_->MaybeShowMoreDownloadItems();
+
+  hbox_.Destroy();
+  progress_area_.Destroy();
+  body_.Destroy();
+
+  // Make sure this widget has been destroyed and the pointer we hold to it
+  // NULLed.
+  DCHECK(!status_label_);
+}
+
+void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) {
+  DCHECK_EQ(download, get_download());
+
+  if (dangerous_prompt_ != NULL &&
+      download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) {
+    // We have been approved.
+    gtk_widget_show_all(hbox_.get());
+    gtk_widget_destroy(dangerous_prompt_);
+    gtk_widget_set_size_request(body_.get(), kBodyWidth, -1);
+    dangerous_prompt_ = NULL;
+
+    // We may free some shelf space for showing more download items.
+    parent_shelf_->MaybeShowMoreDownloadItems();
+  }
+
+  if (download->GetUserVerifiedFilePath() != icon_filepath_) {
+    // Turns out the file path is "Unconfirmed %d.crdownload" for dangerous
+    // downloads. When the download is confirmed, the file is renamed on
+    // another thread, so reload the icon if the download filename changes.
+    LoadIcon();
+
+    UpdateTooltip();
+  }
+
+  switch (download->state()) {
+    case DownloadItem::REMOVING:
+      parent_shelf_->RemoveDownloadItem(this);  // This will delete us!
+      return;
+    case DownloadItem::CANCELLED:
+      StopDownloadProgress();
+      gtk_widget_queue_draw(progress_area_.get());
+      break;
+    case DownloadItem::COMPLETE:
+      if (download->auto_opened()) {
+        parent_shelf_->RemoveDownloadItem(this);  // This will delete us!
+        return;
+      }
+      StopDownloadProgress();
+
+      // Set up the widget as a drag source.
+      DownloadItemDrag::SetSource(body_.get(), get_download(), icon_large_);
+
+      complete_animation_.reset(new ui::SlideAnimation(this));
+      complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs);
+      complete_animation_->SetTweenType(ui::Tween::LINEAR);
+      complete_animation_->Show();
+      break;
+    case DownloadItem::IN_PROGRESS:
+      get_download()->is_paused() ?
+          StopDownloadProgress() : StartDownloadProgress();
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  // Now update the status label. We may have already removed it; if so, we
+  // do nothing.
+  if (!status_label_) {
+    return;
+  }
+
+  status_text_ = UTF16ToUTF8(download_model_->GetStatusText());
+  // Remove the status text label.
+  if (status_text_.empty()) {
+    gtk_widget_destroy(status_label_);
+    return;
+  }
+
+  UpdateStatusLabel(status_text_);
+}
+
+void DownloadItemGtk::AnimationProgressed(const ui::Animation* animation) {
+  if (animation == complete_animation_.get()) {
+    gtk_widget_queue_draw(progress_area_.get());
+  } else {
+    if (IsDangerous()) {
+      int progress = static_cast<int>((dangerous_hbox_full_width_ -
+                                       dangerous_hbox_start_width_) *
+                                      new_item_animation_->GetCurrentValue());
+      int showing_width = dangerous_hbox_start_width_ + progress;
+      gtk_widget_set_size_request(dangerous_hbox_, showing_width, -1);
+    } else {
+      DCHECK(animation == new_item_animation_.get());
+      int showing_width = std::max(kMinDownloadItemWidth,
+          static_cast<int>(kBodyWidth *
+                           new_item_animation_->GetCurrentValue()));
+      gtk_widget_set_size_request(body_.get(), showing_width, -1);
+    }
+  }
+}
+
+void DownloadItemGtk::Observe(NotificationType type,
+                              const NotificationSource& source,
+                              const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    // Our GtkArrow is only visible in gtk mode. Otherwise, we let the custom
+    // rendering code do whatever it wants.
+    if (theme_provider_->UseGtkTheme()) {
+      if (!arrow_) {
+        arrow_ = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+        gtk_widget_set_size_request(arrow_,
+                                    static_cast<int>(kTextSize),
+                                    static_cast<int>(kTextSize));
+        gtk_container_add(GTK_CONTAINER(menu_button_), arrow_);
+      }
+
+      gtk_widget_set_size_request(menu_button_, -1, -1);
+      gtk_widget_show(arrow_);
+    } else {
+      InitNineBoxes();
+
+      gtk_widget_set_size_request(menu_button_, kMenuButtonWidth, 0);
+
+      if (arrow_)
+        gtk_widget_hide(arrow_);
+    }
+
+    UpdateNameLabel();
+    UpdateStatusLabel(status_text_);
+    UpdateDangerWarning();
+  }
+}
+
+DownloadItem* DownloadItemGtk::get_download() {
+  return download_model_->download();
+}
+
+bool DownloadItemGtk::IsDangerous() {
+  return get_download()->safety_state() == DownloadItem::DANGEROUS;
+}
+
+// Download progress animation functions.
+
+void DownloadItemGtk::UpdateDownloadProgress() {
+  progress_angle_ = (progress_angle_ +
+                     download_util::kUnknownIncrementDegrees) %
+                    download_util::kMaxDegrees;
+  gtk_widget_queue_draw(progress_area_.get());
+}
+
+void DownloadItemGtk::StartDownloadProgress() {
+  if (progress_timer_.IsRunning())
+    return;
+  progress_timer_.Start(
+      base::TimeDelta::FromMilliseconds(download_util::kProgressRateMs), this,
+      &DownloadItemGtk::UpdateDownloadProgress);
+}
+
+void DownloadItemGtk::StopDownloadProgress() {
+  progress_timer_.Stop();
+}
+
+// Icon loading functions.
+
+void DownloadItemGtk::OnLoadSmallIconComplete(IconManager::Handle handle,
+                                              SkBitmap* icon_bitmap) {
+  icon_small_ = icon_bitmap;
+  gtk_widget_queue_draw(progress_area_.get());
+}
+
+void DownloadItemGtk::OnLoadLargeIconComplete(IconManager::Handle handle,
+                                              SkBitmap* icon_bitmap) {
+  icon_large_ = icon_bitmap;
+  DownloadItemDrag::SetSource(body_.get(), get_download(), icon_large_);
+}
+
+void DownloadItemGtk::LoadIcon() {
+  icon_consumer_.CancelAllRequests();
+  IconManager* im = g_browser_process->icon_manager();
+  icon_filepath_ = get_download()->GetUserVerifiedFilePath();
+  im->LoadIcon(icon_filepath_,
+               IconLoader::SMALL, &icon_consumer_,
+               NewCallback(this, &DownloadItemGtk::OnLoadSmallIconComplete));
+  im->LoadIcon(icon_filepath_,
+               IconLoader::LARGE, &icon_consumer_,
+               NewCallback(this, &DownloadItemGtk::OnLoadLargeIconComplete));
+}
+
+void DownloadItemGtk::UpdateTooltip() {
+  string16 elided_filename = ui::ElideFilename(
+      get_download()->GetFileNameToReportUser(),
+      gfx::Font(), kTooltipMaxWidth);
+  gtk_widget_set_tooltip_text(body_.get(),
+                              UTF16ToUTF8(elided_filename).c_str());
+}
+
+void DownloadItemGtk::UpdateNameLabel() {
+  // TODO(estade): This is at best an educated guess, since we don't actually
+  // use gfx::Font() to draw the text. This is why we need to add so
+  // much padding when we set the size request. We need to either use gfx::Font
+  // or somehow extend TextElider.
+  string16 elided_filename = ui::ElideFilename(
+      get_download()->GetFileNameToReportUser(),
+      gfx::Font(), kTextWidth);
+
+  GdkColor color = theme_provider_->GetGdkColor(
+      BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+  gtk_util::SetLabelColor(name_label_, theme_provider_->UseGtkTheme() ?
+                                       NULL : &color);
+  gtk_label_set_text(GTK_LABEL(name_label_),
+                     UTF16ToUTF8(elided_filename).c_str());
+}
+
+void DownloadItemGtk::UpdateStatusLabel(const std::string& status_text) {
+  if (!status_label_)
+    return;
+
+  GdkColor text_color;
+  if (!theme_provider_->UseGtkTheme()) {
+    SkColor color = theme_provider_->GetColor(
+        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+    if (color_utils::RelativeLuminance(color) > 0.5) {
+      color = SkColorSetRGB(
+          static_cast<int>(kDownloadItemLuminanceMod *
+                           SkColorGetR(color)),
+          static_cast<int>(kDownloadItemLuminanceMod *
+                           SkColorGetG(color)),
+          static_cast<int>(kDownloadItemLuminanceMod *
+                           SkColorGetB(color)));
+    }
+
+    // Lighten the color by blending it with the download item body color. These
+    // values are taken from IDR_DOWNLOAD_BUTTON.
+    SkColor blend_color = SkColorSetRGB(241, 245, 250);
+    text_color = gfx::SkColorToGdkColor(
+        color_utils::AlphaBlend(blend_color, color, 77));
+  }
+
+  gtk_util::SetLabelColor(status_label_, theme_provider_->UseGtkTheme() ?
+                                        NULL : &text_color);
+  gtk_label_set_text(GTK_LABEL(status_label_), status_text.c_str());
+}
+
+void DownloadItemGtk::UpdateDangerWarning() {
+  if (dangerous_prompt_) {
+    // We create |dangerous_warning| as a wide string so we can more easily
+    // calculate its length in characters.
+    string16 dangerous_warning;
+    if (get_download()->is_extension_install()) {
+      dangerous_warning =
+          l10n_util::GetStringUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
+    } else {
+      string16 elided_filename = ui::ElideFilename(
+          get_download()->target_name(), gfx::Font(), kTextWidth);
+
+      dangerous_warning =
+          l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
+                                     elided_filename);
+    }
+
+    if (theme_provider_->UseGtkTheme()) {
+      gtk_image_set_from_stock(GTK_IMAGE(dangerous_image_),
+          GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+      gtk_util::SetLabelColor(dangerous_label_, NULL);
+    } else {
+      // Set the warning icon.
+      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+      GdkPixbuf* download_pixbuf = rb.GetPixbufNamed(IDR_WARNING);
+      gtk_image_set_from_pixbuf(GTK_IMAGE(dangerous_image_), download_pixbuf);
+
+      GdkColor color = theme_provider_->GetGdkColor(
+          BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+      gtk_util::SetLabelColor(dangerous_label_, &color);
+    }
+
+    gtk_label_set_text(GTK_LABEL(dangerous_label_),
+                       UTF16ToUTF8(dangerous_warning).c_str());
+
+    // Until we switch to vector graphics, force the font size.
+    gtk_util::ForceFontSizePixels(dangerous_label_, kTextSize);
+
+    // Get the label width when displaying in one line, and reduce it to 60% to
+    // wrap the label into two lines.
+    gtk_widget_set_size_request(dangerous_label_, -1, -1);
+    gtk_label_set_line_wrap(GTK_LABEL(dangerous_label_), FALSE);
+
+    GtkRequisition req;
+    gtk_widget_size_request(dangerous_label_, &req);
+
+    gint label_width = req.width * 6 / 10;
+    gtk_label_set_line_wrap(GTK_LABEL(dangerous_label_), TRUE);
+    gtk_widget_set_size_request(dangerous_label_, label_width, -1);
+
+    // The width will depend on the text. We must do this each time we possibly
+    // change the label above.
+    gtk_widget_size_request(dangerous_hbox_, &req);
+    dangerous_hbox_full_width_ = req.width;
+    dangerous_hbox_start_width_ = dangerous_hbox_full_width_ - label_width;
+  }
+}
+
+// static
+void DownloadItemGtk::InitNineBoxes() {
+  if (body_nine_box_normal_)
+    return;
+
+  body_nine_box_normal_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_LEFT_TOP,
+      IDR_DOWNLOAD_BUTTON_CENTER_TOP,
+      IDR_DOWNLOAD_BUTTON_RIGHT_TOP,
+      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE,
+      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE,
+      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE,
+      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM,
+      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM,
+      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM);
+
+  body_nine_box_prelight_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_LEFT_TOP_H,
+      IDR_DOWNLOAD_BUTTON_CENTER_TOP_H,
+      IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H,
+      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_H,
+      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_H,
+      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_H,
+      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_H,
+      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H,
+      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_H);
+
+  body_nine_box_active_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_LEFT_TOP_P,
+      IDR_DOWNLOAD_BUTTON_CENTER_TOP_P,
+      IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P,
+      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_P,
+      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_P,
+      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_P,
+      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_P,
+      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P,
+      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_P);
+
+  menu_nine_box_normal_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_MENU_TOP, 0, 0,
+      IDR_DOWNLOAD_BUTTON_MENU_MIDDLE, 0, 0,
+      IDR_DOWNLOAD_BUTTON_MENU_BOTTOM, 0, 0);
+
+  menu_nine_box_prelight_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_MENU_TOP_H, 0, 0,
+      IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_H, 0, 0,
+      IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_H, 0, 0);
+
+  menu_nine_box_active_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_MENU_TOP_P, 0, 0,
+      IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P, 0, 0,
+      IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P, 0, 0);
+
+  dangerous_nine_box_ = new NineBox(
+      IDR_DOWNLOAD_BUTTON_LEFT_TOP,
+      IDR_DOWNLOAD_BUTTON_CENTER_TOP,
+      IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD,
+      IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE,
+      IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE,
+      IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD,
+      IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM,
+      IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM,
+      IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD);
+}
+
+gboolean DownloadItemGtk::OnHboxExpose(GtkWidget* widget, GdkEventExpose* e) {
+  if (theme_provider_->UseGtkTheme()) {
+    int border_width = GTK_CONTAINER(widget)->border_width;
+    int x = widget->allocation.x + border_width;
+    int y = widget->allocation.y + border_width;
+    int width = widget->allocation.width - border_width * 2;
+    int height = widget->allocation.height - border_width * 2;
+
+    if (IsDangerous()) {
+      // Draw a simple frame around the area when we're displaying the warning.
+      gtk_paint_shadow(widget->style, widget->window,
+                       static_cast<GtkStateType>(widget->state),
+                       static_cast<GtkShadowType>(GTK_SHADOW_OUT),
+                       &e->area, widget, "frame",
+                       x, y, width, height);
+    } else {
+      // Manually draw the GTK button border around the download item. We draw
+      // the left part of the button (the file), a divider, and then the right
+      // part of the button (the menu). We can't draw a button on top of each
+      // other (*cough*Clearlooks*cough*) so instead, to draw the left part of
+      // the button, we instruct GTK to draw the entire button...with a
+      // doctored clip rectangle to the left part of the button sans
+      // separator. We then repeat this for the right button.
+      GtkStyle* style = body_.get()->style;
+
+      GtkAllocation left_allocation = body_.get()->allocation;
+      GdkRectangle left_clip = {
+        left_allocation.x, left_allocation.y,
+        left_allocation.width, left_allocation.height
+      };
+
+      GtkAllocation right_allocation = menu_button_->allocation;
+      GdkRectangle right_clip = {
+        right_allocation.x, right_allocation.y,
+        right_allocation.width, right_allocation.height
+      };
+
+      GtkShadowType body_shadow =
+          GTK_BUTTON(body_.get())->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+      gtk_paint_box(style, widget->window,
+                    static_cast<GtkStateType>(GTK_WIDGET_STATE(body_.get())),
+                    body_shadow,
+                    &left_clip, widget, "button",
+                    x, y, width, height);
+
+      GtkShadowType menu_shadow =
+          GTK_BUTTON(menu_button_)->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+      gtk_paint_box(style, widget->window,
+                    static_cast<GtkStateType>(GTK_WIDGET_STATE(menu_button_)),
+                    menu_shadow,
+                    &right_clip, widget, "button",
+                    x, y, width, height);
+
+      // Doing the math to reverse engineer where we should be drawing our line
+      // is hard and relies on copying GTK internals, so instead steal the
+      // allocation of the gtk arrow which is close enough (and will error on
+      // the conservative side).
+      GtkAllocation arrow_allocation = arrow_->allocation;
+      gtk_paint_vline(style, widget->window,
+                      static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
+                      &e->area, widget, "button",
+                      arrow_allocation.y,
+                      arrow_allocation.y + arrow_allocation.height,
+                      left_allocation.x + left_allocation.width);
+    }
+  }
+  return FALSE;
+}
+
+gboolean DownloadItemGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e) {
+  if (!theme_provider_->UseGtkTheme()) {
+    bool is_body = widget == body_.get();
+
+    NineBox* nine_box = NULL;
+    // If true, this widget is |body_|, otherwise it is |menu_button_|.
+    if (GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT)
+      nine_box = is_body ? body_nine_box_prelight_ : menu_nine_box_prelight_;
+    else if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE)
+      nine_box = is_body ? body_nine_box_active_ : menu_nine_box_active_;
+    else
+      nine_box = is_body ? body_nine_box_normal_ : menu_nine_box_normal_;
+
+    // When the button is showing, we want to draw it as active. We have to do
+    // this explicitly because the button's state will be NORMAL while the menu
+    // has focus.
+    if (!is_body && menu_showing_)
+      nine_box = menu_nine_box_active_;
+
+    nine_box->RenderToWidget(widget);
+  }
+
+  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
+  if (child)
+    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
+
+  return TRUE;
+}
+
+void DownloadItemGtk::OnClick(GtkWidget* widget) {
+  UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
+                           base::Time::Now() - creation_time_);
+  get_download()->OpenDownload();
+  parent_shelf_->ItemOpened();
+}
+
+gboolean DownloadItemGtk::OnProgressAreaExpose(GtkWidget* widget,
+                                               GdkEventExpose* event) {
+  // Create a transparent canvas.
+  gfx::CanvasSkiaPaint canvas(event, false);
+  if (complete_animation_.get()) {
+    if (complete_animation_->is_animating()) {
+      download_util::PaintDownloadComplete(&canvas,
+          widget->allocation.x, widget->allocation.y,
+          complete_animation_->GetCurrentValue(),
+          download_util::SMALL);
+    }
+  } else if (get_download()->state() !=
+             DownloadItem::CANCELLED) {
+    download_util::PaintDownloadProgress(&canvas,
+        widget->allocation.x, widget->allocation.y,
+        progress_angle_,
+        get_download()->PercentComplete(),
+        download_util::SMALL);
+  }
+
+  // |icon_small_| may be NULL if it is still loading. If the file is an
+  // unrecognized type then we will get back a generic system icon. Hence
+  // there is no need to use the chromium-specific default download item icon.
+  if (icon_small_) {
+    const int offset = download_util::kSmallProgressIconOffset;
+    canvas.DrawBitmapInt(*icon_small_,
+        widget->allocation.x + offset, widget->allocation.y + offset);
+  }
+
+  return TRUE;
+}
+
+gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button,
+                                                 GdkEventButton* event) {
+  // Stop any completion animation.
+  if (complete_animation_.get() && complete_animation_->is_animating())
+    complete_animation_->End();
+
+  if (event->type == GDK_BUTTON_PRESS) {
+    GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
+    if (event_button->button == 1) {
+      if (menu_.get() == NULL) {
+        menu_.reset(new DownloadShelfContextMenuGtk(
+            download_model_.get(), this));
+      }
+      menu_->Popup(button, event);
+      menu_showing_ = true;
+      gtk_widget_queue_draw(button);
+    }
+  }
+
+  return FALSE;
+}
+
+gboolean DownloadItemGtk::OnDangerousPromptExpose(GtkWidget* widget,
+                                                  GdkEventExpose* event) {
+  if (!theme_provider_->UseGtkTheme()) {
+    // The hbox renderer will take care of the border when in GTK mode.
+    dangerous_nine_box_->RenderToWidget(widget);
+  }
+  return FALSE;  // Continue propagation.
+}
+
+void DownloadItemGtk::OnDangerousAccept(GtkWidget* button) {
+  UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download",
+                           base::Time::Now() - creation_time_);
+  get_download()->DangerousDownloadValidated();
+}
+
+void DownloadItemGtk::OnDangerousDecline(GtkWidget* button) {
+  UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download",
+                           base::Time::Now() - creation_time_);
+  if (get_download()->state() == DownloadItem::IN_PROGRESS)
+    get_download()->Cancel(true);
+  get_download()->Remove(true);
+}
diff --git a/chrome/browser/ui/gtk/download_item_gtk.h b/chrome/browser/ui/gtk/download_item_gtk.h
new file mode 100644
index 0000000..d8fd8ae
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_item_gtk.h
@@ -0,0 +1,220 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_DOWNLOAD_ITEM_GTK_H_
+#define CHROME_BROWSER_UI_GTK_DOWNLOAD_ITEM_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "chrome/browser/download/download_item.h"
+#include "chrome/browser/icon_manager.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class BaseDownloadItemModel;
+class DownloadShelfContextMenuGtk;
+class DownloadShelfGtk;
+class GtkThemeProvider;
+class NineBox;
+class SkBitmap;
+
+namespace ui {
+class SlideAnimation;
+}
+
+class DownloadItemGtk : public DownloadItem::Observer,
+                        public ui::AnimationDelegate,
+                        public NotificationObserver {
+ public:
+  // DownloadItemGtk takes ownership of |download_item_model|.
+  DownloadItemGtk(DownloadShelfGtk* parent_shelf,
+                  BaseDownloadItemModel* download_item_model);
+
+  // Destroys all widgets belonging to this DownloadItemGtk.
+  ~DownloadItemGtk();
+
+  // DownloadItem::Observer implementation.
+  virtual void OnDownloadUpdated(DownloadItem* download);
+  virtual void OnDownloadFileCompleted(DownloadItem* download) { }
+  virtual void OnDownloadOpened(DownloadItem* download) { }
+
+  // ui::AnimationDelegate implementation.
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Called when the icon manager has finished loading the icon. We take
+  // ownership of |icon_bitmap|.
+  void OnLoadSmallIconComplete(IconManager::Handle handle,
+                               SkBitmap* icon_bitmap);
+  void OnLoadLargeIconComplete(IconManager::Handle handle,
+                               SkBitmap* icon_bitmap);
+
+  // Returns the DownloadItem model object belonging to this item.
+  DownloadItem* get_download();
+
+ private:
+  friend class DownloadShelfContextMenuGtk;
+
+  // Returns true IFF the download is dangerous and unconfirmed.
+  bool IsDangerous();
+
+  // Functions for controlling the progress animation.
+  // Repaint the download progress.
+  void UpdateDownloadProgress();
+
+  // Starts a repeating timer for UpdateDownloadProgress.
+  void StartDownloadProgress();
+
+  // Stops the repeating timer.
+  void StopDownloadProgress();
+
+  // Ask the icon manager to asynchronously start loading the icon for the file.
+  void LoadIcon();
+
+  // Sets the tooltip on the download button.
+  void UpdateTooltip();
+
+  // Sets the name label to the correct color.
+  void UpdateNameLabel();
+
+  // Sets the text of |status_label_| with the correct color.
+  void UpdateStatusLabel(const std::string& status_text);
+
+  // Sets the components of the danger warning.
+  void UpdateDangerWarning();
+
+  static void InitNineBoxes();
+
+  // Draws everything in GTK rendering mode.
+  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnHboxExpose,
+                       GdkEventExpose*);
+
+  // Used for the download item's body and menu button in chrome theme mode.
+  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnExpose, GdkEventExpose*);
+
+  // Called when |body_| is clicked.
+  CHROMEGTK_CALLBACK_0(DownloadItemGtk, void, OnClick);
+
+  // Used for the download icon.
+  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnProgressAreaExpose,
+                       GdkEventExpose*);
+
+  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnMenuButtonPressEvent,
+                       GdkEventButton*);
+
+  // Dangerous download related. -----------------------------------------------
+  CHROMEGTK_CALLBACK_1(DownloadItemGtk, gboolean, OnDangerousPromptExpose,
+                       GdkEventExpose*);
+  CHROMEGTK_CALLBACK_0(DownloadItemGtk, void, OnDangerousAccept);
+  CHROMEGTK_CALLBACK_0(DownloadItemGtk, void, OnDangerousDecline);
+
+  // Nineboxes for the body area.
+  static NineBox* body_nine_box_normal_;
+  static NineBox* body_nine_box_prelight_;
+  static NineBox* body_nine_box_active_;
+
+  // Nineboxes for the menu button.
+  static NineBox* menu_nine_box_normal_;
+  static NineBox* menu_nine_box_prelight_;
+  static NineBox* menu_nine_box_active_;
+
+  // Ninebox for the background of the dangerous download prompt.
+  static NineBox* dangerous_nine_box_;
+
+  // The shelf on which we are displayed.
+  DownloadShelfGtk* parent_shelf_;
+
+  // The widget that contains the body and menu dropdown.
+  OwnedWidgetGtk hbox_;
+
+  // The widget that contains the name of the download and the progress
+  // animation.
+  OwnedWidgetGtk body_;
+
+  // The GtkLabel that holds the download title text.
+  GtkWidget* name_label_;
+
+  // The GtkLabel that holds the status text.
+  GtkWidget* status_label_;
+
+  // The current text of status label
+  std::string status_text_;
+
+  // The widget that creates a dropdown menu when pressed.
+  GtkWidget* menu_button_;
+
+  // A gtk arrow pointing downward displayed in |menu_button_|. Only displayed
+  // in GTK mode.
+  GtkWidget* arrow_;
+
+  // Whether the menu is currently showing for |menu_button_|. Affects how we
+  // draw the button.
+  bool menu_showing_;
+
+  // Whether we should use the GTK text color
+  GtkThemeProvider* theme_provider_;
+
+  // The widget that contains the animation progress and the file's icon
+  // (as well as the complete animation).
+  OwnedWidgetGtk progress_area_;
+
+  // In degrees. Only used for downloads with no known total size.
+  int progress_angle_;
+
+  // The menu that pops down when the user presses |menu_button_|. We do not
+  // create this until the first time we actually need it.
+  scoped_ptr<DownloadShelfContextMenuGtk> menu_;
+
+  // The download item model we represent.
+  scoped_ptr<BaseDownloadItemModel> download_model_;
+
+  // The dangerous download dialog. This will be null for safe downloads.
+  GtkWidget* dangerous_prompt_;
+  GtkWidget* dangerous_image_;
+  GtkWidget* dangerous_label_;
+
+  // An hbox for holding components of the dangerous download dialog.
+  GtkWidget* dangerous_hbox_;
+  int dangerous_hbox_start_width_;
+  int dangerous_hbox_full_width_;
+
+  // The animation when this item is first added to the shelf.
+  scoped_ptr<ui::SlideAnimation> new_item_animation_;
+
+  // Progress animation.
+  base::RepeatingTimer<DownloadItemGtk> progress_timer_;
+
+  // Animation for download complete.
+  scoped_ptr<ui::SlideAnimation> complete_animation_;
+
+  // The file icon for the download. May be null. The small version is used
+  // for display in the shelf; the large version is for use as a drag icon.
+  SkBitmap* icon_small_;
+  SkBitmap* icon_large_;
+
+  // The last download file path for which we requested an icon.
+  FilePath icon_filepath_;
+
+  NotificationRegistrar registrar_;
+
+  // The time at which we were insantiated.
+  base::Time creation_time_;
+
+  // For canceling an in progress icon request.
+  CancelableRequestConsumerT<int, 0> icon_consumer_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_DOWNLOAD_ITEM_GTK_H_
diff --git a/chrome/browser/ui/gtk/download_shelf_gtk.cc b/chrome/browser/ui/gtk/download_shelf_gtk.cc
new file mode 100644
index 0000000..224d1e7
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_shelf_gtk.cc
@@ -0,0 +1,378 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/download_shelf_gtk.h"
+
+#include <string>
+
+#include "chrome/browser/download/download_item.h"
+#include "chrome/browser/download/download_item_model.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/download_item_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+
+namespace {
+
+// The height of the download items.
+const int kDownloadItemHeight = download_util::kSmallProgressIconSize;
+
+// Padding between the download widgets.
+const int kDownloadItemPadding = 10;
+
+// Padding between the top/bottom of the download widgets and the edge of the
+// shelf.
+const int kTopBottomPadding = 4;
+
+// Padding between the left side of the shelf and the first download item.
+const int kLeftPadding = 2;
+
+// Padding between the right side of the shelf and the close button.
+const int kRightPadding = 10;
+
+// Speed of the shelf show/hide animation.
+const int kShelfAnimationDurationMs = 120;
+
+// The time between when the user mouses out of the download shelf zone and
+// when the shelf closes (when auto-close is enabled).
+const int kAutoCloseDelayMs = 300;
+
+// The area to the top of the shelf that is considered part of its "zone".
+const int kShelfAuraSize = 40;
+
+}  // namespace
+
+DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent)
+    : browser_(browser),
+      is_showing_(false),
+      theme_provider_(GtkThemeProvider::GetFrom(browser->profile())),
+      close_on_mouse_out_(false),
+      mouse_in_shelf_(false),
+      auto_close_factory_(this) {
+  // Logically, the shelf is a vbox that contains two children: a one pixel
+  // tall event box, which serves as the top border, and an hbox, which holds
+  // the download items and other shelf widgets (close button, show-all-
+  // downloads link).
+  // To make things pretty, we have to add a few more widgets. To get padding
+  // right, we stick the hbox in an alignment. We put that alignment in an
+  // event box so we can color the background.
+
+  // Create the top border.
+  top_border_ = gtk_event_box_new();
+  gtk_widget_set_size_request(GTK_WIDGET(top_border_), 0, 1);
+
+  // Create |items_hbox_|. We use GtkChromeShrinkableHBox, so that download
+  // items can be hid automatically when there is no enough space to show them.
+  items_hbox_.Own(gtk_chrome_shrinkable_hbox_new(
+      TRUE, FALSE, kDownloadItemPadding));
+  // We want the download shelf to be horizontally shrinkable, so that the
+  // Chrome window can be resized freely even with many download items.
+  gtk_widget_set_size_request(items_hbox_.get(), 0, kDownloadItemHeight);
+
+  // Create a hbox that holds |items_hbox_| and other shelf widgets.
+  GtkWidget* outer_hbox = gtk_hbox_new(FALSE, kDownloadItemPadding);
+
+  // Pack the |items_hbox_| in the outer hbox.
+  gtk_box_pack_start(GTK_BOX(outer_hbox), items_hbox_.get(), TRUE, TRUE, 0);
+
+  // Get the padding and background color for |outer_hbox| right.
+  GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
+  // Subtract 1 from top spacing to account for top border.
+  gtk_alignment_set_padding(GTK_ALIGNMENT(padding),
+      kTopBottomPadding - 1, kTopBottomPadding, kLeftPadding, kRightPadding);
+  padding_bg_ = gtk_event_box_new();
+  gtk_container_add(GTK_CONTAINER(padding_bg_), padding);
+  gtk_container_add(GTK_CONTAINER(padding), outer_hbox);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), top_border_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), padding_bg_, FALSE, FALSE, 0);
+
+  // Put the shelf in an event box so it gets its own window, which makes it
+  // easier to get z-ordering right.
+  shelf_.Own(gtk_event_box_new());
+  gtk_container_add(GTK_CONTAINER(shelf_.get()), vbox);
+
+  // Create and pack the close button.
+  close_button_.reset(CustomDrawButton::CloseButton(theme_provider_));
+  gtk_util::CenterWidgetInHBox(outer_hbox, close_button_->widget(), true, 0);
+  g_signal_connect(close_button_->widget(), "clicked",
+                   G_CALLBACK(OnButtonClickThunk), this);
+
+  // Create the "Show all downloads..." link and connect to the click event.
+  std::string link_text =
+      l10n_util::GetStringUTF8(IDS_SHOW_ALL_DOWNLOADS);
+  link_button_ = gtk_chrome_link_button_new(link_text.c_str());
+  g_signal_connect(link_button_, "clicked",
+                   G_CALLBACK(OnButtonClickThunk), this);
+  gtk_util::SetButtonTriggersNavigation(link_button_);
+  // Until we switch to vector graphics, force the font size.
+  // 13.4px == 10pt @ 96dpi
+  gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link_button_)->label,
+                                13.4);
+
+  // Make the download arrow icon.
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  GdkPixbuf* download_pixbuf = rb.GetPixbufNamed(IDR_DOWNLOADS_FAVICON);
+  GtkWidget* download_image = gtk_image_new_from_pixbuf(download_pixbuf);
+
+  // Pack the link and the icon in outer hbox.
+  gtk_util::CenterWidgetInHBox(outer_hbox, link_button_, true, 0);
+  gtk_util::CenterWidgetInHBox(outer_hbox, download_image, true, 0);
+
+  slide_widget_.reset(new SlideAnimatorGtk(shelf_.get(),
+                                           SlideAnimatorGtk::UP,
+                                           kShelfAnimationDurationMs,
+                                           false, true, this));
+
+  theme_provider_->InitThemesFor(this);
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+
+  gtk_widget_show_all(shelf_.get());
+
+  // Stick ourselves at the bottom of the parent browser.
+  gtk_box_pack_end(GTK_BOX(parent), slide_widget_->widget(),
+                   FALSE, FALSE, 0);
+  // Make sure we are at the very end.
+  gtk_box_reorder_child(GTK_BOX(parent), slide_widget_->widget(), 0);
+  Show();
+}
+
+DownloadShelfGtk::~DownloadShelfGtk() {
+  for (std::vector<DownloadItemGtk*>::iterator iter = download_items_.begin();
+       iter != download_items_.end(); ++iter) {
+    delete *iter;
+  }
+
+  shelf_.Destroy();
+  items_hbox_.Destroy();
+
+  // Make sure we're no longer an observer of the message loop.
+  SetCloseOnMouseOut(false);
+}
+
+void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) {
+  download_items_.push_back(new DownloadItemGtk(this, download_model_));
+  Show();
+}
+
+bool DownloadShelfGtk::IsShowing() const {
+  return slide_widget_->IsShowing();
+}
+
+bool DownloadShelfGtk::IsClosing() const {
+  return slide_widget_->IsClosing();
+}
+
+void DownloadShelfGtk::Show() {
+  slide_widget_->Open();
+  browser_->UpdateDownloadShelfVisibility(true);
+  CancelAutoClose();
+}
+
+void DownloadShelfGtk::Close() {
+  // When we are closing, we can vertically overlap the render view. Make sure
+  // we are on top.
+  gdk_window_raise(shelf_.get()->window);
+  slide_widget_->Close();
+  browser_->UpdateDownloadShelfVisibility(false);
+  SetCloseOnMouseOut(false);
+}
+
+Browser* DownloadShelfGtk::browser() const {
+  return browser_;
+}
+
+void DownloadShelfGtk::Closed() {
+  // When the close animation is complete, remove all completed downloads.
+  size_t i = 0;
+  while (i < download_items_.size()) {
+    DownloadItem* download = download_items_[i]->get_download();
+    bool is_transfer_done = download->state() == DownloadItem::COMPLETE ||
+                            download->state() == DownloadItem::CANCELLED;
+    if (is_transfer_done &&
+        download->safety_state() != DownloadItem::DANGEROUS) {
+      RemoveDownloadItem(download_items_[i]);
+    } else {
+      // We set all remaining items as "opened", so that the shelf will auto-
+      // close in the future without the user clicking on them.
+      download->set_opened(true);
+      ++i;
+    }
+  }
+}
+
+void DownloadShelfGtk::Observe(NotificationType type,
+                               const NotificationSource& source,
+                               const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    GdkColor color = theme_provider_->GetGdkColor(
+        BrowserThemeProvider::COLOR_TOOLBAR);
+    gtk_widget_modify_bg(padding_bg_, GTK_STATE_NORMAL, &color);
+
+    color = theme_provider_->GetBorderColor();
+    gtk_widget_modify_bg(top_border_, GTK_STATE_NORMAL, &color);
+
+    gtk_chrome_link_button_set_use_gtk_theme(
+        GTK_CHROME_LINK_BUTTON(link_button_), theme_provider_->UseGtkTheme());
+
+    // When using a non-standard, non-gtk theme, we make the link color match
+    // the bookmark text color. Otherwise, standard link blue can look very
+    // bad for some dark themes.
+    bool use_default_color = theme_provider_->GetColor(
+        BrowserThemeProvider::COLOR_BOOKMARK_TEXT) ==
+        BrowserThemeProvider::GetDefaultColor(
+            BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+    GdkColor bookmark_color = theme_provider_->GetGdkColor(
+        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+    gtk_chrome_link_button_set_normal_color(
+        GTK_CHROME_LINK_BUTTON(link_button_),
+        use_default_color ? NULL : &bookmark_color);
+
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    close_button_->SetBackground(
+        theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT),
+        rb.GetBitmapNamed(IDR_CLOSE_BAR),
+        rb.GetBitmapNamed(IDR_CLOSE_BAR_MASK));
+  }
+}
+
+int DownloadShelfGtk::GetHeight() const {
+  return slide_widget_->widget()->allocation.height;
+}
+
+void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) {
+  DCHECK(download_item);
+  std::vector<DownloadItemGtk*>::iterator i =
+      find(download_items_.begin(), download_items_.end(), download_item);
+  DCHECK(i != download_items_.end());
+  download_items_.erase(i);
+  delete download_item;
+  if (download_items_.empty()) {
+    slide_widget_->CloseWithoutAnimation();
+    browser_->UpdateDownloadShelfVisibility(false);
+  } else {
+    AutoCloseIfPossible();
+  }
+}
+
+GtkWidget* DownloadShelfGtk::GetHBox() const {
+  return items_hbox_.get();
+}
+
+void DownloadShelfGtk::MaybeShowMoreDownloadItems() {
+  // Show all existing download items. It'll trigger "size-allocate" signal,
+  // which will hide download items that don't have enough space to show.
+  gtk_widget_show_all(items_hbox_.get());
+}
+
+void DownloadShelfGtk::OnButtonClick(GtkWidget* button) {
+  if (button == close_button_->widget()) {
+    Close();
+  } else {
+    // The link button was clicked.
+    browser_->ShowDownloadsTab();
+  }
+}
+
+void DownloadShelfGtk::AutoCloseIfPossible() {
+  for (std::vector<DownloadItemGtk*>::iterator iter = download_items_.begin();
+       iter != download_items_.end(); ++iter) {
+    if (!(*iter)->get_download()->opened())
+      return;
+  }
+
+  SetCloseOnMouseOut(true);
+}
+
+void DownloadShelfGtk::CancelAutoClose() {
+  SetCloseOnMouseOut(false);
+  auto_close_factory_.RevokeAll();
+}
+
+void DownloadShelfGtk::ItemOpened() {
+  AutoCloseIfPossible();
+}
+
+void DownloadShelfGtk::SetCloseOnMouseOut(bool close) {
+  if (close_on_mouse_out_ == close)
+    return;
+
+  close_on_mouse_out_ = close;
+  mouse_in_shelf_ = close;
+  if (close)
+    MessageLoopForUI::current()->AddObserver(this);
+  else
+    MessageLoopForUI::current()->RemoveObserver(this);
+}
+
+void DownloadShelfGtk::WillProcessEvent(GdkEvent* event) {
+}
+
+void DownloadShelfGtk::DidProcessEvent(GdkEvent* event) {
+  gfx::Point cursor_screen_coords;
+
+  switch (event->type) {
+    case GDK_MOTION_NOTIFY:
+      cursor_screen_coords =
+          gfx::Point(event->motion.x_root, event->motion.y_root);
+      break;
+    case GDK_LEAVE_NOTIFY:
+      cursor_screen_coords =
+          gfx::Point(event->crossing.x_root, event->crossing.y_root);
+      break;
+    default:
+      return;
+  }
+
+  bool mouse_in_shelf = IsCursorInShelfZone(cursor_screen_coords);
+  if (mouse_in_shelf == mouse_in_shelf_)
+    return;
+  mouse_in_shelf_ = mouse_in_shelf;
+
+  if (mouse_in_shelf)
+    MouseEnteredShelf();
+  else
+    MouseLeftShelf();
+}
+
+bool DownloadShelfGtk::IsCursorInShelfZone(
+    const gfx::Point& cursor_screen_coords) {
+  gfx::Rect bounds(gtk_util::GetWidgetScreenPosition(shelf_.get()),
+                   gfx::Size(shelf_.get()->allocation.width,
+                             shelf_.get()->allocation.height));
+
+  // Negative insets expand the rectangle. We only expand the top.
+  bounds.Inset(gfx::Insets(-kShelfAuraSize, 0, 0, 0));
+
+  return bounds.Contains(cursor_screen_coords);
+}
+
+void DownloadShelfGtk::MouseLeftShelf() {
+  DCHECK(close_on_mouse_out_);
+
+  MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      auto_close_factory_.NewRunnableMethod(&DownloadShelfGtk::Close),
+      kAutoCloseDelayMs);
+}
+
+void DownloadShelfGtk::MouseEnteredShelf() {
+  auto_close_factory_.RevokeAll();
+}
diff --git a/chrome/browser/ui/gtk/download_shelf_gtk.h b/chrome/browser/ui/gtk/download_shelf_gtk.h
new file mode 100644
index 0000000..384943e
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_shelf_gtk.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_DOWNLOAD_SHELF_GTK_H_
+#define CHROME_BROWSER_UI_GTK_DOWNLOAD_SHELF_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/download/download_shelf.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/native_widget_types.h"
+
+class BaseDownloadItemModel;
+class Browser;
+class CustomDrawButton;
+class DownloadItemGtk;
+class GtkThemeProvider;
+class SlideAnimatorGtk;
+
+namespace gfx {
+class Point;
+}
+
+class DownloadShelfGtk : public DownloadShelf,
+                         public NotificationObserver,
+                         public SlideAnimatorGtk::Delegate,
+                         public MessageLoopForUI::Observer {
+ public:
+  explicit DownloadShelfGtk(Browser* browser, gfx::NativeView view);
+
+  ~DownloadShelfGtk();
+
+  // DownloadShelf implementation.
+  virtual void AddDownload(BaseDownloadItemModel* download_model);
+  virtual bool IsShowing() const;
+  virtual bool IsClosing() const;
+  virtual void Show();
+  virtual void Close();
+  virtual Browser* browser() const;
+
+  // SlideAnimatorGtk::Delegate implementation.
+  virtual void Closed();
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Returns the current height of the shelf.
+  int GetHeight() const;
+
+  // MessageLoop::Observer implementation:
+  virtual void WillProcessEvent(GdkEvent* event);
+  virtual void DidProcessEvent(GdkEvent* event);
+
+ private:
+  // Remove |download_item| from the download shelf and delete it.
+  void RemoveDownloadItem(DownloadItemGtk* download_item);
+
+  // Get the hbox download items ought to pack themselves into.
+  GtkWidget* GetHBox() const;
+
+  // Show more hidden download items if there is enough space in the shelf.
+  // It's called when a download item is removed from the shelf or an item's
+  // size is changed.
+  void MaybeShowMoreDownloadItems();
+
+  // Checks that all download items have been opened, and sets the auto-close
+  // state of the shelf if so.
+  void AutoCloseIfPossible();
+
+  // Cancels the auto-close state set by AutoCloseIfPossible, including any
+  // pending close tasks that have already been posted.
+  void CancelAutoClose();
+
+  // A download item has been opened. It might be possible to automatically
+  // close now.
+  void ItemOpened();
+
+  // Sets whether the shelf should automatically close.
+  void SetCloseOnMouseOut(bool close);
+
+  // Returns whether the given point is within the "zone" of the shelf, which is
+  // the shelf and a band of 40 pixels on the top of it.
+  bool IsCursorInShelfZone(const gfx::Point& cursor_screen_coords);
+
+  // Synthesized enter-notify and leave-notify events for the shelf's "zone".
+  void MouseLeftShelf();
+  void MouseEnteredShelf();
+
+  CHROMEGTK_CALLBACK_0(DownloadShelfGtk, void, OnButtonClick);
+
+  // The browser that owns this download shelf.
+  Browser* browser_;
+
+  // The top level widget of the shelf.
+  scoped_ptr<SlideAnimatorGtk> slide_widget_;
+
+  // |items_hbox_| holds the download items.
+  OwnedWidgetGtk items_hbox_;
+
+  // |shelf_| is the second highest level widget. See the constructor
+  // for an explanation of the widget layout.
+  OwnedWidgetGtk shelf_;
+
+  // Top level event box which draws the one pixel border.
+  GtkWidget* top_border_;
+
+  // A GtkEventBox which we color.
+  GtkWidget* padding_bg_;
+
+  // The "Show all downloads..." link.
+  GtkWidget* link_button_;
+
+  // The 'x' that the user can press to hide the download shelf.
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  // Keeps track of our current hide/show state.
+  bool is_showing_;
+
+  // The download items we have added to our shelf.
+  std::vector<DownloadItemGtk*> download_items_;
+
+  // Gives us our colors and theme information.
+  GtkThemeProvider* theme_provider_;
+
+  NotificationRegistrar registrar_;
+
+  // True if the shelf will automatically close when the user mouses out.
+  bool close_on_mouse_out_;
+
+  // True if the mouse is within the shelf's bounds, as of the last mouse event
+  // we received.
+  bool mouse_in_shelf_;
+
+  ScopedRunnableMethodFactory<DownloadShelfGtk> auto_close_factory_;
+
+  friend class DownloadItemGtk;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_DOWNLOAD_SHELF_GTK_H_
diff --git a/chrome/browser/ui/gtk/download_started_animation_gtk.cc b/chrome/browser/ui/gtk/download_started_animation_gtk.cc
new file mode 100644
index 0000000..e806316
--- /dev/null
+++ b/chrome/browser/ui/gtk/download_started_animation_gtk.cc
@@ -0,0 +1,194 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/download/download_started_animation.h"
+
+#include <gtk/gtk.h>
+
+#include "base/message_loop.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "grit/theme_resources.h"
+#include "ui/base/animation/linear_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/rect.h"
+
+namespace {
+
+// How long to spend moving downwards and fading out after waiting.
+const int kMoveTimeMs = 600;
+
+// The animation framerate.
+const int kFrameRateHz = 60;
+
+// What fraction of the frame height to move downward from the frame center.
+// Note that setting this greater than 0.5 will mean moving past the bottom of
+// the frame.
+const double kMoveFraction = 1.0 / 3.0;
+
+class DownloadStartedAnimationGtk : public ui::LinearAnimation,
+                                    public NotificationObserver {
+ public:
+  explicit DownloadStartedAnimationGtk(TabContents* tab_contents);
+
+  // DownloadStartedAnimation will delete itself, but this is public so
+  // that we can use DeleteSoon().
+  virtual ~DownloadStartedAnimationGtk();
+
+ private:
+  // Move the arrow to wherever it should currently be.
+  void Reposition();
+
+  // Shut down cleanly.
+  void Close();
+
+  // Animation implementation.
+  virtual void AnimateToState(double state);
+
+  // NotificationObserver
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // The top level window that floats over the browser and displays the
+  // image.
+  GtkWidget* popup_;
+
+  // Dimensions of the image.
+  int width_;
+  int height_;
+
+  // The content area holding us.
+  TabContents* tab_contents_;
+
+  // The content area at the start of the animation. We store this so that the
+  // download shelf's resizing of the content area doesn't cause the animation
+  // to move around. This means that once started, the animation won't move
+  // with the parent window, but it's so fast that this shouldn't cause too
+  // much heartbreak.
+  gfx::Rect tab_contents_bounds_;
+
+  // A scoped container for notification registries.
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadStartedAnimationGtk);
+};
+
+DownloadStartedAnimationGtk::DownloadStartedAnimationGtk(
+    TabContents* tab_contents)
+    : ui::LinearAnimation(kMoveTimeMs, kFrameRateHz, NULL),
+      tab_contents_(tab_contents) {
+  static GdkPixbuf* kDownloadImage = NULL;
+  if (!kDownloadImage) {
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    kDownloadImage = rb.GetPixbufNamed(IDR_DOWNLOAD_ANIMATION_BEGIN);
+  }
+
+  width_ = gdk_pixbuf_get_width(kDownloadImage);
+  height_ = gdk_pixbuf_get_height(kDownloadImage);
+
+  // If we're too small to show the download image, then don't bother -
+  // the shelf will be enough.
+  tab_contents_->GetContainerBounds(&tab_contents_bounds_);
+  if (tab_contents_bounds_.height() < height_)
+    return;
+
+  registrar_.Add(
+      this,
+      NotificationType::TAB_CONTENTS_HIDDEN,
+      Source<TabContents>(tab_contents_));
+  registrar_.Add(
+      this,
+      NotificationType::TAB_CONTENTS_DESTROYED,
+      Source<TabContents>(tab_contents_));
+
+  // TODO(estade): don't show up on the wrong virtual desktop.
+
+  popup_ = gtk_window_new(GTK_WINDOW_POPUP);
+  GtkWidget* image = gtk_image_new_from_pixbuf(kDownloadImage);
+  gtk_container_add(GTK_CONTAINER(popup_), image);
+
+  // Set the shape of the window to that of the arrow. Areas with
+  // opacity less than 0xff (i.e. <100% opacity) will be transparent.
+  GdkBitmap* mask = gdk_pixmap_new(NULL, width_, height_, 1);
+  gdk_pixbuf_render_threshold_alpha(kDownloadImage, mask,
+                                    0, 0,
+                                    0, 0, -1, -1,
+                                    0xff);
+  gtk_widget_shape_combine_mask(popup_, mask, 0, 0);
+  g_object_unref(mask);
+
+  Reposition();
+  gtk_widget_show_all(popup_);
+  // Make sure our window has focus, is brought to the top, etc.
+  gtk_window_present(GTK_WINDOW(popup_));
+
+  Start();
+}
+
+DownloadStartedAnimationGtk::~DownloadStartedAnimationGtk() {
+}
+
+void DownloadStartedAnimationGtk::Reposition() {
+  if (!tab_contents_)
+    return;
+
+  // Align the image with the bottom left of the web contents (so that it
+  // points to the newly created download).
+  gtk_window_move(GTK_WINDOW(popup_),
+      tab_contents_bounds_.x(),
+      static_cast<int>(tab_contents_bounds_.bottom() -
+          height_ - height_ * (1 - GetCurrentValue())));
+}
+
+void DownloadStartedAnimationGtk::Close() {
+  if (!tab_contents_)
+    return;
+
+  registrar_.Remove(
+      this,
+      NotificationType::TAB_CONTENTS_HIDDEN,
+      Source<TabContents>(tab_contents_));
+  registrar_.Remove(
+      this,
+      NotificationType::TAB_CONTENTS_DESTROYED,
+      Source<TabContents>(tab_contents_));
+
+  tab_contents_ = NULL;
+  gtk_widget_destroy(popup_);
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void DownloadStartedAnimationGtk::AnimateToState(double state) {
+  if (!tab_contents_)
+    return;
+
+  if (state >= 1.0) {
+    Close();
+  } else {
+    Reposition();
+
+    // Start at zero, peak halfway and end at zero.
+    double opacity = std::min(1.0 - pow(GetCurrentValue() - 0.5, 2) * 4.0,
+                              static_cast<double>(1.0));
+
+    // This only works when there's a compositing manager running. Oh well.
+    gtk_window_set_opacity(GTK_WINDOW(popup_), opacity);
+  }
+}
+
+void DownloadStartedAnimationGtk::Observe(NotificationType type,
+                                          const NotificationSource& source,
+                                          const NotificationDetails& details) {
+  Close();
+}
+
+}  // namespace
+
+// static
+void DownloadStartedAnimation::Show(TabContents* tab_contents) {
+  // The animation will delete itself.
+  new DownloadStartedAnimationGtk(tab_contents);
+}
diff --git a/chrome/browser/ui/gtk/edit_search_engine_dialog.cc b/chrome/browser/ui/gtk/edit_search_engine_dialog.cc
new file mode 100644
index 0000000..b7a7d8f
--- /dev/null
+++ b/chrome/browser/ui/gtk/edit_search_engine_dialog.cc
@@ -0,0 +1,291 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/edit_search_engine_dialog.h"
+
+#include <gtk/gtk.h>
+
+#include "base/i18n/rtl.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/edit_search_engine_controller.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "googleurl/src/gurl.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+std::string GetDisplayURL(const TemplateURL& turl) {
+  return turl.url() ? UTF16ToUTF8(turl.url()->DisplayURL()) : std::string();
+}
+
+// Forces text to lowercase when connected to an editable's "insert-text"
+// signal.  (Like views Textfield::STYLE_LOWERCASE.)
+void LowercaseInsertTextHandler(GtkEditable *editable, const gchar *text,
+                                gint length, gint *position, gpointer data) {
+  string16 original_text = UTF8ToUTF16(text);
+  string16 lower_text = l10n_util::ToLower(original_text);
+  if (lower_text != original_text) {
+    std::string result = UTF16ToUTF8(lower_text);
+    // Prevent ourselves getting called recursively about our own edit.
+    g_signal_handlers_block_by_func(G_OBJECT(editable),
+        reinterpret_cast<gpointer>(LowercaseInsertTextHandler), data);
+    gtk_editable_insert_text(editable, result.c_str(), result.size(), position);
+    g_signal_handlers_unblock_by_func(G_OBJECT(editable),
+        reinterpret_cast<gpointer>(LowercaseInsertTextHandler), data);
+    // We've inserted our modified version, stop the defalut handler from
+    // inserting the original.
+    g_signal_stop_emission_by_name(G_OBJECT(editable), "insert_text");
+  }
+}
+
+void SetWidgetStyle(GtkWidget* entry, GtkStyle* label_style,
+                    GtkStyle* dialog_style) {
+  gtk_widget_modify_fg(entry, GTK_STATE_NORMAL,
+                       &label_style->fg[GTK_STATE_NORMAL]);
+  gtk_widget_modify_fg(entry, GTK_STATE_INSENSITIVE,
+                       &label_style->fg[GTK_STATE_INSENSITIVE]);
+  // GTK_NO_WINDOW widgets like GtkLabel don't draw their own background, so we
+  // combine the normal or insensitive foreground of the label style with the
+  // normal background of the window style to achieve the "normal label" and
+  // "insensitive label" colors.
+  gtk_widget_modify_base(entry, GTK_STATE_NORMAL,
+                         &dialog_style->bg[GTK_STATE_NORMAL]);
+  gtk_widget_modify_base(entry, GTK_STATE_INSENSITIVE,
+                         &dialog_style->bg[GTK_STATE_NORMAL]);
+}
+
+}  // namespace
+
+EditSearchEngineDialog::EditSearchEngineDialog(
+    GtkWindow* parent_window,
+    const TemplateURL* template_url,
+    EditSearchEngineControllerDelegate* delegate,
+    Profile* profile)
+    : controller_(new EditSearchEngineController(template_url, delegate,
+                                                 profile)) {
+  Init(parent_window, profile);
+}
+
+EditSearchEngineDialog::~EditSearchEngineDialog() {}
+
+void EditSearchEngineDialog::Init(GtkWindow* parent_window, Profile* profile) {
+  std::string dialog_name = l10n_util::GetStringUTF8(
+      controller_->template_url() ?
+      IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE :
+      IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE);
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      parent_window,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_CANCEL,
+      NULL);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  ok_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
+                                     controller_->template_url() ?
+                                     GTK_STOCK_SAVE :
+                                     GTK_STOCK_ADD,
+                                     GTK_RESPONSE_OK);
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
+
+  // The dialog layout hierarchy looks like this:
+  //
+  // \ GtkVBox |dialog_->vbox|
+  // +-\ GtkTable |controls|
+  // | +-\ row 0
+  // | | +- GtkLabel
+  // | | +-\ GtkHBox
+  // | |   +- GtkEntry |title_entry_|
+  // | |   +- GtkImage |title_image_|
+  // | +-\ row 1
+  // | | +- GtkLabel
+  // | | +-\ GtkHBox
+  // | |   +- GtkEntry |keyword_entry_|
+  // | |   +- GtkImage |keyword_image_|
+  // | +-\ row 2
+  // |   +- GtkLabel
+  // |   +-\ GtkHBox
+  // |     +- GtkEntry |url_entry_|
+  // |     +- GtkImage |url_image_|
+  // +- GtkLabel |description_label|
+
+  title_entry_ = gtk_entry_new();
+  gtk_entry_set_activates_default(GTK_ENTRY(title_entry_), TRUE);
+  g_signal_connect(title_entry_, "changed",
+                   G_CALLBACK(OnEntryChangedThunk), this);
+  accessible_widget_helper_->SetWidgetName(
+      title_entry_,
+      IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL);
+
+  keyword_entry_ = gtk_entry_new();
+  gtk_entry_set_activates_default(GTK_ENTRY(keyword_entry_), TRUE);
+  g_signal_connect(keyword_entry_, "changed",
+                   G_CALLBACK(OnEntryChangedThunk), this);
+  g_signal_connect(keyword_entry_, "insert-text",
+                   G_CALLBACK(LowercaseInsertTextHandler), NULL);
+  accessible_widget_helper_->SetWidgetName(
+      keyword_entry_,
+      IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL);
+
+  url_entry_ = gtk_entry_new();
+  gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
+  g_signal_connect(url_entry_, "changed",
+                   G_CALLBACK(OnEntryChangedThunk), this);
+  accessible_widget_helper_->SetWidgetName(
+      url_entry_,
+      IDS_SEARCH_ENGINES_EDITOR_URL_LABEL);
+
+  title_image_ = gtk_image_new_from_pixbuf(NULL);
+  keyword_image_ = gtk_image_new_from_pixbuf(NULL);
+  url_image_ = gtk_image_new_from_pixbuf(NULL);
+
+  if (controller_->template_url()) {
+    gtk_entry_set_text(
+        GTK_ENTRY(title_entry_),
+        UTF16ToUTF8(controller_->template_url()->short_name()).c_str());
+    gtk_entry_set_text(
+        GTK_ENTRY(keyword_entry_),
+        UTF16ToUTF8(controller_->template_url()->keyword()).c_str());
+    gtk_entry_set_text(
+        GTK_ENTRY(url_entry_),
+        GetDisplayURL(*controller_->template_url()).c_str());
+    // We don't allow users to edit prepopulated URLs.
+    gtk_editable_set_editable(
+        GTK_EDITABLE(url_entry_),
+        controller_->template_url()->prepopulate_id() == 0);
+
+    if (controller_->template_url()->prepopulate_id() != 0) {
+      GtkWidget* fake_label = gtk_label_new("Fake label");
+      gtk_widget_set_sensitive(fake_label,
+          controller_->template_url()->prepopulate_id() == 0);
+      GtkStyle* label_style = gtk_widget_get_style(fake_label);
+      GtkStyle* dialog_style = gtk_widget_get_style(dialog_);
+      SetWidgetStyle(url_entry_, label_style, dialog_style);
+      gtk_widget_destroy(fake_label);
+    }
+  }
+
+  GtkWidget* controls = gtk_util::CreateLabeledControlsGroup(NULL,
+      l10n_util::GetStringUTF8(
+          IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL).c_str(),
+      gtk_util::CreateEntryImageHBox(title_entry_, title_image_),
+      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL).c_str(),
+      gtk_util::CreateEntryImageHBox(keyword_entry_, keyword_image_),
+      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_URL_LABEL).c_str(),
+      gtk_util::CreateEntryImageHBox(url_entry_, url_image_),
+      NULL);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), controls,
+                     FALSE, FALSE, 0);
+
+  // On RTL UIs (such as Arabic and Hebrew) the description text is not
+  // displayed correctly since it contains the substring "%s". This substring
+  // is not interpreted by the Unicode BiDi algorithm as an LTR string and
+  // therefore the end result is that the following right to left text is
+  // displayed: ".three two s% one" (where 'one', 'two', etc. are words in
+  // Hebrew).
+  //
+  // In order to fix this problem we transform the substring "%s" so that it
+  // is displayed correctly when rendered in an RTL context.
+  std::string description =
+      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_URL_DESCRIPTION_LABEL);
+  if (base::i18n::IsRTL()) {
+    const std::string reversed_percent("s%");
+    std::string::size_type percent_index = description.find("%s");
+    if (percent_index != std::string::npos) {
+      description.replace(percent_index,
+                          reversed_percent.length(),
+                          reversed_percent);
+    }
+  }
+
+  GtkWidget* description_label = gtk_label_new(description.c_str());
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), description_label,
+                     FALSE, FALSE, 0);
+
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  EnableControls();
+
+  gtk_util::ShowDialog(dialog_);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+string16 EditSearchEngineDialog::GetTitleInput() const {
+  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(title_entry_)));
+}
+
+string16 EditSearchEngineDialog::GetKeywordInput() const {
+  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(keyword_entry_)));
+}
+
+std::string EditSearchEngineDialog::GetURLInput() const {
+  return gtk_entry_get_text(GTK_ENTRY(url_entry_));
+}
+
+void EditSearchEngineDialog::EnableControls() {
+  gtk_widget_set_sensitive(ok_button_,
+                           controller_->IsKeywordValid(GetKeywordInput()) &&
+                           controller_->IsTitleValid(GetTitleInput()) &&
+                           controller_->IsURLValid(GetURLInput()));
+  UpdateImage(keyword_image_, controller_->IsKeywordValid(GetKeywordInput()),
+              IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT);
+  UpdateImage(url_image_, controller_->IsURLValid(GetURLInput()),
+              IDS_SEARCH_ENGINES_INVALID_URL_TT);
+  UpdateImage(title_image_, controller_->IsTitleValid(GetTitleInput()),
+              IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
+}
+
+void EditSearchEngineDialog::UpdateImage(GtkWidget* image,
+                                         bool is_valid,
+                                         int invalid_message_id) {
+  if (is_valid) {
+    gtk_widget_set_has_tooltip(image, FALSE);
+    gtk_image_set_from_pixbuf(GTK_IMAGE(image),
+        ResourceBundle::GetSharedInstance().GetPixbufNamed(
+            IDR_INPUT_GOOD));
+  } else {
+    gtk_widget_set_tooltip_text(
+        image, l10n_util::GetStringUTF8(invalid_message_id).c_str());
+    gtk_image_set_from_pixbuf(GTK_IMAGE(image),
+        ResourceBundle::GetSharedInstance().GetPixbufNamed(
+            IDR_INPUT_ALERT));
+  }
+}
+
+void EditSearchEngineDialog::OnEntryChanged(GtkEditable* editable) {
+  EnableControls();
+}
+
+void EditSearchEngineDialog::OnResponse(GtkDialog* dialog, int response_id) {
+  if (response_id == GTK_RESPONSE_OK) {
+    controller_->AcceptAddOrEdit(GetTitleInput(),
+                                 GetKeywordInput(),
+                                 GetURLInput());
+  } else {
+    controller_->CleanUpCancelledAdd();
+  }
+  gtk_widget_destroy(dialog_);
+}
+
+void EditSearchEngineDialog::OnWindowDestroy(GtkWidget* widget) {
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
diff --git a/chrome/browser/ui/gtk/edit_search_engine_dialog.h b/chrome/browser/ui/gtk/edit_search_engine_dialog.h
new file mode 100644
index 0000000..a5520e1
--- /dev/null
+++ b/chrome/browser/ui/gtk/edit_search_engine_dialog.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_EDIT_SEARCH_ENGINE_DIALOG_H_
+#define CHROME_BROWSER_UI_GTK_EDIT_SEARCH_ENGINE_DIALOG_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class AccessibleWidgetHelper;
+class EditSearchEngineController;
+class EditSearchEngineControllerDelegate;
+class Profile;
+class TemplateURL;
+
+class EditSearchEngineDialog {
+ public:
+  EditSearchEngineDialog(GtkWindow* parent_window,
+                         const TemplateURL* template_url,
+                         EditSearchEngineControllerDelegate* delegate,
+                         Profile* profile);
+  virtual ~EditSearchEngineDialog();
+
+ private:
+  // Create and show the window.
+  void Init(GtkWindow* parent_window, Profile* profile);
+
+  // Retrieve the user input in the various fields.
+  string16 GetTitleInput() const;
+  string16 GetKeywordInput() const;
+  std::string GetURLInput() const;
+
+  // Set sensitivity of buttons based on entry state.
+  void EnableControls();
+
+  // Updates the tooltip and image of the image view based on is_valid. If
+  // is_valid is false the tooltip of the image view is set to the message with
+  // id invalid_message_id, otherwise the tooltip is set to the empty text.
+  void UpdateImage(GtkWidget* image, bool is_valid, int invalid_message_id);
+
+  // Callback for entry changes.
+  CHROMEG_CALLBACK_0(EditSearchEngineDialog, void, OnEntryChanged,
+                     GtkEditable*);
+
+  // Callback for dialog buttons.
+  CHROMEG_CALLBACK_1(EditSearchEngineDialog, void, OnResponse, GtkDialog*, int);
+
+  // Callback for window destruction.
+  CHROMEGTK_CALLBACK_0(EditSearchEngineDialog, void, OnWindowDestroy);
+
+  // The dialog window.
+  GtkWidget* dialog_;
+
+  // Text entries for each field.
+  GtkWidget* title_entry_;
+  GtkWidget* keyword_entry_;
+  GtkWidget* url_entry_;
+
+  // Images showing whether each entry is okay or has errors.
+  GtkWidget* title_image_;
+  GtkWidget* keyword_image_;
+  GtkWidget* url_image_;
+
+  // The ok button (we need a reference to it so we can de-activate it when the
+  // entries are not all filled in.)
+  GtkWidget* ok_button_;
+
+  scoped_ptr<EditSearchEngineController> controller_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(EditSearchEngineDialog);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_EDIT_SEARCH_ENGINE_DIALOG_H_
diff --git a/chrome/browser/ui/gtk/extension_infobar_gtk.cc b/chrome/browser/ui/gtk/extension_infobar_gtk.cc
new file mode 100644
index 0000000..aa2053e
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_infobar_gtk.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/extension_infobar_gtk.h"
+
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_icon_set.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+
+ExtensionInfoBarGtk::ExtensionInfoBarGtk(ExtensionInfoBarDelegate* delegate)
+    : InfoBar(delegate),
+      tracker_(this),
+      delegate_(delegate),
+      view_(NULL) {
+  delegate_->extension_host()->view()->SetContainer(this);
+  BuildWidgets();
+}
+
+ExtensionInfoBarGtk::~ExtensionInfoBarGtk() {
+  // This view is not owned by us, so unparent.
+  gtk_widget_unparent(view_->native_view());
+}
+
+void ExtensionInfoBarGtk::OnImageLoaded(
+    SkBitmap* image, ExtensionResource resource, int index) {
+  if (!delegate_)
+    return;  // The delegate can go away while we asynchronously load images.
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+  SkBitmap* icon;
+  if (!image || image->empty())
+    icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
+  else
+    icon = image;
+
+  // TODO(finnur): We now have the icon for the menu button, show the menu
+  // button and layout.
+}
+
+void ExtensionInfoBarGtk::BuildWidgets() {
+  // Start loading the image for the menu button.
+  const Extension* extension = delegate_->extension_host()->extension();
+  ExtensionResource icon_resource = extension->GetIconResource(
+      Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY);
+  if (!icon_resource.relative_path().empty()) {
+    // Create a tracker to load the image. It will report back on OnImageLoaded.
+    tracker_.LoadImage(extension, icon_resource,
+                       gfx::Size(Extension::EXTENSION_ICON_BITTY,
+                                 Extension::EXTENSION_ICON_BITTY),
+                       ImageLoadingTracker::DONT_CACHE);
+  } else {
+    OnImageLoaded(NULL, icon_resource, 0);  // |image|, |index|.
+  }
+
+  ExtensionHost* extension_host = delegate_->extension_host();
+  view_ = extension_host->view();
+  if (gtk_widget_get_parent(view_->native_view())) {
+    gtk_widget_reparent(view_->native_view(), hbox_);
+    gtk_box_set_child_packing(GTK_BOX(hbox_), view_->native_view(),
+                              TRUE, TRUE, 0, GTK_PACK_START);
+  } else {
+    gtk_box_pack_start(GTK_BOX(hbox_), view_->native_view(), TRUE, TRUE, 0);
+  }
+
+  g_signal_connect(view_->native_view(), "size_allocate",
+                   G_CALLBACK(&OnSizeAllocateThunk), this);
+}
+
+void ExtensionInfoBarGtk::OnSizeAllocate(GtkWidget* widget,
+                                         GtkAllocation* allocation) {
+  gfx::Size new_size(allocation->width, allocation->height);
+
+  delegate_->extension_host()->view()->render_view_host()->view()
+      ->SetSize(new_size);
+}
+
+void ExtensionInfoBarGtk::OnExtensionPreferredSizeChanged(
+    ExtensionViewGtk* view,
+    const gfx::Size& new_size) {
+  // TODO(rafaelw) - Size the InfobarGtk vertically based on the preferred size
+  // of the content.
+}
+
+InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() {
+  return new ExtensionInfoBarGtk(this);
+}
diff --git a/chrome/browser/ui/gtk/extension_infobar_gtk.h b/chrome/browser/ui/gtk/extension_infobar_gtk.h
new file mode 100644
index 0000000..760c4e8
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_infobar_gtk.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_EXTENSION_INFOBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_EXTENSION_INFOBAR_GTK_H_
+#pragma once
+
+#include "chrome/browser/extensions/extension_infobar_delegate.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/ui/gtk/extension_view_gtk.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
+#include "ui/gfx/gtk_util.h"
+
+class ExtensionInfobarDelegate;
+class ExtensionResource;
+class ExtensionViewGtk;
+
+class ExtensionInfoBarGtk : public InfoBar,
+                            public ImageLoadingTracker::Observer,
+                            public ExtensionViewGtk::Container {
+ public:
+  explicit ExtensionInfoBarGtk(ExtensionInfoBarDelegate* delegate);
+  virtual ~ExtensionInfoBarGtk();
+
+  // Overridden from ImageLoadingTracker::Observer:
+  virtual void OnImageLoaded(
+      SkBitmap* image, ExtensionResource resource, int index);
+
+  // ExtensionViewGtk::Container implementation
+  virtual void OnExtensionPreferredSizeChanged(ExtensionViewGtk* view,
+                                               const gfx::Size& new_size);
+
+ private:
+  // Build the widgets of the Infobar.
+  void BuildWidgets();
+
+  CHROMEGTK_CALLBACK_1(ExtensionInfoBarGtk, void, OnSizeAllocate,
+                       GtkAllocation*);
+
+  ImageLoadingTracker tracker_;
+
+  ExtensionInfoBarDelegate* delegate_;
+
+  ExtensionViewGtk* view_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionInfoBarGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_EXTENSION_INFOBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/extension_install_prompt2_gtk.cc b/chrome/browser/ui/gtk/extension_install_prompt2_gtk.cc
new file mode 100644
index 0000000..f2cda7d
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_install_prompt2_gtk.cc
@@ -0,0 +1,191 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtk/gtk.h>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/generated_resources.h"
+#include "skia/ext/image_operations.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+class Profile;
+
+namespace {
+
+const int kRightColumnMinWidth = 290;
+
+const int kImageSize = 69;
+
+// Padding on all sides of each permission in the permissions list.
+const int kPermissionsPadding = 8;
+
+// Make a GtkLabel with |str| as its text, using the formatting in |format|.
+GtkWidget* MakeMarkupLabel(const char* format, const std::string& str) {
+  GtkWidget* label = gtk_label_new(NULL);
+  char* markup = g_markup_printf_escaped(format, str.c_str());
+  gtk_label_set_markup(GTK_LABEL(label), markup);
+  g_free(markup);
+
+  // Left align it.
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+
+  return label;
+}
+
+void OnDialogResponse(GtkDialog* dialog, int response_id,
+                      ExtensionInstallUI::Delegate* delegate) {
+  if (response_id == GTK_RESPONSE_ACCEPT) {
+    delegate->InstallUIProceed();
+  } else {
+    delegate->InstallUIAbort();
+  }
+
+  gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+void ShowInstallPromptDialog2(GtkWindow* parent, SkBitmap* skia_icon,
+                              const Extension* extension,
+                              ExtensionInstallUI::Delegate *delegate,
+                              const std::vector<string16>& permissions) {
+  // Build the dialog.
+  GtkWidget* dialog = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALL_PROMPT_TITLE).c_str(),
+      parent,
+      GTK_DIALOG_MODAL,
+      NULL);
+  GtkWidget* close_button = gtk_dialog_add_button(GTK_DIALOG(dialog),
+      GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE);
+  gtk_dialog_add_button(GTK_DIALOG(dialog),
+      l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_INSTALL_BUTTON).c_str(),
+      GTK_RESPONSE_ACCEPT);
+  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+
+  // Create a two column layout.
+  GtkWidget* content_area = GTK_DIALOG(dialog)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* icon_hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_box_pack_start(GTK_BOX(content_area), icon_hbox, TRUE, TRUE, 0);
+
+  // Resize the icon if necessary.
+  SkBitmap scaled_icon = *skia_icon;
+  if (scaled_icon.width() > kImageSize || scaled_icon.height() > kImageSize) {
+    scaled_icon = skia::ImageOperations::Resize(scaled_icon,
+        skia::ImageOperations::RESIZE_LANCZOS3,
+        kImageSize, kImageSize);
+  }
+
+  // Put Icon in the left column.
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&scaled_icon);
+  GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf);
+  g_object_unref(pixbuf);
+  gtk_box_pack_start(GTK_BOX(icon_hbox), icon, FALSE, FALSE, 0);
+  // Top justify the image.
+  gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
+
+  // Create a new vbox for the right column.
+  GtkWidget* right_column_area = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(icon_hbox), right_column_area, TRUE, TRUE, 0);
+
+  std::string heading_text = l10n_util::GetStringFUTF8(
+      IDS_EXTENSION_INSTALL_PROMPT_HEADING, UTF8ToUTF16(extension->name()));
+  GtkWidget* heading_label = MakeMarkupLabel("<span weight=\"bold\">%s</span>",
+                                             heading_text);
+  gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5);
+  bool show_permissions = !permissions.empty();
+  // If we are not going to show the permissions, vertically center the title.
+  gtk_box_pack_start(GTK_BOX(right_column_area), heading_label,
+                     !show_permissions, !show_permissions, 0);
+
+  if (show_permissions) {
+    GtkWidget* warning_label = gtk_label_new(l10n_util::GetStringUTF8(
+        IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO).c_str());
+    gtk_util::SetLabelWidth(warning_label, kRightColumnMinWidth);
+
+    gtk_box_pack_start(GTK_BOX(right_column_area), warning_label,
+                       FALSE, FALSE, 0);
+
+    GtkWidget* frame = gtk_frame_new(NULL);
+    gtk_box_pack_start(GTK_BOX(right_column_area), frame, FALSE, FALSE, 0);
+
+    GtkWidget* text_view = gtk_text_view_new();
+    gtk_container_add(GTK_CONTAINER(frame), text_view);
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), FALSE);
+    gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_view),
+                                  kPermissionsPadding);
+    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text_view),
+                                   kPermissionsPadding);
+    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD);
+    GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
+    GtkTextTagTable* tag_table = gtk_text_buffer_get_tag_table(buffer);
+
+    GtkTextTag* padding_below_tag = gtk_text_tag_new(NULL);
+    g_object_set(G_OBJECT(padding_below_tag), "pixels-below-lines",
+                 kPermissionsPadding, NULL);
+    g_object_set(G_OBJECT(padding_below_tag), "pixels-below-lines-set",
+                 TRUE, NULL);
+    gtk_text_tag_table_add(tag_table, padding_below_tag);
+    g_object_unref(padding_below_tag);
+    GtkTextTag* padding_above_tag = gtk_text_tag_new(NULL);
+    g_object_set(G_OBJECT(padding_above_tag), "pixels-above-lines",
+                 kPermissionsPadding, NULL);
+    g_object_set(G_OBJECT(padding_above_tag), "pixels-above-lines-set",
+                 TRUE, NULL);
+    gtk_text_tag_table_add(tag_table, padding_above_tag);
+    g_object_unref(padding_above_tag);
+
+    GtkTextIter end_iter;
+    gtk_text_buffer_get_end_iter(buffer, &end_iter);
+    for (std::vector<string16>::const_iterator iter = permissions.begin();
+         iter != permissions.end(); ++iter) {
+      if (iter != permissions.begin())
+        gtk_text_buffer_insert(buffer, &end_iter, "\n", -1);
+      gtk_text_buffer_insert_with_tags(
+          buffer, &end_iter, UTF16ToUTF8(*iter).c_str(), -1,
+          padding_below_tag,
+          iter == permissions.begin() ? padding_above_tag : NULL,
+          NULL);
+    }
+  }
+
+  g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), delegate);
+  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
+
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
+  gtk_widget_show_all(dialog);
+  gtk_widget_grab_focus(close_button);
+}
+
+}  // namespace
+
+void ExtensionInstallUI::ShowExtensionInstallUIPrompt2Impl(
+    Profile* profile,
+    Delegate* delegate,
+    const Extension* extension,
+    SkBitmap* icon,
+    const std::vector<string16>& permissions) {
+  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
+  if (!browser) {
+    delegate->InstallUIAbort();
+    return;
+  }
+
+  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
+      browser->window());
+  if (!browser_window) {
+    delegate->InstallUIAbort();
+    return;
+  }
+
+  ShowInstallPromptDialog2(browser_window->window(), icon, extension,
+      delegate, permissions);
+}
diff --git a/chrome/browser/ui/gtk/extension_install_prompt_gtk.cc b/chrome/browser/ui/gtk/extension_install_prompt_gtk.cc
new file mode 100644
index 0000000..9790ced
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_install_prompt_gtk.cc
@@ -0,0 +1,110 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Currently this file is only used for the uninstall prompt. The install prompt
+// code is in extension_install_prompt2_gtk.cc.
+
+#include <gtk/gtk.h>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+class Profile;
+
+namespace {
+
+// Left or right margin.
+const int kPanelHorizMargin = 13;
+
+void OnDialogResponse(GtkDialog* dialog, int response_id,
+                      ExtensionInstallUI::Delegate* delegate) {
+  if (response_id == GTK_RESPONSE_ACCEPT) {
+    delegate->InstallUIProceed();
+  } else {
+    delegate->InstallUIAbort();
+  }
+
+  gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+void ShowInstallPromptDialog(GtkWindow* parent, SkBitmap* skia_icon,
+                             const Extension* extension,
+                             ExtensionInstallUI::Delegate *delegate,
+                             ExtensionInstallUI::PromptType type) {
+  // Build the dialog.
+  int title_id = ExtensionInstallUI::kTitleIds[type];
+  int button_id = ExtensionInstallUI::kButtonIds[type];
+  GtkWidget* dialog = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(title_id).c_str(),
+      parent,
+      GTK_DIALOG_MODAL,
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_CLOSE,
+      l10n_util::GetStringUTF8(button_id).c_str(),
+      GTK_RESPONSE_ACCEPT,
+      NULL);
+  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+
+  // Create a two column layout.
+  GtkWidget* content_area = GTK_DIALOG(dialog)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* icon_hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_box_pack_start(GTK_BOX(content_area), icon_hbox, TRUE, TRUE, 0);
+
+  // Put Icon in the left column.
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(skia_icon);
+  GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf);
+  g_object_unref(pixbuf);
+  gtk_box_pack_start(GTK_BOX(icon_hbox), icon, TRUE, TRUE, 0);
+
+  // Create a new vbox for the right column.
+  GtkWidget* right_column_area = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(icon_hbox), right_column_area, TRUE, TRUE, 0);
+
+  int heading_id = ExtensionInstallUI::kHeadingIds[type];
+  std::string heading_text = l10n_util::GetStringFUTF8(
+      heading_id, UTF8ToUTF16(extension->name()));
+  GtkWidget* heading_label = gtk_label_new(heading_text.c_str());
+  gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5);
+  gtk_box_pack_start(GTK_BOX(right_column_area), heading_label, TRUE, TRUE, 0);
+
+  g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), delegate);
+  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
+  gtk_widget_show_all(dialog);
+}
+
+}  // namespace
+
+void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl(
+    Profile* profile,
+    Delegate* delegate,
+    const Extension* extension,
+    SkBitmap* icon,
+    ExtensionInstallUI::PromptType type) {
+  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
+  if (!browser) {
+    delegate->InstallUIAbort();
+    return;
+  }
+
+  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
+      browser->window());
+  if (!browser_window) {
+    delegate->InstallUIAbort();
+    return;
+  }
+
+  ShowInstallPromptDialog(browser_window->window(), icon, extension, delegate,
+                          type);
+}
diff --git a/chrome/browser/ui/gtk/extension_installed_bubble_gtk.cc b/chrome/browser/ui/gtk/extension_installed_bubble_gtk.cc
new file mode 100644
index 0000000..171caca
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_installed_bubble_gtk.cc
@@ -0,0 +1,323 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/extension_installed_bubble_gtk.h"
+
+#include <string>
+
+#include "base/i18n/rtl.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h"
+#include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+const int kHorizontalColumnSpacing = 10;
+const int kIconPadding = 3;
+const int kIconSize = 43;
+const int kTextColumnVerticalSpacing = 7;
+const int kTextColumnWidth = 350;
+
+// When showing the bubble for a new browser action, we may have to wait for
+// the toolbar to finish animating to know where the item's final position
+// will be.
+const int kAnimationWaitRetries = 10;
+const int kAnimationWaitMS = 50;
+
+// Padding between content and edge of info bubble.
+const int kContentBorder = 7;
+
+}  // namespace
+
+namespace browser {
+
+void ShowExtensionInstalledBubble(
+    const Extension* extension,
+    Browser* browser,
+    SkBitmap icon,
+    Profile* profile) {
+  ExtensionInstalledBubbleGtk::Show(extension, browser, icon);
+}
+
+} // namespace browser
+
+void ExtensionInstalledBubbleGtk::Show(const Extension* extension,
+                                       Browser* browser,
+                                       SkBitmap icon) {
+  new ExtensionInstalledBubbleGtk(extension, browser, icon);
+}
+
+ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk(
+    const Extension* extension, Browser *browser, SkBitmap icon)
+    : extension_(extension),
+      browser_(browser),
+      icon_(icon),
+      animation_wait_retries_(kAnimationWaitRetries) {
+  AddRef();  // Balanced in Close().
+
+  if (!extension_->omnibox_keyword().empty()) {
+    type_ = OMNIBOX_KEYWORD;
+  } else if (extension_->browser_action()) {
+    type_ = BROWSER_ACTION;
+  } else if (extension->page_action() &&
+             !extension->page_action()->default_icon_path().empty()) {
+    type_ = PAGE_ACTION;
+  } else {
+    type_ = GENERIC;
+  }
+
+  // |extension| has been initialized but not loaded at this point. We need
+  // to wait on showing the Bubble until not only the EXTENSION_LOADED gets
+  // fired, but all of the EXTENSION_LOADED Observers have run. Only then can we
+  // be sure that a browser action or page action has had views created which we
+  // can inspect for the purpose of pointing to them.
+  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
+      Source<Profile>(browser->profile()));
+  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+      Source<Profile>(browser->profile()));
+}
+
+ExtensionInstalledBubbleGtk::~ExtensionInstalledBubbleGtk() {}
+
+void ExtensionInstalledBubbleGtk::Observe(NotificationType type,
+                                          const NotificationSource& source,
+                                          const NotificationDetails& details) {
+  if (type == NotificationType::EXTENSION_LOADED) {
+    const Extension* extension = Details<const Extension>(details).ptr();
+    if (extension == extension_) {
+      // PostTask to ourself to allow all EXTENSION_LOADED Observers to run.
+      MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
+          &ExtensionInstalledBubbleGtk::ShowInternal));
+    }
+  } else if (type == NotificationType::EXTENSION_UNLOADED) {
+    const Extension* extension =
+        Details<UnloadedExtensionInfo>(details)->extension;
+    if (extension == extension_)
+      extension_ = NULL;
+  } else {
+    NOTREACHED() << L"Received unexpected notification";
+  }
+}
+
+void ExtensionInstalledBubbleGtk::ShowInternal() {
+  BrowserWindowGtk* browser_window =
+      BrowserWindowGtk::GetBrowserWindowForNativeWindow(
+          browser_->window()->GetNativeHandle());
+
+  GtkWidget* reference_widget = NULL;
+
+  if (type_ == BROWSER_ACTION) {
+    BrowserActionsToolbarGtk* toolbar =
+        browser_window->GetToolbar()->GetBrowserActionsToolbar();
+
+    if (toolbar->animating() && animation_wait_retries_-- > 0) {
+      MessageLoopForUI::current()->PostDelayedTask(
+          FROM_HERE,
+          NewRunnableMethod(this, &ExtensionInstalledBubbleGtk::ShowInternal),
+          kAnimationWaitMS);
+      return;
+    }
+
+    reference_widget = toolbar->GetBrowserActionWidget(extension_);
+    // glib delays recalculating layout, but we need reference_widget to know
+    // its coordinates, so we force a check_resize here.
+    gtk_container_check_resize(GTK_CONTAINER(
+        browser_window->GetToolbar()->widget()));
+    // If the widget is not visible then browser_window could be incognito
+    // with this extension disabled. Try showing it on the chevron.
+    // If that fails, fall back to default position.
+    if (reference_widget && !GTK_WIDGET_VISIBLE(reference_widget)) {
+      reference_widget = GTK_WIDGET_VISIBLE(toolbar->chevron()) ?
+          toolbar->chevron() : NULL;
+    }
+  } else if (type_ == PAGE_ACTION) {
+    LocationBarViewGtk* location_bar_view =
+        browser_window->GetToolbar()->GetLocationBarView();
+    location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(),
+                                                   true);  // preview_enabled
+    reference_widget = location_bar_view->GetPageActionWidget(
+        extension_->page_action());
+    // glib delays recalculating layout, but we need reference_widget to know
+    // it's coordinates, so we force a check_resize here.
+    gtk_container_check_resize(GTK_CONTAINER(
+        browser_window->GetToolbar()->widget()));
+    DCHECK(reference_widget);
+  } else if (type_ == OMNIBOX_KEYWORD) {
+    LocationBarViewGtk* location_bar_view =
+        browser_window->GetToolbar()->GetLocationBarView();
+    reference_widget = location_bar_view->location_entry_widget();
+    DCHECK(reference_widget);
+  }
+
+  // Default case.
+  if (reference_widget == NULL)
+    reference_widget = browser_window->GetToolbar()->GetAppMenuButton();
+
+  GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
+      browser_->profile());
+
+  // Setup the InfoBubble content.
+  GtkWidget* bubble_content = gtk_hbox_new(FALSE, kHorizontalColumnSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder);
+
+  if (!icon_.isNull()) {
+    // Scale icon down to 43x43, but allow smaller icons (don't scale up).
+    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon_);
+    gfx::Size size(icon_.width(), icon_.height());
+    if (size.width() > kIconSize || size.height() > kIconSize) {
+      if (size.width() > size.height()) {
+        size.set_height(size.height() * kIconSize / size.width());
+        size.set_width(kIconSize);
+      } else {
+        size.set_width(size.width() * kIconSize / size.height());
+        size.set_height(kIconSize);
+      }
+
+      GdkPixbuf* old = pixbuf;
+      pixbuf = gdk_pixbuf_scale_simple(pixbuf, size.width(), size.height(),
+                                       GDK_INTERP_BILINEAR);
+      g_object_unref(old);
+    }
+
+    // Put Icon in top of the left column.
+    GtkWidget* icon_column = gtk_vbox_new(FALSE, 0);
+    // Use 3 pixel padding to get visual balance with InfoBubble border on the
+    // left.
+    gtk_box_pack_start(GTK_BOX(bubble_content), icon_column, FALSE, FALSE,
+                       kIconPadding);
+    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
+    g_object_unref(pixbuf);
+    gtk_box_pack_start(GTK_BOX(icon_column), image, FALSE, FALSE, 0);
+  }
+
+  // Center text column.
+  GtkWidget* text_column = gtk_vbox_new(FALSE, kTextColumnVerticalSpacing);
+  gtk_box_pack_start(GTK_BOX(bubble_content), text_column, FALSE, FALSE, 0);
+
+  // Heading label
+  GtkWidget* heading_label = gtk_label_new(NULL);
+  string16 extension_name = UTF8ToUTF16(extension_->name());
+  base::i18n::AdjustStringForLocaleDirection(&extension_name);
+  std::string heading_text = l10n_util::GetStringFUTF8(
+      IDS_EXTENSION_INSTALLED_HEADING, extension_name);
+  char* markup = g_markup_printf_escaped("<span size=\"larger\">%s</span>",
+      heading_text.c_str());
+  gtk_label_set_markup(GTK_LABEL(heading_label), markup);
+  g_free(markup);
+
+  gtk_util::SetLabelWidth(heading_label, kTextColumnWidth);
+  gtk_box_pack_start(GTK_BOX(text_column), heading_label, FALSE, FALSE, 0);
+
+  // Page action label
+  if (type_ == PAGE_ACTION) {
+    GtkWidget* info_label = gtk_label_new(l10n_util::GetStringUTF8(
+        IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO).c_str());
+    gtk_util::SetLabelWidth(info_label, kTextColumnWidth);
+    gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
+  }
+
+  // Omnibox keyword label
+  if (type_ == OMNIBOX_KEYWORD) {
+    GtkWidget* info_label = gtk_label_new(l10n_util::GetStringFUTF8(
+        IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
+        UTF8ToUTF16(extension_->omnibox_keyword())).c_str());
+    gtk_util::SetLabelWidth(info_label, kTextColumnWidth);
+    gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
+  }
+
+  // Manage label
+  GtkWidget* manage_label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALLED_MANAGE_INFO).c_str());
+  gtk_util::SetLabelWidth(manage_label, kTextColumnWidth);
+  gtk_box_pack_start(GTK_BOX(text_column), manage_label, FALSE, FALSE, 0);
+
+  // Create and pack the close button.
+  GtkWidget* close_column = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(bubble_content), close_column, FALSE, FALSE, 0);
+  close_button_.reset(CustomDrawButton::CloseButton(theme_provider));
+  g_signal_connect(close_button_->widget(), "clicked",
+                   G_CALLBACK(OnButtonClick), this);
+  gtk_box_pack_start(GTK_BOX(close_column), close_button_->widget(),
+      FALSE, FALSE, 0);
+
+  InfoBubbleGtk::ArrowLocationGtk arrow_location =
+      !base::i18n::IsRTL() ?
+      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
+      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
+
+  gfx::Rect bounds = gtk_util::WidgetBounds(reference_widget);
+  if (type_ == OMNIBOX_KEYWORD) {
+    // Reverse the arrow for omnibox keywords, since the bubble will be on the
+    // other side of the window. We also clear the width to avoid centering
+    // the popup on the URL bar.
+    arrow_location =
+        !base::i18n::IsRTL() ?
+        InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
+        InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
+    if (base::i18n::IsRTL())
+      bounds.Offset(bounds.width(), 0);
+    bounds.set_width(0);
+  }
+
+  info_bubble_ = InfoBubbleGtk::Show(reference_widget,
+      &bounds,
+      bubble_content,
+      arrow_location,
+      true,  // match_system_theme
+      true,  // grab_input
+      theme_provider,
+      this);
+}
+
+// static
+void ExtensionInstalledBubbleGtk::OnButtonClick(GtkWidget* button,
+    ExtensionInstalledBubbleGtk* bubble) {
+  if (button == bubble->close_button_->widget()) {
+    bubble->info_bubble_->Close();
+  } else {
+    NOTREACHED();
+  }
+}
+// InfoBubbleDelegate
+void ExtensionInstalledBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                                    bool closed_by_escape) {
+  if (extension_ && type_ == PAGE_ACTION) {
+    // Turn the page action preview off.
+    BrowserWindowGtk* browser_window =
+          BrowserWindowGtk::GetBrowserWindowForNativeWindow(
+              browser_->window()->GetNativeHandle());
+    LocationBarViewGtk* location_bar_view =
+        browser_window->GetToolbar()->GetLocationBarView();
+    location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(),
+                                                   false);  // preview_enabled
+  }
+
+  // We need to allow the info bubble to close and remove the widgets from
+  // the window before we call Release() because close_button_ depends
+  // on all references being cleared before it is destroyed.
+  MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
+      &ExtensionInstalledBubbleGtk::Close));
+}
+
+void ExtensionInstalledBubbleGtk::Close() {
+  Release();  // Balanced in ctor.
+  info_bubble_ = NULL;
+}
diff --git a/chrome/browser/ui/gtk/extension_installed_bubble_gtk.h b/chrome/browser/ui/gtk/extension_installed_bubble_gtk.h
new file mode 100644
index 0000000..4c32b5c
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_installed_bubble_gtk.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_EXTENSION_INSTALLED_BUBBLE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_EXTENSION_INSTALLED_BUBBLE_GTK_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+class Browser;
+class BrowserWindowGtk;
+class Extension;
+class SkBitmap;
+
+// Provides feedback to the user upon successful installation of an
+// extension. Depending on the type of extension, the InfoBubble will
+// point to:
+//    OMNIBOX_KEYWORD-> The omnibox.
+//    BROWSER_ACTION -> The browserAction icon in the toolbar.
+//    PAGE_ACTION    -> A preview of the page action icon in the location
+//                      bar which is shown while the InfoBubble is shown.
+//    GENERIC        -> The wrench menu. This case includes page actions that
+//                      don't specify a default icon.
+//
+// ExtensionInstallBubble manages its own lifetime.
+class ExtensionInstalledBubbleGtk
+    : public InfoBubbleGtkDelegate,
+      public NotificationObserver,
+      public base::RefCountedThreadSafe<ExtensionInstalledBubbleGtk> {
+ public:
+  // The behavior and content of this InfoBubble comes in three varieties.
+  enum BubbleType {
+    OMNIBOX_KEYWORD,
+    BROWSER_ACTION,
+    PAGE_ACTION,
+    GENERIC
+  };
+
+  // Creates the ExtensionInstalledBubble and schedules it to be shown once
+  // the extension has loaded. |extension| is the installed extension. |browser|
+  // is the browser window which will host the bubble. |icon| is the install
+  // icon of the extension.
+  static void Show(const Extension* extension, Browser *browser, SkBitmap icon);
+
+ private:
+  friend class base::RefCountedThreadSafe<ExtensionInstalledBubbleGtk>;
+
+  // Private ctor. Registers a listener for EXTENSION_LOADED.
+  ExtensionInstalledBubbleGtk(const Extension* extension, Browser *browser,
+                              SkBitmap icon);
+
+  virtual ~ExtensionInstalledBubbleGtk();
+
+  // Shows the bubble. Called internally via PostTask.
+  void ShowInternal();
+
+  // NotificationObserver
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // InfoBubbleDelegate
+  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                 bool closed_by_escape);
+
+  // Calls Release() internally. Called internally via PostTask.
+  void Close();
+
+  static void OnButtonClick(GtkWidget* button,
+                            ExtensionInstalledBubbleGtk* toolbar);
+
+  const Extension* extension_;
+  Browser *browser_;
+  SkBitmap icon_;
+  NotificationRegistrar registrar_;
+  BubbleType type_;
+
+  // The number of times to retry showing the bubble if the browser action
+  // toolbar is animating.
+  int animation_wait_retries_;
+
+  // The 'x' that the user can press to hide the info bubble shelf.
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  InfoBubbleGtk* info_bubble_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_EXTENSION_INSTALLED_BUBBLE_GTK_H_
diff --git a/chrome/browser/ui/gtk/extension_popup_gtk.cc b/chrome/browser/ui/gtk/extension_popup_gtk.cc
new file mode 100644
index 0000000..e4bae2a
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_popup_gtk.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/extension_popup_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include <algorithm>
+
+#include "base/i18n/rtl.h"
+#include "base/message_loop.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/debugger/devtools_manager.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "googleurl/src/gurl.h"
+
+ExtensionPopupGtk* ExtensionPopupGtk::current_extension_popup_ = NULL;
+
+// The minimum/maximum dimensions of the extension popup.
+// The minimum is just a little larger than the size of a browser action button.
+// The maximum is an arbitrary number that should be smaller than most screens.
+const int ExtensionPopupGtk::kMinWidth = 25;
+const int ExtensionPopupGtk::kMinHeight = 25;
+const int ExtensionPopupGtk::kMaxWidth = 800;
+const int ExtensionPopupGtk::kMaxHeight = 600;
+
+ExtensionPopupGtk::ExtensionPopupGtk(Browser* browser,
+                                     ExtensionHost* host,
+                                     GtkWidget* anchor,
+                                     bool inspect)
+    : browser_(browser),
+      bubble_(NULL),
+      host_(host),
+      anchor_(anchor),
+      being_inspected_(inspect),
+      method_factory_(this) {
+  host_->view()->SetContainer(this);
+
+  // If the host had somehow finished loading, then we'd miss the notification
+  // and not show.  This seems to happen in single-process mode.
+  if (host->did_stop_loading()) {
+    ShowPopup();
+  } else {
+    registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING,
+                   Source<Profile>(host->profile()));
+  }
+
+  registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
+                 Source<Profile>(host->profile()));
+}
+
+ExtensionPopupGtk::~ExtensionPopupGtk() {
+}
+
+void ExtensionPopupGtk::Observe(NotificationType type,
+                                const NotificationSource& source,
+                                const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::EXTENSION_HOST_DID_STOP_LOADING:
+      if (Details<ExtensionHost>(host_.get()) == details)
+        ShowPopup();
+      break;
+    case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE:
+      if (Details<ExtensionHost>(host_.get()) == details)
+        DestroyPopup();
+      break;
+    case NotificationType::DEVTOOLS_WINDOW_CLOSING:
+      // Make sure its the devtools window that inspecting our popup.
+      if (Details<RenderViewHost>(host_->render_view_host()) != details)
+        break;
+
+      // If the devtools window is closing, we post a task to ourselves to
+      // close the popup. This gives the devtools window a chance to finish
+      // detaching from the inspected RenderViewHost.
+      MessageLoop::current()->PostTask(FROM_HERE,
+          method_factory_.NewRunnableMethod(&ExtensionPopupGtk::DestroyPopup));
+      break;
+    default:
+      NOTREACHED() << "Received unexpected notification";
+  }
+}
+
+void ExtensionPopupGtk::ShowPopup() {
+  if (bubble_) {
+    NOTREACHED();
+    return;
+  }
+
+  if (being_inspected_) {
+    DevToolsManager::GetInstance()->OpenDevToolsWindow(
+        host_->render_view_host());
+    // Listen for the the devtools window closing.
+    registrar_.Add(this, NotificationType::DEVTOOLS_WINDOW_CLOSING,
+        Source<Profile>(host_->profile()));
+  }
+
+  // Only one instance should be showing at a time. Get rid of the old one, if
+  // any. Typically, |current_extension_popup_| will be NULL, but it can be
+  // non-NULL if a browser action button is clicked while another extension
+  // popup's extension host is still loading.
+  if (current_extension_popup_)
+    current_extension_popup_->DestroyPopup();
+  current_extension_popup_ = this;
+
+  // We'll be in the upper-right corner of the window for LTR languages, so we
+  // want to put the arrow at the upper-right corner of the bubble to match the
+  // page and app menus.
+  InfoBubbleGtk::ArrowLocationGtk arrow_location =
+      !base::i18n::IsRTL() ?
+      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
+      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
+  bubble_ = InfoBubbleGtk::Show(anchor_,
+                                NULL,
+                                host_->view()->native_view(),
+                                arrow_location,
+                                false,  // match_system_theme
+                                !being_inspected_,  // grab_input
+                                GtkThemeProvider::GetFrom(browser_->profile()),
+                                this);
+}
+
+bool ExtensionPopupGtk::DestroyPopup() {
+  if (!bubble_) {
+    NOTREACHED();
+    return false;
+  }
+
+  bubble_->Close();
+  return true;
+}
+
+void ExtensionPopupGtk::InfoBubbleClosing(InfoBubbleGtk* bubble,
+                                          bool closed_by_escape) {
+  current_extension_popup_ = NULL;
+  delete this;
+}
+
+void ExtensionPopupGtk::OnExtensionPreferredSizeChanged(
+    ExtensionViewGtk* view,
+    const gfx::Size& new_size) {
+  int width = std::max(kMinWidth, std::min(kMaxWidth, new_size.width()));
+  int height = std::max(kMinHeight, std::min(kMaxHeight, new_size.height()));
+
+  view->render_view_host()->view()->SetSize(gfx::Size(width, height));
+  gtk_widget_set_size_request(view->native_view(), width, height);
+}
+
+// static
+void ExtensionPopupGtk::Show(const GURL& url, Browser* browser,
+    GtkWidget* anchor, bool inspect) {
+  ExtensionProcessManager* manager =
+      browser->profile()->GetExtensionProcessManager();
+  DCHECK(manager);
+  if (!manager)
+    return;
+
+  ExtensionHost* host = manager->CreatePopup(url, browser);
+  // This object will delete itself when the info bubble is closed.
+  new ExtensionPopupGtk(browser, host, anchor, inspect);
+}
+
+gfx::Rect ExtensionPopupGtk::GetViewBounds() {
+  return gfx::Rect(host_->view()->native_view()->allocation);
+}
diff --git a/chrome/browser/ui/gtk/extension_popup_gtk.h b/chrome/browser/ui/gtk/extension_popup_gtk.h
new file mode 100644
index 0000000..c28843d
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_popup_gtk.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.
+
+#ifndef CHROME_BROWSER_UI_GTK_EXTENSION_POPUP_GTK_H_
+#define CHROME_BROWSER_UI_GTK_EXTENSION_POPUP_GTK_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/ui/gtk/extension_view_gtk.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/gfx/rect.h"
+
+class Browser;
+class ExtensionHost;
+class GURL;
+
+class ExtensionPopupGtk : public NotificationObserver,
+                          public InfoBubbleGtkDelegate,
+                          public ExtensionViewGtk::Container {
+ public:
+  ExtensionPopupGtk(Browser* browser,
+                    ExtensionHost* host,
+                    GtkWidget* anchor,
+                    bool inspect);
+  virtual ~ExtensionPopupGtk();
+
+  static void Show(const GURL& url,
+                   Browser* browser,
+                   GtkWidget* anchor,
+                   bool inspect);
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // InfoBubbleGtkDelegate implementation.
+  virtual void InfoBubbleClosing(InfoBubbleGtk* bubble,
+                                 bool closed_by_escape);
+
+  // ExtensionViewGtk::Container implementation
+  virtual void OnExtensionPreferredSizeChanged(ExtensionViewGtk* view,
+                                               const gfx::Size& new_size);
+
+  // Destroys the popup widget. This will in turn destroy us since we delete
+  // ourselves when the info bubble closes. Returns true if we successfully
+  // closed the bubble.
+  bool DestroyPopup();
+
+  // Get the currently showing extension popup, or NULL.
+  static ExtensionPopupGtk* get_current_extension_popup() {
+    return current_extension_popup_;
+  }
+
+  bool being_inspected() const {
+    return being_inspected_;
+  }
+
+  // Declared here for testing.
+  static const int kMinWidth;
+  static const int kMinHeight;
+  static const int kMaxWidth;
+  static const int kMaxHeight;
+
+ private:
+  // Shows the popup widget. Called after loading completes.
+  void ShowPopup();
+
+  Browser* browser_;
+
+  InfoBubbleGtk* bubble_;
+
+  // We take ownership of the popup ExtensionHost.
+  scoped_ptr<ExtensionHost> host_;
+
+  // The widget for anchoring the position of the info bubble.
+  GtkWidget* anchor_;
+
+  NotificationRegistrar registrar_;
+
+  static ExtensionPopupGtk* current_extension_popup_;
+
+  // Whether a devtools window is attached to this bubble.
+  bool being_inspected_;
+
+  ScopedRunnableMethodFactory<ExtensionPopupGtk> method_factory_;
+
+  // Used for testing. ---------------------------------------------------------
+  gfx::Rect GetViewBounds();
+
+  friend class BrowserActionTestUtil;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionPopupGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_EXTENSION_POPUP_GTK_H_
diff --git a/chrome/browser/ui/gtk/extension_view_gtk.cc b/chrome/browser/ui/gtk/extension_view_gtk.cc
new file mode 100644
index 0000000..72ad79b
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_view_gtk.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/extension_view_gtk.h"
+
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
+#include "chrome/browser/ui/gtk/extension_popup_gtk.h"
+
+ExtensionViewGtk::ExtensionViewGtk(ExtensionHost* extension_host,
+                                   Browser* browser)
+    : browser_(browser),
+      extension_host_(extension_host),
+      render_widget_host_view_(NULL),
+      container_(NULL) {
+}
+
+void ExtensionViewGtk::Init() {
+  CreateWidgetHostView();
+}
+
+gfx::NativeView ExtensionViewGtk::native_view() {
+  return render_widget_host_view_->native_view();
+}
+
+RenderViewHost* ExtensionViewGtk::render_view_host() const {
+  return extension_host_->render_view_host();
+}
+
+void ExtensionViewGtk::SetBackground(const SkBitmap& background) {
+  if (render_view_host()->IsRenderViewLive()) {
+    render_widget_host_view_->SetBackground(background);
+  } else {
+    pending_background_ = background;
+  }
+}
+
+void ExtensionViewGtk::UpdatePreferredSize(const gfx::Size& new_size) {
+  if (container_)
+    container_->OnExtensionPreferredSizeChanged(this, new_size);
+}
+
+void ExtensionViewGtk::CreateWidgetHostView() {
+  DCHECK(!render_widget_host_view_);
+  render_widget_host_view_ = new RenderWidgetHostViewGtk(render_view_host());
+  render_widget_host_view_->InitAsChild();
+
+  extension_host_->CreateRenderViewSoon(render_widget_host_view_);
+}
+
+void ExtensionViewGtk::RenderViewCreated() {
+  if (!pending_background_.empty() && render_view_host()->view()) {
+    render_widget_host_view_->SetBackground(pending_background_);
+    pending_background_.reset();
+  }
+
+  // Tell the renderer not to draw scrollbars in popups unless the
+  // popups are at the maximum allowed size.
+  gfx::Size largest_popup_size(ExtensionPopupGtk::kMaxWidth,
+                               ExtensionPopupGtk::kMaxHeight);
+  extension_host_->DisableScrollbarsForSmallWindows(largest_popup_size);
+}
diff --git a/chrome/browser/ui/gtk/extension_view_gtk.h b/chrome/browser/ui/gtk/extension_view_gtk.h
new file mode 100644
index 0000000..c0dccfa
--- /dev/null
+++ b/chrome/browser/ui/gtk/extension_view_gtk.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_EXTENSION_VIEW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_EXTENSION_VIEW_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+
+class Browser;
+class ExtensionHost;
+class RenderViewHost;
+class RenderWidgetHostViewGtk;
+class SkBitmap;
+
+class ExtensionViewGtk {
+ public:
+  ExtensionViewGtk(ExtensionHost* extension_host, Browser* browser);
+
+  class Container {
+   public:
+    virtual ~Container() {}
+    virtual void OnExtensionPreferredSizeChanged(ExtensionViewGtk* view,
+                                                 const gfx::Size& new_size) {}
+  };
+
+  void Init();
+
+  gfx::NativeView native_view();
+  Browser* browser() const { return browser_; }
+
+  void SetBackground(const SkBitmap& background);
+
+  // Sets the container for this view.
+  void SetContainer(Container* container) { container_ = container; }
+
+  // Method for the ExtensionHost to notify us about the correct size for
+  // extension contents.
+  void UpdatePreferredSize(const gfx::Size& new_size);
+
+  // Method for the ExtensionHost to notify us when the RenderViewHost has a
+  // connection.
+  void RenderViewCreated();
+
+  RenderViewHost* render_view_host() const;
+
+ private:
+  void CreateWidgetHostView();
+
+  Browser* browser_;
+
+  ExtensionHost* extension_host_;
+
+  RenderWidgetHostViewGtk* render_widget_host_view_;
+
+  // The background the view should have once it is initialized. This is set
+  // when the view has a custom background, but hasn't been initialized yet.
+  SkBitmap pending_background_;
+
+  // This view's container.
+  Container* container_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionViewGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_EXTENSION_VIEW_GTK_H_
diff --git a/chrome/browser/ui/gtk/external_protocol_dialog_gtk.cc b/chrome/browser/ui/gtk/external_protocol_dialog_gtk.cc
new file mode 100644
index 0000000..4bd9572
--- /dev/null
+++ b/chrome/browser/ui/gtk/external_protocol_dialog_gtk.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/external_protocol_dialog_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/external_protocol_handler.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
+
+namespace {
+
+const int kMessageWidth = 400;
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// ExternalProtocolHandler
+
+// static
+void ExternalProtocolHandler::RunExternalProtocolDialog(
+    const GURL& url, int render_process_host_id, int routing_id) {
+  new ExternalProtocolDialogGtk(url);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ExternalProtocolDialogGtk
+
+ExternalProtocolDialogGtk::ExternalProtocolDialogGtk(const GURL& url)
+    : url_(url),
+      creation_time_(base::TimeTicks::Now()) {
+  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_TITLE).c_str(),
+      NULL,
+      GTK_DIALOG_NO_SEPARATOR,
+      NULL);
+
+  // Add the response buttons.
+  gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(
+          IDS_EXTERNAL_PROTOCOL_CANCEL_BUTTON_TEXT).c_str(),
+      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+  gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT).c_str(),
+      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+
+  // Construct the message text.
+  const int kMaxUrlWithoutSchemeSize = 256;
+  const int kMaxCommandSize = 256;
+  std::wstring elided_url_without_scheme;
+  std::wstring elided_command;
+  ui::ElideString(ASCIIToWide(url.possibly_invalid_spec()),
+      kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
+  ui::ElideString(ASCIIToWide(std::string("xdg-open ") + url.spec()),
+      kMaxCommandSize, &elided_command);
+
+  std::string message_text = l10n_util::GetStringFUTF8(
+      IDS_EXTERNAL_PROTOCOL_INFORMATION,
+      ASCIIToUTF16(url.scheme() + ":"),
+      WideToUTF16(elided_url_without_scheme)) + "\n\n";
+
+  message_text += l10n_util::GetStringFUTF8(
+      IDS_EXTERNAL_PROTOCOL_APPLICATION_TO_LAUNCH,
+      WideToUTF16(elided_command)) + "\n\n";
+
+  message_text += l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_WARNING);
+
+  // Create the content-holding vbox.
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox),
+                                 gtk_util::kContentAreaBorder);
+
+  // Add the message text.
+  GtkWidget* label = gtk_label_new(message_text.c_str());
+  gtk_util::SetLabelWidth(label, kMessageWidth);
+  gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+
+  // Add the checkbox.
+  checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), checkbox_,
+                     FALSE, FALSE, 0);
+
+  // Add our vbox to the dialog.
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), vbox,
+                     FALSE, FALSE, 0);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+
+  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+  gtk_widget_show_all(dialog_);
+}
+
+void ExternalProtocolDialogGtk::OnDialogResponse(GtkWidget* widget,
+                                                 int response) {
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox_))) {
+    if (response == GTK_RESPONSE_ACCEPT) {
+      ExternalProtocolHandler::SetBlockState(
+          url_.scheme(), ExternalProtocolHandler::DONT_BLOCK);
+    } else if (response == GTK_RESPONSE_REJECT) {
+      ExternalProtocolHandler::SetBlockState(
+          url_.scheme(), ExternalProtocolHandler::BLOCK);
+    }
+    // If the response is GTK_RESPONSE_DELETE, triggered by the user closing
+    // the dialog, do nothing.
+  }
+
+  if (response == GTK_RESPONSE_ACCEPT) {
+    UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url",
+                             base::TimeTicks::Now() - creation_time_);
+
+    ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_);
+  }
+
+  gtk_widget_destroy(dialog_);
+  delete this;
+}
diff --git a/chrome/browser/ui/gtk/external_protocol_dialog_gtk.h b/chrome/browser/ui/gtk/external_protocol_dialog_gtk.h
new file mode 100644
index 0000000..d0fa3ad
--- /dev/null
+++ b/chrome/browser/ui/gtk/external_protocol_dialog_gtk.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_
+#pragma once
+
+#include "base/time.h"
+#include "googleurl/src/gurl.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class TabContents;
+
+typedef struct _GtkWidget GtkWidget;
+
+class ExternalProtocolDialogGtk {
+ public:
+  explicit ExternalProtocolDialogGtk(const GURL& url);
+
+ protected:
+  virtual ~ExternalProtocolDialogGtk() {}
+
+ private:
+  CHROMEGTK_CALLBACK_1(ExternalProtocolDialogGtk, void, OnDialogResponse, int);
+
+  GtkWidget* dialog_;
+  GtkWidget* checkbox_;
+  GURL url_;
+  base::TimeTicks creation_time_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/find_bar_gtk.cc b/chrome/browser/ui/gtk/find_bar_gtk.cc
new file mode 100644
index 0000000..f8136e8
--- /dev/null
+++ b/chrome/browser/ui/gtk/find_bar_gtk.cc
@@ -0,0 +1,995 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/find_bar_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/i18n/rtl.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_bar_state.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/find_bar/find_notification_details.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_floating_container.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/nine_box.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
+#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/native_web_keyboard_event.h"
+#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+// Used as the color of the text in the entry box and the text for the results
+// label for failure searches.
+const GdkColor kEntryTextColor = gtk_util::kGdkBlack;
+
+// Used as the color of the background of the entry box and the background of
+// the find label for successful searches.
+const GdkColor kEntryBackgroundColor = gtk_util::kGdkWhite;
+const GdkColor kFindFailureBackgroundColor = GDK_COLOR_RGB(255, 102, 102);
+const GdkColor kFindSuccessTextColor = GDK_COLOR_RGB(178, 178, 178);
+
+// Padding around the container.
+const int kBarPaddingTopBottom = 4;
+const int kEntryPaddingLeft = 6;
+const int kCloseButtonPaddingLeft = 3;
+const int kBarPaddingRight = 4;
+
+// The height of the findbar dialog, as dictated by the size of the background
+// images.
+const int kFindBarHeight = 32;
+
+// The width of the text entry field.
+const int kTextEntryWidth = 220;
+
+// The size of the "rounded" corners.
+const int kCornerSize = 3;
+
+enum FrameType {
+  FRAME_MASK,
+  FRAME_STROKE,
+};
+
+// Returns a list of points that either form the outline of the status bubble
+// (|type| == FRAME_MASK) or form the inner border around the inner edge
+// (|type| == FRAME_STROKE).
+std::vector<GdkPoint> MakeFramePolygonPoints(int width,
+                                             int height,
+                                             FrameType type) {
+  using gtk_util::MakeBidiGdkPoint;
+  std::vector<GdkPoint> points;
+
+  bool ltr = !base::i18n::IsRTL();
+  // If we have a stroke, we have to offset some of our points by 1 pixel.
+  // We have to inset by 1 pixel when we draw horizontal lines that are on the
+  // bottom or when we draw vertical lines that are closer to the end (end is
+  // right for ltr).
+  int y_off = (type == FRAME_MASK) ? 0 : -1;
+  // We use this one for LTR.
+  int x_off_l = ltr ? y_off : 0;
+  // We use this one for RTL.
+  int x_off_r = !ltr ? -y_off : 0;
+
+  // Top left corner
+  points.push_back(MakeBidiGdkPoint(x_off_r, 0, width, ltr));
+  points.push_back(MakeBidiGdkPoint(
+      kCornerSize + x_off_r, kCornerSize, width, ltr));
+
+  // Bottom left corner
+  points.push_back(MakeBidiGdkPoint(
+      kCornerSize + x_off_r, height - kCornerSize, width, ltr));
+  points.push_back(MakeBidiGdkPoint(
+      (2 * kCornerSize) + x_off_l, height + y_off,
+      width, ltr));
+
+  // Bottom right corner
+  points.push_back(MakeBidiGdkPoint(
+      width - (2 * kCornerSize) + x_off_r, height + y_off,
+      width, ltr));
+  points.push_back(MakeBidiGdkPoint(
+      width - kCornerSize + x_off_l, height - kCornerSize, width, ltr));
+
+  // Top right corner
+  points.push_back(MakeBidiGdkPoint(
+      width - kCornerSize + x_off_l, kCornerSize, width, ltr));
+  points.push_back(MakeBidiGdkPoint(width + x_off_l, 0, width, ltr));
+
+  return points;
+}
+
+// Give the findbar dialog its unique shape using images.
+void SetDialogShape(GtkWidget* widget) {
+  static NineBox* dialog_shape = NULL;
+  if (!dialog_shape) {
+    dialog_shape = new NineBox(
+      IDR_FIND_DLG_LEFT_BACKGROUND,
+      IDR_FIND_DLG_MIDDLE_BACKGROUND,
+      IDR_FIND_DLG_RIGHT_BACKGROUND,
+      0, 0, 0, 0, 0, 0);
+    dialog_shape->ChangeWhiteToTransparent();
+  }
+
+  dialog_shape->ContourWidget(widget);
+}
+
+// Return a ninebox that will paint the border of the findbar dialog. This is
+// shared across all instances of the findbar. Do not free the returned pointer.
+const NineBox* GetDialogBorder() {
+  static NineBox* dialog_border = NULL;
+  if (!dialog_border) {
+    dialog_border = new NineBox(
+      IDR_FIND_DIALOG_LEFT,
+      IDR_FIND_DIALOG_MIDDLE,
+      IDR_FIND_DIALOG_RIGHT,
+      0, 0, 0, 0, 0, 0);
+  }
+
+  return dialog_border;
+}
+
+// Like gtk_util::CreateGtkBorderBin, but allows control over the alignment and
+// returns both the event box and the alignment so we can modify it during its
+// lifetime (i.e. during a theme change).
+void BuildBorder(GtkWidget* child,
+                 bool center,
+                 int padding_top, int padding_bottom, int padding_left,
+                 int padding_right,
+                 GtkWidget** ebox, GtkWidget** alignment) {
+  *ebox = gtk_event_box_new();
+  if (center)
+    *alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
+  else
+    *alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(*alignment),
+                            padding_top, padding_bottom, padding_left,
+                            padding_right);
+  gtk_container_add(GTK_CONTAINER(*alignment), child);
+  gtk_container_add(GTK_CONTAINER(*ebox), *alignment);
+}
+
+}  // namespace
+
+FindBarGtk::FindBarGtk(Browser* browser)
+    : browser_(browser),
+      window_(static_cast<BrowserWindowGtk*>(browser->window())),
+      theme_provider_(GtkThemeProvider::GetFrom(browser->profile())),
+      container_width_(-1),
+      container_height_(-1),
+      match_label_failure_(false),
+      ignore_changed_signal_(false) {
+  InitWidgets();
+  ViewIDUtil::SetID(text_entry_, VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
+
+  // Insert the widget into the browser gtk hierarchy.
+  window_->AddFindBar(this);
+
+  // Hook up signals after the widget has been added to the hierarchy so the
+  // widget will be realized.
+  g_signal_connect(text_entry_, "changed",
+                   G_CALLBACK(OnChanged), this);
+  g_signal_connect_after(text_entry_, "key-press-event",
+                         G_CALLBACK(OnKeyPressEvent), this);
+  g_signal_connect_after(text_entry_, "key-release-event",
+                         G_CALLBACK(OnKeyReleaseEvent), this);
+  // When the user tabs to us or clicks on us, save where the focus used to
+  // be.
+  g_signal_connect(text_entry_, "focus",
+                   G_CALLBACK(OnFocus), this);
+  gtk_widget_add_events(text_entry_, GDK_BUTTON_PRESS_MASK);
+  g_signal_connect(text_entry_, "button-press-event",
+                   G_CALLBACK(OnButtonPress), this);
+  g_signal_connect(text_entry_, "move-cursor", G_CALLBACK(OnMoveCursor), this);
+  g_signal_connect(text_entry_, "activate", G_CALLBACK(OnActivate), this);
+  g_signal_connect(text_entry_, "direction-changed",
+                   G_CALLBACK(OnWidgetDirectionChanged), this);
+  g_signal_connect(text_entry_, "focus-in-event",
+                   G_CALLBACK(OnFocusIn), this);
+  g_signal_connect(text_entry_, "focus-out-event",
+                   G_CALLBACK(OnFocusOut), this);
+  g_signal_connect(container_, "expose-event",
+                   G_CALLBACK(OnExpose), this);
+}
+
+FindBarGtk::~FindBarGtk() {
+}
+
+void FindBarGtk::InitWidgets() {
+  // The find bar is basically an hbox with a gtkentry (text box) followed by 3
+  // buttons (previous result, next result, close).  We wrap the hbox in a gtk
+  // alignment and a gtk event box to get the padding and light blue
+  // background. We put that event box in a fixed in order to control its
+  // lateral position. We put that fixed in a SlideAnimatorGtk in order to get
+  // the slide effect.
+  GtkWidget* hbox = gtk_hbox_new(false, 0);
+  container_ = gtk_util::CreateGtkBorderBin(hbox, NULL,
+      kBarPaddingTopBottom, kBarPaddingTopBottom,
+      kEntryPaddingLeft, kBarPaddingRight);
+  ViewIDUtil::SetID(container_, VIEW_ID_FIND_IN_PAGE);
+  gtk_widget_set_app_paintable(container_, TRUE);
+
+  slide_widget_.reset(new SlideAnimatorGtk(container_,
+                                           SlideAnimatorGtk::DOWN,
+                                           0, false, false, NULL));
+
+  close_button_.reset(CustomDrawButton::CloseButton(theme_provider_));
+  gtk_util::CenterWidgetInHBox(hbox, close_button_->widget(), true,
+                               kCloseButtonPaddingLeft);
+  g_signal_connect(close_button_->widget(), "clicked",
+                   G_CALLBACK(OnClicked), this);
+  gtk_widget_set_tooltip_text(close_button_->widget(),
+      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_CLOSE_TOOLTIP).c_str());
+
+  find_next_button_.reset(new CustomDrawButton(theme_provider_,
+      IDR_FINDINPAGE_NEXT, IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_H,
+      IDR_FINDINPAGE_NEXT_P, GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU));
+  g_signal_connect(find_next_button_->widget(), "clicked",
+                   G_CALLBACK(OnClicked), this);
+  gtk_widget_set_tooltip_text(find_next_button_->widget(),
+      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_NEXT_TOOLTIP).c_str());
+  gtk_box_pack_end(GTK_BOX(hbox), find_next_button_->widget(),
+                   FALSE, FALSE, 0);
+
+  find_previous_button_.reset(new CustomDrawButton(theme_provider_,
+      IDR_FINDINPAGE_PREV, IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_H,
+      IDR_FINDINPAGE_PREV_P, GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU));
+  g_signal_connect(find_previous_button_->widget(), "clicked",
+                   G_CALLBACK(OnClicked), this);
+  gtk_widget_set_tooltip_text(find_previous_button_->widget(),
+      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP).c_str());
+  gtk_box_pack_end(GTK_BOX(hbox), find_previous_button_->widget(),
+                   FALSE, FALSE, 0);
+
+  // Make a box for the edit and match count widgets. This is fixed size since
+  // we want the widgets inside to resize themselves rather than making the
+  // dialog bigger.
+  GtkWidget* content_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_widget_set_size_request(content_hbox, kTextEntryWidth, -1);
+
+  text_entry_ = gtk_entry_new();
+  gtk_entry_set_has_frame(GTK_ENTRY(text_entry_), FALSE);
+
+  match_count_label_ = gtk_label_new(NULL);
+  // This line adds padding on the sides so that the label has even padding on
+  // all edges.
+  gtk_misc_set_padding(GTK_MISC(match_count_label_), 2, 0);
+  match_count_event_box_ = gtk_event_box_new();
+  GtkWidget* match_count_centerer = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(match_count_centerer), match_count_event_box_,
+                     TRUE, TRUE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(match_count_centerer), 1);
+  gtk_container_add(GTK_CONTAINER(match_count_event_box_), match_count_label_);
+
+  gtk_box_pack_end(GTK_BOX(content_hbox), match_count_centerer,
+                   FALSE, FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(content_hbox), text_entry_, TRUE, TRUE, 0);
+
+  // This event box is necessary to color in the area above and below the match
+  // count label, and is where we draw the entry background onto in GTK mode.
+  BuildBorder(content_hbox, true, 0, 0, 0, 0,
+              &content_event_box_, &content_alignment_);
+  gtk_widget_set_app_paintable(content_event_box_, TRUE);
+  g_signal_connect(content_event_box_, "expose-event",
+                   G_CALLBACK(OnContentEventBoxExpose), this);
+
+  // This alignment isn't centered and is used for spacing in chrome theme
+  // mode. (It's also used in GTK mode for padding because left padding doesn't
+  // equal bottom padding naturally.)
+  BuildBorder(content_event_box_, false, 2, 2, 2, 0,
+              &border_bin_, &border_bin_alignment_);
+  gtk_util::CenterWidgetInHBox(hbox, border_bin_, true, 0);
+
+  theme_provider_->InitThemesFor(this);
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+
+  g_signal_connect(widget(), "parent-set", G_CALLBACK(OnParentSet), this);
+
+  // We take care to avoid showing the slide animator widget.
+  gtk_widget_show_all(container_);
+  gtk_widget_show(widget());
+}
+
+FindBarController* FindBarGtk::GetFindBarController() const {
+  return find_bar_controller_;
+}
+
+void FindBarGtk::SetFindBarController(FindBarController* find_bar_controller) {
+  find_bar_controller_ = find_bar_controller;
+}
+
+void FindBarGtk::Show(bool animate) {
+  if (animate) {
+    slide_widget_->Open();
+    selection_rect_ = gfx::Rect();
+    Reposition();
+    if (container_->window)
+      gdk_window_raise(container_->window);
+  } else {
+    slide_widget_->OpenWithoutAnimation();
+  }
+}
+
+void FindBarGtk::Hide(bool animate) {
+  if (animate)
+    slide_widget_->Close();
+  else
+    slide_widget_->CloseWithoutAnimation();
+}
+
+void FindBarGtk::SetFocusAndSelection() {
+  StoreOutsideFocus();
+  gtk_widget_grab_focus(text_entry_);
+  // Select all the text.
+  gtk_entry_select_region(GTK_ENTRY(text_entry_), 0, -1);
+}
+
+void FindBarGtk::ClearResults(const FindNotificationDetails& results) {
+  UpdateUIForFindResult(results, string16());
+}
+
+void FindBarGtk::StopAnimation() {
+  slide_widget_->End();
+}
+
+void FindBarGtk::MoveWindowIfNecessary(const gfx::Rect& selection_rect,
+                                       bool no_redraw) {
+  // Not moving the window on demand, so do nothing.
+}
+
+void FindBarGtk::SetFindText(const string16& find_text) {
+  std::string find_text_utf8 = UTF16ToUTF8(find_text);
+
+  // Ignore the "changed" signal handler because programatically setting the
+  // text should not fire a "changed" event.
+  ignore_changed_signal_ = true;
+  gtk_entry_set_text(GTK_ENTRY(text_entry_), find_text_utf8.c_str());
+  ignore_changed_signal_ = false;
+}
+
+void FindBarGtk::UpdateUIForFindResult(const FindNotificationDetails& result,
+                                       const string16& find_text) {
+  if (!result.selection_rect().IsEmpty()) {
+    selection_rect_ = result.selection_rect();
+    int xposition = GetDialogPosition(result.selection_rect()).x();
+    if (xposition != widget()->allocation.x)
+      Reposition();
+  }
+
+  // Once we find a match we no longer want to keep track of what had
+  // focus. EndFindSession will then set the focus to the page content.
+  if (result.number_of_matches() > 0)
+    focus_store_.Store(NULL);
+
+  std::string find_text_utf8 = UTF16ToUTF8(find_text);
+  bool have_valid_range =
+      result.number_of_matches() != -1 && result.active_match_ordinal() != -1;
+
+  std::string entry_text(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
+  if (entry_text != find_text_utf8) {
+    SetFindText(find_text);
+    gtk_entry_select_region(GTK_ENTRY(text_entry_), 0, -1);
+  }
+
+  if (!find_text.empty() && have_valid_range) {
+    gtk_label_set_text(GTK_LABEL(match_count_label_),
+        l10n_util::GetStringFUTF8(IDS_FIND_IN_PAGE_COUNT,
+            base::IntToString16(result.active_match_ordinal()),
+            base::IntToString16(result.number_of_matches())).c_str());
+    UpdateMatchLabelAppearance(result.number_of_matches() == 0 &&
+                               result.final_update());
+  } else {
+    // If there was no text entered, we don't show anything in the result count
+    // area.
+    gtk_label_set_text(GTK_LABEL(match_count_label_), "");
+    UpdateMatchLabelAppearance(false);
+  }
+}
+
+void FindBarGtk::AudibleAlert() {
+  // This call causes a lot of weird bugs, especially when using the custom
+  // frame. TODO(estade): if people complain, re-enable it. See
+  // http://crbug.com/27635 and others.
+  //
+  //   gtk_widget_error_bell(widget());
+}
+
+gfx::Rect FindBarGtk::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
+  bool ltr = !base::i18n::IsRTL();
+  // 15 is the size of the scrollbar, copied from ScrollbarThemeChromium.
+  // The height is not used.
+  // At very low browser widths we can wind up with a negative |dialog_bounds|
+  // width, so clamp it to 0.
+  gfx::Rect dialog_bounds = gfx::Rect(ltr ? 0 : 15, 0,
+      std::max(0, widget()->parent->allocation.width - (ltr ? 15 : 0)), 0);
+
+  GtkRequisition req;
+  gtk_widget_size_request(container_, &req);
+  gfx::Size prefsize(req.width, req.height);
+
+  gfx::Rect view_location(
+      ltr ? dialog_bounds.width() - prefsize.width() : dialog_bounds.x(),
+      dialog_bounds.y(), prefsize.width(), prefsize.height());
+  gfx::Rect new_pos = FindBarController::GetLocationForFindbarView(
+      view_location, dialog_bounds, avoid_overlapping_rect);
+
+  return new_pos;
+}
+
+bool FindBarGtk::IsFindBarVisible() {
+  return GTK_WIDGET_VISIBLE(widget());
+}
+
+void FindBarGtk::RestoreSavedFocus() {
+  // This function sometimes gets called when we don't have focus. We should do
+  // nothing in this case.
+  if (!gtk_widget_is_focus(text_entry_))
+    return;
+
+  if (focus_store_.widget())
+    gtk_widget_grab_focus(focus_store_.widget());
+  else
+    find_bar_controller_->tab_contents()->tab_contents()->Focus();
+}
+
+FindBarTesting* FindBarGtk::GetFindBarTesting() {
+  return this;
+}
+
+void FindBarGtk::Observe(NotificationType type,
+                         const NotificationSource& source,
+                         const NotificationDetails& details) {
+  DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED);
+
+  // Force reshapings of the find bar window.
+  container_width_ = -1;
+  container_height_ = -1;
+
+  if (theme_provider_->UseGtkTheme()) {
+    gtk_widget_modify_cursor(text_entry_, NULL, NULL);
+    gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL, NULL);
+    gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL, NULL);
+
+    // Prevent forced font sizes because it causes the jump up and down
+    // character movement (http://crbug.com/22614), and because it will
+    // prevent centering of the text entry.
+    gtk_util::UndoForceFontSize(text_entry_);
+    gtk_util::UndoForceFontSize(match_count_label_);
+
+    gtk_widget_set_size_request(content_event_box_, -1, -1);
+    gtk_widget_modify_bg(content_event_box_, GTK_STATE_NORMAL, NULL);
+
+    // Replicate the normal GtkEntry behaviour by drawing the entry
+    // background. We set the fake alignment to be the frame thickness.
+    GtkStyle* style = gtk_rc_get_style(text_entry_);
+    gint xborder = style->xthickness;
+    gint yborder = style->ythickness;
+    gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment_),
+                              yborder, yborder, xborder, xborder);
+
+    // We leave left padding on the left, even in GTK mode, as it's required
+    // for the left margin to be equivalent to the bottom margin.
+    gtk_alignment_set_padding(GTK_ALIGNMENT(border_bin_alignment_),
+                              0, 0, 1, 0);
+
+    // We need this event box to have its own window in GTK mode for doing the
+    // hacky widget rendering.
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(border_bin_), TRUE);
+    gtk_widget_set_app_paintable(border_bin_, TRUE);
+
+    gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 0.5);
+  } else {
+    gtk_widget_modify_cursor(
+        text_entry_, &gtk_util::kGdkBlack, &gtk_util::kGdkGray);
+    gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL,
+                           &kEntryBackgroundColor);
+    gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL,
+                           &kEntryTextColor);
+
+    // Until we switch to vector graphics, force the font size.
+    gtk_util::ForceFontSizePixels(text_entry_, 13.4);  // 13.4px == 10pt @ 96dpi
+    gtk_util::ForceFontSizePixels(match_count_label_, 13.4);
+
+    // Force the text widget height so it lines up with the buttons regardless
+    // of font size.
+    gtk_widget_set_size_request(content_event_box_, -1, 20);
+    gtk_widget_modify_bg(content_event_box_, GTK_STATE_NORMAL,
+                         &kEntryBackgroundColor);
+
+    gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment_),
+                              0.0, 0.0, 0.0, 0.0);
+
+    gtk_alignment_set_padding(GTK_ALIGNMENT(border_bin_alignment_),
+                              2, 2, 3, 0);
+
+    // We need this event box to be invisible because we're only going to draw
+    // on the background (but we can't take it out of the heiarchy entirely
+    // because we also need it to take up space).
+    gtk_event_box_set_visible_window(GTK_EVENT_BOX(border_bin_), FALSE);
+    gtk_widget_set_app_paintable(border_bin_, FALSE);
+
+    gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 1.0);
+
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    close_button_->SetBackground(
+        theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT),
+        rb.GetBitmapNamed(IDR_CLOSE_BAR),
+        rb.GetBitmapNamed(IDR_CLOSE_BAR_MASK));
+  }
+
+  UpdateMatchLabelAppearance(match_label_failure_);
+}
+
+bool FindBarGtk::GetFindBarWindowInfo(gfx::Point* position,
+                                      bool* fully_visible) {
+  if (position)
+    *position = GetPosition();
+
+  if (fully_visible) {
+    *fully_visible = !slide_widget_->IsAnimating() &&
+                     slide_widget_->IsShowing();
+  }
+  return true;
+}
+
+string16 FindBarGtk::GetFindText() {
+  std::string contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
+  return UTF8ToUTF16(contents);
+}
+
+string16 FindBarGtk::GetFindSelectedText() {
+  gint cursor_pos;
+  gint selection_bound;
+  g_object_get(G_OBJECT(text_entry_), "cursor-position", &cursor_pos,
+               NULL);
+  g_object_get(G_OBJECT(text_entry_), "selection-bound", &selection_bound,
+               NULL);
+  std::string contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
+  return UTF8ToUTF16(contents.substr(cursor_pos, selection_bound));
+}
+
+string16 FindBarGtk::GetMatchCountText() {
+  std::string contents(gtk_label_get_text(GTK_LABEL(match_count_label_)));
+  return UTF8ToUTF16(contents);
+}
+
+void FindBarGtk::FindEntryTextInContents(bool forward_search) {
+  TabContentsWrapper* tab_contents = find_bar_controller_->tab_contents();
+  if (!tab_contents)
+    return;
+  FindManager* find_manager = tab_contents->GetFindManager();
+
+  std::string new_contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
+
+  if (new_contents.length() > 0) {
+    find_manager->StartFinding(UTF8ToUTF16(new_contents), forward_search,
+                               false);  // Not case sensitive.
+  } else {
+    // The textbox is empty so we reset.
+    find_manager->StopFinding(FindBarController::kClearSelection);
+    UpdateUIForFindResult(find_manager->find_result(), string16());
+
+    // Clearing the text box should also clear the prepopulate state so that
+    // when we close and reopen the Find box it doesn't show the search we
+    // just deleted.
+    FindBarState* find_bar_state = browser_->profile()->GetFindBarState();
+    find_bar_state->set_last_prepopulate_text(string16());
+  }
+}
+
+void FindBarGtk::UpdateMatchLabelAppearance(bool failure) {
+  match_label_failure_ = failure;
+  bool use_gtk = theme_provider_->UseGtkTheme();
+
+  if (use_gtk) {
+    GtkStyle* style = gtk_rc_get_style(text_entry_);
+    GdkColor normal_bg = style->base[GTK_STATE_NORMAL];
+    GdkColor normal_text = gtk_util::AverageColors(
+        style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
+
+    gtk_widget_modify_bg(match_count_event_box_, GTK_STATE_NORMAL,
+                         failure ? &kFindFailureBackgroundColor :
+                         &normal_bg);
+    gtk_widget_modify_fg(match_count_label_, GTK_STATE_NORMAL,
+                         failure ? &kEntryTextColor : &normal_text);
+  } else {
+    gtk_widget_modify_bg(match_count_event_box_, GTK_STATE_NORMAL,
+                         failure ? &kFindFailureBackgroundColor :
+                         &kEntryBackgroundColor);
+    gtk_widget_modify_fg(match_count_label_, GTK_STATE_NORMAL,
+                         failure ? &kEntryTextColor : &kFindSuccessTextColor);
+  }
+}
+
+void FindBarGtk::Reposition() {
+  if (!IsFindBarVisible())
+    return;
+
+  // This will trigger an allocate, which allows us to reposition.
+  if (widget()->parent)
+    gtk_widget_queue_resize(widget()->parent);
+}
+
+void FindBarGtk::StoreOutsideFocus() {
+  // |text_entry_| is the only widget in the find bar that can be focused,
+  // so it's the only one we have to check.
+  // TODO(estade): when we make the find bar buttons focusable, we'll have
+  // to change this (same above in RestoreSavedFocus).
+  if (!gtk_widget_is_focus(text_entry_))
+    focus_store_.Store(text_entry_);
+}
+
+bool FindBarGtk::MaybeForwardKeyEventToRenderer(GdkEventKey* event) {
+  switch (event->keyval) {
+    case GDK_Down:
+    case GDK_Up:
+    case GDK_Page_Up:
+    case GDK_Page_Down:
+      break;
+    case GDK_Home:
+    case GDK_End:
+      if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
+          GDK_CONTROL_MASK) {
+        break;
+      }
+    // Fall through.
+    default:
+      return false;
+  }
+
+  TabContentsWrapper* contents = find_bar_controller_->tab_contents();
+  if (!contents)
+    return false;
+
+  RenderViewHost* render_view_host = contents->render_view_host();
+
+  // Make sure we don't have a text field element interfering with keyboard
+  // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
+  render_view_host->ClearFocusedNode();
+
+  NativeWebKeyboardEvent wke(event);
+  render_view_host->ForwardKeyboardEvent(wke);
+  return true;
+}
+
+void FindBarGtk::AdjustTextAlignment() {
+  PangoDirection content_dir =
+      pango_find_base_dir(gtk_entry_get_text(GTK_ENTRY(text_entry_)), -1);
+
+  GtkTextDirection widget_dir = gtk_widget_get_direction(text_entry_);
+
+  // Use keymap or widget direction if content does not have strong direction.
+  // It matches the behavior of GtkEntry.
+  if (content_dir == PANGO_DIRECTION_NEUTRAL) {
+    if (GTK_WIDGET_HAS_FOCUS(text_entry_)) {
+      content_dir = gdk_keymap_get_direction(
+        gdk_keymap_get_for_display(gtk_widget_get_display(text_entry_)));
+    } else {
+      if (widget_dir == GTK_TEXT_DIR_RTL)
+        content_dir = PANGO_DIRECTION_RTL;
+      else
+        content_dir = PANGO_DIRECTION_LTR;
+    }
+  }
+
+  if ((widget_dir == GTK_TEXT_DIR_RTL && content_dir == PANGO_DIRECTION_LTR) ||
+      (widget_dir == GTK_TEXT_DIR_LTR && content_dir == PANGO_DIRECTION_RTL)) {
+    gtk_entry_set_alignment(GTK_ENTRY(text_entry_), 1.0);
+  } else {
+    gtk_entry_set_alignment(GTK_ENTRY(text_entry_), 0.0);
+  }
+}
+
+gfx::Point FindBarGtk::GetPosition() {
+  gfx::Point point;
+
+  GValue value = { 0, };
+  g_value_init(&value, G_TYPE_INT);
+  gtk_container_child_get_property(GTK_CONTAINER(widget()->parent),
+                                   widget(), "x", &value);
+  point.set_x(g_value_get_int(&value));
+
+  gtk_container_child_get_property(GTK_CONTAINER(widget()->parent),
+                                   widget(), "y", &value);
+  point.set_y(g_value_get_int(&value));
+
+  g_value_unset(&value);
+
+  return point;
+}
+
+// static
+void FindBarGtk::OnParentSet(GtkWidget* widget, GtkObject* old_parent,
+                             FindBarGtk* find_bar) {
+  if (!widget->parent)
+    return;
+
+  g_signal_connect(widget->parent, "set-floating-position",
+                   G_CALLBACK(OnSetFloatingPosition), find_bar);
+}
+
+// static
+void FindBarGtk::OnSetFloatingPosition(
+    GtkFloatingContainer* floating_container,
+    GtkAllocation* allocation,
+    FindBarGtk* find_bar) {
+  GtkWidget* findbar = find_bar->widget();
+
+  int xposition = find_bar->GetDialogPosition(find_bar->selection_rect_).x();
+
+  GValue value = { 0, };
+  g_value_init(&value, G_TYPE_INT);
+  g_value_set_int(&value, xposition);
+  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
+                                   findbar, "x", &value);
+
+  g_value_set_int(&value, 0);
+  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
+                                   findbar, "y", &value);
+  g_value_unset(&value);
+}
+
+// static
+gboolean FindBarGtk::OnChanged(GtkWindow* window, FindBarGtk* find_bar) {
+  find_bar->AdjustTextAlignment();
+
+  if (!find_bar->ignore_changed_signal_)
+    find_bar->FindEntryTextInContents(true);
+
+  return FALSE;
+}
+
+// static
+gboolean FindBarGtk::OnKeyPressEvent(GtkWidget* widget, GdkEventKey* event,
+                                     FindBarGtk* find_bar) {
+  if (find_bar->MaybeForwardKeyEventToRenderer(event)) {
+    return TRUE;
+  } else if (GDK_Escape == event->keyval) {
+    find_bar->find_bar_controller_->EndFindSession(
+        FindBarController::kKeepSelection);
+    return TRUE;
+  } else if (GDK_Return == event->keyval ||
+             GDK_KP_Enter == event->keyval) {
+    if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
+        GDK_CONTROL_MASK) {
+      find_bar->find_bar_controller_->EndFindSession(
+          FindBarController::kActivateSelection);
+      return TRUE;
+    }
+
+    bool forward = (event->state & gtk_accelerator_get_default_mod_mask()) !=
+                   GDK_SHIFT_MASK;
+    find_bar->FindEntryTextInContents(forward);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+// static
+gboolean FindBarGtk::OnKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event,
+                                       FindBarGtk* find_bar) {
+  return find_bar->MaybeForwardKeyEventToRenderer(event);
+}
+
+// static
+void FindBarGtk::OnClicked(GtkWidget* button, FindBarGtk* find_bar) {
+  if (button == find_bar->close_button_->widget()) {
+    find_bar->find_bar_controller_->EndFindSession(
+        FindBarController::kKeepSelection);
+  } else if (button == find_bar->find_previous_button_->widget() ||
+             button == find_bar->find_next_button_->widget()) {
+    find_bar->FindEntryTextInContents(
+        button == find_bar->find_next_button_->widget());
+  } else {
+    NOTREACHED();
+  }
+}
+
+// static
+gboolean FindBarGtk::OnContentEventBoxExpose(GtkWidget* widget,
+                                             GdkEventExpose* event,
+                                             FindBarGtk* bar) {
+  if (bar->theme_provider_->UseGtkTheme()) {
+    // Draw the text entry background around where we input stuff. Note the
+    // decrement to |width|. We do this because some theme engines
+    // (*cough*Clearlooks*cough*) don't do any blending and use thickness to
+    // make sure that widgets never overlap.
+    int padding = gtk_widget_get_style(widget)->xthickness;
+    GdkRectangle rec = {
+      widget->allocation.x,
+      widget->allocation.y,
+      widget->allocation.width - padding,
+      widget->allocation.height
+    };
+
+    gtk_util::DrawTextEntryBackground(bar->text_entry_, widget,
+                                      &event->area, &rec);
+  }
+
+  return FALSE;
+}
+
+// Used to handle custom painting of |container_|.
+gboolean FindBarGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e,
+                              FindBarGtk* bar) {
+  GtkRequisition req;
+  gtk_widget_size_request(widget, &req);
+  gtk_widget_set_size_request(bar->widget(), req.width, -1);
+
+  if (bar->theme_provider_->UseGtkTheme()) {
+    if (bar->container_width_ != widget->allocation.width ||
+        bar->container_height_ != widget->allocation.height) {
+      std::vector<GdkPoint> mask_points = MakeFramePolygonPoints(
+          widget->allocation.width, widget->allocation.height, FRAME_MASK);
+      GdkRegion* mask_region = gdk_region_polygon(&mask_points[0],
+                                                  mask_points.size(),
+                                                  GDK_EVEN_ODD_RULE);
+      // Reset the shape.
+      gdk_window_shape_combine_region(widget->window, NULL, 0, 0);
+      gdk_window_shape_combine_region(widget->window, mask_region, 0, 0);
+      gdk_region_destroy(mask_region);
+
+      bar->container_width_ = widget->allocation.width;
+      bar->container_height_ = widget->allocation.height;
+    }
+
+    GdkDrawable* drawable = GDK_DRAWABLE(e->window);
+    GdkGC* gc = gdk_gc_new(drawable);
+    gdk_gc_set_clip_rectangle(gc, &e->area);
+    GdkColor color = bar->theme_provider_->GetBorderColor();
+    gdk_gc_set_rgb_fg_color(gc, &color);
+
+    // Stroke the frame border.
+    std::vector<GdkPoint> points = MakeFramePolygonPoints(
+        widget->allocation.width, widget->allocation.height, FRAME_STROKE);
+    gdk_draw_lines(drawable, gc, &points[0], points.size());
+
+    g_object_unref(gc);
+  } else {
+    if (bar->container_width_ != widget->allocation.width ||
+        bar->container_height_ != widget->allocation.height) {
+      // Reset the shape.
+      gdk_window_shape_combine_region(widget->window, NULL, 0, 0);
+      SetDialogShape(bar->container_);
+
+      bar->container_width_ = widget->allocation.width;
+      bar->container_height_ = widget->allocation.height;
+    }
+
+    cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+    gdk_cairo_rectangle(cr, &e->area);
+    cairo_clip(cr);
+
+    gfx::Point tabstrip_origin =
+        bar->window_->tabstrip()->GetTabStripOriginForWidget(widget);
+
+    gtk_util::DrawThemedToolbarBackground(widget, cr, e, tabstrip_origin,
+                                          bar->theme_provider_);
+
+    // During chrome theme mode, we need to draw the border around content_hbox
+    // now instead of when we render |border_bin_|. We don't use stacked event
+    // boxes to simulate the effect because we need to blend them with this
+    // background.
+    GtkAllocation border_allocation = bar->border_bin_->allocation;
+
+    // Blit the left part of the background image once on the left.
+    CairoCachedSurface* background_left =
+        bar->theme_provider_->GetRTLEnabledSurfaceNamed(
+        IDR_FIND_BOX_BACKGROUND_LEFT, widget);
+    background_left->SetSource(cr, border_allocation.x, border_allocation.y);
+    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(cr, border_allocation.x, border_allocation.y,
+                    background_left->Width(), background_left->Height());
+    cairo_fill(cr);
+
+    // Blit the center part of the background image in all the space between.
+    CairoCachedSurface* background = bar->theme_provider_->GetSurfaceNamed(
+        IDR_FIND_BOX_BACKGROUND, widget);
+    background->SetSource(cr,
+                          border_allocation.x + background_left->Width(),
+                          border_allocation.y);
+    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(cr,
+                    border_allocation.x + background_left->Width(),
+                    border_allocation.y,
+                    border_allocation.width - background_left->Width(),
+                    background->Height());
+    cairo_fill(cr);
+
+    cairo_destroy(cr);
+
+    // Draw the border.
+    GetDialogBorder()->RenderToWidget(widget);
+  }
+
+  // Propagate to the container's child.
+  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
+  if (child)
+    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
+  return TRUE;
+}
+
+// static
+gboolean FindBarGtk::OnFocus(GtkWidget* text_entry, GtkDirectionType focus,
+                             FindBarGtk* find_bar) {
+  find_bar->StoreOutsideFocus();
+
+  // Continue propagating the event.
+  return FALSE;
+}
+
+// static
+gboolean FindBarGtk::OnButtonPress(GtkWidget* text_entry, GdkEventButton* e,
+                                   FindBarGtk* find_bar) {
+  find_bar->StoreOutsideFocus();
+
+  // Continue propagating the event.
+  return FALSE;
+}
+
+// static
+void FindBarGtk::OnMoveCursor(GtkEntry* entry, GtkMovementStep step, gint count,
+                              gboolean selection, FindBarGtk* bar) {
+  static guint signal_id = g_signal_lookup("move-cursor", GTK_TYPE_ENTRY);
+
+  GdkEvent* event = gtk_get_current_event();
+  if (event) {
+    if ((event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE) &&
+        bar->MaybeForwardKeyEventToRenderer(&(event->key))) {
+      g_signal_stop_emission(entry, signal_id, 0);
+    }
+
+    gdk_event_free(event);
+  }
+}
+
+// static
+void FindBarGtk::OnActivate(GtkEntry* entry, FindBarGtk* bar) {
+  bar->FindEntryTextInContents(true);
+}
+
+// static
+gboolean FindBarGtk::OnFocusIn(GtkWidget* entry, GdkEventFocus* event,
+                               FindBarGtk* find_bar) {
+  g_signal_connect(
+      gdk_keymap_get_for_display(gtk_widget_get_display(entry)),
+      "direction-changed",
+      G_CALLBACK(&OnKeymapDirectionChanged), find_bar);
+
+  find_bar->AdjustTextAlignment();
+
+  return FALSE;  // Continue propagation.
+}
+
+// static
+gboolean FindBarGtk::OnFocusOut(GtkWidget* entry, GdkEventFocus* event,
+                                FindBarGtk* find_bar) {
+  g_signal_handlers_disconnect_by_func(
+      gdk_keymap_get_for_display(gtk_widget_get_display(entry)),
+      reinterpret_cast<gpointer>(&OnKeymapDirectionChanged), find_bar);
+
+  return FALSE;  // Continue propagation.
+}
diff --git a/chrome/browser/ui/gtk/find_bar_gtk.h b/chrome/browser/ui/gtk/find_bar_gtk.h
new file mode 100644
index 0000000..446bf99
--- /dev/null
+++ b/chrome/browser/ui/gtk/find_bar_gtk.h
@@ -0,0 +1,240 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_FIND_BAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_FIND_BAR_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/find_bar/find_bar.h"
+#include "chrome/browser/ui/gtk/focus_store_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/gfx/point.h"
+
+class Browser;
+class BrowserWindowGtk;
+class CustomDrawButton;
+class FindBarController;
+class GtkThemeProvider;
+class NineBox;
+class SlideAnimatorGtk;
+class TabContentsContainerGtk;
+
+typedef struct _GtkFloatingContainer GtkFloatingContainer;
+
+// Currently this class contains both a model and a view.  We may want to
+// eventually pull out the model specific bits and share with Windows.
+class FindBarGtk : public FindBar,
+                   public FindBarTesting,
+                   public NotificationObserver {
+ public:
+  explicit FindBarGtk(Browser* browser);
+  virtual ~FindBarGtk();
+
+  GtkWidget* widget() const { return slide_widget_->widget(); }
+
+  // Methods from FindBar.
+  virtual FindBarController* GetFindBarController() const;
+  virtual void SetFindBarController(FindBarController* find_bar_controller);
+  virtual void Show(bool animate);
+  virtual void Hide(bool animate);
+  virtual void SetFocusAndSelection();
+  virtual void ClearResults(const FindNotificationDetails& results);
+  virtual void StopAnimation();
+  virtual void MoveWindowIfNecessary(const gfx::Rect& selection_rect,
+                                     bool no_redraw);
+  virtual void SetFindText(const string16& find_text);
+  virtual void UpdateUIForFindResult(const FindNotificationDetails& result,
+                                     const string16& find_text);
+  virtual void AudibleAlert();
+  virtual bool IsFindBarVisible();
+  virtual void RestoreSavedFocus();
+  virtual FindBarTesting* GetFindBarTesting();
+
+  // Methods from FindBarTesting.
+  virtual bool GetFindBarWindowInfo(gfx::Point* position,
+                                    bool* fully_visible);
+  virtual string16 GetFindText();
+  virtual string16 GetFindSelectedText();
+  virtual string16 GetMatchCountText();
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  void InitWidgets();
+
+  // Store the currently focused widget if it is not in the find bar.
+  // This should always be called before we claim focus.
+  void StoreOutsideFocus();
+
+  // For certain keystrokes, such as up or down, we want to forward the event
+  // to the renderer rather than handling it ourselves. Returns true if the
+  // key event was forwarded.
+  // See similar function in FindBarWin.
+  bool MaybeForwardKeyEventToRenderer(GdkEventKey* event);
+
+  // Searches for another occurrence of the entry text, moving forward if
+  // |forward_search| is true.
+  void FindEntryTextInContents(bool forward_search);
+
+  void UpdateMatchLabelAppearance(bool failure);
+
+  // Asynchronously repositions the dialog.
+  void Reposition();
+
+  // Returns the rectangle representing where to position the find bar. If
+  // |avoid_overlapping_rect| is specified, the return value will be a rectangle
+  // located immediately to the left of |avoid_overlapping_rect|, as long as
+  // there is enough room for the dialog to draw within the bounds. If not, the
+  // dialog position returned will overlap |avoid_overlapping_rect|.
+  // Note: |avoid_overlapping_rect| is expected to use coordinates relative to
+  // the top of the page area, (it will be converted to coordinates relative to
+  // the top of the browser window, when comparing against the dialog
+  // coordinates). The returned value is relative to the browser window.
+  gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect);
+
+  // Adjust the text alignment according to the text direction of the widget
+  // and |text_entry_|'s content, to make sure the real text alignment is
+  // always in sync with the UI language direction.
+  void AdjustTextAlignment();
+
+  // Get the position of the findbar within the floating container.
+  gfx::Point GetPosition();
+
+  static void OnParentSet(GtkWidget* widget, GtkObject* old_parent,
+                          FindBarGtk* find_bar);
+
+  static void OnSetFloatingPosition(GtkFloatingContainer* floating_container,
+                                    GtkAllocation* allocation,
+                                    FindBarGtk* find_bar);
+
+  // Callback when the entry text changes.
+  static gboolean OnChanged(GtkWindow* window, FindBarGtk* find_bar);
+
+  static gboolean OnKeyPressEvent(GtkWidget* widget, GdkEventKey* event,
+                                  FindBarGtk* find_bar);
+  static gboolean OnKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event,
+                                    FindBarGtk* find_bar);
+
+  // Callback for previous, next, and close button.
+  static void OnClicked(GtkWidget* button, FindBarGtk* find_bar);
+
+  // Handles shapping and drawing the find bar background.
+  static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* event,
+                           FindBarGtk* bar);
+
+  // Expose that draws the text entry background in GTK mode.
+  static gboolean OnContentEventBoxExpose(GtkWidget* widget,
+                                          GdkEventExpose* event,
+                                          FindBarGtk* bar);
+
+  // These are both used for focus management.
+  static gboolean OnFocus(GtkWidget* text_entry, GtkDirectionType focus,
+                          FindBarGtk* find_bar);
+  static gboolean OnButtonPress(GtkWidget* text_entry, GdkEventButton* e,
+                                FindBarGtk* find_bar);
+
+  // Forwards ctrl-Home/End key bindings to the renderer.
+  static void OnMoveCursor(GtkEntry* entry, GtkMovementStep step, gint count,
+                           gboolean selection, FindBarGtk* bar);
+
+  // Handles Enter key.
+  static void OnActivate(GtkEntry* entry, FindBarGtk* bar);
+
+  static void OnWidgetDirectionChanged(GtkWidget* widget,
+                                       GtkTextDirection previous_direction,
+                                       FindBarGtk* find_bar) {
+    find_bar->AdjustTextAlignment();
+  }
+
+  static void OnKeymapDirectionChanged(GdkKeymap* keymap,
+                                       FindBarGtk* find_bar) {
+    find_bar->AdjustTextAlignment();
+  }
+
+  static gboolean OnFocusIn(GtkWidget* entry, GdkEventFocus* event,
+                            FindBarGtk* find_bar);
+
+  static gboolean OnFocusOut(GtkWidget* entry, GdkEventFocus* event,
+                             FindBarGtk* find_bar);
+
+  Browser* browser_;
+  BrowserWindowGtk* window_;
+
+  // Provides colors and information about GTK.
+  GtkThemeProvider* theme_provider_;
+
+  // The widget that animates the slide-in and -out of the findbar.
+  scoped_ptr<SlideAnimatorGtk> slide_widget_;
+
+  // A GtkAlignment that is the child of |slide_widget_|.
+  GtkWidget* container_;
+
+  // Cached allocation of |container_|. We keep this on hand so that we can
+  // reset the widget's shape when the width/height change.
+  int container_width_;
+  int container_height_;
+
+  // The widget where text is entered.
+  GtkWidget* text_entry_;
+
+  // An event box and alignment that wrap the entry area and the count label.
+  GtkWidget* content_event_box_;
+  GtkWidget* content_alignment_;
+
+  // The border around the text entry area.
+  GtkWidget* border_bin_;
+  GtkWidget* border_bin_alignment_;
+
+  // The next and previous match buttons.
+  scoped_ptr<CustomDrawButton> find_previous_button_;
+  scoped_ptr<CustomDrawButton> find_next_button_;
+
+  // The GtkLabel listing how many results were found.
+  GtkWidget* match_count_label_;
+  GtkWidget* match_count_event_box_;
+  // Cache whether the match count label is showing failure or not so that
+  // we can update its appearance without changing its semantics.
+  bool match_label_failure_;
+
+  // The X to close the find bar.
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  // The last matchcount number we reported to the user.
+  int last_reported_matchcount_;
+
+  // Pointer back to the owning controller.
+  FindBarController* find_bar_controller_;
+
+  // Saves where the focus used to be whenever we get it.
+  FocusStoreGtk focus_store_;
+
+  // If true, the change signal for the text entry is ignored.
+  bool ignore_changed_signal_;
+
+  // This is the width of widget(). We cache it so we can recognize whether
+  // allocate signals have changed it, and if so take appropriate actions.
+  int current_fixed_width_;
+
+  scoped_ptr<NineBox> dialog_background_;
+
+  // The selection rect we are currently showing. We cache it to avoid covering
+  // it up.
+  gfx::Rect selection_rect_;
+
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(FindBarGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_FIND_BAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/first_run_bubble.cc b/chrome/browser/ui/gtk/first_run_bubble.cc
new file mode 100644
index 0000000..4cdc7a7
--- /dev/null
+++ b/chrome/browser/ui/gtk/first_run_bubble.cc
@@ -0,0 +1,225 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/first_run_bubble.h"
+
+#include <gtk/gtk.h>
+
+#include "base/command_line.h"
+#include "base/i18n/rtl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/search_engines/util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_service.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+// Markup for the text of the Omnibox search label
+const char kSearchLabelMarkup[] = "<big><b>%s</b></big>";
+
+// Padding for the buttons on first run bubble.
+const int kButtonPadding = 4;
+
+// Padding between content and edge of info bubble.
+const int kContentBorder = 7;
+
+// Vertical spacing between labels.
+const int kInterLineSpacing = 5;
+
+}  // namespace
+
+// static
+void FirstRunBubble::Show(Profile* profile,
+                          GtkWidget* anchor,
+                          const gfx::Rect& rect,
+                          FirstRun::BubbleType bubble_type) {
+  new FirstRunBubble(profile, anchor, rect, bubble_type);
+}
+
+void FirstRunBubble::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                       bool closed_by_escape) {
+  // TODO(port): Enable parent window
+}
+
+bool FirstRunBubble::CloseOnEscape() {
+  return true;
+}
+
+void FirstRunBubble::Observe(NotificationType type,
+                             const NotificationSource& source,
+                             const NotificationDetails& details) {
+  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+
+  if (theme_provider_->UseGtkTheme()) {
+    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
+         it != labels_.end(); ++it) {
+      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
+    }
+  } else {
+    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
+         it != labels_.end(); ++it) {
+      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+    }
+  }
+}
+
+FirstRunBubble::FirstRunBubble(Profile* profile,
+                               GtkWidget* anchor,
+                               const gfx::Rect& rect,
+                               FirstRun::BubbleType bubble_type)
+    : profile_(profile),
+      theme_provider_(GtkThemeProvider::GetFrom(profile_)),
+      anchor_(anchor),
+      content_(NULL),
+      bubble_(NULL) {
+  content_ = gtk_vbox_new(FALSE, kInterLineSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(content_), kContentBorder);
+  g_signal_connect(content_, "destroy",
+                   G_CALLBACK(&HandleDestroyThunk), this);
+
+  int width_resource = 0;
+  if (bubble_type == FirstRun::LARGE_BUBBLE) {
+    width_resource = IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS;
+    InitializeContentForLarge();
+  } else if (bubble_type == FirstRun::OEM_BUBBLE) {
+    width_resource = IDS_FIRSTRUNOEMBUBBLE_DIALOG_WIDTH_CHARS;
+    InitializeContentForOEM();
+  } else if (bubble_type == FirstRun::MINIMAL_BUBBLE) {
+    width_resource = IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_WIDTH_CHARS;
+    InitializeContentForMinimal();
+  } else {
+    NOTREACHED();
+  }
+
+  InitializeLabels(width_resource);
+
+  InfoBubbleGtk::ArrowLocationGtk arrow_location =
+      !base::i18n::IsRTL() ?
+      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
+      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
+  bubble_ = InfoBubbleGtk::Show(anchor_,
+                                &rect,
+                                content_,
+                                arrow_location,
+                                true,  // match_system_theme
+                                true,  // grab_input
+                                theme_provider_,
+                                this);  // delegate
+  if (!bubble_) {
+    NOTREACHED();
+    return;
+  }
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_->InitThemesFor(this);
+}
+
+FirstRunBubble::~FirstRunBubble() {
+}
+
+void FirstRunBubble::InitializeContentForLarge() {
+  GtkWidget* label1 = gtk_label_new(NULL);
+  labels_.push_back(label1);
+  char* markup = g_markup_printf_escaped(kSearchLabelMarkup,
+      l10n_util::GetStringUTF8(IDS_FR_BUBBLE_TITLE).c_str());
+  gtk_label_set_markup(GTK_LABEL(label1), markup);
+  g_free(markup);
+
+  GtkWidget* label2 = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_FR_BUBBLE_SUBTEXT).c_str());
+  labels_.push_back(label2);
+
+  string16 search_engine = GetDefaultSearchEngineName(profile_);
+  GtkWidget* label3 = gtk_label_new(
+      l10n_util::GetStringFUTF8(IDS_FR_BUBBLE_QUESTION, search_engine).c_str());
+  labels_.push_back(label3);
+
+  GtkWidget* keep_button = gtk_button_new_with_label(
+      l10n_util::GetStringFUTF8(IDS_FR_BUBBLE_OK, search_engine).c_str());
+  GtkWidget* change_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_FR_BUBBLE_CHANGE).c_str());
+
+  gtk_box_pack_start(GTK_BOX(content_), label1, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(content_), label2, FALSE, FALSE, 0);
+  // Leave an empty line.
+  gtk_box_pack_start(GTK_BOX(content_), gtk_label_new(NULL), FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(content_), label3, FALSE, FALSE, 0);
+
+  GtkWidget* bottom = gtk_hbox_new(FALSE, 0);
+  // We want the buttons on the right, so just use an expanding label to fill
+  // all of the extra space on the left.
+  gtk_box_pack_start(GTK_BOX(bottom), gtk_label_new(NULL), TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(bottom), keep_button, FALSE, FALSE,
+                     kButtonPadding);
+  gtk_box_pack_start(GTK_BOX(bottom), change_button, FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(content_), bottom, FALSE, FALSE, 0);
+  // We want the focus to start on the keep entry, not on the change button.
+  gtk_widget_grab_focus(keep_button);
+
+  g_signal_connect(keep_button, "clicked",
+                   G_CALLBACK(&HandleKeepButtonThunk), this);
+  g_signal_connect(change_button, "clicked",
+                   G_CALLBACK(&HandleChangeButtonThunk), this);
+}
+
+void FirstRunBubble::InitializeContentForOEM() {
+  NOTIMPLEMENTED() << "Falling back to minimal bubble";
+  InitializeContentForMinimal();
+}
+
+void FirstRunBubble::InitializeContentForMinimal() {
+  GtkWidget* label1 = gtk_label_new(NULL);
+  labels_.push_back(label1);
+  char* markup = g_markup_printf_escaped(kSearchLabelMarkup,
+      l10n_util::GetStringFUTF8(
+          IDS_FR_SE_BUBBLE_TITLE,
+          GetDefaultSearchEngineName(profile_)).c_str());
+  gtk_label_set_markup(GTK_LABEL(label1), markup);
+  g_free(markup);
+
+  GtkWidget* label2 =
+      gtk_label_new(l10n_util::GetStringUTF8(IDS_FR_BUBBLE_SUBTEXT).c_str());
+  labels_.push_back(label2);
+
+  gtk_box_pack_start(GTK_BOX(content_), label1, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(content_), label2, FALSE, FALSE, 0);
+}
+
+void FirstRunBubble::InitializeLabels(int width_resource) {
+  int width = -1;
+
+  gtk_util::GetWidgetSizeFromResources(
+      anchor_, width_resource, 0, &width, NULL);
+
+  for (size_t i = 0; i < labels_.size(); ++i) {
+    // Resize the labels so that they don't wrap more than necessary.  We leave
+    // |content_| unsized so that it'll expand as needed to hold the other
+    // widgets -- the buttons may be wider than |width| on high-DPI displays.
+    gtk_util::SetLabelWidth(labels_[i], width);
+  }
+}
+
+void FirstRunBubble::HandleDestroy(GtkWidget* sender) {
+  content_ = NULL;
+  delete this;
+}
+
+void FirstRunBubble::HandleKeepButton(GtkWidget* sender) {
+  bubble_->Close();
+}
+
+void FirstRunBubble::HandleChangeButton(GtkWidget* sender) {
+  bubble_->Close();
+  Browser* browser = BrowserList::GetLastActive();
+  DCHECK(browser);
+  browser->OpenSearchEngineOptionsDialog();
+}
diff --git a/chrome/browser/ui/gtk/first_run_bubble.h b/chrome/browser/ui/gtk/first_run_bubble.h
new file mode 100644
index 0000000..36fe237
--- /dev/null
+++ b/chrome/browser/ui/gtk/first_run_bubble.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 The Chromium 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 the GTK implementation of the First Run bubble, the dialog box
+// presented on first run of Chromium. There can only ever be a single
+// bubble open, so the class presents only static methods.
+
+#ifndef CHROME_BROWSER_UI_GTK_FIRST_RUN_BUBBLE_H_
+#define CHROME_BROWSER_UI_GTK_FIRST_RUN_BUBBLE_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class Profile;
+
+class FirstRunBubble : public InfoBubbleGtkDelegate,
+                       public NotificationObserver {
+ public:
+  // Shows the first run bubble, pointing at |rect|.
+  static void Show(Profile* profile,
+                   GtkWidget* anchor,
+                   const gfx::Rect& rect,
+                   FirstRun::BubbleType bubble_type);
+
+  // Implements the InfoBubbleGtkDelegate.  We are notified when the bubble
+  // is about to be closed.
+  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                 bool closed_by_escape);
+  virtual bool CloseOnEscape();
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  FirstRunBubble(Profile* profile,
+                 GtkWidget* anchor,
+                 const gfx::Rect& rect,
+                 FirstRun::BubbleType bubble_type);
+  virtual ~FirstRunBubble();
+
+  // Create and pack widgets for different bubble types.
+  void InitializeContentForLarge();
+  void InitializeContentForOEM();
+  void InitializeContentForMinimal();
+
+  // Contains some common set up for the labels in the bubble. |width| is a
+  // resource that holds the desired width for the labels.
+  void InitializeLabels(int width_resource);
+
+  CHROMEGTK_CALLBACK_0(FirstRunBubble, void, HandleDestroy);
+  CHROMEGTK_CALLBACK_0(FirstRunBubble, void, HandleKeepButton);
+  CHROMEGTK_CALLBACK_0(FirstRunBubble, void, HandleChangeButton);
+
+  // Our current profile.
+  Profile* profile_;
+
+  // Provides colors and stuff.
+  GtkThemeProvider* theme_provider_;
+
+  // The widget we anchor to, and a descendant of the toplevel window we
+  // are transient for.
+  GtkWidget* anchor_;
+
+  // We let the InfoBubble own our content, and then we delete ourself
+  // when the widget is destroyed (when the InfoBubble is destroyed).
+  GtkWidget* content_;
+
+  // The various labels in the interface. We keep track of them for theme
+  // changes.
+  std::vector<GtkWidget*> labels_;
+
+  InfoBubbleGtk* bubble_;
+
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(FirstRunBubble);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_FIRST_RUN_BUBBLE_H_
diff --git a/chrome/browser/ui/gtk/first_run_dialog.cc b/chrome/browser/ui/gtk/first_run_dialog.cc
new file mode 100644
index 0000000..ae56ea9
--- /dev/null
+++ b/chrome/browser/ui/gtk/first_run_dialog.cc
@@ -0,0 +1,425 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/first_run_dialog.h"
+
+#include <string>
+#include <vector>
+
+#include "base/i18n/rtl.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/process_singleton.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_floating_container.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if defined(USE_LINUX_BREAKPAD)
+#include "chrome/app/breakpad_linux.h"
+#endif
+
+#if defined(GOOGLE_CHROME_BUILD)
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#endif
+
+namespace {
+
+const gchar* kSearchEngineKey = "template-url-search-engine";
+
+// Height of the label that displays the search engine's logo (in lieu of the
+// actual logo) in chromium.
+const int kLogoLabelHeight = 100;
+
+// Size of the small logo (for when we show 4 search engines).
+const int kLogoLabelWidthSmall = 132;
+const int kLogoLabelHeightSmall = 88;
+
+// The number of search engine options we normally show. It may be less than
+// this number if there are not enough search engines for the current locale,
+// or more if the user's imported default is not one of the top search engines
+// for the current locale.
+const size_t kNormalBallotSize = 3;
+
+// The width of the explanatory label. The 180 is the width of the large images.
+const int kExplanationWidth = kNormalBallotSize * 180;
+
+// Horizontal spacing between search engine choices.
+const int kSearchEngineSpacing = 6;
+
+// Set the (x, y) coordinates of the welcome message (which floats on top of
+// the omnibox image at the top of the first run dialog).
+void SetWelcomePosition(GtkFloatingContainer* container,
+                        GtkAllocation* allocation,
+                        GtkWidget* label) {
+  GValue value = { 0, };
+  g_value_init(&value, G_TYPE_INT);
+
+  GtkRequisition req;
+  gtk_widget_size_request(label, &req);
+
+  int x = base::i18n::IsRTL() ?
+      allocation->width - req.width - gtk_util::kContentAreaSpacing :
+      gtk_util::kContentAreaSpacing;
+  g_value_set_int(&value, x);
+  gtk_container_child_set_property(GTK_CONTAINER(container),
+                                   label, "x", &value);
+
+  int y = allocation->height / 2 - req.height / 2;
+  g_value_set_int(&value, y);
+  gtk_container_child_set_property(GTK_CONTAINER(container),
+                                   label, "y", &value);
+  g_value_unset(&value);
+}
+
+}  // namespace
+
+// static
+bool FirstRunDialog::Show(Profile* profile,
+                          bool randomize_search_engine_order) {
+  // Figure out which dialogs we will show.
+  // If the default search is managed via policy, we won't ask.
+  const TemplateURLModel* search_engines_model = profile->GetTemplateURLModel();
+  bool show_search_engines_dialog = search_engines_model &&
+      !search_engines_model->is_default_search_managed();
+
+#if defined(GOOGLE_CHROME_BUILD)
+  // If the metrics reporting is managed, we won't ask.
+  const PrefService::Preference* metrics_reporting_pref =
+      g_browser_process->local_state()->FindPreference(
+          prefs::kMetricsReportingEnabled);
+  bool show_reporting_dialog = !metrics_reporting_pref ||
+      !metrics_reporting_pref->IsManaged();
+#else
+  bool show_reporting_dialog = false;
+#endif
+
+  if (!show_search_engines_dialog && !show_reporting_dialog)
+    return true;  // Nothing to do
+
+  int response = -1;
+  // Object deletes itself.
+  new FirstRunDialog(profile,
+                     show_reporting_dialog,
+                     show_search_engines_dialog,
+                     &response);
+
+  // TODO(port): it should be sufficient to just run the dialog:
+  // int response = gtk_dialog_run(GTK_DIALOG(dialog));
+  // but that spins a nested message loop and hoses us.  :(
+  // http://code.google.com/p/chromium/issues/detail?id=12552
+  // Instead, run a loop and extract the response manually.
+  MessageLoop::current()->Run();
+
+  return (response == GTK_RESPONSE_ACCEPT);
+}
+
+FirstRunDialog::FirstRunDialog(Profile* profile,
+                               bool show_reporting_dialog,
+                               bool show_search_engines_dialog,
+                               int* response)
+    : search_engine_window_(NULL),
+      dialog_(NULL),
+      report_crashes_(NULL),
+      make_default_(NULL),
+      profile_(profile),
+      chosen_search_engine_(NULL),
+      show_reporting_dialog_(show_reporting_dialog),
+      response_(response) {
+  if (!show_search_engines_dialog) {
+    ShowReportingDialog();
+    return;
+  }
+  search_engines_model_ = profile_->GetTemplateURLModel();
+
+  ShowSearchEngineWindow();
+
+  search_engines_model_->AddObserver(this);
+  if (search_engines_model_->loaded())
+    OnTemplateURLModelChanged();
+  else
+    search_engines_model_->Load();
+}
+
+FirstRunDialog::~FirstRunDialog() {
+}
+
+void FirstRunDialog::ShowSearchEngineWindow() {
+  search_engine_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_deletable(GTK_WINDOW(search_engine_window_), FALSE);
+  gtk_window_set_title(
+      GTK_WINDOW(search_engine_window_),
+      l10n_util::GetStringUTF8(IDS_FIRSTRUN_DLG_TITLE).c_str());
+  gtk_window_set_resizable(GTK_WINDOW(search_engine_window_), FALSE);
+  g_signal_connect(search_engine_window_, "destroy",
+                   G_CALLBACK(OnSearchEngineWindowDestroyThunk), this);
+  GtkWidget* content_area = gtk_vbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(search_engine_window_), content_area);
+
+  GdkPixbuf* pixbuf =
+      ResourceBundle::GetSharedInstance().GetRTLEnabledPixbufNamed(
+          IDR_SEARCH_ENGINE_DIALOG_TOP);
+  GtkWidget* top_image = gtk_image_new_from_pixbuf(pixbuf);
+  // Right align the image.
+  gtk_misc_set_alignment(GTK_MISC(top_image), 1, 0);
+  gtk_widget_set_size_request(top_image, 0, -1);
+
+  GtkWidget* welcome_message = gtk_util::CreateBoldLabel(
+      l10n_util::GetStringUTF8(IDS_FR_SEARCH_MAIN_LABEL));
+  // Force the font size to make sure the label doesn't overlap the image.
+  // 13.4px == 10pt @ 96dpi
+  gtk_util::ForceFontSizePixels(welcome_message, 13.4);
+
+  GtkWidget* top_area = gtk_floating_container_new();
+  gtk_container_add(GTK_CONTAINER(top_area), top_image);
+  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(top_area),
+                                      welcome_message);
+  g_signal_connect(top_area, "set-floating-position",
+                   G_CALLBACK(SetWelcomePosition), welcome_message);
+
+  gtk_box_pack_start(GTK_BOX(content_area), top_area,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* bubble_area_background = gtk_event_box_new();
+  gtk_widget_modify_bg(bubble_area_background,
+                       GTK_STATE_NORMAL, &gtk_util::kGdkWhite);
+
+  GtkWidget* bubble_area_box = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(bubble_area_box),
+                                 gtk_util::kContentAreaSpacing);
+  gtk_container_add(GTK_CONTAINER(bubble_area_background),
+                    bubble_area_box);
+
+  GtkWidget* explanation = gtk_label_new(
+      l10n_util::GetStringFUTF8(IDS_FR_SEARCH_TEXT,
+          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
+  gtk_util::SetLabelColor(explanation, &gtk_util::kGdkBlack);
+  gtk_util::SetLabelWidth(explanation, kExplanationWidth);
+  gtk_box_pack_start(GTK_BOX(bubble_area_box), explanation, FALSE, FALSE, 0);
+
+  // We will fill this in after the TemplateURLModel has loaded.
+  // GtkHButtonBox because we want all children to have the same size.
+  search_engine_hbox_ = gtk_hbutton_box_new();
+  gtk_box_set_spacing(GTK_BOX(search_engine_hbox_), kSearchEngineSpacing);
+  gtk_box_pack_start(GTK_BOX(bubble_area_box), search_engine_hbox_,
+                     FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(content_area), bubble_area_background,
+                     TRUE, TRUE, 0);
+
+  gtk_widget_show_all(content_area);
+  gtk_window_present(GTK_WINDOW(search_engine_window_));
+}
+
+void FirstRunDialog::ShowReportingDialog() {
+  // The purpose of the dialog is to ask the user to enable stats and crash
+  // reporting. This setting may be controlled through configuration management
+  // in enterprise scenarios. If that is the case, skip the dialog entirely,
+  // it's not worth bothering the user for only the default browser question
+  // (which is likely to be forced in enterprise deployments anyway).
+  if (!show_reporting_dialog_) {
+    OnResponseDialog(NULL, GTK_RESPONSE_ACCEPT);
+    return;
+  }
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_FIRSTRUN_DLG_TITLE).c_str(),
+      NULL,  // No parent
+      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      NULL);
+  gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(IDS_FIRSTRUN_DLG_OK).c_str(),
+      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
+  gtk_window_set_deletable(GTK_WINDOW(dialog_), FALSE);
+
+  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+
+  g_signal_connect(dialog_, "delete-event",
+                   G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+
+  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
+
+  make_default_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_FR_CUSTOMIZE_DEFAULT_BROWSER).c_str());
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(make_default_), TRUE);
+  gtk_box_pack_start(GTK_BOX(content_area), make_default_, FALSE, FALSE, 0);
+
+  report_crashes_ = gtk_check_button_new();
+  GtkWidget* check_label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ENABLE_LOGGING).c_str());
+  gtk_label_set_line_wrap(GTK_LABEL(check_label), TRUE);
+  gtk_container_add(GTK_CONTAINER(report_crashes_), check_label);
+  GtkWidget* learn_more_vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(learn_more_vbox), report_crashes_,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
+  gtk_button_set_alignment(GTK_BUTTON(learn_more_link), 0.0, 0.5);
+  gtk_box_pack_start(GTK_BOX(learn_more_vbox),
+                     gtk_util::IndentWidget(learn_more_link),
+                     FALSE, FALSE, 0);
+  g_signal_connect(learn_more_link, "clicked",
+                   G_CALLBACK(OnLearnMoreLinkClickedThunk), this);
+
+  gtk_box_pack_start(GTK_BOX(content_area), learn_more_vbox, FALSE, FALSE, 0);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnResponseDialogThunk), this);
+  gtk_widget_show_all(dialog_);
+}
+
+void FirstRunDialog::OnTemplateURLModelChanged() {
+  // We only watch the search engine model change once, on load.  Remove
+  // observer so we don't try to redraw if engines change under us.
+  search_engines_model_->RemoveObserver(this);
+
+  // Add search engines in |search_engines_model_| to buttons list.
+  std::vector<const TemplateURL*> ballot_engines =
+      search_engines_model_->GetTemplateURLs();
+  // Drop any not in the first 3.
+  if (ballot_engines.size() > kNormalBallotSize)
+    ballot_engines.resize(kNormalBallotSize);
+
+  const TemplateURL* default_search_engine =
+      search_engines_model_->GetDefaultSearchProvider();
+  if (std::find(ballot_engines.begin(),
+                ballot_engines.end(),
+                default_search_engine) ==
+      ballot_engines.end()) {
+    ballot_engines.push_back(default_search_engine);
+  }
+
+  std::string choose_text = l10n_util::GetStringUTF8(IDS_FR_SEARCH_CHOOSE);
+  for (std::vector<const TemplateURL*>::iterator search_engine_iter =
+           ballot_engines.begin();
+       search_engine_iter < ballot_engines.end();
+       ++search_engine_iter) {
+    // Create a container for the search engine widgets.
+    GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+    // We show text on Chromium and images on Google Chrome.
+    bool show_images = false;
+#if defined(GOOGLE_CHROME_BUILD)
+    show_images = true;
+#endif
+
+    // Create the image (maybe).
+    int logo_id = (*search_engine_iter)->logo_id();
+    if (show_images && logo_id > 0) {
+      GdkPixbuf* pixbuf =
+          ResourceBundle::GetSharedInstance().GetPixbufNamed(logo_id);
+      if (ballot_engines.size() > kNormalBallotSize) {
+        pixbuf = gdk_pixbuf_scale_simple(pixbuf,
+                                         kLogoLabelWidthSmall,
+                                         kLogoLabelHeightSmall,
+                                         GDK_INTERP_HYPER);
+      } else {
+        g_object_ref(pixbuf);
+      }
+
+      GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
+      gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
+      g_object_unref(pixbuf);
+    } else {
+      GtkWidget* logo_label = gtk_label_new(NULL);
+      char* markup = g_markup_printf_escaped(
+          "<span weight='bold' size='x-large' color='black'>%s</span>",
+          UTF16ToUTF8((*search_engine_iter)->short_name()).c_str());
+      gtk_label_set_markup(GTK_LABEL(logo_label), markup);
+      g_free(markup);
+      gtk_widget_set_size_request(logo_label, -1,
+          ballot_engines.size() > kNormalBallotSize ? kLogoLabelHeightSmall :
+                                                      kLogoLabelHeight);
+      gtk_box_pack_start(GTK_BOX(vbox), logo_label, FALSE, FALSE, 0);
+    }
+
+    // Create the button.
+    GtkWidget* button = gtk_button_new_with_label(choose_text.c_str());
+    g_signal_connect(button, "clicked",
+                     G_CALLBACK(OnSearchEngineButtonClickedThunk), this);
+    g_object_set_data(G_OBJECT(button), kSearchEngineKey,
+                      const_cast<TemplateURL*>(*search_engine_iter));
+
+    GtkWidget* button_centerer = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(button_centerer), button, TRUE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), button_centerer, FALSE, FALSE, 0);
+
+    gtk_container_add(GTK_CONTAINER(search_engine_hbox_), vbox);
+    gtk_widget_show_all(search_engine_hbox_);
+  }
+}
+
+void FirstRunDialog::OnSearchEngineButtonClicked(GtkWidget* sender) {
+  chosen_search_engine_ = static_cast<TemplateURL*>(
+      g_object_get_data(G_OBJECT(sender), kSearchEngineKey));
+  gtk_widget_destroy(search_engine_window_);
+}
+
+void FirstRunDialog::OnSearchEngineWindowDestroy(GtkWidget* sender) {
+  search_engine_window_ = NULL;
+  if (chosen_search_engine_) {
+    search_engines_model_->SetDefaultSearchProvider(chosen_search_engine_);
+    ShowReportingDialog();
+  } else {
+    FirstRunDone();
+  }
+}
+
+void FirstRunDialog::OnResponseDialog(GtkWidget* widget, int response) {
+  if (dialog_)
+    gtk_widget_hide_all(dialog_);
+  *response_ = response;
+
+  // Mark that first run has ran.
+  FirstRun::CreateSentinel();
+
+  // Check if user has opted into reporting.
+  if (report_crashes_ &&
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(report_crashes_))) {
+#if defined(USE_LINUX_BREAKPAD)
+    if (GoogleUpdateSettings::SetCollectStatsConsent(true))
+      InitCrashReporter();
+#endif
+  } else {
+    GoogleUpdateSettings::SetCollectStatsConsent(false);
+  }
+
+  // If selected set as default browser.
+  if (make_default_ &&
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(make_default_))) {
+    ShellIntegration::SetAsDefaultBrowser();
+  }
+
+  FirstRunDone();
+}
+
+void FirstRunDialog::OnLearnMoreLinkClicked(GtkButton* button) {
+  platform_util::OpenExternal(google_util::AppendGoogleLocaleParam(
+      GURL(chrome::kLearnMoreReportingURL)));
+}
+
+void FirstRunDialog::FirstRunDone() {
+  FirstRun::SetShowWelcomePagePref();
+
+  if (dialog_)
+    gtk_widget_destroy(dialog_);
+  MessageLoop::current()->Quit();
+  delete this;
+}
diff --git a/chrome/browser/ui/gtk/first_run_dialog.h b/chrome/browser/ui/gtk/first_run_dialog.h
new file mode 100644
index 0000000..0718ddf
--- /dev/null
+++ b/chrome/browser/ui/gtk/first_run_dialog.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_GTK_FIRST_RUN_DIALOG_H_
+#define CHROME_BROWSER_UI_GTK_FIRST_RUN_DIALOG_H_
+#pragma once
+
+typedef struct _GtkButton GtkButton;
+typedef struct _GtkWidget GtkWidget;
+
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/search_engines/template_url_model_observer.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class TemplateURL;
+class TemplateURLModel;
+
+class FirstRunDialog : public TemplateURLModelObserver {
+ public:
+  // Displays the first run UI for reporting opt-in, import data etc.
+  static bool Show(Profile* profile, bool randomize_search_engine_order);
+
+  virtual void OnTemplateURLModelChanged();
+
+ private:
+  FirstRunDialog(Profile* profile,
+                 bool show_reporting_dialog,
+                 bool show_search_engines_dialog,
+                 int* response);
+  virtual ~FirstRunDialog();
+
+  CHROMEGTK_CALLBACK_1(FirstRunDialog, void, OnResponseDialog, int);
+  CHROMEGTK_CALLBACK_0(FirstRunDialog, void, OnSearchEngineButtonClicked);
+  CHROMEGTK_CALLBACK_0(FirstRunDialog, void, OnSearchEngineWindowDestroy);
+  CHROMEG_CALLBACK_0(FirstRunDialog, void, OnLearnMoreLinkClicked, GtkButton*);
+
+  void ShowSearchEngineWindow();
+  void ShowReportingDialog();
+
+  // This method closes the first run window and quits the message loop so that
+  // the Chrome startup can continue. This should be called when all the
+  // first run tasks are done.
+  void FirstRunDone();
+
+  // The search engine choice window. This is created and shown before
+  // |dialog_|.
+  GtkWidget* search_engine_window_;
+
+  // Dialog that holds the bug reporting and default browser checkboxes.
+  GtkWidget* dialog_;
+
+  // Container for the search engine choices.
+  GtkWidget* search_engine_hbox_;
+
+  // Crash reporting checkbox
+  GtkWidget* report_crashes_;
+
+  // Make browser default checkbox
+  GtkWidget* make_default_;
+
+  // Our current profile
+  Profile* profile_;
+
+  // Owned by the profile_.
+  TemplateURLModel* search_engines_model_;
+
+  // The search engine the user chose, or NULL if the user has not chosen a
+  // search engine.
+  TemplateURL* chosen_search_engine_;
+
+  // Whether we should show the dialog asking the user whether to report
+  // crashes and usage stats.
+  bool show_reporting_dialog_;
+
+  // User response (accept or cancel) is returned through this.
+  int* response_;
+
+  DISALLOW_COPY_AND_ASSIGN(FirstRunDialog);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_FIRST_RUN_DIALOG_H_
diff --git a/chrome/browser/ui/gtk/focus_store_gtk.cc b/chrome/browser/ui/gtk/focus_store_gtk.cc
new file mode 100644
index 0000000..7eb9047
--- /dev/null
+++ b/chrome/browser/ui/gtk/focus_store_gtk.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/focus_store_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/platform_util.h"
+
+FocusStoreGtk::FocusStoreGtk()
+    : widget_(NULL),
+      destroy_handler_id_(0) {
+}
+
+FocusStoreGtk::~FocusStoreGtk() {
+  DisconnectDestroyHandler();
+}
+
+void FocusStoreGtk::Store(GtkWidget* widget) {
+  GtkWidget* focus_widget = NULL;
+  if (widget) {
+    GtkWindow* window = platform_util::GetTopLevel(widget);
+    if (window)
+      focus_widget = window->focus_widget;
+  }
+
+  SetWidget(focus_widget);
+}
+
+void FocusStoreGtk::SetWidget(GtkWidget* widget) {
+  DisconnectDestroyHandler();
+
+  // We don't add a ref. The signal handler below effectively gives us a weak
+  // reference.
+  widget_ = widget;
+  if (widget_) {
+    // When invoked, |gtk_widget_destroyed| will set |widget_| to NULL.
+    destroy_handler_id_ = g_signal_connect(widget_, "destroy",
+                                           G_CALLBACK(gtk_widget_destroyed),
+                                           &widget_);
+  }
+}
+
+void FocusStoreGtk::DisconnectDestroyHandler() {
+  if (widget_) {
+    g_signal_handler_disconnect(widget_, destroy_handler_id_);
+    widget_ = NULL;
+  }
+}
diff --git a/chrome/browser/ui/gtk/focus_store_gtk.h b/chrome/browser/ui/gtk/focus_store_gtk.h
new file mode 100644
index 0000000..012332e
--- /dev/null
+++ b/chrome/browser/ui/gtk/focus_store_gtk.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_FOCUS_STORE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_FOCUS_STORE_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class FocusStoreGtk {
+ public:
+  FocusStoreGtk();
+
+  virtual ~FocusStoreGtk();
+
+  GtkWidget* widget() const { return widget_; }
+
+  // Save the widget that is currently focused for |widget|'s toplevel (NOT
+  // |widget|).
+  void Store(GtkWidget* widget);
+
+  // Save |widget| as the focus widget. Call with NULL to clear |widget_|.
+  void SetWidget(GtkWidget* widget);
+
+ private:
+  // Disconnect the previous destroy handler (if any).
+  void DisconnectDestroyHandler();
+
+  // The widget which last had focus.
+  GtkWidget* widget_;
+
+  // The widget for which we've stored focus might be destroyed by the time we
+  // want to restore focus. Thus we connect to the "destroy" signal on that
+  // widget. This is the ID for the destroy handler.
+  unsigned int destroy_handler_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(FocusStoreGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_FOCUS_STORE_GTK_H_
diff --git a/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.cc b/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.cc
new file mode 100644
index 0000000..fec4b12
--- /dev/null
+++ b/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.cc
@@ -0,0 +1,107 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h"
+
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_floating_container.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "grit/app_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Padding around the link text.
+const int kPaddingPixels = 8;
+
+// Time before the link slides away. This is a bit longer than the Windows
+// timeout because we don't yet support reshowing when the mouse moves to the
+// of the screen.
+const int kInitialDelayMs = 3000;
+
+// How long the slide up animation takes when hiding the bubble.
+const int kSlideOutDurationMs = 700;
+
+}
+
+FullscreenExitBubbleGtk::FullscreenExitBubbleGtk(
+    GtkFloatingContainer* container)
+    : container_(container) {
+  InitWidgets();
+}
+
+FullscreenExitBubbleGtk::~FullscreenExitBubbleGtk() {
+}
+
+void FullscreenExitBubbleGtk::InitWidgets() {
+  // The exit bubble is a gtk_chrome_link_button inside a gtk event box and gtk
+  // alignment (these provide the background color).  This is then made rounded
+  // and put into a slide widget.
+
+  // The Windows code actually looks up the accelerator key in the accelerator
+  // table and then converts the key to a string (in a switch statement).
+  std::string exit_text_utf8("<span color=\"white\" size=\"large\">");
+  exit_text_utf8.append(l10n_util::GetStringFUTF8(
+      IDS_EXIT_FULLSCREEN_MODE, l10n_util::GetStringUTF16(IDS_APP_F11_KEY)));
+  exit_text_utf8.append("</span>");
+  GtkWidget* link = gtk_chrome_link_button_new_with_markup(
+      exit_text_utf8.c_str());
+  gtk_chrome_link_button_set_use_gtk_theme(GTK_CHROME_LINK_BUTTON(link),
+                                           FALSE);
+  signals_.Connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
+
+  GtkWidget* container = gtk_util::CreateGtkBorderBin(
+      link, &gtk_util::kGdkBlack,
+      kPaddingPixels, kPaddingPixels, kPaddingPixels, kPaddingPixels);
+  gtk_util::ActAsRoundedWindow(container, gtk_util::kGdkGreen, kPaddingPixels,
+      gtk_util::ROUNDED_BOTTOM_LEFT | gtk_util::ROUNDED_BOTTOM_RIGHT,
+      gtk_util::BORDER_NONE);
+
+  slide_widget_.reset(new SlideAnimatorGtk(container,
+      SlideAnimatorGtk::DOWN, kSlideOutDurationMs, false, false, NULL));
+  gtk_widget_set_name(widget(), "exit-fullscreen-bubble");
+  gtk_widget_show_all(container);
+  gtk_widget_show(widget());
+  slide_widget_->OpenWithoutAnimation();
+
+  // TODO(tc): Implement the more complex logic in the windows version for
+  // when to show/hide the exit bubble.
+  initial_delay_.Start(base::TimeDelta::FromMilliseconds(kInitialDelayMs), this,
+                       &FullscreenExitBubbleGtk::Hide);
+
+  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(container_),
+                                      widget());
+  signals_.Connect(container_, "set-floating-position",
+                   G_CALLBACK(OnSetFloatingPositionThunk), this);
+}
+
+void FullscreenExitBubbleGtk::Hide() {
+  slide_widget_->Close();
+}
+
+void FullscreenExitBubbleGtk::OnSetFloatingPosition(
+    GtkWidget* floating_container,
+    GtkAllocation* allocation) {
+  GtkRequisition bubble_size;
+  gtk_widget_size_request(widget(), &bubble_size);
+
+  // Position the bubble at the top center of the screen.
+  GValue value = { 0, };
+  g_value_init(&value, G_TYPE_INT);
+  g_value_set_int(&value, (allocation->width - bubble_size.width) / 2);
+  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
+                                   widget(), "x", &value);
+
+  g_value_set_int(&value, 0);
+  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
+                                   widget(), "y", &value);
+  g_value_unset(&value);
+}
+
+void FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link) {
+  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(widget()));
+  gtk_window_unfullscreen(window);
+}
diff --git a/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h b/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h
new file mode 100644
index 0000000..4a55ee0
--- /dev/null
+++ b/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_
+#pragma once
+
+#include "base/timer.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+
+typedef struct _GtkFloatingContainer GtkFloatingContainer;
+typedef struct _GtkWidget GtkWidget;
+
+// FullscreenExitBubbleGTK is responsible for showing a bubble atop the screen
+// in fullscreen mode, telling users how to exit and providing a click target.
+class FullscreenExitBubbleGtk {
+ public:
+  // We place the bubble in |container|.
+  explicit FullscreenExitBubbleGtk(GtkFloatingContainer* container);
+  virtual ~FullscreenExitBubbleGtk();
+
+  void InitWidgets();
+
+ private:
+  GtkWidget* widget() const {
+    return slide_widget_->widget();
+  }
+
+  // Hide the exit bubble.
+  void Hide();
+
+  CHROMEGTK_CALLBACK_1(FullscreenExitBubbleGtk, void, OnSetFloatingPosition,
+                       GtkAllocation*);
+  CHROMEGTK_CALLBACK_0(FullscreenExitBubbleGtk, void, OnLinkClicked);
+
+  // A pointer to the floating container that is our parent.
+  GtkFloatingContainer* container_;
+
+  // The widget that animates the slide-out of fullscreen exit bubble.
+  scoped_ptr<SlideAnimatorGtk> slide_widget_;
+
+  // The timer that does the initial hiding of the exit bubble.
+  base::OneShotTimer<FullscreenExitBubbleGtk> initial_delay_;
+
+  ui::GtkSignalRegistrar signals_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_
diff --git a/chrome/browser/ui/gtk/gconf_titlebar_listener.cc b/chrome/browser/ui/gtk/gconf_titlebar_listener.cc
new file mode 100644
index 0000000..7d3f784
--- /dev/null
+++ b/chrome/browser/ui/gtk/gconf_titlebar_listener.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gconf_titlebar_listener.h"
+
+#include <gtk/gtk.h>
+
+#include "base/environment.h"
+#include "base/nix/xdg_util.h"
+#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "chrome/browser/ui/gtk/browser_titlebar.h"
+
+namespace {
+
+// The GConf key we read for the button placement string. Even through the key
+// has "metacity" in it, it's shared between metacity and compiz.
+const char* kButtonLayoutKey = "/apps/metacity/general/button_layout";
+
+// GConf requires us to subscribe to a parent directory before we can subscribe
+// to changes in an individual key in that directory.
+const char* kMetacityGeneral = "/apps/metacity/general";
+
+}  // namespace
+
+// Public interface:
+
+// static
+GConfTitlebarListener* GConfTitlebarListener::GetInstance() {
+  return Singleton<GConfTitlebarListener>::get();
+}
+
+void GConfTitlebarListener::SetTitlebarButtons(BrowserTitlebar* titlebar) {
+  if (client_) {
+    titlebar->BuildButtons(current_value_);
+    titlebars_.insert(titlebar);
+  } else {
+    titlebar->BuildButtons(BrowserTitlebar::kDefaultButtonString);
+  }
+}
+
+void GConfTitlebarListener::RemoveObserver(BrowserTitlebar* titlebar) {
+  titlebars_.erase(titlebar);
+}
+
+// Protected:
+
+GConfTitlebarListener::~GConfTitlebarListener() {}
+
+// Private:
+
+GConfTitlebarListener::GConfTitlebarListener() : client_(NULL) {
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+  if (base::nix::GetDesktopEnvironment(env.get()) ==
+      base::nix::DESKTOP_ENVIRONMENT_GNOME) {
+    client_ = gconf_client_get_default();
+    // If we fail to get a context, that's OK, since we'll just fallback on
+    // not receiving gconf keys.
+    if (client_) {
+      // Get the initial value of the key.
+      GError* error = NULL;
+      GConfValue* gconf_value = gconf_client_get(client_, kButtonLayoutKey,
+                                                 &error);
+      if (HandleGError(error, kButtonLayoutKey))
+        return;
+      ParseAndStoreValue(gconf_value);
+      if (gconf_value)
+        gconf_value_free(gconf_value);
+
+      // Register that we're interested in the values of this directory.
+      gconf_client_add_dir(client_, kMetacityGeneral,
+                           GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
+      if (HandleGError(error, kMetacityGeneral))
+        return;
+
+      // Register to get notifies about changes to this key.
+      gconf_client_notify_add(
+          client_, kButtonLayoutKey,
+          reinterpret_cast<void (*)(GConfClient*, guint, GConfEntry*, void*)>(
+              OnChangeNotificationThunk),
+          this, NULL, &error);
+      if (HandleGError(error, kButtonLayoutKey))
+        return;
+    }
+  }
+}
+
+void GConfTitlebarListener::OnChangeNotification(GConfClient* client,
+                                                 guint cnxn_id,
+                                                 GConfEntry* entry) {
+  if (strcmp(gconf_entry_get_key(entry), kButtonLayoutKey) == 0) {
+    GConfValue* gconf_value = gconf_entry_get_value(entry);
+    ParseAndStoreValue(gconf_value);
+
+    // Broadcast the new configuration to all windows:
+    for (std::set<BrowserTitlebar*>::const_iterator it = titlebars_.begin();
+         it != titlebars_.end(); ++it) {
+      (*it)->BuildButtons(current_value_);
+    }
+  }
+}
+
+bool GConfTitlebarListener::HandleGError(GError* error, const char* key) {
+  if (error != NULL) {
+    LOG(ERROR) << "Error with gconf key '" << key << "': " << error->message;
+    g_error_free(error);
+    g_object_unref(client_);
+    client_ = NULL;
+    return true;
+  }
+  return false;
+}
+
+void GConfTitlebarListener::ParseAndStoreValue(GConfValue* gconf_value) {
+  if (gconf_value) {
+    const char* value = gconf_value_get_string(gconf_value);
+    current_value_ = value ? value : BrowserTitlebar::kDefaultButtonString;
+  } else {
+    current_value_ = BrowserTitlebar::kDefaultButtonString;
+  }
+}
diff --git a/chrome/browser/ui/gtk/gconf_titlebar_listener.h b/chrome/browser/ui/gtk/gconf_titlebar_listener.h
new file mode 100644
index 0000000..179e92a
--- /dev/null
+++ b/chrome/browser/ui/gtk/gconf_titlebar_listener.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_GCONF_TITLEBAR_LISTENER_H_
+#define CHROME_BROWSER_UI_GTK_GCONF_TITLEBAR_LISTENER_H_
+#pragma once
+
+#include <gconf/gconf-client.h>
+#include <gtk/gtk.h>
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class BrowserTitlebar;
+template <typename T> struct DefaultSingletonTraits;
+
+// On GNOME desktops, subscribes to the gconf key which controlls button order.
+// Everywhere else, SetTiltebarButtons() just calls back into BrowserTitlebar
+// with the default ordering.
+//
+// Meant to be used as a Singleton through base/singleton.h's interface.
+class GConfTitlebarListener {
+ public:
+  // Returns the singleton instance.
+  static GConfTitlebarListener* GetInstance();
+
+  // Sets the current titlebar button order. On GNOME desktops, also subscribes
+  // to further notifications when this changes.
+  void SetTitlebarButtons(BrowserTitlebar* titlebar);
+
+  // Removes |titlebar| from the list of objects observing button order change
+  // notifications.
+  void RemoveObserver(BrowserTitlebar* titlebar);
+
+ protected:
+  virtual ~GConfTitlebarListener();
+
+ private:
+  // Private constructor to enforce singleton access.
+  GConfTitlebarListener();
+
+  // Called whenever the metacity key changes.
+  CHROMEG_CALLBACK_2(GConfTitlebarListener, void, OnChangeNotification,
+                     GConfClient*, guint, GConfEntry*);
+
+  // Checks |error|. On error, prints out a message and closes the connection
+  // to GConf and reverts to default mode.
+  bool HandleGError(GError* error, const char* key);
+
+  // Parses the return data structure from GConf, falling back to the default
+  // value on any error.
+  void ParseAndStoreValue(GConfValue* gconf_value);
+
+  // Pointer to our gconf context. NULL if we aren't on a desktop that uses
+  // gconf.
+  GConfClient* client_;
+
+  // The current button ordering as heard from gconf.
+  std::string current_value_;
+
+  // BrowserTitlebar objects which have subscribed to updates.
+  std::set<BrowserTitlebar*> titlebars_;
+
+  friend struct DefaultSingletonTraits<GConfTitlebarListener>;
+  DISALLOW_COPY_AND_ASSIGN(GConfTitlebarListener);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_GCONF_TITLEBAR_LISTENER_H_
diff --git a/chrome/browser/ui/gtk/gtk_chrome_button.cc b/chrome/browser/ui/gtk/gtk_chrome_button.cc
new file mode 100644
index 0000000..b08427a
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_button.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_chrome_button.h"
+
+#include "base/basictypes.h"
+#include "chrome/browser/ui/gtk/nine_box.h"
+#include "grit/app_resources.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// The theme graphics for when the mouse is over the button.
+NineBox* g_nine_box_prelight;
+// The theme graphics for when the button is clicked.
+NineBox* g_nine_box_active;
+
+}  // namespace
+
+G_BEGIN_DECLS
+
+#define GTK_CHROME_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),\
+                                          GTK_TYPE_CHROME_BUTTON,\
+                                          GtkChromeButtonPrivate))
+typedef struct _GtkChromeButtonPrivate GtkChromeButtonPrivate;
+
+struct _GtkChromeButtonPrivate {
+  int paint_state;
+
+  // If true, we use images provided by the theme instead of GTK's default
+  // button rendering.
+  gboolean use_gtk_rendering;
+
+  gdouble hover_state;
+};
+
+G_DEFINE_TYPE(GtkChromeButton, gtk_chrome_button, GTK_TYPE_BUTTON)
+static gboolean gtk_chrome_button_expose(GtkWidget* widget,
+                                         GdkEventExpose* event);
+
+static void gtk_chrome_button_class_init(GtkChromeButtonClass* button_class) {
+  gtk_rc_parse_string(
+      "style \"chrome-button\" {"
+      "  xthickness = 2 "
+      "  GtkButton::child-displacement-x = 0"
+      "  GtkButton::child-displacement-y = 0"
+      "  GtkButton::inner-border = { 0, 0, 0, 0 }"
+      "}"
+      "widget_class \"*.<GtkChromeButton>\" style \"chrome-button\"");
+
+  GtkWidgetClass* widget_class =
+      reinterpret_cast<GtkWidgetClass*>(button_class);
+  widget_class->expose_event = gtk_chrome_button_expose;
+
+  g_nine_box_prelight = new NineBox(
+      IDR_TEXTBUTTON_TOP_LEFT_H,
+      IDR_TEXTBUTTON_TOP_H,
+      IDR_TEXTBUTTON_TOP_RIGHT_H,
+      IDR_TEXTBUTTON_LEFT_H,
+      IDR_TEXTBUTTON_CENTER_H,
+      IDR_TEXTBUTTON_RIGHT_H,
+      IDR_TEXTBUTTON_BOTTOM_LEFT_H,
+      IDR_TEXTBUTTON_BOTTOM_H,
+      IDR_TEXTBUTTON_BOTTOM_RIGHT_H);
+
+  g_nine_box_active = new NineBox(
+      IDR_TEXTBUTTON_TOP_LEFT_P,
+      IDR_TEXTBUTTON_TOP_P,
+      IDR_TEXTBUTTON_TOP_RIGHT_P,
+      IDR_TEXTBUTTON_LEFT_P,
+      IDR_TEXTBUTTON_CENTER_P,
+      IDR_TEXTBUTTON_RIGHT_P,
+      IDR_TEXTBUTTON_BOTTOM_LEFT_P,
+      IDR_TEXTBUTTON_BOTTOM_P,
+      IDR_TEXTBUTTON_BOTTOM_RIGHT_P);
+
+  GObjectClass* gobject_class = G_OBJECT_CLASS(button_class);
+  g_type_class_add_private(gobject_class, sizeof(GtkChromeButtonPrivate));
+}
+
+static void gtk_chrome_button_init(GtkChromeButton* button) {
+  GtkChromeButtonPrivate* priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
+  priv->paint_state = -1;
+  priv->use_gtk_rendering = FALSE;
+  priv->hover_state = -1.0;
+
+  GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
+}
+
+static gboolean gtk_chrome_button_expose(GtkWidget* widget,
+                                         GdkEventExpose* event) {
+  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(widget);
+  int paint_state = priv->paint_state < 0 ?
+                    GTK_WIDGET_STATE(widget) : priv->paint_state;
+
+  if (priv->use_gtk_rendering) {
+    // We have the superclass handle this expose when we aren't using custom
+    // rendering AND we're in either the prelight or active state so that we
+    // get the button border for the current GTK theme drawn.
+    if (paint_state == GTK_STATE_PRELIGHT || paint_state == GTK_STATE_ACTIVE) {
+      // Set the state of button->depressed so we paint pressed even if the
+      // actual state of the button is something else.
+      GTK_BUTTON(widget)->depressed = (paint_state == GTK_STATE_ACTIVE);
+      return GTK_WIDGET_CLASS(gtk_chrome_button_parent_class)->expose_event
+          (widget, event);
+    }
+  } else {
+    double effective_hover_state = paint_state == GTK_STATE_PRELIGHT ?
+                                   1.0 : 0.0;
+    // |paint_state| overrides |hover_state|.
+    if (priv->hover_state >= 0.0 && priv->paint_state < 0)
+      effective_hover_state = priv->hover_state;
+
+    if (paint_state == GTK_STATE_ACTIVE) {
+      g_nine_box_active->RenderToWidget(widget);
+    } else {
+      g_nine_box_prelight->RenderToWidgetWithOpacity(widget,
+                                                     effective_hover_state);
+    }
+  }
+
+  // If we have a child widget, draw it.
+  if (gtk_bin_get_child(GTK_BIN(widget))) {
+    gtk_container_propagate_expose(GTK_CONTAINER(widget),
+                                   gtk_bin_get_child(GTK_BIN(widget)),
+                                   event);
+  }
+
+  return FALSE;
+}
+
+GtkWidget* gtk_chrome_button_new(void) {
+  return GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_BUTTON, NULL));
+}
+
+void gtk_chrome_button_set_paint_state(GtkChromeButton* button,
+                                       GtkStateType state) {
+  g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
+
+  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
+  priv->paint_state = state;
+
+  gtk_widget_queue_draw(GTK_WIDGET(button));
+}
+
+void gtk_chrome_button_unset_paint_state(GtkChromeButton* button) {
+  g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
+
+  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
+  priv->paint_state = -1;
+
+  gtk_widget_queue_draw(GTK_WIDGET(button));
+}
+
+void gtk_chrome_button_set_use_gtk_rendering(GtkChromeButton* button,
+                                             gboolean value) {
+  g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
+  GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
+  priv->use_gtk_rendering = value;
+}
+
+void gtk_chrome_button_set_hover_state(GtkChromeButton* button,
+                                       gdouble state) {
+  GtkChromeButtonPrivate* priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
+  if (state >= 0.0 && state <= 1.0)
+    priv->hover_state = state;
+  else
+    priv->hover_state = -1.0;
+  gtk_widget_queue_draw(GTK_WIDGET(button));
+}
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/gtk_chrome_button.h b/chrome/browser/ui/gtk/gtk_chrome_button.h
new file mode 100644
index 0000000..1a8e1b8
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_button.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_CHROME_BUTTON_H_
+#define CHROME_BROWSER_UI_GTK_GTK_CHROME_BUTTON_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbutton.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CHROME_BUTTON        (gtk_chrome_button_get_type ())
+#define GTK_CHROME_BUTTON(obj)                              \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CHROME_BUTTON, GtkChromeButton))
+#define GTK_CHROME_BUTTON_CLASS(klass)                      \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CHROME_BUTTON, \
+                           GtkChromeButtonClass))
+#define GTK_IS_CHROME_BUTTON(obj)                           \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHROME_BUTTON))
+#define GTK_IS_CHROME_BUTTON_CLASS(klass)                   \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHROME_BUTTON))
+#define GTK_CHROME_BUTTON_GET_CLASS(obj)                    \
+  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHROME_BUTTON, GtkChromeButton))
+
+typedef struct _GtkChromeButton        GtkChromeButton;
+typedef struct _GtkChromeButtonClass   GtkChromeButtonClass;
+
+struct _GtkChromeButton {
+  GtkButton button;
+};
+
+struct _GtkChromeButtonClass {
+  GtkButtonClass parent_class;
+};
+
+GtkWidget* gtk_chrome_button_new();
+
+GType gtk_chrome_button_get_type();
+
+// Set the paint state to |state|. This overrides the widget's current state.
+void gtk_chrome_button_set_paint_state(GtkChromeButton* button,
+                                       GtkStateType state);
+
+// Revert to using the widget's current state for painting.
+void gtk_chrome_button_unset_paint_state(GtkChromeButton* button);
+
+// Whether we should use custom theme images or let GTK take care of it.
+void gtk_chrome_button_set_use_gtk_rendering(GtkChromeButton* button,
+                                             gboolean value);
+
+// Sets the partial hover state of the button. The acceptable range is 0.0 to
+// 1.0. If |state| is outside of that range, then revert the button to normal
+// hovering. This can be overridden by gtk_chrome_button_set_paint_state.
+void gtk_chrome_button_set_hover_state(GtkChromeButton* button,
+                                       gdouble state);
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_CHROME_BUTTON_H_
diff --git a/chrome/browser/ui/gtk/gtk_chrome_cookie_view.cc b/chrome/browser/ui/gtk/gtk_chrome_cookie_view.cc
new file mode 100644
index 0000000..a7bac57
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_cookie_view.cc
@@ -0,0 +1,675 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_chrome_cookie_view.h"
+
+#include "base/i18n/time_formatting.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+void InitBrowserDetailStyle(GtkWidget* entry, GtkStyle* label_style,
+                            GtkStyle* dialog_style) {
+  gtk_widget_modify_fg(entry, GTK_STATE_NORMAL,
+                       &label_style->fg[GTK_STATE_NORMAL]);
+  gtk_widget_modify_fg(entry, GTK_STATE_INSENSITIVE,
+                       &label_style->fg[GTK_STATE_INSENSITIVE]);
+  // GTK_NO_WINDOW widgets like GtkLabel don't draw their own background, so we
+  // combine the normal or insensitive foreground of the label style with the
+  // normal background of the window style to achieve the "normal label" and
+  // "insensitive label" colors.
+  gtk_widget_modify_base(entry, GTK_STATE_NORMAL,
+                         &dialog_style->bg[GTK_STATE_NORMAL]);
+  gtk_widget_modify_base(entry, GTK_STATE_INSENSITIVE,
+                         &dialog_style->bg[GTK_STATE_NORMAL]);
+}
+
+GtkWidget* InitRowLabel(int row, int label_id, GtkWidget* details_table) {
+  GtkWidget* name_label = gtk_label_new(
+      l10n_util::GetStringUTF8(label_id).c_str());
+  gtk_misc_set_alignment(GTK_MISC(name_label), 1, 0.5);
+  gtk_table_attach(GTK_TABLE(details_table), name_label,
+                   0, 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
+
+  return name_label;
+}
+
+GtkWidget* InitDetailRow(int row, int label_id,
+                         GtkWidget* details_table, GtkWidget** entry) {
+  GtkWidget* name_label = InitRowLabel(row, label_id, details_table);
+
+  *entry = gtk_entry_new();
+  gtk_entry_set_editable(GTK_ENTRY(*entry), FALSE);
+  gtk_entry_set_has_frame(GTK_ENTRY(*entry), FALSE);
+  gtk_table_attach_defaults(GTK_TABLE(details_table), *entry,
+                            1, 2, row, row + 1);
+
+  return name_label;
+}
+
+GtkWidget* InitComboboxRow(int row, int label_id,
+                           GtkWidget* details_table,
+                           GtkWidget** combobox,
+                           GtkListStore** store) {
+  GtkWidget* name_label = InitRowLabel(row, label_id, details_table);
+
+  *store = gtk_list_store_new(1, G_TYPE_STRING);
+  *combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(*store));
+  g_object_unref(*store);
+
+  GtkCellRenderer* cell = gtk_cell_renderer_text_new();
+  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(*combobox), cell, TRUE);
+  gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(*combobox), cell,
+                                  "text", 0, NULL);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), *combobox, FALSE, FALSE, 0);
+
+  gtk_table_attach_defaults(GTK_TABLE(details_table), hbox,
+                            1, 2, row, row + 1);
+
+  return name_label;
+}
+
+void InitStyles(GtkChromeCookieView *self) {
+  GtkStyle* label_style = gtk_widget_get_style(self->first_label_);
+  GtkStyle* dialog_style = gtk_widget_get_style(GTK_WIDGET(self));
+
+  // Cookie details.
+  InitBrowserDetailStyle(self->cookie_name_entry_, label_style, dialog_style);
+  InitBrowserDetailStyle(self->cookie_content_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->cookie_domain_entry_, label_style, dialog_style);
+  InitBrowserDetailStyle(self->cookie_path_entry_, label_style, dialog_style);
+  InitBrowserDetailStyle(self->cookie_send_for_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->cookie_created_entry_, label_style,
+                         dialog_style);
+  if (self->cookie_expires_entry_) {
+    InitBrowserDetailStyle(self->cookie_expires_entry_, label_style,
+                           dialog_style);
+  }
+
+  // Database details.
+  InitBrowserDetailStyle(self->database_name_entry_, label_style, dialog_style);
+  InitBrowserDetailStyle(self->database_description_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->database_size_entry_, label_style, dialog_style);
+  InitBrowserDetailStyle(self->database_last_modified_entry_, label_style,
+                         dialog_style);
+
+  // Local storage details.
+  InitBrowserDetailStyle(self->local_storage_origin_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->local_storage_size_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->local_storage_last_modified_entry_, label_style,
+                         dialog_style);
+
+  // AppCache details.
+  InitBrowserDetailStyle(self->appcache_manifest_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->appcache_size_entry_, label_style, dialog_style);
+  InitBrowserDetailStyle(self->appcache_created_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->appcache_last_accessed_entry_, label_style,
+                         dialog_style);
+
+  // Local storage item.
+  InitBrowserDetailStyle(self->local_storage_item_origin_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->local_storage_item_key_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->local_storage_item_value_entry_, label_style,
+                         dialog_style);
+
+  // Database accessed item.
+  InitBrowserDetailStyle(self->database_accessed_origin_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->database_accessed_name_entry_, label_style,
+                         dialog_style);
+  InitBrowserDetailStyle(self->database_accessed_description_entry_,
+                         label_style, dialog_style);
+  InitBrowserDetailStyle(self->database_accessed_size_entry_, label_style,
+                         dialog_style);
+
+  // AppCache created item.
+  InitBrowserDetailStyle(self->appcache_created_manifest_entry_, label_style,
+                         dialog_style);
+}
+
+void SetCookieDetailsSensitivity(GtkChromeCookieView *self,
+                                 gboolean enabled) {
+  gtk_widget_set_sensitive(self->cookie_name_entry_, enabled);
+  gtk_widget_set_sensitive(self->cookie_content_entry_, enabled);
+  gtk_widget_set_sensitive(self->cookie_domain_entry_, enabled);
+  gtk_widget_set_sensitive(self->cookie_path_entry_, enabled);
+  gtk_widget_set_sensitive(self->cookie_send_for_entry_, enabled);
+  gtk_widget_set_sensitive(self->cookie_created_entry_, enabled);
+  if (self->cookie_expires_entry_)
+    gtk_widget_set_sensitive(self->cookie_expires_entry_, enabled);
+  else
+    gtk_widget_set_sensitive(self->cookie_expires_combobox_, enabled);
+}
+
+void SetDatabaseDetailsSensitivity(GtkChromeCookieView *self,
+                                   gboolean enabled) {
+  gtk_widget_set_sensitive(self->database_name_entry_, enabled);
+  gtk_widget_set_sensitive(self->database_description_entry_, enabled);
+  gtk_widget_set_sensitive(self->database_size_entry_, enabled);
+  gtk_widget_set_sensitive(self->database_last_modified_entry_, enabled);
+}
+
+void SetLocalStorageDetailsSensitivity(GtkChromeCookieView *self,
+                                       gboolean enabled) {
+  gtk_widget_set_sensitive(self->local_storage_origin_entry_, enabled);
+  gtk_widget_set_sensitive(self->local_storage_size_entry_, enabled);
+  gtk_widget_set_sensitive(self->local_storage_last_modified_entry_, enabled);
+}
+
+void SetAppCacheDetailsSensitivity(GtkChromeCookieView *self,
+                                   gboolean enabled) {
+  gtk_widget_set_sensitive(self->appcache_manifest_entry_, enabled);
+  gtk_widget_set_sensitive(self->appcache_size_entry_, enabled);
+  gtk_widget_set_sensitive(self->appcache_created_entry_, enabled);
+  gtk_widget_set_sensitive(self->appcache_last_accessed_entry_, enabled);
+}
+
+void SetIndexedDBDetailsSensitivity(GtkChromeCookieView *self,
+                                    gboolean enabled) {
+  gtk_widget_set_sensitive(self->indexed_db_origin_entry_, enabled);
+  gtk_widget_set_sensitive(self->indexed_db_size_entry_, enabled);
+  gtk_widget_set_sensitive(self->indexed_db_last_modified_entry_, enabled);
+}
+
+void SetLocalStorageItemSensitivity(GtkChromeCookieView* self,
+                                    gboolean enabled) {
+  gtk_widget_set_sensitive(self->local_storage_item_origin_entry_, enabled);
+  gtk_widget_set_sensitive(self->local_storage_item_key_entry_, enabled);
+  gtk_widget_set_sensitive(self->local_storage_item_value_entry_, enabled);
+}
+
+void SetDatabaseAccessedSensitivity(GtkChromeCookieView* self,
+                                    gboolean enabled) {
+  gtk_widget_set_sensitive(self->database_accessed_origin_entry_, enabled);
+  gtk_widget_set_sensitive(self->database_accessed_name_entry_, enabled);
+  gtk_widget_set_sensitive(self->database_accessed_description_entry_, enabled);
+  gtk_widget_set_sensitive(self->database_accessed_size_entry_, enabled);
+}
+
+void SetAppCacheCreatedSensitivity(GtkChromeCookieView* self,
+                                   gboolean enabled) {
+  gtk_widget_set_sensitive(self->appcache_created_manifest_entry_, enabled);
+}
+
+void ClearCookieDetails(GtkChromeCookieView *self) {
+  std::string no_cookie =
+      l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_NONESELECTED);
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_name_entry_),
+                     no_cookie.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_content_entry_),
+                     no_cookie.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_domain_entry_),
+                     no_cookie.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_path_entry_),
+                     no_cookie.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_created_entry_),
+                     no_cookie.c_str());
+  if (self->cookie_expires_entry_) {
+    gtk_entry_set_text(GTK_ENTRY(self->cookie_expires_entry_),
+                       no_cookie.c_str());
+  } else {
+    GtkListStore* store = self->cookie_expires_combobox_store_;
+    GtkTreeIter iter;
+    gtk_list_store_clear(store);
+
+    gtk_list_store_append(store, &iter);
+    gtk_list_store_set(store, &iter, 0, no_cookie.c_str(), -1);
+
+    gtk_combo_box_set_active(GTK_COMBO_BOX(self->cookie_expires_combobox_),
+                             0);
+  }
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_send_for_entry_),
+                     no_cookie.c_str());
+  SetCookieDetailsSensitivity(self, FALSE);
+}
+
+void UpdateVisibleDetailedInfo(GtkChromeCookieView *self, GtkWidget* table) {
+  SetCookieDetailsSensitivity(self, table == self->cookie_details_table_);
+  SetDatabaseDetailsSensitivity(self, table == self->database_details_table_);
+  SetLocalStorageDetailsSensitivity(self,
+      table == self->local_storage_details_table_);
+  SetAppCacheDetailsSensitivity(self, table == self->appcache_details_table_);
+  SetIndexedDBDetailsSensitivity(self,
+      table == self->indexed_db_details_table_);
+  SetLocalStorageItemSensitivity(self,
+      table == self->local_storage_item_table_);
+  SetDatabaseAccessedSensitivity(self,
+      table == self->database_accessed_table_);
+  SetAppCacheCreatedSensitivity(self,
+      table == self->appcache_created_table_);
+
+  // Display everything
+  gtk_widget_show(self->table_box_);
+  gtk_widget_show_all(table);
+  // Hide everything that isn't us.
+  if (table != self->cookie_details_table_)
+    gtk_widget_hide(self->cookie_details_table_);
+  if (table != self->database_details_table_)
+    gtk_widget_hide(self->database_details_table_);
+  if (table != self->local_storage_details_table_)
+    gtk_widget_hide(self->local_storage_details_table_);
+  if (table != self->appcache_details_table_)
+    gtk_widget_hide(self->appcache_details_table_);
+  if (table != self->indexed_db_details_table_)
+    gtk_widget_hide(self->indexed_db_details_table_);
+  if (table != self->local_storage_item_table_)
+    gtk_widget_hide(self->local_storage_item_table_);
+  if (table != self->database_accessed_table_)
+    gtk_widget_hide(self->database_accessed_table_);
+  if (table != self->appcache_created_table_)
+    gtk_widget_hide(self->appcache_created_table_);
+}
+
+}  // namespace
+
+G_DEFINE_TYPE(GtkChromeCookieView, gtk_chrome_cookie_view, GTK_TYPE_FRAME)
+
+static void gtk_chrome_cookie_view_class_init(GtkChromeCookieViewClass *klass) {
+}
+
+static void gtk_chrome_cookie_view_init(GtkChromeCookieView *self) {
+}
+
+void BuildWidgets(GtkChromeCookieView *self, gboolean editable_expiration) {
+  self->table_box_ = gtk_vbox_new(FALSE, 0);
+  gtk_widget_set_no_show_all(self->table_box_, TRUE);
+
+  // Cookie details.
+  self->cookie_details_table_ = gtk_table_new(7, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->cookie_details_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->cookie_details_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  int row = 0;
+  self->first_label_ = InitDetailRow(row++, IDS_COOKIES_COOKIE_NAME_LABEL,
+                self->cookie_details_table_, &self->cookie_name_entry_);
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_CONTENT_LABEL,
+                self->cookie_details_table_, &self->cookie_content_entry_);
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
+                self->cookie_details_table_, &self->cookie_domain_entry_);
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_PATH_LABEL,
+                self->cookie_details_table_, &self->cookie_path_entry_);
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_SENDFOR_LABEL,
+                self->cookie_details_table_, &self->cookie_send_for_entry_);
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_CREATED_LABEL,
+                self->cookie_details_table_, &self->cookie_created_entry_);
+  if (editable_expiration) {
+    InitComboboxRow(row++, IDS_COOKIES_COOKIE_EXPIRES_LABEL,
+                    self->cookie_details_table_,
+                    &self->cookie_expires_combobox_,
+                    &self->cookie_expires_combobox_store_);
+  } else {
+    InitDetailRow(row++, IDS_COOKIES_COOKIE_EXPIRES_LABEL,
+                  self->cookie_details_table_, &self->cookie_expires_entry_);
+  }
+
+  // Database details.
+  self->database_details_table_ = gtk_table_new(4, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->database_details_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->database_details_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_NAME_LABEL,
+                self->database_details_table_, &self->database_name_entry_);
+  InitDetailRow(row++, IDS_COOKIES_WEB_DATABASE_DESCRIPTION_LABEL,
+                self->database_details_table_,
+                &self->database_description_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
+                self->database_details_table_, &self->database_size_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
+                self->database_details_table_,
+                &self->database_last_modified_entry_);
+
+  // Local storage details.
+  self->local_storage_details_table_ = gtk_table_new(3, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->local_storage_details_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->local_storage_details_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  row = 0;
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL,
+                self->local_storage_details_table_,
+                &self->local_storage_origin_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
+                self->local_storage_details_table_,
+                &self->local_storage_size_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
+                self->local_storage_details_table_,
+                &self->local_storage_last_modified_entry_);
+
+  // AppCache details.
+  self->appcache_details_table_ = gtk_table_new(4, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->appcache_details_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->appcache_details_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  row = 0;
+  InitDetailRow(row++, IDS_COOKIES_APPLICATION_CACHE_MANIFEST_LABEL,
+                self->appcache_details_table_,
+                &self->appcache_manifest_entry_);
+  InitDetailRow(row++, IDS_COOKIES_SIZE_LABEL,
+                self->appcache_details_table_, &self->appcache_size_entry_);
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_CREATED_LABEL,
+                self->appcache_details_table_, &self->appcache_created_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LAST_ACCESSED_LABEL,
+                self->appcache_details_table_,
+                &self->appcache_last_accessed_entry_);
+
+  // IndexedDB details.
+  self->indexed_db_details_table_ = gtk_table_new(4, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->indexed_db_details_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->indexed_db_details_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  row = 0;
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL,
+                self->indexed_db_details_table_,
+                &self->indexed_db_origin_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
+                self->indexed_db_details_table_, &self->indexed_db_size_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
+                self->indexed_db_details_table_,
+                &self->indexed_db_last_modified_entry_);
+
+  // Local storage item.
+  self->local_storage_item_table_ = gtk_table_new(3, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->local_storage_item_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->local_storage_item_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  row = 0;
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
+                self->local_storage_item_table_,
+                &self->local_storage_item_origin_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_KEY_LABEL,
+                self->local_storage_item_table_,
+                &self->local_storage_item_key_entry_);
+  InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_VALUE_LABEL,
+                self->local_storage_item_table_,
+                &self->local_storage_item_value_entry_);
+
+  // Database accessed prompt.
+  self->database_accessed_table_ = gtk_table_new(2, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->database_accessed_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->local_storage_item_table_), 0,
+                            gtk_util::kLabelSpacing);
+
+  row = 0;
+  InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
+                self->database_accessed_table_,
+                &self->database_accessed_origin_entry_);
+  InitDetailRow(row++, IDS_COOKIES_WEB_DATABASE_NAME,
+                self->database_accessed_table_,
+                &self->database_accessed_name_entry_);
+  InitDetailRow(row++, IDS_COOKIES_WEB_DATABASE_DESCRIPTION_LABEL,
+                self->database_accessed_table_,
+                &self->database_accessed_description_entry_);
+  InitDetailRow(row++, IDS_COOKIES_SIZE_LABEL,
+                self->database_accessed_table_,
+                &self->database_accessed_size_entry_);
+
+  // AppCache created prompt.
+  self->appcache_created_table_ = gtk_table_new(1, 2, FALSE);
+  gtk_container_add(GTK_CONTAINER(self->table_box_),
+                    self->appcache_created_table_);
+  gtk_table_set_col_spacing(GTK_TABLE(self->appcache_created_table_), 0,
+                            gtk_util::kLabelSpacing);
+  row = 0;
+  InitDetailRow(row++, IDS_COOKIES_APPLICATION_CACHE_MANIFEST_LABEL,
+                self->appcache_created_table_,
+                &self->appcache_created_manifest_entry_);
+
+  gtk_frame_set_shadow_type(GTK_FRAME(self), GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(self), self->table_box_);
+}
+
+GtkWidget* gtk_chrome_cookie_view_new(gboolean editable_expiration) {
+  GtkChromeCookieView* view = GTK_CHROME_COOKIE_VIEW(
+      g_object_new(GTK_TYPE_CHROME_COOKIE_VIEW, NULL));
+  BuildWidgets(view, editable_expiration);
+  g_signal_connect(view, "realize", G_CALLBACK(InitStyles), NULL);
+  return GTK_WIDGET(view);
+}
+
+void gtk_chrome_cookie_view_clear(GtkChromeCookieView* self) {
+  UpdateVisibleDetailedInfo(self, self->cookie_details_table_);
+  ClearCookieDetails(self);
+}
+
+// Switches the display to showing the passed in cookie.
+void gtk_chrome_cookie_view_display_cookie(
+    GtkChromeCookieView* self,
+    const std::string& domain,
+    const net::CookieMonster::CanonicalCookie& cookie) {
+  UpdateVisibleDetailedInfo(self, self->cookie_details_table_);
+
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_name_entry_),
+                     cookie.Name().c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_content_entry_),
+                     cookie.Value().c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_domain_entry_),
+                     domain.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_path_entry_),
+                     cookie.Path().c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->cookie_created_entry_),
+                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                         cookie.CreationDate())).c_str());
+
+  std::string expire_text = cookie.DoesExpire() ?
+      UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate())) :
+      l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION);
+
+  if (self->cookie_expires_entry_) {
+    gtk_entry_set_text(GTK_ENTRY(self->cookie_expires_entry_),
+                       expire_text.c_str());
+  } else {
+    GtkListStore* store = self->cookie_expires_combobox_store_;
+    GtkTreeIter iter;
+    gtk_list_store_clear(store);
+
+    if (cookie.DoesExpire()) {
+      gtk_list_store_append(store, &iter);
+      gtk_list_store_set(store, &iter, 0, expire_text.c_str(), -1);
+    }
+
+    gtk_list_store_append(store, &iter);
+    gtk_list_store_set(
+        store, &iter, 0,
+        l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION).c_str(),
+        -1);
+
+    gtk_combo_box_set_active(GTK_COMBO_BOX(self->cookie_expires_combobox_),
+                             0);
+  }
+
+  gtk_entry_set_text(
+      GTK_ENTRY(self->cookie_send_for_entry_),
+      l10n_util::GetStringUTF8(cookie.IsSecure() ?
+                               IDS_COOKIES_COOKIE_SENDFOR_SECURE :
+                               IDS_COOKIES_COOKIE_SENDFOR_ANY).c_str());
+  SetCookieDetailsSensitivity(self, TRUE);
+}
+
+void gtk_chrome_cookie_view_display_cookie_string(
+    GtkChromeCookieView* self,
+    const GURL& url,
+    const std::string& cookie_line) {
+  net::CookieMonster::ParsedCookie pc(cookie_line);
+  net::CookieMonster::CanonicalCookie cookie(url, pc);
+
+  gtk_chrome_cookie_view_display_cookie(
+      self,
+      pc.HasDomain() ? pc.Domain() : url.host(),
+      cookie);
+}
+
+// Switches the display to showing the passed in database.
+void gtk_chrome_cookie_view_display_database(
+    GtkChromeCookieView* self,
+    const BrowsingDataDatabaseHelper::DatabaseInfo& database_info) {
+  UpdateVisibleDetailedInfo(self, self->database_details_table_);
+
+  gtk_entry_set_text(
+      GTK_ENTRY(self->database_name_entry_),
+      database_info.database_name.empty() ?
+          l10n_util::GetStringUTF8(
+              IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME).c_str() :
+          database_info.database_name.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->database_description_entry_),
+                     database_info.description.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->database_size_entry_),
+                     UTF16ToUTF8(FormatBytes(
+                         database_info.size,
+                         GetByteDisplayUnits(database_info.size),
+                         true)).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->database_last_modified_entry_),
+                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                         database_info.last_modified)).c_str());
+  SetDatabaseDetailsSensitivity(self, TRUE);
+}
+
+// Switches the display to showing the passed in local storage data.
+void gtk_chrome_cookie_view_display_local_storage(
+    GtkChromeCookieView* self,
+    const BrowsingDataLocalStorageHelper::LocalStorageInfo&
+    local_storage_info) {
+  UpdateVisibleDetailedInfo(self, self->local_storage_details_table_);
+
+  gtk_entry_set_text(GTK_ENTRY(self->local_storage_origin_entry_),
+                     local_storage_info.origin.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->local_storage_size_entry_),
+                     UTF16ToUTF8(FormatBytes(
+                         local_storage_info.size,
+                         GetByteDisplayUnits(local_storage_info.size),
+                         true)).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->local_storage_last_modified_entry_),
+                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                         local_storage_info.last_modified)).c_str());
+  SetLocalStorageDetailsSensitivity(self, TRUE);
+}
+
+// Switches the display to showing the passed in app cache.
+void gtk_chrome_cookie_view_display_app_cache(
+    GtkChromeCookieView* self,
+    const appcache::AppCacheInfo& info) {
+  UpdateVisibleDetailedInfo(self, self->appcache_details_table_);
+
+  gtk_entry_set_text(GTK_ENTRY(self->appcache_manifest_entry_),
+                     info.manifest_url.spec().c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->appcache_size_entry_),
+                     UTF16ToUTF8(FormatBytes(
+                         info.size,
+                         GetByteDisplayUnits(info.size),
+                         true)).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->appcache_created_entry_),
+                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                         info.creation_time)).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->appcache_last_accessed_entry_),
+                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                         info.last_access_time)).c_str());
+  SetAppCacheDetailsSensitivity(self, TRUE);
+}
+
+// Switches the display to showing the passed in IndexedDB data.
+void gtk_chrome_cookie_view_display_indexed_db(
+    GtkChromeCookieView* self,
+    const BrowsingDataIndexedDBHelper::IndexedDBInfo& indexed_db_info) {
+  UpdateVisibleDetailedInfo(self, self->indexed_db_details_table_);
+
+  gtk_entry_set_text(GTK_ENTRY(self->indexed_db_origin_entry_),
+                     indexed_db_info.origin.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->indexed_db_size_entry_),
+                     UTF16ToUTF8(FormatBytes(
+                         indexed_db_info.size,
+                         GetByteDisplayUnits(indexed_db_info.size),
+                         true)).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->indexed_db_last_modified_entry_),
+                     UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                         indexed_db_info.last_modified)).c_str());
+  SetLocalStorageDetailsSensitivity(self, TRUE);
+}
+
+void gtk_chrome_cookie_view_display_local_storage_item(
+    GtkChromeCookieView* self,
+    const std::string& host,
+    const string16& key,
+    const string16& value) {
+  UpdateVisibleDetailedInfo(self, self->local_storage_item_table_);
+
+  gtk_entry_set_text(GTK_ENTRY(self->local_storage_item_origin_entry_),
+                     host.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->local_storage_item_key_entry_),
+                     UTF16ToUTF8(key).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->local_storage_item_value_entry_),
+                     UTF16ToUTF8(value).c_str());
+  SetLocalStorageItemSensitivity(self, TRUE);
+}
+
+void gtk_chrome_cookie_view_display_database_accessed(
+    GtkChromeCookieView* self,
+    const std::string& host,
+    const string16& database_name,
+    const string16& display_name,
+    unsigned long estimated_size) {
+  UpdateVisibleDetailedInfo(self, self->database_accessed_table_);
+
+  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_origin_entry_),
+                     host.c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_name_entry_),
+                     UTF16ToUTF8(database_name).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_description_entry_),
+                     UTF16ToUTF8(display_name).c_str());
+  gtk_entry_set_text(GTK_ENTRY(self->database_accessed_size_entry_),
+                     UTF16ToUTF8(FormatBytes(
+                         estimated_size,
+                         GetByteDisplayUnits(estimated_size),
+                         true)).c_str());
+  SetDatabaseAccessedSensitivity(self, TRUE);
+}
+
+void gtk_chrome_cookie_view_display_appcache_created(
+    GtkChromeCookieView* self,
+    const GURL& manifest_url) {
+  UpdateVisibleDetailedInfo(self, self->appcache_created_table_);
+  gtk_entry_set_text(GTK_ENTRY(self->appcache_created_manifest_entry_),
+                     manifest_url.spec().c_str());
+  SetAppCacheCreatedSensitivity(self, TRUE);
+}
+
+bool gtk_chrome_cookie_view_session_expires(GtkChromeCookieView* self) {
+  if (self->cookie_expires_entry_)
+    return false;
+
+  GtkListStore* store = self->cookie_expires_combobox_store_;
+  int store_size = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
+  if (store_size == 1)
+    return false;
+
+  DCHECK_EQ(2, store_size);
+
+  int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(
+      self->cookie_expires_combobox_));
+  return selected == 1;
+}
diff --git a/chrome/browser/ui/gtk/gtk_chrome_cookie_view.h b/chrome/browser/ui/gtk/gtk_chrome_cookie_view.h
new file mode 100644
index 0000000..e0d5d4f
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_cookie_view.h
@@ -0,0 +1,194 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_CHROME_COOKIE_VIEW_H_
+#define CHROME_BROWSER_UI_GTK_GTK_CHROME_COOKIE_VIEW_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "chrome/browser/browsing_data_appcache_helper.h"
+#include "chrome/browser/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data_indexed_db_helper.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "net/base/cookie_monster.h"
+
+class GURL;
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CHROME_COOKIE_VIEW gtk_chrome_cookie_view_get_type()
+
+#define GTK_CHROME_COOKIE_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+  GTK_TYPE_CHROME_COOKIE_VIEW, GtkChromeCookieView))
+
+#define GTK_CHROME_COOKIE_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), \
+  GTK_TYPE_CHROME_COOKIE_VIEW, GtkChromeCookieViewClass))
+
+#define GTK_IS_CHROME_COOKIE_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+  GTK_TYPE_CHROME_COOKIE_VIEW))
+
+#define GTK_IS_CHROME_COOKIE_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), \
+  GTK_TYPE_CHROME_COOKIE_VIEW))
+
+#define GTK_CHROME_COOKIE_VIEW_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj), \
+  GTK_TYPE_CHROME_COOKIE_VIEW, GtkChromeCookieViewClass))
+
+// TODO(erg): Refactor the following class. It's continuously grown as more
+// things have been added to it and should probably become a general key/value
+// table. The problem is that any implementation for that would be much more
+// complicated and would require changing a whole lot of code.
+typedef struct {
+  GtkFrame parent;
+
+  // All public for testing since I don't think there's a "friend" mechanism in
+  // gobject.
+
+  GtkWidget* table_box_;
+
+  // A label we keep around so we can access its GtkStyle* once it is realized.
+  GtkWidget* first_label_;
+
+  // The cookie details widgets.
+  GtkWidget* cookie_details_table_;
+  GtkWidget* cookie_name_entry_;
+  GtkWidget* cookie_content_entry_;
+  GtkWidget* cookie_domain_entry_;
+  GtkWidget* cookie_path_entry_;
+  GtkWidget* cookie_send_for_entry_;
+  GtkWidget* cookie_created_entry_;
+
+  // Note: These two widgets are mutually exclusive based on what
+  // |editable_expiration| was when the cookie view was created. One of these
+  // variables will be NULL.
+  GtkWidget* cookie_expires_entry_;
+  GtkWidget* cookie_expires_combobox_;
+
+  GtkListStore* cookie_expires_combobox_store_;
+
+  // The database details widgets.
+  GtkWidget* database_details_table_;
+  GtkWidget* database_name_entry_;
+  GtkWidget* database_description_entry_;
+  GtkWidget* database_size_entry_;
+  GtkWidget* database_last_modified_entry_;
+
+  // The local storage details widgets.
+  GtkWidget* local_storage_details_table_;
+  GtkWidget* local_storage_origin_entry_;
+  GtkWidget* local_storage_size_entry_;
+  GtkWidget* local_storage_last_modified_entry_;
+
+  // The appcache details widgets.
+  GtkWidget* appcache_details_table_;
+  GtkWidget* appcache_manifest_entry_;
+  GtkWidget* appcache_size_entry_;
+  GtkWidget* appcache_created_entry_;
+  GtkWidget* appcache_last_accessed_entry_;
+
+  // The IndexedDB details widgets.
+  GtkWidget* indexed_db_details_table_;
+  GtkWidget* indexed_db_origin_entry_;
+  GtkWidget* indexed_db_size_entry_;
+  GtkWidget* indexed_db_last_modified_entry_;
+
+  // The local storage item widgets.
+  GtkWidget* local_storage_item_table_;
+  GtkWidget* local_storage_item_origin_entry_;
+  GtkWidget* local_storage_item_key_entry_;
+  GtkWidget* local_storage_item_value_entry_;
+
+  // The database accessed widgets.
+  GtkWidget* database_accessed_table_;
+  GtkWidget* database_accessed_origin_entry_;
+  GtkWidget* database_accessed_name_entry_;
+  GtkWidget* database_accessed_description_entry_;
+  GtkWidget* database_accessed_size_entry_;
+
+  // The appcache created widgets.
+  GtkWidget* appcache_created_table_;
+  GtkWidget* appcache_created_manifest_entry_;
+} GtkChromeCookieView;
+
+typedef struct {
+  GtkFrameClass parent_class;
+} GtkChromeCookieViewClass;
+
+GType gtk_chrome_cookie_view_get_type();
+
+// Builds a new cookie view.
+GtkWidget* gtk_chrome_cookie_view_new(gboolean editable_expiration);
+
+// Clears the cookie view.
+void gtk_chrome_cookie_view_clear(GtkChromeCookieView* widget);
+
+// NOTE: The G_END_DECLS ends here instead of at the end of the document
+// because we want to define some methods on GtkChromeCookieView that take C++
+// objects.
+G_END_DECLS
+// NOTE: ^^^^^^^^^^^^^^^^^^^^^^^
+
+// Switches the display to showing the passed in cookie.
+void gtk_chrome_cookie_view_display_cookie(
+    GtkChromeCookieView* widget,
+    const std::string& domain,
+    const net::CookieMonster::CanonicalCookie& cookie);
+
+// Looks up the cookie_line in CookieMonster and displays that.
+void gtk_chrome_cookie_view_display_cookie_string(
+    GtkChromeCookieView* widget,
+    const GURL& url,
+    const std::string& cookie_line);
+
+// Switches the display to showing the passed in database.
+void gtk_chrome_cookie_view_display_database(
+    GtkChromeCookieView* widget,
+    const BrowsingDataDatabaseHelper::DatabaseInfo& database_info);
+
+// Switches the display to showing the passed in local storage data.
+void gtk_chrome_cookie_view_display_local_storage(
+    GtkChromeCookieView* widget,
+    const BrowsingDataLocalStorageHelper::LocalStorageInfo&
+    local_storage_info);
+
+// Switches the display to showing the passed in app cache.
+void gtk_chrome_cookie_view_display_app_cache(
+    GtkChromeCookieView* widget,
+    const appcache::AppCacheInfo& info);
+
+// Switches the display to showing the passed in IndexedDB data.
+void gtk_chrome_cookie_view_display_indexed_db(
+    GtkChromeCookieView* widget,
+    const BrowsingDataIndexedDBHelper::IndexedDBInfo& info);
+
+// Switches the display to an individual storage item.
+void gtk_chrome_cookie_view_display_local_storage_item(
+    GtkChromeCookieView* widget,
+    const std::string& host,
+    const string16& key,
+    const string16& value);
+
+void gtk_chrome_cookie_view_display_database_accessed(
+    GtkChromeCookieView* self,
+    const std::string& host,
+    const string16& database_name,
+    const string16& display_name,
+    unsigned long estimated_size);
+
+void gtk_chrome_cookie_view_display_appcache_created(
+    GtkChromeCookieView* self,
+    const GURL& manifest_url);
+
+// If |editable_expiration| was true at construction time, returns the value of
+// the combo box. Otherwise, returns false.
+bool gtk_chrome_cookie_view_session_expires(GtkChromeCookieView* self);
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_CHROME_COOKIE_VIEW_H_
diff --git a/chrome/browser/ui/gtk/gtk_chrome_link_button.cc b/chrome/browser/ui/gtk/gtk_chrome_link_button.cc
new file mode 100644
index 0000000..c31a2c1
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_link_button.cc
@@ -0,0 +1,259 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+
+#include <stdlib.h>
+
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/gfx/gtk_util.h"
+
+static const gchar* kLinkMarkup = "<u><span color=\"%s\">%s</span></u>";
+
+namespace {
+
+// Set the GTK style on our custom link button. We don't want any border around
+// the link text.
+void SetLinkButtonStyle() {
+  static bool style_was_set = false;
+
+  if (style_was_set)
+    return;
+  style_was_set = true;
+
+  gtk_rc_parse_string(
+      "style \"chrome-link-button\" {"
+      "  GtkButton::inner-border = {0, 0, 0, 0}"
+      "  GtkButton::child-displacement-x = 0"
+      "  GtkButton::child-displacement-y = 0"
+      "  xthickness = 0"
+      "  ythickness = 0"
+      "}"
+      "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\"");
+}
+
+static void gtk_chrome_link_button_destroy_text_resources(
+    GtkChromeLinkButton* button) {
+  g_free(button->native_markup);
+  button->native_markup = NULL;
+  g_free(button->normal_markup);
+  button->normal_markup = NULL;
+  g_free(button->pressed_markup);
+  button->pressed_markup = NULL;
+
+  g_free(button->text);
+  button->text = NULL;
+}
+
+}  // namespace
+
+G_BEGIN_DECLS
+G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)
+
+static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
+  // If we were called before we were realized, abort. We'll be called for
+  // real when |button| is realized.
+  if (!GTK_WIDGET_REALIZED(button))
+    return;
+
+  g_free(button->native_markup);
+  button->native_markup = NULL;
+  g_free(button->normal_markup);
+  button->normal_markup = NULL;
+  g_free(button->pressed_markup);
+  button->pressed_markup = NULL;
+
+  gchar* text = button->text;
+  gboolean uses_markup = button->uses_markup;
+
+  if (!uses_markup) {
+    button->normal_markup = g_markup_printf_escaped(kLinkMarkup,
+                                                    button->normal_color,
+                                                    text);
+    button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
+  } else {
+    button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color,
+                                            text);
+
+    button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text);
+  }
+
+  // Get the current GTK theme's link button text color.
+  GdkColor* native_color = NULL;
+  gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);
+
+  if (native_color) {
+    gchar color_spec[9];
+    snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257,
+             native_color->green / 257, native_color->blue / 257);
+    gdk_color_free(native_color);
+
+    if (!uses_markup) {
+      button->native_markup = g_markup_printf_escaped(kLinkMarkup,
+          color_spec, text);
+    } else {
+      button->native_markup = g_strdup_printf(kLinkMarkup, color_spec, text);
+    }
+  } else {
+    // If the theme doesn't have a link color, just use blue. This matches the
+    // default for GtkLinkButton.
+    button->native_markup = g_strdup(button->normal_markup);
+  }
+
+  gtk_label_set_markup(GTK_LABEL(button->label),
+      button->using_native_theme ? button->native_markup :
+      button->normal_markup);
+}
+
+static void gtk_chrome_link_button_style_changed(GtkChromeLinkButton* button) {
+  // Regenerate the link with the possibly new colors after the user has
+  // changed his GTK style.
+  gtk_chrome_link_button_set_text(button);
+
+  if (GTK_WIDGET_VISIBLE(button))
+    gtk_widget_queue_draw(GTK_WIDGET(button));
+}
+
+static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
+                                              GdkEventExpose* event) {
+  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
+  GtkWidget* label = button->label;
+
+  if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_normal) {
+    gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup);
+    button->is_normal = FALSE;
+  } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE &&
+             !button->is_normal) {
+    gtk_label_set_markup(GTK_LABEL(label),
+        button->using_native_theme ? button->native_markup :
+                                     button->normal_markup);
+    button->is_normal = TRUE;
+  }
+
+  // Draw the link inside the button.
+  gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);
+
+  // Draw the focus rectangle.
+  if (GTK_WIDGET_HAS_FOCUS(widget)) {
+    gtk_paint_focus(widget->style, widget->window,
+                    static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
+                    &event->area, widget, NULL,
+                    widget->allocation.x, widget->allocation.y,
+                    widget->allocation.width, widget->allocation.height);
+  }
+
+  return TRUE;
+}
+
+static void gtk_chrome_link_button_enter(GtkButton* button) {
+  GtkWidget* widget = GTK_WIDGET(button);
+  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
+  gdk_window_set_cursor(widget->window, link_button->hand_cursor);
+}
+
+static void gtk_chrome_link_button_leave(GtkButton* button) {
+  GtkWidget* widget = GTK_WIDGET(button);
+  gdk_window_set_cursor(widget->window, NULL);
+}
+
+static void gtk_chrome_link_button_destroy(GtkObject* object) {
+  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
+
+  gtk_chrome_link_button_destroy_text_resources(button);
+
+  button->hand_cursor = NULL;
+
+  GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
+}
+
+static void gtk_chrome_link_button_class_init(
+    GtkChromeLinkButtonClass* link_button_class) {
+  GtkWidgetClass* widget_class =
+      reinterpret_cast<GtkWidgetClass*>(link_button_class);
+  GtkButtonClass* button_class =
+      reinterpret_cast<GtkButtonClass*>(link_button_class);
+  GtkObjectClass* object_class =
+      reinterpret_cast<GtkObjectClass*>(link_button_class);
+  widget_class->expose_event = &gtk_chrome_link_button_expose;
+  button_class->enter = &gtk_chrome_link_button_enter;
+  button_class->leave = &gtk_chrome_link_button_leave;
+  object_class->destroy = &gtk_chrome_link_button_destroy;
+}
+
+static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
+  SetLinkButtonStyle();
+
+  // We put a label in a button so we can connect to the click event. We don't
+  // let the button draw itself; catch all expose events to the button and pass
+  // them through to the label.
+  button->label = gtk_label_new(NULL);
+  button->normal_markup = NULL;
+  button->pressed_markup = NULL;
+  button->is_normal = TRUE;
+  strncpy(button->normal_color, "blue", 9);
+  button->native_markup = NULL;
+  button->using_native_theme = TRUE;
+  button->hand_cursor = gfx::GetCursor(GDK_HAND2);
+  button->text = NULL;
+
+  gtk_container_add(GTK_CONTAINER(button), button->label);
+  gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
+  g_signal_connect(button, "realize",
+                   G_CALLBACK(gtk_chrome_link_button_set_text), NULL);
+  g_signal_connect(button, "style-set",
+                   G_CALLBACK(gtk_chrome_link_button_style_changed), NULL);
+}
+
+GtkWidget* gtk_chrome_link_button_new(const char* text) {
+  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
+  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(text);
+  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;
+
+  return lb;
+}
+
+GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
+  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
+  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(markup);
+  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;
+
+  return lb;
+}
+
+void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
+                                              gboolean use_gtk) {
+  if (use_gtk != button->using_native_theme) {
+    button->using_native_theme = use_gtk;
+    if (GTK_WIDGET_VISIBLE(button))
+      gtk_widget_queue_draw(GTK_WIDGET(button));
+  }
+}
+
+void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
+                                      const char* text) {
+  g_free(button->text);
+  button->text = g_strdup(text);
+
+  gtk_chrome_link_button_set_text(button);
+
+  if (GTK_WIDGET_VISIBLE(button))
+    gtk_widget_queue_draw(GTK_WIDGET(button));
+}
+
+void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
+                                             const GdkColor* color) {
+  if (color) {
+    snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257,
+             color->green / 257, color->blue / 257);
+  } else {
+    strncpy(button->normal_color, "blue", 9);
+  }
+
+  gtk_chrome_link_button_set_text(button);
+
+  if (GTK_WIDGET_VISIBLE(button))
+    gtk_widget_queue_draw(GTK_WIDGET(button));
+}
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/gtk_chrome_link_button.h b/chrome/browser/ui/gtk/gtk_chrome_link_button.h
new file mode 100644
index 0000000..4532b02
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_link_button.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Creates a link button that shows |text| in blue and underlined. The cursor
+// changes to a hand when over the link.  This is like the GTK LinkButton, but
+// it doesn't call the global URI link handler, etc.  It is a button subclass,
+// so you can just handle the clicked signal.
+
+#ifndef CHROME_BROWSER_UI_GTK_GTK_CHROME_LINK_BUTTON_H_
+#define CHROME_BROWSER_UI_GTK_GTK_CHROME_LINK_BUTTON_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CHROME_LINK_BUTTON        (gtk_chrome_link_button_get_type ())
+#define GTK_CHROME_LINK_BUTTON(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+                                            GTK_TYPE_CHROME_LINK_BUTTON, \
+                                            GtkChromeLinkButton))
+#define GTK_CHROME_LINK_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
+                                             GTK_TYPE_CHROME_LINK_BUTTON, \
+                                             GtkChromeLinkButtonClass))
+#define GTK_IS_CHROME_LINK_BUTTON(obj)                           \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHROME_LINK_BUTTON))
+#define GTK_IS_CHROME_LINK_BUTTON_CLASS(klass)                   \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHROME_LINK_BUTTON))
+#define GTK_CHROME_LINK_BUTTON_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHROME_LINK_BUTTON, \
+                             GtkChromeLinkButton))
+
+typedef struct _GtkChromeLinkButton        GtkChromeLinkButton;
+typedef struct _GtkChromeLinkButtonClass   GtkChromeLinkButtonClass;
+
+struct _GtkChromeLinkButton {
+  GtkButton button;
+  GtkWidget* label;
+  gchar* normal_markup;
+  gchar* pressed_markup;
+  gboolean is_normal;
+  gchar normal_color[9];
+  gchar* native_markup;
+  gboolean using_native_theme;
+  GdkCursor* hand_cursor;
+  gchar* text;
+  gboolean uses_markup;
+};
+
+struct _GtkChromeLinkButtonClass {
+  GtkButtonClass parent_class;
+};
+
+// Make a link button with display text |text|.
+GtkWidget* gtk_chrome_link_button_new(const char* text);
+
+// As above, but don't escape markup in the text.
+GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup);
+
+// Set whether the link button draws natively (using "link-color"). The default
+// is TRUE.
+void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
+                                              gboolean use_gtk);
+
+// Set the label text of the link.
+void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
+                                      const char* text);
+
+// Set the color when the link is in a normal state (i.e. not pressed).
+// If not set, or called NULL |color|, the color will be blue.
+void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
+                                             const GdkColor* color);
+
+GType gtk_chrome_link_button_get_type();
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_CHROME_LINK_BUTTON_H_
diff --git a/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.cc b/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.cc
new file mode 100644
index 0000000..4f8d857
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.cc
@@ -0,0 +1,283 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
+
+#include <gtk/gtk.h>
+
+#include <algorithm>
+
+namespace {
+
+enum {
+  PROP_0,
+  PROP_HIDE_CHILD_DIRECTLY
+};
+
+struct SizeAllocateData {
+  GtkChromeShrinkableHBox* box;
+  GtkAllocation* allocation;
+  GtkTextDirection direction;
+  bool homogeneous;
+  int border_width;
+
+  // Maximum child width when |homogeneous| is TRUE.
+  int homogeneous_child_width;
+};
+
+void CountVisibleChildren(GtkWidget* child, gpointer userdata) {
+  if (GTK_WIDGET_VISIBLE(child))
+    ++(*reinterpret_cast<int*>(userdata));
+}
+
+void SumChildrenWidthRequisition(GtkWidget* child, gpointer userdata) {
+  if (GTK_WIDGET_VISIBLE(child)) {
+    GtkRequisition req;
+    gtk_widget_get_child_requisition(child, &req);
+    (*reinterpret_cast<int*>(userdata)) += std::max(req.width, 0);
+  }
+}
+
+void ShowInvisibleChildren(GtkWidget* child, gpointer userdata) {
+  if (!GTK_WIDGET_VISIBLE(child)) {
+    gtk_widget_show(child);
+    ++(*reinterpret_cast<int*>(userdata));
+  }
+}
+
+void ChildSizeAllocate(GtkWidget* child, gpointer userdata) {
+  if (!GTK_WIDGET_VISIBLE(child))
+    return;
+
+  SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata);
+  GtkAllocation child_allocation = child->allocation;
+
+  if (data->homogeneous) {
+    // Make sure the child is not overlapped with others' boundary.
+    if (child_allocation.width > data->homogeneous_child_width) {
+      child_allocation.x +=
+          (child_allocation.width - data->homogeneous_child_width) / 2;
+      child_allocation.width = data->homogeneous_child_width;
+    }
+  } else {
+    guint padding;
+    GtkPackType pack_type;
+    gtk_box_query_child_packing(GTK_BOX(data->box), child, NULL, NULL,
+                                &padding, &pack_type);
+
+    if ((data->direction == GTK_TEXT_DIR_RTL && pack_type == GTK_PACK_START) ||
+        (data->direction != GTK_TEXT_DIR_RTL && pack_type == GTK_PACK_END)) {
+      // All children are right aligned, so make sure the child won't overflow
+      // its parent's left edge.
+      int overflow = (data->allocation->x + data->border_width + padding -
+                      child_allocation.x);
+      if (overflow > 0) {
+        child_allocation.width -= overflow;
+        child_allocation.x += overflow;
+      }
+    } else {
+      // All children are left aligned, so make sure the child won't overflow
+      // its parent's right edge.
+      int overflow = (child_allocation.x + child_allocation.width + padding -
+          (data->allocation->x + data->allocation->width - data->border_width));
+      if (overflow > 0)
+        child_allocation.width -= overflow;
+    }
+  }
+
+  if (child_allocation.width != child->allocation.width) {
+    if (data->box->hide_child_directly || child_allocation.width <= 1)
+      gtk_widget_hide(child);
+    else
+      gtk_widget_size_allocate(child, &child_allocation);
+  }
+}
+
+}  // namespace
+
+G_BEGIN_DECLS
+
+static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
+                                             guint prop_id,
+                                             const GValue* value,
+                                             GParamSpec* pspec);
+static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
+                                             guint prop_id,
+                                             GValue* value,
+                                             GParamSpec* pspec);
+static void gtk_chrome_shrinkable_hbox_size_allocate(GtkWidget* widget,
+                                              GtkAllocation* allocation);
+
+G_DEFINE_TYPE(GtkChromeShrinkableHBox, gtk_chrome_shrinkable_hbox,
+              GTK_TYPE_HBOX)
+
+static void gtk_chrome_shrinkable_hbox_class_init(
+    GtkChromeShrinkableHBoxClass *klass) {
+  GObjectClass* object_class = G_OBJECT_CLASS(klass);
+  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
+
+  object_class->set_property = gtk_chrome_shrinkable_hbox_set_property;
+  object_class->get_property = gtk_chrome_shrinkable_hbox_get_property;
+
+  widget_class->size_allocate = gtk_chrome_shrinkable_hbox_size_allocate;
+
+  g_object_class_install_property(object_class, PROP_HIDE_CHILD_DIRECTLY,
+      g_param_spec_boolean("hide-child-directly",
+                           "Hide child directly",
+                           "Whether the children should be hid directly, "
+                           "if there is no enough space in its parent",
+                           FALSE,
+                           static_cast<GParamFlags>(
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+}
+
+static void gtk_chrome_shrinkable_hbox_init(GtkChromeShrinkableHBox* box) {
+  box->hide_child_directly = FALSE;
+  box->children_width_requisition = 0;
+}
+
+static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
+                                                    guint prop_id,
+                                                    const GValue* value,
+                                                    GParamSpec* pspec) {
+  GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(object);
+
+  switch (prop_id) {
+    case PROP_HIDE_CHILD_DIRECTLY:
+      gtk_chrome_shrinkable_hbox_set_hide_child_directly(
+          box, g_value_get_boolean(value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+      break;
+  }
+}
+
+static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
+                                                    guint prop_id,
+                                                    GValue* value,
+                                                    GParamSpec* pspec) {
+  GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(object);
+
+  switch (prop_id) {
+    case PROP_HIDE_CHILD_DIRECTLY:
+      g_value_set_boolean(value, box->hide_child_directly);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+      break;
+  }
+}
+
+static void gtk_chrome_shrinkable_hbox_size_allocate(
+    GtkWidget* widget, GtkAllocation* allocation) {
+  GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(widget);
+  gint children_width_requisition = 0;
+  gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
+                        &children_width_requisition);
+
+  // If we are allocated to more width or some children are removed or shrunk,
+  // then we need to show all invisible children before calling parent class's
+  // size_allocate method, because the new width may be enough to show those
+  // hidden children.
+  if (widget->allocation.width < allocation->width ||
+      box->children_width_requisition > children_width_requisition) {
+    gtk_container_foreach(GTK_CONTAINER(widget),
+                          reinterpret_cast<GtkCallback>(gtk_widget_show), NULL);
+
+    // If there were any invisible children, showing them will trigger another
+    // allocate. But we still need to go through the size allocate process
+    // in this iteration, otherwise before the next allocate iteration, the
+    // children may be redrawn on the screen with incorrect size allocation.
+  }
+
+  // Let the parent class do size allocation first. After that all children will
+  // be allocated with reasonable position and size according to their size
+  // request.
+  (GTK_WIDGET_CLASS(gtk_chrome_shrinkable_hbox_parent_class)->size_allocate)
+      (widget, allocation);
+
+  gint visible_children_count =
+      gtk_chrome_shrinkable_hbox_get_visible_child_count(
+          GTK_CHROME_SHRINKABLE_HBOX(widget));
+
+  box->children_width_requisition = 0;
+  if (visible_children_count == 0)
+    return;
+
+  SizeAllocateData data;
+  data.box = GTK_CHROME_SHRINKABLE_HBOX(widget);
+  data.allocation = allocation;
+  data.direction = gtk_widget_get_direction(widget);
+  data.homogeneous = gtk_box_get_homogeneous(GTK_BOX(widget));
+  data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
+  data.homogeneous_child_width =
+      (allocation->width - data.border_width * 2 -
+       (visible_children_count - 1) * gtk_box_get_spacing(GTK_BOX(widget))) /
+      visible_children_count;
+
+  // Shrink or hide children if necessary.
+  gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data);
+
+  // Record current width requisition of visible children, so we can know if
+  // it's necessary to show invisible children next time.
+  gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
+                        &box->children_width_requisition);
+}
+
+GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly,
+                                          gboolean homogeneous,
+                                          gint spacing) {
+  return GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_SHRINKABLE_HBOX,
+                                 "hide-child-directly", hide_child_directly,
+                                 "homogeneous", homogeneous,
+                                 "spacing", spacing,
+                                 NULL));
+}
+
+void gtk_chrome_shrinkable_hbox_set_hide_child_directly(
+    GtkChromeShrinkableHBox* box, gboolean hide_child_directly) {
+  g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
+
+  if (hide_child_directly != box->hide_child_directly) {
+    box->hide_child_directly = hide_child_directly;
+    g_object_notify(G_OBJECT(box), "hide-child-directly");
+    gtk_widget_queue_resize(GTK_WIDGET(box));
+  }
+}
+
+gboolean gtk_chrome_shrinkable_hbox_get_hide_child_directly(
+    GtkChromeShrinkableHBox* box) {
+  g_return_val_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box), FALSE);
+
+  return box->hide_child_directly;
+}
+
+void gtk_chrome_shrinkable_hbox_pack_start(GtkChromeShrinkableHBox* box,
+                                           GtkWidget* child,
+                                           guint padding) {
+  g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
+  g_return_if_fail(GTK_IS_WIDGET(child));
+
+  gtk_box_pack_start(GTK_BOX(box), child, FALSE, FALSE, 0);
+}
+
+void gtk_chrome_shrinkable_hbox_pack_end(GtkChromeShrinkableHBox* box,
+                                         GtkWidget* child,
+                                         guint padding) {
+  g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
+  g_return_if_fail(GTK_IS_WIDGET(child));
+
+  gtk_box_pack_end(GTK_BOX(box), child, FALSE, FALSE, 0);
+}
+
+gint gtk_chrome_shrinkable_hbox_get_visible_child_count(
+    GtkChromeShrinkableHBox* box) {
+  gint visible_children_count = 0;
+  gtk_container_foreach(GTK_CONTAINER(box), CountVisibleChildren,
+                        &visible_children_count);
+  return visible_children_count;
+}
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h b/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h
new file mode 100644
index 0000000..240021a
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_GTK_GTK_CHROME_SHRINKABLE_HBOX_H_
+#define CHROME_BROWSER_UI_GTK_GTK_CHROME_SHRINKABLE_HBOX_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+// A specialized container derived from GtkHBox, which can shrink or hide its
+// children one by one to fit into its width.
+//
+// Limitations of this container:
+// - All children should have the same pack type, otherwise they may be
+//   overlapped with each other.
+// - All children must be packed with expand == false and fill == false,
+//   otherwise they may be overlapped with each other.
+// - The visibility of a child is adjusted automatically according to the
+//   container's width. The child may not show or hide itself.
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CHROME_SHRINKABLE_HBOX                                 \
+    (gtk_chrome_shrinkable_hbox_get_type())
+#define GTK_CHROME_SHRINKABLE_HBOX(obj)                                 \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CHROME_SHRINKABLE_HBOX, \
+                                GtkChromeShrinkableHBox))
+#define GTK_CHROME_SHRINKABLE_HBOX_CLASS(klass)                         \
+    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CHROME_SHRINKABLE_HBOX,  \
+                             GtkChromeShrinkableHBoxClass))
+#define GTK_IS_CHROME_SHRINKABLE_HBOX(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHROME_SHRINKABLE_HBOX))
+#define GTK_IS_CHROME_SHRINKABLE_HBOX_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHROME_SHRINKABLE_HBOX))
+#define GTK_CHROME_SHRINKABLE_HBOX_GET_CLASS(obj)                       \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHROME_SHRINKABLE_HBOX,  \
+                               GtkChromeShrinkableHBoxClass))
+
+typedef struct _GtkChromeShrinkableHBox GtkChromeShrinkableHBox;
+typedef struct _GtkChromeShrinkableHBoxClass GtkChromeShrinkableHBoxClass;
+
+struct _GtkChromeShrinkableHBox {
+  // Parent class.
+  GtkHBox hbox;
+
+  gboolean hide_child_directly;
+
+  // Private
+  int children_width_requisition;
+};
+
+struct _GtkChromeShrinkableHBoxClass {
+  GtkHBoxClass parent_class;
+};
+
+GType gtk_chrome_shrinkable_hbox_get_type() G_GNUC_CONST;
+
+// Creates a new shrinkable hbox.
+// If |hide_child_directly| is true then its child widgets will be hid directly
+// if they are too wide to be fit into the hbox's width. Otherwise they will be
+// shrunk first before being hid completely.
+GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly,
+                                          gboolean homogeneous,
+                                          gint spacing);
+
+void gtk_chrome_shrinkable_hbox_set_hide_child_directly(
+    GtkChromeShrinkableHBox* box, gboolean hide_child_directly);
+
+gboolean gtk_chrome_shrinkable_hbox_get_hide_child_directly(
+    GtkChromeShrinkableHBox* box);
+
+void gtk_chrome_shrinkable_hbox_pack_start(GtkChromeShrinkableHBox* box,
+                                           GtkWidget* child,
+                                           guint padding);
+
+void gtk_chrome_shrinkable_hbox_pack_end(GtkChromeShrinkableHBox* box,
+                                         GtkWidget* child,
+                                         guint padding);
+
+gint gtk_chrome_shrinkable_hbox_get_visible_child_count(
+    GtkChromeShrinkableHBox* box);
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_CHROME_SHRINKABLE_HBOX_H_
diff --git a/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox_unittest.cc b/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
new file mode 100644
index 0000000..226ebe7
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
@@ -0,0 +1,254 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
+
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const int kSpacing = 3;
+const int kBorderWidth = 5;
+
+}  // namespace
+
+class GtkChromeShrinkableHBoxTest : public testing::Test {
+ protected:
+  GtkChromeShrinkableHBoxTest()
+      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
+        box_(gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, kSpacing)) {
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
+    gtk_window_set_default_size(GTK_WINDOW(window_), 200, 200);
+    gtk_container_add(GTK_CONTAINER(window_), box_);
+    gtk_container_set_border_width(GTK_CONTAINER(box_), kBorderWidth);
+  }
+
+  ~GtkChromeShrinkableHBoxTest() {
+    gtk_widget_destroy(window_);
+  }
+
+  // Add some children widgets with arbitrary width and padding.
+  void AddChildren(bool pack_start) {
+    static struct {
+      int width;
+      int padding;
+    } kChildrenData[] = {
+      { 60, 2 },
+      { 70, 3 },
+      { 80, 5 },
+      { 50, 7 },
+      { 40, 11 },
+      { 60, 0 },
+      { 0, 0 }
+    };
+
+    for (size_t i = 0; kChildrenData[i].width; ++i) {
+      GtkWidget* child = gtk_fixed_new();
+      gtk_widget_set_size_request(child, kChildrenData[i].width, -1);
+      if (pack_start) {
+        gtk_chrome_shrinkable_hbox_pack_start(
+            GTK_CHROME_SHRINKABLE_HBOX(box_), child, kChildrenData[i].padding);
+      } else {
+        gtk_chrome_shrinkable_hbox_pack_end(
+            GTK_CHROME_SHRINKABLE_HBOX(box_), child, kChildrenData[i].padding);
+      }
+    }
+  }
+
+  // Check if all children's size allocation are inside the |box_|'s boundary.
+  void Validate(bool pack_start) {
+    std::vector<ChildData> children_data;
+    gtk_container_foreach(GTK_CONTAINER(box_), CollectChildData,
+                          &children_data);
+
+    size_t children_count = children_data.size();
+    size_t visible_children_count = 0;
+    for (size_t i = 0; i < children_count; ++i) {
+      if (children_data[i].visible)
+        ++visible_children_count;
+    }
+
+    if (visible_children_count == 0)
+      return;
+
+    int border_width = gtk_container_get_border_width(GTK_CONTAINER(box_));
+    int x = box_->allocation.x + border_width;
+    int width = box_->allocation.width - border_width * 2;
+    int spacing = gtk_box_get_spacing(GTK_BOX(box_));
+    bool homogeneous = gtk_box_get_homogeneous(GTK_BOX(box_));
+
+    if (homogeneous) {
+      // If the |box_| is in homogeneous mode, then check if the visible
+      // children are not overlapped with each other.
+      int homogeneous_child_width =
+          (width - (visible_children_count - 1) * spacing) /
+          visible_children_count;
+
+      for (size_t i = 0; i < children_count; ++i) {
+        SCOPED_TRACE(testing::Message() << "Validate homogeneous child " << i
+                     << " visible: " << children_data[i].visible
+                     << " padding: " << children_data[i].padding
+                     << " x: " << children_data[i].x
+                     << " width: " << children_data[i].width);
+
+        if (children_data[i].visible)
+          ASSERT_LE(children_data[i].width, homogeneous_child_width);
+      }
+    } else {
+      // If the |box_| is not in homogeneous mode, then just check if all
+      // visible children are inside the |box_|'s boundary. And for those
+      // hidden children which are out of the boundary, they should only
+      // be hidden one by one from the end of the |box_|.
+      bool last_visible = pack_start;
+      bool visibility_changed = false;
+      for (size_t i = 0; i < children_count; ++i) {
+        SCOPED_TRACE(testing::Message() << "Validate child " << i
+                     << " visible: " << children_data[i].visible
+                     << " padding: " << children_data[i].padding
+                     << " x: " << children_data[i].x
+                     << " width: " << children_data[i].width);
+
+        if (last_visible != children_data[i].visible) {
+          ASSERT_FALSE(visibility_changed);
+          visibility_changed = true;
+          last_visible = children_data[i].visible;
+        }
+        if (children_data[i].visible) {
+          ASSERT_GE(children_data[i].x,
+                    x + children_data[i].padding);
+          ASSERT_LE(children_data[i].x + children_data[i].width,
+                    x + width - children_data[i].padding);
+        }
+      }
+    }
+  }
+
+  void Test(bool pack_start) {
+    gtk_widget_show_all(window_);
+    GtkAllocation allocation = { 0, 0, 0, 200 };
+    gtk_chrome_shrinkable_hbox_set_hide_child_directly(
+        GTK_CHROME_SHRINKABLE_HBOX(box_), FALSE);
+    for (int width = 500; width > kBorderWidth * 2; --width) {
+      SCOPED_TRACE(testing::Message() << "Shrink hide_child_directly = FALSE,"
+                   << " width = " << width);
+
+      allocation.width = width;
+      // Reducing the width may cause some children to be hidden, which will
+      // cause queue resize, so it's necessary to do another size allocation to
+      // emulate the queue resize.
+      gtk_widget_size_allocate(box_, &allocation);
+      gtk_widget_size_allocate(box_, &allocation);
+      ASSERT_NO_FATAL_FAILURE(Validate(pack_start)) << "width = " << width;
+    }
+
+    for (int width = kBorderWidth * 2; width <= 500; ++width) {
+      SCOPED_TRACE(testing::Message() << "Expand hide_child_directly = FALSE,"
+                   << " width = " << width);
+
+      allocation.width = width;
+      // Expanding the width may cause some invisible children to be shown,
+      // which will cause queue resize, so it's necessary to do another size
+      // allocation to emulate the queue resize.
+      gtk_widget_size_allocate(box_, &allocation);
+      gtk_widget_size_allocate(box_, &allocation);
+      ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
+    }
+
+    gtk_chrome_shrinkable_hbox_set_hide_child_directly(
+        GTK_CHROME_SHRINKABLE_HBOX(box_), TRUE);
+    for (int width = 500; width > kBorderWidth * 2; --width) {
+      SCOPED_TRACE(testing::Message() << "Shrink hide_child_directly = TRUE,"
+                   << " width = " << width);
+
+      allocation.width = width;
+      gtk_widget_size_allocate(box_, &allocation);
+      gtk_widget_size_allocate(box_, &allocation);
+      ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
+    }
+
+    for (int width = kBorderWidth * 2; width <= 500; ++width) {
+      SCOPED_TRACE(testing::Message() << "Expand hide_child_directly = TRUE,"
+                   << " width = " << width);
+
+      allocation.width = width;
+      gtk_widget_size_allocate(box_, &allocation);
+      gtk_widget_size_allocate(box_, &allocation);
+      ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
+    }
+  }
+
+ protected:
+  GtkWidget* window_;
+  GtkWidget* box_;
+
+ private:
+  struct ChildData {
+    bool visible;
+    int padding;
+    int x;
+    int width;
+  };
+
+  static void CollectChildData(GtkWidget* child, gpointer userdata) {
+    guint padding;
+    gtk_box_query_child_packing(GTK_BOX(gtk_widget_get_parent(child)), child,
+                                NULL, NULL, &padding, NULL);
+
+    ChildData data;
+    data.visible = GTK_WIDGET_VISIBLE(child);
+    data.padding = padding;
+    data.x = child->allocation.x;
+    data.width = child->allocation.width;
+
+    reinterpret_cast<std::vector<ChildData>*>(userdata)->push_back(data);
+  }
+};
+
+TEST_F(GtkChromeShrinkableHBoxTest, PackStart) {
+  AddChildren(true);
+
+  {
+    SCOPED_TRACE("Test LTR");
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
+    EXPECT_NO_FATAL_FAILURE(Test(true));
+  }
+  {
+    SCOPED_TRACE("Test RTL");
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
+    EXPECT_NO_FATAL_FAILURE(Test(true));
+  }
+}
+
+TEST_F(GtkChromeShrinkableHBoxTest, PackEnd) {
+  AddChildren(false);
+
+  {
+    SCOPED_TRACE("Test LTR");
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
+    EXPECT_NO_FATAL_FAILURE(Test(false));
+  }
+  {
+    SCOPED_TRACE("Test RTL");
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
+    EXPECT_NO_FATAL_FAILURE(Test(false));
+  }
+}
+
+TEST_F(GtkChromeShrinkableHBoxTest, Homogeneous) {
+  AddChildren(true);
+  gtk_box_set_homogeneous(GTK_BOX(box_), true);
+
+  {
+    SCOPED_TRACE("Test LTR");
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
+    EXPECT_NO_FATAL_FAILURE(Test(true));
+  }
+  {
+    SCOPED_TRACE("Test RTL");
+    gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
+    EXPECT_NO_FATAL_FAILURE(Test(true));
+  }
+}
diff --git a/chrome/browser/ui/gtk/gtk_custom_menu.cc b/chrome/browser/ui/gtk/gtk_custom_menu.cc
new file mode 100644
index 0000000..f6119dd
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_custom_menu.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/gtk_custom_menu.h"
+
+#include "chrome/browser/ui/gtk/gtk_custom_menu_item.h"
+
+G_DEFINE_TYPE(GtkCustomMenu, gtk_custom_menu, GTK_TYPE_MENU)
+
+// Stolen directly from gtkmenushell.c. I'd love to call the library version
+// instead, but it's static and isn't exported. :(
+static gint gtk_menu_shell_is_item(GtkMenuShell* menu_shell,
+                                   GtkWidget* child) {
+  GtkWidget *parent;
+
+  g_return_val_if_fail(GTK_IS_MENU_SHELL(menu_shell), FALSE);
+  g_return_val_if_fail(child != NULL, FALSE);
+
+  parent = child->parent;
+  while (GTK_IS_MENU_SHELL(parent)) {
+    if (parent == reinterpret_cast<GtkWidget*>(menu_shell))
+      return TRUE;
+    parent = GTK_MENU_SHELL(parent)->parent_menu_shell;
+  }
+
+  return FALSE;
+}
+
+// Stolen directly from gtkmenushell.c. I'd love to call the library version
+// instead, but it's static and isn't exported. :(
+static GtkWidget* gtk_menu_shell_get_item(GtkMenuShell* menu_shell,
+                                          GdkEvent* event) {
+  GtkWidget* menu_item = gtk_get_event_widget(event);
+
+  while (menu_item && !GTK_IS_MENU_ITEM(menu_item))
+    menu_item = menu_item->parent;
+
+  if (menu_item && gtk_menu_shell_is_item(menu_shell, menu_item))
+    return menu_item;
+  else
+    return NULL;
+}
+
+// When processing a button event, abort processing if the cursor isn't in a
+// clickable region.
+static gboolean gtk_custom_menu_button_press(GtkWidget* widget,
+                                             GdkEventButton* event) {
+  GtkWidget* menu_item = gtk_menu_shell_get_item(
+      GTK_MENU_SHELL(widget), reinterpret_cast<GdkEvent*>(event));
+  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
+    if (!gtk_custom_menu_item_is_in_clickable_region(
+            GTK_CUSTOM_MENU_ITEM(menu_item))) {
+      return TRUE;
+    }
+  }
+
+  return GTK_WIDGET_CLASS(gtk_custom_menu_parent_class)->
+      button_press_event(widget, event);
+}
+
+// When processing a button event, abort processing if the cursor isn't in a
+// clickable region. If it's in a button that doesn't dismiss the menu, fire
+// that event and abort having the normal GtkMenu code run.
+static gboolean gtk_custom_menu_button_release(GtkWidget* widget,
+                                               GdkEventButton* event) {
+  GtkWidget* menu_item = gtk_menu_shell_get_item(
+      GTK_MENU_SHELL(widget), reinterpret_cast<GdkEvent*>(event));
+  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
+    if (!gtk_custom_menu_item_is_in_clickable_region(
+            GTK_CUSTOM_MENU_ITEM(menu_item))) {
+      // Stop processing this event. This isn't a clickable region.
+      return TRUE;
+    }
+
+    if (gtk_custom_menu_item_try_no_dismiss_command(
+            GTK_CUSTOM_MENU_ITEM(menu_item))) {
+      return TRUE;
+    }
+  }
+
+  return GTK_WIDGET_CLASS(gtk_custom_menu_parent_class)->
+      button_release_event(widget, event);
+}
+
+// Manually forward button press events to the menu item (and then do what we'd
+// do normally).
+static gboolean gtk_custom_menu_motion_notify(GtkWidget* widget,
+                                              GdkEventMotion* event) {
+  GtkWidget* menu_item = gtk_menu_shell_get_item(
+      GTK_MENU_SHELL(widget), (GdkEvent*)event);
+  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
+    gtk_custom_menu_item_receive_motion_event(GTK_CUSTOM_MENU_ITEM(menu_item),
+                                              event->x, event->y);
+  }
+
+  return GTK_WIDGET_CLASS(gtk_custom_menu_parent_class)->
+      motion_notify_event(widget, event);
+}
+
+static void gtk_custom_menu_move_current(GtkMenuShell* menu_shell,
+                                         GtkMenuDirectionType direction) {
+  // If the currently selected item is custom, we give it first chance to catch
+  // up/down events.
+
+  // TODO(erg): We are breaking a GSEAL by directly accessing this. We'll need
+  // to fix this by the time gtk3 comes out.
+  GtkWidget* menu_item = GTK_MENU_SHELL(menu_shell)->active_menu_item;
+  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
+    switch (direction) {
+      case GTK_MENU_DIR_PREV:
+      case GTK_MENU_DIR_NEXT:
+        if (gtk_custom_menu_item_handle_move(GTK_CUSTOM_MENU_ITEM(menu_item),
+                                             direction))
+          return;
+        break;
+      default:
+        break;
+    }
+  }
+
+  GTK_MENU_SHELL_CLASS(gtk_custom_menu_parent_class)->
+      move_current(menu_shell, direction);
+
+  // In the case of hitting PREV and transitioning to a custom menu, we want to
+  // make sure we're selecting the final item in the list, not the first one.
+  menu_item = GTK_MENU_SHELL(menu_shell)->active_menu_item;
+  if (GTK_IS_CUSTOM_MENU_ITEM(menu_item)) {
+    gtk_custom_menu_item_select_item_by_direction(
+        GTK_CUSTOM_MENU_ITEM(menu_item), direction);
+  }
+}
+
+static void gtk_custom_menu_init(GtkCustomMenu* menu) {
+}
+
+static void gtk_custom_menu_class_init(GtkCustomMenuClass* klass) {
+  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
+  GtkMenuShellClass* menu_shell_class = GTK_MENU_SHELL_CLASS(klass);
+
+  widget_class->button_press_event = gtk_custom_menu_button_press;
+  widget_class->button_release_event = gtk_custom_menu_button_release;
+  widget_class->motion_notify_event = gtk_custom_menu_motion_notify;
+
+  menu_shell_class->move_current = gtk_custom_menu_move_current;
+}
+
+GtkWidget* gtk_custom_menu_new() {
+  return GTK_WIDGET(g_object_new(GTK_TYPE_CUSTOM_MENU, NULL));
+}
diff --git a/chrome/browser/ui/gtk/gtk_custom_menu.h b/chrome/browser/ui/gtk/gtk_custom_menu.h
new file mode 100644
index 0000000..e832cb0
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_custom_menu.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_H_
+#define CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_H_
+#pragma once
+
+// GtkCustomMenu is a GtkMenu subclass that can contain, and collaborates with,
+// GtkCustomMenuItem instances. GtkCustomMenuItem is a GtkMenuItem that can
+// have buttons and other normal widgets embeded in it. GtkCustomMenu exists
+// only to override most of the button/motion/move callback functions so
+// that the normal GtkMenu implementation doesn't handle events related to
+// GtkCustomMenuItem items.
+//
+// For a more through overview of this system, see the comments in
+// gtk_custom_menu_item.h.
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkmenuitem.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CUSTOM_MENU                                            \
+  (gtk_custom_menu_get_type())
+#define GTK_CUSTOM_MENU(obj)                                            \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CUSTOM_MENU, GtkCustomMenu))
+#define GTK_CUSTOM_MENU_CLASS(klass)                                    \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CUSTOM_MENU, GtkCustomMenuClass))
+#define GTK_IS_CUSTOM_MENU(obj)                                         \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CUSTOM_MENU))
+#define GTK_IS_CUSTOM_MENU_CLASS(klass)                                 \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CUSTOM_MENU))
+#define GTK_CUSTOM_MENU_GET_CLASS(obj)                                  \
+  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CUSTOM_MENU, GtkCustomMenuClass))
+
+typedef struct _GtkCustomMenu GtkCustomMenu;
+typedef struct _GtkCustomMenuClass GtkCustomMenuClass;
+
+struct _GtkCustomMenu {
+  GtkMenu menu;
+};
+
+struct _GtkCustomMenuClass {
+  GtkMenuClass parent_class;
+};
+
+GType gtk_custom_menu_get_type(void) G_GNUC_CONST;
+GtkWidget* gtk_custom_menu_new();
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_H_
diff --git a/chrome/browser/ui/gtk/gtk_custom_menu_item.cc b/chrome/browser/ui/gtk/gtk_custom_menu_item.cc
new file mode 100644
index 0000000..f358f97
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_custom_menu_item.cc
@@ -0,0 +1,434 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_custom_menu_item.h"
+
+#include "base/i18n/rtl.h"
+#include "chrome/browser/ui/gtk/gtk_custom_menu.h"
+
+enum {
+  BUTTON_PUSHED,
+  TRY_BUTTON_PUSHED,
+  LAST_SIGNAL
+};
+
+static guint custom_menu_item_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE(GtkCustomMenuItem, gtk_custom_menu_item, GTK_TYPE_MENU_ITEM)
+
+static void set_selected(GtkCustomMenuItem* item, GtkWidget* selected) {
+  if (selected != item->currently_selected_button) {
+    if (item->currently_selected_button) {
+      gtk_widget_set_state(item->currently_selected_button, GTK_STATE_NORMAL);
+      gtk_widget_set_state(
+          gtk_bin_get_child(GTK_BIN(item->currently_selected_button)),
+          GTK_STATE_NORMAL);
+    }
+
+    item->currently_selected_button = selected;
+    if (item->currently_selected_button) {
+      gtk_widget_set_state(item->currently_selected_button, GTK_STATE_SELECTED);
+      gtk_widget_set_state(
+          gtk_bin_get_child(GTK_BIN(item->currently_selected_button)),
+          GTK_STATE_PRELIGHT);
+    }
+  }
+}
+
+// When GtkButtons set the label text, they rebuild the widget hierarchy each
+// and every time. Therefore, we can't just fish out the label from the button
+// and set some properties; we have to create this callback function that
+// listens on the button's "notify" signal, which is emitted right after the
+// label has been (re)created. (Label values can change dynamically.)
+static void on_button_label_set(GObject* object) {
+  GtkButton* button = GTK_BUTTON(object);
+  gtk_widget_set_sensitive(GTK_BIN(button)->child, FALSE);
+  gtk_misc_set_padding(GTK_MISC(GTK_BIN(button)->child), 2, 0);
+}
+
+static void gtk_custom_menu_item_finalize(GObject *object);
+static gint gtk_custom_menu_item_expose(GtkWidget* widget,
+                                        GdkEventExpose* event);
+static gboolean gtk_custom_menu_item_hbox_expose(GtkWidget* widget,
+                                                 GdkEventExpose* event,
+                                                 GtkCustomMenuItem* menu_item);
+static void gtk_custom_menu_item_select(GtkItem *item);
+static void gtk_custom_menu_item_deselect(GtkItem *item);
+static void gtk_custom_menu_item_activate(GtkMenuItem* menu_item);
+
+static void gtk_custom_menu_item_init(GtkCustomMenuItem* item) {
+  item->all_widgets = NULL;
+  item->button_widgets = NULL;
+  item->currently_selected_button = NULL;
+  item->previously_selected_button = NULL;
+
+  GtkWidget* menu_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(item), menu_hbox);
+
+  item->label = gtk_label_new(NULL);
+  gtk_misc_set_alignment(GTK_MISC(item->label), 0.0, 0.5);
+  gtk_box_pack_start(GTK_BOX(menu_hbox), item->label, TRUE, TRUE, 0);
+
+  item->hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(menu_hbox), item->hbox, FALSE, FALSE, 0);
+
+  g_signal_connect(item->hbox, "expose-event",
+                   G_CALLBACK(gtk_custom_menu_item_hbox_expose),
+                   item);
+
+  gtk_widget_show_all(menu_hbox);
+}
+
+static void gtk_custom_menu_item_class_init(GtkCustomMenuItemClass* klass) {
+  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
+  GtkItemClass* item_class = GTK_ITEM_CLASS(klass);
+  GtkMenuItemClass* menu_item_class = GTK_MENU_ITEM_CLASS(klass);
+
+  gobject_class->finalize = gtk_custom_menu_item_finalize;
+
+  widget_class->expose_event = gtk_custom_menu_item_expose;
+
+  item_class->select = gtk_custom_menu_item_select;
+  item_class->deselect = gtk_custom_menu_item_deselect;
+
+  menu_item_class->activate = gtk_custom_menu_item_activate;
+
+  custom_menu_item_signals[BUTTON_PUSHED] =
+      g_signal_new("button-pushed",
+                   G_OBJECT_CLASS_TYPE(gobject_class),
+                   G_SIGNAL_RUN_FIRST,
+                   0,
+                   NULL, NULL,
+                   gtk_marshal_NONE__INT,
+                   G_TYPE_NONE, 1, GTK_TYPE_INT);
+  // TODO(erg): Change from BOOL__POINTER to BOOLEAN__INTEGER when we get to
+  // use a modern GTK+.
+  custom_menu_item_signals[TRY_BUTTON_PUSHED] =
+      g_signal_new("try-button-pushed",
+                   G_OBJECT_CLASS_TYPE(gobject_class),
+                   G_SIGNAL_RUN_LAST,
+                   0,
+                   NULL, NULL,
+                   gtk_marshal_BOOL__POINTER,
+                   G_TYPE_BOOLEAN, 1, GTK_TYPE_INT);
+}
+
+static void gtk_custom_menu_item_finalize(GObject *object) {
+  GtkCustomMenuItem* item = GTK_CUSTOM_MENU_ITEM(object);
+  g_list_free(item->all_widgets);
+  g_list_free(item->button_widgets);
+
+  G_OBJECT_CLASS(gtk_custom_menu_item_parent_class)->finalize(object);
+}
+
+static gint gtk_custom_menu_item_expose(GtkWidget* widget,
+                                        GdkEventExpose* event) {
+  if (GTK_WIDGET_VISIBLE(widget) &&
+      GTK_WIDGET_MAPPED(widget) &&
+      gtk_bin_get_child(GTK_BIN(widget))) {
+    // We skip the drawing in the GtkMenuItem class it draws the highlighted
+    // background and we don't want that.
+    gtk_container_propagate_expose(GTK_CONTAINER(widget),
+                                   gtk_bin_get_child(GTK_BIN(widget)),
+                                   event);
+  }
+
+  return FALSE;
+}
+
+static void gtk_custom_menu_item_expose_button(GtkWidget* hbox,
+                                               GdkEventExpose* event,
+                                               GList* button_item) {
+  // We search backwards to find the leftmost and rightmost buttons. The
+  // current button may be that button.
+  GtkWidget* current_button = GTK_WIDGET(button_item->data);
+  GtkWidget* first_button = current_button;
+  for (GList* i = button_item; i && GTK_IS_BUTTON(i->data);
+       i = g_list_previous(i)) {
+    first_button = GTK_WIDGET(i->data);
+  }
+
+  GtkWidget* last_button = current_button;
+  for (GList* i = button_item; i && GTK_IS_BUTTON(i->data);
+       i = g_list_next(i)) {
+    last_button = GTK_WIDGET(i->data);
+  }
+
+  if (base::i18n::IsRTL())
+    std::swap(first_button, last_button);
+
+  int x = first_button->allocation.x;
+  int y = first_button->allocation.y;
+  int width = last_button->allocation.width + last_button->allocation.x -
+              first_button->allocation.x;
+  int height = last_button->allocation.height;
+
+  gtk_paint_box(hbox->style, hbox->window,
+                static_cast<GtkStateType>(
+                    GTK_WIDGET_STATE(current_button)),
+                GTK_SHADOW_OUT,
+                &current_button->allocation, hbox, "button",
+                x, y, width, height);
+
+  // Propagate to the button's children.
+  gtk_container_propagate_expose(
+      GTK_CONTAINER(current_button),
+      gtk_bin_get_child(GTK_BIN(current_button)),
+      event);
+}
+
+static gboolean gtk_custom_menu_item_hbox_expose(GtkWidget* widget,
+                                                 GdkEventExpose* event,
+                                                 GtkCustomMenuItem* menu_item) {
+  // First render all the buttons that aren't the currently selected item.
+  for (GList* current_item = menu_item->all_widgets;
+       current_item != NULL; current_item = g_list_next(current_item)) {
+    if (GTK_IS_BUTTON(current_item->data)) {
+      if (GTK_WIDGET(current_item->data) !=
+          menu_item->currently_selected_button) {
+        gtk_custom_menu_item_expose_button(widget, event, current_item);
+      }
+    }
+  }
+
+  // As a separate pass, draw the buton separators above. We need to draw the
+  // separators in a separate pass because we are drawing on top of the
+  // buttons. Otherwise, the vlines are overwritten by the next button.
+  for (GList* current_item = menu_item->all_widgets;
+       current_item != NULL; current_item = g_list_next(current_item)) {
+    if (GTK_IS_BUTTON(current_item->data)) {
+      // Check to see if this is the last button in a run.
+      GList* next_item = g_list_next(current_item);
+      if (next_item && GTK_IS_BUTTON(next_item->data)) {
+        GtkWidget* current_button = GTK_WIDGET(current_item->data);
+        GtkAllocation child_alloc =
+            gtk_bin_get_child(GTK_BIN(current_button))->allocation;
+        int half_offset = widget->style->xthickness / 2;
+        gtk_paint_vline(widget->style, widget->window,
+                        static_cast<GtkStateType>(
+                            GTK_WIDGET_STATE(current_button)),
+                        &event->area, widget, "button",
+                        child_alloc.y,
+                        child_alloc.y + child_alloc.height,
+                        current_button->allocation.x +
+                        current_button->allocation.width - half_offset);
+      }
+    }
+  }
+
+  // Finally, draw the selected item on top of the separators so there are no
+  // artifacts inside the button area.
+  GList* selected = g_list_find(menu_item->all_widgets,
+                                menu_item->currently_selected_button);
+  if (selected) {
+    gtk_custom_menu_item_expose_button(widget, event, selected);
+  }
+
+  return TRUE;
+}
+
+static void gtk_custom_menu_item_select(GtkItem* item) {
+  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(item);
+
+  // When we are selected, the only thing we do is clear information from
+  // previous selections. Actual selection of a button is done either in the
+  // "mouse-motion-event" or is manually set from GtkCustomMenu's overridden
+  // "move-current" handler.
+  custom_item->previously_selected_button = NULL;
+
+  gtk_widget_queue_draw(GTK_WIDGET(item));
+}
+
+static void gtk_custom_menu_item_deselect(GtkItem* item) {
+  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(item);
+
+  // When we are deselected, we store the item that was currently selected so
+  // that it can be acted on. Menu items are first deselected before they are
+  // activated.
+  custom_item->previously_selected_button =
+      custom_item->currently_selected_button;
+  if (custom_item->currently_selected_button)
+    set_selected(custom_item, NULL);
+
+  gtk_widget_queue_draw(GTK_WIDGET(item));
+}
+
+static void gtk_custom_menu_item_activate(GtkMenuItem* menu_item) {
+  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(menu_item);
+
+  // We look at |previously_selected_button| because by the time we've been
+  // activated, we've already gone through our deselect handler.
+  if (custom_item->previously_selected_button) {
+    gpointer id_ptr = g_object_get_data(
+        G_OBJECT(custom_item->previously_selected_button), "command-id");
+    if (id_ptr != NULL) {
+      int command_id = GPOINTER_TO_INT(id_ptr);
+      g_signal_emit(custom_item, custom_menu_item_signals[BUTTON_PUSHED], 0,
+                    command_id);
+      set_selected(custom_item, NULL);
+    }
+  }
+}
+
+GtkWidget* gtk_custom_menu_item_new(const char* title) {
+  GtkCustomMenuItem* item = GTK_CUSTOM_MENU_ITEM(
+      g_object_new(GTK_TYPE_CUSTOM_MENU_ITEM, NULL));
+  gtk_label_set_text(GTK_LABEL(item->label), title);
+  return GTK_WIDGET(item);
+}
+
+GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item,
+                                           int command_id) {
+  GtkWidget* button = gtk_button_new();
+  g_object_set_data(G_OBJECT(button), "command-id",
+                    GINT_TO_POINTER(command_id));
+  gtk_box_pack_start(GTK_BOX(menu_item->hbox), button, FALSE, FALSE, 0);
+  gtk_widget_show(button);
+
+  menu_item->all_widgets = g_list_append(menu_item->all_widgets, button);
+  menu_item->button_widgets = g_list_append(menu_item->button_widgets, button);
+
+  return button;
+}
+
+GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item,
+                                                 int command_id) {
+  GtkWidget* button = gtk_button_new_with_label("");
+  g_object_set_data(G_OBJECT(button), "command-id",
+                    GINT_TO_POINTER(command_id));
+  gtk_box_pack_start(GTK_BOX(menu_item->hbox), button, FALSE, FALSE, 0);
+  g_signal_connect(button, "notify::label",
+                   G_CALLBACK(on_button_label_set), NULL);
+  gtk_widget_show(button);
+
+  menu_item->all_widgets = g_list_append(menu_item->all_widgets, button);
+
+  return button;
+}
+
+void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item) {
+  GtkWidget* fixed = gtk_fixed_new();
+  gtk_widget_set_size_request(fixed, 5, -1);
+
+  gtk_box_pack_start(GTK_BOX(menu_item->hbox), fixed, FALSE, FALSE, 0);
+  gtk_widget_show(fixed);
+
+  menu_item->all_widgets = g_list_append(menu_item->all_widgets, fixed);
+}
+
+void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item,
+                                               gdouble x, gdouble y) {
+  GtkWidget* new_selected_widget = NULL;
+  GList* current = menu_item->button_widgets;
+  for (; current != NULL; current = current->next) {
+    GtkWidget* current_widget = GTK_WIDGET(current->data);
+    GtkAllocation alloc = current_widget->allocation;
+    int offset_x, offset_y;
+    gtk_widget_translate_coordinates(current_widget, GTK_WIDGET(menu_item),
+                                     0, 0, &offset_x, &offset_y);
+    if (x >= offset_x && x < (offset_x + alloc.width) &&
+        y >= offset_y && y < (offset_y + alloc.height)) {
+      new_selected_widget = current_widget;
+      break;
+    }
+  }
+
+  set_selected(menu_item, new_selected_widget);
+}
+
+gboolean gtk_custom_menu_item_handle_move(GtkCustomMenuItem* menu_item,
+                                          GtkMenuDirectionType direction) {
+  GtkWidget* current = menu_item->currently_selected_button;
+  if (menu_item->button_widgets && current) {
+    switch (direction) {
+      case GTK_MENU_DIR_PREV: {
+        if (g_list_first(menu_item->button_widgets)->data == current)
+          return FALSE;
+
+        set_selected(menu_item, GTK_WIDGET(g_list_previous(g_list_find(
+            menu_item->button_widgets, current))->data));
+        break;
+      }
+      case GTK_MENU_DIR_NEXT: {
+        if (g_list_last(menu_item->button_widgets)->data == current)
+          return FALSE;
+
+        set_selected(menu_item, GTK_WIDGET(g_list_next(g_list_find(
+            menu_item->button_widgets, current))->data));
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  return TRUE;
+}
+
+void gtk_custom_menu_item_select_item_by_direction(
+    GtkCustomMenuItem* menu_item, GtkMenuDirectionType direction) {
+  menu_item->previously_selected_button = NULL;
+
+  // If we're just told to be selected by the menu system, select the first
+  // item.
+  if (menu_item->button_widgets) {
+    switch (direction) {
+      case GTK_MENU_DIR_PREV: {
+        GtkWidget* last_button =
+            GTK_WIDGET(g_list_last(menu_item->button_widgets)->data);
+        if (last_button)
+          set_selected(menu_item, last_button);
+        break;
+      }
+      case GTK_MENU_DIR_NEXT: {
+        GtkWidget* first_button =
+            GTK_WIDGET(g_list_first(menu_item->button_widgets)->data);
+        if (first_button)
+          set_selected(menu_item, first_button);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  gtk_widget_queue_draw(GTK_WIDGET(menu_item));
+}
+
+gboolean gtk_custom_menu_item_is_in_clickable_region(
+    GtkCustomMenuItem* menu_item) {
+  return menu_item->currently_selected_button != NULL;
+}
+
+gboolean gtk_custom_menu_item_try_no_dismiss_command(
+    GtkCustomMenuItem* menu_item) {
+  GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(menu_item);
+  gboolean activated = TRUE;
+
+  // We work with |currently_selected_button| instead of
+  // |previously_selected_button| since we haven't been "deselect"ed yet.
+  gpointer id_ptr = g_object_get_data(
+      G_OBJECT(custom_item->currently_selected_button), "command-id");
+  if (id_ptr != NULL) {
+    int command_id = GPOINTER_TO_INT(id_ptr);
+    g_signal_emit(custom_item, custom_menu_item_signals[TRY_BUTTON_PUSHED], 0,
+                  command_id, &activated);
+  }
+
+  return activated;
+}
+
+void gtk_custom_menu_item_foreach_button(GtkCustomMenuItem* menu_item,
+                                         GtkCallback callback,
+                                         gpointer callback_data) {
+  // Even though we're filtering |all_widgets| on GTK_IS_BUTTON(), this isn't
+  // equivalent to |button_widgets| because we also want the button-labels.
+  for (GList* i = menu_item->all_widgets; i && GTK_IS_BUTTON(i->data);
+       i = g_list_next(i)) {
+    if (GTK_IS_BUTTON(i->data)) {
+      callback(GTK_WIDGET(i->data), callback_data);
+    }
+  }
+}
diff --git a/chrome/browser/ui/gtk/gtk_custom_menu_item.h b/chrome/browser/ui/gtk/gtk_custom_menu_item.h
new file mode 100644
index 0000000..d0fbf1a
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_custom_menu_item.h
@@ -0,0 +1,141 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_ITEM_H_
+#define CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_ITEM_H_
+#pragma once
+
+// GtkCustomMenuItem is a GtkMenuItem subclass that has buttons in it and acts
+// to support this. GtkCustomMenuItems only render properly when put in a
+// GtkCustomMenu; there's a lot of collaboration between these two classes
+// necessary to work around how gtk normally does menus.
+//
+// We can't rely on the normal event infrastructure. While a menu is up, the
+// GtkMenu has a grab on all events. Instead of trying to pump events through
+// the normal channels, we have the GtkCustomMenu selectively forward mouse
+// motion through a back channel. The GtkCustomMenu only listens for button
+// press information so it can block the effects of the click if the cursor
+// isn't in a button in the menu item.
+//
+// A GtkCustomMenuItem doesn't try to take these signals and forward them to
+// the buttons it owns. The GtkCustomMenu class keeps track of which button is
+// selected (due to key events and mouse movement) and otherwise acts like a
+// normal GtkItem. The buttons are only for sizing and rendering; they don't
+// respond to events. Instead, when the GtkCustomMenuItem is activated by the
+// GtkMenu, it uses which button was selected as a signal of what to do.
+//
+// Users should connect to the "button-pushed" signal to be notified when a
+// button was pushed. We don't go through the normal "activate" signal because
+// we need to communicate additional information, namely which button was
+// activated.
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CUSTOM_MENU_ITEM                                       \
+  (gtk_custom_menu_item_get_type())
+#define GTK_CUSTOM_MENU_ITEM(obj)                                       \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CUSTOM_MENU_ITEM,         \
+                              GtkCustomMenuItem))
+#define GTK_CUSTOM_MENU_ITEM_CLASS(klass)                               \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CUSTOM_MENU_ITEM,          \
+                           GtkCustomMenuItemClass))
+#define GTK_IS_CUSTOM_MENU_ITEM(obj)                                    \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CUSTOM_MENU_ITEM))
+#define GTK_IS_CUSTOM_MENU_ITEM_CLASS(klass)                            \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CUSTOM_MENU_ITEM))
+#define GTK_CUSTOM_MENU_ITEM_GET_CLASS(obj)                             \
+  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CUSTOM_MENU_ITEM,          \
+                             GtkCustomMenuItemClass))
+
+typedef struct _GtkCustomMenuItem GtkCustomMenuItem;
+typedef struct _GtkCustomMenuItemClass GtkCustomMenuItemClass;
+
+struct _GtkCustomMenuItem {
+  GtkMenuItem menu_item;
+
+  // Container for button widgets.
+  GtkWidget* hbox;
+
+  // Label on left side of menu item.
+  GtkWidget* label;
+
+  // List of all widgets we added. Used to find the leftmost and rightmost
+  // continuous buttons.
+  GList* all_widgets;
+
+  // Possible button widgets. Used for keyboard navigation.
+  GList* button_widgets;
+
+  // The widget that currently has highlight.
+  GtkWidget* currently_selected_button;
+
+  // The widget that was selected *before* |currently_selected_button|. Why do
+  // we hang on to this? Because the menu system sends us a deselect signal
+  // right before activating us. We need to listen to deselect since that's
+  // what we receive when the mouse cursor leaves us entirely.
+  GtkWidget* previously_selected_button;
+};
+
+struct _GtkCustomMenuItemClass {
+  GtkMenuItemClass parent_class;
+};
+
+GType gtk_custom_menu_item_get_type(void) G_GNUC_CONST;
+GtkWidget* gtk_custom_menu_item_new(const char* title);
+
+// Adds a button to our list of items in the |hbox|.
+GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item,
+                                           int command_id);
+
+// Adds a button to our list of items in the |hbox|, but that isn't part of
+// |button_widgets| to prevent it from being activatable.
+GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item,
+                                                 int command_id);
+
+// Adds a vertical space in the |hbox|.
+void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item);
+
+// Receives a motion event from the GtkCustomMenu that contains us. We can't
+// just subscribe to motion-event or the individual widget enter/leave events
+// because the top level GtkMenu has an event grab.
+void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item,
+                                               gdouble x, gdouble y);
+
+// Notification that the menu got a cursor key event. Used to move up/down
+// within the menu buttons. Returns TRUE to stop the default signal handler
+// from running.
+gboolean gtk_custom_menu_item_handle_move(GtkCustomMenuItem* menu_item,
+                                          GtkMenuDirectionType direction);
+
+// Because we only get a generic "selected" signal when we've changed, we need
+// to have a way for the GtkCustomMenu to tell us that we were just
+// selected.
+void gtk_custom_menu_item_select_item_by_direction(
+    GtkCustomMenuItem* menu_item, GtkMenuDirectionType direction);
+
+// Whether we are currently hovering over a clickable region on the menu
+// item. Used by GtkCustomMenu to determine whether it should discard click
+// events.
+gboolean gtk_custom_menu_item_is_in_clickable_region(
+    GtkCustomMenuItem* menu_item);
+
+// If the button is released while the |currently_selected_button| isn't
+// supposed to dismiss the menu, this signals to our listeners that we want to
+// run this command if it doesn't dismiss the menu.  Returns TRUE if we acted
+// on this button click (and should prevent the normal GtkMenu machinery from
+// firing an "activate" signal).
+gboolean gtk_custom_menu_item_try_no_dismiss_command(
+    GtkCustomMenuItem* menu_item);
+
+// Calls |callback| with every button and button-label in the container.
+void gtk_custom_menu_item_foreach_button(GtkCustomMenuItem* menu_item,
+                                         GtkCallback callback,
+                                         gpointer callback_data);
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_ITEM_H_
diff --git a/chrome/browser/ui/gtk/gtk_expanded_container.cc b/chrome/browser/ui/gtk/gtk_expanded_container.cc
new file mode 100644
index 0000000..e0cf510
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_expanded_container.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_expanded_container.h"
+
+#include <gtk/gtk.h>
+
+#include <algorithm>
+
+namespace {
+
+enum {
+  CHILD_SIZE_REQUEST,
+  LAST_SIGNAL
+};
+
+guint expanded_container_signals[LAST_SIGNAL] = { 0 };
+
+struct SizeAllocateData {
+  GtkWidget* container;
+  GtkAllocation* allocation;
+  int border_width;
+};
+
+void GetChildPosition(GtkWidget* container, GtkWidget* child, int* x, int* y) {
+  GValue v = { 0 };
+  g_value_init(&v, G_TYPE_INT);
+  gtk_container_child_get_property(GTK_CONTAINER(container), child, "x", &v);
+  *x = g_value_get_int(&v);
+  gtk_container_child_get_property(GTK_CONTAINER(container), child, "y", &v);
+  *y = g_value_get_int(&v);
+  g_value_unset(&v);
+}
+
+void ChildSizeAllocate(GtkWidget* child, gpointer userdata) {
+  if (!GTK_WIDGET_VISIBLE(child))
+    return;
+
+  SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata);
+
+  GtkRequisition child_requisition;
+  child_requisition.width = data->allocation->width - data->border_width * 2;
+  child_requisition.height = data->allocation->height - data->border_width * 2;
+
+  // We need to give whoever is pulling our strings a chance to adjust the
+  // size of our children.
+  g_signal_emit(data->container,
+                expanded_container_signals[CHILD_SIZE_REQUEST], 0,
+                child, &child_requisition);
+
+  GtkAllocation child_allocation;
+  child_allocation.width = child_requisition.width;
+  child_allocation.height = child_requisition.height;
+  if (child_allocation.width < 0 || child_allocation.height < 0) {
+    gtk_widget_get_child_requisition(child, &child_requisition);
+    if (child_allocation.width < 0)
+      child_allocation.width = child_requisition.width;
+    if (child_allocation.height < 0)
+      child_allocation.height = child_requisition.height;
+  }
+
+  int x, y;
+  GetChildPosition(data->container, child, &x, &y);
+
+  child_allocation.x = x + data->border_width;
+  child_allocation.y = y + data->border_width;
+
+  if (GTK_WIDGET_NO_WINDOW(data->container)) {
+    child_allocation.x += data->allocation->x;
+    child_allocation.y += data->allocation->y;
+  }
+  gtk_widget_size_allocate(child, &child_allocation);
+}
+
+void Marshal_VOID__OBJECT_BOXED(GClosure* closure,
+                                GValue* return_value G_GNUC_UNUSED,
+                                guint n_param_values,
+                                const GValue* param_values,
+                                gpointer invocation_hint G_GNUC_UNUSED,
+                                gpointer marshal_data) {
+  typedef void (*GMarshalFunc_VOID__OBJECT_BOXED) (gpointer data1,
+                                                   gpointer arg_1,
+                                                   gpointer arg_2,
+                                                   gpointer data2);
+  register GMarshalFunc_VOID__OBJECT_BOXED callback;
+  register GCClosure *cc = reinterpret_cast<GCClosure*>(closure);
+  register gpointer data1, data2;
+
+  g_return_if_fail(n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA(closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer(param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer(param_values + 0);
+    data2 = closure->data;
+  }
+
+  callback = reinterpret_cast<GMarshalFunc_VOID__OBJECT_BOXED>(
+      marshal_data ? marshal_data : cc->callback);
+
+  callback(data1,
+           g_value_get_object(param_values + 1),
+           g_value_get_boxed(param_values + 2),
+           data2);
+}
+
+}  // namespace
+
+G_BEGIN_DECLS
+
+static void gtk_expanded_container_size_allocate(GtkWidget* widget,
+                                                 GtkAllocation* allocation);
+
+G_DEFINE_TYPE(GtkExpandedContainer, gtk_expanded_container, GTK_TYPE_FIXED)
+
+static void gtk_expanded_container_class_init(
+    GtkExpandedContainerClass *klass) {
+  GtkObjectClass* object_class =
+      reinterpret_cast<GtkObjectClass*>(klass);
+
+  GtkWidgetClass* widget_class =
+      reinterpret_cast<GtkWidgetClass*>(klass);
+  widget_class->size_allocate = gtk_expanded_container_size_allocate;
+
+  expanded_container_signals[CHILD_SIZE_REQUEST] =
+      g_signal_new("child-size-request",
+                   G_OBJECT_CLASS_TYPE(object_class),
+                   static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST),
+                   0,
+                   NULL, NULL,
+                   Marshal_VOID__OBJECT_BOXED,
+                   G_TYPE_NONE, 2,
+                   GTK_TYPE_WIDGET,
+                   GTK_TYPE_REQUISITION | G_SIGNAL_TYPE_STATIC_SCOPE);
+}
+
+static void gtk_expanded_container_init(GtkExpandedContainer* container) {
+}
+
+static void gtk_expanded_container_size_allocate(GtkWidget* widget,
+                                                 GtkAllocation* allocation) {
+  widget->allocation = *allocation;
+
+  if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
+    gdk_window_move_resize(widget->window,
+                           allocation->x,
+                           allocation->y,
+                           allocation->width,
+                           allocation->height);
+  }
+
+  SizeAllocateData data;
+  data.container = widget;
+  data.allocation = allocation;
+  data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
+
+  gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data);
+}
+
+GtkWidget* gtk_expanded_container_new() {
+  return GTK_WIDGET(g_object_new(GTK_TYPE_EXPANDED_CONTAINER, NULL));
+}
+
+void gtk_expanded_container_put(GtkExpandedContainer* container,
+                                GtkWidget* widget, gint x, gint y) {
+  g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container));
+  g_return_if_fail(GTK_IS_WIDGET(widget));
+  gtk_fixed_put(GTK_FIXED(container), widget, x, y);
+}
+
+void gtk_expanded_container_move(GtkExpandedContainer* container,
+                                 GtkWidget* widget, gint x, gint y) {
+  g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container));
+  g_return_if_fail(GTK_IS_WIDGET(widget));
+  gtk_fixed_move(GTK_FIXED(container), widget, x, y);
+}
+
+void gtk_expanded_container_set_has_window(GtkExpandedContainer* container,
+                                           gboolean has_window) {
+  g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container));
+  g_return_if_fail(!GTK_WIDGET_REALIZED(container));
+  gtk_fixed_set_has_window(GTK_FIXED(container), has_window);
+}
+
+gboolean gtk_expanded_container_get_has_window(
+    GtkExpandedContainer* container) {
+  g_return_val_if_fail(GTK_IS_EXPANDED_CONTAINER(container), FALSE);
+  return gtk_fixed_get_has_window(GTK_FIXED(container));
+}
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/gtk_expanded_container.h b/chrome/browser/ui/gtk/gtk_expanded_container.h
new file mode 100644
index 0000000..ffc9163
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_expanded_container.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_EXPANDED_CONTAINER_H_
+#define CHROME_BROWSER_UI_GTK_GTK_EXPANDED_CONTAINER_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+// A specialized container derived from GtkFixed, which expands the size of its
+// children to fill the container, in one or both directions. The usage of this
+// container is similar to GtkFixed.
+//
+// The "child-size-request" signal is optional, if you want to expand child
+// widgets to customized size other than the container's size. It should have
+// the following signature:
+//
+//   void (*child_size_request)(GtkExpandedContainer* container,
+//                              GtkWidget* child,
+//                              GtkRequisition* requisition);
+//
+// This signal is emitted for each child with the requisition set to the size of
+// the container. Your handler may adjust the value of the requisition. If the
+// width or height is set to -1, then that direction will not be expanded, and
+// the original size request of the child will be used.
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_EXPANDED_CONTAINER                                 \
+    (gtk_expanded_container_get_type())
+#define GTK_EXPANDED_CONTAINER(obj)                                 \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_EXPANDED_CONTAINER, \
+                                GtkExpandedContainer))
+#define GTK_EXPANDED_CONTAINER_CLASS(klass)                         \
+    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_EXPANDED_CONTAINER,  \
+                             GtkExpandedContainerClass))
+#define GTK_IS_EXPANDED_CONTAINER(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_EXPANDED_CONTAINER))
+#define GTK_IS_EXPANDED_CONTAINER_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_EXPANDED_CONTAINER))
+#define GTK_EXPANDED_CONTAINER_GET_CLASS(obj)                       \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_EXPANDED_CONTAINER,  \
+                               GtkExpandedContainerClass))
+
+typedef struct _GtkExpandedContainer GtkExpandedContainer;
+typedef struct _GtkExpandedContainerClass GtkExpandedContainerClass;
+
+struct _GtkExpandedContainer {
+  // Parent class.
+  GtkFixed fixed;
+};
+
+struct _GtkExpandedContainerClass {
+  GtkFixedClass parent_class;
+};
+
+GType gtk_expanded_container_get_type() G_GNUC_CONST;
+GtkWidget* gtk_expanded_container_new();
+void gtk_expanded_container_put(GtkExpandedContainer* container,
+                                GtkWidget* widget, gint x, gint y);
+void gtk_expanded_container_move(GtkExpandedContainer* container,
+                                 GtkWidget* widget, gint x, gint y);
+void gtk_expanded_container_set_has_window(GtkExpandedContainer* container,
+                                           gboolean has_window);
+gboolean gtk_expanded_container_get_has_window(GtkExpandedContainer* container);
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_EXPANDED_CONTAINER_H_
diff --git a/chrome/browser/ui/gtk/gtk_expanded_container_unittest.cc b/chrome/browser/ui/gtk/gtk_expanded_container_unittest.cc
new file mode 100644
index 0000000..77394d7
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_expanded_container_unittest.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_expanded_container.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+class GtkExpandedContainerTest : public testing::Test {
+ protected:
+  GtkExpandedContainerTest()
+      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
+        expanded_(gtk_expanded_container_new()) {
+    gtk_window_set_default_size(GTK_WINDOW(window_), 200, 200);
+    gtk_container_add(GTK_CONTAINER(window_), expanded_);
+  }
+  ~GtkExpandedContainerTest() {
+    gtk_widget_destroy(window_);
+  }
+
+  bool FindChild(GtkWidget* widget) {
+    GList* children = gtk_container_get_children(GTK_CONTAINER(expanded_));
+    for (GList* child = children; child; child = child->next) {
+      if (GTK_WIDGET(child->data) == widget) {
+        g_list_free(children);
+        return true;
+      }
+    }
+    g_list_free(children);
+    return false;
+  }
+
+  int GetChildX(GtkWidget* widget) {
+    GValue x = { 0 };
+    g_value_init(&x, G_TYPE_INT);
+    gtk_container_child_get_property(GTK_CONTAINER(expanded_), widget, "x", &x);
+    return g_value_get_int(&x);
+  }
+
+  int GetChildY(GtkWidget* widget) {
+    GValue y = { 0 };
+    g_value_init(&y, G_TYPE_INT);
+    gtk_container_child_get_property(GTK_CONTAINER(expanded_), widget, "y", &y);
+    return g_value_get_int(&y);
+  }
+
+ protected:
+  GtkWidget* window_;
+  GtkWidget* expanded_;
+};
+
+TEST_F(GtkExpandedContainerTest, AddRemove) {
+  GtkWidget* child1 = gtk_fixed_new();
+  GtkWidget* child2 = gtk_fixed_new();
+  gtk_container_add(GTK_CONTAINER(expanded_), child1);
+  ASSERT_TRUE(FindChild(child1));
+
+  gtk_container_add(GTK_CONTAINER(expanded_), child2);
+  ASSERT_TRUE(FindChild(child2));
+  ASSERT_TRUE(FindChild(child1));
+
+  gtk_container_remove(GTK_CONTAINER(expanded_), child1);
+  ASSERT_FALSE(FindChild(child1));
+  ASSERT_TRUE(FindChild(child2));
+
+  gtk_container_remove(GTK_CONTAINER(expanded_), child2);
+  ASSERT_FALSE(FindChild(child2));
+}
+
+TEST_F(GtkExpandedContainerTest, Expand) {
+  GtkWidget* child1 = gtk_fixed_new();
+  GtkWidget* child2 = gtk_fixed_new();
+  gtk_container_add(GTK_CONTAINER(expanded_), child1);
+  gtk_expanded_container_put(GTK_EXPANDED_CONTAINER(expanded_),
+                             child2, 10, 20);
+  gtk_widget_show_all(window_);
+
+  GtkAllocation allocation = { 0, 0, 50, 100 };
+  gtk_widget_size_allocate(expanded_, &allocation);
+
+  EXPECT_EQ(0, child1->allocation.x);
+  EXPECT_EQ(0, child1->allocation.y);
+  EXPECT_EQ(50, child1->allocation.width);
+  EXPECT_EQ(100, child1->allocation.height);
+
+  EXPECT_EQ(10, child2->allocation.x);
+  EXPECT_EQ(20, child2->allocation.y);
+  EXPECT_EQ(50, child2->allocation.width);
+  EXPECT_EQ(100, child2->allocation.height);
+
+  allocation.x = 10;
+  allocation.y = 20;
+  gtk_widget_size_allocate(expanded_, &allocation);
+
+  EXPECT_EQ(10, child1->allocation.x);
+  EXPECT_EQ(20, child1->allocation.y);
+  EXPECT_EQ(20, child2->allocation.x);
+  EXPECT_EQ(40, child2->allocation.y);
+}
+
+// Test if the size allocation for children still works when using own
+// GdkWindow. In this case, the children's origin starts from (0, 0) rather
+// than the container's origin.
+TEST_F(GtkExpandedContainerTest, HasWindow) {
+  GtkWidget* child = gtk_fixed_new();
+  gtk_container_add(GTK_CONTAINER(expanded_), child);
+  gtk_expanded_container_set_has_window(GTK_EXPANDED_CONTAINER(expanded_),
+                                        TRUE);
+  gtk_widget_show_all(window_);
+
+  GtkAllocation allocation = { 10, 10, 50, 100 };
+  gtk_widget_size_allocate(expanded_, &allocation);
+
+  EXPECT_EQ(0, child->allocation.x);
+  EXPECT_EQ(0, child->allocation.y);
+  EXPECT_EQ(50, child->allocation.width);
+  EXPECT_EQ(100, child->allocation.height);
+}
+
+static void OnChildSizeRequest(GtkExpandedContainer* container,
+                               GtkWidget* child,
+                               GtkRequisition* requisition,
+                               gpointer userdata) {
+  ASSERT_EQ(child, GTK_WIDGET(userdata));
+  requisition->width = 250;
+  requisition->height = -1;
+}
+
+TEST_F(GtkExpandedContainerTest, ChildSizeRequest) {
+  GtkWidget* child = gtk_fixed_new();
+  gtk_widget_set_size_request(child, 10, 25);
+  g_signal_connect(expanded_, "child-size-request",
+                   G_CALLBACK(OnChildSizeRequest), child);
+  gtk_container_add(GTK_CONTAINER(expanded_), child);
+  gtk_widget_show_all(window_);
+
+  GtkAllocation allocation = { 0, 0, 300, 100 };
+  gtk_widget_size_allocate(expanded_, &allocation);
+
+  EXPECT_EQ(0, child->allocation.x);
+  EXPECT_EQ(0, child->allocation.y);
+  EXPECT_EQ(250, child->allocation.width);
+  EXPECT_EQ(25, child->allocation.height);
+}
+
+TEST_F(GtkExpandedContainerTest, ChildPosition) {
+  GtkWidget* child = gtk_fixed_new();
+  gtk_expanded_container_put(GTK_EXPANDED_CONTAINER(expanded_),
+                             child, 10, 20);
+  gtk_widget_show_all(window_);
+
+  EXPECT_EQ(10, GetChildX(child));
+  EXPECT_EQ(20, GetChildY(child));
+
+  gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(expanded_),
+                              child, 40, 50);
+  EXPECT_EQ(40, GetChildX(child));
+  EXPECT_EQ(50, GetChildY(child));
+}
diff --git a/chrome/browser/ui/gtk/gtk_floating_container.cc b/chrome/browser/ui/gtk/gtk_floating_container.cc
new file mode 100644
index 0000000..e3891a6
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_floating_container.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_floating_container.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkmarshal.h>
+#include <gtk/gtkprivate.h>
+
+#include <algorithm>
+
+namespace {
+
+enum {
+  SET_FLOATING_POSITION,
+  LAST_SIGNAL
+};
+
+enum {
+  CHILD_PROP_0,
+  CHILD_PROP_X,
+  CHILD_PROP_Y
+};
+
+// Returns the GtkFloatingContainerChild associated with |widget| (or NULL if
+// |widget| not found).
+GtkFloatingContainerChild* GetChild(GtkFloatingContainer* container,
+                                    GtkWidget* widget) {
+  for (GList* floating_children = container->floating_children;
+       floating_children; floating_children = g_list_next(floating_children)) {
+    GtkFloatingContainerChild* child =
+        reinterpret_cast<GtkFloatingContainerChild*>(floating_children->data);
+
+    if (child->widget == widget)
+      return child;
+  }
+
+  return NULL;
+}
+
+}  // namespace
+
+G_BEGIN_DECLS
+
+static void gtk_floating_container_remove(GtkContainer* container,
+                                          GtkWidget* widget);
+static void gtk_floating_container_forall(GtkContainer* container,
+                                          gboolean include_internals,
+                                          GtkCallback callback,
+                                          gpointer callback_data);
+static void gtk_floating_container_size_request(GtkWidget* widget,
+                                                GtkRequisition* requisition);
+static void gtk_floating_container_size_allocate(GtkWidget* widget,
+                                                 GtkAllocation* allocation);
+static void gtk_floating_container_set_child_property(GtkContainer* container,
+                                                      GtkWidget* child,
+                                                      guint property_id,
+                                                      const GValue* value,
+                                                      GParamSpec* pspec);
+static void gtk_floating_container_get_child_property(GtkContainer* container,
+                                                      GtkWidget* child,
+                                                      guint property_id,
+                                                      GValue* value,
+                                                      GParamSpec* pspec);
+
+static guint floating_container_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE(GtkFloatingContainer, gtk_floating_container, GTK_TYPE_BIN)
+
+static void gtk_floating_container_class_init(
+    GtkFloatingContainerClass *klass) {
+  GtkObjectClass* object_class =
+      reinterpret_cast<GtkObjectClass*>(klass);
+
+  GtkWidgetClass* widget_class =
+      reinterpret_cast<GtkWidgetClass*>(klass);
+  widget_class->size_request = gtk_floating_container_size_request;
+  widget_class->size_allocate = gtk_floating_container_size_allocate;
+
+  GtkContainerClass* container_class =
+      reinterpret_cast<GtkContainerClass*>(klass);
+  container_class->remove = gtk_floating_container_remove;
+  container_class->forall = gtk_floating_container_forall;
+
+  container_class->set_child_property =
+      gtk_floating_container_set_child_property;
+  container_class->get_child_property =
+      gtk_floating_container_get_child_property;
+
+  gtk_container_class_install_child_property(
+      container_class,
+      CHILD_PROP_X,
+      g_param_spec_int("x",
+                       "X position",
+                       "X position of child widget",
+                       G_MININT,
+                       G_MAXINT,
+                       0,
+                       static_cast<GParamFlags>(GTK_PARAM_READWRITE)));
+
+  gtk_container_class_install_child_property(
+      container_class,
+      CHILD_PROP_Y,
+      g_param_spec_int("y",
+                       "Y position",
+                       "Y position of child widget",
+                       G_MININT,
+                       G_MAXINT,
+                       0,
+                       static_cast<GParamFlags>(GTK_PARAM_READWRITE)));
+
+  floating_container_signals[SET_FLOATING_POSITION] =
+      g_signal_new("set-floating-position",
+                   G_OBJECT_CLASS_TYPE(object_class),
+                   static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST |
+                                             G_SIGNAL_ACTION),
+                   0,
+                   NULL, NULL,
+                   gtk_marshal_VOID__BOXED,
+                   G_TYPE_NONE, 1,
+                   GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
+}
+
+static void gtk_floating_container_init(GtkFloatingContainer* container) {
+  GTK_WIDGET_SET_FLAGS(container, GTK_NO_WINDOW);
+
+  container->floating_children = NULL;
+}
+
+static void gtk_floating_container_remove(GtkContainer* container,
+                                          GtkWidget* widget) {
+  g_return_if_fail(GTK_IS_WIDGET(widget));
+
+  GtkBin* bin = GTK_BIN(container);
+  if (bin->child == widget) {
+    ((GTK_CONTAINER_CLASS(gtk_floating_container_parent_class))->remove)
+        (container, widget);
+  } else {
+    // Handle the other case where it's in our |floating_children| list.
+    GtkFloatingContainer* floating = GTK_FLOATING_CONTAINER(container);
+    GList* children = floating->floating_children;
+    gboolean removed_child = false;
+    while (children) {
+      GtkFloatingContainerChild* child =
+          reinterpret_cast<GtkFloatingContainerChild*>(children->data);
+
+      if (child->widget == widget) {
+        removed_child = true;
+        gboolean was_visible = GTK_WIDGET_VISIBLE(widget);
+
+        gtk_widget_unparent(widget);
+
+        floating->floating_children =
+            g_list_remove_link(floating->floating_children, children);
+        g_list_free(children);
+        g_free(child);
+
+        if (was_visible && GTK_WIDGET_VISIBLE(container))
+          gtk_widget_queue_resize(GTK_WIDGET(container));
+
+        break;
+      }
+      children = children->next;
+    }
+
+    g_return_if_fail(removed_child);
+  }
+}
+
+static void gtk_floating_container_forall(GtkContainer* container,
+                                          gboolean include_internals,
+                                          GtkCallback callback,
+                                          gpointer callback_data) {
+  g_return_if_fail(container != NULL);
+  g_return_if_fail(callback != NULL);
+
+  // Let GtkBin do its part of the forall.
+  ((GTK_CONTAINER_CLASS(gtk_floating_container_parent_class))->forall)
+      (container, include_internals, callback, callback_data);
+
+  GtkFloatingContainer* floating = GTK_FLOATING_CONTAINER(container);
+  GList* children = floating->floating_children;
+  while (children) {
+    GtkFloatingContainerChild* child =
+        reinterpret_cast<GtkFloatingContainerChild*>(children->data);
+    children = children->next;
+
+    (*callback)(child->widget, callback_data);
+  }
+}
+
+static void gtk_floating_container_size_request(GtkWidget* widget,
+                                                GtkRequisition* requisition) {
+  GtkBin* bin = GTK_BIN(widget);
+  if (bin && bin->child) {
+    gtk_widget_size_request(bin->child, requisition);
+  } else {
+    requisition->width = 0;
+    requisition->height = 0;
+  }
+}
+
+static void gtk_floating_container_size_allocate(GtkWidget* widget,
+                                                 GtkAllocation* allocation) {
+  widget->allocation = *allocation;
+
+  if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
+    gdk_window_move_resize(widget->window,
+                           allocation->x,
+                           allocation->y,
+                           allocation->width,
+                           allocation->height);
+  }
+
+  // Give the same allocation to our GtkBin component.
+  GtkBin* bin = GTK_BIN(widget);
+  if (bin->child) {
+    gtk_widget_size_allocate(bin->child, allocation);
+  }
+
+  // We need to give whoever is pulling our strings a chance to set the "x" and
+  // "y" properties on all of our children.
+  g_signal_emit(widget, floating_container_signals[SET_FLOATING_POSITION], 0,
+                allocation);
+
+  // Our allocation has been set. We've asked our controller to place the other
+  // widgets. Pass out allocations to all our children based on where they want
+  // to be.
+  GtkFloatingContainer* container = GTK_FLOATING_CONTAINER(widget);
+  GList* children = container->floating_children;
+  GtkAllocation child_allocation;
+  GtkRequisition child_requisition;
+  while (children) {
+    GtkFloatingContainerChild* child =
+        reinterpret_cast<GtkFloatingContainerChild*>(children->data);
+    children = children->next;
+
+    if (GTK_WIDGET_VISIBLE(child->widget)) {
+      gtk_widget_size_request(child->widget, &child_requisition);
+      child_allocation.x = allocation->x + child->x;
+      child_allocation.y = allocation->y + child->y;
+      child_allocation.width = std::max(1, std::min(child_requisition.width,
+                                                    allocation->width));
+      child_allocation.height = std::max(1, std::min(child_requisition.height,
+                                                     allocation->height));
+      gtk_widget_size_allocate(child->widget, &child_allocation);
+    }
+  }
+}
+
+static void gtk_floating_container_set_child_property(GtkContainer* container,
+                                                      GtkWidget* child,
+                                                      guint property_id,
+                                                      const GValue* value,
+                                                      GParamSpec* pspec) {
+  GtkFloatingContainerChild* floating_child =
+      GetChild(GTK_FLOATING_CONTAINER(container), child);
+  g_return_if_fail(floating_child);
+
+  switch (property_id) {
+    case CHILD_PROP_X:
+      floating_child->x = g_value_get_int(value);
+      gtk_widget_child_notify(child, "x");
+      break;
+    case CHILD_PROP_Y:
+      floating_child->y = g_value_get_int(value);
+      gtk_widget_child_notify(child, "y");
+      break;
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID(
+          container, property_id, pspec);
+      break;
+  };
+}
+
+static void gtk_floating_container_get_child_property(GtkContainer* container,
+                                                      GtkWidget* child,
+                                                      guint property_id,
+                                                      GValue* value,
+                                                      GParamSpec* pspec) {
+  GtkFloatingContainerChild* floating_child =
+      GetChild(GTK_FLOATING_CONTAINER(container), child);
+  g_return_if_fail(floating_child);
+
+  switch (property_id) {
+    case CHILD_PROP_X:
+      g_value_set_int(value, floating_child->x);
+      break;
+    case CHILD_PROP_Y:
+      g_value_set_int(value, floating_child->y);
+      break;
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID(
+          container, property_id, pspec);
+      break;
+  };
+}
+
+GtkWidget* gtk_floating_container_new() {
+  return GTK_WIDGET(g_object_new(GTK_TYPE_FLOATING_CONTAINER, NULL));
+}
+
+void gtk_floating_container_add_floating(GtkFloatingContainer* container,
+                                         GtkWidget* widget) {
+  g_return_if_fail(GTK_IS_FLOATING_CONTAINER(container));
+  g_return_if_fail(GTK_IS_WIDGET(widget));
+
+  GtkFloatingContainerChild* child_info = g_new(GtkFloatingContainerChild, 1);
+  child_info->widget = widget;
+  child_info->x = 0;
+  child_info->y = 0;
+
+  gtk_widget_set_parent(widget, GTK_WIDGET(container));
+
+  container->floating_children =
+      g_list_append(container->floating_children, child_info);
+}
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/gtk_floating_container.h b/chrome/browser/ui/gtk/gtk_floating_container.h
new file mode 100644
index 0000000..9b15b74
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_floating_container.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_GTK_GTK_FLOATING_CONTAINER_H_
+#define CHROME_BROWSER_UI_GTK_GTK_FLOATING_CONTAINER_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+// A specialized container, which is a cross between a GtkBin and a
+// GtkFixed. This container dervies from GtkBin and the implementation of
+// gtk_container_add() is the same: only one GtkWidget can be added through
+// that interface. The GtkBin portion contains normal content and is given the
+// same allocation that this container has.
+//
+// In addition, any number of widgets can be added through the
+// gtk_floating_container_add_floating() method, which provides functionality
+// similar to a GtkFixed. Unlike a GtkFixed, coordinates are not set when you
+// gtk_fixed_put(). The location of the floating widgets is determined while
+// running the "set-floating-position" signal, which is emitted during this
+// container's "size-allocate" handler.
+//
+// The "set-floating-position" signal is (semi-)mandatory if you want widgets
+// placed anywhere other than the origin and should have the following
+// signature:
+//
+//   void (*set_floating_position)(GtkFloatingContainer* container,
+//                                 GtkAllocation* allocation,
+//                                 gpointer userdata);
+//
+// Your handler should, for each floating widget, set the "x" and "y" child
+// properties.
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_FLOATING_CONTAINER                                 \
+    (gtk_floating_container_get_type())
+#define GTK_FLOATING_CONTAINER(obj)                                 \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_FLOATING_CONTAINER, \
+                                GtkFloatingContainer))
+#define GTK_FLOATING_CONTAINER_CLASS(klass)                         \
+    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_FLOATING_CONTAINER,  \
+                             GtkFloatingContainerClass))
+#define GTK_IS_FLOATING_CONTAINER(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_FLOATING_CONTAINER))
+#define GTK_IS_FLOATING_CONTAINER_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_FLOATING_CONTAINER))
+#define GTK_FLOATING_CONTAINER_GET_CLASS(obj)                       \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_FLOATING_CONTAINER,  \
+                               GtkFloatingContainerClass))
+
+typedef struct _GtkFloatingContainer GtkFloatingContainer;
+typedef struct _GtkFloatingContainerClass GtkFloatingContainerClass;
+typedef struct _GtkFloatingContainerChild GtkFloatingContainerChild;
+
+struct _GtkFloatingContainer {
+  // Parent class.
+  GtkBin bin;
+
+  // A GList of all our floating children, in GtkFloatingContainerChild
+  // structs. Owned by the GtkFloatingContainer.
+  GList* floating_children;
+};
+
+struct _GtkFloatingContainerClass {
+  GtkBinClass parent_class;
+};
+
+// Internal structure used to associate a widget and its x/y child properties.
+struct _GtkFloatingContainerChild {
+  GtkWidget* widget;
+  gint x;
+  gint y;
+};
+
+GType      gtk_floating_container_get_type() G_GNUC_CONST;
+GtkWidget* gtk_floating_container_new();
+void       gtk_floating_container_add_floating(GtkFloatingContainer* container,
+                                               GtkWidget* widget);
+// Use gtk_container_remove to remove all widgets; both widgets added with
+// gtk_container_add() and gtk_floating_container_add_floating().
+
+G_END_DECLS
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_FLOATING_CONTAINER_H_
diff --git a/chrome/browser/ui/gtk/gtk_theme_provider.cc b/chrome/browser/ui/gtk/gtk_theme_provider.cc
new file mode 100644
index 0000000..d0227ae
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_theme_provider.cc
@@ -0,0 +1,1128 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_theme_provider.h"
+
+#include <gtk/gtk.h>
+
+#include <set>
+
+#include "base/environment.h"
+#include "base/nix/xdg_util.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/chrome_gtk_frame.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/hover_controller_gtk.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/skbitmap_operations.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/gfx/skia_utils_gtk.h"
+
+namespace {
+
+// The size of the rendered toolbar image.
+const int kToolbarImageWidth = 64;
+const int kToolbarImageHeight = 128;
+
+// How much to tint the GTK+ color lighter at the top of the window.
+const color_utils::HSL kGtkFrameShift = { -1, -1, 0.58 };
+
+// How much to tint the GTK+ color when an explicit frame color hasn't been
+// specified.
+const color_utils::HSL kDefaultFrameShift = { -1, -1, 0.4 };
+
+// Values used as the new luminance and saturation values in the inactive tab
+// text color.
+const double kDarkInactiveLuminance = 0.85;
+const double kLightInactiveLuminance = 0.15;
+const double kHeavyInactiveSaturation = 0.7;
+const double kLightInactiveSaturation = 0.3;
+
+// Number of times that the background color should be counted when trying to
+// calculate the border color in GTK theme mode.
+const int kBgWeight = 3;
+
+// Padding to left, top and bottom of vertical separators.
+const int kSeparatorPadding = 2;
+
+// Default color for links on the NTP when the GTK+ theme doesn't define a
+// link color. Constant taken from gtklinkbutton.c.
+const GdkColor kDefaultLinkColor = { 0, 0, 0, 0xeeee };
+
+// Middle color of the separator gradient.
+const double kMidSeparatorColor[] =
+    { 194.0 / 255.0, 205.0 / 255.0, 212.0 / 212.0 };
+// Top color of the separator gradient.
+const double kTopSeparatorColor[] =
+    { 222.0 / 255.0, 234.0 / 255.0, 248.0 / 255.0 };
+
+// Converts a GdkColor to a SkColor.
+SkColor GdkToSkColor(const GdkColor* color) {
+  return SkColorSetRGB(color->red >> 8,
+                       color->green >> 8,
+                       color->blue >> 8);
+}
+
+// A list of images that we provide while in gtk mode.
+const int kThemeImages[] = {
+  IDR_THEME_TOOLBAR,
+  IDR_THEME_TAB_BACKGROUND,
+  IDR_THEME_TAB_BACKGROUND_INCOGNITO,
+  IDR_THEME_FRAME,
+  IDR_THEME_FRAME_INACTIVE,
+  IDR_THEME_FRAME_INCOGNITO,
+  IDR_THEME_FRAME_INCOGNITO_INACTIVE,
+};
+
+// A list of icons used in the autocomplete view that should be tinted to the
+// current gtk theme selection color so they stand out against the GtkEntry's
+// base color.
+const int kAutocompleteImages[] = {
+  IDR_OMNIBOX_HTTP,
+  IDR_OMNIBOX_HTTP_DARK,
+  IDR_OMNIBOX_HISTORY,
+  IDR_OMNIBOX_HISTORY_DARK,
+  IDR_OMNIBOX_SEARCH,
+  IDR_OMNIBOX_SEARCH_DARK,
+  IDR_OMNIBOX_STAR,
+  IDR_OMNIBOX_STAR_DARK,
+  IDR_GEOLOCATION_ALLOWED_LOCATIONBAR_ICON,
+  IDR_GEOLOCATION_DENIED_LOCATIONBAR_ICON
+};
+
+bool IsOverridableImage(int id) {
+  static std::set<int> images;
+  if (images.empty()) {
+    images.insert(kThemeImages, kThemeImages + arraysize(kThemeImages));
+    images.insert(kAutocompleteImages,
+                  kAutocompleteImages + arraysize(kAutocompleteImages));
+
+    const std::set<int>& buttons =
+        BrowserThemeProvider::GetTintableToolbarButtons();
+    images.insert(buttons.begin(), buttons.end());
+  }
+
+  return images.count(id) > 0;
+}
+
+// Picks a button tint from a set of background colors. While
+// |accent_gdk_color| will usually be the same color through a theme, this
+// function will get called with the normal GtkLabel |text_color|/GtkWindow
+// |background_color| pair and the GtkEntry |text_color|/|background_color|
+// pair. While 3/4 of the time the resulting tint will be the same, themes that
+// have a dark window background (with light text) and a light text entry (with
+// dark text) will get better icons with this separated out.
+void PickButtonTintFromColors(const GdkColor& accent_gdk_color,
+                              const GdkColor& text_color,
+                              const GdkColor& background_color,
+                              color_utils::HSL* tint) {
+  SkColor accent_color = GdkToSkColor(&accent_gdk_color);
+  color_utils::HSL accent_tint;
+  color_utils::SkColorToHSL(accent_color, &accent_tint);
+
+  color_utils::HSL text_tint;
+  color_utils::SkColorToHSL(GdkToSkColor(&text_color), &text_tint);
+
+  color_utils::HSL background_tint;
+  color_utils::SkColorToHSL(GdkToSkColor(&background_color), &background_tint);
+
+  // If the accent color is gray, then our normal HSL tomfoolery will bring out
+  // whatever color is oddly dominant (for example, in rgb space [125, 128,
+  // 125] will tint green instead of gray). Slight differences (+/-10 (4%) to
+  // all color components) should be interpreted as this color being gray and
+  // we should switch into a special grayscale mode.
+  int rb_diff = abs(SkColorGetR(accent_color) - SkColorGetB(accent_color));
+  int rg_diff = abs(SkColorGetR(accent_color) - SkColorGetG(accent_color));
+  int bg_diff = abs(SkColorGetB(accent_color) - SkColorGetG(accent_color));
+  if (rb_diff < 10 && rg_diff < 10 && bg_diff < 10) {
+    // Our accent is white/gray/black. Only the luminance of the accent color
+    // matters.
+    tint->h = -1;
+
+    // Use the saturation of the text.
+    tint->s = text_tint.s;
+
+    // Use the luminance of the accent color UNLESS there isn't enough
+    // luminance contrast between the accent color and the base color.
+    if (fabs(accent_tint.l - background_tint.l) > 0.3)
+      tint->l = accent_tint.l;
+    else
+      tint->l = text_tint.l;
+  } else {
+    // Our accent is a color.
+    tint->h = accent_tint.h;
+
+    // Don't modify the saturation; the amount of color doesn't matter.
+    tint->s = -1;
+
+    // If the text wants us to darken the icon, don't change the luminance (the
+    // icons are already dark enough). Otherwise, lighten the icon by no more
+    // than 0.9 since we don't want a pure-white icon even if the text is pure
+    // white.
+    if (text_tint.l < 0.5)
+      tint->l = -1;
+    else if (text_tint.l <= 0.9)
+      tint->l = text_tint.l;
+    else
+      tint->l = 0.9;
+  }
+}
+
+
+// Builds and tints the image with |id| to the GtkStateType |state| and
+// places the result in |icon_set|.
+void BuildIconFromIDRWithColor(int id,
+                               GtkStyle* style,
+                               GtkStateType state,
+                               GtkIconSet* icon_set) {
+  SkColor color = GdkToSkColor(&style->fg[state]);
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  SkBitmap original = *rb.GetBitmapNamed(id);
+
+  SkBitmap fill_color;
+  fill_color.setConfig(SkBitmap::kARGB_8888_Config,
+                       original.width(), original.height(), 0);
+  fill_color.allocPixels();
+  fill_color.eraseColor(color);
+  SkBitmap masked = SkBitmapOperations::CreateMaskedBitmap(
+      fill_color, original);
+
+  GtkIconSource* icon = gtk_icon_source_new();
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&masked);
+  gtk_icon_source_set_pixbuf(icon, pixbuf);
+  g_object_unref(pixbuf);
+
+  gtk_icon_source_set_direction_wildcarded(icon, TRUE);
+  gtk_icon_source_set_size_wildcarded(icon, TRUE);
+
+  gtk_icon_source_set_state(icon, state);
+  // All fields default to wildcarding being on and setting a property doesn't
+  // turn off wildcarding. You need to do this yourself. This is stated once in
+  // the documentation in the gtk_icon_source_new() function, and no where else.
+  gtk_icon_source_set_state_wildcarded(
+      icon, state == GTK_STATE_NORMAL);
+
+  gtk_icon_set_add_source(icon_set, icon);
+  gtk_icon_source_free(icon);
+}
+
+// Applies an HSL shift to a GdkColor (instead of an SkColor)
+void GdkColorHSLShift(const color_utils::HSL& shift, GdkColor* frame_color) {
+  SkColor shifted = color_utils::HSLShift(GdkToSkColor(frame_color), shift);
+  frame_color->pixel = 0;
+  frame_color->red = SkColorGetR(shifted) * kSkiaToGDKMultiplier;
+  frame_color->green = SkColorGetG(shifted) * kSkiaToGDKMultiplier;
+  frame_color->blue = SkColorGetB(shifted) * kSkiaToGDKMultiplier;
+}
+
+}  // namespace
+
+GtkWidget* GtkThemeProvider::icon_widget_ = NULL;
+GdkPixbuf* GtkThemeProvider::default_folder_icon_ = NULL;
+GdkPixbuf* GtkThemeProvider::default_bookmark_icon_ = NULL;
+
+// static
+GtkThemeProvider* GtkThemeProvider::GetFrom(Profile* profile) {
+  return static_cast<GtkThemeProvider*>(profile->GetThemeProvider());
+}
+
+GtkThemeProvider::GtkThemeProvider()
+    : BrowserThemeProvider(),
+      fake_window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
+      fake_frame_(chrome_gtk_frame_new()),
+      signals_(new ui::GtkSignalRegistrar),
+      fullscreen_icon_set_(NULL) {
+  fake_label_.Own(gtk_label_new(""));
+  fake_entry_.Own(gtk_entry_new());
+  fake_menu_item_.Own(gtk_menu_item_new());
+
+  // Only realized widgets receive style-set notifications, which we need to
+  // broadcast new theme images and colors. Only realized widgets have style
+  // properties, too, which we query for some colors.
+  gtk_widget_realize(fake_frame_);
+  gtk_widget_realize(fake_window_);
+  signals_->Connect(fake_frame_, "style-set",
+                    G_CALLBACK(&OnStyleSetThunk), this);
+}
+
+GtkThemeProvider::~GtkThemeProvider() {
+  gtk_widget_destroy(fake_window_);
+  gtk_widget_destroy(fake_frame_);
+  fake_label_.Destroy();
+  fake_entry_.Destroy();
+  fake_menu_item_.Destroy();
+
+  FreeIconSets();
+
+  // We have to call this because FreePlatformCached() in ~BrowserThemeProvider
+  // doesn't call the right virutal FreePlatformCaches.
+  FreePlatformCaches();
+}
+
+void GtkThemeProvider::Init(Profile* profile) {
+  registrar_.Init(profile->GetPrefs());
+  registrar_.Add(prefs::kUsesSystemTheme, this);
+  use_gtk_ = profile->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
+
+  BrowserThemeProvider::Init(profile);
+}
+
+SkBitmap* GtkThemeProvider::GetBitmapNamed(int id) const {
+  // Try to get our cached version:
+  ImageCache::const_iterator it = gtk_images_.find(id);
+  if (it != gtk_images_.end())
+    return it->second;
+
+  if (use_gtk_ && IsOverridableImage(id)) {
+    // We haven't built this image yet:
+    SkBitmap* bitmap = GenerateGtkThemeBitmap(id);
+    gtk_images_[id] = bitmap;
+    return bitmap;
+  }
+
+  return BrowserThemeProvider::GetBitmapNamed(id);
+}
+
+SkColor GtkThemeProvider::GetColor(int id) const {
+  if (use_gtk_) {
+    ColorMap::const_iterator it = colors_.find(id);
+    if (it != colors_.end())
+      return it->second;
+  }
+
+  return BrowserThemeProvider::GetColor(id);
+}
+
+bool GtkThemeProvider::HasCustomImage(int id) const {
+  if (use_gtk_)
+    return IsOverridableImage(id);
+
+  return BrowserThemeProvider::HasCustomImage(id);
+}
+
+void GtkThemeProvider::InitThemesFor(NotificationObserver* observer) {
+  observer->Observe(NotificationType::BROWSER_THEME_CHANGED,
+                    Source<ui::ThemeProvider>(this),
+                    NotificationService::NoDetails());
+}
+
+void GtkThemeProvider::SetTheme(const Extension* extension) {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+  LoadDefaultValues();
+  BrowserThemeProvider::SetTheme(extension);
+}
+
+void GtkThemeProvider::UseDefaultTheme() {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+  LoadDefaultValues();
+  BrowserThemeProvider::UseDefaultTheme();
+}
+
+void GtkThemeProvider::SetNativeTheme() {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, true);
+  ClearAllThemeData();
+  LoadGtkValues();
+  NotifyThemeChanged(NULL);
+}
+
+bool GtkThemeProvider::UsingDefaultTheme() {
+  return !use_gtk_ && BrowserThemeProvider::UsingDefaultTheme();
+}
+
+void GtkThemeProvider::Observe(NotificationType type,
+                               const NotificationSource& source,
+                               const NotificationDetails& details) {
+  if ((type == NotificationType::PREF_CHANGED) &&
+      (*Details<std::string>(details).ptr() == prefs::kUsesSystemTheme))
+    use_gtk_ = profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
+}
+
+GtkWidget* GtkThemeProvider::BuildChromeButton() {
+  GtkWidget* button = HoverControllerGtk::CreateChromeButton();
+  gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(button), use_gtk_);
+  chrome_buttons_.push_back(button);
+
+  signals_->Connect(button, "destroy", G_CALLBACK(OnDestroyChromeButtonThunk),
+                    this);
+  return button;
+}
+
+GtkWidget* GtkThemeProvider::CreateToolbarSeparator() {
+  GtkWidget* separator = gtk_vseparator_new();
+  GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+      kSeparatorPadding, kSeparatorPadding, kSeparatorPadding, 0);
+  gtk_container_add(GTK_CONTAINER(alignment), separator);
+
+  signals_->Connect(separator, "expose-event",
+                    G_CALLBACK(OnSeparatorExposeThunk), this);
+  return alignment;
+}
+
+bool GtkThemeProvider::UseGtkTheme() const {
+  return use_gtk_;
+}
+
+GdkColor GtkThemeProvider::GetGdkColor(int id) const {
+  return gfx::SkColorToGdkColor(GetColor(id));
+}
+
+GdkColor GtkThemeProvider::GetBorderColor() const {
+  GtkStyle* style = gtk_rc_get_style(fake_window_);
+
+  GdkColor text;
+  GdkColor bg;
+  if (use_gtk_) {
+    text = style->text[GTK_STATE_NORMAL];
+    bg = style->bg[GTK_STATE_NORMAL];
+  } else {
+    text = GetGdkColor(COLOR_BOOKMARK_TEXT);
+    bg = GetGdkColor(COLOR_TOOLBAR);
+  }
+
+  // Creates a weighted average between the text and base color where
+  // the base color counts more than once.
+  GdkColor color;
+  color.pixel = 0;
+  color.red = (text.red + (bg.red * kBgWeight)) / (1 + kBgWeight);
+  color.green = (text.green + (bg.green * kBgWeight)) / (1 + kBgWeight);
+  color.blue = (text.blue + (bg.blue * kBgWeight)) / (1 + kBgWeight);
+
+  return color;
+}
+
+GtkIconSet* GtkThemeProvider::GetIconSetForId(int id) const {
+  if (id == IDR_FULLSCREEN_MENU_BUTTON)
+    return fullscreen_icon_set_;
+
+  return NULL;
+}
+
+void GtkThemeProvider::GetScrollbarColors(GdkColor* thumb_active_color,
+                                          GdkColor* thumb_inactive_color,
+                                          GdkColor* track_color) {
+  const GdkColor* theme_thumb_active = NULL;
+  const GdkColor* theme_thumb_inactive = NULL;
+  const GdkColor* theme_trough_color = NULL;
+  gtk_widget_style_get(GTK_WIDGET(fake_frame_),
+                       "scrollbar-slider-prelight-color", &theme_thumb_active,
+                       "scrollbar-slider-normal-color", &theme_thumb_inactive,
+                       "scrollbar-trough-color", &theme_trough_color,
+                       NULL);
+
+  // Ask the theme if the theme specifies all the scrollbar colors and short
+  // circuit the expensive painting/compositing if we have all of them.
+  if (theme_thumb_active && theme_thumb_inactive && theme_trough_color) {
+    *thumb_active_color = *theme_thumb_active;
+    *thumb_inactive_color = *theme_thumb_inactive;
+    *track_color = *theme_trough_color;
+    return;
+  }
+
+  // Create window containing scrollbar elements
+  GtkWidget* window    = gtk_window_new(GTK_WINDOW_POPUP);
+  GtkWidget* fixed     = gtk_fixed_new();
+  GtkWidget* scrollbar = gtk_hscrollbar_new(NULL);
+  gtk_container_add(GTK_CONTAINER(window), fixed);
+  gtk_container_add(GTK_CONTAINER(fixed),  scrollbar);
+  gtk_widget_realize(window);
+  gtk_widget_realize(scrollbar);
+
+  // Draw scrollbar thumb part and track into offscreen image
+  const int kWidth  = 100;
+  const int kHeight = 20;
+  GtkStyle*  style  = gtk_rc_get_style(scrollbar);
+  GdkPixmap* pm     = gdk_pixmap_new(window->window, kWidth, kHeight, -1);
+  GdkRectangle rect = { 0, 0, kWidth, kHeight };
+  unsigned char data[3 * kWidth * kHeight];
+  for (int i = 0; i < 3; ++i) {
+    if (i < 2) {
+      // Thumb part
+      gtk_paint_slider(style, pm,
+                       i == 0 ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
+                       GTK_SHADOW_OUT, &rect, scrollbar, "slider", 0, 0,
+                       kWidth, kHeight, GTK_ORIENTATION_HORIZONTAL);
+    } else {
+      // Track
+      gtk_paint_box(style, pm, GTK_STATE_ACTIVE, GTK_SHADOW_IN, &rect,
+                    scrollbar, "trough-upper", 0, 0, kWidth, kHeight);
+    }
+    GdkPixbuf* pb = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB,
+                                             FALSE, 8, kWidth, kHeight,
+                                             3 * kWidth, 0, 0);
+    gdk_pixbuf_get_from_drawable(pb, pm, NULL, 0, 0, 0, 0, kWidth, kHeight);
+
+    // Sample pixels
+    int components[3] = { 0 };
+    for (int y = 2; y < kHeight - 2; ++y) {
+      for (int c = 0; c < 3; ++c) {
+        // Sample a vertical slice of pixels at about one-thirds from the
+        // left edge. This allows us to avoid any fixed graphics that might be
+        // located at the edges or in the center of the scrollbar.
+        // Each pixel is made up of a red, green, and blue component; taking up
+        // a total of three bytes.
+        components[c] += data[3 * (kWidth / 3 + y * kWidth) + c];
+      }
+    }
+    GdkColor* color = i == 0 ? thumb_active_color :
+                      i == 1 ? thumb_inactive_color :
+                               track_color;
+    color->pixel = 0;
+    // We sampled pixels across the full height of the image, ignoring a two
+    // pixel border. In some themes, the border has a completely different
+    // color which we do not want to factor into our average color computation.
+    //
+    // We now need to scale the colors from the 0..255 range, to the wider
+    // 0..65535 range, and we need to actually compute the average color; so,
+    // we divide by the total number of pixels in the sample.
+    color->red   = components[0] * 65535 / (255 * (kHeight - 4));
+    color->green = components[1] * 65535 / (255 * (kHeight - 4));
+    color->blue  = components[2] * 65535 / (255 * (kHeight - 4));
+
+    g_object_unref(pb);
+  }
+  g_object_unref(pm);
+
+  gtk_widget_destroy(window);
+
+  // Override any of the default colors with ones that were specified by the
+  // theme.
+  if (theme_thumb_active)
+    *thumb_active_color = *theme_thumb_active;
+
+  if (theme_thumb_inactive)
+    *thumb_inactive_color = *theme_thumb_inactive;
+
+  if (theme_trough_color)
+    *track_color = *theme_trough_color;
+}
+
+CairoCachedSurface* GtkThemeProvider::GetSurfaceNamed(
+    int id,
+    GtkWidget* widget_on_display) {
+  return GetSurfaceNamedImpl(id,
+                             &per_display_surfaces_,
+                             GetPixbufNamed(id),
+                             widget_on_display);
+}
+
+CairoCachedSurface* GtkThemeProvider::GetRTLEnabledSurfaceNamed(
+    int id,
+    GtkWidget* widget_on_display) {
+  // We flip the sign of |id| when passing it to GetSurfaceNamedImpl() for the
+  // same reason that BrowserThemeProvider::GetPixbufImpl() does: so that if one
+  // location calls this function with a resource ID, and another place calls
+  // GetSurfaceNamed() with the same ID, they'll correctly get different
+  // surfaces in RTL mode.
+  return GetSurfaceNamedImpl(-id,
+                             &per_display_surfaces_,
+                             GetRTLEnabledPixbufNamed(id),
+                             widget_on_display);
+}
+
+CairoCachedSurface* GtkThemeProvider::GetUnthemedSurfaceNamed(
+    int id,
+    GtkWidget* widget_on_display) {
+  return GetSurfaceNamedImpl(id,
+      &per_display_unthemed_surfaces_,
+      ResourceBundle::GetSharedInstance().GetPixbufNamed(id),
+      widget_on_display);
+}
+
+// static
+GdkPixbuf* GtkThemeProvider::GetFolderIcon(bool native) {
+  if (native) {
+    if (!icon_widget_)
+      icon_widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    // We never release our ref, so we will leak this on program shutdown.
+    if (!default_folder_icon_) {
+      default_folder_icon_ =
+          gtk_widget_render_icon(icon_widget_, GTK_STOCK_DIRECTORY,
+                                 GTK_ICON_SIZE_MENU, NULL);
+    }
+    if (default_folder_icon_)
+      return default_folder_icon_;
+  }
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  static GdkPixbuf* default_folder_icon_ = rb.GetPixbufNamed(
+      IDR_BOOKMARK_BAR_FOLDER);
+  return default_folder_icon_;
+}
+
+// static
+GdkPixbuf* GtkThemeProvider::GetDefaultFavicon(bool native) {
+  if (native) {
+    if (!icon_widget_)
+      icon_widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    // We never release our ref, so we will leak this on program shutdown.
+    if (!default_bookmark_icon_) {
+      default_bookmark_icon_ =
+          gtk_widget_render_icon(icon_widget_, GTK_STOCK_FILE,
+                                 GTK_ICON_SIZE_MENU, NULL);
+    }
+    if (default_bookmark_icon_)
+      return default_bookmark_icon_;
+  }
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  static GdkPixbuf* default_bookmark_icon_ = rb.GetPixbufNamed(
+      IDR_DEFAULT_FAVICON);
+  return default_bookmark_icon_;
+}
+
+// static
+bool GtkThemeProvider::DefaultUsesSystemTheme() {
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+
+  switch (base::nix::GetDesktopEnvironment(env.get())) {
+    case base::nix::DESKTOP_ENVIRONMENT_GNOME:
+    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
+      return true;
+    default:
+      return false;
+  }
+}
+
+void GtkThemeProvider::ClearAllThemeData() {
+  colors_.clear();
+  tints_.clear();
+
+  BrowserThemeProvider::ClearAllThemeData();
+}
+
+void GtkThemeProvider::LoadThemePrefs() {
+  if (use_gtk_) {
+    LoadGtkValues();
+  } else {
+    LoadDefaultValues();
+    BrowserThemeProvider::LoadThemePrefs();
+  }
+
+  RebuildMenuIconSets();
+}
+
+void GtkThemeProvider::NotifyThemeChanged(const Extension* extension) {
+  BrowserThemeProvider::NotifyThemeChanged(extension);
+
+  // Notify all GtkChromeButtons of their new rendering mode:
+  for (std::vector<GtkWidget*>::iterator it = chrome_buttons_.begin();
+       it != chrome_buttons_.end(); ++it) {
+    gtk_chrome_button_set_use_gtk_rendering(
+        GTK_CHROME_BUTTON(*it), use_gtk_);
+  }
+}
+
+void GtkThemeProvider::FreePlatformCaches() {
+  BrowserThemeProvider::FreePlatformCaches();
+  FreePerDisplaySurfaces(&per_display_surfaces_);
+  FreePerDisplaySurfaces(&per_display_unthemed_surfaces_);
+  STLDeleteValues(&gtk_images_);
+}
+
+void GtkThemeProvider::OnStyleSet(GtkWidget* widget,
+                                  GtkStyle* previous_style) {
+  GdkPixbuf* default_folder_icon = default_folder_icon_;
+  GdkPixbuf* default_bookmark_icon = default_bookmark_icon_;
+  default_folder_icon_ = NULL;
+  default_bookmark_icon_ = NULL;
+
+  if (profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme)) {
+    ClearAllThemeData();
+    LoadGtkValues();
+    NotifyThemeChanged(NULL);
+  }
+
+  RebuildMenuIconSets();
+
+  // Free the old icons only after the theme change notification has gone
+  // through.
+  if (default_folder_icon)
+    g_object_unref(default_folder_icon);
+  if (default_bookmark_icon)
+    g_object_unref(default_bookmark_icon);
+}
+
+void GtkThemeProvider::LoadGtkValues() {
+  // Before we start setting images and values, we have to clear out old, stale
+  // values. (If we don't do this, we'll regress startup time in the case where
+  // someone installs a heavyweight theme, then goes back to GTK.)
+  DictionaryValue* pref_images =
+      profile()->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages);
+  pref_images->Clear();
+
+  GtkStyle* frame_style = gtk_rc_get_style(fake_frame_);
+
+  GtkStyle* window_style = gtk_rc_get_style(fake_window_);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_CONTROL_BACKGROUND,
+                       &window_style->bg[GTK_STATE_NORMAL]);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND,
+                       &window_style->bg[GTK_STATE_NORMAL]);
+
+  GdkColor toolbar_color = window_style->bg[GTK_STATE_NORMAL];
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TOOLBAR, &toolbar_color);
+
+  GdkColor button_color = window_style->bg[GTK_STATE_SELECTED];
+  SetThemeTintFromGtk(BrowserThemeProvider::TINT_BUTTONS, &button_color);
+
+  GtkStyle* label_style = gtk_rc_get_style(fake_label_.get());
+  GdkColor label_color = label_style->fg[GTK_STATE_NORMAL];
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TAB_TEXT, &label_color);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, &label_color);
+
+  // Build the various icon tints.
+  GetNormalButtonTintHSL(&button_tint_);
+  GetNormalEntryForegroundHSL(&entry_tint_);
+  GetSelectedEntryForegroundHSL(&selected_entry_tint_);
+  GdkColor frame_color = BuildFrameColors(frame_style);
+
+  // The inactive frame color never occurs naturally in the theme, as it is a
+  // tinted version of |frame_color|. We generate another color based on the
+  // background tab color, with the lightness and saturation moved in the
+  // opposite direction. (We don't touch the hue, since there should be subtle
+  // hints of the color in the text.)
+  color_utils::HSL inactive_tab_text_hsl = tints_[TINT_BACKGROUND_TAB];
+  if (inactive_tab_text_hsl.l < 0.5)
+    inactive_tab_text_hsl.l = kDarkInactiveLuminance;
+  else
+    inactive_tab_text_hsl.l = kLightInactiveLuminance;
+
+  if (inactive_tab_text_hsl.s < 0.5)
+    inactive_tab_text_hsl.s = kHeavyInactiveSaturation;
+  else
+    inactive_tab_text_hsl.s = kLightInactiveSaturation;
+
+  colors_[BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT] =
+      color_utils::HSLToSkColor(inactive_tab_text_hsl, 255);
+
+  // We pick the text and background colors for the NTP out of the colors for a
+  // GtkEntry. We do this because GtkEntries background color is never the same
+  // as |toolbar_color|, is usually a white, and when it isn't a white,
+  // provides sufficient contrast to |toolbar_color|. Try this out with
+  // Darklooks, HighContrastInverse or ThinIce.
+  GtkStyle* entry_style = gtk_rc_get_style(fake_entry_.get());
+  GdkColor ntp_background = entry_style->base[GTK_STATE_NORMAL];
+  GdkColor ntp_foreground = entry_style->text[GTK_STATE_NORMAL];
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_BACKGROUND,
+                       &ntp_background);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_TEXT,
+                       &ntp_foreground);
+
+  // The NTP header is the color that surrounds the current active thumbnail on
+  // the NTP, and acts as the border of the "Recent Links" box. It would be
+  // awesome if they were separated so we could use GetBorderColor() for the
+  // border around the "Recent Links" section, but matching the frame color is
+  // more important.
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_HEADER,
+                       &frame_color);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION,
+                       &toolbar_color);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION_TEXT,
+                       &label_color);
+
+  // Override the link color if the theme provides it.
+  const GdkColor* link_color = NULL;
+  gtk_widget_style_get(GTK_WIDGET(fake_window_),
+                       "link-color", &link_color, NULL);
+  if (!link_color)
+    link_color = &kDefaultLinkColor;
+
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_LINK,
+                       link_color);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE,
+                       link_color);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION_LINK,
+                       link_color);
+  SetThemeColorFromGtk(BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE,
+                       link_color);
+
+  // Generate the colors that we pass to WebKit.
+  focus_ring_color_ = GdkToSkColor(&frame_color);
+  GdkColor thumb_active_color, thumb_inactive_color, track_color;
+  GtkThemeProvider::GetScrollbarColors(&thumb_active_color,
+                                       &thumb_inactive_color,
+                                       &track_color);
+  thumb_active_color_ = GdkToSkColor(&thumb_active_color);
+  thumb_inactive_color_ = GdkToSkColor(&thumb_inactive_color);
+  track_color_ = GdkToSkColor(&track_color);
+
+  // Some GTK themes only define the text selection colors on the GtkEntry
+  // class, so we need to use that for getting selection colors.
+  active_selection_bg_color_ =
+      GdkToSkColor(&entry_style->base[GTK_STATE_SELECTED]);
+  active_selection_fg_color_ =
+      GdkToSkColor(&entry_style->text[GTK_STATE_SELECTED]);
+  inactive_selection_bg_color_ =
+      GdkToSkColor(&entry_style->base[GTK_STATE_ACTIVE]);
+  inactive_selection_fg_color_ =
+      GdkToSkColor(&entry_style->text[GTK_STATE_ACTIVE]);
+}
+
+GdkColor GtkThemeProvider::BuildFrameColors(GtkStyle* frame_style) {
+  const GdkColor* theme_frame = NULL;
+  const GdkColor* theme_inactive_frame = NULL;
+  const GdkColor* theme_incognito_frame = NULL;
+  const GdkColor* theme_incognito_inactive_frame = NULL;
+  gtk_widget_style_get(GTK_WIDGET(fake_frame_),
+                       "frame-color", &theme_frame,
+                       "inactive-frame-color", &theme_inactive_frame,
+                       "incognito-frame-color", &theme_incognito_frame,
+                       "incognito-inactive-frame-color",
+                       &theme_incognito_inactive_frame,
+                       NULL);
+
+  GdkColor frame_color = BuildAndSetFrameColor(
+      &frame_style->bg[GTK_STATE_SELECTED],
+      theme_frame,
+      kDefaultFrameShift,
+      BrowserThemeProvider::COLOR_FRAME,
+      BrowserThemeProvider::TINT_FRAME);
+  SetThemeTintFromGtk(BrowserThemeProvider::TINT_BACKGROUND_TAB, &frame_color);
+
+  BuildAndSetFrameColor(
+      &frame_style->bg[GTK_STATE_INSENSITIVE],
+      theme_inactive_frame,
+      kDefaultFrameShift,
+      BrowserThemeProvider::COLOR_FRAME_INACTIVE,
+      BrowserThemeProvider::TINT_FRAME_INACTIVE);
+
+  BuildAndSetFrameColor(
+      &frame_color,
+      theme_incognito_frame,
+      GetDefaultTint(BrowserThemeProvider::TINT_FRAME_INCOGNITO),
+      BrowserThemeProvider::COLOR_FRAME_INCOGNITO,
+      BrowserThemeProvider::TINT_FRAME_INCOGNITO);
+
+  BuildAndSetFrameColor(
+      &frame_color,
+      theme_incognito_inactive_frame,
+      GetDefaultTint(BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE),
+      BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE,
+      BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE);
+
+  return frame_color;
+}
+
+void GtkThemeProvider::LoadDefaultValues() {
+  focus_ring_color_ = SkColorSetARGB(255, 229, 151, 0);
+  thumb_active_color_ = SkColorSetRGB(244, 244, 244);
+  thumb_inactive_color_ = SkColorSetRGB(234, 234, 234);
+  track_color_ = SkColorSetRGB(211, 211, 211);
+
+  active_selection_bg_color_ = SkColorSetRGB(30, 144, 255);
+  active_selection_fg_color_ = SK_ColorWHITE;
+  inactive_selection_bg_color_ = SkColorSetRGB(200, 200, 200);
+  inactive_selection_fg_color_ = SkColorSetRGB(50, 50, 50);
+}
+
+void GtkThemeProvider::RebuildMenuIconSets() {
+  FreeIconSets();
+
+  GtkStyle* style = gtk_rc_get_style(fake_menu_item_.get());
+
+  fullscreen_icon_set_ = gtk_icon_set_new();
+  BuildIconFromIDRWithColor(IDR_FULLSCREEN_MENU_BUTTON,
+                            style,
+                            GTK_STATE_PRELIGHT,
+                            fullscreen_icon_set_);
+  BuildIconFromIDRWithColor(IDR_FULLSCREEN_MENU_BUTTON,
+                            style,
+                            GTK_STATE_NORMAL,
+                            fullscreen_icon_set_);
+}
+
+void GtkThemeProvider::SetThemeColorFromGtk(int id, const GdkColor* color) {
+  colors_[id] = GdkToSkColor(color);
+}
+
+void GtkThemeProvider::SetThemeTintFromGtk(int id, const GdkColor* color) {
+  color_utils::HSL default_tint = GetDefaultTint(id);
+  color_utils::HSL hsl;
+  color_utils::SkColorToHSL(GdkToSkColor(color), &hsl);
+
+  if (default_tint.s != -1)
+    hsl.s = default_tint.s;
+
+  if (default_tint.l != -1)
+    hsl.l = default_tint.l;
+
+  tints_[id] = hsl;
+}
+
+GdkColor GtkThemeProvider::BuildAndSetFrameColor(const GdkColor* base,
+                                                 const GdkColor* gtk_base,
+                                                 const color_utils::HSL& tint,
+                                                 int color_id,
+                                                 int tint_id) {
+  GdkColor out_color = *base;
+  if (gtk_base) {
+    // The theme author specified a color to use, use it without modification.
+    out_color = *gtk_base;
+  } else {
+    // Tint the basic color since this is a heuristic color instead of one
+    // specified by the theme author.
+    GdkColorHSLShift(tint, &out_color);
+  }
+  SetThemeColorFromGtk(color_id, &out_color);
+  SetThemeTintFromGtk(tint_id, &out_color);
+
+  return out_color;
+}
+
+void GtkThemeProvider::FreePerDisplaySurfaces(
+    PerDisplaySurfaceMap* per_display_map) {
+  for (PerDisplaySurfaceMap::iterator it = per_display_map->begin();
+       it != per_display_map->end(); ++it) {
+    for (CairoCachedSurfaceMap::iterator jt = it->second.begin();
+         jt != it->second.end(); ++jt) {
+      delete jt->second;
+    }
+  }
+  per_display_map->clear();
+}
+
+void GtkThemeProvider::FreeIconSets() {
+  if (fullscreen_icon_set_) {
+    gtk_icon_set_unref(fullscreen_icon_set_);
+    fullscreen_icon_set_ = NULL;
+  }
+}
+
+SkBitmap* GtkThemeProvider::GenerateGtkThemeBitmap(int id) const {
+  switch (id) {
+    case IDR_THEME_TOOLBAR: {
+      GtkStyle* style = gtk_rc_get_style(fake_window_);
+      GdkColor* color = &style->bg[GTK_STATE_NORMAL];
+      SkBitmap* bitmap = new SkBitmap;
+      bitmap->setConfig(SkBitmap::kARGB_8888_Config,
+                        kToolbarImageWidth, kToolbarImageHeight);
+      bitmap->allocPixels();
+      bitmap->eraseRGB(color->red >> 8, color->green >> 8, color->blue >> 8);
+      return bitmap;
+    }
+    case IDR_THEME_TAB_BACKGROUND:
+      return GenerateTabImage(IDR_THEME_FRAME);
+    case IDR_THEME_TAB_BACKGROUND_INCOGNITO:
+      return GenerateTabImage(IDR_THEME_FRAME_INCOGNITO);
+    case IDR_THEME_FRAME:
+      return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME,
+                                "frame-gradient-color");
+    case IDR_THEME_FRAME_INACTIVE:
+      return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME_INACTIVE,
+                                "inactive-frame-gradient-color");
+    case IDR_THEME_FRAME_INCOGNITO:
+      return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME_INCOGNITO,
+                                "incognito-frame-gradient-color");
+    case IDR_THEME_FRAME_INCOGNITO_INACTIVE: {
+      return GenerateFrameImage(
+          BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE,
+          "incognito-inactive-frame-gradient-color");
+    }
+    // Icons that sit inside the omnibox shouldn't receive TINT_BUTTONS and
+    // instead should tint based on the foreground text entry color in GTK+
+    // mode because some themes that try to be dark *and* light have very
+    // different colors between the omnibox and the normal background area.
+    case IDR_OMNIBOX_HISTORY:
+    case IDR_OMNIBOX_HTTP:
+    case IDR_OMNIBOX_SEARCH:
+    case IDR_OMNIBOX_STAR:
+    case IDR_GEOLOCATION_ALLOWED_LOCATIONBAR_ICON:
+    case IDR_GEOLOCATION_DENIED_LOCATIONBAR_ICON: {
+      return GenerateTintedIcon(id, entry_tint_);
+    }
+    // In GTK mode, the dark versions of the omnibox icons only ever appear in
+    // the autocomplete popup and only against the current theme's GtkEntry
+    // base[GTK_STATE_SELECTED] color, so tint the icons so they won't collide
+    // with the selected color.
+    case IDR_OMNIBOX_HISTORY_DARK:
+    case IDR_OMNIBOX_HTTP_DARK:
+    case IDR_OMNIBOX_SEARCH_DARK:
+    case IDR_OMNIBOX_STAR_DARK: {
+      return GenerateTintedIcon(id, selected_entry_tint_);
+    }
+    default: {
+      return GenerateTintedIcon(id, button_tint_);
+    }
+  }
+}
+
+SkBitmap* GtkThemeProvider::GenerateFrameImage(
+    int color_id,
+    const char* gradient_name) const {
+  // We use two colors: the main color (passed in) and a lightened version of
+  // that color (which is supposed to match the light gradient at the top of
+  // several GTK+ themes, such as Ambiance, Clearlooks or Bluebird).
+  ColorMap::const_iterator it = colors_.find(color_id);
+  DCHECK(it != colors_.end());
+  SkColor base = it->second;
+
+  gfx::CanvasSkia canvas(kToolbarImageWidth, kToolbarImageHeight, true);
+
+  int gradient_size;
+  const GdkColor* gradient_top_color = NULL;
+  gtk_widget_style_get(GTK_WIDGET(fake_frame_),
+                       "frame-gradient-size", &gradient_size,
+                       gradient_name, &gradient_top_color,
+                       NULL);
+  if (gradient_size) {
+    SkColor lighter = gradient_top_color ? GdkToSkColor(gradient_top_color)
+                      : color_utils::HSLShift(base, kGtkFrameShift);
+    SkShader* shader = gfx::CreateGradientShader(
+        0, gradient_size, lighter, base);
+    SkPaint paint;
+    paint.setStyle(SkPaint::kFill_Style);
+    paint.setAntiAlias(true);
+    paint.setShader(shader);
+    shader->unref();
+
+    canvas.DrawRectInt(0, 0, kToolbarImageWidth, gradient_size, paint);
+  }
+
+  canvas.FillRectInt(base, 0, gradient_size,
+                     kToolbarImageWidth,
+                     kToolbarImageHeight - gradient_size);
+  return new SkBitmap(canvas.ExtractBitmap());
+}
+
+SkBitmap* GtkThemeProvider::GenerateTabImage(int base_id) const {
+  SkBitmap* base_image = GetBitmapNamed(base_id);
+  SkBitmap bg_tint = SkBitmapOperations::CreateHSLShiftedBitmap(
+      *base_image, GetTint(BrowserThemeProvider::TINT_BACKGROUND_TAB));
+  return new SkBitmap(SkBitmapOperations::CreateTiledBitmap(
+      bg_tint, 0, 0, bg_tint.width(), bg_tint.height()));
+}
+
+SkBitmap* GtkThemeProvider::GenerateTintedIcon(int base_id,
+                                               color_utils::HSL tint) const {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  scoped_ptr<SkBitmap> button(new SkBitmap(*rb.GetBitmapNamed(base_id)));
+  return new SkBitmap(SkBitmapOperations::CreateHSLShiftedBitmap(
+      *button, tint));
+}
+
+void GtkThemeProvider::GetNormalButtonTintHSL(
+    color_utils::HSL* tint) const {
+  GtkStyle* window_style = gtk_rc_get_style(fake_window_);
+  const GdkColor accent_gdk_color = window_style->bg[GTK_STATE_SELECTED];
+  const GdkColor base_color = window_style->base[GTK_STATE_NORMAL];
+
+  GtkStyle* label_style = gtk_rc_get_style(fake_label_.get());
+  const GdkColor text_color = label_style->fg[GTK_STATE_NORMAL];
+
+  PickButtonTintFromColors(accent_gdk_color, text_color, base_color, tint);
+}
+
+void GtkThemeProvider::GetNormalEntryForegroundHSL(
+    color_utils::HSL* tint) const {
+  GtkStyle* window_style = gtk_rc_get_style(fake_window_);
+  const GdkColor accent_gdk_color = window_style->bg[GTK_STATE_SELECTED];
+
+  GtkStyle* style = gtk_rc_get_style(fake_entry_.get());
+  const GdkColor text_color = style->text[GTK_STATE_NORMAL];
+  const GdkColor base_color = style->base[GTK_STATE_NORMAL];
+
+  PickButtonTintFromColors(accent_gdk_color, text_color, base_color, tint);
+}
+
+void GtkThemeProvider::GetSelectedEntryForegroundHSL(
+    color_utils::HSL* tint) const {
+  // The simplest of all the tints. We just use the selected text in the entry
+  // since the icons tinted this way will only be displayed against
+  // base[GTK_STATE_SELECTED].
+  GtkStyle* style = gtk_rc_get_style(fake_entry_.get());
+  const GdkColor color = style->text[GTK_STATE_SELECTED];
+  color_utils::SkColorToHSL(GdkToSkColor(&color), tint);
+}
+
+CairoCachedSurface* GtkThemeProvider::GetSurfaceNamedImpl(
+    int id,
+    PerDisplaySurfaceMap* display_surface_map,
+    GdkPixbuf* pixbuf,
+    GtkWidget* widget_on_display) {
+  GdkDisplay* display = gtk_widget_get_display(widget_on_display);
+  CairoCachedSurfaceMap& surface_map = (*display_surface_map)[display];
+
+  // Check to see if we already have the pixbuf in the cache.
+  CairoCachedSurfaceMap::const_iterator found = surface_map.find(id);
+  if (found != surface_map.end())
+    return found->second;
+
+  CairoCachedSurface* surface = new CairoCachedSurface;
+  surface->UsePixbuf(pixbuf);
+
+  surface_map[id] = surface;
+
+  return surface;
+}
+
+void GtkThemeProvider::OnDestroyChromeButton(GtkWidget* button) {
+  std::vector<GtkWidget*>::iterator it =
+      find(chrome_buttons_.begin(), chrome_buttons_.end(), button);
+  if (it != chrome_buttons_.end())
+    chrome_buttons_.erase(it);
+}
+
+gboolean GtkThemeProvider::OnSeparatorExpose(GtkWidget* widget,
+                                             GdkEventExpose* event) {
+  if (UseGtkTheme())
+    return FALSE;
+
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+
+  GdkColor bottom_color = GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
+  double bottom_color_rgb[] = {
+      static_cast<double>(bottom_color.red / 257) / 255.0,
+      static_cast<double>(bottom_color.green / 257) / 255.0,
+      static_cast<double>(bottom_color.blue / 257) / 255.0, };
+
+  cairo_pattern_t* pattern =
+      cairo_pattern_create_linear(widget->allocation.x, widget->allocation.y,
+                                  widget->allocation.x,
+                                  widget->allocation.y +
+                                  widget->allocation.height);
+  cairo_pattern_add_color_stop_rgb(
+      pattern, 0.0,
+      kTopSeparatorColor[0], kTopSeparatorColor[1], kTopSeparatorColor[2]);
+  cairo_pattern_add_color_stop_rgb(
+      pattern, 0.5,
+      kMidSeparatorColor[0], kMidSeparatorColor[1], kMidSeparatorColor[2]);
+  cairo_pattern_add_color_stop_rgb(
+      pattern, 1.0,
+      bottom_color_rgb[0], bottom_color_rgb[1], bottom_color_rgb[2]);
+  cairo_set_source(cr, pattern);
+
+  double start_x = 0.5 + widget->allocation.x;
+  cairo_new_path(cr);
+  cairo_set_line_width(cr, 1.0);
+  cairo_move_to(cr, start_x, widget->allocation.y);
+  cairo_line_to(cr, start_x,
+                    widget->allocation.y + widget->allocation.height);
+  cairo_stroke(cr);
+  cairo_destroy(cr);
+  cairo_pattern_destroy(pattern);
+
+  return TRUE;
+}
diff --git a/chrome/browser/ui/gtk/gtk_theme_provider.h b/chrome/browser/ui/gtk/gtk_theme_provider.h
new file mode 100644
index 0000000..90c4e78
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_theme_provider.h
@@ -0,0 +1,312 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_THEME_PROVIDER_H_
+#define CHROME_BROWSER_UI_GTK_GTK_THEME_PROVIDER_H_
+#pragma once
+
+#include <map>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "ui/base/gtk/gtk_integers.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/color_utils.h"
+
+class CairoCachedSurface;
+class Profile;
+
+namespace ui {
+class GtkSignalRegistrar;
+}
+
+typedef struct _GdkDisplay GdkDisplay;
+typedef struct _GdkEventExpose GdkEventExpose;
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _GtkIconSet GtkIconSet;
+typedef struct _GtkStyle GtkStyle;
+typedef struct _GtkWidget GtkWidget;
+
+// Specialization of BrowserThemeProvider which supplies system colors.
+class GtkThemeProvider : public BrowserThemeProvider,
+                         public NotificationObserver {
+ public:
+  // Returns GtkThemeProvider, casted from our superclass.
+  static GtkThemeProvider* GetFrom(Profile* profile);
+
+  GtkThemeProvider();
+  virtual ~GtkThemeProvider();
+
+  // Calls |observer|.Observe() for the browser theme with this provider as the
+  // source.
+  void InitThemesFor(NotificationObserver* observer);
+
+  // Overridden from BrowserThemeProvider:
+  //
+  // Sets that we aren't using the system theme, then calls
+  // BrowserThemeProvider's implementation.
+  virtual void Init(Profile* profile);
+  virtual SkBitmap* GetBitmapNamed(int id) const;
+  virtual SkColor GetColor(int id) const;
+  virtual bool HasCustomImage(int id) const;
+  virtual void SetTheme(const Extension* extension);
+  virtual void UseDefaultTheme();
+  virtual void SetNativeTheme();
+  virtual bool UsingDefaultTheme();
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Creates a GtkChromeButton instance, registered with this theme provider,
+  // with a "destroy" signal to remove it from our internal list when it goes
+  // away.
+  GtkWidget* BuildChromeButton();
+
+  // Creates a theme-aware vertical separator widget.
+  GtkWidget* CreateToolbarSeparator();
+
+  // Whether we should use the GTK system theme.
+  bool UseGtkTheme() const;
+
+  // A wrapper around ui::ThemeProvider::GetColor, transforming the result to a
+  // GdkColor.
+  GdkColor GetGdkColor(int id) const;
+
+  // A weighted average between the text color and the background color of a
+  // label. Used for borders between GTK stuff and the webcontent.
+  GdkColor GetBorderColor() const;
+
+  // Returns a set of icons tinted for different GtkStateTypes based on the
+  // label colors for the IDR resource |id|.
+  GtkIconSet* GetIconSetForId(int id) const;
+
+  // This method returns the colors webkit will use for the scrollbars. When no
+  // colors are specified by the GTK+ theme, this function averages of the
+  // thumb part and of the track colors.
+  void GetScrollbarColors(GdkColor* thumb_active_color,
+                          GdkColor* thumb_inactive_color,
+                          GdkColor* track_color);
+
+  // Expose the inner label. Only used for testing.
+  GtkWidget* fake_label() { return fake_label_.get(); }
+
+  // Returns a CairoCachedSurface for a particular Display. CairoCachedSurfaces
+  // (hopefully) live on the X server, instead of the client so we don't have
+  // to send the image to the server on each expose.
+  CairoCachedSurface* GetSurfaceNamed(int id, GtkWidget* widget_on_display);
+
+  // Same as above, but auto-mirrors the underlying pixbuf in RTL mode.
+  CairoCachedSurface* GetRTLEnabledSurfaceNamed(int id,
+                                                GtkWidget* widget_on_display);
+
+  // Same as above, but gets the resource from the ResourceBundle instead of the
+  // BrowserThemeProvider.
+  // NOTE: Never call this with resource IDs that are ever passed to the above
+  // two functions!  Depending on which call comes first, all callers will
+  // either get the themed or the unthemed version.
+  CairoCachedSurface* GetUnthemedSurfaceNamed(int id,
+                                              GtkWidget* widget_on_display);
+
+  // Returns colors that we pass to webkit to match the system theme.
+  const SkColor& get_focus_ring_color() const { return focus_ring_color_; }
+  const SkColor& get_thumb_active_color() const { return thumb_active_color_; }
+  const SkColor& get_thumb_inactive_color() const {
+    return thumb_inactive_color_;
+  }
+  const SkColor& get_track_color() const { return track_color_; }
+  const SkColor& get_active_selection_bg_color() const {
+    return active_selection_bg_color_;
+  }
+  const SkColor& get_active_selection_fg_color() const {
+    return active_selection_fg_color_;
+  }
+  const SkColor& get_inactive_selection_bg_color() const {
+    return inactive_selection_bg_color_;
+  }
+  const SkColor& get_inactive_selection_fg_color() const {
+    return inactive_selection_fg_color_;
+  }
+
+  // These functions do not add a ref to the returned pixbuf, and it should not
+  // be unreffed.  If |native| is true, get the GTK_STOCK version of the icon.
+  static GdkPixbuf* GetFolderIcon(bool native);
+  static GdkPixbuf* GetDefaultFavicon(bool native);
+
+  // Whether we use the GTK theme by default in the current desktop
+  // environment. Returns true when we GTK defaults to on.
+  static bool DefaultUsesSystemTheme();
+
+ private:
+  typedef std::map<int, SkColor> ColorMap;
+  typedef std::map<int, color_utils::HSL> TintMap;
+  typedef std::map<int, SkBitmap*> ImageCache;
+  typedef std::map<int, CairoCachedSurface*> CairoCachedSurfaceMap;
+  typedef std::map<GdkDisplay*, CairoCachedSurfaceMap> PerDisplaySurfaceMap;
+
+  // Clears all the GTK color overrides.
+  virtual void ClearAllThemeData();
+
+  // Load theme data from preferences, possibly picking colors from GTK.
+  virtual void LoadThemePrefs();
+
+  // Let all the browser views know that themes have changed.
+  virtual void NotifyThemeChanged(const Extension* extension);
+
+  // Additionally frees the CairoCachedSurfaces.
+  virtual void FreePlatformCaches();
+
+  // Extracts colors and tints from the GTK theme, both for the
+  // BrowserThemeProvider interface and the colors we send to webkit.
+  void LoadGtkValues();
+
+  // Reads in explicit theme frame colors from the ChromeGtkFrame style class
+  // or generates them per our fallback algorithm.
+  GdkColor BuildFrameColors(GtkStyle* frame_style);
+
+  // Sets the values that we send to webkit to safe defaults.
+  void LoadDefaultValues();
+
+  // Builds all of the tinted menus images needed for custom buttons. This is
+  // always called on style-set even if we aren't using the gtk-theme because
+  // the menus are always rendered with gtk colors.
+  void RebuildMenuIconSets();
+
+  // Sets the underlying theme colors/tints from a GTK color.
+  void SetThemeColorFromGtk(int id, const GdkColor* color);
+  void SetThemeTintFromGtk(int id, const GdkColor* color);
+
+  // Creates and returns a frame color, either using |gtk_base| verbatim if
+  // non-NULL, or tinting |base| with |tint|. Also sets |color_id| and
+  // |tint_id| to the returned color.
+  GdkColor BuildAndSetFrameColor(const GdkColor* base,
+                                 const GdkColor* gtk_base,
+                                 const color_utils::HSL& tint,
+                                 int color_id,
+                                 int tint_id);
+
+  // Split out from FreePlatformCaches so it can be called in our destructor;
+  // FreePlatformCaches() is called from the BrowserThemeProvider's destructor,
+  // but by the time ~BrowserThemeProvider() is run, the vtable no longer
+  // points to GtkThemeProvider's version.
+  void FreePerDisplaySurfaces(PerDisplaySurfaceMap* per_display_map);
+
+  // Frees all the created GtkIconSets we use for the chrome menu.
+  void FreeIconSets();
+
+  // Lazily generates each bitmap used in the gtk theme.
+  SkBitmap* GenerateGtkThemeBitmap(int id) const;
+
+  // Creates a GTK+ version of IDR_THEME_FRAME. Instead of tinting, this
+  // creates a theme configurable gradient ending with |color_id| at the
+  // bottom, and |gradient_name| at the top if that color is specified in the
+  // theme.
+  SkBitmap* GenerateFrameImage(int color_id,
+                               const char* gradient_name) const;
+
+  // Takes the base frame image |base_id| and tints it with |tint_id|.
+  SkBitmap* GenerateTabImage(int base_id) const;
+
+  // Tints an icon based on tint.
+  SkBitmap* GenerateTintedIcon(int base_id, color_utils::HSL tint) const;
+
+  // Returns the tint for buttons that contrasts with the normal window
+  // background color.
+  void GetNormalButtonTintHSL(color_utils::HSL* tint) const;
+
+  // Returns a tint that's the color of the current normal text in an entry.
+  void GetNormalEntryForegroundHSL(color_utils::HSL* tint) const;
+
+  // Returns a tint that's the color of the current highlighted text in an
+  // entry.
+  void GetSelectedEntryForegroundHSL(color_utils::HSL* tint) const;
+
+  // Implements GetXXXSurfaceNamed(), given the appropriate pixbuf to use.
+  CairoCachedSurface* GetSurfaceNamedImpl(int id,
+                                          PerDisplaySurfaceMap* surface_map,
+                                          GdkPixbuf* pixbuf,
+                                          GtkWidget* widget_on_display);
+
+  // Handles signal from GTK that our theme has been changed.
+  CHROMEGTK_CALLBACK_1(GtkThemeProvider, void, OnStyleSet, GtkStyle*);
+
+  // A notification from the GtkChromeButton GObject destructor that we should
+  // remove it from our internal list.
+  CHROMEGTK_CALLBACK_0(GtkThemeProvider, void, OnDestroyChromeButton);
+
+  CHROMEGTK_CALLBACK_1(GtkThemeProvider, gboolean, OnSeparatorExpose,
+                       GdkEventExpose*);
+
+  // Whether we should be using gtk rendering.
+  bool use_gtk_;
+
+  // GtkWidgets that exist only so we can look at their properties (and take
+  // their colors).
+  GtkWidget* fake_window_;
+  GtkWidget* fake_frame_;
+  OwnedWidgetGtk fake_label_;
+  OwnedWidgetGtk fake_entry_;
+  OwnedWidgetGtk fake_menu_item_;
+
+  // A list of all GtkChromeButton instances. We hold on to these to notify
+  // them of theme changes.
+  std::vector<GtkWidget*> chrome_buttons_;
+
+  // Tracks all the signals we have connected to on various widgets.
+  scoped_ptr<ui::GtkSignalRegistrar> signals_;
+
+  // Tints and colors calculated by LoadGtkValues() that are given to the
+  // caller while |use_gtk_| is true.
+  ColorMap colors_;
+  TintMap tints_;
+
+  // Colors used to tint certain icons.
+  color_utils::HSL button_tint_;
+  color_utils::HSL entry_tint_;
+  color_utils::HSL selected_entry_tint_;
+
+  // Colors that we pass to WebKit. These are generated each time the theme
+  // changes.
+  SkColor focus_ring_color_;
+  SkColor thumb_active_color_;
+  SkColor thumb_inactive_color_;
+  SkColor track_color_;
+  SkColor active_selection_bg_color_;
+  SkColor active_selection_fg_color_;
+  SkColor inactive_selection_bg_color_;
+  SkColor inactive_selection_fg_color_;
+
+  // A GtkIconSet that has the tinted icons for the NORMAL and PRELIGHT states
+  // of the IDR_FULLSCREEN_MENU_BUTTON tinted to the respective menu item label
+  // colors.
+  GtkIconSet* fullscreen_icon_set_;
+
+  // Image cache of lazily created images, created when requested by
+  // GetBitmapNamed().
+  mutable ImageCache gtk_images_;
+
+  // Cairo surfaces for each GdkDisplay.
+  PerDisplaySurfaceMap per_display_surfaces_;
+  PerDisplaySurfaceMap per_display_unthemed_surfaces_;
+
+  PrefChangeRegistrar registrar_;
+
+  // This is a dummy widget that only exists so we have something to pass to
+  // gtk_widget_render_icon().
+  static GtkWidget* icon_widget_;
+
+  // The default folder icon and default bookmark icon for the GTK theme.
+  // These are static because the system can only have one theme at a time.
+  // They are cached when they are requested the first time, and cleared when
+  // the system theme changes.
+  static GdkPixbuf* default_folder_icon_;
+  static GdkPixbuf* default_bookmark_icon_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_THEME_PROVIDER_H_
diff --git a/chrome/browser/ui/gtk/gtk_theme_provider_unittest.cc b/chrome/browser/ui/gtk/gtk_theme_provider_unittest.cc
new file mode 100644
index 0000000..30ad5ff
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_theme_provider_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_profile.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Converts a GdkColor to a SkColor.
+SkColor GdkToSkColor(GdkColor* color) {
+  return SkColorSetRGB(color->red >> 8,
+                       color->green >> 8,
+                       color->blue >> 8);
+}
+
+}  // namespace
+
+class GtkThemeProviderTest : public testing::Test {
+ public:
+  GtkThemeProviderTest() : provider_(NULL) {}
+
+  void SetUseGtkTheme(bool use_gtk_theme) {
+    profile_.GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, use_gtk_theme);
+  }
+
+  void BuildProvider() {
+    profile_.InitThemes();
+    provider_ = GtkThemeProvider::GetFrom(&profile_);
+  }
+
+ protected:
+  TestingProfile profile_;
+
+  GtkThemeProvider* provider_;
+};
+
+TEST_F(GtkThemeProviderTest, DefaultValues) {
+  SetUseGtkTheme(false);
+  BuildProvider();
+
+  // Test that we get the default theme colors back when in normal mode.
+  for (int i = BrowserThemeProvider::COLOR_FRAME;
+       i <= BrowserThemeProvider::COLOR_BUTTON_BACKGROUND; ++i) {
+    EXPECT_EQ(provider_->GetColor(i), BrowserThemeProvider::GetDefaultColor(i))
+        << "Wrong default color for " << i;
+  }
+}
+
+TEST_F(GtkThemeProviderTest, UsingGtkValues) {
+  SetUseGtkTheme(true);
+  BuildProvider();
+
+  // This test only verifies that we're using GTK values. Because of Gtk's
+  // large, implied global state, it would take some IN_PROCESS_BROWSER_TESTS
+  // to write an equivalent of DefaultValues above in a way that wouldn't make
+  // other tests flaky. kColorTabText is the only simple path where there's no
+  // weird calculations for edge cases so use that as a simple test.
+  GtkWidget* fake_label = provider_->fake_label();
+  GtkStyle* label_style = gtk_rc_get_style(fake_label);
+  GdkColor label_color = label_style->fg[GTK_STATE_NORMAL];
+  EXPECT_EQ(provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT),
+            GdkToSkColor(&label_color));
+}
diff --git a/chrome/browser/ui/gtk/gtk_tree.cc b/chrome/browser/ui/gtk/gtk_tree.cc
new file mode 100644
index 0000000..7c16ac9
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_tree.cc
@@ -0,0 +1,475 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_tree.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/models/table_model.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace gtk_tree {
+
+gint GetRowNumForPath(GtkTreePath* path) {
+  gint* indices = gtk_tree_path_get_indices(path);
+  if (!indices) {
+    NOTREACHED();
+    return -1;
+  }
+  return indices[0];
+}
+
+gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) {
+  GtkTreePath* path = gtk_tree_model_get_path(model, iter);
+  int row = GetRowNumForPath(path);
+  gtk_tree_path_free(path);
+  return row;
+}
+
+gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
+                                   GtkTreePath* sort_path) {
+  GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path(
+      GTK_TREE_MODEL_SORT(sort_model), sort_path);
+  int row = GetRowNumForPath(child_path);
+  gtk_tree_path_free(child_path);
+  return row;
+}
+
+void SelectAndFocusRowNum(int row, GtkTreeView* tree_view) {
+  GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
+  if (!model) {
+    NOTREACHED();
+    return;
+  }
+  GtkTreeIter iter;
+  if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) {
+    NOTREACHED();
+    return;
+  }
+  GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
+  gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE);
+  gtk_tree_path_free(path);
+}
+
+bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter) {
+  GtkTreeIter child;
+  if (gtk_tree_model_iter_children(GTK_TREE_MODEL(tree_store), &child, iter)) {
+    while (true) {
+      if (!RemoveRecursively(tree_store, &child))
+        break;
+    }
+  }
+  return gtk_tree_store_remove(tree_store, iter);
+}
+
+void GetSelectedIndices(GtkTreeSelection* selection, std::set<int>* out) {
+  GList* list = gtk_tree_selection_get_selected_rows(
+      selection, NULL);
+  GList* node;
+  for (node = list; node != NULL; node = node->next) {
+    out->insert(
+        gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(node->data)));
+  }
+  g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
+  g_list_free(list);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//  TableAdapter
+
+TableAdapter::TableAdapter(Delegate* delegate, GtkListStore* list_store,
+                           ui::TableModel* table_model)
+    : delegate_(delegate), list_store_(list_store), table_model_(table_model) {
+  if (table_model)
+    table_model->SetObserver(this);
+}
+
+void TableAdapter::SetModel(ui::TableModel* table_model) {
+  table_model_ = table_model;
+  table_model_->SetObserver(this);
+}
+
+bool TableAdapter::IsGroupRow(GtkTreeIter* iter) const {
+  if (!table_model_->HasGroups())
+    return false;
+  gboolean is_header = false;
+  gboolean is_separator = false;
+  gtk_tree_model_get(GTK_TREE_MODEL(list_store_),
+                     iter,
+                     COL_IS_HEADER,
+                     &is_header,
+                     COL_IS_SEPARATOR,
+                     &is_separator,
+                     -1);
+  return is_header || is_separator;
+}
+
+static int OffsetForGroupIndex(size_t group_index) {
+  // Every group consists of a header and a separator row, and there is a blank
+  // row between groups.
+  return 3 * group_index + 2;
+}
+
+void TableAdapter::MapListStoreIndicesToModelRows(
+    const std::set<int>& list_store_indices,
+    RemoveRowsTableModel::Rows* model_rows) {
+  if (!table_model_->HasGroups()) {
+    for (std::set<int>::const_iterator it = list_store_indices.begin();
+         it != list_store_indices.end();
+         ++it) {
+      model_rows->insert(*it);
+    }
+    return;
+  }
+
+  const ui::TableModel::Groups& groups = table_model_->GetGroups();
+  ui::TableModel::Groups::const_iterator group_it = groups.begin();
+  for (std::set<int>::const_iterator list_store_it = list_store_indices.begin();
+       list_store_it != list_store_indices.end();
+       ++list_store_it) {
+    int list_store_index = *list_store_it;
+    GtkTreeIter iter;
+    bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
+                                       &iter,
+                                       NULL,
+                                       list_store_index);
+    if (!rv) {
+      NOTREACHED();
+      return;
+    }
+    int group = -1;
+    gtk_tree_model_get(GTK_TREE_MODEL(list_store_),
+                       &iter,
+                       COL_GROUP_ID,
+                       &group,
+                       -1);
+    while (group_it->id != group) {
+      ++group_it;
+      if (group_it == groups.end()) {
+        NOTREACHED();
+        return;
+      }
+    }
+    int offset = OffsetForGroupIndex(group_it - groups.begin());
+    model_rows->insert(list_store_index - offset);
+  }
+}
+
+int TableAdapter::GetListStoreIndexForModelRow(int model_row) const {
+  if (!table_model_->HasGroups())
+    return model_row;
+  int group = table_model_->GetGroupID(model_row);
+  const ui::TableModel::Groups& groups = table_model_->GetGroups();
+  for (ui::TableModel::Groups::const_iterator it = groups.begin();
+       it != groups.end(); ++it) {
+    if (it->id == group) {
+      return model_row + OffsetForGroupIndex(it - groups.begin());
+    }
+  }
+  NOTREACHED();
+  return -1;
+}
+
+void TableAdapter::AddNodeToList(int row) {
+  GtkTreeIter iter;
+  int list_store_index = GetListStoreIndexForModelRow(row);
+  if (list_store_index == 0) {
+    gtk_list_store_prepend(list_store_, &iter);
+  } else {
+    GtkTreeIter sibling;
+    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling, NULL,
+                                  list_store_index - 1);
+    gtk_list_store_insert_after(list_store_, &iter, &sibling);
+  }
+
+  if (table_model_->HasGroups()) {
+    gtk_list_store_set(list_store_,
+                       &iter,
+                       COL_WEIGHT, PANGO_WEIGHT_NORMAL,
+                       COL_WEIGHT_SET, TRUE,
+                       COL_GROUP_ID, table_model_->GetGroupID(row),
+                       -1);
+  }
+  delegate_->SetColumnValues(row, &iter);
+}
+
+void TableAdapter::OnModelChanged() {
+  delegate_->OnAnyModelUpdateStart();
+  gtk_list_store_clear(list_store_);
+  delegate_->OnModelChanged();
+
+  if (table_model_->HasGroups()) {
+    const ui::TableModel::Groups& groups = table_model_->GetGroups();
+    for (ui::TableModel::Groups::const_iterator it = groups.begin();
+         it != groups.end(); ++it) {
+      GtkTreeIter iter;
+      if (it != groups.begin()) {
+        // Blank row between groups.
+        gtk_list_store_append(list_store_, &iter);
+        gtk_list_store_set(list_store_, &iter, COL_IS_HEADER, TRUE, -1);
+      }
+      // Group title.
+      gtk_list_store_append(list_store_, &iter);
+      gtk_list_store_set(list_store_,
+                         &iter,
+                         COL_WEIGHT,
+                         PANGO_WEIGHT_BOLD,
+                         COL_WEIGHT_SET,
+                         TRUE,
+                         COL_TITLE,
+                         UTF16ToUTF8(it->title).c_str(),
+                         COL_IS_HEADER,
+                         TRUE,
+                         -1);
+      // Group separator.
+      gtk_list_store_append(list_store_, &iter);
+      gtk_list_store_set(list_store_,
+                         &iter,
+                         COL_IS_HEADER,
+                         TRUE,
+                         COL_IS_SEPARATOR,
+                         TRUE,
+                         -1);
+    }
+  }
+
+  for (int i = 0; i < table_model_->RowCount(); ++i)
+    AddNodeToList(i);
+  delegate_->OnAnyModelUpdate();
+}
+
+void TableAdapter::OnItemsChanged(int start, int length) {
+  if (length == 0)
+    return;
+  delegate_->OnAnyModelUpdateStart();
+  int list_store_index = GetListStoreIndexForModelRow(start);
+  GtkTreeIter iter;
+  bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
+                                          &iter,
+                                          NULL,
+                                          list_store_index);
+  for (int i = 0; i < length; ++i) {
+    if (!rv) {
+      NOTREACHED();
+      return;
+    }
+    while (IsGroupRow(&iter)) {
+      rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
+      if (!rv) {
+        NOTREACHED();
+        return;
+      }
+    }
+    delegate_->SetColumnValues(start + i, &iter);
+    rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
+  }
+  delegate_->OnAnyModelUpdate();
+}
+
+void TableAdapter::OnItemsAdded(int start, int length) {
+  delegate_->OnAnyModelUpdateStart();
+  for (int i = 0; i < length; ++i) {
+    AddNodeToList(start + i);
+  }
+  delegate_->OnAnyModelUpdate();
+}
+
+void TableAdapter::OnItemsRemoved(int start, int length) {
+  if (length == 0)
+    return;
+  delegate_->OnAnyModelUpdateStart();
+  // When this method is called, the model has already removed the items, so
+  // accessing items in the model from |start| on may not be possible anymore.
+  // Therefore we use the item right before that, if it exists.
+  int list_store_index = 0;
+  if (start > 0)
+    list_store_index = GetListStoreIndexForModelRow(start - 1) + 1;
+  GtkTreeIter iter;
+  bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
+                                          &iter,
+                                          NULL,
+                                          list_store_index);
+  if (!rv) {
+    NOTREACHED();
+    return;
+  }
+  for (int i = 0; i < length; ++i) {
+    while (IsGroupRow(&iter)) {
+      rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
+      if (!rv) {
+        NOTREACHED();
+        return;
+      }
+    }
+    gtk_list_store_remove(list_store_, &iter);
+  }
+  delegate_->OnAnyModelUpdate();
+}
+
+// static
+gboolean TableAdapter::OnCheckRowIsSeparator(GtkTreeModel* model,
+                                             GtkTreeIter* iter,
+                                             gpointer user_data) {
+  gboolean is_separator;
+  gtk_tree_model_get(model,
+                     iter,
+                     COL_IS_SEPARATOR,
+                     &is_separator,
+                     -1);
+  return is_separator;
+}
+
+// static
+gboolean TableAdapter::OnSelectionFilter(GtkTreeSelection* selection,
+                                         GtkTreeModel* model,
+                                         GtkTreePath* path,
+                                         gboolean path_currently_selected,
+                                         gpointer user_data) {
+  GtkTreeIter iter;
+  if (!gtk_tree_model_get_iter(model, &iter, path)) {
+    NOTREACHED();
+    return TRUE;
+  }
+  gboolean is_header;
+  gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1);
+  return !is_header;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//  TreeAdapter
+
+TreeAdapter::TreeAdapter(Delegate* delegate, ui::TreeModel* tree_model)
+    : delegate_(delegate),
+      tree_model_(tree_model) {
+  tree_store_ = gtk_tree_store_new(COL_COUNT,
+                                   GDK_TYPE_PIXBUF,
+                                   G_TYPE_STRING,
+                                   G_TYPE_POINTER);
+  tree_model->AddObserver(this);
+
+  std::vector<SkBitmap> icons;
+  tree_model->GetIcons(&icons);
+  for (size_t i = 0; i < icons.size(); ++i) {
+    pixbufs_.push_back(gfx::GdkPixbufFromSkBitmap(&icons[i]));
+  }
+}
+
+TreeAdapter::~TreeAdapter() {
+  g_object_unref(tree_store_);
+  for (size_t i = 0; i < pixbufs_.size(); ++i)
+    g_object_unref(pixbufs_[i]);
+}
+
+void TreeAdapter::Init() {
+  gtk_tree_store_clear(tree_store_);
+  Fill(NULL, tree_model_->GetRoot());
+}
+
+
+ui::TreeModelNode* TreeAdapter::GetNode(GtkTreeIter* iter) {
+  ui::TreeModelNode* node;
+  gtk_tree_model_get(GTK_TREE_MODEL(tree_store_), iter,
+                     COL_NODE_PTR, &node,
+                     -1);
+  return node;
+}
+
+void TreeAdapter::FillRow(GtkTreeIter* iter, ui::TreeModelNode* node) {
+  GdkPixbuf* pixbuf = NULL;
+  int icon_index = tree_model_->GetIconIndex(node);
+  if (icon_index >= 0 && icon_index < static_cast<int>(pixbufs_.size()))
+    pixbuf = pixbufs_[icon_index];
+  else
+    pixbuf = GtkThemeProvider::GetFolderIcon(true);
+  gtk_tree_store_set(tree_store_, iter,
+                     COL_ICON, pixbuf,
+                     COL_TITLE, UTF16ToUTF8(node->GetTitle()).c_str(),
+                     COL_NODE_PTR, node,
+                     -1);
+}
+
+void TreeAdapter::Fill(GtkTreeIter* parent_iter,
+                       ui::TreeModelNode* parent_node) {
+  if (parent_iter)
+    FillRow(parent_iter, parent_node);
+  GtkTreeIter iter;
+  int child_count = tree_model_->GetChildCount(parent_node);
+  for (int i = 0; i < child_count; ++i) {
+    ui::TreeModelNode* node = tree_model_->GetChild(parent_node, i);
+    gtk_tree_store_append(tree_store_, &iter, parent_iter);
+    Fill(&iter, node);
+  }
+}
+
+GtkTreePath* TreeAdapter::GetTreePath(ui::TreeModelNode* node) {
+  GtkTreePath* path = gtk_tree_path_new();
+  ui::TreeModelNode* parent = node;
+  while (parent) {
+    parent = tree_model_->GetParent(parent);
+    if (parent) {
+      int idx = tree_model_->IndexOfChild(parent, node);
+      gtk_tree_path_prepend_index(path, idx);
+      node = parent;
+    }
+  }
+  return path;
+}
+
+bool TreeAdapter::GetTreeIter(ui::TreeModelNode* node, GtkTreeIter* iter) {
+  GtkTreePath* path = GetTreePath(node);
+  bool rv = false;
+  // Check the path ourselves since gtk_tree_model_get_iter prints a warning if
+  // given an empty path.  The path will be empty when it points to the root
+  // node and we are using SetRootShown(false).
+  if (gtk_tree_path_get_depth(path) > 0)
+    rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), iter, path);
+  gtk_tree_path_free(path);
+  return rv;
+}
+
+void TreeAdapter::TreeNodesAdded(ui::TreeModel* model,
+                                 ui::TreeModelNode* parent,
+                                 int start,
+                                 int count) {
+  delegate_->OnAnyModelUpdateStart();
+  GtkTreeIter parent_iter;
+  GtkTreeIter* parent_iter_ptr = NULL;
+  GtkTreeIter iter;
+  if (GetTreeIter(parent, &parent_iter))
+    parent_iter_ptr = &parent_iter;
+  for (int i = 0; i < count; ++i) {
+    gtk_tree_store_insert(tree_store_, &iter, parent_iter_ptr, start + i);
+    Fill(&iter, tree_model_->GetChild(parent, start + i));
+  }
+  delegate_->OnAnyModelUpdate();
+}
+
+void TreeAdapter::TreeNodesRemoved(ui::TreeModel* model,
+                                   ui::TreeModelNode* parent,
+                                   int start,
+                                   int count) {
+  delegate_->OnAnyModelUpdateStart();
+  GtkTreeIter iter;
+  GtkTreePath* path = GetTreePath(parent);
+  gtk_tree_path_append_index(path, start);
+  gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), &iter, path);
+  gtk_tree_path_free(path);
+  for (int i = 0; i < count; ++i) {
+    RemoveRecursively(tree_store_, &iter);
+  }
+  delegate_->OnAnyModelUpdate();
+}
+
+void TreeAdapter::TreeNodeChanged(ui::TreeModel* model,
+                                  ui::TreeModelNode* node) {
+  delegate_->OnAnyModelUpdateStart();
+  GtkTreeIter iter;
+  if (GetTreeIter(node, &iter))
+    FillRow(&iter, node);
+  delegate_->OnAnyModelUpdate();
+}
+
+}  // namespace gtk_tree
diff --git a/chrome/browser/ui/gtk/gtk_tree.h b/chrome/browser/ui/gtk/gtk_tree.h
new file mode 100644
index 0000000..d527a45
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_tree.h
@@ -0,0 +1,210 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_TREE_H_
+#define CHROME_BROWSER_UI_GTK_GTK_TREE_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <set>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/browser/remove_rows_table_model.h"
+#include "ui/base/models/table_model_observer.h"
+#include "ui/base/models/tree_model.h"
+
+namespace ui {
+class TableModel;
+}
+
+namespace gtk_tree {
+
+// Get the row number corresponding to |path|.
+gint GetRowNumForPath(GtkTreePath* path);
+
+// Get the row number corresponding to |iter|.
+gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter);
+
+// Get the row number in the child tree model corresponding to |sort_path| in
+// the parent tree model.
+gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
+                                   GtkTreePath* sort_path);
+
+// Select the given row by number.
+void SelectAndFocusRowNum(int row, GtkTreeView* tree_view);
+
+// Remove the row and all its children from the |tree_store|.  If there is a
+// following row, |iter| will be updated to point to the it and the return value
+// will be true, otherwise the return will be false and |iter| is no longer
+// valid.
+bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter);
+
+// Writes all the indexes of selected rows into |out|.
+void GetSelectedIndices(GtkTreeSelection* selection, std::set<int>* out);
+
+// A helper class for populating a GtkListStore from a ui::TableModel.
+class TableAdapter : public ui::TableModelObserver {
+ public:
+
+  enum ColumnID {
+    COL_TITLE = 0,
+    COL_IS_HEADER,
+    COL_IS_SEPARATOR,
+    COL_GROUP_ID,
+    COL_WEIGHT,
+    COL_WEIGHT_SET,
+    COL_LAST_ID
+  };
+
+  class Delegate {
+   public:
+    // Should fill in the column and row.
+    virtual void SetColumnValues(int row, GtkTreeIter* iter) = 0;
+
+    // Called after any change to the ui::TableModel but before the
+    // corresponding change to the GtkListStore.
+    virtual void OnAnyModelUpdateStart() {}
+
+    // Called after any change to the ui::TableModel.
+    virtual void OnAnyModelUpdate() {}
+
+    // When the ui::TableModel has been completely changed, called by
+    // OnModelChanged after clearing the list store.  Can be overridden by the
+    // delegate if it needs to do extra initialization before the list store is
+    // populated.
+    virtual void OnModelChanged() {}
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // |table_model| may be NULL.
+  TableAdapter(Delegate* delegate,
+               GtkListStore* list_store,
+               ui::TableModel* table_model);
+  virtual ~TableAdapter() {}
+
+  // Replace the ui::TableModel with a different one.  If the list store
+  // currently has items this would cause weirdness, so this should generally
+  // only be called during the Delegate's OnModelChanged call, or if the adapter
+  // was created with a NULL |table_model|.
+  void SetModel(ui::TableModel* table_model);
+
+  // Add all model rows corresponding to the given list store indices to |rows|.
+  void MapListStoreIndicesToModelRows(const std::set<int>& list_store_indices,
+                                      RemoveRowsTableModel::Rows* model_rows);
+
+  // GtkTreeModel callbacks:
+  // Callback checking whether a row should be drawn as a separator.
+  static gboolean OnCheckRowIsSeparator(GtkTreeModel* model,
+                                        GtkTreeIter* iter,
+                                        gpointer user_data);
+
+  // Callback checking whether a row may be selected.  We use some rows in the
+  // table as headers/separators for the groups, which should not be selectable.
+  static gboolean OnSelectionFilter(GtkTreeSelection* selection,
+                                    GtkTreeModel* model,
+                                    GtkTreePath* path,
+                                    gboolean path_currently_selected,
+                                    gpointer user_data);
+
+  // ui::TableModelObserver implementation.
+  virtual void OnModelChanged();
+  virtual void OnItemsChanged(int start, int length);
+  virtual void OnItemsAdded(int start, int length);
+  virtual void OnItemsRemoved(int start, int length);
+
+ private:
+  // Return whether the row pointed to by |iter| is a group row, i.e. a group
+  // header, or a separator.
+  bool IsGroupRow(GtkTreeIter* iter) const;
+
+  // Return the index into the list store for the given model row.
+  int GetListStoreIndexForModelRow(int model_row) const;
+
+  // Add the values from |row| of the ui::TableModel.
+  void AddNodeToList(int row);
+
+  Delegate* delegate_;
+  GtkListStore* list_store_;
+  ui::TableModel* table_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(TableAdapter);
+};
+
+// A helper class for populating a GtkTreeStore from a TreeModel.
+// TODO(mattm): support SetRootShown(true)
+class TreeAdapter : public ui::TreeModelObserver {
+ public:
+  // Column ids for |tree_store_|.
+  enum {
+    COL_ICON,
+    COL_TITLE,
+    COL_NODE_PTR,
+    COL_COUNT,
+  };
+
+  class Delegate {
+   public:
+    // Called after any change to the TreeModel but before the corresponding
+    // change to the GtkTreeStore.
+    virtual void OnAnyModelUpdateStart() {}
+
+    // Called after any change to the GtkTreeStore.
+    virtual void OnAnyModelUpdate() {}
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  TreeAdapter(Delegate* delegate, ui::TreeModel* tree_model);
+  virtual ~TreeAdapter();
+
+  // Populate the tree store from the |tree_model_|.
+  void Init();
+
+  // Return the tree store.
+  GtkTreeStore* tree_store() { return tree_store_; }
+
+  // Get the TreeModelNode corresponding to iter in the tree store.
+  ui::TreeModelNode* GetNode(GtkTreeIter* iter);
+
+  // Begin TreeModelObserver implementation.
+  virtual void TreeNodesAdded(ui::TreeModel* model,
+                              ui::TreeModelNode* parent,
+                              int start,
+                              int count);
+  virtual void TreeNodesRemoved(ui::TreeModel* model,
+                                ui::TreeModelNode* parent,
+                                int start,
+                                int count);
+  virtual void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node);
+  // End TreeModelObserver implementation.
+
+ private:
+  // Fill the tree store values for a given node.
+  void FillRow(GtkTreeIter* iter, ui::TreeModelNode* node);
+
+  // Fill the tree store for a row and all its descendants.
+  void Fill(GtkTreeIter* parent_iter, ui::TreeModelNode* parent_node);
+
+  // Get the GtkTreePath in the tree store for the given node.
+  // The returned path should be freed with gtk_tree_path_free.
+  GtkTreePath* GetTreePath(ui::TreeModelNode* node);
+
+  // Get the GtkTreeIter in the tree store for the given node.
+  bool GetTreeIter(ui::TreeModelNode* node, GtkTreeIter* iter);
+
+  Delegate* delegate_;
+  GtkTreeStore* tree_store_;
+  ui::TreeModel* tree_model_;
+  std::vector<GdkPixbuf*> pixbufs_;
+
+  DISALLOW_COPY_AND_ASSIGN(TreeAdapter);
+};
+
+}  // namespace gtk_tree
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_TREE_H_
diff --git a/chrome/browser/ui/gtk/gtk_util.cc b/chrome/browser/ui/gtk/gtk_util.cc
new file mode 100644
index 0000000..e757c74
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_util.cc
@@ -0,0 +1,1264 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/gtk_util.h"
+
+#include <cairo/cairo.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include <cstdarg>
+#include <map>
+
+#include "base/environment.h"
+#include "base/i18n/rtl.h"
+#include "base/linux_util.h"
+#include "base/logging.h"
+#include "base/nix/xdg_util.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/disposition_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/common/renderer_preferences.h"
+#include "googleurl/src/gurl.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_util.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/frame/browser_view.h"
+#include "chrome/browser/chromeos/native_dialog_window.h"
+#include "views/window/window.h"
+#else
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#endif
+
+using WebKit::WebDragOperationsMask;
+using WebKit::WebDragOperation;
+using WebKit::WebDragOperationNone;
+using WebKit::WebDragOperationCopy;
+using WebKit::WebDragOperationLink;
+using WebKit::WebDragOperationMove;
+
+namespace {
+
+const char kBoldLabelMarkup[] = "<span weight='bold'>%s</span>";
+
+// Callback used in RemoveAllChildren.
+void RemoveWidget(GtkWidget* widget, gpointer container) {
+  gtk_container_remove(GTK_CONTAINER(container), widget);
+}
+
+// These two functions are copped almost directly from gtk core. The only
+// difference is that they accept middle clicks.
+gboolean OnMouseButtonPressed(GtkWidget* widget, GdkEventButton* event,
+                              gpointer userdata) {
+  if (event->type == GDK_BUTTON_PRESS) {
+    if (gtk_button_get_focus_on_click(GTK_BUTTON(widget)) &&
+        !GTK_WIDGET_HAS_FOCUS(widget)) {
+      gtk_widget_grab_focus(widget);
+    }
+
+    gint button_mask = GPOINTER_TO_INT(userdata);
+    if (button_mask & (1 << event->button))
+      gtk_button_pressed(GTK_BUTTON(widget));
+  }
+
+  return TRUE;
+}
+
+gboolean OnMouseButtonReleased(GtkWidget* widget, GdkEventButton* event,
+                               gpointer userdata) {
+  gint button_mask = GPOINTER_TO_INT(userdata);
+  if (button_mask && (1 << event->button))
+    gtk_button_released(GTK_BUTTON(widget));
+
+  return TRUE;
+}
+
+// Returns the approximate number of characters that can horizontally fit in
+// |pixel_width| pixels.
+int GetCharacterWidthForPixels(GtkWidget* widget, int pixel_width) {
+  DCHECK(GTK_WIDGET_REALIZED(widget))
+      << " widget must be realized to compute font metrics correctly";
+
+  PangoContext* context = gtk_widget_create_pango_context(widget);
+  PangoFontMetrics* metrics = pango_context_get_metrics(context,
+      widget->style->font_desc, pango_context_get_language(context));
+
+  // This technique (max of char and digit widths) matches the code in
+  // gtklabel.c.
+  int char_width = pixel_width * PANGO_SCALE /
+      std::max(pango_font_metrics_get_approximate_char_width(metrics),
+               pango_font_metrics_get_approximate_digit_width(metrics));
+
+  pango_font_metrics_unref(metrics);
+  g_object_unref(context);
+
+  return char_width;
+}
+
+void OnLabelRealize(GtkWidget* label, gpointer pixel_width) {
+  gtk_label_set_width_chars(
+      GTK_LABEL(label),
+      GetCharacterWidthForPixels(label,GPOINTER_TO_INT(pixel_width)));
+}
+
+// Ownership of |icon_list| is passed to the caller.
+GList* GetIconList() {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  GList* icon_list = NULL;
+  icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_ICON_32));
+  icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
+  return icon_list;
+}
+
+// Expose event handler for a container that simply suppresses the default
+// drawing and propagates the expose event to the container's children.
+gboolean PaintNoBackground(GtkWidget* widget,
+                           GdkEventExpose* event,
+                           gpointer unused) {
+  GList* children = gtk_container_get_children(GTK_CONTAINER(widget));
+  for (GList* item = children; item; item = item->next) {
+    gtk_container_propagate_expose(GTK_CONTAINER(widget),
+                                   GTK_WIDGET(item->data),
+                                   event);
+  }
+  g_list_free(children);
+
+  return TRUE;
+}
+
+#if defined(OS_CHROMEOS)
+
+TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
+  chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
+      window);
+  return browser_view->GetSelectedTabContents();
+}
+
+GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
+  gfx::NativeView widget = gtk_window_get_focus(window->GetNativeHandle());
+
+  if (widget == NULL) {
+    chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
+        window);
+    widget = browser_view->saved_focused_widget();
+  }
+
+  return widget;
+}
+
+#else
+
+TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
+  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
+      window);
+  return browser_window->browser()->GetSelectedTabContents();
+}
+
+GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
+  return gtk_window_get_focus(window->GetNativeHandle());
+}
+
+#endif
+
+}  // namespace
+
+namespace event_utils {
+
+WindowOpenDisposition DispositionFromEventFlags(guint event_flags) {
+  return disposition_utils::DispositionFromClick(
+      event_flags & GDK_BUTTON2_MASK,
+      event_flags & GDK_MOD1_MASK,
+      event_flags & GDK_CONTROL_MASK,
+      event_flags & GDK_META_MASK,
+      event_flags & GDK_SHIFT_MASK);
+}
+
+}  // namespace event_utils
+
+namespace gtk_util {
+
+const GdkColor kGdkWhite = GDK_COLOR_RGB(0xff, 0xff, 0xff);
+const GdkColor kGdkGray  = GDK_COLOR_RGB(0x7f, 0x7f, 0x7f);
+const GdkColor kGdkBlack = GDK_COLOR_RGB(0x00, 0x00, 0x00);
+const GdkColor kGdkGreen = GDK_COLOR_RGB(0x00, 0xff, 0x00);
+
+GtkWidget* CreateLabeledControlsGroup(std::vector<GtkWidget*>* labels,
+                                      const char* text, ...) {
+  va_list ap;
+  va_start(ap, text);
+  GtkWidget* table = gtk_table_new(0, 2, FALSE);
+  gtk_table_set_col_spacing(GTK_TABLE(table), 0, kLabelSpacing);
+  gtk_table_set_row_spacings(GTK_TABLE(table), kControlSpacing);
+
+  for (guint row = 0; text; ++row) {
+    gtk_table_resize(GTK_TABLE(table), row + 1, 2);
+    GtkWidget* control = va_arg(ap, GtkWidget*);
+    GtkWidget* label = gtk_label_new(text);
+    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+    if (labels)
+      labels->push_back(label);
+
+    gtk_table_attach(GTK_TABLE(table), label,
+                 0, 1, row, row + 1,
+                 GTK_FILL, GTK_FILL,
+                 0, 0);
+    gtk_table_attach_defaults(GTK_TABLE(table), control,
+                              1, 2, row, row + 1);
+    text = va_arg(ap, const char*);
+  }
+  va_end(ap);
+
+  return table;
+}
+
+GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
+                              int top, int bottom, int left, int right) {
+  // Use a GtkEventBox to get the background painted.  However, we can't just
+  // use a container border, since it won't paint there.  Use an alignment
+  // inside to get the sizes exactly of how we want the border painted.
+  GtkWidget* ebox = gtk_event_box_new();
+  if (color)
+    gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, color);
+  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), top, bottom, left, right);
+  gtk_container_add(GTK_CONTAINER(alignment), child);
+  gtk_container_add(GTK_CONTAINER(ebox), alignment);
+  return ebox;
+}
+
+GtkWidget* LeftAlignMisc(GtkWidget* misc) {
+  gtk_misc_set_alignment(GTK_MISC(misc), 0, 0.5);
+  return misc;
+}
+
+GtkWidget* CreateBoldLabel(const std::string& text) {
+  GtkWidget* label = gtk_label_new(NULL);
+  char* markup = g_markup_printf_escaped(kBoldLabelMarkup, text.c_str());
+  gtk_label_set_markup(GTK_LABEL(label), markup);
+  g_free(markup);
+
+  return LeftAlignMisc(label);
+}
+
+void GetWidgetSizeFromCharacters(
+    GtkWidget* widget, double width_chars, double height_lines,
+    int* width, int* height) {
+  DCHECK(GTK_WIDGET_REALIZED(widget))
+      << " widget must be realized to compute font metrics correctly";
+  PangoContext* context = gtk_widget_create_pango_context(widget);
+  PangoFontMetrics* metrics = pango_context_get_metrics(context,
+      widget->style->font_desc, pango_context_get_language(context));
+  if (width) {
+    *width = static_cast<int>(
+        pango_font_metrics_get_approximate_char_width(metrics) *
+        width_chars / PANGO_SCALE);
+  }
+  if (height) {
+    *height = static_cast<int>(
+        (pango_font_metrics_get_ascent(metrics) +
+        pango_font_metrics_get_descent(metrics)) *
+        height_lines / PANGO_SCALE);
+  }
+  pango_font_metrics_unref(metrics);
+  g_object_unref(context);
+}
+
+void GetWidgetSizeFromResources(
+    GtkWidget* widget, int width_chars, int height_lines,
+    int* width, int* height) {
+  DCHECK(GTK_WIDGET_REALIZED(widget))
+      << " widget must be realized to compute font metrics correctly";
+
+  double chars = 0;
+  if (width)
+    base::StringToDouble(l10n_util::GetStringUTF8(width_chars), &chars);
+
+  double lines = 0;
+  if (height)
+    base::StringToDouble(l10n_util::GetStringUTF8(height_lines), &lines);
+
+  GetWidgetSizeFromCharacters(widget, chars, lines, width, height);
+}
+
+void SetWindowSizeFromResources(GtkWindow* window,
+                                int width_id, int height_id, bool resizable) {
+  int width = -1;
+  int height = -1;
+  gtk_util::GetWidgetSizeFromResources(GTK_WIDGET(window), width_id, height_id,
+                                       (width_id != -1) ? &width : NULL,
+                                       (height_id != -1) ? &height : NULL);
+
+  if (resizable) {
+    gtk_window_set_default_size(window, width, height);
+  } else {
+    // For a non-resizable window, GTK tries to snap the window size
+    // to the minimum size around the content.  We use the sizes in
+    // the resources to set *minimum* window size to allow windows
+    // with long titles to be wide enough to display their titles.
+    //
+    // But if GTK wants to make the window *wider* due to very wide
+    // controls, we should allow that too, so be careful to pick the
+    // wider of the resources size and the natural window size.
+
+    gtk_widget_show_all(GTK_BIN(window)->child);
+    GtkRequisition requisition;
+    gtk_widget_size_request(GTK_WIDGET(window), &requisition);
+    gtk_widget_set_size_request(
+        GTK_WIDGET(window),
+        width == -1 ? -1 : std::max(width, requisition.width),
+        height == -1 ? -1 : std::max(height, requisition.height));
+  }
+  gtk_window_set_resizable(window, resizable ? TRUE : FALSE);
+}
+
+void CenterOverWindow(GtkWindow* window, GtkWindow* parent) {
+  gfx::Rect frame_bounds = gtk_util::GetWidgetScreenBounds(GTK_WIDGET(parent));
+  gfx::Point origin = frame_bounds.origin();
+  gfx::Size size = gtk_util::GetWidgetSize(GTK_WIDGET(window));
+  origin.Offset(
+      (frame_bounds.width() - size.width()) / 2,
+      (frame_bounds.height() - size.height()) / 2);
+
+  // Prevent moving window out of monitor bounds.
+  GdkScreen* screen = gtk_window_get_screen(parent);
+  if (screen) {
+    // It would be better to check against workarea for given monitor
+    // but getting workarea for particular monitor is tricky.
+    gint monitor = gdk_screen_get_monitor_at_window(screen,
+        GTK_WIDGET(parent)->window);
+    GdkRectangle rect;
+    gdk_screen_get_monitor_geometry(screen, monitor, &rect);
+
+    // Check the right bottom corner.
+    if (origin.x() > rect.x + rect.width - size.width())
+      origin.set_x(rect.x + rect.width - size.width());
+    if (origin.y() > rect.y + rect.height - size.height())
+      origin.set_y(rect.y + rect.height - size.height());
+
+    // Check the left top corner.
+    if (origin.x() < rect.x)
+      origin.set_x(rect.x);
+    if (origin.y() < rect.y)
+      origin.set_y(rect.y);
+  }
+
+  gtk_window_move(window, origin.x(), origin.y());
+
+  // Move to user expected desktop if window is already visible.
+  if (GTK_WIDGET(window)->window) {
+    ui::ChangeWindowDesktop(
+        ui::GetX11WindowFromGtkWidget(GTK_WIDGET(window)),
+        ui::GetX11WindowFromGtkWidget(GTK_WIDGET(parent)));
+  }
+}
+
+void MakeAppModalWindowGroup() {
+#if GTK_CHECK_VERSION(2, 14, 0)
+  // Older versions of GTK+ don't give us gtk_window_group_list() which is what
+  // we need to add current non-browser modal dialogs to the list. If
+  // we have 2.14+ we can do things the correct way.
+  GtkWindowGroup* window_group = gtk_window_group_new();
+  for (BrowserList::const_iterator it = BrowserList::begin();
+       it != BrowserList::end(); ++it) {
+    // List all windows in this current group
+    GtkWindowGroup* old_group =
+        gtk_window_get_group((*it)->window()->GetNativeHandle());
+
+    GList* all_windows = gtk_window_group_list_windows(old_group);
+    for (GList* window = all_windows; window; window = window->next) {
+      gtk_window_group_add_window(window_group, GTK_WINDOW(window->data));
+    }
+    g_list_free(all_windows);
+  }
+  g_object_unref(window_group);
+#else
+  // Otherwise just grab all browser windows and be slightly broken.
+  GtkWindowGroup* window_group = gtk_window_group_new();
+  for (BrowserList::const_iterator it = BrowserList::begin();
+       it != BrowserList::end(); ++it) {
+    gtk_window_group_add_window(window_group,
+                                (*it)->window()->GetNativeHandle());
+  }
+  g_object_unref(window_group);
+#endif
+}
+
+void AppModalDismissedUngroupWindows() {
+#if GTK_CHECK_VERSION(2, 14, 0)
+  if (BrowserList::begin() != BrowserList::end()) {
+    std::vector<GtkWindow*> transient_windows;
+
+    // All windows should be part of one big modal group right now.
+    GtkWindowGroup* window_group = gtk_window_get_group(
+        (*BrowserList::begin())->window()->GetNativeHandle());
+    GList* windows = gtk_window_group_list_windows(window_group);
+
+    for (GList* item = windows; item; item = item->next) {
+      GtkWindow* window = GTK_WINDOW(item->data);
+      GtkWindow* transient_for = gtk_window_get_transient_for(window);
+      if (transient_for) {
+        transient_windows.push_back(window);
+      } else {
+        GtkWindowGroup* window_group = gtk_window_group_new();
+        gtk_window_group_add_window(window_group, window);
+        g_object_unref(window_group);
+      }
+    }
+
+    // Put each transient window in the same group as its transient parent.
+    for (std::vector<GtkWindow*>::iterator it = transient_windows.begin();
+         it != transient_windows.end(); ++it) {
+      GtkWindow* transient_parent = gtk_window_get_transient_for(*it);
+      GtkWindowGroup* group = gtk_window_get_group(transient_parent);
+      gtk_window_group_add_window(group, *it);
+    }
+  }
+#else
+  // This is slightly broken in the case where a different window had a dialog,
+  // but its the best we can do since we don't have newer gtk stuff.
+  for (BrowserList::const_iterator it = BrowserList::begin();
+       it != BrowserList::end(); ++it) {
+    GtkWindowGroup* window_group = gtk_window_group_new();
+    gtk_window_group_add_window(window_group,
+                                (*it)->window()->GetNativeHandle());
+    g_object_unref(window_group);
+  }
+#endif
+}
+
+void RemoveAllChildren(GtkWidget* container) {
+  gtk_container_foreach(GTK_CONTAINER(container), RemoveWidget, container);
+}
+
+void ForceFontSizePixels(GtkWidget* widget, double size_pixels) {
+  GtkStyle* style = widget->style;
+  PangoFontDescription* font_desc = style->font_desc;
+  // pango_font_description_set_absolute_size sets the font size in device
+  // units, which for us is pixels.
+  pango_font_description_set_absolute_size(font_desc,
+                                           PANGO_SCALE * size_pixels);
+  gtk_widget_modify_font(widget, font_desc);
+}
+
+void UndoForceFontSize(GtkWidget* widget) {
+  gtk_widget_modify_font(widget, NULL);
+}
+
+gfx::Point GetWidgetScreenPosition(GtkWidget* widget) {
+  if (!widget->window) {
+    NOTREACHED() << "Must only be called on realized widgets.";
+    return gfx::Point(0, 0);
+  }
+
+  gint x, y;
+  gdk_window_get_origin(widget->window, &x, &y);
+
+  if (GTK_WIDGET_NO_WINDOW(widget)) {
+    x += widget->allocation.x;
+    y += widget->allocation.y;
+  }
+
+  return gfx::Point(x, y);
+}
+
+gfx::Rect GetWidgetScreenBounds(GtkWidget* widget) {
+  gfx::Point position = GetWidgetScreenPosition(widget);
+  return gfx::Rect(position.x(), position.y(),
+                   widget->allocation.width, widget->allocation.height);
+}
+
+gfx::Size GetWidgetSize(GtkWidget* widget) {
+  GtkRequisition size;
+  gtk_widget_size_request(widget, &size);
+  return gfx::Size(size.width, size.height);
+}
+
+void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p) {
+  DCHECK(widget);
+  DCHECK(p);
+
+  gfx::Point position = GetWidgetScreenPosition(widget);
+  p->SetPoint(p->x() + position.x(), p->y() + position.y());
+}
+
+void InitRCStyles() {
+  static const char kRCText[] =
+      // Make our dialogs styled like the GNOME HIG.
+      //
+      // TODO(evanm): content-area-spacing was introduced in a later
+      // version of GTK, so we need to set that manually on all dialogs.
+      // Perhaps it would make sense to have a shared FixupDialog() function.
+      "style \"gnome-dialog\" {\n"
+      "  xthickness = 12\n"
+      "  GtkDialog::action-area-border = 0\n"
+      "  GtkDialog::button-spacing = 6\n"
+      "  GtkDialog::content-area-spacing = 18\n"
+      "  GtkDialog::content-area-border = 12\n"
+      "}\n"
+      // Note we set it at the "application" priority, so users can override.
+      "widget \"GtkDialog\" style : application \"gnome-dialog\"\n"
+
+      // Make our about dialog special, so the image is flush with the edge.
+      "style \"about-dialog\" {\n"
+      "  GtkDialog::action-area-border = 12\n"
+      "  GtkDialog::button-spacing = 6\n"
+      "  GtkDialog::content-area-spacing = 18\n"
+      "  GtkDialog::content-area-border = 0\n"
+      "}\n"
+      "widget \"about-dialog\" style : application \"about-dialog\"\n";
+
+  gtk_rc_parse_string(kRCText);
+}
+
+GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
+                              bool pack_at_end, int padding) {
+  GtkWidget* centering_vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(centering_vbox), widget, TRUE, FALSE, 0);
+  if (pack_at_end)
+    gtk_box_pack_end(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
+  else
+    gtk_box_pack_start(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
+
+  return centering_vbox;
+}
+
+bool IsScreenComposited() {
+  GdkScreen* screen = gdk_screen_get_default();
+  return gdk_screen_is_composited(screen) == TRUE;
+}
+
+void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
+  std::vector<XID> stack;
+  if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
+    // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
+    // to old school enumeration of all X windows.  Some WMs parent 'top-level'
+    // windows in unnamed actual top-level windows (ion WM), so extend the
+    // search depth to all children of top-level windows.
+    const int kMaxSearchDepth = 1;
+    ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
+    return;
+  }
+
+  std::vector<XID>::iterator iter;
+  for (iter = stack.begin(); iter != stack.end(); iter++) {
+    if (delegate->ShouldStopIterating(*iter))
+      return;
+  }
+}
+
+void SetButtonClickableByMouseButtons(GtkWidget* button,
+                                      bool left, bool middle, bool right) {
+  gint button_mask = 0;
+  if (left)
+    button_mask |= 1 << 1;
+  if (middle)
+    button_mask |= 1 << 2;
+  if (right)
+    button_mask |= 1 << 3;
+  void* userdata = GINT_TO_POINTER(button_mask);
+
+  g_signal_connect(button, "button-press-event",
+                   G_CALLBACK(OnMouseButtonPressed), userdata);
+  g_signal_connect(button, "button-release-event",
+                   G_CALLBACK(OnMouseButtonReleased), userdata);
+}
+
+void SetButtonTriggersNavigation(GtkWidget* button) {
+  SetButtonClickableByMouseButtons(button, true, true, false);
+}
+
+int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds) {
+  if (!base::i18n::IsRTL())
+    return bounds.x();
+  return widget->allocation.width - bounds.x() - bounds.width();
+}
+
+int MirroredXCoordinate(GtkWidget* widget, int x) {
+  if (base::i18n::IsRTL())
+    return widget->allocation.width - x;
+  return x;
+}
+
+bool WidgetContainsCursor(GtkWidget* widget) {
+  gint x = 0;
+  gint y = 0;
+  gtk_widget_get_pointer(widget, &x, &y);
+  return WidgetBounds(widget).Contains(x, y);
+}
+
+void SetWindowIcon(GtkWindow* window) {
+  GList* icon_list = GetIconList();
+  gtk_window_set_icon_list(window, icon_list);
+  g_list_free(icon_list);
+}
+
+void SetDefaultWindowIcon() {
+  GList* icon_list = GetIconList();
+  gtk_window_set_default_icon_list(icon_list);
+  g_list_free(icon_list);
+}
+
+GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
+                             const gchar* stock_id, gint response_id) {
+  GtkWidget* button = gtk_button_new_with_label(text);
+  gtk_button_set_image(GTK_BUTTON(button),
+                       gtk_image_new_from_stock(stock_id,
+                                                GTK_ICON_SIZE_BUTTON));
+  gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button,
+                               response_id);
+  return button;
+}
+
+GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
+                             const gchar* stock_id) {
+  GtkWidget* button = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(ids_id)).c_str());
+  gtk_button_set_image(GTK_BUTTON(button),
+                       gtk_image_new_from_stock(stock_id,
+                                                GTK_ICON_SIZE_BUTTON));
+  return button;
+}
+
+GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image) {
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+  return hbox;
+}
+
+void SetLabelColor(GtkWidget* label, const GdkColor* color) {
+  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, color);
+  gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, color);
+  gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, color);
+  gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, color);
+}
+
+GtkWidget* IndentWidget(GtkWidget* content) {
+  GtkWidget* content_alignment = gtk_alignment_new(0.0, 0.5, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment), 0, 0,
+                            gtk_util::kGroupIndent, 0);
+  gtk_container_add(GTK_CONTAINER(content_alignment), content);
+  return content_alignment;
+}
+
+void UpdateGtkFontSettings(RendererPreferences* prefs) {
+  DCHECK(prefs);
+
+  // From http://library.gnome.org/devel/gtk/unstable/GtkSettings.html, this is
+  // the default value for gtk-cursor-blink-time.
+  static const gint kGtkDefaultCursorBlinkTime = 1200;
+
+  gint cursor_blink_time = kGtkDefaultCursorBlinkTime;
+  gboolean cursor_blink = TRUE;
+  gint antialias = 0;
+  gint hinting = 0;
+  gchar* hint_style = NULL;
+  gchar* rgba_style = NULL;
+  g_object_get(gtk_settings_get_default(),
+               "gtk-cursor-blink-time", &cursor_blink_time,
+               "gtk-cursor-blink", &cursor_blink,
+               "gtk-xft-antialias", &antialias,
+               "gtk-xft-hinting", &hinting,
+               "gtk-xft-hintstyle", &hint_style,
+               "gtk-xft-rgba", &rgba_style,
+               NULL);
+
+  // Set some reasonable defaults.
+  prefs->should_antialias_text = true;
+  prefs->hinting = RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT;
+  prefs->subpixel_rendering =
+      RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT;
+
+  if (cursor_blink) {
+    // Dividing by 2*1000ms follows the WebKit GTK port and makes the blink
+    // frequency appear similar to the omnibox.  Without this the blink is too
+    // slow.
+    prefs->caret_blink_interval = cursor_blink_time / 2000.;
+  } else {
+    prefs->caret_blink_interval = 0;
+  }
+
+  // g_object_get() doesn't tell us whether the properties were present or not,
+  // but if they aren't (because gnome-settings-daemon isn't running), we'll get
+  // NULL values for the strings.
+  if (hint_style && rgba_style) {
+    prefs->should_antialias_text = antialias;
+
+    if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) {
+      prefs->hinting = RENDERER_PREFERENCES_HINTING_NONE;
+    } else if (strcmp(hint_style, "hintslight") == 0) {
+      prefs->hinting = RENDERER_PREFERENCES_HINTING_SLIGHT;
+    } else if (strcmp(hint_style, "hintmedium") == 0) {
+      prefs->hinting = RENDERER_PREFERENCES_HINTING_MEDIUM;
+    } else if (strcmp(hint_style, "hintfull") == 0) {
+      prefs->hinting = RENDERER_PREFERENCES_HINTING_FULL;
+    }
+
+    if (strcmp(rgba_style, "none") == 0) {
+      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE;
+    } else if (strcmp(rgba_style, "rgb") == 0) {
+      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB;
+    } else if (strcmp(rgba_style, "bgr") == 0) {
+      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR;
+    } else if (strcmp(rgba_style, "vrgb") == 0) {
+      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB;
+    } else if (strcmp(rgba_style, "vbgr") == 0) {
+      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR;
+    }
+  }
+
+  if (hint_style)
+    g_free(hint_style);
+  if (rgba_style)
+    g_free(rgba_style);
+}
+
+gfx::Point ScreenPoint(GtkWidget* widget) {
+  int x, y;
+  gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y,
+                          NULL);
+  return gfx::Point(x, y);
+}
+
+gfx::Point ClientPoint(GtkWidget* widget) {
+  int x, y;
+  gtk_widget_get_pointer(widget, &x, &y);
+  return gfx::Point(x, y);
+}
+
+GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) {
+  GdkPoint point = {ltr ? x : width - x, y};
+  return point;
+}
+
+void DrawTextEntryBackground(GtkWidget* offscreen_entry,
+                             GtkWidget* widget_to_draw_on,
+                             GdkRectangle* dirty_rec,
+                             GdkRectangle* rec) {
+  GtkStyle* gtk_owned_style = gtk_rc_get_style(offscreen_entry);
+  // GTK owns the above and we're going to have to make our own copy of it
+  // that we can edit.
+  GtkStyle* our_style = gtk_style_copy(gtk_owned_style);
+  our_style = gtk_style_attach(our_style, widget_to_draw_on->window);
+
+  // TODO(erg): Draw the focus ring if appropriate...
+
+  // We're using GTK rendering; draw a GTK entry widget onto the background.
+  gtk_paint_shadow(our_style, widget_to_draw_on->window,
+                   GTK_STATE_NORMAL, GTK_SHADOW_IN, dirty_rec,
+                   widget_to_draw_on, "entry",
+                   rec->x, rec->y, rec->width, rec->height);
+
+  // Draw the interior background (not all themes draw the entry background
+  // above; this is a noop on themes that do).
+  gint xborder = our_style->xthickness;
+  gint yborder = our_style->ythickness;
+  gint width = rec->width - 2 * xborder;
+  gint height = rec->height - 2 * yborder;
+  if (width > 0 && height > 0) {
+    gtk_paint_flat_box(our_style, widget_to_draw_on->window,
+                       GTK_STATE_NORMAL, GTK_SHADOW_NONE, dirty_rec,
+                       widget_to_draw_on, "entry_bg",
+                       rec->x + xborder, rec->y + yborder,
+                       width, height);
+  }
+
+  gtk_style_detach(our_style);
+  g_object_unref(our_style);
+}
+
+void DrawThemedToolbarBackground(GtkWidget* widget,
+                                 cairo_t* cr,
+                                 GdkEventExpose* event,
+                                 const gfx::Point& tabstrip_origin,
+                                 GtkThemeProvider* theme_provider) {
+  // Fill the entire region with the toolbar color.
+  GdkColor color = theme_provider->GetGdkColor(
+      BrowserThemeProvider::COLOR_TOOLBAR);
+  gdk_cairo_set_source_color(cr, &color);
+  cairo_fill(cr);
+
+  // The toolbar is supposed to blend in with the active tab, so we have to pass
+  // coordinates for the IDR_THEME_TOOLBAR bitmap relative to the top of the
+  // tab strip.
+  CairoCachedSurface* background = theme_provider->GetSurfaceNamed(
+      IDR_THEME_TOOLBAR, widget);
+  background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
+  // We tile the toolbar background in both directions.
+  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+  cairo_rectangle(cr,
+                  tabstrip_origin.x(),
+                  tabstrip_origin.y(),
+                  event->area.x + event->area.width - tabstrip_origin.x(),
+                  event->area.y + event->area.height - tabstrip_origin.y());
+  cairo_fill(cr);
+}
+
+GdkColor AverageColors(GdkColor color_one, GdkColor color_two) {
+  GdkColor average_color;
+  average_color.pixel = 0;
+  average_color.red = (color_one.red + color_two.red) / 2;
+  average_color.green = (color_one.green + color_two.green) / 2;
+  average_color.blue = (color_one.blue + color_two.blue) / 2;
+  return average_color;
+}
+
+void SetAlwaysShowImage(GtkWidget* image_menu_item) {
+  // Compile time check: if it's available, just use the API.
+  // GTK_CHECK_VERSION is TRUE if the passed version is compatible.
+#if GTK_CHECK_VERSION(2, 16, 1)
+  gtk_image_menu_item_set_always_show_image(
+      GTK_IMAGE_MENU_ITEM(image_menu_item), TRUE);
+#else
+  // Run time check: if the API is not available, set the property manually.
+  // This will still only work with GTK 2.16+ as the property doesn't exist
+  // in earlier versions.
+  // gtk_check_version() returns NULL if the passed version is compatible.
+  if (!gtk_check_version(2, 16, 1)) {
+    GValue true_value = { 0 };
+    g_value_init(&true_value, G_TYPE_BOOLEAN);
+    g_value_set_boolean(&true_value, TRUE);
+    g_object_set_property(G_OBJECT(image_menu_item), "always-show-image",
+                          &true_value);
+  }
+#endif
+}
+
+void StackPopupWindow(GtkWidget* popup, GtkWidget* toplevel) {
+  DCHECK(GTK_IS_WINDOW(popup) && GTK_WIDGET_TOPLEVEL(popup) &&
+         GTK_WIDGET_REALIZED(popup));
+  DCHECK(GTK_IS_WINDOW(toplevel) && GTK_WIDGET_TOPLEVEL(toplevel) &&
+         GTK_WIDGET_REALIZED(toplevel));
+
+  // Stack the |popup| window directly above the |toplevel| window.
+  // The popup window is a direct child of the root window, so we need to
+  // find a similar ancestor for the toplevel window (which might have been
+  // reparented by a window manager).  We grab the server while we're doing
+  // this -- otherwise, we'll get an error if the window manager reparents the
+  // toplevel window right after we call GetHighestAncestorWindow().
+  gdk_x11_display_grab(gtk_widget_get_display(toplevel));
+  XID toplevel_window_base = ui::GetHighestAncestorWindow(
+      ui::GetX11WindowFromGtkWidget(toplevel),
+      ui::GetX11RootWindow());
+  if (toplevel_window_base) {
+    XID window_xid = ui::GetX11WindowFromGtkWidget(popup);
+    XID window_parent = ui::GetParentWindow(window_xid);
+    if (window_parent == ui::GetX11RootWindow()) {
+      ui::RestackWindow(window_xid, toplevel_window_base, true);
+    } else {
+      // The window manager shouldn't reparent override-redirect windows.
+      DLOG(ERROR) << "override-redirect window " << window_xid
+                  << "'s parent is " << window_parent
+                  << ", rather than root window "
+                  << ui::GetX11RootWindow();
+    }
+  }
+  gdk_x11_display_ungrab(gtk_widget_get_display(toplevel));
+}
+
+gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget) {
+  DCHECK(GTK_WIDGET_REALIZED(widget));
+
+  GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
+  DCHECK(toplevel);
+  DCHECK(GTK_WIDGET_REALIZED(toplevel));
+
+  gint x = 0, y = 0;
+  gtk_widget_translate_coordinates(widget,
+                                   toplevel,
+                                   0, 0,
+                                   &x, &y);
+  return gfx::Rect(x, y, widget->allocation.width, widget->allocation.height);
+}
+
+void SuppressDefaultPainting(GtkWidget* container) {
+  g_signal_connect(container, "expose-event",
+                   G_CALLBACK(PaintNoBackground), NULL);
+}
+
+WindowOpenDisposition DispositionForCurrentButtonPressEvent() {
+  GdkEvent* event = gtk_get_current_event();
+  if (!event) {
+    NOTREACHED();
+    return NEW_FOREGROUND_TAB;
+  }
+
+  guint state = event->button.state;
+  gdk_event_free(event);
+  return event_utils::DispositionFromEventFlags(state);
+}
+
+bool GrabAllInput(GtkWidget* widget) {
+  guint time = gtk_get_current_event_time();
+
+  if (!GTK_WIDGET_VISIBLE(widget))
+    return false;
+
+  if (!gdk_pointer_grab(widget->window, TRUE,
+                        GdkEventMask(GDK_BUTTON_PRESS_MASK |
+                                     GDK_BUTTON_RELEASE_MASK |
+                                     GDK_ENTER_NOTIFY_MASK |
+                                     GDK_LEAVE_NOTIFY_MASK |
+                                     GDK_POINTER_MOTION_MASK),
+                        NULL, NULL, time) == 0) {
+    return false;
+  }
+
+  if (!gdk_keyboard_grab(widget->window, TRUE, time) == 0) {
+    gdk_display_pointer_ungrab(gdk_drawable_get_display(widget->window), time);
+    return false;
+  }
+
+  gtk_grab_add(widget);
+  return true;
+}
+
+gfx::Rect WidgetBounds(GtkWidget* widget) {
+  // To quote the gtk docs:
+  //
+  //   Widget coordinates are a bit odd; for historical reasons, they are
+  //   defined as widget->window coordinates for widgets that are not
+  //   GTK_NO_WINDOW widgets, and are relative to widget->allocation.x,
+  //   widget->allocation.y for widgets that are GTK_NO_WINDOW widgets.
+  //
+  // So the base is always (0,0).
+  return gfx::Rect(0, 0, widget->allocation.width, widget->allocation.height);
+}
+
+void SetWMLastUserActionTime(GtkWindow* window) {
+  gdk_x11_window_set_user_time(GTK_WIDGET(window)->window, XTimeNow());
+}
+
+guint32 XTimeNow() {
+  struct timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+bool URLFromPrimarySelection(Profile* profile, GURL* url) {
+  GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
+  DCHECK(clipboard);
+  gchar* selection_text = gtk_clipboard_wait_for_text(clipboard);
+  if (!selection_text)
+    return false;
+
+  // Use autocomplete to clean up the text, going so far as to turn it into
+  // a search query if necessary.
+  AutocompleteMatch match;
+  profile->GetAutocompleteClassifier()->Classify(UTF8ToUTF16(selection_text),
+      string16(), false, &match, NULL);
+  g_free(selection_text);
+  if (!match.destination_url.is_valid())
+    return false;
+
+  *url = match.destination_url;
+  return true;
+}
+
+bool AddWindowAlphaChannel(GtkWidget* window) {
+  GdkScreen* screen = gtk_widget_get_screen(window);
+  GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen);
+  if (rgba)
+    gtk_widget_set_colormap(window, rgba);
+
+  return rgba;
+}
+
+void GetTextColors(GdkColor* normal_base,
+                   GdkColor* selected_base,
+                   GdkColor* normal_text,
+                   GdkColor* selected_text) {
+  GtkWidget* fake_entry = gtk_entry_new();
+  GtkStyle* style = gtk_rc_get_style(fake_entry);
+
+  if (normal_base)
+    *normal_base = style->base[GTK_STATE_NORMAL];
+  if (selected_base)
+    *selected_base = style->base[GTK_STATE_SELECTED];
+  if (normal_text)
+    *normal_text = style->text[GTK_STATE_NORMAL];
+  if (selected_text)
+    *selected_text = style->text[GTK_STATE_SELECTED];
+
+  g_object_ref_sink(fake_entry);
+  g_object_unref(fake_entry);
+}
+
+#if defined(OS_CHROMEOS)
+
+GtkWindow* GetLastActiveBrowserWindow() {
+  if (Browser* b = BrowserList::GetLastActive()) {
+    if (b->type() != Browser::TYPE_NORMAL) {
+      b = BrowserList::FindBrowserWithType(b->profile(),
+                                           Browser::TYPE_NORMAL,
+                                           true);
+    }
+
+    if (b)
+      return GTK_WINDOW(b->window()->GetNativeHandle());
+  }
+
+  return NULL;
+}
+
+GtkWindow* GetDialogTransientParent(GtkWindow* dialog) {
+  GtkWindow* parent = gtk_window_get_transient_for(dialog);
+  if (!parent)
+    parent = GetLastActiveBrowserWindow();
+
+  return parent;
+}
+
+void ShowDialog(GtkWidget* dialog) {
+  // Make sure all controls are visible so that we get correct size.
+  gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
+
+  // Get dialog window size.
+  gint width = 0;
+  gint height = 0;
+  gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
+
+  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
+      dialog,
+      gtk_window_get_resizable(GTK_WINDOW(dialog)) ?
+          chromeos::DIALOG_FLAG_RESIZEABLE :
+          chromeos::DIALOG_FLAG_DEFAULT,
+      gfx::Size(width, height),
+      gfx::Size());
+}
+
+void ShowDialogWithLocalizedSize(GtkWidget* dialog,
+                                 int width_id,
+                                 int height_id,
+                                 bool resizeable) {
+  int width = (width_id == -1) ? 0 :
+      views::Window::GetLocalizedContentsWidth(width_id);
+  int height = (height_id == -1) ? 0 :
+      views::Window::GetLocalizedContentsHeight(height_id);
+
+  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
+      dialog,
+      resizeable ? chromeos::DIALOG_FLAG_RESIZEABLE :
+                   chromeos::DIALOG_FLAG_DEFAULT,
+      gfx::Size(width, height),
+      gfx::Size());
+}
+
+void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
+                                          int width_id) {
+  int width = (width_id == -1) ? 0 :
+      views::Window::GetLocalizedContentsWidth(width_id);
+
+  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
+      dialog,
+      chromeos::DIALOG_FLAG_MODAL,
+      gfx::Size(),
+      gfx::Size(width, 0));
+}
+
+void PresentWindow(GtkWidget* window, int timestamp) {
+  GtkWindow* host_window = chromeos::GetNativeDialogWindow(window);
+  if (!host_window)
+      host_window = GTK_WINDOW(window);
+  if (timestamp)
+    gtk_window_present_with_time(host_window, timestamp);
+  else
+    gtk_window_present(host_window);
+}
+
+GtkWindow* GetDialogWindow(GtkWidget* dialog) {
+  return chromeos::GetNativeDialogWindow(dialog);
+}
+
+gfx::Rect GetDialogBounds(GtkWidget* dialog) {
+  return chromeos::GetNativeDialogContentsBounds(dialog);
+}
+
+#else
+
+void ShowDialog(GtkWidget* dialog) {
+  gtk_widget_show_all(dialog);
+}
+
+void ShowDialogWithLocalizedSize(GtkWidget* dialog,
+                                 int width_id,
+                                 int height_id,
+                                 bool resizeable) {
+  gtk_widget_realize(dialog);
+  SetWindowSizeFromResources(GTK_WINDOW(dialog),
+                             width_id,
+                             height_id,
+                             resizeable);
+  gtk_widget_show_all(dialog);
+}
+
+void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
+                                          int width_id) {
+  gtk_widget_show_all(dialog);
+
+  // Suggest a minimum size.
+  gint width;
+  GtkRequisition req;
+  gtk_widget_size_request(dialog, &req);
+  gtk_util::GetWidgetSizeFromResources(dialog, width_id, 0, &width, NULL);
+  if (width > req.width)
+    gtk_widget_set_size_request(dialog, width, -1);
+}
+
+void PresentWindow(GtkWidget* window, int timestamp) {
+  if (timestamp)
+    gtk_window_present_with_time(GTK_WINDOW(window), timestamp);
+  else
+    gtk_window_present(GTK_WINDOW(window));
+}
+
+GtkWindow* GetDialogWindow(GtkWidget* dialog) {
+  return GTK_WINDOW(dialog);
+}
+
+gfx::Rect GetDialogBounds(GtkWidget* dialog) {
+  gint x = 0, y = 0, width = 1, height = 1;
+  gtk_window_get_position(GTK_WINDOW(dialog), &x, &y);
+  gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
+
+  return gfx::Rect(x, y, width, height);
+}
+
+#endif
+
+string16 GetStockPreferencesMenuLabel() {
+  GtkStockItem stock_item;
+  string16 preferences;
+  if (gtk_stock_lookup(GTK_STOCK_PREFERENCES, &stock_item)) {
+    const char16 kUnderscore[] = { '_', 0 };
+    RemoveChars(UTF8ToUTF16(stock_item.label), kUnderscore, &preferences);
+  }
+  return preferences;
+}
+
+bool IsWidgetAncestryVisible(GtkWidget* widget) {
+  GtkWidget* parent = widget;
+  while (parent && GTK_WIDGET_VISIBLE(parent))
+    parent = parent->parent;
+  return !parent;
+}
+
+void SetGtkFont(const std::string& font_name) {
+  g_object_set(gtk_settings_get_default(),
+               "gtk-font-name", font_name.c_str(), NULL);
+}
+
+void SetLabelWidth(GtkWidget* label, int pixel_width) {
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+  // Do the simple thing in LTR because the bug only affects right-aligned
+  // text. Also, when using the workaround, the label tries to maintain
+  // uniform line-length, which we don't really want.
+  if (gtk_widget_get_direction(label) == GTK_TEXT_DIR_LTR) {
+    gtk_widget_set_size_request(label, pixel_width, -1);
+  } else {
+    // The label has to be realized before we can adjust its width.
+    if (GTK_WIDGET_REALIZED(label)) {
+      OnLabelRealize(label, GINT_TO_POINTER(pixel_width));
+    } else {
+      g_signal_connect(label, "realize", G_CALLBACK(OnLabelRealize),
+                       GINT_TO_POINTER(pixel_width));
+    }
+  }
+}
+
+void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label) {
+  GtkRequisition size;
+  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
+  gtk_widget_set_size_request(label, -1, -1);
+  gtk_widget_size_request(label, &size);
+  gtk_widget_set_size_request(label, size.width, size.height);
+  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
+}
+
+GdkDragAction WebDragOpToGdkDragAction(WebDragOperationsMask op) {
+  GdkDragAction action = static_cast<GdkDragAction>(0);
+  if (op & WebDragOperationCopy)
+    action = static_cast<GdkDragAction>(action | GDK_ACTION_COPY);
+  if (op & WebDragOperationLink)
+    action = static_cast<GdkDragAction>(action | GDK_ACTION_LINK);
+  if (op & WebDragOperationMove)
+    action = static_cast<GdkDragAction>(action | GDK_ACTION_MOVE);
+  return action;
+}
+
+WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action) {
+  WebDragOperationsMask op = WebDragOperationNone;
+  if (action & GDK_ACTION_COPY)
+    op = static_cast<WebDragOperationsMask>(op | WebDragOperationCopy);
+  if (action & GDK_ACTION_LINK)
+    op = static_cast<WebDragOperationsMask>(op | WebDragOperationLink);
+  if (action & GDK_ACTION_MOVE)
+    op = static_cast<WebDragOperationsMask>(op | WebDragOperationMove);
+  return op;
+}
+
+void ApplyMessageDialogQuirks(GtkWidget* dialog) {
+  if (gtk_window_get_modal(GTK_WINDOW(dialog))) {
+    // Work around a KDE 3 window manager bug.
+    scoped_ptr<base::Environment> env(base::Environment::Create());
+    if (base::nix::DESKTOP_ENVIRONMENT_KDE3 ==
+        base::nix::GetDesktopEnvironment(env.get()))
+      gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
+  }
+}
+
+// Performs Cut/Copy/Paste operation on the |window|.
+// If the current render view is focused, then just call the specified |method|
+// against the current render view host, otherwise emit the specified |signal|
+// against the focused widget.
+// TODO(suzhe): This approach does not work for plugins.
+void DoCutCopyPaste(BrowserWindow* window,
+                    void (RenderViewHost::*method)(),
+                    const char* signal) {
+  GtkWidget* widget = GetBrowserWindowFocusedWidget(window);
+  if (widget == NULL)
+    return;  // Do nothing if no focused widget.
+
+  TabContents* current_tab = GetBrowserWindowSelectedTabContents(window);
+  if (current_tab && widget == current_tab->GetContentNativeView()) {
+    (current_tab->render_view_host()->*method)();
+  } else {
+    guint id;
+    if ((id = g_signal_lookup(signal, G_OBJECT_TYPE(widget))) != 0)
+      g_signal_emit(widget, id, 0);
+  }
+}
+
+void DoCut(BrowserWindow* window) {
+  DoCutCopyPaste(window, &RenderViewHost::Cut, "cut-clipboard");
+}
+
+void DoCopy(BrowserWindow* window) {
+  DoCutCopyPaste(window, &RenderViewHost::Copy, "copy-clipboard");
+}
+
+void DoPaste(BrowserWindow* window) {
+  DoCutCopyPaste(window, &RenderViewHost::Paste, "paste-clipboard");
+}
+
+}  // namespace gtk_util
diff --git a/chrome/browser/ui/gtk/gtk_util.h b/chrome/browser/ui/gtk/gtk_util.h
new file mode 100644
index 0000000..d88ecdc
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_util.h
@@ -0,0 +1,380 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
+#define CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <string>
+#include <vector>
+
+#include "base/string16.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "webkit/glue/window_open_disposition.h"
+
+typedef struct _cairo cairo_t;
+typedef struct _GdkColor GdkColor;
+typedef struct _GtkWidget GtkWidget;
+
+class BrowserWindow;
+class GtkThemeProvider;
+class GURL;
+class Profile;
+struct RendererPreferences;  // from common/renderer_preferences.h
+
+const int kSkiaToGDKMultiplier = 257;
+
+// Define a macro for creating GdkColors from RGB values.  This is a macro to
+// allow static construction of literals, etc.  Use this like:
+//   GdkColor white = GDK_COLOR_RGB(0xff, 0xff, 0xff);
+#define GDK_COLOR_RGB(r, g, b) {0, r * kSkiaToGDKMultiplier, \
+        g * kSkiaToGDKMultiplier, b * kSkiaToGDKMultiplier}
+
+namespace event_utils {
+
+// Translates event flags into what kind of disposition they represent.
+// For example, a middle click would mean to open a background tab.
+// event_flags are the state in the GdkEvent structure.
+WindowOpenDisposition DispositionFromEventFlags(guint state);
+
+}  // namespace event_utils
+
+namespace gtk_util {
+
+extern const GdkColor kGdkWhite;
+extern const GdkColor kGdkGray;
+extern const GdkColor kGdkBlack;
+extern const GdkColor kGdkGreen;
+
+// Constants relating to the layout of dialog windows:
+// (See http://library.gnome.org/devel/hig-book/stable/design-window.html.en)
+
+// Spacing between controls of the same group.
+const int kControlSpacing = 6;
+
+// Horizontal spacing between a label and its control.
+const int kLabelSpacing = 12;
+
+// Indent of the controls within each group.
+const int kGroupIndent = 12;
+
+// Space around the outside of a dialog's contents.
+const int kContentAreaBorder = 12;
+
+// Spacing between groups of controls.
+const int kContentAreaSpacing = 18;
+
+// Horizontal Spacing between controls in a form.
+const int kFormControlSpacing = 10;
+
+// Create a table of labeled controls, using proper spacing and alignment.
+// Arguments should be pairs of const char*, GtkWidget*, concluding with a
+// NULL.  The first argument is a vector in which to place all labels
+// produced. It can be NULL if you don't need to keep track of the label
+// widgets. The second argument is a color to force the label text to. It can
+// be NULL to get the system default.
+//
+// For example:
+// controls = CreateLabeledControlsGroup(NULL,
+//                                       "Name:", title_entry_,
+//                                       "Folder:", folder_combobox_,
+//                                       NULL);
+GtkWidget* CreateLabeledControlsGroup(
+    std::vector<GtkWidget*>* labels,
+    const char* text, ...);
+
+// Create a GtkBin with |child| as its child widget.  This bin will paint a
+// border of color |color| with the sizes specified in pixels.
+GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
+                              int top, int bottom, int left, int right);
+
+// Left-align the given GtkMisc and return the same pointer.
+GtkWidget* LeftAlignMisc(GtkWidget* misc);
+
+// Create a left-aligned label with the given text in bold.
+GtkWidget* CreateBoldLabel(const std::string& text);
+
+// As above, but uses number of characters/lines directly rather than looking up
+// a resource.
+void GetWidgetSizeFromCharacters(GtkWidget* widget,
+                                 double width_chars, double height_lines,
+                                 int* width, int* height);
+
+// Calculates the size of given widget based on the size specified in number of
+// characters/lines (in locale specific resource file) and font metrics.
+// NOTE: Make sure to realize |widget| before using this method, or a default
+// font size will be used instead of the actual font size.
+void GetWidgetSizeFromResources(GtkWidget* widget,
+                                int width_chars, int height_lines,
+                                int* width, int* height);
+
+// As above, but a convenience method for configuring dialog size.
+// |width_id| and |height_id| are resource IDs for the size.  If either of these
+// are set to -1, the respective size will be set to the widget default.
+// |resizable| also controls whether the dialog will be resizable
+// (this info is also necessary for getting the width-setting code
+// right).
+void SetWindowSizeFromResources(GtkWindow* window,
+                                int width_id, int height_id, bool resizable);
+
+// Places |window| approximately over center of |parent|, it also moves window
+// to parent's desktop. Use this only for non-modal dialogs, such as the
+// options window and content settings window; otherwise you should be using
+// transient_for.
+void CenterOverWindow(GtkWindow* window, GtkWindow* parent);
+
+// Puts all browser windows in one window group; this will make any dialog
+// spawned app modal.
+void MakeAppModalWindowGroup();
+
+// Called after an app modal dialog that used MakeAppModalWindowGroup() was
+// dismissed. Returns each browser window to its own window group.
+void AppModalDismissedUngroupWindows();
+
+// Remove all children from this container.
+void RemoveAllChildren(GtkWidget* container);
+
+// Force the font size of the widget to |size_pixels|.
+void ForceFontSizePixels(GtkWidget* widget, double size_pixels);
+
+// Undoes the effects of a previous ForceFontSizePixels() call. Safe to call
+// even if ForceFontSizePixels() was never called.
+void UndoForceFontSize(GtkWidget* widget);
+
+// Gets the position of a gtk widget in screen coordinates.
+gfx::Point GetWidgetScreenPosition(GtkWidget* widget);
+
+// Returns the bounds of the specified widget in screen coordinates.
+gfx::Rect GetWidgetScreenBounds(GtkWidget* widget);
+
+// Retuns size of the |widget| without window manager decorations.
+gfx::Size GetWidgetSize(GtkWidget* widget);
+
+// Converts a point in a widget to screen coordinates.  The point |p| is
+// relative to the widget's top-left origin.
+void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p);
+
+// Initialize some GTK settings so that our dialogs are consistent.
+void InitRCStyles();
+
+// Stick the widget in the given hbox without expanding vertically. The widget
+// is packed at the start of the hbox. This is useful for widgets that would
+// otherwise expand to fill the vertical space of the hbox
+// (e.g. buttons). Returns the vbox that widget was packed in.
+GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
+                              bool pack_at_end, int padding);
+
+// Returns true if the screen is composited, false otherwise.
+bool IsScreenComposited();
+
+// Enumerates the top-level gdk windows of the current display.
+void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate);
+
+// Set that clicking the button with the given mouse buttons will cause a click
+// event.
+// NOTE: If you need to connect to the button-press-event or
+// button-release-event signals, do so before calling this function.
+void SetButtonClickableByMouseButtons(GtkWidget* button,
+                                      bool left, bool middle, bool right);
+
+// Set that a button causes a page navigation. In particular, it will accept
+// middle clicks. Warning: only call this *after* you have connected your
+// own handlers for button-press and button-release events, or you will not get
+// those events.
+void SetButtonTriggersNavigation(GtkWidget* button);
+
+// Returns the mirrored x value for |bounds| if the layout is RTL; otherwise,
+// the original value is returned unchanged.
+int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds);
+
+// Returns the mirrored x value for the point |x| if the layout is RTL;
+// otherwise, the original value is returned unchanged.
+int MirroredXCoordinate(GtkWidget* widget, int x);
+
+// Returns true if the pointer is currently inside the widget.
+bool WidgetContainsCursor(GtkWidget* widget);
+
+// Sets the icon of |window| to the product icon (potentially used in window
+// border or alt-tab list).
+void SetWindowIcon(GtkWindow* window);
+
+// Sets the default window icon for windows created in this app.
+void SetDefaultWindowIcon();
+
+// Adds an action button with the given text to the dialog. Only useful when you
+// want a stock icon but not the stock text to go with it. Returns the button.
+GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
+                             const gchar* stock_id, gint response_id);
+
+GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
+                             const gchar* stock_id);
+
+GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image);
+
+// Sets all the foreground color states of |label| to |color|.
+void SetLabelColor(GtkWidget* label, const GdkColor* color);
+
+// Adds the given widget to an alignment identing it by |kGroupIndent|.
+GtkWidget* IndentWidget(GtkWidget* content);
+
+// Sets (or resets) the font settings in |prefs| (used when creating new
+// renderers) based on GtkSettings (which itself comes from XSETTINGS).
+void UpdateGtkFontSettings(RendererPreferences* prefs);
+
+// Get the current location of the mouse cursor relative to the screen.
+gfx::Point ScreenPoint(GtkWidget* widget);
+
+// Get the current location of the mouse cursor relative to the widget.
+gfx::Point ClientPoint(GtkWidget* widget);
+
+// Reverses a point in RTL mode. Used in making vectors of GdkPoints for window
+// shapes.
+GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr);
+
+// Draws a GTK text entry with the style parameters of GtkEntry
+// |offscreen_entry| onto |widget_to_draw_on| in the rectangle |rec|. Drawing
+// is only done in the clip rectangle |dirty_rec|.
+void DrawTextEntryBackground(GtkWidget* offscreen_entry,
+                             GtkWidget* widget_to_draw_on,
+                             GdkRectangle* dirty_rec,
+                             GdkRectangle* rec);
+
+// Draws the background of the toolbar area subject to the expose rectangle
+// |event| and starting image tiling from |tabstrip_origin|.
+void DrawThemedToolbarBackground(GtkWidget* widget,
+                                 cairo_t* cr,
+                                 GdkEventExpose* event,
+                                 const gfx::Point& tabstrip_origin,
+                                 GtkThemeProvider* provider);
+
+// Returns the two colors averaged together.
+GdkColor AverageColors(GdkColor color_one, GdkColor color_two);
+
+// Show the image for the given menu item, even if the user's default is to not
+// show images. Only to be used for favicons or other menus where the image is
+// crucial to its functionality.
+void SetAlwaysShowImage(GtkWidget* image_menu_item);
+
+// Stacks a |popup| window directly on top of a |toplevel| window.
+void StackPopupWindow(GtkWidget* popup, GtkWidget* toplevel);
+
+// Get a rectangle corresponding to a widget's allocation relative to its
+// toplevel window's origin.
+gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget);
+
+// Don't allow the widget to paint anything, and instead propagate the expose
+// to its children. This is similar to calling
+//
+//   gtk_widget_set_app_paintable(container, TRUE);
+//
+// except that it will always work, and it should be called after any custom
+// expose events are connected.
+void SuppressDefaultPainting(GtkWidget* container);
+
+// Get the window open disposition from the state in gtk_get_current_event().
+// This is designed to be called inside a "clicked" event handler. It is an
+// error to call it when gtk_get_current_event() won't return a GdkEventButton*.
+WindowOpenDisposition DispositionForCurrentButtonPressEvent();
+
+// Safely grabs all input (with X grabs and an application grab), returning true
+// for success.
+bool GrabAllInput(GtkWidget* widget);
+
+// Returns a rectangle that represents the widget's bounds. The rectangle it
+// returns is the same as widget->allocation, but anchored at (0, 0).
+gfx::Rect WidgetBounds(GtkWidget* widget);
+
+// Update the timestamp for the given window. This is usually the time of the
+// last user event, but on rare occasions we wish to update it despite not
+// receiving a user event.
+void SetWMLastUserActionTime(GtkWindow* window);
+
+// The current system time, using the format expected by the X server, but not
+// retrieved from the X server. NOTE: You should almost never need to use this
+// function, instead using the timestamp from the latest GDK event.
+guint32 XTimeNow();
+
+// Uses the autocomplete controller for |profile| to convert the contents of the
+// PRIMARY selection to a parsed URL. Returns true and sets |url| on success,
+// otherwise returns false.
+bool URLFromPrimarySelection(Profile* profile, GURL* url);
+
+// Set the colormap of the given window to rgba to allow transparency.
+bool AddWindowAlphaChannel(GtkWidget* window);
+
+// Get the default colors for a text entry.  Parameters may be NULL.
+void GetTextColors(GdkColor* normal_base,
+                   GdkColor* selected_base,
+                   GdkColor* normal_text,
+                   GdkColor* selected_text);
+
+// Wrappers to show a GtkDialog. On Linux, it merely calls gtk_widget_show_all.
+// On ChromeOs, it calls ShowNativeDialog which hosts the its vbox
+// in a view based Window.
+void ShowDialog(GtkWidget* dialog);
+void ShowDialogWithLocalizedSize(GtkWidget* dialog,
+                                 int width_id,
+                                 int height_id,
+                                 bool resizeable);
+void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
+                                          int width_id);
+
+// Wrapper to present a window. On Linux, it just calls gtk_window_present or
+// gtk_window_present_with_time for non-zero timestamp. For ChromeOS, it first
+// finds the host window of the dialog contents and then present it.
+void PresentWindow(GtkWidget* window, int timestamp);
+
+// Get real window for given dialog. On ChromeOS, this gives the native dialog
+// host window. On Linux, it merely returns the passed in dialog.
+GtkWindow* GetDialogWindow(GtkWidget* dialog);
+
+// Gets dialog window bounds.
+gfx::Rect GetDialogBounds(GtkWidget* dialog);
+
+// Returns the stock menu item label for the "preferences" item - returns an
+// empty string if no stock item found.
+string16 GetStockPreferencesMenuLabel();
+
+// Checks whether a widget is actually visible, i.e. whether it and all its
+// ancestors up to its toplevel are visible.
+bool IsWidgetAncestryVisible(GtkWidget* widget);
+
+// Sets the GTK font from the given font name (ex. "Arial Black, 10").
+void SetGtkFont(const std::string& font_name);
+
+// Sets the given label's size request to |pixel_width|. This will cause the
+// label to wrap if it needs to. The reason for this function is that some
+// versions of GTK mis-align labels that have a size request and line wrapping,
+// and this function hides the complexity of the workaround.
+void SetLabelWidth(GtkWidget* label, int pixel_width);
+
+// Make the |label| shrinkable within a GthChromeShrinkableHBox
+// It calculates the real size request of a label and set its ellipsize mode to
+// PANGO_ELLIPSIZE_END.
+// It must be done when the label is mapped (become visible on the screen),
+// to make sure the pango can get correct font information for the calculation.
+void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label);
+
+// Convenience methods for converting between web drag operations and the GDK
+// equivalent.
+GdkDragAction WebDragOpToGdkDragAction(WebKit::WebDragOperationsMask op);
+WebKit::WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action);
+
+// A helper function for gtk_message_dialog_new() to work around a few KDE 3
+// window manager bugs. You should always call it after creating a dialog with
+// gtk_message_dialog_new.
+void ApplyMessageDialogQuirks(GtkWidget* dialog);
+
+// Performs Cut/Copy/Paste operation on the |window|.
+void DoCut(BrowserWindow* window);
+void DoCopy(BrowserWindow* window);
+void DoPaste(BrowserWindow* window);
+
+}  // namespace gtk_util
+
+#endif  // CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
diff --git a/chrome/browser/ui/gtk/hover_controller_gtk.cc b/chrome/browser/ui/gtk/hover_controller_gtk.cc
new file mode 100644
index 0000000..f110ad8
--- /dev/null
+++ b/chrome/browser/ui/gtk/hover_controller_gtk.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/hover_controller_gtk.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+
+static const gchar* kHoverControllerGtkKey = "__HOVER_CONTROLLER_GTK__";
+
+HoverControllerGtk::HoverControllerGtk(GtkWidget* button)
+    : throb_animation_(this),
+      hover_animation_(this),
+      button_(button) {
+  g_object_ref(button_);
+  gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0);
+
+  signals_.Connect(button_, "enter-notify-event",
+                   G_CALLBACK(OnEnterThunk), this);
+  signals_.Connect(button_, "leave-notify-event",
+                   G_CALLBACK(OnLeaveThunk), this);
+  signals_.Connect(button_, "destroy",
+                   G_CALLBACK(OnDestroyThunk), this);
+  signals_.Connect(button_, "hierarchy-changed",
+                   G_CALLBACK(OnHierarchyChangedThunk), this);
+
+#ifndef NDEBUG
+  if (g_object_get_data(G_OBJECT(button_), kHoverControllerGtkKey))
+    NOTREACHED();
+#endif  // !NDEBUG
+
+  g_object_set_data(G_OBJECT(button), kHoverControllerGtkKey, this);
+}
+
+HoverControllerGtk::~HoverControllerGtk() {
+}
+
+void HoverControllerGtk::StartThrobbing(int cycles) {
+  throb_animation_.StartThrobbing(cycles);
+}
+
+// static
+GtkWidget* HoverControllerGtk::CreateChromeButton() {
+  GtkWidget* widget = gtk_chrome_button_new();
+  new HoverControllerGtk(widget);
+  return widget;
+}
+
+// static
+HoverControllerGtk* HoverControllerGtk::GetHoverControllerGtk(
+    GtkWidget* button) {
+  return reinterpret_cast<HoverControllerGtk*>(
+      g_object_get_data(G_OBJECT(button), kHoverControllerGtkKey));
+}
+
+void HoverControllerGtk::Destroy() {
+  gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), -1.0);
+
+  g_object_set_data(G_OBJECT(button_), kHoverControllerGtkKey, NULL);
+  g_object_unref(button_);
+  button_ = NULL;
+
+  delete this;
+}
+
+void HoverControllerGtk::AnimationProgressed(const ui::Animation* animation) {
+  if (!button_)
+    return;
+
+  // Ignore the hover animation if we are throbbing.
+  if (animation == &hover_animation_ && throb_animation_.is_animating())
+    return;
+
+  gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_),
+                                    animation->GetCurrentValue());
+}
+
+void HoverControllerGtk::AnimationEnded(const ui::Animation* animation) {
+  if (!button_)
+    return;
+  if (animation != &throb_animation_)
+    return;
+
+  if (throb_animation_.cycles_remaining() <= 1)
+    gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0);
+}
+
+void HoverControllerGtk::AnimationCanceled(const ui::Animation* animation) {
+  AnimationEnded(animation);
+}
+
+gboolean HoverControllerGtk::OnEnter(GtkWidget* widget,
+                                     GdkEventCrossing* event) {
+  hover_animation_.Show();
+
+  return FALSE;
+}
+
+gboolean HoverControllerGtk::OnLeave(GtkWidget* widget,
+                                     GdkEventCrossing* event) {
+  // When the user is holding a mouse button, we don't want to animate.
+  if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) {
+    hover_animation_.Reset();
+    gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0);
+  } else {
+    hover_animation_.Hide();
+  }
+
+  return FALSE;
+}
+
+void HoverControllerGtk::OnHierarchyChanged(GtkWidget* widget,
+                                            GtkWidget* previous_toplevel) {
+  // GTK+ does not emit leave-notify-event signals when a widget
+  // becomes unanchored, so manually unset the hover states.
+  if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget))) {
+    gtk_widget_set_state(button_, GTK_STATE_NORMAL);
+    hover_animation_.Reset();
+    gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0.0);
+  }
+}
+
+void HoverControllerGtk::OnDestroy(GtkWidget* widget) {
+  Destroy();
+}
diff --git a/chrome/browser/ui/gtk/hover_controller_gtk.h b/chrome/browser/ui/gtk/hover_controller_gtk.h
new file mode 100644
index 0000000..ae133b7
--- /dev/null
+++ b/chrome/browser/ui/gtk/hover_controller_gtk.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_HOVER_CONTROLLER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_HOVER_CONTROLLER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/animation/throb_animation.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+
+// This class handles the "throbbing" of a GtkChromeButton. The visual effect
+// of throbbing is created by painting partially transparent hover effects. It
+// only works in non-gtk theme mode. This class mainly exists to glue an
+// AnimationDelegate (C++ class) to a GtkChromeButton* (GTK/c object).
+class HoverControllerGtk : public ui::AnimationDelegate {
+ public:
+  virtual ~HoverControllerGtk();
+
+  GtkWidget* button() { return button_; }
+
+  // Throb for |cycles| cycles. This will override the current remaining
+  // number of cycles. Note that a "cycle" is (somewhat unintuitively) half of
+  // a complete throb revolution.
+  void StartThrobbing(int cycles);
+
+  // Get the HoverControllerGtk for a given GtkChromeButton*. It is an error
+  // to call this on a widget that is not a GtkChromeButton*.
+  static HoverControllerGtk* GetHoverControllerGtk(GtkWidget* button);
+
+  // Creates a GtkChromeButton and adds a HoverControllerGtk for it.
+  static GtkWidget* CreateChromeButton();
+
+  // Stop throbbing and delete |this|.
+  void Destroy();
+
+ private:
+  explicit HoverControllerGtk(GtkWidget* button);
+
+  // Overridden from ui::AnimationDelegate.
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationEnded(const ui::Animation* animation);
+  virtual void AnimationCanceled(const ui::Animation* animation);
+
+  CHROMEGTK_CALLBACK_1(HoverControllerGtk, gboolean, OnEnter,
+                       GdkEventCrossing*);
+  CHROMEGTK_CALLBACK_1(HoverControllerGtk, gboolean, OnLeave,
+                       GdkEventCrossing*);
+  CHROMEGTK_CALLBACK_1(HoverControllerGtk, void, OnHierarchyChanged,
+                       GtkWidget*);
+  CHROMEGTK_CALLBACK_0(HoverControllerGtk, void, OnDestroy);
+
+  ui::ThrobAnimation throb_animation_;
+  ui::SlideAnimation hover_animation_;
+  GtkWidget* button_;
+
+  ui::GtkSignalRegistrar signals_;
+
+  DISALLOW_COPY_AND_ASSIGN(HoverControllerGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_HOVER_CONTROLLER_GTK_H_
diff --git a/chrome/browser/ui/gtk/html_dialog_gtk.cc b/chrome/browser/ui/gtk/html_dialog_gtk.cc
new file mode 100644
index 0000000..519d987
--- /dev/null
+++ b/chrome/browser/ui/gtk/html_dialog_gtk.cc
@@ -0,0 +1,176 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/html_dialog_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
+#include "chrome/common/native_web_keyboard_event.h"
+#include "ipc/ipc_message.h"
+
+namespace browser {
+
+gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile,
+                                 HtmlDialogUIDelegate* delegate) {
+  HtmlDialogGtk* html_dialog =
+      new HtmlDialogGtk(profile, delegate, parent);
+  return html_dialog->InitDialog();
+}
+
+} // namespace browser
+
+////////////////////////////////////////////////////////////////////////////////
+// HtmlDialogGtk, public:
+
+HtmlDialogGtk::HtmlDialogGtk(Profile* profile,
+                             HtmlDialogUIDelegate* delegate,
+                             gfx::NativeWindow parent_window)
+    : HtmlDialogTabContentsDelegate(profile),
+      delegate_(delegate),
+      parent_window_(parent_window),
+      dialog_(NULL) {
+}
+
+HtmlDialogGtk::~HtmlDialogGtk() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HtmlDialogUIDelegate implementation:
+
+bool HtmlDialogGtk::IsDialogModal() const {
+  return delegate_ ? delegate_->IsDialogModal() : false;
+}
+
+std::wstring HtmlDialogGtk::GetDialogTitle() const {
+  return delegate_ ? delegate_->GetDialogTitle() : L"";
+}
+
+GURL HtmlDialogGtk::GetDialogContentURL() const {
+  if (delegate_)
+    return delegate_->GetDialogContentURL();
+  else
+    return GURL();
+}
+
+void HtmlDialogGtk::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
+  if (delegate_)
+    delegate_->GetWebUIMessageHandlers(handlers);
+  else
+    handlers->clear();
+}
+
+void HtmlDialogGtk::GetDialogSize(gfx::Size* size) const {
+  if (delegate_)
+    delegate_->GetDialogSize(size);
+  else
+    *size = gfx::Size();
+}
+
+std::string HtmlDialogGtk::GetDialogArgs() const {
+  if (delegate_)
+    return delegate_->GetDialogArgs();
+  else
+    return std::string();
+}
+
+void HtmlDialogGtk::OnDialogClosed(const std::string& json_retval) {
+  DCHECK(dialog_);
+
+  Detach();
+  if (delegate_) {
+    HtmlDialogUIDelegate* dialog_delegate = delegate_;
+    delegate_ = NULL;  // We will not communicate further with the delegate.
+    dialog_delegate->OnDialogClosed(json_retval);
+  }
+  gtk_widget_destroy(dialog_);
+  delete this;
+}
+
+bool HtmlDialogGtk::ShouldShowDialogTitle() const {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsDelegate implementation:
+
+void HtmlDialogGtk::MoveContents(TabContents* source, const gfx::Rect& pos) {
+  // The contained web page wishes to resize itself. We let it do this because
+  // if it's a dialog we know about, we trust it not to be mean to the user.
+}
+
+void HtmlDialogGtk::ToolbarSizeChanged(TabContents* source,
+                                       bool is_animating) {
+  // Ignored.
+}
+
+// A simplified version of BrowserWindowGtk::HandleKeyboardEvent().
+// We don't handle global keyboard shortcuts here, but that's fine since
+// they're all browser-specific. (This may change in the future.)
+void HtmlDialogGtk::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
+  GdkEventKey* os_event = event.os_event;
+  if (!os_event || event.type == WebKit::WebInputEvent::Char)
+    return;
+
+  // To make sure the default key bindings can still work, such as Escape to
+  // close the dialog.
+  gtk_bindings_activate_event(GTK_OBJECT(dialog_), os_event);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HtmlDialogGtk:
+
+gfx::NativeWindow HtmlDialogGtk::InitDialog() {
+  tab_contents_.reset(
+      new TabContents(profile(), NULL, MSG_ROUTING_NONE, NULL, NULL));
+  tab_contents_->set_delegate(this);
+
+  // This must be done before loading the page; see the comments in
+  // HtmlDialogUI.
+  HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
+                                                  this);
+
+  tab_contents_->controller().LoadURL(GetDialogContentURL(),
+                                      GURL(), PageTransition::START_PAGE);
+  GtkDialogFlags flags = GTK_DIALOG_NO_SEPARATOR;
+  if (delegate_->IsDialogModal())
+    flags = static_cast<GtkDialogFlags>(flags | GTK_DIALOG_MODAL);
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      WideToUTF8(delegate_->GetDialogTitle()).c_str(),
+      parent_window_,
+      flags,
+      NULL);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+
+  tab_contents_container_.reset(new TabContentsContainerGtk(NULL));
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                     tab_contents_container_->widget(), TRUE, TRUE, 0);
+
+  tab_contents_container_->SetTabContents(tab_contents_.get());
+
+  gfx::Size dialog_size;
+  delegate_->GetDialogSize(&dialog_size);
+
+  gtk_widget_set_size_request(GTK_WIDGET(tab_contents_container_->widget()),
+                              dialog_size.width(),
+                              dialog_size.height());
+
+  gtk_widget_show_all(dialog_);
+
+  return GTK_WINDOW(dialog_);
+}
+
+void HtmlDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
+  OnDialogClosed(std::string());
+}
diff --git a/chrome/browser/ui/gtk/html_dialog_gtk.h b/chrome/browser/ui/gtk/html_dialog_gtk.h
new file mode 100644
index 0000000..3134b42
--- /dev/null
+++ b/chrome/browser/ui/gtk/html_dialog_gtk.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_HTML_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_HTML_DIALOG_GTK_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class Browser;
+class Profile;
+class TabContents;
+class TabContentsContainerGtk;
+
+class HtmlDialogGtk : public HtmlDialogTabContentsDelegate,
+                      public HtmlDialogUIDelegate {
+ public:
+  HtmlDialogGtk(Profile* profile, HtmlDialogUIDelegate* delegate,
+                gfx::NativeWindow parent_window);
+  virtual ~HtmlDialogGtk();
+
+  // Initializes the contents of the dialog (the DOMView and the callbacks).
+  gfx::NativeWindow InitDialog();
+
+  // Overridden from HtmlDialogUI::Delegate:
+  virtual bool IsDialogModal() const;
+  virtual std::wstring GetDialogTitle() const;
+  virtual GURL GetDialogContentURL() const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
+  virtual void GetDialogSize(gfx::Size* size) const;
+  virtual std::string GetDialogArgs() const;
+  virtual void OnDialogClosed(const std::string& json_retval);
+  virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) { }
+  virtual bool ShouldShowDialogTitle() const;
+
+  // Overridden from TabContentsDelegate:
+  virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
+  virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
+  virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
+
+ private:
+  CHROMEGTK_CALLBACK_1(HtmlDialogGtk, void, OnResponse, int);
+
+  // This view is a delegate to the HTML content since it needs to get notified
+  // about when the dialog is closing. For all other actions (besides dialog
+  // closing) we delegate to the creator of this view, which we keep track of
+  // using this variable.
+  HtmlDialogUIDelegate* delegate_;
+
+  gfx::NativeWindow parent_window_;
+
+  GtkWidget* dialog_;
+
+  scoped_ptr<TabContents> tab_contents_;
+  scoped_ptr<TabContentsContainerGtk> tab_contents_container_;
+
+  DISALLOW_COPY_AND_ASSIGN(HtmlDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_HTML_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc b/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc
new file mode 100644
index 0000000..fc41e24
--- /dev/null
+++ b/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc
@@ -0,0 +1,229 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/hung_renderer_dialog.h"
+
+#include <gtk/gtk.h>
+
+#include "base/process_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/result_codes.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// A wrapper class that represents the Gtk dialog.
+class HungRendererDialogGtk {
+ public:
+  HungRendererDialogGtk();
+  void ShowForTabContents(TabContents* hung_contents);
+  void EndForTabContents(TabContents* hung_contents);
+
+ private:
+  // The GtkTreeView column ids.
+  enum {
+    COL_FAVICON,
+    COL_TITLE,
+    COL_COUNT,
+  };
+
+  // Create the gtk dialog and add the widgets.
+  void Init();
+
+  CHROMEGTK_CALLBACK_1(HungRendererDialogGtk, void, OnDialogResponse, gint);
+
+  GtkDialog* dialog_;
+  GtkListStore* model_;
+  TabContents* contents_;
+
+  DISALLOW_COPY_AND_ASSIGN(HungRendererDialogGtk);
+};
+
+// We only support showing one of these at a time per app.
+HungRendererDialogGtk* g_instance = NULL;
+
+// The response ID for the "Kill pages" button.  Anything positive should be
+// fine (the built in GtkResponseTypes are negative numbers).
+const int kKillPagesButtonResponse = 1;
+
+HungRendererDialogGtk::HungRendererDialogGtk()
+    : dialog_(NULL), model_(NULL), contents_(NULL) {
+  Init();
+}
+
+void HungRendererDialogGtk::Init() {
+  dialog_ = GTK_DIALOG(gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE).c_str(),
+      NULL,  // No parent because tabs can span multiple windows.
+      GTK_DIALOG_NO_SEPARATOR,
+      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_END).c_str(),
+      kKillPagesButtonResponse,
+      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT).c_str(),
+      GTK_RESPONSE_OK,
+      NULL));
+  gtk_dialog_set_default_response(dialog_, GTK_RESPONSE_OK);
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+
+  // We have an hbox with the frozen icon on the left.  On the right,
+  // we have a vbox with the unresponsive text on top and a table of
+  // tabs on bottom.
+  // ·-----------------------------------·
+  // |·---------------------------------·|
+  // ||·----·|·------------------------·||
+  // |||icon|||                        |||
+  // ||·----·|| The folowing page(s).. |||
+  // ||      ||                        |||
+  // ||      ||------------------------|||
+  // ||      || table of tabs          |||
+  // ||      |·------------------------·||
+  // |·---------------------------------·|
+  // |                                   |
+  // |         kill button    wait button|
+  // ·-----------------------------------·
+  GtkWidget* contents_vbox = dialog_->vbox;
+  gtk_box_set_spacing(GTK_BOX(contents_vbox), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 12);
+  gtk_box_pack_start(GTK_BOX(contents_vbox), hbox, TRUE, TRUE, 0);
+
+  // Wrap the icon in a vbox so it stays top aligned.
+  GtkWidget* icon_vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), icon_vbox, FALSE, FALSE, 0);
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  GdkPixbuf* icon_pixbuf = rb.GetPixbufNamed(IDR_FROZEN_TAB_ICON);
+  GtkWidget* icon = gtk_image_new_from_pixbuf(icon_pixbuf);
+  gtk_box_pack_start(GTK_BOX(icon_vbox), icon, FALSE, FALSE, 0);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
+
+  GtkWidget* text = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER).c_str());
+  gtk_label_set_line_wrap(GTK_LABEL(text), TRUE);
+  gtk_box_pack_start(GTK_BOX(vbox), text, FALSE, FALSE, 0);
+
+  GtkWidget* scroll_list = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_list),
+      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_list),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_box_pack_start(GTK_BOX(vbox), scroll_list, TRUE, TRUE, 0);
+
+  // The list of hung tabs is GtkTreeView with a GtkListStore as the model.
+  model_ = gtk_list_store_new(COL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+  GtkWidget* tree_view = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(model_));
+  g_object_unref(model_);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
+  GtkTreeViewColumn* column = gtk_tree_view_column_new();
+  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(column, renderer, FALSE);
+  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
+  renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);
+
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+  gtk_container_add(GTK_CONTAINER(scroll_list), tree_view);
+}
+
+void HungRendererDialogGtk::ShowForTabContents(TabContents* hung_contents) {
+  DCHECK(hung_contents && dialog_);
+  contents_ = hung_contents;
+  gtk_list_store_clear(model_);
+
+  GtkTreeIter tree_iter;
+  for (TabContentsIterator it; !it.done(); ++it) {
+    if (it->GetRenderProcessHost() == hung_contents->GetRenderProcessHost()) {
+      gtk_list_store_append(model_, &tree_iter);
+      std::string title = UTF16ToUTF8(it->GetTitle());
+      if (title.empty())
+        title = UTF16ToUTF8(TabContents::GetDefaultTitle());
+      SkBitmap favicon = it->GetFavIcon();
+
+      GdkPixbuf* pixbuf = NULL;
+      if (favicon.width() > 0)
+        pixbuf = gfx::GdkPixbufFromSkBitmap(&favicon);
+      gtk_list_store_set(model_, &tree_iter,
+          COL_FAVICON, pixbuf,
+          COL_TITLE, title.c_str(),
+          -1);
+      if (pixbuf)
+        g_object_unref(pixbuf);
+    }
+  }
+  gtk_util::ShowDialog(GTK_WIDGET(dialog_));
+}
+
+void HungRendererDialogGtk::EndForTabContents(TabContents* contents) {
+  DCHECK(contents);
+  if (contents_ && contents_->GetRenderProcessHost() ==
+      contents->GetRenderProcessHost()) {
+    gtk_widget_hide(GTK_WIDGET(dialog_));
+    // Since we're closing, we no longer need this TabContents.
+    contents_ = NULL;
+  }
+}
+
+// When the user clicks a button on the dialog or closes the dialog, this
+// callback is called.
+void HungRendererDialogGtk::OnDialogResponse(GtkWidget* widget,
+                                             gint response_id) {
+  DCHECK(g_instance == this);
+  switch (response_id) {
+    case kKillPagesButtonResponse:
+      // Kill the process.
+      if (contents_ && contents_->GetRenderProcessHost()) {
+        base::KillProcess(contents_->GetRenderProcessHost()->GetHandle(),
+                          ResultCodes::HUNG, false);
+      }
+      break;
+
+    case GTK_RESPONSE_OK:
+    case GTK_RESPONSE_DELETE_EVENT:
+      // Start waiting again for responsiveness.
+      if (contents_ && contents_->render_view_host())
+        contents_->render_view_host()->RestartHangMonitorTimeout();
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  gtk_widget_destroy(GTK_WIDGET(dialog_));
+  delete g_instance;
+  g_instance = NULL;
+}
+
+}  // namespace
+
+namespace hung_renderer_dialog {
+
+void ShowForTabContents(TabContents* contents) {
+  if (!logging::DialogsAreSuppressed()) {
+    if (!g_instance)
+      g_instance = new HungRendererDialogGtk();
+    g_instance->ShowForTabContents(contents);
+  }
+}
+
+// static
+void HideForTabContents(TabContents* contents) {
+  if (!logging::DialogsAreSuppressed() && g_instance)
+    g_instance->EndForTabContents(contents);
+}
+
+}  // namespace hung_renderer_dialog
diff --git a/chrome/browser/ui/gtk/import_dialog_gtk.cc b/chrome/browser/ui/gtk/import_dialog_gtk.cc
new file mode 100644
index 0000000..4627cee
--- /dev/null
+++ b/chrome/browser/ui/gtk/import_dialog_gtk.cc
@@ -0,0 +1,220 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/import_dialog_gtk.h"
+
+#include <string>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Returns true if the checkbox is checked.
+gboolean IsChecked(GtkWidget* widget) {
+  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
+}   // namespace
+
+// static
+void ImportDialogGtk::Show(GtkWindow* parent, Profile* profile,
+                           int initial_state) {
+  new ImportDialogGtk(parent, profile, initial_state);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ImportObserver implementation:
+void ImportDialogGtk::ImportCanceled() {
+  ImportComplete();
+}
+
+void ImportDialogGtk::ImportComplete() {
+  gtk_widget_destroy(dialog_);
+  delete this;
+}
+
+ImportDialogGtk::ImportDialogGtk(GtkWindow* parent, Profile* profile,
+                                 int initial_state)
+    : parent_(parent),
+      profile_(profile),
+      importer_host_(new ImporterHost),
+      ALLOW_THIS_IN_INITIALIZER_LIST(importer_list_(new ImporterList)),
+      initial_state_(initial_state) {
+  // Load the available source profiles.
+  importer_list_->DetectSourceProfiles(this);
+
+  // Build the dialog.
+  std::string dialog_name = l10n_util::GetStringUTF8(
+      IDS_IMPORT_SETTINGS_TITLE);
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      parent,
+      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_REJECT,
+      NULL);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  importer_host_->set_parent_window(GTK_WINDOW(dialog_));
+
+  // Add import button separately as we might need to disable it, if
+  // no supported browsers found.
+  import_button_ = gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(IDS_IMPORT_COMMIT).c_str(),
+      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);
+  GTK_WIDGET_SET_FLAGS(import_button_, GTK_CAN_DEFAULT);
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
+
+  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* combo_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  GtkWidget* from = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_IMPORT_FROM_LABEL).c_str());
+  gtk_box_pack_start(GTK_BOX(combo_hbox), from, FALSE, FALSE, 0);
+
+  combo_ = gtk_combo_box_new_text();
+  gtk_box_pack_start(GTK_BOX(combo_hbox), combo_, TRUE, TRUE, 0);
+
+  gtk_box_pack_start(GTK_BOX(content_area), combo_hbox, FALSE, FALSE, 0);
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GtkWidget* description = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_IMPORT_ITEMS_LABEL).c_str());
+  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);
+
+  bookmarks_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_IMPORT_FAVORITES_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), bookmarks_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bookmarks_),
+      (initial_state_ & importer::FAVORITES) != 0);
+  g_signal_connect(bookmarks_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  search_engines_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_IMPORT_SEARCH_ENGINES_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), search_engines_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(search_engines_),
+      (initial_state_ & importer::SEARCH_ENGINES) != 0);
+  g_signal_connect(search_engines_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  passwords_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_IMPORT_PASSWORDS_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), passwords_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(passwords_),
+      (initial_state_ & importer::PASSWORDS) != 0);
+  g_signal_connect(passwords_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  history_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_IMPORT_HISTORY_CHKBOX).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), history_, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(history_),
+      (initial_state_ & importer::HISTORY) !=0);
+  g_signal_connect(history_, "toggled",
+                   G_CALLBACK(OnDialogWidgetClickedThunk), this);
+
+  gtk_box_pack_start(GTK_BOX(content_area), vbox, FALSE, FALSE, 0);
+
+  // Let the user know profiles are being loaded.
+  gtk_combo_box_append_text(GTK_COMBO_BOX(combo_),
+      l10n_util::GetStringUTF8(IDS_IMPORT_LOADING_PROFILES).c_str());
+  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_), 0);
+
+  // Disable controls until source profiles are loaded.
+  SetDialogControlsSensitive(false);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+
+  UpdateDialogButtons();
+
+  gtk_util::ShowDialogWithLocalizedSize(dialog_,
+                                        IDS_IMPORT_DIALOG_WIDTH_CHARS,
+                                        -1,  // height
+                                        false);  // resizable
+}
+
+ImportDialogGtk::~ImportDialogGtk() {
+}
+
+void ImportDialogGtk::SourceProfilesLoaded() {
+  // Detect any supported browsers that we can import from and fill
+  // up the combo box. If none found, disable all controls except cancel.
+  int profiles_count = importer_list_->GetAvailableProfileCount();
+  SetDialogControlsSensitive(profiles_count != 0);
+  gtk_combo_box_remove_text(GTK_COMBO_BOX(combo_), 0);
+  if (profiles_count > 0) {
+    for (int i = 0; i < profiles_count; i++) {
+      std::wstring profile = importer_list_->GetSourceProfileNameAt(i);
+      gtk_combo_box_append_text(GTK_COMBO_BOX(combo_),
+                                WideToUTF8(profile).c_str());
+    }
+    gtk_widget_grab_focus(import_button_);
+  } else {
+    gtk_combo_box_append_text(GTK_COMBO_BOX(combo_),
+      l10n_util::GetStringUTF8(IDS_IMPORT_NO_PROFILE_FOUND).c_str());
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_), 0);
+}
+
+void ImportDialogGtk::OnDialogResponse(GtkWidget* widget, int response) {
+  gtk_widget_hide_all(dialog_);
+  if (response == GTK_RESPONSE_ACCEPT) {
+    uint16 items = GetCheckedItems();
+    if (items == 0) {
+      ImportComplete();
+    } else {
+      const ProfileInfo& source_profile =
+          importer_list_->GetSourceProfileInfoAt(
+          gtk_combo_box_get_active(GTK_COMBO_BOX(combo_)));
+      StartImportingWithUI(parent_, items, importer_host_,
+                           source_profile, profile_, this, false);
+    }
+  } else {
+    ImportCanceled();
+  }
+}
+
+void ImportDialogGtk::OnDialogWidgetClicked(GtkWidget* widget) {
+  UpdateDialogButtons();
+}
+
+void ImportDialogGtk::UpdateDialogButtons() {
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT,
+                                    GetCheckedItems() != 0);
+}
+
+void ImportDialogGtk::SetDialogControlsSensitive(bool sensitive) {
+  gtk_widget_set_sensitive(bookmarks_, sensitive);
+  gtk_widget_set_sensitive(search_engines_, sensitive);
+  gtk_widget_set_sensitive(passwords_, sensitive);
+  gtk_widget_set_sensitive(history_, sensitive);
+  gtk_widget_set_sensitive(import_button_, sensitive);
+}
+
+uint16 ImportDialogGtk::GetCheckedItems() {
+  uint16 items = importer::NONE;
+  if (IsChecked(bookmarks_))
+    items |= importer::FAVORITES;
+  if (IsChecked(search_engines_))
+    items |= importer::SEARCH_ENGINES;
+  if (IsChecked(passwords_))
+    items |= importer::PASSWORDS;
+  if (IsChecked(history_))
+    items |= importer::HISTORY;
+  return items;
+}
diff --git a/chrome/browser/ui/gtk/import_dialog_gtk.h b/chrome/browser/ui/gtk/import_dialog_gtk.h
new file mode 100644
index 0000000..05ad215
--- /dev/null
+++ b/chrome/browser/ui/gtk/import_dialog_gtk.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_IMPORT_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_IMPORT_DIALOG_GTK_H_
+#pragma once
+
+#include "chrome/browser/importer/importer.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class AccessibleWidgetHelper;
+class Profile;
+
+class ImportDialogGtk : public ImportObserver,
+                        public ImporterList::Observer {
+ public:
+  // Displays the import box to import data from another browser into |profile|
+  // |initial_state| is a bitmask of ImportItems. Each checkbox for the bits in
+  // is checked.
+  static void Show(GtkWindow* parent, Profile* profile, int initial_state);
+
+  // ImportObserver implementation.
+  virtual void ImportCanceled();
+  virtual void ImportComplete();
+
+ private:
+  ImportDialogGtk(GtkWindow* parent, Profile* profile, int initial_state);
+  ~ImportDialogGtk();
+
+  // ImporterList::Observer implementation.
+  virtual void SourceProfilesLoaded();
+
+  // Handler to respond to OK or Cancel responses from the dialog.
+  CHROMEGTK_CALLBACK_1(ImportDialogGtk, void, OnDialogResponse, int);
+
+  // Handler to respond to widget clicked actions from the dialog.
+  CHROMEGTK_CALLBACK_0(ImportDialogGtk, void, OnDialogWidgetClicked);
+
+  // Enable or disable the dialog buttons depending on the state of the
+  // checkboxes.
+  void UpdateDialogButtons();
+
+  // Sets the sensitivity of all controls on the dialog except the cancel
+  // button.
+  void SetDialogControlsSensitive(bool sensitive);
+
+  // Create a bitmask from the checkboxes of the dialog.
+  uint16 GetCheckedItems();
+
+  // Parent window
+  GtkWindow* parent_;
+
+  // Import Dialog
+  GtkWidget* dialog_;
+
+  // Combo box that displays list of profiles from which we can import.
+  GtkWidget* combo_;
+
+  // Bookmarks/Favorites checkbox
+  GtkWidget* bookmarks_;
+
+  // Search Engines checkbox
+  GtkWidget* search_engines_;
+
+  // Passwords checkbox
+  GtkWidget* passwords_;
+
+  // History checkbox
+  GtkWidget* history_;
+
+  // Import button.
+  GtkWidget* import_button_;
+
+  // Our current profile
+  Profile* profile_;
+
+  // Utility class that does the actual import.
+  scoped_refptr<ImporterHost> importer_host_;
+
+  // Enumerates the source profiles.
+  scoped_refptr<ImporterList> importer_list_;
+
+  int initial_state_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImportDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_IMPORT_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/import_lock_dialog_gtk.cc b/chrome/browser/ui/gtk/import_lock_dialog_gtk.cc
new file mode 100644
index 0000000..072347a
--- /dev/null
+++ b/chrome/browser/ui/gtk/import_lock_dialog_gtk.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/import_lock_dialog_gtk.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace browser {
+
+void ShowImportLockDialog(gfx::NativeWindow parent,
+                          ImporterHost* importer_host) {
+  ImportLockDialogGtk::Show(parent, importer_host);
+}
+
+}  // namespace browser
+
+// static
+void ImportLockDialogGtk::Show(GtkWindow* parent, ImporterHost* importer_host) {
+  new ImportLockDialogGtk(parent, importer_host);
+}
+
+ImportLockDialogGtk::ImportLockDialogGtk(GtkWindow* parent,
+    ImporterHost* importer_host) : importer_host_(importer_host) {
+  // Build the dialog.
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_TITLE).c_str(),
+      parent,
+      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      NULL);
+
+  gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_CANCEL).c_str(),
+      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+  gtk_util::AddButtonToDialog(dialog_,
+      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_OK).c_str(),
+      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+
+  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_IMPORTER_LOCK_TEXT).c_str());
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, FALSE, 0);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+  gtk_widget_show_all(dialog_);
+}
+
+ImportLockDialogGtk::~ImportLockDialogGtk() {}
+
+void ImportLockDialogGtk::OnDialogResponse(GtkWidget* widget, int response) {
+  if (response == GTK_RESPONSE_ACCEPT) {
+    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+        importer_host_.get(), &ImporterHost::OnLockViewEnd, true));
+  } else {
+    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+        importer_host_.get(), &ImporterHost::OnLockViewEnd, false));
+  }
+  gtk_widget_destroy(dialog_);
+  delete this;
+}
diff --git a/chrome/browser/ui/gtk/import_lock_dialog_gtk.h b/chrome/browser/ui/gtk/import_lock_dialog_gtk.h
new file mode 100644
index 0000000..b4760b6
--- /dev/null
+++ b/chrome/browser/ui/gtk/import_lock_dialog_gtk.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_IMPORT_LOCK_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_IMPORT_LOCK_DIALOG_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class ImporterHost;
+
+class ImportLockDialogGtk {
+ public:
+  // Displays the Firefox profile locked warning
+  static void Show(GtkWindow* parent, ImporterHost* importer_host);
+
+ private:
+  ImportLockDialogGtk(GtkWindow* parent, ImporterHost* importer_host);
+  ~ImportLockDialogGtk();
+
+  CHROMEGTK_CALLBACK_1(ImportLockDialogGtk, void, OnDialogResponse, int);
+
+  // Dialog box
+  GtkWidget* dialog_;
+
+  // Utility class that does the actual import.
+  scoped_refptr<ImporterHost> importer_host_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImportLockDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_IMPORT_LOCK_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/import_progress_dialog_gtk.cc b/chrome/browser/ui/gtk/import_progress_dialog_gtk.cc
new file mode 100644
index 0000000..645099a
--- /dev/null
+++ b/chrome/browser/ui/gtk/import_progress_dialog_gtk.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/import_progress_dialog_gtk.h"
+
+#include <string>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using importer::ALL;
+using importer::BOOKMARKS_HTML;
+using importer::FAVORITES;
+using importer::HISTORY;
+using importer::HOME_PAGE;
+using importer::ImportItem;
+using importer::PASSWORDS;
+using importer::ProfileInfo;
+using importer::SEARCH_ENGINES;
+
+namespace {
+
+void SetItemImportStatus(GtkWidget* label, int res_id, bool is_done) {
+  std::string status = l10n_util::GetStringUTF8(res_id);
+  // Windows version of this has fancy throbbers to indicate progress. Here
+  // we rely on text until we can have something equivalent on Linux.
+  if (is_done)
+    status = "\xE2\x9C\x94 " + status;  // U+2714 HEAVY CHECK MARK
+  else
+    status.append(" ...");
+  gtk_label_set_text(GTK_LABEL(label), status.c_str());
+}
+
+}  // namespace
+
+// static
+void ImportProgressDialogGtk::StartImport(GtkWindow* parent,
+                                          int16 items,
+                                          ImporterHost* importer_host,
+                                          const ProfileInfo& browser_profile,
+                                          Profile* profile,
+                                          ImportObserver* observer,
+                                          bool first_run) {
+  ImportProgressDialogGtk* v = new ImportProgressDialogGtk(
+      WideToUTF16(browser_profile.description), items, importer_host, observer,
+      parent, browser_profile.browser_type == BOOKMARKS_HTML);
+
+  // In headless mode it means that we don't show the progress window, but it
+  // still need it to exist. No user interaction will be required.
+  if (!importer_host->is_headless())
+    v->ShowDialog();
+
+  importer_host->StartImportSettings(browser_profile, profile, items,
+                                     new ProfileWriter(profile),
+                                     first_run);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ImporterHost::Observer implementation:
+void ImportProgressDialogGtk::ImportItemStarted(importer::ImportItem item) {
+  DCHECK(items_ & item);
+  switch (item) {
+    case FAVORITES:
+      SetItemImportStatus(bookmarks_,
+                          IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS, false);
+      break;
+    case SEARCH_ENGINES:
+      SetItemImportStatus(search_engines_,
+                          IDS_IMPORT_PROGRESS_STATUS_SEARCH, false);
+      break;
+    case PASSWORDS:
+      SetItemImportStatus(passwords_,
+                          IDS_IMPORT_PROGRESS_STATUS_PASSWORDS, false);
+      break;
+    case HISTORY:
+      SetItemImportStatus(history_,
+                          IDS_IMPORT_PROGRESS_STATUS_HISTORY, false);
+      break;
+    default:
+      break;
+  }
+}
+
+void ImportProgressDialogGtk::ImportItemEnded(importer::ImportItem item) {
+  DCHECK(items_ & item);
+  switch (item) {
+    case FAVORITES:
+      SetItemImportStatus(bookmarks_,
+                          IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS, true);
+      break;
+    case SEARCH_ENGINES:
+      SetItemImportStatus(search_engines_,
+                          IDS_IMPORT_PROGRESS_STATUS_SEARCH, true);
+      break;
+    case PASSWORDS:
+      SetItemImportStatus(passwords_,
+                          IDS_IMPORT_PROGRESS_STATUS_PASSWORDS, true);
+      break;
+    case HISTORY:
+      SetItemImportStatus(history_,
+                          IDS_IMPORT_PROGRESS_STATUS_HISTORY, true);
+      break;
+    default:
+      break;
+  }
+}
+
+void ImportProgressDialogGtk::ImportStarted() {
+  importing_ = true;
+}
+
+void ImportProgressDialogGtk::ImportEnded() {
+  importing_ = false;
+  importer_host_->SetObserver(NULL);
+  if (observer_)
+    observer_->ImportComplete();
+  CloseDialog();
+}
+
+ImportProgressDialogGtk::ImportProgressDialogGtk(const string16& source_profile,
+    int16 items, ImporterHost* importer_host, ImportObserver* observer,
+    GtkWindow* parent, bool bookmarks_import) :
+    parent_(parent), importing_(true), observer_(observer),
+    items_(items), importer_host_(importer_host) {
+  importer_host_->SetObserver(this);
+
+  // Build the dialog.
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_TITLE).c_str(),
+      parent_,
+      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_REJECT,
+      NULL);
+  importer_host_->set_parent_window(GTK_WINDOW(dialog_));
+
+  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
+  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
+
+  GtkWidget* control_group = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GtkWidget* import_info = gtk_label_new(
+      l10n_util::GetStringFUTF8(IDS_IMPORT_PROGRESS_INFO,
+                                source_profile).c_str());
+  gtk_util::SetLabelWidth(import_info, 400);
+  gtk_box_pack_start(GTK_BOX(control_group), import_info, FALSE, FALSE, 0);
+
+  GtkWidget* item_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  if (items_ & HISTORY) {
+    history_ = gtk_label_new(
+        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_HISTORY).c_str());
+    gtk_misc_set_alignment(GTK_MISC(history_), 0, 0.5);
+    gtk_box_pack_start(GTK_BOX(item_box), history_, FALSE, FALSE, 0);
+  }
+
+  if (items_ & FAVORITES) {
+    bookmarks_ = gtk_label_new(
+        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS).c_str());
+    gtk_misc_set_alignment(GTK_MISC(bookmarks_), 0, 0.5);
+    gtk_box_pack_start(GTK_BOX(item_box), bookmarks_, FALSE, FALSE, 0);
+  }
+
+  if (items_ & SEARCH_ENGINES) {
+    search_engines_ = gtk_label_new(
+        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_SEARCH).c_str());
+    gtk_misc_set_alignment(GTK_MISC(search_engines_), 0, 0.5);
+    gtk_box_pack_start(GTK_BOX(item_box), search_engines_, FALSE, FALSE, 0);
+  }
+
+  if (items_ & PASSWORDS) {
+    passwords_ = gtk_label_new(
+        l10n_util::GetStringUTF8(IDS_IMPORT_PROGRESS_STATUS_PASSWORDS).c_str());
+    gtk_misc_set_alignment(GTK_MISC(passwords_), 0, 0.5);
+    gtk_box_pack_start(GTK_BOX(item_box), passwords_, FALSE, FALSE, 0);
+  }
+
+  gtk_box_pack_start(GTK_BOX(control_group), gtk_util::IndentWidget(item_box),
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(content_area), control_group, FALSE, FALSE, 0);
+
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(HandleOnResponseDialog), this);
+  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+}
+
+ImportProgressDialogGtk::~ImportProgressDialogGtk() {}
+
+void ImportProgressDialogGtk::CloseDialog() {
+  gtk_widget_destroy(dialog_);
+  dialog_ = NULL;
+  delete this;
+}
+
+void ImportProgressDialogGtk::OnDialogResponse(GtkWidget* widget,
+                                               int response) {
+  if (!importing_) {
+    CloseDialog();
+    return;
+  }
+
+  // Only response to the dialog is to close it so we hide immediately.
+  gtk_widget_hide_all(dialog_);
+  if (response == GTK_RESPONSE_REJECT)
+    importer_host_->Cancel();
+}
+
+void ImportProgressDialogGtk::ShowDialog() {
+  gtk_widget_show_all(dialog_);
+}
+
+
+void StartImportingWithUI(GtkWindow* parent,
+                          uint16 items,
+                          ImporterHost* importer_host,
+                          const ProfileInfo& browser_profile,
+                          Profile* profile,
+                          ImportObserver* observer,
+                          bool first_run) {
+  DCHECK_NE(0, items);
+  ImportProgressDialogGtk::StartImport(parent, items, importer_host,
+                                       browser_profile, profile, observer,
+                                       first_run);
+}
diff --git a/chrome/browser/ui/gtk/import_progress_dialog_gtk.h b/chrome/browser/ui/gtk/import_progress_dialog_gtk.h
new file mode 100644
index 0000000..2d8d629
--- /dev/null
+++ b/chrome/browser/ui/gtk/import_progress_dialog_gtk.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_IMPORT_PROGRESS_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_IMPORT_PROGRESS_DIALOG_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/importer/importer_data_types.h"
+
+class Profile;
+
+class ImportProgressDialogGtk : public ImporterHost::Observer {
+ public:
+  // Displays the import progress dialog box and starts the import
+  static void StartImport(GtkWindow* parent, int16 items,
+                          ImporterHost* importer_host,
+                          const ProfileInfo& browser_profile,
+                          Profile* profile,
+                          ImportObserver* observer, bool first_run);
+
+  // Overridden from ImporterHost::Observer:
+  virtual void ImportItemStarted(importer::ImportItem item);
+  virtual void ImportItemEnded(importer::ImportItem item);
+  virtual void ImportStarted();
+  virtual void ImportEnded();
+
+ private:
+  ImportProgressDialogGtk(const string16& source_profile, int16 items,
+      ImporterHost* importer_host, ImportObserver* observer,
+      GtkWindow* parent, bool bookmarks_import);
+  virtual ~ImportProgressDialogGtk();
+
+  static void HandleOnResponseDialog(GtkWidget* widget,
+                                     int response,
+                                     gpointer user_data) {
+    reinterpret_cast<ImportProgressDialogGtk*>(user_data)->OnDialogResponse(
+        widget, response);
+  }
+
+  void CloseDialog();
+
+  void OnDialogResponse(GtkWidget* widget, int response);
+
+  void ShowDialog();
+
+  // Parent window
+  GtkWindow* parent_;
+
+  // Import progress dialog
+  GtkWidget* dialog_;
+
+  // Bookmarks/Favorites checkbox
+  GtkWidget* bookmarks_;
+
+  // Search Engines checkbox
+  GtkWidget* search_engines_;
+
+  // Passwords checkbox
+  GtkWidget* passwords_;
+
+  // History checkbox
+  GtkWidget* history_;
+
+  // Boolean that tells whether we are currently in the mid of import process
+  bool importing_;
+
+  // Observer that we need to notify about import events
+  ImportObserver* observer_;
+
+  // Items to import from the other browser.
+  int16 items_;
+
+  // Utility class that does the actual import.
+  scoped_refptr<ImporterHost> importer_host_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImportProgressDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_IMPORT_PROGRESS_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/info_bubble_accelerators_gtk.cc b/chrome/browser/ui/gtk/info_bubble_accelerators_gtk.cc
new file mode 100644
index 0000000..a0a1fb1
--- /dev/null
+++ b/chrome/browser/ui/gtk/info_bubble_accelerators_gtk.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/info_bubble_accelerators_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <glib.h>
+
+namespace {
+// Listing of the accelerators that are either handled or forwarded by
+// info bubbles. Any accelerators that are not explicitly listed here
+// are ignored and silently dropped. This table is expected to change
+// after discussion over which accelerators should be addressed in
+// info bubbles. For a complete listing of accelerators that are used
+// in chrome consult accelerators_gtk.cc
+struct InfoBubbleAcceleratorGtk InfoBubbleAcceleratorGtkTable[] = {
+  // Tab/window controls.
+  { GDK_w, GDK_CONTROL_MASK},
+
+  // Navigation / toolbar buttons.
+  { GDK_Escape, GdkModifierType(0)}
+};
+
+}  // namespace
+
+InfoBubbleAcceleratorGtkList InfoBubbleAcceleratorsGtk::GetList() {
+  InfoBubbleAcceleratorGtkList accelerators;
+  for (size_t i = 0; i < arraysize(InfoBubbleAcceleratorGtkTable); ++i) {
+    accelerators.push_back(InfoBubbleAcceleratorGtkTable[i]);
+  }
+
+  return accelerators;
+}
diff --git a/chrome/browser/ui/gtk/info_bubble_accelerators_gtk.h b/chrome/browser/ui/gtk/info_bubble_accelerators_gtk.h
new file mode 100644
index 0000000..92c66ef
--- /dev/null
+++ b/chrome/browser/ui/gtk/info_bubble_accelerators_gtk.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_INFO_BUBBLE_ACCELERATORS_GTK_H_
+#define CHROME_BROWSER_UI_GTK_INFO_BUBBLE_ACCELERATORS_GTK_H_
+#pragma once
+
+#include <gdk/gdktypes.h>
+#include <glib.h>
+#include <vector>
+
+#include "base/basictypes.h"
+
+struct InfoBubbleAcceleratorGtk {
+  guint keyval;
+  GdkModifierType modifier_type;
+};
+
+typedef std::vector<struct InfoBubbleAcceleratorGtk>
+    InfoBubbleAcceleratorGtkList;
+
+// This class contains a list of accelerators that an InfoBubbleGtk
+// is expected to either catch and respond to or catch and forward to the
+// root browser window. This list is expected to be a subset of the
+// accelerators that are handled by the root browser window, but the
+// specific accelerators to be handled has not yet been fully specified. The
+// common use case for this class has code that uses it needing the entire
+// list and not needing extra processing, so the only get method gives you the
+// entire list.
+class InfoBubbleAcceleratorsGtk {
+ public:
+  static InfoBubbleAcceleratorGtkList GetList();
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(InfoBubbleAcceleratorsGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_INFO_BUBBLE_ACCELERATORS_GTK_H_
diff --git a/chrome/browser/ui/gtk/info_bubble_gtk.cc b/chrome/browser/ui/gtk/info_bubble_gtk.cc
new file mode 100644
index 0000000..3b0c69b
--- /dev/null
+++ b/chrome/browser/ui/gtk/info_bubble_gtk.cc
@@ -0,0 +1,535 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/info_bubble_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/info_bubble_accelerators_gtk.h"
+#include "chrome/common/notification_service.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/rect.h"
+
+namespace {
+
+// The height of the arrow, and the width will be about twice the height.
+const int kArrowSize = 8;
+
+// Number of pixels to the middle of the arrow from the close edge of the
+// window.
+const int kArrowX = 18;
+
+// Number of pixels between the tip of the arrow and the region we're
+// pointing to.
+const int kArrowToContentPadding = -4;
+
+// We draw flat diagonal corners, each corner is an NxN square.
+const int kCornerSize = 3;
+
+// Margins around the content.
+const int kTopMargin = kArrowSize + kCornerSize - 1;
+const int kBottomMargin = kCornerSize - 1;
+const int kLeftMargin = kCornerSize - 1;
+const int kRightMargin = kCornerSize - 1;
+
+const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff);
+const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63);
+
+}  // namespace
+
+// static
+InfoBubbleGtk* InfoBubbleGtk::Show(GtkWidget* anchor_widget,
+                                   const gfx::Rect* rect,
+                                   GtkWidget* content,
+                                   ArrowLocationGtk arrow_location,
+                                   bool match_system_theme,
+                                   bool grab_input,
+                                   GtkThemeProvider* provider,
+                                   InfoBubbleGtkDelegate* delegate) {
+  InfoBubbleGtk* bubble = new InfoBubbleGtk(provider, match_system_theme);
+  bubble->Init(anchor_widget, rect, content, arrow_location, grab_input);
+  bubble->set_delegate(delegate);
+  return bubble;
+}
+
+InfoBubbleGtk::InfoBubbleGtk(GtkThemeProvider* provider,
+                             bool match_system_theme)
+    : delegate_(NULL),
+      window_(NULL),
+      theme_provider_(provider),
+      accel_group_(gtk_accel_group_new()),
+      toplevel_window_(NULL),
+      anchor_widget_(NULL),
+      mask_region_(NULL),
+      preferred_arrow_location_(ARROW_LOCATION_TOP_LEFT),
+      current_arrow_location_(ARROW_LOCATION_TOP_LEFT),
+      match_system_theme_(match_system_theme),
+      grab_input_(true),
+      closed_by_escape_(false) {
+}
+
+InfoBubbleGtk::~InfoBubbleGtk() {
+  // Notify the delegate that we're about to close.  This gives the chance
+  // to save state / etc from the hosted widget before it's destroyed.
+  if (delegate_)
+    delegate_->InfoBubbleClosing(this, closed_by_escape_);
+
+  g_object_unref(accel_group_);
+  if (mask_region_)
+    gdk_region_destroy(mask_region_);
+}
+
+void InfoBubbleGtk::Init(GtkWidget* anchor_widget,
+                         const gfx::Rect* rect,
+                         GtkWidget* content,
+                         ArrowLocationGtk arrow_location,
+                         bool grab_input) {
+  // If there is a current grab widget (menu, other info bubble, etc.), hide it.
+  GtkWidget* current_grab_widget = gtk_grab_get_current();
+  if (current_grab_widget)
+    gtk_widget_hide(current_grab_widget);
+
+  DCHECK(!window_);
+  anchor_widget_ = anchor_widget;
+  toplevel_window_ = GTK_WINDOW(gtk_widget_get_toplevel(anchor_widget_));
+  DCHECK(GTK_WIDGET_TOPLEVEL(toplevel_window_));
+  rect_ = rect ? *rect : gtk_util::WidgetBounds(anchor_widget);
+  preferred_arrow_location_ = arrow_location;
+
+  grab_input_ = grab_input;
+  // Using a TOPLEVEL window may cause placement issues with certain WMs but it
+  // is necessary to be able to focus the window.
+  window_ = gtk_window_new(grab_input ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
+
+  gtk_widget_set_app_paintable(window_, TRUE);
+  // Resizing is handled by the program, not user.
+  gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
+
+  // Attach all of the accelerators to the bubble.
+  InfoBubbleAcceleratorGtkList acceleratorList =
+      InfoBubbleAcceleratorsGtk::GetList();
+  for (InfoBubbleAcceleratorGtkList::const_iterator iter =
+           acceleratorList.begin();
+       iter != acceleratorList.end();
+       ++iter) {
+    gtk_accel_group_connect(accel_group_,
+                            iter->keyval,
+                            iter->modifier_type,
+                            GtkAccelFlags(0),
+                            g_cclosure_new(G_CALLBACK(&OnGtkAcceleratorThunk),
+                                           this,
+                                           NULL));
+  }
+
+  gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_);
+
+  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+                            kTopMargin, kBottomMargin,
+                            kLeftMargin, kRightMargin);
+
+  gtk_container_add(GTK_CONTAINER(alignment), content);
+  gtk_container_add(GTK_CONTAINER(window_), alignment);
+
+  // GtkWidget only exposes the bitmap mask interface.  Use GDK to more
+  // efficently mask a GdkRegion.  Make sure the window is realized during
+  // OnSizeAllocate, so the mask can be applied to the GdkWindow.
+  gtk_widget_realize(window_);
+
+  UpdateArrowLocation(true);  // Force move and reshape.
+  StackWindow();
+
+  gtk_widget_add_events(window_, GDK_BUTTON_PRESS_MASK);
+
+  signals_.Connect(window_, "expose-event", G_CALLBACK(OnExposeThunk), this);
+  signals_.Connect(window_, "size-allocate", G_CALLBACK(OnSizeAllocateThunk),
+                   this);
+  signals_.Connect(window_, "button-press-event",
+                   G_CALLBACK(OnButtonPressThunk), this);
+  signals_.Connect(window_, "destroy", G_CALLBACK(OnDestroyThunk), this);
+  signals_.Connect(window_, "hide", G_CALLBACK(OnHideThunk), this);
+
+  // If the toplevel window is being used as the anchor, then the signals below
+  // are enough to keep us positioned correctly.
+  if (anchor_widget_ != GTK_WIDGET(toplevel_window_)) {
+    signals_.Connect(anchor_widget_, "size-allocate",
+                     G_CALLBACK(OnAnchorAllocateThunk), this);
+    signals_.Connect(anchor_widget_, "destroy",
+                     G_CALLBACK(gtk_widget_destroyed), &anchor_widget_);
+  }
+
+  signals_.Connect(toplevel_window_, "configure-event",
+                   G_CALLBACK(OnToplevelConfigureThunk), this);
+  signals_.Connect(toplevel_window_, "unmap-event",
+                   G_CALLBACK(OnToplevelUnmapThunk), this);
+  // Set |toplevel_window_| to NULL if it gets destroyed.
+  signals_.Connect(toplevel_window_, "destroy",
+                   G_CALLBACK(gtk_widget_destroyed), &toplevel_window_);
+
+  gtk_widget_show_all(window_);
+
+  if (grab_input_) {
+    gtk_grab_add(window_);
+    GrabPointerAndKeyboard();
+  }
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_->InitThemesFor(this);
+}
+
+// NOTE: This seems a bit overcomplicated, but it requires a bunch of careful
+// fudging to get the pixels rasterized exactly where we want them, the arrow to
+// have a 1 pixel point, etc.
+// TODO(deanm): Windows draws with Skia and uses some PNG images for the
+// corners.  This is a lot more work, but they get anti-aliasing.
+// static
+std::vector<GdkPoint> InfoBubbleGtk::MakeFramePolygonPoints(
+    ArrowLocationGtk arrow_location,
+    int width,
+    int height,
+    FrameType type) {
+  using gtk_util::MakeBidiGdkPoint;
+  std::vector<GdkPoint> points;
+
+  bool on_left = (arrow_location == ARROW_LOCATION_TOP_LEFT);
+
+  // If we're stroking the frame, we need to offset some of our points by 1
+  // pixel.  We do this when we draw horizontal lines that are on the bottom or
+  // when we draw vertical lines that are closer to the end (where "end" is the
+  // right side for ARROW_LOCATION_TOP_LEFT).
+  int y_off = (type == FRAME_MASK) ? 0 : -1;
+  // We use this one for arrows located on the left.
+  int x_off_l = on_left ? y_off : 0;
+  // We use this one for RTL.
+  int x_off_r = !on_left ? -y_off : 0;
+
+  // Top left corner.
+  points.push_back(MakeBidiGdkPoint(
+      x_off_r, kArrowSize + kCornerSize - 1, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      kCornerSize + x_off_r - 1, kArrowSize, width, on_left));
+
+  // The arrow.
+  points.push_back(MakeBidiGdkPoint(
+      kArrowX - kArrowSize + x_off_r, kArrowSize, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      kArrowX + x_off_r, 0, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      kArrowX + 1 + x_off_l, 0, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      kArrowX + kArrowSize + 1 + x_off_l, kArrowSize, width, on_left));
+
+  // Top right corner.
+  points.push_back(MakeBidiGdkPoint(
+      width - kCornerSize + 1 + x_off_l, kArrowSize, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      width + x_off_l, kArrowSize + kCornerSize - 1, width, on_left));
+
+  // Bottom right corner.
+  points.push_back(MakeBidiGdkPoint(
+      width + x_off_l, height - kCornerSize, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      width - kCornerSize + x_off_r, height + y_off, width, on_left));
+
+  // Bottom left corner.
+  points.push_back(MakeBidiGdkPoint(
+      kCornerSize + x_off_l, height + y_off, width, on_left));
+  points.push_back(MakeBidiGdkPoint(
+      x_off_r, height - kCornerSize, width, on_left));
+
+  return points;
+}
+
+InfoBubbleGtk::ArrowLocationGtk InfoBubbleGtk::GetArrowLocation(
+    ArrowLocationGtk preferred_location, int arrow_x, int width) {
+  bool wants_left = (preferred_location == ARROW_LOCATION_TOP_LEFT);
+  int screen_width = gdk_screen_get_width(gdk_screen_get_default());
+
+  bool left_is_onscreen = (arrow_x - kArrowX + width < screen_width);
+  bool right_is_onscreen = (arrow_x + kArrowX - width >= 0);
+
+  // Use the requested location if it fits onscreen, use whatever fits
+  // otherwise, and use the requested location if neither fits.
+  if (left_is_onscreen && (wants_left || !right_is_onscreen))
+    return ARROW_LOCATION_TOP_LEFT;
+  if (right_is_onscreen && (!wants_left || !left_is_onscreen))
+    return ARROW_LOCATION_TOP_RIGHT;
+  return (wants_left ? ARROW_LOCATION_TOP_LEFT : ARROW_LOCATION_TOP_RIGHT);
+}
+
+bool InfoBubbleGtk::UpdateArrowLocation(bool force_move_and_reshape) {
+  if (!toplevel_window_ || !anchor_widget_)
+    return false;
+
+  gint toplevel_x = 0, toplevel_y = 0;
+  gdk_window_get_position(
+      GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y);
+  int offset_x, offset_y;
+  gtk_widget_translate_coordinates(anchor_widget_, GTK_WIDGET(toplevel_window_),
+                                   rect_.x(), rect_.y(), &offset_x, &offset_y);
+
+  ArrowLocationGtk old_location = current_arrow_location_;
+  current_arrow_location_ = GetArrowLocation(
+      preferred_arrow_location_,
+      toplevel_x + offset_x + (rect_.width() / 2),  // arrow_x
+      window_->allocation.width);
+
+  if (force_move_and_reshape || current_arrow_location_ != old_location) {
+    UpdateWindowShape();
+    MoveWindow();
+    // We need to redraw the entire window to repaint its border.
+    gtk_widget_queue_draw(window_);
+    return true;
+  }
+  return false;
+}
+
+void InfoBubbleGtk::UpdateWindowShape() {
+  if (mask_region_) {
+    gdk_region_destroy(mask_region_);
+    mask_region_ = NULL;
+  }
+  std::vector<GdkPoint> points = MakeFramePolygonPoints(
+      current_arrow_location_,
+      window_->allocation.width, window_->allocation.height,
+      FRAME_MASK);
+  mask_region_ = gdk_region_polygon(&points[0],
+                                    points.size(),
+                                    GDK_EVEN_ODD_RULE);
+  gdk_window_shape_combine_region(window_->window, NULL, 0, 0);
+  gdk_window_shape_combine_region(window_->window, mask_region_, 0, 0);
+}
+
+void InfoBubbleGtk::MoveWindow() {
+  if (!toplevel_window_ || !anchor_widget_)
+    return;
+
+  gint toplevel_x = 0, toplevel_y = 0;
+  gdk_window_get_position(
+      GTK_WIDGET(toplevel_window_)->window, &toplevel_x, &toplevel_y);
+
+  int offset_x, offset_y;
+  gtk_widget_translate_coordinates(anchor_widget_, GTK_WIDGET(toplevel_window_),
+                                   rect_.x(), rect_.y(), &offset_x, &offset_y);
+
+  gint screen_x = 0;
+  if (current_arrow_location_ == ARROW_LOCATION_TOP_LEFT) {
+    screen_x = toplevel_x + offset_x + (rect_.width() / 2) - kArrowX;
+  } else if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT) {
+    screen_x = toplevel_x + offset_x + (rect_.width() / 2) -
+               window_->allocation.width + kArrowX;
+  } else {
+    NOTREACHED();
+  }
+
+  gint screen_y = toplevel_y + offset_y + rect_.height() +
+                  kArrowToContentPadding;
+
+  gtk_window_move(GTK_WINDOW(window_), screen_x, screen_y);
+}
+
+void InfoBubbleGtk::StackWindow() {
+  // Stack our window directly above the toplevel window.
+  if (toplevel_window_)
+    gtk_util::StackPopupWindow(window_, GTK_WIDGET(toplevel_window_));
+}
+
+void InfoBubbleGtk::Observe(NotificationType type,
+                            const NotificationSource& source,
+                            const NotificationDetails& details) {
+  DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED);
+  if (theme_provider_->UseGtkTheme() && match_system_theme_) {
+    gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, NULL);
+  } else {
+    // Set the background color, so we don't need to paint it manually.
+    gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor);
+  }
+}
+
+void InfoBubbleGtk::HandlePointerAndKeyboardUngrabbedByContent() {
+  if (grab_input_)
+    GrabPointerAndKeyboard();
+}
+
+void InfoBubbleGtk::Close() {
+  // We don't need to ungrab the pointer or keyboard here; the X server will
+  // automatically do that when we destroy our window.
+  DCHECK(window_);
+  gtk_widget_destroy(window_);
+  // |this| has been deleted, see OnDestroy.
+}
+
+void InfoBubbleGtk::GrabPointerAndKeyboard() {
+  // Install X pointer and keyboard grabs to make sure that we have the focus
+  // and get all mouse and keyboard events until we're closed.
+  GdkGrabStatus pointer_grab_status =
+      gdk_pointer_grab(window_->window,
+                       TRUE,                   // owner_events
+                       GDK_BUTTON_PRESS_MASK,  // event_mask
+                       NULL,                   // confine_to
+                       NULL,                   // cursor
+                       GDK_CURRENT_TIME);
+  if (pointer_grab_status != GDK_GRAB_SUCCESS) {
+    // This will fail if someone else already has the pointer grabbed, but
+    // there's not really anything we can do about that.
+    DLOG(ERROR) << "Unable to grab pointer (status="
+                << pointer_grab_status << ")";
+  }
+  GdkGrabStatus keyboard_grab_status =
+      gdk_keyboard_grab(window_->window,
+                        FALSE,  // owner_events
+                        GDK_CURRENT_TIME);
+  if (keyboard_grab_status != GDK_GRAB_SUCCESS) {
+    DLOG(ERROR) << "Unable to grab keyboard (status="
+                << keyboard_grab_status << ")";
+  }
+}
+
+gboolean InfoBubbleGtk::OnGtkAccelerator(GtkAccelGroup* group,
+                                         GObject* acceleratable,
+                                         guint keyval,
+                                         GdkModifierType modifier) {
+  GdkEventKey msg;
+  GdkKeymapKey* keys;
+  gint n_keys;
+
+  switch (keyval) {
+    case GDK_Escape:
+      // Close on Esc and trap the accelerator
+      closed_by_escape_ = true;
+      Close();
+      return TRUE;
+    case GDK_w:
+      // Close on C-w and forward the accelerator
+      if (modifier & GDK_CONTROL_MASK) {
+        Close();
+      }
+      break;
+    default:
+      return FALSE;
+  }
+
+  gdk_keymap_get_entries_for_keyval(NULL,
+                                    keyval,
+                                    &keys,
+                                    &n_keys);
+  if (n_keys) {
+    // Forward the accelerator to root window the bubble is anchored
+    // to for further processing
+    msg.type = GDK_KEY_PRESS;
+    msg.window = GTK_WIDGET(toplevel_window_)->window;
+    msg.send_event = TRUE;
+    msg.time = GDK_CURRENT_TIME;
+    msg.state = modifier | GDK_MOD2_MASK;
+    msg.keyval = keyval;
+    // length and string are deprecated and thus zeroed out
+    msg.length = 0;
+    msg.string = NULL;
+    msg.hardware_keycode = keys[0].keycode;
+    msg.group = keys[0].group;
+    msg.is_modifier = 0;
+
+    g_free(keys);
+
+    gtk_main_do_event(reinterpret_cast<GdkEvent*>(&msg));
+  } else {
+    // This means that there isn't a h/w code for the keyval in the
+    // current keymap, which is weird but possible if the keymap just
+    // changed. This isn't a critical error, but might be indicative
+    // of something off if it happens regularly.
+    DLOG(WARNING) << "Found no keys for value " << keyval;
+  }
+  return TRUE;
+}
+
+gboolean InfoBubbleGtk::OnExpose(GtkWidget* widget, GdkEventExpose* expose) {
+  GdkDrawable* drawable = GDK_DRAWABLE(window_->window);
+  GdkGC* gc = gdk_gc_new(drawable);
+  gdk_gc_set_rgb_fg_color(gc, &kFrameColor);
+
+  // Stroke the frame border.
+  std::vector<GdkPoint> points = MakeFramePolygonPoints(
+      current_arrow_location_,
+      window_->allocation.width, window_->allocation.height,
+      FRAME_STROKE);
+  gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
+
+  g_object_unref(gc);
+  return FALSE;  // Propagate so our children paint, etc.
+}
+
+// When our size is initially allocated or changed, we need to recompute
+// and apply our shape mask region.
+void InfoBubbleGtk::OnSizeAllocate(GtkWidget* widget,
+                                   GtkAllocation* allocation) {
+  if (!UpdateArrowLocation(false)) {
+    UpdateWindowShape();
+    if (current_arrow_location_ == ARROW_LOCATION_TOP_RIGHT)
+      MoveWindow();
+  }
+}
+
+gboolean InfoBubbleGtk::OnButtonPress(GtkWidget* widget,
+                                      GdkEventButton* event) {
+  // If we got a click in our own window, that's okay (we need to additionally
+  // check that it falls within our bounds, since we've grabbed the pointer and
+  // some events that actually occurred in other windows will be reported with
+  // respect to our window).
+  if (event->window == window_->window &&
+      (mask_region_ && gdk_region_point_in(mask_region_, event->x, event->y))) {
+    return FALSE;  // Propagate.
+  }
+
+  // Our content widget got a click.
+  if (event->window != window_->window &&
+      gdk_window_get_toplevel(event->window) == window_->window) {
+    return FALSE;
+  }
+
+  if (grab_input_) {
+    // Otherwise we had a click outside of our window, close ourself.
+    Close();
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+gboolean InfoBubbleGtk::OnDestroy(GtkWidget* widget) {
+  // We are self deleting, we have a destroy signal setup to catch when we
+  // destroy the widget manually, or the window was closed via X.  This will
+  // delete the InfoBubbleGtk object.
+  delete this;
+  return FALSE;  // Propagate.
+}
+
+void InfoBubbleGtk::OnHide(GtkWidget* widget) {
+  gtk_widget_destroy(widget);
+}
+
+gboolean InfoBubbleGtk::OnToplevelConfigure(GtkWidget* widget,
+                                            GdkEventConfigure* event) {
+  if (!UpdateArrowLocation(false))
+    MoveWindow();
+  StackWindow();
+  return FALSE;
+}
+
+gboolean InfoBubbleGtk::OnToplevelUnmap(GtkWidget* widget, GdkEvent* event) {
+  Close();
+  return FALSE;
+}
+
+void InfoBubbleGtk::OnAnchorAllocate(GtkWidget* widget,
+                                     GtkAllocation* allocation) {
+  if (!UpdateArrowLocation(false))
+    MoveWindow();
+}
diff --git a/chrome/browser/ui/gtk/info_bubble_gtk.h b/chrome/browser/ui/gtk/info_bubble_gtk.h
new file mode 100644
index 0000000..e680df7
--- /dev/null
+++ b/chrome/browser/ui/gtk/info_bubble_gtk.h
@@ -0,0 +1,215 @@
+// Copyright (c) 2011 The Chromium 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 the GTK implementation of InfoBubbles.  InfoBubbles are like
+// dialogs, but they point to a given element on the screen.  You should call
+// InfoBubbleGtk::Show, which will create and display a bubble.  The object is
+// self deleting, when the bubble is closed, you will be notified via
+// InfoBubbleGtkDelegate::InfoBubbleClosing().  Then the widgets and the
+// underlying object will be destroyed.  You can also close and destroy the
+// bubble by calling Close().
+
+#ifndef CHROME_BROWSER_UI_GTK_INFO_BUBBLE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_INFO_BUBBLE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+
+class GtkThemeProvider;
+class InfoBubbleGtk;
+namespace gfx {
+class Rect;
+}
+
+class InfoBubbleGtkDelegate {
+ public:
+  // Called when the InfoBubble is closing and is about to be deleted.
+  // |closed_by_escape| is true if the close is the result of pressing escape.
+  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                 bool closed_by_escape) = 0;
+
+  // NOTE: The Views interface has CloseOnEscape, except I can't find a place
+  // where it ever returns false, so we always allow you to close via escape.
+
+ protected:
+  virtual ~InfoBubbleGtkDelegate() {}
+};
+
+class InfoBubbleGtk : public NotificationObserver {
+ public:
+  // Where should the arrow be placed relative to the bubble?
+  enum ArrowLocationGtk {
+    // TODO(derat): Support placing arrows on the bottoms of the bubbles.
+    ARROW_LOCATION_TOP_LEFT,
+    ARROW_LOCATION_TOP_RIGHT,
+  };
+
+  // Show an InfoBubble, pointing at the area |rect| (in coordinates relative to
+  // |anchor_widget|'s origin).  An info bubble will try to fit on the screen,
+  // so it can point to any edge of |rect|.  If |rect| is NULL, the widget's
+  // entire area will be used. The bubble will host the |content|
+  // widget.  Its arrow will be drawn at |arrow_location| if possible.  The
+  // |delegate| will be notified when the bubble is closed.  The bubble will
+  // perform an X grab of the pointer and keyboard, and will close itself if a
+  // click is received outside of the bubble.
+  static InfoBubbleGtk* Show(GtkWidget* anchor_widget,
+                             const gfx::Rect* rect,
+                             GtkWidget* content,
+                             ArrowLocationGtk arrow_location,
+                             bool match_system_theme,
+                             bool grab_input,
+                             GtkThemeProvider* provider,
+                             InfoBubbleGtkDelegate* delegate);
+
+  // Close the bubble if it's open.  This will delete the widgets and object,
+  // so you shouldn't hold a InfoBubbleGtk pointer after calling Close().
+  void Close();
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // If the content contains widgets that can steal our pointer and keyboard
+  // grabs (e.g. GtkComboBox), this method should be called after a widget
+  // releases the grabs so we can reacquire them.  Note that this causes a race
+  // condition; another client could grab them before we do (ideally, GDK would
+  // transfer the grabs back to us when the widget releases them).  The window
+  // is small, though, and the worst-case scenario for this seems to just be
+  // that the content's widgets will appear inactive even after the user clicks
+  // in them.
+  void HandlePointerAndKeyboardUngrabbedByContent();
+
+ private:
+  enum FrameType {
+    FRAME_MASK,
+    FRAME_STROKE,
+  };
+
+  explicit InfoBubbleGtk(GtkThemeProvider* provider, bool match_system_theme);
+  virtual ~InfoBubbleGtk();
+
+  // Creates the InfoBubble.
+  void Init(GtkWidget* anchor_widget,
+            const gfx::Rect* rect,
+            GtkWidget* content,
+            ArrowLocationGtk arrow_location,
+            bool grab_input);
+
+  // Make the points for our polygon frame, either for fill (the mask), or for
+  // when we stroke the border.
+  static std::vector<GdkPoint> MakeFramePolygonPoints(
+      ArrowLocationGtk arrow_location,
+      int width,
+      int height,
+      FrameType type);
+
+  // Get the location where the arrow should be placed (which is a function of
+  // the preferred location and of the direction that the bubble should be
+  // facing to fit onscreen).  |arrow_x| is the X component in screen
+  // coordinates of the point at which the bubble's arrow should be aimed, and
+  // |width| is the bubble's width.
+  static ArrowLocationGtk GetArrowLocation(
+      ArrowLocationGtk preferred_location, int arrow_x, int width);
+
+  // Updates |arrow_location_| based on the toplevel window's current position
+  // and the bubble's size.  If the |force_move_and_reshape| is true or the
+  // location changes, moves and reshapes the window and returns true.
+  bool UpdateArrowLocation(bool force_move_and_reshape);
+
+  // Reshapes the window and updates |mask_region_|.
+  void UpdateWindowShape();
+
+  // Calculate the current screen position for the bubble's window (per
+  // |toplevel_window_|'s position as of its most-recent ConfigureNotify event
+  // and |rect_|) and move it there.
+  void MoveWindow();
+
+  // Restack the bubble's window directly above |toplevel_window_|.
+  void StackWindow();
+
+  // Sets the delegate.
+  void set_delegate(InfoBubbleGtkDelegate* delegate) { delegate_ = delegate; }
+
+  // Grab (in the X sense) the pointer and keyboard.  This is needed to make
+  // sure that we have the input focus.
+  void GrabPointerAndKeyboard();
+
+  CHROMEG_CALLBACK_3(InfoBubbleGtk, gboolean, OnGtkAccelerator, GtkAccelGroup*,
+                     GObject*, guint, GdkModifierType);
+
+  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnExpose, GdkEventExpose*);
+  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, void, OnSizeAllocate, GtkAllocation*);
+  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnButtonPress, GdkEventButton*);
+  CHROMEGTK_CALLBACK_0(InfoBubbleGtk, gboolean, OnDestroy);
+  CHROMEGTK_CALLBACK_0(InfoBubbleGtk, void, OnHide);
+  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnToplevelConfigure,
+                       GdkEventConfigure*);
+  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, gboolean, OnToplevelUnmap, GdkEvent*);
+  CHROMEGTK_CALLBACK_1(InfoBubbleGtk, void, OnAnchorAllocate, GtkAllocation*);
+
+  // The caller supplied delegate, can be NULL.
+  InfoBubbleGtkDelegate* delegate_;
+
+  // Our GtkWindow popup window, we don't technically "own" the widget, since
+  // it deletes us when it is destroyed.
+  GtkWidget* window_;
+
+  // Provides colors and stuff.
+  GtkThemeProvider* theme_provider_;
+
+  // The accel group attached to |window_|, to handle closing with escape.
+  GtkAccelGroup* accel_group_;
+
+  // The window for which we're being shown (and to which |rect_| is relative).
+  // Note that it's possible for |toplevel_window_| to be NULL if the
+  // window is destroyed before this object is destroyed, so it's important
+  // to check for that case.
+  GtkWindow* toplevel_window_;
+
+  // The widget that we use to relatively position the popup window.
+  GtkWidget* anchor_widget_;
+
+  // Provides an offset from |anchor_widget_|'s origin for MoveWindow() to
+  // use.
+  gfx::Rect rect_;
+
+  // The current shape of |window_| (used to test whether clicks fall in it or
+  // not).
+  GdkRegion* mask_region_;
+
+  // Where would we prefer for the arrow be drawn relative to the bubble, and
+  // where is it currently drawn?
+  ArrowLocationGtk preferred_arrow_location_;
+  ArrowLocationGtk current_arrow_location_;
+
+  // Whether the background should match the system theme, when the system theme
+  // is being used. For example, the bookmark bubble does, but extension popups
+  // do not.
+  bool match_system_theme_;
+
+  // If true, the popup owns all X input for the duration of its existence.
+  // This will usually be true, the exception being when inspecting extension
+  // popups with dev tools.
+  bool grab_input_;
+
+  bool closed_by_escape_;
+
+  NotificationRegistrar registrar_;
+
+  ui::GtkSignalRegistrar signals_;
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBubbleGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_INFO_BUBBLE_GTK_H_
diff --git a/chrome/browser/ui/gtk/infobars/infobar_arrow_model.cc b/chrome/browser/ui/gtk/infobars/infobar_arrow_model.cc
new file mode 100644
index 0000000..e448f78
--- /dev/null
+++ b/chrome/browser/ui/gtk/infobars/infobar_arrow_model.cc
@@ -0,0 +1,124 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/infobars/infobar_arrow_model.h"
+
+#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/skia_utils_gtk.h"
+
+InfoBarArrowModel::InfoBarArrowModel(Observer* observer)
+    : observer_(observer),
+      animation_(this) {
+  animation_.SetTweenType(ui::Tween::LINEAR);
+  animation_.Reset(1.0);
+  target_colors_.top = target_colors_.bottom = SkColorSetARGB(0, 0, 0, 0);
+  previous_colors_ = target_colors_;
+}
+
+InfoBarArrowModel::~InfoBarArrowModel() {
+}
+
+InfoBarArrowModel::InfoBarColors InfoBarArrowModel::CurrentInfoBarColors() {
+  double alpha = animation_.GetCurrentValue();
+  InfoBarColors colors = {
+      color_utils::AlphaBlend(target_colors_.top,
+                              previous_colors_.top,
+                              alpha * 0xff),
+      color_utils::AlphaBlend(target_colors_.bottom,
+                              previous_colors_.bottom,
+                              alpha * 0xff)};
+  return colors;
+}
+
+bool InfoBarArrowModel::NeedToDrawInfoBarArrow() {
+  return SkColorGetA(CurrentInfoBarColors().top) != 0;
+}
+
+void InfoBarArrowModel::ShowArrowFor(InfoBar* bar, bool animate) {
+  scoped_ptr<std::pair<SkColor, SkColor> > colors;
+
+  previous_colors_ = CurrentInfoBarColors();
+
+  if (bar) {
+    double r, g, b;
+    bar->GetTopColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
+    target_colors_.top = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
+    bar->GetBottomColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
+    target_colors_.bottom = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
+  } else {
+    target_colors_.bottom = target_colors_.top = SkColorSetARGB(0, 0, 0, 0);
+  }
+
+  if (animate) {
+    // Fade from the current color to the target color.
+    animation_.Reset();
+    animation_.Show();
+  } else {
+    // Skip straight to showing the target color.
+    animation_.Reset(1.0);
+  }
+
+  observer_->PaintStateChanged();
+}
+
+void InfoBarArrowModel::Paint(GtkWidget* widget,
+                              GdkEventExpose* expose,
+                              const gfx::Point& origin,
+                              const GdkColor& border_color) {
+  if (!NeedToDrawInfoBarArrow())
+    return;
+
+  // The size of the arrow (its height; also half its width).
+  const int kArrowSize = 10;
+
+  SkPath path;
+  path.moveTo(SkPoint::Make(origin.x() - kArrowSize, origin.y()));
+  path.rLineTo(kArrowSize, -kArrowSize);
+  path.rLineTo(kArrowSize, kArrowSize);
+  path.close();
+
+  SkPaint paint;
+  paint.setStrokeWidth(1);
+  paint.setStyle(SkPaint::kFill_Style);
+
+  SkPoint grad_points[2];
+  grad_points[0].set(SkIntToScalar(0), SkIntToScalar(origin.y()));
+  grad_points[1].set(SkIntToScalar(0),
+                     SkIntToScalar(origin.y() + InfoBar::kInfoBarHeight));
+
+  InfoBarColors colors = CurrentInfoBarColors();
+  SkColor grad_colors[2];
+  grad_colors[0] = colors.top;
+  grad_colors[1] = colors.bottom;
+
+  SkShader* gradient_shader = SkGradientShader::CreateLinear(
+      grad_points, grad_colors, NULL, 2, SkShader::kMirror_TileMode);
+  paint.setShader(gradient_shader);
+  gradient_shader->unref();
+
+  gfx::CanvasSkiaPaint canvas(expose, false);
+  canvas.drawPath(path, paint);
+
+  paint.setShader(NULL);
+  paint.setColor(SkColorSetA(gfx::GdkColorToSkColor(border_color),
+                             SkColorGetA(colors.top)));
+  paint.setStyle(SkPaint::kStroke_Style);
+  canvas.drawPath(path, paint);
+}
+
+void InfoBarArrowModel::AnimationEnded(const ui::Animation* animation) {
+  observer_->PaintStateChanged();
+}
+
+void InfoBarArrowModel::AnimationProgressed(const ui::Animation* animation) {
+  observer_->PaintStateChanged();
+}
+
+void InfoBarArrowModel::AnimationCanceled(const ui::Animation* animation) {
+  observer_->PaintStateChanged();
+}
diff --git a/chrome/browser/ui/gtk/infobars/infobar_arrow_model.h b/chrome/browser/ui/gtk/infobars/infobar_arrow_model.h
new file mode 100644
index 0000000..139d006
--- /dev/null
+++ b/chrome/browser/ui/gtk/infobars/infobar_arrow_model.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_ARROW_MODEL_H_
+#define CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_ARROW_MODEL_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "third_party/skia/include/core/SkPaint.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/slide_animation.h"
+
+namespace gfx {
+class Point;
+}
+
+class InfoBar;
+
+// A helper class that tracks the state of an infobar arrow and provides a
+// utility to draw it.
+class InfoBarArrowModel : public ui::AnimationDelegate {
+ public:
+  class Observer {
+   public:
+    // The arrow has changed states; relevant widgets need to be repainted.
+    virtual void PaintStateChanged() = 0;
+  };
+
+  explicit InfoBarArrowModel(Observer* observer);
+  virtual ~InfoBarArrowModel();
+
+  // An infobar has been added or removed that will affect the state of this
+  // arrow.
+  void ShowArrowFor(InfoBar* bar, bool animate);
+
+  // Returns true if the arrow is showing at all.
+  bool NeedToDrawInfoBarArrow();
+
+  // Paints the arrow on |widget|, in response to |expose|, with the bottom
+  // center of the arrow at |origin|, drawing a border with |border_color|.
+  void Paint(GtkWidget* widget,
+             GdkEventExpose* expose,
+             const gfx::Point& origin,
+             const GdkColor& border_color);
+
+  // Overridden from ui::AnimationDelegate.
+  virtual void AnimationEnded(const ui::Animation* animation);
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationCanceled(const ui::Animation* animation);
+
+ private:
+  // A pair of colors used to draw a gradient for an arrow.
+  struct InfoBarColors {
+    SkColor top;
+    SkColor bottom;
+  };
+
+  // Calculates the currently showing arrow color, which is a blend of the new
+  // arrow color and the old arrow color.
+  InfoBarColors CurrentInfoBarColors();
+
+  // The view that owns us.
+  Observer* observer_;
+
+  // An animation that tracks the progress of the transition from the last color
+  // to the new color.
+  ui::SlideAnimation animation_;
+
+  // The color we are animating towards.
+  InfoBarColors target_colors_;
+  // The last color we showed (the one we are animating away from).
+  InfoBarColors previous_colors_;
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBarArrowModel);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_ARROW_MODEL_H_
diff --git a/chrome/browser/ui/gtk/infobars/infobar_container_gtk.cc b/chrome/browser/ui/gtk/infobars/infobar_container_gtk.cc
new file mode 100644
index 0000000..e1a3608
--- /dev/null
+++ b/chrome/browser/ui/gtk/infobars/infobar_container_gtk.cc
@@ -0,0 +1,221 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/infobars/infobar_container_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include <utility>
+
+#include "base/command_line.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "third_party/skia/include/core/SkPaint.h"
+
+namespace {
+
+static const char* kInfoBar = "info-bar";
+
+// If |infobar_widget| matches |info_bar_delegate|, then close the infobar.
+void AnimateClosingForDelegate(GtkWidget* infobar_widget,
+                               gpointer info_bar_delegate) {
+  InfoBarDelegate* delegate =
+      static_cast<InfoBarDelegate*>(info_bar_delegate);
+  InfoBar* infobar = reinterpret_cast<InfoBar*>(
+      g_object_get_data(G_OBJECT(infobar_widget), kInfoBar));
+
+  if (!infobar) {
+    NOTREACHED();
+    return;
+  }
+
+  if (delegate == infobar->delegate())
+    infobar->AnimateClose();
+}
+
+// If |infobar_widget| matches |info_bar_delegate|, then close the infobar w/o
+// an animation.
+void ClosingForDelegate(GtkWidget* infobar_widget, gpointer info_bar_delegate) {
+  InfoBarDelegate* delegate =
+      static_cast<InfoBarDelegate*>(info_bar_delegate);
+  InfoBar* infobar = reinterpret_cast<InfoBar*>(
+      g_object_get_data(G_OBJECT(infobar_widget), kInfoBar));
+
+  if (!infobar) {
+    NOTREACHED();
+    return;
+  }
+
+  if (delegate == infobar->delegate())
+    infobar->Close();
+}
+
+// Get the height of the widget and add it to |userdata|, but only if it is in
+// the process of animating.
+void SumAnimatingBarHeight(GtkWidget* widget, gpointer userdata) {
+  int* height_sum = static_cast<int*>(userdata);
+  InfoBar* infobar = reinterpret_cast<InfoBar*>(
+      g_object_get_data(G_OBJECT(widget), kInfoBar));
+  if (infobar->IsAnimating())
+    *height_sum += widget->allocation.height;
+}
+
+}  // namespace
+
+// InfoBarContainerGtk, public: ------------------------------------------------
+
+InfoBarContainerGtk::InfoBarContainerGtk(Profile* profile)
+    : profile_(profile),
+      tab_contents_(NULL),
+      container_(gtk_vbox_new(FALSE, 0)) {
+  gtk_widget_show(widget());
+}
+
+InfoBarContainerGtk::~InfoBarContainerGtk() {
+  ChangeTabContents(NULL);
+
+  container_.Destroy();
+}
+
+void InfoBarContainerGtk::ChangeTabContents(TabContents* contents) {
+  if (tab_contents_)
+    registrar_.RemoveAll();
+
+  gtk_util::RemoveAllChildren(widget());
+  UpdateToolbarInfoBarState(NULL, false);
+
+  tab_contents_ = contents;
+  if (tab_contents_) {
+    UpdateInfoBars();
+    Source<TabContents> source(tab_contents_);
+    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_ADDED, source);
+    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
+                   source);
+    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED,
+                   source);
+  }
+}
+
+void InfoBarContainerGtk::RemoveDelegate(InfoBarDelegate* delegate) {
+  tab_contents_->RemoveInfoBar(delegate);
+}
+
+int InfoBarContainerGtk::TotalHeightOfAnimatingBars() const {
+  int sum = 0;
+  gtk_container_foreach(GTK_CONTAINER(widget()), SumAnimatingBarHeight, &sum);
+  return sum;
+}
+
+// InfoBarContainerGtk, NotificationObserver implementation: -------------------
+
+void InfoBarContainerGtk::Observe(NotificationType type,
+                                  const NotificationSource& source,
+                                  const NotificationDetails& details) {
+  if (type == NotificationType::TAB_CONTENTS_INFOBAR_ADDED) {
+    AddInfoBar(Details<InfoBarDelegate>(details).ptr(), true);
+  } else if (type == NotificationType::TAB_CONTENTS_INFOBAR_REMOVED) {
+    RemoveInfoBar(Details<InfoBarDelegate>(details).ptr(), true);
+  } else if (type == NotificationType::TAB_CONTENTS_INFOBAR_REPLACED) {
+    std::pair<InfoBarDelegate*, InfoBarDelegate*>* delegates =
+        Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details).ptr();
+
+    // By not animating the removal/addition, this appears to be a replace.
+    RemoveInfoBar(delegates->first, false);
+    AddInfoBar(delegates->second, false);
+  } else {
+    NOTREACHED();
+  }
+}
+
+// InfoBarContainerGtk, private: -----------------------------------------------
+
+void InfoBarContainerGtk::UpdateInfoBars() {
+  for (size_t i = 0; i < tab_contents_->infobar_count(); ++i) {
+    InfoBarDelegate* delegate = tab_contents_->GetInfoBarDelegateAt(i);
+    AddInfoBar(delegate, false);
+  }
+}
+
+void InfoBarContainerGtk::ShowArrowForDelegate(InfoBarDelegate* delegate,
+                                               bool animate) {
+  GList* children = gtk_container_get_children(GTK_CONTAINER(widget()));
+  if (!children)
+    return;
+
+  // Iterate through the infobars and find the last one that isn't closing.
+  InfoBar* last_bar = NULL;
+  InfoBar* this_bar = NULL;
+  for (GList* iter = children; iter != NULL; iter = iter->next) {
+    this_bar = reinterpret_cast<InfoBar*>(
+        g_object_get_data(G_OBJECT(iter->data), kInfoBar));
+
+    if (this_bar->delegate() == delegate)
+      break;
+
+    if (!this_bar->IsClosing())
+      last_bar = this_bar;
+
+    this_bar = NULL;
+  }
+
+  if (last_bar)
+    last_bar->ShowArrowFor(this_bar, animate);
+  else
+    UpdateToolbarInfoBarState(this_bar, animate);
+
+  g_list_free(children);
+}
+
+void InfoBarContainerGtk::AddInfoBar(InfoBarDelegate* delegate, bool animate) {
+  InfoBar* infobar = delegate->CreateInfoBar();
+  infobar->set_container(this);
+  infobar->SetThemeProvider(GtkThemeProvider::GetFrom(profile_));
+  gtk_box_pack_start(GTK_BOX(widget()), infobar->widget(),
+                     FALSE, FALSE, 0);
+
+  if (animate)
+    infobar->AnimateOpen();
+  else
+    infobar->Open();
+
+  ShowArrowForDelegate(delegate, animate);
+}
+
+void InfoBarContainerGtk::RemoveInfoBar(InfoBarDelegate* delegate,
+                                        bool animate) {
+  if (animate) {
+    gtk_container_foreach(GTK_CONTAINER(widget()),
+                          AnimateClosingForDelegate, delegate);
+  } else {
+    gtk_container_foreach(GTK_CONTAINER(widget()), ClosingForDelegate,
+                          delegate);
+  }
+
+  InfoBarDelegate* next_delegate = NULL;
+  for (size_t i = 1; i < tab_contents_->infobar_count(); ++i) {
+    if (tab_contents_->GetInfoBarDelegateAt(i - 1) == delegate) {
+      next_delegate = tab_contents_->GetInfoBarDelegateAt(i);
+      break;
+    }
+  }
+
+  ShowArrowForDelegate(next_delegate, animate);
+}
+
+void InfoBarContainerGtk::UpdateToolbarInfoBarState(InfoBar* infobar,
+                                                    bool animate) {
+  GtkWindow* parent = platform_util::GetTopLevel(widget());
+  BrowserWindowGtk* browser_window =
+      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
+  if (browser_window)
+    browser_window->SetInfoBarShowing(infobar, animate);
+}
diff --git a/chrome/browser/ui/gtk/infobars/infobar_container_gtk.h b/chrome/browser/ui/gtk/infobars/infobar_container_gtk.h
new file mode 100644
index 0000000..c3e1a77
--- /dev/null
+++ b/chrome/browser/ui/gtk/infobars/infobar_container_gtk.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_CONTAINER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_CONTAINER_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class InfoBar;
+class InfoBarDelegate;
+class Profile;
+class TabContents;
+
+typedef struct _GtkWidget GtkWidget;
+
+class InfoBarContainerGtk : public NotificationObserver {
+ public:
+  explicit InfoBarContainerGtk(Profile* profile);
+  virtual ~InfoBarContainerGtk();
+
+  // Get the native widget.
+  GtkWidget* widget() const { return container_.get(); }
+
+  // Changes the TabContents for which this container is showing InfoBars. Can
+  // be NULL, in which case we will simply detach ourselves from the old tab
+  // contents.
+  void ChangeTabContents(TabContents* contents);
+
+  // Remove the specified InfoBarDelegate from the selected TabContents. This
+  // will notify us back and cause us to close the View. This is called from
+  // the InfoBar's close button handler.
+  void RemoveDelegate(InfoBarDelegate* delegate);
+
+  // Returns the total pixel height of all infobars in this container that
+  // are currently animating.
+  int TotalHeightOfAnimatingBars() const;
+
+ private:
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Constructs the InfoBars needed to reflect the state of the current
+  // TabContents associated with this container. No animations are run during
+  // this process.
+  void UpdateInfoBars();
+
+  // Makes the calls to show an arrow for |delegate| (either on the browser
+  // toolbar or on the next infobar up).
+  void ShowArrowForDelegate(InfoBarDelegate* delegate, bool animate);
+
+  // Adds an InfoBar for the specified delegate, in response to a notification
+  // from the selected TabContents.
+  void AddInfoBar(InfoBarDelegate* delegate, bool animate);
+
+  // Removes an InfoBar for the specified delegate, in response to a
+  // notification from the selected TabContents. The InfoBar's disappearance
+  // will be animated.
+  void RemoveInfoBar(InfoBarDelegate* delegate, bool animate);
+
+  // Tells the browser window about our state so it can draw the arrow
+  // appropriately.
+  void UpdateToolbarInfoBarState(InfoBar* infobar, bool animate);
+
+  NotificationRegistrar registrar_;
+
+  // The profile for the browser that hosts this InfoBarContainer.
+  Profile* profile_;
+
+  // The TabContents for which we are currently showing InfoBars.
+  TabContents* tab_contents_;
+
+  // VBox that holds the info bars.
+  OwnedWidgetGtk container_;
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBarContainerGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_CONTAINER_GTK_H_
diff --git a/chrome/browser/ui/gtk/infobars/infobar_gtk.cc b/chrome/browser/ui/gtk/infobars/infobar_gtk.cc
new file mode 100644
index 0000000..07d54e5
--- /dev/null
+++ b/chrome/browser/ui/gtk/infobars/infobar_gtk.cc
@@ -0,0 +1,413 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_container_gtk.h"
+#include "chrome/common/notification_service.h"
+#include "ui/gfx/gtk_util.h"
+
+extern const int InfoBar::kInfoBarHeight = 37;
+
+namespace {
+
+// Spacing after message (and before buttons).
+const int kEndOfLabelSpacing = 6;
+// Spacing between buttons.
+const int kButtonButtonSpacing = 3;
+
+// Pixels between infobar elements.
+const int kElementPadding = 5;
+
+// Extra padding on either end of info bar.
+const int kLeftPadding = 5;
+const int kRightPadding = 5;
+
+}  // namespace
+
+InfoBar::InfoBar(InfoBarDelegate* delegate)
+    : container_(NULL),
+      delegate_(delegate),
+      theme_provider_(NULL),
+      arrow_model_(this) {
+  // Create |hbox_| and pad the sides.
+  hbox_ = gtk_hbox_new(FALSE, kElementPadding);
+
+  // Make the whole infor bar horizontally shrinkable.
+  gtk_widget_set_size_request(hbox_, 0, -1);
+
+  GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(padding),
+      0, 0, kLeftPadding, kRightPadding);
+
+  bg_box_ = gtk_event_box_new();
+  gtk_widget_set_app_paintable(bg_box_, TRUE);
+  g_signal_connect(bg_box_, "expose-event",
+                   G_CALLBACK(OnBackgroundExposeThunk), this);
+  gtk_container_add(GTK_CONTAINER(padding), hbox_);
+  gtk_container_add(GTK_CONTAINER(bg_box_), padding);
+  gtk_widget_set_size_request(bg_box_, -1, kInfoBarHeight);
+
+  // Add the icon on the left, if any.
+  SkBitmap* icon = delegate->GetIcon();
+  if (icon) {
+    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(icon);
+    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
+    g_object_unref(pixbuf);
+    gtk_box_pack_start(GTK_BOX(hbox_), image, FALSE, FALSE, 0);
+  }
+
+  close_button_.reset(CustomDrawButton::CloseButton(NULL));
+  gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0);
+  g_signal_connect(close_button_->widget(), "clicked",
+                   G_CALLBACK(OnCloseButtonThunk), this);
+
+  slide_widget_.reset(new SlideAnimatorGtk(bg_box_,
+                                           SlideAnimatorGtk::DOWN,
+                                           0, true, true, this));
+  // We store a pointer back to |this| so we can refer to it from the infobar
+  // container.
+  g_object_set_data(G_OBJECT(slide_widget_->widget()), "info-bar", this);
+}
+
+InfoBar::~InfoBar() {
+}
+
+GtkWidget* InfoBar::widget() {
+  return slide_widget_->widget();
+}
+
+void InfoBar::AnimateOpen() {
+  slide_widget_->Open();
+
+  gtk_widget_show_all(bg_box_);
+  if (bg_box_->window)
+    gdk_window_lower(bg_box_->window);
+}
+
+void InfoBar::Open() {
+  slide_widget_->OpenWithoutAnimation();
+
+  gtk_widget_show_all(bg_box_);
+  if (bg_box_->window)
+    gdk_window_lower(bg_box_->window);
+}
+
+void InfoBar::AnimateClose() {
+  slide_widget_->Close();
+}
+
+void InfoBar::Close() {
+  if (delegate_) {
+    delegate_->InfoBarClosed();
+    delegate_ = NULL;
+  }
+  delete this;
+}
+
+bool InfoBar::IsAnimating() {
+  return slide_widget_->IsAnimating();
+}
+
+bool InfoBar::IsClosing() {
+  return slide_widget_->IsClosing();
+}
+
+void InfoBar::ShowArrowFor(InfoBar* other, bool animate) {
+  arrow_model_.ShowArrowFor(other, animate);
+}
+
+void InfoBar::PaintStateChanged() {
+  gtk_widget_queue_draw(widget());
+}
+
+void InfoBar::RemoveInfoBar() const {
+  container_->RemoveDelegate(delegate_);
+}
+
+void InfoBar::Closed() {
+  Close();
+}
+
+void InfoBar::SetThemeProvider(GtkThemeProvider* theme_provider) {
+  if (theme_provider_) {
+    NOTREACHED();
+    return;
+  }
+
+  theme_provider_ = theme_provider;
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  UpdateBorderColor();
+}
+
+void InfoBar::Observe(NotificationType type,
+                      const NotificationSource& source,
+                      const NotificationDetails& details) {
+  UpdateBorderColor();
+}
+
+void InfoBar::AddLabelWithInlineLink(const string16& display_text,
+                                     const string16& link_text,
+                                     size_t link_offset,
+                                     GCallback callback) {
+  GtkWidget* link_button = gtk_chrome_link_button_new(
+      UTF16ToUTF8(link_text).c_str());
+  gtk_chrome_link_button_set_use_gtk_theme(
+      GTK_CHROME_LINK_BUTTON(link_button), FALSE);
+  gtk_util::ForceFontSizePixels(
+      GTK_CHROME_LINK_BUTTON(link_button)->label, 13.4);
+  DCHECK(callback);
+  g_signal_connect(link_button, "clicked", callback, this);
+  gtk_util::SetButtonTriggersNavigation(link_button);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+  // We want the link to be horizontally shrinkable, so that the Chrome
+  // window can be resized freely even with a very long link.
+  gtk_widget_set_size_request(hbox, 0, -1);
+  gtk_box_pack_start(GTK_BOX(hbox_), hbox, TRUE, TRUE, 0);
+
+  // Need to insert the link inside the display text.
+  GtkWidget* initial_label = gtk_label_new(
+      UTF16ToUTF8(display_text.substr(0, link_offset)).c_str());
+  GtkWidget* trailing_label = gtk_label_new(
+      UTF16ToUTF8(display_text.substr(link_offset)).c_str());
+
+  gtk_util::ForceFontSizePixels(initial_label, 13.4);
+  gtk_util::ForceFontSizePixels(trailing_label, 13.4);
+
+  // TODO(joth): None of the label widgets are set as shrinkable here, meaning
+  // the text will run under the close button etc. when the width is restricted,
+  // rather than eliding.
+  gtk_widget_modify_fg(initial_label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+  gtk_widget_modify_fg(trailing_label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+
+  // We don't want any spacing between the elements, so we pack them into
+  // this hbox that doesn't use kElementPadding.
+  gtk_box_pack_start(GTK_BOX(hbox), initial_label, FALSE, FALSE, 0);
+  gtk_util::CenterWidgetInHBox(hbox, link_button, false, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), trailing_label, FALSE, FALSE, 0);
+}
+
+void InfoBar::GetTopColor(InfoBarDelegate::Type type,
+                          double* r, double* g, double *b) {
+  // These constants are copied from corresponding skia constants from
+  // browser/ui/views/infobars/infobars.cc, and then changed into 0-1 ranged
+  // values for cairo.
+  switch (type) {
+    case InfoBarDelegate::WARNING_TYPE:
+      *r = 255.0 / 255.0;
+      *g = 242.0 / 255.0;
+      *b = 183.0 / 255.0;
+      break;
+    case InfoBarDelegate::PAGE_ACTION_TYPE:
+      *r = 218.0 / 255.0;
+      *g = 231.0 / 255.0;
+      *b = 249.0 / 255.0;
+      break;
+  }
+}
+
+void InfoBar::GetBottomColor(InfoBarDelegate::Type type,
+                             double* r, double* g, double *b) {
+  switch (type) {
+    case InfoBarDelegate::WARNING_TYPE:
+      *r = 250.0 / 255.0;
+      *g = 230.0 / 255.0;
+      *b = 145.0 / 255.0;
+      break;
+    case InfoBarDelegate::PAGE_ACTION_TYPE:
+      *r = 179.0 / 255.0;
+      *g = 202.0 / 255.0;
+      *b = 231.0 / 255.0;
+      break;
+  }
+}
+
+void InfoBar::UpdateBorderColor() {
+  gtk_widget_queue_draw(widget());
+}
+
+void InfoBar::OnCloseButton(GtkWidget* button) {
+  if (delegate_)
+    delegate_->InfoBarDismissed();
+  RemoveInfoBar();
+}
+
+gboolean InfoBar::OnBackgroundExpose(GtkWidget* sender,
+                                     GdkEventExpose* event) {
+  const int height = sender->allocation.height;
+
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+
+  cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height);
+
+  double top_r, top_g, top_b;
+  GetTopColor(delegate_->GetInfoBarType(), &top_r, &top_g, &top_b);
+  cairo_pattern_add_color_stop_rgb(pattern, 0.0, top_r, top_g, top_b);
+
+  double bottom_r, bottom_g, bottom_b;
+  GetBottomColor(delegate_->GetInfoBarType(), &bottom_r, &bottom_g, &bottom_b);
+  cairo_pattern_add_color_stop_rgb(
+      pattern, 1.0, bottom_r, bottom_g, bottom_b);
+  cairo_set_source(cr, pattern);
+  cairo_paint(cr);
+  cairo_pattern_destroy(pattern);
+
+  // Draw the bottom border.
+  GdkColor border_color = theme_provider_->GetBorderColor();
+  cairo_set_source_rgb(cr, border_color.red / 65535.0,
+                           border_color.green / 65535.0,
+                           border_color.blue / 65535.0);
+  cairo_set_line_width(cr, 1.0);
+  int y = sender->allocation.height;
+  cairo_move_to(cr, 0, y - 0.5);
+  cairo_rel_line_to(cr, sender->allocation.width, 0);
+  cairo_stroke(cr);
+
+  cairo_destroy(cr);
+
+  if (!arrow_model_.NeedToDrawInfoBarArrow())
+    return FALSE;
+
+  GtkWindow* parent = platform_util::GetTopLevel(widget());
+  BrowserWindowGtk* browser_window =
+      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
+  int x = browser_window ?
+      browser_window->GetXPositionOfLocationIcon(sender) : 0;
+
+  arrow_model_.Paint(sender, event, gfx::Point(x, y), border_color);
+
+  return FALSE;
+}
+
+// LinkInfoBar -----------------------------------------------------------------
+
+class LinkInfoBar : public InfoBar {
+ public:
+  explicit LinkInfoBar(LinkInfoBarDelegate* delegate)
+      : InfoBar(delegate) {
+    size_t link_offset;
+    string16 display_text = delegate->GetMessageTextWithOffset(&link_offset);
+    string16 link_text = delegate->GetLinkText();
+    AddLabelWithInlineLink(display_text, link_text, link_offset,
+                           G_CALLBACK(OnLinkClick));
+  }
+
+ private:
+  static void OnLinkClick(GtkWidget* button, LinkInfoBar* link_info_bar) {
+    if (link_info_bar->delegate_->AsLinkInfoBarDelegate()->
+        LinkClicked(gtk_util::DispositionForCurrentButtonPressEvent())) {
+      link_info_bar->RemoveInfoBar();
+    }
+  }
+};
+
+// ConfirmInfoBar --------------------------------------------------------------
+
+class ConfirmInfoBar : public InfoBar {
+ public:
+  explicit ConfirmInfoBar(ConfirmInfoBarDelegate* delegate);
+
+ private:
+  // Adds a button to the info bar by type. It will do nothing if the delegate
+  // doesn't specify a button of the given type.
+  void AddButton(ConfirmInfoBarDelegate::InfoBarButton type);
+
+  CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnOkButton);
+  CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnCancelButton);
+  CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnLinkClicked);
+
+  GtkWidget* confirm_hbox_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
+};
+
+ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
+    : InfoBar(delegate) {
+  confirm_hbox_ = gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, 0);
+  // This alignment allocates the confirm hbox only as much space as it
+  // requests, and less if there is not enough available.
+  GtkWidget* align = gtk_alignment_new(0, 0, 0, 1);
+  gtk_container_add(GTK_CONTAINER(align), confirm_hbox_);
+  gtk_box_pack_start(GTK_BOX(hbox_), align, TRUE, TRUE, 0);
+
+  // We add the buttons in reverse order and pack end instead of start so
+  // that the first widget to get shrunk is the label rather than the button(s).
+  AddButton(ConfirmInfoBarDelegate::BUTTON_OK);
+  AddButton(ConfirmInfoBarDelegate::BUTTON_CANCEL);
+
+  std::string label_text = UTF16ToUTF8(delegate->GetMessageText());
+  GtkWidget* label = gtk_label_new(label_text.c_str());
+  gtk_util::ForceFontSizePixels(label, 13.4);
+  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+  gtk_util::CenterWidgetInHBox(confirm_hbox_, label, true, kEndOfLabelSpacing);
+  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+  g_signal_connect(label, "map",
+                   G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
+                   NULL);
+
+  std::string link_text = UTF16ToUTF8(delegate->GetLinkText());
+  if (link_text.empty())
+    return;
+
+  GtkWidget* link = gtk_chrome_link_button_new(link_text.c_str());
+  gtk_misc_set_alignment(GTK_MISC(GTK_CHROME_LINK_BUTTON(link)->label), 0, 0.5);
+  g_signal_connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
+  gtk_util::SetButtonTriggersNavigation(link);
+  // Until we switch to vector graphics, force the font size.
+  // 13.4px == 10pt @ 96dpi
+  gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link)->label, 13.4);
+  gtk_util::CenterWidgetInHBox(hbox_, link, true, kEndOfLabelSpacing);
+}
+
+void ConfirmInfoBar::AddButton(ConfirmInfoBarDelegate::InfoBarButton type) {
+  if (delegate_->AsConfirmInfoBarDelegate()->GetButtons() & type) {
+    GtkWidget* button = gtk_button_new_with_label(UTF16ToUTF8(
+        delegate_->AsConfirmInfoBarDelegate()->GetButtonLabel(type)).c_str());
+    gtk_util::CenterWidgetInHBox(confirm_hbox_, button, true,
+                                 kButtonButtonSpacing);
+    g_signal_connect(button, "clicked",
+                     G_CALLBACK(type == ConfirmInfoBarDelegate::BUTTON_OK ?
+                                OnOkButtonThunk : OnCancelButtonThunk),
+                     this);
+  }
+}
+
+void ConfirmInfoBar::OnCancelButton(GtkWidget* widget) {
+  if (delegate_->AsConfirmInfoBarDelegate()->Cancel())
+    RemoveInfoBar();
+}
+
+void ConfirmInfoBar::OnOkButton(GtkWidget* widget) {
+  if (delegate_->AsConfirmInfoBarDelegate()->Accept())
+    RemoveInfoBar();
+}
+
+void ConfirmInfoBar::OnLinkClicked(GtkWidget* widget) {
+  if (delegate_->AsConfirmInfoBarDelegate()->LinkClicked(
+          gtk_util::DispositionForCurrentButtonPressEvent())) {
+    RemoveInfoBar();
+  }
+}
+
+InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
+  return new LinkInfoBar(this);
+}
+
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
+  return new ConfirmInfoBar(this);
+}
diff --git a/chrome/browser/ui/gtk/infobars/infobar_gtk.h b/chrome/browser/ui/gtk/infobars/infobar_gtk.h
new file mode 100644
index 0000000..e84c236
--- /dev/null
+++ b/chrome/browser/ui/gtk/infobars/infobar_gtk.h
@@ -0,0 +1,139 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/ui/gtk/infobars/infobar_arrow_model.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class CustomDrawButton;
+class GtkThemeProvider;
+class InfoBarContainerGtk;
+class InfoBarDelegate;
+
+class InfoBar : public SlideAnimatorGtk::Delegate,
+                public NotificationObserver,
+                public InfoBarArrowModel::Observer {
+ public:
+  explicit InfoBar(InfoBarDelegate* delegate);
+  virtual ~InfoBar();
+
+  InfoBarDelegate* delegate() const { return delegate_; }
+
+  // Get the top level native GTK widget for this infobar.
+  GtkWidget* widget();
+
+  // Set a link to the parent InfoBarContainer. This must be set before the
+  // InfoBar is added to the view hierarchy.
+  void set_container(InfoBarContainerGtk* container) { container_ = container; }
+
+  // Starts animating the InfoBar open.
+  void AnimateOpen();
+
+  // Opens the InfoBar immediately.
+  void Open();
+
+  // Starts animating the InfoBar closed. It will not be closed until the
+  // animation has completed, when |Close| will be called.
+  void AnimateClose();
+
+  // Closes the InfoBar immediately and removes it from its container. Notifies
+  // the delegate that it has closed. The InfoBar is deleted after this function
+  // is called.
+  void Close();
+
+  // Returns true if the infobar is showing the its open or close animation.
+  bool IsAnimating();
+
+  // Returns true if the infobar is showing the close animation.
+  bool IsClosing();
+
+  void SetThemeProvider(GtkThemeProvider* theme_provider);
+
+  // Show an arrow that originates from another infobar (i.e. a bar was added
+  // below this one). If |other| is NULL, stop showing the arrow.
+  void ShowArrowFor(InfoBar* other, bool animate);
+
+  // InfoBarArrowModel::Observer implementation.
+  virtual void PaintStateChanged();
+
+  // SlideAnimatorGtk::Delegate implementation.
+  virtual void Closed();
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Retrieves the component colors for the infobar's background
+  // gradient. (This varies by infobars and can be animated to change).
+  virtual void GetTopColor(InfoBarDelegate::Type type,
+                           double* r, double* g, double *b);
+  virtual void GetBottomColor(InfoBarDelegate::Type type,
+                              double* r, double* g, double *b);
+
+  // The total height of the info bar.
+  static const int kInfoBarHeight;
+
+ protected:
+  // Removes our associated InfoBarDelegate from the associated TabContents.
+  // (Will lead to this InfoBar being closed).
+  void RemoveInfoBar() const;
+
+  // Adds |display_text| to the infobar. If |link_text| is not empty, it is
+  // rendered as a hyperlink and inserted into |display_text| at |link_offset|,
+  // or right aligned in the infobar if |link_offset| is |npos|. If a link is
+  // supplied, |link_callback| must not be null. It will be invoked on click.
+  void AddLabelWithInlineLink(const string16& display_text,
+                              const string16& link_text,
+                              size_t link_offset,
+                              GCallback callback);
+
+  // The top level widget of the infobar.
+  scoped_ptr<SlideAnimatorGtk> slide_widget_;
+
+  // The second highest widget in the hierarchy (after the slide widget).
+  GtkWidget* bg_box_;
+
+  // The hbox that holds infobar elements (button, text, icon, etc.).
+  GtkWidget* hbox_;
+
+  // The x that closes the bar.
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  // The InfoBar's container
+  InfoBarContainerGtk* container_;
+
+  // The InfoBar's delegate.
+  InfoBarDelegate* delegate_;
+
+  // The theme provider, used for getting border colors.
+  GtkThemeProvider* theme_provider_;
+
+  // The model that tracks the paint state of the arrow for the infobar
+  // below this one (if it exists).
+  InfoBarArrowModel arrow_model_;
+
+  NotificationRegistrar registrar_;
+
+ private:
+  CHROMEGTK_CALLBACK_0(InfoBar, void, OnCloseButton);
+  CHROMEGTK_CALLBACK_1(InfoBar, gboolean, OnBackgroundExpose, GdkEventExpose*);
+
+  void UpdateBorderColor();
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_INFOBARS_INFOBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/instant_confirm_dialog_gtk.cc b/chrome/browser/ui/gtk/instant_confirm_dialog_gtk.cc
new file mode 100644
index 0000000..446428c
--- /dev/null
+++ b/chrome/browser/ui/gtk/instant_confirm_dialog_gtk.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/instant_confirm_dialog_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/instant/instant_confirm_dialog.h"
+#include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/options/show_options_url.h"
+#include "googleurl/src/gurl.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace browser {
+
+void ShowInstantConfirmDialog(GtkWindow* parent, Profile* profile) {
+  new InstantConfirmDialogGtk(parent, profile);
+}
+
+}  // namespace browser
+
+InstantConfirmDialogGtk::InstantConfirmDialogGtk(
+    GtkWindow* parent, Profile* profile) : profile_(profile) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_INSTANT_OPT_IN_TITLE).c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+      NULL);
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+
+  GtkBox* vbox = GTK_BOX(GTK_DIALOG(dialog_)->vbox);
+  gtk_box_set_spacing(vbox, gtk_util::kControlSpacing);
+
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_INSTANT_OPT_IN_MESSAGE).c_str());
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_box_pack_start(vbox, label, FALSE, FALSE, 0);
+
+  GtkWidget* link_button = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_LEARN_MORE_LABEL).c_str());
+  g_signal_connect(link_button, "clicked",
+                   G_CALLBACK(OnLinkButtonClickedThunk), this);
+
+  GtkWidget* action_area = GTK_DIALOG(dialog_)->action_area;
+  gtk_container_add(GTK_CONTAINER(action_area), link_button);
+  gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(action_area),
+                                     link_button,
+                                     TRUE);
+
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
+  gtk_widget_show_all(dialog_);
+}
+
+InstantConfirmDialogGtk::~InstantConfirmDialogGtk() {
+  gtk_widget_destroy(dialog_);
+}
+
+void InstantConfirmDialogGtk::OnDialogResponse(GtkWidget* dialog,
+                                               int response) {
+  if (response == GTK_RESPONSE_ACCEPT)
+    InstantController::Enable(profile_);
+
+  delete this;
+}
+
+void InstantConfirmDialogGtk::OnLinkButtonClicked(GtkWidget* button) {
+  browser::ShowOptionsURL(profile_, browser::InstantLearnMoreURL());
+}
diff --git a/chrome/browser/ui/gtk/instant_confirm_dialog_gtk.h b/chrome/browser/ui/gtk/instant_confirm_dialog_gtk.h
new file mode 100644
index 0000000..8ef0653
--- /dev/null
+++ b/chrome/browser/ui/gtk/instant_confirm_dialog_gtk.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_INSTANT_CONFIRM_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_INSTANT_CONFIRM_DIALOG_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Profile;
+typedef struct _GtkWindow GtkWindow;
+
+// A dialog that explains some of the privacy implications surrounding instant.
+// Shown when the user enables instant for the first time.
+class InstantConfirmDialogGtk {
+ public:
+  InstantConfirmDialogGtk(GtkWindow* parent, Profile* profile);
+  ~InstantConfirmDialogGtk();
+
+ private:
+  CHROMEGTK_CALLBACK_1(InstantConfirmDialogGtk, void, OnDialogResponse, int);
+  CHROMEGTK_CALLBACK_0(InstantConfirmDialogGtk, void, OnLinkButtonClicked);
+
+  GtkWidget* dialog_;
+  Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(InstantConfirmDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_INSTANT_CONFIRM_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/js_modal_dialog_gtk.cc b/chrome/browser/ui/gtk/js_modal_dialog_gtk.cc
new file mode 100644
index 0000000..8d577bc
--- /dev/null
+++ b/chrome/browser/ui/gtk/js_modal_dialog_gtk.cc
@@ -0,0 +1,224 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/js_modal_dialog_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
+
+namespace {
+
+// We stash pointers to widgets on the gtk_dialog so we can refer to them
+// after dialog creation.
+const char kPromptTextId[] = "chrome_prompt_text";
+const char kSuppressCheckboxId[] = "chrome_suppress_checkbox";
+
+// If there's a text entry in the dialog, get the text from the first one and
+// return it.
+std::wstring GetPromptText(GtkDialog* dialog) {
+  GtkWidget* widget = static_cast<GtkWidget*>(
+      g_object_get_data(G_OBJECT(dialog), kPromptTextId));
+  if (widget)
+    return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(widget)));
+  return std::wstring();
+}
+
+// If there's a toggle button in the dialog, return the toggled state.
+// Otherwise, return false.
+bool ShouldSuppressJSDialogs(GtkDialog* dialog) {
+  GtkWidget* widget = static_cast<GtkWidget*>(
+      g_object_get_data(G_OBJECT(dialog), kSuppressCheckboxId));
+  if (widget)
+    return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  return false;
+}
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// JSModalDialogGtk, public:
+
+JSModalDialogGtk::JSModalDialogGtk(JavaScriptAppModalDialog* dialog,
+                                   gfx::NativeWindow parent_window)
+    : dialog_(dialog) {
+  GtkButtonsType buttons = GTK_BUTTONS_NONE;
+  GtkMessageType message_type = GTK_MESSAGE_OTHER;
+
+  // We add in the OK button manually later because we want to focus it
+  // explicitly.
+  switch (dialog_->dialog_flags()) {
+    case ui::MessageBoxFlags::kIsJavascriptAlert:
+      buttons = GTK_BUTTONS_NONE;
+      message_type = GTK_MESSAGE_WARNING;
+      break;
+
+    case ui::MessageBoxFlags::kIsJavascriptConfirm:
+      if (dialog_->is_before_unload_dialog()) {
+        // onbeforeunload also uses a confirm prompt, it just has custom
+        // buttons.  We add the buttons using gtk_dialog_add_button below.
+        buttons = GTK_BUTTONS_NONE;
+      } else {
+        buttons = GTK_BUTTONS_CANCEL;
+      }
+      message_type = GTK_MESSAGE_QUESTION;
+      break;
+
+    case ui::MessageBoxFlags::kIsJavascriptPrompt:
+      buttons = GTK_BUTTONS_CANCEL;
+      message_type = GTK_MESSAGE_QUESTION;
+      break;
+
+    default:
+      NOTREACHED();
+  }
+
+  // We want the alert to be app modal so put all the browser windows into the
+  // same window group.
+  gtk_util::MakeAppModalWindowGroup();
+
+  gtk_dialog_ = gtk_message_dialog_new(parent_window,
+      GTK_DIALOG_MODAL, message_type, buttons, "%s",
+      WideToUTF8(dialog_->message_text()).c_str());
+  gtk_util::ApplyMessageDialogQuirks(gtk_dialog_);
+  gtk_window_set_title(GTK_WINDOW(gtk_dialog_),
+                       WideToUTF8(dialog_->title()).c_str());
+
+  // Adjust content area as needed.  Set up the prompt text entry or
+  // suppression check box.
+  if (ui::MessageBoxFlags::kIsJavascriptPrompt == dialog_->dialog_flags()) {
+    // TODO(tc): Replace with gtk_dialog_get_content_area() when using GTK 2.14+
+    GtkWidget* contents_vbox = GTK_DIALOG(gtk_dialog_)->vbox;
+    GtkWidget* text_box = gtk_entry_new();
+    gtk_entry_set_text(GTK_ENTRY(text_box),
+        WideToUTF8(dialog_->default_prompt_text()).c_str());
+    gtk_box_pack_start(GTK_BOX(contents_vbox), text_box, TRUE, TRUE, 0);
+    g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
+    gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
+  }
+
+  if (dialog_->display_suppress_checkbox()) {
+    GtkWidget* contents_vbox = GTK_DIALOG(gtk_dialog_)->vbox;
+    GtkWidget* check_box = gtk_check_button_new_with_label(
+        l10n_util::GetStringUTF8(
+        IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION).c_str());
+    gtk_box_pack_start(GTK_BOX(contents_vbox), check_box, TRUE, TRUE, 0);
+    g_object_set_data(G_OBJECT(gtk_dialog_), kSuppressCheckboxId, check_box);
+  }
+
+  // Adjust buttons/action area as needed.
+  if (dialog_->is_before_unload_dialog()) {
+    std::string button_text = l10n_util::GetStringUTF8(
+      IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL);
+    gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), button_text.c_str(),
+        GTK_RESPONSE_OK);
+
+    button_text = l10n_util::GetStringUTF8(
+        IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL);
+    gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), button_text.c_str(),
+        GTK_RESPONSE_CANCEL);
+  } else {
+    // Add the OK button and focus it.
+    GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
+        GTK_STOCK_OK, GTK_RESPONSE_OK);
+    if (ui::MessageBoxFlags::kIsJavascriptPrompt != dialog_->dialog_flags())
+      gtk_widget_grab_focus(ok_button);
+  }
+
+  gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
+  g_signal_connect(gtk_dialog_, "response",
+                   G_CALLBACK(OnDialogResponseThunk), this);
+}
+
+JSModalDialogGtk::~JSModalDialogGtk() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// JSModalDialogGtk, NativeAppModalDialog implementation:
+
+int JSModalDialogGtk::GetAppModalDialogButtons() const {
+  switch (dialog_->dialog_flags()) {
+    case ui::MessageBoxFlags::kIsJavascriptAlert:
+      return ui::MessageBoxFlags::DIALOGBUTTON_OK;
+
+    case ui::MessageBoxFlags::kIsJavascriptConfirm:
+      return ui::MessageBoxFlags::DIALOGBUTTON_OK |
+        ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
+
+    case ui::MessageBoxFlags::kIsJavascriptPrompt:
+      return ui::MessageBoxFlags::DIALOGBUTTON_OK;
+
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
+void JSModalDialogGtk::ShowAppModalDialog() {
+  gtk_util::ShowModalDialogWithMinLocalizedWidth(GTK_WIDGET(gtk_dialog_),
+      IDS_ALERT_DIALOG_WIDTH_CHARS);
+}
+
+void JSModalDialogGtk::ActivateAppModalDialog() {
+  DCHECK(gtk_dialog_);
+  gtk_window_present(GTK_WINDOW(gtk_dialog_));}
+
+void JSModalDialogGtk::CloseAppModalDialog() {
+  DCHECK(gtk_dialog_);
+  OnDialogResponse(gtk_dialog_, GTK_RESPONSE_DELETE_EVENT);
+}
+
+void JSModalDialogGtk::AcceptAppModalDialog() {
+  OnDialogResponse(gtk_dialog_, GTK_RESPONSE_OK);
+}
+
+void JSModalDialogGtk::CancelAppModalDialog() {
+  OnDialogResponse(gtk_dialog_, GTK_RESPONSE_CANCEL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// JSModalDialogGtk, private:
+
+void JSModalDialogGtk::OnDialogResponse(GtkWidget* dialog,
+                                        int response_id) {
+  switch (response_id) {
+    case GTK_RESPONSE_OK:
+      // The first arg is the prompt text and the second is true if we want to
+      // suppress additional popups from the page.
+      dialog_->OnAccept(GetPromptText(GTK_DIALOG(dialog)),
+                        ShouldSuppressJSDialogs(GTK_DIALOG(dialog)));
+      break;
+
+    case GTK_RESPONSE_CANCEL:
+    case GTK_RESPONSE_DELETE_EVENT:   // User hit the X on the dialog.
+      dialog_->OnCancel(ShouldSuppressJSDialogs(GTK_DIALOG(dialog)));
+      break;
+
+    default:
+      NOTREACHED();
+  }
+  gtk_widget_destroy(GTK_WIDGET(dialog));
+
+  // Now that the dialog is gone, we can put all the  windows into separate
+  // window groups so other dialogs are no longer app modal.
+  gtk_util::AppModalDismissedUngroupWindows();
+  delete this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeAppModalDialog, public:
+
+// static
+NativeAppModalDialog* NativeAppModalDialog::CreateNativeJavaScriptPrompt(
+    JavaScriptAppModalDialog* dialog,
+    gfx::NativeWindow parent_window) {
+  return new JSModalDialogGtk(dialog, parent_window);
+}
diff --git a/chrome/browser/ui/gtk/js_modal_dialog_gtk.h b/chrome/browser/ui/gtk/js_modal_dialog_gtk.h
new file mode 100644
index 0000000..5626651
--- /dev/null
+++ b/chrome/browser/ui/gtk/js_modal_dialog_gtk.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_JS_MODAL_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_JS_MODAL_DIALOG_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/native_widget_types.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class JavaScriptAppModalDialog;
+
+class JSModalDialogGtk : public NativeAppModalDialog {
+ public:
+  JSModalDialogGtk(JavaScriptAppModalDialog* dialog,
+                   gfx::NativeWindow parent_window);
+  virtual ~JSModalDialogGtk();
+
+  // Overridden from NativeAppModalDialog:
+  virtual int GetAppModalDialogButtons() const;
+  virtual void ShowAppModalDialog();
+  virtual void ActivateAppModalDialog();
+  virtual void CloseAppModalDialog();
+  virtual void AcceptAppModalDialog();
+  virtual void CancelAppModalDialog();
+
+ private:
+  CHROMEGTK_CALLBACK_1(JSModalDialogGtk, void, OnDialogResponse, int);
+
+  scoped_ptr<JavaScriptAppModalDialog> dialog_;
+  GtkWidget* gtk_dialog_;
+
+  DISALLOW_COPY_AND_ASSIGN(JSModalDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_JS_MODAL_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/keyword_editor_view.cc b/chrome/browser/ui/gtk/keyword_editor_view.cc
new file mode 100644
index 0000000..608f9c7
--- /dev/null
+++ b/chrome/browser/ui/gtk/keyword_editor_view.cc
@@ -0,0 +1,502 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/keyword_editor_view.h"
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/keyword_editor_controller.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/template_url_table_model.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/edit_search_engine_dialog.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// How many rows should be added to an index into the |table_model_| to get the
+// corresponding row in |list_store_|
+const int kFirstGroupRowOffset = 2;
+const int kSecondGroupRowOffset = 5;
+
+KeywordEditorView* instance_ = NULL;
+
+}  // namespace
+
+// static
+void KeywordEditorView::Show(Profile* profile) {
+  DCHECK(profile);
+  // If this panel is opened from an Incognito window, closing that window can
+  // leave this with a stale pointer. Use the original profile instead.
+  // See http://crbug.com/23359.
+  profile = profile->GetOriginalProfile();
+  if (!profile->GetTemplateURLModel())
+    return;
+
+  // If there's already an existing editor window, activate it.
+  if (instance_) {
+    gtk_util::PresentWindow(instance_->dialog_, 0);
+  } else {
+    instance_ = new KeywordEditorView(profile);
+    gtk_util::ShowDialogWithLocalizedSize(instance_->dialog_,
+        IDS_SEARCHENGINES_DIALOG_WIDTH_CHARS,
+        IDS_SEARCHENGINES_DIALOG_HEIGHT_LINES,
+        true);
+  }
+}
+
+void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url,
+                                        const string16& title,
+                                        const string16& keyword,
+                                        const std::string& url) {
+  if (template_url) {
+    controller_->ModifyTemplateURL(template_url, title, keyword, url);
+
+    // Force the make default button to update.
+    EnableControls();
+  } else {
+    SelectModelRow(controller_->AddTemplateURL(title, keyword, url));
+  }
+}
+
+KeywordEditorView::~KeywordEditorView() {
+  controller_->url_model()->RemoveObserver(this);
+}
+
+KeywordEditorView::KeywordEditorView(Profile* profile)
+    : profile_(profile),
+      controller_(new KeywordEditorController(profile)),
+      table_model_(controller_->table_model()) {
+  Init();
+}
+
+void KeywordEditorView::Init() {
+  std::string dialog_name =
+      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE);
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      NULL,
+      // Non-modal.
+      GTK_DIALOG_NO_SEPARATOR,
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile_));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_box_pack_start(GTK_BOX(hbox), scroll_window, TRUE, TRUE, 0);
+
+  list_store_ = gtk_list_store_new(COL_COUNT,
+                                   GDK_TYPE_PIXBUF,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_INT,
+                                   G_TYPE_BOOLEAN);
+  tree_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_));
+  g_object_unref(list_store_);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), TRUE);
+  gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(tree_),
+                                       OnCheckRowIsSeparator,
+                                       NULL, NULL);
+  g_signal_connect(tree_, "row-activated",
+                   G_CALLBACK(OnRowActivated), this);
+  gtk_container_add(GTK_CONTAINER(scroll_window), tree_);
+
+  GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
+  GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
+  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
+                                     COL_FAVICON);
+  GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
+  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
+                                     COL_TITLE);
+  gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight",
+                                     COL_WEIGHT);
+  gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight-set",
+                                     COL_WEIGHT_SET);
+  gtk_tree_view_column_set_title(
+      title_column, l10n_util::GetStringUTF8(
+          IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN).c_str());
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), title_column);
+
+  GtkTreeViewColumn* keyword_column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(
+          IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_KEYWORD,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), keyword_column);
+
+  selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_));
+  gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE);
+  gtk_tree_selection_set_select_function(selection_, OnSelectionFilter,
+                                         NULL, NULL);
+  g_signal_connect(selection_, "changed",
+                   G_CALLBACK(OnSelectionChanged), this);
+
+  GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0);
+
+  add_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(
+              IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON)).c_str());
+  g_signal_connect(add_button_, "clicked",
+                   G_CALLBACK(OnAddButtonClicked), this);
+  gtk_box_pack_start(GTK_BOX(button_box), add_button_, FALSE, FALSE, 0);
+
+  edit_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON).c_str());
+  g_signal_connect(edit_button_, "clicked",
+                   G_CALLBACK(OnEditButtonClicked), this);
+  gtk_box_pack_start(GTK_BOX(button_box), edit_button_, FALSE, FALSE, 0);
+
+  remove_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(
+              IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON)).c_str());
+  g_signal_connect(remove_button_, "clicked",
+                   G_CALLBACK(OnRemoveButtonClicked), this);
+  gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0);
+
+  make_default_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(
+          IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON).c_str());
+  g_signal_connect(make_default_button_, "clicked",
+                   G_CALLBACK(OnMakeDefaultButtonClicked), this);
+  gtk_box_pack_start(GTK_BOX(button_box), make_default_button_, FALSE, FALSE,
+                     0);
+
+  controller_->url_model()->AddObserver(this);
+  table_model_->SetObserver(this);
+  table_model_->Reload();
+
+  EnableControls();
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
+}
+
+void KeywordEditorView::EnableControls() {
+  bool can_edit = false;
+  bool can_make_default = false;
+  bool can_remove = false;
+  int model_row = GetSelectedModelRow();
+  if (model_row != -1) {
+    const TemplateURL* selected_url = controller_->GetTemplateURL(model_row);
+    can_edit = controller_->CanEdit(selected_url);
+    can_make_default = controller_->CanMakeDefault(selected_url);
+    can_remove = controller_->CanRemove(selected_url);
+  }
+  gtk_widget_set_sensitive(add_button_, controller_->loaded());
+  gtk_widget_set_sensitive(edit_button_, can_edit);
+  gtk_widget_set_sensitive(remove_button_, can_remove);
+  gtk_widget_set_sensitive(make_default_button_, can_make_default);
+}
+
+void KeywordEditorView::SetColumnValues(int model_row, GtkTreeIter* iter) {
+  SkBitmap bitmap = table_model_->GetIcon(model_row);
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
+  gtk_list_store_set(
+      list_store_, iter,
+      COL_FAVICON, pixbuf,
+      // Dunno why, even with COL_WEIGHT_SET to FALSE here, the weight still
+      // has an effect.  So we just set it to normal.
+      COL_WEIGHT, PANGO_WEIGHT_NORMAL,
+      COL_WEIGHT_SET, TRUE,
+      COL_TITLE, UTF16ToUTF8(table_model_->GetText(
+          model_row, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)).c_str(),
+      COL_KEYWORD, UTF16ToUTF8(table_model_->GetText(
+          model_row, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN)).c_str(),
+      -1);
+  g_object_unref(pixbuf);
+}
+
+int KeywordEditorView::GetListStoreRowForModelRow(int model_row) const {
+  if (model_row < model_second_group_index_)
+    return model_row + kFirstGroupRowOffset;
+  else
+    return model_row + kSecondGroupRowOffset;
+}
+
+int KeywordEditorView::GetModelRowForPath(GtkTreePath* path) const {
+  gint* indices = gtk_tree_path_get_indices(path);
+  if (!indices) {
+    NOTREACHED();
+    return -1;
+  }
+  if (indices[0] >= model_second_group_index_ + kSecondGroupRowOffset)
+    return indices[0] - kSecondGroupRowOffset;
+  return indices[0] - kFirstGroupRowOffset;
+}
+
+int KeywordEditorView::GetModelRowForIter(GtkTreeIter* iter) const {
+  GtkTreePath* path = gtk_tree_model_get_path(GTK_TREE_MODEL(list_store_),
+                                              iter);
+  int model_row = GetModelRowForPath(path);
+  gtk_tree_path_free(path);
+  return model_row;
+}
+
+int KeywordEditorView::GetSelectedModelRow() const {
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(selection_, NULL, &iter))
+    return -1;
+  return GetModelRowForIter(&iter);
+}
+
+void KeywordEditorView::SelectModelRow(int model_row) {
+  int row = GetListStoreRowForModelRow(model_row);
+  gtk_tree::SelectAndFocusRowNum(row, GTK_TREE_VIEW(tree_));
+}
+
+void KeywordEditorView::AddNodeToList(int model_row) {
+  GtkTreeIter iter;
+  int row = GetListStoreRowForModelRow(model_row);
+  if (row == 0) {
+    gtk_list_store_prepend(list_store_, &iter);
+  } else {
+    GtkTreeIter sibling;
+    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling,
+                                  NULL, row - 1);
+    gtk_list_store_insert_after(list_store_, &iter, &sibling);
+  }
+
+  SetColumnValues(model_row, &iter);
+}
+
+void KeywordEditorView::OnModelChanged() {
+  model_second_group_index_ = table_model_->last_search_engine_index();
+  gtk_list_store_clear(list_store_);
+
+  ui::TableModel::Groups groups(table_model_->GetGroups());
+  if (groups.size() != 2) {
+    NOTREACHED();
+    return;
+  }
+
+  GtkTreeIter iter;
+  // First group title.
+  gtk_list_store_append(list_store_, &iter);
+  gtk_list_store_set(
+      list_store_, &iter,
+      COL_WEIGHT, PANGO_WEIGHT_BOLD,
+      COL_WEIGHT_SET, TRUE,
+      COL_TITLE, UTF16ToUTF8(groups[0].title).c_str(),
+      COL_IS_HEADER, TRUE,
+      -1);
+  // First group separator.
+  gtk_list_store_append(list_store_, &iter);
+  gtk_list_store_set(
+      list_store_, &iter,
+      COL_IS_HEADER, TRUE,
+      COL_IS_SEPARATOR, TRUE,
+      -1);
+
+  // Blank row between groups.
+  gtk_list_store_append(list_store_, &iter);
+  gtk_list_store_set(
+      list_store_, &iter,
+      COL_IS_HEADER, TRUE,
+      -1);
+  // Second group title.
+  gtk_list_store_append(list_store_, &iter);
+  gtk_list_store_set(
+      list_store_, &iter,
+      COL_WEIGHT, PANGO_WEIGHT_BOLD,
+      COL_WEIGHT_SET, TRUE,
+      COL_TITLE, UTF16ToUTF8(groups[1].title).c_str(),
+      COL_IS_HEADER, TRUE,
+      -1);
+  // Second group separator.
+  gtk_list_store_append(list_store_, &iter);
+  gtk_list_store_set(
+      list_store_, &iter,
+      COL_IS_HEADER, TRUE,
+      COL_IS_SEPARATOR, TRUE,
+      -1);
+
+  for (int i = 0; i < table_model_->RowCount(); ++i)
+    AddNodeToList(i);
+}
+
+void KeywordEditorView::OnItemsChanged(int start, int length) {
+  DCHECK(model_second_group_index_ == table_model_->last_search_engine_index());
+  GtkTreeIter iter;
+  for (int i = 0; i < length; ++i) {
+    int row = GetListStoreRowForModelRow(start + i);
+    bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
+        &iter, NULL, row);
+    if (!rv) {
+      NOTREACHED();
+      return;
+    }
+    SetColumnValues(start + i, &iter);
+    rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
+  }
+}
+
+void KeywordEditorView::OnItemsAdded(int start, int length) {
+  model_second_group_index_ = table_model_->last_search_engine_index();
+  for (int i = 0; i < length; ++i) {
+    AddNodeToList(start + i);
+  }
+}
+
+void KeywordEditorView::OnItemsRemoved(int start, int length) {
+  // This is quite likely not correct with removing multiple in one call, but
+  // that shouldn't happen since we only can select and modify/remove one at a
+  // time.
+  DCHECK_EQ(length, 1);
+  for (int i = 0; i < length; ++i) {
+    int row = GetListStoreRowForModelRow(start + i);
+    GtkTreeIter iter;
+    if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter,
+                                       NULL, row)) {
+      NOTREACHED();
+      return;
+    }
+    gtk_list_store_remove(list_store_, &iter);
+  }
+  model_second_group_index_ = table_model_->last_search_engine_index();
+}
+
+void KeywordEditorView::OnTemplateURLModelChanged() {
+  EnableControls();
+}
+
+// static
+void KeywordEditorView::OnWindowDestroy(GtkWidget* widget,
+                                        KeywordEditorView* window) {
+  instance_ = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
+}
+
+// static
+void KeywordEditorView::OnResponse(GtkDialog* dialog, int response_id,
+                                   KeywordEditorView* window) {
+  gtk_widget_destroy(window->dialog_);
+}
+
+// static
+gboolean KeywordEditorView::OnCheckRowIsSeparator(GtkTreeModel* model,
+                                                  GtkTreeIter* iter,
+                                                  gpointer user_data) {
+  gboolean is_separator;
+  gtk_tree_model_get(model, iter, COL_IS_SEPARATOR, &is_separator, -1);
+  return is_separator;
+}
+
+// static
+gboolean KeywordEditorView::OnSelectionFilter(GtkTreeSelection* selection,
+                                              GtkTreeModel* model,
+                                              GtkTreePath* path,
+                                              gboolean path_currently_selected,
+                                              gpointer user_data) {
+  GtkTreeIter iter;
+  if (!gtk_tree_model_get_iter(model, &iter, path)) {
+    NOTREACHED();
+    return TRUE;
+  }
+  gboolean is_header;
+  gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1);
+  return !is_header;
+}
+
+// static
+void KeywordEditorView::OnSelectionChanged(
+    GtkTreeSelection* selection, KeywordEditorView* editor) {
+  editor->EnableControls();
+}
+
+// static
+void KeywordEditorView::OnRowActivated(GtkTreeView* tree_view,
+                                       GtkTreePath* path,
+                                       GtkTreeViewColumn* column,
+                                       KeywordEditorView* editor) {
+  OnEditButtonClicked(NULL, editor);
+}
+
+// static
+void KeywordEditorView::OnAddButtonClicked(GtkButton* button,
+                                           KeywordEditorView* editor) {
+  new EditSearchEngineDialog(
+      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(
+          gtk_util::GetDialogWindow(editor->dialog_)))),
+      NULL,
+      editor,
+      editor->profile_);
+}
+
+// static
+void KeywordEditorView::OnEditButtonClicked(GtkButton* button,
+                                            KeywordEditorView* editor) {
+  int model_row = editor->GetSelectedModelRow();
+  if (model_row == -1)
+    return;
+
+  new EditSearchEngineDialog(
+      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(
+          gtk_util::GetDialogWindow(editor->dialog_)))),
+      editor->controller_->GetTemplateURL(model_row),
+      editor,
+      editor->profile_);
+}
+
+// static
+void KeywordEditorView::OnRemoveButtonClicked(GtkButton* button,
+                                              KeywordEditorView* editor) {
+  int model_row = editor->GetSelectedModelRow();
+  if (model_row == -1) {
+    NOTREACHED();
+    return;
+  }
+  editor->controller_->RemoveTemplateURL(model_row);
+  if (model_row >= editor->table_model_->RowCount())
+    model_row = editor->table_model_->RowCount() - 1;
+  if (model_row >= 0)
+    editor->SelectModelRow(model_row);
+}
+
+// static
+void KeywordEditorView::OnMakeDefaultButtonClicked(GtkButton* button,
+                                                   KeywordEditorView* editor) {
+  int model_row = editor->GetSelectedModelRow();
+  if (model_row == -1) {
+    NOTREACHED();
+    return;
+  }
+  int new_index = editor->controller_->MakeDefaultTemplateURL(model_row);
+  if (new_index > 0) {
+    editor->SelectModelRow(new_index);
+  }
+}
diff --git a/chrome/browser/ui/gtk/keyword_editor_view.h b/chrome/browser/ui/gtk/keyword_editor_view.h
new file mode 100644
index 0000000..9a08c67
--- /dev/null
+++ b/chrome/browser/ui/gtk/keyword_editor_view.h
@@ -0,0 +1,167 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_KEYWORD_EDITOR_VIEW_H_
+#define CHROME_BROWSER_UI_GTK_KEYWORD_EDITOR_VIEW_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "chrome/browser/search_engines/edit_search_engine_controller.h"
+#include "chrome/browser/search_engines/template_url_model_observer.h"
+#include "ui/base/models/table_model_observer.h"
+
+class AccessibleWidgetHelper;
+class KeywordEditorController;
+class Profile;
+class TemplateURLTableModel;
+
+class KeywordEditorView : public ui::TableModelObserver,
+                          public TemplateURLModelObserver,
+                          public EditSearchEngineControllerDelegate {
+ public:
+  virtual ~KeywordEditorView();
+
+  // Create (if necessary) and show the keyword editor window.
+  static void Show(Profile* profile);
+
+  // Overriden from EditSearchEngineControllerDelegate.
+  virtual void OnEditedKeyword(const TemplateURL* template_url,
+                               const string16& title,
+                               const string16& keyword,
+                               const std::string& url);
+ private:
+  // Column ids for |list_store_|.
+  enum {
+    COL_FAVICON,
+    COL_TITLE,
+    COL_KEYWORD,
+    COL_IS_HEADER,
+    COL_IS_SEPARATOR,
+    COL_WEIGHT,
+    COL_WEIGHT_SET,
+    COL_COUNT,
+  };
+
+  explicit KeywordEditorView(Profile* profile);
+  void Init();
+
+  // Enable buttons based on selection state.
+  void EnableControls();
+
+  // Set the column values for |row| of |table_model_| in the |list_store_| at
+  // |iter|.
+  void SetColumnValues(int row, GtkTreeIter* iter);
+
+  // Get the row number in the GtkListStore corresponding to |model_row|.
+  int GetListStoreRowForModelRow(int model_row) const;
+
+  // Get the row number in the TemplateURLTableModel corresponding to |path|.
+  int GetModelRowForPath(GtkTreePath* path) const;
+
+  // Get the row number in the TemplateURLTableModel corresponding to |iter|.
+  int GetModelRowForIter(GtkTreeIter* iter) const;
+
+  // Get the row number in the TemplateURLTableModel of the current selection,
+  // or -1 if no row is selected.
+  int GetSelectedModelRow() const;
+
+  // Select the row in the |tree_| corresponding to |model_row|.
+  void SelectModelRow(int model_row);
+
+  // Add the values from |row| of |table_model_|.
+  void AddNodeToList(int row);
+
+  // ui::TableModelObserver implementation.
+  virtual void OnModelChanged();
+  virtual void OnItemsChanged(int start, int length);
+  virtual void OnItemsAdded(int start, int length);
+  virtual void OnItemsRemoved(int start, int length);
+
+  // TemplateURLModelObserver notification.
+  virtual void OnTemplateURLModelChanged();
+
+  // Callback for window destruction.
+  static void OnWindowDestroy(GtkWidget* widget, KeywordEditorView* window);
+
+  // Callback for dialog buttons.
+  static void OnResponse(GtkDialog* dialog, int response_id,
+                         KeywordEditorView* window);
+
+  // Callback checking whether a row should be drawn as a separator.
+  static gboolean OnCheckRowIsSeparator(GtkTreeModel* model,
+                                        GtkTreeIter* iter,
+                                        gpointer user_data);
+
+  // Callback checking whether a row may be selected.  We use some rows in the
+  // table as headers/separators for the groups, which should not be selectable.
+  static gboolean OnSelectionFilter(GtkTreeSelection* selection,
+                                    GtkTreeModel* model,
+                                    GtkTreePath* path,
+                                    gboolean path_currently_selected,
+                                    gpointer user_data);
+
+  // Callback for when user selects something.
+  static void OnSelectionChanged(GtkTreeSelection* selection,
+                                 KeywordEditorView* editor);
+
+  // Callbacks for user actions modifying the table.
+  static void OnRowActivated(GtkTreeView* tree_view,
+                             GtkTreePath* path,
+                             GtkTreeViewColumn* column,
+                             KeywordEditorView* editor);
+  static void OnAddButtonClicked(GtkButton* button,
+                                 KeywordEditorView* editor);
+  static void OnEditButtonClicked(GtkButton* button,
+                                  KeywordEditorView* editor);
+  static void OnRemoveButtonClicked(GtkButton* button,
+                                    KeywordEditorView* editor);
+  static void OnMakeDefaultButtonClicked(GtkButton* button,
+                                         KeywordEditorView* editor);
+
+  // The table listing the search engines.
+  GtkWidget* tree_;
+  GtkListStore* list_store_;
+  GtkTreeSelection* selection_;
+
+  // Buttons for acting on the table.
+  GtkWidget* add_button_;
+  GtkWidget* edit_button_;
+  GtkWidget* remove_button_;
+  GtkWidget* make_default_button_;
+
+  // The containing dialog.
+  GtkWidget* dialog_;
+
+  // The profile.
+  Profile* profile_;
+
+  scoped_ptr<KeywordEditorController> controller_;
+
+  TemplateURLTableModel* table_model_;
+
+  // We store our own index of the start of the second group within the model,
+  // as when OnItemsRemoved is called the value in the model is already updated
+  // but we need the old value to know which row to remove from the
+  // |list_store_|.
+  int model_second_group_index_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  friend class KeywordEditorViewTest;
+  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Empty);
+  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Add);
+  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, MakeDefault);
+  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Remove);
+  FRIEND_TEST_ALL_PREFIXES(KeywordEditorViewTest, Edit);
+
+  DISALLOW_COPY_AND_ASSIGN(KeywordEditorView);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_KEYWORD_EDITOR_VIEW_H_
diff --git a/chrome/browser/ui/gtk/keyword_editor_view_unittest.cc b/chrome/browser/ui/gtk/keyword_editor_view_unittest.cc
new file mode 100644
index 0000000..330634a
--- /dev/null
+++ b/chrome/browser/ui/gtk/keyword_editor_view_unittest.cc
@@ -0,0 +1,271 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/keyword_editor_view.h"
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/template_url_table_model.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class KeywordEditorViewTest : public testing::Test {
+ public:
+  virtual void SetUp() {
+    profile_.reset(new TestingProfile());
+    profile_->CreateTemplateURLModel();
+  }
+
+  TemplateURL* AddToModel(const std::string& name,
+                          const std::string& keyword,
+                          bool make_default) {
+    TemplateURL* template_url = new TemplateURL();
+    template_url->set_short_name(UTF8ToUTF16(name));
+    template_url->set_keyword(UTF8ToUTF16(keyword));
+    template_url->SetURL("http://example.com/{searchTerms}", 0, 0);
+    profile_->GetTemplateURLModel()->Add(template_url);
+    if (make_default)
+      profile_->GetTemplateURLModel()->SetDefaultSearchProvider(template_url);
+    return template_url;
+  }
+
+  int GetSelectedRowNum(const KeywordEditorView& editor) {
+    GtkTreeIter iter;
+    if (!gtk_tree_selection_get_selected(editor.selection_, NULL, &iter))
+      return -1;
+    return gtk_tree::GetRowNumForIter(GTK_TREE_MODEL(editor.list_store_),
+                                      &iter);
+  }
+
+  // Get the search engines displayed in the dialog in the order they are
+  // displayed, as a comma seperated string.
+  // The headers are included as "!,_" for the first group header and "_,@,_"
+  // for the second group header (This allows the tests to ensure the headers
+  // aren't accidentally misplaced/moved.)
+  // Ex: EXPECT_STREQ("!,_,A (Default),_,@,_,B",
+  //                  GetDisplayedEngines(editor).c_str());
+  std::string GetDisplayedEngines(const KeywordEditorView& editor) {
+    ui::TableModel::Groups groups(editor.table_model_->GetGroups());
+    std::vector<std::string> parts;
+    GtkTreeModel* tree_model = GTK_TREE_MODEL(editor.list_store_);
+    GtkTreeIter iter;
+    if (!gtk_tree_model_get_iter_first(tree_model, &iter))
+      return std::string();
+    while (true) {
+      gchar* name;
+      gboolean is_header;
+      gtk_tree_model_get(tree_model, &iter,
+                         KeywordEditorView::COL_TITLE, &name,
+                         KeywordEditorView::COL_IS_HEADER, &is_header,
+                         -1);
+      if (name && UTF16ToUTF8(groups[0].title) == name)
+        parts.push_back("!");
+      else if (name && UTF16ToUTF8(groups[1].title) == name)
+        parts.push_back("@");
+      else if (is_header)
+        parts.push_back("_");
+      else if (name)
+        parts.push_back(name);
+      else
+        parts.push_back("???");
+      if (name)
+        g_free(name);
+      if (!gtk_tree_model_iter_next(tree_model, &iter))
+        break;
+    }
+    return JoinString(parts, ',');
+  }
+
+ protected:
+  MessageLoopForUI message_loop_;
+  scoped_ptr<TestingProfile> profile_;
+};
+
+TEST_F(KeywordEditorViewTest, Empty) {
+  KeywordEditorView editor(profile_.get());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,_,@,_", GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(-1, GetSelectedRowNum(editor));
+}
+
+TEST_F(KeywordEditorViewTest, Add) {
+  AddToModel("A1", "k1", true);
+  KeywordEditorView editor(profile_.get());
+  EXPECT_STREQ("!,_,A1 (Default),_,@,_", GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(-1, GetSelectedRowNum(editor));
+
+  editor.OnEditedKeyword(NULL, ASCIIToUTF16("B"), ASCIIToUTF16("b"),
+                         "example.com");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A1 (Default),_,@,_,B", GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(6, GetSelectedRowNum(editor));
+
+  editor.OnEditedKeyword(NULL, ASCIIToUTF16("C"), ASCIIToUTF16("c"),
+                         "example.com/{searchTerms}");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A1 (Default),_,@,_,B,C",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(7, GetSelectedRowNum(editor));
+
+  editor.OnEditedKeyword(NULL, ASCIIToUTF16("D"), ASCIIToUTF16("d"),
+                         "example.com");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.edit_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A1 (Default),_,@,_,B,C,D",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(8, GetSelectedRowNum(editor));
+}
+
+TEST_F(KeywordEditorViewTest, MakeDefault) {
+  AddToModel("A", "a", true);
+  AddToModel("B", "b", false);
+  AddToModel("C", "c", false);
+  AddToModel("D", "d", false);
+  KeywordEditorView editor(profile_.get());
+  EXPECT_STREQ("!,_,A (Default),_,@,_,B,C,D",
+               GetDisplayedEngines(editor).c_str());
+
+  GtkTreeIter iter;
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
+                                &iter, NULL, 6);
+  gtk_tree_selection_select_iter(editor.selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+
+  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A,B (Default),_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(3, GetSelectedRowNum(editor));
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
+                                &iter, NULL, 8);
+  gtk_tree_selection_select_iter(editor.selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+
+  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A,B,D (Default),_,@,_,C",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(4, GetSelectedRowNum(editor));
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
+                                &iter, NULL, 2);
+  gtk_tree_selection_select_iter(editor.selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+
+  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A (Default),B,D,_,@,_,C",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(2, GetSelectedRowNum(editor));
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
+                                &iter, NULL, 4);
+  gtk_tree_selection_select_iter(editor.selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+
+  gtk_button_clicked(GTK_BUTTON(editor.make_default_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.make_default_button_));
+  EXPECT_STREQ("!,_,A,B,D (Default),_,@,_,C",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(4, GetSelectedRowNum(editor));
+}
+
+TEST_F(KeywordEditorViewTest, Remove) {
+  AddToModel("A", "a", true);
+  AddToModel("B", "b", true);
+  AddToModel("C", "c", false);
+  AddToModel("D", "d", false);
+  KeywordEditorView editor(profile_.get());
+  EXPECT_STREQ("!,_,A,B (Default),_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+
+  GtkTreeIter iter;
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
+                                &iter, NULL, 2);
+  gtk_tree_selection_select_iter(editor.selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(editor.remove_button_));
+  EXPECT_STREQ("!,_,B (Default),_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(2, GetSelectedRowNum(editor));
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(editor.list_store_),
+                                &iter, NULL, 6);
+  gtk_tree_selection_select_iter(editor.selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(editor.remove_button_));
+  EXPECT_STREQ("!,_,B (Default),_,@,_,D",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(6, GetSelectedRowNum(editor));
+
+  gtk_button_clicked(GTK_BUTTON(editor.remove_button_));
+  EXPECT_STREQ("!,_,B (Default),_,@,_",
+               GetDisplayedEngines(editor).c_str());
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(editor.remove_button_));
+  EXPECT_EQ(2, GetSelectedRowNum(editor));
+}
+
+TEST_F(KeywordEditorViewTest, Edit) {
+  TemplateURL* a = AddToModel("A", "a", true);
+  TemplateURL* b = AddToModel("B", "b", true);
+  TemplateURL* c = AddToModel("C", "c", false);
+  TemplateURL* d = AddToModel("D", "d", false);
+  KeywordEditorView editor(profile_.get());
+  EXPECT_STREQ("!,_,A,B (Default),_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+
+  editor.OnEditedKeyword(a, ASCIIToUTF16("AA"), ASCIIToUTF16("a"),
+                         "example.com/{searchTerms}");
+  EXPECT_STREQ("!,_,AA,B (Default),_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+
+  editor.OnEditedKeyword(b, ASCIIToUTF16("BB"), ASCIIToUTF16("b"),
+                         "foo.example.com/{searchTerms}");
+  EXPECT_STREQ("!,_,AA,BB (Default),_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+
+  editor.OnEditedKeyword(b, ASCIIToUTF16("BBB"), ASCIIToUTF16("b"),
+                         "example.com");
+  EXPECT_STREQ("!,_,AA,BBB,_,@,_,C,D",
+               GetDisplayedEngines(editor).c_str());
+
+  editor.OnEditedKeyword(d, ASCIIToUTF16("DD"), ASCIIToUTF16("d"),
+                         "example.com");
+  EXPECT_STREQ("!,_,AA,BBB,_,@,_,C,DD",
+               GetDisplayedEngines(editor).c_str());
+
+  editor.OnEditedKeyword(c, ASCIIToUTF16("CC"), ASCIIToUTF16("cc"),
+                         "example.com");
+  EXPECT_STREQ("!,_,AA,BBB,_,@,_,CC,DD",
+               GetDisplayedEngines(editor).c_str());
+}
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.cc b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
new file mode 100644
index 0000000..1b8859d
--- /dev/null
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
@@ -0,0 +1,1558 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/accessibility_events.h"
+#include "chrome/browser/alternate_nav_url_fetcher.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
+#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/browser/content_setting_bubble_model.h"
+#include "chrome/browser/content_setting_image_model.h"
+#include "chrome/browser/defaults.h"
+#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/bookmark_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
+#include "chrome/browser/ui/gtk/content_setting_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/extension_popup_gtk.h"
+#include "chrome/browser/ui/gtk/first_run_bubble.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/nine_box.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/browser/ui/omnibox/location_bar_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/page_transition_types.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "net/base/net_util.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/gtk_util.h"
+#include "webkit/glue/window_open_disposition.h"
+
+namespace {
+
+// We are positioned with a little bit of extra space that we don't use now.
+const int kTopMargin = 1;
+const int kBottomMargin = 1;
+const int kLeftMargin = 1;
+const int kRightMargin = 1;
+// We draw a border on the top and bottom (but not on left or right).
+const int kBorderThickness = 1;
+
+// Left margin of first run bubble.
+const int kFirstRunBubbleLeftMargin = 8;
+// Extra vertical spacing for first run bubble.
+const int kFirstRunBubbleTopMargin = 5;
+
+// The padding around the top, bottom, and sides of the location bar hbox.
+// We don't want to edit control's text to be right against the edge,
+// as well the tab to search box and other widgets need to have the padding on
+// top and bottom to avoid drawing larger than the location bar space.
+const int kHboxBorder = 2;
+
+// Padding between the elements in the bar.
+const int kInnerPadding = 2;
+
+// Padding between the right of the star and the edge of the URL entry.
+const int kStarRightPadding = 2;
+
+// Colors used to draw the EV certificate rounded bubble.
+const GdkColor kEvSecureTextColor = GDK_COLOR_RGB(0x07, 0x95, 0x00);
+const GdkColor kEvSecureBackgroundColor = GDK_COLOR_RGB(0xef, 0xfc, 0xef);
+const GdkColor kEvSecureBorderColor = GDK_COLOR_RGB(0x90, 0xc3, 0x90);
+
+// Colors used to draw the Tab to Search rounded bubble.
+const GdkColor kKeywordBackgroundColor = GDK_COLOR_RGB(0xf0, 0xf4, 0xfa);
+const GdkColor kKeywordBorderColor = GDK_COLOR_RGB(0xcb, 0xde, 0xf7);
+
+// Use weak gray for showing search and keyword hint text.
+const GdkColor kHintTextColor = GDK_COLOR_RGB(0x75, 0x75, 0x75);
+
+// Size of the rounding of the "Search site for:" box.
+const int kCornerSize = 3;
+
+// If widget is visible, increment the int pointed to by count.
+// Suitible for use with gtk_container_foreach.
+void CountVisibleWidgets(GtkWidget* widget, gpointer count) {
+  if (GTK_WIDGET_VISIBLE(widget))
+    *static_cast<int*>(count) += 1;
+}
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// LocationBarViewGtk
+
+// static
+const GdkColor LocationBarViewGtk::kBackgroundColor =
+    GDK_COLOR_RGB(255, 255, 255);
+
+LocationBarViewGtk::LocationBarViewGtk(Browser* browser)
+    : star_image_(NULL),
+      starred_(false),
+      site_type_alignment_(NULL),
+      site_type_event_box_(NULL),
+      location_icon_image_(NULL),
+      drag_icon_(NULL),
+      enable_location_drag_(false),
+      security_info_label_(NULL),
+      tab_to_search_box_(NULL),
+      tab_to_search_full_label_(NULL),
+      tab_to_search_partial_label_(NULL),
+      tab_to_search_hint_(NULL),
+      tab_to_search_hint_leading_label_(NULL),
+      tab_to_search_hint_icon_(NULL),
+      tab_to_search_hint_trailing_label_(NULL),
+      profile_(NULL),
+      command_updater_(browser->command_updater()),
+      toolbar_model_(browser->toolbar_model()),
+      browser_(browser),
+      disposition_(CURRENT_TAB),
+      transition_(PageTransition::TYPED),
+      first_run_bubble_(this),
+      popup_window_mode_(false),
+      theme_provider_(NULL),
+      hbox_width_(0),
+      entry_box_width_(0),
+      show_selected_keyword_(false),
+      show_keyword_hint_(false),
+      update_instant_(true) {
+}
+
+LocationBarViewGtk::~LocationBarViewGtk() {
+  // All of our widgets should have be children of / owned by the alignment.
+  star_.Destroy();
+  hbox_.Destroy();
+  content_setting_hbox_.Destroy();
+  page_action_hbox_.Destroy();
+}
+
+void LocationBarViewGtk::Init(bool popup_window_mode) {
+  popup_window_mode_ = popup_window_mode;
+
+  // Create the widget first, so we can pass it to the AutocompleteEditViewGtk.
+  hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
+  gtk_container_set_border_width(GTK_CONTAINER(hbox_.get()), kHboxBorder);
+  // We will paint for the alignment, to paint the background and border.
+  gtk_widget_set_app_paintable(hbox_.get(), TRUE);
+  // Redraw the whole location bar when it changes size (e.g., when toggling
+  // the home button on/off.
+  gtk_widget_set_redraw_on_allocate(hbox_.get(), TRUE);
+
+  // Now initialize the AutocompleteEditViewGtk.
+  location_entry_.reset(new AutocompleteEditViewGtk(this,
+                                                    toolbar_model_,
+                                                    profile_,
+                                                    command_updater_,
+                                                    popup_window_mode_,
+                                                    hbox_.get()));
+  location_entry_->Init();
+
+  g_signal_connect(hbox_.get(), "expose-event",
+                   G_CALLBACK(&HandleExposeThunk), this);
+
+  BuildSiteTypeArea();
+
+  // Put |tab_to_search_box_|, |location_entry_|, and |tab_to_search_hint_| into
+  // a sub hbox, so that we can make this part horizontally shrinkable without
+  // affecting other elements in the location bar.
+  entry_box_ = gtk_hbox_new(FALSE, kInnerPadding);
+  gtk_widget_show(entry_box_);
+  gtk_widget_set_size_request(entry_box_, 0, -1);
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), entry_box_, TRUE, TRUE, 0);
+
+  // We need to adjust the visibility of the search hint widgets according to
+  // the horizontal space in the |entry_box_|.
+  g_signal_connect(entry_box_, "size-allocate",
+                   G_CALLBACK(&OnEntryBoxSizeAllocateThunk), this);
+
+  // Tab to search (the keyword box on the left hand side).
+  tab_to_search_full_label_ = gtk_label_new(NULL);
+  tab_to_search_partial_label_ = gtk_label_new(NULL);
+  GtkWidget* tab_to_search_label_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox),
+                     tab_to_search_full_label_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox),
+                     tab_to_search_partial_label_, FALSE, FALSE, 0);
+  GtkWidget* tab_to_search_hbox = gtk_hbox_new(FALSE, 0);
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  tab_to_search_magnifier_ = gtk_image_new_from_pixbuf(
+      rb.GetPixbufNamed(IDR_KEYWORD_SEARCH_MAGNIFIER));
+  gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_magnifier_,
+                     FALSE, FALSE, 0);
+  gtk_util::CenterWidgetInHBox(tab_to_search_hbox, tab_to_search_label_hbox,
+                               false, 0);
+
+  // This creates a box around the keyword text with a border, background color,
+  // and padding around the text.
+  tab_to_search_box_ = gtk_util::CreateGtkBorderBin(
+      tab_to_search_hbox, NULL, 1, 1, 1, 3);
+  gtk_widget_set_name(tab_to_search_box_, "chrome-tab-to-search-box");
+  gtk_util::ActAsRoundedWindow(tab_to_search_box_, kKeywordBorderColor,
+                               kCornerSize,
+                               gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
+  // Show all children widgets of |tab_to_search_box_| initially, except
+  // |tab_to_search_partial_label_|.
+  gtk_widget_show_all(tab_to_search_box_);
+  gtk_widget_hide(tab_to_search_box_);
+  gtk_widget_hide(tab_to_search_partial_label_);
+  gtk_box_pack_start(GTK_BOX(entry_box_), tab_to_search_box_, FALSE, FALSE, 0);
+
+  location_entry_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_container_add(GTK_CONTAINER(location_entry_alignment_),
+                    location_entry_->GetNativeView());
+  gtk_box_pack_start(GTK_BOX(entry_box_), location_entry_alignment_,
+                     TRUE, TRUE, 0);
+
+  // Tab to search notification (the hint on the right hand side).
+  tab_to_search_hint_ = gtk_hbox_new(FALSE, 0);
+  gtk_widget_set_name(tab_to_search_hint_, "chrome-tab-to-search-hint");
+  tab_to_search_hint_leading_label_ = gtk_label_new(NULL);
+  gtk_widget_set_sensitive(tab_to_search_hint_leading_label_, FALSE);
+  tab_to_search_hint_icon_ = gtk_image_new_from_pixbuf(
+      rb.GetPixbufNamed(IDR_LOCATION_BAR_KEYWORD_HINT_TAB));
+  tab_to_search_hint_trailing_label_ = gtk_label_new(NULL);
+  gtk_widget_set_sensitive(tab_to_search_hint_trailing_label_, FALSE);
+  gtk_box_pack_start(GTK_BOX(tab_to_search_hint_),
+                     tab_to_search_hint_leading_label_,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tab_to_search_hint_),
+                     tab_to_search_hint_icon_,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(tab_to_search_hint_),
+                     tab_to_search_hint_trailing_label_,
+                     FALSE, FALSE, 0);
+  // Show all children widgets of |tab_to_search_hint_| initially.
+  gtk_widget_show_all(tab_to_search_hint_);
+  gtk_widget_hide(tab_to_search_hint_);
+  // tab_to_search_hint_ gets hidden initially in OnChanged.  Hiding it here
+  // doesn't work, someone is probably calling show_all on our parent box.
+  gtk_box_pack_end(GTK_BOX(entry_box_), tab_to_search_hint_, FALSE, FALSE, 0);
+
+  // We don't show the star in popups, app windows, etc.
+  if (browser_defaults::bookmarks_enabled && !ShouldOnlyShowLocation()) {
+    CreateStarButton();
+    gtk_box_pack_end(GTK_BOX(hbox_.get()), star_.get(), FALSE, FALSE, 0);
+  }
+
+  content_setting_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding + 1));
+  gtk_widget_set_name(content_setting_hbox_.get(),
+                      "chrome-content-setting-hbox");
+  gtk_box_pack_end(GTK_BOX(hbox_.get()), content_setting_hbox_.get(),
+                   FALSE, FALSE, 1);
+
+  for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+    ContentSettingImageViewGtk* content_setting_view =
+        new ContentSettingImageViewGtk(
+            static_cast<ContentSettingsType>(i), this, profile_);
+    content_setting_views_.push_back(content_setting_view);
+    gtk_box_pack_end(GTK_BOX(content_setting_hbox_.get()),
+                     content_setting_view->widget(), FALSE, FALSE, 0);
+  }
+
+  page_action_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
+  gtk_widget_set_name(page_action_hbox_.get(),
+                      "chrome-page-action-hbox");
+  gtk_box_pack_end(GTK_BOX(hbox_.get()), page_action_hbox_.get(),
+                   FALSE, FALSE, 0);
+
+  // Now that we've created the widget hierarchy, connect to the main |hbox_|'s
+  // size-allocate so we can do proper resizing and eliding on
+  // |security_info_label_|.
+  g_signal_connect(hbox_.get(), "size-allocate",
+                   G_CALLBACK(&OnHboxSizeAllocateThunk), this);
+
+  registrar_.Add(this,
+                 NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  theme_provider_ = GtkThemeProvider::GetFrom(profile_);
+  theme_provider_->InitThemesFor(this);
+}
+
+void LocationBarViewGtk::BuildSiteTypeArea() {
+  location_icon_image_ = gtk_image_new();
+  gtk_widget_set_name(location_icon_image_, "chrome-location-icon");
+
+  GtkWidget* icon_alignment = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(icon_alignment), 0, 0, 2, 0);
+  gtk_container_add(GTK_CONTAINER(icon_alignment), location_icon_image_);
+  gtk_widget_show_all(icon_alignment);
+
+  security_info_label_ = gtk_label_new(NULL);
+  gtk_label_set_ellipsize(GTK_LABEL(security_info_label_),
+                          PANGO_ELLIPSIZE_MIDDLE);
+  gtk_widget_modify_fg(GTK_WIDGET(security_info_label_), GTK_STATE_NORMAL,
+                       &kEvSecureTextColor);
+  gtk_widget_set_name(security_info_label_,
+                      "chrome-location-bar-security-info-label");
+
+  GtkWidget* site_type_hbox = gtk_hbox_new(FALSE, 1);
+  gtk_box_pack_start(GTK_BOX(site_type_hbox), icon_alignment,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(site_type_hbox), security_info_label_,
+                     FALSE, FALSE, 2);
+
+  site_type_event_box_ = gtk_event_box_new();
+  gtk_widget_modify_bg(site_type_event_box_, GTK_STATE_NORMAL,
+                       &kEvSecureBackgroundColor);
+  g_signal_connect(site_type_event_box_, "drag-data-get",
+                   G_CALLBACK(&OnIconDragDataThunk), this);
+  g_signal_connect(site_type_event_box_, "drag-begin",
+                   G_CALLBACK(&OnIconDragBeginThunk), this);
+  g_signal_connect(site_type_event_box_, "drag-end",
+                   G_CALLBACK(&OnIconDragEndThunk), this);
+
+  // Make the event box not visible so it does not paint a background.
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
+                                   FALSE);
+  gtk_widget_set_name(site_type_event_box_,
+                      "chrome-location-icon-eventbox");
+  gtk_container_add(GTK_CONTAINER(site_type_event_box_),
+                    site_type_hbox);
+
+  // Put the event box in an alignment to get the padding correct.
+  site_type_alignment_ = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_),
+                            1, 1, 0, 0);
+  gtk_container_add(GTK_CONTAINER(site_type_alignment_),
+                    site_type_event_box_);
+  gtk_box_pack_start(GTK_BOX(hbox_.get()), site_type_alignment_,
+                     FALSE, FALSE, 0);
+
+  gtk_widget_set_tooltip_text(location_icon_image_,
+      l10n_util::GetStringUTF8(IDS_TOOLTIP_LOCATION_ICON).c_str());
+
+  g_signal_connect(site_type_event_box_, "button-release-event",
+                   G_CALLBACK(&OnIconReleasedThunk), this);
+}
+
+void LocationBarViewGtk::SetSiteTypeDragSource() {
+  bool enable = !location_entry()->IsEditingOrEmpty();
+  if (enable_location_drag_ == enable)
+    return;
+  enable_location_drag_ = enable;
+
+  if (!enable) {
+    gtk_drag_source_unset(site_type_event_box_);
+    return;
+  }
+
+  gtk_drag_source_set(site_type_event_box_, GDK_BUTTON1_MASK,
+                      NULL, 0, GDK_ACTION_COPY);
+  ui::SetSourceTargetListFromCodeMask(site_type_event_box_,
+                                      ui::TEXT_PLAIN |
+                                      ui::TEXT_URI_LIST |
+                                      ui::CHROME_NAMED_URL);
+}
+
+void LocationBarViewGtk::SetProfile(Profile* profile) {
+  profile_ = profile;
+}
+
+TabContents* LocationBarViewGtk::GetTabContents() const {
+  return browser_->GetSelectedTabContents();
+}
+
+void LocationBarViewGtk::SetPreviewEnabledPageAction(
+    ExtensionAction *page_action,
+    bool preview_enabled) {
+  DCHECK(page_action);
+  UpdatePageActions();
+  for (ScopedVector<PageActionViewGtk>::iterator iter =
+       page_action_views_.begin(); iter != page_action_views_.end();
+       ++iter) {
+    if ((*iter)->page_action() == page_action) {
+      (*iter)->set_preview_enabled(preview_enabled);
+      UpdatePageActions();
+      return;
+    }
+  }
+}
+
+GtkWidget* LocationBarViewGtk::GetPageActionWidget(
+    ExtensionAction *page_action) {
+  DCHECK(page_action);
+  for (ScopedVector<PageActionViewGtk>::iterator iter =
+           page_action_views_.begin();
+       iter != page_action_views_.end();
+       ++iter) {
+    if ((*iter)->page_action() == page_action)
+      return (*iter)->widget();
+  }
+  return NULL;
+}
+
+void LocationBarViewGtk::Update(const TabContents* contents) {
+  bool star_enabled = star_.get() && !toolbar_model_->input_in_progress();
+  command_updater_->UpdateCommandEnabled(IDC_BOOKMARK_PAGE, star_enabled);
+  if (star_.get()) {
+    if (star_enabled)
+      gtk_widget_show_all(star_.get());
+    else
+      gtk_widget_hide_all(star_.get());
+  }
+  UpdateSiteTypeArea();
+  UpdateContentSettingsIcons();
+  UpdatePageActions();
+  location_entry_->Update(contents);
+  // The security level (background color) could have changed, etc.
+  if (theme_provider_->UseGtkTheme()) {
+    // In GTK mode, we need our parent to redraw, as it draws the text entry
+    // border.
+    gtk_widget_queue_draw(widget()->parent);
+  } else {
+    gtk_widget_queue_draw(widget());
+  }
+}
+
+void LocationBarViewGtk::OnAutocompleteWillClosePopup() {
+  if (!update_instant_)
+    return;
+
+  InstantController* instant = browser_->instant();
+  if (instant && !instant->commit_on_mouse_up())
+    instant->DestroyPreviewContents();
+}
+
+void LocationBarViewGtk::OnAutocompleteLosingFocus(
+    gfx::NativeView view_gaining_focus) {
+  SetSuggestedText(string16());
+
+  InstantController* instant = browser_->instant();
+  if (instant)
+    instant->OnAutocompleteLostFocus(view_gaining_focus);
+}
+
+void LocationBarViewGtk::OnAutocompleteWillAccept() {
+  update_instant_ = false;
+}
+
+bool LocationBarViewGtk::OnCommitSuggestedText(bool skip_inline_autocomplete) {
+  if (!browser_->instant())
+    return false;
+
+  const string16 suggestion = location_entry_->GetInstantSuggestion();
+  if (suggestion.empty())
+    return false;
+
+  location_entry_->model()->FinalizeInstantQuery(
+      location_entry_->GetText(), suggestion, skip_inline_autocomplete);
+  return true;
+}
+
+bool LocationBarViewGtk::AcceptCurrentInstantPreview() {
+  return InstantController::CommitIfCurrent(browser_->instant());
+}
+
+void LocationBarViewGtk::OnPopupBoundsChanged(const gfx::Rect& bounds) {
+  InstantController* instant = browser_->instant();
+  if (instant)
+    instant->SetOmniboxBounds(bounds);
+}
+
+void LocationBarViewGtk::OnAutocompleteAccept(const GURL& url,
+    WindowOpenDisposition disposition,
+    PageTransition::Type transition,
+    const GURL& alternate_nav_url) {
+  if (url.is_valid()) {
+    location_input_ = UTF8ToWide(url.spec());
+    disposition_ = disposition;
+    transition_ = transition;
+
+    if (command_updater_) {
+      if (!alternate_nav_url.is_valid()) {
+        command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
+      } else {
+        AlternateNavURLFetcher* fetcher =
+            new AlternateNavURLFetcher(alternate_nav_url);
+        // The AlternateNavURLFetcher will listen for the pending navigation
+        // notification that will be issued as a result of the "open URL." It
+        // will automatically install itself into that navigation controller.
+        command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
+        if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
+          // I'm not sure this should be reachable, but I'm not also sure enough
+          // that it shouldn't to stick in a NOTREACHED().  In any case, this is
+          // harmless.
+          delete fetcher;
+        } else {
+          // The navigation controller will delete the fetcher.
+        }
+      }
+    }
+  }
+
+  if (browser_->instant() && !location_entry_->model()->popup_model()->IsOpen())
+    browser_->instant()->DestroyPreviewContents();
+
+  update_instant_ = true;
+}
+
+void LocationBarViewGtk::OnChanged() {
+  UpdateSiteTypeArea();
+
+  const string16 keyword(location_entry_->model()->keyword());
+  const bool is_keyword_hint = location_entry_->model()->is_keyword_hint();
+  show_selected_keyword_ = !keyword.empty() && !is_keyword_hint;
+  show_keyword_hint_ = !keyword.empty() && is_keyword_hint;
+
+  if (show_selected_keyword_)
+    SetKeywordLabel(keyword);
+
+  if (show_keyword_hint_)
+    SetKeywordHintLabel(keyword);
+
+  AdjustChildrenVisibility();
+
+  InstantController* instant = browser_->instant();
+  string16 suggested_text;
+  if (update_instant_ && instant && GetTabContents()) {
+    if (location_entry_->model()->user_input_in_progress() &&
+        location_entry_->model()->popup_model()->IsOpen()) {
+      instant->Update(
+          browser_->GetSelectedTabContentsWrapper(),
+          location_entry_->model()->CurrentMatch(),
+          location_entry_->GetText(),
+          location_entry_->model()->UseVerbatimInstant(),
+          &suggested_text);
+      if (!instant->MightSupportInstant()) {
+        location_entry_->model()->FinalizeInstantQuery(
+            string16(), string16(), false);
+      }
+    } else {
+      instant->DestroyPreviewContents();
+      location_entry_->model()->FinalizeInstantQuery(
+          string16(), string16(), false);
+    }
+  }
+
+  SetSuggestedText(suggested_text);
+}
+
+void LocationBarViewGtk::OnSelectionBoundsChanged() {
+  NOTIMPLEMENTED();
+}
+
+void LocationBarViewGtk::CreateStarButton() {
+  star_image_ = gtk_image_new();
+
+  GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
+                            0, kStarRightPadding);
+  gtk_container_add(GTK_CONTAINER(alignment), star_image_);
+
+  star_.Own(gtk_event_box_new());
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(star_.get()), FALSE);
+  gtk_container_add(GTK_CONTAINER(star_.get()), alignment);
+  gtk_widget_show_all(star_.get());
+  ViewIDUtil::SetID(star_.get(), VIEW_ID_STAR_BUTTON);
+
+  gtk_widget_set_tooltip_text(star_.get(),
+      l10n_util::GetStringUTF8(IDS_TOOLTIP_STAR).c_str());
+  g_signal_connect(star_.get(), "button-press-event",
+                   G_CALLBACK(OnStarButtonPressThunk), this);
+}
+
+void LocationBarViewGtk::OnInputInProgress(bool in_progress) {
+  // This is identical to the Windows code, except that we don't proxy the call
+  // back through the Toolbar, and just access the model here.
+  // The edit should make sure we're only notified when something changes.
+  DCHECK(toolbar_model_->input_in_progress() != in_progress);
+
+  toolbar_model_->set_input_in_progress(in_progress);
+  Update(NULL);
+}
+
+void LocationBarViewGtk::OnKillFocus() {
+}
+
+void LocationBarViewGtk::OnSetFocus() {
+  AccessibilityTextBoxInfo info(
+      profile_,
+      l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION).c_str(),
+      false);
+  NotificationService::current()->Notify(
+      NotificationType::ACCESSIBILITY_CONTROL_FOCUSED,
+      Source<Profile>(profile_),
+      Details<AccessibilityTextBoxInfo>(&info));
+
+  // Update the keyword and search hint states.
+  OnChanged();
+}
+
+SkBitmap LocationBarViewGtk::GetFavIcon() const {
+  return GetTabContents()->GetFavIcon();
+}
+
+string16 LocationBarViewGtk::GetTitle() const {
+  return GetTabContents()->GetTitle();
+}
+
+void LocationBarViewGtk::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {
+  // We need the browser window to be shown before we can show the bubble, but
+  // we get called before that's happened.
+  Task* task = first_run_bubble_.NewRunnableMethod(
+      &LocationBarViewGtk::ShowFirstRunBubbleInternal, bubble_type);
+  MessageLoop::current()->PostTask(FROM_HERE, task);
+}
+
+void LocationBarViewGtk::SetSuggestedText(const string16& text) {
+  // This method is internally invoked to reset suggest text, so we only do
+  // anything if the text isn't empty.
+  // TODO: if we keep autocomplete, make it so this isn't invoked with empty
+  // text.
+  if (!text.empty()) {
+    location_entry_->model()->FinalizeInstantQuery(
+        location_entry_->GetText(), text, false);
+  }
+}
+
+std::wstring LocationBarViewGtk::GetInputString() const {
+  return location_input_;
+}
+
+WindowOpenDisposition LocationBarViewGtk::GetWindowOpenDisposition() const {
+  return disposition_;
+}
+
+PageTransition::Type LocationBarViewGtk::GetPageTransition() const {
+  return transition_;
+}
+
+void LocationBarViewGtk::AcceptInput() {
+  location_entry_->model()->AcceptInput(CURRENT_TAB, false);
+}
+
+void LocationBarViewGtk::FocusLocation(bool select_all) {
+  location_entry_->SetFocus();
+  if (select_all)
+    location_entry_->SelectAll(true);
+}
+
+void LocationBarViewGtk::FocusSearch() {
+  location_entry_->SetFocus();
+  location_entry_->SetForcedQuery();
+}
+
+void LocationBarViewGtk::UpdateContentSettingsIcons() {
+  TabContents* tab_contents = GetTabContents();
+  bool any_visible = false;
+  for (ScopedVector<ContentSettingImageViewGtk>::iterator i(
+           content_setting_views_.begin());
+       i != content_setting_views_.end(); ++i) {
+    (*i)->UpdateFromTabContents(
+        toolbar_model_->input_in_progress() ? NULL : tab_contents);
+    any_visible = (*i)->IsVisible() || any_visible;
+  }
+
+  // If there are no visible content things, hide the top level box so it
+  // doesn't mess with padding.
+  if (any_visible)
+    gtk_widget_show(content_setting_hbox_.get());
+  else
+    gtk_widget_hide(content_setting_hbox_.get());
+}
+
+void LocationBarViewGtk::UpdatePageActions() {
+  std::vector<ExtensionAction*> page_actions;
+  ExtensionService* service = profile_->GetExtensionService();
+  if (!service)
+    return;
+
+  // Find all the page actions.
+  for (size_t i = 0; i < service->extensions()->size(); ++i) {
+    if (service->extensions()->at(i)->page_action())
+      page_actions.push_back(service->extensions()->at(i)->page_action());
+  }
+
+  // Initialize on the first call, or re-inialize if more extensions have been
+  // loaded or added after startup.
+  if (page_actions.size() != page_action_views_.size()) {
+    page_action_views_.reset();  // Delete the old views (if any).
+
+    for (size_t i = 0; i < page_actions.size(); ++i) {
+      page_action_views_.push_back(
+          new PageActionViewGtk(this, profile_, page_actions[i]));
+      gtk_box_pack_end(GTK_BOX(page_action_hbox_.get()),
+                       page_action_views_[i]->widget(), FALSE, FALSE, 0);
+    }
+    NotificationService::current()->Notify(
+        NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
+        Source<LocationBar>(this),
+        NotificationService::NoDetails());
+  }
+
+  TabContents* contents = GetTabContents();
+  if (!page_action_views_.empty() && contents) {
+    GURL url = GURL(WideToUTF8(toolbar_model_->GetText()));
+
+    for (size_t i = 0; i < page_action_views_.size(); i++) {
+      page_action_views_[i]->UpdateVisibility(
+          toolbar_model_->input_in_progress() ? NULL : contents, url);
+    }
+  }
+
+  // If there are no visible page actions, hide the hbox too, so that it does
+  // not affect the padding in the location bar.
+  if (PageActionVisibleCount() && !ShouldOnlyShowLocation())
+    gtk_widget_show(page_action_hbox_.get());
+  else
+    gtk_widget_hide(page_action_hbox_.get());
+}
+
+void LocationBarViewGtk::InvalidatePageActions() {
+  size_t count_before = page_action_views_.size();
+  page_action_views_.reset();
+  if (page_action_views_.size() != count_before) {
+    NotificationService::current()->Notify(
+        NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
+        Source<LocationBar>(this),
+        NotificationService::NoDetails());
+  }
+}
+
+void LocationBarViewGtk::SaveStateToContents(TabContents* contents) {
+  location_entry_->SaveStateToTab(contents);
+}
+
+void LocationBarViewGtk::Revert() {
+  location_entry_->RevertAll();
+}
+
+const AutocompleteEditView* LocationBarViewGtk::location_entry() const {
+  return location_entry_.get();
+}
+
+AutocompleteEditView* LocationBarViewGtk::location_entry() {
+  return location_entry_.get();
+}
+
+LocationBarTesting* LocationBarViewGtk::GetLocationBarForTesting() {
+  return this;
+}
+
+int LocationBarViewGtk::PageActionCount() {
+  return page_action_views_.size();
+}
+
+int LocationBarViewGtk::PageActionVisibleCount() {
+  int count = 0;
+  gtk_container_foreach(GTK_CONTAINER(page_action_hbox_.get()),
+                        CountVisibleWidgets, &count);
+  return count;
+}
+
+ExtensionAction* LocationBarViewGtk::GetPageAction(size_t index) {
+  if (index >= page_action_views_.size()) {
+    NOTREACHED();
+    return NULL;
+  }
+
+  return page_action_views_[index]->page_action();
+}
+
+ExtensionAction* LocationBarViewGtk::GetVisiblePageAction(size_t index) {
+  size_t visible_index = 0;
+  for (size_t i = 0; i < page_action_views_.size(); ++i) {
+    if (page_action_views_[i]->IsVisible()) {
+      if (index == visible_index++)
+        return page_action_views_[i]->page_action();
+    }
+  }
+
+  NOTREACHED();
+  return NULL;
+}
+
+void LocationBarViewGtk::TestPageActionPressed(size_t index) {
+  if (index >= page_action_views_.size()) {
+    NOTREACHED();
+    return;
+  }
+
+  page_action_views_[index]->TestActivatePageAction();
+}
+
+void LocationBarViewGtk::Observe(NotificationType type,
+                                 const NotificationSource& source,
+                                 const NotificationDetails& details) {
+  DCHECK_EQ(type.value,  NotificationType::BROWSER_THEME_CHANGED);
+
+  if (theme_provider_->UseGtkTheme()) {
+    gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL, NULL);
+
+    GdkColor border_color = theme_provider_->GetGdkColor(
+        BrowserThemeProvider::COLOR_FRAME);
+    gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_, border_color);
+
+    gtk_util::SetLabelColor(tab_to_search_full_label_, NULL);
+    gtk_util::SetLabelColor(tab_to_search_partial_label_, NULL);
+    gtk_util::SetLabelColor(tab_to_search_hint_leading_label_, NULL);
+    gtk_util::SetLabelColor(tab_to_search_hint_trailing_label_, NULL);
+
+    gtk_util::UndoForceFontSize(security_info_label_);
+    gtk_util::UndoForceFontSize(tab_to_search_full_label_);
+    gtk_util::UndoForceFontSize(tab_to_search_partial_label_);
+    gtk_util::UndoForceFontSize(tab_to_search_hint_leading_label_);
+    gtk_util::UndoForceFontSize(tab_to_search_hint_trailing_label_);
+
+    gtk_alignment_set_padding(GTK_ALIGNMENT(location_entry_alignment_),
+                              0, 0, 0, 0);
+  } else {
+    gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL,
+                         &kKeywordBackgroundColor);
+    gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_,
+                                          kKeywordBorderColor);
+
+    gtk_util::SetLabelColor(tab_to_search_full_label_, &gtk_util::kGdkBlack);
+    gtk_util::SetLabelColor(tab_to_search_partial_label_, &gtk_util::kGdkBlack);
+    gtk_util::SetLabelColor(tab_to_search_hint_leading_label_,
+                            &kHintTextColor);
+    gtk_util::SetLabelColor(tab_to_search_hint_trailing_label_,
+                            &kHintTextColor);
+
+    // Until we switch to vector graphics, force the font size of labels.
+    // 12.1px = 9pt @ 96dpi
+    gtk_util::ForceFontSizePixels(security_info_label_, 12.1);
+    gtk_util::ForceFontSizePixels(tab_to_search_full_label_,
+        browser_defaults::kAutocompleteEditFontPixelSize);
+    gtk_util::ForceFontSizePixels(tab_to_search_partial_label_,
+        browser_defaults::kAutocompleteEditFontPixelSize);
+    gtk_util::ForceFontSizePixels(tab_to_search_hint_leading_label_,
+        browser_defaults::kAutocompleteEditFontPixelSize);
+    gtk_util::ForceFontSizePixels(tab_to_search_hint_trailing_label_,
+        browser_defaults::kAutocompleteEditFontPixelSize);
+
+    if (popup_window_mode_) {
+      gtk_alignment_set_padding(GTK_ALIGNMENT(location_entry_alignment_),
+                                kTopMargin + kBorderThickness,
+                                kBottomMargin + kBorderThickness,
+                                kBorderThickness,
+                                kBorderThickness);
+    } else {
+      gtk_alignment_set_padding(GTK_ALIGNMENT(location_entry_alignment_),
+                                kTopMargin + kBorderThickness,
+                                kBottomMargin + kBorderThickness,
+                                0, 0);
+    }
+  }
+
+  UpdateStarIcon();
+  UpdateSiteTypeArea();
+  UpdateContentSettingsIcons();
+}
+
+gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
+                                          GdkEventExpose* event) {
+  // If we're not using GTK theming, draw our own border over the edge pixels
+  // of the background.
+  if (!profile_ ||
+      !GtkThemeProvider::GetFrom(profile_)->UseGtkTheme()) {
+    int left, center, right;
+    if (popup_window_mode_) {
+      left = right = IDR_LOCATIONBG_POPUPMODE_EDGE;
+      center = IDR_LOCATIONBG_POPUPMODE_CENTER;
+    } else {
+      left = IDR_LOCATIONBG_L;
+      center = IDR_LOCATIONBG_C;
+      right = IDR_LOCATIONBG_R;
+    }
+
+    NineBox background(left, center, right,
+                       0, 0, 0, 0, 0, 0);
+    background.RenderToWidget(widget);
+  }
+
+  return FALSE;  // Continue propagating the expose.
+}
+
+void LocationBarViewGtk::UpdateSiteTypeArea() {
+  // The icon is always visible except when the |tab_to_search_box_| is visible.
+  if (!location_entry_->model()->keyword().empty() &&
+      !location_entry_->model()->is_keyword_hint()) {
+    gtk_widget_hide(site_type_area());
+    return;
+  }
+
+  int resource_id = location_entry_->GetIcon();
+  gtk_image_set_from_pixbuf(GTK_IMAGE(location_icon_image_),
+                            theme_provider_->GetPixbufNamed(resource_id));
+
+  if (toolbar_model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
+    if (!gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) {
+      // Fun fact: If wee try to make |site_type_event_box_| act as a
+      // rounded window while it doesn't have a visible window, GTK interprets
+      // this as a sign that it should paint the skyline texture into the
+      // omnibox.
+      gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
+                                       TRUE);
+
+      gtk_util::ActAsRoundedWindow(site_type_event_box_,
+                                   kEvSecureBorderColor,
+                                   kCornerSize,
+                                   gtk_util::ROUNDED_ALL,
+                                   gtk_util::BORDER_ALL);
+    }
+
+    std::wstring info_text = toolbar_model_->GetEVCertName();
+    gtk_label_set_text(GTK_LABEL(security_info_label_),
+                       WideToUTF8(info_text).c_str());
+
+    UpdateEVCertificateLabelSize();
+
+    gtk_widget_show(GTK_WIDGET(security_info_label_));
+  } else {
+    if (gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) {
+      gtk_util::StopActingAsRoundedWindow(site_type_event_box_);
+
+      gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
+                                       FALSE);
+    }
+
+    gtk_widget_hide(GTK_WIDGET(security_info_label_));
+  }
+
+  gtk_widget_show(site_type_area());
+
+  SetSiteTypeDragSource();
+}
+
+void LocationBarViewGtk::UpdateEVCertificateLabelSize() {
+  // Figure out the width of the average character.
+  PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(security_info_label_));
+  PangoContext* context = pango_layout_get_context(layout);
+  PangoFontMetrics* metrics = pango_context_get_metrics(
+      context,
+      gtk_widget_get_style(security_info_label_)->font_desc,
+      pango_context_get_language(context));
+  int char_width =
+      pango_font_metrics_get_approximate_char_width(metrics) / PANGO_SCALE;
+
+  // The EV label should never take up more than half the hbox. We try to
+  // correct our inaccurate measurement units ("the average character width")
+  // by dividing more than an even 2.
+  int text_area = security_info_label_->allocation.width +
+                  entry_box_->allocation.width;
+  int max_chars = static_cast<int>(static_cast<float>(text_area) /
+                                   static_cast<float>(char_width) / 2.75);
+  // Don't let the label be smaller than 10 characters so that the country
+  // code is always visible.
+  gtk_label_set_max_width_chars(GTK_LABEL(security_info_label_),
+                                std::max(10, max_chars));
+
+  pango_font_metrics_unref(metrics);
+}
+
+void LocationBarViewGtk::SetKeywordLabel(const string16& keyword) {
+  if (keyword.empty())
+    return;
+
+  DCHECK(profile_);
+  if (!profile_->GetTemplateURLModel())
+    return;
+
+  bool is_extension_keyword;
+  const string16 short_name = profile_->GetTemplateURLModel()->
+      GetKeywordShortName(keyword, &is_extension_keyword);
+  int message_id = is_extension_keyword ?
+      IDS_OMNIBOX_EXTENSION_KEYWORD_TEXT : IDS_OMNIBOX_KEYWORD_TEXT;
+  string16 full_name = l10n_util::GetStringFUTF16(message_id,
+                                                  short_name);
+  string16 partial_name = l10n_util::GetStringFUTF16(
+      message_id,
+      WideToUTF16Hack(
+          location_bar_util::CalculateMinString(UTF16ToWideHack(short_name))));
+  gtk_label_set_text(GTK_LABEL(tab_to_search_full_label_),
+                     UTF16ToUTF8(full_name).c_str());
+  gtk_label_set_text(GTK_LABEL(tab_to_search_partial_label_),
+                     UTF16ToUTF8(partial_name).c_str());
+
+  if (last_keyword_ != keyword) {
+    last_keyword_ = keyword;
+
+    if (is_extension_keyword) {
+      const TemplateURL* template_url =
+          profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
+      const SkBitmap& bitmap = profile_->GetExtensionService()->
+          GetOmniboxIcon(template_url->GetExtensionId());
+      GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
+      gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_), pixbuf);
+      g_object_unref(pixbuf);
+    } else {
+      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+      gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_),
+                                rb.GetPixbufNamed(IDR_OMNIBOX_SEARCH));
+    }
+  }
+}
+
+void LocationBarViewGtk::SetKeywordHintLabel(const string16& keyword) {
+  if (keyword.empty())
+    return;
+
+  DCHECK(profile_);
+  if (!profile_->GetTemplateURLModel())
+    return;
+
+  bool is_extension_keyword;
+  const string16 short_name = profile_->GetTemplateURLModel()->
+      GetKeywordShortName(keyword, &is_extension_keyword);
+  int message_id = is_extension_keyword ?
+      IDS_OMNIBOX_EXTENSION_KEYWORD_HINT : IDS_OMNIBOX_KEYWORD_HINT;
+  std::vector<size_t> content_param_offsets;
+  const string16 keyword_hint = l10n_util::GetStringFUTF16(
+      message_id,
+      string16(),
+      short_name,
+      &content_param_offsets);
+  if (content_param_offsets.size() != 2) {
+    // See comments on an identical NOTREACHED() in search_provider.cc.
+    NOTREACHED();
+    return;
+  }
+
+  std::string leading(UTF16ToUTF8(
+      keyword_hint.substr(0, content_param_offsets.front())));
+  std::string trailing(UTF16ToUTF8(
+      keyword_hint.substr(content_param_offsets.front())));
+  gtk_label_set_text(GTK_LABEL(tab_to_search_hint_leading_label_),
+                     leading.c_str());
+  gtk_label_set_text(GTK_LABEL(tab_to_search_hint_trailing_label_),
+                     trailing.c_str());
+}
+
+void LocationBarViewGtk::ShowFirstRunBubbleInternal(
+    FirstRun::BubbleType bubble_type) {
+  if (!location_entry_.get() || !widget()->window)
+    return;
+
+  GtkWidget* anchor = location_entry_->GetNativeView();
+
+  // The bubble needs to be just below the Omnibox and slightly to the right
+  // of star button, so shift x and y co-ordinates.
+  int y_offset = anchor->allocation.height + kFirstRunBubbleTopMargin;
+  int x_offset = 0;
+  if (!base::i18n::IsRTL())
+    x_offset = kFirstRunBubbleLeftMargin;
+  else
+    x_offset = anchor->allocation.width - kFirstRunBubbleLeftMargin;
+  gfx::Rect rect(x_offset, y_offset, 0, 0);
+
+  FirstRunBubble::Show(profile_, anchor, rect, bubble_type);
+}
+
+gboolean LocationBarViewGtk::OnIconReleased(GtkWidget* sender,
+                                            GdkEventButton* event) {
+  TabContents* tab = GetTabContents();
+
+  if (event->button == 1) {
+    // Do not show page info if the user has been editing the location
+    // bar, or the location bar is at the NTP.
+    if (location_entry()->IsEditingOrEmpty())
+      return FALSE;
+
+    // (0,0) event coordinates indicates that the release came at the end of
+    // a drag.
+    if (event->x == 0 && event->y == 0)
+      return FALSE;
+
+    NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
+    if (!nav_entry) {
+      NOTREACHED();
+      return FALSE;
+    }
+    tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
+    return TRUE;
+  } else if (event->button == 2) {
+    // When the user middle clicks on the location icon, try to open the
+    // contents of the PRIMARY selection in the current tab.
+    // If the click was outside our bounds, do nothing.
+    if (!gtk_util::WidgetBounds(sender).Contains(
+            gfx::Point(event->x, event->y))) {
+      return FALSE;
+    }
+
+    GURL url;
+    if (!gtk_util::URLFromPrimarySelection(profile_, &url))
+      return FALSE;
+
+    tab->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+void LocationBarViewGtk::OnIconDragData(GtkWidget* sender,
+                                        GdkDragContext* context,
+                                        GtkSelectionData* data,
+                                        guint info, guint time) {
+  TabContents* tab = GetTabContents();
+  if (!tab)
+    return;
+  ui::WriteURLWithName(data, tab->GetURL(), tab->GetTitle(), info);
+}
+
+void LocationBarViewGtk::OnIconDragBegin(GtkWidget* sender,
+                                         GdkDragContext* context) {
+  SkBitmap favicon = GetFavIcon();
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&favicon);
+  if (!pixbuf)
+    return;
+  drag_icon_ = bookmark_utils::GetDragRepresentation(pixbuf,
+      GetTitle(), theme_provider_);
+  g_object_unref(pixbuf);
+  gtk_drag_set_icon_widget(context, drag_icon_, 0, 0);
+}
+
+void LocationBarViewGtk::OnIconDragEnd(GtkWidget* sender,
+                                       GdkDragContext* context) {
+  DCHECK(drag_icon_);
+  gtk_widget_destroy(drag_icon_);
+  drag_icon_ = NULL;
+}
+
+void LocationBarViewGtk::OnHboxSizeAllocate(GtkWidget* sender,
+                                            GtkAllocation* allocation) {
+  if (hbox_width_ != allocation->width) {
+    hbox_width_ = allocation->width;
+    UpdateEVCertificateLabelSize();
+  }
+}
+
+void LocationBarViewGtk::OnEntryBoxSizeAllocate(GtkWidget* sender,
+                                                GtkAllocation* allocation) {
+  if (entry_box_width_ != allocation->width) {
+    entry_box_width_ = allocation->width;
+    AdjustChildrenVisibility();
+  }
+}
+
+gboolean LocationBarViewGtk::OnStarButtonPress(GtkWidget* widget,
+                                               GdkEventButton* event) {
+  browser_->ExecuteCommand(IDC_BOOKMARK_PAGE);
+  return FALSE;
+}
+
+void LocationBarViewGtk::ShowStarBubble(const GURL& url,
+                                        bool newly_bookmarked) {
+  if (!star_.get())
+    return;
+
+  BookmarkBubbleGtk::Show(star_.get(), profile_, url, newly_bookmarked);
+}
+
+void LocationBarViewGtk::SetStarred(bool starred) {
+  if (starred == starred_)
+    return;
+
+  starred_ = starred;
+  UpdateStarIcon();
+}
+
+void LocationBarViewGtk::UpdateStarIcon() {
+  if (!star_.get())
+    return;
+
+  gtk_image_set_from_pixbuf(GTK_IMAGE(star_image_),
+      theme_provider_->GetPixbufNamed(
+          starred_ ? IDR_STAR_LIT : IDR_STAR));
+}
+
+bool LocationBarViewGtk::ShouldOnlyShowLocation() {
+  return browser_->type() != Browser::TYPE_NORMAL;
+}
+
+void LocationBarViewGtk::AdjustChildrenVisibility() {
+  int text_width = location_entry_->TextWidth();
+  int available_width = entry_box_width_ - text_width - kInnerPadding;
+
+  // Only one of |tab_to_search_box_| and |tab_to_search_hint_| can be visible
+  // at the same time.
+  if (!show_selected_keyword_ && GTK_WIDGET_VISIBLE(tab_to_search_box_))
+    gtk_widget_hide(tab_to_search_box_);
+  else if (!show_keyword_hint_ && GTK_WIDGET_VISIBLE(tab_to_search_hint_))
+    gtk_widget_hide(tab_to_search_hint_);
+
+  if (show_selected_keyword_) {
+    GtkRequisition box, full_label, partial_label;
+    gtk_widget_size_request(tab_to_search_box_, &box);
+    gtk_widget_size_request(tab_to_search_full_label_, &full_label);
+    gtk_widget_size_request(tab_to_search_partial_label_, &partial_label);
+    int full_partial_width_diff = full_label.width - partial_label.width;
+    int full_box_width;
+    int partial_box_width;
+    if (GTK_WIDGET_VISIBLE(tab_to_search_full_label_)) {
+      full_box_width = box.width;
+      partial_box_width = full_box_width - full_partial_width_diff;
+    } else {
+      partial_box_width = box.width;
+      full_box_width = partial_box_width + full_partial_width_diff;
+    }
+
+    if (partial_box_width >= entry_box_width_ - kInnerPadding) {
+      gtk_widget_hide(tab_to_search_box_);
+    } else if (full_box_width >= available_width) {
+      gtk_widget_hide(tab_to_search_full_label_);
+      gtk_widget_show(tab_to_search_partial_label_);
+      gtk_widget_show(tab_to_search_box_);
+    } else if (full_box_width < available_width) {
+      gtk_widget_hide(tab_to_search_partial_label_);
+      gtk_widget_show(tab_to_search_full_label_);
+      gtk_widget_show(tab_to_search_box_);
+    }
+  } else if (show_keyword_hint_) {
+    GtkRequisition leading, icon, trailing;
+    gtk_widget_size_request(tab_to_search_hint_leading_label_, &leading);
+    gtk_widget_size_request(tab_to_search_hint_icon_, &icon);
+    gtk_widget_size_request(tab_to_search_hint_trailing_label_, &trailing);
+    int full_width = leading.width + icon.width + trailing.width;
+
+    if (icon.width >= entry_box_width_ - kInnerPadding) {
+      gtk_widget_hide(tab_to_search_hint_);
+    } else if (full_width >= available_width) {
+      gtk_widget_hide(tab_to_search_hint_leading_label_);
+      gtk_widget_hide(tab_to_search_hint_trailing_label_);
+      gtk_widget_show(tab_to_search_hint_);
+    } else if (full_width < available_width) {
+      gtk_widget_show(tab_to_search_hint_leading_label_);
+      gtk_widget_show(tab_to_search_hint_trailing_label_);
+      gtk_widget_show(tab_to_search_hint_);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// LocationBarViewGtk::ContentSettingImageViewGtk
+LocationBarViewGtk::ContentSettingImageViewGtk::ContentSettingImageViewGtk(
+    ContentSettingsType content_type,
+    const LocationBarViewGtk* parent,
+    Profile* profile)
+    : content_setting_image_model_(
+          ContentSettingImageModel::CreateContentSettingImageModel(
+              content_type)),
+      parent_(parent),
+      profile_(profile),
+      info_bubble_(NULL) {
+  event_box_.Own(gtk_event_box_new());
+
+  // Make the event box not visible so it does not paint a background.
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
+  g_signal_connect(event_box_.get(), "button-press-event",
+                   G_CALLBACK(&OnButtonPressedThunk), this);
+
+  image_.Own(gtk_image_new());
+  gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get());
+  gtk_widget_hide(widget());
+}
+
+LocationBarViewGtk::ContentSettingImageViewGtk::~ContentSettingImageViewGtk() {
+  image_.Destroy();
+  event_box_.Destroy();
+
+  if (info_bubble_)
+    info_bubble_->Close();
+}
+
+void LocationBarViewGtk::ContentSettingImageViewGtk::UpdateFromTabContents(
+    TabContents* tab_contents) {
+  content_setting_image_model_->UpdateFromTabContents(tab_contents);
+  if (content_setting_image_model_->is_visible()) {
+    gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
+          GtkThemeProvider::GetFrom(profile_)->GetPixbufNamed(
+              content_setting_image_model_->get_icon()));
+
+    gtk_widget_set_tooltip_text(widget(),
+        content_setting_image_model_->get_tooltip().c_str());
+    gtk_widget_show(widget());
+  } else {
+    gtk_widget_hide(widget());
+  }
+}
+
+gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnButtonPressed(
+    GtkWidget* sender, GdkEvent* event) {
+  TabContents* tab_contents = parent_->GetTabContents();
+  if (!tab_contents)
+    return true;
+  GURL url = tab_contents->GetURL();
+  std::wstring display_host;
+  net::AppendFormattedHost(url,
+      UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
+      &display_host,
+      NULL, NULL);
+
+  info_bubble_ = new ContentSettingBubbleGtk(
+      sender, this,
+      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
+          tab_contents, profile_,
+          content_setting_image_model_->get_content_settings_type()),
+      profile_, tab_contents);
+  return TRUE;
+}
+
+void LocationBarViewGtk::ContentSettingImageViewGtk::InfoBubbleClosing(
+    InfoBubbleGtk* info_bubble,
+    bool closed_by_escape) {
+  info_bubble_ = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// LocationBarViewGtk::PageActionViewGtk
+
+LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk(
+    LocationBarViewGtk* owner, Profile* profile,
+    ExtensionAction* page_action)
+    : owner_(NULL),
+      profile_(profile),
+      page_action_(page_action),
+      last_icon_pixbuf_(NULL),
+      tracker_(this),
+      preview_enabled_(false) {
+  event_box_.Own(gtk_event_box_new());
+  gtk_widget_set_size_request(event_box_.get(),
+                              Extension::kPageActionIconMaxSize,
+                              Extension::kPageActionIconMaxSize);
+
+  // Make the event box not visible so it does not paint a background.
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
+  g_signal_connect(event_box_.get(), "button-press-event",
+                   G_CALLBACK(&OnButtonPressedThunk), this);
+  g_signal_connect_after(event_box_.get(), "expose-event",
+                         G_CALLBACK(OnExposeEventThunk), this);
+
+  image_.Own(gtk_image_new());
+  gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get());
+
+  const Extension* extension = profile->GetExtensionService()->
+      GetExtensionById(page_action->extension_id(), false);
+  DCHECK(extension);
+
+  // Load all the icons declared in the manifest. This is the contents of the
+  // icons array, plus the default_icon property, if any.
+  std::vector<std::string> icon_paths(*page_action->icon_paths());
+  if (!page_action_->default_icon_path().empty())
+    icon_paths.push_back(page_action_->default_icon_path());
+
+  for (std::vector<std::string>::iterator iter = icon_paths.begin();
+       iter != icon_paths.end(); ++iter) {
+    tracker_.LoadImage(extension, extension->GetResource(*iter),
+                       gfx::Size(Extension::kPageActionIconMaxSize,
+                                 Extension::kPageActionIconMaxSize),
+                       ImageLoadingTracker::DONT_CACHE);
+  }
+
+  // We set the owner last of all so that we can determine whether we are in
+  // the process of initializing this class or not.
+  owner_ = owner;
+}
+
+LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() {
+  image_.Destroy();
+  event_box_.Destroy();
+  for (PixbufMap::iterator iter = pixbufs_.begin(); iter != pixbufs_.end();
+       ++iter) {
+    g_object_unref(iter->second);
+  }
+  if (last_icon_pixbuf_)
+    g_object_unref(last_icon_pixbuf_);
+}
+
+void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility(
+    TabContents* contents, GURL url) {
+  // Save this off so we can pass it back to the extension when the action gets
+  // executed. See PageActionImageView::OnMousePressed.
+  current_tab_id_ = contents ? ExtensionTabUtil::GetTabId(contents) : -1;
+  current_url_ = url;
+
+  bool visible = contents &&
+      (preview_enabled_ || page_action_->GetIsVisible(current_tab_id_));
+  if (visible) {
+    // Set the tooltip.
+    gtk_widget_set_tooltip_text(event_box_.get(),
+        page_action_->GetTitle(current_tab_id_).c_str());
+
+    // Set the image.
+    // It can come from three places. In descending order of priority:
+    // - The developer can set it dynamically by path or bitmap. It will be in
+    //   page_action_->GetIcon().
+    // - The developer can set it dyanmically by index. It will be in
+    //   page_action_->GetIconIndex().
+    // - It can be set in the manifest by path. It will be in page_action_->
+    //   default_icon_path().
+
+    // First look for a dynamically set bitmap.
+    SkBitmap icon = page_action_->GetIcon(current_tab_id_);
+    GdkPixbuf* pixbuf = NULL;
+    if (!icon.isNull()) {
+      if (icon.pixelRef() != last_icon_skbitmap_.pixelRef()) {
+        if (last_icon_pixbuf_)
+          g_object_unref(last_icon_pixbuf_);
+        last_icon_skbitmap_ = icon;
+        last_icon_pixbuf_ = gfx::GdkPixbufFromSkBitmap(&icon);
+      }
+      DCHECK(last_icon_pixbuf_);
+      pixbuf = last_icon_pixbuf_;
+    } else {
+      // Otherwise look for a dynamically set index, or fall back to the
+      // default path.
+      int icon_index = page_action_->GetIconIndex(current_tab_id_);
+      std::string icon_path = (icon_index < 0) ?
+          page_action_->default_icon_path() :
+          page_action_->icon_paths()->at(icon_index);
+      if (!icon_path.empty()) {
+        PixbufMap::iterator iter = pixbufs_.find(icon_path);
+        if (iter != pixbufs_.end())
+          pixbuf = iter->second;
+      }
+    }
+    // The pixbuf might not be loaded yet.
+    if (pixbuf)
+      gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()), pixbuf);
+  }
+
+  bool old_visible = IsVisible();
+  if (visible)
+    gtk_widget_show_all(event_box_.get());
+  else
+    gtk_widget_hide_all(event_box_.get());
+
+  if (visible != old_visible) {
+    NotificationService::current()->Notify(
+        NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
+        Source<ExtensionAction>(page_action_),
+        Details<TabContents>(contents));
+  }
+}
+
+void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded(
+    SkBitmap* image, ExtensionResource resource, int index) {
+  // We loaded icons()->size() icons, plus one extra if the page action had
+  // a default icon.
+  int total_icons = static_cast<int>(page_action_->icon_paths()->size());
+  if (!page_action_->default_icon_path().empty())
+    total_icons++;
+  DCHECK(index < total_icons);
+
+  // Map the index of the loaded image back to its name. If we ever get an
+  // index greater than the number of icons, it must be the default icon.
+  if (image) {
+    GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(image);
+    if (index < static_cast<int>(page_action_->icon_paths()->size()))
+      pixbufs_[page_action_->icon_paths()->at(index)] = pixbuf;
+    else
+      pixbufs_[page_action_->default_icon_path()] = pixbuf;
+  }
+
+  // If we have no owner, that means this class is still being constructed and
+  // we should not UpdatePageActions, since it leads to the PageActions being
+  // destroyed again and new ones recreated (causing an infinite loop).
+  if (owner_)
+    owner_->UpdatePageActions();
+}
+
+void LocationBarViewGtk::PageActionViewGtk::TestActivatePageAction() {
+  GdkEventButton event = {};
+  event.button = 1;
+  OnButtonPressed(widget(), &event);
+}
+
+void LocationBarViewGtk::PageActionViewGtk::InspectPopup(
+    ExtensionAction* action) {
+  ShowPopup(true);
+}
+
+bool LocationBarViewGtk::PageActionViewGtk::ShowPopup(bool devtools) {
+  if (!page_action_->HasPopup(current_tab_id_))
+    return false;
+
+  ExtensionPopupGtk::Show(
+      page_action_->GetPopupUrl(current_tab_id_),
+      owner_->browser_,
+      event_box_.get(),
+      devtools);
+  return true;
+}
+
+gboolean LocationBarViewGtk::PageActionViewGtk::OnButtonPressed(
+    GtkWidget* sender,
+    GdkEventButton* event) {
+  if (event->button != 3) {
+    if (!ShowPopup(false)) {
+      ExtensionService* service = profile_->GetExtensionService();
+      service->browser_event_router()->PageActionExecuted(
+          profile_,
+          page_action_->extension_id(),
+          page_action_->id(),
+          current_tab_id_,
+          current_url_.spec(),
+          event->button);
+    }
+  } else {
+    const Extension* extension = profile_->GetExtensionService()->
+        GetExtensionById(page_action()->extension_id(), false);
+
+    if (extension->ShowConfigureContextMenus()) {
+      context_menu_model_ =
+          new ExtensionContextMenuModel(extension, owner_->browser_, this);
+      context_menu_.reset(
+          new MenuGtk(NULL, context_menu_model_.get()));
+      context_menu_->PopupForWidget(sender, event->button, event->time);
+    }
+  }
+
+  return TRUE;
+}
+
+gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent(
+    GtkWidget* widget, GdkEventExpose* event) {
+  TabContents* contents = owner_->GetTabContents();
+  if (!contents)
+    return FALSE;
+
+  int tab_id = ExtensionTabUtil::GetTabId(contents);
+  if (tab_id < 0)
+    return FALSE;
+
+  std::string badge_text = page_action_->GetBadgeText(tab_id);
+  if (badge_text.empty())
+    return FALSE;
+
+  gfx::CanvasSkiaPaint canvas(event, false);
+  gfx::Rect bounding_rect(widget->allocation);
+  page_action_->PaintBadge(&canvas, bounding_rect, tab_id);
+  return FALSE;
+}
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.h b/chrome/browser/ui/gtk/location_bar_view_gtk.h
new file mode 100644
index 0000000..33b6111
--- /dev/null
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.h
@@ -0,0 +1,434 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_vector.h"
+#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
+#include "chrome/browser/extensions/extension_context_menu_model.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/omnibox/location_bar.h"
+#include "chrome/common/content_settings_types.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/page_transition_types.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "webkit/glue/window_open_disposition.h"
+
+class AutocompleteEditViewGtk;
+class Browser;
+class CommandUpdater;
+class ContentSettingImageModel;
+class ContentSettingBubbleGtk;
+class ExtensionAction;
+class GtkThemeProvider;
+class Profile;
+class SkBitmap;
+class TabContents;
+class ToolbarModel;
+
+class LocationBarViewGtk : public AutocompleteEditController,
+                           public LocationBar,
+                           public LocationBarTesting,
+                           public NotificationObserver {
+ public:
+  explicit LocationBarViewGtk(Browser* browser);
+  virtual ~LocationBarViewGtk();
+
+  void Init(bool popup_window_mode);
+
+  void SetProfile(Profile* profile);
+
+  // Returns the widget the caller should host.  You must call Init() first.
+  GtkWidget* widget() { return hbox_.get(); }
+
+  // Returns the widget the page info bubble should point to.
+  GtkWidget* location_icon_widget() const { return location_icon_image_; }
+
+  // Returns the widget the extension installed bubble should point to.
+  GtkWidget* location_entry_widget() const { return entry_box_; }
+
+  // Returns the current TabContents.
+  TabContents* GetTabContents() const;
+
+  // Sets |preview_enabled| for the PageActionViewGtk associated with this
+  // |page_action|. If |preview_enabled| is true, the view will display the
+  // page action's icon even though it has not been activated by the extension.
+  // This is used by the ExtensionInstalledBubbleGtk to preview what the icon
+  // will look like for the user upon installation of the extension.
+  void SetPreviewEnabledPageAction(ExtensionAction *page_action,
+                                   bool preview_enabled);
+
+  // Retrieves the GtkWidget which is associated with PageActionView
+  // corresponding to |page_action|.
+  GtkWidget* GetPageActionWidget(ExtensionAction* page_action);
+
+  // Updates the location bar.  We also reset the bar's permanent text and
+  // security style, and, if |tab_for_state_restoring| is non-NULL, also
+  // restore saved state that the tab holds.
+  void Update(const TabContents* tab_for_state_restoring);
+
+  // Show the bookmark bubble.
+  void ShowStarBubble(const GURL& url, bool newly_boomkarked);
+
+  // Set the starred state of the bookmark star.
+  void SetStarred(bool starred);
+
+  // Implement the AutocompleteEditController interface.
+  virtual void OnAutocompleteWillClosePopup();
+  virtual void OnAutocompleteLosingFocus(gfx::NativeView view_gaining_focus);
+  virtual void OnAutocompleteWillAccept();
+  // For this implementation, the parameter is ignored.
+  virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete);
+  virtual bool AcceptCurrentInstantPreview();
+  virtual void OnPopupBoundsChanged(const gfx::Rect& bounds);
+  virtual void OnAutocompleteAccept(const GURL& url,
+      WindowOpenDisposition disposition,
+      PageTransition::Type transition,
+      const GURL& alternate_nav_url);
+  virtual void OnChanged();
+  virtual void OnSelectionBoundsChanged();
+  virtual void OnKillFocus();
+  virtual void OnSetFocus();
+  virtual void OnInputInProgress(bool in_progress);
+  virtual SkBitmap GetFavIcon() const;
+  virtual string16 GetTitle() const;
+
+  // Implement the LocationBar interface.
+  virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type);
+  virtual void SetSuggestedText(const string16& text);
+  virtual std::wstring GetInputString() const;
+  virtual WindowOpenDisposition GetWindowOpenDisposition() const;
+  virtual PageTransition::Type GetPageTransition() const;
+  virtual void AcceptInput();
+  virtual void FocusLocation(bool select_all);
+  virtual void FocusSearch();
+  virtual void UpdateContentSettingsIcons();
+  virtual void UpdatePageActions();
+  virtual void InvalidatePageActions();
+  virtual void SaveStateToContents(TabContents* contents);
+  virtual void Revert();
+  virtual const AutocompleteEditView* location_entry() const;
+  virtual AutocompleteEditView* location_entry();
+  virtual LocationBarTesting* GetLocationBarForTesting();
+
+  // Implement the LocationBarTesting interface.
+  virtual int PageActionCount();
+  virtual int PageActionVisibleCount();
+  virtual ExtensionAction* GetPageAction(size_t index);
+  virtual ExtensionAction* GetVisiblePageAction(size_t index);
+  virtual void TestPageActionPressed(size_t index);
+
+  // Implement the NotificationObserver interface.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Edit background color.
+  static const GdkColor kBackgroundColor;
+
+ private:
+  class ContentSettingImageViewGtk : public InfoBubbleGtkDelegate {
+   public:
+    ContentSettingImageViewGtk(ContentSettingsType content_type,
+                               const LocationBarViewGtk* parent,
+                               Profile* profile);
+    virtual ~ContentSettingImageViewGtk();
+
+    GtkWidget* widget() { return event_box_.get(); }
+
+    void set_profile(Profile* profile) { profile_ = profile; }
+
+    bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); }
+    void UpdateFromTabContents(TabContents* tab_contents);
+
+   private:
+    CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnButtonPressed,
+                         GdkEvent*);
+
+    // InfoBubbleDelegate overrides:
+    virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                   bool closed_by_escape);
+
+    scoped_ptr<ContentSettingImageModel> content_setting_image_model_;
+
+    // The widgets for this content settings view.
+    OwnedWidgetGtk event_box_;
+    OwnedWidgetGtk image_;
+
+    // The owning LocationBarViewGtk.
+    const LocationBarViewGtk* parent_;
+
+    // The currently active profile.
+    Profile* profile_;
+
+    // The currently shown info bubble if any.
+    ContentSettingBubbleGtk* info_bubble_;
+
+    DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk);
+  };
+
+  class PageActionViewGtk : public ImageLoadingTracker::Observer,
+                            public ExtensionContextMenuModel::PopupDelegate {
+   public:
+    PageActionViewGtk(
+        LocationBarViewGtk* owner, Profile* profile,
+        ExtensionAction* page_action);
+    virtual ~PageActionViewGtk();
+
+    GtkWidget* widget() { return event_box_.get(); }
+
+    ExtensionAction* page_action() { return page_action_; }
+
+    void set_preview_enabled(bool preview_enabled) {
+      preview_enabled_ = preview_enabled;
+    }
+
+    bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); }
+
+    // Called to notify the PageAction that it should determine whether to be
+    // visible or hidden. |contents| is the TabContents that is active, |url|
+    // is the current page URL.
+    void UpdateVisibility(TabContents* contents, GURL url);
+
+    // A callback from ImageLoadingTracker for when the image has loaded.
+    virtual void OnImageLoaded(
+        SkBitmap* image, ExtensionResource resource, int index);
+
+    // Simulate left mouse click on the page action button.
+    void TestActivatePageAction();
+
+    // Overridden from ExtensionContextMenuModel::PopupDelegate:
+    virtual void InspectPopup(ExtensionAction* action);
+
+   private:
+    // Show the popup for this page action. If |devtools| is true, show it
+    // with a debugger window attached. Returns true if a popup was shown.
+    bool ShowPopup(bool devtools);
+
+    CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed,
+                         GdkEventButton*);
+    CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent,
+                         GdkEventExpose*);
+
+    // The location bar view that owns us.
+    LocationBarViewGtk* owner_;
+
+    // The current profile (not owned by us).
+    Profile* profile_;
+
+    // The PageAction that this view represents. The PageAction is not owned by
+    // us, it resides in the extension of this particular profile.
+    ExtensionAction* page_action_;
+
+    // A cache of all the different icon paths associated with this page action.
+    typedef std::map<std::string, GdkPixbuf*> PixbufMap;
+    PixbufMap pixbufs_;
+
+    // A cache of the last dynamically generated bitmap and the pixbuf that
+    // corresponds to it. We keep track of both so we can free old pixbufs as
+    // their icons are replaced.
+    SkBitmap last_icon_skbitmap_;
+    GdkPixbuf* last_icon_pixbuf_;
+
+    // The object that is waiting for the image loading to complete
+    // asynchronously.
+    ImageLoadingTracker tracker_;
+
+    // The widgets for this page action.
+    OwnedWidgetGtk event_box_;
+    OwnedWidgetGtk image_;
+
+    // The tab id we are currently showing the icon for.
+    int current_tab_id_;
+
+    // The URL we are currently showing the icon for.
+    GURL current_url_;
+
+    // This is used for post-install visual feedback. The page_action icon
+    // is briefly shown even if it hasn't been enabled by its extension.
+    bool preview_enabled_;
+
+    // The context menu view and model for this extension action.
+    scoped_ptr<MenuGtk> context_menu_;
+    scoped_refptr<ExtensionContextMenuModel> context_menu_model_;
+
+    DISALLOW_COPY_AND_ASSIGN(PageActionViewGtk);
+  };
+  friend class PageActionViewGtk;
+
+  // Creates, initializes, and packs the location icon, EV certificate name,
+  // and optional border.
+  void BuildSiteTypeArea();
+
+  // Enable or disable the location icon/EV certificate as a drag source for
+  // the URL.
+  void SetSiteTypeDragSource();
+
+  GtkWidget* site_type_area() { return site_type_alignment_; }
+
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, HandleExpose,
+                       GdkEventExpose*);
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnIconReleased,
+                       GdkEventButton*);
+  CHROMEGTK_CALLBACK_4(LocationBarViewGtk, void, OnIconDragData,
+                       GdkDragContext*, GtkSelectionData*, guint, guint);
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragBegin,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragEnd,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnHboxSizeAllocate,
+                       GtkAllocation*);
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnEntryBoxSizeAllocate,
+                       GtkAllocation*);
+  CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnStarButtonPress,
+                       GdkEventButton*);
+
+  // Updates the site type area: changes the icon and shows/hides the EV
+  // certificate information.
+  void UpdateSiteTypeArea();
+
+  // Updates the maximum size of the EV certificate label.
+  void UpdateEVCertificateLabelSize();
+
+  // Sets the text that should be displayed in the info label and its associated
+  // tooltip text.  Call with an empty string if the info label should be
+  // hidden.
+  void SetInfoText();
+
+  // Set the keyword text for the Search BLAH: keyword box.
+  void SetKeywordLabel(const string16& keyword);
+
+  // Set the keyword text for the "Press tab to search BLAH" hint box.
+  void SetKeywordHintLabel(const string16& keyword);
+
+  void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type);
+
+  // Show or hide |tab_to_search_box_| and |tab_to_search_hint_| according to
+  // the value of |show_selected_keyword_|, |show_keyword_hint_|, and the
+  // available horizontal space in the location bar.
+  void AdjustChildrenVisibility();
+
+  // Build the star icon.
+  void CreateStarButton();
+
+  // Update the star icon after it is toggled or the theme changes.
+  void UpdateStarIcon();
+
+  // Returns true if we should only show the URL and none of the extras like
+  // the star button or page actions.
+  bool ShouldOnlyShowLocation();
+
+  // The outermost widget we want to be hosted.
+  OwnedWidgetGtk hbox_;
+
+  // Star button.
+  OwnedWidgetGtk star_;
+  GtkWidget* star_image_;
+  bool starred_;
+
+  // An icon to the left of the address bar.
+  GtkWidget* site_type_alignment_;
+  GtkWidget* site_type_event_box_;
+  GtkWidget* location_icon_image_;
+  GtkWidget* drag_icon_;
+  bool enable_location_drag_;
+  // TODO(pkasting): Split this label off and move the rest of the items to the
+  // left of the address bar.
+  GtkWidget* security_info_label_;
+
+  // Content setting icons.
+  OwnedWidgetGtk content_setting_hbox_;
+  ScopedVector<ContentSettingImageViewGtk> content_setting_views_;
+
+  // Extension page action icons.
+  OwnedWidgetGtk page_action_hbox_;
+  ScopedVector<PageActionViewGtk> page_action_views_;
+
+  // The widget that contains our tab hints and the location bar.
+  GtkWidget* entry_box_;
+
+  // Area on the left shown when in tab to search mode.
+  GtkWidget* tab_to_search_box_;
+  GtkWidget* tab_to_search_magnifier_;
+  GtkWidget* tab_to_search_full_label_;
+  GtkWidget* tab_to_search_partial_label_;
+
+  // Hint to user that they can tab-to-search by hitting tab.
+  GtkWidget* tab_to_search_hint_;
+  GtkWidget* tab_to_search_hint_leading_label_;
+  GtkWidget* tab_to_search_hint_icon_;
+  GtkWidget* tab_to_search_hint_trailing_label_;
+
+  scoped_ptr<AutocompleteEditViewGtk> location_entry_;
+
+  // Alignment used to wrap |location_entry_|.
+  GtkWidget* location_entry_alignment_;
+
+  Profile* profile_;
+  CommandUpdater* command_updater_;
+  ToolbarModel* toolbar_model_;
+  Browser* browser_;
+
+  // When we get an OnAutocompleteAccept notification from the autocomplete
+  // edit, we save the input string so we can give it back to the browser on
+  // the LocationBar interface via GetInputString().
+  std::wstring location_input_;
+
+  // The user's desired disposition for how their input should be opened.
+  WindowOpenDisposition disposition_;
+
+  // The transition type to use for the navigation.
+  PageTransition::Type transition_;
+
+  // Used to schedule a task for the first run info bubble.
+  ScopedRunnableMethodFactory<LocationBarViewGtk> first_run_bubble_;
+
+  // When true, the location bar view is read only and also is has a slightly
+  // different presentation (font size / color). This is used for popups.
+  bool popup_window_mode_;
+
+  // Provides colors and rendering mode.
+  GtkThemeProvider* theme_provider_;
+
+  NotificationRegistrar registrar_;
+
+  // Width of the main |hbox_|. Used to properly elide the EV certificate.
+  int hbox_width_;
+
+  // Width of the hbox that holds |tab_to_search_box_|, |location_entry_| and
+  // |tab_to_search_hint_|.
+  int entry_box_width_;
+
+  // Indicate if |tab_to_search_box_| should be shown.
+  bool show_selected_keyword_;
+
+  // Indicate if |tab_to_search_hint_| should be shown.
+  bool show_keyword_hint_;
+
+  // The last search keyword that was shown via the |tab_to_search_box_|.
+  string16 last_keyword_;
+
+  // True if we should update the instant controller when the edit text changes.
+  bool update_instant_;
+
+  DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_
diff --git a/chrome/browser/ui/gtk/menu_bar_helper.cc b/chrome/browser/ui/gtk/menu_bar_helper.cc
new file mode 100644
index 0000000..7a792f8
--- /dev/null
+++ b/chrome/browser/ui/gtk/menu_bar_helper.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/menu_bar_helper.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+
+namespace {
+
+// Recursively find all the GtkMenus that are attached to menu item |child|
+// and add them to |data|, which is a vector of GtkWidgets.
+void PopulateSubmenus(GtkWidget* child, gpointer data) {
+  std::vector<GtkWidget*>* submenus =
+      static_cast<std::vector<GtkWidget*>*>(data);
+  GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(child));
+  if (submenu) {
+    submenus->push_back(submenu);
+    gtk_container_foreach(GTK_CONTAINER(submenu), PopulateSubmenus, submenus);
+  }
+}
+
+// Is the cursor over |menu| or one of its parent menus?
+bool MotionIsOverMenu(GtkWidget* menu, GdkEventMotion* motion) {
+  if (motion->x >= 0 && motion->y >= 0 &&
+      motion->x < menu->allocation.width &&
+      motion->y < menu->allocation.height) {
+    return true;
+  }
+
+  while (menu) {
+    GtkWidget* menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu));
+    if (!menu_item)
+      return false;
+    GtkWidget* parent = gtk_widget_get_parent(menu_item);
+
+    if (gtk_util::WidgetContainsCursor(parent))
+      return true;
+    menu = parent;
+  }
+
+  return false;
+}
+
+}  // namespace
+
+MenuBarHelper::MenuBarHelper(Delegate* delegate)
+    : button_showing_menu_(NULL),
+      showing_menu_(NULL),
+      delegate_(delegate) {
+  DCHECK(delegate_);
+}
+
+MenuBarHelper::~MenuBarHelper() {
+}
+
+void MenuBarHelper::Add(GtkWidget* button) {
+  buttons_.push_back(button);
+}
+
+void MenuBarHelper::Remove(GtkWidget* button) {
+  std::vector<GtkWidget*>::iterator iter =
+      find(buttons_.begin(), buttons_.end(), button);
+  if (iter == buttons_.end()) {
+    NOTREACHED();
+    return;
+  }
+  buttons_.erase(iter);
+}
+
+void MenuBarHelper::Clear() {
+  buttons_.clear();
+}
+
+void MenuBarHelper::MenuStartedShowing(GtkWidget* button, GtkWidget* menu) {
+  DCHECK(GTK_IS_MENU(menu));
+  button_showing_menu_ = button;
+  showing_menu_ = menu;
+
+  signal_handlers_.reset(new ui::GtkSignalRegistrar());
+  signal_handlers_->Connect(menu, "destroy",
+                            G_CALLBACK(OnMenuHiddenOrDestroyedThunk), this);
+  signal_handlers_->Connect(menu, "hide",
+                            G_CALLBACK(OnMenuHiddenOrDestroyedThunk), this);
+  signal_handlers_->Connect(menu, "motion-notify-event",
+                            G_CALLBACK(OnMenuMotionNotifyThunk), this);
+  signal_handlers_->Connect(menu, "move-current",
+                            G_CALLBACK(OnMenuMoveCurrentThunk), this);
+  gtk_container_foreach(GTK_CONTAINER(menu), PopulateSubmenus, &submenus_);
+
+  for (size_t i = 0; i < submenus_.size(); ++i) {
+    signal_handlers_->Connect(submenus_[i], "motion-notify-event",
+                              G_CALLBACK(OnMenuMotionNotifyThunk), this);
+  }
+}
+
+gboolean MenuBarHelper::OnMenuMotionNotify(GtkWidget* menu,
+                                           GdkEventMotion* motion) {
+  // Don't do anything if pointer is in the menu.
+  if (MotionIsOverMenu(menu, motion))
+    return FALSE;
+  if (buttons_.empty())
+    return FALSE;
+
+  gint x = 0;
+  gint y = 0;
+  GtkWidget* last_button = NULL;
+
+  for (size_t i = 0; i < buttons_.size(); ++i) {
+    GtkWidget* button = buttons_[i];
+    // Figure out coordinates relative to this button. Avoid using
+    // gtk_widget_get_pointer() unnecessarily.
+    if (i == 0) {
+      // We have to make this call because the menu is a popup window, so it
+      // doesn't share a toplevel with the buttons and we can't just use
+      // gtk_widget_translate_coordinates().
+      gtk_widget_get_pointer(buttons_[0], &x, &y);
+    } else {
+      gint last_x = x;
+      gint last_y = y;
+      if (!gtk_widget_translate_coordinates(
+          last_button, button, last_x, last_y, &x, &y)) {
+        // |button| may not be realized.
+        continue;
+      }
+    }
+
+    last_button = button;
+
+    if (x >= 0 && y >= 0 && x < button->allocation.width &&
+        y < button->allocation.height) {
+      if (button != button_showing_menu_)
+        delegate_->PopupForButton(button);
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+void MenuBarHelper::OnMenuHiddenOrDestroyed(GtkWidget* menu) {
+  DCHECK_EQ(showing_menu_, menu);
+
+  signal_handlers_.reset();
+  showing_menu_ = NULL;
+  button_showing_menu_ = NULL;
+  submenus_.clear();
+}
+
+void MenuBarHelper::OnMenuMoveCurrent(GtkWidget* menu,
+                                      GtkMenuDirectionType dir) {
+  // The menu directions are triggered by the arrow keys as follows
+  //
+  //   PARENT   left
+  //   CHILD    right
+  //   NEXT     down
+  //   PREV     up
+  //
+  // We only care about left and right. Note that for RTL, they are swapped.
+  switch (dir) {
+    case GTK_MENU_DIR_CHILD: {
+      GtkWidget* active_item = GTK_MENU_SHELL(menu)->active_menu_item;
+      // The move is going to open a submenu; don't override default behavior.
+      if (active_item && gtk_menu_item_get_submenu(GTK_MENU_ITEM(active_item)))
+        return;
+      // Fall through.
+    }
+    case GTK_MENU_DIR_PARENT: {
+      delegate_->PopupForButtonNextTo(button_showing_menu_, dir);
+      break;
+    }
+    default:
+      return;
+  }
+
+  // This signal doesn't have a return value; we have to manually stop its
+  // propagation.
+  g_signal_stop_emission_by_name(menu, "move-current");
+}
diff --git a/chrome/browser/ui/gtk/menu_bar_helper.h b/chrome/browser/ui/gtk/menu_bar_helper.h
new file mode 100644
index 0000000..57077e9
--- /dev/null
+++ b/chrome/browser/ui/gtk/menu_bar_helper.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 class replicates some menubar behaviors that are tricky to get right.
+// It is used to create a more native feel for the bookmark bar.
+
+#ifndef CHROME_BROWSER_UI_GTK_MENU_BAR_HELPER_H_
+#define CHROME_BROWSER_UI_GTK_MENU_BAR_HELPER_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+namespace ui {
+class GtkSignalRegistrar;
+}
+
+class MenuBarHelper {
+ public:
+  class Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    // Called when a the menu for a button ought to be triggered.
+    virtual void PopupForButton(GtkWidget* button) = 0;
+    virtual void PopupForButtonNextTo(GtkWidget* button,
+                                      GtkMenuDirectionType dir) = 0;
+  };
+
+  // |delegate| cannot be null.
+  explicit MenuBarHelper(Delegate* delegate);
+  virtual ~MenuBarHelper();
+
+  // Must be called whenever a button's menu starts showing. It triggers the
+  // MenuBarHelper to start listening for certain events.
+  void MenuStartedShowing(GtkWidget* button, GtkWidget* menu);
+
+  // Add |button| to the set of buttons we care about.
+  void Add(GtkWidget* button);
+
+  // Remove |button| from the set of buttons we care about.
+  void Remove(GtkWidget* button);
+
+  // Clear all buttons from the set.
+  void Clear();
+
+ private:
+  CHROMEGTK_CALLBACK_0(MenuBarHelper, void, OnMenuHiddenOrDestroyed);
+  CHROMEGTK_CALLBACK_1(MenuBarHelper, gboolean, OnMenuMotionNotify,
+                       GdkEventMotion*);
+  CHROMEGTK_CALLBACK_1(MenuBarHelper, void, OnMenuMoveCurrent,
+                       GtkMenuDirectionType);
+
+  // The buttons for which we pop up menus. We do not own these, or even add
+  // refs to them.
+  std::vector<GtkWidget*> buttons_;
+
+  // The button that is currently showing a menu, or NULL.
+  GtkWidget* button_showing_menu_;
+
+  // The highest level menu that is currently showing, or NULL.
+  GtkWidget* showing_menu_;
+
+  // All the submenus of |showing_menu_|. We connect to motion events on all
+  // of them.
+  std::vector<GtkWidget*> submenus_;
+
+  // Signal handlers that are attached only between the "show" and "hide" events
+  // for the menu.
+  scoped_ptr<ui::GtkSignalRegistrar> signal_handlers_;
+
+  Delegate* delegate_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_MENU_BAR_HELPER_H_
diff --git a/chrome/browser/ui/gtk/menu_gtk.cc b/chrome/browser/ui/gtk/menu_gtk.cc
new file mode 100644
index 0000000..c3e6eec
--- /dev/null
+++ b/chrome/browser/ui/gtk/menu_gtk.cc
@@ -0,0 +1,832 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/menu_gtk.h"
+
+#include <map>
+
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/gtk/gtk_custom_menu.h"
+#include "chrome/browser/ui/gtk/gtk_custom_menu_item.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/models/accelerator_gtk.h"
+#include "ui/base/models/button_menu_item_model.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/gtk_util.h"
+#include "webkit/glue/window_open_disposition.h"
+
+bool MenuGtk::block_activation_ = false;
+
+namespace {
+
+// Sets the ID of a menu item.
+void SetMenuItemID(GtkWidget* menu_item, int menu_id) {
+  DCHECK_GE(menu_id, 0);
+
+  // Add 1 to the menu_id to avoid setting zero (null) to "menu-id".
+  g_object_set_data(G_OBJECT(menu_item), "menu-id",
+                    GINT_TO_POINTER(menu_id + 1));
+}
+
+// Gets the ID of a menu item.
+// Returns true if the menu item has an ID.
+bool GetMenuItemID(GtkWidget* menu_item, int* menu_id) {
+  gpointer id_ptr = g_object_get_data(G_OBJECT(menu_item), "menu-id");
+  if (id_ptr != NULL) {
+    *menu_id = GPOINTER_TO_INT(id_ptr) - 1;
+    return true;
+  }
+
+  return false;
+}
+
+ui::MenuModel* ModelForMenuItem(GtkMenuItem* menu_item) {
+  return reinterpret_cast<ui::MenuModel*>(
+      g_object_get_data(G_OBJECT(menu_item), "model"));
+}
+
+void SetupButtonShowHandler(GtkWidget* button,
+                            ui::ButtonMenuItemModel* model,
+                            int index) {
+  g_object_set_data(G_OBJECT(button), "button-model",
+                    model);
+  g_object_set_data(G_OBJECT(button), "button-model-id",
+                    GINT_TO_POINTER(index));
+}
+
+void OnSubmenuShowButtonImage(GtkWidget* widget, GtkButton* button) {
+  MenuGtk::Delegate* delegate = reinterpret_cast<MenuGtk::Delegate*>(
+      g_object_get_data(G_OBJECT(button), "menu-gtk-delegate"));
+  int icon_idr = GPOINTER_TO_INT(g_object_get_data(
+      G_OBJECT(button), "button-image-idr"));
+
+  GtkIconSet* icon_set = delegate->GetIconSetForId(icon_idr);
+  if (icon_set) {
+    gtk_button_set_image(
+        button, gtk_image_new_from_icon_set(icon_set,
+                                            GTK_ICON_SIZE_MENU));
+  }
+}
+
+void SetupImageIcon(GtkWidget* button,
+                    GtkWidget* menu,
+                    int icon_idr,
+                    MenuGtk::Delegate* menu_gtk_delegate) {
+  g_object_set_data(G_OBJECT(button), "button-image-idr",
+                    GINT_TO_POINTER(icon_idr));
+  g_object_set_data(G_OBJECT(button), "menu-gtk-delegate",
+                    menu_gtk_delegate);
+
+  g_signal_connect(menu, "show", G_CALLBACK(OnSubmenuShowButtonImage), button);
+}
+
+// Popup menus may get squished if they open up too close to the bottom of the
+// screen. This function takes the size of the screen, the size of the menu,
+// an optional widget, the Y position of the mouse click, and adjusts the popup
+// menu's Y position to make it fit if it's possible to do so.
+// Returns the new Y position of the popup menu.
+int CalculateMenuYPosition(const GdkRectangle* screen_rect,
+                           const GtkRequisition* menu_req,
+                           const GtkWidget* widget, const int y) {
+  CHECK(screen_rect);
+  CHECK(menu_req);
+  // If the menu would run off the bottom of the screen, and there is enough
+  // screen space upwards to accommodate the menu, then pop upwards. If there
+  // is a widget, then also move the anchor point to the top of the widget
+  // rather than the bottom.
+  const int screen_top = screen_rect->y;
+  const int screen_bottom = screen_rect->y + screen_rect->height;
+  const int menu_bottom = y + menu_req->height;
+  int alternate_y = y - menu_req->height;
+  if (widget)
+    alternate_y -= widget->allocation.height;
+  if (menu_bottom >= screen_bottom && alternate_y >= screen_top)
+    return alternate_y;
+  return y;
+}
+
+}  // namespace
+
+GtkWidget* MenuGtk::Delegate::GetDefaultImageForCommandId(int command_id) {
+  const char* stock;
+  switch (command_id) {
+    case IDC_NEW_TAB:
+    case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB:
+    case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB:
+    case IDC_CONTENT_CONTEXT_OPENAVNEWTAB:
+      stock = GTK_STOCK_NEW;
+      break;
+
+    case IDC_CLOSE_TAB:
+      stock = GTK_STOCK_CLOSE;
+      break;
+
+    case IDC_CONTENT_CONTEXT_SAVEIMAGEAS:
+    case IDC_CONTENT_CONTEXT_SAVEAVAS:
+    case IDC_CONTENT_CONTEXT_SAVELINKAS:
+      stock = GTK_STOCK_SAVE_AS;
+      break;
+
+    case IDC_SAVE_PAGE:
+      stock = GTK_STOCK_SAVE;
+      break;
+
+    case IDC_COPY:
+    case IDC_COPY_URL:
+    case IDC_CONTENT_CONTEXT_COPYIMAGELOCATION:
+    case IDC_CONTENT_CONTEXT_COPYLINKLOCATION:
+    case IDC_CONTENT_CONTEXT_COPYAVLOCATION:
+    case IDC_CONTENT_CONTEXT_COPYEMAILADDRESS:
+    case IDC_CONTENT_CONTEXT_COPY:
+      stock = GTK_STOCK_COPY;
+      break;
+
+    case IDC_CUT:
+    case IDC_CONTENT_CONTEXT_CUT:
+      stock = GTK_STOCK_CUT;
+      break;
+
+    case IDC_PASTE:
+    case IDC_CONTENT_CONTEXT_PASTE:
+      stock = GTK_STOCK_PASTE;
+      break;
+
+    case IDC_CONTENT_CONTEXT_DELETE:
+    case IDC_BOOKMARK_BAR_REMOVE:
+      stock = GTK_STOCK_DELETE;
+      break;
+
+    case IDC_CONTENT_CONTEXT_UNDO:
+      stock = GTK_STOCK_UNDO;
+      break;
+
+    case IDC_CONTENT_CONTEXT_REDO:
+      stock = GTK_STOCK_REDO;
+      break;
+
+    case IDC_SEARCH:
+    case IDC_FIND:
+    case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
+      stock = GTK_STOCK_FIND;
+      break;
+
+    case IDC_CONTENT_CONTEXT_SELECTALL:
+      stock = GTK_STOCK_SELECT_ALL;
+      break;
+
+    case IDC_CLEAR_BROWSING_DATA:
+      stock = GTK_STOCK_CLEAR;
+      break;
+
+    case IDC_BACK:
+      stock = GTK_STOCK_GO_BACK;
+      break;
+
+    case IDC_RELOAD:
+      stock = GTK_STOCK_REFRESH;
+      break;
+
+    case IDC_FORWARD:
+      stock = GTK_STOCK_GO_FORWARD;
+      break;
+
+    case IDC_PRINT:
+      stock = GTK_STOCK_PRINT;
+      break;
+
+    case IDC_CONTENT_CONTEXT_VIEWPAGEINFO:
+      stock = GTK_STOCK_INFO;
+      break;
+
+    case IDC_SPELLCHECK_MENU:
+      stock = GTK_STOCK_SPELL_CHECK;
+      break;
+
+    case IDC_RESTORE_TAB:
+      stock = GTK_STOCK_UNDELETE;
+      break;
+
+    case IDC_HOME:
+      stock = GTK_STOCK_HOME;
+      break;
+
+    case IDC_STOP:
+      stock = GTK_STOCK_STOP;
+      break;
+
+    case IDC_ABOUT:
+      stock = GTK_STOCK_ABOUT;
+      break;
+
+    case IDC_EXIT:
+      stock = GTK_STOCK_QUIT;
+      break;
+
+    case IDC_HELP_PAGE:
+      stock = GTK_STOCK_HELP;
+      break;
+
+    case IDC_OPTIONS:
+      stock = GTK_STOCK_PREFERENCES;
+      break;
+
+    case IDC_CONTENT_CONTEXT_GOTOURL:
+      stock = GTK_STOCK_JUMP_TO;
+      break;
+
+    case IDC_DEV_TOOLS_INSPECT:
+    case IDC_CONTENT_CONTEXT_INSPECTELEMENT:
+      stock = GTK_STOCK_PROPERTIES;
+      break;
+
+    case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK:
+      stock = GTK_STOCK_ADD;
+      break;
+
+    case IDC_BOOKMARK_BAR_RENAME_FOLDER:
+    case IDC_BOOKMARK_BAR_EDIT:
+      stock = GTK_STOCK_EDIT;
+      break;
+
+    case IDC_BOOKMARK_BAR_NEW_FOLDER:
+      stock = GTK_STOCK_DIRECTORY;
+      break;
+
+    case IDC_BOOKMARK_BAR_OPEN_ALL:
+      stock = GTK_STOCK_OPEN;
+      break;
+
+    default:
+      stock = NULL;
+  }
+
+  return stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU) : NULL;
+}
+
+GtkWidget* MenuGtk::Delegate::GetImageForCommandId(int command_id) const {
+  return GetDefaultImageForCommandId(command_id);
+}
+
+MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
+                 ui::MenuModel* model)
+    : delegate_(delegate),
+      model_(model),
+      dummy_accel_group_(gtk_accel_group_new()),
+      menu_(gtk_custom_menu_new()),
+      factory_(this) {
+  DCHECK(model);
+  g_object_ref_sink(menu_);
+  ConnectSignalHandlers();
+  BuildMenuFromModel();
+}
+
+MenuGtk::~MenuGtk() {
+  Cancel();
+
+  gtk_widget_destroy(menu_);
+  g_object_unref(menu_);
+
+  STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end());
+  g_object_unref(dummy_accel_group_);
+}
+
+void MenuGtk::ConnectSignalHandlers() {
+  // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may
+  // take a long time or even start a nested message loop.
+  g_signal_connect(menu_, "show", G_CALLBACK(OnMenuShowThunk), this);
+  g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this);
+}
+
+GtkWidget* MenuGtk::AppendMenuItemWithLabel(int command_id,
+                                            const std::string& label) {
+  std::string converted_label = gfx::ConvertAcceleratorsFromWindowsStyle(label);
+  GtkWidget* menu_item = BuildMenuItemWithLabel(label, command_id);
+  return AppendMenuItem(command_id, menu_item);
+}
+
+GtkWidget* MenuGtk::AppendMenuItemWithIcon(int command_id,
+                                           const std::string& label,
+                                           const SkBitmap& icon) {
+  std::string converted_label = gfx::ConvertAcceleratorsFromWindowsStyle(label);
+  GtkWidget* menu_item = BuildMenuItemWithImage(converted_label, icon);
+  return AppendMenuItem(command_id, menu_item);
+}
+
+GtkWidget* MenuGtk::AppendCheckMenuItemWithLabel(int command_id,
+                                                 const std::string& label) {
+  std::string converted_label = gfx::ConvertAcceleratorsFromWindowsStyle(label);
+  GtkWidget* menu_item =
+      gtk_check_menu_item_new_with_mnemonic(converted_label.c_str());
+  return AppendMenuItem(command_id, menu_item);
+}
+
+GtkWidget* MenuGtk::AppendSeparator() {
+  GtkWidget* menu_item = gtk_separator_menu_item_new();
+  gtk_widget_show(menu_item);
+  gtk_menu_shell_append(GTK_MENU_SHELL(menu_), menu_item);
+  return menu_item;
+}
+
+GtkWidget* MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) {
+  if (delegate_ && delegate_->AlwaysShowIconForCmd(command_id) &&
+      GTK_IS_IMAGE_MENU_ITEM(menu_item))
+    gtk_util::SetAlwaysShowImage(menu_item);
+
+  return AppendMenuItemToMenu(command_id, NULL, menu_item, menu_, true);
+}
+
+GtkWidget* MenuGtk::AppendMenuItemToMenu(int index,
+                                         ui::MenuModel* model,
+                                         GtkWidget* menu_item,
+                                         GtkWidget* menu,
+                                         bool connect_to_activate) {
+  SetMenuItemID(menu_item, index);
+
+  // Native menu items do their own thing, so only selectively listen for the
+  // activate signal.
+  if (connect_to_activate) {
+    g_signal_connect(menu_item, "activate",
+                     G_CALLBACK(OnMenuItemActivatedThunk), this);
+  }
+
+  // AppendMenuItemToMenu is used both internally when we control menu creation
+  // from a model (where the model can choose to hide certain menu items), and
+  // with immediate commands which don't provide the option.
+  if (model) {
+    if (model->IsVisibleAt(index))
+      gtk_widget_show(menu_item);
+  } else {
+    gtk_widget_show(menu_item);
+  }
+  gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+  return menu_item;
+}
+
+void MenuGtk::PopupForWidget(GtkWidget* widget, int button,
+                             guint32 event_time) {
+  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
+                 WidgetMenuPositionFunc,
+                 widget,
+                 button, event_time);
+}
+
+void MenuGtk::PopupAsContext(const gfx::Point& point, guint32 event_time) {
+  // gtk_menu_popup doesn't like the "const" qualifier on point.
+  gfx::Point nonconst_point(point);
+  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
+                 PointMenuPositionFunc, &nonconst_point,
+                 3, event_time);
+}
+
+void MenuGtk::PopupAsContextForStatusIcon(guint32 event_time, guint32 button,
+                                          GtkStatusIcon* icon) {
+  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, gtk_status_icon_position_menu,
+                 icon, button, event_time);
+}
+
+void MenuGtk::PopupAsFromKeyEvent(GtkWidget* widget) {
+  PopupForWidget(widget, 0, gtk_get_current_event_time());
+  gtk_menu_shell_select_first(GTK_MENU_SHELL(menu_), FALSE);
+}
+
+void MenuGtk::Cancel() {
+  gtk_menu_popdown(GTK_MENU(menu_));
+}
+
+void MenuGtk::UpdateMenu() {
+  gtk_container_foreach(GTK_CONTAINER(menu_), SetMenuItemInfo, this);
+}
+
+GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
+                                  GtkWidget* image) {
+  GtkWidget* menu_item =
+      gtk_image_menu_item_new_with_mnemonic(label.c_str());
+  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
+  return menu_item;
+}
+
+GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
+                                           const SkBitmap& icon) {
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
+  GtkWidget* menu_item = BuildMenuItemWithImage(label,
+      gtk_image_new_from_pixbuf(pixbuf));
+  g_object_unref(pixbuf);
+  return menu_item;
+}
+
+GtkWidget* MenuGtk::BuildMenuItemWithLabel(const std::string& label,
+                                           int command_id) {
+  GtkWidget* img =
+      delegate_ ? delegate_->GetImageForCommandId(command_id) :
+                  MenuGtk::Delegate::GetDefaultImageForCommandId(command_id);
+  return img ? BuildMenuItemWithImage(label, img) :
+               gtk_menu_item_new_with_mnemonic(label.c_str());
+}
+
+void MenuGtk::BuildMenuFromModel() {
+  BuildSubmenuFromModel(model_, menu_);
+}
+
+void MenuGtk::BuildSubmenuFromModel(ui::MenuModel* model, GtkWidget* menu) {
+  std::map<int, GtkWidget*> radio_groups;
+  GtkWidget* menu_item = NULL;
+  for (int i = 0; i < model->GetItemCount(); ++i) {
+    SkBitmap icon;
+    std::string label =
+        gfx::ConvertAcceleratorsFromWindowsStyle(
+            UTF16ToUTF8(model->GetLabelAt(i)));
+    bool connect_to_activate = true;
+
+    switch (model->GetTypeAt(i)) {
+      case ui::MenuModel::TYPE_SEPARATOR:
+        menu_item = gtk_separator_menu_item_new();
+        break;
+
+      case ui::MenuModel::TYPE_CHECK:
+        menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
+        break;
+
+      case ui::MenuModel::TYPE_RADIO: {
+        std::map<int, GtkWidget*>::iterator iter =
+            radio_groups.find(model->GetGroupIdAt(i));
+
+        if (iter == radio_groups.end()) {
+          menu_item = gtk_radio_menu_item_new_with_mnemonic(
+              NULL, label.c_str());
+          radio_groups[model->GetGroupIdAt(i)] = menu_item;
+        } else {
+          menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
+              GTK_RADIO_MENU_ITEM(iter->second), label.c_str());
+        }
+        break;
+      }
+      case ui::MenuModel::TYPE_BUTTON_ITEM: {
+        ui::ButtonMenuItemModel* button_menu_item_model =
+            model->GetButtonMenuItemAt(i);
+        menu_item = BuildButtomMenuItem(button_menu_item_model, menu);
+        connect_to_activate = false;
+        break;
+      }
+      case ui::MenuModel::TYPE_SUBMENU:
+      case ui::MenuModel::TYPE_COMMAND: {
+        int command_id = model->GetCommandIdAt(i);
+        if (model->GetIconAt(i, &icon))
+          menu_item = BuildMenuItemWithImage(label, icon);
+        else
+          menu_item = BuildMenuItemWithLabel(label, command_id);
+        if (delegate_ && delegate_->AlwaysShowIconForCmd(command_id) &&
+            GTK_IS_IMAGE_MENU_ITEM(menu_item))
+          gtk_util::SetAlwaysShowImage(menu_item);
+        break;
+      }
+
+      default:
+        NOTREACHED();
+    }
+
+    if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
+      GtkWidget* submenu = gtk_menu_new();
+      BuildSubmenuFromModel(model->GetSubmenuModelAt(i), submenu);
+      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
+    }
+
+    ui::AcceleratorGtk accelerator;
+    if (model->GetAcceleratorAt(i, &accelerator)) {
+      gtk_widget_add_accelerator(menu_item,
+                                 "activate",
+                                 dummy_accel_group_,
+                                 accelerator.GetGdkKeyCode(),
+                                 accelerator.gdk_modifier_type(),
+                                 GTK_ACCEL_VISIBLE);
+    }
+
+    g_object_set_data(G_OBJECT(menu_item), "model", model);
+    AppendMenuItemToMenu(i, model, menu_item, menu, connect_to_activate);
+
+    menu_item = NULL;
+  }
+}
+
+GtkWidget* MenuGtk::BuildButtomMenuItem(ui::ButtonMenuItemModel* model,
+                                        GtkWidget* menu) {
+  GtkWidget* menu_item = gtk_custom_menu_item_new(
+      gfx::RemoveWindowsStyleAccelerators(UTF16ToUTF8(model->label())).c_str());
+
+  // Set up the callback to the model for when it is clicked.
+  g_object_set_data(G_OBJECT(menu_item), "button-model", model);
+  g_signal_connect(menu_item, "button-pushed",
+                   G_CALLBACK(OnMenuButtonPressedThunk), this);
+  g_signal_connect(menu_item, "try-button-pushed",
+                   G_CALLBACK(OnMenuTryButtonPressedThunk), this);
+
+  GtkSizeGroup* group = NULL;
+  for (int i = 0; i < model->GetItemCount(); ++i) {
+    GtkWidget* button = NULL;
+
+    switch (model->GetTypeAt(i)) {
+      case ui::ButtonMenuItemModel::TYPE_SPACE: {
+        gtk_custom_menu_item_add_space(GTK_CUSTOM_MENU_ITEM(menu_item));
+        break;
+      }
+      case ui::ButtonMenuItemModel::TYPE_BUTTON: {
+        button = gtk_custom_menu_item_add_button(
+            GTK_CUSTOM_MENU_ITEM(menu_item),
+            model->GetCommandIdAt(i));
+
+        int icon_idr;
+        if (model->GetIconAt(i, &icon_idr)) {
+          SetupImageIcon(button, menu, icon_idr, delegate_);
+        } else {
+          gtk_button_set_label(
+              GTK_BUTTON(button),
+              gfx::RemoveWindowsStyleAccelerators(
+                  UTF16ToUTF8(model->GetLabelAt(i))).c_str());
+        }
+
+        SetupButtonShowHandler(button, model, i);
+        break;
+      }
+      case ui::ButtonMenuItemModel::TYPE_BUTTON_LABEL: {
+        button = gtk_custom_menu_item_add_button_label(
+            GTK_CUSTOM_MENU_ITEM(menu_item),
+            model->GetCommandIdAt(i));
+        gtk_button_set_label(
+            GTK_BUTTON(button),
+            gfx::RemoveWindowsStyleAccelerators(
+                UTF16ToUTF8(model->GetLabelAt(i))).c_str());
+        SetupButtonShowHandler(button, model, i);
+        break;
+      }
+    }
+
+    if (button && model->PartOfGroup(i)) {
+      if (!group)
+        group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+      gtk_size_group_add_widget(group, button);
+    }
+  }
+
+  if (group) {
+    g_object_unref(group);
+  }
+
+  return menu_item;
+}
+
+void MenuGtk::OnMenuItemActivated(GtkWidget* menuitem) {
+  if (block_activation_)
+    return;
+
+  // We receive activation messages when highlighting a menu that has a
+  // submenu. Ignore them.
+  if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuitem)))
+    return;
+
+  // The activate signal is sent to radio items as they get deselected;
+  // ignore it in this case.
+  if (GTK_IS_RADIO_MENU_ITEM(menuitem) &&
+      !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
+    return;
+  }
+
+  int id;
+  if (!GetMenuItemID(menuitem, &id))
+    return;
+
+  ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menuitem));
+
+  // The menu item can still be activated by hotkeys even if it is disabled.
+  if (model->IsEnabledAt(id))
+    ExecuteCommand(model, id);
+}
+
+void MenuGtk::OnMenuButtonPressed(GtkWidget* menu_item, int command_id) {
+  ui::ButtonMenuItemModel* model =
+      reinterpret_cast<ui::ButtonMenuItemModel*>(
+          g_object_get_data(G_OBJECT(menu_item), "button-model"));
+  if (model && model->IsCommandIdEnabled(command_id)) {
+    if (delegate_)
+      delegate_->CommandWillBeExecuted();
+
+    model->ActivatedCommand(command_id);
+  }
+}
+
+gboolean MenuGtk::OnMenuTryButtonPressed(GtkWidget* menu_item,
+                                         int command_id) {
+  gboolean pressed = FALSE;
+  ui::ButtonMenuItemModel* model =
+      reinterpret_cast<ui::ButtonMenuItemModel*>(
+          g_object_get_data(G_OBJECT(menu_item), "button-model"));
+  if (model &&
+      model->IsCommandIdEnabled(command_id) &&
+      !model->DoesCommandIdDismissMenu(command_id)) {
+    if (delegate_)
+      delegate_->CommandWillBeExecuted();
+
+    model->ActivatedCommand(command_id);
+    pressed = TRUE;
+  }
+
+  return pressed;
+}
+
+// static
+void MenuGtk::WidgetMenuPositionFunc(GtkMenu* menu,
+                                     int* x,
+                                     int* y,
+                                     gboolean* push_in,
+                                     void* void_widget) {
+  GtkWidget* widget = GTK_WIDGET(void_widget);
+  GtkRequisition menu_req;
+
+  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
+
+  gdk_window_get_origin(widget->window, x, y);
+  GdkScreen *screen = gtk_widget_get_screen(widget);
+  gint monitor = gdk_screen_get_monitor_at_point(screen, *x, *y);
+
+  GdkRectangle screen_rect;
+  gdk_screen_get_monitor_geometry(screen, monitor,
+                                  &screen_rect);
+
+  if (GTK_WIDGET_NO_WINDOW(widget)) {
+    *x += widget->allocation.x;
+    *y += widget->allocation.y;
+  }
+  *y += widget->allocation.height;
+
+  bool start_align =
+    !!g_object_get_data(G_OBJECT(widget), "left-align-popup");
+  if (base::i18n::IsRTL())
+    start_align = !start_align;
+
+  if (!start_align)
+    *x += widget->allocation.width - menu_req.width;
+
+  *y = CalculateMenuYPosition(&screen_rect, &menu_req, widget, *y);
+
+  *push_in = FALSE;
+}
+
+// static
+void MenuGtk::PointMenuPositionFunc(GtkMenu* menu,
+                                    int* x,
+                                    int* y,
+                                    gboolean* push_in,
+                                    gpointer userdata) {
+  *push_in = TRUE;
+
+  gfx::Point* point = reinterpret_cast<gfx::Point*>(userdata);
+  *x = point->x();
+  *y = point->y();
+
+  GtkRequisition menu_req;
+  gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
+  GdkScreen* screen;
+  gdk_display_get_pointer(gdk_display_get_default(), &screen, NULL, NULL, NULL);
+  gint monitor = gdk_screen_get_monitor_at_point(screen, *x, *y);
+
+  GdkRectangle screen_rect;
+  gdk_screen_get_monitor_geometry(screen, monitor, &screen_rect);
+
+  *y = CalculateMenuYPosition(&screen_rect, &menu_req, NULL, *y);
+}
+
+void MenuGtk::ExecuteCommand(ui::MenuModel* model, int id) {
+  if (delegate_)
+    delegate_->CommandWillBeExecuted();
+
+  GdkEvent* event = gtk_get_current_event();
+  if (event && event->type == GDK_BUTTON_RELEASE) {
+    model->ActivatedAtWithDisposition(
+        id, event_utils::DispositionFromEventFlags(event->button.state));
+  } else {
+    model->ActivatedAt(id);
+  }
+
+  if (event)
+    gdk_event_free(event);
+}
+
+void MenuGtk::OnMenuShow(GtkWidget* widget) {
+  MessageLoop::current()->PostTask(FROM_HERE,
+      factory_.NewRunnableMethod(&MenuGtk::UpdateMenu));
+}
+
+void MenuGtk::OnMenuHidden(GtkWidget* widget) {
+  if (delegate_)
+    delegate_->StoppedShowing();
+  model_->MenuClosed();
+}
+
+// static
+void MenuGtk::SetButtonItemInfo(GtkWidget* button, gpointer userdata) {
+  ui::ButtonMenuItemModel* model =
+      reinterpret_cast<ui::ButtonMenuItemModel*>(
+          g_object_get_data(G_OBJECT(button), "button-model"));
+  int index = GPOINTER_TO_INT(g_object_get_data(
+      G_OBJECT(button), "button-model-id"));
+
+  if (model->IsItemDynamicAt(index)) {
+    std::string label =
+        gfx::ConvertAcceleratorsFromWindowsStyle(
+            UTF16ToUTF8(model->GetLabelAt(index)));
+    gtk_button_set_label(GTK_BUTTON(button), label.c_str());
+  }
+
+  gtk_widget_set_sensitive(GTK_WIDGET(button), model->IsEnabledAt(index));
+}
+
+// static
+void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
+  if (GTK_IS_SEPARATOR_MENU_ITEM(widget)) {
+    // We need to explicitly handle this case because otherwise we'll ask the
+    // menu delegate about something with an invalid id.
+    return;
+  }
+
+  int id;
+  if (!GetMenuItemID(widget, &id))
+    return;
+
+  ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(widget));
+  if (!model) {
+    // If we're not providing the sub menu, then there's no model.  For
+    // example, the IME submenu doesn't have a model.
+    return;
+  }
+
+  if (GTK_IS_CHECK_MENU_ITEM(widget)) {
+    GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget);
+
+    // gtk_check_menu_item_set_active() will send the activate signal. Touching
+    // the underlying "active" property will also call the "activate" handler
+    // for this menu item. So we prevent the "activate" handler from
+    // being called while we set the checkbox.
+    // Why not use one of the glib signal-blocking functions?  Because when we
+    // toggle a radio button, it will deactivate one of the other radio buttons,
+    // which we don't have a pointer to.
+    // Wny not make this a member variable?  Because "menu" is a pointer to the
+    // root of the MenuGtk and we want to disable *all* MenuGtks, including
+    // submenus.
+    block_activation_ = true;
+    gtk_check_menu_item_set_active(item, model->IsItemCheckedAt(id));
+    block_activation_ = false;
+  }
+
+  if (GTK_IS_CUSTOM_MENU_ITEM(widget)) {
+    // Iterate across all the buttons to update their visible properties.
+    gtk_custom_menu_item_foreach_button(GTK_CUSTOM_MENU_ITEM(widget),
+                                        SetButtonItemInfo,
+                                        userdata);
+  }
+
+  if (GTK_IS_MENU_ITEM(widget)) {
+    gtk_widget_set_sensitive(widget, model->IsEnabledAt(id));
+
+    if (model->IsVisibleAt(id)) {
+      // Update the menu item label if it is dynamic.
+      if (model->IsItemDynamicAt(id)) {
+        std::string label =
+            gfx::ConvertAcceleratorsFromWindowsStyle(
+                UTF16ToUTF8(model->GetLabelAt(id)));
+
+#if GTK_CHECK_VERSION(2, 16, 0)
+        gtk_menu_item_set_label(GTK_MENU_ITEM(widget), label.c_str());
+#else
+        gtk_label_set_label(GTK_LABEL(GTK_BIN(widget)->child), label.c_str());
+#endif
+        if (GTK_IS_IMAGE_MENU_ITEM(widget)) {
+          SkBitmap icon;
+          if (model->GetIconAt(id, &icon)) {
+            GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
+            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget),
+                                          gtk_image_new_from_pixbuf(pixbuf));
+            g_object_unref(pixbuf);
+          } else {
+            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), NULL);
+          }
+        }
+      }
+
+      gtk_widget_show(widget);
+    } else {
+      gtk_widget_hide(widget);
+    }
+
+    GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
+    if (submenu) {
+      gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
+                            userdata);
+    }
+  }
+}
diff --git a/chrome/browser/ui/gtk/menu_gtk.h b/chrome/browser/ui/gtk/menu_gtk.h
new file mode 100644
index 0000000..58138f2
--- /dev/null
+++ b/chrome/browser/ui/gtk/menu_gtk.h
@@ -0,0 +1,196 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_MENU_GTK_H_
+#define CHROME_BROWSER_UI_GTK_MENU_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/task.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/point.h"
+
+class SkBitmap;
+
+namespace ui {
+class ButtonMenuItemModel;
+class MenuModel;
+}
+
+class MenuGtk {
+ public:
+  // Delegate class that lets another class control the status of the menu.
+  class Delegate {
+   public:
+    virtual ~Delegate() { }
+
+    // Called before a command is executed. This exists for the case where a
+    // model is handling the actual execution of commands, but the delegate
+    // still needs to know that some command got executed. This is called before
+    // and not after the command is executed because its execution may delete
+    // the menu and/or the delegate.
+    virtual void CommandWillBeExecuted() {}
+
+    // Called when the menu stops showing. This will be called before
+    // ExecuteCommand if the user clicks an item, but will also be called when
+    // the user clicks away from the menu.
+    virtual void StoppedShowing() {}
+
+    // Return true if we should override the "gtk-menu-images" system setting
+    // when showing image menu items for this menu.
+    virtual bool AlwaysShowIconForCmd(int command_id) const { return false; }
+
+    // Returns a tinted image used in button in a menu.
+    virtual GtkIconSet* GetIconSetForId(int idr) { return NULL; }
+
+    // Returns an icon for the menu item, if available.
+    virtual GtkWidget* GetImageForCommandId(int command_id) const;
+
+    static GtkWidget* GetDefaultImageForCommandId(int command_id);
+  };
+
+  MenuGtk(MenuGtk::Delegate* delegate, ui::MenuModel* model);
+  ~MenuGtk();
+
+  // Initialize GTK signal handlers.
+  void ConnectSignalHandlers();
+
+  // These methods are used to build the menu dynamically. The return value
+  // is the new menu item.
+  GtkWidget* AppendMenuItemWithLabel(int command_id, const std::string& label);
+  GtkWidget* AppendMenuItemWithIcon(int command_id, const std::string& label,
+                                    const SkBitmap& icon);
+  GtkWidget* AppendCheckMenuItemWithLabel(int command_id,
+                                          const std::string& label);
+  GtkWidget* AppendSeparator();
+  GtkWidget* AppendMenuItem(int command_id, GtkWidget* menu_item);
+  GtkWidget* AppendMenuItemToMenu(int index,
+                                  ui::MenuModel* model,
+                                  GtkWidget* menu_item,
+                                  GtkWidget* menu,
+                                  bool connect_to_activate);
+
+  // Displays the menu near a widget, as if the widget were a menu bar.
+  // Example: the wrench menu button.
+  // |button| is the mouse button that brought up the menu.
+  // |event_time| is the time from the GdkEvent.
+  void PopupForWidget(GtkWidget* widget, int button, guint32 event_time);
+
+  // Displays the menu as a context menu, i.e. at the cursor location.
+  // It is implicit that it was brought up using the right mouse button.
+  // |point| is the point where to put the menu.
+  // |event_time| is the time of the event that triggered the menu's display.
+  void PopupAsContext(const gfx::Point& point, guint32 event_time);
+
+  // Displays the menu as a context menu for the passed status icon.
+  void PopupAsContextForStatusIcon(guint32 event_time, guint32 button,
+                                   GtkStatusIcon* icon);
+
+  // Displays the menu following a keyboard event (such as selecting |widget|
+  // and pressing "enter").
+  void PopupAsFromKeyEvent(GtkWidget* widget);
+
+  // Closes the menu.
+  void Cancel();
+
+  // Repositions the menu to be right under the button.  Alignment is set as
+  // object data on |void_widget| with the tag "left_align".  If "left_align"
+  // is true, it aligns the left side of the menu with the left side of the
+  // button. Otherwise it aligns the right side of the menu with the right side
+  // of the button. Public since some menus have odd requirements that don't
+  // belong in a public class.
+  static void WidgetMenuPositionFunc(GtkMenu* menu,
+                                     int* x,
+                                     int* y,
+                                     gboolean* push_in,
+                                     void* void_widget);
+
+  // Positions the menu to appear at the gfx::Point represented by |userdata|.
+  static void PointMenuPositionFunc(GtkMenu* menu,
+                                    int* x,
+                                    int* y,
+                                    gboolean* push_in,
+                                    gpointer userdata);
+
+  GtkWidget* widget() const { return menu_; }
+
+  // Updates all the enabled/checked states and the dynamic labels.
+  void UpdateMenu();
+
+ private:
+  // Builds a GtkImageMenuItem.
+  GtkWidget* BuildMenuItemWithImage(const std::string& label,
+                                    const SkBitmap& icon);
+
+  GtkWidget* BuildMenuItemWithImage(const std::string& label,
+                                    GtkWidget* image);
+
+  GtkWidget* BuildMenuItemWithLabel(const std::string& label,
+                                    int command_id);
+
+  // A function that creates a GtkMenu from |model_|.
+  void BuildMenuFromModel();
+  // Implementation of the above; called recursively.
+  void BuildSubmenuFromModel(ui::MenuModel* model, GtkWidget* menu);
+  // Builds a menu item with buttons in it from the data in the model.
+  GtkWidget* BuildButtomMenuItem(ui::ButtonMenuItemModel* model,
+                                 GtkWidget* menu);
+
+  void ExecuteCommand(ui::MenuModel* model, int id);
+
+  // Callback for when a menu item is clicked.
+  CHROMEGTK_CALLBACK_0(MenuGtk, void, OnMenuItemActivated);
+
+  // Called when one of the buttons are pressed.
+  CHROMEGTK_CALLBACK_1(MenuGtk, void, OnMenuButtonPressed, int);
+
+  // Called to maybe activate a button if that button isn't supposed to dismiss
+  // the menu.
+  CHROMEGTK_CALLBACK_1(MenuGtk, gboolean, OnMenuTryButtonPressed, int);
+
+  // Updates all the menu items' state.
+  CHROMEGTK_CALLBACK_0(MenuGtk, void, OnMenuShow);
+
+  // Sets the activating widget back to a normal appearance.
+  CHROMEGTK_CALLBACK_0(MenuGtk, void, OnMenuHidden);
+
+  // Sets the enable/disabled state and dynamic labels on our menu items.
+  static void SetButtonItemInfo(GtkWidget* button, gpointer userdata);
+
+  // Sets the check mark, enabled/disabled state and dynamic labels on our menu
+  // items.
+  static void SetMenuItemInfo(GtkWidget* widget, void* raw_menu);
+
+  // Queries this object about the menu state.
+  MenuGtk::Delegate* delegate_;
+
+  // If non-NULL, the MenuModel that we use to populate and control the GTK
+  // menu (overriding the delegate as a controller).
+  ui::MenuModel* model_;
+
+  // For some menu items, we want to show the accelerator, but not actually
+  // explicitly handle it. To this end we connect those menu items' accelerators
+  // to this group, but don't attach this group to any top level window.
+  GtkAccelGroup* dummy_accel_group_;
+
+  // gtk_menu_popup() does not appear to take ownership of popup menus, so
+  // MenuGtk explicitly manages the lifetime of the menu.
+  GtkWidget* menu_;
+
+  // True when we should ignore "activate" signals.  Used to prevent
+  // menu items from getting activated when we are setting up the
+  // menu.
+  static bool block_activation_;
+
+  // We must free these at shutdown.
+  std::vector<MenuGtk*> submenus_we_own_;
+
+  ScopedRunnableMethodFactory<MenuGtk> factory_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_MENU_GTK_H_
diff --git a/chrome/browser/ui/gtk/nine_box.cc b/chrome/browser/ui/gtk/nine_box.cc
new file mode 100644
index 0000000..8956195
--- /dev/null
+++ b/chrome/browser/ui/gtk/nine_box.cc
@@ -0,0 +1,252 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/nine_box.h"
+
+#include "base/basictypes.h"
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/point.h"
+
+namespace {
+
+// Draw pixbuf |src| into |dst| at position (x, y).
+void DrawPixbuf(cairo_t* cr, GdkPixbuf* src, int x, int y, double alpha) {
+  gdk_cairo_set_source_pixbuf(cr, src, x, y);
+  cairo_paint_with_alpha(cr, alpha);
+}
+
+// Tile pixbuf |src| across |cr| at |x|, |y| for |width| and |height|.
+void TileImage(cairo_t* cr, GdkPixbuf* src,
+               int x, int y, int width, int height, double alpha) {
+  if (alpha == 1.0) {
+    gdk_cairo_set_source_pixbuf(cr, src, x, y);
+    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(cr, x, y, width, height);
+    cairo_fill(cr);
+  } else {
+    // Since there is no easy way to apply a mask to a fill operation, we create
+    // a secondary surface and tile into that, then paint it with |alpha|.
+    cairo_surface_t* surface = cairo_image_surface_create(
+        CAIRO_FORMAT_ARGB32, width, height);
+    cairo_t* tiled = cairo_create(surface);
+    gdk_cairo_set_source_pixbuf(tiled, src, 0, 0);
+    cairo_pattern_set_extend(cairo_get_source(tiled), CAIRO_EXTEND_REPEAT);
+    cairo_rectangle(tiled, 0, 0, width, height);
+    cairo_fill(tiled);
+
+    cairo_set_source_surface(cr, surface, x, y);
+    cairo_paint_with_alpha(cr, alpha);
+
+    cairo_destroy(tiled);
+    cairo_surface_destroy(surface);
+  }
+}
+
+}  // namespace
+
+NineBox::NineBox(int top_left, int top, int top_right, int left, int center,
+                 int right, int bottom_left, int bottom, int bottom_right)
+    : unref_pixbufs_on_destroy_(false) {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  images_[0] = top_left ? rb.GetPixbufNamed(top_left) : NULL;
+  images_[1] = top ? rb.GetPixbufNamed(top) : NULL;
+  images_[2] = top_right ? rb.GetPixbufNamed(top_right) : NULL;
+  images_[3] = left ? rb.GetPixbufNamed(left) : NULL;
+  images_[4] = center ? rb.GetPixbufNamed(center) : NULL;
+  images_[5] = right ? rb.GetPixbufNamed(right) : NULL;
+  images_[6] = bottom_left ? rb.GetPixbufNamed(bottom_left) : NULL;
+  images_[7] = bottom ? rb.GetPixbufNamed(bottom) : NULL;
+  images_[8] = bottom_right ? rb.GetPixbufNamed(bottom_right) : NULL;
+}
+
+NineBox::NineBox(int image, int top_margin, int bottom_margin, int left_margin,
+                 int right_margin)
+    : unref_pixbufs_on_destroy_(true) {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  GdkPixbuf* pixbuf = rb.GetPixbufNamed(image);
+  int width = gdk_pixbuf_get_width(pixbuf);
+  int height = gdk_pixbuf_get_height(pixbuf);
+  int inset_width = left_margin + right_margin;
+  int inset_height = top_margin + bottom_margin;
+
+  images_[0] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, 0, left_margin, top_margin);
+  images_[1] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, 0,
+                                        width - inset_width, top_margin);
+  images_[2] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin, 0,
+                                        right_margin, top_margin);
+  images_[3] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, top_margin,
+                                        left_margin, height - inset_height);
+  images_[4] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, top_margin,
+                                        width - inset_width,
+                                        height - inset_height);
+  images_[5] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin,
+                                        top_margin, right_margin,
+                                        height - inset_height);
+  images_[6] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, height - bottom_margin,
+                                        left_margin, bottom_margin);
+  images_[7] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin,
+                                        height - bottom_margin,
+                                        width - inset_width, bottom_margin);
+  images_[8] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin,
+                                        height - bottom_margin,
+                                        right_margin, bottom_margin);
+}
+
+NineBox::~NineBox() {
+  if (unref_pixbufs_on_destroy_) {
+    for (int i = 0; i < 9; i++) {
+      g_object_unref(images_[i]);
+    }
+  }
+}
+
+void NineBox::RenderToWidget(GtkWidget* dst) const {
+  RenderToWidgetWithOpacity(dst, 1.0);
+}
+
+void NineBox::RenderToWidgetWithOpacity(GtkWidget* dst, double opacity) const {
+  int dst_width = dst->allocation.width;
+  int dst_height = dst->allocation.height;
+
+  // The upper-left and lower-right corners of the center square in the
+  // rendering of the ninebox.
+  int x1 = gdk_pixbuf_get_width(images_[0]);
+  int y1 = gdk_pixbuf_get_height(images_[0]);
+  int x2 = images_[2] ? dst_width - gdk_pixbuf_get_width(images_[2]) : x1;
+  int y2 = images_[6] ? dst_height - gdk_pixbuf_get_height(images_[6]) : y1;
+  // Paint nothing if there's not enough room.
+  if (x2 < x1 || y2 < y1)
+    return;
+
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(dst->window));
+  // For widgets that have their own window, the allocation (x,y) coordinates
+  // are GdkWindow relative. For other widgets, the coordinates are relative
+  // to their container.
+  if (GTK_WIDGET_NO_WINDOW(dst)) {
+    // Transform our cairo from window to widget coordinates.
+    cairo_translate(cr, dst->allocation.x, dst->allocation.y);
+  }
+
+  if (base::i18n::IsRTL()) {
+    cairo_translate(cr, dst_width, 0.0f);
+    cairo_scale(cr, -1.0f, 1.0f);
+  }
+
+  // Top row, center image is horizontally tiled.
+  if (images_[0])
+    DrawPixbuf(cr, images_[0], 0, 0, opacity);
+  if (images_[1])
+    TileImage(cr, images_[1], x1, 0, x2 - x1, y1, opacity);
+  if (images_[2])
+    DrawPixbuf(cr, images_[2], x2, 0, opacity);
+
+  // Center row, all images are vertically tiled, center is horizontally tiled.
+  if (images_[3])
+    TileImage(cr, images_[3], 0, y1, x1, y2 - y1, opacity);
+  if (images_[4])
+    TileImage(cr, images_[4], x1, y1, x2 - x1, y2 - y1, opacity);
+  if (images_[5])
+    TileImage(cr, images_[5], x2, y1, dst_width - x2, y2 - y1, opacity);
+
+  // Bottom row, center image is horizontally tiled.
+  if (images_[6])
+    DrawPixbuf(cr, images_[6], 0, y2, opacity);
+  if (images_[7])
+    TileImage(cr, images_[7], x1, y2, x2 - x1, dst_height - y2, opacity);
+  if (images_[8])
+    DrawPixbuf(cr, images_[8], x2, y2, opacity);
+
+  cairo_destroy(cr);
+}
+
+void NineBox::RenderTopCenterStrip(cairo_t* cr, int x, int y,
+                                   int width) const {
+  const int height = gdk_pixbuf_get_height(images_[1]);
+  TileImage(cr, images_[1], x, y, width, height, 1.0);
+}
+
+void NineBox::ChangeWhiteToTransparent() {
+  for (int image_idx = 0; image_idx < 9; ++image_idx) {
+    GdkPixbuf* pixbuf = images_[image_idx];
+    if (!pixbuf)
+      continue;
+
+    if (!gdk_pixbuf_get_has_alpha(pixbuf))
+      continue;
+
+    guchar* pixels = gdk_pixbuf_get_pixels(pixbuf);
+    int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
+    int width = gdk_pixbuf_get_width(pixbuf);
+    int height = gdk_pixbuf_get_height(pixbuf);
+
+    if (width * 4 > rowstride) {
+      NOTREACHED();
+      continue;
+    }
+
+    for (int i = 0; i < height; ++i) {
+      for (int j = 0; j < width; ++j) {
+         guchar* pixel = &pixels[i * rowstride + j * 4];
+         if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) {
+           pixel[3] = 0;
+         }
+      }
+    }
+  }
+}
+
+void NineBox::ContourWidget(GtkWidget* widget) const {
+  int width = widget->allocation.width;
+  int height = widget->allocation.height;
+  int x1 = gdk_pixbuf_get_width(images_[0]);
+  int x2 = width - gdk_pixbuf_get_width(images_[2]);
+
+  // Paint the left and right sides.
+  GdkBitmap* mask = gdk_pixmap_new(NULL, width, height, 1);
+  gdk_pixbuf_render_threshold_alpha(images_[0], mask,
+                                    0, 0,
+                                    0, 0, -1, -1,
+                                    1);
+  gdk_pixbuf_render_threshold_alpha(images_[2], mask,
+                                    0, 0,
+                                    x2, 0, -1, -1,
+                                    1);
+
+  // Assume no transparency in the middle rectangle.
+  cairo_t* cr = gdk_cairo_create(mask);
+  cairo_rectangle(cr, x1, 0, x2 - x1, height);
+  cairo_fill(cr);
+  cairo_destroy(cr);
+
+  // Mask the widget's window's shape.
+  if (!base::i18n::IsRTL()) {
+    gtk_widget_shape_combine_mask(widget, mask, 0, 0);
+  } else {
+    GdkBitmap* flipped_mask = gdk_pixmap_new(NULL, width, height, 1);
+    cairo_t* flipped_cr = gdk_cairo_create(flipped_mask);
+
+    // Clear the target bitmap.
+    cairo_set_operator(flipped_cr, CAIRO_OPERATOR_CLEAR);
+    cairo_paint(flipped_cr);
+
+    // Apply flipping transformation.
+    cairo_translate(flipped_cr, width, 0.0f);
+    cairo_scale(flipped_cr, -1.0f, 1.0f);
+
+    // Paint the source bitmap onto the target.
+    cairo_set_operator(flipped_cr, CAIRO_OPERATOR_SOURCE);
+    gdk_cairo_set_source_pixmap(flipped_cr, mask, 0, 0);
+    cairo_paint(flipped_cr);
+    cairo_destroy(flipped_cr);
+
+    // Mask the widget.
+    gtk_widget_shape_combine_mask(widget, flipped_mask, 0, 0);
+    g_object_unref(flipped_mask);
+  }
+
+  g_object_unref(mask);
+}
diff --git a/chrome/browser/ui/gtk/nine_box.h b/chrome/browser/ui/gtk/nine_box.h
new file mode 100644
index 0000000..6a8fc85
--- /dev/null
+++ b/chrome/browser/ui/gtk/nine_box.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_NINE_BOX_H_
+#define CHROME_BROWSER_UI_GTK_NINE_BOX_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+// A NineBox manages a set of source images representing a 3x3 grid, where
+// non-corner images can be tiled to make a larger image.  It's used to
+// use bitmaps for constructing image-based resizable widgets like buttons.
+//
+// If you want just a vertical image that stretches in height but is fixed
+// in width, only pass in images for the left column (leave others NULL).
+// Similarly, for a horizontal image that stretches in width but is fixed in
+// height, only pass in images for the top row.
+//
+// TODO(port): add support for caching server-side pixmaps of prerendered
+// nineboxes.
+class NineBox {
+ public:
+  // Construct a NineBox with nine images.  Images are specified using resource
+  // ids that will be passed to the resource bundle.  Use 0 for no image.
+  NineBox(int top_left, int top, int top_right, int left, int center, int right,
+          int bottom_left, int bottom, int bottom_right);
+
+  // Construct a NineBox from a single image and insets indicating the sizes
+  // of the edges and corners.
+  NineBox(int image, int top_margin, int bottom_margin, int left_margin,
+          int right_margin);
+  ~NineBox();
+
+  // Render the NineBox to |dst|.
+  // The images will be tiled to fit into the widget.
+  void RenderToWidget(GtkWidget* dst) const;
+
+  // As above, but rendered partially transparent.
+  void RenderToWidgetWithOpacity(GtkWidget* dst, double opacity) const;
+
+  // Render the top row of images to |dst| between |x1| and |x1| + |width|.
+  // This is split from RenderToWidget so the toolbar can use it.
+  void RenderTopCenterStrip(cairo_t* cr, int x, int y, int width) const;
+
+  // Change all pixels that are white in |images_| to have 0 opacity.
+  void ChangeWhiteToTransparent();
+
+  // Set the shape of |widget| to match that of the ninebox. Note that |widget|
+  // must have its own window and be allocated. Also, currently only the top
+  // three images are used.
+  // TODO(estade): extend this function to use all 9 images (if it's ever
+  // needed).
+  void ContourWidget(GtkWidget* widget) const;
+
+ private:
+  GdkPixbuf* images_[9];
+  bool unref_pixbufs_on_destroy_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_NINE_BOX_H_
diff --git a/chrome/browser/ui/gtk/notifications/balloon_view_gtk.cc b/chrome/browser/ui/gtk/notifications/balloon_view_gtk.cc
new file mode 100644
index 0000000..f9bf94f
--- /dev/null
+++ b/chrome/browser/ui/gtk/notifications/balloon_view_gtk.cc
@@ -0,0 +1,471 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/notifications/balloon_view_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_options_menu_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace {
+
+// Margin, in pixels, between the notification frame and the contents
+// of the notification.
+const int kTopMargin = 0;
+const int kBottomMargin = 1;
+const int kLeftMargin = 1;
+const int kRightMargin = 1;
+
+// How many pixels of overlap there is between the shelf top and the
+// balloon bottom.
+const int kShelfBorderTopOverlap = 0;
+
+// Properties of the origin label.
+const int kLeftLabelMargin = 8;
+
+// TODO(johnnyg): Add a shadow for the frame.
+const int kLeftShadowWidth = 0;
+const int kRightShadowWidth = 0;
+const int kTopShadowWidth = 0;
+const int kBottomShadowWidth = 0;
+
+// Space in pixels between text and icon on the buttons.
+const int kButtonSpacing = 4;
+
+// Number of characters to show in the origin label before ellipsis.
+const int kOriginLabelCharacters = 18;
+
+// The shelf height for the system default font size.  It is scaled
+// with changes in the default font size.
+const int kDefaultShelfHeight = 21;
+const int kShelfVerticalMargin = 4;
+
+// The amount that the bubble collections class offsets from the side of the
+// screen.
+const int kScreenBorder = 5;
+
+// Colors specified in various ways for different parts of the UI.
+// These match the windows colors in balloon_view.cc
+const char* kLabelColor = "#7D7D7D";
+const double kShelfBackgroundColorR = 245.0 / 255.0;
+const double kShelfBackgroundColorG = 245.0 / 255.0;
+const double kShelfBackgroundColorB = 245.0 / 255.0;
+const double kDividerLineColorR = 180.0 / 255.0;
+const double kDividerLineColorG = 180.0 / 255.0;
+const double kDividerLineColorB = 180.0 / 255.0;
+
+// Makes the website label relatively smaller to the base text size.
+const char* kLabelMarkup = "<span size=\"small\" color=\"%s\">%s</span>";
+
+}  // namespace
+
+BalloonViewImpl::BalloonViewImpl(BalloonCollection* collection)
+    : balloon_(NULL),
+      frame_container_(NULL),
+      html_container_(NULL),
+      method_factory_(this),
+      close_button_(NULL),
+      animation_(NULL),
+      menu_showing_(false),
+      pending_close_(false) {
+}
+
+BalloonViewImpl::~BalloonViewImpl() {
+}
+
+void BalloonViewImpl::Close(bool by_user) {
+  // Delay a system-initiated close if the menu is showing.
+  if (!by_user && menu_showing_) {
+    pending_close_ = true;
+  } else {
+    MessageLoop::current()->PostTask(
+        FROM_HERE,
+        method_factory_.NewRunnableMethod(
+            &BalloonViewImpl::DelayedClose, by_user));
+  }
+}
+
+gfx::Size BalloonViewImpl::GetSize() const {
+  // BalloonView has no size if it hasn't been shown yet (which is when
+  // balloon_ is set).
+  if (!balloon_)
+    return gfx::Size();
+
+  // Although this may not be the instantaneous size of the balloon if
+  // called in the middle of an animation, it is the effective size that
+  // will result from the animation.
+  return gfx::Size(GetDesiredTotalWidth(), GetDesiredTotalHeight());
+}
+
+BalloonHost* BalloonViewImpl::GetHost() const {
+  return html_contents_.get();
+}
+
+void BalloonViewImpl::DelayedClose(bool by_user) {
+  html_contents_->Shutdown();
+  if (frame_container_) {
+    // It's possible that |frame_container_| was destroyed before the
+    // BalloonViewImpl if our related browser window was closed first.
+    gtk_widget_hide(frame_container_);
+  }
+  balloon_->OnClose(by_user);
+}
+
+void BalloonViewImpl::RepositionToBalloon() {
+  if (!frame_container_) {
+    // No need to create a slide animation when this balloon is fading out.
+    return;
+  }
+
+  DCHECK(balloon_);
+
+  // Create an amination from the current position to the desired one.
+  int start_x;
+  int start_y;
+  int start_w;
+  int start_h;
+  gtk_window_get_position(GTK_WINDOW(frame_container_), &start_x, &start_y);
+  gtk_window_get_size(GTK_WINDOW(frame_container_), &start_w, &start_h);
+
+  int end_x = balloon_->GetPosition().x();
+  int end_y = balloon_->GetPosition().y();
+  int end_w = GetDesiredTotalWidth();
+  int end_h = GetDesiredTotalHeight();
+
+  anim_frame_start_ = gfx::Rect(start_x, start_y, start_w, start_h);
+  anim_frame_end_ = gfx::Rect(end_x, end_y, end_w, end_h);
+  animation_.reset(new ui::SlideAnimation(this));
+  animation_->Show();
+}
+
+void BalloonViewImpl::AnimationProgressed(const ui::Animation* animation) {
+  DCHECK_EQ(animation, animation_.get());
+
+  // Linear interpolation from start to end position.
+  double end = animation->GetCurrentValue();
+  double start = 1.0 - end;
+
+  gfx::Rect frame_position(
+      static_cast<int>(start * anim_frame_start_.x() +
+                       end * anim_frame_end_.x()),
+      static_cast<int>(start * anim_frame_start_.y() +
+                       end * anim_frame_end_.y()),
+      static_cast<int>(start * anim_frame_start_.width() +
+                       end * anim_frame_end_.width()),
+      static_cast<int>(start * anim_frame_start_.height() +
+                       end * anim_frame_end_.height()));
+  gtk_window_resize(GTK_WINDOW(frame_container_),
+                    frame_position.width(), frame_position.height());
+  gtk_window_move(GTK_WINDOW(frame_container_),
+                  frame_position.x(), frame_position.y());
+
+  gfx::Rect contents_rect = GetContentsRectangle();
+  html_contents_->UpdateActualSize(contents_rect.size());
+}
+
+void BalloonViewImpl::Show(Balloon* balloon) {
+  theme_provider_ = GtkThemeProvider::GetFrom(balloon->profile());
+
+  const std::string source_label_text = l10n_util::GetStringFUTF8(
+      IDS_NOTIFICATION_BALLOON_SOURCE_LABEL,
+      balloon->notification().display_source());
+  const std::string options_text =
+      l10n_util::GetStringUTF8(IDS_NOTIFICATION_OPTIONS_MENU_LABEL);
+  const std::string dismiss_text =
+      l10n_util::GetStringUTF8(IDS_NOTIFICATION_BALLOON_DISMISS_LABEL);
+
+  balloon_ = balloon;
+  frame_container_ = gtk_window_new(GTK_WINDOW_POPUP);
+
+  // Construct the options menu.
+  options_menu_model_.reset(new NotificationOptionsMenuModel(balloon_));
+  options_menu_.reset(new MenuGtk(this, options_menu_model_.get()));
+
+  // Create a BalloonViewHost to host the HTML contents of this balloon.
+  html_contents_.reset(new BalloonViewHost(balloon));
+  html_contents_->Init();
+  gfx::NativeView contents = html_contents_->native_view();
+  g_signal_connect_after(contents, "expose-event",
+                         G_CALLBACK(OnContentsExposeThunk), this);
+
+  // Divide the frame vertically into the shelf and the content area.
+  GtkWidget* vbox = gtk_vbox_new(0, 0);
+  gtk_container_add(GTK_CONTAINER(frame_container_), vbox);
+
+  shelf_ = gtk_hbox_new(0, 0);
+  gtk_container_add(GTK_CONTAINER(vbox), shelf_);
+
+  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(
+      GTK_ALIGNMENT(alignment),
+      kTopMargin, kBottomMargin, kLeftMargin, kRightMargin);
+  gtk_widget_show_all(alignment);
+  gtk_container_add(GTK_CONTAINER(alignment), contents);
+  gtk_container_add(GTK_CONTAINER(vbox), alignment);
+
+  // Create a toolbar and add it to the shelf.
+  hbox_ = gtk_hbox_new(FALSE, 0);
+  gtk_widget_set_size_request(GTK_WIDGET(hbox_), -1, GetShelfHeight());
+  gtk_container_add(GTK_CONTAINER(shelf_), hbox_);
+  gtk_widget_show_all(vbox);
+
+  g_signal_connect(frame_container_, "expose-event",
+                   G_CALLBACK(OnExposeThunk), this);
+  g_signal_connect(frame_container_, "destroy",
+                   G_CALLBACK(OnDestroyThunk), this);
+
+  // Create a label for the source of the notification and add it to the
+  // toolbar.
+  GtkWidget* source_label_ = gtk_label_new(NULL);
+  char* markup = g_markup_printf_escaped(kLabelMarkup,
+                                         kLabelColor,
+                                         source_label_text.c_str());
+  gtk_label_set_markup(GTK_LABEL(source_label_), markup);
+  g_free(markup);
+  gtk_label_set_max_width_chars(GTK_LABEL(source_label_),
+                                kOriginLabelCharacters);
+  gtk_label_set_ellipsize(GTK_LABEL(source_label_), PANGO_ELLIPSIZE_END);
+  GtkWidget* label_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(label_alignment),
+                            kShelfVerticalMargin, kShelfVerticalMargin,
+                            kLeftLabelMargin, 0);
+  gtk_container_add(GTK_CONTAINER(label_alignment), source_label_);
+  gtk_box_pack_start(GTK_BOX(hbox_), label_alignment, FALSE, FALSE, 0);
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+  // Create a button to dismiss the balloon and add it to the toolbar.
+  close_button_.reset(new CustomDrawButton(IDR_TAB_CLOSE,
+                                           IDR_TAB_CLOSE_P,
+                                           IDR_TAB_CLOSE_H,
+                                           IDR_TAB_CLOSE));
+  close_button_->SetBackground(SK_ColorBLACK,
+                               rb.GetBitmapNamed(IDR_TAB_CLOSE),
+                               rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
+  gtk_widget_set_tooltip_text(close_button_->widget(), dismiss_text.c_str());
+  g_signal_connect(close_button_->widget(), "clicked",
+                   G_CALLBACK(OnCloseButtonThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(close_button_->widget(), GTK_CAN_FOCUS);
+  GtkWidget* close_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(close_alignment),
+                            kShelfVerticalMargin, kShelfVerticalMargin,
+                            0, kButtonSpacing);
+  gtk_container_add(GTK_CONTAINER(close_alignment), close_button_->widget());
+  gtk_box_pack_end(GTK_BOX(hbox_), close_alignment, FALSE, FALSE, 0);
+
+  // Create a button for showing the options menu, and add it to the toolbar.
+  options_menu_button_.reset(new CustomDrawButton(IDR_BALLOON_WRENCH,
+                                                  IDR_BALLOON_WRENCH_P,
+                                                  IDR_BALLOON_WRENCH_H,
+                                                  0));
+  gtk_widget_set_tooltip_text(options_menu_button_->widget(),
+                              options_text.c_str());
+  g_signal_connect(options_menu_button_->widget(), "button-press-event",
+                   G_CALLBACK(OnOptionsMenuButtonThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(options_menu_button_->widget(), GTK_CAN_FOCUS);
+  GtkWidget* options_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(options_alignment),
+                            kShelfVerticalMargin, kShelfVerticalMargin,
+                            0, kButtonSpacing);
+  gtk_container_add(GTK_CONTAINER(options_alignment),
+                    options_menu_button_->widget());
+  gtk_box_pack_end(GTK_BOX(hbox_), options_alignment, FALSE, FALSE, 0);
+
+  notification_registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                              NotificationService::AllSources());
+
+  // We don't do InitThemesFor() because it just forces a redraw.
+  gtk_util::ActAsRoundedWindow(frame_container_, gtk_util::kGdkBlack, 3,
+                               gtk_util::ROUNDED_ALL,
+                               gtk_util::BORDER_ALL);
+
+  // Realize the frame container so we can do size calculations.
+  gtk_widget_realize(frame_container_);
+
+  // Update to make sure we have everything sized properly and then move our
+  // window offscreen for its initial animation.
+  html_contents_->UpdateActualSize(balloon_->content_size());
+  int window_width;
+  gtk_window_get_size(GTK_WINDOW(frame_container_), &window_width, NULL);
+
+  int pos_x = gdk_screen_width() - window_width - kScreenBorder;
+  int pos_y = gdk_screen_height();
+  gtk_window_move(GTK_WINDOW(frame_container_), pos_x, pos_y);
+  balloon_->SetPosition(gfx::Point(pos_x, pos_y), false);
+  gtk_widget_show_all(frame_container_);
+
+  notification_registrar_.Add(this,
+      NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon));
+}
+
+void BalloonViewImpl::Update() {
+  DCHECK(html_contents_.get()) << "BalloonView::Update called before Show";
+  if (html_contents_->render_view_host())
+    html_contents_->render_view_host()->NavigateToURL(
+        balloon_->notification().content_url());
+}
+
+gfx::Point BalloonViewImpl::GetContentsOffset() const {
+  return gfx::Point(kLeftShadowWidth + kLeftMargin,
+                    GetShelfHeight() + kTopShadowWidth + kTopMargin);
+}
+
+int BalloonViewImpl::GetShelfHeight() const {
+  // TODO(johnnyg): add scaling here.
+  return kDefaultShelfHeight;
+}
+
+int BalloonViewImpl::GetDesiredTotalWidth() const {
+  return balloon_->content_size().width() +
+      kLeftMargin + kRightMargin + kLeftShadowWidth + kRightShadowWidth;
+}
+
+int BalloonViewImpl::GetDesiredTotalHeight() const {
+  return balloon_->content_size().height() +
+      kTopMargin + kBottomMargin + kTopShadowWidth + kBottomShadowWidth +
+      GetShelfHeight();
+}
+
+gfx::Rect BalloonViewImpl::GetContentsRectangle() const {
+  if (!frame_container_)
+    return gfx::Rect();
+
+  gfx::Size content_size = balloon_->content_size();
+  gfx::Point offset = GetContentsOffset();
+  int x = 0, y = 0;
+  gtk_window_get_position(GTK_WINDOW(frame_container_), &x, &y);
+  return gfx::Rect(x + offset.x(), y + offset.y(),
+                   content_size.width(), content_size.height());
+}
+
+void BalloonViewImpl::Observe(NotificationType type,
+                              const NotificationSource& source,
+                              const NotificationDetails& details) {
+  if (type == NotificationType::NOTIFY_BALLOON_DISCONNECTED) {
+    // If the renderer process attached to this balloon is disconnected
+    // (e.g., because of a crash), we want to close the balloon.
+    notification_registrar_.Remove(this,
+        NotificationType::NOTIFY_BALLOON_DISCONNECTED,
+        Source<Balloon>(balloon_));
+    Close(false);
+  } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    // Since all the buttons change their own properties, and our expose does
+    // all the real differences, we'll need a redraw.
+    gtk_widget_queue_draw(frame_container_);
+  } else {
+    NOTREACHED();
+  }
+}
+
+void BalloonViewImpl::OnCloseButton(GtkWidget* widget) {
+  Close(true);
+}
+
+// We draw black dots on the bottom left and right corners to fill in the
+// border. Otherwise, the border has a gap because the sharp corners of the
+// HTML view cut off the roundedness of the notification window.
+gboolean BalloonViewImpl::OnContentsExpose(GtkWidget* sender,
+                                           GdkEventExpose* event) {
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+
+  // According to a discussion on a mailing list I found, these degenerate
+  // paths are the officially supported way to draw points in Cairo.
+  cairo_set_source_rgb(cr, 0, 0, 0);
+  cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
+  cairo_set_line_width(cr, 1.0);
+  cairo_move_to(cr, 0.5, sender->allocation.height - 0.5);
+  cairo_close_path(cr);
+  cairo_move_to(cr, sender->allocation.width - 0.5,
+                    sender->allocation.height - 0.5);
+  cairo_close_path(cr);
+  cairo_stroke(cr);
+  cairo_destroy(cr);
+
+  return FALSE;
+}
+
+gboolean BalloonViewImpl::OnExpose(GtkWidget* sender, GdkEventExpose* event) {
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+
+  gfx::Size content_size = balloon_->content_size();
+  gfx::Point offset = GetContentsOffset();
+
+  // Draw a background color behind the shelf.
+  cairo_set_source_rgb(cr, kShelfBackgroundColorR,
+                       kShelfBackgroundColorG, kShelfBackgroundColorB);
+  cairo_rectangle(cr, kLeftMargin, kTopMargin + 0.5,
+                  content_size.width() - 0.5, GetShelfHeight());
+  cairo_fill(cr);
+
+  // Now draw a one pixel line between content and shelf.
+  cairo_move_to(cr, offset.x(), offset.y() - 1);
+  cairo_line_to(cr, offset.x() + content_size.width(), offset.y() - 1);
+  cairo_set_line_width(cr, 0.5);
+  cairo_set_source_rgb(cr, kDividerLineColorR,
+                       kDividerLineColorG, kDividerLineColorB);
+  cairo_stroke(cr);
+
+  cairo_destroy(cr);
+
+  return FALSE;
+}
+
+void BalloonViewImpl::OnOptionsMenuButton(GtkWidget* widget,
+                                          GdkEventButton* event) {
+  menu_showing_ = true;
+  options_menu_->PopupForWidget(widget, event->button, event->time);
+}
+
+// Called when the menu stops showing.
+void BalloonViewImpl::StoppedShowing() {
+  if (pending_close_)
+    DelayedClose(false);
+  menu_showing_ = false;
+}
+
+gboolean BalloonViewImpl::OnDestroy(GtkWidget* widget) {
+  frame_container_ = NULL;
+  Close(false);
+  return FALSE;  // Propagate.
+}
diff --git a/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h b/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h
new file mode 100644
index 0000000..9b02c0c
--- /dev/null
+++ b/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h
@@ -0,0 +1,142 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Draws the view for the balloons.
+
+#ifndef CHROME_BROWSER_UI_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+class BalloonCollection;
+class CustomDrawButton;
+class GtkThemeProvider;
+class MenuGtk;
+class NotificationDetails;
+class NotificationOptionsMenuModel;
+class NotificationSource;
+
+namespace ui {
+class SlideAnimation;
+}
+
+// A balloon view is the UI component for desktop notification toasts.
+// It draws a border, and within the border an HTML renderer.
+class BalloonViewImpl : public BalloonView,
+                        public MenuGtk::Delegate,
+                        public NotificationObserver,
+                        public ui::AnimationDelegate {
+ public:
+  explicit BalloonViewImpl(BalloonCollection* collection);
+  virtual ~BalloonViewImpl();
+
+  // BalloonView interface.
+  virtual void Show(Balloon* balloon);
+  virtual void Update();
+  virtual void RepositionToBalloon();
+  virtual void Close(bool by_user);
+  virtual gfx::Size GetSize() const;
+  virtual BalloonHost* GetHost() const;
+
+  // MenuGtk::Delegate interface.
+  virtual void StoppedShowing();
+
+ private:
+  // NotificationObserver interface.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // ui::AnimationDelegate interface.
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
+  // Do the delayed close work.
+  void DelayedClose(bool by_user);
+
+  // The height of the balloon's shelf.
+  // The shelf is where is close button is located.
+  int GetShelfHeight() const;
+
+  // The width and height that the frame should be.  If the balloon inside
+  // changes size, this will not be the same as the actual frame size until
+  // RepositionToBalloon() has been called and the animation completes.
+  int GetDesiredTotalWidth() const;
+  int GetDesiredTotalHeight() const;
+
+  // Where the balloon contents should be placed with respect to the top left
+  // of the frame.
+  gfx::Point GetContentsOffset() const;
+
+  // Where the balloon contents should be in screen coordinates.
+  gfx::Rect GetContentsRectangle() const;
+
+  CHROMEGTK_CALLBACK_1(BalloonViewImpl, gboolean, OnContentsExpose,
+                       GdkEventExpose*);
+  CHROMEGTK_CALLBACK_0(BalloonViewImpl, void, OnCloseButton);
+  CHROMEGTK_CALLBACK_1(BalloonViewImpl, gboolean, OnExpose, GdkEventExpose*);
+  CHROMEGTK_CALLBACK_1(BalloonViewImpl, void, OnOptionsMenuButton,
+                       GdkEventButton*);
+  CHROMEGTK_CALLBACK_0(BalloonViewImpl, gboolean, OnDestroy);
+
+  // Non-owned pointer to the balloon which owns this object.
+  Balloon* balloon_;
+
+  GtkThemeProvider* theme_provider_;
+
+  // The window that contains the frame of the notification.
+  GtkWidget* frame_container_;
+
+  // The widget that contains the shelf.
+  GtkWidget* shelf_;
+
+  // The hbox within the shelf that contains the buttons.
+  GtkWidget* hbox_;
+
+  // The window that contains the contents of the notification.
+  GtkWidget* html_container_;
+
+  // The renderer of the HTML contents.
+  scoped_ptr<BalloonViewHost> html_contents_;
+
+  // The following factory is used to call methods at a later time.
+  ScopedRunnableMethodFactory<BalloonViewImpl> method_factory_;
+
+  // Close button.
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  // An animation to move the balloon on the screen as its position changes.
+  scoped_ptr<ui::SlideAnimation> animation_;
+  gfx::Rect anim_frame_start_;
+  gfx::Rect anim_frame_end_;
+
+  // The options menu.
+  scoped_ptr<MenuGtk> options_menu_;
+  scoped_ptr<NotificationOptionsMenuModel> options_menu_model_;
+  // The button to open the options menu.
+  scoped_ptr<CustomDrawButton> options_menu_button_;
+
+  NotificationRegistrar notification_registrar_;
+
+  // Is the menu currently showing?
+  bool menu_showing_;
+
+  // Is there a pending system-initiated close?
+  bool pending_close_;
+
+  DISALLOW_COPY_AND_ASSIGN(BalloonViewImpl);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_
diff --git a/chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.cc b/chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.cc
new file mode 100644
index 0000000..7d85faa
--- /dev/null
+++ b/chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.h"
+
+#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
+
+BalloonViewHost::BalloonViewHost(Balloon* balloon)
+    : BalloonHost(balloon),
+      render_widget_host_view_(NULL) {
+}
+
+void BalloonViewHost::UpdateActualSize(const gfx::Size& new_size) {
+  render_widget_host_view_->SetSize(new_size);
+  gtk_widget_set_size_request(
+      native_view(), new_size.width(), new_size.height());
+}
+
+gfx::NativeView BalloonViewHost::native_view() const {
+  return render_widget_host_view_->native_view();
+}
+
+void BalloonViewHost::InitRenderWidgetHostView() {
+  DCHECK(render_view_host_);
+  render_widget_host_view_ = new RenderWidgetHostViewGtk(render_view_host_);
+  render_widget_host_view_->InitAsChild();
+}
+
+RenderWidgetHostView* BalloonViewHost::render_widget_host_view() const {
+  return render_widget_host_view_;
+}
diff --git a/chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.h b/chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.h
new file mode 100644
index 0000000..60b223c
--- /dev/null
+++ b/chrome/browser/ui/gtk/notifications/balloon_view_host_gtk.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_NOTIFICATIONS_BALLOON_VIEW_HOST_GTK_H_
+#define CHROME_BROWSER_UI_GTK_NOTIFICATIONS_BALLOON_VIEW_HOST_GTK_H_
+#pragma once
+
+#include "chrome/browser/notifications/balloon_host.h"
+#include "ui/gfx/native_widget_types.h"
+
+class RenderWidgetHostViewGtk;
+
+// BalloonViewHost class is a delegate to the renderer host for the HTML
+// notification.  When initialized it creates a new RenderViewHost and loads
+// the contents of the toast into it.  It also handles links within the toast,
+// loading them into a new tab.
+class BalloonViewHost : public BalloonHost {
+ public:
+  explicit BalloonViewHost(Balloon* balloon);
+
+  ~BalloonViewHost() {
+    Shutdown();
+  }
+
+  // Changes the size of the balloon.
+  void UpdateActualSize(const gfx::Size& new_size);
+
+  // Accessors.
+  gfx::NativeView native_view() const;
+
+ protected:
+  virtual void InitRenderWidgetHostView();
+  virtual RenderWidgetHostView* render_widget_host_view() const;
+
+ private:
+  // The GTK-specific widget host view.  Owned by its native view.
+  RenderWidgetHostViewGtk* render_widget_host_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(BalloonViewHost);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_NOTIFICATIONS_BALLOON_VIEW_HOST_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/advanced_contents_gtk.cc b/chrome/browser/ui/gtk/options/advanced_contents_gtk.cc
new file mode 100644
index 0000000..1b35b44
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/advanced_contents_gtk.cc
@@ -0,0 +1,1234 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/advanced_contents_gtk.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/string_tokenizer.h"
+#include "base/nix/xdg_util.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/fonts_languages_window.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/prefs/pref_set_observer.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/content_settings_window_gtk.h"
+#include "chrome/browser/ui/gtk/options/options_layout_gtk.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "chrome/browser/ui/options/options_util.h"
+#include "chrome/browser/ui/options/show_options_url.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/process_watcher.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Command used to configure GNOME proxy settings. The command was renamed
+// in January 2009, so both are used to work on both old and new systems.
+const char* kOldGNOMEProxyConfigCommand[] = {"gnome-network-preferences", NULL};
+const char* kGNOMEProxyConfigCommand[] = {"gnome-network-properties", NULL};
+// KDE3 and KDE4 are only slightly different, but incompatible. Go figure.
+const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL};
+const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL};
+
+// The URL for Linux ssl certificate configuration help.
+const char* const kLinuxCertificatesConfigUrl =
+    "http://code.google.com/p/chromium/wiki/LinuxCertManagement";
+
+// The URL for Linux proxy configuration help when not running under a
+// supported desktop environment.
+const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config";
+
+// The pixel width we wrap labels at.
+// TODO(evanm): make the labels wrap at the appropriate width.
+#if defined(OS_CHROMEOS)
+// ChromeOS uses IDS_OPTIONS_DIALOG_WIDTH_CHARS for options dialog width, which
+// is slightly smaller than the Gtk options dialog's 500px.
+const int kWrapWidth = 445;
+#else
+const int kWrapWidth = 475;
+#endif
+
+GtkWidget* CreateWrappedLabel(int string_id) {
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(string_id).c_str());
+  gtk_util::SetLabelWidth(label, kWrapWidth);
+  return label;
+}
+
+GtkWidget* CreateCheckButtonWithWrappedLabel(int string_id) {
+  GtkWidget* checkbox = gtk_check_button_new();
+  gtk_container_add(GTK_CONTAINER(checkbox),
+                    CreateWrappedLabel(string_id));
+  return checkbox;
+}
+
+GtkWidget* AddCheckButtonWithWrappedLabel(int string_id,
+                                          GtkWidget* container,
+                                          GCallback handler,
+                                          gpointer data) {
+  GtkWidget* checkbox = CreateCheckButtonWithWrappedLabel(string_id);
+  gtk_box_pack_start(GTK_BOX(container), checkbox, FALSE, FALSE, 0);
+  g_signal_connect(checkbox, "toggled", handler, data);
+
+  return checkbox;
+}
+
+// Don't let the widget handle scroll events. Instead, pass it on to the
+// parent widget.
+gboolean PassScrollToParent(GtkWidget* widget, GdkEvent* event,
+                            gpointer unused) {
+  if (widget->parent)
+    gtk_propagate_event(widget->parent, event);
+
+  return TRUE;
+}
+
+// Recursively search for a combo box among the children of |widget|.
+void SearchForComboBox(GtkWidget* widget, gpointer data) {
+  if (GTK_IS_COMBO_BOX(widget)) {
+    *reinterpret_cast<GtkWidget**>(data) = widget;
+  } else if (GTK_IS_CONTAINER(widget)) {
+    gtk_container_foreach(GTK_CONTAINER(widget), SearchForComboBox, data);
+  }
+}
+
+// Letting the combo boxes in the advanced options page handle scroll events is
+// annoying because they fight with the scrolled window. Also,
+// GtkFileChooserButton is buggy in that if you scroll on it very quickly it
+// spews Gtk-WARNINGs, which causes us to crash in debug. This function disables
+// scrolling for the combo box in |widget| (the first one it finds in a DFS).
+void DisableScrolling(GtkWidget* widget) {
+  gpointer combo_box_ptr = NULL;
+  SearchForComboBox(widget, &combo_box_ptr);
+
+  if (!combo_box_ptr) {
+    NOTREACHED() << " Did not find a combo box in this widget.";
+    return;
+  }
+
+  g_signal_connect(GTK_WIDGET(combo_box_ptr), "scroll-event",
+                   G_CALLBACK(PassScrollToParent), NULL);
+}
+
+}  // anonymous namespace
+
+
+///////////////////////////////////////////////////////////////////////////////
+// DownloadSection
+
+class DownloadSection : public OptionsPageBase {
+ public:
+  explicit DownloadSection(Profile* profile);
+  virtual ~DownloadSection() {}
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  // Callbacks for the widgets.
+  static void OnDownloadLocationChanged(GtkFileChooser* widget,
+                                        DownloadSection* section);
+  static void OnDownloadAskForSaveLocationChanged(GtkWidget* widget,
+                                                  DownloadSection* section);
+  static void OnResetFileHandlersClicked(GtkButton *button,
+                                         DownloadSection* section);
+
+  // The widgets for the download options.
+  GtkWidget* download_location_button_;
+  GtkWidget* download_ask_for_save_location_checkbox_;
+  GtkWidget* reset_file_handlers_label_;
+  GtkWidget* reset_file_handlers_button_;
+
+  // The widget containing the options for this section.
+  GtkWidget* page_;
+
+  // Pref members.
+  FilePathPrefMember default_download_location_;
+  BooleanPrefMember ask_for_save_location_;
+  StringPrefMember auto_open_files_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool pref_changing_;
+
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadSection);
+};
+
+DownloadSection::DownloadSection(Profile* profile)
+    : OptionsPageBase(profile),
+      pref_changing_(true) {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      page_, profile));
+
+  // Download location options.
+  download_location_button_ = gtk_file_chooser_button_new(
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE).c_str(),
+      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+  g_signal_connect(download_location_button_, "selection-changed",
+                   G_CALLBACK(OnDownloadLocationChanged), this);
+  DisableScrolling(download_location_button_);
+
+  // Add the default download path to the list of shortcuts in the selector.
+  FilePath default_download_path;
+  if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
+                        &default_download_path)) {
+    NOTREACHED();
+  } else {
+    if (!gtk_file_chooser_add_shortcut_folder(
+        GTK_FILE_CHOOSER(download_location_button_),
+        default_download_path.value().c_str(),
+        NULL)) {
+      NOTREACHED();
+    }
+  }
+
+  GtkWidget* download_location_control = gtk_util::CreateLabeledControlsGroup(
+      NULL,
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE).c_str(),
+      download_location_button_,
+      NULL);
+  gtk_box_pack_start(GTK_BOX(page_), download_location_control,
+                     FALSE, FALSE, 0);
+
+  download_ask_for_save_location_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION);
+  gtk_box_pack_start(GTK_BOX(page_), download_ask_for_save_location_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(download_ask_for_save_location_checkbox_, "clicked",
+                   G_CALLBACK(OnDownloadAskForSaveLocationChanged), this);
+  accessible_widget_helper_->SetWidgetName(
+      download_ask_for_save_location_checkbox_,
+      IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION);
+
+  // Option for resetting file handlers.
+  reset_file_handlers_label_ = CreateWrappedLabel(
+      IDS_OPTIONS_AUTOOPENFILETYPES_INFO);
+  gtk_misc_set_alignment(GTK_MISC(reset_file_handlers_label_), 0, 0);
+  gtk_box_pack_start(GTK_BOX(page_), reset_file_handlers_label_,
+                     FALSE, FALSE, 0);
+
+  reset_file_handlers_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT).c_str());
+  g_signal_connect(reset_file_handlers_button_, "clicked",
+                   G_CALLBACK(OnResetFileHandlersClicked), this);
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(button_hbox),
+                     reset_file_handlers_button_,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(page_),
+                     gtk_util::IndentWidget(button_hbox),
+                     FALSE, FALSE, 0);
+
+  // Init prefs watchers.
+  default_download_location_.Init(prefs::kDownloadDefaultDirectory,
+                                  profile->GetPrefs(), this);
+  ask_for_save_location_.Init(prefs::kPromptForDownload,
+                              profile->GetPrefs(), this);
+  auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, profile->GetPrefs(),
+                        this);
+
+  NotifyPrefChanged(NULL);
+}
+
+void DownloadSection::NotifyPrefChanged(const std::string* pref_name) {
+  pref_changing_ = true;
+  if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) {
+    gtk_file_chooser_set_current_folder(
+        GTK_FILE_CHOOSER(download_location_button_),
+            default_download_location_.GetValue().value().c_str());
+  }
+
+  if (!pref_name || *pref_name == prefs::kPromptForDownload) {
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(download_ask_for_save_location_checkbox_),
+        ask_for_save_location_.GetValue());
+  }
+
+  if (!pref_name || *pref_name == prefs::kDownloadExtensionsToOpen) {
+    DownloadPrefs* prefs = profile()->GetDownloadManager()->download_prefs();
+    bool enabled = prefs->IsAutoOpenUsed();
+    gtk_widget_set_sensitive(reset_file_handlers_label_, enabled);
+    gtk_widget_set_sensitive(reset_file_handlers_button_, enabled);
+  }
+  pref_changing_ = false;
+}
+
+// static
+void DownloadSection::OnDownloadLocationChanged(GtkFileChooser* widget,
+                                                DownloadSection* section) {
+  if (section->pref_changing_)
+    return;
+
+  gchar* folder = gtk_file_chooser_get_filename(widget);
+  FilePath path(folder);
+  g_free(folder);
+  // Gtk seems to call this signal multiple times, so we only set the pref and
+  // metric if something actually changed.
+  if (path != section->default_download_location_.GetValue()) {
+    section->default_download_location_.SetValue(path);
+    section->UserMetricsRecordAction(
+        UserMetricsAction("Options_SetDownloadDirectory"),
+        section->profile()->GetPrefs());
+  }
+}
+
+// static
+void DownloadSection::OnDownloadAskForSaveLocationChanged(
+    GtkWidget* widget, DownloadSection* section) {
+  if (section->pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  if (enabled) {
+    section->UserMetricsRecordAction(
+        UserMetricsAction("Options_AskForSaveLocation_Enable"),
+        section->profile()->GetPrefs());
+  } else {
+    section->UserMetricsRecordAction(
+        UserMetricsAction("Options_AskForSaveLocation_Disable"),
+        section->profile()->GetPrefs());
+  }
+  section->ask_for_save_location_.SetValue(enabled);
+}
+
+// static
+void DownloadSection::OnResetFileHandlersClicked(GtkButton *button,
+                                                 DownloadSection* section) {
+  section->profile()->GetDownloadManager()->download_prefs()->ResetAutoOpen();
+  section->UserMetricsRecordAction(
+      UserMetricsAction("Options_ResetAutoOpenFiles"),
+      section->profile()->GetPrefs());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// NetworkSection
+
+class NetworkSection : public OptionsPageBase {
+ public:
+  explicit NetworkSection(Profile* profile);
+  virtual ~NetworkSection() {}
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  struct ProxyConfigCommand {
+    std::string binary;
+    const char** argv;
+  };
+  // The callback functions for invoking the proxy config dialog.
+  static void OnChangeProxiesButtonClicked(GtkButton *button,
+                                           NetworkSection* section);
+  // Detect, and if possible, start the appropriate proxy config utility. On
+  // failure to do so, show the Linux proxy config URL in a new tab instead.
+  static void DetectAndStartProxyConfigUtil(Profile* profile);
+  // Show the proxy config URL in a new tab.
+  static void ShowLinuxProxyConfigUrl(Profile* profile);
+  // Search $PATH to find one of the commands. Store the full path to
+  // it in the |binary| field and the command array index in in |index|.
+  static bool SearchPATH(ProxyConfigCommand* commands, size_t ncommands,
+                         size_t* index);
+  // Start the given proxy configuration utility.
+  static void StartProxyConfigUtil(Profile* profile,
+                                   const ProxyConfigCommand& command);
+
+  // Tracks the state of proxy preferences.
+  scoped_ptr<PrefSetObserver> proxy_prefs_;
+
+  // The widget containing the options for this section.
+  GtkWidget* page_;
+
+  // The proxy configuration button.
+  GtkWidget* change_proxies_button_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkSection);
+};
+
+NetworkSection::NetworkSection(Profile* profile)
+    : OptionsPageBase(profile) {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GtkWidget* proxy_description_label = CreateWrappedLabel(
+      IDS_OPTIONS_PROXIES_LABEL);
+  gtk_misc_set_alignment(GTK_MISC(proxy_description_label), 0, 0);
+  gtk_box_pack_start(GTK_BOX(page_), proxy_description_label,
+                     FALSE, FALSE, 0);
+
+  change_proxies_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON).c_str());
+  g_signal_connect(change_proxies_button_, "clicked",
+                   G_CALLBACK(OnChangeProxiesButtonClicked), this);
+
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(button_hbox),
+                     change_proxies_button_,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(page_),
+                     gtk_util::IndentWidget(button_hbox),
+                     FALSE, FALSE, 0);
+
+  proxy_prefs_.reset(PrefSetObserver::CreateProxyPrefSetObserver(
+      profile->GetPrefs(), this));
+  NotifyPrefChanged(NULL);
+}
+
+void NetworkSection::NotifyPrefChanged(const std::string* pref_name) {
+  if (!pref_name || proxy_prefs_->IsObserved(*pref_name))
+    gtk_widget_set_sensitive(change_proxies_button_,
+                             !proxy_prefs_->IsManaged());
+}
+
+// static
+void NetworkSection::DetectAndStartProxyConfigUtil(Profile* profile) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+
+  ProxyConfigCommand command;
+  bool found_command = false;
+  switch (base::nix::GetDesktopEnvironment(env.get())) {
+    case base::nix::DESKTOP_ENVIRONMENT_GNOME: {
+      size_t index;
+      ProxyConfigCommand commands[2];
+      commands[0].argv = kGNOMEProxyConfigCommand;
+      commands[1].argv = kOldGNOMEProxyConfigCommand;
+      found_command = SearchPATH(commands, 2, &index);
+      if (found_command)
+        command = commands[index];
+      break;
+    }
+
+    case base::nix::DESKTOP_ENVIRONMENT_KDE3:
+      command.argv = kKDE3ProxyConfigCommand;
+      found_command = SearchPATH(&command, 1, NULL);
+      break;
+
+    case base::nix::DESKTOP_ENVIRONMENT_KDE4:
+      command.argv = kKDE4ProxyConfigCommand;
+      found_command = SearchPATH(&command, 1, NULL);
+      break;
+
+    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
+    case base::nix::DESKTOP_ENVIRONMENT_OTHER:
+      break;
+  }
+
+  if (found_command) {
+    StartProxyConfigUtil(profile, command);
+  } else {
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableFunction(&NetworkSection::ShowLinuxProxyConfigUrl, profile));
+  }
+}
+
+// static
+void NetworkSection::ShowLinuxProxyConfigUrl(Profile* profile) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+  const char* name = base::nix::GetDesktopEnvironmentName(env.get());
+  if (name)
+    LOG(ERROR) << "Could not find " << name << " network settings in $PATH";
+  browser::ShowOptionsURL(profile, GURL(kLinuxProxyConfigUrl));
+}
+
+// static
+void NetworkSection::OnChangeProxiesButtonClicked(GtkButton *button,
+                                                  NetworkSection* section) {
+  section->UserMetricsRecordAction(UserMetricsAction("Options_ChangeProxies"),
+                                   NULL);
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+      NewRunnableFunction(&NetworkSection::DetectAndStartProxyConfigUtil,
+                          section->profile()));
+}
+
+// static
+bool NetworkSection::SearchPATH(ProxyConfigCommand* commands, size_t ncommands,
+                                size_t* index) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  const char* path = getenv("PATH");
+  if (!path)
+    return false;
+  FilePath bin_path;
+  CStringTokenizer tk(path, path + strlen(path), ":");
+  // Search $PATH looking for the commands in order.
+  while (tk.GetNext()) {
+    for (size_t i = 0; i < ncommands; i++) {
+      bin_path = FilePath(tk.token()).Append(commands[i].argv[0]);
+      if (file_util::PathExists(bin_path)) {
+        commands[i].binary = bin_path.value();
+        if (index)
+          *index = i;
+        return true;
+      }
+    }
+  }
+  // Did not find any of the binaries in $PATH.
+  return false;
+}
+
+// static
+void NetworkSection::StartProxyConfigUtil(Profile* profile,
+                                          const ProxyConfigCommand& command) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  std::vector<std::string> argv;
+  argv.push_back(command.binary);
+  for (size_t i = 1; command.argv[i]; i++)
+    argv.push_back(command.argv[i]);
+  base::file_handle_mapping_vector no_files;
+  base::ProcessHandle handle;
+  if (!base::LaunchApp(argv, no_files, false, &handle)) {
+    LOG(ERROR) << "StartProxyConfigUtil failed to start " << command.binary;
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+        NewRunnableFunction(&NetworkSection::ShowLinuxProxyConfigUrl, profile));
+    return;
+  }
+  ProcessWatcher::EnsureProcessGetsReaped(handle);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TranslateSection
+
+class TranslateSection : public OptionsPageBase {
+ public:
+  explicit TranslateSection(Profile* profile);
+  virtual ~TranslateSection() {}
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  CHROMEGTK_CALLBACK_0(TranslateSection, void, OnTranslateClicked);
+
+  // Preferences for this section:
+  BooleanPrefMember enable_translate_;
+
+  // The widget containing the options for this section.
+  GtkWidget* page_;
+
+  // The checkbox.
+  GtkWidget* translate_checkbox_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool pref_changing_;
+
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(TranslateSection);
+};
+
+TranslateSection::TranslateSection(Profile* profile)
+    : OptionsPageBase(profile),
+      pref_changing_(true) {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      page_, profile));
+
+  translate_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
+  gtk_box_pack_start(GTK_BOX(page_), translate_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(translate_checkbox_, "clicked",
+                   G_CALLBACK(OnTranslateClickedThunk), this);
+  accessible_widget_helper_->SetWidgetName(
+      translate_checkbox_,
+      IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE);
+
+  // Init member prefs so we can update the controls if prefs change.
+  enable_translate_.Init(prefs::kEnableTranslate, profile->GetPrefs(), this);
+
+  NotifyPrefChanged(NULL);
+}
+
+void TranslateSection::NotifyPrefChanged(const std::string* pref_name) {
+  pref_changing_ = true;
+  if (!pref_name || *pref_name == prefs::kEnableTranslate) {
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(translate_checkbox_), enable_translate_.GetValue());
+  }
+  pref_changing_ = false;
+}
+
+void TranslateSection::OnTranslateClicked(GtkWidget* widget) {
+  if (pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  UserMetricsRecordAction(
+      enabled ?
+      UserMetricsAction("Options_Translate_Enable") :
+      UserMetricsAction("Options_Translate_Disable"),
+      profile()->GetPrefs());
+  enable_translate_.SetValue(enabled);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PrivacySection
+
+class PrivacySection : public OptionsPageBase {
+ public:
+  explicit PrivacySection(Profile* profile);
+  virtual ~PrivacySection() {}
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  // Try to make the the crash stats consent and the metrics upload
+  // permission match the |reporting_enabled_checkbox_|.
+  void ResolveMetricsReportingEnabled();
+
+  // The callback functions for the options widgets.
+  static void OnContentSettingsClicked(GtkButton* button,
+                                       PrivacySection* privacy_section);
+  static void OnClearBrowsingDataButtonClicked(GtkButton* widget,
+                                               PrivacySection* page);
+  static void OnLearnMoreLinkClicked(GtkButton *button,
+                                     PrivacySection* privacy_section);
+  static void OnEnableLinkDoctorChange(GtkWidget* widget,
+                                       PrivacySection* options_window);
+  static void OnEnableSuggestChange(GtkWidget* widget,
+                                    PrivacySection* options_window);
+  static void OnDNSPrefetchingChange(GtkWidget* widget,
+                                     PrivacySection* options_window);
+  static void OnSafeBrowsingChange(GtkWidget* widget,
+                                   PrivacySection* options_window);
+  static void OnLoggingChange(GtkWidget* widget,
+                              PrivacySection* options_window);
+
+  // The widget containing the options for this section.
+  GtkWidget* page_;
+
+  // The widgets for the privacy options.
+  GtkWidget* enable_link_doctor_checkbox_;
+  GtkWidget* enable_suggest_checkbox_;
+  GtkWidget* enable_dns_prefetching_checkbox_;
+  GtkWidget* enable_safe_browsing_checkbox_;
+#if defined(GOOGLE_CHROME_BUILD)
+  GtkWidget* reporting_enabled_checkbox_;
+#endif
+
+  // Preferences for this section:
+  BooleanPrefMember alternate_error_pages_;
+  BooleanPrefMember use_suggest_;
+  BooleanPrefMember dns_prefetch_enabled_;
+  BooleanPrefMember safe_browsing_;
+  BooleanPrefMember enable_metrics_recording_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool pref_changing_;
+
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrivacySection);
+};
+
+PrivacySection::PrivacySection(Profile* profile)
+    : OptionsPageBase(profile),
+      pref_changing_(true) {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      page_, profile));
+
+  GtkWidget* content_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON).c_str());
+  g_signal_connect(content_button, "clicked",
+                   G_CALLBACK(OnContentSettingsClicked), this);
+
+  GtkWidget* clear_data_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON).c_str());
+  g_signal_connect(clear_data_button, "clicked",
+                   G_CALLBACK(OnClearBrowsingDataButtonClicked), this);
+
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(button_hbox), content_button, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(button_hbox), clear_data_button, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(page_), gtk_util::IndentWidget(button_hbox),
+                     FALSE, FALSE, 0);
+
+  GtkWidget* section_description_label = CreateWrappedLabel(
+      IDS_OPTIONS_DISABLE_SERVICES);
+  gtk_misc_set_alignment(GTK_MISC(section_description_label), 0, 0);
+  gtk_box_pack_start(GTK_BOX(page_), section_description_label,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  GtkWidget* learn_more_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(learn_more_hbox), learn_more_link,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(page_), learn_more_hbox,
+                     FALSE, FALSE, 0);
+  g_signal_connect(learn_more_link, "clicked",
+                   G_CALLBACK(OnLearnMoreLinkClicked), this);
+
+  enable_link_doctor_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_LINKDOCTOR_PREF);
+  gtk_box_pack_start(GTK_BOX(page_), enable_link_doctor_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(enable_link_doctor_checkbox_, "clicked",
+                   G_CALLBACK(OnEnableLinkDoctorChange), this);
+  accessible_widget_helper_->SetWidgetName(
+      enable_link_doctor_checkbox_, IDS_OPTIONS_LINKDOCTOR_PREF);
+
+  enable_suggest_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_SUGGEST_PREF);
+  gtk_box_pack_start(GTK_BOX(page_), enable_suggest_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(enable_suggest_checkbox_, "clicked",
+                   G_CALLBACK(OnEnableSuggestChange), this);
+  accessible_widget_helper_->SetWidgetName(
+      enable_suggest_checkbox_, IDS_OPTIONS_SUGGEST_PREF);
+
+  enable_dns_prefetching_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION);
+  gtk_box_pack_start(GTK_BOX(page_), enable_dns_prefetching_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(enable_dns_prefetching_checkbox_, "clicked",
+                   G_CALLBACK(OnDNSPrefetchingChange), this);
+  accessible_widget_helper_->SetWidgetName(
+      enable_dns_prefetching_checkbox_,
+      IDS_NETWORK_DNS_PREFETCH_ENABLED_DESCRIPTION);
+
+  enable_safe_browsing_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION);
+  gtk_box_pack_start(GTK_BOX(page_), enable_safe_browsing_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(enable_safe_browsing_checkbox_, "clicked",
+                   G_CALLBACK(OnSafeBrowsingChange), this);
+  accessible_widget_helper_->SetWidgetName(
+      enable_safe_browsing_checkbox_,
+      IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION);
+
+#if defined(GOOGLE_CHROME_BUILD)
+  reporting_enabled_checkbox_ = CreateCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_ENABLE_LOGGING);
+  gtk_box_pack_start(GTK_BOX(page_), reporting_enabled_checkbox_,
+                     FALSE, FALSE, 0);
+  g_signal_connect(reporting_enabled_checkbox_, "clicked",
+                   G_CALLBACK(OnLoggingChange), this);
+  accessible_widget_helper_->SetWidgetName(
+      reporting_enabled_checkbox_, IDS_OPTIONS_ENABLE_LOGGING);
+#endif
+
+  // Init member prefs so we can update the controls if prefs change.
+  alternate_error_pages_.Init(prefs::kAlternateErrorPagesEnabled,
+                              profile->GetPrefs(), this);
+  use_suggest_.Init(prefs::kSearchSuggestEnabled,
+                    profile->GetPrefs(), this);
+  dns_prefetch_enabled_.Init(prefs::kDnsPrefetchingEnabled,
+                             profile->GetPrefs(), this);
+  safe_browsing_.Init(prefs::kSafeBrowsingEnabled, profile->GetPrefs(), this);
+  enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled,
+                                 g_browser_process->local_state(), this);
+  NotifyPrefChanged(NULL);
+}
+
+// static
+void PrivacySection::OnContentSettingsClicked(GtkButton* button,
+                                              PrivacySection* privacy_section) {
+  ContentSettingsWindowGtk::Show(
+      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
+      CONTENT_SETTINGS_TYPE_DEFAULT,
+      privacy_section->profile());
+}
+
+// static
+void PrivacySection::OnClearBrowsingDataButtonClicked(GtkButton* widget,
+                                                      PrivacySection* section) {
+  ClearBrowsingDataDialogGtk::Show(
+      GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))),
+      section->profile());
+}
+
+// static
+void PrivacySection::OnLearnMoreLinkClicked(GtkButton *button,
+                                            PrivacySection* privacy_section) {
+  GURL url = google_util::AppendGoogleLocaleParam(
+      GURL(chrome::kPrivacyLearnMoreURL));
+  browser::ShowOptionsURL(privacy_section->profile(), url);
+}
+
+// static
+void PrivacySection::OnEnableLinkDoctorChange(GtkWidget* widget,
+                                              PrivacySection* privacy_section) {
+  if (privacy_section->pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  privacy_section->UserMetricsRecordAction(
+      enabled ?
+          UserMetricsAction("Options_LinkDoctorCheckbox_Enable") :
+          UserMetricsAction("Options_LinkDoctorCheckbox_Disable"),
+      privacy_section->profile()->GetPrefs());
+  privacy_section->alternate_error_pages_.SetValue(enabled);
+}
+
+// static
+void PrivacySection::OnEnableSuggestChange(GtkWidget* widget,
+                                           PrivacySection* privacy_section) {
+  if (privacy_section->pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  privacy_section->UserMetricsRecordAction(
+      enabled ?
+          UserMetricsAction("Options_UseSuggestCheckbox_Enable") :
+          UserMetricsAction("Options_UseSuggestCheckbox_Disable"),
+      privacy_section->profile()->GetPrefs());
+  privacy_section->use_suggest_.SetValue(enabled);
+}
+
+// static
+void PrivacySection::OnDNSPrefetchingChange(GtkWidget* widget,
+                                           PrivacySection* privacy_section) {
+  if (privacy_section->pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  privacy_section->UserMetricsRecordAction(
+      enabled ?
+          UserMetricsAction("Options_DnsPrefetchCheckbox_Enable") :
+          UserMetricsAction("Options_DnsPrefetchCheckbox_Disable"),
+      privacy_section->profile()->GetPrefs());
+  privacy_section->dns_prefetch_enabled_.SetValue(enabled);
+}
+
+// static
+void PrivacySection::OnSafeBrowsingChange(GtkWidget* widget,
+                                          PrivacySection* privacy_section) {
+  if (privacy_section->pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  privacy_section->UserMetricsRecordAction(
+      enabled ?
+          UserMetricsAction("Options_SafeBrowsingCheckbox_Enable") :
+          UserMetricsAction("Options_SafeBrowsingCheckbox_Disable"),
+      privacy_section->profile()->GetPrefs());
+  privacy_section->safe_browsing_.SetValue(enabled);
+  SafeBrowsingService* safe_browsing_service =
+      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
+  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+      safe_browsing_service, &SafeBrowsingService::OnEnable, enabled));
+}
+
+// static
+void PrivacySection::OnLoggingChange(GtkWidget* widget,
+                                     PrivacySection* privacy_section) {
+  if (privacy_section->pref_changing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  privacy_section->UserMetricsRecordAction(
+      enabled ?
+          UserMetricsAction("Options_MetricsReportingCheckbox_Enable") :
+          UserMetricsAction("Options_MetricsReportingCheckbox_Disable"),
+      privacy_section->profile()->GetPrefs());
+  // Prevent us from being called again by ResolveMetricsReportingEnabled
+  // resetting the checkbox if there was a problem.
+  g_signal_handlers_block_by_func(widget,
+                                  reinterpret_cast<gpointer>(OnLoggingChange),
+                                  privacy_section);
+  privacy_section->ResolveMetricsReportingEnabled();
+  g_signal_handlers_unblock_by_func(widget,
+                                    reinterpret_cast<gpointer>(OnLoggingChange),
+                                    privacy_section);
+  privacy_section->enable_metrics_recording_.SetValue(enabled);
+}
+
+void PrivacySection::NotifyPrefChanged(const std::string* pref_name) {
+  pref_changing_ = true;
+  if (!pref_name || *pref_name == prefs::kAlternateErrorPagesEnabled) {
+    gtk_widget_set_sensitive(
+        GTK_WIDGET(enable_link_doctor_checkbox_),
+        !alternate_error_pages_.IsManaged());
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(enable_link_doctor_checkbox_),
+        alternate_error_pages_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kSearchSuggestEnabled) {
+    gtk_widget_set_sensitive(
+        GTK_WIDGET(enable_suggest_checkbox_),
+        !use_suggest_.IsManaged());
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(enable_suggest_checkbox_),
+        use_suggest_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kDnsPrefetchingEnabled) {
+    gtk_widget_set_sensitive(
+        GTK_WIDGET(enable_dns_prefetching_checkbox_),
+        !dns_prefetch_enabled_.IsManaged());
+    bool enabled = dns_prefetch_enabled_.GetValue();
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(enable_dns_prefetching_checkbox_), enabled);
+  }
+  if (!pref_name || *pref_name == prefs::kSafeBrowsingEnabled) {
+    gtk_widget_set_sensitive(
+        GTK_WIDGET(enable_safe_browsing_checkbox_),
+        !safe_browsing_.IsManaged());
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(enable_safe_browsing_checkbox_),
+        safe_browsing_.GetValue());
+  }
+#if defined(GOOGLE_CHROME_BUILD)
+  if (!pref_name || *pref_name == prefs::kMetricsReportingEnabled) {
+    gtk_widget_set_sensitive(
+        GTK_WIDGET(reporting_enabled_checkbox_),
+        !enable_metrics_recording_.IsManaged());
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_),
+        enable_metrics_recording_.GetValue());
+    ResolveMetricsReportingEnabled();
+  }
+#endif
+  pref_changing_ = false;
+}
+
+void PrivacySection::ResolveMetricsReportingEnabled() {
+#if defined(GOOGLE_CHROME_BUILD)
+  bool enabled = gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_));
+
+  enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled);
+
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reporting_enabled_checkbox_),
+                               enabled);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SecuritySection
+
+class SecuritySection : public OptionsPageBase {
+ public:
+  explicit SecuritySection(Profile* profile);
+  virtual ~SecuritySection() {}
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  // The callback functions for the options widgets.
+  static void OnManageCertificatesClicked(GtkButton* button,
+                                          SecuritySection* section);
+  static void OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton,
+                                          SecuritySection* section);
+  static void OnSSL3EnabledToggled(GtkToggleButton* togglebutton,
+                                   SecuritySection* section);
+  static void OnTLS1EnabledToggled(GtkToggleButton* togglebutton,
+                                   SecuritySection* section);
+
+  // The widget containing the options for this section.
+  GtkWidget* page_;
+  GtkWidget* rev_checking_enabled_checkbox_;
+  GtkWidget* ssl3_enabled_checkbox_;
+  GtkWidget* tls1_enabled_checkbox_;
+
+  // SSLConfigService prefs.
+  BooleanPrefMember rev_checking_enabled_;
+  BooleanPrefMember ssl3_enabled_;
+  BooleanPrefMember tls1_enabled_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool pref_changing_;
+
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(SecuritySection);
+};
+
+SecuritySection::SecuritySection(Profile* profile)
+    : OptionsPageBase(profile),
+      pref_changing_(true) {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      page_, profile));
+
+  GtkWidget* manage_certificates_label = CreateWrappedLabel(
+      IDS_OPTIONS_CERTIFICATES_LABEL);
+  gtk_misc_set_alignment(GTK_MISC(manage_certificates_label), 0, 0);
+  gtk_box_pack_start(GTK_BOX(page_), manage_certificates_label,
+                     FALSE, FALSE, 0);
+
+  // TODO(mattm): change this to a button to launch the system certificate
+  // manager, when one exists.
+  GtkWidget* manage_certificates_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON).c_str());
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  GtkWidget* manage_certificates_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(manage_certificates_hbox),
+                     manage_certificates_link, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(page_),
+                     gtk_util::IndentWidget(manage_certificates_hbox),
+                     FALSE, FALSE, 0);
+  g_signal_connect(manage_certificates_link, "clicked",
+                   G_CALLBACK(OnManageCertificatesClicked), this);
+
+  // TODO(mattm): should have a description label here and have the checkboxes
+  // indented, but IDS_OPTIONS_SSL_GROUP_DESCRIPTION isn't appropriate and
+  // didn't think of adding a Linux specific one before the string freeze.
+  rev_checking_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_SSL_CHECKREVOCATION, page_,
+      G_CALLBACK(OnRevCheckingEnabledToggled), this);
+  accessible_widget_helper_->SetWidgetName(
+      rev_checking_enabled_checkbox_, IDS_OPTIONS_SSL_CHECKREVOCATION);
+  ssl3_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_SSL_USESSL3, page_, G_CALLBACK(OnSSL3EnabledToggled), this);
+  accessible_widget_helper_->SetWidgetName(
+      ssl3_enabled_checkbox_, IDS_OPTIONS_SSL_USESSL3);
+  tls1_enabled_checkbox_ = AddCheckButtonWithWrappedLabel(
+      IDS_OPTIONS_SSL_USETLS1, page_, G_CALLBACK(OnTLS1EnabledToggled), this);
+  accessible_widget_helper_->SetWidgetName(
+      tls1_enabled_checkbox_, IDS_OPTIONS_SSL_USETLS1);
+
+  rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled,
+                             profile->GetPrefs(), this);
+  ssl3_enabled_.Init(prefs::kSSL3Enabled, profile->GetPrefs(), this);
+  tls1_enabled_.Init(prefs::kTLS1Enabled, profile->GetPrefs(), this);
+
+  NotifyPrefChanged(NULL);
+}
+
+void SecuritySection::NotifyPrefChanged(const std::string* pref_name) {
+  pref_changing_ = true;
+  if (!pref_name || *pref_name == prefs::kCertRevocationCheckingEnabled) {
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(rev_checking_enabled_checkbox_),
+        rev_checking_enabled_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kSSL3Enabled) {
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl3_enabled_checkbox_),
+                                 ssl3_enabled_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kTLS1Enabled) {
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tls1_enabled_checkbox_),
+                                 tls1_enabled_.GetValue());
+  }
+  pref_changing_ = false;
+}
+
+
+// static
+void SecuritySection::OnManageCertificatesClicked(GtkButton* button,
+                                                  SecuritySection* section) {
+  browser::ShowOptionsURL(section->profile(),
+                          GURL(kLinuxCertificatesConfigUrl));
+}
+
+// static
+void SecuritySection::OnRevCheckingEnabledToggled(GtkToggleButton* togglebutton,
+                                                  SecuritySection* section) {
+  if (section->pref_changing_)
+    return;
+
+  bool enabled = gtk_toggle_button_get_active(togglebutton);
+  if (enabled) {
+    section->UserMetricsRecordAction(
+        UserMetricsAction("Options_CheckCertRevocation_Enable"),
+        NULL);
+  } else {
+    section->UserMetricsRecordAction(
+        UserMetricsAction("Options_CheckCertRevocation_Disable"),
+        NULL);
+  }
+  section->rev_checking_enabled_.SetValue(enabled);
+}
+
+// static
+void SecuritySection::OnSSL3EnabledToggled(GtkToggleButton* togglebutton,
+                                           SecuritySection* section) {
+  if (section->pref_changing_)
+    return;
+
+  bool enabled = gtk_toggle_button_get_active(togglebutton);
+  if (enabled) {
+    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Enable"),
+                                     NULL);
+  } else {
+    section->UserMetricsRecordAction(UserMetricsAction("Options_SSL3_Disable"),
+                                     NULL);
+  }
+  section->ssl3_enabled_.SetValue(enabled);
+}
+
+// static
+void SecuritySection::OnTLS1EnabledToggled(GtkToggleButton* togglebutton,
+                                           SecuritySection* section) {
+  if (section->pref_changing_)
+    return;
+
+  bool enabled = gtk_toggle_button_get_active(togglebutton);
+  if (enabled) {
+    section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Enable"),
+                                     NULL);
+  } else {
+    section->UserMetricsRecordAction(UserMetricsAction("Options_TLS1_Disable"),
+                                     NULL);
+  }
+  section->tls1_enabled_.SetValue(enabled);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WebContentSection
+
+class WebContentSection : public OptionsPageBase {
+ public:
+  explicit WebContentSection(Profile* profile);
+  virtual ~WebContentSection() {}
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // The callback functions for the options widgets.
+  static void OnFontsAndLanguagesButtonClicked(GtkButton *button,
+                                               WebContentSection* section);
+
+  // The widget containing the options for this section.
+  GtkWidget* page_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebContentSection);
+};
+
+WebContentSection::WebContentSection(Profile* profile)
+    : OptionsPageBase(profile) {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GtkWidget* fonts_and_languages_label = CreateWrappedLabel(
+      IDS_OPTIONS_FONTSETTINGS_INFO);
+  gtk_misc_set_alignment(GTK_MISC(fonts_and_languages_label), 0, 0);
+  gtk_box_pack_start(GTK_BOX(page_), fonts_and_languages_label,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* fonts_and_languages_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_FONTSETTINGS_CONFIGUREFONTS_BUTTON).c_str());
+  g_signal_connect(fonts_and_languages_button, "clicked",
+                   G_CALLBACK(OnFontsAndLanguagesButtonClicked), this);
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(button_hbox),
+                     fonts_and_languages_button,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(page_),
+                     gtk_util::IndentWidget(button_hbox),
+                     FALSE, FALSE, 0);
+
+  // TODO(mattm): gears options would go here if we supported gears
+}
+
+// static
+void WebContentSection::OnFontsAndLanguagesButtonClicked(
+    GtkButton *button, WebContentSection* section) {
+  ShowFontsLanguagesWindow(GTK_WINDOW(gtk_widget_get_toplevel(section->page_)),
+                           FONTS_ENCODING_PAGE,
+                           section->profile());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AdvancedContentsGtk
+
+AdvancedContentsGtk::AdvancedContentsGtk(Profile* profile)
+    : profile_(profile) {
+  Init();
+}
+
+AdvancedContentsGtk::~AdvancedContentsGtk() {
+}
+
+void AdvancedContentsGtk::Init() {
+  scoped_ptr<OptionsLayoutBuilderGtk>
+    options_builder(OptionsLayoutBuilderGtk::Create());
+
+  privacy_section_.reset(new PrivacySection(profile_));
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY),
+      privacy_section_->get_page_widget(), false);
+
+  network_section_.reset(new NetworkSection(profile_));
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK),
+      network_section_->get_page_widget(), false);
+
+  translate_section_.reset(new TranslateSection(profile_));
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE),
+      translate_section_->get_page_widget(), false);
+
+  download_section_.reset(new DownloadSection(profile_));
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME),
+      download_section_->get_page_widget(), false);
+
+  web_content_section_.reset(new WebContentSection(profile_));
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT),
+      web_content_section_->get_page_widget(), false);
+
+  security_section_.reset(new SecuritySection(profile_));
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY),
+      security_section_->get_page_widget(), false);
+
+  page_ = options_builder->get_page_widget();
+}
diff --git a/chrome/browser/ui/gtk/options/advanced_contents_gtk.h b/chrome/browser/ui/gtk/options/advanced_contents_gtk.h
new file mode 100644
index 0000000..b1d6485
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/advanced_contents_gtk.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_ADVANCED_CONTENTS_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_ADVANCED_CONTENTS_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+
+class Profile;
+class DownloadSection;
+class NetworkSection;
+class PrivacySection;
+class SecuritySection;
+class TranslateSection;
+class WebContentSection;
+
+class AdvancedContentsGtk {
+ public:
+  explicit AdvancedContentsGtk(Profile* profile);
+  virtual ~AdvancedContentsGtk();
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  void Init();
+
+  // The profile.
+  Profile* profile_;
+
+  // The sections of the page.
+  scoped_ptr<DownloadSection> download_section_;
+  scoped_ptr<NetworkSection> network_section_;
+  scoped_ptr<TranslateSection> translate_section_;
+  scoped_ptr<PrivacySection> privacy_section_;
+  scoped_ptr<SecuritySection> security_section_;
+  scoped_ptr<WebContentSection> web_content_section_;
+
+  // The widget containing the advanced options sections.
+  GtkWidget* page_;
+
+  DISALLOW_COPY_AND_ASSIGN(AdvancedContentsGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_ADVANCED_CONTENTS_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/advanced_page_gtk.cc b/chrome/browser/ui/gtk/options/advanced_page_gtk.cc
new file mode 100644
index 0000000..3c7c354
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/advanced_page_gtk.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/advanced_page_gtk.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/options/options_util.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+AdvancedPageGtk::AdvancedPageGtk(Profile* profile)
+    : OptionsPageBase(profile),
+      advanced_contents_(profile),
+      managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_ADVANCED) {
+  Init();
+}
+
+AdvancedPageGtk::~AdvancedPageGtk() {
+}
+
+void AdvancedPageGtk::Init() {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(page_),
+                                 gtk_util::kContentAreaBorder);
+
+  gtk_box_pack_start(GTK_BOX(page_), managed_prefs_banner_.banner_widget(),
+                     false, false, 0);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_container_add(GTK_CONTAINER(page_), scroll_window);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_NEVER,
+                                 GTK_POLICY_AUTOMATIC);
+  // Note that typically we call gtk_scrolled_window_set_shadow_type right
+  // here, but the add_with_viewport method of GtkScrolledWindow already adds
+  // its own shadow.
+  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll_window),
+                                        advanced_contents_.get_page_widget());
+
+  GtkWidget* button_box = gtk_hbutton_box_new();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
+  GtkWidget* reset_button = gtk_button_new_with_label(
+        l10n_util::GetStringUTF8(IDS_OPTIONS_RESET).c_str());
+  g_signal_connect(reset_button, "clicked",
+                   G_CALLBACK(OnResetToDefaultsClickedThunk), this);
+  gtk_container_add(GTK_CONTAINER(button_box), reset_button);
+  gtk_box_pack_start(GTK_BOX(page_), button_box, FALSE, FALSE, 0);
+}
+
+void AdvancedPageGtk::OnResetToDefaultsClicked(GtkWidget* button) {
+  UserMetricsRecordAction(UserMetricsAction("Options_ResetToDefaults"), NULL);
+  GtkWidget* dialog_ = gtk_message_dialog_new(
+      GTK_WINDOW(gtk_widget_get_toplevel(page_)),
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
+      GTK_MESSAGE_QUESTION,
+      GTK_BUTTONS_NONE,
+      "%s",
+      l10n_util::GetStringUTF8(IDS_OPTIONS_RESET_MESSAGE).c_str());
+  gtk_util::ApplyMessageDialogQuirks(dialog_);
+  gtk_dialog_add_buttons(
+      GTK_DIALOG(dialog_),
+      l10n_util::GetStringUTF8(IDS_OPTIONS_RESET_CANCELLABEL).c_str(),
+      GTK_RESPONSE_CANCEL,
+      l10n_util::GetStringUTF8(IDS_OPTIONS_RESET_OKLABEL).c_str(),
+      GTK_RESPONSE_OK,
+      NULL);
+  gtk_window_set_title(GTK_WINDOW(dialog_),
+      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str());
+  g_signal_connect(dialog_, "response",
+                   G_CALLBACK(OnResetToDefaultsResponseThunk), this);
+
+  gtk_util::ShowDialog(dialog_);
+}
+
+void AdvancedPageGtk::OnResetToDefaultsResponse(GtkWidget* dialog,
+                                                int response_id) {
+  if (response_id == GTK_RESPONSE_OK) {
+    OptionsUtil::ResetToDefaults(profile());
+  }
+  gtk_widget_destroy(dialog);
+}
diff --git a/chrome/browser/ui/gtk/options/advanced_page_gtk.h b/chrome/browser/ui/gtk/options/advanced_page_gtk.h
new file mode 100644
index 0000000..39277ef
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/advanced_page_gtk.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_ADVANCED_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_ADVANCED_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/gtk/options/advanced_contents_gtk.h"
+#include "chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Profile;
+
+class AdvancedPageGtk : public OptionsPageBase {
+ public:
+  explicit AdvancedPageGtk(Profile* profile);
+  virtual ~AdvancedPageGtk();
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  void Init();
+
+  // Callback for reset to default button.
+  CHROMEGTK_CALLBACK_0(AdvancedPageGtk, void, OnResetToDefaultsClicked);
+
+  // Callback for reset to default confirmation dialog.
+  CHROMEGTK_CALLBACK_1(AdvancedPageGtk, void, OnResetToDefaultsResponse, int);
+
+  // The contents of the scroll box.
+  AdvancedContentsGtk advanced_contents_;
+
+  // The widget containing the options for this page.
+  GtkWidget* page_;
+
+  // Tracks managed preference warning banner state.
+  ManagedPrefsBannerGtk managed_prefs_banner_;
+
+  DISALLOW_COPY_AND_ASSIGN(AdvancedPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_ADVANCED_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/content_exception_editor.cc b/chrome/browser/ui/gtk/options/content_exception_editor.cc
new file mode 100644
index 0000000..1b5eadc
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_exception_editor.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/content_exception_editor.h"
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/content_exceptions_table_model.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+ContentExceptionEditor::ContentExceptionEditor(
+    GtkWindow* parent,
+    ContentExceptionEditor::Delegate* delegate,
+    ContentExceptionsTableModel* model,
+    bool allow_off_the_record,
+    int index,
+    const ContentSettingsPattern& pattern,
+    ContentSetting setting,
+    bool is_off_the_record)
+    : delegate_(delegate),
+      model_(model),
+      cb_model_(model->content_type()),
+      index_(index),
+      pattern_(pattern),
+      setting_(setting) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(is_new() ?
+                               IDS_EXCEPTION_EDITOR_NEW_TITLE :
+                               IDS_EXCEPTION_EDITOR_TITLE).c_str(),
+      parent,
+      // Non-modal.
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_CANCEL,
+      GTK_STOCK_OK,
+      GTK_RESPONSE_OK,
+      NULL);
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
+
+  entry_ = gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(entry_), pattern_.AsString().c_str());
+  g_signal_connect(entry_, "changed", G_CALLBACK(OnEntryChangedThunk), this);
+  gtk_entry_set_activates_default(GTK_ENTRY(entry_), TRUE);
+
+  pattern_image_ = gtk_image_new_from_pixbuf(NULL);
+
+  action_combo_ = gtk_combo_box_new_text();
+  for (int i = 0; i < cb_model_.GetItemCount(); ++i) {
+    gtk_combo_box_append_text(GTK_COMBO_BOX(action_combo_),
+        UTF16ToUTF8(cb_model_.GetItemAt(i)).c_str());
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(action_combo_),
+                           cb_model_.IndexForSetting(setting_));
+
+  otr_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_OTR_TITLE).c_str());
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(otr_checkbox_),
+                               is_off_the_record);
+
+  GtkWidget* table = gtk_util::CreateLabeledControlsGroup(
+      NULL,
+      l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_PATTERN_TITLE).c_str(),
+      gtk_util::CreateEntryImageHBox(entry_, pattern_image_),
+      l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_ACTION_TITLE).c_str(),
+      action_combo_,
+      NULL);
+  if (allow_off_the_record) {
+    gtk_table_attach(GTK_TABLE(table), otr_checkbox_,
+                     0, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
+  }
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), table,
+                     FALSE, FALSE, 0);
+
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  // Prime the state of the buttons.
+  OnEntryChanged(entry_);
+
+  gtk_util::ShowDialog(dialog_);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+bool ContentExceptionEditor::IsPatternValid(
+    const ContentSettingsPattern& pattern,
+    bool is_off_the_record) const {
+  bool is_valid_pattern = pattern.IsValid() &&
+      (model_->IndexOfExceptionByPattern(pattern, is_off_the_record) == -1);
+
+  return is_new() ? is_valid_pattern : (!pattern.AsString().empty() &&
+      ((pattern_ == pattern) || is_valid_pattern));
+}
+
+void ContentExceptionEditor::UpdateImage(GtkWidget* image, bool is_valid) {
+  return gtk_image_set_from_pixbuf(GTK_IMAGE(image),
+      ResourceBundle::GetSharedInstance().GetPixbufNamed(
+          is_valid ? IDR_INPUT_GOOD : IDR_INPUT_ALERT));
+}
+
+void ContentExceptionEditor::OnEntryChanged(GtkWidget* entry) {
+  ContentSettingsPattern new_pattern(gtk_entry_get_text(GTK_ENTRY(entry)));
+  bool is_off_the_record =
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(otr_checkbox_));
+  bool is_valid = IsPatternValid(new_pattern, is_off_the_record);
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
+                                    GTK_RESPONSE_OK, is_valid);
+  UpdateImage(pattern_image_, is_valid);
+}
+
+void ContentExceptionEditor::OnResponse(GtkWidget* sender, int response_id) {
+  if (response_id == GTK_RESPONSE_OK) {
+    // Notify our delegate to update everything.
+    ContentSettingsPattern new_pattern(gtk_entry_get_text(GTK_ENTRY(entry_)));
+    ContentSetting setting = cb_model_.SettingForIndex(
+        gtk_combo_box_get_active(GTK_COMBO_BOX(action_combo_)));
+    bool is_off_the_record =
+        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(otr_checkbox_));
+    delegate_->AcceptExceptionEdit(
+        new_pattern, setting, is_off_the_record, index_, is_new());
+  }
+
+  gtk_widget_destroy(dialog_);
+}
+
+void ContentExceptionEditor::OnWindowDestroy(GtkWidget* widget) {
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
diff --git a/chrome/browser/ui/gtk/options/content_exception_editor.h b/chrome/browser/ui/gtk/options/content_exception_editor.h
new file mode 100644
index 0000000..6839838
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_exception_editor.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_EXCEPTION_EDITOR_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_EXCEPTION_EDITOR_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/content_exceptions_table_model.h"
+#include "chrome/browser/content_setting_combo_model.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/content_settings_types.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+// An editor which lets the user create or edit an individual exception to the
+// current content setting policy. (i.e. let www.google.com always show
+// images). Modal to parent.
+class ContentExceptionEditor {
+ public:
+  class Delegate {
+   public:
+    // Invoked when the user accepts the edit.
+    virtual void AcceptExceptionEdit(
+        const ContentSettingsPattern& pattern,
+        ContentSetting setting,
+        bool is_off_the_record,
+        int index,
+        bool is_new) = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  ContentExceptionEditor(GtkWindow* parent,
+                         Delegate* delegate,
+                         ContentExceptionsTableModel* model,
+                         bool allow_off_the_record,
+                         int index,
+                         const ContentSettingsPattern& pattern,
+                         ContentSetting setting,
+                         bool is_off_the_record);
+  virtual ~ContentExceptionEditor() {}
+
+ private:
+  // Returns true if we're adding a new item.
+  bool is_new() const { return index_ == -1; }
+
+  bool IsPatternValid(const ContentSettingsPattern& pattern,
+                      bool is_off_the_record) const;
+
+  void UpdateImage(GtkWidget* image, bool is_valid);
+
+  // GTK callbacks
+  CHROMEGTK_CALLBACK_0(ContentExceptionEditor, void, OnEntryChanged);
+  CHROMEGTK_CALLBACK_1(ContentExceptionEditor, void, OnResponse, int);
+  CHROMEGTK_CALLBACK_0(ContentExceptionEditor, void, OnWindowDestroy);
+
+  Delegate* delegate_;
+  ContentExceptionsTableModel* model_;
+
+  // The model for Combobox widget.
+  ContentSettingComboModel cb_model_;
+
+  // Index of the item being edited. If -1, indicates this is a new entry.
+  const int index_;
+  const ContentSettingsPattern pattern_;
+  const ContentSetting setting_;
+
+  // UI widgets.
+  GtkWidget* dialog_;
+  GtkWidget* entry_;
+  GtkWidget* pattern_image_;
+  GtkWidget* action_combo_;
+  GtkWidget* otr_checkbox_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentExceptionEditor);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_EXCEPTION_EDITOR_H_
diff --git a/chrome/browser/ui/gtk/options/content_exceptions_window_gtk.cc b/chrome/browser/ui/gtk/options/content_exceptions_window_gtk.cc
new file mode 100644
index 0000000..a3edcf0
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_exceptions_window_gtk.cc
@@ -0,0 +1,336 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h"
+
+#include <set>
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/content_exception_editor.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Singletons for each possible exception window.
+ContentExceptionsWindowGtk* instances[CONTENT_SETTINGS_NUM_TYPES] = { NULL };
+
+}  // namespace
+
+// static
+void ContentExceptionsWindowGtk::ShowExceptionsWindow(
+    GtkWindow* parent,
+    HostContentSettingsMap* map,
+    HostContentSettingsMap* off_the_record_map,
+    ContentSettingsType type) {
+  DCHECK(map);
+  DCHECK(type < CONTENT_SETTINGS_NUM_TYPES);
+  // Geolocation exceptions are handled by SimpleContentExceptionsWindow.
+  DCHECK_NE(type, CONTENT_SETTINGS_TYPE_GEOLOCATION);
+  // Notification exceptions are handled by SimpleContentExceptionsWindow.
+  DCHECK_NE(type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
+
+  if (!instances[type]) {
+    // Create the options window.
+    instances[type] =
+        new ContentExceptionsWindowGtk(parent, map, off_the_record_map, type);
+  } else {
+    gtk_util::PresentWindow(instances[type]->dialog_, 0);
+  }
+}
+
+ContentExceptionsWindowGtk::~ContentExceptionsWindowGtk() {
+}
+
+ContentExceptionsWindowGtk::ContentExceptionsWindowGtk(
+    GtkWindow* parent,
+    HostContentSettingsMap* map,
+    HostContentSettingsMap* off_the_record_map,
+    ContentSettingsType type)
+    : allow_off_the_record_(off_the_record_map) {
+  // Build the list backing that GTK uses, along with an adapter which will
+  // sort stuff without changing the underlying backing store.
+  list_store_ = gtk_list_store_new(COL_COUNT, G_TYPE_STRING, G_TYPE_STRING,
+                                   PANGO_TYPE_STYLE);
+  sort_list_store_ = gtk_tree_model_sort_new_with_model(
+      GTK_TREE_MODEL(list_store_));
+  treeview_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(sort_list_store_));
+  g_object_unref(list_store_);
+  g_object_unref(sort_list_store_);
+
+  // Set up the properties of the treeview
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview_), TRUE);
+  g_signal_connect(treeview_, "row-activated",
+                   G_CALLBACK(OnTreeViewRowActivateThunk), this);
+
+  GtkTreeViewColumn* pattern_column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_PATTERN_HEADER).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_PATTERN,
+      "style", COL_OTR,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), pattern_column);
+  gtk_tree_view_column_set_sort_column_id(pattern_column, COL_PATTERN);
+
+  GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_ACTION,
+      "style", COL_OTR,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), action_column);
+  gtk_tree_view_column_set_sort_column_id(action_column, COL_ACTION);
+
+  treeview_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(treeview_));
+  gtk_tree_selection_set_mode(treeview_selection_, GTK_SELECTION_MULTIPLE);
+  g_signal_connect(treeview_selection_, "changed",
+                   G_CALLBACK(OnTreeSelectionChangedThunk), this);
+
+  // Bind |list_store_| to our C++ model.
+  model_.reset(new ContentExceptionsTableModel(map, off_the_record_map, type));
+  model_adapter_.reset(new gtk_tree::TableAdapter(this, list_store_,
+                                                  model_.get()));
+  // Force a reload of everything to copy data into |list_store_|.
+  model_adapter_->OnModelChanged();
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      GetWindowTitle().c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
+  // Allow browser windows to go in front of the options dialog in metacity.
+  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox);
+
+  GtkWidget* treeview_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  // Create a scrolled window to wrap the treeview widget.
+  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
+  gtk_box_pack_start(GTK_BOX(treeview_box), scrolled, TRUE, TRUE, 0);
+
+  // If we also have an OTR profile, inform the user that OTR exceptions are
+  // displayed in italics.
+  if (allow_off_the_record_) {
+    GtkWidget* incognito_label = gtk_label_new(
+        l10n_util::GetStringUTF8(IDS_EXCEPTIONS_OTR_IN_ITALICS).c_str());
+    PangoAttrList* attributes = pango_attr_list_new();
+    pango_attr_list_insert(attributes,
+                           pango_attr_style_new(PANGO_STYLE_ITALIC));
+    gtk_label_set_attributes(GTK_LABEL(incognito_label), attributes);
+    pango_attr_list_unref(attributes);
+    gtk_misc_set_alignment(GTK_MISC(incognito_label), 0, 0);
+    gtk_box_pack_start(GTK_BOX(treeview_box), incognito_label, FALSE, FALSE, 0);
+  }
+
+  gtk_box_pack_start(GTK_BOX(hbox), treeview_box, TRUE, TRUE, 0);
+
+  GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GtkWidget* add_button = gtk_util::BuildDialogButton(dialog_,
+                                                      IDS_EXCEPTIONS_ADD_BUTTON,
+                                                      GTK_STOCK_ADD);
+  g_signal_connect(add_button, "clicked", G_CALLBACK(AddThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0);
+
+  edit_button_ = gtk_util::BuildDialogButton(dialog_,
+                                             IDS_EXCEPTIONS_EDIT_BUTTON,
+                                             GTK_STOCK_EDIT);
+  g_signal_connect(edit_button_, "clicked", G_CALLBACK(EditThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_box), edit_button_, FALSE, FALSE, 0);
+
+  remove_button_ = gtk_util::BuildDialogButton(dialog_,
+                                               IDS_EXCEPTIONS_REMOVE_BUTTON,
+                                               GTK_STOCK_REMOVE);
+  g_signal_connect(remove_button_, "clicked", G_CALLBACK(RemoveThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0);
+
+  remove_all_button_ = gtk_util::BuildDialogButton(
+      dialog_,
+      IDS_EXCEPTIONS_REMOVEALL_BUTTON,
+      GTK_STOCK_CLEAR);
+  g_signal_connect(remove_all_button_, "clicked", G_CALLBACK(RemoveAllThunk),
+                   this);
+  gtk_box_pack_start(GTK_BOX(button_box), remove_all_button_, FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0);
+
+  UpdateButtonState();
+
+  gtk_util::ShowDialogWithLocalizedSize(dialog_,
+      IDS_CONTENT_EXCEPTION_DIALOG_WIDTH_CHARS,
+      -1,
+      true);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+void ContentExceptionsWindowGtk::SetColumnValues(int row, GtkTreeIter* iter) {
+  string16 pattern = model_->GetText(row, IDS_EXCEPTIONS_PATTERN_HEADER);
+  gtk_list_store_set(list_store_, iter, COL_PATTERN,
+                     UTF16ToUTF8(pattern).c_str(), -1);
+
+  string16 action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER);
+  gtk_list_store_set(list_store_, iter, COL_ACTION,
+                     UTF16ToUTF8(action).c_str(), -1);
+
+  bool is_off_the_record = model_->entry_is_off_the_record(row);
+  PangoStyle style =
+      is_off_the_record ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
+  gtk_list_store_set(list_store_, iter, COL_OTR, style, -1);
+}
+
+void ContentExceptionsWindowGtk::AcceptExceptionEdit(
+    const ContentSettingsPattern& pattern,
+    ContentSetting setting,
+    bool is_off_the_record,
+    int index,
+    bool is_new) {
+  DCHECK(!is_off_the_record || allow_off_the_record_);
+
+  if (!is_new)
+    model_->RemoveException(index);
+
+  model_->AddException(pattern, setting, is_off_the_record);
+
+  int new_index = model_->IndexOfExceptionByPattern(pattern, is_off_the_record);
+  DCHECK_NE(-1, new_index);
+
+  gtk_tree::SelectAndFocusRowNum(new_index, GTK_TREE_VIEW(treeview_));
+
+  UpdateButtonState();
+}
+
+void ContentExceptionsWindowGtk::UpdateButtonState() {
+  int num_selected = gtk_tree_selection_count_selected_rows(
+      treeview_selection_);
+  int row_count = gtk_tree_model_iter_n_children(
+      GTK_TREE_MODEL(sort_list_store_), NULL);
+
+  // TODO(erg): http://crbug.com/34177 , support editing of more than one entry
+  // at a time.
+  gtk_widget_set_sensitive(edit_button_, num_selected == 1);
+  gtk_widget_set_sensitive(remove_button_, num_selected >= 1);
+  gtk_widget_set_sensitive(remove_all_button_, row_count > 0);
+}
+
+void ContentExceptionsWindowGtk::Add(GtkWidget* widget) {
+  new ContentExceptionEditor(GTK_WINDOW(dialog_),
+                             this, model_.get(), allow_off_the_record_, -1,
+                             ContentSettingsPattern(),
+                             CONTENT_SETTING_BLOCK, false);
+}
+
+void ContentExceptionsWindowGtk::Edit(GtkWidget* widget) {
+  std::set<std::pair<int, int> > indices;
+  GetSelectedModelIndices(&indices);
+  DCHECK_GT(indices.size(), 0u);
+  int index = indices.begin()->first;
+  const HostContentSettingsMap::PatternSettingPair& entry =
+      model_->entry_at(index);
+  new ContentExceptionEditor(GTK_WINDOW(dialog_), this, model_.get(),
+                             allow_off_the_record_, index,
+                             entry.first, entry.second,
+                             model_->entry_is_off_the_record(index));
+}
+
+void ContentExceptionsWindowGtk::Remove(GtkWidget* widget) {
+  std::set<std::pair<int, int> > model_selected_indices;
+  GetSelectedModelIndices(&model_selected_indices);
+
+  int selected_row = gtk_tree_model_iter_n_children(
+      GTK_TREE_MODEL(sort_list_store_), NULL);
+  for (std::set<std::pair<int, int> >::reverse_iterator i =
+           model_selected_indices.rbegin();
+       i != model_selected_indices.rend(); ++i) {
+    model_->RemoveException(i->first);
+    selected_row = std::min(selected_row, i->second);
+  }
+
+  int row_count = model_->RowCount();
+  if (row_count <= 0)
+    return;
+  if (selected_row >= row_count)
+    selected_row = row_count - 1;
+  gtk_tree::SelectAndFocusRowNum(selected_row,
+                                 GTK_TREE_VIEW(treeview_));
+
+  UpdateButtonState();
+}
+
+void ContentExceptionsWindowGtk::RemoveAll(GtkWidget* widget) {
+  model_->RemoveAll();
+  UpdateButtonState();
+}
+
+std::string ContentExceptionsWindowGtk::GetWindowTitle() const {
+  switch (model_->content_type()) {
+    case CONTENT_SETTINGS_TYPE_COOKIES:
+      return l10n_util::GetStringUTF8(IDS_COOKIE_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_IMAGES:
+      return l10n_util::GetStringUTF8(IDS_IMAGES_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
+      return l10n_util::GetStringUTF8(IDS_JS_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_PLUGINS:
+      return l10n_util::GetStringUTF8(IDS_PLUGINS_EXCEPTION_TITLE);
+    case CONTENT_SETTINGS_TYPE_POPUPS:
+      return l10n_util::GetStringUTF8(IDS_POPUP_EXCEPTION_TITLE);
+    default:
+      NOTREACHED();
+  }
+  return std::string();
+}
+
+void ContentExceptionsWindowGtk::GetSelectedModelIndices(
+    std::set<std::pair<int, int> >* indices) {
+  GtkTreeModel* model;
+  GList* paths = gtk_tree_selection_get_selected_rows(treeview_selection_,
+                                                      &model);
+  for (GList* item = paths; item; item = item->next) {
+    GtkTreePath* sorted_path = reinterpret_cast<GtkTreePath*>(item->data);
+    int sorted_row = gtk_tree::GetRowNumForPath(sorted_path);
+    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
+        GTK_TREE_MODEL_SORT(sort_list_store_), sorted_path);
+    int row = gtk_tree::GetRowNumForPath(path);
+    gtk_tree_path_free(path);
+    indices->insert(std::make_pair(row, sorted_row));
+  }
+
+  g_list_foreach(paths, (GFunc)gtk_tree_path_free, NULL);
+  g_list_free(paths);
+}
+
+void ContentExceptionsWindowGtk::OnTreeViewRowActivate(
+    GtkWidget* sender,
+    GtkTreePath* path,
+    GtkTreeViewColumn* column) {
+  Edit(sender);
+}
+
+void ContentExceptionsWindowGtk::OnWindowDestroy(GtkWidget* widget) {
+  instances[model_->content_type()] = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void ContentExceptionsWindowGtk::OnTreeSelectionChanged(
+    GtkWidget* selection) {
+  UpdateButtonState();
+}
diff --git a/chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h b/chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h
new file mode 100644
index 0000000..2f1940e
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_EXCEPTIONS_WINDOW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_EXCEPTIONS_WINDOW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/content_exceptions_table_model.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/options/content_exception_editor.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/content_settings_types.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class HostContentSettingsMap;
+
+// Dialog that lists each of the exceptions to the current content policy, and
+// has options for adding/editing/removing entries. Modal to parrent.
+class ContentExceptionsWindowGtk : public gtk_tree::TableAdapter::Delegate,
+                                   public ContentExceptionEditor::Delegate {
+ public:
+  static void ShowExceptionsWindow(GtkWindow* window,
+                                   HostContentSettingsMap* map,
+                                   HostContentSettingsMap* off_the_record_map,
+                                   ContentSettingsType content_type);
+
+  ~ContentExceptionsWindowGtk();
+
+  // gtk_tree::TableAdapter::Delegate implementation:
+  virtual void SetColumnValues(int row, GtkTreeIter* iter);
+
+  // ContentExceptionEditor::Delegate implementation:
+  virtual void AcceptExceptionEdit(
+      const ContentSettingsPattern& pattern,
+      ContentSetting setting,
+      bool is_off_the_record,
+      int index,
+      bool is_new);
+
+ private:
+  // Column ids for |list_store_|.
+  enum {
+    COL_PATTERN,
+    COL_ACTION,
+    COL_OTR,
+    COL_COUNT
+  };
+
+  ContentExceptionsWindowGtk(GtkWindow* parent,
+                             HostContentSettingsMap* map,
+                             HostContentSettingsMap* off_the_record_map,
+                             ContentSettingsType type);
+
+  // Updates which buttons are enabled.
+  void UpdateButtonState();
+
+  // Callbacks for the buttons.
+  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, Add);
+  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, Edit);
+  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, Remove);
+  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, RemoveAll);
+
+  // Returns the title of the window (changes based on what ContentSettingsType
+  // was set to in the constructor).
+  std::string GetWindowTitle() const;
+
+  // Gets the selected indicies in the two list stores. Indicies are returned
+  // in <list_store_, sort_list_store_> order.
+  void GetSelectedModelIndices(std::set<std::pair<int, int> >* indices);
+
+  // GTK Callbacks
+  CHROMEGTK_CALLBACK_2(ContentExceptionsWindowGtk, void,
+                       OnTreeViewRowActivate, GtkTreePath*, GtkTreeViewColumn*);
+  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void, OnWindowDestroy);
+  CHROMEGTK_CALLBACK_0(ContentExceptionsWindowGtk, void,
+                       OnTreeSelectionChanged);
+
+  // The list presented in |treeview_|. Separate from |list_store_|, the list
+  // that backs |sort_model_|. This separation comes so the user can sort the
+  // data on screen without changing the underlying |list_store_|.
+  GtkTreeModel* sort_list_store_;
+
+  // The backing to |sort_list_store_|. Doesn't change when sorted.
+  GtkListStore* list_store_;
+
+  // The C++, views-ish, cross-platform model class that actually contains the
+  // gold standard data.
+  scoped_ptr<ContentExceptionsTableModel> model_;
+
+  // True if we also show exceptions from an OTR profile.
+  bool allow_off_the_record_;
+
+  // The adapter that ferries data back and forth between |model_| and
+  // |list_store_| whenever either of them change.
+  scoped_ptr<gtk_tree::TableAdapter> model_adapter_;
+
+  // The exception window.
+  GtkWidget* dialog_;
+
+  // The treeview that presents the site/action pairs.
+  GtkWidget* treeview_;
+
+  // The current user selection from |treeview_|.
+  GtkTreeSelection* treeview_selection_;
+
+  // Buttons.
+  GtkWidget* edit_button_;
+  GtkWidget* remove_button_;
+  GtkWidget* remove_all_button_;
+
+  friend class ContentExceptionsWindowGtkUnittest;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_EXCEPTIONS_WINDOW_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/content_exceptions_window_gtk_unittest.cc b/chrome/browser/ui/gtk/options/content_exceptions_window_gtk_unittest.cc
new file mode 100644
index 0000000..16b8f0c
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_exceptions_window_gtk_unittest.cc
@@ -0,0 +1,211 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h"
+
+#include "chrome/test/testing_profile.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::ElementsAre;
+
+class ContentExceptionsWindowGtkUnittest : public testing::Test {
+ public:
+  ContentExceptionsWindowGtkUnittest()
+      : ui_thread_(BrowserThread::UI, &message_loop_),
+        host_content_settings_map_(profile_.GetHostContentSettingsMap()),
+        window_(NULL) {
+  }
+
+  ~ContentExceptionsWindowGtkUnittest() {
+    // This will delete window_ too.
+    gtk_widget_destroy(window_->dialog_);
+    message_loop_.RunAllPending();
+  }
+
+  void AddException(const std::string& pattern, ContentSetting value) {
+    host_content_settings_map_->SetContentSetting(
+        ContentSettingsPattern(pattern),
+        CONTENT_SETTINGS_TYPE_JAVASCRIPT,
+        "",
+        value);
+  }
+
+  void BuildWindow() {
+    window_ = new ContentExceptionsWindowGtk(
+        NULL,
+        host_content_settings_map_,
+        NULL,
+        CONTENT_SETTINGS_TYPE_JAVASCRIPT);
+  }
+
+  // Actions:
+  void SelectRows(const std::vector<int>& rows) {
+    gtk_tree_selection_unselect_all(window_->treeview_selection_);
+
+    for (std::vector<int>::const_iterator it = rows.begin(); it != rows.end();
+         ++it) {
+      GtkTreeIter iter;
+      if (!gtk_tree_model_iter_nth_child(window_->sort_list_store_,
+                                         &iter, NULL, *it)) {
+        NOTREACHED();
+        return;
+      }
+
+      gtk_tree_selection_select_iter(window_->treeview_selection_, &iter);
+    }
+  }
+
+  void Remove() {
+    window_->Remove(window_->remove_button_);
+  }
+
+  // Getters:
+
+  void GetSelectedRows(std::set<std::pair<int, int> >* selected) {
+    window_->GetSelectedModelIndices(selected);
+  }
+
+  int StoreListStoreCount() {
+    return gtk_tree_model_iter_n_children(
+        GTK_TREE_MODEL(window_->sort_list_store_), NULL);
+  }
+
+  int ListStoreCount() {
+    return gtk_tree_model_iter_n_children(
+        GTK_TREE_MODEL(window_->list_store_), NULL);
+  }
+
+  std::set<std::string> Paths() {
+    std::set<std::string> paths;
+    GtkTreeIter iter;
+    bool valid = gtk_tree_model_get_iter_first(
+        GTK_TREE_MODEL(window_->sort_list_store_), &iter);
+
+    while (valid) {
+      gchar* str = NULL;
+      gtk_tree_model_get(GTK_TREE_MODEL(window_->sort_list_store_), &iter,
+                         0, &str, -1);
+      paths.insert(str);
+      g_free(str);
+
+      valid = gtk_tree_model_iter_next(
+          GTK_TREE_MODEL(window_->sort_list_store_), &iter);
+    }
+
+    return paths;
+  }
+
+  // Whether certain widgets are enabled:
+  bool EditButtonSensitive() {
+    return GTK_WIDGET_SENSITIVE(window_->edit_button_);
+  }
+
+  bool RemoveButtonSensitive() {
+    return GTK_WIDGET_SENSITIVE(window_->remove_button_);
+  }
+
+  bool RemoveAllSensitive() {
+    return GTK_WIDGET_SENSITIVE(window_->remove_all_button_);
+  }
+
+ private:
+  MessageLoop message_loop_;
+  BrowserThread ui_thread_;
+
+  TestingProfile profile_;
+  HostContentSettingsMap* host_content_settings_map_;
+
+  ContentExceptionsWindowGtk* window_;
+};
+
+TEST_F(ContentExceptionsWindowGtkUnittest, TestEmptyDisplay) {
+  BuildWindow();
+
+  EXPECT_EQ(0, StoreListStoreCount());
+  EXPECT_EQ(0, ListStoreCount());
+
+  EXPECT_FALSE(RemoveAllSensitive());
+}
+
+TEST_F(ContentExceptionsWindowGtkUnittest, TestDisplay) {
+  AddException("a", CONTENT_SETTING_BLOCK);
+  AddException("b", CONTENT_SETTING_ALLOW);
+
+  BuildWindow();
+
+  EXPECT_EQ(2, StoreListStoreCount());
+  EXPECT_EQ(2, ListStoreCount());
+
+  EXPECT_TRUE(RemoveAllSensitive());
+}
+
+TEST_F(ContentExceptionsWindowGtkUnittest, TestSelection) {
+  AddException("a", CONTENT_SETTING_BLOCK);
+
+  BuildWindow();
+
+  EXPECT_FALSE(EditButtonSensitive());
+  EXPECT_FALSE(RemoveButtonSensitive());
+
+  std::vector<int> rows;
+  rows.push_back(0);
+  SelectRows(rows);
+
+  EXPECT_TRUE(EditButtonSensitive());
+  EXPECT_TRUE(RemoveButtonSensitive());
+}
+
+TEST_F(ContentExceptionsWindowGtkUnittest, TestSimpleRemoval) {
+  AddException("a", CONTENT_SETTING_BLOCK);
+  AddException("b", CONTENT_SETTING_ALLOW);
+  AddException("c", CONTENT_SETTING_BLOCK);
+  AddException("d", CONTENT_SETTING_ALLOW);
+
+  BuildWindow();
+
+  std::vector<int> rows;
+  rows.push_back(1);
+  SelectRows(rows);
+
+  Remove();
+
+  EXPECT_EQ(3, StoreListStoreCount());
+  EXPECT_EQ(3, ListStoreCount());
+  EXPECT_TRUE(EditButtonSensitive());
+  EXPECT_TRUE(RemoveButtonSensitive());
+
+  std::set<std::pair<int, int> > selected;
+  GetSelectedRows(&selected);
+
+  ASSERT_EQ(1u, selected.size());
+  EXPECT_EQ(1, selected.begin()->first);
+  EXPECT_EQ(1, selected.begin()->second);
+  EXPECT_THAT(Paths(), ElementsAre("a", "c", "d"));
+}
+
+TEST_F(ContentExceptionsWindowGtkUnittest, TestComplexRemoval) {
+  AddException("a", CONTENT_SETTING_BLOCK);
+  AddException("b", CONTENT_SETTING_ALLOW);
+  AddException("c", CONTENT_SETTING_BLOCK);
+  AddException("d", CONTENT_SETTING_ALLOW);
+  AddException("e", CONTENT_SETTING_BLOCK);
+
+  BuildWindow();
+
+  std::vector<int> rows;
+  rows.push_back(1);
+  rows.push_back(3);
+  SelectRows(rows);
+
+  Remove();
+
+  std::set<std::pair<int, int> > selected;
+  GetSelectedRows(&selected);
+
+  ASSERT_EQ(1u, selected.size());
+  EXPECT_EQ(1, selected.begin()->first);
+  EXPECT_EQ(1, selected.begin()->second);
+  EXPECT_THAT(Paths(), ElementsAre("a", "c", "e"));
+}
diff --git a/chrome/browser/ui/gtk/options/content_filter_page_gtk.cc b/chrome/browser/ui/gtk/options/content_filter_page_gtk.cc
new file mode 100644
index 0000000..4d60dcd
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_filter_page_gtk.cc
@@ -0,0 +1,315 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/content_filter_page_gtk.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/content_settings/content_settings_details.h"
+#include "chrome/browser/content_settings/content_settings_pattern.h"
+#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
+#include "chrome/browser/geolocation/geolocation_exceptions_table_model.h"
+#include "chrome/browser/plugin_exceptions_table_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/notification_exceptions_table_model.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h"
+#include "chrome/browser/ui/gtk/options/simple_content_exceptions_window.h"
+#include "chrome/browser/ui/options/show_options_url.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/url_constants.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+ContentFilterPageGtk::ContentFilterPageGtk(Profile* profile,
+                                           ContentSettingsType content_type)
+    : OptionsPageBase(profile),
+      content_type_(content_type),
+      ask_radio_(NULL),
+      ignore_toggle_(false) {
+  static const int kTitleIDs[] = {
+    0,  // This dialog isn't used for cookies.
+    IDS_IMAGES_SETTING_LABEL,
+    IDS_JS_SETTING_LABEL,
+    IDS_PLUGIN_SETTING_LABEL,
+    IDS_POPUP_SETTING_LABEL,
+    IDS_GEOLOCATION_SETTING_LABEL,
+    IDS_NOTIFICATIONS_SETTING_LABEL,
+  };
+  COMPILE_ASSERT(arraysize(kTitleIDs) == CONTENT_SETTINGS_NUM_TYPES,
+                 kTitleIDs_IncorrectSize);
+
+  GtkWidget* title_label = gtk_util::CreateBoldLabel(
+      l10n_util::GetStringUTF8(kTitleIDs[content_type_]));
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(page_), title_label, FALSE, FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(page_), InitGroup());
+}
+
+ContentFilterPageGtk::~ContentFilterPageGtk() {
+}
+
+
+GtkWidget* ContentFilterPageGtk::InitGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  static const int kAllowIDs[] = {
+    0,  // This dialog isn't used for cookies.
+    IDS_IMAGES_LOAD_RADIO,
+    IDS_JS_ALLOW_RADIO,
+    IDS_PLUGIN_LOAD_RADIO,
+    IDS_POPUP_ALLOW_RADIO,
+    IDS_GEOLOCATION_ALLOW_RADIO,
+    IDS_NOTIFICATIONS_ALLOW_RADIO,
+  };
+  COMPILE_ASSERT(arraysize(kAllowIDs) == CONTENT_SETTINGS_NUM_TYPES,
+                 kAllowIDs_IncorrectSize);
+  allow_radio_ = gtk_radio_button_new_with_label(NULL,
+      l10n_util::GetStringUTF8(kAllowIDs[content_type_]).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), allow_radio_, FALSE, FALSE, 0);
+
+  static const int kAskIDs[] = {
+     0,  // This dialog isn't used for cookies.
+     0,
+     0,
+     IDS_PLUGIN_ASK_RADIO,
+     0,
+     IDS_GEOLOCATION_ASK_RADIO,
+     IDS_NOTIFICATIONS_ASK_RADIO,
+  };
+  COMPILE_ASSERT(arraysize(kAskIDs) == CONTENT_SETTINGS_NUM_TYPES,
+                 kAskIDs_IncorrectSize);
+  int askID = kAskIDs[content_type_];
+  if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS &&
+      !CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableClickToPlay)) {
+    askID = 0;
+  }
+
+  if (askID) {
+    ask_radio_ = gtk_radio_button_new_with_label_from_widget(
+        GTK_RADIO_BUTTON(allow_radio_),
+        l10n_util::GetStringUTF8(askID).c_str());
+    gtk_box_pack_start(GTK_BOX(vbox), ask_radio_, FALSE, FALSE, 0);
+  }
+
+  static const int kBlockIDs[] = {
+    0,  // This dialog isn't used for cookies.
+    IDS_IMAGES_NOLOAD_RADIO,
+    IDS_JS_DONOTALLOW_RADIO,
+    IDS_PLUGIN_NOLOAD_RADIO,
+    IDS_POPUP_BLOCK_RADIO,
+    IDS_GEOLOCATION_BLOCK_RADIO,
+    IDS_NOTIFICATIONS_BLOCK_RADIO,
+  };
+  COMPILE_ASSERT(arraysize(kBlockIDs) == CONTENT_SETTINGS_NUM_TYPES,
+                 kBlockIDs_IncorrectSize);
+  block_radio_ = gtk_radio_button_new_with_label_from_widget(
+      GTK_RADIO_BUTTON(allow_radio_),
+      l10n_util::GetStringUTF8(kBlockIDs[content_type_]).c_str());
+  gtk_box_pack_start(GTK_BOX(vbox), block_radio_, FALSE, FALSE, 0);
+
+  exceptions_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str());
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), exceptions_button_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+  g_signal_connect(G_OBJECT(allow_radio_), "toggled",
+                   G_CALLBACK(OnAllowToggledThunk), this);
+  if (ask_radio_) {
+    g_signal_connect(G_OBJECT(ask_radio_), "toggled",
+                     G_CALLBACK(OnAllowToggledThunk), this);
+  }
+  g_signal_connect(G_OBJECT(block_radio_), "toggled",
+                   G_CALLBACK(OnAllowToggledThunk), this);
+
+  g_signal_connect(G_OBJECT(exceptions_button_), "clicked",
+                   G_CALLBACK(OnExceptionsClickedThunk), this);
+
+  // Add the "Disable individual plug-ins..." link on the plug-ins page.
+  if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) {
+    GtkWidget* plugins_page_link = gtk_chrome_link_button_new(
+        l10n_util::GetStringUTF8(IDS_PLUGIN_SELECTIVE_DISABLE).c_str());
+    g_signal_connect(G_OBJECT(plugins_page_link), "clicked",
+                     G_CALLBACK(OnPluginsPageLinkClickedThunk), this);
+
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), plugins_page_link, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+  }
+
+  // Now that the buttons have been added to the view hierarchy, it's safe to
+  // call SetChecked() on them. So Update the Buttons.
+  ignore_toggle_ = true;
+  UpdateButtonsState();
+  ignore_toggle_ = false;
+
+  // Register for CONTENT_SETTINGS_CHANGED notifications to update the UI
+  // aften content settings change.
+  registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
+                 NotificationService::AllSources());
+  registrar_.Add(this, NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED,
+                 NotificationService::AllSources());
+  registrar_.Add(this, NotificationType::GEOLOCATION_SETTINGS_CHANGED,
+                 NotificationService::AllSources());
+
+  return vbox;
+}
+
+void ContentFilterPageGtk::UpdateButtonsState() {
+  // Get default_setting.
+  ContentSetting default_setting;
+  // If the content setting is managed, sensitive is set to false and the radio
+  // buttons will be disabled.
+  bool sensitive = true;
+  if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
+    default_setting = profile()->GetGeolocationContentSettingsMap()->
+        GetDefaultContentSetting();
+    sensitive = !profile()->GetGeolocationContentSettingsMap()->
+        IsDefaultContentSettingManaged();
+  } else if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+    default_setting = profile()->GetDesktopNotificationService()->
+        GetDefaultContentSetting();
+    sensitive = !profile()->GetDesktopNotificationService()->
+        IsDefaultContentSettingManaged();
+  } else {
+    default_setting = profile()->GetHostContentSettingsMap()->
+        GetDefaultContentSetting(content_type_);
+    sensitive = !profile()->GetHostContentSettingsMap()->
+        IsDefaultContentSettingManaged(content_type_);
+  }
+  // Set UI state.
+  if (default_setting == CONTENT_SETTING_ALLOW) {
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE);
+  } else if (default_setting == CONTENT_SETTING_ASK) {
+    DCHECK(ask_radio_);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ask_radio_), TRUE);
+  } else {
+    DCHECK(default_setting == CONTENT_SETTING_BLOCK);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE);
+  }
+
+  // Disable the UI if the default content setting is managed.
+  gtk_widget_set_sensitive(allow_radio_, sensitive);
+  gtk_widget_set_sensitive(block_radio_, sensitive);
+  if (ask_radio_)
+    gtk_widget_set_sensitive(ask_radio_, sensitive);
+  gtk_widget_set_sensitive(exceptions_button_, sensitive);
+}
+
+void ContentFilterPageGtk::OnAllowToggled(GtkWidget* toggle_button) {
+  if (ignore_toggle_)
+    return;
+
+  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
+    // When selecting a radio button, we get two signals (one for the old radio
+    // being toggled off, one for the new one being toggled on.)  Ignore the
+    // signal for toggling off the old button.
+    return;
+  }
+
+  DCHECK((toggle_button == allow_radio_) ||
+         (toggle_button == ask_radio_) ||
+         (toggle_button == block_radio_));
+
+  ContentSetting default_setting =
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(allow_radio_)) ?
+          CONTENT_SETTING_ALLOW :
+          gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(block_radio_)) ?
+              CONTENT_SETTING_BLOCK : CONTENT_SETTING_ASK;
+
+  DCHECK(ask_radio_ || default_setting != CONTENT_SETTING_ASK);
+  if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
+    profile()->GetGeolocationContentSettingsMap()->SetDefaultContentSetting(
+        default_setting);
+  } else if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+    profile()->GetDesktopNotificationService()->SetDefaultContentSetting(
+        default_setting);
+  } else {
+    profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
+        content_type_, default_setting);
+  }
+}
+
+void ContentFilterPageGtk::OnExceptionsClicked(GtkWidget* button) {
+  if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
+    SimpleContentExceptionsWindow::ShowExceptionsWindow(
+        GTK_WINDOW(gtk_widget_get_toplevel(button)),
+        new GeolocationExceptionsTableModel(
+            profile()->GetGeolocationContentSettingsMap()),
+        IDS_GEOLOCATION_EXCEPTION_TITLE);
+    return;
+  }
+  if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+    SimpleContentExceptionsWindow::ShowExceptionsWindow(
+        GTK_WINDOW(gtk_widget_get_toplevel(button)),
+        new NotificationExceptionsTableModel(
+            profile()->GetDesktopNotificationService()),
+        IDS_NOTIFICATIONS_EXCEPTION_TITLE);
+    return;
+  }
+  HostContentSettingsMap* settings_map =
+      profile()->GetHostContentSettingsMap();
+  HostContentSettingsMap* otr_settings_map =
+      profile()->HasOffTheRecordProfile() ?
+          profile()->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
+          NULL;
+  if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS &&
+      CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableResourceContentSettings)) {
+    PluginExceptionsTableModel* model =
+        new PluginExceptionsTableModel(settings_map, otr_settings_map);
+    model->LoadSettings();
+    SimpleContentExceptionsWindow::ShowExceptionsWindow(
+        GTK_WINDOW(gtk_widget_get_toplevel(button)),
+        model,
+        IDS_PLUGINS_EXCEPTION_TITLE);
+    return;
+  }
+  ContentExceptionsWindowGtk::ShowExceptionsWindow(
+      GTK_WINDOW(gtk_widget_get_toplevel(button)),
+      settings_map, otr_settings_map, content_type_);
+}
+
+void ContentFilterPageGtk::OnPluginsPageLinkClicked(GtkWidget* button) {
+  browser::ShowOptionsURL(profile(), GURL(chrome::kChromeUIPluginsURL));
+}
+
+void ContentFilterPageGtk::Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) {
+  if (type == NotificationType::CONTENT_SETTINGS_CHANGED) {
+    NotifyContentSettingsChanged(
+        Details<const ContentSettingsDetails>(details).ptr());
+  } else if (type == NotificationType::GEOLOCATION_SETTINGS_CHANGED) {
+    NotifyContentSettingsChanged(
+        Details<const ContentSettingsDetails>(details).ptr());
+  } else if (type == NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED) {
+    ContentSettingsDetails content_settings_details(
+        ContentSettingsPattern(),
+        CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
+        "");
+    NotifyContentSettingsChanged(&content_settings_details);
+  } else {
+    OptionsPageBase::Observe(type, source, details);
+  }
+}
+
+void ContentFilterPageGtk::NotifyContentSettingsChanged(
+    const ContentSettingsDetails *details) {
+  if (details->type() == CONTENT_SETTINGS_TYPE_DEFAULT ||
+      details->type() == content_type_) {
+    ignore_toggle_ = true;
+    UpdateButtonsState();
+    ignore_toggle_ = false;
+  }
+}
diff --git a/chrome/browser/ui/gtk/options/content_filter_page_gtk.h b/chrome/browser/ui/gtk/options/content_filter_page_gtk.h
new file mode 100644
index 0000000..39d4179
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_filter_page_gtk.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_FILTER_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_FILTER_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/content_settings_types.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class ContentSettingsDetails;
+
+// A page in the content settings window. Used for everything but the Cookies
+// page (which has a much more complex dialog). A |content_type| is passed into
+// the constructor and the correct strings and settings are used.
+class ContentFilterPageGtk : public OptionsPageBase {
+ public:
+  ContentFilterPageGtk(Profile* profile, ContentSettingsType content_type);
+  virtual ~ContentFilterPageGtk();
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  // This method is called during initialization to set the initial state of the
+  // buttons and called after a default content setting change (either value
+  // change or "is managed" state).
+  virtual void UpdateButtonsState();
+
+  virtual void NotifyContentSettingsChanged(
+      const ContentSettingsDetails* details);
+
+  // Builds the content of the dialog.
+  GtkWidget* InitGroup();
+
+  CHROMEGTK_CALLBACK_0(ContentFilterPageGtk, void, OnAllowToggled);
+  CHROMEGTK_CALLBACK_0(ContentFilterPageGtk, void, OnExceptionsClicked);
+  CHROMEGTK_CALLBACK_0(ContentFilterPageGtk, void, OnPluginsPageLinkClicked);
+
+  ContentSettingsType content_type_;
+
+  GtkWidget* page_;
+
+  // Controls for the content filter tab page.
+  GtkWidget* allow_radio_;
+  GtkWidget* ask_radio_;
+  GtkWidget* block_radio_;
+
+  GtkWidget* exceptions_button_;
+
+  NotificationRegistrar registrar_;
+
+  // If state of the UI is not changed by a user-action we need to ignore
+  // "toggled" events.
+  bool ignore_toggle_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentFilterPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_FILTER_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/content_page_gtk.cc b/chrome/browser/ui/gtk/options/content_page_gtk.cc
new file mode 100644
index 0000000..e90e667
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_page_gtk.cc
@@ -0,0 +1,586 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/content_page_gtk.h"
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/defaults.h"
+#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/sync_ui_util.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/import_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/options/options_layout_gtk.h"
+#include "chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "grit/app_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Background color for the status label when it's showing an error.
+static const GdkColor kSyncLabelErrorBgColor = GDK_COLOR_RGB(0xff, 0x9a, 0x9a);
+
+// Helper for WrapLabelAtAllocationHack.
+void OnLabelAllocate(GtkWidget* label, GtkAllocation* allocation) {
+  gtk_util::SetLabelWidth(label, allocation->width);
+
+  // Disconnect ourselves.  Repeatedly resizing based on allocation causes
+  // the dialog to become unshrinkable.
+  g_signal_handlers_disconnect_by_func(
+      label, reinterpret_cast<gpointer>(OnLabelAllocate), NULL);
+}
+
+// Set the label to use a request size equal to its initial allocation
+// size.  This causes the label to wrap at the width of the container
+// it is in, instead of at the default width.  This is called a hack
+// because GTK doesn't really work when a widget to make its size
+// request depend on its allocation.  It does, however, have the
+// intended effect of wrapping the label at the proper width.
+void WrapLabelAtAllocationHack(GtkWidget* label) {
+  g_signal_connect(label, "size-allocate",
+                   G_CALLBACK(OnLabelAllocate), NULL);
+}
+
+}  // anonymous namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentPageGtk, public:
+
+ContentPageGtk::ContentPageGtk(Profile* profile)
+    : OptionsPageBase(profile),
+      sync_status_label_background_(NULL),
+      sync_status_label_(NULL),
+      sync_action_link_background_(NULL),
+      sync_action_link_(NULL),
+      sync_start_stop_button_(NULL),
+      sync_customize_button_(NULL),
+      privacy_dashboard_link_(NULL),
+      initializing_(true),
+      sync_service_(NULL),
+      managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_CONTENT) {
+  if (profile->GetProfileSyncService()) {
+    sync_service_ = profile->GetProfileSyncService();
+    sync_service_->AddObserver(this);
+  }
+
+  // Prepare the group options layout.
+  scoped_ptr<OptionsLayoutBuilderGtk>
+    options_builder(OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout());
+  options_builder->AddWidget(managed_prefs_banner_.banner_widget(), false);
+  if (sync_service_) {
+    options_builder->AddOptionGroup(
+        l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_GROUP_NAME),
+        InitSyncGroup(), false);
+    UpdateSyncControls();
+  }
+
+  // Add preferences observers.
+  ask_to_save_passwords_.Init(prefs::kPasswordManagerEnabled,
+                              profile->GetPrefs(), this);
+  form_autofill_enabled_.Init(prefs::kAutoFillEnabled,
+                              profile->GetPrefs(), this);
+  if (browser_defaults::kCanToggleSystemTitleBar) {
+    use_custom_chrome_frame_.Init(prefs::kUseCustomChromeFrame,
+                                  profile->GetPrefs(), this);
+  }
+
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_GROUP_NAME),
+      InitPasswordSavingGroup(), false);
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_AUTOFILL_SETTING_WINDOWS_GROUP_NAME),
+      InitFormAutoFillGroup(), false);
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_BROWSING_DATA_GROUP_NAME),
+      InitBrowsingDataGroup(), false);
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_APPEARANCE_GROUP_NAME),
+      InitThemesGroup(), false);
+  page_ = options_builder->get_page_widget();
+
+  // Load initial values.
+  NotifyPrefChanged(NULL);
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  ObserveThemeChanged();
+}
+
+ContentPageGtk::~ContentPageGtk() {
+  if (sync_service_)
+    sync_service_->RemoveObserver(this);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentsPageView, ProfileSyncServiceObserver implementation:
+
+void ContentPageGtk::OnStateChanged() {
+  // If the UI controls are not yet initialized, then don't do anything. This
+  // can happen if the Options dialog is up, but the Content tab is not yet
+  // clicked.
+  if (!initializing_)
+    UpdateSyncControls();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentPageGtk, private:
+
+// If |pref_name| is NULL, set the state of all the widgets. (This is used
+// in ContentPageGtk() above to initialize the dialog.) Otherwise, reset the
+// state of the widget for the given preference name, as it has changed.
+void ContentPageGtk::NotifyPrefChanged(const std::string* pref_name) {
+  initializing_ = true;
+  if (!pref_name || *pref_name == prefs::kPasswordManagerEnabled) {
+    if (ask_to_save_passwords_.GetValue()) {
+      gtk_toggle_button_set_active(
+          GTK_TOGGLE_BUTTON(passwords_asktosave_radio_), TRUE);
+    } else {
+      gtk_toggle_button_set_active(
+          GTK_TOGGLE_BUTTON(passwords_neversave_radio_), TRUE);
+    }
+    bool isPasswordManagerEnabled = !ask_to_save_passwords_.IsManaged();
+    gtk_widget_set_sensitive(passwords_asktosave_radio_,
+                             isPasswordManagerEnabled);
+    gtk_widget_set_sensitive(passwords_neversave_radio_,
+                             isPasswordManagerEnabled);
+    gtk_widget_set_sensitive(show_passwords_button_,
+                             isPasswordManagerEnabled ||
+                             ask_to_save_passwords_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kAutoFillEnabled) {
+    bool disabled_by_policy = form_autofill_enabled_.IsManaged() &&
+        !form_autofill_enabled_.GetValue();
+    gtk_widget_set_sensitive(autofill_button_, !disabled_by_policy);
+  }
+  if (browser_defaults::kCanToggleSystemTitleBar &&
+      (!pref_name || *pref_name == prefs::kUseCustomChromeFrame)) {
+    if (use_custom_chrome_frame_.GetValue()) {
+      gtk_toggle_button_set_active(
+          GTK_TOGGLE_BUTTON(system_title_bar_hide_radio_), TRUE);
+    } else {
+      gtk_toggle_button_set_active(
+          GTK_TOGGLE_BUTTON(system_title_bar_show_radio_), TRUE);
+    }
+  }
+  initializing_ = false;
+}
+
+void ContentPageGtk::Observe(NotificationType type,
+                             const NotificationSource& source,
+                             const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED)
+    ObserveThemeChanged();
+  else
+    OptionsPageBase::Observe(type, source, details);
+}
+
+void ContentPageGtk::ObserveThemeChanged() {
+#if defined(TOOLKIT_GTK)
+  GtkThemeProvider* provider = GtkThemeProvider::GetFrom(profile());
+  bool is_gtk_theme = provider->UseGtkTheme();
+  gtk_widget_set_sensitive(gtk_theme_button_, !is_gtk_theme);
+#else
+  BrowserThemeProvider* provider =
+      reinterpret_cast<BrowserThemeProvider*>(profile()->GetThemeProvider());
+  bool is_gtk_theme = false;
+#endif
+
+  bool is_classic_theme = !is_gtk_theme && provider->GetThemeID().empty();
+  gtk_widget_set_sensitive(themes_reset_button_, !is_classic_theme);
+}
+
+GtkWidget* ContentPageGtk::InitPasswordSavingGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  // Ask to save radio button.
+  passwords_asktosave_radio_ = gtk_radio_button_new_with_label(NULL,
+      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_ASKTOSAVE).c_str());
+  g_signal_connect(passwords_asktosave_radio_, "toggled",
+                   G_CALLBACK(OnPasswordRadioToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), passwords_asktosave_radio_, FALSE,
+                     FALSE, 0);
+
+  // Never save radio button.
+  passwords_neversave_radio_ = gtk_radio_button_new_with_label_from_widget(
+      GTK_RADIO_BUTTON(passwords_asktosave_radio_),
+      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_NEVERSAVE).c_str());
+  g_signal_connect(passwords_neversave_radio_, "toggled",
+                   G_CALLBACK(OnPasswordRadioToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), passwords_neversave_radio_, FALSE,
+                     FALSE, 0);
+
+  // Add the show passwords button into its own horizontal box so it does not
+  // depend on the spacing above.
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  gtk_container_add(GTK_CONTAINER(vbox), button_hbox);
+  show_passwords_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_PASSWORDS_SHOWPASSWORDS).c_str());
+  g_signal_connect(show_passwords_button_, "clicked",
+                   G_CALLBACK(OnShowPasswordsButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_hbox), show_passwords_button_, FALSE,
+                     FALSE, 0);
+
+  return vbox;
+}
+
+GtkWidget* ContentPageGtk::InitFormAutoFillGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(vbox), button_hbox);
+
+  // AutoFill button.
+  autofill_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_AUTOFILL_OPTIONS).c_str());
+
+  g_signal_connect(G_OBJECT(autofill_button_), "clicked",
+                   G_CALLBACK(OnAutoFillButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_hbox), autofill_button_, FALSE, FALSE, 0);
+
+  return vbox;
+}
+
+GtkWidget* ContentPageGtk::InitBrowsingDataGroup() {
+  GtkWidget* button_box = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+
+  // Import button.
+  GtkWidget* import_button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_IMPORT_DATA_BUTTON).c_str());
+  g_signal_connect(import_button, "clicked",
+                   G_CALLBACK(OnImportButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_box), import_button, FALSE, FALSE, 0);
+
+  return button_box;
+}
+
+GtkWidget* ContentPageGtk::InitThemesGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+
+#if defined(TOOLKIT_GTK)
+  // GTK theme button.
+  gtk_theme_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_THEMES_GTK_BUTTON).c_str());
+  g_signal_connect(gtk_theme_button_, "clicked",
+                   G_CALLBACK(OnGtkThemeButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), gtk_theme_button_, FALSE, FALSE, 0);
+#endif
+
+  // Reset theme button.
+  themes_reset_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_THEMES_SET_CLASSIC).c_str());
+  g_signal_connect(themes_reset_button_, "clicked",
+                   G_CALLBACK(OnResetDefaultThemeButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), themes_reset_button_, FALSE, FALSE, 0);
+
+  // Get themes button.
+  GtkWidget* themes_gallery_button = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_BUTTON).c_str());
+  g_signal_connect(themes_gallery_button, "clicked",
+                   G_CALLBACK(OnGetThemesButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), themes_gallery_button, FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+  // "Use system title bar and borders" radio buttons.
+  if (browser_defaults::kCanToggleSystemTitleBar) {
+    // Use system title bar and borders
+    system_title_bar_show_radio_ = gtk_radio_button_new_with_label(NULL,
+        l10n_util::GetStringUTF8(IDS_SHOW_WINDOW_DECORATIONS_RADIO).c_str());
+    g_signal_connect(system_title_bar_show_radio_, "toggled",
+                     G_CALLBACK(OnSystemTitleBarRadioToggledThunk), this);
+    gtk_box_pack_start(GTK_BOX(vbox), system_title_bar_show_radio_, FALSE,
+                       FALSE, 0);
+
+    // Hide system title bar and use custom borders
+    system_title_bar_hide_radio_ = gtk_radio_button_new_with_label_from_widget(
+        GTK_RADIO_BUTTON(system_title_bar_show_radio_),
+        l10n_util::GetStringUTF8(IDS_HIDE_WINDOW_DECORATIONS_RADIO).c_str());
+    g_signal_connect(system_title_bar_hide_radio_, "toggled",
+                     G_CALLBACK(OnSystemTitleBarRadioToggledThunk), this);
+    gtk_box_pack_start(GTK_BOX(vbox), system_title_bar_hide_radio_, FALSE,
+                       FALSE, 0);
+  }
+
+  return vbox;
+}
+
+GtkWidget* ContentPageGtk::InitSyncGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  // Sync label.
+  sync_status_label_background_ = gtk_event_box_new();
+  sync_status_label_ = gtk_label_new("");
+  WrapLabelAtAllocationHack(sync_status_label_);
+
+  gtk_misc_set_alignment(GTK_MISC(sync_status_label_), 0, 0.5);
+  gtk_box_pack_start(GTK_BOX(vbox), sync_status_label_background_, FALSE,
+                     FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(sync_status_label_background_),
+                    sync_status_label_);
+
+  // Sync action link.
+  GtkWidget* link_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  sync_action_link_background_ = gtk_event_box_new();
+  sync_action_link_ = gtk_chrome_link_button_new("");
+  g_signal_connect(sync_action_link_, "clicked",
+                   G_CALLBACK(OnSyncActionLinkClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), link_hbox, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(link_hbox), sync_action_link_background_, FALSE,
+                     FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(sync_action_link_background_),
+                    sync_action_link_);
+  gtk_widget_hide(sync_action_link_background_);
+
+  // Add the sync button into its own horizontal box so it does not
+  // depend on the spacing above.
+  GtkWidget* button_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  gtk_container_add(GTK_CONTAINER(vbox), button_hbox);
+  sync_start_stop_button_ = gtk_button_new_with_label("");
+  g_signal_connect(sync_start_stop_button_, "clicked",
+                   G_CALLBACK(OnSyncStartStopButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_hbox), sync_start_stop_button_, FALSE,
+                     FALSE, 0);
+  sync_customize_button_ = gtk_button_new_with_label("");
+  g_signal_connect(sync_customize_button_, "clicked",
+                   G_CALLBACK(OnSyncCustomizeButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_hbox), sync_customize_button_, FALSE,
+                     FALSE, 0);
+
+  // Add the privacy dashboard link.
+  GtkWidget* dashboard_link_hbox =
+      gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  GtkWidget* dashboard_link_background = gtk_event_box_new();
+  std::string dashboard_link_label =
+      l10n_util::GetStringUTF8(IDS_SYNC_PRIVACY_DASHBOARD_LINK_LABEL);
+  privacy_dashboard_link_ =
+      gtk_chrome_link_button_new(dashboard_link_label.c_str());
+  g_signal_connect(privacy_dashboard_link_, "clicked",
+                   G_CALLBACK(OnPrivacyDashboardLinkClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), dashboard_link_hbox, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(dashboard_link_hbox),
+                     dashboard_link_background, FALSE, FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(dashboard_link_background),
+                    privacy_dashboard_link_);
+
+
+  return vbox;
+}
+
+void ContentPageGtk::UpdateSyncControls() {
+  DCHECK(sync_service_);
+  string16 status_label;
+  string16 link_label;
+  std::string customize_button_label;
+  bool managed = sync_service_->IsManaged();
+  bool sync_setup_completed = sync_service_->HasSyncSetupCompleted();
+  bool status_has_error = sync_ui_util::GetStatusLabels(sync_service_,
+      &status_label, &link_label) == sync_ui_util::SYNC_ERROR;
+  customize_button_label =
+    l10n_util::GetStringUTF8(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL);
+
+  std::string start_stop_button_label;
+  bool is_start_stop_button_sensitive = false;
+  if (sync_setup_completed) {
+    start_stop_button_label =
+        l10n_util::GetStringUTF8(IDS_SYNC_STOP_SYNCING_BUTTON_LABEL);
+    is_start_stop_button_sensitive = !managed;
+  } else if (sync_service_->SetupInProgress()) {
+    start_stop_button_label =
+        l10n_util::GetStringUTF8(IDS_SYNC_NTP_SETUP_IN_PROGRESS);
+    is_start_stop_button_sensitive = false;
+  } else {
+    start_stop_button_label =
+        l10n_util::GetStringUTF8(IDS_SYNC_START_SYNC_BUTTON_LABEL);
+    is_start_stop_button_sensitive = !managed;
+  }
+  gtk_widget_set_no_show_all(sync_start_stop_button_, FALSE);
+  gtk_widget_show(sync_start_stop_button_);
+  gtk_widget_set_sensitive(sync_start_stop_button_,
+                           is_start_stop_button_sensitive);
+  gtk_button_set_label(GTK_BUTTON(sync_start_stop_button_),
+                       start_stop_button_label.c_str());
+
+  gtk_label_set_label(GTK_LABEL(sync_status_label_),
+                      UTF16ToUTF8(status_label).c_str());
+
+  gtk_widget_set_child_visible(sync_customize_button_,
+      sync_setup_completed && !status_has_error);
+  gtk_button_set_label(GTK_BUTTON(sync_customize_button_),
+                       customize_button_label.c_str());
+  gtk_widget_set_sensitive(sync_customize_button_, !managed);
+  gtk_chrome_link_button_set_label(GTK_CHROME_LINK_BUTTON(sync_action_link_),
+                                   UTF16ToUTF8(link_label).c_str());
+  if (link_label.empty()) {
+    gtk_widget_set_no_show_all(sync_action_link_background_, TRUE);
+    gtk_widget_hide(sync_action_link_background_);
+  } else {
+    gtk_widget_set_no_show_all(sync_action_link_background_, FALSE);
+    gtk_widget_show(sync_action_link_background_);
+  }
+  gtk_widget_set_sensitive(sync_action_link_, !managed);
+  if (status_has_error) {
+    gtk_widget_modify_bg(sync_status_label_background_, GTK_STATE_NORMAL,
+                         &kSyncLabelErrorBgColor);
+    gtk_widget_modify_bg(sync_action_link_background_, GTK_STATE_NORMAL,
+                         &kSyncLabelErrorBgColor);
+  } else {
+    gtk_widget_modify_bg(sync_status_label_background_, GTK_STATE_NORMAL, NULL);
+    gtk_widget_modify_bg(sync_action_link_background_, GTK_STATE_NORMAL, NULL);
+  }
+}
+
+void ContentPageGtk::OnAutoFillButtonClicked(GtkWidget* widget) {
+  ShowAutoFillDialog(NULL, profile()->GetPersonalDataManager(), profile());
+}
+
+void ContentPageGtk::OnImportButtonClicked(GtkWidget* widget) {
+  ImportDialogGtk::Show(
+      GTK_WINDOW(gtk_widget_get_toplevel(widget)),
+      profile(), importer::ALL);
+}
+
+void ContentPageGtk::OnGtkThemeButtonClicked(GtkWidget* widget) {
+  UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet"),
+                          profile()->GetPrefs());
+  profile()->SetNativeTheme();
+}
+
+void ContentPageGtk::OnResetDefaultThemeButtonClicked(GtkWidget* widget) {
+  UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset"),
+                          profile()->GetPrefs());
+  profile()->ClearTheme();
+}
+
+void ContentPageGtk::OnGetThemesButtonClicked(GtkWidget* widget) {
+  UserMetricsRecordAction(UserMetricsAction("Options_ThemesGallery"),
+                          profile()->GetPrefs());
+  BrowserList::GetLastActive()->OpenThemeGalleryTabAndActivate();
+}
+
+void ContentPageGtk::OnSystemTitleBarRadioToggled(GtkWidget* widget) {
+  DCHECK(browser_defaults::kCanToggleSystemTitleBar);
+  if (initializing_)
+    return;
+
+  // We get two signals when selecting a radio button, one for the old radio
+  // being toggled off and one for the new one being toggled on. Ignore the
+  // signal for the toggling off the old button.
+  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+    return;
+
+  bool use_custom = gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(system_title_bar_hide_radio_));
+  if (use_custom) {
+    UserMetricsRecordAction(UserMetricsAction("Options_CustomFrame_Enable"),
+                            profile()->GetPrefs());
+  } else {
+    UserMetricsRecordAction(UserMetricsAction("Options_CustomFrame_Disable"),
+                            profile()->GetPrefs());
+  }
+
+  use_custom_chrome_frame_.SetValue(use_custom);
+}
+
+void ContentPageGtk::OnShowPasswordsButtonClicked(GtkWidget* widget) {
+  ShowPasswordsExceptionsWindow(profile());
+}
+
+void ContentPageGtk::OnPasswordRadioToggled(GtkWidget* widget) {
+  if (initializing_)
+    return;
+
+  // We get two signals when selecting a radio button, one for the old radio
+  // being toggled off and one for the new one being toggled on. Ignore the
+  // signal for the toggling off the old button.
+  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+    return;
+
+  bool enabled = gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(passwords_asktosave_radio_));
+  if (enabled) {
+    UserMetricsRecordAction(UserMetricsAction("Options_PasswordManager_Enable"),
+                            profile()->GetPrefs());
+  } else {
+    UserMetricsRecordAction(
+        UserMetricsAction("Options_PasswordManager_Disable"),
+        profile()->GetPrefs());
+  }
+  ask_to_save_passwords_.SetValue(enabled);
+}
+
+void ContentPageGtk::OnSyncStartStopButtonClicked(GtkWidget* widget) {
+  DCHECK(sync_service_ && !sync_service_->IsManaged());
+
+  if (sync_service_->HasSyncSetupCompleted()) {
+    GtkWidget* dialog = gtk_message_dialog_new(
+        GTK_WINDOW(gtk_widget_get_toplevel(widget)),
+        static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL),
+        GTK_MESSAGE_WARNING,
+        GTK_BUTTONS_NONE,
+        "%s",
+        l10n_util::GetStringUTF8(
+            IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL).c_str());
+    gtk_util::ApplyMessageDialogQuirks(dialog);
+    gtk_window_set_title(GTK_WINDOW(dialog),
+                         l10n_util::GetStringUTF8(
+                             IDS_SYNC_STOP_SYNCING_DIALOG_TITLE).c_str());
+    gtk_dialog_add_buttons(
+        GTK_DIALOG(dialog),
+        l10n_util::GetStringUTF8(IDS_CANCEL).c_str(),
+        GTK_RESPONSE_REJECT,
+        l10n_util::GetStringUTF8(
+            IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL).c_str(),
+        GTK_RESPONSE_ACCEPT,
+        NULL);
+
+    g_signal_connect(dialog, "response",
+                     G_CALLBACK(OnStopSyncDialogResponseThunk), this);
+
+    gtk_util::ShowDialog(dialog);
+    return;
+  } else {
+    sync_service_->ShowLoginDialog(NULL);
+    ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
+  }
+}
+
+void ContentPageGtk::OnSyncCustomizeButtonClicked(GtkWidget* widget) {
+  // sync_customize_button_ should be invisible if sync is not yet set up.
+  DCHECK(sync_service_ && !sync_service_->IsManaged() &&
+         sync_service_->HasSyncSetupCompleted());
+  sync_service_->ShowConfigure(NULL);
+}
+
+void ContentPageGtk::OnSyncActionLinkClicked(GtkWidget* widget) {
+  DCHECK(sync_service_ && !sync_service_->IsManaged());
+  sync_service_->ShowErrorUI(NULL);
+}
+
+void ContentPageGtk::OnStopSyncDialogResponse(GtkWidget* widget, int response) {
+  if (response == GTK_RESPONSE_ACCEPT) {
+    sync_service_->DisableForUser();
+    ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
+  }
+  gtk_widget_destroy(widget);
+}
+
+void ContentPageGtk::OnPrivacyDashboardLinkClicked(GtkWidget* widget) {
+  BrowserList::GetLastActive()->OpenPrivacyDashboardTabAndActivate();
+}
diff --git a/chrome/browser/ui/gtk/options/content_page_gtk.h b/chrome/browser/ui/gtk/options/content_page_gtk.h
new file mode 100644
index 0000000..313e402
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_page_gtk.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Profile;
+
+class ContentPageGtk : public OptionsPageBase,
+                       public ProfileSyncServiceObserver {
+ public:
+  explicit ContentPageGtk(Profile* profile);
+  ~ContentPageGtk();
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+  // ProfileSyncServiceObserver method.
+  virtual void OnStateChanged();
+
+ private:
+  // Updates various sync controls based on the current sync state.
+  void UpdateSyncControls();
+
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  // Overridden from OptionsPageBase.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Update content area after a theme changed.
+  void ObserveThemeChanged();
+
+  // Initialize the option group widgets, return their container.
+  GtkWidget* InitPasswordSavingGroup();
+  GtkWidget* InitFormAutoFillGroup();
+  GtkWidget* InitBrowsingDataGroup();
+  GtkWidget* InitThemesGroup();
+  GtkWidget* InitSyncGroup();
+
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnImportButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnGtkThemeButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnResetDefaultThemeButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnGetThemesButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSystemTitleBarRadioToggled);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnShowPasswordsButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnPasswordRadioToggled);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnAutoFillButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSyncStartStopButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSyncCustomizeButtonClicked);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnSyncActionLinkClicked);
+  CHROMEGTK_CALLBACK_1(ContentPageGtk, void, OnStopSyncDialogResponse, int);
+  CHROMEGTK_CALLBACK_0(ContentPageGtk, void, OnPrivacyDashboardLinkClicked);
+
+  // Widgets for the Password saving group.
+  GtkWidget* passwords_asktosave_radio_;
+  GtkWidget* passwords_neversave_radio_;
+  GtkWidget* show_passwords_button_;
+
+  // Widgets for the AutoFill group.
+  GtkWidget* autofill_button_;
+
+  // Widgets for the Appearance group.
+  GtkWidget* system_title_bar_show_radio_;
+  GtkWidget* system_title_bar_hide_radio_;
+  GtkWidget* themes_reset_button_;
+#if defined(TOOLKIT_GTK)
+  GtkWidget* gtk_theme_button_;
+#endif
+
+  // Widgets for the Sync group.
+  GtkWidget* sync_status_label_background_;
+  GtkWidget* sync_status_label_;
+  GtkWidget* sync_action_link_background_;
+  GtkWidget* sync_action_link_;
+  GtkWidget* sync_start_stop_button_;
+  GtkWidget* sync_customize_button_;
+  GtkWidget* privacy_dashboard_link_;
+
+  // The parent GtkTable widget
+  GtkWidget* page_;
+
+  // Pref members.
+  BooleanPrefMember ask_to_save_passwords_;
+  BooleanPrefMember form_autofill_enabled_;
+  BooleanPrefMember use_custom_chrome_frame_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool initializing_;
+
+  NotificationRegistrar registrar_;
+
+  // Cached pointer to ProfileSyncService, if it exists. Kept up to date
+  // and NULL-ed out on destruction.
+  ProfileSyncService* sync_service_;
+
+  // Tracks managed preference warning banner state.
+  ManagedPrefsBannerGtk managed_prefs_banner_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/content_settings_window_gtk.cc b/chrome/browser/ui/gtk/options/content_settings_window_gtk.cc
new file mode 100644
index 0000000..527419a
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_settings_window_gtk.cc
@@ -0,0 +1,239 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/content_settings_window_gtk.h"
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/content_settings_types.h"
+#include "chrome/common/pref_names.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// The singleton options window object.
+ContentSettingsWindowGtk* settings_window = NULL;
+
+}  // namespace
+
+// static
+void ContentSettingsWindowGtk::Show(GtkWindow* parent,
+                                    ContentSettingsType page,
+                                    Profile* profile) {
+  DCHECK(profile);
+
+  if (!settings_window) {
+    // Creating and initializing a bunch of controls generates a bunch of
+    // spurious events as control values change. Temporarily suppress
+    // accessibility events until the window is created.
+    profile->PauseAccessibilityEvents();
+
+    // Create the options window.
+    settings_window = new ContentSettingsWindowGtk(parent, profile);
+
+    // Resume accessibility events.
+    profile->ResumeAccessibilityEvents();
+  }
+  settings_window->ShowContentSettingsTab(page);
+}
+
+ContentSettingsWindowGtk::ContentSettingsWindowGtk(GtkWindow* parent,
+                                                   Profile* profile)
+    : profile_(profile),
+      cookie_page_(profile),
+      image_page_(profile, CONTENT_SETTINGS_TYPE_IMAGES),
+      javascript_page_(profile, CONTENT_SETTINGS_TYPE_JAVASCRIPT),
+      plugin_page_(profile, CONTENT_SETTINGS_TYPE_PLUGINS),
+      popup_page_(profile, CONTENT_SETTINGS_TYPE_POPUPS),
+      geolocation_page_(profile, CONTENT_SETTINGS_TYPE_GEOLOCATION),
+      notifications_page_(profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+  const struct {
+    int message_id;
+    GtkWidget* widget;
+  } kNotebookPages[] = {
+    { IDS_COOKIES_TAB_LABEL, cookie_page_.get_page_widget() },
+    { IDS_IMAGES_TAB_LABEL, image_page_.get_page_widget() },
+    { IDS_JAVASCRIPT_TAB_LABEL, javascript_page_.get_page_widget() },
+    { IDS_PLUGIN_TAB_LABEL, plugin_page_.get_page_widget() },
+    { IDS_POPUP_TAB_LABEL, popup_page_.get_page_widget() },
+    { IDS_GEOLOCATION_TAB_LABEL, geolocation_page_.get_page_widget() },
+    { IDS_NOTIFICATIONS_TAB_LABEL, notifications_page_.get_page_widget() },
+  };
+
+  // We don't need to observe changes in this value.
+  last_selected_page_.Init(prefs::kContentSettingsWindowLastTabIndex,
+                           profile->GetPrefs(), NULL);
+
+  std::string dialog_name = l10n_util::GetStringUTF8(
+      IDS_CONTENT_SETTINGS_TITLE);
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+  gtk_window_set_policy(GTK_WINDOW(dialog_), FALSE, FALSE, TRUE);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile_));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
+  // Allow browser windows to go in front of the options dialog in metacity.
+  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+  gtk_util::SetWindowIcon(GTK_WINDOW(dialog_));
+
+  // Create hbox with list view and notebook.
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);
+
+  list_ = gtk_tree_view_new();
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list_), FALSE);
+
+  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
+      "List Item", renderer, "text", 0, NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(list_), column);
+
+  const int kColumnCount = 1;
+  GtkListStore* store = gtk_list_store_new(kColumnCount, G_TYPE_STRING);
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNotebookPages); ++i) {
+    GtkTreeIter iter;
+    gtk_list_store_append(store, &iter);
+    std::string label = l10n_util::GetStringUTF8(kNotebookPages[i].message_id);
+    gtk_list_store_set(store, &iter, 0, label.c_str(), -1);
+  }
+  gtk_tree_view_set_model(GTK_TREE_VIEW(list_), GTK_TREE_MODEL(store));
+  g_object_unref(store);
+
+  // Needs to happen after the model is all set up.
+  GtkTreeSelection* selection = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(list_));
+  gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
+
+  // Wrap the list widget in a scrolled window in order to have a frame.
+  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+                                 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+  gtk_container_add(GTK_CONTAINER(scrolled), list_);
+  gtk_box_pack_start(GTK_BOX(hbox), scrolled, FALSE, FALSE, 0);
+
+  notebook_ = gtk_notebook_new();
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNotebookPages); ++i) {
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook_),
+                             kNotebookPages[i].widget,
+                             NULL);
+  }
+  gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook_), FALSE);
+  gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook_), FALSE);
+  gtk_box_pack_start(GTK_BOX(hbox), notebook_, FALSE, FALSE, 0);
+  DCHECK_EQ(gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)),
+            CONTENT_SETTINGS_NUM_TYPES);
+
+  // Create vbox with "Features:" text and hbox below.
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_CONTENT_SETTINGS_FEATURES_LABEL).c_str());
+  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), vbox);
+
+  // Need to show the notebook before connecting switch-page signal, otherwise
+  // we'll immediately get a signal switching to page 0 and overwrite our
+  // last_selected_page_ value.
+  gtk_util::ShowDialogWithLocalizedSize(dialog_, -1, -1, true);
+
+  g_signal_connect(notebook_, "switch-page",
+                   G_CALLBACK(OnSwitchPageThunk), this);
+  g_signal_connect(selection, "changed",
+                   G_CALLBACK(OnListSelectionChangedThunk), this);
+
+  // We only have one button and don't do any special handling, so just hook it
+  // directly to gtk_widget_destroy.
+  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+ContentSettingsWindowGtk::~ContentSettingsWindowGtk() {
+}
+
+void ContentSettingsWindowGtk::ShowContentSettingsTab(
+    ContentSettingsType page) {
+  // Bring options window to front if it already existed and isn't already
+  // in front
+  gtk_util::PresentWindow(dialog_,  gtk_get_current_event_time());
+
+  if (page == CONTENT_SETTINGS_TYPE_DEFAULT) {
+    // Remember the last visited page from local state.
+    page = static_cast<ContentSettingsType>(last_selected_page_.GetValue());
+    if (page == CONTENT_SETTINGS_TYPE_DEFAULT)
+      page = CONTENT_SETTINGS_TYPE_COOKIES;
+  }
+  // If the page number is out of bounds, reset to the first tab.
+  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
+    page = CONTENT_SETTINGS_TYPE_COOKIES;
+
+  gtk_tree::SelectAndFocusRowNum(page, GTK_TREE_VIEW(list_));
+}
+
+void ContentSettingsWindowGtk::OnSwitchPage(
+    GtkWidget* notebook,
+    GtkNotebookPage* page,
+    guint page_num) {
+  int index = page_num;
+  DCHECK(index > CONTENT_SETTINGS_TYPE_DEFAULT &&
+         index < CONTENT_SETTINGS_NUM_TYPES);
+
+  // Keep list in sync.
+  GtkTreeModel* model;
+  GtkTreeIter iter;
+  if (gtk_tree_selection_get_selected(
+      gtk_tree_view_get_selection(GTK_TREE_VIEW(list_)), &model, &iter)) {
+    gint row_index = gtk_tree::GetRowNumForIter(model, &iter);
+    if (row_index == index)
+      return;
+  }
+  gtk_tree::SelectAndFocusRowNum(index, GTK_TREE_VIEW(list_));
+}
+
+void ContentSettingsWindowGtk::OnWindowDestroy(GtkWidget* widget) {
+  settings_window = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void ContentSettingsWindowGtk::OnListSelectionChanged(
+    GtkTreeSelection* selection) {
+  GtkTreeModel* model;
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
+    NOTREACHED();
+    return;
+  }
+  gint row_index = gtk_tree::GetRowNumForIter(model, &iter);
+  DCHECK(row_index > CONTENT_SETTINGS_TYPE_DEFAULT &&
+         row_index < CONTENT_SETTINGS_NUM_TYPES);
+
+  last_selected_page_.SetValue(row_index);
+
+  if (row_index != gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_)))
+    gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), row_index);
+}
diff --git a/chrome/browser/ui/gtk/options/content_settings_window_gtk.h b/chrome/browser/ui/gtk/options/content_settings_window_gtk.h
new file mode 100644
index 0000000..7a5b248
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/content_settings_window_gtk.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_SETTINGS_WINDOW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_SETTINGS_WINDOW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/gtk/options/content_filter_page_gtk.h"
+#include "chrome/browser/ui/gtk/options/cookie_filter_page_gtk.h"
+#include "chrome/common/content_settings_types.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class AccessibleWidgetHelper;
+
+// A window that presents options to the user for blocking various kinds of
+// content in webpages (cookies, javascript, images, popups).
+class ContentSettingsWindowGtk {
+ public:
+  // Shows the current content settings page, opening a new one if it doesn't
+  // exist.
+  static void Show(GtkWindow* parent, ContentSettingsType page,
+                   Profile* profile);
+  static void RegisterUserPrefs(PrefService* prefs);
+
+  explicit ContentSettingsWindowGtk(GtkWindow* parent, Profile* profile);
+  virtual ~ContentSettingsWindowGtk();
+
+ private:
+  // Shows the Tab corresponding to the specified Content Settings page.
+  void ShowContentSettingsTab(ContentSettingsType page);
+
+  CHROMEGTK_CALLBACK_2(ContentSettingsWindowGtk, void, OnSwitchPage,
+                       GtkNotebookPage*, guint);
+  CHROMEGTK_CALLBACK_0(ContentSettingsWindowGtk, void, OnWindowDestroy);
+  CHROMEG_CALLBACK_0(ContentSettingsWindowGtk, void, OnListSelectionChanged,
+                     GtkTreeSelection*);
+
+  // The options dialog.
+  GtkWidget* dialog_;
+
+  // The container of the option pages.
+  GtkWidget* notebook_;
+  GtkWidget* list_;
+
+  // The Profile associated with these options.
+  Profile* profile_;
+
+  // The last page the user was on when they opened the ContentSettings window.
+  IntegerPrefMember last_selected_page_;
+
+  // The individual page implementations. Note that we have a specialized one
+  // for cookies (which have more complex rules) and use the same basic page
+  // layout for each other type.
+  CookieFilterPageGtk cookie_page_;
+  ContentFilterPageGtk image_page_;
+  ContentFilterPageGtk javascript_page_;
+  ContentFilterPageGtk plugin_page_;
+  ContentFilterPageGtk popup_page_;
+  ContentFilterPageGtk geolocation_page_;
+  ContentFilterPageGtk notifications_page_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentSettingsWindowGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_CONTENT_SETTINGS_WINDOW_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/cookie_filter_page_gtk.cc b/chrome/browser/ui/gtk/options/cookie_filter_page_gtk.cc
new file mode 100644
index 0000000..39c0605
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/cookie_filter_page_gtk.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/cookie_filter_page_gtk.h"
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/content_exceptions_window_gtk.h"
+#include "chrome/browser/ui/gtk/options/cookies_view.h"
+#include "chrome/browser/ui/options/show_options_url.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Stick small widgets in an hbox so it doesn't expand to the whole width.
+GtkWidget* WrapInHBox(GtkWidget* widget) {
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
+  return hbox;
+}
+
+}  // namespace
+
+CookieFilterPageGtk::CookieFilterPageGtk(Profile* profile)
+    : OptionsPageBase(profile),
+      ignore_toggle_(false) {
+  // The pref members must be initialized first since the pref values are read
+  // afterwards when we initialize the cookie storing group.
+  clear_site_data_on_exit_.Init(prefs::kClearSiteDataOnExit,
+                                profile->GetPrefs(), this);
+
+  block_third_party_cookies_.Init(prefs::kBlockThirdPartyCookies,
+                                  profile->GetPrefs(), this);
+
+  managed_default_cookies_setting_.Init(prefs::kManagedDefaultCookiesSetting,
+                                        profile->GetPrefs(), this);
+
+  GtkWidget* title_label = gtk_util::CreateBoldLabel(
+      l10n_util::GetStringUTF8(IDS_MODIFY_COOKIE_STORING_LABEL));
+  page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(page_), title_label, FALSE, FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(page_), InitCookieStoringGroup());
+}
+
+CookieFilterPageGtk::~CookieFilterPageGtk() {
+}
+
+void CookieFilterPageGtk::NotifyPrefChanged(const std::string* pref_name) {
+  AutoReset<bool> toggle_guard(&ignore_toggle_, true);
+
+  if (!pref_name || *pref_name == prefs::kClearSiteDataOnExit) {
+    UpdateUiState();
+  }
+  if (!pref_name || *pref_name == prefs::kManagedDefaultCookiesSetting) {
+    UpdateUiState();
+  }
+  if (!pref_name || *pref_name == prefs::kBlockThirdPartyCookies) {
+    UpdateUiState();
+  }
+}
+
+void CookieFilterPageGtk::HighlightGroup(OptionsGroup highlight_group) {
+  // TODO(erg): implement group highlighting
+}
+
+GtkWidget* CookieFilterPageGtk::InitCookieStoringGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  allow_radio_ = gtk_radio_button_new_with_label(NULL,
+      l10n_util::GetStringUTF8(IDS_COOKIES_ALLOW_RADIO).c_str());
+  g_signal_connect(G_OBJECT(allow_radio_), "toggled",
+                   G_CALLBACK(OnCookiesAllowToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), allow_radio_, FALSE, FALSE, 0);
+
+  block_radio_ = gtk_radio_button_new_with_label_from_widget(
+      GTK_RADIO_BUTTON(allow_radio_),
+      l10n_util::GetStringUTF8(IDS_COOKIES_BLOCK_RADIO).c_str());
+  g_signal_connect(G_OBJECT(block_radio_), "toggled",
+                   G_CALLBACK(OnCookiesAllowToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), block_radio_, FALSE, FALSE, 0);
+
+  exceptions_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str());
+  g_signal_connect(G_OBJECT(exceptions_button_), "clicked",
+                   G_CALLBACK(OnExceptionsClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(exceptions_button_),
+                     FALSE, FALSE, 0);
+
+  block_3rdparty_check_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX).c_str());
+  g_signal_connect(G_OBJECT(block_3rdparty_check_), "toggled",
+                   G_CALLBACK(OnBlockThirdPartyToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), block_3rdparty_check_, FALSE, FALSE, 0);
+
+  clear_on_close_check_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX).c_str());
+  g_signal_connect(G_OBJECT(clear_on_close_check_), "toggled",
+                   G_CALLBACK(OnClearOnCloseToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), clear_on_close_check_, FALSE, FALSE, 0);
+
+  show_cookies_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_COOKIES_SHOW_COOKIES_BUTTON).c_str());
+  g_signal_connect(G_OBJECT(show_cookies_button_), "clicked",
+                   G_CALLBACK(OnShowCookiesClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(show_cookies_button_),
+                     FALSE, FALSE, 0);
+
+  GtkWidget* flash_settings_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_SETTINGS).c_str());
+  g_signal_connect(G_OBJECT(flash_settings_link), "clicked",
+                   G_CALLBACK(OnFlashLinkClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(flash_settings_link),
+                     FALSE, FALSE, 0);
+
+  ignore_toggle_ = true;
+  UpdateUiState();
+  ignore_toggle_ = false;
+
+  return vbox;
+};
+
+void CookieFilterPageGtk::UpdateUiState() {
+  // Get default_setting.
+  ContentSetting default_setting;
+  default_setting = profile()->GetHostContentSettingsMap()->
+      GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
+
+  // Set UI state.
+  if (default_setting == CONTENT_SETTING_ALLOW) {
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE);
+  } else {
+    DCHECK(default_setting == CONTENT_SETTING_BLOCK);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE);
+  }
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(clear_on_close_check_),
+                               clear_site_data_on_exit_.GetValue());
+  gtk_toggle_button_set_active(
+      GTK_TOGGLE_BUTTON(block_3rdparty_check_),
+      block_third_party_cookies_.GetValue());
+
+  // Disable the UI if the default content setting is managed.
+  gtk_widget_set_sensitive(block_3rdparty_check_,
+                           !block_third_party_cookies_.IsManaged());
+  bool sensitive = true;
+  if (profile()->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
+      CONTENT_SETTINGS_TYPE_COOKIES)) {
+    sensitive = false;
+  }
+  gtk_widget_set_sensitive(allow_radio_, sensitive);
+  gtk_widget_set_sensitive(block_radio_, sensitive);
+  gtk_widget_set_sensitive(exceptions_button_, sensitive);
+}
+
+void CookieFilterPageGtk::OnCookiesAllowToggled(GtkWidget* toggle_button) {
+  if (ignore_toggle_)
+    return;
+
+  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
+    // When selecting a radio button, we get two signals (one for the old radio
+    // being toggled off, one for the new one being toggled on.)  Ignore the
+    // signal for toggling off the old button.
+    return;
+  }
+
+  ContentSetting setting = CONTENT_SETTING_ALLOW;
+  if (toggle_button == allow_radio_)
+    setting = CONTENT_SETTING_ALLOW;
+  else if (toggle_button == block_radio_)
+    setting = CONTENT_SETTING_BLOCK;
+
+  profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_COOKIES, setting);
+}
+
+void CookieFilterPageGtk::OnExceptionsClicked(GtkWidget* button) {
+  HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap();
+  HostContentSettingsMap* otr_settings_map =
+      profile()->HasOffTheRecordProfile() ?
+          profile()->GetOffTheRecordProfile()->GetHostContentSettingsMap() :
+          NULL;
+  ContentExceptionsWindowGtk::ShowExceptionsWindow(
+      GTK_WINDOW(gtk_widget_get_toplevel(button)),
+      settings_map, otr_settings_map, CONTENT_SETTINGS_TYPE_COOKIES);
+}
+
+void CookieFilterPageGtk::OnBlockThirdPartyToggled(GtkWidget* toggle_button) {
+  if (ignore_toggle_)
+    return;
+
+  HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap();
+  settings_map->SetBlockThirdPartyCookies(
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
+}
+
+void CookieFilterPageGtk::OnClearOnCloseToggled(GtkWidget* toggle_button) {
+  if (ignore_toggle_)
+    return;
+
+  clear_site_data_on_exit_.SetValue(
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
+}
+
+void CookieFilterPageGtk::OnShowCookiesClicked(GtkWidget* button) {
+  UserMetricsRecordAction(UserMetricsAction("Options_ShowCookies"), NULL);
+  CookiesView::Show(GTK_WINDOW(gtk_widget_get_toplevel(button)),
+                    profile(),
+                    new BrowsingDataDatabaseHelper(profile()),
+                    new BrowsingDataLocalStorageHelper(profile()),
+                    new BrowsingDataAppCacheHelper(profile()),
+                    BrowsingDataIndexedDBHelper::Create(profile()));
+}
+
+void CookieFilterPageGtk::OnFlashLinkClicked(GtkWidget* button) {
+  browser::ShowOptionsURL(
+      profile(), GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)));
+}
diff --git a/chrome/browser/ui/gtk/options/cookie_filter_page_gtk.h b/chrome/browser/ui/gtk/options/cookie_filter_page_gtk.h
new file mode 100644
index 0000000..82c0128
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/cookie_filter_page_gtk.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_COOKIE_FILTER_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_COOKIE_FILTER_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Profile;
+
+// A page in the content settings window for cookie options. This dialog has
+// more options as is more complicated then all the other pages implemented
+// with ContentPageGtk.
+class CookieFilterPageGtk : public OptionsPageBase {
+ public:
+  explicit CookieFilterPageGtk(Profile* profile);
+  virtual ~CookieFilterPageGtk();
+
+  GtkWidget* get_page_widget() const {
+    return page_;
+  }
+
+ private:
+  // Updates the UI state.
+  virtual void UpdateUiState();
+
+  // Overridden from OptionsPageBase
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+  virtual void HighlightGroup(OptionsGroup highlight_group);
+
+  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnCookiesAllowToggled);
+  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnExceptionsClicked);
+  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnBlockThirdPartyToggled);
+  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnClearOnCloseToggled);
+  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnShowCookiesClicked);
+  CHROMEGTK_CALLBACK_0(CookieFilterPageGtk, void, OnFlashLinkClicked);
+
+  GtkWidget* InitCookieStoringGroup();
+
+  // Widgets of the cookie storing group
+  GtkWidget* allow_radio_;
+  GtkWidget* block_radio_;
+
+  GtkWidget* exceptions_button_;
+  GtkWidget* block_3rdparty_check_;
+  GtkWidget* clear_on_close_check_;
+  GtkWidget* show_cookies_button_;
+
+  // The parent GtkTable widget
+  GtkWidget* page_;
+
+  // If state of the UI is not changed by a user-action we need to ignore
+  // "toggled" events.
+  bool ignore_toggle_;
+
+  // Clear locally stored site data on exit pref.
+  BooleanPrefMember clear_site_data_on_exit_;
+
+  // Block third-party-cookies.
+  BooleanPrefMember block_third_party_cookies_;
+
+  // Managed default-cookies-setting.
+  IntegerPrefMember managed_default_cookies_setting_;
+
+  DISALLOW_COPY_AND_ASSIGN(CookieFilterPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_COOKIE_FILTER_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/cookies_view.cc b/chrome/browser/ui/gtk/options/cookies_view.cc
new file mode 100644
index 0000000..dc7be33
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/cookies_view.cc
@@ -0,0 +1,396 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/cookies_view.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <set>
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Initial size for dialog.
+const int kDialogDefaultWidth = 550;
+const int kDialogDefaultHeight = 550;
+
+// Delay after entering filter text before filtering occurs.
+const int kSearchFilterDelayMs = 500;
+
+// Response ids for our custom buttons.
+enum {
+  RESPONSE_REMOVE = 1,
+  RESPONSE_REMOVE_ALL
+};
+
+// The currently open cookie manager, if any.
+CookiesView* instance_ = NULL;
+
+}  // namespace
+
+CookiesView::~CookiesView() {
+  if (destroy_dialog_in_destructor_)
+    gtk_widget_destroy(dialog_);
+}
+
+// static
+void CookiesView::Show(
+    GtkWindow* parent,
+    Profile* profile,
+    BrowsingDataDatabaseHelper* browsing_data_database_helper,
+    BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
+    BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
+    BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper) {
+  DCHECK(profile);
+  DCHECK(browsing_data_database_helper);
+  DCHECK(browsing_data_local_storage_helper);
+  DCHECK(browsing_data_appcache_helper);
+  DCHECK(browsing_data_indexed_db_helper);
+
+  // If there's already an existing editor window, activate it.
+  if (instance_) {
+    gtk_util::PresentWindow(instance_->dialog_, 0);
+  } else {
+    instance_ = new CookiesView(parent,
+                                profile,
+                                browsing_data_database_helper,
+                                browsing_data_local_storage_helper,
+                                browsing_data_appcache_helper,
+                                browsing_data_indexed_db_helper);
+  }
+}
+
+CookiesView::CookiesView(
+    GtkWindow* parent,
+    Profile* profile,
+    BrowsingDataDatabaseHelper* browsing_data_database_helper,
+    BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
+    BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
+    BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper)
+    : profile_(profile),
+      browsing_data_database_helper_(browsing_data_database_helper),
+      browsing_data_local_storage_helper_(browsing_data_local_storage_helper),
+      browsing_data_appcache_helper_(browsing_data_appcache_helper),
+      browsing_data_indexed_db_helper_(browsing_data_indexed_db_helper),
+      filter_update_factory_(this),
+      destroy_dialog_in_destructor_(false) {
+  Init(parent);
+
+  gtk_util::ShowDialogWithLocalizedSize(dialog_,
+      IDS_COOKIES_DIALOG_WIDTH_CHARS,
+      -1,
+      true);
+
+  gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_display_));
+}
+
+void CookiesView::TestDestroySynchronously() {
+  g_signal_handler_disconnect(dialog_, destroy_handler_);
+  destroy_dialog_in_destructor_ = true;
+}
+
+void CookiesView::Init(GtkWindow* parent) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(
+          IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE).c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+  // Allow browser windows to go in front of the options dialog in metacity.
+  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
+  gtk_util::SetWindowIcon(GTK_WINDOW(dialog_));
+
+  remove_button_ = gtk_util::AddButtonToDialog(
+      dialog_,
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+        l10n_util::GetStringUTF8(IDS_COOKIES_REMOVE_LABEL)).c_str(),
+      GTK_STOCK_REMOVE,
+      RESPONSE_REMOVE);
+  gtk_button_set_use_underline(GTK_BUTTON(remove_button_), TRUE);
+  gtk_button_box_set_child_secondary(
+      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area),
+      remove_button_,
+      TRUE);
+
+  remove_all_button_ = gtk_util::AddButtonToDialog(
+      dialog_,
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(IDS_COOKIES_REMOVE_ALL_LABEL)).c_str(),
+      GTK_STOCK_CLEAR,
+      RESPONSE_REMOVE_ALL);
+  gtk_button_set_use_underline(GTK_BUTTON(remove_all_button_), TRUE);
+  gtk_button_box_set_child_secondary(
+      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area),
+      remove_all_button_,
+      TRUE);
+
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_CLOSE);
+  gtk_window_set_default_size(GTK_WINDOW(dialog_), kDialogDefaultWidth,
+                              kDialogDefaultHeight);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+  destroy_handler_ = g_signal_connect(dialog_, "destroy",
+                                      G_CALLBACK(OnWindowDestroyThunk), this);
+
+  // Filtering controls.
+  GtkWidget* filter_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  filter_entry_ = gtk_entry_new();
+  g_signal_connect(filter_entry_, "activate",
+                   G_CALLBACK(OnFilterEntryActivatedThunk), this);
+  g_signal_connect(filter_entry_, "changed",
+                   G_CALLBACK(OnFilterEntryChangedThunk), this);
+  gtk_box_pack_start(GTK_BOX(filter_hbox), filter_entry_,
+                     TRUE, TRUE, 0);
+  filter_clear_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(IDS_COOKIES_CLEAR_SEARCH_LABEL)).c_str());
+  g_signal_connect(filter_clear_button_, "clicked",
+                   G_CALLBACK(OnFilterClearButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(filter_hbox), filter_clear_button_,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* filter_controls = gtk_util::CreateLabeledControlsGroup(NULL,
+      l10n_util::GetStringUTF8(IDS_COOKIES_SEARCH_LABEL).c_str(), filter_hbox,
+      NULL);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), filter_controls,
+                     FALSE, FALSE, 0);
+
+  // Cookie list.
+  GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), cookie_list_vbox,
+                     TRUE, TRUE, 0);
+
+  description_label_ = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_COOKIES_INFO_LABEL).c_str());
+  gtk_misc_set_alignment(GTK_MISC(description_label_), 0, 0.5);
+  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), description_label_,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
+
+  cookies_tree_model_.reset(new CookiesTreeModel(
+      profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(),
+      browsing_data_database_helper_,
+      browsing_data_local_storage_helper_,
+      NULL,
+      browsing_data_appcache_helper_,
+      browsing_data_indexed_db_helper_));
+  cookies_tree_adapter_.reset(
+      new gtk_tree::TreeAdapter(this, cookies_tree_model_.get()));
+  tree_ = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(cookies_tree_adapter_->tree_store()));
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), FALSE);
+  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(tree_), TRUE);
+  gtk_container_add(GTK_CONTAINER(scroll_window), tree_);
+
+  GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
+  GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE);
+  gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf",
+                                     gtk_tree::TreeAdapter::COL_ICON);
+  GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
+  gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
+                                     gtk_tree::TreeAdapter::COL_TITLE);
+  gtk_tree_view_column_set_title(
+      title_column, l10n_util::GetStringUTF8(
+          IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), title_column);
+  g_signal_connect(tree_, "key-press-event",
+                   G_CALLBACK(OnTreeViewKeyPressThunk), this);
+  g_signal_connect(tree_, "row-expanded",
+                   G_CALLBACK(OnTreeViewRowExpandedThunk), this);
+
+  selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_));
+  gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE);
+  g_signal_connect(selection_, "changed",
+                   G_CALLBACK(OnTreeViewSelectionChangeThunk), this);
+
+  cookie_display_ = gtk_chrome_cookie_view_new(FALSE);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                     cookie_display_, FALSE, FALSE, 0);
+
+  // Populate the view.
+  cookies_tree_adapter_->Init();
+  SetInitialTreeState();
+  EnableControls();
+}
+
+void CookiesView::SetInitialTreeState() {
+  if (cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot()))
+    gtk_tree::SelectAndFocusRowNum(0, GTK_TREE_VIEW(tree_));
+}
+
+void CookiesView::EnableControls() {
+  GtkTreeIter iter;
+  bool selected = gtk_tree_selection_get_selected(selection_, NULL, &iter);
+  gtk_widget_set_sensitive(remove_button_, selected);
+  gtk_widget_set_sensitive(
+      remove_all_button_,
+      cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot()));
+
+  const gchar* filter_text = gtk_entry_get_text(GTK_ENTRY(filter_entry_));
+  gtk_widget_set_sensitive(filter_clear_button_, filter_text && *filter_text);
+
+  if (selected) {
+    CookieTreeNode::DetailedInfo detailed_info =
+        static_cast<CookieTreeNode*>(
+            cookies_tree_adapter_->GetNode(&iter))->GetDetailedInfo();
+    if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
+      gtk_chrome_cookie_view_display_cookie(
+          GTK_CHROME_COOKIE_VIEW(cookie_display_),
+          detailed_info.cookie->Domain(),
+          *detailed_info.cookie);
+    } else if (detailed_info.node_type ==
+               CookieTreeNode::DetailedInfo::TYPE_DATABASE) {
+      gtk_chrome_cookie_view_display_database(
+          GTK_CHROME_COOKIE_VIEW(cookie_display_),
+          *detailed_info.database_info);
+    } else if (detailed_info.node_type ==
+               CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE) {
+      gtk_chrome_cookie_view_display_local_storage(
+          GTK_CHROME_COOKIE_VIEW(cookie_display_),
+          *detailed_info.local_storage_info);
+    } else if (detailed_info.node_type ==
+               CookieTreeNode::DetailedInfo::TYPE_APPCACHE) {
+      gtk_chrome_cookie_view_display_app_cache(
+          GTK_CHROME_COOKIE_VIEW(cookie_display_),
+          *detailed_info.appcache_info);
+    } else if (detailed_info.node_type ==
+               CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB) {
+      gtk_chrome_cookie_view_display_indexed_db(
+          GTK_CHROME_COOKIE_VIEW(cookie_display_),
+          *detailed_info.indexed_db_info);
+    } else {
+      gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_display_));
+    }
+  } else {
+    gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_display_));
+  }
+}
+
+void CookiesView::RemoveSelectedItems() {
+  GtkTreeIter iter;
+  bool selected = gtk_tree_selection_get_selected(selection_, NULL, &iter);
+  if (selected) {
+    GtkTreePath* path = gtk_tree_model_get_path(
+        GTK_TREE_MODEL(cookies_tree_adapter_->tree_store()),
+        &iter);
+    CookieTreeNode* node = static_cast<CookieTreeNode*>(
+        cookies_tree_adapter_->GetNode(&iter));
+    cookies_tree_model_->DeleteCookieNode(node);
+    // After removing a node, try to select the "next" node.
+    // We call gtk_tree_model_get_iter to check if there is still a node at the
+    // pointed to by path.  If not, we try to select the previous node in that
+    // subtree.  If that subtree is empty, we then try to select the parent.
+    if (gtk_tree_model_get_iter(
+        GTK_TREE_MODEL(cookies_tree_adapter_->tree_store()),
+        &iter,
+        path)) {
+      gtk_tree_selection_select_iter(selection_, &iter);
+    } else if (gtk_tree_path_prev(path)) {
+      gtk_tree_selection_select_path(selection_, path);
+    } else if (gtk_tree_path_up(path)) {
+      gtk_tree_selection_select_path(selection_, path);
+    }
+    gtk_tree_path_free(path);
+  }
+}
+
+void CookiesView::OnAnyModelUpdateStart() {
+  g_signal_handlers_block_by_func(
+      selection_, reinterpret_cast<gpointer>(OnTreeViewSelectionChangeThunk),
+      this);
+}
+
+void CookiesView::OnAnyModelUpdate() {
+  g_signal_handlers_unblock_by_func(
+      selection_, reinterpret_cast<gpointer>(OnTreeViewSelectionChangeThunk),
+      this);
+  EnableControls();
+}
+
+void CookiesView::OnResponse(GtkWidget* dialog, int response_id) {
+  if (response_id == RESPONSE_REMOVE) {
+    RemoveSelectedItems();
+  } else if (response_id == RESPONSE_REMOVE_ALL) {
+    cookies_tree_model_->DeleteAllStoredObjects();
+  } else {
+    gtk_widget_destroy(dialog);
+  }
+}
+
+void CookiesView::OnWindowDestroy(GtkWidget* widget) {
+  instance_ = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void CookiesView::OnTreeViewSelectionChange(GtkWidget* selection) {
+  EnableControls();
+}
+
+gboolean CookiesView::OnTreeViewKeyPress(GtkWidget* tree_view,
+                                         GdkEventKey* key) {
+  if (key->keyval == GDK_Delete) {
+    RemoveSelectedItems();
+    return TRUE;
+  }
+  return FALSE;
+}
+
+void CookiesView::OnTreeViewRowExpanded(GtkWidget* tree_view,
+                                        GtkTreeIter* iter,
+                                        GtkTreePath* path) {
+  // When a row in the tree is expanded, expand all the children too.
+  g_signal_handlers_block_by_func(
+      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
+  gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
+  g_signal_handlers_unblock_by_func(
+      tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this);
+}
+
+void CookiesView::UpdateFilterResults() {
+  const gchar* text = gtk_entry_get_text(GTK_ENTRY(filter_entry_));
+  if (text) {
+    cookies_tree_model_->UpdateSearchResults(UTF8ToWide(text));
+    SetInitialTreeState();
+  }
+}
+
+void CookiesView::OnFilterEntryActivated(GtkWidget* entry) {
+  filter_update_factory_.RevokeAll();
+  UpdateFilterResults();
+}
+
+void CookiesView::OnFilterEntryChanged(GtkWidget* editable) {
+  filter_update_factory_.RevokeAll();
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      filter_update_factory_.NewRunnableMethod(
+          &CookiesView::UpdateFilterResults), kSearchFilterDelayMs);
+  EnableControls();
+}
+
+void CookiesView::OnFilterClearButtonClicked(GtkWidget* button) {
+  gtk_entry_set_text(GTK_ENTRY(filter_entry_), "");
+  filter_update_factory_.RevokeAll();
+  UpdateFilterResults();
+}
diff --git a/chrome/browser/ui/gtk/options/cookies_view.h b/chrome/browser/ui/gtk/options/cookies_view.h
new file mode 100644
index 0000000..26d72f6
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/cookies_view.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is the Gtk implementation of the Cookie Manager dialog.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_COOKIES_VIEW_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_COOKIES_VIEW_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/browsing_data_appcache_helper.h"
+#include "chrome/browser/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data_indexed_db_helper.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_cookie_view.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "net/base/cookie_monster.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class CookieDisplayGtk;
+class CookiesTreeModel;
+class CookiesViewTest;
+class Profile;
+
+// CookiesView is thread-hostile, and should only be called on the UI thread.
+// Usage:
+//   CookiesView::Show(profile);
+// Once the CookiesView is shown, it is responsible for deleting itself when the
+// user closes the dialog.
+
+class CookiesView : public gtk_tree::TreeAdapter::Delegate {
+ public:
+  virtual ~CookiesView();
+
+  // Create (if necessary) and show the cookie manager window.
+  static void Show(
+      GtkWindow* parent,
+      Profile* profile,
+      BrowsingDataDatabaseHelper* browsing_data_database_helper,
+      BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
+      BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
+      BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper);
+
+  // gtk_tree::TreeAdapter::Delegate implementation.
+  virtual void OnAnyModelUpdateStart();
+  virtual void OnAnyModelUpdate();
+
+ private:
+  CookiesView(
+      GtkWindow* parent,
+      Profile* profile,
+      BrowsingDataDatabaseHelper* browsing_data_database_helper,
+      BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper,
+      BrowsingDataAppCacheHelper* browsing_data_appcache_helper,
+      BrowsingDataIndexedDBHelper* browsing_data_indexed_db_helper);
+
+  // A method only used in unit tests that sets a bit inside this class that
+  // lets it be stack allocated.
+  void TestDestroySynchronously();
+
+  // Initialize the dialog contents and layout.
+  void Init(GtkWindow* parent);
+
+  // Set the initial selection and tree expanded state.
+  void SetInitialTreeState();
+
+  // Set sensitivity of buttons based on selection and filter state.
+  void EnableControls();
+
+  // Remove any cookies that are currently selected.
+  void RemoveSelectedItems();
+
+  CHROMEGTK_CALLBACK_1(CookiesView, void, OnResponse, int);
+  CHROMEGTK_CALLBACK_0(CookiesView, void, OnWindowDestroy);
+  // Callback for the table.
+  CHROMEGTK_CALLBACK_0(CookiesView, void, OnTreeViewSelectionChange);
+  CHROMEGTK_CALLBACK_1(CookiesView, gboolean, OnTreeViewKeyPress,
+                       GdkEventKey*);
+  CHROMEGTK_CALLBACK_2(CookiesView, void, OnTreeViewRowExpanded,
+                       GtkTreeIter*, GtkTreePath*);
+  // Callbacks for user actions filtering the list.
+  CHROMEGTK_CALLBACK_0(CookiesView, void, OnFilterEntryActivated);
+  CHROMEGTK_CALLBACK_0(CookiesView, void, OnFilterEntryChanged);
+  CHROMEGTK_CALLBACK_0(CookiesView, void, OnFilterClearButtonClicked);
+
+  // Filter the list against the text in |filter_entry_|.
+  void UpdateFilterResults();
+
+
+  // The parent widget.
+  GtkWidget* dialog_;
+
+  // Widgets of the dialog.
+  GtkWidget* description_label_;
+  GtkWidget* filter_entry_;
+  GtkWidget* filter_clear_button_;
+  GtkWidget* remove_button_;
+  GtkWidget* remove_all_button_;
+
+  // The table listing the cookies.
+  GtkWidget* tree_;
+  GtkTreeSelection* selection_;
+
+  GtkWidget* cookie_display_;
+
+  // The profile and related helpers.
+  Profile* profile_;
+  scoped_refptr<BrowsingDataDatabaseHelper> browsing_data_database_helper_;
+  scoped_refptr<BrowsingDataLocalStorageHelper>
+      browsing_data_local_storage_helper_;
+  scoped_refptr<BrowsingDataAppCacheHelper> browsing_data_appcache_helper_;
+  scoped_refptr<BrowsingDataIndexedDBHelper> browsing_data_indexed_db_helper_;
+
+  // A factory to construct Runnable Methods so that we can be called back to
+  // re-evaluate the model after the search query string changes.
+  ScopedRunnableMethodFactory<CookiesView> filter_update_factory_;
+
+  // The Cookies Table model.
+  scoped_ptr<CookiesTreeModel> cookies_tree_model_;
+  scoped_ptr<gtk_tree::TreeAdapter> cookies_tree_adapter_;
+
+  // A reference to the "destroy" signal handler for this object. We disconnect
+  // from this signal if we need to be destroyed synchronously.
+  gulong destroy_handler_;
+
+  // Whether we own |dialog_| or the other way around.
+  bool destroy_dialog_in_destructor_;
+
+  friend class CookiesViewTest;
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Empty);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Noop);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveAll);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveAllWithDefaultSelected);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Remove);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveCookiesByType);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveByDomain);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, RemoveDefaultSelection);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, Filter);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, FilterRemoveAll);
+  FRIEND_TEST_ALL_PREFIXES(CookiesViewTest, FilterRemove);
+
+  DISALLOW_COPY_AND_ASSIGN(CookiesView);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_COOKIES_VIEW_H_
diff --git a/chrome/browser/ui/gtk/options/cookies_view_unittest.cc b/chrome/browser/ui/gtk/options/cookies_view_unittest.cc
new file mode 100644
index 0000000..60db7b4
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/cookies_view_unittest.cc
@@ -0,0 +1,1202 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/cookies_view.h"
+
+#include <string>
+#include <vector>
+
+#include <gtk/gtk.h>
+
+#include "base/string_util.h"
+#include "chrome/browser/mock_browsing_data_appcache_helper.h"
+#include "chrome/browser/mock_browsing_data_database_helper.h"
+#include "chrome/browser/mock_browsing_data_indexed_db_helper.h"
+#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_cookie_view.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "chrome/test/testing_profile.h"
+#include "net/url_request/url_request_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class CookiesViewTest : public testing::Test {
+ public:
+  CookiesViewTest() : io_thread_(BrowserThread::IO, &message_loop_) {
+  }
+
+  virtual ~CookiesViewTest() {
+  }
+
+  virtual void SetUp() {
+    profile_.reset(new TestingProfile());
+    profile_->CreateRequestContext();
+    mock_browsing_data_database_helper_ =
+        new MockBrowsingDataDatabaseHelper(profile_.get());
+    mock_browsing_data_local_storage_helper_ =
+        new MockBrowsingDataLocalStorageHelper(profile_.get());
+    mock_browsing_data_appcache_helper_ =
+        new MockBrowsingDataAppCacheHelper(profile_.get());
+    mock_browsing_data_indexed_db_helper_ =
+        new MockBrowsingDataIndexedDBHelper(profile_.get());
+  }
+
+  void CheckDetailsSensitivity(gboolean expected_cookies,
+                               gboolean expected_database,
+                               gboolean expected_local_storage,
+                               gboolean expected_appcache,
+                               gboolean expected_indexed_db,
+                               const CookiesView& cookies_view) {
+    GtkChromeCookieView* display = GTK_CHROME_COOKIE_VIEW(
+        cookies_view.cookie_display_);
+
+    // Cookies
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_name_entry_));
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_content_entry_));
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_domain_entry_));
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_path_entry_));
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_send_for_entry_));
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_created_entry_));
+    EXPECT_EQ(expected_cookies,
+              GTK_WIDGET_SENSITIVE(display->cookie_expires_entry_));
+    // Database
+    EXPECT_EQ(expected_database,
+              GTK_WIDGET_SENSITIVE(display->database_description_entry_));
+    EXPECT_EQ(expected_database,
+              GTK_WIDGET_SENSITIVE(display->database_size_entry_));
+    EXPECT_EQ(expected_database,
+              GTK_WIDGET_SENSITIVE(display->database_last_modified_entry_));
+    // Local Storage
+    EXPECT_EQ(expected_local_storage,
+              GTK_WIDGET_SENSITIVE(display->local_storage_origin_entry_));
+    EXPECT_EQ(expected_local_storage,
+              GTK_WIDGET_SENSITIVE(display->local_storage_size_entry_));
+    EXPECT_EQ(expected_local_storage, GTK_WIDGET_SENSITIVE(
+        display->local_storage_last_modified_entry_));
+    // AppCache
+    EXPECT_EQ(expected_appcache,
+              GTK_WIDGET_SENSITIVE(display->appcache_manifest_entry_));
+    EXPECT_EQ(expected_appcache,
+              GTK_WIDGET_SENSITIVE(display->appcache_size_entry_));
+    EXPECT_EQ(expected_appcache,
+              GTK_WIDGET_SENSITIVE(display->appcache_created_entry_));
+    EXPECT_EQ(expected_appcache,
+              GTK_WIDGET_SENSITIVE(display->appcache_last_accessed_entry_));
+    // IndexedDB
+    EXPECT_EQ(expected_indexed_db,
+              GTK_WIDGET_SENSITIVE(display->indexed_db_origin_entry_));
+    EXPECT_EQ(expected_indexed_db,
+              GTK_WIDGET_SENSITIVE(display->indexed_db_size_entry_));
+    EXPECT_EQ(expected_indexed_db,
+              GTK_WIDGET_SENSITIVE(display->indexed_db_last_modified_entry_));
+  }
+
+  // Get the cookie names in the cookie list, as a comma seperated string.
+  // (Note that the CookieMonster cookie list is sorted by domain.)
+  // Ex:
+  //   monster->SetCookie(GURL("http://b"), "X=1")
+  //   monster->SetCookie(GURL("http://a"), "Y=1")
+  //   EXPECT_STREQ("Y,X", GetMonsterCookies(monster).c_str());
+  std::string GetMonsterCookies(net::CookieMonster* monster) {
+    std::vector<std::string> parts;
+    net::CookieList cookie_list = monster->GetAllCookies();
+    for (size_t i = 0; i < cookie_list.size(); ++i)
+      parts.push_back(cookie_list[i].Name());
+    return JoinString(parts, ',');
+  }
+
+  typedef std::pair<std::vector<std::string>*, GtkTreeView*>
+      DisplayedCookiesData;
+
+  static gboolean GetDisplayedCookiesHelper(GtkTreeModel *model,
+                                            GtkTreePath *path,
+                                            GtkTreeIter *iter,
+                                            gpointer user_data) {
+    DisplayedCookiesData* data =
+        reinterpret_cast<DisplayedCookiesData*>(user_data);
+    gchar* title;
+    gtk_tree_model_get(model, iter,
+                       gtk_tree::TreeAdapter::COL_TITLE, &title,
+                       -1);
+    std::string str;
+    if (gtk_tree_path_get_depth(path) > 1) {
+      // There isn't a function to check if a row is visible, instead we have to
+      // check whether the parent is expanded.
+      GtkTreePath* parent_path = gtk_tree_path_copy(path);
+      gtk_tree_path_up(parent_path);
+      str.append(
+          gtk_tree_path_get_depth(parent_path),
+          gtk_tree_view_row_expanded(data->second, parent_path) ? '+' : '_');
+      gtk_tree_path_free(parent_path);
+    }
+    str += title;
+    g_free(title);
+    data->first->push_back(str);
+    return FALSE;
+  }
+
+  // Get the cookie names displayed in the dialog in the order they are
+  // displayed, as a comma seperated string.
+  // Items are prefixed with _ or + up to their indent level.
+  // _ when hidden (parent is closed) and + when visible (parent is expanded).
+  // Ex: EXPECT_STREQ("a,+Cookies,++Y,b,_Cookies,__X",
+  //                  GetDisplayedCookies(cookies_view).c_str());
+  std::string GetDisplayedCookies(const CookiesView& cookies_view) {
+    GtkTreeStore* tree_store = cookies_view.cookies_tree_adapter_->tree_store();
+    std::vector<std::string> parts;
+    DisplayedCookiesData helper_data(&parts, GTK_TREE_VIEW(cookies_view.tree_));
+    gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store),
+                           GetDisplayedCookiesHelper, &helper_data);
+    return JoinString(parts, ',');
+  }
+
+  bool ExpandByPath(const CookiesView& cookies_view, const char* path_str) {
+    GtkTreePath* path = gtk_tree_path_new_from_string(path_str);
+    if (!path)
+      return false;
+    bool rv = gtk_tree_view_expand_row(GTK_TREE_VIEW(cookies_view.tree_), path,
+                                       FALSE);
+    gtk_tree_path_free(path);
+    return rv;
+  }
+
+  bool SelectByPath(const CookiesView& cookies_view, const char* path_str) {
+    GtkTreePath* path = gtk_tree_path_new_from_string(path_str);
+    if (!path)
+      return false;
+    gtk_tree_selection_select_path(cookies_view.selection_, path);
+    bool rv = gtk_tree_selection_path_is_selected(cookies_view.selection_,
+                                                  path);
+    gtk_tree_path_free(path);
+    return rv;
+  }
+
+  std::string GetSelectedPath(const CookiesView& cookies_view) {
+    std::string result;
+    GtkTreeIter iter;
+    bool selected = gtk_tree_selection_get_selected(cookies_view.selection_,
+                                                    NULL, &iter);
+    if (selected) {
+      gchar* path_str = gtk_tree_model_get_string_from_iter(
+          GTK_TREE_MODEL(cookies_view.cookies_tree_adapter_->tree_store()),
+          &iter);
+      if (path_str) {
+        result = path_str;
+        g_free(path_str);
+      }
+    }
+    return result;
+  }
+
+ protected:
+  MessageLoop message_loop_;
+  BrowserThread io_thread_;
+
+  scoped_ptr<TestingProfile> profile_;
+  scoped_refptr<MockBrowsingDataDatabaseHelper>
+      mock_browsing_data_database_helper_;
+  scoped_refptr<MockBrowsingDataLocalStorageHelper>
+      mock_browsing_data_local_storage_helper_;
+  scoped_refptr<MockBrowsingDataAppCacheHelper>
+      mock_browsing_data_appcache_helper_;
+  scoped_refptr<MockBrowsingDataIndexedDBHelper>
+      mock_browsing_data_indexed_db_helper_;
+};
+
+TEST_F(CookiesViewTest, Empty) {
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+}
+
+TEST_F(CookiesViewTest, Noop) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://foo0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://foo1"), "A=1");
+  monster->SetCookie(GURL("http://foo1"), "E=1");
+  monster->SetCookie(GURL("http://foo2"), "G=1");
+  monster->SetCookie(GURL("http://foo2"), "X=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo1,_Cookies,__A,__B,__E,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+}
+
+TEST_F(CookiesViewTest, RemoveAll) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo"), "A=1");
+  monster->SetCookie(GURL("http://foo2"), "B=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  // Reset the selection of the first row.
+  gtk_tree_selection_unselect_all(cookies_view.selection_);
+
+  {
+    SCOPED_TRACE("Before removing");
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B,"
+                 "gdbhost1,_Web Databases,__db1,"
+                 "gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+  }
+
+  mock_browsing_data_database_helper_->Reset();
+  mock_browsing_data_local_storage_helper_->Reset();
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_));
+  {
+    SCOPED_TRACE("After removing");
+    EXPECT_EQ(0u, monster->GetAllCookies().size());
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_TRUE(mock_browsing_data_database_helper_->AllDeleted());
+    EXPECT_TRUE(mock_browsing_data_local_storage_helper_->AllDeleted());
+  }
+}
+
+TEST_F(CookiesViewTest, RemoveAllWithDefaultSelected) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo"), "A=1");
+  monster->SetCookie(GURL("http://foo2"), "B=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+  EXPECT_EQ(1, gtk_tree_selection_count_selected_rows(cookies_view.selection_));
+  {
+    SCOPED_TRACE("Before removing");
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B,"
+                 "gdbhost1,_Web Databases,__db1,"
+                 "gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+  }
+
+  mock_browsing_data_database_helper_->Reset();
+  mock_browsing_data_local_storage_helper_->Reset();
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_));
+  {
+    SCOPED_TRACE("After removing");
+    EXPECT_EQ(0u, monster->GetAllCookies().size());
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(0,
+              gtk_tree_selection_count_selected_rows(cookies_view.selection_));
+    EXPECT_TRUE(mock_browsing_data_database_helper_->AllDeleted());
+    EXPECT_TRUE(mock_browsing_data_local_storage_helper_->AllDeleted());
+  }
+}
+
+TEST_F(CookiesViewTest, Remove) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo1"), "A=1");
+  monster->SetCookie(GURL("http://foo2"), "B=1");
+  monster->SetCookie(GURL("http://foo2"), "C=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
+
+  {
+    SCOPED_TRACE("First selection");
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++B,++C,"
+                 "gdbhost1,_Web Databases,__db1,"
+                 "gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+  }
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("First selection removed");
+    EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
+    EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++C,"
+                 "gdbhost1,_Web Databases,__db1,"
+                 "gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str());
+    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("Second selection");
+    EXPECT_STREQ("A", GetMonsterCookies(monster).c_str());
+    EXPECT_STREQ("foo1,_Cookies,__A,"
+                 "gdbhost1,_Web Databases,__db1,"
+                 "gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    EXPECT_STREQ("", GetSelectedPath(cookies_view).c_str());
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
+  EXPECT_STREQ("foo1,+Cookies,++A,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("Second selection removed");
+    EXPECT_EQ(0u, monster->GetAllCookies().size());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+                 "gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+  }
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
+  EXPECT_STREQ("gdbhost1,+Web Databases,++db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("Third selection removed");
+    EXPECT_EQ(0u, monster->GetAllCookies().size());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
+                "http_gdbhost1_1");
+    EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
+                "db1");
+  }
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+               "host1,+Local Storage,++http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("Fourth selection removed");
+    EXPECT_EQ(0u, monster->GetAllCookies().size());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
+                FilePath(FILE_PATH_LITERAL("file1")));
+  }
+}
+
+TEST_F(CookiesViewTest, RemoveCookiesByType) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://foo0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://foo1"), "A=1");
+  monster->SetCookie(GURL("http://foo1"), "E=1");
+  monster->SetCookie(GURL("http://foo2"), "G=1");
+  monster->SetCookie(GURL("http://foo2"), "X=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo1,_Cookies,__A,__B,__E,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo1,+Cookies,++A,++B,++E,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "1:0"));
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("C,D,G,X", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
+  EXPECT_STREQ("foo0,+Cookies,++C,++D,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
+  EXPECT_STREQ("foo2,+Cookies,++G,++X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
+  EXPECT_STREQ("gdbhost1,+Web Databases,++db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
+              "http_gdbhost1_1");
+  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
+              "db1");
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+               "host1,+Local Storage,++http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "1:0"));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
+              FilePath(FILE_PATH_LITERAL("file1")));
+}
+
+TEST_F(CookiesViewTest, RemoveByDomain) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://foo0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://foo1"), "A=1");
+  monster->SetCookie(GURL("http://foo1"), "E=1");
+  monster->SetCookie(GURL("http://foo2"), "G=1");
+  monster->SetCookie(GURL("http://foo2"), "X=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo1,_Cookies,__A,__B,__E,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  ASSERT_TRUE(SelectByPath(cookies_view, "1"));
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("C,D,G,X", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_STREQ("1", GetSelectedPath(cookies_view).c_str());
+
+  ASSERT_TRUE(SelectByPath(cookies_view, "0"));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
+              "http_gdbhost1_1");
+  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
+              "db1");
+  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_origin_ ==
+              "http_gdbhost2_2");
+  EXPECT_TRUE(mock_browsing_data_database_helper_->last_deleted_db_ ==
+              "db2");
+  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
+        FilePath(FILE_PATH_LITERAL("file1")));
+  EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  EXPECT_TRUE(mock_browsing_data_local_storage_helper_->last_deleted_file_ ==
+        FilePath(FILE_PATH_LITERAL("file2")));
+
+  EXPECT_EQ(0, gtk_tree_selection_count_selected_rows(cookies_view.selection_));
+}
+
+TEST_F(CookiesViewTest, RemoveDefaultSelection) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://foo0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://foo1"), "A=1");
+  monster->SetCookie(GURL("http://foo1"), "E=1");
+  monster->SetCookie(GURL("http://foo2"), "G=1");
+  monster->SetCookie(GURL("http://foo2"), "X=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("foo0,_Cookies,__C,__D,"
+               "foo1,_Cookies,__A,__B,__E,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("B,A,E,G,X", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("foo1,_Cookies,__A,__B,__E,"
+               "foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("foo2,_Cookies,__G,__X,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+  EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+}
+
+TEST_F(CookiesViewTest, Filter) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://bar0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://bar1"), "A=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+
+  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  // Entering text doesn't immediately filter the results.
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  // Results are filtered immediately if you activate (hit enter in the entry).
+  gtk_widget_activate(cookies_view.filter_entry_);
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "hos");
+  gtk_widget_activate(cookies_view.filter_entry_);
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+}
+
+TEST_F(CookiesViewTest, FilterRemoveAll) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://bar0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://bar1"), "A=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+
+  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  // Entering text doesn't immediately filter the results.
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  // Results are filtered immediately if you activate (hit enter in the entry).
+  gtk_widget_activate(cookies_view.filter_entry_);
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_));
+
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+  EXPECT_STREQ("",
+               GetDisplayedCookies(cookies_view).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
+  EXPECT_STREQ("foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+}
+
+TEST_F(CookiesViewTest, FilterRemove) {
+  net::CookieMonster* monster = profile_->GetCookieMonster();
+  monster->SetCookie(GURL("http://foo0"), "C=1");
+  monster->SetCookie(GURL("http://bar0"), "D=1");
+  monster->SetCookie(GURL("http://foo1"), "B=1");
+  monster->SetCookie(GURL("http://bar1"), "A=1");
+  monster->SetCookie(GURL("http://bar1"), "E=1");
+  CookiesView cookies_view(NULL,
+                           profile_.get(),
+                           mock_browsing_data_database_helper_,
+                           mock_browsing_data_local_storage_helper_,
+                           mock_browsing_data_appcache_helper_,
+                           mock_browsing_data_indexed_db_helper_);
+  cookies_view.TestDestroySynchronously();
+  mock_browsing_data_database_helper_->AddDatabaseSamples();
+  mock_browsing_data_database_helper_->Notify();
+  mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
+  mock_browsing_data_local_storage_helper_->Notify();
+
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,__E,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  // All default paths; order will be creation time.
+  EXPECT_STREQ("C,D,B,A,E", GetMonsterCookies(monster).c_str());
+
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+
+  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  // Entering text doesn't immediately filter the results.
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,__E,"
+               "foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  // Results are filtered immediately if you activate (hit enter in the entry).
+  gtk_widget_activate(cookies_view.filter_entry_);
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,_Cookies,__A,__E",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+  EXPECT_STREQ("bar0,_Cookies,__D,"
+               "bar1,+Cookies,++A,++E",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
+
+  {
+    SCOPED_TRACE("First selection");
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("First selection removed");
+    EXPECT_STREQ("C,D,B,E", GetMonsterCookies(monster).c_str());
+    EXPECT_STREQ("bar0,_Cookies,__D,"
+                 "bar1,+Cookies,++E",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str());
+    CheckDetailsSensitivity(TRUE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("Second selection");
+    EXPECT_STREQ("C,D,B", GetMonsterCookies(monster).c_str());
+    EXPECT_STREQ("bar0,_Cookies,__D",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
+  ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("Second selection removed");
+    EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+    EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+  }
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
+  EXPECT_STREQ("foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "hos");
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+  // Entering text doesn't immediately filter the results.
+  EXPECT_STREQ("foo0,_Cookies,__C,"
+               "foo1,_Cookies,__B,"
+               "gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  // Results are filtered immediately if you activate (hit enter in the entry).
+  gtk_widget_activate(cookies_view.filter_entry_);
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,_Web Databases,__db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "gdbhost2,+Web Databases,++db2,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,_Local Storage,__http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
+
+  {
+    SCOPED_TRACE("First selection");
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, TRUE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("First selection removed");
+    EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
+    EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+                 "host1,_Local Storage,__http://host1:1/,"
+                 "host2,_Local Storage,__http://host2:2/",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+
+  ASSERT_TRUE(ExpandByPath(cookies_view, "2"));
+  EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+               "host1,_Local Storage,__http://host1:1/,"
+               "host2,+Local Storage,++http://host2:2/",
+               GetDisplayedCookies(cookies_view).c_str());
+  ASSERT_TRUE(SelectByPath(cookies_view, "2:0:0"));
+
+  {
+    SCOPED_TRACE("First selection");
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, TRUE, FALSE, FALSE, cookies_view);
+  }
+
+  gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+  {
+    SCOPED_TRACE("First selection removed");
+    EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
+    EXPECT_STREQ("gdbhost1,_Web Databases,__db1,"
+                 "host1,_Local Storage,__http://host1:1/",
+                 GetDisplayedCookies(cookies_view).c_str());
+    EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+    EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+    CheckDetailsSensitivity(FALSE, FALSE, FALSE, FALSE, FALSE, cookies_view);
+  }
+}
diff --git a/chrome/browser/ui/gtk/options/fonts_languages_window_gtk.cc b/chrome/browser/ui/gtk/options/fonts_languages_window_gtk.cc
new file mode 100644
index 0000000..909b31c
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/fonts_languages_window_gtk.cc
@@ -0,0 +1,149 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/fonts_languages_window.h"
+
+#include <gtk/gtk.h>
+
+#include "base/message_loop.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/fonts_page_gtk.h"
+#include "chrome/browser/ui/gtk/options/languages_page_gtk.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// FontsLanguagesWindowGtk
+//
+// The contents of the Options dialog window.
+
+class FontsLanguagesWindowGtk {
+ public:
+  explicit FontsLanguagesWindowGtk(Profile* profile);
+  ~FontsLanguagesWindowGtk();
+
+  // Shows the tab corresponding to the specified |page|.
+  void ShowTabPage(gfx::NativeWindow window, FontsLanguagesPage page);
+
+ private:
+  static void OnWindowDestroy(GtkWidget* widget,
+                              FontsLanguagesWindowGtk* window);
+
+  // The fonts and languages dialog.
+  GtkWidget *dialog_;
+
+  // The container of the option pages.
+  GtkWidget *notebook_;
+
+  // The Profile associated with these options.
+  Profile* profile_;
+
+  // The fonts page.
+  FontsPageGtk fonts_page_;
+
+  // The languages page.
+  LanguagesPageGtk languages_page_;
+
+  DISALLOW_COPY_AND_ASSIGN(FontsLanguagesWindowGtk);
+};
+
+static FontsLanguagesWindowGtk* instance_ = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+// FontsLanguagesWindowGtk, public:
+
+FontsLanguagesWindowGtk::FontsLanguagesWindowGtk(Profile* profile)
+      // Always show preferences for the original profile. Most state when off
+      // the record comes from the original profile, but we explicitly use
+      // the original profile to avoid potential problems.
+    : profile_(profile->GetOriginalProfile()),
+      fonts_page_(profile_),
+      languages_page_(profile_) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_FONT_LANGUAGE_SETTING_WINDOWS_TITLE).c_str(),
+      // Prefs window is shared between all browser windows.
+      NULL,
+      // Non-modal.
+      GTK_DIALOG_NO_SEPARATOR,
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+
+  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  notebook_ = gtk_notebook_new();
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
+
+  // Fonts and Encoding tab.
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      fonts_page_.get_page_widget(),
+      gtk_label_new(
+          l10n_util::GetStringUTF8(
+              IDS_FONT_LANGUAGE_SETTING_FONT_TAB_TITLE).c_str()));
+
+  // Langauges tab.
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      languages_page_.get_page_widget(),
+      gtk_label_new(
+          l10n_util::GetStringUTF8(
+              IDS_FONT_LANGUAGE_SETTING_LANGUAGES_TAB_TITLE).c_str()));
+
+  // Show the notebook.
+  gtk_util::ShowDialogWithLocalizedSize(dialog_, -1, -1, false);
+
+  // We only have one button and don't do any special handling, so just hook it
+  // directly to gtk_widget_destroy.
+  g_signal_connect_swapped(dialog_, "response", G_CALLBACK(gtk_widget_destroy),
+                           dialog_);
+
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
+}
+
+FontsLanguagesWindowGtk::~FontsLanguagesWindowGtk() {
+}
+
+void FontsLanguagesWindowGtk::ShowTabPage(gfx::NativeWindow window,
+                                          FontsLanguagesPage page) {
+  // Center our dialog over whoever displayed us.
+  gtk_util::CenterOverWindow(GTK_WINDOW(dialog_), window);
+
+  // Bring options window to front if it already existed and isn't already
+  // in front.
+  gtk_util::PresentWindow(dialog_, 0);
+
+  // If the page is out of bounds, reset to the first tab.
+  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
+    page = FONTS_ENCODING_PAGE;
+
+  // Switch the tab to the selected |page|.
+  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// FontsLanguagesWindowGtk, private:
+
+// static
+void FontsLanguagesWindowGtk::OnWindowDestroy(GtkWidget* widget,
+    FontsLanguagesWindowGtk* window) {
+  instance_ = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
+}
+
+void ShowFontsLanguagesWindow(gfx::NativeWindow window,
+                              FontsLanguagesPage page,
+                              Profile* profile) {
+  DCHECK(profile);
+  // If there's already an existing fonts and language window, activate it and
+  // switch to the specified page.
+  if (!instance_)
+    instance_ = new FontsLanguagesWindowGtk(profile);
+
+  instance_->ShowTabPage(window, page);
+}
diff --git a/chrome/browser/ui/gtk/options/fonts_page_gtk.cc b/chrome/browser/ui/gtk/options/fonts_page_gtk.cc
new file mode 100644
index 0000000..32a9f3b
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/fonts_page_gtk.cc
@@ -0,0 +1,188 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/fonts_page_gtk.h"
+
+#include <string>
+
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/default_encoding_combo_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/options_layout_gtk.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/font.h"
+
+namespace {
+
+// Make a Gtk font name string from a font family name and pixel size.
+std::string MakeFontName(std::string family_name, int pixel_size) {
+  // The given font might not be available (the default fonts we use are not
+  // installed by default on some distros).  So figure out which font we are
+  // actually falling back to and display that.  (See crbug.com/31381.)
+  string16 actual_family_name = gfx::Font(
+      UTF8ToUTF16(family_name), pixel_size).GetFontName();
+  std::string fontname;
+  // TODO(mattm): We can pass in the size in pixels (px), and the font button
+  // actually honors it, but when you open the selector it interprets it as
+  // points.  See crbug.com/17857
+  base::SStringPrintf(&fontname, "%s, %dpx",
+                      UTF16ToUTF8(actual_family_name).c_str(), pixel_size);
+  return fontname;
+}
+
+}  // namespace
+
+FontsPageGtk::FontsPageGtk(Profile* profile) : OptionsPageBase(profile) {
+  Init();
+}
+
+FontsPageGtk::~FontsPageGtk() {
+}
+
+void FontsPageGtk::Init() {
+  scoped_ptr<OptionsLayoutBuilderGtk>
+    options_builder(OptionsLayoutBuilderGtk::Create());
+  serif_font_button_ = gtk_font_button_new();
+  gtk_font_button_set_use_font(GTK_FONT_BUTTON(serif_font_button_), TRUE);
+  gtk_font_button_set_use_size(GTK_FONT_BUTTON(serif_font_button_), TRUE);
+  g_signal_connect(serif_font_button_, "font-set",
+                   G_CALLBACK(OnSerifFontSetThunk), this);
+
+  sans_font_button_ = gtk_font_button_new();
+  gtk_font_button_set_use_font(GTK_FONT_BUTTON(sans_font_button_), TRUE);
+  gtk_font_button_set_use_size(GTK_FONT_BUTTON(sans_font_button_), TRUE);
+  g_signal_connect(sans_font_button_, "font-set",
+                   G_CALLBACK(OnSansFontSetThunk), this);
+
+  fixed_font_button_ = gtk_font_button_new();
+  gtk_font_button_set_use_font(GTK_FONT_BUTTON(fixed_font_button_), TRUE);
+  gtk_font_button_set_use_size(GTK_FONT_BUTTON(fixed_font_button_), TRUE);
+  g_signal_connect(fixed_font_button_, "font-set",
+                   G_CALLBACK(OnFixedFontSetThunk), this);
+
+  GtkWidget* font_controls = gtk_util::CreateLabeledControlsGroup(NULL,
+      l10n_util::GetStringUTF8(
+          IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SERIF_LABEL).c_str(),
+      serif_font_button_,
+      l10n_util::GetStringUTF8(
+        IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SANS_SERIF_LABEL).c_str(),
+      sans_font_button_,
+      l10n_util::GetStringUTF8(
+        IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_FIXED_WIDTH_LABEL).c_str(),
+      fixed_font_button_,
+      NULL);
+
+  options_builder->AddOptionGroup(l10n_util::GetStringUTF8(
+        IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_FONT_TITLE),
+      font_controls, false);
+
+  InitDefaultEncodingComboBox();
+  std::string encoding_group_description = l10n_util::GetStringUTF8(
+      IDS_FONT_LANGUAGE_SETTING_FONT_DEFAULT_ENCODING_SELECTOR_LABEL);
+  GtkWidget* encoding_controls = gtk_util::CreateLabeledControlsGroup(NULL,
+      encoding_group_description.c_str(),
+      default_encoding_combobox_,
+      NULL);
+  options_builder->AddOptionGroup(l10n_util::GetStringUTF8(
+        IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_ENCODING_TITLE),
+      encoding_controls, false);
+
+  page_ = options_builder->get_page_widget();
+
+  serif_name_.Init(prefs::kWebKitSerifFontFamily, profile()->GetPrefs(), this);
+  sans_serif_name_.Init(prefs::kWebKitSansSerifFontFamily,
+                        profile()->GetPrefs(), this);
+  variable_width_size_.Init(prefs::kWebKitDefaultFontSize,
+                            profile()->GetPrefs(), this);
+
+  fixed_width_name_.Init(prefs::kWebKitFixedFontFamily, profile()->GetPrefs(),
+                         this);
+  fixed_width_size_.Init(prefs::kWebKitDefaultFixedFontSize,
+                         profile()->GetPrefs(), this);
+
+  default_encoding_.Init(prefs::kDefaultCharset, profile()->GetPrefs(), this);
+
+  NotifyPrefChanged(NULL);
+}
+
+void FontsPageGtk::InitDefaultEncodingComboBox() {
+  default_encoding_combobox_ = gtk_combo_box_new_text();
+  g_signal_connect(default_encoding_combobox_, "changed",
+                   G_CALLBACK(OnDefaultEncodingChangedThunk), this);
+  default_encoding_combobox_model_.reset(new DefaultEncodingComboboxModel);
+  for (int i = 0; i < default_encoding_combobox_model_->GetItemCount(); ++i) {
+    gtk_combo_box_append_text(
+        GTK_COMBO_BOX(default_encoding_combobox_),
+        UTF16ToUTF8(default_encoding_combobox_model_->GetItemAt(i)).c_str());
+  }
+}
+
+void FontsPageGtk::NotifyPrefChanged(const std::string* pref_name) {
+  if (!pref_name || *pref_name == prefs::kWebKitSerifFontFamily ||
+      *pref_name == prefs::kWebKitDefaultFontSize) {
+    gtk_font_button_set_font_name(GTK_FONT_BUTTON(serif_font_button_),
+        MakeFontName(serif_name_.GetValue(),
+          variable_width_size_.GetValue()).c_str());
+  }
+  if (!pref_name || *pref_name == prefs::kWebKitSansSerifFontFamily ||
+      *pref_name == prefs::kWebKitDefaultFontSize) {
+    gtk_font_button_set_font_name(GTK_FONT_BUTTON(sans_font_button_),
+        MakeFontName(sans_serif_name_.GetValue(),
+          variable_width_size_.GetValue()).c_str());
+  }
+  if (!pref_name || *pref_name == prefs::kWebKitFixedFontFamily ||
+      *pref_name == prefs::kWebKitDefaultFixedFontSize) {
+    gtk_font_button_set_font_name(GTK_FONT_BUTTON(fixed_font_button_),
+        MakeFontName(fixed_width_name_.GetValue(),
+          fixed_width_size_.GetValue()).c_str());
+  }
+  if (!pref_name || *pref_name == prefs::kDefaultCharset) {
+    gtk_combo_box_set_active(
+        GTK_COMBO_BOX(default_encoding_combobox_),
+        default_encoding_combobox_model_->GetSelectedEncodingIndex(profile()));
+  }
+}
+
+void FontsPageGtk::SetFontsFromButton(StringPrefMember* name_pref,
+                                      IntegerPrefMember* size_pref,
+                                      GtkWidget* font_button) {
+  PangoFontDescription* desc = pango_font_description_from_string(
+      gtk_font_button_get_font_name(GTK_FONT_BUTTON(font_button)));
+  int size = pango_font_description_get_size(desc);
+  name_pref->SetValue(pango_font_description_get_family(desc));
+  size_pref->SetValue(size / PANGO_SCALE);
+  pango_font_description_free(desc);
+  // Reset the button font in px, since the chooser will have set it in points.
+  // Also, both sans and serif share the same size so we need to update them
+  // both.
+  NotifyPrefChanged(NULL);
+}
+
+void FontsPageGtk::OnSerifFontSet(GtkWidget* font_button) {
+  SetFontsFromButton(&serif_name_,
+                     &variable_width_size_,
+                     font_button);
+}
+
+void FontsPageGtk::OnSansFontSet(GtkWidget* font_button) {
+  SetFontsFromButton(&sans_serif_name_,
+                     &variable_width_size_,
+                     font_button);
+}
+
+void FontsPageGtk::OnFixedFontSet(GtkWidget* font_button) {
+  SetFontsFromButton(&fixed_width_name_,
+                     &fixed_width_size_,
+                     font_button);
+}
+
+void FontsPageGtk::OnDefaultEncodingChanged(GtkWidget* combo_box) {
+  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_box));
+  default_encoding_.SetValue(default_encoding_combobox_model_->
+      GetEncodingCharsetByIndex(index));
+}
diff --git a/chrome/browser/ui/gtk/options/fonts_page_gtk.h b/chrome/browser/ui/gtk/options/fonts_page_gtk.h
new file mode 100644
index 0000000..e61d225
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/fonts_page_gtk.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2011 The Chromium 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 fonts page of the fonts & languages options dialog, which contains font
+// family and size settings, as well as the default encoding option.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_FONTS_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_FONTS_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/character_encoding.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class DefaultEncodingComboboxModel;
+
+class FontsPageGtk : public OptionsPageBase {
+ public:
+  explicit FontsPageGtk(Profile* profile);
+  virtual ~FontsPageGtk();
+
+  GtkWidget* get_page_widget() const { return page_; }
+
+ private:
+  void Init();
+  void InitDefaultEncodingComboBox();
+
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  // Retrieve the font selection from the button and save it to the prefs.  Also
+  // ensure the button(s) are displayed in the proper size, as the
+  // GtkFontSelector returns the value in points not pixels.
+  void SetFontsFromButton(StringPrefMember* name_pref,
+                          IntegerPrefMember* size_pref,
+                          GtkWidget* font_button);
+
+  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnSerifFontSet);
+  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnSansFontSet);
+  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnFixedFontSet);
+  CHROMEGTK_CALLBACK_0(FontsPageGtk, void, OnDefaultEncodingChanged);
+
+  // The font chooser widgets
+  GtkWidget* serif_font_button_;
+  GtkWidget* sans_font_button_;
+  GtkWidget* fixed_font_button_;
+
+  // The default encoding combobox widget.
+  GtkWidget* default_encoding_combobox_;
+  scoped_ptr<DefaultEncodingComboboxModel> default_encoding_combobox_model_;
+
+  // The widget containing the options for this page.
+  GtkWidget* page_;
+
+  // Font name preferences.
+  StringPrefMember serif_name_;
+  StringPrefMember sans_serif_name_;
+  StringPrefMember fixed_width_name_;
+
+  // Font size preferences, in pixels.
+  IntegerPrefMember variable_width_size_;
+  IntegerPrefMember fixed_width_size_;
+
+  // Default encoding preference.
+  StringPrefMember default_encoding_;
+
+  DISALLOW_COPY_AND_ASSIGN(FontsPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_FONTS_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/general_page_gtk.cc b/chrome/browser/ui/gtk/options/general_page_gtk.cc
new file mode 100644
index 0000000..0d95420
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/general_page_gtk.cc
@@ -0,0 +1,820 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/general_page_gtk.h"
+
+#include <set>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/custom_home_pages_table_model.h"
+#include "chrome/browser/instant/instant_confirm_dialog.h"
+#include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/keyword_editor_view.h"
+#include "chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h"
+#include "chrome/browser/ui/gtk/options/options_layout_gtk.h"
+#include "chrome/browser/ui/gtk/options/url_picker_dialog_gtk.h"
+#include "chrome/browser/ui/options/show_options_url.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Markup for the text showing the current state of the default browser
+const char kDefaultBrowserLabelMarkup[] = "<span color='#%s'>%s</span>";
+
+// Color of the default browser text when Chromium is the default browser
+const char kDefaultBrowserLabelColor[] = "008700";
+
+// Color of the default browser text when Chromium is not the default browser
+const char kNotDefaultBrowserLabelColor[] = "870000";
+
+// Column ids for |startup_custom_pages_store_|.
+enum {
+  COL_FAVICON,
+  COL_URL,
+  COL_TOOLTIP,
+  COL_COUNT,
+};
+
+// Column ids for |default_search_engines_model_|.
+enum {
+  SEARCH_ENGINES_COL_INDEX,
+  SEARCH_ENGINES_COL_TITLE,
+  SEARCH_ENGINES_COL_COUNT,
+};
+
+bool IsNewTabUIURLString(const GURL& url) {
+  return url == GURL(chrome::kChromeUINewTabURL);
+}
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// GeneralPageGtk, public:
+
+GeneralPageGtk::GeneralPageGtk(Profile* profile)
+    : OptionsPageBase(profile),
+      template_url_model_(NULL),
+      instant_checkbox_(NULL),
+      default_search_initializing_(true),
+      initializing_(true),
+      default_browser_worker_(
+          new ShellIntegration::DefaultBrowserWorker(this)),
+      managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_GENERAL) {
+  scoped_ptr<OptionsLayoutBuilderGtk>
+    options_builder(OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout());
+  page_ = options_builder->get_page_widget();
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(page_, profile));
+
+  options_builder->AddWidget(managed_prefs_banner_.banner_widget(), false);
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_GROUP_NAME),
+      InitStartupGroup(), true);
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_GROUP_NAME),
+      InitHomepageGroup(), false);
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME),
+      InitDefaultSearchGroup(), false);
+#if !defined(OS_CHROMEOS)
+  options_builder->AddOptionGroup(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME),
+      InitDefaultBrowserGroup(), false);
+#endif
+
+  registrar_.Init(profile->GetPrefs());
+  registrar_.Add(prefs::kRestoreOnStartup, this);
+  registrar_.Add(prefs::kURLsToRestoreOnStartup, this);
+
+  new_tab_page_is_home_page_.Init(prefs::kHomePageIsNewTabPage,
+      profile->GetPrefs(), this);
+  homepage_.Init(prefs::kHomePage, profile->GetPrefs(), this);
+  show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this);
+
+  default_browser_policy_.Init(prefs::kDefaultBrowserSettingEnabled,
+                               g_browser_process->local_state(),
+                               this);
+
+  instant_.Init(prefs::kInstantEnabled, profile->GetPrefs(), this);
+
+  // Load initial values
+  NotifyPrefChanged(NULL);
+}
+
+GeneralPageGtk::~GeneralPageGtk() {
+  if (template_url_model_)
+    template_url_model_->RemoveObserver(this);
+
+  default_browser_worker_->ObserverDestroyed();
+}
+
+GtkWindow* GeneralPageGtk::GetWindow() {
+  return GTK_WINDOW(gtk_widget_get_toplevel(page_));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// GeneralPageGtk, OptionsPageBase overrides:
+
+void GeneralPageGtk::NotifyPrefChanged(const std::string* pref_name) {
+  initializing_ = true;
+  PrefService* prefs = profile()->GetPrefs();
+  if (!pref_name ||
+      *pref_name == prefs::kRestoreOnStartup ||
+      *pref_name == prefs::kURLsToRestoreOnStartup) {
+    const SessionStartupPref startup_pref =
+        SessionStartupPref::GetStartupPref(prefs);
+    bool radio_buttons_enabled = !SessionStartupPref::TypeIsManaged(prefs);
+    bool restore_urls_enabled = !SessionStartupPref::URLsAreManaged(prefs);
+    switch (startup_pref.type) {
+    case SessionStartupPref::DEFAULT:
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startup_homepage_radio_),
+                                   TRUE);
+      restore_urls_enabled = false;
+      break;
+
+    case SessionStartupPref::LAST:
+      gtk_toggle_button_set_active(
+          GTK_TOGGLE_BUTTON(startup_last_session_radio_), TRUE);
+      restore_urls_enabled = false;
+      break;
+
+    case SessionStartupPref::URLS:
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startup_custom_radio_),
+                                   TRUE);
+      break;
+    }
+    gtk_widget_set_sensitive(startup_homepage_radio_, radio_buttons_enabled);
+    gtk_widget_set_sensitive(startup_last_session_radio_,
+                             radio_buttons_enabled);
+    gtk_widget_set_sensitive(startup_custom_radio_, radio_buttons_enabled);
+    EnableCustomHomepagesControls(restore_urls_enabled);
+    startup_custom_pages_table_model_->SetURLs(startup_pref.urls);
+  }
+
+  if (!pref_name ||
+      *pref_name == prefs::kHomePageIsNewTabPage ||
+      *pref_name == prefs::kHomePage) {
+    bool new_tab_page_is_home_page_managed =
+        new_tab_page_is_home_page_.IsManaged();
+    bool homepage_managed = homepage_.IsManaged();
+    bool homepage_url_is_new_tab =
+        IsNewTabUIURLString(GURL(homepage_.GetValue()));
+    bool homepage_is_new_tab = homepage_url_is_new_tab ||
+        new_tab_page_is_home_page_.GetValue();
+    // If HomepageIsNewTab is managed or
+    // Homepage is 'chrome://newtab' and managed, disable the radios.
+    bool disable_homepage_choice_buttons =
+        new_tab_page_is_home_page_managed ||
+        (homepage_managed && homepage_url_is_new_tab);
+    if (!homepage_url_is_new_tab) {
+      gtk_entry_set_text(GTK_ENTRY(homepage_use_url_entry_),
+                         homepage_.GetValue().c_str());
+    }
+    UpdateHomepageIsNewTabRadio(
+        homepage_is_new_tab, !disable_homepage_choice_buttons);
+    EnableHomepageURLField(!homepage_is_new_tab);
+  }
+
+  if (!pref_name || *pref_name == prefs::kShowHomeButton) {
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(homepage_show_home_button_checkbox_),
+        show_home_button_.GetValue());
+    gtk_widget_set_sensitive(
+        homepage_show_home_button_checkbox_,
+        !show_home_button_.IsManaged());
+  }
+
+  if ((!pref_name || *pref_name == prefs::kInstantEnabled) &&
+      instant_checkbox_) {
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(instant_checkbox_), instant_.GetValue());
+  }
+
+  if (!pref_name || *pref_name == prefs::kDefaultBrowserSettingEnabled) {
+    // If the option is managed the UI is uncondionally disabled otherwise we
+    // restart the standard button enabling logic.
+    if (default_browser_policy_.IsManaged())
+      gtk_widget_set_sensitive(default_browser_use_as_default_button_, false);
+    else
+      default_browser_worker_->StartCheckDefaultBrowser();
+  }
+
+  initializing_ = false;
+}
+
+void GeneralPageGtk::HighlightGroup(OptionsGroup highlight_group) {
+  // TODO(mattm): implement group highlighting
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// GeneralPageGtk, private:
+
+GtkWidget* GeneralPageGtk::InitStartupGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  startup_homepage_radio_ = gtk_radio_button_new_with_label(NULL,
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB).c_str());
+  g_signal_connect(startup_homepage_radio_, "toggled",
+                   G_CALLBACK(OnStartupRadioToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), startup_homepage_radio_, FALSE, FALSE, 0);
+
+  startup_last_session_radio_ = gtk_radio_button_new_with_label_from_widget(
+      GTK_RADIO_BUTTON(startup_homepage_radio_),
+      l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION).c_str());
+  g_signal_connect(startup_last_session_radio_, "toggled",
+                   G_CALLBACK(OnStartupRadioToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), startup_last_session_radio_,
+                     FALSE, FALSE, 0);
+
+  startup_custom_radio_ = gtk_radio_button_new_with_label_from_widget(
+      GTK_RADIO_BUTTON(startup_homepage_radio_),
+      l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_SHOW_PAGES).c_str());
+  g_signal_connect(startup_custom_radio_, "toggled",
+                   G_CALLBACK(OnStartupRadioToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(vbox), startup_custom_radio_, FALSE, FALSE, 0);
+
+  GtkWidget* url_list_container = gtk_hbox_new(FALSE,
+                                               gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(vbox), url_list_container, TRUE, TRUE, 0);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(url_list_container),
+                    scroll_window);
+  startup_custom_pages_store_ = gtk_list_store_new(COL_COUNT,
+                                                   GDK_TYPE_PIXBUF,
+                                                   G_TYPE_STRING,
+                                                   G_TYPE_STRING);
+  startup_custom_pages_tree_ = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(startup_custom_pages_store_));
+  gtk_container_add(GTK_CONTAINER(scroll_window), startup_custom_pages_tree_);
+
+  // Release |startup_custom_pages_store_| so that |startup_custom_pages_tree_|
+  // owns the model.
+  g_object_unref(startup_custom_pages_store_);
+
+  gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(startup_custom_pages_tree_),
+                                   COL_TOOLTIP);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(startup_custom_pages_tree_),
+                                    FALSE);
+  GtkTreeViewColumn* column = gtk_tree_view_column_new();
+  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(column, renderer, FALSE);
+  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
+  renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_URL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(startup_custom_pages_tree_),
+                              column);
+  startup_custom_pages_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(startup_custom_pages_tree_));
+  gtk_tree_selection_set_mode(startup_custom_pages_selection_,
+                              GTK_SELECTION_MULTIPLE);
+  g_signal_connect(startup_custom_pages_selection_, "changed",
+                   G_CALLBACK(OnStartupPagesSelectionChangedThunk), this);
+
+  startup_custom_pages_table_model_.reset(
+      new CustomHomePagesTableModel(profile()));
+  startup_custom_pages_table_adapter_.reset(
+      new gtk_tree::TableAdapter(this, startup_custom_pages_store_,
+                                 startup_custom_pages_table_model_.get()));
+
+  GtkWidget* url_list_buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_end(GTK_BOX(url_list_container), url_list_buttons,
+                   FALSE, FALSE, 0);
+
+  startup_add_custom_page_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_ADD_BUTTON)).c_str());
+  g_signal_connect(startup_add_custom_page_button_, "clicked",
+                   G_CALLBACK(OnStartupAddCustomPageClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(url_list_buttons), startup_add_custom_page_button_,
+                     FALSE, FALSE, 0);
+  startup_remove_custom_page_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+        l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_REMOVE_BUTTON)).c_str());
+  g_signal_connect(startup_remove_custom_page_button_, "clicked",
+                   G_CALLBACK(OnStartupRemoveCustomPageClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(url_list_buttons),
+                     startup_remove_custom_page_button_, FALSE, FALSE, 0);
+  startup_use_current_page_button_ = gtk_button_new_with_mnemonic(
+      gfx::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_USE_CURRENT)).c_str());
+  g_signal_connect(startup_use_current_page_button_, "clicked",
+                   G_CALLBACK(OnStartupUseCurrentPageClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(url_list_buttons),
+                     startup_use_current_page_button_, FALSE, FALSE, 0);
+
+  return vbox;
+}
+
+GtkWidget* GeneralPageGtk::InitHomepageGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  homepage_use_newtab_radio_ = gtk_radio_button_new_with_label(NULL,
+      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_USE_NEWTAB).c_str());
+  g_signal_connect(homepage_use_newtab_radio_, "toggled",
+                   G_CALLBACK(OnNewTabIsHomePageToggledThunk), this);
+  gtk_container_add(GTK_CONTAINER(vbox), homepage_use_newtab_radio_);
+
+  GtkWidget* homepage_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  gtk_container_add(GTK_CONTAINER(vbox), homepage_hbox);
+
+  homepage_use_url_radio_ = gtk_radio_button_new_with_label_from_widget(
+      GTK_RADIO_BUTTON(homepage_use_newtab_radio_),
+      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_USE_URL).c_str());
+  g_signal_connect(homepage_use_url_radio_, "toggled",
+                   G_CALLBACK(OnNewTabIsHomePageToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(homepage_hbox), homepage_use_url_radio_,
+                     FALSE, FALSE, 0);
+
+  homepage_use_url_entry_ = gtk_entry_new();
+  g_signal_connect(homepage_use_url_entry_, "changed",
+                   G_CALLBACK(OnHomepageUseUrlEntryChangedThunk), this);
+  gtk_box_pack_start(GTK_BOX(homepage_hbox), homepage_use_url_entry_,
+                     TRUE, TRUE, 0);
+
+  homepage_show_home_button_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_SHOW_BUTTON).c_str());
+  g_signal_connect(homepage_show_home_button_checkbox_, "toggled",
+                   G_CALLBACK(OnShowHomeButtonToggledThunk), this);
+  gtk_container_add(GTK_CONTAINER(vbox), homepage_show_home_button_checkbox_);
+
+  return vbox;
+}
+
+GtkWidget* GeneralPageGtk::InitDefaultSearchGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  GtkWidget* search_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(vbox), search_hbox, FALSE, FALSE, 0);
+
+  default_search_engines_model_ = gtk_list_store_new(SEARCH_ENGINES_COL_COUNT,
+                                                     G_TYPE_UINT,
+                                                     G_TYPE_STRING);
+  default_search_engine_combobox_ = gtk_combo_box_new_with_model(
+      GTK_TREE_MODEL(default_search_engines_model_));
+  g_object_unref(default_search_engines_model_);
+  g_signal_connect(default_search_engine_combobox_, "changed",
+                   G_CALLBACK(OnDefaultSearchEngineChangedThunk), this);
+  gtk_container_add(GTK_CONTAINER(search_hbox),
+                    default_search_engine_combobox_);
+  accessible_widget_helper_->SetWidgetName(
+      default_search_engine_combobox_, IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME);
+
+  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(default_search_engine_combobox_),
+                             renderer, TRUE);
+  gtk_cell_layout_set_attributes(
+      GTK_CELL_LAYOUT(default_search_engine_combobox_), renderer,
+      "text", SEARCH_ENGINES_COL_TITLE,
+      NULL);
+
+  template_url_model_ = profile()->GetTemplateURLModel();
+  if (template_url_model_) {
+    template_url_model_->Load();
+    template_url_model_->AddObserver(this);
+  }
+  OnTemplateURLModelChanged();
+
+  default_search_manage_engines_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(
+          IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES_LINK).c_str());
+  g_signal_connect(default_search_manage_engines_button_, "clicked",
+                   G_CALLBACK(OnDefaultSearchManageEnginesClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(search_hbox),
+                     default_search_manage_engines_button_, FALSE, FALSE, 0);
+
+  // When the instant lab is on, add some options for instant. We want the
+  // warning text and link to align with the pref's checkbox's label.
+  // Need a new vbox as we don't want any spacing between these labels.
+  GtkWidget* instant_vbox = gtk_vbox_new(FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), instant_vbox, FALSE, FALSE, 0);
+
+  instant_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_INSTANT_PREF).c_str());
+  g_signal_connect(instant_checkbox_, "toggled",
+                   G_CALLBACK(OnInstantToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(instant_vbox), instant_checkbox_, FALSE, FALSE, 0);
+
+  // Relies on knowledge of GTK+ internals to find the checkbox's label child
+  // and then make the indent below match its vertical spacing.
+  GtkWidget* instant_label = gtk_bin_get_child(GTK_BIN(instant_checkbox_));
+  if (instant_label && GTK_IS_LABEL(instant_label)) {
+    g_signal_connect(instant_label, "size-allocate",
+                     G_CALLBACK(OnInstantLabelSizeAllocateThunk), this);
+  }
+
+  instant_indent_ = gtk_fixed_new();
+  GtkWidget* explanation_box = gtk_hbox_new(FALSE, 0);
+  GtkWidget* explanation = gtk_label_new((
+      l10n_util::GetStringUTF8(IDS_INSTANT_PREF_WARNING) + " ").c_str());
+  GtkWidget* learn_more_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
+  g_signal_connect(learn_more_link, "clicked",
+                   G_CALLBACK(OnSearchLearnMoreClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(explanation_box), instant_indent_,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(explanation_box), explanation,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(explanation_box), learn_more_link,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(instant_vbox), explanation_box, FALSE, FALSE, 0);
+
+  return vbox;
+}
+
+GtkWidget* GeneralPageGtk::InitDefaultBrowserGroup() {
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  // TODO(mattm): the label should be created with a text like "checking for
+  // default" to be displayed while we wait for the check to complete.
+  default_browser_status_label_ = gtk_label_new(NULL);
+  gtk_box_pack_start(GTK_BOX(vbox), default_browser_status_label_,
+                     FALSE, FALSE, 0);
+
+  default_browser_use_as_default_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT,
+          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
+  g_signal_connect(default_browser_use_as_default_button_, "clicked",
+                   G_CALLBACK(OnBrowserUseAsDefaultClickedThunk), this);
+
+  gtk_box_pack_start(GTK_BOX(vbox), default_browser_use_as_default_button_,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* vbox_alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
+  gtk_container_add(GTK_CONTAINER(vbox_alignment), vbox);
+
+  default_browser_worker_->StartCheckDefaultBrowser();
+
+  return vbox_alignment;
+}
+
+void GeneralPageGtk::OnStartupRadioToggled(GtkWidget* toggle_button) {
+  if (initializing_)
+    return;
+
+  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
+    // When selecting a radio button, we get two signals (one for the old radio
+    // being toggled off, one for the new one being toggled on.)  Ignore the
+    // signal for toggling off the old button.
+    return;
+  }
+  SaveStartupPref();
+  if (toggle_button == startup_homepage_radio_) {
+    UserMetricsRecordAction(UserMetricsAction("Options_Startup_Homepage"),
+                            profile()->GetPrefs());
+  } else if (toggle_button == startup_last_session_radio_) {
+    UserMetricsRecordAction(UserMetricsAction("Options_Startup_LastSession"),
+                            profile()->GetPrefs());
+  } else if (toggle_button == startup_custom_radio_) {
+    UserMetricsRecordAction(UserMetricsAction("Options_Startup_Custom"),
+                            profile()->GetPrefs());
+  }
+}
+
+void GeneralPageGtk::OnStartupAddCustomPageClicked(GtkWidget* button) {
+  new UrlPickerDialogGtk(
+      NewCallback(this, &GeneralPageGtk::OnAddCustomUrl),
+      profile(),
+      GetWindow());
+}
+
+void GeneralPageGtk::OnStartupRemoveCustomPageClicked(GtkWidget* button) {
+  RemoveSelectedCustomUrls();
+}
+
+void GeneralPageGtk::OnStartupUseCurrentPageClicked(GtkWidget* button) {
+  SetCustomUrlListFromCurrentPages();
+}
+
+void GeneralPageGtk::OnStartupPagesSelectionChanged(
+    GtkTreeSelection* selection) {
+  EnableCustomHomepagesControls(true);
+}
+
+void GeneralPageGtk::OnNewTabIsHomePageToggled(GtkWidget* toggle_button) {
+  if (initializing_)
+    return;
+  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) {
+    // Ignore the signal for toggling off the old button.
+    return;
+  }
+  if (toggle_button == homepage_use_newtab_radio_) {
+    UserMetricsRecordAction(UserMetricsAction("Options_Homepage_UseNewTab"),
+                            profile()->GetPrefs());
+    UpdateHomepagePrefs();
+    EnableHomepageURLField(false);
+  } else if (toggle_button == homepage_use_url_radio_) {
+    UserMetricsRecordAction(UserMetricsAction("Options_Homepage_UseURL"),
+                            profile()->GetPrefs());
+    UpdateHomepagePrefs();
+    EnableHomepageURLField(true);
+  }
+}
+
+void GeneralPageGtk::OnHomepageUseUrlEntryChanged(GtkWidget* editable) {
+  if (initializing_)
+    return;
+  UpdateHomepagePrefs();
+}
+
+void GeneralPageGtk::OnShowHomeButtonToggled(GtkWidget* toggle_button) {
+  if (initializing_)
+    return;
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button));
+  show_home_button_.SetValue(enabled);
+  if (enabled) {
+    UserMetricsRecordAction(
+        UserMetricsAction("Options_Homepage_ShowHomeButton"),
+        profile()->GetPrefs());
+  } else {
+    UserMetricsRecordAction(
+        UserMetricsAction("Options_Homepage_HideHomeButton"),
+        profile()->GetPrefs());
+  }
+}
+
+void GeneralPageGtk::OnInstantToggled(GtkWidget* toggle_button) {
+  if (initializing_)
+    return;
+
+  bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button));
+
+  if (enabled) {
+    if (!instant_.GetValue())
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(instant_checkbox_), false);
+    browser::ShowInstantConfirmDialogIfNecessary(GetWindow(), profile());
+  } else {
+    InstantController::Disable(profile());
+  }
+
+  // TODO(estade): UMA?
+}
+
+void GeneralPageGtk::OnDefaultSearchEngineChanged(GtkWidget* combo_box) {
+  if (default_search_initializing_)
+    return;
+  SetDefaultSearchEngineFromComboBox();
+}
+
+void GeneralPageGtk::OnDefaultSearchManageEnginesClicked(GtkWidget* button) {
+  KeywordEditorView::Show(profile());
+}
+
+void GeneralPageGtk::OnBrowserUseAsDefaultClicked(GtkWidget* button) {
+  default_browser_worker_->StartSetAsDefaultBrowser();
+  // If the user made Chrome the default browser, then he/she arguably wants
+  // to be notified when that changes.
+  profile()->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, true);
+  UserMetricsRecordAction(UserMetricsAction("Options_SetAsDefaultBrowser"),
+                          profile()->GetPrefs());
+}
+
+void GeneralPageGtk::SaveStartupPref() {
+  SessionStartupPref pref;
+
+  if (gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(startup_last_session_radio_))) {
+    pref.type = SessionStartupPref::LAST;
+  } else if (gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(startup_custom_radio_))) {
+    pref.type = SessionStartupPref::URLS;
+  }
+
+  pref.urls = startup_custom_pages_table_model_->GetURLs();
+
+  SessionStartupPref::SetStartupPref(profile()->GetPrefs(), pref);
+}
+
+void GeneralPageGtk::SetColumnValues(int row, GtkTreeIter* iter) {
+  SkBitmap bitmap = startup_custom_pages_table_model_->GetIcon(row);
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
+  string16 text = startup_custom_pages_table_model_->GetText(row, 0);
+  std::string tooltip =
+      UTF16ToUTF8(startup_custom_pages_table_model_->GetTooltip(row));
+  gchar* escaped_tooltip = g_markup_escape_text(tooltip.c_str(),
+                                                tooltip.size());
+  gtk_list_store_set(startup_custom_pages_store_, iter,
+                     COL_FAVICON, pixbuf,
+                     COL_URL, UTF16ToUTF8(text).c_str(),
+                     COL_TOOLTIP, escaped_tooltip,
+                     -1);
+  g_object_unref(pixbuf);
+  g_free(escaped_tooltip);
+}
+
+void GeneralPageGtk::SetCustomUrlListFromCurrentPages() {
+  startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
+
+  SaveStartupPref();
+}
+
+void GeneralPageGtk::OnAddCustomUrl(const GURL& url) {
+  // The restore URLs policy might have become managed while the dialog is
+  // displayed.  While the model makes sure that no changes are made in this
+  // condition, we should still avoid the rest of the method otherwise
+  // graphic elements will become enabled.
+  if (SessionStartupPref::URLsAreManaged(profile()->GetPrefs()))
+    return;
+  std::set<int> indices;
+  gtk_tree::GetSelectedIndices(startup_custom_pages_selection_, &indices);
+  int index;
+  if (indices.empty())
+    index = startup_custom_pages_table_model_->RowCount();
+  else
+    index = *indices.begin() + 1;
+  startup_custom_pages_table_model_->Add(index, url);
+
+  SaveStartupPref();
+
+  gtk_tree::SelectAndFocusRowNum(index,
+                                 GTK_TREE_VIEW(startup_custom_pages_tree_));
+}
+
+void GeneralPageGtk::RemoveSelectedCustomUrls() {
+  std::set<int> indices;
+  gtk_tree::GetSelectedIndices(startup_custom_pages_selection_, &indices);
+
+  int selected_row = 0;
+  for (std::set<int>::reverse_iterator i = indices.rbegin();
+       i != indices.rend(); ++i) {
+    startup_custom_pages_table_model_->Remove(*i);
+    selected_row = *i;
+  }
+
+  SaveStartupPref();
+
+  // Select the next row after the last row deleted, or the above item if the
+  // latest item was deleted or nothing when the table doesn't have any items.
+  int row_count = startup_custom_pages_table_model_->RowCount();
+  if (selected_row >= row_count)
+    selected_row = row_count - 1;
+  if (selected_row >= 0) {
+    gtk_tree::SelectAndFocusRowNum(selected_row,
+                                   GTK_TREE_VIEW(startup_custom_pages_tree_));
+  }
+}
+
+void GeneralPageGtk::OnTemplateURLModelChanged() {
+  if (!template_url_model_ || !template_url_model_->loaded()) {
+    EnableDefaultSearchEngineComboBox(false);
+    return;
+  }
+  default_search_initializing_ = true;
+  gtk_list_store_clear(default_search_engines_model_);
+  const TemplateURL* default_search_provider =
+      template_url_model_->GetDefaultSearchProvider();
+  std::vector<const TemplateURL*> model_urls =
+      template_url_model_->GetTemplateURLs();
+  bool populated = false;
+  for (size_t i = 0; i < model_urls.size(); ++i) {
+    if (!model_urls[i]->ShowInDefaultList())
+      continue;
+    populated = true;
+    GtkTreeIter iter;
+    gtk_list_store_append(default_search_engines_model_, &iter);
+    gtk_list_store_set(
+        default_search_engines_model_, &iter,
+        SEARCH_ENGINES_COL_INDEX, i,
+        SEARCH_ENGINES_COL_TITLE,
+        UTF16ToUTF8(model_urls[i]->short_name()).c_str(),
+        -1);
+    if (model_urls[i] == default_search_provider) {
+      gtk_combo_box_set_active_iter(
+          GTK_COMBO_BOX(default_search_engine_combobox_), &iter);
+    }
+  }
+  EnableDefaultSearchEngineComboBox(populated &&
+      !template_url_model_->is_default_search_managed());
+  default_search_initializing_ = false;
+}
+
+void GeneralPageGtk::SetDefaultSearchEngineFromComboBox() {
+  GtkTreeIter iter;
+  if (!gtk_combo_box_get_active_iter(
+      GTK_COMBO_BOX(default_search_engine_combobox_), &iter)) {
+    return;
+  }
+  guint index;
+  gtk_tree_model_get(GTK_TREE_MODEL(default_search_engines_model_), &iter,
+                     SEARCH_ENGINES_COL_INDEX, &index,
+                     -1);
+  std::vector<const TemplateURL*> model_urls =
+      template_url_model_->GetTemplateURLs();
+  if (index < model_urls.size())
+    template_url_model_->SetDefaultSearchProvider(model_urls[index]);
+  else
+    NOTREACHED();
+}
+
+void GeneralPageGtk::EnableDefaultSearchEngineComboBox(bool enable) {
+  gtk_widget_set_sensitive(default_search_engine_combobox_, enable);
+}
+
+void GeneralPageGtk::UpdateHomepagePrefs() {
+  const GURL& homepage = URLFixerUpper::FixupURL(
+      gtk_entry_get_text(GTK_ENTRY(homepage_use_url_entry_)), std::string());
+  bool new_tab_page_is_home_page =
+    gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(homepage_use_newtab_radio_));
+  if (IsNewTabUIURLString(homepage)) {
+    new_tab_page_is_home_page = true;
+    homepage_.SetValueIfNotManaged(std::string());
+  } else if (!homepage.is_valid()) {
+    new_tab_page_is_home_page = true;
+    if (!homepage.has_host())
+      homepage_.SetValueIfNotManaged(std::string());
+  } else {
+    homepage_.SetValueIfNotManaged(homepage.spec());
+  }
+  new_tab_page_is_home_page_.SetValueIfNotManaged(new_tab_page_is_home_page);
+}
+
+void GeneralPageGtk::UpdateHomepageIsNewTabRadio(bool homepage_is_new_tab,
+                                                 bool enabled) {
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(homepage_use_newtab_radio_),
+                               homepage_is_new_tab);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(homepage_use_url_radio_),
+                               !homepage_is_new_tab);
+  gtk_widget_set_sensitive(homepage_use_newtab_radio_, enabled);
+  gtk_widget_set_sensitive(homepage_use_url_radio_, enabled);
+}
+
+void GeneralPageGtk::EnableHomepageURLField(bool enabled) {
+  if (homepage_.IsManaged())
+    enabled = false;
+  gtk_widget_set_sensitive(homepage_use_url_entry_, enabled);
+}
+
+void GeneralPageGtk::EnableCustomHomepagesControls(bool enable) {
+  gtk_widget_set_sensitive(startup_add_custom_page_button_, enable);
+  gtk_widget_set_sensitive(startup_remove_custom_page_button_,
+      enable &&
+      gtk_tree_selection_count_selected_rows(startup_custom_pages_selection_));
+  gtk_widget_set_sensitive(startup_use_current_page_button_, enable);
+  gtk_widget_set_sensitive(startup_custom_pages_tree_, enable);
+}
+
+void GeneralPageGtk::SetDefaultBrowserUIState(
+    ShellIntegration::DefaultBrowserUIState state) {
+  const char* color = NULL;
+  std::string text;
+  if (state == ShellIntegration::STATE_IS_DEFAULT) {
+    color = kDefaultBrowserLabelColor;
+    text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_DEFAULT,
+        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  } else if (state == ShellIntegration::STATE_NOT_DEFAULT) {
+    color = kNotDefaultBrowserLabelColor;
+    text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT,
+        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  } else if (state == ShellIntegration::STATE_UNKNOWN) {
+    color = kNotDefaultBrowserLabelColor;
+    text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
+        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  }
+  if (color) {
+    char* markup = g_markup_printf_escaped(kDefaultBrowserLabelMarkup,
+                                           color, text.c_str());
+    gtk_label_set_markup(GTK_LABEL(default_browser_status_label_), markup);
+    g_free(markup);
+  }
+
+  gtk_widget_set_sensitive(default_browser_use_as_default_button_,
+                           state == ShellIntegration::STATE_NOT_DEFAULT &&
+                               !default_browser_policy_.IsManaged());
+}
+
+void GeneralPageGtk::OnInstantLabelSizeAllocate(GtkWidget* sender,
+                                                GtkAllocation* allocation) {
+  int desired_width = allocation->x - sender->parent->allocation.x;
+  GtkRequisition req;
+  gtk_widget_size_request(instant_indent_, &req);
+  if (req.width != desired_width)
+    gtk_widget_set_size_request(instant_indent_, desired_width, -1);
+}
+
+void GeneralPageGtk::OnSearchLearnMoreClicked(GtkWidget* sender) {
+  browser::ShowOptionsURL(profile(), browser::InstantLearnMoreURL());
+}
diff --git a/chrome/browser/ui/gtk/options/general_page_gtk.h b/chrome/browser/ui/gtk/options/general_page_gtk.h
new file mode 100644
index 0000000..0584486
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/general_page_gtk.h
@@ -0,0 +1,180 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_GENERAL_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_GENERAL_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/search_engines/template_url_model_observer.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "googleurl/src/gurl.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class AccessibleWidgetHelper;
+class CustomHomePagesTableModel;
+class Profile;
+class TemplateURLModel;
+
+class GeneralPageGtk : public OptionsPageBase,
+                       public TemplateURLModelObserver,
+                       public ShellIntegration::DefaultBrowserObserver,
+                       public gtk_tree::TableAdapter::Delegate {
+ public:
+  explicit GeneralPageGtk(Profile* profile);
+  ~GeneralPageGtk();
+
+  GtkWidget* get_page_widget() const { return page_; }
+
+ private:
+  GtkWindow* GetWindow();
+
+  // Overridden from OptionsPageBase
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+  virtual void HighlightGroup(OptionsGroup highlight_group);
+
+  // Initialize the option group widgets, return their container
+  GtkWidget* InitStartupGroup();
+  GtkWidget* InitHomepageGroup();
+  GtkWidget* InitDefaultSearchGroup();
+  GtkWidget* InitDefaultBrowserGroup();
+
+  // Saves the startup preference from the values in the ui
+  void SaveStartupPref();
+
+  // Set the custom url list using the pages currently open
+  void SetCustomUrlListFromCurrentPages();
+
+  // Callback from UrlPickerDialogGtk, for adding custom urls manually.
+  // If a single row in the list is selected, the new url will be inserted
+  // before that row.  Otherwise the new row will be added to the end.
+  void OnAddCustomUrl(const GURL& url);
+
+  // Removes urls that are currently selected
+  void RemoveSelectedCustomUrls();
+
+  // Overridden from TemplateURLModelObserver.
+  // Populates the default search engine combobox from the model.
+  virtual void OnTemplateURLModelChanged();
+
+  // Set the default search engine pref to the combo box active item.
+  void SetDefaultSearchEngineFromComboBox();
+
+  // Set the default search engine combo box state.
+  void EnableDefaultSearchEngineComboBox(bool enable);
+
+  // Copies the home page preferences from the gui controls to
+  // kNewTabPageIsHomePage and kHomePage. If an empty or null-host
+  // URL is specified, then we revert to using NewTab page as the Homepage.
+  void UpdateHomepagePrefs();
+
+  // Enables or disables the field for entering a custom homepage URL.
+  void EnableHomepageURLField(bool enabled);
+
+  // Sets the state and enables/disables the radio buttons that control
+  // if the home page is the new tab page.
+  void UpdateHomepageIsNewTabRadio(bool homepage_is_new_tab, bool enabled);
+
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupRadioToggled);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupAddCustomPageClicked);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupRemoveCustomPageClicked);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnStartupUseCurrentPageClicked);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnNewTabIsHomePageToggled);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnHomepageUseUrlEntryChanged);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnShowHomeButtonToggled);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnDefaultSearchEngineChanged);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void,
+                       OnDefaultSearchManageEnginesClicked);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnInstantToggled);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnBrowserUseAsDefaultClicked);
+  CHROMEGTK_CALLBACK_1(GeneralPageGtk, void, OnInstantLabelSizeAllocate,
+                       GtkAllocation*);
+  CHROMEGTK_CALLBACK_0(GeneralPageGtk, void, OnSearchLearnMoreClicked);
+
+  CHROMEG_CALLBACK_0(GeneralPageGtk, void, OnStartupPagesSelectionChanged,
+                     GtkTreeSelection*);
+
+  // Enables/Disables the controls associated with the custom start pages
+  // option if that preference is not selected.
+  void EnableCustomHomepagesControls(bool enable);
+
+  // ShellIntegration::DefaultBrowserObserver implementation.
+  virtual void SetDefaultBrowserUIState(
+      ShellIntegration::DefaultBrowserUIState state);
+
+  // gtk_tree::TableAdapter::Delegate implementation.
+  virtual void SetColumnValues(int row, GtkTreeIter* iter);
+
+  // Widgets of the startup group
+  GtkWidget* startup_homepage_radio_;
+  GtkWidget* startup_last_session_radio_;
+  GtkWidget* startup_custom_radio_;
+  GtkWidget* startup_custom_pages_tree_;
+  GtkListStore* startup_custom_pages_store_;
+  GtkTreeSelection* startup_custom_pages_selection_;
+  GtkWidget* startup_add_custom_page_button_;
+  GtkWidget* startup_remove_custom_page_button_;
+  GtkWidget* startup_use_current_page_button_;
+
+  // The model for |startup_custom_pages_store_|.
+  scoped_ptr<CustomHomePagesTableModel> startup_custom_pages_table_model_;
+  scoped_ptr<gtk_tree::TableAdapter> startup_custom_pages_table_adapter_;
+
+  // Widgets and prefs of the homepage group
+  GtkWidget* homepage_use_newtab_radio_;
+  GtkWidget* homepage_use_url_radio_;
+  GtkWidget* homepage_use_url_entry_;
+  GtkWidget* homepage_show_home_button_checkbox_;
+  BooleanPrefMember new_tab_page_is_home_page_;
+  StringPrefMember homepage_;
+  BooleanPrefMember show_home_button_;
+
+  // Widgets and data of the default search group
+  GtkWidget* default_search_engine_combobox_;
+  GtkListStore* default_search_engines_model_;
+  GtkWidget* default_search_manage_engines_button_;
+  TemplateURLModel* template_url_model_;
+  GtkWidget* instant_checkbox_;
+  // This widget acts as the indent for the instant warning label.
+  GtkWidget* instant_indent_;
+  BooleanPrefMember instant_;
+
+  // Widgets of the default browser group
+  GtkWidget* default_browser_status_label_;
+  GtkWidget* default_browser_use_as_default_button_;
+  BooleanPrefMember default_browser_policy_;
+
+  // The parent GtkTable widget
+  GtkWidget* page_;
+
+  // Flag to ignore gtk callbacks while we are populating default search urls.
+  bool default_search_initializing_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool initializing_;
+
+  // The helper object that performs default browser set/check tasks.
+  scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  // Tracks managed preference warning banner state.
+  ManagedPrefsBannerGtk managed_prefs_banner_;
+
+  PrefChangeRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(GeneralPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_GENERAL_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/languages_page_gtk.cc b/chrome/browser/ui/gtk/options/languages_page_gtk.cc
new file mode 100644
index 0000000..77c6929
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/languages_page_gtk.cc
@@ -0,0 +1,450 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/languages_page_gtk.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/language_combobox_model.h"
+#include "chrome/browser/language_order_table_model.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/spellcheck_common.h"
+#include "grit/generated_resources.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+const int kWrapWidth = 475;
+
+GtkWidget* NewComboboxFromModel(ui::ComboboxModel* model) {
+  GtkWidget* combobox = gtk_combo_box_new_text();
+  int count = model->GetItemCount();
+  for (int i = 0; i < count; ++i)
+    gtk_combo_box_append_text(GTK_COMBO_BOX(combobox),
+                              UTF16ToUTF8(model->GetItemAt(i)).c_str());
+  return combobox;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AddLanguageDialog
+
+class AddLanguageDialog {
+ public:
+  AddLanguageDialog(Profile* profile, LanguagesPageGtk* delegate);
+  virtual ~AddLanguageDialog() {}
+
+ private:
+  // Callback for dialog buttons.
+  CHROMEGTK_CALLBACK_1(AddLanguageDialog, void, OnResponse, int);
+
+  // Callback for window destruction.
+  CHROMEGTK_CALLBACK_0(AddLanguageDialog, void, OnWindowDestroy);
+
+  // The dialog window.
+  GtkWidget* dialog_;
+
+  // The language chooser combobox.
+  GtkWidget* combobox_;
+  scoped_ptr<LanguageComboboxModel> accept_language_combobox_model_;
+
+  // Used for call back to LanguagePageGtk that language has been selected.
+  LanguagesPageGtk* language_delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(AddLanguageDialog);
+};
+
+AddLanguageDialog::AddLanguageDialog(Profile* profile,
+                                     LanguagesPageGtk* delegate)
+    : language_delegate_(delegate) {
+  GtkWindow* parent = GTK_WINDOW(
+      gtk_widget_get_toplevel(delegate->get_page_widget()));
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(
+          IDS_FONT_LANGUAGE_SETTING_LANGUAGES_TAB_TITLE).c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_CANCEL,
+      GTK_STOCK_ADD,
+      GTK_RESPONSE_OK,
+      NULL);
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  const std::string app_locale = g_browser_process->GetApplicationLocale();
+  std::vector<std::string> locale_codes;
+  l10n_util::GetAcceptLanguagesForLocale(app_locale, &locale_codes);
+  accept_language_combobox_model_.reset(
+      new LanguageComboboxModel(profile, locale_codes));
+  combobox_ = NewComboboxFromModel(accept_language_combobox_model_.get());
+  gtk_combo_box_set_active(GTK_COMBO_BOX(combobox_), 0);
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), combobox_);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+
+  gtk_util::ShowDialog(dialog_);
+}
+
+void AddLanguageDialog::OnResponse(GtkWidget* dialog, int response_id) {
+  if (response_id == GTK_RESPONSE_OK) {
+    int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox_));
+    language_delegate_->OnAddLanguage(
+        accept_language_combobox_model_->GetLocaleFromIndex(selected));
+  }
+  gtk_widget_destroy(dialog_);
+}
+
+void AddLanguageDialog::OnWindowDestroy(GtkWidget* widget) {
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// LanguagesPageGtk
+
+LanguagesPageGtk::LanguagesPageGtk(Profile* profile)
+    : OptionsPageBase(profile),
+      enable_autospellcorrect_checkbox_(NULL),
+      initializing_(true) {
+  Init();
+}
+
+LanguagesPageGtk::~LanguagesPageGtk() {
+}
+
+void LanguagesPageGtk::Init() {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(page_),
+                                 gtk_util::kContentAreaBorder);
+
+  // Languages order controls.
+  GtkWidget* languages_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(page_), languages_vbox,
+                     TRUE, TRUE, 0);
+
+  GtkWidget* languages_instructions_label = gtk_label_new(
+      l10n_util::GetStringUTF8(
+          IDS_FONT_LANGUAGE_SETTING_LANGUAGES_INSTRUCTIONS).c_str());
+  gtk_util::SetLabelWidth(languages_instructions_label, kWrapWidth);
+  gtk_box_pack_start(GTK_BOX(languages_vbox), languages_instructions_label,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* languages_list_hbox = gtk_hbox_new(FALSE,
+                                                gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(languages_vbox), languages_list_hbox,
+                     TRUE, TRUE, 0);
+
+  // Languages order tree.
+  language_order_store_ = gtk_list_store_new(COL_COUNT,
+                                             G_TYPE_STRING);
+  language_order_tree_ = gtk_tree_view_new_with_model(
+      GTK_TREE_MODEL(language_order_store_));
+  g_object_unref(language_order_store_);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(language_order_tree_), FALSE);
+  GtkTreeViewColumn* lang_column = gtk_tree_view_column_new_with_attributes(
+      "",
+      gtk_cell_renderer_text_new(),
+      "text", COL_LANG,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(language_order_tree_), lang_column);
+  language_order_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(language_order_tree_));
+  gtk_tree_selection_set_mode(language_order_selection_,
+                              GTK_SELECTION_MULTIPLE);
+  g_signal_connect(language_order_selection_, "changed",
+                   G_CALLBACK(OnSelectionChangedThunk), this);
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(scroll_window), language_order_tree_);
+  gtk_box_pack_start(GTK_BOX(languages_list_hbox), scroll_window,
+                     TRUE, TRUE, 0);
+
+  language_order_table_model_.reset(new LanguageOrderTableModel);
+  language_order_table_adapter_.reset(
+      new gtk_tree::TableAdapter(this, language_order_store_,
+                                 language_order_table_model_.get()));
+
+  // Languages order buttons.
+  GtkWidget* languages_buttons_vbox = gtk_vbox_new(FALSE,
+                                                   gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(languages_list_hbox), languages_buttons_vbox,
+                     FALSE, FALSE, 0);
+
+  add_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
+      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_ADD_BUTTON_LABEL).c_str());
+  g_signal_connect(add_button_, "clicked",
+                   G_CALLBACK(OnAddButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), add_button_,
+                     FALSE, FALSE, 0);
+
+  std::string remove_button_text  = l10n_util::GetStringUTF8(
+      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_REMOVE_BUTTON_LABEL);
+  remove_button_ = gtk_button_new_with_label(remove_button_text.c_str());
+  g_signal_connect(remove_button_, "clicked",
+                   G_CALLBACK(OnRemoveButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), remove_button_,
+                     FALSE, FALSE, 0);
+
+  std::string move_up_button_text  = l10n_util::GetStringUTF8(
+      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_MOVEUP_BUTTON_LABEL);
+  move_up_button_ = gtk_button_new_with_label(move_up_button_text.c_str());
+  g_signal_connect(move_up_button_, "clicked",
+                   G_CALLBACK(OnMoveUpButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), move_up_button_,
+                     FALSE, FALSE, 0);
+
+  std::string move_down_button_text  = l10n_util::GetStringUTF8(
+      IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_MOVEDOWN_BUTTON_LABEL);
+  move_down_button_ = gtk_button_new_with_label(move_down_button_text.c_str());
+  g_signal_connect(move_down_button_, "clicked",
+                   G_CALLBACK(OnMoveDownButtonClickedThunk), this);
+  gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), move_down_button_,
+                     FALSE, FALSE, 0);
+
+  // Spell checker controls.
+  GtkWidget* spellchecker_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(page_), spellchecker_vbox,
+                     FALSE, FALSE, 0);
+
+  enable_spellchecking_checkbox_ = gtk_check_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_OPTIONS_ENABLE_SPELLCHECK).c_str());
+  g_signal_connect(enable_spellchecking_checkbox_, "toggled",
+                   G_CALLBACK(OnEnableSpellCheckingToggledThunk), this);
+  gtk_box_pack_start(GTK_BOX(spellchecker_vbox), enable_spellchecking_checkbox_,
+                     FALSE, FALSE, 0);
+
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures)) {
+    enable_autospellcorrect_checkbox_ = gtk_check_button_new_with_label(
+        l10n_util::GetStringUTF8(
+            IDS_OPTIONS_ENABLE_AUTO_SPELL_CORRECTION).c_str());
+    g_signal_connect(enable_autospellcorrect_checkbox_, "toggled",
+                     G_CALLBACK(OnEnableAutoSpellCheckingToggledThunk), this);
+    gtk_box_pack_start(GTK_BOX(spellchecker_vbox),
+                       enable_autospellcorrect_checkbox_, FALSE, FALSE, 0);
+  }
+
+  std::vector<std::string> spell_check_languages;
+  SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
+  dictionary_language_model_.reset(new LanguageComboboxModel(profile(),
+      spell_check_languages));
+  dictionary_language_combobox_ = NewComboboxFromModel(
+      dictionary_language_model_.get());
+  g_signal_connect(dictionary_language_combobox_, "changed",
+                   G_CALLBACK(OnDictionaryLanguageChangedThunk), this);
+  GtkWidget* dictionary_language_control =
+      gtk_util::CreateLabeledControlsGroup(NULL,
+          l10n_util::GetStringUTF8(
+              IDS_OPTIONS_CHROME_DICTIONARY_LANGUAGE).c_str(),
+          dictionary_language_combobox_,
+          NULL);
+  gtk_box_pack_start(GTK_BOX(spellchecker_vbox), dictionary_language_control,
+                     FALSE, FALSE, 0);
+
+  // Initialize.
+  accept_languages_.Init(prefs::kAcceptLanguages,
+                         profile()->GetPrefs(), this);
+  dictionary_language_.Init(prefs::kSpellCheckDictionary,
+                            profile()->GetPrefs(), this);
+  enable_spellcheck_.Init(prefs::kEnableSpellCheck,
+                          profile()->GetPrefs(), this);
+  enable_autospellcorrect_.Init(prefs::kEnableAutoSpellCorrect,
+                                profile()->GetPrefs(), this);
+  NotifyPrefChanged(NULL);
+  EnableControls();
+}
+
+void LanguagesPageGtk::SetColumnValues(int row, GtkTreeIter* iter) {
+  string16 lang = language_order_table_model_->GetText(row, 0);
+  gtk_list_store_set(language_order_store_, iter,
+                     COL_LANG, UTF16ToUTF8(lang).c_str(),
+                     -1);
+}
+
+void LanguagesPageGtk::OnAnyModelUpdate() {
+  if (!initializing_)
+    accept_languages_.SetValue(language_order_table_model_->GetLanguageList());
+  EnableControls();
+}
+
+void LanguagesPageGtk::EnableControls() {
+  int num_selected = gtk_tree_selection_count_selected_rows(
+      language_order_selection_);
+  int row_count = gtk_tree_model_iter_n_children(
+      GTK_TREE_MODEL(language_order_store_), NULL);
+  gtk_widget_set_sensitive(move_up_button_,
+                           num_selected == 1 && FirstSelectedRowNum() > 0);
+  gtk_widget_set_sensitive(move_down_button_,
+                           num_selected == 1 &&
+                           FirstSelectedRowNum() < row_count - 1);
+  gtk_widget_set_sensitive(remove_button_, num_selected > 0);
+}
+
+int LanguagesPageGtk::FirstSelectedRowNum() {
+  int row_num = -1;
+  GList* list = gtk_tree_selection_get_selected_rows(language_order_selection_,
+                                                     NULL);
+  if (list) {
+    row_num = gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(list->data));
+    g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
+    g_list_free(list);
+  }
+  return row_num;
+}
+
+void LanguagesPageGtk::NotifyPrefChanged(const std::string* pref_name) {
+  initializing_ = true;
+  if (!pref_name || *pref_name == prefs::kAcceptLanguages) {
+    language_order_table_model_->SetAcceptLanguagesString(
+        accept_languages_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kSpellCheckDictionary) {
+    int index = dictionary_language_model_->GetSelectedLanguageIndex(
+        prefs::kSpellCheckDictionary);
+
+    // If not found, fall back from "language-region" to "language".
+    if (index < 0) {
+      const std::string& lang_region = dictionary_language_.GetValue();
+      dictionary_language_.SetValue(
+          SpellCheckCommon::GetLanguageFromLanguageRegion(lang_region));
+      index = dictionary_language_model_->GetSelectedLanguageIndex(
+          prefs::kSpellCheckDictionary);
+    }
+
+    gtk_combo_box_set_active(GTK_COMBO_BOX(dictionary_language_combobox_),
+                             index);
+  }
+  if (!pref_name || *pref_name == prefs::kEnableSpellCheck) {
+    gtk_toggle_button_set_active(
+        GTK_TOGGLE_BUTTON(enable_spellchecking_checkbox_),
+        enable_spellcheck_.GetValue());
+  }
+  if (!pref_name || *pref_name == prefs::kEnableAutoSpellCorrect) {
+    if (enable_autospellcorrect_checkbox_) {
+      gtk_toggle_button_set_active(
+          GTK_TOGGLE_BUTTON(enable_autospellcorrect_checkbox_),
+          enable_autospellcorrect_.GetValue());
+    }
+  }
+  initializing_ = false;
+}
+
+void LanguagesPageGtk::OnAddLanguage(const std::string& new_language) {
+  if (language_order_table_model_->Add(new_language))
+    gtk_tree::SelectAndFocusRowNum(language_order_table_model_->RowCount() - 1,
+                                   GTK_TREE_VIEW(language_order_tree_));
+}
+
+void LanguagesPageGtk::OnSelectionChanged(GtkTreeSelection* selection) {
+  EnableControls();
+}
+
+void LanguagesPageGtk::OnAddButtonClicked(GtkWidget* button) {
+  new AddLanguageDialog(profile(), this);
+}
+
+void LanguagesPageGtk::OnRemoveButtonClicked(GtkWidget* button) {
+  std::set<int> selected_rows;
+  gtk_tree::GetSelectedIndices(language_order_selection_,
+                               &selected_rows);
+
+  int selected_row = 0;
+  for (std::set<int>::reverse_iterator selected = selected_rows.rbegin();
+       selected != selected_rows.rend(); ++selected) {
+    language_order_table_model_->Remove(*selected);
+    selected_row = *selected;
+  }
+  int row_count = language_order_table_model_->RowCount();
+  if (row_count <= 0)
+    return;
+  if (selected_row >= row_count)
+    selected_row = row_count - 1;
+  gtk_tree::SelectAndFocusRowNum(selected_row,
+      GTK_TREE_VIEW(language_order_tree_));
+}
+
+void LanguagesPageGtk::OnMoveUpButtonClicked(GtkWidget* button) {
+  int item_selected = FirstSelectedRowNum();
+  language_order_table_model_->MoveUp(item_selected);
+  gtk_tree::SelectAndFocusRowNum(
+      item_selected - 1, GTK_TREE_VIEW(language_order_tree_));
+}
+
+void LanguagesPageGtk::OnMoveDownButtonClicked(GtkWidget* button) {
+  int item_selected = FirstSelectedRowNum();
+  language_order_table_model_->MoveDown(item_selected);
+  gtk_tree::SelectAndFocusRowNum(
+      item_selected + 1, GTK_TREE_VIEW(language_order_tree_));
+}
+
+void LanguagesPageGtk::OnEnableSpellCheckingToggled(GtkWidget* toggle_button) {
+  if (initializing_)
+    return;
+  enable_spellcheck_.SetValue(
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
+}
+
+void LanguagesPageGtk::OnEnableAutoSpellCheckingToggled(
+    GtkWidget* toggle_button) {
+  if (initializing_)
+    return;
+  enable_autospellcorrect_.SetValue(
+      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
+}
+
+void LanguagesPageGtk::OnDictionaryLanguageChanged(GtkWidget* widget) {
+  if (initializing_)
+    return;
+  int new_index = gtk_combo_box_get_active(
+      GTK_COMBO_BOX(dictionary_language_combobox_));
+
+  if (new_index < 0 ||
+      new_index >= dictionary_language_model_->GetItemCount()) {
+    NOTREACHED();
+    return;
+  }
+
+  // Remove the previously added spell check language to the accept list.
+  if (!spellcheck_language_added_.empty()) {
+    int old_index = language_order_table_model_->GetIndex(
+        spellcheck_language_added_);
+    if (old_index > -1)
+      language_order_table_model_->Remove(old_index);
+  }
+
+  // Add this new spell check language only if it is not already in the
+  // accept language list.
+  std::string language =
+      dictionary_language_model_->GetLocaleFromIndex(new_index);
+  int index = language_order_table_model_->GetIndex(language);
+  if (index == -1) {
+    // Add the new language.
+    OnAddLanguage(language);
+    spellcheck_language_added_ = language;
+  } else {
+    spellcheck_language_added_ = "";
+  }
+
+  UserMetricsRecordAction(UserMetricsAction("Options_DictionaryLanguage"),
+                          profile()->GetPrefs());
+  dictionary_language_.SetValue(language);
+}
diff --git a/chrome/browser/ui/gtk/options/languages_page_gtk.h b/chrome/browser/ui/gtk/options/languages_page_gtk.h
new file mode 100644
index 0000000..e3eaa27
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/languages_page_gtk.h
@@ -0,0 +1,132 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The languages page of the Languages & languages options dialog, which
+// contains accept-languages and spellchecker language options.
+//
+// Note that we intentionally do not implement the application locale setting,
+// as it does not make sense on Linux, where locale is set through the LANG and
+// LC_* environment variables.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/options/options_page_base.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class LanguageComboboxModel;
+class LanguageOrderTableModel;
+
+class LanguagesPageGtk
+    : public OptionsPageBase,
+      public gtk_tree::TableAdapter::Delegate {
+ public:
+  explicit LanguagesPageGtk(Profile* profile);
+  virtual ~LanguagesPageGtk();
+
+  GtkWidget* get_page_widget() const { return page_; }
+
+  // gtk_tree::TableAdapter::Delegate implementation.
+  virtual void OnAnyModelUpdate();
+  virtual void SetColumnValues(int row, GtkTreeIter* iter);
+
+  // Callback from AddLanguageDialog.
+  void OnAddLanguage(const std::string& new_language);
+
+ private:
+  // Column ids for |language_order_store_|.
+  enum {
+    COL_LANG,
+    COL_COUNT,
+  };
+
+  void Init();
+
+  // Enable buttons based on selection state.
+  void EnableControls();
+
+  // Get the row number of the first selected row or -1 if no row is selected.
+  int FirstSelectedRowNum();
+
+  // Overridden from OptionsPageBase.
+  virtual void NotifyPrefChanged(const std::string* pref_name);
+
+  // Callbacks for accept languages widgets.
+  CHROMEG_CALLBACK_0(LanguagesPageGtk, void, OnSelectionChanged,
+                     GtkTreeSelection*);
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnAddButtonClicked);
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnRemoveButtonClicked);
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnMoveUpButtonClicked);
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnMoveDownButtonClicked);
+
+  // Callbacks for spellchecker option widgets.
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnEnableSpellCheckingToggled);
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void,
+                       OnEnableAutoSpellCheckingToggled);
+  CHROMEGTK_CALLBACK_0(LanguagesPageGtk, void, OnDictionaryLanguageChanged);
+
+  // The accept languages widgets.
+  GtkListStore* language_order_store_;
+  GtkWidget* language_order_tree_;
+  GtkTreeSelection* language_order_selection_;
+  GtkWidget* move_up_button_;
+  GtkWidget* move_down_button_;
+  GtkWidget* add_button_;
+  GtkWidget* remove_button_;
+
+  // The spell checking widgets.
+  GtkWidget* dictionary_language_combobox_;
+  GtkWidget* enable_autospellcorrect_checkbox_;
+  GtkWidget* enable_spellchecking_checkbox_;
+
+  // The widget containing the options for this page.
+  GtkWidget* page_;
+
+  // The model for |language_order_store_|.
+  scoped_ptr<LanguageOrderTableModel> language_order_table_model_;
+  scoped_ptr<gtk_tree::TableAdapter> language_order_table_adapter_;
+
+  // Accept languages pref.
+  StringPrefMember accept_languages_;
+
+  // The spellchecker "dictionary language" pref and model.
+  StringPrefMember dictionary_language_;
+  scoped_ptr<LanguageComboboxModel> dictionary_language_model_;
+
+  // If a language was auto-added to accept_languages_ due to being selected as
+  // the dictionary language, it is saved in this string, so that it can be
+  // removed if the dictionary language is changed again.
+  std::string spellcheck_language_added_;
+
+  // SpellChecker enable pref.
+  BooleanPrefMember enable_spellcheck_;
+
+  // Auto spell correction pref.
+  BooleanPrefMember enable_autospellcorrect_;
+
+  // Flag to ignore gtk callbacks while we are loading prefs, to avoid
+  // then turning around and saving them again.
+  bool initializing_;
+
+  friend class LanguagesPageGtkTest;
+  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, RemoveAcceptLang);
+  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, RemoveMultipleAcceptLang);
+  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, MoveAcceptLang);
+  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, AddAcceptLang);
+  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, EnableSpellChecking);
+  FRIEND_TEST_ALL_PREFIXES(LanguagesPageGtkTest, DictionaryLanguage);
+
+  DISALLOW_COPY_AND_ASSIGN(LanguagesPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/languages_page_gtk_unittest.cc b/chrome/browser/ui/gtk/options/languages_page_gtk_unittest.cc
new file mode 100644
index 0000000..7df868f
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/languages_page_gtk_unittest.cc
@@ -0,0 +1,309 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/languages_page_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/browser/language_combobox_model.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class LanguagesPageGtkTest : public testing::Test {
+ public:
+  virtual void SetUp() {
+    profile_.reset(new TestingProfile());
+  }
+
+  // Get the accept languages displayed in the dialog in the order they are
+  // displayed, as a comma seperated string.
+  // Ex: EXPECT_STREQ("en,ja", GetDisplayedLangs(page).c_str());
+  std::string GetDisplayedLangs(const LanguagesPageGtk& page) {
+    std::vector<std::string> parts;
+    GtkTreeModel* tree_model = GTK_TREE_MODEL(page.language_order_store_);
+    GtkTreeIter iter;
+    if (!gtk_tree_model_get_iter_first(tree_model, &iter))
+      return std::string();
+    while (true) {
+      gchar* name;
+      gtk_tree_model_get(tree_model, &iter, LanguagesPageGtk::COL_LANG, &name,
+                         -1);
+      parts.push_back(name);
+      g_free(name);
+      if (!gtk_tree_model_iter_next(tree_model, &iter))
+        break;
+    }
+    return JoinString(parts, ',');
+  }
+
+  std::string GetDisplayedSpellCheckerLang(const LanguagesPageGtk& page) {
+    gchar* text = gtk_combo_box_get_active_text(
+        GTK_COMBO_BOX(page.dictionary_language_combobox_));
+    std::string result = text;
+    g_free(text);
+    int space_pos = result.find(' ');
+    if (space_pos)
+      result = result.substr(0, space_pos);
+    return result;
+  }
+
+ protected:
+  MessageLoopForUI message_loop_;
+  scoped_ptr<TestingProfile> profile_;
+};
+
+TEST_F(LanguagesPageGtkTest, RemoveAcceptLang) {
+  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en,ja,es");
+  LanguagesPageGtk page(profile_.get());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  GtkTreeIter iter;
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 1);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
+  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(1, page.FirstSelectedRowNum());
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 1);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
+  EXPECT_STREQ("English", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(0, page.FirstSelectedRowNum());
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 0);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
+  EXPECT_STREQ("", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(-1, page.FirstSelectedRowNum());
+}
+
+TEST_F(LanguagesPageGtkTest, RemoveMultipleAcceptLang) {
+  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en,ja,es,fr,it");
+  LanguagesPageGtk page(profile_.get());
+  GtkTreeIter iter;
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 1);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 3);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 4);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
+  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(1, page.FirstSelectedRowNum());
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 1);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 0);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  gtk_button_clicked(GTK_BUTTON(page.remove_button_));
+  EXPECT_STREQ("", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(-1, page.FirstSelectedRowNum());
+}
+
+TEST_F(LanguagesPageGtkTest, MoveAcceptLang) {
+  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en,ja,es");
+  LanguagesPageGtk page(profile_.get());
+  EXPECT_STREQ("English,Japanese,Spanish", GetDisplayedLangs(page).c_str());
+  GtkTreeIter iter;
+
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_),
+                                &iter, NULL, 0);
+  gtk_tree_selection_select_iter(page.language_order_selection_, &iter);
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+
+  gtk_button_clicked(GTK_BUTTON(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_STREQ("Japanese,English,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("ja,en,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_STREQ("Japanese,Spanish,English", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("ja,es,en",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(page.move_up_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_STREQ("Japanese,English,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("ja,en,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+
+  gtk_button_clicked(GTK_BUTTON(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_STREQ("English,Japanese,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en,ja,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+}
+
+TEST_F(LanguagesPageGtkTest, AddAcceptLang) {
+  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "");
+  LanguagesPageGtk page(profile_.get());
+  EXPECT_STREQ("", GetDisplayedLangs(page).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+
+  page.OnAddLanguage("en");
+  EXPECT_STREQ("English", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(0, page.FirstSelectedRowNum());
+
+  page.OnAddLanguage("es");
+  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(1, page.FirstSelectedRowNum());
+
+  // Duplicates should be ignored and selection should not be changed.
+  gtk_tree_selection_unselect_all(page.language_order_selection_);
+  page.OnAddLanguage("en");
+  EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("en,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_));
+  EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_));
+  EXPECT_EQ(0, gtk_tree_selection_count_selected_rows(
+      page.language_order_selection_));
+}
+
+TEST_F(LanguagesPageGtkTest, EnableSpellChecking) {
+  profile_->GetPrefs()->SetBoolean(prefs::kEnableSpellCheck, false);
+  LanguagesPageGtk page(profile_.get());
+  EXPECT_EQ(FALSE, gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
+
+  profile_->GetPrefs()->SetBoolean(prefs::kEnableSpellCheck, true);
+  EXPECT_EQ(TRUE, gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
+
+  gtk_button_clicked(GTK_BUTTON(page.enable_spellchecking_checkbox_));
+  EXPECT_EQ(FALSE, gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
+  EXPECT_FALSE(profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck));
+
+  gtk_button_clicked(GTK_BUTTON(page.enable_spellchecking_checkbox_));
+  EXPECT_EQ(TRUE, gtk_toggle_button_get_active(
+      GTK_TOGGLE_BUTTON(page.enable_spellchecking_checkbox_)));
+  EXPECT_TRUE(profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck));
+}
+
+// TODO(mattm): add EnableAutoSpellChecking test
+
+TEST_F(LanguagesPageGtkTest, DictionaryLanguage) {
+  profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "it");
+  profile_->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "es");
+  LanguagesPageGtk page(profile_.get());
+  EXPECT_STREQ("Italian", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("it",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_STREQ("Spanish", GetDisplayedSpellCheckerLang(page).c_str());
+  int spanish_index = gtk_combo_box_get_active(
+        GTK_COMBO_BOX(page.dictionary_language_combobox_));
+
+  profile_->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "fr");
+  EXPECT_STREQ("Italian", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("it",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_STREQ("French", GetDisplayedSpellCheckerLang(page).c_str());
+  int french_index = gtk_combo_box_get_active(
+        GTK_COMBO_BOX(page.dictionary_language_combobox_));
+
+  gtk_combo_box_set_active(
+        GTK_COMBO_BOX(page.dictionary_language_combobox_), spanish_index);
+  EXPECT_STREQ("Italian,Spanish", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("it,es",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_STREQ("Spanish", GetDisplayedSpellCheckerLang(page).c_str());
+
+  gtk_combo_box_set_active(
+        GTK_COMBO_BOX(page.dictionary_language_combobox_), french_index);
+  EXPECT_STREQ("Italian,French", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("it,fr",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_STREQ("French", GetDisplayedSpellCheckerLang(page).c_str());
+
+  gtk_combo_box_set_active(
+        GTK_COMBO_BOX(page.dictionary_language_combobox_),
+        page.dictionary_language_model_->GetIndexFromLocale("it"));
+  EXPECT_STREQ("Italian", GetDisplayedLangs(page).c_str());
+  EXPECT_STREQ("it",
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages).c_str());
+  EXPECT_STREQ("Italian", GetDisplayedSpellCheckerLang(page).c_str());
+}
diff --git a/chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.cc b/chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.cc
new file mode 100644
index 0000000..53d8a61
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h"
+
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Padding within the banner box.
+const int kBannerPadding = 3;
+
+}
+
+ManagedPrefsBannerGtk::ManagedPrefsBannerGtk(PrefService* prefs,
+                                             OptionsPage page)
+    : policy::ManagedPrefsBannerBase(prefs, page),
+      banner_widget_(NULL) {
+  InitWidget();
+  OnUpdateVisibility();
+}
+
+void ManagedPrefsBannerGtk::InitWidget() {
+  banner_widget_ = gtk_frame_new(NULL);
+  GtkWidget* contents = gtk_hbox_new(FALSE, kBannerPadding);
+  gtk_container_set_border_width(GTK_CONTAINER(contents), kBannerPadding);
+  gtk_container_add(GTK_CONTAINER(banner_widget_), contents);
+  GtkWidget* warning_image =
+      gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
+                               GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_box_pack_start(GTK_BOX(contents), warning_image, FALSE, FALSE, 0);
+  std::string info_text(l10n_util::GetStringUTF8(IDS_OPTIONS_MANAGED_PREFS));
+  GtkWidget* info_label = gtk_label_new(info_text.c_str());
+  gtk_box_pack_start(GTK_BOX(contents), info_label, FALSE, FALSE, 0);
+  gtk_widget_show_all(banner_widget_);
+  gtk_widget_set_no_show_all(GTK_WIDGET(banner_widget_), TRUE);
+}
+
+void ManagedPrefsBannerGtk::OnUpdateVisibility() {
+  DCHECK(banner_widget_);
+  if (DetermineVisibility())
+    gtk_widget_show(banner_widget_);
+  else
+    gtk_widget_hide(banner_widget_);
+}
diff --git a/chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h b/chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h
new file mode 100644
index 0000000..8a1ec85
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/managed_prefs_banner_gtk.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_MANAGED_PREFS_BANNER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_MANAGED_PREFS_BANNER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/policy/managed_prefs_banner_base.h"
+
+// Constructs and maintains a GTK widget displaying a warning banner. The banner
+// is displayed on the preferences dialog whenever there are options that are
+// not settable by the user due to policy.
+class ManagedPrefsBannerGtk : public policy::ManagedPrefsBannerBase {
+ public:
+  ManagedPrefsBannerGtk(PrefService* prefs, OptionsPage page);
+  virtual ~ManagedPrefsBannerGtk() { }
+
+  GtkWidget* banner_widget() { return banner_widget_; }
+
+ protected:
+  // Update widget visibility.
+  virtual void OnUpdateVisibility();
+
+ private:
+  // Construct the widget.
+  void InitWidget();
+
+  GtkWidget* banner_widget_;
+
+  DISALLOW_COPY_AND_ASSIGN(ManagedPrefsBannerGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_MANAGED_PREFS_BANNER_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/options_layout_gtk.cc b/chrome/browser/ui/gtk/options/options_layout_gtk.cc
new file mode 100644
index 0000000..33dbc86
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/options_layout_gtk.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/options_layout_gtk.h"
+
+#include "chrome/browser/ui/gtk/gtk_util.h"
+
+// If the height of screen is equal or shorter than this, we will use
+// a more compact option layout.
+const int kCompactScreenHeight = 600;
+
+// Default option layout builder follows GNOME HIG, which uses header and
+// spacing to group options.
+class DefaultOptionsLayoutBuilderGtk : public OptionsLayoutBuilderGtk {
+ public:
+  explicit DefaultOptionsLayoutBuilderGtk();
+
+  void AddOptionGroup(const std::string& title, GtkWidget* content,
+                      bool expandable);
+  void AddWidget(GtkWidget* content, bool expandable);
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DefaultOptionsLayoutBuilderGtk);
+};
+
+DefaultOptionsLayoutBuilderGtk::DefaultOptionsLayoutBuilderGtk() {
+  page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(page_),
+                                 gtk_util::kContentAreaBorder);
+}
+
+void DefaultOptionsLayoutBuilderGtk::AddOptionGroup(const std::string& title,
+                                                    GtkWidget* content,
+                                                    bool expandable) {
+  GtkWidget* title_label = gtk_util::CreateBoldLabel(title);
+
+  GtkWidget* group = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(group), title_label, FALSE, FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(group), gtk_util::IndentWidget(content));
+
+  AddWidget(group, expandable);
+}
+
+void DefaultOptionsLayoutBuilderGtk::AddWidget(GtkWidget* content,
+                                               bool expandable) {
+  gtk_box_pack_start(GTK_BOX(page_), content, expandable, expandable, 0);
+}
+
+// Compact layout builder uses table to layout label and content horizontally.
+class CompactOptionsLayoutBuilderGtk : public OptionsLayoutBuilderGtk {
+ public:
+  explicit CompactOptionsLayoutBuilderGtk();
+
+  void AddOptionGroup(const std::string& title, GtkWidget* content,
+                      bool expandable);
+  void AddWidget(GtkWidget* content, bool expandable);
+ private:
+  GtkWidget *table_;
+  guint row_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompactOptionsLayoutBuilderGtk);
+};
+
+CompactOptionsLayoutBuilderGtk::CompactOptionsLayoutBuilderGtk() {
+  row_ = 0;
+  table_ = NULL;
+
+  page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(page_),
+                                 gtk_util::kContentAreaBorder);
+}
+
+void CompactOptionsLayoutBuilderGtk::AddOptionGroup(const std::string& title,
+                                             GtkWidget* content,
+                                             bool expandable) {
+  if (!table_) {
+    // Create a new table to contain option groups
+    table_ = gtk_table_new(0, 2, FALSE);
+    gtk_table_set_col_spacing(GTK_TABLE(table_), 0, gtk_util::kLabelSpacing);
+    gtk_table_set_row_spacings(GTK_TABLE(table_),
+                               gtk_util::kContentAreaSpacing);
+
+    gtk_container_set_border_width(GTK_CONTAINER(table_),
+                                   gtk_util::kContentAreaBorder);
+    gtk_box_pack_start(GTK_BOX(page_), table_, TRUE, TRUE, 0);
+  }
+
+  GtkWidget* title_label = gtk_util::CreateBoldLabel(title);
+
+  gtk_table_resize(GTK_TABLE(table_), row_ + 1, 2);
+  gtk_misc_set_alignment(GTK_MISC(title_label), 1, 0);
+
+  gtk_table_attach(GTK_TABLE(table_), title_label,
+                   0, 1, row_, row_ + 1,
+                   GTK_FILL, GTK_FILL,
+                   0, 0);
+  gtk_table_attach(GTK_TABLE(table_), content,
+                   1, 2, row_, row_ + 1,
+                   expandable ?
+                   GTK_FILL : GtkAttachOptions(GTK_FILL | GTK_EXPAND),
+                   GTK_FILL,
+                   0, 0);
+  row_++;
+}
+
+void CompactOptionsLayoutBuilderGtk::AddWidget(GtkWidget* content,
+                                               bool expandable) {
+  gtk_box_pack_start(GTK_BOX(page_), content, expandable, expandable, 0);
+
+  // Let AddOptionGroup create a new table and append after this widget
+  table_ = NULL;
+}
+
+OptionsLayoutBuilderGtk* OptionsLayoutBuilderGtk::Create() {
+    return new DefaultOptionsLayoutBuilderGtk();
+}
+
+OptionsLayoutBuilderGtk*
+OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout() {
+  gint screen_height = gdk_screen_get_height(gdk_screen_get_default());
+  if (screen_height <= kCompactScreenHeight)
+    return new CompactOptionsLayoutBuilderGtk();
+  else
+    return new DefaultOptionsLayoutBuilderGtk();
+}
diff --git a/chrome/browser/ui/gtk/options/options_layout_gtk.h b/chrome/browser/ui/gtk/options/options_layout_gtk.h
new file mode 100644
index 0000000..5add467
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/options_layout_gtk.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_OPTIONS_LAYOUT_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_OPTIONS_LAYOUT_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <string>
+
+#include "base/basictypes.h"
+
+class OptionsLayoutBuilderGtk {
+ public:
+  virtual ~OptionsLayoutBuilderGtk() {}
+
+  GtkWidget* get_page_widget() {
+    return page_;
+  }
+
+  // Adds an option group to the table.  Handles layout and the placing of
+  // separators between groups.  If expandable is true, the content widget will
+  // be allowed to expand and fill any extra space when the dialog is resized.
+  virtual void AddOptionGroup(const std::string& title, GtkWidget* content,
+                              bool expandable) = 0;
+
+  // Adds a widget without title or special layout.  If expandable is true, the
+  // content widget will be allowed to expand and fill any extra space when the
+  // dialog is resized.
+  virtual void AddWidget(GtkWidget* content, bool expandable) = 0;
+
+  // Creates a default option layout builder. The default layout builder
+  // follows the GNOME HIG.
+  static OptionsLayoutBuilderGtk* Create();
+
+  // Creates a compact option layout builder, if the screen is compact.
+  // Otherwise, creates a default one.
+  static OptionsLayoutBuilderGtk* CreateOptionallyCompactLayout();
+
+ protected:
+  // The parent widget
+  GtkWidget* page_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_OPTIONS_LAYOUT_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/options_window_gtk.cc b/chrome/browser/ui/gtk/options/options_window_gtk.cc
new file mode 100644
index 0000000..32fea06
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/options_window_gtk.cc
@@ -0,0 +1,244 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtk/gtk.h>
+
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/accessibility_events.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/advanced_page_gtk.h"
+#include "chrome/browser/ui/gtk/options/content_page_gtk.h"
+#include "chrome/browser/ui/gtk/options/general_page_gtk.h"
+#include "chrome/browser/ui/options/options_window.h"
+#include "chrome/browser/ui/window_sizer.h"
+#include "chrome/common/pref_names.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// OptionsWindowGtk
+//
+// The contents of the Options dialog window.
+
+class OptionsWindowGtk {
+ public:
+  explicit OptionsWindowGtk(Profile* profile);
+  ~OptionsWindowGtk();
+
+  // Shows the Tab corresponding to the specified OptionsPage.
+  void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group);
+
+ private:
+  static void OnSwitchPage(GtkNotebook* notebook, GtkNotebookPage* page,
+                           guint page_num, OptionsWindowGtk* window);
+
+  static void OnWindowDestroy(GtkWidget* widget, OptionsWindowGtk* window);
+
+  // The options dialog.
+  GtkWidget* dialog_;
+
+  // The container of the option pages.
+  GtkWidget* notebook_;
+
+  // The Profile associated with these options.
+  Profile* profile_;
+
+  // The general page.
+  GeneralPageGtk general_page_;
+
+  // The content page.
+  ContentPageGtk content_page_;
+
+  // The advanced (user data) page.
+  AdvancedPageGtk advanced_page_;
+
+  // The last page the user was on when they opened the Options window.
+  IntegerPrefMember last_selected_page_;
+
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(OptionsWindowGtk);
+};
+
+// The singleton options window object.
+static OptionsWindowGtk* options_window = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+// OptionsWindowGtk, public:
+
+OptionsWindowGtk::OptionsWindowGtk(Profile* profile)
+      // Always show preferences for the original profile. Most state when off
+      // the record comes from the original profile, but we explicitly use
+      // the original profile to avoid potential problems.
+    : profile_(profile->GetOriginalProfile()),
+      general_page_(profile_),
+      content_page_(profile_),
+      advanced_page_(profile_) {
+
+  // We don't need to observe changes in this value.
+  last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex,
+                           g_browser_process->local_state(), NULL);
+
+  std::string dialog_name =
+      l10n_util::GetStringFUTF8(
+          IDS_PREFERENCES_DIALOG_TITLE,
+          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      // Prefs window is shared between all browser windows.
+      NULL,
+      // Non-modal.
+      GTK_DIALOG_NO_SEPARATOR,
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
+  // Allow browser windows to go in front of the options dialog in metacity.
+  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  notebook_ = gtk_notebook_new();
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      general_page_.get_page_widget(),
+      gtk_label_new(
+          l10n_util::GetStringUTF8(IDS_OPTIONS_GENERAL_TAB_LABEL).c_str()));
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      content_page_.get_page_widget(),
+      gtk_label_new(
+          l10n_util::GetStringUTF8(IDS_OPTIONS_CONTENT_TAB_LABEL).c_str()));
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      advanced_page_.get_page_widget(),
+      gtk_label_new(
+          l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_TAB_LABEL).c_str()));
+
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
+
+  DCHECK_EQ(
+      gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), OPTIONS_PAGE_COUNT);
+
+  // Show the content so that we can compute full dialog size, both
+  // for centering and because we want to show the notebook before
+  // connecting switch-page signal, otherwise we'll immediately get a
+  // signal switching to page 0 and overwrite our last_selected_page_
+  // value.
+  gtk_widget_show_all(gtk_bin_get_child(GTK_BIN(dialog_)));
+
+  if (Browser* b = BrowserList::GetLastActive()) {
+    gtk_util::CenterOverWindow(GTK_WINDOW(dialog_),
+                               b->window()->GetNativeHandle());
+  }
+
+  // Now that we're centered over the browser, we add our dialog to its own
+  // window group. We don't do anything with the response and we don't want the
+  // options window's modal dialogs to be associated with the main browser
+  // window because gtk grabs work on a per window group basis.
+  gtk_window_group_add_window(gtk_window_group_new(), GTK_WINDOW(dialog_));
+  g_object_unref(gtk_window_get_group(GTK_WINDOW(dialog_)));
+
+  g_signal_connect(notebook_, "switch-page", G_CALLBACK(OnSwitchPage), this);
+
+  // We only have one button and don't do any special handling, so just hook it
+  // directly to gtk_widget_destroy.
+  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
+
+  gtk_widget_show(dialog_);
+}
+
+OptionsWindowGtk::~OptionsWindowGtk() {
+}
+
+void OptionsWindowGtk::ShowOptionsPage(OptionsPage page,
+                                       OptionsGroup highlight_group) {
+  if (Browser* b = BrowserList::GetLastActive()) {
+    gtk_util::CenterOverWindow(GTK_WINDOW(dialog_),
+                               b->window()->GetNativeHandle());
+  }
+
+  // Bring options window to front if it already existed and isn't already
+  // in front
+  gtk_window_present_with_time(GTK_WINDOW(dialog_),
+                               gtk_get_current_event_time());
+
+  if (page == OPTIONS_PAGE_DEFAULT) {
+    // Remember the last visited page from local state.
+    page = static_cast<OptionsPage>(last_selected_page_.GetValue());
+    if (page == OPTIONS_PAGE_DEFAULT)
+      page = OPTIONS_PAGE_GENERAL;
+  }
+  // If the page number is out of bounds, reset to the first tab.
+  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
+    page = OPTIONS_PAGE_GENERAL;
+
+  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page);
+
+  // TODO(mattm): set highlight_group
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// OptionsWindowGtk, private:
+
+// static
+void OptionsWindowGtk::OnSwitchPage(GtkNotebook* notebook,
+                                    GtkNotebookPage* page,
+                                    guint page_num,
+                                    OptionsWindowGtk* window) {
+  int index = page_num;
+  DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT);
+  window->last_selected_page_.SetValue(index);
+}
+
+// static
+void OptionsWindowGtk::OnWindowDestroy(GtkWidget* widget,
+                                       OptionsWindowGtk* window) {
+  options_window = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Factory/finder method:
+
+void ShowOptionsWindow(OptionsPage page,
+                       OptionsGroup highlight_group,
+                       Profile* profile) {
+  DCHECK(profile);
+
+  // If there's already an existing options window, activate it and switch to
+  // the specified page.
+  if (!options_window) {
+    // Creating and initializing a bunch of controls generates a bunch of
+    // spurious events as control values change. Temporarily suppress
+    // accessibility events until the window is created.
+    profile->PauseAccessibilityEvents();
+
+    // Create the options window.
+    options_window = new OptionsWindowGtk(profile);
+
+    // Resume accessibility events.
+    profile->ResumeAccessibilityEvents();
+  }
+  options_window->ShowOptionsPage(page, highlight_group);
+}
diff --git a/chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.cc b/chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.cc
new file mode 100644
index 0000000..2d21122
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.h"
+
+#include <string>
+
+#include "base/stl_util-inl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "grit/app_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Column ids for |exception_list_store_|.
+enum {
+  COL_SITE,
+  COL_COUNT,
+};
+
+}  // anonymous namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsPageGtk, public:
+
+PasswordsExceptionsPageGtk::PasswordsExceptionsPageGtk(Profile* profile)
+    : populater(this), profile_(profile) {
+
+  remove_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON).c_str());
+  gtk_widget_set_sensitive(remove_button_, FALSE);
+  g_signal_connect(remove_button_, "clicked",
+                   G_CALLBACK(OnRemoveButtonClickedThunk), this);
+  remove_all_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
+          IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON).c_str());
+  gtk_widget_set_sensitive(remove_all_button_, FALSE);
+  g_signal_connect(remove_all_button_, "clicked",
+                   G_CALLBACK(OnRemoveAllButtonClickedThunk), this);
+
+  GtkWidget* buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(buttons), remove_button_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(buttons), remove_all_button_, FALSE, FALSE, 0);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+
+  // Sets exception_tree_ among other things.
+  InitExceptionTree();
+  gtk_container_add(GTK_CONTAINER(scroll_window), exception_tree_);
+
+  page_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(page_),
+                                 gtk_util::kContentAreaBorder);
+  gtk_box_pack_end(GTK_BOX(page_), buttons, FALSE, FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(page_), scroll_window, TRUE, TRUE, 0);
+}
+
+PasswordsExceptionsPageGtk::~PasswordsExceptionsPageGtk() {
+  STLDeleteElements(&exception_list_);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsPageGtk, private:
+
+void PasswordsExceptionsPageGtk::InitExceptionTree() {
+  exception_list_store_ = gtk_list_store_new(COL_COUNT, G_TYPE_STRING);
+  exception_list_sort_ = gtk_tree_model_sort_new_with_model(
+      GTK_TREE_MODEL(exception_list_store_));
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(exception_list_sort_),
+                                  COL_SITE, CompareSite, this, NULL);
+  exception_tree_ = gtk_tree_view_new_with_model(exception_list_sort_);
+  g_object_unref(exception_list_store_);
+  g_object_unref(exception_list_sort_);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(exception_tree_), TRUE);
+
+  exception_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(exception_tree_));
+  gtk_tree_selection_set_mode(exception_selection_,
+                              GTK_SELECTION_SINGLE);
+  g_signal_connect(exception_selection_, "changed",
+                   G_CALLBACK(OnExceptionSelectionChangedThunk), this);
+
+  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_SITE,
+      NULL);
+  gtk_tree_view_column_set_sort_column_id(column, COL_SITE);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(exception_tree_), column);
+
+  populater.populate();
+}
+
+PasswordStore* PasswordsExceptionsPageGtk::GetPasswordStore() {
+    return profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+}
+
+void PasswordsExceptionsPageGtk::SetExceptionList(
+    const std::vector<webkit_glue::PasswordForm*>& result) {
+  std::string languages =
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
+  gtk_list_store_clear(exception_list_store_);
+  STLDeleteElements(&exception_list_);
+  exception_list_ = result;
+  for (size_t i = 0; i < result.size(); ++i) {
+    GtkTreeIter iter;
+    gtk_list_store_insert_with_values(exception_list_store_, &iter, (gint) i,
+        COL_SITE,
+        UTF16ToUTF8(net::FormatUrl(result[i]->origin, languages)).c_str(), -1);
+  }
+  gtk_widget_set_sensitive(remove_all_button_, result.size() > 0);
+}
+
+void PasswordsExceptionsPageGtk::OnRemoveButtonClicked(GtkWidget* widget) {
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(exception_selection_,
+                                       NULL, &iter)) {
+    NOTREACHED();
+    return;
+  }
+
+  GtkTreePath* path = gtk_tree_model_get_path(
+      GTK_TREE_MODEL(exception_list_sort_), &iter);
+  gint index = gtk_tree::GetTreeSortChildRowNumForPath(
+      exception_list_sort_, path);
+  gtk_tree_path_free(path);
+
+  GtkTreeIter child_iter;
+  gtk_tree_model_sort_convert_iter_to_child_iter(
+      GTK_TREE_MODEL_SORT(exception_list_sort_), &child_iter, &iter);
+
+  // Remove from GTK list, DB, and vector.
+  gtk_list_store_remove(exception_list_store_, &child_iter);
+  GetPasswordStore()->RemoveLogin(*exception_list_[index]);
+  delete exception_list_[index];
+  exception_list_.erase(exception_list_.begin() + index);
+
+  gtk_widget_set_sensitive(remove_all_button_, exception_list_.size() > 0);
+}
+
+void PasswordsExceptionsPageGtk::OnRemoveAllButtonClicked(GtkWidget* widget) {
+  // Remove from GTK list, DB, and vector.
+  PasswordStore* store = GetPasswordStore();
+  gtk_list_store_clear(exception_list_store_);
+  for (size_t i = 0; i < exception_list_.size(); ++i)
+    store->RemoveLogin(*exception_list_[i]);
+  STLDeleteElements(&exception_list_);
+  gtk_widget_set_sensitive(remove_all_button_, FALSE);
+}
+
+void PasswordsExceptionsPageGtk::OnExceptionSelectionChanged(
+    GtkTreeSelection* selection) {
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
+    gtk_widget_set_sensitive(remove_button_, FALSE);
+    return;
+  }
+  gtk_widget_set_sensitive(remove_button_, TRUE);
+}
+
+// static
+gint PasswordsExceptionsPageGtk::CompareSite(GtkTreeModel* model,
+                                   GtkTreeIter* a, GtkTreeIter* b,
+                                   gpointer window) {
+  int row1 = gtk_tree::GetRowNumForIter(model, a);
+  int row2 = gtk_tree::GetRowNumForIter(model, b);
+  PasswordsExceptionsPageGtk* page =
+      reinterpret_cast<PasswordsExceptionsPageGtk*>(window);
+  return page->exception_list_[row1]->origin.spec().compare(
+         page->exception_list_[row2]->origin.spec());
+}
+
+void PasswordsExceptionsPageGtk::ExceptionListPopulater::populate() {
+  DCHECK(!pending_login_query_);
+  PasswordStore* store = page_->GetPasswordStore();
+  if (store != NULL)
+    pending_login_query_ = store->GetBlacklistLogins(this);
+  else
+    LOG(ERROR) << "No password store! Cannot display exceptions.";
+}
+
+void
+PasswordsExceptionsPageGtk::ExceptionListPopulater::OnPasswordStoreRequestDone(
+    int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
+  DCHECK_EQ(pending_login_query_, handle);
+  pending_login_query_ = 0;
+  page_->SetExceptionList(result);
+}
diff --git a/chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.h b/chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.h
new file mode 100644
index 0000000..8c0f145
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <vector>
+
+#include "chrome/browser/password_manager/password_store.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Profile;
+
+// A page in the show saved passwords dialog that lists what sites we never
+// show passwords for, with controls for the user to add/remove sites from that
+// list.
+class PasswordsExceptionsPageGtk {
+ public:
+  explicit PasswordsExceptionsPageGtk(Profile* profile);
+  virtual ~PasswordsExceptionsPageGtk();
+
+  GtkWidget* get_page_widget() const { return page_; }
+
+ private:
+  // Initialize the exception tree widget, setting the member variables.
+  void InitExceptionTree();
+
+  // The password store associated with the currently active profile.
+  PasswordStore* GetPasswordStore();
+
+  // Sets the exception list contents to the given data. We take ownership of
+  // the PasswordForms in the vector.
+  void SetExceptionList(const std::vector<webkit_glue::PasswordForm*>& result);
+
+  CHROMEGTK_CALLBACK_0(PasswordsExceptionsPageGtk, void, OnRemoveButtonClicked);
+  CHROMEGTK_CALLBACK_0(PasswordsExceptionsPageGtk, void,
+                       OnRemoveAllButtonClicked);
+
+  CHROMEG_CALLBACK_0(PasswordsExceptionsPageGtk, void,
+                     OnExceptionSelectionChanged, GtkTreeSelection*);
+
+  // Sorting function.
+  static gint CompareSite(GtkTreeModel* model,
+                          GtkTreeIter* a, GtkTreeIter* b,
+                          gpointer window);
+
+  // A short class to mediate requests to the password store.
+  class ExceptionListPopulater : public PasswordStoreConsumer {
+   public:
+    explicit ExceptionListPopulater(PasswordsExceptionsPageGtk* page)
+        : page_(page),
+          pending_login_query_(0) {
+    }
+
+    // Send a query to the password store to populate an
+    // PasswordsExceptionsPageGtk.
+    void populate();
+
+    // PasswordStoreConsumer implementation.
+    // Send the password store's reply back to the PasswordsExceptionsPageGtk.
+    virtual void OnPasswordStoreRequestDone(
+        int handle, const std::vector<webkit_glue::PasswordForm*>& result);
+
+   private:
+    PasswordsExceptionsPageGtk* page_;
+    int pending_login_query_;
+  };
+
+  // Password store consumer for populating the exception list.
+  ExceptionListPopulater populater;
+
+  // Widgets for the buttons.
+  GtkWidget* remove_button_;
+  GtkWidget* remove_all_button_;
+
+  // Widgets for the exception table.
+  GtkWidget* exception_tree_;
+  GtkListStore* exception_list_store_;
+  GtkTreeModel* exception_list_sort_;
+  GtkTreeSelection* exception_selection_;
+
+  // The parent GtkHBox widget.
+  GtkWidget* page_;
+
+  Profile* profile_;
+  std::vector<webkit_glue::PasswordForm*> exception_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordsExceptionsPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.cc b/chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.cc
new file mode 100644
index 0000000..f06b48d
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/passwords_exceptions_page_gtk.h"
+#include "chrome/browser/ui/gtk/options/passwords_page_gtk.h"
+#include "chrome/browser/ui/options/options_window.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowGtk
+//
+// The contents of the Passwords and Exceptions dialog window.
+
+class PasswordsExceptionsWindowGtk {
+ public:
+  explicit PasswordsExceptionsWindowGtk(Profile* profile);
+  ~PasswordsExceptionsWindowGtk();
+
+  void Show();
+
+ private:
+  static void OnWindowDestroy(GtkWidget* widget,
+                              PasswordsExceptionsWindowGtk* window);
+
+  // The passwords and exceptions dialog.
+  GtkWidget *dialog_;
+
+  // The container of the password and exception pages.
+  GtkWidget *notebook_;
+
+  // The Profile associated with these passwords and exceptions.
+  Profile* profile_;
+
+  // The passwords page.
+  PasswordsPageGtk passwords_page_;
+
+  // The exceptions page.
+  PasswordsExceptionsPageGtk exceptions_page_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordsExceptionsWindowGtk);
+};
+
+// The singleton passwords and exceptions window object.
+static PasswordsExceptionsWindowGtk* passwords_exceptions_window = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowGtk, public:
+
+PasswordsExceptionsWindowGtk::PasswordsExceptionsWindowGtk(Profile* profile)
+    : profile_(profile),
+      passwords_page_(profile_),
+      exceptions_page_(profile_) {
+  std::string dialog_name = l10n_util::GetStringUTF8(
+      IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      // Passwords and exceptions window is shared between all browser windows.
+      NULL,
+      // Non-modal.
+      GTK_DIALOG_NO_SEPARATOR,
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  notebook_ = gtk_notebook_new();
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      passwords_page_.get_page_widget(),
+      gtk_label_new(l10n_util::GetStringUTF8(
+              IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE).c_str()));
+
+  gtk_notebook_append_page(
+      GTK_NOTEBOOK(notebook_),
+      exceptions_page_.get_page_widget(),
+      gtk_label_new(l10n_util::GetStringUTF8(
+              IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE).c_str()));
+
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_);
+
+  // We only have one button and don't do any special handling, so just hook it
+  // directly to gtk_widget_destroy.
+  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
+
+  gtk_util::ShowDialogWithLocalizedSize(dialog_,
+      IDS_PASSWORDS_DIALOG_WIDTH_CHARS,
+      IDS_PASSWORDS_DIALOG_HEIGHT_LINES,
+      true);
+}
+
+PasswordsExceptionsWindowGtk::~PasswordsExceptionsWindowGtk() {
+}
+
+void PasswordsExceptionsWindowGtk::Show() {
+  // Bring options window to front if it already existed and isn't already
+  // in front
+  gtk_util::PresentWindow(dialog_, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsExceptionsWindowGtk, private:
+
+// static
+void PasswordsExceptionsWindowGtk::OnWindowDestroy(GtkWidget* widget,
+    PasswordsExceptionsWindowGtk* window) {
+  passwords_exceptions_window = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Factory/finder method:
+
+void ShowPasswordsExceptionsWindow(Profile* profile) {
+  DCHECK(profile);
+  // If there's already an existing passwords and exceptions window, use it.
+  if (!passwords_exceptions_window) {
+    passwords_exceptions_window = new PasswordsExceptionsWindowGtk(profile);
+  }
+  passwords_exceptions_window->Show();
+}
diff --git a/chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.h b/chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.h
new file mode 100644
index 0000000..b6c5c6c
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_GTK_H_
+#pragma once
+
+class Profile;
+
+void ShowPasswordsExceptionsWindow(Profile* profile);
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/passwords_page_gtk.cc b/chrome/browser/ui/gtk/options/passwords_page_gtk.cc
new file mode 100644
index 0000000..6eb3b0b
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/passwords_page_gtk.cc
@@ -0,0 +1,367 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/options/passwords_page_gtk.h"
+
+#include <string>
+
+#include "base/stl_util-inl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "grit/app_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Initial width of the first column.
+const int kSiteColumnInitialSize = 265;
+
+// Column ids for |password_list_store_|.
+enum {
+  COL_SITE,
+  COL_USERNAME,
+  COL_COUNT,
+};
+
+}  // anonymous namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsPageGtk, public:
+
+PasswordsPageGtk::PasswordsPageGtk(Profile* profile)
+    : populater(this), password_showing_(false), profile_(profile) {
+  allow_show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords,
+                             profile->GetPrefs(),
+                             this);
+
+  remove_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON).c_str());
+  gtk_widget_set_sensitive(remove_button_, FALSE);
+  g_signal_connect(remove_button_, "clicked",
+                   G_CALLBACK(OnRemoveButtonClickedThunk), this);
+  remove_all_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8(
+          IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON).c_str());
+  gtk_widget_set_sensitive(remove_all_button_, FALSE);
+  g_signal_connect(remove_all_button_, "clicked",
+                   G_CALLBACK(OnRemoveAllButtonClickedThunk), this);
+
+  // We start with the "hide password" text but change it in the realize event.
+  show_password_button_ = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON).c_str());
+  gtk_widget_set_no_show_all(show_password_button_, true);
+  gtk_widget_set_sensitive(show_password_button_, FALSE);
+  g_signal_connect(show_password_button_, "clicked",
+                   G_CALLBACK(OnShowPasswordButtonClickedThunk), this);
+  g_signal_connect(show_password_button_, "realize",
+                   G_CALLBACK(OnShowPasswordButtonRealizedThunk), this);
+
+  password_ = gtk_label_new("");
+  gtk_label_set_selectable(GTK_LABEL(password_), TRUE);
+  gtk_widget_set_no_show_all(password_, true);
+
+  GtkWidget* buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(buttons), remove_button_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(buttons), remove_all_button_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(buttons), show_password_button_, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(buttons), password_, FALSE, FALSE, 0);
+
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+
+  // Sets password_tree_ among other things.
+  InitPasswordTree();
+  gtk_container_add(GTK_CONTAINER(scroll_window), password_tree_);
+
+  page_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_set_border_width(GTK_CONTAINER(page_),
+                                 gtk_util::kContentAreaBorder);
+  gtk_box_pack_end(GTK_BOX(page_), buttons, FALSE, FALSE, 0);
+  gtk_box_pack_end(GTK_BOX(page_), scroll_window, TRUE, TRUE, 0);
+
+  // Initialize UI state based on current preference values.
+  OnPrefChanged(prefs::kPasswordManagerAllowShowPasswords);
+}
+
+PasswordsPageGtk::~PasswordsPageGtk() {
+  STLDeleteElements(&password_list_);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PasswordsPageGtk, private:
+
+void PasswordsPageGtk::InitPasswordTree() {
+  password_list_store_ = gtk_list_store_new(COL_COUNT,
+                                            G_TYPE_STRING,
+                                            G_TYPE_STRING);
+  password_list_sort_ = gtk_tree_model_sort_new_with_model(
+      GTK_TREE_MODEL(password_list_store_));
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(password_list_sort_),
+                                  COL_SITE, CompareSite, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(password_list_sort_),
+                                  COL_USERNAME, CompareUsername, this, NULL);
+  password_tree_ = gtk_tree_view_new_with_model(password_list_sort_);
+  g_object_unref(password_list_store_);
+  g_object_unref(password_list_sort_);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(password_tree_), TRUE);
+
+  password_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(password_tree_));
+  gtk_tree_selection_set_mode(password_selection_,
+                              GTK_SELECTION_SINGLE);
+  g_signal_connect(password_selection_, "changed",
+                   G_CALLBACK(OnPasswordSelectionChangedThunk), this);
+
+  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_SITE,
+      NULL);
+  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+  gtk_tree_view_column_set_resizable(column, TRUE);
+  gtk_tree_view_column_set_fixed_width(column, kSiteColumnInitialSize);
+  gtk_tree_view_column_set_sort_column_id(column, COL_SITE);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(password_tree_), column);
+
+  column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_USERNAME,
+      NULL);
+  gtk_tree_view_column_set_sort_column_id(column, COL_USERNAME);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(password_tree_), column);
+  populater.populate();
+}
+
+PasswordStore* PasswordsPageGtk::GetPasswordStore() {
+    return profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+}
+
+void PasswordsPageGtk::SetPasswordList(
+    const std::vector<webkit_glue::PasswordForm*>& result) {
+  std::string languages =
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
+  gtk_list_store_clear(password_list_store_);
+  STLDeleteElements(&password_list_);
+  password_list_ = result;
+  for (size_t i = 0; i < result.size(); ++i) {
+    GtkTreeIter iter;
+    gtk_list_store_insert_with_values(password_list_store_, &iter, (gint) i,
+        COL_SITE,
+        UTF16ToUTF8(net::FormatUrl(result[i]->origin, languages)).c_str(),
+        COL_USERNAME, UTF16ToUTF8(result[i]->username_value).c_str(), -1);
+  }
+  gtk_widget_set_sensitive(remove_all_button_, result.size() > 0);
+}
+
+void PasswordsPageGtk::HidePassword() {
+  password_showing_ = false;
+  gtk_label_set_text(GTK_LABEL(password_), "");
+  gtk_button_set_label(GTK_BUTTON(show_password_button_),
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON).c_str());
+}
+
+void PasswordsPageGtk::Observe(NotificationType type,
+                               const NotificationSource& source,
+                               const NotificationDetails& details) {
+  DCHECK_EQ(NotificationType::PREF_CHANGED, type.value);
+  const std::string* pref_name = Details<std::string>(details).ptr();
+  OnPrefChanged(*pref_name);
+}
+
+void PasswordsPageGtk::OnPrefChanged(const std::string& pref_name) {
+  if (pref_name == prefs::kPasswordManagerAllowShowPasswords) {
+    if (allow_show_passwords_.GetValue()) {
+      gtk_widget_show(show_password_button_);
+      gtk_widget_show(password_);
+    } else {
+      HidePassword();
+      gtk_widget_hide(show_password_button_);
+      gtk_widget_hide(password_);
+    }
+  } else {
+    NOTREACHED();
+  }
+}
+
+void PasswordsPageGtk::OnRemoveButtonClicked(GtkWidget* widget) {
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(password_selection_,
+                                       NULL, &iter)) {
+    NOTREACHED();
+    return;
+  }
+
+  GtkTreePath* path = gtk_tree_model_get_path(
+      GTK_TREE_MODEL(password_list_sort_), &iter);
+  gint index = gtk_tree::GetTreeSortChildRowNumForPath(
+      password_list_sort_, path);
+  gtk_tree_path_free(path);
+
+  GtkTreeIter child_iter;
+  gtk_tree_model_sort_convert_iter_to_child_iter(
+      GTK_TREE_MODEL_SORT(password_list_sort_), &child_iter, &iter);
+
+  // Remove from GTK list, DB, and vector.
+  gtk_list_store_remove(password_list_store_, &child_iter);
+  GetPasswordStore()->RemoveLogin(*password_list_[index]);
+  delete password_list_[index];
+  password_list_.erase(password_list_.begin() + index);
+
+  gtk_widget_set_sensitive(remove_all_button_, password_list_.size() > 0);
+}
+
+void PasswordsPageGtk::OnRemoveAllButtonClicked(GtkWidget* widget) {
+  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(page_));
+  GtkWidget* confirm = gtk_message_dialog_new(
+      window,
+      static_cast<GtkDialogFlags>(
+          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
+      GTK_MESSAGE_QUESTION,
+      GTK_BUTTONS_YES_NO,
+      "%s",
+      l10n_util::GetStringUTF8(
+          IDS_PASSWORDS_PAGE_VIEW_TEXT_DELETE_ALL_PASSWORDS).c_str());
+  gtk_util::ApplyMessageDialogQuirks(confirm);
+  gtk_window_set_title(GTK_WINDOW(confirm), l10n_util::GetStringUTF8(
+          IDS_PASSWORDS_PAGE_VIEW_CAPTION_DELETE_ALL_PASSWORDS).c_str());
+  g_signal_connect(confirm, "response",
+                   G_CALLBACK(OnRemoveAllConfirmResponseThunk), this);
+  gtk_widget_show_all(confirm);
+}
+
+void PasswordsPageGtk::OnRemoveAllConfirmResponse(GtkWidget* confirm,
+                                                  gint response) {
+  bool confirmed = false;
+  switch (response) {
+    case GTK_RESPONSE_YES:
+      confirmed = true;
+      break;
+    default:
+      break;
+  }
+  gtk_widget_destroy(confirm);
+  if (!confirmed)
+    return;
+
+  // Remove from GTK list, DB, and vector.
+  PasswordStore* store = GetPasswordStore();
+  gtk_list_store_clear(password_list_store_);
+  for (size_t i = 0; i < password_list_.size(); ++i)
+    store->RemoveLogin(*password_list_[i]);
+  STLDeleteElements(&password_list_);
+  gtk_widget_set_sensitive(remove_all_button_, FALSE);
+}
+
+void PasswordsPageGtk::OnShowPasswordButtonClicked(GtkWidget* widget) {
+  if (password_showing_ || !allow_show_passwords_.GetValue()) {
+    // Hide the password.
+    HidePassword();
+    return;
+  }
+  // Show the password.
+  password_showing_ = true;
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(password_selection_,
+                                       NULL, &iter)) {
+    NOTREACHED();
+    return;
+  }
+  GtkTreePath* path = gtk_tree_model_get_path(
+      GTK_TREE_MODEL(password_list_sort_), &iter);
+  gint index = gtk_tree::GetTreeSortChildRowNumForPath(
+      password_list_sort_, path);
+  gtk_tree_path_free(path);
+  std::string pass = UTF16ToUTF8(password_list_[index]->password_value);
+  gtk_label_set_text(GTK_LABEL(password_), pass.c_str());
+  gtk_button_set_label(GTK_BUTTON(show_password_button_),
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON).c_str());
+}
+
+void PasswordsPageGtk::OnShowPasswordButtonRealized(GtkWidget* widget) {
+  // We have just realized the "show password" button, so we can now accurately
+  // find out how big it needs to be in order to accomodate both the "show" and
+  // "hide" labels. (This requires font information to work correctly.) The
+  // button starts with the "hide" label so we only have to change it once.
+  GtkRequisition hide_size, show_size;
+  // Get the size request of the button with the "hide password" text.
+  gtk_widget_size_request(show_password_button_, &hide_size);
+  gtk_button_set_label(GTK_BUTTON(show_password_button_),
+      l10n_util::GetStringUTF8(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON).c_str());
+  // Get the size request of the button with the "show password" text.
+  gtk_widget_size_request(show_password_button_, &show_size);
+  // Determine the maximum width and height.
+  if (hide_size.width > show_size.width)
+    show_size.width = hide_size.width;
+  if (hide_size.height > show_size.height)
+    show_size.height = hide_size.height;
+  // Force the button to be large enough for both labels.
+  gtk_widget_set_size_request(show_password_button_, show_size.width,
+                              show_size.height);
+}
+
+void PasswordsPageGtk::OnPasswordSelectionChanged(GtkTreeSelection* selection) {
+  // No matter how the selection changed, we want to hide the old password.
+  HidePassword();
+
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
+    gtk_widget_set_sensitive(show_password_button_, FALSE);
+    gtk_widget_set_sensitive(remove_button_, FALSE);
+    return;
+  }
+  gtk_widget_set_sensitive(show_password_button_, TRUE);
+  gtk_widget_set_sensitive(remove_button_, TRUE);
+}
+
+// static
+gint PasswordsPageGtk::CompareSite(GtkTreeModel* model,
+                                   GtkTreeIter* a, GtkTreeIter* b,
+                                   gpointer window) {
+  int row1 = gtk_tree::GetRowNumForIter(model, a);
+  int row2 = gtk_tree::GetRowNumForIter(model, b);
+  PasswordsPageGtk* page = reinterpret_cast<PasswordsPageGtk*>(window);
+  return page->password_list_[row1]->origin.spec().compare(
+         page->password_list_[row2]->origin.spec());
+}
+
+// static
+gint PasswordsPageGtk::CompareUsername(GtkTreeModel* model,
+                                       GtkTreeIter* a, GtkTreeIter* b,
+                                       gpointer window) {
+  int row1 = gtk_tree::GetRowNumForIter(model, a);
+  int row2 = gtk_tree::GetRowNumForIter(model, b);
+  PasswordsPageGtk* page = reinterpret_cast<PasswordsPageGtk*>(window);
+  return page->password_list_[row1]->username_value.compare(
+         page->password_list_[row2]->username_value);
+}
+
+void PasswordsPageGtk::PasswordListPopulater::populate() {
+  DCHECK(!pending_login_query_);
+  PasswordStore* store = page_->GetPasswordStore();
+  if (store != NULL)
+    pending_login_query_ = store->GetAutofillableLogins(this);
+  else
+    LOG(ERROR) << "No password store! Cannot display passwords.";
+}
+
+void PasswordsPageGtk::PasswordListPopulater::OnPasswordStoreRequestDone(
+    int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
+  DCHECK_EQ(pending_login_query_, handle);
+  pending_login_query_ = 0;
+  page_->SetPasswordList(result);
+}
diff --git a/chrome/browser/ui/gtk/options/passwords_page_gtk.h b/chrome/browser/ui/gtk/options/passwords_page_gtk.h
new file mode 100644
index 0000000..618f1ad
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/passwords_page_gtk.h
@@ -0,0 +1,115 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_PAGE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_PAGE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/common/notification_observer.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Profile;
+
+class PasswordsPageGtk : public NotificationObserver {
+ public:
+  explicit PasswordsPageGtk(Profile* profile);
+  virtual ~PasswordsPageGtk();
+
+  GtkWidget* get_page_widget() const { return page_; }
+
+ private:
+  // Initialize the password tree widget, setting the member variables.
+  void InitPasswordTree();
+
+  // The password store associated with the currently active profile.
+  PasswordStore* GetPasswordStore();
+
+  // Sets the password list contents to the given data. We take ownership of
+  // the PasswordForms in the vector.
+  void SetPasswordList(const std::vector<webkit_glue::PasswordForm*>& result);
+
+  // Helper that hides the password.
+  void HidePassword();
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Handles changes to the observed preferences and updates the UI.
+  void OnPrefChanged(const std::string& pref_name);
+
+  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnRemoveButtonClicked);
+  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnRemoveAllButtonClicked);
+  CHROMEGTK_CALLBACK_1(PasswordsPageGtk, void, OnRemoveAllConfirmResponse, int);
+  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnShowPasswordButtonClicked);
+  CHROMEGTK_CALLBACK_0(PasswordsPageGtk, void, OnShowPasswordButtonRealized);
+
+  CHROMEG_CALLBACK_0(PasswordsPageGtk, void, OnPasswordSelectionChanged,
+                     GtkTreeSelection*);
+
+  // Sorting functions.
+  static gint CompareSite(GtkTreeModel* model,
+                          GtkTreeIter* a, GtkTreeIter* b,
+                          gpointer window);
+  static gint CompareUsername(GtkTreeModel* model,
+                              GtkTreeIter* a, GtkTreeIter* b,
+                              gpointer window);
+
+  // A short class to mediate requests to the password store.
+  class PasswordListPopulater : public PasswordStoreConsumer {
+   public:
+    explicit PasswordListPopulater(PasswordsPageGtk* page)
+        : page_(page),
+          pending_login_query_(0) {
+    }
+
+    // Send a query to the password store to populate a PasswordsPageGtk.
+    void populate();
+
+    // Send the password store's reply back to the PasswordsPageGtk.
+    virtual void OnPasswordStoreRequestDone(
+        int handle, const std::vector<webkit_glue::PasswordForm*>& result);
+
+   private:
+    PasswordsPageGtk* page_;
+    int pending_login_query_;
+  };
+
+  // Password store consumer for populating the password list.
+  PasswordListPopulater populater;
+
+  // Widgets for the buttons.
+  GtkWidget* remove_button_;
+  GtkWidget* remove_all_button_;
+  GtkWidget* show_password_button_;
+
+  // Widget for the shown password
+  GtkWidget* password_;
+  bool password_showing_;
+
+  // Widgets for the password table.
+  GtkWidget* password_tree_;
+  GtkListStore* password_list_store_;
+  GtkTreeModel* password_list_sort_;
+  GtkTreeSelection* password_selection_;
+
+  // The parent GtkHBox widget and GtkWindow window.
+  GtkWidget* page_;
+
+  Profile* profile_;
+  BooleanPrefMember allow_show_passwords_;
+  std::vector<webkit_glue::PasswordForm*> password_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordsPageGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_PASSWORDS_PAGE_GTK_H_
diff --git a/chrome/browser/ui/gtk/options/simple_content_exceptions_window.cc b/chrome/browser/ui/gtk/options/simple_content_exceptions_window.cc
new file mode 100644
index 0000000..a8d9396
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/simple_content_exceptions_window.cc
@@ -0,0 +1,212 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/options/simple_content_exceptions_window.h"
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Singleton for exception window.
+SimpleContentExceptionsWindow* instance = NULL;
+
+enum {
+  COL_ACTION = gtk_tree::TableAdapter::COL_LAST_ID,
+  COL_COUNT
+};
+
+}  // namespace
+
+// static
+void SimpleContentExceptionsWindow::ShowExceptionsWindow(
+    GtkWindow* parent, RemoveRowsTableModel* model, int title_message_id) {
+  DCHECK(model);
+  scoped_ptr<RemoveRowsTableModel> owned_model(model);
+
+  if (!instance) {
+    instance = new SimpleContentExceptionsWindow(
+        parent, owned_model.release(), title_message_id);
+  } else {
+    gtk_util::PresentWindow(instance->dialog_, 0);
+  }
+}
+
+SimpleContentExceptionsWindow::SimpleContentExceptionsWindow(
+    GtkWindow* parent,
+    RemoveRowsTableModel* model,
+    int title_message_id)
+      : ignore_selection_changes_(false) {
+  // Build the model adapters that translate views and TableModels into
+  // something GTK can use.
+  list_store_ = gtk_list_store_new(COL_COUNT,
+                                   G_TYPE_STRING,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_INT,
+                                   G_TYPE_INT,
+                                   G_TYPE_BOOLEAN,
+                                   G_TYPE_STRING);
+  treeview_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_));
+  g_object_unref(list_store_);
+
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview_), TRUE);
+  gtk_tree_view_set_row_separator_func(
+      GTK_TREE_VIEW(treeview_),
+      gtk_tree::TableAdapter::OnCheckRowIsSeparator,
+      NULL,
+      NULL);
+
+  // Set up the properties of the treeview
+  GtkTreeViewColumn* hostname_column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_HOSTNAME_HEADER).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", gtk_tree::TableAdapter::COL_TITLE,
+      "weight", gtk_tree::TableAdapter::COL_WEIGHT,
+      "weight-set", gtk_tree::TableAdapter::COL_WEIGHT_SET,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), hostname_column);
+
+  GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_ACTION,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), action_column);
+
+  treeview_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(treeview_));
+  gtk_tree_selection_set_mode(treeview_selection_, GTK_SELECTION_MULTIPLE);
+  gtk_tree_selection_set_select_function(
+      treeview_selection_,
+      gtk_tree::TableAdapter::OnSelectionFilter,
+      NULL,
+      NULL);
+  g_signal_connect(treeview_selection_, "changed",
+                   G_CALLBACK(OnTreeSelectionChangedThunk), this);
+
+  // Bind |list_store_| to our C++ model.
+  model_.reset(model);
+  model_adapter_.reset(new gtk_tree::TableAdapter(this, list_store_,
+                                                  model_.get()));
+  // Force a reload of everything to copy data into |list_store_|.
+  model_adapter_->OnModelChanged();
+
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(title_message_id).c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CLOSE,
+      GTK_RESPONSE_CLOSE,
+      NULL);
+  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, 400);
+  // Allow browser windows to go in front of the options dialog in metacity.
+  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox);
+
+  // Create a scrolled window to wrap the treeview widget.
+  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
+  gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0);
+
+  GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+
+  remove_button_ = gtk_util::BuildDialogButton(dialog_,
+                                               IDS_EXCEPTIONS_REMOVE_BUTTON,
+                                               GTK_STOCK_REMOVE);
+
+  g_signal_connect(remove_button_, "clicked", G_CALLBACK(RemoveThunk), this);
+  gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0);
+
+  remove_all_button_ = gtk_util::BuildDialogButton(
+      dialog_,
+      IDS_EXCEPTIONS_REMOVEALL_BUTTON,
+      GTK_STOCK_CLEAR);
+  g_signal_connect(remove_all_button_, "clicked", G_CALLBACK(RemoveAllThunk),
+                   this);
+  gtk_box_pack_start(GTK_BOX(button_box), remove_all_button_, FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0);
+
+  UpdateButtonState();
+
+  gtk_util::ShowDialogWithLocalizedSize(dialog_,
+      IDS_SIMPLE_CONTENT_EXCEPTION_DIALOG_WIDTH_CHARS,
+      IDS_SIMPLE_CONTENT_EXCEPTION_DIALOG_HEIGHT_LINES,
+      true);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+SimpleContentExceptionsWindow::~SimpleContentExceptionsWindow() {}
+
+void SimpleContentExceptionsWindow::SetColumnValues(int row,
+                                                    GtkTreeIter* iter) {
+  string16 hostname = model_->GetText(row, IDS_EXCEPTIONS_HOSTNAME_HEADER);
+  gtk_list_store_set(list_store_, iter, gtk_tree::TableAdapter::COL_TITLE,
+                     UTF16ToUTF8(hostname).c_str(), -1);
+
+  string16 action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER);
+  gtk_list_store_set(list_store_, iter, COL_ACTION,
+                     UTF16ToUTF8(action).c_str(), -1);
+}
+
+void SimpleContentExceptionsWindow::OnAnyModelUpdateStart() {
+  ignore_selection_changes_ = true;
+}
+
+void SimpleContentExceptionsWindow::OnAnyModelUpdate() {
+  ignore_selection_changes_ = false;
+}
+
+void SimpleContentExceptionsWindow::UpdateButtonState() {
+  int row_count = gtk_tree_model_iter_n_children(
+      GTK_TREE_MODEL(list_store_), NULL);
+
+  RemoveRowsTableModel::Rows rows;
+  std::set<int> indices;
+  gtk_tree::GetSelectedIndices(treeview_selection_, &indices);
+  model_adapter_->MapListStoreIndicesToModelRows(indices, &rows);
+  gtk_widget_set_sensitive(remove_button_, model_->CanRemoveRows(rows));
+  gtk_widget_set_sensitive(remove_all_button_, row_count > 0);
+}
+
+void SimpleContentExceptionsWindow::Remove(GtkWidget* widget) {
+  RemoveRowsTableModel::Rows rows;
+  std::set<int> indices;
+  gtk_tree::GetSelectedIndices(treeview_selection_, &indices);
+  model_adapter_->MapListStoreIndicesToModelRows(indices, &rows);
+  model_->RemoveRows(rows);
+  UpdateButtonState();
+}
+
+void SimpleContentExceptionsWindow::RemoveAll(GtkWidget* widget) {
+  model_->RemoveAll();
+  UpdateButtonState();
+}
+
+void SimpleContentExceptionsWindow::OnWindowDestroy(GtkWidget* widget) {
+  instance = NULL;
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void SimpleContentExceptionsWindow::OnTreeSelectionChanged(
+    GtkWidget* selection) {
+  if (!ignore_selection_changes_)
+    UpdateButtonState();
+}
diff --git a/chrome/browser/ui/gtk/options/simple_content_exceptions_window.h b/chrome/browser/ui/gtk/options/simple_content_exceptions_window.h
new file mode 100644
index 0000000..c817c01
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/simple_content_exceptions_window.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.
+
+#ifndef CHROME_BROWSER_UI_GTK_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_WINDOW_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_WINDOW_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/remove_rows_table_model.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/content_settings_types.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class SimpleContentExceptionsWindow
+    : public gtk_tree::TableAdapter::Delegate {
+ public:
+  // Takes ownership of |model|.
+  static void ShowExceptionsWindow(GtkWindow* parent,
+                                   RemoveRowsTableModel* model,
+                                   int tile_message_id);
+
+  virtual ~SimpleContentExceptionsWindow();
+
+  // gtk_tree::TableAdapter::Delegate implementation:
+  virtual void SetColumnValues(int row, GtkTreeIter* iter);
+  virtual void OnAnyModelUpdateStart();
+  virtual void OnAnyModelUpdate();
+
+ private:
+  // Takes ownership of |model|.
+  SimpleContentExceptionsWindow(GtkWindow* parent,
+                                RemoveRowsTableModel* model,
+                                int title_message_id);
+
+  // Updates which buttons are enabled.
+  void UpdateButtonState();
+
+  // Callbacks for the buttons.
+  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void, Remove);
+  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void, RemoveAll);
+
+  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void,
+                       OnWindowDestroy);
+  CHROMEGTK_CALLBACK_0(SimpleContentExceptionsWindow, void,
+                       OnTreeSelectionChanged);
+
+  // The list presented in |treeview_|; a gobject instead of a C++ object.
+  GtkListStore* list_store_;
+
+  // The C++, views-ish, cross-platform model class that actually contains the
+  // gold standard data.
+  scoped_ptr<RemoveRowsTableModel> model_;
+
+  // The adapter that ferries data back and forth between |model_| and
+  // |list_store_| whenever either of them change.
+  scoped_ptr<gtk_tree::TableAdapter> model_adapter_;
+
+  // The exception window.
+  GtkWidget* dialog_;
+
+  // The treeview that presents the site/action pairs.
+  GtkWidget* treeview_;
+
+  // The current user selection from |treeview_|.
+  GtkTreeSelection* treeview_selection_;
+
+  // Whether to ignore selection changes. This is set during model updates,
+  // when the list store may be inconsistent with the table model.
+  bool ignore_selection_changes_;
+
+  // Buttons.
+  GtkWidget* remove_button_;
+  GtkWidget* remove_all_button_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_WINDOW_H_
diff --git a/chrome/browser/ui/gtk/options/url_picker_dialog_gtk.cc b/chrome/browser/ui/gtk/options/url_picker_dialog_gtk.cc
new file mode 100644
index 0000000..76cb739
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/url_picker_dialog_gtk.cc
@@ -0,0 +1,276 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/possible_url_model.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/accessible_widget_helper_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/options/url_picker_dialog_gtk.h"
+#include "chrome/common/pref_names.h"
+#include "googleurl/src/gurl.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "net/base/net_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// Column ids for |history_list_store_|.
+enum {
+  COL_FAVICON,
+  COL_TITLE,
+  COL_DISPLAY_URL,
+  COL_COUNT,
+};
+
+}  // anonymous namespace
+
+UrlPickerDialogGtk::UrlPickerDialogGtk(UrlPickerCallback* callback,
+                                       Profile* profile,
+                                       GtkWindow* parent)
+    : profile_(profile),
+      callback_(callback) {
+  std::string dialog_name = l10n_util::GetStringUTF8(IDS_ASI_ADD_TITLE);
+  dialog_ = gtk_dialog_new_with_buttons(
+      dialog_name.c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      GTK_STOCK_CANCEL,
+      GTK_RESPONSE_CANCEL,
+      NULL);
+  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
+      dialog_, profile));
+  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);
+
+  add_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
+                                      GTK_STOCK_ADD, GTK_RESPONSE_OK);
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  // URL entry.
+  GtkWidget* url_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+  GtkWidget* url_label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_ASI_URL).c_str());
+  gtk_box_pack_start(GTK_BOX(url_hbox), url_label,
+                     FALSE, FALSE, 0);
+  url_entry_ = gtk_entry_new();
+  accessible_widget_helper_->SetWidgetName(url_entry_, IDS_ASI_URL);
+  gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
+  g_signal_connect(url_entry_, "changed",
+                   G_CALLBACK(OnUrlEntryChangedThunk), this);
+  gtk_box_pack_start(GTK_BOX(url_hbox), url_entry_,
+                     TRUE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), url_hbox,
+                     FALSE, FALSE, 0);
+
+  // Recent history description label.
+  GtkWidget* history_vbox = gtk_vbox_new(FALSE, gtk_util::kLabelSpacing);
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), history_vbox);
+  GtkWidget* history_label = gtk_util::CreateBoldLabel(
+      l10n_util::GetStringUTF8(IDS_ASI_DESCRIPTION));
+  gtk_box_pack_start(GTK_BOX(history_vbox), history_label, FALSE, FALSE, 0);
+
+  // Recent history list.
+  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(history_vbox), scroll_window);
+
+  history_list_store_ = gtk_list_store_new(COL_COUNT,
+                                           GDK_TYPE_PIXBUF,
+                                           G_TYPE_STRING,
+                                           G_TYPE_STRING);
+  history_list_sort_ = gtk_tree_model_sort_new_with_model(
+      GTK_TREE_MODEL(history_list_store_));
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
+                                  COL_TITLE, CompareTitle, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
+                                  COL_DISPLAY_URL, CompareURL, this, NULL);
+  history_tree_ = gtk_tree_view_new_with_model(history_list_sort_);
+  accessible_widget_helper_->SetWidgetName(
+      history_tree_, IDS_ASI_DESCRIPTION);
+  g_object_unref(history_list_store_);
+  g_object_unref(history_list_sort_);
+  gtk_container_add(GTK_CONTAINER(scroll_window), history_tree_);
+  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(history_tree_),
+                                    TRUE);
+  g_signal_connect(history_tree_, "row-activated",
+                   G_CALLBACK(OnHistoryRowActivatedThunk), this);
+
+  history_selection_ = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(history_tree_));
+  gtk_tree_selection_set_mode(history_selection_,
+                              GTK_SELECTION_SINGLE);
+  g_signal_connect(history_selection_, "changed",
+                   G_CALLBACK(OnHistorySelectionChangedThunk), this);
+
+  // History list columns.
+  GtkTreeViewColumn* column = gtk_tree_view_column_new();
+  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(column, renderer, FALSE);
+  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
+  renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_),
+                              column);
+  gtk_tree_view_column_set_title(
+      column, l10n_util::GetStringUTF8(IDS_ASI_PAGE_COLUMN).c_str());
+  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+  gtk_tree_view_column_set_resizable(column, TRUE);
+  gtk_tree_view_column_set_sort_column_id(column, COL_TITLE);
+
+  GtkTreeViewColumn* url_column = gtk_tree_view_column_new_with_attributes(
+      l10n_util::GetStringUTF8(IDS_ASI_URL_COLUMN).c_str(),
+      gtk_cell_renderer_text_new(),
+      "text", COL_DISPLAY_URL,
+      NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_), url_column);
+  gtk_tree_view_column_set_sort_column_id(url_column, COL_DISPLAY_URL);
+
+  // Loading data, showing dialog.
+  url_table_model_.reset(new PossibleURLModel());
+  url_table_adapter_.reset(new gtk_tree::TableAdapter(this, history_list_store_,
+                                                      url_table_model_.get()));
+  url_table_model_->Reload(profile_);
+
+  EnableControls();
+
+  // Set the size of the dialog.
+  gtk_widget_realize(dialog_);
+  gtk_util::SetWindowSizeFromResources(GTK_WINDOW(dialog_),
+                                       IDS_URLPICKER_DIALOG_WIDTH_CHARS,
+                                       IDS_URLPICKER_DIALOG_HEIGHT_LINES,
+                                       true);
+
+  // Set the width of the first column as well.
+  int width;
+  gtk_util::GetWidgetSizeFromResources(
+      dialog_,
+      IDS_URLPICKER_DIALOG_LEFT_COLUMN_WIDTH_CHARS, 0,
+      &width, NULL);
+  gtk_tree_view_column_set_fixed_width(column, width);
+
+  gtk_util::ShowDialogWithLocalizedSize(dialog_,
+      IDS_URLPICKER_DIALOG_WIDTH_CHARS,
+      IDS_URLPICKER_DIALOG_HEIGHT_LINES,
+      false);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+UrlPickerDialogGtk::~UrlPickerDialogGtk() {
+  delete callback_;
+}
+
+void UrlPickerDialogGtk::AddURL() {
+  callback_->Run(URLFixerUpper::FixupURL(
+      gtk_entry_get_text(GTK_ENTRY(url_entry_)), std::string()));
+}
+
+void UrlPickerDialogGtk::EnableControls() {
+  const gchar* text = gtk_entry_get_text(GTK_ENTRY(url_entry_));
+  gtk_widget_set_sensitive(add_button_, text && *text);
+}
+
+std::string UrlPickerDialogGtk::GetURLForPath(GtkTreePath* path) const {
+  gint row = gtk_tree::GetTreeSortChildRowNumForPath(history_list_sort_, path);
+  if (row < 0) {
+    NOTREACHED();
+    return std::string();
+  }
+  std::string languages =
+      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
+  // Because this gets parsed by FixupURL(), it's safe to omit the scheme or
+  // trailing slash, and unescape most characters, but we need to not drop any
+  // username/password, or unescape anything that changes the meaning.
+  return UTF16ToUTF8(net::FormatUrl(url_table_model_->GetURL(row),
+      languages, net::kFormatUrlOmitAll & ~net::kFormatUrlOmitUsernamePassword,
+      UnescapeRule::SPACES, NULL, NULL, NULL));
+}
+
+void UrlPickerDialogGtk::SetColumnValues(int row, GtkTreeIter* iter) {
+  SkBitmap bitmap = url_table_model_->GetIcon(row);
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
+  string16 title = url_table_model_->GetText(row, IDS_ASI_PAGE_COLUMN);
+  string16 url = url_table_model_->GetText(row, IDS_ASI_URL_COLUMN);
+  gtk_list_store_set(history_list_store_, iter,
+                     COL_FAVICON, pixbuf,
+                     COL_TITLE, UTF16ToUTF8(title).c_str(),
+                     COL_DISPLAY_URL, UTF16ToUTF8(url).c_str(),
+                     -1);
+  g_object_unref(pixbuf);
+}
+
+// static
+gint UrlPickerDialogGtk::CompareTitle(GtkTreeModel* model,
+                                      GtkTreeIter* a,
+                                      GtkTreeIter* b,
+                                      gpointer window) {
+  int row1 = gtk_tree::GetRowNumForIter(model, a);
+  int row2 = gtk_tree::GetRowNumForIter(model, b);
+  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
+      CompareValues(row1, row2, IDS_ASI_PAGE_COLUMN);
+}
+
+// static
+gint UrlPickerDialogGtk::CompareURL(GtkTreeModel* model,
+                                    GtkTreeIter* a,
+                                    GtkTreeIter* b,
+                                    gpointer window) {
+  int row1 = gtk_tree::GetRowNumForIter(model, a);
+  int row2 = gtk_tree::GetRowNumForIter(model, b);
+  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
+      CompareValues(row1, row2, IDS_ASI_URL_COLUMN);
+}
+
+void UrlPickerDialogGtk::OnUrlEntryChanged(GtkWidget* editable) {
+  EnableControls();
+}
+
+void UrlPickerDialogGtk::OnHistorySelectionChanged(
+    GtkTreeSelection* selection) {
+  GtkTreeIter iter;
+  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
+    // The user has unselected the history element, nothing to do.
+    return;
+  }
+  GtkTreePath* path = gtk_tree_model_get_path(
+      GTK_TREE_MODEL(history_list_sort_), &iter);
+  gtk_entry_set_text(GTK_ENTRY(url_entry_),
+                     GetURLForPath(path).c_str());
+  gtk_tree_path_free(path);
+}
+
+void UrlPickerDialogGtk::OnHistoryRowActivated(GtkWidget* tree_view,
+                                               GtkTreePath* path,
+                                               GtkTreeViewColumn* column) {
+  callback_->Run(URLFixerUpper::FixupURL(GetURLForPath(path), std::string()));
+  gtk_widget_destroy(dialog_);
+}
+
+void UrlPickerDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
+  if (response_id == GTK_RESPONSE_OK)
+    AddURL();
+  gtk_widget_destroy(dialog_);
+}
+
+void UrlPickerDialogGtk::OnWindowDestroy(GtkWidget* widget) {
+  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
diff --git a/chrome/browser/ui/gtk/options/url_picker_dialog_gtk.h b/chrome/browser/ui/gtk/options/url_picker_dialog_gtk.h
new file mode 100644
index 0000000..2129f4c
--- /dev/null
+++ b/chrome/browser/ui/gtk/options/url_picker_dialog_gtk.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_OPTIONS_URL_PICKER_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OPTIONS_URL_PICKER_DIALOG_GTK_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class AccessibleWidgetHelper;
+class GURL;
+class Profile;
+class PossibleURLModel;
+
+class UrlPickerDialogGtk : public gtk_tree::TableAdapter::Delegate {
+ public:
+  typedef Callback1<const GURL&>::Type UrlPickerCallback;
+
+  UrlPickerDialogGtk(UrlPickerCallback* callback,
+                     Profile* profile,
+                     GtkWindow* parent);
+
+  ~UrlPickerDialogGtk();
+
+  // gtk_tree::TableAdapter::Delegate implementation.
+  virtual void SetColumnValues(int row, GtkTreeIter* iter);
+
+ private:
+  // Call the callback based on url entry.
+  void AddURL();
+
+  // Set sensitivity of buttons based on url entry state.
+  void EnableControls();
+
+  // Return the entry-formatted url for path in the sorted model.
+  std::string GetURLForPath(GtkTreePath* path) const;
+
+  // GTK sorting callbacks.
+  static gint CompareTitle(GtkTreeModel* model, GtkTreeIter* a, GtkTreeIter* b,
+                           gpointer window);
+  static gint CompareURL(GtkTreeModel* model, GtkTreeIter* a, GtkTreeIter* b,
+                         gpointer window);
+
+  CHROMEGTK_CALLBACK_0(UrlPickerDialogGtk, void, OnUrlEntryChanged);
+  CHROMEGTK_CALLBACK_2(UrlPickerDialogGtk, void, OnHistoryRowActivated,
+                       GtkTreePath*, GtkTreeViewColumn*);
+  CHROMEGTK_CALLBACK_1(UrlPickerDialogGtk, void, OnResponse, int);
+  CHROMEGTK_CALLBACK_0(UrlPickerDialogGtk, void, OnWindowDestroy);
+
+  // Callback for user selecting rows in recent history list.
+  CHROMEG_CALLBACK_0(UrlPickerDialogGtk, void, OnHistorySelectionChanged,
+                     GtkTreeSelection*)
+
+  // The dialog window.
+  GtkWidget* dialog_;
+
+  // The text entry for manually adding an URL.
+  GtkWidget* url_entry_;
+
+  // The add button (we need a reference to it so we can de-activate it when the
+  // |url_entry_| is empty.)
+  GtkWidget* add_button_;
+
+  // The recent history list.
+  GtkWidget* history_tree_;
+  GtkListStore* history_list_store_;
+  GtkTreeModel* history_list_sort_;
+  GtkTreeSelection* history_selection_;
+
+  // Profile.
+  Profile* profile_;
+
+  // The table model.
+  scoped_ptr<PossibleURLModel> url_table_model_;
+  scoped_ptr<gtk_tree::TableAdapter> url_table_adapter_;
+
+  // Called if the user selects an url.
+  UrlPickerCallback* callback_;
+
+  // Helper object to manage accessibility metadata.
+  scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(UrlPickerDialogGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OPTIONS_URL_PICKER_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/gtk/overflow_button.cc b/chrome/browser/ui/gtk/overflow_button.cc
new file mode 100644
index 0000000..45dcec4
--- /dev/null
+++ b/chrome/browser/ui/gtk/overflow_button.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/overflow_button.h"
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+
+OverflowButton::OverflowButton(Profile* profile) : profile_(profile) {
+  widget_.Own(GtkThemeProvider::GetFrom(profile)->BuildChromeButton());
+  gtk_widget_set_no_show_all(widget_.get(), TRUE);
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+  GtkThemeProvider::GetFrom(profile)->InitThemesFor(this);
+}
+
+OverflowButton::~OverflowButton() {
+  widget_.Destroy();
+}
+
+void OverflowButton::Observe(NotificationType type,
+                             const NotificationSource& source,
+                             const NotificationDetails& details) {
+  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(widget()));
+  if (former_child)
+    gtk_widget_destroy(former_child);
+
+  GtkWidget* new_child =
+      GtkThemeProvider::GetFrom(profile_)->UseGtkTheme() ?
+      gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE) :
+      gtk_image_new_from_pixbuf(ResourceBundle::GetSharedInstance().
+          GetRTLEnabledPixbufNamed(IDR_BOOKMARK_BAR_CHEVRONS));
+
+  gtk_container_add(GTK_CONTAINER(widget()), new_child);
+  gtk_widget_show(new_child);
+}
diff --git a/chrome/browser/ui/gtk/overflow_button.h b/chrome/browser/ui/gtk/overflow_button.h
new file mode 100644
index 0000000..298e5a2
--- /dev/null
+++ b/chrome/browser/ui/gtk/overflow_button.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_OVERFLOW_BUTTON_H_
+#define CHROME_BROWSER_UI_GTK_OVERFLOW_BUTTON_H_
+#pragma once
+
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+typedef struct _GtkWidget GtkWidget;
+class Profile;
+
+// An overflow chevron button. The button itself is a plain gtk_chrome_button,
+// and this class handles theming it.
+class OverflowButton : public NotificationObserver {
+ public:
+  explicit OverflowButton(Profile* profile);
+  virtual ~OverflowButton();
+
+  GtkWidget* widget() { return widget_.get(); }
+
+ private:
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  OwnedWidgetGtk widget_;
+
+  Profile* profile_;
+
+  NotificationRegistrar registrar_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OVERFLOW_BUTTON_H_
diff --git a/chrome/browser/ui/gtk/owned_widget_gtk.cc b/chrome/browser/ui/gtk/owned_widget_gtk.cc
new file mode 100644
index 0000000..5448115
--- /dev/null
+++ b/chrome/browser/ui/gtk/owned_widget_gtk.cc
@@ -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.
+
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+
+OwnedWidgetGtk::~OwnedWidgetGtk() {
+  DCHECK(!widget_) << "You must explicitly call OwnerWidgetGtk::Destroy().";
+}
+
+void OwnedWidgetGtk::Own(GtkWidget* widget) {
+  if (!widget)
+    return;
+
+  DCHECK(!widget_);
+  // We want to make sure that Own() was called properly, right after the
+  // widget was created. There should be a floating reference.
+  DCHECK(g_object_is_floating(widget));
+
+  // Sink the floating reference, we should now own this reference.
+  g_object_ref_sink(widget);
+  widget_ = widget;
+}
+
+void OwnedWidgetGtk::Destroy() {
+  if (!widget_)
+    return;
+
+  GtkWidget* widget = widget_;
+  widget_ = NULL;
+  gtk_widget_destroy(widget);
+
+  DCHECK(!g_object_is_floating(widget));
+  // NOTE: Assumes some implementation details about glib internals.
+  DCHECK_EQ(G_OBJECT(widget)->ref_count, 1U);
+  g_object_unref(widget);
+}
diff --git a/chrome/browser/ui/gtk/owned_widget_gtk.h b/chrome/browser/ui/gtk/owned_widget_gtk.h
new file mode 100644
index 0000000..aaa8fe9
--- /dev/null
+++ b/chrome/browser/ui/gtk/owned_widget_gtk.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 The Chromium 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 class assists you in dealing with a specific situation when managing
+// ownership between a C++ object and a GTK widget.  It is common to have a
+// C++ object which encapsulates a GtkWidget, and that widget is exposed from
+// the object for use outside of the class.  In this situation, you commonly
+// want the GtkWidget's lifetime to match its C++ object's lifetime.  Using an
+// OwnedWigetGtk will take ownership over the initial reference of the
+// GtkWidget, so that it is "owned" by the C++ object.  Example usage:
+//
+// class FooViewGtk() {
+//  public:
+//   FooViewGtk() { }
+//   ~FooViewGtk() { widget_.Destroy(); }
+//   void Init() { vbox_.Own(gtk_vbox_new()); }
+//   GtkWidget* widget() { return vbox_.get() };  // Host my widget!
+//  private:
+//   OwnedWidgetGtk vbox_;
+// };
+//
+// This design will ensure that the widget stays alive from the call to Own()
+// until the call to Destroy().
+//
+// - Details of the problem and OwnedWidgetGtk's solution:
+// In order to make passing ownership more convenient for newly created
+// widgets, GTK has a concept of a "floating" reference.  All GtkObjects (and
+// thus GtkWidgets) inherit from GInitiallyUnowned.  When they are created, the
+// object starts with a reference count of 1, but has its floating flag set.
+// When it is put into a container for the first time, that container will
+// "sink" the floating reference, and the count will still be 1.  Now the
+// container owns the widget, and if we remove the widget from the container,
+// the widget is destroyed.  This style of ownership often causes problems when
+// you have an object encapsulating the widget.  If we just use a raw
+// GtkObject* with no specific ownership management, we push the widget's
+// ownership onto the user of the class.  Now the C++ object can't depend on
+// the widget being valid, since it doesn't manage its lifetime.  If the widget
+// was removed from a container, removing its only reference, it would be
+// destroyed (from the C++ object's perspective) unexpectantly destroyed.  The
+// solution is fairly simple, make sure that the C++ object owns the widget,
+// and thus it is also responsible for destroying it.  This boils down to:
+//   GtkWidget* widget = gtk_widget_new();
+//   g_object_ref_sink(widget);  // Claim the initial floating reference.
+//   ...
+//   gtk_destroy_widget(widget);  // Ask all code to destroy their references.
+//   g_object_unref(widget);  // Destroy the initial reference we had claimed.
+
+#ifndef CHROME_BROWSER_UI_GTK_OWNED_WIDGET_GTK_H_
+#define CHROME_BROWSER_UI_GTK_OWNED_WIDGET_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class OwnedWidgetGtk {
+ public:
+  // Create an instance that isn't managing any ownership.
+  OwnedWidgetGtk() : widget_(NULL) { }
+  // Create an instance that owns |widget|.
+  explicit OwnedWidgetGtk(GtkWidget* widget) : widget_(NULL) { Own(widget); }
+
+  ~OwnedWidgetGtk();
+
+  // Return the currently owned widget, or NULL if no widget is owned.
+  GtkWidget* get() const { return widget_; }
+  GtkWidget* operator->() const { return widget_; }
+
+  // Takes ownership of a widget, by taking the initial floating reference of
+  // the GtkWidget.  It is expected that Own() is called right after the widget
+  // has been created, and before any other references to the widget might have
+  // been added.  It is valid to never call Own(), in which case Destroy() will
+  // do nothing.  If Own() has been called, you must explicitly call Destroy().
+  void Own(GtkWidget* widget);
+
+  // You must call Destroy() after you have called Own().  Calling Destroy()
+  // will call gtk_widget_destroy(), and drop our reference to the widget.
+  // After a call to Destroy(), you may call Own() again.  NOTE: It is expected
+  // that after gtk_widget_destroy we will be holding the only reference left
+  // on the object.  We assert this in debug mode to help catch any leaks.
+  void Destroy();
+
+ private:
+  GtkWidget* widget_;
+
+  DISALLOW_COPY_AND_ASSIGN(OwnedWidgetGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_OWNED_WIDGET_GTK_H_
diff --git a/chrome/browser/ui/gtk/page_info_bubble_gtk.cc b/chrome/browser/ui/gtk/page_info_bubble_gtk.cc
new file mode 100644
index 0000000..ffac6d6
--- /dev/null
+++ b/chrome/browser/ui/gtk/page_info_bubble_gtk.cc
@@ -0,0 +1,290 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+
+#include "build/build_config.h"
+
+#include "base/i18n/rtl.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/certificate_viewer.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/page_info_model.h"
+#include "chrome/browser/page_info_window.h"
+#include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/info_bubble_gtk.h"
+#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+class Profile;
+
+namespace {
+
+class PageInfoBubbleGtk : public PageInfoModel::PageInfoModelObserver,
+                          public InfoBubbleGtkDelegate,
+                          public NotificationObserver {
+ public:
+  PageInfoBubbleGtk(gfx::NativeWindow parent,
+                    Profile* profile,
+                    const GURL& url,
+                    const NavigationEntry::SSLStatus& ssl,
+                    bool show_history);
+  virtual ~PageInfoBubbleGtk();
+
+  // PageInfoModelObserver implementation:
+  virtual void ModelChanged();
+
+  // NotificationObserver implementation:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // InfoBubbleGtkDelegate implementation:
+  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                 bool closed_by_escape);
+
+ private:
+  // Layouts the different sections retrieved from the model.
+  void InitContents();
+
+  // Returns a widget that contains the UI for the passed |section|.
+  GtkWidget* CreateSection(const PageInfoModel::SectionInfo& section);
+
+  // Link button callbacks.
+  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnViewCertLinkClicked);
+  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnHelpLinkClicked);
+
+  // The model containing the different sections to display.
+  PageInfoModel model_;
+
+  // The url for this dialog. Should be unique among active dialogs.
+  GURL url_;
+
+  // The id of the certificate for this page.
+  int cert_id_;
+
+  // Parent window.
+  GtkWindow* parent_;
+
+  // The virtual box containing the sections.
+  GtkWidget* contents_;
+
+  // The widget relative to which we are positioned.
+  GtkWidget* anchor_;
+
+  // Provides colors and stuff.
+  GtkThemeProvider* theme_provider_;
+
+  // The various elements in the interface we keep track of for theme changes.
+  std::vector<GtkWidget*> labels_;
+  std::vector<GtkWidget*> links_;
+
+  InfoBubbleGtk* bubble_;
+
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleGtk);
+};
+
+PageInfoBubbleGtk::PageInfoBubbleGtk(gfx::NativeWindow parent,
+                                     Profile* profile,
+                                     const GURL& url,
+                                     const NavigationEntry::SSLStatus& ssl,
+                                     bool show_history)
+    : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
+                                            show_history, this)),
+      url_(url),
+      cert_id_(ssl.cert_id()),
+      parent_(parent),
+      contents_(NULL),
+      theme_provider_(GtkThemeProvider::GetFrom(profile)) {
+  BrowserWindowGtk* browser_window =
+      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
+
+  anchor_ = browser_window->
+      GetToolbar()->GetLocationBarView()->location_icon_widget();
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+
+  InitContents();
+
+  InfoBubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ?
+      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
+      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
+  bubble_ = InfoBubbleGtk::Show(anchor_,
+                                NULL,  // |rect|
+                                contents_,
+                                arrow_location,
+                                true,  // |match_system_theme|
+                                true,  // |grab_input|
+                                theme_provider_,
+                                this);  // |delegate|
+  if (!bubble_) {
+    NOTREACHED();
+    return;
+  }
+}
+
+PageInfoBubbleGtk::~PageInfoBubbleGtk() {
+}
+
+void PageInfoBubbleGtk::ModelChanged() {
+  InitContents();
+}
+
+void PageInfoBubbleGtk::Observe(NotificationType type,
+                                const NotificationSource& source,
+                                const NotificationDetails& details) {
+  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+
+  for (std::vector<GtkWidget*>::iterator it = links_.begin();
+       it != links_.end(); ++it) {
+    gtk_chrome_link_button_set_use_gtk_theme(
+        GTK_CHROME_LINK_BUTTON(*it),
+        theme_provider_->UseGtkTheme());
+  }
+
+  if (theme_provider_->UseGtkTheme()) {
+    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
+         it != labels_.end(); ++it) {
+      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
+    }
+  } else {
+    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
+         it != labels_.end(); ++it) {
+      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+    }
+  }
+}
+
+void PageInfoBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+                                          bool closed_by_escape) {
+  delete this;
+}
+
+void PageInfoBubbleGtk::InitContents() {
+  if (!contents_) {
+    contents_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
+    gtk_container_set_border_width(GTK_CONTAINER(contents_),
+                                   gtk_util::kContentAreaBorder);
+  } else {
+    labels_.clear();
+    links_.clear();
+    gtk_util::RemoveAllChildren(contents_);
+  }
+
+  for (int i = 0; i < model_.GetSectionCount(); i++) {
+    gtk_box_pack_start(GTK_BOX(contents_),
+                       CreateSection(model_.GetSectionInfo(i)),
+                       FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(contents_),
+                       gtk_hseparator_new(),
+                       FALSE, FALSE, 0);
+  }
+
+  GtkWidget* help_link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK).c_str());
+  links_.push_back(help_link);
+  GtkWidget* help_link_hbox = gtk_hbox_new(FALSE, 0);
+  // Stick it in an hbox so it doesn't expand to the whole width.
+  gtk_box_pack_start(GTK_BOX(help_link_hbox), help_link, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(contents_), help_link_hbox, FALSE, FALSE, 0);
+  g_signal_connect(help_link, "clicked",
+                   G_CALLBACK(OnHelpLinkClickedThunk), this);
+
+  theme_provider_->InitThemesFor(this);
+  gtk_widget_show_all(contents_);
+}
+
+GtkWidget* PageInfoBubbleGtk::CreateSection(
+    const PageInfoModel::SectionInfo& section) {
+  GtkWidget* section_box = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+
+  GdkPixbuf* pixbuf = model_.GetIconImage(section.icon_id);
+  if (pixbuf) {
+    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
+    gtk_box_pack_start(GTK_BOX(section_box), image, FALSE, FALSE, 0);
+    gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+  }
+
+  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(section_box), vbox, TRUE, TRUE, 0);
+
+  if (!section.headline.empty()) {
+    GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.headline).c_str());
+    labels_.push_back(label);
+    PangoAttrList* attributes = pango_attr_list_new();
+    pango_attr_list_insert(attributes,
+                           pango_attr_weight_new(PANGO_WEIGHT_BOLD));
+    gtk_label_set_attributes(GTK_LABEL(label), attributes);
+    pango_attr_list_unref(attributes);
+    gtk_util::SetLabelWidth(label, 400);
+    // Allow linebreaking in the middle of words if necessary, so that extremely
+    // long hostnames (longer than one line) will still be completely shown.
+    gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
+    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+  }
+  GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.description).c_str());
+  labels_.push_back(label);
+  gtk_util::SetLabelWidth(label, 400);
+  // Allow linebreaking in the middle of words if necessary, so that extremely
+  // long hostnames (longer than one line) will still be completely shown.
+  gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+  if (section.type == PageInfoModel::SECTION_INFO_IDENTITY && cert_id_ > 0) {
+    GtkWidget* view_cert_link = gtk_chrome_link_button_new(
+        l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
+    links_.push_back(view_cert_link);
+    GtkWidget* cert_link_hbox = gtk_hbox_new(FALSE, 0);
+    // Stick it in an hbox so it doesn't expand to the whole width.
+    gtk_box_pack_start(GTK_BOX(cert_link_hbox), view_cert_link,
+                       FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), cert_link_hbox, FALSE, FALSE, 0);
+    g_signal_connect(view_cert_link, "clicked",
+                     G_CALLBACK(OnViewCertLinkClickedThunk), this);
+  }
+
+  return section_box;
+}
+
+void PageInfoBubbleGtk::OnViewCertLinkClicked(GtkWidget* widget) {
+  ShowCertificateViewerByID(GTK_WINDOW(parent_), cert_id_);
+  bubble_->Close();
+}
+
+void PageInfoBubbleGtk::OnHelpLinkClicked(GtkWidget* widget) {
+  GURL url = google_util::AppendGoogleLocaleParam(
+      GURL(chrome::kPageInfoHelpCenterURL));
+  Browser* browser = BrowserList::GetLastActive();
+  browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
+  bubble_->Close();
+}
+
+}  // namespace
+
+namespace browser {
+
+void ShowPageInfoBubble(gfx::NativeWindow parent,
+                        Profile* profile,
+                        const GURL& url,
+                        const NavigationEntry::SSLStatus& ssl,
+                        bool show_history) {
+  new PageInfoBubbleGtk(parent, profile, url, ssl, show_history);
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/gtk/process_singleton_dialog.cc b/chrome/browser/ui/gtk/process_singleton_dialog.cc
new file mode 100644
index 0000000..78d91cf
--- /dev/null
+++ b/chrome/browser/ui/gtk/process_singleton_dialog.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/process_singleton_dialog.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/chromium_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// static
+void ProcessSingletonDialog::ShowAndRun(const std::string& message) {
+  ProcessSingletonDialog dialog(message);
+}
+
+ProcessSingletonDialog::ProcessSingletonDialog(const std::string& message) {
+  dialog_ = gtk_message_dialog_new(
+      NULL,
+      static_cast<GtkDialogFlags>(0),
+      GTK_MESSAGE_ERROR,
+      GTK_BUTTONS_NONE,
+      "%s",
+      message.c_str());
+  gtk_util::ApplyMessageDialogQuirks(dialog_);
+  gtk_window_set_title(GTK_WINDOW(dialog_),
+                       l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str());
+  gtk_dialog_add_button(GTK_DIALOG(dialog_), GTK_STOCK_QUIT,
+                        GTK_RESPONSE_REJECT);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
+
+  gtk_widget_show_all(dialog_);
+  MessageLoop::current()->Run();
+}
+
+// static
+void ProcessSingletonDialog::OnResponse(GtkWidget* widget, int response,
+                                        ProcessSingletonDialog* dialog) {
+  gtk_widget_destroy(dialog->dialog_);
+  MessageLoop::current()->Quit();
+}
diff --git a/chrome/browser/ui/gtk/process_singleton_dialog.h b/chrome/browser/ui/gtk/process_singleton_dialog.h
new file mode 100644
index 0000000..e46803e
--- /dev/null
+++ b/chrome/browser/ui/gtk/process_singleton_dialog.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_PROCESS_SINGLETON_DIALOG_H_
+#define CHROME_BROWSER_UI_GTK_PROCESS_SINGLETON_DIALOG_H_
+#pragma once
+
+#include <string>
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+
+// Displays an error to the user when the ProcessSingleton cannot acquire the
+// lock.  This runs the message loop itself as the browser message loop has not
+// started by that point in the startup process.
+class ProcessSingletonDialog {
+ public:
+  // Shows the dialog, and returns once the dialog has been closed.
+  static void ShowAndRun(const std::string& message);
+
+ private:
+  explicit ProcessSingletonDialog(const std::string& message);
+
+  static void OnResponse(GtkWidget* widget,
+                         int response,
+                         ProcessSingletonDialog* dialog);
+
+  GtkWidget* dialog_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessSingletonDialog);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_PROCESS_SINGLETON_DIALOG_H_
diff --git a/chrome/browser/ui/gtk/reload_button_gtk.cc b/chrome/browser/ui/gtk/reload_button_gtk.cc
new file mode 100644
index 0000000..4bed9fa
--- /dev/null
+++ b/chrome/browser/ui/gtk/reload_button_gtk.cc
@@ -0,0 +1,279 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/reload_button_gtk.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "chrome/common/notification_source.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// The width of this button in GTK+ theme mode. The Stop and Refresh stock icons
+// can be different sizes; this variable is used to make sure that the button
+// doesn't change sizes when switching between the two.
+static int GtkButtonWidth = 0;
+
+////////////////////////////////////////////////////////////////////////////////
+// ReloadButton, public:
+
+ReloadButtonGtk::ReloadButtonGtk(LocationBarViewGtk* location_bar,
+                                 Browser* browser)
+    : location_bar_(location_bar),
+      browser_(browser),
+      intended_mode_(MODE_RELOAD),
+      visible_mode_(MODE_RELOAD),
+      theme_provider_(browser ?
+                      GtkThemeProvider::GetFrom(browser->profile()) : NULL),
+      reload_(theme_provider_, IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0),
+      stop_(theme_provider_, IDR_STOP, IDR_STOP_P, IDR_STOP_H, IDR_STOP_D),
+      widget_(gtk_chrome_button_new()),
+      stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)),
+      testing_mouse_hovered_(false),
+      testing_reload_count_(0) {
+  gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height());
+
+  gtk_widget_set_app_paintable(widget(), TRUE);
+
+  g_signal_connect(widget(), "clicked", G_CALLBACK(OnClickedThunk), this);
+  g_signal_connect(widget(), "expose-event", G_CALLBACK(OnExposeThunk), this);
+  g_signal_connect(widget(), "leave-notify-event",
+                   G_CALLBACK(OnLeaveNotifyThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS);
+
+  gtk_widget_set_has_tooltip(widget(), TRUE);
+  g_signal_connect(widget(), "query-tooltip", G_CALLBACK(OnQueryTooltipThunk),
+                   this);
+
+  hover_controller_.Init(widget());
+  gtk_util::SetButtonTriggersNavigation(widget());
+
+  if (theme_provider_) {
+    theme_provider_->InitThemesFor(this);
+    registrar_.Add(this,
+                   NotificationType::BROWSER_THEME_CHANGED,
+                   Source<GtkThemeProvider>(theme_provider_));
+  }
+
+  // Set the default double-click timer delay to the system double-click time.
+  int timer_delay_ms;
+  GtkSettings* settings = gtk_settings_get_default();
+  g_object_get(G_OBJECT(settings), "gtk-double-click-time", &timer_delay_ms,
+               NULL);
+  double_click_timer_delay_ = base::TimeDelta::FromMilliseconds(timer_delay_ms);
+}
+
+ReloadButtonGtk::~ReloadButtonGtk() {
+  widget_.Destroy();
+}
+
+void ReloadButtonGtk::ChangeMode(Mode mode, bool force) {
+  intended_mode_ = mode;
+
+  // If the change is forced, or the user isn't hovering the icon, or it's safe
+  // to change it to the other image type, make the change immediately;
+  // otherwise we'll let it happen later.
+  if (force || ((GTK_WIDGET_STATE(widget()) == GTK_STATE_NORMAL) &&
+      !testing_mouse_hovered_) || ((mode == MODE_STOP) ?
+          !double_click_timer_.IsRunning() : (visible_mode_ != MODE_STOP))) {
+    double_click_timer_.Stop();
+    stop_to_reload_timer_.Stop();
+    visible_mode_ = mode;
+
+    stop_.set_paint_override(-1);
+    gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget_.get()));
+
+    UpdateThemeButtons();
+    gtk_widget_queue_draw(widget());
+  } else if (visible_mode_ != MODE_RELOAD) {
+    // If you read the views implementation of reload_button.cc, you'll see
+    // that instead of screwing with paint states, the views implementation
+    // just changes whether the view is enabled. We can't do that here because
+    // changing the widget state to GTK_STATE_INSENSITIVE will cause a cascade
+    // of messages on all its children and will also trigger a synthesized
+    // leave notification and prevent the real leave notification from turning
+    // the button back to normal. So instead, override the stop_ paint state
+    // for chrome-theme mode, and use this as a flag to discard click events.
+    stop_.set_paint_override(GTK_STATE_INSENSITIVE);
+
+    // Also set the gtk_chrome_button paint state to insensitive to hide
+    // the border drawn around the stop icon.
+    gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget_.get()),
+                                      GTK_STATE_INSENSITIVE);
+
+    // If we're in GTK theme mode, we need to also render the correct icon for
+    // the stop/insensitive since we won't be using |stop_| to render the icon.
+    UpdateThemeButtons();
+
+    // Go ahead and change to reload after a bit, which allows repeated reloads
+    // without moving the mouse.
+    if (!stop_to_reload_timer_.IsRunning()) {
+      stop_to_reload_timer_.Start(stop_to_reload_timer_delay_, this,
+                                  &ReloadButtonGtk::OnStopToReloadTimer);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReloadButtonGtk, NotificationObserver implementation:
+
+void ReloadButtonGtk::Observe(NotificationType type,
+                              const NotificationSource& source,
+                              const NotificationDetails& /* details */) {
+  DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
+
+  GtkThemeProvider* provider = static_cast<GtkThemeProvider*>(
+      Source<GtkThemeProvider>(source).ptr());
+  DCHECK_EQ(provider, theme_provider_);
+  GtkButtonWidth = 0;
+  UpdateThemeButtons();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReloadButtonGtk, private:
+
+void ReloadButtonGtk::OnClicked(GtkWidget* /* sender */) {
+  if (visible_mode_ == MODE_STOP) {
+    // Do nothing if Stop was disabled due to an attempt to change back to
+    // RELOAD mode while hovered.
+    if (stop_.paint_override() == GTK_STATE_INSENSITIVE)
+      return;
+
+    if (browser_)
+      browser_->Stop();
+
+    // The user has clicked, so we can feel free to update the button,
+    // even if the mouse is still hovering.
+    ChangeMode(MODE_RELOAD, true);
+  } else if (!double_click_timer_.IsRunning()) {
+    // Shift-clicking or Ctrl-clicking the reload button means we should ignore
+    // any cached content.
+    int command;
+    GdkModifierType modifier_state;
+    gtk_get_current_event_state(&modifier_state);
+    guint modifier_state_uint = modifier_state;
+    if (modifier_state_uint & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
+      command = IDC_RELOAD_IGNORING_CACHE;
+      // Mask off Shift and Control so they don't affect the disposition below.
+      modifier_state_uint &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+    } else {
+      command = IDC_RELOAD;
+    }
+
+    WindowOpenDisposition disposition =
+        event_utils::DispositionFromEventFlags(modifier_state_uint);
+    if ((disposition == CURRENT_TAB) && location_bar_) {
+      // Forcibly reset the location bar, since otherwise it won't discard any
+      // ongoing user edits, since it doesn't realize this is a user-initiated
+      // action.
+      location_bar_->Revert();
+    }
+
+    // Start a timer - while this timer is running, the reload button cannot be
+    // changed to a stop button.  We do not set |intended_mode_| to MODE_STOP
+    // here as the browser will do that when it actually starts loading (which
+    // may happen synchronously, thus the need to do this before telling the
+    // browser to execute the reload command).
+    double_click_timer_.Start(double_click_timer_delay_, this,
+                              &ReloadButtonGtk::OnDoubleClickTimer);
+
+    if (browser_)
+      browser_->ExecuteCommandWithDisposition(command, disposition);
+    ++testing_reload_count_;
+  }
+}
+
+gboolean ReloadButtonGtk::OnExpose(GtkWidget* widget,
+                                   GdkEventExpose* e) {
+  if (theme_provider_ && theme_provider_->UseGtkTheme())
+    return FALSE;
+  return ((visible_mode_ == MODE_RELOAD) ? reload_ : stop_).OnExpose(
+      widget, e, hover_controller_.GetCurrentValue());
+}
+
+gboolean ReloadButtonGtk::OnLeaveNotify(GtkWidget* /* widget */,
+                                        GdkEventCrossing* /* event */) {
+  ChangeMode(intended_mode_, true);
+  return FALSE;
+}
+
+gboolean ReloadButtonGtk::OnQueryTooltip(GtkWidget* /* sender */,
+                                         gint /* x */,
+                                         gint /* y */,
+                                         gboolean /* keyboard_mode */,
+                                         GtkTooltip* tooltip) {
+  // |location_bar_| can be NULL in tests.
+  if (!location_bar_)
+    return FALSE;
+
+  gtk_tooltip_set_text(tooltip, l10n_util::GetStringUTF8(
+      (visible_mode_ == MODE_RELOAD) ?
+      IDS_TOOLTIP_RELOAD : IDS_TOOLTIP_STOP).c_str());
+  return TRUE;
+}
+
+void ReloadButtonGtk::UpdateThemeButtons() {
+  bool use_gtk = theme_provider_ && theme_provider_->UseGtkTheme();
+
+  if (use_gtk) {
+    gtk_widget_ensure_style(widget());
+    GtkIconSet* icon_set = gtk_style_lookup_icon_set(
+        widget()->style,
+        (visible_mode_ == MODE_RELOAD) ? GTK_STOCK_REFRESH : GTK_STOCK_STOP);
+    if (icon_set) {
+      GtkStateType state = static_cast<GtkStateType>(
+          GTK_WIDGET_STATE(widget()));
+      if (visible_mode_ == MODE_STOP && stop_.paint_override() != -1)
+        state = static_cast<GtkStateType>(stop_.paint_override());
+
+      GdkPixbuf* pixbuf = gtk_icon_set_render_icon(
+          icon_set,
+          widget()->style,
+          gtk_widget_get_direction(widget()),
+          state,
+          GTK_ICON_SIZE_SMALL_TOOLBAR,
+          widget(),
+          NULL);
+
+      gtk_button_set_image(GTK_BUTTON(widget()),
+                           gtk_image_new_from_pixbuf(pixbuf));
+      g_object_unref(pixbuf);
+    }
+
+    gtk_widget_set_size_request(widget(), -1, -1);
+    GtkRequisition req;
+    gtk_widget_size_request(widget(), &req);
+    GtkButtonWidth = std::max(GtkButtonWidth, req.width);
+    gtk_widget_set_size_request(widget(), GtkButtonWidth, -1);
+
+    gtk_widget_set_app_paintable(widget(), FALSE);
+    gtk_widget_set_double_buffered(widget(), TRUE);
+  } else {
+    gtk_button_set_image(GTK_BUTTON(widget()), NULL);
+
+    gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height());
+
+    gtk_widget_set_app_paintable(widget(), TRUE);
+    // We effectively double-buffer by virtue of having only one image...
+    gtk_widget_set_double_buffered(widget(), FALSE);
+  }
+
+  gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(widget()), use_gtk);
+}
+
+void ReloadButtonGtk::OnDoubleClickTimer() {
+  ChangeMode(intended_mode_, false);
+}
+
+void ReloadButtonGtk::OnStopToReloadTimer() {
+  ChangeMode(intended_mode_, true);
+}
diff --git a/chrome/browser/ui/gtk/reload_button_gtk.h b/chrome/browser/ui/gtk/reload_button_gtk.h
new file mode 100644
index 0000000..442a739
--- /dev/null
+++ b/chrome/browser/ui/gtk/reload_button_gtk.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_RELOAD_BUTTON_GTK_H_
+#define CHROME_BROWSER_UI_GTK_RELOAD_BUTTON_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/timer.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class Browser;
+class GtkThemeProvider;
+class LocationBarViewGtk;
+class Task;
+
+class ReloadButtonGtk : public NotificationObserver {
+ public:
+  enum Mode { MODE_RELOAD = 0, MODE_STOP };
+
+  ReloadButtonGtk(LocationBarViewGtk* location_bar, Browser* browser);
+  ~ReloadButtonGtk();
+
+  GtkWidget* widget() const { return widget_.get(); }
+
+  // Ask for a specified button state.  If |force| is true this will be applied
+  // immediately.
+  void ChangeMode(Mode mode, bool force);
+
+  // Provide NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& /* details */);
+
+ private:
+  friend class ReloadButtonGtkTest;
+
+  CHROMEGTK_CALLBACK_0(ReloadButtonGtk, void, OnClicked);
+  CHROMEGTK_CALLBACK_1(ReloadButtonGtk, gboolean, OnExpose, GdkEventExpose*);
+  CHROMEGTK_CALLBACK_1(ReloadButtonGtk,
+                       gboolean,
+                       OnLeaveNotify,
+                       GdkEventCrossing*);
+  CHROMEGTK_CALLBACK_4(ReloadButtonGtk,
+                       gboolean,
+                       OnQueryTooltip,
+                       gint,
+                       gint,
+                       gboolean,
+                       GtkTooltip*);
+
+  void UpdateThemeButtons();
+
+  void OnDoubleClickTimer();
+  void OnStopToReloadTimer();
+
+  base::OneShotTimer<ReloadButtonGtk> double_click_timer_;
+  base::OneShotTimer<ReloadButtonGtk> stop_to_reload_timer_;
+
+  // These may be NULL when testing.
+  LocationBarViewGtk* const location_bar_;
+  Browser* const browser_;
+
+  // The mode we should be in assuming no timers are running.
+  Mode intended_mode_;
+
+  // The currently-visible mode - this may differ from the intended mode.
+  Mode visible_mode_;
+
+  // Used to listen for theme change notifications.
+  NotificationRegistrar registrar_;
+
+  GtkThemeProvider* theme_provider_;
+
+  CustomDrawButtonBase reload_;
+  CustomDrawButtonBase stop_;
+  CustomDrawHoverController hover_controller_;
+
+  OwnedWidgetGtk widget_;
+
+  // The delay times for the timers.  These are members so that tests can modify
+  // them.
+  base::TimeDelta double_click_timer_delay_;
+  base::TimeDelta stop_to_reload_timer_delay_;
+
+  // TESTING ONLY
+  // True if we should pretend the button is hovered.
+  bool testing_mouse_hovered_;
+  // Increments when we would tell the browser to "reload", so
+  // test code can tell whether we did so (as there may be no |browser_|).
+  int testing_reload_count_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ReloadButtonGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_RELOAD_BUTTON_GTK_H_
diff --git a/chrome/browser/ui/gtk/reload_button_gtk_unittest.cc b/chrome/browser/ui/gtk/reload_button_gtk_unittest.cc
new file mode 100644
index 0000000..6a612d8
--- /dev/null
+++ b/chrome/browser/ui/gtk/reload_button_gtk_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 The Chromium 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/message_loop.h"
+#include "chrome/browser/ui/gtk/reload_button_gtk.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class ReloadButtonGtkTest : public testing::Test {
+ public:
+  ReloadButtonGtkTest();
+
+  void CheckState(bool enabled,
+                  ReloadButtonGtk::Mode intended_mode,
+                  ReloadButtonGtk::Mode visible_mode,
+                  bool double_click_timer_running,
+                  bool stop_to_reload_timer_running);
+
+  // These accessors eliminate the need to declare each testcase as a friend.
+  void set_mouse_hovered(bool hovered) {
+    reload_.testing_mouse_hovered_ = hovered;
+  }
+  int reload_count() { return reload_.testing_reload_count_; }
+  void fake_mouse_leave() { reload_.OnLeaveNotify(reload_.widget(), NULL); }
+
+ protected:
+  // We need a message loop for the timers to post events.
+  MessageLoop loop_;
+
+  ReloadButtonGtk reload_;
+};
+
+ReloadButtonGtkTest::ReloadButtonGtkTest() : reload_(NULL, NULL) {
+  // Set the timer delays to 0 so that timers will fire as soon as we tell the
+  // message loop to run pending tasks.
+  reload_.double_click_timer_delay_ = base::TimeDelta();
+  reload_.stop_to_reload_timer_delay_ = base::TimeDelta();
+}
+
+void ReloadButtonGtkTest::CheckState(bool enabled,
+                                     ReloadButtonGtk::Mode intended_mode,
+                                     ReloadButtonGtk::Mode visible_mode,
+                                     bool double_click_timer_running,
+                                     bool stop_to_reload_timer_running) {
+  EXPECT_NE(enabled, reload_.stop_.paint_override() == GTK_STATE_INSENSITIVE);
+  EXPECT_EQ(intended_mode, reload_.intended_mode_);
+  EXPECT_EQ(visible_mode, reload_.visible_mode_);
+  EXPECT_EQ(double_click_timer_running,
+            reload_.double_click_timer_.IsRunning());
+  EXPECT_EQ(stop_to_reload_timer_running,
+            reload_.stop_to_reload_timer_.IsRunning());
+}
+
+TEST_F(ReloadButtonGtkTest, Basic) {
+  // The stop/reload button starts in the "enabled reload" state with no timers
+  // running.
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             false, false);
+
+  // Press the button.  This should start the double-click timer.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             true, false);
+
+  // Now change the mode (as if the browser had started loading the page).  This
+  // should cancel the double-click timer since the button is not hovered.
+  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
+  CheckState(true, ReloadButtonGtk::MODE_STOP, ReloadButtonGtk::MODE_STOP,
+             false, false);
+
+  // Press the button again.  This should change back to reload.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             false, false);
+}
+
+TEST_F(ReloadButtonGtkTest, DoubleClickTimer) {
+  // Start by pressing the button.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+
+  // Try to press the button again.  This should do nothing because the timer is
+  // running.
+  int original_reload_count = reload_count();
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             true, false);
+  EXPECT_EQ(original_reload_count, reload_count());
+
+  // Hover the button, and change mode.  The visible mode should not change,
+  // again because the timer is running.
+  set_mouse_hovered(true);
+  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
+  CheckState(true, ReloadButtonGtk::MODE_STOP, ReloadButtonGtk::MODE_RELOAD,
+             true, false);
+
+  // Now fire the timer.  This should complete the mode change.
+  loop_.RunAllPending();
+  CheckState(true, ReloadButtonGtk::MODE_STOP, ReloadButtonGtk::MODE_STOP,
+             false, false);
+}
+
+TEST_F(ReloadButtonGtkTest, DisableOnHover) {
+  // Change to stop and hover.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
+  set_mouse_hovered(true);
+
+  // Now change back to reload.  This should result in a disabled stop button
+  // due to the hover.
+  reload_.ChangeMode(ReloadButtonGtk::MODE_RELOAD, false);
+  CheckState(false, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_STOP,
+             false, true);
+
+  // Un-hover the button, which should allow it to reset.
+  set_mouse_hovered(false);
+  fake_mouse_leave();
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             false, false);
+}
+
+TEST_F(ReloadButtonGtkTest, ResetOnClick) {
+  // Change to stop and hover.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
+  set_mouse_hovered(true);
+
+  // Press the button.  This should change back to reload despite the hover,
+  // because it's a direct user action.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             false, false);
+}
+
+TEST_F(ReloadButtonGtkTest, ResetOnTimer) {
+  // Change to stop, hover, and change back to reload.
+  gtk_button_clicked(GTK_BUTTON(reload_.widget()));
+  reload_.ChangeMode(ReloadButtonGtk::MODE_STOP, false);
+  set_mouse_hovered(true);
+  reload_.ChangeMode(ReloadButtonGtk::MODE_RELOAD, false);
+
+  // Now fire the stop-to-reload timer.  This should reset the button.
+  loop_.RunAllPending();
+  CheckState(true, ReloadButtonGtk::MODE_RELOAD, ReloadButtonGtk::MODE_RELOAD,
+             false, false);
+}
diff --git a/chrome/browser/ui/gtk/repost_form_warning_gtk.cc b/chrome/browser/ui/gtk/repost_form_warning_gtk.cc
new file mode 100644
index 0000000..68aa14e
--- /dev/null
+++ b/chrome/browser/ui/gtk/repost_form_warning_gtk.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/repost_form_warning_gtk.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/repost_form_warning_controller.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_type.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+RepostFormWarningGtk::RepostFormWarningGtk(GtkWindow* parent,
+                                           TabContents* tab_contents)
+    : controller_(new RepostFormWarningController(tab_contents)) {
+  dialog_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaBorder);
+  gtk_box_set_spacing(GTK_BOX(dialog_), gtk_util::kContentAreaSpacing);
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_HTTP_POST_WARNING).c_str());
+  GtkWidget* image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,
+                                              GTK_ICON_SIZE_DIALOG);
+  gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0);
+
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+
+  GtkWidget *hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+
+  gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+
+  gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+
+  gtk_box_pack_start(GTK_BOX(dialog_), hbox, FALSE, FALSE, 0);
+
+  GtkWidget* buttonBox = gtk_hbutton_box_new();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END);
+  gtk_box_set_spacing(GTK_BOX(buttonBox), gtk_util::kControlSpacing);
+  gtk_box_pack_end(GTK_BOX(dialog_), buttonBox, FALSE, TRUE, 0);
+
+  cancel_ = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+  gtk_button_set_label(GTK_BUTTON(cancel_),
+                       l10n_util::GetStringUTF8(IDS_CANCEL).c_str());
+  g_signal_connect(cancel_, "clicked", G_CALLBACK(OnCancelThunk), this);
+  gtk_box_pack_end(GTK_BOX(buttonBox), cancel_, FALSE, TRUE, 0);
+
+  ok_ = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
+  gtk_button_set_label(
+      GTK_BUTTON(ok_),
+      l10n_util::GetStringUTF8(IDS_HTTP_POST_WARNING_RESEND).c_str());
+  g_signal_connect(ok_, "clicked", G_CALLBACK(OnRefreshThunk), this);
+  gtk_box_pack_end(GTK_BOX(buttonBox), ok_, FALSE, TRUE, 0);
+
+  g_signal_connect(cancel_, "hierarchy-changed",
+                   G_CALLBACK(OnHierarchyChangedThunk), this);
+
+  controller_->Show(this);
+}
+
+GtkWidget* RepostFormWarningGtk::GetWidgetRoot() {
+  return dialog_;
+}
+
+void RepostFormWarningGtk::DeleteDelegate() {
+  delete this;
+}
+
+RepostFormWarningGtk::~RepostFormWarningGtk() {
+  gtk_widget_destroy(dialog_);
+}
+
+void RepostFormWarningGtk::OnRefresh(GtkWidget* widget) {
+  controller_->Continue();
+}
+
+void RepostFormWarningGtk::OnCancel(GtkWidget* widget) {
+  controller_->Cancel();
+}
+
+void RepostFormWarningGtk::OnHierarchyChanged(GtkWidget* root,
+                                              GtkWidget* previous_toplevel) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(cancel_))) {
+    return;
+  }
+  gtk_widget_grab_focus(cancel_);
+}
diff --git a/chrome/browser/ui/gtk/repost_form_warning_gtk.h b/chrome/browser/ui/gtk/repost_form_warning_gtk.h
new file mode 100644
index 0000000..6fa7cef
--- /dev/null
+++ b/chrome/browser/ui/gtk/repost_form_warning_gtk.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_REPOST_FORM_WARNING_GTK_H_
+#define CHROME_BROWSER_UI_GTK_REPOST_FORM_WARNING_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class RepostFormWarningController;
+
+// Displays a dialog that warns the user that they are about to resubmit
+// a form.
+// To display the dialog, allocate this object on the heap. It will open the
+// dialog from its constructor and then delete itself when the user dismisses
+// the dialog.
+class RepostFormWarningGtk : public ConstrainedDialogDelegate {
+ public:
+  RepostFormWarningGtk(GtkWindow* parent, TabContents* tab_contents);
+
+  // ConstrainedDialogDelegate methods
+  virtual GtkWidget* GetWidgetRoot();
+
+  virtual void DeleteDelegate();
+
+ private:
+  virtual ~RepostFormWarningGtk();
+
+  // Callbacks
+  CHROMEGTK_CALLBACK_0(RepostFormWarningGtk, void, OnRefresh);
+  CHROMEGTK_CALLBACK_0(RepostFormWarningGtk, void, OnCancel);
+  CHROMEGTK_CALLBACK_1(RepostFormWarningGtk,
+                       void,
+                       OnHierarchyChanged,
+                       GtkWidget*);
+
+  scoped_ptr<RepostFormWarningController> controller_;
+
+  GtkWidget* dialog_;
+  GtkWidget* ok_;
+  GtkWidget* cancel_;
+
+  DISALLOW_COPY_AND_ASSIGN(RepostFormWarningGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_REPOST_FORM_WARNING_GTK_H_
diff --git a/chrome/browser/ui/gtk/rounded_window.cc b/chrome/browser/ui/gtk/rounded_window.cc
new file mode 100644
index 0000000..3f8b6e4
--- /dev/null
+++ b/chrome/browser/ui/gtk/rounded_window.cc
@@ -0,0 +1,321 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/rounded_window.h"
+
+#include <gtk/gtk.h>
+#include <math.h>
+
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+
+namespace gtk_util {
+
+namespace {
+
+const char* kRoundedData = "rounded-window-data";
+
+// If the border radius is less than |kMinRoundedBorderSize|, we don't actually
+// round the corners, we just truncate the corner.
+const int kMinRoundedBorderSize = 8;
+
+struct RoundedWindowData {
+  // Expected window size. Used to detect when we need to reshape the window.
+  int expected_width;
+  int expected_height;
+
+  // Color of the border.
+  GdkColor border_color;
+
+  // Radius of the edges in pixels.
+  int corner_size;
+
+  // Which corners should be rounded?
+  int rounded_edges;
+
+  // Which sides of the window should have an internal border?
+  int drawn_borders;
+
+  // Keeps track of attached signal handlers.
+  ui::GtkSignalRegistrar signals;
+};
+
+// Callback from GTK to release allocated memory.
+void FreeRoundedWindowData(gpointer data) {
+  delete static_cast<RoundedWindowData*>(data);
+}
+
+enum FrameType {
+  FRAME_MASK,
+  FRAME_STROKE,
+};
+
+// Returns a list of points that either form the outline of the status bubble
+// (|type| == FRAME_MASK) or form the inner border around the inner edge
+// (|type| == FRAME_STROKE).
+std::vector<GdkPoint> MakeFramePolygonPoints(RoundedWindowData* data,
+                                             FrameType type) {
+  using gtk_util::MakeBidiGdkPoint;
+  int width = data->expected_width;
+  int height = data->expected_height;
+  int corner_size = data->corner_size;
+
+  std::vector<GdkPoint> points;
+
+  bool ltr = !base::i18n::IsRTL();
+  // If we have a stroke, we have to offset some of our points by 1 pixel.
+  // We have to inset by 1 pixel when we draw horizontal lines that are on the
+  // bottom or when we draw vertical lines that are closer to the end (end is
+  // right for ltr).
+  int y_off = (type == FRAME_MASK) ? 0 : -1;
+  // We use this one for LTR.
+  int x_off_l = ltr ? y_off : 0;
+  // We use this one for RTL.
+  int x_off_r = !ltr ? -y_off : 0;
+
+  // Build up points starting with the bottom left corner and continuing
+  // clockwise.
+
+  // Bottom left corner.
+  if (type == FRAME_MASK ||
+      (data->drawn_borders & (BORDER_LEFT | BORDER_BOTTOM))) {
+    if (data->rounded_edges & ROUNDED_BOTTOM_LEFT) {
+      if (corner_size >= kMinRoundedBorderSize) {
+        // We are careful to only add points that are horizontal or vertically
+        // offset from the previous point (not both).  This avoids rounding
+        // differences when two points are connected.
+        for (int x = 0; x <= corner_size; ++x) {
+          int y = static_cast<int>(sqrt(static_cast<double>(
+              (corner_size * corner_size) - (x * x))));
+          if (x > 0) {
+            points.push_back(MakeBidiGdkPoint(
+                corner_size - x + x_off_r + 1,
+                height - (corner_size - y) + y_off, width, ltr));
+          }
+          points.push_back(MakeBidiGdkPoint(
+              corner_size - x + x_off_r,
+              height - (corner_size - y) + y_off, width, ltr));
+        }
+      } else {
+        points.push_back(MakeBidiGdkPoint(
+            corner_size + x_off_l, height + y_off, width, ltr));
+        points.push_back(MakeBidiGdkPoint(
+            x_off_r, height - corner_size, width, ltr));
+      }
+    } else {
+      points.push_back(MakeBidiGdkPoint(x_off_r, height + y_off, width, ltr));
+    }
+  }
+
+  // Top left corner.
+  if (type == FRAME_MASK ||
+      (data->drawn_borders & (BORDER_LEFT | BORDER_TOP))) {
+    if (data->rounded_edges & ROUNDED_TOP_LEFT) {
+      if (corner_size >= kMinRoundedBorderSize) {
+        for (int x = corner_size; x >= 0; --x) {
+          int y = static_cast<int>(sqrt(static_cast<double>(
+              (corner_size * corner_size) - (x * x))));
+          points.push_back(MakeBidiGdkPoint(corner_size - x + x_off_r,
+              corner_size - y, width, ltr));
+          if (x > 0) {
+            points.push_back(MakeBidiGdkPoint(corner_size - x + 1 + x_off_r,
+                corner_size - y, width, ltr));
+          }
+        }
+      } else {
+        points.push_back(MakeBidiGdkPoint(
+            x_off_r, corner_size - 1, width, ltr));
+        points.push_back(MakeBidiGdkPoint(
+            corner_size + x_off_r - 1, 0, width, ltr));
+      }
+    } else {
+      points.push_back(MakeBidiGdkPoint(x_off_r, 0, width, ltr));
+    }
+  }
+
+  // Top right corner.
+  if (type == FRAME_MASK ||
+      (data->drawn_borders & (BORDER_TOP | BORDER_RIGHT))) {
+    if (data->rounded_edges & ROUNDED_TOP_RIGHT) {
+      if (corner_size >= kMinRoundedBorderSize) {
+        for (int x = 0; x <= corner_size; ++x) {
+          int y = static_cast<int>(sqrt(static_cast<double>(
+              (corner_size * corner_size) - (x * x))));
+          if (x > 0) {
+            points.push_back(MakeBidiGdkPoint(
+                width - (corner_size - x) + x_off_l - 1,
+                corner_size - y, width, ltr));
+          }
+          points.push_back(MakeBidiGdkPoint(
+              width - (corner_size - x) + x_off_l,
+              corner_size - y, width, ltr));
+        }
+      } else {
+        points.push_back(MakeBidiGdkPoint(
+            width - corner_size + 1 + x_off_l, 0, width, ltr));
+        points.push_back(MakeBidiGdkPoint(
+            width + x_off_l, corner_size - 1, width, ltr));
+      }
+    } else {
+      points.push_back(MakeBidiGdkPoint(
+          width + x_off_l, 0, width, ltr));
+    }
+  }
+
+  // Bottom right corner.
+  if (type == FRAME_MASK ||
+      (data->drawn_borders & (BORDER_RIGHT | BORDER_BOTTOM))) {
+    if (data->rounded_edges & ROUNDED_BOTTOM_RIGHT) {
+      if (corner_size >= kMinRoundedBorderSize) {
+        for (int x = corner_size; x >= 0; --x) {
+          int y = static_cast<int>(sqrt(static_cast<double>(
+              (corner_size * corner_size) - (x * x))));
+          points.push_back(MakeBidiGdkPoint(
+              width - (corner_size - x) + x_off_l,
+              height - (corner_size - y) + y_off, width, ltr));
+          if (x > 0) {
+            points.push_back(MakeBidiGdkPoint(
+                width - (corner_size - x) + x_off_l - 1,
+                height - (corner_size - y) + y_off, width, ltr));
+          }
+        }
+      } else {
+        points.push_back(MakeBidiGdkPoint(
+            width + x_off_l, height - corner_size, width, ltr));
+        points.push_back(MakeBidiGdkPoint(
+            width - corner_size + x_off_r, height + y_off, width, ltr));
+      }
+    } else {
+      points.push_back(MakeBidiGdkPoint(
+          width + x_off_l, height + y_off, width, ltr));
+    }
+  }
+
+  return points;
+}
+
+// Set the window shape in needed, lets our owner do some drawing (if it wants
+// to), and finally draw the border.
+gboolean OnRoundedWindowExpose(GtkWidget* widget,
+                               GdkEventExpose* event) {
+  RoundedWindowData* data = static_cast<RoundedWindowData*>(
+      g_object_get_data(G_OBJECT(widget), kRoundedData));
+
+  if (data->expected_width != widget->allocation.width ||
+      data->expected_height != widget->allocation.height) {
+    data->expected_width = widget->allocation.width;
+    data->expected_height = widget->allocation.height;
+
+    // We need to update the shape of the status bubble whenever our GDK
+    // window changes shape.
+    std::vector<GdkPoint> mask_points = MakeFramePolygonPoints(
+        data, FRAME_MASK);
+    GdkRegion* mask_region = gdk_region_polygon(&mask_points[0],
+                                                mask_points.size(),
+                                                GDK_EVEN_ODD_RULE);
+    gdk_window_shape_combine_region(widget->window, mask_region, 0, 0);
+    gdk_region_destroy(mask_region);
+  }
+
+  GdkDrawable* drawable = GDK_DRAWABLE(event->window);
+  GdkGC* gc = gdk_gc_new(drawable);
+  gdk_gc_set_clip_rectangle(gc, &event->area);
+  gdk_gc_set_rgb_fg_color(gc, &data->border_color);
+
+  // Stroke the frame border.
+  std::vector<GdkPoint> points = MakeFramePolygonPoints(
+      data, FRAME_STROKE);
+  if (data->drawn_borders == BORDER_ALL) {
+    // If we want to have borders everywhere, we need to draw a polygon instead
+    // of a set of lines.
+    gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
+  } else if (points.size() > 0) {
+    gdk_draw_lines(drawable, gc, &points[0], points.size());
+  }
+
+  g_object_unref(gc);
+  return FALSE;  // Propagate so our children paint, etc.
+}
+
+// On theme changes, window shapes are reset, but we detect whether we need to
+// reshape a window by whether its allocation has changed so force it to reset
+// the window shape on next expose.
+void OnStyleSet(GtkWidget* widget, GtkStyle* previous_style) {
+  DCHECK(widget);
+  RoundedWindowData* data = static_cast<RoundedWindowData*>(
+      g_object_get_data(G_OBJECT(widget), kRoundedData));
+  DCHECK(data);
+  data->expected_width = -1;
+  data->expected_height = -1;
+}
+
+}  // namespace
+
+void ActAsRoundedWindow(
+    GtkWidget* widget, const GdkColor& color, int corner_size,
+    int rounded_edges, int drawn_borders) {
+  DCHECK(widget);
+  DCHECK(!g_object_get_data(G_OBJECT(widget), kRoundedData));
+
+  gtk_widget_set_app_paintable(widget, TRUE);
+
+  RoundedWindowData* data = new RoundedWindowData;
+  data->signals.Connect(widget, "expose-event",
+                        G_CALLBACK(OnRoundedWindowExpose), NULL);
+  data->signals.Connect(widget, "style-set", G_CALLBACK(OnStyleSet), NULL);
+
+  data->expected_width = -1;
+  data->expected_height = -1;
+
+  data->border_color = color;
+  data->corner_size = corner_size;
+
+  data->rounded_edges = rounded_edges;
+  data->drawn_borders = drawn_borders;
+
+  g_object_set_data_full(G_OBJECT(widget), kRoundedData,
+                         data, FreeRoundedWindowData);
+
+  if (GTK_WIDGET_VISIBLE(widget))
+    gtk_widget_queue_draw(widget);
+}
+
+void StopActingAsRoundedWindow(GtkWidget* widget) {
+  g_object_set_data(G_OBJECT(widget), kRoundedData, NULL);
+
+  if (GTK_WIDGET_REALIZED(widget))
+    gdk_window_shape_combine_mask(widget->window, NULL, 0, 0);
+
+  if (GTK_WIDGET_VISIBLE(widget))
+    gtk_widget_queue_draw(widget);
+}
+
+bool IsActingAsRoundedWindow(GtkWidget* widget) {
+  return g_object_get_data(G_OBJECT(widget), kRoundedData) != NULL;
+}
+
+void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
+                                     int corner_size,
+                                     int rounded_edges,
+                                     int drawn_borders) {
+  DCHECK(widget);
+  RoundedWindowData* data = static_cast<RoundedWindowData*>(
+      g_object_get_data(G_OBJECT(widget), kRoundedData));
+  DCHECK(data);
+  data->corner_size = corner_size;
+  data->rounded_edges = rounded_edges;
+  data->drawn_borders = drawn_borders;
+}
+
+void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color) {
+  DCHECK(widget);
+  RoundedWindowData* data = static_cast<RoundedWindowData*>(
+      g_object_get_data(G_OBJECT(widget), kRoundedData));
+  DCHECK(data);
+  data->border_color = color;
+}
+
+}  // namespace gtk_util
diff --git a/chrome/browser/ui/gtk/rounded_window.h b/chrome/browser/ui/gtk/rounded_window.h
new file mode 100644
index 0000000..52b611f
--- /dev/null
+++ b/chrome/browser/ui/gtk/rounded_window.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_ROUNDED_WINDOW_H_
+#define CHROME_BROWSER_UI_GTK_ROUNDED_WINDOW_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+namespace gtk_util {
+
+// Symbolic names for arguments to |rounded_edges| in ActAsRoundedWindow().
+enum RoundedBorders {
+  ROUNDED_NONE = 0,
+  ROUNDED_BOTTOM_LEFT = 1 << 0,
+  ROUNDED_TOP_LEFT = 1 << 1,
+  ROUNDED_TOP_RIGHT = 1 << 2,
+  ROUNDED_TOP = (1 << 1) | (1 << 2),
+  ROUNDED_BOTTOM_RIGHT = 1 << 3,
+  ROUNDED_ALL = 0xF
+};
+
+// Symbolic names for arguments to |drawn_borders| in ActAsRoundedWindow().
+enum BorderEdge {
+  BORDER_NONE = 0,
+  BORDER_LEFT = 1 << 0,
+  BORDER_TOP = 1 << 1,
+  BORDER_RIGHT = 1 << 2,
+  BORDER_BOTTOM = 1 << 3,
+  BORDER_ALL = 0xF
+};
+
+// Sets up the passed in widget that has its own GdkWindow with an expose
+// handler that forces the window shape into roundness. Caller should not set
+// an "expose-event" handler on |widget|; if caller needs to do custom
+// rendering, use SetRoundedWindowExposeFunction() instead. |rounded_edges|
+// control which corners are rounded. |drawn_borders| border control which
+// sides have a visible border drawn in |color|.
+void ActAsRoundedWindow(
+    GtkWidget* widget, const GdkColor& color, int corner_size,
+    int rounded_edges, int drawn_borders);
+
+// Undoes most of the actions of ActAsRoundedWindow().
+void StopActingAsRoundedWindow(GtkWidget* widget);
+
+// Returns true if the window is rounded.
+bool IsActingAsRoundedWindow(GtkWidget* widget);
+
+// Sets edge and border properties on a widget that has already been configured
+// with ActAsRoundedWindow().
+void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
+                                     int corner_size,
+                                     int rounded_edges,
+                                     int drawn_borders);
+
+// Sets the color of the border on a widget that has already been configured
+// with ActAsRoundedWindow().
+void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color);
+
+
+}  // namespace gtk_util
+
+#endif  // CHROME_BROWSER_UI_GTK_ROUNDED_WINDOW_H_
diff --git a/chrome/browser/ui/gtk/sad_tab_gtk.cc b/chrome/browser/ui/gtk/sad_tab_gtk.cc
new file mode 100644
index 0000000..ba0eec7
--- /dev/null
+++ b/chrome/browser/ui/gtk/sad_tab_gtk.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/sad_tab_gtk.h"
+
+#include <string>
+
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/url_constants.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+// Background color of the content (a grayish blue) for a crashed tab.
+const GdkColor kCrashedBackgroundColor = GDK_COLOR_RGB(35, 48, 64);
+
+// Background color of the content (a grayish purple) for a killed
+// tab.  TODO(gspencer): update this for the "real" color when the UI
+// team provides one.  See http://crosbug.com/10711
+const GdkColor kKilledBackgroundColor = GDK_COLOR_RGB(57, 48, 88);
+
+// Construct a centered GtkLabel with a white foreground.
+// |format| is a printf-style format containing a %s;
+// |str| is substituted into the format.
+GtkWidget* MakeWhiteMarkupLabel(const char* format, const std::string& str) {
+  GtkWidget* label = gtk_label_new(NULL);
+  char* markup = g_markup_printf_escaped(format, str.c_str());
+  gtk_label_set_markup(GTK_LABEL(label), markup);
+  g_free(markup);
+
+  // Center align and justify it.
+  gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
+  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
+
+  // Set text to white.
+  GdkColor white = gtk_util::kGdkWhite;
+  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &white);
+
+  return label;
+}
+
+}  // namespace
+
+SadTabGtk::SadTabGtk(TabContents* tab_contents, Kind kind)
+    : tab_contents_(tab_contents),
+      kind_(kind) {
+  DCHECK(tab_contents_);
+
+  // Use an event box to get the background painting correctly.
+  event_box_.Own(gtk_event_box_new());
+  gtk_widget_modify_bg(event_box_.get(), GTK_STATE_NORMAL,
+                       kind == CRASHED ?
+                       &kCrashedBackgroundColor :
+                       &kKilledBackgroundColor);
+  // Allow ourselves to be resized arbitrarily small.
+  gtk_widget_set_size_request(event_box_.get(), 0, 0);
+
+  GtkWidget* centering = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
+  gtk_container_add(GTK_CONTAINER(event_box_.get()), centering);
+
+  // Use a vertical box to contain icon, title, message and link.
+  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(centering), vbox);
+
+  // Add center-aligned image.
+  GtkWidget* image = gtk_image_new_from_pixbuf(
+      ResourceBundle::GetSharedInstance().GetPixbufNamed(kind == CRASHED ?
+                                                         IDR_SAD_TAB :
+                                                         IDR_KILLED_TAB));
+  gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5);
+  gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
+
+  // Add spacer between image and title.
+  GtkWidget* spacer = gtk_label_new(NULL);
+  gtk_label_set_markup(GTK_LABEL(spacer), "<span size=\"larger\"> </span>");
+  gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
+
+  // Add center-aligned title.
+  GtkWidget* title = MakeWhiteMarkupLabel(
+      "<span size=\"larger\" style=\"normal\"><b>%s</b></span>",
+      l10n_util::GetStringUTF8(kind == CRASHED ?
+                               IDS_SAD_TAB_TITLE :
+                               IDS_KILLED_TAB_TITLE));
+  gtk_box_pack_start(GTK_BOX(vbox), title, FALSE, FALSE, 0);
+
+  // Add spacer between title and message.
+  spacer = gtk_label_new(" ");
+  gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
+
+  // Add center-aligned message.
+  GtkWidget* message = MakeWhiteMarkupLabel(
+      "<span style=\"normal\">%s</span>",
+      l10n_util::GetStringUTF8(kind == CRASHED ?
+                               IDS_SAD_TAB_MESSAGE :
+                               IDS_KILLED_TAB_MESSAGE));
+  gtk_label_set_line_wrap(GTK_LABEL(message), TRUE);
+  gtk_box_pack_start(GTK_BOX(vbox), message, FALSE, FALSE, 0);
+
+  // Add spacer between message and link.
+  spacer = gtk_label_new(" ");
+  gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
+
+  if (tab_contents_ != NULL) {
+    // Add the learn-more link and center-align it in an alignment.
+    GtkWidget* link = gtk_chrome_link_button_new(
+        l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
+    gtk_chrome_link_button_set_normal_color(GTK_CHROME_LINK_BUTTON(link),
+                                            &gtk_util::kGdkWhite);
+    g_signal_connect(link, "clicked", G_CALLBACK(OnLinkButtonClickThunk), this);
+    GtkWidget* link_alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
+    gtk_container_add(GTK_CONTAINER(link_alignment), link);
+    gtk_box_pack_start(GTK_BOX(vbox), link_alignment, FALSE, FALSE, 0);
+  }
+
+  gtk_widget_show_all(event_box_.get());
+}
+
+SadTabGtk::~SadTabGtk() {
+  event_box_.Destroy();
+}
+
+void SadTabGtk::OnLinkButtonClick(GtkWidget* sender) {
+  if (tab_contents_ != NULL) {
+    GURL help_url =
+        google_util::AppendGoogleLocaleParam(GURL(
+            kind_ == CRASHED ?
+            chrome::kCrashReasonURL :
+            chrome::kKillReasonURL));
+    tab_contents_->OpenURL(help_url, GURL(), CURRENT_TAB, PageTransition::LINK);
+  }
+}
diff --git a/chrome/browser/ui/gtk/sad_tab_gtk.h b/chrome/browser/ui/gtk/sad_tab_gtk.h
new file mode 100644
index 0000000..03ab37f
--- /dev/null
+++ b/chrome/browser/ui/gtk/sad_tab_gtk.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_SAD_TAB_GTK_H_
+#define CHROME_BROWSER_UI_GTK_SAD_TAB_GTK_H_
+#pragma once
+
+typedef struct _GtkWidget GtkWidget;
+
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class TabContents;
+
+class SadTabGtk {
+ public:
+  enum Kind {
+    CRASHED,  // The tab crashed.  Display the "Aw, Snap!" page.
+    KILLED    // The tab was killed.  Display the killed tab page.
+  };
+
+  explicit SadTabGtk(TabContents* tab_contents, Kind kind);
+  virtual ~SadTabGtk();
+
+  GtkWidget* widget() const { return event_box_.get(); }
+
+ private:
+  CHROMEGTK_CALLBACK_0(SadTabGtk, void, OnLinkButtonClick);
+
+  void OnLinkButtonClick();
+
+  TabContents* tab_contents_;
+  OwnedWidgetGtk event_box_;
+  Kind kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(SadTabGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_SAD_TAB_GTK_H_
diff --git a/chrome/browser/ui/gtk/slide_animator_gtk.cc b/chrome/browser/ui/gtk/slide_animator_gtk.cc
new file mode 100644
index 0000000..e18b748
--- /dev/null
+++ b/chrome/browser/ui/gtk/slide_animator_gtk.cc
@@ -0,0 +1,151 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+
+#include "chrome/browser/ui/gtk/gtk_expanded_container.h"
+#include "ui/base/animation/animation.h"
+#include "ui/base/animation/slide_animation.h"
+
+namespace {
+
+void OnChildSizeRequest(GtkWidget* expanded,
+                        GtkWidget* child,
+                        GtkRequisition* requisition,
+                        gpointer control_child_size) {
+  // If |control_child_size| is true, then we want |child_| to match the width
+  // of the |widget_|, but the height of |child_| should not change.
+  if (!GPOINTER_TO_INT(control_child_size)) {
+    requisition->width = -1;
+  }
+  requisition->height = -1;
+}
+
+}  // namespace
+
+bool SlideAnimatorGtk::animations_enabled_ = true;
+
+SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget* child,
+                                   Direction direction,
+                                   int duration,
+                                   bool linear,
+                                   bool control_child_size,
+                                   Delegate* delegate)
+    : child_(child),
+      direction_(direction),
+      delegate_(delegate) {
+  widget_.Own(gtk_expanded_container_new());
+  gtk_container_add(GTK_CONTAINER(widget_.get()), child);
+  gtk_widget_set_size_request(widget_.get(), -1, 0);
+
+  // If the child requests it, we will manually set the size request for
+  // |child_| every time the |widget_| changes sizes. This is mainly useful
+  // for bars, where we want the child to expand to fill all available space.
+  g_signal_connect(widget_.get(), "child-size-request",
+                   G_CALLBACK(OnChildSizeRequest),
+                   GINT_TO_POINTER(control_child_size));
+
+  // We connect to this signal to set an initial position for our child widget.
+  // The reason we connect to this signal rather than setting the initial
+  // position here is that the widget is currently unallocated and may not
+  // even have a size request.
+  g_signal_connect(child, "size-allocate",
+                   G_CALLBACK(OnChildSizeAllocate), this);
+
+  child_needs_move_ = (direction == DOWN);
+
+  animation_.reset(new ui::SlideAnimation(this));
+  // Default tween type is EASE_OUT.
+  if (linear)
+    animation_->SetTweenType(ui::Tween::LINEAR);
+  if (duration != 0)
+    animation_->SetSlideDuration(duration);
+}
+
+SlideAnimatorGtk::~SlideAnimatorGtk() {
+  widget_.Destroy();
+}
+
+void SlideAnimatorGtk::Open() {
+  if (!animations_enabled_)
+    return OpenWithoutAnimation();
+
+  gtk_widget_show(widget_.get());
+  animation_->Show();
+}
+
+void SlideAnimatorGtk::OpenWithoutAnimation() {
+  gtk_widget_show(widget_.get());
+  animation_->Reset(1.0);
+  animation_->Show();
+  AnimationProgressed(animation_.get());
+}
+
+void SlideAnimatorGtk::Close() {
+  if (!animations_enabled_)
+    return CloseWithoutAnimation();
+
+  animation_->Hide();
+}
+
+void SlideAnimatorGtk::End() {
+  animation_->End();
+}
+
+void SlideAnimatorGtk::CloseWithoutAnimation() {
+  animation_->Reset(0.0);
+  animation_->Hide();
+  AnimationProgressed(animation_.get());
+  gtk_widget_hide(widget_.get());
+}
+
+bool SlideAnimatorGtk::IsShowing() {
+  return animation_->IsShowing();
+}
+
+bool SlideAnimatorGtk::IsClosing() {
+  return animation_->IsClosing();
+}
+
+bool SlideAnimatorGtk::IsAnimating() {
+  return animation_->is_animating();
+}
+
+void SlideAnimatorGtk::AnimationProgressed(const ui::Animation* animation) {
+  GtkRequisition req;
+  gtk_widget_size_request(child_, &req);
+
+  int showing_height = static_cast<int>(req.height *
+                                        animation_->GetCurrentValue());
+  if (direction_ == DOWN) {
+    gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()),
+                                child_, 0, showing_height - req.height);
+    child_needs_move_ = false;
+  }
+  gtk_widget_set_size_request(widget_.get(), -1, showing_height);
+}
+
+void SlideAnimatorGtk::AnimationEnded(const ui::Animation* animation) {
+  if (!animation_->IsShowing()) {
+    gtk_widget_hide(widget_.get());
+    if (delegate_)
+      delegate_->Closed();
+  }
+}
+
+// static
+void SlideAnimatorGtk::SetAnimationsForTesting(bool enable) {
+  animations_enabled_ = enable;
+}
+
+// static
+void SlideAnimatorGtk::OnChildSizeAllocate(GtkWidget* child,
+                                           GtkAllocation* allocation,
+                                           SlideAnimatorGtk* slider) {
+  if (slider->child_needs_move_) {
+    gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(slider->widget()),
+                                child, 0, -allocation->height);
+    slider->child_needs_move_ = false;
+  }
+}
diff --git a/chrome/browser/ui/gtk/slide_animator_gtk.h b/chrome/browser/ui/gtk/slide_animator_gtk.h
new file mode 100644
index 0000000..4e8fd0d
--- /dev/null
+++ b/chrome/browser/ui/gtk/slide_animator_gtk.h
@@ -0,0 +1,123 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A helper class for animating the display of native widget content.
+// Currently only handle vertical sliding, but could be extended to handle
+// horizontal slides or other types of animations.
+//
+// NOTE: This does not handle clipping. If you are not careful, you will
+// wind up with visibly overlapping widgets. If you need clipping, you can
+// extend the constructor to take an option to give |fixed| its own GdkWindow
+// (via gtk_fixed_set_has_window).
+
+#ifndef CHROME_BROWSER_UI_GTK_SLIDE_ANIMATOR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_SLIDE_ANIMATOR_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "ui/base/animation/animation_delegate.h"
+
+namespace ui {
+class SlideAnimation;
+}
+
+class SlideAnimatorGtk : public ui::AnimationDelegate {
+ public:
+  class Delegate {
+   public:
+    // Called when a call to Close() finishes animating.
+    virtual void Closed() = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  enum Direction {
+    DOWN,
+    UP
+  };
+
+  // |child| is the widget we pack into |widget_|.
+  // |direction| indicates which side the contents will appear to come from.
+  // |duration| is the duration of the slide in milliseconds, or 0 for default.
+  // |linear| controls how the animation progresses. If true, the
+  // velocity of the slide is constant over time, otherwise it goes a bit faster
+  // at the beginning and slows to a halt.
+  // |delegate| may be NULL.
+  SlideAnimatorGtk(GtkWidget* child,
+                   Direction direction,
+                   int duration,
+                   bool linear,
+                   bool control_child_size,
+                   Delegate* delegate);
+
+  virtual ~SlideAnimatorGtk();
+
+  GtkWidget* widget() { return widget_.get(); }
+
+  // Slide open.
+  void Open();
+
+  // Immediately show the widget.
+  void OpenWithoutAnimation();
+
+  // Slide shut.
+  void Close();
+
+  // End the current animation.
+  void End();
+
+  // Immediately hide the widget.
+  void CloseWithoutAnimation();
+
+  // Returns whether the widget is visible.
+  bool IsShowing();
+
+  // Returns whether the widget is currently showing the close animation.
+  bool IsClosing();
+
+  // Returns whether the widget is currently showing the open or close
+  // animation.
+  bool IsAnimating();
+
+  // ui::AnimationDelegate implementation.
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationEnded(const ui::Animation* animation);
+
+  // Used during testing; disable or enable animations (default is enabled).
+  static void SetAnimationsForTesting(bool enable);
+
+ private:
+  static void OnChildSizeAllocate(GtkWidget* child,
+                                  GtkAllocation* allocation,
+                                  SlideAnimatorGtk* slider);
+
+  scoped_ptr<ui::SlideAnimation> animation_;
+
+  // The top level widget of the SlideAnimatorGtk. It is a GtkFixed.
+  OwnedWidgetGtk widget_;
+
+  // The widget passed to us at construction time, and the only direct child of
+  // |widget_|.
+  GtkWidget* child_;
+
+  // The direction of the slide.
+  Direction direction_;
+
+  // The object to inform about certain events. It may be NULL.
+  Delegate* delegate_;
+
+  // We need to move the child widget to (0, -height), but we don't know its
+  // height until it has been allocated. This variable will be true until the
+  // child widget has been allocated, at which point we will move it, and then
+  // set this variable to false to indicate it should not be moved again.
+  bool child_needs_move_;
+
+  static bool animations_enabled_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_SLIDE_ANIMATOR_GTK_H_
diff --git a/chrome/browser/ui/gtk/ssl_client_certificate_selector.cc b/chrome/browser/ui/gtk/ssl_client_certificate_selector.cc
new file mode 100644
index 0000000..bc5be25
--- /dev/null
+++ b/chrome/browser/ui/gtk/ssl_client_certificate_selector.cc
@@ -0,0 +1,378 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ssl_client_certificate_selector.h"
+
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "base/i18n/time_formatting.h"
+#include "base/logging.h"
+#include "base/nss_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/certificate_viewer.h"
+#include "chrome/browser/ssl/ssl_client_auth_handler.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/crypto_module_password_dialog.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/net/x509_certificate_model.h"
+#include "grit/generated_resources.h"
+#include "net/base/x509_certificate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace {
+
+enum {
+  RESPONSE_SHOW_CERT_INFO = 1,
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// SSLClientCertificateSelector
+
+class SSLClientCertificateSelector : public ConstrainedDialogDelegate {
+ public:
+  explicit SSLClientCertificateSelector(
+      TabContents* parent,
+      net::SSLCertRequestInfo* cert_request_info,
+      SSLClientAuthHandler* delegate);
+  ~SSLClientCertificateSelector();
+
+  void Show();
+
+  // ConstrainedDialogDelegate implementation:
+  virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); }
+  virtual void DeleteDelegate();
+
+ private:
+  void PopulateCerts();
+
+  net::X509Certificate* GetSelectedCert();
+
+  static std::string FormatComboBoxText(
+      net::X509Certificate::OSCertHandle cert,
+      const std::string& nickname);
+  static std::string FormatDetailsText(
+      net::X509Certificate::OSCertHandle cert);
+
+  // Callback after unlocking certificate slot.
+  void Unlocked();
+
+  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged);
+  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked);
+  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked);
+  CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked);
+  CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown,
+                       GtkWidget*);
+
+  scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
+
+  std::vector<std::string> details_strings_;
+
+  GtkWidget* cert_combo_box_;
+  GtkTextBuffer* cert_details_buffer_;
+
+  scoped_refptr<SSLClientAuthHandler> delegate_;
+
+  OwnedWidgetGtk root_widget_;
+  // Hold on to the select button to focus it.
+  GtkWidget* select_button_;
+
+  TabContents* parent_;
+  ConstrainedWindow* window_;
+
+  DISALLOW_COPY_AND_ASSIGN(SSLClientCertificateSelector);
+};
+
+SSLClientCertificateSelector::SSLClientCertificateSelector(
+    TabContents* parent,
+    net::SSLCertRequestInfo* cert_request_info,
+    SSLClientAuthHandler* delegate)
+    : cert_request_info_(cert_request_info),
+      delegate_(delegate),
+      parent_(parent),
+      window_(NULL) {
+  root_widget_.Own(gtk_vbox_new(FALSE, gtk_util::kControlSpacing));
+
+  GtkWidget* site_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(root_widget_.get()), site_vbox,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* site_description_label = gtk_util::CreateBoldLabel(
+      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_SITE_DESCRIPTION_LABEL));
+  gtk_box_pack_start(GTK_BOX(site_vbox), site_description_label,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* site_label = gtk_label_new(
+      cert_request_info->host_and_port.c_str());
+  gtk_util::LeftAlignMisc(site_label);
+  gtk_box_pack_start(GTK_BOX(site_vbox), site_label, FALSE, FALSE, 0);
+
+  GtkWidget* selector_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_box_pack_start(GTK_BOX(root_widget_.get()), selector_vbox,
+                     TRUE, TRUE, 0);
+
+  GtkWidget* choose_description_label = gtk_util::CreateBoldLabel(
+      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CHOOSE_DESCRIPTION_LABEL));
+  gtk_box_pack_start(GTK_BOX(selector_vbox), choose_description_label,
+                     FALSE, FALSE, 0);
+
+
+  cert_combo_box_ = gtk_combo_box_new_text();
+  g_signal_connect(cert_combo_box_, "changed",
+                   G_CALLBACK(OnComboBoxChangedThunk), this);
+  gtk_box_pack_start(GTK_BOX(selector_vbox), cert_combo_box_,
+                     FALSE, FALSE, 0);
+
+  GtkWidget* details_label = gtk_label_new(l10n_util::GetStringUTF8(
+      IDS_CERT_SELECTOR_DETAILS_DESCRIPTION_LABEL).c_str());
+  gtk_util::LeftAlignMisc(details_label);
+  gtk_box_pack_start(GTK_BOX(selector_vbox), details_label, FALSE, FALSE, 0);
+
+  // TODO(mattm): fix text view coloring (should have grey background).
+  GtkWidget* cert_details_view = gtk_text_view_new();
+  gtk_text_view_set_editable(GTK_TEXT_VIEW(cert_details_view), FALSE);
+  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(cert_details_view), GTK_WRAP_WORD);
+  cert_details_buffer_ = gtk_text_view_get_buffer(
+      GTK_TEXT_VIEW(cert_details_view));
+  // We put the details in a frame instead of a scrolled window so that the
+  // entirety will be visible without requiring scrolling or expanding the
+  // dialog.  This does however mean the dialog will grow itself if you switch
+  // to different cert that has longer details text.
+  GtkWidget* details_frame = gtk_frame_new(NULL);
+  gtk_frame_set_shadow_type(GTK_FRAME(details_frame), GTK_SHADOW_ETCHED_IN);
+  gtk_container_add(GTK_CONTAINER(details_frame), cert_details_view);
+  gtk_box_pack_start(GTK_BOX(selector_vbox), details_frame, TRUE, TRUE, 0);
+
+  // And then create a set of buttons like a GtkDialog would.
+  GtkWidget* button_box = gtk_hbutton_box_new();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
+  gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
+  gtk_box_pack_end(GTK_BOX(root_widget_.get()), button_box, FALSE, FALSE, 0);
+
+  GtkWidget* view_button = gtk_button_new_with_mnemonic(
+      l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
+  gtk_box_pack_start(GTK_BOX(button_box), view_button, FALSE, FALSE, 0);
+  g_signal_connect(view_button, "clicked",
+                   G_CALLBACK(OnViewClickedThunk), this);
+
+  GtkWidget* cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+  gtk_box_pack_end(GTK_BOX(button_box), cancel_button, FALSE, FALSE, 0);
+  g_signal_connect(cancel_button, "clicked",
+                   G_CALLBACK(OnCancelClickedThunk), this);
+
+  GtkWidget* select_button = gtk_button_new_from_stock(GTK_STOCK_OK);
+  gtk_box_pack_end(GTK_BOX(button_box), select_button, FALSE, FALSE, 0);
+  g_signal_connect(select_button, "clicked",
+                   G_CALLBACK(OnOkClickedThunk), this);
+
+  // When we are attached to a window, focus the select button.
+  select_button_ = select_button;
+  g_signal_connect(root_widget_.get(), "hierarchy-changed",
+                   G_CALLBACK(OnPromptShownThunk), this);
+  PopulateCerts();
+
+  gtk_widget_show_all(root_widget_.get());
+}
+
+SSLClientCertificateSelector::~SSLClientCertificateSelector() {
+  root_widget_.Destroy();
+}
+
+void SSLClientCertificateSelector::Show() {
+  DCHECK(!window_);
+  window_ = parent_->CreateConstrainedDialog(this);
+}
+
+void SSLClientCertificateSelector::DeleteDelegate() {
+  if (delegate_) {
+    // The dialog was closed by escape key.
+    delegate_->CertificateSelected(NULL);
+  }
+  delete this;
+}
+
+void SSLClientCertificateSelector::PopulateCerts() {
+  std::vector<std::string> nicknames;
+  x509_certificate_model::GetNicknameStringsFromCertList(
+      cert_request_info_->client_certs,
+      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_EXPIRED),
+      l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_NOT_YET_VALID),
+      &nicknames);
+
+  DCHECK_EQ(nicknames.size(),
+            cert_request_info_->client_certs.size());
+
+  for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) {
+    net::X509Certificate::OSCertHandle cert =
+        cert_request_info_->client_certs[i]->os_cert_handle();
+
+    details_strings_.push_back(FormatDetailsText(cert));
+
+    gtk_combo_box_append_text(
+        GTK_COMBO_BOX(cert_combo_box_),
+        FormatComboBoxText(cert, nicknames[i]).c_str());
+  }
+
+  // Auto-select the first cert.
+  gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0);
+}
+
+net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() {
+  int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_));
+  if (selected >= 0 &&
+      selected < static_cast<int>(
+          cert_request_info_->client_certs.size()))
+    return cert_request_info_->client_certs[selected];
+  return NULL;
+}
+
+// static
+std::string SSLClientCertificateSelector::FormatComboBoxText(
+    net::X509Certificate::OSCertHandle cert, const std::string& nickname) {
+  std::string rv(nickname);
+  rv += " [";
+  rv += x509_certificate_model::GetSerialNumberHexified(cert, "");
+  rv += ']';
+  return rv;
+}
+
+// static
+std::string SSLClientCertificateSelector::FormatDetailsText(
+    net::X509Certificate::OSCertHandle cert) {
+  std::string rv;
+
+  rv += l10n_util::GetStringFUTF8(
+      IDS_CERT_SUBJECTNAME_FORMAT,
+      UTF8ToUTF16(x509_certificate_model::GetSubjectName(cert)));
+
+  rv += "\n  ";
+  rv += l10n_util::GetStringFUTF8(
+      IDS_CERT_SERIAL_NUMBER_FORMAT,
+      UTF8ToUTF16(
+          x509_certificate_model::GetSerialNumberHexified(cert, "")));
+
+  base::Time issued, expires;
+  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
+    string16 issued_str = base::TimeFormatShortDateAndTime(issued);
+    string16 expires_str = base::TimeFormatShortDateAndTime(expires);
+    rv += "\n  ";
+    rv += l10n_util::GetStringFUTF8(IDS_CERT_VALIDITY_RANGE_FORMAT,
+                                    issued_str, expires_str);
+  }
+
+  std::vector<std::string> usages;
+  x509_certificate_model::GetUsageStrings(cert, &usages);
+  if (usages.size()) {
+    rv += "\n  ";
+    rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_EXTENDED_KEY_USAGE_FORMAT,
+                                    UTF8ToUTF16(JoinString(usages, ',')));
+  }
+
+  std::string key_usage_str = x509_certificate_model::GetKeyUsageString(cert);
+  if (!key_usage_str.empty()) {
+    rv += "\n  ";
+    rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_KEY_USAGE_FORMAT,
+                                    UTF8ToUTF16(key_usage_str));
+  }
+
+  std::vector<std::string> email_addresses;
+  x509_certificate_model::GetEmailAddresses(cert, &email_addresses);
+  if (email_addresses.size()) {
+    rv += "\n  ";
+    rv += l10n_util::GetStringFUTF8(
+        IDS_CERT_EMAIL_ADDRESSES_FORMAT,
+        UTF8ToUTF16(JoinString(email_addresses, ',')));
+  }
+
+  rv += '\n';
+  rv += l10n_util::GetStringFUTF8(
+      IDS_CERT_ISSUERNAME_FORMAT,
+      UTF8ToUTF16(x509_certificate_model::GetIssuerName(cert)));
+
+  string16 token(UTF8ToUTF16(x509_certificate_model::GetTokenName(cert)));
+  if (!token.empty()) {
+    rv += '\n';
+    rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token);
+  }
+
+  return rv;
+}
+
+void SSLClientCertificateSelector::Unlocked() {
+  // TODO(mattm): refactor so we don't need to call GetSelectedCert again.
+  net::X509Certificate* cert = GetSelectedCert();
+  delegate_->CertificateSelected(cert);
+  delegate_ = NULL;
+  DCHECK(window_);
+  window_->CloseConstrainedWindow();
+}
+
+void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) {
+  int selected = gtk_combo_box_get_active(
+      GTK_COMBO_BOX(cert_combo_box_));
+  if (selected < 0)
+    return;
+  gtk_text_buffer_set_text(cert_details_buffer_,
+                           details_strings_[selected].c_str(),
+                           details_strings_[selected].size());
+}
+
+void SSLClientCertificateSelector::OnViewClicked(GtkWidget* button) {
+  net::X509Certificate* cert = GetSelectedCert();
+  if (cert) {
+    GtkWidget* toplevel = gtk_widget_get_toplevel(root_widget_.get());
+    ShowCertificateViewer(GTK_WINDOW(toplevel), cert);
+  }
+}
+
+void SSLClientCertificateSelector::OnCancelClicked(GtkWidget* button) {
+  delegate_->CertificateSelected(NULL);
+  delegate_ = NULL;
+  DCHECK(window_);
+  window_->CloseConstrainedWindow();
+}
+
+void SSLClientCertificateSelector::OnOkClicked(GtkWidget* button) {
+  net::X509Certificate* cert = GetSelectedCert();
+
+  browser::UnlockCertSlotIfNecessary(
+      cert,
+      browser::kCryptoModulePasswordClientAuth,
+      cert_request_info_->host_and_port,
+      NewCallback(this, &SSLClientCertificateSelector::Unlocked));
+}
+
+void SSLClientCertificateSelector::OnPromptShown(GtkWidget* widget,
+                                                 GtkWidget* previous_toplevel) {
+  if (!root_widget_.get() ||
+      !GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(root_widget_.get())))
+    return;
+  GTK_WIDGET_SET_FLAGS(select_button_, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(select_button_);
+  gtk_widget_grab_focus(select_button_);
+}
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// SSLClientAuthHandler platform specific implementation:
+
+namespace browser {
+
+void ShowSSLClientCertificateSelector(
+    TabContents* parent,
+    net::SSLCertRequestInfo* cert_request_info,
+    SSLClientAuthHandler* delegate) {
+  (new SSLClientCertificateSelector(parent,
+                                    cert_request_info,
+                                    delegate))->Show();
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/gtk/status_bubble_gtk.cc b/chrome/browser/ui/gtk/status_bubble_gtk.cc
new file mode 100644
index 0000000..7f2dccb
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_bubble_gtk.cc
@@ -0,0 +1,366 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/status_bubble_gtk.h"
+
+#include <gtk/gtk.h>
+
+#include <algorithm>
+
+#include "base/i18n/rtl.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
+#include "chrome/common/notification_service.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/text/text_elider.h"
+
+namespace {
+
+// Inner padding between the border and the text label.
+const int kInternalTopBottomPadding = 1;
+const int kInternalLeftRightPadding = 2;
+
+// The radius of the edges of our bubble.
+const int kCornerSize = 3;
+
+// Milliseconds before we hide the status bubble widget when you mouseout.
+const int kHideDelay = 250;
+
+// How close the mouse can get to the infobubble before it starts sliding
+// off-screen.
+const int kMousePadding = 20;
+
+}  // namespace
+
+StatusBubbleGtk::StatusBubbleGtk(Profile* profile)
+    : theme_provider_(GtkThemeProvider::GetFrom(profile)),
+      padding_(NULL),
+      label_(NULL),
+      flip_horizontally_(false),
+      y_offset_(0),
+      download_shelf_is_visible_(false),
+      last_mouse_location_(0, 0),
+      last_mouse_left_content_(false),
+      ignore_next_left_content_(false) {
+  InitWidgets();
+
+  theme_provider_->InitThemesFor(this);
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+StatusBubbleGtk::~StatusBubbleGtk() {
+  container_.Destroy();
+}
+
+void StatusBubbleGtk::SetStatus(const string16& status_text_wide) {
+  std::string status_text = UTF16ToUTF8(status_text_wide);
+  if (status_text_ == status_text)
+    return;
+
+  status_text_ = status_text;
+  if (!status_text_.empty())
+    SetStatusTextTo(status_text_);
+  else if (!url_text_.empty())
+    SetStatusTextTo(url_text_);
+  else
+    SetStatusTextTo(std::string());
+}
+
+void StatusBubbleGtk::SetURL(const GURL& url, const string16& languages) {
+  url_ = url;
+  languages_ = languages;
+
+  // If we want to clear a displayed URL but there is a status still to
+  // display, display that status instead.
+  if (url.is_empty() && !status_text_.empty()) {
+    url_text_ = std::string();
+    SetStatusTextTo(status_text_);
+    return;
+  }
+
+  SetStatusTextToURL();
+}
+
+void StatusBubbleGtk::SetStatusTextToURL() {
+  GtkWidget* parent = gtk_widget_get_parent(container_.get());
+
+  // It appears that parent can be NULL (probably only during shutdown).
+  if (!parent || !GTK_WIDGET_REALIZED(parent))
+    return;
+
+  int desired_width = parent->allocation.width;
+  if (!expanded()) {
+    expand_timer_.Stop();
+    expand_timer_.Start(base::TimeDelta::FromMilliseconds(kExpandHoverDelay),
+                        this, &StatusBubbleGtk::ExpandURL);
+    // When not expanded, we limit the size to one third the browser's
+    // width.
+    desired_width /= 3;
+  }
+
+  // TODO(tc): We don't actually use gfx::Font as the font in the status
+  // bubble.  We should extend ui::ElideUrl to take some sort of pango font.
+  url_text_ = UTF16ToUTF8(ui::ElideUrl(url_, gfx::Font(), desired_width,
+                          UTF16ToWideHack(languages_)));
+  SetStatusTextTo(url_text_);
+}
+
+void StatusBubbleGtk::Show() {
+  // If we were going to hide, stop.
+  hide_timer_.Stop();
+
+  gtk_widget_show(container_.get());
+  if (container_->window)
+    gdk_window_raise(container_->window);
+}
+
+void StatusBubbleGtk::Hide() {
+  // If we were going to expand the bubble, stop.
+  expand_timer_.Stop();
+  expand_animation_.reset();
+
+  gtk_widget_hide(container_.get());
+}
+
+void StatusBubbleGtk::SetStatusTextTo(const std::string& status_utf8) {
+  if (status_utf8.empty()) {
+    hide_timer_.Stop();
+    hide_timer_.Start(base::TimeDelta::FromMilliseconds(kHideDelay),
+                      this, &StatusBubbleGtk::Hide);
+  } else {
+    gtk_label_set_text(GTK_LABEL(label_), status_utf8.c_str());
+    GtkRequisition req;
+    gtk_widget_size_request(label_, &req);
+    desired_width_ = req.width;
+
+    UpdateLabelSizeRequest();
+
+    if (!last_mouse_left_content_) {
+      // Show the padding and label to update our requisition and then
+      // re-process the last mouse event -- if the label was empty before or the
+      // text changed, our size will have changed and we may need to move
+      // ourselves away from the pointer now.
+      gtk_widget_show_all(padding_);
+      MouseMoved(last_mouse_location_, false);
+    }
+    Show();
+  }
+}
+
+void StatusBubbleGtk::MouseMoved(
+    const gfx::Point& location, bool left_content) {
+  if (left_content && ignore_next_left_content_) {
+    ignore_next_left_content_ = false;
+    return;
+  }
+
+  last_mouse_location_ = location;
+  last_mouse_left_content_ = left_content;
+
+  if (!GTK_WIDGET_REALIZED(container_.get()))
+    return;
+
+  GtkWidget* parent = gtk_widget_get_parent(container_.get());
+  if (!parent || !GTK_WIDGET_REALIZED(parent))
+    return;
+
+  int old_y_offset = y_offset_;
+  bool old_flip_horizontally = flip_horizontally_;
+
+  if (left_content) {
+    SetFlipHorizontally(false);
+    y_offset_ = 0;
+  } else {
+    GtkWidget* toplevel = gtk_widget_get_toplevel(container_.get());
+    if (!toplevel || !GTK_WIDGET_REALIZED(toplevel))
+      return;
+
+    bool ltr = !base::i18n::IsRTL();
+
+    GtkRequisition requisition;
+    gtk_widget_size_request(container_.get(), &requisition);
+
+    // Get our base position (that is, not including the current offset)
+    // relative to the origin of the root window.
+    gint toplevel_x = 0, toplevel_y = 0;
+    gdk_window_get_position(toplevel->window, &toplevel_x, &toplevel_y);
+    gfx::Rect parent_rect =
+        gtk_util::GetWidgetRectRelativeToToplevel(parent);
+    gfx::Rect bubble_rect(
+        toplevel_x + parent_rect.x() +
+            (ltr ? 0 : parent->allocation.width - requisition.width),
+        toplevel_y + parent_rect.y() +
+            parent->allocation.height - requisition.height,
+        requisition.width,
+        requisition.height);
+
+    int left_threshold =
+        bubble_rect.x() - bubble_rect.height() - kMousePadding;
+    int right_threshold =
+        bubble_rect.right() + bubble_rect.height() + kMousePadding;
+    int top_threshold = bubble_rect.y() - kMousePadding;
+
+    if (((ltr && location.x() < right_threshold) ||
+         (!ltr && location.x() > left_threshold)) &&
+        location.y() > top_threshold) {
+      if (download_shelf_is_visible_) {
+        SetFlipHorizontally(true);
+        y_offset_ = 0;
+      } else {
+        SetFlipHorizontally(false);
+        int distance = std::max(ltr ?
+                                    location.x() - right_threshold :
+                                    left_threshold - location.x(),
+                                top_threshold - location.y());
+        y_offset_ = std::min(-1 * distance, requisition.height);
+      }
+    } else {
+      SetFlipHorizontally(false);
+      y_offset_ = 0;
+    }
+  }
+
+  if (y_offset_ != old_y_offset || flip_horizontally_ != old_flip_horizontally)
+    gtk_widget_queue_resize_no_redraw(parent);
+}
+
+void StatusBubbleGtk::UpdateDownloadShelfVisibility(bool visible) {
+  download_shelf_is_visible_ = visible;
+}
+
+void StatusBubbleGtk::Observe(NotificationType type,
+                              const NotificationSource& source,
+                              const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    UserChangedTheme();
+  }
+}
+
+void StatusBubbleGtk::InitWidgets() {
+  bool ltr = !base::i18n::IsRTL();
+
+  label_ = gtk_label_new(NULL);
+
+  padding_ = gtk_alignment_new(0, 0, 1, 1);
+  gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
+      kInternalTopBottomPadding, kInternalTopBottomPadding,
+      kInternalLeftRightPadding + (ltr ? 0 : kCornerSize),
+      kInternalLeftRightPadding + (ltr ? kCornerSize : 0));
+  gtk_container_add(GTK_CONTAINER(padding_), label_);
+  gtk_widget_show_all(padding_);
+
+  container_.Own(gtk_event_box_new());
+  gtk_widget_set_no_show_all(container_.get(), TRUE);
+  gtk_util::ActAsRoundedWindow(
+      container_.get(), gtk_util::kGdkWhite, kCornerSize,
+      gtk_util::ROUNDED_TOP_RIGHT,
+      gtk_util::BORDER_TOP | gtk_util::BORDER_RIGHT);
+  gtk_widget_set_name(container_.get(), "status-bubble");
+  gtk_container_add(GTK_CONTAINER(container_.get()), padding_);
+
+  // We need to listen for mouse motion events, since a fast-moving pointer may
+  // enter our window without us getting any motion events on the browser near
+  // enough for us to run away.
+  gtk_widget_add_events(container_.get(), GDK_POINTER_MOTION_MASK |
+                                          GDK_ENTER_NOTIFY_MASK);
+  g_signal_connect(container_.get(), "motion-notify-event",
+                   G_CALLBACK(HandleMotionNotifyThunk), this);
+  g_signal_connect(container_.get(), "enter-notify-event",
+                   G_CALLBACK(HandleEnterNotifyThunk), this);
+
+  UserChangedTheme();
+}
+
+void StatusBubbleGtk::UserChangedTheme() {
+  if (theme_provider_->UseGtkTheme()) {
+    gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, NULL);
+    gtk_widget_modify_bg(container_.get(), GTK_STATE_NORMAL, NULL);
+  } else {
+    // TODO(erg): This is the closest to "text that will look good on a
+    // toolbar" that I can find. Maybe in later iterations of the theme system,
+    // there will be a better color to pick.
+    GdkColor bookmark_text =
+        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
+    gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, &bookmark_text);
+
+    GdkColor toolbar_color =
+        theme_provider_->GetGdkColor(BrowserThemeProvider::COLOR_TOOLBAR);
+    gtk_widget_modify_bg(container_.get(), GTK_STATE_NORMAL, &toolbar_color);
+  }
+
+  gtk_util::SetRoundedWindowBorderColor(container_.get(),
+                                        theme_provider_->GetBorderColor());
+}
+
+void StatusBubbleGtk::SetFlipHorizontally(bool flip_horizontally) {
+  if (flip_horizontally == flip_horizontally_)
+    return;
+
+  flip_horizontally_ = flip_horizontally;
+
+  bool ltr = !base::i18n::IsRTL();
+  bool on_left = (ltr && !flip_horizontally) || (!ltr && flip_horizontally);
+
+  gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
+      kInternalTopBottomPadding, kInternalTopBottomPadding,
+      kInternalLeftRightPadding + (on_left ? 0 : kCornerSize),
+      kInternalLeftRightPadding + (on_left ? kCornerSize : 0));
+  // The rounded window code flips these arguments if we're RTL.
+  gtk_util::SetRoundedWindowEdgesAndBorders(
+      container_.get(),
+      kCornerSize,
+      flip_horizontally ?
+          gtk_util::ROUNDED_TOP_LEFT :
+          gtk_util::ROUNDED_TOP_RIGHT,
+      gtk_util::BORDER_TOP |
+          (flip_horizontally ? gtk_util::BORDER_LEFT : gtk_util::BORDER_RIGHT));
+  gtk_widget_queue_draw(container_.get());
+}
+
+void StatusBubbleGtk::ExpandURL() {
+  start_width_ = label_->allocation.width;
+  expand_animation_.reset(new ui::SlideAnimation(this));
+  expand_animation_->SetTweenType(ui::Tween::LINEAR);
+  expand_animation_->Show();
+
+  SetStatusTextToURL();
+}
+
+void StatusBubbleGtk::UpdateLabelSizeRequest() {
+  if (!expanded() || !expand_animation_->is_animating()) {
+    gtk_widget_set_size_request(label_, -1, -1);
+    return;
+  }
+
+  int new_width = start_width_ +
+      (desired_width_ - start_width_) * expand_animation_->GetCurrentValue();
+  gtk_widget_set_size_request(label_, new_width, -1);
+}
+
+// See http://crbug.com/68897 for why we have to handle this event.
+gboolean StatusBubbleGtk::HandleEnterNotify(GtkWidget* sender,
+                                            GdkEventCrossing* event) {
+  ignore_next_left_content_ = true;
+  MouseMoved(gfx::Point(event->x_root, event->y_root), false);
+  return FALSE;
+}
+
+gboolean StatusBubbleGtk::HandleMotionNotify(GtkWidget* sender,
+                                             GdkEventMotion* event) {
+  MouseMoved(gfx::Point(event->x_root, event->y_root), false);
+  return FALSE;
+}
+
+void StatusBubbleGtk::AnimationEnded(const ui::Animation* animation) {
+  UpdateLabelSizeRequest();
+}
+
+void StatusBubbleGtk::AnimationProgressed(const ui::Animation* animation) {
+  UpdateLabelSizeRequest();
+}
diff --git a/chrome/browser/ui/gtk/status_bubble_gtk.h b/chrome/browser/ui/gtk/status_bubble_gtk.h
new file mode 100644
index 0000000..0608f7a
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_bubble_gtk.h
@@ -0,0 +1,176 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/timer.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/status_bubble.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "googleurl/src/gurl.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/point.h"
+
+class GtkThemeProvider;
+class Profile;
+
+namespace ui {
+class SlideAnimation;
+}
+
+// GTK implementation of StatusBubble. Unlike Windows, our status bubble
+// doesn't have the nice leave-the-window effect since we can't rely on the
+// window manager to not try to be "helpful" and center our popups, etc.
+// We therefore position it absolutely in a GtkFixed, that we don't own.
+class StatusBubbleGtk : public StatusBubble,
+                        public NotificationObserver,
+                        public ui::AnimationDelegate {
+ public:
+  explicit StatusBubbleGtk(Profile* profile);
+  virtual ~StatusBubbleGtk();
+
+  bool flip_horizontally() const { return flip_horizontally_; }
+  int y_offset() const { return y_offset_; }
+
+  // StatusBubble implementation.
+  virtual void SetStatus(const string16& status);
+  virtual void SetURL(const GURL& url, const string16& languages);
+  virtual void Hide();
+  virtual void MouseMoved(const gfx::Point& location, bool left_content);
+
+  // ui::AnimationDelegate implementation.
+  virtual void AnimationEnded(const ui::Animation* animation);
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
+  // Called when the download shelf becomes visible or invisible.
+  // This is used by to ensure that the status bubble does not obscure
+  // the download shelf, when it is visible.
+  virtual void UpdateDownloadShelfVisibility(bool visible);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Top of the widget hierarchy for a StatusBubble. This top level widget is
+  // guarenteed to have its gtk_widget_name set to "status-bubble" for
+  // identification.
+  GtkWidget* widget() { return container_.get(); }
+
+ private:
+  // Sets the text of the label widget and controls visibility. (As contrasted
+  // with setting the current status or URL text, which may be ignored for now).
+  void SetStatusTextTo(const std::string& status_utf8);
+
+  // Sets the status text to the current value of |url_|, eliding it as
+  // necessary.
+  void SetStatusTextToURL();
+
+  // Sets the status bubble's location in the parent GtkFixed, shows the widget
+  // and makes sure that the status bubble has the highest z-order.
+  void Show();
+
+  // Builds the widgets, containers, etc.
+  void InitWidgets();
+
+  // Notification from the window that we should retheme ourself.
+  void UserChangedTheme();
+
+  // Sets whether the bubble should be flipped horizontally and displayed on the
+  // opposite side of the tab contents.  Reshapes the container and queues a
+  // redraw if necessary.
+  void SetFlipHorizontally(bool flip_horizontally);
+
+  // Expand the bubble up to the full width of the browser, so that the entire
+  // URL may be seen. Called after the user hovers over a link for sufficient
+  // time.
+  void ExpandURL();
+
+  // Adjust the actual size of the bubble by changing the label's size request.
+  void UpdateLabelSizeRequest();
+
+  // Returns true if the status bubble is in the expand-state (i.e., is
+  // currently expanded or in the process of expanding).
+  bool expanded() {
+    return expand_animation_.get();
+  }
+
+  CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleMotionNotify,
+                       GdkEventMotion*);
+
+  CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleEnterNotify,
+                       GdkEventCrossing*);
+
+  NotificationRegistrar registrar_;
+
+  // Provides colors.
+  GtkThemeProvider* theme_provider_;
+
+  // The toplevel event box.
+  OwnedWidgetGtk container_;
+
+  // The GtkAlignment holding |label_|.
+  GtkWidget* padding_;
+
+  // The GtkLabel holding the text.
+  GtkWidget* label_;
+
+  // The status text we want to display when there are no URLs to display.
+  std::string status_text_;
+
+  // The URL we are displaying for.
+  GURL url_;
+
+  // The possibly elided url text we want to display.
+  std::string url_text_;
+
+  // Used to determine the character set that the user can read (for eliding
+  // the url text).
+  string16 languages_;
+
+  // A timer that hides our window after a delay.
+  base::OneShotTimer<StatusBubbleGtk> hide_timer_;
+
+  // A timer that expands our window after a delay.
+  base::OneShotTimer<StatusBubbleGtk> expand_timer_;
+
+  // The animation for resizing the status bubble on long hovers.
+  scoped_ptr<ui::SlideAnimation> expand_animation_;
+
+  // The start and end width of the current resize animation.
+  int start_width_;
+  int desired_width_;
+
+  // Should the bubble be flipped horizontally (e.g. displayed on the right for
+  // an LTR language)?  We move the bubble to the other side of the tab contents
+  // rather than sliding it down when the download shelf is visible.
+  bool flip_horizontally_;
+
+  // Vertical offset used to hide the status bubble as the pointer nears it.
+  int y_offset_;
+
+  // If the download shelf is visible, do not obscure it.
+  bool download_shelf_is_visible_;
+
+  // 'location' and 'left_content' values from the last invocation of
+  // MouseMoved().  We hang onto these so we can move the bubble if necessary
+  // when its text changes, triggering a size change.
+  gfx::Point last_mouse_location_;
+  bool last_mouse_left_content_;
+
+  // Shortly after the cursor enters the status bubble, we'll get a message
+  // that the cursor left the content area. This lets us ignore that.
+  bool ignore_next_left_content_;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_
diff --git a/chrome/browser/ui/gtk/status_icons/status_icon_gtk.cc b/chrome/browser/ui/gtk/status_icons/status_icon_gtk.cc
new file mode 100644
index 0000000..1d66b6b
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_icons/status_icon_gtk.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/status_icons/status_icon_gtk.h"
+
+#include "base/string16.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/gtk_util.h"
+
+StatusIconGtk::StatusIconGtk() {
+  icon_ = gtk_status_icon_new();
+  gtk_status_icon_set_visible(icon_, TRUE);
+
+  g_signal_connect(icon_, "activate",
+                   G_CALLBACK(OnClickThunk), this);
+  g_signal_connect(icon_, "popup-menu",
+                   G_CALLBACK(OnPopupMenuThunk), this);
+}
+
+StatusIconGtk::~StatusIconGtk() {
+  g_object_unref(icon_);
+}
+
+void StatusIconGtk::SetImage(const SkBitmap& image) {
+  if (image.isNull())
+    return;
+
+  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&image);
+  gtk_status_icon_set_from_pixbuf(icon_, pixbuf);
+  g_object_unref(pixbuf);
+}
+
+void StatusIconGtk::SetPressedImage(const SkBitmap& image) {
+  // Ignore pressed images, since the standard on Linux is to not highlight
+  // pressed status icons.
+}
+
+void StatusIconGtk::SetToolTip(const string16& tool_tip) {
+  gtk_status_icon_set_tooltip(icon_, UTF16ToUTF8(tool_tip).c_str());
+}
+
+void StatusIconGtk::OnClick(GtkWidget* widget) {
+  DispatchClickEvent();
+}
+
+void StatusIconGtk::UpdatePlatformContextMenu(ui::MenuModel* model) {
+  if (!model)
+    menu_.reset();
+  else
+    menu_.reset(new MenuGtk(NULL, model));
+}
+
+void StatusIconGtk::OnPopupMenu(GtkWidget* widget, guint button, guint time) {
+  // If we have a menu - display it.
+  if (menu_.get())
+    menu_->PopupAsContextForStatusIcon(time, button, icon_);
+}
diff --git a/chrome/browser/ui/gtk/status_icons/status_icon_gtk.h b/chrome/browser/ui/gtk/status_icons/status_icon_gtk.h
new file mode 100644
index 0000000..3acf454
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_icons/status_icon_gtk.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_STATUS_ICONS_STATUS_ICON_GTK_H_
+#define CHROME_BROWSER_UI_GTK_STATUS_ICONS_STATUS_ICON_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/status_icons/status_icon.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class MenuGtk;
+class SkBitmap;
+
+class StatusIconGtk : public StatusIcon {
+ public:
+  StatusIconGtk();
+  virtual ~StatusIconGtk();
+
+  // Overridden from StatusIcon:
+  virtual void SetImage(const SkBitmap& image);
+  virtual void SetPressedImage(const SkBitmap& image);
+  virtual void SetToolTip(const string16& tool_tip);
+
+  // Exposed for testing.
+  CHROMEGTK_CALLBACK_0(StatusIconGtk, void, OnClick);
+
+ protected:
+  // Overridden from StatusIcon.
+  virtual void UpdatePlatformContextMenu(ui::MenuModel* menu);
+
+ private:
+  // Callback invoked when user right-clicks on the status icon.
+  CHROMEGTK_CALLBACK_2(StatusIconGtk, void, OnPopupMenu, guint, guint);
+
+  // The currently-displayed icon for the window.
+  GtkStatusIcon* icon_;
+
+  // The context menu for this icon (if any).
+  scoped_ptr<MenuGtk> menu_;
+
+  DISALLOW_COPY_AND_ASSIGN(StatusIconGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_STATUS_ICONS_STATUS_ICON_GTK_H_
diff --git a/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc
new file mode 100644
index 0000000..04bc250
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/status_icons/status_tray_gtk.h"
+
+#include "chrome/browser/ui/gtk/status_icons/status_icon_gtk.h"
+
+StatusTrayGtk::StatusTrayGtk() {
+}
+
+StatusTrayGtk::~StatusTrayGtk() {
+}
+
+StatusIcon* StatusTrayGtk::CreatePlatformStatusIcon() {
+  return new StatusIconGtk();
+}
+
+StatusTray* StatusTray::Create() {
+  return new StatusTrayGtk();
+}
diff --git a/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h
new file mode 100644
index 0000000..28d0d7a
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_STATUS_ICONS_STATUS_TRAY_GTK_H_
+#define CHROME_BROWSER_UI_GTK_STATUS_ICONS_STATUS_TRAY_GTK_H_
+#pragma once
+
+#include "chrome/browser/status_icons/status_tray.h"
+
+class StatusTrayGtk : public StatusTray {
+ public:
+  StatusTrayGtk();
+  ~StatusTrayGtk();
+
+ protected:
+  // Overriden from StatusTray:
+  virtual StatusIcon* CreatePlatformStatusIcon();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StatusTrayGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_STATUS_ICONS_STATUS_TRAY_GTK_H_
diff --git a/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc b/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc
new file mode 100644
index 0000000..ab65f6e
--- /dev/null
+++ b/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/status_icons/status_icon_gtk.h"
+#include "chrome/browser/ui/gtk/status_icons/status_tray_gtk.h"
+#include "grit/browser_resources.h"
+#include "grit/theme_resources.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+class MockStatusIconObserver : public StatusIcon::Observer {
+ public:
+  MOCK_METHOD0(OnClicked, void());
+};
+
+TEST(StatusTrayGtkTest, CreateTray) {
+  // Just tests creation/destruction.
+  StatusTrayGtk tray;
+}
+
+TEST(StatusTrayGtkTest, CreateIcon) {
+  // Create an icon, set the images and tooltip, then shut it down.
+  StatusTrayGtk tray;
+  StatusIcon* icon = tray.CreateStatusIcon();
+  SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed(
+      IDR_STATUS_TRAY_ICON);
+  icon->SetImage(*bitmap);
+  icon->SetPressedImage(*bitmap);
+  icon->SetToolTip(ASCIIToUTF16("tool tip"));
+  ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(NULL);
+  menu->AddItem(0, ASCIIToUTF16("foo"));
+  icon->SetContextMenu(menu);
+}
+
+TEST(StatusTrayGtkTest, ClickOnIcon) {
+  // Create an icon, send a fake click event, make sure observer is called.
+  StatusTrayGtk tray;
+  StatusIconGtk* icon = static_cast<StatusIconGtk*>(tray.CreateStatusIcon());
+  MockStatusIconObserver observer;
+  icon->AddObserver(&observer);
+  EXPECT_CALL(observer, OnClicked());
+  // Mimic a click.
+  icon->OnClick(NULL);
+  icon->RemoveObserver(&observer);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/gtk/tab_contents_container_gtk.cc b/chrome/browser/ui/gtk/tab_contents_container_gtk.cc
new file mode 100644
index 0000000..01cc890
--- /dev/null
+++ b/chrome/browser/ui/gtk/tab_contents_container_gtk.cc
@@ -0,0 +1,244 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
+
+#include <algorithm>
+
+#include "base/i18n/rtl.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/gtk_expanded_container.h"
+#include "chrome/browser/ui/gtk/gtk_floating_container.h"
+#include "chrome/browser/ui/gtk/status_bubble_gtk.h"
+#include "chrome/common/notification_source.h"
+#include "ui/gfx/native_widget_types.h"
+
+TabContentsContainerGtk::TabContentsContainerGtk(StatusBubbleGtk* status_bubble)
+    : tab_contents_(NULL),
+      preview_contents_(NULL),
+      status_bubble_(status_bubble) {
+  Init();
+}
+
+TabContentsContainerGtk::~TabContentsContainerGtk() {
+  floating_.Destroy();
+}
+
+void TabContentsContainerGtk::Init() {
+  // A high level overview of the TabContentsContainer:
+  //
+  // +- GtkFloatingContainer |floating_| -------------------------------+
+  // |+- GtkExpandedContainer |expanded_| -----------------------------+|
+  // ||                                                                ||
+  // ||                                                                ||
+  // ||                                                                ||
+  // ||                                                                ||
+  // |+- (StatusBubble) ------+                                        ||
+  // |+                       +                                        ||
+  // |+-----------------------+----------------------------------------+|
+  // +------------------------------------------------------------------+
+
+  floating_.Own(gtk_floating_container_new());
+  gtk_widget_set_name(floating_.get(), "chrome-tab-contents-container");
+  g_signal_connect(floating_.get(), "focus", G_CALLBACK(OnFocusThunk), this);
+
+  expanded_ = gtk_expanded_container_new();
+  gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_);
+
+  if (status_bubble_) {
+    gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
+                                        status_bubble_->widget());
+    g_signal_connect(floating_.get(), "set-floating-position",
+                     G_CALLBACK(OnSetFloatingPosition), this);
+  }
+
+  gtk_widget_show(expanded_);
+  gtk_widget_show(floating_.get());
+
+  ViewIDUtil::SetDelegateForWidget(widget(), this);
+}
+
+void TabContentsContainerGtk::SetTabContents(TabContents* tab_contents) {
+  HideTabContents(tab_contents_);
+  if (tab_contents_) {
+    registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                      Source<TabContents>(tab_contents_));
+  }
+
+  tab_contents_ = tab_contents;
+
+  if (tab_contents_ == preview_contents_) {
+    // If the preview contents is becoming the new permanent tab contents, we
+    // just reassign some pointers.
+    preview_contents_ = NULL;
+  } else if (tab_contents_) {
+    // Otherwise we actually have to add it to the widget hierarchy.
+    PackTabContents(tab_contents);
+    registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                   Source<TabContents>(tab_contents_));
+  }
+}
+
+TabContents* TabContentsContainerGtk::GetVisibleTabContents() {
+  return preview_contents_ ? preview_contents_ : tab_contents_;
+}
+
+void TabContentsContainerGtk::SetPreviewContents(TabContents* preview) {
+  if (preview_contents_)
+    RemovePreviewContents();
+  else
+    HideTabContents(tab_contents_);
+
+  preview_contents_ = preview;
+
+  PackTabContents(preview);
+  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                 Source<TabContents>(preview_contents_));
+}
+
+void TabContentsContainerGtk::RemovePreviewContents() {
+  if (!preview_contents_)
+    return;
+
+  HideTabContents(preview_contents_);
+
+  GtkWidget* preview_widget = preview_contents_->GetNativeView();
+  if (preview_widget)
+    gtk_container_remove(GTK_CONTAINER(expanded_), preview_widget);
+
+  registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
+                    Source<TabContents>(preview_contents_));
+  preview_contents_ = NULL;
+}
+
+void TabContentsContainerGtk::PopPreviewContents() {
+  if (!preview_contents_)
+    return;
+
+  RemovePreviewContents();
+
+  PackTabContents(tab_contents_);
+}
+
+void TabContentsContainerGtk::PackTabContents(TabContents* contents) {
+  if (!contents)
+    return;
+
+  gfx::NativeView widget = contents->GetNativeView();
+  if (widget) {
+    if (widget->parent != expanded_)
+      gtk_container_add(GTK_CONTAINER(expanded_), widget);
+    gtk_widget_show(widget);
+  }
+
+  // We need to make sure that we are below the findbar.
+  // Sometimes the content native view will be null.
+  if (contents->GetContentNativeView()) {
+    GdkWindow* content_gdk_window =
+        contents->GetContentNativeView()->window;
+    if (content_gdk_window)
+      gdk_window_lower(content_gdk_window);
+  }
+
+  contents->ShowContents();
+}
+
+void TabContentsContainerGtk::HideTabContents(TabContents* contents) {
+  if (!contents)
+    return;
+
+  gfx::NativeView widget = contents->GetNativeView();
+  if (widget)
+    gtk_widget_hide(widget);
+
+  contents->WasHidden();
+}
+
+void TabContentsContainerGtk::DetachTabContents(TabContents* tab_contents) {
+  gfx::NativeView widget = tab_contents->GetNativeView();
+
+  // It is possible to detach an unrealized, unparented TabContents if you
+  // slow things down enough in valgrind. Might happen in the real world, too.
+  if (widget && widget->parent) {
+    DCHECK_EQ(widget->parent, expanded_);
+    gtk_container_remove(GTK_CONTAINER(expanded_), widget);
+  }
+}
+
+void TabContentsContainerGtk::Observe(NotificationType type,
+                                      const NotificationSource& source,
+                                      const NotificationDetails& details) {
+  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
+
+  TabContentsDestroyed(Source<TabContents>(source).ptr());
+}
+
+void TabContentsContainerGtk::TabContentsDestroyed(TabContents* contents) {
+  // Sometimes, a TabContents is destroyed before we know about it. This allows
+  // us to clean up our state in case this happens.
+  if (contents == preview_contents_)
+    PopPreviewContents();
+  else if (contents == tab_contents_)
+    SetTabContents(NULL);
+  else
+    NOTREACHED();
+}
+
+// Prevent |preview_contents_| from getting focus via the tab key. If
+// |tab_contents_| exists, try to focus that. Otherwise, do nothing, but stop
+// event propagation. See bug http://crbug.com/63365
+gboolean TabContentsContainerGtk::OnFocus(GtkWidget* widget,
+                                          GtkDirectionType focus) {
+  if (preview_contents_) {
+    gtk_widget_child_focus(tab_contents_->GetContentNativeView(), focus);
+    return TRUE;
+  }
+
+  // No preview contents; let the default handler run.
+  return FALSE;
+}
+
+// -----------------------------------------------------------------------------
+// ViewIDUtil::Delegate implementation
+
+GtkWidget* TabContentsContainerGtk::GetWidgetForViewID(ViewID view_id) {
+  if (view_id == VIEW_ID_TAB_CONTAINER ||
+      view_id == VIEW_ID_TAB_CONTAINER_FOCUS_VIEW) {
+    return widget();
+  }
+
+  return NULL;
+}
+
+// -----------------------------------------------------------------------------
+
+// static
+void TabContentsContainerGtk::OnSetFloatingPosition(
+    GtkFloatingContainer* floating_container, GtkAllocation* allocation,
+    TabContentsContainerGtk* tab_contents_container) {
+  StatusBubbleGtk* status = tab_contents_container->status_bubble_;
+
+  // Look at the size request of the status bubble and tell the
+  // GtkFloatingContainer where we want it positioned.
+  GtkRequisition requisition;
+  gtk_widget_size_request(status->widget(), &requisition);
+
+  bool ltr = !base::i18n::IsRTL();
+
+  GValue value = { 0, };
+  g_value_init(&value, G_TYPE_INT);
+  if (ltr ^ status->flip_horizontally())  // Is it on the left?
+    g_value_set_int(&value, 0);
+  else
+    g_value_set_int(&value, allocation->width - requisition.width);
+  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
+                                   status->widget(), "x", &value);
+
+  int child_y = std::max(allocation->height - requisition.height, 0);
+  g_value_set_int(&value, child_y + status->y_offset());
+  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
+                                   status->widget(), "y", &value);
+  g_value_unset(&value);
+}
diff --git a/chrome/browser/ui/gtk/tab_contents_container_gtk.h b/chrome/browser/ui/gtk/tab_contents_container_gtk.h
new file mode 100644
index 0000000..49f57bb
--- /dev/null
+++ b/chrome/browser/ui/gtk/tab_contents_container_gtk.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TAB_CONTENTS_CONTAINER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TAB_CONTENTS_CONTAINER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class RenderViewHost;
+class StatusBubbleGtk;
+class TabContents;
+
+typedef struct _GtkFloatingContainer GtkFloatingContainer;
+
+class TabContentsContainerGtk : public NotificationObserver,
+                                public ViewIDUtil::Delegate {
+ public:
+  explicit TabContentsContainerGtk(StatusBubbleGtk* status_bubble);
+  ~TabContentsContainerGtk();
+
+  void Init();
+
+  // Make the specified tab visible.
+  void SetTabContents(TabContents* tab_contents);
+  TabContents* GetTabContents() const { return tab_contents_; }
+
+  // Gets the tab contents currently being displayed (either |tab_contents_| or
+  // |preview_contents_|).
+  TabContents* GetVisibleTabContents();
+
+  void SetPreviewContents(TabContents* preview);
+  void PopPreviewContents();
+
+  // Remove the tab from the hierarchy.
+  void DetachTabContents(TabContents* tab_contents);
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  GtkWidget* widget() { return floating_.get(); }
+
+  // ViewIDUtil::Delegate implementation ---------------------------------------
+  virtual GtkWidget* GetWidgetForViewID(ViewID id);
+
+ private:
+  // Called when a TabContents is destroyed. This gives us a chance to clean
+  // up our internal state if the TabContents is somehow destroyed before we
+  // get notified.
+  void TabContentsDestroyed(TabContents* contents);
+
+  // Handler for |floating_|'s "set-floating-position" signal. During this
+  // callback, we manually set the position of the status bubble.
+  static void OnSetFloatingPosition(
+      GtkFloatingContainer* container, GtkAllocation* allocation,
+      TabContentsContainerGtk* tab_contents_container);
+
+  // Add |contents| to the container and start showing it.
+  void PackTabContents(TabContents* contents);
+
+  // Stop showing |contents|.
+  void HideTabContents(TabContents* contents);
+
+  // Removes |preview_contents_|.
+  void RemovePreviewContents();
+
+  // Handle focus traversal on the tab contents container. Focus should not
+  // traverse to the preview contents.
+  CHROMEGTK_CALLBACK_1(TabContentsContainerGtk, gboolean, OnFocus,
+                       GtkDirectionType);
+
+  NotificationRegistrar registrar_;
+
+  // The TabContents for the currently selected tab. This will be showing unless
+  // there is a preview contents.
+  TabContents* tab_contents_;
+
+  // The current preview contents (for instant). If non-NULL, it will be
+  // visible.
+  TabContents* preview_contents_;
+
+  // The status bubble manager.  Always non-NULL.
+  StatusBubbleGtk* status_bubble_;
+
+  // Top of the TabContentsContainerGtk widget hierarchy. A cross between a
+  // GtkBin and a GtkFixed, |floating_| has |expanded_| as its one "real" child,
+  // and the various things that hang off the bottom (status bubble, etc) have
+  // their positions manually set in OnSetFloatingPosition.
+  OwnedWidgetGtk floating_;
+
+  // We insert and remove TabContents GtkWidgets into this expanded_. This
+  // should not be a GtkVBox since there were errors with timing where the vbox
+  // was horizontally split with the top half displaying the current TabContents
+  // and bottom half displaying the loading page.
+  GtkWidget* expanded_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabContentsContainerGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TAB_CONTENTS_CONTAINER_GTK_H_
diff --git a/chrome/browser/ui/gtk/tab_contents_drag_source.cc b/chrome/browser/ui/gtk/tab_contents_drag_source.cc
new file mode 100644
index 0000000..e858a68
--- /dev/null
+++ b/chrome/browser/ui/gtk/tab_contents_drag_source.cc
@@ -0,0 +1,380 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tab_contents_drag_source.h"
+
+#include <string>
+
+#include "base/file_util.h"
+#include "base/mime_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/drag_download_file.h"
+#include "chrome/browser/download/drag_download_util.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "net/base/file_stream.h"
+#include "net/base/net_util.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/gfx/gtk_util.h"
+#include "webkit/glue/webdropdata.h"
+
+using WebKit::WebDragOperation;
+using WebKit::WebDragOperationsMask;
+using WebKit::WebDragOperationNone;
+
+TabContentsDragSource::TabContentsDragSource(
+    TabContentsView* tab_contents_view)
+    : tab_contents_view_(tab_contents_view),
+      drag_pixbuf_(NULL),
+      drag_failed_(false),
+      drag_widget_(gtk_invisible_new()),
+      drag_context_(NULL),
+      drag_icon_(gtk_window_new(GTK_WINDOW_POPUP)) {
+  signals_.Connect(drag_widget_, "drag-failed",
+                   G_CALLBACK(OnDragFailedThunk), this);
+  signals_.Connect(drag_widget_, "drag-begin",
+                   G_CALLBACK(OnDragBeginThunk),
+                   this);
+  signals_.Connect(drag_widget_, "drag-end",
+                   G_CALLBACK(OnDragEndThunk), this);
+  signals_.Connect(drag_widget_, "drag-data-get",
+                   G_CALLBACK(OnDragDataGetThunk), this);
+
+  signals_.Connect(drag_icon_, "expose-event",
+                   G_CALLBACK(OnDragIconExposeThunk), this);
+}
+
+TabContentsDragSource::~TabContentsDragSource() {
+  // Break the current drag, if any.
+  if (drop_data_.get()) {
+    gtk_grab_add(drag_widget_);
+    gtk_grab_remove(drag_widget_);
+    MessageLoopForUI::current()->RemoveObserver(this);
+    drop_data_.reset();
+  }
+
+  gtk_widget_destroy(drag_widget_);
+  gtk_widget_destroy(drag_icon_);
+}
+
+TabContents* TabContentsDragSource::tab_contents() const {
+  return tab_contents_view_->tab_contents();
+}
+
+void TabContentsDragSource::StartDragging(const WebDropData& drop_data,
+                                          WebDragOperationsMask allowed_ops,
+                                          GdkEventButton* last_mouse_down,
+                                          const SkBitmap& image,
+                                          const gfx::Point& image_offset) {
+  // Guard against re-starting before previous drag completed.
+  if (drag_context_) {
+    NOTREACHED();
+    tab_contents()->SystemDragEnded();
+    return;
+  }
+
+  int targets_mask = 0;
+
+  if (!drop_data.plain_text.empty())
+    targets_mask |= ui::TEXT_PLAIN;
+  if (drop_data.url.is_valid()) {
+    targets_mask |= ui::TEXT_URI_LIST;
+    targets_mask |= ui::CHROME_NAMED_URL;
+    targets_mask |= ui::NETSCAPE_URL;
+  }
+  if (!drop_data.text_html.empty())
+    targets_mask |= ui::TEXT_HTML;
+  if (!drop_data.file_contents.empty())
+    targets_mask |= ui::CHROME_WEBDROP_FILE_CONTENTS;
+  if (!drop_data.download_metadata.empty() &&
+      drag_download_util::ParseDownloadMetadata(drop_data.download_metadata,
+                                                &wide_download_mime_type_,
+                                                &download_file_name_,
+                                                &download_url_)) {
+    targets_mask |= ui::DIRECT_SAVE_FILE;
+  }
+
+  // NOTE: Begin a drag even if no targets present. Otherwise, things like
+  // draggable list elements will not work.
+
+  drop_data_.reset(new WebDropData(drop_data));
+
+  // The image we get from WebKit makes heavy use of alpha-shading. This looks
+  // bad on non-compositing WMs. Fall back to the default drag icon.
+  if (!image.isNull() && gtk_util::IsScreenComposited())
+    drag_pixbuf_ = gfx::GdkPixbufFromSkBitmap(&image);
+  image_offset_ = image_offset;
+
+  GtkTargetList* list = ui::GetTargetListFromCodeMask(targets_mask);
+  if (targets_mask & ui::CHROME_WEBDROP_FILE_CONTENTS) {
+    drag_file_mime_type_ = gdk_atom_intern(
+        mime_util::GetDataMimeType(drop_data.file_contents).c_str(), FALSE);
+    gtk_target_list_add(list, drag_file_mime_type_,
+                        0, ui::CHROME_WEBDROP_FILE_CONTENTS);
+  }
+
+  drag_failed_ = false;
+  // If we don't pass an event, GDK won't know what event time to start grabbing
+  // mouse events. Technically it's the mouse motion event and not the mouse
+  // down event that causes the drag, but there's no reliable way to know
+  // *which* motion event initiated the drag, so this will have to do.
+  // TODO(estade): This can sometimes be very far off, e.g. if the user clicks
+  // and holds and doesn't start dragging for a long time. I doubt it matters
+  // much, but we should probably look into the possibility of getting the
+  // initiating event from webkit.
+  drag_context_ = gtk_drag_begin(drag_widget_, list,
+      gtk_util::WebDragOpToGdkDragAction(allowed_ops),
+      1,  // Drags are always initiated by the left button.
+      reinterpret_cast<GdkEvent*>(last_mouse_down));
+  // The drag adds a ref; let it own the list.
+  gtk_target_list_unref(list);
+
+  // Sometimes the drag fails to start; |context| will be NULL and we won't
+  // get a drag-end signal.
+  if (!drag_context_) {
+    drag_failed_ = true;
+    drop_data_.reset();
+    tab_contents()->SystemDragEnded();
+    return;
+  }
+
+  MessageLoopForUI::current()->AddObserver(this);
+}
+
+void TabContentsDragSource::WillProcessEvent(GdkEvent* event) {
+  // No-op.
+}
+
+void TabContentsDragSource::DidProcessEvent(GdkEvent* event) {
+  if (event->type != GDK_MOTION_NOTIFY)
+    return;
+
+  GdkEventMotion* event_motion = reinterpret_cast<GdkEventMotion*>(event);
+  gfx::Point client = gtk_util::ClientPoint(GetContentNativeView());
+
+  if (tab_contents()->render_view_host()) {
+    tab_contents()->render_view_host()->DragSourceMovedTo(
+        client.x(), client.y(),
+        static_cast<int>(event_motion->x_root),
+        static_cast<int>(event_motion->y_root));
+  }
+}
+
+void TabContentsDragSource::OnDragDataGet(GtkWidget* sender,
+    GdkDragContext* context, GtkSelectionData* selection_data,
+    guint target_type, guint time) {
+  const int kBitsPerByte = 8;
+
+  switch (target_type) {
+    case ui::TEXT_PLAIN: {
+      std::string utf8_text = UTF16ToUTF8(drop_data_->plain_text);
+      gtk_selection_data_set_text(selection_data, utf8_text.c_str(),
+                                  utf8_text.length());
+      break;
+    }
+
+    case ui::TEXT_HTML: {
+      // TODO(estade): change relative links to be absolute using
+      // |html_base_url|.
+      std::string utf8_text = UTF16ToUTF8(drop_data_->text_html);
+      gtk_selection_data_set(selection_data,
+                             ui::GetAtomForTarget(ui::TEXT_HTML),
+                             kBitsPerByte,
+                             reinterpret_cast<const guchar*>(utf8_text.c_str()),
+                             utf8_text.length());
+      break;
+    }
+
+    case ui::TEXT_URI_LIST:
+    case ui::CHROME_NAMED_URL:
+    case ui::NETSCAPE_URL: {
+      ui::WriteURLWithName(selection_data, drop_data_->url,
+                           drop_data_->url_title, target_type);
+      break;
+    }
+
+    case ui::CHROME_WEBDROP_FILE_CONTENTS: {
+      gtk_selection_data_set(
+          selection_data,
+          drag_file_mime_type_, kBitsPerByte,
+          reinterpret_cast<const guchar*>(drop_data_->file_contents.data()),
+          drop_data_->file_contents.length());
+      break;
+    }
+
+    case ui::DIRECT_SAVE_FILE: {
+      char status_code = 'E';
+
+      // Retrieves the full file path (in file URL format) provided by the
+      // drop target by reading from the source window's XdndDirectSave0
+      // property.
+      gint file_url_len = 0;
+      guchar* file_url_value = NULL;
+      if (gdk_property_get(context->source_window,
+                           ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE),
+                           ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET),
+                           0,
+                           1024,
+                           FALSE,
+                           NULL,
+                           NULL,
+                           &file_url_len,
+                           &file_url_value) &&
+          file_url_value) {
+        // Convert from the file url to the file path.
+        GURL file_url(std::string(reinterpret_cast<char*>(file_url_value),
+                                  file_url_len));
+        g_free(file_url_value);
+        FilePath file_path;
+        if (net::FileURLToFilePath(file_url, &file_path)) {
+          // Open the file as a stream.
+          net::FileStream* file_stream =
+              drag_download_util::CreateFileStreamForDrop(&file_path);
+          if (file_stream) {
+              // Start downloading the file to the stream.
+              TabContents* tab_contents = tab_contents_view_->tab_contents();
+              scoped_refptr<DragDownloadFile> drag_file_downloader =
+                  new DragDownloadFile(file_path,
+                                       linked_ptr<net::FileStream>(file_stream),
+                                       download_url_,
+                                       tab_contents->GetURL(),
+                                       tab_contents->encoding(),
+                                       tab_contents);
+              drag_file_downloader->Start(
+                  new drag_download_util::PromiseFileFinalizer(
+                      drag_file_downloader));
+
+              // Set the status code to success.
+              status_code = 'S';
+          }
+        }
+
+        // Return the status code to the file manager.
+        gtk_selection_data_set(selection_data,
+                               selection_data->target,
+                               8,
+                               reinterpret_cast<guchar*>(&status_code),
+                               1);
+      }
+      break;
+    }
+
+    default:
+      NOTREACHED();
+  }
+}
+
+gboolean TabContentsDragSource::OnDragFailed(GtkWidget* sender,
+                                             GdkDragContext* context,
+                                             GtkDragResult result) {
+  drag_failed_ = true;
+
+  gfx::Point root = gtk_util::ScreenPoint(GetContentNativeView());
+  gfx::Point client = gtk_util::ClientPoint(GetContentNativeView());
+
+  if (tab_contents()->render_view_host()) {
+    tab_contents()->render_view_host()->DragSourceEndedAt(
+        client.x(), client.y(), root.x(), root.y(),
+        WebDragOperationNone);
+  }
+
+  // Let the native failure animation run.
+  return FALSE;
+}
+
+void TabContentsDragSource::OnDragBegin(GtkWidget* sender,
+                                        GdkDragContext* drag_context) {
+  if (!download_url_.is_empty()) {
+    // Generate the file name based on both mime type and proposed file name.
+    std::string download_mime_type = UTF16ToUTF8(wide_download_mime_type_);
+    std::string content_disposition("attachment; filename=");
+    content_disposition += download_file_name_.value();
+    FilePath generated_download_file_name;
+    download_util::GenerateFileName(download_url_,
+                                    content_disposition,
+                                    std::string(),
+                                    download_mime_type,
+                                    &generated_download_file_name);
+
+    // Pass the file name to the drop target by setting the source window's
+    // XdndDirectSave0 property.
+    gdk_property_change(drag_context->source_window,
+                        ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE),
+                        ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET),
+                        8,
+                        GDK_PROP_MODE_REPLACE,
+                        reinterpret_cast<const guchar*>(
+                            generated_download_file_name.value().c_str()),
+                        generated_download_file_name.value().length());
+  }
+
+  if (drag_pixbuf_) {
+    gtk_widget_set_size_request(drag_icon_,
+                                gdk_pixbuf_get_width(drag_pixbuf_),
+                                gdk_pixbuf_get_height(drag_pixbuf_));
+
+    // We only need to do this once.
+    if (!GTK_WIDGET_REALIZED(drag_icon_)) {
+      GdkScreen* screen = gtk_widget_get_screen(drag_icon_);
+      GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen);
+      if (rgba)
+        gtk_widget_set_colormap(drag_icon_, rgba);
+    }
+
+    gtk_drag_set_icon_widget(drag_context, drag_icon_,
+                             image_offset_.x(), image_offset_.y());
+  }
+}
+
+void TabContentsDragSource::OnDragEnd(GtkWidget* sender,
+                                      GdkDragContext* drag_context) {
+  if (drag_pixbuf_) {
+    g_object_unref(drag_pixbuf_);
+    drag_pixbuf_ = NULL;
+  }
+
+  MessageLoopForUI::current()->RemoveObserver(this);
+
+  if (!download_url_.is_empty()) {
+    gdk_property_delete(drag_context->source_window,
+                        ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE));
+  }
+
+  if (!drag_failed_) {
+    gfx::Point root = gtk_util::ScreenPoint(GetContentNativeView());
+    gfx::Point client = gtk_util::ClientPoint(GetContentNativeView());
+
+    if (tab_contents()->render_view_host()) {
+      tab_contents()->render_view_host()->DragSourceEndedAt(
+          client.x(), client.y(), root.x(), root.y(),
+          gtk_util::GdkDragActionToWebDragOp(drag_context->action));
+    }
+  }
+
+  tab_contents()->SystemDragEnded();
+
+  drop_data_.reset();
+  drag_context_ = NULL;
+}
+
+gfx::NativeView TabContentsDragSource::GetContentNativeView() const {
+  return tab_contents_view_->GetContentNativeView();
+}
+
+gboolean TabContentsDragSource::OnDragIconExpose(GtkWidget* sender,
+                                                 GdkEventExpose* event) {
+  cairo_t* cr = gdk_cairo_create(event->window);
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+  gdk_cairo_set_source_pixbuf(cr, drag_pixbuf_, 0, 0);
+  cairo_paint(cr);
+  cairo_destroy(cr);
+
+  return TRUE;
+}
diff --git a/chrome/browser/ui/gtk/tab_contents_drag_source.h b/chrome/browser/ui/gtk/tab_contents_drag_source.h
new file mode 100644
index 0000000..1fa638c
--- /dev/null
+++ b/chrome/browser/ui/gtk/tab_contents_drag_source.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TAB_CONTENTS_DRAG_SOURCE_H_
+#define CHROME_BROWSER_UI_GTK_TAB_CONTENTS_DRAG_SOURCE_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "base/string16.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/gtk/gtk_signal_registrar.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
+
+class SkBitmap;
+class TabContents;
+class TabContentsView;
+struct WebDropData;
+
+// TabContentsDragSource takes care of managing the drag from a TabContents
+// with Gtk.
+class TabContentsDragSource : public MessageLoopForUI::Observer {
+ public:
+  explicit TabContentsDragSource(TabContentsView* tab_contents_view);
+  ~TabContentsDragSource();
+
+  TabContents* tab_contents() const;
+
+  // Starts a drag for the tab contents this TabContentsDragSource was
+  // created for.
+  void StartDragging(const WebDropData& drop_data,
+                     WebKit::WebDragOperationsMask allowed_ops,
+                     GdkEventButton* last_mouse_down,
+                     const SkBitmap& image,
+                     const gfx::Point& image_offset);
+
+  // MessageLoop::Observer implementation:
+  virtual void WillProcessEvent(GdkEvent* event);
+  virtual void DidProcessEvent(GdkEvent* event);
+
+ private:
+  CHROMEGTK_CALLBACK_2(TabContentsDragSource, gboolean, OnDragFailed,
+                       GdkDragContext*, GtkDragResult);
+  CHROMEGTK_CALLBACK_1(TabContentsDragSource, void, OnDragBegin,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_1(TabContentsDragSource, void, OnDragEnd,
+                       GdkDragContext*);
+  CHROMEGTK_CALLBACK_4(TabContentsDragSource, void, OnDragDataGet,
+                       GdkDragContext*, GtkSelectionData*, guint, guint);
+  CHROMEGTK_CALLBACK_1(TabContentsDragSource, gboolean, OnDragIconExpose,
+                       GdkEventExpose*);
+
+  gfx::NativeView GetContentNativeView() const;
+
+  // The view we're manging the drag for.
+  TabContentsView* tab_contents_view_;
+
+  // The drop data for the current drag (for drags that originate in the render
+  // view). Non-NULL iff there is a current drag.
+  scoped_ptr<WebDropData> drop_data_;
+
+  // The image used for depicting the drag, and the offset between the cursor
+  // and the top left pixel.
+  GdkPixbuf* drag_pixbuf_;
+  gfx::Point image_offset_;
+
+  // The mime type for the file contents of the current drag (if any).
+  GdkAtom drag_file_mime_type_;
+
+  // Whether the current drag has failed. Meaningless if we are not the source
+  // for a current drag.
+  bool drag_failed_;
+
+  // This is the widget we use to initiate drags. Since we don't use the
+  // renderer widget, we can persist drags even when our contents is switched
+  // out. We can't use an OwnedWidgetGtk because the GtkInvisible widget
+  // initialization code sinks the reference.
+  GtkWidget* drag_widget_;
+
+  // Context created once drag starts.  A NULL value indicates that there is
+  // no drag currently in progress.
+  GdkDragContext* drag_context_;
+
+  // The file mime type for a drag-out download.
+  string16 wide_download_mime_type_;
+
+  // The file name to be saved to for a drag-out download.
+  FilePath download_file_name_;
+
+  // The URL to download from for a drag-out download.
+  GURL download_url_;
+
+  // The widget that provides visual feedback for the drag. We can't use
+  // an OwnedWidgetGtk because the GtkWindow initialization code sinks
+  // the reference.
+  GtkWidget* drag_icon_;
+
+  ui::GtkSignalRegistrar signals_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabContentsDragSource);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TAB_CONTENTS_DRAG_SOURCE_H_
diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
new file mode 100644
index 0000000..741eb36
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
@@ -0,0 +1,788 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h"
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/tabs/dragged_tab_gtk.h"
+#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/notification_source.h"
+
+namespace {
+
+// Delay, in ms, during dragging before we bring a window to front.
+const int kBringToFrontDelay = 750;
+
+// Used to determine how far a tab must obscure another tab in order to swap
+// their indexes.
+const int kHorizontalMoveThreshold = 16;  // pixels
+
+// How far a drag must pull a tab out of the tabstrip in order to detach it.
+const int kVerticalDetachMagnetism = 15;  // pixels
+
+}  // namespace
+
+DraggedTabControllerGtk::DraggedTabControllerGtk(TabGtk* source_tab,
+                                                 TabStripGtk* source_tabstrip)
+    : dragged_contents_(NULL),
+      original_delegate_(NULL),
+      source_tab_(source_tab),
+      source_tabstrip_(source_tabstrip),
+      source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)),
+      attached_tabstrip_(source_tabstrip),
+      in_destructor_(false),
+      last_move_screen_x_(0),
+      mini_(source_tabstrip->model()->IsMiniTab(source_model_index_)),
+      pinned_(source_tabstrip->model()->IsTabPinned(source_model_index_)) {
+  SetDraggedContents(
+      source_tabstrip_->model()->GetTabContentsAt(source_model_index_));
+}
+
+DraggedTabControllerGtk::~DraggedTabControllerGtk() {
+  in_destructor_ = true;
+  CleanUpSourceTab();
+  // Need to delete the dragged tab here manually _before_ we reset the dragged
+  // contents to NULL, otherwise if the view is animating to its destination
+  // bounds, it won't be able to clean up properly since its cleanup routine
+  // uses GetIndexForDraggedContents, which will be invalid.
+  dragged_tab_.reset();
+  SetDraggedContents(NULL);
+}
+
+void DraggedTabControllerGtk::CaptureDragInfo(const gfx::Point& mouse_offset) {
+  start_screen_point_ = GetCursorScreenPoint();
+  mouse_offset_ = mouse_offset;
+}
+
+void DraggedTabControllerGtk::Drag() {
+  if (!source_tab_ || !dragged_contents_)
+    return;
+
+  bring_to_front_timer_.Stop();
+
+  EnsureDraggedTab();
+
+  // Before we get to dragging anywhere, ensure that we consider ourselves
+  // attached to the source tabstrip.
+  if (source_tab_->IsVisible()) {
+    Attach(source_tabstrip_, gfx::Point());
+  }
+
+  if (!source_tab_->IsVisible()) {
+    // TODO(jhawkins): Save focus.
+    ContinueDragging();
+  }
+}
+
+bool DraggedTabControllerGtk::EndDrag(bool canceled) {
+  return EndDragImpl(canceled ? CANCELED : NORMAL);
+}
+
+TabGtk* DraggedTabControllerGtk::GetDragSourceTabForContents(
+    TabContents* contents) const {
+  if (attached_tabstrip_ == source_tabstrip_)
+    return contents == dragged_contents_->tab_contents() ? source_tab_ : NULL;
+  return NULL;
+}
+
+bool DraggedTabControllerGtk::IsDragSourceTab(const TabGtk* tab) const {
+  return source_tab_ == tab;
+}
+
+bool DraggedTabControllerGtk::IsTabDetached(const TabGtk* tab) const {
+  if (!IsDragSourceTab(tab))
+    return false;
+  return (attached_tabstrip_ == NULL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DraggedTabControllerGtk, TabContentsDelegate implementation:
+
+void DraggedTabControllerGtk::OpenURLFromTab(TabContents* source,
+                                             const GURL& url,
+                                             const GURL& referrer,
+                                             WindowOpenDisposition disposition,
+                                             PageTransition::Type transition) {
+  if (original_delegate_) {
+    if (disposition == CURRENT_TAB)
+      disposition = NEW_WINDOW;
+
+    original_delegate_->OpenURLFromTab(source, url, referrer,
+                                       disposition, transition);
+  }
+}
+
+void DraggedTabControllerGtk::NavigationStateChanged(const TabContents* source,
+                                                     unsigned changed_flags) {
+  if (dragged_tab_.get())
+    dragged_tab_->Update();
+}
+
+void DraggedTabControllerGtk::AddNewContents(TabContents* source,
+                                             TabContents* new_contents,
+                                             WindowOpenDisposition disposition,
+                                             const gfx::Rect& initial_pos,
+                                             bool user_gesture) {
+  DCHECK(disposition != CURRENT_TAB);
+
+  // Theoretically could be called while dragging if the page tries to
+  // spawn a window. Route this message back to the browser in most cases.
+  if (original_delegate_) {
+    original_delegate_->AddNewContents(source, new_contents, disposition,
+                                       initial_pos, user_gesture);
+  }
+}
+
+void DraggedTabControllerGtk::ActivateContents(TabContents* contents) {
+  // Ignored.
+}
+
+void DraggedTabControllerGtk::DeactivateContents(TabContents* contents) {
+  // Ignored.
+}
+
+void DraggedTabControllerGtk::LoadingStateChanged(TabContents* source) {
+  // TODO(jhawkins): It would be nice to respond to this message by changing the
+  // screen shot in the dragged tab.
+  if (dragged_tab_.get())
+    dragged_tab_->Update();
+}
+
+void DraggedTabControllerGtk::CloseContents(TabContents* source) {
+  // Theoretically could be called by a window. Should be ignored
+  // because window.close() is ignored (usually, even though this
+  // method gets called.)
+}
+
+void DraggedTabControllerGtk::MoveContents(TabContents* source,
+                                        const gfx::Rect& pos) {
+  // Theoretically could be called by a web page trying to move its
+  // own window. Should be ignored since we're moving the window...
+}
+
+bool DraggedTabControllerGtk::IsPopup(const TabContents* source) const {
+  return false;
+}
+
+void DraggedTabControllerGtk::ToolbarSizeChanged(TabContents* source,
+                                                 bool finished) {
+  // Dragged tabs don't care about this.
+}
+
+void DraggedTabControllerGtk::UpdateTargetURL(TabContents* source,
+                                              const GURL& url) {
+  // Ignored.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DraggedTabControllerGtk, NotificationObserver implementation:
+
+void DraggedTabControllerGtk::Observe(NotificationType type,
+                                   const NotificationSource& source,
+                                   const NotificationDetails& details) {
+  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
+  DCHECK(Source<TabContentsWrapper>(source).ptr() == dragged_contents_);
+  EndDragImpl(TAB_DESTROYED);
+}
+
+void DraggedTabControllerGtk::InitWindowCreatePoint() {
+  window_create_point_.SetPoint(mouse_offset_.x(), mouse_offset_.y());
+}
+
+gfx::Point DraggedTabControllerGtk::GetWindowCreatePoint() const {
+  gfx::Point cursor_point = GetCursorScreenPoint();
+  return gfx::Point(cursor_point.x() - window_create_point_.x(),
+                    cursor_point.y() - window_create_point_.y());
+}
+
+void DraggedTabControllerGtk::SetDraggedContents(
+    TabContentsWrapper* new_contents) {
+  if (dragged_contents_) {
+    registrar_.Remove(this,
+                      NotificationType::TAB_CONTENTS_DESTROYED,
+                      Source<TabContentsWrapper>(dragged_contents_));
+    if (original_delegate_)
+      dragged_contents_->tab_contents()->set_delegate(original_delegate_);
+  }
+  original_delegate_ = NULL;
+  dragged_contents_ = new_contents;
+  if (dragged_contents_) {
+    registrar_.Add(this,
+                   NotificationType::TAB_CONTENTS_DESTROYED,
+                   Source<TabContentsWrapper>(dragged_contents_));
+
+    // We need to be the delegate so we receive messages about stuff,
+    // otherwise our dragged_contents() may be replaced and subsequently
+    // collected/destroyed while the drag is in process, leading to
+    // nasty crashes.
+    original_delegate_ = dragged_contents_->tab_contents()->delegate();
+    dragged_contents_->tab_contents()->set_delegate(this);
+  }
+}
+
+void DraggedTabControllerGtk::ContinueDragging() {
+  // TODO(jhawkins): We don't handle the situation where the last tab is dragged
+  // out of a window, so we'll just go with the way Windows handles dragging for
+  // now.
+  gfx::Point screen_point = GetCursorScreenPoint();
+
+  // Determine whether or not we have dragged over a compatible TabStrip in
+  // another browser window. If we have, we should attach to it and start
+  // dragging within it.
+#if defined(OS_CHROMEOS)
+  // We don't allow detaching on chrome os.
+  TabStripGtk* target_tabstrip = source_tabstrip_;
+#else
+  TabStripGtk* target_tabstrip = GetTabStripForPoint(screen_point);
+#endif
+  if (target_tabstrip != attached_tabstrip_) {
+    // Make sure we're fully detached from whatever TabStrip we're attached to
+    // (if any).
+    if (attached_tabstrip_)
+      Detach();
+
+    if (target_tabstrip)
+      Attach(target_tabstrip, screen_point);
+  }
+
+  if (!target_tabstrip) {
+    bring_to_front_timer_.Start(
+        base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this,
+        &DraggedTabControllerGtk::BringWindowUnderMouseToFront);
+  }
+
+  MoveTab(screen_point);
+}
+
+void DraggedTabControllerGtk::MoveTab(const gfx::Point& screen_point) {
+  gfx::Point dragged_tab_point = GetDraggedTabPoint(screen_point);
+
+  if (attached_tabstrip_) {
+    TabStripModel* attached_model = attached_tabstrip_->model();
+    int from_index = attached_model->GetIndexOfTabContents(dragged_contents_);
+
+    // Determine the horizontal move threshold. This is dependent on the width
+    // of tabs. The smaller the tabs compared to the standard size, the smaller
+    // the threshold.
+    double unselected, selected;
+    attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected);
+    double ratio = unselected / TabGtk::GetStandardSize().width();
+    int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold);
+
+    // Update the model, moving the TabContents from one index to another. Do
+    // this only if we have moved a minimum distance since the last reorder (to
+    // prevent jitter).
+    if (abs(screen_point.x() - last_move_screen_x_) > threshold) {
+      gfx::Rect bounds = GetDraggedTabTabStripBounds(dragged_tab_point);
+      int to_index = GetInsertionIndexForDraggedBounds(bounds, true);
+      to_index = NormalizeIndexToAttachedTabStrip(to_index);
+      if (from_index != to_index) {
+        last_move_screen_x_ = screen_point.x();
+        attached_model->MoveTabContentsAt(from_index, to_index, true);
+      }
+    }
+  }
+
+  // Move the dragged tab. There are no changes to the model if we're detached.
+  dragged_tab_->MoveTo(dragged_tab_point);
+}
+
+TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint(
+    const gfx::Point& screen_point) {
+  GtkWidget* dragged_window = dragged_tab_->widget();
+  dock_windows_.insert(dragged_window);
+  gfx::NativeWindow local_window =
+      DockInfo::GetLocalProcessWindowAtPoint(screen_point, dock_windows_);
+  dock_windows_.erase(dragged_window);
+  if (!local_window)
+    return NULL;
+
+  BrowserWindowGtk* browser =
+      BrowserWindowGtk::GetBrowserWindowForNativeWindow(local_window);
+  if (!browser)
+    return NULL;
+
+  TabStripGtk* other_tabstrip = browser->tabstrip();
+  if (!other_tabstrip->IsCompatibleWith(source_tabstrip_))
+    return NULL;
+
+  return GetTabStripIfItContains(other_tabstrip, screen_point);
+}
+
+TabStripGtk* DraggedTabControllerGtk::GetTabStripIfItContains(
+    TabStripGtk* tabstrip, const gfx::Point& screen_point) const {
+  // Make sure the specified screen point is actually within the bounds of the
+  // specified tabstrip...
+  gfx::Rect tabstrip_bounds =
+      gtk_util::GetWidgetScreenBounds(tabstrip->tabstrip_.get());
+  if (screen_point.x() < tabstrip_bounds.right() &&
+      screen_point.x() >= tabstrip_bounds.x()) {
+    // TODO(beng): make this be relative to the start position of the mouse for
+    // the source TabStrip.
+    int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism;
+    int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism;
+    if (screen_point.y() >= lower_threshold &&
+        screen_point.y() <= upper_threshold) {
+      return tabstrip;
+    }
+  }
+
+  return NULL;
+}
+
+void DraggedTabControllerGtk::Attach(TabStripGtk* attached_tabstrip,
+                                     const gfx::Point& screen_point) {
+  attached_tabstrip_ = attached_tabstrip;
+  InitWindowCreatePoint();
+  attached_tabstrip_->GenerateIdealBounds();
+
+  TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
+
+  // Update the tab first, so we can ask it for its bounds and determine
+  // where to insert the hidden tab.
+
+  // If this is the first time Attach is called for this drag, we're attaching
+  // to the source tabstrip, and we should assume the tab count already
+  // includes this tab since we haven't been detached yet. If we don't do this,
+  // the dragged representation will be a different size to others in the
+  // tabstrip.
+  int tab_count = attached_tabstrip_->GetTabCount();
+  int mini_tab_count = attached_tabstrip_->GetMiniTabCount();
+  if (!tab)
+    ++tab_count;
+  double unselected_width = 0, selected_width = 0;
+  attached_tabstrip_->GetDesiredTabWidths(tab_count, mini_tab_count,
+                                          &unselected_width, &selected_width);
+  int dragged_tab_width =
+      mini_ ? TabGtk::GetMiniWidth() : static_cast<int>(selected_width);
+  dragged_tab_->Attach(dragged_tab_width);
+
+  if (!tab) {
+    // There is no tab in |attached_tabstrip| that corresponds to the dragged
+    // TabContents. We must now create one.
+
+    // Remove ourselves as the delegate now that the dragged TabContents is
+    // being inserted back into a Browser.
+    dragged_contents_->tab_contents()->set_delegate(NULL);
+    original_delegate_ = NULL;
+
+    // Return the TabContents' to normalcy.
+    dragged_contents_->tab_contents()->set_capturing_contents(false);
+
+    // We need to ask the tabstrip we're attached to ensure that the ideal
+    // bounds for all its tabs are correctly generated, because the calculation
+    // in GetInsertionIndexForDraggedBounds needs them to be to figure out the
+    // appropriate insertion index.
+    attached_tabstrip_->GenerateIdealBounds();
+
+    // Inserting counts as a move. We don't want the tabs to jitter when the
+    // user moves the tab immediately after attaching it.
+    last_move_screen_x_ = screen_point.x();
+
+    // Figure out where to insert the tab based on the bounds of the dragged
+    // representation and the ideal bounds of the other tabs already in the
+    // strip. ("ideal bounds" are stable even if the tabs' actual bounds are
+    // changing due to animation).
+    gfx::Rect bounds = GetDraggedTabTabStripBounds(screen_point);
+    int index = GetInsertionIndexForDraggedBounds(bounds, false);
+    attached_tabstrip_->model()->InsertTabContentsAt(
+        index, dragged_contents_,
+        TabStripModel::ADD_SELECTED |
+            (pinned_ ? TabStripModel::ADD_PINNED : 0));
+
+    tab = GetTabMatchingDraggedContents(attached_tabstrip_);
+  }
+  DCHECK(tab);  // We should now have a tab.
+  tab->SetVisible(false);
+  tab->set_dragging(true);
+
+  // TODO(jhawkins): Move the corresponding window to the front.
+}
+
+void DraggedTabControllerGtk::Detach() {
+  // Update the Model.
+  TabStripModel* attached_model = attached_tabstrip_->model();
+  int index = attached_model->GetIndexOfTabContents(dragged_contents_);
+  if (index >= 0 && index < attached_model->count()) {
+    // Sometimes, DetachTabContentsAt has consequences that result in
+    // attached_tabstrip_ being set to NULL, so we need to save it first.
+    TabStripGtk* attached_tabstrip = attached_tabstrip_;
+    attached_model->DetachTabContentsAt(index);
+    attached_tabstrip->SchedulePaint();
+  }
+
+  // If we've removed the last tab from the tabstrip, hide the frame now.
+  if (attached_model->empty())
+    HideWindow();
+
+  // Update the dragged tab. This NULL check is necessary apparently in some
+  // conditions during automation where the view_ is destroyed inside a
+  // function call preceding this point but after it is created.
+  if (dragged_tab_.get()) {
+    dragged_tab_->Detach();
+  }
+
+  // Detaching resets the delegate, but we still want to be the delegate.
+  dragged_contents_->tab_contents()->set_delegate(this);
+
+  attached_tabstrip_ = NULL;
+}
+
+gfx::Point DraggedTabControllerGtk::ConvertScreenPointToTabStripPoint(
+    TabStripGtk* tabstrip, const gfx::Point& screen_point) {
+  gfx::Point tabstrip_screen_point =
+      gtk_util::GetWidgetScreenPosition(tabstrip->tabstrip_.get());
+  return screen_point.Subtract(tabstrip_screen_point);
+}
+
+gfx::Rect DraggedTabControllerGtk::GetDraggedTabTabStripBounds(
+    const gfx::Point& screen_point) {
+  gfx::Point client_point =
+      ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point);
+  gfx::Size tab_size = dragged_tab_->attached_tab_size();
+  return gfx::Rect(client_point.x(), client_point.y(),
+                   tab_size.width(), tab_size.height());
+}
+
+int DraggedTabControllerGtk::GetInsertionIndexForDraggedBounds(
+    const gfx::Rect& dragged_bounds,
+    bool is_tab_attached) const {
+  int right_tab_x = 0;
+
+  // TODO(jhawkins): Handle RTL layout.
+
+  // Divides each tab into two halves to see if the dragged tab has crossed
+  // the halfway boundary necessary to move past the next tab.
+  int index = -1;
+  for (int i = 0; i < attached_tabstrip_->GetTabCount(); i++) {
+    gfx::Rect ideal_bounds = attached_tabstrip_->GetIdealBounds(i);
+
+    gfx::Rect left_half = ideal_bounds;
+    left_half.set_width(left_half.width() / 2);
+
+    gfx::Rect right_half = ideal_bounds;
+    right_half.set_width(ideal_bounds.width() - left_half.width());
+    right_half.set_x(left_half.right());
+
+    right_tab_x = right_half.right();
+
+    if (dragged_bounds.x() >= right_half.x() &&
+        dragged_bounds.x() < right_half.right()) {
+      index = i + 1;
+      break;
+    } else if (dragged_bounds.x() >= left_half.x() &&
+               dragged_bounds.x() < left_half.right()) {
+      index = i;
+      break;
+    }
+  }
+
+  if (index == -1) {
+    if (dragged_bounds.right() > right_tab_x)
+      index = attached_tabstrip_->model()->count();
+    else
+      index = 0;
+  }
+
+  index = attached_tabstrip_->model()->ConstrainInsertionIndex(index, mini_);
+  if (is_tab_attached && mini_ &&
+      index == attached_tabstrip_->model()->IndexOfFirstNonMiniTab()) {
+    index--;
+  }
+
+  return index;
+}
+
+gfx::Point DraggedTabControllerGtk::GetDraggedTabPoint(
+    const gfx::Point& screen_point) {
+  int x = screen_point.x() - mouse_offset_.x();
+  int y = screen_point.y() - mouse_offset_.y();
+
+  // If we're not attached, we just use x and y from above.
+  if (attached_tabstrip_) {
+    gfx::Rect tabstrip_bounds =
+        gtk_util::GetWidgetScreenBounds(attached_tabstrip_->tabstrip_.get());
+    // Snap the dragged tab to the tabstrip if we are attached, detaching
+    // only when the mouse position (screen_point) exceeds the screen bounds
+    // of the tabstrip.
+    if (x < tabstrip_bounds.x() && screen_point.x() >= tabstrip_bounds.x())
+      x = tabstrip_bounds.x();
+
+    gfx::Size tab_size = dragged_tab_->attached_tab_size();
+    int vertical_drag_magnetism = tab_size.height() * 2;
+    int vertical_detach_point = tabstrip_bounds.y() - vertical_drag_magnetism;
+    if (y < tabstrip_bounds.y() && screen_point.y() >= vertical_detach_point)
+      y = tabstrip_bounds.y();
+
+    // Make sure the tab can't be dragged off the right side of the tabstrip
+    // unless the mouse pointer passes outside the bounds of the strip by
+    // clamping the position of the dragged window to the tabstrip width less
+    // the width of one tab until the mouse pointer (screen_point) exceeds the
+    // screen bounds of the tabstrip.
+    int max_x = tabstrip_bounds.right() - tab_size.width();
+    int max_y = tabstrip_bounds.bottom() - tab_size.height();
+    if (x > max_x && screen_point.x() <= tabstrip_bounds.right())
+      x = max_x;
+    if (y > max_y && screen_point.y() <=
+        (tabstrip_bounds.bottom() + vertical_drag_magnetism)) {
+      y = max_y;
+    }
+#if defined(OS_CHROMEOS)
+    // We don't allow detaching on chromeos. This restricts dragging to the
+    // source window.
+    x = std::min(std::max(x, tabstrip_bounds.x()), max_x);
+    y = tabstrip_bounds.y();
+#endif
+  }
+  return gfx::Point(x, y);
+}
+
+int DraggedTabControllerGtk::NormalizeIndexToAttachedTabStrip(int index) const {
+  if (index >= attached_tabstrip_->model_->count())
+    return attached_tabstrip_->model_->count() - 1;
+  if (index == TabStripModel::kNoTab)
+    return 0;
+  return index;
+}
+
+TabGtk* DraggedTabControllerGtk::GetTabMatchingDraggedContents(
+    TabStripGtk* tabstrip) const {
+  int index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_);
+  return index == TabStripModel::kNoTab ? NULL : tabstrip->GetTabAt(index);
+}
+
+bool DraggedTabControllerGtk::EndDragImpl(EndDragType type) {
+  bring_to_front_timer_.Stop();
+
+  // WARNING: this may be invoked multiple times. In particular, if deletion
+  // occurs after a delay (as it does when the tab is released in the original
+  // tab strip) and the navigation controller/tab contents is deleted before
+  // the animation finishes, this is invoked twice. The second time through
+  // type == TAB_DESTROYED.
+
+  bool destroy_now = true;
+  if (type == TAB_DESTROYED) {
+    // If we get here it means the NavigationController is going down. Don't
+    // attempt to do any cleanup other than resetting the delegate (if we're
+    // still the delegate).
+    if (dragged_contents_ &&
+        dragged_contents_->tab_contents()->delegate() == this)
+      dragged_contents_->tab_contents()->set_delegate(NULL);
+    dragged_contents_ = NULL;
+  } else {
+    // If we never received a drag-motion event, the drag will never have
+    // started in the sense that |dragged_tab_| will be NULL. We don't need to
+    // revert or complete the drag in that case.
+    if (dragged_tab_.get()) {
+      if (type == CANCELED) {
+        RevertDrag();
+      } else {
+        destroy_now = CompleteDrag();
+      }
+    }
+
+    if (dragged_contents_ &&
+        dragged_contents_->tab_contents()->delegate() == this)
+      dragged_contents_->tab_contents()->set_delegate(original_delegate_);
+  }
+
+  // The delegate of the dragged contents should have been reset. Unset the
+  // original delegate so that we don't attempt to reset the delegate when
+  // deleted.
+  DCHECK(!dragged_contents_ ||
+         dragged_contents_->tab_contents()->delegate() != this);
+  original_delegate_ = NULL;
+
+  // If we're not destroyed now, we'll be destroyed asynchronously later.
+  if (destroy_now)
+    source_tabstrip_->DestroyDragController();
+
+  return destroy_now;
+}
+
+void DraggedTabControllerGtk::RevertDrag() {
+  // We save this here because code below will modify |attached_tabstrip_|.
+  bool restore_window = attached_tabstrip_ != source_tabstrip_;
+  if (attached_tabstrip_) {
+    int index = attached_tabstrip_->model()->GetIndexOfTabContents(
+        dragged_contents_);
+    if (attached_tabstrip_ != source_tabstrip_) {
+      // The tab was inserted into another tabstrip. We need to put it back
+      // into the original one.
+      attached_tabstrip_->model()->DetachTabContentsAt(index);
+      // TODO(beng): (Cleanup) seems like we should use Attach() for this
+      //             somehow.
+      attached_tabstrip_ = source_tabstrip_;
+      source_tabstrip_->model()->InsertTabContentsAt(
+          source_model_index_, dragged_contents_,
+          TabStripModel::ADD_SELECTED |
+              (pinned_ ? TabStripModel::ADD_PINNED : 0));
+    } else {
+      // The tab was moved within the tabstrip where the drag was initiated.
+      // Move it back to the starting location.
+      source_tabstrip_->model()->MoveTabContentsAt(index, source_model_index_,
+          true);
+    }
+  } else {
+    // TODO(beng): (Cleanup) seems like we should use Attach() for this
+    //             somehow.
+    attached_tabstrip_ = source_tabstrip_;
+    // The tab was detached from the tabstrip where the drag began, and has not
+    // been attached to any other tabstrip. We need to put it back into the
+    // source tabstrip.
+    source_tabstrip_->model()->InsertTabContentsAt(
+        source_model_index_, dragged_contents_,
+        TabStripModel::ADD_SELECTED |
+            (pinned_ ? TabStripModel::ADD_PINNED : 0));
+  }
+
+  // If we're not attached to any tab strip, or attached to some other tab
+  // strip, we need to restore the bounds of the original tab strip's frame, in
+  // case it has been hidden.
+  if (restore_window)
+    ShowWindow();
+
+  source_tab_->SetVisible(true);
+  source_tab_->set_dragging(false);
+}
+
+bool DraggedTabControllerGtk::CompleteDrag() {
+  bool destroy_immediately = true;
+  if (attached_tabstrip_) {
+    // We don't need to do anything other than make the tab visible again,
+    // since the dragged tab is going away.
+    TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
+    gfx::Rect rect = GetTabScreenBounds(tab);
+    dragged_tab_->AnimateToBounds(GetTabScreenBounds(tab),
+        NewCallback(this, &DraggedTabControllerGtk::OnAnimateToBoundsComplete));
+    destroy_immediately = false;
+  } else {
+    // Compel the model to construct a new window for the detached TabContents.
+    BrowserWindowGtk* window = source_tabstrip_->window();
+    gfx::Rect window_bounds = window->GetRestoredBounds();
+    window_bounds.set_origin(GetWindowCreatePoint());
+    Browser* new_browser =
+        source_tabstrip_->model()->delegate()->CreateNewStripWithContents(
+        dragged_contents_, window_bounds, dock_info_, window->IsMaximized());
+    TabStripModel* new_model = new_browser->tabstrip_model();
+    new_model->SetTabPinned(new_model->GetIndexOfTabContents(dragged_contents_),
+                            pinned_);
+    new_browser->window()->Show();
+    CleanUpHiddenFrame();
+  }
+
+  return destroy_immediately;
+}
+
+void DraggedTabControllerGtk::EnsureDraggedTab() {
+  if (!dragged_tab_.get()) {
+    gfx::Rect rect;
+    dragged_contents_->tab_contents()->GetContainerBounds(&rect);
+
+    dragged_tab_.reset(new DraggedTabGtk(dragged_contents_->tab_contents(),
+                                         mouse_offset_, rect.size(), mini_));
+  }
+}
+
+gfx::Point DraggedTabControllerGtk::GetCursorScreenPoint() const {
+  // Get default display and screen.
+  GdkDisplay* display = gdk_display_get_default();
+
+  // Get cursor position.
+  int x, y;
+  gdk_display_get_pointer(display, NULL, &x, &y, NULL);
+
+  return gfx::Point(x, y);
+}
+
+// static
+gfx::Rect DraggedTabControllerGtk::GetTabScreenBounds(TabGtk* tab) {
+  // A hidden widget moved with gtk_fixed_move in a GtkFixed container doesn't
+  // update its allocation until after the widget is shown, so we have to use
+  // the tab bounds we keep track of.
+  //
+  // We use the requested bounds instead of the allocation because the
+  // allocation is relative to the first windowed widget ancestor of the tab.
+  // Because of this, we can't use the tabs allocation to get the screen bounds.
+  gfx::Rect bounds = tab->GetRequisition();
+  GtkWidget* widget = tab->widget();
+  GtkWidget* parent = gtk_widget_get_parent(widget);
+  gfx::Point point = gtk_util::GetWidgetScreenPosition(parent);
+  bounds.Offset(point);
+
+  return gfx::Rect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
+}
+
+void DraggedTabControllerGtk::HideWindow() {
+  GtkWidget* tabstrip = source_tabstrip_->widget();
+  GtkWindow* window = platform_util::GetTopLevel(tabstrip);
+  gtk_widget_hide(GTK_WIDGET(window));
+}
+
+void DraggedTabControllerGtk::ShowWindow() {
+  GtkWidget* tabstrip = source_tabstrip_->widget();
+  GtkWindow* window = platform_util::GetTopLevel(tabstrip);
+  gtk_window_present(window);
+}
+
+void DraggedTabControllerGtk::CleanUpHiddenFrame() {
+  // If the model we started dragging from is now empty, we must ask the
+  // delegate to close the frame.
+  if (source_tabstrip_->model()->empty())
+    source_tabstrip_->model()->delegate()->CloseFrameAfterDragSession();
+}
+
+void DraggedTabControllerGtk::CleanUpSourceTab() {
+  // If we were attached to the source tabstrip, source tab will be in use
+  // as the tab. If we were detached or attached to another tabstrip, we can
+  // safely remove this item and delete it now.
+  if (attached_tabstrip_ != source_tabstrip_) {
+    source_tabstrip_->DestroyDraggedSourceTab(source_tab_);
+    source_tab_ = NULL;
+  }
+}
+
+void DraggedTabControllerGtk::OnAnimateToBoundsComplete() {
+  // Sometimes, for some reason, in automation we can be called back on a
+  // detach even though we aren't attached to a tabstrip. Guard against that.
+  if (attached_tabstrip_) {
+    TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
+    if (tab) {
+      tab->SetVisible(true);
+      tab->set_dragging(false);
+      // Paint the tab now, otherwise there may be slight flicker between the
+      // time the dragged tab window is destroyed and we paint.
+      tab->SchedulePaint();
+    }
+  }
+
+  CleanUpHiddenFrame();
+
+  if (!in_destructor_)
+    source_tabstrip_->DestroyDragController();
+}
+
+void DraggedTabControllerGtk::BringWindowUnderMouseToFront() {
+  // If we're going to dock to another window, bring it to the front.
+  gfx::NativeWindow window = dock_info_.window();
+  if (!window) {
+    gfx::NativeView dragged_tab = dragged_tab_->widget();
+    dock_windows_.insert(dragged_tab);
+    window = DockInfo::GetLocalProcessWindowAtPoint(GetCursorScreenPoint(),
+                                                    dock_windows_);
+    dock_windows_.erase(dragged_tab);
+  }
+
+  if (window)
+    gtk_window_present(GTK_WINDOW(window));
+}
diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h
new file mode 100644
index 0000000..c1799e0
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h
@@ -0,0 +1,271 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <set>
+
+#include "base/scoped_ptr.h"
+#include "base/timer.h"
+#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/browser/ui/tabs/dock_info.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/x/x11_util.h"
+
+class DraggedTabGtk;
+class TabGtk;
+class TabStripGtk;
+class TabContentsWrapper;
+
+class DraggedTabControllerGtk : public NotificationObserver,
+                                public TabContentsDelegate {
+ public:
+  DraggedTabControllerGtk(TabGtk* source_tab, TabStripGtk* source_tabstrip);
+  virtual ~DraggedTabControllerGtk();
+
+  // Capture information needed to be used during a drag session for this
+  // controller's associated source Tab and TabStrip. |mouse_offset| is the
+  // distance of the mouse pointer from the Tab's origin.
+  void CaptureDragInfo(const gfx::Point& mouse_offset);
+
+  // Responds to drag events subsequent to StartDrag. If the mouse moves a
+  // sufficient distance before the mouse is released, a drag session is
+  // initiated.
+  void Drag();
+
+  // Complete the current drag session. If the drag session was canceled
+  // because the user pressed Escape or something interrupted it, |canceled|
+  // is true so the helper can revert the state to the world before the drag
+  // begun. Returns whether the tab has been destroyed.
+  bool EndDrag(bool canceled);
+
+  // Retrieve the source tab if the TabContents specified matches the one being
+  // dragged by this controller, or NULL if the specified TabContents is not
+  // the same as the one being dragged.
+  TabGtk* GetDragSourceTabForContents(TabContents* contents) const;
+
+  // Returns true if the specified tab matches the tab being dragged.
+  bool IsDragSourceTab(const TabGtk* tab) const;
+
+  // Returns true if the specified tab is detached.
+  bool IsTabDetached(const TabGtk* tab) const;
+
+ private:
+  // Enumeration of the ways a drag session can end.
+  enum EndDragType {
+    // Drag session exited normally: the user released the mouse.
+    NORMAL,
+
+    // The drag session was canceled (alt-tab during drag, escape ...)
+    CANCELED,
+
+    // The tab (NavigationController) was destroyed during the drag.
+    TAB_DESTROYED
+  };
+
+  // Overridden from TabContentsDelegate:
+  virtual void OpenURLFromTab(TabContents* source,
+                              const GURL& url,
+                              const GURL& referrer,
+                              WindowOpenDisposition disposition,
+                              PageTransition::Type transition);
+  virtual void NavigationStateChanged(const TabContents* source,
+                                      unsigned changed_flags);
+  virtual void AddNewContents(TabContents* source,
+                              TabContents* new_contents,
+                              WindowOpenDisposition disposition,
+                              const gfx::Rect& initial_pos,
+                              bool user_gesture);
+  virtual void ActivateContents(TabContents* contents);
+  virtual void DeactivateContents(TabContents* contents);
+  virtual void LoadingStateChanged(TabContents* source);
+  virtual void CloseContents(TabContents* source);
+  virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
+  virtual bool IsPopup(const TabContents* source) const;
+  virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
+  virtual void UpdateTargetURL(TabContents* source, const GURL& url);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Initialize the offset used to calculate the position to create windows
+  // in |GetWindowCreatePoint|.
+  void InitWindowCreatePoint();
+
+  // Returns the point where a detached window should be created given the
+  // current mouse position.
+  gfx::Point GetWindowCreatePoint() const;
+
+  // Sets the TabContents being dragged with the specified |new_contents|.
+  void SetDraggedContents(TabContentsWrapper* new_contents);
+
+  // Move the DraggedTabView according to the current mouse screen position,
+  // potentially updating the source and other TabStrips.
+  void ContinueDragging();
+
+  // Handles moving the Tab within a TabStrip as well as updating the View.
+  void MoveTab(const gfx::Point& screen_point);
+
+  // Returns the compatible TabStrip that is under the specified point (screen
+  // coordinates), or NULL if there is none.
+  TabStripGtk* GetTabStripForPoint(const gfx::Point& screen_point);
+
+  // Returns the specified |tabstrip| if it contains the specified point
+  // (screen coordinates), NULL if it does not.
+  TabStripGtk* GetTabStripIfItContains(TabStripGtk* tabstrip,
+                                       const gfx::Point& screen_point) const;
+
+  // Attach the dragged Tab to the specified TabStrip.
+  void Attach(TabStripGtk* attached_tabstrip, const gfx::Point& screen_point);
+
+  // Detach the dragged Tab from the current TabStrip.
+  void Detach();
+
+  // Converts a screen point to a point relative to the tab strip.
+  gfx::Point ConvertScreenPointToTabStripPoint(TabStripGtk* tabstrip,
+                                               const gfx::Point& screen_point);
+
+  // Retrieve the bounds of the DraggedTabGtk, relative to the attached
+  // TabStrip, given location of the dragged tab in screen coordinates.
+  gfx::Rect GetDraggedTabTabStripBounds(const gfx::Point& screen_point);
+
+  // Returns the index where the dragged TabContents should be inserted into
+  // the attached TabStripModel given the DraggedTabView's bounds
+  // |dragged_bounds| in coordinates relative to the attached TabStrip.
+  // |is_tab_attached| is true if the tab has already been added.
+  int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds,
+                                        bool is_tab_attached) const;
+
+  // Get the position of the dragged tab relative to the attached tab strip.
+  gfx::Point GetDraggedTabPoint(const gfx::Point& screen_point);
+
+  // Finds the Tab within the specified TabStrip that corresponds to the
+  // dragged TabContents.
+  TabGtk* GetTabMatchingDraggedContents(TabStripGtk* tabstrip) const;
+
+  // Does the work for EndDrag. Returns whether the tab has been destroyed.
+  bool EndDragImpl(EndDragType how_end);
+
+  // If the drag was aborted for some reason, this function is called to un-do
+  // the changes made during the drag operation.
+  void RevertDrag();
+
+  // Finishes the drag operation. Returns true if the drag controller should
+  // be destroyed immediately, false otherwise.
+  bool CompleteDrag();
+
+  // Create the DraggedTabGtk if it does not yet exist.
+  void EnsureDraggedTab();
+
+  // Utility for getting the mouse position in screen coordinates.
+  gfx::Point GetCursorScreenPoint() const;
+
+  // Gets the screen bounds of a tab.
+  static gfx::Rect GetTabScreenBounds(TabGtk* tab);
+
+  // Utility to convert the specified TabStripModel index to something valid
+  // for the attached TabStrip.
+  int NormalizeIndexToAttachedTabStrip(int index) const;
+
+  // Hides the window that contains the tab strip the current drag session was
+  // initiated from.
+  void HideWindow();
+
+  // Presents the window that was hidden by HideWindow.
+  void ShowWindow();
+
+  // Closes a hidden frame at the end of a drag session.
+  void CleanUpHiddenFrame();
+
+  // Cleans up a source tab that is no longer used.
+  void CleanUpSourceTab();
+
+  // Completes the drag session after the view has animated to its final
+  // position.
+  void OnAnimateToBoundsComplete();
+
+  // Activates whichever window is under the mouse.
+  void BringWindowUnderMouseToFront();
+
+  // Handles registering for notifications.
+  NotificationRegistrar registrar_;
+
+  // The TabContents being dragged.
+  TabContentsWrapper* dragged_contents_;
+
+  // The original TabContentsDelegate of |dragged_contents_|, before it was
+  // detached from the browser window. We store this so that we can forward
+  // certain delegate notifications back to it if we can't handle them locally.
+  TabContentsDelegate* original_delegate_;
+
+  // The tab that initiated the drag session.
+  TabGtk* source_tab_;
+
+  // The tab strip |source_tab_| originated from.
+  TabStripGtk* source_tabstrip_;
+
+  // This is the index of the |source_tab_| in |source_tabstrip_| when the drag
+  // began. This is used to restore the previous state if the drag is aborted.
+  int source_model_index_;
+
+  // The TabStrip the dragged Tab is currently attached to, or NULL if the
+  // dragged Tab is detached.
+  TabStripGtk* attached_tabstrip_;
+
+  // The visual representation of the dragged Tab.
+  scoped_ptr<DraggedTabGtk> dragged_tab_;
+
+  // The position of the mouse (in screen coordinates) at the start of the drag
+  // operation. This is used to calculate minimum elasticity before a
+  // DraggedTabView is constructed.
+  gfx::Point start_screen_point_;
+
+  // This is the offset of the mouse from the top left of the Tab where
+  // dragging begun. This is used to ensure that the dragged view is always
+  // positioned at the correct location during the drag, and to ensure that the
+  // detached window is created at the right location.
+  gfx::Point mouse_offset_;
+
+  // A hint to use when positioning new windows created by detaching Tabs. This
+  // is the distance of the mouse from the top left of the dragged tab as if it
+  // were the distance of the mouse from the top left of the first tab in the
+  // attached TabStrip from the top left of the window.
+  gfx::Point window_create_point_;
+
+  // Whether we're in the destructor or not.  Makes sure we don't destroy the
+  // drag controller more than once.
+  bool in_destructor_;
+
+  // The horizontal position of the mouse cursor in screen coordinates at the
+  // time of the last re-order event.
+  int last_move_screen_x_;
+
+  // DockInfo for the tabstrip.
+  DockInfo dock_info_;
+
+  typedef std::set<GtkWidget*> DockWindows;
+  DockWindows dock_windows_;
+
+  // Is the tab mini?
+  const bool mini_;
+
+  // Is the tab pinned?
+  const bool pinned_;
+
+  // Timer used to bring the window under the cursor to front. If the user
+  // stops moving the mouse for a brief time over a browser window, it is
+  // brought to front.
+  base::OneShotTimer<DraggedTabControllerGtk> bring_to_front_timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(DraggedTabControllerGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/ui/gtk/tabs/dragged_tab_gtk.cc
new file mode 100644
index 0000000..c42cdff
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/dragged_tab_gtk.cc
@@ -0,0 +1,339 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tabs/dragged_tab_gtk.h"
+
+#include <gdk/gdk.h>
+
+#include <algorithm>
+
+#include "base/i18n/rtl.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/backing_store_x.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h"
+#include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_util.h"
+
+namespace {
+
+// The size of the dragged window frame.
+const int kDragFrameBorderSize = 1;
+const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize;
+
+// Used to scale the dragged window sizes.
+const float kScalingFactor = 0.5;
+
+const int kAnimateToBoundsDurationMs = 150;
+
+const gdouble kTransparentAlpha = (200.0f / 255.0f);
+const gdouble kOpaqueAlpha = 1.0f;
+const double kDraggedTabBorderColor[] = { 103.0 / 0xff,
+                                          129.0 / 0xff,
+                                          162.0 / 0xff };
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// DraggedTabGtk, public:
+
+DraggedTabGtk::DraggedTabGtk(TabContents* datasource,
+                             const gfx::Point& mouse_tab_offset,
+                             const gfx::Size& contents_size,
+                             bool mini)
+    : data_source_(datasource),
+      renderer_(new TabRendererGtk(datasource->profile()->GetThemeProvider())),
+      attached_(false),
+      mouse_tab_offset_(mouse_tab_offset),
+      attached_tab_size_(TabRendererGtk::GetMinimumSelectedSize()),
+      contents_size_(contents_size),
+      close_animation_(this) {
+  renderer_->UpdateData(datasource,
+                        datasource->is_app(),
+                        false); // loading_only
+  renderer_->set_mini(mini);
+
+  container_ = gtk_window_new(GTK_WINDOW_POPUP);
+  SetContainerColorMap();
+  gtk_widget_set_app_paintable(container_, TRUE);
+  g_signal_connect(container_, "expose-event",
+                   G_CALLBACK(OnExposeEvent), this);
+  gtk_widget_add_events(container_, GDK_STRUCTURE_MASK);
+
+  // We contain the tab renderer in a GtkFixed in order to maintain the
+  // requested size.  Otherwise, the widget will fill the entire window and
+  // cause a crash when rendering because the bounds don't match our images.
+  fixed_ = gtk_fixed_new();
+  gtk_fixed_put(GTK_FIXED(fixed_), renderer_->widget(), 0, 0);
+  gtk_container_add(GTK_CONTAINER(container_), fixed_);
+  gtk_widget_show_all(container_);
+}
+
+DraggedTabGtk::~DraggedTabGtk() {
+  gtk_widget_destroy(container_);
+}
+
+void DraggedTabGtk::MoveTo(const gfx::Point& screen_point) {
+  int x = screen_point.x() + mouse_tab_offset_.x() -
+      ScaleValue(mouse_tab_offset_.x());
+  int y = screen_point.y() + mouse_tab_offset_.y() -
+      ScaleValue(mouse_tab_offset_.y());
+
+  gtk_window_move(GTK_WINDOW(container_), x, y);
+}
+
+void DraggedTabGtk::Attach(int selected_width) {
+  attached_ = true;
+  Resize(selected_width);
+
+  if (gtk_util::IsScreenComposited())
+    gdk_window_set_opacity(container_->window, kOpaqueAlpha);
+}
+
+void DraggedTabGtk::Resize(int width) {
+  attached_tab_size_.set_width(width);
+  ResizeContainer();
+}
+
+void DraggedTabGtk::Detach() {
+  attached_ = false;
+  ResizeContainer();
+
+  if (gtk_util::IsScreenComposited())
+    gdk_window_set_opacity(container_->window, kTransparentAlpha);
+}
+
+void DraggedTabGtk::Update() {
+  gtk_widget_queue_draw(container_);
+}
+
+void DraggedTabGtk::AnimateToBounds(const gfx::Rect& bounds,
+                                    AnimateToBoundsCallback* callback) {
+  animation_callback_.reset(callback);
+
+  gint x, y, width, height;
+  gdk_window_get_origin(container_->window, &x, &y);
+  gdk_window_get_geometry(container_->window, NULL, NULL,
+                          &width, &height, NULL);
+
+  animation_start_bounds_ = gfx::Rect(x, y, width, height);
+  animation_end_bounds_ = bounds;
+
+  close_animation_.SetSlideDuration(kAnimateToBoundsDurationMs);
+  close_animation_.SetTweenType(ui::Tween::EASE_OUT);
+  if (!close_animation_.IsShowing()) {
+    close_animation_.Reset();
+    close_animation_.Show();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DraggedTabGtk, ui::AnimationDelegate implementation:
+
+void DraggedTabGtk::AnimationProgressed(const ui::Animation* animation) {
+  int delta_x = (animation_end_bounds_.x() - animation_start_bounds_.x());
+  int x = animation_start_bounds_.x() +
+      static_cast<int>(delta_x * animation->GetCurrentValue());
+  int y = animation_end_bounds_.y();
+  gdk_window_move(container_->window, x, y);
+}
+
+void DraggedTabGtk::AnimationEnded(const ui::Animation* animation) {
+  animation_callback_->Run();
+}
+
+void DraggedTabGtk::AnimationCanceled(const ui::Animation* animation) {
+  AnimationEnded(animation);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DraggedTabGtk, private:
+
+void DraggedTabGtk::Layout() {
+  if (attached_) {
+    renderer_->SetBounds(gfx::Rect(GetPreferredSize()));
+  } else {
+    int left = 0;
+    if (base::i18n::IsRTL())
+      left = GetPreferredSize().width() - attached_tab_size_.width();
+
+    // The renderer_'s width should be attached_tab_size_.width() in both LTR
+    // and RTL locales. Wrong width will cause the wrong positioning of the tab
+    // view in dragging. Please refer to http://crbug.com/6223 for details.
+    renderer_->SetBounds(gfx::Rect(left, 0, attached_tab_size_.width(),
+                         attached_tab_size_.height()));
+  }
+}
+
+gfx::Size DraggedTabGtk::GetPreferredSize() {
+  if (attached_)
+    return attached_tab_size_;
+
+  int width = std::max(attached_tab_size_.width(), contents_size_.width()) +
+      kTwiceDragFrameBorderSize;
+  int height = attached_tab_size_.height() + kDragFrameBorderSize +
+      contents_size_.height();
+  return gfx::Size(width, height);
+}
+
+void DraggedTabGtk::ResizeContainer() {
+  gfx::Size size = GetPreferredSize();
+  gtk_window_resize(GTK_WINDOW(container_),
+                    ScaleValue(size.width()), ScaleValue(size.height()));
+  Layout();
+}
+
+int DraggedTabGtk::ScaleValue(int value) {
+  return attached_ ? value : static_cast<int>(value * kScalingFactor);
+}
+
+gfx::Rect DraggedTabGtk::bounds() const {
+  gint x, y, width, height;
+  gtk_window_get_position(GTK_WINDOW(container_), &x, &y);
+  gtk_window_get_size(GTK_WINDOW(container_), &width, &height);
+  return gfx::Rect(x, y, width, height);
+}
+
+void DraggedTabGtk::SetContainerColorMap() {
+  GdkScreen* screen = gtk_widget_get_screen(container_);
+  GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
+
+  // If rgba is not available, use rgb instead.
+  if (!colormap)
+    colormap = gdk_screen_get_rgb_colormap(screen);
+
+  gtk_widget_set_colormap(container_, colormap);
+}
+
+void DraggedTabGtk::SetContainerTransparency() {
+  cairo_t* cairo_context = gdk_cairo_create(container_->window);
+  if (!cairo_context)
+    return;
+
+  // Make the background of the dragged tab window fully transparent.  All of
+  // the content of the window (child widgets) will be completely opaque.
+  gfx::Size size = bounds().size();
+  cairo_scale(cairo_context, static_cast<double>(size.width()),
+              static_cast<double>(size.height()));
+  cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
+  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
+  cairo_paint(cairo_context);
+  cairo_destroy(cairo_context);
+}
+
+void DraggedTabGtk::SetContainerShapeMask(cairo_surface_t* surface) {
+  // Create a 1bpp bitmap the size of |container_|.
+  gfx::Size size = bounds().size();
+  GdkPixmap* pixmap = gdk_pixmap_new(NULL, size.width(), size.height(), 1);
+  cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(pixmap));
+
+  // Set the transparency.
+  cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
+
+  // Blit the rendered bitmap into a pixmap.  Any pixel set in the pixmap will
+  // be opaque in the container window.
+  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
+  if (!attached_)
+    cairo_scale(cairo_context, kScalingFactor, kScalingFactor);
+  cairo_set_source_surface(cairo_context, surface, 0, 0);
+  cairo_paint(cairo_context);
+
+  if (!attached_) {
+    // Make the render area depiction opaque (leaving enough room for the
+    // border).
+    cairo_identity_matrix(cairo_context);
+    // On Lucid running VNC, the X server will reject RGBA (1,1,1,1) as an
+    // invalid value below in gdk_window_shape_combine_mask(). Using (0,0,0,1)
+    // instead. The value doesn't really matter, as long as the alpha is not 0.
+    cairo_set_source_rgba(cairo_context, 0.0f, 0.0f, 0.0f, 1.0f);
+    int tab_height = static_cast<int>(kScalingFactor *
+                                      renderer_->height() -
+                                      kDragFrameBorderSize);
+    cairo_rectangle(cairo_context,
+                    0, tab_height,
+                    size.width(), size.height() - tab_height);
+    cairo_fill(cairo_context);
+  }
+
+  cairo_destroy(cairo_context);
+
+  // Set the shape mask.
+  gdk_window_shape_combine_mask(container_->window, pixmap, 0, 0);
+  g_object_unref(pixmap);
+}
+
+// static
+gboolean DraggedTabGtk::OnExposeEvent(GtkWidget* widget,
+                                      GdkEventExpose* event,
+                                      DraggedTabGtk* dragged_tab) {
+  cairo_surface_t* surface = dragged_tab->renderer_->PaintToSurface();
+  if (gtk_util::IsScreenComposited()) {
+    dragged_tab->SetContainerTransparency();
+  } else {
+    dragged_tab->SetContainerShapeMask(surface);
+  }
+
+  // Only used when not attached.
+  int tab_width = static_cast<int>(kScalingFactor *
+      dragged_tab->renderer_->width());
+  int tab_height = static_cast<int>(kScalingFactor *
+      dragged_tab->renderer_->height());
+
+  // Draw the render area.
+  BackingStore* backing_store =
+      dragged_tab->data_source_->render_view_host()->GetBackingStore(false);
+  if (backing_store && !dragged_tab->attached_) {
+    // This leaves room for the border.
+    static_cast<BackingStoreX*>(backing_store)->PaintToRect(
+        gfx::Rect(kDragFrameBorderSize, tab_height,
+                  widget->allocation.width - kTwiceDragFrameBorderSize,
+                  widget->allocation.height - tab_height -
+                  kDragFrameBorderSize),
+        GDK_DRAWABLE(widget->window));
+  }
+
+  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+  // Draw the border.
+  if (!dragged_tab->attached_) {
+    cairo_set_line_width(cr, kDragFrameBorderSize);
+    cairo_set_source_rgb(cr, kDraggedTabBorderColor[0],
+                             kDraggedTabBorderColor[1],
+                             kDraggedTabBorderColor[2]);
+    // |offset| is the distance from the edge of the image to the middle of
+    // the border line.
+    double offset = kDragFrameBorderSize / 2.0 - 0.5;
+    double left_x = offset;
+    double top_y = tab_height - kDragFrameBorderSize + offset;
+    double right_x = widget->allocation.width - offset;
+    double bottom_y = widget->allocation.height - offset;
+    double middle_x = tab_width + offset;
+
+    // We don't use cairo_rectangle() because we don't want to draw the border
+    // under the tab itself.
+    cairo_move_to(cr, left_x, top_y);
+    cairo_line_to(cr, left_x, bottom_y);
+    cairo_line_to(cr, right_x, bottom_y);
+    cairo_line_to(cr, right_x, top_y);
+    cairo_line_to(cr, middle_x, top_y);
+    cairo_stroke(cr);
+  }
+
+  // Draw the tab.
+  if (!dragged_tab->attached_)
+    cairo_scale(cr, kScalingFactor, kScalingFactor);
+  cairo_set_source_surface(cr, surface, 0, 0);
+  cairo_paint(cr);
+
+  cairo_destroy(cr);
+
+  cairo_surface_destroy(surface);
+
+  // We've already drawn the tab, so don't propagate the expose-event signal.
+  return TRUE;
+}
diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/ui/gtk/tabs/dragged_tab_gtk.h
new file mode 100644
index 0000000..c416b63
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/dragged_tab_gtk.h
@@ -0,0 +1,147 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/callback.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+class TabContents;
+class TabRendererGtk;
+
+class DraggedTabGtk : public ui::AnimationDelegate {
+ public:
+  DraggedTabGtk(TabContents* datasource,
+                const gfx::Point& mouse_tab_offset,
+                const gfx::Size& contents_size,
+                bool mini);
+  virtual ~DraggedTabGtk();
+
+  // Moves the dragged tab to the appropriate location given the mouse
+  // pointer at |screen_point|.
+  void MoveTo(const gfx::Point& screen_point);
+
+  // Sets the offset of the mouse from the upper left corner of the tab.
+  void set_mouse_tab_offset(const gfx::Point& offset) {
+    mouse_tab_offset_ = offset;
+  }
+
+  // Notifies the dragged tab that it has become attached to a tabstrip.
+  void Attach(int selected_width);
+
+  // Resizes the dragged tab to a width of |width|.
+  void Resize(int width);
+
+  // Notifies the dragged tab that it has been detached from a tabstrip.
+  void Detach();
+
+  // Notifies the dragged tab that it should update itself.
+  void Update();
+
+  // Animates the dragged tab to the specified bounds, then calls back to
+  // |callback|.
+  typedef Callback0::Type AnimateToBoundsCallback;
+  void AnimateToBounds(const gfx::Rect& bounds,
+                       AnimateToBoundsCallback* callback);
+
+  // Returns the size of the dragged tab. Used when attaching to a tabstrip
+  // to determine where to place the tab in the attached tabstrip.
+  const gfx::Size& attached_tab_size() const { return attached_tab_size_; }
+
+  GtkWidget* widget() const { return container_; }
+
+ private:
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationEnded(const ui::Animation* animation);
+  virtual void AnimationCanceled(const ui::Animation* animation);
+
+  // Arranges the contents of the dragged tab.
+  void Layout();
+
+  // Gets the preferred size of the dragged tab.
+  gfx::Size GetPreferredSize();
+
+  // Resizes the container to fit the content for the current attachment mode.
+  void ResizeContainer();
+
+  // Utility for scaling a size by the current scaling factor.
+  int ScaleValue(int value);
+
+  // Returns the bounds of the container window.
+  gfx::Rect bounds() const;
+
+  // Sets the color map of the container window to allow the window to be
+  // transparent.
+  void SetContainerColorMap();
+
+  // Sets full transparency for the container window.  This is used if
+  // compositing is available for the screen.
+  void SetContainerTransparency();
+
+  // Sets the shape mask for the container window to emulate a transparent
+  // container window.  This is used if compositing is not available for the
+  // screen.
+  // |surface| represents the tab only (not the render view).
+  void SetContainerShapeMask(cairo_surface_t* surface);
+
+  // expose-event handler that notifies when the tab needs to be redrawn.
+  static gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event,
+                                DraggedTabGtk* dragged_tab);
+
+  // The tab contents that the dragged tab contains.
+  TabContents* data_source_;
+
+  // The window that contains the dragged tab or tab contents.
+  GtkWidget* container_;
+
+  // The fixed widget that we use to contain the tab renderer so that the
+  // tab widget won't be resized.
+  GtkWidget* fixed_;
+
+  // The renderer that paints the dragged tab.
+  scoped_ptr<TabRendererGtk> renderer_;
+
+  // True if the view is currently attached to a tabstrip. Controls rendering
+  // and sizing modes.
+  bool attached_;
+
+  // The unscaled offset of the mouse from the top left of the dragged tab.
+  // This is used to maintain an appropriate offset for the mouse pointer when
+  // dragging scaled and unscaled representations, and also to calculate the
+  // position of detached windows.
+  gfx::Point mouse_tab_offset_;
+
+  // The size of the tab renderer when the dragged tab is attached to a
+  // tabstrip.
+  gfx::Size attached_tab_size_;
+
+  // The dimensions of the TabContents being dragged.
+  gfx::Size contents_size_;
+
+  // The animation used to slide the attached tab to its final location.
+  ui::SlideAnimation close_animation_;
+
+  // A callback notified when the animation is complete.
+  scoped_ptr<Callback0::Type> animation_callback_;
+
+  // The start and end bounds of the animation sequence.
+  gfx::Rect animation_start_bounds_;
+  gfx::Rect animation_end_bounds_;
+
+  DISALLOW_COPY_AND_ASSIGN(DraggedTabGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_GTK_H_
diff --git a/chrome/browser/ui/gtk/tabs/tab_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_gtk.cc
new file mode 100644
index 0000000..4614d19
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_gtk.cc
@@ -0,0 +1,396 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tabs/tab_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include "base/singleton.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/gtk/accelerators_gtk.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/tabs/tab_menu_model.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/models/accelerator_gtk.h"
+#include "ui/gfx/path.h"
+
+namespace {
+
+// Returns the width of the title for the current font, in pixels.
+int GetTitleWidth(gfx::Font* font, string16 title) {
+  DCHECK(font);
+  if (title.empty())
+    return 0;
+
+  return font->GetStringWidth(title);
+}
+
+}  // namespace
+
+class TabGtk::ContextMenuController : public ui::SimpleMenuModel::Delegate,
+                                      public MenuGtk::Delegate {
+ public:
+  explicit ContextMenuController(TabGtk* tab)
+      : tab_(tab),
+        model_(this, tab->delegate()->IsTabPinned(tab)) {
+    menu_.reset(new MenuGtk(this, &model_));
+  }
+
+  virtual ~ContextMenuController() {}
+
+  void RunMenu(const gfx::Point& point, guint32 event_time) {
+    menu_->PopupAsContext(point, event_time);
+  }
+
+  void Cancel() {
+    tab_ = NULL;
+    menu_->Cancel();
+  }
+
+ private:
+  // Overridden from ui::SimpleMenuModel::Delegate:
+  virtual bool IsCommandIdChecked(int command_id) const {
+    return false;
+  }
+  virtual bool IsCommandIdEnabled(int command_id) const {
+    return tab_ && tab_->delegate()->IsCommandEnabledForTab(
+        static_cast<TabStripModel::ContextMenuCommand>(command_id),
+        tab_);
+  }
+  virtual bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator) {
+    int browser_command;
+    if (!TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
+                                                           &browser_command))
+      return false;
+    const ui::AcceleratorGtk* accelerator_gtk =
+        AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(
+            browser_command);
+    if (accelerator_gtk)
+      *accelerator = *accelerator_gtk;
+    return !!accelerator_gtk;
+  }
+
+  virtual void ExecuteCommand(int command_id) {
+    if (!tab_)
+      return;
+    tab_->delegate()->ExecuteCommandForTab(
+        static_cast<TabStripModel::ContextMenuCommand>(command_id), tab_);
+  }
+
+  GtkWidget* GetImageForCommandId(int command_id) const {
+    int browser_cmd_id;
+    return TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
+                                                             &browser_cmd_id) ?
+        MenuGtk::Delegate::GetDefaultImageForCommandId(browser_cmd_id) :
+        NULL;
+  }
+
+  // The context menu.
+  scoped_ptr<MenuGtk> menu_;
+
+  // The Tab the context menu was brought up for. Set to NULL when the menu
+  // is canceled.
+  TabGtk* tab_;
+
+  // The model.
+  TabMenuModel model_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
+};
+
+class TabGtk::TabGtkObserverHelper {
+ public:
+  explicit TabGtkObserverHelper(TabGtk* tab)
+      : tab_(tab) {
+    MessageLoopForUI::current()->AddObserver(tab_);
+  }
+
+  ~TabGtkObserverHelper() {
+    MessageLoopForUI::current()->RemoveObserver(tab_);
+  }
+
+ private:
+  TabGtk* tab_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabGtkObserverHelper);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// TabGtk, public:
+
+TabGtk::TabGtk(TabDelegate* delegate)
+    : TabRendererGtk(delegate->GetThemeProvider()),
+      delegate_(delegate),
+      closing_(false),
+      dragging_(false),
+      last_mouse_down_(NULL),
+      drag_widget_(NULL),
+      title_width_(0),
+      ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)),
+      ALLOW_THIS_IN_INITIALIZER_LIST(drag_end_factory_(this)) {
+  event_box_ = gtk_event_box_new();
+  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
+  g_signal_connect(event_box_, "button-press-event",
+                   G_CALLBACK(OnButtonPressEventThunk), this);
+  g_signal_connect(event_box_, "button-release-event",
+                   G_CALLBACK(OnButtonReleaseEventThunk), this);
+  g_signal_connect(event_box_, "enter-notify-event",
+                   G_CALLBACK(OnEnterNotifyEventThunk), this);
+  g_signal_connect(event_box_, "leave-notify-event",
+                   G_CALLBACK(OnLeaveNotifyEventThunk), this);
+  gtk_widget_add_events(event_box_,
+        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+        GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
+  gtk_container_add(GTK_CONTAINER(event_box_), TabRendererGtk::widget());
+  gtk_widget_show_all(event_box_);
+}
+
+TabGtk::~TabGtk() {
+  if (drag_widget_) {
+    // Shadow the drag grab so the grab terminates. We could do this using any
+    // widget, |drag_widget_| is just convenient.
+    gtk_grab_add(drag_widget_);
+    gtk_grab_remove(drag_widget_);
+    DestroyDragWidget();
+  }
+
+  if (menu_controller_.get()) {
+    // The menu is showing. Close the menu.
+    menu_controller_->Cancel();
+
+    // Invoke this so that we hide the highlight.
+    ContextMenuClosed();
+  }
+}
+
+gboolean TabGtk::OnButtonPressEvent(GtkWidget* widget, GdkEventButton* event) {
+  // Every button press ensures either a button-release-event or a drag-fail
+  // signal for |widget|.
+  if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+    // Store whether or not we were selected just now... we only want to be
+    // able to drag foreground tabs, so we don't start dragging the tab if
+    // it was in the background.
+    bool just_selected = !IsSelected();
+    if (just_selected) {
+      delegate_->SelectTab(this);
+    }
+
+    // Hook into the message loop to handle dragging.
+    observer_.reset(new TabGtkObserverHelper(this));
+
+    // Store the button press event, used to initiate a drag.
+    last_mouse_down_ = gdk_event_copy(reinterpret_cast<GdkEvent*>(event));
+  } else if (event->button == 3) {
+    // Only show the context menu if the left mouse button isn't down (i.e.,
+    // the user might want to drag instead).
+    if (!last_mouse_down_) {
+      menu_controller_.reset(new ContextMenuController(this));
+      menu_controller_->RunMenu(gfx::Point(event->x_root, event->y_root),
+                                event->time);
+    }
+  }
+
+  return TRUE;
+}
+
+gboolean TabGtk::OnButtonReleaseEvent(GtkWidget* widget,
+                                      GdkEventButton* event) {
+  if (event->button == 1) {
+    observer_.reset();
+
+    if (last_mouse_down_) {
+      gdk_event_free(last_mouse_down_);
+      last_mouse_down_ = NULL;
+    }
+  }
+
+  // Middle mouse up means close the tab, but only if the mouse is over it
+  // (like a button).
+  if (event->button == 2 &&
+      event->x >= 0 && event->y >= 0 &&
+      event->x < widget->allocation.width &&
+      event->y < widget->allocation.height) {
+    // If the user is currently holding the left mouse button down but hasn't
+    // moved the mouse yet, a drag hasn't started yet.  In that case, clean up
+    // some state before closing the tab to avoid a crash.  Once the drag has
+    // started, we don't get the middle mouse click here.
+    if (last_mouse_down_) {
+      DCHECK(!drag_widget_);
+      observer_.reset();
+      gdk_event_free(last_mouse_down_);
+      last_mouse_down_ = NULL;
+    }
+    delegate_->CloseTab(this);
+  }
+
+  return TRUE;
+}
+
+gboolean TabGtk::OnDragFailed(GtkWidget* widget, GdkDragContext* context,
+                              GtkDragResult result) {
+  bool canceled = (result == GTK_DRAG_RESULT_USER_CANCELLED);
+  EndDrag(canceled);
+  return TRUE;
+}
+
+gboolean TabGtk::OnDragButtonReleased(GtkWidget* widget,
+                                      GdkEventButton* button) {
+  // We always get this event when gtk is releasing the grab and ending the
+  // drag.  However, if the user ended the drag with space or enter, we don't
+  // get a follow up event to tell us the drag has finished (either a
+  // drag-failed or a drag-end).  So we post a task to manually end the drag.
+  // If GTK+ does send the drag-failed or drag-end event, we cancel the task.
+  MessageLoop::current()->PostTask(FROM_HERE,
+      drag_end_factory_.NewRunnableMethod(&TabGtk::EndDrag, false));
+  return TRUE;
+}
+
+void TabGtk::OnDragBegin(GtkWidget* widget, GdkDragContext* context) {
+  GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
+  gdk_pixbuf_fill(pixbuf, 0);
+  gtk_drag_set_icon_pixbuf(context, pixbuf, 0, 0);
+  g_object_unref(pixbuf);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TabGtk, MessageLoop::Observer implementation:
+
+void TabGtk::WillProcessEvent(GdkEvent* event) {
+  // Nothing to do.
+}
+
+void TabGtk::DidProcessEvent(GdkEvent* event) {
+  if (!(event->type == GDK_MOTION_NOTIFY || event->type == GDK_LEAVE_NOTIFY ||
+        event->type == GDK_ENTER_NOTIFY)) {
+    return;
+  }
+
+  if (drag_widget_) {
+    delegate_->ContinueDrag(NULL);
+    return;
+  }
+
+  gint old_x = static_cast<gint>(last_mouse_down_->button.x_root);
+  gint old_y = static_cast<gint>(last_mouse_down_->button.y_root);
+  gdouble new_x;
+  gdouble new_y;
+  gdk_event_get_root_coords(event, &new_x, &new_y);
+
+  if (gtk_drag_check_threshold(widget(), old_x, old_y,
+      static_cast<gint>(new_x), static_cast<gint>(new_y))) {
+    StartDragging(gfx::Point(
+        static_cast<int>(last_mouse_down_->button.x),
+        static_cast<int>(last_mouse_down_->button.y)));
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TabGtk, TabRendererGtk overrides:
+
+bool TabGtk::IsSelected() const {
+  return delegate_->IsTabSelected(this);
+}
+
+bool TabGtk::IsVisible() const {
+  return GTK_WIDGET_FLAGS(event_box_) & GTK_VISIBLE;
+}
+
+void TabGtk::SetVisible(bool visible) const {
+  if (visible) {
+    gtk_widget_show(event_box_);
+  } else {
+    gtk_widget_hide(event_box_);
+  }
+}
+
+void TabGtk::CloseButtonClicked() {
+  delegate_->CloseTab(this);
+}
+
+void TabGtk::UpdateData(TabContents* contents, bool app, bool loading_only) {
+  TabRendererGtk::UpdateData(contents, app, loading_only);
+  // Cache the title width so we don't recalculate it every time the tab is
+  // resized.
+  title_width_ = GetTitleWidth(title_font(), GetTitle());
+  UpdateTooltipState();
+}
+
+void TabGtk::SetBounds(const gfx::Rect& bounds) {
+  TabRendererGtk::SetBounds(bounds);
+  UpdateTooltipState();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TabGtk, private:
+
+void TabGtk::ContextMenuClosed() {
+  delegate()->StopAllHighlighting();
+  menu_controller_.reset();
+}
+
+void TabGtk::UpdateTooltipState() {
+  // Only show the tooltip if the title is truncated.
+  if (title_width_ > title_bounds().width()) {
+    gtk_widget_set_tooltip_text(widget(), UTF16ToUTF8(GetTitle()).c_str());
+  } else {
+    gtk_widget_set_has_tooltip(widget(), FALSE);
+  }
+}
+
+void TabGtk::CreateDragWidget() {
+  DCHECK(!drag_widget_);
+  drag_widget_ = gtk_invisible_new();
+  g_signal_connect(drag_widget_, "drag-failed",
+                   G_CALLBACK(OnDragFailedThunk), this);
+  g_signal_connect(drag_widget_, "button-release-event",
+                   G_CALLBACK(OnDragButtonReleasedThunk), this);
+  g_signal_connect_after(drag_widget_, "drag-begin",
+                         G_CALLBACK(OnDragBeginThunk), this);
+}
+
+void TabGtk::DestroyDragWidget() {
+  if (drag_widget_) {
+    gtk_widget_destroy(drag_widget_);
+    drag_widget_ = NULL;
+  }
+}
+
+void TabGtk::StartDragging(gfx::Point drag_offset) {
+  CreateDragWidget();
+
+  GtkTargetList* list = ui::GetTargetListFromCodeMask(ui::CHROME_TAB);
+  gtk_drag_begin(drag_widget_, list, GDK_ACTION_MOVE,
+                 1,  // Drags are always initiated by the left button.
+                 last_mouse_down_);
+
+  delegate_->MaybeStartDrag(this, drag_offset);
+}
+
+void TabGtk::EndDrag(bool canceled) {
+  // Make sure we only run EndDrag once by canceling any tasks that want
+  // to call EndDrag.
+  drag_end_factory_.RevokeAll();
+
+  // We must let gtk clean up after we handle the drag operation, otherwise
+  // there will be outstanding references to the drag widget when we try to
+  // destroy it.
+  MessageLoop::current()->PostTask(FROM_HERE,
+      destroy_factory_.NewRunnableMethod(&TabGtk::DestroyDragWidget));
+
+  if (last_mouse_down_) {
+    gdk_event_free(last_mouse_down_);
+    last_mouse_down_ = NULL;
+  }
+
+  // Notify the drag helper that we're done with any potential drag operations.
+  // Clean up the drag helper, which is re-created on the next mouse press.
+  delegate_->EndDrag(canceled);
+
+  observer_.reset();
+}
diff --git a/chrome/browser/ui/gtk/tabs/tab_gtk.h b/chrome/browser/ui/gtk/tabs/tab_gtk.h
new file mode 100644
index 0000000..460d25d
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_gtk.h
@@ -0,0 +1,212 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TABS_TAB_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TABS_TAB_GTK_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/message_loop.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+namespace gfx {
+class Path;
+}
+
+namespace ui {
+class ThemeProvider;
+}
+
+class TabGtk : public TabRendererGtk,
+               public MessageLoopForUI::Observer {
+ public:
+  // An interface implemented by an object that can help this Tab complete
+  // various actions. The index parameter is the index of this Tab in the
+  // TabRenderer::Model.
+  class TabDelegate {
+   public:
+    // Returns true if the specified Tab is selected.
+    virtual bool IsTabSelected(const TabGtk* tab) const = 0;
+
+    // Returns true if the specified Tab is pinned.
+    virtual bool IsTabPinned(const TabGtk* tab) const = 0;
+
+    // Returns true if the specified Tab is detached.
+    virtual bool IsTabDetached(const TabGtk* tab) const = 0;
+
+    // Selects the specified Tab.
+    virtual void SelectTab(TabGtk* tab) = 0;
+
+    // Closes the specified Tab.
+    virtual void CloseTab(TabGtk* tab) = 0;
+
+    // Returns true if the specified command is enabled for the specified Tab.
+    virtual bool IsCommandEnabledForTab(
+        TabStripModel::ContextMenuCommand command_id,
+        const TabGtk* tab) const = 0;
+
+    // Executes the specified command for the specified Tab.
+    virtual void ExecuteCommandForTab(
+        TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
+
+    // Starts/Stops highlighting the tabs that will be affected by the
+    // specified command for the specified Tab.
+    virtual void StartHighlightTabsForCommand(
+        TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
+    virtual void StopHighlightTabsForCommand(
+        TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
+    virtual void StopAllHighlighting() = 0;
+
+    // Potentially starts a drag for the specified Tab.
+    virtual void MaybeStartDrag(TabGtk* tab, const gfx::Point& point) = 0;
+
+    // Continues dragging a Tab.
+    virtual void ContinueDrag(GdkDragContext* context) = 0;
+
+    // Ends dragging a Tab. |canceled| is true if the drag was aborted in a way
+    // other than the user releasing the mouse. Returns whether the tab has been
+    // destroyed.
+    virtual bool EndDrag(bool canceled) = 0;
+
+    // Returns true if the associated TabStrip's delegate supports tab moving or
+    // detaching. Used by the Frame to determine if dragging on the Tab
+    // itself should move the window in cases where there's only one
+    // non drag-able Tab.
+    virtual bool HasAvailableDragActions() const = 0;
+
+    // Returns the theme provider for icons and colors.
+    virtual ui::ThemeProvider* GetThemeProvider() = 0;
+
+   protected:
+    virtual ~TabDelegate() {}
+  };
+
+  explicit TabGtk(TabDelegate* delegate);
+  virtual ~TabGtk();
+
+  // Access the delegate.
+  TabDelegate* delegate() const { return delegate_; }
+
+  GtkWidget* widget() const { return event_box_; }
+
+  // Used to set/check whether this Tab is being animated closed.
+  void set_closing(bool closing) { closing_ = closing; }
+  bool closing() const { return closing_; }
+
+  // Used to set/check whether this Tab is being dragged.
+  void set_dragging(bool dragging) { dragging_ = dragging; }
+  bool dragging() const { return dragging_; }
+
+  // TabRendererGtk overrides:
+  virtual bool IsSelected() const;
+  virtual bool IsVisible() const;
+  virtual void SetVisible(bool visible) const;
+  virtual void CloseButtonClicked();
+  virtual void UpdateData(TabContents* contents, bool app, bool loading_only);
+  virtual void SetBounds(const gfx::Rect& bounds);
+
+ private:
+  class ContextMenuController;
+  class TabGtkObserverHelper;
+  friend class ContextMenuController;
+
+  // MessageLoop::Observer implementation:
+  virtual void WillProcessEvent(GdkEvent* event);
+  virtual void DidProcessEvent(GdkEvent* event);
+
+  // button-press-event handler that handles mouse clicks.
+  CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnButtonPressEvent, GdkEventButton*);
+
+  // button-release-event handler that handles mouse click releases.
+  CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnButtonReleaseEvent, GdkEventButton*);
+
+  // drag-begin is emitted when the drag is started. We connect so that we can
+  // set the drag icon to a transparent pixbuf.
+  CHROMEGTK_CALLBACK_1(TabGtk, void, OnDragBegin, GdkDragContext*);
+
+  // drag-failed is emitted when the drag is finished.  In our case the signal
+  // does not imply failure as we don't use the drag-n-drop API to transfer drop
+  // data.
+  CHROMEGTK_CALLBACK_2(TabGtk, gboolean, OnDragFailed, GdkDragContext*,
+                       GtkDragResult);
+
+  // When a drag is ending, a fake button release event is passed to the drag
+  // widget to fake letting go of the mouse button.  We need a callback for
+  // this event because it is the only way to catch drag end events when the
+  // user presses space or return.
+  CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnDragButtonReleased, GdkEventButton*);
+
+  // Invoked when the context menu closes.
+  void ContextMenuClosed();
+
+  // Sets whether the tooltip should be shown or not, depending on the size of
+  // the tab.
+  void UpdateTooltipState();
+
+  // Creates the drag widget used to track a drag operation.
+  void CreateDragWidget();
+
+  // Destroys the drag widget.
+  void DestroyDragWidget();
+
+  // Starts the dragging operation.  |drag_offset| is the offset inside the tab
+  // bounds where the grab occurred.
+  void StartDragging(gfx::Point drag_offset);
+
+  // Ends the dragging operations.  |canceled| is true if the operation was
+  // canceled.
+  void EndDrag(bool canceled);
+
+  // An instance of a delegate object that can perform various actions based on
+  // user gestures.
+  TabDelegate* delegate_;
+
+  // True if the tab is being animated closed.
+  bool closing_;
+
+  // True if the tab is being dragged.
+  bool dragging_;
+
+  // The context menu controller.
+  scoped_ptr<ContextMenuController> menu_controller_;
+
+  // The windowless widget used to collect input events for the tab.  We can't
+  // use an OwnedWidgetGtk because of the way the dragged tab controller
+  // destroys the source tab.  The source tab is destroyed when the drag ends
+  // before we let gtk handle the end of the drag.  This results in the widget
+  // having an extra reference, which will cause OwnedWidgetGtk.Destroy to
+  // DCHECK.
+  GtkWidget* event_box_;
+
+  // A copy of the last button press event, used to initiate a drag.
+  GdkEvent* last_mouse_down_;
+
+  // A GtkInivisible used to track the drag event.  GtkInvisibles are of the
+  // type GInitiallyUnowned, but the widget initialization code sinks the
+  // reference, so we can't used an OwnedWidgetGtk here.
+  GtkWidget* drag_widget_;
+
+  // The cached width of the title in pixels, updated whenever the title
+  // changes.
+  int title_width_;
+
+  // Keep track of whether or not we have an observer.
+  scoped_ptr<TabGtkObserverHelper> observer_;
+
+  // Used to destroy the drag widget after a return to the message loop.
+  ScopedRunnableMethodFactory<TabGtk> destroy_factory_;
+
+  // Due to a bug in GTK+, we need to force the end of a drag when we get a
+  // mouse release event on the the dragged widget, otherwise, we don't know
+  // when the drag has ended when the user presses space or enter.  We queue
+  // a task to end the drag and only run it if GTK+ didn't send us the
+  // drag-failed event.
+  ScopedRunnableMethodFactory<TabGtk> drag_end_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TABS_TAB_GTK_H_
diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
new file mode 100644
index 0000000..3abd11b
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
@@ -0,0 +1,1084 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/defaults.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/notification_service.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/animation/throb_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/platform_font_gtk.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+namespace {
+
+const int kFontPixelSize = 13;
+const int kLeftPadding = 16;
+const int kTopPadding = 6;
+const int kRightPadding = 15;
+const int kBottomPadding = 5;
+const int kDropShadowHeight = 2;
+const int kFavIconTitleSpacing = 4;
+const int kTitleCloseButtonSpacing = 5;
+const int kStandardTitleWidth = 175;
+const int kDropShadowOffset = 2;
+const int kInactiveTabBackgroundOffsetY = 15;
+
+// When a non-mini-tab becomes a mini-tab the width of the tab animates. If
+// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab
+// is rendered as a normal tab. This is done to avoid having the title
+// immediately disappear when transitioning a tab from normal to mini-tab.
+const int kMiniTabRendererAsNormalTabWidth =
+    browser_defaults::kMiniTabWidth + 30;
+
+// The tab images are designed to overlap the toolbar by 1 pixel. For now we
+// don't actually overlap the toolbar, so this is used to know how many pixels
+// at the bottom of the tab images are to be ignored.
+const int kToolbarOverlap = 1;
+
+// How long the hover state takes.
+const int kHoverDurationMs = 90;
+
+// How opaque to make the hover state (out of 1).
+const double kHoverOpacity = 0.33;
+
+// Max opacity for the mini-tab title change animation.
+const double kMiniTitleChangeThrobOpacity = 0.75;
+
+// Duration for when the title of an inactive mini-tab changes.
+const int kMiniTitleChangeThrobDuration = 1000;
+
+const SkScalar kTabCapWidth = 15;
+const SkScalar kTabTopCurveWidth = 4;
+const SkScalar kTabBottomCurveWidth = 3;
+
+// The vertical and horizontal offset used to position the close button
+// in the tab. TODO(jhawkins): Ask pkasting what the Fuzz is about.
+const int kCloseButtonVertFuzz = 0;
+const int kCloseButtonHorzFuzz = 5;
+
+SkBitmap* crashed_fav_icon = NULL;
+
+// Gets the bounds of |widget| relative to |parent|.
+gfx::Rect GetWidgetBoundsRelativeToParent(GtkWidget* parent,
+                                          GtkWidget* widget) {
+  gfx::Point parent_pos = gtk_util::GetWidgetScreenPosition(parent);
+  gfx::Point widget_pos = gtk_util::GetWidgetScreenPosition(widget);
+  return gfx::Rect(widget_pos.x() - parent_pos.x(),
+                   widget_pos.y() - parent_pos.y(),
+                   widget->allocation.width, widget->allocation.height);
+}
+
+}  // namespace
+
+TabRendererGtk::LoadingAnimation::Data::Data(
+    ui::ThemeProvider* theme_provider) {
+  // The loading animation image is a strip of states. Each state must be
+  // square, so the height must divide the width evenly.
+  loading_animation_frames = theme_provider->GetBitmapNamed(IDR_THROBBER);
+  DCHECK(loading_animation_frames);
+  DCHECK_EQ(loading_animation_frames->width() %
+            loading_animation_frames->height(), 0);
+  loading_animation_frame_count =
+      loading_animation_frames->width() /
+      loading_animation_frames->height();
+
+  waiting_animation_frames =
+      theme_provider->GetBitmapNamed(IDR_THROBBER_WAITING);
+  DCHECK(waiting_animation_frames);
+  DCHECK_EQ(waiting_animation_frames->width() %
+            waiting_animation_frames->height(), 0);
+  waiting_animation_frame_count =
+      waiting_animation_frames->width() /
+      waiting_animation_frames->height();
+
+  waiting_to_loading_frame_count_ratio =
+      waiting_animation_frame_count /
+      loading_animation_frame_count;
+  // TODO(beng): eventually remove this when we have a proper themeing system.
+  //             themes not supporting IDR_THROBBER_WAITING are causing this
+  //             value to be 0 which causes DIV0 crashes. The value of 5
+  //             matches the current bitmaps in our source.
+  if (waiting_to_loading_frame_count_ratio == 0)
+    waiting_to_loading_frame_count_ratio = 5;
+}
+
+TabRendererGtk::LoadingAnimation::Data::Data(
+    int loading, int waiting, int waiting_to_loading)
+    : waiting_animation_frames(NULL),
+      loading_animation_frames(NULL),
+      loading_animation_frame_count(loading),
+      waiting_animation_frame_count(waiting),
+      waiting_to_loading_frame_count_ratio(waiting_to_loading) {
+}
+
+bool TabRendererGtk::initialized_ = false;
+TabRendererGtk::TabImage TabRendererGtk::tab_active_ = {0};
+TabRendererGtk::TabImage TabRendererGtk::tab_inactive_ = {0};
+TabRendererGtk::TabImage TabRendererGtk::tab_alpha_ = {0};
+gfx::Font* TabRendererGtk::title_font_ = NULL;
+int TabRendererGtk::title_font_height_ = 0;
+int TabRendererGtk::close_button_width_ = 0;
+int TabRendererGtk::close_button_height_ = 0;
+SkColor TabRendererGtk::selected_title_color_ = SK_ColorBLACK;
+SkColor TabRendererGtk::unselected_title_color_ = SkColorSetRGB(64, 64, 64);
+
+////////////////////////////////////////////////////////////////////////////////
+// TabRendererGtk::LoadingAnimation, public:
+//
+TabRendererGtk::LoadingAnimation::LoadingAnimation(
+    ui::ThemeProvider* theme_provider)
+    : data_(new Data(theme_provider)),
+      theme_provider_(theme_provider),
+      animation_state_(ANIMATION_NONE),
+      animation_frame_(0) {
+  registrar_.Add(this,
+                 NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+TabRendererGtk::LoadingAnimation::LoadingAnimation(
+    const LoadingAnimation::Data& data)
+    : data_(new Data(data)),
+      theme_provider_(NULL),
+      animation_state_(ANIMATION_NONE),
+      animation_frame_(0) {
+}
+
+TabRendererGtk::LoadingAnimation::~LoadingAnimation() {}
+
+bool TabRendererGtk::LoadingAnimation::ValidateLoadingAnimation(
+    AnimationState animation_state) {
+  bool has_changed = false;
+  if (animation_state_ != animation_state) {
+    // The waiting animation is the reverse of the loading animation, but at a
+    // different rate - the following reverses and scales the animation_frame_
+    // so that the frame is at an equivalent position when going from one
+    // animation to the other.
+    if (animation_state_ == ANIMATION_WAITING &&
+        animation_state == ANIMATION_LOADING) {
+      animation_frame_ = data_->loading_animation_frame_count -
+          (animation_frame_ / data_->waiting_to_loading_frame_count_ratio);
+    }
+    animation_state_ = animation_state;
+    has_changed = true;
+  }
+
+  if (animation_state_ != ANIMATION_NONE) {
+    animation_frame_ = (animation_frame_ + 1) %
+                       ((animation_state_ == ANIMATION_WAITING) ?
+                         data_->waiting_animation_frame_count :
+                         data_->loading_animation_frame_count);
+    has_changed = true;
+  } else {
+    animation_frame_ = 0;
+  }
+  return has_changed;
+}
+
+void TabRendererGtk::LoadingAnimation::Observe(
+    NotificationType type,
+    const NotificationSource& source,
+    const NotificationDetails& details) {
+  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+  data_.reset(new Data(theme_provider_));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FaviconCrashAnimation
+//
+//  A custom animation subclass to manage the favicon crash animation.
+class TabRendererGtk::FavIconCrashAnimation : public ui::LinearAnimation,
+                                              public ui::AnimationDelegate {
+ public:
+  explicit FavIconCrashAnimation(TabRendererGtk* target)
+      : ALLOW_THIS_IN_INITIALIZER_LIST(ui::LinearAnimation(1000, 25, this)),
+        target_(target) {
+  }
+  virtual ~FavIconCrashAnimation() {}
+
+  // ui::Animation overrides:
+  virtual void AnimateToState(double state) {
+    const double kHidingOffset = 27;
+
+    if (state < .5) {
+      target_->SetFavIconHidingOffset(
+          static_cast<int>(floor(kHidingOffset * 2.0 * state)));
+    } else {
+      target_->DisplayCrashedFavIcon();
+      target_->SetFavIconHidingOffset(
+          static_cast<int>(
+              floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset))));
+    }
+  }
+
+  // ui::AnimationDelegate overrides:
+  virtual void AnimationCanceled(const ui::Animation* animation) {
+    target_->SetFavIconHidingOffset(0);
+  }
+
+ private:
+  TabRendererGtk* target_;
+
+  DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// TabRendererGtk, public:
+
+TabRendererGtk::TabRendererGtk(ui::ThemeProvider* theme_provider)
+    : showing_icon_(false),
+      showing_close_button_(false),
+      fav_icon_hiding_offset_(0),
+      should_display_crashed_favicon_(false),
+      loading_animation_(theme_provider),
+      background_offset_x_(0),
+      background_offset_y_(kInactiveTabBackgroundOffsetY),
+      close_button_color_(0) {
+  InitResources();
+
+  tab_.Own(gtk_fixed_new());
+  gtk_widget_set_app_paintable(tab_.get(), TRUE);
+  g_signal_connect(tab_.get(), "expose-event",
+                   G_CALLBACK(OnExposeEventThunk), this);
+  g_signal_connect(tab_.get(), "size-allocate",
+                   G_CALLBACK(OnSizeAllocateThunk), this);
+  close_button_.reset(MakeCloseButton());
+  gtk_widget_show(tab_.get());
+
+  hover_animation_.reset(new ui::SlideAnimation(this));
+  hover_animation_->SetSlideDuration(kHoverDurationMs);
+
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+TabRendererGtk::~TabRendererGtk() {
+  tab_.Destroy();
+  for (BitmapCache::iterator it = cached_bitmaps_.begin();
+       it != cached_bitmaps_.end(); ++it) {
+    delete it->second.bitmap;
+  }
+}
+
+void TabRendererGtk::UpdateData(TabContents* contents,
+                                bool app,
+                                bool loading_only) {
+  DCHECK(contents);
+  theme_provider_ = GtkThemeProvider::GetFrom(contents->profile());
+
+  if (!loading_only) {
+    data_.title = contents->GetTitle();
+    data_.off_the_record = contents->profile()->IsOffTheRecord();
+    data_.crashed = contents->is_crashed();
+
+    SkBitmap* app_icon = contents->GetExtensionAppIcon();
+    if (app_icon)
+      data_.favicon = *app_icon;
+    else
+      data_.favicon = contents->GetFavIcon();
+
+    data_.app = app;
+    // This is kind of a hacky way to determine whether our icon is the default
+    // favicon. But the plumbing that would be necessary to do it right would
+    // be a good bit of work and would sully code for other platforms which
+    // don't care to custom-theme the favicon. Hopefully the default favicon
+    // will eventually be chromium-themable and this code will go away.
+    data_.is_default_favicon =
+        (data_.favicon.pixelRef() ==
+        ResourceBundle::GetSharedInstance().GetBitmapNamed(
+            IDR_DEFAULT_FAVICON)->pixelRef());
+  }
+
+  // Loading state also involves whether we show the favicon, since that's where
+  // we display the throbber.
+  data_.loading = contents->is_loading();
+  data_.show_icon = contents->ShouldDisplayFavIcon();
+}
+
+void TabRendererGtk::UpdateFromModel() {
+  // Force a layout, since the tab may have grown a favicon.
+  Layout();
+  SchedulePaint();
+
+  if (data_.crashed) {
+    if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation())
+      StartCrashAnimation();
+  } else {
+    if (IsPerformingCrashAnimation())
+      StopCrashAnimation();
+    ResetCrashedFavIcon();
+  }
+}
+
+void TabRendererGtk::SetBlocked(bool blocked) {
+  if (data_.blocked == blocked)
+    return;
+  data_.blocked = blocked;
+  // TODO(zelidrag) bug 32399: Make tabs pulse on Linux as well.
+}
+
+bool TabRendererGtk::is_blocked() const {
+  return data_.blocked;
+}
+
+bool TabRendererGtk::IsSelected() const {
+  return true;
+}
+
+bool TabRendererGtk::IsVisible() const {
+  return GTK_WIDGET_FLAGS(tab_.get()) & GTK_VISIBLE;
+}
+
+void TabRendererGtk::SetVisible(bool visible) const {
+  if (visible) {
+    gtk_widget_show(tab_.get());
+    if (data_.mini)
+      gtk_widget_show(close_button_->widget());
+  } else {
+    gtk_widget_hide_all(tab_.get());
+  }
+}
+
+bool TabRendererGtk::ValidateLoadingAnimation(AnimationState animation_state) {
+  return loading_animation_.ValidateLoadingAnimation(animation_state);
+}
+
+void TabRendererGtk::PaintFavIconArea(GdkEventExpose* event) {
+  DCHECK(ShouldShowIcon());
+
+  // The paint area is the favicon bounds, but we're painting into the gdk
+  // window belonging to the tabstrip.  So the coordinates are relative to the
+  // top left of the tab strip.
+  event->area.x = x() + favicon_bounds_.x();
+  event->area.y = y() + favicon_bounds_.y();
+  event->area.width = favicon_bounds_.width();
+  event->area.height = favicon_bounds_.height();
+  gfx::CanvasSkiaPaint canvas(event, false);
+
+  // The actual paint methods expect 0, 0 to be the tab top left (see
+  // PaintTab).
+  canvas.TranslateInt(x(), y());
+
+  // Paint the background behind the favicon.
+  int theme_id;
+  int offset_y = 0;
+  if (IsSelected()) {
+    theme_id = IDR_THEME_TOOLBAR;
+  } else {
+    if (!data_.off_the_record) {
+      theme_id = IDR_THEME_TAB_BACKGROUND;
+    } else {
+      theme_id = IDR_THEME_TAB_BACKGROUND_INCOGNITO;
+    }
+    if (!theme_provider_->HasCustomImage(theme_id))
+      offset_y = background_offset_y_;
+  }
+  SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(theme_id);
+  canvas.TileImageInt(*tab_bg,
+      x() + favicon_bounds_.x(), offset_y + favicon_bounds_.y(),
+      favicon_bounds_.x(), favicon_bounds_.y(),
+      favicon_bounds_.width(), favicon_bounds_.height());
+
+  if (!IsSelected()) {
+    double throb_value = GetThrobValue();
+    if (throb_value > 0) {
+      SkRect bounds;
+      bounds.set(favicon_bounds_.x(), favicon_bounds_.y(),
+          favicon_bounds_.right(), favicon_bounds_.bottom());
+      canvas.saveLayerAlpha(&bounds, static_cast<int>(throb_value * 0xff),
+                            SkCanvas::kARGB_ClipLayer_SaveFlag);
+      canvas.drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
+      SkBitmap* active_bg = theme_provider_->GetBitmapNamed(IDR_THEME_TOOLBAR);
+      canvas.TileImageInt(*active_bg,
+          x() + favicon_bounds_.x(), favicon_bounds_.y(),
+          favicon_bounds_.x(), favicon_bounds_.y(),
+          favicon_bounds_.width(), favicon_bounds_.height());
+      canvas.restore();
+    }
+  }
+
+  // Now paint the icon.
+  PaintIcon(&canvas);
+}
+
+bool TabRendererGtk::ShouldShowIcon() const {
+  if (mini() && height() >= GetMinimumUnselectedSize().height()) {
+    return true;
+  } else if (!data_.show_icon) {
+    return false;
+  } else if (IsSelected()) {
+    // The selected tab clips favicon before close button.
+    return IconCapacity() >= 2;
+  }
+  // Non-selected tabs clip close button before favicon.
+  return IconCapacity() >= 1;
+}
+
+// static
+gfx::Size TabRendererGtk::GetMinimumUnselectedSize() {
+  InitResources();
+
+  gfx::Size minimum_size;
+  minimum_size.set_width(kLeftPadding + kRightPadding);
+  // Since we use bitmap images, the real minimum height of the image is
+  // defined most accurately by the height of the end cap images.
+  minimum_size.set_height(tab_active_.image_l->height() - kToolbarOverlap);
+  return minimum_size;
+}
+
+// static
+gfx::Size TabRendererGtk::GetMinimumSelectedSize() {
+  gfx::Size minimum_size = GetMinimumUnselectedSize();
+  minimum_size.set_width(kLeftPadding + kFavIconSize + kRightPadding);
+  return minimum_size;
+}
+
+// static
+gfx::Size TabRendererGtk::GetStandardSize() {
+  gfx::Size standard_size = GetMinimumUnselectedSize();
+  standard_size.Enlarge(kFavIconTitleSpacing + kStandardTitleWidth, 0);
+  return standard_size;
+}
+
+// static
+int TabRendererGtk::GetMiniWidth() {
+  return browser_defaults::kMiniTabWidth;
+}
+
+// static
+int TabRendererGtk::GetContentHeight() {
+  // The height of the content of the Tab is the largest of the favicon,
+  // the title text and the close button graphic.
+  int content_height = std::max(kFavIconSize, title_font_height_);
+  return std::max(content_height, close_button_height_);
+}
+
+// static
+void TabRendererGtk::LoadTabImages() {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+  tab_alpha_.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
+  tab_alpha_.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
+
+  tab_active_.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
+  tab_active_.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
+  tab_active_.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
+  tab_active_.l_width = tab_active_.image_l->width();
+  tab_active_.r_width = tab_active_.image_r->width();
+
+  tab_inactive_.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
+  tab_inactive_.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
+  tab_inactive_.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
+  tab_inactive_.l_width = tab_inactive_.image_l->width();
+  tab_inactive_.r_width = tab_inactive_.image_r->width();
+
+  close_button_width_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->width();
+  close_button_height_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->height();
+}
+
+// static
+void TabRendererGtk::SetSelectedTitleColor(SkColor color) {
+  selected_title_color_ = color;
+}
+
+// static
+void TabRendererGtk::SetUnselectedTitleColor(SkColor color) {
+  unselected_title_color_ = color;
+}
+
+gfx::Rect TabRendererGtk::GetNonMirroredBounds(GtkWidget* parent) const {
+  // The tabstrip widget is a windowless widget so the tab widget's allocation
+  // is relative to the browser titlebar.  We need the bounds relative to the
+  // tabstrip.
+  gfx::Rect bounds = GetWidgetBoundsRelativeToParent(parent, widget());
+  bounds.set_x(gtk_util::MirroredLeftPointForRect(parent, bounds));
+  return bounds;
+}
+
+gfx::Rect TabRendererGtk::GetRequisition() const {
+  return gfx::Rect(requisition_.x(), requisition_.y(),
+                   requisition_.width(), requisition_.height());
+}
+
+void TabRendererGtk::StartMiniTabTitleAnimation() {
+  if (!mini_title_animation_.get()) {
+    mini_title_animation_.reset(new ui::ThrobAnimation(this));
+    mini_title_animation_->SetThrobDuration(kMiniTitleChangeThrobDuration);
+  }
+
+  if (!mini_title_animation_->is_animating()) {
+    mini_title_animation_->StartThrobbing(2);
+  } else if (mini_title_animation_->cycles_remaining() <= 2) {
+    // The title changed while we're already animating. Add at most one more
+    // cycle. This is done in an attempt to smooth out pages that continuously
+    // change the title.
+    mini_title_animation_->set_cycles_remaining(
+        mini_title_animation_->cycles_remaining() + 2);
+  }
+}
+
+void TabRendererGtk::StopMiniTabTitleAnimation() {
+  if (mini_title_animation_.get())
+    mini_title_animation_->Stop();
+}
+
+void TabRendererGtk::SetBounds(const gfx::Rect& bounds) {
+  requisition_ = bounds;
+  gtk_widget_set_size_request(tab_.get(), bounds.width(), bounds.height());
+}
+
+void TabRendererGtk::Observe(NotificationType type,
+                             const NotificationSource& source,
+                             const NotificationDetails& details) {
+  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+
+  // Clear our cache when we receive a theme change notification because it
+  // contains cached bitmaps based off the previous theme.
+  for (BitmapCache::iterator it = cached_bitmaps_.begin();
+       it != cached_bitmaps_.end(); ++it) {
+    delete it->second.bitmap;
+  }
+  cached_bitmaps_.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabRendererGtk, protected:
+
+string16 TabRendererGtk::GetTitle() const {
+  return data_.title;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TabRendererGtk, ui::AnimationDelegate implementation:
+
+void TabRendererGtk::AnimationProgressed(const ui::Animation* animation) {
+  gtk_widget_queue_draw(tab_.get());
+}
+
+void TabRendererGtk::AnimationCanceled(const ui::Animation* animation) {
+  AnimationEnded(animation);
+}
+
+void TabRendererGtk::AnimationEnded(const ui::Animation* animation) {
+  gtk_widget_queue_draw(tab_.get());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabRendererGtk, private:
+
+void TabRendererGtk::StartCrashAnimation() {
+  if (!crash_animation_.get())
+    crash_animation_.reset(new FavIconCrashAnimation(this));
+  crash_animation_->Stop();
+  crash_animation_->Start();
+}
+
+void TabRendererGtk::StopCrashAnimation() {
+  if (!crash_animation_.get())
+    return;
+  crash_animation_->Stop();
+}
+
+bool TabRendererGtk::IsPerformingCrashAnimation() const {
+  return crash_animation_.get() && crash_animation_->is_animating();
+}
+
+void TabRendererGtk::SetFavIconHidingOffset(int offset) {
+  fav_icon_hiding_offset_ = offset;
+  SchedulePaint();
+}
+
+void TabRendererGtk::DisplayCrashedFavIcon() {
+  should_display_crashed_favicon_ = true;
+}
+
+void TabRendererGtk::ResetCrashedFavIcon() {
+  should_display_crashed_favicon_ = false;
+}
+
+void TabRendererGtk::Paint(gfx::Canvas* canvas) {
+  // Don't paint if we're narrower than we can render correctly. (This should
+  // only happen during animations).
+  if (width() < GetMinimumUnselectedSize().width() && !mini())
+    return;
+
+  // See if the model changes whether the icons should be painted.
+  const bool show_icon = ShouldShowIcon();
+  const bool show_close_button = ShouldShowCloseBox();
+  if (show_icon != showing_icon_ ||
+      show_close_button != showing_close_button_)
+    Layout();
+
+  PaintTabBackground(canvas);
+
+  if (!mini() || width() > kMiniTabRendererAsNormalTabWidth)
+    PaintTitle(canvas);
+
+  if (show_icon)
+    PaintIcon(canvas);
+}
+
+SkBitmap TabRendererGtk::PaintBitmap() {
+  gfx::CanvasSkia canvas(width(), height(), false);
+  Paint(&canvas);
+  return canvas.ExtractBitmap();
+}
+
+cairo_surface_t* TabRendererGtk::PaintToSurface() {
+  gfx::CanvasSkia canvas(width(), height(), false);
+  Paint(&canvas);
+  return cairo_surface_reference(cairo_get_target(canvas.beginPlatformPaint()));
+}
+
+void TabRendererGtk::SchedulePaint() {
+  gtk_widget_queue_draw(tab_.get());
+}
+
+gfx::Rect TabRendererGtk::GetLocalBounds() {
+  return gfx::Rect(0, 0, bounds_.width(), bounds_.height());
+}
+
+void TabRendererGtk::Layout() {
+  gfx::Rect local_bounds = GetLocalBounds();
+  if (local_bounds.IsEmpty())
+    return;
+  local_bounds.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding);
+
+  // Figure out who is tallest.
+  int content_height = GetContentHeight();
+
+  // Size the Favicon.
+  showing_icon_ = ShouldShowIcon();
+  if (showing_icon_) {
+    int favicon_top = kTopPadding + (content_height - kFavIconSize) / 2;
+    favicon_bounds_.SetRect(local_bounds.x(), favicon_top,
+                            kFavIconSize, kFavIconSize);
+    if ((mini() || data_.animating_mini_change) &&
+        bounds_.width() < kMiniTabRendererAsNormalTabWidth) {
+      int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth();
+      int ideal_delta = bounds_.width() - GetMiniWidth();
+      if (ideal_delta < mini_delta) {
+        int ideal_x = (GetMiniWidth() - kFavIconSize) / 2;
+        int x = favicon_bounds_.x() + static_cast<int>(
+            (1 - static_cast<float>(ideal_delta) /
+             static_cast<float>(mini_delta)) *
+            (ideal_x - favicon_bounds_.x()));
+        favicon_bounds_.set_x(x);
+      }
+    }
+  } else {
+    favicon_bounds_.SetRect(local_bounds.x(), local_bounds.y(), 0, 0);
+  }
+
+  // Size the Close button.
+  showing_close_button_ = ShouldShowCloseBox();
+  if (showing_close_button_) {
+    int close_button_top =
+        kTopPadding + kCloseButtonVertFuzz +
+        (content_height - close_button_height_) / 2;
+    close_button_bounds_.SetRect(local_bounds.width() + kCloseButtonHorzFuzz,
+                                 close_button_top, close_button_width_,
+                                 close_button_height_);
+
+    // If the close button color has changed, generate a new one.
+    if (theme_provider_) {
+      SkColor tab_text_color =
+        theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT);
+      if (!close_button_color_ || tab_text_color != close_button_color_) {
+        close_button_color_ = tab_text_color;
+        ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+        close_button_->SetBackground(close_button_color_,
+            rb.GetBitmapNamed(IDR_TAB_CLOSE),
+            rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
+      }
+    }
+  } else {
+    close_button_bounds_.SetRect(0, 0, 0, 0);
+  }
+
+  if (!mini() || width() >= kMiniTabRendererAsNormalTabWidth) {
+    // Size the Title text to fill the remaining space.
+    int title_left = favicon_bounds_.right() + kFavIconTitleSpacing;
+    int title_top = kTopPadding;
+
+    // If the user has big fonts, the title will appear rendered too far down
+    // on the y-axis if we use the regular top padding, so we need to adjust it
+    // so that the text appears centered.
+    gfx::Size minimum_size = GetMinimumUnselectedSize();
+    int text_height = title_top + title_font_height_ + kBottomPadding;
+    if (text_height > minimum_size.height())
+      title_top -= (text_height - minimum_size.height()) / 2;
+
+    int title_width;
+    if (close_button_bounds_.width() && close_button_bounds_.height()) {
+      title_width = std::max(close_button_bounds_.x() -
+                             kTitleCloseButtonSpacing - title_left, 0);
+    } else {
+      title_width = std::max(local_bounds.width() - title_left, 0);
+    }
+    title_bounds_.SetRect(title_left, title_top, title_width, content_height);
+  }
+
+  favicon_bounds_.set_x(
+      gtk_util::MirroredLeftPointForRect(tab_.get(), favicon_bounds_));
+  close_button_bounds_.set_x(
+      gtk_util::MirroredLeftPointForRect(tab_.get(), close_button_bounds_));
+  title_bounds_.set_x(
+      gtk_util::MirroredLeftPointForRect(tab_.get(), title_bounds_));
+
+  MoveCloseButtonWidget();
+}
+
+void TabRendererGtk::MoveCloseButtonWidget() {
+  if (!close_button_bounds_.IsEmpty()) {
+    gtk_fixed_move(GTK_FIXED(tab_.get()), close_button_->widget(),
+                   close_button_bounds_.x(), close_button_bounds_.y());
+    gtk_widget_show(close_button_->widget());
+  } else {
+    gtk_widget_hide(close_button_->widget());
+  }
+}
+
+SkBitmap* TabRendererGtk::GetMaskedBitmap(const SkBitmap* mask,
+    const SkBitmap* background, int bg_offset_x, int bg_offset_y) {
+  // We store a bitmap for each mask + background pair (4 total bitmaps).  We
+  // replace the cached image if the tab has moved relative to the background.
+  BitmapCache::iterator it = cached_bitmaps_.find(std::make_pair(mask,
+                                                                 background));
+  if (it != cached_bitmaps_.end()) {
+    if (it->second.bg_offset_x == bg_offset_x &&
+        it->second.bg_offset_y == bg_offset_y) {
+      return it->second.bitmap;
+    }
+    // The background offset changed so we should re-render with the new
+    // offsets.
+    delete it->second.bitmap;
+  }
+  SkBitmap image = SkBitmapOperations::CreateTiledBitmap(
+      *background, bg_offset_x, bg_offset_y, mask->width(),
+      height() + kToolbarOverlap);
+  CachedBitmap bitmap = {
+    bg_offset_x,
+    bg_offset_y,
+    new SkBitmap(SkBitmapOperations::CreateMaskedBitmap(image, *mask))
+  };
+  cached_bitmaps_[std::make_pair(mask, background)] = bitmap;
+  return bitmap.bitmap;
+}
+
+void TabRendererGtk::PaintTab(GdkEventExpose* event) {
+  gfx::CanvasSkiaPaint canvas(event, false);
+  if (canvas.is_empty())
+    return;
+
+  // The tab is rendered into a windowless widget whose offset is at the
+  // coordinate event->area.  Translate by these offsets so we can render at
+  // (0,0) to match Windows' rendering metrics.
+  canvas.TranslateInt(event->area.x, event->area.y);
+
+  // Save the original x offset so we can position background images properly.
+  background_offset_x_ = event->area.x;
+
+  Paint(&canvas);
+}
+
+void TabRendererGtk::PaintTitle(gfx::Canvas* canvas) {
+  // Paint the Title.
+  string16 title = data_.title;
+  if (title.empty()) {
+    title = data_.loading ?
+        l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) :
+        TabContents::GetDefaultTitle();
+  } else {
+    Browser::FormatTitleForDisplay(&title);
+  }
+
+  SkColor title_color = IsSelected() ? selected_title_color_
+                                     : unselected_title_color_;
+  canvas->DrawStringInt(title, *title_font_, title_color,
+                        title_bounds_.x(), title_bounds_.y(),
+                        title_bounds_.width(), title_bounds_.height());
+}
+
+void TabRendererGtk::PaintIcon(gfx::Canvas* canvas) {
+  if (loading_animation_.animation_state() != ANIMATION_NONE) {
+    PaintLoadingAnimation(canvas);
+  } else {
+    canvas->Save();
+    canvas->ClipRectInt(0, 0, width(), height() - kFavIconTitleSpacing);
+    if (should_display_crashed_favicon_) {
+      canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0,
+                            crashed_fav_icon->width(),
+                            crashed_fav_icon->height(),
+                            favicon_bounds_.x(),
+                            favicon_bounds_.y() + fav_icon_hiding_offset_,
+                            kFavIconSize, kFavIconSize,
+                            true);
+    } else {
+      if (!data_.favicon.isNull()) {
+        if (data_.is_default_favicon && theme_provider_->UseGtkTheme()) {
+          GdkPixbuf* favicon = GtkThemeProvider::GetDefaultFavicon(true);
+          canvas->AsCanvasSkia()->DrawGdkPixbuf(
+              favicon, favicon_bounds_.x(),
+              favicon_bounds_.y() + fav_icon_hiding_offset_);
+        } else {
+          // If the favicon is an app icon, it is allowed to be drawn slightly
+          // larger than the standard favicon.
+          int favIconHeightOffset = data_.app ? -2 : 0;
+          int favIconWidthDelta = data_.app ?
+              data_.favicon.width() - kFavIconSize : 0;
+          int favIconHeightDelta = data_.app ?
+              data_.favicon.height() - kFavIconSize : 0;
+
+          // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch
+          // to using that class to render the favicon).
+          canvas->DrawBitmapInt(data_.favicon, 0, 0,
+                                data_.favicon.width(),
+                                data_.favicon.height(),
+                                favicon_bounds_.x() - favIconWidthDelta/2,
+                                favicon_bounds_.y() + favIconHeightOffset
+                                    - favIconHeightDelta/2
+                                    + fav_icon_hiding_offset_,
+                                kFavIconSize + favIconWidthDelta,
+                                kFavIconSize + favIconHeightDelta,
+                                true);
+        }
+      }
+    }
+    canvas->Restore();
+  }
+}
+
+void TabRendererGtk::PaintTabBackground(gfx::Canvas* canvas) {
+  if (IsSelected()) {
+    PaintActiveTabBackground(canvas);
+  } else {
+    PaintInactiveTabBackground(canvas);
+
+    double throb_value = GetThrobValue();
+    if (throb_value > 0) {
+      canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff),
+                             gfx::Rect(width(), height()));
+      canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255,
+                                       SkXfermode::kClear_Mode);
+      PaintActiveTabBackground(canvas);
+      canvas->Restore();
+    }
+  }
+}
+
+void TabRendererGtk::PaintInactiveTabBackground(gfx::Canvas* canvas) {
+  bool is_otr = data_.off_the_record;
+
+  // The tab image needs to be lined up with the background image
+  // so that it feels partially transparent.
+  int offset_x = background_offset_x_;
+
+  int tab_id = is_otr ?
+      IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND;
+
+  SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(tab_id);
+
+  // If the theme is providing a custom background image, then its top edge
+  // should be at the top of the tab. Otherwise, we assume that the background
+  // image is a composited foreground + frame image.
+  int offset_y = theme_provider_->HasCustomImage(tab_id) ?
+      0 : background_offset_y_;
+
+  // Draw left edge.
+  SkBitmap* theme_l = GetMaskedBitmap(tab_alpha_.image_l, tab_bg, offset_x,
+                                      offset_y);
+  canvas->DrawBitmapInt(*theme_l, 0, 0);
+
+  // Draw right edge.
+  SkBitmap* theme_r = GetMaskedBitmap(tab_alpha_.image_r, tab_bg,
+      offset_x + width() - tab_active_.r_width, offset_y);
+
+  canvas->DrawBitmapInt(*theme_r, width() - theme_r->width(), 0);
+
+  // Draw center.
+  canvas->TileImageInt(*tab_bg,
+      offset_x + tab_active_.l_width, kDropShadowOffset + offset_y,
+      tab_active_.l_width, 2,
+      width() - tab_active_.l_width - tab_active_.r_width, height() - 2);
+
+  canvas->DrawBitmapInt(*tab_inactive_.image_l, 0, 0);
+  canvas->TileImageInt(*tab_inactive_.image_c, tab_inactive_.l_width, 0,
+      width() - tab_inactive_.l_width - tab_inactive_.r_width, height());
+  canvas->DrawBitmapInt(*tab_inactive_.image_r,
+      width() - tab_inactive_.r_width, 0);
+}
+
+void TabRendererGtk::PaintActiveTabBackground(gfx::Canvas* canvas) {
+  int offset_x = background_offset_x_;
+
+  SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(IDR_THEME_TOOLBAR);
+
+  // Draw left edge.
+  SkBitmap* theme_l = GetMaskedBitmap(tab_alpha_.image_l, tab_bg, offset_x, 0);
+  canvas->DrawBitmapInt(*theme_l, 0, 0);
+
+  // Draw right edge.
+  SkBitmap* theme_r = GetMaskedBitmap(tab_alpha_.image_r, tab_bg,
+      offset_x + width() - tab_active_.r_width, 0);
+  canvas->DrawBitmapInt(*theme_r, width() - tab_active_.r_width, 0);
+
+  // Draw center.
+  canvas->TileImageInt(*tab_bg,
+      offset_x + tab_active_.l_width, kDropShadowHeight,
+      tab_active_.l_width, kDropShadowHeight,
+      width() - tab_active_.l_width - tab_active_.r_width,
+      height() - kDropShadowHeight);
+
+  canvas->DrawBitmapInt(*tab_active_.image_l, 0, 0);
+  canvas->TileImageInt(*tab_active_.image_c, tab_active_.l_width, 0,
+      width() - tab_active_.l_width - tab_active_.r_width, height());
+  canvas->DrawBitmapInt(*tab_active_.image_r, width() - tab_active_.r_width, 0);
+}
+
+void TabRendererGtk::PaintLoadingAnimation(gfx::Canvas* canvas) {
+  const SkBitmap* frames =
+      (loading_animation_.animation_state() == ANIMATION_WAITING) ?
+      loading_animation_.waiting_animation_frames() :
+      loading_animation_.loading_animation_frames();
+  const int image_size = frames->height();
+  const int image_offset = loading_animation_.animation_frame() * image_size;
+  DCHECK(image_size == favicon_bounds_.height());
+  DCHECK(image_size == favicon_bounds_.width());
+
+  canvas->DrawBitmapInt(*frames, image_offset, 0, image_size, image_size,
+      favicon_bounds_.x(), favicon_bounds_.y(), image_size, image_size,
+      false);
+}
+
+int TabRendererGtk::IconCapacity() const {
+  if (height() < GetMinimumUnselectedSize().height())
+    return 0;
+  return (width() - kLeftPadding - kRightPadding) / kFavIconSize;
+}
+
+bool TabRendererGtk::ShouldShowCloseBox() const {
+  // The selected tab never clips close button.
+  return !mini() && (IsSelected() || IconCapacity() >= 3);
+}
+
+CustomDrawButton* TabRendererGtk::MakeCloseButton() {
+  CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE,
+      IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE);
+
+  gtk_widget_set_tooltip_text(button->widget(),
+      l10n_util::GetStringUTF8(IDS_TOOLTIP_CLOSE_TAB).c_str());
+
+  g_signal_connect(button->widget(), "clicked",
+                   G_CALLBACK(OnCloseButtonClickedThunk), this);
+  g_signal_connect(button->widget(), "button-release-event",
+                   G_CALLBACK(OnCloseButtonMouseReleaseThunk), this);
+  g_signal_connect(button->widget(), "enter-notify-event",
+                   G_CALLBACK(OnEnterNotifyEventThunk), this);
+  g_signal_connect(button->widget(), "leave-notify-event",
+                   G_CALLBACK(OnLeaveNotifyEventThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS);
+  gtk_fixed_put(GTK_FIXED(tab_.get()), button->widget(), 0, 0);
+
+  return button;
+}
+
+double TabRendererGtk::GetThrobValue() {
+  if (mini_title_animation_.get() && mini_title_animation_->is_animating()) {
+    return mini_title_animation_->GetCurrentValue() *
+        kMiniTitleChangeThrobOpacity;
+  }
+  return hover_animation_.get() ?
+      kHoverOpacity * hover_animation_->GetCurrentValue() : 0;
+}
+
+void TabRendererGtk::CloseButtonClicked() {
+  // Nothing to do.
+}
+
+void TabRendererGtk::OnCloseButtonClicked(GtkWidget* widget) {
+  CloseButtonClicked();
+}
+
+gboolean TabRendererGtk::OnCloseButtonMouseRelease(GtkWidget* widget,
+                                                   GdkEventButton* event) {
+  if (event->button == 2) {
+    CloseButtonClicked();
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+gboolean TabRendererGtk::OnExposeEvent(GtkWidget* widget,
+                                       GdkEventExpose* event) {
+  PaintTab(event);
+  gtk_container_propagate_expose(GTK_CONTAINER(tab_.get()),
+                                 close_button_->widget(), event);
+  return TRUE;
+}
+
+void TabRendererGtk::OnSizeAllocate(GtkWidget* widget,
+                                    GtkAllocation* allocation) {
+  gfx::Rect bounds = gfx::Rect(allocation->x, allocation->y,
+                               allocation->width, allocation->height);
+
+  // Nothing to do if the bounds are the same.  If we don't catch this, we'll
+  // get an infinite loop of size-allocate signals.
+  if (bounds_ == bounds)
+    return;
+
+  bounds_ = bounds;
+  Layout();
+}
+
+gboolean TabRendererGtk::OnEnterNotifyEvent(GtkWidget* widget,
+                                            GdkEventCrossing* event) {
+  hover_animation_->SetTweenType(ui::Tween::EASE_OUT);
+  hover_animation_->Show();
+  return FALSE;
+}
+
+gboolean TabRendererGtk::OnLeaveNotifyEvent(GtkWidget* widget,
+                                            GdkEventCrossing* event) {
+  hover_animation_->SetTweenType(ui::Tween::EASE_IN);
+  hover_animation_->Hide();
+  return FALSE;
+}
+
+// static
+void TabRendererGtk::InitResources() {
+  if (initialized_)
+    return;
+
+  LoadTabImages();
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
+  title_font_ = new gfx::Font(base_font.GetFontName(), kFontPixelSize);
+  title_font_height_ = title_font_->GetHeight();
+
+  crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON);
+
+  initialized_ = true;
+}
diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h
new file mode 100644
index 0000000..97c061e
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h
@@ -0,0 +1,456 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TABS_TAB_RENDERER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TABS_TAB_RENDERER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/rect.h"
+
+namespace gfx {
+class Size;
+}  // namespace gfx
+
+class CustomDrawButton;
+class GtkThemeProvider;
+class TabContents;
+
+namespace ui {
+class SlideAnimation;
+class ThemeProvider;
+class ThrobAnimation;
+}
+
+class TabRendererGtk : public ui::AnimationDelegate,
+                       public NotificationObserver {
+ public:
+  // Possible animation states.
+  enum AnimationState {
+    ANIMATION_NONE,
+    ANIMATION_WAITING,
+    ANIMATION_LOADING
+  };
+
+  class LoadingAnimation : public NotificationObserver {
+   public:
+    struct Data {
+      explicit Data(ui::ThemeProvider* theme_provider);
+      Data(int loading, int waiting, int waiting_to_loading);
+
+      SkBitmap* waiting_animation_frames;
+      SkBitmap* loading_animation_frames;
+      int loading_animation_frame_count;
+      int waiting_animation_frame_count;
+      int waiting_to_loading_frame_count_ratio;
+    };
+
+    explicit LoadingAnimation(ui::ThemeProvider* theme_provider);
+
+    // Used in unit tests to inject specific data.
+    explicit LoadingAnimation(const LoadingAnimation::Data& data);
+
+    virtual ~LoadingAnimation();
+
+    // Advance the loading animation to the next frame, or hide the animation if
+    // the tab isn't loading. Returns |true| if the icon area needs to be
+    // repainted.
+    bool ValidateLoadingAnimation(AnimationState animation_state);
+
+    AnimationState animation_state() const { return animation_state_; }
+    int animation_frame() const { return animation_frame_; }
+
+    const SkBitmap* waiting_animation_frames() const {
+      return data_->waiting_animation_frames;
+    }
+    const SkBitmap* loading_animation_frames() const {
+      return data_->loading_animation_frames;
+    }
+
+    // Provide NotificationObserver implementation.
+    virtual void Observe(NotificationType type,
+                         const NotificationSource& source,
+                         const NotificationDetails& details);
+
+   private:
+    scoped_ptr<Data> data_;
+
+    // Used to listen for theme change notifications.
+    NotificationRegistrar registrar_;
+
+    // Gives us our throbber images.
+    ui::ThemeProvider* theme_provider_;
+
+    // Current state of the animation.
+    AnimationState animation_state_;
+
+    // The current index into the Animation image strip.
+    int animation_frame_;
+
+    DISALLOW_COPY_AND_ASSIGN(LoadingAnimation);
+  };
+
+  explicit TabRendererGtk(ui::ThemeProvider* theme_provider);
+  virtual ~TabRendererGtk();
+
+  // TabContents. If only the loading state was updated, the loading_only flag
+  // should be specified. If other things change, set this flag to false to
+  // update everything.
+  virtual void UpdateData(TabContents* contents, bool app, bool loading_only);
+
+  // Sets the blocked state of the tab.
+  void SetBlocked(bool pinned);
+  bool is_blocked() const;
+
+  // Sets the mini-state of the tab.
+  void set_mini(bool mini) { data_.mini = mini; }
+  bool mini() const { return data_.mini; }
+
+  // Sets the app state of the tab.
+  void set_app(bool app) { data_.app = app; }
+  bool app() const { return data_.app; }
+
+  // Are we in the process of animating a mini tab state change on this tab?
+  void set_animating_mini_change(bool value) {
+    data_.animating_mini_change = value;
+  }
+
+  // Updates the display to reflect the contents of this TabRenderer's model.
+  void UpdateFromModel();
+
+  // Returns true if the Tab is selected, false otherwise.
+  virtual bool IsSelected() const;
+
+  // Returns true if the Tab is visible, false otherwise.
+  virtual bool IsVisible() const;
+
+  // Sets the visibility of the Tab.
+  virtual void SetVisible(bool visible) const;
+
+  // Paints the tab into |canvas|.
+  virtual void Paint(gfx::Canvas* canvas);
+
+  // Paints the tab into a SkBitmap.
+  virtual SkBitmap PaintBitmap();
+
+  // Paints the tab, and keeps the result server-side. The returned surface must
+  // be freed with cairo_surface_destroy().
+  virtual cairo_surface_t* PaintToSurface();
+
+  // There is no PaintNow available, so the fastest we can do is schedule a
+  // paint with the windowing system.
+  virtual void SchedulePaint();
+
+  // Notifies the Tab that the close button has been clicked.
+  virtual void CloseButtonClicked();
+
+  // Sets the bounds of the tab.
+  virtual void SetBounds(const gfx::Rect& bounds);
+
+  // Provide NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Advance the loading animation to the next frame, or hide the animation if
+  // the tab isn't loading.  Returns |true| if the icon area needs to be
+  // repainted.
+  bool ValidateLoadingAnimation(AnimationState animation_state);
+
+  // Repaint only the area of the tab that contains the favicon.
+  void PaintFavIconArea(GdkEventExpose* event);
+
+  // Returns whether the Tab should display a favicon.
+  bool ShouldShowIcon() const;
+
+  // Returns the minimum possible size of a single unselected Tab.
+  static gfx::Size GetMinimumUnselectedSize();
+  // Returns the minimum possible size of a selected Tab. Selected tabs must
+  // always show a close button and have a larger minimum size than unselected
+  // tabs.
+  static gfx::Size GetMinimumSelectedSize();
+  // Returns the preferred size of a single Tab, assuming space is
+  // available.
+  static gfx::Size GetStandardSize();
+
+  // Returns the width for mini-tabs. Mini-tabs always have this width.
+  static int GetMiniWidth();
+
+  // Loads the images to be used for the tab background.
+  static void LoadTabImages();
+
+  // Sets the colors used for painting text on the tabs.
+  static void SetSelectedTitleColor(SkColor color);
+  static void SetUnselectedTitleColor(SkColor color);
+
+  static gfx::Font* title_font() { return title_font_; }
+
+  // Returns the bounds of the Tab.
+  int x() const { return bounds_.x(); }
+  int y() const { return bounds_.y(); }
+  int width() const { return bounds_.width(); }
+  int height() const { return bounds_.height(); }
+
+  gfx::Rect bounds() const { return bounds_; }
+
+  gfx::Rect favicon_bounds() const { return favicon_bounds_; }
+
+  // Returns the non-mirrored (LTR) bounds of this tab.
+  gfx::Rect GetNonMirroredBounds(GtkWidget* parent) const;
+
+  // Returns the requested bounds of the tab.
+  gfx::Rect GetRequisition() const;
+
+  GtkWidget* widget() const { return tab_.get(); }
+
+  // Start/stop the mini-tab title animation.
+  void StartMiniTabTitleAnimation();
+  void StopMiniTabTitleAnimation();
+
+  void set_vertical_offset(int offset) { background_offset_y_ = offset; }
+
+ protected:
+  const gfx::Rect& title_bounds() const { return title_bounds_; }
+  const gfx::Rect& close_button_bounds() const { return close_button_bounds_; }
+
+  // Returns the title of the Tab.
+  string16 GetTitle() const;
+
+  // enter-notify-event handler that signals when the mouse enters the tab.
+  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnEnterNotifyEvent,
+                       GdkEventCrossing*);
+
+  // leave-notify-event handler that signals when the mouse enters the tab.
+  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnLeaveNotifyEvent,
+                       GdkEventCrossing*);
+
+ private:
+  class FavIconCrashAnimation;
+
+  // The data structure used to hold cached bitmaps.  We need to manually free
+  // the bitmap in CachedBitmap when we remove it from |cached_bitmaps_|.  We
+  // handle this when we replace images in the map and in the destructor.
+  struct CachedBitmap {
+    int bg_offset_x;
+    int bg_offset_y;
+    SkBitmap* bitmap;
+  };
+  typedef std::map<std::pair<const SkBitmap*, const SkBitmap*>, CachedBitmap>
+      BitmapCache;
+
+  // Model data. We store this here so that we don't need to ask the underlying
+  // model, which is tricky since instances of this object can outlive the
+  // corresponding objects in the underlying model.
+  struct TabData {
+    TabData()
+        : is_default_favicon(false),
+          loading(false),
+          crashed(false),
+          off_the_record(false),
+          show_icon(true),
+          mini(false),
+          blocked(false),
+          animating_mini_change(false),
+          app(false) {
+    }
+
+    SkBitmap favicon;
+    bool is_default_favicon;
+    string16 title;
+    bool loading;
+    bool crashed;
+    bool off_the_record;
+    bool show_icon;
+    bool mini;
+    bool blocked;
+    bool animating_mini_change;
+    bool app;
+  };
+
+  // TODO(jhawkins): Move into TabResources class.
+  struct TabImage {
+    SkBitmap* image_l;
+    SkBitmap* image_c;
+    SkBitmap* image_r;
+    int l_width;
+    int r_width;
+    int y_offset;
+  };
+
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation);
+  virtual void AnimationCanceled(const ui::Animation* animation);
+  virtual void AnimationEnded(const ui::Animation* animation);
+
+  // Starts/Stops the crash animation.
+  void StartCrashAnimation();
+  void StopCrashAnimation();
+
+  // Return true if the crash animation is currently running.
+  bool IsPerformingCrashAnimation() const;
+
+  // Set the temporary offset for the favicon. This is used during animation.
+  void SetFavIconHidingOffset(int offset);
+
+  void DisplayCrashedFavIcon();
+  void ResetCrashedFavIcon();
+
+  // Generates the bounds for the interior items of the tab.
+  void Layout();
+
+  // Returns the local bounds of the tab.  This returns the rect
+  // {0, 0, width(), height()} for now, as we don't yet support borders.
+  gfx::Rect GetLocalBounds();
+
+  // Moves the close button widget within the GtkFixed container.
+  void MoveCloseButtonWidget();
+
+  // Returns the largest of the favicon, title text, and the close button.
+  static int GetContentHeight();
+
+  // A helper method for generating the masked bitmaps used to draw the curved
+  // edges of tabs.  We cache the generated bitmaps because they can take a
+  // long time to compute.
+  SkBitmap* GetMaskedBitmap(const SkBitmap* mask,
+                            const SkBitmap* background,
+                            int bg_offset_x,
+                            int bg_offset_y);
+  BitmapCache cached_bitmaps_;
+
+  // Paints the tab, minus the close button.
+  void PaintTab(GdkEventExpose* event);
+
+  // Paint various portions of the Tab
+  void PaintTitle(gfx::Canvas* canvas);
+  void PaintIcon(gfx::Canvas* canvas);
+  void PaintTabBackground(gfx::Canvas* canvas);
+  void PaintInactiveTabBackground(gfx::Canvas* canvas);
+  void PaintActiveTabBackground(gfx::Canvas* canvas);
+  void PaintLoadingAnimation(gfx::Canvas* canvas);
+
+  // Returns the number of favicon-size elements that can fit in the tab's
+  // current size.
+  int IconCapacity() const;
+
+
+  // Returns whether the Tab should display a close button.
+  bool ShouldShowCloseBox() const;
+
+  CustomDrawButton* MakeCloseButton();
+
+  // Gets the throb value for the tab. When a tab is not selected the
+  // active background is drawn at |GetThrobValue()|%. This is used for hover
+  // and mini-tab title change effects.
+  double GetThrobValue();
+
+  // Handles the clicked signal for the close button.
+  CHROMEGTK_CALLBACK_0(TabRendererGtk, void, OnCloseButtonClicked);
+
+  // Handles middle clicking the close button.
+  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnCloseButtonMouseRelease,
+                       GdkEventButton*);
+
+  // expose-event handler that redraws the tab.
+  CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnExposeEvent,
+                       GdkEventExpose*);
+
+  // size-allocate handler used to update the current bounds of the tab.
+  CHROMEGTK_CALLBACK_1(TabRendererGtk, void, OnSizeAllocate, GtkAllocation*);
+
+  // TODO(jhawkins): Move to TabResources.
+  static void InitResources();
+  static bool initialized_;
+
+  // The bounds of various sections of the display.
+  gfx::Rect favicon_bounds_;
+  gfx::Rect title_bounds_;
+  gfx::Rect close_button_bounds_;
+
+  TabData data_;
+
+  static TabImage tab_active_;
+  static TabImage tab_inactive_;
+  static TabImage tab_alpha_;
+
+  static gfx::Font* title_font_;
+  static int title_font_height_;
+
+  static int close_button_width_;
+  static int close_button_height_;
+
+  static SkColor selected_title_color_;
+  static SkColor unselected_title_color_;
+
+  // The GtkDrawingArea we draw the tab on.
+  OwnedWidgetGtk tab_;
+
+  // Whether we're showing the icon. It is cached so that we can detect when it
+  // changes and layout appropriately.
+  bool showing_icon_;
+
+  // Whether we are showing the close button. It is cached so that we can
+  // detect when it changes and layout appropriately.
+  bool showing_close_button_;
+
+  // The offset used to animate the favicon location.
+  int fav_icon_hiding_offset_;
+
+  // The animation object used to swap the favicon with the sad tab icon.
+  scoped_ptr<FavIconCrashAnimation> crash_animation_;
+
+  // Set when the crashed favicon should be displayed.
+  bool should_display_crashed_favicon_;
+
+  // The bounds of this Tab.
+  gfx::Rect bounds_;
+
+  // The requested bounds of this tab.  These bounds are relative to the
+  // tabstrip.
+  gfx::Rect requisition_;
+
+  // Hover animation.
+  scoped_ptr<ui::SlideAnimation> hover_animation_;
+
+  // Animation used when the title of an inactive mini-tab changes.
+  scoped_ptr<ui::ThrobAnimation> mini_title_animation_;
+
+  // Contains the loading animation state.
+  LoadingAnimation loading_animation_;
+
+  // The offset used to paint the tab theme images.
+  int background_offset_x_;
+
+  // The vertical offset used to paint the tab theme images. Controlled by the
+  // tabstrip and plumbed here to offset the theme image by the size of the
+  // alignment in the BrowserTitlebar.
+  int background_offset_y_;
+
+  GtkThemeProvider* theme_provider_;
+
+  // The close button.
+  scoped_ptr<CustomDrawButton> close_button_;
+
+  // The current color of the close button.
+  SkColor close_button_color_;
+
+  // Used to listen for theme change notifications.
+  NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabRendererGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TABS_TAB_RENDERER_GTK_H_
diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk_unittest.cc b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk_unittest.cc
new file mode 100644
index 0000000..6f6ae2c
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk_unittest.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+typedef TabRendererGtk::LoadingAnimation LoadingAnimation;
+
+const int kTestLoadingAnimationFrameCount = 10;
+const int kTestWaitingAnimationFrameCount = 40;
+const int kTestWaitingToLoadingFrameCountRatio = 4;
+
+const LoadingAnimation::Data kMockAnimationData =
+    LoadingAnimation::Data(kTestLoadingAnimationFrameCount,
+                           kTestWaitingAnimationFrameCount,
+                           kTestWaitingToLoadingFrameCountRatio);
+
+TEST(LoadingAnimationTest, InitialState) {
+  LoadingAnimation loading_animation(kMockAnimationData);
+  EXPECT_EQ(TabRendererGtk::ANIMATION_NONE,
+            loading_animation.animation_state());
+  EXPECT_EQ(0, loading_animation.animation_frame());
+}
+
+TEST(LoadingAnimationTest, AdvanceWaitingFrames) {
+  LoadingAnimation loading_animation(kMockAnimationData);
+  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
+  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+            loading_animation.animation_state());
+  EXPECT_EQ(1, loading_animation.animation_frame());
+  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
+  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+            loading_animation.animation_state());
+  EXPECT_EQ(2, loading_animation.animation_frame());
+
+  for (int i = 2; i < kTestWaitingAnimationFrameCount - 1; ++i) {
+    loading_animation.ValidateLoadingAnimation(
+        TabRendererGtk::ANIMATION_WAITING);
+  }
+  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+            loading_animation.animation_state());
+  EXPECT_EQ(kTestWaitingAnimationFrameCount - 1,
+            loading_animation.animation_frame());
+
+  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
+  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+            loading_animation.animation_state());
+  EXPECT_EQ(0, loading_animation.animation_frame()) <<
+            "The animation frame should have wrapped around to 0.";
+}
+
+TEST(LoadingAnimationTest, AdvanceFromWaitingToLoading) {
+  LoadingAnimation loading_animation(kMockAnimationData);
+  for (int i = 0; i < 2 * kTestWaitingToLoadingFrameCountRatio; ++i) {
+    loading_animation.ValidateLoadingAnimation(
+        TabRendererGtk::ANIMATION_WAITING);
+  }
+  EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+            loading_animation.animation_state());
+  EXPECT_EQ(2 * kTestWaitingToLoadingFrameCountRatio,
+            loading_animation.animation_frame());
+
+  loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_LOADING);
+  EXPECT_EQ(TabRendererGtk::ANIMATION_LOADING,
+            loading_animation.animation_state());
+  EXPECT_EQ(kTestLoadingAnimationFrameCount - 1,
+            loading_animation.animation_frame());
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc
new file mode 100644
index 0000000..18f4991
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc
@@ -0,0 +1,2066 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
+
+#include <algorithm>
+
+#include "base/i18n/rtl.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tabs/tab_strip_model_delegate.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/custom_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "grit/app_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+#include "ui/gfx/point.h"
+
+namespace {
+
+const int kDefaultAnimationDurationMs = 100;
+const int kResizeLayoutAnimationDurationMs = 166;
+const int kReorderAnimationDurationMs = 166;
+const int kAnimateToBoundsDurationMs = 150;
+const int kMiniTabAnimationDurationMs = 150;
+
+const int kNewTabButtonHOffset = -5;
+const int kNewTabButtonVOffset = 5;
+
+// The delay between when the mouse leaves the tabstrip and the resize animation
+// is started.
+const int kResizeTabsTimeMs = 300;
+
+// The range outside of the tabstrip where the pointer must enter/leave to
+// start/stop the resize animation.
+const int kTabStripAnimationVSlop = 40;
+
+const int kHorizontalMoveThreshold = 16;  // pixels
+
+// The horizontal offset from one tab to the next, which results in overlapping
+// tabs.
+const int kTabHOffset = -16;
+
+// A linux specific menu item for toggling window decorations.
+const int kShowWindowDecorationsCommand = 200;
+
+// Size of the drop indicator.
+static int drop_indicator_width;
+static int drop_indicator_height;
+
+inline int Round(double x) {
+  return static_cast<int>(x + 0.5);
+}
+
+// widget->allocation is not guaranteed to be set.  After window creation,
+// we pick up the normal bounds by connecting to the configure-event signal.
+gfx::Rect GetInitialWidgetBounds(GtkWidget* widget) {
+  GtkRequisition request;
+  gtk_widget_size_request(widget, &request);
+  return gfx::Rect(0, 0, request.width, request.height);
+}
+
+// Sort rectangles based on their x position.  We don't care about y position
+// so we don't bother breaking ties.
+int CompareGdkRectangles(const void* p1, const void* p2) {
+  int p1_x = static_cast<const GdkRectangle*>(p1)->x;
+  int p2_x = static_cast<const GdkRectangle*>(p2)->x;
+  if (p1_x < p2_x)
+    return -1;
+  else if (p1_x == p2_x)
+    return 0;
+  return 1;
+}
+
+bool GdkRectMatchesTabFavIconBounds(const GdkRectangle& gdk_rect, TabGtk* tab) {
+  gfx::Rect favicon_bounds = tab->favicon_bounds();
+  return gdk_rect.x == favicon_bounds.x() + tab->x() &&
+      gdk_rect.y == favicon_bounds.y() + tab->y() &&
+      gdk_rect.width == favicon_bounds.width() &&
+      gdk_rect.height == favicon_bounds.height();
+}
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// TabAnimation
+//
+//  A base class for all TabStrip animations.
+//
+class TabStripGtk::TabAnimation : public ui::AnimationDelegate {
+ public:
+  friend class TabStripGtk;
+
+  // Possible types of animation.
+  enum Type {
+    INSERT,
+    REMOVE,
+    MOVE,
+    RESIZE,
+    MINI,
+    MINI_MOVE
+  };
+
+  TabAnimation(TabStripGtk* tabstrip, Type type)
+      : tabstrip_(tabstrip),
+        animation_(this),
+        start_selected_width_(0),
+        start_unselected_width_(0),
+        end_selected_width_(0),
+        end_unselected_width_(0),
+        layout_on_completion_(false),
+        type_(type) {
+  }
+  virtual ~TabAnimation() {}
+
+  Type type() const { return type_; }
+
+  void Start() {
+    animation_.SetSlideDuration(GetDuration());
+    animation_.SetTweenType(ui::Tween::EASE_OUT);
+    if (!animation_.IsShowing()) {
+      animation_.Reset();
+      animation_.Show();
+    }
+  }
+
+  void Stop() {
+    animation_.Stop();
+  }
+
+  void set_layout_on_completion(bool layout_on_completion) {
+    layout_on_completion_ = layout_on_completion;
+  }
+
+  // Retrieves the width for the Tab at the specified index if an animation is
+  // active.
+  static double GetCurrentTabWidth(TabStripGtk* tabstrip,
+                                   TabStripGtk::TabAnimation* animation,
+                                   int index) {
+    TabGtk* tab = tabstrip->GetTabAt(index);
+    double tab_width;
+    if (tab->mini()) {
+      tab_width = TabGtk::GetMiniWidth();
+    } else {
+      double unselected, selected;
+      tabstrip->GetCurrentTabWidths(&unselected, &selected);
+      tab_width = tab->IsSelected() ? selected : unselected;
+    }
+
+    if (animation) {
+      double specified_tab_width = animation->GetWidthForTab(index);
+      if (specified_tab_width != -1)
+        tab_width = specified_tab_width;
+    }
+
+    return tab_width;
+  }
+
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation) {
+    tabstrip_->AnimationLayout(end_unselected_width_);
+  }
+
+  virtual void AnimationEnded(const ui::Animation* animation) {
+    tabstrip_->FinishAnimation(this, layout_on_completion_);
+    // This object is destroyed now, so we can't do anything else after this.
+  }
+
+  virtual void AnimationCanceled(const ui::Animation* animation) {
+    AnimationEnded(animation);
+  }
+
+  // Returns the gap before the tab at the specified index. Subclass if during
+  // an animation you need to insert a gap before a tab.
+  virtual double GetGapWidth(int index) {
+    return 0;
+  }
+
+ protected:
+  // Returns the duration of the animation.
+  virtual int GetDuration() const {
+    return kDefaultAnimationDurationMs;
+  }
+
+  // Subclasses override to return the width of the Tab at the specified index
+  // at the current animation frame. -1 indicates the default width should be
+  // used for the Tab.
+  virtual double GetWidthForTab(int index) const {
+    return -1;  // Use default.
+  }
+
+  // Figure out the desired start and end widths for the specified pre- and
+  // post- animation tab counts.
+  void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count,
+                                 int start_mini_count,
+                                 int end_mini_count) {
+    tabstrip_->GetDesiredTabWidths(start_tab_count, start_mini_count,
+                                   &start_unselected_width_,
+                                   &start_selected_width_);
+    double standard_tab_width =
+        static_cast<double>(TabRendererGtk::GetStandardSize().width());
+
+    if ((end_tab_count - start_tab_count) > 0 &&
+        start_unselected_width_ < standard_tab_width) {
+      double minimum_tab_width = static_cast<double>(
+          TabRendererGtk::GetMinimumUnselectedSize().width());
+      start_unselected_width_ -= minimum_tab_width / start_tab_count;
+    }
+
+    tabstrip_->GenerateIdealBounds();
+    tabstrip_->GetDesiredTabWidths(end_tab_count, end_mini_count,
+                                   &end_unselected_width_,
+                                   &end_selected_width_);
+  }
+
+  TabStripGtk* tabstrip_;
+  ui::SlideAnimation animation_;
+
+  double start_selected_width_;
+  double start_unselected_width_;
+  double end_selected_width_;
+  double end_unselected_width_;
+
+ private:
+  // True if a complete re-layout is required upon completion of the animation.
+  // Subclasses set this if they don't perform a complete layout
+  // themselves and canceling the animation may leave the strip in an
+  // inconsistent state.
+  bool layout_on_completion_;
+
+  const Type type_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Handles insertion of a Tab at |index|.
+class InsertTabAnimation : public TabStripGtk::TabAnimation {
+ public:
+  explicit InsertTabAnimation(TabStripGtk* tabstrip, int index)
+      : TabAnimation(tabstrip, INSERT),
+        index_(index) {
+    int tab_count = tabstrip->GetTabCount();
+    int end_mini_count = tabstrip->GetMiniTabCount();
+    int start_mini_count = end_mini_count;
+    if (index < end_mini_count)
+      start_mini_count--;
+    GenerateStartAndEndWidths(tab_count - 1, tab_count, start_mini_count,
+                              end_mini_count);
+  }
+  virtual ~InsertTabAnimation() {}
+
+ protected:
+  // Overridden from TabStripGtk::TabAnimation:
+  virtual double GetWidthForTab(int index) const {
+    if (index == index_) {
+      bool is_selected = tabstrip_->model()->selected_index() == index;
+      double start_width, target_width;
+      if (index < tabstrip_->GetMiniTabCount()) {
+        start_width = TabGtk::GetMinimumSelectedSize().width();
+        target_width = TabGtk::GetMiniWidth();
+      } else {
+        target_width =
+            is_selected ? end_unselected_width_ : end_selected_width_;
+        start_width =
+            is_selected ? TabGtk::GetMinimumSelectedSize().width() :
+                          TabGtk::GetMinimumUnselectedSize().width();
+      }
+
+      double delta = target_width - start_width;
+      if (delta > 0)
+        return start_width + (delta * animation_.GetCurrentValue());
+
+      return start_width;
+    }
+
+    if (tabstrip_->GetTabAt(index)->mini())
+      return TabGtk::GetMiniWidth();
+
+    if (tabstrip_->GetTabAt(index)->IsSelected()) {
+      double delta = end_selected_width_ - start_selected_width_;
+      return start_selected_width_ + (delta * animation_.GetCurrentValue());
+    }
+
+    double delta = end_unselected_width_ - start_unselected_width_;
+    return start_unselected_width_ + (delta * animation_.GetCurrentValue());
+  }
+
+ private:
+  int index_;
+
+  DISALLOW_COPY_AND_ASSIGN(InsertTabAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Handles removal of a Tab from |index|
+class RemoveTabAnimation : public TabStripGtk::TabAnimation {
+ public:
+  RemoveTabAnimation(TabStripGtk* tabstrip, int index, TabContents* contents)
+      : TabAnimation(tabstrip, REMOVE),
+        index_(index) {
+    int tab_count = tabstrip->GetTabCount();
+    int start_mini_count = tabstrip->GetMiniTabCount();
+    int end_mini_count = start_mini_count;
+    if (index < start_mini_count)
+      end_mini_count--;
+    GenerateStartAndEndWidths(tab_count, tab_count - 1, start_mini_count,
+                              end_mini_count);
+    // If the last non-mini-tab is being removed we force a layout on
+    // completion. This is necessary as the value returned by GetTabHOffset
+    // changes once the tab is actually removed (which happens at the end of
+    // the animation), and unless we layout GetTabHOffset won't be called after
+    // the removal.
+    // We do the same when the last mini-tab is being removed for the same
+    // reason.
+    set_layout_on_completion(start_mini_count > 0 &&
+                             (end_mini_count == 0 ||
+                              (start_mini_count == end_mini_count &&
+                               tab_count == start_mini_count + 1)));
+  }
+
+  virtual ~RemoveTabAnimation() {}
+
+  // Returns the index of the tab being removed.
+  int index() const { return index_; }
+
+ protected:
+  // Overridden from TabStripGtk::TabAnimation:
+  virtual double GetWidthForTab(int index) const {
+    TabGtk* tab = tabstrip_->GetTabAt(index);
+
+    if (index == index_) {
+      // The tab(s) being removed are gradually shrunken depending on the state
+      // of the animation.
+      if (tab->mini()) {
+        return animation_.CurrentValueBetween(TabGtk::GetMiniWidth(),
+                                              -kTabHOffset);
+      }
+
+      // Removed animated Tabs are never selected.
+      double start_width = start_unselected_width_;
+      // Make sure target_width is at least abs(kTabHOffset), otherwise if
+      // less than kTabHOffset during layout tabs get negatively offset.
+      double target_width =
+          std::max(abs(kTabHOffset),
+                   TabGtk::GetMinimumUnselectedSize().width() + kTabHOffset);
+      return animation_.CurrentValueBetween(start_width, target_width);
+    }
+
+    if (tab->mini())
+      return TabGtk::GetMiniWidth();
+
+    if (tabstrip_->available_width_for_tabs_ != -1 &&
+        index_ != tabstrip_->GetTabCount() - 1) {
+      return TabStripGtk::TabAnimation::GetWidthForTab(index);
+    }
+
+    // All other tabs are sized according to the start/end widths specified at
+    // the start of the animation.
+    if (tab->IsSelected()) {
+      double delta = end_selected_width_ - start_selected_width_;
+      return start_selected_width_ + (delta * animation_.GetCurrentValue());
+    }
+
+    double delta = end_unselected_width_ - start_unselected_width_;
+    return start_unselected_width_ + (delta * animation_.GetCurrentValue());
+  }
+
+  virtual void AnimationEnded(const ui::Animation* animation) {
+    tabstrip_->RemoveTabAt(index_);
+    TabStripGtk::TabAnimation::AnimationEnded(animation);
+  }
+
+ private:
+  int index_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoveTabAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Handles the movement of a Tab from one position to another.
+class MoveTabAnimation : public TabStripGtk::TabAnimation {
+ public:
+  MoveTabAnimation(TabStripGtk* tabstrip, int tab_a_index, int tab_b_index)
+      : TabAnimation(tabstrip, MOVE),
+        start_tab_a_bounds_(tabstrip_->GetIdealBounds(tab_b_index)),
+        start_tab_b_bounds_(tabstrip_->GetIdealBounds(tab_a_index)) {
+    tab_a_ = tabstrip_->GetTabAt(tab_a_index);
+    tab_b_ = tabstrip_->GetTabAt(tab_b_index);
+
+    // Since we don't do a full TabStrip re-layout, we need to force a full
+    // layout upon completion since we're not guaranteed to be in a good state
+    // if for example the animation is canceled.
+    set_layout_on_completion(true);
+  }
+  virtual ~MoveTabAnimation() {}
+
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation) {
+    // Position Tab A
+    double distance = start_tab_b_bounds_.x() - start_tab_a_bounds_.x();
+    double delta = distance * animation_.GetCurrentValue();
+    double new_x = start_tab_a_bounds_.x() + delta;
+    gfx::Rect bounds(Round(new_x), start_tab_a_bounds_.y(), tab_a_->width(),
+        tab_a_->height());
+    tabstrip_->SetTabBounds(tab_a_, bounds);
+
+    // Position Tab B
+    distance = start_tab_a_bounds_.x() - start_tab_b_bounds_.x();
+    delta = distance * animation_.GetCurrentValue();
+    new_x = start_tab_b_bounds_.x() + delta;
+    bounds = gfx::Rect(Round(new_x), start_tab_b_bounds_.y(), tab_b_->width(),
+        tab_b_->height());
+    tabstrip_->SetTabBounds(tab_b_, bounds);
+  }
+
+ protected:
+  // Overridden from TabStripGtk::TabAnimation:
+  virtual int GetDuration() const { return kReorderAnimationDurationMs; }
+
+ private:
+  // The two tabs being exchanged.
+  TabGtk* tab_a_;
+  TabGtk* tab_b_;
+
+  // ...and their bounds.
+  gfx::Rect start_tab_a_bounds_;
+  gfx::Rect start_tab_b_bounds_;
+
+  DISALLOW_COPY_AND_ASSIGN(MoveTabAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Handles the animated resize layout of the entire TabStrip from one width
+// to another.
+class ResizeLayoutAnimation : public TabStripGtk::TabAnimation {
+ public:
+  explicit ResizeLayoutAnimation(TabStripGtk* tabstrip)
+      : TabAnimation(tabstrip, RESIZE) {
+    int tab_count = tabstrip->GetTabCount();
+    int mini_tab_count = tabstrip->GetMiniTabCount();
+    GenerateStartAndEndWidths(tab_count, tab_count, mini_tab_count,
+                              mini_tab_count);
+    InitStartState();
+  }
+  virtual ~ResizeLayoutAnimation() {}
+
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationEnded(const ui::Animation* animation) {
+    tabstrip_->needs_resize_layout_ = false;
+    TabStripGtk::TabAnimation::AnimationEnded(animation);
+  }
+
+ protected:
+  // Overridden from TabStripGtk::TabAnimation:
+  virtual int GetDuration() const {
+    return kResizeLayoutAnimationDurationMs;
+  }
+
+  virtual double GetWidthForTab(int index) const {
+    TabGtk* tab = tabstrip_->GetTabAt(index);
+
+    if (tab->mini())
+      return TabGtk::GetMiniWidth();
+
+    if (tab->IsSelected()) {
+      return animation_.CurrentValueBetween(start_selected_width_,
+                                            end_selected_width_);
+    }
+
+    return animation_.CurrentValueBetween(start_unselected_width_,
+                                          end_unselected_width_);
+  }
+
+ private:
+  // We need to start from the current widths of the Tabs as they were last
+  // laid out, _not_ the last known good state, which is what'll be done if we
+  // don't measure the Tab sizes here and just go with the default TabAnimation
+  // behavior...
+  void InitStartState() {
+    for (int i = 0; i < tabstrip_->GetTabCount(); ++i) {
+      TabGtk* current_tab = tabstrip_->GetTabAt(i);
+      if (!current_tab->mini()) {
+        if (current_tab->IsSelected()) {
+          start_selected_width_ = current_tab->width();
+        } else {
+          start_unselected_width_ = current_tab->width();
+        }
+      }
+    }
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(ResizeLayoutAnimation);
+};
+
+// Handles a tabs mini-state changing while the tab does not change position
+// in the model.
+class MiniTabAnimation : public TabStripGtk::TabAnimation {
+ public:
+  explicit MiniTabAnimation(TabStripGtk* tabstrip, int index)
+      : TabAnimation(tabstrip, MINI),
+        index_(index) {
+    int tab_count = tabstrip->GetTabCount();
+    int start_mini_count = tabstrip->GetMiniTabCount();
+    int end_mini_count = start_mini_count;
+    if (tabstrip->GetTabAt(index)->mini())
+      start_mini_count--;
+    else
+      start_mini_count++;
+    tabstrip_->GetTabAt(index)->set_animating_mini_change(true);
+    GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count,
+                              end_mini_count);
+  }
+
+ protected:
+  // Overridden from TabStripGtk::TabAnimation:
+  virtual int GetDuration() const {
+    return kMiniTabAnimationDurationMs;
+  }
+
+  virtual double GetWidthForTab(int index) const {
+    TabGtk* tab = tabstrip_->GetTabAt(index);
+
+    if (index == index_) {
+      if (tab->mini()) {
+        return animation_.CurrentValueBetween(
+            start_selected_width_,
+            static_cast<double>(TabGtk::GetMiniWidth()));
+      } else {
+        return animation_.CurrentValueBetween(
+            static_cast<double>(TabGtk::GetMiniWidth()),
+            end_selected_width_);
+      }
+    } else if (tab->mini()) {
+      return TabGtk::GetMiniWidth();
+    }
+
+    if (tab->IsSelected()) {
+      return animation_.CurrentValueBetween(start_selected_width_,
+                                            end_selected_width_);
+    }
+
+    return animation_.CurrentValueBetween(start_unselected_width_,
+                                          end_unselected_width_);
+  }
+
+ private:
+  // Index of the tab whose mini-state changed.
+  int index_;
+
+  DISALLOW_COPY_AND_ASSIGN(MiniTabAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Handles the animation when a tabs mini-state changes and the tab moves as a
+// result.
+class MiniMoveAnimation : public TabStripGtk::TabAnimation {
+ public:
+  explicit MiniMoveAnimation(TabStripGtk* tabstrip,
+                             int from_index,
+                             int to_index,
+                             const gfx::Rect& start_bounds)
+      : TabAnimation(tabstrip, MINI_MOVE),
+        tab_(tabstrip->GetTabAt(to_index)),
+        start_bounds_(start_bounds),
+        from_index_(from_index),
+        to_index_(to_index) {
+    int tab_count = tabstrip->GetTabCount();
+    int start_mini_count = tabstrip->GetMiniTabCount();
+    int end_mini_count = start_mini_count;
+    if (tabstrip->GetTabAt(to_index)->mini())
+      start_mini_count--;
+    else
+      start_mini_count++;
+    GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count,
+                              end_mini_count);
+    target_bounds_ = tabstrip->GetIdealBounds(to_index);
+    tab_->set_animating_mini_change(true);
+  }
+
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation) {
+    // Do the normal layout.
+    TabAnimation::AnimationProgressed(animation);
+
+    // Then special case the position of the tab being moved.
+    int x = animation_.CurrentValueBetween(start_bounds_.x(),
+                                           target_bounds_.x());
+    int width = animation_.CurrentValueBetween(start_bounds_.width(),
+                                               target_bounds_.width());
+    gfx::Rect tab_bounds(x, start_bounds_.y(), width,
+                         start_bounds_.height());
+    tabstrip_->SetTabBounds(tab_, tab_bounds);
+  }
+
+  virtual void AnimationEnded(const ui::Animation* animation) {
+    tabstrip_->needs_resize_layout_ = false;
+    TabStripGtk::TabAnimation::AnimationEnded(animation);
+  }
+
+  virtual double GetGapWidth(int index) {
+    if (to_index_ < from_index_) {
+      // The tab was made mini.
+      if (index == to_index_) {
+        double current_size =
+            animation_.CurrentValueBetween(0, target_bounds_.width());
+        if (current_size < -kTabHOffset)
+          return -(current_size + kTabHOffset);
+      } else if (index == from_index_ + 1) {
+        return animation_.CurrentValueBetween(start_bounds_.width(), 0);
+      }
+    } else {
+      // The tab was was made a normal tab.
+      if (index == from_index_) {
+        return animation_.CurrentValueBetween(
+            TabGtk::GetMiniWidth() + kTabHOffset, 0);
+      }
+    }
+    return 0;
+  }
+
+ protected:
+  // Overridden from TabStripGtk::TabAnimation:
+  virtual int GetDuration() const { return kReorderAnimationDurationMs; }
+
+  virtual double GetWidthForTab(int index) const {
+    TabGtk* tab = tabstrip_->GetTabAt(index);
+
+    if (index == to_index_)
+      return animation_.CurrentValueBetween(0, target_bounds_.width());
+
+    if (tab->mini())
+      return TabGtk::GetMiniWidth();
+
+    if (tab->IsSelected()) {
+      return animation_.CurrentValueBetween(start_selected_width_,
+                                            end_selected_width_);
+    }
+
+    return animation_.CurrentValueBetween(start_unselected_width_,
+                                          end_unselected_width_);
+  }
+
+ private:
+  // The tab being moved.
+  TabGtk* tab_;
+
+  // Initial bounds of tab_.
+  gfx::Rect start_bounds_;
+
+  // Target bounds.
+  gfx::Rect target_bounds_;
+
+  // Start and end indices of the tab.
+  int from_index_;
+  int to_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(MiniMoveAnimation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// TabStripGtk, public:
+
+// static
+const int TabStripGtk::mini_to_non_mini_gap_ = 3;
+
+TabStripGtk::TabStripGtk(TabStripModel* model, BrowserWindowGtk* window)
+    : current_unselected_width_(TabGtk::GetStandardSize().width()),
+      current_selected_width_(TabGtk::GetStandardSize().width()),
+      available_width_for_tabs_(-1),
+      needs_resize_layout_(false),
+      tab_vertical_offset_(0),
+      model_(model),
+      window_(window),
+      theme_provider_(GtkThemeProvider::GetFrom(model->profile())),
+      resize_layout_factory_(this),
+      added_as_message_loop_observer_(false) {
+  theme_provider_->InitThemesFor(this);
+  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
+                 NotificationService::AllSources());
+}
+
+TabStripGtk::~TabStripGtk() {
+  model_->RemoveObserver(this);
+  tabstrip_.Destroy();
+
+  // Free any remaining tabs.  This is needed to free the very last tab,
+  // because it is not animated on close.  This also happens when all of the
+  // tabs are closed at once.
+  std::vector<TabData>::iterator iterator = tab_data_.begin();
+  for (; iterator < tab_data_.end(); iterator++) {
+    delete iterator->tab;
+  }
+
+  tab_data_.clear();
+
+  // Make sure we unhook ourselves as a message loop observer so that we don't
+  // crash in the case where the user closes the last tab in a window.
+  RemoveMessageLoopObserver();
+}
+
+void TabStripGtk::Init() {
+  model_->AddObserver(this);
+
+  tabstrip_.Own(gtk_fixed_new());
+  ViewIDUtil::SetID(tabstrip_.get(), VIEW_ID_TAB_STRIP);
+  // We want the tab strip to be horizontally shrinkable, so that the Chrome
+  // window can be resized freely.
+  gtk_widget_set_size_request(tabstrip_.get(), 0,
+                              TabGtk::GetMinimumUnselectedSize().height());
+  gtk_widget_set_app_paintable(tabstrip_.get(), TRUE);
+  gtk_drag_dest_set(tabstrip_.get(), GTK_DEST_DEFAULT_ALL,
+                    NULL, 0,
+                    static_cast<GdkDragAction>(
+                        GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK));
+  static const int targets[] = { ui::TEXT_URI_LIST,
+                                 ui::NETSCAPE_URL,
+                                 ui::TEXT_PLAIN,
+                                 -1 };
+  ui::SetDestTargetList(tabstrip_.get(), targets);
+
+  g_signal_connect(tabstrip_.get(), "expose-event",
+                   G_CALLBACK(OnExposeThunk), this);
+  g_signal_connect(tabstrip_.get(), "size-allocate",
+                   G_CALLBACK(OnSizeAllocateThunk), this);
+  g_signal_connect(tabstrip_.get(), "drag-motion",
+                   G_CALLBACK(OnDragMotionThunk), this);
+  g_signal_connect(tabstrip_.get(), "drag-drop",
+                   G_CALLBACK(OnDragDropThunk), this);
+  g_signal_connect(tabstrip_.get(), "drag-leave",
+                   G_CALLBACK(OnDragLeaveThunk), this);
+  g_signal_connect(tabstrip_.get(), "drag-data-received",
+                   G_CALLBACK(OnDragDataReceivedThunk), this);
+
+  newtab_button_.reset(MakeNewTabButton());
+
+  gtk_widget_show_all(tabstrip_.get());
+
+  bounds_ = GetInitialWidgetBounds(tabstrip_.get());
+
+  if (drop_indicator_width == 0) {
+    // Direction doesn't matter, both images are the same size.
+    GdkPixbuf* drop_image = GetDropArrowImage(true);
+    drop_indicator_width = gdk_pixbuf_get_width(drop_image);
+    drop_indicator_height = gdk_pixbuf_get_height(drop_image);
+  }
+
+  ViewIDUtil::SetDelegateForWidget(widget(), this);
+}
+
+void TabStripGtk::Show() {
+  gtk_widget_show(tabstrip_.get());
+}
+
+void TabStripGtk::Hide() {
+  gtk_widget_hide(tabstrip_.get());
+}
+
+bool TabStripGtk::IsActiveDropTarget() const {
+  for (int i = 0; i < GetTabCount(); ++i) {
+    TabGtk* tab = GetTabAt(i);
+    if (tab->dragging())
+      return true;
+  }
+  return false;
+}
+
+void TabStripGtk::Layout() {
+  // Called from:
+  // - window resize
+  // - animation completion
+  StopAnimation();
+
+  GenerateIdealBounds();
+  int tab_count = GetTabCount();
+  int tab_right = 0;
+  for (int i = 0; i < tab_count; ++i) {
+    const gfx::Rect& bounds = tab_data_.at(i).ideal_bounds;
+    TabGtk* tab = GetTabAt(i);
+    tab->set_animating_mini_change(false);
+    tab->set_vertical_offset(tab_vertical_offset_);
+    SetTabBounds(tab, bounds);
+    tab_right = bounds.right();
+    tab_right += GetTabHOffset(i + 1);
+  }
+
+  LayoutNewTabButton(static_cast<double>(tab_right), current_unselected_width_);
+}
+
+void TabStripGtk::SchedulePaint() {
+  gtk_widget_queue_draw(tabstrip_.get());
+}
+
+void TabStripGtk::SetBounds(const gfx::Rect& bounds) {
+  bounds_ = bounds;
+}
+
+void TabStripGtk::UpdateLoadingAnimations() {
+  for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
+    TabGtk* current_tab = GetTabAt(i);
+    if (current_tab->closing()) {
+      --index;
+    } else {
+      TabRendererGtk::AnimationState state;
+      TabContentsWrapper* contents = model_->GetTabContentsAt(index);
+      if (!contents || !contents->tab_contents()->is_loading()) {
+        state = TabGtk::ANIMATION_NONE;
+      } else if (contents->tab_contents()->waiting_for_response()) {
+        state = TabGtk::ANIMATION_WAITING;
+      } else {
+        state = TabGtk::ANIMATION_LOADING;
+      }
+      if (current_tab->ValidateLoadingAnimation(state)) {
+        // Queue the tab's icon area to be repainted.
+        gfx::Rect favicon_bounds = current_tab->favicon_bounds();
+        gtk_widget_queue_draw_area(tabstrip_.get(),
+            favicon_bounds.x() + current_tab->x(),
+            favicon_bounds.y() + current_tab->y(),
+            favicon_bounds.width(),
+            favicon_bounds.height());
+      }
+    }
+  }
+}
+
+bool TabStripGtk::IsCompatibleWith(TabStripGtk* other) {
+  return model_->profile() == other->model()->profile();
+}
+
+bool TabStripGtk::IsAnimating() const {
+  return active_animation_.get() != NULL;
+}
+
+void TabStripGtk::DestroyDragController() {
+  drag_controller_.reset();
+}
+
+void TabStripGtk::DestroyDraggedSourceTab(TabGtk* tab) {
+  // We could be running an animation that references this Tab.
+  StopAnimation();
+
+  // Make sure we leave the tab_data_ vector in a consistent state, otherwise
+  // we'll be pointing to tabs that have been deleted and removed from the
+  // child view list.
+  std::vector<TabData>::iterator it = tab_data_.begin();
+  for (; it != tab_data_.end(); ++it) {
+    if (it->tab == tab) {
+      if (!model_->closing_all())
+        NOTREACHED() << "Leaving in an inconsistent state!";
+      tab_data_.erase(it);
+      break;
+    }
+  }
+
+  gtk_container_remove(GTK_CONTAINER(tabstrip_.get()), tab->widget());
+  // If we delete the dragged source tab here, the DestroyDragWidget posted
+  // task will be run after the tab is deleted, leading to a crash.
+  MessageLoop::current()->DeleteSoon(FROM_HERE, tab);
+
+  // Force a layout here, because if we've just quickly drag detached a Tab,
+  // the stopping of the active animation above may have left the TabStrip in a
+  // bad (visual) state.
+  Layout();
+}
+
+gfx::Rect TabStripGtk::GetIdealBounds(int index) {
+  DCHECK(index >= 0 && index < GetTabCount());
+  return tab_data_.at(index).ideal_bounds;
+}
+
+void TabStripGtk::SetVerticalOffset(int offset) {
+  tab_vertical_offset_ = offset;
+  Layout();
+}
+
+gfx::Point TabStripGtk::GetTabStripOriginForWidget(GtkWidget* target) {
+  int x, y;
+  if (!gtk_widget_translate_coordinates(widget(), target,
+      -widget()->allocation.x, 0, &x, &y)) {
+    // If the tab strip isn't showing, give the coordinates relative to the
+    // toplevel instead.
+    if (!gtk_widget_translate_coordinates(
+        gtk_widget_get_toplevel(widget()), target, 0, 0, &x, &y)) {
+      NOTREACHED();
+    }
+  }
+  if (GTK_WIDGET_NO_WINDOW(target)) {
+    x += target->allocation.x;
+    y += target->allocation.y;
+  }
+  return gfx::Point(x, y);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewIDUtil::Delegate implementation
+
+GtkWidget* TabStripGtk::GetWidgetForViewID(ViewID view_id) {
+  if (GetTabCount() > 0) {
+    if (view_id == VIEW_ID_TAB_LAST) {
+      return GetTabAt(GetTabCount() - 1)->widget();
+    } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) {
+      int index = view_id - VIEW_ID_TAB_0;
+      if (index >= 0 && index < GetTabCount()) {
+        return GetTabAt(index)->widget();
+      } else {
+        return NULL;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabStripGtk, TabStripModelObserver implementation:
+
+void TabStripGtk::TabInsertedAt(TabContentsWrapper* contents,
+                                int index,
+                                bool foreground) {
+  DCHECK(contents);
+  DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index));
+
+  StopAnimation();
+
+  bool contains_tab = false;
+  TabGtk* tab = NULL;
+  // First see if this Tab is one that was dragged out of this TabStrip and is
+  // now being dragged back in. In this case, the DraggedTabController actually
+  // has the Tab already constructed and we can just insert it into our list
+  // again.
+  if (IsDragSessionActive()) {
+    tab = drag_controller_->GetDragSourceTabForContents(
+        contents->tab_contents());
+    if (tab) {
+      // If the Tab was detached, it would have been animated closed but not
+      // removed, so we need to reset this property.
+      tab->set_closing(false);
+      tab->ValidateLoadingAnimation(TabRendererGtk::ANIMATION_NONE);
+      tab->SetVisible(true);
+    }
+
+    // See if we're already in the list. We don't want to add ourselves twice.
+    std::vector<TabData>::const_iterator iter = tab_data_.begin();
+    for (; iter != tab_data_.end() && !contains_tab; ++iter) {
+      if (iter->tab == tab)
+        contains_tab = true;
+    }
+  }
+
+  if (!tab)
+    tab = new TabGtk(this);
+
+  // Only insert if we're not already in the list.
+  if (!contains_tab) {
+    TabData d = { tab, gfx::Rect() };
+    tab_data_.insert(tab_data_.begin() + index, d);
+    tab->UpdateData(contents->tab_contents(), model_->IsAppTab(index), false);
+  }
+  tab->set_mini(model_->IsMiniTab(index));
+  tab->set_app(model_->IsAppTab(index));
+  tab->SetBlocked(model_->IsTabBlocked(index));
+
+  if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get())
+    gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0);
+
+  // Don't animate the first tab; it looks weird.
+  if (GetTabCount() > 1) {
+    StartInsertTabAnimation(index);
+    // We added the tab at 0x0, we need to force an animation step otherwise
+    // if GTK paints before the animation event the tab is painted at 0x0
+    // which is most likely not where it should be positioned.
+    active_animation_->AnimationProgressed(NULL);
+  } else {
+    Layout();
+  }
+}
+
+void TabStripGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
+  GenerateIdealBounds();
+  StartRemoveTabAnimation(index, contents->tab_contents());
+  // Have to do this _after_ calling StartRemoveTabAnimation, so that any
+  // previous remove is completed fully and index is valid in sync with the
+  // model index.
+  GetTabAt(index)->set_closing(true);
+}
+
+void TabStripGtk::TabSelectedAt(TabContentsWrapper* old_contents,
+                                TabContentsWrapper* new_contents,
+                                int index,
+                                bool user_gesture) {
+  DCHECK(index >= 0 && index < static_cast<int>(GetTabCount()));
+
+  // We have "tiny tabs" if the tabs are so tiny that the unselected ones are
+  // a different size to the selected ones.
+  bool tiny_tabs = current_unselected_width_ != current_selected_width_;
+  if (!IsAnimating() && (!needs_resize_layout_ || tiny_tabs))
+    Layout();
+
+  GetTabAt(index)->SchedulePaint();
+
+  int old_index = model_->GetIndexOfTabContents(old_contents);
+  if (old_index >= 0) {
+    GetTabAt(old_index)->SchedulePaint();
+    GetTabAt(old_index)->StopMiniTabTitleAnimation();
+  }
+}
+
+void TabStripGtk::TabMoved(TabContentsWrapper* contents,
+                           int from_index,
+                           int to_index) {
+  gfx::Rect start_bounds = GetIdealBounds(from_index);
+  TabGtk* tab = GetTabAt(from_index);
+  tab_data_.erase(tab_data_.begin() + from_index);
+  TabData data = {tab, gfx::Rect()};
+  tab->set_mini(model_->IsMiniTab(to_index));
+  tab->SetBlocked(model_->IsTabBlocked(to_index));
+  tab_data_.insert(tab_data_.begin() + to_index, data);
+  GenerateIdealBounds();
+  StartMoveTabAnimation(from_index, to_index);
+}
+
+void TabStripGtk::TabChangedAt(TabContentsWrapper* contents, int index,
+                               TabChangeType change_type) {
+  // Index is in terms of the model. Need to make sure we adjust that index in
+  // case we have an animation going.
+  TabGtk* tab = GetTabAtAdjustForAnimation(index);
+  if (change_type == TITLE_NOT_LOADING) {
+    if (tab->mini() && !tab->IsSelected())
+      tab->StartMiniTabTitleAnimation();
+    // We'll receive another notification of the change asynchronously.
+    return;
+  }
+  tab->UpdateData(contents->tab_contents(),
+                  model_->IsAppTab(index),
+                  change_type == LOADING_ONLY);
+  tab->UpdateFromModel();
+}
+
+void TabStripGtk::TabReplacedAt(TabStripModel* tab_strip_model,
+                                TabContentsWrapper* old_contents,
+                                TabContentsWrapper* new_contents,
+                                int index) {
+  TabChangedAt(new_contents, index, ALL);
+}
+
+void TabStripGtk::TabMiniStateChanged(TabContentsWrapper* contents, int index) {
+  // Don't do anything if we've already picked up the change from TabMoved.
+  if (GetTabAt(index)->mini() == model_->IsMiniTab(index))
+    return;
+
+  GetTabAt(index)->set_mini(model_->IsMiniTab(index));
+  // Don't animate if the window isn't visible yet. The window won't be visible
+  // when dragging a mini-tab to a new window.
+  if (window_ && window_->window() &&
+      GTK_WIDGET_VISIBLE(GTK_WIDGET(window_->window()))) {
+    StartMiniTabAnimation(index);
+  } else {
+    Layout();
+  }
+}
+
+void TabStripGtk::TabBlockedStateChanged(TabContentsWrapper* contents,
+                                         int index) {
+  GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabStripGtk, TabGtk::TabDelegate implementation:
+
+bool TabStripGtk::IsTabSelected(const TabGtk* tab) const {
+  if (tab->closing())
+    return false;
+
+  return GetIndexOfTab(tab) == model_->selected_index();
+}
+
+bool TabStripGtk::IsTabDetached(const TabGtk* tab) const {
+  if (drag_controller_.get())
+    return drag_controller_->IsTabDetached(tab);
+  return false;
+}
+
+void TabStripGtk::GetCurrentTabWidths(double* unselected_width,
+                                      double* selected_width) const {
+  *unselected_width = current_unselected_width_;
+  *selected_width = current_selected_width_;
+}
+
+bool TabStripGtk::IsTabPinned(const TabGtk* tab) const {
+  if (tab->closing())
+    return false;
+
+  return model_->IsTabPinned(GetIndexOfTab(tab));
+}
+
+void TabStripGtk::SelectTab(TabGtk* tab) {
+  int index = GetIndexOfTab(tab);
+  if (model_->ContainsIndex(index))
+    model_->SelectTabContentsAt(index, true);
+}
+
+void TabStripGtk::CloseTab(TabGtk* tab) {
+  int tab_index = GetIndexOfTab(tab);
+  if (model_->ContainsIndex(tab_index)) {
+    TabGtk* last_tab = GetTabAt(GetTabCount() - 1);
+    // Limit the width available to the TabStrip for laying out Tabs, so that
+    // Tabs are not resized until a later time (when the mouse pointer leaves
+    // the TabStrip).
+    available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
+    needs_resize_layout_ = true;
+    // We hook into the message loop in order to receive mouse move events when
+    // the mouse is outside of the tabstrip.  We unhook once the resize layout
+    // animation is started.
+    AddMessageLoopObserver();
+    model_->CloseTabContentsAt(tab_index,
+                               TabStripModel::CLOSE_USER_GESTURE |
+                               TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
+  }
+}
+
+bool TabStripGtk::IsCommandEnabledForTab(
+    TabStripModel::ContextMenuCommand command_id, const TabGtk* tab) const {
+  int index = GetIndexOfTab(tab);
+  if (model_->ContainsIndex(index))
+    return model_->IsContextMenuCommandEnabled(index, command_id);
+  return false;
+}
+
+void TabStripGtk::ExecuteCommandForTab(
+    TabStripModel::ContextMenuCommand command_id, TabGtk* tab) {
+  int index = GetIndexOfTab(tab);
+  if (model_->ContainsIndex(index))
+    model_->ExecuteContextMenuCommand(index, command_id);
+}
+
+void TabStripGtk::StartHighlightTabsForCommand(
+    TabStripModel::ContextMenuCommand command_id, TabGtk* tab) {
+  if (command_id == TabStripModel::CommandCloseOtherTabs ||
+      command_id == TabStripModel::CommandCloseTabsToRight) {
+    NOTIMPLEMENTED();
+  }
+}
+
+void TabStripGtk::StopHighlightTabsForCommand(
+    TabStripModel::ContextMenuCommand command_id, TabGtk* tab) {
+  if (command_id == TabStripModel::CommandCloseTabsToRight ||
+      command_id == TabStripModel::CommandCloseOtherTabs) {
+    // Just tell all Tabs to stop pulsing - it's safe.
+    StopAllHighlighting();
+  }
+}
+
+void TabStripGtk::StopAllHighlighting() {
+  // TODO(jhawkins): Hook up animations.
+  NOTIMPLEMENTED();
+}
+
+void TabStripGtk::MaybeStartDrag(TabGtk* tab, const gfx::Point& point) {
+  // Don't accidentally start any drag operations during animations if the
+  // mouse is down.
+  if (IsAnimating() || tab->closing() || !HasAvailableDragActions())
+    return;
+
+  drag_controller_.reset(new DraggedTabControllerGtk(tab, this));
+  drag_controller_->CaptureDragInfo(point);
+}
+
+void TabStripGtk::ContinueDrag(GdkDragContext* context) {
+  // We can get called even if |MaybeStartDrag| wasn't called in the event of
+  // a TabStrip animation when the mouse button is down. In this case we should
+  // _not_ continue the drag because it can lead to weird bugs.
+  if (drag_controller_.get())
+    drag_controller_->Drag();
+}
+
+bool TabStripGtk::EndDrag(bool canceled) {
+  return drag_controller_.get() ? drag_controller_->EndDrag(canceled) : false;
+}
+
+bool TabStripGtk::HasAvailableDragActions() const {
+  return model_->delegate()->GetDragActions() != 0;
+}
+
+ui::ThemeProvider* TabStripGtk::GetThemeProvider() {
+  return theme_provider_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TabStripGtk, MessageLoop::Observer implementation:
+
+void TabStripGtk::WillProcessEvent(GdkEvent* event) {
+  // Nothing to do.
+}
+
+void TabStripGtk::DidProcessEvent(GdkEvent* event) {
+  switch (event->type) {
+    case GDK_MOTION_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      HandleGlobalMouseMoveEvent();
+      break;
+    default:
+      break;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TabStripGtk, NotificationObserver implementation:
+
+void TabStripGtk::Observe(NotificationType type,
+                          const NotificationSource& source,
+                          const NotificationDetails& details) {
+  if (type == NotificationType::BROWSER_THEME_CHANGED) {
+    TabRendererGtk::SetSelectedTitleColor(theme_provider_->GetColor(
+        BrowserThemeProvider::COLOR_TAB_TEXT));
+    TabRendererGtk::SetUnselectedTitleColor(theme_provider_->GetColor(
+        BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT));
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabStripGtk, private:
+
+int TabStripGtk::GetTabCount() const {
+  return static_cast<int>(tab_data_.size());
+}
+
+int TabStripGtk::GetMiniTabCount() const {
+  int mini_count = 0;
+  for (size_t i = 0; i < tab_data_.size(); ++i) {
+    if (tab_data_[i].tab->mini())
+      mini_count++;
+    else
+      return mini_count;
+  }
+  return mini_count;
+}
+
+int TabStripGtk::GetAvailableWidthForTabs(TabGtk* last_tab) const {
+  if (!base::i18n::IsRTL())
+    return last_tab->x() - bounds_.x() + last_tab->width();
+  else
+    return bounds_.width() - last_tab->x();
+}
+
+int TabStripGtk::GetIndexOfTab(const TabGtk* tab) const {
+  for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
+    TabGtk* current_tab = GetTabAt(i);
+    if (current_tab->closing()) {
+      --index;
+    } else if (current_tab == tab) {
+      return index;
+    }
+  }
+  return -1;
+}
+
+TabGtk* TabStripGtk::GetTabAt(int index) const {
+  DCHECK_GE(index, 0);
+  DCHECK_LT(index, GetTabCount());
+  return tab_data_.at(index).tab;
+}
+
+TabGtk* TabStripGtk::GetTabAtAdjustForAnimation(int index) const {
+  if (active_animation_.get() &&
+      active_animation_->type() == TabAnimation::REMOVE &&
+      index >=
+      static_cast<RemoveTabAnimation*>(active_animation_.get())->index()) {
+    index++;
+  }
+  return GetTabAt(index);
+}
+
+void TabStripGtk::RemoveTabAt(int index) {
+  TabGtk* removed = tab_data_.at(index).tab;
+
+  // Remove the Tab from the TabStrip's list.
+  tab_data_.erase(tab_data_.begin() + index);
+
+  if (!IsDragSessionActive() || !drag_controller_->IsDragSourceTab(removed)) {
+    gtk_container_remove(GTK_CONTAINER(tabstrip_.get()), removed->widget());
+    delete removed;
+  }
+}
+
+void TabStripGtk::HandleGlobalMouseMoveEvent() {
+  if (!IsCursorInTabStripZone()) {
+    // Mouse moved outside the tab slop zone, start a timer to do a resize
+    // layout after a short while...
+    if (resize_layout_factory_.empty()) {
+      MessageLoop::current()->PostDelayedTask(FROM_HERE,
+          resize_layout_factory_.NewRunnableMethod(
+              &TabStripGtk::ResizeLayoutTabs),
+          kResizeTabsTimeMs);
+    }
+  } else {
+    // Mouse moved quickly out of the tab strip and then into it again, so
+    // cancel the timer so that the strip doesn't move when the mouse moves
+    // back over it.
+    resize_layout_factory_.RevokeAll();
+  }
+}
+
+void TabStripGtk::GenerateIdealBounds() {
+  int tab_count = GetTabCount();
+  double unselected, selected;
+  GetDesiredTabWidths(tab_count, GetMiniTabCount(), &unselected, &selected);
+
+  current_unselected_width_ = unselected;
+  current_selected_width_ = selected;
+
+  // NOTE: This currently assumes a tab's height doesn't differ based on
+  // selected state or the number of tabs in the strip!
+  int tab_height = TabGtk::GetStandardSize().height();
+  double tab_x = tab_start_x();
+  for (int i = 0; i < tab_count; ++i) {
+    TabGtk* tab = GetTabAt(i);
+    double tab_width = unselected;
+    if (tab->mini())
+      tab_width = TabGtk::GetMiniWidth();
+    else if (tab->IsSelected())
+      tab_width = selected;
+    double end_of_tab = tab_x + tab_width;
+    int rounded_tab_x = Round(tab_x);
+    gfx::Rect state(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
+                    tab_height);
+    tab_data_.at(i).ideal_bounds = state;
+    tab_x = end_of_tab + GetTabHOffset(i + 1);
+  }
+}
+
+void TabStripGtk::LayoutNewTabButton(double last_tab_right,
+                                     double unselected_width) {
+  gfx::Rect bounds(0, kNewTabButtonVOffset,
+                   newtab_button_->width(), newtab_button_->height());
+  int delta = abs(Round(unselected_width) - TabGtk::GetStandardSize().width());
+  if (delta > 1 && !needs_resize_layout_) {
+    // We're shrinking tabs, so we need to anchor the New Tab button to the
+    // right edge of the TabStrip's bounds, rather than the right edge of the
+    // right-most Tab, otherwise it'll bounce when animating.
+    bounds.set_x(bounds_.width() - newtab_button_->width());
+  } else {
+    bounds.set_x(Round(last_tab_right - kTabHOffset) + kNewTabButtonHOffset);
+  }
+  bounds.set_x(gtk_util::MirroredLeftPointForRect(tabstrip_.get(), bounds));
+
+  gtk_fixed_move(GTK_FIXED(tabstrip_.get()), newtab_button_->widget(),
+                 bounds.x(), bounds.y());
+}
+
+void TabStripGtk::GetDesiredTabWidths(int tab_count,
+                                      int mini_tab_count,
+                                      double* unselected_width,
+                                      double* selected_width) const {
+  DCHECK(tab_count >= 0 && mini_tab_count >= 0 && mini_tab_count <= tab_count);
+  const double min_unselected_width =
+      TabGtk::GetMinimumUnselectedSize().width();
+  const double min_selected_width =
+      TabGtk::GetMinimumSelectedSize().width();
+
+  *unselected_width = min_unselected_width;
+  *selected_width = min_selected_width;
+
+  if (tab_count == 0) {
+    // Return immediately to avoid divide-by-zero below.
+    return;
+  }
+
+  // Determine how much space we can actually allocate to tabs.
+  int available_width = tabstrip_->allocation.width;
+  if (available_width_for_tabs_ < 0) {
+    available_width = bounds_.width();
+    available_width -=
+        (kNewTabButtonHOffset + newtab_button_->width());
+  } else {
+    // Interesting corner case: if |available_width_for_tabs_| > the result
+    // of the calculation in the conditional arm above, the strip is in
+    // overflow.  We can either use the specified width or the true available
+    // width here; the first preserves the consistent "leave the last tab under
+    // the user's mouse so they can close many tabs" behavior at the cost of
+    // prolonging the glitchy appearance of the overflow state, while the second
+    // gets us out of overflow as soon as possible but forces the user to move
+    // their mouse for a few tabs' worth of closing.  We choose visual
+    // imperfection over behavioral imperfection and select the first option.
+    available_width = available_width_for_tabs_;
+  }
+
+  if (mini_tab_count > 0) {
+    available_width -= mini_tab_count * (TabGtk::GetMiniWidth() + kTabHOffset);
+    tab_count -= mini_tab_count;
+    if (tab_count == 0) {
+      *selected_width = *unselected_width = TabGtk::GetStandardSize().width();
+      return;
+    }
+    // Account for gap between the last mini-tab and first normal tab.
+    available_width -= mini_to_non_mini_gap_;
+  }
+
+  // Calculate the desired tab widths by dividing the available space into equal
+  // portions.  Don't let tabs get larger than the "standard width" or smaller
+  // than the minimum width for each type, respectively.
+  const int total_offset = kTabHOffset * (tab_count - 1);
+  const double desired_tab_width = std::min(
+      (static_cast<double>(available_width - total_offset) /
+       static_cast<double>(tab_count)),
+      static_cast<double>(TabGtk::GetStandardSize().width()));
+
+  *unselected_width = std::max(desired_tab_width, min_unselected_width);
+  *selected_width = std::max(desired_tab_width, min_selected_width);
+
+  // When there are multiple tabs, we'll have one selected and some unselected
+  // tabs.  If the desired width was between the minimum sizes of these types,
+  // try to shrink the tabs with the smaller minimum.  For example, if we have
+  // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5.  If
+  // selected tabs have a minimum width of 4 and unselected tabs have a minimum
+  // width of 1, the above code would set *unselected_width = 2.5,
+  // *selected_width = 4, which results in a total width of 11.5.  Instead, we
+  // want to set *unselected_width = 2, *selected_width = 4, for a total width
+  // of 10.
+  if (tab_count > 1) {
+    if ((min_unselected_width < min_selected_width) &&
+        (desired_tab_width < min_selected_width)) {
+      double calc_width =
+          static_cast<double>(
+              available_width - total_offset - min_selected_width) /
+          static_cast<double>(tab_count - 1);
+      *unselected_width = std::max(calc_width, min_unselected_width);
+    } else if ((min_unselected_width > min_selected_width) &&
+               (desired_tab_width < min_unselected_width)) {
+      *selected_width = std::max(available_width - total_offset -
+          (min_unselected_width * (tab_count - 1)), min_selected_width);
+    }
+  }
+}
+
+int TabStripGtk::GetTabHOffset(int tab_index) {
+  if (tab_index < GetTabCount() && GetTabAt(tab_index - 1)->mini() &&
+      !GetTabAt(tab_index)->mini()) {
+    return mini_to_non_mini_gap_ + kTabHOffset;
+  }
+  return kTabHOffset;
+}
+
+int TabStripGtk::tab_start_x() const {
+  return 0;
+}
+
+bool TabStripGtk::ResizeLayoutTabs() {
+  resize_layout_factory_.RevokeAll();
+
+  // It is critically important that this is unhooked here, otherwise we will
+  // keep spying on messages forever.
+  RemoveMessageLoopObserver();
+
+  available_width_for_tabs_ = -1;
+  int mini_tab_count = GetMiniTabCount();
+  if (mini_tab_count == GetTabCount()) {
+    // Only mini tabs, we know the tab widths won't have changed (all mini-tabs
+    // have the same width), so there is nothing to do.
+    return false;
+  }
+  TabGtk* first_tab = GetTabAt(mini_tab_count);
+  double unselected, selected;
+  GetDesiredTabWidths(GetTabCount(), mini_tab_count, &unselected, &selected);
+  int w = Round(first_tab->IsSelected() ? selected : unselected);
+
+  // We only want to run the animation if we're not already at the desired
+  // size.
+  if (abs(first_tab->width() - w) > 1) {
+    StartResizeLayoutAnimation();
+    return true;
+  }
+
+  return false;
+}
+
+bool TabStripGtk::IsCursorInTabStripZone() const {
+  gfx::Point tabstrip_topleft;
+  gtk_util::ConvertWidgetPointToScreen(tabstrip_.get(), &tabstrip_topleft);
+
+  gfx::Rect bds = bounds();
+  bds.set_origin(tabstrip_topleft);
+  bds.set_height(bds.height() + kTabStripAnimationVSlop);
+
+  GdkScreen* screen = gdk_screen_get_default();
+  GdkDisplay* display = gdk_screen_get_display(screen);
+  gint x, y;
+  gdk_display_get_pointer(display, NULL, &x, &y, NULL);
+  gfx::Point cursor_point(x, y);
+
+  return bds.Contains(cursor_point);
+}
+
+void TabStripGtk::AddMessageLoopObserver() {
+  if (!added_as_message_loop_observer_) {
+    MessageLoopForUI::current()->AddObserver(this);
+    added_as_message_loop_observer_ = true;
+  }
+}
+
+void TabStripGtk::RemoveMessageLoopObserver() {
+  if (added_as_message_loop_observer_) {
+    MessageLoopForUI::current()->RemoveObserver(this);
+    added_as_message_loop_observer_ = false;
+  }
+}
+
+gfx::Rect TabStripGtk::GetDropBounds(int drop_index,
+                                     bool drop_before,
+                                     bool* is_beneath) {
+  DCHECK_NE(drop_index, -1);
+  int center_x;
+  if (drop_index < GetTabCount()) {
+    TabGtk* tab = GetTabAt(drop_index);
+    gfx::Rect bounds = tab->GetNonMirroredBounds(tabstrip_.get());
+    // TODO(sky): update these for pinned tabs.
+    if (drop_before)
+      center_x = bounds.x() - (kTabHOffset / 2);
+    else
+      center_x = bounds.x() + (bounds.width() / 2);
+  } else {
+    TabGtk* last_tab = GetTabAt(drop_index - 1);
+    gfx::Rect bounds = last_tab->GetNonMirroredBounds(tabstrip_.get());
+    center_x = bounds.x() + bounds.width() + (kTabHOffset / 2);
+  }
+
+  center_x = gtk_util::MirroredXCoordinate(tabstrip_.get(), center_x);
+
+  // Determine the screen bounds.
+  gfx::Point drop_loc(center_x - drop_indicator_width / 2,
+                      -drop_indicator_height);
+  gtk_util::ConvertWidgetPointToScreen(tabstrip_.get(), &drop_loc);
+  gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width,
+                        drop_indicator_height);
+
+  // TODO(jhawkins): We always display the arrow underneath the tab because we
+  // don't have custom frame support yet.
+  *is_beneath = true;
+  if (*is_beneath)
+    drop_bounds.Offset(0, drop_bounds.height() + bounds().height());
+
+  return drop_bounds;
+}
+
+void TabStripGtk::UpdateDropIndex(GdkDragContext* context, gint x, gint y) {
+  // If the UI layout is right-to-left, we need to mirror the mouse
+  // coordinates since we calculate the drop index based on the
+  // original (and therefore non-mirrored) positions of the tabs.
+  x = gtk_util::MirroredXCoordinate(tabstrip_.get(), x);
+  // We don't allow replacing the urls of mini-tabs.
+  for (int i = GetMiniTabCount(); i < GetTabCount(); ++i) {
+    TabGtk* tab = GetTabAt(i);
+    gfx::Rect bounds = tab->GetNonMirroredBounds(tabstrip_.get());
+    const int tab_max_x = bounds.x() + bounds.width();
+    const int hot_width = bounds.width() / 3;
+    if (x < tab_max_x) {
+      if (x < bounds.x() + hot_width)
+        SetDropIndex(i, true);
+      else if (x >= tab_max_x - hot_width)
+        SetDropIndex(i + 1, true);
+      else
+        SetDropIndex(i, false);
+      return;
+    }
+  }
+
+  // The drop isn't over a tab, add it to the end.
+  SetDropIndex(GetTabCount(), true);
+}
+
+void TabStripGtk::SetDropIndex(int index, bool drop_before) {
+  bool is_beneath;
+  gfx::Rect drop_bounds = GetDropBounds(index, drop_before, &is_beneath);
+
+  if (!drop_info_.get()) {
+    drop_info_.reset(new DropInfo(index, drop_before, !is_beneath));
+  } else {
+    if (!GTK_IS_WIDGET(drop_info_->container)) {
+      drop_info_->CreateContainer();
+    } else if (drop_info_->drop_index == index &&
+               drop_info_->drop_before == drop_before) {
+      return;
+    }
+
+    drop_info_->drop_index = index;
+    drop_info_->drop_before = drop_before;
+    if (is_beneath == drop_info_->point_down) {
+      drop_info_->point_down = !is_beneath;
+      drop_info_->drop_arrow= GetDropArrowImage(drop_info_->point_down);
+    }
+  }
+
+  gtk_window_move(GTK_WINDOW(drop_info_->container),
+                  drop_bounds.x(), drop_bounds.y());
+  gtk_window_resize(GTK_WINDOW(drop_info_->container),
+                    drop_bounds.width(), drop_bounds.height());
+}
+
+bool TabStripGtk::CompleteDrop(guchar* data, bool is_plain_text) {
+  if (!drop_info_.get())
+    return false;
+
+  const int drop_index = drop_info_->drop_index;
+  const bool drop_before = drop_info_->drop_before;
+
+  // Destroy the drop indicator.
+  drop_info_.reset();
+
+  GURL url;
+  if (is_plain_text) {
+    AutocompleteMatch match;
+    model_->profile()->GetAutocompleteClassifier()->Classify(
+        UTF8ToUTF16(reinterpret_cast<char*>(data)), string16(), false,
+        &match, NULL);
+    url = match.destination_url;
+  } else {
+    std::string url_string(reinterpret_cast<char*>(data));
+    url = GURL(url_string.substr(0, url_string.find_first_of('\n')));
+  }
+  if (!url.is_valid())
+    return false;
+
+  browser::NavigateParams params(window()->browser(), url,
+                                 PageTransition::LINK);
+  params.tabstrip_index = drop_index;
+
+  if (drop_before) {
+    params.disposition = NEW_FOREGROUND_TAB;
+  } else {
+    params.disposition = CURRENT_TAB;
+    params.source_contents = model_->GetTabContentsAt(drop_index);
+  }
+
+  browser::Navigate(&params);
+
+  return true;
+}
+
+// static
+GdkPixbuf* TabStripGtk::GetDropArrowImage(bool is_down) {
+  return ResourceBundle::GetSharedInstance().GetPixbufNamed(
+      is_down ? IDR_TAB_DROP_DOWN : IDR_TAB_DROP_UP);
+}
+
+// TabStripGtk::DropInfo -------------------------------------------------------
+
+TabStripGtk::DropInfo::DropInfo(int drop_index, bool drop_before,
+                                bool point_down)
+    : drop_index(drop_index),
+      drop_before(drop_before),
+      point_down(point_down) {
+  CreateContainer();
+  drop_arrow = GetDropArrowImage(point_down);
+}
+
+TabStripGtk::DropInfo::~DropInfo() {
+  DestroyContainer();
+}
+
+gboolean TabStripGtk::DropInfo::OnExposeEvent(GtkWidget* widget,
+                                              GdkEventExpose* event) {
+  if (gtk_util::IsScreenComposited()) {
+    SetContainerTransparency();
+  } else {
+    SetContainerShapeMask();
+  }
+
+  gdk_pixbuf_render_to_drawable(drop_arrow,
+                                container->window,
+                                0, 0, 0,
+                                0, 0,
+                                drop_indicator_width,
+                                drop_indicator_height,
+                                GDK_RGB_DITHER_NONE, 0, 0);
+
+  return FALSE;
+}
+
+// Sets the color map of the container window to allow the window to be
+// transparent.
+void TabStripGtk::DropInfo::SetContainerColorMap() {
+  GdkScreen* screen = gtk_widget_get_screen(container);
+  GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
+
+  // If rgba is not available, use rgb instead.
+  if (!colormap)
+    colormap = gdk_screen_get_rgb_colormap(screen);
+
+  gtk_widget_set_colormap(container, colormap);
+}
+
+// Sets full transparency for the container window.  This is used if
+// compositing is available for the screen.
+void TabStripGtk::DropInfo::SetContainerTransparency() {
+  cairo_t* cairo_context = gdk_cairo_create(container->window);
+  if (!cairo_context)
+      return;
+
+  // Make the background of the dragged tab window fully transparent.  All of
+  // the content of the window (child widgets) will be completely opaque.
+
+  cairo_scale(cairo_context, static_cast<double>(drop_indicator_width),
+              static_cast<double>(drop_indicator_height));
+  cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
+  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
+  cairo_paint(cairo_context);
+  cairo_destroy(cairo_context);
+}
+
+// Sets the shape mask for the container window to emulate a transparent
+// container window.  This is used if compositing is not available for the
+// screen.
+void TabStripGtk::DropInfo::SetContainerShapeMask() {
+  // Create a 1bpp bitmap the size of |container|.
+  GdkPixmap* pixmap = gdk_pixmap_new(NULL,
+                                     drop_indicator_width,
+                                     drop_indicator_height, 1);
+  cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(pixmap));
+
+  // Set the transparency.
+  cairo_set_source_rgba(cairo_context, 1, 1, 1, 0);
+
+  // Blit the rendered bitmap into a pixmap.  Any pixel set in the pixmap will
+  // be opaque in the container window.
+  cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
+  gdk_cairo_set_source_pixbuf(cairo_context, drop_arrow, 0, 0);
+  cairo_paint(cairo_context);
+  cairo_destroy(cairo_context);
+
+  // Set the shape mask.
+  gdk_window_shape_combine_mask(container->window, pixmap, 0, 0);
+  g_object_unref(pixmap);
+}
+
+void TabStripGtk::DropInfo::CreateContainer() {
+  container = gtk_window_new(GTK_WINDOW_POPUP);
+  SetContainerColorMap();
+  gtk_widget_set_app_paintable(container, TRUE);
+  g_signal_connect(container, "expose-event",
+                   G_CALLBACK(OnExposeEventThunk), this);
+  gtk_widget_add_events(container, GDK_STRUCTURE_MASK);
+  gtk_window_move(GTK_WINDOW(container), 0, 0);
+  gtk_window_resize(GTK_WINDOW(container),
+                    drop_indicator_width, drop_indicator_height);
+  gtk_widget_show_all(container);
+}
+
+void TabStripGtk::DropInfo::DestroyContainer() {
+  if (GTK_IS_WIDGET(container))
+    gtk_widget_destroy(container);
+}
+
+void TabStripGtk::StopAnimation() {
+  if (active_animation_.get())
+    active_animation_->Stop();
+}
+
+// Called from:
+// - animation tick
+void TabStripGtk::AnimationLayout(double unselected_width) {
+  int tab_height = TabGtk::GetStandardSize().height();
+  double tab_x = tab_start_x();
+  for (int i = 0; i < GetTabCount(); ++i) {
+    TabAnimation* animation = active_animation_.get();
+    if (animation)
+      tab_x += animation->GetGapWidth(i);
+    double tab_width = TabAnimation::GetCurrentTabWidth(this, animation, i);
+    double end_of_tab = tab_x + tab_width;
+    int rounded_tab_x = Round(tab_x);
+    TabGtk* tab = GetTabAt(i);
+    gfx::Rect bounds(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
+                     tab_height);
+    SetTabBounds(tab, bounds);
+    tab_x = end_of_tab + GetTabHOffset(i + 1);
+  }
+  LayoutNewTabButton(tab_x, unselected_width);
+}
+
+void TabStripGtk::StartInsertTabAnimation(int index) {
+  // The TabStrip can now use its entire width to lay out Tabs.
+  available_width_for_tabs_ = -1;
+  StopAnimation();
+  active_animation_.reset(new InsertTabAnimation(this, index));
+  active_animation_->Start();
+}
+
+void TabStripGtk::StartRemoveTabAnimation(int index, TabContents* contents) {
+  if (active_animation_.get()) {
+    // Some animations (e.g. MoveTabAnimation) cause there to be a Layout when
+    // they're completed (which includes canceled). Since |tab_data_| is now
+    // inconsistent with TabStripModel, doing this Layout will crash now, so
+    // we ask the MoveTabAnimation to skip its Layout (the state will be
+    // corrected by the RemoveTabAnimation we're about to initiate).
+    active_animation_->set_layout_on_completion(false);
+    active_animation_->Stop();
+  }
+
+  active_animation_.reset(new RemoveTabAnimation(this, index, contents));
+  active_animation_->Start();
+}
+
+void TabStripGtk::StartMoveTabAnimation(int from_index, int to_index) {
+  StopAnimation();
+  active_animation_.reset(new MoveTabAnimation(this, from_index, to_index));
+  active_animation_->Start();
+}
+
+void TabStripGtk::StartResizeLayoutAnimation() {
+  StopAnimation();
+  active_animation_.reset(new ResizeLayoutAnimation(this));
+  active_animation_->Start();
+}
+
+void TabStripGtk::StartMiniTabAnimation(int index) {
+  StopAnimation();
+  active_animation_.reset(new MiniTabAnimation(this, index));
+  active_animation_->Start();
+}
+
+void TabStripGtk::StartMiniMoveTabAnimation(int from_index,
+                                            int to_index,
+                                            const gfx::Rect& start_bounds) {
+  StopAnimation();
+  active_animation_.reset(
+      new MiniMoveAnimation(this, from_index, to_index, start_bounds));
+  active_animation_->Start();
+}
+
+void TabStripGtk::FinishAnimation(TabStripGtk::TabAnimation* animation,
+                                  bool layout) {
+  active_animation_.reset(NULL);
+
+  // Reset the animation state of each tab.
+  for (int i = 0, count = GetTabCount(); i < count; ++i)
+    GetTabAt(i)->set_animating_mini_change(false);
+
+  if (layout)
+    Layout();
+}
+
+gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event) {
+  if (gdk_region_empty(event->region))
+    return TRUE;
+
+  // If we're only repainting favicons, optimize the paint path and only draw
+  // the favicons.
+  GdkRectangle* rects;
+  gint num_rects;
+  gdk_region_get_rectangles(event->region, &rects, &num_rects);
+  qsort(rects, num_rects, sizeof(GdkRectangle), CompareGdkRectangles);
+  std::vector<int> tabs_to_repaint;
+  if (!IsDragSessionActive() &&
+      CanPaintOnlyFavIcons(rects, num_rects, &tabs_to_repaint)) {
+    PaintOnlyFavIcons(event, tabs_to_repaint);
+    g_free(rects);
+    return TRUE;
+  }
+  g_free(rects);
+
+  // TODO(jhawkins): Ideally we'd like to only draw what's needed in the damage
+  // rect, but the tab widgets overlap each other, and painting on one widget
+  // will cause an expose-event to be sent to the widgets underneath.  The
+  // underlying widget does not need to be redrawn as we control the order of
+  // expose-events.  Currently we hack it to redraw the entire tabstrip.  We
+  // could change the damage rect to just contain the tabs + the new tab button.
+  event->area.x = 0;
+  event->area.y = 0;
+  event->area.width = bounds_.width();
+  event->area.height = bounds_.height();
+  gdk_region_union_with_rect(event->region, &event->area);
+
+  // Paint the New Tab button.
+  gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()),
+      newtab_button_->widget(), event);
+
+  // Paint the tabs in reverse order, so they stack to the left.
+  TabGtk* selected_tab = NULL;
+  int tab_count = GetTabCount();
+  for (int i = tab_count - 1; i >= 0; --i) {
+    TabGtk* tab = GetTabAt(i);
+    // We must ask the _Tab's_ model, not ourselves, because in some situations
+    // the model will be different to this object, e.g. when a Tab is being
+    // removed after its TabContents has been destroyed.
+    if (!tab->IsSelected()) {
+      gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()),
+                                     tab->widget(), event);
+    } else {
+      selected_tab = tab;
+    }
+  }
+
+  // Paint the selected tab last, so it overlaps all the others.
+  if (selected_tab) {
+    gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()),
+                                   selected_tab->widget(), event);
+  }
+
+  return TRUE;
+}
+
+void TabStripGtk::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) {
+  gfx::Rect bounds = gfx::Rect(allocation->x, allocation->y,
+      allocation->width, allocation->height);
+
+  // Nothing to do if the bounds are the same.  If we don't catch this, we'll
+  // get an infinite loop of size-allocate signals.
+  if (bounds_ == bounds)
+    return;
+
+  SetBounds(bounds);
+
+  // No tabs, nothing to layout.  This happens when a browser window is created
+  // and shown before tabs are added (as in a popup window).
+  if (GetTabCount() == 0)
+    return;
+
+  // When there is only one tab, Layout() so we don't animate it. With more
+  // tabs, do ResizeLayoutTabs(). In RTL(), we will also need to manually
+  // Layout() when ResizeLayoutTabs() is a no-op.
+  if ((GetTabCount() == 1) || (!ResizeLayoutTabs() && base::i18n::IsRTL()))
+    Layout();
+}
+
+gboolean TabStripGtk::OnDragMotion(GtkWidget* widget, GdkDragContext* context,
+                                   gint x, gint y, guint time) {
+  UpdateDropIndex(context, x, y);
+  return TRUE;
+}
+
+gboolean TabStripGtk::OnDragDrop(GtkWidget* widget, GdkDragContext* context,
+                                 gint x, gint y, guint time) {
+  if (!drop_info_.get())
+    return FALSE;
+
+  GdkAtom target = gtk_drag_dest_find_target(widget, context, NULL);
+  if (target != GDK_NONE)
+    gtk_drag_finish(context, FALSE, FALSE, time);
+  else
+    gtk_drag_get_data(widget, context, target, time);
+
+  return TRUE;
+}
+
+gboolean TabStripGtk::OnDragLeave(GtkWidget* widget, GdkDragContext* context,
+                                  guint time) {
+  // Destroy the drop indicator.
+  drop_info_->DestroyContainer();
+  return FALSE;
+}
+
+gboolean TabStripGtk::OnDragDataReceived(GtkWidget* widget,
+                                         GdkDragContext* context,
+                                         gint x, gint y,
+                                         GtkSelectionData* data,
+                                         guint info, guint time) {
+  bool success = false;
+
+  if (info == ui::TEXT_URI_LIST ||
+      info == ui::NETSCAPE_URL ||
+      info == ui::TEXT_PLAIN) {
+    success = CompleteDrop(data->data, info == ui::TEXT_PLAIN);
+  }
+
+  gtk_drag_finish(context, success, success, time);
+  return TRUE;
+}
+
+void TabStripGtk::OnNewTabClicked(GtkWidget* widget) {
+  GdkEvent* event = gtk_get_current_event();
+  DCHECK_EQ(event->type, GDK_BUTTON_RELEASE);
+  int mouse_button = event->button.button;
+  gdk_event_free(event);
+
+  switch (mouse_button) {
+    case 1:
+      model_->delegate()->AddBlankTab(true);
+      break;
+    case 2: {
+      // On middle-click, try to parse the PRIMARY selection as a URL and load
+      // it instead of creating a blank page.
+      GURL url;
+      if (!gtk_util::URLFromPrimarySelection(model_->profile(), &url))
+        return;
+
+      Browser* browser = window_->browser();
+      DCHECK(browser);
+      browser->AddSelectedTabWithURL(url, PageTransition::TYPED);
+      break;
+    }
+    default:
+      NOTREACHED() << "Got click on new tab button with unhandled mouse "
+                   << "button " << mouse_button;
+  }
+}
+
+void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) {
+  gfx::Rect bds = bounds;
+  bds.set_x(gtk_util::MirroredLeftPointForRect(tabstrip_.get(), bounds));
+  tab->SetBounds(bds);
+  gtk_fixed_move(GTK_FIXED(tabstrip_.get()), tab->widget(),
+                 bds.x(), bds.y());
+}
+
+bool TabStripGtk::CanPaintOnlyFavIcons(const GdkRectangle* rects,
+    int num_rects, std::vector<int>* tabs_to_paint) {
+  // |rects| are sorted so we just need to scan from left to right and compare
+  // it to the tab favicon positions from left to right.
+  int t = 0;
+  for (int r = 0; r < num_rects; ++r) {
+    while (t < GetTabCount()) {
+      TabGtk* tab = GetTabAt(t);
+      if (GdkRectMatchesTabFavIconBounds(rects[r], tab) &&
+          tab->ShouldShowIcon()) {
+        tabs_to_paint->push_back(t);
+        ++t;
+        break;
+      }
+      ++t;
+    }
+  }
+  return static_cast<int>(tabs_to_paint->size()) == num_rects;
+}
+
+void TabStripGtk::PaintOnlyFavIcons(GdkEventExpose* event,
+                                    const std::vector<int>& tabs_to_paint) {
+  for (size_t i = 0; i < tabs_to_paint.size(); ++i)
+    GetTabAt(tabs_to_paint[i])->PaintFavIconArea(event);
+}
+
+CustomDrawButton* TabStripGtk::MakeNewTabButton() {
+  CustomDrawButton* button = new CustomDrawButton(IDR_NEWTAB_BUTTON,
+      IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0);
+
+  // Let the middle mouse button initiate clicks as well.
+  gtk_util::SetButtonTriggersNavigation(button->widget());
+  g_signal_connect(button->widget(), "clicked",
+                   G_CALLBACK(OnNewTabClickedThunk), this);
+  GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS);
+  gtk_fixed_put(GTK_FIXED(tabstrip_.get()), button->widget(), 0, 0);
+
+  return button;
+}
diff --git a/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h
new file mode 100644
index 0000000..b7849ae
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h
@@ -0,0 +1,466 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TABS_TAB_STRIP_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TABS_TAB_STRIP_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/task.h"
+#include "base/message_loop.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
+#include "chrome/browser/ui/gtk/tabs/tab_gtk.h"
+#include "chrome/browser/ui/gtk/tabstrip_origin_provider.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/common/notification_observer.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/rect.h"
+
+class BrowserWindowGtk;
+class CustomDrawButton;
+class DraggedTabControllerGtk;
+class GtkThemeProvider;
+
+class TabStripGtk : public TabStripModelObserver,
+                    public TabGtk::TabDelegate,
+                    public MessageLoopForUI::Observer,
+                    public NotificationObserver,
+                    public TabstripOriginProvider,
+                    public ViewIDUtil::Delegate {
+ public:
+  class TabAnimation;
+
+  TabStripGtk(TabStripModel* model, BrowserWindowGtk* window);
+  virtual ~TabStripGtk();
+
+  // Initialize and load the TabStrip into a container.
+  // TODO(tc): Pass in theme provider so we can properly theme the tabs.
+  void Init();
+
+  void Show();
+  void Hide();
+
+  TabStripModel* model() const { return model_; }
+
+  BrowserWindowGtk* window() const { return window_; }
+
+  GtkWidget* widget() const { return tabstrip_.get(); }
+
+  // Returns true if there is an active drag session.
+  bool IsDragSessionActive() const { return drag_controller_.get() != NULL; }
+
+  // Returns true if a tab is being dragged into this tabstrip.
+  bool IsActiveDropTarget() const;
+
+  // Sets the bounds of the tabs.
+  void Layout();
+
+  // Queues a draw for the tabstrip widget.
+  void SchedulePaint();
+
+  // Sets the bounds of the tabstrip.
+  void SetBounds(const gfx::Rect& bounds);
+
+  // Returns the bounds of the tabstrip.
+  const gfx::Rect& bounds() const { return bounds_; }
+
+  // Updates loading animations for the TabStrip.
+  void UpdateLoadingAnimations();
+
+  // Return true if this tab strip is compatible with the provided tab strip.
+  // Compatible tab strips can transfer tabs during drag and drop.
+  bool IsCompatibleWith(TabStripGtk* other);
+
+  // Returns true if Tabs in this TabStrip are currently changing size or
+  // position.
+  bool IsAnimating() const;
+
+  // Destroys the active drag controller.
+  void DestroyDragController();
+
+  // Removes the drag source tab from this tabstrip, and deletes it.
+  void DestroyDraggedSourceTab(TabGtk* tab);
+
+  // Retrieve the ideal bounds for the Tab at the specified index.
+  gfx::Rect GetIdealBounds(int index);
+
+  // Sets the vertical offset that each tab will use to offset against the
+  // background image. Passed in from the titlebar and based on the size of the
+  // alignment that sits above the tabstrip.
+  void SetVerticalOffset(int offset);
+
+  // TabstripOriginProvider implementation -------------------------------------
+  virtual gfx::Point GetTabStripOriginForWidget(GtkWidget* widget);
+
+  // ViewIDUtil::Delegate implementation ---------------------------------------
+  virtual GtkWidget* GetWidgetForViewID(ViewID id);
+
+ protected:
+  // TabStripModelObserver implementation:
+  virtual void TabInsertedAt(TabContentsWrapper* contents,
+                             int index,
+                             bool foreground);
+  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
+  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
+                             TabContentsWrapper* contents,
+                             int index,
+                             bool user_gesture);
+  virtual void TabMoved(TabContentsWrapper* contents,
+                        int from_index,
+                        int to_index);
+  virtual void TabChangedAt(TabContentsWrapper* contents, int index,
+                            TabChangeType change_type);
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index);
+  virtual void TabMiniStateChanged(TabContentsWrapper* contents, int index);
+  virtual void TabBlockedStateChanged(TabContentsWrapper* contents,
+                                      int index);
+
+  // TabGtk::TabDelegate implementation:
+  virtual bool IsTabSelected(const TabGtk* tab) const;
+  virtual bool IsTabPinned(const TabGtk* tab) const;
+  virtual bool IsTabDetached(const TabGtk* tab) const;
+  virtual void SelectTab(TabGtk* tab);
+  virtual void CloseTab(TabGtk* tab);
+  virtual bool IsCommandEnabledForTab(
+      TabStripModel::ContextMenuCommand command_id, const TabGtk* tab) const;
+  virtual void ExecuteCommandForTab(
+      TabStripModel::ContextMenuCommand command_id, TabGtk* tab);
+  virtual void StartHighlightTabsForCommand(
+      TabStripModel::ContextMenuCommand command_id, TabGtk* tab);
+  virtual void StopHighlightTabsForCommand(
+      TabStripModel::ContextMenuCommand command_id, TabGtk* tab);
+  virtual void StopAllHighlighting();
+  virtual void MaybeStartDrag(TabGtk* tab, const gfx::Point& point);
+  virtual void ContinueDrag(GdkDragContext* context);
+  virtual bool EndDrag(bool canceled);
+  virtual bool HasAvailableDragActions() const;
+  virtual ui::ThemeProvider* GetThemeProvider();
+
+  // MessageLoop::Observer implementation:
+  virtual void WillProcessEvent(GdkEvent* event);
+  virtual void DidProcessEvent(GdkEvent* event);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Horizontal gap between mini-tabs and normal tabs.
+  static const int mini_to_non_mini_gap_;
+
+ private:
+  friend class BrowserWindowGtk;
+  friend class DraggedTabControllerGtk;
+  friend class InsertTabAnimation;
+  friend class MiniMoveAnimation;
+  friend class MiniTabAnimation;
+  friend class MoveTabAnimation;
+  friend class RemoveTabAnimation;
+  friend class ResizeLayoutAnimation;
+  friend class TabAnimation;
+
+  struct TabData {
+    TabGtk* tab;
+    gfx::Rect ideal_bounds;
+  };
+
+  // Used during a drop session of a url. Tracks the position of the drop as
+  // well as a window used to highlight where the drop occurs.
+  class DropInfo {
+   public:
+    DropInfo(int index, bool drop_before, bool point_down);
+    virtual ~DropInfo();
+
+    // TODO(jhawkins): Factor out this code into a TransparentContainer class.
+
+    // expose-event handler that redraws the drop indicator.
+    CHROMEGTK_CALLBACK_1(DropInfo, gboolean, OnExposeEvent, GdkEventExpose*);
+
+    // Sets the color map of the container window to allow the window to be
+    // transparent.
+    void SetContainerColorMap();
+
+    // Sets full transparency for the container window.  This is used if
+    // compositing is available for the screen.
+    void SetContainerTransparency();
+
+    // Sets the shape mask for the container window to emulate a transparent
+    // container window.  This is used if compositing is not available for the
+    // screen.
+    void SetContainerShapeMask();
+
+    // Creates the container widget.
+    void CreateContainer();
+
+    // Destroys the container widget.
+    void DestroyContainer();
+
+    // Index of the tab to drop on. If drop_before is true, the drop should
+    // occur between the tab at drop_index - 1 and drop_index.
+    // WARNING: if drop_before is true it is possible this will == tab_count,
+    // which indicates the drop should create a new tab at the end of the tabs.
+    int drop_index;
+    bool drop_before;
+
+    // Direction the arrow should point in. If true, the arrow is displayed
+    // above the tab and points down. If false, the arrow is displayed beneath
+    // the tab and points up.
+    bool point_down;
+
+    // Transparent container window used to render the drop indicator over the
+    // tabstrip and toolbar.
+    GtkWidget* container;
+
+    // The drop indicator image.
+    GdkPixbuf* drop_arrow;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(DropInfo);
+  };
+
+  // expose-event handler that redraws the tabstrip
+  CHROMEGTK_CALLBACK_1(TabStripGtk, gboolean, OnExpose, GdkEventExpose*);
+
+  // size-allocate handler that gets the new bounds of the tabstrip.
+  CHROMEGTK_CALLBACK_1(TabStripGtk, void, OnSizeAllocate, GtkAllocation*);
+
+  // drag-motion handler that is signaled when the user performs a drag in the
+  // tabstrip bounds.
+  CHROMEGTK_CALLBACK_4(TabStripGtk, gboolean, OnDragMotion, GdkDragContext*,
+                       gint, gint, guint);
+
+  // drag-drop handler that is notified when the user finishes a drag.
+  CHROMEGTK_CALLBACK_4(TabStripGtk, gboolean, OnDragDrop, GdkDragContext*,
+                       gint, gint, guint);
+
+  // drag-leave handler that is signaled when the mouse leaves the tabstrip
+  // during a drag.
+  CHROMEGTK_CALLBACK_2(TabStripGtk, gboolean, OnDragLeave, GdkDragContext*,
+                       guint);
+
+  // drag-data-received handler that receives the data associated with the drag.
+  CHROMEGTK_CALLBACK_6(TabStripGtk, gboolean, OnDragDataReceived,
+                       GdkDragContext*, gint, gint, GtkSelectionData*,
+                       guint, guint);
+
+  // Handles the clicked signal from the new tab button.
+  CHROMEGTK_CALLBACK_0(TabStripGtk, void, OnNewTabClicked);
+
+  // Sets the bounds of the tab and moves the tab widget to those bounds.
+  void SetTabBounds(TabGtk* tab, const gfx::Rect& bounds);
+
+  // Returns true if |rects| are all areas that match up with tab favicons.
+  // |rects| must be sorted from left to right.  |tabs_to_paint| are the tab
+  // positions that match the rects.
+  bool CanPaintOnlyFavIcons(const GdkRectangle* rects,
+                            int num_rects,
+                            std::vector<int>* tabs_to_paint);
+
+  // Paints the tab favicon areas for tabs in |tabs_to_paint|.
+  void PaintOnlyFavIcons(GdkEventExpose* event,
+                         const std::vector<int>& tabs_to_paint);
+
+  // Initializes the new tab button.
+  CustomDrawButton* MakeNewTabButton();
+
+  // Gets the number of Tabs in the collection.
+  int GetTabCount() const;
+
+  // Returns the number of mini-tabs.
+  int GetMiniTabCount() const;
+
+  // Retrieves the Tab at the specified index. Take care in using this, you may
+  // need to use GetTabAtAdjustForAnimation.
+  TabGtk* GetTabAt(int index) const;
+
+  // Returns the tab at the specified index. If a remove animation is on going
+  // and the index is >= the index of the tab being removed, the index is
+  // incremented. While a remove operation is on going the indices of the model
+  // do not line up with the indices of the view. This method adjusts the index
+  // accordingly.
+  //
+  // Use this instead of GetTabAt if the index comes from the model.
+  TabGtk* GetTabAtAdjustForAnimation(int index) const;
+
+  // Returns the exact (unrounded) current width of each tab.
+  void GetCurrentTabWidths(double* unselected_width,
+                           double* selected_width) const;
+
+  // Returns the exact (unrounded) desired width of each tab, based on the
+  // desired strip width and number of tabs.  If
+  // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in
+  // calculating the desired strip width; otherwise we use the current width.
+  // |mini_tab_count| gives the number of mini-tabs, and |tab_count| the
+  // number of mini and non-mini-tabs.
+  void GetDesiredTabWidths(int tab_count,
+                           int mini_tab_count,
+                           double* unselected_width,
+                           double* selected_width) const;
+
+  // Returns the horizontal offset before the tab at |tab_index|.
+  int GetTabHOffset(int tab_index);
+
+  // Returns the x-coordinate tabs start from.
+  int tab_start_x() const;
+
+  // Perform an animated resize-relayout of the TabStrip immediately. The
+  // value returned indicates whether a resize actually took place.
+  bool ResizeLayoutTabs();
+
+  // Returns whether or not the cursor is currently in the "tab strip zone"
+  // which is defined as the region above the TabStrip and a bit below it.
+  bool IsCursorInTabStripZone() const;
+
+  // Ensure that the message loop observer used for event spying is added and
+  // removed appropriately so we can tell when to resize layout the tab strip.
+  void AddMessageLoopObserver();
+  void RemoveMessageLoopObserver();
+
+  // Calculates the available width for tabs, assuming a Tab is to be closed.
+  int GetAvailableWidthForTabs(TabGtk* last_tab) const;
+
+  // Finds the index of the TabContents corresponding to |tab| in our
+  // associated TabStripModel, or -1 if there is none (e.g. the specified |tab|
+  // is being animated closed).
+  int GetIndexOfTab(const TabGtk* tab) const;
+
+  // Cleans up the tab from the TabStrip at the specified |index|.
+  void RemoveTabAt(int index);
+
+  // Called from the message loop observer when a mouse movement has occurred
+  // anywhere over our containing window.
+  void HandleGlobalMouseMoveEvent();
+
+  // Generates the ideal bounds of the TabStrip when all Tabs have finished
+  // animating to their desired position/bounds. This is used by the standard
+  // Layout method and other callers like the DraggedTabController that need
+  // stable representations of Tab positions.
+  void GenerateIdealBounds();
+
+  // Lays out the New Tab button, assuming the right edge of the last Tab on
+  // the TabStrip at |last_tab_right|.  |unselected_width| is the width of
+  // unselected tabs at the moment this function is called.  The value changes
+  // during animations, so we can't use current_unselected_width_.
+  void LayoutNewTabButton(double last_tab_right, double unselected_width);
+
+  // -- Link Drag & Drop ------------------------------------------------------
+
+  // Returns the bounds to render the drop at, in screen coordinates. Sets
+  // |is_beneath| to indicate whether the arrow is beneath the tab, or above
+  // it.
+  gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath);
+
+  // Updates the location of the drop based on the event.
+  void UpdateDropIndex(GdkDragContext* context, gint x, gint y);
+
+  // Sets the location of the drop, repainting as necessary.
+  void SetDropIndex(int index, bool drop_before);
+
+  // Determines whether the data is acceptable by the tabstrip and opens a new
+  // tab with the data as URL if it is.  Returns true if the drop was
+  // successful.
+  bool CompleteDrop(guchar* data, bool is_plain_text);
+
+  // Returns the image to use for indicating a drop on a tab. If is_down is
+  // true, this returns an arrow pointing down.
+  static GdkPixbuf* GetDropArrowImage(bool is_down);
+
+  // -- Animations -------------------------------------------------------------
+
+  // Stops the current animation.
+  void StopAnimation();
+
+  // A generic Layout method for various classes of TabStrip animations,
+  // including Insert, Remove and Resize Layout cases.
+  void AnimationLayout(double unselected_width);
+
+  // Starts various types of TabStrip animations.
+  void StartInsertTabAnimation(int index);
+  void StartRemoveTabAnimation(int index, TabContents* contents);
+  void StartMoveTabAnimation(int from_index, int to_index);
+  void StartMiniTabAnimation(int index);
+  void StartMiniMoveTabAnimation(int from_index,
+                                 int to_index,
+                                 const gfx::Rect& start_bounds);
+  void StartResizeLayoutAnimation();
+
+  // Notifies the TabStrip that the specified TabAnimation has completed.
+  // Optionally a full Layout will be performed, specified by |layout|.
+  void FinishAnimation(TabAnimation* animation, bool layout);
+
+  NotificationRegistrar registrar_;
+
+  // The Tabs we contain, and their last generated "good" bounds.
+  std::vector<TabData> tab_data_;
+
+  // The current widths of various types of tabs.  We save these so that, as
+  // users close tabs while we're holding them at the same size, we can lay out
+  // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving
+  // them all at their existing, rounded widths.
+  double current_unselected_width_;
+  double current_selected_width_;
+
+  // If this value is nonnegative, it is used in GetDesiredTabWidths() to
+  // calculate how much space in the tab strip to use for tabs.  Most of the
+  // time this will be -1, but while we're handling closing a tab via the mouse,
+  // we'll set this to the edge of the last tab before closing, so that if we
+  // are closing the last tab and need to resize immediately, we'll resize only
+  // back to this width, thus once again placing the last tab under the mouse
+  // cursor.
+  int available_width_for_tabs_;
+
+  // True if a resize layout animation should be run a short delay after the
+  // mouse exits the TabStrip.
+  bool needs_resize_layout_;
+
+  // The GtkFixed widget.
+  OwnedWidgetGtk tabstrip_;
+
+  // The bounds of the tabstrip.
+  gfx::Rect bounds_;
+
+  // The amount to offset tab backgrounds when we are using an autogenerated
+  // tab background image.
+  int tab_vertical_offset_;
+
+  // Our model.
+  TabStripModel* model_;
+
+  // The BrowserWindowGtk containing this tab strip.
+  BrowserWindowGtk* window_;
+
+  // Theme resources.
+  GtkThemeProvider* theme_provider_;
+
+  // The currently running animation.
+  scoped_ptr<TabAnimation> active_animation_;
+
+  // The New Tab button.
+  scoped_ptr<CustomDrawButton> newtab_button_;
+
+  // Valid for the lifetime of a drag over us.
+  scoped_ptr<DropInfo> drop_info_;
+
+  // The controller for a drag initiated from a Tab. Valid for the lifetime of
+  // the drag session.
+  scoped_ptr<DraggedTabControllerGtk> drag_controller_;
+
+  // A factory that is used to construct a delayed callback to the
+  // ResizeLayoutTabsNow method.
+  ScopedRunnableMethodFactory<TabStripGtk> resize_layout_factory_;
+
+  // True if the tabstrip has already been added as a MessageLoop observer.
+  bool added_as_message_loop_observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabStripGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TABS_TAB_STRIP_GTK_H_
diff --git a/chrome/browser/ui/gtk/tabstrip_origin_provider.h b/chrome/browser/ui/gtk/tabstrip_origin_provider.h
new file mode 100644
index 0000000..bba83c3
--- /dev/null
+++ b/chrome/browser/ui/gtk/tabstrip_origin_provider.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_TABSTRIP_ORIGIN_PROVIDER_H_
+#define CHROME_BROWSER_UI_GTK_TABSTRIP_ORIGIN_PROVIDER_H_
+#pragma once
+
+namespace gfx{
+class Point;
+}
+
+// Abstract interface that provides an offset of a widget. Many pieces of the
+// UI don't need the full BrowserWindowGtk, but just need information about
+// it's position relative to the tabstrip to draw correctly. This interface
+// exists to make it easier to test piece by piece.
+class TabstripOriginProvider {
+ public:
+  virtual ~TabstripOriginProvider() { }
+
+  // Return the origin of the tab strip in coordinates relative to where we
+  // start drawing the background theme image. This is the x coordinate of
+  // the origin of the GdkWindow of widget(), but the y coordinate of the origin
+  // of widget() itself.
+  // Used to help other widgets draw their background relative to the tabstrip.
+  // Should only be called after both the tabstrip and |widget| have been
+  // allocated.
+  virtual gfx::Point GetTabStripOriginForWidget(GtkWidget* widget) = 0;
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TABSTRIP_ORIGIN_PROVIDER_H_
diff --git a/chrome/browser/ui/gtk/task_manager_gtk.cc b/chrome/browser/ui/gtk/task_manager_gtk.cc
new file mode 100644
index 0000000..4617c78
--- /dev/null
+++ b/chrome/browser/ui/gtk/task_manager_gtk.cc
@@ -0,0 +1,988 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/task_manager_gtk.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include <algorithm>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/defaults.h"
+#include "chrome/browser/memory_purger.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
+#include "chrome/browser/ui/gtk/gtk_tree.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/chromium_strings.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/gtk_util.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "views/controls/menu/menu_2.h"
+#else
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#endif
+
+namespace {
+
+// The task manager window default size.
+const int kDefaultWidth = 460;
+const int kDefaultHeight = 270;
+
+// The resource id for the 'End process' button.
+const gint kTaskManagerResponseKill = 1;
+
+// The resource id for the 'Stats for nerds' link button.
+const gint kTaskManagerAboutMemoryLink = 2;
+
+// The resource id for the 'Purge Memory' button
+const gint kTaskManagerPurgeMemory = 3;
+
+enum TaskManagerColumn {
+  kTaskManagerIcon,
+  kTaskManagerPage,
+  kTaskManagerSharedMem,
+  kTaskManagerPrivateMem,
+  kTaskManagerCPU,
+  kTaskManagerNetwork,
+  kTaskManagerProcessID,
+  kTaskManagerJavaScriptMemory,
+  kTaskManagerWebCoreImageCache,
+  kTaskManagerWebCoreScriptsCache,
+  kTaskManagerWebCoreCssCache,
+  kTaskManagerSqliteMemoryUsed,
+  kTaskManagerGoatsTeleported,
+  // Columns below this point are not visible in the task manager.
+  kTaskManagerBackgroundColor,
+  kTaskManagerColumnCount,
+};
+
+const TaskManagerColumn kTaskManagerLastVisibleColumn =
+    kTaskManagerGoatsTeleported;
+
+static const GdkColor kHighlightColor = GDK_COLOR_RGB(0xff, 0xfa, 0xcd);
+
+TaskManagerColumn TaskManagerResourceIDToColumnID(int id) {
+  switch (id) {
+    case IDS_TASK_MANAGER_PAGE_COLUMN:
+      return kTaskManagerPage;
+    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
+      return kTaskManagerSharedMem;
+    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
+      return kTaskManagerPrivateMem;
+    case IDS_TASK_MANAGER_CPU_COLUMN:
+      return kTaskManagerCPU;
+    case IDS_TASK_MANAGER_NET_COLUMN:
+      return kTaskManagerNetwork;
+    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
+      return kTaskManagerProcessID;
+    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
+      return kTaskManagerJavaScriptMemory;
+    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
+      return kTaskManagerWebCoreImageCache;
+    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
+      return kTaskManagerWebCoreScriptsCache;
+    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
+      return kTaskManagerWebCoreCssCache;
+    case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
+      return kTaskManagerSqliteMemoryUsed;
+    case IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN:
+      return kTaskManagerGoatsTeleported;
+    default:
+      NOTREACHED();
+      return static_cast<TaskManagerColumn>(-1);
+  }
+}
+
+int TaskManagerColumnIDToResourceID(int id) {
+  switch (id) {
+    case kTaskManagerPage:
+      return IDS_TASK_MANAGER_PAGE_COLUMN;
+    case kTaskManagerSharedMem:
+      return IDS_TASK_MANAGER_SHARED_MEM_COLUMN;
+    case kTaskManagerPrivateMem:
+      return IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN;
+    case kTaskManagerCPU:
+      return IDS_TASK_MANAGER_CPU_COLUMN;
+    case kTaskManagerNetwork:
+      return IDS_TASK_MANAGER_NET_COLUMN;
+    case kTaskManagerProcessID:
+      return IDS_TASK_MANAGER_PROCESS_ID_COLUMN;
+    case kTaskManagerJavaScriptMemory:
+      return IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN;
+    case kTaskManagerWebCoreImageCache:
+      return IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN;
+    case kTaskManagerWebCoreScriptsCache:
+      return IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN;
+    case kTaskManagerWebCoreCssCache:
+      return IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN;
+    case kTaskManagerSqliteMemoryUsed:
+      return IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN;
+    case kTaskManagerGoatsTeleported:
+      return IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN;
+    default:
+      NOTREACHED();
+      return -1;
+  }
+}
+
+// Should be used for all gtk_tree_view functions that require a column index on
+// input.
+//
+// We need colid - 1 because the gtk_tree_view function is asking for the
+// column index, not the column id, and both kTaskManagerIcon and
+// kTaskManagerPage are in the same column index, so all column IDs are off by
+// one.
+int TreeViewColumnIndexFromID(TaskManagerColumn colid) {
+  return colid - 1;
+}
+
+// Shows or hides a treeview column.
+void TreeViewColumnSetVisible(GtkWidget* treeview, TaskManagerColumn colid,
+                              bool visible) {
+  GtkTreeViewColumn* column = gtk_tree_view_get_column(
+      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
+  gtk_tree_view_column_set_visible(column, visible);
+}
+
+bool TreeViewColumnIsVisible(GtkWidget* treeview, TaskManagerColumn colid) {
+  GtkTreeViewColumn* column = gtk_tree_view_get_column(
+      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
+  return gtk_tree_view_column_get_visible(column);
+}
+
+void TreeViewInsertColumnWithPixbuf(GtkWidget* treeview, int resid) {
+  int colid = TaskManagerResourceIDToColumnID(resid);
+  GtkTreeViewColumn* column = gtk_tree_view_column_new();
+  gtk_tree_view_column_set_title(column,
+                                 l10n_util::GetStringUTF8(resid).c_str());
+  GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
+  gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
+  gtk_tree_view_column_add_attribute(column, image_renderer,
+                                     "pixbuf", kTaskManagerIcon);
+  gtk_tree_view_column_add_attribute(column, image_renderer,
+                                     "cell-background-gdk",
+                                     kTaskManagerBackgroundColor);
+  GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
+  gtk_tree_view_column_add_attribute(column, text_renderer, "text", colid);
+  gtk_tree_view_column_add_attribute(column, text_renderer,
+                                     "cell-background-gdk",
+                                     kTaskManagerBackgroundColor);
+  gtk_tree_view_column_set_resizable(column, TRUE);
+  // This is temporary: we'll turn expanding off after getting the size.
+  gtk_tree_view_column_set_expand(column, TRUE);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+  gtk_tree_view_column_set_sort_column_id(column, colid);
+}
+
+// Inserts a column with a column id of |colid| and |name|.
+void TreeViewInsertColumnWithName(GtkWidget* treeview,
+                                  TaskManagerColumn colid, const char* name) {
+  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_insert_column_with_attributes(
+      GTK_TREE_VIEW(treeview), -1,
+      name, renderer,
+      "text", colid,
+      "cell-background-gdk", kTaskManagerBackgroundColor,
+      NULL);
+  GtkTreeViewColumn* column = gtk_tree_view_get_column(
+      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
+  gtk_tree_view_column_set_resizable(column, TRUE);
+  gtk_tree_view_column_set_sort_column_id(column, colid);
+}
+
+// Loads the column name from |resid| and uses the corresponding
+// TaskManagerColumn value as the column id to insert into the treeview.
+void TreeViewInsertColumn(GtkWidget* treeview, int resid) {
+  TreeViewInsertColumnWithName(treeview, TaskManagerResourceIDToColumnID(resid),
+                               l10n_util::GetStringUTF8(resid).c_str());
+}
+
+// Set the current width of the column without forcing a minimum width as
+// gtk_tree_view_column_set_fixed_width() would. This would basically be
+// gtk_tree_view_column_set_width() except that there is no such function.
+void TreeViewColumnSetWidth(GtkTreeViewColumn* column, gint width) {
+  column->width = width;
+  column->resized_width = width;
+  column->use_resized_width = TRUE;
+  // Needed for use_resized_width to be effective.
+  gtk_widget_queue_resize(column->tree_view);
+}
+
+}  // namespace
+
+class TaskManagerGtk::ContextMenuController
+    : public ui::SimpleMenuModel::Delegate {
+ public:
+  explicit ContextMenuController(TaskManagerGtk* task_manager)
+      : task_manager_(task_manager) {
+    menu_model_.reset(new ui::SimpleMenuModel(this));
+    for (int i = kTaskManagerPage; i <= kTaskManagerLastVisibleColumn; i++) {
+      menu_model_->AddCheckItemWithStringId(
+          i, TaskManagerColumnIDToResourceID(i));
+    }
+#if defined(TOOLKIT_VIEWS)
+    menu_.reset(new views::Menu2(menu_model_.get()));
+#else
+    menu_.reset(new MenuGtk(NULL, menu_model_.get()));
+#endif
+  }
+
+  virtual ~ContextMenuController() {}
+
+  void RunMenu(const gfx::Point& point, guint32 event_time) {
+#if defined(TOOLKIT_VIEWS)
+    menu_->RunContextMenuAt(point);
+#else
+    menu_->PopupAsContext(point, event_time);
+#endif
+  }
+
+  void Cancel() {
+    task_manager_ = NULL;
+#if defined(TOOLKIT_VIEWS)
+    menu_->CancelMenu();
+#else
+    menu_->Cancel();
+#endif
+  }
+
+ private:
+  // ui::SimpleMenuModel::Delegate implementation:
+  virtual bool IsCommandIdEnabled(int command_id) const {
+    if (!task_manager_)
+      return false;
+
+    return true;
+  }
+
+  virtual bool IsCommandIdChecked(int command_id) const {
+    if (!task_manager_)
+      return false;
+
+    TaskManagerColumn colid = static_cast<TaskManagerColumn>(command_id);
+    return TreeViewColumnIsVisible(task_manager_->treeview_, colid);
+  }
+
+  virtual bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator) {
+    return false;
+  }
+
+  virtual void ExecuteCommand(int command_id) {
+    if (!task_manager_)
+      return;
+
+    TaskManagerColumn colid = static_cast<TaskManagerColumn>(command_id);
+    bool visible = !TreeViewColumnIsVisible(task_manager_->treeview_, colid);
+    TreeViewColumnSetVisible(task_manager_->treeview_, colid, visible);
+  }
+
+  // The model and view for the right click context menu.
+  scoped_ptr<ui::SimpleMenuModel> menu_model_;
+#if defined(TOOLKIT_VIEWS)
+  scoped_ptr<views::Menu2> menu_;
+#else
+  scoped_ptr<MenuGtk> menu_;
+#endif
+
+  // The TaskManager the context menu was brought up for. Set to NULL when the
+  // menu is canceled.
+  TaskManagerGtk* task_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
+};
+
+TaskManagerGtk::TaskManagerGtk(bool highlight_background_resources)
+  : task_manager_(TaskManager::GetInstance()),
+    model_(TaskManager::GetInstance()->model()),
+    dialog_(NULL),
+    treeview_(NULL),
+    process_list_(NULL),
+    process_count_(0),
+    ignore_selection_changed_(false),
+    highlight_background_resources_(highlight_background_resources) {
+  Init();
+}
+
+// static
+TaskManagerGtk* TaskManagerGtk::instance_ = NULL;
+
+TaskManagerGtk::~TaskManagerGtk() {
+  model_->RemoveObserver(this);
+  task_manager_->OnWindowClosed();
+
+  gtk_accel_group_disconnect_key(accel_group_, GDK_w, GDK_CONTROL_MASK);
+  gtk_window_remove_accel_group(GTK_WINDOW(dialog_), accel_group_);
+  g_object_unref(accel_group_);
+  accel_group_ = NULL;
+
+  // Disconnect the destroy signal so it doesn't delete |this|.
+  g_signal_handler_disconnect(G_OBJECT(dialog_), destroy_handler_id_);
+  gtk_widget_destroy(dialog_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerGtk, TaskManagerModelObserver implementation:
+
+void TaskManagerGtk::OnModelChanged() {
+  // Nothing to do.
+}
+
+void TaskManagerGtk::OnItemsChanged(int start, int length) {
+  GtkTreeIter iter;
+  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
+                                NULL, start);
+
+  for (int i = start; i < start + length; i++) {
+    SetRowDataFromModel(i, &iter);
+    gtk_tree_model_iter_next(GTK_TREE_MODEL(process_list_), &iter);
+  }
+}
+
+void TaskManagerGtk::OnItemsAdded(int start, int length) {
+  AutoReset<bool> autoreset(&ignore_selection_changed_, true);
+
+  GtkTreeIter iter;
+  if (start == 0) {
+    gtk_list_store_prepend(process_list_, &iter);
+  } else if (start >= process_count_) {
+    gtk_list_store_append(process_list_, &iter);
+  } else {
+    GtkTreeIter sibling;
+    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &sibling,
+                                  NULL, start);
+    gtk_list_store_insert_before(process_list_, &iter, &sibling);
+  }
+
+  SetRowDataFromModel(start, &iter);
+
+  for (int i = start + 1; i < start + length; i++) {
+    gtk_list_store_insert_after(process_list_, &iter, &iter);
+    SetRowDataFromModel(i, &iter);
+  }
+
+  process_count_ += length;
+}
+
+void TaskManagerGtk::OnItemsRemoved(int start, int length) {
+  {
+    AutoReset<bool> autoreset(&ignore_selection_changed_, true);
+
+    GtkTreeIter iter;
+    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
+                                  NULL, start);
+
+    for (int i = 0; i < length; i++) {
+      // |iter| is moved to the next valid node when the current node is
+      // removed.
+      gtk_list_store_remove(process_list_, &iter);
+    }
+
+    process_count_ -= length;
+  }
+
+  // It is possible that we have removed the current selection; run selection
+  // changed to detect that case.
+  OnSelectionChanged(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerGtk, public:
+
+void TaskManagerGtk::Close() {
+  // Blow away our dialog - this will cause TaskManagerGtk to free itself.
+  gtk_widget_destroy(dialog_);
+  DCHECK(!instance_);
+}
+
+// static
+void TaskManagerGtk::Show(bool highlight_background_resources) {
+  if (instance_ &&
+      instance_->highlight_background_resources_ !=
+          highlight_background_resources) {
+    instance_->Close();
+    DCHECK(!instance_);
+  }
+
+  if (instance_) {
+    // If there's a Task manager window open already, just activate it.
+    gtk_util::PresentWindow(instance_->dialog_, 0);
+  } else {
+    instance_ = new TaskManagerGtk(highlight_background_resources);
+    instance_->model_->StartUpdating();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerGtk, private:
+
+void TaskManagerGtk::Init() {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_TITLE).c_str(),
+      // Task Manager window is shared between all browsers.
+      NULL,
+      GTK_DIALOG_NO_SEPARATOR,
+      NULL);
+
+  // Allow browser windows to go in front of the task manager dialog in
+  // metacity.
+  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
+
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kPurgeMemoryButton)) {
+    gtk_dialog_add_button(GTK_DIALOG(dialog_),
+        l10n_util::GetStringUTF8(IDS_TASK_MANAGER_PURGE_MEMORY).c_str(),
+        kTaskManagerPurgeMemory);
+  }
+
+  if (browser_defaults::kShowCancelButtonInTaskManager) {
+    gtk_dialog_add_button(GTK_DIALOG(dialog_),
+        l10n_util::GetStringUTF8(IDS_CLOSE).c_str(),
+        GTK_RESPONSE_DELETE_EVENT);
+  }
+
+  gtk_dialog_add_button(GTK_DIALOG(dialog_),
+      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_KILL).c_str(),
+      kTaskManagerResponseKill);
+
+  // The response button should not be sensitive when the dialog is first opened
+  // because the selection is initially empty.
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
+                                    kTaskManagerResponseKill, FALSE);
+
+  GtkWidget* link = gtk_chrome_link_button_new(
+      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK).c_str());
+  gtk_dialog_add_action_widget(GTK_DIALOG(dialog_), link,
+                               kTaskManagerAboutMemoryLink);
+
+  // Setting the link widget to secondary positions the button on the left side
+  // of the action area (vice versa for RTL layout).
+  gtk_button_box_set_child_secondary(
+      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area), link, TRUE);
+
+  ConnectAccelerators();
+
+  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+                      gtk_util::kContentAreaSpacing);
+
+  destroy_handler_id_ = g_signal_connect(dialog_, "destroy",
+                                         G_CALLBACK(OnDestroyThunk), this);
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+  // GTK does menu on mouse-up while views does menu on mouse-down,
+  // so connect to different handlers.
+#if defined(TOOLKIT_VIEWS)
+  g_signal_connect(dialog_, "button-release-event",
+                   G_CALLBACK(OnButtonEventThunk), this);
+#else
+  g_signal_connect(dialog_, "button-press-event",
+                   G_CALLBACK(OnButtonEventThunk), this);
+#endif
+  gtk_widget_add_events(dialog_,
+                        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+
+  // Wrap the treeview widget in a scrolled window in order to have a frame.
+  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+                                      GTK_SHADOW_ETCHED_IN);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), scrolled);
+
+  CreateTaskManagerTreeview();
+  gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(treeview_), TRUE);
+  g_signal_connect(treeview_, "row-activated",
+                   G_CALLBACK(OnRowActivatedThunk), this);
+
+  // |selection| is owned by |treeview_|.
+  GtkTreeSelection* selection = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(treeview_));
+  gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+  g_signal_connect(selection, "changed",
+                   G_CALLBACK(OnSelectionChangedThunk), this);
+
+  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
+
+  SetInitialDialogSize();
+  gtk_util::ShowDialog(dialog_);
+
+  // If the model already has resources, we need to add them before we start
+  // observing events.
+  if (model_->ResourceCount() > 0)
+    OnItemsAdded(0, model_->ResourceCount());
+
+  model_->AddObserver(this);
+}
+
+void TaskManagerGtk::SetInitialDialogSize() {
+  // Hook up to the realize event so we can size the page column to the
+  // size of the leftover space after packing the other columns.
+  g_signal_connect(treeview_, "realize",
+                   G_CALLBACK(OnTreeViewRealizeThunk), this);
+  // If we previously saved the dialog's bounds, use them.
+  if (g_browser_process->local_state()) {
+    const DictionaryValue* placement_pref =
+        g_browser_process->local_state()->GetDictionary(
+            prefs::kTaskManagerWindowPlacement);
+    int top = 0, left = 0, bottom = 1, right = 1;
+    if (placement_pref &&
+        placement_pref->GetInteger("top", &top) &&
+        placement_pref->GetInteger("left", &left) &&
+        placement_pref->GetInteger("bottom", &bottom) &&
+        placement_pref->GetInteger("right", &right)) {
+      gtk_window_resize(GTK_WINDOW(dialog_),
+                        std::max(1, right - left),
+                        std::max(1, bottom - top));
+      return;
+    }
+  }
+
+  // Otherwise, just set a default size (GTK will override this if it's not
+  // large enough to hold the window's contents).
+  gtk_window_set_default_size(
+      GTK_WINDOW(dialog_), kDefaultWidth, kDefaultHeight);
+}
+
+void TaskManagerGtk::ConnectAccelerators() {
+  accel_group_ = gtk_accel_group_new();
+  gtk_window_add_accel_group(GTK_WINDOW(dialog_), accel_group_);
+
+  gtk_accel_group_connect(accel_group_,
+                          GDK_w, GDK_CONTROL_MASK, GtkAccelFlags(0),
+                          g_cclosure_new(G_CALLBACK(OnGtkAcceleratorThunk),
+                                         this, NULL));
+}
+
+void TaskManagerGtk::CreateTaskManagerTreeview() {
+  process_list_ = gtk_list_store_new(kTaskManagerColumnCount,
+      GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+      G_TYPE_STRING, GDK_TYPE_COLOR);
+
+  // Support sorting on all columns.
+  process_list_sort_ = gtk_tree_model_sort_new_with_model(
+      GTK_TREE_MODEL(process_list_));
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerPage,
+                                  ComparePage, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerSharedMem,
+                                  CompareSharedMemory, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerPrivateMem,
+                                  ComparePrivateMemory, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerJavaScriptMemory,
+                                  CompareV8Memory, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerCPU,
+                                  CompareCPU, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerNetwork,
+                                  CompareNetwork, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerProcessID,
+                                  CompareProcessID, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerWebCoreImageCache,
+                                  CompareWebCoreImageCache, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerWebCoreScriptsCache,
+                                  CompareWebCoreScriptsCache, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerWebCoreCssCache,
+                                  CompareWebCoreCssCache, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerSqliteMemoryUsed,
+                                  CompareSqliteMemoryUsed, this, NULL);
+  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
+                                  kTaskManagerGoatsTeleported,
+                                  CompareGoatsTeleported, this, NULL);
+  treeview_ = gtk_tree_view_new_with_model(process_list_sort_);
+
+  // Insert all the columns.
+  TreeViewInsertColumnWithPixbuf(treeview_, IDS_TASK_MANAGER_PAGE_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_CPU_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_NET_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
+  TreeViewInsertColumn(treeview_,
+                       IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
+  TreeViewInsertColumn(treeview_,
+                       IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
+  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
+
+  // Hide some columns by default.
+  TreeViewColumnSetVisible(treeview_, kTaskManagerSharedMem, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerProcessID, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerJavaScriptMemory, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreImageCache, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreScriptsCache, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreCssCache, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerSqliteMemoryUsed, false);
+  TreeViewColumnSetVisible(treeview_, kTaskManagerGoatsTeleported, false);
+
+  g_object_unref(process_list_);
+  g_object_unref(process_list_sort_);
+}
+
+bool IsSharedByGroup(int col_id) {
+  switch (col_id) {
+    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
+    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
+    case IDS_TASK_MANAGER_CPU_COLUMN:
+    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
+    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
+    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
+    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
+    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
+      return true;
+    default:
+      return false;
+  }
+}
+
+std::string TaskManagerGtk::GetModelText(int row, int col_id) {
+  if (IsSharedByGroup(col_id) && !model_->IsResourceFirstInGroup(row))
+    return std::string();
+
+  switch (col_id) {
+    case IDS_TASK_MANAGER_PAGE_COLUMN:  // Process
+      return UTF16ToUTF8(model_->GetResourceTitle(row));
+
+    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:  // Memory
+      return UTF16ToUTF8(model_->GetResourcePrivateMemory(row));
+
+    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:  // Memory
+      return UTF16ToUTF8(model_->GetResourceSharedMemory(row));
+
+    case IDS_TASK_MANAGER_CPU_COLUMN:  // CPU
+      return UTF16ToUTF8(model_->GetResourceCPUUsage(row));
+
+    case IDS_TASK_MANAGER_NET_COLUMN:  // Net
+      return UTF16ToUTF8(model_->GetResourceNetworkUsage(row));
+
+    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:  // Process ID
+      return UTF16ToUTF8(model_->GetResourceProcessId(row));
+
+    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
+      return UTF16ToUTF8(model_->GetResourceV8MemoryAllocatedSize(row));
+
+    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
+      return UTF16ToUTF8(model_->GetResourceWebCoreImageCacheSize(row));
+
+    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
+      return UTF16ToUTF8(model_->GetResourceWebCoreScriptsCacheSize(row));
+
+    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
+      return UTF16ToUTF8(model_->GetResourceWebCoreCSSCacheSize(row));
+
+    case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
+      return UTF16ToUTF8(model_->GetResourceSqliteMemoryUsed(row));
+
+    case IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN:  // Goats Teleported!
+      return UTF16ToUTF8(model_->GetResourceGoatsTeleported(row));
+
+    default:
+      NOTREACHED();
+      return std::string();
+  }
+}
+
+GdkPixbuf* TaskManagerGtk::GetModelIcon(int row) {
+  SkBitmap icon = model_->GetResourceIcon(row);
+  if (icon.pixelRef() ==
+      ResourceBundle::GetSharedInstance().GetBitmapNamed(
+          IDR_DEFAULT_FAVICON)->pixelRef()) {
+    return static_cast<GdkPixbuf*>(g_object_ref(
+        GtkThemeProvider::GetDefaultFavicon(true)));
+  }
+
+  return gfx::GdkPixbufFromSkBitmap(&icon);
+}
+
+void TaskManagerGtk::SetRowDataFromModel(int row, GtkTreeIter* iter) {
+  GdkPixbuf* icon = GetModelIcon(row);
+  std::string page = GetModelText(row, IDS_TASK_MANAGER_PAGE_COLUMN);
+  std::string shared_mem = GetModelText(
+      row, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
+  std::string priv_mem = GetModelText(row, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
+  std::string cpu = GetModelText(row, IDS_TASK_MANAGER_CPU_COLUMN);
+  std::string net = GetModelText(row, IDS_TASK_MANAGER_NET_COLUMN);
+  std::string procid = GetModelText(row, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
+
+  // Querying the renderer metrics is slow as it has to do IPC, so only do it
+  // when the columns are visible.
+  std::string javascript_memory;
+  if (TreeViewColumnIsVisible(treeview_, kTaskManagerJavaScriptMemory))
+    javascript_memory = GetModelText(
+        row, IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
+  std::string wk_img_cache;
+  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreImageCache))
+    wk_img_cache = GetModelText(
+        row, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
+  std::string wk_scripts_cache;
+  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreScriptsCache))
+    wk_scripts_cache = GetModelText(
+        row, IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
+  std::string wk_css_cache;
+  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreCssCache))
+    wk_css_cache = GetModelText(
+        row, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
+  std::string sqlite_memory;
+  if (TreeViewColumnIsVisible(treeview_, kTaskManagerSqliteMemoryUsed))
+    sqlite_memory = GetModelText(
+        row, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
+
+  std::string goats = GetModelText(
+      row, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
+
+  bool is_background = model_->IsBackgroundResource(row) &&
+      highlight_background_resources_;
+  gtk_list_store_set(process_list_, iter,
+                     kTaskManagerIcon, icon,
+                     kTaskManagerPage, page.c_str(),
+                     kTaskManagerSharedMem, shared_mem.c_str(),
+                     kTaskManagerPrivateMem, priv_mem.c_str(),
+                     kTaskManagerCPU, cpu.c_str(),
+                     kTaskManagerNetwork, net.c_str(),
+                     kTaskManagerProcessID, procid.c_str(),
+                     kTaskManagerJavaScriptMemory, javascript_memory.c_str(),
+                     kTaskManagerWebCoreImageCache, wk_img_cache.c_str(),
+                     kTaskManagerWebCoreScriptsCache, wk_scripts_cache.c_str(),
+                     kTaskManagerWebCoreCssCache, wk_css_cache.c_str(),
+                     kTaskManagerSqliteMemoryUsed, sqlite_memory.c_str(),
+                     kTaskManagerGoatsTeleported, goats.c_str(),
+                     kTaskManagerBackgroundColor,
+                     is_background ? &kHighlightColor : NULL,
+                     -1);
+  g_object_unref(icon);
+}
+
+void TaskManagerGtk::KillSelectedProcesses() {
+  GtkTreeSelection* selection = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(treeview_));
+
+  GtkTreeModel* model;
+  GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
+  for (GList* item = paths; item; item = item->next) {
+    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
+        GTK_TREE_MODEL_SORT(process_list_sort_),
+        reinterpret_cast<GtkTreePath*>(item->data));
+    int row = gtk_tree::GetRowNumForPath(path);
+    gtk_tree_path_free(path);
+    task_manager_->KillProcess(row);
+  }
+  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
+  g_list_free(paths);
+}
+
+void TaskManagerGtk::ShowContextMenu(const gfx::Point& point,
+                                     guint32 event_time) {
+  if (!menu_controller_.get())
+    menu_controller_.reset(new ContextMenuController(this));
+
+  menu_controller_->RunMenu(point, event_time);
+}
+
+void TaskManagerGtk::OnLinkActivated() {
+  task_manager_->OpenAboutMemory();
+}
+
+gint TaskManagerGtk::CompareImpl(GtkTreeModel* model, GtkTreeIter* a,
+                                 GtkTreeIter* b, int id) {
+  int row1 = gtk_tree::GetRowNumForIter(model, b);
+  int row2 = gtk_tree::GetRowNumForIter(model, a);
+
+  // When sorting by non-grouped attributes (e.g., Network), just do a normal
+  // sort.
+  if (!IsSharedByGroup(id))
+    return model_->CompareValues(row1, row2, id);
+
+  // Otherwise, make sure grouped resources are shown together.
+  std::pair<int, int> group_range1 = model_->GetGroupRangeForResource(row1);
+  std::pair<int, int> group_range2 = model_->GetGroupRangeForResource(row2);
+
+  if (group_range1 == group_range2) {
+    // Sort within groups.
+    // We want the first-in-group row at the top, whether we are sorting up or
+    // down.
+    GtkSortType sort_type;
+    gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(process_list_sort_),
+                                         NULL, &sort_type);
+    if (row1 == group_range1.first)
+      return sort_type == GTK_SORT_ASCENDING ? -1 : 1;
+    if (row2 == group_range2.first)
+      return sort_type == GTK_SORT_ASCENDING ? 1 : -1;
+
+    return model_->CompareValues(row1, row2, id);
+  } else {
+    // Sort between groups.
+    // Compare by the first-in-group rows so that the groups will stay together.
+    return model_->CompareValues(group_range1.first, group_range2.first, id);
+  }
+}
+
+void TaskManagerGtk::OnDestroy(GtkWidget* dialog) {
+  instance_ = NULL;
+  delete this;
+}
+
+void TaskManagerGtk::OnResponse(GtkWidget* dialog, gint response_id) {
+  if (response_id == GTK_RESPONSE_DELETE_EVENT) {
+    // Store the dialog's size so we can restore it the next time it's opened.
+    if (g_browser_process->local_state()) {
+      gfx::Rect dialog_bounds = gtk_util::GetDialogBounds(GTK_WIDGET(dialog));
+
+      DictionaryValue* placement_pref =
+          g_browser_process->local_state()->GetMutableDictionary(
+              prefs::kTaskManagerWindowPlacement);
+      // Note that we store left/top for consistency with Windows, but that we
+      // *don't* restore them.
+      placement_pref->SetInteger("left", dialog_bounds.x());
+      placement_pref->SetInteger("top", dialog_bounds.y());
+      placement_pref->SetInteger("right", dialog_bounds.right());
+      placement_pref->SetInteger("bottom", dialog_bounds.bottom());
+      placement_pref->SetBoolean("maximized", false);
+    }
+
+    instance_ = NULL;
+    delete this;
+  } else if (response_id == kTaskManagerResponseKill) {
+    KillSelectedProcesses();
+  } else if (response_id == kTaskManagerAboutMemoryLink) {
+    OnLinkActivated();
+  } else if (response_id == kTaskManagerPurgeMemory) {
+    MemoryPurger::PurgeAll();
+  }
+}
+
+void TaskManagerGtk::OnTreeViewRealize(GtkTreeView* treeview) {
+  // Four columns show by default: the page column, the memory column, the
+  // CPU column, and the network column. Initially we set the page column to
+  // take all the extra space, with the other columns being sized to fit the
+  // column names. Here we turn off the expand property of the first column
+  // (to make the table behave sanely when the user resizes columns) and set
+  // the effective sizes of all four default columns to the automatically
+  // chosen size before any rows are added. This causes them to stay at that
+  // size even if the data would overflow, preventing a horizontal scroll
+  // bar from appearing due to the row data.
+  const TaskManagerColumn dfl_columns[] = {kTaskManagerNetwork, kTaskManagerCPU,
+                                           kTaskManagerPrivateMem};
+  GtkTreeViewColumn* column = NULL;
+  gint width;
+  for (size_t i = 0; i < arraysize(dfl_columns); ++i) {
+    column = gtk_tree_view_get_column(treeview,
+        TreeViewColumnIndexFromID(dfl_columns[i]));
+    width = gtk_tree_view_column_get_width(column);
+    TreeViewColumnSetWidth(column, width);
+  }
+  // Do the page column separately since it's a little different.
+  column = gtk_tree_view_get_column(treeview,
+      TreeViewColumnIndexFromID(kTaskManagerPage));
+  width = gtk_tree_view_column_get_width(column);
+  // Turn expanding back off to make resizing columns behave sanely.
+  gtk_tree_view_column_set_expand(column, FALSE);
+  TreeViewColumnSetWidth(column, width);
+}
+
+void TaskManagerGtk::OnSelectionChanged(GtkTreeSelection* selection) {
+  if (ignore_selection_changed_)
+    return;
+  AutoReset<bool> autoreset(&ignore_selection_changed_, true);
+
+  // The set of groups that should be selected.
+  std::set<std::pair<int, int> > ranges;
+  bool selection_contains_browser_process = false;
+
+  GtkTreeModel* model;
+  GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
+  for (GList* item = paths; item; item = item->next) {
+    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
+        GTK_TREE_MODEL_SORT(process_list_sort_),
+        reinterpret_cast<GtkTreePath*>(item->data));
+    int row = gtk_tree::GetRowNumForPath(path);
+    gtk_tree_path_free(path);
+    if (task_manager_->IsBrowserProcess(row))
+      selection_contains_browser_process = true;
+    ranges.insert(model_->GetGroupRangeForResource(row));
+  }
+  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
+  g_list_free(paths);
+
+  for (std::set<std::pair<int, int> >::iterator iter = ranges.begin();
+       iter != ranges.end(); ++iter) {
+    for (int i = 0; i < iter->second; ++i) {
+      GtkTreePath* child_path = gtk_tree_path_new_from_indices(iter->first + i,
+                                                               -1);
+      GtkTreePath* sort_path = gtk_tree_model_sort_convert_child_path_to_path(
+        GTK_TREE_MODEL_SORT(process_list_sort_), child_path);
+      gtk_tree_selection_select_path(selection, sort_path);
+      gtk_tree_path_free(child_path);
+      gtk_tree_path_free(sort_path);
+    }
+  }
+
+  bool sensitive = (paths != NULL) && !selection_contains_browser_process;
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
+                                    kTaskManagerResponseKill, sensitive);
+}
+
+void TaskManagerGtk::OnRowActivated(GtkWidget* widget,
+                                    GtkTreePath* path,
+                                    GtkTreeViewColumn* column) {
+  GtkTreePath* child_path = gtk_tree_model_sort_convert_path_to_child_path(
+      GTK_TREE_MODEL_SORT(process_list_sort_), path);
+  int row = gtk_tree::GetRowNumForPath(child_path);
+  gtk_tree_path_free(child_path);
+  task_manager_->ActivateProcess(row);
+}
+
+gboolean TaskManagerGtk::OnButtonEvent(GtkWidget* widget,
+                                       GdkEventButton* event) {
+  // GTK does menu on mouse-up while views does menu on mouse-down,
+  // so this function does different handlers.
+  if (event->button == 3) {
+    ShowContextMenu(gfx::Point(event->x_root, event->y_root),
+                    event->time);
+  }
+
+  return FALSE;
+}
+
+gboolean TaskManagerGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
+                                          GObject* acceleratable,
+                                          guint keyval,
+                                          GdkModifierType modifier) {
+  if (keyval == GDK_w && modifier == GDK_CONTROL_MASK) {
+    // The GTK_RESPONSE_DELETE_EVENT response must be sent before the widget
+    // is destroyed.  The deleted object will receive gtk signals otherwise.
+    gtk_dialog_response(GTK_DIALOG(dialog_), GTK_RESPONSE_DELETE_EVENT);
+  }
+
+  return TRUE;
+}
diff --git a/chrome/browser/ui/gtk/task_manager_gtk.h b/chrome/browser/ui/gtk/task_manager_gtk.h
new file mode 100644
index 0000000..fc5c021
--- /dev/null
+++ b/chrome/browser/ui/gtk/task_manager_gtk.h
@@ -0,0 +1,237 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TASK_MANAGER_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TASK_MANAGER_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/task_manager/task_manager.h"
+#include "grit/generated_resources.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+namespace gfx {
+class Point;
+}
+
+class TaskManagerGtk : public TaskManagerModelObserver {
+ public:
+  explicit TaskManagerGtk(bool highlight_background_resources);
+  virtual ~TaskManagerGtk();
+
+  // TaskManagerModelObserver
+  virtual void OnModelChanged();
+  virtual void OnItemsChanged(int start, int length);
+  virtual void OnItemsAdded(int start, int length);
+  virtual void OnItemsRemoved(int start, int length);
+
+  // Closes the task manager window.
+  void Close();
+
+  // Creates the task manager if it doesn't exist; otherwise, it activates the
+  // existing task manager window. If |highlight_background_resources| is true,
+  // background resources are rendered with a yellow highlight (for the
+  // "View Background Pages" menu item).
+  static void Show(bool highlight_background_resources);
+
+ private:
+  class ContextMenuController;
+  friend class ContextMenuController;
+
+  // Initializes the task manager dialog.
+  void Init();
+
+  // Set |dialog_|'s initial size, using its previous size if that was saved.
+  void SetInitialDialogSize();
+
+  // Connects the ctrl-w accelerator to the dialog.
+  void ConnectAccelerators();
+
+  // Sets up the treeview widget.
+  void CreateTaskManagerTreeview();
+
+  // Returns the model data for a given |row| and |col_id|.
+  std::string GetModelText(int row, int col_id);
+
+  // Retrieves the resource icon from the model for |row|.
+  GdkPixbuf* GetModelIcon(int row);
+
+  // Sets the treeview row data.  |row| is an index into the model and |iter|
+  // is the current position in the treeview.
+  void SetRowDataFromModel(int row, GtkTreeIter* iter);
+
+  // Queries the treeview for the selected rows, and kills those processes.
+  void KillSelectedProcesses();
+
+  // Opens the context menu used to select the task manager columns.
+  void ShowContextMenu(const gfx::Point& point, guint32 event_time);
+
+  // Opens about:memory in a new foreground tab.
+  void OnLinkActivated();
+
+  // Compare implementation used for sorting columns.
+  gint CompareImpl(GtkTreeModel* tree_model, GtkTreeIter* a,
+                   GtkTreeIter* b, int id);
+
+  // Response signal handler that notifies us of dialog destruction.
+  CHROMEGTK_CALLBACK_0(TaskManagerGtk, void, OnDestroy);
+
+  // Response signal handler that notifies us of dialog responses.
+  CHROMEGTK_CALLBACK_1(TaskManagerGtk, void, OnResponse, gint);
+
+  // Realize signal handler to set the page column's initial size.
+  CHROMEG_CALLBACK_0(TaskManagerGtk, void, OnTreeViewRealize, GtkTreeView*);
+
+  // Changed signal handler that is sent when the treeview selection changes.
+  CHROMEG_CALLBACK_0(TaskManagerGtk, void, OnSelectionChanged,
+                     GtkTreeSelection*);
+
+  // row-activated handler that foregrounds a process on activation (e.g.,
+  // double-click).
+  CHROMEGTK_CALLBACK_2(TaskManagerGtk, void, OnRowActivated,
+                       GtkTreePath*, GtkTreeViewColumn*);
+
+  // button-event handler that opens the right-click context menu.
+  // Note: GTK does menu on mouse-up while views does menu on mouse-down;
+  // this handler is used for both.
+  CHROMEGTK_CALLBACK_1(TaskManagerGtk, gboolean, OnButtonEvent,
+                       GdkEventButton*);
+
+  // Handles an accelerator being pressed.
+  CHROMEG_CALLBACK_3(TaskManagerGtk, gboolean, OnGtkAccelerator,
+                     GtkAccelGroup*, GObject*, guint, GdkModifierType);
+
+  // Page sorting callback.
+  static gint ComparePage(GtkTreeModel* model, GtkTreeIter* a,
+                          GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_PAGE_COLUMN);
+  }
+
+  // Shared memory sorting callback.
+  static gint CompareSharedMemory(GtkTreeModel* model, GtkTreeIter* a,
+                                  GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
+  }
+
+  // Private memory sorting callback.
+  static gint ComparePrivateMemory(GtkTreeModel* model, GtkTreeIter* a,
+                                   GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
+  }
+
+  // Javascript memory sorting callback.
+  static gint CompareV8Memory(GtkTreeModel* model, GtkTreeIter* a,
+                              GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b,
+                    IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
+  }
+
+  // CPU sorting callback.
+  static gint CompareCPU(GtkTreeModel* model, GtkTreeIter* a,
+                         GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_CPU_COLUMN);
+  }
+
+  // Network sorting callback.
+  static gint CompareNetwork(GtkTreeModel* model, GtkTreeIter* a,
+                             GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_NET_COLUMN);
+  }
+
+  // Process ID sorting callback.
+  static gint CompareProcessID(GtkTreeModel* model, GtkTreeIter* a,
+                               GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
+  }
+
+  // WebCore Image Cache sorting callback.
+  static gint CompareWebCoreImageCache(GtkTreeModel* model, GtkTreeIter* a,
+                                       GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
+  }
+
+  // WebCore Scripts Cache sorting callback.
+  static gint CompareWebCoreScriptsCache(GtkTreeModel* model, GtkTreeIter* a,
+                                         GtkTreeIter* b,
+                                         gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
+  }
+
+  // WebCore CSS Cache sorting callback.
+  static gint CompareWebCoreCssCache(GtkTreeModel* model, GtkTreeIter* a,
+                                     GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
+  }
+
+  // Sqlite memory sorting callback.
+  static gint CompareSqliteMemoryUsed(GtkTreeModel* model, GtkTreeIter* a,
+                                      GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
+  }
+
+  // Goats Teleported sorting callback.
+  static gint CompareGoatsTeleported(GtkTreeModel* model, GtkTreeIter* a,
+                                     GtkTreeIter* b, gpointer task_manager) {
+    return reinterpret_cast<TaskManagerGtk*>(task_manager)->
+        CompareImpl(model, a, b, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
+  }
+
+  // The task manager.
+  TaskManager* task_manager_;
+
+  // Our model.
+  TaskManagerModel* model_;
+
+  // The task manager dialog window.
+  GtkWidget* dialog_;
+
+  // The treeview that contains the process list.
+  GtkWidget* treeview_;
+
+  // The list of processes.
+  GtkListStore* process_list_;
+  GtkTreeModel* process_list_sort_;
+
+  // The number of processes in |process_list_|.
+  int process_count_;
+
+  // The id of the |dialog_| destroy signal handler.
+  gulong destroy_handler_id_;
+
+  // The context menu controller.
+  scoped_ptr<ContextMenuController> menu_controller_;
+
+  GtkAccelGroup* accel_group_;
+
+  // An open task manager window. There can only be one open at a time. This
+  // is reset to NULL when the window is closed.
+  static TaskManagerGtk* instance_;
+
+  // We edit the selection in the OnSelectionChanged handler, and we use this
+  // variable to prevent ourselves from handling further changes that we
+  // ourselves caused.
+  bool ignore_selection_changed_;
+
+  // If true, background resources are rendered with a yellow highlight.
+  bool highlight_background_resources_;
+
+  DISALLOW_COPY_AND_ASSIGN(TaskManagerGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TASK_MANAGER_GTK_H_
diff --git a/chrome/browser/ui/gtk/theme_install_bubble_view_gtk.cc b/chrome/browser/ui/gtk/theme_install_bubble_view_gtk.cc
new file mode 100644
index 0000000..016f3e3
--- /dev/null
+++ b/chrome/browser/ui/gtk/theme_install_bubble_view_gtk.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/theme_install_bubble_view_gtk.h"
+
+#include <math.h>
+
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/rounded_window.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// Roundedness of bubble.
+static const int kBubbleCornerRadius = 4;
+
+// Padding between border of bubble and text.
+static const int kTextPadding = 8;
+
+// The bubble is partially transparent.
+static const double kBubbleOpacity = static_cast<double>(0xcc) / 0xff;
+
+ThemeInstallBubbleViewGtk* ThemeInstallBubbleViewGtk::instance_ = NULL;
+
+// ThemeInstallBubbleViewGtk, public -------------------------------------------
+
+// static
+void ThemeInstallBubbleViewGtk::Show(GtkWindow* parent) {
+  if (instance_)
+    instance_->increment_num_loading();
+  else
+    instance_ = new ThemeInstallBubbleViewGtk(GTK_WIDGET(parent));
+}
+
+void ThemeInstallBubbleViewGtk::Observe(NotificationType type,
+                                        const NotificationSource& source,
+                                        const NotificationDetails& details) {
+  if (--num_loads_extant_ == 0)
+    delete this;
+}
+
+// ThemeInstallBubbleViewGtk, private ------------------------------------------
+
+ThemeInstallBubbleViewGtk::ThemeInstallBubbleViewGtk(GtkWidget* parent)
+    : widget_(NULL),
+      parent_(parent),
+      num_loads_extant_(1) {
+  InitWidgets();
+
+  // Close when theme has been installed.
+  registrar_.Add(
+      this,
+      NotificationType::BROWSER_THEME_CHANGED,
+      NotificationService::AllSources());
+
+  // Close when we are installing an extension, not a theme.
+  registrar_.Add(
+      this,
+      NotificationType::NO_THEME_DETECTED,
+      NotificationService::AllSources());
+  registrar_.Add(
+      this,
+      NotificationType::EXTENSION_INSTALLED,
+      NotificationService::AllSources());
+  registrar_.Add(
+      this,
+      NotificationType::EXTENSION_INSTALL_ERROR,
+      NotificationService::AllSources());
+
+  // Don't let the bubble overlap the confirm dialog.
+  registrar_.Add(
+      this,
+      NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
+      NotificationService::AllSources());
+}
+
+ThemeInstallBubbleViewGtk::~ThemeInstallBubbleViewGtk() {
+  gtk_widget_destroy(widget_);
+  instance_ = NULL;
+}
+
+void ThemeInstallBubbleViewGtk::InitWidgets() {
+  // Widgematically, the bubble is just a label in a popup window.
+  widget_ = gtk_window_new(GTK_WINDOW_POPUP);
+  gtk_container_set_border_width(GTK_CONTAINER(widget_), kTextPadding);
+  GtkWidget* label = gtk_label_new(NULL);
+
+  gchar* markup = g_markup_printf_escaped(
+      "<span size='xx-large'>%s</span>",
+      l10n_util::GetStringUTF8(IDS_THEME_LOADING_TITLE).c_str());
+  gtk_label_set_markup(GTK_LABEL(label), markup);
+  g_free(markup);
+
+  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkWhite);
+  gtk_container_add(GTK_CONTAINER(widget_), label);
+
+  // We need to show the label so we'll know the widget's actual size when we
+  // call MoveWindow().
+  gtk_widget_show_all(label);
+
+  bool composited = false;
+  if (gtk_util::IsScreenComposited()) {
+    composited = true;
+    GdkScreen* screen = gtk_widget_get_screen(widget_);
+    GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
+
+    if (colormap)
+      gtk_widget_set_colormap(widget_, colormap);
+    else
+      composited = false;
+  }
+
+  if (composited) {
+    gtk_widget_set_app_paintable(widget_, TRUE);
+    g_signal_connect(widget_, "expose-event",
+                     G_CALLBACK(OnExposeThunk), this);
+    gtk_widget_realize(widget_);
+  } else {
+    gtk_widget_modify_bg(widget_, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+    GdkColor color;
+    gtk_util::ActAsRoundedWindow(widget_, color, kBubbleCornerRadius,
+                                 gtk_util::ROUNDED_ALL, gtk_util::BORDER_NONE);
+  }
+
+  MoveWindow();
+
+  g_signal_connect(widget_, "unmap-event",
+                   G_CALLBACK(OnUnmapEventThunk), this);
+
+  gtk_widget_show_all(widget_);
+}
+
+void ThemeInstallBubbleViewGtk::MoveWindow() {
+  GtkRequisition req;
+  gtk_widget_size_request(widget_, &req);
+
+  gint parent_x = 0, parent_y = 0;
+  gdk_window_get_position(parent_->window, &parent_x, &parent_y);
+  gint parent_width = parent_->allocation.width;
+  gint parent_height = parent_->allocation.height;
+
+  gint x = parent_x + parent_width / 2 - req.width / 2;
+  gint y = parent_y + parent_height / 2 - req.height / 2;
+
+  gtk_window_move(GTK_WINDOW(widget_), x, y);
+}
+
+gboolean ThemeInstallBubbleViewGtk::OnUnmapEvent(GtkWidget* widget) {
+  delete this;
+  return FALSE;
+}
+
+gboolean ThemeInstallBubbleViewGtk::OnExpose(GtkWidget* widget,
+                                             GdkEventExpose* event) {
+  cairo_t* cr = gdk_cairo_create(event->window);
+  gdk_cairo_rectangle(cr, &event->area);
+  cairo_clip(cr);
+
+  cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+  cairo_paint(cr);
+  cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+
+  // |inner_rect| has its corners at the centerpoints of the corner arcs.
+  gfx::Rect inner_rect(widget_->allocation);
+  int inset = kBubbleCornerRadius;
+  inner_rect.Inset(inset, inset);
+
+  // The positive y axis is down, so M_PI_2 is down.
+  cairo_arc(cr, inner_rect.x(), inner_rect.y(), inset,
+            M_PI, 3 * M_PI_2);
+  cairo_arc(cr, inner_rect.right(), inner_rect.y(), inset,
+            3 * M_PI_2, 0);
+  cairo_arc(cr, inner_rect.right(), inner_rect.bottom(), inset,
+            0, M_PI_2);
+  cairo_arc(cr, inner_rect.x(), inner_rect.bottom(), inset,
+            M_PI_2, M_PI);
+
+  cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, kBubbleOpacity);
+  cairo_fill(cr);
+  cairo_destroy(cr);
+
+  return FALSE;
+}
diff --git a/chrome/browser/ui/gtk/theme_install_bubble_view_gtk.h b/chrome/browser/ui/gtk/theme_install_bubble_view_gtk.h
new file mode 100644
index 0000000..7bed460
--- /dev/null
+++ b/chrome/browser/ui/gtk/theme_install_bubble_view_gtk.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_THEME_INSTALL_BUBBLE_VIEW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_THEME_INSTALL_BUBBLE_VIEW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class ThemeInstallBubbleViewGtk : public NotificationObserver {
+ public:
+  static void Show(GtkWindow* parent);
+
+  // NotificationObserver implementation.
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+ private:
+  explicit ThemeInstallBubbleViewGtk(GtkWidget* parent);
+
+  virtual ~ThemeInstallBubbleViewGtk();
+
+  void increment_num_loading() { num_loads_extant_++; }
+
+  // Create the widget hierarchy.
+  void InitWidgets();
+
+  // Reposition |widget_| to be centered over |parent_|.
+  void MoveWindow();
+
+  // Our parent is going down; self destruct.
+  CHROMEGTK_CALLBACK_0(ThemeInstallBubbleViewGtk, gboolean, OnUnmapEvent);
+
+  // Draw the background. This is only signalled if we are using a compositing
+  // window manager, otherwise we just use ActAsRoundedWindow().
+  CHROMEGTK_CALLBACK_1(ThemeInstallBubbleViewGtk, gboolean,
+                       OnExpose, GdkEventExpose*);
+
+  GtkWidget* widget_;
+
+  // The parent browser window, over which we position ourselves.
+  GtkWidget* parent_;
+
+  // The number of loads we represent. When it reaches 0 we delete ourselves.
+  int num_loads_extant_;
+
+  NotificationRegistrar registrar_;
+
+  // Our one instance. We don't allow more than one to exist at a time.
+  static ThemeInstallBubbleViewGtk* instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThemeInstallBubbleViewGtk);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_THEME_INSTALL_BUBBLE_VIEW_GTK_H_
diff --git a/chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.cc b/chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.cc
new file mode 100644
index 0000000..3eeec4e
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.h"
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+AfterTranslateInfoBar::AfterTranslateInfoBar(
+    TranslateInfoBarDelegate* delegate)
+    : TranslateInfoBarBase(delegate),
+      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+}
+
+AfterTranslateInfoBar::~AfterTranslateInfoBar() {
+}
+
+void AfterTranslateInfoBar::Init() {
+  TranslateInfoBarBase::Init();
+
+  bool swapped_language_combos = false;
+  std::vector<string16> strings;
+  TranslateInfoBarDelegate::GetAfterTranslateStrings(
+      &strings, &swapped_language_combos);
+  DCHECK(strings.size() == 3U);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_util::CenterWidgetInHBox(hbox_, hbox, false, 0);
+
+  GtkWidget* original_lang_combo =
+      CreateLanguageCombobox(GetDelegate()->original_language_index(),
+                             GetDelegate()->target_language_index());
+  g_signal_connect(original_lang_combo, "changed",
+                   G_CALLBACK(&OnOriginalLanguageModifiedThunk), this);
+  GtkWidget* target_lang_combo =
+      CreateLanguageCombobox(GetDelegate()->target_language_index(),
+                             GetDelegate()->original_language_index());
+  g_signal_connect(target_lang_combo, "changed",
+                   G_CALLBACK(&OnTargetLanguageModifiedThunk), this);
+
+  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(UTF16ToUTF8(strings[0])),
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox),
+                     swapped_language_combos ? target_lang_combo :
+                                               original_lang_combo,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(UTF16ToUTF8(strings[1])),
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox),
+                     swapped_language_combos ? original_lang_combo :
+                                               target_lang_combo,
+                     FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(UTF16ToUTF8(strings[2])),
+                     FALSE, FALSE, 0);
+
+  GtkWidget* button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_REVERT).c_str());
+  g_signal_connect(button, "clicked",G_CALLBACK(&OnRevertPressedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+}
+
+bool AfterTranslateInfoBar::ShowOptionsMenuButton() const {
+  return true;
+}
+
+void AfterTranslateInfoBar::OnOriginalLanguageModified(GtkWidget* sender) {
+  size_t index = GetLanguageComboboxActiveId(GTK_COMBO_BOX(sender));
+  if (index == GetDelegate()->original_language_index())
+    return;
+
+  // Setting the language will lead to a new translation that is going to close
+  // the infobar.  This is not OK to do this from the signal handler, so we'll
+  // defer it.
+  MessageLoop::current()->PostTask(FROM_HERE, method_factory_.NewRunnableMethod(
+      &AfterTranslateInfoBar::SetOriginalLanguage, index));
+}
+
+void AfterTranslateInfoBar::OnTargetLanguageModified(GtkWidget* sender) {
+  size_t index = GetLanguageComboboxActiveId(GTK_COMBO_BOX(sender));
+  if (index == GetDelegate()->target_language_index())
+    return;
+
+  // See comment in OnOriginalLanguageModified on why we use a task.
+  MessageLoop::current()->PostTask(FROM_HERE, method_factory_.NewRunnableMethod(
+      &AfterTranslateInfoBar::SetTargetLanguage, index));
+}
+
+void AfterTranslateInfoBar::OnRevertPressed(GtkWidget* sender) {
+  GetDelegate()->RevertTranslation();
+}
+
+void AfterTranslateInfoBar::SetOriginalLanguage(size_t language_index) {
+  GetDelegate()->SetOriginalLanguage(language_index);
+}
+
+void AfterTranslateInfoBar::SetTargetLanguage(size_t language_index) {
+  GetDelegate()->SetTargetLanguage(language_index);
+}
diff --git a/chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.h b/chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.h
new file mode 100644
index 0000000..0f5d5fe
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TRANSLATE_AFTER_TRANSLATE_INFOBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TRANSLATE_AFTER_TRANSLATE_INFOBAR_GTK_H_
+#pragma once
+
+#include "base/task.h"
+#include "chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h"
+
+class TranslateInfoBarDelegate;
+
+class AfterTranslateInfoBar : public TranslateInfoBarBase {
+ public:
+  explicit AfterTranslateInfoBar(TranslateInfoBarDelegate* delegate);
+  virtual ~AfterTranslateInfoBar();
+
+  // Overridden from TranslateInfoBarBase:
+  virtual void Init();
+
+ protected:
+  virtual bool ShowOptionsMenuButton() const;
+
+ private:
+  CHROMEGTK_CALLBACK_0(AfterTranslateInfoBar, void, OnOriginalLanguageModified);
+  CHROMEGTK_CALLBACK_0(AfterTranslateInfoBar, void, OnTargetLanguageModified);
+  CHROMEGTK_CALLBACK_0(AfterTranslateInfoBar, void, OnRevertPressed);
+
+  // These methods set the original/target language on the
+  // TranslateInfobarDelegate.
+  void SetOriginalLanguage(size_t language_index);
+  void SetTargetLanguage(size_t language_index);
+
+  ScopedRunnableMethodFactory<AfterTranslateInfoBar> method_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(AfterTranslateInfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TRANSLATE_AFTER_TRANSLATE_INFOBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.cc b/chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.cc
new file mode 100644
index 0000000..c3cdc12
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+BeforeTranslateInfoBar::BeforeTranslateInfoBar(
+    TranslateInfoBarDelegate* delegate)
+    : TranslateInfoBarBase(delegate) {
+}
+
+BeforeTranslateInfoBar::~BeforeTranslateInfoBar() {
+}
+
+void BeforeTranslateInfoBar::Init() {
+  TranslateInfoBarBase::Init();
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_util::CenterWidgetInHBox(hbox_, hbox, false, 0);
+  size_t offset = 0;
+  string16 text =
+      l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE,
+                                 string16(), &offset);
+
+  gtk_box_pack_start(GTK_BOX(hbox),
+                     CreateLabel(UTF16ToUTF8(text.substr(0, offset))),
+                     FALSE, FALSE, 0);
+  GtkWidget* combobox =
+      CreateLanguageCombobox(GetDelegate()->original_language_index(),
+                             GetDelegate()->target_language_index());
+  g_signal_connect(combobox, "changed",
+                   G_CALLBACK(&OnLanguageModifiedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), combobox, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox),
+                     CreateLabel(UTF16ToUTF8(text.substr(offset))),
+                     FALSE, FALSE, 0);
+
+  GtkWidget* button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_ACCEPT).c_str());
+  g_signal_connect(button, "clicked",G_CALLBACK(&OnAcceptPressedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+  button = gtk_button_new_with_label(
+      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_DENY).c_str());
+  g_signal_connect(button, "clicked",G_CALLBACK(&OnDenyPressedThunk), this);
+  gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+  TranslateInfoBarDelegate* delegate = GetDelegate();
+  if (delegate->ShouldShowNeverTranslateButton()) {
+    std::string label =
+        l10n_util::GetStringFUTF8(IDS_TRANSLATE_INFOBAR_NEVER_TRANSLATE,
+                                  delegate->GetLanguageDisplayableNameAt(
+                                      delegate->original_language_index()));
+    button = gtk_button_new_with_label(label.c_str());
+    g_signal_connect(button, "clicked",
+                     G_CALLBACK(&OnNeverTranslatePressedThunk), this);
+    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+  }
+
+  if (delegate->ShouldShowAlwaysTranslateButton()) {
+    std::string label =
+        l10n_util::GetStringFUTF8(IDS_TRANSLATE_INFOBAR_ALWAYS_TRANSLATE,
+                                  delegate->GetLanguageDisplayableNameAt(
+                                      delegate->original_language_index()));
+    button = gtk_button_new_with_label(label.c_str());
+    g_signal_connect(button, "clicked",
+                     G_CALLBACK(&OnAlwaysTranslatePressedThunk), this);
+    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+  }
+}
+
+bool BeforeTranslateInfoBar::ShowOptionsMenuButton() const {
+  return true;
+}
+
+void BeforeTranslateInfoBar::OnLanguageModified(GtkWidget* sender) {
+  size_t index = GetLanguageComboboxActiveId(GTK_COMBO_BOX(sender));
+  if (index == GetDelegate()->original_language_index())
+    return;
+
+  GetDelegate()->SetOriginalLanguage(index);
+}
+
+void BeforeTranslateInfoBar::OnAcceptPressed(GtkWidget* sender) {
+  GetDelegate()->Translate();
+}
+
+void BeforeTranslateInfoBar::OnDenyPressed(GtkWidget* sender) {
+  GetDelegate()->TranslationDeclined();
+  RemoveInfoBar();
+}
+
+void BeforeTranslateInfoBar::OnNeverTranslatePressed(GtkWidget* sender) {
+  GetDelegate()->NeverTranslatePageLanguage();
+}
+
+void BeforeTranslateInfoBar::OnAlwaysTranslatePressed(GtkWidget* sender) {
+  GetDelegate()->AlwaysTranslatePageLanguage();
+}
diff --git a/chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.h b/chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.h
new file mode 100644
index 0000000..e15a1b1
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_GTK_H_
+#pragma once
+
+#include "chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h"
+
+class TranslateInfoBarDelegate;
+
+class BeforeTranslateInfoBar : public TranslateInfoBarBase {
+ public:
+  explicit BeforeTranslateInfoBar(TranslateInfoBarDelegate* delegate);
+  virtual ~BeforeTranslateInfoBar();
+
+  // Overridden from TranslateInfoBarBase:
+  virtual void Init();
+
+ protected:
+  virtual bool ShowOptionsMenuButton() const;
+
+ private:
+  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnLanguageModified);
+  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnAcceptPressed);
+  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnDenyPressed);
+  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnNeverTranslatePressed);
+  CHROMEGTK_CALLBACK_0(BeforeTranslateInfoBar, void, OnAlwaysTranslatePressed);
+
+  DISALLOW_COPY_AND_ASSIGN(BeforeTranslateInfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.cc b/chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.cc
new file mode 100644
index 0000000..5b0182c
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.cc
@@ -0,0 +1,239 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/translate/options_menu_model.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/menu_gtk.h"
+#include "chrome/browser/ui/gtk/translate/after_translate_infobar_gtk.h"
+#include "chrome/browser/ui/gtk/translate/before_translate_infobar_gtk.h"
+#include "chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.h"
+#include "grit/generated_resources.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+
+namespace {
+
+// To be able to map from language id <-> entry in the combo box, we
+// store the language id in the combo box data model in addition to the
+// displayed name.
+enum {
+  LANGUAGE_COMBO_COLUMN_ID,
+  LANGUAGE_COMBO_COLUMN_NAME,
+  LANGUAGE_COMBO_COLUMN_COUNT
+};
+
+}  // namespace
+
+TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate)
+    : InfoBar(delegate) {
+  TranslateInfoBarDelegate::BackgroundAnimationType animation =
+      delegate->background_animation_type();
+  if (animation != TranslateInfoBarDelegate::NONE) {
+    background_color_animation_.reset(new ui::SlideAnimation(this));
+    background_color_animation_->SetTweenType(ui::Tween::LINEAR);
+    background_color_animation_->SetSlideDuration(500);
+    if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
+      background_color_animation_->Show();
+    } else {
+      DCHECK_EQ(TranslateInfoBarDelegate::ERROR_TO_NORMAL, animation);
+      // Hide() runs the animation in reverse.
+      background_color_animation_->Reset(1.0);
+      background_color_animation_->Hide();
+    }
+  } else {
+    background_error_percent_ = delegate->IsError() ? 1 : 0;
+  }
+}
+
+TranslateInfoBarBase::~TranslateInfoBarBase() {
+}
+
+void TranslateInfoBarBase::Init() {
+  if (!ShowOptionsMenuButton())
+    return;
+
+  // The options button sits outside the translate_box so that it can be end
+  // packed in hbox_.
+  GtkWidget* options_menu_button = BuildOptionsMenuButton();
+  g_signal_connect(options_menu_button, "clicked",
+                   G_CALLBACK(&OnOptionsClickedThunk), this);
+  gtk_widget_show_all(options_menu_button);
+  gtk_util::CenterWidgetInHBox(hbox_, options_menu_button, true, 0);
+}
+
+void TranslateInfoBarBase::GetTopColor(InfoBarDelegate::Type type,
+                                       double* r, double* g, double *b) {
+  if (background_error_percent_ <= 0) {
+    InfoBar::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b);
+  } else if (background_error_percent_ >= 1) {
+    InfoBar::GetTopColor(InfoBarDelegate::WARNING_TYPE, r, g, b);
+  } else {
+    double normal_r, normal_g, normal_b;
+    InfoBar::GetTopColor(InfoBarDelegate::PAGE_ACTION_TYPE,
+                         &normal_r, &normal_g, &normal_b);
+
+    double error_r, error_g, error_b;
+    InfoBar::GetTopColor(InfoBarDelegate::WARNING_TYPE,
+                         &error_r, &error_g, &error_b);
+
+    double offset_r = error_r - normal_r;
+    double offset_g = error_g - normal_g;
+    double offset_b = error_b - normal_b;
+
+    *r = normal_r + (background_error_percent_ * offset_r);
+    *g = normal_g + (background_error_percent_ * offset_g);
+    *b = normal_b + (background_error_percent_ * offset_b);
+  }
+}
+
+void TranslateInfoBarBase::GetBottomColor(InfoBarDelegate::Type type,
+                                          double* r, double* g, double *b) {
+  if (background_error_percent_ <= 0) {
+    InfoBar::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE, r, g, b);
+  } else if (background_error_percent_ >= 1) {
+    InfoBar::GetBottomColor(InfoBarDelegate::WARNING_TYPE, r, g, b);
+  } else {
+    double normal_r, normal_g, normal_b;
+    InfoBar::GetBottomColor(InfoBarDelegate::PAGE_ACTION_TYPE,
+                            &normal_r, &normal_g, &normal_b);
+
+    double error_r, error_g, error_b;
+    InfoBar::GetBottomColor(InfoBarDelegate::WARNING_TYPE,
+                            &error_r, &error_g, &error_b);
+
+    double offset_r = error_r - normal_r;
+    double offset_g = error_g - normal_g;
+    double offset_b = error_b - normal_b;
+
+    *r = normal_r + (background_error_percent_ * offset_r);
+    *g = normal_g + (background_error_percent_ * offset_g);
+    *b = normal_b + (background_error_percent_ * offset_b);
+  }
+}
+
+void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
+  DCHECK(animation == background_color_animation_.get());
+  background_error_percent_ = animation->GetCurrentValue();
+  // Queue the info bar widget for redisplay so it repaints its background.
+  gtk_widget_queue_draw(widget());
+}
+
+bool TranslateInfoBarBase::ShowOptionsMenuButton() const {
+  return false;
+}
+
+GtkWidget* TranslateInfoBarBase::CreateLabel(const std::string& text) {
+  GtkWidget* label = gtk_label_new(text.c_str());
+  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gtk_util::kGdkBlack);
+  return label;
+}
+
+GtkWidget* TranslateInfoBarBase::CreateLanguageCombobox(
+    size_t selected_language,
+    size_t exclude_language) {
+  GtkListStore* model = gtk_list_store_new(LANGUAGE_COMBO_COLUMN_COUNT,
+                                           G_TYPE_INT, G_TYPE_STRING);
+  bool set_selection = false;
+  GtkTreeIter selected_iter;
+  TranslateInfoBarDelegate* delegate = GetDelegate();
+  for (size_t i = 0; i < delegate->GetLanguageCount(); ++i) {
+    if (i == exclude_language)
+      continue;
+    GtkTreeIter tree_iter;
+    const string16& name = delegate->GetLanguageDisplayableNameAt(i);
+
+    gtk_list_store_append(model, &tree_iter);
+    gtk_list_store_set(model, &tree_iter,
+                       LANGUAGE_COMBO_COLUMN_ID, i,
+                       LANGUAGE_COMBO_COLUMN_NAME, UTF16ToUTF8(name).c_str(),
+                       -1);
+    if (i == selected_language) {
+      selected_iter = tree_iter;
+      set_selection = true;
+    }
+  }
+
+  GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
+  if (set_selection)
+    gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combobox), &selected_iter);
+  g_object_unref(model);
+  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
+  gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer,
+                                 "text", LANGUAGE_COMBO_COLUMN_NAME,
+                                 NULL);
+  return combobox;
+}
+
+// static
+size_t TranslateInfoBarBase::GetLanguageComboboxActiveId(GtkComboBox* combo) {
+  GtkTreeIter iter;
+  if (!gtk_combo_box_get_active_iter(combo, &iter))
+    return 0;
+
+  gint id = 0;
+  gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter,
+                     LANGUAGE_COMBO_COLUMN_ID, &id,
+                     -1);
+  return static_cast<size_t>(id);
+}
+
+TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() const {
+  return static_cast<TranslateInfoBarDelegate*>(delegate());
+}
+
+// static
+GtkWidget* TranslateInfoBarBase::BuildOptionsMenuButton() {
+  GtkWidget* button = gtk_button_new();
+  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
+  if (former_child)
+    gtk_container_remove(GTK_CONTAINER(button), former_child);
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
+
+  GtkWidget* label = gtk_label_new(
+      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS).c_str());
+  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+  GtkWidget* arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+  gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);
+
+  gtk_container_add(GTK_CONTAINER(button), hbox);
+
+  return button;
+}
+
+void TranslateInfoBarBase::OnOptionsClicked(GtkWidget* sender) {
+  if (!options_menu_model_.get()) {
+    options_menu_model_.reset(new OptionsMenuModel(GetDelegate()));
+    options_menu_menu_.reset(new MenuGtk(NULL, options_menu_model_.get()));
+  }
+  options_menu_menu_->PopupForWidget(sender, 1, gtk_get_current_event_time());
+}
+
+// TranslateInfoBarDelegate specific method:
+InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
+  TranslateInfoBarBase* infobar = NULL;
+  switch (type_) {
+    case BEFORE_TRANSLATE:
+      infobar = new BeforeTranslateInfoBar(this);
+      break;
+    case AFTER_TRANSLATE:
+      infobar = new AfterTranslateInfoBar(this);
+      break;
+    case TRANSLATING:
+    case TRANSLATION_ERROR:
+      infobar = new TranslateMessageInfoBar(this);
+      break;
+    default:
+      NOTREACHED();
+  }
+  infobar->Init();
+  return infobar;
+}
diff --git a/chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h b/chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h
new file mode 100644
index 0000000..f35ffd5
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_
+#pragma once
+
+#include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
+#include "ui/base/animation/animation_delegate.h"
+
+class MenuGtk;
+class OptionsMenuModel;
+class TranslateInfoBarDelegate;
+
+// This class contains some of the base functionality that translate infobars
+// use.
+class TranslateInfoBarBase : public InfoBar,
+                             public ui::AnimationDelegate {
+ public:
+  explicit TranslateInfoBarBase(TranslateInfoBarDelegate* delegate);
+  virtual ~TranslateInfoBarBase();
+
+  // Initializes the infobar widgets. Should be called after the object has been
+  // created.
+  virtual void Init();
+
+  // Overridden from InfoBar:
+  virtual void GetTopColor(InfoBarDelegate::Type type,
+                           double* r, double* g, double *b);
+  virtual void GetBottomColor(InfoBarDelegate::Type type,
+                              double* r, double* g, double *b);
+
+  // Overridden from ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
+ protected:
+  // Sub-classes that want to have the options menu button showing sould
+  // override and return true.
+  virtual bool ShowOptionsMenuButton() const;
+
+  // Creates a label with the appropriate font and color for the translate
+  // infobars.
+  GtkWidget* CreateLabel(const std::string& text);
+
+  // Creates a combobox that displays the languages currently available.
+  // |selected_language| is the language index (as used in the
+  // TranslateInfoBarDelegate) that should be selected initially.
+  // |exclude_language| is the language index of the language that should not be
+  // included in the list (TranslateInfoBarDelegate::kNoIndex means no language
+  // excluded).
+  GtkWidget* CreateLanguageCombobox(size_t selected_language,
+                                    size_t exclude_language);
+
+  // Given an above-constructed combobox, returns the currently selected
+  // language id.
+  static size_t GetLanguageComboboxActiveId(GtkComboBox* combo);
+
+  // Convenience to retrieve the TranslateInfoBarDelegate for this infobar.
+  TranslateInfoBarDelegate* GetDelegate() const;
+
+ private:
+  // Builds a button with an arrow in it to emulate the menu-button style from
+  // the windows version.
+  static GtkWidget* BuildOptionsMenuButton();
+
+  // The menu displayed when the Options button is pressed.
+  scoped_ptr<OptionsMenuModel> options_menu_model_;
+  scoped_ptr<MenuGtk> options_menu_menu_;
+
+  CHROMEGTK_CALLBACK_0(TranslateInfoBarBase, void, OnOptionsClicked);
+
+  // A percentage to average the normal page action background with the error
+  // background. When 0, the infobar background should be pure PAGE_ACTION_TYPE.
+  // When 1, the infobar background should be pure WARNING_TYPE.
+  double background_error_percent_;
+
+  // Changes the color of the background from normal to error color and back.
+  scoped_ptr<ui::SlideAnimation> background_color_animation_;
+
+  DISALLOW_COPY_AND_ASSIGN(TranslateInfoBarBase);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_
diff --git a/chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.cc b/chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.cc
new file mode 100644
index 0000000..b2704ae
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+
+TranslateMessageInfoBar::TranslateMessageInfoBar(
+    TranslateInfoBarDelegate* delegate)
+    : TranslateInfoBarBase(delegate) {
+}
+
+TranslateMessageInfoBar::~TranslateMessageInfoBar() {
+}
+
+void TranslateMessageInfoBar::Init() {
+  TranslateInfoBarBase::Init();
+
+  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+  gtk_util::CenterWidgetInHBox(hbox_, hbox, false, 0);
+
+  std::string text = UTF16ToUTF8(GetDelegate()->GetMessageInfoBarText());
+  gtk_box_pack_start(GTK_BOX(hbox), CreateLabel(text.c_str()), FALSE, FALSE, 0);
+  string16 button_text = GetDelegate()->GetMessageInfoBarButtonText();
+  if (!button_text.empty()) {
+    GtkWidget* button =
+        gtk_button_new_with_label(UTF16ToUTF8(button_text).c_str());
+    g_signal_connect(button, "clicked",G_CALLBACK(&OnButtonPressedThunk), this);
+    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+  }
+}
+
+void TranslateMessageInfoBar::OnButtonPressed(GtkWidget* sender) {
+  GetDelegate()->MessageInfoBarButtonPressed();
+}
diff --git a/chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.h b/chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.h
new file mode 100644
index 0000000..efb39ec
--- /dev/null
+++ b/chrome/browser/ui/gtk/translate/translate_message_infobar_gtk.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_GTK_TRANSLATE_TRANSLATE_MESSAGE_INFOBAR_GTK_H_
+#define CHROME_BROWSER_UI_GTK_TRANSLATE_TRANSLATE_MESSAGE_INFOBAR_GTK_H_
+#pragma once
+
+#include "chrome/browser/ui/gtk/translate/translate_infobar_base_gtk.h"
+
+class TranslateInfoBarDelegate;
+
+class TranslateMessageInfoBar : public TranslateInfoBarBase {
+ public:
+  explicit TranslateMessageInfoBar(TranslateInfoBarDelegate* delegate);
+  virtual ~TranslateMessageInfoBar();
+
+  // Overridden from TranslateInfoBarBase:
+  virtual void Init();
+
+ private:
+  CHROMEGTK_CALLBACK_0(TranslateMessageInfoBar, void, OnButtonPressed);
+
+  DISALLOW_COPY_AND_ASSIGN(TranslateMessageInfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_TRANSLATE_TRANSLATE_MESSAGE_INFOBAR_GTK_H_
diff --git a/chrome/browser/ui/gtk/update_recommended_dialog.cc b/chrome/browser/ui/gtk/update_recommended_dialog.cc
new file mode 100644
index 0000000..d39736f
--- /dev/null
+++ b/chrome/browser/ui/gtk/update_recommended_dialog.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/update_recommended_dialog.h"
+
+#include <gtk/gtk.h>
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/pref_names.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+static const int kMessageWidth = 400;
+
+// static
+void UpdateRecommendedDialog::Show(GtkWindow* parent) {
+  new UpdateRecommendedDialog(parent);
+}
+
+UpdateRecommendedDialog::UpdateRecommendedDialog(GtkWindow* parent) {
+  dialog_ = gtk_dialog_new_with_buttons(
+      l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str(),
+      parent,
+      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+      l10n_util::GetStringUTF8(IDS_NOT_NOW).c_str(),
+      GTK_RESPONSE_REJECT,
+      l10n_util::GetStringUTF8(IDS_RELAUNCH_AND_UPDATE).c_str(),
+      GTK_RESPONSE_ACCEPT,
+      NULL);
+
+  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+
+  // Add the message text.
+  std::string text(
+      l10n_util::GetStringFUTF8(IDS_UPDATE_RECOMMENDED,
+                                l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+  GtkWidget* label = gtk_label_new(text.c_str());
+  gtk_util::SetLabelWidth(label, kMessageWidth);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), label,
+                     FALSE, FALSE, 0);
+
+  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+
+  gtk_widget_show_all(dialog_);
+}
+
+UpdateRecommendedDialog::~UpdateRecommendedDialog() {
+}
+
+void UpdateRecommendedDialog::OnResponse(GtkWidget* sender, gint response_id) {
+  gtk_widget_destroy(dialog_);
+
+  if (response_id == GTK_RESPONSE_ACCEPT) {
+    // Set the flag to restore the last session on shutdown.
+    PrefService* pref_service = g_browser_process->local_state();
+    pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
+
+    BrowserList::CloseAllBrowsersAndExit();
+  }
+
+  delete this;
+}
diff --git a/chrome/browser/ui/gtk/update_recommended_dialog.h b/chrome/browser/ui/gtk/update_recommended_dialog.h
new file mode 100644
index 0000000..e52a505
--- /dev/null
+++ b/chrome/browser/ui/gtk/update_recommended_dialog.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_UPDATE_RECOMMENDED_DIALOG_H_
+#define CHROME_BROWSER_UI_GTK_UPDATE_RECOMMENDED_DIALOG_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "ui/base/gtk/gtk_integers.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkWindow GtkWindow;
+
+class UpdateRecommendedDialog {
+ public:
+  static void Show(GtkWindow* parent);
+
+ private:
+  CHROMEGTK_CALLBACK_1(UpdateRecommendedDialog, void, OnResponse, gint);
+
+  explicit UpdateRecommendedDialog(GtkWindow* parent);
+  ~UpdateRecommendedDialog();
+
+  GtkWidget* dialog_;
+
+  DISALLOW_COPY_AND_ASSIGN(UpdateRecommendedDialog);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_UPDATE_RECOMMENDED_DIALOG_H_
diff --git a/chrome/browser/ui/gtk/view_id_util.cc b/chrome/browser/ui/gtk/view_id_util.cc
new file mode 100644
index 0000000..2b033c5
--- /dev/null
+++ b/chrome/browser/ui/gtk/view_id_util.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/gtk/view_id_util.h"
+
+#include <stdint.h>
+#include <string>
+
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+
+namespace {
+
+const char kViewIDString[] = "__VIEW_ID__";
+const char kViewIDOverrideString[] = "__VIEW_ID_OVERRIDE__";
+
+struct ViewIDSearchStruct {
+  ViewID id;  // Input: the ID we are searching for.
+  GtkWidget* widget;  // Output: the found widget, or NULL.
+};
+
+// Recursively search for the given view ID among the children of |widget|.
+void SearchForWidgetWithViewID(GtkWidget* widget, gpointer data) {
+  ViewIDSearchStruct* search_struct =
+      reinterpret_cast<ViewIDSearchStruct*>(data);
+
+  // The widget has already been found; abort the search.
+  if (search_struct->widget)
+    return;
+
+  // Check if the widget defines its own ID function.
+  ViewIDUtil::Delegate* delegate = reinterpret_cast<ViewIDUtil::Delegate*>(
+      g_object_get_data(G_OBJECT(widget), kViewIDOverrideString));
+  if (delegate) {
+    search_struct->widget = delegate->GetWidgetForViewID(search_struct->id);
+    // If there was success, return.
+    if (search_struct->widget)
+      return;
+  }
+
+  // Otherwise check the g_object data.
+  int widget_id =
+      reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(widget),
+                                 kViewIDString));
+  if (search_struct->id == widget_id) {
+    // Success; set |widget| and return.
+    search_struct->widget = widget;
+    return;
+  }
+
+  // Recurse.
+  if (GTK_IS_CONTAINER(widget)) {
+    gtk_container_foreach(GTK_CONTAINER(widget),
+                          SearchForWidgetWithViewID, data);
+  }
+}
+
+const char* GetNameFromID(ViewID id) {
+  switch (id) {
+    case VIEW_ID_TAB_STRIP:
+      return "chrome-tab-strip";
+
+    case VIEW_ID_TOOLBAR:
+      return "chrome-toolbar";
+
+    case VIEW_ID_BACK_BUTTON:
+      return "chrome-toolbar-back-button";
+
+    case VIEW_ID_FORWARD_BUTTON:
+      return "chrome-toolbar-forward-button";
+
+    case VIEW_ID_RELOAD_BUTTON:
+      return "chrome-toolbar-reload-button";
+
+    case VIEW_ID_HOME_BUTTON:
+      return "chrome-toolbar-home-button";
+
+    case VIEW_ID_STAR_BUTTON:
+      return "chrome-toolbar-star-button";
+
+    case VIEW_ID_LOCATION_BAR:
+      return "chrome-location-bar";
+
+    case VIEW_ID_BROWSER_ACTION_TOOLBAR:
+      return "chrome-toolbar-browser-actions-container";
+
+    case VIEW_ID_APP_MENU:
+      return "chrome-app-menu";
+
+    case VIEW_ID_AUTOCOMPLETE:
+      return "chrome-autocomplete-edit";
+
+    case VIEW_ID_BOOKMARK_BAR:
+      return "chrome-bookmark-bar";
+
+    case VIEW_ID_OTHER_BOOKMARKS:
+      return "chrome-bookmark-bar-other-bookmarks";
+
+    case VIEW_ID_FIND_IN_PAGE_TEXT_FIELD:
+      return "chrome-find-in-page-entry";
+
+    case VIEW_ID_FIND_IN_PAGE:
+      return "chrome-find-in-page";
+
+    case VIEW_ID_DEV_TOOLS_DOCKED:
+      return "chrome-dev-tools-docked";
+
+    // These are never hit because the tab container uses the delegate to
+    // set its ID.
+    case VIEW_ID_TAB_CONTAINER:
+    case VIEW_ID_TAB_CONTAINER_FOCUS_VIEW:
+    default:
+      NOTREACHED() << "If you added a new VIEW_ID, please provide "
+                      "a name for the widget.";
+      return NULL;
+  }
+}
+
+}  // namespace
+
+void ViewIDUtil::SetID(GtkWidget* widget, ViewID id) {
+  const char* name = GetNameFromID(id);
+  if (name)
+    gtk_widget_set_name(widget, name);
+  g_object_set_data(G_OBJECT(widget), kViewIDString,
+                    reinterpret_cast<void*>(id));
+}
+
+GtkWidget* ViewIDUtil::GetWidget(GtkWidget* root, ViewID id) {
+  ViewIDSearchStruct search_struct = { id, NULL };
+  SearchForWidgetWithViewID(root, &search_struct);
+  return search_struct.widget;
+}
+
+void ViewIDUtil::SetDelegateForWidget(GtkWidget* widget, Delegate* delegate) {
+  g_object_set_data(G_OBJECT(widget), kViewIDOverrideString, delegate);
+}
diff --git a/chrome/browser/ui/gtk/view_id_util.h b/chrome/browser/ui/gtk/view_id_util.h
new file mode 100644
index 0000000..278de6e
--- /dev/null
+++ b/chrome/browser/ui/gtk/view_id_util.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_VIEW_ID_UTIL_H_
+#define CHROME_BROWSER_UI_GTK_VIEW_ID_UTIL_H_
+#pragma once
+
+#include "chrome/browser/ui/view_ids.h"
+
+typedef struct _GtkWidget GtkWidget;
+
+class ViewIDUtil {
+ public:
+  // Use this delegate to override default view id searches.
+  class Delegate {
+   public:
+    virtual GtkWidget* GetWidgetForViewID(ViewID id) = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  // If you set the ID via this function, it will also set the name of your
+  // widget to a human-readable value for debugging.
+  static void SetID(GtkWidget* widget, ViewID id);
+
+  static GtkWidget* GetWidget(GtkWidget* root, ViewID id);
+
+  static void SetDelegateForWidget(GtkWidget* widget, Delegate* delegate);
+};
+
+#endif  // CHROME_BROWSER_UI_GTK_VIEW_ID_UTIL_H_
diff --git a/chrome/browser/ui/gtk/view_id_util_browsertest.cc b/chrome/browser/ui/gtk/view_id_util_browsertest.cc
new file mode 100644
index 0000000..88b74bd
--- /dev/null
+++ b/chrome/browser/ui/gtk/view_id_util_browsertest.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2011 The Chromium 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 <gtk/gtk.h>
+
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/gtk/view_id_util.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/in_process_browser_test.h"
+
+class ViewIDTest : public InProcessBrowserTest {
+ public:
+  ViewIDTest() : root_window_(NULL) {}
+
+  void CheckViewID(ViewID id, bool should_have) {
+    if (!root_window_)
+      root_window_ = GTK_WIDGET(browser()->window()->GetNativeHandle());
+
+    ASSERT_TRUE(root_window_);
+    EXPECT_EQ(should_have, !!ViewIDUtil::GetWidget(root_window_, id))
+        << " Failed id=" << id;
+  }
+
+ private:
+  GtkWidget* root_window_;
+};
+
+IN_PROC_BROWSER_TEST_F(ViewIDTest, Basic) {
+  // Make sure FindBar is created to test
+  // VIEW_ID_FIND_IN_PAGE_TEXT_FIELD and VIEW_ID_FIND_IN_PAGE.
+  browser()->ShowFindBar();
+
+  for (int i = VIEW_ID_TOOLBAR; i < VIEW_ID_PREDEFINED_COUNT; ++i) {
+    // The following ids are used only in views implementation.
+    if (i == VIEW_ID_CONTENTS_SPLIT ||
+        i == VIEW_ID_INFO_BAR_CONTAINER ||
+        i == VIEW_ID_DOWNLOAD_SHELF ||
+        i == VIEW_ID_BOOKMARK_BAR_ELEMENT ||
+        i == VIEW_ID_TAB ||
+        i == VIEW_ID_SIDE_BAR_CONTAINER ||
+        i == VIEW_ID_SIDE_BAR_SPLIT ||
+        i == VIEW_ID_FEEDBACK_BUTTON) {
+      continue;
+    }
+
+    CheckViewID(static_cast<ViewID>(i), true);
+  }
+
+  CheckViewID(VIEW_ID_PREDEFINED_COUNT, false);
+}
+
+IN_PROC_BROWSER_TEST_F(ViewIDTest, Delegate) {
+  CheckViewID(VIEW_ID_TAB_0, true);
+  CheckViewID(VIEW_ID_TAB_1, false);
+
+  browser()->OpenURL(GURL(chrome::kAboutBlankURL), GURL(),
+                     NEW_BACKGROUND_TAB, PageTransition::TYPED);
+
+  CheckViewID(VIEW_ID_TAB_0, true);
+  CheckViewID(VIEW_ID_TAB_1, true);
+}
diff --git a/chrome/browser/ui/input_window_dialog.h b/chrome/browser/ui/input_window_dialog.h
index aa7455a..1934b38 100644
--- a/chrome/browser/ui/input_window_dialog.h
+++ b/chrome/browser/ui/input_window_dialog.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 // Cross platform access to a modal input window.
 class InputWindowDialog {
diff --git a/chrome/browser/ui/input_window_dialog_gtk.cc b/chrome/browser/ui/input_window_dialog_gtk.cc
index 87696bb..4b2c3f7 100644
--- a/chrome/browser/ui/input_window_dialog_gtk.cc
+++ b/chrome/browser/ui/input_window_dialog_gtk.cc
@@ -6,12 +6,12 @@
 
 #include <gtk/gtk.h>
 
-#include "app/gtk_signal.h"
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
 #include "base/string_piece.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/gtk/gtk_signal.h"
 
 class InputWindowDialogGtk : public InputWindowDialog {
  public:
diff --git a/chrome/browser/ui/input_window_dialog_win.cc b/chrome/browser/ui/input_window_dialog_win.cc
index 63b5255..1f6aeed 100644
--- a/chrome/browser/ui/input_window_dialog_win.cc
+++ b/chrome/browser/ui/input_window_dialog_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,13 +7,13 @@
 #include "base/compiler_specific.h"
 #include "base/message_loop.h"
 #include "base/task.h"
-#include "views/grid_layout.h"
+#include "grit/generated_resources.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
-#include "grit/generated_resources.h"
 
 // Width to make the text field, in pixels.
 static const int kTextfieldWidth = 200;
@@ -171,13 +171,13 @@
   using views::GridLayout;
 
   // TODO(sky): Vertical alignment should be baseline.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   ColumnSet* c1 = layout->AddColumnSet(0);
   c1->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                 GridLayout::USE_PREF, 0, 0);
-  c1->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  c1->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   c1->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                 GridLayout::USE_PREF, kTextfieldWidth, kTextfieldWidth);
 
diff --git a/chrome/browser/ui/login/login_prompt.cc b/chrome/browser/ui/login/login_prompt.cc
index e58d53a..4f8189a 100644
--- a/chrome/browser/ui/login/login_prompt.cc
+++ b/chrome/browser/ui/login/login_prompt.cc
@@ -6,25 +6,26 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
 #include "chrome/browser/tab_contents/constrained_window.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
 #include "net/base/auth.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using webkit_glue::PasswordForm;
 
@@ -114,8 +115,17 @@
                                       tab_contents_id_);
 }
 
-void LoginHandler::SetAuth(const std::wstring& username,
-                           const std::wstring& password) {
+RenderViewHostDelegate* LoginHandler::GetRenderViewHostDelegate() const {
+  RenderViewHost* rvh = RenderViewHost::FromID(render_process_host_id_,
+                                               tab_contents_id_);
+  if (!rvh)
+    return NULL;
+
+  return rvh->delegate();
+}
+
+void LoginHandler::SetAuth(const string16& username,
+                           const string16& password) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   if (TestAndSetAuthHandled())
@@ -123,8 +133,8 @@
 
   // Tell the password manager the credentials were submitted / accepted.
   if (password_manager_) {
-    password_form_.username_value = WideToUTF16Hack(username);
-    password_form_.password_value = WideToUTF16Hack(password);
+    password_form_.username_value = username;
+    password_form_.password_value = password;
     password_manager_->ProvisionallySavePassword(password_form_);
   }
 
@@ -251,12 +261,13 @@
   if (WasAuthHandled())
     return;
 
-  TabContents* requesting_contents = GetTabContentsForLogin();
-  if (!requesting_contents)
-    return;
-
   NotificationService* service = NotificationService::current();
-  NavigationController* controller = &requesting_contents->controller();
+  NavigationController* controller = NULL;
+
+  TabContents* requesting_contents = GetTabContentsForLogin();
+  if (requesting_contents)
+    controller = &requesting_contents->controller();
+
   LoginNotificationDetails details(this);
 
   service->Notify(NotificationType::AUTH_NEEDED,
@@ -268,12 +279,13 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(WasAuthHandled());
 
-  TabContents* requesting_contents = GetTabContentsForLogin();
-  if (!requesting_contents)
-    return;
-
   NotificationService* service = NotificationService::current();
-  NavigationController* controller = &requesting_contents->controller();
+  NavigationController* controller = NULL;
+
+  TabContents* requesting_contents = GetTabContentsForLogin();
+  if (requesting_contents)
+    controller = &requesting_contents->controller();
+
   LoginNotificationDetails details(this);
 
   service->Notify(NotificationType::AUTH_CANCELLED,
@@ -281,8 +293,8 @@
                   Details<LoginNotificationDetails>(&details));
 }
 
-void LoginHandler::NotifyAuthSupplied(const std::wstring& username,
-                                      const std::wstring& password) {
+void LoginHandler::NotifyAuthSupplied(const string16& username,
+                                      const string16& password) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(WasAuthHandled());
 
@@ -319,26 +331,26 @@
 
 // Returns whether authentication had been handled (SetAuth or CancelAuth).
 bool LoginHandler::WasAuthHandled() const {
-  AutoLock lock(handled_auth_lock_);
+  base::AutoLock lock(handled_auth_lock_);
   bool was_handled = handled_auth_;
   return was_handled;
 }
 
 // Marks authentication as handled and returns the previous handled state.
 bool LoginHandler::TestAndSetAuthHandled() {
-  AutoLock lock(handled_auth_lock_);
+  base::AutoLock lock(handled_auth_lock_);
   bool was_handled = handled_auth_;
   handled_auth_ = true;
   return was_handled;
 }
 
 // Calls SetAuth from the IO loop.
-void LoginHandler::SetAuthDeferred(const std::wstring& username,
-                                   const std::wstring& password) {
+void LoginHandler::SetAuthDeferred(const string16& username,
+                                   const string16& password) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   if (request_) {
-    request_->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password));
+    request_->SetAuth(username, password);
     ResetLoginHandlerForRequest(request_);
   }
 }
@@ -391,15 +403,14 @@
     }
 
     // Tell the password manager to look for saved passwords.
-    TabContentsWrapper** wrapper =
-        TabContentsWrapper::property_accessor()->GetProperty(
-            parent_contents->property_bag());
+    TabContentsWrapper* wrapper =
+        TabContentsWrapper::GetCurrentWrapperForContents(parent_contents);
     if (!wrapper)
       return;
-    PasswordManager* password_manager = (*wrapper)->GetPasswordManager();
+    PasswordManager* password_manager = wrapper->GetPasswordManager();
     std::vector<PasswordForm> v;
     MakeInputForPasswordManager(&v);
-    password_manager->PasswordFormsFound(v);
+    password_manager->OnPasswordFormsFound(v);
     handler_->SetPasswordManager(password_manager);
 
     string16 host_and_port_hack16 = WideToUTF16Hack(auth_info_->host_and_port);
@@ -410,8 +421,7 @@
         l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION,
                                    host_and_port_hack16,
                                    realm_hack16);
-    handler_->BuildViewForPasswordManager(password_manager,
-                                          UTF16ToWideHack(explanation));
+    handler_->BuildViewForPasswordManager(password_manager, explanation);
   }
 
  private:
diff --git a/chrome/browser/ui/login/login_prompt.h b/chrome/browser/ui/login/login_prompt.h
index b566402..7742996 100644
--- a/chrome/browser/ui/login/login_prompt.h
+++ b/chrome/browser/ui/login/login_prompt.h
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
@@ -22,6 +22,7 @@
 
 class ConstrainedWindow;
 class GURL;
+class RenderViewHostDelegate;
 
 // This is the base implementation for the OS-specific classes that route
 // authentication info to the net::URLRequest that needs it. These functions
@@ -40,7 +41,7 @@
 
   // Initializes the underlying platform specific view.
   virtual void BuildViewForPasswordManager(PasswordManager* manager,
-                                           std::wstring explanation) = 0;
+                                           const string16& explanation) = 0;
 
   // Sets information about the authentication type (|form|) and the
   // |password_manager| for this profile.
@@ -50,9 +51,12 @@
   // Returns the TabContents that needs authentication.
   TabContents* GetTabContentsForLogin() const;
 
+  // Returns the RenderViewHostDelegate for the page that needs authentication.
+  RenderViewHostDelegate* GetRenderViewHostDelegate() const;
+
   // Resend the request with authentication credentials.
   // This function can be called from either thread.
-  void SetAuth(const std::wstring& username, const std::wstring& password);
+  void SetAuth(const string16& username, const string16& password);
 
   // Display the error page without asking for credentials again.
   // This function can be called from either thread.
@@ -95,8 +99,8 @@
   void RemoveObservers();
 
   // Notify observers that authentication is supplied.
-  void NotifyAuthSupplied(const std::wstring& username,
-                          const std::wstring& password);
+  void NotifyAuthSupplied(const string16& username,
+                          const string16& password);
 
   // Notify observers that authentication is cancelled.
   void NotifyAuthCancelled();
@@ -106,8 +110,8 @@
   bool TestAndSetAuthHandled();
 
   // Calls SetAuth from the IO loop.
-  void SetAuthDeferred(const std::wstring& username,
-                       const std::wstring& password);
+  void SetAuthDeferred(const string16& username,
+                       const string16& password);
 
   // Calls CancelAuth from the IO loop.
   void CancelAuthDeferred();
@@ -117,7 +121,7 @@
 
   // True if we've handled auth (SetAuth or CancelAuth has been called).
   bool handled_auth_;
-  mutable Lock handled_auth_lock_;
+  mutable base::Lock handled_auth_lock_;
 
   // The ConstrainedWindow that is hosting our LoginView.
   // This should only be accessed on the UI loop.
@@ -175,20 +179,20 @@
 class AuthSuppliedLoginNotificationDetails : public LoginNotificationDetails {
  public:
   AuthSuppliedLoginNotificationDetails(LoginHandler* handler,
-                                       const std::wstring& username,
-                                       const std::wstring& password)
+                                       const string16& username,
+                                       const string16& password)
       : LoginNotificationDetails(handler),
         username_(username),
         password_(password) {}
-  const std::wstring& username() const { return username_; }
-  const std::wstring& password() const { return password_; }
+  const string16& username() const { return username_; }
+  const string16& password() const { return password_; }
 
  private:
   // The username that was used for the authentication.
-  const std::wstring username_;
+  const string16 username_;
 
   // The password that was used for the authentication.
-  const std::wstring password_;
+  const string16 password_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthSuppliedLoginNotificationDetails);
 };
diff --git a/chrome/browser/ui/login/login_prompt_browsertest.cc b/chrome/browser/ui/login/login_prompt_browsertest.cc
index de9be6f..bc52d66 100644
--- a/chrome/browser/ui/login/login_prompt_browsertest.cc
+++ b/chrome/browser/ui/login/login_prompt_browsertest.cc
@@ -6,7 +6,9 @@
 #include <list>
 #include <map>
 
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/login/login_prompt.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
@@ -55,7 +57,8 @@
   EXPECT_TRUE(auth_map_.end() != i);
   if (i != auth_map_.end()) {
     const AuthInfo& info = i->second;
-    handler->SetAuth(info.username_, info.password_);
+    handler->SetAuth(WideToUTF16Hack(info.username_),
+                     WideToUTF16Hack(info.password_));
   }
 }
 
@@ -162,6 +165,8 @@
 typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
     WindowedAuthSuppliedObserver;
 
+const char* kPrefetchAuthPage = "files/login/prefetch.html";
+
 const char* kMultiRealmTestPage = "files/login/multi_realm.html";
 const int   kMultiRealmTestRealmCount = 2;
 const int   kMultiRealmTestResourceCount = 4;
@@ -169,6 +174,49 @@
 const char* kSingleRealmTestPage = "files/login/single_realm.html";
 const int   kSingleRealmTestResourceCount = 6;
 
+// Confirm that <link rel="prefetch"> targetting an auth required
+// resource does not provide a login dialog.  These types of requests
+// should instead just cancel the auth.
+
+// Unfortunately, this test doesn't assert on anything for its
+// correctness.  Instead, it relies on the auth dialog blocking the
+// browser, and triggering a timeout to cause failure when the
+// prefetch resource requires authorization.
+IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
+  ASSERT_TRUE(test_server()->Start());
+
+  GURL test_page = test_server()->GetURL(kPrefetchAuthPage);
+
+  class SetPrefetchForTest {
+   public:
+    explicit SetPrefetchForTest(bool prefetch)
+        : old_prefetch_state_(ResourceDispatcherHost::is_prefetch_enabled()) {
+      ResourceDispatcherHost::set_is_prefetch_enabled(prefetch);
+    }
+
+    ~SetPrefetchForTest() {
+      ResourceDispatcherHost::set_is_prefetch_enabled(old_prefetch_state_);
+    }
+   private:
+    bool old_prefetch_state_;
+  } set_prefetch_for_test(true);
+
+  TabContentsWrapper* contents =
+      browser()->GetSelectedTabContentsWrapper();
+  ASSERT_TRUE(contents);
+  NavigationController* controller = &contents->controller();
+  LoginPromptBrowserTestObserver observer;
+
+  observer.Register(Source<NavigationController>(controller));
+
+  WindowedLoadStopObserver load_stop_waiter(controller);
+  browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
+
+  load_stop_waiter.Wait();
+  EXPECT_TRUE(observer.handlers_.empty());
+  EXPECT_TRUE(test_server()->Stop());
+}
+
 // Test handling of resources that require authentication even though
 // the page they are included on doesn't.  In this case we should only
 // present the minimal number of prompts necessary for successfully
@@ -225,7 +273,14 @@
 
 // Similar to the MultipleRealmCancellation test above, but tests
 // whether supplying credentials work as exepcted.
-IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
+#if defined(OS_WIN)
+// See http://crbug.com/70960
+#define MAYBE_MultipleRealmConfirmation DISABLED_MultipleRealmConfirmation
+#else
+#define MAYBE_MultipleRealmConfirmation MultipleRealmConfirmation
+#endif
+IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
+                       MAYBE_MultipleRealmConfirmation) {
   ASSERT_TRUE(test_server()->Start());
   GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
 
@@ -276,8 +331,9 @@
 
 // Testing for recovery from an incorrect password for the case where
 // there are multiple authenticated resources.
-// Marked as flaky.  See crbug.com/68860
-IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, FLAKY_IncorrectConfirmation) {
+// Marked as flaky.  See http://crbug.com/69266 and http://crbug.com/68860
+// TODO(asanka): Remove logging when timeout issues are resolved.
+IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, DISABLED_IncorrectConfirmation) {
   ASSERT_TRUE(test_server()->Start());
   GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
 
@@ -292,9 +348,13 @@
 
   WindowedLoadStopObserver load_stop_waiter(controller);
 
+  LOG(INFO) <<
+      "Begin test run "
+      "(tracing for potential hang. crbug.com/69266)";
   {
     WindowedAuthNeededObserver auth_needed_waiter(controller);
     browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
+    LOG(INFO) << "Waiting for initial AUTH_NEEDED";
     auth_needed_waiter.Wait();
   }
 
@@ -306,12 +366,15 @@
     LoginHandler* handler = *observer.handlers_.begin();
 
     ASSERT_TRUE(handler);
-    handler->SetAuth(bad_username_, bad_password_);
+    handler->SetAuth(WideToUTF16Hack(bad_username_),
+                     WideToUTF16Hack(bad_password_));
+    LOG(INFO) << "Waiting for initial AUTH_SUPPLIED";
     auth_supplied_waiter.Wait();
 
     // The request should be retried after the incorrect password is
     // supplied.  This should result in a new AUTH_NEEDED notification
     // for the same realm.
+    LOG(INFO) << "Waiting for secondary AUTH_NEEDED";
     auth_needed_waiter.Wait();
   }
 
@@ -327,21 +390,25 @@
       ASSERT_TRUE(handler);
       n_handlers++;
       SetAuthFor(handler);
+      LOG(INFO) << "Waiting for secondary AUTH_SUPPLIED";
       auth_supplied_waiter.Wait();
     }
 
-    if (n_handlers < 1)
+    if (n_handlers < 1) {
+      LOG(INFO) << "Waiting for additional AUTH_NEEDED";
       auth_needed_waiter.Wait();
+    }
   }
 
-  load_stop_waiter.Wait();
-
   // The single realm test has only one realm, and thus only one login
   // prompt.
   EXPECT_EQ(1, n_handlers);
   EXPECT_LT(0, observer.auth_needed_count_);
-  EXPECT_LT(0, observer.auth_supplied_count_);
   EXPECT_EQ(0, observer.auth_cancelled_count_);
+  EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_);
+  LOG(INFO) << "Waiting for LOAD_STOP";
+  load_stop_waiter.Wait();
   EXPECT_TRUE(test_server()->Stop());
+  LOG(INFO) << "Done with test";
 }
-} // namespace
+}  // namespace
diff --git a/chrome/browser/ui/login/login_prompt_gtk.cc b/chrome/browser/ui/login/login_prompt_gtk.cc
index 8cdd6e0..e6487a5 100644
--- a/chrome/browser/ui/login/login_prompt_gtk.cc
+++ b/chrome/browser/ui/login/login_prompt_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,8 @@
 
 #include <gtk/gtk.h>
 
-#include "app/l10n_util.h"
-#include "app/gtk_signal.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
@@ -19,9 +15,13 @@
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents_view_gtk.h"
 #include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/browser/ui/login/login_model.h"
 #include "grit/generated_resources.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using webkit_glue::PasswordForm;
 
@@ -64,11 +64,11 @@
 
   // LoginHandler:
   virtual void BuildViewForPasswordManager(PasswordManager* manager,
-                                           std::wstring explanation) {
+                                           const string16& explanation) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
     root_.Own(gtk_vbox_new(FALSE, gtk_util::kContentAreaBorder));
-    GtkWidget* label = gtk_label_new(WideToUTF8(explanation).c_str());
+    GtkWidget* label = gtk_label_new(UTF16ToUTF8(explanation).c_str());
     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
     gtk_box_pack_start(GTK_BOX(root_.get()), label, FALSE, FALSE, 0);
 
@@ -153,8 +153,8 @@
 
 void LoginHandlerGtk::OnOKClicked(GtkWidget* sender) {
   SetAuth(
-      UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(username_entry_))),
-      UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(password_entry_))));
+      UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(username_entry_))),
+      UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(password_entry_))));
 }
 
 void LoginHandlerGtk::OnCancelClicked(GtkWidget* sender) {
diff --git a/chrome/browser/ui/login/login_prompt_mac.mm b/chrome/browser/ui/login/login_prompt_mac.mm
index 0547e39..6036831 100644
--- a/chrome/browser/ui/login/login_prompt_mac.mm
+++ b/chrome/browser/ui/login/login_prompt_mac.mm
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/login/login_prompt.h"
 #import "chrome/browser/ui/login/login_prompt_mac.h"
 
-#include "app/l10n_util.h"
 #include "base/mac/mac_util.h"
 #include "base/string_util.h"
 #include "base/sys_string_conversions.h"
@@ -21,6 +20,7 @@
 #include "grit/generated_resources.h"
 #include "net/url_request/url_request.h"
 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using webkit_glue::PasswordForm;
 
@@ -53,7 +53,7 @@
 
   // LoginHandler:
   virtual void BuildViewForPasswordManager(PasswordManager* manager,
-                                           std::wstring explanation) {
+                                           const string16& explanation) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
     // Load nib here instead of in constructor.
@@ -64,7 +64,7 @@
 
     SetModel(manager);
 
-    [sheet_controller_ setExplanation:base::SysWideToNSString(explanation)];
+    [sheet_controller_ setExplanation:base::SysUTF16ToNSString(explanation)];
 
     // Scary thread safety note: This can potentially be called *after* SetAuth
     // or CancelAuth (say, if the request was cancelled before the UI thread got
@@ -92,8 +92,8 @@
     ReleaseSoon();
   }
 
-  void OnLoginPressed(const std::wstring& username,
-                      const std::wstring& password) {
+  void OnLoginPressed(const string16& username,
+                      const string16& password) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
     SetAuth(username, password);
@@ -147,8 +147,9 @@
 - (IBAction)loginPressed:(id)sender {
   using base::SysNSStringToWide;
   [NSApp endSheet:[self window]];
-  handler_->OnLoginPressed(SysNSStringToWide([nameField_ stringValue]),
-                           SysNSStringToWide([passwordField_ stringValue]));
+  handler_->OnLoginPressed(
+      base::SysNSStringToUTF16([nameField_ stringValue]),
+      base::SysNSStringToUTF16([passwordField_ stringValue]));
 }
 
 - (IBAction)cancelPressed:(id)sender {
diff --git a/chrome/browser/ui/login/login_prompt_uitest.cc b/chrome/browser/ui/login/login_prompt_uitest.cc
index bdda3fd..eabb682 100644
--- a/chrome/browser/ui/login/login_prompt_uitest.cc
+++ b/chrome/browser/ui/login/login_prompt_uitest.cc
@@ -1,11 +1,10 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <string>
 
 #include "chrome/browser/net/url_fixer_upper.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/browser_proxy.h"
diff --git a/chrome/browser/ui/login/login_prompt_win.cc b/chrome/browser/ui/login/login_prompt_win.cc
index 58a93bc..019679c 100644
--- a/chrome/browser/ui/login/login_prompt_win.cc
+++ b/chrome/browser/ui/login/login_prompt_win.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/login/login_prompt.h"
 
-#include "app/l10n_util.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/views/login_view.h"
 #include "grit/generated_resources.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/window/dialog_delegate.h"
 
 using webkit_glue::PasswordForm;
@@ -101,14 +102,15 @@
   // LoginHandler:
 
   virtual void BuildViewForPasswordManager(PasswordManager* manager,
-                                           std::wstring explanation) {
+                                           const string16& explanation) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
     TabContents* tab_contents = GetTabContentsForLogin();
     bool should_focus_view = !tab_contents->delegate() ||
         tab_contents->delegate()->ShouldFocusConstrainedWindow();
 
-    LoginView* view = new LoginView(explanation, should_focus_view);
+    LoginView* view = new LoginView(UTF16ToWideHack(explanation),
+                                    should_focus_view);
 
     // Set the model for the login view. The model (password manager) is owned
     // by the view's parent TabContents, so natural destruction order means we
diff --git a/chrome/browser/ui/omnibox/location_bar_util.cc b/chrome/browser/ui/omnibox/location_bar_util.cc
index a5e9404..83407bc 100644
--- a/chrome/browser/ui/omnibox/location_bar_util.cc
+++ b/chrome/browser/ui/omnibox/location_bar_util.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/omnibox/location_bar_util.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace location_bar_util {
 
@@ -18,9 +18,10 @@
 // TODO(sky): Once LocationBarView adds a listener to the TemplateURLModel
 // to track changes to the model, this should become a DCHECK.
   const TemplateURL* template_url =
-      profile->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
+      profile->GetTemplateURLModel()->GetTemplateURLForKeyword(
+          WideToUTF16Hack(keyword));
   if (template_url)
-    return template_url->AdjustedShortNameForLocaleDirection();
+    return UTF16ToWideHack(template_url->AdjustedShortNameForLocaleDirection());
   return std::wstring();
 }
 
diff --git a/chrome/browser/ui/options/options_util.cc b/chrome/browser/ui/options/options_util.cc
index d23e5e5..5ed6a83 100644
--- a/chrome/browser/ui/options/options_util.cc
+++ b/chrome/browser/ui/options/options_util.cc
@@ -27,7 +27,6 @@
   const char* kUserPrefs[] = {
     prefs::kAcceptLanguages,
     prefs::kAlternateErrorPagesEnabled,
-    prefs::kClearPluginLSODataOnExit,
     prefs::kClearSiteDataOnExit,
     prefs::kCookieBehavior,
     prefs::kDefaultCharset,
@@ -37,7 +36,6 @@
     prefs::kDeleteCookies,
     prefs::kDeleteDownloadHistory,
     prefs::kDeleteFormData,
-    prefs::kDeleteLSOData,
     prefs::kDeletePasswords,
     prefs::kDnsPrefetchingEnabled,
 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
diff --git a/chrome/browser/ui/shell_dialogs.cc b/chrome/browser/ui/shell_dialogs.cc
new file mode 100644
index 0000000..01dce47
--- /dev/null
+++ b/chrome/browser/ui/shell_dialogs.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/shell_dialogs.h"
+
+SelectFileDialog::FileTypeInfo::FileTypeInfo() : include_all_files(false) {}
+
+SelectFileDialog::FileTypeInfo::~FileTypeInfo() {}
+
+SelectFileDialog::SelectFileDialog() {}
+
+SelectFileDialog::~SelectFileDialog() {}
+
+SelectFontDialog::SelectFontDialog() {}
+
+SelectFontDialog::~SelectFontDialog() {}
diff --git a/chrome/browser/ui/shell_dialogs.h b/chrome/browser/ui/shell_dialogs.h
new file mode 100644
index 0000000..f691c34
--- /dev/null
+++ b/chrome/browser/ui/shell_dialogs.h
@@ -0,0 +1,202 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_SHELL_DIALOGS_H_
+#define CHROME_BROWSER_UI_SHELL_DIALOGS_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "base/string16.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Font;
+}
+
+// This function is declared extern such that it is accessible for unit tests
+// in /chrome/browser/ui/views/shell_dialogs_win_unittest.cc
+extern std::wstring AppendExtensionIfNeeded(const std::wstring& filename,
+                                            const std::wstring& filter_selected,
+                                            const std::wstring& suggested_ext);
+
+// A base class for shell dialogs.
+class BaseShellDialog {
+ public:
+  // Returns true if a shell dialog box is currently being shown modally
+  // to the specified owner.
+  virtual bool IsRunning(gfx::NativeWindow owning_window) const = 0;
+
+  // Notifies the dialog box that the listener has been destroyed and it should
+  // no longer be sent notifications.
+  virtual void ListenerDestroyed() = 0;
+
+ protected:
+  virtual ~BaseShellDialog() {}
+};
+
+// Shows a dialog box for selecting a file or a folder.
+class SelectFileDialog
+    : public base::RefCountedThreadSafe<SelectFileDialog>,
+      public BaseShellDialog {
+ public:
+  enum Type {
+    SELECT_NONE,
+    SELECT_FOLDER,
+    SELECT_SAVEAS_FILE,
+    SELECT_OPEN_FILE,
+    SELECT_OPEN_MULTI_FILE
+  };
+
+  // An interface implemented by a Listener object wishing to know about the
+  // the result of the Select File/Folder action. These callbacks must be
+  // re-entrant.
+  class Listener {
+   public:
+    // Notifies the Listener that a file/folder selection has been made. The
+    // file/folder path is in |path|. |params| is contextual passed to
+    // SelectFile. |index| specifies the index of the filter passed to the
+    // the initial call to SelectFile.
+    virtual void FileSelected(const FilePath& path,
+                              int index, void* params) = 0;
+
+    // Notifies the Listener that many files have been selected. The
+    // files are in |files|. |params| is contextual passed to SelectFile.
+    virtual void MultiFilesSelected(
+      const std::vector<FilePath>& files, void* params) {}
+
+    // Notifies the Listener that the file/folder selection was aborted (via
+    // the  user canceling or closing the selection dialog box, for example).
+    // |params| is contextual passed to SelectFile.
+    virtual void FileSelectionCanceled(void* params) {}
+
+   protected:
+    virtual ~Listener() {}
+  };
+
+  // Creates a dialog box helper. This object is ref-counted, but the returned
+  // object will have no reference (refcount is 0).
+  static SelectFileDialog* Create(Listener* listener);
+
+  // Holds information about allowed extensions on a file save dialog.
+  // |extensions| is a list of allowed extensions. For example, it might be
+  //   { { "htm", "html" }, { "txt" } }. Only pass more than one extension
+  //   in the inner vector if the extensions are equivalent. Do NOT include
+  //   leading periods.
+  // |extension_description_overrides| overrides the system descriptions of the
+  //   specified extensions. Entries correspond to |extensions|; if left blank
+  //   the system descriptions will be used.
+  // |include_all_files| specifies whether there will be a filter added for all
+  //   files (i.e. *.*).
+  struct FileTypeInfo {
+    FileTypeInfo();
+    ~FileTypeInfo();
+
+    std::vector<std::vector<FilePath::StringType> > extensions;
+    std::vector<string16> extension_description_overrides;
+    bool include_all_files;
+  };
+
+  // Selects a file. This will start displaying the dialog box. This will also
+  // block the calling window until the dialog box is complete. The listener
+  // associated with this object will be notified when the selection is
+  // complete.
+  // |type| is the type of file dialog to be shown, see Type enumeration above.
+  // |title| is the title to be displayed in the dialog. If this string is
+  //   empty, the default title is used.
+  // |default_path| is the default path and suggested file name to be shown in
+  //   the dialog. This only works for SELECT_SAVEAS_FILE and SELECT_OPEN_FILE.
+  //   Can be an empty string to indicate the platform default.
+  // |file_types| holds the infomation about the file types allowed. Pass NULL
+  //   to get no special behavior
+  // |file_type_index| is the 1-based index into the file type list in
+  //   |file_types|. Specify 0 if you don't need to specify extension behavior.
+  // |default_extension| is the default extension to add to the file if the
+  //   user doesn't type one. This should NOT include the '.'. On Windows, if
+  //   you specify this you must also specify |file_types|.
+  // |owning_window| is the window the dialog is modal to, or NULL for a
+  //   modeless dialog.
+  // |params| is data from the calling context which will be passed through to
+  //   the listener. Can be NULL.
+  // NOTE: only one instance of any shell dialog can be shown per owning_window
+  //       at a time (for obvious reasons).
+  virtual void SelectFile(Type type,
+                          const string16& title,
+                          const FilePath& default_path,
+                          const FileTypeInfo* file_types,
+                          int file_type_index,
+                          const FilePath::StringType& default_extension,
+                          gfx::NativeWindow owning_window,
+                          void* params) = 0;
+
+  // browser_mode is true when running inside the browser.
+  virtual void set_browser_mode(bool value) {}
+
+ protected:
+  friend class base::RefCountedThreadSafe<SelectFileDialog>;
+  SelectFileDialog();
+  virtual ~SelectFileDialog();
+};
+
+// Shows a dialog box for selecting a font.
+class SelectFontDialog
+    : public base::RefCountedThreadSafe<SelectFontDialog>,
+      public BaseShellDialog {
+ public:
+
+  // An interface implemented by a Listener object wishing to know about the
+  // the result of the Select Font action. These callbacks must be
+  // re-entrant.
+  class Listener {
+   public:
+    // Notifies the Listener that a font selection has been made. The font
+    // details are supplied in |font|. |params| is contextual passed to
+    // SelectFont.
+    virtual void FontSelected(const gfx::Font& font, void* params) = 0;
+
+    // Notifies the Listener that the font selection was aborted (via the user
+    // canceling or closing the selection dialog box, for example). |params| is
+    // contextual passed to SelectFont.
+    virtual void FontSelectionCanceled(void* params) {}
+
+   protected:
+    virtual ~Listener() {}
+  };
+
+  // Creates a dialog box helper. This object is ref-counted, but the returned
+  // object will have no reference (refcount is 0).
+  static SelectFontDialog* Create(Listener* listener);
+
+  // Selects a font. This will start displaying the dialog box. This will also
+  // block the calling window until the dialog box is complete. The listener
+  // associated with this object will be notified when the selection is
+  // complete.
+  // |owning_window| is the window the dialog is modal to, or NULL for a
+  // modeless dialog.
+  // |params| is data from the calling context which will be passed through to
+  // the listener. Can be NULL.
+  // NOTE: only one instance of any shell dialog can be shown per owning_window
+  //       at a time (for obvious reasons).
+  // TODO(beng): support specifying the default font selected in the list when
+  //             the dialog appears.
+  virtual void SelectFont(gfx::NativeWindow owning_window,
+                          void* params) = 0;
+
+  // Same as above - also support specifying the default font selected in the
+  // list when the dialog appears.
+  virtual void SelectFont(gfx::NativeWindow owning_window,
+                          void* params,
+                          const std::wstring& font_name,
+                          int font_size) = 0;
+
+ protected:
+  friend class base::RefCountedThreadSafe<SelectFontDialog>;
+  SelectFontDialog();
+  virtual ~SelectFontDialog();
+};
+
+#endif  // CHROME_BROWSER_UI_SHELL_DIALOGS_H_
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
index b44c346..dcb50c6 100644
--- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
@@ -1,13 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 
 #include "base/lazy_instance.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/password_manager/password_manager.h"
 #include "chrome/browser/password_manager_delegate_impl.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
+#include "chrome/common/notification_service.h"
 
 static base::LazyInstance<PropertyAccessor<TabContentsWrapper*> >
     g_tab_contents_wrapper_property_accessor(base::LINKER_INITIALIZED);
@@ -16,19 +21,32 @@
 // TabContentsWrapper, public:
 
 TabContentsWrapper::TabContentsWrapper(TabContents* contents)
-    : tab_contents_(contents) {
+    : delegate_(NULL),
+      is_starred_(false),
+      tab_contents_(contents) {
   DCHECK(contents);
   // Stash this in the property bag so it can be retrieved without having to
   // go to a Browser.
   property_accessor()->SetProperty(contents->property_bag(), this);
 
   // Needed so that we initialize the password manager on first navigation.
-  tab_contents()->AddNavigationObserver(this);
+  tab_contents()->AddObserver(this);
+
+  // Register for notifications about URL starredness changing on any profile.
+  registrar_.Add(this, NotificationType::URLS_STARRED,
+                 NotificationService::AllSources());
+  registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED,
+                 NotificationService::AllSources());
 }
 
 TabContentsWrapper::~TabContentsWrapper() {
-  // Unregister observers (TabContents outlives supporting objects).
-  tab_contents()->RemoveNavigationObserver(password_manager_.get());
+  // We don't want any notifications while we're running our destructor.
+  registrar_.RemoveAll();
+
+  // Unregister observers.
+  tab_contents()->RemoveObserver(this);
+  if (password_manager_.get())
+    tab_contents()->RemoveObserver(password_manager_.get());
 }
 
 PropertyAccessor<TabContentsWrapper*>* TabContentsWrapper::property_accessor() {
@@ -38,12 +56,20 @@
 TabContentsWrapper* TabContentsWrapper::Clone() {
   TabContents* new_contents = tab_contents()->Clone();
   TabContentsWrapper* new_wrapper = new TabContentsWrapper(new_contents);
-  // Instantiate the passowrd manager if it has been instantiated here.
+  // Instantiate the password manager if it has been instantiated here.
   if (password_manager_.get())
     new_wrapper->GetPasswordManager();
   return new_wrapper;
 }
 
+TabContentsWrapper* TabContentsWrapper::GetCurrentWrapperForContents(
+    TabContents* contents) {
+  TabContentsWrapper** wrapper =
+      property_accessor()->GetProperty(contents->property_bag());
+
+  return wrapper ? *wrapper : NULL;
+}
+
 PasswordManager* TabContentsWrapper::GetPasswordManager() {
   if (!password_manager_.get()) {
     // Create the delegate then create the manager.
@@ -52,15 +78,68 @@
     password_manager_.reset(
         new PasswordManager(password_manager_delegate_.get()));
     // Register the manager to receive navigation notifications.
-    tab_contents()->AddNavigationObserver(password_manager_.get());
+    tab_contents()->AddObserver(password_manager_.get());
   }
   return password_manager_.get();
 }
 
+FindManager* TabContentsWrapper::GetFindManager() {
+  if (!find_manager_.get()) {
+    find_manager_.reset(new FindManager(this));
+    // Register the manager to receive navigation notifications.
+    tab_contents()->AddObserver(find_manager_.get());
+  }
+  return find_manager_.get();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
-// TabContentsWrapper, WebNavigationObserver implementation:
+// TabContentsWrapper, TabContentsObserver implementation:
 
 void TabContentsWrapper::NavigateToPendingEntry() {
+  // If any page loads, ensure that the password manager is loaded so that forms
+  // get filled out.
   GetPasswordManager();
-  tab_contents()->RemoveNavigationObserver(this);
+}
+
+void TabContentsWrapper::DidNavigateMainFramePostCommit(
+    const NavigationController::LoadCommittedDetails& /*details*/,
+    const ViewHostMsg_FrameNavigate_Params& /*params*/) {
+  UpdateStarredStateForCurrentURL();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsWrapper, NotificationObserver implementation:
+
+void TabContentsWrapper::Observe(NotificationType type,
+                                 const NotificationSource& source,
+                                 const NotificationDetails& details) {
+  switch (type.value) {
+    case NotificationType::BOOKMARK_MODEL_LOADED:
+      // BookmarkModel finished loading, fall through to update starred state.
+    case NotificationType::URLS_STARRED: {
+      // Somewhere, a URL has been starred.
+      // Ignore notifications for profiles other than our current one.
+      Profile* source_profile = Source<Profile>(source).ptr();
+      if (!source_profile || !source_profile->IsSameProfile(profile()))
+        return;
+
+      UpdateStarredStateForCurrentURL();
+      break;
+    }
+
+    default:
+      NOTREACHED();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Internal helpers
+
+void TabContentsWrapper::UpdateStarredStateForCurrentURL() {
+  BookmarkModel* model = tab_contents()->profile()->GetBookmarkModel();
+  const bool old_state = is_starred_;
+  is_starred_ = (model && model->IsBookmarked(tab_contents()->GetURL()));
+
+  if (is_starred_ != old_state && delegate())
+    delegate()->URLStarredChanged(this, is_starred_);
 }
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.h b/chrome/browser/ui/tab_contents/tab_contents_wrapper.h
index f47a6ad..742cbe2 100644
--- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.h
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,23 +6,28 @@
 #define CHROME_BROWSER_UI_TAB_CONTENTS_TAB_CONTENTS_WRAPPER_H_
 #pragma once
 
+#include "base/basictypes.h"
 #include "base/scoped_ptr.h"
+#include "base/compiler_specific.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/web_navigation_observer.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
+#include "chrome/common/notification_registrar.h"
 
 class Extension;
+class FindManager;
 class NavigationController;
 class PasswordManager;
 class PasswordManagerDelegate;
-class TabContentsDelegate;
+class TabContentsWrapperDelegate;
 
-// Wraps TabContents and all of its supporting objetcs in order to control
+// Wraps TabContents and all of its supporting objects in order to control
 // their ownership and lifetime, while allowing TabContents to remain generic
 // and re-usable in other projects.
 // TODO(pinkerton): Eventually, this class will become TabContents as far as
 // the browser front-end is concerned, and the current TabContents will be
 // renamed to something like WebPage or WebView (ben's suggestions).
-class TabContentsWrapper : public WebNavigationObserver {
+class TabContentsWrapper : public NotificationObserver,
+                           public TabContentsObserver {
  public:
   // Takes ownership of |contents|, which must be heap-allocated (as it lives
   // in a scoped_ptr) and can not be NULL.
@@ -37,6 +42,14 @@
   // heap-allocated pointer is owned by the caller.
   TabContentsWrapper* Clone();
 
+  // Helper to retrieve the existing instance that wraps a given TabContents.
+  // Returns NULL if there is no such existing instance.
+  static TabContentsWrapper* GetCurrentWrapperForContents(
+      TabContents* contents);
+
+  TabContentsWrapperDelegate* delegate() const { return delegate_; }
+  void set_delegate(TabContentsWrapperDelegate* d) { delegate_ = d; }
+
   TabContents* tab_contents() const { return tab_contents_.get(); }
   NavigationController& controller() const {
     return tab_contents()->controller();
@@ -46,8 +59,6 @@
     return tab_contents()->render_view_host();
   }
   Profile* profile() const { return tab_contents()->profile(); }
-  TabContentsDelegate* delegate() const { return tab_contents()->delegate(); }
-  void set_delegate(TabContentsDelegate* d) { tab_contents()->set_delegate(d); }
 
   // Convenience methods until extensions are removed from TabContents.
   void SetExtensionAppById(const std::string& extension_app_id) {
@@ -58,22 +69,65 @@
   }
   bool is_app() const { return tab_contents()->is_app(); }
 
+  bool is_starred() const { return is_starred_; }
+
   // Returns the PasswordManager, creating it if necessary.
   PasswordManager* GetPasswordManager();
 
-  // WebNavigationObserver overrides:
-  virtual void NavigateToPendingEntry();
+  // Returns the FindManager, creating it if necessary.
+  FindManager* GetFindManager();
+
+  // Overrides -----------------------------------------------------------------
+
+  // TabContentsObserver overrides:
+  virtual void NavigateToPendingEntry() OVERRIDE;
+  virtual void DidNavigateMainFramePostCommit(
+      const NavigationController::LoadCommittedDetails& details,
+      const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE;
+
+  // NotificationObserver overrides:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) OVERRIDE;
 
  private:
+  // Internal helpers ----------------------------------------------------------
+
+  // Updates the starred state from the bookmark bar model. If the state has
+  // changed, the delegate is notified.
+  void UpdateStarredStateForCurrentURL();
+
+  // Data for core operation ---------------------------------------------------
+
+  // Delegate for notifying our owner about stuff. Not owned by us.
+  TabContentsWrapperDelegate* delegate_;
+
+  // Registers and unregisters us for notifications.
+  NotificationRegistrar registrar_;
+
+  // Data for current page -----------------------------------------------------
+
+  // Whether the current URL is starred.
+  bool is_starred_;
+
+  // Supporting objects --------------------------------------------------------
+
   // PasswordManager and its delegate, lazily created. The delegate must
   // outlive the manager, per documentation in password_manager.h.
   scoped_ptr<PasswordManagerDelegate> password_manager_delegate_;
   scoped_ptr<PasswordManager> password_manager_;
 
+  // FindManager, lazily created.
+  scoped_ptr<FindManager> find_manager_;
+
+  // TabContents (MUST BE LAST) ------------------------------------------------
+
   // The supporting objects need to outlive the TabContents dtor (as they may
   // be called upon during its execution). As a result, this must come last
   // in the list.
   scoped_ptr<TabContents> tab_contents_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabContentsWrapper);
 };
 
 #endif  // CHROME_BROWSER_UI_TAB_CONTENTS_TAB_CONTENTS_WRAPPER_H_
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.cc b/chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.cc
new file mode 100644
index 0000000..61a2718
--- /dev/null
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.cc
@@ -0,0 +1,8 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
+
+TabContentsWrapperDelegate::~TabContentsWrapperDelegate() {
+}
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h b/chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h
new file mode 100644
index 0000000..14cdc2f
--- /dev/null
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_TAB_CONTENTS_TAB_CONTENTS_WRAPPER_DELEGATE_H_
+#define CHROME_BROWSER_UI_TAB_CONTENTS_TAB_CONTENTS_WRAPPER_DELEGATE_H_
+#pragma once
+
+class TabContentsWrapper;
+
+// Objects implement this interface to get notified about changes in the
+// TabContentsWrapper and to provide necessary functionality.
+class TabContentsWrapperDelegate {
+ public:
+  // Notification that the starredness of the current URL changed.
+  virtual void URLStarredChanged(TabContentsWrapper* source, bool starred) = 0;
+
+ protected:
+  virtual ~TabContentsWrapperDelegate();
+};
+
+#endif  // CHROME_BROWSER_UI_TAB_CONTENTS_TAB_CONTENTS_WRAPPER_DELEGATE_H_
diff --git a/chrome/browser/ui/tab_contents/test_tab_contents_wrapper.cc b/chrome/browser/ui/tab_contents/test_tab_contents_wrapper.cc
new file mode 100644
index 0000000..10b8a6b
--- /dev/null
+++ b/chrome/browser/ui/tab_contents/test_tab_contents_wrapper.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h"
+
+#include "chrome/browser/tab_contents/test_tab_contents.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/test/testing_profile.h"
+
+TabContentsWrapperTestHarness::TabContentsWrapperTestHarness()
+    : RenderViewHostTestHarness() {
+}
+
+TabContentsWrapperTestHarness::~TabContentsWrapperTestHarness() {
+}
+
+TestTabContents* TabContentsWrapperTestHarness::contents() {
+  return static_cast<TestTabContents*>(contents_wrapper_.get()->tab_contents());
+}
+
+TabContentsWrapper* TabContentsWrapperTestHarness::contents_wrapper() {
+  return contents_wrapper_.get();
+}
+
+void TabContentsWrapperTestHarness::SetUp() {
+  contents_wrapper_.reset(new TabContentsWrapper(CreateTestTabContents()));
+}
+
+void TabContentsWrapperTestHarness::TearDown() {
+  contents_wrapper_.reset();
+
+  // Make sure that we flush any messages related to TabContents destruction
+  // before we destroy the profile.
+  MessageLoop::current()->RunAllPending();
+
+  // Release the profile on the UI thread.
+  message_loop_.DeleteSoon(FROM_HERE, profile_.release());
+  message_loop_.RunAllPending();
+}
diff --git a/chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h b/chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h
new file mode 100644
index 0000000..9c60c12
--- /dev/null
+++ b/chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TAB_CONTENTS_TEST_TAB_CONTENTS_WRAPPER_H_
+#define CHROME_BROWSER_UI_TAB_CONTENTS_TEST_TAB_CONTENTS_WRAPPER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+
+class TabContentsWrapper;
+
+class TabContentsWrapperTestHarness : public RenderViewHostTestHarness {
+ public:
+  TabContentsWrapperTestHarness();
+  virtual ~TabContentsWrapperTestHarness();
+
+  TestTabContents* contents();
+  TabContentsWrapper* contents_wrapper();
+
+ protected:
+  // testing::Test
+  virtual void SetUp() OVERRIDE;
+  virtual void TearDown() OVERRIDE;
+
+  scoped_ptr<TabContentsWrapper> contents_wrapper_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabContentsWrapperTestHarness);
+};
+
+#endif  // CHROME_BROWSER_UI_TAB_CONTENTS_TEST_TAB_CONTENTS_WRAPPER_H_
diff --git a/chrome/browser/ui/tabs/dock_info.cc b/chrome/browser/ui/tabs/dock_info.cc
index 97fe29d..b7a6997 100644
--- a/chrome/browser/ui/tabs/dock_info.cc
+++ b/chrome/browser/ui/tabs/dock_info.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/tabs/dock_info.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/views/tabs/tab.h"
+#include "chrome/browser/ui/views/tabs/tab.h"
 #else
-#include "chrome/browser/gtk/tabs/tab_gtk.h"
+#include "chrome/browser/ui/gtk/tabs/tab_gtk.h"
 #endif
 
 namespace {
diff --git a/chrome/browser/ui/tabs/dock_info.h b/chrome/browser/ui/tabs/dock_info.h
index fa45b1a..8c3b740 100644
--- a/chrome/browser/ui/tabs/dock_info.h
+++ b/chrome/browser/ui/tabs/dock_info.h
@@ -8,9 +8,9 @@
 
 #include <set>
 
-#include "gfx/native_widget_types.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 
 // DockInfo is used to do determine possible dock locations for a dragged
 // tab. To use DockInfo invoke GetDockInfoAtPoint. This returns a new
diff --git a/chrome/browser/ui/tabs/dock_info_gtk.cc b/chrome/browser/ui/tabs/dock_info_gtk.cc
index 3fb2778..07c14c1 100644
--- a/chrome/browser/ui/tabs/dock_info_gtk.cc
+++ b/chrome/browser/ui/tabs/dock_info_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,23 +8,24 @@
 
 #include "base/logging.h"
 #include "base/task.h"
-#include "chrome/browser/gtk/browser_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "gfx/native_widget_types.h"
+#include "chrome/browser/ui/gtk/browser_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/native_widget_types.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // BaseWindowFinder
 //
 // Base class used to locate a window. A subclass need only override
 // ShouldStopIterating to determine when iteration should stop.
-class BaseWindowFinder : public x11_util::EnumerateWindowsDelegate {
+class BaseWindowFinder : public ui::EnumerateWindowsDelegate {
  public:
   explicit BaseWindowFinder(const std::set<GtkWidget*>& ignore) {
     std::set<GtkWidget*>::iterator iter;
     for (iter = ignore.begin(); iter != ignore.end(); iter++) {
-      XID xid = x11_util::GetX11WindowFromGtkWidget(*iter);
+      XID xid = ui::GetX11WindowFromGtkWidget(*iter);
       ignore_.insert(xid);
     }
   }
@@ -75,13 +76,13 @@
       return true;
     }
 
-    if (!x11_util::IsWindowVisible(window)) {
+    if (!ui::IsWindowVisible(window)) {
       // The window isn't visible, keep iterating.
       return false;
     }
 
     gfx::Rect rect;
-    if (x11_util::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) {
+    if (ui::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) {
       // At this point we haven't found our target window, so this window is
       // higher in the z-order than the target window.  If this window contains
       // the point, then we can stop the search now because this window is
@@ -145,11 +146,11 @@
     if (!BrowserWindowGtk::GetBrowserWindowForXID(window))
       return false;
 
-    if (!x11_util::IsWindowVisible(window))
+    if (!ui::IsWindowVisible(window))
       return false;
 
     gfx::Rect rect;
-    if (x11_util::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) {
+    if (ui::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) {
       result_ = window;
       return true;
     }
diff --git a/chrome/browser/ui/tabs/dock_info_unittest.cc b/chrome/browser/ui/tabs/dock_info_unittest.cc
index ee4557e..c4abfd5 100644
--- a/chrome/browser/ui/tabs/dock_info_unittest.cc
+++ b/chrome/browser/ui/tabs/dock_info_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/ui/tabs/dock_info.h"
-#include "gfx/point.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/point.h"
 
 namespace {
 // Distance in pixels between the hotspot and when the hint should be shown.
@@ -101,7 +101,7 @@
 
 TEST(DockInfoTest, IsValidForPoint) {
   DockInfo d;
-  EXPECT_EQ(false, d.IsValidForPoint(gfx::Point(0, 0)));
+  EXPECT_FALSE(d.IsValidForPoint(gfx::Point(0, 0)));
   d.set_monitor_bounds(gfx::Rect(0, 0, kPopupWidth, kPopupHeight));
   d.set_hot_spot(gfx::Point(0, 0));
   d.set_type(DockInfo::LEFT_HALF);
@@ -124,9 +124,9 @@
 TEST(DockInfoTest, equals) {
   DockInfo d;
   DockInfo dd;
-  EXPECT_EQ(true, d.equals(dd));
+  EXPECT_TRUE(d.equals(dd));
   d.set_type(DockInfo::MAXIMIZE);
-  EXPECT_EQ(false, d.equals(dd));
+  EXPECT_FALSE(d.equals(dd));
 }
 
 TEST(DockInfoTest, CheckMonitorPoint) {
diff --git a/chrome/browser/ui/tabs/dock_info_win.cc b/chrome/browser/ui/tabs/dock_info_win.cc
index c9aa412..67ca6e4 100644
--- a/chrome/browser/ui/tabs/dock_info_win.cc
+++ b/chrome/browser/ui/tabs/dock_info_win.cc
@@ -5,11 +5,11 @@
 #include "chrome/browser/ui/tabs/dock_info.h"
 
 #include "base/win/scoped_gdi_object.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/tab.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/tabs/tab.h"
+#include "views/screen.h"
 
 namespace {
 
@@ -231,12 +231,10 @@
                      const std::set<HWND>& ignore)
       : BaseWindowFinder(ignore),
         screen_loc_(screen_loc) {
-    HMONITOR monitor = MonitorFromPoint(screen_loc.ToPOINT(),
-                                        MONITOR_DEFAULTTONULL);
-    MONITORINFO monitor_info = {0};
-    monitor_info.cbSize = sizeof(MONITORINFO);
-    if (monitor && GetMonitorInfo(monitor, &monitor_info)) {
-      result_.set_monitor_bounds(gfx::Rect(monitor_info.rcWork));
+    gfx::Rect work_area = views::Screen::GetMonitorWorkAreaNearestPoint(
+        screen_loc);
+    if (!work_area.IsEmpty()) {
+      result_.set_monitor_bounds(work_area);
       EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc,
                         reinterpret_cast<LPARAM>(this));
     }
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc
index 6d96adb..907969d 100644
--- a/chrome/browser/ui/tabs/tab_menu_model.cc
+++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -7,12 +7,11 @@
 #include "base/command_line.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 
-TabMenuModel::TabMenuModel(menus::SimpleMenuModel::Delegate* delegate,
+TabMenuModel::TabMenuModel(ui::SimpleMenuModel::Delegate* delegate,
                            bool is_pinned)
-    : menus::SimpleMenuModel(delegate) {
+    : ui::SimpleMenuModel(delegate) {
   Build(is_pinned);
 }
 
diff --git a/chrome/browser/ui/tabs/tab_menu_model.h b/chrome/browser/ui/tabs/tab_menu_model.h
index aeff953..61a8e34 100644
--- a/chrome/browser/ui/tabs/tab_menu_model.h
+++ b/chrome/browser/ui/tabs/tab_menu_model.h
@@ -6,15 +6,15 @@
 #define CHROME_BROWSER_UI_TABS_TAB_MENU_MODEL_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
+#include "ui/base/models/simple_menu_model.h"
 
 // A menu model that builds the contents of the tab context menu. This menu has
 // only one level (no submenus). TabMenuModel caches local state from the
 // tab (such as the pinned state). To make sure the menu reflects the real state
 // of the tab a new TabMenuModel should be created each time the menu is shown.
-class TabMenuModel : public menus::SimpleMenuModel {
+class TabMenuModel : public ui::SimpleMenuModel {
  public:
-  TabMenuModel(menus::SimpleMenuModel::Delegate* delegate, bool is_pinned);
+  TabMenuModel(ui::SimpleMenuModel::Delegate* delegate, bool is_pinned);
   virtual ~TabMenuModel() {}
 
   // Returns true if vertical tabs are enabled.
diff --git a/chrome/browser/ui/tests/browser_uitest.cc b/chrome/browser/ui/tests/browser_uitest.cc
index 680a86a..c72b245 100644
--- a/chrome/browser/ui/tests/browser_uitest.cc
+++ b/chrome/browser/ui/tests/browser_uitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include "base/string_util.h"
 #include "base/sys_info.h"
 #include "base/test/test_file_util.h"
+#include "base/test/test_timeouts.h"
 #include "base/values.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/platform_util.h"
@@ -20,11 +21,11 @@
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-#include "gfx/native_widget_types.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_util.h"
 #include "net/test/test_server.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace {
 
@@ -101,7 +102,8 @@
   tab->NavigateToURL(net::FilePathToFileURL(test_file));
   int orig_tab_count = -1;
   ASSERT_TRUE(window->GetTabCount(&orig_tab_count));
-  int orig_process_count = GetBrowserProcessCount();
+  int orig_process_count = 0;
+  ASSERT_TRUE(GetBrowserProcessCount(&orig_process_count));
   ASSERT_GE(orig_process_count, 1);
 
   // Use JavaScript URL to "fork" a new tab, just like Gmail.  (Open tab to a
@@ -113,8 +115,10 @@
   // Make sure that a new tab has been created and that we have a new renderer
   // process for it.
   ASSERT_TRUE(tab->NavigateToURLAsync(fork_url));
-  PlatformThread::Sleep(sleep_timeout_ms());
-  ASSERT_EQ(orig_process_count + 1, GetBrowserProcessCount());
+  PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
+  int process_count = 0;
+  ASSERT_TRUE(GetBrowserProcessCount(&process_count));
+  ASSERT_EQ(orig_process_count + 1, process_count);
   int new_tab_count = -1;
   ASSERT_TRUE(window->GetTabCount(&new_tab_count));
   ASSERT_EQ(orig_tab_count + 1, new_tab_count);
@@ -153,7 +157,8 @@
             tab->NavigateToURL(net::FilePathToFileURL(test_file)));
   int orig_tab_count = -1;
   ASSERT_TRUE(window->GetTabCount(&orig_tab_count));
-  int orig_process_count = GetBrowserProcessCount();
+  int orig_process_count = 0;
+  ASSERT_TRUE(GetBrowserProcessCount(&orig_process_count));
   ASSERT_GE(orig_process_count, 1);
 
   // Use JavaScript URL to almost fork a new tab, but not quite.  (Leave the
@@ -166,8 +171,10 @@
 
   // Make sure that a new tab but not new process has been created.
   ASSERT_TRUE(tab->NavigateToURLAsync(dont_fork_url));
-  base::PlatformThread::Sleep(sleep_timeout_ms());
-  ASSERT_EQ(orig_process_count, GetBrowserProcessCount());
+  base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
+  int process_count = 0;
+  ASSERT_TRUE(GetBrowserProcessCount(&process_count));
+  ASSERT_EQ(orig_process_count, process_count);
   int new_tab_count = -1;
   ASSERT_TRUE(window->GetTabCount(&new_tab_count));
   ASSERT_EQ(orig_tab_count + 1, new_tab_count);
@@ -181,8 +188,9 @@
 
   // Make sure that no new process has been created.
   ASSERT_TRUE(tab->NavigateToURLAsync(dont_fork_url2));
-  base::PlatformThread::Sleep(sleep_timeout_ms());
-  ASSERT_EQ(orig_process_count, GetBrowserProcessCount());
+  base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
+  ASSERT_TRUE(GetBrowserProcessCount(&process_count));
+  ASSERT_EQ(orig_process_count, process_count);
 }
 
 TEST_F(VisibleBrowserTest, WindowOpenClose) {
@@ -239,7 +247,7 @@
   ASSERT_TRUE(tab->NavigateToURL(url));
 
   std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
-        "status", action_max_timeout_ms());
+        "status", TestTimeouts::action_max_timeout_ms());
   ASSERT_STREQ("Disallowed", value.c_str());
 }
 
diff --git a/chrome/browser/ui/tests/ui_gfx_image_unittest.cc b/chrome/browser/ui/tests/ui_gfx_image_unittest.cc
new file mode 100644
index 0000000..a8e8166
--- /dev/null
+++ b/chrome/browser/ui/tests/ui_gfx_image_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/image.h"
+#include "ui/gfx/image_unittest.h"
+
+#if defined(OS_LINUX)
+#include <gtk/gtk.h>
+#include "ui/gfx/gtk_util.h"
+#endif
+
+#if defined(TOOLKIT_VIEWS)
+#include "views/controls/image_view.h"
+#include "views/view.h"
+#endif
+
+namespace {
+
+using namespace ui::gfx::test;
+
+#if defined(TOOLKIT_VIEWS)
+TEST(UiGfxImageTest, ViewsImageView) {
+  ui::gfx::Image image(CreatePlatformImage());
+
+  scoped_ptr<views::View> container(new views::View());
+  container->SetBounds(0, 0, 200, 200);
+  container->SetVisible(true);
+
+  scoped_ptr<views::ImageView> image_view(new views::ImageView());
+  image_view->SetImage(image);
+  container->AddChildView(image_view.get());
+}
+#endif
+
+#if defined(OS_LINUX)
+TEST(UiGfxImageTest, GtkImageView) {
+  GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_window_resize(GTK_WINDOW(window), 200, 200);
+  gtk_window_move(GTK_WINDOW(window), 300, 300);
+
+  GtkWidget* fixed = gtk_fixed_new();
+  gtk_container_add(GTK_CONTAINER(window), fixed);
+
+  ui::gfx::Image image(CreateBitmap());
+  GtkWidget* image_view = gtk_image_new_from_pixbuf(image);
+  gtk_fixed_put(GTK_FIXED(fixed), image_view, 10, 10);
+  gtk_widget_set_size_request(image_view, 25, 25);
+
+  gtk_widget_show_all(window);
+
+  gtk_widget_destroy(window);
+}
+#endif
+
+}  // namespace
diff --git a/chrome/browser/ui/tests/ui_gfx_image_unittest.mm b/chrome/browser/ui/tests/ui_gfx_image_unittest.mm
new file mode 100644
index 0000000..c48e9bd
--- /dev/null
+++ b/chrome/browser/ui/tests/ui_gfx_image_unittest.mm
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <AppKit/AppKit.h>
+
+#include "base/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/image.h"
+#include "ui/gfx/image_unittest.h"
+
+namespace {
+
+using namespace ui::gfx::test;
+
+class UiGfxImageTest : public CocoaTest {
+};
+
+TEST_F(UiGfxImageTest, CheckColor) {
+  ui::gfx::Image image(CreateBitmap());
+  [image lockFocus];
+  NSColor* color = NSReadPixel(NSMakePoint(10, 10));
+  [image unlockFocus];
+
+  // SkBitmapToNSImage returns a bitmap in the calibrated color space (sRGB),
+  // while NSReadPixel returns a color in the device color space. Convert back
+  // to the calibrated color space before testing.
+  color = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+
+  CGFloat components[4] = { 0 };
+  [color getComponents:components];
+
+  EXPECT_GT(components[0], 0.95);
+  EXPECT_LT(components[1], 0.05);
+  EXPECT_LT(components[2], 0.05);
+  EXPECT_GT(components[3], 0.95);
+}
+
+TEST_F(UiGfxImageTest, ImageView) {
+  scoped_nsobject<NSImageView> image_view(
+      [[NSImageView alloc] initWithFrame:NSMakeRect(10, 10, 25, 25)]);
+  [[test_window() contentView] addSubview:image_view];
+  [test_window() orderFront:nil];
+
+  ui::gfx::Image image(CreateBitmap());
+  [image_view setImage:image];
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.cc b/chrome/browser/ui/toolbar/back_forward_menu_model.cc
index 9874ef9..67943d9 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model.cc
@@ -6,9 +6,6 @@
 
 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
 
-#include "app/l10n_util.h"
-#include "app/text_elider.h"
-#include "app/resource_bundle.h"
 #include "base/string_number_conversions.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
@@ -22,6 +19,9 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/registry_controlled_domain.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
 
 const int BackForwardMenuModel::kMaxHistoryItems = 12;
 const int BackForwardMenuModel::kMaxChapterStops = 5;
@@ -59,7 +59,7 @@
   return items;
 }
 
-menus::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(int index) const {
+ui::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(int index) const {
   return IsSeparator(index) ? TYPE_SEPARATOR : TYPE_COMMAND;
 }
 
@@ -82,7 +82,7 @@
   string16 menu_text(entry->GetTitleForDisplay(
       GetTabContents()->profile()->GetPrefs()->
           GetString(prefs::kAcceptLanguages)));
-  menu_text = gfx::ElideText(menu_text, gfx::Font(), kMaxWidth, false);
+  menu_text = ui::ElideText(menu_text, gfx::Font(), kMaxWidth, false);
 
   for (size_t i = menu_text.find('&'); i != string16::npos;
        i = menu_text.find('&', i + 2)) {
@@ -98,7 +98,7 @@
 
 bool BackForwardMenuModel::GetAcceleratorAt(
     int index,
-    menus::Accelerator* accelerator) const {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
@@ -125,7 +125,7 @@
   return true;
 }
 
-menus::ButtonMenuItemModel* BackForwardMenuModel::GetButtonMenuItemAt(
+ui::ButtonMenuItemModel* BackForwardMenuModel::GetButtonMenuItemAt(
     int index) const {
   return NULL;
 }
@@ -134,7 +134,7 @@
   return index < GetItemCount() && !IsSeparator(index);
 }
 
-menus::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(int index) const {
+ui::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(int index) const {
   return NULL;
 }
 
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.h b/chrome/browser/ui/toolbar/back_forward_menu_model.h
index 1d669a0..d256f0c 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model.h
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model.h
@@ -8,10 +8,10 @@
 
 #include <string>
 
-#include "app/menus/menu_model.h"
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "base/string16.h"
+#include "ui/base/models/menu_model.h"
 #include "webkit/glue/window_open_disposition.h"
 
 class Browser;
@@ -26,7 +26,7 @@
 // Interface for the showing of the dropdown menu for the Back/Forward buttons.
 // Actual implementations are platform-specific.
 ///////////////////////////////////////////////////////////////////////////////
-class BackForwardMenuModel : public menus::MenuModel {
+class BackForwardMenuModel : public ui::MenuModel {
  public:
   // These are IDs used to identify individual UI elements within the
   // browser window using View::GetViewByID.
@@ -50,11 +50,11 @@
   virtual string16 GetLabelAt(int index) const;
   virtual bool IsItemDynamicAt(int index) const;
   virtual bool GetAcceleratorAt(int index,
-                                menus::Accelerator* accelerator) const;
+                                ui::Accelerator* accelerator) const;
   virtual bool IsItemCheckedAt(int index) const;
   virtual int GetGroupIdAt(int index) const;
   virtual bool GetIconAt(int index, SkBitmap* icon) const;
-  virtual menus::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const;
+  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const;
   virtual bool IsEnabledAt(int index) const;
   virtual MenuModel* GetSubmenuModelAt(int index) const;
   virtual void HighlightChangedTo(int index);
diff --git a/chrome/browser/ui/toolbar/encoding_menu_controller.cc b/chrome/browser/ui/toolbar/encoding_menu_controller.cc
index 177aa28..d28a437 100644
--- a/chrome/browser/ui/toolbar/encoding_menu_controller.cc
+++ b/chrome/browser/ui/toolbar/encoding_menu_controller.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -14,6 +13,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 const int EncodingMenuController::kValidEncodingIds[] = {
     IDC_ENCODING_UTF8,
diff --git a/chrome/browser/ui/toolbar/toolbar_model.cc b/chrome/browser/ui/toolbar/toolbar_model.cc
index 98c392a..b8091a3 100644
--- a/chrome/browser/ui/toolbar/toolbar_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model.cc
@@ -53,9 +53,11 @@
   // Note that we can't unescape spaces here, because if the user copies this
   // and pastes it into another program, that program may think the URL ends at
   // the space.
-  return AutocompleteInput::FormattedStringWithEquivalentMeaning(url,
-      UTF16ToWideHack(net::FormatUrl(url, languages, net::kFormatUrlOmitAll,
-                                     UnescapeRule::NORMAL, NULL, NULL, NULL)));
+  return UTF16ToWideHack(
+      AutocompleteInput::FormattedStringWithEquivalentMeaning(
+          url,
+          net::FormatUrl(url, languages, net::kFormatUrlOmitAll,
+                         UnescapeRule::NORMAL, NULL, NULL, NULL)));
 }
 
 ToolbarModel::SecurityLevel ToolbarModel::GetSecurityLevel() const {
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index a68922f..dd4591a 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,9 +7,6 @@
 #include <algorithm>
 #include <cmath>
 
-#include "app/l10n_util.h"
-#include "app/menus/button_menu_item_model.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/i18n/number_formatting.h"
 #include "base/string_number_conversions.h"
@@ -19,8 +16,8 @@
 #include "chrome/browser/background_page_tracker.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/defaults.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
@@ -33,13 +30,17 @@
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/profiling.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/button_menu_item_model.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_LINUX)
 #include <gtk/gtk.h>
-#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #endif
 
 #if defined(OS_MACOSX)
@@ -59,7 +60,7 @@
 // EncodingMenuModel
 
 EncodingMenuModel::EncodingMenuModel(Browser* browser)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       browser_(browser) {
   Build();
 }
@@ -116,7 +117,7 @@
 
 bool EncodingMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   return false;
 }
 
@@ -127,7 +128,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ZoomMenuModel
 
-ZoomMenuModel::ZoomMenuModel(menus::SimpleMenuModel::Delegate* delegate)
+ZoomMenuModel::ZoomMenuModel(ui::SimpleMenuModel::Delegate* delegate)
     : SimpleMenuModel(delegate) {
   Build();
 }
@@ -144,7 +145,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ToolsMenuModel
 
-ToolsMenuModel::ToolsMenuModel(menus::SimpleMenuModel::Delegate* delegate,
+ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate* delegate,
                                Browser* browser)
     : SimpleMenuModel(delegate) {
   Build(browser);
@@ -171,10 +172,10 @@
   AddItemWithStringId(IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA);
 
   AddSeparator();
-#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_LINUX)
+
   AddItemWithStringId(IDC_FEEDBACK, IDS_FEEDBACK);
+
   AddSeparator();
-#endif
 
   encoding_menu_model_.reset(new EncodingMenuModel(browser));
   AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
@@ -184,14 +185,19 @@
     AddItemWithStringId(IDC_DEV_TOOLS, IDS_DEV_TOOLS);
     AddItemWithStringId(IDC_DEV_TOOLS_CONSOLE, IDS_DEV_TOOLS_CONSOLE);
   }
+
+#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
+  AddSeparator();
+  AddCheckItemWithStringId(IDC_PROFILING_ENABLED, IDS_PROFILING_ENABLED);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // WrenchMenuModel
 
-WrenchMenuModel::WrenchMenuModel(menus::AcceleratorProvider* provider,
+WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider* provider,
                                  Browser* browser)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       provider_(provider),
       browser_(browser),
       tabstrip_model_(browser_->tabstrip_model()) {
@@ -224,27 +230,6 @@
          command_id == IDC_VIEW_BACKGROUND_PAGES;
 }
 
-bool WrenchMenuModel::GetIconForCommandId(int command_id,
-                                          SkBitmap* bitmap) const {
-  switch (command_id) {
-    case IDC_VIEW_BACKGROUND_PAGES: {
-      int num_pages = BackgroundPageTracker::GetInstance()->
-          GetUnacknowledgedBackgroundPageCount();
-      if (num_pages > 0) {
-        *bitmap = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
-            IDR_BACKGROUND_MENU);
-        return true;
-      } else {
-        // No icon.
-        return false;
-      }
-    }
-    default:
-      // No icon for other dynamic menu items.
-      return false;
-  }
-}
-
 string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const {
   switch (command_id) {
     case IDC_SYNC_BOOKMARKS:
@@ -279,20 +264,14 @@
 bool WrenchMenuModel::IsCommandIdChecked(int command_id) const {
   if (command_id == IDC_SHOW_BOOKMARK_BAR) {
     return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
+  } else if (command_id == IDC_PROFILING_ENABLED) {
+    return Profiling::BeingProfiled();
   }
 
   return false;
 }
 
 bool WrenchMenuModel::IsCommandIdEnabled(int command_id) const {
-#if defined(OS_CHROMEOS)
-  // Special case because IDC_NEW_WINDOW item should be disabled in BWSI mode,
-  // but accelerator should work.
-  if (command_id == IDC_NEW_WINDOW &&
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession))
-    return false;
-#endif
-
   return browser_->command_updater()->IsCommandEnabled(command_id);
 }
 
@@ -321,7 +300,7 @@
 
 bool WrenchMenuModel::GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) {
+      ui::Accelerator* accelerator) {
   return provider_->GetAcceleratorForCommandId(command_id, accelerator);
 }
 
@@ -334,7 +313,8 @@
   UpdateZoomControls();
 }
 
-void WrenchMenuModel::TabReplacedAt(TabContentsWrapper* old_contents,
+void WrenchMenuModel::TabReplacedAt(TabStripModel* tab_strip_model,
+                                    TabContentsWrapper* old_contents,
                                     TabContentsWrapper* new_contents,
                                     int index) {
   UpdateZoomControls();
@@ -362,7 +342,7 @@
 
 // For testing.
 WrenchMenuModel::WrenchMenuModel()
-    : ALLOW_THIS_IN_INITIALIZER_LIST(menus::SimpleMenuModel(this)),
+    : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
       provider_(NULL),
       browser_(NULL),
       tabstrip_model_(NULL) {
@@ -371,15 +351,19 @@
 void WrenchMenuModel::Build() {
   AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
   AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
-  AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW,
-                             IDS_NEW_INCOGNITO_WINDOW);
+#if defined(OS_CHROMEOS)
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession))
+    AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
+#else
+  AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
+#endif
 
   AddSeparator();
 #if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(TOOLKIT_VIEWS))
   // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the
   // layout for this menu item in Toolbar.xib. It does, however, use the
   // command_id value from AddButtonItem() to identify this special item.
-  edit_menu_item_model_.reset(new menus::ButtonMenuItemModel(IDS_EDIT, this));
+  edit_menu_item_model_.reset(new ui::ButtonMenuItemModel(IDS_EDIT, this));
   edit_menu_item_model_->AddGroupItemWithStringId(IDC_CUT, IDS_CUT);
   edit_menu_item_model_->AddGroupItemWithStringId(IDC_COPY, IDS_COPY);
   edit_menu_item_model_->AddGroupItemWithStringId(IDC_PASTE, IDS_PASTE);
@@ -393,7 +377,7 @@
 #if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(TOOLKIT_VIEWS))
   // WARNING: See above comment.
   zoom_menu_item_model_.reset(
-      new menus::ButtonMenuItemModel(IDS_ZOOM_MENU, this));
+      new ui::ButtonMenuItemModel(IDS_ZOOM_MENU, this));
   zoom_menu_item_model_->AddGroupItemWithStringId(
       IDC_ZOOM_MINUS, IDS_ZOOM_MINUS2);
   zoom_menu_item_model_->AddButtonLabel(IDC_ZOOM_PERCENT_DISPLAY,
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.h b/chrome/browser/ui/toolbar/wrench_menu_model.h
index 2690ea9..3b95383 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.h
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_UI_TOOLBAR_WRENCH_MENU_MODEL_H_
 #pragma once
 
-#include "app/menus/accelerator.h"
-#include "app/menus/button_menu_item_model.h"
-#include "app/menus/simple_menu_model.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/tabs/tab_strip_model_observer.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "ui/base/models/accelerator.h"
+#include "ui/base/models/button_menu_item_model.h"
+#include "ui/base/models/simple_menu_model.h"
 
 class Browser;
 class TabStripModel;
@@ -22,17 +22,17 @@
 }  // namespace
 
 // A menu model that builds the contents of an encoding menu.
-class EncodingMenuModel : public menus::SimpleMenuModel,
-                          public menus::SimpleMenuModel::Delegate {
+class EncodingMenuModel : public ui::SimpleMenuModel,
+                          public ui::SimpleMenuModel::Delegate {
  public:
   explicit EncodingMenuModel(Browser* browser);
   virtual ~EncodingMenuModel();
 
-  // Overridden from menus::SimpleMenuModel::Delegate:
+  // Overridden from ui::SimpleMenuModel::Delegate:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
  private:
@@ -44,9 +44,9 @@
 };
 
 // A menu model that builds the contents of the zoom menu.
-class ZoomMenuModel : public menus::SimpleMenuModel {
+class ZoomMenuModel : public ui::SimpleMenuModel {
  public:
-  explicit ZoomMenuModel(menus::SimpleMenuModel::Delegate* delegate);
+  explicit ZoomMenuModel(ui::SimpleMenuModel::Delegate* delegate);
   virtual ~ZoomMenuModel();
 
  private:
@@ -55,9 +55,9 @@
   DISALLOW_COPY_AND_ASSIGN(ZoomMenuModel);
 };
 
-class ToolsMenuModel : public menus::SimpleMenuModel {
+class ToolsMenuModel : public ui::SimpleMenuModel {
  public:
-  ToolsMenuModel(menus::SimpleMenuModel::Delegate* delegate, Browser* browser);
+  ToolsMenuModel(ui::SimpleMenuModel::Delegate* delegate, Browser* browser);
   virtual ~ToolsMenuModel();
 
  private:
@@ -69,13 +69,13 @@
 };
 
 // A menu model that builds the contents of the wrench menu.
-class WrenchMenuModel : public menus::SimpleMenuModel,
-                        public menus::SimpleMenuModel::Delegate,
-                        public menus::ButtonMenuItemModel::Delegate,
+class WrenchMenuModel : public ui::SimpleMenuModel,
+                        public ui::SimpleMenuModel::Delegate,
+                        public ui::ButtonMenuItemModel::Delegate,
                         public TabStripModelObserver,
                         public NotificationObserver {
  public:
-  WrenchMenuModel(menus::AcceleratorProvider* provider, Browser* browser);
+  WrenchMenuModel(ui::AcceleratorProvider* provider, Browser* browser);
   virtual ~WrenchMenuModel();
 
   // Overridden for ButtonMenuItemModel::Delegate:
@@ -84,22 +84,23 @@
   // Overridden for both ButtonMenuItemModel::Delegate and SimpleMenuModel:
   virtual bool IsItemForCommandIdDynamic(int command_id) const;
   virtual string16 GetLabelForCommandId(int command_id) const;
-  virtual bool GetIconForCommandId(int command_id, SkBitmap* icon) const;
   virtual void ExecuteCommand(int command_id);
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool IsCommandIdVisible(int command_id) const;
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator);
+      ui::Accelerator* accelerator);
 
   // Overridden from TabStripModelObserver:
   virtual void TabSelectedAt(TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int index,
                              bool user_gesture);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
-                             TabContentsWrapper* new_contents, int index);
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index);
   virtual void TabStripModelDeleted();
 
   // Overridden from NotificationObserver:
@@ -128,8 +129,8 @@
   string16 GetSyncMenuLabel() const;
 
   // Models for the special menu items with buttons.
-  scoped_ptr<menus::ButtonMenuItemModel> edit_menu_item_model_;
-  scoped_ptr<menus::ButtonMenuItemModel> zoom_menu_item_model_;
+  scoped_ptr<ui::ButtonMenuItemModel> edit_menu_item_model_;
+  scoped_ptr<ui::ButtonMenuItemModel> zoom_menu_item_model_;
 
   // Label of the zoom label in the zoom menu item.
   string16 zoom_label_;
@@ -137,7 +138,7 @@
   // Tools menu.
   scoped_ptr<ToolsMenuModel> tools_menu_model_;
 
-  menus::AcceleratorProvider* provider_;  // weak
+  ui::AcceleratorProvider* provider_;  // weak
 
   Browser* browser_;  // weak
   TabStripModel* tabstrip_model_; // weak
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
index 92a8125..9e88848 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
 
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/menu_model_test.h"
 #include "chrome/test/testing_profile.h"
@@ -12,12 +13,12 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 class WrenchMenuModelTest : public BrowserWithTestWindowTest,
-                            public menus::AcceleratorProvider {
+                            public ui::AcceleratorProvider {
  public:
   // Don't handle accelerators.
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) { return false; }
+      ui::Accelerator* accelerator) { return false; }
 };
 
 // Copies parts of MenuModelTest::Delegate and combines them with the
@@ -25,7 +26,7 @@
 // not derived from SimpleMenuModel.
 class TestWrenchMenuModel : public WrenchMenuModel {
  public:
-  TestWrenchMenuModel(menus::AcceleratorProvider* provider,
+  TestWrenchMenuModel(ui::AcceleratorProvider* provider,
                       Browser* browser)
       : WrenchMenuModel(provider, browser),
         execute_count_(0),
@@ -33,7 +34,7 @@
         enable_count_(0) {
   }
 
-  // Testing overrides to menus::SimpleMenuModel::Delegate:
+  // Testing overrides to ui::SimpleMenuModel::Delegate:
   virtual bool IsCommandIdChecked(int command_id) const {
     bool val = WrenchMenuModel::IsCommandIdChecked(command_id);
     if (val)
@@ -79,13 +80,13 @@
   // the delegate as well. Use the first submenu as the tools one.
   int toolsModelIndex = -1;
   for (int i = 0; i < itemCount; ++i) {
-    if (model.GetTypeAt(i) == menus::MenuModel::TYPE_SUBMENU) {
+    if (model.GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
       toolsModelIndex = i;
       break;
     }
   }
   EXPECT_GT(toolsModelIndex, -1);
-  menus::MenuModel* toolsModel = model.GetSubmenuModelAt(toolsModelIndex);
+  ui::MenuModel* toolsModel = model.GetSubmenuModelAt(toolsModelIndex);
   EXPECT_TRUE(toolsModel);
   EXPECT_GT(toolsModel->GetItemCount(), 2);
   toolsModel->ActivatedAt(2);
diff --git a/chrome/browser/ui/touch/frame/keyboard_container_view.cc b/chrome/browser/ui/touch/frame/keyboard_container_view.cc
new file mode 100644
index 0000000..d11bdfb
--- /dev/null
+++ b/chrome/browser/ui/touch/frame/keyboard_container_view.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/touch/frame/keyboard_container_view.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/ui/views/dom_view.h"
+#include "chrome/common/url_constants.h"
+
+namespace {
+
+// Make the provided view and all of its descendents unfocusable.
+void MakeViewHierarchyUnfocusable(views::View* view) {
+  view->SetFocusable(false);
+  for (int i = 0; i < view->child_count(); ++i) {
+    MakeViewHierarchyUnfocusable(view->GetChildViewAt(i));
+  }
+}
+
+}  // namepsace
+
+///////////////////////////////////////////////////////////////////////////////
+// KeyboardContainerView, public:
+
+KeyboardContainerView::KeyboardContainerView(Profile* profile)
+    : dom_view_(new DOMView) {
+  GURL keyboard_url(chrome::kChromeUIKeyboardURL);
+  dom_view_->Init(profile,
+      SiteInstance::CreateSiteInstanceForURL(profile, keyboard_url));
+  dom_view_->LoadURL(keyboard_url);
+
+  dom_view_->SetVisible(true);
+  AddChildView(dom_view_);
+}
+
+KeyboardContainerView::~KeyboardContainerView() {
+}
+
+void KeyboardContainerView::Layout() {
+  // TODO(bryeung): include a border between the keyboard and the client view
+  dom_view_->SetBounds(0, 0, width(), height());
+}
+
+void KeyboardContainerView::ViewHierarchyChanged(bool is_add,
+                                                 View* parent,
+                                                 View* child) {
+  if (is_add)
+    MakeViewHierarchyUnfocusable(child);
+}
+
diff --git a/chrome/browser/ui/touch/frame/keyboard_container_view.h b/chrome/browser/ui/touch/frame/keyboard_container_view.h
new file mode 100644
index 0000000..a5e2040
--- /dev/null
+++ b/chrome/browser/ui/touch/frame/keyboard_container_view.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TOUCH_FRAME_KEYBOARD_CONTAINER_VIEW_H_
+#define CHROME_BROWSER_UI_TOUCH_FRAME_KEYBOARD_CONTAINER_VIEW_H_
+#pragma once
+
+#include "views/view.h"
+
+class DOMView;
+class Profile;
+
+// A class that contains and decorates the virtual keyboard.
+//
+// This class is also responsible for managing focus of all views related to
+// the keyboard to prevent them from interfering with the ClientView.
+class KeyboardContainerView : public views::View {
+ public:
+  explicit KeyboardContainerView(Profile* profile);
+  virtual ~KeyboardContainerView();
+
+  // Overridden from views::View
+  virtual void Layout();
+
+ protected:
+  // Overridden from views::View
+  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
+
+ private:
+  DOMView* dom_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(KeyboardContainerView);
+};
+
+#endif  // CHROME_BROWSER_UI_TOUCH_FRAME_KEYBOARD_CONTAINER_VIEW_H_
diff --git a/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc b/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc
index cba6353..c2d915d 100644
--- a/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc
+++ b/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc
@@ -4,25 +4,30 @@
 
 #include "chrome/browser/ui/touch/frame/touch_browser_frame_view.h"
 
-#include <algorithm>
-
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_views.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/views/dom_view.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/touch/frame/keyboard_container_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
-#include "chrome/common/url_constants.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
+#include "views/controls/textfield/textfield.h"
 
 namespace {
 
 const int kKeyboardHeight = 300;
 
+PropertyAccessor<bool>* GetFocusedStateAccessor() {
+  static PropertyAccessor<bool> state;
+  return &state;
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -32,6 +37,7 @@
                                              BrowserView* browser_view)
     : OpaqueBrowserFrameView(frame, browser_view),
       keyboard_showing_(false),
+      focus_listener_added_(false),
       keyboard_(NULL) {
   registrar_.Add(this,
                  NotificationType::NAV_ENTRY_COMMITTED,
@@ -39,9 +45,15 @@
   registrar_.Add(this,
                  NotificationType::FOCUS_CHANGED_IN_PAGE,
                  NotificationService::AllSources());
+  registrar_.Add(this,
+                 NotificationType::TAB_CONTENTS_DESTROYED,
+                 NotificationService::AllSources());
+
+  browser_view->browser()->tabstrip_model()->AddObserver(this);
 }
 
 TouchBrowserFrameView::~TouchBrowserFrameView() {
+  browser_view()->browser()->tabstrip_model()->RemoveObserver(this);
 }
 
 void TouchBrowserFrameView::Layout() {
@@ -50,9 +62,18 @@
   if (!keyboard_)
     return;
 
-  keyboard_->SetBounds(GetBoundsForReservedArea());
   keyboard_->SetVisible(keyboard_showing_);
-  keyboard_->Layout();
+  keyboard_->SetBoundsRect(GetBoundsForReservedArea());
+}
+
+void TouchBrowserFrameView::FocusWillChange(views::View* focused_before,
+                                            views::View* focused_now) {
+  VirtualKeyboardType before = DecideKeyboardStateForView(focused_before);
+  VirtualKeyboardType now = DecideKeyboardStateForView(focused_now);
+  if (before != now) {
+    // TODO(varunjain): support other types of keyboard.
+    UpdateKeyboardAndLayout(now == GENERIC);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -64,6 +85,24 @@
   return 0;
 }
 
+void TouchBrowserFrameView::ViewHierarchyChanged(bool is_add,
+                                                 View* parent,
+                                                 View* child) {
+  OpaqueBrowserFrameView::ViewHierarchyChanged(is_add, parent, child);
+  if (!GetFocusManager())
+    return;
+
+  if (is_add && !focus_listener_added_) {
+    // Add focus listener when this view is added to the hierarchy.
+    GetFocusManager()->AddFocusChangeListener(this);
+    focus_listener_added_ = true;
+  } else if (!is_add && focus_listener_added_) {
+    // Remove focus listener when this view is removed from the hierarchy.
+    GetFocusManager()->RemoveFocusChangeListener(this);
+    focus_listener_added_ = false;
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // TouchBrowserFrameView, private:
 
@@ -71,16 +110,10 @@
   if (keyboard_)
     return;
 
-  keyboard_ = new DOMView;
-
   Profile* keyboard_profile = browser_view()->browser()->profile();
   DCHECK(keyboard_profile) << "Profile required for virtual keyboard.";
 
-  GURL keyboard_url(chrome::kChromeUIKeyboardURL);
-  keyboard_->Init(keyboard_profile,
-      SiteInstance::CreateSiteInstanceForURL(keyboard_profile, keyboard_url));
-  keyboard_->LoadURL(keyboard_url);
-
+  keyboard_ = new KeyboardContainerView(keyboard_profile);
   keyboard_->SetVisible(false);
   AddChildView(keyboard_);
 }
@@ -98,7 +131,7 @@
 
   // Because the NonClientFrameView is a sibling of the ClientView, we rely on
   // the parent to resize the ClientView instead of resizing it directly.
-  GetParent()->Layout();
+  parent()->Layout();
 
   // The keyboard that pops up may end up hiding the text entry. So make sure
   // the renderer scrolls when necessary to keep the textfield visible.
@@ -109,6 +142,35 @@
   }
 }
 
+TouchBrowserFrameView::VirtualKeyboardType
+    TouchBrowserFrameView::DecideKeyboardStateForView(views::View* view) {
+  if (!view)
+    return NONE;
+
+  std::string cname = view->GetClassName();
+  if (cname == views::Textfield::kViewClassName) {
+    return GENERIC;
+  } else if (cname == RenderWidgetHostViewViews::kViewClassName) {
+    TabContents* contents = browser_view()->browser()->GetSelectedTabContents();
+    bool* editable = contents ? GetFocusedStateAccessor()->GetProperty(
+        contents->property_bag()) : NULL;
+    if (editable && *editable)
+      return GENERIC;
+  }
+  return NONE;
+}
+
+void TouchBrowserFrameView::TabSelectedAt(TabContentsWrapper* old_contents,
+                                          TabContentsWrapper* new_contents,
+                                          int index,
+                                          bool user_gesture) {
+  TabContents* contents = new_contents->tab_contents();
+  bool* editable = GetFocusedStateAccessor()->GetProperty(
+      contents->property_bag());
+  UpdateKeyboardAndLayout(editable ? *editable : false);
+}
+
+
 void TouchBrowserFrameView::Observe(NotificationType type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
@@ -116,16 +178,26 @@
   if (type == NotificationType::FOCUS_CHANGED_IN_PAGE) {
     // Only modify the keyboard state if the currently active tab sent the
     // notification.
-    const TabContents* tab_contents = browser->GetSelectedTabContents();
-    if (tab_contents &&
-        tab_contents->render_view_host() ==
-            Source<RenderViewHost>(source).ptr())
-      UpdateKeyboardAndLayout(*Details<const bool>(details).ptr());
+    const TabContents* current_tab = browser->GetSelectedTabContents();
+    TabContents* source_tab = Source<TabContents>(source).ptr();
+    const bool editable = *Details<const bool>(details).ptr();
+
+    if (current_tab == source_tab) {
+      UpdateKeyboardAndLayout(editable);
+    }
+
+    // Save the state of the focused field so that the keyboard visibility
+    // can be determined after tab switching.
+    GetFocusedStateAccessor()->SetProperty(
+        source_tab->property_bag(), editable);
   } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
     Browser* source_browser = Browser::GetBrowserForController(
         Source<NavigationController>(source).ptr(), NULL);
     // If the Browser for the keyboard has navigated, hide the keyboard.
     if (source_browser == browser)
       UpdateKeyboardAndLayout(false);
+  } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
+    GetFocusedStateAccessor()->DeleteProperty(
+        Source<TabContents>(source).ptr()->property_bag());
   }
 }
diff --git a/chrome/browser/ui/touch/frame/touch_browser_frame_view.h b/chrome/browser/ui/touch/frame/touch_browser_frame_view.h
index 7fb5703..e5700f4 100644
--- a/chrome/browser/ui/touch/frame/touch_browser_frame_view.h
+++ b/chrome/browser/ui/touch/frame/touch_browser_frame_view.h
@@ -7,18 +7,28 @@
 #pragma once
 
 #include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h"
+#include "chrome/browser/tabs/tab_strip_model_observer.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
+#include "views/focus/focus_manager.h"
 
 class BrowserFrame;
 class BrowserView;
-class DOMView;
+class KeyboardContainerView;
 class NotificationDetails;
 class NotificationSource;
 
 class TouchBrowserFrameView : public OpaqueBrowserFrameView,
+                              public views::FocusChangeListener,
+                              public TabStripModelObserver,
                               public NotificationObserver {
  public:
+  enum VirtualKeyboardType {
+    NONE,
+    GENERIC,
+    URL,
+  };
+
   // Constructs a non-client view for an BrowserFrame.
   TouchBrowserFrameView(BrowserFrame* frame, BrowserView* browser_view);
   virtual ~TouchBrowserFrameView();
@@ -26,13 +36,25 @@
   // Overridden from OpaqueBrowserFrameView
   virtual void Layout();
 
+  // views::FocusChangeListener implementation
+  virtual void FocusWillChange(views::View* focused_before,
+                               views::View* focused_now);
+
  protected:
   // Overridden from OpaqueBrowserFrameView
   virtual int GetReservedHeight() const;
+  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
 
  private:
   virtual void InitVirtualKeyboard();
   virtual void UpdateKeyboardAndLayout(bool should_show_keyboard);
+  virtual VirtualKeyboardType DecideKeyboardStateForView(views::View* view);
+
+  // Overrridden from TabStripModelObserver.
+  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
+                             TabContentsWrapper* new_contents,
+                             int index,
+                             bool user_gesture);
 
   // Overridden from NotificationObserver.
   virtual void Observe(NotificationType type,
@@ -40,7 +62,8 @@
                        const NotificationDetails& details);
 
   bool keyboard_showing_;
-  DOMView* keyboard_;
+  bool focus_listener_added_;
+  KeyboardContainerView* keyboard_;
   NotificationRegistrar registrar_;
 
   DISALLOW_COPY_AND_ASSIGN(TouchBrowserFrameView);
diff --git a/chrome/browser/ui/touch/tabs/tab_strip_factory.cc b/chrome/browser/ui/touch/tabs/tab_strip_factory.cc
new file mode 100644
index 0000000..aeef15f
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/tab_strip_factory.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2011 The Chromium 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 only compiled when touchui is defined.
+
+#include "chrome/browser/ui/views/tabs/tab_strip_factory.h"
+
+#include "chrome/browser/ui/touch/tabs/touch_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
+
+// The implmentation of CreateTabStrip for touchui creates a TouchTabStrip
+BaseTabStrip* CreateTabStrip(BrowserTabStripController* tabstrip_controller,
+                             bool use_vertical_tabs) {
+  return new TouchTabStrip(tabstrip_controller);
+}
+
diff --git a/chrome/browser/ui/touch/tabs/touch_tab.cc b/chrome/browser/ui/touch/tabs/touch_tab.cc
new file mode 100644
index 0000000..b4df099
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/touch_tab.cc
@@ -0,0 +1,234 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/touch/tabs/touch_tab.h"
+
+#include "chrome/browser/themes/browser_theme_provider.h"
+#include "grit/app_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+static const int kLeftPadding = 16;
+static const int kRightPadding = 15;
+static const int kDropShadowHeight = 2;
+static const int kTouchFaviconSize = 32;
+
+TouchTab::TouchTabImage TouchTab::tab_alpha = {0};
+TouchTab::TouchTabImage TouchTab::tab_active = {0};
+TouchTab::TouchTabImage TouchTab::tab_inactive = {0};
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchTab, public:
+
+TouchTab::TouchTab(TabController* controller)
+    : BaseTab(controller) {
+  InitTabResources();
+}
+
+TouchTab::~TouchTab() {
+}
+
+// static
+gfx::Size TouchTab::GetMinimumUnselectedSize() {
+  InitTabResources();
+
+  gfx::Size minimum_size;
+  minimum_size.set_width(kLeftPadding + kRightPadding);
+  minimum_size.set_height(32);
+  return minimum_size;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchTab, views::View overrides:
+
+void TouchTab::Paint(gfx::Canvas* canvas) {
+  // Don't paint if we're narrower than we can render correctly. (This should
+  // only happen during animations).
+  if (width() < GetMinimumUnselectedSize().width() && !data().mini)
+    return;
+
+  PaintTabBackground(canvas);
+
+  SkColor title_color = GetThemeProvider()->
+      GetColor(IsSelected() ?
+          BrowserThemeProvider::COLOR_TAB_TEXT :
+          BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT);
+
+  PaintTitle(canvas, title_color);
+  PaintIcon(canvas);
+}
+
+void TouchTab::Layout() {
+  gfx::Rect local_bounds = GetContentsBounds();
+  TouchTabImage* tab_image = &tab_active;
+  TouchTabImage* alpha = &tab_alpha;
+  int image_height = alpha->image_l->height();
+  int x_base = tab_image->image_l->width();
+  int y_base = height() - image_height;
+  int center_width = width() - tab_image->l_width - tab_image->r_width;
+  if (center_width < 0)
+    center_width = 0;
+  title_bounds_ = gfx::Rect(x_base, y_base, center_width, image_height);
+  favicon_bounds_ = local_bounds;
+}
+
+bool TouchTab::HasHitTestMask() const {
+  return true;
+}
+
+void TouchTab::GetHitTestMask(gfx::Path* path) const {
+  DCHECK(path);
+
+  SkScalar h = SkIntToScalar(height());
+  SkScalar w = SkIntToScalar(width());
+
+  path->moveTo(0, h);
+  path->lineTo(0, 0);
+  path->lineTo(w, 0);
+  path->lineTo(w, h);
+  path->lineTo(0, h);
+  path->close();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchTab, private:
+
+void TouchTab::PaintTabBackground(gfx::Canvas* canvas) {
+  if (IsSelected()) {
+    PaintActiveTabBackground(canvas);
+  }
+}
+
+void TouchTab::PaintActiveTabBackground(gfx::Canvas* canvas) {
+  int offset = GetMirroredX() + background_offset_.x();
+  ThemeProvider* tp = GetThemeProvider();
+  if (!tp)
+    NOTREACHED() << "Unable to get theme provider";
+
+  SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
+
+  TouchTabImage* tab_image = &tab_active;
+  TouchTabImage* alpha = &tab_alpha;
+
+  // Draw left edge.
+  int image_height = alpha->image_l->height();
+  int y_base = height() - image_height;
+  SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
+      *tab_bg, offset, 0, tab_image->l_width, image_height);
+  SkBitmap theme_l =
+      SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
+  canvas->DrawBitmapInt(theme_l, 0, y_base);
+
+  // Draw right edge.
+  SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
+      offset + width() - tab_image->r_width, 0,
+      tab_image->r_width, image_height);
+  SkBitmap theme_r =
+      SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
+  canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, y_base);
+
+  // Draw center.  Instead of masking out the top portion we simply skip over it
+  // by incrementing by kDropShadowHeight, since it's a simple rectangle.
+  canvas->TileImageInt(*tab_bg,
+     offset + tab_image->l_width,
+     kDropShadowHeight + tab_image->y_offset,
+     tab_image->l_width,
+     y_base + kDropShadowHeight + tab_image->y_offset,
+     width() - tab_image->l_width - tab_image->r_width,
+     height() - kDropShadowHeight - tab_image->y_offset);
+
+  // Now draw the highlights/shadows around the tab edge.
+  canvas->DrawBitmapInt(*tab_image->image_l, 0, y_base);
+  canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, y_base,
+      width() - tab_image->l_width - tab_image->r_width, image_height);
+  canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width,
+                        y_base);
+}
+
+void TouchTab::PaintIcon(gfx::Canvas* canvas) {
+  // TODO(wyck): use thumbnailer to get better page images
+  int x = favicon_bounds_.x();
+  int y = favicon_bounds_.y();
+
+  TouchTabImage* tab_image = &tab_active;
+  int x_base = tab_image->image_l->width();
+
+  x += x_base;
+
+  if (base::i18n::IsRTL()) {
+    x = width() - x -
+        (data().favicon.isNull() ? kFavIconSize : data().favicon.width());
+  }
+
+  int favicon_x = x;
+  if (!data().favicon.isNull() && data().favicon.width() != kFavIconSize)
+    favicon_x += (data().favicon.width() - kFavIconSize) / 2;
+
+  if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
+    ThemeProvider* tp = GetThemeProvider();
+    SkBitmap frames(*tp->GetBitmapNamed(
+        (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
+        IDR_THROBBER_WAITING : IDR_THROBBER));
+    int image_size = frames.height();
+    int image_offset = loading_animation_frame() * image_size;
+    canvas->DrawBitmapInt(frames, image_offset, 0, image_size, image_size, x, y,
+                          kTouchFaviconSize, kTouchFaviconSize, false);
+  } else {
+    canvas->Save();
+    canvas->ClipRectInt(0, 0, width(), height());
+    if (should_display_crashed_favicon()) {
+      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+      SkBitmap crashed_fav_icon(*rb.GetBitmapNamed(IDR_SAD_FAVICON));
+      canvas->DrawBitmapInt(crashed_fav_icon, 0, 0, crashed_fav_icon.width(),
+          crashed_fav_icon.height(), x, y + fav_icon_hiding_offset(),
+          kTouchFaviconSize, kTouchFaviconSize, true);
+    } else {
+      if (!data().favicon.isNull()) {
+        canvas->DrawBitmapInt(data().favicon, 0, 0,
+                              data().favicon.width(), data().favicon.height(),
+                              x, y + fav_icon_hiding_offset(),
+                              kTouchFaviconSize, kTouchFaviconSize, true);
+      }
+    }
+    canvas->Restore();
+  }
+}
+
+// static
+void TouchTab::InitTabResources() {
+  static bool initialized = false;
+  if (initialized)
+    return;
+
+  initialized = true;
+
+  // Load the tab images once now, and maybe again later if the theme changes.
+  LoadTabImages();
+}
+
+
+// static
+void TouchTab::LoadTabImages() {
+  // We're not letting people override tab images just yet.
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+  tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
+  tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
+
+  tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
+  tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
+  tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
+  tab_active.l_width = tab_active.image_l->width();
+  tab_active.r_width = tab_active.image_r->width();
+
+  tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
+  tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
+  tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
+  tab_inactive.l_width = tab_inactive.image_l->width();
+  tab_inactive.r_width = tab_inactive.image_r->width();
+}
diff --git a/chrome/browser/ui/touch/tabs/touch_tab.h b/chrome/browser/ui/touch/tabs/touch_tab.h
new file mode 100644
index 0000000..bc7eb2f
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/touch_tab.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_H_
+#define CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_H_
+#pragma once
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/ui/views/tabs/base_tab.h"
+#include "ui/gfx/point.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// TouchTab
+//
+//  A View that renders a TouchTab in a TouchTabStrip
+//
+///////////////////////////////////////////////////////////////////////////////
+class TouchTab : public BaseTab {
+ public:
+  // The menu button's class name.
+  static const char kViewClassName[];
+
+  explicit TouchTab(TabController* controller);
+  virtual ~TouchTab();
+
+  // Set the background offset used to match the image in the inactive tab
+  // to the frame image.
+  void set_background_offset(const gfx::Point& offset) {
+    background_offset_ = offset;
+  }
+
+  // Returns the minimum possible size of a single unselected Tab.
+  static gfx::Size GetMinimumUnselectedSize();
+
+ protected:
+  virtual const gfx::Rect& title_bounds() const { return title_bounds_; }
+
+ private:
+  // Overridden from views::View:
+  virtual void Paint(gfx::Canvas* canvas);
+  virtual void Layout();
+  virtual bool HasHitTestMask() const;
+  virtual void GetHitTestMask(gfx::Path* path) const;
+
+  // Paint various portions of the Tab
+  void PaintTabBackground(gfx::Canvas* canvas);
+  void PaintIcon(gfx::Canvas* canvas);
+  void PaintActiveTabBackground(gfx::Canvas* canvas);
+
+  // TODO(wyck): will eventually add OnTouchEvent when the Touch Tab Strip
+  // requires touch-specific event handling.
+
+  // Performs a one-time initialization of static resources such as tab images.
+  static void InitTabResources();
+
+  // Loads the images to be used for the tab background.
+  static void LoadTabImages();
+
+  // the bounds of the title text
+  gfx::Rect title_bounds_;
+
+  // the bounds of the favicon
+  gfx::Rect favicon_bounds_;
+
+  // The offset used to paint the inactive background image.
+  gfx::Point background_offset_;
+
+  // 'l' is for left
+  // 'c' is for center
+  // 'r' is for right
+  struct TouchTabImage {
+    SkBitmap* image_l;
+    SkBitmap* image_c;
+    SkBitmap* image_r;
+    int l_width;
+    int r_width;
+    int y_offset;
+  };
+  static TouchTabImage tab_active;
+  static TouchTabImage tab_inactive;
+  static TouchTabImage tab_alpha;
+
+  DISALLOW_COPY_AND_ASSIGN(TouchTab);
+};
+
+#endif  // CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_H_
diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip.cc b/chrome/browser/ui/touch/tabs/touch_tab_strip.cc
new file mode 100644
index 0000000..b950fb0
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/touch_tab_strip.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/touch/tabs/touch_tab_strip.h"
+
+#include "chrome/browser/ui/touch/tabs/touch_tab.h"
+#include "chrome/browser/ui/view_ids.h"
+#include "ui/gfx/canvas_skia.h"
+#include "views/window/non_client_view.h"
+#include "views/window/window.h"
+
+static const int kTouchTabStripHeight = 64;
+static const int kTouchTabWidth = 64;
+static const int kTouchTabHeight = 64;
+
+TouchTabStrip::TouchTabStrip(TabStripController* controller)
+    : BaseTabStrip(controller, BaseTabStrip::HORIZONTAL_TAB_STRIP),
+      in_tab_close_(false) {
+  Init();
+}
+
+TouchTabStrip::~TouchTabStrip() {
+  // The animations may reference the tabs. Shut down the animation before we
+  // delete the tabs.
+  StopAnimating(false);
+
+  DestroyDragController();
+
+  // The children (tabs) may callback to us from their destructor. Delete them
+  // so that if they call back we aren't in a weird state.
+  RemoveAllChildViews(true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchTabStrip, BaseTabStrip implementation:
+
+void TouchTabStrip::SetBackgroundOffset(const gfx::Point& offset) {
+  for (int i = 0; i < tab_count(); ++i)
+    GetTabAtTabDataIndex(i)->set_background_offset(offset);
+}
+
+bool TouchTabStrip::IsPositionInWindowCaption(const gfx::Point& point) {
+  views::View* v = GetViewForPoint(point);
+
+  // If there is no control at this location, claim the hit was in the title
+  // bar to get a move action.
+  if (v == this)
+    return true;
+
+  // All other regions, should be considered part of the containing Window's
+  // client area so that regular events can be processed for them.
+  return false;
+}
+
+void TouchTabStrip::PrepareForCloseAt(int model_index) {
+  if (!in_tab_close_ && IsAnimating()) {
+    // Cancel any current animations. We do this as remove uses the current
+    // ideal bounds and we need to know ideal bounds is in a good state.
+    StopAnimating(true);
+  }
+
+  in_tab_close_ = true;
+}
+
+void TouchTabStrip::StartHighlight(int model_index) {
+}
+
+void TouchTabStrip::StopAllHighlighting() {
+}
+
+BaseTab* TouchTabStrip::CreateTabForDragging() {
+  return NULL;
+}
+
+void TouchTabStrip::RemoveTabAt(int model_index) {
+  StartRemoveTabAnimation(model_index);
+}
+
+void TouchTabStrip::SelectTabAt(int old_model_index, int new_model_index) {
+  SchedulePaint();
+}
+
+void TouchTabStrip::TabTitleChangedNotLoading(int model_index) {
+}
+
+BaseTab* TouchTabStrip::CreateTab() {
+  return new TouchTab(this);
+}
+
+void TouchTabStrip::StartInsertTabAnimation(int model_index, bool foreground) {
+  PrepareForAnimation();
+
+  in_tab_close_ = false;
+
+  GenerateIdealBounds();
+
+  int tab_data_index = ModelIndexToTabIndex(model_index);
+  BaseTab* tab = base_tab_at_tab_index(tab_data_index);
+  if (model_index == 0) {
+    tab->SetBounds(0, ideal_bounds(tab_data_index).y(), 0,
+                   ideal_bounds(tab_data_index).height());
+  } else {
+    BaseTab* last_tab = base_tab_at_tab_index(tab_data_index - 1);
+    tab->SetBounds(last_tab->bounds().right(),
+                   ideal_bounds(tab_data_index).y(), 0,
+                   ideal_bounds(tab_data_index).height());
+  }
+
+  AnimateToIdealBounds();
+}
+
+void TouchTabStrip::AnimateToIdealBounds() {
+  for (int i = 0; i < tab_count(); ++i) {
+    TouchTab* tab = GetTabAtTabDataIndex(i);
+    if (!tab->closing() && !tab->dragging())
+      bounds_animator().AnimateViewTo(tab, ideal_bounds(i));
+  }
+}
+
+bool TouchTabStrip::ShouldHighlightCloseButtonAfterRemove() {
+  return in_tab_close_;
+}
+
+void TouchTabStrip::GenerateIdealBounds() {
+  gfx::Rect bounds;
+  int tab_x = 0;
+  int tab_y = 0;
+  for (int i = 0; i < tab_count(); ++i) {
+    TouchTab* tab = GetTabAtTabDataIndex(i);
+    if (!tab->closing()) {
+      set_ideal_bounds(i, gfx::Rect(tab_x, tab_y, kTouchTabWidth,
+                                    kTouchTabHeight));
+      // offset the next tab to the right by the width of this tab
+      tab_x += kTouchTabWidth;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchTabStrip, views::View overrides:
+
+gfx::Size TouchTabStrip::GetPreferredSize() {
+  return gfx::Size(0, kTouchTabStripHeight);
+}
+
+void TouchTabStrip::PaintChildren(gfx::Canvas* canvas) {
+  // Tabs are painted in reverse order, so they stack to the left.
+  TouchTab* selected_tab = NULL;
+  TouchTab* dragging_tab = NULL;
+
+  for (int i = tab_count() - 1; i >= 0; --i) {
+    TouchTab* tab = GetTabAtTabDataIndex(i);
+    // We must ask the _Tab's_ model, not ourselves, because in some situations
+    // the model will be different to this object, e.g. when a Tab is being
+    // removed after its TabContents has been destroyed.
+    if (tab->dragging()) {
+      dragging_tab = tab;
+    } else if (!tab->IsSelected()) {
+      tab->ProcessPaint(canvas);
+    } else {
+      selected_tab = tab;
+    }
+  }
+
+  if (GetWindow()->GetNonClientView()->UseNativeFrame()) {
+    // Make sure unselected tabs are somewhat transparent.
+    SkPaint paint;
+    paint.setColor(SkColorSetARGB(200, 255, 255, 255));
+    paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+    paint.setStyle(SkPaint::kFill_Style);
+    canvas->DrawRectInt(0, 0, width(),
+        height() - 2,  // Visible region that overlaps the toolbar.
+        paint);
+  }
+
+  // Paint the selected tab last, so it overlaps all the others.
+  if (selected_tab)
+    selected_tab->ProcessPaint(canvas);
+
+  // And the dragged tab.
+  if (dragging_tab)
+    dragging_tab->ProcessPaint(canvas);
+}
+
+TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const {
+  return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchTabStrip, private:
+
+void TouchTabStrip::Init() {
+  SetID(VIEW_ID_TAB_STRIP);
+}
+
diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip.h b/chrome/browser/ui/touch/tabs/touch_tab_strip.h
new file mode 100644
index 0000000..8248493
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/touch_tab_strip.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_H_
+#define CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_H_
+#pragma once
+
+#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
+
+class TouchTab;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// TouchTabStrip
+//
+//  A View that represents the TabStripModel. The TouchTabStrip has the
+//  following responsibilities:
+//    - It implements the TabStripModelObserver interface, and acts as a
+//      container for Tabs, and is also responsible for creating them.
+//
+///////////////////////////////////////////////////////////////////////////////
+class TouchTabStrip : public BaseTabStrip {
+ public:
+  explicit TouchTabStrip(TabStripController* controller);
+  virtual ~TouchTabStrip();
+
+  // BaseTabStrip implementation:
+  virtual void SetBackgroundOffset(const gfx::Point& offset);
+  virtual bool IsPositionInWindowCaption(const gfx::Point& point);
+  virtual void PrepareForCloseAt(int model_index);
+  virtual void StartHighlight(int model_index);
+  virtual void StopAllHighlighting();
+  virtual BaseTab* CreateTabForDragging();
+  virtual void RemoveTabAt(int model_index);
+  virtual void SelectTabAt(int old_model_index, int new_model_index);
+  virtual void TabTitleChangedNotLoading(int model_index);
+  virtual BaseTab* CreateTab();
+  virtual void StartInsertTabAnimation(int model_index, bool foreground);
+  virtual void AnimateToIdealBounds();
+  virtual bool ShouldHighlightCloseButtonAfterRemove();
+  virtual void GenerateIdealBounds();
+
+  // views::View overrides
+  virtual gfx::Size GetPreferredSize();
+  virtual void PaintChildren(gfx::Canvas* canvas);
+
+  // Retrieves the Tab at the specified index. Remember, the specified index
+  // is in terms of tab_data, *not* the model.
+  TouchTab* GetTabAtTabDataIndex(int tab_data_index) const;
+
+ private:
+  void Init();
+
+  // True if PrepareForCloseAt has been invoked. When true remove animations
+  // preserve current tab bounds.
+  bool in_tab_close_;
+
+  DISALLOW_COPY_AND_ASSIGN(TouchTabStrip);
+};
+
+#endif  // CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_H_
diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h
index 948eabb..3df052d 100644
--- a/chrome/browser/ui/view_ids.h
+++ b/chrome/browser/ui/view_ids.h
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // This defines an enumeration of IDs that can uniquely identify a view within
 // the scope of a container view.
 
-#ifndef CHROME_BROWSER_VIEW_IDS_H_
-#define CHROME_BROWSER_VIEW_IDS_H_
+#ifndef CHROME_BROWSER_UI_VIEW_IDS_H_
+#define CHROME_BROWSER_UI_VIEW_IDS_H_
 #pragma once
 
 enum ViewID {
@@ -78,9 +78,10 @@
   // The sidebar split.
   VIEW_ID_SIDE_BAR_SPLIT,
 
-  // Used in chrome/browser/gtk/view_id_util_browsertests.cc
+  // Used in chrome/browser/ui/gtk/view_id_util_browsertests.cc
   // If you add new ids, make sure the above test passes.
   VIEW_ID_PREDEFINED_COUNT
 };
 
-#endif  // CHROME_BROWSER_VIEW_IDS_H_
+#endif  // CHROME_BROWSER_UI_VIEW_IDS_H_
+
diff --git a/chrome/browser/ui/views/about_chrome_view.cc b/chrome/browser/ui/views/about_chrome_view.cc
index 341c6f8..e68ce75 100644
--- a/chrome/browser/ui/views/about_chrome_view.cc
+++ b/chrome/browser/ui/views/about_chrome_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/about_chrome_view.h"
+#include "chrome/browser/ui/views/about_chrome_view.h"
 
 #if defined(OS_WIN)
 #include <commdlg.h>
@@ -12,8 +12,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/i18n/rtl.h"
 #include "base/string_number_conversions.h"
@@ -24,21 +22,22 @@
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/views/accessible_view_helper.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/installer/util/browser_distribution.h"
-#include "gfx/canvas.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/textfield/textfield.h"
 #include "views/controls/throbber.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/view_text_utils.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -46,7 +45,7 @@
 
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
-#include "chrome/browser/views/restart_message_box.h"
+#include "chrome/browser/ui/views/restart_message_box.h"
 #include "chrome/installer/util/install_util.h"
 #endif  // defined(OS_WIN)
 
@@ -159,6 +158,9 @@
 
   current_version_ = version_info.Version();
 
+  // This code only runs as a result of the user opening the About box so
+  // doing registry access to get the version string modifier should be fine.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   std::string version_modifier = platform_util::GetVersionStringModifier();
   if (!version_modifier.empty())
     version_details_ += " " + version_modifier;
@@ -293,13 +295,13 @@
 
   // Add up the height of the various elements on the page.
   int height = about_background_logo->height() +
-               kRelatedControlVerticalSpacing +
+               views::kRelatedControlVerticalSpacing +
                // Copyright line.
                font.GetHeight() +
                // Main label.
                dummy_text.GetHeightForWidth(
                    dialog_dimensions_.width() - (2 * kPanelHorizMargin)) +
-               kRelatedControlVerticalSpacing;
+               views::kRelatedControlVerticalSpacing;
 
 #if defined(GOOGLE_CHROME_BUILD)
   std::vector<size_t> url_offsets;
@@ -318,7 +320,7 @@
   terms_of_service_url_->SetController(this);
 
   // Add the Terms of Service line and some whitespace.
-  height += font.GetHeight() + kRelatedControlVerticalSpacing;
+  height += font.GetHeight() + views::kRelatedControlVerticalSpacing;
 #endif
 
   // Use whichever is greater (the calculated height or the specified minimum
@@ -353,7 +355,7 @@
   version_label_->SetBounds(kPanelHorizMargin,
                             about_title_label_->y() +
                                 about_title_label_->height() +
-                                kRelatedControlVerticalSpacing,
+                                views::kRelatedControlVerticalSpacing,
                             kVersionFieldWidth,
                             sz.height());
 
@@ -364,14 +366,14 @@
       kPanelHorizMargin,
       version_label_->y() +
           version_label_->height() +
-          kRelatedControlVerticalSpacing,
+          views::kRelatedControlVerticalSpacing,
       kVersionFieldWidth,
       sz.height());
 #endif
 
   // For the width of the main text label we want to use up the whole panel
   // width and remaining height, minus a little margin on each side.
-  int y_pos = background_image_height + kRelatedControlVerticalSpacing;
+  int y_pos = background_image_height + views::kRelatedControlVerticalSpacing;
   sz.set_width(panel_size.width() - 2 * kPanelHorizMargin);
 
   // Draw the text right below the background image.
@@ -389,12 +391,12 @@
 
   // Get the y-coordinate of our parent so we can position the text left of the
   // buttons at the bottom.
-  gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
+  gfx::Rect parent_bounds = parent()->GetContentsBounds();
 
   sz = throbber_->GetPreferredSize();
   int throbber_topleft_x = kPanelHorizMargin;
-  int throbber_topleft_y = parent_bounds.bottom() - sz.height() -
-                           kButtonVEdgeMargin - 3;
+  int throbber_topleft_y =
+      parent_bounds.bottom() - sz.height() - views::kButtonVEdgeMargin - 3;
   throbber_->SetBounds(throbber_topleft_x, throbber_topleft_y,
                        sz.width(), sz.height());
 
@@ -418,16 +420,12 @@
   // variable length messages.
   sz = update_label_.GetPreferredSize();
   int update_label_x = throbber_->x() + throbber_->width() +
-                       kRelatedControlHorizontalSpacing;
+                       views::kRelatedControlHorizontalSpacing;
   update_label_.SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   update_label_.SetBounds(update_label_x,
                           throbber_topleft_y + 1,
                           parent_bounds.width() - update_label_x,
                           sz.height());
-
-  if (!accessible_view_helper_.get())
-    accessible_view_helper_.reset(
-        new AccessibleViewHelper(GetParent(), profile_));
 }
 
 
@@ -474,7 +472,7 @@
 #if defined(GOOGLE_CHROME_BUILD)
   // Insert a line break and some whitespace.
   position.set_width(0);
-  position.Enlarge(0, font.GetHeight() + kRelatedControlVerticalSpacing);
+  position.Enlarge(0, font.GetHeight() + views::kRelatedControlVerticalSpacing);
 
   // And now the Terms of Service and position the TOS url.
   view_text_utils::DrawTextAndPositionUrl(canvas, main_text_label_,
@@ -565,7 +563,7 @@
 std::wstring AboutChromeView::GetDialogButtonLabel(
     MessageBoxFlags::DialogButton button) const {
   if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
-    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_RESTART_AND_UPDATE));
+    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_RELAUNCH_AND_UPDATE));
   } else if (button == MessageBoxFlags::DIALOGBUTTON_CANCEL) {
     if (restart_button_visible_)
       return UTF16ToWide(l10n_util::GetStringUTF16(IDS_NOT_NOW));
@@ -752,8 +750,13 @@
       // are running the latest version and if not, notify the user by falling
       // into the next case of UPGRADE_SUCCESSFUL.
       BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+      base::ThreadRestrictions::ScopedAllowIO allow_io;
       scoped_ptr<Version> installed_version(
           InstallUtil::GetChromeVersion(dist, false));
+      if (!installed_version.get()) {
+        // User-level Chrome is not installed, check system-level.
+        installed_version.reset(InstallUtil::GetChromeVersion(dist, true));
+      }
       scoped_ptr<Version> running_version(
           Version::GetVersionFromString(current_version_));
       if (!installed_version.get() ||
@@ -793,7 +796,7 @@
       restart_button_visible_ = true;
       const std::wstring& update_string =
           UTF16ToWide(l10n_util::GetStringFUTF16(
-              IDS_UPGRADE_SUCCESSFUL_RESTART,
+              IDS_UPGRADE_SUCCESSFUL_RELAUNCH,
               l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
       update_label_.SetText(update_string);
       show_success_indicator = true;
@@ -803,8 +806,13 @@
       UserMetrics::RecordAction(UserMetricsAction("UpgradeCheck_Error"),
                                 profile_);
       restart_button_visible_ = false;
-      update_label_.SetText(UTF16ToWide(
-          l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code)));
+      if (error_code != GOOGLE_UPDATE_DISABLED_BY_POLICY) {
+        update_label_.SetText(UTF16ToWide(
+            l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code)));
+      } else {
+        update_label_.SetText(UTF16ToWide(
+            l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY)));
+      }
       show_timeout_indicator = true;
       break;
     default:
@@ -822,8 +830,7 @@
     throbber_->Stop();
 
   // We have updated controls on the parent, so we need to update its layout.
-  View* parent = GetParent();
-  parent->Layout();
+  parent()->Layout();
 
   // Check button may have appeared/disappeared. We cannot call this during
   // ViewHierarchyChanged because the |window()| pointer hasn't been set yet.
diff --git a/chrome/browser/ui/views/about_chrome_view.h b/chrome/browser/ui/views/about_chrome_view.h
index ab287be..edbcb32 100644
--- a/chrome/browser/ui/views/about_chrome_view.h
+++ b/chrome/browser/ui/views/about_chrome_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -25,7 +25,6 @@
 class Window;
 }
 
-class AccessibleViewHelper;
 class Profile;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -165,8 +164,6 @@
   CancelableRequestConsumer consumer_;
 #endif
 
-  scoped_ptr<AccessibleViewHelper> accessible_view_helper_;
-
   DISALLOW_COPY_AND_ASSIGN(AboutChromeView);
 };
 
diff --git a/chrome/browser/ui/views/about_ipc_dialog.cc b/chrome/browser/ui/views/about_ipc_dialog.cc
index c072d3e..12fe150 100644
--- a/chrome/browser/ui/views/about_ipc_dialog.cc
+++ b/chrome/browser/ui/views/about_ipc_dialog.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,7 @@
 #ifdef IPC_MESSAGE_LOG_ENABLED
 #define IPC_MESSAGE_MACROS_LOG_ENABLED
 
-#include "chrome/browser/views/about_ipc_dialog.h"
+#include "chrome/browser/ui/views/about_ipc_dialog.h"
 
 #include <set>
 
@@ -22,6 +22,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/chrome_dll_resource.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/devtools_messages.h"
 #include "chrome/common/plugin_messages.h"
@@ -29,10 +30,10 @@
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job.h"
 #include "net/url_request/url_request_job_tracker.h"
-#include "views/grid_layout.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/native/native_view_host.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -67,7 +68,7 @@
 
 // The singleton dialog box. This is non-NULL when a dialog is active so we
 // know not to create a new one.
-AboutIPCDialog* active_dialog = NULL;
+AboutIPCDialog* g_active_dialog = NULL;
 
 std::set<int> disabled_messages;
 
@@ -207,22 +208,23 @@
 }
 
 AboutIPCDialog::~AboutIPCDialog() {
-  active_dialog = NULL;
+  g_active_dialog = NULL;
   IPC::Logging::GetInstance()->SetConsumer(NULL);
 }
 
 // static
 void AboutIPCDialog::RunDialog() {
-  if (!active_dialog) {
-    active_dialog = new AboutIPCDialog;
-    views::Window::CreateChromeWindow(NULL, gfx::Rect(), active_dialog)->Show();
+  if (!g_active_dialog) {
+    g_active_dialog = new AboutIPCDialog;
+    views::Window::CreateChromeWindow(NULL, gfx::Rect(),
+                                      g_active_dialog)->Show();
   } else {
     // TOOD(brettw) it would be nice to focus the existing window.
   }
 }
 
 void AboutIPCDialog::SetupControls() {
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   track_toggle_ = new views::TextButton(this, kStartTrackingLabel);
@@ -249,7 +251,7 @@
   layout->AddView(track_toggle_);
   layout->AddView(clear_button_);
   layout->AddView(filter_button_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(1.0f, table_column_set);
   layout->AddView(table_);
 }
@@ -367,4 +369,12 @@
   }
 }
 
+namespace browser {
+
+void ShowAboutIPCDialog() {
+  AboutIPCDialog::RunDialog();
+}
+
+} // namespace browser
+
 #endif  // IPC_MESSAGE_LOG_ENABLED
diff --git a/chrome/browser/ui/views/accelerator_table_gtk.cc b/chrome/browser/ui/views/accelerator_table_gtk.cc
index c87580b..025714b 100644
--- a/chrome/browser/ui/views/accelerator_table_gtk.cc
+++ b/chrome/browser/ui/views/accelerator_table_gtk.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/accelerator_table_gtk.h"
+#include "chrome/browser/ui/views/accelerator_table_gtk.h"
 
-#include "app/keyboard_codes.h"
 #include "base/basictypes.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
 namespace browser {
 
@@ -14,144 +14,144 @@
 // the Windows accelerators in ../../app/chrome_dll.rc.
 const AcceleratorMapping kAcceleratorMap[] = {
   // Keycode                  Shift  Ctrl   Alt    Command ID
-  { app::VKEY_A,              true,  true,  false, IDC_AUTOFILL_DEFAULT },
-  { app::VKEY_LEFT,           false, false, true,  IDC_BACK },
-  { app::VKEY_BACK,           false, false, false, IDC_BACK },
+  { ui::VKEY_A,              true,  true,  false, IDC_AUTOFILL_DEFAULT },
+  { ui::VKEY_LEFT,           false, false, true,  IDC_BACK },
+  { ui::VKEY_BACK,           false, false, false, IDC_BACK },
 #if defined(OS_CHROMEOS)
-  { app::VKEY_F1,             false, false, false, IDC_BACK },
+  { ui::VKEY_F1,             false, false, false, IDC_BACK },
   // TODO(mazda): Change VKEY_1 to VKEY_OME_2 once the new version of the
   // keyboard overlay is ready.
-  { app::VKEY_1,              false, true,  true,  IDC_SHOW_KEYBOARD_OVERLAY },
+  { ui::VKEY_1,              false, true,  true,  IDC_SHOW_KEYBOARD_OVERLAY },
 #endif
-  { app::VKEY_D,              false, true,  false, IDC_BOOKMARK_PAGE },
-  { app::VKEY_D,              true,  true,  false, IDC_BOOKMARK_ALL_TABS },
-  { app::VKEY_DELETE,         true,  true,  false, IDC_CLEAR_BROWSING_DATA },
+  { ui::VKEY_D,              false, true,  false, IDC_BOOKMARK_PAGE },
+  { ui::VKEY_D,              true,  true,  false, IDC_BOOKMARK_ALL_TABS },
+  { ui::VKEY_DELETE,         true,  true,  false, IDC_CLEAR_BROWSING_DATA },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F4,             false, true,  false, IDC_CLOSE_TAB },
+  { ui::VKEY_F4,             false, true,  false, IDC_CLOSE_TAB },
 #endif
-  { app::VKEY_W,              false, true,  false, IDC_CLOSE_TAB },
-  { app::VKEY_W,              true,  true,  false, IDC_CLOSE_WINDOW },
+  { ui::VKEY_W,              false, true,  false, IDC_CLOSE_TAB },
+  { ui::VKEY_W,              true,  true,  false, IDC_CLOSE_WINDOW },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F4,             false, false, true,  IDC_CLOSE_WINDOW },
+  { ui::VKEY_F4,             false, false, true,  IDC_CLOSE_WINDOW },
 #endif
-  { app::VKEY_Q,              true,  true,  false, IDC_EXIT },
-  { app::VKEY_F,              false, true,  false, IDC_FIND },
-  { app::VKEY_G,              false, true,  false, IDC_FIND_NEXT },
+  { ui::VKEY_Q,              true,  true,  false, IDC_EXIT },
+  { ui::VKEY_F,              false, true,  false, IDC_FIND },
+  { ui::VKEY_G,              false, true,  false, IDC_FIND_NEXT },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F3,             false, false, false, IDC_FIND_NEXT },
+  { ui::VKEY_F3,             false, false, false, IDC_FIND_NEXT },
 #endif
-  { app::VKEY_G,              true,  true,  false, IDC_FIND_PREVIOUS },
+  { ui::VKEY_G,              true,  true,  false, IDC_FIND_PREVIOUS },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F3,             true,  false, false, IDC_FIND_PREVIOUS },
+  { ui::VKEY_F3,             true,  false, false, IDC_FIND_PREVIOUS },
 #endif
 #if defined(OS_CHROMEOS)
-  { app::VKEY_S,              true,  false, true,  IDC_FOCUS_CHROMEOS_STATUS },
+  { ui::VKEY_S,              true,  false, true,  IDC_FOCUS_CHROMEOS_STATUS },
 #endif
-  { app::VKEY_D,              false, false, true,  IDC_FOCUS_LOCATION },
-  { app::VKEY_L,              false, true,  false, IDC_FOCUS_LOCATION },
+  { ui::VKEY_D,              false, false, true,  IDC_FOCUS_LOCATION },
+  { ui::VKEY_L,              false, true,  false, IDC_FOCUS_LOCATION },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F10,            false, false, false, IDC_FOCUS_MENU_BAR },
+  { ui::VKEY_F10,            false, false, false, IDC_FOCUS_MENU_BAR },
 #endif
-  { app::VKEY_MENU,           false, false, false, IDC_FOCUS_MENU_BAR },
+  { ui::VKEY_MENU,           false, false, false, IDC_FOCUS_MENU_BAR },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F6,             false, false, false, IDC_FOCUS_NEXT_PANE },
+  { ui::VKEY_F6,             false, false, false, IDC_FOCUS_NEXT_PANE },
 #endif
 #if defined(OS_CHROMEOS)
-  { app::VKEY_F2,             false, true,  false, IDC_FOCUS_NEXT_PANE },
+  { ui::VKEY_F2,             false, true,  false, IDC_FOCUS_NEXT_PANE },
 #endif
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F6,             true,  false, false, IDC_FOCUS_PREVIOUS_PANE },
+  { ui::VKEY_F6,             true,  false, false, IDC_FOCUS_PREVIOUS_PANE },
 #endif
 #if defined(OS_CHROMEOS)
-  { app::VKEY_F1,             false, true,  false, IDC_FOCUS_PREVIOUS_PANE },
+  { ui::VKEY_F1,             false, true,  false, IDC_FOCUS_PREVIOUS_PANE },
 #endif
-  { app::VKEY_K,              false, true,  false, IDC_FOCUS_SEARCH },
-  { app::VKEY_E,              false, true,  false, IDC_FOCUS_SEARCH },
-  { app::VKEY_BROWSER_SEARCH, false, false, false, IDC_FOCUS_SEARCH },
-  { app::VKEY_T,              true,  false, true,  IDC_FOCUS_TOOLBAR },
-  { app::VKEY_B,              true,  false, true,  IDC_FOCUS_BOOKMARKS },
-  { app::VKEY_RIGHT,          false, false, true,  IDC_FORWARD },
-  { app::VKEY_BACK,           true,  false, false, IDC_FORWARD },
+  { ui::VKEY_K,              false, true,  false, IDC_FOCUS_SEARCH },
+  { ui::VKEY_E,              false, true,  false, IDC_FOCUS_SEARCH },
+  { ui::VKEY_BROWSER_SEARCH, false, false, false, IDC_FOCUS_SEARCH },
+  { ui::VKEY_T,              true,  false, true,  IDC_FOCUS_TOOLBAR },
+  { ui::VKEY_B,              true,  false, true,  IDC_FOCUS_BOOKMARKS },
+  { ui::VKEY_RIGHT,          false, false, true,  IDC_FORWARD },
+  { ui::VKEY_BACK,           true,  false, false, IDC_FORWARD },
 #if defined(OS_CHROMEOS)
-  { app::VKEY_F2,             false, false, false, IDC_FORWARD },
+  { ui::VKEY_F2,             false, false, false, IDC_FORWARD },
 #endif
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F11,            false, false, false, IDC_FULLSCREEN },
+  { ui::VKEY_F11,            false, false, false, IDC_FULLSCREEN },
 #endif
 #if defined(OS_CHROMEOS)
-  { app::VKEY_F4,             false, false, false, IDC_FULLSCREEN },
+  { ui::VKEY_F4,             false, false, false, IDC_FULLSCREEN },
 #endif
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F1,             false, false, false, IDC_HELP_PAGE },
+  { ui::VKEY_F1,             false, false, false, IDC_HELP_PAGE },
 #endif
 #if defined(OS_CHROMEOS)
-  { app::VKEY_OEM_2,          false, true,  false, IDC_HELP_PAGE },
-  { app::VKEY_OEM_2,          true,  true,  false, IDC_HELP_PAGE },
+  { ui::VKEY_OEM_2,          false, true,  false, IDC_HELP_PAGE },
+  { ui::VKEY_OEM_2,          true,  true,  false, IDC_HELP_PAGE },
 #endif
-  { app::VKEY_I,              true,  true,  false, IDC_DEV_TOOLS },
-  { app::VKEY_J,              true,  true,  false, IDC_DEV_TOOLS_CONSOLE },
-  { app::VKEY_C,              true,  true,  false, IDC_DEV_TOOLS_INSPECT },
-  { app::VKEY_N,              true,  true,  false, IDC_NEW_INCOGNITO_WINDOW },
-  { app::VKEY_T,              false, true,  false, IDC_NEW_TAB },
-  { app::VKEY_N,              false, true,  false, IDC_NEW_WINDOW },
-  { app::VKEY_O,              false, true,  false, IDC_OPEN_FILE },
-  { app::VKEY_P,              false, true,  false, IDC_PRINT},
-  { app::VKEY_R,              false, true,  false, IDC_RELOAD },
-  { app::VKEY_R,              true,  true,  false, IDC_RELOAD_IGNORING_CACHE },
+  { ui::VKEY_I,              true,  true,  false, IDC_DEV_TOOLS },
+  { ui::VKEY_J,              true,  true,  false, IDC_DEV_TOOLS_CONSOLE },
+  { ui::VKEY_C,              true,  true,  false, IDC_DEV_TOOLS_INSPECT },
+  { ui::VKEY_N,              true,  true,  false, IDC_NEW_INCOGNITO_WINDOW },
+  { ui::VKEY_T,              false, true,  false, IDC_NEW_TAB },
+  { ui::VKEY_N,              false, true,  false, IDC_NEW_WINDOW },
+  { ui::VKEY_O,              false, true,  false, IDC_OPEN_FILE },
+  { ui::VKEY_P,              false, true,  false, IDC_PRINT},
+  { ui::VKEY_R,              false, true,  false, IDC_RELOAD },
+  { ui::VKEY_R,              true,  true,  false, IDC_RELOAD_IGNORING_CACHE },
 #if !defined(OS_CHROMEOS)
-  { app::VKEY_F5,             false, false, false, IDC_RELOAD },
-  { app::VKEY_F5,             false, true,  false, IDC_RELOAD_IGNORING_CACHE },
-  { app::VKEY_F5,             true,  false, false, IDC_RELOAD_IGNORING_CACHE },
+  { ui::VKEY_F5,             false, false, false, IDC_RELOAD },
+  { ui::VKEY_F5,             false, true,  false, IDC_RELOAD_IGNORING_CACHE },
+  { ui::VKEY_F5,             true,  false, false, IDC_RELOAD_IGNORING_CACHE },
 #endif
 #if defined(OS_CHROMEOS)
-  { app::VKEY_F3,             false, false, false, IDC_RELOAD },
-  { app::VKEY_F3,             false, true,  false, IDC_RELOAD_IGNORING_CACHE },
-  { app::VKEY_F3,             true,  false, false, IDC_RELOAD_IGNORING_CACHE },
+  { ui::VKEY_F3,             false, false, false, IDC_RELOAD },
+  { ui::VKEY_F3,             false, true,  false, IDC_RELOAD_IGNORING_CACHE },
+  { ui::VKEY_F3,             true,  false, false, IDC_RELOAD_IGNORING_CACHE },
 #endif
-  { app::VKEY_HOME,           false, false, true,  IDC_HOME },
-  { app::VKEY_T,              true,  true,  false, IDC_RESTORE_TAB },
-  { app::VKEY_S,              false, true,  false, IDC_SAVE_PAGE },
+  { ui::VKEY_HOME,           false, false, true,  IDC_HOME },
+  { ui::VKEY_T,              true,  true,  false, IDC_RESTORE_TAB },
+  { ui::VKEY_S,              false, true,  false, IDC_SAVE_PAGE },
 #if defined(OS_CHROMEOS)
-  { app::VKEY_LWIN,           false, false, false, IDC_SEARCH },
+  { ui::VKEY_LWIN,           false, false, false, IDC_SEARCH },
 #endif
-  { app::VKEY_9,              false, true,  false, IDC_SELECT_LAST_TAB },
-  { app::VKEY_NUMPAD9,        false, true,  false, IDC_SELECT_LAST_TAB },
-  { app::VKEY_TAB,            false, true,  false, IDC_SELECT_NEXT_TAB },
-  { app::VKEY_NEXT,           false, true,  false, IDC_SELECT_NEXT_TAB },
-  { app::VKEY_TAB,            true,  true,  false, IDC_SELECT_PREVIOUS_TAB },
-  { app::VKEY_PRIOR,          false, true,  false, IDC_SELECT_PREVIOUS_TAB },
-  { app::VKEY_1,              false, true,  false, IDC_SELECT_TAB_0 },
-  { app::VKEY_NUMPAD1,        false, true,  false, IDC_SELECT_TAB_0 },
-  { app::VKEY_2,              false, true,  false, IDC_SELECT_TAB_1 },
-  { app::VKEY_NUMPAD2,        false, true,  false, IDC_SELECT_TAB_1 },
-  { app::VKEY_3,              false, true,  false, IDC_SELECT_TAB_2 },
-  { app::VKEY_NUMPAD3,        false, true,  false, IDC_SELECT_TAB_2 },
-  { app::VKEY_4,              false, true,  false, IDC_SELECT_TAB_3 },
-  { app::VKEY_NUMPAD4,        false, true,  false, IDC_SELECT_TAB_3 },
-  { app::VKEY_5,              false, true,  false, IDC_SELECT_TAB_4 },
-  { app::VKEY_NUMPAD5,        false, true,  false, IDC_SELECT_TAB_4 },
-  { app::VKEY_6,              false, true,  false, IDC_SELECT_TAB_5 },
-  { app::VKEY_NUMPAD6,        false, true,  false, IDC_SELECT_TAB_5 },
-  { app::VKEY_7,              false, true,  false, IDC_SELECT_TAB_6 },
-  { app::VKEY_NUMPAD7,        false, true,  false, IDC_SELECT_TAB_6 },
-  { app::VKEY_8,              false, true,  false, IDC_SELECT_TAB_7 },
-  { app::VKEY_NUMPAD8,        false, true,  false, IDC_SELECT_TAB_7 },
-  { app::VKEY_B,              true,  true,  false, IDC_SHOW_BOOKMARK_BAR },
-  { app::VKEY_J,              false, true,  false, IDC_SHOW_DOWNLOADS },
-  { app::VKEY_H,              false, true,  false, IDC_SHOW_HISTORY },
-  { app::VKEY_F,              false, false, true,  IDC_SHOW_APP_MENU},
-  { app::VKEY_E,              false, false, true,  IDC_SHOW_APP_MENU},
-  { app::VKEY_ESCAPE,         false, false, false, IDC_STOP },
-  { app::VKEY_ESCAPE,         true,  false, false, IDC_TASK_MANAGER },
-  { app::VKEY_U,              false, true,  false, IDC_VIEW_SOURCE },
-  { app::VKEY_OEM_MINUS,      false, true,  false, IDC_ZOOM_MINUS },
-  { app::VKEY_OEM_MINUS,      true,  true,  false, IDC_ZOOM_MINUS },
-  { app::VKEY_SUBTRACT,       false, true,  false, IDC_ZOOM_MINUS },
-  { app::VKEY_0,              false, true,  false, IDC_ZOOM_NORMAL },
-  { app::VKEY_NUMPAD0,        false, true,  false, IDC_ZOOM_NORMAL },
-  { app::VKEY_OEM_PLUS,       false, true,  false, IDC_ZOOM_PLUS },
-  { app::VKEY_OEM_PLUS,       true,  true,  false, IDC_ZOOM_PLUS },
-  { app::VKEY_ADD,            false, true,  false, IDC_ZOOM_PLUS },
+  { ui::VKEY_9,              false, true,  false, IDC_SELECT_LAST_TAB },
+  { ui::VKEY_NUMPAD9,        false, true,  false, IDC_SELECT_LAST_TAB },
+  { ui::VKEY_TAB,            false, true,  false, IDC_SELECT_NEXT_TAB },
+  { ui::VKEY_NEXT,           false, true,  false, IDC_SELECT_NEXT_TAB },
+  { ui::VKEY_TAB,            true,  true,  false, IDC_SELECT_PREVIOUS_TAB },
+  { ui::VKEY_PRIOR,          false, true,  false, IDC_SELECT_PREVIOUS_TAB },
+  { ui::VKEY_1,              false, true,  false, IDC_SELECT_TAB_0 },
+  { ui::VKEY_NUMPAD1,        false, true,  false, IDC_SELECT_TAB_0 },
+  { ui::VKEY_2,              false, true,  false, IDC_SELECT_TAB_1 },
+  { ui::VKEY_NUMPAD2,        false, true,  false, IDC_SELECT_TAB_1 },
+  { ui::VKEY_3,              false, true,  false, IDC_SELECT_TAB_2 },
+  { ui::VKEY_NUMPAD3,        false, true,  false, IDC_SELECT_TAB_2 },
+  { ui::VKEY_4,              false, true,  false, IDC_SELECT_TAB_3 },
+  { ui::VKEY_NUMPAD4,        false, true,  false, IDC_SELECT_TAB_3 },
+  { ui::VKEY_5,              false, true,  false, IDC_SELECT_TAB_4 },
+  { ui::VKEY_NUMPAD5,        false, true,  false, IDC_SELECT_TAB_4 },
+  { ui::VKEY_6,              false, true,  false, IDC_SELECT_TAB_5 },
+  { ui::VKEY_NUMPAD6,        false, true,  false, IDC_SELECT_TAB_5 },
+  { ui::VKEY_7,              false, true,  false, IDC_SELECT_TAB_6 },
+  { ui::VKEY_NUMPAD7,        false, true,  false, IDC_SELECT_TAB_6 },
+  { ui::VKEY_8,              false, true,  false, IDC_SELECT_TAB_7 },
+  { ui::VKEY_NUMPAD8,        false, true,  false, IDC_SELECT_TAB_7 },
+  { ui::VKEY_B,              true,  true,  false, IDC_SHOW_BOOKMARK_BAR },
+  { ui::VKEY_J,              false, true,  false, IDC_SHOW_DOWNLOADS },
+  { ui::VKEY_H,              false, true,  false, IDC_SHOW_HISTORY },
+  { ui::VKEY_F,              false, false, true,  IDC_SHOW_APP_MENU},
+  { ui::VKEY_E,              false, false, true,  IDC_SHOW_APP_MENU},
+  { ui::VKEY_ESCAPE,         false, false, false, IDC_STOP },
+  { ui::VKEY_ESCAPE,         true,  false, false, IDC_TASK_MANAGER },
+  { ui::VKEY_U,              false, true,  false, IDC_VIEW_SOURCE },
+  { ui::VKEY_OEM_MINUS,      false, true,  false, IDC_ZOOM_MINUS },
+  { ui::VKEY_OEM_MINUS,      true,  true,  false, IDC_ZOOM_MINUS },
+  { ui::VKEY_SUBTRACT,       false, true,  false, IDC_ZOOM_MINUS },
+  { ui::VKEY_0,              false, true,  false, IDC_ZOOM_NORMAL },
+  { ui::VKEY_NUMPAD0,        false, true,  false, IDC_ZOOM_NORMAL },
+  { ui::VKEY_OEM_PLUS,       false, true,  false, IDC_ZOOM_PLUS },
+  { ui::VKEY_OEM_PLUS,       true,  true,  false, IDC_ZOOM_PLUS },
+  { ui::VKEY_ADD,            false, true,  false, IDC_ZOOM_PLUS },
 };
 
 const size_t kAcceleratorMapLength = arraysize(kAcceleratorMap);
diff --git a/chrome/browser/ui/views/accelerator_table_gtk.h b/chrome/browser/ui/views/accelerator_table_gtk.h
index 4b38144..865db16 100644
--- a/chrome/browser/ui/views/accelerator_table_gtk.h
+++ b/chrome/browser/ui/views/accelerator_table_gtk.h
@@ -8,14 +8,14 @@
 
 #include <stdio.h>
 
-#include "app/keyboard_codes.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 
 // This contains the list of accelerators for the Linux toolkit_view
 // implementation.
 namespace browser {
 
   struct AcceleratorMapping {
-    app::KeyboardCode keycode;
+    ui::KeyboardCode keycode;
     bool shift_pressed;
     bool ctrl_pressed;
     bool alt_pressed;
diff --git a/chrome/browser/ui/views/accessibility_event_router_views.cc b/chrome/browser/ui/views/accessibility_event_router_views.cc
index b563b8d..b296cac 100644
--- a/chrome/browser/ui/views/accessibility_event_router_views.cc
+++ b/chrome/browser/ui/views/accessibility_event_router_views.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/accessibility_event_router_views.h"
+#include "chrome/browser/ui/views/accessibility_event_router_views.h"
 
 #include "base/basictypes.h"
 #include "base/callback.h"
@@ -11,7 +11,7 @@
 #include "chrome/browser/extensions/extension_accessibility_api.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/common/notification_type.h"
 #include "views/accessibility/accessibility_types.h"
 #include "views/controls/button/custom_button.h"
@@ -21,6 +21,7 @@
 #include "views/controls/menu/menu_item_view.h"
 #include "views/controls/menu/submenu_view.h"
 #include "views/view.h"
+#include "views/window/window.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/autocomplete/autocomplete_edit_view_win.h"
@@ -41,35 +42,6 @@
   return Singleton<AccessibilityEventRouterViews>::get();
 }
 
-bool AccessibilityEventRouterViews::AddViewTree(
-    views::View* view, Profile* profile) {
-  if (view_tree_profile_map_[view] != NULL)
-    return false;
-
-  view_tree_profile_map_[view] = profile;
-  return true;
-}
-
-void AccessibilityEventRouterViews::RemoveViewTree(views::View* view) {
-  DCHECK(view_tree_profile_map_.find(view) !=
-         view_tree_profile_map_.end());
-  view_tree_profile_map_.erase(view);
-}
-
-void AccessibilityEventRouterViews::IgnoreView(views::View* view) {
-  view_info_map_[view].ignore = true;
-}
-
-void AccessibilityEventRouterViews::SetViewName(
-    views::View* view, std::string name) {
-  view_info_map_[view].name = name;
-}
-
-void AccessibilityEventRouterViews::RemoveView(views::View* view) {
-  DCHECK(view_info_map_.find(view) != view_info_map_.end());
-  view_info_map_.erase(view);
-}
-
 void AccessibilityEventRouterViews::HandleAccessibilityEvent(
     views::View* view, AccessibilityTypes::Event event_type) {
   if (!ExtensionAccessibilityEventRouter::GetInstance()->
@@ -115,80 +87,40 @@
 // Private methods
 //
 
-void AccessibilityEventRouterViews::FindView(
-    views::View* view, Profile** profile, bool* is_accessible) {
-  *is_accessible = false;
-
-  // First see if it's a descendant of an accessible view.
-  for (base::hash_map<views::View*, Profile*>::const_iterator iter =
-           view_tree_profile_map_.begin();
-       iter != view_tree_profile_map_.end();
-       ++iter) {
-    if (iter->first->IsParentOf(view)) {
-      *is_accessible = true;
-      if (profile)
-        *profile = iter->second;
-      break;
-    }
-  }
-
-  if (!*is_accessible)
-    return;
-
-  // Now make sure it's not marked as a widget to be ignored.
-  base::hash_map<views::View*, ViewInfo>::const_iterator iter =
-      view_info_map_.find(view);
-  if (iter != view_info_map_.end() && iter->second.ignore)
-    *is_accessible = false;
-}
-
 std::string AccessibilityEventRouterViews::GetViewName(views::View* view) {
-  std::string name;
-
-  // First see if we have a name registered for this view.
-  base::hash_map<views::View*, ViewInfo>::const_iterator iter =
-      view_info_map_.find(view);
-  if (iter != view_info_map_.end())
-    name = iter->second.name;
-
-  // Otherwise ask the view for its accessible name.
-  if (name.empty()) {
-    std::wstring wname;
-    view->GetAccessibleName(&wname);
-    name = WideToUTF8(wname);
-  }
-
-  return name;
+  string16 wname;
+  view->GetAccessibleName(&wname);
+  return UTF16ToUTF8(wname);
 }
 
 void AccessibilityEventRouterViews::DispatchAccessibilityNotification(
     views::View* view, NotificationType type) {
+  // Get the profile associated with this view. If it's not found, use
+  // the most recent profile where accessibility events were sent, or
+  // the default profile.
   Profile* profile = NULL;
-  bool is_accessible;
-  FindView(view, &profile, &is_accessible);
-
-  // Special case: a menu isn't associated with any particular top-level
-  // window, so menu events get routed to the profile of the most recent
-  // event that was associated with a window, which should be the window
-  // that triggered opening the menu.
-  bool is_menu_event = IsMenuEvent(view, type);
-  if (is_menu_event && !profile && most_recent_profile_) {
-    profile = most_recent_profile_;
-    is_accessible = true;
+  views::Window* window = view->GetWindow();
+  if (window) {
+    profile = reinterpret_cast<Profile*>(window->GetNativeWindowProperty(
+        Profile::kProfileKey));
   }
-
-  if (!is_accessible)
+  if (!profile)
+    profile = most_recent_profile_;
+  if (!profile)
+    profile = g_browser_process->profile_manager()->GetDefaultProfile();
+  if (!profile) {
+    NOTREACHED();
     return;
+  }
 
   most_recent_profile_ = profile;
 
   std::string class_name = view->GetClassName();
-
   if (class_name == views::MenuButton::kViewClassName ||
       type == NotificationType::ACCESSIBILITY_MENU_OPENED ||
       type == NotificationType::ACCESSIBILITY_MENU_CLOSED) {
     SendMenuNotification(view, type, profile);
-  } else if (is_menu_event) {
+  } else if (IsMenuEvent(view, type)) {
     SendMenuItemNotification(view, type, profile);
   } else if (class_name == views::CustomButton::kViewClassName ||
              class_name == views::NativeButton::kViewClassName ||
@@ -198,8 +130,6 @@
     SendLinkNotification(view, type, profile);
   } else if (class_name == LocationBarView::kViewClassName) {
     SendLocationBarNotification(view, type, profile);
-  } else {
-    class_name += " ";
   }
 }
 
@@ -232,10 +162,10 @@
   if (view->GetClassName() == views::MenuItemView::kViewClassName)
     has_submenu = static_cast<views::MenuItemView*>(view)->HasSubmenu();
 
-  views::View* parent_menu = view->GetParent();
+  views::View* parent_menu = view->parent();
   while (parent_menu != NULL && parent_menu->GetClassName() !=
          views::SubmenuView::kViewClassName) {
-    parent_menu = parent_menu->GetParent();
+    parent_menu = parent_menu->parent();
   }
   if (parent_menu) {
     count = 0;
@@ -248,7 +178,7 @@
 
 void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount(
     views::View* menu, views::View* item, int* index, int* count) {
-  for (int i = 0; i < menu->GetChildViewCount(); ++i) {
+  for (int i = 0; i < menu->child_count(); ++i) {
     views::View* child = menu->GetChildViewAt(i);
     int previous_count = *count;
     RecursiveGetMenuItemIndexAndCount(child, item, index, count);
@@ -277,7 +207,7 @@
         role == AccessibilityTypes::ROLE_MENUPOPUP) {
       return true;
     }
-    view = view->GetParent();
+    view = view->parent();
   }
 
   return false;
diff --git a/chrome/browser/ui/views/accessibility_event_router_views.h b/chrome/browser/ui/views/accessibility_event_router_views.h
index 3748474..77b256d 100644
--- a/chrome/browser/ui/views/accessibility_event_router_views.h
+++ b/chrome/browser/ui/views/accessibility_event_router_views.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,6 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/hash_tables.h"
 #include "base/singleton.h"
 #include "base/task.h"
 #include "chrome/browser/accessibility_events.h"
@@ -21,18 +20,6 @@
 class View;
 }
 
-// Allows us to use (View*) in a hash_map with gcc.
-#if defined(COMPILER_GCC)
-namespace __gnu_cxx {
-template<>
-struct hash<views::View*> {
-  size_t operator()(views::View* view) const {
-    return reinterpret_cast<size_t>(view);
-  }
-};
-}  // namespace __gnu_cxx
-#endif  // defined(COMPILER_GCC)
-
 // NOTE: This class is part of the Accessibility Extension API, which lets
 // extensions receive accessibility events. It's distinct from code that
 // implements platform accessibility APIs like MSAA or ATK.
@@ -65,27 +52,6 @@
   // Get the single instance of this class.
   static AccessibilityEventRouterViews* GetInstance();
 
-  // Start sending accessibility events for this view and all of its
-  // descendants.  Notifications will go to the specified profile.
-  // Returns true on success, false if "view" was already registered.
-  // It is the responsibility of the caller to call RemoveViewTree if
-  // this view is ever deleted; consider using AccessibleViewHelper.
-  bool AddViewTree(views::View* view, Profile* profile);
-
-  // Stop sending accessibility events for this view and all of its
-  // descendants.
-  void RemoveViewTree(views::View* view);
-
-  // Don't send any events for this view.
-  void IgnoreView(views::View* view);
-
-  // Use the following string as the name of this view, instead of the
-  // gtk label associated with the view.
-  void SetViewName(views::View* view, std::string name);
-
-  // Forget all information about this view.
-  void RemoveView(views::View* view);
-
   // Handle an accessibility event generated by a view.
   void HandleAccessibilityEvent(
       views::View* view, AccessibilityTypes::Event event_type);
@@ -98,10 +64,6 @@
   FRIEND_TEST_ALL_PREFIXES(AccessibilityEventRouterViewsTest,
                            TestFocusNotification);
 
-  // Given a view, determine if it's part of a view tree that's mapped to
-  // a profile and if so, if it's marked as accessible.
-  void FindView(views::View* view, Profile** profile, bool* is_accessible);
-
   // Checks the type of the view and calls one of the more specific
   // Send*Notification methods, below.
   void DispatchAccessibilityNotification(
@@ -134,13 +96,6 @@
   void RecursiveGetMenuItemIndexAndCount(
       views::View* menu, views::View* item, int* index, int* count);
 
-  // The set of all view tree roots; only descendants of these will generate
-  // accessibility notifications.
-  base::hash_map<views::View*, Profile*> view_tree_profile_map_;
-
-  // Extra information about specific views.
-  base::hash_map<views::View*, ViewInfo> view_info_map_;
-
   // The profile associated with the most recent window event  - used to
   // figure out where to route a few events that can't be directly traced
   // to a window with a profile (like menu events).
diff --git a/chrome/browser/ui/views/accessibility_event_router_views_unittest.cc b/chrome/browser/ui/views/accessibility_event_router_views_unittest.cc
index 7e51ab2..caecfbb 100644
--- a/chrome/browser/ui/views/accessibility_event_router_views_unittest.cc
+++ b/chrome/browser/ui/views/accessibility_event_router_views_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,23 +8,18 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_accessibility_api.h"
-#include "chrome/browser/views/accessibility_event_router_views.h"
-#include "chrome/browser/views/accessible_view_helper.h"
+#include "chrome/browser/ui/views/accessibility_event_router_views.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "views/controls/button/native_button.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/views_delegate.h"
 #include "views/widget/root_view.h"
+#include "views/widget/widget.h"
 #include "views/window/window.h"
-
-#if defined(OS_WIN)
-#include "views/widget/widget_win.h"
-#elif defined(OS_LINUX)
-#include "views/widget/widget_gtk.h"
-#endif
+#include "views/window/window_delegate.h"
 
 #if defined(TOOLKIT_VIEWS)
 
@@ -34,16 +29,19 @@
   virtual ~AccessibilityViewsDelegate() {}
 
   // Overridden from views::ViewsDelegate:
-  virtual Clipboard* GetClipboard() const { return NULL; }
-  virtual void SaveWindowPlacement(const std::wstring& window_name,
+  virtual ui::Clipboard* GetClipboard() const { return NULL; }
+  virtual void SaveWindowPlacement(views::Window* window,
+                                   const std::wstring& window_name,
                                    const gfx::Rect& bounds,
                                    bool maximized) {
   }
-  virtual bool GetSavedWindowBounds(const std::wstring& window_name,
+  virtual bool GetSavedWindowBounds(views::Window* window,
+                                    const std::wstring& window_name,
                                     gfx::Rect* bounds) const {
     return false;
   }
-  virtual bool GetSavedMaximizedState(const std::wstring& window_name,
+  virtual bool GetSavedMaximizedState(views::Window* window,
+                                      const std::wstring& window_name,
                                       bool* maximized) const {
     return false;
   }
@@ -63,25 +61,39 @@
   DISALLOW_COPY_AND_ASSIGN(AccessibilityViewsDelegate);
 };
 
+class AccessibilityWindowDelegate : public views::WindowDelegate {
+ public:
+  explicit AccessibilityWindowDelegate(views::View* contents)
+      : contents_(contents) { }
+
+  virtual void DeleteDelegate() { delete this; }
+
+  virtual views::View* GetContentsView() { return contents_; }
+
+ private:
+  views::View* contents_;
+};
+
 class AccessibilityEventRouterViewsTest
     : public testing::Test,
       public NotificationObserver {
  public:
   virtual void SetUp() {
     views::ViewsDelegate::views_delegate = new AccessibilityViewsDelegate();
+    window_delegate_ = NULL;
   }
 
   virtual void TearDown() {
     delete views::ViewsDelegate::views_delegate;
     views::ViewsDelegate::views_delegate = NULL;
+    if (window_delegate_)
+      delete window_delegate_;
   }
 
-  views::Widget* CreateWidget() {
-#if defined(OS_WIN)
-    return new views::WidgetWin();
-#elif defined(OS_LINUX)
-    return new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
-#endif
+  views::Window* CreateWindowWithContents(views::View* contents) {
+    window_delegate_ = new AccessibilityWindowDelegate(contents);
+    return views::Window::CreateChromeWindow(
+        NULL, gfx::Rect(0, 0, 500, 500), window_delegate_);
   }
 
  protected:
@@ -100,37 +112,29 @@
   MessageLoopForUI message_loop_;
   int focus_event_count_;
   std::string last_control_name_;
+  AccessibilityWindowDelegate* window_delegate_;
 };
 
 TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
   const char kButton1ASCII[] = "Button1";
   const char kButton2ASCII[] = "Button2";
   const char kButton3ASCII[] = "Button3";
-  const char kButton3NewASCII[] = "Button3";
+  const char kButton3NewASCII[] = "Button3New";
 
-  // Create a window and layout.
-  views::Widget* window = CreateWidget();
-  window->Init(NULL, gfx::Rect(0, 0, 100, 100));
-  views::RootView* root_view = window->GetRootView();
-  views::GridLayout* layout = new views::GridLayout(root_view);
-  root_view->SetLayoutManager(layout);
-  views::ColumnSet* column_set = layout->AddColumnSet(0);
-  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
-                        views::GridLayout::USE_PREF, 0, 0);
-
-  // Add 3 buttons.
+  // Create a contents view with 3 buttons.
+  views::View* contents = new views::View();
   views::NativeButton* button1 = new views::NativeButton(
       NULL, ASCIIToWide(kButton1ASCII));
-  layout->StartRow(0, 0);
-  layout->AddView(button1);
+  contents->AddChildView(button1);
   views::NativeButton* button2 = new views::NativeButton(
       NULL, ASCIIToWide(kButton2ASCII));
-  layout->StartRow(0, 0);
-  layout->AddView(button2);
+  contents->AddChildView(button2);
   views::NativeButton* button3 = new views::NativeButton(
       NULL, ASCIIToWide(kButton3ASCII));
-  layout->StartRow(0, 0);
-  layout->AddView(button3);
+  contents->AddChildView(button3);
+
+  // Put the view in a window.
+  views::Window* window = CreateWindowWithContents(contents);
 
   // Set focus to the first button initially.
   button1->RequestFocus();
@@ -142,19 +146,21 @@
                 NotificationService::AllSources());
 
   // Switch on accessibility event notifications.
-  TestingProfile profile;
   ExtensionAccessibilityEventRouter* accessibility_event_router =
       ExtensionAccessibilityEventRouter::GetInstance();
   accessibility_event_router->SetAccessibilityEnabled(true);
 
-  // Create an AccessibleViewHelper for this window, which will send
-  // accessibility notifications for all events that happen in child views.
-  AccessibleViewHelper accessible_view_helper(root_view, &profile);
-  accessible_view_helper.SetViewName(button3, std::string(kButton3NewASCII));
+  // Create a profile and associate it with this window.
+  TestingProfile profile;
+  window->SetNativeWindowProperty(
+      Profile::kProfileKey, &profile);
+
+  // Change the accessible name of button3.
+  button3->SetAccessibleName(ASCIIToUTF16(kButton3NewASCII));
 
   // Advance focus to the next button and test that we got the
   // expected notification with the name of button 2.
-  views::FocusManager* focus_manager = window->GetFocusManager();
+  views::FocusManager* focus_manager = contents->GetWidget()->GetFocusManager();
   focus_event_count_ = 0;
   focus_manager->AdvanceFocus(false);
   EXPECT_EQ(1, focus_event_count_);
diff --git a/chrome/browser/ui/views/accessible_pane_view.cc b/chrome/browser/ui/views/accessible_pane_view.cc
index 1e07d1d..c6789bc 100644
--- a/chrome/browser/ui/views/accessible_pane_view.cc
+++ b/chrome/browser/ui/views/accessible_pane_view.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/logging.h"
 #include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/accessible_pane_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/accessible_pane_view.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/native/native_view_host.h"
 #include "views/focus/focus_search.h"
@@ -18,11 +18,11 @@
     : pane_has_focus_(false),
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
       focus_manager_(NULL),
-      home_key_(app::VKEY_HOME, false, false, false),
-      end_key_(app::VKEY_END, false, false, false),
-      escape_key_(app::VKEY_ESCAPE, false, false, false),
-      left_key_(app::VKEY_LEFT, false, false, false),
-      right_key_(app::VKEY_RIGHT, false, false, false),
+      home_key_(ui::VKEY_HOME, false, false, false),
+      end_key_(ui::VKEY_END, false, false, false),
+      escape_key_(ui::VKEY_ESCAPE, false, false, false),
+      left_key_(ui::VKEY_LEFT, false, false, false),
+      right_key_(ui::VKEY_RIGHT, false, false, false),
       last_focused_view_storage_id_(-1) {
   focus_search_.reset(new views::FocusSearch(this, true, true));
 }
@@ -48,7 +48,7 @@
   // Use the provided initial focus if it's visible and enabled, otherwise
   // use the first focusable child.
   if (!initial_focus ||
-      !IsParentOf(initial_focus) ||
+      !Contains(initial_focus) ||
       !initial_focus->IsVisible() ||
       !initial_focus->IsEnabled()) {
     initial_focus = GetFirstFocusableChild();
@@ -161,21 +161,21 @@
   }
 
   switch (accelerator.GetKeyCode()) {
-    case app::VKEY_ESCAPE:
+    case ui::VKEY_ESCAPE:
       RemovePaneFocus();
       RestoreLastFocusedView();
       return true;
-    case app::VKEY_LEFT:
+    case ui::VKEY_LEFT:
       focus_manager_->AdvanceFocus(true);
       return true;
-    case app::VKEY_RIGHT:
+    case ui::VKEY_RIGHT:
       focus_manager_->AdvanceFocus(false);
       return true;
-    case app::VKEY_HOME:
+    case ui::VKEY_HOME:
       focus_manager_->SetFocusedViewWithReason(
           GetFirstFocusableChild(), views::FocusManager::kReasonFocusTraversal);
       return true;
-    case app::VKEY_END:
+    case ui::VKEY_END:
       focus_manager_->SetFocusedViewWithReason(
           GetLastFocusableChild(), views::FocusManager::kReasonFocusTraversal);
       return true;
@@ -216,7 +216,7 @@
             &AccessiblePaneView::LocationBarSelectAll));
   }
 
-  if (!IsParentOf(focused_now) ||
+  if (!Contains(focused_now) ||
       reason == views::FocusManager::kReasonDirectFocusChange) {
     // We should remove pane focus (i.e. make most of the controls
     // not focusable again) either because the focus is leaving the pane,
diff --git a/chrome/browser/ui/views/accessible_view_helper.cc b/chrome/browser/ui/views/accessible_view_helper.cc
deleted file mode 100644
index ca15381..0000000
--- a/chrome/browser/ui/views/accessible_view_helper.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/views/accessible_view_helper.h"
-
-#include "app/l10n_util.h"
-#include "chrome/browser/accessibility_events.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/accessibility_event_router_views.h"
-#include "chrome/common/notification_service.h"
-#include "views/controls/native/native_view_host.h"
-#include "views/widget/widget.h"
-#include "views/view.h"
-
-AccessibleViewHelper::AccessibleViewHelper(
-    views::View* view_tree, Profile* profile)
-    : accessibility_event_router_(AccessibilityEventRouterViews::GetInstance()),
-      profile_(profile),
-      view_tree_(view_tree) {
-  if (!accessibility_event_router_->AddViewTree(view_tree_, profile))
-    view_tree_ = NULL;
-
-#if defined(OS_LINUX)
-  GtkWidget* widget = view_tree->GetWidget()->GetNativeView();
-  widget_helper_.reset(new AccessibleWidgetHelper(widget, profile));
-#endif
-}
-
-AccessibleViewHelper::~AccessibleViewHelper() {
-  if (!window_title_.empty()) {
-    AccessibilityWindowInfo info(profile_, window_title_);
-    NotificationService::current()->Notify(
-        NotificationType::ACCESSIBILITY_WINDOW_CLOSED,
-        Source<Profile>(profile_),
-        Details<AccessibilityWindowInfo>(&info));
-  }
-
-  if (view_tree_) {
-    accessibility_event_router_->RemoveViewTree(view_tree_);
-    for (std::vector<views::View*>::iterator iter = managed_views_.begin();
-         iter != managed_views_.end();
-         ++iter) {
-      accessibility_event_router_->RemoveView(*iter);
-    }
-  }
-}
-
-void AccessibleViewHelper::SendOpenWindowNotification(
-    const std::string& window_title) {
-  window_title_ = window_title;
-  AccessibilityWindowInfo info(profile_, window_title);
-  NotificationService::current()->Notify(
-      NotificationType::ACCESSIBILITY_WINDOW_OPENED,
-      Source<Profile>(profile_),
-      Details<AccessibilityWindowInfo>(&info));
-}
-
-void AccessibleViewHelper::SetViewName(views::View* view, std::string name) {
-  if (!view_tree_)
-    return;
-
-  accessibility_event_router_->SetViewName(view, name);
-  managed_views_.push_back(view);
-
- #if defined(OS_LINUX)
-  gfx::NativeView native_view = GetNativeView(view);
-  if (native_view)
-    widget_helper_->SetWidgetName(native_view, name);
- #endif
-}
-
-void AccessibleViewHelper::SetViewName(views::View* view, int string_id) {
-  const std::string name = l10n_util::GetStringUTF8(string_id);
-  SetViewName(view, name);
-}
-
-gfx::NativeView AccessibleViewHelper::GetNativeView(views::View* view) const {
-  if (view->GetClassName() == views::NativeViewHost::kViewClassName)
-    return static_cast<views::NativeViewHost*>(view)->native_view();
-
-  for (int i = 0; i < view->GetChildViewCount(); i++) {
-    gfx::NativeView native_view = GetNativeView(view->GetChildViewAt(i));
-    if (native_view)
-      return native_view;
-  }
-
-  return NULL;
-}
diff --git a/chrome/browser/ui/views/accessible_view_helper.h b/chrome/browser/ui/views/accessible_view_helper.h
deleted file mode 100644
index 7a6c848..0000000
--- a/chrome/browser/ui/views/accessible_view_helper.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_ACCESSIBLE_VIEW_HELPER_H_
-#define CHROME_BROWSER_UI_VIEWS_ACCESSIBLE_VIEW_HELPER_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "base/singleton.h"
-#include "chrome/browser/accessibility_events.h"
-#include "gfx/native_widget_types.h"
-
-#if defined(OS_LINUX)
-#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
-#endif
-
-class AccessibilityEventRouterViews;
-class Profile;
-namespace views {
-class View;
-}
-
-// NOTE: This class is part of the Accessibility Extension API, which lets
-// extensions receive accessibility events. It's distinct from code that
-// implements platform accessibility APIs like MSAA or ATK.
-//
-// Helper class that helps to manage the accessibility information for a
-// view and all of its descendants.  Create an instance of this class for
-// the root of a tree of views (like a dialog) that should send accessibility
-// events for all of its descendants.
-//
-// Most controls have default behavior for accessibility; when this needs
-// to be augmented, call one of the methods below to ignore a particular
-// view or change its details.
-//
-// All of the information managed by this class is registered with the
-// (global) AccessibilityEventRouterViews and unregistered when this object is
-// destroyed.
-class AccessibleViewHelper {
- public:
-  // Constructs an AccessibleViewHelper that makes the given view and all
-  // of its descendants accessible for the lifetime of this object,
-  // sending accessibility notifications to the given profile.
-  AccessibleViewHelper(views::View* view_tree, Profile* profile);
-
-  virtual ~AccessibleViewHelper();
-
-  // Sends a notification that a new window was opened now, and a
-  // corresponding close window notification when this object
-  // goes out of scope.
-  void SendOpenWindowNotification(const std::string& window_title);
-
-  // Uses the following string as the name of this view, instead of
-  // view->GetAccessibleName().
-  void SetViewName(views::View* view, std::string name);
-
-  // Uses the following string id as the name of this view, instead of
-  // view->GetAccessibleName().
-  void SetViewName(views::View* view, int string_id);
-
- private:
-  // Returns a native view if the given view has a native view in it.
-  gfx::NativeView GetNativeView(views::View* view) const;
-
-  AccessibilityEventRouterViews* accessibility_event_router_;
-  Profile* profile_;
-  views::View* view_tree_;
-  std::string window_title_;
-  std::vector<views::View*> managed_views_;
-
-#if defined(OS_LINUX)
-  scoped_ptr<AccessibleWidgetHelper> widget_helper_;
-#endif
-
-  DISALLOW_COPY_AND_ASSIGN(AccessibleViewHelper);
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_ACCESSIBLE_VIEW_HELPER_H_
diff --git a/chrome/browser/ui/views/app_launched_animation_win.cc b/chrome/browser/ui/views/app_launched_animation_win.cc
deleted file mode 100644
index a2007d3..0000000
--- a/chrome/browser/ui/views/app_launched_animation_win.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/app_launched_animation.h"
-
-#include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_icon_set.h"
-#include "chrome/common/extensions/extension_resource.h"
-#include "gfx/rect.h"
-#include "ui/base/animation/animation.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
-#include "views/controls/image_view.h"
-#include "views/widget/widget_win.h"
-
-namespace {
-
-// Start at 1, end at 0
-//    0ms You click the icon
-//    0ms The launcher and contents begins to fade out, the icon
-//        you clicked does not (stays opaque)
-//    0ms The app begins loading behind the launcher
-// +100ms The app icon begins to fade out.
-// +200ms The launcher finishes fading out
-// +350ms The app icon finishes fading out
-
-// How long the fade should take.
-static const int kDurationMS = 250;
-
-// The delay before the fade out should start.
-static const int kDelayMS = 100;
-
-// AppLaunchedAnimation creates an animation. It loads the icon for the
-// extension and once the image is loaded the animation starts. The icon fades
-// out after a short delay.
-class AppLaunchedAnimationWin : public ui::AnimationDelegate,
-                                public ImageLoadingTracker::Observer,
-                                public views::ImageView {
- public:
-  AppLaunchedAnimationWin(const Extension* extension, const gfx::Rect& rect);
-
- private:
-  // ui::AnimationDelegate
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationCanceled(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-
-  // We use a HWND for the popup so that it may float above any HWNDs in our UI.
-  views::WidgetWin* popup_;
-
-  // The rect to use for the popup.
-  gfx::Rect rect_;
-
-  // Used for loading extension application icon.
-  ImageLoadingTracker app_icon_loader_;
-
-  // ImageLoadingTracker::Observer.
-  virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
-                             int index);
-
-  // Hover animation.
-  scoped_ptr<ui::SlideAnimation> animation_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppLaunchedAnimationWin);
-};
-
-AppLaunchedAnimationWin::AppLaunchedAnimationWin(const Extension* extension,
-                                                 const gfx::Rect& rect)
-    : popup_(NULL),
-      rect_(rect),
-      ALLOW_THIS_IN_INITIALIZER_LIST(app_icon_loader_(this)) {
-  DCHECK(extension);
-  app_icon_loader_.LoadImage(
-      extension,
-      extension->GetIconResource(Extension::EXTENSION_ICON_LARGE,
-                                 ExtensionIconSet::MATCH_EXACTLY),
-      rect_.size(),
-      ImageLoadingTracker::DONT_CACHE);
-}
-
-void AppLaunchedAnimationWin::AnimationCanceled(
-    const ui::Animation* animation) {
-  AnimationEnded(animation);
-}
-
-void AppLaunchedAnimationWin::AnimationEnded(const ui::Animation* animation) {
-  popup_->Close();
-}
-
-void AppLaunchedAnimationWin::AnimationProgressed(
-    const ui::Animation* animation) {
-  // GetCurrentValue goes from 1 to 0 since we are hiding.
-  const double current_value = 1.0 - animation->GetCurrentValue();
-  const double current_time = current_value * (kDelayMS + kDurationMS);
-
-  double opacity = 1.0 -
-      std::max(0.0, static_cast<double>(current_time - kDelayMS)) /
-          static_cast<double>(kDurationMS);
-
-  popup_->SetOpacity(static_cast<SkColor>(opacity * 255.0));
-  SchedulePaint();
-}
-
-void AppLaunchedAnimationWin::OnImageLoaded(SkBitmap* image,
-                                            ExtensionResource resource,
-                                            int index) {
-  if (image) {
-    SetImage(image);
-
-    popup_ = new views::WidgetWin;
-    popup_->set_window_style(WS_POPUP);
-    popup_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW |
-                                WS_EX_TRANSPARENT);
-    popup_->SetOpacity(static_cast<SkColor>(255));
-
-    popup_->Init(NULL, rect_);
-    popup_->SetContentsView(this);
-    popup_->Show();
-
-    // Start animation.
-    animation_.reset(new ui::SlideAnimation(this));
-    animation_->SetSlideDuration(kDelayMS + kDurationMS);
-    animation_->SetTweenType(ui::Tween::LINEAR);
-    animation_->Reset(1.0);
-    animation_->Hide();
-  }
-}
-
-}  // namespace
-
-// static
-void AppLaunchedAnimation::Show(const Extension* extension,
-                                const gfx::Rect& rect) {
-  // The animation will delete itself when it's finished.
-  new AppLaunchedAnimationWin(extension, rect);
-}
diff --git a/chrome/browser/ui/views/appcache_info_view.cc b/chrome/browser/ui/views/appcache_info_view.cc
index 03d3919..199d256 100644
--- a/chrome/browser/ui/views/appcache_info_view.cc
+++ b/chrome/browser/ui/views/appcache_info_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/appcache_info_view.h"
+#include "chrome/browser/ui/views/appcache_info_view.h"
 
 #include "base/i18n/time_formatting.h"
 #include "base/string_util.h"
diff --git a/chrome/browser/ui/views/appcache_info_view.h b/chrome/browser/ui/views/appcache_info_view.h
index 141524a..20e1ebc 100644
--- a/chrome/browser/ui/views/appcache_info_view.h
+++ b/chrome/browser/ui/views/appcache_info_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_APPCACHE_INFO_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/generic_info_view.h"
 #include "chrome/browser/browsing_data_appcache_helper.h"
+#include "chrome/browser/ui/views/generic_info_view.h"
 
 // AppCacheInfoView
 // Displays a tabular grid of AppCache information.
diff --git a/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.cc
index 059de7e..e507df5 100644
--- a/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.cc
+++ b/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.cc
@@ -1,15 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
 
-#include "app/bidi_line_iterator.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
-#include "app/text_elider.h"
 #include "base/compiler_specific.h"
+#include "base/i18n/bidi_line_iterator.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
@@ -18,37 +14,41 @@
 #include "chrome/browser/instant/instant_confirm_dialog.h"
 #include "chrome/browser/instant/promo_counter.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/bubble_border.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
-#include "gfx/insets.h"
-#include "gfx/path.h"
+#include "chrome/browser/ui/views/bubble_border.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/path.h"
 #include "unicode/ubidi.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/painter.h"
-#include "views/standard_layout.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
 #if defined(OS_WIN)
-#include <objidl.h>
 #include <commctrl.h>
 #include <dwmapi.h>
+#include <objidl.h>
 
-#include "app/win/hwnd_util.h"
 #include "base/win/scoped_gdi_object.h"
+#include "views/widget/widget_win.h"
 #endif
 
 #if defined(OS_LINUX)
-#include "chrome/browser/gtk/gtk_util.h"
-#include "gfx/skia_utils_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/gfx/skia_utils_gtk.h"
 #endif
 
 namespace {
@@ -108,7 +108,7 @@
   return colors[state][kind];
 }
 
-const wchar_t kEllipsis[] = L"\x2026";
+const char16 kEllipsis[] = { 0x2026 };
 
 const SkAlpha kGlassPopupAlpha = 240;
 const SkAlpha kOpaquePopupAlpha = 255;
@@ -122,8 +122,8 @@
 const int kTextVerticalPadding = 3;
 // The size delta between the font used for the edit and the result rows. Passed
 // to gfx::Font::DeriveFont.
-#if defined(OS_CHROMEOS) && !defined(CROS_FONTS_USING_BCI)
-// Don't adjust font on chromeos as it becomes too small.
+#if defined(OS_CHROMEOS)
+// Don't adjust the size on Chrome OS (http://crbug.com/61433).
 const int kEditFontAdjust = 0;
 #else
 const int kEditFontAdjust = -1;
@@ -214,7 +214,7 @@
     views::ColumnSet* column_set = layout->AddColumnSet(first_column_set);
     column_set->AddColumn(views::GridLayout::TRAILING, v_align, 1,
                           views::GridLayout::USE_PREF, 0, 0);
-    column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     column_set->AddColumn(views::GridLayout::CENTER, v_align, 0,
                           views::GridLayout::USE_PREF, 0, 0);
     column_set->AddPaddingColumn(0, kOptInButtonPadding);
@@ -293,7 +293,7 @@
   // Precalculated data used to draw the portion of a match classification that
   // fits entirely within one run.
   struct ClassificationData {
-    std::wstring text;
+    string16 text;
     const gfx::Font* font;
     SkColor color;
     int pixel_width;
@@ -327,7 +327,7 @@
   // added to all of the classifications. Returns the x position to the right
   // of the string.
   int DrawString(gfx::Canvas* canvas,
-                 const std::wstring& text,
+                 const string16& text,
                  const ACMatchClassifications& classifications,
                  bool force_dim,
                  int x,
@@ -422,7 +422,7 @@
       model_index_(model_index),
       normal_font_(font),
       bold_font_(bold_font),
-      ellipsis_width_(font.GetStringWidth(WideToUTF16(kEllipsis))),
+      ellipsis_width_(font.GetStringWidth(string16(kEllipsis))),
       mirroring_context_(new MirroringContext()),
       match_(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED) {
   CHECK(model_index >= 0);
@@ -442,11 +442,11 @@
     canvas->AsCanvasSkia()->drawColor(GetColor(state, BACKGROUND));
 
   // Paint the icon.
-  canvas->DrawBitmapInt(*GetIcon(), MirroredLeftPointForRect(icon_bounds_),
+  canvas->DrawBitmapInt(*GetIcon(), GetMirroredXForRect(icon_bounds_),
                         icon_bounds_.y());
 
   // Paint the text.
-  int x = MirroredLeftPointForRect(text_bounds_);
+  int x = GetMirroredXForRect(text_bounds_);
   mirroring_context_->Initialize(x, text_bounds_.width());
   x = DrawString(canvas, match_.contents, match_.contents_class, false, x,
                  text_bounds_.y());
@@ -458,8 +458,8 @@
   // would also let us use a more properly-localizable string than we get with
   // just the IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR.
   if (!match_.description.empty()) {
-    std::wstring separator = UTF16ToWide(l10n_util::GetStringUTF16(
-        IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR));
+    string16 separator =
+        l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR);
     ACMatchClassifications classifications;
     classifications.push_back(
         ACMatchClassification(0, ACMatchClassification::NONE));
@@ -525,7 +525,6 @@
       case IDR_OMNIBOX_HTTP:    icon = IDR_OMNIBOX_HTTP_SELECTED; break;
       case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_SELECTED; break;
       case IDR_OMNIBOX_SEARCH:  icon = IDR_OMNIBOX_SEARCH_SELECTED; break;
-      case IDR_OMNIBOX_MORE:    icon = IDR_OMNIBOX_MORE_SELECTED; break;
       case IDR_OMNIBOX_STAR:    icon = IDR_OMNIBOX_STAR_SELECTED; break;
       default:             NOTREACHED(); break;
     }
@@ -535,7 +534,7 @@
 
 int AutocompleteResultView::DrawString(
     gfx::Canvas* canvas,
-    const std::wstring& text,
+    const string16& text,
     const ACMatchClassifications& classifications,
     bool force_dim,
     int x,
@@ -558,7 +557,7 @@
   // worry about whether our eliding might change the visual display in
   // unintended ways, e.g. by removing directional markings or by adding an
   // ellipsis that's not enclosed in appropriate markings.
-  BiDiLineIterator bidi_line;
+  base::i18n::BiDiLineIterator bidi_line;
   if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url))
     return x;
   const int num_runs = bidi_line.CountRuns();
@@ -614,8 +613,7 @@
       else
         current_data->color = GetColor(state, force_dim ? DIMMED_TEXT : TEXT);
       current_data->pixel_width =
-          current_data->font->GetStringWidth(
-              WideToUTF16Hack(current_data->text));
+          current_data->font->GetStringWidth(current_data->text);
       current_run->pixel_width += current_data->pixel_width;
     }
     DCHECK(!current_run->classifications.empty());
@@ -671,8 +669,8 @@
     for (Classifications::const_iterator j(i->classifications.begin());
          j != i->classifications.end(); ++j) {
       int left = mirroring_context_->mirrored_left_coord(x, x + j->pixel_width);
-      canvas->DrawStringInt(j->text, *j->font, j->color, left, y,
-                            j->pixel_width, j->font->GetHeight(), flags);
+      canvas->DrawStringInt(j->text, *j->font, j->color, left,
+                            y, j->pixel_width, j->font->GetHeight(), flags);
       x += j->pixel_width;
     }
   }
@@ -710,9 +708,8 @@
       first_classification = false;
 
       // Can we fit at least an ellipsis?
-      std::wstring elided_text(UTF16ToWideHack(
-          gfx::ElideText(WideToUTF16Hack(j->text), *j->font, remaining_width,
-                         false)));
+      string16 elided_text =
+          ui::ElideText(j->text, *j->font, remaining_width, false);
       Classifications::reverse_iterator prior_classification(j);
       ++prior_classification;
       const bool on_first_classification =
@@ -741,7 +738,7 @@
              (prior_classification->font == &normal_font_)))
           j->font = &normal_font_;
 
-        j->pixel_width = j->font->GetStringWidth(WideToUTF16Hack(elided_text));
+        j->pixel_width = j->font->GetStringWidth(elided_text);
 
         // Erase any other classifications that come after the elided one.
         i->classifications.erase(j.base(), i->classifications.end());
@@ -840,7 +837,7 @@
   // Update the match cached by each row, in the process of doing so make sure
   // we have enough row views.
   int total_child_height = 0;
-  size_t child_rv_count = GetChildViewCount();
+  size_t child_rv_count = child_count();
   if (opt_in_view_) {
     DCHECK(child_rv_count > 0);
     child_rv_count--;
@@ -850,7 +847,7 @@
     if (i >= child_rv_count) {
       result_view =
           new AutocompleteResultView(this, i, result_font_, result_bold_font_);
-      AddChildView(static_cast<int>(i), result_view);
+      AddChildViewAt(result_view, static_cast<int>(i));
     } else {
       result_view = static_cast<AutocompleteResultView*>(GetChildViewAt(i));
       result_view->SetVisible(true);
@@ -980,7 +977,7 @@
   shader->unref();
 
   gfx::Path path;
-  MakeContentsPath(&path, GetLocalBounds(false));
+  MakeContentsPath(&path, GetContentsBounds());
   canvas->AsCanvasSkia()->drawPath(path, paint);
 
   // Now we paint the border, so it will be alpha-blended atop the contents.
@@ -993,10 +990,9 @@
   UpdateBlurRegion();
 
   // Size our children to the available content area.
-  gfx::Rect contents_rect = GetLocalBounds(false);
-  int child_count = GetChildViewCount();
+  gfx::Rect contents_rect = GetContentsBounds();
   int top = contents_rect.y();
-  for (int i = 0; i < child_count; ++i) {
+  for (int i = 0; i < child_count(); ++i) {
     View* v = GetChildViewAt(i);
     if (v->IsVisible()) {
       v->SetBounds(contents_rect.x(), top, contents_rect.width(),
@@ -1033,7 +1029,7 @@
     size_t index = GetIndexForPoint(event.location());
     model_->SetHoveredLine(index);
     if (HasMatchAt(index) && event.IsLeftMouseButton())
-      model_->SetSelectedLine(index, false);
+      model_->SetSelectedLine(index, false, false);
   }
   return true;
 }
@@ -1059,7 +1055,7 @@
     size_t index = GetIndexForPoint(event.location());
     model_->SetHoveredLine(index);
     if (!ignore_mouse_drag_ && HasMatchAt(index) && event.IsLeftMouseButton())
-      model_->SetSelectedLine(index, false);
+      model_->SetSelectedLine(index, false, false);
   }
   return true;
 }
@@ -1074,7 +1070,7 @@
   views::View* child = views::View::GetViewForPoint(point);
   views::View* ancestor = child;
   while (ancestor && ancestor != opt_in_view_)
-    ancestor = ancestor->GetParent();
+    ancestor = ancestor->parent();
   return ancestor ? child : this;
 }
 
@@ -1107,7 +1103,7 @@
 void AutocompletePopupContentsView::UpdateBlurRegion() {
 #if defined(OS_WIN)
   // We only support background blurring on Vista with Aero-Glass enabled.
-  if (!app::win::ShouldUseVistaFrame() || !GetWidget())
+  if (!views::WidgetWin::IsAeroGlassEnabled() || !GetWidget())
     return;
 
   // Provide a blurred background effect within the contents region of the
@@ -1118,7 +1114,7 @@
 
   // Translate the contents rect into widget coordinates, since that's what
   // DwmEnableBlurBehindWindow expects a region in.
-  gfx::Rect contents_rect = GetLocalBounds(false);
+  gfx::Rect contents_rect = GetContentsBounds();
   gfx::Point origin(contents_rect.origin());
   views::View::ConvertPointToWidget(this, &origin);
   contents_rect.set_origin(origin);
@@ -1153,10 +1149,10 @@
   // extension, |match| and its contents.  So copy the relevant strings out to
   // make sure they stay alive until the call completes.
   const GURL url(match.destination_url);
-  std::wstring keyword;
+  string16 keyword;
   const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword);
   edit_view_->OpenURL(url, disposition, match.transition, GURL(), index,
-                      is_keyword_hint ? std::wstring() : keyword);
+                      is_keyword_hint ? string16() : keyword);
 }
 
 size_t AutocompletePopupContentsView::GetIndexForPoint(
@@ -1165,7 +1161,7 @@
     return AutocompletePopupModel::kNoMatch;
 
   int nb_match = model_->result().size();
-  DCHECK(nb_match <= GetChildViewCount());
+  DCHECK(nb_match <= child_count());
   for (int i = 0; i < nb_match; ++i) {
     views::View* child = GetChildViewAt(i);
     gfx::Point point_in_child_coords(point);
@@ -1177,7 +1173,7 @@
 }
 
 gfx::Rect AutocompletePopupContentsView::CalculateTargetBounds(int h) {
-  gfx::Rect location_bar_bounds(gfx::Point(), location_bar_->size());
+  gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds());
   const views::Border* border = location_bar_->border();
   if (border) {
     // Adjust for the border so that the bubble and location bar borders are
diff --git a/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h b/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h
index 72cb7bd..b1af5e3 100644
--- a/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h
+++ b/chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,16 +9,16 @@
 #include "chrome/browser/autocomplete/autocomplete.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_view.h"
-#include "gfx/font.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/gfx/font.h"
 #include "views/view.h"
 #include "webkit/glue/window_open_disposition.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/views/autocomplete/autocomplete_popup_win.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_win.h"
 #else
-#include "chrome/browser/views/autocomplete/autocomplete_popup_gtk.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.h"
 #endif
 
 class AutocompleteEditModel;
diff --git a/chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.cc b/chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.cc
index 4bb7f09..e62db24 100644
--- a/chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.cc
+++ b/chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/autocomplete/autocomplete_popup_gtk.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.h"
 
 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h"
-#include "gfx/insets.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
+#include "ui/gfx/insets.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // AutocompletePopupGtk, public:
diff --git a/chrome/browser/ui/views/autocomplete/autocomplete_popup_win.cc b/chrome/browser/ui/views/autocomplete/autocomplete_popup_win.cc
index e720108..da76989 100644
--- a/chrome/browser/ui/views/autocomplete/autocomplete_popup_win.cc
+++ b/chrome/browser/ui/views/autocomplete/autocomplete_popup_win.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/autocomplete/autocomplete_popup_win.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_win.h"
 
 #include "chrome/browser/autocomplete/autocomplete_edit_view_win.h"
 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h"
-#include "gfx/insets.h"
+#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
+#include "ui/gfx/insets.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // AutocompletePopupWin, public:
diff --git a/chrome/browser/ui/views/autofill_profiles_view_win.cc b/chrome/browser/ui/views/autofill_profiles_view_win.cc
index d7f1cc8..04ca0e1 100644
--- a/chrome/browser/ui/views/autofill_profiles_view_win.cc
+++ b/chrome/browser/ui/views/autofill_profiles_view_win.cc
@@ -1,14 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/autofill_profiles_view_win.h"
+#include "chrome/browser/ui/views/autofill_profiles_view_win.h"
 
 #include <vsstyle.h>
 #include <vssym32.h>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/string16.h"
 #include "base/string_number_conversions.h"
@@ -26,14 +24,16 @@
 #include "chrome/browser/ui/window_sizer.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas.h"
-#include "gfx/native_theme_win.h"
-#include "gfx/size.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/native_theme_win.h"
+#include "ui/gfx/size.h"
 #include "views/border.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/button/native_button.h"
@@ -43,8 +43,8 @@
 #include "views/controls/scroll_view.h"
 #include "views/controls/separator.h"
 #include "views/controls/table/table_view.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 namespace {
@@ -468,7 +468,7 @@
   remove_button_ = new views::NativeButton(this,
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_AUTOFILL_DELETE_BUTTON)));
 
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int table_with_buttons_column_view_set_id = 0;
@@ -476,14 +476,14 @@
       layout->AddColumnSet(table_with_buttons_column_view_set_id);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                         views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0,
                         views::GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, table_with_buttons_column_view_set_id);
   layout->AddView(enable_auto_fill_button_, 3, 1, views::GridLayout::FILL,
                   views::GridLayout::FILL);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, table_with_buttons_column_view_set_id);
   layout->AddView(scroll_view_, 1, 8, views::GridLayout::FILL,
@@ -491,17 +491,17 @@
   layout->AddView(add_address_button_);
 
   layout->StartRowWithPadding(0, table_with_buttons_column_view_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(2);
   layout->AddView(add_credit_card_button_);
 
   layout->StartRowWithPadding(0, table_with_buttons_column_view_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(2);
   layout->AddView(edit_button_);
 
   layout->StartRowWithPadding(0, table_with_buttons_column_view_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(2);
   layout->AddView(remove_button_);
 
@@ -629,7 +629,7 @@
         layout->AddColumnSet(two_column_fill_view_set_id);
     column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
         views::GridLayout::USE_PREF, 0, 0);
-    column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0,
         views::GridLayout::USE_PREF, 0, 0);
     layout->StartRow(0, two_column_fill_view_set_id);
@@ -926,21 +926,21 @@
         AutoFillType(address_fields_[field].type)));
   }
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_FULL_NAME));
 
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(text_fields_[TEXT_FULL_NAME]);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_COMPANY_NAME));
 
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(text_fields_[TEXT_COMPANY]);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_leading_view_set_id_);
   layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
                   IDS_AUTOFILL_DIALOG_ADDRESS_LINE_1))));
@@ -948,7 +948,7 @@
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(text_fields_[TEXT_ADDRESS_LINE_1]);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_leading_view_set_id_);
   layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
                   IDS_AUTOFILL_DIALOG_ADDRESS_LINE_2))));
@@ -956,7 +956,7 @@
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(text_fields_[TEXT_ADDRESS_LINE_2]);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, triple_column_fill_view_set_id_);
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_CITY));
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_STATE));
@@ -971,7 +971,7 @@
   layout->AddView(text_fields_[TEXT_ADDRESS_STATE]);
   layout->AddView(text_fields_[TEXT_ADDRESS_ZIP]);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_COUNTRY));
 
@@ -994,12 +994,12 @@
 
   phone_sub_views_.push_back(fax);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(phone);
   layout->AddView(fax);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_EMAIL));
 
@@ -1047,14 +1047,14 @@
     text_fields_[credit_card_fields_[field].text_field]->SetText(field_text);
   }
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_NAME_ON_CARD));
   layout->StartRow(0, double_column_fill_view_set_id_);
   layout->AddView(text_fields_[TEXT_CC_NAME]);
 
   // Layout credit card info
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_ccnumber_cvc_);
   layout->AddView(
       CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER));
@@ -1063,7 +1063,7 @@
   text_fields_[TEXT_CC_NUMBER]->set_default_width_in_chars(20);
   layout->AddView(text_fields_[TEXT_CC_NUMBER]);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_ccexpiration_);
   layout->AddView(
       CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_EXPIRATION_DATE), 3, 1);
@@ -1096,28 +1096,28 @@
   int i;
   for (i = 0; i < 2; ++i) {
     if (i)
-      column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+      column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
                           views::GridLayout::USE_PREF, 0, 0);
   }
   column_set = layout->AddColumnSet(double_column_leading_view_set_id_);
   for (i = 0; i < 2; ++i) {
     if (i)
-      column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+      column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
                           1, views::GridLayout::USE_PREF, 0, 0);
   }
   column_set = layout->AddColumnSet(triple_column_fill_view_set_id_);
   for (i = 0; i < 3; ++i) {
     if (i)
-      column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+      column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
                           views::GridLayout::USE_PREF, 0, 0);
   }
   column_set = layout->AddColumnSet(triple_column_leading_view_set_id_);
   for (i = 0; i < 3; ++i) {
     if (i)
-      column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+      column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
                           1, views::GridLayout::USE_PREF, 0, 0);
   }
@@ -1125,13 +1125,13 @@
   column_set = layout->AddColumnSet(four_column_city_state_zip_set_id_);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                         16, views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                         16, views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                         5, views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                         11, views::GridLayout::USE_PREF, 0, 0);
 
@@ -1139,7 +1139,7 @@
   // Number and CVC are in ratio 20:4
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                         20, views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                         4, views::GridLayout::USE_PREF, 0, 0);
 
@@ -1153,7 +1153,7 @@
   column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
                         0, views::GridLayout::FIXED,
                         font.GetStringWidth(ASCIIToUTF16("000000")), 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
                         0, views::GridLayout::FIXED,
                         font.GetStringWidth(ASCIIToUTF16("00000000")), 0);
@@ -1161,10 +1161,10 @@
   column_set = layout->AddColumnSet(three_column_header_);
   column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
                         0, views::GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
                         1, views::GridLayout::FIXED, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
                         1, views::GridLayout::FIXED, 0, 0);
 }
@@ -1278,10 +1278,11 @@
   }
 }
 
-TableModel::Groups AutoFillProfilesView::ContentListTableModel::GetGroups() {
-  TableModel::Groups groups;
+ui::TableModel::Groups
+    AutoFillProfilesView::ContentListTableModel::GetGroups() {
+  ui::TableModel::Groups groups;
 
-  TableModel::Group profile_group;
+  ui::TableModel::Group profile_group;
   profile_group.title =
       l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESSES_GROUP_NAME);
   profile_group.id = kAddressGroup;
@@ -1303,7 +1304,7 @@
 }
 
 void AutoFillProfilesView::ContentListTableModel::SetObserver(
-    TableModelObserver* observer) {
+    ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
diff --git a/chrome/browser/ui/views/autofill_profiles_view_win.h b/chrome/browser/ui/views/autofill_profiles_view_win.h
index b758b5a..45eabaf 100644
--- a/chrome/browser/ui/views/autofill_profiles_view_win.h
+++ b/chrome/browser/ui/views/autofill_profiles_view_win.h
@@ -10,8 +10,6 @@
 #include <map>
 #include <vector>
 
-#include "app/combobox_model.h"
-#include "app/table_model.h"
 #include "base/compiler_specific.h"
 #include "base/string16.h"
 #include "chrome/browser/autofill/autofill_dialog.h"
@@ -19,6 +17,8 @@
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/common/notification_observer.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/base/models/table_model.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/link.h"
 #include "views/controls/table/table_view_observer.h"
@@ -358,7 +358,7 @@
     DISALLOW_COPY_AND_ASSIGN(EditableSetViewContents);
   };
 
-  class StringVectorComboboxModel : public ComboboxModel {
+  class StringVectorComboboxModel : public ui::ComboboxModel {
    public:
     StringVectorComboboxModel() {}
     virtual ~StringVectorComboboxModel() {}
@@ -367,7 +367,7 @@
     // |source|.
     void set_cb_strings(std::vector<std::wstring> *source);
 
-    // Overridden from ComboboxModel:
+    // Overridden from ui::ComboboxModel:
     virtual int GetItemCount();
     virtual string16 GetItemAt(int index);
 
@@ -381,7 +381,7 @@
   };
 
   // Model for scrolling credit cards and addresses.
-  class ContentListTableModel : public TableModel {
+  class ContentListTableModel : public ui::TableModel {
    public:
     ContentListTableModel(std::vector<EditableSetInfo>* profiles,
                           std::vector<EditableSetInfo>* credit_cards);
@@ -398,18 +398,18 @@
     void RemoveItem(int index);
     void UpdateItem(int index);
 
-    // TableModel members:
+    // ui::TableModel members:
     virtual int RowCount() OVERRIDE;
     virtual string16 GetText(int row, int column_id) OVERRIDE;
     virtual bool HasGroups() OVERRIDE { return true; }
-    virtual TableModel::Groups GetGroups() OVERRIDE;
+    virtual ui::TableModel::Groups GetGroups() OVERRIDE;
     virtual int GetGroupID(int row) OVERRIDE;
-    virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+    virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
    private:
     std::vector<EditableSetInfo>* profiles_;
     std::vector<EditableSetInfo>* credit_cards_;
-    TableModelObserver* observer_;
+    ui::TableModelObserver* observer_;
 
     DISALLOW_COPY_AND_ASSIGN(ContentListTableModel);
   };
diff --git a/chrome/browser/ui/views/bookmark_bar_instructions_view.cc b/chrome/browser/ui/views/bookmark_bar_instructions_view.cc
index 36af2a6..b4c3351 100644
--- a/chrome/browser/ui/views/bookmark_bar_instructions_view.cc
+++ b/chrome/browser/ui/views/bookmark_bar_instructions_view.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_bar_instructions_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_instructions_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
 
 using views::View;
@@ -38,7 +38,7 @@
 
 gfx::Size BookmarkBarInstructionsView::GetPreferredSize() {
   int ascent = 0, descent = 0, height = 0, width = 0;
-  for (int i = 0; i < GetChildViewCount(); ++i) {
+  for (int i = 0; i < child_count(); ++i) {
     View* view = GetChildViewAt(i);
     gfx::Size pref = view->GetPreferredSize();
     int baseline = view->GetBaseline();
@@ -50,7 +50,7 @@
     }
     width += pref.width();
   }
-  width += (GetChildViewCount() - 1) * kViewPadding;
+  width += (child_count() - 1) * kViewPadding;
   if (ascent != 0)
     height = std::max(ascent + descent, height);
   return gfx::Size(width, height);
@@ -59,7 +59,7 @@
 void BookmarkBarInstructionsView::Layout() {
   int remaining_width = width();
   int x = 0;
-  for (int i = 0; i < GetChildViewCount(); ++i) {
+  for (int i = 0; i < child_count(); ++i) {
     View* view = GetChildViewAt(i);
     gfx::Size pref = view->GetPreferredSize();
     int baseline = view->GetBaseline();
@@ -97,7 +97,7 @@
 
 void BookmarkBarInstructionsView::UpdateColors() {
   // We don't always have a theme provider (ui tests, for example).
-  const ThemeProvider* theme_provider = GetThemeProvider();
+  const ui::ThemeProvider* theme_provider = GetThemeProvider();
   if (!theme_provider)
     return;
   updated_colors_ = true;
diff --git a/chrome/browser/ui/views/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmark_bar_view.cc
index 42f481e..af27fec 100644
--- a/chrome/browser/ui/views/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmark_bar_view.cc
@@ -1,18 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 
 #include <algorithm>
 #include <limits>
 #include <set>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/os_exchange_data.h"
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
 #include "base/i18n/rtl.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -38,11 +34,15 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/page_transition_types.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/label.h"
 #include "views/controls/menu/menu_item_view.h"
@@ -53,7 +53,7 @@
 #include "views/window/window.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/views/importer_view.h"
+#include "chrome/browser/ui/views/importer_view.h"
 #endif
 
 using views::CustomButton;
@@ -126,46 +126,6 @@
 
 namespace {
 
-// Returns the tooltip text for the specified url and title. The returned
-// text is clipped to fit within the bounds of the monitor.
-//
-// Note that we adjust the direction of both the URL and the title based on the
-// locale so that pure LTR strings are displayed properly in RTL locales.
-static std::wstring CreateToolTipForURLAndTitle(const gfx::Point& screen_loc,
-                                                const GURL& url,
-                                                const std::wstring& title,
-                                                const std::wstring& languages) {
-  int max_width = views::TooltipManager::GetMaxWidth(screen_loc.x(),
-                                                     screen_loc.y());
-  gfx::Font tt_font = views::TooltipManager::GetDefaultFont();
-  std::wstring result;
-
-  // First the title.
-  if (!title.empty()) {
-    std::wstring localized_title = title;
-    base::i18n::AdjustStringForLocaleDirection(&localized_title);
-    result.append(UTF16ToWideHack(gfx::ElideText(WideToUTF16Hack(
-        localized_title), tt_font, max_width, false)));
-  }
-
-  // Only show the URL if the url and title differ.
-  if (title != UTF8ToWide(url.spec())) {
-    if (!result.empty())
-      result.append(views::TooltipManager::GetLineSeparator());
-
-    // We need to explicitly specify the directionality of the URL's text to
-    // make sure it is treated as an LTR string when the context is RTL. For
-    // example, the URL "http://www.yahoo.com/" appears as
-    // "/http://www.yahoo.com" when rendered, as is, in an RTL context since
-    // the Unicode BiDi algorithm puts certain characters on the left by
-    // default.
-    string16 elided_url(gfx::ElideUrl(url, tt_font, max_width, languages));
-    elided_url = base::i18n::GetDisplayStringInLTRDirectionality(elided_url);
-    result.append(UTF16ToWideHack(elided_url));
-  }
-  return result;
-}
-
 // BookmarkButton -------------------------------------------------------------
 
 // Buttons used for the bookmarks on the bookmark bar.
@@ -192,8 +152,8 @@
   bool GetTooltipText(const gfx::Point& p, std::wstring* tooltip) {
     gfx::Point location(p);
     ConvertPointToScreen(this, &location);
-    *tooltip = CreateToolTipForURLAndTitle(location, url_, text(),
-        UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)));
+    *tooltip = BookmarkBarView::CreateToolTipForURLAndTitle(location, url_,
+        text(), profile_);
     return !tooltip->empty();
   }
 
@@ -233,12 +193,12 @@
   virtual bool IsTriggerableEvent(const views::MouseEvent& e) {
     // Left clicks should show the menu contents and right clicks should show
     // the context menu. They should not trigger the opening of underlying urls.
-    if (e.GetFlags() == views::MouseEvent::EF_LEFT_BUTTON_DOWN ||
-        e.GetFlags() == views::MouseEvent::EF_RIGHT_BUTTON_DOWN)
+    if (e.flags() == ui::EF_LEFT_BUTTON_DOWN ||
+        e.flags() == ui::EF_RIGHT_BUTTON_DOWN)
       return false;
 
     WindowOpenDisposition disposition(
-        event_utils::DispositionFromEventFlags(e.GetFlags()));
+        event_utils::DispositionFromEventFlags(e.flags()));
     return disposition != CURRENT_TAB;
   }
 
@@ -497,11 +457,6 @@
   LayoutItems(false);
 }
 
-void BookmarkBarView::DidChangeBounds(const gfx::Rect& previous,
-                                      const gfx::Rect& current) {
-  Layout();
-}
-
 void BookmarkBarView::ViewHierarchyChanged(bool is_add,
                                            View* parent,
                                            View* child) {
@@ -513,8 +468,8 @@
 
     if (height() > 0) {
       // We only layout while parented. When we become parented, if our bounds
-      // haven't changed, DidChangeBounds won't get invoked and we won't layout.
-      // Therefore we always force a layout when added.
+      // haven't changed, OnBoundsChanged() won't get invoked and we won't
+      // layout. Therefore we always force a layout when added.
       Layout();
     }
   }
@@ -552,7 +507,7 @@
                                y,
                                kDropIndicatorWidth,
                                h);
-    indicator_bounds.set_x(MirroredLeftPointForRect(indicator_bounds));
+    indicator_bounds.set_x(GetMirroredXForRect(indicator_bounds));
 
     // TODO(sky/glen): make me pretty!
     canvas->FillRectInt(kDropIndicatorColor, indicator_bounds.x(),
@@ -563,10 +518,10 @@
 
 bool BookmarkBarView::GetDropFormats(
       int* formats,
-      std::set<OSExchangeData::CustomFormat>* custom_formats) {
+      std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
   if (!model_ || !model_->IsLoaded())
     return false;
-  *formats = OSExchangeData::URL;
+  *formats = ui::OSExchangeData::URL;
   custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat());
   return true;
 }
@@ -575,7 +530,7 @@
   return true;
 }
 
-bool BookmarkBarView::CanDrop(const OSExchangeData& data) {
+bool BookmarkBarView::CanDrop(const ui::OSExchangeData& data) {
   if (!model_ || !model_->IsLoaded())
     return false;
 
@@ -674,7 +629,7 @@
     bookmark_drop_menu_->Cancel();
 
   if (!drop_info_.get() || !drop_info_->drag_operation)
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
 
   const BookmarkNode* root =
       drop_info_->is_over_other ? model_->other_node() :
@@ -822,7 +777,7 @@
   if (loc.x() < 0 || loc.x() >= width() || loc.y() < 0 || loc.y() >= height())
     return NULL;
 
-  gfx::Point adjusted_loc(MirroredXCoordinateInsideView(loc.x()), loc.y());
+  gfx::Point adjusted_loc(GetMirroredXInView(loc.x()), loc.y());
 
   // Check the buttons first.
   for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
@@ -915,7 +870,7 @@
 
   bookmarks_separator_view_ = new ButtonSeparatorView();
   bookmarks_separator_view_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_SEPARATOR)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_SEPARATOR));
   AddChildView(bookmarks_separator_view_);
 
   instructions_ = new BookmarkBarInstructionsView(this);
@@ -937,7 +892,7 @@
   button->SetContextMenuController(this);
   button->set_tag(kOtherFolderButtonTag);
   button->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_BOOKMARKED)));
+      l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_BOOKMARKED));
   return button;
 }
 
@@ -959,7 +914,7 @@
   button->SetVisible(false);
   // Set accessibility name.
   button->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS_CHEVRON)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS_CHEVRON));
   return button;
 }
 
@@ -972,8 +927,9 @@
   DCHECK(node && model_->other_node());
   // Create a button for each of the children on the bookmark bar.
   for (int i = 0, child_count = node->GetChildCount(); i < child_count; ++i)
-    AddChildView(i, CreateBookmarkButton(node->GetChild(i)));
+    AddChildViewAt(CreateBookmarkButton(node->GetChild(i)), i);
   UpdateColors();
+  UpdateOtherBookmarksVisibility();
   other_bookmarked_button_->SetEnabled(true);
 
   Layout();
@@ -1011,6 +967,7 @@
 void BookmarkBarView::BookmarkNodeAddedImpl(BookmarkModel* model,
                                             const BookmarkNode* parent,
                                             int index) {
+  UpdateOtherBookmarksVisibility();
   NotifyModelChanged();
   if (parent != model_->GetBookmarkBarNode()) {
     // We only care about nodes on the bookmark bar.
@@ -1021,7 +978,7 @@
   if (!throbbing_view_ && sync_service_ && sync_service_->SetupInProgress()) {
     StartThrobbing(node, true);
   }
-  AddChildView(index, CreateBookmarkButton(node));
+  AddChildViewAt(CreateBookmarkButton(node), index);
   UpdateColors();
   Layout();
   SchedulePaint();
@@ -1037,6 +994,8 @@
 void BookmarkBarView::BookmarkNodeRemovedImpl(BookmarkModel* model,
                                               const BookmarkNode* parent,
                                               int index) {
+  UpdateOtherBookmarksVisibility();
+
   StopThrobbing(true);
   // No need to start throbbing again as the bookmark bubble can't be up at
   // the same time as the user reorders.
@@ -1095,7 +1054,7 @@
 
   // Create the new buttons.
   for (int i = 0, child_count = node->GetChildCount(); i < child_count; ++i)
-    AddChildView(i, CreateBookmarkButton(node->GetChild(i)));
+    AddChildViewAt(CreateBookmarkButton(node->GetChild(i)), i);
   UpdateColors();
 
   Layout();
@@ -1109,7 +1068,7 @@
 
 void BookmarkBarView::WriteDragData(View* sender,
                                     const gfx::Point& press_pt,
-                                    OSExchangeData* data) {
+                                    ui::OSExchangeData* data) {
   UserMetrics::RecordAction(UserMetricsAction("BookmarkBar_DragButton"),
                             profile_);
 
@@ -1118,8 +1077,8 @@
       views::TextButton* button = GetBookmarkButton(i);
       gfx::CanvasSkia canvas(button->width(), button->height(), false);
       button->Paint(&canvas, true);
-      drag_utils::SetDragImageOnDataObject(canvas, button->size(),
-                                           press_pt, data);
+      drag_utils::SetDragImageOnDataObject(canvas, button->size(), press_pt,
+                                           data);
       WriteDragData(model_->GetBookmarkBarNode()->GetChild(i), data);
       return;
     }
@@ -1134,7 +1093,7 @@
     // the new tab page, on the new tab page size_animation_ is always 0). This
     // typically is only hit if the user does something to inadvertanty trigger
     // dnd, such as pressing the mouse and hitting control-b.
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
   }
 
   for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
@@ -1144,7 +1103,7 @@
     }
   }
   NOTREACHED();
-  return DragDropTypes::DRAG_NONE;
+  return ui::DragDropTypes::DRAG_NONE;
 }
 
 bool BookmarkBarView::CanStartDrag(views::View* sender,
@@ -1172,7 +1131,7 @@
 }
 
 void BookmarkBarView::WriteDragData(const BookmarkNode* node,
-                                    OSExchangeData* data) {
+                                    ui::OSExchangeData* data) {
   DCHECK(node && data);
   BookmarkNodeData drag_data(node);
   drag_data.Write(profile_, data);
@@ -1188,7 +1147,7 @@
     node = model_->GetBookmarkBarNode();
     start_index = GetFirstHiddenNodeIndex();
   } else {
-    int button_index = GetChildIndex(view);
+    int button_index = GetIndexOf(view);
     DCHECK_NE(-1, button_index);
     node = model_->GetBookmarkBarNode()->GetChild(button_index);
   }
@@ -1205,7 +1164,7 @@
   if (sender->tag() == kSyncErrorButtonTag) {
     DCHECK(sender == sync_error_button_);
     DCHECK(sync_service_ && !sync_service_->IsManaged());
-    sync_service_->ShowLoginDialog(GetWindow()->GetNativeWindow());
+    sync_service_->ShowErrorUI(GetWindow()->GetNativeWindow());
     return;
   }
 
@@ -1213,7 +1172,7 @@
   if (sender->tag() == kOtherFolderButtonTag) {
     node = model_->other_node();
   } else {
-    int index = GetChildIndex(sender);
+    int index = GetIndexOf(sender);
     DCHECK_NE(-1, index);
     node = model_->GetBookmarkBarNode()->GetChild(index);
   }
@@ -1251,7 +1210,7 @@
   } else if (source != this) {
     // User clicked on one of the bookmark buttons, find which one they
     // clicked on.
-    int bookmark_button_index = GetChildIndex(source);
+    int bookmark_button_index = GetIndexOf(source);
     DCHECK(bookmark_button_index != -1 &&
            bookmark_button_index < GetBookmarkButtonCount());
     const BookmarkNode* node =
@@ -1288,7 +1247,7 @@
 void BookmarkBarView::ConfigureButton(const BookmarkNode* node,
                                       views::TextButton* button) {
   button->SetText(UTF16ToWide(node->GetTitle()));
-  button->SetAccessibleName(UTF16ToWide(node->GetTitle()));
+  button->SetAccessibleName(node->GetTitle());
   button->SetID(VIEW_ID_BOOKMARK_BAR_ELEMENT);
   // We don't always have a theme provider (ui tests, for example).
   if (GetThemeProvider()) {
@@ -1416,7 +1375,7 @@
   // right-to-left on RTL locales). Thus, in order to make sure the drop
   // coordinates calculation works, we mirror the event's X coordinate if the
   // locale is RTL.
-  int mirrored_x = MirroredXCoordinateInsideView(event.x());
+  int mirrored_x = GetMirroredXInView(event.x());
 
   *index = -1;
   *drop_on = false;
@@ -1426,7 +1385,7 @@
       event.y() >= other_bookmarked_button_->y() +
                       other_bookmarked_button_->height()) {
     // Mouse isn't over a button.
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
   }
 
   bool found = false;
@@ -1441,11 +1400,10 @@
     // No bookmarks, accept the drop.
     *index = 0;
     int ops = data.GetFirstNode(profile_)
-        ? DragDropTypes::DRAG_MOVE
-        : DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
-    return
-        bookmark_utils::PreferredDropOperation(event.GetSourceOperations(),
-                                               ops);
+        ? ui::DragDropTypes::DRAG_MOVE
+        : ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK;
+    return bookmark_utils::PreferredDropOperation(event.source_operations(),
+                                                  ops);
   }
 
   for (int i = 0; i < GetBookmarkButtonCount() &&
@@ -1488,14 +1446,14 @@
         // use the last visible index.
         *index = GetFirstHiddenNodeIndex();
       } else {
-        return DragDropTypes::DRAG_NONE;
+        return ui::DragDropTypes::DRAG_NONE;
       }
     } else if (mirrored_x < other_bookmarked_button_->x()) {
       // Mouse is after the last visible button but before more recently
       // bookmarked; use the last visible index.
       *index = GetFirstHiddenNodeIndex();
     } else {
-      return DragDropTypes::DRAG_NONE;
+      return ui::DragDropTypes::DRAG_NONE;
     }
   }
 
@@ -1560,10 +1518,10 @@
 }
 
 int BookmarkBarView::GetBookmarkButtonCount() {
-  // We contain at least four non-bookmark button views: other bookmarks,
-  // bookmarks separator, chevrons (for overflow), the instruction label and
-  // the sync error button.
-  return GetChildViewCount() - 5;
+  // We contain five non-bookmark button views: other bookmarks, bookmarks
+  // separator, chevrons (for overflow), the instruction label and the sync
+  // error button.
+  return child_count() - 5;
 }
 
 void BookmarkBarView::StopThrobbing(bool immediate) {
@@ -1575,9 +1533,48 @@
   throbbing_view_ = NULL;
 }
 
+// static
+std::wstring BookmarkBarView::CreateToolTipForURLAndTitle(
+    const gfx::Point& screen_loc,
+    const GURL& url,
+    const std::wstring& title,
+    Profile* profile) {
+  int max_width = views::TooltipManager::GetMaxWidth(screen_loc.x(),
+                                                     screen_loc.y());
+  gfx::Font tt_font = views::TooltipManager::GetDefaultFont();
+  std::wstring result;
+
+  // First the title.
+  if (!title.empty()) {
+    std::wstring localized_title = title;
+    base::i18n::AdjustStringForLocaleDirection(&localized_title);
+    result.append(UTF16ToWideHack(ui::ElideText(WideToUTF16Hack(
+        localized_title), tt_font, max_width, false)));
+  }
+
+  // Only show the URL if the url and title differ.
+  if (title != UTF8ToWide(url.spec())) {
+    if (!result.empty())
+      result.append(views::TooltipManager::GetLineSeparator());
+
+    // We need to explicitly specify the directionality of the URL's text to
+    // make sure it is treated as an LTR string when the context is RTL. For
+    // example, the URL "http://www.yahoo.com/" appears as
+    // "/http://www.yahoo.com" when rendered, as is, in an RTL context since
+    // the Unicode BiDi algorithm puts certain characters on the left by
+    // default.
+    std::wstring languages =
+        UTF8ToWide(profile->GetPrefs()->GetString(prefs::kAcceptLanguages));
+    string16 elided_url(ui::ElideUrl(url, tt_font, max_width, languages));
+    elided_url = base::i18n::GetDisplayStringInLTRDirectionality(elided_url);
+    result.append(UTF16ToWideHack(elided_url));
+  }
+  return result;
+}
+
 void BookmarkBarView::UpdateColors() {
   // We don't always have a theme provider (ui tests, for example).
-  const ThemeProvider* theme_provider = GetThemeProvider();
+  const ui::ThemeProvider* theme_provider = GetThemeProvider();
   if (!theme_provider)
     return;
   SkColor text_color =
@@ -1587,9 +1584,15 @@
   other_bookmarked_button()->SetEnabledColor(text_color);
 }
 
+void BookmarkBarView::UpdateOtherBookmarksVisibility() {
+  bool has_other_children = model_->other_node()->GetChildCount() > 0;
+  other_bookmarked_button_->SetVisible(has_other_children);
+  bookmarks_separator_view_->SetVisible(has_other_children);
+}
+
 gfx::Size BookmarkBarView::LayoutItems(bool compute_bounds_only) {
   gfx::Size prefsize;
-  if (!GetParent() && !compute_bounds_only)
+  if (!parent() && !compute_bounds_only)
     return prefsize;
 
   int x = kLeftMargin;
@@ -1614,7 +1617,8 @@
   }
 
   gfx::Size other_bookmarked_pref =
-      other_bookmarked_button_->GetPreferredSize();
+      other_bookmarked_button_->IsVisible() ?
+      other_bookmarked_button_->GetPreferredSize() : gfx::Size();
   gfx::Size overflow_pref = overflow_button_->GetPreferredSize();
   gfx::Size bookmarks_separator_pref =
       bookmarks_separator_view_->GetPreferredSize();
@@ -1624,9 +1628,10 @@
   if (sync_ui_util::ShouldShowSyncErrorButton(sync_service_)) {
     sync_error_total_width += kButtonPadding + sync_error_button_pref.width();
   }
-  const int max_x = width - other_bookmarked_pref.width() - kButtonPadding -
-      overflow_pref.width() - kButtonPadding -
+  int max_x = width - overflow_pref.width() - kButtonPadding -
       bookmarks_separator_pref.width() - sync_error_total_width;
+  if (other_bookmarked_button_->IsVisible())
+    max_x -= other_bookmarked_pref.width() + kButtonPadding;
 
   // Next, layout out the buttons. Any buttons that are placed beyond the
   // visible region and made invisible.
@@ -1675,22 +1680,26 @@
   x += overflow_pref.width();
 
   // Separator.
-  if (!compute_bounds_only) {
-    bookmarks_separator_view_->SetBounds(x,
-                                         y - top_margin,
-                                         bookmarks_separator_pref.width(),
-                                         height + top_margin + kBottomMargin -
-                                         separator_margin);
-  }
+  if (bookmarks_separator_view_->IsVisible()) {
+    if (!compute_bounds_only) {
+      bookmarks_separator_view_->SetBounds(x,
+                                           y - top_margin,
+                                           bookmarks_separator_pref.width(),
+                                           height + top_margin + kBottomMargin -
+                                           separator_margin);
+    }
 
-  x += bookmarks_separator_pref.width();
+    x += bookmarks_separator_pref.width();
+  }
 
   // The other bookmarks button.
-  if (!compute_bounds_only) {
-    other_bookmarked_button_->SetBounds(x, y, other_bookmarked_pref.width(),
-                                        height);
+  if (other_bookmarked_button_->IsVisible()) {
+    if (!compute_bounds_only) {
+      other_bookmarked_button_->SetBounds(x, y, other_bookmarked_pref.width(),
+                                          height);
+    }
+    x += other_bookmarked_pref.width() + kButtonPadding;
   }
-  x += other_bookmarked_pref.width() + kButtonPadding;
 
   // Set the real bounds of the sync error button only if it needs to appear on
   // the bookmarks bar.
@@ -1736,7 +1745,7 @@
   sync_error_button->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_SYNC_BOOKMARK_BAR_ERROR_DESC)));
   sync_error_button->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_SYNC_ERROR_BUTTON)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_SYNC_ERROR_BUTTON));
   sync_error_button->SetIcon(
       *ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING));
   return sync_error_button;
diff --git a/chrome/browser/ui/views/bookmark_bar_view.h b/chrome/browser/ui/views/bookmark_bar_view.h
index 79709f4..2f4cf53 100644
--- a/chrome/browser/ui/views/bookmark_bar_view.h
+++ b/chrome/browser/ui/views/bookmark_bar_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,9 +11,9 @@
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/views/bookmark_bar_instructions_view.h"
-#include "chrome/browser/views/bookmark_menu_controller_views.h"
-#include "chrome/browser/views/detachable_toolbar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_instructions_view.h"
+#include "chrome/browser/ui/views/bookmark_menu_controller_views.h"
+#include "chrome/browser/ui/views/detachable_toolbar_view.h"
 #include "chrome/common/notification_registrar.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "views/controls/button/button.h"
@@ -121,15 +121,13 @@
   virtual gfx::Size GetPreferredSize();
   virtual gfx::Size GetMinimumSize();
   virtual void Layout();
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
   virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
   virtual void PaintChildren(gfx::Canvas* canvas);
   virtual bool GetDropFormats(
       int* formats,
-      std::set<OSExchangeData::CustomFormat>* custom_formats);
+      std::set<ui::OSExchangeData::CustomFormat>* custom_formats);
   virtual bool AreDropTypesRequired();
-  virtual bool CanDrop(const OSExchangeData& data);
+  virtual bool CanDrop(const ui::OSExchangeData& data);
   virtual void OnDragEntered(const views::DropTargetEvent& event);
   virtual int OnDragUpdated(const views::DropTargetEvent& event);
   virtual void OnDragExited();
@@ -241,6 +239,17 @@
   // bookmark bar model has.
   int GetBookmarkButtonCount();
 
+  // Returns the tooltip text for the specified url and title. The returned
+  // text is clipped to fit within the bounds of the monitor.
+  //
+  // Note that we adjust the direction of both the URL and the title based on
+  // the locale so that pure LTR strings are displayed properly in RTL locales.
+  static std::wstring CreateToolTipForURLAndTitle(
+      const gfx::Point& screen_loc,
+      const GURL& url,
+      const std::wstring& title,
+      Profile* profile);
+
   // If true we're running tests. This short circuits a couple of animations.
   static bool testing_;
 
@@ -347,7 +356,7 @@
   // WriteDragData to write the actual data.
   virtual void WriteDragData(views::View* sender,
                              const gfx::Point& press_pt,
-                             OSExchangeData* data);
+                             ui::OSExchangeData* data);
 
   virtual int GetDragOperations(views::View* sender, const gfx::Point& p);
 
@@ -356,7 +365,7 @@
                             const gfx::Point& p);
 
   // Writes a BookmarkNodeData for node to data.
-  void WriteDragData(const BookmarkNode* node, OSExchangeData* data);
+  void WriteDragData(const BookmarkNode* node, ui::OSExchangeData* data);
 
   // ViewMenuDelegate method. Ends up creating a BookmarkMenuController to
   // show the menu.
@@ -409,7 +418,7 @@
   void StartShowFolderDropMenuTimer(const BookmarkNode* node);
 
   // Returns the drop operation and index for the drop based on the event
-  // and data. Returns DragDropTypes::DRAG_NONE if not a valid location.
+  // and data. Returns ui::DragDropTypes::DRAG_NONE if not a valid location.
   int CalculateDropOperation(const views::DropTargetEvent& event,
                              const BookmarkNodeData& data,
                              int* index,
@@ -430,6 +439,10 @@
   // Updates the colors for all the child objects in the bookmarks bar.
   void UpdateColors();
 
+  // Updates the visibility of |other_bookmarked_button_| and
+  // |bookmarks_separator_view_|.
+  void UpdateOtherBookmarksVisibility();
+
   // This method computes the bounds for the bookmark bar items. If
   // |compute_bounds_only| = TRUE, the bounds for the items are just computed,
   // but are not set. This mode is used by GetPreferredSize() to obtain the
diff --git a/chrome/browser/ui/views/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmark_bar_view_test.cc
index d98c20f..2dd5f79 100644
--- a/chrome/browser/ui/views/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmark_bar_view_test.cc
@@ -1,8 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/keyboard_codes.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -12,13 +11,15 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/page_navigator.h"
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/testing_profile.h"
 #include "chrome/test/interactive_ui/view_event_test_base.h"
 #include "chrome/test/ui_test_utils.h"
 #include "grit/generated_resources.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/menu/menu_controller.h"
@@ -66,15 +67,18 @@
 class ViewsDelegateImpl : public views::ViewsDelegate {
  public:
   ViewsDelegateImpl() {}
-  virtual Clipboard* GetClipboard() const { return NULL; }
-  virtual void SaveWindowPlacement(const std::wstring& window_name,
+  virtual ui::Clipboard* GetClipboard() const { return NULL; }
+  virtual void SaveWindowPlacement(views::Window* window,
+                                   const std::wstring& window_name,
                                    const gfx::Rect& bounds,
                                    bool maximized) {}
-  virtual bool GetSavedWindowBounds(const std::wstring& window_name,
+  virtual bool GetSavedWindowBounds(views::Window* window,
+                                    const std::wstring& window_name,
                                     gfx::Rect* bounds) const {
     return false;
   }
-  virtual bool GetSavedMaximizedState(const std::wstring& window_name,
+  virtual bool GetSavedMaximizedState(views::Window* window,
+                                      const std::wstring& window_name,
                                       bool* maximized) const {
     return false;
   }
@@ -816,9 +820,9 @@
     start_y_ = menu_loc.y();
 
     // Move the mouse over the scroll button.
-    views::View* scroll_container = menu->GetSubmenu()->GetParent();
+    views::View* scroll_container = menu->GetSubmenu()->parent();
     ASSERT_TRUE(scroll_container != NULL);
-    scroll_container = scroll_container->GetParent();
+    scroll_container = scroll_container->parent();
     ASSERT_TRUE(scroll_container != NULL);
     views::View* scroll_down_button = scroll_container->GetChildViewAt(1);
     ASSERT_TRUE(scroll_down_button);
@@ -881,7 +885,7 @@
 
     // Send a down event, which should select the first item.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_DOWN, false, false, false, false,
+        NULL, ui::VKEY_DOWN, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest10::Step3));
   }
 
@@ -894,7 +898,7 @@
 
     // Send a key down event, which should select the next item.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_DOWN, false, false, false, false,
+        NULL, ui::VKEY_DOWN, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest10::Step4));
   }
 
@@ -907,7 +911,7 @@
 
     // Send a right arrow to force the menu to open.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_RIGHT, false, false, false, false,
+        NULL, ui::VKEY_RIGHT, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest10::Step5));
   }
 
@@ -923,7 +927,7 @@
 
     // Send a left arrow to close the submenu.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_LEFT, false, false, false, false,
+        NULL, ui::VKEY_LEFT, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest10::Step6));
   }
 
@@ -938,7 +942,7 @@
 
     // Send a down arrow to wrap back to f1a
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_DOWN, false, false, false, false,
+        NULL, ui::VKEY_DOWN, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest10::Step7));
   }
 
@@ -951,7 +955,7 @@
 
     // Send enter, which should select the item.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_RETURN, false, false, false, false,
+        NULL, ui::VKEY_RETURN, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest10::Step8));
   }
 
@@ -1006,7 +1010,7 @@
   void Step3() {
     // Send escape so that the context menu hides.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_ESCAPE, false, false, false, false,
+        NULL, ui::VKEY_ESCAPE, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest11::Step4));
   }
 
@@ -1095,7 +1099,7 @@
 
   void Step4() {
     // Press tab to give focus to the cancel button.
-    ui_controls::SendKeyPress(NULL, app::VKEY_TAB, false, false, false, false);
+    ui_controls::SendKeyPress(NULL, ui::VKEY_TAB, false, false, false, false);
 
     // For some reason return isn't processed correctly unless we delay.
     MessageLoop::current()->PostDelayedTask(FROM_HERE,
@@ -1105,7 +1109,7 @@
   void Step5() {
     // And press enter so that the cancel button is selected.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_RETURN, false, false, false, false,
+        NULL, ui::VKEY_RETURN, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest12::Step6));
   }
 
@@ -1168,7 +1172,7 @@
     // Find the first separator.
     views::SubmenuView* submenu = menu->GetSubmenu();
     views::View* separator_view = NULL;
-    for (int i = 0; i < submenu->GetChildViewCount(); ++i) {
+    for (int i = 0; i < submenu->child_count(); ++i) {
       if (submenu->GetChildViewAt(i)->GetID() !=
           views::MenuItemView::kMenuItemViewID) {
         separator_view = submenu->GetChildViewAt(i);
@@ -1234,7 +1238,7 @@
 
     // Send escape so that the context menu hides.
     ui_controls::SendKeyPressNotifyWhenDone(
-        NULL, app::VKEY_ESCAPE, false, false, false, false,
+        NULL, ui::VKEY_ESCAPE, false, false, false, false,
         CreateEventTask(this, &BookmarkBarViewTest14::Step3));
   }
 
diff --git a/chrome/browser/ui/views/bookmark_bar_view_unittest.cc b/chrome/browser/ui/views/bookmark_bar_view_unittest.cc
index 3f66795..42181e2 100644
--- a/chrome/browser/ui/views/bookmark_bar_view_unittest.cc
+++ b/chrome/browser/ui/views/bookmark_bar_view_unittest.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 #include "chrome/test/browser_with_test_window_test.h"
 #include "chrome/test/testing_profile.h"
 
diff --git a/chrome/browser/ui/views/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmark_bubble_view.cc
index fdb47df..d9660c0 100644
--- a/chrome/browser/ui/views/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmark_bubble_view.cc
@@ -1,12 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_bubble_view.h"
+#include "chrome/browser/ui/views/bookmark_bubble_view.h"
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string16.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -16,17 +13,21 @@
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/canvas.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "views/event.h"
-#include "views/standard_layout.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/textfield/textfield.h"
+#include "views/events/event.h"
 #include "views/focus/focus_manager.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/client_view.h"
 #include "views/window/window.h"
 
@@ -92,6 +93,13 @@
   InfoBubble* info_bubble = InfoBubble::Show(
       parent->GetClientView()->GetWidget(), bounds, BubbleBorder::TOP_RIGHT,
       bubble_, bubble_);
+  // |bubble_| can be set to NULL in InfoBubbleClosing when we close the bubble
+  // asynchronously. However, that can happen during the Show call above if the
+  // window loses activation while we are getting to ready to show the bubble,
+  // so we must check to make sure we still have a valid bubble before
+  // proceeding.
+  if (!bubble_)
+    return;
   bubble_->set_info_bubble(info_bubble);
   info_bubble->SizeToContents();
   GURL url_ptr(url);
@@ -123,15 +131,10 @@
   }
 }
 
-void BookmarkBubbleView::DidChangeBounds(const gfx::Rect& previous,
-                                         const gfx::Rect& current) {
-  Layout();
-}
-
 void BookmarkBubbleView::BubbleShown() {
   DCHECK(GetWidget());
   GetFocusManager()->RegisterAccelerator(
-      views::Accelerator(app::VKEY_RETURN, false, false, false), this);
+      views::Accelerator(ui::VKEY_RETURN, false, false, false), this);
 
   title_tf_->RequestFocus();
   title_tf_->SelectAll();
@@ -139,7 +142,7 @@
 
 bool BookmarkBubbleView::AcceleratorPressed(
     const views::Accelerator& accelerator) {
-  if (accelerator.GetKeyCode() != app::VKEY_RETURN)
+  if (accelerator.GetKeyCode() != ui::VKEY_RETURN)
     return false;
 
   if (edit_button_->HasFocus())
@@ -199,7 +202,8 @@
   parent_combobox_ = new Combobox(&parent_model_);
   parent_combobox_->SetSelectedItem(parent_model_.node_parent_index());
   parent_combobox_->set_listener(this);
-  parent_combobox_->SetAccessibleName(combobox_label->GetText());
+  parent_combobox_->SetAccessibleName(
+      WideToUTF16Hack(combobox_label->GetText()));
 
   Label* title_label = new Label(UTF16ToWide(l10n_util::GetStringUTF16(
       newly_bookmarked_ ? IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED :
@@ -216,7 +220,7 @@
   // Top (title) row.
   cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF,
                 0, 0);
-  cs->AddPaddingColumn(1, kUnrelatedControlHorizontalSpacing);
+  cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
   cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF,
                 0, 0);
 
@@ -224,19 +228,19 @@
   cs = layout->AddColumnSet(2);
   cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                 GridLayout::USE_PREF, 0, 0);
-  cs->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                 GridLayout::USE_PREF, 0, kMinimumFieldSize);
 
   // Bottom (buttons) row.
   cs = layout->AddColumnSet(3);
-  cs->AddPaddingColumn(1, kRelatedControlHorizontalSpacing);
+  cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
   cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
                 GridLayout::USE_PREF, 0, 0);
   // We subtract 2 to account for the natural button padding, and
   // to bring the separation visually in line with the row separation
   // height.
-  cs->AddPaddingColumn(0, kRelatedButtonHSpacing - 2);
+  cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing - 2);
   cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
                 GridLayout::USE_PREF, 0, 0);
 
@@ -244,7 +248,7 @@
   layout->AddView(title_label);
   layout->AddView(remove_link_);
 
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, 2);
   layout->AddView(new Label(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_BOOMARK_BUBBLE_TITLE_TEXT))));
@@ -252,12 +256,12 @@
   title_tf_->SetText(GetTitle());
   layout->AddView(title_tf_);
 
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
 
   layout->StartRow(0, 2);
   layout->AddView(combobox_label);
   layout->AddView(parent_combobox_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
 
   layout->StartRow(0, 3);
   layout->AddView(edit_button_);
diff --git a/chrome/browser/ui/views/bookmark_bubble_view.h b/chrome/browser/ui/views/bookmark_bubble_view.h
index d411c01..353fb7f 100644
--- a/chrome/browser/ui/views/bookmark_bubble_view.h
+++ b/chrome/browser/ui/views/bookmark_bubble_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,9 +8,9 @@
 
 #include "base/string16.h"
 #include "chrome/browser/bookmarks/recently_used_folders_combo_model.h"
-#include "chrome/browser/views/info_bubble.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/button/button.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/link.h"
@@ -51,10 +51,6 @@
 
   void set_info_bubble(InfoBubble* info_bubble) { info_bubble_ = info_bubble; }
 
-  // Overridden to force a layout.
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
-
   // Invoked after the bubble has been shown.
   virtual void BubbleShown();
 
diff --git a/chrome/browser/ui/views/bookmark_context_menu.cc b/chrome/browser/ui/views/bookmark_context_menu.cc
index 9067dd9..44a8618 100644
--- a/chrome/browser/ui/views/bookmark_context_menu.cc
+++ b/chrome/browser/ui/views/bookmark_context_menu.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_context_menu.h"
+#include "chrome/browser/ui/views/bookmark_context_menu.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/notification_service.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/menu/menu_item_view.h"
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/bookmark_context_menu.h b/chrome/browser/ui/views/bookmark_context_menu.h
index c6cd19d..86befa4 100644
--- a/chrome/browser/ui/views/bookmark_context_menu.h
+++ b/chrome/browser/ui/views/bookmark_context_menu.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_BOOKMARK_CONTEXT_MENU_H_
 #pragma once
 
-#include "chrome/browser/views/bookmark_context_menu_controller_views.h"
+#include "chrome/browser/ui/views/bookmark_context_menu_controller_views.h"
 #include "views/controls/menu/menu_delegate.h"
 
 // Observer for the BookmarkContextMenu.
diff --git a/chrome/browser/ui/views/bookmark_context_menu_controller_views.cc b/chrome/browser/ui/views/bookmark_context_menu_controller_views.cc
index b2f7c29..3234403 100644
--- a/chrome/browser/ui/views/bookmark_context_menu_controller_views.cc
+++ b/chrome/browser/ui/views/bookmark_context_menu_controller_views.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_context_menu_controller_views.h"
+#include "chrome/browser/ui/views/bookmark_context_menu_controller_views.h"
 
 #include "base/compiler_specific.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -231,10 +231,12 @@
        selection_[0]->GetParent() == model_->root_node());
   switch (id) {
     case IDC_BOOKMARK_BAR_OPEN_INCOGNITO:
-      return !profile_->IsOffTheRecord();
+      return !profile_->IsOffTheRecord() &&
+             profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
 
     case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO:
-      return HasURLs() && !profile_->IsOffTheRecord();
+      return HasURLs() && !profile_->IsOffTheRecord() &&
+             profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
 
     case IDC_BOOKMARK_BAR_OPEN_ALL:
     case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW:
diff --git a/chrome/browser/ui/views/bookmark_context_menu_controller_views.h b/chrome/browser/ui/views/bookmark_context_menu_controller_views.h
index 1246a96..d63727b 100644
--- a/chrome/browser/ui/views/bookmark_context_menu_controller_views.h
+++ b/chrome/browser/ui/views/bookmark_context_menu_controller_views.h
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Browser;
 class PageNavigator;
diff --git a/chrome/browser/ui/views/bookmark_context_menu_test.cc b/chrome/browser/ui/views/bookmark_context_menu_test.cc
index 8cf12d4..9fa9a26 100644
--- a/chrome/browser/ui/views/bookmark_context_menu_test.cc
+++ b/chrome/browser/ui/views/bookmark_context_menu_test.cc
@@ -1,24 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+#include <vector>
+
 #include "base/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/page_navigator.h"
-#include "chrome/browser/views/bookmark_context_menu.h"
-#include "chrome/common/pref_names.h"
+#include "chrome/browser/ui/views/bookmark_context_menu.h"
 #include "chrome/test/testing_profile.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
 #endif
 
 namespace {
@@ -314,4 +315,3 @@
   ASSERT_TRUE(model_->GetBookmarkBarNode()->GetChild(1)->is_folder());
   ASSERT_EQ(old_count, model_->GetBookmarkBarNode()->GetChildCount());
 }
-
diff --git a/chrome/browser/ui/views/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmark_editor_view.cc
index c6768c4..bc94312 100644
--- a/chrome/browser/ui/views/bookmark_editor_view.cc
+++ b/chrome/browser/ui/views/bookmark_editor_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_editor_view.h"
+#include "chrome/browser/ui/views/bookmark_editor_view.h"
 
-#include "app/l10n_util.h"
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/string_util.h"
@@ -21,13 +20,14 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/background.h"
 #include "views/focus/focus_manager.h"
-#include "views/grid_layout.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/label.h"
 #include "views/controls/menu/menu_2.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -139,10 +139,10 @@
 
   // Manually lay out the New Folder button in the same row as the OK/Cancel
   // buttons...
-  gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
+  gfx::Rect parent_bounds = parent()->GetContentsBounds();
   gfx::Size prefsize = new_group_button_->GetPreferredSize();
   int button_y =
-      parent_bounds.bottom() - prefsize.height() - kButtonVEdgeMargin;
+      parent_bounds.bottom() - prefsize.height() - views::kButtonVEdgeMargin;
   new_group_button_->SetBounds(kPanelHorizMargin, button_y, prefsize.width(),
                               prefsize.height());
 }
@@ -174,7 +174,7 @@
 }
 
 bool BookmarkEditorView::CanEdit(views::TreeView* tree_view,
-                                 TreeModelNode* node) {
+                                 ui::TreeModelNode* node) {
   // Only allow editting of children of the bookmark bar node and other node.
   EditorNode* bb_node = tree_model_->AsNode(node);
   return (bb_node->GetParent() && bb_node->GetParent()->GetParent());
@@ -208,7 +208,7 @@
 
 bool BookmarkEditorView::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   return GetWidget()->GetAccelerator(command_id, accelerator);
 }
 
@@ -249,7 +249,7 @@
       (tree_model_->GetParent(tree_view_->GetSelectedNode()) ==
        tree_model_->GetRoot());
   if (!context_menu_contents_.get()) {
-    context_menu_contents_.reset(new menus::SimpleMenuModel(this));
+    context_menu_contents_.reset(new ui::SimpleMenuModel(this));
     context_menu_contents_->AddItemWithStringId(IDS_EDIT, IDS_EDIT);
     context_menu_contents_->AddItemWithStringId(
         IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM,
@@ -278,7 +278,7 @@
 
   title_label_ = new views::Label(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_BOOMARK_EDITOR_NAME_LABEL)));
-  title_tf_.SetAccessibleName(title_label_->GetText());
+  title_tf_.SetAccessibleName(WideToUTF16Hack(title_label_->GetText()));
 
   string16 url_text;
   if (details_.type == EditDetails::EXISTING_NODE) {
@@ -297,7 +297,7 @@
 
   url_label_ = new views::Label(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_BOOMARK_EDITOR_URL_LABEL)));
-  url_tf_.SetAccessibleName(url_label_->GetText());
+  url_tf_.SetAccessibleName(WideToUTF16Hack(url_label_->GetText()));
 
   if (show_tree_) {
     tree_view_ = new views::TreeView();
@@ -314,7 +314,7 @@
   }
 
   // Yummy layout code.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int labels_column_set_id = 0;
@@ -324,7 +324,7 @@
   ColumnSet* column_set = layout->AddColumnSet(labels_column_set_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -335,10 +335,10 @@
   column_set = layout->AddColumnSet(buttons_column_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(1, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
                         GridLayout::USE_PREF, 0, 0);
   column_set->LinkColumnSizes(0, 2, 4, -1);
@@ -349,7 +349,7 @@
   layout->AddView(&title_tf_);
 
   if (details_.type != EditDetails::NEW_FOLDER) {
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
     layout->StartRow(0, labels_column_set_id);
     layout->AddView(url_label_);
@@ -357,12 +357,12 @@
   }
 
   if (show_tree_) {
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     layout->StartRow(1, single_column_view_set_id);
     layout->AddView(tree_view_);
   }
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   if (!show_tree_ || bb_model_->IsLoaded())
     Reset();
@@ -403,7 +403,7 @@
 
 void BookmarkEditorView::Reset() {
   if (!show_tree_) {
-    if (GetParent())
+    if (parent())
       UserInputChanged();
     return;
   }
@@ -422,7 +422,7 @@
 
   context_menu_.reset();
 
-  if (GetParent())
+  if (parent())
     ExpandAndSelect();
 }
 GURL BookmarkEditorView::GetInputURL() const {
diff --git a/chrome/browser/ui/views/bookmark_editor_view.h b/chrome/browser/ui/views/bookmark_editor_view.h
index f6da363..d090c48 100644
--- a/chrome/browser/ui/views/bookmark_editor_view.h
+++ b/chrome/browser/ui/views/bookmark_editor_view.h
@@ -6,8 +6,6 @@
 #define CHROME_BROWSER_UI_VIEWS_BOOKMARK_EDITOR_VIEW_H_
 #pragma once
 
-#include "app/menus/simple_menu_model.h"
-#include "app/tree_node_model.h"
 #include "base/string16.h"
 #include "chrome/browser/bookmarks/bookmark_editor.h"
 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
@@ -16,6 +14,8 @@
 #include "views/controls/tree/tree_view.h"
 #include "views/window/dialog_delegate.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/models/tree_node_model.h"
 
 namespace views {
 class Label;
@@ -46,20 +46,20 @@
                            public views::DialogDelegate,
                            public views::Textfield::Controller,
                            public views::ContextMenuController,
-                           public menus::SimpleMenuModel::Delegate,
+                           public ui::SimpleMenuModel::Delegate,
                            public BookmarkModelObserver {
  public:
   // Type of node in the tree. Public purely for testing.
-  typedef TreeNodeWithValue<int64> EditorNode;
+  typedef ui::TreeNodeWithValue<int64> EditorNode;
 
   // Model for the TreeView. Trivial subclass that doesn't allow titles with
   // empty strings. Public purely for testing.
-  class EditorTreeModel : public TreeNodeModel<EditorNode> {
+  class EditorTreeModel : public ui::TreeNodeModel<EditorNode> {
    public:
     explicit EditorTreeModel(EditorNode* root)
-        : TreeNodeModel<EditorNode>(root) {}
+        : ui::TreeNodeModel<EditorNode>(root) {}
 
-    virtual void SetTitle(TreeModelNode* node,
+    virtual void SetTitle(ui::TreeModelNode* node,
                           const string16& title) {
       if (!title.empty())
         TreeNodeModel::SetTitle(node, title);
@@ -94,7 +94,7 @@
 
   // TreeViewObserver methods.
   virtual void OnTreeViewSelectionChanged(views::TreeView* tree_view);
-  virtual bool CanEdit(views::TreeView* tree_view, TreeModelNode* node);
+  virtual bool CanEdit(views::TreeView* tree_view, ui::TreeModelNode* node);
 
   // Textfield::Controller methods.
   virtual void ContentsChanged(views::Textfield* sender,
@@ -107,11 +107,11 @@
   // NativeButton.
   virtual void ButtonPressed(views::Button* sender, const views::Event& event);
 
-  // menus::SimpleMenuModel::Delegate.
+  // ui::SimpleMenuModel::Delegate.
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual void ExecuteCommand(int command_id);
 
   // Creates a Window and adds the BookmarkEditorView to it. When the window is
@@ -247,7 +247,7 @@
   const EditDetails details_;
 
   // The context menu.
-  scoped_ptr<menus::SimpleMenuModel> context_menu_contents_;
+  scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
   scoped_ptr<views::Menu2> context_menu_;
 
   // Mode used to create nodes from.
diff --git a/chrome/browser/ui/views/bookmark_editor_view_unittest.cc b/chrome/browser/ui/views/bookmark_editor_view_unittest.cc
index b2d9dea..11c64c9 100644
--- a/chrome/browser/ui/views/bookmark_editor_view_unittest.cc
+++ b/chrome/browser/ui/views/bookmark_editor_view_unittest.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser_thread.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/bookmark_editor_view.h"
-#include "chrome/common/pref_names.h"
+#include "chrome/browser/ui/views/bookmark_editor_view.h"
 #include "chrome/test/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -86,7 +86,7 @@
   }
 
   bool URLTFHasParent() {
-    return editor_->url_tf_.GetParent();
+    return editor_->url_tf_.parent();
   }
 
  private:
diff --git a/chrome/browser/ui/views/bookmark_menu_controller_views.cc b/chrome/browser/ui/views/bookmark_menu_controller_views.cc
index 8829dac..5c0d684 100644
--- a/chrome/browser/ui/views/bookmark_menu_controller_views.cc
+++ b/chrome/browser/ui/views/bookmark_menu_controller_views.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bookmark_menu_controller_views.h"
+#include "chrome/browser/ui/views/bookmark_menu_controller_views.h"
 
-#include "app/os_exchange_data.h"
-#include "app/resource_bundle.h"
 #include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
@@ -14,12 +12,14 @@
 #include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/page_navigator.h"
-#include "chrome/browser/views/bookmark_bar_view.h"
-#include "chrome/browser/views/event_utils.h"
+#include "chrome/browser/ui/views/bookmark_bar_view.h"
+#include "chrome/browser/ui/views/event_utils.h"
 #include "chrome/common/page_transition_types.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/menu_button.h"
 
 using views::MenuItemView;
@@ -85,6 +85,15 @@
   menu_->Cancel();
 }
 
+std::wstring BookmarkMenuController::GetTooltipText(
+    int id, const gfx::Point& screen_loc) {
+  DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
+
+  const BookmarkNode* node = menu_id_to_node_map_[id];
+  return BookmarkBarView::CreateToolTipForURLAndTitle(
+      screen_loc, node->GetURL(), UTF16ToWide(node->GetTitle()), profile_);
+}
+
 bool BookmarkMenuController::IsTriggerableEvent(const views::MouseEvent& e) {
   return event_utils::IsPossibleDispositionEvent(e);
 }
@@ -107,8 +116,8 @@
 bool BookmarkMenuController::GetDropFormats(
       MenuItemView* menu,
       int* formats,
-      std::set<OSExchangeData::CustomFormat>* custom_formats) {
-  *formats = OSExchangeData::URL;
+      std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
+  *formats = ui::OSExchangeData::URL;
   custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat());
   return true;
 }
@@ -118,7 +127,7 @@
 }
 
 bool BookmarkMenuController::CanDrop(MenuItemView* menu,
-                                     const OSExchangeData& data) {
+                                     const ui::OSExchangeData& data) {
   // Only accept drops of 1 node, which is the case for all data dragged from
   // bookmark bar and menus.
 
@@ -218,7 +227,7 @@
 }
 
 void BookmarkMenuController::WriteDragData(MenuItemView* sender,
-                                           OSExchangeData* data) {
+                                           ui::OSExchangeData* data) {
   DCHECK(sender && data);
 
   UserMetrics::RecordAction(UserMetricsAction("BookmarkBar_DragFromFolder"),
@@ -379,7 +388,7 @@
                      // be a menu.
       removed_menus->insert(menu);
       changed_parent_menus.insert(menu->GetParentMenuItem());
-      menu->GetParent()->RemoveChildView(menu);
+      menu->parent()->RemoveChildView(menu);
       node_to_menu_id_map_.erase(node_to_menu);
     }
   }
diff --git a/chrome/browser/ui/views/bookmark_menu_controller_views.h b/chrome/browser/ui/views/bookmark_menu_controller_views.h
index 3d4f013..ea9821a 100644
--- a/chrome/browser/ui/views/bookmark_menu_controller_views.h
+++ b/chrome/browser/ui/views/bookmark_menu_controller_views.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,27 +11,30 @@
 
 #include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/views/bookmark_context_menu.h"
-#include "gfx/native_widget_types.h"
+#include "chrome/browser/ui/views/bookmark_context_menu.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/controls/menu/menu_delegate.h"
 #include "views/controls/menu/menu_item_view.h"
 
-namespace gfx {
-class Rect;
-}  // namespace gfx
-
-namespace views {
-class MenuButton;
-}  // namespace views
-
 class BookmarkBarView;
 class BookmarkContextMenu;
 class BookmarkNode;
 class Browser;
-class OSExchangeData;
 class PageNavigator;
 class Profile;
 
+namespace gfx {
+class Rect;
+}  // namespace gfx
+
+namespace ui {
+class OSExchangeData;
+}  // namespace ui
+
+namespace views {
+class MenuButton;
+}  // namespace views
+
 // BookmarkMenuController is responsible for showing a menu of bookmarks,
 // each item in the menu represents a bookmark.
 // BookmarkMenuController deletes itself as necessary, although the menu can
@@ -82,14 +85,16 @@
   void set_observer(Observer* observer) { observer_ = observer; }
 
   // MenuDelegate methods.
+  virtual std::wstring GetTooltipText(int id, const gfx::Point& p);
   virtual bool IsTriggerableEvent(const views::MouseEvent& e);
   virtual void ExecuteCommand(int id, int mouse_event_flags);
   virtual bool GetDropFormats(
       views::MenuItemView* menu,
       int* formats,
-      std::set<OSExchangeData::CustomFormat>* custom_formats);
+      std::set<ui::OSExchangeData::CustomFormat>* custom_formats);
   virtual bool AreDropTypesRequired(views::MenuItemView* menu);
-  virtual bool CanDrop(views::MenuItemView* menu, const OSExchangeData& data);
+  virtual bool CanDrop(views::MenuItemView* menu,
+                       const ui::OSExchangeData& data);
   virtual int GetDropOperation(views::MenuItemView* item,
                                const views::DropTargetEvent& event,
                                DropPosition* position);
@@ -102,7 +107,8 @@
                                bool is_mouse_gesture);
   virtual void DropMenuClosed(views::MenuItemView* menu);
   virtual bool CanDrag(views::MenuItemView* menu);
-  virtual void WriteDragData(views::MenuItemView* sender, OSExchangeData* data);
+  virtual void WriteDragData(views::MenuItemView* sender,
+                             ui::OSExchangeData* data);
   virtual int GetDragOperations(views::MenuItemView* sender);
   virtual views::MenuItemView* GetSiblingMenu(
       views::MenuItemView* menu,
diff --git a/chrome/browser/ui/views/browser_actions_container.cc b/chrome/browser/ui/views/browser_actions_container.cc
index 44a4a00..9516d73 100644
--- a/chrome/browser/ui/views/browser_actions_container.cc
+++ b/chrome/browser/ui/views/browser_actions_container.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/browser_actions_container.h"
+#include "chrome/browser/ui/views/browser_actions_container.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -30,14 +28,16 @@
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/menu/menu_2.h"
@@ -165,12 +165,12 @@
   }
 
   // If the browser action name is empty, show the extension name instead.
-  std::wstring name = UTF8ToWide(browser_action()->GetTitle(tab_id));
+  string16 name = UTF8ToUTF16(browser_action()->GetTitle(tab_id));
   if (name.empty())
-    name = UTF8ToWide(extension()->name());
-  SetTooltipText(name);
+    name = UTF8ToUTF16(extension()->name());
+  SetTooltipText(UTF16ToWideHack(name));
   SetAccessibleName(name);
-  GetParent()->SchedulePaint();
+  parent()->SchedulePaint();
 }
 
 void BrowserActionButton::Observe(NotificationType type,
@@ -251,6 +251,9 @@
 
 void BrowserActionButton::ShowContextMenu(const gfx::Point& p,
                                           bool is_mouse_gesture) {
+  if (!extension()->ShowConfigureContextMenus())
+    return;
+
   showing_context_menu_ = true;
   SetButtonPushed();
 
@@ -288,8 +291,8 @@
   button_->SetDragController(panel_);
   AddChildView(button_);
   button_->UpdateState();
-  SetAccessibleName(UTF16ToWide(
-      l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_BROWSER_ACTION)));
+  SetAccessibleName(
+      l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_BROWSER_ACTION));
 }
 
 BrowserActionView::~BrowserActionView() {
@@ -369,19 +372,18 @@
   resize_animation_.reset(new ui::SlideAnimation(this));
   resize_area_ = new views::ResizeArea(this);
   resize_area_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_SEPARATOR)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_SEPARATOR));
   AddChildView(resize_area_);
 
   chevron_ = new views::MenuButton(NULL, std::wstring(), this, false);
   chevron_->set_border(NULL);
   chevron_->EnableCanvasFlippingForRTLUI(true);
   chevron_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_CHEVRON)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_CHEVRON));
   chevron_->SetVisible(false);
   AddChildView(chevron_);
 
-  SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS)));
+  SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS));
 }
 
 BrowserActionsContainer::~BrowserActionsContainer() {
@@ -484,7 +486,8 @@
   // Popups just display.  No notification to the extension.
   // TODO(erikkay): should there be?
   if (!button->IsPopup()) {
-    ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
+    ExtensionService* service = profile_->GetExtensionService();
+    service->browser_event_router()->BrowserActionExecuted(
         profile_, browser_action->extension_id(), browser_);
     return;
   }
@@ -502,19 +505,18 @@
   // We can get the execute event for browser actions that are not visible,
   // since buttons can be activated from the overflow menu (chevron). In that
   // case we show the popup as originating from the chevron.
-  View* reference_view = button->GetParent()->IsVisible() ? button : chevron_;
+  View* reference_view = button->parent()->IsVisible() ? button : chevron_;
   gfx::Point origin;
   View::ConvertPointToScreen(reference_view, &origin);
   gfx::Rect rect = reference_view->bounds();
   rect.set_origin(origin);
 
-  gfx::NativeWindow frame_window = browser_->window()->GetNativeHandle();
   BubbleBorder::ArrowLocation arrow_location = base::i18n::IsRTL() ?
       BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
 
-  popup_ = ExtensionPopup::Show(button->GetPopupUrl(), browser_,
-      browser_->profile(), frame_window, rect, arrow_location, true,
-      inspect_with_devtools, ExtensionPopup::BUBBLE_CHROME, this);
+  popup_ = ExtensionPopup::Show(button->GetPopupUrl(), browser_, rect,
+                                arrow_location, inspect_with_devtools,
+                                this);
   popup_button_ = button;
   popup_button_->SetButtonPushed();
 }
@@ -634,7 +636,7 @@
   if (GetViewForPoint(event.location()) == chevron_) {
     if (show_menu_task_factory_.empty() && !overflow_menu_)
       StartShowFolderDropMenuTimer();
-    return DragDropTypes::DRAG_MOVE;
+    return ui::DragDropTypes::DRAG_MOVE;
   }
   StopShowFolderDropMenuTimer();
 
@@ -684,7 +686,7 @@
   SetDropIndicator(width_before_icons + (before_icon * IconWidth(true)) -
       (kItemSpacing / 2));
 
-  return DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 void BrowserActionsContainer::OnDragExited() {
@@ -696,8 +698,8 @@
 int BrowserActionsContainer::OnPerformDrop(
     const views::DropTargetEvent& event) {
   BrowserActionDragData data;
-  if (!data.Read(event.GetData()))
-    return DragDropTypes::DRAG_NONE;
+  if (!data.Read(event.data()))
+    return ui::DragDropTypes::DRAG_NONE;
 
   // Make sure we have the same view as we started with.
   DCHECK_EQ(browser_action_views_[data.index()]->button()->extension()->id(),
@@ -706,8 +708,7 @@
 
   size_t i = 0;
   for (; i < browser_action_views_.size(); ++i) {
-    int view_x =
-        browser_action_views_[i]->GetBounds(APPLY_MIRRORING_TRANSFORMATION).x();
+    int view_x = browser_action_views_[i]->GetMirroredBounds().x();
     if (!browser_action_views_[i]->IsVisible() ||
         (base::i18n::IsRTL() ? (view_x < drop_indicator_position_) :
             (view_x >= drop_indicator_position_))) {
@@ -732,7 +733,7 @@
       browser_action_views_[data.index()]->button()->extension(), i);
 
   OnDragExited();  // Perform clean up after dragging.
-  return DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 void BrowserActionsContainer::OnThemeChanged() {
@@ -777,7 +778,7 @@
 
 int BrowserActionsContainer::GetDragOperations(View* sender,
                                                const gfx::Point& p) {
-  return DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 bool BrowserActionsContainer::CanStartDrag(View* sender,
@@ -910,7 +911,7 @@
     index = model_->OriginalIndexToIncognito(index);
   BrowserActionView* view = new BrowserActionView(extension, this);
   browser_action_views_.insert(browser_action_views_.begin() + index, view);
-  AddChildView(index, view);
+  AddChildViewAt(view, index);
 
   // If we are still initializing the container, don't bother animating.
   if (!model_->extensions_initialized())
@@ -986,7 +987,7 @@
 }
 
 void BrowserActionsContainer::LoadImages() {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
   chevron_->SetIcon(*tp->GetBitmapNamed(IDR_BROWSER_ACTIONS_OVERFLOW));
   chevron_->SetHoverIcon(*tp->GetBitmapNamed(IDR_BROWSER_ACTIONS_OVERFLOW_H));
   chevron_->SetPushedIcon(*tp->GetBitmapNamed(IDR_BROWSER_ACTIONS_OVERFLOW_P));
diff --git a/chrome/browser/ui/views/browser_actions_container.h b/chrome/browser/ui/views/browser_actions_container.h
index 5291ece..4bce4b5 100644
--- a/chrome/browser/ui/views/browser_actions_container.h
+++ b/chrome/browser/ui/views/browser_actions_container.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,9 +14,9 @@
 #include "chrome/browser/extensions/extension_context_menu_model.h"
 #include "chrome/browser/extensions/extension_toolbar_model.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/views/browser_bubble.h"
-#include "chrome/browser/views/extensions/browser_action_overflow_menu_controller.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
+#include "chrome/browser/ui/views/browser_bubble.h"
+#include "chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h"
+#include "chrome/browser/ui/views/extensions/extension_popup.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "ui/base/animation/animation_delegate.h"
@@ -323,9 +323,9 @@
                                     views::View* parent,
                                     views::View* child);
   virtual bool GetDropFormats(
-      int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats);
+      int* formats, std::set<ui::OSExchangeData::CustomFormat>* custom_formats);
   virtual bool AreDropTypesRequired();
-  virtual bool CanDrop(const OSExchangeData& data);
+  virtual bool CanDrop(const ui::OSExchangeData& data);
   virtual void OnDragEntered(const views::DropTargetEvent& event);
   virtual int OnDragUpdated(const views::DropTargetEvent& event);
   virtual void OnDragExited();
@@ -339,7 +339,7 @@
   // Overridden from views::DragController:
   virtual void WriteDragData(View* sender,
                              const gfx::Point& press_pt,
-                             OSExchangeData* data);
+                             ui::OSExchangeData* data);
   virtual int GetDragOperations(View* sender, const gfx::Point& p);
   virtual bool CanStartDrag(View* sender,
                             const gfx::Point& press_pt,
diff --git a/chrome/browser/ui/views/browser_actions_container_browsertest.cc b/chrome/browser/ui/views/browser_actions_container_browsertest.cc
index 8751881..08b6133 100644
--- a/chrome/browser/ui/views/browser_actions_container_browsertest.cc
+++ b/chrome/browser/ui/views/browser_actions_container_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,8 +7,7 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/browser_actions_container.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/ui/views/browser_actions_container.h"
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/extensions/extension_resource.h"
 
diff --git a/chrome/browser/ui/views/browser_bubble.cc b/chrome/browser/ui/views/browser_bubble.cc
index a118852..33d5052 100644
--- a/chrome/browser/ui/views/browser_bubble.cc
+++ b/chrome/browser/ui/views/browser_bubble.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/browser_bubble.h"
+#include "chrome/browser/ui/views/browser_bubble.h"
 
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #if defined(OS_WIN)
 #include "chrome/browser/external_tab_container_win.h"
 #endif
@@ -24,28 +24,19 @@
         window->GetNativeWindow());
     DCHECK(bubble_host);
   }
-#if defined(OS_WIN)
-  // The frame may also be an ExternalTabContainer, which is also capable of
-  // hosting BrowserBubbles.
-  gfx::NativeView native_view = frame->GetNativeView();
-  if (!bubble_host) {
-    bubble_host =
-        ExternalTabContainer::GetExternalContainerFromNativeWindow(native_view);
-  }
-#endif
+
   return bubble_host;
 }
 
 }  // namespace
 
 BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame,
-                             const gfx::Point& origin, bool drop_shadow)
+                             const gfx::Point& origin)
     : frame_(frame),
       view_(view),
       visible_(false),
       delegate_(NULL),
       attached_(false),
-      drop_shadow_enabled_(drop_shadow),
       bubble_host_(GetBubbleHostFromFrame(frame)) {
   gfx::Size size = view->GetPreferredSize();
   bounds_.SetRect(origin.x(), origin.y(), size.width(), size.height());
diff --git a/chrome/browser/ui/views/browser_bubble.h b/chrome/browser/ui/views/browser_bubble.h
index 8cc63a3..8bb433f 100644
--- a/chrome/browser/ui/views/browser_bubble.h
+++ b/chrome/browser/ui/views/browser_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -40,10 +40,9 @@
   // Note that the bubble will size itself to the preferred size of |view|.
   // |view| is the embedded view, |frame| is widget that the bubble is being
   // positioned relative to, |origin| is the location that the bubble will
-  // be positioned relative to |frame|.  Pass true through |drop_shadow| to
-  // surround the bubble widget with a drop-shadow.
+  // be positioned relative to |frame|.
   BrowserBubble(views::View* view, views::Widget* frame,
-                const gfx::Point& origin, bool drop_shadow);
+                const gfx::Point& origin);
   virtual ~BrowserBubble();
 
   // Call manually if you need to detach the bubble from tracking the browser's
@@ -119,9 +118,6 @@
   // Is the bubble attached to a Browser window.
   bool attached_;
 
-  // Does the bubble have a drop-shadow.
-  bool drop_shadow_enabled_;
-
   // Non-owning pointer to the host of this bubble.
   BrowserBubbleHost* bubble_host_;
 
diff --git a/chrome/browser/ui/views/browser_bubble_gtk.cc b/chrome/browser/ui/views/browser_bubble_gtk.cc
index 631aff7..8932731 100644
--- a/chrome/browser/ui/views/browser_bubble_gtk.cc
+++ b/chrome/browser/ui/views/browser_bubble_gtk.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/browser_bubble.h"
+#include "chrome/browser/ui/views/browser_bubble.h"
 
 #include <vector>
 
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "views/widget/widget_gtk.h"
 #include "views/window/window.h"
 
@@ -84,9 +84,6 @@
 
 void BrowserBubble::InitPopup() {
   // TODO(port)
-  DCHECK(!drop_shadow_enabled_) <<
-    "Drop shadows not supported on GTK browser bubbles.";
-
   views::WidgetGtk* pop = new BubbleWidget(this);
   pop->SetOpacity(0xFF);
   pop->make_transient_to_parent();
diff --git a/chrome/browser/ui/views/browser_bubble_win.cc b/chrome/browser/ui/views/browser_bubble_win.cc
index 84985fd..4d75cdf 100644
--- a/chrome/browser/ui/views/browser_bubble_win.cc
+++ b/chrome/browser/ui/views/browser_bubble_win.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/browser_bubble.h"
+#include "chrome/browser/ui/views/browser_bubble.h"
 
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_win.h"
 #include "views/window/window.h"
@@ -98,10 +98,6 @@
   // we'll assign it into popup_.
   views::WidgetWin* pop = new BubbleWidget(this);
 
-  // Enable the drop-shadow through the native windows drop-shadow support.
-  if (drop_shadow_enabled_)
-    pop->set_initial_class_style(CS_DROPSHADOW | pop->initial_class_style());
-
   pop->Init(frame_->GetNativeView(), bounds_);
   pop->SetContentsView(view_);
 
diff --git a/chrome/browser/ui/views/browser_dialogs.h b/chrome/browser/ui/views/browser_dialogs.h
index ce74e38..d68cedf 100644
--- a/chrome/browser/ui/views/browser_dialogs.h
+++ b/chrome/browser/ui/views/browser_dialogs.h
@@ -9,12 +9,14 @@
 #include <string>
 
 #include "chrome/common/content_settings_types.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 // This file contains functions for running a variety of browser dialogs and
 // popups. The dialogs here are the ones that the caller does not need to
 // access the class of the popup. It allows us to break dependencies by
 // allowing the callers to not depend on the classes implementing the dialogs.
+// TODO: Make as many of these methods as possible cross platform, and move them
+// into chrome/browser/ui/browser_dialogs.h.
 
 class Browser;
 class BrowserView;
@@ -23,7 +25,6 @@
 class FilePath;
 class FindBar;
 class GURL;
-class HtmlDialogUIDelegate;
 class InfoBubbleDelegate;
 class Profile;
 class TabContents;
@@ -71,10 +72,6 @@
 views::Window* ShowAboutChromeView(gfx::NativeWindow parent,
                                    Profile* profile);
 
-// Shows an HTML dialog. See HtmlDialogView.
-void ShowHtmlDialogView(gfx::NativeWindow parent, Profile* profile,
-                        HtmlDialogUIDelegate* delegate);
-
 // Creates and returns a find bar for the given browser window. See FindBarWin.
 FindBar* CreateFindBar(BrowserView* browser_view);
 
@@ -88,6 +85,9 @@
 // Shows the Task Manager.
 void ShowTaskManager();
 
+// Shows the Task Manager, highlighting the background pages.
+void ShowBackgroundPages();
+
 #if defined(OS_CHROMEOS)
 // Shows the Login Wizard.
 void ShowLoginWizard(const std::string& start_screen, const gfx::Size& size);
diff --git a/chrome/browser/ui/views/browser_keyboard_accessibility_test_win.cc b/chrome/browser/ui/views/browser_keyboard_accessibility_test_win.cc
deleted file mode 100644
index ea7e52e..0000000
--- a/chrome/browser/ui/views/browser_keyboard_accessibility_test_win.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "app/keyboard_codes.h"
-#include "chrome/browser/automation/ui_controls.h"
-#include "chrome/browser/views/chrome_views_delegate.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/test/in_process_browser_test.h"
-#include "chrome/test/ui_test_utils.h"
-#include "views/view.h"
-#include "views/accessibility/view_accessibility.h"
-#include "views/widget/widget.h"
-#include "views/window/window.h"
-
-namespace {
-
-class BrowserKeyboardAccessibility : public InProcessBrowserTest,
-                                     public ChromeViewsDelegate {
- public:
-  BrowserKeyboardAccessibility()
-      : is_waiting_(false),
-        current_view_(NULL),
-        current_event_type_(AccessibilityTypes::EVENT_FOCUS) {
-    // Set ourselves as the currently active ViewsDelegate.
-    ViewsDelegate::views_delegate = this;
-  }
-
-  ~BrowserKeyboardAccessibility() {}
-
-  // Overridden from ChromeViewsDelegate.
-  // Save the last notification sent by views::View::NotifyAccessibilityEvent.
-  virtual void NotifyAccessibilityEvent(
-      views::View* view, AccessibilityTypes::Event event_type) {
-    current_view_  = view;
-    current_event_type_ = event_type;
-
-    // Are we within a message loop waiting for a particular event?
-    // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-    LOG(ERROR) << "Got notification; is_waiting_ is "
-               << (is_waiting_ ? "true" : "false");
-    if (is_waiting_) {
-      is_waiting_ = false;
-      MessageLoop::current()->Quit();
-    }
-  }
-
-  // Helper that performs tabbing until it cycles back to the original focus.
-  void TabCyclerForwardAndBack(gfx::NativeWindow hwnd);
-  void TabCycler(gfx::NativeWindow hwnd, bool forward_tab);
-
-  views::View* current_view() const { return current_view_; }
-
-  gfx::NativeWindow current_view_native_window() const {
-    return current_view()->GetWidget()->GetNativeView();
-  }
-
-  AccessibilityTypes::Event current_event() const {
-    return current_event_type_;
-  }
-
-  void set_waiting(bool value) { is_waiting_ = value; }
-
- private:
-  // Are we waiting for an event?
-  bool is_waiting_;
-
-  // View of interest (i.e. for testing or one we are waiting to gain focus).
-  views::View* current_view_;
-
-  // Event type of interest.
-  AccessibilityTypes::Event current_event_type_;
-};
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInAboutChromeDialog) {
-  views::Window* about_chrome_window =
-      BrowserView::GetBrowserViewForNativeWindow(
-          browser()->window()->GetNativeHandle())->ShowAboutChromeDialog();
-
-  TabCyclerForwardAndBack(about_chrome_window->GetNativeWindow());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInClearBrowsingDataDialog) {
-  browser()->OpenClearBrowsingDataDialog();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInImportSettingsDialog) {
-  browser()->OpenImportSettingsDialog();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInKeywordEditor) {
-  browser()->OpenKeywordEditor();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInOptionsDialog) {
-  browser()->OpenOptionsDialog();
-
-  // Tab through each of the three tabs.
-  for (int i = 0; i < 3; ++i) {
-    // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-    LOG(ERROR) << "Iteration no. " << i;
-
-    TabCyclerForwardAndBack(current_view_native_window());
-
-
-    // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-    LOG(ERROR) << "Sending TAB key event...";
-    ui_controls::SendKeyPressNotifyWhenDone(current_view_native_window(),
-                                            app::VKEY_TAB,
-                                            true, false, false, false,
-                                            new MessageLoop::QuitTask());
-    set_waiting(true);
-    ui_test_utils::RunMessageLoop();
-  }
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInPasswordManager) {
-  browser()->OpenPasswordManager();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// TODO(dtseng): http://www.crbug.com/50402
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInSyncMyBookmarksDialog) {
-  browser()->OpenSyncMyBookmarksDialog();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInTaskManager) {
-  browser()->OpenTaskManager();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInToolbar) {
-  gfx::NativeWindow native_window = browser()->window()->GetNativeHandle();
-  ui_controls::SendKeyPressNotifyWhenDone(native_window,
-                                          app::VKEY_T,
-                                          false, true, true, false,
-                                          new MessageLoop::QuitTask());
-  set_waiting(true);
-  ui_test_utils::RunMessageLoop();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-// This test is disabled, see bug 50864.
-IN_PROC_BROWSER_TEST_F(BrowserKeyboardAccessibility,
-                       DISABLED_TabInUpdateChromeDialog) {
-  browser()->OpenUpdateChromeDialog();
-  TabCyclerForwardAndBack(current_view_native_window());
-}
-
-void BrowserKeyboardAccessibility::TabCyclerForwardAndBack(
-    gfx::NativeWindow hwnd) {
-  TabCycler(hwnd, true);
-  TabCycler(hwnd, false);
-}
-
-void BrowserKeyboardAccessibility::TabCycler(gfx::NativeWindow hwnd,
-                                             bool forward_tab) {
-  // Wait for a focus event on the provided native window.
-  while (current_event() != AccessibilityTypes::EVENT_FOCUS ||
-         current_view_native_window() != hwnd) {
-    // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-    LOG(ERROR) << "Runnig message loop...";
-    set_waiting(true);
-    ui_test_utils::RunMessageLoop();
-  }
-  // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-  LOG(ERROR) << "After the loop.";
-
-  views::View* first_focused_item = current_view();
-
-  ASSERT_TRUE(first_focused_item != NULL);
-
-  views::View* next_focused_item = first_focused_item;
-
-  // Keep tabbing until we reach the originally focused view.
-  do {
-    // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-    LOG(ERROR) << "Sending TAB key event.";
-    ui_controls::SendKeyPressNotifyWhenDone(hwnd, app::VKEY_TAB,
-        false, !forward_tab, false, false, new MessageLoop::QuitTask());
-    set_waiting(true);
-    ui_test_utils::RunMessageLoop();
-    next_focused_item = current_view();
-  } while (first_focused_item != next_focused_item);
-  // TODO(phajdan.jr): remove logging after fixing http://crbug.com/50663.
-  LOG(ERROR) << "After second loop.";
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/views/bubble_border.cc b/chrome/browser/ui/views/bubble_border.cc
index e37f5fe..17c5933 100644
--- a/chrome/browser/ui/views/bubble_border.cc
+++ b/chrome/browser/ui/views/bubble_border.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/bubble_border.h"
+#include "chrome/browser/ui/views/bubble_border.h"
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/path.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/path.h"
 
 // static
 SkBitmap* BubbleBorder::left_ = NULL;
@@ -433,7 +433,7 @@
   paint.setStyle(SkPaint::kFill_Style);
   paint.setColor(border_->background_color());
   gfx::Path path;
-  gfx::Rect bounds(view->GetLocalBounds(false));
+  gfx::Rect bounds(view->GetContentsBounds());
   SkRect rect;
   rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
            SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom()));
diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc
index 7ed8ef7..3771682 100644
--- a/chrome/browser/ui/views/chrome_views_delegate.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate.cc
@@ -1,38 +1,65 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/chrome_views_delegate.h"
+#include "chrome/browser/ui/views/chrome_views_delegate.h"
 
-#include "app/clipboard/clipboard.h"
 #include "base/scoped_ptr.h"
+#include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/views/accessibility_event_router_views.h"
 #include "chrome/browser/ui/window_sizer.h"
-#include "gfx/rect.h"
+#include "chrome/common/pref_names.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/gfx/rect.h"
+#include "views/window/window.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/app_icon_win.h"
 #endif
 
+namespace {
+
+// If the given window has a profile associated with it, use that profile's
+// preference service. Otherwise, store and retrieve the data from Local State.
+// This function may return NULL if the necessary pref service has not yet
+// been initialized.
+// TODO(mirandac): This function will also separate windows by profile in a
+// multi-profile environment.
+PrefService* GetPrefsForWindow(views::Window* window) {
+  Profile* profile =
+      reinterpret_cast<Profile*>(window->GetNativeWindowProperty(
+          Profile::kProfileKey));
+  if (!profile) {
+    // Use local state for windows that have no explicit profile.
+    return g_browser_process->local_state();
+  }
+  return profile->GetPrefs();
+}
+
+}  // namespace
+
 ///////////////////////////////////////////////////////////////////////////////
 // ChromeViewsDelegate, views::ViewsDelegate implementation:
 
-Clipboard* ChromeViewsDelegate::GetClipboard() const {
+ui::Clipboard* ChromeViewsDelegate::GetClipboard() const {
   return g_browser_process->clipboard();
 }
 
-void ChromeViewsDelegate::SaveWindowPlacement(const std::wstring& window_name,
+void ChromeViewsDelegate::SaveWindowPlacement(views::Window* window,
+                                              const std::wstring& window_name,
                                               const gfx::Rect& bounds,
                                               bool maximized) {
-  if (!g_browser_process->local_state())
+  PrefService* prefs = GetPrefsForWindow(window);
+  if (!prefs)
     return;
 
+  DCHECK(prefs->FindPreference(WideToUTF8(window_name).c_str()));
   DictionaryValue* window_preferences =
-      g_browser_process->local_state()->GetMutableDictionary(
-          WideToUTF8(window_name).c_str());
+      prefs->GetMutableDictionary(WideToUTF8(window_name).c_str());
   window_preferences->SetInteger("left", bounds.x());
   window_preferences->SetInteger("top", bounds.y());
   window_preferences->SetInteger("right", bounds.right());
@@ -49,14 +76,16 @@
   window_preferences->SetInteger("work_area_bottom", work_area.bottom());
 }
 
-bool ChromeViewsDelegate::GetSavedWindowBounds(const std::wstring& window_name,
+bool ChromeViewsDelegate::GetSavedWindowBounds(views::Window* window,
+                                               const std::wstring& window_name,
                                                gfx::Rect* bounds) const {
-  if (!g_browser_process->local_state())
+  PrefService* prefs = GetPrefsForWindow(window);
+  if (!prefs)
     return false;
 
+  DCHECK(prefs->FindPreference(WideToUTF8(window_name).c_str()));
   const DictionaryValue* dictionary =
-      g_browser_process->local_state()->GetDictionary(
-          WideToUTF8(window_name).c_str());
+      prefs->GetDictionary(WideToUTF8(window_name).c_str());
   int left, top, right, bottom;
   if (!dictionary || !dictionary->GetInteger("left", &left) ||
       !dictionary->GetInteger("top", &top) ||
@@ -69,14 +98,17 @@
 }
 
 bool ChromeViewsDelegate::GetSavedMaximizedState(
+    views::Window* window,
     const std::wstring& window_name,
     bool* maximized) const {
-  if (!g_browser_process->local_state())
+  PrefService* prefs = GetPrefsForWindow(window);
+  if (!prefs)
     return false;
 
+  DCHECK(prefs->FindPreference(WideToUTF8(window_name).c_str()));
   const DictionaryValue* dictionary =
-      g_browser_process->local_state()->GetDictionary(
-          WideToUTF8(window_name).c_str());
+      prefs->GetDictionary(WideToUTF8(window_name).c_str());
+
   return dictionary && dictionary->GetBoolean("maximized", maximized) &&
       maximized;
 }
diff --git a/chrome/browser/ui/views/chrome_views_delegate.h b/chrome/browser/ui/views/chrome_views_delegate.h
index 8b3a6a2..c48f07b 100644
--- a/chrome/browser/ui/views/chrome_views_delegate.h
+++ b/chrome/browser/ui/views/chrome_views_delegate.h
@@ -10,19 +10,26 @@
 #include "build/build_config.h"
 #include "views/views_delegate.h"
 
+namespace views {
+class Window;
+}
+
 class ChromeViewsDelegate : public views::ViewsDelegate {
  public:
   ChromeViewsDelegate() {}
   virtual ~ChromeViewsDelegate() {}
 
   // Overridden from views::ViewsDelegate:
-  virtual Clipboard* GetClipboard() const;
-  virtual void SaveWindowPlacement(const std::wstring& window_name,
+  virtual ui::Clipboard* GetClipboard() const;
+  virtual void SaveWindowPlacement(views::Window* window,
+                                   const std::wstring& window_name,
                                    const gfx::Rect& bounds,
                                    bool maximized);
-  virtual bool GetSavedWindowBounds(const std::wstring& window_name,
+  virtual bool GetSavedWindowBounds(views::Window* window,
+                                    const std::wstring& window_name,
                                     gfx::Rect* bounds) const;
-  virtual bool GetSavedMaximizedState(const std::wstring& window_name,
+  virtual bool GetSavedMaximizedState(views::Window* window,
+                                      const std::wstring& window_name,
                                       bool* maximized) const;
   virtual void NotifyAccessibilityEvent(
       views::View* view, AccessibilityTypes::Event event_type);
diff --git a/chrome/browser/ui/views/clear_browsing_data.cc b/chrome/browser/ui/views/clear_browsing_data.cc
index 0693d5a..3b572c2 100644
--- a/chrome/browser/ui/views/clear_browsing_data.cc
+++ b/chrome/browser/ui/views/clear_browsing_data.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/clear_browsing_data.h"
+#include "chrome/browser/ui/views/clear_browsing_data.h"
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
@@ -13,20 +12,21 @@
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/ui/browser.h"
 #if defined(OS_WIN)
-#include "chrome/browser/views/clear_browsing_data_view.h"
+#include "chrome/browser/ui/views/clear_browsing_data_view.h"
 #endif
 #include "chrome/common/pref_names.h"
-#include "gfx/insets.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/insets.h"
 #include "views/background.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/dialog_client_view.h"
 #include "views/window/window.h"
@@ -135,7 +135,8 @@
   time_period_combobox_->SetSelectedItem(profile_->GetPrefs()->GetInteger(
                                          prefs::kDeleteTimePeriod));
   time_period_combobox_->set_listener(this);
-  time_period_combobox_->SetAccessibleName(time_period_label_->GetText());
+  time_period_combobox_->SetAccessibleName(
+      WideToUTF16Hack(time_period_label_->GetText()));
   AddChildView(time_period_combobox_);
 
   // Create the throbber and related views. The throbber and status link are
@@ -149,11 +150,13 @@
   // DialogClientView positions the extra view at kButtonHEdgeMargin, but we
   // put all our controls at kPanelHorizMargin. Add a padding column so things
   // line up nicely.
-  if (kPanelHorizMargin - kButtonHEdgeMargin > 0)
-    column_set->AddPaddingColumn(0, kPanelHorizMargin - kButtonHEdgeMargin);
+  if (kPanelHorizMargin - views::kButtonHEdgeMargin > 0) {
+    column_set->AddPaddingColumn(
+        0, kPanelHorizMargin - views::kButtonHEdgeMargin);
+  }
   column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
   layout->StartRow(1, 0);
@@ -183,42 +186,42 @@
   del_history_checkbox_->SetBounds(2 * kPanelHorizMargin,
                                    delete_all_label_->y() +
                                        delete_all_label_->height() +
-                                       kRelatedControlVerticalSpacing,
+                                       views::kRelatedControlVerticalSpacing,
                                    sz.width(), sz.height());
 
   sz = del_downloads_checkbox_->GetPreferredSize();
   del_downloads_checkbox_->SetBounds(2 * kPanelHorizMargin,
                                      del_history_checkbox_->y() +
                                          del_history_checkbox_->height() +
-                                         kRelatedControlVerticalSpacing,
+                                         views::kRelatedControlVerticalSpacing,
                                      sz.width(), sz.height());
 
   sz = del_cache_checkbox_->GetPreferredSize();
   del_cache_checkbox_->SetBounds(2 * kPanelHorizMargin,
                                  del_downloads_checkbox_->y() +
                                      del_downloads_checkbox_->height() +
-                                     kRelatedControlVerticalSpacing,
+                                     views::kRelatedControlVerticalSpacing,
                                  sz.width(), sz.height());
 
   sz = del_cookies_checkbox_->GetPreferredSize();
   del_cookies_checkbox_->SetBounds(2 * kPanelHorizMargin,
                                    del_cache_checkbox_->y() +
                                        del_cache_checkbox_->height() +
-                                       kRelatedControlVerticalSpacing,
+                                       views::kRelatedControlVerticalSpacing,
                                    sz.width(), sz.height());
 
   sz = del_passwords_checkbox_->GetPreferredSize();
   del_passwords_checkbox_->SetBounds(2 * kPanelHorizMargin,
                                      del_cookies_checkbox_->y() +
                                          del_cookies_checkbox_->height() +
-                                         kRelatedControlVerticalSpacing,
+                                         views::kRelatedControlVerticalSpacing,
                                      sz.width(), sz.height());
 
   sz = del_form_data_checkbox_->GetPreferredSize();
   del_form_data_checkbox_->SetBounds(2 * kPanelHorizMargin,
                                      del_passwords_checkbox_->y() +
                                          del_passwords_checkbox_->height() +
-                                         kRelatedControlVerticalSpacing,
+                                         views::kRelatedControlVerticalSpacing,
                                      sz.width(), sz.height());
 
   // Time period label is next below the combo boxes.
@@ -226,7 +229,7 @@
   time_period_label_->SetBounds(kPanelHorizMargin,
                                 del_form_data_checkbox_->y() +
                                     del_form_data_checkbox_->height() +
-                                    kRelatedControlVerticalSpacing +
+                                    views::kRelatedControlVerticalSpacing +
                                     kExtraMarginForTimePeriodLabel,
                                 sz.width(), sz.height());
 
@@ -236,7 +239,7 @@
   sz = time_period_combobox_->GetPreferredSize();
   time_period_combobox_->SetBounds(time_period_label_->x() +
                                        time_period_label_->width() +
-                                       kRelatedControlVerticalSpacing,
+                                       views::kRelatedControlVerticalSpacing,
                                    time_period_label_->y() -
                                        ((sz.height() - label_y_size) / 2),
                                    sz.width(), sz.height());
@@ -337,14 +340,15 @@
 
   views::View* settings_view = new views::View();
   GridLayout* layout = new GridLayout(settings_view);
-  layout->SetInsets(gfx::Insets(0, kPanelHorizMargin, 0, kButtonHEdgeMargin));
+  layout->SetInsets(
+      gfx::Insets(0, kPanelHorizMargin, 0, views::kButtonHEdgeMargin));
   settings_view->SetLayoutManager(layout);
   views::ColumnSet* column_set = layout->AddColumnSet(0);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
   layout->StartRow(0, 0);
   layout->AddView(new views::Separator());
-  layout->StartRowWithPadding(0, 0, 0, kRelatedControlVerticalSpacing);
+  layout->StartRowWithPadding(0, 0, 0, views::kRelatedControlVerticalSpacing);
   layout->AddView(flash_link, 1, 1, GridLayout::LEADING, GridLayout::CENTER);
 
   views::DialogClientView* client_view =
diff --git a/chrome/browser/ui/views/clear_browsing_data.h b/chrome/browser/ui/views/clear_browsing_data.h
index 8b1359e..b7e2ce9 100644
--- a/chrome/browser/ui/views/clear_browsing_data.h
+++ b/chrome/browser/ui/views/clear_browsing_data.h
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_CLEAR_BROWSING_DATA_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "chrome/browser/browsing_data_remover.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/button/button.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/label.h"
@@ -35,7 +35,7 @@
 class ClearBrowsingDataView : public views::View,
                               public views::DialogDelegate,
                               public views::ButtonListener,
-                              public ComboboxModel,
+                              public ui::ComboboxModel,
                               public views::Combobox::Listener,
                               public BrowsingDataRemover::Observer,
                               public views::LinkController {
@@ -69,7 +69,7 @@
   virtual bool GetSizeExtraViewHeightToButtons() { return true; }
   virtual views::View* GetInitiallyFocusedView();
 
-  // Overridden from ComboboxModel:
+  // Overridden from ui::ComboboxModel:
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
diff --git a/chrome/browser/ui/views/clear_browsing_data_view.cc b/chrome/browser/ui/views/clear_browsing_data_view.cc
index 2aced59..6fbcabb 100644
--- a/chrome/browser/ui/views/clear_browsing_data_view.cc
+++ b/chrome/browser/ui/views/clear_browsing_data_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/clear_browsing_data_view.h"
+#include "chrome/browser/ui/views/clear_browsing_data_view.h"
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
@@ -13,17 +12,18 @@
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/insets.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/insets.h"
 #include "views/background.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/dialog_client_view.h"
 #include "views/window/window.h"
@@ -117,7 +117,7 @@
 
   clear_browsing_data_button_ = new views::NativeButton(
       this,
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_BUTTON)));
+      UTF16ToWide(l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_COMMIT)));
 
   // Add a label which appears before the combo box for the time period.
   time_period_label_ = new views::Label(UTF16ToWide(
@@ -128,7 +128,8 @@
   time_period_combobox_->SetSelectedItem(profile_->GetPrefs()->GetInteger(
                                          prefs::kDeleteTimePeriod));
   time_period_combobox_->set_listener(this);
-  time_period_combobox_->SetAccessibleName(time_period_label_->GetText());
+  time_period_combobox_->SetAccessibleName(
+      WideToUTF16Hack(time_period_label_->GetText()));
 
   // Create the throbber and related views. The throbber and status link are
   // contained in throbber_view_, which is positioned by DialogClientView right
@@ -142,11 +143,13 @@
   // DialogClientView positions the extra view at kButtonHEdgeMargin, but we
   // put all our controls at kPanelHorizMargin. Add a padding column so things
   // line up nicely.
-  if (kPanelHorizMargin - kButtonHEdgeMargin > 0)
-    column_set->AddPaddingColumn(0, kPanelHorizMargin - kButtonHEdgeMargin);
+  if (kPanelHorizMargin - views::kButtonHEdgeMargin > 0) {
+    column_set->AddPaddingColumn(
+        0, kPanelHorizMargin - views::kButtonHEdgeMargin);
+  }
   column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
   layout->StartRow(1, 0);
@@ -155,7 +158,7 @@
 }
 
 void ClearBrowsingDataView2::InitControlLayout() {
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   this->SetLayoutManager(layout);
 
   int leading_column_set_id = 0;
@@ -173,7 +176,7 @@
   column_set = layout->AddColumnSet(two_column_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -185,32 +188,32 @@
   // Delete All label goes to the top left corner.
   layout->StartRow(0, leading_column_set_id);
   layout->AddView(delete_all_label_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Check-boxes go beneath it (with a little indentation).
   layout->StartRow(0, indented_column_set_id);
   layout->AddView(del_history_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, indented_column_set_id);
   layout->AddView(del_downloads_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, indented_column_set_id);
   layout->AddView(del_cache_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, indented_column_set_id);
   layout->AddView(del_cookies_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, indented_column_set_id);
   layout->AddView(del_passwords_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, indented_column_set_id);
   layout->AddView(del_form_data_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Time period label is next below the combo boxes followed by time
   // period combo box
@@ -220,7 +223,7 @@
   layout->AddView(time_period_combobox_, 1, 1, views::GridLayout::LEADING,
                   views::GridLayout::CENTER);
 
-  layout->AddPaddingRow(0, kUnrelatedControlLargeVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
 
   // Left-align the throbber
   layout->StartRow(0, two_column_set_id);
diff --git a/chrome/browser/ui/views/clear_browsing_data_view.h b/chrome/browser/ui/views/clear_browsing_data_view.h
index 0659057..695382a 100644
--- a/chrome/browser/ui/views/clear_browsing_data_view.h
+++ b/chrome/browser/ui/views/clear_browsing_data_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_UI_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "chrome/browser/browsing_data_remover.h"
-#include "chrome/browser/views/clear_data_view.h"
+#include "chrome/browser/ui/views/clear_data_view.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/button/button.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/label.h"
@@ -38,7 +38,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 class ClearBrowsingDataView2 : public views::View,
                                public views::ButtonListener,
-                               public ComboboxModel,
+                               public ui::ComboboxModel,
                                public views::Combobox::Listener,
                                public BrowsingDataRemover::Observer,
                                public views::LinkController {
@@ -50,7 +50,7 @@
   // Initialize the controls on the dialog.
   void Init();
 
-  // Overridden from ComboboxModel:
+  // Overridden from ui::ComboboxModel:
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
diff --git a/chrome/browser/ui/views/clear_data_view.cc b/chrome/browser/ui/views/clear_data_view.cc
index 839d668..4863917 100644
--- a/chrome/browser/ui/views/clear_data_view.cc
+++ b/chrome/browser/ui/views/clear_data_view.cc
@@ -1,31 +1,28 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/clear_data_view.h"
+#include "chrome/browser/ui/views/clear_data_view.h"
 
-#include "app/l10n_util.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/clear_browsing_data.h"
-#include "chrome/browser/views/clear_server_data.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/insets.h"
+#include "chrome/browser/ui/views/clear_browsing_data.h"
+#include "chrome/browser/ui/views/clear_server_data.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/insets.h"
 #include "views/background.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/dialog_client_view.h"
 #include "views/window/window.h"
@@ -53,9 +50,9 @@
 void ClearDataView::Init() {
   tabs_ = new views::TabbedPane;
 
-  tabs_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringFUTF16(IDS_OPTIONS_DIALOG_TITLE,
-          l10n_util::GetStringUTF16(IDS_OPTIONS_DIALOG_TITLE))));
+  tabs_->SetAccessibleName(l10n_util::GetStringFUTF16(
+      IDS_OPTIONS_DIALOG_TITLE,
+      l10n_util::GetStringUTF16(IDS_OPTIONS_DIALOG_TITLE)));
   AddChildView(tabs_);
 
   int tab_index = 0;
@@ -174,4 +171,3 @@
 views::View* ClearDataView::GetInitiallyFocusedView() {
   return GetDialogClientView()->cancel_button();
 }
-
diff --git a/chrome/browser/ui/views/clear_data_view.h b/chrome/browser/ui/views/clear_data_view.h
index ffd9338..4d2f027 100644
--- a/chrome/browser/ui/views/clear_data_view.h
+++ b/chrome/browser/ui/views/clear_data_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,12 +6,10 @@
 #define CHROME_BROWSER_UI_VIEWS_CLEAR_DATA_VIEW_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "chrome/browser/browsing_data_remover.h"
-#include "chrome/browser/views/clear_browsing_data_view.h"
-#include "chrome/browser/views/clear_server_data.h"
+#include "chrome/browser/ui/views/clear_browsing_data_view.h"
+#include "chrome/browser/ui/views/clear_server_data.h"
 #include "views/controls/button/button.h"
-#include "views/controls/combobox/combobox.h"
 #include "views/controls/label.h"
 #include "views/controls/link.h"
 #include "views/controls/tabbed_pane/tabbed_pane.h"
diff --git a/chrome/browser/ui/views/clear_server_data.cc b/chrome/browser/ui/views/clear_server_data.cc
index 34c158d..86d12b4 100644
--- a/chrome/browser/ui/views/clear_server_data.cc
+++ b/chrome/browser/ui/views/clear_server_data.cc
@@ -1,33 +1,31 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/clear_server_data.h"
+#include "chrome/browser/ui/views/clear_server_data.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/insets.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/url_request/url_request_context.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/insets.h"
 #include "views/background.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
 #include "views/controls/throbber.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/dialog_client_view.h"
 #include "views/window/window.h"
@@ -114,7 +112,7 @@
 }
 
 void ClearServerDataView::InitControlLayout() {
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   this->SetLayoutManager(layout);
 
   int centered_column_set_id = 0;
@@ -131,10 +129,10 @@
   column_set = layout->AddColumnSet(three_column_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -208,8 +206,9 @@
 
 void ClearServerDataView::AddSpacing(views::GridLayout* layout,
                                      bool related_follows) {
-  layout->AddPaddingRow(0, related_follows ? kRelatedControlVerticalSpacing
-                                           : kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(
+      0, related_follows ? views::kRelatedControlVerticalSpacing
+                         : views::kUnrelatedControlVerticalSpacing);
 }
 
 gfx::Size ClearServerDataView::GetPreferredSize() {
@@ -344,4 +343,3 @@
       sync_service_->HasSyncSetupCompleted() &&
       !delete_in_progress && allow_clear_);
 }
-
diff --git a/chrome/browser/ui/views/clear_server_data.h b/chrome/browser/ui/views/clear_server_data.h
index 6d0f09f..c80d8b4 100644
--- a/chrome/browser/ui/views/clear_server_data.h
+++ b/chrome/browser/ui/views/clear_server_data.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,15 +6,14 @@
 #define CHROME_BROWSER_UI_VIEWS_CLEAR_SERVER_DATA_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "chrome/browser/browsing_data_remover.h"
-#include "chrome/browser/views/clear_data_view.h"
-#include "chrome/browser/views/confirm_message_box_dialog.h"
 #include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/ui/views/clear_data_view.h"
+#include "chrome/browser/ui/views/confirm_message_box_dialog.h"
 #include "views/controls/button/button.h"
 #include "views/controls/label.h"
 #include "views/controls/link.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/view.h"
 #include "views/window/dialog_delegate.h"
 
diff --git a/chrome/browser/ui/views/collected_cookies_win.cc b/chrome/browser/ui/views/collected_cookies_win.cc
index a545971..5c7e45e 100644
--- a/chrome/browser/ui/views/collected_cookies_win.cc
+++ b/chrome/browser/ui/views/collected_cookies_win.cc
@@ -1,26 +1,27 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/collected_cookies_win.h"
+#include "chrome/browser/ui/views/collected_cookies_win.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "chrome/browser/cookies_tree_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
-#include "views/box_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
-#include "views/standard_layout.h"
+#include "views/layout/box_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget_win.h"
 #include "views/window/window.h"
@@ -113,7 +114,7 @@
         new views::BoxLayout(views::BoxLayout::kHorizontal,
                              kInfobarHorizontalPadding,
                              kInfobarVerticalPadding,
-                             kRelatedControlSmallHorizontalSpacing));
+                             views::kRelatedControlSmallHorizontalSpacing));
     content_->AddChildView(info_image_);
     content_->AddChildView(label_);
     UpdateVisibility(false, CONTENT_SETTING_BLOCK, std::wstring());
@@ -126,14 +127,14 @@
 
     // Add space around the banner.
     gfx::Size size(content_->GetPreferredSize());
-    size.Enlarge(0, 2 * kRelatedControlVerticalSpacing);
+    size.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing);
     return size;
   }
 
   virtual void Layout() {
     content_->SetBounds(
-        0, kRelatedControlVerticalSpacing,
-        width(), height() - kRelatedControlVerticalSpacing);
+        0, views::kRelatedControlVerticalSpacing,
+        width(), height() - views::kRelatedControlVerticalSpacing);
   }
 
   virtual void ViewHierarchyChanged(bool is_add,
@@ -221,7 +222,7 @@
 
   using views::GridLayout;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int single_column_layout_id = 0;
@@ -233,41 +234,41 @@
   column_set = layout->AddColumnSet(three_columns_layout_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, single_column_layout_id);
   layout->AddView(allowed_label_);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(1, single_column_layout_id);
   layout->AddView(
       allowed_cookies_tree_, 1, 1, GridLayout::FILL, GridLayout::FILL,
       kTreeViewWidth, kTreeViewHeight);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_layout_id);
   block_allowed_button_ = new views::NativeButton(this, UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON)));
   layout->AddView(
       block_allowed_button_, 1, 1, GridLayout::LEADING, GridLayout::CENTER);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_layout_id);
   layout->AddView(
       new views::Separator(), 1, 1, GridLayout::FILL, GridLayout::FILL);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_layout_id);
   layout->AddView(blocked_label_, 1, 1, GridLayout::FILL, GridLayout::FILL);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(1, single_column_layout_id);
   layout->AddView(
       blocked_cookies_tree_, 1, 1, GridLayout::FILL, GridLayout::FILL,
       kTreeViewWidth, kTreeViewHeight);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, three_columns_layout_id);
   allow_blocked_button_ = new views::NativeButton(this, UTF16ToWide(
@@ -339,7 +340,7 @@
 
 void CollectedCookiesWin::EnableControls() {
   bool enable_allowed_buttons = false;
-  TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode();
+  ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode();
   if (node) {
     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
     if (cookie_node->GetDetailedInfo().node_type ==
diff --git a/chrome/browser/ui/views/confirm_message_box_dialog.cc b/chrome/browser/ui/views/confirm_message_box_dialog.cc
index 10569f9..c79c347 100644
--- a/chrome/browser/ui/views/confirm_message_box_dialog.cc
+++ b/chrome/browser/ui/views/confirm_message_box_dialog.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/confirm_message_box_dialog.h"
+#include "chrome/browser/ui/views/confirm_message_box_dialog.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/utf_string_conversions.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-#include "views/standard_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -65,8 +65,8 @@
 }
 
 int ConfirmMessageBoxDialog::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK |
-         MessageBoxFlags::DIALOGBUTTON_CANCEL;
+  return ui::MessageBoxFlags::DIALOGBUTTON_OK |
+         ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
 }
 
 std::wstring ConfirmMessageBoxDialog::GetWindowTitle() const {
@@ -74,11 +74,11 @@
 }
 
 std::wstring ConfirmMessageBoxDialog::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
+    ui::MessageBoxFlags::DialogButton button) const {
+  if (button == ui::MessageBoxFlags::DIALOGBUTTON_OK) {
     return confirm_label_;
   }
-  if (button == MessageBoxFlags::DIALOGBUTTON_CANCEL)
+  if (button == ui::MessageBoxFlags::DIALOGBUTTON_CANCEL)
     return reject_label_;
   return DialogDelegate::GetDialogButtonLabel(button);
 }
diff --git a/chrome/browser/ui/views/confirm_message_box_dialog.h b/chrome/browser/ui/views/confirm_message_box_dialog.h
index f0da06e..cc97d31 100644
--- a/chrome/browser/ui/views/confirm_message_box_dialog.h
+++ b/chrome/browser/ui/views/confirm_message_box_dialog.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/controls/label.h"
 #include "views/window/dialog_delegate.h"
 
diff --git a/chrome/browser/ui/views/constrained_html_delegate_gtk.cc b/chrome/browser/ui/views/constrained_html_delegate_gtk.cc
index 60f3ec4..462f5b8 100644
--- a/chrome/browser/ui/views/constrained_html_delegate_gtk.cc
+++ b/chrome/browser/ui/views/constrained_html_delegate_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,13 @@
 
 #include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/gtk_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
 #include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
-#include "gfx/rect.h"
 #include "ipc/ipc_message.h"
+#include "ui/gfx/rect.h"
 #include "views/widget/widget_gtk.h"
 
 // ConstrainedHtmlDelegateGtk works with ConstrainedWindowGtk to present
diff --git a/chrome/browser/ui/views/constrained_html_delegate_win.cc b/chrome/browser/ui/views/constrained_html_delegate_win.cc
index 34d638e..98fe766 100644
--- a/chrome/browser/ui/views/constrained_html_delegate_win.cc
+++ b/chrome/browser/ui/views/constrained_html_delegate_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,9 +8,9 @@
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/tab_contents/tab_contents_container.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
 #include "ipc/ipc_message.h"
+#include "ui/gfx/rect.h"
 #include "views/view.h"
 #include "views/widget/widget_win.h"
 #include "views/window/window_delegate.h"
@@ -62,7 +62,7 @@
     window_ = window;
   }
 
-private:
+ private:
   TabContents html_tab_contents_;
 
   HtmlDialogUIDelegate* html_delegate_;
diff --git a/chrome/browser/ui/views/constrained_window_win.cc b/chrome/browser/ui/views/constrained_window_win.cc
index 121605f..116a072 100644
--- a/chrome/browser/ui/views/constrained_window_win.cc
+++ b/chrome/browser/ui/views/constrained_window_win.cc
@@ -1,14 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/constrained_window_win.h"
+#include "chrome/browser/ui/views/constrained_window_win.h"
 
-#include "app/resource_bundle.h"
-#include "app/win/hwnd_util.h"
-#include "app/win/win_util.h"
+#include <algorithm>
+
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
@@ -17,22 +15,24 @@
 #include "chrome/browser/ui/window_sizer.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/notification_service.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
-#include "gfx/path.h"
-#include "gfx/rect.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "net/base/net_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/button/image_button.h"
 #include "views/focus/focus_manager.h"
+#include "views/widget/widget_win.h"
 #include "views/window/client_view.h"
 #include "views/window/non_client_view.h"
 #include "views/window/window_resources.h"
 #include "views/window/window_shape.h"
+#include "views/window/window_win.h"
 
 using base::TimeDelta;
 
@@ -198,7 +198,8 @@
 
   SkColor GetTitleColor() const {
     return (container_->owner()->profile()->IsOffTheRecord() ||
-        !app::win::ShouldUseVistaFrame()) ? SK_ColorWHITE : SK_ColorBLACK;
+            !views::WidgetWin::IsAeroGlassEnabled()) ? SK_ColorWHITE
+                                                     : SK_ColorBLACK;
   }
 
   // Loads the appropriate set of WindowResources for the frame view.
@@ -312,7 +313,7 @@
   // See if we're in the sysmenu region.  (We check the ClientView first to be
   // consistent with OpaqueBrowserFrameView; it's not really necessary here.)
   gfx::Rect sysmenu_rect(IconBounds());
-  sysmenu_rect.set_x(MirroredLeftPointForRect(sysmenu_rect));
+  sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect));
   if (sysmenu_rect.Contains(point))
     return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU;
 
@@ -320,7 +321,7 @@
     return frame_component;
 
   // Then see if the point is within any of the window controls.
-  if (close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point))
+  if (close_button_->GetMirroredBounds().Contains(point))
     return HTCLOSE;
 
   int window_component = GetHTComponentForFrame(point, kFrameBorderThickness,
@@ -480,7 +481,7 @@
 
 void ConstrainedWindowFrameView::PaintTitleBar(gfx::Canvas* canvas) {
   canvas->DrawStringInt(container_->GetWindowTitle(), *title_font_,
-      GetTitleColor(), MirroredLeftPointForRect(title_bounds_),
+      GetTitleColor(), GetMirroredXForRect(title_bounds_),
       title_bounds_.y(), title_bounds_.width(), title_bounds_.height());
 }
 
@@ -535,7 +536,7 @@
 }
 
 void ConstrainedWindowFrameView::InitWindowResources() {
-  resources_.reset(app::win::ShouldUseVistaFrame() ?
+  resources_.reset(views::WidgetWin::IsAeroGlassEnabled() ?
     static_cast<views::WindowResources*>(new VistaWindowResources) :
     new XPWindowResources);
 }
@@ -544,7 +545,7 @@
 void ConstrainedWindowFrameView::InitClass() {
   static bool initialized = false;
   if (!initialized) {
-    title_font_ = new gfx::Font(app::win::GetWindowTitleFont());
+    title_font_ = new gfx::Font(views::WindowWin::GetWindowTitleFont());
     initialized = true;
   }
 }
@@ -571,6 +572,9 @@
 }
 
 void ConstrainedWindowWin::ShowConstrainedWindow() {
+  // We marked the view as hidden during construction.  Mark it as
+  // visible now so FocusManager will let us receive focus.
+  GetNonClientView()->SetVisible(true);
   if (owner_->delegate())
     owner_->delegate()->WillShowConstrainedWindow(owner_);
   ActivateConstrainedWindow();
@@ -614,6 +618,10 @@
   set_window_style(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION |
                    WS_THICKFRAME | WS_SYSMENU);
   set_focus_on_creation(false);
+  // Views default to visible.  Since we are creating a window that is
+  // not visible (no WS_VISIBLE), mark our View as hidden so that
+  // FocusManager can deal with it properly.
+  GetNonClientView()->SetVisible(false);
 
   WindowWin::Init(owner_->GetNativeView(), gfx::Rect());
 }
diff --git a/chrome/browser/ui/views/constrained_window_win.h b/chrome/browser/ui/views/constrained_window_win.h
index b7933aa..ca20a09 100644
--- a/chrome/browser/ui/views/constrained_window_win.h
+++ b/chrome/browser/ui/views/constrained_window_win.h
@@ -8,7 +8,7 @@
 
 #include "chrome/browser/tab_contents/constrained_window.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 #include "views/window/window_win.h"
 
 class ConstrainedTabContentsWindowDelegate;
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 25122f2..47589e1 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -1,14 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/content_setting_bubble_contents.h"
+#include "chrome/browser/ui/views/content_setting_bubble_contents.h"
 
 #if defined(OS_LINUX)
 #include <gdk/gdk.h>
 #endif
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/blocked_content_container.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
@@ -16,22 +15,23 @@
 #include "chrome/browser/plugin_updater.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/browser_dialogs.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/button/radio_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "webkit/glue/plugins/plugin_list.h"
 
 #if defined(OS_LINUX)
-#include "gfx/gtk_util.h"
+#include "ui/gfx/gtk_util.h"
 #endif
 
 // If we don't clamp the maximum width, then very long URLs and titles can make
@@ -57,9 +57,8 @@
   // views::View overrides:
   virtual bool OnMousePressed(const views::MouseEvent& event);
   virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
-  virtual gfx::NativeCursor GetCursorForPoint(
-      views::Event::EventType event_type,
-      const gfx::Point& p);
+  virtual gfx::NativeCursor GetCursorForPoint(ui::EventType event_type,
+                                              const gfx::Point& p);
 
   ContentSettingBubbleContents* parent_;
   views::Link* link_;
@@ -92,11 +91,11 @@
   if (!canceled &&
       (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) &&
       HitTest(event.location()))
-    parent_->LinkActivated(link_, event.GetFlags());
+    parent_->LinkActivated(link_, event.flags());
 }
 
 gfx::NativeCursor ContentSettingBubbleContents::Favicon::GetCursorForPoint(
-    views::Event::EventType event_type,
+    ui::EventType event_type,
     const gfx::Point& p) {
 #if defined(OS_WIN)
   if (!g_hand_cursor)
@@ -215,7 +214,7 @@
   const std::set<std::string>& plugins = bubble_content.resource_identifiers;
   if (!plugins.empty()) {
     if (!bubble_content_empty)
-      layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     for (std::set<std::string>::const_iterator it = plugins.begin();
         it != plugins.end(); ++it) {
       std::wstring name = UTF16ToWide(
@@ -235,7 +234,8 @@
         layout->AddColumnSet(popup_column_set_id);
     popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
                                 GridLayout::USE_PREF, 0, 0);
-    popup_column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    popup_column_set->AddPaddingColumn(
+        0, views::kRelatedControlHorizontalSpacing);
     popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
                                 GridLayout::USE_PREF, 0, 0);
 
@@ -243,7 +243,7 @@
          i(bubble_content.popup_items.begin());
          i != bubble_content.popup_items.end(); ++i) {
       if (!bubble_content_empty)
-        layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+        layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
       layout->StartRow(0, popup_column_set_id);
 
       views::Link* link = new views::Link(UTF8ToWide(i->title));
@@ -266,7 +266,7 @@
       radio->set_listener(this);
       radio_group_.push_back(radio);
       if (!bubble_content_empty)
-        layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+        layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
       layout->StartRow(0, single_column_set_id);
       layout->AddView(radio);
       bubble_content_empty = false;
@@ -307,18 +307,18 @@
     custom_link_->SetEnabled(bubble_content.custom_link_enabled);
     custom_link_->SetController(this);
     if (!bubble_content_empty)
-      layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     layout->StartRow(0, single_column_set_id);
     layout->AddView(custom_link_);
     bubble_content_empty = false;
   }
 
   if (!bubble_content_empty) {
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     layout->StartRow(0, single_column_set_id);
     layout->AddView(new views::Separator, 1, 1,
                     GridLayout::FILL, GridLayout::FILL);
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
 
   const int double_column_set_id = 1;
@@ -326,7 +326,8 @@
       layout->AddColumnSet(double_column_set_id);
   double_column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
-  double_column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
+  double_column_set->AddPaddingColumn(
+      0, views::kUnrelatedControlHorizontalSpacing);
   double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
diff --git a/chrome/browser/ui/views/cookie_info_view.cc b/chrome/browser/ui/views/cookie_info_view.cc
index 0b3fe98..9d4f297 100644
--- a/chrome/browser/ui/views/cookie_info_view.cc
+++ b/chrome/browser/ui/views/cookie_info_view.cc
@@ -1,29 +1,29 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/cookie_info_view.h"
+#include "chrome/browser/ui/views/cookie_info_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/message_loop.h"
 #include "base/string16.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/cookies_tree_model.h"
-#include "gfx/canvas.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
 #include "views/border.h"
-#include "views/grid_layout.h"
 #include "views/controls/label.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/tree/tree_view.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 static const int kCookieInfoViewBorderSize = 1;
 static const int kCookieInfoViewInsetSize = 3;
@@ -163,7 +163,7 @@
   layout->AddView(label);
   layout->AddView(value, 2, 1, views::GridLayout::FILL,
                   views::GridLayout::CENTER);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
 }
 
 void CookieInfoView::AddControlRow(int layout_id, views::GridLayout* layout,
@@ -171,7 +171,7 @@
   layout->StartRow(0, layout_id);
   layout->AddView(label);
   layout->AddView(control, 1, 1);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -225,7 +225,7 @@
   ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
diff --git a/chrome/browser/ui/views/cookie_info_view.h b/chrome/browser/ui/views/cookie_info_view.h
index 071201c..1b8d650 100644
--- a/chrome/browser/ui/views/cookie_info_view.h
+++ b/chrome/browser/ui/views/cookie_info_view.h
@@ -9,9 +9,9 @@
 #include <string>
 #include <vector>
 
-#include "app/combobox_model.h"
 #include "base/string16.h"
 #include "net/base/cookie_monster.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/view.h"
 
@@ -40,7 +40,7 @@
 //  Responsible for displaying a tabular grid of Cookie information.
 class CookieInfoView : public views::View,
                        public views::Combobox::Listener,
-                       public ComboboxModel {
+                       public ui::ComboboxModel {
  public:
   explicit CookieInfoView(bool editable_expiration_date);
   virtual ~CookieInfoView();
@@ -72,7 +72,7 @@
                            int prev_index,
                            int new_index);
 
-  // ComboboxModel overrides for expires_value_combobox_.
+  // ui::ComboboxModel overrides for expires_value_combobox_.
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc
index 61415fb..cc12d2c 100644
--- a/chrome/browser/ui/views/create_application_shortcut_view.cc
+++ b/chrome/browser/ui/views/create_application_shortcut_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/create_application_shortcut_view.h"
+#include "chrome/browser/ui/views/create_application_shortcut_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/utf_string_conversions.h"
 #include "base/win/windows_version.h"
@@ -17,19 +15,21 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/codec/png_codec.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkPaint.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 namespace {
@@ -119,7 +119,7 @@
 }
 
 void AppInfoView::SetupLayout() {
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   static const int kColumnSetId = 0;
@@ -156,7 +156,7 @@
 }
 
 void AppInfoView::Paint(gfx::Canvas* canvas) {
-  gfx::Rect bounds = GetLocalBounds(true);
+  gfx::Rect bounds = GetLocalBounds();
 
   SkRect border_rect = {
     SkIntToScalar(bounds.x()),
@@ -263,7 +263,7 @@
 #endif
 
   // Layout controls
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   static const int kHeaderColumnSetId = 0;
@@ -289,13 +289,13 @@
   layout->AddView(desktop_check_box_);
 
   if (menu_check_box_ != NULL) {
-    layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
     layout->StartRow(0, kTableColumnSetId);
     layout->AddView(menu_check_box_);
   }
 
   if (quick_launch_check_box_ != NULL) {
-    layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
     layout->StartRow(0, kTableColumnSetId);
     layout->AddView(quick_launch_check_box_);
   }
diff --git a/chrome/browser/ui/views/database_info_view.cc b/chrome/browser/ui/views/database_info_view.cc
index 065d814..0f0d6e4 100644
--- a/chrome/browser/ui/views/database_info_view.cc
+++ b/chrome/browser/ui/views/database_info_view.cc
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/database_info_view.h"
+#include "chrome/browser/ui/views/database_info_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 static const int kDatabaseInfoViewBorderSize = 1;
 static const int kDatabaseInfoViewInsetSize = 3;
@@ -111,7 +111,7 @@
   views::ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -121,11 +121,11 @@
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(description_label);
   layout->AddView(description_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(size_label);
   layout->AddView(size_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(last_modified_label);
   layout->AddView(last_modified_value_field_);
diff --git a/chrome/browser/ui/views/database_open_info_view.cc b/chrome/browser/ui/views/database_open_info_view.cc
index 02e7fae..7bdbbef 100644
--- a/chrome/browser/ui/views/database_open_info_view.cc
+++ b/chrome/browser/ui/views/database_open_info_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/database_open_info_view.h"
+#include "chrome/browser/ui/views/database_open_info_view.h"
 
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
diff --git a/chrome/browser/ui/views/database_open_info_view.h b/chrome/browser/ui/views/database_open_info_view.h
index c8df3cd..8dd69e5 100644
--- a/chrome/browser/ui/views/database_open_info_view.h
+++ b/chrome/browser/ui/views/database_open_info_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/string16.h"
-#include "chrome/browser/views/generic_info_view.h"
+#include "chrome/browser/ui/views/generic_info_view.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // DatabaseOpenInfoView
diff --git a/chrome/browser/ui/views/default_search_view.cc b/chrome/browser/ui/views/default_search_view.cc
index b2c1e27..3dea858 100644
--- a/chrome/browser/ui/views/default_search_view.cc
+++ b/chrome/browser/ui/views/default_search_view.cc
@@ -1,29 +1,29 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/default_search_view.h"
+#include "chrome/browser/ui/views/default_search_view.h"
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/message_box_flags.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/dialog_client_view.h"
 #include "views/window/window.h"
 
@@ -156,7 +156,7 @@
 }
 
 int DefaultSearchView::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_NONE;
+  return ui::MessageBoxFlags::DIALOGBUTTON_NONE;
 }
 
 bool DefaultSearchView::Accept() {
@@ -244,7 +244,8 @@
   choices_column_set->AddPaddingColumn(1, kPanelVertMargin);
   choices_column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER,
                                 1, GridLayout::USE_PREF, 0, 0);
-  choices_column_set->AddPaddingColumn(1, kRelatedControlHorizontalSpacing);
+  choices_column_set->AddPaddingColumn(
+      1, views::kRelatedControlHorizontalSpacing);
   choices_column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER,
                                 1, GridLayout::USE_PREF, 0, 0);
   choices_column_set->LinkColumnSizes(0, 2, -1);
@@ -275,19 +276,19 @@
 
   // Add the labels for the tops of the choices.
   layout->StartRowWithPadding(0, kChoicesViewSetId,
-                              0, kRelatedControlVerticalSpacing);
+                              0, views::kRelatedControlVerticalSpacing);
   layout->AddView(CreateProviderLabel(IDS_DEFAULT_SEARCH_LABEL_CURRENT));
   layout->AddView(CreateProviderLabel(IDS_DEFAULT_SEARCH_LABEL_PROPOSED));
 
   // Add the logos.
   layout->StartRowWithPadding(0, kChoicesViewSetId,
-                              0, kRelatedControlVerticalSpacing);
+                              0, views::kRelatedControlVerticalSpacing);
   layout->AddView(CreateProviderLogo(default_logo_id, default_short_name));
   layout->AddView(CreateProviderLogo(proposed_logo_id, proposed_short_name));
 
   // Add the buttons.
   layout->StartRowWithPadding(0, kChoicesViewSetId,
-                              0, kRelatedControlVerticalSpacing);
+                              0, views::kRelatedControlVerticalSpacing);
   default_provider_button_ = CreateProviderChoiceButton(
       this,
       IDS_DEFAULT_SEARCH_PROMPT_CURRENT,
diff --git a/chrome/browser/ui/views/default_search_view.h b/chrome/browser/ui/views/default_search_view.h
index 607bca6..a60263e 100644
--- a/chrome/browser/ui/views/default_search_view.h
+++ b/chrome/browser/ui/views/default_search_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,7 +13,7 @@
 #include "views/window/dialog_delegate.h"
 
 #if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
 #endif
 
 class PrefService;
diff --git a/chrome/browser/ui/views/detachable_toolbar_view.cc b/chrome/browser/ui/views/detachable_toolbar_view.cc
index e2aaa3a..f87010f 100644
--- a/chrome/browser/ui/views/detachable_toolbar_view.cc
+++ b/chrome/browser/ui/views/detachable_toolbar_view.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/detachable_toolbar_view.h"
+#include "chrome/browser/ui/views/detachable_toolbar_view.h"
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/skia_util.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/skia_util.h"
 #include "views/window/non_client_view.h"
 
 // How round the 'new tab' style bookmarks bar is.
@@ -26,7 +26,7 @@
     gfx::Canvas* canvas,
     views::View* view,
     const gfx::Point& background_origin) {
-  ThemeProvider* tp = view->GetThemeProvider();
+  ui::ThemeProvider* tp = view->GetThemeProvider();
   SkColor theme_toolbar_color =
       tp->GetColor(BrowserThemeProvider::COLOR_TOOLBAR);
   canvas->FillRectInt(theme_toolbar_color, 0, 0,
@@ -63,7 +63,7 @@
 
 // static
 void DetachableToolbarView::PaintContentAreaBackground(
-    gfx::Canvas* canvas, ThemeProvider* theme_provider,
+    gfx::Canvas* canvas, ui::ThemeProvider* theme_provider,
     const SkRect& rect, double roundness) {
   SkPaint paint;
   paint.setAntiAlias(true);
@@ -75,7 +75,7 @@
 
 // static
 void DetachableToolbarView::PaintContentAreaBorder(
-    gfx::Canvas* canvas, ThemeProvider* theme_provider,
+    gfx::Canvas* canvas, ui::ThemeProvider* theme_provider,
     const SkRect& rect, double roundness) {
   SkPaint border_paint;
   border_paint.setColor(
diff --git a/chrome/browser/ui/views/detachable_toolbar_view.h b/chrome/browser/ui/views/detachable_toolbar_view.h
index 65008e0..9f69bf1 100644
--- a/chrome/browser/ui/views/detachable_toolbar_view.h
+++ b/chrome/browser/ui/views/detachable_toolbar_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/accessible_pane_view.h"
+#include "chrome/browser/ui/views/accessible_pane_view.h"
 
 class SkBitmap;
 struct SkRect;
@@ -60,12 +60,12 @@
   // bookmarks or extension toolstrips). |rect| is the rectangle to paint
   // the background within. |roundness| describes the roundness of the corners.
   static void PaintContentAreaBackground(gfx::Canvas* canvas,
-                                         ThemeProvider* theme_provider,
+                                         ui::ThemeProvider* theme_provider,
                                          const SkRect& rect,
                                          double roundness);
   // Paint the border around the content area (when in detached mode).
   static void PaintContentAreaBorder(gfx::Canvas* canvas,
-                                     ThemeProvider* theme_provider,
+                                     ui::ThemeProvider* theme_provider,
                                      const SkRect& rect,
                                      double roundness);
 
diff --git a/chrome/browser/ui/views/dialog_stubs_gtk.cc b/chrome/browser/ui/views/dialog_stubs_gtk.cc
index 4dd0150..463295b 100644
--- a/chrome/browser/ui/views/dialog_stubs_gtk.cc
+++ b/chrome/browser/ui/views/dialog_stubs_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,17 +8,17 @@
 #include <gtk/gtk.h>
 
 #include "base/logging.h"
-#include "chrome/browser/gtk/about_chrome_dialog.h"
 #include "chrome/browser/fonts_languages_window.h"
-#include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h"
-#include "chrome/browser/gtk/collected_cookies_gtk.h"
-#include "chrome/browser/gtk/edit_search_engine_dialog.h"
-#include "chrome/browser/gtk/keyword_editor_view.h"
-#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
-#include "chrome/browser/gtk/options/passwords_exceptions_window_gtk.h"
-#include "chrome/browser/gtk/repost_form_warning_gtk.h"
-#include "chrome/browser/gtk/task_manager_gtk.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/gtk/about_chrome_dialog.h"
+#include "chrome/browser/ui/gtk/clear_browsing_data_dialog_gtk.h"
+#include "chrome/browser/ui/gtk/collected_cookies_gtk.h"
+#include "chrome/browser/ui/gtk/edit_search_engine_dialog.h"
+#include "chrome/browser/ui/gtk/keyword_editor_view.h"
+#include "chrome/browser/ui/gtk/options/content_settings_window_gtk.h"
+#include "chrome/browser/ui/gtk/options/passwords_exceptions_window_gtk.h"
+#include "chrome/browser/ui/gtk/repost_form_warning_gtk.h"
+#include "chrome/browser/ui/gtk/task_manager_gtk.h"
 #include "chrome/browser/ui/options/options_window.h"
 #include "chrome/browser/ui/views/browser_dialogs.h"
 #include "views/widget/widget.h"
@@ -45,7 +45,11 @@
 }
 
 void ShowTaskManager() {
-  TaskManagerGtk::Show();
+  TaskManagerGtk::Show(false);
+}
+
+void ShowBackgroundPages() {
+  TaskManagerGtk::Show(true);
 }
 
 void EditSearchEngine(gfx::NativeWindow parent,
diff --git a/chrome/browser/ui/views/dom_view.cc b/chrome/browser/ui/views/dom_view.cc
index cc442d3..ec5e78f 100644
--- a/chrome/browser/ui/views/dom_view.cc
+++ b/chrome/browser/ui/views/dom_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/dom_view.h"
+#include "chrome/browser/ui/views/dom_view.h"
 
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "ipc/ipc_message.h"
diff --git a/chrome/browser/ui/views/dom_view.h b/chrome/browser/ui/views/dom_view.h
index 7a95d30..17af6be 100644
--- a/chrome/browser/ui/views/dom_view.h
+++ b/chrome/browser/ui/views/dom_view.h
@@ -12,7 +12,7 @@
 #include "base/scoped_ptr.h"
 #include "googleurl/src/gurl.h"
 #include "views/controls/native/native_view_host.h"
-#include "views/event.h"
+#include "views/events/event.h"
 
 class Profile;
 class SiteInstance;
diff --git a/chrome/browser/ui/views/dom_view_browsertest.cc b/chrome/browser/ui/views/dom_view_browsertest.cc
index 59cdef9..1e7ed8d 100644
--- a/chrome/browser/ui/views/dom_view_browsertest.cc
+++ b/chrome/browser/ui/views/dom_view_browsertest.cc
@@ -1,9 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/dom_view.h"
+#include "chrome/browser/ui/views/dom_view.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "views/widget/root_view.h"
diff --git a/chrome/browser/ui/views/download_item_view.cc b/chrome/browser/ui/views/download_item_view.cc
index 474b27b..92f5c34 100644
--- a/chrome/browser/ui/views/download_item_view.cc
+++ b/chrome/browser/ui/views/download_item_view.cc
@@ -1,14 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/download_item_view.h"
+#include "chrome/browser/ui/views/download_item_view.h"
 
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
 #include "base/callback.h"
 #include "base/file_path.h"
 #include "base/i18n/rtl.h"
@@ -20,12 +17,15 @@
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/views/download_shelf_view.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
+#include "chrome/browser/ui/views/download_shelf_view.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/widget/root_view.h"
@@ -280,16 +280,16 @@
     // Elide giant extensions (this shouldn't currently be hit, but might
     // in future, should we ever notice unsafe giant extensions).
     if (extension.length() > kFileNameMaxLength / 2)
-      gfx::ElideString(extension, kFileNameMaxLength / 2, &extension);
+      ui::ElideString(extension, kFileNameMaxLength / 2, &extension);
 
     // The dangerous download label text is different for an extension file.
     if (download->is_extension_install()) {
       dangerous_download_label_ = new views::Label(UTF16ToWide(
           l10n_util::GetStringUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION)));
     } else {
-      gfx::ElideString(rootname,
-                       kFileNameMaxLength - extension.length(),
-                       &rootname);
+      ui::ElideString(rootname,
+                      kFileNameMaxLength - extension.length(),
+                      &rootname);
       std::wstring filename = rootname + L"." + extension;
       filename = UTF16ToWide(base::i18n::GetDisplayStringInLTRDirectionality(
           WideToUTF16(filename)));
@@ -393,7 +393,7 @@
   // We use the parent's (DownloadShelfView's) SchedulePaint, since there
   // are spaces between each DownloadItemView that the parent is responsible
   // for painting.
-  GetParent()->SchedulePaint();
+  parent()->SchedulePaint();
 }
 
 void DownloadItemView::OnDownloadOpened(DownloadItem* download) {
@@ -498,7 +498,7 @@
   // Draw status before button image to effectively lighten text.
   if (!IsDangerousMode()) {
     if (show_status_text_) {
-      int mirrored_x = MirroredXWithWidthInsideView(
+      int mirrored_x = GetMirroredXWithWidthInView(
           download_util::kSmallProgressIconSize, kTextWidth);
       // Add font_.height() to compensate for title, which is drawn later.
       int y = box_y_ + kVerticalPadding + font_.GetHeight() +
@@ -515,8 +515,9 @@
                                SkColorGetG(file_name_color)),
               static_cast<int>(kDownloadItemLuminanceMod *
                                SkColorGetB(file_name_color)));
-      canvas->DrawStringInt(status_text_, font_, file_name_color,
-                            mirrored_x, y, kTextWidth, font_.GetHeight());
+      canvas->DrawStringInt(WideToUTF16Hack(status_text_), font_,
+                            file_name_color, mirrored_x, y, kTextWidth,
+                            font_.GetHeight());
     }
   }
 
@@ -608,8 +609,8 @@
   if (!IsDangerousMode()) {
     string16 filename;
     if (!disabled_while_opening_) {
-      filename = gfx::ElideFilename(download_->GetFileNameToReportUser(),
-                                    font_, kTextWidth);
+      filename = ui::ElideFilename(download_->GetFileNameToReportUser(),
+                                   font_, kTextWidth);
     } else {
       // First, Calculate the download status opening string width.
       string16 status_string =
@@ -617,14 +618,14 @@
       int status_string_width = font_.GetStringWidth(status_string);
       // Then, elide the file name.
       string16 filename_string =
-          gfx::ElideFilename(download_->GetFileNameToReportUser(), font_,
-                             kTextWidth - status_string_width);
+          ui::ElideFilename(download_->GetFileNameToReportUser(), font_,
+                            kTextWidth - status_string_width);
       // Last, concat the whole string.
       filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING,
                                             filename_string);
     }
 
-    int mirrored_x = MirroredXWithWidthInsideView(
+    int mirrored_x = GetMirroredXWithWidthInView(
         download_util::kSmallProgressIconSize, kTextWidth);
     SkColor file_name_color = GetThemeProvider()->GetColor(
         BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
@@ -633,7 +634,7 @@
                                       (box_height_ - font_.GetHeight()) / 2);
 
     // Draw the file's name.
-    canvas->DrawStringInt(UTF16ToWide(filename), font_,
+    canvas->DrawStringInt(filename, font_,
                           IsEnabled() ? file_name_color :
                                         kFileNameDisabledColor,
                           mirrored_x, y, kTextWidth, font_.GetHeight());
@@ -666,7 +667,7 @@
     }
 
     // Draw the icon image.
-    int mirrored_x = MirroredXWithWidthInsideView(
+    int mirrored_x = GetMirroredXWithWidthInView(
         download_util::kSmallProgressIconOffset, icon->width());
     if (IsEnabled()) {
       canvas->DrawBitmapInt(*icon, mirrored_x,
@@ -875,8 +876,7 @@
   if (IsDangerousMode())
     return true;
 
-  if (e.GetKeyCode() == app::VKEY_SPACE ||
-      e.GetKeyCode() == app::VKEY_RETURN) {
+  if (e.key_code() == ui::VKEY_SPACE || e.key_code() == ui::VKEY_RETURN) {
     OpenDownload();
     return true;
   }
@@ -960,7 +960,7 @@
 void DownloadItemView::OnExtractIconComplete(IconManager::Handle handle,
                                              SkBitmap* icon_bitmap) {
   if (icon_bitmap)
-    GetParent()->SchedulePaint();
+    parent()->SchedulePaint();
 }
 
 void DownloadItemView::LoadIcon() {
@@ -1060,15 +1060,15 @@
 }
 
 void DownloadItemView::UpdateAccessibleName() {
-  std::wstring current_name;
+  string16 current_name;
   GetAccessibleName(&current_name);
 
-  std::wstring new_name;
+  string16 new_name;
   if (download_->safety_state() == DownloadItem::DANGEROUS) {
-    new_name = dangerous_download_label_->GetText();
+    new_name = WideToUTF16Hack(dangerous_download_label_->GetText());
   } else {
-    new_name = status_text_ + L" " +
-        download_->GetFileNameToReportUser().ToWStringHack();
+    new_name = WideToUTF16Hack(status_text_) + char16(' ') +
+        WideToUTF16Hack(download_->GetFileNameToReportUser().ToWStringHack());
   }
 
   // If the name has changed, call SetAccessibleName and notify
diff --git a/chrome/browser/ui/views/download_item_view.h b/chrome/browser/ui/views/download_item_view.h
index c2beb3c..2bdfafd 100644
--- a/chrome/browser/ui/views/download_item_view.h
+++ b/chrome/browser/ui/views/download_item_view.h
@@ -27,9 +27,9 @@
 #include "chrome/browser/download/download_item.h"
 #include "chrome/browser/download/download_manager.h"
 #include "chrome/browser/icon_manager.h"
-#include "gfx/font.h"
 #include "ui/base/animation/animation_delegate.h"
-#include "views/event.h"
+#include "ui/gfx/font.h"
+#include "views/events/event.h"
 #include "views/controls/button/button.h"
 #include "views/view.h"
 
diff --git a/chrome/browser/ui/views/download_shelf_view.cc b/chrome/browser/ui/views/download_shelf_view.cc
index c3a4ea3..fa2fc37 100644
--- a/chrome/browser/ui/views/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download_shelf_view.cc
@@ -1,13 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/download_shelf_view.h"
+#include "chrome/browser/ui/views/download_shelf_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/download/download_item.h"
@@ -19,10 +17,12 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/download_item_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/image_view.h"
@@ -116,7 +116,7 @@
   close_button_->SetImage(views::CustomButton::BS_PUSHED,
                           rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
   close_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
   UpdateButtonColors();
   AddChildView(close_button_);
 
diff --git a/chrome/browser/ui/views/download_shelf_view.h b/chrome/browser/ui/views/download_shelf_view.h
index e7c1253..8d9c1f0 100644
--- a/chrome/browser/ui/views/download_shelf_view.h
+++ b/chrome/browser/ui/views/download_shelf_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "chrome/browser/download/download_shelf.h"
-#include "chrome/browser/views/accessible_pane_view.h"
+#include "chrome/browser/ui/views/accessible_pane_view.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "views/controls/button/button.h"
 #include "views/controls/link.h"
diff --git a/chrome/browser/ui/views/download_started_animation_win.cc b/chrome/browser/ui/views/download_started_animation_win.cc
index cbcbc97..973eca2 100644
--- a/chrome/browser/ui/views/download_started_animation_win.cc
+++ b/chrome/browser/ui/views/download_started_animation_win.cc
@@ -4,14 +4,14 @@
 
 #include "chrome/browser/download/download_started_animation.h"
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/rect.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/linear_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/image_view.h"
 #include "views/widget/widget_win.h"
 
diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc
index 5a1c2ad..60e2f0b 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host.cc
@@ -1,17 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/dropdown_bar_host.h"
+#include "chrome/browser/ui/views/dropdown_bar_host.h"
 
-#include "app/keyboard_codes.h"
-#include "chrome/browser/ui/browser.h"
+#include <algorithm>
+
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/dropdown_bar_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "gfx/path.h"
-#include "gfx/scrollbar_size.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/scrollbar_size.h"
 #include "views/focus/external_focus_tracker.h"
 #include "views/focus/view_storage.h"
 #include "views/widget/widget.h"
@@ -19,7 +20,7 @@
 #if defined(OS_WIN)
 #include "base/win/scoped_gdi_object.h"
 #elif defined(OS_LINUX)
-#include "app/scoped_handle_gtk.h"
+#include "ui/base/gtk/scoped_handle_gtk.h"
 #endif
 
 namespace {
@@ -27,7 +28,7 @@
 #if defined(OS_WIN)
 typedef base::win::ScopedRegion ScopedPlatformRegion;
 #elif defined(OS_LINUX)
-typedef ScopedRegion ScopedPlatformRegion;
+typedef ui::ScopedRegion ScopedPlatformRegion;
 #endif
 
 }  // namespace
@@ -130,8 +131,8 @@
                                       views::View* focused_now) {
   // First we need to determine if one or both of the views passed in are child
   // views of our view.
-  bool our_view_before = focused_before && view_->IsParentOf(focused_before);
-  bool our_view_now = focused_now && view_->IsParentOf(focused_now);
+  bool our_view_before = focused_before && view_->Contains(focused_before);
+  bool our_view_now = focused_now && view_->Contains(focused_now);
 
   // When both our_view_before and our_view_now are false, it means focus is
   // changing hands elsewhere in the application (and we shouldn't do anything).
@@ -305,14 +306,14 @@
 
 void DropdownBarHost::RegisterAccelerators() {
   DCHECK(!esc_accel_target_registered_);
-  views::Accelerator escape(app::VKEY_ESCAPE, false, false, false);
+  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
   focus_manager_->RegisterAccelerator(escape, this);
   esc_accel_target_registered_ = true;
 }
 
 void DropdownBarHost::UnregisterAccelerators() {
   DCHECK(esc_accel_target_registered_);
-  views::Accelerator escape(app::VKEY_ESCAPE, false, false, false);
+  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
   focus_manager_->UnregisterAccelerator(escape, this);
   esc_accel_target_registered_ = false;
 }
diff --git a/chrome/browser/ui/views/dropdown_bar_host.h b/chrome/browser/ui/views/dropdown_bar_host.h
index d9f1d7b..5b9dabf 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.h
+++ b/chrome/browser/ui/views/dropdown_bar_host.h
@@ -8,9 +8,9 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/common/native_web_keyboard_event.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
 #include "ui/base/animation/animation_delegate.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/textfield/textfield.h"
 #include "views/focus/focus_manager.h"
 
diff --git a/chrome/browser/ui/views/dropdown_bar_host_gtk.cc b/chrome/browser/ui/views/dropdown_bar_host_gtk.cc
index 298ca75..61f53f8 100644
--- a/chrome/browser/ui/views/dropdown_bar_host_gtk.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host_gtk.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/dropdown_bar_host.h"
+#include "chrome/browser/ui/views/dropdown_bar_host.h"
 
 #include <gdk/gdkkeysyms.h>
 
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "views/widget/widget_gtk.h"
 #include "views/controls/textfield/textfield.h"
 
 #if defined(TOUCH_UI)
-#include "app/keyboard_code_conversion_gtk.h"
+#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
 #endif
 
 views::Widget* DropdownBarHost::CreateHost() {
@@ -37,15 +37,15 @@
   // Refactor and eliminate the dup code.
   NativeWebKeyboardEvent wke;
   wke.type = WebKit::WebInputEvent::KeyDown;
-  wke.windowsKeyCode = key_event.GetKeyCode();
+  wke.windowsKeyCode = key_event.key_code();
   wke.setKeyIdentifierFromWindowsKeyCode();
 
   wke.text[0] = wke.unmodifiedText[0] =
     static_cast<unsigned short>(gdk_keyval_to_unicode(
-          app::GdkKeyCodeForWindowsKeyCode(key_event.GetKeyCode(),
+          ui::GdkKeyCodeForWindowsKeyCode(key_event.key_code(),
               key_event.IsShiftDown() ^ key_event.IsCapsLockDown())));
   return wke;
 #else
-  return NativeWebKeyboardEvent(key_event.native_event());
+  return NativeWebKeyboardEvent(&key_event.native_event()->key);
 #endif
 }
diff --git a/chrome/browser/ui/views/dropdown_bar_host_win.cc b/chrome/browser/ui/views/dropdown_bar_host_win.cc
index df55449..ef25f14 100644
--- a/chrome/browser/ui/views/dropdown_bar_host_win.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host_win.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/dropdown_bar_host.h"
+#include "chrome/browser/ui/views/dropdown_bar_host.h"
 
-#include "app/keyboard_code_conversion_win.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "ui/base/keycodes/keyboard_code_conversion_win.h"
 #include "views/controls/scrollbar/native_scroll_bar.h"
 #include "views/widget/widget_win.h"
 
@@ -17,9 +17,9 @@
      const TabContents* contents,
      const views::KeyEvent& key_event) {
   HWND hwnd = contents->GetContentNativeView();
-  WORD key = WindowsKeyCodeForKeyboardCode(key_event.GetKeyCode());
+  WORD key = WindowsKeyCodeForKeyboardCode(key_event.key_code());
 
-  return NativeWebKeyboardEvent(hwnd, key_event.message(), key, 0);
+  return NativeWebKeyboardEvent(hwnd, key_event.native_event().message, key, 0);
 }
 
 views::Widget* DropdownBarHost::CreateHost() {
diff --git a/chrome/browser/ui/views/edit_search_engine_dialog.cc b/chrome/browser/ui/views/edit_search_engine_dialog.cc
index e699e97..e7f48f2 100644
--- a/chrome/browser/ui/views/edit_search_engine_dialog.cc
+++ b/chrome/browser/ui/views/edit_search_engine_dialog.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/edit_search_engine_dialog.h"
+#include "chrome/browser/ui/views/edit_search_engine_dialog.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -15,11 +13,13 @@
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/label.h"
 #include "views/controls/image_view.h"
 #include "views/controls/table/table_view.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 using views::GridLayout;
@@ -142,12 +142,12 @@
 
   UpdateImageViews();
 
-  const int related_x = kRelatedControlHorizontalSpacing;
-  const int related_y = kRelatedControlVerticalSpacing;
-  const int unrelated_y = kUnrelatedControlVerticalSpacing;
+  const int related_x = views::kRelatedControlHorizontalSpacing;
+  const int related_y = views::kRelatedControlVerticalSpacing;
+  const int unrelated_y = views::kUnrelatedControlVerticalSpacing;
 
   // View and GridLayout take care of deleting GridLayout for us.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   // Define the structure of the layout.
diff --git a/chrome/browser/ui/views/event_utils.cc b/chrome/browser/ui/views/event_utils.cc
index 06b9f0d..6e13947 100644
--- a/chrome/browser/ui/views/event_utils.cc
+++ b/chrome/browser/ui/views/event_utils.cc
@@ -1,27 +1,23 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/event_utils.h"
+#include "chrome/browser/ui/views/event_utils.h"
 
-#include "views/event.h"
+#include "chrome/browser/disposition_utils.h"
+#include "views/events/event.h"
 
 using views::Event;
 
 namespace event_utils {
 
 WindowOpenDisposition DispositionFromEventFlags(int event_flags) {
-  if (((event_flags & Event::EF_MIDDLE_BUTTON_DOWN) ==
-          Event::EF_MIDDLE_BUTTON_DOWN) ||
-      ((event_flags & Event::EF_CONTROL_DOWN) ==
-          Event::EF_CONTROL_DOWN)) {
-    return ((event_flags & Event::EF_SHIFT_DOWN) ==  Event::EF_SHIFT_DOWN) ?
-        NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
-  }
-
-  if ((event_flags & Event::EF_SHIFT_DOWN) == Event::EF_SHIFT_DOWN)
-    return NEW_WINDOW;
-  return false /*event.IsAltDown()*/ ? SAVE_TO_DISK : CURRENT_TAB;
+  return disposition_utils::DispositionFromClick(
+      (event_flags & ui::EF_MIDDLE_BUTTON_DOWN) != 0,
+      (event_flags & ui::EF_ALT_DOWN) != 0,
+      (event_flags & ui::EF_CONTROL_DOWN) != 0,
+      false /* meta_key */,
+      (event_flags & ui::EF_SHIFT_DOWN) != 0);
 }
 
 bool IsPossibleDispositionEvent(const views::MouseEvent& event) {
diff --git a/chrome/browser/ui/views/extensions/browser_action_drag_data.cc b/chrome/browser/ui/views/extensions/browser_action_drag_data.cc
index 565c89c..a520ebc 100644
--- a/chrome/browser/ui/views/extensions/browser_action_drag_data.cc
+++ b/chrome/browser/ui/views/extensions/browser_action_drag_data.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/extensions/browser_action_drag_data.h"
+#include "chrome/browser/ui/views/extensions/browser_action_drag_data.h"
 
 #include "base/logging.h"
 #include "base/pickle.h"
@@ -27,14 +27,14 @@
 
 #if defined(TOOLKIT_VIEWS)
 void BrowserActionDragData::Write(
-    Profile* profile, OSExchangeData* data) const {
+    Profile* profile, ui::OSExchangeData* data) const {
   DCHECK(data);
   Pickle data_pickle;
   WriteToPickle(profile, &data_pickle);
   data->SetPickledData(GetBrowserActionCustomFormat(), data_pickle);
 }
 
-bool BrowserActionDragData::Read(const OSExchangeData& data) {
+bool BrowserActionDragData::Read(const ui::OSExchangeData& data) {
   if (!data.HasCustomFormat(GetBrowserActionCustomFormat()))
     return false;
 
@@ -49,14 +49,14 @@
 }
 
 // static
-OSExchangeData::CustomFormat
+ui::OSExchangeData::CustomFormat
     BrowserActionDragData::GetBrowserActionCustomFormat() {
-  static OSExchangeData::CustomFormat format;
+  static ui::OSExchangeData::CustomFormat format;
   static bool format_valid = false;
 
   if (!format_valid) {
     format_valid = true;
-    format = OSExchangeData::RegisterCustomFormat(
+    format = ui::OSExchangeData::RegisterCustomFormat(
         BrowserActionDragData::kClipboardFormatString);
   }
   return format;
diff --git a/chrome/browser/ui/views/extensions/browser_action_drag_data.h b/chrome/browser/ui/views/extensions/browser_action_drag_data.h
index 7168025..ee729b3 100644
--- a/chrome/browser/ui/views/extensions/browser_action_drag_data.h
+++ b/chrome/browser/ui/views/extensions/browser_action_drag_data.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "app/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
 #endif
 
 class BrowserActionButton;
@@ -32,13 +32,13 @@
   bool IsFromProfile(Profile* profile) const;
 
 #if defined(TOOLKIT_VIEWS)
-  void Write(Profile* profile, OSExchangeData* data) const;
+  void Write(Profile* profile, ui::OSExchangeData* data) const;
 
   // Restores this data from the clipboard, returning true on success.
-  bool Read(const OSExchangeData& data);
+  bool Read(const ui::OSExchangeData& data);
 
   // Returns the Custom Format this class supports (for Browser Actions).
-  static OSExchangeData::CustomFormat GetBrowserActionCustomFormat();
+  static ui::OSExchangeData::CustomFormat GetBrowserActionCustomFormat();
 #endif
 
  private:
diff --git a/chrome/browser/ui/views/extensions/browser_action_drag_data_unittest.cc b/chrome/browser/ui/views/extensions/browser_action_drag_data_unittest.cc
index 226591f..0774caf 100644
--- a/chrome/browser/ui/views/extensions/browser_action_drag_data_unittest.cc
+++ b/chrome/browser/ui/views/extensions/browser_action_drag_data_unittest.cc
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/os_exchange_data.h"
-#include "app/os_exchange_data_provider_win.h"
 #include "base/pickle.h"
-#include "chrome/browser/views/extensions/browser_action_drag_data.h"
+#include "chrome/browser/ui/views/extensions/browser_action_drag_data.h"
 #include "chrome/test/testing_profile.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
 
 namespace {
 
-OSExchangeData::Provider* CloneProvider(const OSExchangeData& data) {
-  return new OSExchangeDataProviderWin(
-      OSExchangeDataProviderWin::GetIDataObject(data));
+ui::OSExchangeData::Provider* CloneProvider(const ui::OSExchangeData& data) {
+  return new ui::OSExchangeDataProviderWin(
+      ui::OSExchangeDataProviderWin::GetIDataObject(data));
 }
 
 }  // namespace
@@ -25,12 +25,12 @@
   TestingProfile profile;
   profile.SetID(L"id");
 
-  OSExchangeData data;
+  ui::OSExchangeData data;
   data.SetURL(GURL("http://www.google.com"), L"Title");
 
   // We only support our format, so this should not succeed.
   BrowserActionDragData drag_data;
-  EXPECT_FALSE(drag_data.Read(OSExchangeData(CloneProvider(data))));
+  EXPECT_FALSE(drag_data.Read(ui::OSExchangeData(CloneProvider(data))));
 }
 
 TEST_F(BrowserActionDragDataTest, BrowserActionDragDataFormat) {
@@ -44,12 +44,12 @@
   pickle.WriteString(extension_id);
   pickle.WriteInt(42);
 
-  OSExchangeData data;
+  ui::OSExchangeData data;
   data.SetPickledData(BrowserActionDragData::GetBrowserActionCustomFormat(),
                       pickle);
 
   BrowserActionDragData drag_data;
-  EXPECT_TRUE(drag_data.Read(OSExchangeData(CloneProvider(data))));
+  EXPECT_TRUE(drag_data.Read(ui::OSExchangeData(CloneProvider(data))));
   ASSERT_TRUE(drag_data.IsFromProfile(profile.GetOriginalProfile()));
   ASSERT_STREQ(extension_id.c_str(), drag_data.id().c_str());
   ASSERT_EQ(42, drag_data.index());
diff --git a/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.cc b/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.cc
index 509188f..549017d 100644
--- a/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.cc
+++ b/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/extensions/browser_action_overflow_menu_controller.h"
+#include "chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h"
 
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/extensions/extension_context_menu_model.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/browser_actions_container.h"
-#include "chrome/browser/views/extensions/browser_action_drag_data.h"
+#include "chrome/browser/ui/views/browser_actions_container.h"
+#include "chrome/browser/ui/views/extensions/browser_action_drag_data.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_action.h"
-#include "gfx/canvas_skia.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/menu/menu_item_view.h"
 #include "views/controls/menu/menu_2.h"
 
@@ -58,8 +58,7 @@
                                                   bool for_drop) {
   for_drop_ = for_drop;
 
-  gfx::Rect bounds = menu_button_->GetBounds(
-      views::View::IGNORE_MIRRORING_TRANSFORMATION);
+  gfx::Rect bounds = menu_button_->bounds();
   gfx::Point screen_loc;
   views::View::ConvertPointToScreen(menu_button_, &screen_loc);
   bounds.set_x(screen_loc.x());
@@ -93,8 +92,13 @@
     int id,
     const gfx::Point& p,
     bool is_mouse_gesture) {
+  const Extension* extension =
+      (*views_)[start_index_ + id - 1]->button()->extension();
+  if (!extension->ShowConfigureContextMenus())
+    return false;
+
   context_menu_contents_ = new ExtensionContextMenuModel(
-      (*views_)[start_index_ + id - 1]->button()->extension(),
+      extension,
       owner_->browser(),
       owner_);
   context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get()));
@@ -144,14 +148,14 @@
   // (because we don't shrink the BrowserActionContainer when you do this).
   if ((item->GetCommand() == 0) && (*position == DROP_BEFORE)) {
     BrowserActionDragData drop_data;
-    if (!drop_data.Read(event.GetData()))
-      return DragDropTypes::DRAG_NONE;
+    if (!drop_data.Read(event.data()))
+      return ui::DragDropTypes::DRAG_NONE;
 
     if (drop_data.index() < owner_->VisibleBrowserActions())
-      return DragDropTypes::DRAG_NONE;
+      return ui::DragDropTypes::DRAG_NONE;
   }
 
-  return DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 int BrowserActionOverflowMenuController::OnPerformDrop(
@@ -159,8 +163,8 @@
     DropPosition position,
     const views::DropTargetEvent& event) {
   BrowserActionDragData drop_data;
-  if (!drop_data.Read(event.GetData()))
-    return DragDropTypes::DRAG_NONE;
+  if (!drop_data.Read(event.data()))
+    return ui::DragDropTypes::DRAG_NONE;
 
   size_t drop_index;
   ViewForId(menu->GetCommand(), &drop_index);
@@ -175,7 +179,7 @@
 
   if (for_drop_)
     delete this;
-  return DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 bool BrowserActionOverflowMenuController::CanDrag(views::MenuItemView* menu) {
@@ -194,7 +198,7 @@
 
 int BrowserActionOverflowMenuController::GetDragOperations(
     views::MenuItemView* sender) {
-  return DragDropTypes::DRAG_MOVE;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 BrowserActionView* BrowserActionOverflowMenuController::ViewForId(
diff --git a/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h b/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h
index 06f8823..7d0fa1e 100644
--- a/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h
+++ b/chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h
@@ -58,9 +58,9 @@
   virtual bool GetDropFormats(
       views::MenuItemView* menu,
       int* formats,
-      std::set<OSExchangeData::CustomFormat>* custom_formats);
+      std::set<ui::OSExchangeData::CustomFormat>* custom_formats);
   virtual bool AreDropTypesRequired(views::MenuItemView* menu);
-  virtual bool CanDrop(views::MenuItemView* menu, const OSExchangeData& data);
+  virtual bool CanDrop(views::MenuItemView* menu, const ui::OSExchangeData& data);
   virtual int GetDropOperation(views::MenuItemView* item,
                                const views::DropTargetEvent& event,
                                DropPosition* position);
@@ -70,7 +70,7 @@
   // These three drag functions offer support for dragging icons out of the
   // overflow menu.
   virtual bool CanDrag(views::MenuItemView* menu);
-  virtual void WriteDragData(views::MenuItemView* sender, OSExchangeData* data);
+  virtual void WriteDragData(views::MenuItemView* sender, ui::OSExchangeData* data);
   virtual int GetDragOperations(views::MenuItemView* sender);
 
  private:
diff --git a/chrome/browser/ui/views/extensions/extension_install_prompt.cc b/chrome/browser/ui/views/extensions/extension_install_prompt.cc
index ea32328..4cf5954 100644
--- a/chrome/browser/ui/views/extensions/extension_install_prompt.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_prompt.cc
@@ -1,22 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/extensions/extension.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/link.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/view.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
diff --git a/chrome/browser/ui/views/extensions/extension_install_prompt2.cc b/chrome/browser/ui/views/extensions/extension_install_prompt2.cc
index 0a4e2d6..92069af 100644
--- a/chrome/browser/ui/views/extensions/extension_install_prompt2.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_prompt2.cc
@@ -1,19 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/browser/views/window.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/view.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
@@ -223,16 +223,16 @@
   height += heading_->GetHeightForWidth(right_column_width_);
 
   if (permission_box_) {
-    height += kRelatedControlVerticalSpacing;
+    height += views::kRelatedControlVerticalSpacing;
     height += will_have_access_to_->GetHeightForWidth(right_column_width_);
 
-    height += kRelatedControlVerticalSpacing;
+    height += views::kRelatedControlVerticalSpacing;
     height += kPermissionBoxBorderWidth * 2;
     height += kPermissionBoxVerticalPadding * 2;
 
     for (size_t i = 0; i < permissions_.size(); ++i) {
       if (i > 0)
-        height += kRelatedControlVerticalSpacing;
+        height += views::kRelatedControlVerticalSpacing;
       height += permissions_[0]->GetHeightForWidth(kPermissionLabelWidth);
     }
   }
@@ -262,13 +262,13 @@
   heading_->SetY(y);
   y += heading_->height();
 
-  y += kRelatedControlVerticalSpacing;
+  y += views::kRelatedControlVerticalSpacing;
   will_have_access_to_->SizeToFit(right_column_width_);
   will_have_access_to_->SetX(x);
   will_have_access_to_->SetY(y);
   y += will_have_access_to_->height();
 
-  y += kRelatedControlVerticalSpacing;
+  y += views::kRelatedControlVerticalSpacing;
   permission_box_->SetX(x);
   permission_box_->SetY(y);
 
@@ -281,7 +281,7 @@
 
   for (size_t i = 0; i < permissions_.size(); ++i) {
     if (i > 0) {
-      label_y += kRelatedControlVerticalSpacing;
+      label_y += views::kRelatedControlVerticalSpacing;
       permission_box_height += kPanelVertMargin;
     }
 
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble.cc
index b2e0697..148aedd 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble.cc
@@ -1,21 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/extensions/extension_installed_bubble.h"
+#include "chrome/browser/ui/views/extensions/extension_installed_bubble.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include <algorithm>
+
 #include "base/i18n/rtl.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/browser_actions_container.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
-#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/browser/ui/views/browser_actions_container.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/notification_details.h"
@@ -23,10 +23,12 @@
 #include "chrome/common/notification_type.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/view.h"
 
 namespace {
@@ -60,6 +62,18 @@
 
 }  // namespace
 
+namespace browser {
+
+void ShowExtensionInstalledBubble(
+    const Extension* extension,
+    Browser* browser,
+    SkBitmap icon,
+    Profile* profile) {
+  ExtensionInstalledBubble::Show(extension, browser, icon);
+}
+
+} // namespace browser
+
 // InstalledBubbleContent is the content view which is placed in the
 // ExtensionInstalledBubble. It displays the install icon and explanatory
 // text about the installed extension.
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble.h b/chrome/browser/ui/views/extensions/extension_installed_bubble.h
index bbe12f5..ff15b6d 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble.h
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/ref_counted.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc
index 0271fa4..15a6a26 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.cc
+++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/extensions/extension_popup.h"
+#include "chrome/browser/ui/views/extensions/extension_popup.h"
 
 #include <vector>
 
@@ -14,15 +14,12 @@
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/window_sizer.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "third_party/skia/include/core/SkColor.h"
 #include "views/widget/root_view.h"
 #include "views/window/window.h"
 
@@ -38,10 +35,9 @@
 using std::vector;
 using views::Widget;
 
-// The minimum, and default maximum dimensions of the popup.
+// The minimum/maximum dimensions of the popup.
 // The minimum is just a little larger than the size of the button itself.
-// The default maximum is an arbitrary number that should be smaller than most
-// screens.
+// The maximum is an arbitrary number that should be smaller than most screens.
 const int ExtensionPopup::kMinWidth = 25;
 const int ExtensionPopup::kMinHeight = 25;
 const int ExtensionPopup::kMaxWidth = 800;
@@ -60,31 +56,20 @@
                                views::Widget* frame,
                                const gfx::Rect& relative_to,
                                BubbleBorder::ArrowLocation arrow_location,
-                               bool activate_on_show,
                                bool inspect_with_devtools,
-                               PopupChrome chrome,
                                Observer* observer)
     : BrowserBubble(host->view(),
                     frame,
-                    gfx::Point(),
-                    RECTANGLE_CHROME == chrome),  // If no bubble chrome is to
-                                                  // be displayed, then enable a
-                                                  // drop-shadow on the bubble
-                                                  // widget.
+                    gfx::Point()),
       relative_to_(relative_to),
       extension_host_(host),
-      activate_on_show_(activate_on_show),
       inspect_with_devtools_(inspect_with_devtools),
       close_on_lost_focus_(true),
       closing_(false),
       border_widget_(NULL),
       border_(NULL),
       border_view_(NULL),
-      popup_chrome_(chrome),
-      max_size_(kMaxWidth, kMaxHeight),
-      observer_(observer),
-      anchor_position_(arrow_location),
-      instance_lifetime_(new InternalRefCounter()){
+      observer_(observer) {
   AddRef();  // Balanced in Close();
   set_delegate(this);
   host->view()->SetContainer(this);
@@ -108,67 +93,47 @@
   relative_to_.set_origin(origin);
 
   // The bubble chrome requires a separate window, so construct it here.
-  if (BUBBLE_CHROME == popup_chrome_) {
-    gfx::NativeView native_window = frame->GetNativeView();
+  gfx::NativeView native_window = frame->GetNativeView();
 #if defined(OS_LINUX)
-    border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
-    static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
-    static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
+  border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
+  static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
+  static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
 #else
-    border_widget_ = Widget::CreatePopupWidget(Widget::Transparent,
-                                               Widget::NotAcceptEvents,
-                                               Widget::DeleteOnDestroy,
-                                               Widget::MirrorOriginInRTL);
+  border_widget_ = Widget::CreatePopupWidget(Widget::Transparent,
+                                             Widget::NotAcceptEvents,
+                                             Widget::DeleteOnDestroy,
+                                             Widget::MirrorOriginInRTL);
 #endif
-    border_widget_->Init(native_window, bounds());
+  border_widget_->Init(native_window, bounds());
 #if defined(OS_CHROMEOS)
-    {
-      vector<int> params;
-      params.push_back(0);  // don't show while screen is locked
-      chromeos::WmIpc::instance()->SetWindowType(
-          border_widget_->GetNativeView(),
-          chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
-          &params);
-    }
-#endif
-    border_ = new BubbleBorder(arrow_location);
-    border_view_ = new views::View;
-    border_view_->set_background(new BubbleBackground(border_));
-
-    border_view_->set_border(border_);
-    border_widget_->SetContentsView(border_view_);
-    // Ensure that the popup contents are always displayed ontop of the border
-    // widget.
-    border_widget_->MoveAbove(popup_);
-  } else {
-    // Otherwise simply set a black-border on the view containing the popup
-    // extension view.
-    views::Border* border = views::Border::CreateSolidBorder(kPopupBorderWidth,
-                                                             SK_ColorBLACK);
-    view()->set_border(border);
+  {
+    vector<int> params;
+    params.push_back(0);  // don't show while screen is locked
+    chromeos::WmIpc::instance()->SetWindowType(
+        border_widget_->GetNativeView(),
+        chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
+        &params);
   }
+#endif
+  border_ = new BubbleBorder(arrow_location);
+  border_view_ = new views::View;
+  border_view_->set_background(new BubbleBackground(border_));
+
+  border_view_->set_border(border_);
+  border_widget_->SetContentsView(border_view_);
+  // Ensure that the popup contents are always displayed ontop of the border
+  // widget.
+  border_widget_->MoveAbove(popup_);
 }
 
 ExtensionPopup::~ExtensionPopup() {
   // The widget is set to delete on destroy, so no leak here.
-  if (border_widget_)
-    border_widget_->Close();
-}
-
-void ExtensionPopup::SetArrowPosition(
-    BubbleBorder::ArrowLocation arrow_location) {
-  DCHECK_NE(BubbleBorder::NONE, arrow_location) <<
-    "Extension popups must be positioned relative to an arrow.";
-
-  anchor_position_ = arrow_location;
-  if (border_)
-    border_->set_arrow_location(anchor_position_);
+  border_widget_->Close();
 }
 
 void ExtensionPopup::Hide() {
   BrowserBubble::Hide();
-  if (border_widget_)
-    border_widget_->Hide();
+  border_widget_->Hide();
 }
 
 void ExtensionPopup::Show(bool activate) {
@@ -176,46 +141,43 @@
     return;
 
 #if defined(OS_WIN)
-  if (frame_->GetWindow())
-    frame_->GetWindow()->DisableInactiveRendering();
+  frame_->GetWindow()->DisableInactiveRendering();
 #endif
 
   ResizeToView();
 
   // Show the border first, then the popup overlaid on top.
-  if (border_widget_)
-    border_widget_->Show();
+  border_widget_->Show();
   BrowserBubble::Show(activate);
 }
 
 void ExtensionPopup::ResizeToView() {
-  if (observer_)
-    observer_->ExtensionPopupResized(this);
+  // We'll be sizing ourselves to this size shortly, but wait until we
+  // know our position to do it.
+  gfx::Size new_size = view()->size();
 
-  gfx::Rect rect = GetOuterBounds();
+  // The rounded corners cut off more of the view than the border insets claim.
+  // Since we can't clip the ExtensionView's corners, we need to increase the
+  // inset by half the corner radius as well as lying about the size of the
+  // contents size to compensate.
+  int corner_inset = BubbleBorder::GetCornerRadius() / 2;
+  gfx::Size adjusted_size = new_size;
+  adjusted_size.Enlarge(2 * corner_inset, 2 * corner_inset);
+  gfx::Rect rect = border_->GetBounds(relative_to_, adjusted_size);
+  border_widget_->SetBounds(rect);
 
+  // Now calculate the inner bounds.  This is a bit more convoluted than
+  // it should be because BrowserBubble coordinates are in Browser coordinates
+  // while |rect| is in screen coordinates.
+  gfx::Insets border_insets;
+  border_->GetInsets(&border_insets);
   gfx::Point origin = rect.origin();
   views::View::ConvertPointToView(NULL, frame_->GetRootView(), &origin);
 
-  if (border_widget_) {
-    // Set the bubble-chrome widget according to the outer bounds of the entire
-    // popup.
-    border_widget_->SetBounds(rect);
+  origin.set_x(origin.x() + border_insets.left() + corner_inset);
+  origin.set_y(origin.y() + border_insets.top() + corner_inset);
 
-    // Now calculate the inner bounds.  This is a bit more convoluted than
-    // it should be because BrowserBubble coordinates are in Browser coordinates
-    // while |rect| is in screen coordinates.
-    gfx::Insets border_insets;
-    border_->GetInsets(&border_insets);
-
-    origin.set_x(origin.x() + border_insets.left() + kPopupBubbleCornerRadius);
-    origin.set_y(origin.y() + border_insets.top() + kPopupBubbleCornerRadius);
-
-    gfx::Size new_size = view()->size();
-    SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
-  } else {
-    SetBounds(origin.x(), origin.y(), rect.width(), rect.height());
-  }
+  SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
 }
 
 void ExtensionPopup::BubbleBrowserWindowMoved(BrowserBubble* bubble) {
@@ -259,7 +221,7 @@
       // Once we receive did stop loading, the content will be complete and
       // the width will have been computed.  Now it's safe to show.
       if (extension_host_.get() == Details<ExtensionHost>(details).ptr()) {
-        Show(activate_on_show_);
+        Show(true);
 
         if (inspect_with_devtools_) {
           // Listen for the the devtools window closing.
@@ -299,121 +261,38 @@
 void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) {
   // Constrain the size to popup min/max.
   gfx::Size sz = view->GetPreferredSize();
-
-  // Enforce that the popup never resizes to larger than the working monitor
-  // bounds.
-  scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
-      WindowSizer::CreateDefaultMonitorInfoProvider());
-  gfx::Rect monitor_bounds(
-      monitor_provider->GetMonitorWorkAreaMatching(relative_to_));
-
-  int max_width = std::min(max_size_.width(), monitor_bounds.width());
-  int max_height = std::min(max_size_.height(), monitor_bounds.height());
   view->SetBounds(view->x(), view->y(),
-      std::max(kMinWidth, std::min(max_width, sz.width())),
-      std::max(kMinHeight, std::min(max_height, sz.height())));
-
-  // If popup_chrome_ == RECTANGLE_CHROME, the border is drawn in the client
-  // area of the ExtensionView, rather than in a window which sits behind it.
-  // In this case, the actual size of the view must be enlarged so that the
-  // web contents portion of the view gets its full PreferredSize area.
-  if (view->border()) {
-    gfx::Insets border_insets;
-    view->border()->GetInsets(&border_insets);
-
-    gfx::Rect bounds(view->bounds());
-    gfx::Size size(bounds.size());
-    size.Enlarge(border_insets.width(), border_insets.height());
-    view->SetBounds(bounds.x(), bounds.y(), size.width(), size.height());
-  }
+      std::max(kMinWidth, std::min(kMaxWidth, sz.width())),
+      std::max(kMinHeight, std::min(kMaxHeight, sz.height())));
 
   ResizeToView();
 }
 
-gfx::Rect ExtensionPopup::GetOuterBounds() const {
-  gfx::Rect relative_rect = relative_to_;
-  gfx::Point origin = relative_rect.origin();
-  views::View::ConvertPointToScreen(frame_->GetRootView(), &origin);
-  relative_rect.set_origin(origin);
-
-  gfx::Size contents_size = view()->size();
-
-  // If the popup has a bubble-chrome, then let the BubbleBorder compute
-  // the bounds.
-  if (BUBBLE_CHROME == popup_chrome_) {
-    // The rounded corners cut off more of the view than the border insets
-    // claim. Since we can't clip the ExtensionView's corners, we need to
-    // increase the inset by half the corner radius as well as lying about the
-    // size of the contents size to compensate.
-    contents_size.Enlarge(2 * kPopupBubbleCornerRadius,
-                          2 * kPopupBubbleCornerRadius);
-    return border_->GetBounds(relative_rect, contents_size);
-  }
-
-  // Position the bounds according to the location of the |anchor_position_|.
-  int y;
-  if (BubbleBorder::is_arrow_on_top(anchor_position_))
-    y = relative_rect.bottom();
-  else
-    y = relative_rect.y() - contents_size.height();
-
-  int x;
-  if (BubbleBorder::is_arrow_on_left(anchor_position_))
-    x = relative_rect.x();
-  else
-    // Note that if the arrow is on the right, that the x position of the popup
-    // is assigned so that the rightmost edge of the popup is aligned with the
-    // rightmost edge of the relative region.
-    x = relative_rect.right() - contents_size.width();
-
-  return gfx::Rect(x, y, contents_size.width(), contents_size.height());
-}
-
 // static
 ExtensionPopup* ExtensionPopup::Show(
     const GURL& url,
     Browser* browser,
-    Profile* profile,
-    gfx::NativeWindow frame_window,
     const gfx::Rect& relative_to,
     BubbleBorder::ArrowLocation arrow_location,
-    bool activate_on_show,
     bool inspect_with_devtools,
-    PopupChrome chrome,
     Observer* observer) {
-  DCHECK(profile);
-  DCHECK(frame_window);
-  ExtensionProcessManager* manager = profile->GetExtensionProcessManager();
+  ExtensionProcessManager* manager =
+      browser->profile()->GetExtensionProcessManager();
   DCHECK(manager);
   if (!manager)
     return NULL;
 
-  // If no Browser instance was given, attempt to look up one matching the given
-  // profile.
-  if (!browser)
-    browser = BrowserList::FindBrowserWithProfile(profile);
-
-  Widget* frame_widget = Widget::GetWidgetFromNativeWindow(frame_window);
-  DCHECK(frame_widget);
-  if (!frame_widget)
-    return NULL;
-
   ExtensionHost* host = manager->CreatePopup(url, browser);
-  if (observer)
-    observer->ExtensionHostCreated(host);
-
-  ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to,
-                                             arrow_location, activate_on_show,
-                                             inspect_with_devtools, chrome,
-                                             observer);
-
-  if (observer)
-    observer->ExtensionPopupCreated(popup);
+  views::Widget* frame = BrowserView::GetBrowserViewForNativeWindow(
+      browser->window()->GetNativeHandle())->GetWidget();
+  ExtensionPopup* popup = new ExtensionPopup(host, frame, relative_to,
+                                             arrow_location,
+                                             inspect_with_devtools, observer);
 
   // If the host had somehow finished loading, then we'd miss the notification
   // and not show.  This seems to happen in single-process mode.
   if (host->did_stop_loading())
-    popup->Show(activate_on_show);
+    popup->Show(true);
 
   return popup;
 }
@@ -429,18 +308,3 @@
 
   Release();  // Balanced in ctor.
 }
-
-void ExtensionPopup::Release() {
-  bool final_release = instance_lifetime_->HasOneRef();
-  instance_lifetime_->Release();
-  if (final_release) {
-    DCHECK(closing_) << "ExtensionPopup to be destroyed before being closed.";
-    ExtensionPopup::Observer* observer = observer_;
-    delete this;
-
-    // |this| is passed only as a 'cookie'. The observer API explicitly takes a
-    // void* argument to emphasize this.
-    if (observer)
-      observer->ExtensionPopupClosed(this);
-  }
-}
diff --git a/chrome/browser/ui/views/extensions/extension_popup.h b/chrome/browser/ui/views/extensions/extension_popup.h
index 0fc6f92..2b5870d 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.h
+++ b/chrome/browser/ui/views/extensions/extension_popup.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_POPUP_H_
 #pragma once
 
+#include "base/ref_counted.h"
 #include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/views/browser_bubble.h"
-#include "chrome/browser/views/extensions/extension_view.h"
-#include "chrome/browser/views/bubble_border.h"
+#include "chrome/browser/ui/views/browser_bubble.h"
+#include "chrome/browser/ui/views/bubble_border.h"
+#include "chrome/browser/ui/views/extensions/extension_view.h"
 #include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
 #include "googleurl/src/gurl.h"
 
 
@@ -26,8 +25,9 @@
 
 class ExtensionPopup : public BrowserBubble,
                        public BrowserBubble::Delegate,
+                       public ExtensionView::Container,
                        public NotificationObserver,
-                       public ExtensionView::Container {
+                       public base::RefCounted<ExtensionPopup> {
  public:
   // Observer to ExtensionPopup events.
   class Observer {
@@ -36,32 +36,6 @@
     // is ref-counted, and thus will be released shortly after
     // making this delegate call.
     virtual void ExtensionPopupIsClosing(ExtensionPopup* popup) {}
-
-    // Called after the ExtensionPopup has been closed and deleted.
-    // |popup_token| is the address of the deleted ExtensionPopup.
-    virtual void ExtensionPopupClosed(void* popup_token) {}
-
-    // Called when the ExtensionHost is first created for the pop-up view.
-    // Note that this is invoked BEFORE the ExtensionPopup is created, and can
-    // be used to provide extra configuration of the host before it is pushed
-    // into the popup.  An example use is for automation resource routing in
-    // Chrome-Frame.  See extension_popup_api.cc.
-    virtual void ExtensionHostCreated(ExtensionHost* host) {}
-
-    // Called immediately after a popup is created, but before the hosted
-    // extension has loaded and before the popup has been displayed.  Use to
-    // finalize configuration of |popup|.
-    virtual void ExtensionPopupCreated(ExtensionPopup* popup) {}
-
-    // Called when the ExtensionPopup is resized.  Note that the popup may have
-    // an empty bounds, if a popup is repositioned before the hosted content
-    // has loaded.
-    virtual void ExtensionPopupResized(ExtensionPopup* popup) {}
-  };
-
-  enum PopupChrome {
-    BUBBLE_CHROME,
-    RECTANGLE_CHROME
   };
 
   virtual ~ExtensionPopup();
@@ -70,46 +44,22 @@
   // screen coordinates.
   // |browser| is the browser to which the pop-up will be attached.  NULL is a
   // valid parameter for pop-ups not associated with a browser.
-  // |profile| is the user profile instance associated with the popup.  A
-  // non NULL value must be given.
-  // |frame_window| is the native window that hosts the view inside which the
-  // popup will be anchored.
   // The positioning of the pop-up is determined by |arrow_location| according
   // to the following logic:  The popup is anchored so that the corner indicated
   // by value of |arrow_location| remains fixed during popup resizes.
   // If |arrow_location| is BOTTOM_*, then the popup 'pops up', otherwise
   // the popup 'drops down'.
-  // Pass |activate_on_show| as true to activate the popup window.
   // Pass |inspect_with_devtools| as true to pin the popup open and show the
   // devtools window for it.
-  // The |chrome| argument controls the chrome that surrounds the pop-up.
-  // Passing BUBBLE_CHROME will give the pop-up a bubble-like appearance,
-  // including the arrow mentioned above.  Passing RECTANGLE_CHROME will give
-  // the popup a rectangular, black border with a drop-shadow with no arrow.
-  // The positioning of the popup is still governed by the arrow-location
-  // parameter.
-  //
   // The actual display of the popup is delayed until the page contents
   // finish loading in order to minimize UI flashing and resizing.
   static ExtensionPopup* Show(const GURL& url, Browser* browser,
-                              Profile* profile,
-                              gfx::NativeWindow frame_window,
                               const gfx::Rect& relative_to,
                               BubbleBorder::ArrowLocation arrow_location,
-                              bool activate_on_show,
                               bool inspect_with_devtools,
-                              PopupChrome chrome,
                               Observer* observer);
 
-  // Assigns the maximal width and height, respectively, to which the popup
-  // may expand.  If these routines are not called, the popup will resize to
-  // no larger than |kMaxWidth| x |kMaxHeight|.  Note that the popup will
-  // never expand to larger than the dimensions of the screen.
-  void set_max_width(int width) { max_size_.set_width(width); }
-  void set_max_height(int height) { max_size_.set_height(height); }
-
-  // Closes the ExtensionPopup (this will cause the delegate
-  // ExtensionPopupIsClosing and ExtensionPopupClosed to fire.
+  // Closes the ExtensionPopup.
   void Close();
 
   // Some clients wish to do their own custom focus change management. If this
@@ -121,18 +71,6 @@
 
   ExtensionHost* host() const { return extension_host_.get(); }
 
-  // Assigns the arrow location of the popup view, and updates the popup
-  // border widget, if necessary.
-  void SetArrowPosition(BubbleBorder::ArrowLocation arrow_location);
-  BubbleBorder::ArrowLocation arrow_position() const {
-    return anchor_position_;
-  }
-
-  // Gives the desired bounds (in screen coordinates) given the rect to point
-  // to and the size of the contained contents.  Includes all of the
-  // border-chrome surrounding the pop-up as well.
-  gfx::Rect GetOuterBounds() const;
-
   // BrowserBubble overrides.
   virtual void Hide();
   virtual void Show(bool activate);
@@ -155,18 +93,6 @@
   virtual void OnExtensionMouseLeave(ExtensionView* view) { }
   virtual void OnExtensionPreferredSizeChanged(ExtensionView* view);
 
-  // Export the refrence-counted interface required for use as template
-  // arguments for RefCounted.  ExtensionPopup does not inherit from RefCounted
-  // because it must override the behaviour of Release.
-  void AddRef() { instance_lifetime_->AddRef(); }
-  static bool ImplementsThreadSafeReferenceCounting() {
-    return InternalRefCounter::ImplementsThreadSafeReferenceCounting();
-  }
-
-  // Implements the standard RefCounted<T>::Release behaviour, except
-  // signals Observer::ExtensionPopupClosed after final release.
-  void Release();
-
   // The min/max height of popups.
   static const int kMinWidth;
   static const int kMinHeight;
@@ -178,9 +104,7 @@
                  views::Widget* frame,
                  const gfx::Rect& relative_to,
                  BubbleBorder::ArrowLocation arrow_location,
-                 bool activate_on_show,
                  bool inspect_with_devtools,
-                 PopupChrome chrome,
                  Observer* observer);
 
   // The area on the screen that the popup should be positioned relative to.
@@ -189,9 +113,6 @@
   // The contained host for the view.
   scoped_ptr<ExtensionHost> extension_host_;
 
-  // Flag used to indicate if the pop-up should be activated upon first display.
-  bool activate_on_show_;
-
   // Flag used to indicate if the pop-up should open a devtools window once
   // it is shown inspecting it.
   bool inspect_with_devtools_;
@@ -212,27 +133,9 @@
   BubbleBorder* border_;
   views::View* border_view_;
 
-  // The type of chrome associated with the popup window.
-  PopupChrome popup_chrome_;
-
-  // The maximal size to which the popup may expand.
-  gfx::Size max_size_;
-
   // The observer of this popup.
   Observer* observer_;
 
-  // A cached copy of the arrow-position for the bubble chrome.
-  // If a black-border was requested, we still need this value to determine
-  // the position of the pop-up in relation to |relative_to_|.
-  BubbleBorder::ArrowLocation anchor_position_;
-
-  // ExtensionPopup's lifetime is managed via reference counting, but it does
-  // not expose the RefCounted interface.  Instead, the lifetime is tied to
-  // this member variable.
-  class InternalRefCounter : public base::RefCounted<InternalRefCounter> {
-  };
-  InternalRefCounter* instance_lifetime_;
-
   DISALLOW_COPY_AND_ASSIGN(ExtensionPopup);
 };
 
diff --git a/chrome/browser/ui/views/extensions/extension_view.cc b/chrome/browser/ui/views/extensions/extension_view.cc
index fcace1a..811f12e 100644
--- a/chrome/browser/ui/views/extensions/extension_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_view.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/extensions/extension_view.h"
+#include "chrome/browser/ui/views/extensions/extension_view.h"
 
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
+#include "chrome/browser/ui/views/extensions/extension_popup.h"
 #include "views/widget/widget.h"
 
 #if defined(OS_WIN)
@@ -33,9 +33,8 @@
 }
 
 ExtensionView::~ExtensionView() {
-  View* parent = GetParent();
-  if (parent)
-    parent->RemoveChildView(this);
+  if (parent())
+    parent()->RemoveChildView(this);
   CleanUp();
 }
 
@@ -75,13 +74,12 @@
   }
 }
 
-void ExtensionView::DidChangeBounds(const gfx::Rect& previous,
-                                    const gfx::Rect& current) {
-  View::DidChangeBounds(previous, current);
+void ExtensionView::OnBoundsChanged() {
+  View::OnBoundsChanged();
   // Propagate the new size to RenderWidgetHostView.
   // We can't send size zero because RenderWidget DCHECKs that.
-  if (render_view_host()->view() && !current.IsEmpty())
-    render_view_host()->view()->SetSize(gfx::Size(width(), height()));
+  if (render_view_host()->view() && !bounds().IsEmpty())
+    render_view_host()->view()->SetSize(size());
 }
 
 void ExtensionView::CreateWidgetHostView() {
@@ -172,15 +170,14 @@
 
 void ExtensionView::PreferredSizeChanged() {
   View::PreferredSizeChanged();
-  if (container_) {
+  if (container_)
     container_->OnExtensionPreferredSizeChanged(this);
-  }
 }
 
 bool ExtensionView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
   // Let the tab key event be processed by the renderer (instead of moving the
   // focus to the next focusable view).
-  return (e.GetKeyCode() == app::VKEY_TAB);
+  return (e.key_code() == ui::VKEY_TAB);
 }
 
 void ExtensionView::HandleMouseMove() {
diff --git a/chrome/browser/ui/views/extensions/extension_view.h b/chrome/browser/ui/views/extensions/extension_view.h
index b8cfecd..baee155 100644
--- a/chrome/browser/ui/views/extensions/extension_view.h
+++ b/chrome/browser/ui/views/extensions/extension_view.h
@@ -58,8 +58,7 @@
 
   // Overridden from views::NativeViewHost:
   virtual void SetVisible(bool is_visible);
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
+  virtual void OnBoundsChanged();
   virtual void ViewHierarchyChanged(bool is_add,
                                     views::View *parent, views::View *child);
 
diff --git a/chrome/browser/ui/views/external_protocol_dialog.cc b/chrome/browser/ui/views/external_protocol_dialog.cc
index 1155770..434d82e 100644
--- a/chrome/browser/ui/views/external_protocol_dialog.cc
+++ b/chrome/browser/ui/views/external_protocol_dialog.cc
@@ -1,12 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/external_protocol_dialog.h"
+#include "chrome/browser/ui/views/external_protocol_dialog.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
-#include "app/text_elider.h"
 #include "base/metrics/histogram.h"
 #include "base/string_util.h"
 #include "base/threading/thread.h"
@@ -18,6 +15,9 @@
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
+#include "ui/base/text/text_elider.h"
 #include "views/controls/message_box_view.h"
 #include "views/window/window.h"
 
@@ -56,12 +56,12 @@
 // ExternalProtocolDialog, views::DialogDelegate implementation:
 
 int ExternalProtocolDialog::GetDefaultDialogButton() const {
-  return MessageBoxFlags::DIALOGBUTTON_CANCEL;
+  return ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
 }
 
 std::wstring ExternalProtocolDialog::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK)
+    ui::MessageBoxFlags::DialogButton button) const {
+  if (button == ui::MessageBoxFlags::DIALOGBUTTON_OK)
     return UTF16ToWide(
         l10n_util::GetStringUTF16(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT));
   else
@@ -125,9 +125,9 @@
   const int kMaxCommandSize = 256;
   std::wstring elided_url_without_scheme;
   std::wstring elided_command;
-  gfx::ElideString(ASCIIToWide(url.possibly_invalid_spec()),
-                   kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
-  gfx::ElideString(command, kMaxCommandSize, &elided_command);
+  ui::ElideString(ASCIIToWide(url.possibly_invalid_spec()),
+                  kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
+  ui::ElideString(command, kMaxCommandSize, &elided_command);
 
   std::wstring message_text = UTF16ToWide(l10n_util::GetStringFUTF16(
       IDS_EXTERNAL_PROTOCOL_INFORMATION,
@@ -141,10 +141,11 @@
   message_text +=
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXTERNAL_PROTOCOL_WARNING));
 
-  message_box_view_ = new MessageBoxView(MessageBoxFlags::kIsConfirmMessageBox,
-                                         message_text,
-                                         std::wstring(),
-                                         kMessageWidth);
+  message_box_view_ = new MessageBoxView(
+      ui::MessageBoxFlags::kIsConfirmMessageBox,
+      message_text,
+      std::wstring(),
+      kMessageWidth);
   message_box_view_->SetCheckBoxLabel(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT)));
 
@@ -176,7 +177,7 @@
   std::wstring parameters = url_spec.substr(split_offset + 1,
                                             url_spec.length() - 1);
   std::wstring application_to_launch;
-  if (cmd_key.ReadValue(NULL, &application_to_launch)) {
+  if (cmd_key.ReadValue(NULL, &application_to_launch) == ERROR_SUCCESS) {
     ReplaceSubstringsAfterOffset(&application_to_launch, 0, L"%1", parameters);
     return application_to_launch;
   } else {
diff --git a/chrome/browser/ui/views/find_bar_host.cc b/chrome/browser/ui/views/find_bar_host.cc
index f54ba6c..c1eac91 100644
--- a/chrome/browser/ui/views/find_bar_host.cc
+++ b/chrome/browser/ui/views/find_bar_host.cc
@@ -1,18 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/find_bar_host.h"
+#include "chrome/browser/ui/views/find_bar_host.h"
 
-#include "app/keyboard_codes.h"
+#include <algorithm>
+
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/find_bar_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "views/focus/external_focus_tracker.h"
 #include "views/focus/view_storage.h"
 #include "views/widget/root_view.h"
@@ -46,14 +49,14 @@
     return false;
   }
 
-  switch (key_event.GetKeyCode()) {
-    case app::VKEY_DOWN:
-    case app::VKEY_UP:
-    case app::VKEY_PRIOR:
-    case app::VKEY_NEXT:
+  switch (key_event.key_code()) {
+    case ui::VKEY_DOWN:
+    case ui::VKEY_UP:
+    case ui::VKEY_PRIOR:
+    case ui::VKEY_NEXT:
       break;
-    case app::VKEY_HOME:
-    case app::VKEY_END:
+    case ui::VKEY_HOME:
+    case ui::VKEY_END:
       if (key_event.IsControlDown())
         break;
     // Fall through.
@@ -61,7 +64,7 @@
       return false;
   }
 
-  TabContents* contents = find_bar_controller_->tab_contents();
+  TabContentsWrapper* contents = find_bar_controller_->tab_contents();
   if (!contents)
     return false;
 
@@ -70,7 +73,8 @@
   // Make sure we don't have a text field element interfering with keyboard
   // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
   render_view_host->ClearFocusedNode();
-  NativeWebKeyboardEvent event = GetKeyboardEvent(contents, key_event);
+  NativeWebKeyboardEvent event = GetKeyboardEvent(contents->tab_contents(),
+                                                  key_event);
   render_view_host->ForwardKeyboardEvent(event);
   return true;
 }
@@ -109,7 +113,8 @@
   // don't check this, then SetWidgetPosition below will end up making the Find
   // Bar visible.
   if (!find_bar_controller_->tab_contents() ||
-      !find_bar_controller_->tab_contents()->find_ui_active()) {
+      !find_bar_controller_->
+          tab_contents()->GetFindManager()->find_ui_active()) {
     return;
   }
 
@@ -150,7 +155,7 @@
 void FindBarHost::RestoreSavedFocus() {
   if (focus_tracker() == NULL) {
     // TODO(brettw) Focus() should be on TabContentsView.
-    find_bar_controller_->tab_contents()->Focus();
+    find_bar_controller_->tab_contents()->tab_contents()->Focus();
   } else {
     focus_tracker()->FocusLastFocusedExternalView();
   }
@@ -164,11 +169,11 @@
 // FindBarWin, views::AcceleratorTarget implementation:
 
 bool FindBarHost::AcceleratorPressed(const views::Accelerator& accelerator) {
-  app::KeyboardCode key = accelerator.GetKeyCode();
-  if (key == app::VKEY_RETURN && accelerator.IsCtrlDown()) {
+  ui::KeyboardCode key = accelerator.GetKeyCode();
+  if (key == ui::VKEY_RETURN && accelerator.IsCtrlDown()) {
     // Ctrl+Enter closes the Find session and navigates any link that is active.
     find_bar_controller_->EndFindSession(FindBarController::kActivateSelection);
-  } else if (key == app::VKEY_ESCAPE) {
+  } else if (key == ui::VKEY_ESCAPE) {
     // This will end the Find session and hide the window, causing it to loose
     // focus and in the process unregister us as the handler for the Escape
     // accelerator through the FocusWillChange event.
@@ -288,13 +293,13 @@
   DropdownBarHost::RegisterAccelerators();
 
   // Register for Ctrl+Return.
-  views::Accelerator escape(app::VKEY_RETURN, false, true, false);
+  views::Accelerator escape(ui::VKEY_RETURN, false, true, false);
   focus_manager()->RegisterAccelerator(escape, this);
 }
 
 void FindBarHost::UnregisterAccelerators() {
   // Unregister Ctrl+Return.
-  views::Accelerator escape(app::VKEY_RETURN, false, true, false);
+  views::Accelerator escape(ui::VKEY_RETURN, false, true, false);
   focus_manager()->UnregisterAccelerator(escape, this);
 
   DropdownBarHost::UnregisterAccelerators();
diff --git a/chrome/browser/ui/views/find_bar_host.h b/chrome/browser/ui/views/find_bar_host.h
index 997d2f8..3b0b173 100644
--- a/chrome/browser/ui/views/find_bar_host.h
+++ b/chrome/browser/ui/views/find_bar_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,9 +8,9 @@
 
 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
-#include "chrome/browser/views/dropdown_bar_host.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/views/dropdown_bar_host.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/textfield/textfield.h"
 
 class BrowserView;
diff --git a/chrome/browser/ui/views/find_bar_host_gtk.cc b/chrome/browser/ui/views/find_bar_host_gtk.cc
index 7306361..bacb9d8 100644
--- a/chrome/browser/ui/views/find_bar_host_gtk.cc
+++ b/chrome/browser/ui/views/find_bar_host_gtk.cc
@@ -1,13 +1,14 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/find_bar_host.h"
+#include "chrome/browser/ui/views/find_bar_host.h"
 
 #include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tab_contents/tab_contents_view_gtk.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "views/widget/widget_gtk.h"
 
 void FindBarHost::AudibleAlert() {
@@ -19,8 +20,7 @@
   gfx::Rect frame_rect, webcontents_rect;
   host()->GetRootWidget()->GetBounds(&frame_rect, true);
   TabContentsView* tab_view = find_bar_controller_->tab_contents()->view();
-  static_cast<TabContentsViewGtk*>(tab_view)->GetBounds(&webcontents_rect,
-                                                        true);
+  tab_view->GetViewBounds(&webcontents_rect);
   avoid_overlapping_rect->Offset(0, webcontents_rect.y() - frame_rect.y());
 }
 
diff --git a/chrome/browser/ui/views/find_bar_host_interactive_uitest.cc b/chrome/browser/ui/views/find_bar_host_interactive_uitest.cc
index cb3d364..816ead2 100644
--- a/chrome/browser/ui/views/find_bar_host_interactive_uitest.cc
+++ b/chrome/browser/ui/views/find_bar_host_interactive_uitest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/keyboard_codes.h"
 #include "base/process_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -16,6 +15,7 @@
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
 #include "net/test/test_server.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "views/focus/focus_manager.h"
 #include "views/view.h"
 
@@ -73,7 +73,7 @@
 
   // This used to crash until bug 1303709 was fixed.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_ESCAPE, false, false, false, false));
+      browser(), ui::VKEY_ESCAPE, false, false, false, false));
 }
 
 IN_PROC_BROWSER_TEST_F(FindInPageTest, FocusRestore) {
@@ -100,7 +100,7 @@
   browser()->Find();
   EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(),
                                            VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
-  ui_test_utils::FindInPage(browser()->GetSelectedTabContents(),
+  ui_test_utils::FindInPage(browser()->GetSelectedTabContentsWrapper(),
                             ASCIIToUTF16("a"), true, false, NULL);
   browser()->GetFindBarController()->EndFindSession(
       FindBarController::kKeepSelection);
@@ -135,7 +135,7 @@
       browser()->GetFindBarController()->find_bar()->GetFindBarTesting();
 
   // Search for 'a'.
-  ui_test_utils::FindInPage(browser()->GetSelectedTabContents(),
+  ui_test_utils::FindInPage(browser()->GetSelectedTabContentsWrapper(),
                             ASCIIToUTF16("a"), true, false, NULL);
   EXPECT_TRUE(ASCIIToUTF16("a") == find_bar->GetFindSelectedText());
 
@@ -149,7 +149,7 @@
                                            VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
 
   // Search for 'b'.
-  ui_test_utils::FindInPage(browser()->GetSelectedTabContents(),
+  ui_test_utils::FindInPage(browser()->GetSelectedTabContentsWrapper(),
                             ASCIIToUTF16("b"), true, false, NULL);
   EXPECT_TRUE(ASCIIToUTF16("b") == find_bar->GetFindSelectedText());
 
@@ -171,7 +171,8 @@
 // This tests that whenever you clear values from the Find box and close it that
 // it respects that and doesn't show you the last search, as reported in bug:
 // http://crbug.com/40121.
-IN_PROC_BROWSER_TEST_F(FindInPageTest, PrepopulateRespectBlank) {
+// Crashy, http://crbug.com/69882.
+IN_PROC_BROWSER_TEST_F(FindInPageTest, DISABLED_PrepopulateRespectBlank) {
 #if defined(OS_MACOSX)
   // FindInPage on Mac doesn't use prepopulated values. Search there is global.
   return;
@@ -192,21 +193,21 @@
 
   // Search for "a".
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_A, false, false, false, false));
+      browser(), ui::VKEY_A, false, false, false, false));
 
   // We should find "a" here.
   EXPECT_EQ(ASCIIToUTF16("a"), GetFindBarText());
 
   // Delete "a".
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_BACK, false, false, false, false));
+      browser(), ui::VKEY_BACK, false, false, false, false));
 
   // Validate we have cleared the text.
   EXPECT_EQ(string16(), GetFindBarText());
 
   // Close the Find box.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_ESCAPE, false, false, false, false));
+      browser(), ui::VKEY_ESCAPE, false, false, false, false));
 
   // Show the Find bar.
   browser()->GetFindBarController()->Show();
@@ -217,11 +218,11 @@
 
   // Close the Find box.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_ESCAPE, false, false, false, false));
+      browser(), ui::VKEY_ESCAPE, false, false, false, false));
 
   // Press F3 to trigger FindNext.
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
-      browser(), app::VKEY_F3, false, false, false, false));
+      browser(), ui::VKEY_F3, false, false, false, false));
 
   // After the Find box has been reopened, it should still have no prepopulate
   // value.
diff --git a/chrome/browser/ui/views/find_bar_host_win.cc b/chrome/browser/ui/views/find_bar_host_win.cc
index d74a8d1..ee0a980 100644
--- a/chrome/browser/ui/views/find_bar_host_win.cc
+++ b/chrome/browser/ui/views/find_bar_host_win.cc
@@ -1,14 +1,15 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/find_bar_host.h"
+#include "chrome/browser/ui/views/find_bar_host.h"
 
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "views/controls/scrollbar/native_scroll_bar.h"
 #include "views/widget/widget_win.h"
 
@@ -21,7 +22,8 @@
   ::GetWindowRect(
       static_cast<views::WidgetWin*>(host())->GetParent(), &frame_rect);
   ::GetWindowRect(
-      find_bar_controller_->tab_contents()->view()->GetNativeView(),
+      find_bar_controller_->
+          tab_contents()->tab_contents()->view()->GetNativeView(),
       &webcontents_rect);
   avoid_overlapping_rect->Offset(0, webcontents_rect.top - frame_rect.top);
 }
@@ -29,5 +31,6 @@
 bool FindBarHost::ShouldForwardKeyEventToWebpageNative(
     const views::KeyEvent& key_event) {
   // We specifically ignore WM_CHAR. See http://crbug.com/10509.
-  return key_event.message() == WM_KEYDOWN || key_event.message() == WM_KEYUP;
+  return key_event.native_event().message == WM_KEYDOWN ||
+         key_event.native_event().message == WM_KEYUP;
 }
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc
index 4a98ec4..87a7abd 100644
--- a/chrome/browser/ui/views/find_bar_view.cc
+++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -1,13 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/find_bar_view.h"
+#include "chrome/browser/ui/views/find_bar_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -16,13 +14,17 @@
 #include "chrome/browser/themes/browser_theme_provider.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/browser/ui/find_bar/find_bar_state.h"
+#include "chrome/browser/ui/find_bar/find_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/find_bar_host.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/label.h"
@@ -102,8 +104,7 @@
   find_text_->SetFont(rb.GetFont(ResourceBundle::BaseFont));
   find_text_->set_default_width_in_chars(kDefaultCharWidth);
   find_text_->SetController(this);
-  find_text_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_FIND)));
+  find_text_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_FIND));
   AddChildView(find_text_);
 
   match_count_text_ = new views::Label();
@@ -128,7 +129,7 @@
   find_previous_button_->SetTooltipText(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP)));
   find_previous_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_PREVIOUS)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_PREVIOUS));
   AddChildView(find_previous_button_);
 
   find_next_button_ = new views::ImageButton(this);
@@ -143,7 +144,7 @@
   find_next_button_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_FIND_IN_PAGE_NEXT_TOOLTIP)));
   find_next_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_NEXT)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_NEXT));
   AddChildView(find_next_button_);
 
   close_button_ = new views::ImageButton(this);
@@ -158,7 +159,7 @@
   close_button_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_FIND_IN_PAGE_CLOSE_TOOLTIP)));
   close_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
   AddChildView(close_button_);
 
   if (kDialog_left == NULL) {
@@ -287,7 +288,7 @@
   // controller, so the whitespace in the left and right background images is
   // actually outside the window region and is therefore not drawn. See
   // FindInPageWidgetWin::CreateRoundedWindowEdges() for details.
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
   canvas->TileImageInt(*tp->GetBitmapNamed(IDR_THEME_TOOLBAR), origin.x(),
                        origin.y(), 0, 0, bounds.width(), bounds.height());
 
@@ -440,9 +441,9 @@
     case FIND_NEXT_TAG:
       if (!find_text_->text().empty()) {
         find_bar_host()->GetFindBarController()->tab_contents()->
-            StartFinding(find_text_->text(),
-                         sender->tag() == FIND_NEXT_TAG,
-                         false);  // Not case sensitive.
+            GetFindManager()->StartFinding(find_text_->text(),
+                                           sender->tag() == FIND_NEXT_TAG,
+                                           false);  // Not case sensitive.
       }
       if (event.IsMouseEvent()) {
         // If mouse event, we move the focus back to the text-field, so that the
@@ -481,16 +482,17 @@
   // can lead to crashes, as exposed by automation testing in issue 8048.
   if (!controller->tab_contents())
     return;
+  FindManager* find_manager = controller->tab_contents()->GetFindManager();
 
   // When the user changes something in the text box we check the contents and
   // if the textbox contains something we set it as the new search string and
   // initiate search (even though old searches might be in progress).
   if (!new_contents.empty()) {
     // The last two params here are forward (true) and case sensitive (false).
-    controller->tab_contents()->StartFinding(new_contents, true, false);
+    find_manager->StartFinding(new_contents, true, false);
   } else {
-    controller->tab_contents()->StopFinding(FindBarController::kClearSelection);
-    UpdateForResult(controller->tab_contents()->find_result(), string16());
+    find_manager->StopFinding(FindBarController::kClearSelection);
+    UpdateForResult(find_manager->find_result(), string16());
 
     // Clearing the text box should clear the prepopulate state so that when
     // we close and reopen the Find box it doesn't show the search we just
@@ -512,15 +514,16 @@
   if (find_bar_host()->MaybeForwardKeyEventToWebpage(key_event))
     return true;  // Handled, we are done!
 
-  if (key_event.GetKeyCode() == app::VKEY_RETURN) {
+  if (key_event.key_code() == ui::VKEY_RETURN) {
     // Pressing Return/Enter starts the search (unless text box is empty).
     string16 find_string = find_text_->text();
     if (!find_string.empty()) {
+      FindBarController* controller = find_bar_host()->GetFindBarController();
+      FindManager* find_manager = controller->tab_contents()->GetFindManager();
       // Search forwards for enter, backwards for shift-enter.
-      find_bar_host()->GetFindBarController()->tab_contents()->StartFinding(
-          find_string,
-          !key_event.IsShiftDown(),
-          false);  // Not case sensitive.
+      find_manager->StartFinding(find_string,
+                                 !key_event.IsShiftDown(),
+                                 false);  // Not case sensitive.
     }
   }
 
diff --git a/chrome/browser/ui/views/find_bar_view.h b/chrome/browser/ui/views/find_bar_view.h
index e3ef231..80e7647 100644
--- a/chrome/browser/ui/views/find_bar_view.h
+++ b/chrome/browser/ui/views/find_bar_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,8 @@
 
 #include "base/string16.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
-#include "chrome/browser/views/dropdown_bar_view.h"
-#include "gfx/size.h"
+#include "chrome/browser/ui/views/dropdown_bar_view.h"
+#include "ui/gfx/size.h"
 #include "views/controls/button/button.h"
 #include "views/controls/textfield/textfield.h"
 
diff --git a/chrome/browser/ui/views/first_run_bubble.cc b/chrome/browser/ui/views/first_run_bubble.cc
index 8fe3cd4..802979a 100644
--- a/chrome/browser/ui/views/first_run_bubble.cc
+++ b/chrome/browser/ui/views/first_run_bubble.cc
@@ -1,13 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/first_run_bubble.h"
+#include "chrome/browser/ui/views/first_run_bubble.h"
 
-#include "app/gfx/font_util.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/win/hwnd_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
@@ -19,12 +15,16 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
-#include "views/event.h"
+#include "ui/base/l10n/l10n_font_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/label.h"
+#include "views/events/event.h"
 #include "views/focus/focus_manager.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
+#include "views/widget/widget_win.h"
 #include "views/window/window.h"
 
 namespace {
@@ -175,7 +175,7 @@
                      pref_size.height());
 
   int next_v_space = label1_->y() + pref_size.height() +
-                     kRelatedControlSmallVerticalSpacing;
+                     views::kRelatedControlSmallVerticalSpacing;
 
   pref_size = label2_->GetPreferredSize();
   label2_->SetBounds(kBubblePadding, next_v_space,
@@ -193,12 +193,12 @@
   pref_size = change_button_->GetPreferredSize();
   change_button_->SetBounds(
       canvas.width() - pref_size.width() - kBubblePadding,
-      canvas.height() - pref_size.height() - kButtonVEdgeMargin,
+      canvas.height() - pref_size.height() - views::kButtonVEdgeMargin,
       pref_size.width(), pref_size.height());
 
   pref_size = keep_button_->GetPreferredSize();
   keep_button_->SetBounds(change_button_->x() - pref_size.width() -
-                          kRelatedButtonHSpacing, change_button_->y(),
+                          views::kRelatedButtonHSpacing, change_button_->y(),
                           pref_size.width(), pref_size.height());
 }
 
@@ -332,7 +332,8 @@
       pref_size.height());
 
   int next_v_space =
-      label1_->y() + pref_size.height() + kRelatedControlSmallVerticalSpacing;
+      label1_->y() + pref_size.height() +
+          views::kRelatedControlSmallVerticalSpacing;
 
   pref_size = label3_->GetPreferredSize();
   label3_->SetBounds(kOEMBubblePadding, next_v_space,
@@ -346,9 +347,9 @@
   const gfx::Font& font = rb.GetFont(
       ResourceBundle::MediumFont).DeriveFont(3, gfx::Font::BOLD);
   gfx::Size size = gfx::Size(
-      gfx::GetLocalizedContentsWidthForFont(
+      ui::GetLocalizedContentsWidthForFont(
           IDS_FIRSTRUNOEMBUBBLE_DIALOG_WIDTH_CHARS, font),
-      gfx::GetLocalizedContentsHeightForFont(
+      ui::GetLocalizedContentsHeightForFont(
           IDS_FIRSTRUNOEMBUBBLE_DIALOG_HEIGHT_LINES, font));
 
   // WARNING: HACK. Vista and XP calculate font size differently; this means
@@ -358,7 +359,7 @@
   // now, we force Vista to show a correctly-sized box by taking account of
   // the difference in font size calculation. The coefficient should not be
   // stored in a variable because it's a hack and should go away.
-  if (app::win::ShouldUseVistaFrame()) {
+  if (views::WidgetWin::IsAeroGlassEnabled()) {
     size.set_width(static_cast<int>(size.width() * 0.85));
     size.set_height(static_cast<int>(size.height() * 0.85));
   }
@@ -445,7 +446,7 @@
                      pref_size.height());
 
   int next_v_space = label1_->y() + pref_size.height() +
-                     kRelatedControlSmallVerticalSpacing;
+                     views::kRelatedControlSmallVerticalSpacing;
 
   pref_size = label2_->GetPreferredSize();
   label2_->SetBounds(kBubblePadding, next_v_space,
diff --git a/chrome/browser/ui/views/first_run_bubble.h b/chrome/browser/ui/views/first_run_bubble.h
index 2829218..cf6da71 100644
--- a/chrome/browser/ui/views/first_run_bubble.h
+++ b/chrome/browser/ui/views/first_run_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/task.h"
 #include "chrome/browser/first_run/first_run.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 
 class FirstRunBubbleViewBase;
 class Profile;
diff --git a/chrome/browser/ui/views/first_run_search_engine_view.cc b/chrome/browser/ui/views/first_run_search_engine_view.cc
index 91cf367..5cf2451 100644
--- a/chrome/browser/ui/views/first_run_search_engine_view.cc
+++ b/chrome/browser/ui/views/first_run_search_engine_view.cc
@@ -1,15 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/first_run_search_engine_view.h"
+#include "chrome/browser/ui/views/first_run_search_engine_view.h"
 
 #include <algorithm>
 #include <map>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/rand_util.h"
 #include "base/time.h"
@@ -19,19 +17,21 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/ui/options/options_window.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/google_chrome_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
 #include "views/controls/button/button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/view_text_utils.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -92,7 +92,7 @@
   // screenreaders. It uses the browser name rather than the text of the
   // button "Choose", since it's not obvious to a screenreader user which
   // browser each button corresponds to.
-  SetAccessibleName(search_engine_->short_name());
+  SetAccessibleName(WideToUTF16Hack(search_engine_->short_name()));
 }
 
 int SearchEngineChoice::GetChoiceViewWidth() {
diff --git a/chrome/browser/ui/views/first_run_search_engine_view.h b/chrome/browser/ui/views/first_run_search_engine_view.h
index e901f1e..754111f 100644
--- a/chrome/browser/ui/views/first_run_search_engine_view.h
+++ b/chrome/browser/ui/views/first_run_search_engine_view.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "chrome/browser/search_engines/template_url_model_observer.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/controls/button/native_button.h"
 #include "views/view.h"
 #include "views/window/window_delegate.h"
diff --git a/chrome/browser/ui/views/frame/app_panel_browser_frame_view.cc b/chrome/browser/ui/views/frame/app_panel_browser_frame_view.cc
index fdfff0a..bb75ed8 100644
--- a/chrome/browser/ui/views/frame/app_panel_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/app_panel_browser_frame_view.cc
@@ -1,23 +1,23 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/app_panel_browser_frame_view.h"
+#include "chrome/browser/ui/views/frame/app_panel_browser_frame_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/compiler_specific.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
-#include "gfx/path.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/path.h"
 #include "views/controls/button/image_button.h"
 #include "views/window/window.h"
 #include "views/window/window_resources.h"
@@ -73,7 +73,7 @@
   close_button_->SetImage(views::CustomButton::BS_PUSHED,
                           rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
   close_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
   AddChildView(close_button_);
 
   window_icon_ = new TabIconView(this);
@@ -89,7 +89,7 @@
 // AppPanelBrowserFrameView, BrowserNonClientFrameView implementation:
 
 gfx::Rect AppPanelBrowserFrameView::GetBoundsForTabStrip(
-    BaseTabStrip* tabstrip) const {
+    views::View* tabstrip) const {
   // App panels never show a tab strip.
   NOTREACHED();
   return gfx::Rect();
@@ -156,7 +156,7 @@
   // of Fitts' Law.
   if (frame_->GetWindow()->IsMaximized())
     sysmenu_rect.SetRect(0, 0, sysmenu_rect.right(), sysmenu_rect.bottom());
-  sysmenu_rect.set_x(MirroredLeftPointForRect(sysmenu_rect));
+  sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect));
   if (sysmenu_rect.Contains(point))
     return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU;
 
@@ -165,7 +165,7 @@
 
   // Then see if the point is within any of the window controls.
   if (close_button_->IsVisible() &&
-      close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point))
+      close_button_->GetMirroredBounds().Contains(point))
     return HTCLOSE;
 
   int window_component = GetHTComponentForFrame(point,
@@ -404,7 +404,7 @@
   // The window icon is painted by the TabIconView.
   views::WindowDelegate* d = frame_->GetWindow()->GetDelegate();
   canvas->DrawStringInt(d->GetWindowTitle(), BrowserFrame::GetTitleFont(),
-      SK_ColorBLACK, MirroredLeftPointForRect(title_bounds_), title_bounds_.y(),
+      SK_ColorBLACK, GetMirroredXForRect(title_bounds_), title_bounds_.y(),
       title_bounds_.width(), title_bounds_.height());
 }
 
@@ -481,7 +481,7 @@
 void AppPanelBrowserFrameView::LayoutTitleBar() {
   // Size the icon first; the window title is based on the icon position.
   gfx::Rect icon_bounds(IconBounds());
-  window_icon_->SetBounds(icon_bounds);
+  window_icon_->SetBoundsRect(icon_bounds);
 
   // Size the title.
   int title_x = icon_bounds.right() + kIconTitleSpacing;
diff --git a/chrome/browser/ui/views/frame/app_panel_browser_frame_view.h b/chrome/browser/ui/views/frame/app_panel_browser_frame_view.h
index 1f6deec..198284f 100644
--- a/chrome/browser/ui/views/frame/app_panel_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/app_panel_browser_frame_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_UI_VIEWS_FRAME_APP_PANEL_BROWSER_FRAME_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/frame/browser_non_client_frame_view.h"
-#include "chrome/browser/views/tab_icon_view.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
+#include "chrome/browser/ui/views/tab_icon_view.h"
 #include "views/controls/button/button.h"
 #include "views/window/non_client_view.h"
 
-class BaseTabStrip;
 class BrowserView;
 class TabContents;
 namespace gfx {
@@ -34,7 +33,7 @@
   virtual ~AppPanelBrowserFrameView();
 
   // Overridden from BrowserNonClientFrameView:
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const;
   virtual int GetHorizontalTabStripVerticalOffset(bool restored) const;
   virtual void UpdateThrobber(bool running);
   virtual gfx::Size GetMinimumSize();
diff --git a/chrome/browser/ui/views/frame/browser_bubble_host.cc b/chrome/browser/ui/views/frame/browser_bubble_host.cc
index 60809bf..ed13309 100644
--- a/chrome/browser/ui/views/frame/browser_bubble_host.cc
+++ b/chrome/browser/ui/views/frame/browser_bubble_host.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/browser_bubble_host.h"
+#include "chrome/browser/ui/views/frame/browser_bubble_host.h"
 
 #include "base/logging.h"
-#include "chrome/browser/views/browser_bubble.h"
+#include "chrome/browser/ui/views/browser_bubble.h"
 
 void BrowserBubbleHost::WindowMoved() {
   // Do safe iteration in case the bubble winds up closing as a result of this
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h
index 3c6a98d..3be0ddd 100644
--- a/chrome/browser/ui/views/frame/browser_frame.h
+++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -9,16 +9,18 @@
 #include "build/build_config.h"
 #include "views/window/non_client_view.h"
 
-class BaseTabStrip;
 class BrowserView;
 class Profile;
-class ThemeProvider;
 
 namespace gfx {
 class Font;
 class Rect;
 }  // namespace gfx
 
+namespace ui {
+class ThemeProvider;
+}
+
 namespace views {
 class Window;
 
@@ -47,8 +49,8 @@
   virtual int GetMinimizeButtonOffset() const = 0;
 
   // Retrieves the bounds, in non-client view coordinates for the specified
-  // TabStrip.
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const = 0;
+  // TabStrip view.
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const = 0;
 
   // Returns the y coordinate within the window at which the horizontal TabStrip
   // begins (or would begin).  If |restored| is true, this is calculated as if
@@ -59,7 +61,7 @@
   virtual void UpdateThrobber(bool running) = 0;
 
   // Returns the theme provider for this frame.
-  virtual ThemeProvider* GetThemeProviderForFrame() const = 0;
+  virtual ui::ThemeProvider* GetThemeProviderForFrame() const = 0;
 
   // Returns true if the window should use the native frame view. This is true
   // if there are no themes applied on Vista, or if there are themes applied and
diff --git a/chrome/browser/ui/views/frame/browser_frame_gtk.cc b/chrome/browser/ui/views/frame/browser_frame_gtk.cc
index f092657..4aeefb4 100644
--- a/chrome/browser/ui/views/frame/browser_frame_gtk.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_gtk.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/browser_frame_gtk.h"
+#include "chrome/browser/ui/views/frame/browser_frame_gtk.h"
 
 #include "base/logging.h"
 #include "chrome/browser/profiles/profile.h"
@@ -12,7 +12,7 @@
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/frame/browser_root_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "gfx/font.h"
+#include "ui/gfx/font.h"
 #include "views/widget/root_view.h"
 #include "views/window/hit_test.h"
 
@@ -63,7 +63,7 @@
   return 0;
 }
 
-gfx::Rect BrowserFrameGtk::GetBoundsForTabStrip(BaseTabStrip* tabstrip) const {
+gfx::Rect BrowserFrameGtk::GetBoundsForTabStrip(views::View* tabstrip) const {
   return browser_frame_view_->GetBoundsForTabStrip(tabstrip);
 }
 
@@ -90,7 +90,7 @@
 }
 
 void BrowserFrameGtk::TabStripDisplayModeChanged() {
-  if (GetRootView()->GetChildViewCount() > 0) {
+  if (GetRootView()->has_children()) {
     // Make sure the child of the root view gets Layout again.
     GetRootView()->GetChildViewAt(0)->InvalidateLayout();
   }
@@ -121,7 +121,7 @@
 }
 
 bool BrowserFrameGtk::GetAccelerator(int cmd_id,
-                                     menus::Accelerator* accelerator) {
+                                     ui::Accelerator* accelerator) {
   return browser_view_->GetAccelerator(cmd_id, accelerator);
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_frame_gtk.h b/chrome/browser/ui/views/frame/browser_frame_gtk.h
index e49227f..44be1a1 100644
--- a/chrome/browser/ui/views/frame/browser_frame_gtk.h
+++ b/chrome/browser/ui/views/frame/browser_frame_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "chrome/browser/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "views/window/window_gtk.h"
 
 class BrowserNonClientFrameView;
@@ -30,17 +30,17 @@
   // Overridden from BrowserFrame:
   virtual views::Window* GetWindow();
   virtual int GetMinimizeButtonOffset() const;
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const;
   virtual int GetHorizontalTabStripVerticalOffset(bool restored) const;
   virtual void UpdateThrobber(bool running);
-  virtual ThemeProvider* GetThemeProviderForFrame() const;
+  virtual ui::ThemeProvider* GetThemeProviderForFrame() const;
   virtual bool AlwaysUseNativeFrame() const;
   virtual views::View* GetFrameView() const;
   virtual void TabStripDisplayModeChanged();
 
   // Overridden from views::Widget:
-  virtual ThemeProvider* GetThemeProvider() const;
-  virtual ThemeProvider* GetDefaultThemeProvider() const;
+  virtual ui::ThemeProvider* GetThemeProvider() const;
+  virtual ui::ThemeProvider* GetDefaultThemeProvider() const;
   virtual void IsActiveChanged();
   virtual void SetInitialFocus();
 
@@ -51,7 +51,7 @@
 
   // Overridden from views::WidgetGtk:
   virtual views::RootView* CreateRootView();
-  virtual bool GetAccelerator(int cmd_id, menus::Accelerator* accelerator);
+  virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator);
 
   // Overriden from views::WindowGtk:
   virtual gboolean OnWindowStateEvent(GtkWidget* widget,
diff --git a/chrome/browser/ui/views/frame/browser_frame_win.cc b/chrome/browser/ui/views/frame/browser_frame_win.cc
index f1ef85d..1db3f49 100644
--- a/chrome/browser/ui/views/frame/browser_frame_win.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_win.cc
@@ -1,28 +1,28 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/browser_frame_win.h"
+#include "chrome/browser/ui/views/frame/browser_frame_win.h"
 
 #include <dwmapi.h>
 #include <shellapi.h>
 
 #include <set>
 
-#include "app/win/hwnd_util.h"
-#include "app/win/win_util.h"
 #include "chrome/browser/accessibility/browser_accessibility_state.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/views/frame/browser_non_client_frame_view.h"
-#include "chrome/browser/views/frame/browser_root_view.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/frame/glass_browser_frame_view.h"
-#include "gfx/font.h"
+#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
+#include "chrome/browser/ui/views/frame/browser_root_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h"
 #include "grit/theme_resources.h"
+#include "ui/gfx/font.h"
 #include "views/screen.h"
+#include "views/widget/widget_win.h"
 #include "views/window/window_delegate.h"
+#include "views/window/window_win.h"
 
 // static
 static const int kClientEdgeThickness = 3;
@@ -41,7 +41,8 @@
 
 // static
 const gfx::Font& BrowserFrame::GetTitleFont() {
-  static gfx::Font* title_font = new gfx::Font(app::win::GetWindowTitleFont());
+  static gfx::Font* title_font =
+      new gfx::Font(views::WindowWin::GetWindowTitleFont());
   return *title_font;
 }
 
@@ -83,7 +84,7 @@
   return minimize_button_corner.x;
 }
 
-gfx::Rect BrowserFrameWin::GetBoundsForTabStrip(BaseTabStrip* tabstrip) const {
+gfx::Rect BrowserFrameWin::GetBoundsForTabStrip(views::View* tabstrip) const {
   return browser_frame_view_->GetBoundsForTabStrip(tabstrip);
 }
 
@@ -109,7 +110,8 @@
   // We don't theme popup or app windows, so regardless of whether or not a
   // theme is active for normal browser windows, we don't want to use the custom
   // frame for popups/apps.
-  if (!browser_view_->IsBrowserTypeNormal() && app::win::ShouldUseVistaFrame())
+  if (!browser_view_->IsBrowserTypeNormal() &&
+      views::WidgetWin::IsAeroGlassEnabled())
     return true;
 
   // Otherwise, we use the native frame when we're told we should by the theme
@@ -122,7 +124,7 @@
 }
 
 void BrowserFrameWin::TabStripDisplayModeChanged() {
-  if (GetRootView()->GetChildViewCount() > 0) {
+  if (GetRootView()->has_children()) {
     // Make sure the child of the root view gets Layout again.
     GetRootView()->GetChildViewAt(0)->InvalidateLayout();
   }
@@ -153,7 +155,7 @@
 }
 
 bool BrowserFrameWin::GetAccelerator(int cmd_id,
-                                     menus::Accelerator* accelerator) {
+                                     ui::Accelerator* accelerator) {
   return browser_view_->GetAccelerator(cmd_id, accelerator);
 }
 
@@ -166,7 +168,7 @@
 }
 
 void BrowserFrameWin::OnExitSizeMove() {
-  WidgetWin::OnExitSizeMove();
+  views::WidgetWin::OnExitSizeMove();
 }
 
 void BrowserFrameWin::OnInitMenuPopup(HMENU menu, UINT position,
diff --git a/chrome/browser/ui/views/frame/browser_frame_win.h b/chrome/browser/ui/views/frame/browser_frame_win.h
index a74eae2..c106385 100644
--- a/chrome/browser/ui/views/frame/browser_frame_win.h
+++ b/chrome/browser/ui/views/frame/browser_frame_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "chrome/browser/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "views/window/window_win.h"
 
 class AeroGlassNonClientView;
@@ -39,10 +39,10 @@
   // BrowserFrame implementation.
   virtual views::Window* GetWindow();
   virtual int GetMinimizeButtonOffset() const;
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const;
   virtual int GetHorizontalTabStripVerticalOffset(bool restored) const;
   virtual void UpdateThrobber(bool running);
-  virtual ThemeProvider* GetThemeProviderForFrame() const;
+  virtual ui::ThemeProvider* GetThemeProviderForFrame() const;
   virtual bool AlwaysUseNativeFrame() const;
   virtual views::View* GetFrameView() const;
   virtual void TabStripDisplayModeChanged();
@@ -50,7 +50,7 @@
  protected:
   // Overridden from views::WindowWin:
   virtual gfx::Insets GetClientAreaInsets() const;
-  virtual bool GetAccelerator(int cmd_id, menus::Accelerator* accelerator);
+  virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator);
   virtual void OnEndSession(BOOL ending, UINT logoff);
   virtual void OnEnterSizeMove();
   virtual void OnExitSizeMove();
@@ -63,8 +63,8 @@
   virtual LRESULT OnNCActivate(BOOL active);
   virtual LRESULT OnNCHitTest(const CPoint& pt);
   virtual void OnWindowPosChanged(WINDOWPOS* window_pos);
-  virtual ThemeProvider* GetThemeProvider() const;
-  virtual ThemeProvider* GetDefaultThemeProvider() const;
+  virtual ui::ThemeProvider* GetThemeProvider() const;
+  virtual ui::ThemeProvider* GetDefaultThemeProvider() const;
   virtual void OnScreenReaderDetected();
 
   // Overridden from views::Window:
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 642c96d..6d69dcb 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -8,7 +8,6 @@
 
 #include "views/window/non_client_view.h"
 
-class BaseTabStrip;
 class BrowserFrame;
 class BrowserView;
 
@@ -20,7 +19,7 @@
   virtual ~BrowserNonClientFrameView() {}
 
   // Returns the bounds within which the TabStrip should be laid out.
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const = 0;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const = 0;
 
   // Returns the y coordinate within the window at which the horizontal TabStrip
   // begins, or (in vertical tabs mode) would begin.  If |restored| is true,
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_win.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_win.cc
index 69ad1c8..5eaf7fd 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_win.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_win.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 
-#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/app_panel_browser_frame_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h"
 
 namespace browser {
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc
index b6de9d6..bba2945 100644
--- a/chrome/browser/ui/views/frame/browser_root_view.cc
+++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -1,36 +1,36 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/browser_root_view.h"
+#include "chrome/browser/ui/views/frame/browser_root_view.h"
 
-#include "app/drag_drop_types.h"
-#include "app/l10n_util.h"
-#include "app/os_exchange_data.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "grit/chromium_strings.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/l10n/l10n_util.h"
 
 BrowserRootView::BrowserRootView(BrowserView* browser_view,
                                  views::Widget* widget)
     : views::RootView(widget),
       browser_view_(browser_view),
       forwarding_to_tab_strip_(false) {
-  SetAccessibleName(UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+  SetAccessibleName(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
 }
 
 bool BrowserRootView::GetDropFormats(
       int* formats,
-      std::set<OSExchangeData::CustomFormat>* custom_formats) {
+      std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
   if (tabstrip() && tabstrip()->IsVisible() && !tabstrip()->IsAnimating()) {
-    *formats = OSExchangeData::URL | OSExchangeData::STRING;
+    *formats = ui::OSExchangeData::URL | ui::OSExchangeData::STRING;
     return true;
   }
   return false;
@@ -40,7 +40,7 @@
   return true;
 }
 
-bool BrowserRootView::CanDrop(const OSExchangeData& data) {
+bool BrowserRootView::CanDrop(const ui::OSExchangeData& data) {
   if (!tabstrip() || !tabstrip()->IsVisible() || tabstrip()->IsAnimating())
     return false;
 
@@ -56,7 +56,7 @@
   if (ShouldForwardToTabStrip(event)) {
     forwarding_to_tab_strip_ = true;
     scoped_ptr<views::DropTargetEvent> mapped_event(
-        MapEventToTabStrip(event, event.GetData()));
+        MapEventToTabStrip(event, event.data()));
     tabstrip()->OnDragEntered(*mapped_event.get());
   }
 }
@@ -64,7 +64,7 @@
 int BrowserRootView::OnDragUpdated(const views::DropTargetEvent& event) {
   if (ShouldForwardToTabStrip(event)) {
     scoped_ptr<views::DropTargetEvent> mapped_event(
-        MapEventToTabStrip(event, event.GetData()));
+        MapEventToTabStrip(event, event.data()));
     if (!forwarding_to_tab_strip_) {
       tabstrip()->OnDragEntered(*mapped_event.get());
       forwarding_to_tab_strip_ = true;
@@ -74,7 +74,7 @@
     forwarding_to_tab_strip_ = false;
     tabstrip()->OnDragExited();
   }
-  return DragDropTypes::DRAG_NONE;
+  return ui::DragDropTypes::DRAG_NONE;
 }
 
 void BrowserRootView::OnDragExited() {
@@ -86,21 +86,21 @@
 
 int BrowserRootView::OnPerformDrop(const views::DropTargetEvent& event) {
   if (!forwarding_to_tab_strip_)
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
 
-  // Extract the URL and create a new OSExchangeData containing the URL. We do
-  // this as the TabStrip doesn't know about the autocomplete edit and neeeds
+  // Extract the URL and create a new ui::OSExchangeData containing the URL. We
+  // do this as the TabStrip doesn't know about the autocomplete edit and needs
   // to know about it to handle 'paste and go'.
   GURL url;
   std::wstring title;
-  OSExchangeData mapped_data;
-  if (!event.GetData().GetURLAndTitle(&url, &title) || !url.is_valid()) {
+  ui::OSExchangeData mapped_data;
+  if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid()) {
     // The url isn't valid. Use the paste and go url.
-    if (GetPasteAndGoURL(event.GetData(), &url))
+    if (GetPasteAndGoURL(event.data(), &url))
       mapped_data.SetURL(url, std::wstring());
     // else case: couldn't extract a url or 'paste and go' url. This ends up
-    // passing through an OSExchangeData with nothing in it. We need to do this
-    // so that the tab strip cleans up properly.
+    // passing through an ui::OSExchangeData with nothing in it. We need to do
+    // this so that the tab strip cleans up properly.
   } else {
     mapped_data.SetURL(url, std::wstring());
   }
@@ -124,19 +124,20 @@
 
 views::DropTargetEvent* BrowserRootView::MapEventToTabStrip(
     const views::DropTargetEvent& event,
-    const OSExchangeData& data) {
+    const ui::OSExchangeData& data) {
   gfx::Point tab_strip_loc(event.location());
   ConvertPointToView(this, tabstrip(), &tab_strip_loc);
   return new views::DropTargetEvent(data, tab_strip_loc.x(),
                                     tab_strip_loc.y(),
-                                    event.GetSourceOperations());
+                                    event.source_operations());
 }
 
 BaseTabStrip* BrowserRootView::tabstrip() const {
   return browser_view_->tabstrip();
 }
 
-bool BrowserRootView::GetPasteAndGoURL(const OSExchangeData& data, GURL* url) {
+bool BrowserRootView::GetPasteAndGoURL(const ui::OSExchangeData& data,
+                                       GURL* url) {
   if (!data.HasString())
     return false;
 
@@ -146,7 +147,7 @@
 
   AutocompleteMatch match;
   browser_view_->browser()->profile()->GetAutocompleteClassifier()->Classify(
-      text, std::wstring(), false, &match, NULL);
+      WideToUTF16Hack(text), string16(), false, &match, NULL);
   if (!match.destination_url.is_valid())
     return false;
 
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1559980..ae55758 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1,17 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 
 #if defined(OS_LINUX)
 #include <gtk/gtk.h>
 #endif
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
+#include "base/metrics/histogram.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -40,11 +39,11 @@
 #include "chrome/browser/themes/browser_theme_provider.h"
 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
 #include "chrome/browser/ui/view_ids.h"
-#include "chrome/browser/ui/views/accessible_view_helper.h"
 #include "chrome/browser/ui/views/bookmark_bar_view.h"
 #include "chrome/browser/ui/views/browser_dialogs.h"
 #include "chrome/browser/ui/views/default_search_view.h"
@@ -52,10 +51,11 @@
 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
 #include "chrome/browser/ui/views/frame/contents_container.h"
 #include "chrome/browser/ui/views/fullscreen_exit_bubble.h"
+#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/views/status_bubble_views.h"
 #include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
 #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
-#include "chrome/browser/ui/views/tabs/side_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab_strip_factory.h"
 #include "chrome/browser/ui/views/theme_install_bubble_view.h"
 #include "chrome/browser/ui/views/toolbar_view.h"
 #include "chrome/browser/ui/views/update_recommended_message_box.h"
@@ -67,28 +67,30 @@
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/canvas_skia.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
 #include "grit/webkit_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/single_split_view.h"
 #include "views/focus/external_focus_tracker.h"
 #include "views/focus/view_storage.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/widget/root_view.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
 
 #if defined(OS_WIN)
-#include "app/view_prop.h"
-#include "app/win/win_util.h"
 #include "chrome/browser/aeropeek_manager.h"
 #include "chrome/browser/jumplist_win.h"
+#include "ui/base/message_box_win.h"
+#include "ui/base/view_prop.h"
 #elif defined(OS_LINUX)
-#include "chrome/browser/views/accelerator_table_gtk.h"
+#include "chrome/browser/ui/views/accelerator_table_gtk.h"
 #include "views/window/hit_test.h"
 #include "views/window/window_gtk.h"
 #endif
@@ -123,7 +125,7 @@
 // ------------
 
 // Returned from BrowserView::GetClassName.
-const char BrowserView::kViewClassName[] = "browser/views/BrowserView";
+const char BrowserView::kViewClassName[] = "browser/ui/views/BrowserView";
 
 #if defined(OS_CHROMEOS)
 // Get a normal browser window of given |profile| to use as dialog parent
@@ -179,7 +181,7 @@
 
 void BookmarkExtensionBackground::Paint(gfx::Canvas* canvas,
                                         views::View* view) const {
-  ThemeProvider* tp = host_view_->GetThemeProvider();
+  ui::ThemeProvider* tp = host_view_->GetThemeProvider();
   int toolbar_overlap = host_view_->GetToolbarOverlap();
   // The client edge is drawn below the toolbar bounds.
   if (toolbar_overlap)
@@ -218,7 +220,7 @@
   } else {
     DetachableToolbarView::PaintBackgroundAttachedMode(canvas, host_view_,
         browser_view_->OffsetPointForToolbarBackgroundImage(
-        gfx::Point(host_view_->MirroredX(), host_view_->y())));
+        gfx::Point(host_view_->GetMirroredX(), host_view_->y())));
     if (host_view_->height() >= toolbar_overlap)
       DetachableToolbarView::PaintHorizontalBorder(canvas, host_view_);
   }
@@ -260,14 +262,13 @@
   }
 
   virtual void Layout() {
-    views::View* parent_view = GetParent();
-    if (parent_view) {
+    if (parent()) {
       gfx::Size ps = GetPreferredSize();
       // No need to handle Right to left text direction here,
       // our parent must take care of it for us...
       // TODO(alekseys): fix it.
-      SetBounds(parent_view->width() - ps.width(),
-                parent_view->height() - ps.height(), ps.width(), ps.height());
+      SetBounds(parent()->width() - ps.width(),
+                parent()->height() - ps.height(), ps.width(), ps.height());
     }
   }
 
@@ -476,10 +477,13 @@
 
   // The TabStrip attaches a listener to the model. Make sure we shut down the
   // TabStrip first so that it can cleanly remove the listener.
-  tabstrip_->GetParent()->RemoveChildView(tabstrip_);
+  tabstrip_->parent()->RemoveChildView(tabstrip_);
   delete tabstrip_;
   tabstrip_ = NULL;
 
+  // Child views maintain PrefMember attributes that point to
+  // OffTheRecordProfile's PrefService which gets deleted by ~Browser.
+  RemoveAllChildViews(true);
   // Explicitly set browser_ to NULL.
   browser_.reset();
 }
@@ -490,7 +494,7 @@
 #if defined(OS_WIN)
   if (IsWindow(window)) {
     return reinterpret_cast<BrowserView*>(
-        app::ViewProp::GetValue(window, kBrowserViewKey));
+        ui::ViewProp::GetValue(window, kBrowserViewKey));
   }
 #else
   if (window) {
@@ -556,7 +560,7 @@
 gfx::Rect BrowserView::GetClientAreaBounds() const {
   gfx::Rect container_bounds = contents_->bounds();
   gfx::Point container_origin = container_bounds.origin();
-  ConvertPointToView(this, GetParent(), &container_origin);
+  ConvertPointToView(this, parent(), &container_origin);
   container_bounds.set_origin(container_origin);
   return container_bounds;
 }
@@ -577,7 +581,7 @@
   // The background image starts tiling horizontally at the window left edge and
   // vertically at the top edge of the horizontal tab strip (or where it would
   // be).  We expect our parent's origin to be the window origin.
-  gfx::Point window_point(point.Add(gfx::Point(MirroredX(), y())));
+  gfx::Point window_point(point.Add(GetMirroredPosition()));
   window_point.Offset(0, -frame_->GetHorizontalTabStripVerticalOffset(false));
   return window_point;
 }
@@ -605,6 +609,17 @@
 }
 
 bool BrowserView::AcceleratorPressed(const views::Accelerator& accelerator) {
+#if defined(OS_CHROMEOS)
+  // If accessibility is enabled, ignore accelerators involving the Search
+  // key so that key combinations involving Search can be used for extra
+  // accessibility functionality.
+  if (accelerator.GetKeyCode() == ui::VKEY_LWIN &&
+      g_browser_process->local_state()->GetBoolean(
+          prefs::kAccessibilityEnabled)) {
+    return false;
+  }
+#endif
+
   std::map<views::Accelerator, int>::const_iterator iter =
       accelerator_table_.find(accelerator);
   DCHECK(iter != accelerator_table_.end());
@@ -615,18 +630,18 @@
   return browser_->ExecuteCommandIfEnabled(command_id);
 }
 
-bool BrowserView::GetAccelerator(int cmd_id, menus::Accelerator* accelerator) {
+bool BrowserView::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) {
   // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators
   // anywhere so we need to check for them explicitly here.
   switch (cmd_id) {
     case IDC_CUT:
-      *accelerator = views::Accelerator(app::VKEY_X, false, true, false);
+      *accelerator = views::Accelerator(ui::VKEY_X, false, true, false);
       return true;
     case IDC_COPY:
-      *accelerator = views::Accelerator(app::VKEY_C, false, true, false);
+      *accelerator = views::Accelerator(ui::VKEY_C, false, true, false);
       return true;
     case IDC_PASTE:
-      *accelerator = views::Accelerator(app::VKEY_V, false, true, false);
+      *accelerator = views::Accelerator(ui::VKEY_V, false, true, false);
       return true;
   }
   // Else, we retrieve the accelerator information from the accelerator table.
@@ -722,6 +737,7 @@
 }
 
 void BrowserView::SetBounds(const gfx::Rect& bounds) {
+  SetFullscreen(false);
   GetWidget()->SetBounds(bounds);
 }
 
@@ -804,12 +820,14 @@
   if (should_animate) {
     if (!loading_animation_timer_.IsRunning()) {
       // Loads are happening, and the timer isn't running, so start it.
+      last_animation_time_ = base::TimeTicks::Now();
       loading_animation_timer_.Start(
           TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
           &BrowserView::LoadingAnimationCallback);
     }
   } else {
     if (loading_animation_timer_.IsRunning()) {
+      last_animation_time_ = base::TimeTicks();
       loading_animation_timer_.Stop();
       // Loads are now complete, update the state if a task was scheduled.
       LoadingAnimationCallback();
@@ -825,6 +843,10 @@
   return frame_->GetWindow()->GetNormalBounds();
 }
 
+gfx::Rect BrowserView::GetBounds() const {
+  return frame_->GetWindow()->GetBounds();
+}
+
 bool BrowserView::IsMaximized() const {
   return frame_->GetWindow()->IsMaximized();
 }
@@ -948,7 +970,7 @@
   if (focused_view) {
     for (int i = 0; i < count; ++i) {
       if (accessible_views[i] == focused_view ||
-          accessible_views[i]->IsParentOf(focused_view)) {
+          accessible_views[i]->Contains(focused_view)) {
         index = i;
         break;
       }
@@ -1058,6 +1080,10 @@
   browser::ShowTaskManager();
 }
 
+void BrowserView::ShowBackgroundPages() {
+  browser::ShowBackgroundPages();
+}
+
 void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) {
   toolbar_->location_bar()->ShowStarBubble(url, !already_bookmarked);
 }
@@ -1094,10 +1120,6 @@
   return download_shelf_.get();
 }
 
-void BrowserView::ShowReportBugDialog() {
-  browser::ShowHtmlBugReportView(GetWindow(), browser_.get());
-}
-
 void BrowserView::ShowClearBrowsingDataDialog() {
   browser::ShowClearBrowsingDataView(GetWindow()->GetNativeWindow(),
                                      browser_->profile());
@@ -1132,8 +1154,8 @@
 #if defined(OS_WIN)
   string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
   string16 message = l10n_util::GetStringUTF16(message_id);
-  app::win::MessageBox(GetNativeHandle(), message, title,
-                       MB_OK | MB_ICONWARNING | MB_TOPMOST);
+  ui::MessageBox(GetNativeHandle(), message, title,
+                 MB_OK | MB_ICONWARNING | MB_TOPMOST);
 #elif defined(OS_LINUX)
   std::string title = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
   std::string message = l10n_util::GetStringUTF8(message_id);
@@ -1171,7 +1193,7 @@
   parent = GetNormalBrowserWindowForBrowser(browser(), NULL);
 #endif  // defined(OS_CHROMEOS)
 
-  browser::ShowHtmlDialogView(parent, browser_.get()->profile(), delegate);
+  browser::ShowHtmlDialog(parent, browser_.get()->profile(), delegate);
 }
 
 void BrowserView::ShowCreateWebAppShortcutsDialog(TabContents* tab_contents) {
@@ -1202,10 +1224,6 @@
                                bool show_history) {
   gfx::NativeWindow parent = GetWindow()->GetNativeWindow();
 
-#if defined(OS_CHROMEOS)
-  parent = GetNormalBrowserWindowForBrowser(browser(), profile);
-#endif  // defined(OS_CHROMEOS)
-
   browser::ShowPageInfoBubble(parent, profile, url, ssl, show_history);
 }
 
@@ -1221,7 +1239,7 @@
 #if defined(OS_WIN)
   // As Alt+F4 is the close-app keyboard shortcut, it needs processing
   // immediately.
-  if (event.windowsKeyCode == app::VKEY_F4 &&
+  if (event.windowsKeyCode == ui::VKEY_F4 &&
       event.modifiers == NativeWebKeyboardEvent::AltKey) {
     DefWindowProc(event.os_event.hwnd, event.os_event.message,
                   event.os_event.wParam, event.os_event.lParam);
@@ -1239,14 +1257,14 @@
   // TODO(suzhe): We need to check if Windows code also has this issue, and
   // it'll be best if we can unify these conversion tables.
   // See http://crbug.com/54315
-  views::KeyEvent views_event(event.os_event);
-  views::Accelerator accelerator(views_event.GetKeyCode(),
+  views::KeyEvent views_event(reinterpret_cast<GdkEvent*>(event.os_event));
+  views::Accelerator accelerator(views_event.key_code(),
                                  views_event.IsShiftDown(),
                                  views_event.IsControlDown(),
                                  views_event.IsAltDown());
 #else
   views::Accelerator accelerator(
-      static_cast<app::KeyboardCode>(event.windowsKeyCode),
+      static_cast<ui::KeyboardCode>(event.windowsKeyCode),
       (event.modifiers & NativeWebKeyboardEvent::ShiftKey) ==
           NativeWebKeyboardEvent::ShiftKey,
       (event.modifiers & NativeWebKeyboardEvent::ControlKey) ==
@@ -1280,9 +1298,10 @@
 
   // Executing the command may cause |this| object to be destroyed.
 #if defined(OS_LINUX) && !defined(TOUCH_UI)
-  if (browser_->IsReservedCommand(id) && !event.match_edit_command) {
+  if (browser_->IsReservedCommandOrKey(id, event) &&
+      !event.match_edit_command) {
 #else
-  if (browser_->IsReservedCommand(id)) {
+  if (browser_->IsReservedCommandOrKey(id, event)) {
 #endif
     UpdateAcceleratorMetrics(accelerator, id);
     return browser_->ExecuteCommandIfEnabled(id);
@@ -1312,39 +1331,20 @@
 // to windows. The real fix to this bug is to disable the commands when they
 // won't do anything. We'll need something like an overall clipboard command
 // manager to do that.
-#if !defined(OS_MACOSX)
 void BrowserView::Cut() {
-  ui_controls::SendKeyPress(GetNativeHandle(), app::VKEY_X,
+  ui_controls::SendKeyPress(GetNativeHandle(), ui::VKEY_X,
                             true, false, false, false);
 }
 
 void BrowserView::Copy() {
-  ui_controls::SendKeyPress(GetNativeHandle(), app::VKEY_C,
+  ui_controls::SendKeyPress(GetNativeHandle(), ui::VKEY_C,
                             true, false, false, false);
 }
 
 void BrowserView::Paste() {
-  ui_controls::SendKeyPress(GetNativeHandle(), app::VKEY_V,
+  ui_controls::SendKeyPress(GetNativeHandle(), ui::VKEY_V,
                             true, false, false, false);
 }
-#else
-// Mac versions.  Not tested by antyhing yet;
-// don't assume written == works.
-void BrowserView::Cut() {
-  ui_controls::SendKeyPress(GetNativeHandle(), app::VKEY_X,
-                            false, false, false, true);
-}
-
-void BrowserView::Copy() {
-  ui_controls::SendKeyPress(GetNativeHandle(), app::VKEY_C,
-                            false, false, false, true);
-}
-
-void BrowserView::Paste() {
-  ui_controls::SendKeyPress(GetNativeHandle(), app::VKEY_V,
-                            false, false, false, true);
-}
-#endif
 
 void BrowserView::ToggleTabStripMode() {
   InitTabStrip(browser_->tabstrip_model());
@@ -1356,10 +1356,8 @@
 }
 
 void BrowserView::ShowInstant(TabContents* preview_contents) {
-  if (!preview_container_) {
+  if (!preview_container_)
     preview_container_ = new TabContentsContainer();
-    preview_container_->set_reserved_area_delegate(this);
-  }
   contents_->SetPreview(preview_container_, preview_contents);
   preview_container_->ChangeTabContents(preview_contents);
 
@@ -1486,7 +1484,8 @@
   ProcessTabSelected(new_contents, true);
 }
 
-void BrowserView::TabReplacedAt(TabContentsWrapper* old_contents,
+void BrowserView::TabReplacedAt(TabStripModel* tab_strip_model,
+                                TabContentsWrapper* old_contents,
                                 TabContentsWrapper* new_contents,
                                 int index) {
   if (index != browser_->tabstrip_model()->selected_index())
@@ -1513,7 +1512,7 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// BrowserView, menus::SimpleMenuModel::Delegate implementation:
+// BrowserView, ui::SimpleMenuModel::Delegate implementation:
 
 bool BrowserView::IsCommandIdChecked(int command_id) const {
   // TODO(beng): encoding menu.
@@ -1526,7 +1525,7 @@
 }
 
 bool BrowserView::GetAcceleratorForCommandId(int command_id,
-                                             menus::Accelerator* accelerator) {
+                                             ui::Accelerator* accelerator) {
   // Let's let the ToolbarView own the canonical implementation of this method.
   return toolbar_->GetAcceleratorForCommandId(command_id, accelerator);
 }
@@ -1692,7 +1691,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView, views::ClientView overrides:
 
-bool BrowserView::CanClose() const {
+bool BrowserView::CanClose() {
   // You cannot close a frame for which there is an active originating drag
   // session.
   if (tabstrip_->IsDragSessionActive())
@@ -1798,6 +1797,14 @@
 #endif
 }
 
+void BrowserView::PaintChildren(gfx::Canvas* canvas) {
+  views::ClientView::PaintChildren(canvas);
+
+  infobar_container_->PaintInfoBarArrows(canvas->AsCanvasSkia(),
+                                         this,
+                                         GetInfoBarArrowCenterX());
+}
+
 void BrowserView::ViewHierarchyChanged(bool is_add,
                                        views::View* parent,
                                        views::View* child) {
@@ -1815,45 +1822,16 @@
   return AccessibilityTypes::ROLE_CLIENT;
 }
 
-void BrowserView::InfoBarSizeChanged(bool is_animating) {
+void BrowserView::InfoBarContainerSizeChanged(bool is_animating) {
   SelectedTabToolbarSizeChanged(is_animating);
 }
 
-void BrowserView::UpdateReservedContentsRect(
-    const TabContentsContainer* source) {
-  RenderWidgetHostView* render_widget_host_view =
-      source->tab_contents() ? source->tab_contents()->GetRenderWidgetHostView()
-                             : NULL;
-  if (!render_widget_host_view)
-    return;
-
-  gfx::Rect reserved_rect;
-
-  if (!frame_->GetWindow()->IsMaximized() &&
-      !frame_->GetWindow()->IsFullscreen()) {
-    gfx::Size resize_corner_size = ResizeCorner::GetSize();
-    if (!resize_corner_size.IsEmpty()) {
-      gfx::Point resize_corner_origin;
-      gfx::Rect bounds = GetLocalBounds(false);
-      resize_corner_origin.set_x(bounds.right() - resize_corner_size.width());
-      resize_corner_origin.set_y(bounds.bottom() - resize_corner_size.height());
-
-      View::ConvertPointToView(this, source, &resize_corner_origin);
-
-      gfx::Size container_size = source->size();
-
-      if (resize_corner_origin.x() < container_size.width() &&
-          resize_corner_origin.y() < container_size.height()) {
-        reserved_rect = gfx::Rect(resize_corner_origin, resize_corner_size);
-      }
-    }
-  }
-
-  // TODO(alekseys): for source == contents_container_, consult SidebarTabView
-  // for the current size to reserve. Something like this:
-  // reserved_rect = reserved_rect.Union(SidebarTabView::GetCurrentBounds());
-
-  render_widget_host_view->set_reserved_contents_rect(reserved_rect);
+bool BrowserView::SplitHandleMoved(views::SingleSplitView* view) {
+  for (int i = 0; i < view->child_count(); ++i)
+    view->GetChildViewAt(i)->InvalidateLayout();
+  SchedulePaint();
+  Layout();
+  return false;
 }
 
 views::LayoutManager* BrowserView::CreateLayoutManager() const {
@@ -1863,20 +1841,15 @@
 void BrowserView::InitTabStrip(TabStripModel* model) {
   // Throw away the existing tabstrip if we're switching display modes.
   scoped_ptr<BaseTabStrip> old_strip(tabstrip_);
-  if (tabstrip_) {
-    tabstrip_->GetParent()->RemoveChildView(tabstrip_);
-  }
+  if (tabstrip_)
+    tabstrip_->parent()->RemoveChildView(tabstrip_);
 
   BrowserTabStripController* tabstrip_controller =
       new BrowserTabStripController(browser_.get(), model);
 
-  if (UseVerticalTabs())
-    tabstrip_ = new SideTabStrip(tabstrip_controller);
-  else
-    tabstrip_ = new TabStrip(tabstrip_controller);
+  tabstrip_ = CreateTabStrip(tabstrip_controller, UseVerticalTabs());
 
-  tabstrip_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_TABSTRIP)));
+  tabstrip_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_TABSTRIP));
   AddChildView(tabstrip_);
 
   tabstrip_controller->InitFromModel(tabstrip_);
@@ -1886,14 +1859,16 @@
 // BrowserView, private:
 
 void BrowserView::Init() {
-  accessible_view_helper_.reset(new AccessibleViewHelper(
-      this, browser_->profile()));
-
   SetLayoutManager(CreateLayoutManager());
-  // Stow a pointer to this object onto the window handle so that we can get
-  // at it later when all we have is a native view.
+  // Stow a pointer to this object onto the window handle so that we can get at
+  // it later when all we have is a native view.
   GetWidget()->SetNativeWindowProperty(kBrowserViewKey, this);
 
+  // Stow a pointer to the browser's profile onto the window handle so that we
+  // can get it later when all we have is a native view.
+  GetWindow()->SetNativeWindowProperty(Profile::kProfileKey,
+                                       browser_->profile());
+
   // Start a hung plugin window detector for this browser object (as long as
   // hang detection is not disabled).
   if (!CommandLine::ForCurrentProcess()->HasSwitch(
@@ -1902,21 +1877,19 @@
   }
 
   LoadAccelerators();
-  SetAccessibleName(UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+  SetAccessibleName(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
 
   InitTabStrip(browser_->tabstrip_model());
 
   toolbar_ = new ToolbarView(browser_.get());
   AddChildView(toolbar_);
   toolbar_->Init(browser_->profile());
-  toolbar_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLBAR)));
+  toolbar_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLBAR));
 
   infobar_container_ = new InfoBarContainer(this);
   AddChildView(infobar_container_);
 
   contents_container_ = new TabContentsContainer;
-  contents_container_->set_reserved_area_delegate(this);
   contents_ = new ContentsContainer(contents_container_);
 
   SkColor bg_color = GetWidget()->GetThemeProvider()->
@@ -1925,23 +1898,22 @@
   bool sidebar_allowed = SidebarManager::IsSidebarAllowed();
   if (sidebar_allowed) {
     sidebar_container_ = new TabContentsContainer;
-    sidebar_container_->set_reserved_area_delegate(this);
     sidebar_container_->SetID(VIEW_ID_SIDE_BAR_CONTAINER);
     sidebar_container_->SetVisible(false);
 
     sidebar_split_ = new views::SingleSplitView(
         contents_,
         sidebar_container_,
-        views::SingleSplitView::HORIZONTAL_SPLIT);
+        views::SingleSplitView::HORIZONTAL_SPLIT,
+        this);
     sidebar_split_->SetID(VIEW_ID_SIDE_BAR_SPLIT);
     sidebar_split_->SetAccessibleName(
-        UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_SIDE_BAR)));
+        l10n_util::GetStringUTF16(IDS_ACCNAME_SIDE_BAR));
     sidebar_split_->set_background(
         views::Background::CreateSolidBackground(bg_color));
   }
 
   devtools_container_ = new TabContentsContainer;
-  devtools_container_->set_reserved_area_delegate(this);
   devtools_container_->SetID(VIEW_ID_DEV_TOOLS_DOCKED);
   devtools_container_->SetVisible(false);
 
@@ -1952,10 +1924,11 @@
   contents_split_ = new views::SingleSplitView(
       contents_view,
       devtools_container_,
-      views::SingleSplitView::VERTICAL_SPLIT);
+      views::SingleSplitView::VERTICAL_SPLIT,
+      this);
   contents_split_->SetID(VIEW_ID_CONTENTS_SPLIT);
   contents_split_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_WEB_CONTENTS)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_WEB_CONTENTS));
   contents_split_->set_background(
       views::Background::CreateSolidBackground(bg_color));
   AddChildView(contents_split_);
@@ -2000,6 +1973,15 @@
 }
 #endif
 
+int BrowserView::GetInfoBarArrowCenterX() const {
+  const LocationIconView* location_icon_view =
+      toolbar_->location_bar()->location_icon_view();
+  gfx::Rect icon_bounds = location_icon_view->GetLocalBounds();
+  gfx::Point icon_center = icon_bounds.CenterPoint();
+  ConvertPointToView(location_icon_view, this, &icon_center);
+  return icon_center.x();
+}
+
 BrowserViewLayout* BrowserView::GetBrowserViewLayout() const {
   return static_cast<BrowserViewLayout*>(GetLayoutManager());
 }
@@ -2034,7 +2016,7 @@
     }
     bookmark_bar_view_->SetPageNavigator(contents->tab_contents());
     bookmark_bar_view_->SetAccessibleName(
-        UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS)));
+        l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS));
     new_bookmark_bar_view = bookmark_bar_view_.get();
   }
   return UpdateChildViewAndLayout(new_bookmark_bar_view, &active_bookmark_bar_);
@@ -2096,7 +2078,8 @@
         sidebar_split_->width() - sidebar_width);
 
     sidebar_container_->SetVisible(true);
-    sidebar_split_->Layout();
+    sidebar_split_->InvalidateLayout();
+    Layout();
   } else if (should_hide) {
     // Store split offset when hiding sidebar only.
     g_browser_process->local_state()->SetInteger(
@@ -2104,7 +2087,8 @@
         sidebar_split_->width() - sidebar_split_->divider_offset());
 
     sidebar_container_->SetVisible(false);
-    sidebar_split_->Layout();
+    sidebar_split_->InvalidateLayout();
+    Layout();
   }
 }
 
@@ -2128,8 +2112,8 @@
     }
 
     // Restore split offset.
-    int split_offset = g_browser_process->local_state()->GetInteger(
-        prefs::kDevToolsSplitLocation);
+    int split_offset = browser_->profile()->GetPrefs()->
+        GetInteger(prefs::kDevToolsSplitLocation);
     if (split_offset == -1) {
       // Initial load, set to default value.
       split_offset = 2 * contents_split_->height() / 3;
@@ -2141,17 +2125,19 @@
     contents_split_->set_divider_offset(split_offset);
 
     devtools_container_->SetVisible(true);
-    contents_split_->Layout();
+    contents_split_->InvalidateLayout();
+    Layout();
   } else if (should_hide) {
     // Store split offset when hiding devtools window only.
-    g_browser_process->local_state()->SetInteger(
-        prefs::kDevToolsSplitLocation, contents_split_->divider_offset());
+    browser_->profile()->GetPrefs()->SetInteger(prefs::kDevToolsSplitLocation,
+        contents_split_->divider_offset());
 
     // Restore focus to the last focused view when hiding devtools window.
     devtools_focus_tracker_->FocusLastFocusedExternalView();
 
     devtools_container_->SetVisible(false);
-    contents_split_->Layout();
+    contents_split_->InvalidateLayout();
+    Layout();
   }
 }
 
@@ -2196,7 +2182,7 @@
   } else if (new_view && *old_view) {
     // The view changed, but the new view wants the same size, give it the
     // bounds of the last view and have it repaint.
-    new_view->SetBounds((*old_view)->bounds());
+    new_view->SetBoundsRect((*old_view)->bounds());
     new_view->SchedulePaint();
   } else if (new_view) {
     DCHECK_EQ(0, new_height);
@@ -2311,7 +2297,7 @@
     bool ctrl_down = (accelerators[i].fVirt & FCONTROL) == FCONTROL;
     bool shift_down = (accelerators[i].fVirt & FSHIFT) == FSHIFT;
     views::Accelerator accelerator(
-        static_cast<app::KeyboardCode>(accelerators[i].key),
+        static_cast<ui::KeyboardCode>(accelerators[i].key),
         shift_down, ctrl_down, alt_down);
     accelerator_table_[accelerator] = accelerators[i].cmd;
 
@@ -2423,6 +2409,13 @@
 }
 
 void BrowserView::LoadingAnimationCallback() {
+  base::TimeTicks now = base::TimeTicks::Now();
+  if (!last_animation_time_.is_null()) {
+    UMA_HISTOGRAM_TIMES(
+        "Tabs.LoadingAnimationTime",
+        now - last_animation_time_);
+  }
+  last_animation_time_ = now;
   if (browser_->type() == Browser::TYPE_NORMAL) {
     // Loading animations are shown in the tab for tabbed windows.  We check the
     // browser type instead of calling IsTabStripVisible() because the latter
@@ -2470,53 +2463,53 @@
 #if defined(OS_CHROMEOS)
   // Collect information about the relative popularity of various accelerators
   // on Chrome OS.
-  const app::KeyboardCode key_code = accelerator.GetKeyCode();
+  const ui::KeyboardCode key_code = accelerator.GetKeyCode();
   switch (command_id) {
     case IDC_BACK:
-      if (key_code == app::VKEY_BACK)
+      if (key_code == ui::VKEY_BACK)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Back_Backspace"));
-      else if (key_code == app::VKEY_F1)
+      else if (key_code == ui::VKEY_F1)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Back_F1"));
-      else if (key_code == app::VKEY_LEFT)
+      else if (key_code == ui::VKEY_LEFT)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Back_Left"));
       break;
     case IDC_FORWARD:
-      if (key_code == app::VKEY_BACK)
+      if (key_code == ui::VKEY_BACK)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Forward_Backspace"));
-      else if (key_code == app::VKEY_F2)
+      else if (key_code == ui::VKEY_F2)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Forward_F2"));
-      else if (key_code == app::VKEY_LEFT)
+      else if (key_code == ui::VKEY_RIGHT)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Forward_Right"));
       break;
     case IDC_RELOAD:
     case IDC_RELOAD_IGNORING_CACHE:
-      if (key_code == app::VKEY_R)
+      if (key_code == ui::VKEY_R)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Reload_R"));
-      else if (key_code == app::VKEY_F3)
+      else if (key_code == ui::VKEY_F3)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Reload_F3"));
       break;
     case IDC_FULLSCREEN:
-      if (key_code == app::VKEY_F4)
+      if (key_code == ui::VKEY_F4)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Fullscreen_F4"));
       break;
     case IDC_NEW_TAB:
-      if (key_code == app::VKEY_T)
+      if (key_code == ui::VKEY_T)
         UserMetrics::RecordAction(UserMetricsAction("Accel_NewTab_T"));
       break;
     case IDC_SEARCH:
-      if (key_code == app::VKEY_LWIN)
+      if (key_code == ui::VKEY_LWIN)
         UserMetrics::RecordAction(UserMetricsAction("Accel_Search_LWin"));
       break;
     case IDC_FOCUS_LOCATION:
-      if (key_code == app::VKEY_D)
+      if (key_code == ui::VKEY_D)
         UserMetrics::RecordAction(UserMetricsAction("Accel_FocusLocation_D"));
-      else if (key_code == app::VKEY_L)
+      else if (key_code == ui::VKEY_L)
         UserMetrics::RecordAction(UserMetricsAction("Accel_FocusLocation_L"));
       break;
     case IDC_FOCUS_SEARCH:
-      if (key_code == app::VKEY_E)
+      if (key_code == ui::VKEY_E)
         UserMetrics::RecordAction(UserMetricsAction("Accel_FocusSearch_E"));
-      else if (key_code == app::VKEY_K)
+      else if (key_code == ui::VKEY_K)
         UserMetrics::RecordAction(UserMetricsAction("Accel_FocusSearch_K"));
       break;
     default:
@@ -2557,8 +2550,12 @@
 
   // Update all the UI bits.
   UpdateTitleBar();
-  UpdateToolbar(new_contents, true);
-  UpdateUIForContents(new_contents);
+  // No need to update Toolbar because it's already updated in
+  // browser.cc.
+}
+
+gfx::Size BrowserView::GetResizeCornerSize() const {
+  return ResizeCorner::GetSize();
 }
 
 #if !defined(OS_CHROMEOS)
@@ -2570,7 +2567,7 @@
   BrowserFrame::Create(view, browser->profile());
 
   view->GetWindow()->GetNonClientView()->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
 
   return view;
 }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 645b425..1610d80 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,22 +10,23 @@
 #include <string>
 #include <vector>
 
-#include "app/menus/simple_menu_model.h"
 #include "base/scoped_ptr.h"
 #include "base/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/frame/browser_bubble_host.h"
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/infobars/infobar_container.h"
-#include "chrome/browser/views/tab_contents/tab_contents_container.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
-#include "chrome/browser/views/tabs/base_tab_strip.h"
-#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
+#include "chrome/browser/ui/views/frame/browser_bubble_host.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/infobars/infobar_container.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
+#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/native_widget_types.h"
+#include "views/controls/single_split_view.h"
 #include "views/window/client_view.h"
 #include "views/window/window_delegate.h"
 
@@ -39,7 +40,6 @@
 // view: http://dev.chromium.org/developers/design-documents/browser-window
 
 class AccessiblePaneView;
-class AccessibleViewHelper;
 class BookmarkBarView;
 class Browser;
 class BrowserBubble;
@@ -53,6 +53,7 @@
 class LocationBarView;
 class SideTabStrip;
 class StatusBubbleViews;
+class TabContentsContainer;
 class TabStripModel;
 class ToolbarView;
 class ZoomMenuModel;
@@ -66,7 +67,6 @@
 namespace views {
 class ExternalFocusTracker;
 class Menu;
-class SingleSplitView;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -80,11 +80,11 @@
                     public BrowserWindowTesting,
                     public NotificationObserver,
                     public TabStripModelObserver,
-                    public menus::SimpleMenuModel::Delegate,
+                    public ui::SimpleMenuModel::Delegate,
                     public views::WindowDelegate,
                     public views::ClientView,
                     public InfoBarContainer::Delegate,
-                    public TabContentsContainer::ReservedAreaDelegate {
+                    public views::SingleSplitView::Observer {
  public:
   // The browser view's class name.
   static const char kViewClassName[];
@@ -177,7 +177,7 @@
   // command id. This can be used to provide menu item shortcut hints etc.
   // Returns true if an accelerator was found for the specified |cmd_id|, false
   // otherwise.
-  bool GetAccelerator(int cmd_id, menus::Accelerator* accelerator);
+  bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator);
 
   // Shows the next app-modal dialog box, if there is one to be shown, or moves
   // an existing showing one to the front. Returns true if one was shown or
@@ -259,6 +259,7 @@
   virtual void UpdateLoadingAnimations(bool should_animate);
   virtual void SetStarredState(bool is_starred);
   virtual gfx::Rect GetRestoredBounds() const;
+  virtual gfx::Rect GetBounds() const;
   virtual bool IsMaximized() const;
   virtual void SetFullscreen(bool fullscreen);
   virtual bool IsFullscreen() const;
@@ -288,11 +289,11 @@
   virtual views::Window* ShowAboutChromeDialog();
   virtual void ShowUpdateChromeDialog();
   virtual void ShowTaskManager();
+  virtual void ShowBackgroundPages();
   virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
   virtual void SetDownloadShelfVisible(bool visible);
   virtual bool IsDownloadShelfVisible() const;
   virtual DownloadShelf* GetDownloadShelf();
-  virtual void ShowReportBugDialog();
   virtual void ShowClearBrowsingDataDialog();
   virtual void ShowImportDialog();
   virtual void ShowSearchEnginesDialog();
@@ -328,6 +329,7 @@
   virtual void ShowInstant(TabContents* preview_contents);
   virtual void HideInstant(bool instant_is_active);
   virtual gfx::Rect GetInstantBounds();
+
 #if defined(OS_CHROMEOS)
   virtual void ShowKeyboardOverlay(gfx::NativeWindow owning_window);
 #endif
@@ -351,16 +353,17 @@
                              TabContentsWrapper* new_contents,
                              int index,
                              bool user_gesture);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int index);
   virtual void TabStripEmpty();
 
-  // Overridden from menus::SimpleMenuModel::Delegate:
+  // Overridden from ui::SimpleMenuModel::Delegate:
   virtual bool IsCommandIdChecked(int command_id) const;
   virtual bool IsCommandIdEnabled(int command_id) const;
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
   virtual bool IsItemForCommandIdDynamic(int command_id) const;
   virtual string16 GetLabelForCommandId(int command_id) const;
   virtual void ExecuteCommand(int command_id);
@@ -386,15 +389,15 @@
   virtual views::ClientView* CreateClientView(views::Window* window);
 
   // Overridden from views::ClientView:
-  virtual bool CanClose() const;
+  virtual bool CanClose();
   virtual int NonClientHitTest(const gfx::Point& point);
   virtual gfx::Size GetMinimumSize();
 
   // InfoBarContainer::Delegate overrides
-  virtual void InfoBarSizeChanged(bool is_animating);
+  virtual void InfoBarContainerSizeChanged(bool is_animating);
 
-  // TabContentsContainer::ReservedAreaDelegate overrides.
-  virtual void UpdateReservedContentsRect(const TabContentsContainer* source);
+  // views::SingleSplitView::Observer overrides:
+  virtual bool SplitHandleMoved(views::SingleSplitView* view);
 
  protected:
   // Appends to |toolbars| a pointer to each AccessiblePaneView that
@@ -413,6 +416,7 @@
   // Overridden from views::View:
   virtual std::string GetClassName() const;
   virtual void Layout();
+  virtual void PaintChildren(gfx::Canvas* canvas);
   virtual void ViewHierarchyChanged(bool is_add,
                                     views::View* parent,
                                     views::View* child);
@@ -440,6 +444,11 @@
   void InitSystemMenu();
 #endif
 
+  // Get the X value, in this BrowserView's coordinate system, where
+  // the points of the infobar arrows should be anchored.  This is the
+  // center of the omnibox location icon.
+  int GetInfoBarArrowCenterX() const;
+
   // Returns the BrowserViewLayout.
   BrowserViewLayout* GetBrowserViewLayout() const;
 
@@ -519,6 +528,9 @@
   void ProcessTabSelected(TabContentsWrapper* new_contents,
                           bool change_tab_contents);
 
+  // Exposes resize corner size to BrowserViewLayout.
+  gfx::Size GetResizeCornerSize() const;
+
   // Last focused view that issued a tab traversal.
   int last_focused_view_storage_id_;
 
@@ -663,10 +675,11 @@
 
   UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
 
-  scoped_ptr<AccessibleViewHelper> accessible_view_helper_;
-
   NotificationRegistrar registrar_;
 
+  // Used to measure the loading spinner animation rate.
+  base::TimeTicks last_animation_time_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserView);
 };
 
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 914f202..2429088 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/browser_view_layout.h"
+#include "chrome/browser/ui/views/frame/browser_view_layout.h"
 
 #include "chrome/browser/sidebar/sidebar_manager.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
@@ -13,10 +13,14 @@
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/contents_container.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
 #include "chrome/browser/ui/views/tabs/side_tab_strip.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/toolbar_view.h"
-#include "gfx/scrollbar_size.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/scrollbar_size.h"
+#include "ui/gfx/size.h"
+#include "views/controls/single_split_view.h"
 #include "views/window/window.h"
 
 #if defined(OS_LINUX)
@@ -51,6 +55,9 @@
       find_bar_y_(0) {
 }
 
+BrowserViewLayout::~BrowserViewLayout() {
+}
+
 gfx::Size BrowserViewLayout::GetMinimumSize() {
   // TODO(noname): In theory the tabstrip width should probably be
   // (OTR + tabstrip + caption buttons) width.
@@ -128,7 +135,7 @@
   // area of the window. So we need to treat hit-tests in these regions as
   // hit-tests of the titlebar.
 
-  views::View* parent = browser_view_->GetParent();
+  views::View* parent = browser_view_->parent();
 
   gfx::Point point_in_browser_view_coords(point);
   views::View::ConvertPointToView(
@@ -207,9 +214,9 @@
 void BrowserViewLayout::ViewAdded(views::View* host, views::View* view) {
   switch (view->GetID()) {
     case VIEW_ID_CONTENTS_SPLIT: {
-      contents_split_ = view;
+      contents_split_ = static_cast<views::SingleSplitView*>(view);
       // We're installed as the LayoutManager before BrowserView creates the
-      // contents, so we have to set contents_container_ here rather than
+      // contents, so we have to set contents_container_ here rather than in
       // Installed.
       contents_container_ = browser_view_->contents_;
       break;
@@ -241,11 +248,11 @@
 }
 
 void BrowserViewLayout::Layout(views::View* host) {
-  vertical_layout_rect_ = browser_view_->GetLocalBounds(true);
+  vertical_layout_rect_ = browser_view_->GetLocalBounds();
   int top = LayoutTabStrip();
   if (browser_view_->IsTabStripVisible() && !browser_view_->UseVerticalTabs()) {
     tabstrip_->SetBackgroundOffset(gfx::Point(
-        tabstrip_->MirroredX() + browser_view_->MirroredX(),
+        tabstrip_->GetMirroredX() + browser_view_->GetMirroredX(),
         browser_view_->frame()->GetHorizontalTabStripVerticalOffset(false)));
   }
   top = LayoutToolbar(top);
@@ -292,7 +299,7 @@
   gfx::Rect tabstrip_bounds(
       browser_view_->frame()->GetBoundsForTabStrip(tabstrip_));
   gfx::Point tabstrip_origin(tabstrip_bounds.origin());
-  views::View::ConvertPointToView(browser_view_->GetParent(), browser_view_,
+  views::View::ConvertPointToView(browser_view_->parent(), browser_view_,
                                   &tabstrip_origin);
   tabstrip_bounds.set_origin(tabstrip_origin);
 
@@ -300,7 +307,7 @@
     vertical_layout_rect_.Inset(tabstrip_bounds.width(), 0, 0, 0);
 
   tabstrip_->SetVisible(true);
-  tabstrip_->SetBounds(tabstrip_bounds);
+  tabstrip_->SetBoundsRect(tabstrip_bounds);
   return browser_view_->UseVerticalTabs() ?
       tabstrip_bounds.y() : tabstrip_bounds.bottom();
 }
@@ -363,9 +370,112 @@
   return top + height;
 }
 
+// |browser_reserved_rect| is in browser_view_ coordinates.
+// |future_source_bounds| is in |source|'s parent coordinates.
+// |future_parent_offset| is required, since parent view is not moved yet.
+// Note that |future_parent_offset| is relative to browser_view_, not to
+// the parent view.
+void BrowserViewLayout::UpdateReservedContentsRect(
+    const gfx::Rect& browser_reserved_rect,
+    TabContentsContainer* source,
+    const gfx::Rect& future_source_bounds,
+    const gfx::Point& future_parent_offset) {
+  gfx::Point resize_corner_origin(browser_reserved_rect.origin());
+  // Convert |resize_corner_origin| from browser_view_ to source's parent
+  // coordinates.
+  views::View::ConvertPointToView(browser_view_, source->parent(),
+                                  &resize_corner_origin);
+  // Create |reserved_rect| in source's parent coordinates.
+  gfx::Rect reserved_rect(resize_corner_origin, browser_reserved_rect.size());
+  // Apply source's parent future offset to it.
+  reserved_rect.Offset(-future_parent_offset.x(), -future_parent_offset.y());
+  if (future_source_bounds.Intersects(reserved_rect)) {
+    // |source| is not properly positioned yet to use ConvertPointToView,
+    // so convert it into |source|'s coordinates manually.
+    reserved_rect.Offset(-future_source_bounds.x(), -future_source_bounds.y());
+  } else {
+    reserved_rect = gfx::Rect();
+  }
+
+  source->SetReservedContentsRect(reserved_rect);
+}
+
 void BrowserViewLayout::LayoutTabContents(int top, int bottom) {
-  contents_split_->SetBounds(vertical_layout_rect_.x(), top,
-                             vertical_layout_rect_.width(), bottom - top);
+  // The ultimate idea is to calcualte bounds and reserved areas for all
+  // contents views first and then resize them all, so every view
+  // (and its contents) is resized and laid out only once.
+
+  // The views hierarcy (see browser_view.h for more details):
+  // 1) Sidebar is not allowed:
+  //     contents_split_ -> [contents_container_ | devtools]
+  // 2) Sidebar is allowed:
+  //     contents_split_ ->
+  //         [sidebar_split -> [contents_container_ | sidebar]] | devtools
+
+  gfx::Rect sidebar_split_bounds;
+  gfx::Rect contents_bounds;
+  gfx::Rect sidebar_bounds;
+  gfx::Rect devtools_bounds;
+
+  gfx::Rect contents_split_bounds(vertical_layout_rect_.x(), top,
+                                  vertical_layout_rect_.width(),
+                                  std::max(0, bottom - top));
+  contents_split_->CalculateChildrenBounds(
+      contents_split_bounds, &sidebar_split_bounds, &devtools_bounds);
+  gfx::Point contents_split_offset(
+      contents_split_bounds.x() - contents_split_->bounds().x(),
+      contents_split_bounds.y() - contents_split_->bounds().y());
+  gfx::Point sidebar_split_offset(contents_split_offset);
+  sidebar_split_offset.Offset(sidebar_split_bounds.x(),
+                              sidebar_split_bounds.y());
+
+  views::SingleSplitView* sidebar_split = browser_view_->sidebar_split_;
+  if (sidebar_split) {
+    DCHECK(sidebar_split == contents_split_->GetChildViewAt(0));
+    sidebar_split->CalculateChildrenBounds(
+        sidebar_split_bounds, &contents_bounds, &sidebar_bounds);
+  } else {
+    contents_bounds = sidebar_split_bounds;
+  }
+
+  // Layout resize corner, sidebar mini tabs and calculate reserved contents
+  // rects here as all contents view bounds are already determined, but not yet
+  // set at this point, so contents will be laid out once at most.
+  // TODO(alekseys): layout sidebar minitabs and adjust reserved rect
+  // accordingly.
+  gfx::Rect browser_reserved_rect;
+  if (!browser_view_->frame_->GetWindow()->IsMaximized() &&
+      !browser_view_->frame_->GetWindow()->IsFullscreen()) {
+    gfx::Size resize_corner_size = browser_view_->GetResizeCornerSize();
+    if (!resize_corner_size.IsEmpty()) {
+      gfx::Rect bounds = browser_view_->GetContentsBounds();
+      gfx::Point resize_corner_origin(
+          bounds.right() - resize_corner_size.width(),
+          bounds.bottom() - resize_corner_size.height());
+      browser_reserved_rect =
+          gfx::Rect(resize_corner_origin, resize_corner_size);
+    }
+  }
+
+  UpdateReservedContentsRect(browser_reserved_rect,
+                             browser_view_->contents_container_,
+                             contents_bounds,
+                             sidebar_split_offset);
+  if (sidebar_split) {
+    UpdateReservedContentsRect(browser_reserved_rect,
+                               browser_view_->sidebar_container_,
+                               sidebar_bounds,
+                               sidebar_split_offset);
+  }
+  UpdateReservedContentsRect(browser_reserved_rect,
+                             browser_view_->devtools_container_,
+                             devtools_bounds,
+                             contents_split_offset);
+
+  // Now it's safe to actually resize all contents views in the hierarchy.
+  contents_split_->SetBoundsRect(contents_split_bounds);
+  if (sidebar_split)
+    sidebar_split->SetBoundsRect(sidebar_split_bounds);
 }
 
 int BrowserViewLayout::GetTopMarginForActiveContent() {
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.h b/chrome/browser/ui/views/frame/browser_view_layout.h
index 279803c..e5049fd 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.h
+++ b/chrome/browser/ui/views/frame/browser_view_layout.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,9 @@
 #define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
 #pragma once
 
-#include "views/layout_manager.h"
+#include "base/basictypes.h"
+#include "ui/gfx/rect.h"
+#include "views/layout/layout_manager.h"
 
 class BaseTabStrip;
 class BookmarkBarView;
@@ -14,13 +16,23 @@
 class BrowserView;
 class ContentsContainer;
 class DownloadShelfView;
+class TabContentsContainer;
 class ToolbarView;
 
+namespace gfx {
+class Point;
+class Size;
+}
+
+namespace views {
+class SingleSplitView;
+}
+
 // The layout manager used in chrome browser.
 class BrowserViewLayout : public views::LayoutManager {
  public:
   BrowserViewLayout();
-  virtual ~BrowserViewLayout() {}
+  virtual ~BrowserViewLayout();
 
   // Returns the minimum size of the browser view.
   virtual gfx::Size GetMinimumSize();
@@ -61,6 +73,15 @@
   int LayoutBookmarkBar(int top);
   int LayoutInfoBar(int top);
 
+  // Updates |source|'s reserved contents rect by mapping BrowserView's
+  // |browser_reserved_rect| into |future_source_bounds| taking into
+  // account |source|'s |future_parent_offset| (offset is relative to
+  // browser_view_).
+  void UpdateReservedContentsRect(const gfx::Rect& browser_reserved_rect,
+                                  TabContentsContainer* source,
+                                  const gfx::Rect& future_source_bounds,
+                                  const gfx::Point& future_parent_offset);
+
   // Layout the TabContents container, between the coordinates |top| and
   // |bottom|.
   void LayoutTabContents(int top, int bottom);
@@ -88,7 +109,7 @@
   // Child views that the layout manager manages.
   BaseTabStrip* tabstrip_;
   ToolbarView* toolbar_;
-  views::View* contents_split_;
+  views::SingleSplitView* contents_split_;
   ContentsContainer* contents_container_;
   views::View* infobar_container_;
   DownloadShelfView* download_shelf_;
@@ -109,4 +130,3 @@
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
-
diff --git a/chrome/browser/ui/views/frame/contents_container.cc b/chrome/browser/ui/views/frame/contents_container.cc
index 1c8abfd..f35ac74 100644
--- a/chrome/browser/ui/views/frame/contents_container.cc
+++ b/chrome/browser/ui/views/frame/contents_container.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/contents_container.h"
+#include "chrome/browser/ui/views/frame/contents_container.h"
 
 #include "base/logging.h"
 #include "third_party/skia/include/core/SkColor.h"
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index fdc1956..1901ae7 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -1,22 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/glass_browser_frame_view.h"
+#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h"
 
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/chrome_dll_resource.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/side_tab_strip.h"
-#include "chrome/browser/views/tabs/tab.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/icon_util.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/tabs/side_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/icon_util.h"
 #include "views/window/client_view.h"
 #include "views/window/window_resources.h"
 
@@ -77,14 +77,15 @@
 // GlassBrowserFrameView, BrowserNonClientFrameView implementation:
 
 gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
-    BaseTabStrip* tabstrip) const {
+    views::View* tabstrip) const {
   if (browser_view_->UseVerticalTabs()) {
     gfx::Size ps = tabstrip->GetPreferredSize();
     return gfx::Rect(NonClientBorderThickness(),
         NonClientTopBorderHeight(false, false), ps.width(),
         browser_view_->height());
   }
-  int minimize_button_offset = frame_->GetMinimizeButtonOffset();
+  int minimize_button_offset =
+      std::min(frame_->GetMinimizeButtonOffset(), width());
   int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ?
       (otr_avatar_bounds_.right() + kOTRSideSpacing) :
       NonClientBorderThickness();
@@ -104,7 +105,7 @@
           kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing);
   return gfx::Rect(tabstrip_x, GetHorizontalTabStripVerticalOffset(false),
                    std::max(0, tabstrip_width),
-                   tabstrip->GetPreferredHeight());
+                   tabstrip->GetPreferredSize().height());
 }
 
 int GlassBrowserFrameView::GetHorizontalTabStripVerticalOffset(
@@ -243,7 +244,7 @@
 }
 
 void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
 
   gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds());
   gfx::Point toolbar_origin(toolbar_bounds.origin());
@@ -360,7 +361,7 @@
 }
 
 void GlassBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
   gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height());
 
   // The client edges start below the toolbar upper corner images regardless
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
index c191568..4086ea2 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/frame/browser_frame_win.h"
-#include "chrome/browser/views/frame/browser_non_client_frame_view.h"
+#include "chrome/browser/ui/views/frame/browser_frame_win.h"
+#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "views/controls/button/button.h"
 #include "views/window/non_client_view.h"
 
@@ -21,7 +21,7 @@
   virtual ~GlassBrowserFrameView();
 
   // Overridden from BrowserNonClientFrameView:
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const;
   virtual int GetHorizontalTabStripVerticalOffset(bool restored) const;
   virtual void UpdateThrobber(bool running);
 
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 0704ebd..c6e7f34 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -1,27 +1,27 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/opaque_browser_frame_view.h"
+#include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
 #include "base/compiler_specific.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
-#include "chrome/browser/views/toolbar_view.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/font.h"
-#include "gfx/path.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/path.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/image_view.h"
 #include "views/widget/root_view.h"
@@ -107,7 +107,7 @@
       window_icon_(NULL),
       frame_(frame),
       browser_view_(browser_view) {
-  ThemeProvider* tp = frame_->GetThemeProviderForFrame();
+  ui::ThemeProvider* tp = frame_->GetThemeProviderForFrame();
   SkColor color = tp->GetColor(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND);
   SkBitmap* background =
       tp->GetBitmapNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND);
@@ -122,7 +122,7 @@
         tp->GetBitmapNamed(IDR_MINIMIZE_BUTTON_MASK));
   }
   minimize_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_MINIMIZE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_MINIMIZE));
   AddChildView(minimize_button_);
 
   maximize_button_->SetImage(views::CustomButton::BS_NORMAL,
@@ -136,7 +136,7 @@
         tp->GetBitmapNamed(IDR_MAXIMIZE_BUTTON_MASK));
   }
   maximize_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_MAXIMIZE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_MAXIMIZE));
   AddChildView(maximize_button_);
 
   restore_button_->SetImage(views::CustomButton::BS_NORMAL,
@@ -150,7 +150,7 @@
         tp->GetBitmapNamed(IDR_RESTORE_BUTTON_MASK));
   }
   restore_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_RESTORE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_RESTORE));
   AddChildView(restore_button_);
 
   close_button_->SetImage(views::CustomButton::BS_NORMAL,
@@ -164,7 +164,7 @@
         tp->GetBitmapNamed(IDR_CLOSE_BUTTON_MASK));
   }
   close_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
   AddChildView(close_button_);
 
   // Initializing the TabIconView is expensive, so only do it if we need to.
@@ -199,7 +199,7 @@
 // OpaqueBrowserFrameView, BrowserNonClientFrameView implementation:
 
 gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip(
-    BaseTabStrip* tabstrip) const {
+    views::View* tabstrip) const {
   if (browser_view_->UseVerticalTabs()) {
     gfx::Size ps = tabstrip->GetPreferredSize();
     return gfx::Rect(NonClientBorderThickness(),
@@ -215,7 +215,8 @@
       (frame_->GetWindow()->IsMaximized() ?
       kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing);
   return gfx::Rect(tabstrip_x, GetHorizontalTabStripVerticalOffset(false),
-                   std::max(0, tabstrip_width), tabstrip->GetPreferredHeight());
+                   std::max(0, tabstrip_width),
+                   tabstrip->GetPreferredSize().height());
 }
 
 int OpaqueBrowserFrameView::GetHorizontalTabStripVerticalOffset(
@@ -291,7 +292,7 @@
   // of Fitts' Law.
   if (frame_->GetWindow()->IsMaximized())
     sysmenu_rect.SetRect(0, 0, sysmenu_rect.right(), sysmenu_rect.bottom());
-  sysmenu_rect.set_x(MirroredLeftPointForRect(sysmenu_rect));
+  sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect));
   if (sysmenu_rect.Contains(point))
     return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU;
 
@@ -300,19 +301,16 @@
 
   // Then see if the point is within any of the window controls.
   if (close_button_->IsVisible() &&
-      close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point))
+      close_button_->GetMirroredBounds().Contains(point))
     return HTCLOSE;
   if (restore_button_->IsVisible() &&
-      restore_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(
-      point))
+      restore_button_->GetMirroredBounds().Contains(point))
     return HTMAXBUTTON;
   if (maximize_button_->IsVisible() &&
-      maximize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(
-      point))
+      maximize_button_->GetMirroredBounds().Contains(point))
     return HTMAXBUTTON;
   if (minimize_button_->IsVisible() &&
-      minimize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(
-      point))
+      minimize_button_->GetMirroredBounds().Contains(point))
     return HTMINBUTTON;
 
   views::WindowDelegate* delegate = frame_->GetWindow()->GetDelegate();
@@ -398,7 +396,7 @@
   // completely. We need to do this since we're not a parent of the tabstrip,
   // meaning ConvertPointToView would otherwise return something bogus.
   gfx::Point browser_view_point(l);
-  View::ConvertPointToView(GetParent(), browser_view_, &browser_view_point);
+  View::ConvertPointToView(parent(), browser_view_, &browser_view_point);
   return browser_view_->IsPositionInWindowCaption(browser_view_point);
 }
 
@@ -541,7 +539,7 @@
 }
 
 void OpaqueBrowserFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
 
   SkBitmap* top_left_corner = tp->GetBitmapNamed(IDR_WINDOW_TOP_LEFT_CORNER);
   SkBitmap* top_right_corner =
@@ -659,7 +657,7 @@
 
 
 void OpaqueBrowserFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
   views::Window* window = frame_->GetWindow();
 
   // Window frame mode and color
@@ -712,9 +710,9 @@
     return;
   }
   if (delegate->ShouldShowWindowTitle()) {
-    canvas->DrawStringInt(delegate->GetWindowTitle(),
+    canvas->DrawStringInt(WideToUTF16Hack(delegate->GetWindowTitle()),
                           BrowserFrame::GetTitleFont(),
-        SK_ColorWHITE, MirroredLeftPointForRect(title_bounds_),
+        SK_ColorWHITE, GetMirroredXForRect(title_bounds_),
         title_bounds_.y(), title_bounds_.width(), title_bounds_.height());
     /* TODO(pkasting):  If this window is active, we should also draw a drop
      * shadow on the title.  This is tricky, because we don't want to hardcode a
@@ -752,7 +750,7 @@
   // section so that we never break the gradient.
   int split_point = kFrameShadowThickness * 2;
   int bottom_y = y + split_point;
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
   SkBitmap* toolbar_left = tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER);
   int bottom_edge_height = std::min(toolbar_left->height(), h) - split_point;
 
@@ -857,7 +855,7 @@
 }
 
 void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
   int client_area_top = frame_->GetWindow()->GetClientView()->y();
   int image_top = client_area_top;
 
@@ -1023,7 +1021,7 @@
   gfx::Rect icon_bounds(IconBounds());
   views::WindowDelegate* delegate = frame_->GetWindow()->GetDelegate();
   if (delegate && delegate->ShouldShowWindowIcon())
-    window_icon_->SetBounds(icon_bounds);
+    window_icon_->SetBoundsRect(icon_bounds);
 
   // Size the title, if visible.
   if (delegate && delegate->ShouldShowWindowTitle()) {
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
index 5d27f0c..baedea7 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_UI_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/frame/browser_non_client_frame_view.h"
-#include "chrome/browser/views/tab_icon_view.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
+#include "chrome/browser/ui/views/tab_icon_view.h"
 #include "views/controls/button/button.h"
 #include "views/window/non_client_view.h"
 
-class BaseTabStrip;
 class BrowserView;
 namespace gfx {
 class Font;
@@ -32,7 +31,7 @@
   virtual ~OpaqueBrowserFrameView();
 
   // Overridden from BrowserNonClientFrameView:
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const;
   virtual int GetHorizontalTabStripVerticalOffset(bool restored) const;
   virtual void UpdateThrobber(bool running);
   virtual gfx::Size GetMinimumSize();
diff --git a/chrome/browser/ui/views/frame/popup_non_client_frame_view.cc b/chrome/browser/ui/views/frame/popup_non_client_frame_view.cc
index dd76c86..bb9af66 100644
--- a/chrome/browser/ui/views/frame/popup_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/popup_non_client_frame_view.cc
@@ -1,13 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/frame/popup_non_client_frame_view.h"
+#include "chrome/browser/ui/views/frame/popup_non_client_frame_view.h"
 
-#include "chrome/browser/views/tabs/base_tab_strip.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 #if defined(OS_LINUX)
 #include "views/window/hit_test.h"
@@ -45,8 +44,8 @@
 }
 
 gfx::Rect PopupNonClientFrameView::GetBoundsForTabStrip(
-    BaseTabStrip* tabstrip) const {
-  return gfx::Rect(0, 0, width(), tabstrip->GetPreferredHeight());
+    views::View* tabstrip) const {
+  return gfx::Rect(0, 0, width(), tabstrip->GetPreferredSize().height());
 }
 
 int PopupNonClientFrameView::GetHorizontalTabStripVerticalOffset(
diff --git a/chrome/browser/ui/views/frame/popup_non_client_frame_view.h b/chrome/browser/ui/views/frame/popup_non_client_frame_view.h
index 95e13fc..891d1a2 100644
--- a/chrome/browser/ui/views/frame/popup_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/popup_non_client_frame_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_FRAME_POPUP_NON_CLIENT_FRAME_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/frame/browser_non_client_frame_view.h"
-
-class BaseTabStrip;
+#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 
 // BrowserNonClientFrameView implementation for popups. We let the window
 // manager implementation render the decorations for popups, so this draws
@@ -29,7 +27,7 @@
   virtual void ResetWindowControls();
 
   // BrowserNonClientFrameView:
-  virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
+  virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const;
   virtual int GetHorizontalTabStripVerticalOffset(bool restored) const;
   virtual void UpdateThrobber(bool running);
 
diff --git a/chrome/browser/ui/views/fullscreen_exit_bubble.cc b/chrome/browser/ui/views/fullscreen_exit_bubble.cc
index e94ed66..fc38f30 100644
--- a/chrome/browser/ui/views/fullscreen_exit_bubble.cc
+++ b/chrome/browser/ui/views/fullscreen_exit_bubble.cc
@@ -1,23 +1,23 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/fullscreen_exit_bubble.h"
+#include "chrome/browser/ui/views/fullscreen_exit_bubble.h"
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "gfx/canvas_skia.h"
 #include "grit/generated_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/screen.h"
 #include "views/widget/root_view.h"
 #include "views/window/window.h"
 
 #if defined(OS_WIN)
-#include "app/l10n_util_win.h"
+#include "ui/base/l10n/l10n_util_win.h"
 #include "views/widget/widget_win.h"
 #elif defined(OS_LINUX)
 #include "views/widget/widget_gtk.h"
@@ -147,10 +147,11 @@
   size_animation_->Reset(1);
 
   // Create the contents view.
-  views::Accelerator accelerator(app::VKEY_UNKNOWN, false, false, false);
+  views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false);
   bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
   DCHECK(got_accelerator);
-  view_ = new FullscreenExitView(this, accelerator.GetShortcutText());
+  view_ = new FullscreenExitView(
+      this, UTF16ToWideHack(accelerator.GetShortcutText()));
 
   // Initialize the popup.
 #if defined(OS_WIN)
diff --git a/chrome/browser/ui/views/generic_info_view.cc b/chrome/browser/ui/views/generic_info_view.cc
index 7eb6d90..644d960 100644
--- a/chrome/browser/ui/views/generic_info_view.cc
+++ b/chrome/browser/ui/views/generic_info_view.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/generic_info_view.h"
+#include "chrome/browser/ui/views/generic_info_view.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/color_utils.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 GenericInfoView::GenericInfoView(int number_of_rows)
     : number_of_rows_(number_of_rows), name_string_ids_(NULL) {
@@ -72,7 +72,7 @@
   views::ColumnSet* column_set = layout->AddColumnSet(kLayoutId);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -81,7 +81,7 @@
 
   for (int i = 0; i < number_of_rows_; ++i) {
     if (i)
-      layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+      layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
     name_views_[i] = new views::Label;
     value_views_[i] = new views::Textfield;
     AddRow(kLayoutId, layout, name_views_[i], value_views_[i]);
diff --git a/chrome/browser/ui/views/generic_info_view_unittest.cc b/chrome/browser/ui/views/generic_info_view_unittest.cc
index ba079f8..8f7cceb 100644
--- a/chrome/browser/ui/views/generic_info_view_unittest.cc
+++ b/chrome/browser/ui/views/generic_info_view_unittest.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/views/generic_info_view.h"
+#include "chrome/browser/ui/views/generic_info_view.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
 #include "views/widget/root_view.h"
diff --git a/chrome/browser/ui/views/html_dialog_view.cc b/chrome/browser/ui/views/html_dialog_view.cc
index 2cb5cb0..38e2797 100644
--- a/chrome/browser/ui/views/html_dialog_view.cc
+++ b/chrome/browser/ui/views/html_dialog_view.cc
@@ -1,14 +1,16 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/html_dialog_view.h"
+#include "chrome/browser/ui/views/html_dialog_view.h"
 
-#include "app/keyboard_codes.h"
+#include <vector>
+
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/native_web_keyboard_event.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -20,13 +22,14 @@
 namespace browser {
 
 // Declared in browser_dialogs.h so that others don't need to depend on our .h.
-void ShowHtmlDialogView(gfx::NativeWindow parent, Profile* profile,
-                        HtmlDialogUIDelegate* delegate) {
+gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile,
+                                 HtmlDialogUIDelegate* delegate) {
   HtmlDialogView* html_view =
       new HtmlDialogView(profile, delegate);
   browser::CreateViewsWindow(parent, gfx::Rect(), html_view);
   html_view->InitDialog();
   html_view->window()->Show();
+  return html_view->window()->GetNativeWindow();
 }
 
 }  // namespace browser
@@ -56,7 +59,7 @@
 
 bool HtmlDialogView::AcceleratorPressed(const views::Accelerator& accelerator) {
   // Pressing ESC closes the dialog.
-  DCHECK_EQ(app::VKEY_ESCAPE, accelerator.GetKeyCode());
+  DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.GetKeyCode());
   OnDialogClosed(std::string());
   return true;
 }
@@ -117,10 +120,10 @@
   return GURL();
 }
 
-void HtmlDialogView::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void HtmlDialogView::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   if (delegate_)
-    delegate_->GetDOMMessageHandlers(handlers);
+    delegate_->GetWebUIMessageHandlers(handlers);
 }
 
 void HtmlDialogView::GetDialogSize(gfx::Size* size) const {
@@ -214,7 +217,7 @@
                                                   this);
 
   // Pressing the ESC key will close the dialog.
-  AddAccelerator(views::Accelerator(app::VKEY_ESCAPE, false, false, false));
+  AddAccelerator(views::Accelerator(ui::VKEY_ESCAPE, false, false, false));
 
   DOMView::LoadURL(GetDialogContentURL());
 }
diff --git a/chrome/browser/ui/views/html_dialog_view.h b/chrome/browser/ui/views/html_dialog_view.h
index 5706c68..dc8bf7c 100644
--- a/chrome/browser/ui/views/html_dialog_view.h
+++ b/chrome/browser/ui/views/html_dialog_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,8 +10,8 @@
 
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h"
-#include "chrome/browser/views/dom_view.h"
-#include "gfx/size.h"
+#include "chrome/browser/ui/views/dom_view.h"
+#include "ui/gfx/size.h"
 #include "views/window/window_delegate.h"
 
 class Browser;
@@ -61,8 +61,8 @@
   virtual bool IsDialogModal() const;
   virtual std::wstring GetDialogTitle() const;
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
diff --git a/chrome/browser/ui/views/html_dialog_view_browsertest.cc b/chrome/browser/ui/views/html_dialog_view_browsertest.cc
index a230922..776fd2f 100644
--- a/chrome/browser/ui/views/html_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/html_dialog_view_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/views/html_dialog_view.h"
+#include "chrome/browser/ui/views/html_dialog_view.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/in_process_browser_test.h"
 #include "chrome/test/ui_test_utils.h"
@@ -44,8 +44,8 @@
   virtual GURL GetDialogContentURL() const {
     return GURL(chrome::kAboutBlankURL);
   }
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const { }
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const { }
   virtual void GetDialogSize(gfx::Size* size) const {
     size->set_width(40);
     size->set_height(40);
diff --git a/chrome/browser/ui/views/hung_renderer_view.cc b/chrome/browser/ui/views/hung_renderer_view.cc
index 95184af..ffefd9f 100644
--- a/chrome/browser/ui/views/hung_renderer_view.cc
+++ b/chrome/browser/ui/views/hung_renderer_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/hung_renderer_dialog.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/rtl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
@@ -15,16 +13,18 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/common/result_codes.h"
-#include "gfx/canvas.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/table/group_table_view.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/client_view.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
@@ -50,14 +50,14 @@
   virtual int RowCount();
   virtual string16 GetText(int row, int column_id);
   virtual SkBitmap GetIcon(int row);
-  virtual void SetObserver(TableModelObserver* observer);
+  virtual void SetObserver(ui::TableModelObserver* observer);
   virtual void GetGroupRangeForItem(int item, views::GroupRange* range);
 
  private:
   typedef std::vector<TabContents*> TabContentsVector;
   TabContentsVector tab_contentses_;
 
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
 };
@@ -106,7 +106,7 @@
   return tab_contentses_.at(row)->GetFavIcon();
 }
 
-void HungPagesTableModel::SetObserver(TableModelObserver* observer) {
+void HungPagesTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
@@ -239,6 +239,9 @@
   }
 
   if (!window()->IsActive()) {
+    volatile TabContents* passed_c = contents;
+    volatile TabContents* this_contents = contents_;
+
     gfx::Rect bounds = GetDisplayBounds(contents);
     window()->SetBounds(bounds, frame_hwnd);
 
@@ -364,14 +367,15 @@
   using views::GridLayout;
   using views::ColumnSet;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int double_column_set_id = 0;
   ColumnSet* column_set = layout->AddColumnSet(double_column_set_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
                         GridLayout::FIXED, frozen_icon_->width(), 0);
-  column_set->AddPaddingColumn(0, kUnrelatedControlLargeHorizontalSpacing);
+  column_set->AddPaddingColumn(
+      0, views::kUnrelatedControlLargeHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -379,7 +383,7 @@
   layout->AddView(frozen_icon_view_, 1, 3);
   layout->AddView(info_label_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, double_column_set_id);
   layout->SkipColumns(1);
@@ -403,7 +407,7 @@
   const int single_column_set_id = 0;
   ColumnSet* column_set = layout->AddColumnSet(single_column_set_id);
   column_set->AddPaddingColumn(0, frozen_icon_->width() +
-      kPanelHorizMargin + kUnrelatedControlHorizontalSpacing);
+      kPanelHorizMargin + views::kUnrelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
                         GridLayout::USE_PREF, 0, 0);
 
diff --git a/chrome/browser/ui/views/importer_lock_view.cc b/chrome/browser/ui/views/importer_lock_view.cc
index 714265c..2230a21 100644
--- a/chrome/browser/ui/views/importer_lock_view.cc
+++ b/chrome/browser/ui/views/importer_lock_view.cc
@@ -1,24 +1,41 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/importer_lock_view.h"
+#include "chrome/browser/ui/views/importer_lock_view.h"
 
-#include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/importer/importer.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 // Default size of the dialog window.
 static const int kDefaultWindowWidth = 320;
 static const int kDefaultWindowHeight = 100;
 
+namespace browser {
+
+void ShowImportLockDialog(gfx::NativeWindow parent,
+                          ImporterHost* importer_host) {
+  ImporterLockView::Show(parent, importer_host);
+}
+
+}  // namespace browser
+
+// static
+void ImporterLockView::Show(gfx::NativeWindow parent,
+                            ImporterHost* importer_host) {
+  views::Window::CreateChromeWindow(
+      NULL, gfx::Rect(),
+      new ImporterLockView(importer_host))->Show();
+}
+
 ImporterLockView::ImporterLockView(ImporterHost* host)
     : description_label_(NULL),
       importer_host_(host) {
diff --git a/chrome/browser/ui/views/importer_lock_view.h b/chrome/browser/ui/views/importer_lock_view.h
index 73e6e8c..97fa82a 100644
--- a/chrome/browser/ui/views/importer_lock_view.h
+++ b/chrome/browser/ui/views/importer_lock_view.h
@@ -21,6 +21,9 @@
 class ImporterLockView : public views::View,
                          public views::DialogDelegate {
  public:
+  static void Show(gfx::NativeWindow parent, ImporterHost* importer_host);
+
+ private:
   explicit ImporterLockView(ImporterHost* host);
   virtual ~ImporterLockView();
 
diff --git a/chrome/browser/ui/views/importer_view.cc b/chrome/browser/ui/views/importer_view.cc
index 9af35f4..317456c 100644
--- a/chrome/browser/ui/views/importer_view.cc
+++ b/chrome/browser/ui/views/importer_view.cc
@@ -1,21 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/importer_view.h"
+#include "chrome/browser/ui/views/importer_view.h"
 
-#include "app/l10n_util.h"
 #include "base/compiler_specific.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/importer/importer_list.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -42,9 +43,11 @@
       passwords_checkbox_(NULL),
       search_engines_checkbox_(NULL),
       profile_(profile),
-      ALLOW_THIS_IN_INITIALIZER_LIST(importer_host_(new ImporterHost(this))),
+      importer_host_(new ImporterHost),
+      importer_list_(new ImporterList),
       initial_state_(initial_state) {
   DCHECK(profile);
+  importer_list_->DetectSourceProfiles(this);
   SetupControl();
 }
 
@@ -58,7 +61,8 @@
 
   profile_combobox_ = new views::Combobox(this);
   profile_combobox_->set_listener(this);
-  profile_combobox_->SetAccessibleName(import_from_label_->GetText());
+  profile_combobox_->SetAccessibleName(
+      WideToUTF16Hack(import_from_label_->GetText()));
 
   import_items_label_ = new views::Label(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_IMPORT_ITEMS_LABEL)));
@@ -78,12 +82,12 @@
 
   // Arranges controls by using GridLayout.
   const int column_set_id = 0;
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
   ColumnSet* column_set = layout->AddColumnSet(column_set_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::FIXED, 200, 0);
 
@@ -91,22 +95,22 @@
   layout->AddView(import_from_label_);
   layout->AddView(profile_combobox_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
   layout->StartRow(0, column_set_id);
   layout->AddView(import_items_label_, 3, 1);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, column_set_id);
   layout->AddView(favorites_checkbox_, 3, 1);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, column_set_id);
   layout->AddView(search_engines_checkbox_, 3, 1);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, column_set_id);
   layout->AddView(passwords_checkbox_, 3, 1);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, column_set_id);
   layout->AddView(history_checkbox_, 3, 1);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 }
 
 gfx::Size ImporterView::GetPreferredSize() {
@@ -157,7 +161,7 @@
   int selected_index = profile_combobox_->selected_item();
   StartImportingWithUI(GetWidget()->GetNativeView(), items,
                        importer_host_.get(),
-                       importer_host_->GetSourceProfileInfoAt(selected_index),
+                       importer_list_->GetSourceProfileInfoAt(selected_index),
                        profile_, this, false);
   // We return false here to prevent the window from being closed. We will be
   // notified back by our implementation of ImportObserver when the import is
@@ -184,22 +188,22 @@
 string16 ImporterView::GetItemAt(int index) {
   DCHECK(importer_host_.get());
 
-  if (!importer_host_->source_profiles_loaded())
+  if (!importer_list_->source_profiles_loaded())
     return l10n_util::GetStringUTF16(IDS_IMPORT_LOADING_PROFILES);
   else
-    return WideToUTF16Hack(importer_host_->GetSourceProfileNameAt(index));
+    return WideToUTF16Hack(importer_list_->GetSourceProfileNameAt(index));
 }
 
 void ImporterView::ItemChanged(views::Combobox* combobox,
                                int prev_index, int new_index) {
   DCHECK(combobox);
   DCHECK(checkbox_items_.size() >=
-      static_cast<size_t>(importer_host_->GetAvailableProfileCount()));
+      static_cast<size_t>(importer_list_->GetAvailableProfileCount()));
 
   if (prev_index == new_index)
     return;
 
-  if (!importer_host_->source_profiles_loaded()) {
+  if (!importer_list_->source_profiles_loaded()) {
     SetCheckedItemsState(0);
     return;
   }
@@ -209,7 +213,7 @@
   checkbox_items_[prev_index] = prev_items;
 
   // Enable/Disable the checkboxes for this Item
-  uint16 new_enabled_items = importer_host_->GetSourceProfileInfoAt(
+  uint16 new_enabled_items = importer_list_->GetSourceProfileInfoAt(
       new_index).services_supported;
   SetCheckedItemsState(new_enabled_items);
 
@@ -219,9 +223,9 @@
 }
 
 void ImporterView::SourceProfilesLoaded() {
-  DCHECK(importer_host_->source_profiles_loaded());
+  DCHECK(importer_list_->source_profiles_loaded());
   checkbox_items_.resize(
-      importer_host_->GetAvailableProfileCount(), initial_state_);
+      importer_list_->GetAvailableProfileCount(), initial_state_);
 
   // Reload the profile combobox.
   profile_combobox_->ModelChanged();
diff --git a/chrome/browser/ui/views/importer_view.h b/chrome/browser/ui/views/importer_view.h
index 0d06485..c1ed9b2 100644
--- a/chrome/browser/ui/views/importer_view.h
+++ b/chrome/browser/ui/views/importer_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_UI_VIEWS_IMPORTER_VIEW_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "base/string16.h"
 #include "chrome/browser/importer/importer.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/view.h"
@@ -20,6 +20,7 @@
 class Window;
 }
 
+class ImporterList;
 class Profile;
 
 // ImporterView draws the dialog that allows the user to select what to
@@ -29,7 +30,7 @@
 class ImporterView : public views::View,
                      public views::DialogDelegate,
                      public views::ButtonListener,
-                     public ComboboxModel,
+                     public ui::ComboboxModel,
                      public views::Combobox::Listener,
                      public ImporterList::Observer,
                      public ImportObserver {
@@ -56,7 +57,7 @@
   // views::ButtonListener implementation.
   virtual void ButtonPressed(views::Button* sender, const views::Event& event);
 
-  // ComboboxModel implementation.
+  // ui::ComboboxModel implementation.
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
@@ -97,6 +98,7 @@
   views::Checkbox* search_engines_checkbox_;
 
   scoped_refptr<ImporterHost> importer_host_;
+  scoped_refptr<ImporterList> importer_list_;
 
   // Stores the state of the checked items associated with the position of the
   // selected item in the combo-box.
diff --git a/chrome/browser/ui/views/importing_progress_view.cc b/chrome/browser/ui/views/importing_progress_view.cc
index 2befd5f..fce962f 100644
--- a/chrome/browser/ui/views/importing_progress_view.cc
+++ b/chrome/browser/ui/views/importing_progress_view.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/importing_progress_view.h"
+#include "chrome/browser/ui/views/importing_progress_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
 #include "views/controls/throbber.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -228,7 +228,7 @@
   using views::GridLayout;
   using views::ColumnSet;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   gfx::Size ps = state_history_->GetPreferredSize();
@@ -238,55 +238,57 @@
   if (bookmarks_import_) {
     column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                           GridLayout::FIXED, ps.width(), 0);
-    column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+    column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   }
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
   const int double_column_view_set_id = 1;
   column_set = layout->AddColumnSet(double_column_view_set_id);
-  column_set->AddPaddingColumn(0, kUnrelatedControlLargeHorizontalSpacing);
+  column_set->AddPaddingColumn(
+      0, views::kUnrelatedControlLargeHorizontalSpacing);
   column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                         GridLayout::FIXED, ps.width(), 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kUnrelatedControlLargeHorizontalSpacing);
+  column_set->AddPaddingColumn(
+      0, views::kUnrelatedControlLargeHorizontalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   if (bookmarks_import_)
     layout->AddView(state_bookmarks_.get());
   layout->AddView(label_info_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   if (items_ & importer::HISTORY) {
     layout->StartRow(0, double_column_view_set_id);
     layout->AddView(state_history_.get());
     layout->AddView(label_history_.get());
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
   if (items_ & importer::FAVORITES && !bookmarks_import_) {
     layout->StartRow(0, double_column_view_set_id);
     layout->AddView(state_bookmarks_.get());
     layout->AddView(label_bookmarks_.get());
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
   if (items_ & importer::SEARCH_ENGINES) {
     layout->StartRow(0, double_column_view_set_id);
     layout->AddView(state_searches_.get());
     layout->AddView(label_searches_.get());
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
   if (items_ & importer::PASSWORDS) {
     layout->StartRow(0, double_column_view_set_id);
     layout->AddView(state_passwords_.get());
     layout->AddView(label_passwords_.get());
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
   if (items_ & importer::COOKIES) {
     layout->StartRow(0, double_column_view_set_id);
     layout->AddView(state_cookies_.get());
     layout->AddView(label_cookies_.get());
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
 }
 
diff --git a/chrome/browser/ui/views/indexed_db_info_view.cc b/chrome/browser/ui/views/indexed_db_info_view.cc
index a1718ef..34fd9eb 100644
--- a/chrome/browser/ui/views/indexed_db_info_view.cc
+++ b/chrome/browser/ui/views/indexed_db_info_view.cc
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/indexed_db_info_view.h"
+#include "chrome/browser/ui/views/indexed_db_info_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 static const int kIndexedDBInfoViewBorderSize = 1;
 static const int kIndexedDBInfoViewInsetSize = 3;
@@ -101,18 +101,18 @@
   views::ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(origin_label);
   layout->AddView(origin_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(size_label);
   layout->AddView(size_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(last_modified_label);
   layout->AddView(last_modified_value_field_);
diff --git a/chrome/browser/ui/views/info_bubble.cc b/chrome/browser/ui/views/info_bubble.cc
index 8d07a57..aad0b38 100644
--- a/chrome/browser/ui/views/info_bubble.cc
+++ b/chrome/browser/ui/views/info_bubble.cc
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 
 #include <vector>
 
-#include "app/keyboard_codes.h"
 #include "chrome/browser/ui/window_sizer.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
-#include "gfx/path.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "ui/base/animation/slide_animation.h"
-#include "views/fill_layout.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/path.h"
+#include "views/layout/fill_layout.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget.h"
 #include "views/window/client_view.h"
@@ -113,7 +113,7 @@
   paint.setStyle(SkPaint::kFill_Style);
   paint.setColor(InfoBubble::kBackgroundColor);
   gfx::Path path;
-  gfx::Rect bounds(GetLocalBounds(false));
+  gfx::Rect bounds(GetContentsBounds());
   SkRect rect;
   rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
            SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom()));
@@ -438,18 +438,19 @@
       arrow_location, false, contents->GetPreferredSize(),
       &contents_bounds, &window_bounds);
   // This new view must be added before |contents| so it will paint under it.
-  contents_view->AddChildView(0, border_contents_);
+  contents_view->AddChildViewAt(border_contents_, 0);
 
   // |contents_view| has no layout manager, so we have to explicitly position
   // its children.
-  border_contents_->SetBounds(gfx::Rect(gfx::Point(), window_bounds.size()));
-  contents->SetBounds(contents_bounds);
+  border_contents_->SetBoundsRect(
+      gfx::Rect(gfx::Point(), window_bounds.size()));
+  contents->SetBoundsRect(contents_bounds);
 #endif
   SetBounds(window_bounds);
 
   // Register the Escape accelerator for closing.
   GetFocusManager()->RegisterAccelerator(
-      views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
+      views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this);
 
   // Done creating the bubble.
   NotificationService::current()->Notify(NotificationType::INFO_BUBBLE_CREATED,
@@ -486,8 +487,9 @@
       &contents_bounds, &window_bounds);
   // |contents_view| has no layout manager, so we have to explicitly position
   // its children.
-  border_contents_->SetBounds(gfx::Rect(gfx::Point(), window_bounds.size()));
-  contents_->SetBounds(contents_bounds);
+  border_contents_->SetBoundsRect(
+      gfx::Rect(gfx::Point(), window_bounds.size()));
+  contents_->SetBoundsRect(contents_bounds);
 #endif
   SetBounds(window_bounds);
 }
@@ -498,7 +500,7 @@
   if (action == WA_INACTIVE) {
     Close();
   } else if (action == WA_ACTIVE) {
-    DCHECK_GT(GetRootView()->GetChildViewCount(), 0);
+    DCHECK(GetRootView()->has_children());
     GetRootView()->GetChildViewAt(0)->RequestFocus();
   }
 }
@@ -514,7 +516,7 @@
     return;
 
   GetFocusManager()->UnregisterAccelerator(
-      views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
+      views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this);
   if (delegate_)
     delegate_->InfoBubbleClosing(this, closed_by_escape);
   show_status_ = kClosed;
diff --git a/chrome/browser/ui/views/info_bubble.h b/chrome/browser/ui/views/info_bubble.h
index 74fffb2..b329e80 100644
--- a/chrome/browser/ui/views/info_bubble.h
+++ b/chrome/browser/ui/views/info_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_UI_VIEWS_INFO_BUBBLE_H_
 #pragma once
 
+#include "chrome/browser/ui/views/bubble_border.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "views/accelerator.h"
 #include "views/view.h"
-#include "chrome/browser/views/bubble_border.h"
 
 #if defined(OS_WIN)
 #include "views/widget/widget_win.h"
diff --git a/chrome/browser/ui/views/info_bubble_unittest.cc b/chrome/browser/ui/views/info_bubble_unittest.cc
index 8d7f8ec..1e9c583 100644
--- a/chrome/browser/ui/views/info_bubble_unittest.cc
+++ b/chrome/browser/ui/views/info_bubble_unittest.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 typedef testing::Test InfoBubbleTest;
diff --git a/chrome/browser/ui/views/infobars/after_translate_infobar.cc b/chrome/browser/ui/views/infobars/after_translate_infobar.cc
index 63b6c8a..6c38fae 100644
--- a/chrome/browser/ui/views/infobars/after_translate_infobar.cc
+++ b/chrome/browser/ui/views/infobars/after_translate_infobar.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/after_translate_infobar.h"
+#include "chrome/browser/ui/views/infobars/after_translate_infobar.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/translate/options_menu_model.h"
 #include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/views/infobars/infobar_button_border.h"
-#include "chrome/browser/views/infobars/infobar_text_button.h"
+#include "chrome/browser/ui/views/infobars/infobar_button_border.h"
+#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/button/text_button.h"
 #include "views/controls/image_view.h"
@@ -26,106 +26,100 @@
       options_menu_model_(delegate),
       swapped_language_buttons_(false) {
   std::vector<string16> strings;
-  TranslateInfoBarDelegate::GetAfterTranslateStrings(
-      &strings, &swapped_language_buttons_);
-  DCHECK(strings.size() == 3U);
+  GetDelegate()->GetAfterTranslateStrings(&strings, &swapped_language_buttons_);
+  DCHECK_EQ(3U, strings.size());
 
   label_1_ = CreateLabel(strings[0]);
   AddChildView(label_1_);
 
+  original_language_menu_button_ = CreateMenuButton(string16(), true, this);
+  target_language_menu_button_ = CreateMenuButton(string16(), true, this);
+  AddChildView(swapped_language_buttons_ ?
+      target_language_menu_button_ : original_language_menu_button_);
+
   label_2_ = CreateLabel(strings[1]);
   AddChildView(label_2_);
 
+  AddChildView(swapped_language_buttons_ ?
+      original_language_menu_button_ : target_language_menu_button_);
+
   label_3_ = CreateLabel(strings[2]);
   AddChildView(label_3_);
 
-  original_language_menu_button_ = CreateMenuButton(string16(), true, this);
-  AddChildView(original_language_menu_button_);
-
-  target_language_menu_button_ = CreateMenuButton(string16(), true, this);
-  AddChildView(target_language_menu_button_);
-
-  options_menu_button_ =
-      CreateMenuButton(l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS),
-                       false, this);
-  AddChildView(options_menu_button_);
-
   revert_button_ = InfoBarTextButton::Create(this,
       l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT));
   AddChildView(revert_button_);
 
-  UpdateLanguageButtonText(LanguagesMenuModel::ORIGINAL);
-  UpdateLanguageButtonText(LanguagesMenuModel::TARGET);
+  options_menu_button_ = CreateMenuButton(
+      l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), false, this);
+  AddChildView(options_menu_button_);
+
+  OriginalLanguageChanged();
+  TargetLanguageChanged();
 }
 
 AfterTranslateInfoBar::~AfterTranslateInfoBar() {
 }
 
-// Overridden from views::View:
 void AfterTranslateInfoBar::Layout() {
-  // Layout the icon and close button.
   TranslateInfoBarBase::Layout();
 
-  // Layout the options menu button on right of bar.
-  int available_width = InfoBar::GetAvailableWidth();
-  gfx::Size pref_size = options_menu_button_->GetPreferredSize();
-  options_menu_button_->SetBounds(available_width - pref_size.width(),
-      OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+  int available_width = GetAvailableWidth();
+  gfx::Size label_1_size = label_1_->GetPreferredSize();
+  label_1_->SetBounds(icon_->bounds().right() + kIconLabelSpacing,
+      OffsetY(this, label_1_size), label_1_size.width(), label_1_size.height());
 
-  views::MenuButton* left_button = swapped_language_buttons_ ?
-      target_language_menu_button_ : original_language_menu_button_;
-  views::MenuButton* right_button = swapped_language_buttons_ ?
-      original_language_menu_button_ : target_language_menu_button_;
+  views::MenuButton* first_button = original_language_menu_button_;
+  views::MenuButton* second_button = target_language_menu_button_;
+  if (swapped_language_buttons_)
+    std::swap(first_button, second_button);
+  gfx::Size first_button_size = first_button->GetPreferredSize();
+  first_button->SetBounds(label_1_->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, first_button_size), first_button_size.width(),
+      first_button_size.height());
 
-  pref_size = label_1_->GetPreferredSize();
-  label_1_->SetBounds(icon_->bounds().right() + InfoBar::kIconLabelSpacing,
-      InfoBar::OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+  gfx::Size label_2_size = label_2_->GetPreferredSize();
+  label_2_->SetBounds(first_button->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, label_2_size), label_2_size.width(), label_2_size.height());
 
-  pref_size = left_button->GetPreferredSize();
-  left_button->SetBounds(label_1_->bounds().right() +
-      InfoBar::kButtonInLabelSpacing, OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
+  gfx::Size second_button_size = second_button->GetPreferredSize();
+  second_button->SetBounds(label_2_->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, second_button_size), second_button_size.width(),
+      second_button_size.height());
 
-  pref_size = label_2_->GetPreferredSize();
-  label_2_->SetBounds(left_button->bounds().right() +
-      InfoBar::kButtonInLabelSpacing, InfoBar::OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
+  gfx::Size label_3_size = label_3_->GetPreferredSize();
+  label_3_->SetBounds(second_button->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, label_3_size), label_3_size.width(), label_3_size.height());
 
-  pref_size = right_button->GetPreferredSize();
-  right_button->SetBounds(label_2_->bounds().right() +
-      InfoBar::kButtonInLabelSpacing, OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
+  gfx::Size revert_button_size = revert_button_->GetPreferredSize();
+  revert_button_->SetBounds(label_3_->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, revert_button_size),
+      revert_button_size.width(), revert_button_size.height());
 
-  pref_size = label_3_->GetPreferredSize();
-  label_3_->SetBounds(right_button->bounds().right() +
-      InfoBar::kButtonInLabelSpacing, InfoBar::OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
-
-  pref_size = revert_button_->GetPreferredSize();
-  revert_button_->SetBounds(label_3_->bounds().right() +
-      InfoBar::kButtonInLabelSpacing, InfoBar::OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
-}
-
-void AfterTranslateInfoBar::OriginalLanguageChanged() {
-  UpdateLanguageButtonText(LanguagesMenuModel::ORIGINAL);
-}
-
-void AfterTranslateInfoBar::TargetLanguageChanged() {
-  UpdateLanguageButtonText(LanguagesMenuModel::TARGET);
+  gfx::Size options_size = options_menu_button_->GetPreferredSize();
+  options_menu_button_->SetBounds(available_width - options_size.width(),
+      OffsetY(this, options_size), options_size.width(), options_size.height());
 }
 
 void AfterTranslateInfoBar::ButtonPressed(views::Button* sender,
                                           const views::Event& event) {
-  if (sender == revert_button_) {
+  if (sender == revert_button_)
     GetDelegate()->RevertTranslation();
-    return;
-  }
-  TranslateInfoBarBase::ButtonPressed(sender, event);
+  else
+    TranslateInfoBarBase::ButtonPressed(sender, event);
 }
 
-void AfterTranslateInfoBar::RunMenu(views::View* source,
-                                    const gfx::Point& pt) {
+void AfterTranslateInfoBar::OriginalLanguageChanged() {
+  UpdateLanguageButtonText(original_language_menu_button_,
+                           LanguagesMenuModel::ORIGINAL);
+}
+
+void AfterTranslateInfoBar::TargetLanguageChanged() {
+  UpdateLanguageButtonText(target_language_menu_button_,
+                           LanguagesMenuModel::TARGET);
+}
+
+void AfterTranslateInfoBar::RunMenu(View* source, const gfx::Point& pt) {
   if (source == original_language_menu_button_) {
     if (!original_language_menu_.get()) {
       original_language_menu_.reset(
@@ -133,37 +127,15 @@
     }
     original_language_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
   } else if (source == target_language_menu_button_) {
-      if (!target_language_menu_.get()) {
-        target_language_menu_.reset(
-            new views::Menu2(&target_language_menu_model_));
-      }
-      target_language_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
-  } else if (source == options_menu_button_) {
+    if (!target_language_menu_.get()) {
+      target_language_menu_.reset(
+          new views::Menu2(&target_language_menu_model_));
+    }
+    target_language_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
+  } else {
+    DCHECK_EQ(options_menu_button_, source);
     if (!options_menu_.get())
       options_menu_.reset(new views::Menu2(&options_menu_model_));
     options_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
-  } else {
-    NOTREACHED();
   }
 }
-
-void AfterTranslateInfoBar::UpdateLanguageButtonText(
-    LanguagesMenuModel::LanguageType language_type) {
-  int language_index;
-  views::MenuButton* language_button;
-  if (language_type == LanguagesMenuModel::ORIGINAL) {
-    language_index = GetDelegate()->original_language_index();
-    language_button = original_language_menu_button_;
-  } else {
-    language_index = GetDelegate()->target_language_index();
-    language_button = target_language_menu_button_;
-  }
-  string16 language =
-      GetDelegate()->GetLanguageDisplayableNameAt(language_index);
-  language_button->SetText(UTF16ToWideHack(language));
-  // The following line is necessary for the preferred size to be recomputed.
-  language_button->ClearMaxTextSize();
-  // The button may have to grow to show the new text.
-  Layout();
-  SchedulePaint();
-}
diff --git a/chrome/browser/ui/views/infobars/after_translate_infobar.h b/chrome/browser/ui/views/infobars/after_translate_infobar.h
index 18c74a7..bf873be 100644
--- a/chrome/browser/ui/views/infobars/after_translate_infobar.h
+++ b/chrome/browser/ui/views/infobars/after_translate_infobar.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,15 +8,11 @@
 
 #include "chrome/browser/translate/languages_menu_model.h"
 #include "chrome/browser/translate/options_menu_model.h"
-#include "chrome/browser/translate/translate_infobar_view.h"
-#include "chrome/browser/views/infobars/translate_infobar_base.h"
-#include "views/controls/button/button.h"
-#include "views/controls/link.h"
+#include "chrome/browser/ui/views/infobars/translate_infobar_base.h"
 #include "views/controls/menu/view_menu_delegate.h"
 
 class InfoBarTextButton;
 class TranslateInfoBarDelegate;
-
 namespace views {
 class Menu2;
 class MenuButton;
@@ -26,40 +22,31 @@
                               public views::ViewMenuDelegate {
  public:
   explicit AfterTranslateInfoBar(TranslateInfoBarDelegate* delegate);
+
+ private:
   virtual ~AfterTranslateInfoBar();
 
-  // Overridden from views::View:
+  // TranslateInfoBarBase:
   virtual void Layout();
-
-  // Overridden from TranslateInfoBarView:
+  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
   virtual void OriginalLanguageChanged();
   virtual void TargetLanguageChanged();
 
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
- protected:
-  // Overridden from views::ViewMenuDelegate:
+  // ViewMenuDelegate:
   virtual void RunMenu(View* source, const gfx::Point& pt);
 
- private:
-  // Sets the text of the original or target language menu buttons to reflect
-  // the current value from the delegate.
-  void UpdateLanguageButtonText(LanguagesMenuModel::LanguageType language);
-
   // The text displayed in the infobar is something like:
-  // "Translated from <lang1> to <lang2>"
-  // Where <lang1> and <lang2> are displayed in a combobox.
-  // So the text is split in 3 chunks, each one displayed in one of the label
-  // below.
+  // "Translated from <lang1> to <lang2> [more text in some languages]"
+  // ...where <lang1> and <lang2> are comboboxes.  So the text is split in 3
+  // chunks, each displayed in one of the labels below.
   views::Label* label_1_;
   views::Label* label_2_;
   views::Label* label_3_;
 
   views::MenuButton* original_language_menu_button_;
   views::MenuButton* target_language_menu_button_;
-  views::MenuButton* options_menu_button_;
   InfoBarTextButton* revert_button_;
+  views::MenuButton* options_menu_button_;
 
   scoped_ptr<views::Menu2> original_language_menu_;
   LanguagesMenuModel original_language_menu_model_;
diff --git a/chrome/browser/ui/views/infobars/before_translate_infobar.cc b/chrome/browser/ui/views/infobars/before_translate_infobar.cc
index f4d636a..19a83f5 100644
--- a/chrome/browser/ui/views/infobars/before_translate_infobar.cc
+++ b/chrome/browser/ui/views/infobars/before_translate_infobar.cc
@@ -1,17 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/before_translate_infobar.h"
+#include "chrome/browser/ui/views/infobars/before_translate_infobar.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/translate/options_menu_model.h"
 #include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/views/infobars/infobar_text_button.h"
+#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/image_view.h"
+#include "views/controls/label.h"
 #include "views/controls/menu/menu_2.h"
 
 BeforeTranslateInfoBar::BeforeTranslateInfoBar(
@@ -22,152 +23,129 @@
       languages_menu_model_(delegate, LanguagesMenuModel::ORIGINAL),
       options_menu_model_(delegate) {
   size_t offset = 0;
-  string16 text =
-      l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE,
-                                 string16(), &offset);
+  string16 text(l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE,
+                                           string16(), &offset));
 
   label_1_ = CreateLabel(text.substr(0, offset));
   AddChildView(label_1_);
 
-  label_2_ = CreateLabel(text.substr(offset));
-  AddChildView(label_2_);
-
-  accept_button_ =
-    InfoBarTextButton::CreateWithMessageID(this,
-                                           IDS_TRANSLATE_INFOBAR_ACCEPT);
-  AddChildView(accept_button_);
-
-  deny_button_ =
-    InfoBarTextButton::CreateWithMessageID(this,
-                                           IDS_TRANSLATE_INFOBAR_DENY);
-  AddChildView(deny_button_);
-
   language_menu_button_ = CreateMenuButton(string16(), true, this);
   AddChildView(language_menu_button_);
 
-  options_menu_button_ =
-      CreateMenuButton(l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS),
-                       false, this);
-  AddChildView(options_menu_button_);
+  label_2_ = CreateLabel(text.substr(offset));
+  AddChildView(label_2_);
 
+  accept_button_ = InfoBarTextButton::CreateWithMessageID(this,
+      IDS_TRANSLATE_INFOBAR_ACCEPT);
+  AddChildView(accept_button_);
+
+  deny_button_ = InfoBarTextButton::CreateWithMessageID(this,
+      IDS_TRANSLATE_INFOBAR_DENY);
+  AddChildView(deny_button_);
+
+  const string16& language(delegate->GetLanguageDisplayableNameAt(
+      delegate->original_language_index()));
   if (delegate->ShouldShowNeverTranslateButton()) {
-    const string16& language = delegate->GetLanguageDisplayableNameAt(
-        delegate->original_language_index());
     never_translate_button_ = InfoBarTextButton::CreateWithMessageIDAndParam(
         this, IDS_TRANSLATE_INFOBAR_NEVER_TRANSLATE, language);
     AddChildView(never_translate_button_);
-  }
-
-  if (delegate->ShouldShowAlwaysTranslateButton()) {
-    const string16& language = delegate->GetLanguageDisplayableNameAt(
-        delegate->original_language_index());
+  } else if (delegate->ShouldShowAlwaysTranslateButton()) {
     always_translate_button_ = InfoBarTextButton::CreateWithMessageIDAndParam(
         this, IDS_TRANSLATE_INFOBAR_ALWAYS_TRANSLATE, language);
     AddChildView(always_translate_button_);
   }
 
-  UpdateOriginalButtonText();
+  options_menu_button_ = CreateMenuButton(
+      l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), false, this);
+  AddChildView(options_menu_button_);
+
+  OriginalLanguageChanged();
 }
 
 BeforeTranslateInfoBar::~BeforeTranslateInfoBar() {
 }
 
-// Overridden from views::View:
 void BeforeTranslateInfoBar::Layout() {
-  // Layout the icon and close button.
   TranslateInfoBarBase::Layout();
 
-  // Layout the options menu button on right of bar.
-  int available_width = InfoBar::GetAvailableWidth();
-  gfx::Size pref_size = options_menu_button_->GetPreferredSize();
-  options_menu_button_->SetBounds(available_width - pref_size.width(),
-      OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+  int available_width = GetAvailableWidth();
+  gfx::Size label_1_size = label_1_->GetPreferredSize();
+  label_1_->SetBounds(icon_->bounds().right() + kIconLabelSpacing,
+      OffsetY(this, label_1_size), label_1_size.width(), label_1_size.height());
 
-  pref_size = label_1_->GetPreferredSize();
-  label_1_->SetBounds(icon_->bounds().right() + InfoBar::kIconLabelSpacing,
-      InfoBar::OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+  gfx::Size language_button_size = language_menu_button_->GetPreferredSize();
+  language_menu_button_->SetBounds(
+      label_1_->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, language_button_size), language_button_size.width(),
+      language_button_size.height());
 
-  pref_size = language_menu_button_->GetPreferredSize();
-  language_menu_button_->SetBounds(label_1_->bounds().right() +
-      InfoBar::kButtonInLabelSpacing, OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
+  gfx::Size label_2_size = label_2_->GetPreferredSize();
+  label_2_->SetBounds(
+      language_menu_button_->bounds().right() + kButtonInLabelSpacing,
+      OffsetY(this, label_2_size), label_2_size.width(), label_2_size.height());
 
-  pref_size = label_2_->GetPreferredSize();
-  label_2_->SetBounds(language_menu_button_->bounds().right() +
-      InfoBar::kButtonInLabelSpacing , InfoBar::OffsetY(this, pref_size),
-      pref_size.width(), pref_size.height());
+  gfx::Size accept_button_size = accept_button_->GetPreferredSize();
+  accept_button_->SetBounds(label_2_->bounds().right() + kEndOfLabelSpacing,
+      OffsetY(this, accept_button_size), accept_button_size.width(),
+      accept_button_size.height());
 
-  pref_size = accept_button_->GetPreferredSize();
-  accept_button_->SetBounds(
-      label_2_->bounds().right() + InfoBar::kEndOfLabelSpacing,
-      OffsetY(this, pref_size), pref_size.width(), pref_size.height());
-
-  pref_size = deny_button_->GetPreferredSize();
+  gfx::Size deny_button_size = deny_button_->GetPreferredSize();
   deny_button_->SetBounds(
-        accept_button_->bounds().right() + InfoBar::kButtonButtonSpacing,
-        OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+        accept_button_->bounds().right() + kButtonButtonSpacing,
+        OffsetY(this, deny_button_size), deny_button_size.width(),
+        deny_button_size.height());
 
   if (never_translate_button_) {
-    pref_size = never_translate_button_->GetPreferredSize();
+    gfx::Size never_button_size = never_translate_button_->GetPreferredSize();
     never_translate_button_->SetBounds(
-          deny_button_->bounds().right() + InfoBar::kButtonButtonSpacing,
-          OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+          deny_button_->bounds().right() + kButtonButtonSpacing,
+          OffsetY(this, never_button_size), never_button_size.width(),
+          never_button_size.height());
   }
+
   if (always_translate_button_) {
-    DCHECK(!never_translate_button_);
-    pref_size = always_translate_button_->GetPreferredSize();
+    gfx::Size always_button_size = always_translate_button_->GetPreferredSize();
     always_translate_button_->SetBounds(
-          deny_button_->bounds().right() + InfoBar::kButtonButtonSpacing,
-          OffsetY(this, pref_size), pref_size.width(), pref_size.height());
+          deny_button_->bounds().right() + kButtonButtonSpacing,
+          OffsetY(this, always_button_size), always_button_size.width(),
+          always_button_size.height());
   }
+
+  gfx::Size options_size = options_menu_button_->GetPreferredSize();
+  options_menu_button_->SetBounds(available_width - options_size.width(),
+      OffsetY(this, options_size), options_size.width(), options_size.height());
 }
 
 void BeforeTranslateInfoBar::ButtonPressed(views::Button* sender,
                                            const views::Event& event) {
+  TranslateInfoBarDelegate* delegate = GetDelegate();
   if (sender == accept_button_) {
-    GetDelegate()->Translate();
+    delegate->Translate();
   } else if (sender == deny_button_) {
+    delegate->TranslationDeclined();
     RemoveInfoBar();
-    GetDelegate()->TranslationDeclined();
   } else if (sender == never_translate_button_) {
-    GetDelegate()->NeverTranslatePageLanguage();
+    delegate->NeverTranslatePageLanguage();
   } else if (sender == always_translate_button_) {
-    GetDelegate()->AlwaysTranslatePageLanguage();
+    delegate->AlwaysTranslatePageLanguage();
   } else {
     TranslateInfoBarBase::ButtonPressed(sender, event);
   }
 }
 
 void BeforeTranslateInfoBar::OriginalLanguageChanged() {
-  UpdateOriginalButtonText();
+  UpdateLanguageButtonText(language_menu_button_, LanguagesMenuModel::ORIGINAL);
 }
 
-void BeforeTranslateInfoBar::TargetLanguageChanged() {
-  NOTREACHED();
-}
-
-void BeforeTranslateInfoBar::RunMenu(views::View* source,
-                                     const gfx::Point& pt) {
+void BeforeTranslateInfoBar::RunMenu(View* source, const gfx::Point& pt) {
   if (source == language_menu_button_) {
     if (!languages_menu_.get())
       languages_menu_.reset(new views::Menu2(&languages_menu_model_));
     languages_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
-  } else if (source == options_menu_button_) {
+  } else {
+    DCHECK_EQ(options_menu_button_, source);
     if (!options_menu_.get())
       options_menu_.reset(new views::Menu2(&options_menu_model_));
     options_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
-  } else {
-    NOTREACHED();
   }
 }
-
-void BeforeTranslateInfoBar::UpdateOriginalButtonText() {
-  string16 language = GetDelegate()->GetLanguageDisplayableNameAt(
-      GetDelegate()->original_language_index());
-  language_menu_button_->SetText(UTF16ToWideHack(language));
-  // The following line is necessary for the preferred size to be recomputed.
-  language_menu_button_->ClearMaxTextSize();
-  // The button may have to grow to show the new text.
-  Layout();
-  SchedulePaint();
-}
diff --git a/chrome/browser/ui/views/infobars/before_translate_infobar.h b/chrome/browser/ui/views/infobars/before_translate_infobar.h
index 52ba882..b327fcd 100644
--- a/chrome/browser/ui/views/infobars/before_translate_infobar.h
+++ b/chrome/browser/ui/views/infobars/before_translate_infobar.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,61 +8,45 @@
 
 #include "chrome/browser/translate/languages_menu_model.h"
 #include "chrome/browser/translate/options_menu_model.h"
-#include "chrome/browser/translate/translate_infobar_view.h"
-#include "chrome/browser/views/infobars/infobars.h"
-#include "chrome/browser/views/infobars/translate_infobar_base.h"
-#include "views/controls/button/button.h"
-#include "views/controls/link.h"
+#include "chrome/browser/ui/views/infobars/translate_infobar_base.h"
 #include "views/controls/menu/view_menu_delegate.h"
 
 class InfoBarTextButton;
 class TranslateInfoBarDelegate;
-
 namespace views {
 class Menu2;
 class MenuButton;
 }
 
-class BeforeTranslateInfoBar
-    : public TranslateInfoBarBase,
-      public views::ViewMenuDelegate {
+class BeforeTranslateInfoBar : public TranslateInfoBarBase,
+                               public views::ViewMenuDelegate {
  public:
   explicit BeforeTranslateInfoBar(TranslateInfoBarDelegate* delegate);
-  virtual ~BeforeTranslateInfoBar();
-
-  // Overridden from views::View:
-  virtual void Layout();
-
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // Overridden from TranslateInfoBarView:
-  virtual void OriginalLanguageChanged();
-  virtual void TargetLanguageChanged();
-
- protected:
-  // Overridden from views::ViewMenuDelegate:
-  virtual void RunMenu(View* source, const gfx::Point& pt);
 
  private:
-  // Sets the text of the original language menu button to reflect the current
-  // value from the delegate.
-  void UpdateOriginalButtonText();
+  virtual ~BeforeTranslateInfoBar();
+
+  // TranslateInfoBarBase:
+  virtual void Layout();
+  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+  virtual void OriginalLanguageChanged();
+
+  // views::ViewMenuDelegate:
+  virtual void RunMenu(View* source, const gfx::Point& pt);
 
   // The text displayed in the infobar is something like:
   // "The page is in <lang>. Would you like to translate it?"
-  // Where <lang> is displayed in a combobox.
-  // So the text is split in 2 chunks, each one displayed in one of the label
-  // below.
+  // ...where <lang> is a combobox.  So the text is split in 2 chunks, each
+  // displayed in one of the labels below.
   views::Label* label_1_;
   views::Label* label_2_;
 
   views::MenuButton* language_menu_button_;
-  views::MenuButton* options_menu_button_;
   InfoBarTextButton* accept_button_;
   InfoBarTextButton* deny_button_;
   InfoBarTextButton* never_translate_button_;
   InfoBarTextButton* always_translate_button_;
+  views::MenuButton* options_menu_button_;
 
   scoped_ptr<views::Menu2> languages_menu_;
   LanguagesMenuModel languages_menu_model_;
diff --git a/chrome/browser/ui/views/infobars/confirm_infobar.cc b/chrome/browser/ui/views/infobars/confirm_infobar.cc
new file mode 100644
index 0000000..d9737d5
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/confirm_infobar.cc
@@ -0,0 +1,176 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/views/infobars/confirm_infobar.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/ui/views/event_utils.h"
+#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "views/controls/image_view.h"
+#include "views/controls/label.h"
+
+// AlertInfoBar, public: -------------------------------------------------------
+
+AlertInfoBar::AlertInfoBar(ConfirmInfoBarDelegate* delegate)
+    : InfoBarView(delegate) {
+  label_ = new views::Label(
+      UTF16ToWideHack(delegate->GetMessageText()),
+      ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont));
+  label_->SetColor(SK_ColorBLACK);
+  label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+  AddChildView(label_);
+
+  icon_ = new views::ImageView;
+  if (delegate->GetIcon())
+    icon_->SetImage(delegate->GetIcon());
+  AddChildView(icon_);
+}
+
+AlertInfoBar::~AlertInfoBar() {
+}
+
+// AlertInfoBar, views::View overrides: ----------------------------------------
+
+void AlertInfoBar::Layout() {
+  // Layout the close button.
+  InfoBarView::Layout();
+
+  // Layout the icon and text.
+  gfx::Size icon_size = icon_->GetPreferredSize();
+  icon_->SetBounds(kHorizontalPadding, OffsetY(this, icon_size),
+                   icon_size.width(), icon_size.height());
+
+  gfx::Size text_size = label_->GetPreferredSize();
+  int text_width = std::min(text_size.width(),
+      GetAvailableWidth() - icon_->bounds().right() - kIconLabelSpacing);
+  label_->SetBounds(icon_->bounds().right() + kIconLabelSpacing,
+                    OffsetY(this, text_size), text_width, text_size.height());
+}
+
+// ConfirmInfoBarDelegate -----------------------------------------------------
+
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
+  return new ConfirmInfoBar(this);
+}
+
+// ConfirmInfoBar -------------------------------------------------------------
+
+ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
+    : AlertInfoBar(delegate),
+      ok_button_(NULL),
+      cancel_button_(NULL),
+      link_(NULL),
+      initialized_(false) {
+  ok_button_ = InfoBarTextButton::Create(this,
+      (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) ?
+          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK) :
+          string16());
+  ok_button_->SetAccessibleName(WideToUTF16Hack(ok_button_->text()));
+  cancel_button_ = InfoBarTextButton::Create(this,
+      (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) ?
+          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL) :
+          string16());
+  cancel_button_->SetAccessibleName(WideToUTF16Hack(cancel_button_->text()));
+
+  // Set up the link.
+  link_ = new views::Link;
+  link_->SetText(UTF16ToWideHack(delegate->GetLinkText()));
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  link_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+  link_->SetController(this);
+  link_->MakeReadableOverBackgroundColor(background()->get_color());
+}
+
+ConfirmInfoBar::~ConfirmInfoBar() {
+  if (!initialized_) {
+    delete ok_button_;
+    delete cancel_button_;
+    delete link_;
+  }
+}
+
+void ConfirmInfoBar::Layout() {
+  InfoBarView::Layout();
+
+  int available_width = AlertInfoBar::GetAvailableWidth();
+  int ok_button_width = 0;
+  int cancel_button_width = 0;
+  gfx::Size ok_size = ok_button_->GetPreferredSize();
+  gfx::Size cancel_size = cancel_button_->GetPreferredSize();
+
+  if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) {
+    ok_button_width = ok_size.width();
+  } else {
+    ok_button_->SetVisible(false);
+  }
+  if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
+    cancel_button_width = cancel_size.width();
+  } else {
+    cancel_button_->SetVisible(false);
+  }
+
+  cancel_button_->SetBounds(available_width - cancel_button_width,
+      OffsetY(this, cancel_size), cancel_size.width(), cancel_size.height());
+  int spacing = cancel_button_width > 0 ? kButtonButtonSpacing : 0;
+  ok_button_->SetBounds(cancel_button_->x() - spacing - ok_button_width,
+      OffsetY(this, ok_size), ok_size.width(), ok_size.height());
+
+  // Layout the icon and label.
+  AlertInfoBar::Layout();
+
+  // Now append the link to the label's right edge.
+  link_->SetVisible(!link_->GetText().empty());
+  gfx::Size link_size = link_->GetPreferredSize();
+  int link_x = label()->bounds().right() + kEndOfLabelSpacing;
+  int link_w = std::min(GetAvailableWidth() - link_x, link_size.width());
+  link_->SetBounds(link_x, OffsetY(this, link_size), link_w,
+                   link_size.height());
+}
+
+void ConfirmInfoBar::ViewHierarchyChanged(bool is_add,
+                                          View* parent,
+                                          View* child) {
+  if (is_add && child == this && !initialized_) {
+    AddChildView(ok_button_);
+    AddChildView(cancel_button_);
+    AddChildView(link_);
+    initialized_ = true;
+  }
+
+  // This must happen after adding all other children so InfoBarView can ensure
+  // the close button is the last child.
+  InfoBarView::ViewHierarchyChanged(is_add, parent, child);
+}
+
+int ConfirmInfoBar::GetAvailableWidth() const {
+  return ok_button_->x() - kEndOfLabelSpacing;
+}
+
+void ConfirmInfoBar::ButtonPressed(views::Button* sender,
+                                   const views::Event& event) {
+  ConfirmInfoBarDelegate* delegate = GetDelegate();
+  if (sender == ok_button_) {
+    if (delegate->Accept())
+      RemoveInfoBar();
+  } else if (sender == cancel_button_) {
+    if (delegate->Cancel())
+      RemoveInfoBar();
+  } else {
+    InfoBarView::ButtonPressed(sender, event);
+  }
+}
+
+void ConfirmInfoBar::LinkActivated(views::Link* source, int event_flags) {
+  DCHECK_EQ(link_, source);
+  if (GetDelegate()->LinkClicked(
+      event_utils::DispositionFromEventFlags(event_flags)))
+    RemoveInfoBar();
+}
+
+ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
+  return delegate()->AsConfirmInfoBarDelegate();
+}
diff --git a/chrome/browser/ui/views/infobars/confirm_infobar.h b/chrome/browser/ui/views/infobars/confirm_infobar.h
new file mode 100644
index 0000000..15aac4b
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/confirm_infobar.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_VIEWS_INFOBARS_CONFIRM_INFOBAR_H_
+#define CHROME_BROWSER_UI_VIEWS_INFOBARS_CONFIRM_INFOBAR_H_
+#pragma once
+
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
+#include "views/controls/link.h"
+
+class ConfirmInfoBarDelegate;
+class InfoBarTextButton;
+namespace views {
+class Label;
+}
+
+// TODO(pkasting): This class will die soon.
+class AlertInfoBar : public InfoBarView {
+ public:
+  explicit AlertInfoBar(ConfirmInfoBarDelegate* delegate);
+  virtual ~AlertInfoBar();
+
+  // Overridden from views::View:
+  virtual void Layout();
+
+ protected:
+  views::Label* label() const { return label_; }
+  views::ImageView* icon() const { return icon_; }
+
+ private:
+  views::Label* label_;
+  views::ImageView* icon_;
+
+  DISALLOW_COPY_AND_ASSIGN(AlertInfoBar);
+};
+
+// An infobar that shows a message, up to two optional buttons, and an optional,
+// right-aligned link.  This is commonly used to do things like:
+// "Would you like to do X?  [Yes]  [No]               _Learn More_ [x]"
+// TODO(pkasting): The above layout is the desired, but not current, layout; fix
+// coming in a future patch.
+class ConfirmInfoBar : public AlertInfoBar,
+                       public views::LinkController {
+ public:
+  explicit ConfirmInfoBar(ConfirmInfoBarDelegate* delegate);
+
+ private:
+  virtual ~ConfirmInfoBar();
+
+  // InfoBarView:
+  virtual void Layout();
+  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
+  virtual int GetAvailableWidth() const;
+  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+
+  // views::LinkController:
+  virtual void LinkActivated(views::Link* source, int event_flags);
+
+  ConfirmInfoBarDelegate* GetDelegate();
+
+  InfoBarTextButton* ok_button_;
+  InfoBarTextButton* cancel_button_;
+  views::Link* link_;
+
+  bool initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_INFOBARS_CONFIRM_INFOBAR_H_
diff --git a/chrome/browser/ui/views/infobars/extension_infobar.cc b/chrome/browser/ui/views/infobars/extension_infobar.cc
index 9540b5d..7d5a404 100644
--- a/chrome/browser/ui/views/infobars/extension_infobar.cc
+++ b/chrome/browser/ui/views/infobars/extension_infobar.cc
@@ -1,139 +1,136 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/extension_infobar.h"
+#include "chrome/browser/ui/views/infobars/extension_infobar.h"
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/extensions/extension_context_menu_model.h"
-#include "chrome/browser/extensions/extension_infobar_delegate.h"
 #include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_infobar_delegate.h"
 #include "chrome/browser/platform_util.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/infobars/infobar_background.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/extension_resource.h"
-#include "gfx/canvas_skia.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/menu/menu_2.h"
 #include "views/widget/widget.h"
 
+// ExtensionInfoBarDelegate ---------------------------------------------------
+
+InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() {
+  return new ExtensionInfoBar(this);
+}
+
+// ExtensionInfoBar -----------------------------------------------------------
+
+namespace {
 // The horizontal margin between the menu and the Extension (HTML) view.
 static const int kMenuHorizontalMargin = 1;
 
 // The amount of space to the right of the Extension (HTML) view (to avoid
 // overlapping the close button for the InfoBar).
 static const int kFarRightMargin = 30;
-
-// The margin between the extension icon and the drop-down arrow bitmap.
-static const int kDropArrowLeftMargin = 3;
+};
 
 ExtensionInfoBar::ExtensionInfoBar(ExtensionInfoBarDelegate* delegate)
-    : InfoBar(delegate),
+    : InfoBarView(delegate),
       delegate_(delegate),
       ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) {
-  delegate_->set_observer(this);
+  delegate->set_observer(this);
 
-  ExtensionHost* extension_host = delegate_->extension_host();
-
-  // We set the target height for the InfoBar to be the height of the
-  // ExtensionView it contains (plus 1 because the view should not overlap the
-  // separator line at the bottom). When the InfoBar is first created, however,
-  // this value is 0 but becomes positive after the InfoBar has been shown. See
-  // function: OnExtensionPreferredSizeChanged.
-  gfx::Size sz = extension_host->view()->GetPreferredSize();
-  if (sz.height() > 0)
-    sz.set_height(sz.height() + 1);
-  set_target_height(sz.height());
+  ExtensionView* extension_view = delegate->extension_host()->view();
+  int height = extension_view->GetPreferredSize().height();
+  set_target_height((height > 0) ?
+      (height + InfoBarBackground::kSeparatorLineHeight) : height);
 
   // Setup the extension icon and its associated drop down menu.
   SetupIconAndMenu();
 
   // Get notified of resize events for the ExtensionView.
-  extension_host->view()->SetContainer(this);
+  extension_view->SetContainer(this);
   // We show the ExtensionView, but we don't want it deleted when we get
   // destroyed, which happens on tab switching (for example).
-  extension_host->view()->set_parent_owned(false);
-  AddChildView(extension_host->view());
+  extension_view->set_parent_owned(false);
+  AddChildView(extension_view);
 }
 
 ExtensionInfoBar::~ExtensionInfoBar() {
-  if (delegate_) {
-    delegate_->extension_host()->view()->SetContainer(NULL);
-    delegate_->set_observer(NULL);
+  if (GetDelegate()) {
+    GetDelegate()->extension_host()->view()->SetContainer(NULL);
+    GetDelegate()->set_observer(NULL);
   }
 }
 
+void ExtensionInfoBar::Layout() {
+  InfoBarView::Layout();
+
+  gfx::Size menu_size = menu_->GetPreferredSize();
+  menu_->SetBounds(0, (height() - menu_size.height()) / 2, menu_size.width(),
+                   menu_size.height());
+
+  int x = menu_->bounds().right() + kMenuHorizontalMargin;
+  GetDelegate()->extension_host()->view()->SetBounds(x, 0,
+      width() - x - kFarRightMargin - 1, height() - 1);
+}
+
+void ExtensionInfoBar::OnExtensionMouseMove(ExtensionView* view) {
+}
+
+void ExtensionInfoBar::OnExtensionMouseLeave(ExtensionView* view) {
+}
+
 void ExtensionInfoBar::OnExtensionPreferredSizeChanged(ExtensionView* view) {
-  DCHECK(view == delegate_->extension_host()->view());
+  ExtensionInfoBarDelegate* delegate = GetDelegate();
+  DCHECK_EQ(delegate->extension_host()->view(), view);
 
   // When the infobar is closed, it animates to 0 vertical height. We'll
   // continue to get size changed notifications from the ExtensionView, but we
   // need to ignore them otherwise we'll try to re-animate open (and leak the
   // infobar view).
-  if (delegate_->closing())
+  if (delegate->closing())
     return;
 
-  delegate_->extension_host()->view()->SetVisible(true);
-
-  gfx::Size sz = view->GetPreferredSize();
-  // Clamp height to a min and a max size of between 1 and 2 InfoBars.
-  int default_height = static_cast<int>(InfoBar::kDefaultTargetHeight);
-  sz.set_height(std::max(default_height, sz.height()));
-  sz.set_height(std::min(2 * default_height, sz.height()));
+  view->SetVisible(true);
 
   if (height() == 0)
     animation()->Reset(0.0);
-  set_target_height(sz.height());
+
+  // Clamp height to a min and a max size of between 1 and 2 InfoBars.
+  set_target_height(std::min(2 * kDefaultTargetHeight,
+      std::max(kDefaultTargetHeight, view->GetPreferredSize().height())));
+
   animation()->Show();
 }
 
-void ExtensionInfoBar::Layout() {
-  // Layout the close button and the background.
-  InfoBar::Layout();
-
-  // Layout the extension icon + drop down menu.
-  int x = 0;
-  gfx::Size sz = menu_->GetPreferredSize();
-  menu_->SetBounds(x,
-                  (height() - sz.height()) / 2,
-                   sz.width(), sz.height());
-  x += sz.width() + kMenuHorizontalMargin;
-
-  // Layout the ExtensionView, showing the HTML InfoBar.
-  ExtensionView* view = delegate_->extension_host()->view();
-  view->SetBounds(x, 0, width() - x - kFarRightMargin - 1, height() - 1);
-}
-
-void ExtensionInfoBar::OnImageLoaded(
-    SkBitmap* image, ExtensionResource resource, int index) {
-  if (!delegate_)
+void ExtensionInfoBar::OnImageLoaded(SkBitmap* image,
+                                     ExtensionResource resource,
+                                     int index) {
+  if (!GetDelegate())
     return;  // The delegate can go away while we asynchronously load images.
 
+  SkBitmap* icon = image;
+  // Fall back on the default extension icon on failure.
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
-  // We fall back on the default extension icon on failure.
-  SkBitmap* icon;
   if (!image || image->empty())
     icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
-  else
-    icon = image;
 
   SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW);
 
   int image_size = Extension::EXTENSION_ICON_BITTY;
-  scoped_ptr<gfx::CanvasSkia> canvas(
-      new gfx::CanvasSkia(
-          image_size + kDropArrowLeftMargin + drop_image->width(),
-          image_size, false));
-  canvas->DrawBitmapInt(*icon,
-                        0, 0, icon->width(), icon->height(),
-                        0, 0, image_size, image_size,
-                        false);
-  canvas->DrawBitmapInt(*drop_image,
-                        image_size + kDropArrowLeftMargin,
+  // The margin between the extension icon and the drop-down arrow bitmap.
+  static const int kDropArrowLeftMargin = 3;
+  scoped_ptr<gfx::CanvasSkia> canvas(new gfx::CanvasSkia(
+      image_size + kDropArrowLeftMargin + drop_image->width(), image_size,
+      false));
+  canvas->DrawBitmapInt(*icon, 0, 0, icon->width(), icon->height(), 0, 0,
+                        image_size, image_size, false);
+  canvas->DrawBitmapInt(*drop_image, image_size + kDropArrowLeftMargin,
                         image_size / 2);
   menu_->SetIcon(canvas->ExtractBitmap());
   menu_->SetVisible(true);
@@ -142,17 +139,21 @@
 }
 
 void ExtensionInfoBar::OnDelegateDeleted() {
-  delegate_->extension_host()->view()->SetContainer(NULL);
+  GetDelegate()->extension_host()->view()->SetContainer(NULL);
   delegate_ = NULL;
 }
 
 void ExtensionInfoBar::RunMenu(View* source, const gfx::Point& pt) {
+  const Extension* extension = GetDelegate()->extension_host()->extension();
+  if (!extension->ShowConfigureContextMenus())
+    return;
+
   if (!options_menu_contents_.get()) {
     Browser* browser = BrowserView::GetBrowserViewForNativeWindow(
         platform_util::GetTopLevel(source->GetWidget()->GetNativeView()))->
             browser();
-    options_menu_contents_ = new ExtensionContextMenuModel(
-        delegate_->extension_host()->extension(), browser, NULL);
+    options_menu_contents_ = new ExtensionContextMenuModel(extension, browser,
+                                                           NULL);
   }
 
   options_menu_menu_.reset(new views::Menu2(options_menu_contents_.get()));
@@ -164,20 +165,18 @@
   menu_->SetVisible(false);
   AddChildView(menu_);
 
-  const Extension* extension = delegate_->extension_host()->extension();
+  const Extension* extension = GetDelegate()->extension_host()->extension();
+  int image_size = Extension::EXTENSION_ICON_BITTY;
   ExtensionResource icon_resource = extension->GetIconResource(
-      Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY);
+      image_size, ExtensionIconSet::MATCH_EXACTLY);
   if (!icon_resource.relative_path().empty()) {
-    // Create a tracker to load the image. It will report back on OnImageLoaded.
     tracker_.LoadImage(extension, icon_resource,
-                       gfx::Size(Extension::EXTENSION_ICON_BITTY,
-                                 Extension::EXTENSION_ICON_BITTY),
-                       ImageLoadingTracker::DONT_CACHE);
+        gfx::Size(image_size, image_size), ImageLoadingTracker::DONT_CACHE);
   } else {
-    OnImageLoaded(NULL, icon_resource, 0);  // |image|, |index|.
+    OnImageLoaded(NULL, icon_resource, 0);
   }
 }
 
-InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() {
-  return new ExtensionInfoBar(this);
+ExtensionInfoBarDelegate* ExtensionInfoBar::GetDelegate() {
+  return delegate_ ? delegate_->AsExtensionInfoBarDelegate() : NULL;
 }
diff --git a/chrome/browser/ui/views/infobars/extension_infobar.h b/chrome/browser/ui/views/infobars/extension_infobar.h
index 71cfa0a..9a7068a 100644
--- a/chrome/browser/ui/views/infobars/extension_infobar.h
+++ b/chrome/browser/ui/views/infobars/extension_infobar.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,57 +6,61 @@
 #define CHROME_BROWSER_UI_VIEWS_INFOBARS_EXTENSION_INFOBAR_H_
 #pragma once
 
-#include "chrome/browser/views/infobars/infobars.h"
-
 #include "chrome/browser/extensions/extension_infobar_delegate.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
-#include "chrome/browser/views/extensions/extension_view.h"
+#include "chrome/browser/ui/views/extensions/extension_view.h"
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
 #include "views/controls/menu/view_menu_delegate.h"
 
 class ExtensionContextMenuModel;
-class ExtensionInfoBarDelegate;
-
 namespace views {
-  class MenuButton;
-  class Menu2;
+class MenuButton;
+class Menu2;
 }
 
 // This class implements InfoBars for Extensions.
-class ExtensionInfoBar : public InfoBar,
+class ExtensionInfoBar : public InfoBarView,
                          public ExtensionView::Container,
                          public ImageLoadingTracker::Observer,
                          public ExtensionInfoBarDelegate::DelegateObserver,
                          public views::ViewMenuDelegate {
  public:
   explicit ExtensionInfoBar(ExtensionInfoBarDelegate* delegate);
-  virtual ~ExtensionInfoBar();
-
-  // Overridden from ExtensionView::Container:
-  virtual void OnExtensionMouseMove(ExtensionView* view) {}
-  virtual void OnExtensionMouseLeave(ExtensionView* view) {}
-  virtual void OnExtensionPreferredSizeChanged(ExtensionView* view);
-
-  // Overridden from views::View:
-  virtual void Layout();
-
-  // Overridden from ImageLoadingTracker::Observer:
-  virtual void OnImageLoaded(
-      SkBitmap* image, ExtensionResource resource, int index);
-
-  // Overridden from ExtensionInfoBarDelegate::DelegateObserver:
-  virtual void OnDelegateDeleted();
-
-  // Overridden from views::ViewMenuDelegate:
-  virtual void RunMenu(View* source, const gfx::Point& pt);
 
  private:
+  virtual ~ExtensionInfoBar();
+
+  // InfoBarView:
+  virtual void Layout();
+
+  // ExtensionView::Container:
+  virtual void OnExtensionMouseMove(ExtensionView* view);
+  virtual void OnExtensionMouseLeave(ExtensionView* view);
+  virtual void OnExtensionPreferredSizeChanged(ExtensionView* view);
+
+  // ImageLoadingTracker::Observer:
+  virtual void OnImageLoaded(SkBitmap* image,
+                             ExtensionResource resource,
+                             int index);
+
+  // ExtensionInfoBarDelegate::DelegateObserver:
+  virtual void OnDelegateDeleted();
+
+  // views::ViewMenuDelegate:
+  virtual void RunMenu(View* source, const gfx::Point& pt);
+
   // Setup the menu button showing the small extension icon and its dropdown
   // menu.
   void SetupIconAndMenu();
 
+  ExtensionInfoBarDelegate* GetDelegate();
+
   NotificationRegistrar notification_registrar_;
 
-  ExtensionInfoBarDelegate* delegate_;
+  // TODO(pkasting): This shadows InfoBarView::delegate_.  Get rid of this once
+  // InfoBars own their delegates (and thus we don't need the DelegateObserver
+  // functionality).  For now, almost everyone should use GetDelegate() instead.
+  InfoBarDelegate* delegate_;
 
   // The dropdown menu for accessing the contextual extension actions.
   scoped_refptr<ExtensionContextMenuModel> options_menu_contents_;
diff --git a/chrome/browser/ui/views/infobars/infobar_background.cc b/chrome/browser/ui/views/infobars/infobar_background.cc
new file mode 100644
index 0000000..71fa45c
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/infobar_background.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/views/infobars/infobar_background.h"
+
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "views/view.h"
+
+// static
+const int InfoBarBackground::kSeparatorLineHeight = 1;
+
+InfoBarBackground::InfoBarBackground(InfoBarDelegate::Type infobar_type) {
+  gradient_background_.reset(
+      views::Background::CreateVerticalGradientBackground(
+          GetTopColor(infobar_type),
+          GetBottomColor(infobar_type)));
+}
+
+InfoBarBackground::~InfoBarBackground() {
+}
+
+SkColor InfoBarBackground::GetTopColor(InfoBarDelegate::Type infobar_type) {
+  static const SkColor kWarningBackgroundColorTop =
+      SkColorSetRGB(255, 242, 183);
+  static const SkColor kPageActionBackgroundColorTop =
+      SkColorSetRGB(218, 231, 249);
+
+  return (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
+      kWarningBackgroundColorTop : kPageActionBackgroundColorTop;
+}
+
+SkColor InfoBarBackground::GetBottomColor(InfoBarDelegate::Type infobar_type) {
+  static const SkColor kWarningBackgroundColorBottom =
+      SkColorSetRGB(250, 230, 145);
+  static const SkColor kPageActionBackgroundColorBottom =
+      SkColorSetRGB(179, 202, 231);
+
+  return (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
+      kWarningBackgroundColorBottom : kPageActionBackgroundColorBottom;
+}
+
+void InfoBarBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
+  gradient_background_->Paint(canvas, view);
+  canvas->FillRectInt(ResourceBundle::toolbar_separator_color, 0,
+                      view->height() - kSeparatorLineHeight, view->width(),
+                      kSeparatorLineHeight);
+}
diff --git a/chrome/browser/ui/views/infobars/infobar_background.h b/chrome/browser/ui/views/infobars/infobar_background.h
new file mode 100644
index 0000000..1849588
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/infobar_background.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_BACKGROUND_H_
+#define CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_BACKGROUND_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "views/background.h"
+
+class InfoBarBackground : public views::Background {
+ public:
+  static const int kSeparatorLineHeight;
+
+  explicit InfoBarBackground(InfoBarDelegate::Type infobar_type);
+  virtual ~InfoBarBackground();
+
+  static SkColor GetTopColor(InfoBarDelegate::Type infobar_type);
+  static SkColor GetBottomColor(InfoBarDelegate::Type infobar_type);
+
+ private:
+  // views::Background:
+  virtual void Paint(gfx::Canvas* canvas, views::View* view) const;
+
+  scoped_ptr<views::Background> gradient_background_;
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBarBackground);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_BACKGROUND_H_
diff --git a/chrome/browser/ui/views/infobars/infobar_button_border.cc b/chrome/browser/ui/views/infobars/infobar_button_border.cc
index ed65885..981f3d5 100644
--- a/chrome/browser/ui/views/infobars/infobar_button_border.cc
+++ b/chrome/browser/ui/views/infobars/infobar_button_border.cc
@@ -1,23 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/infobar_button_border.h"
+#include "chrome/browser/ui/views/infobars/infobar_button_border.h"
 
-#include "app/resource_bundle.h"
-#include "gfx/canvas.h"
 #include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/button/text_button.h"
 
-// Preferred padding between text and edge
-static const int kPreferredPaddingHorizontal = 6;
-static const int kPreferredPaddingVertical = 5;
-
-// InfoBarButtonBorder, public: ----------------------------------------------
-
 InfoBarButtonBorder::InfoBarButtonBorder() {
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
   normal_set_.top_left = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_LEFT_N);
   normal_set_.top = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_N);
   normal_set_.top_right = rb.GetBitmapNamed(IDR_INFOBARBUTTON_TOP_RIGHT_N);
@@ -54,9 +48,9 @@
 InfoBarButtonBorder::~InfoBarButtonBorder() {
 }
 
-// InfoBarButtonBorder, Border overrides: ------------------------------------
-
 void InfoBarButtonBorder::GetInsets(gfx::Insets* insets) const {
+  static const int kPreferredPaddingHorizontal = 6;
+  static const int kPreferredPaddingVertical = 5;
   insets->Set(kPreferredPaddingVertical, kPreferredPaddingHorizontal,
               kPreferredPaddingVertical, kPreferredPaddingHorizontal);
 }
@@ -65,25 +59,19 @@
                                 gfx::Canvas* canvas) const {
   const views::TextButton* mb = static_cast<const views::TextButton*>(&view);
   int state = mb->state();
-
-  // TextButton takes care of deciding when to call Paint.
   const MBBImageSet* set = &normal_set_;
   if (state == views::TextButton::BS_HOT)
     set = &hot_set_;
   else if (state == views::TextButton::BS_PUSHED)
     set = &pushed_set_;
 
-  gfx::Rect bounds = view.bounds();
-
   // Draw top left image.
   canvas->DrawBitmapInt(*set->top_left, 0, 0);
 
   // Stretch top image.
-  canvas->DrawBitmapInt(
-      *set->top,
-      0, 0, set->top->width(), set->top->height(),
-      set->top_left->width(),
-      0,
+  const gfx::Rect& bounds = view.bounds();
+  canvas->DrawBitmapInt(*set->top, 0, 0, set->top->width(), set->top->height(),
+      set->top_left->width(), 0,
       bounds.width() - set->top_right->width() - set->top_left->width(),
       set->top->height(), false);
 
@@ -92,46 +80,32 @@
                         bounds.width() - set->top_right->width(), 0);
 
   // Stretch left image.
-  canvas->DrawBitmapInt(
-      *set->left,
-      0, 0, set->left->width(), set->left->height(),
-      0,
-      set->top_left->height(),
-      set->top_left->width(),
+  canvas->DrawBitmapInt(*set->left, 0, 0, set->left->width(),
+      set->left->height(), 0, set->top_left->height(), set->top_left->width(),
       bounds.height() - set->top->height() - set->bottom_left->height(), false);
 
   // Stretch center image.
-  canvas->DrawBitmapInt(
-      *set->center,
-      0, 0, set->center->width(), set->center->height(),
-      set->left->width(),
-      set->top->height(),
+  canvas->DrawBitmapInt(*set->center, 0, 0, set->center->width(),
+      set->center->height(), set->left->width(), set->top->height(),
       bounds.width() - set->right->width() - set->left->width(),
       bounds.height() - set->bottom->height() - set->top->height(), false);
 
   // Stretch right image.
-  canvas->DrawBitmapInt(
-      *set->right,
-      0, 0, set->right->width(), set->right->height(),
-      bounds.width() - set->right->width(),
-      set->top_right->height(),
-      set->right->width(),
-      bounds.height() - set->bottom_right->height() -
-          set->top_right->height(), false);
+  canvas->DrawBitmapInt(*set->right, 0, 0, set->right->width(),
+      set->right->height(), bounds.width() - set->right->width(),
+      set->top_right->height(), set->right->width(),
+      bounds.height() - set->bottom_right->height() - set->top_right->height(),
+      false);
 
   // Draw bottom left image.
-  canvas->DrawBitmapInt(*set->bottom_left,
-                        0,
+  canvas->DrawBitmapInt(*set->bottom_left, 0,
                         bounds.height() - set->bottom_left->height());
 
   // Stretch bottom image.
-  canvas->DrawBitmapInt(
-      *set->bottom,
-      0, 0, set->bottom->width(), set->bottom->height(),
-      set->bottom_left->width(),
+  canvas->DrawBitmapInt(*set->bottom, 0, 0, set->bottom->width(),
+      set->bottom->height(), set->bottom_left->width(),
       bounds.height() - set->bottom->height(),
-      bounds.width() - set->bottom_right->width() -
-          set->bottom_left->width(),
+      bounds.width() - set->bottom_right->width() - set->bottom_left->width(),
       set->bottom->height(), false);
 
   // Draw bottom right image.
diff --git a/chrome/browser/ui/views/infobars/infobar_button_border.h b/chrome/browser/ui/views/infobars/infobar_button_border.h
index c8cfa83..fccdd87 100644
--- a/chrome/browser/ui/views/infobars/infobar_button_border.h
+++ b/chrome/browser/ui/views/infobars/infobar_button_border.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,7 @@
 
 #include "views/border.h"
 
-#include "third_party/skia/include/core/SkBitmap.h"
-
+class SkBitmap;
 namespace gfx {
 class Canvas;
 }
@@ -19,18 +18,17 @@
 
 // A TextButtonBorder that is dark and also paints the button frame in the
 // normal state.
-
 class InfoBarButtonBorder : public views::Border {
  public:
   InfoBarButtonBorder();
+
+ private:
   virtual ~InfoBarButtonBorder();
 
-  // Overriden from Border:
+  // views::Border:
   virtual void GetInsets(gfx::Insets* insets) const;
   virtual void Paint(const views::View& view, gfx::Canvas* canvas) const;
 
- private:
-   // Images
   struct MBBImageSet {
     SkBitmap* top_left;
     SkBitmap* top;
diff --git a/chrome/browser/ui/views/infobars/infobar_container.cc b/chrome/browser/ui/views/infobars/infobar_container.cc
index e9706ff..f7148f1 100644
--- a/chrome/browser/ui/views/infobars/infobar_container.cc
+++ b/chrome/browser/ui/views/infobars/infobar_container.cc
@@ -1,27 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/infobar_container.h"
+#include "chrome/browser/ui/views/infobars/infobar_container.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/tab_contents/infobar_delegate.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/view_ids.h"
-#include "chrome/browser/ui/views/infobars/infobars.h"
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "grit/generated_resources.h"
-
-// InfoBarContainer, public: ---------------------------------------------------
+#include "ui/base/l10n/l10n_util.h"
 
 InfoBarContainer::InfoBarContainer(Delegate* delegate)
     : delegate_(delegate),
       tab_contents_(NULL) {
   SetID(VIEW_ID_INFO_BAR_CONTAINER);
   SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_INFOBAR_CONTAINER)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_INFOBAR_CONTAINER));
 }
 
 InfoBarContainer::~InfoBarContainer() {
@@ -35,7 +33,7 @@
 void InfoBarContainer::ChangeTabContents(TabContents* contents) {
   registrar_.RemoveAll();
   // No need to delete the child views here, their removal from the view
-  // hierarchy does this automatically (see InfoBar::InfoBarRemoved).
+  // hierarchy does this automatically (see InfoBarView::InfoBarRemoved).
   RemoveAllChildViews(false);
   tab_contents_ = contents;
   if (tab_contents_) {
@@ -52,29 +50,36 @@
 
 void InfoBarContainer::InfoBarAnimated(bool completed) {
   if (delegate_)
-    delegate_->InfoBarSizeChanged(!completed);
+    delegate_->InfoBarContainerSizeChanged(!completed);
 }
 
 void InfoBarContainer::RemoveDelegate(InfoBarDelegate* delegate) {
   tab_contents_->RemoveInfoBar(delegate);
 }
 
-// InfoBarContainer, views::View overrides: ------------------------------------
+void InfoBarContainer::PaintInfoBarArrows(gfx::Canvas* canvas,
+                                          View* outer_view,
+                                          int arrow_center_x) {
+  for (int i = 0; i < child_count(); ++i) {
+    InfoBarView* infobar = static_cast<InfoBarView*>(GetChildViewAt(i));
+    infobar->PaintArrow(canvas, outer_view, arrow_center_x);
+  }
+}
 
 gfx::Size InfoBarContainer::GetPreferredSize() {
   // We do not have a preferred width (we will expand to fit the available width
-  // of the delegate). Our preferred height is the sum of the preferred
-  // heights of the InfoBars contained within us.
+  // of the delegate). Our preferred height is the sum of the preferred heights
+  // of the InfoBars contained within us.
   int height = 0;
-  for (int i = 0; i < GetChildViewCount(); ++i)
+  for (int i = 0; i < child_count(); ++i)
     height += GetChildViewAt(i)->GetPreferredSize().height();
   return gfx::Size(0, height);
 }
 
 void InfoBarContainer::Layout() {
   int top = 0;
-  for (int i = 0; i < GetChildViewCount(); ++i) {
-    views::View* child = GetChildViewAt(i);
+  for (int i = 0; i < child_count(); ++i) {
+    View* child = GetChildViewAt(i);
     gfx::Size ps = child->GetPreferredSize();
     child->SetBounds(0, top, width(), ps.height());
     top += ps.height();
@@ -86,19 +91,17 @@
 }
 
 void InfoBarContainer::ViewHierarchyChanged(bool is_add,
-                                            views::View* parent,
-                                            views::View* child) {
-  if (parent == this && child->GetParent() == this) {
+                                            View* parent,
+                                            View* child) {
+  if (parent == this && child->parent() == this) {
     if (delegate_) {
       // An InfoBar child was added or removed. Tell the delegate it needs to
       // re-layout since our preferred size will have changed.
-      delegate_->InfoBarSizeChanged(false);
+      delegate_->InfoBarContainerSizeChanged(false);
     }
   }
 }
 
-// InfoBarContainer, NotificationObserver implementation: ----------------------
-
 void InfoBarContainer::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {
@@ -115,12 +118,10 @@
   }
 }
 
-// InfoBarContainer, private: --------------------------------------------------
-
 void InfoBarContainer::UpdateInfoBars() {
-  for (int i = 0; i < tab_contents_->infobar_delegate_count(); ++i) {
+  for (size_t i = 0; i < tab_contents_->infobar_count(); ++i) {
     InfoBarDelegate* delegate = tab_contents_->GetInfoBarDelegateAt(i);
-    InfoBar* infobar = delegate->CreateInfoBar();
+    InfoBarView* infobar = static_cast<InfoBarView*>(delegate->CreateInfoBar());
     infobar->set_container(this);
     AddChildView(infobar);
     infobar->Open();
@@ -129,7 +130,7 @@
 
 void InfoBarContainer::AddInfoBar(InfoBarDelegate* delegate,
                                   bool use_animation) {
-  InfoBar* infobar = delegate->CreateInfoBar();
+  InfoBarView* infobar = static_cast<InfoBarView*>(delegate->CreateInfoBar());
   infobar->set_container(this);
   AddChildView(infobar);
 
@@ -146,8 +147,8 @@
   // a child view until its close animation completes, which can result in
   // different number of infobars in container and infobar delegates in tab
   // contents.
-  for (int i = 0; i < GetChildViewCount(); ++i) {
-    InfoBar* infobar = static_cast<InfoBar*>(GetChildViewAt(i));
+  for (int i = 0; i < child_count(); ++i) {
+    InfoBarView* infobar = static_cast<InfoBarView*>(GetChildViewAt(i));
     if (infobar->delegate() == delegate) {
       if (use_animation) {
         // The View will be removed once the Close animation completes.
diff --git a/chrome/browser/ui/views/infobars/infobar_container.h b/chrome/browser/ui/views/infobars/infobar_container.h
index c3a48fb..9d03acb 100644
--- a/chrome/browser/ui/views/infobars/infobar_container.h
+++ b/chrome/browser/ui/views/infobars/infobar_container.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
 #pragma once
 
-#include "chrome/browser/views/accessible_pane_view.h"
+#include "chrome/browser/ui/views/accessible_pane_view.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 #include "views/view.h"
@@ -25,7 +25,7 @@
   class Delegate {
    public:
     virtual ~Delegate() {}
-    virtual void InfoBarSizeChanged(bool is_animating) = 0;
+    virtual void InfoBarContainerSizeChanged(bool is_animating) = 0;
   };
 
   explicit InfoBarContainer(Delegate* delegate);
@@ -44,18 +44,21 @@
   // the InfoBar's close button handler.
   void RemoveDelegate(InfoBarDelegate* delegate);
 
-  // Overridden from views::View:
+  // Paint the InfoBar arrows on |canvas|. |arrow_center_x| indicates
+  // the desired location of the center of the arrow in the
+  // |outer_view| coordinate system.
+  void PaintInfoBarArrows(gfx::Canvas* canvas,
+                          View* outer_view,
+                          int arrow_center_x);
+
+ private:
+  // AccessiblePaneView:
   virtual gfx::Size GetPreferredSize();
   virtual void Layout();
   virtual AccessibilityTypes::Role GetAccessibleRole();
+  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
 
- protected:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
-
- private:
-  // Overridden from NotificationObserver:
+  // NotificationObserver:
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
                        const NotificationDetails& details);
diff --git a/chrome/browser/ui/views/infobars/infobar_text_button.cc b/chrome/browser/ui/views/infobars/infobar_text_button.cc
index ebf5d22..5adabc7 100644
--- a/chrome/browser/ui/views/infobars/infobar_text_button.cc
+++ b/chrome/browser/ui/views/infobars/infobar_text_button.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/infobar_text_button.h"
+#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/views/infobars/infobar_button_border.h"
+#include "chrome/browser/ui/views/infobars/infobar_button_border.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 // static
 InfoBarTextButton* InfoBarTextButton::Create(views::ButtonListener* listener,
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc
new file mode 100644
index 0000000..06d2c9f
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -0,0 +1,281 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
+
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/views/infobars/infobar_background.h"
+#include "chrome/browser/ui/views/infobars/infobar_container.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "views/controls/button/image_button.h"
+#include "views/controls/image_view.h"
+#include "views/controls/label.h"
+#include "views/focus/external_focus_tracker.h"
+#include "views/widget/widget.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/hwnd_util.h"
+#endif
+
+// static
+const int InfoBarView::kDefaultTargetHeight = 36;
+const int InfoBarView::kHorizontalPadding = 6;
+const int InfoBarView::kIconLabelSpacing = 6;
+const int InfoBarView::kButtonButtonSpacing = 10;
+const int InfoBarView::kEndOfLabelSpacing = 16;
+
+InfoBarView::InfoBarView(InfoBarDelegate* delegate)
+    : InfoBar(delegate),
+      delegate_(delegate),
+      ALLOW_THIS_IN_INITIALIZER_LIST(
+          close_button_(new views::ImageButton(this))),
+      ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)),
+      target_height_(kDefaultTargetHeight) {
+  set_parent_owned(false);  // InfoBar deletes itself at the appropriate time.
+
+  InfoBarDelegate::Type infobar_type = delegate->GetInfoBarType();
+  set_background(new InfoBarBackground(infobar_type));
+  SetAccessibleName(l10n_util::GetStringUTF16(
+      (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
+      IDS_ACCNAME_INFOBAR_WARNING : IDS_ACCNAME_INFOBAR_PAGE_ACTION));
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  close_button_->SetImage(views::CustomButton::BS_NORMAL,
+                          rb.GetBitmapNamed(IDR_CLOSE_BAR));
+  close_button_->SetImage(views::CustomButton::BS_HOT,
+                          rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
+  close_button_->SetImage(views::CustomButton::BS_PUSHED,
+                          rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
+  close_button_->SetAccessibleName(
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
+  close_button_->SetFocusable(true);
+  AddChildView(close_button_);
+
+  animation_.reset(new ui::SlideAnimation(this));
+  animation_->SetTweenType(ui::Tween::LINEAR);
+}
+
+void InfoBarView::AnimateOpen() {
+  animation_->Show();
+}
+
+void InfoBarView::Open() {
+  // Set the animation value to 1.0 so that GetPreferredSize() returns the right
+  // size.
+  animation_->Reset(1.0);
+  if (container_)
+    container_->InfoBarAnimated(false);
+}
+
+void InfoBarView::AnimateClose() {
+  bool restore_focus = true;
+#if defined(OS_WIN)
+  // Do not restore focus (and active state with it) on Windows if some other
+  // top-level window became active.
+  if (GetWidget() &&
+      !ui::DoesWindowBelongToActiveWindow(GetWidget()->GetNativeView()))
+    restore_focus = false;
+#endif  // defined(OS_WIN)
+  DestroyFocusTracker(restore_focus);
+  animation_->Hide();
+}
+
+void InfoBarView::Close() {
+  parent()->RemoveChildView(this);
+  // Note that we only tell the delegate we're closed here, and not when we're
+  // simply destroyed (by virtue of a tab switch or being moved from window to
+  // window), since this action can cause the delegate to destroy itself.
+  if (delegate_) {
+    delegate_->InfoBarClosed();
+    delegate_ = NULL;
+  }
+}
+
+void InfoBarView::PaintArrow(gfx::Canvas* canvas,
+                             View* outer_view,
+                             int arrow_center_x) {
+  gfx::Point infobar_top(0, y());
+  ConvertPointToView(parent(), outer_view, &infobar_top);
+  int infobar_top_y = infobar_top.y();
+  SkPoint gradient_points[2] = {
+      {SkIntToScalar(0), SkIntToScalar(infobar_top_y)},
+      {SkIntToScalar(0), SkIntToScalar(infobar_top_y + target_height_)}
+  };
+  InfoBarDelegate::Type infobar_type = delegate_->GetInfoBarType();
+  SkColor gradient_colors[2] = {
+      InfoBarBackground::GetTopColor(infobar_type),
+      InfoBarBackground::GetBottomColor(infobar_type),
+  };
+  SkShader* gradient_shader = SkGradientShader::CreateLinear(gradient_points,
+      gradient_colors, NULL, 2, SkShader::kMirror_TileMode);
+  SkPaint paint;
+  paint.setStrokeWidth(1);
+  paint.setStyle(SkPaint::kFill_Style);
+  paint.setShader(gradient_shader);
+  gradient_shader->unref();
+
+  // The size of the arrow (its height; also half its width).  The
+  // arrow area is |arrow_size| ^ 2.  By taking the square root of the
+  // animation value, we cause a linear animation of the area, which
+  // matches the perception of the animation of the InfoBar.
+  const int kArrowSize = 10;
+  int arrow_size = static_cast<int>(kArrowSize *
+                                    sqrt(animation_->GetCurrentValue()));
+  SkPath fill_path;
+  fill_path.moveTo(SkPoint::Make(SkIntToScalar(arrow_center_x - arrow_size),
+                                 SkIntToScalar(infobar_top_y)));
+  fill_path.rLineTo(SkIntToScalar(arrow_size), SkIntToScalar(-arrow_size));
+  fill_path.rLineTo(SkIntToScalar(arrow_size), SkIntToScalar(arrow_size));
+  SkPath border_path(fill_path);
+  fill_path.close();
+  gfx::CanvasSkia* canvas_skia = canvas->AsCanvasSkia();
+  canvas_skia->drawPath(fill_path, paint);
+
+  // Fill and stroke have different opinions about how to treat paths.  Because
+  // in Skia integral coordinates represent pixel boundaries, offsetting the
+  // path makes it go exactly through pixel centers; this results in lines that
+  // are exactly where we expect, instead of having odd "off by one" issues.
+  // Were we to do this for |fill_path|, however, which tries to fill "inside"
+  // the path (using some questionable math), we'd get a fill at a very
+  // different place than we'd want.
+  border_path.offset(SK_ScalarHalf, SK_ScalarHalf);
+  paint.setShader(NULL);
+  paint.setColor(SkColorSetA(ResourceBundle::toolbar_separator_color,
+                             SkColorGetA(gradient_colors[0])));
+  paint.setStyle(SkPaint::kStroke_Style);
+  canvas_skia->drawPath(border_path, paint);
+}
+
+InfoBarView::~InfoBarView() {
+}
+
+void InfoBarView::Layout() {
+  gfx::Size button_size = close_button_->GetPreferredSize();
+  close_button_->SetBounds(width() - kHorizontalPadding - button_size.width(),
+                           OffsetY(this, button_size), button_size.width(),
+                           button_size.height());
+}
+
+void InfoBarView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
+  View::ViewHierarchyChanged(is_add, parent, child);
+
+  if (child == this) {
+    if (is_add) {
+      // The container_ pointer must be set before adding to the view hierarchy.
+      DCHECK(container_);
+#if defined(OS_WIN)
+      // When we're added to a view hierarchy within a widget, we create an
+      // external focus tracker to track what was focused in case we obtain
+      // focus so that we can restore focus when we're removed.
+      views::Widget* widget = GetWidget();
+      if (widget) {
+        focus_tracker_.reset(
+            new views::ExternalFocusTracker(this, GetFocusManager()));
+      }
+#endif
+      if (GetFocusManager())
+        GetFocusManager()->AddFocusChangeListener(this);
+      NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT);
+    } else {
+      DestroyFocusTracker(false);
+      // NULL our container_ pointer so that if Animation::Stop results in
+      // AnimationEnded being called, we do not try and delete ourselves twice.
+      container_ = NULL;
+      animation_->Stop();
+      // Finally, clean ourselves up when we're removed from the view hierarchy
+      // since no-one refers to us now.
+      MessageLoop::current()->PostTask(FROM_HERE,
+          delete_factory_.NewRunnableMethod(&InfoBarView::DeleteSelf));
+      if (GetFocusManager())
+        GetFocusManager()->RemoveFocusChangeListener(this);
+    }
+  }
+
+  // For accessibility, ensure the close button is the last child view.
+  if ((parent == this) && (child != close_button_) &&
+      (close_button_->parent() == this) &&
+      (GetChildViewAt(child_count() - 1) != close_button_)) {
+    RemoveChildView(close_button_);
+    AddChildView(close_button_);
+  }
+}
+
+void InfoBarView::ButtonPressed(views::Button* sender,
+                                const views::Event& event) {
+  if (sender == close_button_) {
+    if (delegate_)
+      delegate_->InfoBarDismissed();
+    RemoveInfoBar();
+  }
+}
+
+void InfoBarView::AnimationProgressed(const ui::Animation* animation) {
+  if (container_)
+    container_->InfoBarAnimated(true);
+}
+
+int InfoBarView::GetAvailableWidth() const {
+  const int kCloseButtonSpacing = 12;
+  return close_button_->x() - kCloseButtonSpacing;
+}
+
+void InfoBarView::RemoveInfoBar() const {
+  if (container_)
+    container_->RemoveDelegate(delegate());
+}
+
+int InfoBarView::CenterY(const gfx::Size prefsize) const {
+  return std::max((target_height_ - prefsize.height()) / 2, 0);
+}
+
+int InfoBarView::OffsetY(View* parent, const gfx::Size prefsize) const {
+  return CenterY(prefsize) - (target_height_ - parent->height());
+}
+
+AccessibilityTypes::Role InfoBarView::GetAccessibleRole() {
+  return AccessibilityTypes::ROLE_ALERT;
+}
+
+gfx::Size InfoBarView::GetPreferredSize() {
+  return gfx::Size(0,
+      static_cast<int>(target_height_ * animation_->GetCurrentValue()));
+}
+
+void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) {
+  // This will trigger some screen readers to read the entire contents of this
+  // infobar.
+  if (focused_before && focused_now && !this->Contains(focused_before) &&
+      this->Contains(focused_now))
+    NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT);
+}
+
+void InfoBarView::AnimationEnded(const ui::Animation* animation) {
+  if (container_) {
+    container_->InfoBarAnimated(false);
+
+    if (!animation_->IsShowing())
+      Close();
+  }
+}
+
+void InfoBarView::DestroyFocusTracker(bool restore_focus) {
+  if (focus_tracker_ != NULL) {
+    if (restore_focus)
+      focus_tracker_->FocusLastFocusedExternalView();
+    focus_tracker_->SetFocusManager(NULL);
+    focus_tracker_.reset();
+  }
+}
+
+void InfoBarView::DeleteSelf() {
+  delete this;
+}
diff --git a/chrome/browser/ui/views/infobars/infobar_view.h b/chrome/browser/ui/views/infobars/infobar_view.h
new file mode 100644
index 0000000..dc62f25
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/infobar_view.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_VIEW_H_
+#pragma once
+
+#include "base/task.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "views/controls/button/button.h"
+#include "views/focus/focus_manager.h"
+
+class InfoBarContainer;
+class InfoBarDelegate;
+
+namespace ui {
+class SlideAnimation;
+}
+
+namespace views {
+class ExternalFocusTracker;
+class ImageButton;
+class ImageView;
+class Label;
+}
+
+// TODO(pkasting): infobar_delegate.h forward declares "class InfoBar" but the
+// definitions are (right now) completely port-specific.  This stub class will
+// be turned into the cross-platform base class for InfoBar views (in the MVC
+// sense).  Right now it's just here so the various InfoBarDelegates can
+// continue to return an InfoBar*, it doesn't do anything.
+class InfoBar {
+ public:
+  explicit InfoBar(InfoBarDelegate* delegate) {}
+  virtual ~InfoBar() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InfoBar);
+};
+
+class InfoBarView : public InfoBar,
+                    public views::View,
+                    public views::ButtonListener,
+                    public views::FocusChangeListener,
+                    public ui::AnimationDelegate {
+ public:
+  explicit InfoBarView(InfoBarDelegate* delegate);
+
+  InfoBarDelegate* delegate() const { return delegate_; }
+
+  // Set a link to the parent InfoBarContainer. This must be set before the
+  // InfoBar is added to the view hierarchy.
+  void set_container(InfoBarContainer* container) { container_ = container; }
+
+  // Starts animating the InfoBar open.
+  void AnimateOpen();
+
+  // Opens the InfoBar immediately.
+  void Open();
+
+  // Starts animating the InfoBar closed. It will not be closed until the
+  // animation has completed, when |Close| will be called.
+  void AnimateClose();
+
+  // Closes the InfoBar immediately and removes it from its container. Notifies
+  // the delegate that it has closed. The InfoBar is deleted after this function
+  // is called.
+  void Close();
+
+  // Paint the arrow on |canvas|. |arrow_center_x| indicates the
+  // desired location of the center of the arrow in the |outer_view|
+  // coordinate system.
+  void PaintArrow(gfx::Canvas* canvas, View* outer_view, int arrow_center_x);
+
+ protected:
+  // The target height of the InfoBar, regardless of what its current height
+  // is (due to animation).
+  static const int kDefaultTargetHeight;
+  static const int kHorizontalPadding;
+  static const int kIconLabelSpacing;
+  static const int kButtonButtonSpacing;
+  static const int kEndOfLabelSpacing;
+
+  virtual ~InfoBarView();
+
+  // views::View:
+  virtual void Layout();
+  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
+
+  // views::ButtonListener:
+  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+
+  // ui::AnimationDelegate:
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
+  // Returns the available width of the View for use by child view layout,
+  // excluding the close button.
+  virtual int GetAvailableWidth() const;
+
+  // Removes our associated InfoBarDelegate from the associated TabContents.
+  // (Will lead to this InfoBar being closed).
+  void RemoveInfoBar() const;
+
+  void set_target_height(int height) { target_height_ = height; }
+
+  ui::SlideAnimation* animation() { return animation_.get(); }
+
+  // Returns a centered y-position of a control of height specified in
+  // |prefsize| within the standard InfoBar height. Stable during an animation.
+  int CenterY(const gfx::Size prefsize) const;
+
+  // Returns a centered y-position of a control of height specified in
+  // |prefsize| within the standard InfoBar height, adjusted according to the
+  // current amount of animation offset the |parent| InfoBar currently has.
+  // Changes during an animation.
+  int OffsetY(View* parent, const gfx::Size prefsize) const;
+
+ private:
+  // views::View:
+  virtual AccessibilityTypes::Role GetAccessibleRole();
+  virtual gfx::Size GetPreferredSize();
+
+  // views::FocusChangeListener:
+  virtual void FocusWillChange(View* focused_before, View* focused_now);
+
+  // ui::AnimationDelegate:
+  virtual void AnimationEnded(const ui::Animation* animation);
+
+  // Destroys the external focus tracker, if present. If |restore_focus| is
+  // true, restores focus to the view tracked by the focus tracker before doing
+  // so.
+  void DestroyFocusTracker(bool restore_focus);
+
+  // Deletes this object (called after a return to the message loop to allow
+  // the stack in ViewHierarchyChanged to unwind).
+  void DeleteSelf();
+
+  // The InfoBar's container
+  InfoBarContainer* container_;
+
+  // The InfoBar's delegate.
+  InfoBarDelegate* delegate_;
+
+  // The close button at the right edge of the InfoBar.
+  views::ImageButton* close_button_;
+
+  // The animation that runs when the InfoBar is opened or closed.
+  scoped_ptr<ui::SlideAnimation> animation_;
+
+  // Tracks and stores the last focused view which is not the InfoBar or any of
+  // its children. Used to restore focus once the InfoBar is closed.
+  scoped_ptr<views::ExternalFocusTracker> focus_tracker_;
+
+  // Used to delete this object after a return to the message loop.
+  ScopedRunnableMethodFactory<InfoBarView> delete_factory_;
+
+  // The target height for the InfoBarView.
+  int target_height_;
+
+  DISALLOW_COPY_AND_ASSIGN(InfoBarView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBAR_VIEW_H_
diff --git a/chrome/browser/ui/views/infobars/infobars.cc b/chrome/browser/ui/views/infobars/infobars.cc
deleted file mode 100644
index d1af02e..0000000
--- a/chrome/browser/ui/views/infobars/infobars.cc
+++ /dev/null
@@ -1,618 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/views/infobars/infobars.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/message_loop.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/views/event_utils.h"
-#include "chrome/browser/views/infobars/infobar_container.h"
-#include "gfx/canvas.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/animation/slide_animation.h"
-#include "views/background.h"
-#include "views/controls/button/image_button.h"
-#include "views/controls/button/native_button.h"
-#include "views/controls/image_view.h"
-#include "views/controls/label.h"
-#include "views/focus/external_focus_tracker.h"
-#include "views/widget/widget.h"
-
-#if defined(OS_WIN)
-#include "app/win/hwnd_util.h"
-#endif
-
-// static
-const double InfoBar::kDefaultTargetHeight = 36.0;
-const int InfoBar::kHorizontalPadding = 6;
-const int InfoBar::kIconLabelSpacing = 6;
-const int InfoBar::kButtonButtonSpacing = 10;
-const int InfoBar::kEndOfLabelSpacing = 16;
-const int InfoBar::kCloseButtonSpacing = 12;
-const int InfoBar::kButtonInLabelSpacing = 5;
-
-static const SkColor kWarningBackgroundColorTop = SkColorSetRGB(255, 242, 183);
-static const SkColor kWarningBackgroundColorBottom =
-    SkColorSetRGB(250, 230, 145);
-
-static const SkColor kPageActionBackgroundColorTop =
-    SkColorSetRGB(218, 231, 249);
-static const SkColor kPageActionBackgroundColorBottom =
-    SkColorSetRGB(179, 202, 231);
-
-static const int kSeparatorLineHeight = 1;
-
-// InfoBarBackground, public: --------------------------------------------------
-
-InfoBarBackground::InfoBarBackground(InfoBarDelegate::Type infobar_type) {
-  SkColor top_color;
-  SkColor bottom_color;
-  switch (infobar_type) {
-    case InfoBarDelegate::WARNING_TYPE:
-      top_color = kWarningBackgroundColorTop;
-      bottom_color = kWarningBackgroundColorBottom;
-      break;
-    case InfoBarDelegate::PAGE_ACTION_TYPE:
-      top_color = kPageActionBackgroundColorTop;
-      bottom_color = kPageActionBackgroundColorBottom;
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  gradient_background_.reset(
-      views::Background::CreateVerticalGradientBackground(top_color,
-                                                          bottom_color));
-}
-
-// InfoBarBackground, views::Background overrides: -----------------------------
-
-void InfoBarBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
-  // First paint the gradient background.
-  gradient_background_->Paint(canvas, view);
-
-  // Now paint the separator line.
-  canvas->FillRectInt(ResourceBundle::toolbar_separator_color, 0,
-                      view->height() - kSeparatorLineHeight, view->width(),
-                      kSeparatorLineHeight);
-}
-
-// InfoBar, public: ------------------------------------------------------------
-
-InfoBar::InfoBar(InfoBarDelegate* delegate)
-    : delegate_(delegate),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          close_button_(new views::ImageButton(this))),
-      ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)),
-      target_height_(kDefaultTargetHeight) {
-  // We delete ourselves when we're removed from the view hierarchy.
-  set_parent_owned(false);
-
-  set_background(new InfoBarBackground(delegate->GetInfoBarType()));
-
-  switch (delegate->GetInfoBarType()) {
-    case InfoBarDelegate::WARNING_TYPE:
-      SetAccessibleName(UTF16ToWide(
-          l10n_util::GetStringUTF16(IDS_ACCNAME_INFOBAR_WARNING)));
-      break;
-    case InfoBarDelegate::PAGE_ACTION_TYPE:
-      SetAccessibleName(UTF16ToWide(
-          l10n_util::GetStringUTF16(IDS_ACCNAME_INFOBAR_PAGE_ACTION)));
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  close_button_->SetImage(views::CustomButton::BS_NORMAL,
-                          rb.GetBitmapNamed(IDR_CLOSE_BAR));
-  close_button_->SetImage(views::CustomButton::BS_HOT,
-                          rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
-  close_button_->SetImage(views::CustomButton::BS_PUSHED,
-                          rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
-  close_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)));
-  AddChildView(close_button_);
-
-  animation_.reset(new ui::SlideAnimation(this));
-  animation_->SetTweenType(ui::Tween::LINEAR);
-}
-
-InfoBar::~InfoBar() {
-}
-
-// InfoBar, views::View overrides: ---------------------------------------------
-
-AccessibilityTypes::Role InfoBar::GetAccessibleRole() {
-  return AccessibilityTypes::ROLE_ALERT;
-}
-
-gfx::Size InfoBar::GetPreferredSize() {
-  int height = static_cast<int>(target_height_ * animation_->GetCurrentValue());
-  return gfx::Size(0, height);
-}
-
-void InfoBar::Layout() {
-  gfx::Size button_ps = close_button_->GetPreferredSize();
-  close_button_->SetBounds(width() - kHorizontalPadding - button_ps.width(),
-                           OffsetY(this, button_ps), button_ps.width(),
-                           button_ps.height());
-}
-
-void InfoBar::ViewHierarchyChanged(bool is_add, views::View* parent,
-                                   views::View* child) {
-  if (child == this) {
-    if (is_add) {
-      InfoBarAdded();
-    } else {
-      InfoBarRemoved();
-    }
-  }
-
-  if (GetWidget() && GetWidget()->IsAccessibleWidget()) {
-    // For accessibility, make the close button the last child view.
-    if (parent == this && child != close_button_ &&
-        HasChildView(close_button_) &&
-        GetChildViewAt(GetChildViewCount() - 1) != close_button_) {
-      RemoveChildView(close_button_);
-      AddChildView(close_button_);
-    }
-
-    // Allow screen reader users to focus the close button.
-    close_button_->SetFocusable(true);
-  }
-}
-
-// InfoBar, protected: ---------------------------------------------------------
-
-int InfoBar::GetAvailableWidth() const {
-  return close_button_->x() - kCloseButtonSpacing;
-}
-
-void InfoBar::RemoveInfoBar() const {
-  if (container_)
-    container_->RemoveDelegate(delegate());
-}
-
-int InfoBar::CenterY(const gfx::Size prefsize) {
-  return std::max((static_cast<int>(target_height_) -
-      prefsize.height()) / 2, 0);
-}
-
-int InfoBar::OffsetY(views::View* parent, const gfx::Size prefsize) {
-  return CenterY(prefsize) -
-      (static_cast<int>(target_height_) - parent->height());
-}
-
-// InfoBar, views::ButtonListener implementation: ------------------
-
-void InfoBar::ButtonPressed(views::Button* sender, const views::Event& event) {
-  if (sender == close_button_) {
-    if (delegate_)
-      delegate_->InfoBarDismissed();
-    RemoveInfoBar();
-  }
-}
-
-// InfoBar, views::FocusChangeListener implementation: ------------------
-
-void InfoBar::FocusWillChange(View* focused_before, View* focused_now) {
-  // This will trigger some screen readers to read the entire contents of this
-  // infobar.
-  if (focused_before && focused_now &&
-      !this->IsParentOf(focused_before) && this->IsParentOf(focused_now)) {
-    NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT);
-  }
-}
-
-// InfoBar, ui::AnimationDelegate implementation: ------------------------------
-
-void InfoBar::AnimationProgressed(const ui::Animation* animation) {
-  if (container_)
-    container_->InfoBarAnimated(true);
-}
-
-void InfoBar::AnimationEnded(const ui::Animation* animation) {
-  if (container_) {
-    container_->InfoBarAnimated(false);
-
-    if (!animation_->IsShowing())
-      Close();
-  }
-}
-
-// InfoBar, private: -----------------------------------------------------------
-
-void InfoBar::AnimateOpen() {
-  animation_->Show();
-}
-
-void InfoBar::Open() {
-  // Set the animation value to 1.0 so that GetPreferredSize() returns the right
-  // size.
-  animation_->Reset(1.0);
-  if (container_)
-    container_->InfoBarAnimated(false);
-}
-
-void InfoBar::AnimateClose() {
-  bool restore_focus = true;
-#if defined(OS_WIN)
-  // Do not restore focus (and active state with it) on Windows if some other
-  // top-level window became active.
-  if (GetWidget() &&
-      !app::win::DoesWindowBelongToActiveWindow(GetWidget()->GetNativeView())) {
-    restore_focus = false;
-  }
-#endif  // defined(OS_WIN)
-  DestroyFocusTracker(restore_focus);
-  animation_->Hide();
-}
-
-void InfoBar::Close() {
-  GetParent()->RemoveChildView(this);
-  // Note that we only tell the delegate we're closed here, and not when we're
-  // simply destroyed (by virtue of a tab switch or being moved from window to
-  // window), since this action can cause the delegate to destroy itself.
-  if (delegate_) {
-    delegate_->InfoBarClosed();
-    delegate_ = NULL;
-  }
-}
-
-void InfoBar::InfoBarAdded() {
-  // The container_ pointer must be set before adding to the view hierarchy.
-  DCHECK(container_);
-#if defined(OS_WIN)
-  // When we're added to a view hierarchy within a widget, we create an
-  // external focus tracker to track what was focused in case we obtain
-  // focus so that we can restore focus when we're removed.
-  views::Widget* widget = GetWidget();
-  if (widget) {
-    focus_tracker_.reset(new views::ExternalFocusTracker(this,
-                                                         GetFocusManager()));
-  }
-#endif
-
-  if (GetFocusManager())
-    GetFocusManager()->AddFocusChangeListener(this);
-
-  NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT);
-}
-
-void InfoBar::InfoBarRemoved() {
-  DestroyFocusTracker(false);
-  // NULL our container_ pointer so that if Animation::Stop results in
-  // AnimationEnded being called, we do not try and delete ourselves twice.
-  container_ = NULL;
-  animation_->Stop();
-  // Finally, clean ourselves up when we're removed from the view hierarchy
-  // since no-one refers to us now.
-  MessageLoop::current()->PostTask(FROM_HERE,
-      delete_factory_.NewRunnableMethod(&InfoBar::DeleteSelf));
-
-  if (GetFocusManager())
-    GetFocusManager()->RemoveFocusChangeListener(this);
-}
-
-void InfoBar::DestroyFocusTracker(bool restore_focus) {
-  if (focus_tracker_.get()) {
-    if (restore_focus)
-      focus_tracker_->FocusLastFocusedExternalView();
-    focus_tracker_->SetFocusManager(NULL);
-    focus_tracker_.reset(NULL);
-  }
-}
-
-void InfoBar::DeleteSelf() {
-  delete this;
-}
-
-// AlertInfoBar, public: -------------------------------------------------------
-
-AlertInfoBar::AlertInfoBar(AlertInfoBarDelegate* delegate)
-    : InfoBar(delegate) {
-  label_ = new views::Label(
-      UTF16ToWideHack(delegate->GetMessageText()),
-      ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont));
-  label_->SetColor(SK_ColorBLACK);
-  label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  AddChildView(label_);
-
-  icon_ = new views::ImageView;
-  if (delegate->GetIcon())
-    icon_->SetImage(delegate->GetIcon());
-  AddChildView(icon_);
-}
-
-AlertInfoBar::~AlertInfoBar() {
-}
-
-// AlertInfoBar, views::View overrides: ----------------------------------------
-
-void AlertInfoBar::Layout() {
-  // Layout the close button.
-  InfoBar::Layout();
-
-  // Layout the icon and text.
-  gfx::Size icon_ps = icon_->GetPreferredSize();
-  icon_->SetBounds(kHorizontalPadding, OffsetY(this, icon_ps), icon_ps.width(),
-                   icon_ps.height());
-
-  gfx::Size text_ps = label_->GetPreferredSize();
-  int text_width = std::min(
-      text_ps.width(),
-      GetAvailableWidth() - icon_->bounds().right() - kIconLabelSpacing);
-  label_->SetBounds(icon_->bounds().right() + kIconLabelSpacing,
-                    OffsetY(this, text_ps), text_width, text_ps.height());
-}
-
-// AlertInfoBar, private: ------------------------------------------------------
-
-AlertInfoBarDelegate* AlertInfoBar::GetDelegate() {
-  return delegate()->AsAlertInfoBarDelegate();
-}
-
-// LinkInfoBar, public: --------------------------------------------------------
-
-LinkInfoBar::LinkInfoBar(LinkInfoBarDelegate* delegate)
-    : InfoBar(delegate),
-      icon_(new views::ImageView),
-      label_1_(new views::Label),
-      label_2_(new views::Label),
-      link_(new views::Link) {
-  // Set up the icon.
-  if (delegate->GetIcon())
-    icon_->SetImage(delegate->GetIcon());
-  AddChildView(icon_);
-
-  // Set up the labels.
-  size_t offset;
-  string16 message_text = delegate->GetMessageTextWithOffset(&offset);
-  if (offset != string16::npos) {
-    label_1_->SetText(UTF16ToWideHack(message_text.substr(0, offset)));
-    label_2_->SetText(UTF16ToWideHack(message_text.substr(offset)));
-  } else {
-    label_1_->SetText(UTF16ToWideHack(message_text));
-  }
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  label_1_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
-  label_2_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
-  label_1_->SetColor(SK_ColorBLACK);
-  label_2_->SetColor(SK_ColorBLACK);
-  label_1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  label_2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  AddChildView(label_1_);
-  AddChildView(label_2_);
-
-  // Set up the link.
-  link_->SetText(UTF16ToWideHack(delegate->GetLinkText()));
-  link_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
-  link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  link_->SetController(this);
-  link_->MakeReadableOverBackgroundColor(background()->get_color());
-  AddChildView(link_);
-}
-
-LinkInfoBar::~LinkInfoBar() {
-}
-
-// LinkInfoBar, views::LinkController implementation: --------------------------
-
-void LinkInfoBar::LinkActivated(views::Link* source, int event_flags) {
-  DCHECK(source == link_);
-  if (GetDelegate()->LinkClicked(
-          event_utils::DispositionFromEventFlags(event_flags))) {
-    RemoveInfoBar();
-  }
-}
-
-// LinkInfoBar, views::View overrides: -----------------------------------------
-
-void LinkInfoBar::Layout() {
-  // Layout the close button.
-  InfoBar::Layout();
-
-  // Layout the icon.
-  gfx::Size icon_ps = icon_->GetPreferredSize();
-  icon_->SetBounds(kHorizontalPadding, OffsetY(this, icon_ps), icon_ps.width(),
-                   icon_ps.height());
-
-  int label_1_x = icon_->bounds().right() + kIconLabelSpacing;
-
-  // Figure out the amount of space available to the rest of the content now
-  // that the close button and the icon have been positioned.
-  int available_width = GetAvailableWidth() - label_1_x;
-
-  // Layout the left label.
-  gfx::Size label_1_ps = label_1_->GetPreferredSize();
-  label_1_->SetBounds(label_1_x, OffsetY(this, label_1_ps), label_1_ps.width(),
-                      label_1_ps.height());
-
-  // Layout the link.
-  gfx::Size link_ps = link_->GetPreferredSize();
-  bool has_second_label = !label_2_->GetText().empty();
-  if (has_second_label) {
-    // Embed the link in the text string between the two labels.
-    link_->SetBounds(label_1_->bounds().right(),
-                     OffsetY(this, link_ps), link_ps.width(), link_ps.height());
-  } else {
-    // Right-align the link toward the edge of the InfoBar.
-    link_->SetBounds(label_1_x + available_width - link_ps.width(),
-                     OffsetY(this, link_ps), link_ps.width(), link_ps.height());
-  }
-
-  // Layout the right label (we do this regardless of whether or not it has
-  // text).
-  gfx::Size label_2_ps = label_2_->GetPreferredSize();
-  label_2_->SetBounds(link_->bounds().right(),
-                      OffsetY(this, label_2_ps), label_2_ps.width(),
-                      label_2_ps.height());
-}
-
-// LinkInfoBar, private: -------------------------------------------------------
-
-LinkInfoBarDelegate* LinkInfoBar::GetDelegate() {
-  return delegate()->AsLinkInfoBarDelegate();
-}
-
-// ConfirmInfoBar, public: -----------------------------------------------------
-
-ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
-    : AlertInfoBar(delegate),
-      ok_button_(NULL),
-      cancel_button_(NULL),
-      link_(NULL),
-      initialized_(false) {
-  ok_button_ = new views::NativeButton(this,
-      UTF16ToWideHack(delegate->GetButtonLabel(
-                          ConfirmInfoBarDelegate::BUTTON_OK)));
-  ok_button_->SetAccessibleName(ok_button_->label());
-  if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK_DEFAULT)
-    ok_button_->SetAppearsAsDefault(true);
-  if (delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_OK))
-    ok_button_->SetNeedElevation(true);
-  cancel_button_ = new views::NativeButton(
-      this, UTF16ToWideHack(
-          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL)));
-  cancel_button_->SetAccessibleName(cancel_button_->label());
-
-  // Set up the link.
-  link_ = new views::Link;
-  link_->SetText(UTF16ToWideHack(delegate->GetLinkText()));
-  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  link_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
-  link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  link_->SetController(this);
-  link_->MakeReadableOverBackgroundColor(background()->get_color());
-}
-
-ConfirmInfoBar::~ConfirmInfoBar() {
-  if (!initialized_) {
-    delete ok_button_;
-    delete cancel_button_;
-    delete link_;
-  }
-}
-
-// ConfirmInfoBar, views::LinkController implementation: -----------------------
-
-void ConfirmInfoBar::LinkActivated(views::Link* source, int event_flags) {
-  DCHECK(source == link_);
-  DCHECK(link_->IsVisible());
-  DCHECK(!link_->GetText().empty());
-  if (GetDelegate()->LinkClicked(
-          event_utils::DispositionFromEventFlags(event_flags))) {
-    RemoveInfoBar();
-  }
-}
-
-// ConfirmInfoBar, views::View overrides: --------------------------------------
-
-void ConfirmInfoBar::Layout() {
-  // First layout right aligned items (from right to left) in order to determine
-  // the space avalable, then layout the left aligned items.
-
-  // Layout the close button.
-  InfoBar::Layout();
-
-  // Layout the cancel and OK buttons.
-  int available_width = AlertInfoBar::GetAvailableWidth();
-  int ok_button_width = 0;
-  int cancel_button_width = 0;
-  gfx::Size ok_ps = ok_button_->GetPreferredSize();
-  gfx::Size cancel_ps = cancel_button_->GetPreferredSize();
-
-  if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) {
-    ok_button_width = ok_ps.width();
-  } else {
-    ok_button_->SetVisible(false);
-  }
-  if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
-    cancel_button_width = cancel_ps.width();
-  } else {
-    cancel_button_->SetVisible(false);
-  }
-
-  cancel_button_->SetBounds(available_width - cancel_button_width,
-                            OffsetY(this, cancel_ps), cancel_ps.width(),
-                            cancel_ps.height());
-  int spacing = cancel_button_width > 0 ? kButtonButtonSpacing : 0;
-  ok_button_->SetBounds(cancel_button_->x() - spacing - ok_button_width,
-                        OffsetY(this, ok_ps), ok_ps.width(), ok_ps.height());
-
-  // Layout the icon and label.
-  AlertInfoBar::Layout();
-
-  // Now append the link to the label's right edge.
-  link_->SetVisible(!link_->GetText().empty());
-  gfx::Size link_ps = link_->GetPreferredSize();
-  int link_x = label()->bounds().right() + kEndOfLabelSpacing;
-  int link_w = std::min(GetAvailableWidth() - link_x, link_ps.width());
-  link_->SetBounds(link_x, OffsetY(this, link_ps), link_w, link_ps.height());
-}
-
-void ConfirmInfoBar::ViewHierarchyChanged(bool is_add,
-                                          views::View* parent,
-                                          views::View* child) {
-  if (is_add && child == this && !initialized_) {
-    Init();
-    initialized_ = true;
-  }
-  InfoBar::ViewHierarchyChanged(is_add, parent, child);
-}
-
-// ConfirmInfoBar, views::ButtonListener implementation: ---------------
-
-void ConfirmInfoBar::ButtonPressed(
-    views::Button* sender, const views::Event& event) {
-  InfoBar::ButtonPressed(sender, event);
-  if (sender == ok_button_) {
-    if (GetDelegate()->Accept())
-      RemoveInfoBar();
-  } else if (sender == cancel_button_) {
-    if (GetDelegate()->Cancel())
-      RemoveInfoBar();
-  }
-}
-
-// ConfirmInfoBar, InfoBar overrides: ------------------------------------------
-
-int ConfirmInfoBar::GetAvailableWidth() const {
-  return ok_button_->x() - kEndOfLabelSpacing;
-}
-
-// ConfirmInfoBar, private: ----------------------------------------------------
-
-ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
-  return delegate()->AsConfirmInfoBarDelegate();
-}
-
-void ConfirmInfoBar::Init() {
-  AddChildView(ok_button_);
-  AddChildView(cancel_button_);
-  AddChildView(link_);
-}
-
-// AlertInfoBarDelegate, InfoBarDelegate overrides: ----------------------------
-
-InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
-  return new AlertInfoBar(this);
-}
-
-// LinkInfoBarDelegate, InfoBarDelegate overrides: -----------------------------
-
-InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
-  return new LinkInfoBar(this);
-}
-
-// ConfirmInfoBarDelegate, InfoBarDelegate overrides: --------------------------
-
-InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
-  return new ConfirmInfoBar(this);
-}
diff --git a/chrome/browser/ui/views/infobars/infobars.h b/chrome/browser/ui/views/infobars/infobars.h
deleted file mode 100644
index b6fc879..0000000
--- a/chrome/browser/ui/views/infobars/infobars.h
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBARS_H_
-#define CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBARS_H_
-#pragma once
-
-#include "base/task.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "views/controls/button/button.h"
-#include "views/controls/link.h"
-#include "views/focus/focus_manager.h"
-
-class InfoBarContainer;
-
-namespace ui {
-class SlideAnimation;
-}
-
-namespace views {
-class ExternalFocusTracker;
-class ImageButton;
-class ImageView;
-class Label;
-class NativeButton;
-}
-
-// This file contains implementations for some general purpose InfoBars. See
-// chrome/browser/tab_contents/infobar_delegate.h for the delegate interface(s)
-// that you must implement to use these.
-
-class InfoBarBackground : public views::Background {
- public:
-  explicit InfoBarBackground(InfoBarDelegate::Type infobar_type);
-
-  // Overridden from views::Background:
-  virtual void Paint(gfx::Canvas* canvas, views::View* view) const;
-
- private:
-  scoped_ptr<views::Background> gradient_background_;
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBarBackground);
-};
-
-class InfoBar : public views::View,
-                public views::ButtonListener,
-                public views::FocusChangeListener,
-                public ui::AnimationDelegate {
- public:
-  explicit InfoBar(InfoBarDelegate* delegate);
-  virtual ~InfoBar();
-
-  InfoBarDelegate* delegate() const { return delegate_; }
-
-  // Set a link to the parent InfoBarContainer. This must be set before the
-  // InfoBar is added to the view hierarchy.
-  void set_container(InfoBarContainer* container) { container_ = container; }
-
-  // The target height of the InfoBar, regardless of what its current height
-  // is (due to animation).
-  static const double kDefaultTargetHeight;
-
-  static const int kHorizontalPadding;
-  static const int kIconLabelSpacing;
-  static const int kButtonButtonSpacing;
-  static const int kEndOfLabelSpacing;
-  static const int kCloseButtonSpacing;
-  static const int kButtonInLabelSpacing;
-
-  // Overridden from views::View:
-  virtual AccessibilityTypes::Role GetAccessibleRole();
-  virtual gfx::Size GetPreferredSize();
-  virtual void Layout();
-
- protected:
-  // Overridden from views::View:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
-
-  // Returns the available width of the View for use by child view layout,
-  // excluding the close button.
-  virtual int GetAvailableWidth() const;
-
-  // Removes our associated InfoBarDelegate from the associated TabContents.
-  // (Will lead to this InfoBar being closed).
-  void RemoveInfoBar() const;
-
-  void set_target_height(double height) { target_height_ = height; }
-
-  ui::SlideAnimation* animation() { return animation_.get(); }
-
-  // Returns a centered y-position of a control of height specified in
-  // |prefsize| within the standard InfoBar height. Stable during an animation.
-  int CenterY(const gfx::Size prefsize);
-
-  // Returns a centered y-position of a control of height specified in
-  // |prefsize| within the standard InfoBar height, adjusted according to the
-  // current amount of animation offset the |parent| InfoBar currently has.
-  // Changes during an animation.
-  int OffsetY(views::View* parent, const gfx::Size prefsize);
-
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // Overridden from views::FocusChangeListener:
-  virtual void FocusWillChange(View* focused_before, View* focused_now);
-
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation);
-  virtual void AnimationEnded(const ui::Animation* animation);
-
- private:
-  friend class InfoBarContainer;
-
-  // Starts animating the InfoBar open.
-  void AnimateOpen();
-
-  // Opens the InfoBar immediately.
-  void Open();
-
-  // Starts animating the InfoBar closed. It will not be closed until the
-  // animation has completed, when |Close| will be called.
-  void AnimateClose();
-
-  // Closes the InfoBar immediately and removes it from its container. Notifies
-  // the delegate that it has closed. The InfoBar is deleted after this function
-  // is called.
-  void Close();
-
-  // Called when an InfoBar is added or removed from a view hierarchy to do
-  // setup and shutdown.
-  void InfoBarAdded();
-  void InfoBarRemoved();
-
-  // Destroys the external focus tracker, if present. If |restore_focus| is
-  // true, restores focus to the view tracked by the focus tracker before doing
-  // so.
-  void DestroyFocusTracker(bool restore_focus);
-
-  // Deletes this object (called after a return to the message loop to allow
-  // the stack in ViewHierarchyChanged to unwind).
-  void DeleteSelf();
-
-  // The InfoBar's container
-  InfoBarContainer* container_;
-
-  // The InfoBar's delegate.
-  InfoBarDelegate* delegate_;
-
-  // The Close Button at the right edge of the InfoBar.
-  views::ImageButton* close_button_;
-
-  // The animation that runs when the InfoBar is opened or closed.
-  scoped_ptr<ui::SlideAnimation> animation_;
-
-  // Tracks and stores the last focused view which is not the InfoBar or any of
-  // its children. Used to restore focus once the InfoBar is closed.
-  scoped_ptr<views::ExternalFocusTracker> focus_tracker_;
-
-  // Used to delete this object after a return to the message loop.
-  ScopedRunnableMethodFactory<InfoBar> delete_factory_;
-
-  // The target height for the InfoBar.
-  double target_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(InfoBar);
-};
-
-class AlertInfoBar : public InfoBar {
- public:
-  explicit AlertInfoBar(AlertInfoBarDelegate* delegate);
-  virtual ~AlertInfoBar();
-
-  // Overridden from views::View:
-  virtual void Layout();
-
- protected:
-  views::Label* label() const { return label_; }
-  views::ImageView* icon() const { return icon_; }
-
- private:
-  AlertInfoBarDelegate* GetDelegate();
-
-  views::Label* label_;
-  views::ImageView* icon_;
-
-  DISALLOW_COPY_AND_ASSIGN(AlertInfoBar);
-};
-
-class LinkInfoBar : public InfoBar,
-                    public views::LinkController {
- public:
-  explicit LinkInfoBar(LinkInfoBarDelegate* delegate);
-  virtual ~LinkInfoBar();
-
-  // Overridden from views::LinkController:
-  virtual void LinkActivated(views::Link* source, int event_flags);
-
-  // Overridden from views::View:
-  virtual void Layout();
-
- private:
-  LinkInfoBarDelegate* GetDelegate();
-
-  views::ImageView* icon_;
-  views::Label* label_1_;
-  views::Label* label_2_;
-  views::Link* link_;
-
-  DISALLOW_COPY_AND_ASSIGN(LinkInfoBar);
-};
-
-class ConfirmInfoBar : public AlertInfoBar,
-                       public views::LinkController  {
- public:
-  explicit ConfirmInfoBar(ConfirmInfoBarDelegate* delegate);
-  virtual ~ConfirmInfoBar();
-
-  // Overridden from views::LinkController:
-  virtual void LinkActivated(views::Link* source, int event_flags);
-
-  // Overridden from views::View:
-  virtual void Layout();
-
- protected:
-  // Overridden from views::View:
-  virtual void ViewHierarchyChanged(bool is_add,
-                                    views::View* parent,
-                                    views::View* child);
-
-  // Overridden from views::ButtonListener:
-  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
-  // Overridden from InfoBar:
-  virtual int GetAvailableWidth() const;
-
- private:
-  void Init();
-
-  ConfirmInfoBarDelegate* GetDelegate();
-
-  views::NativeButton* ok_button_;
-  views::NativeButton* cancel_button_;
-  views::Link* link_;
-
-  bool initialized_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
-};
-
-
-#endif  // CHROME_BROWSER_UI_VIEWS_INFOBARS_INFOBARS_H_
diff --git a/chrome/browser/ui/views/infobars/link_infobar.cc b/chrome/browser/ui/views/infobars/link_infobar.cc
new file mode 100644
index 0000000..64105ee
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/link_infobar.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/views/infobars/link_infobar.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/ui/views/event_utils.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "views/controls/image_view.h"
+
+// LinkInfoBarDelegate --------------------------------------------------------
+
+InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
+  return new LinkInfoBar(this);
+}
+
+// LinkInfoBar ----------------------------------------------------------------
+
+LinkInfoBar::LinkInfoBar(LinkInfoBarDelegate* delegate)
+    : InfoBarView(delegate),
+      icon_(new views::ImageView),
+      label_1_(new views::Label),
+      link_(new views::Link),
+      label_2_(new views::Label) {
+  // Set up the icon.
+  if (delegate->GetIcon())
+    icon_->SetImage(delegate->GetIcon());
+  AddChildView(icon_);
+
+  // Set up the labels.
+  size_t offset;
+  string16 message_text = delegate->GetMessageTextWithOffset(&offset);
+  if (offset != string16::npos) {
+    label_1_->SetText(UTF16ToWideHack(message_text.substr(0, offset)));
+    label_2_->SetText(UTF16ToWideHack(message_text.substr(offset)));
+  } else {
+    label_1_->SetText(UTF16ToWideHack(message_text));
+  }
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  label_1_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  label_2_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  label_1_->SetColor(SK_ColorBLACK);
+  label_2_->SetColor(SK_ColorBLACK);
+  label_1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+  label_2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+  AddChildView(label_1_);
+  AddChildView(label_2_);
+
+  // Set up the link.
+  link_->SetText(UTF16ToWideHack(delegate->GetLinkText()));
+  link_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+  link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+  link_->SetController(this);
+  link_->MakeReadableOverBackgroundColor(background()->get_color());
+  AddChildView(link_);
+}
+
+LinkInfoBar::~LinkInfoBar() {
+}
+
+void LinkInfoBar::Layout() {
+  InfoBarView::Layout();
+
+  // Layout the icon.
+  gfx::Size icon_size = icon_->GetPreferredSize();
+  icon_->SetBounds(kHorizontalPadding, OffsetY(this, icon_size),
+                   icon_size.width(), icon_size.height());
+
+  int label_1_x = icon_->bounds().right() + kIconLabelSpacing;
+
+  // Figure out the amount of space available to the rest of the content now
+  // that the close button and the icon have been positioned.
+  int available_width = GetAvailableWidth() - label_1_x;
+
+  // Layout the left label.
+  gfx::Size label_1_size = label_1_->GetPreferredSize();
+  label_1_->SetBounds(label_1_x, OffsetY(this, label_1_size),
+                      label_1_size.width(), label_1_size.height());
+
+  // Layout the link.
+  gfx::Size link_size = link_->GetPreferredSize();
+  bool has_second_label = !label_2_->GetText().empty();
+  if (has_second_label) {
+    // Embed the link in the text string between the two labels.
+    link_->SetBounds(label_1_->bounds().right(), OffsetY(this, link_size),
+                     link_size.width(), link_size.height());
+  } else {
+    // Right-align the link toward the edge of the InfoBar.
+    link_->SetBounds(label_1_x + available_width - link_size.width(),
+        OffsetY(this, link_size), link_size.width(), link_size.height());
+  }
+
+  // Layout the right label (we do this regardless of whether or not it has
+  // text).
+  gfx::Size label_2_size = label_2_->GetPreferredSize();
+  label_2_->SetBounds(link_->bounds().right(), OffsetY(this, label_2_size),
+                      label_2_size.width(), label_2_size.height());
+}
+
+void LinkInfoBar::LinkActivated(views::Link* source, int event_flags) {
+  DCHECK_EQ(link_, source);
+  if (GetDelegate()->LinkClicked(
+      event_utils::DispositionFromEventFlags(event_flags)))
+    RemoveInfoBar();
+}
+
+LinkInfoBarDelegate* LinkInfoBar::GetDelegate() {
+  return delegate()->AsLinkInfoBarDelegate();
+}
diff --git a/chrome/browser/ui/views/infobars/link_infobar.h b/chrome/browser/ui/views/infobars/link_infobar.h
new file mode 100644
index 0000000..6e8be35
--- /dev/null
+++ b/chrome/browser/ui/views/infobars/link_infobar.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_INFOBARS_LINK_INFOBAR_H_
+#define CHROME_BROWSER_UI_VIEWS_INFOBARS_LINK_INFOBAR_H_
+#pragma once
+
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
+#include "views/controls/link.h"
+
+class LinkInfoBarDelegate;
+
+// An infobar that shows a string with an embedded link.
+class LinkInfoBar : public InfoBarView,
+                    public views::LinkController {
+ public:
+  explicit LinkInfoBar(LinkInfoBarDelegate* delegate);
+
+ private:
+  virtual ~LinkInfoBar();
+
+  // InfoBarView:
+  virtual void Layout();
+
+  // views::LinkController:
+  virtual void LinkActivated(views::Link* source, int event_flags);
+
+  LinkInfoBarDelegate* GetDelegate();
+
+  views::ImageView* icon_;
+  views::Label* label_1_;
+  views::Link* link_;
+  views::Label* label_2_;
+
+  DISALLOW_COPY_AND_ASSIGN(LinkInfoBar);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_INFOBARS_LINK_INFOBAR_H_
diff --git a/chrome/browser/ui/views/infobars/translate_infobar_base.cc b/chrome/browser/ui/views/infobars/translate_infobar_base.cc
index fec6886..53c0734 100644
--- a/chrome/browser/ui/views/infobars/translate_infobar_base.cc
+++ b/chrome/browser/ui/views/infobars/translate_infobar_base.cc
@@ -1,64 +1,78 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/translate_infobar_base.h"
+#include "chrome/browser/ui/views/infobars/translate_infobar_base.h"
 
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/views/infobars/after_translate_infobar.h"
-#include "chrome/browser/views/infobars/before_translate_infobar.h"
-#include "chrome/browser/views/infobars/translate_message_infobar.h"
-#include "chrome/browser/views/infobars/infobar_button_border.h"
-#include "gfx/canvas_skia.h"
+#include "chrome/browser/ui/views/infobars/after_translate_infobar.h"
+#include "chrome/browser/ui/views/infobars/before_translate_infobar.h"
+#include "chrome/browser/ui/views/infobars/infobar_button_border.h"
+#include "chrome/browser/ui/views/infobars/translate_message_infobar.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/image_view.h"
+#include "views/controls/label.h"
 
-TranslateInfoBarBase::TranslateInfoBarBase(
-    TranslateInfoBarDelegate* delegate)
-    : InfoBar(delegate),
+// TranslateInfoBarDelegate ---------------------------------------------------
+
+InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
+  TranslateInfoBarBase* infobar = NULL;
+  switch (type_) {
+    case BEFORE_TRANSLATE:
+      infobar = new BeforeTranslateInfoBar(this);
+      break;
+    case AFTER_TRANSLATE:
+      infobar = new AfterTranslateInfoBar(this);
+      break;
+    case TRANSLATING:
+    case TRANSLATION_ERROR:
+      infobar = new TranslateMessageInfoBar(this);
+      break;
+    default:
+      NOTREACHED();
+  }
+  infobar_view_ = infobar;
+  return infobar;
+}
+
+// TranslateInfoBarBase -------------------------------------------------------
+
+// static
+const int TranslateInfoBarBase::kButtonInLabelSpacing = 5;
+
+TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate)
+    : InfoBarView(delegate),
       normal_background_(InfoBarDelegate::PAGE_ACTION_TYPE),
       error_background_(InfoBarDelegate::WARNING_TYPE) {
   icon_ = new views::ImageView;
-  SkBitmap* image = delegate->GetIcon();
+  SkBitmap* image = static_cast<InfoBarDelegate*>(delegate)->GetIcon();
   if (image)
     icon_->SetImage(image);
   AddChildView(icon_);
 
+  background_color_animation_.reset(new ui::SlideAnimation(this));
+  background_color_animation_->SetTweenType(ui::Tween::LINEAR);
+  background_color_animation_->SetSlideDuration(500);
   TranslateInfoBarDelegate::BackgroundAnimationType animation =
-      delegate->background_animation_type();
-  if (animation != TranslateInfoBarDelegate::NONE) {
-    background_color_animation_.reset(new ui::SlideAnimation(this));
-    background_color_animation_->SetTweenType(ui::Tween::LINEAR);
-    background_color_animation_->SetSlideDuration(500);
-    if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
-      background_color_animation_->Show();
-    } else {
-      DCHECK_EQ(TranslateInfoBarDelegate::ERROR_TO_NORMAL, animation);
-      // Hide() runs the animation in reverse.
-      background_color_animation_->Reset(1.0);
-      background_color_animation_->Hide();
-    }
+      GetDelegate()->background_animation_type();
+  if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) {
+    background_color_animation_->Show();
+  } else if (animation == TranslateInfoBarDelegate::ERROR_TO_NORMAL) {
+    // Hide() runs the animation in reverse.
+    background_color_animation_->Reset(1.0);
+    background_color_animation_->Hide();
   }
 }
 
 TranslateInfoBarBase::~TranslateInfoBarBase() {
 }
 
-// Overridden from views::View:
-void TranslateInfoBarBase::Layout() {
-  // Layout the close button.
-  InfoBar::Layout();
-
-  // Layout the icon on left of bar.
-  gfx::Size icon_ps = icon_->GetPreferredSize();
-  icon_->SetBounds(InfoBar::kHorizontalPadding, InfoBar::OffsetY(this, icon_ps),
-      icon_ps.width(), icon_ps.height());
-}
-
+// static
 views::Label* TranslateInfoBarBase::CreateLabel(const string16& text) {
   views::Label* label = new views::Label(UTF16ToWideHack(text),
       ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont));
@@ -67,27 +81,7 @@
   return label;
 }
 
-void TranslateInfoBarBase::PaintBackground(gfx::Canvas* canvas) {
-  // If we're not animating, simply paint the background for the current state.
-  if (background_color_animation_ == NULL ||
-      !background_color_animation_->is_animating()) {
-    GetBackground().Paint(canvas, this);
-    return;
-  }
-
-  FadeBackground(canvas, 1.0 - background_color_animation_->GetCurrentValue(),
-                 normal_background_);
-  FadeBackground(canvas, background_color_animation_->GetCurrentValue(),
-                 error_background_);
-}
-
-void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
-  if (background_color_animation_.get() == animation)
-    SchedulePaint();  // That'll trigger a PaintBackgroud.
-  else
-    InfoBar::AnimationProgressed(animation);
-}
-
+// static
 views::MenuButton* TranslateInfoBarBase::CreateMenuButton(
     const string16& text,
     bool normal_has_border,
@@ -118,34 +112,58 @@
   return menu_button;
 }
 
-gfx::Point TranslateInfoBarBase::DetermineMenuPosition(
-    views::MenuButton* menu_button) {
-  gfx::Rect lb = menu_button->GetLocalBounds(true);
-  gfx::Point menu_position(lb.origin());
-  menu_position.Offset(2, lb.height() - 3);
-  if (base::i18n::IsRTL())
-    menu_position.Offset(lb.width() - 4, 0);
+void TranslateInfoBarBase::Layout() {
+  InfoBarView::Layout();
 
-  View::ConvertPointToScreen(menu_button, &menu_position);
-#if defined(OS_WIN)
-  int left_bound = GetSystemMetrics(SM_XVIRTUALSCREEN);
-  if (menu_position.x() < left_bound)
-    menu_position.set_x(left_bound);
-#endif
-  return menu_position;
+  gfx::Size icon_size = icon_->GetPreferredSize();
+  icon_->SetBounds(kHorizontalPadding, OffsetY(this, icon_size),
+                   icon_size.width(), icon_size.height());
 }
 
-TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() const {
-  return static_cast<TranslateInfoBarDelegate*>(delegate());
+void TranslateInfoBarBase::UpdateLanguageButtonText(
+    views::MenuButton* button,
+    LanguagesMenuModel::LanguageType language_type) {
+  TranslateInfoBarDelegate* delegate = GetDelegate();
+  button->SetText(UTF16ToWideHack(delegate->GetLanguageDisplayableNameAt(
+      (language_type == LanguagesMenuModel::ORIGINAL) ?
+          delegate->original_language_index() :
+          delegate->target_language_index())));
+  // The button may have to grow to show the new text.
+  Layout();
+  SchedulePaint();
 }
 
-const InfoBarBackground& TranslateInfoBarBase::GetBackground() const {
+TranslateInfoBarDelegate* TranslateInfoBarBase::GetDelegate() {
+  return delegate()->AsTranslateInfoBarDelegate();
+}
+
+void TranslateInfoBarBase::PaintBackground(gfx::Canvas* canvas) {
+  // If we're not animating, simply paint the background for the current state.
+  if (!background_color_animation_->is_animating()) {
+    GetBackground().Paint(canvas, this);
+    return;
+  }
+
+  FadeBackground(canvas, 1.0 - background_color_animation_->GetCurrentValue(),
+                 normal_background_);
+  FadeBackground(canvas, background_color_animation_->GetCurrentValue(),
+                 error_background_);
+}
+
+void TranslateInfoBarBase::AnimationProgressed(const ui::Animation* animation) {
+  if (animation == background_color_animation_.get())
+    SchedulePaint();  // That'll trigger a PaintBackgroud.
+  else
+    InfoBarView::AnimationProgressed(animation);
+}
+
+const views::Background& TranslateInfoBarBase::GetBackground() {
   return GetDelegate()->IsError() ? error_background_ : normal_background_;
 }
 
 void TranslateInfoBarBase::FadeBackground(gfx::Canvas* canvas,
                                           double animation_value,
-                                          const InfoBarBackground& background) {
+                                          const views::Background& background) {
   // Draw the background into an offscreen buffer with alpha value per animation
   // value, then blend it back into the current canvas.
   canvas->SaveLayerAlpha(static_cast<int>(animation_value * 255));
@@ -153,26 +171,3 @@
   background.Paint(canvas, this);
   canvas->Restore();
 }
-
-// TranslateInfoBarDelegate views specific method:
-InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
-  TranslateInfoBarBase* infobar = NULL;
-  switch (type_) {
-    case BEFORE_TRANSLATE:
-      infobar = new BeforeTranslateInfoBar(this);
-      break;
-    case AFTER_TRANSLATE:
-      infobar = new AfterTranslateInfoBar(this);
-      break;
-    case TRANSLATING:
-    case TRANSLATION_ERROR:
-      infobar = new TranslateMessageInfoBar(this);
-      break;
-    default:
-      NOTREACHED();
-  }
-  // Set |infobar_view_| so that the model can notify the infobar when it
-  // changes.
-  infobar_view_ = infobar;
-  return infobar;
-}
diff --git a/chrome/browser/ui/views/infobars/translate_infobar_base.h b/chrome/browser/ui/views/infobars/translate_infobar_base.h
index 3f49c01..73494ef 100644
--- a/chrome/browser/ui/views/infobars/translate_infobar_base.h
+++ b/chrome/browser/ui/views/infobars/translate_infobar_base.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_UI_VIEWS_INFOBARS_TRANSLATE_INFOBAR_BASE_H_
 #pragma once
 
+#include "chrome/browser/translate/languages_menu_model.h"
 #include "chrome/browser/translate/translate_infobar_view.h"
-#include "chrome/browser/views/infobars/infobars.h"
+#include "chrome/browser/ui/views/infobars/infobar_background.h"
+#include "chrome/browser/ui/views/infobars/infobar_view.h"
 
 class TranslateInfoBarDelegate;
 
@@ -19,55 +21,55 @@
 // This class contains some of the base functionality that translate infobars
 // use.
 class TranslateInfoBarBase : public TranslateInfoBarView,
-                             public InfoBar {
+                             public InfoBarView {
  public:
   explicit TranslateInfoBarBase(TranslateInfoBarDelegate* delegate);
   virtual ~TranslateInfoBarBase();
 
-  // TranslateInfoBarView implementation:
-  virtual void OriginalLanguageChanged() {}
-  virtual void TargetLanguageChanged() {}
-
-  // Overridden from views::View:
-  virtual void Layout();
-  virtual void PaintBackground(gfx::Canvas* canvas);
-
  protected:
-  // Overridden from ui::AnimationDelegate:
-  virtual void AnimationProgressed(const ui::Animation* animation);
+  static const int kButtonInLabelSpacing;
 
   // Creates a label with the appropriate font and color for the translate
   // infobars.
-  views::Label* CreateLabel(const string16& text);
+  static views::Label* CreateLabel(const string16& text);
 
   // Creates a menu-button with a custom appearance for the translate infobars.
-  views::MenuButton* CreateMenuButton(const string16& text,
-                                      bool normal_has_border,
-                                      views::ViewMenuDelegate* menu_delegate);
+  static views::MenuButton* CreateMenuButton(
+      const string16& text,
+      bool normal_has_border,
+      views::ViewMenuDelegate* menu_delegate);
 
-  // Returns the location at which the menu triggered by |menu_button| should be
-  // positioned.
-  gfx::Point DetermineMenuPosition(views::MenuButton* menu_button);
+  // InfoBarView:
+  virtual void Layout();
+
+  // Sets the text of the provided language menu button to reflect the current
+  // value from the delegate.
+  void UpdateLanguageButtonText(views::MenuButton* button,
+                                LanguagesMenuModel::LanguageType language);
 
   // Convenience to retrieve the TranslateInfoBarDelegate for this infobar.
-  TranslateInfoBarDelegate* GetDelegate() const;
+  TranslateInfoBarDelegate* GetDelegate();
 
   // The translate icon.
   views::ImageView* icon_;
 
-  InfoBarBackground normal_background_;
-  InfoBarBackground error_background_;
-  scoped_ptr<ui::SlideAnimation> background_color_animation_;
-
  private:
+  // InfoBarView:
+  virtual void PaintBackground(gfx::Canvas* canvas);
+  virtual void AnimationProgressed(const ui::Animation* animation);
+
   // Returns the background that should be displayed when not animating.
-  const InfoBarBackground& GetBackground() const;
+  const views::Background& GetBackground();
 
   // Paints |background| to |canvas| with the opacity level based on
   // |animation_value|.
   void FadeBackground(gfx::Canvas* canvas,
                       double animation_value,
-                      const InfoBarBackground& background);
+                      const views::Background& background);
+
+  InfoBarBackground normal_background_;
+  InfoBarBackground error_background_;
+  scoped_ptr<ui::SlideAnimation> background_color_animation_;
 
   DISALLOW_COPY_AND_ASSIGN(TranslateInfoBarBase);
 };
diff --git a/chrome/browser/ui/views/infobars/translate_message_infobar.cc b/chrome/browser/ui/views/infobars/translate_message_infobar.cc
index 8094d4e..47ead3c 100644
--- a/chrome/browser/ui/views/infobars/translate_message_infobar.cc
+++ b/chrome/browser/ui/views/infobars/translate_message_infobar.cc
@@ -1,57 +1,55 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/infobars/translate_message_infobar.h"
+#include "chrome/browser/ui/views/infobars/translate_message_infobar.h"
 
 #include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/views/infobars/infobar_text_button.h"
+#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
 #include "views/controls/image_view.h"
+#include "views/controls/label.h"
 
 TranslateMessageInfoBar::TranslateMessageInfoBar(
     TranslateInfoBarDelegate* delegate)
-    : TranslateInfoBarBase(delegate) {
+    : TranslateInfoBarBase(delegate),
+      button_(NULL) {
   label_ = CreateLabel(delegate->GetMessageInfoBarText());
   AddChildView(label_);
 
   string16 button_text = delegate->GetMessageInfoBarButtonText();
-  if (button_text.empty()) {
-    button_ = NULL;
-  } else {
+  if (!button_text.empty()) {
     button_ = InfoBarTextButton::Create(this, button_text);
     AddChildView(button_);
   }
 }
 
+TranslateMessageInfoBar::~TranslateMessageInfoBar() {
+}
+
 void TranslateMessageInfoBar::Layout() {
   TranslateInfoBarBase::Layout();
 
-  int x = icon_->bounds().right() + InfoBar::kIconLabelSpacing;
-  gfx::Size label_pref_size = label_->GetPreferredSize();
+  int x = icon_->bounds().right() + kIconLabelSpacing;
+  gfx::Size label_size = label_->GetPreferredSize();
   int available_width = GetAvailableWidth() - x;
-  gfx::Size button_pref_size;
+  gfx::Size button_size;
   if (button_) {
-    button_pref_size = button_->GetPreferredSize();
-    available_width -=
-        (button_pref_size.width() + InfoBar::kButtonInLabelSpacing);
+    button_size = button_->GetPreferredSize();
+    available_width -= (button_size.width() + kButtonInLabelSpacing);
   }
-  label_->SetBounds(x, InfoBar::OffsetY(this, label_pref_size),
-                    std::min(label_pref_size.width(), available_width),
-                    label_pref_size.height());
+  label_->SetBounds(x, OffsetY(this, label_size),
+      std::min(label_size.width(), available_width), label_size.height());
 
   if (button_) {
-    button_->SetBounds(label_->bounds().right() +
-                          InfoBar::kButtonInLabelSpacing,
-                       InfoBar::OffsetY(this, button_pref_size),
-                       button_pref_size.width(), button_pref_size.height());
+    button_->SetBounds(label_->bounds().right() + kButtonInLabelSpacing,
+        OffsetY(this, button_size), button_size.width(), button_size.height());
   }
 }
 
 void TranslateMessageInfoBar::ButtonPressed(views::Button* sender,
                                             const views::Event& event) {
-  if (sender == button_) {
+  if (sender == button_)
     GetDelegate()->MessageInfoBarButtonPressed();
-    return;
-  }
-  TranslateInfoBarBase::ButtonPressed(sender, event);
+  else
+    TranslateInfoBarBase::ButtonPressed(sender, event);
 }
diff --git a/chrome/browser/ui/views/infobars/translate_message_infobar.h b/chrome/browser/ui/views/infobars/translate_message_infobar.h
index b809c15..a29122d 100644
--- a/chrome/browser/ui/views/infobars/translate_message_infobar.h
+++ b/chrome/browser/ui/views/infobars/translate_message_infobar.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_INFOBARS_TRANSLATE_MESSAGE_INFOBAR_H_
 #pragma once
 
-#include "chrome/browser/views/infobars/translate_infobar_base.h"
+#include "chrome/browser/ui/views/infobars/translate_infobar_base.h"
 
 class InfoBarTextButton;
 
@@ -14,12 +14,13 @@
  public:
   explicit TranslateMessageInfoBar(TranslateInfoBarDelegate* delegate);
 
-  virtual void Layout();
+ private:
+  virtual ~TranslateMessageInfoBar();
 
-  // views::ButtonListener implementation:
+  // TranslateInfoBarBase:
+  virtual void Layout();
   virtual void ButtonPressed(views::Button* sender, const views::Event& event);
 
- private:
   views::Label* label_;
   InfoBarTextButton* button_;
 
diff --git a/chrome/browser/ui/views/instant_confirm_view.cc b/chrome/browser/ui/views/instant_confirm_view.cc
index cd338d2..99ca448 100644
--- a/chrome/browser/ui/views/instant_confirm_view.cc
+++ b/chrome/browser/ui/views/instant_confirm_view.cc
@@ -1,25 +1,22 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/instant_confirm_view.h"
+#include "chrome/browser/ui/views/instant_confirm_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/instant/instant_confirm_dialog.h"
 #include "chrome/browser/instant/instant_controller.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
-#include "views/grid_layout.h"
-#include "views/layout_manager.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 InstantConfirmView::InstantConfirmView(Profile* profile) : profile_(profile) {
@@ -33,7 +30,7 @@
   learn_more_link->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   learn_more_link->SetController(this);
 
-  views::GridLayout* layout = CreatePanelGridLayout(this);
+  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int first_column_set = 1;
diff --git a/chrome/browser/ui/views/js_modal_dialog_views.cc b/chrome/browser/ui/views/js_modal_dialog_views.cc
index a75d922..6657ade 100644
--- a/chrome/browser/ui/views/js_modal_dialog_views.cc
+++ b/chrome/browser/ui/views/js_modal_dialog_views.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/js_modal_dialog_views.h"
+#include "chrome/browser/ui/views/js_modal_dialog_views.h"
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 #include "grit/generated_resources.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
 #include "views/controls/message_box_view.h"
 #include "views/window/window.h"
 
@@ -21,12 +21,12 @@
     JavaScriptAppModalDialog* parent)
     : parent_(parent),
       message_box_view_(new MessageBoxView(
-          parent->dialog_flags() | MessageBoxFlags::kAutoDetectAlignment,
+          parent->dialog_flags() | ui::MessageBoxFlags::kAutoDetectAlignment,
           parent->message_text(), parent->default_prompt_text())) {
   DCHECK(message_box_view_);
 
   message_box_view_->AddAccelerator(
-      views::Accelerator(app::VKEY_C, false, true, false));
+      views::Accelerator(ui::VKEY_C, false, true, false));
   if (parent->display_suppress_checkbox()) {
     message_box_view_->SetCheckBoxLabel(UTF16ToWide(
         l10n_util::GetStringUTF16(IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION)));
@@ -68,22 +68,22 @@
 // JSModalDialogViews, views::DialogDelegate implementation:
 
 int JSModalDialogViews::GetDefaultDialogButton() const {
-  if (parent_->dialog_flags() & MessageBoxFlags::kFlagHasOKButton)
-    return MessageBoxFlags::DIALOGBUTTON_OK;
+  if (parent_->dialog_flags() & ui::MessageBoxFlags::kFlagHasOKButton)
+    return ui::MessageBoxFlags::DIALOGBUTTON_OK;
 
-  if (parent_->dialog_flags() & MessageBoxFlags::kFlagHasCancelButton)
-    return MessageBoxFlags::DIALOGBUTTON_CANCEL;
+  if (parent_->dialog_flags() & ui::MessageBoxFlags::kFlagHasCancelButton)
+    return ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
 
-  return MessageBoxFlags::DIALOGBUTTON_NONE;
+  return ui::MessageBoxFlags::DIALOGBUTTON_NONE;
 }
 
 int JSModalDialogViews::GetDialogButtons() const {
   int dialog_buttons = 0;
-  if (parent_->dialog_flags() & MessageBoxFlags::kFlagHasOKButton)
-    dialog_buttons = MessageBoxFlags::DIALOGBUTTON_OK;
+  if (parent_->dialog_flags() & ui::MessageBoxFlags::kFlagHasOKButton)
+    dialog_buttons = ui::MessageBoxFlags::DIALOGBUTTON_OK;
 
-  if (parent_->dialog_flags() & MessageBoxFlags::kFlagHasCancelButton)
-    dialog_buttons |= MessageBoxFlags::DIALOGBUTTON_CANCEL;
+  if (parent_->dialog_flags() & ui::MessageBoxFlags::kFlagHasCancelButton)
+    dialog_buttons |= ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
 
   return dialog_buttons;
 }
@@ -117,12 +117,12 @@
 }
 
 std::wstring JSModalDialogViews::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
+    ui::MessageBoxFlags::DialogButton button) const {
   if (parent_->is_before_unload_dialog()) {
-    if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
+    if (button == ui::MessageBoxFlags::DIALOGBUTTON_OK) {
       return UTF16ToWide(l10n_util::GetStringUTF16(
           IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL));
-    } else if (button == MessageBoxFlags::DIALOGBUTTON_CANCEL) {
+    } else if (button == ui::MessageBoxFlags::DIALOGBUTTON_CANCEL) {
       return UTF16ToWide(l10n_util::GetStringUTF16(
           IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL));
     }
diff --git a/chrome/browser/ui/views/js_modal_dialog_views.h b/chrome/browser/ui/views/js_modal_dialog_views.h
index 2ff27f9..1a9a7c3 100644
--- a/chrome/browser/ui/views/js_modal_dialog_views.h
+++ b/chrome/browser/ui/views/js_modal_dialog_views.h
@@ -10,8 +10,8 @@
 
 #include <string>
 
-#include "app/message_box_flags.h"
 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
+#include "ui/base/message_box_flags.h"
 #include "views/window/dialog_delegate.h"
 
 class MessageBoxView;
@@ -39,7 +39,7 @@
   virtual bool Cancel();
   virtual bool Accept();
   virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const;
+      ui::MessageBoxFlags::DialogButton button) const;
 
   // Overridden from views::WindowDelegate:
   virtual bool IsModal() const { return true; }
diff --git a/chrome/browser/ui/views/keyboard_overlay_delegate.cc b/chrome/browser/ui/views/keyboard_overlay_delegate.cc
index 6081316..88ec7b1 100644
--- a/chrome/browser/ui/views/keyboard_overlay_delegate.cc
+++ b/chrome/browser/ui/views/keyboard_overlay_delegate.cc
@@ -4,22 +4,29 @@
 
 #include "chrome/browser/ui/views/keyboard_overlay_delegate.h"
 
-#include "app/l10n_util.h"
 #include "base/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
+#include "chrome/browser/chromeos/frame/bubble_window.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/html_dialog_view.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
-
+#include "ui/base/l10n/l10n_util.h"
 
 void KeyboardOverlayDelegate::ShowDialog(gfx::NativeWindow owning_window) {
   Browser* browser = BrowserList::GetLastActive();
   KeyboardOverlayDelegate* delegate = new KeyboardOverlayDelegate(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_KEYBOARD_OVERLAY_TITLE)));
-  DCHECK(browser);
-  browser->BrowserShowHtmlDialog(delegate, owning_window);
+  HtmlDialogView* html_view =
+      new HtmlDialogView(browser->profile(), delegate);
+  html_view->InitDialog();
+  chromeos::BubbleWindow::Create(owning_window,
+                                 gfx::Rect(),
+                                 chromeos::BubbleWindow::STYLE_XSHAPE,
+                                 html_view);
+  html_view->window()->Show();
 }
 
 KeyboardOverlayDelegate::KeyboardOverlayDelegate(
@@ -43,13 +50,13 @@
   return GURL(url_string);
 }
 
-void KeyboardOverlayDelegate::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void KeyboardOverlayDelegate::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
 }
 
 void KeyboardOverlayDelegate::GetDialogSize(
     gfx::Size* size) const {
-  size->SetSize(1170, 483);
+  size->SetSize(1280, 528);
 }
 
 std::string KeyboardOverlayDelegate::GetDialogArgs() const {
diff --git a/chrome/browser/ui/views/keyboard_overlay_delegate.h b/chrome/browser/ui/views/keyboard_overlay_delegate.h
index 9c957e1..962fae2 100644
--- a/chrome/browser/ui/views/keyboard_overlay_delegate.h
+++ b/chrome/browser/ui/views/keyboard_overlay_delegate.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_KEYBOARD_OVERLAY_DELEGATE_H_
 #define CHROME_BROWSER_UI_VIEWS_KEYBOARD_OVERLAY_DELEGATE_H_
 
-#include "gfx/native_widget_types.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "ui/gfx/native_widget_types.h"
 
 class KeyboardOverlayDelegate : public HtmlDialogUIDelegate {
  public:
@@ -22,8 +22,8 @@
   virtual bool IsDialogModal() const;
   virtual std::wstring GetDialogTitle() const;
   virtual GURL GetDialogContentURL() const;
-  virtual void GetDOMMessageHandlers(
-      std::vector<DOMMessageHandler*>* handlers) const;
+  virtual void GetWebUIMessageHandlers(
+      std::vector<WebUIMessageHandler*>* handlers) const;
   virtual void GetDialogSize(gfx::Size* size) const;
   virtual std::string GetDialogArgs() const;
   virtual void OnDialogClosed(const std::string& json_retval);
diff --git a/chrome/browser/ui/views/keyword_editor_view.cc b/chrome/browser/ui/views/keyword_editor_view.cc
index bd2c820..090e5a4 100644
--- a/chrome/browser/ui/views/keyword_editor_view.cc
+++ b/chrome/browser/ui/views/keyword_editor_view.cc
@@ -1,34 +1,34 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/keyword_editor_view.h"
+#include "chrome/browser/ui/views/keyword_editor_view.h"
 
+#include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/search_engines/template_url_table_model.h"
-#include "chrome/browser/views/browser_dialogs.h"
-#include "chrome/browser/views/first_run_search_engine_view.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/first_run_search_engine_view.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/point.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/point.h"
 #include "views/background.h"
-#include "views/grid_layout.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/table/table_view.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
@@ -153,14 +153,14 @@
 }
 
 void KeywordEditorView::Init() {
-  std::vector<TableColumn> columns;
+  std::vector<ui::TableColumn> columns;
   columns.push_back(
-      TableColumn(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN,
-                  TableColumn::LEFT, -1, .75));
+      ui::TableColumn(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN,
+                      ui::TableColumn::LEFT, -1, .75));
   columns.back().sortable = true;
   columns.push_back(
-      TableColumn(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN,
-                  TableColumn::LEFT, -1, .25));
+      ui::TableColumn(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN,
+                      ui::TableColumn::LEFT, -1, .25));
   columns.back().sortable = true;
   table_view_ = new views::TableView(controller_->table_model(), columns,
       views::ICON_AND_TEXT, false, true, true);
@@ -170,7 +170,7 @@
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON)));
   add_button_->SetEnabled(controller_->loaded());
   add_button_->AddAccelerator(
-      views::Accelerator(app::VKEY_A, false, false, true));
+      views::Accelerator(ui::VKEY_A, false, false, true));
   add_button_->SetAccessibleKeyboardShortcut(L"A");
 
   edit_button_ = new views::NativeButton(this, UTF16ToWide(
@@ -181,7 +181,7 @@
       l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON)));
   remove_button_->SetEnabled(false);
   remove_button_->AddAccelerator(
-      views::Accelerator(app::VKEY_R, false, false, true));
+      views::Accelerator(ui::VKEY_R, false, false, true));
   remove_button_->SetAccessibleKeyboardShortcut(L"R");
 
   make_default_button_ = new views::NativeButton(
@@ -194,11 +194,11 @@
 }
 
 void KeywordEditorView::InitLayoutManager() {
-  const int related_x = kRelatedControlHorizontalSpacing;
-  const int related_y = kRelatedControlVerticalSpacing;
-  const int unrelated_y = kUnrelatedControlVerticalSpacing;
+  const int related_x = views::kRelatedControlHorizontalSpacing;
+  const int related_y = views::kRelatedControlVerticalSpacing;
+  const int unrelated_y = views::kUnrelatedControlVerticalSpacing;
 
-  GridLayout* contents_layout = CreatePanelGridLayout(this);
+  GridLayout* contents_layout = GridLayout::CreatePanel(this);
   SetLayoutManager(contents_layout);
 
   // For the table and buttons.
@@ -258,9 +258,9 @@
   if (edit_button_->IsEnabled()) {
     DWORD pos = GetMessagePos();
     gfx::Point cursor_point(pos);
-    views::MouseEvent event(views::Event::ET_MOUSE_RELEASED,
+    views::MouseEvent event(ui::ET_MOUSE_RELEASED,
                             cursor_point.x(), cursor_point.y(),
-                            views::Event::EF_LEFT_BUTTON_DOWN);
+                            ui::EF_LEFT_BUTTON_DOWN);
     ButtonPressed(edit_button_, event);
   }
 }
diff --git a/chrome/browser/ui/views/list_background.h b/chrome/browser/ui/views/list_background.h
index 82a3000..233910d 100644
--- a/chrome/browser/ui/views/list_background.h
+++ b/chrome/browser/ui/views/list_background.h
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_LIST_BACKGROUND_H_
 #pragma once
 
-#include "gfx/canvas_skia.h"
-#include "gfx/native_theme_win.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/native_theme_win.h"
 #include "views/background.h"
 
 // A background object that paints the scrollable list background,
@@ -24,7 +24,7 @@
 
   virtual void Paint(gfx::Canvas* canvas, views::View* view) const {
     HDC dc = canvas->BeginPlatformPaint();
-    RECT native_lb = view->GetLocalBounds(true).ToRECT();
+    RECT native_lb = view->GetLocalBounds().ToRECT();
     gfx::NativeTheme::instance()->PaintListBackground(dc, true, &native_lb);
     canvas->EndPlatformPaint();
   }
diff --git a/chrome/browser/ui/views/local_storage_info_view.cc b/chrome/browser/ui/views/local_storage_info_view.cc
index b21b74e..894d7c9 100644
--- a/chrome/browser/ui/views/local_storage_info_view.cc
+++ b/chrome/browser/ui/views/local_storage_info_view.cc
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/local_storage_info_view.h"
+#include "chrome/browser/ui/views/local_storage_info_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 static const int kLocalStorageInfoViewBorderSize = 1;
 static const int kLocalStorageInfoViewInsetSize = 3;
@@ -102,18 +102,18 @@
   views::ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(origin_label);
   layout->AddView(origin_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(size_label);
   layout->AddView(size_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(last_modified_label);
   layout->AddView(last_modified_value_field_);
diff --git a/chrome/browser/ui/views/local_storage_set_item_info_view.cc b/chrome/browser/ui/views/local_storage_set_item_info_view.cc
index 24b2d75..30bdbe5 100644
--- a/chrome/browser/ui/views/local_storage_set_item_info_view.cc
+++ b/chrome/browser/ui/views/local_storage_set_item_info_view.cc
@@ -1,19 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/local_storage_set_item_info_view.h"
+#include "chrome/browser/ui/views/local_storage_set_item_info_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 static const int kLocalStorageSetItemInfoViewBorderSize = 1;
 static const int kLocalStorageSetItemInfoViewInsetSize = 3;
@@ -97,18 +97,18 @@
   views::ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
   column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(host_label);
   layout->AddView(host_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(key_label);
   layout->AddView(key_value_field_);
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
   layout->StartRow(0, three_column_layout_id);
   layout->AddView(value_label);
   layout->AddView(value_value_field_);
diff --git a/chrome/browser/ui/views/location_bar/click_handler.cc b/chrome/browser/ui/views/location_bar/click_handler.cc
index 38002ff..63082cb 100644
--- a/chrome/browser/ui/views/location_bar/click_handler.cc
+++ b/chrome/browser/ui/views/location_bar/click_handler.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/click_handler.h"
+#include "chrome/browser/ui/views/location_bar/click_handler.h"
 
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index 92f1cb8..c7ac5d1 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/content_setting_bubble_model.h"
@@ -15,10 +13,12 @@
 #include "chrome/browser/ui/views/content_setting_bubble_contents.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/common/chrome_switches.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/skia_util.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/skia_util.h"
 #include "views/border.h"
 
 namespace {
@@ -183,7 +183,7 @@
   if (animation_in_progress_) {
     // Paint text to the right of the icon.
     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    canvas->DrawStringInt(UTF16ToWideHack(animated_text_),
+    canvas->DrawStringInt(animated_text_,
         rb.GetFont(ResourceBundle::MediumFont), SK_ColorBLACK,
         GetImageBounds().right() + kTextMarginPixels, y(),
         width() - GetImageBounds().width(), height(),
@@ -201,7 +201,8 @@
   SkPaint paint;
   paint.setShader(gfx::CreateGradientShader(kEdgeThickness,
                   height() - (2 * kEdgeThickness),
-                  kTopBoxColor, kBottomBoxColor))->safeUnref();
+                  kTopBoxColor, kBottomBoxColor));
+  SkSafeUnref(paint.getShader());
   SkRect color_rect;
   color_rect.iset(0, 0, width() - 1, height() - 1);
   canvas->AsCanvasSkia()->drawRoundRect(color_rect, kBoxCornerRadius,
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.h b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
index 3281a38..0de0c8f 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.h
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "chrome/common/content_settings_types.h"
 #include "ui/base/animation/linear_animation.h"
 #include "views/controls/image_view.h"
diff --git a/chrome/browser/ui/views/location_bar/ev_bubble_view.cc b/chrome/browser/ui/views/location_bar/ev_bubble_view.cc
index 215ad51..4687c63 100644
--- a/chrome/browser/ui/views/location_bar/ev_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/ev_bubble_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/ev_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
 
 EVBubbleView::EVBubbleView(const int background_images[],
                            int contained_image,
diff --git a/chrome/browser/ui/views/location_bar/ev_bubble_view.h b/chrome/browser/ui/views/location_bar/ev_bubble_view.h
index d80d98f..0dc33cc 100644
--- a/chrome/browser/ui/views/location_bar/ev_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/ev_bubble_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/location_bar/click_handler.h"
-#include "chrome/browser/views/location_bar/icon_label_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/click_handler.h"
+#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 
 class LocationBarView;
 
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 1e0159b..c4a61ef 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/icon_label_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 
-#include "app/resource_bundle.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
-#include "gfx/canvas.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 
 // Amount of padding at the edges of the bubble.
-static const int kBubbleOuterPadding =
-    LocationBarView::kEdgeItemPadding - LocationBarView::kBubblePadding;
+static const int kBubbleOuterPadding = LocationBarView::kEdgeItemPadding -
+    LocationBarView::kBubbleHorizontalPadding;
 
 // Amount of padding after the label.
 static const int kLabelPadding = 5;
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
index e8b7e11..97b4546 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -8,7 +8,7 @@
 
 #include <string>
 
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/painter.h"
 #include "views/view.h"
 
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
index 7b757e8..c2f28d1 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
@@ -1,21 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/keyword_hint_view.h"
+#include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_model.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "views/controls/label.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "views/controls/label.h"
 
 // Amount of space to offset the tab image from the top of the view by.
 static const int kTabImageYOffset = 4;
@@ -48,7 +48,7 @@
   trailing_label_->SetColor(color);
 }
 
-void KeywordHintView::SetKeyword(const std::wstring& keyword) {
+void KeywordHintView::SetKeyword(const string16& keyword) {
   keyword_ = keyword;
   if (keyword_.empty())
     return;
@@ -58,7 +58,7 @@
 
   std::vector<size_t> content_param_offsets;
   bool is_extension_keyword;
-  std::wstring short_name = profile_->GetTemplateURLModel()->
+  string16 short_name = profile_->GetTemplateURLModel()->
       GetKeywordShortName(keyword, &is_extension_keyword);
   int message_id = is_extension_keyword ?
       IDS_OMNIBOX_EXTENSION_KEYWORD_HINT : IDS_OMNIBOX_KEYWORD_HINT;
@@ -66,7 +66,7 @@
       UTF16ToWide(l10n_util::GetStringFUTF16(
           message_id,
           string16(),
-          WideToUTF16(short_name),
+          short_name,
           &content_param_offsets));
   if (content_param_offsets.size() == 2) {
     leading_label_->SetText(
@@ -89,7 +89,7 @@
                               kTabImageYOffset,
                               kTabButtonBitmap->width(),
                               kTabButtonBitmap->height());
-  tab_button_bounds.set_x(MirroredLeftPointForRect(tab_button_bounds));
+  tab_button_bounds.set_x(GetMirroredXForRect(tab_button_bounds));
   canvas->DrawBitmapInt(*kTabButtonBitmap,
                         tab_button_bounds.x(),
                         tab_button_bounds.y());
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.h b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
index d7b23ec..64e18a9 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.h
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
@@ -8,7 +8,7 @@
 
 #include <string>
 
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/view.h"
 
 namespace gfx {
@@ -36,8 +36,8 @@
 
   void SetColor(const SkColor& color);
 
-  void SetKeyword(const std::wstring& keyword);
-  std::wstring keyword() const { return keyword_; }
+  void SetKeyword(const string16& keyword);
+  string16 keyword() const { return keyword_; }
 
   virtual void Paint(gfx::Canvas* canvas);
   virtual gfx::Size GetPreferredSize();
@@ -52,7 +52,7 @@
   views::Label* trailing_label_;
 
   // The keyword.
-  std::wstring keyword_;
+  string16 keyword_;
 
   Profile* profile_;
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index b5dad74..08d9f9c 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -1,17 +1,14 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 
 #if defined(OS_LINUX)
 #include <gtk/gtk.h>
 #endif
 
-#include "app/drag_drop_types.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
+#include "base/command_line.h"
 #include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -36,18 +33,23 @@
 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
 #include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
 #include "chrome/browser/ui/views/location_bar/star_view.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
-#include "gfx/skia_util.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/skia_util.h"
 #include "views/controls/label.h"
 #include "views/drag_utils.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/ui/views/location_bar/suggested_text_view.h"
-#include "chrome/browser/views/first_run_bubble.h"
+#include "chrome/browser/ui/views/first_run_bubble.h"
 #endif
 
 using views::View;
@@ -65,9 +67,9 @@
 const int LocationBarView::kItemPadding = 3;
 const int LocationBarView::kExtensionItemPadding = 5;
 const int LocationBarView::kEdgeItemPadding = kItemPadding;
-const int LocationBarView::kBubblePadding = 1;
+const int LocationBarView::kBubbleHorizontalPadding = 1;
 const char LocationBarView::kViewClassName[] =
-    "browser/views/location_bar/LocationBarView";
+    "browser/ui/views/location_bar/LocationBarView";
 
 static const int kEVBubbleBackgroundImages[] = {
   IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_L,
@@ -171,7 +173,7 @@
   location_entry_view_ = location_entry_->AddToView(this);
   location_entry_view_->SetID(VIEW_ID_AUTOCOMPLETE);
   location_entry_view_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION));
 
   selected_keyword_view_ = new SelectedKeywordView(
       kSelectedKeywordBackgroundImages, IDR_KEYWORD_SEARCH_MAGNIFIER,
@@ -207,8 +209,7 @@
   // AutocompleteEditView to close its popup.
   SetNotifyWhenVisibleBoundsInRootChanges(true);
 
-  SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION)));
+  SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION));
 
   // Initialize the location entry. We do this to avoid a black flash which is
   // visible when the location entry has just been initialized.
@@ -398,15 +399,6 @@
   return origin;
 }
 
-#if defined(OS_WIN)
-void LocationBarView::OnCommitSuggestedText() {
-  InstantController* instant = delegate_->GetInstant();
-  DCHECK(instant);
-  DCHECK(suggested_text_view_);
-  OnCommitSuggestedText(location_entry_->GetText());
-}
-#endif
-
 gfx::Size LocationBarView::GetPreferredSize() {
   return gfx::Size(0, GetThemeProvider()->GetBitmapNamed(mode_ == POPUP ?
       IDR_LOCATIONBG_POPUPMODE_CENTER : IDR_LOCATIONBG_C)->height());
@@ -436,6 +428,8 @@
       LocationBarView::kItemPadding - kEditInternalSpace;
   const int kEdgeEditPadding =
       LocationBarView::kEdgeItemPadding - kEditInternalSpace;
+  const int kBubbleVerticalPadding = (mode_ == POPUP) ?
+      -1 : kBubbleHorizontalPadding;
 
   // Start by reserving the padding at the right edge.
   int entry_width = width() - kEdgeThickness - kEdgeItemPadding;
@@ -446,7 +440,7 @@
   int ev_bubble_width = 0;
   location_icon_view_->SetVisible(false);
   ev_bubble_view_->SetVisible(false);
-  const std::wstring keyword(location_entry_->model()->keyword());
+  const string16 keyword(location_entry_->model()->keyword());
   const bool is_keyword_hint(location_entry_->model()->is_keyword_hint());
   const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint;
   if (show_selected_keyword) {
@@ -487,7 +481,7 @@
     static const int kMinElidedBubbleWidth = 150;
     static const double kMaxBubbleFraction = 0.5;
     const int total_padding =
-        kEdgeThickness + kBubblePadding + kItemEditPadding;
+        kEdgeThickness + kBubbleHorizontalPadding + kItemEditPadding;
     ev_bubble_width = std::min(ev_bubble_width, std::max(kMinElidedBubbleWidth,
         static_cast<int>((entry_width - total_padding) * kMaxBubbleFraction)));
     entry_width -= (total_padding + ev_bubble_width);
@@ -570,21 +564,21 @@
         location_y, location_icon_width, location_height);
     offset = location_icon_view_->bounds().right() + kItemEditPadding;
   } else if (ev_bubble_view_->IsVisible()) {
-    ev_bubble_view_->SetBounds(kEdgeThickness + kBubblePadding,
-        location_y + kBubblePadding, ev_bubble_width,
+    ev_bubble_view_->SetBounds(kEdgeThickness + kBubbleHorizontalPadding,
+        location_y + kBubbleVerticalPadding, ev_bubble_width,
         ev_bubble_view_->GetPreferredSize().height());
     offset = ev_bubble_view_->bounds().right() + kItemEditPadding;
   } else {
     offset = kEdgeThickness +
-        (show_selected_keyword ? kBubblePadding : kEdgeEditPadding);
+        (show_selected_keyword ? kBubbleHorizontalPadding : kEdgeEditPadding);
   }
 
   // Now lay out the edit field and views that autocollapse to give it more
   // room.
   gfx::Rect location_bounds(offset, location_y, entry_width, location_height);
   if (show_selected_keyword) {
-    selected_keyword_view_->SetBounds(0, location_y + kBubblePadding, 0,
-        selected_keyword_view_->GetPreferredSize().height());
+    selected_keyword_view_->SetBounds(0, location_y + kBubbleVerticalPadding,
+        0, selected_keyword_view_->GetPreferredSize().height());
     LayoutView(selected_keyword_view_, kItemEditPadding, available_width,
                true, &location_bounds);
     location_bounds.set_x(selected_keyword_view_->IsVisible() ?
@@ -637,7 +631,7 @@
   }
 #endif
 
-  location_entry_view_->SetBounds(location_bounds);
+  location_entry_view_->SetBoundsRect(location_bounds);
 }
 
 void LocationBarView::Paint(gfx::Canvas* canvas) {
@@ -659,7 +653,7 @@
   // can draw the border images over the background color instead of the
   // reverse; this antialiases better (see comments in
   // AutocompletePopupContentsView::Paint()).
-  gfx::Rect bounds(GetLocalBounds(false));
+  gfx::Rect bounds(GetContentsBounds());
   bounds.Inset(0, kVerticalEdgeThickness);
   SkColor color(GetColor(ToolbarModel::NONE, BACKGROUND));
   if (mode_ == NORMAL) {
@@ -705,13 +699,13 @@
 bool LocationBarView::OnMousePressed(const views::MouseEvent& event) {
   UINT msg;
   if (event.IsLeftMouseButton()) {
-    msg = (event.GetFlags() & views::MouseEvent::EF_IS_DOUBLE_CLICK) ?
+    msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
         WM_LBUTTONDBLCLK : WM_LBUTTONDOWN;
   } else if (event.IsMiddleMouseButton()) {
-    msg = (event.GetFlags() & views::MouseEvent::EF_IS_DOUBLE_CLICK) ?
+    msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
         WM_MBUTTONDBLCLK : WM_MBUTTONDOWN;
   } else if (event.IsRightMouseButton()) {
-    msg = (event.GetFlags() & views::MouseEvent::EF_IS_DOUBLE_CLICK) ?
+    msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
         WM_RBUTTONDBLCLK : WM_RBUTTONDOWN;
   } else {
     NOTREACHED();
@@ -767,27 +761,30 @@
   update_instant_ = false;
 }
 
-bool LocationBarView::OnCommitSuggestedText(const std::wstring& typed_text) {
-  InstantController* instant = delegate_->GetInstant();
-  if (!instant)
+bool LocationBarView::OnCommitSuggestedText(bool skip_inline_autocomplete) {
+  if (!delegate_->GetInstant())
     return false;
-  std::wstring suggestion;
+
+  string16 suggestion;
 #if defined(OS_WIN)
-  if (!HasValidSuggestText())
-    return false;
-  suggestion = suggested_text_view_->GetText();
+  if (HasValidSuggestText())
+    suggestion = suggested_text_view_->GetText();
+#else
+  suggestion = location_entry_->GetInstantSuggestion();
 #endif
-  return location_entry_->CommitInstantSuggestion(typed_text, suggestion);
+
+  if (suggestion.empty())
+    return false;
+
+  location_entry_->model()->FinalizeInstantQuery(
+      location_entry_->GetText(), suggestion, skip_inline_autocomplete);
+  return true;
 }
 
 bool LocationBarView::AcceptCurrentInstantPreview() {
   return InstantController::CommitIfCurrent(delegate_->GetInstant());
 }
 
-void LocationBarView::OnSetSuggestedSearchText(const string16& suggested_text) {
-  SetSuggestedText(suggested_text);
-}
-
 void LocationBarView::OnPopupBoundsChanged(const gfx::Rect& bounds) {
   InstantController* instant = delegate_->GetInstant();
   if (instant)
@@ -851,17 +848,17 @@
         location_entry_->model()->popup_model()->IsOpen()) {
       instant->Update(GetTabContentsWrapper(),
                       location_entry_->model()->CurrentMatch(),
-                      WideToUTF16(location_entry_->GetText()),
+                      location_entry_->GetText(),
                       location_entry_->model()->UseVerbatimInstant(),
                       &suggested_text);
       if (!instant->MightSupportInstant()) {
-        location_entry_->model()->FinalizeInstantQuery(std::wstring(),
-                                                       std::wstring());
+        location_entry_->model()->FinalizeInstantQuery(
+            string16(), string16(), false);
       }
     } else {
       instant->DestroyPreviewContents();
-      location_entry_->model()->FinalizeInstantQuery(std::wstring(),
-                                                     std::wstring());
+      location_entry_->model()->FinalizeInstantQuery(
+          string16(), string16(), false);
     }
   }
 
@@ -897,8 +894,8 @@
   return GetTabContentsFromDelegate(delegate_)->GetFavIcon();
 }
 
-std::wstring LocationBarView::GetTitle() const {
-  return UTF16ToWideHack(GetTabContentsFromDelegate(delegate_)->GetTitle());
+string16 LocationBarView::GetTitle() const {
+  return GetTabContentsFromDelegate(delegate_)->GetTitle();
 }
 
 int LocationBarView::AvailableWidth(int location_bar_width) {
@@ -973,7 +970,7 @@
       page_action_views_[i] = new PageActionWithBadgeView(
           new PageActionImageView(this, profile_, page_actions[i]));
       page_action_views_[i]->SetVisible(false);
-      AddChildView(GetChildIndex(star_view_), page_action_views_[i]);
+      AddChildViewAt(page_action_views_[i], GetIndexOf(star_view_));
     }
   }
 
@@ -1061,6 +1058,10 @@
       return true;
     }
 
+    // If the caret is not at the end, then tab moves the caret to the end.
+    if (!location_entry_->IsCaretAtEnd())
+      return true;
+
     // Tab while showing instant commits instant immediately.
     // Return true so that focus traversal isn't attempted. The edit ends
     // up doing nothing in this case.
@@ -1083,7 +1084,7 @@
 void LocationBarView::WriteDragData(views::View* sender,
                                     const gfx::Point& press_pt,
                                     OSExchangeData* data) {
-  DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE);
+  DCHECK(GetDragOperations(sender, press_pt) != ui::DragDropTypes::DRAG_NONE);
 
   TabContents* tab_contents = GetTabContentsFromDelegate(delegate_);
   DCHECK(tab_contents);
@@ -1098,8 +1099,8 @@
   TabContents* tab_contents = GetTabContentsFromDelegate(delegate_);
   return (tab_contents && tab_contents->GetURL().is_valid() &&
           !location_entry()->IsEditingOrEmpty()) ?
-      (DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK) :
-      DragDropTypes::DRAG_NONE;
+      (ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK) :
+      ui::DragDropTypes::DRAG_NONE;
 }
 
 bool LocationBarView::CanStartDrag(View* sender,
@@ -1124,37 +1125,14 @@
 }
 
 void LocationBarView::SetSuggestedText(const string16& input) {
-#if defined(OS_WIN)
-  // Don't show the suggested text if inline autocomplete is prevented.
-  string16 text = location_entry_->model()->UseVerbatimInstant() ?
-      string16() : input;
-  if (!text.empty()) {
-    if (!suggested_text_view_) {
-      suggested_text_view_ = new SuggestedTextView(this);
-      suggested_text_view_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-      suggested_text_view_->SetColor(
-          GetColor(ToolbarModel::NONE,
-                   LocationBarView::DEEMPHASIZED_TEXT));
-      suggested_text_view_->SetText(UTF16ToWide(text));
-      suggested_text_view_->SetFont(location_entry_->GetFont());
-      AddChildView(suggested_text_view_);
-    } else if (suggested_text_view_->GetText() != UTF16ToWide(text)) {
-      suggested_text_view_->SetText(UTF16ToWide(text));
-    }
-    if (!location_entry_->IsImeComposing())
-      suggested_text_view_->StartAnimation();
-  } else if (suggested_text_view_) {
-    delete suggested_text_view_;
-    suggested_text_view_ = NULL;
-  } else {
-    return;
+  // This method is internally invoked to reset suggest text, so we only do
+  // anything if the text isn't empty.
+  // TODO: if we keep autocomplete, make it so this isn't invoked with empty
+  // text.
+  if (!input.empty()) {
+    location_entry_->model()->FinalizeInstantQuery(location_entry_->GetText(),
+                                                   input, false);
   }
-
-  Layout();
-  SchedulePaint();
-#else
-  location_entry_->SetInstantSuggestion(input);
-#endif
 }
 
 std::wstring LocationBarView::GetInputString() const {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 1ffa5b1..82445b6 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,11 +16,9 @@
 #include "chrome/browser/search_engines/template_url_model_observer.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/toolbar/toolbar_model.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/font.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/views/extensions/extension_popup.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/native/native_view_host.h"
 
 #if defined(OS_WIN)
@@ -156,11 +154,6 @@
   // appears, not where the icons are shown).
   gfx::Point GetLocationEntryOrigin() const;
 
-#if defined(OS_WIN)
-  // Invoked from SuggestedTextView when the suggested text should be committed.
-  void OnCommitSuggestedText();
-#endif
-
   // Sizing functions
   virtual gfx::Size GetPreferredSize();
 
@@ -191,13 +184,16 @@
   virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
 #endif
 
+  const LocationIconView* location_icon_view() const {
+    return location_icon_view_;
+  }
+
   // AutocompleteEditController
   virtual void OnAutocompleteWillClosePopup();
   virtual void OnAutocompleteLosingFocus(gfx::NativeView view_gaining_focus);
   virtual void OnAutocompleteWillAccept();
-  virtual bool OnCommitSuggestedText(const std::wstring& typed_text);
+  virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete);
   virtual bool AcceptCurrentInstantPreview();
-  virtual void OnSetSuggestedSearchText(const string16& suggested_text);
   virtual void OnPopupBoundsChanged(const gfx::Rect& bounds);
   virtual void OnAutocompleteAccept(const GURL& url,
                                     WindowOpenDisposition disposition,
@@ -209,7 +205,7 @@
   virtual void OnKillFocus();
   virtual void OnSetFocus();
   virtual SkBitmap GetFavIcon() const;
-  virtual std::wstring GetTitle() const;
+  virtual string16 GetTitle() const;
 
   // Overridden from views::View:
   virtual std::string GetClassName() const;
@@ -269,7 +265,7 @@
   // Space between the edges and the items next to them.
   static const int kEdgeItemPadding;
   // Space between the edge and a bubble.
-  static const int kBubblePadding;
+  static const int kBubbleHorizontalPadding;
 
  protected:
   void Focus();
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index b862559..0e70a66 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -1,11 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/location_icon_view.h"
+#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
+
+#include "base/utf_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 LocationIconView::LocationIconView(const LocationBarView* location_bar)
     : ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) {
+  SetTooltipText(UTF16ToWide(l10n_util::GetStringUTF16(
+      IDS_TOOLTIP_LOCATION_ICON)));
 }
 
 LocationIconView::~LocationIconView() {
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.h b/chrome/browser/ui/views/location_bar/location_icon_view.h
index 02813c5..7bc9c9d 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/location_bar/click_handler.h"
+#include "chrome/browser/ui/views/location_bar/click_handler.h"
 #include "views/controls/image_view.h"
 
 class LocationBarView;
diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.cc b/chrome/browser/ui/views/location_bar/page_action_image_view.cc
index 3483095..1e7ca9a 100644
--- a/chrome/browser/ui/views/location_bar/page_action_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/page_action_image_view.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/page_action_image_view.h"
+#include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
 
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/extensions/extension_browser_event_router.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/extensions/extension_resource.h"
@@ -89,16 +89,13 @@
     popup_ = ExtensionPopup::Show(
         page_action_->GetPopupUrl(current_tab_id_),
         browser,
-        browser->profile(),
-        browser->window()->GetNativeHandle(),
         screen_bounds,
         arrow_location,
-        true,  // Activate the popup window.
         inspect_with_devtools,
-        ExtensionPopup::BUBBLE_CHROME,
         this);  // ExtensionPopup::Observer
   } else {
-    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+    ExtensionService* service = profile_->GetExtensionService();
+    service->browser_event_router()->PageActionExecuted(
         profile_, page_action_->extension_id(), page_action_->id(),
         current_tab_id_, current_url_.spec(), button);
   }
@@ -139,8 +136,7 @@
 }
 
 bool PageActionImageView::OnKeyPressed(const views::KeyEvent& e) {
-  if (e.GetKeyCode() == app::VKEY_SPACE ||
-      e.GetKeyCode() == app::VKEY_RETURN) {
+  if (e.key_code() == ui::VKEY_SPACE || e.key_code() == ui::VKEY_RETURN) {
     ExecuteAction(1, false);
     return true;
   }
@@ -151,6 +147,9 @@
                                           bool is_mouse_gesture) {
   const Extension* extension = profile_->GetExtensionService()->
       GetExtensionById(page_action()->extension_id(), false);
+  if (!extension->ShowConfigureContextMenus())
+    return;
+
   Browser* browser = BrowserView::GetBrowserViewForNativeWindow(
       platform_util::GetTopLevel(GetWidget()->GetNativeView()))->browser();
   context_menu_contents_ =
@@ -180,7 +179,7 @@
   // During object construction (before the parent has been set) we are already
   // in a UpdatePageActions call, so we don't need to start another one (and
   // doing so causes crash described in http://crbug.com/57333).
-  if (GetParent())
+  if (parent())
     owner_->UpdatePageActions();
 }
 
diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.h b/chrome/browser/ui/views/location_bar/page_action_image_view.h
index c7b9851..ed0f190 100644
--- a/chrome/browser/ui/views/location_bar/page_action_image_view.h
+++ b/chrome/browser/ui/views/location_bar/page_action_image_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,7 +12,7 @@
 #include "base/scoped_ptr.h"
 #include "chrome/browser/extensions/image_loading_tracker.h"
 #include "chrome/browser/extensions/extension_context_menu_model.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
+#include "chrome/browser/ui/views/extensions/extension_popup.h"
 #include "views/controls/image_view.h"
 
 class LocationBarView;
diff --git a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
index fd2204e..75cc136 100644
--- a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
+++ b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/page_action_with_badge_view.h"
+#include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
 
-#include "chrome/browser/views/location_bar/page_action_image_view.h"
+#include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
 #include "chrome/common/extensions/extension.h"
 
 PageActionWithBadgeView::PageActionWithBadgeView(
diff --git a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
index 951516f..6071bad 100644
--- a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
+++ b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
 #pragma once
 
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/view.h"
 
 class GURL;
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
index bf133b9..6af5000 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/selected_keyword_view.h"
+#include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
 
-#include "app/l10n_util.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/search_engines/template_url_model.h"
@@ -12,6 +11,7 @@
 #include "chrome/browser/ui/omnibox/location_bar_util.h"
 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 SelectedKeywordView::SelectedKeywordView(const int background_images[],
                                          int contained_image,
@@ -50,7 +50,7 @@
   IconLabelBubbleView::Layout();
 }
 
-void SelectedKeywordView::SetKeyword(const std::wstring& keyword) {
+void SelectedKeywordView::SetKeyword(const string16& keyword) {
   keyword_ = keyword;
   if (keyword.empty())
     return;
@@ -59,8 +59,8 @@
     return;
 
   bool is_extension_keyword;
-  const string16 short_name = WideToUTF16(profile_->GetTemplateURLModel()->
-      GetKeywordShortName(keyword, &is_extension_keyword));
+  const string16 short_name = profile_->GetTemplateURLModel()->
+      GetKeywordShortName(keyword, &is_extension_keyword);
   int message_id = is_extension_keyword ?
       IDS_OMNIBOX_EXTENSION_KEYWORD_TEXT : IDS_OMNIBOX_KEYWORD_TEXT;
   full_label_.SetText(UTF16ToWide(
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.h b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
index 3e274ce..2e0c530 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.h
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include <string>
 
-#include "chrome/browser/views/location_bar/icon_label_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 #include "views/controls/label.h"
 
 class Profile;
@@ -33,8 +33,8 @@
   virtual void Layout();
 
   // The current keyword, or an empty string if no keyword is displayed.
-  void SetKeyword(const std::wstring& keyword);
-  std::wstring keyword() const { return keyword_; }
+  void SetKeyword(const string16& keyword);
+  string16 keyword() const { return keyword_; }
 
   void set_profile(Profile* profile) { profile_ = profile; }
 
@@ -42,7 +42,7 @@
   // The keyword we're showing. If empty, no keyword is selected.
   // NOTE: we don't cache the TemplateURL as it is possible for it to get
   // deleted out from under us.
-  std::wstring keyword_;
+  string16 keyword_;
 
   // These labels are never visible.  They are used to size the view.  One
   // label contains the complete description of the keyword, the second
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index f806037..886aec2 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/location_bar/star_view.h"
+#include "chrome/browser/ui/views/location_bar/star_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/command_updater.h"
@@ -13,6 +11,8 @@
 #include "chrome/browser/ui/views/browser_dialogs.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 StarView::StarView(CommandUpdater* command_updater)
     : command_updater_(command_updater) {
@@ -30,7 +30,7 @@
   // Since StarView is an ImageView, the SetTooltipText changes the accessible
   // name. To keep the accessible name unchanged, we need to set the accessible
   // name right after we modify the tooltip text for this view.
-  SetAccessibleName(UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_STAR)));
+  SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_STAR));
   SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
       on ? IDR_STAR_LIT : IDR_STAR));
 }
@@ -59,8 +59,7 @@
 }
 
 bool StarView::OnKeyPressed(const views::KeyEvent& e) {
-  if (e.GetKeyCode() == app::VKEY_SPACE ||
-      e.GetKeyCode() == app::VKEY_RETURN) {
+  if (e.key_code() == ui::VKEY_SPACE || e.key_code() == ui::VKEY_RETURN) {
     command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE);
     return true;
   }
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h
index 2ea7b35..ad02f9e 100644
--- a/chrome/browser/ui/views/location_bar/star_view.h
+++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "views/controls/image_view.h"
 
 class CommandUpdater;
diff --git a/chrome/browser/ui/views/location_bar/suggested_text_view.cc b/chrome/browser/ui/views/location_bar/suggested_text_view.cc
index 6da1a7b..fe7094d 100644
--- a/chrome/browser/ui/views/location_bar/suggested_text_view.cc
+++ b/chrome/browser/ui/views/location_bar/suggested_text_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 
 #include "chrome/browser/instant/instant_controller.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "gfx/canvas.h"
-#include "gfx/color_utils.h"
 #include "ui/base/animation/multi_animation.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
 
 SuggestedTextView::SuggestedTextView(LocationBarView* location_bar)
     : location_bar_(location_bar),
@@ -19,10 +19,6 @@
 }
 
 void SuggestedTextView::StartAnimation() {
-  if (!InstantController::IsEnabled(location_bar_->profile(),
-                                    InstantController::PREDICTIVE_TYPE)) {
-    return;
-  }
   StopAnimation();
 
   animation_.reset(CreateAnimation());
@@ -50,7 +46,7 @@
 }
 
 void SuggestedTextView::AnimationEnded(const ui::Animation* animation) {
-  location_bar_->OnCommitSuggestedText();
+  location_bar_->OnCommitSuggestedText(false);
 }
 
 void SuggestedTextView::AnimationProgressed(const ui::Animation* animation) {
diff --git a/chrome/browser/ui/views/login_view.cc b/chrome/browser/ui/views/login_view.cc
index a7e4e40..a898943 100644
--- a/chrome/browser/ui/views/login_view.cc
+++ b/chrome/browser/ui/views/login_view.cc
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/login_view.h"
+#include "chrome/browser/ui/views/login_view.h"
 
 #include <string>
 
-#include "app/l10n_util.h"
 #include "base/compiler_specific.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/root_view.h"
 
 static const int kMessageWidth = 320;
@@ -43,7 +43,7 @@
   message_label_->SetAllowCharacterBreak(true);
 
   // Initialize the Grid Layout Manager used for this dialog box.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   // Add the column set for the information message at the top of the dialog
@@ -60,7 +60,7 @@
   column_set->AddPaddingColumn(0, kTextfieldStackHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
   column_set->AddPaddingColumn(0, kTextfieldStackHorizontalSpacing);
@@ -68,19 +68,19 @@
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(message_label_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlLargeVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
 
   layout->StartRow(0, labels_column_set_id);
   layout->AddView(username_label_);
   layout->AddView(username_field_);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, labels_column_set_id);
   layout->AddView(password_label_);
   layout->AddView(password_field_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 }
 
 LoginView::~LoginView() {
diff --git a/chrome/browser/ui/views/notifications/balloon_view.cc b/chrome/browser/ui/views/notifications/balloon_view.cc
index 43ed162..69859cb 100644
--- a/chrome/browser/ui/views/notifications/balloon_view.cc
+++ b/chrome/browser/ui/views/notifications/balloon_view.cc
@@ -1,13 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/notifications/balloon_view.h"
+#include "chrome/browser/ui/views/notifications/balloon_view.h"
 
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/notifications/balloon.h"
@@ -18,17 +16,19 @@
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/views/bubble_border.h"
-#include "chrome/browser/views/notifications/balloon_view_host.h"
+#include "chrome/browser/ui/views/bubble_border.h"
+#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/insets.h"
-#include "gfx/native_widget_types.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/controls/button/button.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/button/text_button.h"
@@ -165,8 +165,7 @@
   balloon_->OnClose(by_user);
 }
 
-void BalloonViewImpl::DidChangeBounds(const gfx::Rect& previous,
-                                      const gfx::Rect& current) {
+void BalloonViewImpl::OnBoundsChanged() {
   SizeContentsWindow();
 }
 
@@ -186,9 +185,9 @@
   GetContentsMask(contents_rect, &path);
   html_container_->SetShape(path.CreateNativeRegion());
 
-  close_button_->SetBounds(GetCloseButtonBounds());
-  options_menu_button_->SetBounds(GetOptionsButtonBounds());
-  source_label_->SetBounds(GetLabelBounds());
+  close_button_->SetBoundsRect(GetCloseButtonBounds());
+  options_menu_button_->SetBoundsRect(GetOptionsButtonBounds());
+  source_label_->SetBoundsRect(GetLabelBounds());
 }
 
 void BalloonViewImpl::RepositionToBalloon() {
@@ -346,7 +345,7 @@
                           rb.GetBitmapNamed(IDR_TAB_CLOSE_H));
   close_button_->SetImage(views::CustomButton::BS_PUSHED,
                           rb.GetBitmapNamed(IDR_TAB_CLOSE_P));
-  close_button_->SetBounds(GetCloseButtonBounds());
+  close_button_->SetBoundsRect(GetCloseButtonBounds());
   close_button_->SetBackground(SK_ColorBLACK,
                                rb.GetBitmapNamed(IDR_TAB_CLOSE),
                                rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
@@ -356,12 +355,12 @@
   options_menu_button_->SetPushedIcon(*rb.GetBitmapNamed(IDR_BALLOON_WRENCH_P));
   options_menu_button_->set_alignment(views::TextButton::ALIGN_CENTER);
   options_menu_button_->set_border(NULL);
-  options_menu_button_->SetBounds(GetOptionsButtonBounds());
+  options_menu_button_->SetBoundsRect(GetOptionsButtonBounds());
 
   source_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
   source_label_->SetColor(kControlBarTextColor);
   source_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
-  source_label_->SetBounds(GetLabelBounds());
+  source_label_->SetBoundsRect(GetLabelBounds());
 
   SizeContentsWindow();
   html_container_->Show();
@@ -477,7 +476,7 @@
   DCHECK(canvas);
   // Paint the menu bar area white, with proper rounded corners.
   gfx::Path path;
-  gfx::Rect rect = GetLocalBounds(false);
+  gfx::Rect rect = GetContentsBounds();
   rect.set_height(GetShelfHeight());
   GetFrameMask(rect, &path);
 
diff --git a/chrome/browser/ui/views/notifications/balloon_view.h b/chrome/browser/ui/views/notifications/balloon_view.h
index a551f5a..82bb309 100644
--- a/chrome/browser/ui/views/notifications/balloon_view.h
+++ b/chrome/browser/ui/views/notifications/balloon_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,13 +12,13 @@
 #include "base/scoped_ptr.h"
 #include "base/task.h"
 #include "chrome/browser/notifications/balloon.h"
-#include "chrome/browser/views/notifications/balloon_view_host.h"
+#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/path.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "ui/base/animation/animation_delegate.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/label.h"
 #include "views/controls/menu/view_menu_delegate.h"
@@ -67,8 +67,7 @@
  private:
   // views::View interface.
   virtual void Paint(gfx::Canvas* canvas);
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
+  virtual void OnBoundsChanged();
   virtual gfx::Size GetPreferredSize();
 
   // views::ViewMenuDelegate interface.
diff --git a/chrome/browser/ui/views/notifications/balloon_view_host.cc b/chrome/browser/ui/views/notifications/balloon_view_host.cc
index eb9cb20..fcdbadf 100644
--- a/chrome/browser/ui/views/notifications/balloon_view_host.cc
+++ b/chrome/browser/ui/views/notifications/balloon_view_host.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/notifications/balloon_view_host.h"
+#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
 
 #include "chrome/browser/notifications/balloon.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
diff --git a/chrome/browser/ui/views/options/advanced_contents_view.cc b/chrome/browser/ui/views/options/advanced_contents_view.cc
index 6314525..3711870 100644
--- a/chrome/browser/ui/views/options/advanced_contents_view.cc
+++ b/chrome/browser/ui/views/options/advanced_contents_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/advanced_contents_view.h"
+#include "chrome/browser/ui/views/options/advanced_contents_view.h"
 
 #include <windows.h>
 
@@ -12,8 +12,8 @@
 #include <vsstyle.h>
 #include <vssym32.h>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include <string>
+
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/i18n/rtl.h"
@@ -37,10 +37,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/browser/shell_dialogs.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/options/options_util.h"
 #include "chrome/browser/ui/options/show_options_url.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "chrome/browser/ui/views/browser_dialogs.h"
 #include "chrome/browser/ui/views/clear_browsing_data.h"
 #include "chrome/browser/ui/views/list_background.h"
@@ -49,8 +48,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/native_theme_win.h"
 #include "grit/app_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -58,13 +55,17 @@
 #include "net/base/ssl_config_service_win.h"
 #include "skia/ext/skia_utils_win.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/native_theme_win.h"
 #include "views/background.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/scroll_view.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -135,7 +136,7 @@
     base::i18n::WrapPathWithLTRFormatting(file_path, &localized_file_path);
     text_field_->SetText(UTF16ToWide(localized_file_path));
   } else {
-    text_field_->SetText(file_path.ToWStringHack());
+    text_field_->SetText(file_path.LossyDisplayName());
   }
 }
 
@@ -147,8 +148,7 @@
       skia::SkColorToCOLORREF(text_field_background_color_), true, true);
   canvas->EndPlatformPaint();
   // Mirror left point for icon_bounds_ to draw icon in RTL locales correctly.
-  canvas->DrawBitmapInt(default_folder_icon_,
-                        MirroredLeftPointForRect(icon_bounds_),
+  canvas->DrawBitmapInt(default_folder_icon_, GetMirroredXForRect(icon_bounds_),
                         icon_bounds_.y());
 }
 
@@ -213,9 +213,6 @@
   AdvancedSection(Profile* profile, const std::wstring& title);
   virtual ~AdvancedSection() {}
 
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
-
  protected:
   // Convenience helpers to add different kinds of ColumnSets for specific
   // types of layout.
@@ -289,11 +286,6 @@
   title_label_->SetColor(title_color);
 }
 
-void AdvancedSection::DidChangeBounds(const gfx::Rect& previous,
-                                      const gfx::Rect& current) {
-  Layout();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // AdvancedSection, protected:
 
@@ -309,17 +301,17 @@
   column_set->AddPaddingColumn(0, views::Checkbox::GetTextIndent());
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
 }
 
 void AdvancedSection::AddTwoColumnSet(views::GridLayout* layout, int id) {
   ColumnSet* column_set = layout->AddColumnSet(id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
 }
@@ -360,8 +352,8 @@
                                              bool related_follows) {
   label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   AddTwoColumnRow(layout, label, control, control_stretches, id,
-      related_follows ?
-          kRelatedControlVerticalSpacing : kUnrelatedControlVerticalSpacing);
+      related_follows ? views::kRelatedControlVerticalSpacing
+                      : views::kUnrelatedControlVerticalSpacing);
 }
 
 void AdvancedSection::AddTwoColumnRow(views::GridLayout* layout,
@@ -392,8 +384,9 @@
 
 void AdvancedSection::AddSpacing(views::GridLayout* layout,
                                  bool related_follows) {
-  layout->AddPaddingRow(0, related_follows ? kRelatedControlVerticalSpacing
-                                           : kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(
+      0, related_follows ? views::kRelatedControlVerticalSpacing
+                         : views::kUnrelatedControlVerticalSpacing);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -411,13 +404,13 @@
                         GridLayout::USE_PREF, 0, 0);
   const int inset_column_layout_id = 1;
   column_set = layout->AddColumnSet(inset_column_layout_id);
-  column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, single_column_layout_id);
   layout->AddView(title_label_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, inset_column_layout_id);
   layout->AddView(contents_);
 }
@@ -597,7 +590,8 @@
   AddIndentedColumnSet(layout, indented_column_set_id);
 
   AddTwoColumnRow(layout, content_settings_button_, clear_data_button_, false,
-                  leading_column_set_id, kUnrelatedControlLargeVerticalSpacing);
+                  leading_column_set_id,
+                  views::kUnrelatedControlLargeVerticalSpacing);
 
   // The description label at the top and label.
   section_description_label_->SetMultiLine(true);
@@ -1186,10 +1180,10 @@
   ColumnSet* column_set = layout->AddColumnSet(double_column_view_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
   layout->StartRow(0, double_column_view_set_id);
   layout->AddView(download_default_download_location_display_, 1, 1,
                   GridLayout::FILL, GridLayout::CENTER);
@@ -1337,6 +1331,7 @@
 
   // Preferences we tie things to.
   StringPrefMember cloud_print_proxy_email_;
+  BooleanPrefMember cloud_print_proxy_enabled_;
 
   base::ScopedCallbackFactory<CloudPrintProxySection> factory_;
 
@@ -1424,11 +1419,13 @@
 
   // The enable / disable button and manage button.
   AddTwoColumnRow(layout, enable_disable_button_, manage_printer_button_, false,
-                  control_view_set_id, kRelatedControlVerticalSpacing);
+                  control_view_set_id, views::kRelatedControlVerticalSpacing);
 
   // Attach the preferences so we can flip things appropriately.
   cloud_print_proxy_email_.Init(prefs::kCloudPrintEmail,
                                 profile()->GetPrefs(), this);
+  cloud_print_proxy_enabled_.Init(prefs::kCloudPrintProxyEnabled,
+                                  profile()->GetPrefs(), this);
 
   // Start the UI off in the state we think it should be in.
   std::string pref_string(prefs::kCloudPrintEmail);
@@ -1443,8 +1440,13 @@
   if (pref_name == NULL)
     return;
 
-  if (*pref_name == prefs::kCloudPrintEmail) {
-    if (Enabled()) {
+  if (*pref_name == prefs::kCloudPrintEmail ||
+      *pref_name == prefs::kCloudPrintProxyEnabled) {
+    bool cloud_print_proxy_allowed =
+        !cloud_print_proxy_enabled_.IsManaged() ||
+        cloud_print_proxy_enabled_.GetValue();
+
+    if (Enabled() && cloud_print_proxy_allowed) {
       std::string email;
       if (profile()->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail))
         email = profile()->GetPrefs()->GetString(prefs::kCloudPrintEmail);
@@ -1456,6 +1458,7 @@
       enable_disable_button_->SetLabel(UTF16ToWide(l10n_util::GetStringUTF16(
           IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_BUTTON)));
       enable_disable_button_->InvalidateLayout();
+      enable_disable_button_->SetEnabled(true);
       manage_printer_button_->SetVisible(true);
       manage_printer_button_->InvalidateLayout();
     } else {
@@ -1464,6 +1467,7 @@
       enable_disable_button_->SetLabel(UTF16ToWide(l10n_util::GetStringUTF16(
           IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_BUTTON)));
       enable_disable_button_->InvalidateLayout();
+      enable_disable_button_->SetEnabled(cloud_print_proxy_allowed);
       manage_printer_button_->SetVisible(false);
     }
 
@@ -1471,12 +1475,12 @@
     // possible that the section_description_label_ has changed
     // heights.  And scroll us back to being visible in that case, to
     // be nice to the user.
-    views::View* view = section_description_label_->GetParent();
+    views::View* view = section_description_label_->parent();
     while (view && view->GetClassName() != views::ScrollView::kViewClassName)
-      view = view->GetParent();
+      view = view->parent();
     if (view) {
       gfx::Rect visible_bounds = GetVisibleBounds();
-      bool was_all_visible = (visible_bounds.size() == bounds().size());
+      bool was_all_visible = (visible_bounds.size() == size());
       // Our bounds can change across this call, so we have to use the
       // new bounds if we want to stay completely visible.
       view->Layout();
@@ -1504,8 +1508,7 @@
   virtual int GetLineScrollIncrement(views::ScrollView* scroll_view,
                                      bool is_horizontal, bool is_positive);
   virtual void Layout();
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
+  virtual void OnBoundsChanged();
 
  protected:
   // OptionsPageView implementation:
@@ -1547,9 +1550,8 @@
 }
 
 void AdvancedContentsView::Layout() {
-  views::View* parent = GetParent();
-  if (parent && parent->width()) {
-    const int width = parent->width();
+  if (parent() && parent()->width()) {
+    const int width = parent()->width();
     const int height = GetHeightForWidth(width);
     SetBounds(0, 0, width, height);
   } else {
@@ -1559,8 +1561,7 @@
   View::Layout();
 }
 
-void AdvancedContentsView::DidChangeBounds(const gfx::Rect& previous,
-                                           const gfx::Rect& current) {
+void AdvancedContentsView::OnBoundsChanged() {
   // Override to do nothing. Calling Layout() interferes with our scrolling.
 }
 
@@ -1569,7 +1570,7 @@
 // AdvancedContentsView, OptionsPageView implementation:
 
 void AdvancedContentsView::InitControlLayout() {
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int single_column_view_set_id = 0;
@@ -1636,10 +1637,10 @@
 // AdvancedScrollViewContainer, views::View overrides:
 
 void AdvancedScrollViewContainer::Layout() {
-  gfx::Rect lb = GetLocalBounds(false);
+  gfx::Rect lb = GetLocalBounds();
 
   gfx::Size border = gfx::NativeTheme::instance()->GetThemeBorderSize(
       gfx::NativeTheme::LIST);
   lb.Inset(border.width(), border.height());
-  scroll_view_->SetBounds(lb);
+  scroll_view_->SetBoundsRect(lb);
 }
diff --git a/chrome/browser/ui/views/options/advanced_contents_view.h b/chrome/browser/ui/views/options/advanced_contents_view.h
index 7671e9b..eda31a0 100644
--- a/chrome/browser/ui/views/options/advanced_contents_view.h
+++ b/chrome/browser/ui/views/options/advanced_contents_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_OPTIONS_ADVANCED_CONTENTS_VIEW_H__
 #pragma once
 
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 
 class AdvancedContentsView;
 namespace views {
diff --git a/chrome/browser/ui/views/options/advanced_page_view.cc b/chrome/browser/ui/views/options/advanced_page_view.cc
index 62f8660..907caa7 100644
--- a/chrome/browser/ui/views/options/advanced_page_view.cc
+++ b/chrome/browser/ui/views/options/advanced_page_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/advanced_page_view.h"
+#include "chrome/browser/ui/views/options/advanced_page_view.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
@@ -16,11 +14,13 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
 #include "views/controls/message_box_view.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/scroll_view.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
 
@@ -38,12 +38,12 @@
  protected:
   // views::DialogDelegate
   virtual std::wstring GetDialogButtonLabel(
-      MessageBoxFlags::DialogButton button) const {
+      ui::MessageBoxFlags::DialogButton button) const {
     switch (button) {
-      case MessageBoxFlags::DIALOGBUTTON_OK:
+      case ui::MessageBoxFlags::DIALOGBUTTON_OK:
         return UTF16ToWide(
             l10n_util::GetStringUTF16(IDS_OPTIONS_RESET_OKLABEL));
-      case MessageBoxFlags::DIALOGBUTTON_CANCEL:
+      case ui::MessageBoxFlags::DIALOGBUTTON_CANCEL:
         return UTF16ToWide(
             l10n_util::GetStringUTF16(IDS_OPTIONS_RESET_CANCELLABEL));
       default:
@@ -71,7 +71,8 @@
         IDS_OPTIONS_RESET_CONFIRM_BOX_WIDTH_CHARS);
     // Also deleted when the window closes.
     message_box_view_ = new MessageBoxView(
-        MessageBoxFlags::kFlagHasMessage | MessageBoxFlags::kFlagHasOKButton,
+        ui::MessageBoxFlags::kFlagHasMessage |
+            ui::MessageBoxFlags::kFlagHasOKButton,
         UTF16ToWide(
             l10n_util::GetStringUTF16(IDS_OPTIONS_RESET_MESSAGE)).c_str(),
         std::wstring(),
@@ -128,7 +129,7 @@
   using views::GridLayout;
   using views::ColumnSet;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int single_column_view_set_id = 0;
@@ -141,7 +142,7 @@
 
   layout->StartRow(1, single_column_view_set_id);
   layout->AddView(advanced_scroll_view_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(reset_to_default_button_, 1, 1,
diff --git a/chrome/browser/ui/views/options/advanced_page_view.h b/chrome/browser/ui/views/options/advanced_page_view.h
index 5769be9..90ce325 100644
--- a/chrome/browser/ui/views/options/advanced_page_view.h
+++ b/chrome/browser/ui/views/options/advanced_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_OPTIONS_ADVANCED_PAGE_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 #include "views/controls/button/button.h"
 
 class AdvancedOptionsListModel;
diff --git a/chrome/browser/ui/views/options/content_exceptions_table_view.cc b/chrome/browser/ui/views/options/content_exceptions_table_view.cc
index 1b81aa1..39c2478 100644
--- a/chrome/browser/ui/views/options/content_exceptions_table_view.cc
+++ b/chrome/browser/ui/views/options/content_exceptions_table_view.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/content_exceptions_table_view.h"
+#include "chrome/browser/ui/views/options/content_exceptions_table_view.h"
 
-#include "gfx/font.h"
+#include "ui/gfx/font.h"
 
 ContentExceptionsTableView::ContentExceptionsTableView(
     ContentExceptionsTableModel* model,
diff --git a/chrome/browser/ui/views/options/content_filter_page_view.cc b/chrome/browser/ui/views/options/content_filter_page_view.cc
index 919ccbb..265bd63 100644
--- a/chrome/browser/ui/views/options/content_filter_page_view.cc
+++ b/chrome/browser/ui/views/options/content_filter_page_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/content_filter_page_view.h"
+#include "chrome/browser/ui/views/options/content_filter_page_view.h"
 
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/content_settings/content_settings_details.h"
@@ -14,16 +13,17 @@
 #include "chrome/browser/notifications/notification_exceptions_table_model.h"
 #include "chrome/browser/plugin_exceptions_table_model.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/options/exceptions_view.h"
-#include "chrome/browser/views/options/simple_content_exceptions_view.h"
+#include "chrome/browser/ui/views/options/exceptions_view.h"
+#include "chrome/browser/ui/views/options/simple_content_exceptions_view.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/notification_type.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/radio_button.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 ContentFilterPageView::ContentFilterPageView(Profile* profile,
@@ -50,10 +50,10 @@
 
   const int single_column_set_id = 0;
   views::ColumnSet* column_set = layout->AddColumnSet(single_column_set_id);
-  column_set->AddPaddingColumn(0, kRelatedControlVerticalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlVerticalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   static const int kTitleIDs[] = {
     IDS_MODIFY_COOKIE_STORING_LABEL,
@@ -73,7 +73,7 @@
 
   layout->StartRow(0, single_column_set_id);
   layout->AddView(title_label);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   static const int kAllowIDs[] = {
     IDS_COOKIES_ALLOW_RADIO,
@@ -94,7 +94,7 @@
   allow_radio_->SetMultiLine(true);
   layout->StartRow(0, single_column_set_id);
   layout->AddView(allow_radio_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   static const int kAskIDs[] = {
     IDS_COOKIES_ASK_EVERY_TIME_RADIO,
@@ -121,7 +121,7 @@
       ask_radio_->SetMultiLine(true);
       layout->StartRow(0, single_column_set_id);
       layout->AddView(ask_radio_);
-      layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     }
   }
 
@@ -143,7 +143,7 @@
   block_radio_->SetMultiLine(true);
   layout->StartRow(0, single_column_set_id);
   layout->AddView(block_radio_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   exceptions_button_ = new views::NativeButton(this,
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_EXCEPTIONS_BUTTON)));
diff --git a/chrome/browser/ui/views/options/content_filter_page_view.h b/chrome/browser/ui/views/options/content_filter_page_view.h
index 5f23583..eff5899 100644
--- a/chrome/browser/ui/views/options/content_filter_page_view.h
+++ b/chrome/browser/ui/views/options/content_filter_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 #include "chrome/common/content_settings_types.h"
 #include "chrome/common/notification_registrar.h"
 #include "views/controls/button/button.h"
diff --git a/chrome/browser/ui/views/options/content_page_view.cc b/chrome/browser/ui/views/options/content_page_view.cc
index 7bdba35..19ace33 100644
--- a/chrome/browser/ui/views/options/content_page_view.cc
+++ b/chrome/browser/ui/views/options/content_page_view.cc
@@ -1,15 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/content_page_view.h"
+#include "chrome/browser/ui/views/options/content_page_view.h"
 
 #include <windows.h>
 #include <shlobj.h>
 #include <vsstyle.h>
 #include <vssym32.h>
 
-#include "app/l10n_util.h"
+#include <string>
+
 #include "base/command_line.h"
 #include "base/string_util.h"
 #include "chrome/browser/autofill/autofill_dialog.h"
@@ -20,21 +21,20 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/sync/sync_setup_wizard.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/importer_view.h"
-#include "chrome/browser/views/options/managed_prefs_banner_view.h"
-#include "chrome/browser/views/options/options_group_view.h"
-#include "chrome/browser/views/options/passwords_exceptions_window_view.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/ui/views/importer_view.h"
+#include "chrome/browser/ui/views/options/managed_prefs_banner_view.h"
+#include "chrome/browser/ui/views/options/options_group_view.h"
+#include "chrome/browser/ui/views/options/passwords_exceptions_window_view.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas.h"
-#include "gfx/native_theme_win.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/native_theme_win.h"
 #include "views/controls/button/radio_button.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -128,9 +128,8 @@
       ConfirmMessageBoxDialog::RunWithCustomConfiguration(
           GetWindow()->GetNativeWindow(),
           this,
-          UTF16ToWide(l10n_util::GetStringFUTF16(
-              IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL,
-              l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))),
+          UTF16ToWide(l10n_util::GetStringUTF16(
+              IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL)),
           UTF16ToWide(l10n_util::GetStringUTF16(
               IDS_SYNC_STOP_SYNCING_DIALOG_TITLE)),
           UTF16ToWide(l10n_util::GetStringUTF16(
@@ -160,7 +159,7 @@
   }
   if (source == sync_action_link_) {
     DCHECK(sync_service_ && !sync_service_->IsManaged());
-    sync_service_->ShowLoginDialog(GetWindow()->GetNativeWindow());
+    sync_service_->ShowErrorUI(GetWindow()->GetNativeWindow());
     return;
   }
   if (source == privacy_dashboard_link_) {
@@ -194,28 +193,28 @@
     layout->StartRow(0, single_column_view_set_id);
     InitSyncGroup();
     layout->AddView(sync_group_);
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
 
   layout->StartRow(0, single_column_view_set_id);
   InitPasswordSavingGroup();
   layout->AddView(passwords_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   InitFormAutofillGroup();
   layout->AddView(form_autofill_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   InitBrowsingDataGroup();
   layout->AddView(browsing_data_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   InitThemesGroup();
   layout->AddView(themes_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Init member prefs so we can update the controls if prefs change.
   ask_to_save_passwords_.Init(prefs::kPasswordManagerEnabled,
@@ -307,11 +306,11 @@
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(passwords_asktosave_radio_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(passwords_neversave_radio_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(show_passwords_button_);
 
@@ -370,7 +369,7 @@
   ColumnSet* double_col_set = layout->AddColumnSet(double_column_view_set_id);
   double_col_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                             GridLayout::USE_PREF, 0, 0);
-  double_col_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  double_col_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   double_col_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                             GridLayout::USE_PREF, 0, 0);
 
@@ -443,7 +442,7 @@
   ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -452,11 +451,11 @@
                   GridLayout::FILL, GridLayout::LEADING);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(sync_action_link_, 3, 1);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(sync_start_stop_button_);
   layout->AddView(sync_customize_button_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(privacy_dashboard_link_, 3, 1);
 
diff --git a/chrome/browser/ui/views/options/content_page_view.h b/chrome/browser/ui/views/options/content_page_view.h
index 45a7390..1f811c4 100644
--- a/chrome/browser/ui/views/options/content_page_view.h
+++ b/chrome/browser/ui/views/options/content_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,8 @@
 #include "chrome/browser/autofill/personal_data_manager.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "chrome/browser/views/confirm_message_box_dialog.h"
+#include "chrome/browser/ui/views/confirm_message_box_dialog.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 #include "views/controls/button/button.h"
 #include "views/controls/link.h"
 #include "views/view.h"
diff --git a/chrome/browser/ui/views/options/content_settings_window_view.cc b/chrome/browser/ui/views/options/content_settings_window_view.cc
index eeaca4e..30916cf 100644
--- a/chrome/browser/ui/views/options/content_settings_window_view.cc
+++ b/chrome/browser/ui/views/options/content_settings_window_view.cc
@@ -1,24 +1,24 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/content_settings_window_view.h"
+#include "chrome/browser/ui/views/options/content_settings_window_view.h"
 
-#include "app/l10n_util.h"
 #include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/options/advanced_page_view.h"
-#include "chrome/browser/views/options/content_filter_page_view.h"
-#include "chrome/browser/views/options/cookie_filter_page_view.h"
-#include "chrome/browser/views/options/general_page_view.h"
-#include "chrome/browser/views/options/plugin_filter_page_view.h"
+#include "chrome/browser/ui/views/options/advanced_page_view.h"
+#include "chrome/browser/ui/views/options/content_filter_page_view.h"
+#include "chrome/browser/ui/views/options/cookie_filter_page_view.h"
+#include "chrome/browser/ui/views/options/general_page_view.h"
+#include "chrome/browser/ui/views/options/plugin_filter_page_view.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/label.h"
 #include "views/widget/root_view.h"
 #include "views/window/dialog_delegate.h"
@@ -129,7 +129,7 @@
                       listbox_width,
                       height() - (3 * kDialogPadding) - label_->height());
 
-  if (pages_[current_page_]->GetParent()) {
+  if (pages_[current_page_]->parent()) {
     pages_[current_page_]->SetBounds(
         2 * kDialogPadding + listbox_width,
         2 * kDialogPadding + label_->height(),
@@ -196,7 +196,7 @@
 }
 
 void ContentSettingsWindowView::ShowSettingsPage(int page) {
-  if (pages_[current_page_]->GetParent())
+  if (pages_[current_page_]->parent())
     RemoveChildView(pages_[current_page_]);
   current_page_ = page;
   AddChildView(pages_[current_page_]);
diff --git a/chrome/browser/ui/views/options/cookie_filter_page_view.cc b/chrome/browser/ui/views/options/cookie_filter_page_view.cc
index 055a964..ec44bdf 100644
--- a/chrome/browser/ui/views/options/cookie_filter_page_view.cc
+++ b/chrome/browser/ui/views/options/cookie_filter_page_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/cookie_filter_page_view.h"
+#include "chrome/browser/ui/views/options/cookie_filter_page_view.h"
 
-#include "app/l10n_util.h"
 #include "chrome/browser/content_settings/host_content_settings_map.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/options/show_options_url.h"
@@ -12,9 +11,10 @@
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/checkbox.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 CookieFilterPageView::CookieFilterPageView(Profile* profile)
     : ContentFilterPageView(profile, CONTENT_SETTINGS_TYPE_COOKIES),
@@ -40,7 +40,7 @@
 
   GridLayout* layout = static_cast<GridLayout*>(GetLayoutManager());
   const int single_column_set_id = 0;
-  layout->AddPaddingRow(0, kUnrelatedControlLargeVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
 
   block_3rdparty_check_ = new views::Checkbox(UTF16ToWide(
       l10n_util::GetStringUTF16(IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX)));
@@ -48,7 +48,7 @@
 
   layout->StartRow(0, single_column_set_id);
   layout->AddView(block_3rdparty_check_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Now that this has been added to the view hierarchy, it's safe to call
   // SetChecked() on it.
@@ -62,7 +62,7 @@
 
   layout->StartRow(0, single_column_set_id);
   layout->AddView(clear_on_close_check_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   show_cookies_button_ = new views::NativeButton(this,
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_SHOW_COOKIES_BUTTON)));
@@ -70,7 +70,7 @@
   layout->StartRow(0, single_column_set_id);
   layout->AddView(show_cookies_button_, 1, 1, GridLayout::LEADING,
                   GridLayout::FILL);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   views::Link* flash_settings_link = new views::Link(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_FLASH_STORAGE_SETTINGS)));
diff --git a/chrome/browser/ui/views/options/cookie_filter_page_view.h b/chrome/browser/ui/views/options/cookie_filter_page_view.h
index 4a03723..c0d9445 100644
--- a/chrome/browser/ui/views/options/cookie_filter_page_view.h
+++ b/chrome/browser/ui/views/options/cookie_filter_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_OPTIONS_COOKIE_FILTER_PAGE_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/options/content_filter_page_view.h"
+#include "chrome/browser/ui/views/options/content_filter_page_view.h"
 
 #include "chrome/browser/prefs/pref_member.h"
 
diff --git a/chrome/browser/ui/views/options/cookies_view.cc b/chrome/browser/ui/views/options/cookies_view.cc
index 973e11b..24c8ccc 100644
--- a/chrome/browser/ui/views/options/cookies_view.cc
+++ b/chrome/browser/ui/views/options/cookies_view.cc
@@ -1,32 +1,32 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/cookies_view.h"
+#include "chrome/browser/ui/views/options/cookies_view.h"
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/appcache_info_view.h"
-#include "chrome/browser/views/cookie_info_view.h"
-#include "chrome/browser/views/database_info_view.h"
-#include "chrome/browser/views/indexed_db_info_view.h"
-#include "chrome/browser/views/local_storage_info_view.h"
-#include "gfx/canvas.h"
-#include "gfx/color_utils.h"
+#include "chrome/browser/ui/views/appcache_info_view.h"
+#include "chrome/browser/ui/views/cookie_info_view.h"
+#include "chrome/browser/ui/views/database_info_view.h"
+#include "chrome/browser/ui/views/indexed_db_info_view.h"
+#include "chrome/browser/ui/views/local_storage_info_view.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/cookie_monster.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
 #include "views/border.h"
-#include "views/grid_layout.h"
 #include "views/controls/label.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/tree/tree_view.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 // static
 views::Window* CookiesView::instance_ = NULL;
@@ -55,7 +55,7 @@
 }
 
 void CookiesTreeView::RemoveSelectedItems() {
-  TreeModelNode* selected_node = GetSelectedNode();
+  ui::TreeModelNode* selected_node = GetSelectedNode();
   if (selected_node) {
     static_cast<CookiesTreeModel*>(model())->DeleteCookieNode(
         static_cast<CookieTreeNode*>(GetSelectedNode()));
@@ -73,13 +73,12 @@
 class CookiesView::InfoPanelView : public views::View {
  public:
   virtual void Layout() {
-    int child_count = GetChildViewCount();
-    for (int i = 0; i < child_count; ++i)
+    for (int i = 0; i < child_count(); ++i)
       GetChildViewAt(i)->SetBounds(0, 0, width(), height());
   }
 
   virtual gfx::Size GetPreferredSize() {
-    DCHECK(GetChildViewCount() > 0);
+    DCHECK(has_children());
     return GetChildViewAt(0)->GetPreferredSize();
   }
 };
@@ -108,8 +107,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 // CookiesView, TreeModelObserver overrides:
 
-void CookiesView::TreeNodesAdded(TreeModel* model,
-                                 TreeModelNode* parent,
+void CookiesView::TreeNodesAdded(ui::TreeModel* model,
+                                 ui::TreeModelNode* parent,
                                  int start,
                                  int count) {
   UpdateRemoveButtonsState();
@@ -146,9 +145,9 @@
 
 bool CookiesView::HandleKeyEvent(views::Textfield* sender,
                                  const views::KeyEvent& key_event) {
-  if (key_event.GetKeyCode() == app::VKEY_ESCAPE) {
+  if (key_event.key_code() == ui::VKEY_ESCAPE) {
     ResetSearchQuery();
-  } else if (key_event.GetKeyCode() == app::VKEY_RETURN) {
+  } else if (key_event.key_code() == ui::VKEY_RETURN) {
     search_update_factory_.RevokeAll();
     UpdateSearchResults();
   }
@@ -177,15 +176,16 @@
 void CookiesView::Layout() {
   // Lay out the Remove/Remove All buttons in the parent view.
   gfx::Size ps = remove_button_->GetPreferredSize();
-  gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
-  int y_buttons = parent_bounds.bottom() - ps.height() - kButtonVEdgeMargin;
+  gfx::Rect parent_bounds = parent()->GetContentsBounds();
+  int y_buttons =
+      parent_bounds.bottom() - ps.height() - views::kButtonVEdgeMargin;
 
   remove_button_->SetBounds(kPanelHorizMargin, y_buttons, ps.width(),
                             ps.height());
 
   ps = remove_all_button_->GetPreferredSize();
   int remove_all_x = remove_button_->x() + remove_button_->width() +
-      kRelatedControlHorizontalSpacing;
+      views::kRelatedControlHorizontalSpacing;
   remove_all_button_->SetBounds(remove_all_x, y_buttons, ps.width(),
                                 ps.height());
 
@@ -241,8 +241,8 @@
   }
 }
 
-void CookiesView::OnTreeViewKeyDown(app::KeyboardCode keycode) {
-  if (keycode == app::VKEY_DELETE)
+void CookiesView::OnTreeViewKeyDown(ui::KeyboardCode keycode) {
+  if (keycode == ui::VKEY_DELETE)
     cookies_tree_->RemoveSelectedItems();
 }
 
@@ -295,7 +295,7 @@
       NULL,
       new BrowsingDataAppCacheHelper(profile_),
       BrowsingDataIndexedDBHelper::Create(profile_)));
-  cookies_tree_model_->AddObserver(this);
+  cookies_tree_model_->AddCookiesTreeObserver(this);
 
   info_panel_ = new InfoPanelView;
   cookie_info_view_ = new CookieInfoView(false);
@@ -320,17 +320,17 @@
   using views::GridLayout;
   using views::ColumnSet;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int five_column_layout_id = 0;
   ColumnSet* column_set = layout->AddColumnSet(five_column_layout_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -343,12 +343,12 @@
   layout->AddView(search_label_);
   layout->AddView(search_field_);
   layout->AddView(clear_search_button_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_layout_id);
   layout->AddView(description_label_);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(1, single_column_layout_id);
   cookies_tree_->set_lines_at_root(true);
   cookies_tree_->set_auto_expand_children(true);
@@ -356,14 +356,13 @@
 
   cookies_tree_->SetController(this);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_layout_id);
   layout->AddView(info_panel_);
 
   // Add the Remove/Remove All buttons to the ClientView
-  View* parent = GetParent();
-  parent->AddChildView(remove_button_);
-  parent->AddChildView(remove_all_button_);
+  parent()->AddChildView(remove_button_);
+  parent()->AddChildView(remove_all_button_);
   if (!cookies_tree_model_.get()->GetRoot()->GetChildCount()) {
     UpdateForEmptyState();
   } else {
diff --git a/chrome/browser/ui/views/options/cookies_view.h b/chrome/browser/ui/views/options/cookies_view.h
index af0d9ec..0b05fc1 100644
--- a/chrome/browser/ui/views/options/cookies_view.h
+++ b/chrome/browser/ui/views/options/cookies_view.h
@@ -18,14 +18,6 @@
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
 
-namespace views {
-
-class Label;
-class NativeButton;
-
-}  // namespace views
-
-
 class AppCacheInfoView;
 class CookieInfoView;
 class CookiesTreeView;
@@ -34,9 +26,16 @@
 class LocalStorageInfoView;
 class Profile;
 class Timer;
+
+namespace ui {
 class TreeModel;
 class TreeModelNode;
+}  // namespace ui
 
+namespace views {
+class Label;
+class NativeButton;
+}  // namespace views
 
 class CookiesView : public CookiesTreeModel::Observer,
                     public views::View,
@@ -54,15 +53,15 @@
   void UpdateSearchResults();
 
   // Begin TreeModelObserver implementation.
-  virtual void TreeNodesAdded(TreeModel* model,
-                              TreeModelNode* parent,
+  virtual void TreeNodesAdded(ui::TreeModel* model,
+                              ui::TreeModelNode* parent,
                               int start,
                               int count);
-  virtual void TreeNodesRemoved(TreeModel* model,
-                                TreeModelNode* parent,
+  virtual void TreeNodesRemoved(ui::TreeModel* model,
+                                ui::TreeModelNode* parent,
                                 int start,
                                 int count) {}
-  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) {}
+  virtual void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) {}
   // End TreeModelObserver implementation.
 
   // views::ButtonListener implementation.
@@ -72,7 +71,7 @@
   virtual void OnTreeViewSelectionChanged(views::TreeView* tree_view);
 
   // views::TreeViewController implementation.
-  virtual void OnTreeViewKeyDown(app::KeyboardCode keycode);
+  virtual void OnTreeViewKeyDown(ui::KeyboardCode keycode);
 
   // views::Textfield::Controller implementation.
   virtual void ContentsChanged(views::Textfield* sender,
diff --git a/chrome/browser/ui/views/options/exception_editor_view.cc b/chrome/browser/ui/views/options/exception_editor_view.cc
index d5ceaa7..c4404d3 100644
--- a/chrome/browser/ui/views/options/exception_editor_view.cc
+++ b/chrome/browser/ui/views/options/exception_editor_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/exception_editor_view.h"
+#include "chrome/browser/ui/views/options/exception_editor_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/content_exceptions_table_model.h"
 #include "googleurl/src/url_canon.h"
@@ -13,10 +11,12 @@
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 ExceptionEditorView::ExceptionEditorView(
@@ -123,17 +123,17 @@
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTION_EDITOR_OTR_TITLE)));
   incognito_cb_->SetChecked(is_off_the_record_);
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   // For the Textfields.
   views::ColumnSet* column_set = layout->AddColumnSet(1);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -143,12 +143,12 @@
   layout->AddView(pattern_tf_);
   layout->AddView(pattern_iv_);
 
-  layout->StartRowWithPadding(0, 1, 0, kRelatedControlVerticalSpacing);
+  layout->StartRowWithPadding(0, 1, 0, views::kRelatedControlVerticalSpacing);
   layout->AddView(CreateLabel(IDS_EXCEPTION_EDITOR_ACTION_TITLE));
   layout->AddView(action_cb_);
 
   if (allow_off_the_record_) {
-    layout->StartRowWithPadding(0, 1, 0, kRelatedControlVerticalSpacing);
+    layout->StartRowWithPadding(0, 1, 0, views::kRelatedControlVerticalSpacing);
     layout->AddView(incognito_cb_, 3, 1, GridLayout::FILL, GridLayout::FILL);
   }
 }
diff --git a/chrome/browser/ui/views/options/exceptions_page_view.cc b/chrome/browser/ui/views/options/exceptions_page_view.cc
index 3cb7488..ab96ed8 100644
--- a/chrome/browser/ui/views/options/exceptions_page_view.cc
+++ b/chrome/browser/ui/views/options/exceptions_page_view.cc
@@ -1,20 +1,21 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/exceptions_page_view.h"
+#include "chrome/browser/ui/views/options/exceptions_page_view.h"
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
 #include "views/background.h"
 #include "views/controls/button/native_button.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 using views::ColumnSet;
 using views::GridLayout;
@@ -55,7 +56,7 @@
       UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
   for (size_t i = 0; i < result.size(); ++i) {
     saved_signons_.push_back(new PasswordRow(
-        gfx::SortedDisplayURL(result[i]->origin, languages), result[i]));
+        ui::SortedDisplayURL(result[i]->origin, languages), result[i]));
   }
   if (observer_)
     observer_->OnModelChanged();
@@ -128,7 +129,7 @@
   SetupTable();
 
   // Do the layout thing.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int top_column_set_id = 0;
@@ -137,7 +138,7 @@
   ColumnSet* column_set = layout->AddColumnSet(top_column_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -147,11 +148,11 @@
                   GridLayout::FILL);
   layout->AddView(&remove_button_);
   layout->StartRowWithPadding(0, top_column_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(1);
   layout->AddView(&remove_all_button_);
   layout->StartRowWithPadding(0, top_column_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
 
   layout->SkipColumns(1);
   layout->AddView(&show_button_);
@@ -182,9 +183,9 @@
 
   // Creates the different columns for the table.
   // The float resize values are the result of much tinkering.
-  std::vector<TableColumn> columns;
-  columns.push_back(TableColumn(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN,
-                                TableColumn::LEFT, -1, 0.55f));
+  std::vector<ui::TableColumn> columns;
+  columns.push_back(ui::TableColumn(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN,
+                                    ui::TableColumn::LEFT, -1, 0.55f));
   columns.back().sortable = true;
   table_view_ = new views::TableView(&table_model_, columns, views::TEXT_ONLY,
                                      true, true, true);
diff --git a/chrome/browser/ui/views/options/exceptions_page_view.h b/chrome/browser/ui/views/options/exceptions_page_view.h
index 618b408..ee34869 100644
--- a/chrome/browser/ui/views/options/exceptions_page_view.h
+++ b/chrome/browser/ui/views/options/exceptions_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,8 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "chrome/browser/views/options/passwords_page_view.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/options/passwords_page_view.h"
 #include "views/controls/table/table_view_observer.h"
 
 class Profile;
diff --git a/chrome/browser/ui/views/options/exceptions_view.cc b/chrome/browser/ui/views/options/exceptions_view.cc
index 55de5aa..67ff3b6 100644
--- a/chrome/browser/ui/views/options/exceptions_view.cc
+++ b/chrome/browser/ui/views/options/exceptions_view.cc
@@ -1,23 +1,23 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/exceptions_view.h"
+#include "chrome/browser/ui/views/options/exceptions_view.h"
 
 #include <algorithm>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/views/options/content_exceptions_table_view.h"
+#include "chrome/browser/ui/views/options/content_exceptions_table_view.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-#include "gfx/rect.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/label.h"
 #include "views/controls/table/table_view.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 static const int kExceptionsViewInsetSize = 5;
@@ -83,14 +83,15 @@
                                      remove_button_, remove_all_button_ };
 
   // The buttons are placed in the parent, but we need to lay them out.
-  int max_y = GetParent()->GetLocalBounds(false).bottom() - kButtonVEdgeMargin;
+  int max_y =
+      parent()->GetContentsBounds().bottom() - views::kButtonVEdgeMargin;
   int x = kPanelHorizMargin;
 
   for (size_t i = 0; i < arraysize(buttons); ++i) {
     gfx::Size pref = buttons[i]->GetPreferredSize();
     buttons[i]->SetBounds(x, max_y - pref.height(), pref.width(),
                           pref.height());
-    x += pref.width() + kRelatedControlHorizontalSpacing;
+    x += pref.width() + views::kRelatedControlHorizontalSpacing;
   }
 
   // Lay out the rest of this view.
@@ -164,12 +165,14 @@
 
   using views::GridLayout;
 
-  std::vector<TableColumn> columns;
+  std::vector<ui::TableColumn> columns;
   columns.push_back(
-      TableColumn(IDS_EXCEPTIONS_PATTERN_HEADER, TableColumn::LEFT, -1, .75));
+      ui::TableColumn(IDS_EXCEPTIONS_PATTERN_HEADER, ui::TableColumn::LEFT, -1,
+                      .75));
   columns.back().sortable = true;
   columns.push_back(
-      TableColumn(IDS_EXCEPTIONS_ACTION_HEADER, TableColumn::LEFT, -1, .25));
+      ui::TableColumn(IDS_EXCEPTIONS_ACTION_HEADER, ui::TableColumn::LEFT, -1,
+                      .25));
   columns.back().sortable = true;
   table_ = new ContentExceptionsTableView(&model_, columns);
   views::TableView::SortDescriptors sort;
@@ -193,11 +196,10 @@
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_REMOVEALL_BUTTON)));
   remove_all_button_->set_tag(IDS_EXCEPTIONS_REMOVEALL_BUTTON);
 
-  View* parent = GetParent();
-  parent->AddChildView(add_button_);
-  parent->AddChildView(edit_button_);
-  parent->AddChildView(remove_button_);
-  parent->AddChildView(remove_all_button_);
+  parent()->AddChildView(add_button_);
+  parent()->AddChildView(edit_button_);
+  parent()->AddChildView(remove_button_);
+  parent()->AddChildView(remove_all_button_);
 
   GridLayout* layout = new GridLayout(this);
   layout->SetInsets(kExceptionsViewInsetSize, kExceptionsViewInsetSize,
@@ -206,14 +208,14 @@
 
   const int single_column_layout_id = 0;
   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(1, single_column_layout_id);
   layout->AddView(table_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   if (allow_off_the_record_) {
     views::Label* label = new views::Label(
@@ -221,7 +223,7 @@
     label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
     layout->StartRow(0, single_column_layout_id);
     layout->AddView(label, 1, 1, GridLayout::LEADING, GridLayout::CENTER);
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
 
   UpdateButtonState();
diff --git a/chrome/browser/ui/views/options/exceptions_view.h b/chrome/browser/ui/views/options/exceptions_view.h
index a0747be..d168685 100644
--- a/chrome/browser/ui/views/options/exceptions_view.h
+++ b/chrome/browser/ui/views/options/exceptions_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "chrome/browser/content_exceptions_table_model.h"
-#include "chrome/browser/views/options/exception_editor_view.h"
+#include "chrome/browser/ui/views/options/exception_editor_view.h"
 #include "chrome/common/content_settings.h"
 #include "chrome/common/content_settings_types.h"
 #include "views/controls/button/button.h"
diff --git a/chrome/browser/ui/views/options/fonts_languages_window_view.cc b/chrome/browser/ui/views/options/fonts_languages_window_view.cc
index 79a146b..70b0492 100644
--- a/chrome/browser/ui/views/options/fonts_languages_window_view.cc
+++ b/chrome/browser/ui/views/options/fonts_languages_window_view.cc
@@ -1,20 +1,18 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/fonts_languages_window_view.h"
+#include "chrome/browser/ui/views/options/fonts_languages_window_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/views/options/fonts_page_view.h"
-#include "chrome/browser/views/options/languages_page_view.h"
+#include "chrome/browser/ui/views/options/fonts_page_view.h"
+#include "chrome/browser/ui/views/options/languages_page_view.h"
 #include "chrome/common/chrome_constants.h"
-#include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/tabbed_pane/tabbed_pane.h"
 #include "views/window/window.h"
 
diff --git a/chrome/browser/ui/views/options/fonts_page_view.cc b/chrome/browser/ui/views/options/fonts_page_view.cc
index b02a27e..be6b4a7 100644
--- a/chrome/browser/ui/views/options/fonts_page_view.cc
+++ b/chrome/browser/ui/views/options/fonts_page_view.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/fonts_page_view.h"
+#include "chrome/browser/ui/views/options/fonts_page_view.h"
 
 #include <windows.h>
 #include <shlobj.h>
@@ -11,26 +11,25 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/file_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/default_encoding_combo_model.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/shell_dialogs.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/font.h"
-#include "gfx/native_theme_win.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "grit/locale_settings.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/native_theme_win.h"
 #include "views/controls/button/native_button.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -257,7 +256,7 @@
   using views::GridLayout;
   using views::ColumnSet;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int single_column_view_set_id = 0;
@@ -273,11 +272,11 @@
   fonts_group_title_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(fonts_group_title_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   InitFontLayout();
   layout->AddView(fonts_contents_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   // Encoding group.
   encoding_group_title_ = new views::Label(
@@ -287,7 +286,7 @@
   encoding_group_title_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(encoding_group_title_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   InitEncodingLayout();
   layout->AddView(encoding_contents_);
@@ -364,10 +363,10 @@
 
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -377,7 +376,7 @@
   layout->AddView(serif_font_display_view_, 1, 1,
                   GridLayout::FILL, GridLayout::CENTER);
   layout->AddView(serif_font_change_page_button_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Sans serif font controls.
   layout->StartRow(0, triple_column_view_set_id);
@@ -385,7 +384,7 @@
   layout->AddView(sans_serif_font_display_view_, 1, 1,
                   GridLayout::FILL, GridLayout::CENTER);
   layout->AddView(sans_serif_font_change_page_button_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Fixed-width font controls.
   layout->StartRow(0, triple_column_view_set_id);
@@ -393,7 +392,7 @@
   layout->AddView(fixed_width_font_display_view_, 1, 1,
                   GridLayout::FILL, GridLayout::CENTER);
   layout->AddView(fixed_width_font_change_page_button_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 }
 
 void FontsPageView::InitEncodingLayout() {
@@ -423,7 +422,7 @@
   ColumnSet* column_set = layout->AddColumnSet(double_column_view_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
diff --git a/chrome/browser/ui/views/options/fonts_page_view.h b/chrome/browser/ui/views/options/fonts_page_view.h
index 7627aa7..6891fda 100644
--- a/chrome/browser/ui/views/options/fonts_page_view.h
+++ b/chrome/browser/ui/views/options/fonts_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,12 +9,15 @@
 #include <string>
 
 #include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/shell_dialogs.h"
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/shell_dialogs.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/button/button.h"
 #include "views/view.h"
 
+class DefaultEncodingComboboxModel;
+class FontDisplayView;
+
 namespace views {
 class GroupboxView;
 class Label;
@@ -22,10 +25,6 @@
 class TableView;
 }
 
-class DefaultEncodingComboboxModel;
-class FontDisplayView;
-class TableModel;
-
 ///////////////////////////////////////////////////////////////////////////////
 // FontsPageView
 
diff --git a/chrome/browser/ui/views/options/general_page_view.cc b/chrome/browser/ui/views/options/general_page_view.cc
index a0243cf..b78f51a 100644
--- a/chrome/browser/ui/views/options/general_page_view.cc
+++ b/chrome/browser/ui/views/options/general_page_view.cc
@@ -1,17 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/general_page_view.h"
+#include "chrome/browser/ui/views/options/general_page_view.h"
 
-#include "app/combobox_model.h"
-#include "app/l10n_util.h"
+#include <string>
+#include <vector>
+
 #include "base/callback.h"
 #include "base/message_loop.h"
 #include "base/string16.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_window.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/custom_home_pages_table_model.h"
 #include "chrome/browser/dom_ui/new_tab_ui.h"
 #include "chrome/browser/instant/instant_confirm_dialog.h"
@@ -23,7 +25,6 @@
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_model.h"
 #include "chrome/browser/search_engines/template_url_model_observer.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/options/show_options_url.h"
 #include "chrome/browser/ui/views/keyword_editor_view.h"
 #include "chrome/browser/ui/views/options/managed_prefs_banner_view.h"
@@ -34,12 +35,14 @@
 #include "chrome/installer/util/browser_distribution.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/button/radio_button.h"
 #include "views/controls/label.h"
 #include "views/controls/table/table_view.h"
 #include "views/controls/textfield/textfield.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 namespace {
 
@@ -74,7 +77,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 // SearchEngineListModel
 
-class SearchEngineListModel : public ComboboxModel,
+class SearchEngineListModel : public ui::ComboboxModel,
                               public TemplateURLModelObserver {
  public:
   explicit SearchEngineListModel(Profile* profile);
@@ -84,7 +87,7 @@
   // so that when the TemplateURLModel changes the combobox can be updated.
   void SetCombobox(views::Combobox* combobox);
 
-  // ComboboxModel overrides:
+  // ui::ComboboxModel overrides:
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
@@ -351,23 +354,23 @@
   layout->StartRow(0, single_column_view_set_id);
   InitStartupGroup();
   layout->AddView(startup_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   InitHomepageGroup();
   layout->AddView(homepage_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   InitDefaultSearchGroup();
   layout->AddView(default_search_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
 #if !defined(OS_CHROMEOS)
   layout->StartRow(0, single_column_view_set_id);
   InitDefaultBrowserGroup();
   layout->AddView(default_browser_group_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 #endif
 
   // Register pref observers that update the controls when a pref changes.
@@ -380,6 +383,9 @@
       profile()->GetPrefs(), this);
   homepage_.Init(prefs::kHomePage, profile()->GetPrefs(), this);
   show_home_button_.Init(prefs::kShowHomeButton, profile()->GetPrefs(), this);
+  default_browser_policy_.Init(prefs::kDefaultBrowserSettingEnabled,
+                               g_browser_process->local_state(),
+                               this);
 }
 
 void GeneralPageView::NotifyPrefChanged(const std::string* pref_name) {
@@ -444,6 +450,15 @@
 
   if (!pref_name || *pref_name == prefs::kInstantEnabled)
     instant_checkbox_->SetChecked(prefs->GetBoolean(prefs::kInstantEnabled));
+
+  if (!pref_name || *pref_name == prefs::kDefaultBrowserSettingEnabled) {
+    // If the option is managed the UI is uncondionally disabled otherwise we
+    // restart the standard button enabling logic.
+    if (default_browser_policy_.IsManaged())
+      default_browser_use_as_default_button_->SetEnabled(false);
+    else
+      default_browser_worker_->StartCheckDefaultBrowser();
+  }
 }
 
 void GeneralPageView::HighlightGroup(OptionsGroup highlight_group) {
@@ -461,7 +476,9 @@
 
 void GeneralPageView::SetDefaultBrowserUIState(
     ShellIntegration::DefaultBrowserUIState state) {
-  bool button_enabled = state == ShellIntegration::STATE_NOT_DEFAULT;
+  bool button_enabled =
+      (state == ShellIntegration::STATE_NOT_DEFAULT) &&
+      !default_browser_policy_.IsManaged();
   default_browser_use_as_default_button_->SetEnabled(button_enabled);
   default_browser_use_as_default_button_->SetNeedElevation(true);
   if (state == ShellIntegration::STATE_IS_DEFAULT) {
@@ -545,20 +562,20 @@
   column_set = layout->AddColumnSet(double_column_view_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(startup_homepage_radio_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(startup_last_session_radio_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(startup_custom_radio_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, double_column_view_set_id);
   layout->AddView(startup_custom_pages_table_, 1, 1,
@@ -574,11 +591,11 @@
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(startup_add_custom_page_button_,
                                1, 1, GridLayout::FILL, GridLayout::CENTER);
-  button_stack_layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  button_stack_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(startup_remove_custom_page_button_,
                                1, 1, GridLayout::FILL, GridLayout::CENTER);
-  button_stack_layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  button_stack_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(startup_use_current_page_button_,
                                1, 1, GridLayout::FILL, GridLayout::CENTER);
@@ -625,18 +642,18 @@
   column_set = layout->AddColumnSet(double_column_view_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(homepage_use_newtab_radio_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, double_column_view_set_id);
   layout->AddView(homepage_use_url_radio_);
   layout->AddView(homepage_use_url_textfield_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(homepage_show_home_button_checkbox_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
@@ -681,7 +698,7 @@
   ColumnSet* column_set = layout->AddColumnSet(double_column_view_set_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -696,14 +713,14 @@
   column_set->AddPaddingColumn(0, views::Checkbox::GetTextIndent() + 3);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, double_column_view_set_id);
   layout->AddView(default_search_engine_combobox_);
   layout->AddView(default_search_manage_engines_button_);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, checkbox_column_view_set_id);
   layout->AddView(instant_checkbox_);
@@ -747,7 +764,7 @@
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(default_browser_status_label_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(default_browser_use_as_default_button_);
 
diff --git a/chrome/browser/ui/views/options/general_page_view.h b/chrome/browser/ui/views/options/general_page_view.h
index 928fc42..d8f5533 100644
--- a/chrome/browser/ui/views/options/general_page_view.h
+++ b/chrome/browser/ui/views/options/general_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,14 +9,18 @@
 #include "chrome/browser/prefs/pref_change_registrar.h"
 #include "chrome/browser/prefs/pref_member.h"
 #include "chrome/browser/shell_integration.h"
-#include "chrome/browser/views/options/options_page_view.h"
-#include "chrome/browser/views/url_picker.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/url_picker.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/button/button.h"
 #include "views/controls/link.h"
 #include "views/controls/table/table_view_observer.h"
 #include "views/view.h"
 
+class CustomHomePagesTableModel;
+class OptionsGroupView;
+class SearchEngineListModel;
+
 namespace views {
 class Checkbox;
 class GroupboxView;
@@ -26,10 +30,6 @@
 class TableView;
 class Textfield;
 }
-class CustomHomePagesTableModel;
-class OptionsGroupView;
-class SearchEngineListModel;
-class TableModel;
 
 ///////////////////////////////////////////////////////////////////////////////
 // GeneralPageView
@@ -160,6 +160,7 @@
   OptionsGroupView* default_browser_group_;
   views::Label* default_browser_status_label_;
   views::NativeButton* default_browser_use_as_default_button_;
+  BooleanPrefMember default_browser_policy_;
 
   // The helper object that performs default browser set/check tasks.
   scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
diff --git a/chrome/browser/ui/views/options/languages_page_view.cc b/chrome/browser/ui/views/options/languages_page_view.cc
index afe1e84..f260202 100644
--- a/chrome/browser/ui/views/options/languages_page_view.cc
+++ b/chrome/browser/ui/views/options/languages_page_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,10 +7,8 @@
 #include <vsstyle.h>
 #include <vssym32.h>
 
-#include "chrome/browser/views/options/languages_page_view.h"
+#include "chrome/browser/ui/views/options/languages_page_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/string_util.h"
@@ -20,24 +18,26 @@
 #include "chrome/browser/language_order_table_model.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/shell_dialogs.h"
-#include "chrome/browser/views/restart_message_box.h"
+#include "chrome/browser/ui/shell_dialogs.h"
+#include "chrome/browser/ui/views/restart_message_box.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/spellcheck_common.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
-#include "gfx/native_theme_win.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/native_theme_win.h"
 #include "unicode/uloc.h"
 #include "views/controls/button/radio_button.h"
 #include "views/controls/tabbed_pane/tabbed_pane.h"
 #include "views/controls/table/table_view.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -265,7 +265,7 @@
   using views::GridLayout;
   using views::ColumnSet;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int single_column_view_set_id = 0;
@@ -282,7 +282,7 @@
       views::Label::ALIGN_LEFT);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(languages_instructions_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Add two columns - for table, and for button stack.
   std::vector<TableColumn> columns;
@@ -297,7 +297,7 @@
   column_set = layout->AddColumnSet(double_column_view_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -317,22 +317,22 @@
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(add_button_, 1, 1, GridLayout::FILL,
                                GridLayout::CENTER);
-  button_stack_layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  button_stack_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(remove_button_, 1, 1, GridLayout::FILL,
                                GridLayout::CENTER);
-  button_stack_layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  button_stack_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(move_up_button_, 1, 1, GridLayout::FILL,
                                GridLayout::CENTER);
-  button_stack_layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  button_stack_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   button_stack_layout->StartRow(0, single_column_view_set_id);
   button_stack_layout->AddView(move_down_button_, 1, 1, GridLayout::FILL,
                                GridLayout::CENTER);
 
   layout->AddView(button_stack_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   language_info_label_ = new views::Label(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_CHROME_LANGUAGE_INFO)));
@@ -371,17 +371,17 @@
   // SpellCheck language settings.
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(enable_spellchecking_checkbox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   if (command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures)) {
     layout->StartRow(0, single_column_view_set_id);
     layout->AddView(enable_autospellcorrect_checkbox_);
-    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
   const int double_column_view_set_2_id = 2;
   column_set = layout->AddColumnSet(double_column_view_set_2_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -390,15 +390,15 @@
   layout->AddView(change_dictionary_language_combobox_);
 
   // UI language settings.
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
   layout->StartRow(0, single_column_view_set_id);
   layout->AddView(language_info_label_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(0, double_column_view_set_2_id);
   layout->AddView(ui_language_label_);
   layout->AddView(change_ui_language_combobox_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Init member prefs so we can update the controls if prefs change.
   app_locale_.Init(prefs::kApplicationLocale,
diff --git a/chrome/browser/ui/views/options/languages_page_view.h b/chrome/browser/ui/views/options/languages_page_view.h
index f6a1372..1babef7 100644
--- a/chrome/browser/ui/views/options/languages_page_view.h
+++ b/chrome/browser/ui/views/options/languages_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,12 +7,16 @@
 #pragma once
 
 #include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/controls/button/button.h"
 #include "views/controls/table/table_view_observer.h"
 #include "views/view.h"
 
+class AddLanguageView;
+class LanguageComboboxModel;
+class LanguageOrderTableModel;
+
 namespace views {
 class Checkbox;
 class Label;
@@ -20,11 +24,6 @@
 class TableView;
 }
 
-class AddLanguageView;
-class LanguageComboboxModel;
-class LanguageOrderTableModel;
-class TableModel;
-
 ///////////////////////////////////////////////////////////////////////////////
 // LanguagesPageView
 
diff --git a/chrome/browser/ui/views/options/managed_prefs_banner_view.cc b/chrome/browser/ui/views/options/managed_prefs_banner_view.cc
index e063d14..02ef429 100644
--- a/chrome/browser/ui/views/options/managed_prefs_banner_view.cc
+++ b/chrome/browser/ui/views/options/managed_prefs_banner_view.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/managed_prefs_banner_view.h"
+#include "chrome/browser/ui/views/options/managed_prefs_banner_view.h"
 
-#include "app/resource_bundle.h"
-#include "gfx/color_utils.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
-#include "views/box_layout.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/color_utils.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
+#include "views/layout/box_layout.h"
+#include "views/layout/layout_constants.h"
 
 // Spacing between the banner frame and its contents.
 static const int kPrefsBannerPadding = 3;
@@ -39,7 +39,7 @@
       new views::BoxLayout(views::BoxLayout::kHorizontal,
                            kPrefsBannerPadding,
                            kPrefsBannerPadding,
-                           kRelatedControlSmallHorizontalSpacing));
+                           views::kRelatedControlSmallHorizontalSpacing));
   content_->AddChildView(warning_image_);
   content_->AddChildView(label_);
   OnUpdateVisibility();
@@ -51,12 +51,13 @@
 
   // Add space below the banner.
   gfx::Size size(content_->GetPreferredSize());
-  size.Enlarge(0, kRelatedControlVerticalSpacing);
+  size.Enlarge(0, views::kRelatedControlVerticalSpacing);
   return size;
 }
 
 void ManagedPrefsBannerView::Layout() {
-  content_->SetBounds(0, 0, width(), height() - kRelatedControlVerticalSpacing);
+  content_->SetBounds(
+      0, 0, width(), height() - views::kRelatedControlVerticalSpacing);
 }
 
 void ManagedPrefsBannerView::ViewHierarchyChanged(bool is_add,
diff --git a/chrome/browser/ui/views/options/options_group_view.cc b/chrome/browser/ui/views/options/options_group_view.cc
index 70f88b8..0d4a64d 100644
--- a/chrome/browser/ui/views/options/options_group_view.cc
+++ b/chrome/browser/ui/views/options/options_group_view.cc
@@ -1,24 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <vsstyle.h>
 #include <vssym32.h>
 
-#include "chrome/browser/views/options/options_group_view.h"
+#include "chrome/browser/ui/views/options/options_group_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_number_conversions.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
-#include "gfx/native_theme_win.h"
+#include "base/utf_string_conversions.h"
 #include "grit/locale_settings.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/native_theme_win.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 static const int kLeftColumnWidthChars = 20;
 static const int kOptionsGroupViewColumnSpacing = 30;
@@ -50,8 +51,8 @@
   description_label_->SetMultiLine(true);
   description_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
 
-  SetAccessibleName(title);
-  contents->SetAccessibleName(title);
+  SetAccessibleName(WideToUTF16Hack(title));
+  contents->SetAccessibleName(WideToUTF16Hack(title));
 }
 
 OptionsGroupView::~OptionsGroupView() {
@@ -79,7 +80,7 @@
     SkColor background_color = SkColorSetRGB(GetRValue(infocolor),
                                              GetGValue(infocolor),
                                              GetBValue(infocolor));
-    int y_offset = kUnrelatedControlVerticalSpacing / 2;
+    int y_offset = views::kUnrelatedControlVerticalSpacing / 2;
     canvas->FillRectInt(background_color, 0, 0, width(),
                         height() - y_offset);
   }
@@ -112,23 +113,23 @@
 
   const int two_column_layout_id = 0;
   ColumnSet* column_set = layout->AddColumnSet(two_column_layout_id);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
                         GridLayout::FIXED, left_column_width, 0);
   column_set->AddPaddingColumn(0, kOptionsGroupViewColumnSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(0, two_column_layout_id);
   layout->AddView(title_label_, 1, 1, GridLayout::FILL, GridLayout::LEADING);
   layout->AddView(contents_, 1, 3, GridLayout::FILL, GridLayout::FILL);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   layout->StartRow(1, two_column_layout_id);
   layout->AddView(description_label_, 1, 1,
                   GridLayout::FILL, GridLayout::LEADING);
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   if (show_separator_) {
     const int single_column_layout_id = 1;
diff --git a/chrome/browser/ui/views/options/options_page_view.cc b/chrome/browser/ui/views/options/options_page_view.cc
index 81b1e98..b81b3af 100644
--- a/chrome/browser/ui/views/options/options_page_view.cc
+++ b/chrome/browser/ui/views/options/options_page_view.cc
@@ -1,11 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
 
 #include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "views/widget/widget.h"
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/options/options_window_view.cc b/chrome/browser/ui/views/options/options_window_view.cc
index e2940d6..7126f7d 100644
--- a/chrome/browser/ui/views/options/options_window_view.cc
+++ b/chrome/browser/ui/views/options/options_window_view.cc
@@ -2,10 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -19,6 +17,7 @@
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/tabbed_pane/tabbed_pane.h"
 #include "views/widget/root_view.h"
 #include "views/window/dialog_delegate.h"
@@ -197,9 +196,9 @@
 
 void OptionsWindowView::Init() {
   tabs_ = new views::TabbedPane;
-  tabs_->SetAccessibleName(UTF16ToWide(
-      l10n_util::GetStringFUTF16(IDS_OPTIONS_DIALOG_TITLE,
-                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))));
+  tabs_->SetAccessibleName(l10n_util::GetStringFUTF16(
+      IDS_OPTIONS_DIALOG_TITLE,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
   tabs_->SetListener(this);
   AddChildView(tabs_);
 
@@ -222,6 +221,10 @@
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_ADVANCED_TAB_LABEL)),
       advanced_page, false);
 
+  // Bind the profile to the window so that the ChromeViewsDelegate can find
+  // the user preferences to store and retrieve window placement settings.
+  window()->SetNativeWindowProperty(Profile::kProfileKey, profile_);
+
   DCHECK(tabs_->GetTabCount() == OPTIONS_PAGE_COUNT);
 }
 
diff --git a/chrome/browser/ui/views/options/passwords_exceptions_window_view.cc b/chrome/browser/ui/views/options/passwords_exceptions_window_view.cc
index c9f5c73..ed9c70d 100644
--- a/chrome/browser/ui/views/options/passwords_exceptions_window_view.cc
+++ b/chrome/browser/ui/views/options/passwords_exceptions_window_view.cc
@@ -1,15 +1,15 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/passwords_exceptions_window_view.h"
+#include "chrome/browser/ui/views/options/passwords_exceptions_window_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/views/options/passwords_page_view.h"
-#include "chrome/browser/views/options/exceptions_page_view.h"
+#include "chrome/browser/ui/views/options/exceptions_page_view.h"
+#include "chrome/browser/ui/views/options/passwords_page_view.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/tabbed_pane/tabbed_pane.h"
 #include "views/window/window.h"
 
diff --git a/chrome/browser/ui/views/options/passwords_page_view.cc b/chrome/browser/ui/views/options/passwords_page_view.cc
index 8e30879..705c4d1 100644
--- a/chrome/browser/ui/views/options/passwords_page_view.cc
+++ b/chrome/browser/ui/views/options/passwords_page_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/passwords_page_view.h"
+#include "chrome/browser/ui/views/options/passwords_page_view.h"
 
-#include "app/l10n_util.h"
 #include "base/i18n/rtl.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -13,10 +12,11 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/background.h"
 #include "views/controls/button/native_button.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 using views::ColumnSet;
 using views::GridLayout;
@@ -99,7 +99,7 @@
   return TableModel::CompareValues(row1, row2, column_id);
 }
 
-void PasswordsTableModel::SetObserver(TableModelObserver* observer) {
+void PasswordsTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
@@ -119,7 +119,7 @@
       UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
   for (size_t i = 0; i < result.size(); ++i) {
     saved_signons_[i] = new PasswordRow(
-        gfx::SortedDisplayURL(result[i]->origin, languages), result[i]);
+        ui::SortedDisplayURL(result[i]->origin, languages), result[i]);
   }
   if (observer_)
     observer_->OnModelChanged();
@@ -277,14 +277,14 @@
 
   // Do the layout thing.
   const int top_column_set_id = 0;
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   // Design the grid.
   ColumnSet* column_set = layout->AddColumnSet(top_column_set_id);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -294,15 +294,15 @@
                   GridLayout::FILL);
   layout->AddView(&remove_button_);
   layout->StartRowWithPadding(0, top_column_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(1);
   layout->AddView(&remove_all_button_);
   layout->StartRowWithPadding(0, top_column_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(1);
   layout->AddView(&show_button_);
   layout->StartRowWithPadding(0, top_column_set_id, 0,
-                              kRelatedControlVerticalSpacing);
+                              views::kRelatedControlVerticalSpacing);
   layout->SkipColumns(1);
   layout->AddView(&password_label_);
   layout->AddPaddingRow(1, 0);
@@ -333,12 +333,12 @@
 
   // Creates the different columns for the table.
   // The float resize values are the result of much tinkering.
-  std::vector<TableColumn> columns;
-  columns.push_back(TableColumn(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN,
-                                       TableColumn::LEFT, -1, 0.55f));
+  std::vector<ui::TableColumn> columns;
+  columns.push_back(ui::TableColumn(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN,
+                                    ui::TableColumn::LEFT, -1, 0.55f));
   columns.back().sortable = true;
-  columns.push_back(TableColumn(
-      IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN, TableColumn::LEFT,
+  columns.push_back(ui::TableColumn(
+      IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN, ui::TableColumn::LEFT,
       -1, 0.37f));
   columns.back().sortable = true;
   table_view_ = new views::TableView(&table_model_, columns, views::TEXT_ONLY,
diff --git a/chrome/browser/ui/views/options/passwords_page_view.h b/chrome/browser/ui/views/options/passwords_page_view.h
index 39428bf..76eed4e 100644
--- a/chrome/browser/ui/views/options/passwords_page_view.h
+++ b/chrome/browser/ui/views/options/passwords_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,16 +8,16 @@
 
 #include <vector>
 
-#include "app/table_model.h"
-#include "app/text_elider.h"
 #include "base/compiler_specific.h"
 #include "base/scoped_ptr.h"
 #include "base/stl_util-inl.h"
 #include "chrome/browser/password_manager/password_store.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/prefs/pref_member.h"
-#include "chrome/browser/views/confirm_message_box_dialog.h"
-#include "chrome/browser/views/options/options_page_view.h"
+#include "chrome/browser/ui/views/confirm_message_box_dialog.h"
+#include "chrome/browser/ui/views/options/options_page_view.h"
+#include "ui/base/models/table_model.h"
+#include "ui/base/text/text_elider.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/label.h"
 #include "views/controls/table/table_view.h"
@@ -73,7 +73,7 @@
   virtual int RowCount() OVERRIDE;
   virtual string16 GetText(int row, int column) OVERRIDE;
   virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE;
-  virtual void SetObserver(TableModelObserver* observer) OVERRIDE;
+  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
 
   // Delete the PasswordForm at specified row from the database (and remove
   // from view).
@@ -102,13 +102,13 @@
   // Wraps the PasswordForm from the database and caches the display URL for
   // quick sorting.
   struct PasswordRow {
-    PasswordRow(const gfx::SortedDisplayURL& url,
+    PasswordRow(const ui::SortedDisplayURL& url,
                 webkit_glue::PasswordForm* password_form)
         : display_url(url), form(password_form) {
     }
 
     // Contains the URL that is displayed along with the
-    gfx::SortedDisplayURL display_url;
+    ui::SortedDisplayURL display_url;
 
     // The underlying PasswordForm. We own this.
     scoped_ptr<webkit_glue::PasswordForm> form;
@@ -120,7 +120,7 @@
   }
 
   // The TableView observing this model.
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 
   // Dispatching row count events specific to this password manager table model
   // to this observer.
diff --git a/chrome/browser/ui/views/options/plugin_filter_page_view.cc b/chrome/browser/ui/views/options/plugin_filter_page_view.cc
index b527960..7d37ef3 100644
--- a/chrome/browser/ui/views/options/plugin_filter_page_view.cc
+++ b/chrome/browser/ui/views/options/plugin_filter_page_view.cc
@@ -1,17 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/plugin_filter_page_view.h"
+#include "chrome/browser/ui/views/options/plugin_filter_page_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/options/show_options_url.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 PluginFilterPageView::PluginFilterPageView(Profile* profile)
     : ContentFilterPageView(profile, CONTENT_SETTINGS_TYPE_PLUGINS) {
@@ -30,7 +29,7 @@
 
   GridLayout* layout = static_cast<GridLayout*>(GetLayoutManager());
   const int single_column_set_id = 0;
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   views::Link* plugins_page_link = new views::Link(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_PLUGIN_SELECTIVE_DISABLE)));
diff --git a/chrome/browser/ui/views/options/plugin_filter_page_view.h b/chrome/browser/ui/views/options/plugin_filter_page_view.h
index f874774..6a1d441 100644
--- a/chrome/browser/ui/views/options/plugin_filter_page_view.h
+++ b/chrome/browser/ui/views/options/plugin_filter_page_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_OPTIONS_PLUGIN_FILTER_PAGE_VIEW_H_
 #pragma once
 
-#include "chrome/browser/views/options/content_filter_page_view.h"
+#include "chrome/browser/ui/views/options/content_filter_page_view.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // PluginFilterPageView class is used to render the plugin content settings tab.
diff --git a/chrome/browser/ui/views/options/simple_content_exceptions_view.cc b/chrome/browser/ui/views/options/simple_content_exceptions_view.cc
index 51be466..5dc1d3e 100644
--- a/chrome/browser/ui/views/options/simple_content_exceptions_view.cc
+++ b/chrome/browser/ui/views/options/simple_content_exceptions_view.cc
@@ -1,21 +1,21 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/options/simple_content_exceptions_view.h"
+#include "chrome/browser/ui/views/options/simple_content_exceptions_view.h"
 
 #include <algorithm>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
-#include "gfx/rect.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/button/native_button.h"
 #include "views/controls/table/table_view.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/window/window.h"
 
 static const int kExceptionsViewInsetSize = 5;
@@ -69,14 +69,15 @@
   views::NativeButton* buttons[] = { remove_button_, remove_all_button_ };
 
   // The buttons are placed in the parent, but we need to lay them out.
-  int max_y = GetParent()->GetLocalBounds(false).bottom() - kButtonVEdgeMargin;
+  int max_y =
+      parent()->GetContentsBounds().bottom() - views::kButtonVEdgeMargin;
   int x = kPanelHorizMargin;
 
   for (size_t i = 0; i < arraysize(buttons); ++i) {
     gfx::Size pref = buttons[i]->GetPreferredSize();
     buttons[i]->SetBounds(x, max_y - pref.height(), pref.width(),
                           pref.height());
-    x += pref.width() + kRelatedControlHorizontalSpacing;
+    x += pref.width() + views::kRelatedControlHorizontalSpacing;
   }
 
   // Lay out the rest of this view.
@@ -116,12 +117,14 @@
 
   using views::GridLayout;
 
-  std::vector<TableColumn> columns;
+  std::vector<ui::TableColumn> columns;
   columns.push_back(
-      TableColumn(IDS_EXCEPTIONS_HOSTNAME_HEADER, TableColumn::LEFT, -1, .75));
+      ui::TableColumn(IDS_EXCEPTIONS_HOSTNAME_HEADER, ui::TableColumn::LEFT, -1,
+                      .75));
   columns.back().sortable = true;
   columns.push_back(
-      TableColumn(IDS_EXCEPTIONS_ACTION_HEADER, TableColumn::LEFT, -1, .25));
+      ui::TableColumn(IDS_EXCEPTIONS_ACTION_HEADER, ui::TableColumn::LEFT, -1,
+                      .25));
   columns.back().sortable = true;
   table_ = new views::TableView(model_.get(), columns, views::TEXT_ONLY,
                                 false, true, false);
@@ -140,9 +143,8 @@
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_REMOVEALL_BUTTON)));
   remove_all_button_->set_tag(IDS_EXCEPTIONS_REMOVEALL_BUTTON);
 
-  View* parent = GetParent();
-  parent->AddChildView(remove_button_);
-  parent->AddChildView(remove_all_button_);
+  parent()->AddChildView(remove_button_);
+  parent()->AddChildView(remove_all_button_);
 
   GridLayout* layout = new GridLayout(this);
   layout->SetInsets(kExceptionsViewInsetSize, kExceptionsViewInsetSize,
@@ -151,14 +153,14 @@
 
   const int single_column_layout_id = 0;
   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                         GridLayout::USE_PREF, 0, 0);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(1, single_column_layout_id);
   layout->AddView(table_);
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   UpdateButtonState();
 }
diff --git a/chrome/browser/ui/views/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info_bubble_view.cc
index d872399..a062d15 100644
--- a/chrome/browser/ui/views/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info_bubble_view.cc
@@ -1,25 +1,25 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/page_info_bubble_view.h"
+#include "chrome/browser/ui/views/page_info_bubble_view.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/cert_store.h"
 #include "chrome/browser/certificate_viewer.h"
 #include "chrome/browser/google/google_util.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/info_bubble.h"
-#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/info_bubble.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/image_view.h"
 #include "views/controls/label.h"
 #include "views/controls/separator.h"
-#include "views/grid_layout.h"
+#include "views/layout/grid_layout.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
 
@@ -207,6 +207,11 @@
 }
 
 void PageInfoBubbleView::LinkActivated(views::Link* source, int event_flags) {
+  // We want to make sure the info bubble closes once the link is activated.  So
+  // we close it explicitly rather than relying on a side-effect of opening a
+  // new tab (see http://crosbug.com/10186).
+  info_bubble_->Close();
+
   GURL url = google_util::AppendGoogleLocaleParam(
       GURL(chrome::kPageInfoHelpCenterURL));
   Browser* browser = BrowserList::GetLastActive();
diff --git a/chrome/browser/ui/views/page_info_bubble_view.h b/chrome/browser/ui/views/page_info_bubble_view.h
index fc2917b..0f57d5a 100644
--- a/chrome/browser/ui/views/page_info_bubble_view.h
+++ b/chrome/browser/ui/views/page_info_bubble_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "chrome/browser/page_info_model.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/slide_animation.h"
 #include "views/controls/link.h"
diff --git a/chrome/browser/ui/views/pinned_contents_info_bubble.cc b/chrome/browser/ui/views/pinned_contents_info_bubble.cc
index c064c16..90074f7 100644
--- a/chrome/browser/ui/views/pinned_contents_info_bubble.cc
+++ b/chrome/browser/ui/views/pinned_contents_info_bubble.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/pinned_contents_info_bubble.h"
+#include "chrome/browser/ui/views/pinned_contents_info_bubble.h"
 
-#include "chrome/browser/views/bubble_border.h"
+#include "chrome/browser/ui/views/bubble_border.h"
 
 void PinnedContentsBorderContents::SizeAndGetBounds(
     const gfx::Rect& position_relative_to,
diff --git a/chrome/browser/ui/views/pinned_contents_info_bubble.h b/chrome/browser/ui/views/pinned_contents_info_bubble.h
index d1070b6..cdf4ed5 100644
--- a/chrome/browser/ui/views/pinned_contents_info_bubble.h
+++ b/chrome/browser/ui/views/pinned_contents_info_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_
 #pragma once
 
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/ui/views/info_bubble.h"
 
 // This is a specialization of BorderContents, used to draw a border around
 // an InfoBubble that has its contents pinned to a specific location. See
diff --git a/chrome/browser/ui/views/reload_button.cc b/chrome/browser/ui/views/reload_button.cc
index 0df1030..4189dd1 100644
--- a/chrome/browser/ui/views/reload_button.cc
+++ b/chrome/browser/ui/views/reload_button.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/reload_button.h"
+#include "chrome/browser/ui/views/reload_button.h"
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/event_utils.h"
-#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/event_utils.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // ReloadButton, public:
@@ -83,7 +83,7 @@
     if (event.IsShiftDown() || event.IsControlDown()) {
       command = IDC_RELOAD_IGNORING_CACHE;
       // Mask off Shift and Control so they don't affect the disposition below.
-      flags &= ~(views::Event::EF_SHIFT_DOWN | views::Event::EF_CONTROL_DOWN);
+      flags &= ~(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
     } else {
       command = IDC_RELOAD;
     }
diff --git a/chrome/browser/ui/views/reload_button_unittest.cc b/chrome/browser/ui/views/reload_button_unittest.cc
index 5f8255b..2f1aab0 100644
--- a/chrome/browser/ui/views/reload_button_unittest.cc
+++ b/chrome/browser/ui/views/reload_button_unittest.cc
@@ -1,9 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/message_loop.h"
-#include "chrome/browser/views/reload_button.h"
+#include "chrome/browser/ui/views/reload_button.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class ReloadButtonTest : public testing::Test {
@@ -57,7 +57,7 @@
              false);
 
   // Press the button.  This should start the double-click timer.
-  views::MouseEvent e(views::Event::ET_MOUSE_PRESSED, 0, 0, 0);
+  views::MouseEvent e(ui::ET_MOUSE_PRESSED, 0, 0, 0);
   reload_.ButtonPressed(&reload_, e);
   CheckState(true, ReloadButton::MODE_RELOAD, ReloadButton::MODE_RELOAD, true,
              false);
@@ -76,7 +76,7 @@
 
 TEST_F(ReloadButtonTest, DoubleClickTimer) {
   // Start by pressing the button.
-  views::MouseEvent e(views::Event::ET_MOUSE_PRESSED, 0, 0, 0);
+  views::MouseEvent e(ui::ET_MOUSE_PRESSED, 0, 0, 0);
   reload_.ButtonPressed(&reload_, e);
 
   // Try to press the button again.  This should do nothing because the timer is
@@ -102,7 +102,7 @@
 
 TEST_F(ReloadButtonTest, DisableOnHover) {
   // Change to stop and hover.
-  views::MouseEvent e(views::Event::ET_MOUSE_PRESSED, 0, 0, 0);
+  views::MouseEvent e(ui::ET_MOUSE_PRESSED, 0, 0, 0);
   reload_.ButtonPressed(&reload_, e);
   reload_.ChangeMode(ReloadButton::MODE_STOP, false);
   set_mouse_hovered(true);
@@ -115,7 +115,7 @@
 
   // Un-hover the button, which should allow it to reset.
   set_mouse_hovered(false);
-  views::MouseEvent e2(views::Event::ET_MOUSE_MOVED, 0, 0, 0);
+  views::MouseEvent e2(ui::ET_MOUSE_MOVED, 0, 0, 0);
   reload_.OnMouseExited(e2);
   CheckState(true, ReloadButton::MODE_RELOAD, ReloadButton::MODE_RELOAD, false,
              false);
@@ -123,7 +123,7 @@
 
 TEST_F(ReloadButtonTest, ResetOnClick) {
   // Change to stop and hover.
-  views::MouseEvent e(views::Event::ET_MOUSE_PRESSED, 0, 0, 0);
+  views::MouseEvent e(ui::ET_MOUSE_PRESSED, 0, 0, 0);
   reload_.ButtonPressed(&reload_, e);
   reload_.ChangeMode(ReloadButton::MODE_STOP, false);
   set_mouse_hovered(true);
@@ -137,7 +137,7 @@
 
 TEST_F(ReloadButtonTest, ResetOnTimer) {
   // Change to stop, hover, and change back to reload.
-  views::MouseEvent e(views::Event::ET_MOUSE_PRESSED, 0, 0, 0);
+  views::MouseEvent e(ui::ET_MOUSE_PRESSED, 0, 0, 0);
   reload_.ButtonPressed(&reload_, e);
   reload_.ChangeMode(ReloadButton::MODE_STOP, false);
   set_mouse_hovered(true);
diff --git a/chrome/browser/ui/views/repost_form_warning_view.cc b/chrome/browser/ui/views/repost_form_warning_view.cc
index 18022e8..36ec052 100644
--- a/chrome/browser/ui/views/repost_form_warning_view.cc
+++ b/chrome/browser/ui/views/repost_form_warning_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/repost_form_warning_view.h"
+#include "chrome/browser/ui/views/repost_form_warning_view.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
@@ -13,6 +11,8 @@
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
 #include "views/controls/message_box_view.h"
 #include "views/window/window.h"
 
@@ -35,7 +35,7 @@
       : controller_(new RepostFormWarningController(tab_contents)),
         message_box_view_(NULL) {
   message_box_view_ = new MessageBoxView(
-      MessageBoxFlags::kIsConfirmMessageBox,
+      ui::MessageBoxFlags::kIsConfirmMessageBox,
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_HTTP_POST_WARNING)),
       std::wstring());
   controller_->Show(this);
@@ -52,10 +52,10 @@
 }
 
 std::wstring RepostFormWarningView::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  if (button == MessageBoxFlags::DIALOGBUTTON_OK)
+    ui::MessageBoxFlags::DialogButton button) const {
+  if (button == ui::MessageBoxFlags::DIALOGBUTTON_OK)
     return UTF16ToWide(l10n_util::GetStringUTF16(IDS_HTTP_POST_WARNING_RESEND));
-  if (button == MessageBoxFlags::DIALOGBUTTON_CANCEL)
+  if (button == ui::MessageBoxFlags::DIALOGBUTTON_CANCEL)
     return UTF16ToWide(l10n_util::GetStringUTF16(IDS_CANCEL));
   return std::wstring();
 }
diff --git a/chrome/browser/ui/views/repost_form_warning_view.h b/chrome/browser/ui/views/repost_form_warning_view.h
index 980eab0..97148be 100644
--- a/chrome/browser/ui/views/repost_form_warning_view.h
+++ b/chrome/browser/ui/views/repost_form_warning_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,8 +7,7 @@
 #pragma once
 
 #include "chrome/browser/tab_contents/constrained_window.h"
-#include "chrome/common/notification_registrar.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/window/dialog_delegate.h"
 
 class ConstrainedWindow;
diff --git a/chrome/browser/ui/views/restart_message_box.cc b/chrome/browser/ui/views/restart_message_box.cc
index 4e2804d..420c109 100644
--- a/chrome/browser/ui/views/restart_message_box.cc
+++ b/chrome/browser/ui/views/restart_message_box.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/restart_message_box.h"
+#include "chrome/browser/ui/views/restart_message_box.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/utf_string_conversions.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
 #include "views/controls/message_box_view.h"
 #include "views/window/window.h"
 
@@ -22,12 +22,12 @@
 }
 
 int RestartMessageBox::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK;
+  return ui::MessageBoxFlags::DIALOGBUTTON_OK;
 }
 
 std::wstring RestartMessageBox::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  DCHECK(button == MessageBoxFlags::DIALOGBUTTON_OK);
+    ui::MessageBoxFlags::DialogButton button) const {
+  DCHECK(button == ui::MessageBoxFlags::DIALOGBUTTON_OK);
   return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK));
 }
 
@@ -54,9 +54,10 @@
   const int kDialogWidth = 400;
   // Also deleted when the window closes.
   message_box_view_ = new MessageBoxView(
-      MessageBoxFlags::kFlagHasMessage | MessageBoxFlags::kFlagHasOKButton,
+      ui::MessageBoxFlags::kFlagHasMessage |
+          ui::MessageBoxFlags::kFlagHasOKButton,
       UTF16ToWide(
-          l10n_util::GetStringUTF16(IDS_OPTIONS_RESTART_REQUIRED)).c_str(),
+          l10n_util::GetStringUTF16(IDS_OPTIONS_RELAUNCH_REQUIRED)).c_str(),
       std::wstring(),
       kDialogWidth);
   views::Window::CreateChromeWindow(parent_window, gfx::Rect(), this)->Show();
diff --git a/chrome/browser/ui/views/restart_message_box.h b/chrome/browser/ui/views/restart_message_box.h
index cfa3da5..adb5806 100644
--- a/chrome/browser/ui/views/restart_message_box.h
+++ b/chrome/browser/ui/views/restart_message_box.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/window/dialog_delegate.h"
 
 class MessageBoxView;
diff --git a/chrome/browser/ui/views/sad_tab_view.cc b/chrome/browser/ui/views/sad_tab_view.cc
index 876f9ed..a5d2838 100644
--- a/chrome/browser/ui/views/sad_tab_view.cc
+++ b/chrome/browser/ui/views/sad_tab_view.cc
@@ -1,24 +1,24 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/sad_tab_view.h"
+#include "chrome/browser/ui/views/sad_tab_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/size.h"
-#include "gfx/skia_util.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/skia_util.h"
 
 static const int kSadTabOffset = -64;
 static const int kIconTitleSpacing = 20;
@@ -28,8 +28,12 @@
 static const SkColor kTitleColor = SK_ColorWHITE;
 static const SkColor kMessageColor = SK_ColorWHITE;
 static const SkColor kLinkColor = SK_ColorWHITE;
-static const SkColor kBackgroundColor = SkColorSetRGB(35, 48, 64);
-static const SkColor kBackgroundEndColor = SkColorSetRGB(35, 48, 64);
+static const SkColor kCrashBackgroundColor = SkColorSetRGB(35, 48, 64);
+static const SkColor kCrashBackgroundEndColor = SkColorSetRGB(35, 48, 64);
+// TODO(gspencer): update these colors when the UI team has picked
+// official versions.  See http://crosbug.com/10711.
+static const SkColor kKillBackgroundColor = SkColorSetRGB(57, 48, 88);
+static const SkColor kKillBackgroundEndColor = SkColorSetRGB(57, 48, 88);
 
 // Font size correction.
 #if defined(CROS_FONTS_USING_BCI)
@@ -48,12 +52,13 @@
 std::wstring SadTabView::message_;
 int SadTabView::title_width_;
 
-SadTabView::SadTabView(TabContents* tab_contents)
+SadTabView::SadTabView(TabContents* tab_contents, Kind kind)
     : tab_contents_(tab_contents),
-      learn_more_link_(NULL) {
+      learn_more_link_(NULL),
+      kind_(kind) {
   DCHECK(tab_contents);
 
-  InitClass();
+  InitClass(kind);
 
   if (tab_contents != NULL) {
     learn_more_link_ =
@@ -67,22 +72,26 @@
 
 void SadTabView::Paint(gfx::Canvas* canvas) {
   SkPaint paint;
-  SkSafeUnref(paint.setShader(gfx::CreateGradientShader(0, height(),
-                                                        kBackgroundColor,
-                                                        kBackgroundEndColor)));
+  SkSafeUnref(paint.setShader(
+      gfx::CreateGradientShader(
+          0,
+          height(),
+          kind_ == CRASHED ? kCrashBackgroundColor : kKillBackgroundColor,
+          kind_ == CRASHED ?
+            kCrashBackgroundEndColor : kKillBackgroundEndColor)));
   paint.setStyle(SkPaint::kFill_Style);
   canvas->AsCanvasSkia()->drawRectCoords(
       0, 0, SkIntToScalar(width()), SkIntToScalar(height()), paint);
 
   canvas->DrawBitmapInt(*sad_tab_bitmap_, icon_bounds_.x(), icon_bounds_.y());
 
-  canvas->DrawStringInt(title_, *title_font_, kTitleColor, title_bounds_.x(),
-                        title_bounds_.y(), title_bounds_.width(),
-                        title_bounds_.height(),
+  canvas->DrawStringInt(WideToUTF16Hack(title_), *title_font_, kTitleColor,
+                        title_bounds_.x(), title_bounds_.y(),
+                        title_bounds_.width(), title_bounds_.height(),
                         gfx::Canvas::TEXT_ALIGN_CENTER);
 
-  canvas->DrawStringInt(message_, *message_font_, kMessageColor,
-                        message_bounds_.x(), message_bounds_.y(),
+  canvas->DrawStringInt(WideToUTF16Hack(message_), *message_font_,
+                        kMessageColor, message_bounds_.x(), message_bounds_.y(),
                         message_bounds_.width(), message_bounds_.height(),
                         gfx::Canvas::MULTI_LINE);
 
@@ -124,7 +133,9 @@
 void SadTabView::LinkActivated(views::Link* source, int event_flags) {
   if (tab_contents_ != NULL && source == learn_more_link_) {
     GURL help_url =
-        google_util::AppendGoogleLocaleParam(GURL(chrome::kCrashReasonURL));
+        google_util::AppendGoogleLocaleParam(GURL(kind_ == CRASHED ?
+                                                  chrome::kCrashReasonURL :
+                                                  chrome::kKillReasonURL));
     WindowOpenDisposition disposition(CURRENT_TAB);
 #if defined(OS_CHROMEOS)
     if (tab_contents_->delegate() &&
@@ -139,7 +150,7 @@
 }
 
 // static
-void SadTabView::InitClass() {
+void SadTabView::InitClass(Kind kind) {
   static bool initialized = false;
   if (!initialized) {
     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
@@ -148,11 +159,14 @@
                                                         gfx::Font::BOLD));
     message_font_ = new gfx::Font(
         rb.GetFont(ResourceBundle::BaseFont).DeriveFont(kMessageFontSizeDelta));
-    sad_tab_bitmap_ = rb.GetBitmapNamed(IDR_SAD_TAB);
+    sad_tab_bitmap_ = rb.GetBitmapNamed(
+        kind == CRASHED ? IDR_SAD_TAB : IDR_KILLED_TAB);
 
-    title_ = UTF16ToWide(l10n_util::GetStringUTF16(IDS_SAD_TAB_TITLE));
+    title_ = UTF16ToWide(l10n_util::GetStringUTF16(
+        kind == CRASHED ? IDS_SAD_TAB_TITLE : IDS_KILLED_TAB_TITLE));
     title_width_ = title_font_->GetStringWidth(WideToUTF16Hack(title_));
-    message_ = UTF16ToWide(l10n_util::GetStringUTF16(IDS_SAD_TAB_MESSAGE));
+    message_ = UTF16ToWide(l10n_util::GetStringUTF16(
+        kind == CRASHED ? IDS_SAD_TAB_MESSAGE : IDS_KILLED_TAB_MESSAGE));
 
     initialized = true;
   }
diff --git a/chrome/browser/ui/views/sad_tab_view.h b/chrome/browser/ui/views/sad_tab_view.h
index 22c088a..284fedf 100644
--- a/chrome/browser/ui/views/sad_tab_view.h
+++ b/chrome/browser/ui/views/sad_tab_view.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "gfx/font.h"
+#include "ui/gfx/font.h"
 #include "views/controls/link.h"
 #include "views/view.h"
 
@@ -25,7 +25,12 @@
 class SadTabView : public views::View,
                    public views::LinkController {
  public:
-  explicit SadTabView(TabContents* tab_contents);
+  enum Kind {
+    CRASHED,  // The tab crashed.  Display the "Aw, Snap!" page.
+    KILLED    // The tab was killed.  Display the killed tab page.
+  };
+
+  explicit SadTabView(TabContents* tab_contents, Kind kind);
   virtual ~SadTabView() {}
 
   // Overridden from views::View:
@@ -36,7 +41,7 @@
   virtual void LinkActivated(views::Link* source, int event_flags);
 
  private:
-  static void InitClass();
+  static void InitClass(Kind kind);
 
   // Assorted resources for display.
   static SkBitmap* sad_tab_bitmap_;
@@ -56,6 +61,8 @@
   gfx::Rect message_bounds_;
   gfx::Rect link_bounds_;
 
+  Kind kind_;
+
   DISALLOW_COPY_AND_ASSIGN(SadTabView);
 };
 
diff --git a/chrome/browser/ui/views/select_file_dialog.cc b/chrome/browser/ui/views/select_file_dialog.cc
index 1ebf2e5..4f83231 100644
--- a/chrome/browser/ui/views/select_file_dialog.cc
+++ b/chrome/browser/ui/views/select_file_dialog.cc
@@ -1,28 +1,28 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 
-#include "app/l10n_util.h"
 #include "base/callback.h"
 #include "base/file_path.h"
 #include "base/json/json_reader.h"
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
+#include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/dom_ui/html_dialog_ui.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/shell_dialogs.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/views/browser_dialogs.h"
-#include "chrome/browser/views/html_dialog_view.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/html_dialog_view.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/window/non_client_view.h"
 #include "views/window/window.h"
 
@@ -108,8 +108,8 @@
     virtual bool IsDialogModal() const;
     virtual std::wstring GetDialogTitle() const;
     virtual GURL GetDialogContentURL() const;
-    virtual void GetDOMMessageHandlers(
-        std::vector<DOMMessageHandler*>* handlers) const;
+    virtual void GetWebUIMessageHandlers(
+        std::vector<WebUIMessageHandler*>* handlers) const;
     virtual void GetDialogSize(gfx::Size* size) const;
     virtual std::string GetDialogArgs() const;
     virtual void OnDialogClosed(const std::string& json_retval);
@@ -123,11 +123,11 @@
     DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegate);
   };
 
-  class FileBrowseDelegateHandler : public DOMMessageHandler {
+  class FileBrowseDelegateHandler : public WebUIMessageHandler {
    public:
     explicit FileBrowseDelegateHandler(FileBrowseDelegate* delegate);
 
-    // DOMMessageHandler implementation.
+    // WebUIMessageHandler implementation.
     virtual void RegisterMessages();
 
     // Callback for the "setDialogTitle" message.
@@ -263,8 +263,12 @@
         std::string path_string;
         if (dict->HasKey(kKeyNamePath) &&
             dict->GetString(kKeyNamePath, &path_string)) {
-          FilePath path = FilePath::FromWStringHack(UTF8ToWide(path_string));
-
+#if defined(OS_WIN)
+          FilePath path(base::SysUTF8ToWide(path_string));
+#else
+          FilePath path(
+              base::SysWideToNativeMB(base::SysUTF8ToWide(path_string)));
+#endif
           listener_->FileSelected(path, kSaveCompletePageIndex,
                                   delegate->params_);
           notification_fired = true;
@@ -280,8 +284,13 @@
             std::string path_string;
             if (paths_value->GetString(i, &path_string) &&
                 !path_string.empty()) {
-              paths.push_back(FilePath::FromWStringHack(
-                  UTF8ToWide(path_string)));
+#if defined(OS_WIN)
+              FilePath path(base::SysUTF8ToWide(path_string));
+#else
+              FilePath path(
+                  base::SysWideToNativeMB(base::SysUTF8ToWide(path_string)));
+#endif
+              paths.push_back(path);
             }
           }
 
@@ -305,9 +314,9 @@
 void SelectFileDialogImpl::OpenHtmlDialog(
     gfx::NativeWindow owning_window,
     FileBrowseDelegate* file_browse_delegate) {
-  browser::ShowHtmlDialogView(owning_window,
-                              ProfileManager::GetDefaultProfile(),
-                              file_browse_delegate);
+  browser::ShowHtmlDialog(owning_window,
+                          ProfileManager::GetDefaultProfile(),
+                          file_browse_delegate);
 }
 
 SelectFileDialogImpl::FileBrowseDelegate::FileBrowseDelegate(
@@ -351,8 +360,8 @@
   return GURL(url_string);
 }
 
-void SelectFileDialogImpl::FileBrowseDelegate::GetDOMMessageHandlers(
-    std::vector<DOMMessageHandler*>* handlers) const {
+void SelectFileDialogImpl::FileBrowseDelegate::GetWebUIMessageHandlers(
+    std::vector<WebUIMessageHandler*>* handlers) const {
   handlers->push_back(new FileBrowseDelegateHandler(
       const_cast<FileBrowseDelegate*>(this)));
   return;
@@ -365,16 +374,16 @@
 
 std::string SelectFileDialogImpl::FileBrowseDelegate::GetDialogArgs() const {
   // SelectFile inputs as json.
-  //  {
-  //    "type"            : "open",   // (or "open_multiple", "save", "folder"
-  //    "all_files"       : true,
-  //    "file_types"      : {
-  //                          "exts" : [ ["htm", "html"], ["txt"] ],
-  //                          "desc" : [ "HTML files", "Text files" ],
-  //                        },
-  //    "file_type_index" : 1,    // 1-based file type index.
-  //  }
-  //  See browser/shell_dialogs.h for more details.
+  //   {
+  //     "type"            : "open",   // (or "open_multiple", "save", "folder"
+  //     "all_files"       : true,
+  //     "file_types"      : {
+  //                           "exts" : [ ["htm", "html"], ["txt"] ],
+  //                           "desc" : [ "HTML files", "Text files" ],
+  //                         },
+  //     "file_type_index" : 1,    // 1-based file type index.
+  //   }
+  // See browser/ui/shell_dialogs.h for more details.
 
   std::string type_string;
   switch (type_) {
@@ -460,7 +469,7 @@
 }
 
 void SelectFileDialogImpl::FileBrowseDelegateHandler::RegisterMessages() {
-  dom_ui_->RegisterMessageCallback("setDialogTitle",
+  web_ui_->RegisterMessageCallback("setDialogTitle",
       NewCallback(this, &FileBrowseDelegateHandler::HandleSetDialogTitle));
 }
 
@@ -477,7 +486,7 @@
     // its title.
     // TODO(xiyuan): Change this when the infrastructure is improved.
     HtmlDialogUIDelegate** delegate = HtmlDialogUI::GetPropertyAccessor().
-        GetProperty(dom_ui_->tab_contents()->property_bag());
+        GetProperty(web_ui_->tab_contents()->property_bag());
     HtmlDialogView* containing_view = static_cast<HtmlDialogView*>(*delegate);
     DCHECK(containing_view);
 
diff --git a/chrome/browser/ui/views/shell_dialogs_win.cc b/chrome/browser/ui/views/shell_dialogs_win.cc
index f1c59b4..28fd588 100644
--- a/chrome/browser/ui/views/shell_dialogs_win.cc
+++ b/chrome/browser/ui/views/shell_dialogs_win.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 
 #include <windows.h>
 #include <commdlg.h>
@@ -11,7 +11,7 @@
 #include <algorithm>
 #include <set>
 
-#include "app/l10n_util.h"
+#include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "base/scoped_comptr_win.h"
@@ -21,9 +21,10 @@
 #include "base/win/registry.h"
 #include "base/win/windows_version.h"
 #include "chrome/browser/browser_thread.h"
-#include "gfx/font.h"
 #include "grit/app_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/font.h"
 
 // This function takes the output of a SaveAs dialog: a filename, a filter and
 // the extension originally suggested to the user (shown in the dialog box) and
@@ -75,9 +76,9 @@
   DCHECK(reg_description);
   base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
   std::wstring reg_app;
-  if (reg_ext.ReadValue(NULL, &reg_app) && !reg_app.empty()) {
+  if (reg_ext.ReadValue(NULL, &reg_app) == ERROR_SUCCESS && !reg_app.empty()) {
     base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
-    if (reg_link.ReadValue(NULL, reg_description))
+    if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
       return true;
   }
   return false;
@@ -348,12 +349,11 @@
 bool SaveFileAs(HWND owner,
                 const std::wstring& suggested_name,
                 std::wstring* final_name) {
-  std::wstring file_ext = file_util::GetFileExtensionFromPath(suggested_name);
-  file_ext.insert(0, L"*.");
+  std::wstring file_ext = FilePath(suggested_name).Extension().insert(0, L"*");
   std::wstring filter = FormatFilterForExtensions(
-    std::vector<std::wstring>(1, file_ext),
-    std::vector<std::wstring>(),
-    true);
+      std::vector<std::wstring>(1, file_ext),
+      std::vector<std::wstring>(),
+      true);
   unsigned index = 1;
   return SaveFileAsWithFilter(owner,
                               suggested_name,
@@ -698,13 +698,12 @@
                                     params.run_state.owner,
                                     &path);
   } else if (params.type == SELECT_SAVEAS_FILE) {
-    std::wstring path_as_wstring = path.ToWStringHack();
+    std::wstring path_as_wstring = path.value();
     success = SaveFileAsWithFilter(params.run_state.owner,
-        params.default_path.ToWStringHack(), filter,
+        params.default_path.value(), filter,
         params.default_extension, false, &filter_index, &path_as_wstring);
-    if (success) {
-      path = FilePath::FromWStringHack(path_as_wstring);
-    }
+    if (success)
+      path = FilePath(path_as_wstring);
     DisableOwner(params.run_state.owner);
   } else if (params.type == SELECT_OPEN_FILE) {
     success = RunOpenFileDialog(params.title, filter,
diff --git a/chrome/browser/ui/views/shell_dialogs_win_unittest.cc b/chrome/browser/ui/views/shell_dialogs_win_unittest.cc
index 0c2cad5..02fd19b 100644
--- a/chrome/browser/ui/views/shell_dialogs_win_unittest.cc
+++ b/chrome/browser/ui/views/shell_dialogs_win_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(ShellDialogsWin, AppendExtensionIfNeeded) {
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector_win.cc b/chrome/browser/ui/views/ssl_client_certificate_selector_win.cc
index 45bb28f..35a5ee1 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector_win.cc
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector_win.cc
@@ -8,16 +8,15 @@
 #include <cryptuiapi.h>
 #pragma comment(lib, "cryptui.lib")
 
-#include "app/l10n_util.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/ssl/ssl_client_auth_handler.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/ui/browser.h"
 #include "grit/generated_resources.h"
 #include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace browser {
 
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index a684464..022ea11 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -1,20 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/status_bubble_views.h"
+#include "chrome/browser/ui/views/status_bubble_views.h"
 
 #include <algorithm>
 
-#include "app/resource_bundle.h"
-#include "app/text_elider.h"
 #include "base/i18n/rtl.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/point.h"
 #include "googleurl/src/gurl.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -24,6 +20,10 @@
 #include "third_party/skia/include/core/SkRect.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/linear_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/point.h"
 #include "views/controls/label.h"
 #include "views/controls/scrollbar/native_scroll_bar.h"
 #include "views/screen.h"
@@ -73,7 +73,7 @@
                                       public ui::AnimationDelegate {
  public:
   StatusView(StatusBubble* status_bubble, views::Widget* popup,
-             ThemeProvider* theme_provider)
+             ui::ThemeProvider* theme_provider)
       : ALLOW_THIS_IN_INITIALIZER_LIST(ui::LinearAnimation(kFramerate, this)),
         stage_(BUBBLE_HIDDEN),
         style_(STYLE_STANDARD),
@@ -174,7 +174,7 @@
   double opacity_end_;
 
   // Holds the theme provider of the frame that created us.
-  ThemeProvider* theme_provider_;
+  ui::ThemeProvider* theme_provider_;
 };
 
 void StatusBubbleViews::StatusView::SetText(const string16& text,
@@ -437,7 +437,7 @@
                         kShadowThickness,
                         std::max(0, text_width),
                         std::max(0, text_height));
-  body_bounds.set_x(MirroredLeftPointForRect(body_bounds));
+  body_bounds.set_x(GetMirroredXForRect(body_bounds));
   SkColor text_color =
       theme_provider_->GetColor(BrowserThemeProvider::COLOR_TAB_TEXT);
 
@@ -447,7 +447,7 @@
       (SkColorGetR(text_color) + SkColorGetR(toolbar_color)) / 2,
       (SkColorGetG(text_color) + SkColorGetR(toolbar_color)) / 2,
       (SkColorGetB(text_color) + SkColorGetR(toolbar_color)) / 2);
-  canvas->DrawStringInt(UTF16ToWide(text_),
+  canvas->DrawStringInt(text_,
                         views::Label::font(),
                         text_color,
                         body_bounds.x(),
@@ -593,7 +593,7 @@
 
 void StatusBubbleViews::SetBounds(int x, int y, int w, int h) {
   original_position_.SetPoint(x, y);
-  position_.SetPoint(base_view_->MirroredXWithWidthInsideView(x, w), y);
+  position_.SetPoint(base_view_->GetMirroredXWithWidthInView(x, w), y);
   size_.SetSize(w, h);
   Reposition();
 }
@@ -648,7 +648,7 @@
   popup_->GetBounds(&popup_bounds, true);
   int text_width = static_cast<int>(popup_bounds.width() -
       (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1);
-  url_text_ = gfx::ElideUrl(url, view_->Label::font(),
+  url_text_ = ui::ElideUrl(url, view_->Label::font(),
       text_width, UTF16ToWideHack(languages));
 
   std::wstring original_url_text =
@@ -707,7 +707,7 @@
   gfx::Point top_left;
   views::View::ConvertPointToScreen(base_view_, &top_left);
   // Border included.
-  int window_width = base_view_->GetLocalBounds(true).width();
+  int window_width = base_view_->GetLocalBounds().width();
 
   // Get the cursor position relative to the popup.
   gfx::Point relative_location = location;
@@ -803,7 +803,7 @@
   gfx::Rect popup_bounds;
   popup_->GetBounds(&popup_bounds, true);
   int max_status_bubble_width = GetMaxStatusBubbleWidth();
-  url_text_ = gfx::ElideUrl(url_, view_->Label::font(),
+  url_text_ = ui::ElideUrl(url_, view_->Label::font(),
       max_status_bubble_width, UTF16ToWideHack(languages_));
   int expanded_bubble_width =std::max(GetStandardStatusBubbleWidth(),
       std::min(view_->Label::font().GetStringWidth(url_text_) +
diff --git a/chrome/browser/ui/views/status_bubble_views.h b/chrome/browser/ui/views/status_bubble_views.h
index 456eab7..eeb83f5 100644
--- a/chrome/browser/ui/views/status_bubble_views.h
+++ b/chrome/browser/ui/views/status_bubble_views.h
@@ -12,7 +12,7 @@
 #include "base/task.h"
 #include "chrome/browser/ui/status_bubble.h"
 #include "googleurl/src/gurl.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class GURL;
 namespace gfx {
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.cc b/chrome/browser/ui/views/status_icons/status_icon_win.cc
index 5545560..19d182a 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_win.cc
+++ b/chrome/browser/ui/views/status_icons/status_icon_win.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/status_icons/status_icon_win.h"
+#include "chrome/browser/ui/views/status_icons/status_icon_win.h"
 
 #include "base/sys_string_conversions.h"
-#include "gfx/icon_util.h"
-#include "gfx/point.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/icon_util.h"
+#include "ui/gfx/point.h"
 #include "views/controls/menu/menu_2.h"
 
 StatusIconWin::StatusIconWin(UINT id, HWND window, UINT message)
@@ -19,7 +19,10 @@
   icon_data.uFlags = NIF_MESSAGE;
   icon_data.uCallbackMessage = message_id_;
   BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
-  DCHECK(result);
+  // This can happen if the explorer process isn't running when we try to
+  // create the icon for some reason (for example, at startup).
+  if (!result)
+    LOG(WARNING) << "Unable to create status tray icon.";
 }
 
 StatusIconWin::~StatusIconWin() {
@@ -37,7 +40,27 @@
   icon_.Set(IconUtil::CreateHICONFromSkBitmap(image));
   icon_data.hIcon = icon_.Get();
   BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
-  DCHECK(result);
+  if (!result)
+    LOG(WARNING) << "Error setting status tray icon image";
+}
+
+void StatusIconWin::ResetIcon() {
+  NOTIFYICONDATA icon_data;
+  InitIconData(&icon_data);
+  // Delete any previously existing icon.
+  Shell_NotifyIcon(NIM_DELETE, &icon_data);
+  InitIconData(&icon_data);
+  icon_data.uFlags = NIF_MESSAGE;
+  icon_data.uCallbackMessage = message_id_;
+  icon_data.hIcon = icon_.Get();
+  // If we have an image, then set the NIF_ICON flag, which tells
+  // Shell_NotifyIcon() to set the image for the status icon it creates.
+  if (icon_data.hIcon)
+    icon_data.uFlags |= NIF_ICON;
+  // Re-add our icon.
+  BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
+  if (!result)
+    LOG(WARNING) << "Unable to re-create status tray icon.";
 }
 
 void StatusIconWin::SetPressedImage(const SkBitmap& image) {
@@ -52,7 +75,8 @@
   icon_data.uFlags = NIF_TIP;
   wcscpy_s(icon_data.szTip, tool_tip.c_str());
   BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
-  DCHECK(result);
+  if (!result)
+    LOG(WARNING) << "Unable to set tooltip for status tray icon";
 }
 
 void StatusIconWin::InitIconData(NOTIFYICONDATA* icon_data) {
@@ -61,7 +85,7 @@
   icon_data->uID = icon_id_;
 }
 
-void StatusIconWin::UpdatePlatformContextMenu(menus::MenuModel* menu) {
+void StatusIconWin::UpdatePlatformContextMenu(ui::MenuModel* menu) {
   // If no items are passed, blow away our context menu.
   if (!menu) {
     context_menu_.reset();
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.h b/chrome/browser/ui/views/status_icons/status_icon_win.h
index 6bbda23..a4582ba 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_win.h
+++ b/chrome/browser/ui/views/status_icons/status_icon_win.h
@@ -37,9 +37,12 @@
   // otherwise displays the context menu if there is one.
   void HandleClickEvent(int x, int y, bool left_button_click);
 
+  // Re-creates the status tray icon now after the taskbar has been created.
+  void ResetIcon();
+
  protected:
   // Overridden from StatusIcon.
-  virtual void UpdatePlatformContextMenu(menus::MenuModel* menu);
+  virtual void UpdatePlatformContextMenu(ui::MenuModel* menu);
 
  private:
   void InitIconData(NOTIFYICONDATA* icon_data);
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc
index 53f80f9..2fa679e 100644
--- a/chrome/browser/ui/views/status_icons/status_tray_win.cc
+++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/status_icons/status_tray_win.h"
+#include "chrome/browser/ui/views/status_icons/status_tray_win.h"
 
-#include "app/win/hwnd_util.h"
-#include "chrome/browser/views/status_icons/status_icon_win.h"
+#include "chrome/browser/ui/views/status_icons/status_icon_win.h"
 #include "chrome/common/chrome_constants.h"
+#include "ui/base/win/hwnd_util.h"
 
 static const UINT kStatusIconMessage = WM_APP + 1;
 
@@ -22,10 +22,17 @@
   ATOM clazz = RegisterClassEx(&wc);
   DCHECK(clazz);
 
-  // Create an offscreen window for handling messages for the status icons.
+  // If the taskbar is re-created after we start up, we have to rebuild all of
+  // our icons.
+  taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));
+
+  // Create an offscreen window for handling messages for the status icons. We
+  // create a hidden WS_POPUP window instead of an HWND_MESSAGE window, because
+  // only top-level windows such as popups can receive broadcast messages like
+  // "TaskbarCreated".
   window_ = CreateWindow(chrome::kStatusTrayWindowClass,
-                         0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0);
-  app::win::SetWindowUserData(window_, this);
+                         0, WS_POPUP, 0, 0, 0, 0, 0, 0, hinst, 0);
+  ui::SetWindowUserData(window_, this);
 }
 
 LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd,
@@ -34,34 +41,44 @@
                                               LPARAM lparam) {
   StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>(
       GetWindowLongPtr(hwnd, GWLP_USERDATA));
-  return msg_wnd->WndProc(hwnd, message, wparam, lparam);
+  if (msg_wnd)
+    return msg_wnd->WndProc(hwnd, message, wparam, lparam);
+  else
+    return ::DefWindowProc(hwnd, message, wparam, lparam);
 }
 
 LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd,
                                         UINT message,
                                         WPARAM wparam,
                                         LPARAM lparam) {
-  switch (message) {
-    case kStatusIconMessage:
-      switch (lparam) {
-        case WM_LBUTTONDOWN:
-        case WM_RBUTTONDOWN:
-        case WM_CONTEXTMENU:
-          // Walk our icons, find which one was clicked on, and invoke its
-          // HandleClickEvent() method.
-          for (StatusIconList::const_iterator iter = status_icons().begin();
-               iter != status_icons().end();
-               ++iter) {
-            StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
-            if (win_icon->icon_id() == wparam) {
-              POINT p;
-              GetCursorPos(&p);
-              win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN);
-            }
+  if (message == taskbar_created_message_) {
+    // We need to reset all of our icons because the taskbar went away.
+    for (StatusIconList::const_iterator iter = status_icons().begin();
+         iter != status_icons().end();
+         ++iter) {
+      StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
+      win_icon->ResetIcon();
+    }
+    return TRUE;
+  } else if (message == kStatusIconMessage) {
+    switch (lparam) {
+      case WM_LBUTTONDOWN:
+      case WM_RBUTTONDOWN:
+      case WM_CONTEXTMENU:
+        // Walk our icons, find which one was clicked on, and invoke its
+        // HandleClickEvent() method.
+        for (StatusIconList::const_iterator iter = status_icons().begin();
+             iter != status_icons().end();
+             ++iter) {
+          StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
+          if (win_icon->icon_id() == wparam) {
+            POINT p;
+            GetCursorPos(&p);
+            win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN);
           }
-          return TRUE;
-      }
-      break;
+        }
+        return TRUE;
+    }
   }
   return ::DefWindowProc(hwnd, message, wparam, lparam);
 }
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.h b/chrome/browser/ui/views/status_icons/status_tray_win.h
index c6d3c52..fe4f87b 100644
--- a/chrome/browser/ui/views/status_icons/status_tray_win.h
+++ b/chrome/browser/ui/views/status_icons/status_tray_win.h
@@ -33,9 +33,14 @@
 
   // The unique icon ID we will assign to the next icon.
   UINT next_icon_id_;
+
   // The window used for processing events.
   HWND window_;
 
+  // The message ID of the "TaskbarCreated" message, sent to us when we need to
+  // reset our status icons.
+  UINT taskbar_created_message_;
+
   DISALLOW_COPY_AND_ASSIGN(StatusTrayWin);
 };
 
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
index c824755..21a1da1 100644
--- a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
+++ b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/menus/simple_menu_model.h"
-#include "app/resource_bundle.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/views/status_icons/status_icon_win.h"
-#include "chrome/browser/views/status_icons/status_tray_win.h"
+#include "chrome/browser/ui/views/status_icons/status_icon_win.h"
+#include "chrome/browser/ui/views/status_icons/status_tray_win.h"
 #include "grit/browser_resources.h"
 #include "grit/theme_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/resource/resource_bundle.h"
 
 class SkBitmap;
 
@@ -35,7 +35,7 @@
   icon->SetImage(*bitmap);
   icon->SetPressedImage(*bitmap);
   icon->SetToolTip(ASCIIToUTF16("tool tip"));
-  menus::SimpleMenuModel* menu = new menus::SimpleMenuModel(NULL);
+  ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(NULL);
   menu->AddItem(0, L"foo");
   icon->SetContextMenu(menu);
 }
diff --git a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.cc b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.cc
index 82c0b26..2013a65 100644
--- a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.cc
+++ b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h"
 
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/tab_contents/interstitial_page.h"
diff --git a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h
index a863e2b..122b3d3 100644
--- a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h
+++ b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include <gtk/gtk.h>
 
-#include "chrome/browser/views/tab_contents/native_tab_contents_container.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container.h"
 #include "views/controls/native/native_view_host.h"
 
 class NativeTabContentsContainerGtk : public NativeTabContentsContainer,
diff --git a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.cc b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.cc
index 99c37a9..ae94dd2 100644
--- a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.cc
+++ b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/native_tab_contents_container_win.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h"
 
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
 #include "chrome/browser/tab_contents/interstitial_page.h"
diff --git a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h
index 8d12f0e..a390b49 100644
--- a/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h
+++ b/chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_WIN_H_
 #pragma once
 
-#include "chrome/browser/views/tab_contents/native_tab_contents_container.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container.h"
 #include "views/controls/native/native_view_host.h"
 
 class NativeTabContentsContainerWin : public NativeTabContentsContainer,
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
index 75675cd..bedf718 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
+#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
 
-#include "app/keyboard_codes.h"
 #include "base/logging.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "grit/generated_resources.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "views/accelerator.h"
 #include "views/controls/menu/menu_2.h"
 
@@ -62,33 +62,33 @@
 
 bool RenderViewContextMenuViews::GetAcceleratorForCommandId(
     int command_id,
-    menus::Accelerator* accel) {
+    ui::Accelerator* accel) {
   // There are no formally defined accelerators we can query so we assume
   // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
   switch (command_id) {
     case IDC_CONTENT_CONTEXT_UNDO:
-      *accel = views::Accelerator(app::VKEY_Z, false, true, false);
+      *accel = views::Accelerator(ui::VKEY_Z, false, true, false);
       return true;
 
     case IDC_CONTENT_CONTEXT_REDO:
       // TODO(jcampan): should it be Ctrl-Y?
-      *accel = views::Accelerator(app::VKEY_Z, true, true, false);
+      *accel = views::Accelerator(ui::VKEY_Z, true, true, false);
       return true;
 
     case IDC_CONTENT_CONTEXT_CUT:
-      *accel = views::Accelerator(app::VKEY_X, false, true, false);
+      *accel = views::Accelerator(ui::VKEY_X, false, true, false);
       return true;
 
     case IDC_CONTENT_CONTEXT_COPY:
-      *accel = views::Accelerator(app::VKEY_C, false, true, false);
+      *accel = views::Accelerator(ui::VKEY_C, false, true, false);
       return true;
 
     case IDC_CONTENT_CONTEXT_PASTE:
-      *accel = views::Accelerator(app::VKEY_V, false, true, false);
+      *accel = views::Accelerator(ui::VKEY_V, false, true, false);
       return true;
 
     case IDC_CONTENT_CONTEXT_SELECTALL:
-      *accel = views::Accelerator(app::VKEY_A, false, true, false);
+      *accel = views::Accelerator(ui::VKEY_A, false, true, false);
       return true;
 
     default:
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
index 266e762..af13bd0 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
@@ -36,7 +36,7 @@
   // RenderViewContextMenu implementation --------------------------------------
   virtual void PlatformInit();
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
  private:
   // The context menu itself and its contents.
   scoped_ptr<views::Menu2> menu_;
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_container.cc b/chrome/browser/ui/views/tab_contents/tab_contents_container.cc
index 47ed229..440cfee 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_container.cc
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_container.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/tab_contents_container.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
 
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_widget_host_view.h"
@@ -13,75 +13,15 @@
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
 
-#if defined(TOUCH_UI)
-#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h"
-#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"
-#include "views/border.h"
-#include "views/fill_layout.h"
-#endif
 
 ////////////////////////////////////////////////////////////////////////////////
 // TabContentsContainer, public:
 
-TabContentsContainer::TabContentsContainer()
-    : native_container_(NULL),
-      tab_contents_(NULL),
-      reserved_area_delegate_(NULL) {
-  SetID(VIEW_ID_TAB_CONTAINER);
-}
-
 TabContentsContainer::~TabContentsContainer() {
   if (tab_contents_)
     RemoveObservers();
 }
 
-void TabContentsContainer::ChangeTabContents(TabContents* contents) {
-  if (tab_contents_) {
-#if !defined(TOUCH_UI)
-    native_container_->DetachContents(tab_contents_);
-#else
-    views::View *v = static_cast<TabContentsViewViews*>(tab_contents_->view());
-    RemoveChildView(v);
-#endif
-    tab_contents_->WasHidden();
-    RemoveObservers();
-  }
-#if !defined(TOUCH_UI)
-  TabContents* old_contents = tab_contents_;
-#endif
-  tab_contents_ = contents;
-  // When detaching the last tab of the browser ChangeTabContents is invoked
-  // with NULL. Don't attempt to do anything in that case.
-  if (tab_contents_) {
-#if defined(TOUCH_UI)
-    views::View *v = static_cast<TabContentsViewViews*>(contents->view());
-    // Guard against re-adding ourselves, which happens because the NULL
-    // value is ignored by the pre-existing if() above.
-    if (v->GetParent() != this) {
-      AddChildView(v);
-      SetLayoutManager(new views::FillLayout());
-      Layout();
-    }
-#else
-    RenderWidgetHostViewChanged(
-        old_contents ? old_contents->GetRenderWidgetHostView() : NULL,
-        tab_contents_->GetRenderWidgetHostView());
-    native_container_->AttachContents(tab_contents_);
-#endif
-    AddObservers();
-  }
-}
-
-void TabContentsContainer::TabContentsFocused(TabContents* tab_contents) {
-  if (native_container_)
-    native_container_->TabContentsFocused(tab_contents);
-}
-
-void TabContentsContainer::SetFastResize(bool fast_resize) {
-  if (native_container_)
-    native_container_->SetFastResize(fast_resize);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // TabContentsContainer, NotificationObserver implementation:
 
@@ -103,36 +43,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TabContentsContainer, View overrides:
 
-void TabContentsContainer::Layout() {
-#if defined(TOUCH_UI)
-  views::View::Layout();
-#else
-  if (native_container_) {
-    if (reserved_area_delegate_)
-      reserved_area_delegate_->UpdateReservedContentsRect(this);
-    native_container_->GetView()->SetBounds(0, 0, width(), height());
-    native_container_->GetView()->Layout();
-  }
-#endif
-}
-
 AccessibilityTypes::Role TabContentsContainer::GetAccessibleRole() {
   return AccessibilityTypes::ROLE_WINDOW;
 }
 
-void TabContentsContainer::ViewHierarchyChanged(bool is_add,
-                                                views::View* parent,
-                                                views::View* child) {
-#if defined(TOUCH_UI)
-  views::View::ViewHierarchyChanged(is_add, parent, child);
-#else
-  if (is_add && child == this) {
-    native_container_ = NativeTabContentsContainer::CreateNativeContainer(this);
-    AddChildView(native_container_->GetView());
-  }
-#endif
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // TabContentsContainer, private:
 
@@ -153,19 +67,6 @@
   registrar_.RemoveAll();
 }
 
-void TabContentsContainer::RenderViewHostChanged(RenderViewHost* old_host,
-                                                 RenderViewHost* new_host) {
-#if defined(TOUCH_UI)
-  NOTIMPLEMENTED();  // TODO(anicolao)
-#else
-  if (new_host) {
-    RenderWidgetHostViewChanged(
-        old_host ? old_host->view() : NULL, new_host->view());
-  }
-  native_container_->RenderViewHostChanged(old_host, new_host);
-#endif
-}
-
 void TabContentsContainer::TabContentsDestroyed(TabContents* contents) {
   // Sometimes, a TabContents is destroyed before we know about it. This allows
   // us to clean up our state in case this happens.
@@ -174,12 +75,7 @@
 }
 
 void TabContentsContainer::RenderWidgetHostViewChanged(
-    RenderWidgetHostView* old_view, RenderWidgetHostView* new_view) {
-  // Carry over the reserved rect, if possible.
-  if (old_view && new_view) {
-    new_view->set_reserved_contents_rect(old_view->reserved_contents_rect());
-  } else {
-    if (reserved_area_delegate_)
-      reserved_area_delegate_->UpdateReservedContentsRect(this);
-  }
+    RenderWidgetHostView* new_view) {
+  if (new_view)
+    new_view->set_reserved_contents_rect(cached_reserved_rect_);
 }
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_container.h b/chrome/browser/ui/views/tab_contents/tab_contents_container.h
index 9928f5b..1777479 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_container.h
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_container.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,101 +6,20 @@
 #define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
 #pragma once
 
-#include "chrome/browser/views/tab_contents/native_tab_contents_container.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "views/view.h"
-
-class NativeTabContentsContainer;
-class RenderViewHost;
-class RenderWidgetHostView;
-class TabContents;
-
-class TabContentsContainer : public views::View,
-                             public NotificationObserver {
- public:
-  // Interface to request the reserved contents area updates.
-  class ReservedAreaDelegate {
-   public:
-    // Notifies that |source|'s reserved contents area should be updated.
-    // Reserved contents area is a rect in tab contents view coordinates where
-    // contents should not be rendered (to display the resize corner, sidebar
-    // mini tabs or any other UI elements overlaying this container).
-    virtual void UpdateReservedContentsRect(
-        const TabContentsContainer* source) = 0;
-   protected:
-    virtual ~ReservedAreaDelegate() {}
-  };
-
-  TabContentsContainer();
-  virtual ~TabContentsContainer();
-
-  // Changes the TabContents associated with this view.
-  void ChangeTabContents(TabContents* contents);
-
-  View* GetFocusView() { return native_container_->GetView(); }
-
-  // Accessor for |tab_contents_|.
-  TabContents* tab_contents() const { return tab_contents_; }
-
-  // Called by the BrowserView to notify that |tab_contents| got the focus.
-  void TabContentsFocused(TabContents* tab_contents);
-
-  // Tells the container to update less frequently during resizing operations
-  // so performance is better.
-  void SetFastResize(bool fast_resize);
-
-  void set_reserved_area_delegate(ReservedAreaDelegate* delegate) {
-    reserved_area_delegate_ = delegate;
-  }
-
-  // Overridden from NotificationObserver:
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Overridden from views::View:
-  virtual void Layout();
-  virtual AccessibilityTypes::Role GetAccessibleRole();
-
- protected:
-  // Overridden from views::View:
-  virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
-                                    views::View* child);
-
- private:
-  // Add or remove observers for events that we care about.
-  void AddObservers();
-  void RemoveObservers();
-
-  // Called when the RenderViewHost of the hosted TabContents has changed, e.g.
-  // to show an interstitial page.
-  void RenderViewHostChanged(RenderViewHost* old_host,
-                             RenderViewHost* new_host);
-
-  // Called when a TabContents is destroyed. This gives us a chance to clean
-  // up our internal state if the TabContents is somehow destroyed before we
-  // get notified.
-  void TabContentsDestroyed(TabContents* contents);
-
-  // Called when the RenderWidgetHostView of the hosted TabContents has changed.
-  void RenderWidgetHostViewChanged(RenderWidgetHostView* old_view,
-                                   RenderWidgetHostView* new_view);
-
-  // An instance of a NativeTabContentsContainer object that holds the native
-  // view handle associated with the attached TabContents.
-  NativeTabContentsContainer* native_container_;
-
-  // The attached TabContents.
-  TabContents* tab_contents_;
-
-  // Handles registering for our notifications.
-  NotificationRegistrar registrar_;
-
-  // Delegate for enquiring reserved contents area. Not owned by us.
-  ReservedAreaDelegate* reserved_area_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(TabContentsContainer);
-};
+// There are two strategies implemented for embedding the actual tab contents
+// which are to use a views implementaiton all the way down, or to use a
+// NativeViewHost to encapsulate a native widget that then contains another
+// views heirarchy rooted at that widget. The TOUCH_UI is currently the only UI
+// that uses the pure views approach.
+//
+// Common code to the two approaches is in tab_contents_container.cc, while
+// views-only code is in tab_contents_container_views.cc and native-widget only
+// code is in tab_contents_container_native.cc. The headers are distinct
+// because the classes have different member variables.
+#if defined(TOUCH_UI)
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container_views.h"
+#else
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container_native.h"
+#endif
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_container_native.cc b/chrome/browser/ui/views/tab_contents/tab_contents_container_native.cc
new file mode 100644
index 0000000..5c62682
--- /dev/null
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_container_native.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
+
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/interstitial_page.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+
+// Some of this class is implemented in tab_contents_container.cc, where
+// the implementation doesn't vary between a pure views approach and a
+// native view host approach. See the header file for details.
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsContainer, public:
+
+TabContentsContainer::TabContentsContainer()
+    : native_container_(NULL),
+      tab_contents_(NULL) {
+  SetID(VIEW_ID_TAB_CONTAINER);
+}
+
+void TabContentsContainer::SetReservedContentsRect(
+    const gfx::Rect& reserved_rect) {
+  cached_reserved_rect_ = reserved_rect;
+  if (tab_contents_ && tab_contents_->GetRenderWidgetHostView()) {
+    tab_contents_->GetRenderWidgetHostView()->set_reserved_contents_rect(
+        reserved_rect);
+  }
+}
+
+void TabContentsContainer::ChangeTabContents(TabContents* contents) {
+  if (tab_contents_) {
+    native_container_->DetachContents(tab_contents_);
+    tab_contents_->WasHidden();
+    RemoveObservers();
+  }
+  tab_contents_ = contents;
+  // When detaching the last tab of the browser ChangeTabContents is invoked
+  // with NULL. Don't attempt to do anything in that case.
+  if (tab_contents_) {
+    RenderWidgetHostViewChanged(tab_contents_->GetRenderWidgetHostView());
+    native_container_->AttachContents(tab_contents_);
+    AddObservers();
+  }
+}
+
+void TabContentsContainer::TabContentsFocused(TabContents* tab_contents) {
+  native_container_->TabContentsFocused(tab_contents);
+}
+
+void TabContentsContainer::SetFastResize(bool fast_resize) {
+  native_container_->SetFastResize(fast_resize);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsContainer, View overrides:
+
+void TabContentsContainer::Layout() {
+  if (native_container_) {
+    native_container_->GetView()->SetBounds(0, 0, width(), height());
+    native_container_->GetView()->Layout();
+  }
+}
+
+void TabContentsContainer::ViewHierarchyChanged(bool is_add,
+                                                views::View* parent,
+                                                views::View* child) {
+  if (is_add && child == this) {
+    native_container_ = NativeTabContentsContainer::CreateNativeContainer(this);
+    AddChildView(native_container_->GetView());
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsContainer, private:
+
+void TabContentsContainer::RenderViewHostChanged(RenderViewHost* old_host,
+                                                 RenderViewHost* new_host) {
+  if (new_host)
+    RenderWidgetHostViewChanged(new_host->view());
+  native_container_->RenderViewHostChanged(old_host, new_host);
+}
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_container_native.h b/chrome/browser/ui/views/tab_contents/tab_contents_container_native.h
new file mode 100644
index 0000000..a845464
--- /dev/null
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_container_native.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_NATIVE_H_
+#define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_NATIVE_H_
+#pragma once
+
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "views/view.h"
+
+class NativeTabContentsContainer;
+class RenderViewHost;
+class RenderWidgetHostView;
+class TabContents;
+
+class TabContentsContainer : public views::View,
+                             public NotificationObserver {
+ public:
+  TabContentsContainer();
+  virtual ~TabContentsContainer();
+
+  // Changes the TabContents associated with this view.
+  void ChangeTabContents(TabContents* contents);
+
+  View* GetFocusView() { return native_container_->GetView(); }
+
+  // Accessor for |tab_contents_|.
+  TabContents* tab_contents() const { return tab_contents_; }
+
+  // Called by the BrowserView to notify that |tab_contents| got the focus.
+  void TabContentsFocused(TabContents* tab_contents);
+
+  // Tells the container to update less frequently during resizing operations
+  // so performance is better.
+  void SetFastResize(bool fast_resize);
+
+  // Updates the current reserved rect in view coordinates where contents
+  // should not be rendered to draw the resize corner, sidebar mini tabs etc.
+  void SetReservedContentsRect(const gfx::Rect& reserved_rect);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  // Overridden from views::View:
+  virtual void Layout();
+  virtual AccessibilityTypes::Role GetAccessibleRole();
+
+ protected:
+  // Overridden from views::View:
+  virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
+                                    views::View* child);
+
+ private:
+  // Add or remove observers for events that we care about.
+  void AddObservers();
+  void RemoveObservers();
+
+  // Called when the RenderViewHost of the hosted TabContents has changed, e.g.
+  // to show an interstitial page.
+  void RenderViewHostChanged(RenderViewHost* old_host,
+                             RenderViewHost* new_host);
+
+  // Called when a TabContents is destroyed. This gives us a chance to clean
+  // up our internal state if the TabContents is somehow destroyed before we
+  // get notified.
+  void TabContentsDestroyed(TabContents* contents);
+
+  // Called when the RenderWidgetHostView of the hosted TabContents has changed.
+  void RenderWidgetHostViewChanged(RenderWidgetHostView* new_view);
+
+  // An instance of a NativeTabContentsContainer object that holds the native
+  // view handle associated with the attached TabContents.
+  NativeTabContentsContainer* native_container_;
+
+  // The attached TabContents.
+  TabContents* tab_contents_;
+
+  // Handles registering for our notifications.
+  NotificationRegistrar registrar_;
+
+  // The current reserved rect in view coordinates where contents should not be
+  // rendered to draw the resize corner, sidebar mini tabs etc.
+  // Cached here to update ever changing renderers.
+  gfx::Rect cached_reserved_rect_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabContentsContainer);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_NATIVE_H_
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_container_views.cc b/chrome/browser/ui/views/tab_contents/tab_contents_container_views.cc
new file mode 100644
index 0000000..6cb17a0
--- /dev/null
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_container_views.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
+
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/interstitial_page.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h"
+#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "views/layout/fill_layout.h"
+
+// Some of this class is implemented in tab_contents_container.cc, where
+// the implementation doesn't vary between a pure views approach and a
+// native view host approach. See the header file for details.
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsContainer, public:
+
+TabContentsContainer::TabContentsContainer()
+    : tab_contents_(NULL) {
+  SetID(VIEW_ID_TAB_CONTAINER);
+}
+
+void TabContentsContainer::SetReservedContentsRect(
+    const gfx::Rect& reserved_rect) {
+  cached_reserved_rect_ = reserved_rect;
+  // TODO(anicolao): find out what this is supposed to be used for and ensure
+  // it's OK for touch.
+}
+
+void TabContentsContainer::ChangeTabContents(TabContents* contents) {
+  if (tab_contents_) {
+    views::View *v = static_cast<TabContentsViewViews*>(tab_contents_->view());
+    RemoveChildView(v);
+    tab_contents_->WasHidden();
+    RemoveObservers();
+  }
+  tab_contents_ = contents;
+  // When detaching the last tab of the browser ChangeTabContents is invoked
+  // with NULL. Don't attempt to do anything in that case.
+  if (tab_contents_) {
+    views::View *v = static_cast<TabContentsViewViews*>(contents->view());
+    AddChildView(v);
+    SetLayoutManager(new views::FillLayout());
+    Layout();
+    AddObservers();
+  }
+}
+
+void TabContentsContainer::TabContentsFocused(TabContents* tab_contents) {
+}
+
+void TabContentsContainer::SetFastResize(bool fast_resize) {
+}
+
+void TabContentsContainer::RenderViewHostChanged(RenderViewHost* old_host,
+                                                 RenderViewHost* new_host) {
+  NOTIMPLEMENTED();  // TODO(anicolao)
+}
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_container_views.h b/chrome/browser/ui/views/tab_contents/tab_contents_container_views.h
new file mode 100644
index 0000000..d5a79aa
--- /dev/null
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_container_views.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_VIEWS_H_
+#pragma once
+
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "views/view.h"
+
+class NativeTabContentsContainer;
+class RenderViewHost;
+class RenderWidgetHostView;
+class TabContents;
+
+class TabContentsContainer : public views::View,
+                             public NotificationObserver {
+ public:
+  TabContentsContainer();
+  virtual ~TabContentsContainer();
+
+  // Changes the TabContents associated with this view.
+  void ChangeTabContents(TabContents* contents);
+
+  View* GetFocusView() { return this; }
+
+  // Accessor for |tab_contents_|.
+  TabContents* tab_contents() const { return tab_contents_; }
+
+  // Called by the BrowserView to notify that |tab_contents| got the focus.
+  void TabContentsFocused(TabContents* tab_contents);
+
+  // Tells the container to update less frequently during resizing operations
+  // so performance is better.
+  void SetFastResize(bool fast_resize);
+
+  // Updates the current reserved rect in view coordinates where contents
+  // should not be rendered to draw the resize corner, sidebar mini tabs etc.
+  void SetReservedContentsRect(const gfx::Rect& reserved_rect);
+
+  // Overridden from NotificationObserver:
+  virtual void Observe(NotificationType type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details);
+
+  virtual AccessibilityTypes::Role GetAccessibleRole();
+
+ private:
+  // Add or remove observers for events that we care about.
+  void AddObservers();
+  void RemoveObservers();
+
+  // Called when the RenderViewHost of the hosted TabContents has changed, e.g.
+  // to show an interstitial page.
+  void RenderViewHostChanged(RenderViewHost* old_host,
+                             RenderViewHost* new_host);
+
+  // Called when a TabContents is destroyed. This gives us a chance to clean
+  // up our internal state if the TabContents is somehow destroyed before we
+  // get notified.
+  void TabContentsDestroyed(TabContents* contents);
+
+  // Called when the RenderWidgetHostView of the hosted TabContents has changed.
+  void RenderWidgetHostViewChanged(RenderWidgetHostView* new_view);
+
+  // The attached TabContents.
+  TabContents* tab_contents_;
+
+  // Handles registering for our notifications.
+  NotificationRegistrar registrar_;
+
+  // The current reserved rect in view coordinates where contents should not be
+  // rendered to draw the resize corner, sidebar mini tabs etc.
+  // Cached here to update ever changing renderers.
+  gfx::Rect cached_reserved_rect_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabContentsContainer);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_VIEWS_H_
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.cc b/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.cc
index 4b21ec0..2590c69 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.cc
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/tab_contents_drag_win.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h"
 
 #include <windows.h>
 
@@ -23,7 +23,7 @@
 #include "chrome/browser/tab_contents/web_drag_source_win.h"
 #include "chrome/browser/tab_contents/web_drag_utils_win.h"
 #include "chrome/browser/tab_contents/web_drop_target_win.h"
-#include "chrome/browser/views/tab_contents/tab_contents_view_win.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_view_win.h"
 #include "chrome/common/url_constants.h"
 #include "net/base/net_util.h"
 #include "views/drag_utils.h"
@@ -182,7 +182,7 @@
 
 void TabContentsDragWin::PrepareDragForDownload(
     const WebDropData& drop_data,
-    OSExchangeData* data,
+    ui::OSExchangeData* data,
     const GURL& page_url,
     const std::string& page_encoding) {
   // Parse the download metadata.
@@ -215,23 +215,24 @@
                            page_url,
                            page_encoding,
                            view_->tab_contents());
-  OSExchangeData::DownloadFileInfo file_download(FilePath(),
-                                                 download_file.get());
+  ui::OSExchangeData::DownloadFileInfo file_download(FilePath(),
+                                                     download_file.get());
   data->SetDownloadFileInfo(file_download);
 
   // Enable asynchronous operation.
-  OSExchangeDataProviderWin::GetIAsyncOperation(*data)->SetAsyncMode(TRUE);
+  ui::OSExchangeDataProviderWin::GetIAsyncOperation(*data)->SetAsyncMode(TRUE);
 }
 
 void TabContentsDragWin::PrepareDragForFileContents(
-    const WebDropData& drop_data, OSExchangeData* data) {
+    const WebDropData& drop_data, ui::OSExchangeData* data) {
   // Images without ALT text will only have a file extension so we need to
   // synthesize one from the provided extension and URL.
   FilePath file_name(drop_data.file_description_filename);
   file_name = file_name.BaseName().RemoveExtension();
   if (file_name.value().empty()) {
     // Retrieve the name from the URL.
-    file_name = net::GetSuggestedFilename(drop_data.url, "", "", FilePath());
+    file_name = FilePath(
+        net::GetSuggestedFilename(drop_data.url, "", "", string16()));
     if (file_name.value().size() + drop_data.file_extension.size() + 1 >
         MAX_PATH) {
       file_name = FilePath(file_name.value().substr(
@@ -243,7 +244,7 @@
 }
 
 void TabContentsDragWin::PrepareDragForUrl(const WebDropData& drop_data,
-                                           OSExchangeData* data) {
+                                           ui::OSExchangeData* data) {
   if (drop_data.url.SchemeIs(chrome::kJavaScriptScheme)) {
     // We don't want to allow javascript URLs to be dragged to the desktop,
     // but we do want to allow them to be added to the bookmarks bar
@@ -271,13 +272,13 @@
                                     const std::string& page_encoding,
                                     const SkBitmap& image,
                                     const gfx::Point& image_offset) {
-  OSExchangeData data;
+  ui::OSExchangeData data;
 
   if (!drop_data.download_metadata.empty()) {
     PrepareDragForDownload(drop_data, &data, page_url, page_encoding);
 
     // Set the observer.
-    OSExchangeDataProviderWin::GetDataObjectImpl(data)->set_observer(this);
+    ui::OSExchangeDataProviderWin::GetDataObjectImpl(data)->set_observer(this);
   } else {
     // We set the file contents before the URL because the URL also sets file
     // contents (to a .URL shortcut).  We want to prefer file content data over
@@ -305,7 +306,7 @@
   bool old_state = MessageLoop::current()->NestableTasksAllowed();
   MessageLoop::current()->SetNestableTasksAllowed(true);
   DWORD effect;
-  DoDragDrop(OSExchangeDataProviderWin::GetIDataObject(data), drag_source_,
+  DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data), drag_source_,
              web_drag_utils_win::WebDragOpMaskToWinDragOpMask(ops), &effect);
   MessageLoop::current()->SetNestableTasksAllowed(old_state);
 
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h b/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h
index 7e2b7c8..52666ba 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_DRAG_WIN_H_
 #pragma once
 
-#include "app/os_exchange_data_provider_win.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/threading/platform_thread.h"
-#include "gfx/point.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
+#include "ui/gfx/point.h"
 
 class DragDropThread;
 class TabContentsViewWin;
@@ -25,7 +25,7 @@
 // message loop in the UI thread. For all other cases, the drag-and-drop happens
 // in the UI thread.
 class TabContentsDragWin
-    : public DataObjectImpl::Observer,
+    : public ui::DataObjectImpl::Observer,
       public base::RefCountedThreadSafe<TabContentsDragWin> {
  public:
   explicit TabContentsDragWin(TabContentsViewWin* view);
@@ -46,12 +46,13 @@
  private:
   // Called on either UI thread or drag-and-drop thread.
   void PrepareDragForDownload(const WebDropData& drop_data,
-                              OSExchangeData* data,
+                              ui::OSExchangeData* data,
                               const GURL& page_url,
                               const std::string& page_encoding);
   void PrepareDragForFileContents(const WebDropData& drop_data,
-                                  OSExchangeData* data);
-  void PrepareDragForUrl(const WebDropData& drop_data, OSExchangeData* data);
+                                  ui::OSExchangeData* data);
+  void PrepareDragForUrl(const WebDropData& drop_data,
+                         ui::OSExchangeData* data);
   void DoDragging(const WebDropData& drop_data,
                   WebKit::WebDragOperationsMask ops,
                   const GURL& page_url,
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc
index 3d0db15..f9f5979 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/tab_contents_view_gtk.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h"
 
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
@@ -11,8 +11,6 @@
 #include "base/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/download/download_shelf.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
-#include "chrome/browser/gtk/tab_contents_drag_source.h"
 #include "chrome/browser/renderer_host/render_view_host.h"
 #include "chrome/browser/renderer_host/render_view_host_factory.h"
 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
@@ -20,12 +18,14 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/web_drag_dest_gtk.h"
-#include "chrome/browser/views/sad_tab_view.h"
-#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
+#include "chrome/browser/ui/gtk/tab_contents_drag_source.h"
+#include "chrome/browser/ui/views/sad_tab_view.h"
+#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "views/controls/native/native_view_host.h"
 #include "views/focus/view_storage.h"
 #include "views/screen.h"
@@ -239,7 +239,8 @@
     gdk_window_set_title(content_view->window, WideToUTF8(title).c_str());
 }
 
-void TabContentsViewGtk::OnTabCrashed() {
+void TabContentsViewGtk::OnTabCrashed(base::TerminationStatus /* status */,
+                                      int /* error_code */) {
 }
 
 void TabContentsViewGtk::SizeContents(const gfx::Size& size) {
@@ -322,6 +323,10 @@
   }
 }
 
+void TabContentsViewGtk::GetViewBounds(gfx::Rect* out) const {
+  GetBounds(out, true);
+}
+
 void TabContentsViewGtk::UpdateDragCursor(WebDragOperation operation) {
   if (drag_dest_.get())
     drag_dest_->UpdateDragStatus(operation);
@@ -393,13 +398,16 @@
 gboolean TabContentsViewGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) {
   if (tab_contents()->render_view_host() &&
       !tab_contents()->render_view_host()->IsRenderViewLive()) {
-    if (sad_tab_ == NULL) {
-      sad_tab_ = new SadTabView(tab_contents());
-      SetContentsView(sad_tab_);
-    }
+    base::TerminationStatus status =
+        tab_contents()->render_view_host()->render_view_termination_status();
+    SadTabView::Kind kind =
+        status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
+        SadTabView::KILLED : SadTabView::CRASHED;
+    sad_tab_ = new SadTabView(tab_contents(), kind);
+    SetContentsView(sad_tab_);
     gfx::Rect bounds;
     GetBounds(&bounds, true);
-    sad_tab_->SetBounds(gfx::Rect(0, 0, bounds.width(), bounds.height()));
+    sad_tab_->SetBoundsRect(gfx::Rect(0, 0, bounds.width(), bounds.height()));
     gfx::CanvasSkiaPaint canvas(event);
     sad_tab_->ProcessPaint(&canvas);
   }
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h b/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h
index 5352aaf..4703505 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h
@@ -10,7 +10,7 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/widget/widget_gtk.h"
 
 class ConstrainedWindowGtk;
@@ -56,12 +56,14 @@
   virtual gfx::NativeWindow GetTopLevelNativeWindow() const;
   virtual void GetContainerBounds(gfx::Rect* out) const;
   virtual void SetPageTitle(const std::wstring& title);
-  virtual void OnTabCrashed();
+  virtual void OnTabCrashed(base::TerminationStatus status,
+                            int error_code);
   virtual void SizeContents(const gfx::Size& size);
   virtual void Focus();
   virtual void SetInitialFocus();
   virtual void StoreFocus();
   virtual void RestoreFocus();
+  virtual void GetViewBounds(gfx::Rect* out) const;
 
   // Backend implementation of RenderViewHostDelegate::View.
   virtual void ShowContextMenu(const ContextMenuParams& params);
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_views.cc b/chrome/browser/ui/views/tab_contents/tab_contents_view_views.cc
index 5abdc07..345482b 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_view_views.cc
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_views.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,16 +13,16 @@
 #include "chrome/browser/tab_contents/interstitial_page.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "chrome/browser/views/sad_tab_view.h"
-#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
-#include "gfx/canvas_skia_paint.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "chrome/browser/ui/views/sad_tab_view.h"
+#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
+#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "views/controls/native/native_view_host.h"
-#include "views/fill_layout.h"
 #include "views/focus/focus_manager.h"
 #include "views/focus/view_storage.h"
+#include "views/layout/fill_layout.h"
 #include "views/screen.h"
 #include "views/widget/widget.h"
 
@@ -56,18 +56,18 @@
 
 void TabContentsViewViews::AttachConstrainedWindow(
     ConstrainedWindowGtk* constrained_window) {
-  // TODO(anicolao): reimplement all dialogs as DOMUI
+  // TODO(anicolao): reimplement all dialogs as WebUI
   NOTIMPLEMENTED();
 }
 
 void TabContentsViewViews::RemoveConstrainedWindow(
     ConstrainedWindowGtk* constrained_window) {
-  // TODO(anicolao): reimplement all dialogs as DOMUI
+  // TODO(anicolao): reimplement all dialogs as WebUI
   NOTIMPLEMENTED();
 }
 
 void TabContentsViewViews::CreateView(const gfx::Size& initial_size) {
-  SetBounds(gfx::Rect(bounds().origin(), initial_size));
+  SetBoundsRect(gfx::Rect(bounds().origin(), initial_size));
 }
 
 RenderWidgetHostView* TabContentsViewViews::CreateViewForWidget(
@@ -130,11 +130,15 @@
   // TODO(anicolao): figure out if there's anything useful to do here
 }
 
-void TabContentsViewViews::OnTabCrashed() {
+void TabContentsViewViews::OnTabCrashed(base::TerminationStatus status,
+                                        int /* error_code */) {
   if (sad_tab_ != NULL)
     return;
 
-  sad_tab_.reset(new SadTabView(tab_contents()));
+  sad_tab_.reset(new SadTabView(
+      tab_contents(),
+      status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
+          SadTabView::KILLED : SadTabView::CRASHED));
   RemoveAllChildViews(true);
   AddChildView(sad_tab_.get());
   Layout();
@@ -217,10 +221,13 @@
   }
 }
 
-void TabContentsViewViews::DidChangeBounds(const gfx::Rect& previous,
-                                           const gfx::Rect& current) {
+void TabContentsViewViews::GetViewBounds(gfx::Rect* out) const {
+  out->SetRect(x(), y(), width(), height());
+}
+
+void TabContentsViewViews::OnBoundsChanged() {
   if (IsVisibleInRootView())
-    WasSized(gfx::Size(current.width(), current.height()));
+    WasSized(size());
 }
 
 void TabContentsViewViews::Paint(gfx::Canvas* canvas) {
@@ -321,6 +328,6 @@
 }
 
 void TabContentsViewViews::SetFloatingPosition(const gfx::Size& size) {
-  // TODO(anicolao): rework this once we have DOMUI views for dialogs
+  // TODO(anicolao): rework this once we have WebUI views for dialogs
   SetBounds(x(), y(), size.width(), size.height());
 }
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_views.h b/chrome/browser/ui/views/tab_contents/tab_contents_view_views.h
index ab0e666..8033a45 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_view_views.h
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_views.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_VIEWS_H_
+#ifndef CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_VIEWS_H_
 #pragma once
 
 #include <vector>
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/view.h"
 
 class ConstrainedWindowGtk;
@@ -52,16 +52,17 @@
   virtual gfx::NativeWindow GetTopLevelNativeWindow() const;
   virtual void GetContainerBounds(gfx::Rect* out) const;
   virtual void SetPageTitle(const std::wstring& title);
-  virtual void OnTabCrashed();
+  virtual void OnTabCrashed(base::TerminationStatus status,
+                            int error_code);
   virtual void SizeContents(const gfx::Size& size);
   virtual void Focus();
   virtual void SetInitialFocus();
   virtual void StoreFocus();
   virtual void RestoreFocus();
+  virtual void GetViewBounds(gfx::Rect* out) const;
 
   // views::View implementation
-  virtual void DidChangeBounds(const gfx::Rect& previous,
-                               const gfx::Rect& current);
+  virtual void OnBoundsChanged();
 
   virtual void Paint(gfx::Canvas* canvas);
 
@@ -128,4 +129,4 @@
   DISALLOW_COPY_AND_ASSIGN(TabContentsViewViews);
 };
 
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_VIEWS_H_
+#endif  // CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_VIEWS_H_
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_win.cc b/chrome/browser/ui/views/tab_contents/tab_contents_view_win.cc
index 164fd92..6a5bb7e 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_view_win.cc
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_win.cc
@@ -1,11 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_contents/tab_contents_view_win.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_view_win.h"
 
 #include <windows.h>
 
+#include <vector>
+
 #include "base/time.h"
 #include "chrome/browser/download/download_request_limiter.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
@@ -16,11 +18,10 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
 #include "chrome/browser/tab_contents/web_drop_target_win.h"
-#include "chrome/browser/ui/browser.h"  // TODO(beng): this dependency is awful.
-#include "chrome/browser/views/sad_tab_view.h"
-#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
-#include "chrome/browser/views/tab_contents/tab_contents_drag_win.h"
-#include "gfx/canvas_skia_paint.h"
+#include "chrome/browser/ui/views/sad_tab_view.h"
+#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
+#include "chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h"
+#include "ui/gfx/canvas_skia_paint.h"
 #include "views/focus/view_storage.h"
 #include "views/screen.h"
 #include "views/widget/root_view.h"
@@ -133,9 +134,7 @@
                            &TabContentsViewWin::CloseTab);
   }
 
-  if (tab_contents()->render_view_host())
-    tab_contents()->render_view_host()->DragSourceSystemDragEnded();
-
+  tab_contents()->SystemDragEnded();
   drag_handler_ = NULL;
 }
 
@@ -155,7 +154,8 @@
   }
 }
 
-void TabContentsViewWin::OnTabCrashed() {
+void TabContentsViewWin::OnTabCrashed(base::TerminationStatus /* status */,
+                                      int /* error_code */) {
   // Force an invalidation to render sad tab. We will notice we crashed when we
   // paint.
   // Note that it's possible to get this message after the window was destroyed.
@@ -182,9 +182,6 @@
 }
 
 void TabContentsViewWin::Focus() {
-  views::FocusManager* focus_manager =
-      views::FocusManager::GetFocusManagerForNativeView(GetNativeView());
-
   if (tab_contents()->interstitial_page()) {
     tab_contents()->interstitial_page()->Focus();
     return;
@@ -284,6 +281,10 @@
   close_tab_after_drag_ends_ = true;
 }
 
+void TabContentsViewWin::GetViewBounds(gfx::Rect* out) const {
+  GetBounds(out, true);
+}
+
 void TabContentsViewWin::UpdateDragCursor(WebDragOperation operation) {
   drop_target_->set_drag_cursor(operation);
 }
@@ -400,13 +401,16 @@
 void TabContentsViewWin::OnPaint(HDC junk_dc) {
   if (tab_contents()->render_view_host() &&
       !tab_contents()->render_view_host()->IsRenderViewLive()) {
-    if (sad_tab_ == NULL) {
-      sad_tab_ = new SadTabView(tab_contents());
-      SetContentsView(sad_tab_);
-    }
+    base::TerminationStatus status =
+        tab_contents()->render_view_host()->render_view_termination_status();
+    SadTabView::Kind kind =
+        status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
+        SadTabView::KILLED : SadTabView::CRASHED;
+    sad_tab_ = new SadTabView(tab_contents(), kind);
+    SetContentsView(sad_tab_);
     CRect cr;
     GetClientRect(&cr);
-    sad_tab_->SetBounds(gfx::Rect(cr));
+    sad_tab_->SetBoundsRect(gfx::Rect(cr));
     gfx::CanvasSkiaPaint canvas(GetNativeView(), true);
     sad_tab_->ProcessPaint(&canvas);
     return;
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_win.h b/chrome/browser/ui/views/tab_contents/tab_contents_view_win.h
index fcfbfe4..fad7edc 100644
--- a/chrome/browser/ui/views/tab_contents/tab_contents_view_win.h
+++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_win.h
@@ -9,7 +9,7 @@
 #include "base/scoped_ptr.h"
 #include "base/timer.h"
 #include "chrome/browser/tab_contents/tab_contents_view.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 #include "views/widget/widget_win.h"
 
 class RenderViewContextMenuViews;
@@ -48,7 +48,8 @@
   virtual gfx::NativeWindow GetTopLevelNativeWindow() const;
   virtual void GetContainerBounds(gfx::Rect* out) const;
   virtual void SetPageTitle(const std::wstring& title);
-  virtual void OnTabCrashed();
+  virtual void OnTabCrashed(base::TerminationStatus status,
+                            int error_code);
   virtual void SizeContents(const gfx::Size& size);
   virtual void Focus();
   virtual void SetInitialFocus();
@@ -56,6 +57,7 @@
   virtual void RestoreFocus();
   virtual bool IsDoingDrag() const;
   virtual void CancelDragAndCloseTab();
+  virtual void GetViewBounds(gfx::Rect* out) const;
 
   // Backend implementation of RenderViewHostDelegate::View.
   virtual void ShowContextMenu(const ContextMenuParams& params);
diff --git a/chrome/browser/ui/views/tab_icon_view.cc b/chrome/browser/ui/views/tab_icon_view.cc
index 27f82d4..34f1270 100644
--- a/chrome/browser/ui/views/tab_icon_view.cc
+++ b/chrome/browser/ui/views/tab_icon_view.cc
@@ -1,27 +1,27 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tab_icon_view.h"
+#include "chrome/browser/ui/views/tab_icon_view.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
 #include <shellapi.h>
 #endif
 
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "gfx/canvas.h"
-#include "gfx/favicon_size.h"
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/favicon_size.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/app_icon_win.h"
-#include "gfx/icon_util.h"
+#include "ui/gfx/icon_util.h"
 #endif
 
 static bool g_initialized = false;
diff --git a/chrome/browser/ui/views/tabs/base_tab.cc b/chrome/browser/ui/views/tabs/base_tab.cc
index 0a60a11..8fd7d3d 100644
--- a/chrome/browser/ui/views/tabs/base_tab.cc
+++ b/chrome/browser/ui/views/tabs/base_tab.cc
@@ -1,14 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/base_tab.h"
+#include "chrome/browser/ui/views/tabs/base_tab.h"
 
 #include <limits>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
@@ -16,14 +13,17 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/tabs/tab_controller.h"
 #include "chrome/common/chrome_switches.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/favicon_size.h"
-#include "gfx/font.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/slide_animation.h"
 #include "ui/base/animation/throb_animation.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/font.h"
 #include "views/controls/button/image_button.h"
 
 // How long the pulse throb takes.
@@ -58,12 +58,12 @@
   // fire before Enter events, so this works.
   virtual void OnMouseEntered(const views::MouseEvent& event) {
     CustomButton::OnMouseEntered(event);
-    GetParent()->OnMouseEntered(event);
+    parent()->OnMouseEntered(event);
   }
 
   virtual void OnMouseExited(const views::MouseEvent& event) {
     CustomButton::OnMouseExited(event);
-    GetParent()->OnMouseExited(event);
+    parent()->OnMouseExited(event);
   }
 
  private:
@@ -120,11 +120,11 @@
     : controller_(controller),
       closing_(false),
       dragging_(false),
-      loading_animation_frame_(0),
-      throbber_disabled_(false),
-      theme_provider_(NULL),
       fav_icon_hiding_offset_(0),
-      should_display_crashed_favicon_(false) {
+      loading_animation_frame_(0),
+      should_display_crashed_favicon_(false),
+      throbber_disabled_(false),
+      theme_provider_(NULL) {
   BaseTab::InitResources();
 
   SetID(VIEW_ID_TAB);
@@ -141,7 +141,7 @@
   close_button_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_CLOSE_TAB)));
   close_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
   // Disable animation so that the red danger sign shows up immediately
   // to help avoid mis-clicks.
   close_button_->SetAnimationDuration(0);
@@ -157,9 +157,30 @@
   TabRendererData old(data_);
   data_ = data;
 
-  if (data_.crashed) {
-    if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation())
-      StartCrashAnimation();
+  if (data_.IsCrashed()) {
+    if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) {
+      // When --reload-killed-tabs is specified, then the idea is that
+      // when tab is killed, the tab has no visual indication that it
+      // died and should reload when the tab is next focused without
+      // the user seeing the killed tab page.
+      //
+      // The only exception to this is when the tab is in the
+      // foreground (i.e. when it's the selected tab), because we
+      // don't want to go into an infinite loop reloading a page that
+      // will constantly get killed, or if it's the only tab.  So this
+      // code makes it so that the favicon will only be shown for
+      // killed tabs when the tab is currently selected.
+      if (CommandLine::ForCurrentProcess()->
+          HasSwitch(switches::kReloadKilledTabs) && !IsSelected()) {
+        // If we're reloading killed tabs, we don't want to display
+        // the crashed animation at all if the process was killed and
+        // the tab wasn't the current tab.
+        if (data_.crashed_status != base::TERMINATION_STATUS_PROCESS_WAS_KILLED)
+          StartCrashAnimation();
+      } else {
+        StartCrashAnimation();
+      }
+    }
   } else {
     if (IsPerformingCrashAnimation())
       StopCrashAnimation();
@@ -167,7 +188,7 @@
   }
 
   // Sets the accessible name for the tab.
-  SetAccessibleName(UTF16ToWide(data_.title));
+  SetAccessibleName(data_.title);
 
   DataChanged(old);
 
@@ -305,8 +326,8 @@
   return AccessibilityTypes::ROLE_PAGETAB;
 }
 
-ThemeProvider* BaseTab::GetThemeProvider() {
-  ThemeProvider* tp = View::GetThemeProvider();
+ui::ThemeProvider* BaseTab::GetThemeProvider() {
+  ui::ThemeProvider* tp = View::GetThemeProvider();
   return tp ? tp : theme_provider_;
 }
 
@@ -359,7 +380,7 @@
     favicon_x += (data().favicon.width() - kFavIconSize) / 2;
 
   if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
-    ThemeProvider* tp = GetThemeProvider();
+    ui::ThemeProvider* tp = GetThemeProvider();
     SkBitmap frames(*tp->GetBitmapNamed(
         (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
         IDR_THROBBER_WAITING : IDR_THROBBER));
@@ -406,7 +427,7 @@
     Browser::FormatTitleForDisplay(&title);
   }
 
-  canvas->DrawStringInt(UTF16ToWideHack(title), *font_, title_color,
+  canvas->DrawStringInt(title, *font_, title_color,
                         title_bounds().x(), title_bounds().y(),
                         title_bounds().width(), title_bounds().height());
 }
diff --git a/chrome/browser/ui/views/tabs/base_tab.h b/chrome/browser/ui/views/tabs/base_tab.h
index 1a98bdc..6d1f3ea 100644
--- a/chrome/browser/ui/views/tabs/base_tab.h
+++ b/chrome/browser/ui/views/tabs/base_tab.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
-#include "chrome/browser/views/tabs/tab_renderer_data.h"
+#include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
 #include "ui/base/animation/animation_container.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "views/controls/button/button.h"
@@ -72,7 +72,7 @@
   // Set the theme provider - because we get detached, we are frequently
   // outside of a hierarchy with a theme provider at the top. This should be
   // called whenever we're detached or attached to a hierarchy.
-  void set_theme_provider(ThemeProvider* provider) {
+  void set_theme_provider(ui::ThemeProvider* provider) {
     theme_provider_ = provider;
   }
 
@@ -135,6 +135,14 @@
   // Returns the bounds of the title.
   virtual const gfx::Rect& title_bounds() const = 0;
 
+  virtual int loading_animation_frame() const {
+    return loading_animation_frame_;
+  }
+  virtual bool should_display_crashed_favicon() const {
+    return should_display_crashed_favicon_;
+  }
+  virtual int fav_icon_hiding_offset() const { return fav_icon_hiding_offset_; }
+
   static gfx::Font* font() { return font_; }
   static int font_height() { return font_height_; }
 
@@ -170,6 +178,15 @@
   // True if the tab is being dragged.
   bool dragging_;
 
+  // The offset used to animate the favicon location. This is used when the tab
+  // crashes.
+  int fav_icon_hiding_offset_;
+
+  // The current index of the loading animation.
+  int loading_animation_frame_;
+
+  bool should_display_crashed_favicon_;
+
   // Pulse animation.
   scoped_ptr<ui::ThrobAnimation> pulse_animation_;
 
@@ -183,21 +200,12 @@
 
   views::ImageButton* close_button_;
 
-  // The current index of the loading animation.
-  int loading_animation_frame_;
-
   // Whether to disable throbber animations. Only true if this is an app tab
   // renderer and a command line flag has been passed in to disable the
   // animations.
   bool throbber_disabled_;
 
-  ThemeProvider* theme_provider_;
-
-  // The offset used to animate the favicon location. This is used when the tab
-  // crashes.
-  int fav_icon_hiding_offset_;
-
-  bool should_display_crashed_favicon_;
+  ui::ThemeProvider* theme_provider_;
 
   static gfx::Font* font_;
   static int font_height_;
diff --git a/chrome/browser/ui/views/tabs/base_tab_strip.cc b/chrome/browser/ui/views/tabs/base_tab_strip.cc
index 8a467d9..1afbc1b 100644
--- a/chrome/browser/ui/views/tabs/base_tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/base_tab_strip.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/base_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
 
 #include "base/logging.h"
 #include "chrome/browser/ui/view_ids.h"
@@ -333,7 +333,7 @@
 
   // Walk up the view hierarchy until we find a tab, or the TabStrip.
   while (view && view != this && view->GetID() != VIEW_ID_TAB)
-    view = view->GetParent();
+    view = view->parent();
 
   return view && view->GetID() == VIEW_ID_TAB ?
       static_cast<BaseTab*>(view) : NULL;
@@ -357,6 +357,12 @@
   EndDrag(canceled);
 }
 
+void BaseTabStrip::StartMoveTabAnimation() {
+  PrepareForAnimation();
+  GenerateIdealBounds();
+  AnimateToIdealBounds();
+}
+
 void BaseTabStrip::StartRemoveTabAnimation(int model_index) {
   PrepareForAnimation();
 
@@ -408,6 +414,16 @@
   return -1;
 }
 
+void BaseTabStrip::StopAnimating(bool layout) {
+  if (!IsAnimating())
+    return;
+
+  bounds_animator().Cancel();
+
+  if (layout)
+    DoLayout();
+}
+
 void BaseTabStrip::DestroyDragController() {
   if (IsDragSessionActive())
     drag_controller_.reset(NULL);
@@ -431,7 +447,7 @@
   GenerateIdealBounds();
   int tab_data_index = TabIndexOfTab(tab);
   DCHECK(tab_data_index != -1);
-  tab->SetBounds(ideal_bounds(tab_data_index));
+  tab->SetBoundsRect(ideal_bounds(tab_data_index));
   SchedulePaint();
 }
 
@@ -475,7 +491,7 @@
   GenerateIdealBounds();
 
   for (int i = 0; i < tab_count(); ++i)
-    tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds);
+    tab_data_[i].tab->SetBoundsRect(tab_data_[i].ideal_bounds);
 
   SchedulePaint();
 }
diff --git a/chrome/browser/ui/views/tabs/base_tab_strip.h b/chrome/browser/ui/views/tabs/base_tab_strip.h
index 98b304e..6868608 100644
--- a/chrome/browser/ui/views/tabs/base_tab_strip.h
+++ b/chrome/browser/ui/views/tabs/base_tab_strip.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,15 +9,14 @@
 #include <vector>
 
 #include "base/scoped_ptr.h"
-#include "chrome/browser/views/tabs/base_tab.h"
-#include "chrome/browser/views/tabs/tab_controller.h"
+#include "chrome/browser/ui/views/tabs/base_tab.h"
+#include "chrome/browser/ui/views/tabs/tab_controller.h"
 #include "views/animation/bounds_animator.h"
 #include "views/view.h"
 
 class BaseTab;
 class DraggedTabController;
 class TabStripController;
-class ThemeProvider;
 
 // Base class for the view tab strip implementations.
 class BaseTabStrip : public views::View,
@@ -33,10 +32,6 @@
 
   Type type() const { return type_; }
 
-  // Returns the preferred height of this TabStrip. This is based on the
-  // typical height of its constituent tabs.
-  virtual int GetPreferredHeight() = 0;
-
   // Set the background offset used by inactive tabs to match the frame image.
   virtual void SetBackgroundOffset(const gfx::Point& offset) = 0;
 
@@ -172,7 +167,7 @@
 
   // Invoked from |MoveTab| after |tab_data_| has been updated to animate the
   // move.
-  virtual void StartMoveTabAnimation() = 0;
+  virtual void StartMoveTabAnimation();
 
   // Starts the remove tab animation.
   virtual void StartRemoveTabAnimation(int model_index);
@@ -205,7 +200,7 @@
 
   // Stops any ongoing animations. If |layout| is true and an animation is
   // ongoing this does a layout.
-  virtual void StopAnimating(bool layout) = 0;
+  virtual void StopAnimating(bool layout);
 
   // Destroys the active drag controller.
   void DestroyDragController();
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 51e24af..100f61d 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/browser_tab_strip_controller.h"
+#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
 
 #include "base/auto_reset.h"
 #include "base/command_line.h"
@@ -16,7 +16,6 @@
 #include "chrome/browser/ui/tabs/tab_menu_model.h"
 #include "chrome/browser/ui/views/tabs/base_tab_strip.h"
 #include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/url_constants.h"
 #include "views/controls/menu/menu_2.h"
@@ -32,7 +31,7 @@
 }
 
 class BrowserTabStripController::TabContextMenuContents
-    : public menus::SimpleMenuModel::Delegate {
+    : public ui::SimpleMenuModel::Delegate {
  public:
   TabContextMenuContents(BaseTab* tab,
                          BrowserTabStripController* controller)
@@ -58,7 +57,7 @@
     // We could be gone now. Assume |this| is junk!
   }
 
-  // Overridden from menus::SimpleMenuModel::Delegate:
+  // Overridden from ui::SimpleMenuModel::Delegate:
   virtual bool IsCommandIdChecked(int command_id) const {
     return controller_->IsCommandCheckedForTab(
         static_cast<TabStripModel::ContextMenuCommand>(command_id),
@@ -71,7 +70,7 @@
   }
   virtual bool GetAcceleratorForCommandId(
       int command_id,
-      menus::Accelerator* accelerator) {
+      ui::Accelerator* accelerator) {
     int browser_cmd;
     return TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
                                                              &browser_cmd) ?
@@ -336,7 +335,8 @@
   SetTabDataAt(contents, model_index);
 }
 
-void BrowserTabStripController::TabReplacedAt(TabContentsWrapper* old_contents,
+void BrowserTabStripController::TabReplacedAt(TabStripModel* tab_strip_model,
+                                              TabContentsWrapper* old_contents,
                                               TabContentsWrapper* new_contents,
                                               int model_index) {
   SetTabDataAt(new_contents, model_index);
@@ -386,7 +386,7 @@
   data->network_state = TabContentsNetworkState(contents);
   data->title = contents->GetTitle();
   data->loading = contents->is_loading();
-  data->crashed = contents->is_crashed();
+  data->crashed_status = contents->crashed_status();
   data->off_the_record = contents->profile()->IsOffTheRecord();
   data->show_icon = contents->ShouldDisplayFavIcon();
   data->mini = model_->IsMiniTab(model_index);
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index 1dcd1f4..e7e9915 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include "base/scoped_ptr.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/views/tabs/tab_strip_controller.h"
+#include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
 
@@ -71,7 +71,8 @@
   virtual void TabChangedAt(TabContentsWrapper* contents,
                             int model_index,
                             TabChangeType change_type);
-  virtual void TabReplacedAt(TabContentsWrapper* old_contents,
+  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
+                             TabContentsWrapper* old_contents,
                              TabContentsWrapper* new_contents,
                              int model_index);
   virtual void TabPinnedStateChanged(TabContentsWrapper* contents,
diff --git a/chrome/browser/ui/views/tabs/dragged_tab_controller.cc b/chrome/browser/ui/views/tabs/dragged_tab_controller.cc
index e23e1c4..0ee3832 100644
--- a/chrome/browser/ui/views/tabs/dragged_tab_controller.cc
+++ b/chrome/browser/ui/views/tabs/dragged_tab_controller.cc
@@ -1,13 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/dragged_tab_controller.h"
+#include "chrome/browser/ui/views/tabs/dragged_tab_controller.h"
 
 #include <math.h>
 #include <set>
 
-#include "app/resource_bundle.h"
 #include "base/callback.h"
 #include "base/i18n/rtl.h"
 #include "chrome/browser/browser_window.h"
@@ -15,25 +14,27 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/tabs/tab_strip_model.h"
 #include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/base_tab.h"
-#include "chrome/browser/views/tabs/base_tab_strip.h"
-#include "chrome/browser/views/tabs/browser_tab_strip_controller.h"
-#include "chrome/browser/views/tabs/dragged_tab_view.h"
-#include "chrome/browser/views/tabs/native_view_photobooth.h"
-#include "chrome/browser/views/tabs/side_tab.h"
-#include "chrome/browser/views/tabs/side_tab_strip.h"
-#include "chrome/browser/views/tabs/tab.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/tabs/base_tab.h"
+#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
+#include "chrome/browser/ui/views/tabs/dragged_tab_view.h"
+#include "chrome/browser/ui/views/tabs/native_view_photobooth.h"
+#include "chrome/browser/ui/views/tabs/side_tab.h"
+#include "chrome/browser/ui/views/tabs/side_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/canvas_skia.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/animation/animation.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/slide_animation.h"
-#include "views/event.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "views/events/event.h"
+#include "views/screen.h"
 #include "views/widget/root_view.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -459,11 +460,6 @@
   // Dragged tabs don't care about this.
 }
 
-void DraggedTabController::URLStarredChanged(TabContents* source,
-                                             bool starred) {
-  // Ignored.
-}
-
 void DraggedTabController::UpdateTargetURL(TabContents* source,
                                            const GURL& url) {
   // Ignored.
@@ -532,11 +528,25 @@
 
 gfx::Point DraggedTabController::GetWindowCreatePoint() const {
   gfx::Point cursor_point = GetCursorScreenPoint();
-  if (dock_info_.type() != DockInfo::NONE) {
+  if (dock_info_.type() != DockInfo::NONE && dock_info_.in_enable_area()) {
     // If we're going to dock, we need to return the exact coordinate,
     // otherwise we may attempt to maximize on the wrong monitor.
     return cursor_point;
   }
+  // If the cursor is outside the monitor area, move it inside. For example,
+  // dropping a tab onto the task bar on Windows produces this situation.
+  gfx::Rect work_area = views::Screen::GetMonitorWorkAreaNearestPoint(
+      cursor_point);
+  if (!work_area.IsEmpty()) {
+    if (cursor_point.x() < work_area.x())
+      cursor_point.set_x(work_area.x());
+    else if (cursor_point.x() > work_area.right())
+      cursor_point.set_x(work_area.right());
+    if (cursor_point.y() < work_area.y())
+      cursor_point.set_y(work_area.y());
+    else if (cursor_point.y() > work_area.bottom())
+      cursor_point.set_y(work_area.bottom());
+  }
   return gfx::Point(cursor_point.x() - window_create_point_.x(),
                     cursor_point.y() - window_create_point_.y());
 }
@@ -586,7 +596,7 @@
                       NotificationType::TAB_CONTENTS_DESTROYED,
                       Source<TabContents>(dragged_contents_->tab_contents()));
     if (original_delegate_)
-      dragged_contents_->set_delegate(original_delegate_);
+      dragged_contents_->tab_contents()->set_delegate(original_delegate_);
   }
   original_delegate_ = NULL;
   dragged_contents_ = new_contents;
@@ -599,8 +609,8 @@
     // otherwise our dragged_contents() may be replaced and subsequently
     // collected/destroyed while the drag is in process, leading to
     // nasty crashes.
-    original_delegate_ = dragged_contents_->delegate();
-    dragged_contents_->set_delegate(this);
+    original_delegate_ = dragged_contents_->tab_contents()->delegate();
+    dragged_contents_->tab_contents()->set_delegate(this);
   }
 }
 
@@ -641,7 +651,7 @@
   // guaranteed to be correct regardless of monitor config.
   gfx::Point screen_point = GetCursorScreenPoint();
 
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(TOUCH_UI)
   // We don't allow detaching in chrome os.
   BaseTabStrip* target_tabstrip = source_tabstrip_;
 #else
@@ -713,7 +723,7 @@
   attached_tab_->SchedulePaint();
   attached_tab_->SetX(dragged_view_point.x());
   attached_tab_->SetX(
-      attached_tabstrip_->MirroredLeftPointForRect(attached_tab_->bounds()));
+      attached_tabstrip_->GetMirroredXForRect(attached_tab_->bounds()));
   attached_tab_->SetY(dragged_view_point.y());
   attached_tab_->SchedulePaint();
 }
@@ -832,7 +842,7 @@
 
     // Remove ourselves as the delegate now that the dragged TabContents is
     // being inserted back into a Browser.
-    dragged_contents_->set_delegate(NULL);
+    dragged_contents_->tab_contents()->set_delegate(NULL);
     original_delegate_ = NULL;
 
     // Return the TabContents' to normalcy.
@@ -905,7 +915,7 @@
   view_->SetTabWidthAndUpdate(attached_tab_width, photobooth_.get());
 
   // Detaching resets the delegate, but we still want to be the delegate.
-  dragged_contents_->set_delegate(this);
+  dragged_contents_->tab_contents()->set_delegate(this);
 
   attached_tabstrip_ = NULL;
 }
@@ -927,7 +937,7 @@
   // it uses the same orientation used by the tabs on the tab strip.
   gfx::Rect adjusted_bounds(dragged_bounds);
   adjusted_bounds.set_x(
-      attached_tabstrip_->MirroredLeftPointForRect(adjusted_bounds));
+      attached_tabstrip_->GetMirroredXForRect(adjusted_bounds));
 
   int index = -1;
   for (int i = 0; i < attached_tabstrip_->tab_count(); ++i) {
@@ -1018,7 +1028,7 @@
   x = tab_loc.x();
   y = tab_loc.y();
 
-  const gfx::Size& tab_size = attached_tab_->bounds().size();
+  const gfx::Size& tab_size = attached_tab_->size();
 
   if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) {
     int max_x = attached_tabstrip_->width() - tab_size.width();
@@ -1072,21 +1082,24 @@
       else
         CompleteDrag();
     }
-    if (dragged_contents_ && dragged_contents_->delegate() == this)
-      dragged_contents_->set_delegate(original_delegate_);
+    if (dragged_contents_ &&
+        dragged_contents_->tab_contents()->delegate() == this)
+      dragged_contents_->tab_contents()->set_delegate(original_delegate_);
   } else {
     // If we get here it means the NavigationController is going down. Don't
     // attempt to do any cleanup other than resetting the delegate (if we're
     // still the delegate).
-    if (dragged_contents_ && dragged_contents_->delegate() == this)
-      dragged_contents_->set_delegate(NULL);
+    if (dragged_contents_ &&
+        dragged_contents_->tab_contents()->delegate() == this)
+      dragged_contents_->tab_contents()->set_delegate(NULL);
     dragged_contents_ = NULL;
   }
 
   // The delegate of the dragged contents should have been reset. Unset the
   // original delegate so that we don't attempt to reset the delegate when
   // deleted.
-  DCHECK(!dragged_contents_ || dragged_contents_->delegate() != this);
+  DCHECK(!dragged_contents_ ||
+         dragged_contents_->tab_contents()->delegate() != this);
   original_delegate_ = NULL;
 
   source_tabstrip_->DestroyDragController();
@@ -1255,7 +1268,7 @@
 gfx::Rect DraggedTabController::GetViewScreenBounds(views::View* view) const {
   gfx::Point view_topleft;
   views::View::ConvertPointToScreen(view, &view_topleft);
-  gfx::Rect view_screen_bounds = view->GetLocalBounds(true);
+  gfx::Rect view_screen_bounds = view->GetLocalBounds();
   view_screen_bounds.Offset(view_topleft.x(), view_topleft.y());
   return view_screen_bounds;
 }
diff --git a/chrome/browser/ui/views/tabs/dragged_tab_controller.h b/chrome/browser/ui/views/tabs/dragged_tab_controller.h
index 78481ae..832693c 100644
--- a/chrome/browser/ui/views/tabs/dragged_tab_controller.h
+++ b/chrome/browser/ui/views/tabs/dragged_tab_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
 #include "chrome/browser/ui/tabs/dock_info.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 namespace views {
 class View;
@@ -110,7 +110,6 @@
   virtual void CloseContents(TabContents* source);
   virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
   virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
-  virtual void URLStarredChanged(TabContents* source, bool starred);
   virtual void UpdateTargetURL(TabContents* source, const GURL& url);
 
   // Overridden from NotificationObserver:
diff --git a/chrome/browser/ui/views/tabs/dragged_tab_view.cc b/chrome/browser/ui/views/tabs/dragged_tab_view.cc
index 8f77a87..367019e 100644
--- a/chrome/browser/ui/views/tabs/dragged_tab_view.cc
+++ b/chrome/browser/ui/views/tabs/dragged_tab_view.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/dragged_tab_view.h"
+#include "chrome/browser/ui/views/tabs/dragged_tab_view.h"
 
-#include "chrome/browser/views/tabs/native_view_photobooth.h"
-#include "gfx/canvas_skia.h"
+#include "chrome/browser/ui/views/tabs/native_view_photobooth.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/widget/widget.h"
 
 #if defined(OS_WIN)
@@ -62,7 +62,7 @@
 }
 
 DraggedTabView::~DraggedTabView() {
-  GetParent()->RemoveChildView(this);
+  parent()->RemoveChildView(this);
   container_->CloseNow();
 }
 
@@ -74,8 +74,7 @@
     // window position differently.
     gfx::Size ps = GetPreferredSize();
     x = screen_point.x() - ScaleValue(ps.width()) + mouse_tab_offset_.x() +
-        ScaleValue(
-            renderer_->MirroredXCoordinateInsideView(mouse_tab_offset_.x()));
+        ScaleValue(renderer_->GetMirroredXInView(mouse_tab_offset_.x()));
   } else {
     x = screen_point.x() + mouse_tab_offset_.x() -
         ScaleValue(mouse_tab_offset_.x());
diff --git a/chrome/browser/ui/views/tabs/dragged_tab_view.h b/chrome/browser/ui/views/tabs/dragged_tab_view.h
index e36cd03..d2dda61 100644
--- a/chrome/browser/ui/views/tabs/dragged_tab_view.h
+++ b/chrome/browser/ui/views/tabs/dragged_tab_view.h
@@ -7,8 +7,8 @@
 #pragma once
 
 #include "build/build_config.h"
-#include "gfx/point.h"
-#include "gfx/size.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/size.h"
 #include "views/view.h"
 
 namespace views {
diff --git a/chrome/browser/ui/views/tabs/native_view_photobooth.h b/chrome/browser/ui/views/tabs/native_view_photobooth.h
index b0bfea8..cd56ffe 100644
--- a/chrome/browser/ui/views/tabs/native_view_photobooth.h
+++ b/chrome/browser/ui/views/tabs/native_view_photobooth.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace gfx {
 class Canvas;
diff --git a/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.cc b/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.cc
index a307112..26d7503 100644
--- a/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.cc
+++ b/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/native_view_photobooth_gtk.h"
+#include "chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h"
 
 #include "base/logging.h"
-#include "gfx/canvas.h"
+#include "ui/gfx/canvas.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // NativeViewPhotoboothGtk, public:
diff --git a/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h b/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h
index 8764e89..f2082db 100644
--- a/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h
+++ b/chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_GTK_H_
 #pragma once
 
-#include "chrome/browser/views/tabs/native_view_photobooth.h"
+#include "chrome/browser/ui/views/tabs/native_view_photobooth.h"
 
 class NativeViewPhotoboothGtk : public NativeViewPhotobooth {
  public:
diff --git a/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc b/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
index d749ea0..0a912fb 100644
--- a/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
+++ b/chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/native_view_photobooth_win.h"
+#include "chrome/browser/ui/views/tabs/native_view_photobooth_win.h"
 
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/point.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/point.h"
 #include "views/widget/widget_win.h"
 
 namespace {
diff --git a/chrome/browser/ui/views/tabs/native_view_photobooth_win.h b/chrome/browser/ui/views/tabs/native_view_photobooth_win.h
index 5797910..44402ae 100644
--- a/chrome/browser/ui/views/tabs/native_view_photobooth_win.h
+++ b/chrome/browser/ui/views/tabs/native_view_photobooth_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_
 #pragma once
 
-#include "chrome/browser/views/tabs/native_view_photobooth.h"
+#include "chrome/browser/ui/views/tabs/native_view_photobooth.h"
 
 namespace views {
 class WidgetWin;
diff --git a/chrome/browser/ui/views/tabs/side_tab.cc b/chrome/browser/ui/views/tabs/side_tab.cc
index b42bca0..71efa38 100644
--- a/chrome/browser/ui/views/tabs/side_tab.cc
+++ b/chrome/browser/ui/views/tabs/side_tab.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/side_tab.h"
+#include "chrome/browser/ui/views/tabs/side_tab.h"
 
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/favicon_size.h"
-#include "gfx/path.h"
-#include "gfx/skia_util.h"
 #include "grit/app_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/skia_util.h"
 #include "views/controls/button/image_button.h"
 
 namespace {
diff --git a/chrome/browser/ui/views/tabs/side_tab.h b/chrome/browser/ui/views/tabs/side_tab.h
index c82f5c9..b0ac0a7 100644
--- a/chrome/browser/ui/views/tabs/side_tab.h
+++ b/chrome/browser/ui/views/tabs/side_tab.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_SIDE_TAB_H_
 #pragma once
 
-#include "chrome/browser/views/tabs/base_tab.h"
-#include "gfx/font.h"
+#include "chrome/browser/ui/views/tabs/base_tab.h"
+#include "ui/gfx/font.h"
 
 class SideTab;
 class TabStripController;
diff --git a/chrome/browser/ui/views/tabs/side_tab_strip.cc b/chrome/browser/ui/views/tabs/side_tab_strip.cc
index c9e2b69..8eedb75 100644
--- a/chrome/browser/ui/views/tabs/side_tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/side_tab_strip.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/side_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/side_tab_strip.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/tabs/side_tab.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
-#include "gfx/canvas.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/background.h"
 #include "views/controls/button/image_button.h"
 
@@ -89,10 +89,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // SideTabStrip, BaseTabStrip implementation:
 
-int SideTabStrip::GetPreferredHeight() {
-  return 0;
-}
-
 void SideTabStrip::SetBackgroundOffset(const gfx::Point& offset) {
 }
 
@@ -155,7 +151,7 @@
 }
 
 void SideTabStrip::GenerateIdealBounds() {
-  gfx::Rect layout_rect = GetLocalBounds(false);
+  gfx::Rect layout_rect = GetContentsBounds();
   layout_rect.Inset(kTabStripInset, kTabStripInset);
 
   int y = layout_rect.y();
@@ -214,23 +210,6 @@
   AnimateToIdealBounds();
 }
 
-void SideTabStrip::StartMoveTabAnimation() {
-  PrepareForAnimation();
-
-  GenerateIdealBounds();
-  AnimateToIdealBounds();
-}
-
-void SideTabStrip::StopAnimating(bool layout) {
-  if (!IsAnimating())
-    return;
-
-  bounds_animator().Cancel();
-
-  if (layout)
-    DoLayout();
-}
-
 void SideTabStrip::AnimateToIdealBounds() {
   for (int i = 0; i < tab_count(); ++i) {
     BaseTab* tab = base_tab_at_tab_index(i);
@@ -246,7 +225,7 @@
 void SideTabStrip::DoLayout() {
   BaseTabStrip::DoLayout();
 
-  newtab_button_->SetBounds(newtab_button_bounds_);
+  newtab_button_->SetBoundsRect(newtab_button_bounds_);
 
-  separator_->SetBounds(separator_bounds_);
+  separator_->SetBoundsRect(separator_bounds_);
 }
diff --git a/chrome/browser/ui/views/tabs/side_tab_strip.h b/chrome/browser/ui/views/tabs/side_tab_strip.h
index 6e091a8..66312b0 100644
--- a/chrome/browser/ui/views/tabs/side_tab_strip.h
+++ b/chrome/browser/ui/views/tabs/side_tab_strip.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_SIDE_TAB_STRIP_H_
 #pragma once
 
-#include "chrome/browser/views/tabs/base_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
 
 struct TabRendererData;
 
@@ -19,7 +19,6 @@
   virtual ~SideTabStrip();
 
   // BaseTabStrip implementation:
-  virtual int GetPreferredHeight();
   virtual void SetBackgroundOffset(const gfx::Point& offset);
   virtual bool IsPositionInWindowCaption(const gfx::Point& point);
 
@@ -39,8 +38,6 @@
   virtual BaseTab* CreateTab();
   virtual void GenerateIdealBounds();
   virtual void StartInsertTabAnimation(int model_index, bool foreground);
-  virtual void StartMoveTabAnimation();
-  virtual void StopAnimating(bool layout);
   virtual void AnimateToIdealBounds();
   virtual void DoLayout();
 
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 98e19cc..8230b89 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -6,15 +6,9 @@
 
 #include <limits>
 
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/favicon_size.h"
-#include "gfx/font.h"
-#include "gfx/path.h"
-#include "gfx/skbitmap_operations.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -22,6 +16,12 @@
 #include "ui/base/animation/multi_animation.h"
 #include "ui/base/animation/slide_animation.h"
 #include "ui/base/animation/throb_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/skbitmap_operations.h"
 #include "views/controls/button/image_button.h"
 #include "views/widget/tooltip_manager.h"
 #include "views/widget/widget.h"
@@ -52,10 +52,11 @@
 
 // How opaque to make the hover state (out of 1).
 static const double kHoverOpacity = 0.33;
+static const double kHoverSlideOpacity = 0.5;
 
-Tab::TabImage Tab::tab_alpha = {0};
-Tab::TabImage Tab::tab_active = {0};
-Tab::TabImage Tab::tab_inactive = {0};
+Tab::TabImage Tab::tab_alpha_ = {0};
+Tab::TabImage Tab::tab_active_ = {0};
+Tab::TabImage Tab::tab_inactive_ = {0};
 
 // Durations for the various parts of the mini tab title animation.
 static const int kMiniTitleChangeAnimationDuration1MS = 1600;
@@ -82,19 +83,6 @@
 static const SkScalar kTabTopCurveWidth = 4;
 static const SkScalar kTabBottomCurveWidth = 3;
 
-namespace {
-
-void InitTabResources() {
-  static bool initialized = false;
-  if (initialized)
-    return;
-
-  initialized = true;
-  Tab::LoadTabImages();
-}
-
-}  // namespace
-
 // static
 const char Tab::kViewClassName[] = "browser/tabs/Tab";
 
@@ -140,10 +128,6 @@
     mini_title_animation_->Stop();
 }
 
-void Tab::PaintIcon(gfx::Canvas* canvas) {
-  BaseTab::PaintIcon(canvas, favicon_bounds_.x(), favicon_bounds_.y());
-}
-
 // static
 gfx::Size Tab::GetMinimumUnselectedSize() {
   InitTabResources();
@@ -152,7 +136,7 @@
   minimum_size.set_width(kLeftPadding + kRightPadding);
   // Since we use bitmap images, the real minimum height of the image is
   // defined most accurately by the height of the end cap images.
-  minimum_size.set_height(tab_active.image_l->height());
+  minimum_size.set_height(tab_active_.image_l->height());
   return minimum_size;
 }
 
@@ -228,7 +212,7 @@
 }
 
 void Tab::Layout() {
-  gfx::Rect lb = GetLocalBounds(false);
+  gfx::Rect lb = GetContentsBounds();
   if (lb.IsEmpty())
     return;
   lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding);
@@ -317,11 +301,11 @@
   // instance) are automatically mirrored by the mirroring infrastructure in
   // views. The elements Tab draws directly on the canvas need to be manually
   // mirrored if the View's layout is right-to-left.
-  title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_));
+  title_bounds_.set_x(GetMirroredXForRect(title_bounds_));
 }
 
 void Tab::OnThemeChanged() {
-  Tab::LoadTabImages();
+  LoadTabImages();
 }
 
 bool Tab::HasHitTestMask() const {
@@ -370,6 +354,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Tab, private
 
+void Tab::PaintIcon(gfx::Canvas* canvas) {
+  BaseTab::PaintIcon(canvas, favicon_bounds_.x(), favicon_bounds_.y());
+}
+
 void Tab::PaintTabBackground(gfx::Canvas* canvas) {
   if (IsSelected()) {
     PaintActiveTabBackground(canvas);
@@ -451,8 +439,7 @@
   // The tab image needs to be lined up with the background image
   // so that it feels partially transparent.  These offsets represent the tab
   // position within the frame background image.
-  int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
-      background_offset_.x();
+  int offset = GetMirroredX() + background_offset_.x();
 
   int tab_id;
   if (GetWidget() &&
@@ -465,9 +452,9 @@
 
   SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
 
-  TabImage* tab_image = &tab_active;
-  TabImage* tab_inactive_image = &tab_inactive;
-  TabImage* alpha = &tab_alpha;
+  TabImage* tab_image = &tab_active_;
+  TabImage* tab_inactive_image = &tab_inactive_;
+  TabImage* alpha = &tab_alpha_;
 
   // If the theme is providing a custom background image, then its top edge
   // should be at the top of the tab. Otherwise, we assume that the background
@@ -516,7 +503,8 @@
   canvas->DrawBitmapInt(background_canvas.ExtractBitmap(), 0, 0);
 
   if (!GetThemeProvider()->HasCustomImage(tab_id) &&
-      hover_animation() && hover_animation()->IsShowing()) {
+      hover_animation() &&
+      (hover_animation()->IsShowing() || hover_animation()->is_animating())) {
     SkBitmap hover_glow = DrawHoverGlowBitmap(width(), height());
     // Draw the hover glow clipped to the background into hover_image.
     SkBitmap hover_image = SkBitmapOperations::CreateMaskedBitmap(
@@ -536,16 +524,14 @@
 }
 
 void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) {
-  int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
-      background_offset_.x();
-  ThemeProvider* tp = GetThemeProvider();
-  if (!tp)
-    NOTREACHED() << "Unable to get theme provider";
+  int offset = GetMirroredX() + background_offset_.x();
+  ui::ThemeProvider* tp = GetThemeProvider();
+  DCHECK(tp) << "Unable to get theme provider";
 
   SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
 
-  TabImage* tab_image = &tab_active;
-  TabImage* alpha = &tab_alpha;
+  TabImage* tab_image = &tab_active_;
+  TabImage* alpha = &tab_alpha_;
 
   // Draw left edge.
   SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
@@ -594,8 +580,8 @@
   const ui::SlideAnimation* hover_slide = hover_animation();
   int hover_alpha = 0;
   if (hover_slide) {
-    hover_alpha =
-        static_cast<int>(255 * kHoverOpacity * hover_slide->GetCurrentValue());
+    hover_alpha = static_cast<int>(255 * kHoverSlideOpacity *
+                                   hover_slide->GetCurrentValue());
   }
   colors[0] = SkColorSetARGB(hover_alpha, 255, 255, 255);
   colors[1] = SkColorSetARGB(0, 255, 255, 255);
@@ -655,22 +641,34 @@
 // Tab, private:
 
 // static
+void Tab::InitTabResources() {
+  static bool initialized = false;
+  if (initialized)
+    return;
+
+  initialized = true;
+
+  // Load the tab images once now, and maybe again later if the theme changes.
+  LoadTabImages();
+}
+
+// static
 void Tab::LoadTabImages() {
   // We're not letting people override tab images just yet.
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
 
-  tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
-  tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
+  tab_alpha_.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
+  tab_alpha_.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
 
-  tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
-  tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
-  tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
-  tab_active.l_width = tab_active.image_l->width();
-  tab_active.r_width = tab_active.image_r->width();
+  tab_active_.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
+  tab_active_.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
+  tab_active_.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
+  tab_active_.l_width = tab_active_.image_l->width();
+  tab_active_.r_width = tab_active_.image_r->width();
 
-  tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
-  tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
-  tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
-  tab_inactive.l_width = tab_inactive.image_l->width();
-  tab_inactive.r_width = tab_inactive.image_r->width();
+  tab_inactive_.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
+  tab_inactive_.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
+  tab_inactive_.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
+  tab_inactive_.l_width = tab_inactive_.image_l->width();
+  tab_inactive_.r_width = tab_inactive_.image_r->width();
 }
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 743f818..f76615e 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "base/scoped_ptr.h"
-#include "chrome/browser/views/tabs/base_tab.h"
-#include "gfx/point.h"
+#include "chrome/browser/ui/views/tabs/base_tab.h"
+#include "ui/gfx/point.h"
 
 namespace ui {
 class MultiAnimation;
@@ -38,14 +38,10 @@
 
   // Set the background offset used to match the image in the inactive tab
   // to the frame image.
-  void SetBackgroundOffset(const gfx::Point& offset) {
+  void set_background_offset(const gfx::Point& offset) {
     background_offset_ = offset;
   }
 
-  // Paints the icon. Most of the time you'll want to invoke Paint directly, but
-  // in certain situations this invoked outside of Paint.
-  void PaintIcon(gfx::Canvas* canvas);
-
   // Returns the minimum possible size of a single unselected Tab.
   static gfx::Size GetMinimumUnselectedSize();
   // Returns the minimum possible size of a selected Tab. Selected tabs must
@@ -59,9 +55,6 @@
   // Returns the width for mini-tabs. Mini-tabs always have this width.
   static int GetMiniWidth();
 
-  // Loads the images to be used for the tab background.
-  static void LoadTabImages();
-
  protected:
   virtual const gfx::Rect& title_bounds() const { return title_bounds_; }
 
@@ -84,6 +77,7 @@
   void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas);
   void PaintInactiveTabBackground(gfx::Canvas* canvas);
   void PaintActiveTabBackground(gfx::Canvas* canvas);
+  void PaintIcon(gfx::Canvas* canvas);
   SkBitmap DrawHoverGlowBitmap(int width, int height);
 
   // Returns the number of favicon-size elements that can fit in the tab's
@@ -101,6 +95,12 @@
   // mini tab title change and pulsing.
   double GetThrobValue();
 
+  // Performs a one-time initialization of static resources such as tab images.
+  static void InitTabResources();
+
+  // Loads the images to be used for the tab background.
+  static void LoadTabImages();
+
   // The bounds of various sections of the display.
   gfx::Rect favicon_bounds_;
   gfx::Rect title_bounds_;
@@ -122,9 +122,9 @@
     int r_width;
     int y_offset;
   };
-  static TabImage tab_active;
-  static TabImage tab_inactive;
-  static TabImage tab_alpha;
+  static TabImage tab_active_;
+  static TabImage tab_inactive_;
+  static TabImage tab_alpha_;
 
   // Whether we're showing the icon. It is cached so that we can detect when it
   // changes and layout appropriately.
diff --git a/chrome/browser/ui/views/tabs/tab_dragging_test.cc b/chrome/browser/ui/views/tabs/tab_dragging_test.cc
index dc433ad..d39b3ff 100644
--- a/chrome/browser/ui/views/tabs/tab_dragging_test.cc
+++ b/chrome/browser/ui/views/tabs/tab_dragging_test.cc
@@ -7,16 +7,14 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/browser_proxy.h"
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/net_util.h"
-#include "views/event.h"
+#include "ui/gfx/rect.h"
+#include "views/events/event.h"
 
 #if defined(OS_LINUX)
 // This test doesn't make sense on chromeos as chromeos doesn't allow dragging
@@ -136,7 +134,7 @@
                    bounds1.y() + bounds1.height() / 2);
   gfx::Point end(start.x() + 2 * bounds1.width() / 3, start.y());
   ASSERT_TRUE(browser->SimulateDrag(start, end,
-                                    views::Event::EF_LEFT_BUTTON_DOWN,
+                                    ui::EF_LEFT_BUTTON_DOWN,
                                     false));
 
   // Now check for expected results.
@@ -236,7 +234,7 @@
                      bounds3.width() / 2,
                  start.y());
   ASSERT_TRUE(browser->SimulateDrag(start, end,
-                                    views::Event::EF_LEFT_BUTTON_DOWN,
+                                    ui::EF_LEFT_BUTTON_DOWN,
                                     false));
 
   // Now check for expected results.
@@ -346,7 +344,7 @@
   // Simulate drag with 'true' as the last parameter. This will interrupt
   // in-flight with Escape.
   ASSERT_TRUE(browser->SimulateDrag(start, end,
-                                    views::Event::EF_LEFT_BUTTON_DOWN,
+                                    ui::EF_LEFT_BUTTON_DOWN,
                                     true));
 
   // Now check for expected results.
@@ -467,7 +465,7 @@
 
   // Simulate tab drag.
   ASSERT_TRUE(browser->SimulateDrag(start, end,
-                                    views::Event::EF_LEFT_BUTTON_DOWN,
+                                    ui::EF_LEFT_BUTTON_DOWN,
                                     false));
 
   // Now, first make sure that the old window has only two tabs remaining.
diff --git a/chrome/browser/ui/views/tabs/tab_renderer_data.h b/chrome/browser/ui/views/tabs/tab_renderer_data.h
index 3099e38..ce6b338 100644
--- a/chrome/browser/ui/views/tabs/tab_renderer_data.h
+++ b/chrome/browser/ui/views/tabs/tab_renderer_data.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_RENDERER_DATA_H_
 #pragma once
 
+#include "base/process_util.h"
 #include "base/string16.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -23,7 +24,7 @@
   TabRendererData()
       : network_state(NETWORK_STATE_NONE),
         loading(false),
-        crashed(false),
+        crashed_status(base::TERMINATION_STATUS_STILL_RUNNING),
         off_the_record(false),
         show_icon(true),
         mini(false),
@@ -31,11 +32,20 @@
         app(false) {
   }
 
+  // This interprets the crashed status to decide whether or not this
+  // render data represents a tab that is "crashed" (i.e. the render
+  // process died unexpectedly).
+  bool IsCrashed() const {
+    return (crashed_status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ||
+            crashed_status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
+            crashed_status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION);
+  }
+
   SkBitmap favicon;
   NetworkState network_state;
   string16 title;
   bool loading;
-  bool crashed;
+  base::TerminationStatus crashed_status;
   bool off_the_record;
   bool show_icon;
   bool mini;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index f0c6017..84d7517 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1,35 +1,35 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
 
-#include "app/drag_drop_types.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include <algorithm>
+
 #include "base/compiler_specific.h"
 #include "base/stl_util-inl.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
-#include "chrome/common/pref_names.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/path.h"
-#include "gfx/size.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/animation/animation_container.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/size.h"
 #include "views/controls/image_view.h"
 #include "views/widget/default_theme_provider.h"
 #include "views/window/non_client_view.h"
 #include "views/window/window.h"
 
 #if defined(OS_WIN)
-#include "app/win/win_util.h"
+#include "views/widget/monitor_win.h"
 #include "views/widget/widget_win.h"
 #elif defined(OS_LINUX)
 #include "views/widget/widget_gtk.h"
@@ -149,7 +149,7 @@
   }
   LoadNewTabButtonImage();
   newtab_button_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)));
+      l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB));
   AddChildView(newtab_button_);
 }
 
@@ -164,13 +164,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TabStrip, BaseTabStrip implementation:
 
-int TabStrip::GetPreferredHeight() {
-  return GetPreferredSize().height();
-}
-
 void TabStrip::SetBackgroundOffset(const gfx::Point& offset) {
   for (int i = 0; i < tab_count(); ++i)
-    GetTabAtTabDataIndex(i)->SetBackgroundOffset(offset);
+    GetTabAtTabDataIndex(i)->set_background_offset(offset);
 }
 
 bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) {
@@ -310,7 +306,7 @@
 }
 
 // Overridden to support automation. See automation_proxy_uitest.cc.
-views::View* TabStrip::GetViewByID(int view_id) const {
+const views::View* TabStrip::GetViewByID(int view_id) const {
   if (tab_count() > 0) {
     if (view_id == VIEW_ID_TAB_LAST) {
       return GetTabAtTabDataIndex(tab_count() - 1);
@@ -349,7 +345,7 @@
 
 int TabStrip::OnPerformDrop(const DropTargetEvent& event) {
   if (!drop_info_.get())
-    return DragDropTypes::DRAG_NONE;
+    return ui::DragDropTypes::DRAG_NONE;
 
   const int drop_index = drop_info_->drop_index;
   const bool drop_before = drop_info_->drop_before;
@@ -359,8 +355,8 @@
 
   GURL url;
   std::wstring title;
-  if (!event.GetData().GetURLAndTitle(&url, &title) || !url.is_valid())
-    return DragDropTypes::DRAG_NONE;
+  if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid())
+    return ui::DragDropTypes::DRAG_NONE;
 
   controller()->PerformDrop(drop_before, drop_index, url);
 
@@ -429,13 +425,6 @@
   AnimateToIdealBounds();
 }
 
-void TabStrip::StartMoveTabAnimation() {
-  PrepareForAnimation();
-
-  GenerateIdealBounds();
-  AnimateToIdealBounds();
-}
-
 void TabStrip::AnimateToIdealBounds() {
   for (int i = 0; i < tab_count(); ++i) {
     Tab* tab = GetTabAtTabDataIndex(i);
@@ -453,7 +442,7 @@
 void TabStrip::DoLayout() {
   BaseTabStrip::DoLayout();
 
-  newtab_button_->SetBounds(newtab_button_bounds_);
+  newtab_button_->SetBoundsRect(newtab_button_bounds_);
 }
 
 void TabStrip::ViewHierarchyChanged(bool is_add,
@@ -498,7 +487,7 @@
 }
 
 void TabStrip::LoadNewTabButtonImage() {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
 
   // If we don't have a theme provider yet, it means we do not have a
   // root view, and are therefore in a test.
@@ -678,7 +667,7 @@
   }
 
   // Mirror the center point if necessary.
-  center_x = MirroredXCoordinateInsideView(center_x);
+  center_x = GetMirroredXInView(center_x);
 
   // Determine the screen bounds.
   gfx::Point drop_loc(center_x - drop_indicator_width / 2,
@@ -689,7 +678,7 @@
 
   // If the rect doesn't fit on the monitor, push the arrow to the bottom.
 #if defined(OS_WIN)
-  gfx::Rect monitor_bounds = app::win::GetMonitorBoundsForRect(drop_bounds);
+  gfx::Rect monitor_bounds = views::GetMonitorBoundsForRect(drop_bounds);
   *is_beneath = (monitor_bounds.IsEmpty() ||
                  !monitor_bounds.Contains(drop_bounds));
 #else
@@ -706,7 +695,7 @@
   // If the UI layout is right-to-left, we need to mirror the mouse
   // coordinates since we calculate the drop index based on the
   // original (and therefore non-mirrored) positions of the tabs.
-  const int x = MirroredXCoordinateInsideView(event.x());
+  const int x = GetMirroredXInView(event.x());
   // We don't allow replacing the urls of mini-tabs.
   for (int i = GetMiniTabCount(); i < tab_count(); ++i) {
     Tab* tab = GetTabAtTabDataIndex(i);
@@ -769,12 +758,12 @@
 }
 
 int TabStrip::GetDropEffect(const views::DropTargetEvent& event) {
-  const int source_ops = event.GetSourceOperations();
-  if (source_ops & DragDropTypes::DRAG_COPY)
-    return DragDropTypes::DRAG_COPY;
-  if (source_ops & DragDropTypes::DRAG_LINK)
-    return DragDropTypes::DRAG_LINK;
-  return DragDropTypes::DRAG_MOVE;
+  const int source_ops = event.source_operations();
+  if (source_ops & ui::DragDropTypes::DRAG_COPY)
+    return ui::DragDropTypes::DRAG_COPY;
+  if (source_ops & ui::DragDropTypes::DRAG_LINK)
+    return ui::DragDropTypes::DRAG_LINK;
+  return ui::DragDropTypes::DRAG_MOVE;
 }
 
 // static
@@ -942,18 +931,6 @@
                                          true);
 }
 
-void TabStrip::StopAnimating(bool layout) {
-  if (!IsAnimating())
-    return;
-
-  bounds_animator().Cancel();
-
-  DCHECK(!IsAnimating());
-
-  if (layout)
-    DoLayout();
-}
-
 int TabStrip::GetMiniTabCount() const {
   int mini_count = 0;
   for (int i = 0; i < tab_count(); ++i) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index ca2aed3..82f3f35 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,10 +8,10 @@
 
 #include "base/ref_counted.h"
 #include "base/timer.h"
-#include "chrome/browser/views/tabs/base_tab_strip.h"
-#include "gfx/point.h"
-#include "gfx/rect.h"
+#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
 #include "ui/base/animation/animation_container.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 #include "views/controls/button/image_button.h"
 #include "views/mouse_watcher.h"
 
@@ -56,7 +56,6 @@
   virtual void MouseMovedOutOfView();
 
   // BaseTabStrip implementation:
-  virtual int GetPreferredHeight();
   virtual void SetBackgroundOffset(const gfx::Point& offset);
   virtual bool IsPositionInWindowCaption(const gfx::Point& point);
   virtual void PrepareForCloseAt(int model_index);
@@ -69,7 +68,7 @@
 
   // views::View overrides:
   virtual void PaintChildren(gfx::Canvas* canvas);
-  virtual views::View* GetViewByID(int id) const;
+  virtual const views::View* GetViewByID(int id) const;
   virtual gfx::Size GetPreferredSize();
   // NOTE: the drag and drop methods are invoked from FrameView. This is done to
   // allow for a drop region that extends outside the bounds of the TabStrip.
@@ -85,7 +84,6 @@
   // BaseTabStrip overrides:
   virtual BaseTab* CreateTab();
   virtual void StartInsertTabAnimation(int model_index, bool foreground);
-  virtual void StartMoveTabAnimation();
   virtual void AnimateToIdealBounds();
   virtual bool ShouldHighlightCloseButtonAfterRemove();
   virtual void DoLayout();
@@ -220,10 +218,6 @@
   void StartMiniTabAnimation();
   void StartMouseInitiatedRemoveTabAnimation(int model_index);
 
-  // Stops any ongoing animations. If |layout| is true and an animation is
-  // ongoing this does a layout.
-  virtual void StopAnimating(bool layout);
-
   // Calculates the available width for tabs, assuming a Tab is to be closed.
   int GetAvailableWidthForTabs(Tab* last_tab) const;
 
@@ -261,7 +255,7 @@
 
   // The size of the new tab button must be hardcoded because we need to be
   // able to lay it out before we are able to get its image from the
-  // ThemeProvider.  It also makes sense to do this, because the size of the
+  // ui::ThemeProvider.  It also makes sense to do this, because the size of the
   // new tab button should not need to be calculated dynamically.
   static const int kNewTabButtonWidth = 28;
   static const int kNewTabButtonHeight = 18;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_factory.cc b/chrome/browser/ui/views/tabs/tab_strip_factory.cc
new file mode 100644
index 0000000..d15fb81
--- /dev/null
+++ b/chrome/browser/ui/views/tabs/tab_strip_factory.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/tabs/tab_strip_factory.h"
+
+#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
+#include "chrome/browser/ui/views/tabs/side_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
+
+// This default implementation of CreateTabStrip creates a TabStrip or a
+// SideTabStrip, depending on whether we are using vertical tabs.
+BaseTabStrip* CreateTabStrip(BrowserTabStripController* tabstrip_controller,
+                             bool use_vertical_tabs) {
+  if (use_vertical_tabs)
+    return new SideTabStrip(tabstrip_controller);
+  else
+    return new TabStrip(tabstrip_controller);
+}
+
diff --git a/chrome/browser/ui/views/tabs/tab_strip_factory.h b/chrome/browser/ui/views/tabs/tab_strip_factory.h
new file mode 100644
index 0000000..1438e34
--- /dev/null
+++ b/chrome/browser/ui/views/tabs/tab_strip_factory.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_FACTORY_H_
+#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_FACTORY_H_
+#pragma once
+
+class BaseTabStrip;
+class BrowserTabStripController;
+
+BaseTabStrip* CreateTabStrip(BrowserTabStripController* tabstrip_controller,
+                             bool use_vertical_tabs);
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_FACTORY_H_
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc
index a80d6de..9b2c6c7 100644
--- a/chrome/browser/ui/views/task_manager_view.cc
+++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/task_manager/task_manager.h"
 
-#include "app/l10n_util.h"
-#include "app/table_model_observer.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/metrics/stats_table.h"
@@ -16,12 +14,14 @@
 #include "chrome/browser/browser_window.h"
 #include "chrome/browser/memory_purger.h"
 #include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model_observer.h"
 #include "views/accelerator.h"
 #include "views/background.h"
 #include "views/controls/button/native_button.h"
@@ -29,7 +29,7 @@
 #include "views/controls/menu/menu.h"
 #include "views/controls/table/group_table_view.h"
 #include "views/controls/table/table_view_observer.h"
-#include "views/standard_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 #include "views/window/dialog_delegate.h"
 #include "views/window/window.h"
@@ -38,6 +38,10 @@
 static const int kDefaultWidth = 460;
 static const int kDefaultHeight = 270;
 
+// Yellow highlight used when highlighting background resources.
+static const SkColor kBackgroundResourceHighlight =
+    SkColorSetRGB(0xff,0xf1,0xcd);
+
 namespace {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -62,7 +66,7 @@
   string16 GetText(int row, int column) OVERRIDE;
   SkBitmap GetIcon(int row) OVERRIDE;
   void GetGroupRangeForItem(int item, views::GroupRange* range) OVERRIDE;
-  void SetObserver(TableModelObserver* observer) OVERRIDE;
+  void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
   virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE;
 
   // TaskManagerModelObserver.
@@ -71,9 +75,12 @@
   virtual void OnItemsAdded(int start, int length);
   virtual void OnItemsRemoved(int start, int length);
 
+  // Returns true if resource corresponding to |row| is a background resource.
+  bool IsBackgroundResource(int row);
+
  private:
   TaskManagerModel* model_;
-  TableModelObserver* observer_;
+  ui::TableModelObserver* observer_;
 };
 
 int TaskManagerTableModel::RowCount() {
@@ -159,7 +166,7 @@
   range->length = range_pair.second;
 }
 
-void TaskManagerTableModel::SetObserver(TableModelObserver* observer) {
+void TaskManagerTableModel::SetObserver(ui::TableModelObserver* observer) {
   observer_ = observer;
 }
 
@@ -181,10 +188,20 @@
   if (observer_)
     observer_->OnItemsAdded(start, length);
   // There's a bug in the Windows ListView where inserting items with groups
-  // enabled puts them in the wrong position, so we just rebuild the list view
-  // in this case.
-  // (see: http://connect.microsoft.com/VisualStudio/feedback/details/115345/)
-  OnModelChanged();
+  // enabled puts them in the wrong position, so we will need to rebuild the
+  // list view in this case.
+  // (see: http://connect.microsoft.com/VisualStudio/feedback/details/115345/).
+  //
+  // Turns out, forcing a list view rebuild causes http://crbug.com/69391
+  // because items are added to the ListView one-at-a-time when initially
+  // displaying the TaskManager, resulting in many ListView rebuilds. So we are
+  // no longer forcing a rebuild for now because the current UI doesn't use
+  // groups - if we are going to add groups in the upcoming TaskManager UI
+  // revamp, we'll need to re-enable this call to OnModelChanged() and also add
+  // code to avoid doing multiple rebuilds on startup (maybe just generate a
+  // single OnModelChanged() call after the initial population).
+
+  // OnModelChanged();
 }
 
 void TaskManagerTableModel::OnItemsRemoved(int start, int length) {
@@ -196,6 +213,44 @@
   OnModelChanged();
 }
 
+bool TaskManagerTableModel::IsBackgroundResource(int row) {
+  return model_->IsBackgroundResource(row);
+}
+
+// Thin wrapper around GroupTableView to enable setting the background
+// resource highlight color.
+class BackgroundColorGroupTableView : public views::GroupTableView {
+ public:
+  BackgroundColorGroupTableView(TaskManagerTableModel* model,
+                                std::vector<ui::TableColumn> columns,
+                                bool highlight_background_resources)
+      : views::GroupTableView(model, columns, views::ICON_AND_TEXT,
+                              false, true, true, true),
+        model_(model) {
+    SetCustomColorsEnabled(highlight_background_resources);
+  }
+
+  virtual ~BackgroundColorGroupTableView() {}
+
+ private:
+  virtual bool GetCellColors(int model_row,
+                             int column,
+                             ItemColor* foreground,
+                             ItemColor* background,
+                             LOGFONT* logfont) {
+    if (!model_->IsBackgroundResource(model_row))
+      return false;
+
+    // Render background resources with a yellow highlight.
+    background->color_is_set = true;
+    background->color = kBackgroundResourceHighlight;
+    foreground->color_is_set = false;
+    return true;
+  }
+
+  TaskManagerTableModel* model_;
+};
+
 // The Task manager UI container.
 class TaskManagerView : public views::View,
                         public views::ButtonListener,
@@ -205,11 +260,13 @@
                         public views::ContextMenuController,
                         public views::Menu::Delegate {
  public:
-  TaskManagerView();
+  explicit TaskManagerView(bool highlight_background_resources);
   virtual ~TaskManagerView();
 
-  // Shows the Task manager window, or re-activates an existing one.
-  static void Show();
+  // Shows the Task manager window, or re-activates an existing one. If
+  // |highlight_background_resources| is true, highlights the background
+  // resources in the resource display.
+  static void Show(bool highlight_background_resources);
 
   // views::View
   virtual void Layout();
@@ -233,7 +290,7 @@
   // views::TableViewObserver implementation.
   virtual void OnSelectionChanged();
   virtual void OnDoubleClick();
-  virtual void OnKeyDown(app::KeyboardCode keycode);
+  virtual void OnKeyDown(ui::KeyboardCode keycode);
 
   // views::LinkController implementation.
   virtual void LinkActivated(views::Link* source, int event_flags);
@@ -275,13 +332,16 @@
   TaskManagerModel* model_;
 
   // all possible columns, not necessarily visible
-  std::vector<TableColumn> columns_;
+  std::vector<ui::TableColumn> columns_;
 
   scoped_ptr<TaskManagerTableModel> table_model_;
 
   // True when the Task Manager window should be shown on top of other windows.
   bool is_always_on_top_;
 
+  // True when the Task Manager should highlight background resources.
+  bool highlight_background_resources_;
+
   // We need to own the text of the menu, the Windows API does not copy it.
   std::wstring always_on_top_menu_text_;
 
@@ -296,11 +356,12 @@
 TaskManagerView* TaskManagerView::instance_ = NULL;
 
 
-TaskManagerView::TaskManagerView()
+TaskManagerView::TaskManagerView(bool highlight_background_resources)
     : purge_memory_button_(NULL),
       task_manager_(TaskManager::GetInstance()),
       model_(TaskManager::GetInstance()->model()),
-      is_always_on_top_(false) {
+      is_always_on_top_(false),
+      highlight_background_resources_(highlight_background_resources) {
   Init();
 }
 
@@ -313,47 +374,48 @@
   table_model_.reset(new TaskManagerTableModel(model_));
 
   // Page column has no header label.
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_PAGE_COLUMN,
-                                 TableColumn::LEFT, -1, 1));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PAGE_COLUMN,
+                                     ui::TableColumn::LEFT, -1, 1));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_CPU_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_CPU_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_NET_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_NET_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(
+      IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN,
+      ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(
+      IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN,
+      ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
-  columns_.push_back(TableColumn(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN,
-                                 TableColumn::RIGHT, -1, 0));
+  columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN,
+                                     ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
   columns_.push_back(
-      TableColumn(IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN,
-                  TableColumn::RIGHT, -1, 0));
+      ui::TableColumn(IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN,
+                      ui::TableColumn::RIGHT, -1, 0));
   columns_.back().sortable = true;
 
-  tab_table_ = new views::GroupTableView(table_model_.get(), columns_,
-                                         views::ICON_AND_TEXT, false, true,
-                                         true, true);
+  tab_table_ = new BackgroundColorGroupTableView(
+      table_model_.get(), columns_, highlight_background_resources_);
 
   // Hide some columns by default
   tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, false);
@@ -384,7 +446,7 @@
   }
   kill_button_ = new views::NativeButton(
       this, UTF16ToWide(l10n_util::GetStringUTF16(IDS_TASK_MANAGER_KILL)));
-  kill_button_->AddAccelerator(views::Accelerator(app::VKEY_E,
+  kill_button_->AddAccelerator(views::Accelerator(ui::VKEY_E,
                                                   false, false, false));
   kill_button_->SetAccessibleKeyboardShortcut(L"E");
   about_memory_link_ = new views::Link(UTF16ToWide(
@@ -408,7 +470,8 @@
         // stat names not in the string table would be filtered out.
         // TODO(erikkay): Width is hard-coded right now, so many column
         // names are clipped.
-        TableColumn col(i, ASCIIToUTF16(row), TableColumn::RIGHT, 90, 0);
+        ui::TableColumn col(i, ASCIIToUTF16(row), ui::TableColumn::RIGHT, 90,
+                            0);
         col.sortable = true;
         columns_.push_back(col);
         tab_table_->AddColumn(col);
@@ -455,8 +518,9 @@
                         height() - 2 * kPanelVertMargin - prefered_height);
 
   // y-coordinate of button top left.
-  gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
-  int y_buttons = parent_bounds.bottom() - prefered_height - kButtonVEdgeMargin;
+  gfx::Rect parent_bounds = parent()->GetContentsBounds();
+  int y_buttons =
+      parent_bounds.bottom() - prefered_height - views::kButtonVEdgeMargin;
 
   kill_button_->SetBounds(x() + width() - prefered_width - kPanelHorizMargin,
                           y_buttons,
@@ -466,7 +530,8 @@
   if (purge_memory_button_) {
     size = purge_memory_button_->GetPreferredSize();
     purge_memory_button_->SetBounds(
-        kill_button_->x() - size.width() - kUnrelatedControlHorizontalSpacing,
+        kill_button_->x() - size.width() -
+            views::kUnrelatedControlHorizontalSpacing,
         y_buttons, size.width(), size.height());
   }
 
@@ -488,22 +553,27 @@
 }
 
 // static
-void TaskManagerView::Show() {
+void TaskManagerView::Show(bool highlight_background_resources) {
   if (instance_) {
-    // If there's a Task manager window open already, just activate it.
-    instance_->window()->Activate();
-  } else {
-    instance_ = new TaskManagerView;
-    views::Window::CreateChromeWindow(NULL, gfx::Rect(), instance_);
-    instance_->InitAlwaysOnTopState();
-    instance_->model_->StartUpdating();
-    instance_->window()->Show();
-
-    // Set the initial focus to the list of tasks.
-    views::FocusManager* focus_manager = instance_->GetFocusManager();
-    if (focus_manager)
-      focus_manager->SetFocusedView(instance_->tab_table_);
+    if (instance_->highlight_background_resources_ !=
+        highlight_background_resources) {
+      instance_->window()->Close();
+    } else {
+      // If there's a Task manager window open already, just activate it.
+      instance_->window()->Activate();
+      return;
+    }
   }
+  instance_ = new TaskManagerView(highlight_background_resources);
+  views::Window::CreateChromeWindow(NULL, gfx::Rect(), instance_);
+  instance_->InitAlwaysOnTopState();
+  instance_->model_->StartUpdating();
+  instance_->window()->Show();
+
+  // Set the initial focus to the list of tasks.
+  views::FocusManager* focus_manager = instance_->GetFocusManager();
+  if (focus_manager)
+    focus_manager->SetFocusedView(instance_->tab_table_);
 }
 
 // ButtonListener implementation.
@@ -600,8 +670,8 @@
   ActivateFocusedTab();
 }
 
-void TaskManagerView::OnKeyDown(app::KeyboardCode keycode) {
-  if (keycode == app::VKEY_RETURN)
+void TaskManagerView::OnKeyDown(ui::KeyboardCode keycode) {
+  if (keycode == ui::VKEY_RETURN)
     ActivateFocusedTab();
 }
 
@@ -617,7 +687,7 @@
   UpdateStatsCounters();
   scoped_ptr<views::Menu> menu(views::Menu::Create(
       this, views::Menu::TOPLEFT, source->GetWidget()->GetNativeView()));
-  for (std::vector<TableColumn>::iterator i =
+  for (std::vector<ui::TableColumn>::iterator i =
        columns_.begin(); i != columns_.end(); ++i) {
     menu->AppendMenuItem(i->id, l10n_util::GetStringUTF16(i->id),
         views::Menu::CHECKBOX);
@@ -699,7 +769,11 @@
 
 // Declared in browser_dialogs.h so others don't need to depend on our header.
 void ShowTaskManager() {
-  TaskManagerView::Show();
+  TaskManagerView::Show(false);
+}
+
+void ShowBackgroundPages() {
+  TaskManagerView::Show(true);
 }
 
 }  // namespace browser
diff --git a/chrome/browser/ui/views/textfield_views.cc b/chrome/browser/ui/views/textfield_views.cc
index f15be68..cf57a0d 100644
--- a/chrome/browser/ui/views/textfield_views.cc
+++ b/chrome/browser/ui/views/textfield_views.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/textfield_views.h"
+#include "chrome/browser/ui/views/textfield_views.h"
 
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
@@ -12,12 +12,12 @@
 TextfieldViews::TextfieldViews() : DOMView() {}
 
 std::wstring TextfieldViews::GetText() {
-  TextfieldsUI* textfields_ui = dom_ui();
+  TextfieldsUI* textfields_ui = web_ui();
   return (textfields_ui) ? textfields_ui->text() : std::wstring();
 }
 
 void TextfieldViews::SetText(const std::wstring& text) {
-  TextfieldsUI* textfields_ui = dom_ui();
+  TextfieldsUI* textfields_ui = web_ui();
   if (textfields_ui) {
     StringValue text_value(WideToUTF16(text));
     textfields_ui->CallJavascriptFunction(L"setTextfieldValue", text_value);
@@ -25,10 +25,10 @@
   SchedulePaint();
 }
 
-TextfieldsUI* TextfieldViews::dom_ui() {
-  TextfieldsUI* dom_ui = NULL;
-  if (tab_contents_.get() && tab_contents_->dom_ui()) {
-    dom_ui = static_cast<TextfieldsUI*>(tab_contents_->dom_ui());
+TextfieldsUI* TextfieldViews::web_ui() {
+  TextfieldsUI* web_ui = NULL;
+  if (tab_contents_.get() && tab_contents_->web_ui()) {
+    web_ui = static_cast<TextfieldsUI*>(tab_contents_->web_ui());
   }
-  return dom_ui;
+  return web_ui;
 }
diff --git a/chrome/browser/ui/views/textfield_views.h b/chrome/browser/ui/views/textfield_views.h
index 10fe0a1..16ce10b 100644
--- a/chrome/browser/ui/views/textfield_views.h
+++ b/chrome/browser/ui/views/textfield_views.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,7 @@
 
 #include <string>
 
-#include "chrome/browser/views/dom_view.h"
+#include "chrome/browser/ui/views/dom_view.h"
 
 class TextfieldsUI;
 
@@ -19,7 +19,7 @@
   void SetText(const std::wstring& text);
 
  private:
-  TextfieldsUI* dom_ui();
+  TextfieldsUI* web_ui();
 
   DISALLOW_COPY_AND_ASSIGN(TextfieldViews);
 };
diff --git a/chrome/browser/ui/views/theme_background.cc b/chrome/browser/ui/views/theme_background.cc
index b2320fc..dabd9ae 100644
--- a/chrome/browser/ui/views/theme_background.cc
+++ b/chrome/browser/ui/views/theme_background.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/theme_background.h"
+#include "chrome/browser/ui/views/theme_background.h"
 
-#include "app/resource_bundle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/browser_theme_provider.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "gfx/canvas.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "grit/app_resources.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
 #include "views/view.h"
 
 ThemeBackground::ThemeBackground(BrowserView* browser_view)
@@ -30,7 +30,7 @@
       background = rb.GetBitmapNamed(IDR_THEME_FRAME_INACTIVE);
   } else {
     Profile* profile = browser_view_->browser()->profile();
-    ThemeProvider* theme = profile->GetThemeProvider();
+    ui::ThemeProvider* theme = profile->GetThemeProvider();
     if (browser_view_->IsActive()) {
       background = theme->GetBitmapNamed(
           profile->IsOffTheRecord() ?
diff --git a/chrome/browser/ui/views/theme_helpers.cc b/chrome/browser/ui/views/theme_helpers.cc
index 41f6db5..4b0f6b3 100644
--- a/chrome/browser/ui/views/theme_helpers.cc
+++ b/chrome/browser/ui/views/theme_helpers.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/theme_helpers.h"
+#include "chrome/browser/ui/views/theme_helpers.h"
 
 #include <atlbase.h>
 #include <atlapp.h>
 #include <atltheme.h>
 
 #include "base/logging.h"
-#include "gfx/canvas_skia.h"
 #include "skia/ext/bitmap_platform_device_win.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/gfx/canvas_skia.h"
 
 void GetRebarGradientColors(int width, int x1, int x2,
                             SkColor* c1, SkColor* c2) {
diff --git a/chrome/browser/ui/views/theme_install_bubble_view.cc b/chrome/browser/ui/views/theme_install_bubble_view.cc
index 157e7fd..f28e848 100644
--- a/chrome/browser/ui/views/theme_install_bubble_view.cc
+++ b/chrome/browser/ui/views/theme_install_bubble_view.cc
@@ -1,16 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/theme_install_bubble_view.h"
+#include "chrome/browser/ui/views/theme_install_bubble_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
 #include "views/widget/widget.h"
 
 namespace {
@@ -132,10 +132,10 @@
 
   int text_width = views::Label::font().GetStringWidth(text_);
   gfx::Rect body_bounds(kTextHorizPadding / 2, 0, text_width, height());
-  body_bounds.set_x(MirroredLeftPointForRect(body_bounds));
+  body_bounds.set_x(GetMirroredXForRect(body_bounds));
 
   SkColor text_color = SK_ColorWHITE;
-  canvas->DrawStringInt(UTF16ToWideHack(text_),
+  canvas->DrawStringInt(text_,
                         views::Label::font(),
                         text_color,
                         body_bounds.x(),
diff --git a/chrome/browser/ui/views/theme_install_bubble_view.h b/chrome/browser/ui/views/theme_install_bubble_view.h
index 4bd070f..dc81616 100644
--- a/chrome/browser/ui/views/theme_install_bubble_view.h
+++ b/chrome/browser/ui/views/theme_install_bubble_view.h
@@ -9,7 +9,7 @@
 #include "base/string16.h"
 #include "chrome/common/notification_observer.h"
 #include "chrome/common/notification_registrar.h"
-#include "gfx/canvas.h"
+#include "ui/gfx/canvas.h"
 #include "views/controls/label.h"
 
 class TabContents;
diff --git a/chrome/browser/ui/views/toolbar_view.cc b/chrome/browser/ui/views/toolbar_view.cc
index 3ebeef9..4871177 100644
--- a/chrome/browser/ui/views/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar_view.cc
@@ -1,11 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/i18n/number_formatting.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -25,12 +23,14 @@
 #include "chrome/browser/upgrade_detector.h"
 #include "chrome/common/notification_service.h"
 #include "chrome/common/pref_names.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/skbitmap_operations.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/skbitmap_operations.h"
 #include "views/controls/button/button_dropdown.h"
 #include "views/focus/view_storage.h"
 #include "views/widget/tooltip_manager.h"
@@ -43,7 +43,7 @@
 #include "chrome/browser/chromeos/dom_ui/wrench_menu_ui.h"
 #include "views/controls/menu/menu_2.h"
 #endif
-#include "chrome/browser/views/wrench_menu.h"
+#include "chrome/browser/ui/views/wrench_menu.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/enumerate_modules_model_win.h"
@@ -146,25 +146,23 @@
   }
 #endif
   back_ = new views::ButtonDropDown(this, back_menu_model_.get());
-  back_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN |
-                                     views::Event::EF_MIDDLE_BUTTON_DOWN);
+  back_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN |
+                                     ui::EF_MIDDLE_BUTTON_DOWN);
   back_->set_tag(IDC_BACK);
   back_->SetImageAlignment(views::ImageButton::ALIGN_RIGHT,
                            views::ImageButton::ALIGN_TOP);
   back_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_BACK)));
-  back_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK)));
+  back_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK));
   back_->SetID(VIEW_ID_BACK_BUTTON);
 
   forward_ = new views::ButtonDropDown(this, forward_menu_model_.get());
-  forward_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN |
-                                        views::Event::EF_MIDDLE_BUTTON_DOWN);
+  forward_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN |
+                                        ui::EF_MIDDLE_BUTTON_DOWN);
   forward_->set_tag(IDC_FORWARD);
   forward_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_FORWARD)));
-  forward_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_FORWARD)));
+  forward_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_FORWARD));
   forward_->SetID(VIEW_ID_FORWARD_BUTTON);
 
   // Have to create this before |reload_| as |reload_|'s constructor needs it.
@@ -173,20 +171,19 @@
           LocationBarView::POPUP : LocationBarView::NORMAL);
 
   reload_ = new ReloadButton(location_bar_, browser_);
-  reload_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN |
-                                       views::Event::EF_MIDDLE_BUTTON_DOWN);
+  reload_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN |
+                                       ui::EF_MIDDLE_BUTTON_DOWN);
   reload_->set_tag(IDC_RELOAD);
   reload_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_RELOAD)));
-  reload_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_RELOAD)));
+  reload_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_RELOAD));
   reload_->SetID(VIEW_ID_RELOAD_BUTTON);
 
 #if defined(OS_CHROMEOS)
   feedback_ = new views::ImageButton(this);
   feedback_->set_tag(IDC_FEEDBACK);
-  feedback_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN |
-                                         views::Event::EF_MIDDLE_BUTTON_DOWN);
+  feedback_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN |
+                                         ui::EF_MIDDLE_BUTTON_DOWN);
   feedback_->set_tag(IDC_FEEDBACK);
   feedback_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_FEEDBACK)));
@@ -194,13 +191,12 @@
 #endif
 
   home_ = new views::ImageButton(this);
-  home_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN |
-                                     views::Event::EF_MIDDLE_BUTTON_DOWN);
+  home_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN |
+                                     ui::EF_MIDDLE_BUTTON_DOWN);
   home_->set_tag(IDC_HOME);
   home_->SetTooltipText(
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_HOME)));
-  home_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_HOME)));
+  home_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_HOME));
   home_->SetID(VIEW_ID_HOME_BUTTON);
 
   browser_actions_ = new BrowserActionsContainer(browser_, this);
@@ -208,8 +204,7 @@
   app_menu_ = new views::MenuButton(NULL, std::wstring(), this, false);
   app_menu_->set_border(NULL);
   app_menu_->EnableCanvasFlippingForRTLUI(true);
-  app_menu_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_APP)));
+  app_menu_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_APP));
   app_menu_->SetTooltipText(UTF16ToWide(l10n_util::GetStringFUTF16(
       IDS_APPMENU_TOOLTIP,
       l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))));
@@ -323,7 +318,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ToolbarView, Menu::BaseControllerDelegate overrides:
 
-bool ToolbarView::GetAcceleratorInfo(int id, menus::Accelerator* accel) {
+bool ToolbarView::GetAcceleratorInfo(int id, ui::Accelerator* accel) {
   return GetWidget()->GetAccelerator(id, accel);
 }
 
@@ -345,7 +340,7 @@
     wrench_menu_2_->RunMenuAt(gfx::Point(bounds.right(), bounds.bottom()),
                               views::Menu2::ALIGN_TOPRIGHT);
     // TODO(oshima): nuke this once we made decision about go or no go
-    // for domui menu.
+    // for WebUI menu.
     goto cleanup;
   }
 #endif
@@ -358,7 +353,7 @@
   wrench_menu_->RunMenu(app_menu_);
 
 #if defined(OS_CHROMEOS)
-cleanup:
+ cleanup:
 #endif
   if (destroyed_flag)
     return;
@@ -451,22 +446,22 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// ToolbarView, menus::AcceleratorProvider implementation:
+// ToolbarView, ui::AcceleratorProvider implementation:
 
 bool ToolbarView::GetAcceleratorForCommandId(int command_id,
-    menus::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) {
   // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators
   // anywhere so we need to check for them explicitly here.
   // TODO(cpu) Bug 1109102. Query WebKit land for the actual bindings.
   switch (command_id) {
     case IDC_CUT:
-      *accelerator = views::Accelerator(app::VKEY_X, false, true, false);
+      *accelerator = views::Accelerator(ui::VKEY_X, false, true, false);
       return true;
     case IDC_COPY:
-      *accelerator = views::Accelerator(app::VKEY_C, false, true, false);
+      *accelerator = views::Accelerator(ui::VKEY_C, false, true, false);
       return true;
     case IDC_PASTE:
-      *accelerator = views::Accelerator(app::VKEY_V, false, true, false);
+      *accelerator = views::Accelerator(ui::VKEY_V, false, true, false);
       return true;
   }
   // Else, we retrieve the accelerator information from the frame.
@@ -511,8 +506,9 @@
   if (back_ == NULL)
     return;
 
+  bool maximized = browser_->window() && browser_->window()->IsMaximized();
   if (!IsDisplayModeNormal()) {
-    int edge_width = (browser_->window() && browser_->window()->IsMaximized()) ?
+    int edge_width = maximized ?
         0 : kPopupBackgroundEdge->width();  // See Paint().
     location_bar_->SetBounds(edge_width, PopupTopSpacing(),
         width() - (edge_width * 2), location_bar_->GetPreferredSize().height());
@@ -532,7 +528,7 @@
   //                Layout() in this case.
   //                http://crbug.com/5540
   int back_width = back_->GetPreferredSize().width();
-  if (browser_->window() && browser_->window()->IsMaximized())
+  if (maximized)
     back_->SetBounds(0, child_y, back_width + kEdgeSpacing, child_height);
   else
     back_->SetBounds(kEdgeSpacing, child_y, back_width, child_height);
@@ -579,6 +575,10 @@
   //                required.
   browser_actions_->Layout();
 
+  // Extend the app menu to the screen's right edge in maximized mode just like
+  // we extend the back button to the left edge.
+  if (maximized)
+    app_menu_width += kEdgeSpacing;
 #if defined(OS_CHROMEOS)
   feedback_->SetBounds(browser_actions_->x() + browser_actions_width, child_y,
                        feedback_->GetPreferredSize().width(), child_height);
@@ -662,7 +662,7 @@
 }
 
 void ToolbarView::LoadImages() {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
 
   back_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_BACK));
   back_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_BACK_H));
@@ -722,7 +722,7 @@
 }
 
 SkBitmap ToolbarView::GetAppMenuIcon(views::CustomButton::ButtonState state) {
-  ThemeProvider* tp = GetThemeProvider();
+  ui::ThemeProvider* tp = GetThemeProvider();
 
   int id = 0;
   switch (state) {
diff --git a/chrome/browser/ui/views/toolbar_view.h b/chrome/browser/ui/views/toolbar_view.h
index 8c07dc2..f08e35f 100644
--- a/chrome/browser/ui/views/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar_view.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,6 @@
 
 #include <vector>
 
-#include "app/menus/accelerator.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "chrome/browser/command_updater.h"
@@ -18,6 +17,7 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/reload_button.h"
 #include "ui/base/animation/slide_animation.h"
+#include "ui/base/models/accelerator.h"
 #include "views/controls/button/menu_button.h"
 #include "views/controls/menu/menu.h"
 #include "views/controls/menu/menu_wrapper.h"
@@ -37,7 +37,7 @@
 // The Browser Window's toolbar.
 class ToolbarView : public AccessiblePaneView,
                     public views::ViewMenuDelegate,
-                    public menus::AcceleratorProvider,
+                    public ui::AcceleratorProvider,
                     public LocationBarView::Delegate,
                     public NotificationObserver,
                     public CommandUpdater::CommandObserver,
@@ -90,7 +90,7 @@
   virtual AccessibilityTypes::Role GetAccessibleRole();
 
   // Overridden from Menu::BaseControllerDelegate:
-  virtual bool GetAcceleratorInfo(int id, menus::Accelerator* accel);
+  virtual bool GetAcceleratorInfo(int id, ui::Accelerator* accel);
 
   // Overridden from views::MenuDelegate:
   virtual void RunMenu(views::View* source, const gfx::Point& pt);
@@ -111,9 +111,9 @@
                        const NotificationSource& source,
                        const NotificationDetails& details);
 
-  // Overridden from menus::AcceleratorProvider:
+  // Overridden from ui::AcceleratorProvider:
   virtual bool GetAcceleratorForCommandId(int command_id,
-                                          menus::Accelerator* accelerator);
+                                          ui::Accelerator* accelerator);
 
   // Overridden from views::View:
   virtual gfx::Size GetPreferredSize();
@@ -192,7 +192,7 @@
   Browser* browser_;
 
   // Contents of the profiles menu to populate with profile names.
-  scoped_ptr<menus::SimpleMenuModel> profiles_menu_contents_;
+  scoped_ptr<ui::SimpleMenuModel> profiles_menu_contents_;
 
   // Controls whether or not a home button should be shown on the toolbar.
   BooleanPrefMember show_home_button_;
@@ -201,10 +201,10 @@
   DisplayMode display_mode_;
 
   // The contents of the wrench menu.
-  scoped_ptr<menus::SimpleMenuModel> wrench_menu_model_;
+  scoped_ptr<ui::SimpleMenuModel> wrench_menu_model_;
 
 #if defined(OS_CHROMEOS)
-  // Wrench menu using domui menu.
+  // Wrench menu using WebUI menu.
   // MenuLister is managed by Menu2.
   scoped_ptr<views::Menu2> wrench_menu_2_;
 #endif
diff --git a/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc b/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc
index bb77b8b..02eda65 100644
--- a/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc
+++ b/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
+#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h"
 
 #include "base/logging.h"
 #include "views/focus/focus_manager.h"
@@ -34,7 +34,7 @@
 
   if (event.type == WebKit::WebInputEvent::RawKeyDown) {
     views::Accelerator accelerator(
-        static_cast<app::KeyboardCode>(event.windowsKeyCode),
+        static_cast<ui::KeyboardCode>(event.windowsKeyCode),
         (event.modifiers & NativeWebKeyboardEvent::ShiftKey) ==
             NativeWebKeyboardEvent::ShiftKey,
         (event.modifiers & NativeWebKeyboardEvent::ControlKey) ==
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc
index 2217319..c087b41 100644
--- a/chrome/browser/ui/views/uninstall_view.cc
+++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/uninstall_view.h"
+#include "chrome/browser/ui/views/uninstall_view.h"
 
-#include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/string16.h"
@@ -13,11 +12,12 @@
 #include "chrome/common/result_codes.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/shell_util.h"
+#include "grit/chromium_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "views/controls/button/checkbox.h"
 #include "views/controls/label.h"
-#include "views/standard_layout.h"
-
-#include "grit/chromium_strings.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 
 UninstallView::UninstallView(int& user_selection)
     : confirm_label_(NULL),
@@ -38,7 +38,7 @@
   using views::ColumnSet;
   using views::GridLayout;
 
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   // Message to confirm uninstallation.
@@ -52,12 +52,12 @@
   confirm_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
   layout->AddView(confirm_label_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   // The "delete profile" check box.
   ++column_set_id;
   column_set = layout->AddColumnSet(column_set_id);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
   layout->StartRow(0, column_set_id);
@@ -72,14 +72,14 @@
     browsers_.reset(new BrowsersMap());
     ShellUtil::GetRegisteredBrowsers(dist, browsers_.get());
     if (!browsers_->empty()) {
-      layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
       ++column_set_id;
       column_set = layout->AddColumnSet(column_set_id);
-      column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+      column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
       column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                             GridLayout::USE_PREF, 0, 0);
-      column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+      column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
       column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                             GridLayout::USE_PREF, 0, 0);
       layout->StartRow(0, column_set_id);
@@ -93,7 +93,7 @@
     }
   }
 
-  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
 }
 
 bool UninstallView::Accept() {
diff --git a/chrome/browser/ui/views/uninstall_view.h b/chrome/browser/ui/views/uninstall_view.h
index 23aad8c..3f29582 100644
--- a/chrome/browser/ui/views/uninstall_view.h
+++ b/chrome/browser/ui/views/uninstall_view.h
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_UI_VIEWS_UNINSTALL_VIEW_H_
 #pragma once
 
-#include "app/combobox_model.h"
 #include "base/string16.h"
+#include "ui/base/models/combobox_model.h"
 #include "views/controls/combobox/combobox.h"
 #include "views/window/dialog_delegate.h"
 
@@ -22,7 +22,7 @@
 class UninstallView : public views::View,
                       public views::ButtonListener,
                       public views::DialogDelegate,
-                      public ComboboxModel {
+                      public ui::ComboboxModel {
  public:
   explicit UninstallView(int& user_selection);
   virtual ~UninstallView();
@@ -40,7 +40,7 @@
   virtual std::wstring GetWindowTitle() const;
   virtual views::View* GetContentsView();
 
-  // Overridden from views::Combobox::Model.
+  // Overridden from ui::ComboboxModel.
   virtual int GetItemCount();
   virtual string16 GetItemAt(int index);
 
diff --git a/chrome/browser/ui/views/update_recommended_message_box.cc b/chrome/browser/ui/views/update_recommended_message_box.cc
index 019846e..cc672c6 100644
--- a/chrome/browser/ui/views/update_recommended_message_box.cc
+++ b/chrome/browser/ui/views/update_recommended_message_box.cc
@@ -1,19 +1,19 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/update_recommended_message_box.h"
+#include "chrome/browser/ui/views/update_recommended_message_box.h"
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 #include "chrome/common/pref_names.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
 #include "views/controls/message_box_view.h"
 #include "views/window/window.h"
 
@@ -47,16 +47,16 @@
 }
 
 int UpdateRecommendedMessageBox::GetDialogButtons() const {
-  return MessageBoxFlags::DIALOGBUTTON_OK |
-         MessageBoxFlags::DIALOGBUTTON_CANCEL;
+  return ui::MessageBoxFlags::DIALOGBUTTON_OK |
+         ui::MessageBoxFlags::DIALOGBUTTON_CANCEL;
 }
 
 std::wstring UpdateRecommendedMessageBox::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
-  DCHECK(button == MessageBoxFlags::DIALOGBUTTON_OK ||
-         button == MessageBoxFlags::DIALOGBUTTON_CANCEL);
-  return button == MessageBoxFlags::DIALOGBUTTON_OK ?
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_RESTART_AND_UPDATE)) :
+    ui::MessageBoxFlags::DialogButton button) const {
+  DCHECK(button == ui::MessageBoxFlags::DIALOGBUTTON_OK ||
+         button == ui::MessageBoxFlags::DIALOGBUTTON_CANCEL);
+  return button == ui::MessageBoxFlags::DIALOGBUTTON_OK ?
+      UTF16ToWide(l10n_util::GetStringUTF16(IDS_RELAUNCH_AND_UPDATE)) :
       UTF16ToWide(l10n_util::GetStringUTF16(IDS_NOT_NOW));
 }
 
@@ -90,7 +90,8 @@
   const string16 product_name = l10n_util::GetStringUTF16(kProductNameId);
   // Also deleted when the window closes.
   message_box_view_ = new MessageBoxView(
-      MessageBoxFlags::kFlagHasMessage | MessageBoxFlags::kFlagHasOKButton,
+      ui::MessageBoxFlags::kFlagHasMessage |
+          ui::MessageBoxFlags::kFlagHasOKButton,
       UTF16ToWide(l10n_util::GetStringFUTF16(IDS_UPDATE_RECOMMENDED,
                                              product_name)),
       std::wstring(),
diff --git a/chrome/browser/ui/views/update_recommended_message_box.h b/chrome/browser/ui/views/update_recommended_message_box.h
index 0e115d0..111a907 100644
--- a/chrome/browser/ui/views/update_recommended_message_box.h
+++ b/chrome/browser/ui/views/update_recommended_message_box.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "views/window/dialog_delegate.h"
 
 class MessageBoxView;
diff --git a/chrome/browser/ui/views/url_picker.cc b/chrome/browser/ui/views/url_picker.cc
index e1977ee..7d6060b 100644
--- a/chrome/browser/ui/views/url_picker.cc
+++ b/chrome/browser/ui/views/url_picker.cc
@@ -1,13 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/url_picker.h"
+#include "chrome/browser/ui/views/url_picker.h"
 
-#include "app/keyboard_codes.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/table_model.h"
 #include "base/stl_util-inl.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
@@ -20,13 +16,17 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "net/base/net_util.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "views/background.h"
 #include "views/controls/label.h"
 #include "views/controls/table/table_view.h"
 #include "views/controls/textfield/textfield.h"
 #include "views/focus/focus_manager.h"
-#include "views/grid_layout.h"
-#include "views/standard_layout.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
 #include "views/widget/widget.h"
 
 using views::ColumnSet;
@@ -52,13 +52,11 @@
 
   url_table_model_.reset(new PossibleURLModel());
 
-  TableColumn col1(IDS_ASI_PAGE_COLUMN, TableColumn::LEFT, -1,
-                          50);
+  ui::TableColumn col1(IDS_ASI_PAGE_COLUMN, ui::TableColumn::LEFT, -1, 50);
   col1.sortable = true;
-  TableColumn col2(IDS_ASI_URL_COLUMN, TableColumn::LEFT, -1,
-                          50);
+  ui::TableColumn col2(IDS_ASI_URL_COLUMN, TableColumn::LEFT, -1, 50);
   col2.sortable = true;
-  std::vector<TableColumn> cols;
+  std::vector<ui::TableColumn> cols;
   cols.push_back(col1);
   cols.push_back(col2);
 
@@ -68,7 +66,7 @@
   url_table_->SetObserver(this);
 
   // Yummy layout code.
-  GridLayout* layout = CreatePanelGridLayout(this);
+  GridLayout* layout = GridLayout::CreatePanel(this);
   SetLayoutManager(layout);
 
   const int labels_column_set_id = 0;
@@ -77,7 +75,7 @@
   ColumnSet* column_set = layout->AddColumnSet(labels_column_set_id);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
                         GridLayout::USE_PREF, 0, 0);
 
@@ -95,7 +93,7 @@
   url_field_->SetController(this);
   layout->AddView(url_field_);
 
-  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, single_column_view_set_id);
   views::Label* description_label = new views::Label();
@@ -106,14 +104,14 @@
       description_label->font().DeriveFont(0, gfx::Font::BOLD));
   layout->AddView(description_label);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   layout->StartRow(1, single_column_view_set_id);
   layout->AddView(url_table_);
 
-  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
-  AddAccelerator(views::Accelerator(app::VKEY_RETURN, false, false, false));
+  AddAccelerator(views::Accelerator(ui::VKEY_RETURN, false, false, false));
 }
 
 UrlPicker::~UrlPicker() {
diff --git a/chrome/browser/ui/views/user_data_dir_dialog.cc b/chrome/browser/ui/views/user_data_dir_dialog.cc
index 9784cd5..0794d63 100644
--- a/chrome/browser/ui/views/user_data_dir_dialog.cc
+++ b/chrome/browser/ui/views/user_data_dir_dialog.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
-#include "app/message_box_flags.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
-#include "chrome/browser/views/user_data_dir_dialog.h"
+#include "chrome/browser/ui/views/user_data_dir_dialog.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/message_box_flags.h"
 #include "views/controls/message_box_view.h"
 #include "views/widget/widget.h"
 #include "views/window/window.h"
@@ -28,9 +28,10 @@
       is_blocking_(true) {
   std::wstring message_text = UTF16ToWide(l10n_util::GetStringFUTF16(
       IDS_CANT_WRITE_USER_DIRECTORY_SUMMARY,
-      WideToUTF16Hack(user_data_dir.ToWStringHack())));
+      user_data_dir.LossyDisplayName()));
   const int kDialogWidth = 400;
-  message_box_view_ = new MessageBoxView(MessageBoxFlags::kIsConfirmMessageBox,
+  message_box_view_ = new MessageBoxView(
+      ui::MessageBoxFlags::kIsConfirmMessageBox,
       message_text.c_str(), std::wstring(), kDialogWidth);
 
   views::Window::CreateChromeWindow(NULL, gfx::Rect(), this)->Show();
@@ -41,13 +42,13 @@
 }
 
 std::wstring UserDataDirDialog::GetDialogButtonLabel(
-    MessageBoxFlags::DialogButton button) const {
+    ui::MessageBoxFlags::DialogButton button) const {
 
   switch (button) {
-    case MessageBoxFlags::DIALOGBUTTON_OK:
+    case ui::MessageBoxFlags::DIALOGBUTTON_OK:
       return UTF16ToWide(l10n_util::GetStringUTF16(
           IDS_CANT_WRITE_USER_DIRECTORY_CHOOSE_DIRECTORY_BUTTON));
-    case MessageBoxFlags::DIALOGBUTTON_CANCEL:
+    case ui::MessageBoxFlags::DIALOGBUTTON_CANCEL:
       return UTF16ToWide(l10n_util::GetStringUTF16(
           IDS_CANT_WRITE_USER_DIRECTORY_EXIT_BUTTON));
     default:
diff --git a/chrome/browser/ui/views/user_data_dir_dialog.h b/chrome/browser/ui/views/user_data_dir_dialog.h
index 9120e49..6c60acd 100644
--- a/chrome/browser/ui/views/user_data_dir_dialog.h
+++ b/chrome/browser/ui/views/user_data_dir_dialog.h
@@ -11,7 +11,7 @@
 
 #include "base/basictypes.h"
 #include "base/message_loop.h"
-#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/ui/shell_dialogs.h"
 #include "views/window/dialog_delegate.h"
 
 class FilePath;
diff --git a/chrome/browser/ui/views/window.cc b/chrome/browser/ui/views/window.cc
index ae28ce4..ed52599 100644
--- a/chrome/browser/ui/views/window.cc
+++ b/chrome/browser/ui/views/window.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/window.h"
+#include "chrome/browser/ui/views/window.h"
 
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 #include "views/window/window.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/views/window.h b/chrome/browser/ui/views/window.h
index 56056ed..9981f2d 100644
--- a/chrome/browser/ui/views/window.h
+++ b/chrome/browser/ui/views/window.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_WINDOW_H_
 #pragma once
 
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace gfx {
 class Rect;
diff --git a/chrome/browser/ui/views/wrench_menu.cc b/chrome/browser/ui/views/wrench_menu.cc
index bc10859..8f769bd 100644
--- a/chrome/browser/ui/views/wrench_menu.cc
+++ b/chrome/browser/ui/views/wrench_menu.cc
@@ -1,16 +1,15 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/views/wrench_menu.h"
+#include "chrome/browser/ui/views/wrench_menu.h"
 
 #include <cmath>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/metrics/user_metrics.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/browser/ui/browser.h"
@@ -18,13 +17,15 @@
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/notification_source.h"
 #include "chrome/common/notification_type.h"
-#include "gfx/canvas.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/skia_util.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkPaint.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/skia_util.h"
 #include "views/background.h"
 #include "views/controls/button/image_button.h"
 #include "views/controls/button/menu_button.h"
@@ -36,7 +37,7 @@
 #include "views/controls/menu/submenu_view.h"
 #include "views/window/window.h"
 
-using menus::MenuModel;
+using ui::MenuModel;
 using views::CustomButton;
 using views::ImageButton;
 using views::Label;
@@ -234,23 +235,20 @@
     if (!IsVisible())
       return;
 
-    if (GetParent()) {
-      GetParent()->SchedulePaint(GetBounds(APPLY_MIRRORING_TRANSFORMATION),
-                                 urgent);
-    }
+    if (parent())
+      parent()->SchedulePaint(GetMirroredBounds(), urgent);
   }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ScheduleAllView);
 };
 
-std::wstring GetAccessibleNameForWrenchMenuItem(
+string16 GetAccessibleNameForWrenchMenuItem(
       MenuModel* model, int item_index, int accessible_string_id) {
-  std::wstring accessible_name =
-      UTF16ToWide(l10n_util::GetStringUTF16(accessible_string_id));
-  std::wstring accelerator_text;
+  string16 accessible_name = l10n_util::GetStringUTF16(accessible_string_id);
+  string16 accelerator_text;
 
-  menus::Accelerator menu_accelerator;
+  ui::Accelerator menu_accelerator;
   if (model->GetAcceleratorAt(item_index, &menu_accelerator)) {
     accelerator_text =
         views::Accelerator(menu_accelerator.GetKeyCode(),
@@ -344,13 +342,13 @@
   gfx::Size GetPreferredSize() {
     // Returned height doesn't matter as MenuItemView forces everything to the
     // height of the menuitemview.
-    return gfx::Size(GetMaxChildViewPreferredWidth() * GetChildViewCount(), 0);
+    return gfx::Size(GetMaxChildViewPreferredWidth() * child_count(), 0);
   }
 
   void Layout() {
     // All buttons are given the same width.
     int width = GetMaxChildViewPreferredWidth();
-    for (int i = 0; i < GetChildViewCount(); ++i)
+    for (int i = 0; i < child_count(); ++i)
       GetChildViewAt(i)->SetBounds(i * width, 0, width, height());
   }
 
@@ -363,7 +361,7 @@
   // Returns the max preferred width of all the children.
   int GetMaxChildViewPreferredWidth() {
     int width = 0;
-    for (int i = 0; i < GetChildViewCount(); ++i)
+    for (int i = 0; i < child_count(); ++i)
       width = std::max(width, GetChildViewAt(i)->GetPreferredSize().width());
     return width;
   }
@@ -458,22 +456,22 @@
                                 decrement_button_->GetPreferredSize().width());
     gfx::Rect bounds(0, 0, button_width, height());
 
-    decrement_button_->SetBounds(bounds);
+    decrement_button_->SetBoundsRect(bounds);
 
     x += bounds.width();
     bounds.set_x(x);
     bounds.set_width(zoom_label_width_);
-    zoom_label_->SetBounds(bounds);
+    zoom_label_->SetBoundsRect(bounds);
 
     x += bounds.width();
     bounds.set_x(x);
     bounds.set_width(button_width);
-    increment_button_->SetBounds(bounds);
+    increment_button_->SetBoundsRect(bounds);
 
     x += bounds.width() + kZoomPadding;
     bounds.set_x(x);
     bounds.set_width(fullscreen_button_->GetPreferredSize().width());
-    fullscreen_button_->SetBounds(bounds);
+    fullscreen_button_->SetBoundsRect(bounds);
   }
 
   // ButtonListener:
@@ -569,11 +567,10 @@
       selected_index_(0) {
 }
 
-void WrenchMenu::Init(menus::MenuModel* model) {
+void WrenchMenu::Init(ui::MenuModel* model) {
   DCHECK(!root_.get());
   root_.reset(new MenuItemView(this));
-  root_->SetAccessibleName(
-      UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_APP)));
+  root_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_APP));
   root_->set_has_icons(true);  // We have checks, radios and icons, set this
                                // so we get the taller menu style.
   int next_id = 1;
@@ -589,6 +586,7 @@
   gfx::Point screen_loc;
   views::View::ConvertPointToScreen(host, &screen_loc);
   gfx::Rect bounds(screen_loc, host->size());
+  UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu"));
   root_->RunMenuAt(host->GetWindow()->GetNativeWindow(), host, bounds,
       base::i18n::IsRTL() ? MenuItemView::TOPLEFT : MenuItemView::TOPRIGHT,
       true);
@@ -636,7 +634,7 @@
     return false;
   }
 
-  menus::Accelerator menu_accelerator;
+  ui::Accelerator menu_accelerator;
   if (!entry.first->GetAcceleratorAt(entry.second, &menu_accelerator))
     return false;
 
diff --git a/chrome/browser/ui/views/wrench_menu.h b/chrome/browser/ui/views/wrench_menu.h
index 6efaaa8..f77e67d 100644
--- a/chrome/browser/ui/views/wrench_menu.h
+++ b/chrome/browser/ui/views/wrench_menu.h
@@ -9,9 +9,9 @@
 #include <map>
 #include <utility>
 
-#include "app/menus/menu_model.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "ui/base/models/menu_model.h"
 #include "views/controls/menu/menu_delegate.h"
 
 class Browser;
@@ -28,7 +28,7 @@
  public:
   explicit WrenchMenu(Browser* browser);
 
-  void Init(menus::MenuModel* model);
+  void Init(ui::MenuModel* model);
 
   // Shows the menu relative to the specified view.
   void RunMenu(views::MenuButton* host);
@@ -45,7 +45,7 @@
   class CutCopyPasteView;
   class ZoomView;
 
-  typedef std::pair<menus::MenuModel*,int> Entry;
+  typedef std::pair<ui::MenuModel*,int> Entry;
   typedef std::map<int,Entry> IDToEntry;
 
   ~WrenchMenu();
@@ -54,20 +54,20 @@
   // |PopulateMenu| for any submenu. |next_id| is incremented for every menu
   // that is created.
   void PopulateMenu(views::MenuItemView* parent,
-                    menus::MenuModel* model,
+                    ui::MenuModel* model,
                     int* next_id);
 
   // Adds a new menu to |parent| to represent the MenuModel/index pair passed
   // in.
   views::MenuItemView* AppendMenuItem(views::MenuItemView* parent,
-                                      menus::MenuModel* model,
+                                      ui::MenuModel* model,
                                       int index,
-                                      menus::MenuModel::ItemType menu_type,
+                                      ui::MenuModel::ItemType menu_type,
                                       int* next_id);
 
   // Invoked from the cut/copy/paste menus. Cancels the current active menu and
   // activates the menu item in |model| at |index|.
-  void CancelAndEvaluate(menus::MenuModel* model, int index);
+  void CancelAndEvaluate(ui::MenuModel* model, int index);
 
   // The views menu.
   scoped_ptr<views::MenuItemView> root_;
@@ -83,7 +83,7 @@
   // If |selected_menu_model_| is non-null after the menu completes
   // ActivatedAt is invoked. This is done so that ActivatedAt isn't invoked
   // while the message loop is nested.
-  menus::MenuModel* selected_menu_model_;
+  ui::MenuModel* selected_menu_model_;
   int selected_index_;
 
   DISALLOW_COPY_AND_ASSIGN(WrenchMenu);
diff --git a/chrome/browser/ui/window_sizer.cc b/chrome/browser/ui/window_sizer.cc
index 292f5fc..e1dd834 100644
--- a/chrome/browser/ui/window_sizer.cc
+++ b/chrome/browser/ui/window_sizer.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -16,9 +17,9 @@
 // and persistent state from the browser window and the user's profile.
 class DefaultStateProvider : public WindowSizer::StateProvider {
  public:
-  explicit DefaultStateProvider(const std::string& app_name, Browser* browser)
-      : app_name_(app_name),
-        browser_(browser) {
+  explicit DefaultStateProvider(const std::string& app_name,
+      const Browser* browser) : app_name_(app_name),
+                                browser_(browser) {
   }
 
   // Overridden from WindowSizer::StateProvider:
@@ -33,11 +34,11 @@
       key.append(app_name_);
     }
 
-    if (!g_browser_process->local_state())
+    if (!browser_->profile()->GetPrefs())
       return false;
 
     const DictionaryValue* wp_pref =
-        g_browser_process->local_state()->GetDictionary(key.c_str());
+        browser_->profile()->GetPrefs()->GetDictionary(key.c_str());
     int top = 0, left = 0, bottom = 0, right = 0;
     bool has_prefs =
         wp_pref &&
@@ -74,9 +75,9 @@
     // If a reference browser is set, use its window. Otherwise find last
     // active.
     BrowserWindow* window = NULL;
-    if (browser_) {
+    // Window may be null if browser is just starting up.
+    if (browser_ && browser_->window()) {
       window = browser_->window();
-      DCHECK(window);
     } else {
       BrowserList::const_reverse_iterator it = BrowserList::begin_last_active();
       BrowserList::const_reverse_iterator end = BrowserList::end_last_active();
@@ -102,7 +103,7 @@
   std::string app_name_;
 
   // If set, is used as the reference browser for GetLastActiveWindowState.
-  Browser* browser_;
+  const Browser* browser_;
   DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider);
 };
 
@@ -132,7 +133,7 @@
 // static
 void WindowSizer::GetBrowserWindowBounds(const std::string& app_name,
                                          const gfx::Rect& specified_bounds,
-                                         Browser* browser,
+                                         const Browser* browser,
                                          gfx::Rect* window_bounds,
                                          bool* maximized) {
   const WindowSizer sizer(new DefaultStateProvider(app_name, browser),
diff --git a/chrome/browser/ui/window_sizer.h b/chrome/browser/ui/window_sizer.h
index 7d34399..159bf34 100644
--- a/chrome/browser/ui/window_sizer.h
+++ b/chrome/browser/ui/window_sizer.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "gfx/rect.h"
+#include "ui/gfx/rect.h"
 
 class Browser;
 
@@ -121,7 +121,7 @@
   // non-NULL value for |browser|.
   static void GetBrowserWindowBounds(const std::string& app_name,
                                      const gfx::Rect& specified_bounds,
-                                     Browser* browser,
+                                     const Browser* browser,
                                      gfx::Rect* window_bounds,
                                      bool* maximized);
 
@@ -181,4 +181,5 @@
   DISALLOW_COPY_AND_ASSIGN(WindowSizer);
 };
 
-#endif  // CHROME_BROWSER_WINDOW_SIZER_H_
+#endif  // CHROME_BROWSER_UI_WINDOW_SIZER_H_
+
diff --git a/chrome/browser/ui/window_snapshot/window_snapshot.h b/chrome/browser/ui/window_snapshot/window_snapshot.h
new file mode 100644
index 0000000..5178662
--- /dev/null
+++ b/chrome/browser/ui/window_snapshot/window_snapshot.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WINDOW_SNAPSHOT_WINDOW_SNAPSHOT_H_
+#define CHROME_BROWSER_UI_WINDOW_SNAPSHOT_WINDOW_SNAPSHOT_H_
+#pragma once
+
+#include <vector>
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+  class Rect;
+}
+
+namespace browser {
+
+// Grabs a snapshot of the designated window and stores a PNG representation
+// into a byte vector. Returns the image bounds.
+gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window,
+                             std::vector<unsigned char>* png_representation);
+
+}  // namespace browser
+
+#endif  // CHROME_BROWSER_UI_WINDOW_SNAPSHOT_WINDOW_SNAPSHOT_H_
diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm b/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm
new file mode 100644
index 0000000..d3f7c50
--- /dev/null
+++ b/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/window_snapshot/window_snapshot.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/scoped_nsobject.h"
+#include "ui/gfx/rect.h"
+
+namespace browser {
+
+gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window,
+    std::vector<unsigned char>* png_representation) {
+  png_representation->clear();
+
+  // Make sure to grab the "window frame" view so we get current tab +
+  // tabstrip.
+  NSView* view = [[window contentView] superview];
+  base::mac::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage(
+      CGRectNull, kCGWindowListOptionIncludingWindow,
+      [[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming));
+  if (CGImageGetWidth(windowSnapshot) <= 0)
+    return gfx::Rect();
+
+  scoped_nsobject<NSBitmapImageRep> rep(
+      [[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]);
+  NSData* data = [rep representationUsingType:NSPNGFileType properties:nil];
+  const unsigned char* buf = static_cast<const unsigned char*>([data bytes]);
+  NSUInteger length = [data length];
+  if (buf == NULL || length == 0)
+    return gfx::Rect();
+
+  png_representation->assign(buf, buf + length);
+  DCHECK(png_representation->size() > 0);
+
+  return gfx::Rect(static_cast<int>([rep pixelsWide]),
+                   static_cast<int>([rep pixelsHigh]));
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm b/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm
new file mode 100644
index 0000000..b49a6a4
--- /dev/null
+++ b/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/window_snapshot/window_snapshot.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "base/test/mock_chrome_application_mac.h"
+#include "testing/platform_test.h"
+#include "ui/gfx/rect.h"
+
+namespace browser {
+namespace {
+
+typedef PlatformTest GrabWindowSnapshotTest;
+
+TEST_F(GrabWindowSnapshotTest, TestGrabWindowSnapshot) {
+  // Launch a test window so we can take a snapshot.
+  NSRect frame = NSMakeRect(0, 0, 400, 400);
+  scoped_nsobject<NSWindow> window(
+      [[NSWindow alloc] initWithContentRect:frame
+                                  styleMask:NSBorderlessWindowMask
+                                    backing:NSBackingStoreBuffered
+                                      defer:NO]);
+  [window setBackgroundColor:[NSColor whiteColor]];
+  [window makeKeyAndOrderFront:NSApp];
+
+  scoped_ptr<std::vector<unsigned char> > png_representation(
+      new std::vector<unsigned char>);
+  browser::GrabWindowSnapshot(window, png_representation.get());
+
+  // Copy png back into NSData object so we can make sure we grabbed a png.
+  scoped_nsobject<NSData> image_data(
+      [[NSData alloc] initWithBytes:&(*png_representation)[0]
+                             length:png_representation->size()]);
+  NSBitmapImageRep* rep = [NSBitmapImageRep imageRepWithData:image_data.get()];
+  EXPECT_TRUE([rep isKindOfClass:[NSBitmapImageRep class]]);
+  EXPECT_TRUE(CGImageGetWidth([rep CGImage]) == 400);
+  NSColor* color = [rep colorAtX:200 y:200];
+  CGFloat red = 0, green = 0, blue = 0, alpha = 0;
+  [color getRed:&red green:&green blue:&blue alpha:&alpha];
+  EXPECT_GE(red + green + blue, 3.0);
+}
+
+}  // namespace
+}  // namespace browser
diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_win.cc b/chrome/browser/ui/window_snapshot/window_snapshot_win.cc
new file mode 100644
index 0000000..b4fcdba
--- /dev/null
+++ b/chrome/browser/ui/window_snapshot/window_snapshot_win.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/window_snapshot/window_snapshot.h"
+
+#include "base/win/scoped_gdi_object.h"
+#include "base/win/scoped_hdc.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/rect.h"
+
+namespace browser {
+
+gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle,
+                             std::vector<unsigned char>* png_representation) {
+  // Create a memory DC that's compatible with the window.
+  HDC window_hdc = GetWindowDC(window_handle);
+  base::win::ScopedHDC mem_hdc(CreateCompatibleDC(window_hdc));
+
+  // Create a DIB that's the same size as the window.
+  RECT content_rect = {0, 0, 0, 0};
+  ::GetWindowRect(window_handle, &content_rect);
+  content_rect.right++;  // Match what PrintWindow wants.
+  int width = content_rect.right - content_rect.left;
+  int height = content_rect.bottom - content_rect.top;
+  BITMAPINFOHEADER hdr;
+  gfx::CreateBitmapHeader(width, height, &hdr);
+  unsigned char *bit_ptr = NULL;
+  base::win::ScopedBitmap bitmap(
+      CreateDIBSection(mem_hdc,
+                       reinterpret_cast<BITMAPINFO*>(&hdr),
+                       DIB_RGB_COLORS,
+                       reinterpret_cast<void **>(&bit_ptr),
+                       NULL, 0));
+
+  SelectObject(mem_hdc, bitmap);
+  // Clear the bitmap to white (so that rounded corners on windows
+  // show up on a white background, and strangely-shaped windows
+  // look reasonable). Not capturing an alpha mask saves a
+  // bit of space.
+  PatBlt(mem_hdc, 0, 0, width, height, WHITENESS);
+  // Grab a copy of the window
+  // First, see if PrintWindow is defined (it's not in Windows 2000).
+  typedef BOOL (WINAPI *PrintWindowPointer)(HWND, HDC, UINT);
+  PrintWindowPointer print_window =
+      reinterpret_cast<PrintWindowPointer>(
+          GetProcAddress(GetModuleHandle(L"User32.dll"), "PrintWindow"));
+
+  // If PrintWindow is defined, use it.  It will work on partially
+  // obscured windows, and works better for out of process sub-windows.
+  // Otherwise grab the bits we can get with BitBlt; it's better
+  // than nothing and will work fine in the average case (window is
+  // completely on screen).
+  if (print_window)
+    (*print_window)(window_handle, mem_hdc, 0);
+  else
+    BitBlt(mem_hdc, 0, 0, width, height, window_hdc, 0, 0, SRCCOPY);
+
+  // We now have a copy of the window contents in a DIB, so
+  // encode it into a useful format for posting to the bug report
+  // server.
+  gfx::PNGCodec::Encode(bit_ptr, gfx::PNGCodec::FORMAT_BGRA,
+                        width, height, width * 4, true,
+                        png_representation);
+
+  ReleaseDC(window_handle, window_hdc);
+
+  return gfx::Rect(width, height);
+}
+
+}  // namespace browser
diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_x.cc b/chrome/browser/ui/window_snapshot/window_snapshot_x.cc
new file mode 100644
index 0000000..4507996
--- /dev/null
+++ b/chrome/browser/ui/window_snapshot/window_snapshot_x.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/ui/window_snapshot/window_snapshot.h"
+
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/rect.h"
+
+namespace browser {
+
+static cairo_status_t SnapshotCallback(
+    void *closure, const unsigned char *data, unsigned int length) {
+  std::vector<unsigned char>* png_representation =
+      static_cast<std::vector<unsigned char>*>(closure);
+
+  size_t old_size = png_representation->size();
+  png_representation->resize(old_size + length);
+  memcpy(&(*png_representation)[old_size], data, length);
+  return CAIRO_STATUS_SUCCESS;
+}
+
+gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window,
+                             std::vector<unsigned char>* png_representation) {
+  GdkWindow* gdk_window = GTK_WIDGET(gtk_window)->window;
+  Display* display = GDK_WINDOW_XDISPLAY(gdk_window);
+  XID win = GDK_WINDOW_XID(gdk_window);
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, win, &attr) == 0) {
+    LOG(ERROR) << "Couldn't get window attributes";
+    return gfx::Rect();
+  }
+  XImage* image = XGetImage(
+      display, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
+  if (!image) {
+    LOG(ERROR) << "Couldn't get image";
+    return gfx::Rect();
+  }
+  if (image->depth != 24) {
+    LOG(ERROR)<< "Unsupported image depth " << image->depth;
+    return gfx::Rect();
+  }
+  cairo_surface_t* surface =
+      cairo_image_surface_create_for_data(
+          reinterpret_cast<unsigned char*>(image->data),
+          CAIRO_FORMAT_RGB24,
+          image->width,
+          image->height,
+          image->bytes_per_line);
+
+  if (!surface) {
+    LOG(ERROR) << "Unable to create Cairo surface from XImage data";
+    return gfx::Rect();
+  }
+  cairo_surface_write_to_png_stream(
+      surface, SnapshotCallback, png_representation);
+  cairo_surface_destroy(surface);
+
+  return gfx::Rect(image->width, image->height);
+}
+
+}  // namespace browser
diff --git a/chrome/browser/unload_uitest.cc b/chrome/browser/unload_uitest.cc
index a359e23..84f0e4f 100644
--- a/chrome/browser/unload_uitest.cc
+++ b/chrome/browser/unload_uitest.cc
@@ -1,9 +1,9 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/message_box_flags.h"
 #include "base/file_util.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/browser/net/url_request_mock_http_job.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/common/chrome_switches.h"
@@ -11,8 +11,9 @@
 #include "chrome/test/automation/tab_proxy.h"
 #include "chrome/test/automation/window_proxy.h"
 #include "chrome/test/ui/ui_test.h"
-#include "net/url_request/url_request_unittest.h"
-#include "views/event.h"
+#include "net/url_request/url_request_test_util.h"
+#include "ui/base/events.h"
+#include "ui/base/message_box_flags.h"
 
 const std::string NOLISTENERS_HTML =
     "<html><head><title>nolisteners</title></head><body></body></html>";
@@ -104,7 +105,7 @@
 
   void WaitForBrowserClosed() {
     const int kCheckDelayMs = 100;
-    for (int max_wait_time = action_max_timeout_ms();
+    for (int max_wait_time = TestTimeouts::action_max_timeout_ms();
          max_wait_time > 0; max_wait_time -= kCheckDelayMs) {
       CrashAwareSleep(kCheckDelayMs);
       if (!IsBrowserRunning())
@@ -116,7 +117,7 @@
 
   void CheckTitle(const std::wstring& expected_title) {
     const int kCheckDelayMs = 100;
-    for (int max_wait_time = action_max_timeout_ms();
+    for (int max_wait_time = TestTimeouts::action_max_timeout_ms();
          max_wait_time > 0; max_wait_time -= kCheckDelayMs) {
       CrashAwareSleep(kCheckDelayMs);
       if (expected_title == GetActiveTabTitle())
@@ -164,9 +165,9 @@
     EXPECT_TRUE(CloseBrowser(browser.get(), &application_closed));
   }
 
-  void ClickModalDialogButton(MessageBoxFlags::DialogButton button) {
+  void ClickModalDialogButton(ui::MessageBoxFlags::DialogButton button) {
     bool modal_dialog_showing = false;
-    MessageBoxFlags::DialogButton available_buttons;
+    ui::MessageBoxFlags::DialogButton available_buttons;
     EXPECT_TRUE(automation()->WaitForAppModalDialog());
     EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
         &available_buttons));
@@ -244,7 +245,7 @@
   gfx::Rect bounds;
   ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds, false));
   ASSERT_TRUE(browser->SimulateDrag(bounds.CenterPoint(), bounds.CenterPoint(),
-                                    views::Event::EF_LEFT_BUTTON_DOWN, false));
+                                    ui::EF_LEFT_BUTTON_DOWN, false));
 
   // The title should update before the timeout in CheckTitle.
   CheckTitle(L"Title Of Awesomeness");
@@ -299,7 +300,7 @@
   NavigateToDataURL(BEFORE_UNLOAD_HTML, L"beforeunload");
 
   CloseBrowserAsync(browser.get());
-  ClickModalDialogButton(MessageBoxFlags::DIALOGBUTTON_OK);
+  ClickModalDialogButton(ui::MessageBoxFlags::DIALOGBUTTON_OK);
   WaitForBrowserClosed();
 }
 
@@ -311,14 +312,14 @@
   NavigateToDataURL(BEFORE_UNLOAD_HTML, L"beforeunload");
 
   CloseBrowserAsync(browser.get());
-  ClickModalDialogButton(MessageBoxFlags::DIALOGBUTTON_CANCEL);
+  ClickModalDialogButton(ui::MessageBoxFlags::DIALOGBUTTON_CANCEL);
   // There's no real graceful way to wait for something _not_ to happen, so
   // we just wait a short period.
   CrashAwareSleep(500);
   ASSERT_TRUE(IsBrowserRunning());
 
   CloseBrowserAsync(browser.get());
-  ClickModalDialogButton(MessageBoxFlags::DIALOGBUTTON_OK);
+  ClickModalDialogButton(ui::MessageBoxFlags::DIALOGBUTTON_OK);
   WaitForBrowserClosed();
 }
 
@@ -340,7 +341,7 @@
   NavigateToDataURL(INNER_FRAME_WITH_FOCUS_HTML, L"innerframewithfocus");
 
   CloseBrowserAsync(browser.get());
-  ClickModalDialogButton(MessageBoxFlags::DIALOGBUTTON_OK);
+  ClickModalDialogButton(ui::MessageBoxFlags::DIALOGBUTTON_OK);
   WaitForBrowserClosed();
 }
 
@@ -436,7 +437,7 @@
   // Simulate a click to force user_gesture to true; if we don't, the resulting
   // popup will be constrained, which isn't what we want to test.
   ASSERT_TRUE(window->SimulateOSClick(tab_view_bounds.CenterPoint(),
-                                      views::Event::EF_LEFT_BUTTON_DOWN));
+                                      ui::EF_LEFT_BUTTON_DOWN));
   ASSERT_TRUE(browser->WaitForTabCountToBecome(2));
 
   scoped_refptr<TabProxy> popup_tab(browser->GetActiveTab());
diff --git a/chrome/browser/upgrade_detector.cc b/chrome/browser/upgrade_detector.cc
index 99d8a2b..5588d4f 100644
--- a/chrome/browser/upgrade_detector.cc
+++ b/chrome/browser/upgrade_detector.cc
@@ -27,7 +27,7 @@
 #if defined(OS_WIN)
 #include "chrome/installer/util/install_util.h"
 #elif defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/keystone_glue.h"
+#include "chrome/browser/cocoa/keystone_glue.h"
 #elif defined(OS_POSIX)
 #include "base/process_util.h"
 #include "base/version.h"
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index 4d208fd..378f945 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -15,6 +15,7 @@
 #include "chrome/common/utility_messages.h"
 #include "ipc/ipc_switches.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/ui_base_switches.h"
 
 UtilityProcessHost::UtilityProcessHost(ResourceDispatcherHost* rdh,
                                        Client* client,
diff --git a/chrome/browser/views/about_chrome_view.h b/chrome/browser/views/about_chrome_view.h
deleted file mode 100644
index cb2a7dd..0000000
--- a/chrome/browser/views/about_chrome_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_ABOUT_CHROME_VIEW_H_
-#define CHROME_BROWSER_VIEWS_ABOUT_CHROME_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/about_chrome_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_ABOUT_CHROME_VIEW_H_
-
diff --git a/chrome/browser/views/about_ipc_dialog.h b/chrome/browser/views/about_ipc_dialog.h
deleted file mode 100644
index 13c1255..0000000
--- a/chrome/browser/views/about_ipc_dialog.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_ABOUT_IPC_DIALOG_H_
-#define CHROME_BROWSER_VIEWS_ABOUT_IPC_DIALOG_H_
-#pragma once
-
-#include "chrome/browser/ui/views/about_ipc_dialog.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_ABOUT_IPC_DIALOG_H_
-
diff --git a/chrome/browser/views/accelerator_table_gtk.h b/chrome/browser/views/accelerator_table_gtk.h
deleted file mode 100644
index 1b3a20a..0000000
--- a/chrome/browser/views/accelerator_table_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_ACCELERATOR_TABLE_GTK_H_
-#define CHROME_BROWSER_VIEWS_ACCELERATOR_TABLE_GTK_H_
-#pragma once
-
-#include "chrome/browser/ui/views/accelerator_table_gtk.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_ACCELERATOR_TABLE_GTK_H_
-
diff --git a/chrome/browser/views/accessibility_event_router_views.h b/chrome/browser/views/accessibility_event_router_views.h
deleted file mode 100644
index e3850b2..0000000
--- a/chrome/browser/views/accessibility_event_router_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/accessibility_event_router_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_
-
diff --git a/chrome/browser/views/accessible_pane_view.h b/chrome/browser/views/accessible_pane_view.h
deleted file mode 100644
index 8a2ebb1..0000000
--- a/chrome/browser/views/accessible_pane_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_ACCESSIBLE_PANE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_ACCESSIBLE_PANE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/accessible_pane_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_ACCESSIBLE_PANE_VIEW_H_
-
diff --git a/chrome/browser/views/accessible_view_helper.h b/chrome/browser/views/accessible_view_helper.h
deleted file mode 100644
index e02fde1..0000000
--- a/chrome/browser/views/accessible_view_helper.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_ACCESSIBLE_VIEW_HELPER_H_
-#define CHROME_BROWSER_VIEWS_ACCESSIBLE_VIEW_HELPER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/accessible_view_helper.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_ACCESSIBLE_VIEW_HELPER_H_
-
diff --git a/chrome/browser/views/appcache_info_view.h b/chrome/browser/views/appcache_info_view.h
deleted file mode 100644
index 991b819..0000000
--- a/chrome/browser/views/appcache_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_APPCACHE_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_APPCACHE_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/appcache_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_APPCACHE_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
deleted file mode 100644
index 770818d..0000000
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_CONTENTS_VIEW_H_
-#define CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_CONTENTS_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_CONTENTS_VIEW_H_
-
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_gtk.h b/chrome/browser/views/autocomplete/autocomplete_popup_gtk.h
deleted file mode 100644
index f3a156f..0000000
--- a/chrome/browser/views/autocomplete/autocomplete_popup_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_GTK_H_
-#define CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_GTK_H_
-#pragma once
-
-#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_GTK_H_
-
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_win.h b/chrome/browser/views/autocomplete/autocomplete_popup_win.h
deleted file mode 100644
index 68fa02c..0000000
--- a/chrome/browser/views/autocomplete/autocomplete_popup_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_WIN_H_
-#define CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_WIN_H_
-
diff --git a/chrome/browser/views/autofill_profiles_view_win.h b/chrome/browser/views/autofill_profiles_view_win.h
deleted file mode 100644
index 5768e9f..0000000
--- a/chrome/browser/views/autofill_profiles_view_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_AUTOFILL_PROFILES_VIEW_WIN_H_
-#define CHROME_BROWSER_VIEWS_AUTOFILL_PROFILES_VIEW_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/autofill_profiles_view_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_AUTOFILL_PROFILES_VIEW_WIN_H_
-
diff --git a/chrome/browser/views/bookmark_bar_instructions_view.h b/chrome/browser/views/bookmark_bar_instructions_view.h
deleted file mode 100644
index 599ad78..0000000
--- a/chrome/browser/views/bookmark_bar_instructions_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_BAR_INSTRUCTIONS_VIEW_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_BAR_INSTRUCTIONS_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_bar_instructions_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_BAR_INSTRUCTIONS_VIEW_H_
-
diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h
deleted file mode 100644
index 7dea837..0000000
--- a/chrome/browser/views/bookmark_bar_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_bar_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
-
diff --git a/chrome/browser/views/bookmark_bubble_view.h b/chrome/browser/views/bookmark_bubble_view.h
deleted file mode 100644
index cd35459..0000000
--- a/chrome/browser/views/bookmark_bubble_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_BUBBLE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_BUBBLE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_bubble_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_BUBBLE_VIEW_H_
-
diff --git a/chrome/browser/views/bookmark_context_menu.h b/chrome/browser/views/bookmark_context_menu.h
deleted file mode 100644
index 1f6f2f2..0000000
--- a/chrome/browser/views/bookmark_context_menu.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_CONTEXT_MENU_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_CONTEXT_MENU_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_context_menu.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_CONTEXT_MENU_H_
-
diff --git a/chrome/browser/views/bookmark_context_menu_controller_views.h b/chrome/browser/views/bookmark_context_menu_controller_views.h
deleted file mode 100644
index 73b54e6..0000000
--- a/chrome/browser/views/bookmark_context_menu_controller_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_CONTEXT_MENU_CONTROLLER_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_CONTEXT_MENU_CONTROLLER_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_context_menu_controller_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_CONTEXT_MENU_CONTROLLER_VIEWS_H_
-
diff --git a/chrome/browser/views/bookmark_editor_view.h b/chrome/browser/views/bookmark_editor_view.h
deleted file mode 100644
index fca0aab..0000000
--- a/chrome/browser/views/bookmark_editor_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_EDITOR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_EDITOR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_editor_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_EDITOR_VIEW_H_
-
diff --git a/chrome/browser/views/bookmark_menu_controller_views.h b/chrome/browser/views/bookmark_menu_controller_views.h
deleted file mode 100644
index 2fcca0c..0000000
--- a/chrome/browser/views/bookmark_menu_controller_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_MENU_CONTROLLER_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_BOOKMARK_MENU_CONTROLLER_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bookmark_menu_controller_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BOOKMARK_MENU_CONTROLLER_VIEWS_H_
-
diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h
deleted file mode 100644
index 0b6b094..0000000
--- a/chrome/browser/views/browser_actions_container.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BROWSER_ACTIONS_CONTAINER_H_
-#define CHROME_BROWSER_VIEWS_BROWSER_ACTIONS_CONTAINER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/browser_actions_container.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BROWSER_ACTIONS_CONTAINER_H_
-
diff --git a/chrome/browser/views/browser_bubble.h b/chrome/browser/views/browser_bubble.h
deleted file mode 100644
index cc4352c..0000000
--- a/chrome/browser/views/browser_bubble.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BROWSER_BUBBLE_H_
-#define CHROME_BROWSER_VIEWS_BROWSER_BUBBLE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/browser_bubble.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BROWSER_BUBBLE_H_
-
diff --git a/chrome/browser/views/browser_dialogs.h b/chrome/browser/views/browser_dialogs.h
deleted file mode 100644
index ebff745..0000000
--- a/chrome/browser/views/browser_dialogs.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BROWSER_DIALOGS_H_
-#define CHROME_BROWSER_VIEWS_BROWSER_DIALOGS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/browser_dialogs.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BROWSER_DIALOGS_H_
-
diff --git a/chrome/browser/views/bubble_border.h b/chrome/browser/views/bubble_border.h
deleted file mode 100644
index 2d88c30..0000000
--- a/chrome/browser/views/bubble_border.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_BUBBLE_BORDER_H_
-#define CHROME_BROWSER_VIEWS_BUBBLE_BORDER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/bubble_border.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_BUBBLE_BORDER_H_
-
diff --git a/chrome/browser/views/chrome_views_delegate.h b/chrome/browser/views/chrome_views_delegate.h
deleted file mode 100644
index 01144e5..0000000
--- a/chrome/browser/views/chrome_views_delegate.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CHROME_VIEWS_DELEGATE_H_
-#define CHROME_BROWSER_VIEWS_CHROME_VIEWS_DELEGATE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/chrome_views_delegate.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CHROME_VIEWS_DELEGATE_H_
-
diff --git a/chrome/browser/views/clear_browsing_data.h b/chrome/browser/views/clear_browsing_data.h
deleted file mode 100644
index e9d8b20..0000000
--- a/chrome/browser/views/clear_browsing_data.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_H_
-#define CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_H_
-#pragma once
-
-#include "chrome/browser/ui/views/clear_browsing_data.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_H_
-
diff --git a/chrome/browser/views/clear_browsing_data_view.h b/chrome/browser/views/clear_browsing_data_view.h
deleted file mode 100644
index 9911fb1..0000000
--- a/chrome/browser/views/clear_browsing_data_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_
-#define CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/clear_browsing_data_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_
-
diff --git a/chrome/browser/views/clear_data_view.h b/chrome/browser/views/clear_data_view.h
deleted file mode 100644
index f03a941..0000000
--- a/chrome/browser/views/clear_data_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CLEAR_DATA_VIEW_H_
-#define CHROME_BROWSER_VIEWS_CLEAR_DATA_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/clear_data_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CLEAR_DATA_VIEW_H_
-
diff --git a/chrome/browser/views/clear_server_data.h b/chrome/browser/views/clear_server_data.h
deleted file mode 100644
index ecce971..0000000
--- a/chrome/browser/views/clear_server_data.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CLEAR_SERVER_DATA_H_
-#define CHROME_BROWSER_VIEWS_CLEAR_SERVER_DATA_H_
-#pragma once
-
-#include "chrome/browser/ui/views/clear_server_data.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CLEAR_SERVER_DATA_H_
-
diff --git a/chrome/browser/views/collected_cookies_win.h b/chrome/browser/views/collected_cookies_win.h
deleted file mode 100644
index a13b856..0000000
--- a/chrome/browser/views/collected_cookies_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_COLLECTED_COOKIES_WIN_H_
-#define CHROME_BROWSER_VIEWS_COLLECTED_COOKIES_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/collected_cookies_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_COLLECTED_COOKIES_WIN_H_
-
diff --git a/chrome/browser/views/confirm_message_box_dialog.h b/chrome/browser/views/confirm_message_box_dialog.h
deleted file mode 100644
index 26ca059..0000000
--- a/chrome/browser/views/confirm_message_box_dialog.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CONFIRM_MESSAGE_BOX_DIALOG_H_
-#define CHROME_BROWSER_VIEWS_CONFIRM_MESSAGE_BOX_DIALOG_H_
-#pragma once
-
-#include "chrome/browser/ui/views/confirm_message_box_dialog.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CONFIRM_MESSAGE_BOX_DIALOG_H_
-
diff --git a/chrome/browser/views/constrained_window_win.h b/chrome/browser/views/constrained_window_win.h
deleted file mode 100644
index 61ed885..0000000
--- a/chrome/browser/views/constrained_window_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CONSTRAINED_WINDOW_WIN_H_
-#define CHROME_BROWSER_VIEWS_CONSTRAINED_WINDOW_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/constrained_window_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CONSTRAINED_WINDOW_WIN_H_
-
diff --git a/chrome/browser/views/content_setting_bubble_contents.h b/chrome/browser/views/content_setting_bubble_contents.h
deleted file mode 100644
index 03ac993..0000000
--- a/chrome/browser/views/content_setting_bubble_contents.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CONTENT_SETTING_BUBBLE_CONTENTS_H_
-#define CHROME_BROWSER_VIEWS_CONTENT_SETTING_BUBBLE_CONTENTS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/content_setting_bubble_contents.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CONTENT_SETTING_BUBBLE_CONTENTS_H_
-
diff --git a/chrome/browser/views/cookie_info_view.h b/chrome/browser/views/cookie_info_view.h
deleted file mode 100644
index 6eb19e5..0000000
--- a/chrome/browser/views/cookie_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_COOKIE_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_COOKIE_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/cookie_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_COOKIE_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/create_application_shortcut_view.h b/chrome/browser/views/create_application_shortcut_view.h
deleted file mode 100644
index d117ab2..0000000
--- a/chrome/browser/views/create_application_shortcut_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_CREATE_APPLICATION_SHORTCUT_VIEW_H_
-#define CHROME_BROWSER_VIEWS_CREATE_APPLICATION_SHORTCUT_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/create_application_shortcut_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_CREATE_APPLICATION_SHORTCUT_VIEW_H_
-
diff --git a/chrome/browser/views/database_info_view.h b/chrome/browser/views/database_info_view.h
deleted file mode 100644
index 5f7e747..0000000
--- a/chrome/browser/views/database_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DATABASE_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DATABASE_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/database_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DATABASE_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/database_open_info_view.h b/chrome/browser/views/database_open_info_view.h
deleted file mode 100644
index be80823..0000000
--- a/chrome/browser/views/database_open_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DATABASE_OPEN_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DATABASE_OPEN_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/database_open_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DATABASE_OPEN_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/default_search_view.h b/chrome/browser/views/default_search_view.h
deleted file mode 100644
index 12651c4..0000000
--- a/chrome/browser/views/default_search_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DEFAULT_SEARCH_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DEFAULT_SEARCH_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/default_search_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DEFAULT_SEARCH_VIEW_H_
-
diff --git a/chrome/browser/views/detachable_toolbar_view.h b/chrome/browser/views/detachable_toolbar_view.h
deleted file mode 100644
index 68c967b..0000000
--- a/chrome/browser/views/detachable_toolbar_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/detachable_toolbar_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_
-
diff --git a/chrome/browser/views/dom_view.h b/chrome/browser/views/dom_view.h
deleted file mode 100644
index 095fcb7..0000000
--- a/chrome/browser/views/dom_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DOM_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DOM_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/dom_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DOM_VIEW_H_
-
diff --git a/chrome/browser/views/download_item_view.h b/chrome/browser/views/download_item_view.h
deleted file mode 100644
index cb7dd5c..0000000
--- a/chrome/browser/views/download_item_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DOWNLOAD_ITEM_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DOWNLOAD_ITEM_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/download_item_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DOWNLOAD_ITEM_VIEW_H_
-
diff --git a/chrome/browser/views/download_shelf_view.h b/chrome/browser/views/download_shelf_view.h
deleted file mode 100644
index 628abba..0000000
--- a/chrome/browser/views/download_shelf_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_DOWNLOAD_SHELF_VIEW_H_
-#define CHROME_BROWSER_DOWNLOAD_SHELF_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/download_shelf_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_DOWNLOAD_SHELF_VIEW_H_
-
diff --git a/chrome/browser/views/dropdown_bar_host.h b/chrome/browser/views/dropdown_bar_host.h
deleted file mode 100644
index 23c9053..0000000
--- a/chrome/browser/views/dropdown_bar_host.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DROPDOWN_BAR_HOST_H_
-#define CHROME_BROWSER_VIEWS_DROPDOWN_BAR_HOST_H_
-#pragma once
-
-#include "chrome/browser/ui/views/dropdown_bar_host.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DROPDOWN_BAR_HOST_H_
-
diff --git a/chrome/browser/views/dropdown_bar_view.h b/chrome/browser/views/dropdown_bar_view.h
deleted file mode 100644
index 9ae52cc..0000000
--- a/chrome/browser/views/dropdown_bar_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_DROPDOWN_BAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_DROPDOWN_BAR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/dropdown_bar_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_DROPDOWN_BAR_VIEW_H_
-
diff --git a/chrome/browser/views/edit_search_engine_dialog.h b/chrome/browser/views/edit_search_engine_dialog.h
deleted file mode 100644
index f5881ec..0000000
--- a/chrome/browser/views/edit_search_engine_dialog.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EDIT_SEARCH_ENGINE_DIALOG_H_
-#define CHROME_BROWSER_VIEWS_EDIT_SEARCH_ENGINE_DIALOG_H_
-#pragma once
-
-#include "chrome/browser/ui/views/edit_search_engine_dialog.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EDIT_SEARCH_ENGINE_DIALOG_H_
-
diff --git a/chrome/browser/views/event_utils.h b/chrome/browser/views/event_utils.h
deleted file mode 100644
index 7d7d370..0000000
--- a/chrome/browser/views/event_utils.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EVENT_UTILS_H_
-#define CHROME_BROWSER_VIEWS_EVENT_UTILS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/event_utils.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EVENT_UTILS_H_
-
diff --git a/chrome/browser/views/extensions/browser_action_drag_data.h b/chrome/browser/views/extensions/browser_action_drag_data.h
deleted file mode 100644
index ee3ac8f..0000000
--- a/chrome/browser/views/extensions/browser_action_drag_data.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_DRAG_DATA_H_
-#define CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_DRAG_DATA_H_
-#pragma once
-
-#include "chrome/browser/ui/views/extensions/browser_action_drag_data.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_DRAG_DATA_H_
-
diff --git a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.h b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.h
deleted file mode 100644
index 5023765..0000000
--- a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_OVERFLOW_MENU_CONTROLLER_H_
-#define CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_OVERFLOW_MENU_CONTROLLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_OVERFLOW_MENU_CONTROLLER_H_
-
diff --git a/chrome/browser/views/extensions/extension_installed_bubble.h b/chrome/browser/views/extensions/extension_installed_bubble.h
deleted file mode 100644
index ab1c498..0000000
--- a/chrome/browser/views/extensions/extension_installed_bubble.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_H_
-#define CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/extensions/extension_installed_bubble.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_H_
-
diff --git a/chrome/browser/views/extensions/extension_popup.h b/chrome/browser/views/extensions/extension_popup.h
deleted file mode 100644
index 6bfa6f6..0000000
--- a/chrome/browser/views/extensions/extension_popup.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_POPUP_H_
-#define CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_POPUP_H_
-#pragma once
-
-#include "chrome/browser/ui/views/extensions/extension_popup.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_POPUP_H_
-
diff --git a/chrome/browser/views/extensions/extension_view.h b/chrome/browser/views/extensions/extension_view.h
deleted file mode 100644
index f7b4e8d..0000000
--- a/chrome/browser/views/extensions/extension_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_VIEW_H_
-#define CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/extensions/extension_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_VIEW_H_
-
diff --git a/chrome/browser/views/external_protocol_dialog.h b/chrome/browser/views/external_protocol_dialog.h
deleted file mode 100644
index 9925dd4..0000000
--- a/chrome/browser/views/external_protocol_dialog.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_EXTERNAL_PROTOCOL_DIALOG_H_
-#define CHROME_BROWSER_VIEWS_EXTERNAL_PROTOCOL_DIALOG_H_
-#pragma once
-
-#include "chrome/browser/ui/views/external_protocol_dialog.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_EXTERNAL_PROTOCOL_DIALOG_H_
-
diff --git a/chrome/browser/views/find_bar_host.h b/chrome/browser/views/find_bar_host.h
deleted file mode 100644
index 4e34679..0000000
--- a/chrome/browser/views/find_bar_host.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FIND_BAR_HOST_H_
-#define CHROME_BROWSER_VIEWS_FIND_BAR_HOST_H_
-#pragma once
-
-#include "chrome/browser/ui/views/find_bar_host.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FIND_BAR_HOST_H_
-
diff --git a/chrome/browser/views/find_bar_view.h b/chrome/browser/views/find_bar_view.h
deleted file mode 100644
index bb980df..0000000
--- a/chrome/browser/views/find_bar_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FIND_BAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FIND_BAR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/find_bar_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FIND_BAR_VIEW_H_
-
diff --git a/chrome/browser/views/first_run_bubble.h b/chrome/browser/views/first_run_bubble.h
deleted file mode 100644
index 235e004..0000000
--- a/chrome/browser/views/first_run_bubble.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FIRST_RUN_BUBBLE_H_
-#define CHROME_BROWSER_VIEWS_FIRST_RUN_BUBBLE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/first_run_bubble.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FIRST_RUN_BUBBLE_H_
-
diff --git a/chrome/browser/views/first_run_search_engine_view.h b/chrome/browser/views/first_run_search_engine_view.h
deleted file mode 100644
index 7dffda0..0000000
--- a/chrome/browser/views/first_run_search_engine_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FIRST_RUN_SEARCH_ENGINE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FIRST_RUN_SEARCH_ENGINE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/first_run_search_engine_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FIRST_RUN_SEARCH_ENGINE_VIEW_H_
-
diff --git a/chrome/browser/views/frame/app_panel_browser_frame_view.h b/chrome/browser/views/frame/app_panel_browser_frame_view.h
deleted file mode 100644
index cc93319..0000000
--- a/chrome/browser/views/frame/app_panel_browser_frame_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_APP_PANEL_BROWSER_FRAME_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_APP_PANEL_BROWSER_FRAME_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/app_panel_browser_frame_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_APP_PANEL_BROWSER_FRAME_VIEW_H_
-
diff --git a/chrome/browser/views/frame/browser_bubble_host.h b/chrome/browser/views/frame/browser_bubble_host.h
deleted file mode 100644
index f903d99..0000000
--- a/chrome/browser/views/frame/browser_bubble_host.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_BUBBLE_HOST_H_
-#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_BUBBLE_HOST_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_bubble_host.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_BROWSER_BUBBLE_HOST_H_
-
diff --git a/chrome/browser/views/frame/browser_frame.h b/chrome/browser/views/frame/browser_frame.h
deleted file mode 100644
index eaf9fe6..0000000
--- a/chrome/browser/views/frame/browser_frame.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_H_
-#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_frame.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_H_
-
diff --git a/chrome/browser/views/frame/browser_frame_gtk.h b/chrome/browser/views/frame/browser_frame_gtk.h
deleted file mode 100644
index 1b8977c..0000000
--- a/chrome/browser/views/frame/browser_frame_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_GTK_H_
-#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_GTK_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_frame_gtk.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_GTK_H_
-
diff --git a/chrome/browser/views/frame/browser_frame_win.h b/chrome/browser/views/frame/browser_frame_win.h
deleted file mode 100644
index b755e21..0000000
--- a/chrome/browser/views/frame/browser_frame_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_WIN_H_
-#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_frame_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_WIN_H_
-
diff --git a/chrome/browser/views/frame/browser_non_client_frame_view.h b/chrome/browser/views/frame/browser_non_client_frame_view.h
deleted file mode 100644
index 38b6cfd..0000000
--- a/chrome/browser/views/frame/browser_non_client_frame_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
-
diff --git a/chrome/browser/views/frame/browser_root_view.h b/chrome/browser/views/frame/browser_root_view.h
deleted file mode 100644
index bf129da..0000000
--- a/chrome/browser/views/frame/browser_root_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_POPUP_BROWSER_ROOT_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_POPUP_BROWSER_ROOT_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_root_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_POPUP_BROWSER_ROOT_VIEW_H_
-
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
deleted file mode 100644
index 4e90f82..0000000
--- a/chrome/browser/views/frame/browser_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_POPUP_BROWSER_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_POPUP_BROWSER_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_POPUP_BROWSER_VIEW_H_
-
diff --git a/chrome/browser/views/frame/browser_view_layout.h b/chrome/browser/views/frame/browser_view_layout.h
deleted file mode 100644
index a96fa8e..0000000
--- a/chrome/browser/views/frame/browser_view_layout.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
-#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_view_layout.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
-
diff --git a/chrome/browser/views/frame/contents_container.h b/chrome/browser/views/frame/contents_container.h
deleted file mode 100644
index 07b7983..0000000
--- a/chrome/browser/views/frame/contents_container.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_CONTENTS_CONTAINER_H_
-#define CHROME_BROWSER_VIEWS_FRAME_CONTENTS_CONTAINER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/contents_container.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_CONTENTS_CONTAINER_H_
-
diff --git a/chrome/browser/views/frame/glass_browser_frame_view.h b/chrome/browser/views/frame/glass_browser_frame_view.h
deleted file mode 100644
index 397ef26..0000000
--- a/chrome/browser/views/frame/glass_browser_frame_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_
-
diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.h b/chrome/browser/views/frame/opaque_browser_frame_view.h
deleted file mode 100644
index 3e11721..0000000
--- a/chrome/browser/views/frame/opaque_browser_frame_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_H_
-
diff --git a/chrome/browser/views/frame/popup_non_client_frame_view.h b/chrome/browser/views/frame/popup_non_client_frame_view.h
deleted file mode 100644
index 4866d34..0000000
--- a/chrome/browser/views/frame/popup_non_client_frame_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FRAME_POPUP_NON_CLIENT_FRAME_VIEW_H_
-#define CHROME_BROWSER_VIEWS_FRAME_POPUP_NON_CLIENT_FRAME_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/popup_non_client_frame_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FRAME_POPUP_NON_CLIENT_FRAME_VIEW_H_
-
diff --git a/chrome/browser/views/fullscreen_exit_bubble.h b/chrome/browser/views/fullscreen_exit_bubble.h
deleted file mode 100644
index fc71d5c..0000000
--- a/chrome/browser/views/fullscreen_exit_bubble.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_FULLSCREEN_EXIT_BUBBLE_H_
-#define CHROME_BROWSER_VIEWS_FULLSCREEN_EXIT_BUBBLE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/fullscreen_exit_bubble.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_FULLSCREEN_EXIT_BUBBLE_H_
-
diff --git a/chrome/browser/views/generic_info_view.h b/chrome/browser/views/generic_info_view.h
deleted file mode 100644
index 014ae18..0000000
--- a/chrome/browser/views/generic_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_GENERIC_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_GENERIC_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/generic_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_GENERIC_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/html_dialog_view.h b/chrome/browser/views/html_dialog_view.h
deleted file mode 100644
index c26c76a..0000000
--- a/chrome/browser/views/html_dialog_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_HTML_DIALOG_VIEW_H_
-#define CHROME_BROWSER_VIEWS_HTML_DIALOG_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/html_dialog_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_HTML_DIALOG_VIEW_H_
-
diff --git a/chrome/browser/views/importer_lock_view.h b/chrome/browser/views/importer_lock_view.h
deleted file mode 100644
index 1c64d40..0000000
--- a/chrome/browser/views/importer_lock_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_IMPORTER_LOCK_VIEW_H_
-#define CHROME_BROWSER_IMPORTER_LOCK_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/importer_lock_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_IMPORTER_LOCK_VIEW_H_
-
diff --git a/chrome/browser/views/importer_view.h b/chrome/browser/views/importer_view.h
deleted file mode 100644
index 44afa36..0000000
--- a/chrome/browser/views/importer_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_IMPORTER_VIEW_H_
-#define CHROME_BROWSER_VIEWS_IMPORTER_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/importer_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_IMPORTER_VIEW_H_
-
diff --git a/chrome/browser/views/importing_progress_view.h b/chrome/browser/views/importing_progress_view.h
deleted file mode 100644
index 5805c52..0000000
--- a/chrome/browser/views/importing_progress_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_IMPORTING_PROGRESS_VIEW_H_
-#define CHROME_BROWSER_VIEWS_IMPORTING_PROGRESS_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/importing_progress_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_IMPORTING_PROGRESS_VIEW_H_
-
diff --git a/chrome/browser/views/indexed_db_info_view.h b/chrome/browser/views/indexed_db_info_view.h
deleted file mode 100644
index 6f2ccb4..0000000
--- a/chrome/browser/views/indexed_db_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INDEXED_DB_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_INDEXED_DB_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/indexed_db_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INDEXED_DB_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/info_bubble.h b/chrome/browser/views/info_bubble.h
deleted file mode 100644
index bd7dba6..0000000
--- a/chrome/browser/views/info_bubble.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFO_BUBBLE_H_
-#define CHROME_BROWSER_VIEWS_INFO_BUBBLE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/info_bubble.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFO_BUBBLE_H_
-
diff --git a/chrome/browser/views/infobars/after_translate_infobar.h b/chrome/browser/views/infobars/after_translate_infobar.h
deleted file mode 100644
index d0c8fcc..0000000
--- a/chrome/browser/views/infobars/after_translate_infobar.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_AFTER_TRANSLATE_INFOBAR_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_AFTER_TRANSLATE_INFOBAR_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/after_translate_infobar.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_AFTER_TRANSLATE_INFOBAR_H_
-
diff --git a/chrome/browser/views/infobars/before_translate_infobar.h b/chrome/browser/views/infobars/before_translate_infobar.h
deleted file mode 100644
index 1cf685c..0000000
--- a/chrome/browser/views/infobars/before_translate_infobar.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_BEFORE_TRANSLATE_INFOBAR_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_BEFORE_TRANSLATE_INFOBAR_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/before_translate_infobar.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_BEFORE_TRANSLATE_INFOBAR_H_
-
diff --git a/chrome/browser/views/infobars/extension_infobar.h b/chrome/browser/views/infobars/extension_infobar.h
deleted file mode 100644
index 0b1ae4a..0000000
--- a/chrome/browser/views/infobars/extension_infobar.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_EXTENSION_INFOBAR_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_EXTENSION_INFOBAR_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/extension_infobar.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_EXTENSION_INFOBAR_H_
-
diff --git a/chrome/browser/views/infobars/infobar_button_border.h b/chrome/browser/views/infobars/infobar_button_border.h
deleted file mode 100644
index daafb16..0000000
--- a/chrome/browser/views/infobars/infobar_button_border.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_BUTTON_BORDER_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_BUTTON_BORDER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/infobar_button_border.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_BUTTON_BORDER_H_
-
diff --git a/chrome/browser/views/infobars/infobar_container.h b/chrome/browser/views/infobars/infobar_container.h
deleted file mode 100644
index 13c3f56..0000000
--- a/chrome/browser/views/infobars/infobar_container.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/infobar_container.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
-
diff --git a/chrome/browser/views/infobars/infobar_text_button.h b/chrome/browser/views/infobars/infobar_text_button.h
deleted file mode 100644
index 7255f0d..0000000
--- a/chrome/browser/views/infobars/infobar_text_button.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_TEXT_BUTTON_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_TEXT_BUTTON_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/infobar_text_button.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_TEXT_BUTTON_H_
-
diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h
deleted file mode 100644
index 9345bdc..0000000
--- a/chrome/browser/views/infobars/infobars.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/infobars.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_
-
diff --git a/chrome/browser/views/infobars/translate_infobar_base.h b/chrome/browser/views/infobars/translate_infobar_base.h
deleted file mode 100644
index 84b68dc..0000000
--- a/chrome/browser/views/infobars/translate_infobar_base.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_INFOBAR_BASE_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_INFOBAR_BASE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/translate_infobar_base.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_INFOBAR_BASE_H_
-
diff --git a/chrome/browser/views/infobars/translate_message_infobar.h b/chrome/browser/views/infobars/translate_message_infobar.h
deleted file mode 100644
index d893fe7..0000000
--- a/chrome/browser/views/infobars/translate_message_infobar.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_MESSAGE_INFOBAR_H_
-#define CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_MESSAGE_INFOBAR_H_
-#pragma once
-
-#include "chrome/browser/ui/views/infobars/translate_message_infobar.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INFOBARS_TRANSLATE_MESSAGE_INFOBAR_H_
-
diff --git a/chrome/browser/views/instant_confirm_view.h b/chrome/browser/views/instant_confirm_view.h
deleted file mode 100644
index d0f87d4..0000000
--- a/chrome/browser/views/instant_confirm_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_INSTANT_CONFIRM_VIEW_H_
-#define CHROME_BROWSER_VIEWS_INSTANT_CONFIRM_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/instant_confirm_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_INSTANT_CONFIRM_VIEW_H_
-
diff --git a/chrome/browser/views/js_modal_dialog_views.h b/chrome/browser/views/js_modal_dialog_views.h
deleted file mode 100644
index a5c6425..0000000
--- a/chrome/browser/views/js_modal_dialog_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_JS_MODAL_DIALOG_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_JS_MODAL_DIALOG_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/js_modal_dialog_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_JS_MODAL_DIALOG_VIEWS_H_
-
diff --git a/chrome/browser/views/keyword_editor_view.h b/chrome/browser/views/keyword_editor_view.h
deleted file mode 100644
index a3f5b8f..0000000
--- a/chrome/browser/views/keyword_editor_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_KEYWORD_EDITOR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_KEYWORD_EDITOR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/keyword_editor_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_KEYWORD_EDITOR_VIEW_H_
-
diff --git a/chrome/browser/views/list_background.h b/chrome/browser/views/list_background.h
deleted file mode 100644
index 4cf550b..0000000
--- a/chrome/browser/views/list_background.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LIST_BACKGROUND_H_
-#define CHROME_BROWSER_VIEWS_LIST_BACKGROUND_H_
-#pragma once
-
-#include "chrome/browser/ui/views/list_background.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LIST_BACKGROUND_H_
-
diff --git a/chrome/browser/views/local_storage_info_view.h b/chrome/browser/views/local_storage_info_view.h
deleted file mode 100644
index 3550959..0000000
--- a/chrome/browser/views/local_storage_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCAL_STORAGE_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCAL_STORAGE_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/local_storage_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCAL_STORAGE_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/local_storage_set_item_info_view.h b/chrome/browser/views/local_storage_set_item_info_view.h
deleted file mode 100644
index ee16aaa..0000000
--- a/chrome/browser/views/local_storage_set_item_info_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCAL_STORAGE_SET_ITEM_INFO_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCAL_STORAGE_SET_ITEM_INFO_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/local_storage_set_item_info_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCAL_STORAGE_SET_ITEM_INFO_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/click_handler.h b/chrome/browser/views/location_bar/click_handler.h
deleted file mode 100644
index 155e501..0000000
--- a/chrome/browser/views/location_bar/click_handler.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_CLICK_HANDLER_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_CLICK_HANDLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/click_handler.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_CLICK_HANDLER_H_
-
diff --git a/chrome/browser/views/location_bar/content_setting_image_view.h b/chrome/browser/views/location_bar/content_setting_image_view.h
deleted file mode 100644
index 1bcb7bf..0000000
--- a/chrome/browser/views/location_bar/content_setting_image_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/ev_bubble_view.h b/chrome/browser/views/location_bar/ev_bubble_view.h
deleted file mode 100644
index 1070a6b..0000000
--- a/chrome/browser/views/location_bar/ev_bubble_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.h b/chrome/browser/views/location_bar/icon_label_bubble_view.h
deleted file mode 100644
index 9e3dde6..0000000
--- a/chrome/browser/views/location_bar/icon_label_bubble_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_ICON_LABEL_BUBBLE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_ICON_LABEL_BUBBLE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_ICON_LABEL_BUBBLE_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/keyword_hint_view.h b/chrome/browser/views/location_bar/keyword_hint_view.h
deleted file mode 100644
index defea0e..0000000
--- a/chrome/browser/views/location_bar/keyword_hint_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_KEYWORD_HINT_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_KEYWORD_HINT_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_KEYWORD_HINT_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/location_bar_view.h b/chrome/browser/views/location_bar/location_bar_view.h
deleted file mode 100644
index 1e2b2d7..0000000
--- a/chrome/browser/views/location_bar/location_bar_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_BAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_BAR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_BAR_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/location_icon_view.h b/chrome/browser/views/location_bar/location_icon_view.h
deleted file mode 100644
index d0de238..0000000
--- a/chrome/browser/views/location_bar/location_icon_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/page_action_image_view.h b/chrome/browser/views/location_bar/page_action_image_view.h
deleted file mode 100644
index aa01f4d..0000000
--- a/chrome/browser/views/location_bar/page_action_image_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_IMAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_IMAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_IMAGE_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/page_action_with_badge_view.h b/chrome/browser/views/location_bar/page_action_with_badge_view.h
deleted file mode 100644
index 4bdc71e..0000000
--- a/chrome/browser/views/location_bar/page_action_with_badge_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/selected_keyword_view.h b/chrome/browser/views/location_bar/selected_keyword_view.h
deleted file mode 100644
index bce29d0..0000000
--- a/chrome/browser/views/location_bar/selected_keyword_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_SELECTED_KEYWORD_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_SELECTED_KEYWORD_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_SELECTED_KEYWORD_VIEW_H_
-
diff --git a/chrome/browser/views/location_bar/star_view.h b/chrome/browser/views/location_bar/star_view.h
deleted file mode 100644
index a964d14..0000000
--- a/chrome/browser/views/location_bar/star_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOCATION_BAR_STAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOCATION_BAR_STAR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/location_bar/star_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOCATION_BAR_STAR_VIEW_H_
-
diff --git a/chrome/browser/views/login_view.h b/chrome/browser/views/login_view.h
deleted file mode 100644
index bb45e10..0000000
--- a/chrome/browser/views/login_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_LOGIN_VIEW_H_
-#define CHROME_BROWSER_VIEWS_LOGIN_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/login_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_LOGIN_VIEW_H_
-
diff --git a/chrome/browser/views/modal_dialog_delegate.h b/chrome/browser/views/modal_dialog_delegate.h
deleted file mode 100644
index 06cba14..0000000
--- a/chrome/browser/views/modal_dialog_delegate.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_MODAL_DIALOG_DELEGATE_H_
-#define CHROME_BROWSER_VIEWS_MODAL_DIALOG_DELEGATE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/modal_dialog_delegate.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_MODAL_DIALOG_DELEGATE_H_
-
diff --git a/chrome/browser/views/notifications/balloon_view.h b/chrome/browser/views/notifications/balloon_view.h
deleted file mode 100644
index 2896feb..0000000
--- a/chrome/browser/views/notifications/balloon_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_H_
-#define CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/notifications/balloon_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_H_
-
diff --git a/chrome/browser/views/notifications/balloon_view_host.h b/chrome/browser/views/notifications/balloon_view_host.h
deleted file mode 100644
index 2c1a302..0000000
--- a/chrome/browser/views/notifications/balloon_view_host.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_HOST_H_
-#define CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_HOST_H_
-#pragma once
-
-#include "chrome/browser/ui/views/notifications/balloon_view_host.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_NOTIFICATIONS_BALLOON_VIEW_HOST_H_
-
diff --git a/chrome/browser/views/options/advanced_contents_view.h b/chrome/browser/views/options/advanced_contents_view.h
deleted file mode 100644
index 9026e82..0000000
--- a/chrome/browser/views/options/advanced_contents_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_ADVANCED_CONTENTS_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_ADVANCED_CONTENTS_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/advanced_contents_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_ADVANCED_CONTENTS_VIEW_H_
-
diff --git a/chrome/browser/views/options/advanced_page_view.h b/chrome/browser/views/options/advanced_page_view.h
deleted file mode 100644
index dccd66e..0000000
--- a/chrome/browser/views/options/advanced_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_ADVANCED_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_ADVANCED_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/advanced_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_ADVANCED_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/content_exceptions_table_view.h b/chrome/browser/views/options/content_exceptions_table_view.h
deleted file mode 100644
index 6cc48fb..0000000
--- a/chrome/browser/views/options/content_exceptions_table_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_EXCEPTIONS_TABLE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_EXCEPTIONS_TABLE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/content_exceptions_table_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_EXCEPTIONS_TABLE_VIEW_H_
-
diff --git a/chrome/browser/views/options/content_filter_page_view.h b/chrome/browser/views/options/content_filter_page_view.h
deleted file mode 100644
index 0a1115e..0000000
--- a/chrome/browser/views/options/content_filter_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_FILTER_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_FILTER_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/content_filter_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_FILTER_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/content_page_view.h b/chrome/browser/views/options/content_page_view.h
deleted file mode 100644
index 1335775..0000000
--- a/chrome/browser/views/options/content_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/content_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/content_settings_window_view.h b/chrome/browser/views/options/content_settings_window_view.h
deleted file mode 100644
index a3bc919..0000000
--- a/chrome/browser/views/options/content_settings_window_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_SETTINGS_WINDOW_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_SETTINGS_WINDOW_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/content_settings_window_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_CONTENT_SETTINGS_WINDOW_VIEW_H_
-
diff --git a/chrome/browser/views/options/cookie_filter_page_view.h b/chrome/browser/views/options/cookie_filter_page_view.h
deleted file mode 100644
index 3168e0e..0000000
--- a/chrome/browser/views/options/cookie_filter_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_COOKIE_FILTER_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_COOKIE_FILTER_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/cookie_filter_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_COOKIE_FILTER_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/cookies_view.h b/chrome/browser/views/options/cookies_view.h
deleted file mode 100644
index dd74019..0000000
--- a/chrome/browser/views/options/cookies_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_COOKIES_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_COOKIES_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/cookies_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_COOKIES_VIEW_H_
-
diff --git a/chrome/browser/views/options/exception_editor_view.h b/chrome/browser/views/options/exception_editor_view.h
deleted file mode 100644
index fb63617..0000000
--- a/chrome/browser/views/options/exception_editor_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTION_EDITOR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTION_EDITOR_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/exception_editor_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTION_EDITOR_VIEW_H_
-
diff --git a/chrome/browser/views/options/exceptions_page_view.h b/chrome/browser/views/options/exceptions_page_view.h
deleted file mode 100644
index c9eab58..0000000
--- a/chrome/browser/views/options/exceptions_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/exceptions_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/exceptions_view.h b/chrome/browser/views/options/exceptions_view.h
deleted file mode 100644
index 6ff6f02..0000000
--- a/chrome/browser/views/options/exceptions_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/exceptions_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_EXCEPTIONS_VIEW_H_
-
diff --git a/chrome/browser/views/options/fonts_languages_window_view.h b/chrome/browser/views/options/fonts_languages_window_view.h
deleted file mode 100644
index 1702d9a..0000000
--- a/chrome/browser/views/options/fonts_languages_window_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_FONTS_LANGUAGES_WINDOW_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_FONTS_LANGUAGES_WINDOW_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/fonts_languages_window_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_FONTS_LANGUAGES_WINDOW_VIEW_H_
-
diff --git a/chrome/browser/views/options/fonts_page_view.h b/chrome/browser/views/options/fonts_page_view.h
deleted file mode 100644
index 22cad00..0000000
--- a/chrome/browser/views/options/fonts_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_FONTS_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_FONTS_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/fonts_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_FONTS_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/general_page_view.h b/chrome/browser/views/options/general_page_view.h
deleted file mode 100644
index f9072e1..0000000
--- a/chrome/browser/views/options/general_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_GENERAL_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_GENERAL_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/general_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_GENERAL_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/languages_page_view.h b/chrome/browser/views/options/languages_page_view.h
deleted file mode 100644
index 722a893..0000000
--- a/chrome/browser/views/options/languages_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_LANGUAGES_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_LANGUAGES_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/languages_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_LANGUAGES_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/managed_prefs_banner_view.h b/chrome/browser/views/options/managed_prefs_banner_view.h
deleted file mode 100644
index d1efb86..0000000
--- a/chrome/browser/views/options/managed_prefs_banner_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_MANAGED_PREFS_BANNER_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_MANAGED_PREFS_BANNER_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/managed_prefs_banner_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_MANAGED_PREFS_BANNER_VIEW_H_
-
diff --git a/chrome/browser/views/options/options_group_view.h b/chrome/browser/views/options/options_group_view.h
deleted file mode 100644
index b3bf71b..0000000
--- a/chrome/browser/views/options/options_group_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_OPTIONS_GROUP_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_OPTIONS_GROUP_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/options_group_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_OPTIONS_GROUP_VIEW_H_
-
diff --git a/chrome/browser/views/options/options_page_view.h b/chrome/browser/views/options/options_page_view.h
deleted file mode 100644
index 2920edb..0000000
--- a/chrome/browser/views/options/options_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_OPTIONS_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_OPTIONS_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/options_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_OPTIONS_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/passwords_exceptions_window_view.h b/chrome/browser/views/options/passwords_exceptions_window_view.h
deleted file mode 100644
index 7adbd5f..0000000
--- a/chrome/browser/views/options/passwords_exceptions_window_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/passwords_exceptions_window_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_EXCEPTIONS_WINDOW_VIEW_H_
-
diff --git a/chrome/browser/views/options/passwords_page_view.h b/chrome/browser/views/options/passwords_page_view.h
deleted file mode 100644
index 2c4612a..0000000
--- a/chrome/browser/views/options/passwords_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/passwords_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_PASSWORDS_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/plugin_filter_page_view.h b/chrome/browser/views/options/plugin_filter_page_view.h
deleted file mode 100644
index d1d4086..0000000
--- a/chrome/browser/views/options/plugin_filter_page_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_PLUGIN_FILTER_PAGE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_PLUGIN_FILTER_PAGE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/plugin_filter_page_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_PLUGIN_FILTER_PAGE_VIEW_H_
-
diff --git a/chrome/browser/views/options/simple_content_exceptions_view.h b/chrome/browser/views/options/simple_content_exceptions_view.h
deleted file mode 100644
index 6b89cd9..0000000
--- a/chrome/browser/views/options/simple_content_exceptions_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_VIEW_H_
-#define CHROME_BROWSER_VIEWS_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/options/simple_content_exceptions_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_OPTIONS_SIMPLE_CONTENT_EXCEPTIONS_VIEW_H_
-
diff --git a/chrome/browser/views/page_info_bubble_view.h b/chrome/browser/views/page_info_bubble_view.h
deleted file mode 100644
index cb920bb..0000000
--- a/chrome/browser/views/page_info_bubble_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_PAGE_INFO_BUBBLE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_PAGE_INFO_BUBBLE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/page_info_bubble_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_PAGE_INFO_BUBBLE_VIEW_H_
-
diff --git a/chrome/browser/views/pinned_contents_info_bubble.h b/chrome/browser/views/pinned_contents_info_bubble.h
deleted file mode 100644
index a2af973..0000000
--- a/chrome/browser/views/pinned_contents_info_bubble.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_
-#define CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_
-#pragma once
-
-#include "chrome/browser/ui/views/pinned_contents_info_bubble.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_
-
diff --git a/chrome/browser/views/reload_button.h b/chrome/browser/views/reload_button.h
deleted file mode 100644
index 71118e1..0000000
--- a/chrome/browser/views/reload_button.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_RELOAD_BUTTON_H_
-#define CHROME_BROWSER_VIEWS_RELOAD_BUTTON_H_
-#pragma once
-
-#include "chrome/browser/ui/views/reload_button.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_RELOAD_BUTTON_H_
-
diff --git a/chrome/browser/views/repost_form_warning_view.h b/chrome/browser/views/repost_form_warning_view.h
deleted file mode 100644
index 1dd6888..0000000
--- a/chrome/browser/views/repost_form_warning_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_REPOST_FORM_WARNING_VIEW_H_
-#define CHROME_BROWSER_VIEWS_REPOST_FORM_WARNING_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/repost_form_warning_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_REPOST_FORM_WARNING_VIEW_H_
-
diff --git a/chrome/browser/views/restart_message_box.h b/chrome/browser/views/restart_message_box.h
deleted file mode 100644
index 1547e92..0000000
--- a/chrome/browser/views/restart_message_box.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_RESTART_MESSAGE_BOX_H_
-#define CHROME_BROWSER_VIEWS_RESTART_MESSAGE_BOX_H_
-#pragma once
-
-#include "chrome/browser/ui/views/restart_message_box.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_RESTART_MESSAGE_BOX_H_
-
diff --git a/chrome/browser/views/sad_tab_view.h b/chrome/browser/views/sad_tab_view.h
deleted file mode 100644
index f21d8e8..0000000
--- a/chrome/browser/views/sad_tab_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_SAD_TAB_VIEW_H_
-#define CHROME_BROWSER_VIEWS_SAD_TAB_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/sad_tab_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_SAD_TAB_VIEW_H_
-
diff --git a/chrome/browser/views/status_bubble_views.h b/chrome/browser/views/status_bubble_views.h
deleted file mode 100644
index 3d10bd4..0000000
--- a/chrome/browser/views/status_bubble_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_STATUS_BUBBLE_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_STATUS_BUBBLE_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/status_bubble_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_STATUS_BUBBLE_VIEWS_H_
-
diff --git a/chrome/browser/views/status_icons/status_icon_win.h b/chrome/browser/views/status_icons/status_icon_win.h
deleted file mode 100644
index 1f7ce62..0000000
--- a/chrome/browser/views/status_icons/status_icon_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_STATUS_ICONS_STATUS_ICON_WIN_H_
-#define CHROME_BROWSER_VIEWS_STATUS_ICONS_STATUS_ICON_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/status_icons/status_icon_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_STATUS_ICONS_STATUS_ICON_WIN_H_
-
diff --git a/chrome/browser/views/status_icons/status_tray_win.h b/chrome/browser/views/status_icons/status_tray_win.h
deleted file mode 100644
index 7d7f301..0000000
--- a/chrome/browser/views/status_icons/status_tray_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_STATUS_ICONS_STATUS_TRAY_WIN_H_
-#define CHROME_BROWSER_VIEWS_STATUS_ICONS_STATUS_TRAY_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/status_icons/status_tray_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_STATUS_ICONS_STATUS_TRAY_WIN_H_
-
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container.h b/chrome/browser/views/tab_contents/native_tab_contents_container.h
deleted file mode 100644
index 7f2cdfc..0000000
--- a/chrome/browser/views/tab_contents/native_tab_contents_container.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_H_
-
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h b/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h
deleted file mode 100644
index cab3c2b..0000000
--- a/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_GTK_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_GTK_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_GTK_H_
-
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container_win.h b/chrome/browser/views/tab_contents/native_tab_contents_container_win.h
deleted file mode 100644
index 5418181..0000000
--- a/chrome/browser/views/tab_contents/native_tab_contents_container_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_WIN_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_NATIVE_TAB_CONTENTS_CONTAINER_WIN_H_
-
diff --git a/chrome/browser/views/tab_contents/render_view_context_menu_views.h b/chrome/browser/views/tab_contents/render_view_context_menu_views.h
deleted file mode 100644
index 98e610d..0000000
--- a/chrome/browser/views/tab_contents/render_view_context_menu_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_VIEWS_H_
-
diff --git a/chrome/browser/views/tab_contents/tab_contents_container.h b/chrome/browser/views/tab_contents/tab_contents_container.h
deleted file mode 100644
index 9039060..0000000
--- a/chrome/browser/views/tab_contents/tab_contents_container.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
-
diff --git a/chrome/browser/views/tab_contents/tab_contents_drag_win.h b/chrome/browser/views/tab_contents/tab_contents_drag_win.h
deleted file mode 100644
index 79067eb..0000000
--- a/chrome/browser/views/tab_contents/tab_contents_drag_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_DRAG_WIN_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_DRAG_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_DRAG_WIN_H_
-
diff --git a/chrome/browser/views/tab_contents/tab_contents_view_gtk.h b/chrome/browser/views/tab_contents/tab_contents_view_gtk.h
deleted file mode 100644
index 3ee3e9a..0000000
--- a/chrome/browser/views/tab_contents/tab_contents_view_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_GTK_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_GTK_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_GTK_H_
-
diff --git a/chrome/browser/views/tab_contents/tab_contents_view_win.h b/chrome/browser/views/tab_contents/tab_contents_view_win.h
deleted file mode 100644
index 49f6a13..0000000
--- a/chrome/browser/views/tab_contents/tab_contents_view_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_WIN_H_
-#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_contents/tab_contents_view_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_VIEW_WIN_H_
-
diff --git a/chrome/browser/views/tab_icon_view.h b/chrome/browser/views/tab_icon_view.h
deleted file mode 100644
index 064c8a7..0000000
--- a/chrome/browser/views/tab_icon_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TAB_ICON_VIEW_H_
-#define CHROME_BROWSER_VIEWS_TAB_ICON_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tab_icon_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TAB_ICON_VIEW_H_
-
diff --git a/chrome/browser/views/tabs/base_tab.h b/chrome/browser/views/tabs/base_tab.h
deleted file mode 100644
index e826fbf..0000000
--- a/chrome/browser/views/tabs/base_tab.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_
-#define CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/base_tab.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_
-
diff --git a/chrome/browser/views/tabs/base_tab_strip.h b/chrome/browser/views/tabs/base_tab_strip.h
deleted file mode 100644
index 603dcf9..0000000
--- a/chrome/browser/views/tabs/base_tab_strip.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_BASE_TAB_STRIP_H_
-#define CHROME_BROWSER_VIEWS_TABS_BASE_TAB_STRIP_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/base_tab_strip.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_STRIP_H_
-
diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.h b/chrome/browser/views/tabs/browser_tab_strip_controller.h
deleted file mode 100644
index 6606f28..0000000
--- a/chrome/browser/views/tabs/browser_tab_strip_controller.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_
-#define CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_
-
diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h
deleted file mode 100644
index e445018..0000000
--- a/chrome/browser/views/tabs/dragged_tab_controller.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_CONTROLLER_H_
-#define CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_CONTROLLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/dragged_tab_controller.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_CONTROLLER_H_
-
diff --git a/chrome/browser/views/tabs/dragged_tab_view.h b/chrome/browser/views/tabs/dragged_tab_view.h
deleted file mode 100644
index 2848baf..0000000
--- a/chrome/browser/views/tabs/dragged_tab_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_VIEW_H_
-#define CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/dragged_tab_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_VIEW_H_
-
diff --git a/chrome/browser/views/tabs/native_view_photobooth.h b/chrome/browser/views/tabs/native_view_photobooth.h
deleted file mode 100644
index 1a954e5..0000000
--- a/chrome/browser/views/tabs/native_view_photobooth.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_
-#define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/native_view_photobooth.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_
-
diff --git a/chrome/browser/views/tabs/native_view_photobooth_gtk.h b/chrome/browser/views/tabs/native_view_photobooth_gtk.h
deleted file mode 100644
index 22c3901..0000000
--- a/chrome/browser/views/tabs/native_view_photobooth_gtk.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_GTK_H_
-#define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_GTK_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_GTK_H_
-
diff --git a/chrome/browser/views/tabs/native_view_photobooth_win.h b/chrome/browser/views/tabs/native_view_photobooth_win.h
deleted file mode 100644
index 2cd2a4b..0000000
--- a/chrome/browser/views/tabs/native_view_photobooth_win.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_
-#define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/native_view_photobooth_win.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_
-
diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h
deleted file mode 100644
index 5d27ce3..0000000
--- a/chrome/browser/views/tabs/side_tab.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_
-#define CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/side_tab.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_
-
diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h
deleted file mode 100644
index cbecf20..0000000
--- a/chrome/browser/views/tabs/side_tab_strip.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_H_
-#define CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/side_tab_strip.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_H_
-
diff --git a/chrome/browser/views/tabs/tab.h b/chrome/browser/views/tabs/tab.h
deleted file mode 100644
index 11076c1..0000000
--- a/chrome/browser/views/tabs/tab.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_H_
-#define CHROME_BROWSER_VIEWS_TABS_TAB_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/tab.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_TAB_H_
-
diff --git a/chrome/browser/views/tabs/tab_controller.h b/chrome/browser/views/tabs/tab_controller.h
deleted file mode 100644
index 5205f5e..0000000
--- a/chrome/browser/views/tabs/tab_controller.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_
-#define CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/tab_controller.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_
-
diff --git a/chrome/browser/views/tabs/tab_renderer_data.h b/chrome/browser/views/tabs/tab_renderer_data.h
deleted file mode 100644
index dca47c9..0000000
--- a/chrome/browser/views/tabs/tab_renderer_data.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_DATA_H_
-#define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_DATA_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_DATA_H_
-
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h
deleted file mode 100644
index 4c24f8c..0000000
--- a/chrome/browser/views/tabs/tab_strip.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_
-#define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/tab_strip.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_
-
diff --git a/chrome/browser/views/tabs/tab_strip_controller.h b/chrome/browser/views/tabs/tab_strip_controller.h
deleted file mode 100644
index b0c7be9..0000000
--- a/chrome/browser/views/tabs/tab_strip_controller.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
-#define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
-
diff --git a/chrome/browser/views/textfield_views.h b/chrome/browser/views/textfield_views.h
deleted file mode 100644
index 3b699f0..0000000
--- a/chrome/browser/views/textfield_views.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TEXTFIELD_VIEWS_H_
-#define CHROME_BROWSER_VIEWS_TEXTFIELD_VIEWS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/textfield_views.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TEXTFIELD_VIEWS_H_
-
diff --git a/chrome/browser/views/theme_background.h b/chrome/browser/views/theme_background.h
deleted file mode 100644
index 98ce8f6..0000000
--- a/chrome/browser/views/theme_background.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_THEME_BACKGROUND_H_
-#define CHROME_BROWSER_VIEWS_THEME_BACKGROUND_H_
-#pragma once
-
-#include "chrome/browser/ui/views/theme_background.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_THEME_BACKGROUND_H_
-
diff --git a/chrome/browser/views/theme_helpers.h b/chrome/browser/views/theme_helpers.h
deleted file mode 100644
index b7bd4f2..0000000
--- a/chrome/browser/views/theme_helpers.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_THEME_HELPERS_H_
-#define CHROME_BROWSER_VIEWS_THEME_HELPERS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/theme_helpers.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_THEME_HELPERS_H_
-
diff --git a/chrome/browser/views/theme_install_bubble_view.h b/chrome/browser/views/theme_install_bubble_view.h
deleted file mode 100644
index b0eddec..0000000
--- a/chrome/browser/views/theme_install_bubble_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_THEME_INSTALL_BUBBLE_VIEW_H_
-#define CHROME_BROWSER_VIEWS_THEME_INSTALL_BUBBLE_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/theme_install_bubble_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_THEME_INSTALL_BUBBLE_VIEW_H_
-
diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h
deleted file mode 100644
index 647f721..0000000
--- a/chrome/browser/views/toolbar_view.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H_
-#define CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H_
-#pragma once
-
- #include "chrome/browser/ui/views/toolbar_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H_
diff --git a/chrome/browser/views/unhandled_keyboard_event_handler.h b/chrome/browser/views/unhandled_keyboard_event_handler.h
deleted file mode 100644
index a007663..0000000
--- a/chrome/browser/views/unhandled_keyboard_event_handler.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_UNHANDLED_KEYBOARD_EVENT_HANDLER_H_
-#define CHROME_BROWSER_VIEWS_UNHANDLED_KEYBOARD_EVENT_HANDLER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_UNHANDLED_KEYBOARD_EVENT_HANDLER_H_
-
diff --git a/chrome/browser/views/uninstall_view.h b/chrome/browser/views/uninstall_view.h
deleted file mode 100644
index e366791..0000000
--- a/chrome/browser/views/uninstall_view.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_UNINSTALL_VIEW_H_
-#define CHROME_BROWSER_VIEWS_UNINSTALL_VIEW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/uninstall_view.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_UNINSTALL_VIEW_H_
-
diff --git a/chrome/browser/views/update_recommended_message_box.h b/chrome/browser/views/update_recommended_message_box.h
deleted file mode 100644
index a5f589e..0000000
--- a/chrome/browser/views/update_recommended_message_box.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UPDATE_RECOMMENDED_MESSAGE_BOX_H_
-#define CHROME_BROWSER_UPDATE_RECOMMENDED_MESSAGE_BOX_H_
-#pragma once
-
-#include "chrome/browser/ui/views/update_recommended_message_box.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_UPDATE_RECOMMENDED_MESSAGE_BOX_H_
-
diff --git a/chrome/browser/views/url_picker.h b/chrome/browser/views/url_picker.h
deleted file mode 100644
index c716ec5..0000000
--- a/chrome/browser/views/url_picker.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_URL_PICKER_H_
-#define CHROME_BROWSER_VIEWS_URL_PICKER_H_
-#pragma once
-
-#include "chrome/browser/ui/views/url_picker.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_URL_PICKER_H_
-
diff --git a/chrome/browser/views/user_data_dir_dialog.h b/chrome/browser/views/user_data_dir_dialog.h
deleted file mode 100644
index 3ca925d..0000000
--- a/chrome/browser/views/user_data_dir_dialog.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_USER_DATA_DIR_DIALOG_H_
-#define CHROME_BROWSER_VIEWS_USER_DATA_DIR_DIALOG_H_
-#pragma once
-
-#include "chrome/browser/ui/views/user_data_dir_dialog.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_USER_DATA_DIR_DIALOG_H_
-
diff --git a/chrome/browser/views/window.h b/chrome/browser/views/window.h
deleted file mode 100644
index 9733676..0000000
--- a/chrome/browser/views/window.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_WINDOW_H_
-#define CHROME_BROWSER_VIEWS_WINDOW_H_
-#pragma once
-
-#include "chrome/browser/ui/views/window.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_WINDOW_H_
-
diff --git a/chrome/browser/views/wrench_menu.h b/chrome/browser/views/wrench_menu.h
deleted file mode 100644
index 1a2c52b..0000000
--- a/chrome/browser/views/wrench_menu.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_WRENCH_MENU_H_
-#define CHROME_BROWSER_VIEWS_WRENCH_MENU_H_
-#pragma once
-
-#include "chrome/browser/ui/views/wrench_menu.h"
-// TODO(beng): remove this file once all includes have been updated.
-
-#endif  // CHROME_BROWSER_VIEWS_WRENCH_MENU_H_
-
diff --git a/chrome/browser/visitedlink/visitedlink_master.cc b/chrome/browser/visitedlink/visitedlink_master.cc
index e4b8444..0c7b923 100644
--- a/chrome/browser/visitedlink/visitedlink_master.cc
+++ b/chrome/browser/visitedlink/visitedlink_master.cc
@@ -950,7 +950,8 @@
   DCHECK(!posted_asynchronous_operation_);
 #endif
 
-  fseek(file, offset, SEEK_SET);
+  if (fseek(file, offset, SEEK_SET) != 0)
+    return false;
 
   size_t num_read = fread(data, 1, data_size, file);
   return num_read == data_size;
diff --git a/chrome/browser/visitedlink/visitedlink_perftest.cc b/chrome/browser/visitedlink/visitedlink_perftest.cc
index 7d44b59..299515f 100644
--- a/chrome/browser/visitedlink/visitedlink_perftest.cc
+++ b/chrome/browser/visitedlink/visitedlink_perftest.cc
@@ -45,14 +45,6 @@
 };
 
 
-// Call at the beginning of the test to retrieve the database name.
-void InitDBName(std::wstring* db_name) {
-  FilePath db_path;
-  ASSERT_TRUE(file_util::GetCurrentDirectory(&db_path));
-  db_path = db_path.AppendASCII("TempVisitedLinks");
-  *db_name = db_path.ToWStringHack();
-}
-
 // this checks IsVisited for the URLs starting with the given prefix and
 // within the given range
 void CheckVisited(VisitedLinkMaster& master, const char* prefix,
@@ -71,13 +63,12 @@
 
 class VisitedLink : public testing::Test {
  protected:
-  std::wstring db_name_;
+  FilePath db_path_;
   virtual void SetUp() {
-    InitDBName(&db_name_);
-    file_util::Delete(db_name_, false);
+    ASSERT_TRUE(file_util::CreateTemporaryFile(&db_path_));
   }
   virtual void TearDown() {
-    file_util::Delete(db_name_, false);
+    file_util::Delete(db_path_, false);
   }
 };
 
@@ -91,7 +82,7 @@
 TEST_F(VisitedLink, TestAddAndQuery) {
   // init
   VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(),
-                           NULL, true, FilePath(db_name_), 0);
+                           NULL, true, db_path_, 0);
   ASSERT_TRUE(master.Init());
 
   PerfTimeLogger timer("Visited_link_add_and_query");
@@ -122,7 +113,7 @@
     PerfTimeLogger table_initialization_timer("Table_initialization");
 
     VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(),
-                             NULL, true, FilePath(db_name_), 0);
+                             NULL, true, db_path_, 0);
 
     // time init with empty table
     PerfTimeLogger initTimer("Empty_visited_link_init");
@@ -153,8 +144,7 @@
   std::vector<double> hot_load_times;
   for (int i = 0; i < load_count; i++) {
     // make sure the file has to be re-loaded
-    file_util::EvictFileFromSystemCache(
-        FilePath::FromWStringHack(std::wstring(db_name_)));
+    file_util::EvictFileFromSystemCache(db_path_);
 
     // cold load (no OS cache, hopefully)
     {
@@ -163,7 +153,7 @@
       VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(),
                                NULL,
                                true,
-                               FilePath(db_name_),
+                               db_path_,
                                0);
       bool success = master.Init();
       TimeDelta elapsed = cold_timer.Elapsed();
@@ -179,7 +169,7 @@
       VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(),
                                NULL,
                                true,
-                               FilePath(db_name_),
+                               db_path_,
                                0);
       bool success = master.Init();
       TimeDelta elapsed = hot_timer.Elapsed();
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index 2c619e2..6d269d2 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -29,6 +29,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_plugin_util.h"
+#include "chrome/common/extensions/extension.h"
 #include "chrome/common/notification_registrar.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/web_apps.h"
@@ -41,7 +42,7 @@
 #include "base/win/win_util.h"
 #include "chrome/common/notification_details.h"
 #include "chrome/common/notification_source.h"
-#include "gfx/icon_util.h"
+#include "ui/gfx/icon_util.h"
 #endif  // defined(OS_WIN)
 
 namespace {
@@ -90,27 +91,37 @@
 #endif  // defined(OS_WIN)
 
 // Returns relative directory of given web app url.
-FilePath GetWebAppDir(const GURL& url) {
-  FilePath::StringType host;
-  FilePath::StringType scheme_port;
+FilePath GetWebAppDir(const ShellIntegration::ShortcutInfo& info) {
+  if (!info.extension_id.empty()) {
+    std::string app_name = web_app::GenerateApplicationNameFromExtensionId(
+        UTF16ToUTF8(info.extension_id));
+#if defined(OS_WIN)
+    return FilePath(UTF8ToWide(app_name));
+#elif defined(OS_POSIX)
+    return FilePath(app_name);
+#endif
+  } else {
+    FilePath::StringType host;
+    FilePath::StringType scheme_port;
 
 #if defined(OS_WIN)
-  host = UTF8ToWide(url.host());
-  scheme_port = (url.has_scheme() ? UTF8ToWide(url.scheme()) : L"http") +
-      FILE_PATH_LITERAL("_") +
-      (url.has_port() ? UTF8ToWide(url.port()) : L"80");
+    host = UTF8ToWide(info.url.host());
+    scheme_port = (info.url.has_scheme() ? UTF8ToWide(info.url.scheme())
+        : L"http") + FILE_PATH_LITERAL("_") +
+        (info.url.has_port() ? UTF8ToWide(info.url.port()) : L"80");
 #elif defined(OS_POSIX)
-  host = url.host();
-  scheme_port = url.scheme() + FILE_PATH_LITERAL("_") + url.port();
+    host = info.url.host();
+    scheme_port = info.url.scheme() + FILE_PATH_LITERAL("_") + info.url.port();
 #endif
 
-  return FilePath(host).Append(scheme_port);
+    return FilePath(host).Append(scheme_port);
+  }
 }
 
 // Returns data directory for given web app url
 FilePath GetWebAppDataDirectory(const FilePath& root_dir,
-                                const GURL& url) {
-  return root_dir.Append(GetWebAppDir(url));
+                                const ShellIntegration::ShortcutInfo& info) {
+  return root_dir.Append(GetWebAppDir(info));
 }
 
 #if defined(TOOLKIT_VIEWS)
@@ -242,8 +253,9 @@
     const FilePath& profile_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
     web_app::CreateShortcutCallback* callback)
-    : web_app_path_(GetWebAppDataDirectory(web_app::GetDataDir(profile_path),
-                                           shortcut_info.url)),
+    : web_app_path_(GetWebAppDataDirectory(
+        web_app::GetDataDir(profile_path),
+        shortcut_info)),
       profile_path_(profile_path),
       shortcut_info_(shortcut_info),
       callback_(callback),
@@ -376,9 +388,16 @@
     shortcut_info_.description.resize(MAX_PATH - 1);
 
   // Generates app id from web app url and profile path.
+  std::string app_name;
+  if (!shortcut_info_.extension_id.empty()) {
+    app_name = web_app::GenerateApplicationNameFromExtensionId(
+        UTF16ToUTF8(shortcut_info_.extension_id));
+  } else {
+    app_name = web_app::GenerateApplicationNameFromURL(
+        shortcut_info_.url);
+  }
   std::wstring app_id = ShellIntegration::GetAppId(
-      UTF8ToWide(web_app::GenerateApplicationNameFromURL(shortcut_info_.url)),
-      profile_path_);
+      UTF8ToWide(app_name), profile_path_);
 
   FilePath shortcut_to_pin;
 
@@ -615,7 +634,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   FilePath web_app_path = GetWebAppDataDirectory(
-      web_app::GetDataDir(profile_path_), shortcut_info_.url);
+      web_app::GetDataDir(profile_path_), shortcut_info_);
 
   // Ensure web_app_path exists. web_app_path could be missing for a legacy
   // shortcut created by gears.
@@ -685,6 +704,14 @@
 
 namespace web_app {
 
+// The following string is used to build the directory name for
+// shortcuts to chrome applications (the kind which are installed
+// from a CRX).  Application shortcuts to URLs use the {host}_{path}
+// for the name of this directory.  Hosts can't include an underscore.
+// By starting this string with an underscore, we ensure that there
+// are no naming conflicts.
+static const char* kCrxAppPrefix = "_crx_";
+
 std::string GenerateApplicationNameFromURL(const GURL& url) {
   std::string t;
   t.append(url.host());
@@ -693,6 +720,12 @@
   return t;
 }
 
+std::string GenerateApplicationNameFromExtensionId(const std::string& id) {
+  std::string t(web_app::kCrxAppPrefix);
+  t.append(id);
+  return t;
+}
+
 void CreateShortcut(
     const FilePath& data_dir,
     const ShellIntegration::ShortcutInfo& shortcut_info,
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index 4734b7e..76b666c 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -24,6 +24,9 @@
 // as app id for BrowserWindow, shortcut and jump list.
 std::string GenerateApplicationNameFromURL(const GURL& url);
 
+// Compute a deterministic name based on an extension/apps's id.
+std::string GenerateApplicationNameFromExtensionId(const std::string& id);
+
 // Callback after user dismisses CreateShortcutView. "true" indicates
 // shortcut is created successfully. Otherwise, it is false.
 typedef Callback1<bool>::Type CreateShortcutCallback;
@@ -32,7 +35,7 @@
 // |profile_path| is used as root directory for persisted data such as icon.
 // Directory layout is similar to what Gears has, i.e. an web application's
 // file is stored under "#/host_name/scheme_port", where '#' is the
-// |root_dir|.
+// |root_dir|.  A crx based app uses a directory named _crx_<app id>.
 void CreateShortcut(
     const FilePath& profile_path,
     const ShellIntegration::ShortcutInfo& shortcut_info,
diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc
index cdee197..dad4343 100644
--- a/chrome/browser/web_resource/web_resource_service.cc
+++ b/chrome/browser/web_resource/web_resource_service.cc
@@ -1,19 +1,23 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/browser/web_resource/web_resource_service.h"
 
+#include <string>
+
 #include "base/command_line.h"
 #include "base/file_path.h"
 #include "base/string_util.h"
 #include "base/string_number_conversions.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/common/chrome_switches.h"
@@ -34,6 +38,21 @@
 // Delay between calls to update the cache (48 hours).
 static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000;
 
+// Users are randomly assigned to one of kNTPPromoGroupSize buckets, in order
+// to be able to roll out promos slowly, or display different promos to
+// different groups.
+static const int kNTPPromoGroupSize = 16;
+
+// Maximum number of hours for each time slice (4 weeks).
+static const int kMaxTimeSliceHours = 24 * 7 * 4;
+
+// Used to determine which build type should be shown a given promo.
+enum BuildType {
+  DEV_BUILD = 1,
+  BETA_BUILD = 1 << 1,
+  STABLE_BUILD = 1 << 2,
+};
+
 }  // namespace
 
 const char* WebResourceService::kCurrentTipPrefName = "current_tip";
@@ -49,7 +68,7 @@
 
   // Delay initial load of resource data into cache so as not to interfere
   // with startup time.
-  void StartAfterDelay(int delay_ms) {
+  void StartAfterDelay(int64 delay_ms) {
     MessageLoop::current()->PostDelayedTask(FROM_HERE,
       fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch),
                                          delay_ms);
@@ -70,21 +89,27 @@
     else
       web_resource_service_->in_fetch_ = true;
 
+    std::string locale = g_browser_process->GetApplicationLocale();
+    std::string web_resource_server = kDefaultWebResourceServer;
+    web_resource_server.append(locale);
+
     url_fetcher_.reset(new URLFetcher(GURL(
-        kDefaultWebResourceServer),
+        web_resource_server),
         URLFetcher::GET, this));
     // Do not let url fetcher affect existing state in profile (by setting
     // cookies, for example.
     url_fetcher_->set_load_flags(net::LOAD_DISABLE_CACHE |
       net::LOAD_DO_NOT_SAVE_COOKIES);
-    url_fetcher_->set_request_context(Profile::GetDefaultRequestContext());
+    URLRequestContextGetter* url_request_context_getter =
+        web_resource_service_->profile()->GetRequestContext();
+    url_fetcher_->set_request_context(url_request_context_getter);
     url_fetcher_->Start();
   }
 
   // From URLFetcher::Delegate.
   void OnURLFetchComplete(const URLFetcher* source,
                           const GURL& url,
-                          const URLRequestStatus& status,
+                          const net::URLRequestStatus& status,
                           int response_code,
                           const ResponseCookies& cookies,
                           const std::string& data) {
@@ -203,7 +228,7 @@
 // Server for dynamically loaded NTP HTML elements. TODO(mirandac): append
 // locale for future usage, when we're serving localizable strings.
 const char* WebResourceService::kDefaultWebResourceServer =
-    "https://www.google.com/support/chrome/bin/topic/30248/inproduct";
+    "https://www.google.com/support/chrome/bin/topic/1142433/inproduct?hl=";
 
 WebResourceService::WebResourceService(Profile* profile)
     : prefs_(profile->GetPrefs()),
@@ -221,17 +246,21 @@
   resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host();
   web_resource_fetcher_.reset(new WebResourceFetcher(this));
   prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0");
-  prefs_->RegisterRealPref(prefs::kNTPCustomLogoStart, 0);
-  prefs_->RegisterRealPref(prefs::kNTPCustomLogoEnd, 0);
-  prefs_->RegisterRealPref(prefs::kNTPPromoStart, 0);
-  prefs_->RegisterRealPref(prefs::kNTPPromoEnd, 0);
+  prefs_->RegisterDoublePref(prefs::kNTPCustomLogoStart, 0);
+  prefs_->RegisterDoublePref(prefs::kNTPCustomLogoEnd, 0);
+  prefs_->RegisterDoublePref(prefs::kNTPPromoStart, 0);
+  prefs_->RegisterDoublePref(prefs::kNTPPromoEnd, 0);
   prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string());
   prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false);
+  prefs_->RegisterIntegerPref(prefs::kNTPPromoGroup, -1);
+  prefs_->RegisterIntegerPref(prefs::kNTPPromoBuild,
+                              DEV_BUILD | BETA_BUILD | STABLE_BUILD);
+  prefs_->RegisterIntegerPref(prefs::kNTPPromoGroupTimeSlice, 0);
 
   // If the promo start is in the future, set a notification task to invalidate
   // the NTP cache at the time of the promo start.
-  double promo_start = prefs_->GetReal(prefs::kNTPPromoStart);
-  double promo_end = prefs_->GetReal(prefs::kNTPPromoEnd);
+  double promo_start = prefs_->GetDouble(prefs::kNTPPromoStart);
+  double promo_end = prefs_->GetDouble(prefs::kNTPPromoEnd);
   ScheduleNotification(promo_start, promo_end);
 }
 
@@ -242,8 +271,7 @@
 void WebResourceService::OnWebResourceUnpacked(
   const DictionaryValue& parsed_json) {
   UnpackLogoSignal(parsed_json);
-  if (WebResourceServiceUtil::CanShowPromo(profile_))
-    UnpackPromoSignal(parsed_json);
+  UnpackPromoSignal(parsed_json);
   EndFetch();
 }
 
@@ -258,11 +286,11 @@
 void WebResourceService::ScheduleNotification(double promo_start,
                                               double promo_end) {
   if (promo_start > 0 && promo_end > 0 && !web_resource_update_scheduled_) {
-    int ms_until_start =
-        static_cast<int>((base::Time::FromDoubleT(
+    int64 ms_until_start =
+        static_cast<int64>((base::Time::FromDoubleT(
             promo_start) - base::Time::Now()).InMilliseconds());
-    int ms_until_end =
-        static_cast<int>((base::Time::FromDoubleT(
+    int64 ms_until_end =
+        static_cast<int64>((base::Time::FromDoubleT(
             promo_end) - base::Time::Now()).InMilliseconds());
     if (ms_until_start > 0) {
       web_resource_update_scheduled_ = true;
@@ -286,7 +314,7 @@
 }
 
 void WebResourceService::StartAfterDelay() {
-  int delay = kStartResourceFetchDelay;
+  int64 delay = kStartResourceFetchDelay;
   // Check whether we have ever put a value in the web resource cache;
   // if so, pull it out and see if it's time to update again.
   if (prefs_->HasPrefPath(prefs::kNTPWebResourceCacheUpdate)) {
@@ -295,8 +323,8 @@
     if (!last_update_pref.empty()) {
       double last_update_value;
       base::StringToDouble(last_update_pref, &last_update_value);
-      int ms_until_update = cache_update_delay_ -
-          static_cast<int>((base::Time::Now() - base::Time::FromDoubleT(
+      int64 ms_until_update = cache_update_delay_ -
+          static_cast<int64>((base::Time::Now() - base::Time::FromDoubleT(
           last_update_value)).InMilliseconds());
       delay = ms_until_update > cache_update_delay_ ?
           cache_update_delay_ : (ms_until_update < kStartResourceFetchDelay ?
@@ -304,7 +332,7 @@
     }
   }
   // Start fetch and wait for UpdateResourceCache.
-  web_resource_fetcher_->StartAfterDelay(static_cast<int>(delay));
+  web_resource_fetcher_->StartAfterDelay(delay);
 }
 
 void WebResourceService::UpdateResourceCache(const std::string& json_data) {
@@ -367,8 +395,8 @@
   // Check for preexisting start and end values.
   if (prefs_->HasPrefPath(prefs::kNTPPromoStart) &&
       prefs_->HasPrefPath(prefs::kNTPPromoEnd)) {
-    old_promo_start = prefs_->GetReal(prefs::kNTPPromoStart);
-    old_promo_end = prefs_->GetReal(prefs::kNTPPromoEnd);
+    old_promo_start = prefs_->GetDouble(prefs::kNTPPromoStart);
+    old_promo_end = prefs_->GetDouble(prefs::kNTPPromoEnd);
   }
 
   // Check for newly received start and end values.
@@ -377,6 +405,9 @@
       std::string promo_start_string = "";
       std::string promo_end_string = "";
       std::string promo_string = "";
+      std::string promo_build = "";
+      int promo_build_type = 0;
+      int time_slice_hrs = 0;
       for (ListValue::const_iterator tip_iter = answer_list->begin();
            tip_iter != answer_list->end(); ++tip_iter) {
         if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY))
@@ -386,9 +417,33 @@
         std::string promo_signal;
         if (a_dic->GetString("name", &promo_signal)) {
           if (promo_signal == "promo_start") {
+            a_dic->GetString("question", &promo_build);
+            size_t split = promo_build.find(":");
+            if (split != std::string::npos &&
+                base::StringToInt(promo_build.substr(0, split),
+                                  &promo_build_type) &&
+                base::StringToInt(promo_build.substr(split+1),
+                                  &time_slice_hrs) &&
+                promo_build_type >= 0 &&
+                promo_build_type <= (DEV_BUILD | BETA_BUILD | STABLE_BUILD) &&
+                time_slice_hrs >= 0 &&
+                time_slice_hrs <= kMaxTimeSliceHours) {
+              prefs_->SetInteger(prefs::kNTPPromoBuild, promo_build_type);
+              prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice,
+                                 time_slice_hrs);
+            } else {
+              // If no time data or bad time data are set, show promo on all
+              // builds with no time slicing.
+              prefs_->SetInteger(prefs::kNTPPromoBuild,
+                                 DEV_BUILD | BETA_BUILD | STABLE_BUILD);
+              prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, 0);
+            }
             a_dic->GetString("inproduct", &promo_start_string);
             a_dic->GetString("tooltip", &promo_string);
             prefs_->SetString(prefs::kNTPPromoLine, promo_string);
+            srand(static_cast<uint32>(time(NULL)));
+            prefs_->SetInteger(prefs::kNTPPromoGroup,
+                               rand() % kNTPPromoGroupSize);
           } else if (promo_signal == "promo_end") {
             a_dic->GetString("inproduct", &promo_end_string);
           }
@@ -404,7 +459,11 @@
                 ASCIIToWide(promo_start_string).c_str(), &start_time) &&
             base::Time::FromString(
                 ASCIIToWide(promo_end_string).c_str(), &end_time)) {
-          promo_start = start_time.ToDoubleT();
+          // Add group time slice, adjusted from hours to seconds.
+          promo_start = start_time.ToDoubleT() +
+              (prefs_->FindPreference(prefs::kNTPPromoGroup) ?
+                  prefs_->GetInteger(prefs::kNTPPromoGroup) *
+                      time_slice_hrs * 60 * 60 : 0);
           promo_end = end_time.ToDoubleT();
         }
       }
@@ -415,10 +474,12 @@
   // notification, so that the logo on the NTP is updated. This check is
   // outside the reading of the web resource data, because the absence of
   // dates counts as a triggering change if there were dates before.
+  // Also reset the promo closed preference, to signal a new promo.
   if (!(old_promo_start == promo_start) ||
       !(old_promo_end == promo_end)) {
-    prefs_->SetReal(prefs::kNTPPromoStart, promo_start);
-    prefs_->SetReal(prefs::kNTPPromoEnd, promo_end);
+    prefs_->SetDouble(prefs::kNTPPromoStart, promo_start);
+    prefs_->SetDouble(prefs::kNTPPromoEnd, promo_end);
+    prefs_->SetBoolean(prefs::kNTPPromoClosed, false);
     ScheduleNotification(promo_start, promo_end);
   }
 }
@@ -434,8 +495,8 @@
   // Check for preexisting start and end values.
   if (prefs_->HasPrefPath(prefs::kNTPCustomLogoStart) &&
       prefs_->HasPrefPath(prefs::kNTPCustomLogoEnd)) {
-    old_logo_start = prefs_->GetReal(prefs::kNTPCustomLogoStart);
-    old_logo_end = prefs_->GetReal(prefs::kNTPCustomLogoEnd);
+    old_logo_start = prefs_->GetDouble(prefs::kNTPCustomLogoStart);
+    old_logo_end = prefs_->GetDouble(prefs::kNTPCustomLogoEnd);
   }
 
   // Check for newly received start and end values.
@@ -481,8 +542,8 @@
   // dates counts as a triggering change if there were dates before.
   if (!(old_logo_start == logo_start) ||
       !(old_logo_end == logo_end)) {
-    prefs_->SetReal(prefs::kNTPCustomLogoStart, logo_start);
-    prefs_->SetReal(prefs::kNTPCustomLogoEnd, logo_end);
+    prefs_->SetDouble(prefs::kNTPCustomLogoStart, logo_start);
+    prefs_->SetDouble(prefs::kNTPCustomLogoEnd, logo_end);
     NotificationService* service = NotificationService::current();
     service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED,
                     Source<WebResourceService>(this),
@@ -498,32 +559,30 @@
   if (prefs->HasPrefPath(prefs::kNTPPromoClosed))
     promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed);
 
-  bool has_extensions = false;
-  ExtensionService* extensions_service = profile->GetExtensionService();
-  if (extensions_service) {
-    const ExtensionList* extensions = extensions_service->extensions();
-    for (ExtensionList::const_iterator iter = extensions->begin();
-         iter != extensions->end();
-         ++iter) {
-      if ((*iter)->location() == Extension::INTERNAL) {
-        has_extensions = true;
-        break;
-      }
+  // Only show if not synced.
+  bool is_synced =
+      (profile->HasProfileSyncService() &&
+          sync_ui_util::GetStatus(
+              profile->GetProfileSyncService()) == sync_ui_util::SYNCED);
+
+  // GetVersionStringModifier hits the registry. See http://crbug.com/70898.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  const std::string channel = platform_util::GetVersionStringModifier();
+  bool is_promo_build = false;
+  if (prefs->HasPrefPath(prefs::kNTPPromoBuild)) {
+    int builds_allowed = prefs->GetInteger(prefs::kNTPPromoBuild);
+    if (channel == "dev") {
+      is_promo_build = (DEV_BUILD & builds_allowed) != 0;
+    } else if (channel == "beta") {
+      is_promo_build = (BETA_BUILD & builds_allowed) != 0;
+    } else if (channel == "stable") {
+      is_promo_build = (STABLE_BUILD & builds_allowed) != 0;
+    } else {
+      is_promo_build = true;
     }
   }
 
-  // Note that HasProfileSyncService() will be false for ChromeOS, so
-  // promo_options will only be true if the user has an extension installed.
-  // See http://crosbug/10209
-  bool promo_options =
-      (profile->HasProfileSyncService() &&
-          sync_ui_util::GetStatus(
-              profile->GetProfileSyncService()) == sync_ui_util::SYNCED) ||
-      has_extensions;
-
-  return !promo_closed &&
-         promo_options &&
-         g_browser_process->GetApplicationLocale() == "en-US";
+  return !promo_closed && !is_synced && is_promo_build;
 }
 
 }  // namespace WebResourceService
diff --git a/chrome/browser/web_resource/web_resource_service.h b/chrome/browser/web_resource/web_resource_service.h
index 70c8000..815eaf7 100644
--- a/chrome/browser/web_resource/web_resource_service.h
+++ b/chrome/browser/web_resource/web_resource_service.h
@@ -23,6 +23,14 @@
 
 }  // namespace WebResourceService
 
+// A WebResourceService fetches data from a web resource server to be used to
+// dynamically change the appearance of the New Tab Page. For example, it has
+// been used to fetch "tips" to be displayed on the NTP, or to display
+// promotional messages to certain groups of Chrome users.
+//
+// TODO(mirandac): Arrange for a server to be set up specifically for promo
+// messages, which have until now been piggybacked onto the old tips server
+// structure. (see http://crbug.com/70634 for details.)
 class WebResourceService
     : public UtilityProcessHost::Client {
  public:
@@ -65,7 +73,7 @@
   //       {
   //         "answer_id": "1067976",
   //         "name": "promo_start",
-  //         "question": "",
+  //         "question": "1:24",
   //         "tooltip":
   //       "Click \u003ca href=http://www.google.com\u003ehere\u003c/a\u003e!",
   //         "inproduct": "10/8/09 12:00",
@@ -84,6 +92,18 @@
   //   }
   // }
   //
+  // Because the promo signal data is piggybacked onto the tip server, the
+  // values don't exactly correspond with the field names:
+  //
+  // For "promo_start" or "promo_end", the date to start or stop showing the
+  // promotional line is given by the "inproduct" line.
+  // For "promo_start", the promotional line itself is given in the "tooltip"
+  // field. The "question" field gives the type of builds that should be shown
+  // this promo (see the BuildType enum in web_resource_service.cc) and the
+  // number of hours that each promo group should see it, separated by ":".
+  // For example, "7:24" would indicate that all builds should see the promo,
+  // and each group should see it for 24 hours.
+  //
   // Public for unit testing.
   void UnpackPromoSignal(const DictionaryValue& parsed_json);
 
@@ -118,6 +138,8 @@
 
   int cache_update_delay() const { return cache_update_delay_; }
 
+  Profile* profile() const { return profile_; }
+
   static const char* kCurrentTipPrefName;
   static const char* kTipCachePrefName;
 
diff --git a/chrome/browser/web_resource/web_resource_service_unittest.cc b/chrome/browser/web_resource/web_resource_service_unittest.cc
index 2211bb4..cb51d9f 100644
--- a/chrome/browser/web_resource/web_resource_service_unittest.cc
+++ b/chrome/browser/web_resource/web_resource_service_unittest.cc
@@ -14,6 +14,17 @@
 
 typedef testing::Test WebResourceServiceTest;
 
+namespace {
+
+// From web_resource_service.cc
+enum BuildType {
+  DEV_BUILD = 1,
+  BETA_BUILD = 1 << 1,
+  STABLE_BUILD = 1 << 2,
+};
+
+}  // namespace
+
 // Verifies that custom dates read from a web resource server are written to
 // the preferences file.
 TEST_F(WebResourceServiceTest, UnpackLogoSignal) {
@@ -42,12 +53,15 @@
 
   // Check that prefs are set correctly.
   web_resource_service->UnpackLogoSignal(*(test_json.get()));
+  PrefService* prefs = profile.GetPrefs();
+  ASSERT_TRUE(prefs != NULL);
+
   double logo_start =
-      profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoStart);
-  ASSERT_EQ(logo_start, 1264899600);  // unix epoch for Jan 31 2010 0100 GMT.
+      prefs->GetDouble(prefs::kNTPCustomLogoStart);
+  EXPECT_EQ(logo_start, 1264899600);  // unix epoch for Jan 31 2010 0100 GMT.
   double logo_end =
-      profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoEnd);
-  ASSERT_EQ(logo_end, 1327971600);  // unix epoch for Jan 31 2012 0100 GMT.
+      prefs->GetDouble(prefs::kNTPCustomLogoEnd);
+  EXPECT_EQ(logo_end, 1327971600);  // unix epoch for Jan 31 2012 0100 GMT.
 
   // Change the start only and recheck.
   json = "{ "
@@ -70,8 +84,9 @@
 
   // Check that prefs are set correctly.
   web_resource_service->UnpackLogoSignal(*(test_json.get()));
-  logo_start = profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoStart);
-  ASSERT_EQ(logo_start, 1267365600);  // date changes to Feb 28 2010 1400 GMT.
+
+  logo_start = prefs->GetDouble(prefs::kNTPCustomLogoStart);
+  EXPECT_EQ(logo_start, 1267365600);  // date changes to Feb 28 2010 1400 GMT.
 
   // If no date is included in the prefs, reset custom logo dates to 0.
   json = "{ "
@@ -88,10 +103,10 @@
 
   // Check that prefs are set correctly.
   web_resource_service->UnpackLogoSignal(*(test_json.get()));
-  logo_start = profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoStart);
-  ASSERT_EQ(logo_start, 0);  // date value reset to 0;
-  logo_end = profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoEnd);
-  ASSERT_EQ(logo_end, 0);  // date value reset to 0;
+  logo_start = prefs->GetDouble(prefs::kNTPCustomLogoStart);
+  EXPECT_EQ(logo_start, 0);  // date value reset to 0;
+  logo_end = prefs->GetDouble(prefs::kNTPCustomLogoEnd);
+  EXPECT_EQ(logo_end, 0);  // date value reset to 0;
 }
 
 TEST_F(WebResourceServiceTest, UnpackPromoSignal) {
@@ -107,6 +122,7 @@
                      "    \"answers\": ["
                      "       {"
                      "        \"name\": \"promo_start\","
+                     "        \"question\": \"3:2\","
                      "        \"tooltip\": \"Eat more pie!\","
                      "        \"inproduct\": \"31/01/10 01:00 GMT\""
                      "       },"
@@ -125,13 +141,33 @@
 
   // Check that prefs are set correctly.
   web_resource_service->UnpackPromoSignal(*(test_json.get()));
+  PrefService* prefs = profile.GetPrefs();
+  ASSERT_TRUE(prefs != NULL);
+
+  std::string promo_line = prefs->GetString(prefs::kNTPPromoLine);
+  EXPECT_EQ(promo_line, "Eat more pie!");
+
+  int promo_group = prefs->GetInteger(prefs::kNTPPromoGroup);
+  EXPECT_GE(promo_group, 0);
+  EXPECT_LT(promo_group, 16);
+
+  int promo_build_type = prefs->GetInteger(prefs::kNTPPromoBuild);
+  EXPECT_EQ(promo_build_type & DEV_BUILD, DEV_BUILD);
+  EXPECT_EQ(promo_build_type & BETA_BUILD, BETA_BUILD);
+  EXPECT_EQ(promo_build_type & STABLE_BUILD, 0);
+
+  int promo_time_slice = prefs->GetInteger(prefs::kNTPPromoGroupTimeSlice);
+  EXPECT_EQ(promo_time_slice, 2);
+
   double promo_start =
-      profile.GetPrefs()->GetReal(prefs::kNTPPromoStart);
-  ASSERT_EQ(promo_start, 1264899600);  // unix epoch for Jan 31 2010 0100 GMT.
+      prefs->GetDouble(prefs::kNTPPromoStart);
+  int64 actual_start = 1264899600 +  // unix epoch for Jan 31 2010 0100 GMT.
+      promo_group * 2 * 60 * 60;
+  EXPECT_EQ(promo_start, actual_start);
+
   double promo_end =
-      profile.GetPrefs()->GetReal(prefs::kNTPPromoEnd);
-  ASSERT_EQ(promo_end, 1327971600);  // unix epoch for Jan 31 2012 0100 GMT.
-  std::string promo_line = profile.GetPrefs()->GetString(prefs::kNTPPromoLine);
-  ASSERT_EQ(promo_line, "Eat more pie!");
+      prefs->GetDouble(prefs::kNTPPromoEnd);
+  EXPECT_EQ(promo_end, 1327971600);  // unix epoch for Jan 31 2012 0100 GMT.
 }
 
+
diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc
index b359ef5..b52f225 100644
--- a/chrome/browser/webdata/web_data_service.cc
+++ b/chrome/browser/webdata/web_data_service.cc
@@ -73,7 +73,7 @@
 }
 
 void WebDataService::CancelRequest(Handle h) {
-  AutoLock l(pending_lock_);
+  base::AutoLock l(pending_lock_);
   RequestMap::iterator i = pending_requests_.find(h);
   if (i == pending_requests_.end()) {
     NOTREACHED() << "Canceling a nonexistent web data service request";
@@ -547,7 +547,7 @@
 }
 
 void WebDataService::RegisterRequest(WebDataRequest* request) {
-  AutoLock l(pending_lock_);
+  base::AutoLock l(pending_lock_);
   pending_requests_[request->GetHandle()] = request;
 }
 
@@ -637,7 +637,7 @@
 }
 
 int WebDataService::GetNextRequestHandle() {
-  AutoLock l(pending_lock_);
+  base::AutoLock l(pending_lock_);
   return ++next_request_handle_;
 }
 
diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h
index b1fbfb3..21dbab8 100644
--- a/chrome/browser/webdata/web_data_service.h
+++ b/chrome/browser/webdata/web_data_service.h
@@ -11,8 +11,8 @@
 
 #include "app/sql/init_status.h"
 #include "base/file_path.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "chrome/browser/browser_thread.h"
 #include "chrome/browser/search_engines/template_url_id.h"
 #ifdef ANDROID
@@ -632,7 +632,7 @@
   bool should_commit_;
 
   // A lock to protect pending requests and next request handle.
-  Lock pending_lock_;
+  base::Lock pending_lock_;
 
   // Next handle to be used for requests. Incremented for each use.
   Handle next_request_handle_;
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index 2400c04..6f510c6 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,6 @@
 #include <set>
 #include <string>
 
-#include "app/l10n_util.h"
 #include "app/sql/statement.h"
 #include "app/sql/transaction.h"
 #include "base/string_number_conversions.h"
@@ -27,8 +26,9 @@
 #include "chrome/browser/webdata/autofill_change.h"
 #include "chrome/common/guid.h"
 #include "chrome/common/notification_service.h"
-#include "gfx/codec/png_codec.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "webkit/glue/form_field.h"
 #include "webkit/glue/password_form.h"
 
@@ -179,8 +179,8 @@
 const size_t kMaxDataLength = 1024;
 
 void BindURLToStatement(const TemplateURL& url, sql::Statement* s) {
-  s->BindString(0, WideToUTF8(url.short_name()));
-  s->BindString(1, WideToUTF8(url.keyword()));
+  s->BindString(0, UTF16ToUTF8(url.short_name()));
+  s->BindString(1, UTF16ToUTF8(url.keyword()));
   GURL favicon_url = url.GetFavIconURL();
   if (!favicon_url.is_valid()) {
     s->BindString(2, std::string());
@@ -866,9 +866,9 @@
     std::string tmp;
     tmp = s.ColumnString(1);
     DCHECK(!tmp.empty());
-    template_url->set_short_name(UTF8ToWide(tmp));
+    template_url->set_short_name(UTF8ToUTF16(tmp));
 
-    template_url->set_keyword(UTF8ToWide(s.ColumnString(2)));
+    template_url->set_keyword(UTF8ToUTF16(s.ColumnString(2)));
 
     tmp = s.ColumnString(3);
     if (!tmp.empty())
@@ -1202,6 +1202,7 @@
   s.BindString16(0, element.name());
   s.BindString16(1, element.value());
 
+  *pair_id = 0;
   *count = 0;
 
   if (s.Step()) {
@@ -2203,8 +2204,8 @@
             "INSERT INTO credit_cards_temp "
             "SELECT label,unique_id,name_on_card,type,card_number,"
             "expiration_month,expiration_year,verification_code,0,"
-            "shipping_address,card_number_encrypted,verification_code_encrypted "
-            "FROM credit_cards")) {
+            "shipping_address,card_number_encrypted,"
+            "verification_code_encrypted FROM credit_cards")) {
           LOG(WARNING) << "Unable to update web database to version 27.";
           NOTREACHED();
           return sql::INIT_FAILURE;
@@ -2509,8 +2510,8 @@
         if (!db_.Execute(
             "INSERT INTO autofill_profiles_temp "
             "SELECT guid, label, first_name, middle_name, last_name, email, "
-            "company_name, address_line_1, address_line_2, city, state, zipcode, "
-            "country, phone, fax, date_modified "
+            "company_name, address_line_1, address_line_2, city, state, "
+            "zipcode, country, phone, fax, date_modified "
             "FROM autofill_profiles")) {
           LOG(WARNING) << "Unable to update web database to version 32.";
           NOTREACHED();
diff --git a/chrome/browser/webdata/web_database.h b/chrome/browser/webdata/web_database.h
index 17bc19c..0356381 100644
--- a/chrome/browser/webdata/web_database.h
+++ b/chrome/browser/webdata/web_database.h
@@ -183,7 +183,8 @@
   bool AddToCountOfFormElement(int64 pair_id, int delta, bool* was_removed);
 
   // Gets the pair_id and count entries from name and value specified in
-  // |element|.  Sets *count to 0 if there is no such row in the table.
+  // |element|.  Sets *pair_id and *count to 0 if there is no such row in
+  // the table.
   bool GetIDAndCountOfFormElement(const webkit_glue::FormField& element,
                                   int64* pair_id,
                                   int* count);
diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc
index dc38100..41489e9 100644
--- a/chrome/browser/webdata/web_database_unittest.cc
+++ b/chrome/browser/webdata/web_database_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -305,8 +305,8 @@
   ASSERT_EQ(sql::INIT_OK, db.Init(file_));
 
   TemplateURL template_url;
-  template_url.set_short_name(L"short_name");
-  template_url.set_keyword(L"keyword");
+  template_url.set_short_name(ASCIIToUTF16("short_name"));
+  template_url.set_keyword(ASCIIToUTF16("keyword"));
   GURL favicon_url("http://favicon.url/");
   GURL originating_url("http://google.com/");
   template_url.SetFavIconURL(favicon_url);
@@ -398,8 +398,8 @@
   ASSERT_EQ(sql::INIT_OK, db.Init(file_));
 
   TemplateURL template_url;
-  template_url.set_short_name(L"short_name");
-  template_url.set_keyword(L"keyword");
+  template_url.set_short_name(ASCIIToUTF16("short_name"));
+  template_url.set_keyword(ASCIIToUTF16("keyword"));
   GURL favicon_url("http://favicon.url/");
   GURL originating_url("http://originating.url/");
   template_url.SetFavIconURL(favicon_url);
@@ -414,7 +414,7 @@
   GURL originating_url2("http://originating.url/");
   template_url.set_originating_url(originating_url2);
   template_url.set_autogenerate_keyword(true);
-  EXPECT_EQ(L"url", template_url.keyword());
+  EXPECT_EQ(ASCIIToUTF16("url"), template_url.keyword());
   template_url.add_input_encoding("Shift_JIS");
   set_prepopulate_id(&template_url, 5);
   set_logo_id(&template_url, 2000);
@@ -468,8 +468,8 @@
   ASSERT_EQ(sql::INIT_OK, db.Init(file_));
 
   TemplateURL template_url;
-  template_url.set_short_name(L"short_name");
-  template_url.set_keyword(L"keyword");
+  template_url.set_short_name(ASCIIToUTF16("short_name"));
+  template_url.set_keyword(ASCIIToUTF16("keyword"));
   template_url.SetURL("http://url/", 0, 0);
   template_url.set_safe_for_autoreplace(true);
   SetID(-100, &template_url);
diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc
index 2006e2f..f164e63 100644
--- a/chrome/browser/worker_host/worker_process_host.cc
+++ b/chrome/browser/worker_host/worker_process_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -44,23 +44,23 @@
 namespace {
 
 // Helper class that we pass to SocketStreamDispatcherHost so that it can find
-// the right URLRequestContext for a request.
+// the right net::URLRequestContext for a request.
 class URLRequestContextOverride
     : public ResourceMessageFilter::URLRequestContextOverride {
  public:
   explicit URLRequestContextOverride(
-      URLRequestContext* url_request_context)
+      net::URLRequestContext* url_request_context)
       : url_request_context_(url_request_context) {
   }
   virtual ~URLRequestContextOverride() {}
 
-  virtual URLRequestContext* GetRequestContext(
-      uint32 request_id, ResourceType::Type resource_type) {
+  virtual net::URLRequestContext* GetRequestContext(
+      const ViewHostMsg_Resource_Request& resource_request) {
     return url_request_context_;
   }
 
  private:
-  URLRequestContext* url_request_context_;
+  net::URLRequestContext* url_request_context_;
 };
 
 }  // namespace
@@ -75,12 +75,8 @@
   void Run() {
     RenderViewHost* host =
         RenderViewHost::FromID(render_process_unique_id_, render_view_id_);
-    if (host) {
-      RenderViewHostDelegate::BrowserIntegration* integration_delegate =
-          host->delegate()->GetBrowserIntegrationDelegate();
-      if (integration_delegate)
-        integration_delegate->OnCrashedWorker();
-    }
+    if (host)
+      host->delegate()->WorkerCrashed();
   }
 
  private:
diff --git a/chrome/browser/worker_host/worker_process_host.h b/chrome/browser/worker_host/worker_process_host.h
index f3f6fdd..36979c3 100644
--- a/chrome/browser/worker_host/worker_process_host.h
+++ b/chrome/browser/worker_host/worker_process_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -20,8 +20,8 @@
 // The WorkerProcessHost is the interface that represents the browser side of
 // the browser <-> worker communication channel. There will be one
 // WorkerProcessHost per worker process.  Currently each worker runs in its own
-// process, but that may change.  However, we do assume [by storing a
-// URLRequestContext] that a WorkerProcessHost serves a single Profile.
+// process, but that may change.  However, we do assume (by storing a
+// net::URLRequestContext) that a WorkerProcessHost serves a single Profile.
 class WorkerProcessHost : public BrowserChildProcessHost {
  public:
 
diff --git a/chrome/browser/zygote_host_linux.cc b/chrome/browser/zygote_host_linux.cc
index 6e2c7e3..ad6b072 100644
--- a/chrome/browser/zygote_host_linux.cc
+++ b/chrome/browser/zygote_host_linux.cc
@@ -235,7 +235,7 @@
 
   pid_t pid;
   {
-    AutoLock lock(control_lock_);
+    base::AutoLock lock(control_lock_);
     if (!UnixDomainSocket::SendMsg(control_fd_, pickle.data(), pickle.size(),
                                    fds))
       return base::kNullProcessHandle;
@@ -331,7 +331,7 @@
   char buf[kMaxMessageLength];
   ssize_t len;
   {
-    AutoLock lock(control_lock_);
+    base::AutoLock lock(control_lock_);
     if (HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size())) < 0)
       PLOG(ERROR) << "write";
 
diff --git a/chrome/browser/zygote_host_linux.h b/chrome/browser/zygote_host_linux.h
index e13f1b4..bbc00dc 100644
--- a/chrome/browser/zygote_host_linux.h
+++ b/chrome/browser/zygote_host_linux.h
@@ -12,9 +12,9 @@
 #include <vector>
 
 #include "base/global_descriptors_posix.h"
-#include "base/lock.h"
 #include "base/process.h"
 #include "base/process_util.h"
+#include "base/synchronization/lock.h"
 
 template<typename Type>
 struct DefaultSingletonTraits;
@@ -86,7 +86,7 @@
   // A lock protecting all communication with the zygote. This lock must be
   // acquired before sending a command and released after the result has been
   // received.
-  Lock control_lock_;
+  base::Lock control_lock_;
   pid_t pid_;
   bool init_;
   bool using_suid_sandbox_;
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc
index 7199e14..b03e59c 100644
--- a/chrome/browser/zygote_main_linux.cc
+++ b/chrome/browser/zygote_main_linux.cc
@@ -232,10 +232,10 @@
     Pickle write_pickle;
     write_pickle.WriteInt(static_cast<int>(status));
     write_pickle.WriteInt(exit_code);
-    if (HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())) !=
-        write_pickle.size()) {
+    ssize_t written =
+        HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
+    if (written != static_cast<ssize_t>(write_pickle.size()))
       PLOG(ERROR) << "write";
-    }
   }
 
   // This is equivalent to fork(), except that, when using the SUID
@@ -322,8 +322,10 @@
     }
 
    error:
-    if (pid > 0)
-      waitpid(pid, NULL, WNOHANG);
+    if (pid > 0) {
+      if (waitpid(pid, NULL, WNOHANG) == -1)
+        LOG(ERROR) << "Failed to wait for process";
+    }
     if (dummy_fd >= 0)
       close(dummy_fd);
     if (pipe_fds[0] >= 0)
@@ -587,14 +589,6 @@
 
   base::SysInfo::MaxSharedMemorySize();
 
-  // To make wcstombs/mbstowcs work in a renderer, setlocale() has to be
-  // called before the sandbox is triggered. It's possible to avoid calling
-  // setlocale() by pulling out the conversion between FilePath and
-  // WebCore String out of the renderer and using string16 in place of
-  // FilePath for IPC.
-  const char* locale = setlocale(LC_ALL, "");
-  LOG_IF(WARNING, locale == NULL) << "setlocale failed.";
-
   // ICU DateFormat class (used in base/time_format.cc) needs to get the
   // Olson timezone ID by accessing the zoneinfo files on disk. After
   // TimeZone::createDefault is called once here, the timezone ID is
diff --git a/chrome/common/about_handler.cc b/chrome/common/about_handler.cc
index d2121b8..6e3e152 100644
--- a/chrome/common/about_handler.cc
+++ b/chrome/common/about_handler.cc
@@ -12,6 +12,7 @@
 // chrome/renderer/about_handler.cc.
 const char* const about_urls[] = {
   chrome::kAboutCrashURL,
+  chrome::kAboutKillURL,
   chrome::kAboutHangURL,
   chrome::kAboutShorthangURL,
   NULL,
diff --git a/chrome/common/appcache/appcache_dispatcher.h b/chrome/common/appcache/appcache_dispatcher.h
index f88a38a..bec0d82 100644
--- a/chrome/common/appcache/appcache_dispatcher.h
+++ b/chrome/common/appcache/appcache_dispatcher.h
@@ -24,7 +24,7 @@
   AppCacheBackendProxy* backend_proxy() { return &backend_proxy_; }
 
   // IPC::Channel::Listener implementation
-  bool OnMessageReceived(const IPC::Message& msg);
+  virtual bool OnMessageReceived(const IPC::Message& msg);
 
  private:
   // Ipc message handlers
diff --git a/chrome/common/autofill_messages.cc b/chrome/common/autofill_messages.cc
new file mode 100644
index 0000000..80b43f3
--- /dev/null
+++ b/chrome/common/autofill_messages.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/common/common_param_traits.h"
+#include "webkit/glue/form_data.h"
+#include "webkit/glue/form_field.h"
+#include "webkit/glue/password_form.h"
+#include "webkit/glue/password_form_dom_manager.h"
+
+#define IPC_MESSAGE_IMPL
+#include "chrome/common/autofill_messages.h"
+
+namespace IPC {
+
+void ParamTraits<webkit_glue::FormField>::Write(Message* m,
+                                                const param_type& p) {
+  WriteParam(m, p.label());
+  WriteParam(m, p.name());
+  WriteParam(m, p.value());
+  WriteParam(m, p.form_control_type());
+  WriteParam(m, p.max_length());
+  WriteParam(m, p.is_autofilled());
+  WriteParam(m, p.option_strings());
+}
+
+bool ParamTraits<webkit_glue::FormField>::Read(const Message* m, void** iter,
+                                               param_type* p) {
+  string16 label, name, value, form_control_type;
+  int max_length = 0;
+  bool is_autofilled;
+  std::vector<string16> options;
+  bool result = ReadParam(m, iter, &label);
+  result = result && ReadParam(m, iter, &name);
+  result = result && ReadParam(m, iter, &value);
+  result = result && ReadParam(m, iter, &form_control_type);
+  result = result && ReadParam(m, iter, &max_length);
+  result = result && ReadParam(m, iter, &is_autofilled);
+  result = result && ReadParam(m, iter, &options);
+  if (!result)
+    return false;
+
+  p->set_label(label);
+  p->set_name(name);
+  p->set_value(value);
+  p->set_form_control_type(form_control_type);
+  p->set_max_length(max_length);
+  p->set_autofilled(is_autofilled);
+  p->set_option_strings(options);
+  return true;
+}
+
+void ParamTraits<webkit_glue::FormField>::Log(const param_type& p,
+                                              std::string* l) {
+  l->append("<FormField>");
+}
+
+void ParamTraits<webkit_glue::FormData>::Write(Message* m,
+                                               const param_type& p) {
+  WriteParam(m, p.name);
+  WriteParam(m, p.method);
+  WriteParam(m, p.origin);
+  WriteParam(m, p.action);
+  WriteParam(m, p.user_submitted);
+  WriteParam(m, p.fields);
+}
+
+bool ParamTraits<webkit_glue::FormData>::Read(const Message* m, void** iter,
+                                              param_type* p) {
+  return
+      ReadParam(m, iter, &p->name) &&
+      ReadParam(m, iter, &p->method) &&
+      ReadParam(m, iter, &p->origin) &&
+      ReadParam(m, iter, &p->action) &&
+      ReadParam(m, iter, &p->user_submitted) &&
+      ReadParam(m, iter, &p->fields);
+}
+
+void ParamTraits<webkit_glue::FormData>::Log(const param_type& p,
+                                             std::string* l) {
+  l->append("<FormData>");
+}
+
+void ParamTraits<webkit_glue::PasswordFormFillData>::Write(
+    Message* m, const param_type& p) {
+  WriteParam(m, p.basic_data);
+  WriteParam(m, p.additional_logins);
+  WriteParam(m, p.wait_for_username);
+}
+
+bool ParamTraits<webkit_glue::PasswordFormFillData>::Read(
+    const Message* m, void** iter, param_type* r) {
+  return
+      ReadParam(m, iter, &r->basic_data) &&
+      ReadParam(m, iter, &r->additional_logins) &&
+      ReadParam(m, iter, &r->wait_for_username);
+}
+
+void ParamTraits<webkit_glue::PasswordFormFillData>::Log(const param_type& p,
+                                                         std::string* l) {
+  l->append("<PasswordFormFillData>");
+}
+
+}  // namespace IPC
diff --git a/chrome/common/autofill_messages.h b/chrome/common/autofill_messages.h
new file mode 100644
index 0000000..4e2f9bc
--- /dev/null
+++ b/chrome/common/autofill_messages.h
@@ -0,0 +1,125 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_COMMON_AUTOFILL_MESSAGES_H_
+#define CHROME_COMMON_AUTOFILL_MESSAGES_H_
+#pragma once
+
+#include <string>
+
+#include "ipc/ipc_message_macros.h"
+
+#define IPC_MESSAGE_START AutoFillMsgStart
+
+namespace webkit_glue {
+class FormField;
+struct FormData;
+struct PasswordForm;
+struct PasswordFormFillData;
+}
+
+namespace IPC {
+
+template <>
+struct ParamTraits<webkit_glue::FormField> {
+  typedef webkit_glue::FormField param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
+
+// Traits for FormData structure to pack/unpack.
+template <>
+struct ParamTraits<webkit_glue::FormData> {
+  typedef webkit_glue::FormData param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<webkit_glue::PasswordFormFillData> {
+  typedef webkit_glue::PasswordFormFillData param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+}  // namespace IPC
+
+// AutoFill messages sent from the browser to the renderer.
+
+// Reply to the AutoFillHostMsg_QueryFormFieldAutoFill message with the
+// AutoFill suggestions.
+IPC_MESSAGE_ROUTED5(AutoFillMsg_SuggestionsReturned,
+                    int /* id of the request message */,
+                    std::vector<string16> /* names */,
+                    std::vector<string16> /* labels */,
+                    std::vector<string16> /* icons */,
+                    std::vector<int> /* unique_ids */)
+
+// Reply to the AutoFillHostMsg_FillAutoFillFormData message with the
+// AutoFill form data.
+IPC_MESSAGE_ROUTED2(AutoFillMsg_FormDataFilled,
+                    int /* id of the request message */,
+                    webkit_glue::FormData /* form data */)
+
+// Fill a password form and prepare field autocomplete for multiple
+// matching logins.
+IPC_MESSAGE_ROUTED1(AutoFillMsg_FillPasswordForm,
+                    webkit_glue::PasswordFormFillData)
+
+
+// AutoFill messages sent from the renderer to the browser.
+
+// Notification that forms have been seen that are candidates for
+// filling/submitting by the AutoFillManager.
+IPC_MESSAGE_ROUTED1(AutoFillHostMsg_FormsSeen,
+                    std::vector<webkit_glue::FormData> /* forms */)
+
+// Notification that password forms have been seen that are candidates for
+// filling/submitting by the password manager.
+IPC_MESSAGE_ROUTED1(AutoFillHostMsg_PasswordFormsFound,
+                    std::vector<webkit_glue::PasswordForm> /* forms */)
+
+// Notification that initial layout has occurred and the following password
+// forms are visible on the page (e.g. not set to display:none.)
+IPC_MESSAGE_ROUTED1(AutoFillHostMsg_PasswordFormsVisible,
+                    std::vector<webkit_glue::PasswordForm> /* forms */)
+
+// Notification that a form has been submitted.  The user hit the button.
+IPC_MESSAGE_ROUTED1(AutoFillHostMsg_FormSubmitted,
+                    webkit_glue::FormData /* form */)
+
+// Queries the browser for AutoFill suggestions for a form input field.
+IPC_MESSAGE_ROUTED3(AutoFillHostMsg_QueryFormFieldAutoFill,
+                    int /* id of this message */,
+                    webkit_glue::FormData /* the form */,
+                    webkit_glue::FormField /* the form field */)
+
+// Sent when the popup with AutoFill suggestions for a form is shown.
+IPC_MESSAGE_ROUTED0(AutoFillHostMsg_DidShowAutoFillSuggestions)
+
+// Instructs the browser to fill in the values for a form using AutoFill
+// profile data.
+IPC_MESSAGE_ROUTED4(AutoFillHostMsg_FillAutoFillFormData,
+                    int /* id of this message */,
+                    webkit_glue::FormData /* the form  */,
+                    webkit_glue::FormField /* the form field  */,
+                    int /* profile unique ID */)
+
+// Sent when a form is previewed or filled with AutoFill suggestions.
+IPC_MESSAGE_ROUTED0(AutoFillHostMsg_DidFillAutoFillFormData)
+
+// Instructs the browser to remove the specified Autocomplete entry from the
+// database.
+IPC_MESSAGE_ROUTED2(AutoFillHostMsg_RemoveAutocompleteEntry,
+                    string16 /* field name */,
+                    string16 /* value */)
+
+// Instructs the browser to show the AutoFill dialog.
+IPC_MESSAGE_ROUTED0(AutoFillHostMsg_ShowAutoFillDialog)
+
+#endif  // CHROME_COMMON_AUTOFILL_MESSAGES_H_
diff --git a/chrome/common/automation_constants.h b/chrome/common/automation_constants.h
index 6579776..c4aa683 100644
--- a/chrome/common/automation_constants.h
+++ b/chrome/common/automation_constants.h
@@ -26,6 +26,24 @@
 // Amount of time to wait before querying the browser.
 static const int kSleepTime = 250;
 
+// Recognized by the AutomationProvider's SendWebKeyboardEventToSelectedTab
+// command. Specifies the type of the keyboard event.
+enum KeyEventTypes {
+  kRawKeyDownType = 0,
+  kKeyDownType,
+  kCharType,
+  kKeyUpType,
+};
+
+// Recognized by the AutomationProvider's SendWebKeyboardEventToSelectedTab
+// command. Specifies masks to be used in constructing keyboard event modifiers.
+enum KeyModifierMasks {
+  kShiftKeyMask   = 1 << 0,
+  kControlKeyMask = 1 << 1,
+  kAltKeyMask     = 1 << 2,
+  kMetaKeyMask    = 1 << 3,
+};
+
 }  // namespace automation
 
 // Used by AutomationProxy, declared here so that other headers don't need
diff --git a/chrome/common/automation_messages.h b/chrome/common/automation_messages.h
index 7a9ba91..8bc8153 100644
--- a/chrome/common/automation_messages.h
+++ b/chrome/common/automation_messages.h
@@ -14,8 +14,8 @@
 #include "chrome/common/page_type.h"
 #include "chrome/common/security_style.h"
 #include "chrome/common/common_param_traits.h"
-#include "gfx/rect.h"
 #include "net/base/upload_data.h"
+#include "ui/gfx/rect.h"
 
 struct AutomationMsg_Find_Params {
   // Unused value, which exists only for backwards compat.
diff --git a/chrome/common/automation_messages_internal.h b/chrome/common/automation_messages_internal.h
index a0a71ae..d6008e0 100644
--- a/chrome/common/automation_messages_internal.h
+++ b/chrome/common/automation_messages_internal.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,10 +11,10 @@
 #include "chrome/common/content_settings.h"
 #include "chrome/common/navigation_types.h"
 #include "chrome/test/automation/autocomplete_edit_proxy.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_macros.h"
 #include "net/url_request/url_request_status.h"
+#include "ui/gfx/rect.h"
 
 
 
@@ -24,7 +24,7 @@
 //       any other purpose in these message types.
 
 // NOTE: All the new IPC messages should go at the end.
-//       The IPC message IDs need to match the reference builds.  Since we know
+//       The IPC message IDs need to match the reference builds.  Since we now
 //       define the IDs based on __LINE__, to allow these IPC messages to be
 //       used to control an old version of Chrome we need the message IDs to
 //       remain the same.  This means that you should not change the line number
@@ -364,7 +364,7 @@
 // This message requests that a key press be performed.
 // Request:
 //   int - the handle of the window that's the context for this click
-//   int - the app::KeyboardCode of the key that was pressed.
+//   int - the ui::KeyboardCode of the key that was pressed.
 //   int - the flags which identify the modifiers (shift, ctrl, alt)
 //         associated for, as defined in chrome/views/event.h
 IPC_MESSAGE_CONTROL3(AutomationMsg_WindowKeyPress,
@@ -533,8 +533,8 @@
 //   - int: handle of the tab
 // Response:
 //  - bool: whether the operation was successful.
-IPC_SYNC_MESSAGE_CONTROL1_0(AutomationMsg_WaitForTabToBeRestored,
-                            int)
+IPC_SYNC_MESSAGE_CONTROL1_1(AutomationMsg_WaitForTabToBeRestored,
+                            int, bool)
 
 // This message is an outgoing message from Chrome to an external host.
 // It is a notification that a navigation happened
@@ -653,7 +653,7 @@
 IPC_SYNC_MESSAGE_CONTROL1_2(AutomationMsg_AutocompleteEditGetText,
                             int /* autocomplete edit handle */,
                             bool /* the requested autocomplete edit exists */,
-                            std::wstring /* omnibox text */)
+                            string16 /* omnibox text */)
 
 // This message sets the text being displayed in the AutocompleteEdit.  The
 // first parameter is the handle to the omnibox and the second parameter is
@@ -662,7 +662,7 @@
 // completed.
 IPC_SYNC_MESSAGE_CONTROL2_1(AutomationMsg_AutocompleteEditSetText,
                             int /* autocomplete edit handle */,
-                            std::wstring /* text to set */,
+                            string16 /* text to set */,
                             bool /* the requested autocomplete edit exists */)
 
 // This message requests if a query to a autocomplete provider is still in
@@ -755,16 +755,16 @@
 // returns -1 if an error occurred.
 IPC_SYNC_MESSAGE_CONTROL1_1(AutomationMsg_GetInfoBarCount,
                             int /* tab_handle */,
-                            int /* info bar count */)
+                            size_t /* info bar count */)
 
 // This message triggers the action associated with the "accept" button in
 // the info-bar at the specified index.  If |wait for navigation| is true, it
 // won't return until a navigation has occurred.
 IPC_SYNC_MESSAGE_CONTROL3_1(AutomationMsg_ClickInfoBarAccept,
                             int /* tab_handle */,
-                            int /* info bar index */,
+                            size_t /* info bar index */,
                             bool /* wait for navigation */,
-
+// This line blank on purpose, see comment atop file about __LINE__.
                             /* navigation result */
                             AutomationMsg_NavigationResponseValues)
 
@@ -779,7 +779,7 @@
 IPC_SYNC_MESSAGE_CONTROL2_1(AutomationMsg_WaitForNavigation,
                             int /* tab_handle */,
                             int64 /* last navigation time */,
-
+// This line blank on purpose, see comment atop file about __LINE__.
                             /* navigation result */
                             AutomationMsg_NavigationResponseValues)
 
@@ -958,7 +958,7 @@
 
 IPC_MESSAGE_ROUTED2(AutomationMsg_RequestEnd,
                     int /* request_id */,
-                    URLRequestStatus /* status */)
+                    net::URLRequestStatus /* status */)
 
 IPC_MESSAGE_CONTROL1(AutomationMsg_PrintAsync,
                      int /* tab_handle */)
@@ -1027,7 +1027,7 @@
 // This message requests the provider to wait until the window count
 // reached the specified value.
 // Request:
-//   - int: target browser window count
+//  - int: target browser window count
 // Response:
 //  - bool: whether the operation was successful.
 IPC_SYNC_MESSAGE_CONTROL1_1(AutomationMsg_WaitForBrowserWindowCountToBecome,
@@ -1414,7 +1414,7 @@
 // Waits for the infobar count to reach given number.
 IPC_SYNC_MESSAGE_CONTROL2_1(AutomationMsg_WaitForInfoBarCount,
                             int /* tab handle */,
-                            int /* target count */,
+                            size_t /* target count */,
                             bool /* success */)
 
 // Waits for the autocomplete edit to receive focus.
@@ -1438,3 +1438,15 @@
                             int,
                             FilePath,
                             bool)
+
+// Notify the JavaScript engine in the render to change its parameters
+// while performing stress testing.
+IPC_MESSAGE_ROUTED3(AutomationMsg_JavaScriptStressTestControl,
+                    int /* tab handle */,
+                    int /* command */,
+                    int /* type or run */)
+
+// This message posts a task to the PROCESS_LAUNCHER thread. Once processed
+// the response is sent back. This is useful when you want to make sure all
+// changes to the number of processes have completed.
+IPC_SYNC_MESSAGE_CONTROL0_0(AutomationMsg_WaitForProcessLauncherThreadToGoIdle)
diff --git a/chrome/common/badge_util.cc b/chrome/common/badge_util.cc
index bd2067c..21746b0 100644
--- a/chrome/common/badge_util.cc
+++ b/chrome/common/badge_util.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/common/badge_util.h"
 
-#include "app/resource_bundle.h"
 #include "base/utf_string_conversions.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/font.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkTypeface.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/font.h"
 
 namespace badge_util {
 
@@ -40,7 +40,7 @@
       ResourceBundle& rb = ResourceBundle::GetSharedInstance();
       const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
       typeface = SkTypeface::CreateFromName(
-          WideToUTF8(base_font.GetFontName()).c_str(), SkTypeface::kNormal);
+          UTF16ToUTF8(base_font.GetFontName()).c_str(), SkTypeface::kNormal);
     }
 
     text_paint->setTypeface(typeface);
diff --git a/chrome/common/bindings_policy.h b/chrome/common/bindings_policy.h
index 0df8371..7d0db25 100644
--- a/chrome/common/bindings_policy.h
+++ b/chrome/common/bindings_policy.h
@@ -13,7 +13,7 @@
   enum {
     // HTML-based UI bindings that allows he js content to send JSON-encoded
     // data back to the browser process.
-    DOM_UI = 1 << 0,
+    WEB_UI = 1 << 0,
     // DOM automation bindings that allows the js content to send JSON-encoded
     // data back to automation in the parent process.  (By default this isn't
     // allowed unless the app has been started up with the --dom-automation
@@ -26,8 +26,8 @@
     EXTENSION = 1 << 3,
   };
 
-  static bool is_dom_ui_enabled(int flags) {
-    return (flags & DOM_UI) != 0;
+  static bool is_web_ui_enabled(int flags) {
+    return (flags & WEB_UI) != 0;
   }
   static bool is_dom_automation_enabled(int flags) {
     return (flags & DOM_AUTOMATION) != 0;
diff --git a/chrome/common/child_process_host.cc b/chrome/common/child_process_host.cc
index e03b3a6..1b6459a 100644
--- a/chrome/common/child_process_host.cc
+++ b/chrome/common/child_process_host.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/metrics/histogram.h"
 #include "base/path_service.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "chrome/common/child_process_info.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths_internal.h"
@@ -56,7 +57,10 @@
 #if defined(OS_LINUX)
   // Use /proc/self/exe rather than our known binary path so updates
   // can't swap out the binary from underneath us.
-  if (allow_self)
+  // When running under Valgrind, forking /proc/self/exe ends up forking the
+  // Valgrind executable, which then crashes. However, it's almost safe to
+  // assume that the updates won't happen while testing with Valgrind tools.
+  if (allow_self && !RunningOnValgrind())
     return FilePath("/proc/self/exe");
 #endif
 
@@ -139,6 +143,16 @@
   Notify(NotificationType::CHILD_INSTANCE_CREATED);
 }
 
+bool ChildProcessHost::OnMessageReceived(const IPC::Message& msg) {
+  return false;
+}
+
+void ChildProcessHost::OnChannelConnected(int32 peer_pid) {
+}
+
+void ChildProcessHost::OnChannelError() {
+}
+
 bool ChildProcessHost::Send(IPC::Message* message) {
   if (!channel_.get()) {
     delete message;
@@ -151,6 +165,12 @@
   delete this;
 }
 
+void ChildProcessHost::ShutdownStarted() {
+}
+
+void ChildProcessHost::Notify(NotificationType type) {
+}
+
 ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
     : host_(host) {
 }
diff --git a/chrome/common/child_process_host.h b/chrome/common/child_process_host.h
index c822346..08f585e 100644
--- a/chrome/common/child_process_host.h
+++ b/chrome/common/child_process_host.h
@@ -58,7 +58,7 @@
 #endif  // defined(OS_WIN)
 
   // IPC::Message::Sender implementation.
-  bool Send(IPC::Message* message);
+  virtual bool Send(IPC::Message* message);
 
  protected:
   ChildProcessHost();
@@ -80,9 +80,9 @@
   virtual void InstanceCreated();
 
   // IPC::Channel::Listener implementation:
-  virtual bool OnMessageReceived(const IPC::Message& msg) { return false; }
-  virtual void OnChannelConnected(int32 peer_pid) { }
-  virtual void OnChannelError() { }
+  virtual bool OnMessageReceived(const IPC::Message& msg);
+  virtual void OnChannelConnected(int32 peer_pid);
+  virtual void OnChannelError();
 
   bool opening_channel() { return opening_channel_; }
   const std::string& channel_id() { return channel_id_; }
@@ -91,9 +91,9 @@
   // Called when the child process goes away.
   virtual void OnChildDied();
   // Notifies the derived class that we told the child process to kill itself.
-  virtual void ShutdownStarted() { }
+  virtual void ShutdownStarted();
   // Subclasses can implement specific notification methods.
-  virtual void Notify(NotificationType type) { }
+  virtual void Notify(NotificationType type);
 
  private:
   // By using an internal class as the IPC::Channel::Listener, we can intercept
diff --git a/chrome/common/child_process_info.cc b/chrome/common/child_process_info.cc
index 69122cc..9084646 100644
--- a/chrome/common/child_process_info.cc
+++ b/chrome/common/child_process_info.cc
@@ -6,7 +6,6 @@
 
 #include <limits>
 
-#include "app/l10n_util.h"
 #include "base/atomicops.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
@@ -15,6 +14,7 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 ChildProcessInfo::ChildProcessInfo(ProcessType type, int id) :
     type_(type),
diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h
index 4d5b721..8d4e60e 100644
--- a/chrome/common/child_process_info.h
+++ b/chrome/common/child_process_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -37,7 +37,7 @@
   enum RendererProcessType {
     RENDERER_UNKNOWN = 0,
     RENDERER_NORMAL,
-    RENDERER_CHROME,        // DOMUI (chrome:// URL)
+    RENDERER_CHROME,        // WebUI (chrome:// URL)
     RENDERER_EXTENSION,     // chrome-extension://
     RENDERER_DEVTOOLS,      // Web inspector
     RENDERER_INTERSTITIAL,  // malware/phishing interstitial
@@ -68,6 +68,9 @@
   // Getter to the process handle.
   base::ProcessHandle handle() const { return process_.handle(); }
 
+  // Getter to the process ID.
+  int pid() const { return process_.pid(); }
+
   // The unique identifier for this child process. This identifier is NOT a
   // process ID, and will be unique for all types of child process for
   // one run of the browser.
diff --git a/chrome/common/child_process_logging_mac.mm b/chrome/common/child_process_logging_mac.mm
index ca12d1c..e14aa36 100644
--- a/chrome/common/child_process_logging_mac.mm
+++ b/chrome/common/child_process_logging_mac.mm
@@ -151,7 +151,7 @@
                  base::UintToString(gpu_info.device_id()),
                  set_key_func);
   SetGpuKeyValue(kGPUDriverVersionParamName,
-                 WideToUTF8(gpu_info.driver_version()),
+                 gpu_info.driver_version(),
                  set_key_func);
   SetGpuKeyValue(kGPUPixelShaderVersionParamName,
                  base::UintToString(gpu_info.pixel_shader_version()),
diff --git a/chrome/common/child_process_logging_win.cc b/chrome/common/child_process_logging_win.cc
index 1be4921..0753f44 100644
--- a/chrome/common/child_process_logging_win.cc
+++ b/chrome/common/child_process_logging_win.cc
@@ -139,7 +139,7 @@
   (set_gpu_info)(
       base::UintToString16(gpu_info.vendor_id()).c_str(),
       base::UintToString16(gpu_info.device_id()).c_str(),
-      gpu_info.driver_version().c_str(),
+      UTF8ToUTF16(gpu_info.driver_version()).c_str(),
       base::UintToString16(gpu_info.pixel_shader_version()).c_str(),
       base::UintToString16(gpu_info.vertex_shader_version()).c_str());
 }
diff --git a/chrome/common/child_thread.cc b/chrome/common/child_thread.cc
index 53823bc..dd74aee 100644
--- a/chrome/common/child_thread.cc
+++ b/chrome/common/child_thread.cc
@@ -168,6 +168,10 @@
   return router_.OnMessageReceived(msg);
 }
 
+bool ChildThread::OnControlMessageReceived(const IPC::Message& msg) {
+  return false;
+}
+
 void ChildThread::OnAskBeforeShutdown() {
   check_with_browser_before_shutdown_ = true;
 }
diff --git a/chrome/common/child_thread.h b/chrome/common/child_thread.h
index dbe8677..4537f1b 100644
--- a/chrome/common/child_thread.h
+++ b/chrome/common/child_thread.h
@@ -74,9 +74,7 @@
   // Called when the process refcount is 0.
   void OnProcessFinalRelease();
 
-  virtual bool OnControlMessageReceived(const IPC::Message& msg) {
-    return false;
-  }
+  virtual bool OnControlMessageReceived(const IPC::Message& msg);
   virtual void OnAskBeforeShutdown();
   virtual void OnShutdown();
 
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 97bb58e..0cb0fca 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -115,7 +115,7 @@
 // This number used to be limited to 32 in the past (see b/535234).
 const unsigned int kMaxRendererProcessCount = 42;
 const int kStatsMaxThreads = 32;
-const int kStatsMaxCounters = 300;
+const int kStatsMaxCounters = 3000;
 
 const size_t kMaxTitleChars = 4 * 1024;
 const size_t kMaxURLChars = 2 * 1024 * 1024;
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
index 344db91..584bd9e 100644
--- a/chrome/common/chrome_paths.cc
+++ b/chrome/common/chrome_paths.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -182,7 +182,6 @@
       if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
         return false;
       cur = cur.Append(FILE_PATH_LITERAL("Temp"));
-      create_dir = true;
       break;
     case chrome::DIR_INTERNAL_PLUGINS:
       if (!GetInternalPluginsDirectory(&cur))
@@ -295,7 +294,7 @@
       if (!file_util::PathExists(cur))  // we don't want to create this
         return false;
       break;
-#if !defined(OS_MACOSX) && defined(OS_POSIX)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
     case chrome::DIR_POLICY_FILES: {
 #if defined(GOOGLE_CHROME_BUILD)
       cur = FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
@@ -321,6 +320,14 @@
       break;
     }
 #endif
+#if defined(OS_CHROMEOS)
+    case chrome::DIR_USER_EXTERNAL_EXTENSIONS: {
+      if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
+        return false;
+      cur = cur.Append(FILE_PATH_LITERAL("External Extensions"));
+      break;
+    }
+#endif
     default:
       return false;
   }
diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h
index 21867bd..74f7920 100644
--- a/chrome/common/chrome_paths.h
+++ b/chrome/common/chrome_paths.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -24,7 +24,7 @@
   DIR_RESOURCES,                // Directory containing separate file resources
                                 // used by Chrome at runtime.
   DIR_SHARED_RESOURCES,         // Directory containing js and css files used
-                                // by DOMUI and component extensions.
+                                // by WebUI and component extensions.
   DIR_INSPECTOR,                // Directory where web inspector is located.
   DIR_APP_DICTIONARIES,         // Directory where the global dictionaries are.
   DIR_USER_DOCUMENTS,           // Directory for a user's "My Documents".
@@ -35,6 +35,9 @@
                                 // this when a temporary file or directory will
                                 // be moved into the profile, to avoid issues
                                 // moving across volumes.  See crbug.com/13044 .
+                                // Getting this path does not create it.  Users
+                                // should check that the path exists before
+                                // using it.
   DIR_INTERNAL_PLUGINS,         // Directory where internal plugins reside.
 #if !defined(OS_MACOSX) && defined(OS_POSIX)
   DIR_POLICY_FILES,             // Directory for system-wide read-only
@@ -46,6 +49,12 @@
   DIR_MANAGED_PREFS,            // Directory that stores the managed prefs plist
                                 // files for the current user.
 #endif
+#if defined(OS_CHROMEOS)
+  DIR_USER_EXTERNAL_EXTENSIONS,  // Directory for per-user external extensions.
+                                 // Used for OEM customization on Chrome OS.
+                                 // Getting this path does not create it.
+#endif
+
   FILE_RESOURCE_MODULE,         // Full path and filename of the module that
                                 // contains embedded resources (version,
                                 // strings, images, etc.).
diff --git a/chrome/common/chrome_paths_win.cc b/chrome/common/chrome_paths_win.cc
index 062c43b..1892b43 100644
--- a/chrome/common/chrome_paths_win.cc
+++ b/chrome/common/chrome_paths_win.cc
@@ -15,7 +15,6 @@
 #include "base/path_service.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/master_preferences.h"
 
 namespace chrome {
 
@@ -32,8 +31,7 @@
   if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result))
     return false;
   BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
-      BrowserDistribution::CHROME_FRAME,
-      installer::MasterPreferences::ForCurrentProcess());
+      BrowserDistribution::CHROME_FRAME);
   *result = result->Append(dist->GetInstallSubDir());
   *result = result->Append(chrome::kUserDataDirname);
   return true;
diff --git a/chrome/common/chrome_plugin_lib.cc b/chrome/common/chrome_plugin_lib.cc
index fb4ac83..e19a247 100644
--- a/chrome/common/chrome_plugin_lib.cc
+++ b/chrome/common/chrome_plugin_lib.cc
@@ -153,11 +153,11 @@
     reg_path.append(iter.Name());
     base::win::RegKey key(HKEY_CURRENT_USER, reg_path.c_str());
 
-    DWORD is_persistent;
-    if (key.ReadValueDW(kRegistryLoadOnStartup, &is_persistent) &&
-        is_persistent) {
+    DWORD is_persistent = 0;
+    key.ReadValueDW(kRegistryLoadOnStartup, &is_persistent);
+    if (is_persistent) {
       std::wstring path;
-      if (key.ReadValue(kRegistryPath, &path)) {
+      if (key.ReadValue(kRegistryPath, &path) == ERROR_SUCCESS) {
         ChromePluginLib::Create(path, bfuncs);
       }
     }
diff --git a/chrome/common/chrome_plugin_util.cc b/chrome/common/chrome_plugin_util.cc
index 649975f..d88773a 100644
--- a/chrome/common/chrome_plugin_util.cc
+++ b/chrome/common/chrome_plugin_util.cc
@@ -126,6 +126,8 @@
 
 CPError CPB_GetCommandLineArgumentsCommon(const char* url,
                                           std::string* arguments) {
+  // TODO(aa): all of this code is only used by Gears, which we are removing.
+#if defined(OS_WIN)
   const CommandLine cmd = *CommandLine::ForCurrentProcess();
   std::wstring arguments_w;
 
@@ -137,18 +139,10 @@
         file_util::PathExists(user_data_dir)) {
       // TODO(evanm): use CommandLine APIs instead of this.
       arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kUserDataDir) +
-                     L"=\"" + user_data_dir.ToWStringHack() + L"\" ";
+                     L"=\"" + user_data_dir.value() + L"\" ";
     }
   }
 
-#if defined(OS_CHROMEOS)
-  FilePath profile = cmd.GetSwitchValuePath(switches::kLoginProfile);
-  if (!profile.empty()) {
-    arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kLoginProfile) +
-        L"=\"" + profile.ToWStringHack() + L"\" ";
-  }
-#endif
-
   // Use '--app=url' instead of just 'url' to launch the browser with minimal
   // chrome.
   // Note: Do not change this flag!  Old Gears shortcuts will break if you do!
@@ -157,15 +151,18 @@
   ReplaceSubstringsAfterOffset(&url_string, 0, "\"", "%22");
   ReplaceSubstringsAfterOffset(&url_string, 0, ";",  "%3B");
   ReplaceSubstringsAfterOffset(&url_string, 0, "$",  "%24");
-#if defined(OS_WIN)  // Windows shortcuts can't escape % so we use \x instead.
+  // Windows shortcuts can't escape % so we use \x instead.
   ReplaceSubstringsAfterOffset(&url_string, 0, "%",  "\\x");
-#endif
   std::wstring url_w = UTF8ToWide(url_string);
   // TODO(evanm): use CommandLine APIs instead of this.
   arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kApp) +
       L"=\"" + url_w + L"\"";
 
   *arguments = WideToUTF8(arguments_w);
+#else
+  // None of this code is used on non-Windows platforms.
+  NOTREACHED();
+#endif
 
   return CPERR_SUCCESS;
 }
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 935a711..c4d19bf 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -43,6 +43,10 @@
 // useful for automation testing of the gallery.
 const char kAllowScriptingGallery[]         = "allow-scripting-gallery";
 
+// This prevents Chrome from requiring authorization to run certain widely
+// installed but less commonly used plug-ins.
+const char kAlwaysAuthorizePlugins[]        = "always-authorize-plugins";
+
 // Enable web inspector for all windows, even if they're part of the browser.
 // Allows us to use our dev tools to debug browser windows itself.
 const char kAlwaysEnableDevTools[]          = "always-enable-dev-tools";
@@ -87,6 +91,11 @@
 // automation-related messages on IPC channel with the given ID.
 const char kAutomationClientChannelID[]     = "automation-channel";
 
+// When the option to block third-party cookies from being set is enabled,
+// also block third-party cookies from being read.
+const char kBlockReadingThirdPartyCookies[] =
+    "block-reading-third-party-cookies";
+
 // Causes the browser process to throw an assertion on startup.
 const char kBrowserAssertTest[]             = "assert-test";
 
@@ -111,6 +120,14 @@
 // The unique id to be used for this cloud print proxy instance.
 const char kCloudPrintProxyId[]             = "cloud-print-proxy-id";
 
+// Tells chrome to display the cloud print dialog and upload the
+// specified file for printing.
+const char kCloudPrintFile[]                = "cloud-print-file";
+
+// Used with kCloudPrintFile to specify a title for the resulting print
+// job.
+const char kCloudPrintJobTitle[]            = "cloud-print-job-title";
+
 // The URL of the cloud print service to use, overrides any value
 // stored in preferences, and the default.  Only used if the cloud
 // print service has been enabled (see enable-cloud-print).
@@ -191,11 +208,6 @@
 // exceeded.
 const char kDisableConnectBackupJobs[]      = "disable-connect-backup-jobs";
 
-// Disable requests that webkit labels TargetIsPrefetch.  As of
-// writing only <link rel=prefetch...> but also eventually
-// Link: headers.
-const char kDisableContentPrefetch[]        = "disable-content-prefetch";
-
 // Disables the custom JumpList on Windows 7.
 const char kDisableCustomJumpList[]         = "disable-custom-jumplist";
 
@@ -237,6 +249,9 @@
 // Suppresses support for the Geolocation javascript API.
 const char kDisableGeolocation[]            = "disable-geolocation";
 
+// Disable GL multisampling.
+const char kDisableGLMultisampling[]        = "disable-gl-multisampling";
+
 // Disable the GLSL translator.
 const char kDisableGLSLTranslator[]         = "disable-glsl-translator";
 
@@ -258,6 +273,10 @@
 // Disable the Indexed Database API.
 const char kDisableIndexedDatabase[]         = "disable-indexed-database";
 
+// Disables HTML5 Forms interactive validation.
+const char kDisableInteractiveFormValidation[] =
+    "disable-interactive-form-validation";
+
 // Disable the internal Flash Player.
 const char kDisableInternalFlash[]          = "disable-internal-flash";
 
@@ -343,17 +362,16 @@
 // Disable syncing of extensions.
 const char kDisableSyncExtensions[]         = "disable-sync-extensions";
 
+// Disable syncing browser passwords.
+const char kDisableSyncPasswords[]          = "disable-sync-passwords";
+
 // Disable syncing of preferences.
 const char kDisableSyncPreferences[]        = "disable-sync-preferences";
 
 // Disable syncing of themes.
 const char kDisableSyncThemes[]             = "disable-sync-themes";
 
-// Enable the new autofill type.
-const char kEnableSyncNewAutofill[]     =
-    "enable-sync-new-autofill-data-type";
-
-// Disable tabbed options, i.e., DOMUI version of options window.
+// Disable tabbed options, i.e., WebUI version of options window.
 const char kDisableTabbedOptions[]           = "disable-tabbed-options";
 
 // TabCloseableStateWatcher disallows closing of tabs and browsers under certain
@@ -377,6 +395,9 @@
 // Disable Web Sockets support.
 const char kDisableWebSockets[]             = "disable-web-sockets";
 
+// Disable WebKit's XSSAuditor.  The XSSAuditor mitigates reflective XSS.
+const char kDisableXSSAuditor[]             = "disable-xss-auditor";
+
 // Use a specific disk cache location, rather than one derived from the
 // UserDatadir.
 const char kDiskCacheDir[]                  = "disk-cache-dir";
@@ -412,6 +433,9 @@
 // Enables the hardware acceleration of 3D CSS and animation.
 const char kEnableAcceleratedLayers[]       = "enable-accelerated-layers";
 
+// Enables the hardware acceleration of plugins.
+const char kEnableAcceleratedPlugins[]       = "enable-accelerated-plugins";
+
 // Enables WebKit accessibility within the renderer process.
 const char kEnableAccessibility[]           = "enable-accessibility";
 
@@ -454,11 +478,6 @@
 // exceeded.
 const char kEnableConnectBackupJobs[]       = "enable-connect-backup-jobs";
 
-// Enable requests that webkit labels TargetIsPrefetch.  As of
-// writing only <link rel=prefetch...> but also eventually
-// Link: headers.
-const char kEnableContentPrefetch[]         = "enable-content-prefetch";
-
 // Enables web developers to create apps for Chrome without using crx packages.
 const char kEnableCrxlessWebApps[]          = "enable-crxless-web-apps";
 
@@ -486,6 +505,14 @@
 // testing, for example page cycler and layout tests.  See bug 1157243.
 const char kEnableFileCookies[]             = "enable-file-cookies";
 
+// Enable FileSystem API URLs.
+const char kEnableFileSystemURLScheme[]     = "enable-filesystem-url-scheme";
+
+// Enable the in-browser thumbnailing, which is more efficient than the
+// in-renderer thumbnailing, as we can use more information to determine
+// if we need to update thumbnails.
+const char kEnableInBrowserThumbnailing[]   = "enable-in-browser-thumbnailing";
+
 // Enable IPv6 support, even if probes suggest that it may not be fully
 // supported.  Some probes may require internet connections, and this flag will
 // allow support independent of application testing.
@@ -495,6 +522,9 @@
 // Enable the GPU plugin and Pepper 3D rendering.
 const char kEnableGPUPlugin[]               = "enable-gpu-plugin";
 
+// Enable experimental JavaScript I18N API.
+const char kEnableJavaScriptI18NAPI[]       = "enable-javascript-i18n-api";
+
 // Force logging to be enabled.  Logging is disabled by default in release
 // builds.
 const char kEnableLogging[]                 = "enable-logging";
@@ -508,7 +538,7 @@
 const char kEnableMonitorProfile[]          = "enable-monitor-profile";
 
 // Runs the Native Client inside the renderer process and enables GPU plugin
-// (internally adds kInternalNaCl and lEnableGpuPlugin to the command line).
+// (internally adds lEnableGpuPlugin to the command line).
 const char kEnableNaCl[]                    = "enable-nacl";
 
 // Enables debugging via RSP over a socket.
@@ -517,13 +547,6 @@
 // Enable Native Web Worker support.
 const char kEnableNativeWebWorkers[]        = "enable-native-web-workers";
 
-// Is InstantController::PREDICTIVE_TYPE enabled?
-const char kEnablePredictiveInstant[]       = "enable-predictive-instant";
-
-// Is InstantController::PREDICTIVE_NO_AUTO_COMPLETE_TYPE enabled?
-const char kEnablePredictiveNoAutoCompleteInstant[] =
-    "enable-predictive-no-auto-complete-instant";
-
 // This applies only when the process type is "service". Enables the
 // Chromoting Host Process within the service process.
 const char kEnableRemoting[]                = "enable-remoting";
@@ -532,9 +555,6 @@
 const char kEnableResourceContentSettings[] =
     "enable-resource-content-settings";
 
-// Enable speculative prerendering of pages.
-const char kEnablePagePrerender[]           = "enable-page-prerender";
-
 // Enable speculative TCP/IP preconnection.
 const char kEnablePreconnect[]              = "enable-preconnect";
 
@@ -563,9 +583,6 @@
 // Enable syncing browser autofill.
 const char kEnableSyncAutofill[]            = "enable-sync-autofill";
 
-// Enable syncing browser passwords.
-const char kEnableSyncPasswords[]           = "enable-sync-passwords";
-
 // Enable syncing browser sessions.
 const char kEnableSyncSessions[]            = "enable-sync-sessions";
 
@@ -576,15 +593,9 @@
 // SYN packet.
 const char kEnableTcpFastOpen[]             = "enable-tcp-fastopen";
 
-// Enables TopSites.
-const char kEnableTopSites[]                = "enable-top-sites";
-
 // Whether or not the touch events API is exposed.
 const char kEnableTouch[]                   = "enable-touch";
 
-// Is verbatim instant enabled?
-const char kEnableVerbatimInstant[]         = "enable-verbatim-instant";
-
 // Enables the option to show tabs as a vertical stack down the side of the
 // browser window.
 const char kEnableVerticalTabs[]            = "enable-vertical-tabs";
@@ -603,8 +614,8 @@
 // Order of the listed sub-arguments does not matter.
 const char kEnableWatchdog[]                = "enable-watchdog";
 
-// Disable WebKit's XSSAuditor.  The XSSAuditor mitigates reflective XSS.
-const char kEnableXSSAuditor[]              = "enable-xss-auditor";
+// Enable web audio API.
+const char kEnableWebAudio[]                = "enable-webaudio";
 
 // Enables experimental features for the geolocation API.
 // Current features:
@@ -667,10 +678,6 @@
 // current details.
 const char kForceFieldTestNameAndValue[]    = "force-fieldtest";
 
-// Forces the internal PDF plugin to be used for this run, even if it's disabled
-// by default.  Used for testing.
-const char kForceInternalPDFPlugin[]        = "force-internal-pdf";
-
 // Force renderer accessibility to be on instead of enabling it on demand when
 // a screen reader is detected. The disable-renderer-accessibility switch
 // overrides this if present.
@@ -752,9 +759,6 @@
 // TemplateURL.
 const char kInstantURL[]                    = "instant-url";
 
-// Runs the Native Client inside the renderer process.
-const char kInternalNaCl[]                  = "internal-nacl";
-
 // Runs a trusted Pepper plugin inside the renderer process.
 const char kInternalPepper[]                = "internal-pepper";
 
@@ -805,6 +809,9 @@
 // and performance tests.
 const char kMetricsRecordingOnly[]          = "metrics-recording-only";
 
+// The minimum version of Flash that implements the NPP_ClearSiteData API.
+const char kMinClearSiteDataFlashVersion[]  = "min-clearsitedata-flash-version";
+
 // Sets the default IP address (interface) for the stub (normally 127.0.0.1).
 const char kNaClDebugIP[]                   = "nacl-debug-ip";
 
@@ -923,9 +930,18 @@
 // Causes the PPAPI sub process to display a dialog on launch.
 const char kPpapiStartupDialog[]            = "ppapi-startup-dialog";
 
-// Establishes a channel to the GPU process asynchronously and (re)launches it
-// if necessary when a renderer process starts.
-const char kPrelaunchGpuProcess[]           = "prelaunch-gpu-process";
+// Controls speculative prerendering of pages, and content prefetching.  Both
+// are dispatched from <link rel=prefetch href=...> elements.
+const char kPrerender[]                     = "prerender";
+// These are the values the switch may have, as in "--prerender=auto".
+//   auto: Allow field trial selection in both prerender and prefetch.
+const char kPrerenderSwitchValueAuto[]      = "auto";
+//   disabled: No prerendering or prefetching.
+const char kPrerenderSwitchValueDisabled[]  = "disabled";
+//   enabled: Both prerendering and prefetching.
+const char kPrerenderSwitchValueEnabled[]   = "enabled";
+//   prefetch_only: No prerendering, but enable prefetching.
+const char kPrerenderSwitchValuePrefetchOnly[] = "prefetch_only";
 
 // Prints the pages on the screen.
 const char kPrint[]                         = "print";
@@ -953,6 +969,26 @@
 // Causes the process to run as a profile import subprocess.
 const char kProfileImportProcess[]          = "profile-import";
 
+// Starts the sampling based profiler for the browser process at
+// startup. This will only work if chrome has been built with
+// the gyp variable profiling=1. The output will go to the value
+// of kProfilingFile.
+const char kProfilingAtStart[]              = "profiling-at-start";
+
+// Specifies a location for profiling output. This will only work if chrome
+// has been built with the gyp variable profiling=1.
+//   {pid} if present will be replaced by the pid of the process.
+//   {count} if present will be incremented each time a profile is generated
+//           for this process.
+// The default is chrome-profile-{pid}.
+const char kProfilingFile[]                 = "profiling-file";
+
+// Controls whether profile data is periodically flushed to a file.
+// Normally the data gets written on exit but cases exist where chrome
+// doesn't exit cleanly (especially when using single-process).
+// A time in seconds can be specified.
+const char kProfilingFlush[]                = "profiling-flush";
+
 // Force proxy auto-detection.
 const char kProxyAutoDetect[]               = "proxy-auto-detect";
 
@@ -986,6 +1022,9 @@
 // Register pepper plugins that should be loaded into the renderer.
 const char kRegisterPepperPlugins[]         = "register-pepper-plugins";
 
+// Reload pages that have been killed when they are next focused by the user.
+const char kReloadKilledTabs[]              = "reload-killed-tabs";
+
 // Enable remote debug over HTTP on the specified port.
 const char kRemoteDebuggingPort[]           = "remote-debugging-port";
 
@@ -1277,8 +1316,8 @@
 // switch separates chrome code from the rest of ChromeOS.
 const char kForceStubLibcros[]              = "force-stub-libcros";
 
-// Enables DOMUI menu.
-const char kEnableDOMUIMenu[]               = "enable-domui-menu";
+// Enables WebUI menu.
+const char kEnableWebUIMenu[]               = "enable-webui-menu";
 
 // Enables Media Player.
 const char kEnableMediaPlayer[]             = "enable-media-player";
@@ -1321,9 +1360,6 @@
 // has been out there for a few dev channel releases without problems.
 const char kDisableHolePunching[]           = "disable-hole-punching";
 
-// Enables the tabs expose feature ( http://crbug.com/50307 ).
-const char kEnableExposeForTabs[] = "enable-expose-for-tabs";
-
 // Cause the OS X sandbox write to syslog every time an access to a resource
 // is denied by the sandbox.
 const char kEnableSandboxLogging[]          = "enable-sandbox-logging";
@@ -1332,6 +1368,12 @@
 const char kKioskMode[]                     = "kiosk";
 #endif
 
+// Enables debug paint in views framework. Enabling this causes the damaged
+// region being painted to flash in red.
+#if defined(TOOLKIT_VIEWS)
+const char kDebugViewsPaint[]               = "debug-views-paint";
+#endif
+
 #ifndef NDEBUG
 // Clear the token service before using it.  This allows simulating
 // the expiration of credentials during testing.
@@ -1350,6 +1392,9 @@
 #endif
 
 #if defined(HAVE_XINPUT2)
+// Tells chrome to interpret events from these devices as touch events. Only
+// available with XInput 2 (i.e. X server 1.8 or above). The id's of the devices
+// can be retrieved from 'xinput list'.
 const char kTouchDevices[]                  = "touch-devices";
 #endif
 
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 9a24f9f..988c2f2 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -27,6 +27,7 @@
 extern const char kAllowSSLMITMProxies[];
 extern const char kAllowSandboxDebugging[];
 extern const char kAllowScriptingGallery[];
+extern const char kAlwaysAuthorizePlugins[];
 extern const char kAlwaysEnableDevTools[];
 extern const char kApp[];
 extern const char kAppId[];
@@ -38,12 +39,15 @@
 extern const char kAuthSchemes[];
 extern const char kAuthServerWhitelist[];
 extern const char kAutomationClientChannelID[];
+extern const char kBlockReadingThirdPartyCookies[];
 extern const char kBrowserAssertTest[];
 extern const char kBrowserCrashTest[];
 extern const char kBrowserSubprocessPath[];
 extern const char kCheckForUpdateIntervalSec[];
 extern const char kChromeFrame[];
 extern const char kChromeVersion[];
+extern const char kCloudPrintFile[];
+extern const char kCloudPrintJobTitle[];
 extern const char kCloudPrintProxyId[];
 extern const char kCloudPrintServiceURL[];
 extern const char kConflictingModulesCheck[];
@@ -63,7 +67,6 @@
 extern const char kDisableBackingStoreLimit[];
 extern const char kDisableBlockContentAnimation[];
 extern const char kDisableConnectBackupJobs[];
-extern const char kDisableContentPrefetch[];
 extern const char kDisableCustomJumpList[];
 extern const char kDisableDatabases[];
 extern const char kDisableDesktopNotifications[];
@@ -75,12 +78,14 @@
 extern const char kDisableExtensions[];
 extern const char kDisableFileSystem[];
 extern const char kDisableFlashSandbox[];
+extern const char kDisableGLMultisampling[];
 extern const char kDisableGLSLTranslator[];
 extern const char kDisableGeolocation[];
 extern const char kDisableGpuWatchdog[];
 extern const char kDisableHangMonitor[];
 extern const char kDisableHistoryQuickProvider[];
 extern const char kDisableHistoryURLProvider[];
+extern const char kDisableInteractiveFormValidation[];
 extern const char kDisableInternalFlash[];
 extern const char kDisableIndexedDatabase[];
 extern const char kDisableIPv6[];
@@ -107,6 +112,7 @@
 extern const char kDisableSyncAutofillProfile[];
 extern const char kDisableSyncBookmarks[];
 extern const char kDisableSyncExtensions[];
+extern const char kDisableSyncPasswords[];
 extern const char kDisableSyncPreferences[];
 extern const char kDisableSyncThemes[];
 extern const char kDisableTabbedOptions[];
@@ -115,6 +121,7 @@
 extern const char kDisableWebResources[];
 extern const char kDisableWebSecurity[];
 extern const char kDisableWebSockets[];
+extern const char kDisableXSSAuditor[];
 extern const char kDiskCacheDir[];
 extern const char kDiskCacheSize[];
 extern const char kDnsLogDetails[];
@@ -124,6 +131,7 @@
 extern const char kDumpHistogramsOnExit[];
 extern const char kEnableAccelerated2dCanvas[];
 extern const char kEnableAcceleratedLayers[];
+extern const char kEnableAcceleratedPlugins[];
 extern const char kEnableAccessibility[];
 extern const char kEnableAeroPeekTabs[];
 extern const char kEnableAuthNegotiatePort[];
@@ -135,7 +143,6 @@
 extern const char kEnableCloudPrint[];
 extern const char kEnableConfirmToQuit[];
 extern const char kEnableConnectBackupJobs[];
-extern const char kEnableContentPrefetch[];
 extern const char kEnableCrxlessWebApps[];
 extern const char kEnableDeviceMotion[];
 extern const char kEnableDNSCertProvenanceChecking[];
@@ -144,19 +151,18 @@
 extern const char kEnableExtensionTimelineApi[];
 extern const char kEnableFastback[];
 extern const char kEnableFileCookies[];
+extern const char kEnableFileSystemURLScheme[];
 extern const char kEnableGPUPlugin[];
+extern const char kEnableInBrowserThumbnailing[];
 extern const char kEnableIPv6[];
+extern const char kEnableJavaScriptI18NAPI[];
 extern const char kEnableLogging[];
 extern const char kEnableMemoryInfo[];
 extern const char kEnableMonitorProfile[];
 extern const char kEnableNaCl[];
 extern const char kEnableNaClDebug[];
 extern const char kEnableNativeWebWorkers[];
-extern const char kEnablePagePrerender[];
-extern const char kEnableSyncNewAutofill[];
 extern const char kEnablePreconnect[];
-extern const char kEnablePredictiveInstant[];
-extern const char kEnablePredictiveNoAutoCompleteInstant[];
 extern const char kEnablePreparsedJsCaching[];
 extern const char kEnablePrintPreview[];
 extern const char kEnableRemoting[];
@@ -167,19 +173,17 @@
 extern const char kEnableStatsTable[];
 extern const char kEnableSync[];
 extern const char kEnableSyncAutofill[];
-extern const char kEnableSyncPasswords[];
 extern const char kEnableSyncPreferences[];
 extern const char kEnableSyncSessions[];
 extern const char kEnableSyncTypedUrls[];
 extern const char kEnableTcpFastOpen[];
 extern const char kEnableTopSites[];
 extern const char kEnableTouch[];
-extern const char kEnableVerbatimInstant[];
 extern const char kEnableVerticalTabs[];
 extern const char kEnableVideoFullscreen[];
 extern const char kEnableVideoLogging[];
 extern const char kEnableWatchdog[];
-extern const char kEnableXSSAuditor[];
+extern const char kEnableWebAudio[];
 // Experimental features.
 extern const char kExperimentalLocationFeatures[];
 extern const char kExperimentalSpellcheckerFeatures[];
@@ -194,7 +198,6 @@
 extern const char kFirstRun[];
 extern const char kForceAppsPromoVisible[];
 extern const char kForceFieldTestNameAndValue[];
-extern const char kForceInternalPDFPlugin[];
 extern const char kForceRendererAccessibility[];
 extern const char kForceStubLibcros[];
 extern const char kGpuLauncher[];
@@ -215,7 +218,6 @@
 extern const char kInProcessWebGL[];
 extern const char kIncognito[];
 extern const char kInstantURL[];
-extern const char kInternalNaCl[];
 extern const char kInternalPepper[];
 extern const char kJavaScriptFlags[];
 extern const char kKeepAliveForTest[];
@@ -231,6 +233,7 @@
 extern const char kMemoryProfiling[];
 extern const char kMessageLoopHistogrammer[];
 extern const char kMetricsRecordingOnly[];
+extern const char kMinClearSiteDataFlashVersion[];
 extern const char kNaClDebugIP[];
 extern const char kNaClDebugPorts[];
 extern const char kNaClBrokerProcess[];
@@ -264,13 +267,20 @@
 extern const char kPpapiPluginLauncher[];
 extern const char kPpapiPluginProcess[];
 extern const char kPpapiStartupDialog[];
-extern const char kPrelaunchGpuProcess[];
+extern const char kPrerender[];
+extern const char kPrerenderSwitchValueAuto[];
+extern const char kPrerenderSwitchValueDisabled[];
+extern const char kPrerenderSwitchValueEnabled[];
+extern const char kPrerenderSwitchValuePrefetchOnly[];
 extern const char kPrint[];
 extern const char kProcessPerSite[];
 extern const char kProcessPerTab[];
 extern const char kProcessType[];
 extern const char kProductVersion[];
 extern const char kProfileImportProcess[];
+extern const char kProfilingAtStart[];
+extern const char kProfilingFile[];
+extern const char kProfilingFlush[];
 extern const char kProxyAutoDetect[];
 extern const char kProxyBypassList[];
 extern const char kProxyPacUrl[];
@@ -278,6 +288,7 @@
 extern const char kPurgeMemoryButton[];
 extern const char kRecordMode[];
 extern const char kRegisterPepperPlugins[];
+extern const char kReloadKilledTabs[];
 extern const char kRemoteDebuggingPort[];
 extern const char kRemoteShellPort[];
 extern const char kRendererAssertTest[];
@@ -359,7 +370,7 @@
 extern const char kStubCros[];
 extern const char kScreenSaverUrl[];
 extern const char kCompressSystemFeedback[];
-extern const char kEnableDOMUIMenu[];
+extern const char kEnableWebUIMenu[];
 extern const char kEnableMediaPlayer[];
 extern const char kEnableAdvancedFileSystem[];
 #endif
@@ -382,12 +393,15 @@
 
 #if defined(OS_MACOSX)
 extern const char kDisableHolePunching[];
-extern const char kEnableExposeForTabs[];
 extern const char kEnableSandboxLogging[];
 #else
 extern const char kKioskMode[];
 #endif
 
+#if defined(TOOLKIT_VIEWS)
+extern const char kDebugViewsPaint[];
+#endif
+
 #ifndef NDEBUG
 extern const char kClearTokenService[];
 extern const char kGearsPluginPathOverride[];
diff --git a/chrome/common/common.sb b/chrome/common/common.sb
index 4b5c4f5..ec97f66 100644
--- a/chrome/common/common.sb
+++ b/chrome/common/common.sb
@@ -33,4 +33,4 @@
     (regex #"^/System/Library/CoreServices($|/)"))  ; 10.5.6
 
 ; Needed for IPC on 10.6
-;10.6_ONLY (allow ipc-posix-shm)
\ No newline at end of file
+;10.6_ONLY (allow ipc-posix-shm)
diff --git a/chrome/common/common_glue.cc b/chrome/common/common_glue.cc
index 5fe6094..4573dfb 100644
--- a/chrome/common/common_glue.cc
+++ b/chrome/common/common_glue.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "app/app_switches.h"
-#include "app/l10n_util.h"
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/string16.h"
@@ -13,6 +12,8 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/plugin/npobject_util.h"
 #include "googleurl/src/url_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_switches.h"
 #include "webkit/glue/webkit_glue.h"
 
 namespace webkit_glue {
diff --git a/chrome/common/common_message_generator.cc b/chrome/common/common_message_generator.cc
new file mode 100644
index 0000000..e349e3b
--- /dev/null
+++ b/chrome/common/common_message_generator.cc
@@ -0,0 +1,33 @@
+// 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "chrome/common/common_message_generator.h"
+#include "chrome/common/common_param_traits.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "chrome/common/common_message_generator.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "chrome/common/common_message_generator.h"
+
+namespace IPC {
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+#include "chrome/common/common_message_generator.h"
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+#include "chrome/common/common_message_generator.h"
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+#include "chrome/common/common_message_generator.h"
+
+}  // namespace IPC
+
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h
new file mode 100644
index 0000000..3a31c77
--- /dev/null
+++ b/chrome/common/common_message_generator.h
@@ -0,0 +1,29 @@
+// 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.
+
+// Multiply-included file, hence no include guard.
+
+#include "chrome/common/indexed_db_messages.h"
+
+#if 0  // This feature is not yet enabled for these files.
+
+#include "chrome/common/autofill_messages.h"
+#include "chrome/common/automation_messages.h"
+#include "chrome/common/database_messages.h"
+#include "chrome/common/devtools_messages.h"
+#include "chrome/common/dom_storage_messages.h"
+#include "chrome/common/file_utilities_messages.h"
+#include "chrome/common/gpu_messages.h"
+#include "chrome/common/mime_registry_messages.h"
+#include "chrome/common/nacl_messages.h"
+#include "chrome/common/pepper_file_messages.h"
+#include "chrome/common/pepper_messages.h"
+#include "chrome/common/plugin_messages.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/service_messages.h"
+#include "chrome/common/speech_input_messages.h"
+#include "chrome/common/utility_messages.h"
+#include "chrome/common/worker_messages.h"
+
+#endif
diff --git a/chrome/common/common_param_traits.cc b/chrome/common/common_param_traits.cc
index 40417fc..64fa35c 100644
--- a/chrome/common/common_param_traits.cc
+++ b/chrome/common/common_param_traits.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,12 +10,12 @@
 #include "chrome/common/geoposition.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/upload_data.h"
 #include "printing/backend/print_backend.h"
 #include "printing/native_metafile.h"
 #include "printing/page_range.h"
+#include "ui/gfx/rect.h"
 
 #ifndef EXCLUDE_SKIA_DEPENDENCIES
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -290,50 +290,52 @@
   l->append("<WebApplicationInfo>");
 }
 
-void ParamTraits<URLRequestStatus>::Write(Message* m, const param_type& p) {
+void ParamTraits<net::URLRequestStatus>::Write(Message* m,
+                                               const param_type& p) {
   WriteParam(m, static_cast<int>(p.status()));
   WriteParam(m, p.os_error());
 }
 
-bool ParamTraits<URLRequestStatus>::Read(const Message* m, void** iter,
-                                         param_type* r) {
+bool ParamTraits<net::URLRequestStatus>::Read(const Message* m, void** iter,
+                                              param_type* r) {
   int status, os_error;
   if (!ReadParam(m, iter, &status) ||
       !ReadParam(m, iter, &os_error))
     return false;
-  r->set_status(static_cast<URLRequestStatus::Status>(status));
+  r->set_status(static_cast<net::URLRequestStatus::Status>(status));
   r->set_os_error(os_error);
   return true;
 }
 
-void ParamTraits<URLRequestStatus>::Log(const param_type& p, std::string* l) {
+void ParamTraits<net::URLRequestStatus>::Log(const param_type& p,
+                                             std::string* l) {
   std::string status;
   switch (p.status()) {
-    case URLRequestStatus::SUCCESS:
+    case net::URLRequestStatus::SUCCESS:
       status = "SUCCESS";
       break;
-    case URLRequestStatus::IO_PENDING:
+    case net::URLRequestStatus::IO_PENDING:
       status = "IO_PENDING ";
       break;
-    case URLRequestStatus::HANDLED_EXTERNALLY:
+    case net::URLRequestStatus::HANDLED_EXTERNALLY:
       status = "HANDLED_EXTERNALLY";
       break;
-    case URLRequestStatus::CANCELED:
+    case net::URLRequestStatus::CANCELED:
       status = "CANCELED";
       break;
-    case URLRequestStatus::FAILED:
+    case net::URLRequestStatus::FAILED:
       status = "FAILED";
       break;
     default:
       status = "UNKNOWN";
       break;
   }
-  if (p.status() == URLRequestStatus::FAILED)
+  if (p.status() == net::URLRequestStatus::FAILED)
     l->append("(");
 
   LogParam(status, l);
 
-  if (p.status() == URLRequestStatus::FAILED) {
+  if (p.status() == net::URLRequestStatus::FAILED) {
     l->append(", ");
     LogParam(p.os_error(), l);
     l->append(")");
@@ -348,47 +350,83 @@
   typedef net::UploadData::Element param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, static_cast<int>(p.type()));
-    if (p.type() == net::UploadData::TYPE_BYTES) {
-      m->WriteData(&p.bytes()[0], static_cast<int>(p.bytes().size()));
-    } else if (p.type() == net::UploadData::TYPE_FILE) {
-      WriteParam(m, p.file_path());
-      WriteParam(m, p.file_range_offset());
-      WriteParam(m, p.file_range_length());
-      WriteParam(m, p.expected_file_modification_time());
-    } else {
-      WriteParam(m, p.blob_url());
+    switch (p.type()) {
+      case net::UploadData::TYPE_BYTES: {
+        m->WriteData(&p.bytes()[0], static_cast<int>(p.bytes().size()));
+        break;
+      }
+      case net::UploadData::TYPE_CHUNK: {
+        m->WriteData(&p.bytes()[0], static_cast<int>(p.bytes().size()));
+        // If this element is part of a chunk upload then send over information
+        // indicating if this is the last chunk.
+        WriteParam(m, p.is_last_chunk());
+        break;
+      }
+      case net::UploadData::TYPE_FILE: {
+        WriteParam(m, p.file_path());
+        WriteParam(m, p.file_range_offset());
+        WriteParam(m, p.file_range_length());
+        WriteParam(m, p.expected_file_modification_time());
+        break;
+      }
+      default: {
+        WriteParam(m, p.blob_url());
+        break;
+      }
     }
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     int type;
     if (!ReadParam(m, iter, &type))
       return false;
-    if (type == net::UploadData::TYPE_BYTES) {
-      const char* data;
-      int len;
-      if (!m->ReadData(iter, &data, &len))
-        return false;
-      r->SetToBytes(data, len);
-    } else if (type == net::UploadData::TYPE_FILE) {
-      FilePath file_path;
-      uint64 offset, length;
-      base::Time expected_modification_time;
-      if (!ReadParam(m, iter, &file_path))
-        return false;
-      if (!ReadParam(m, iter, &offset))
-        return false;
-      if (!ReadParam(m, iter, &length))
-        return false;
-      if (!ReadParam(m, iter, &expected_modification_time))
-        return false;
-      r->SetToFilePathRange(file_path, offset, length,
-                            expected_modification_time);
-    } else {
-      DCHECK(type == net::UploadData::TYPE_BLOB);
-      GURL blob_url;
-      if (!ReadParam(m, iter, &blob_url))
-        return false;
-      r->SetToBlobUrl(blob_url);
+    switch (type) {
+      case net::UploadData::TYPE_BYTES: {
+        const char* data;
+        int len;
+        if (!m->ReadData(iter, &data, &len))
+          return false;
+        r->SetToBytes(data, len);
+        break;
+      }
+      case net::UploadData::TYPE_CHUNK: {
+        const char* data;
+        int len;
+        if (!m->ReadData(iter, &data, &len))
+          return false;
+        r->SetToBytes(data, len);
+        // If this element is part of a chunk upload then we need to explicitly
+        // set the type of the element and whether it is the last chunk.
+        bool is_last_chunk = false;
+        if (!ReadParam(m, iter, &is_last_chunk))
+          return false;
+        r->set_type(net::UploadData::TYPE_CHUNK);
+        r->set_is_last_chunk(is_last_chunk);
+        break;
+      }
+      case net::UploadData::TYPE_FILE: {
+        FilePath file_path;
+        uint64 offset, length;
+        base::Time expected_modification_time;
+        if (!ReadParam(m, iter, &file_path))
+          return false;
+        if (!ReadParam(m, iter, &offset))
+          return false;
+        if (!ReadParam(m, iter, &length))
+          return false;
+        if (!ReadParam(m, iter, &expected_modification_time))
+          return false;
+        r->SetToFilePathRange(file_path, offset, length,
+                              expected_modification_time);
+        break;
+      }
+      default: {
+        DCHECK(type == net::UploadData::TYPE_BLOB);
+        GURL blob_url;
+        if (!ReadParam(m, iter, &blob_url))
+          return false;
+        r->SetToBlobUrl(blob_url);
+        break;
+      }
     }
     return true;
   }
@@ -403,6 +441,7 @@
   if (p) {
     WriteParam(m, *p->elements());
     WriteParam(m, p->identifier());
+    WriteParam(m, p->is_chunked());
   }
 }
 
@@ -420,9 +459,13 @@
   int64 identifier;
   if (!ReadParam(m, iter, &identifier))
     return false;
+  bool is_chunked = false;
+  if (!ReadParam(m, iter, &is_chunked))
+    return false;
   *r = new net::UploadData;
   (*r)->swap_elements(&elements);
   (*r)->set_identifier(identifier);
+  (*r)->set_is_chunked(is_chunked);
   return true;
 }
 
diff --git a/chrome/common/common_param_traits.h b/chrome/common/common_param_traits.h
index ad9c05a..f1e8cb0 100644
--- a/chrome/common/common_param_traits.h
+++ b/chrome/common/common_param_traits.h
@@ -18,7 +18,6 @@
 #include "base/ref_counted.h"
 #include "chrome/common/content_settings.h"
 #include "chrome/common/page_zoom.h"
-#include "gfx/native_widget_types.h"
 #include "ipc/ipc_message_utils.h"
 #include "net/url_request/url_request_status.h"
 #include "printing/native_metafile.h"
@@ -30,6 +29,7 @@
 //
 // TODO(erg): The following two headers are historical and only work because
 // their definitions are inlined, which also needs to be fixed.
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/webcursor.h"
 #include "webkit/glue/window_open_disposition.h"
 
@@ -265,8 +265,8 @@
 
 // Traits for URLRequestStatus
 template <>
-struct ParamTraits<URLRequestStatus> {
-  typedef URLRequestStatus param_type;
+struct ParamTraits<net::URLRequestStatus> {
+  typedef net::URLRequestStatus param_type;
   static void Write(Message* m, const param_type& p);
   static bool Read(const Message* m, void** iter, param_type* r);
   static void Log(const param_type& p, std::string* l);
diff --git a/chrome/common/common_param_traits_unittest.cc b/chrome/common/common_param_traits_unittest.cc
index 8446158..a11ddd1 100644
--- a/chrome/common/common_param_traits_unittest.cc
+++ b/chrome/common/common_param_traits_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/values.h"
 #include "chrome/common/common_param_traits.h"
 #include "chrome/common/geoposition.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_utils.h"
@@ -18,6 +17,7 @@
 #include "printing/page_range.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/rect.h"
 
 // Tests that serialize/deserialize correctly understand each other
 TEST(IPCMessageTest, Serialize) {
@@ -118,7 +118,7 @@
 
 TEST(IPCMessageTest, ListValue) {
   ListValue input;
-  input.Set(0, Value::CreateRealValue(42.42));
+  input.Set(0, Value::CreateDoubleValue(42.42));
   input.Set(1, Value::CreateStringValue("forty"));
   input.Set(2, Value::CreateNullValue());
 
@@ -149,7 +149,7 @@
   subdict->Set("bool", Value::CreateBooleanValue(false));
 
   scoped_ptr<ListValue> sublist(new ListValue());
-  sublist->Set(0, Value::CreateRealValue(42.42));
+  sublist->Set(0, Value::CreateDoubleValue(42.42));
   sublist->Set(1, Value::CreateStringValue("forty"));
   sublist->Set(2, Value::CreateStringValue("two"));
   subdict->Set("list", sublist.release());
diff --git a/chrome/common/css_colors.h b/chrome/common/css_colors.h
index 9ba36ba..cf4231d 100644
--- a/chrome/common/css_colors.h
+++ b/chrome/common/css_colors.h
@@ -9,8 +9,8 @@
 #include <utility>
 
 #include "base/basictypes.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebColor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebColorName.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebColor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebColorName.h"
 
 // Functionality related to sending the values of CSS colors to the renderer.
 class CSSColors {
diff --git a/chrome/common/database_util.cc b/chrome/common/database_util.cc
index 36abdb8..9e4a99d 100644
--- a/chrome/common/database_util.cc
+++ b/chrome/common/database_util.cc
@@ -8,7 +8,7 @@
 #include "chrome/common/database_messages.h"
 #include "ipc/ipc_sync_message_filter.h"
 #include "third_party/sqlite/sqlite3.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 using WebKit::WebKitClient;
 using WebKit::WebString;
diff --git a/chrome/common/db_message_filter.cc b/chrome/common/db_message_filter.cc
index e10bb1d..50cad70 100644
--- a/chrome/common/db_message_filter.cc
+++ b/chrome/common/db_message_filter.cc
@@ -5,8 +5,8 @@
 #include "chrome/common/db_message_filter.h"
 
 #include "chrome/common/database_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDatabase.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 DBMessageFilter::DBMessageFilter() {
 }
diff --git a/chrome/common/default_plugin.cc b/chrome/common/default_plugin.cc
index 3337c7c..61bbc87 100644
--- a/chrome/common/default_plugin.cc
+++ b/chrome/common/default_plugin.cc
@@ -10,25 +10,20 @@
 namespace chrome {
 
 void RegisterInternalDefaultPlugin() {
-  const webkit::npapi::PluginVersionInfo default_plugin = {
-    FilePath(webkit::npapi::kDefaultPluginLibraryName),
-    L"Default Plug-in",
-    L"Provides functionality for installing third-party plug-ins",
-    L"1",
-    L"*",
-    L"",
-    L"",
-    {
+  const webkit::npapi::PluginEntryPoints entry_points = {
 #if !defined(OS_POSIX) || defined(OS_MACOSX)
-      default_plugin::NP_GetEntryPoints,
+    default_plugin::NP_GetEntryPoints,
 #endif
-      default_plugin::NP_Initialize,
-      default_plugin::NP_Shutdown
-    }
+    default_plugin::NP_Initialize,
+    default_plugin::NP_Shutdown
   };
 
   webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(
-      default_plugin);
+      FilePath(webkit::npapi::kDefaultPluginLibraryName),
+      "Default Plug-in",
+      "Provides functionality for installing third-party plug-ins",
+      "*",
+      entry_points);
 }
 
 }  // namespace chrome
diff --git a/chrome/common/desktop_notifications/active_notification_tracker.cc b/chrome/common/desktop_notifications/active_notification_tracker.cc
index 7bf619c..3603103 100644
--- a/chrome/common/desktop_notifications/active_notification_tracker.cc
+++ b/chrome/common/desktop_notifications/active_notification_tracker.cc
@@ -6,8 +6,8 @@
 
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotification.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPermissionCallback.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotification.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPermissionCallback.h"
 
 using WebKit::WebNotification;
 using WebKit::WebNotificationPermissionCallback;
diff --git a/chrome/common/desktop_notifications/active_notification_tracker.h b/chrome/common/desktop_notifications/active_notification_tracker.h
index 2fd8a6a..9610ce4 100644
--- a/chrome/common/desktop_notifications/active_notification_tracker.h
+++ b/chrome/common/desktop_notifications/active_notification_tracker.h
@@ -11,7 +11,7 @@
 #include "base/basictypes.h"
 #include "base/id_map.h"
 #include "base/hash_tables.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNotification.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotification.h"
 
 namespace WebKit {
 class WebNotificationPermissionCallback;
diff --git a/chrome/common/dom_storage_messages.h b/chrome/common/dom_storage_messages.h
index e36f517..85db0e6 100644
--- a/chrome/common/dom_storage_messages.h
+++ b/chrome/common/dom_storage_messages.h
@@ -10,7 +10,7 @@
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_param_traits.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageArea.h"
 
 #define IPC_MESSAGE_START DOMStorageMsgStart
 
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 7709ec2..55c2946 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -156,7 +156,7 @@
       {
         "name": "getBackgroundPage",
         "type": "function",
-        "description": "Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no backround page.",
+        "description": "Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no background page.",
         "parameters": [],
         "returns": {
           "type": "object", "isInstanceOf": "DOMWindow", "properties": {}, "additionalProperties": { "type": "any" }
@@ -472,29 +472,7 @@
     ]
   },
   {
-    "namespace": "experimental.extension",
-    "nodoc": true,
-    "types": [],
-    "functions": [
-      {
-        "name": "getPopupView",
-        "type": "function",
-        "description": "Returns a reference to the JavaScript 'window' object of the popup view.  Returns undefined if no popup presently shown.",
-        "parameters": [],
-        "returns": {
-          "type": "object",
-          "isInstanceOf": "DOMWindow",
-          "properties": {},
-          "additionalProperties": { "type": "any" },
-          "optional": true
-        }
-      }
-    ],
-    "events": []
-  },
-  {
     "namespace": "experimental.tts",
-    "nodoc": true,
     "functions": [
       {
         "name": "speak",
@@ -504,13 +482,13 @@
           {
             "type": "string",
             "name": "utterance",
-            "description": "The text to speak."
+            "description": "The text to speak. May include SSML markup."
           },
           {
             "type": "object",
             "name": "options",
             "optional": true,
-            "description": "The speak options. This parameter is currently ignored.",
+            "description": "The speech options.",
             "properties": {
               "enqueue": {
 	        "type": "boolean",
@@ -520,12 +498,12 @@
 	      "voiceName": {
                 "type": "string",
                 "optional": true,
-                "description": "The name of the voice to use for synthesis."
+                "description": "The name of the voice to use for synthesis. If empty, uses any available voice."
               },
 	      "locale": {
                 "type": "string",
                 "optional": true,
-                "description": "The language and region code that specify the language and dialect to be used for synthesis, in the form <language>-<region>, e.g. en-US, en-GB, fr-CA, zh-CN, etc."
+                "description": "The language and optional region code that specify the language and dialect to be used for synthesis, in the form &lt;language&gt;-&lt;region&gt;. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc."
               },
               "gender": {
                 "type": "string",
@@ -538,21 +516,21 @@
                 "optional": true,
                 "minimum": 0,
                 "maximum": 1,
-                "description": "Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest."
+                "description": "Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest, with a default of 0.5."
               },
               "pitch": {
                 "type": "number",
                 "optional": true,
                 "minimum": 0,
                 "maximum": 1,
-                "description": "Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest."
+                "description": "Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 0.5."
               },
               "volume": {
                 "type": "number",
                 "optional": true,
                 "minimum": 0,
                 "maximum": 1,
-                "description": "Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest."
+                "description": "Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0."
               }
             }
           },
@@ -617,7 +595,7 @@
           {
             "type": "string",
             "name": "utterance",
-            "description": "The text to speak."
+            "description": "The text to speak. This may include SSML, so if your engine does not support SSML, you should strip out all XML markup and synthesize only the underlying text content."
           },
           {
             "type": "object",
@@ -681,7 +659,7 @@
       {
         "name": "onStop",
         "type": "function",
-        "description": "Fired when a call is made to tts.stop and this extension may be in the middle of speaking."
+        "description": "Fired when a call is made to tts.stop and this extension may be in the middle of speaking. If an extension receives a call to onStop and speech is already stopped, it should do nothing (not raise an error)."
       }
     ]
   },
@@ -2406,94 +2384,6 @@
     "events": []
   },
   {
-    "namespace": "experimental.popup",
-    "nodoc": true,
-    "types": [],
-    "functions": [
-      {
-        "name": "show",
-        "type": "function",
-        "description": "Displays a pop-up window hosting an extension view.",
-        "parameters": [
-          {
-            "type": "string",
-            "name": "url",
-            "description": "The URL of the contents to which the pop-up will be navigated."
-          },
-          {
-            "type": "object",
-            "name": "showDetails",
-            "properties": {
-              "relativeTo": {
-                "type": "object",
-                "properties": {},
-                "additionalProperties": { "type": "any" },
-                "isInstanceOf": "HTMLElement",
-                "description": "A HTML DOM object to which the pop-up's position will be made relative."
-              },
-              "giveFocus": {
-                "type": "boolean",
-                "description": "Pass true to give the focus to the popup window.  The default behaviour is true.",
-                "optional": true
-              },
-              "borderStyle": {
-                "type": "string",
-                "description": "Pass 'bubble' to give the pop-up window a bubble-chrome border, including an arrow pointing at the relative-to point.  Pass 'rectangle' to give the pop-up a rectangular black border with drop-shadow.  Default behaviour is to pass 'bubble'.",
-                "optional": true,
-                "enum": ["bubble", "rectangle"]
-              },
-              "maxSize": {
-                "type": "object",
-                "optional": true,
-                "properties": {
-                  "width": {
-                    "type": "integer",
-                    "description": "The maximal width to which the popup will resize.  If not present, the popup will be no wider than 800 pixels.  The popup will widen to no larger than the minimum of the width parameter and the width of the screen.",
-                    "optional": true,
-                    "minimum": 32
-                  },
-                  "height": {
-                    "type": "integer",
-                    "description": "The maximal height to which the popup will resize.  If not present, the popup will be no taller than 600 pixels.  The popup will grow to no taller than than the minimum of the height parameter and the width of the screen.",
-                    "optional": true,
-                    "minimum": 32
-                  }
-                }
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "getParentWindow",
-        "type": "function",
-        "description": "Returns a reference to the JavaScript 'window' object of the extension view that launched the popup.  Returns undefined if called outside of a popup window.",
-        "parameters": [],
-        "returns": {
-          "type": "object",
-          "isInstanceOf": "DOMWindow",
-          "properties": {},
-          "additionalProperties": { "type": "any" },
-          "optional": true
-        }
-      }
-    ],
-    "events": [
-      {
-        "name": "onClosed",
-        "type": "function",
-        "description": "Fired when the popup view is closed.",
-        "parameters": []
-      }
-    ]
-  },
-  {
     "namespace": "experimental.bookmarkManager",
     "nodoc": true,
     "types": [
@@ -2573,10 +2463,18 @@
       {
         "name": "paste",
         "type": "function",
-        "description": "Pastes bookmarks from the clipboard into the parent folder",
+        "description": "Pastes bookmarks from the clipboard into the parent folder after the last selected node",
         "nodoc": "true",
         "parameters": [
           {"type": "string", "name": "parentId"},
+          {
+            "name": "selectedIdList",
+            "description": "An array of string-valued ids for selected bookmarks",
+            "optional": true,
+            "type": "array",
+            "items": {"type": "string"},
+            "minItems": 0
+          },
           {"type": "function", "name": "callback", "optional": true, "parameters": []}
         ]
       },
@@ -3065,6 +2963,39 @@
     ],
     "functions": [
       {
+        "name": "getEnabled",
+        "type": "function",
+        "description": "Get the user preference to send UMA and crash reports to Google.",
+        "parameters": [
+          {
+            "type": "function",
+            "name": "callback",
+            "parameters": [
+              {"name": "enabled", "type": "boolean"}
+            ]
+          }
+        ]
+      },
+      {
+        "name": "setEnabled",
+        "type": "function",
+        "description": "Set the user preference to send UMA and crash reports to Google.",
+        "parameters": [
+          {"name": "enabled", "type": "boolean", "description": "True for setting Chrome to actively send UMA and crash reports, false for disabling this."},
+          {
+            "type": "function",
+            "name": "callback",
+            "parameters": [
+              {
+                "name": "enabled", 
+                "type": "boolean",
+                "description": "The actual value set. If it is not the one passed in parameter, the value couldn't be changed (e.g. because of security)."
+              }
+            ]
+          }          
+        ]
+      },
+      {
         "name": "recordUserAction",
         "type": "function",
         "description": "Records an action performed by the user.",
@@ -3476,8 +3407,58 @@
   },
   {
     "namespace": "experimental.webRequest",
-    "types": [],
-    "functions": [],
+    "types": [
+      {
+        "id": "RequestFilter",
+        "type": "object",
+        "description": "An object describing filters to apply to webRequest events.",
+        "properties": {
+          "urls": {
+            "type": "array",
+            "optional": true,
+            "description": "A list of URLs or URL patterns. Requests that cannot match any of the URLs will be filtered out.",
+            "items": { "type": "string" }
+          },
+          "types": {
+            "type": "array",
+            "optional": true,
+            "description": "A list of request types. Requests that cannot match any of the types will be filtered out.",
+            "items": { "type": "string", "enum": ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "other"] }
+          },
+          "tabId": { "type": "integer", "optional": true },
+          "windowId": { "type": "integer", "optional": true }
+        }
+      }
+    ],
+    "functions": [
+      {
+        "name": "addEventListener",
+        "nodoc": true,
+        "type": "function",
+        "description": "Used internally to implement the special form of addListener for the webRequest events.",
+        "parameters": [
+          {"type": "function", "name": "callback"},
+          {
+            "$ref": "RequestFilter",
+            "optional": true,
+            "name": "filter",
+            "description": "A set of filters that restricts the events that will be sent to this listener."
+          },
+          {
+            "type": "array",
+            "optional": true,
+            "name": "extraInfoSpec",
+            "description": "Array of extra information that should be passed to the listener function.",
+            "items": {
+              "type": "string",
+              "enum": ["requestLine", "requestHeaders", "statusLine", "responseHeaders", "redirectRequestLine", "redirectRequestHeaders"]
+            }
+          },
+          {"type": "string", "name": "eventName"},
+          {"type": "string", "name": "subEventName"}
+        ]
+      }
+    ],
     "events": [
       {
         "name": "onBeforeRequest",
@@ -3703,7 +3684,7 @@
         "type": "object",
         "description": "An object encapsulating a single proxy server's specification.",
         "properties": {
-          "scheme": {"type": "string", "optional": true, "enum": ["http", "socks", "socks4", "socks5"], "description": "The scheme (protocol) of the proxy server itself."},
+          "scheme": {"type": "string", "optional": true, "enum": ["http", "https", "socks", "socks4", "socks5"], "description": "The scheme (protocol) of the proxy server itself."},
           "host": {"type": "string", "description": "The URI of the proxy server."},
           "port": {"type": "integer", "optional": true, "description": "The port of the proxy server."}
         }
@@ -3711,13 +3692,14 @@
       {
         "id": "ProxyRules",
         "type": "object",
-        "description": "An object encapsulating the set of proxy rules for all protocols.",
+        "description": "An object encapsulating the set of proxy rules for all protocols. Use either 'singleProxy' or (a subset of) 'proxyForHttp', 'proxyForHttps', 'proxyForFtp' and 'socksProxy'.",
         "properties": {
           "singleProxy": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for all per-URL requests (i.e., http, https, and ftp)."},
           "proxyForHttp": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for HTTP requests."},
           "proxyForHttps": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for HTTPS requests."},
           "proxyForFtp": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for FTP requests."},
-          "socksProxy": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for SOCKS requests."}
+          "socksProxy": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for SOCKS requests."},
+          "bypassList": {"type": "array", "items": {"type": "string"}, "optional": true, "description": "List of servers to connect to without a proxy server."}
         }
       },
       {
@@ -3733,8 +3715,8 @@
         "type": "object",
         "description": "An object encapsulating a complete proxy configuration.",
         "properties": {
-          "rules": {"$ref": "ProxyRules", "optional": true, "description": "The proxy rules describing this configuration."},
-          "pacScript": {"$ref": "PacScript", "optional": true, "description": "The proxy auto-config (PAC) script for this configuration."},
+          "rules": {"$ref": "ProxyRules", "optional": true, "description": "The proxy rules describing this configuration. Use this for 'fixed_servers' mode."},
+          "pacScript": {"$ref": "PacScript", "optional": true, "description": "The proxy auto-config (PAC) script for this configuration. Use this for 'pac_script' mode."},
           "mode": {
             "type": "string",
             "enum": ["direct", "auto_detect", "pac_script", "fixed_servers", "system"],
@@ -3749,7 +3731,52 @@
         "type": "function",
         "description": "Apply the given proxy configuration.",
         "parameters": [
-          {"name": "config", "$ref": "ProxyConfig"}
+          {
+            "name": "config",
+            "$ref": "ProxyConfig"
+          },
+          {
+            "name": "incognito",
+            "type": "boolean",
+            "description": "If true, the proxy settings apply only to incognito windows. Otherwise they apply to regular windows (and incognito windows if no specific settings are provided for incognito windows)",
+            "optional": true
+          }
+        ]
+      },
+      {
+        "name": "removeCustomProxySettings",
+        "type": "function",
+        "description": "Remove a custom proxy set by the current extension. This is the inverse of useCustomProxySettings.",
+        "parameters": [
+          {
+            "name": "incognito",
+            "type": "boolean",
+            "description": "See incognito parameter of useCustomProxySettings.",
+            "optional": true
+          }
+        ]
+      },
+      {
+        "name": "getCurrentProxySettings",
+        "type": "function",
+        "description": "Returns the currently effective proxy settings. These can originate from default values, command line options, the extension settings API, policies and possibly other sources in the future.",
+        "parameters": [
+          {
+            "name": "incognito",
+            "type": "boolean",
+            "description": "See incognito parameter of useCustomProxySettings."
+          },
+          {
+            "name": "callback",
+            "type": "function",
+            "parameters": [
+              {
+                "name": "config",
+                "$ref": "ProxyConfig",
+                "description": "Configuration, not necessarily a literal copy of the configuration passed to useCustomProxySettings."
+              }
+            ]
+          }
         ]
       }
     ]
@@ -3875,7 +3902,7 @@
       {
         "name": "navigate",
         "type": "function",
-        "description": "Navigates sidebar for the specified tab to the specified URL.",
+        "description": "Loads the the specified html file into the sidebar for the specified tab.",
         "parameters": [
           {
             "type": "object",
@@ -3887,7 +3914,10 @@
                 "optional": true,
                 "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
               },
-              "url": { "type": "string" }
+              "path": {
+                "type": "string",
+                "description": "Relative path to the html file in the extension to show in the sidebar."
+              }
             }
           }
         ]
diff --git a/chrome/common/extensions/docs/README.txt b/chrome/common/extensions/docs/README.txt
index b056210..ea0c0fa 100644
--- a/chrome/common/extensions/docs/README.txt
+++ b/chrome/common/extensions/docs/README.txt
@@ -35,10 +35,10 @@
 This will regenerate the docs and report which, if any, files have changed
 and need to be included in the changelist that changed the dependent files.
 
-Note that the build.py script depends on test_shell to run, so you must be
-able to build test_shell to build extension_docs. The build.py script will
-look in typical locations for the test_shell executable, but you may set
-the path to test_shell explicitly with --test-shell-path.
+Note that the build.py script depends on DumpRenderTree to run, so you must be
+able to build DumpRenderTree to build extension_docs. The build.py script will
+look in typical locations for the DumpRenderTree executable, but you may set
+the path to DumpRenderTree explicitly with --dump-render-tree-path.
 
 --------------------------------------------------------------------------------
 Design
diff --git a/chrome/common/extensions/docs/a11y.html b/chrome/common/extensions/docs/a11y.html
index d18f6f7..356c452 100644
--- a/chrome/common/extensions/docs/a11y.html
+++ b/chrome/common/extensions/docs/a11y.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -300,7 +310,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -308,7 +318,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -815,8 +825,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -891,10 +901,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -912,14 +921,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/api_index.html b/chrome/common/extensions/docs/api_index.html
index af8e72b..fcfd737 100644
--- a/chrome/common/extensions/docs/api_index.html
+++ b/chrome/common/extensions/docs/api_index.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -289,7 +299,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -382,8 +392,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -458,10 +468,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -479,14 +488,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/api_other.html b/chrome/common/extensions/docs/api_other.html
index 7a0077e..3490961 100644
--- a/chrome/common/extensions/docs/api_other.html
+++ b/chrome/common/extensions/docs/api_other.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -414,8 +424,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -490,10 +500,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -511,14 +520,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/apps.html b/chrome/common/extensions/docs/apps.html
index 7a79f45..8130ad6 100644
--- a/chrome/common/extensions/docs/apps.html
+++ b/chrome/common/extensions/docs/apps.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -289,7 +299,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -512,8 +522,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -588,10 +598,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -609,14 +618,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/autoupdate.html b/chrome/common/extensions/docs/autoupdate.html
index d3aaf51..69d7c31 100644
--- a/chrome/common/extensions/docs/autoupdate.html
+++ b/chrome/common/extensions/docs/autoupdate.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -302,7 +312,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -310,7 +320,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -471,8 +481,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -547,10 +557,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -568,14 +577,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/background_pages.html b/chrome/common/extensions/docs/background_pages.html
index 85d9b99..2516499 100644
--- a/chrome/common/extensions/docs/background_pages.html
+++ b/chrome/common/extensions/docs/background_pages.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -289,7 +299,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -464,8 +474,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -540,10 +550,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -561,14 +570,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/bookmarks.html b/chrome/common/extensions/docs/bookmarks.html
index 33dd392..71ff4c2 100644
--- a/chrome/common/extensions/docs/bookmarks.html
+++ b/chrome/common/extensions/docs/bookmarks.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-create">create</a>
@@ -311,7 +321,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onChanged">onChanged</a>
@@ -464,8 +474,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -587,6 +597,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -647,6 +667,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -707,6 +737,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -767,6 +807,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -777,6 +827,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -837,6 +897,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -925,6 +995,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1080,6 +1160,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1140,6 +1230,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1239,6 +1339,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1330,6 +1440,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1390,6 +1510,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1489,6 +1619,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1578,6 +1718,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1638,6 +1788,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1737,6 +1897,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1827,6 +1997,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1926,6 +2106,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2084,6 +2274,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2191,6 +2391,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2251,6 +2461,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2261,6 +2481,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2321,6 +2551,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2409,6 +2649,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2500,6 +2750,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2560,6 +2820,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2682,6 +2952,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2742,6 +3022,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2864,6 +3154,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2924,6 +3224,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3023,6 +3333,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3115,6 +3435,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3222,6 +3552,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3282,6 +3622,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3292,6 +3642,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3352,6 +3712,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3440,6 +3810,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3465,10 +3845,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onChanged"></a>
@@ -3484,10 +3863,11 @@
                 <p>Fired when a bookmark or folder changes.  <b>Note:</b> Currently, only title and url changes trigger this.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>id</var>
               <em>
@@ -3540,14 +3920,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>changeInfo</var>
               <em>
@@ -3647,6 +4037,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3707,6 +4107,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3717,15 +4127,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -3742,10 +4162,11 @@
                 <p>Fired when the children of a folder have changed their order due to the order being sorted in the UI.  This is not called as a result of a move().</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>id</var>
               <em>
@@ -3798,14 +4219,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>reorderInfo</var>
               <em>
@@ -3916,6 +4347,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3926,15 +4367,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -3951,10 +4402,11 @@
                 <p>Fired when a bookmark or folder is created.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>id</var>
               <em>
@@ -4007,14 +4459,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>bookmark</var>
               <em>
@@ -4067,15 +4529,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -4092,14 +4564,15 @@
                 <p>Fired when a bookmark import session is begun.  Expensive observers should ignore handleCreated updates until onImportEnded is fired.  Observers should still handle other notifications immediately.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div style="display: none; ">
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -4116,14 +4589,15 @@
                 <p>Fired when a bookmark import session is ended.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div style="display: none; ">
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -4140,10 +4614,11 @@
                 <p>Fired when a bookmark or folder is moved to a different parent folder.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>id</var>
               <em>
@@ -4196,14 +4671,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>moveInfo</var>
               <em>
@@ -4303,6 +4788,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4363,6 +4858,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4423,6 +4928,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4483,6 +4998,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4493,15 +5018,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -4518,10 +5053,11 @@
                 <p>Fired when a bookmark or folder is removed.  When a folder is removed recursively, a single notification is fired for the folder, and none for its contents.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>id</var>
               <em>
@@ -4574,14 +5110,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>removeInfo</var>
               <em>
@@ -4681,6 +5227,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4741,6 +5297,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4751,15 +5317,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -4872,6 +5448,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4930,6 +5516,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4988,6 +5584,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5046,6 +5652,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5104,6 +5720,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5162,6 +5788,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5220,6 +5856,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5289,6 +5935,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5299,6 +5955,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/browserAction.html b/chrome/common/extensions/docs/browserAction.html
index f8b505f..5ed7b39 100644
--- a/chrome/common/extensions/docs/browserAction.html
+++ b/chrome/common/extensions/docs/browserAction.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -294,7 +304,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-setBadgeBackgroundColor">setBadgeBackgroundColor</a>
@@ -310,7 +320,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onClicked">onClicked</a>
@@ -385,7 +395,7 @@
   "name": "My extension",
   ...
   <b>"browser_action": {
-    "default_icon": "images/icon19.png", <em>// <b>required</b></em>
+    "default_icon": "images/icon19.png", <em>// optional</em>
     "default_title": "Google Mail",      <em>// optional; shown in tooltip</em>
     "default_popup": "popup.html"        <em>// optional</em>
   }</b>,
@@ -395,8 +405,7 @@
 <h2 id="ui">Parts of the UI</h2>
 
 <p>
-A browser action must have an <a href="#icon">icon</a>.
-It can also have
+A browser action can have an <a href="#icon">icon</a>,
 a <a href="#tooltip">tooltip</a>,
 a <a href="#badge">badge</a>,
 and a <a href="#popups">popup</a>.
@@ -540,8 +549,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -671,6 +680,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -729,6 +748,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -739,6 +768,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -905,6 +944,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -963,6 +1012,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -973,6 +1032,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1139,6 +1208,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1197,6 +1276,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1255,6 +1344,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1265,6 +1364,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1431,6 +1540,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1489,6 +1608,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1499,6 +1628,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1665,6 +1804,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1723,6 +1872,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1733,6 +1892,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1789,10 +1958,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onClicked"></a>
@@ -1808,10 +1976,11 @@
                 <p>Fired when a browser action icon is clicked.  This event will not fire if the browser action has a popup.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tab</var>
               <em>
@@ -1864,15 +2033,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/build/build.py b/chrome/common/extensions/docs/build/build.py
index 220924e..336756e 100755
--- a/chrome/common/extensions/docs/build/build.py
+++ b/chrome/common/extensions/docs/build/build.py
@@ -18,6 +18,8 @@
 _script_path = os.path.realpath(__file__)
 _build_dir = os.path.dirname(_script_path)
 _base_dir = os.path.normpath(_build_dir + "/..")
+_webkit_dir = _base_dir + "/../../../../third_party/WebKit"
+_devtools_dir = _webkit_dir + "/Source/WebCore/inspector/front-end"
 _static_dir = _base_dir + "/static"
 _js_dir = _base_dir + "/js"
 _template_dir = _base_dir + "/template"
@@ -25,6 +27,7 @@
 _extension_api_dir = os.path.normpath(_base_dir + "/../api")
 
 _extension_api_json = _extension_api_dir + "/extension_api.json"
+_devtools_api_json = _devtools_dir + "/ExtensionAPISchema.json"
 _api_template_html = _template_dir + "/api_template.html"
 _page_shell_html = _template_dir + "/page_shell.html"
 _generator_html = _build_dir + "/generator.html"
@@ -42,9 +45,9 @@
 from directory import ApiManifest
 from directory import SamplesManifest
 
-def RenderPages(names, test_shell):
+def RenderPages(names, dump_render_tree):
   """
-  Calls test_shell --layout-tests .../generator.html?<names> and writes the
+  Calls DumpRenderTree .../generator.html?<names> and writes the
   results to .../docs/<name>.html
   """
   if not names:
@@ -67,11 +70,11 @@
 
     shutil.copy(_page_shell_html, input_file)
 
-  # Run test_shell and capture result
-  test_shell_timeout = 1000 * 60 * 5  # five minutes
+  # Run DumpRenderTree and capture result
+  dump_render_tree_timeout = 1000 * 60 * 5  # five minutes
   p = Popen(
-      [test_shell, "--layout-tests", "--time-out-ms=%s" % test_shell_timeout,
-          generator_url],
+      [dump_render_tree, "--test-shell",
+       "%s %s" % (generator_url, dump_render_tree_timeout)],
       stdout=PIPE)
 
   # The remaining output will be the content of the generated pages.
@@ -82,21 +85,22 @@
   end = output.rfind(_expected_output_postamble)
 
   if (begin < 0 or end < 0):
-    raise Exception ("test_shell returned invalid output:\n\n" + output)
+    raise Exception("%s returned invalid output:\n\n%s" %
+        (dump_render_tree, output))
 
   begin += len(_expected_output_preamble)
 
   try:
     output_parsed = json.loads(output[begin:end])
   except ValueError, msg:
-   raise Exception("Could not parse test_shell output as JSON. Error: " + msg +
-                   "\n\nOutput was:\n" + output)
+   raise Exception("Could not parse DumpRenderTree output as JSON. Error: " +
+                   msg + "\n\nOutput was:\n" + output)
 
   changed_files = []
   for name in names:
     result = output_parsed[name].encode("utf8") + '\n'
 
-    # Remove CRs that are appearing from captured test_shell output.
+    # Remove CRs that are appearing from captured DumpRenderTree output.
     result = result.replace('\r', '')
 
     # Remove page_shell
@@ -111,8 +115,8 @@
   return changed_files
 
 
-def FindTestShell():
-  # This is hacky. It is used to guess the location of the test_shell
+def FindDumpRenderTree():
+  # This is hacky. It is used to guess the location of the DumpRenderTree
   chrome_dir = os.path.normpath(_base_dir + "/../../../")
   src_dir = os.path.normpath(chrome_dir + "/../")
 
@@ -120,34 +124,36 @@
 
   if (sys.platform in ('cygwin', 'win32')):
     home_dir = os.path.normpath(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH"))
-    search_locations.append(chrome_dir + "/Release/test_shell.exe")
-    search_locations.append(chrome_dir + "/Debug/test_shell.exe")
-    search_locations.append(home_dir + "/bin/test_shell/" +
-                            "test_shell.exe")
+    search_locations.append(chrome_dir + "/Release/DumpRenderTree.exe")
+    search_locations.append(chrome_dir + "/Debug/DumpRenderTree.exe")
+    search_locations.append(home_dir + "/bin/DumpRenderTree/"
+                            "DumpRenderTree.exe")
 
   if (sys.platform in ('linux', 'linux2')):
-    search_locations.append(src_dir + "/sconsbuild/Release/test_shell")
-    search_locations.append(src_dir + "/out/Release/test_shell")
-    search_locations.append(src_dir + "/sconsbuild/Debug/test_shell")
-    search_locations.append(src_dir + "/out/Debug/test_shell")
-    search_locations.append(os.getenv("HOME") + "/bin/test_shell/test_shell")
+    search_locations.append(src_dir + "/sconsbuild/Release/DumpRenderTree")
+    search_locations.append(src_dir + "/out/Release/DumpRenderTree")
+    search_locations.append(src_dir + "/sconsbuild/Debug/DumpRenderTree")
+    search_locations.append(src_dir + "/out/Debug/DumpRenderTree")
+    search_locations.append(os.getenv("HOME") + "/bin/DumpRenderTree/"
+                            "DumpRenderTree")
 
   if (sys.platform == 'darwin'):
     search_locations.append(src_dir +
-        "/xcodebuild/Release/TestShell.app/Contents/MacOS/TestShell")
+        "/xcodebuild/Release/DumpRenderTree.app/Contents/MacOS/DumpRenderTree")
     search_locations.append(src_dir +
-        "/xcodebuild/Debug/TestShell.app/Contents/MacOS/TestShell")
-    search_locations.append(os.getenv("HOME") + "/bin/test_shell/" +
-                            "TestShell.app/Contents/MacOS/TestShell")
+        "/xcodebuild/Debug/DumpRenderTree.app/Contents/MacOS/DumpRenderTree")
+    search_locations.append(os.getenv("HOME") + "/bin/DumpRenderTree/" +
+                            "DumpRenderTree.app/Contents/MacOS/DumpRenderTree")
 
   for loc in search_locations:
     if os.path.isfile(loc):
       return loc
 
-  raise Exception("Could not find test_shell executable\n" +
-                  "**test_shell may need to be built**\n" +
-                  "Searched: \n" + "\n".join(search_locations) + "\n" +
-                  "To specify a path to test_shell use --test-shell-path")
+  raise Exception("Could not find DumpRenderTree executable\n"
+                  "**DumpRenderTree may need to be built**\n"
+                  "Searched: \n" + "\n".join(search_locations) + "\n"
+                  "To specify a path to DumpRenderTree use "
+                  "--dump-render-tree-path")
 
 def GetStaticFileNames():
   static_files = os.listdir(_static_dir)
@@ -162,29 +168,34 @@
              "build.sh script instead, which uses depot_tools python.")
 
   parser = OptionParser()
-  parser.add_option("--test-shell-path", dest="test_shell_path",
+  parser.add_option("--dump-render-tree-path", dest="dump_render_tree_path",
                     metavar="PATH",
-                    help="path to test_shell executable")
+                    help="path to DumpRenderTree executable")
   parser.add_option("--page-name", dest="page_name", metavar="PAGE",
                     help="only generate docs for PAGE.html")
   parser.add_option("--nozip", dest="zips", action="store_false",
                     help="do not generate zip files for samples",
                     default=True)
-  (options, args) = parser.parse_args()
+  options, args = parser.parse_args()
 
-  if (options.test_shell_path and os.path.isfile(options.test_shell_path)):
-    test_shell = options.test_shell_path
+  if (options.dump_render_tree_path and
+      os.path.isfile(options.dump_render_tree_path)):
+    dump_render_tree = options.dump_render_tree_path
   else:
-    test_shell = FindTestShell()
+    dump_render_tree = FindDumpRenderTree()
 
   # Load the manifest of existing API Methods
   api_manifest = ApiManifest(_extension_api_json)
 
+  # DevTools API is maintained separately, in WebCore land
+  devtools_api_manifest = ApiManifest(_devtools_api_json)
+
   # Read static file names
   static_names = GetStaticFileNames()
 
   # Read module names
-  module_names = api_manifest.getModuleNames()
+  module_names = (api_manifest.getModuleNames() |
+      devtools_api_manifest.getModuleNames())
 
   # All pages to generate
   page_names = static_names | module_names
@@ -208,7 +219,7 @@
   else:
     modified_zips = []
 
-  modified_files = RenderPages(page_names, test_shell)
+  modified_files = RenderPages(page_names, dump_render_tree)
   modified_files.extend(modified_zips)
 
   if len(modified_files) == 0:
diff --git a/chrome/common/extensions/docs/build/build.sh b/chrome/common/extensions/docs/build/build.sh
index 2082f66..eec460e 100755
--- a/chrome/common/extensions/docs/build/build.sh
+++ b/chrome/common/extensions/docs/build/build.sh
@@ -27,7 +27,7 @@
   # The output from build.py doesn't seem seem to print to the console until
   # it's finished, so print a message so people don't think it's hung.
   echo "Running - this can take about a minute"
-  echo "(it goes faster if you have a Release build of test_shell)"
+  echo "(it goes faster if you have a Release build of DumpRenderTree)"
 
   $PYTHON_PATH $BUILD_DIR/build.py $*
 else
diff --git a/chrome/common/extensions/docs/build/directory.py b/chrome/common/extensions/docs/build/directory.py
index 04c748f..a58ea87 100644
--- a/chrome/common/extensions/docs/build/directory.py
+++ b/chrome/common/extensions/docs/build/directory.py
@@ -631,7 +631,10 @@
 
     zip_filename = self._get_zip_filename()
     zip_path = os.path.join(sample_parentpath, zip_filename)
-    zip_manifest_path = os.path.join(sample_dirname, 'manifest.json')
+    # we pass zip_manifest_path to zipfile.getinfo(), which chokes on
+    # backslashes, so don't rely on os.path.join, use forward slash on
+    # all platforms.
+    zip_manifest_path = sample_dirname + '/manifest.json'
 
     zipfile.ZipFile.debug = 3
 
diff --git a/chrome/common/extensions/docs/content_scripts.html b/chrome/common/extensions/docs/content_scripts.html
index e64f704..e044dca 100644
--- a/chrome/common/extensions/docs/content_scripts.html
+++ b/chrome/common/extensions/docs/content_scripts.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -316,7 +326,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -324,7 +334,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -820,8 +830,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -896,10 +906,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -917,14 +926,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/contextMenus.html b/chrome/common/extensions/docs/contextMenus.html
index 981c17d..f76f8c3 100644
--- a/chrome/common/extensions/docs/contextMenus.html
+++ b/chrome/common/extensions/docs/contextMenus.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -274,7 +284,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-create">create</a>
@@ -288,7 +298,7 @@
                     </ol>
                   </li>
                   <li style="display: none; ">
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -392,8 +402,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -513,6 +523,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -571,6 +591,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -629,6 +659,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -698,6 +738,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -756,6 +806,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div>
@@ -813,6 +873,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -871,6 +941,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -935,6 +1015,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1004,6 +1094,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1073,6 +1173,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1083,6 +1193,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1141,6 +1261,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1205,6 +1335,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1316,6 +1456,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1374,6 +1524,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1493,6 +1653,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1614,6 +1784,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1719,6 +1899,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1779,6 +1969,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1839,6 +2039,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1910,6 +2120,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1970,6 +2190,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2028,6 +2258,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2099,6 +2339,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2170,6 +2420,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2180,6 +2440,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2238,6 +2508,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2294,10 +2574,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup" style="display: none; ">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -2315,14 +2594,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -2435,6 +2715,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2493,6 +2783,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2551,6 +2851,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2609,6 +2919,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2667,6 +2987,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2725,6 +3055,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2783,6 +3123,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2841,6 +3191,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2899,6 +3259,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2909,6 +3279,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/cookies.html b/chrome/common/extensions/docs/cookies.html
index f45e8ef..247b976 100644
--- a/chrome/common/extensions/docs/cookies.html
+++ b/chrome/common/extensions/docs/cookies.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -274,7 +284,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-get">get</a>
@@ -290,7 +300,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onChanged">onChanged</a>
@@ -380,8 +390,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -499,6 +509,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -557,6 +577,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -615,6 +645,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -625,6 +665,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -685,6 +735,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -771,6 +831,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -905,6 +975,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -963,6 +1043,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1021,6 +1111,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1079,6 +1179,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1137,6 +1247,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1195,6 +1315,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1253,6 +1383,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1263,6 +1403,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1323,6 +1473,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1420,6 +1580,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1510,6 +1680,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1607,6 +1787,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1740,6 +1930,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1798,6 +1998,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1856,6 +2066,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1866,6 +2086,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2030,6 +2260,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2088,6 +2328,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2146,6 +2396,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2204,6 +2464,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2262,6 +2532,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2320,6 +2600,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2378,6 +2668,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2436,6 +2736,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2494,6 +2804,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2504,6 +2824,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2560,10 +2890,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onChanged"></a>
@@ -2579,10 +2908,11 @@
                 <p>Fired when a cookie is set or removed.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>changeInfo</var>
               <em>
@@ -2680,6 +3010,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2738,6 +3078,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2748,15 +3098,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -2869,6 +3229,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2927,6 +3297,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2985,6 +3365,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3043,6 +3433,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3101,6 +3501,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3159,6 +3569,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3217,6 +3637,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3275,6 +3705,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3333,6 +3773,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3391,6 +3841,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3401,6 +3861,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3508,6 +3978,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3577,6 +4057,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3587,6 +4077,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/crx.html b/chrome/common/extensions/docs/crx.html
index 9a72d60..dafb0eb 100644
--- a/chrome/common/extensions/docs/crx.html
+++ b/chrome/common/extensions/docs/crx.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -290,7 +300,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -298,7 +308,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -497,8 +507,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -573,10 +583,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -594,14 +603,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/css/ApiRefStyles.css b/chrome/common/extensions/docs/css/ApiRefStyles.css
index 5759b38..3a7040f 100644
--- a/chrome/common/extensions/docs/css/ApiRefStyles.css
+++ b/chrome/common/extensions/docs/css/ApiRefStyles.css
@@ -135,16 +135,6 @@
   font-size:110%
 }
 
-#gc-pagecontent h1 {
-  font-size:130%;
-  font-weight:bold;
-  margin:2em 0 0 -10px;
-  padding:1px 3px;
-  position:relative;
-  border-top:1px solid #36C;
-  background-color:#e5ecf9
-}
-
 .labs #gc-pagecontent h1 {
   background-color:#dcf6db;
   border-top:1px solid #090
@@ -155,39 +145,6 @@
   border-top:1px solid #333
 }
 
-#gc-pagecontent h2 {
-  font-size:130%;
-  font-weight:bold;
-  margin:1.5em 0 0 0
-}
-
-#gc-pagecontent h3 {
-  font-size:110%;
-  margin:.7em 0 0 0;
-  position:relative;
-  top:.4em
-}
-
-#gc-pagecontent h4 {
-  font-size:100%;
-  font-weight:bold;
-  margin:.6em 0 0 0;
-  position:relative;
-  top:.4em;
-  z-index:5
-}
-
-#gc-pagecontent h5 {
-  font-size:100%;
-  font-weight:normal;
-  font-style:italic;
-  text-decoration:underline;
-  margin:.4em 0 0 0;
-  position:relative;
-  top:.4em;
-  z-index:5
-}
-
 /* This next set of rules for headings comes from the Codesite "semantic_headers.css" file. */
 
 #gc-pagecontent h1 {
@@ -257,6 +214,11 @@
   background:none
 }
 
+#gc-pagecontent .apiItem h3 {
+  margin-top: 1em;
+  font-size:110%;
+}
+
 ol,ul {
   padding:0;
   margin:.5em 0 0 15px;
@@ -1282,7 +1244,8 @@
 .apiGroup div.summary {
   border: 1px solid rgb(147, 180, 217);
   font-family: "Courier New", courier, monospace;
-  padding: 0.5em;
+  padding: 0.5em 0.5em 0.5em 2em;
+  text-indent: -1.5em;
   background-color: rgb(202, 222, 244);
   margin-top: 1em;
 }
@@ -1317,6 +1280,14 @@
 .apiItem {
 }
 
+.apiGroup .apiItem {
+  margin-bottom: 2em;
+}
+
+.apiItem .apiItem {
+  margin-bottom: 0px;
+}
+
 div.note {
   background-color: rgb(202, 222, 244);
   border: 1px solid rgb(147, 180, 217);
@@ -1376,4 +1347,3 @@
   margin: 1.3em 1em 0 0;
   padding: 0;
 }
-
diff --git a/chrome/common/extensions/docs/devguide.html b/chrome/common/extensions/docs/devguide.html
index 8e489a6..dd69d13 100644
--- a/chrome/common/extensions/docs/devguide.html
+++ b/chrome/common/extensions/docs/devguide.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -466,8 +476,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -542,10 +552,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -563,14 +572,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/docs.html b/chrome/common/extensions/docs/docs.html
index baab851..81fce56 100644
--- a/chrome/common/extensions/docs/docs.html
+++ b/chrome/common/extensions/docs/docs.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -469,8 +479,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -545,10 +555,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -566,14 +575,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/events.html b/chrome/common/extensions/docs/events.html
index 3136703..583250e 100644
--- a/chrome/common/extensions/docs/events.html
+++ b/chrome/common/extensions/docs/events.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -374,8 +384,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -450,10 +460,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -471,14 +480,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip b/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip
index 02d772f..0d61e73 100644
--- a/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip
+++ b/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html b/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html
index 00919c2..377b74a 100644
--- a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html
+++ b/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html
@@ -1,6 +1,6 @@
 <html>
 <head>
-<link type="text/css" href="http://jqueryui.com/themes/base/ui.all.css" rel="stylesheet">
+<link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/base/jquery-ui.css" rel="stylesheet">
 <style>
 div, td, th { color: black; }
 </style>
@@ -48,7 +48,7 @@
       });
       var span = $('<span>');
       var options = bookmarkNode.children ?
-        $('<span>[<a href="#" id='addlink'>Add</a>]</span>') :
+        $('<span>[<a href="#" id="addlink">Add</a>]</span>') :
         $('<span>[<a id="editlink" href="#">Edit</a> <a id="deletelink" ' +
           'href="#">Delete</a>]</span>');
       var edit = bookmarkNode.children ? $('<table><tr><td>Name</td><td>' +
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip b/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip
index 5c942c4..af4689f 100644
--- a/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip
+++ b/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/cookies.zip b/chrome/common/extensions/docs/examples/api/cookies.zip
index 30bf11a..561ac09 100644
--- a/chrome/common/extensions/docs/examples/api/cookies.zip
+++ b/chrome/common/extensions/docs/examples/api/cookies.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple.zip b/chrome/common/extensions/docs/examples/apps/background-simple.zip
new file mode 100644
index 0000000..6886e53
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/apps/background-simple.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/README b/chrome/common/extensions/docs/examples/apps/background-simple/README
new file mode 100644
index 0000000..dc74c5a
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/apps/background-simple/README
@@ -0,0 +1,19 @@
+This example demonstrates background window functionality in a hosted app.
+To run the app, you first need to edit it and install it:
+
+1. Put index.html and background.html in a directory where the HTTP server
+   can find them.
+
+2. Edit manifest.json. Search for SOME_, replacing the text with URLs
+   pointing to the launch page (index.html) and to the directory where
+   index.html and background.html live.
+
+3. Install the app from manifest.json. You can use the Load unpacked extension
+   button on the chrome://extensions page.
+
+Once the app is installed, you can launch it by clicking its icon on the
+New Tab page.
+
+For more information, see the documentation:
+
+   http://code.google.com/chrome/apps/docs/developers_guide.html
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/background.html b/chrome/common/extensions/docs/examples/apps/background-simple/background.html
new file mode 100644
index 0000000..12d906e
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/apps/background-simple/background.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!--
+ * 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.
+-->
+<html>
+  <script>
+    var notification = webkitNotifications.createNotification("",
+        "Simple Background App",
+        "A background window has been created");
+    notification.show();
+  </script>
+</html>
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/index.html b/chrome/common/extensions/docs/examples/apps/background-simple/index.html
new file mode 100644
index 0000000..e5da99b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/apps/background-simple/index.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+ * 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.
+-->
+<html>
+  <head>
+    <title> Simple Background App </title>
+    <style>
+      .hidden { display: none; }
+      #unsupported { color: #d00; }
+    </style>
+  </head>
+  <body>
+    <h1> Simple Background App </h1>
+    <p id="supported" class="hidden">
+      <button onclick="openBackgroundWindow()">Open background window</button>
+      <button onclick="closeBackgroundWindow()">Close background window</button>
+    </p>
+    <p id="unsupported" class="hidden">
+      You are not using Chrome or have not installed the application for this
+      page.
+    </p>
+    <script>
+      // Check for support
+      if (window.chrome && window.chrome.app && window.chrome.app.isInstalled) {
+        document.getElementById('supported').className = '';
+      } else {
+        document.getElementById('unsupported').className = '';
+      }
+      var bgWinUrl = "background.html#yay";
+      var bgWinName = "bgNotifier";
+
+      function openBackgroundWindow() {
+        window.open(bgWinUrl, bgWinName, "background");
+      }
+      function closeBackgroundWindow() {
+        var w = window.open(bgWinUrl, bgWinName, "background");
+        w.close();
+      }
+    </script>
+    <p>
+      This app displays a notification
+      whenever its background window is created.
+      Background windows and this app are described in the
+      <a href="http://code.google.com/chrome/apps/docs/developers_guide.html">apps documentation</a>.
+    </p>
+    <p>
+      The generic source code is available for
+      <a href="http://code.google.com/chrome/extensions/trunk/examples/apps/background-simple.zip">download</a>.
+      The
+      <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/apps/background-simple/README?content-type=text/plain">README</a>
+      tells you how to modify the code.
+    </p>
+    <p>
+      If you just want to run a version of this app that's already on the web,
+      here's how:
+    </p>
+    <ol>
+      <li>
+        <a href="http://background-simple.appspot.com/app.crx">Install the app</a>
+        from background-simple.appspot.com.
+      </li>
+      <li>
+        Launch Simple Background App from the New Tab page.
+      </li>
+    </ol>
+  </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/manifest.json b/chrome/common/extensions/docs/examples/apps/background-simple/manifest.json
new file mode 100644
index 0000000..db35da0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/apps/background-simple/manifest.json
@@ -0,0 +1,11 @@
+{

+  "name": "Simple Background App",

+  "version": "0.1",

+  "app": {

+    "urls": [ "http://SOME_SITE_WITHOUT_PORT_NUMBERS/SOME_PATH/" ],

+    "launch": {

+      "web_url": "http://SOME_SITE/SOME_PATH/index.html"

+    }

+  },

+  "permissions": ["background", "notifications"]

+}

diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark.zip b/chrome/common/extensions/docs/examples/extensions/benchmark.zip
index 3d799d2..3370dc1 100644
--- a/chrome/common/extensions/docs/examples/extensions/benchmark.zip
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar.zip b/chrome/common/extensions/docs/examples/extensions/calendar.zip
index 4ce9b2f..addfe53 100644
--- a/chrome/common/extensions/docs/examples/extensions/calendar.zip
+++ b/chrome/common/extensions/docs/examples/extensions/calendar.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/fx.zip b/chrome/common/extensions/docs/examples/extensions/fx.zip
index 027e286..f2c66fa 100644
--- a/chrome/common/extensions/docs/examples/extensions/fx.zip
+++ b/chrome/common/extensions/docs/examples/extensions/fx.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo.zip b/chrome/common/extensions/docs/examples/extensions/imageinfo.zip
index dbce95b..1629fef 100644
--- a/chrome/common/extensions/docs/examples/extensions/imageinfo.zip
+++ b/chrome/common/extensions/docs/examples/extensions/imageinfo.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy.zip b/chrome/common/extensions/docs/examples/extensions/mappy.zip
index 79245b1..e5c9f3b 100644
--- a/chrome/common/extensions/docs/examples/extensions/mappy.zip
+++ b/chrome/common/extensions/docs/examples/extensions/mappy.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/getstarted.zip b/chrome/common/extensions/docs/examples/tutorials/getstarted.zip
index 268cc5d..54083ae 100644
--- a/chrome/common/extensions/docs/examples/tutorials/getstarted.zip
+++ b/chrome/common/extensions/docs/examples/tutorials/getstarted.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/getstarted/getstarted.zip b/chrome/common/extensions/docs/examples/tutorials/getstarted/getstarted.zip
deleted file mode 100644
index 37deb7f..0000000
--- a/chrome/common/extensions/docs/examples/tutorials/getstarted/getstarted.zip
+++ /dev/null
Binary files differ
diff --git a/chrome/common/extensions/docs/experimental.clipboard.html b/chrome/common/extensions/docs/experimental.clipboard.html
index 24287e0..c2bc246 100644
--- a/chrome/common/extensions/docs/experimental.clipboard.html
+++ b/chrome/common/extensions/docs/experimental.clipboard.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-executeCopy">executeCopy</a>
@@ -279,7 +289,7 @@
                     </ol>
                   </li>
                   <li style="display: none; ">
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -345,8 +355,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -421,6 +431,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -481,6 +501,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -603,6 +633,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -663,6 +703,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -785,6 +835,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -845,6 +905,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -901,10 +971,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup" style="display: none; ">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -922,14 +991,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.contextMenus.html b/chrome/common/extensions/docs/experimental.contextMenus.html
index aa7a362..bfee164 100644
--- a/chrome/common/extensions/docs/experimental.contextMenus.html
+++ b/chrome/common/extensions/docs/experimental.contextMenus.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -339,8 +349,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -415,10 +425,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -436,14 +445,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.cookies.html b/chrome/common/extensions/docs/experimental.cookies.html
index 5fdcdcc..7144325 100644
--- a/chrome/common/extensions/docs/experimental.cookies.html
+++ b/chrome/common/extensions/docs/experimental.cookies.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -339,8 +349,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -415,10 +425,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -436,14 +445,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.history.html b/chrome/common/extensions/docs/experimental.history.html
index 0e45ec7..aa36096 100644
--- a/chrome/common/extensions/docs/experimental.history.html
+++ b/chrome/common/extensions/docs/experimental.history.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -339,8 +349,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -415,10 +425,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -436,14 +445,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html
index 1c9ebe1..80a6919 100644
--- a/chrome/common/extensions/docs/experimental.html
+++ b/chrome/common/extensions/docs/experimental.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -316,6 +326,7 @@
   <a href="experimental.processes.html">experimental.processes</a></li><li>
   <a href="experimental.proxy.html">experimental.proxy</a></li><li>
   <a href="experimental.sidebar.html">experimental.sidebar</a></li><li>
+  <a href="experimental.tts.html">experimental.tts</a></li><li>
   <a href="experimental.webNavigation.html">experimental.webNavigation</a></li><li>
   <a href="experimental.webRequest.html">experimental.webRequest</a></li>
 </ul>
@@ -406,8 +417,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -482,10 +493,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -503,14 +513,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.idle.html b/chrome/common/extensions/docs/experimental.idle.html
index 6d1ae19..549094c 100644
--- a/chrome/common/extensions/docs/experimental.idle.html
+++ b/chrome/common/extensions/docs/experimental.idle.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -339,8 +349,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -415,10 +425,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -436,14 +445,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.infobars.html b/chrome/common/extensions/docs/experimental.infobars.html
index f542b7a..be9ecd2 100644
--- a/chrome/common/extensions/docs/experimental.infobars.html
+++ b/chrome/common/extensions/docs/experimental.infobars.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-show">show</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li style="display: none; ">
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -375,8 +385,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -496,6 +506,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -554,6 +574,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -564,6 +594,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -624,6 +664,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -710,6 +760,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -735,10 +795,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup" style="display: none; ">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -756,14 +815,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.processes.html b/chrome/common/extensions/docs/experimental.processes.html
index f2a289e..6fa41b0 100644
--- a/chrome/common/extensions/docs/experimental.processes.html
+++ b/chrome/common/extensions/docs/experimental.processes.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-getProcessIdForTab">getProcessIdForTab</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onUpdated">onUpdated</a>
@@ -340,8 +350,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -416,6 +426,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -476,6 +496,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -562,6 +592,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -587,10 +627,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onUpdated"></a>
@@ -606,10 +645,11 @@
                 <p>Fires each time the Task Manager updates its process statistics, providing the dictionary of updated Process objects, indexed by process ID.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>processes</var>
               <em>
@@ -662,15 +702,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -783,6 +833,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -841,6 +901,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -899,6 +969,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -957,6 +1037,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1015,6 +1105,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1073,6 +1173,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1083,6 +1193,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/experimental.proxy.html b/chrome/common/extensions/docs/experimental.proxy.html
index 07ba013..1b1a16c 100644
--- a/chrome/common/extensions/docs/experimental.proxy.html
+++ b/chrome/common/extensions/docs/experimental.proxy.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,15 +277,19 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
+                        <a href="#method-getCurrentProxySettings">getCurrentProxySettings</a>
+                      </li><li>
+                        <a href="#method-removeCustomProxySettings">removeCustomProxySettings</a>
+                      </li><li>
                         <a href="#method-useCustomProxySettings">useCustomProxySettings</a>
                       </li>
                     </ol>
                   </li>
                   <li style="display: none; ">
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -334,19 +348,414 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
             <div class="apiItem">
+              <a name="method-getCurrentProxySettings"></a> <!-- method-anchor -->
+              <h4>getCurrentProxySettings</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>chrome.experimental.proxy.getCurrentProxySettings</span>(<span class="null"><span style="display: none; ">, </span><span>boolean</span>
+                      <var><span>incognito</span></var></span><span class="null"><span>, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Returns the currently effective proxy settings. These can originate from default values, command line options, the extension settings API, policies and possibly other sources in the future.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>incognito</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>See incognito parameter of useCustomProxySettings.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p style="display: none; ">
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>ProxyConfig config</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>config</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.proxy.html#type-ProxyConfig">ProxyConfig</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Configuration, not necessarily a literal copy of the configuration passed to useCustomProxySettings.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-removeCustomProxySettings"></a> <!-- method-anchor -->
+              <h4>removeCustomProxySettings</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>chrome.experimental.proxy.removeCustomProxySettings</span>(<span class="optional"><span style="display: none; ">, </span><span>boolean</span>
+                      <var><span>incognito</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Remove a custom proxy set by the current extension. This is the inverse of useCustomProxySettings.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>incognito</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>See incognito parameter of useCustomProxySettings.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
               <a name="method-useCustomProxySettings"></a> <!-- method-anchor -->
               <h4>useCustomProxySettings</h4>
 
               <div class="summary"><span style="display: none; ">void</span>
                   <!-- Note: intentionally longer 80 columns -->
                   <span>chrome.experimental.proxy.useCustomProxySettings</span>(<span class="null"><span style="display: none; ">, </span><span>ProxyConfig</span>
-                      <var><span>config</span></var></span>)</div>
+                      <var><span>config</span></var></span><span class="optional"><span>, </span><span>boolean</span>
+                      <var><span>incognito</span></var></span>)</div>
 
               <div class="description">
                 <p class="todo" style="display: none; ">Undocumented.</p>
@@ -409,6 +818,84 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>incognito</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>If true, the proxy settings apply only to incognito windows. Otherwise they apply to regular windows (and incognito windows if no specific settings are provided for incognito windows)</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -465,10 +952,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup" style="display: none; ">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -486,14 +972,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -574,7 +1061,7 @@
                           array of <span><span></span></span>
                         </span>
                         <span>string</span>
-                        <span>["http", "socks", "socks4", "socks5"]</span>
+                        <span>["http", "https", "socks", "socks4", "socks5"]</span>
                       </span>
                     </span>
                   )
@@ -606,6 +1093,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -664,6 +1161,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -722,6 +1229,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -732,6 +1249,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -773,7 +1300,7 @@
           <dd class="todo" style="display: none; ">
             Undocumented.
           </dd>
-          <dd>An object encapsulating the set of proxy rules for all protocols.</dd>
+          <dd>An object encapsulating the set of proxy rules for all protocols. Use either 'singleProxy' or (a subset of) 'proxyForHttp', 'proxyForHttps', 'proxyForFtp' and 'socksProxy'.</dd>
           <dd style="display: none; ">
             This parameter was added in version
             <b><span></span></b>.
@@ -839,6 +1366,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -897,6 +1434,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -955,6 +1502,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1013,6 +1570,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1071,6 +1638,95 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>bypassList</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span>
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span></span>
+                        </span>
+                        <span style="display: none; ">paramType</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>List of servers to connect to without a proxy server.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1081,6 +1737,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1188,6 +1854,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1198,6 +1874,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1284,7 +1970,7 @@
           <dd class="todo" style="display: none; ">
             Undocumented.
           </dd>
-          <dd>The proxy rules describing this configuration.</dd>
+          <dd>The proxy rules describing this configuration. Use this for 'fixed_servers' mode.</dd>
           <dd style="display: none; ">
             This parameter was added in version
             <b><span></span></b>.
@@ -1305,6 +1991,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1342,7 +2038,7 @@
           <dd class="todo" style="display: none; ">
             Undocumented.
           </dd>
-          <dd>The proxy auto-config (PAC) script for this configuration.</dd>
+          <dd>The proxy auto-config (PAC) script for this configuration. Use this for 'pac_script' mode.</dd>
           <dd style="display: none; ">
             This parameter was added in version
             <b><span></span></b>.
@@ -1363,6 +2059,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1421,6 +2127,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1431,6 +2147,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/experimental.sidebar.html b/chrome/common/extensions/docs/experimental.sidebar.html
index 148de03..aa6f2ee 100644
--- a/chrome/common/extensions/docs/experimental.sidebar.html
+++ b/chrome/common/extensions/docs/experimental.sidebar.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-collapse">collapse</a>
@@ -291,7 +301,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onStateChanged">onStateChanged</a>
@@ -344,8 +354,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -464,6 +474,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -474,6 +494,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -640,6 +670,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -650,6 +690,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -817,6 +867,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -827,6 +887,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -887,6 +957,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -973,6 +1053,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1108,6 +1198,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1118,6 +1218,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1180,7 +1290,7 @@
 
               <div class="description">
                 <p class="todo" style="display: none; ">Undocumented.</p>
-                <p>Navigates sidebar for the specified tab to the specified URL.</p>
+                <p>Loads the the specified html file into the sidebar for the specified tab.</p>
 
                 <!-- PARAMETERS -->
                 <h4>Parameters</h4>
@@ -1284,6 +1394,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1293,7 +1413,7 @@
               </div><div>
                 <div>
           <dt>
-            <var>url</var>
+            <var>path</var>
               <em>
 
                 <!-- TYPE -->
@@ -1318,12 +1438,10 @@
 
               </em>
           </dt>
-          <dd class="todo">
+          <dd class="todo" style="display: none; ">
             Undocumented.
           </dd>
-          <dd style="display: none; ">
-            Description of this parameter from the json schema.
-          </dd>
+          <dd>Relative path to the html file in the extension to show in the sidebar.</dd>
           <dd style="display: none; ">
             This parameter was added in version
             <b><span></span></b>.
@@ -1344,6 +1462,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1354,6 +1482,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1520,6 +1658,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1578,6 +1726,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1588,6 +1746,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1754,6 +1922,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1812,6 +1990,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1870,6 +2058,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1880,6 +2078,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2046,6 +2254,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2104,6 +2322,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2114,6 +2342,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2280,6 +2518,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2290,6 +2538,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2346,10 +2604,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onStateChanged"></a>
@@ -2365,10 +2622,11 @@
                 <p>Notifies about sidebar state changes.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -2468,6 +2726,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2528,6 +2796,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2538,15 +2816,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.tts.html b/chrome/common/extensions/docs/experimental.tts.html
new file mode 100644
index 0000000..413fc3d
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.tts.html
@@ -0,0 +1,2313 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+    1) The <head> information in this page is significant, should be uniform
+       across api docs and should be edited only with knowledge of the
+       templating mechanism.
+    3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+       browser, it will be re-generated from the template, json schema and
+       authored overview content.
+    4) The <body>.innerHTML is also generated by an offline step so that this
+       page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+    <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+    </script>
+    <script type="text/javascript" src="js/api_page_generator.js"></script>
+    <script type="text/javascript" src="js/bootstrap.js"></script>
+    <script type="text/javascript" src="js/sidebar.js"></script>
+  <title>chrome.experimental.tts - Google Chrome Extensions - Google Code</title></head>
+  <body>  <div id="gc-container" class="labs">
+      <div id="devModeWarning">
+        You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+      </div>
+      <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+      <!-- In particular, sub-templates that recurse, must be used by allowing
+           jstemplate to make a copy of the template in this section which
+           are not operated on by way of the jsskip="true" -->
+      <div style="display:none">
+
+        <!-- VALUE -->
+        <div id="valueTemplate">
+          <dt>
+            <var>paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd>
+            Description of this parameter from the json schema.
+          </dd>
+          <dd>
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd>
+            <div></div>
+          </dd>
+
+        </div> <!-- /VALUE -->
+
+        <div id="functionParametersTemplate">
+          <h5>Parameters</h5>
+          <dl>
+            <div>
+              <div>
+              </div>
+            </div>
+          </dl>
+        </div>
+      </div> <!-- /SUBTEMPLATES -->
+
+  <a id="top"></a>
+    <div id="skipto">
+      <a href="#gc-pagecontent">Skip to page content</a>
+      <a href="#gc-toc">Skip to main navigation</a>
+    </div>
+    <!-- API HEADER -->
+    <table id="header" width="100%" cellspacing="0" border="0">
+      <tbody><tr>
+        <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+        <td valign="middle" width="100%" style="padding-left:0.6em;">
+          <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+            <div id="gsc-search-box">
+              <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+              <input type="hidden" name="ie" value="UTF-8">
+              <input type="text" name="q" value="" size="55">
+              <input class="gsc-search-button" type="submit" name="sa" value="Search">
+              <br>
+              <span class="greytext">e.g. "page action" or "tabs"</span>
+            </div>
+          </form>
+
+          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+          <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+        </td>
+      </tr>
+    </tbody></table>
+
+    <div id="codesiteContent" class="">
+
+      <a id="gc-topnav-anchor"></a>
+      <div id="gc-topnav">
+        <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+        <ul id="home" class="gc-topnav-tabs">
+          <li id="home_link">
+            <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+          </li>
+          <li id="docs_link">
+            <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+          </li>
+          <li id="faq_link">
+            <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+          </li>
+          <li id="samples_link">
+            <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+          </li>
+          <li id="group_link">
+            <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+          </li>
+        </ul>
+      </div> <!-- end gc-topnav -->
+
+    <div class="g-section g-tpl-170">
+      <!-- SIDENAV -->
+      <div class="g-unit g-first" id="gc-toc">
+        <ul>
+          <li><a href="getstarted.html">Getting Started</a></li>
+          <li><a href="overview.html">Overview</a></li>
+          <li><a href="whats_new.html">What's New?</a></li>
+          <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+            <ul>
+              <li>Browser UI
+                <ul>
+                  <li><a href="browserAction.html">Browser Actions</a></li>
+                  <li><a href="contextMenus.html">Context Menus</a></li>
+                  <li><a href="notifications.html">Desktop Notifications</a></li>
+                  <li><a href="omnibox.html">Omnibox</a></li>
+                  <li><a href="options.html">Options Pages</a></li>
+                  <li><a href="override.html">Override Pages</a></li>
+                  <li><a href="pageAction.html">Page Actions</a></li>
+                </ul>
+              </li>
+              <li>Browser Interaction
+                <ul>
+                  <li><a href="bookmarks.html">Bookmarks</a></li>
+                  <li><a href="cookies.html">Cookies</a></li>
+                  <li><a href="events.html">Events</a></li>
+                  <li><a href="history.html">History</a></li>
+                  <li><a href="management.html">Management</a></li>
+                  <li><a href="tabs.html">Tabs</a></li>
+                  <li><a href="windows.html">Windows</a></li>
+                </ul>
+              </li>
+              <li>Implementation
+                <ul>
+                  <li><a href="a11y.html">Accessibility</a></li>
+                  <li><a href="background_pages.html">Background Pages</a></li>
+                  <li><a href="content_scripts.html">Content Scripts</a></li>
+                  <li><a href="xhr.html">Cross-Origin XHR</a></li>
+                  <li><a href="idle.html">Idle</a></li>
+                  <li><a href="i18n.html">Internationalization</a></li>
+                  <li><a href="messaging.html">Message Passing</a></li>
+                  <li><a href="npapi.html">NPAPI Plugins</a></li>
+                </ul>
+              </li>
+              <li>Finishing
+                <ul>
+                  <li><a href="hosting.html">Hosting</a></li>
+                  <li><a href="external_extensions.html">Other Deployment Options</a></li>
+                </ul>
+              </li>
+            </ul>
+          </li>
+          <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+          <li><h2><a href="tutorials.html">Tutorials</a></h2>
+            <ul>
+              <li><a href="tut_debugging.html">Debugging</a></li>
+              <li><a href="tut_analytics.html">Google Analytics</a></li>
+              <li><a href="tut_oauth.html">OAuth</a></li>
+            </ul>
+          </li>
+          <li><h2>Reference</h2>
+            <ul>
+              <li>Formats
+                <ul>
+                  <li><a href="manifest.html">Manifest Files</a></li>
+                  <li><a href="match_patterns.html">Match Patterns</a></li>
+                </ul>
+              </li>
+              <li><a href="permission_warnings.html">Permission Warnings</a></li>
+              <li><a href="api_index.html">chrome.* APIs</a></li>
+              <li><a href="api_other.html">Other APIs</a></li>
+            </ul>
+          </li>
+          <li><h2><a href="samples.html">Samples</a></h2></li>
+          <div class="line"> </div>
+          <li><h2>More</h2>
+            <ul>
+              <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+              <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+              <li><a href="themes.html">Themes</a></li>
+            </ul>
+          </li>
+        </ul>
+      </div>
+      <script>
+        initToggles();
+      </script>
+
+    <div class="g-unit" id="gc-pagecontent">
+      <div id="pageTitle">
+        <h1 class="page_title">chrome.experimental.tts</h1>
+      </div>
+        <!-- TABLE OF CONTENTS -->
+        <div id="toc">
+          <h2>Contents</h2>
+          <ol>
+            <li>
+              <a href="#overview">Overview</a>
+              <ol>
+                <li style="display: none; ">
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li><li>
+              <a href="#generating_speech">Generating speech</a>
+              <ol>
+                <li style="display: none; ">
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li><li>
+              <a href="#ssml">SSML markup</a>
+              <ol>
+                <li style="display: none; ">
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li><li>
+              <a href="#provider">Implementing a speech provider</a>
+              <ol>
+                <li style="display: none; ">
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li>
+              <li>
+                <a href="#apiReference">API reference: chrome.experimental.tts</a>
+                <ol>
+                  <li style="display: none; ">
+                    <a href="#properties">Properties</a>
+                    <ol>
+                      <li>
+                        <a href="#property-anchor">propertyName</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-methods">Methods</a>
+                    <ol>
+                      <li>
+                        <a href="#method-isSpeaking">isSpeaking</a>
+                      </li><li>
+                        <a href="#method-speak">speak</a>
+                      </li><li style="display: none; ">
+                        <a href="#method-anchor">methodName</a>
+                      </li><li>
+                        <a href="#method-stop">stop</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-events">Events</a>
+                    <ol>
+                      <li>
+                        <a href="#event-onSpeak">onSpeak</a>
+                      </li><li>
+                        <a href="#event-onStop">onStop</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li style="display: none; ">
+                    <a href="#types">Types</a>
+                    <ol>
+                      <li>
+                        <a href="#id-anchor">id</a>
+                      </li>
+                    </ol>
+                  </li>
+                </ol>
+              </li>
+          </ol>
+        </div>
+        <!-- /TABLE OF CONTENTS -->
+
+        <!-- Standard content lead-in for experimental API pages -->
+        <p id="classSummary">
+          For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+        </p>
+
+        <!-- STATIC CONTENT PLACEHOLDER -->
+        <div id="static"><p id="classSummary">
+Use the <code>chrome.experimental.tts</code> module to play synthesized
+text-to-speech (TTS) from your extension or packaged app, or to register
+as a speech provider for other extensions and packaged apps that want to speak.
+</p>
+
+<p class="note"><b>Give us feedback:</b> If you have suggestions,
+especially changes that should be made before stabilizing the first
+version of this API, please send your ideas to the
+<a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">chromium-extensions</a>
+group.</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>To enable this experimental API, visit
+<b>chrome://flags</b> and enable <b>Experimental Extension APIs</b>.
+
+</p><p>Chrome provides native support for speech on Windows (using SAPI
+5), Mac OS X, and Chrome OS, using speech synthesis capabilities
+provided by the operating system. On all platforms, the user can
+install extensions that register themselves as alternative speech
+synthesis providers.</p>
+
+<h2 id="generating_speech">Generating speech</h2>
+
+<p>Call <code>speak()</code> from your extension or
+packaged app to speak. For example:</p>
+
+<pre>chrome.experimental.tts.speak('Hello, world.');</pre>
+
+<p>You can provide options that control various properties of the speech,
+such as its rate, pitch, and more. For example:</p>
+
+<pre>chrome.experimental.tts.speak('Hello, world.', {'rate': 0.8});</pre>
+
+<p>It's also a good idea to specify the locale so that a synthesizer
+supporting that language (and regional dialect, if applicable) is chosen.</p>
+
+<pre>chrome.experimental.tts.speak(
+    'Hello, world.',
+    {
+      'locale': 'en-US',
+      'rate': 0.8
+    });</pre>
+
+<p>Not all speech engines will support all options.</p>
+
+<p>You can also pass a callback function that will be called when the
+speech has finished. For example, suppose we have an image on our page
+displaying a picture of a face with a closed mouth. We could open the mouth
+while speaking, and close it when done.</p>
+
+<pre>faceImage.src = 'open_mouth.png';
+chrome.experimental.tts.speak(
+    'Hello, world.', null, function() {
+      faceImage.src = 'closed_mouth.png';
+    });
+</pre>
+
+<p>To stop speaking immediately, just call <code>stop()</code>. Call
+<code>isSpeaking()</code> to find out if a TTS engine is currently speaking.</p>
+
+<p>You can check to see if an error occurred by checking
+<code>chrome.extension.lastError</code> inside the callback function.</p>
+
+<h2 id="ssml">SSML markup</h2>
+
+<p>Utterances used in this API may include markup using the
+<a href="http://www.w3.org/TR/speech-synthesis">Speech Synthesis Markup
+Language (SSML)</a>. For example:
+
+</p><pre>chrome.experimental.tts.speak('The &lt;emphasis&gt;second&lt;/emphasis&gt; word of this sentence was emphasized.');</pre>
+
+<p>Not all speech engines will support all SSML tags, and some may not support
+SSML at all, but all engines are expected to ignore any SSML they don't
+support and still speak the underlying text.</p>
+
+<h2 id="provider">Implementing a speech provider</h2>
+
+<p>An extension can register itself as a speech provider. By doing so, it
+can intercept some or all calls to functions such as
+<code>speak()</code> and <code>stop()</code> and provide an alternate
+implementation. Extensions are free to use any available web technology
+to provide speech, including streaming audio from a server, HTML5 audio,
+Native Client, or Flash. An extension could even do something different
+with the utterances, like display closed captions in a pop-up window or
+send them as log messages to a remote server.</p>
+
+<p>To provide TTS, an extension must first declare all voices it provides
+in the extension manifest, like this:</p>
+
+<pre>{
+  "name": "My TTS Provider",
+  "version": "1.0",
+  <b>"permissions": ["experimental"]
+  "tts": {
+    "voices": [
+      {
+        "voiceName": "Alice",
+        "locale": "en-US",
+        "gender": "female"
+      },
+      {
+        "voiceName": "Pat",
+        "locale": "en-US"
+      }
+    ]
+  },</b>
+  "background_page": "background.html",
+}</pre>
+
+<p>An extension can specify any number of voices. The three
+parameters—<code>voiceName</code>, <code>locale</code>,
+and <code>gender</code>—are all optional. If they are all unspecified,
+the extension will handle all speech from all clients. If any of them
+are specified, they can be used to filter speech requests. For
+example, if a voice only supports French, it should set the locale to
+'fr' (or something more specific like 'fr-FR') so that only utterances
+in that locale are routed to that extension.</p>
+
+<p>To handle speech calls, the extension should register listeners
+for <code>onSpeak</code> and <code>onStop</code>, like this:</p>
+
+<pre>var speakListener = function(utterance, options, callback) {
+  ...
+  callback();
+};
+var stopListener = function() {
+  ...
+};
+chrome.experimental.tts.onSpeak.addListener(speakListener);
+chrome.experimental.tts.onStop.addListener(stopListener);</pre>
+
+<p class="warning"><b>Important:</b> Don't forget to call the callback
+function from your speak listener!</p>
+
+<p>If an extension does not register listeners for both
+<code>onSpeak</code> and <code>onStop</code>, it will not intercept any
+speech calls, regardless of what is in the manifest.
+
+</p><p>The decision of whether or not to send a given speech request to an
+extension is based solely on whether the extension supports the given voice
+parameters in its manifest and has registered listeners
+for <code>onSpeak</code> and <code>onStop</code>. In other words,
+there's no way for an extension to receive a speech request and
+dynamically decide whether to handle it or not.</p>
+</div>
+
+        <!-- API PAGE -->
+        <div class="apiPage">
+        <a name="apiReference"></a>
+        <h2>API reference: chrome.experimental.tts</h2>
+
+          <!-- PROPERTIES -->
+          <div class="apiGroup" style="display: none; ">
+            <a name="properties"></a>
+            <h3 id="properties">Properties</h3>
+
+            <div>
+              <a></a>
+              <h4>getLastError</h4>
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span>chrome.extension</span><span>lastError</span>
+              </div>
+              <div>
+              </div>
+            </div>
+
+          </div> <!-- /apiGroup -->
+
+          <!-- METHODS -->
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
+            <h3>Methods</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-isSpeaking"></a> <!-- method-anchor -->
+              <h4>isSpeaking</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>chrome.experimental.tts.isSpeaking</span>(<span class="optional"><span style="display: none; ">, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Check if the engine is currently speaking.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p style="display: none; ">
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>boolean speaking</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>speaking</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>True if speaking, false otherwise.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-speak"></a> <!-- method-anchor -->
+              <h4>speak</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>chrome.experimental.tts.speak</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>utterance</span></var></span><span class="optional"><span>, </span><span>object</span>
+                      <var><span>options</span></var></span><span class="optional"><span>, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Speak text using a text-to-speech engine.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>utterance</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The text to speak. May include SSML markup.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>options</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The speech options.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+          <dt>
+            <var>enqueue</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>If true, enqueues this utterance if TTS is already in progress. If false (the default), interrupts any current speech and flushes the speech queue before speaking this new utterance.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>voiceName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The name of the voice to use for synthesis. If empty, uses any available voice.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>locale</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The language and optional region code that specify the language and dialect to be used for synthesis, in the form &lt;language&gt;-&lt;region&gt;. Examples: 'en', 'en-US', 'en-GB', 'zh-CN', etc.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>gender</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span>["male", "female"]</span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Gender of voice for synthesized speech.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>rate</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest, with a default of 0.5.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>pitch</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 0.5.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>volume</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>This function is called when speaking is finished.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p style="display: none; ">
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span></span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div style="display: none; ">
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem" style="display: none; ">
+              <a></a> <!-- method-anchor -->
+              <h4>method name</h4>
+
+              <div class="summary"><span>void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>chrome.module.methodName</span>(<span><span>, </span><span></span>
+                      <var><span></span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo">Undocumented.</p>
+                <p>
+                  A description from the json schema def of the function goes here.
+                </p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p>
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-stop"></a> <!-- method-anchor -->
+              <h4>stop</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>chrome.experimental.tts.stop</span>(<span style="display: none; "><span>, </span><span></span>
+                      <var><span></span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Stop any current speech.</p>
+
+                <!-- PARAMETERS -->
+                <h4 style="display: none; ">Parameters</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>  <!-- /apiGroup -->
+
+          <!-- EVENTS -->
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a name="event-onSpeak"></a>
+              <h4>onSpeak</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">chrome.experimental.tts.</span><span>onSpeak</span><span class="subdued">.addListener</span>(function(<span>string utterance, object options, function callback</span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Called when the user makes a call to tts.speak and the options matches one of the tts_voices from this extension's manifest.</p>
+
+                <!-- PARAMETERS -->
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>utterance</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The text to speak. This may include SSML, so if your engine does not support SSML, you should strip out all XML markup and synthesize only the underlying text content.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div><div>
+                      <div>
+          <dt>
+            <var>options</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The speak options.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+          <dt>
+            <var>voiceName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The name of the voice to use for synthesis.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>locale</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The language and region code that specify the language and dialect to be used for synthesis, in the form <language>-<region>, e.g. en-US, en-GB, fr-CA, zh-CN, etc.</region></language></dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>gender</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span>["male", "female"]</span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Gender of voice for synthesized speech.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>rate</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Speaking speed between 0 and 1 inclusive, with 0 being slowest and 1 being fastest.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>pitch</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Speaking pitch between 0 and 1 inclusive, with 0 being lowest and 1 being highest.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>volume</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div><div>
+                      <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>You must call this function when speaking is finished.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div><div class="apiItem">
+              <a name="event-onStop"></a>
+              <h4>onStop</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">chrome.experimental.tts.</span><span>onStop</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired when a call is made to tts.stop and this extension may be in the middle of speaking. If an extension receives a call to onStop and speech is already stopped, it should do nothing (not raise an error).</p>
+
+                <!-- PARAMETERS -->
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+          <!-- TYPES -->
+          <div class="apiGroup" style="display: none; ">
+            <a name="types"></a>
+            <h3 id="types">Types</h3>
+
+            <!-- iterates over all types -->
+            <div class="apiItem">
+              <a></a>
+              <h4>type name</h4>
+
+              <div>
+              </div>
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+        </div> <!-- /apiPage -->
+      </div> <!-- /gc-pagecontent -->
+    </div> <!-- /g-section -->
+  </div> <!-- /codesiteContent -->
+    <div id="gc-footer" --="">
+      <div class="text">
+  <p>
+  Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+  the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+  Attribution 3.0 License</a>, and code samples are licensed under the
+  <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+  </p>
+  <p>
+  ©2011 Google
+  </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+  // chrome doc tracking
+  try {
+    var engdocs = _gat._getTracker("YT-10763712-2");
+    engdocs._trackPageview();
+  } catch(err) {}
+
+  // code.google.com site-wide tracking
+  try {
+    _uacct="UA-18071-1";
+    _uanchor=1;
+    _uff=0;
+    urchinTracker();
+  }
+  catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+      </div>
+    </div> <!-- /gc-footer -->
+  </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/experimental.webInspector.audits.html b/chrome/common/extensions/docs/experimental.webInspector.audits.html
new file mode 100644
index 0000000..2520d1c
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.webInspector.audits.html
@@ -0,0 +1,3256 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+    1) The <head> information in this page is significant, should be uniform
+       across api docs and should be edited only with knowledge of the
+       templating mechanism.
+    3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+       browser, it will be re-generated from the template, json schema and
+       authored overview content.
+    4) The <body>.innerHTML is also generated by an offline step so that this
+       page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+    <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+    </script>
+    <script type="text/javascript" src="js/api_page_generator.js"></script>
+    <script type="text/javascript" src="js/bootstrap.js"></script>
+    <script type="text/javascript" src="js/sidebar.js"></script>
+  <title>experimental.webInspector.audits - Google Chrome Extensions - Google Code</title></head>
+  <body>  <div id="gc-container" class="labs">
+      <div id="devModeWarning">
+        You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+      </div>
+      <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+      <!-- In particular, sub-templates that recurse, must be used by allowing
+           jstemplate to make a copy of the template in this section which
+           are not operated on by way of the jsskip="true" -->
+      <div style="display:none">
+
+        <!-- VALUE -->
+        <div id="valueTemplate">
+          <dt>
+            <var>paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd>
+            Description of this parameter from the json schema.
+          </dd>
+          <dd>
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd>
+            <div></div>
+          </dd>
+
+        </div> <!-- /VALUE -->
+
+        <div id="functionParametersTemplate">
+          <h5>Parameters</h5>
+          <dl>
+            <div>
+              <div>
+              </div>
+            </div>
+          </dl>
+        </div>
+      </div> <!-- /SUBTEMPLATES -->
+
+  <a id="top"></a>
+    <div id="skipto">
+      <a href="#gc-pagecontent">Skip to page content</a>
+      <a href="#gc-toc">Skip to main navigation</a>
+    </div>
+    <!-- API HEADER -->
+    <table id="header" width="100%" cellspacing="0" border="0">
+      <tbody><tr>
+        <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+        <td valign="middle" width="100%" style="padding-left:0.6em;">
+          <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+            <div id="gsc-search-box">
+              <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+              <input type="hidden" name="ie" value="UTF-8">
+              <input type="text" name="q" value="" size="55">
+              <input class="gsc-search-button" type="submit" name="sa" value="Search">
+              <br>
+              <span class="greytext">e.g. "page action" or "tabs"</span>
+            </div>
+          </form>
+
+          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+          <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+        </td>
+      </tr>
+    </tbody></table>
+
+    <div id="codesiteContent" class="">
+
+      <a id="gc-topnav-anchor"></a>
+      <div id="gc-topnav">
+        <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+        <ul id="home" class="gc-topnav-tabs">
+          <li id="home_link">
+            <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+          </li>
+          <li id="docs_link">
+            <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+          </li>
+          <li id="faq_link">
+            <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+          </li>
+          <li id="samples_link">
+            <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+          </li>
+          <li id="group_link">
+            <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+          </li>
+        </ul>
+      </div> <!-- end gc-topnav -->
+
+    <div class="g-section g-tpl-170">
+      <!-- SIDENAV -->
+      <div class="g-unit g-first" id="gc-toc">
+        <ul>
+          <li><a href="getstarted.html">Getting Started</a></li>
+          <li><a href="overview.html">Overview</a></li>
+          <li><a href="whats_new.html">What's New?</a></li>
+          <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+            <ul>
+              <li>Browser UI
+                <ul>
+                  <li><a href="browserAction.html">Browser Actions</a></li>
+                  <li><a href="contextMenus.html">Context Menus</a></li>
+                  <li><a href="notifications.html">Desktop Notifications</a></li>
+                  <li><a href="omnibox.html">Omnibox</a></li>
+                  <li><a href="options.html">Options Pages</a></li>
+                  <li><a href="override.html">Override Pages</a></li>
+                  <li><a href="pageAction.html">Page Actions</a></li>
+                </ul>
+              </li>
+              <li>Browser Interaction
+                <ul>
+                  <li><a href="bookmarks.html">Bookmarks</a></li>
+                  <li><a href="cookies.html">Cookies</a></li>
+                  <li><a href="events.html">Events</a></li>
+                  <li><a href="history.html">History</a></li>
+                  <li><a href="management.html">Management</a></li>
+                  <li><a href="tabs.html">Tabs</a></li>
+                  <li><a href="windows.html">Windows</a></li>
+                </ul>
+              </li>
+              <li>Implementation
+                <ul>
+                  <li><a href="a11y.html">Accessibility</a></li>
+                  <li><a href="background_pages.html">Background Pages</a></li>
+                  <li><a href="content_scripts.html">Content Scripts</a></li>
+                  <li><a href="xhr.html">Cross-Origin XHR</a></li>
+                  <li><a href="idle.html">Idle</a></li>
+                  <li><a href="i18n.html">Internationalization</a></li>
+                  <li><a href="messaging.html">Message Passing</a></li>
+                  <li><a href="npapi.html">NPAPI Plugins</a></li>
+                </ul>
+              </li>
+              <li>Finishing
+                <ul>
+                  <li><a href="hosting.html">Hosting</a></li>
+                  <li><a href="external_extensions.html">Other Deployment Options</a></li>
+                </ul>
+              </li>
+            </ul>
+          </li>
+          <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+          <li><h2><a href="tutorials.html">Tutorials</a></h2>
+            <ul>
+              <li><a href="tut_debugging.html">Debugging</a></li>
+              <li><a href="tut_analytics.html">Google Analytics</a></li>
+              <li><a href="tut_oauth.html">OAuth</a></li>
+            </ul>
+          </li>
+          <li><h2>Reference</h2>
+            <ul>
+              <li>Formats
+                <ul>
+                  <li><a href="manifest.html">Manifest Files</a></li>
+                  <li><a href="match_patterns.html">Match Patterns</a></li>
+                </ul>
+              </li>
+              <li><a href="permission_warnings.html">Permission Warnings</a></li>
+              <li><a href="api_index.html">chrome.* APIs</a></li>
+              <li><a href="api_other.html">Other APIs</a></li>
+            </ul>
+          </li>
+          <li><h2><a href="samples.html">Samples</a></h2></li>
+          <div class="line"> </div>
+          <li><h2>More</h2>
+            <ul>
+              <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+              <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+              <li><a href="themes.html">Themes</a></li>
+            </ul>
+          </li>
+        </ul>
+      </div>
+      <script>
+        initToggles();
+      </script>
+
+    <div class="g-unit" id="gc-pagecontent">
+      <div id="pageTitle">
+        <h1 class="page_title">experimental.webInspector.audits</h1>
+      </div>
+        <!-- TABLE OF CONTENTS -->
+        <div id="toc">
+          <h2>Contents</h2>
+          <ol>
+            <li style="display: none; ">
+              <a>h2Name</a>
+              <ol>
+                <li>
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li>
+              <li>
+                <a href="#apiReference">API reference: experimental.webInspector.audits</a>
+                <ol>
+                  <li style="display: none; ">
+                    <a href="#properties">Properties</a>
+                    <ol>
+                      <li>
+                        <a href="#property-anchor">propertyName</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-methods">Methods</a>
+                    <ol>
+                      <li>
+                        <a href="#method-addCategory">addCategory</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li style="display: none; ">
+                    <a>Events</a>
+                    <ol>
+                      <li>
+                        <a href="#event-anchor">eventName</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#types">Types</a>
+                    <ol>
+                      <li>
+                        <a href="#type-AuditCategory">AuditCategory</a>
+                      </li><li>
+                        <a href="#type-FormattedValue">FormattedValue</a>
+                      </li><li>
+                        <a href="#type-AuditResults">AuditResults</a>
+                      </li><li>
+                        <a href="#type-AuditResultNode">AuditResultNode</a>
+                      </li><li>
+                        <a href="#type-AuditResultSeverity">AuditResultSeverity</a>
+                      </li>
+                    </ol>
+                  </li>
+                </ol>
+              </li>
+          </ol>
+        </div>
+        <!-- /TABLE OF CONTENTS -->
+
+        <!-- Standard content lead-in for experimental API pages -->
+        <p id="classSummary" style="display: none; ">
+          For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+        </p>
+
+        <!-- STATIC CONTENT PLACEHOLDER -->
+        <div id="static"></div>
+
+        <!-- API PAGE -->
+        <div class="apiPage">
+        <a name="apiReference"></a>
+        <h2>API reference: experimental.webInspector.audits</h2>
+
+          <!-- PROPERTIES -->
+          <div class="apiGroup" style="display: none; ">
+            <a name="properties"></a>
+            <h3 id="properties">Properties</h3>
+
+            <div>
+              <a></a>
+              <h4>getLastError</h4>
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span>chrome.extension</span><span>lastError</span>
+              </div>
+              <div>
+              </div>
+            </div>
+
+          </div> <!-- /apiGroup -->
+
+          <!-- METHODS -->
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
+            <h3>Methods</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-addCategory"></a> <!-- method-anchor -->
+              <h4>addCategory</h4>
+
+              <div class="summary"><span>AuditCategory</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>experimental.webInspector.audits.addCategory</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>displayName</span></var></span><span class="null"><span>, </span><span>number</span>
+                      <var><span>resultCount</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Adds an audit category.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>displayName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A display name for the category</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>resultCount</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The expected number of audit results in the category.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditCategory">AuditCategory</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>  <!-- /apiGroup -->
+
+          <!-- EVENTS -->
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a></a>
+              <h4>event name</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo">Undocumented.</p>
+                <p>
+                  A description from the json schema def of the event goes here.
+                </p>
+
+                <!-- PARAMETERS -->
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+          <!-- TYPES -->
+          <div class="apiGroup">
+            <a name="types"></a>
+            <h3 id="types">Types</h3>
+
+            <!-- iterates over all types -->
+            <div class="apiItem">
+              <a name="type-AuditCategory"></a>
+              <h4>AuditCategory</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A set of audit rules</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div class="apiGroup" style="">
+            <a name="global-AuditCategory-events"></a>
+            <h3>Events of AuditCategory</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a name="event-AuditCategory-onAuditStarted"></a>
+              <h4>onAuditStarted</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">auditCategory.</span><span>onAuditStarted</span><span class="subdued">.addListener</span>(function(<span>AuditResults results</span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired when the audit is started, if the category is enabled -- the extension is expected to begin executing audit rules.</p>
+
+                <!-- PARAMETERS -->
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>results</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditResults">AuditResults</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-FormattedValue"></a>
+              <h4>FormattedValue</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A value returned from one of the formatters (an URL, code snippet etc), to be passed to createResult or addChild</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-AuditResults"></a>
+              <h4>AuditResults</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A collection of audit results for current run of the audit category</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+          <dt>
+            <var>Severity</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditResultSeverity">AuditResultSeverity</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A class that contains possible values for audit result severities.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>text</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The contents of the node.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>children</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span>
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditResultNode">AuditResultNode</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span></span>
+                        </span>
+                        <span style="display: none; ">paramType</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Children of this node.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>expanded</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Whether the node is expanded by default.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div class="apiGroup">
+            <a name="global-AuditResults-methods"></a>
+            <h3>Methods of AuditResults</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-AuditResults-addResult"></a> <!-- method-anchor -->
+              <h4>addResult</h4>
+
+              <div class="summary"><span style="display: none; ">AuditCategory</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>auditResults.addResult</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>displayName</span></var></span><span class="null"><span>, </span><span>string</span>
+                      <var><span>description</span></var></span><span class="null"><span>, </span><span>AuditResultSeverety</span>
+                      <var><span>severity</span></var></span><span class="optional"><span>, </span><span>AuditResultNode</span>
+                      <var><span>details</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p style="display: none; ">Adds an audit category.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>displayName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A concise, high-level description of audit rule result</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>description</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A detailed description of what the displayName means</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>severity</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="">
+                        <a>AuditResultSeverety</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">The expected number of audit results in the category.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>details</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="">
+                        <a href="experimental.webInspector.audits.html#type-AuditResultNode">AuditResultNode</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A subtree that appears under added result that may provide additional details on the violations found</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditCategory">AuditCategory</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-AuditResults-createResult"></a> <!-- method-anchor -->
+              <h4>createResult</h4>
+
+              <div class="summary"><span>AuditResultNode</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>auditResults.createResult</span>(<span class="null"><span style="display: none; ">, </span><span>string or FormattedValue</span>
+                      <var><span>content ...</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Creates a result node that may be user as details parameters to addResult</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>content ...</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string or FormattedValue</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Either string or formatted values returned by one of AuditResult formatters (url, snippet etc)</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditResultNode">AuditResultNode</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-AuditResults-done"></a> <!-- method-anchor -->
+              <h4>done</h4>
+
+              <div class="summary"><span style="display: none; ">AuditCategory</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>auditResults.done</span>(<span class="null" style="display: none; "><span style="display: none; ">, </span><span>string</span>
+                      <var><span>displayName</span></var></span><span class="null" style="display: none; "><span>, </span><span>number</span>
+                      <var><span>resultCount</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Signals the WebInspector Audits panel that the run of this category is over. Normally the run completes automatically when a number of added top-level results is equal to that declared when AuditCategory was created.</p>
+
+                <!-- PARAMETERS -->
+                <h4 style="display: none; ">Parameters</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var>displayName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A display name for the category</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div style="display: none; ">
+                    <div>
+          <dt>
+            <var>resultCount</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>number</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The expected number of audit results in the category.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditCategory">AuditCategory</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-AuditResults-snippet"></a> <!-- method-anchor -->
+              <h4>snippet</h4>
+
+              <div class="summary"><span>FormattedValue</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>auditResults.snippet</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>text</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Render passed text as a code snippet in the Audits panel</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>text</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Snippet text</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-FormattedValue">FormattedValue</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-AuditResults-url"></a> <!-- method-anchor -->
+              <h4>url</h4>
+
+              <div class="summary"><span>FormattedValue</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>auditResults.url</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>href</span></var></span><span class="optional"><span>, </span><span>string</span>
+                      <var><span>displayText</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Render passed value as an URL in the Audits panel</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>href</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An URL that will appear as href value on resulting link</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>displayText</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A text that will appear to user</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-FormattedValue">FormattedValue</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-AuditResultNode"></a>
+              <h4>AuditResultNode</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A node in the audit result trees. Displays some content and optionally has children node</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+          <dt>
+            <var>expanded</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>If set, the subtree will always be expanded</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div class="apiGroup">
+            <a name="global-AuditResultNode-methods"></a>
+            <h3>Methods of AuditResultNode</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-AuditResultNode-addChild"></a> <!-- method-anchor -->
+              <h4>addChild</h4>
+
+              <div class="summary"><span>AuditResultNode</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>auditResultNode.addChild</span>(<span class="null"><span style="display: none; ">, </span><span>string or FormattedValue</span>
+                      <var><span>content ...</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Adds another child node to this node</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>content ...</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string or FormattedValue</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Either string or formatted values returned by one of AuditResult formatters (url, snippet etc)</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.audits.html#type-AuditResultNode">AuditResultNode</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-AuditResultSeverity"></a>
+              <h4>AuditResultSeverity</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+          <dt>
+            <var>Info</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>Warning</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>Severe</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+        </div> <!-- /apiPage -->
+      </div> <!-- /gc-pagecontent -->
+    </div> <!-- /g-section -->
+  </div> <!-- /codesiteContent -->
+    <div id="gc-footer" --="">
+      <div class="text">
+  <p>
+  Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+  the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+  Attribution 3.0 License</a>, and code samples are licensed under the
+  <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+  </p>
+  <p>
+  ©2011 Google
+  </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+  // chrome doc tracking
+  try {
+    var engdocs = _gat._getTracker("YT-10763712-2");
+    engdocs._trackPageview();
+  } catch(err) {}
+
+  // code.google.com site-wide tracking
+  try {
+    _uacct="UA-18071-1";
+    _uanchor=1;
+    _uff=0;
+    urchinTracker();
+  }
+  catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+      </div>
+    </div> <!-- /gc-footer -->
+  </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/experimental.webInspector.inspectedWindow.html b/chrome/common/extensions/docs/experimental.webInspector.inspectedWindow.html
new file mode 100644
index 0000000..b1d645c
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.webInspector.inspectedWindow.html
@@ -0,0 +1,826 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+    1) The <head> information in this page is significant, should be uniform
+       across api docs and should be edited only with knowledge of the
+       templating mechanism.
+    3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+       browser, it will be re-generated from the template, json schema and
+       authored overview content.
+    4) The <body>.innerHTML is also generated by an offline step so that this
+       page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+    <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+    </script>
+    <script type="text/javascript" src="js/api_page_generator.js"></script>
+    <script type="text/javascript" src="js/bootstrap.js"></script>
+    <script type="text/javascript" src="js/sidebar.js"></script>
+  <title>experimental.webInspector.inspectedWindow - Google Chrome Extensions - Google Code</title></head>
+  <body>  <div id="gc-container" class="labs">
+      <div id="devModeWarning">
+        You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+      </div>
+      <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+      <!-- In particular, sub-templates that recurse, must be used by allowing
+           jstemplate to make a copy of the template in this section which
+           are not operated on by way of the jsskip="true" -->
+      <div style="display:none">
+
+        <!-- VALUE -->
+        <div id="valueTemplate">
+          <dt>
+            <var>paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd>
+            Description of this parameter from the json schema.
+          </dd>
+          <dd>
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd>
+            <div></div>
+          </dd>
+
+        </div> <!-- /VALUE -->
+
+        <div id="functionParametersTemplate">
+          <h5>Parameters</h5>
+          <dl>
+            <div>
+              <div>
+              </div>
+            </div>
+          </dl>
+        </div>
+      </div> <!-- /SUBTEMPLATES -->
+
+  <a id="top"></a>
+    <div id="skipto">
+      <a href="#gc-pagecontent">Skip to page content</a>
+      <a href="#gc-toc">Skip to main navigation</a>
+    </div>
+    <!-- API HEADER -->
+    <table id="header" width="100%" cellspacing="0" border="0">
+      <tbody><tr>
+        <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+        <td valign="middle" width="100%" style="padding-left:0.6em;">
+          <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+            <div id="gsc-search-box">
+              <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+              <input type="hidden" name="ie" value="UTF-8">
+              <input type="text" name="q" value="" size="55">
+              <input class="gsc-search-button" type="submit" name="sa" value="Search">
+              <br>
+              <span class="greytext">e.g. "page action" or "tabs"</span>
+            </div>
+          </form>
+
+          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+          <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+        </td>
+      </tr>
+    </tbody></table>
+
+    <div id="codesiteContent" class="">
+
+      <a id="gc-topnav-anchor"></a>
+      <div id="gc-topnav">
+        <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+        <ul id="home" class="gc-topnav-tabs">
+          <li id="home_link">
+            <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+          </li>
+          <li id="docs_link">
+            <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+          </li>
+          <li id="faq_link">
+            <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+          </li>
+          <li id="samples_link">
+            <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+          </li>
+          <li id="group_link">
+            <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+          </li>
+        </ul>
+      </div> <!-- end gc-topnav -->
+
+    <div class="g-section g-tpl-170">
+      <!-- SIDENAV -->
+      <div class="g-unit g-first" id="gc-toc">
+        <ul>
+          <li><a href="getstarted.html">Getting Started</a></li>
+          <li><a href="overview.html">Overview</a></li>
+          <li><a href="whats_new.html">What's New?</a></li>
+          <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+            <ul>
+              <li>Browser UI
+                <ul>
+                  <li><a href="browserAction.html">Browser Actions</a></li>
+                  <li><a href="contextMenus.html">Context Menus</a></li>
+                  <li><a href="notifications.html">Desktop Notifications</a></li>
+                  <li><a href="omnibox.html">Omnibox</a></li>
+                  <li><a href="options.html">Options Pages</a></li>
+                  <li><a href="override.html">Override Pages</a></li>
+                  <li><a href="pageAction.html">Page Actions</a></li>
+                </ul>
+              </li>
+              <li>Browser Interaction
+                <ul>
+                  <li><a href="bookmarks.html">Bookmarks</a></li>
+                  <li><a href="cookies.html">Cookies</a></li>
+                  <li><a href="events.html">Events</a></li>
+                  <li><a href="history.html">History</a></li>
+                  <li><a href="management.html">Management</a></li>
+                  <li><a href="tabs.html">Tabs</a></li>
+                  <li><a href="windows.html">Windows</a></li>
+                </ul>
+              </li>
+              <li>Implementation
+                <ul>
+                  <li><a href="a11y.html">Accessibility</a></li>
+                  <li><a href="background_pages.html">Background Pages</a></li>
+                  <li><a href="content_scripts.html">Content Scripts</a></li>
+                  <li><a href="xhr.html">Cross-Origin XHR</a></li>
+                  <li><a href="idle.html">Idle</a></li>
+                  <li><a href="i18n.html">Internationalization</a></li>
+                  <li><a href="messaging.html">Message Passing</a></li>
+                  <li><a href="npapi.html">NPAPI Plugins</a></li>
+                </ul>
+              </li>
+              <li>Finishing
+                <ul>
+                  <li><a href="hosting.html">Hosting</a></li>
+                  <li><a href="external_extensions.html">Other Deployment Options</a></li>
+                </ul>
+              </li>
+            </ul>
+          </li>
+          <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+          <li><h2><a href="tutorials.html">Tutorials</a></h2>
+            <ul>
+              <li><a href="tut_debugging.html">Debugging</a></li>
+              <li><a href="tut_analytics.html">Google Analytics</a></li>
+              <li><a href="tut_oauth.html">OAuth</a></li>
+            </ul>
+          </li>
+          <li><h2>Reference</h2>
+            <ul>
+              <li>Formats
+                <ul>
+                  <li><a href="manifest.html">Manifest Files</a></li>
+                  <li><a href="match_patterns.html">Match Patterns</a></li>
+                </ul>
+              </li>
+              <li><a href="permission_warnings.html">Permission Warnings</a></li>
+              <li><a href="api_index.html">chrome.* APIs</a></li>
+              <li><a href="api_other.html">Other APIs</a></li>
+            </ul>
+          </li>
+          <li><h2><a href="samples.html">Samples</a></h2></li>
+          <div class="line"> </div>
+          <li><h2>More</h2>
+            <ul>
+              <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+              <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+              <li><a href="themes.html">Themes</a></li>
+            </ul>
+          </li>
+        </ul>
+      </div>
+      <script>
+        initToggles();
+      </script>
+
+    <div class="g-unit" id="gc-pagecontent">
+      <div id="pageTitle">
+        <h1 class="page_title">experimental.webInspector.inspectedWindow</h1>
+      </div>
+        <!-- TABLE OF CONTENTS -->
+        <div id="toc">
+          <h2>Contents</h2>
+          <ol>
+            <li style="display: none; ">
+              <a>h2Name</a>
+              <ol>
+                <li>
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li>
+              <li>
+                <a href="#apiReference">API reference: experimental.webInspector.inspectedWindow</a>
+                <ol>
+                  <li style="display: none; ">
+                    <a href="#properties">Properties</a>
+                    <ol>
+                      <li>
+                        <a href="#property-anchor">propertyName</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-methods">Methods</a>
+                    <ol>
+                      <li>
+                        <a href="#method-eval">eval</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-events">Events</a>
+                    <ol>
+                      <li>
+                        <a href="#event-onDOMContentLoaded">onDOMContentLoaded</a>
+                      </li><li>
+                        <a href="#event-onLoaded">onLoaded</a>
+                      </li><li>
+                        <a href="#event-onNavigated">onNavigated</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li style="display: none; ">
+                    <a href="#types">Types</a>
+                    <ol>
+                      <li>
+                        <a href="#id-anchor">id</a>
+                      </li>
+                    </ol>
+                  </li>
+                </ol>
+              </li>
+          </ol>
+        </div>
+        <!-- /TABLE OF CONTENTS -->
+
+        <!-- Standard content lead-in for experimental API pages -->
+        <p id="classSummary" style="display: none; ">
+          For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+        </p>
+
+        <!-- STATIC CONTENT PLACEHOLDER -->
+        <div id="static"></div>
+
+        <!-- API PAGE -->
+        <div class="apiPage">
+        <a name="apiReference"></a>
+        <h2>API reference: experimental.webInspector.inspectedWindow</h2>
+
+          <!-- PROPERTIES -->
+          <div class="apiGroup" style="display: none; ">
+            <a name="properties"></a>
+            <h3 id="properties">Properties</h3>
+
+            <div>
+              <a></a>
+              <h4>getLastError</h4>
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span>chrome.extension</span><span>lastError</span>
+              </div>
+              <div>
+              </div>
+            </div>
+
+          </div> <!-- /apiGroup -->
+
+          <!-- METHODS -->
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
+            <h3>Methods</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-eval"></a> <!-- method-anchor -->
+              <h4>eval</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>experimental.webInspector.inspectedWindow.eval</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>expression</span></var></span><span class="null"><span>, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Evaluates a JavaScript expression in the context of inspected page (NOTE: the expression must evaluate to a JSON-compliant object, otherwise the exception is thrown)</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>expression</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An expression to evaluate.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A function called when evaluation completes.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p style="display: none; ">
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>object result, boolean isException</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>result</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>The result of evaluation</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div><div>
+                      <div>
+          <dt>
+            <var>isException</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>boolean</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Set if an exception was caught while evaluating the expression</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>  <!-- /apiGroup -->
+
+          <!-- EVENTS -->
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a name="event-onDOMContentLoaded"></a>
+              <h4>onDOMContentLoaded</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">experimental.webInspector.inspectedWindow.</span><span>onDOMContentLoaded</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired after DOMContentLoaded event on inspected page is fired.</p>
+
+                <!-- PARAMETERS -->
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div><div class="apiItem">
+              <a name="event-onLoaded"></a>
+              <h4>onLoaded</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">experimental.webInspector.inspectedWindow.</span><span>onLoaded</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired after load event on inspected page is fired.</p>
+
+                <!-- PARAMETERS -->
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div><div class="apiItem">
+              <a name="event-onNavigated"></a>
+              <h4>onNavigated</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">experimental.webInspector.inspectedWindow.</span><span>onNavigated</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired when navigation occurs in the window being inspected.</p>
+
+                <!-- PARAMETERS -->
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+          <!-- TYPES -->
+          <div class="apiGroup" style="display: none; ">
+            <a name="types"></a>
+            <h3 id="types">Types</h3>
+
+            <!-- iterates over all types -->
+            <div class="apiItem">
+              <a></a>
+              <h4>type name</h4>
+
+              <div>
+              </div>
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+        </div> <!-- /apiPage -->
+      </div> <!-- /gc-pagecontent -->
+    </div> <!-- /g-section -->
+  </div> <!-- /codesiteContent -->
+    <div id="gc-footer" --="">
+      <div class="text">
+  <p>
+  Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+  the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+  Attribution 3.0 License</a>, and code samples are licensed under the
+  <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+  </p>
+  <p>
+  ©2011 Google
+  </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+  // chrome doc tracking
+  try {
+    var engdocs = _gat._getTracker("YT-10763712-2");
+    engdocs._trackPageview();
+  } catch(err) {}
+
+  // code.google.com site-wide tracking
+  try {
+    _uacct="UA-18071-1";
+    _uanchor=1;
+    _uff=0;
+    urchinTracker();
+  }
+  catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+      </div>
+    </div> <!-- /gc-footer -->
+  </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/experimental.webInspector.panels.html b/chrome/common/extensions/docs/experimental.webInspector.panels.html
new file mode 100644
index 0000000..29a1295
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.webInspector.panels.html
@@ -0,0 +1,3056 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+    1) The <head> information in this page is significant, should be uniform
+       across api docs and should be edited only with knowledge of the
+       templating mechanism.
+    3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+       browser, it will be re-generated from the template, json schema and
+       authored overview content.
+    4) The <body>.innerHTML is also generated by an offline step so that this
+       page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+    <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+    </script>
+    <script type="text/javascript" src="js/api_page_generator.js"></script>
+    <script type="text/javascript" src="js/bootstrap.js"></script>
+    <script type="text/javascript" src="js/sidebar.js"></script>
+  <title>experimental.webInspector.panels - Google Chrome Extensions - Google Code</title></head>
+  <body>  <div id="gc-container" class="labs">
+      <div id="devModeWarning">
+        You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+      </div>
+      <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+      <!-- In particular, sub-templates that recurse, must be used by allowing
+           jstemplate to make a copy of the template in this section which
+           are not operated on by way of the jsskip="true" -->
+      <div style="display:none">
+
+        <!-- VALUE -->
+        <div id="valueTemplate">
+          <dt>
+            <var>paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd>
+            Description of this parameter from the json schema.
+          </dd>
+          <dd>
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd>
+            <div></div>
+          </dd>
+
+        </div> <!-- /VALUE -->
+
+        <div id="functionParametersTemplate">
+          <h5>Parameters</h5>
+          <dl>
+            <div>
+              <div>
+              </div>
+            </div>
+          </dl>
+        </div>
+      </div> <!-- /SUBTEMPLATES -->
+
+  <a id="top"></a>
+    <div id="skipto">
+      <a href="#gc-pagecontent">Skip to page content</a>
+      <a href="#gc-toc">Skip to main navigation</a>
+    </div>
+    <!-- API HEADER -->
+    <table id="header" width="100%" cellspacing="0" border="0">
+      <tbody><tr>
+        <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+        <td valign="middle" width="100%" style="padding-left:0.6em;">
+          <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+            <div id="gsc-search-box">
+              <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+              <input type="hidden" name="ie" value="UTF-8">
+              <input type="text" name="q" value="" size="55">
+              <input class="gsc-search-button" type="submit" name="sa" value="Search">
+              <br>
+              <span class="greytext">e.g. "page action" or "tabs"</span>
+            </div>
+          </form>
+
+          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+          <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+        </td>
+      </tr>
+    </tbody></table>
+
+    <div id="codesiteContent" class="">
+
+      <a id="gc-topnav-anchor"></a>
+      <div id="gc-topnav">
+        <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+        <ul id="home" class="gc-topnav-tabs">
+          <li id="home_link">
+            <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+          </li>
+          <li id="docs_link">
+            <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+          </li>
+          <li id="faq_link">
+            <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+          </li>
+          <li id="samples_link">
+            <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+          </li>
+          <li id="group_link">
+            <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+          </li>
+        </ul>
+      </div> <!-- end gc-topnav -->
+
+    <div class="g-section g-tpl-170">
+      <!-- SIDENAV -->
+      <div class="g-unit g-first" id="gc-toc">
+        <ul>
+          <li><a href="getstarted.html">Getting Started</a></li>
+          <li><a href="overview.html">Overview</a></li>
+          <li><a href="whats_new.html">What's New?</a></li>
+          <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+            <ul>
+              <li>Browser UI
+                <ul>
+                  <li><a href="browserAction.html">Browser Actions</a></li>
+                  <li><a href="contextMenus.html">Context Menus</a></li>
+                  <li><a href="notifications.html">Desktop Notifications</a></li>
+                  <li><a href="omnibox.html">Omnibox</a></li>
+                  <li><a href="options.html">Options Pages</a></li>
+                  <li><a href="override.html">Override Pages</a></li>
+                  <li><a href="pageAction.html">Page Actions</a></li>
+                </ul>
+              </li>
+              <li>Browser Interaction
+                <ul>
+                  <li><a href="bookmarks.html">Bookmarks</a></li>
+                  <li><a href="cookies.html">Cookies</a></li>
+                  <li><a href="events.html">Events</a></li>
+                  <li><a href="history.html">History</a></li>
+                  <li><a href="management.html">Management</a></li>
+                  <li><a href="tabs.html">Tabs</a></li>
+                  <li><a href="windows.html">Windows</a></li>
+                </ul>
+              </li>
+              <li>Implementation
+                <ul>
+                  <li><a href="a11y.html">Accessibility</a></li>
+                  <li><a href="background_pages.html">Background Pages</a></li>
+                  <li><a href="content_scripts.html">Content Scripts</a></li>
+                  <li><a href="xhr.html">Cross-Origin XHR</a></li>
+                  <li><a href="idle.html">Idle</a></li>
+                  <li><a href="i18n.html">Internationalization</a></li>
+                  <li><a href="messaging.html">Message Passing</a></li>
+                  <li><a href="npapi.html">NPAPI Plugins</a></li>
+                </ul>
+              </li>
+              <li>Finishing
+                <ul>
+                  <li><a href="hosting.html">Hosting</a></li>
+                  <li><a href="external_extensions.html">Other Deployment Options</a></li>
+                </ul>
+              </li>
+            </ul>
+          </li>
+          <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+          <li><h2><a href="tutorials.html">Tutorials</a></h2>
+            <ul>
+              <li><a href="tut_debugging.html">Debugging</a></li>
+              <li><a href="tut_analytics.html">Google Analytics</a></li>
+              <li><a href="tut_oauth.html">OAuth</a></li>
+            </ul>
+          </li>
+          <li><h2>Reference</h2>
+            <ul>
+              <li>Formats
+                <ul>
+                  <li><a href="manifest.html">Manifest Files</a></li>
+                  <li><a href="match_patterns.html">Match Patterns</a></li>
+                </ul>
+              </li>
+              <li><a href="permission_warnings.html">Permission Warnings</a></li>
+              <li><a href="api_index.html">chrome.* APIs</a></li>
+              <li><a href="api_other.html">Other APIs</a></li>
+            </ul>
+          </li>
+          <li><h2><a href="samples.html">Samples</a></h2></li>
+          <div class="line"> </div>
+          <li><h2>More</h2>
+            <ul>
+              <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+              <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+              <li><a href="themes.html">Themes</a></li>
+            </ul>
+          </li>
+        </ul>
+      </div>
+      <script>
+        initToggles();
+      </script>
+
+    <div class="g-unit" id="gc-pagecontent">
+      <div id="pageTitle">
+        <h1 class="page_title">experimental.webInspector.panels</h1>
+      </div>
+        <!-- TABLE OF CONTENTS -->
+        <div id="toc">
+          <h2>Contents</h2>
+          <ol>
+            <li style="display: none; ">
+              <a>h2Name</a>
+              <ol>
+                <li>
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li>
+              <li>
+                <a href="#apiReference">API reference: experimental.webInspector.panels</a>
+                <ol>
+                  <li>
+                    <a href="#properties">Properties</a>
+                    <ol>
+                      <li>
+                        <a href="#property-scripts">scripts</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-methods">Methods</a>
+                    <ol>
+                      <li>
+                        <a href="#method-create">create</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li style="display: none; ">
+                    <a>Events</a>
+                    <ol>
+                      <li>
+                        <a href="#event-anchor">eventName</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#types">Types</a>
+                    <ol>
+                      <li>
+                        <a href="#type-PanelWithSidebars">PanelWithSidebars</a>
+                      </li><li>
+                        <a href="#type-ElementsPanel">ElementsPanel</a>
+                      </li><li>
+                        <a href="#type-ExtensionPanel">ExtensionPanel</a>
+                      </li><li>
+                        <a href="#type-ExtensionSidebarPane">ExtensionSidebarPane</a>
+                      </li><li>
+                        <a href="#type-WatchExpressionSidebarPane">WatchExpressionSidebarPane</a>
+                      </li>
+                    </ol>
+                  </li>
+                </ol>
+              </li>
+          </ol>
+        </div>
+        <!-- /TABLE OF CONTENTS -->
+
+        <!-- Standard content lead-in for experimental API pages -->
+        <p id="classSummary" style="display: none; ">
+          For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+        </p>
+
+        <!-- STATIC CONTENT PLACEHOLDER -->
+        <div id="static"></div>
+
+        <!-- API PAGE -->
+        <div class="apiPage">
+        <a name="apiReference"></a>
+        <h2>API reference: experimental.webInspector.panels</h2>
+
+          <!-- PROPERTIES -->
+          <div class="apiGroup">
+            <a name="properties"></a>
+            <h3 id="properties">Properties</h3>
+
+            <div>
+              <a name="property-scripts"></a>
+              <h4>scripts</h4>
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span>experimental.webInspector.panels.</span><span>scripts</span>
+              </div>
+              <div>
+          <dt>
+            <var>scripts</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a>ScriptsPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Scripts panel</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+            </div>
+
+          </div> <!-- /apiGroup -->
+
+          <!-- METHODS -->
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
+            <h3>Methods</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-create"></a> <!-- method-anchor -->
+              <h4>create</h4>
+
+              <div class="summary"><span>ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>experimental.webInspector.panels.create</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>title</span></var></span><span class="null"><span>, </span><span>string</span>
+                      <var><span>iconURL</span></var></span><span class="null"><span>, </span><span>string</span>
+                      <var><span>pageURL</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Creates an extension panel.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>title</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Title that is displayed under the extension icon in the toolbar.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>iconURL</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An URL of the toolbar icon.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>pageURL</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An URL of the page that represents this panel.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4>Returns</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>  <!-- /apiGroup -->
+
+          <!-- EVENTS -->
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a></a>
+              <h4>event name</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo">Undocumented.</p>
+                <p>
+                  A description from the json schema def of the event goes here.
+                </p>
+
+                <!-- PARAMETERS -->
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+          <!-- TYPES -->
+          <div class="apiGroup">
+            <a name="types"></a>
+            <h3 id="types">Types</h3>
+
+            <!-- iterates over all types -->
+            <div class="apiItem">
+              <a name="type-PanelWithSidebars"></a>
+              <h4>PanelWithSidebars</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>Panel</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel within Web Inspector UI that has sidebars.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div class="apiGroup">
+            <a name="global-PanelWithSidebars-methods"></a>
+            <h3>Methods of PanelWithSidebars</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-PanelWithSidebars-createSidebarPane"></a> <!-- method-anchor -->
+              <h4>createSidebarPane</h4>
+
+              <div class="summary"><span style="display: none; ">ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>panelWithSidebars.createSidebarPane</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>title</span></var></span><span class="null"><span>, </span><span>string</span>
+                      <var><span>url</span></var></span><span class="null"><span>, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Creates a pane within panel's sidebar.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>title</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A text that is displayed in sidebar caption.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>url</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An URL of the page that represents the sidebar.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A callback invoked when sidebar is created</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p style="display: none; ">
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>ExtensionSidebarPane result</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>result</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionSidebarPane">ExtensionSidebarPane</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An ExtensionSidebarPane object for created sidebar pane</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-PanelWithSidebars-createWatchExpressionSidebarPane"></a> <!-- method-anchor -->
+              <h4>createWatchExpressionSidebarPane</h4>
+
+              <div class="summary"><span style="display: none; ">ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>panelWithSidebars.createWatchExpressionSidebarPane</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>title</span></var></span><span class="null"><span>, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Creates a pane with an object property tree (similar to a watch sidebar pane).</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>title</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A text that is displayed in sidebar caption.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A callback invoked when sidebar is created</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p style="display: none; ">
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>WatchExpressionSidebarPane result</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>result</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-WatchExpressionSidebarPane">WatchExpressionSidebarPane</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A WatchExpressionSidebarPane object for created sidebar pane</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-ElementsPanel"></a>
+              <h4>ElementsPanel</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>PanelWithSidebars</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Represents Elements panel</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div class="apiGroup" style="">
+            <a name="global-ElementsPanel-events"></a>
+            <h3>Events of ElementsPanel</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a name="event-ElementsPanel-onSelectionChanged"></a>
+              <h4>onSelectionChanged</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">elementsPanel.</span><span>onSelectionChanged</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired when an objects is selected in the panel.</p>
+
+                <!-- PARAMETERS -->
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-ExtensionPanel"></a>
+              <h4>ExtensionPanel</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>Panel</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Represents a panel created by extension</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div class="apiGroup" style="">
+            <a name="global-ExtensionPanel-events"></a>
+            <h3>Events of ExtensionPanel</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a name="event-ExtensionPanel-onSearch"></a>
+              <h4>onSearch</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">extensionPanel.</span><span>onSearch</span><span class="subdued">.addListener</span>(function(<span>string action, string queryString</span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired upon a search action (start of a new search, search result navigation or search being canceled).</p>
+
+                <!-- PARAMETERS -->
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>action</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Type of search action being performed.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div><div>
+                      <div>
+          <dt>
+            <var>queryString</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Query string (only for 'performSearch')</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-ExtensionSidebarPane"></a>
+              <h4>ExtensionSidebarPane</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A sidebar created by the extension.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div class="apiGroup">
+            <a name="global-ExtensionSidebarPane-methods"></a>
+            <h3>Methods of ExtensionSidebarPane</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-ExtensionSidebarPane-setHeight"></a> <!-- method-anchor -->
+              <h4>setHeight</h4>
+
+              <div class="summary"><span style="display: none; ">ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>extensionSidebarPane.setHeight</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>height</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Sets the height of the sidebar.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>height</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A CSS-like size specification, e.g. '10px' or '12pt'</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div><div class="apiItem">
+              <a name="type-WatchExpressionSidebarPane"></a>
+              <h4>WatchExpressionSidebarPane</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A sidebar created by the extension.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div class="apiGroup">
+            <a name="global-WatchExpressionSidebarPane-methods"></a>
+            <h3>Methods of WatchExpressionSidebarPane</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-WatchExpressionSidebarPane-setExpression"></a> <!-- method-anchor -->
+              <h4>setExpression</h4>
+
+              <div class="summary"><span style="display: none; ">ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>watchExpressionSidebarPane.setExpression</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>expression</span></var></span><span class="optional"><span>, </span><span>string</span>
+                      <var><span>rootTitle</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Sets an expression that is evaluated within the inspected page. The result is displayed in the sidebar pane.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>expression</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An expression to be evaluated in context of the inspected page. JavaScript objects and DOM nodes are displayed in an expandable tree similar to the console/watch.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>rootTitle</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An optional title for the root of the expression tree.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-WatchExpressionSidebarPane-setHeight"></a> <!-- method-anchor -->
+              <h4>setHeight</h4>
+
+              <div class="summary"><span style="display: none; ">ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>watchExpressionSidebarPane.setHeight</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>height</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Sets the height of the sidebar.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>height</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A CSS-like size specification, e.g. '10px' or '12pt'</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div><div class="apiItem">
+              <a name="method-WatchExpressionSidebarPane-setObject"></a> <!-- method-anchor -->
+              <h4>setObject</h4>
+
+              <div class="summary"><span style="display: none; ">ExtensionPanel</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>watchExpressionSidebarPane.setObject</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+                      <var><span>jsonObject</span></var></span><span class="optional"><span>, </span><span>string</span>
+                      <var><span>rootTitle</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Sets a JSON-compliant object to be displayed in the sidebar pane.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>jsonObject</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An object to be displayed in context of the inspected page. Evaluated in the context of the caller (API client).</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div><div>
+                    <div>
+          <dt>
+            <var>rootTitle</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An optional title for the root of the expression tree.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.panels.html#type-ExtensionPanel">ExtensionPanel</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A panel that was created.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div style="display: none; ">
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p>
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+                      </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+        </div> <!-- /apiPage -->
+      </div> <!-- /gc-pagecontent -->
+    </div> <!-- /g-section -->
+  </div> <!-- /codesiteContent -->
+    <div id="gc-footer" --="">
+      <div class="text">
+  <p>
+  Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+  the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+  Attribution 3.0 License</a>, and code samples are licensed under the
+  <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+  </p>
+  <p>
+  ©2011 Google
+  </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+  // chrome doc tracking
+  try {
+    var engdocs = _gat._getTracker("YT-10763712-2");
+    engdocs._trackPageview();
+  } catch(err) {}
+
+  // code.google.com site-wide tracking
+  try {
+    _uacct="UA-18071-1";
+    _uanchor=1;
+    _uff=0;
+    urchinTracker();
+  }
+  catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+      </div>
+    </div> <!-- /gc-footer -->
+  </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/experimental.webInspector.resources.html b/chrome/common/extensions/docs/experimental.webInspector.resources.html
new file mode 100644
index 0000000..60036e2
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.webInspector.resources.html
@@ -0,0 +1,1036 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+    1) The <head> information in this page is significant, should be uniform
+       across api docs and should be edited only with knowledge of the
+       templating mechanism.
+    3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+       browser, it will be re-generated from the template, json schema and
+       authored overview content.
+    4) The <body>.innerHTML is also generated by an offline step so that this
+       page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+    <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+    </script>
+    <script type="text/javascript" src="js/api_page_generator.js"></script>
+    <script type="text/javascript" src="js/bootstrap.js"></script>
+    <script type="text/javascript" src="js/sidebar.js"></script>
+  <title>experimental.webInspector.resources - Google Chrome Extensions - Google Code</title></head>
+  <body>  <div id="gc-container" class="labs">
+      <div id="devModeWarning">
+        You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+      </div>
+      <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+      <!-- In particular, sub-templates that recurse, must be used by allowing
+           jstemplate to make a copy of the template in this section which
+           are not operated on by way of the jsskip="true" -->
+      <div style="display:none">
+
+        <!-- VALUE -->
+        <div id="valueTemplate">
+          <dt>
+            <var>paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd>
+            Description of this parameter from the json schema.
+          </dd>
+          <dd>
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd>
+            <div></div>
+          </dd>
+
+        </div> <!-- /VALUE -->
+
+        <div id="functionParametersTemplate">
+          <h5>Parameters</h5>
+          <dl>
+            <div>
+              <div>
+              </div>
+            </div>
+          </dl>
+        </div>
+      </div> <!-- /SUBTEMPLATES -->
+
+  <a id="top"></a>
+    <div id="skipto">
+      <a href="#gc-pagecontent">Skip to page content</a>
+      <a href="#gc-toc">Skip to main navigation</a>
+    </div>
+    <!-- API HEADER -->
+    <table id="header" width="100%" cellspacing="0" border="0">
+      <tbody><tr>
+        <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+        <td valign="middle" width="100%" style="padding-left:0.6em;">
+          <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+            <div id="gsc-search-box">
+              <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+              <input type="hidden" name="ie" value="UTF-8">
+              <input type="text" name="q" value="" size="55">
+              <input class="gsc-search-button" type="submit" name="sa" value="Search">
+              <br>
+              <span class="greytext">e.g. "page action" or "tabs"</span>
+            </div>
+          </form>
+
+          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+          <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+          <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+        </td>
+      </tr>
+    </tbody></table>
+
+    <div id="codesiteContent" class="">
+
+      <a id="gc-topnav-anchor"></a>
+      <div id="gc-topnav">
+        <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+        <ul id="home" class="gc-topnav-tabs">
+          <li id="home_link">
+            <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+          </li>
+          <li id="docs_link">
+            <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+          </li>
+          <li id="faq_link">
+            <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+          </li>
+          <li id="samples_link">
+            <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+          </li>
+          <li id="group_link">
+            <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+          </li>
+        </ul>
+      </div> <!-- end gc-topnav -->
+
+    <div class="g-section g-tpl-170">
+      <!-- SIDENAV -->
+      <div class="g-unit g-first" id="gc-toc">
+        <ul>
+          <li><a href="getstarted.html">Getting Started</a></li>
+          <li><a href="overview.html">Overview</a></li>
+          <li><a href="whats_new.html">What's New?</a></li>
+          <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+            <ul>
+              <li>Browser UI
+                <ul>
+                  <li><a href="browserAction.html">Browser Actions</a></li>
+                  <li><a href="contextMenus.html">Context Menus</a></li>
+                  <li><a href="notifications.html">Desktop Notifications</a></li>
+                  <li><a href="omnibox.html">Omnibox</a></li>
+                  <li><a href="options.html">Options Pages</a></li>
+                  <li><a href="override.html">Override Pages</a></li>
+                  <li><a href="pageAction.html">Page Actions</a></li>
+                </ul>
+              </li>
+              <li>Browser Interaction
+                <ul>
+                  <li><a href="bookmarks.html">Bookmarks</a></li>
+                  <li><a href="cookies.html">Cookies</a></li>
+                  <li><a href="events.html">Events</a></li>
+                  <li><a href="history.html">History</a></li>
+                  <li><a href="management.html">Management</a></li>
+                  <li><a href="tabs.html">Tabs</a></li>
+                  <li><a href="windows.html">Windows</a></li>
+                </ul>
+              </li>
+              <li>Implementation
+                <ul>
+                  <li><a href="a11y.html">Accessibility</a></li>
+                  <li><a href="background_pages.html">Background Pages</a></li>
+                  <li><a href="content_scripts.html">Content Scripts</a></li>
+                  <li><a href="xhr.html">Cross-Origin XHR</a></li>
+                  <li><a href="idle.html">Idle</a></li>
+                  <li><a href="i18n.html">Internationalization</a></li>
+                  <li><a href="messaging.html">Message Passing</a></li>
+                  <li><a href="npapi.html">NPAPI Plugins</a></li>
+                </ul>
+              </li>
+              <li>Finishing
+                <ul>
+                  <li><a href="hosting.html">Hosting</a></li>
+                  <li><a href="external_extensions.html">Other Deployment Options</a></li>
+                </ul>
+              </li>
+            </ul>
+          </li>
+          <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
+          <li><h2><a href="tutorials.html">Tutorials</a></h2>
+            <ul>
+              <li><a href="tut_debugging.html">Debugging</a></li>
+              <li><a href="tut_analytics.html">Google Analytics</a></li>
+              <li><a href="tut_oauth.html">OAuth</a></li>
+            </ul>
+          </li>
+          <li><h2>Reference</h2>
+            <ul>
+              <li>Formats
+                <ul>
+                  <li><a href="manifest.html">Manifest Files</a></li>
+                  <li><a href="match_patterns.html">Match Patterns</a></li>
+                </ul>
+              </li>
+              <li><a href="permission_warnings.html">Permission Warnings</a></li>
+              <li><a href="api_index.html">chrome.* APIs</a></li>
+              <li><a href="api_other.html">Other APIs</a></li>
+            </ul>
+          </li>
+          <li><h2><a href="samples.html">Samples</a></h2></li>
+          <div class="line"> </div>
+          <li><h2>More</h2>
+            <ul>
+              <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
+              <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
+              <li><a href="themes.html">Themes</a></li>
+            </ul>
+          </li>
+        </ul>
+      </div>
+      <script>
+        initToggles();
+      </script>
+
+    <div class="g-unit" id="gc-pagecontent">
+      <div id="pageTitle">
+        <h1 class="page_title">experimental.webInspector.resources</h1>
+      </div>
+        <!-- TABLE OF CONTENTS -->
+        <div id="toc">
+          <h2>Contents</h2>
+          <ol>
+            <li style="display: none; ">
+              <a>h2Name</a>
+              <ol>
+                <li>
+                  <a>h3Name</a>
+                </li>
+              </ol>
+            </li>
+              <li>
+                <a href="#apiReference">API reference: experimental.webInspector.resources</a>
+                <ol>
+                  <li style="display: none; ">
+                    <a href="#properties">Properties</a>
+                    <ol>
+                      <li>
+                        <a href="#property-anchor">propertyName</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-methods">Methods</a>
+                    <ol>
+                      <li>
+                        <a href="#method-getHAR">getHAR</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#global-events">Events</a>
+                    <ol>
+                      <li>
+                        <a href="#event-onFinished">onFinished</a>
+                      </li>
+                    </ol>
+                  </li>
+                  <li>
+                    <a href="#types">Types</a>
+                    <ol>
+                      <li>
+                        <a href="#type-Resource">Resource</a>
+                      </li>
+                    </ol>
+                  </li>
+                </ol>
+              </li>
+          </ol>
+        </div>
+        <!-- /TABLE OF CONTENTS -->
+
+        <!-- Standard content lead-in for experimental API pages -->
+        <p id="classSummary" style="display: none; ">
+          For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+        </p>
+
+        <!-- STATIC CONTENT PLACEHOLDER -->
+        <div id="static"></div>
+
+        <!-- API PAGE -->
+        <div class="apiPage">
+        <a name="apiReference"></a>
+        <h2>API reference: experimental.webInspector.resources</h2>
+
+          <!-- PROPERTIES -->
+          <div class="apiGroup" style="display: none; ">
+            <a name="properties"></a>
+            <h3 id="properties">Properties</h3>
+
+            <div>
+              <a></a>
+              <h4>getLastError</h4>
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span>chrome.extension</span><span>lastError</span>
+              </div>
+              <div>
+              </div>
+            </div>
+
+          </div> <!-- /apiGroup -->
+
+          <!-- METHODS -->
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
+            <h3>Methods</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-getHAR"></a> <!-- method-anchor -->
+              <h4>getHAR</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>experimental.webInspector.resources.getHAR</span>(<span class="null"><span style="display: none; ">, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Returns HAR archive that contains all known resource objects.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A function that is called upon request completion.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p style="display: none; ">
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>object har</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>har</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A HAR archieve. See HAR specification for details.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>  <!-- /apiGroup -->
+
+          <!-- EVENTS -->
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
+            <!-- iterates over all events -->
+            <div class="apiItem">
+              <a name="event-onFinished"></a>
+              <h4>onFinished</h4>
+
+              <div class="summary">
+                <!-- Note: intentionally longer 80 columns -->
+                <span class="subdued">experimental.webInspector.resources.</span><span>onFinished</span><span class="subdued">.addListener</span>(function(<span>Resource resource</span>) <span class="subdued">{...}</span>);
+              </div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Fired when a resource request is finished and all resource data are available.</p>
+
+                <!-- PARAMETERS -->
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>resource</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span>
+                        <a href="experimental.webInspector.resources.html#type-Resource">Resource</a>
+                      </span>
+                      <span style="display: none; ">
+                        <span>
+                          array of <span><span></span></span>
+                        </span>
+                        <span>paramType</span>
+                        <span></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                </div>
+              </div> <!-- /decription -->
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+          <!-- TYPES -->
+          <div class="apiGroup">
+            <a name="types"></a>
+            <h3 id="types">Types</h3>
+
+            <!-- iterates over all types -->
+            <div class="apiItem">
+              <a name="type-Resource"></a>
+              <h4>Resource</h4>
+
+              <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Represents a resource (document, script, image etc). See HAR Specification for reference.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div class="apiGroup">
+            <a name="global-Resource-methods"></a>
+            <h3>Methods of Resource</h3>
+
+            <!-- iterates over all functions -->
+            <div class="apiItem">
+              <a name="method-Resource-getContent"></a> <!-- method-anchor -->
+              <h4>getContent</h4>
+
+              <div class="summary"><span style="display: none; ">void</span>
+                  <!-- Note: intentionally longer 80 columns -->
+                  <span>resource.getContent</span>(<span class="null"><span style="display: none; ">, </span><span>function</span>
+                      <var><span>callback</span></var></span>)</div>
+
+              <div class="description">
+                <p class="todo" style="display: none; ">Undocumented.</p>
+                <p>Returns resource content.</p>
+
+                <!-- PARAMETERS -->
+                <h4>Parameters</h4>
+                <dl>
+                  <div>
+                    <div>
+          <dt>
+            <var>callback</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>function</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A function that is called upon request completion.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                  </div>
+                </dl>
+
+                <!-- RETURNS -->
+                <h4 style="display: none; ">Returns</h4>
+                <dl>
+                  <div style="display: none; ">
+                    <div>
+                    </div>
+                  </div>
+                </dl>
+
+                <!-- CALLBACK -->
+                <div>
+                  <div>
+                  <h4>Callback function</h4>
+                  <p>
+                    The callback <em>parameter</em> should specify a function
+                    that looks like this:
+                  </p>
+                  <p style="display: none; ">
+                    If you specify the <em>callback</em> parameter, it should
+                    specify a function that looks like this:
+                  </p>
+
+                  <!-- Note: intentionally longer 80 columns -->
+                  <pre>function(<span>string content, string encoding</span>) <span class="subdued">{...}</span>;</pre>
+                  <dl>
+                    <div>
+                      <div>
+          <dt>
+            <var>content</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Resource content (potentially encoded).</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div><div>
+                      <div>
+          <dt>
+            <var>encoding</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>Empty if content is not encoded, encoding name otherwise. Currently, only base64 supported.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+                    </div>
+                  </dl>
+                  </div>
+                </div>
+
+                <!-- MIN_VERSION -->
+                <p style="display: none; ">
+                  This function was added in version <b><span></span></b>.
+                  If you require this function, the manifest key
+                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+                  can ensure that your extension won't be run in an earlier browser version.
+                </p>
+              </div> <!-- /description -->
+
+            </div>  <!-- /apiItem -->
+
+          </div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+
+            </div> <!-- /apiItem -->
+
+          </div> <!-- /apiGroup -->
+
+        </div> <!-- /apiPage -->
+      </div> <!-- /gc-pagecontent -->
+    </div> <!-- /g-section -->
+  </div> <!-- /codesiteContent -->
+    <div id="gc-footer" --="">
+      <div class="text">
+  <p>
+  Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+  the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+  Attribution 3.0 License</a>, and code samples are licensed under the
+  <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+  </p>
+  <p>
+  ©2011 Google
+  </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+  // chrome doc tracking
+  try {
+    var engdocs = _gat._getTracker("YT-10763712-2");
+    engdocs._trackPageview();
+  } catch(err) {}
+
+  // code.google.com site-wide tracking
+  try {
+    _uacct="UA-18071-1";
+    _uanchor=1;
+    _uff=0;
+    urchinTracker();
+  }
+  catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+      </div>
+    </div> <!-- /gc-footer -->
+  </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/docs/experimental.webNavigation.html b/chrome/common/extensions/docs/experimental.webNavigation.html
index 52a04af..166af51 100644
--- a/chrome/common/extensions/docs/experimental.webNavigation.html
+++ b/chrome/common/extensions/docs/experimental.webNavigation.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li style="display: none; ">
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onBeforeNavigate">onBeforeNavigate</a>
@@ -338,8 +348,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods" style="display: none; ">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -414,10 +424,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onBeforeNavigate"></a>
@@ -433,10 +442,11 @@
                 <p>Fires when a navigation is about to occur.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -534,6 +544,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -594,6 +614,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -652,6 +682,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -710,6 +750,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -768,6 +818,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -778,15 +838,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -803,10 +873,11 @@
                 <p>Fires when a new window, or a new tab in an existing window, is about to be created to host a navigation.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -904,6 +975,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -962,6 +1043,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1020,6 +1111,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1078,6 +1179,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1088,15 +1199,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1113,10 +1234,11 @@
                 <p>Fires when a navigation is committed. The document (and the resources it refers to, such as images and subframes) might still be downloading, but at least part of the document has been received from the server and the browser has decided to switch to the new document.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -1214,6 +1336,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1274,6 +1406,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1332,6 +1474,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1390,6 +1542,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1448,6 +1610,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1506,6 +1678,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1516,15 +1698,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1541,10 +1733,11 @@
                 <p>Fires when a document, including the resources it refers to, is completely loaded and initialized.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -1642,6 +1835,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1702,6 +1905,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1760,6 +1973,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1818,6 +2041,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1828,15 +2061,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1853,10 +2096,11 @@
                 <p>Fires when the page's DOM is fully constructed, but the referenced resources may not finish loading.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -1954,6 +2198,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2014,6 +2268,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2072,6 +2336,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2130,6 +2404,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2140,15 +2424,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2165,10 +2459,11 @@
                 <p>Fires when an error occurs.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -2266,6 +2561,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2326,6 +2631,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2384,6 +2699,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2442,6 +2767,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2500,6 +2835,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2510,15 +2855,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/experimental.webRequest.html b/chrome/common/extensions/docs/experimental.webRequest.html
index 71769af..0e11c39 100644
--- a/chrome/common/extensions/docs/experimental.webRequest.html
+++ b/chrome/common/extensions/docs/experimental.webRequest.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -266,16 +276,16 @@
                       </li>
                     </ol>
                   </li>
-                  <li style="display: none; ">
-                    <a href="#methods">Methods</a>
+                  <li>
+                    <a href="#global-methods">Methods</a>
                     <ol>
-                      <li>
+                      <li style="display: none; ">
                         <a href="#method-anchor">methodName</a>
                       </li>
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onBeforeRedirect">onBeforeRedirect</a>
@@ -292,11 +302,11 @@
                       </li>
                     </ol>
                   </li>
-                  <li style="display: none; ">
+                  <li>
                     <a href="#types">Types</a>
                     <ol>
                       <li>
-                        <a href="#id-anchor">id</a>
+                        <a href="#type-RequestFilter">RequestFilter</a>
                       </li>
                     </ol>
                   </li>
@@ -338,12 +348,12 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods" style="display: none; ">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
-            <div class="apiItem">
+            <div class="apiItem" style="display: none; ">
               <a></a> <!-- method-anchor -->
               <h4>method name</h4>
 
@@ -414,10 +424,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onBeforeRedirect"></a>
@@ -433,10 +442,11 @@
                 <p>Fires when a server initiated redirect is about to occur.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -534,6 +544,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -592,6 +612,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -650,6 +680,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -708,6 +748,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -766,6 +816,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -776,15 +836,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -801,10 +871,11 @@
                 <p>Fires when a request is about to occur.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -902,6 +973,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -962,6 +1043,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1020,6 +1111,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1078,6 +1179,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1136,6 +1247,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1194,6 +1315,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1204,15 +1335,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1229,10 +1370,11 @@
                 <p>Fires when a request is completed.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -1330,6 +1472,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1388,6 +1540,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1446,6 +1608,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1504,6 +1676,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1514,15 +1696,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1539,10 +1731,11 @@
                 <p>Fires when an error occurs.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -1640,6 +1833,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1698,6 +1901,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1756,6 +1969,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1814,6 +2037,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1824,15 +2057,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1849,10 +2092,11 @@
                 <p>Fires when the status line and response headers are received after a request is sent to the server.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -1950,6 +2194,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2010,6 +2264,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2068,6 +2332,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2126,6 +2400,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2136,15 +2420,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2161,10 +2455,11 @@
                 <p>Fires when a request is sent to the server.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>details</var>
               <em>
@@ -2262,6 +2557,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2322,6 +2627,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2380,6 +2695,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2438,6 +2763,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2448,15 +2783,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -2464,17 +2809,377 @@
           </div> <!-- /apiGroup -->
 
           <!-- TYPES -->
-          <div class="apiGroup" style="display: none; ">
+          <div class="apiGroup">
             <a name="types"></a>
             <h3 id="types">Types</h3>
 
             <!-- iterates over all types -->
             <div class="apiItem">
-              <a></a>
-              <h4>type name</h4>
+              <a name="type-RequestFilter"></a>
+              <h4>RequestFilter</h4>
 
               <div>
+          <dt>
+            <var style="display: none; ">paramName</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional" style="display: none; ">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>object</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>An object describing filters to apply to webRequest events.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd>
+            <dl>
+              <div>
+                <div>
+          <dt>
+            <var>urls</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span>
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span></span>
+                        </span>
+                        <span style="display: none; ">paramType</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A list of URLs or URL patterns. Requests that cannot match any of the URLs will be filtered out.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
               </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>types</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span>
+                          array of <span><span>
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>string</span>
+                        <span>["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "other"]</span>
+                      </span>
+                    </span></span>
+                        </span>
+                        <span style="display: none; ">paramType</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo" style="display: none; ">
+            Undocumented.
+          </dd>
+          <dd>A list of request types. Requests that cannot match any of the types will be filtered out.</dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>tabId</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>integer</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div><div>
+                <div>
+          <dt>
+            <var>windowId</var>
+              <em>
+
+                <!-- TYPE -->
+                <div style="display:inline">
+                  (
+                    <span class="optional">optional</span>
+                    <span class="enum" style="display: none; ">enumerated</span>
+                    <span id="typeTemplate">
+                      <span style="display: none; ">
+                        <a> Type</a>
+                      </span>
+                      <span>
+                        <span style="display: none; ">
+                          array of <span><span></span></span>
+                        </span>
+                        <span>integer</span>
+                        <span style="display: none; "></span>
+                      </span>
+                    </span>
+                  )
+                </div>
+
+              </em>
+          </dt>
+          <dd class="todo">
+            Undocumented.
+          </dd>
+          <dd style="display: none; ">
+            Description of this parameter from the json schema.
+          </dd>
+          <dd style="display: none; ">
+            This parameter was added in version
+            <b><span></span></b>.
+            You must omit this parameter in earlier versions,
+            and you may omit it in any version.  If you require this
+            parameter, the manifest key
+            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+            can ensure that your extension won't be run in an earlier browser version.
+          </dd>
+
+          <!-- OBJECT PROPERTIES -->
+          <dd style="display: none; ">
+            <dl>
+              <div>
+                <div>
+                </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
+              </div>
+            </dl>
+          </dd>
+
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- FUNCTION PARAMETERS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+        </div>
 
             </div> <!-- /apiItem -->
 
diff --git a/chrome/common/extensions/docs/extension.html b/chrome/common/extensions/docs/extension.html
index a0e11fd..9e99f0e 100644
--- a/chrome/common/extensions/docs/extension.html
+++ b/chrome/common/extensions/docs/extension.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -269,7 +279,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-connect">connect</a>
@@ -291,7 +301,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onConnect">onConnect</a>
@@ -490,6 +500,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -500,6 +520,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -609,6 +639,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -619,6 +659,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -630,8 +680,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -704,6 +754,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -809,6 +869,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -819,6 +889,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -883,6 +963,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -936,10 +1026,10 @@
 
               <div class="description">
                 <p class="todo" style="display: none; ">Undocumented.</p>
-                <p>Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no backround page.</p>
+                <p>Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no background page.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
+                <h4 style="display: none; ">Parameters</h4>
                 <dl>
                   <div style="display: none; ">
                     <div>
@@ -1004,6 +1094,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1246,6 +1346,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1310,6 +1420,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1467,6 +1587,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1525,6 +1655,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1535,6 +1675,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1610,6 +1760,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1722,6 +1882,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1782,6 +1952,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1842,6 +2022,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div>
@@ -1899,6 +2089,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1991,6 +2191,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2081,6 +2291,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2137,10 +2357,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onConnect"></a>
@@ -2156,10 +2375,11 @@
                 <p>Fired when a connection is made from either an extension process or a content script.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>port</var>
               <em>
@@ -2212,15 +2432,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2237,10 +2467,11 @@
                 <p>Fired when a connection is made from another extension.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>port</var>
               <em>
@@ -2293,15 +2524,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2318,10 +2559,11 @@
                 <p>Fired when a request is sent from either an extension process or a content script.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>request</var>
               <em>
@@ -2372,14 +2614,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>sender</var>
               <em>
@@ -2432,14 +2684,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>sendResponse</var>
               <em>
@@ -2490,15 +2752,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2515,10 +2787,11 @@
                 <p>Fired when a request is sent from another extension.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>request</var>
               <em>
@@ -2569,14 +2842,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>sender</var>
               <em>
@@ -2629,14 +2912,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>sendResponse</var>
               <em>
@@ -2687,15 +2980,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -2808,6 +3111,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2866,6 +3179,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2876,6 +3199,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2985,6 +3318,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3045,6 +3388,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3105,6 +3458,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3165,6 +3528,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3175,6 +3548,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3284,6 +3667,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3344,6 +3737,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3404,6 +3807,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3464,6 +3877,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3522,6 +3945,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3532,6 +3965,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/external_extensions.html b/chrome/common/extensions/docs/external_extensions.html
index 0ee2ed5..c566a62 100644
--- a/chrome/common/extensions/docs/external_extensions.html
+++ b/chrome/common/extensions/docs/external_extensions.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -295,7 +305,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -303,7 +313,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -627,8 +637,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -703,10 +713,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -724,14 +733,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/faq.html b/chrome/common/extensions/docs/faq.html
index 0e17982..245567f 100644
--- a/chrome/common/extensions/docs/faq.html
+++ b/chrome/common/extensions/docs/faq.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -731,8 +741,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -807,10 +817,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -828,14 +837,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/getstarted.html b/chrome/common/extensions/docs/getstarted.html
index 3adba4e..e45e814 100644
--- a/chrome/common/extensions/docs/getstarted.html
+++ b/chrome/common/extensions/docs/getstarted.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -289,7 +299,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -376,7 +386,6 @@
       by clicking the wrench icon
       <img src="images/toolsmenu.gif" width="29" height="29" alt="" style="margin-top:0">
       and choosing <b>Tools &gt; Extensions</b>.
-      (On Mac, use <b>Window &gt; Extensions</b>.)
       </li>
 
       <li>
@@ -515,8 +524,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -591,10 +600,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -612,14 +620,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/history.html b/chrome/common/extensions/docs/history.html
index e6be466..9b80f25 100644
--- a/chrome/common/extensions/docs/history.html
+++ b/chrome/common/extensions/docs/history.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-addUrl">addUrl</a>
@@ -299,7 +309,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onVisitRemoved">onVisitRemoved</a>
@@ -512,8 +522,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -632,6 +642,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -642,6 +662,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -763,6 +793,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -930,6 +970,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -988,6 +1038,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -998,6 +1058,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1058,6 +1128,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1224,6 +1304,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1234,6 +1324,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1401,6 +1501,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1411,6 +1521,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1471,6 +1591,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1570,6 +1700,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1706,6 +1846,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1764,6 +1914,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1822,6 +1982,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1880,6 +2050,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1890,6 +2070,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1950,6 +2140,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2049,6 +2249,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2074,10 +2284,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onVisitRemoved"></a>
@@ -2093,10 +2302,11 @@
                 <p>Fired when one or more URLs are removed from the history service.  When all visits have been removed the URL is purged from history.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>removed</var>
               <em>
@@ -2194,6 +2404,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2265,6 +2485,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2275,15 +2505,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2300,10 +2540,11 @@
                 <p>Fired when a URL is visited, providing the HistoryItem data for that URL.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>result</var>
               <em>
@@ -2356,15 +2597,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -2477,6 +2728,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2535,6 +2796,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2593,6 +2864,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2651,6 +2932,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2709,6 +3000,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2767,6 +3068,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2777,6 +3088,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2884,6 +3205,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2942,6 +3273,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3000,6 +3341,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3058,6 +3409,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3116,6 +3477,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3126,6 +3497,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/hosting.html b/chrome/common/extensions/docs/hosting.html
index 0a688fb..7210219 100644
--- a/chrome/common/extensions/docs/hosting.html
+++ b/chrome/common/extensions/docs/hosting.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -419,8 +429,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -495,10 +505,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -516,14 +525,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/i18n-messages.html b/chrome/common/extensions/docs/i18n-messages.html
index 3c85b6b..8dee90c 100644
--- a/chrome/common/extensions/docs/i18n-messages.html
+++ b/chrome/common/extensions/docs/i18n-messages.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -287,7 +297,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -295,7 +305,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -673,8 +683,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -749,10 +759,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -770,14 +779,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/i18n.html b/chrome/common/extensions/docs/i18n.html
index d5e3bb9..fc3351f 100644
--- a/chrome/common/extensions/docs/i18n.html
+++ b/chrome/common/extensions/docs/i18n.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -294,7 +304,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-getAcceptLanguages">getAcceptLanguages</a>
@@ -304,7 +314,7 @@
                     </ol>
                   </li>
                   <li style="display: none; ">
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -586,7 +596,7 @@
 </p>
 
 <pre>body {
-  <b>dir: __MSG_@@bidi_dir__;</b>
+  <b>direction: __MSG_@@bidi_dir__;</b>
 }
 
 div#header {
@@ -926,8 +936,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -1001,6 +1011,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1098,6 +1118,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1187,6 +1217,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1245,6 +1285,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1309,6 +1359,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1356,10 +1416,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup" style="display: none; ">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup" style="display: none; ">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -1377,14 +1436,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/idle.html b/chrome/common/extensions/docs/idle.html
index 1ab1b64..6ad4097 100644
--- a/chrome/common/extensions/docs/idle.html
+++ b/chrome/common/extensions/docs/idle.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-queryState">queryState</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onStateChanged">onStateChanged</a>
@@ -346,8 +356,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -420,6 +430,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -480,6 +500,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -568,6 +598,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -593,10 +633,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onStateChanged"></a>
@@ -612,10 +651,11 @@
                 <p>Fired when the browser changes to an active state.  Currently only reports the transition from idle to active.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>newState</var>
               <em>
@@ -668,15 +708,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/index.html b/chrome/common/extensions/docs/index.html
index 54cd32f..3888f88 100644
--- a/chrome/common/extensions/docs/index.html
+++ b/chrome/common/extensions/docs/index.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -441,8 +451,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -517,10 +527,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -538,14 +547,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/js/api_page_generator.js b/chrome/common/extensions/docs/js/api_page_generator.js
index 856d11a..185aafc 100644
--- a/chrome/common/extensions/docs/js/api_page_generator.js
+++ b/chrome/common/extensions/docs/js/api_page_generator.js
@@ -14,8 +14,13 @@
  *
  */
 
+var USE_DEVTOOLS_SCHEMA = /\.webInspector\.[^/]*\.html/.test(location.href);
 var API_TEMPLATE = "template/api_template.html";
-var SCHEMA = "../api/extension_api.json";
+var WEBKIT_PATH = "../../../../third_party/WebKit";
+var SCHEMA = USE_DEVTOOLS_SCHEMA ?
+    WEBKIT_PATH + "/Source/WebCore/inspector/front-end/ExtensionAPISchema.json"
+    : "../api/extension_api.json";
+var API_MODULE_PREFIX = USE_DEVTOOLS_SCHEMA ? "" : "chrome.";
 var SAMPLES = "samples.json";
 var REQUEST_TIMEOUT = 2000;
 
@@ -184,7 +189,7 @@
       }
       // This page is an api page. Setup types and apiDefinition.
       module = mod;
-      apiModuleName = "chrome." + module.namespace;
+      apiModuleName = API_MODULE_PREFIX + module.namespace;
       pageData.apiDefinition = module;
     }
 
@@ -433,11 +438,15 @@
 }
 
 function getModuleName() {
-  return "chrome." + module.namespace;
+  return API_MODULE_PREFIX + module.namespace;
 }
 
-function getFullyQualifiedFunctionName(func) {
-  return getModuleName() + "." + func.name;
+function getFullyQualifiedFunctionName(scope, func) {
+  return (getObjectName(scope) || getModuleName()) + "." + func.name;
+}
+
+function getObjectName(typeName) {
+  return typeName.charAt(0).toLowerCase() + typeName.substring(1);
 }
 
 function isExperimentalAPIPage() {
@@ -454,6 +463,10 @@
   return parameters[parameters.length - 1];
 }
 
+function getAnchorName(type, name, scope) {
+  return type + "-" + (scope ? scope + "-" : "") + name;
+}
+
 function shouldExpandObject(object) {
   return (object.type == "object" && object.properties);
 }
@@ -491,6 +504,8 @@
 }
 
 function getSignatureString(parameters) {
+  if (!parameters)
+    return "";
   var retval = [];
   parameters.forEach(function(param, i) {
     retval.push(getTypeName(param) + " " + param.name);
diff --git a/chrome/common/extensions/docs/management.html b/chrome/common/extensions/docs/management.html
index 149e27e..59e4e08 100644
--- a/chrome/common/extensions/docs/management.html
+++ b/chrome/common/extensions/docs/management.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-get">get</a>
@@ -283,7 +293,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onDisabled">onDisabled</a>
@@ -367,8 +377,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -441,6 +451,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -501,6 +521,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -589,6 +619,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -679,6 +719,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -778,6 +828,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -867,6 +927,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -927,6 +997,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1048,6 +1128,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1106,6 +1196,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1166,6 +1266,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1286,6 +1396,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1346,6 +1466,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1402,10 +1532,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onDisabled"></a>
@@ -1421,10 +1550,11 @@
                 <p>Fired when an app or extension has been disabled</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>info</var>
               <em>
@@ -1477,15 +1607,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1502,10 +1642,11 @@
                 <p>Fired when an app or extension has been enabled.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>info</var>
               <em>
@@ -1558,15 +1699,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1583,10 +1734,11 @@
                 <p>Fired when an app or extension has been installed.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>info</var>
               <em>
@@ -1639,15 +1791,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1664,10 +1826,11 @@
                 <p>Fired when an app or extension has been uninstalled.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>id</var>
               <em>
@@ -1718,15 +1881,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -1839,6 +2012,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1897,6 +2080,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1907,6 +2100,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2014,6 +2217,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2072,6 +2285,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2130,6 +2353,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2188,6 +2421,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2246,6 +2489,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2304,6 +2557,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2362,6 +2625,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2420,6 +2693,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2489,6 +2772,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2558,6 +2851,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2627,6 +2930,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2637,6 +2950,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/manifest.html b/chrome/common/extensions/docs/manifest.html
index 7f477f9..73f24dc 100644
--- a/chrome/common/extensions/docs/manifest.html
+++ b/chrome/common/extensions/docs/manifest.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -294,7 +304,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -302,7 +312,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -808,8 +818,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -884,10 +894,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -905,14 +914,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/match_patterns.html b/chrome/common/extensions/docs/match_patterns.html
index ddbc56b..46b1bb0 100644
--- a/chrome/common/extensions/docs/match_patterns.html
+++ b/chrome/common/extensions/docs/match_patterns.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -561,8 +571,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -637,10 +647,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -658,14 +667,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/messaging.html b/chrome/common/extensions/docs/messaging.html
index 19e683d..0fec286 100644
--- a/chrome/common/extensions/docs/messaging.html
+++ b/chrome/common/extensions/docs/messaging.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -295,7 +305,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -303,7 +313,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -627,8 +637,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -703,10 +713,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -724,14 +733,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/notifications.html b/chrome/common/extensions/docs/notifications.html
index 82c5e07..c2d1556 100644
--- a/chrome/common/extensions/docs/notifications.html
+++ b/chrome/common/extensions/docs/notifications.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -288,7 +298,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -296,7 +306,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -468,8 +478,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -544,10 +554,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -565,14 +574,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/npapi.html b/chrome/common/extensions/docs/npapi.html
index 8aad2ea..ef2d0b3 100644
--- a/chrome/common/extensions/docs/npapi.html
+++ b/chrome/common/extensions/docs/npapi.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -426,8 +436,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -502,10 +512,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -523,14 +532,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/omnibox.html b/chrome/common/extensions/docs/omnibox.html
index 6f7afa7..5da9484 100644
--- a/chrome/common/extensions/docs/omnibox.html
+++ b/chrome/common/extensions/docs/omnibox.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -274,7 +284,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li style="display: none; ">
                         <a href="#method-anchor">methodName</a>
@@ -284,7 +294,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onInputCancelled">onInputCancelled</a>
@@ -418,8 +428,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -602,6 +612,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -612,6 +632,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -668,10 +698,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onInputCancelled"></a>
@@ -687,14 +716,15 @@
                 <p>User has ended the keyword input session without accepting the input.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div style="display: none; ">
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -711,10 +741,11 @@
                 <p>User has changed what is typed into the omnibox.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>text</var>
               <em>
@@ -767,14 +798,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>suggest</var>
               <em>
@@ -825,6 +866,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div>
@@ -893,6 +944,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -905,9 +966,9 @@
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -924,10 +985,11 @@
                 <p>User has accepted what is typed into the omnibox.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>text</var>
               <em>
@@ -980,15 +1042,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -1005,14 +1077,15 @@
                 <p>User has started a keyword input session by typing the extension's keyword. This is guaranteed to be sent exactly once per input session, and before any onInputChanged events.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div style="display: none; ">
+                <div style="display: none; ">
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -1125,6 +1198,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1183,6 +1266,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1193,6 +1286,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/options.html b/chrome/common/extensions/docs/options.html
index 982032f..2dd3cd8 100644
--- a/chrome/common/extensions/docs/options.html
+++ b/chrome/common/extensions/docs/options.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -289,7 +299,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -417,8 +427,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -493,10 +503,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -514,14 +523,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/override.html b/chrome/common/extensions/docs/override.html
index bfa7e7d..f2aa1dd 100644
--- a/chrome/common/extensions/docs/override.html
+++ b/chrome/common/extensions/docs/override.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -289,7 +299,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -388,6 +398,11 @@
 manifest property.
 </p>
 
+<p class="note">
+<b>Note:</b>
+You cannot override the New Tab page in incognito windows.
+</p>
+
 <p>
 The following screenshots show the default New Tab page
 next to a custom New Tab page.
@@ -522,8 +537,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -598,10 +613,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -619,14 +633,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/overview.html b/chrome/common/extensions/docs/overview.html
index 49e7d8c..89a18cb 100644
--- a/chrome/common/extensions/docs/overview.html
+++ b/chrome/common/extensions/docs/overview.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -308,7 +318,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -316,7 +326,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -796,8 +806,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -872,10 +882,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -893,14 +902,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/packaging.html b/chrome/common/extensions/docs/packaging.html
index ccfa542..cf63a8b 100644
--- a/chrome/common/extensions/docs/packaging.html
+++ b/chrome/common/extensions/docs/packaging.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -288,7 +298,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -296,7 +306,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -508,8 +518,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -584,10 +594,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -605,14 +614,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/pageAction.html b/chrome/common/extensions/docs/pageAction.html
index f6d0ac4..6dc7c5c 100644
--- a/chrome/common/extensions/docs/pageAction.html
+++ b/chrome/common/extensions/docs/pageAction.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -288,7 +298,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-hide">hide</a>
@@ -304,7 +314,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onClicked">onClicked</a>
@@ -378,7 +388,7 @@
   "name": "My extension",
   ...
   <b>"page_action": {
-    "default_icon": "icons/foo.png", <em>// <b>required</b></em>
+    "default_icon": "icons/foo.png", <em>// optional</em>
     "default_title": "Do action",    <em>// optional; shown in tooltip</em>
     "default_popup": "popup.html"    <em>// optional</em>
   }</b>,
@@ -389,8 +399,8 @@
 
 <p>
 Like browser actions,
-page actions have an icon and
-can also have a tooltip and popup;
+page actions can have an icon,
+a tooltip, and popup;
 they can't have badges, however.
 In addition, page actions can appear and disappear.
 You can find information about icons, tooltips, and popups
@@ -427,15 +437,6 @@
     for features that make sense
     for most pages.
     Use <a href="browserAction.html">browser actions</a> instead.
-  </li><li><b>Do</b> use icons
-    that are slightly lighter weight
-    than <a href="browserAction.html#icon">browser action icons</a>.
-    Most icons that Chrome displays
-    in the location bar
-    are smaller than 19 pixels.
-    If the edge pixels are used,
-    they are usually only used
-    for a faint shadow.
   </li><li><b>Don't</b> constantly animate your icon.
     That's just annoying.
 </li></ul>
@@ -478,8 +479,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -551,6 +552,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -717,6 +728,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -775,6 +796,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -833,6 +864,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -891,6 +932,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -901,6 +952,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1067,6 +1128,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1125,6 +1196,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1135,6 +1216,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1301,6 +1392,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1359,6 +1460,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1369,6 +1480,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1488,6 +1609,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1544,10 +1675,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onClicked"></a>
@@ -1563,10 +1693,11 @@
                 <p>Fired when a page action icon is clicked.  This event will not fire if the page action has a popup.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tab</var>
               <em>
@@ -1619,15 +1750,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/permission_warnings.html b/chrome/common/extensions/docs/permission_warnings.html
index eb062e3..66b96dd 100644
--- a/chrome/common/extensions/docs/permission_warnings.html
+++ b/chrome/common/extensions/docs/permission_warnings.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -288,7 +298,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -296,7 +306,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -423,7 +433,7 @@
 <p>
 It can be surprising when adding a permission such as "tabs"
 results in the seemingly unrelated warning
-that the extension can access your browsing history.
+that the extension can access your browsing activity.
 The reason for the warning is that
 although the <code>chrome.tabs</code> API
 might be used only to open new tabs,
@@ -488,7 +498,24 @@
   </td>
   <td>
     <!-- HasEffectiveBrowsingHistoryPermission -->
-     "history" or "tabs" permission
+     "history" permission
+  </td>
+  <td>
+    <p>
+      The "history" permission is required by
+      <a href="history.html"><code>chrome.history</code></a>.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td style="font-weight:bold">
+    <!-- IDS_EXTENSION_PROMPT_WARNING_TABS -->
+    Your tabs and browsing activity
+  </td>
+  <td>
+    <!-- HasEffectiveBrowsingHistoryPermission -->
+     "tabs" permission
   </td>
   <td>
     <p>
@@ -496,15 +523,6 @@
       <a href="tabs.html"><code>chrome.tabs</code></a> and 
       <a href="windows.html"><code>chrome.windows</code></a> modules.
     </p>
-    <p>
-      The "history" permission is required by
-      <a href="history.html"><code>chrome.history</code></a>.
-    </p>
-    <p>
-      Adding "tabs" to an existing extension
-      that already has "history", or vice versa,
-      doesn't cause a warning when the extension is autoupdated.
-    </p>
   </td>
 </tr>
 
@@ -684,8 +702,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -760,10 +778,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -781,14 +798,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/samples.html b/chrome/common/extensions/docs/samples.html
index f51faa5..3e19c14 100644
--- a/chrome/common/extensions/docs/samples.html
+++ b/chrome/common/extensions/docs/samples.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -303,7 +313,7 @@
 
         <!-- STATIC CONTENT PLACEHOLDER -->
         <div id="static"><link rel="stylesheet" href="css/samples.css">
-<script>var search_data = {"0262260daf0c8f7b28feff2ef23b05e7abf9d1e0":"A BROWSER ACTION WHICH CHANGES ITS ICON WHEN CLICKED.  BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON","ea2894c41cb8e80a4433a3e6c5772dadce9be90d":"A BROWSER ACTION WITH A POPUP THAT CHANGES THE PAGE COLOR.  BROWSER_ACTION POPUP TABS CHROME.TABS.EXECUTESCRIPT","ede3c47b7757245be42ec33fd5ca63df4b490066":"A BROWSER ACTION WITH NO ICON THAT MAKES THE PAGE RED  BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.EXECUTESCRIPT","fbf0aa1a09a15ff8cc4fc7de4fd176d6c663d07a":"ACCEPTLANGUAGE RETURNS ACCEPT LANGUAGES OF THE BROWSER BROWSER_ACTION POPUP CHROME.I18N.GETACCEPTLANGUAGES CHROME.I18N.GETMESSAGE","9a6e4ec46997fb92b324974afa08a3d007e2537f":"ANIMATED PAGE ACTION THIS EXTENSION ADDS AN ANIMATED BROWSER ACTION TO THE TOOLBAR. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.ONCLICKED CHROME.PAGEACTION.SETICON CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED","a1f7cf79dd555b04fa8d603247a040e644996293":"APP LAUNCHER  BROWSER_ACTION MANAGEMENT CHROME.EXTENSION.GETURL CHROME.MANAGEMENT.GET CHROME.MANAGEMENT.GETALL CHROME.MANAGEMENT.LAUNCHAPP CHROME.TABS.CREATE","9747e3d6a3eab39bc7c17f11a80573c62d44c7e5":"BLANK NEW TAB PAGE  CHROME_URL_OVERRIDES","903e7277139e1e6caec123d3319cab295d8d1b3a":"CHROME SOUNDS ENJOY A MORE MAGICAL AND IMMERSIVE EXPERIENCE WHEN BROWSING THE WEB USING THE POWER OF SOUND. BACKGROUND_PAGE BOOKMARKS OPTIONS_PAGE TABS CHROME.BOOKMARKS.ONCREATED CHROME.BOOKMARKS.ONMOVED CHROME.BOOKMARKS.ONREMOVED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.TABS.GET CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED","0e790e035a4a00b6f1def5ef9a7d7be1bce95ab5":"CHROMIUM BUILDBOT MONITOR DISPLAYS THE STATUS OF THE CHROMIUM BUILDBOT IN THE TOOLBAR.  CLICK TO SEE MORE DETAILED STATUS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION NOTIFICATIONS OPTIONS_PAGE POPUP CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETURL","ac31228200b41a87982e386cc90d3a6eee4ad885":"CHROMIUM SEARCH ADD SUPPORT TO THE OMNIBOX TO SEARCH THE CHROMIUM SOURCE CODE. BACKGROUND_PAGE TABS CHROME.OMNIBOX.ONINPUTCANCELLED CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED CHROME.OMNIBOX.ONINPUTSTARTED CHROME.OMNIBOX.SETDEFAULTSUGGESTION CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE","7d5d6cf195bc25480256618e360aa38c6e6fba82":"CLD DISPLAYS THE LANGUAGE OF A TAB BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.DETECTLANGUAGE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED","5d81304a17cf7ac2887484f730fbd2b01e51e166":"CONTEXT MENUS SAMPLE SHOWS SOME OF THE FEATURES OF THE CONTEXT MENUS API BACKGROUND_PAGE CONTEXTMENUS CHROME.CONTEXTMENUS.CREATE","4daa6becd0899a54776d9cf7f09613ed1a9f4d77":"COOKIE API TEST EXTENSION TESTING COOKIE API BACKGROUND_PAGE BROWSER_ACTION COOKIES TABS CHROME.BROWSERACTION.ONCLICKED CHROME.COOKIES.GET CHROME.COOKIES.GETALL CHROME.COOKIES.ONCHANGED CHROME.COOKIES.REMOVE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL","6871d09f4a96bf9d4b6cc724d00e909cee0f3902":"CROSS-DOMAIN XMLHTTPREQUEST FROM A CONTENT SCRIPT DEMONSTRATES A METHOD TO MAKE A CROSS-DOMAIN XMLHTTPREQUEST FETCH FROM A CONTENT SCRIPT.  THIS EXTENSION FETCHES THE CURRENT TRENDING TOPICS FROM TWITTER AND INSERTS THEM IN AN OVERLAY AT THE TOP OF GOOGLE NEWS.  VISIT HTTP://NEWS.GOOGLE.COM TO TEST THIS EXTENSION. BACKGROUND_PAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","028eb5364924344029bcbe1d527f132fc72b34e5":"EMAIL THIS PAGE (BY GOOGLE) THIS EXTENSION ADDS AN EMAIL BUTTON TO THE TOOLBAR WHICH ALLOWS YOU TO EMAIL THE PAGE LINK USING YOUR DEFAULT MAIL CLIENT OR GMAIL. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.CONNECT CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.UPDATE","763a08e9b06595d785568a8d392b95a2f3700258":"EVENT TRACKING WITH GOOGLE ANALYTICS A SAMPLE EXTENSION WHICH USES GOOGLE ANALYTICS TO TRACK USAGE. BACKGROUND_PAGE BROWSER_ACTION POPUP","e3df888a89e35bdeb9c8bc8d03be5e1851b97c68":"EXTENSION DOCS SEARCH SEARCH THE CHROME EXTENSIONS DOCUMENTATION.  TO USE, TYPE CRDOC PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE TABS CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.ONREMOVED CHROME.TABS.UPDATE","8b0dd31216235941bdd8eb33fda915ef5cf79a82":"GOOGLE CALENDAR CHECKER (BY GOOGLE) QUICKLY SEE THE TIME UNTIL YOUR NEXT MEETING FROM ANY OF YOUR CALENDARS. CLICK ON THE BUTTON TO BE TAKEN TO YOUR CALENDAR. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE","4e35caa9742fb82dbd628892d23a781614f6eff6":"GOOGLE DOCUMENT LIST VIEWER DEMONSTRATES HOW TO USE OAUTH TO CONNECT THE GOOGLE DOCUMENTS LIST DATA API. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","bb57f7a0132cbeb36ad7e7bb0ab75c21704234ca":"GOOGLE MAIL CHECKER DISPLAYS THE NUMBER OF UNREAD MESSAGES IN YOUR GOOGLE MAIL INBOX. YOU CAN ALSO CLICK THE BUTTON TO OPEN YOUR INBOX. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE","1682e05ea9a1bde985123b04f6f8ac50a8a64033":"GOOGLE WAVE NOTIFIER FIND OUT WHEN YOU HAVE NEW WAVES AND PREVIEW THEM FAST. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","14b9651fda4e57b2a5914ba73a779812201b750a":"HELLO WORLD THE FIRST EXTENSION THAT I MADE. BROWSER_ACTION POPUP","2020d72f2577f53caf8e94e3dbac0fb849ceaa4d":"IDLE - SIMPLE EXAMPLE DEMONSTRATES THE IDLE API BACKGROUND_PAGE BROWSER_ACTION IDLE CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.IDLE.ONSTATECHANGED CHROME.IDLE.QUERYSTATE","0ea1588bd07b20338fc21f725de1542a5fdf9726":"IGOOGLE NEW TAB PAGE  CHROME_URL_OVERRIDES","646325c25f572a1d15edc73d057f821d847a4fbe":"IMAGEINFO GET IMAGE INFO FOR IMAGES, INCLUDING EXIF DATA BACKGROUND_PAGE CONTEXTMENUS TABS CHROME.CONTEXTMENUS.CREATE CHROME.TABS.GET CHROME.TABS.GETCURRENT CHROME.WINDOWS.CREATE CHROME.WINDOWS.UPDATE","ec97ec20ca2f095d081e39f1565fc12af09ef067":"MAPPY FINDS ADDRESSES IN THE WEB PAGE YOURE ON AND POPS UP A MAP WINDOW. BACKGROUND_PAGE PAGE_ACTION POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.SENDREQUEST","b2f5f8a790e16f091a7e4e0a39b2d0a6d32e3a6d":"MERGE WINDOWS MERGES ALL OF THE BROWSERS WINDOWS INTO THE CURRENT WINDOW BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.MOVE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT","51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e":"MESSAGE TIMER TIMES HOW LONG IT TAKES TO SEND A MESSAGE TO A CONTENT SCRIPT AND BACK. BROWSER_ACTION POPUP TABS CHROME.EXTENSION.ONCONNECT CHROME.EXTENSION.ONREQUEST CHROME.TABS.CONNECT CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.SENDREQUEST","4f6785ec4f937add6728615682dd37c9a42d9548":"MY BOOKMARKS A BROWSER ACTION WITH A POPUP DUMP OF ALL BOOKMARKS, INCLUDING SEARCH, ADD, EDIT AND DELETE. BOOKMARKS BROWSER_ACTION POPUP TABS CHROME.BOOKMARKS.CREATE CHROME.BOOKMARKS.GET CHROME.BOOKMARKS.GETTREE CHROME.BOOKMARKS.REMOVE CHROME.BOOKMARKS.UPDATE CHROME.TABS.CREATE","597015d3bcce3da693b02314afd607bec4f55291":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE","6444e5c8ae112a6a433909c5e770669cd16e2e5f":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE","3aea027164cb9b732ba4a8c51cb93708891726ef":"NEWS READER (BY GOOGLE) DISPLAYS THE LATEST STORIES FROM GOOGLE NEWS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETURL CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE","f799e26ceef2367cf836f24bcb47df4398b0df58":"NOTIFICATION DEMO SHOWS OFF DESKTOP NOTIFICATIONS, WHICH ARE TOAST WINDOWS THAT POP UP ON THE DESKTOP. BACKGROUND_PAGE NOTIFICATIONS OPTIONS_PAGE TABS CHROME.TABS.CREATE","e787b322bddbc6289bb31b7d7550b1bf6456a80b":"OMNIBOX EXAMPLE TO USE, TYPE OMNIX PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED","8d0a50b57c26bb498be592e871001ffed91541b4":"PAGE ACTION BY CONTENT SHOWS A PAGE ACTION FOR HTML PAGES CONTAINING THE WORD SANDWICH BACKGROUND_PAGE PAGE_ACTION CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.PAGEACTION.SHOW","80b86ccc6e8520660fa591caa565826f0ed1b12c":"PAGE ACTION BY URL SHOWS A PAGE ACTION FOR URLS WHICH HAVE THE LETTER G IN THEM. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.SHOW CHROME.TABS.ONUPDATED","d74c3c18a1c1dd18b035149105a306f837c8823e":"PAGE BENCHMARKER CHROMIUM PAGE BENCHMARKER. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.CONNECT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETEXTENSIONTABS CHROME.EXTENSION.GETURL CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETCURRENT","e6ae17ab4ccfd7e059c8c01f25760ca5d894c7fd":"PRINT THIS PAGE ADDS A PRINT BUTTON TO THE BROWSER. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.UPDATE","beff6ecd9677dea0a7c648c5042165b48bb66f09":"PROCESS MONITOR ADDS A BROWSER ACTION THAT MONITORS RESOURCE USAGE OF ALL BROWSER PROCESSES. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.ONUPDATED","56a8d2ac24ca7bba78fd88ad57f43fc13c784497":"SAMPLE - OAUTH CONTACTS USES OAUTH TO CONNECT TO GOOGLES CONTACTS SERVICE AND DISPLAY A LIST OF YOUR CONTACTS. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","38f6e1e17756ede38b1364c7114a738ca717dcbb":"SANDWICHBAR SHOWS AN INFOBAR ON PAGES WHICH CONTAIN THE WORD SANDWICH BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.INFOBARS.SHOW CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","fc89b35755483af30b66cd72cefa34a43a3e8312":"SHOW TABS IN PROCESS ADDS A BROWSER ACTION SHOWING WHICH TABS SHARE THE CURRENT TABS PROCESS. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.GETPROCESSIDFORTAB CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.UPDATE","230463f2d5c3d4d0ca13c230e1f00f2aae0a8a64":"TAB INSPECTOR UTILITY FOR WORKING WITH THE EXTENSION TABS API BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.MOVE CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.CREATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.GETLASTFOCUSED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED CHROME.WINDOWS.REMOVE CHROME.WINDOWS.UPDATE","e1697cacebad05218798bf3e8a0f724517f0e8c3":"TEST SCREENSHOT EXTENSION DEMONSTRATE SCREENSHOT FUNCTIONALITY IN THE CHROME.TABS API. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.EXTENSION.GETVIEWS CHROME.TABS.CAPTUREVISIBLETAB CHROME.TABS.CREATE CHROME.TABS.ONUPDATED","b3de91ab04b7d7a2670ca7ee9d740eb42cead0b6":"TYPED URL HISTORY READS YOUR HISTORY, AND SHOWS THE TOP TEN PAGES YOU GO TO BY TYPING THE URL. BROWSER_ACTION HISTORY TABS CHROME.HISTORY.GETVISITS CHROME.HISTORY.SEARCH CHROME.TABS.CREATE"}</script>
+<script>var search_data = {"4da084813a9c0f3de28821a1c8d2504f5f7bcbad":"A BROWSER ACTION WHICH CHANGES ITS ICON WHEN CLICKED.  BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON","0569ec913dfd1aa4fad58fff04af99b0de7ec4b6":"A BROWSER ACTION WITH A POPUP THAT CHANGES THE PAGE COLOR.  BROWSER_ACTION POPUP TABS CHROME.TABS.EXECUTESCRIPT","a02f64d5e8c8f96efb45b26c11bfa2320deddd36":"A BROWSER ACTION WITH NO ICON THAT MAKES THE PAGE RED  BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.EXECUTESCRIPT","ebed3a237b5606a154cfc0e6326821154607d388":"ACCEPTLANGUAGE RETURNS ACCEPT LANGUAGES OF THE BROWSER BROWSER_ACTION POPUP CHROME.I18N.GETACCEPTLANGUAGES CHROME.I18N.GETMESSAGE","2f7777c80368bb0a8caf057dffaadd5feed7e9ee":"ANIMATED PAGE ACTION THIS EXTENSION ADDS AN ANIMATED BROWSER ACTION TO THE TOOLBAR. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.ONCLICKED CHROME.PAGEACTION.SETICON CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED","4da5aeb0840b36af753e694f2e81c90620494688":"APP LAUNCHER  BROWSER_ACTION MANAGEMENT CHROME.EXTENSION.GETURL CHROME.MANAGEMENT.GET CHROME.MANAGEMENT.GETALL CHROME.MANAGEMENT.LAUNCHAPP CHROME.TABS.CREATE","63349d2a4f5ec8f315a05fc9b1cab181ad546fd2":"BLANK NEW TAB PAGE  CHROME_URL_OVERRIDES","4c45b5015d2ca5f9053514ac70ff3acc3bca1f76":"CHROME SOUNDS ENJOY A MORE MAGICAL AND IMMERSIVE EXPERIENCE WHEN BROWSING THE WEB USING THE POWER OF SOUND. BACKGROUND_PAGE BOOKMARKS OPTIONS_PAGE TABS CHROME.BOOKMARKS.ONCREATED CHROME.BOOKMARKS.ONMOVED CHROME.BOOKMARKS.ONREMOVED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.TABS.GET CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED","2f41f968c8b6ddfc078363e305d2b530802a11dd":"CHROMIUM BUILDBOT MONITOR DISPLAYS THE STATUS OF THE CHROMIUM BUILDBOT IN THE TOOLBAR.  CLICK TO SEE MORE DETAILED STATUS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION NOTIFICATIONS OPTIONS_PAGE POPUP CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETURL","32ff053c4a55b305243c83756304ca7c9d135ed0":"CHROMIUM SEARCH ADD SUPPORT TO THE OMNIBOX TO SEARCH THE CHROMIUM SOURCE CODE. BACKGROUND_PAGE TABS CHROME.OMNIBOX.ONINPUTCANCELLED CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED CHROME.OMNIBOX.ONINPUTSTARTED CHROME.OMNIBOX.SETDEFAULTSUGGESTION CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE","6484bb796d9aef70aa1026c0edc0799bc7a48b68":"CLD DISPLAYS THE LANGUAGE OF A TAB BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.DETECTLANGUAGE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED","8818cf9ded850b5f0ba7348127526eb00165f202":"CONTEXT MENUS SAMPLE SHOWS SOME OF THE FEATURES OF THE CONTEXT MENUS API BACKGROUND_PAGE CONTEXTMENUS CHROME.CONTEXTMENUS.CREATE","ba79d21d1e9a1cf5edebc246b11f667406cb001f":"COOKIE API TEST EXTENSION TESTING COOKIE API BACKGROUND_PAGE BROWSER_ACTION COOKIES TABS CHROME.BROWSERACTION.ONCLICKED CHROME.COOKIES.GET CHROME.COOKIES.GETALL CHROME.COOKIES.ONCHANGED CHROME.COOKIES.REMOVE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL","b6ab1c298a1c1f939b393f36868c937391502112":"CROSS-DOMAIN XMLHTTPREQUEST FROM A CONTENT SCRIPT DEMONSTRATES A METHOD TO MAKE A CROSS-DOMAIN XMLHTTPREQUEST FETCH FROM A CONTENT SCRIPT.  THIS EXTENSION FETCHES THE CURRENT TRENDING TOPICS FROM TWITTER AND INSERTS THEM IN AN OVERLAY AT THE TOP OF GOOGLE NEWS.  VISIT HTTP://NEWS.GOOGLE.COM TO TEST THIS EXTENSION. BACKGROUND_PAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","fad4ea2189bbcce1d2669a409ed296b10ec8b7c9":"EMAIL THIS PAGE (BY GOOGLE) THIS EXTENSION ADDS AN EMAIL BUTTON TO THE TOOLBAR WHICH ALLOWS YOU TO EMAIL THE PAGE LINK USING YOUR DEFAULT MAIL CLIENT OR GMAIL. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.CONNECT CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.UPDATE","26af638d88737474bed3837343caa13f3b924615":"EVENT TRACKING WITH GOOGLE ANALYTICS A SAMPLE EXTENSION WHICH USES GOOGLE ANALYTICS TO TRACK USAGE. BACKGROUND_PAGE BROWSER_ACTION POPUP","97c797be0add2ec9ce72747b1ecdbd9b80bc73d9":"EXTENSION DOCS SEARCH SEARCH THE CHROME EXTENSIONS DOCUMENTATION.  TO USE, TYPE CRDOC PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE TABS CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.ONREMOVED CHROME.TABS.UPDATE","f802b3cce3b05de17dddd7ccfb3394d70f0ba1b5":"GOOGLE CALENDAR CHECKER (BY GOOGLE) QUICKLY SEE THE TIME UNTIL YOUR NEXT MEETING FROM ANY OF YOUR CALENDARS. CLICK ON THE BUTTON TO BE TAKEN TO YOUR CALENDAR. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE","e83ae8cea73dfe87e420a9dac5e2906d795263cc":"GOOGLE DOCUMENT LIST VIEWER DEMONSTRATES HOW TO USE OAUTH TO CONNECT THE GOOGLE DOCUMENTS LIST DATA API. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","8ad6dbf5f536e3181945cd352930da9cc159dc71":"GOOGLE MAIL CHECKER DISPLAYS THE NUMBER OF UNREAD MESSAGES IN YOUR GOOGLE MAIL INBOX. YOU CAN ALSO CLICK THE BUTTON TO OPEN YOUR INBOX. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE","56529b7cbd67869d7fcebd6d46c3efddfe7b598f":"GOOGLE WAVE NOTIFIER FIND OUT WHEN YOU HAVE NEW WAVES AND PREVIEW THEM FAST. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","6deee0c2a7dbdd62a80deb526005814fa37e6556":"HELLO WORLD THE FIRST EXTENSION THAT I MADE. BROWSER_ACTION POPUP","f0f5a81e76c7b29f8d13543dafd728285ecc96d7":"IDLE - SIMPLE EXAMPLE DEMONSTRATES THE IDLE API BACKGROUND_PAGE BROWSER_ACTION IDLE CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.IDLE.ONSTATECHANGED CHROME.IDLE.QUERYSTATE","6e8555409ac09df65620a4f1651e9f283983eec5":"IGOOGLE NEW TAB PAGE  CHROME_URL_OVERRIDES","e08426e68f327ea625937f4668b89da16da0e467":"IMAGEINFO GET IMAGE INFO FOR IMAGES, INCLUDING EXIF DATA BACKGROUND_PAGE CONTEXTMENUS TABS CHROME.CONTEXTMENUS.CREATE CHROME.TABS.GET CHROME.TABS.GETCURRENT CHROME.WINDOWS.CREATE CHROME.WINDOWS.UPDATE","5c7def7e0a26bac297128161b2bb9b2fc279985b":"MAPPY FINDS ADDRESSES IN THE WEB PAGE YOURE ON AND POPS UP A MAP WINDOW. BACKGROUND_PAGE PAGE_ACTION POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.SENDREQUEST","d72b4e8576fb00ad176957738099c930cffcfb9e":"MERGE WINDOWS MERGES ALL OF THE BROWSERS WINDOWS INTO THE CURRENT WINDOW BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.MOVE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT","af975d20117c15a36dff66ef5a1ebca92f653969":"MESSAGE TIMER TIMES HOW LONG IT TAKES TO SEND A MESSAGE TO A CONTENT SCRIPT AND BACK. BROWSER_ACTION POPUP TABS CHROME.EXTENSION.ONCONNECT CHROME.EXTENSION.ONREQUEST CHROME.TABS.CONNECT CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.SENDREQUEST","7772f091557a50889effa6e5b19e83b4cf80399b":"MY BOOKMARKS A BROWSER ACTION WITH A POPUP DUMP OF ALL BOOKMARKS, INCLUDING SEARCH, ADD, EDIT AND DELETE. BOOKMARKS BROWSER_ACTION POPUP TABS CHROME.BOOKMARKS.CREATE CHROME.BOOKMARKS.GET CHROME.BOOKMARKS.GETTREE CHROME.BOOKMARKS.REMOVE CHROME.BOOKMARKS.UPDATE CHROME.TABS.CREATE","28c933f585b0903a56f9a16658aa26cf61f9da0f":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE","80e7eac29801029c81ecaabb7c7021bbd0ceea88":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE","e9e5f15da193c45aad4d49ced748dfbbd6c904b3":"NEWS READER (BY GOOGLE) DISPLAYS THE LATEST STORIES FROM GOOGLE NEWS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETURL CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE","324e557c216dd6edbeb0112ed53d55a05b5e6112":"NOTIFICATION DEMO SHOWS OFF DESKTOP NOTIFICATIONS, WHICH ARE TOAST WINDOWS THAT POP UP ON THE DESKTOP. BACKGROUND_PAGE NOTIFICATIONS OPTIONS_PAGE TABS CHROME.TABS.CREATE","85a9f4cfd3645dfc4d1d90cc559261b689803626":"OMNIBOX EXAMPLE TO USE, TYPE OMNIX PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED","56bbb002845c9ada93807b2f83d51447adf146fd":"PAGE ACTION BY CONTENT SHOWS A PAGE ACTION FOR HTML PAGES CONTAINING THE WORD SANDWICH BACKGROUND_PAGE PAGE_ACTION CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.PAGEACTION.SHOW","65afad56921c30f207a30f5ecf929e06b712f552":"PAGE ACTION BY URL SHOWS A PAGE ACTION FOR URLS WHICH HAVE THE LETTER G IN THEM. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.SHOW CHROME.TABS.ONUPDATED","7446de67bf18dc34b5ff0fb4e1d9d7d166339bb9":"PAGE BENCHMARKER CHROMIUM PAGE BENCHMARKER. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.CONNECT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETEXTENSIONTABS CHROME.EXTENSION.GETURL CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETCURRENT","a9ea9e35b2e9990e488afeb97407655ea14fc8dc":"PRINT THIS PAGE ADDS A PRINT BUTTON TO THE BROWSER. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.UPDATE","455ec3784d8094b318eac572bc092ec07c5286b0":"PROCESS MONITOR ADDS A BROWSER ACTION THAT MONITORS RESOURCE USAGE OF ALL BROWSER PROCESSES. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.ONUPDATED","545d6989740a0e7f57a9751c2ebc0e250053a08f":"SAMPLE - OAUTH CONTACTS USES OAUTH TO CONNECT TO GOOGLES CONTACTS SERVICE AND DISPLAY A LIST OF YOUR CONTACTS. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","39a3d4c4282ee5090652938decfb6df79b626151":"SANDWICHBAR SHOWS AN INFOBAR ON PAGES WHICH CONTAIN THE WORD SANDWICH BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.INFOBARS.SHOW CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","364415e46171be6479a095b214eab9783a4648d2":"SHOW TABS IN PROCESS ADDS A BROWSER ACTION SHOWING WHICH TABS SHARE THE CURRENT TABS PROCESS. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.GETPROCESSIDFORTAB CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.UPDATE","ad0d399dfc6d92af6ee9b759d7792a0d0bb85370":"TAB INSPECTOR UTILITY FOR WORKING WITH THE EXTENSION TABS API BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.MOVE CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.CREATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.GETLASTFOCUSED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED CHROME.WINDOWS.REMOVE CHROME.WINDOWS.UPDATE","1e28bcf89e80466f155ab3a01a76cf5f60cb4104":"TEST SCREENSHOT EXTENSION DEMONSTRATE SCREENSHOT FUNCTIONALITY IN THE CHROME.TABS API. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.EXTENSION.GETVIEWS CHROME.TABS.CAPTUREVISIBLETAB CHROME.TABS.CREATE CHROME.TABS.ONUPDATED","7b375c0f2c88517b42a5a341ac77e0762b481233":"TYPED URL HISTORY READS YOUR HISTORY, AND SHOWS THE TOP TEN PAGES YOU GO TO BY TYPING THE URL. BROWSER_ACTION HISTORY TABS CHROME.HISTORY.GETVISITS CHROME.HISTORY.SEARCH CHROME.TABS.CREATE"}</script>
 <script src="js/sample_search.js"></script>
 
 
@@ -351,11 +361,11 @@
   </div>
 </div>
 
-<div class="sample" id="0262260daf0c8f7b28feff2ef23b05e7abf9d1e0">
+<div class="sample" id="4da084813a9c0f3de28821a1c8d2504f5f7bcbad">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#0262260daf0c8f7b28feff2ef23b05e7abf9d1e0">A browser action which changes its icon when clicked.</a>
+    <a href="#4da084813a9c0f3de28821a1c8d2504f5f7bcbad">A browser action which changes its icon when clicked.</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -382,21 +392,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\set_icon_path\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\set_icon_path\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/">Browse source</a>
-    - <a href="examples/api/browserAction/set_icon_path.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\set_icon_path\">Browse source</a>
+    - <a href="examples\api\browserAction\set_icon_path.zip">Download source</a>
   </div>
-</div><div class="sample" id="ea2894c41cb8e80a4433a3e6c5772dadce9be90d">
+</div><div class="sample" id="0569ec913dfd1aa4fad58fff04af99b0de7ec4b6">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#ea2894c41cb8e80a4433a3e6c5772dadce9be90d">A browser action with a popup that changes the page color.</a>
+    <a href="#0569ec913dfd1aa4fad58fff04af99b0de7ec4b6">A browser action with a popup that changes the page color.</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -421,21 +431,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\set_page_color\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\set_page_color\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/">Browse source</a>
-    - <a href="examples/api/browserAction/set_page_color.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\set_page_color\">Browse source</a>
+    - <a href="examples\api\browserAction\set_page_color.zip">Download source</a>
   </div>
-</div><div class="sample" id="ede3c47b7757245be42ec33fd5ca63df4b490066">
+</div><div class="sample" id="a02f64d5e8c8f96efb45b26c11bfa2320deddd36">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#ede3c47b7757245be42ec33fd5ca63df4b490066">A browser action with no icon that makes the page red</a>
+    <a href="#a02f64d5e8c8f96efb45b26c11bfa2320deddd36">A browser action with no icon that makes the page red</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -466,21 +476,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\make_page_red\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\make_page_red\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/">Browse source</a>
-    - <a href="examples/api/browserAction/make_page_red.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\make_page_red\">Browse source</a>
+    - <a href="examples\api\browserAction\make_page_red.zip">Download source</a>
   </div>
-</div><div class="sample" id="fbf0aa1a09a15ff8cc4fc7de4fd176d6c663d07a">
+</div><div class="sample" id="ebed3a237b5606a154cfc0e6326821154607d388">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#fbf0aa1a09a15ff8cc4fc7de4fd176d6c663d07a">AcceptLanguage</a>
+    <a href="#ebed3a237b5606a154cfc0e6326821154607d388">AcceptLanguage</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -504,27 +514,27 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json?content-type=text/plain">_locales/en_US/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\getMessage\_locales\en_US\messages.json?content-type=text/plain">_locales\en_US\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json?content-type=text/plain">_locales/es/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\getMessage\_locales\es\messages.json?content-type=text/plain">_locales\es\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json?content-type=text/plain">_locales/sr/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\getMessage\_locales\sr\messages.json?content-type=text/plain">_locales\sr\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\getMessage\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\getMessage\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/getMessage/">Browse source</a>
-    - <a href="examples/api/i18n/getMessage.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\getMessage\">Browse source</a>
+    - <a href="examples\api\i18n\getMessage.zip">Download source</a>
   </div>
-</div><div class="sample" id="9a6e4ec46997fb92b324974afa08a3d007e2537f">
+</div><div class="sample" id="2f7777c80368bb0a8caf057dffaadd5feed7e9ee">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#9a6e4ec46997fb92b324974afa08a3d007e2537f">Animated Page Action</a>
+    <a href="#2f7777c80368bb0a8caf057dffaadd5feed7e9ee">Animated Page Action</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -563,21 +573,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\set_icon\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\set_icon\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/set_icon/">Browse source</a>
-    - <a href="examples/api/pageAction/set_icon.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\set_icon\">Browse source</a>
+    - <a href="examples\api\pageAction\set_icon.zip">Download source</a>
   </div>
-</div><div class="sample" id="a1f7cf79dd555b04fa8d603247a040e644996293">
+</div><div class="sample" id="4da5aeb0840b36af753e694f2e81c90620494688">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#a1f7cf79dd555b04fa8d603247a040e644996293">App Launcher</a>
+    <a href="#4da5aeb0840b36af753e694f2e81c90620494688">App Launcher</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -607,25 +617,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/app_launcher/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\app_launcher\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.css?content-type=text/plain">popup.css</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\app_launcher\popup.css?content-type=text/plain">popup.css</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\app_launcher\popup.html?content-type=text/plain">popup.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.js?content-type=text/plain">popup.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\app_launcher\popup.js?content-type=text/plain">popup.js</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/app_launcher/">Browse source</a>
-    - <a href="examples/extensions/app_launcher.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\app_launcher\">Browse source</a>
+    - <a href="examples\extensions\app_launcher.zip">Download source</a>
   </div>
-</div><div class="sample" id="9747e3d6a3eab39bc7c17f11a80573c62d44c7e5">
+</div><div class="sample" id="63349d2a4f5ec8f315a05fc9b1cab181ad546fd2">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#9747e3d6a3eab39bc7c17f11a80573c62d44c7e5">Blank new tab page</a>
+    <a href="#63349d2a4f5ec8f315a05fc9b1cab181ad546fd2">Blank new tab page</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -644,21 +654,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html?content-type=text/plain">blank.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\override\blank_ntp\blank.html?content-type=text/plain">blank.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\override\blank_ntp\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/override/blank_ntp/">Browse source</a>
-    - <a href="examples/api/override/blank_ntp.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\override\blank_ntp\">Browse source</a>
+    - <a href="examples\api\override\blank_ntp.zip">Download source</a>
   </div>
-</div><div class="sample" id="903e7277139e1e6caec123d3319cab295d8d1b3a">
-  <img class="icon" src="examples/extensions/fx/icon.png">
+</div><div class="sample" id="4c45b5015d2ca5f9053514ac70ff3acc3bca1f76">
+  <img class="icon" src="examples\extensions\fx\icon.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#903e7277139e1e6caec123d3319cab295d8d1b3a">Chrome Sounds</a>
+    <a href="#4c45b5015d2ca5f9053514ac70ff3acc3bca1f76">Chrome Sounds</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -718,27 +728,27 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/fx/bg.html?content-type=text/plain">bg.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\fx\bg.html?content-type=text/plain">bg.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/fx/bg.js?content-type=text/plain">bg.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\fx\bg.js?content-type=text/plain">bg.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/fx/content.js?content-type=text/plain">content.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\fx\content.js?content-type=text/plain">content.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/fx/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\fx\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/fx/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\fx\options.html?content-type=text/plain">options.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/fx/">Browse source</a>
-    - <a href="examples/extensions/fx.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\fx\">Browse source</a>
+    - <a href="examples\extensions\fx.zip">Download source</a>
   </div>
-</div><div class="sample" id="0e790e035a4a00b6f1def5ef9a7d7be1bce95ab5">
-  <img class="icon" src="examples/extensions/buildbot/icon.png">
+</div><div class="sample" id="2f41f968c8b6ddfc078363e305d2b530802a11dd">
+  <img class="icon" src="examples\extensions\buildbot\icon.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#0e790e035a4a00b6f1def5ef9a7d7be1bce95ab5">Chromium Buildbot Monitor</a>
+    <a href="#2f41f968c8b6ddfc078363e305d2b530802a11dd">Chromium Buildbot Monitor</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -775,25 +785,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/buildbot/bg.html?content-type=text/plain">bg.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\buildbot\bg.html?content-type=text/plain">bg.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/buildbot/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\buildbot\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/buildbot/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\buildbot\options.html?content-type=text/plain">options.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/buildbot/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\buildbot\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/buildbot/">Browse source</a>
-    - <a href="examples/extensions/buildbot.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\buildbot\">Browse source</a>
+    - <a href="examples\extensions\buildbot.zip">Download source</a>
   </div>
-</div><div class="sample" id="ac31228200b41a87982e386cc90d3a6eee4ad885">
+</div><div class="sample" id="32ff053c4a55b305243c83756304ca7c9d135ed0">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#ac31228200b41a87982e386cc90d3a6eee4ad885">Chromium Search</a>
+    <a href="#32ff053c4a55b305243c83756304ca7c9d135ed0">Chromium Search</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -829,21 +839,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/chrome_search/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\chrome_search\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\chrome_search\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/chrome_search/">Browse source</a>
-    - <a href="examples/extensions/chrome_search.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\chrome_search\">Browse source</a>
+    - <a href="examples\extensions\chrome_search.zip">Download source</a>
   </div>
-</div><div class="sample" id="7d5d6cf195bc25480256618e360aa38c6e6fba82">
+</div><div class="sample" id="6484bb796d9aef70aa1026c0edc0799bc7a48b68">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#7d5d6cf195bc25480256618e360aa38c6e6fba82">CLD</a>
+    <a href="#6484bb796d9aef70aa1026c0edc0799bc7a48b68">CLD</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -878,21 +888,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/cld/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\cld\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\cld\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/cld/">Browse source</a>
-    - <a href="examples/api/i18n/cld.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\i18n\cld\">Browse source</a>
+    - <a href="examples\api\i18n\cld.zip">Download source</a>
   </div>
-</div><div class="sample" id="5d81304a17cf7ac2887484f730fbd2b01e51e166">
+</div><div class="sample" id="8818cf9ded850b5f0ba7348127526eb00165f202">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#5d81304a17cf7ac2887484f730fbd2b01e51e166">Context Menus Sample</a>
+    <a href="#8818cf9ded850b5f0ba7348127526eb00165f202">Context Menus Sample</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -914,23 +924,23 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/contextMenus/basic/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\contextMenus\basic\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\contextMenus\basic\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js?content-type=text/plain">sample.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\contextMenus\basic\sample.js?content-type=text/plain">sample.js</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/contextMenus/basic/">Browse source</a>
-    - <a href="examples/api/contextMenus/basic.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\contextMenus\basic\">Browse source</a>
+    - <a href="examples\api\contextMenus\basic.zip">Download source</a>
   </div>
-</div><div class="sample" id="4daa6becd0899a54776d9cf7f09613ed1a9f4d77">
-  <img class="icon" src="examples/api/cookies/cookie.png">
+</div><div class="sample" id="ba79d21d1e9a1cf5edebc246b11f667406cb001f">
+  <img class="icon" src="examples\api\cookies\cookie.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#4daa6becd0899a54776d9cf7f09613ed1a9f4d77">Cookie API Test Extension</a>
+    <a href="#ba79d21d1e9a1cf5edebc246b11f667406cb001f">Cookie API Test Extension</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -976,23 +986,23 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/cookies/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\cookies\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/cookies/manager.html?content-type=text/plain">manager.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\cookies\manager.html?content-type=text/plain">manager.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/cookies/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\cookies\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/cookies/">Browse source</a>
-    - <a href="examples/api/cookies.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\cookies\">Browse source</a>
+    - <a href="examples\api\cookies.zip">Download source</a>
   </div>
-</div><div class="sample" id="6871d09f4a96bf9d4b6cc724d00e909cee0f3902">
-  <img class="icon" src="examples/howto/contentscript_xhr/sample-128.png">
+</div><div class="sample" id="b6ab1c298a1c1f939b393f36868c937391502112">
+  <img class="icon" src="examples\howto\contentscript_xhr\sample-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#6871d09f4a96bf9d4b6cc724d00e909cee0f3902">Cross-domain XMLHttpRequest from a content script</a>
+    <a href="#b6ab1c298a1c1f939b393f36868c937391502112">Cross-domain XMLHttpRequest from a content script</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1013,23 +1023,23 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\howto\contentscript_xhr\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr/contentscript.js?content-type=text/plain">contentscript.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\howto\contentscript_xhr\contentscript.js?content-type=text/plain">contentscript.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\howto\contentscript_xhr\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr/">Browse source</a>
-    - <a href="examples/howto/contentscript_xhr.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\howto\contentscript_xhr\">Browse source</a>
+    - <a href="examples\howto\contentscript_xhr.zip">Download source</a>
   </div>
-</div><div class="sample" id="028eb5364924344029bcbe1d527f132fc72b34e5">
-  <img class="icon" src="examples/extensions/email_this_page/mail_128x128.png">
+</div><div class="sample" id="fad4ea2189bbcce1d2669a409ed296b10ec8b7c9">
+  <img class="icon" src="examples\extensions\email_this_page\mail_128x128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#028eb5364924344029bcbe1d527f132fc72b34e5">Email this page (by Google)</a>
+    <a href="#fad4ea2189bbcce1d2669a409ed296b10ec8b7c9">Email this page (by Google)</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1067,25 +1077,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/email_this_page/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\email_this_page\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/email_this_page/content_script.js?content-type=text/plain">content_script.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\email_this_page\content_script.js?content-type=text/plain">content_script.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/email_this_page/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\email_this_page\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/email_this_page/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\email_this_page\options.html?content-type=text/plain">options.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/email_this_page/">Browse source</a>
-    - <a href="examples/extensions/email_this_page.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\email_this_page\">Browse source</a>
+    - <a href="examples\extensions\email_this_page.zip">Download source</a>
   </div>
-</div><div class="sample" id="763a08e9b06595d785568a8d392b95a2f3700258">
-  <img class="icon" src="examples/tutorials/analytics/analytics-extension-icon-128.png">
+</div><div class="sample" id="26af638d88737474bed3837343caa13f3b924615">
+  <img class="icon" src="examples\tutorials\analytics\analytics-extension-icon-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#763a08e9b06595d785568a8d392b95a2f3700258">Event Tracking with Google Analytics</a>
+    <a href="#26af638d88737474bed3837343caa13f3b924615">Event Tracking with Google Analytics</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1110,25 +1120,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/analytics/analytics.js?content-type=text/plain">analytics.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\analytics\analytics.js?content-type=text/plain">analytics.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/analytics/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\analytics\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/analytics/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\analytics\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/analytics/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\analytics\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/analytics/">Browse source</a>
-    - <a href="examples/tutorials/analytics.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\analytics\">Browse source</a>
+    - <a href="examples\tutorials\analytics.zip">Download source</a>
   </div>
-</div><div class="sample" id="e3df888a89e35bdeb9c8bc8d03be5e1851b97c68">
-  <img class="icon" src="examples/api/omnibox/extension-docs/icon-128.png">
+</div><div class="sample" id="97c797be0add2ec9ce72747b1ecdbd9b80bc73d9">
+  <img class="icon" src="examples\api\omnibox\extension-docs\icon-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#e3df888a89e35bdeb9c8bc8d03be5e1851b97c68">Extension Docs Search</a>
+    <a href="#97c797be0add2ec9ce72747b1ecdbd9b80bc73d9">Extension Docs Search</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1160,21 +1170,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\omnibox\extension-docs\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\omnibox\extension-docs\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/">Browse source</a>
-    - <a href="examples/api/omnibox/extension-docs.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\omnibox\extension-docs\">Browse source</a>
+    - <a href="examples\api\omnibox\extension-docs.zip">Download source</a>
   </div>
-</div><div class="sample" id="8b0dd31216235941bdd8eb33fda915ef5cf79a82">
-  <img class="icon" src="examples/extensions/calendar/images/icon-128.gif">
+</div><div class="sample" id="f802b3cce3b05de17dddd7ccfb3394d70f0ba1b5">
+  <img class="icon" src="examples\extensions\calendar\images/icon-128.gif">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#8b0dd31216235941bdd8eb33fda915ef5cf79a82">Google Calendar Checker (by Google)</a>
+    <a href="#f802b3cce3b05de17dddd7ccfb3394d70f0ba1b5">Google Calendar Checker (by Google)</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1228,31 +1238,31 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en/messages.json?content-type=text/plain">_locales/en/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\_locales\en\messages.json?content-type=text/plain">_locales\en\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/javascript/background.js?content-type=text/plain">javascript/background.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\javascript\background.js?content-type=text/plain">javascript\background.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/javascript/options.js?content-type=text/plain">javascript/options.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\javascript\options.js?content-type=text/plain">javascript\options.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/javascript/util.js?content-type=text/plain">javascript/util.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\javascript\util.js?content-type=text/plain">javascript\util.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/views/background.html?content-type=text/plain">views/background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\views\background.html?content-type=text/plain">views\background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/views/options.html?content-type=text/plain">views/options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\views\options.html?content-type=text/plain">views\options.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/calendar/">Browse source</a>
-    - <a href="examples/extensions/calendar.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\calendar\">Browse source</a>
+    - <a href="examples\extensions\calendar.zip">Download source</a>
   </div>
-</div><div class="sample" id="4e35caa9742fb82dbd628892d23a781614f6eff6">
-  <img class="icon" src="examples/extensions/gdocs/img/docs_spreadsheets-128.gif">
+</div><div class="sample" id="e83ae8cea73dfe87e420a9dac5e2906d795263cc">
+  <img class="icon" src="examples\extensions\gdocs\img/docs_spreadsheets-128.gif">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#4e35caa9742fb82dbd628892d23a781614f6eff6">Google Document List Viewer</a>
+    <a href="#e83ae8cea73dfe87e420a9dac5e2906d795263cc">Google Document List Viewer</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1297,33 +1307,33 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.html?content-type=text/plain">chrome_ex_oauth.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\chrome_ex_oauth.html?content-type=text/plain">chrome_ex_oauth.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/js/jquery-1.4.1.min.js?content-type=text/plain">js/jquery-1.4.1.min.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\js\jquery-1.4.1.min.js?content-type=text/plain">js\jquery-1.4.1.min.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\options.html?content-type=text/plain">options.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/">Browse source</a>
-    - <a href="examples/extensions/gdocs.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gdocs\">Browse source</a>
+    - <a href="examples\extensions\gdocs.zip">Download source</a>
   </div>
-</div><div class="sample" id="bb57f7a0132cbeb36ad7e7bb0ab75c21704234ca">
-  <img class="icon" src="examples/extensions/gmail/icon_128.png">
+</div><div class="sample" id="8ad6dbf5f536e3181945cd352930da9cc159dc71">
+  <img class="icon" src="examples\extensions\gmail\icon_128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#bb57f7a0132cbeb36ad7e7bb0ab75c21704234ca">Google Mail Checker</a>
+    <a href="#8ad6dbf5f536e3181945cd352930da9cc159dc71">Google Mail Checker</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1371,107 +1381,107 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ar/messages.json?content-type=text/plain">_locales/ar/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\ar\messages.json?content-type=text/plain">_locales\ar\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/bg/messages.json?content-type=text/plain">_locales/bg/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\bg\messages.json?content-type=text/plain">_locales\bg\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ca/messages.json?content-type=text/plain">_locales/ca/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\ca\messages.json?content-type=text/plain">_locales\ca\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/cs/messages.json?content-type=text/plain">_locales/cs/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\cs\messages.json?content-type=text/plain">_locales\cs\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/da/messages.json?content-type=text/plain">_locales/da/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\da\messages.json?content-type=text/plain">_locales\da\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/de/messages.json?content-type=text/plain">_locales/de/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\de\messages.json?content-type=text/plain">_locales\de\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/el/messages.json?content-type=text/plain">_locales/el/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\el\messages.json?content-type=text/plain">_locales\el\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en/messages.json?content-type=text/plain">_locales/en/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\en\messages.json?content-type=text/plain">_locales\en\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en_GB/messages.json?content-type=text/plain">_locales/en_GB/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\en_GB\messages.json?content-type=text/plain">_locales\en_GB\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es/messages.json?content-type=text/plain">_locales/es/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\es\messages.json?content-type=text/plain">_locales\es\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es_419/messages.json?content-type=text/plain">_locales/es_419/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\es_419\messages.json?content-type=text/plain">_locales\es_419\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/et/messages.json?content-type=text/plain">_locales/et/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\et\messages.json?content-type=text/plain">_locales\et\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fi/messages.json?content-type=text/plain">_locales/fi/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\fi\messages.json?content-type=text/plain">_locales\fi\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fil/messages.json?content-type=text/plain">_locales/fil/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\fil\messages.json?content-type=text/plain">_locales\fil\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fr/messages.json?content-type=text/plain">_locales/fr/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\fr\messages.json?content-type=text/plain">_locales\fr\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/he/messages.json?content-type=text/plain">_locales/he/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\he\messages.json?content-type=text/plain">_locales\he\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hi/messages.json?content-type=text/plain">_locales/hi/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\hi\messages.json?content-type=text/plain">_locales\hi\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hr/messages.json?content-type=text/plain">_locales/hr/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\hr\messages.json?content-type=text/plain">_locales\hr\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hu/messages.json?content-type=text/plain">_locales/hu/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\hu\messages.json?content-type=text/plain">_locales\hu\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/id/messages.json?content-type=text/plain">_locales/id/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\id\messages.json?content-type=text/plain">_locales\id\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/it/messages.json?content-type=text/plain">_locales/it/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\it\messages.json?content-type=text/plain">_locales\it\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ja/messages.json?content-type=text/plain">_locales/ja/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\ja\messages.json?content-type=text/plain">_locales\ja\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ko/messages.json?content-type=text/plain">_locales/ko/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\ko\messages.json?content-type=text/plain">_locales\ko\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lt/messages.json?content-type=text/plain">_locales/lt/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\lt\messages.json?content-type=text/plain">_locales\lt\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lv/messages.json?content-type=text/plain">_locales/lv/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\lv\messages.json?content-type=text/plain">_locales\lv\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nb/messages.json?content-type=text/plain">_locales/nb/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\nb\messages.json?content-type=text/plain">_locales\nb\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nl/messages.json?content-type=text/plain">_locales/nl/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\nl\messages.json?content-type=text/plain">_locales\nl\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pl/messages.json?content-type=text/plain">_locales/pl/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\pl\messages.json?content-type=text/plain">_locales\pl\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_BR/messages.json?content-type=text/plain">_locales/pt_BR/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\pt_BR\messages.json?content-type=text/plain">_locales\pt_BR\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_PT/messages.json?content-type=text/plain">_locales/pt_PT/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\pt_PT\messages.json?content-type=text/plain">_locales\pt_PT\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ro/messages.json?content-type=text/plain">_locales/ro/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\ro\messages.json?content-type=text/plain">_locales\ro\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ru/messages.json?content-type=text/plain">_locales/ru/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\ru\messages.json?content-type=text/plain">_locales\ru\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sk/messages.json?content-type=text/plain">_locales/sk/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\sk\messages.json?content-type=text/plain">_locales\sk\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sl/messages.json?content-type=text/plain">_locales/sl/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\sl\messages.json?content-type=text/plain">_locales\sl\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sr/messages.json?content-type=text/plain">_locales/sr/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\sr\messages.json?content-type=text/plain">_locales\sr\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sv/messages.json?content-type=text/plain">_locales/sv/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\sv\messages.json?content-type=text/plain">_locales\sv\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/th/messages.json?content-type=text/plain">_locales/th/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\th\messages.json?content-type=text/plain">_locales\th\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/tr/messages.json?content-type=text/plain">_locales/tr/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\tr\messages.json?content-type=text/plain">_locales\tr\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/uk/messages.json?content-type=text/plain">_locales/uk/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\uk\messages.json?content-type=text/plain">_locales\uk\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/vi/messages.json?content-type=text/plain">_locales/vi/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\vi\messages.json?content-type=text/plain">_locales\vi\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_CN/messages.json?content-type=text/plain">_locales/zh_CN/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\zh_CN\messages.json?content-type=text/plain">_locales\zh_CN\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_TW/messages.json?content-type=text/plain">_locales/zh_TW/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\_locales\zh_TW\messages.json?content-type=text/plain">_locales\zh_TW\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\options.html?content-type=text/plain">options.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/">Browse source</a>
-    - <a href="examples/extensions/gmail.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\gmail\">Browse source</a>
+    - <a href="examples\extensions\gmail.zip">Download source</a>
   </div>
-</div><div class="sample" id="1682e05ea9a1bde985123b04f6f8ac50a8a64033">
-  <img class="icon" src="examples/extensions/wave/128.png">
+</div><div class="sample" id="56529b7cbd67869d7fcebd6d46c3efddfe7b598f">
+  <img class="icon" src="examples\extensions\wave\128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#1682e05ea9a1bde985123b04f6f8ac50a8a64033">Google Wave Notifier</a>
+    <a href="#56529b7cbd67869d7fcebd6d46c3efddfe7b598f">Google Wave Notifier</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1514,33 +1524,33 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/chrome_ex_oauth.html?content-type=text/plain">chrome_ex_oauth.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\chrome_ex_oauth.html?content-type=text/plain">chrome_ex_oauth.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\options.html?content-type=text/plain">options.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\popup.html?content-type=text/plain">popup.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/prettyload.js?content-type=text/plain">prettyload.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\prettyload.js?content-type=text/plain">prettyload.js</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/wave/">Browse source</a>
-    - <a href="examples/extensions/wave.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\wave\">Browse source</a>
+    - <a href="examples\extensions\wave.zip">Download source</a>
   </div>
-</div><div class="sample" id="14b9651fda4e57b2a5914ba73a779812201b750a">
+</div><div class="sample" id="6deee0c2a7dbdd62a80deb526005814fa37e6556">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#14b9651fda4e57b2a5914ba73a779812201b750a">Hello World</a>
+    <a href="#6deee0c2a7dbdd62a80deb526005814fa37e6556">Hello World</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1562,21 +1572,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/getstarted/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\getstarted\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\getstarted\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/getstarted/">Browse source</a>
-    - <a href="examples/tutorials/getstarted.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\tutorials\getstarted\">Browse source</a>
+    - <a href="examples\tutorials\getstarted.zip">Download source</a>
   </div>
-</div><div class="sample" id="2020d72f2577f53caf8e94e3dbac0fb849ceaa4d">
-  <img class="icon" src="examples/api/idle/idle_simple/sample-128.png">
+</div><div class="sample" id="f0f5a81e76c7b29f8d13543dafd728285ecc96d7">
+  <img class="icon" src="examples\api\idle\idle_simple\sample-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#2020d72f2577f53caf8e94e3dbac0fb849ceaa4d">Idle - Simple Example</a>
+    <a href="#f0f5a81e76c7b29f8d13543dafd728285ecc96d7">Idle - Simple Example</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1607,23 +1617,23 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\idle\idle_simple\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html?content-type=text/plain">history.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\idle\idle_simple\history.html?content-type=text/plain">history.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\idle\idle_simple\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/idle/idle_simple/">Browse source</a>
-    - <a href="examples/api/idle/idle_simple.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\idle\idle_simple\">Browse source</a>
+    - <a href="examples\api\idle\idle_simple.zip">Download source</a>
   </div>
-</div><div class="sample" id="0ea1588bd07b20338fc21f725de1542a5fdf9726">
+</div><div class="sample" id="6e8555409ac09df65620a4f1651e9f283983eec5">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#0ea1588bd07b20338fc21f725de1542a5fdf9726">iGoogle new tab page</a>
+    <a href="#6e8555409ac09df65620a4f1651e9f283983eec5">iGoogle new tab page</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1642,21 +1652,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\override\override_igoogle\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html?content-type=text/plain">redirect.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\override\override_igoogle\redirect.html?content-type=text/plain">redirect.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/override/override_igoogle/">Browse source</a>
-    - <a href="examples/api/override/override_igoogle.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\override\override_igoogle\">Browse source</a>
+    - <a href="examples\api\override\override_igoogle.zip">Download source</a>
   </div>
-</div><div class="sample" id="646325c25f572a1d15edc73d057f821d847a4fbe">
-  <img class="icon" src="examples/extensions/imageinfo/imageinfo-128.png">
+</div><div class="sample" id="e08426e68f327ea625937f4668b89da16da0e467">
+  <img class="icon" src="examples\extensions\imageinfo\imageinfo-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#646325c25f572a1d15edc73d057f821d847a4fbe">Imageinfo</a>
+    <a href="#e08426e68f327ea625937f4668b89da16da0e467">Imageinfo</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1689,29 +1699,29 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/binaryajax.js?content-type=text/plain">imageinfo/binaryajax.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\imageinfo\binaryajax.js?content-type=text/plain">imageinfo\binaryajax.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/exif.js?content-type=text/plain">imageinfo/exif.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\imageinfo\exif.js?content-type=text/plain">imageinfo\exif.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/imageinfo.js?content-type=text/plain">imageinfo/imageinfo.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\imageinfo\imageinfo.js?content-type=text/plain">imageinfo\imageinfo.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html?content-type=text/plain">info.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\info.html?content-type=text/plain">info.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/imageinfo/">Browse source</a>
-    - <a href="examples/extensions/imageinfo.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\imageinfo\">Browse source</a>
+    - <a href="examples\extensions\imageinfo.zip">Download source</a>
   </div>
-</div><div class="sample" id="ec97ec20ca2f095d081e39f1565fc12af09ef067">
-  <img class="icon" src="examples/extensions/mappy/icon.png">
+</div><div class="sample" id="5c7def7e0a26bac297128161b2bb9b2fc279985b">
+  <img class="icon" src="examples\extensions\mappy\icon.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#ec97ec20ca2f095d081e39f1565fc12af09ef067">Mappy</a>
+    <a href="#5c7def7e0a26bac297128161b2bb9b2fc279985b">Mappy</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1757,25 +1767,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/mappy/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\mappy\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\mappy\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js?content-type=text/plain">mappy_content_script.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\mappy\mappy_content_script.js?content-type=text/plain">mappy_content_script.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/mappy/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\mappy\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/mappy/">Browse source</a>
-    - <a href="examples/extensions/mappy.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\mappy\">Browse source</a>
+    - <a href="examples\extensions\mappy.zip">Download source</a>
   </div>
-</div><div class="sample" id="b2f5f8a790e16f091a7e4e0a39b2d0a6d32e3a6d">
-  <img class="icon" src="examples/api/windows/merge_windows/merge_windows_128.png">
+</div><div class="sample" id="d72b4e8576fb00ad176957738099c930cffcfb9e">
+  <img class="icon" src="examples\api\windows\merge_windows\merge_windows_128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#b2f5f8a790e16f091a7e4e0a39b2d0a6d32e3a6d">Merge Windows</a>
+    <a href="#d72b4e8576fb00ad176957738099c930cffcfb9e">Merge Windows</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1812,21 +1822,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\windows\merge_windows\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\windows\merge_windows\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/windows/merge_windows/">Browse source</a>
-    - <a href="examples/api/windows/merge_windows.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\windows\merge_windows\">Browse source</a>
+    - <a href="examples\api\windows\merge_windows.zip">Download source</a>
   </div>
-</div><div class="sample" id="51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e">
+</div><div class="sample" id="af975d20117c15a36dff66ef5a1ebca92f653969">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e">Message Timer</a>
+    <a href="#af975d20117c15a36dff66ef5a1ebca92f653969">Message Timer</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1861,23 +1871,23 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\messaging\timer\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/timer/page.js?content-type=text/plain">page.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\messaging\timer\page.js?content-type=text/plain">page.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\messaging\timer\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/timer/">Browse source</a>
-    - <a href="examples/api/messaging/timer.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\messaging\timer\">Browse source</a>
+    - <a href="examples\api\messaging\timer.zip">Download source</a>
   </div>
-</div><div class="sample" id="4f6785ec4f937add6728615682dd37c9a42d9548">
+</div><div class="sample" id="7772f091557a50889effa6e5b19e83b4cf80399b">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#4f6785ec4f937add6728615682dd37c9a42d9548">My Bookmarks</a>
+    <a href="#7772f091557a50889effa6e5b19e83b4cf80399b">My Bookmarks</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1915,21 +1925,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\bookmarks\basic\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\bookmarks\basic\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/bookmarks/basic/">Browse source</a>
-    - <a href="examples/api/bookmarks/basic.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\bookmarks\basic\">Browse source</a>
+    - <a href="examples\api\bookmarks\basic.zip">Download source</a>
   </div>
-</div><div class="sample" id="597015d3bcce3da693b02314afd607bec4f55291">
-  <img class="icon" src="examples/extensions/news_a11y/news_icon.png">
+</div><div class="sample" id="28c933f585b0903a56f9a16658aa26cf61f9da0f">
+  <img class="icon" src="examples\extensions\news_a11y\news_icon.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#597015d3bcce3da693b02314afd607bec4f55291">News Reader</a>
+    <a href="#28c933f585b0903a56f9a16658aa26cf61f9da0f">News Reader</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1954,21 +1964,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.html?content-type=text/plain">feed.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_a11y\feed.html?content-type=text/plain">feed.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_a11y/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_a11y\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_a11y/">Browse source</a>
-    - <a href="examples/extensions/news_a11y.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_a11y\">Browse source</a>
+    - <a href="examples\extensions\news_a11y.zip">Download source</a>
   </div>
-</div><div class="sample" id="6444e5c8ae112a6a433909c5e770669cd16e2e5f">
-  <img class="icon" src="examples/extensions/news_i18n/news_icon.png">
+</div><div class="sample" id="80e7eac29801029c81ecaabb7c7021bbd0ceea88">
+  <img class="icon" src="examples\extensions\news_i18n\news_icon.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#6444e5c8ae112a6a433909c5e770669cd16e2e5f">News Reader</a>
+    <a href="#80e7eac29801029c81ecaabb7c7021bbd0ceea88">News Reader</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -1995,27 +2005,27 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/en/messages.json?content-type=text/plain">_locales/en/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_i18n\_locales\en\messages.json?content-type=text/plain">_locales\en\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/es/messages.json?content-type=text/plain">_locales/es/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_i18n\_locales\es\messages.json?content-type=text/plain">_locales\es\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/sr/messages.json?content-type=text/plain">_locales/sr/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_i18n\_locales\sr\messages.json?content-type=text/plain">_locales\sr\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_i18n/feed.html?content-type=text/plain">feed.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_i18n\feed.html?content-type=text/plain">feed.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_i18n/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_i18n\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_i18n/">Browse source</a>
-    - <a href="examples/extensions/news_i18n.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news_i18n\">Browse source</a>
+    - <a href="examples\extensions\news_i18n.zip">Download source</a>
   </div>
-</div><div class="sample" id="3aea027164cb9b732ba4a8c51cb93708891726ef">
-  <img class="icon" src="examples/extensions/news/images/news_icon.png">
+</div><div class="sample" id="e9e5f15da193c45aad4d49ced748dfbbd6c904b3">
+  <img class="icon" src="examples\extensions\news\images/news_icon.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#3aea027164cb9b732ba4a8c51cb93708891726ef">News Reader (by Google)</a>
+    <a href="#e9e5f15da193c45aad4d49ced748dfbbd6c904b3">News Reader (by Google)</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2050,37 +2060,37 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json?content-type=text/plain">_locales/en/messages.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\_locales\en\messages.json?content-type=text/plain">_locales\en\messages.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/css/feed.css?content-type=text/plain">css/feed.css</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\css\feed.css?content-type=text/plain">css\feed.css</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/css/options.css?content-type=text/plain">css/options.css</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\css\options.css?content-type=text/plain">css\options.css</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js?content-type=text/plain">javascript/feed.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\javascript\feed.js?content-type=text/plain">javascript\feed.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js?content-type=text/plain">javascript/options.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\javascript\options.js?content-type=text/plain">javascript\options.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js?content-type=text/plain">javascript/util.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\javascript\util.js?content-type=text/plain">javascript\util.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/views/background.html?content-type=text/plain">views/background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\views\background.html?content-type=text/plain">views\background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/views/feed.html?content-type=text/plain">views/feed.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\views\feed.html?content-type=text/plain">views\feed.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/views/options.html?content-type=text/plain">views/options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\views\options.html?content-type=text/plain">views\options.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/">Browse source</a>
-    - <a href="examples/extensions/news.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\news\">Browse source</a>
+    - <a href="examples\extensions\news.zip">Download source</a>
   </div>
-</div><div class="sample" id="f799e26ceef2367cf836f24bcb47df4398b0df58">
-  <img class="icon" src="examples/api/notifications/128.png">
+</div><div class="sample" id="324e557c216dd6edbeb0112ed53d55a05b5e6112">
+  <img class="icon" src="examples\api\notifications\128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#f799e26ceef2367cf836f24bcb47df4398b0df58">Notification Demo</a>
+    <a href="#324e557c216dd6edbeb0112ed53d55a05b5e6112">Notification Demo</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2108,25 +2118,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/notifications/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\notifications\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/notifications/error.html?content-type=text/plain">error.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\notifications\error.html?content-type=text/plain">error.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/notifications/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\notifications\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/notifications/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\notifications\options.html?content-type=text/plain">options.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/notifications/">Browse source</a>
-    - <a href="examples/api/notifications.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\notifications\">Browse source</a>
+    - <a href="examples\api\notifications.zip">Download source</a>
   </div>
-</div><div class="sample" id="e787b322bddbc6289bb31b7d7550b1bf6456a80b">
+</div><div class="sample" id="85a9f4cfd3645dfc4d1d90cc559261b689803626">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#e787b322bddbc6289bb31b7d7550b1bf6456a80b">Omnibox Example</a>
+    <a href="#85a9f4cfd3645dfc4d1d90cc559261b689803626">Omnibox Example</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2147,21 +2157,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\omnibox\simple-example\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\omnibox\simple-example\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/simple-example/">Browse source</a>
-    - <a href="examples/api/omnibox/simple-example.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\omnibox\simple-example\">Browse source</a>
+    - <a href="examples\api\omnibox\simple-example.zip">Download source</a>
   </div>
-</div><div class="sample" id="8d0a50b57c26bb498be592e871001ffed91541b4">
-  <img class="icon" src="examples/api/pageAction/pageaction_by_content/sandwich-128.png">
+</div><div class="sample" id="56bbb002845c9ada93807b2f83d51447adf146fd">
+  <img class="icon" src="examples\api\pageAction\pageaction_by_content\sandwich-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#8d0a50b57c26bb498be592e871001ffed91541b4">Page action by content</a>
+    <a href="#56bbb002845c9ada93807b2f83d51447adf146fd">Page action by content</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2187,23 +2197,23 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_content\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/contentscript.js?content-type=text/plain">contentscript.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_content\contentscript.js?content-type=text/plain">contentscript.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_content\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/">Browse source</a>
-    - <a href="examples/api/pageAction/pageaction_by_content.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_content\">Browse source</a>
+    - <a href="examples\api\pageAction\pageaction_by_content.zip">Download source</a>
   </div>
-</div><div class="sample" id="80b86ccc6e8520660fa591caa565826f0ed1b12c">
-  <img class="icon" src="examples/api/pageAction/pageaction_by_url/icon-128.png">
+</div><div class="sample" id="65afad56921c30f207a30f5ecf929e06b712f552">
+  <img class="icon" src="examples\api\pageAction\pageaction_by_url\icon-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#80b86ccc6e8520660fa591caa565826f0ed1b12c">Page action by URL</a>
+    <a href="#65afad56921c30f207a30f5ecf929e06b712f552">Page action by URL</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2230,21 +2240,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_url\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_url\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/">Browse source</a>
-    - <a href="examples/api/pageAction/pageaction_by_url.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\pageAction\pageaction_by_url\">Browse source</a>
+    - <a href="examples\api\pageAction\pageaction_by_url.zip">Download source</a>
   </div>
-</div><div class="sample" id="d74c3c18a1c1dd18b035149105a306f837c8823e">
+</div><div class="sample" id="7446de67bf18dc34b5ff0fb4e1d9d7d166339bb9">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#d74c3c18a1c1dd18b035149105a306f837c8823e">Page Benchmarker</a>
+    <a href="#7446de67bf18dc34b5ff0fb4e1d9d7d166339bb9">Page Benchmarker</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2306,53 +2316,53 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-1.4.2.min.js?content-type=text/plain">jquery/jquery-1.4.2.min.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery-1.4.2.min.js?content-type=text/plain">jquery\jquery-1.4.2.min.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-ui-1.8.4.custom.min.js?content-type=text/plain">jquery/jquery-ui-1.8.4.custom.min.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery-ui-1.8.4.custom.min.js?content-type=text/plain">jquery\jquery-ui-1.8.4.custom.min.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.client.js?content-type=text/plain">jquery/jquery.client.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery.client.js?content-type=text/plain">jquery\jquery.client.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.dashes.js?content-type=text/plain">jquery/jquery.flot.dashes.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery.flot.dashes.js?content-type=text/plain">jquery\jquery.flot.dashes.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.js?content-type=text/plain">jquery/jquery.flot.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery.flot.js?content-type=text/plain">jquery\jquery.flot.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.min.js?content-type=text/plain">jquery/jquery.flot.min.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery.flot.min.js?content-type=text/plain">jquery\jquery.flot.min.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.navigate.js?content-type=text/plain">jquery/jquery.flot.navigate.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery.flot.navigate.js?content-type=text/plain">jquery\jquery.flot.navigate.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.valuelabels.js?content-type=text/plain">jquery/jquery.flot.valuelabels.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jquery\jquery.flot.valuelabels.js?content-type=text/plain">jquery\jquery.flot.valuelabels.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jst/jsevalcontext.js?content-type=text/plain">jst/jsevalcontext.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jst\jsevalcontext.js?content-type=text/plain">jst\jsevalcontext.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jst/jstemplate.js?content-type=text/plain">jst/jstemplate.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jst\jstemplate.js?content-type=text/plain">jst\jstemplate.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jst/jstemplate_test.js?content-type=text/plain">jst/jstemplate_test.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jst\jstemplate_test.js?content-type=text/plain">jst\jstemplate_test.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jst/util.js?content-type=text/plain">jst/util.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\jst\util.js?content-type=text/plain">jst\util.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/options.html?content-type=text/plain">options.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\options.html?content-type=text/plain">options.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/script.js?content-type=text/plain">script.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\script.js?content-type=text/plain">script.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/util/sorttable.js?content-type=text/plain">util/sorttable.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\util\sorttable.js?content-type=text/plain">util\sorttable.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/util/table2CSV.js?content-type=text/plain">util/table2CSV.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\util\table2CSV.js?content-type=text/plain">util\table2CSV.js</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/">Browse source</a>
-    - <a href="examples/extensions/benchmark.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\benchmark\">Browse source</a>
+    - <a href="examples\extensions\benchmark.zip">Download source</a>
   </div>
-</div><div class="sample" id="e6ae17ab4ccfd7e059c8c01f25760ca5d894c7fd">
+</div><div class="sample" id="a9ea9e35b2e9990e488afeb97407655ea14fc8dc">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#e6ae17ab4ccfd7e059c8c01f25760ca5d894c7fd">Print this page</a>
+    <a href="#a9ea9e35b2e9990e488afeb97407655ea14fc8dc">Print this page</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2379,21 +2389,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/print/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\print\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\print\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/print/">Browse source</a>
-    - <a href="examples/api/browserAction/print.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\browserAction\print\">Browse source</a>
+    - <a href="examples\api\browserAction\print.zip">Download source</a>
   </div>
-</div><div class="sample" id="beff6ecd9677dea0a7c648c5042165b48bb66f09">
+</div><div class="sample" id="455ec3784d8094b318eac572bc092ec07c5286b0">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#beff6ecd9677dea0a7c648c5042165b48bb66f09">Process Monitor</a>
+    <a href="#455ec3784d8094b318eac572bc092ec07c5286b0">Process Monitor</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2421,21 +2431,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/processes/process_monitor/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\processes\process_monitor\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\processes\process_monitor\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/processes/process_monitor/">Browse source</a>
-    - <a href="examples/api/processes/process_monitor.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\processes\process_monitor\">Browse source</a>
+    - <a href="examples\api\processes\process_monitor.zip">Download source</a>
   </div>
-</div><div class="sample" id="56a8d2ac24ca7bba78fd88ad57f43fc13c784497">
-  <img class="icon" src="examples/extensions/oauth_contacts/img/icon-128.png">
+</div><div class="sample" id="545d6989740a0e7f57a9751c2ebc0e250053a08f">
+  <img class="icon" src="examples\extensions\oauth_contacts\img/icon-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#56a8d2ac24ca7bba78fd88ad57f43fc13c784497">Sample - OAuth Contacts</a>
+    <a href="#545d6989740a0e7f57a9751c2ebc0e250053a08f">Sample - OAuth Contacts</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2476,29 +2486,29 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.html?content-type=text/plain">chrome_ex_oauth.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\chrome_ex_oauth.html?content-type=text/plain">chrome_ex_oauth.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.html?content-type=text/plain">contacts.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\contacts.html?content-type=text/plain">contacts.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/">Browse source</a>
-    - <a href="examples/extensions/oauth_contacts.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\extensions\oauth_contacts\">Browse source</a>
+    - <a href="examples\extensions\oauth_contacts.zip">Download source</a>
   </div>
-</div><div class="sample" id="38f6e1e17756ede38b1364c7114a738ca717dcbb">
-  <img class="icon" src="examples/api/infobars/sandwichbar/sandwich-128.png">
+</div><div class="sample" id="39a3d4c4282ee5090652938decfb6df79b626151">
+  <img class="icon" src="examples\api\infobars\sandwichbar\sandwich-128.png">
   <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
   <h2 class="name">
-    <a href="#38f6e1e17756ede38b1364c7114a738ca717dcbb">SandwichBar</a>
+    <a href="#39a3d4c4282ee5090652938decfb6df79b626151">SandwichBar</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2524,25 +2534,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\infobars\sandwichbar\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/contentscript.js?content-type=text/plain">contentscript.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\infobars\sandwichbar\contentscript.js?content-type=text/plain">contentscript.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/infobar.html?content-type=text/plain">infobar.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\infobars\sandwichbar\infobar.html?content-type=text/plain">infobar.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\infobars\sandwichbar\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/">Browse source</a>
-    - <a href="examples/api/infobars/sandwichbar.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\infobars\sandwichbar\">Browse source</a>
+    - <a href="examples\api\infobars\sandwichbar.zip">Download source</a>
   </div>
-</div><div class="sample" id="fc89b35755483af30b66cd72cefa34a43a3e8312">
+</div><div class="sample" id="364415e46171be6479a095b214eab9783a4648d2">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#fc89b35755483af30b66cd72cefa34a43a3e8312">Show Tabs in Process</a>
+    <a href="#364415e46171be6479a095b214eab9783a4648d2">Show Tabs in Process</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2584,21 +2594,21 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\processes\show_tabs\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html?content-type=text/plain">popup.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\processes\show_tabs\popup.html?content-type=text/plain">popup.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/processes/show_tabs/">Browse source</a>
-    - <a href="examples/api/processes/show_tabs.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\processes\show_tabs\">Browse source</a>
+    - <a href="examples\api\processes\show_tabs.zip">Download source</a>
   </div>
-</div><div class="sample" id="230463f2d5c3d4d0ca13c230e1f00f2aae0a8a64">
+</div><div class="sample" id="ad0d399dfc6d92af6ee9b759d7792a0d0bb85370">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#230463f2d5c3d4d0ca13c230e1f00f2aae0a8a64">Tab Inspector</a>
+    <a href="#ad0d399dfc6d92af6ee9b759d7792a0d0bb85370">Tab Inspector</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2673,25 +2683,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\inspector\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js?content-type=text/plain">jstemplate_compiled.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\inspector\jstemplate_compiled.js?content-type=text/plain">jstemplate_compiled.js</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\inspector\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html?content-type=text/plain">tabs_api.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\inspector\tabs_api.html?content-type=text/plain">tabs_api.html</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/">Browse source</a>
-    - <a href="examples/api/tabs/inspector.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\inspector\">Browse source</a>
+    - <a href="examples\api\tabs\inspector.zip">Download source</a>
   </div>
-</div><div class="sample" id="e1697cacebad05218798bf3e8a0f724517f0e8c3">
+</div><div class="sample" id="1e28bcf89e80466f155ab3a01a76cf5f60cb4104">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#e1697cacebad05218798bf3e8a0f724517f0e8c3">Test Screenshot Extension</a>
+    <a href="#1e28bcf89e80466f155ab3a01a76cf5f60cb4104">Test Screenshot Extension</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2726,25 +2736,25 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.html?content-type=text/plain">background.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\screenshot\background.html?content-type=text/plain">background.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\screenshot\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html?content-type=text/plain">screenshot.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\screenshot\screenshot.html?content-type=text/plain">screenshot.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js?content-type=text/plain">screenshot.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\screenshot\screenshot.js?content-type=text/plain">screenshot.js</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/screenshot/">Browse source</a>
-    - <a href="examples/api/tabs/screenshot.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\tabs\screenshot\">Browse source</a>
+    - <a href="examples\api\tabs\screenshot.zip">Download source</a>
   </div>
-</div><div class="sample" id="b3de91ab04b7d7a2670ca7ee9d740eb42cead0b6">
+</div><div class="sample" id="7b375c0f2c88517b42a5a341ac77e0762b481233">
   <img class="icon" style="display: none; ">
   <img class="icon" src="images/sample-default-icon.png">
   <h2 class="name">
-    <a href="#b3de91ab04b7d7a2670ca7ee9d740eb42cead0b6">Typed URL History</a>
+    <a href="#7b375c0f2c88517b42a5a341ac77e0762b481233">Typed URL History</a>
   </h2>
   <p class="metadata features">Uses
     <span>
@@ -2773,17 +2783,17 @@
   <div class="sourcefiles"><strong>Source files:</strong>
     <ul>
       <li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json?content-type=text/plain">manifest.json</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\history\showHistory\manifest.json?content-type=text/plain">manifest.json</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html?content-type=text/plain">typedUrls.html</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\history\showHistory\typedUrls.html?content-type=text/plain">typedUrls.html</a></code>
       </li><li>
-        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js?content-type=text/plain">typedUrls.js</a></code>
+        <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\history\showHistory\typedUrls.js?content-type=text/plain">typedUrls.js</a></code>
       </li>
     </ul>
   </div>
   <div>
-    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/history/showHistory/">Browse source</a>
-    - <a href="examples/api/history/showHistory.zip">Download source</a>
+    <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples\api\history\showHistory\">Browse source</a>
+    - <a href="examples\api\history\showHistory.zip">Download source</a>
   </div>
 </div>
 
@@ -2816,8 +2826,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -2892,10 +2902,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -2913,14 +2922,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/samples.json b/chrome/common/extensions/docs/samples.json
index b060a44..eacba16 100644
--- a/chrome/common/extensions/docs/samples.json
+++ b/chrome/common/extensions/docs/samples.json
@@ -41,6 +41,8 @@
     "chrome.experimental.infobars.show": "experimental.infobars.html#method-show", 
     "chrome.experimental.processes.getProcessIdForTab": "experimental.processes.html#method-getProcessIdForTab", 
     "chrome.experimental.processes.onUpdated": "experimental.processes.html#event-onUpdated", 
+    "chrome.experimental.proxy.getCurrentProxySettings": "experimental.proxy.html#method-getCurrentProxySettings", 
+    "chrome.experimental.proxy.removeCustomProxySettings": "experimental.proxy.html#method-removeCustomProxySettings", 
     "chrome.experimental.proxy.useCustomProxySettings": "experimental.proxy.html#method-useCustomProxySettings", 
     "chrome.experimental.sidebar.collapse": "experimental.sidebar.html#method-collapse", 
     "chrome.experimental.sidebar.expand": "experimental.sidebar.html#method-expand", 
@@ -52,12 +54,19 @@
     "chrome.experimental.sidebar.setIcon": "experimental.sidebar.html#method-setIcon", 
     "chrome.experimental.sidebar.setTitle": "experimental.sidebar.html#method-setTitle", 
     "chrome.experimental.sidebar.show": "experimental.sidebar.html#method-show", 
+    "chrome.experimental.tts.isSpeaking": "experimental.tts.html#method-isSpeaking", 
+    "chrome.experimental.tts.onSpeak": "experimental.tts.html#event-onSpeak", 
+    "chrome.experimental.tts.onStop": "experimental.tts.html#event-onStop", 
+    "chrome.experimental.tts.speak": "experimental.tts.html#method-speak", 
+    "chrome.experimental.tts.speakCompleted": "experimental.tts.html#method-speakCompleted", 
+    "chrome.experimental.tts.stop": "experimental.tts.html#method-stop", 
     "chrome.experimental.webNavigation.onBeforeNavigate": "experimental.webNavigation.html#event-onBeforeNavigate", 
     "chrome.experimental.webNavigation.onBeforeRetarget": "experimental.webNavigation.html#event-onBeforeRetarget", 
     "chrome.experimental.webNavigation.onCommitted": "experimental.webNavigation.html#event-onCommitted", 
     "chrome.experimental.webNavigation.onCompleted": "experimental.webNavigation.html#event-onCompleted", 
     "chrome.experimental.webNavigation.onDOMContentLoaded": "experimental.webNavigation.html#event-onDOMContentLoaded", 
     "chrome.experimental.webNavigation.onErrorOccurred": "experimental.webNavigation.html#event-onErrorOccurred", 
+    "chrome.experimental.webRequest.addEventListener": "experimental.webRequest.html#method-addEventListener", 
     "chrome.experimental.webRequest.onBeforeRedirect": "experimental.webRequest.html#event-onBeforeRedirect", 
     "chrome.experimental.webRequest.onBeforeRequest": "experimental.webRequest.html#event-onBeforeRequest", 
     "chrome.experimental.webRequest.onCompleted": "experimental.webRequest.html#event-onCompleted", 
@@ -154,11 +163,11 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "0262260daf0c8f7b28feff2ef23b05e7abf9d1e0", 
+      "id": "4da084813a9c0f3de28821a1c8d2504f5f7bcbad", 
       "name": "A browser action which changes its icon when clicked.", 
-      "path": "examples/api/browserAction/set_icon_path/", 
+      "path": "examples\\api\\browserAction\\set_icon_path\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "A BROWSER ACTION WHICH CHANGES ITS ICON WHEN CLICKED.  BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON", 
       "source_files": [
@@ -166,7 +175,7 @@
         "manifest.json"
       ], 
       "source_hash": "c5752555642e89340c57657b48440b0dcd74ee99", 
-      "zip_path": "examples/api/browserAction/set_icon_path.zip"
+      "zip_path": "examples\\api\\browserAction\\set_icon_path.zip"
     }, 
     {
       "api_calls": [
@@ -179,12 +188,12 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "ea2894c41cb8e80a4433a3e6c5772dadce9be90d", 
+      "id": "0569ec913dfd1aa4fad58fff04af99b0de7ec4b6", 
       "name": "A browser action with a popup that changes the page color.", 
-      "path": "examples/api/browserAction/set_page_color/", 
+      "path": "examples\\api\\browserAction\\set_page_color\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "A BROWSER ACTION WITH A POPUP THAT CHANGES THE PAGE COLOR.  BROWSER_ACTION POPUP TABS CHROME.TABS.EXECUTESCRIPT", 
       "source_files": [
@@ -192,7 +201,7 @@
         "popup.html"
       ], 
       "source_hash": "c8d14b6893e75a62f3bd150d5d2cc5bb785bc411", 
-      "zip_path": "examples/api/browserAction/set_page_color.zip"
+      "zip_path": "examples\\api\\browserAction\\set_page_color.zip"
     }, 
     {
       "api_calls": [
@@ -208,11 +217,11 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "ede3c47b7757245be42ec33fd5ca63df4b490066", 
+      "id": "a02f64d5e8c8f96efb45b26c11bfa2320deddd36", 
       "name": "A browser action with no icon that makes the page red", 
-      "path": "examples/api/browserAction/make_page_red/", 
+      "path": "examples\\api\\browserAction\\make_page_red\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "A BROWSER ACTION WITH NO ICON THAT MAKES THE PAGE RED  BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.EXECUTESCRIPT", 
       "source_files": [
@@ -220,7 +229,7 @@
         "manifest.json"
       ], 
       "source_hash": "dfbb05ead54a0228a6d2f591ce1038d5c625249a", 
-      "zip_path": "examples/api/browserAction/make_page_red.zip"
+      "zip_path": "examples\\api\\browserAction\\make_page_red.zip"
     }, 
     {
       "api_calls": [
@@ -233,20 +242,20 @@
         "popup"
       ], 
       "icon": null, 
-      "id": "fbf0aa1a09a15ff8cc4fc7de4fd176d6c663d07a", 
+      "id": "ebed3a237b5606a154cfc0e6326821154607d388", 
       "name": "AcceptLanguage", 
-      "path": "examples/api/i18n/getMessage/", 
+      "path": "examples\\api\\i18n\\getMessage\\", 
       "protocols": [], 
       "search_string": "ACCEPTLANGUAGE RETURNS ACCEPT LANGUAGES OF THE BROWSER BROWSER_ACTION POPUP CHROME.I18N.GETACCEPTLANGUAGES CHROME.I18N.GETMESSAGE", 
       "source_files": [
-        "_locales/en_US/messages.json", 
-        "_locales/es/messages.json", 
-        "_locales/sr/messages.json", 
+        "_locales\\en_US\\messages.json", 
+        "_locales\\es\\messages.json", 
+        "_locales\\sr\\messages.json", 
         "manifest.json", 
         "popup.html"
       ], 
       "source_hash": "67f203e2773eebf401d0aa0a9709d961e506d875", 
-      "zip_path": "examples/api/i18n/getMessage.zip"
+      "zip_path": "examples\\api\\i18n\\getMessage.zip"
     }, 
     {
       "api_calls": [
@@ -266,9 +275,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "9a6e4ec46997fb92b324974afa08a3d007e2537f", 
+      "id": "2f7777c80368bb0a8caf057dffaadd5feed7e9ee", 
       "name": "Animated Page Action", 
-      "path": "examples/api/pageAction/set_icon/", 
+      "path": "examples\\api\\pageAction\\set_icon\\", 
       "protocols": [], 
       "search_string": "ANIMATED PAGE ACTION THIS EXTENSION ADDS AN ANIMATED BROWSER ACTION TO THE TOOLBAR. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.ONCLICKED CHROME.PAGEACTION.SETICON CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED", 
       "source_files": [
@@ -276,7 +285,7 @@
         "manifest.json"
       ], 
       "source_hash": "9d5e9f8fd525c6d02fe03e1843041f5b0f94f690", 
-      "zip_path": "examples/api/pageAction/set_icon.zip"
+      "zip_path": "examples\\api\\pageAction\\set_icon.zip"
     }, 
     {
       "api_calls": [
@@ -292,9 +301,9 @@
         "management"
       ], 
       "icon": null, 
-      "id": "a1f7cf79dd555b04fa8d603247a040e644996293", 
+      "id": "4da5aeb0840b36af753e694f2e81c90620494688", 
       "name": "App Launcher", 
-      "path": "examples/extensions/app_launcher/", 
+      "path": "examples\\extensions\\app_launcher\\", 
       "protocols": [], 
       "search_string": "APP LAUNCHER  BROWSER_ACTION MANAGEMENT CHROME.EXTENSION.GETURL CHROME.MANAGEMENT.GET CHROME.MANAGEMENT.GETALL CHROME.MANAGEMENT.LAUNCHAPP CHROME.TABS.CREATE", 
       "source_files": [
@@ -304,7 +313,7 @@
         "popup.js"
       ], 
       "source_hash": "4cb1348cfca9c990117d52290f93eb5fc5081bc2", 
-      "zip_path": "examples/extensions/app_launcher.zip"
+      "zip_path": "examples\\extensions\\app_launcher.zip"
     }, 
     {
       "api_calls": [], 
@@ -313,9 +322,9 @@
         "chrome_url_overrides"
       ], 
       "icon": null, 
-      "id": "9747e3d6a3eab39bc7c17f11a80573c62d44c7e5", 
+      "id": "63349d2a4f5ec8f315a05fc9b1cab181ad546fd2", 
       "name": "Blank new tab page", 
-      "path": "examples/api/override/blank_ntp/", 
+      "path": "examples\\api\\override\\blank_ntp\\", 
       "protocols": [], 
       "search_string": "BLANK NEW TAB PAGE  CHROME_URL_OVERRIDES", 
       "source_files": [
@@ -323,7 +332,7 @@
         "manifest.json"
       ], 
       "source_hash": "477acf6d15e3fa252e6307e156707538b61c86db", 
-      "zip_path": "examples/api/override/blank_ntp.zip"
+      "zip_path": "examples\\api\\override\\blank_ntp.zip"
     }, 
     {
       "api_calls": [
@@ -353,12 +362,12 @@
         "tabs"
       ], 
       "icon": "icon.png", 
-      "id": "903e7277139e1e6caec123d3319cab295d8d1b3a", 
+      "id": "4c45b5015d2ca5f9053514ac70ff3acc3bca1f76", 
       "name": "Chrome Sounds", 
-      "path": "examples/extensions/fx/", 
+      "path": "examples\\extensions\\fx\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "CHROME SOUNDS ENJOY A MORE MAGICAL AND IMMERSIVE EXPERIENCE WHEN BROWSING THE WEB USING THE POWER OF SOUND. BACKGROUND_PAGE BOOKMARKS OPTIONS_PAGE TABS CHROME.BOOKMARKS.ONCREATED CHROME.BOOKMARKS.ONMOVED CHROME.BOOKMARKS.ONREMOVED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.TABS.GET CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED", 
       "source_files": [
@@ -368,8 +377,8 @@
         "manifest.json", 
         "options.html"
       ], 
-      "source_hash": "4155e4e6ba7d523ba7bc3b75da352c22e534c3c3", 
-      "zip_path": "examples/extensions/fx.zip"
+      "source_hash": "800ec3bb17be14c24c3c287c843393211094e40d", 
+      "zip_path": "examples\\extensions\\fx.zip"
     }, 
     {
       "api_calls": [
@@ -387,12 +396,12 @@
         "popup"
       ], 
       "icon": "icon.png", 
-      "id": "0e790e035a4a00b6f1def5ef9a7d7be1bce95ab5", 
+      "id": "2f41f968c8b6ddfc078363e305d2b530802a11dd", 
       "name": "Chromium Buildbot Monitor", 
-      "path": "examples/extensions/buildbot/", 
+      "path": "examples\\extensions\\buildbot\\", 
       "protocols": [
-        "http://", 
-        "http://"
+        "http:\/\/", 
+        "http:\/\/"
       ], 
       "search_string": "CHROMIUM BUILDBOT MONITOR DISPLAYS THE STATUS OF THE CHROMIUM BUILDBOT IN THE TOOLBAR.  CLICK TO SEE MORE DETAILED STATUS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION NOTIFICATIONS OPTIONS_PAGE POPUP CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETURL", 
       "source_files": [
@@ -402,7 +411,7 @@
         "popup.html"
       ], 
       "source_hash": "ad985dc5b3e2b40826042be1d7b77c07fadfcc68", 
-      "zip_path": "examples/extensions/buildbot.zip"
+      "zip_path": "examples\\extensions\\buildbot.zip"
     }, 
     {
       "api_calls": [
@@ -421,11 +430,11 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "ac31228200b41a87982e386cc90d3a6eee4ad885", 
+      "id": "32ff053c4a55b305243c83756304ca7c9d135ed0", 
       "name": "Chromium Search", 
-      "path": "examples/extensions/chrome_search/", 
+      "path": "examples\\extensions\\chrome_search\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "CHROMIUM SEARCH ADD SUPPORT TO THE OMNIBOX TO SEARCH THE CHROMIUM SOURCE CODE. BACKGROUND_PAGE TABS CHROME.OMNIBOX.ONINPUTCANCELLED CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED CHROME.OMNIBOX.ONINPUTSTARTED CHROME.OMNIBOX.SETDEFAULTSUGGESTION CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE", 
       "source_files": [
@@ -433,7 +442,7 @@
         "manifest.json"
       ], 
       "source_hash": "37dd43080094bbe459b0429f1a2b995c33bab7c3", 
-      "zip_path": "examples/extensions/chrome_search.zip"
+      "zip_path": "examples\\extensions\\chrome_search.zip"
     }, 
     {
       "api_calls": [
@@ -451,9 +460,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "7d5d6cf195bc25480256618e360aa38c6e6fba82", 
+      "id": "6484bb796d9aef70aa1026c0edc0799bc7a48b68", 
       "name": "CLD", 
-      "path": "examples/api/i18n/cld/", 
+      "path": "examples\\api\\i18n\\cld\\", 
       "protocols": [], 
       "search_string": "CLD DISPLAYS THE LANGUAGE OF A TAB BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.DETECTLANGUAGE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED", 
       "source_files": [
@@ -461,7 +470,7 @@
         "manifest.json"
       ], 
       "source_hash": "913694d89e0b081f1ea5ad6f07b60b0141e82394", 
-      "zip_path": "examples/api/i18n/cld.zip"
+      "zip_path": "examples\\api\\i18n\\cld.zip"
     }, 
     {
       "api_calls": [
@@ -473,9 +482,9 @@
         "contextMenus"
       ], 
       "icon": null, 
-      "id": "5d81304a17cf7ac2887484f730fbd2b01e51e166", 
+      "id": "8818cf9ded850b5f0ba7348127526eb00165f202", 
       "name": "Context Menus Sample", 
-      "path": "examples/api/contextMenus/basic/", 
+      "path": "examples\\api\\contextMenus\\basic\\", 
       "protocols": [], 
       "search_string": "CONTEXT MENUS SAMPLE SHOWS SOME OF THE FEATURES OF THE CONTEXT MENUS API BACKGROUND_PAGE CONTEXTMENUS CHROME.CONTEXTMENUS.CREATE", 
       "source_files": [
@@ -483,8 +492,8 @@
         "manifest.json", 
         "sample.js"
       ], 
-      "source_hash": "0e35ce268b3b2cf3d9830e6411c85c5dfef2ffdf", 
-      "zip_path": "examples/api/contextMenus/basic.zip"
+      "source_hash": "f7240f31b5864b3f6da99cba794b3070cbdf41ef", 
+      "zip_path": "examples\\api\\contextMenus\\basic.zip"
     }, 
     {
       "api_calls": [
@@ -507,12 +516,12 @@
         "tabs"
       ], 
       "icon": "cookie.png", 
-      "id": "4daa6becd0899a54776d9cf7f09613ed1a9f4d77", 
+      "id": "ba79d21d1e9a1cf5edebc246b11f667406cb001f", 
       "name": "Cookie API Test Extension", 
-      "path": "examples/api/cookies/", 
+      "path": "examples\\api\\cookies\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "COOKIE API TEST EXTENSION TESTING COOKIE API BACKGROUND_PAGE BROWSER_ACTION COOKIES TABS CHROME.BROWSERACTION.ONCLICKED CHROME.COOKIES.GET CHROME.COOKIES.GETALL CHROME.COOKIES.ONCHANGED CHROME.COOKIES.REMOVE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL", 
       "source_files": [
@@ -520,33 +529,33 @@
         "manager.html", 
         "manifest.json"
       ], 
-      "source_hash": "d0741a5ff0ce9ac38a1be3e6abc46065d74cb498", 
-      "zip_path": "examples/api/cookies.zip"
+      "source_hash": "6618d2f19b3d02fa21e3980027609a5ced23364a", 
+      "zip_path": "examples\\api\\cookies.zip"
     }, 
     {
       "api_calls": [
         "chrome.extension.onRequest", 
         "chrome.extension.sendRequest"
       ], 
-      "description": "Demonstrates a method to make a cross-domain XMLHttpRequest fetch from a content script.  This extension fetches the current trending topics from Twitter and inserts them in an overlay at the top of Google News.  Visit http://news.google.com to test this extension.", 
+      "description": "Demonstrates a method to make a cross-domain XMLHttpRequest fetch from a content script.  This extension fetches the current trending topics from Twitter and inserts them in an overlay at the top of Google News.  Visit http:\/\/news.google.com to test this extension.", 
       "features": [
         "background_page"
       ], 
       "icon": "sample-128.png", 
-      "id": "6871d09f4a96bf9d4b6cc724d00e909cee0f3902", 
+      "id": "b6ab1c298a1c1f939b393f36868c937391502112", 
       "name": "Cross-domain XMLHttpRequest from a content script", 
-      "path": "examples/howto/contentscript_xhr/", 
+      "path": "examples\\howto\\contentscript_xhr\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
-      "search_string": "CROSS-DOMAIN XMLHTTPREQUEST FROM A CONTENT SCRIPT DEMONSTRATES A METHOD TO MAKE A CROSS-DOMAIN XMLHTTPREQUEST FETCH FROM A CONTENT SCRIPT.  THIS EXTENSION FETCHES THE CURRENT TRENDING TOPICS FROM TWITTER AND INSERTS THEM IN AN OVERLAY AT THE TOP OF GOOGLE NEWS.  VISIT HTTP://NEWS.GOOGLE.COM TO TEST THIS EXTENSION. BACKGROUND_PAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST", 
+      "search_string": "CROSS-DOMAIN XMLHTTPREQUEST FROM A CONTENT SCRIPT DEMONSTRATES A METHOD TO MAKE A CROSS-DOMAIN XMLHTTPREQUEST FETCH FROM A CONTENT SCRIPT.  THIS EXTENSION FETCHES THE CURRENT TRENDING TOPICS FROM TWITTER AND INSERTS THEM IN AN OVERLAY AT THE TOP OF GOOGLE NEWS.  VISIT HTTP:\/\/NEWS.GOOGLE.COM TO TEST THIS EXTENSION. BACKGROUND_PAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST", 
       "source_files": [
         "background.html", 
         "contentscript.js", 
         "manifest.json"
       ], 
       "source_hash": "0fe56cea50dc18b7e5e31d47c383356a85d8b896", 
-      "zip_path": "examples/howto/contentscript_xhr.zip"
+      "zip_path": "examples\\howto\\contentscript_xhr.zip"
     }, 
     {
       "api_calls": [
@@ -565,12 +574,12 @@
         "tabs"
       ], 
       "icon": "mail_128x128.png", 
-      "id": "028eb5364924344029bcbe1d527f132fc72b34e5", 
+      "id": "fad4ea2189bbcce1d2669a409ed296b10ec8b7c9", 
       "name": "Email this page (by Google)", 
-      "path": "examples/extensions/email_this_page/", 
+      "path": "examples\\extensions\\email_this_page\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "EMAIL THIS PAGE (BY GOOGLE) THIS EXTENSION ADDS AN EMAIL BUTTON TO THE TOOLBAR WHICH ALLOWS YOU TO EMAIL THE PAGE LINK USING YOUR DEFAULT MAIL CLIENT OR GMAIL. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.CONNECT CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.UPDATE", 
       "source_files": [
@@ -580,7 +589,7 @@
         "options.html"
       ], 
       "source_hash": "54b5469031ddcb2097f39dbaae1bcd81ae650154", 
-      "zip_path": "examples/extensions/email_this_page.zip"
+      "zip_path": "examples\\extensions\\email_this_page.zip"
     }, 
     {
       "api_calls": [], 
@@ -591,9 +600,9 @@
         "popup"
       ], 
       "icon": "analytics-extension-icon-128.png", 
-      "id": "763a08e9b06595d785568a8d392b95a2f3700258", 
+      "id": "26af638d88737474bed3837343caa13f3b924615", 
       "name": "Event Tracking with Google Analytics", 
-      "path": "examples/tutorials/analytics/", 
+      "path": "examples\\tutorials\\analytics\\", 
       "protocols": [], 
       "search_string": "EVENT TRACKING WITH GOOGLE ANALYTICS A SAMPLE EXTENSION WHICH USES GOOGLE ANALYTICS TO TRACK USAGE. BACKGROUND_PAGE BROWSER_ACTION POPUP", 
       "source_files": [
@@ -603,7 +612,7 @@
         "popup.html"
       ], 
       "source_hash": "b02f040a3eb56f8a0e780549954f69172d62dcd3", 
-      "zip_path": "examples/tutorials/analytics.zip"
+      "zip_path": "examples\\tutorials\\analytics.zip"
     }, 
     {
       "api_calls": [
@@ -620,11 +629,11 @@
         "tabs"
       ], 
       "icon": "icon-128.png", 
-      "id": "e3df888a89e35bdeb9c8bc8d03be5e1851b97c68", 
+      "id": "97c797be0add2ec9ce72747b1ecdbd9b80bc73d9", 
       "name": "Extension Docs Search", 
-      "path": "examples/api/omnibox/extension-docs/", 
+      "path": "examples\\api\\omnibox\\extension-docs\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "EXTENSION DOCS SEARCH SEARCH THE CHROME EXTENSIONS DOCUMENTATION.  TO USE, TYPE CRDOC PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE TABS CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.ONREMOVED CHROME.TABS.UPDATE", 
       "source_files": [
@@ -632,7 +641,7 @@
         "manifest.json"
       ], 
       "source_hash": "0aa8ec9a2c091e227661ca5010d08f6823e643a7", 
-      "zip_path": "examples/api/omnibox/extension-docs.zip"
+      "zip_path": "examples\\api\\omnibox\\extension-docs.zip"
     }, 
     {
       "api_calls": [
@@ -658,26 +667,26 @@
         "options_page", 
         "tabs"
       ], 
-      "icon": "images/icon-128.gif", 
-      "id": "8b0dd31216235941bdd8eb33fda915ef5cf79a82", 
+      "icon": "images\/icon-128.gif", 
+      "id": "f802b3cce3b05de17dddd7ccfb3394d70f0ba1b5", 
       "name": "Google Calendar Checker (by Google)", 
-      "path": "examples/extensions/calendar/", 
+      "path": "examples\\extensions\\calendar\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "GOOGLE CALENDAR CHECKER (BY GOOGLE) QUICKLY SEE THE TIME UNTIL YOUR NEXT MEETING FROM ANY OF YOUR CALENDARS. CLICK ON THE BUTTON TO BE TAKEN TO YOUR CALENDAR. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE", 
       "source_files": [
-        "_locales/en/messages.json", 
-        "javascript/background.js", 
-        "javascript/options.js", 
-        "javascript/util.js", 
+        "_locales\\en\\messages.json", 
+        "javascript\\background.js", 
+        "javascript\\options.js", 
+        "javascript\\util.js", 
         "manifest.json", 
-        "views/background.html", 
-        "views/options.html"
+        "views\\background.html", 
+        "views\\options.html"
       ], 
-      "source_hash": "3d9782a3e8315bbbca36c63297db2c8926df4521", 
-      "zip_path": "examples/extensions/calendar.zip"
+      "source_hash": "7f39521994eb05b10c222681712ee6cdbe029334", 
+      "zip_path": "examples\\extensions\\calendar.zip"
     }, 
     {
       "api_calls": [
@@ -698,15 +707,15 @@
         "popup", 
         "tabs"
       ], 
-      "icon": "img/docs_spreadsheets-128.gif", 
-      "id": "4e35caa9742fb82dbd628892d23a781614f6eff6", 
+      "icon": "img\/docs_spreadsheets-128.gif", 
+      "id": "e83ae8cea73dfe87e420a9dac5e2906d795263cc", 
       "name": "Google Document List Viewer", 
-      "path": "examples/extensions/gdocs/", 
+      "path": "examples\\extensions\\gdocs\\", 
       "protocols": [
-        "https://", 
-        "https://", 
-        "https://", 
-        "https://"
+        "https:\/\/", 
+        "https:\/\/", 
+        "https:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "GOOGLE DOCUMENT LIST VIEWER DEMONSTRATES HOW TO USE OAUTH TO CONNECT THE GOOGLE DOCUMENTS LIST DATA API. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE", 
       "source_files": [
@@ -714,13 +723,13 @@
         "chrome_ex_oauth.html", 
         "chrome_ex_oauth.js", 
         "chrome_ex_oauthsimple.js", 
-        "js/jquery-1.4.1.min.js", 
+        "js\\jquery-1.4.1.min.js", 
         "manifest.json", 
         "options.html", 
         "popup.html"
       ], 
       "source_hash": "284e44d603a62348dd1b7e98e593f3f4b877b124", 
-      "zip_path": "examples/extensions/gdocs.zip"
+      "zip_path": "examples\\extensions\\gdocs.zip"
     }, 
     {
       "api_calls": [
@@ -744,63 +753,63 @@
         "tabs"
       ], 
       "icon": "icon_128.png", 
-      "id": "bb57f7a0132cbeb36ad7e7bb0ab75c21704234ca", 
+      "id": "8ad6dbf5f536e3181945cd352930da9cc159dc71", 
       "name": "Google Mail Checker", 
-      "path": "examples/extensions/gmail/", 
+      "path": "examples\\extensions\\gmail\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "GOOGLE MAIL CHECKER DISPLAYS THE NUMBER OF UNREAD MESSAGES IN YOUR GOOGLE MAIL INBOX. YOU CAN ALSO CLICK THE BUTTON TO OPEN YOUR INBOX. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE", 
       "source_files": [
-        "_locales/ar/messages.json", 
-        "_locales/bg/messages.json", 
-        "_locales/ca/messages.json", 
-        "_locales/cs/messages.json", 
-        "_locales/da/messages.json", 
-        "_locales/de/messages.json", 
-        "_locales/el/messages.json", 
-        "_locales/en/messages.json", 
-        "_locales/en_GB/messages.json", 
-        "_locales/es/messages.json", 
-        "_locales/es_419/messages.json", 
-        "_locales/et/messages.json", 
-        "_locales/fi/messages.json", 
-        "_locales/fil/messages.json", 
-        "_locales/fr/messages.json", 
-        "_locales/he/messages.json", 
-        "_locales/hi/messages.json", 
-        "_locales/hr/messages.json", 
-        "_locales/hu/messages.json", 
-        "_locales/id/messages.json", 
-        "_locales/it/messages.json", 
-        "_locales/ja/messages.json", 
-        "_locales/ko/messages.json", 
-        "_locales/lt/messages.json", 
-        "_locales/lv/messages.json", 
-        "_locales/nb/messages.json", 
-        "_locales/nl/messages.json", 
-        "_locales/pl/messages.json", 
-        "_locales/pt_BR/messages.json", 
-        "_locales/pt_PT/messages.json", 
-        "_locales/ro/messages.json", 
-        "_locales/ru/messages.json", 
-        "_locales/sk/messages.json", 
-        "_locales/sl/messages.json", 
-        "_locales/sr/messages.json", 
-        "_locales/sv/messages.json", 
-        "_locales/th/messages.json", 
-        "_locales/tr/messages.json", 
-        "_locales/uk/messages.json", 
-        "_locales/vi/messages.json", 
-        "_locales/zh_CN/messages.json", 
-        "_locales/zh_TW/messages.json", 
+        "_locales\\ar\\messages.json", 
+        "_locales\\bg\\messages.json", 
+        "_locales\\ca\\messages.json", 
+        "_locales\\cs\\messages.json", 
+        "_locales\\da\\messages.json", 
+        "_locales\\de\\messages.json", 
+        "_locales\\el\\messages.json", 
+        "_locales\\en\\messages.json", 
+        "_locales\\en_GB\\messages.json", 
+        "_locales\\es\\messages.json", 
+        "_locales\\es_419\\messages.json", 
+        "_locales\\et\\messages.json", 
+        "_locales\\fi\\messages.json", 
+        "_locales\\fil\\messages.json", 
+        "_locales\\fr\\messages.json", 
+        "_locales\\he\\messages.json", 
+        "_locales\\hi\\messages.json", 
+        "_locales\\hr\\messages.json", 
+        "_locales\\hu\\messages.json", 
+        "_locales\\id\\messages.json", 
+        "_locales\\it\\messages.json", 
+        "_locales\\ja\\messages.json", 
+        "_locales\\ko\\messages.json", 
+        "_locales\\lt\\messages.json", 
+        "_locales\\lv\\messages.json", 
+        "_locales\\nb\\messages.json", 
+        "_locales\\nl\\messages.json", 
+        "_locales\\pl\\messages.json", 
+        "_locales\\pt_BR\\messages.json", 
+        "_locales\\pt_PT\\messages.json", 
+        "_locales\\ro\\messages.json", 
+        "_locales\\ru\\messages.json", 
+        "_locales\\sk\\messages.json", 
+        "_locales\\sl\\messages.json", 
+        "_locales\\sr\\messages.json", 
+        "_locales\\sv\\messages.json", 
+        "_locales\\th\\messages.json", 
+        "_locales\\tr\\messages.json", 
+        "_locales\\uk\\messages.json", 
+        "_locales\\vi\\messages.json", 
+        "_locales\\zh_CN\\messages.json", 
+        "_locales\\zh_TW\\messages.json", 
         "background.html", 
         "manifest.json", 
         "options.html"
       ], 
       "source_hash": "030b77992ed5bbbbc18f1b717bc330b965b26aaf", 
-      "zip_path": "examples/extensions/gmail.zip"
+      "zip_path": "examples\\extensions\\gmail.zip"
     }, 
     {
       "api_calls": [
@@ -821,12 +830,12 @@
         "tabs"
       ], 
       "icon": "128.png", 
-      "id": "1682e05ea9a1bde985123b04f6f8ac50a8a64033", 
+      "id": "56529b7cbd67869d7fcebd6d46c3efddfe7b598f", 
       "name": "Google Wave Notifier", 
-      "path": "examples/extensions/wave/", 
+      "path": "examples\\extensions\\wave\\", 
       "protocols": [
-        "https://", 
-        "http://"
+        "https:\/\/", 
+        "http:\/\/"
       ], 
       "search_string": "GOOGLE WAVE NOTIFIER FIND OUT WHEN YOU HAVE NEW WAVES AND PREVIEW THEM FAST. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE", 
       "source_files": [
@@ -840,7 +849,7 @@
         "prettyload.js"
       ], 
       "source_hash": "9f360bf8772e8a23862d854ea088e0bec867ba02", 
-      "zip_path": "examples/extensions/wave.zip"
+      "zip_path": "examples\\extensions\\wave.zip"
     }, 
     {
       "api_calls": [], 
@@ -850,11 +859,11 @@
         "popup"
       ], 
       "icon": null, 
-      "id": "14b9651fda4e57b2a5914ba73a779812201b750a", 
+      "id": "6deee0c2a7dbdd62a80deb526005814fa37e6556", 
       "name": "Hello World", 
-      "path": "examples/tutorials/getstarted/", 
+      "path": "examples\\tutorials\\getstarted\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "HELLO WORLD THE FIRST EXTENSION THAT I MADE. BROWSER_ACTION POPUP", 
       "source_files": [
@@ -862,7 +871,7 @@
         "popup.html"
       ], 
       "source_hash": "1a3139dcb7f3e3499023703643e7056c61235123", 
-      "zip_path": "examples/tutorials/getstarted.zip"
+      "zip_path": "examples\\tutorials\\getstarted.zip"
     }, 
     {
       "api_calls": [
@@ -878,9 +887,9 @@
         "idle"
       ], 
       "icon": "sample-128.png", 
-      "id": "2020d72f2577f53caf8e94e3dbac0fb849ceaa4d", 
+      "id": "f0f5a81e76c7b29f8d13543dafd728285ecc96d7", 
       "name": "Idle - Simple Example", 
-      "path": "examples/api/idle/idle_simple/", 
+      "path": "examples\\api\\idle\\idle_simple\\", 
       "protocols": [], 
       "search_string": "IDLE - SIMPLE EXAMPLE DEMONSTRATES THE IDLE API BACKGROUND_PAGE BROWSER_ACTION IDLE CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.IDLE.ONSTATECHANGED CHROME.IDLE.QUERYSTATE", 
       "source_files": [
@@ -889,7 +898,7 @@
         "manifest.json"
       ], 
       "source_hash": "1378042fee96e115d7b8003588eca369b43f772b", 
-      "zip_path": "examples/api/idle/idle_simple.zip"
+      "zip_path": "examples\\api\\idle\\idle_simple.zip"
     }, 
     {
       "api_calls": [], 
@@ -898,9 +907,9 @@
         "chrome_url_overrides"
       ], 
       "icon": null, 
-      "id": "0ea1588bd07b20338fc21f725de1542a5fdf9726", 
+      "id": "6e8555409ac09df65620a4f1651e9f283983eec5", 
       "name": "iGoogle new tab page", 
-      "path": "examples/api/override/override_igoogle/", 
+      "path": "examples\\api\\override\\override_igoogle\\", 
       "protocols": [], 
       "search_string": "IGOOGLE NEW TAB PAGE  CHROME_URL_OVERRIDES", 
       "source_files": [
@@ -908,7 +917,7 @@
         "redirect.html"
       ], 
       "source_hash": "8ee76608adbf87c3260f9905e6cb1c8a45bd8e0c", 
-      "zip_path": "examples/api/override/override_igoogle.zip"
+      "zip_path": "examples\\api\\override\\override_igoogle.zip"
     }, 
     {
       "api_calls": [
@@ -925,24 +934,24 @@
         "tabs"
       ], 
       "icon": "imageinfo-128.png", 
-      "id": "646325c25f572a1d15edc73d057f821d847a4fbe", 
+      "id": "e08426e68f327ea625937f4668b89da16da0e467", 
       "name": "Imageinfo", 
-      "path": "examples/extensions/imageinfo/", 
+      "path": "examples\\extensions\\imageinfo\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "IMAGEINFO GET IMAGE INFO FOR IMAGES, INCLUDING EXIF DATA BACKGROUND_PAGE CONTEXTMENUS TABS CHROME.CONTEXTMENUS.CREATE CHROME.TABS.GET CHROME.TABS.GETCURRENT CHROME.WINDOWS.CREATE CHROME.WINDOWS.UPDATE", 
       "source_files": [
         "background.html", 
-        "imageinfo/binaryajax.js", 
-        "imageinfo/exif.js", 
-        "imageinfo/imageinfo.js", 
+        "imageinfo\\binaryajax.js", 
+        "imageinfo\\exif.js", 
+        "imageinfo\\imageinfo.js", 
         "info.html", 
         "manifest.json"
       ], 
-      "source_hash": "c746d9114348f4b414c1ec05e988e2807feb963a", 
-      "zip_path": "examples/extensions/imageinfo.zip"
+      "source_hash": "672f49ed8edbe0829c7ba5a1d890b4440b157991", 
+      "zip_path": "examples\\extensions\\imageinfo.zip"
     }, 
     {
       "api_calls": [
@@ -965,11 +974,11 @@
         "tabs"
       ], 
       "icon": "icon.png", 
-      "id": "ec97ec20ca2f095d081e39f1565fc12af09ef067", 
+      "id": "5c7def7e0a26bac297128161b2bb9b2fc279985b", 
       "name": "Mappy", 
-      "path": "examples/extensions/mappy/", 
+      "path": "examples\\extensions\\mappy\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "MAPPY FINDS ADDRESSES IN THE WEB PAGE YOURE ON AND POPS UP A MAP WINDOW. BACKGROUND_PAGE PAGE_ACTION POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.SENDREQUEST", 
       "source_files": [
@@ -978,8 +987,8 @@
         "mappy_content_script.js", 
         "popup.html"
       ], 
-      "source_hash": "81cf2d3975d7df8b58e5226c5b2b6df026446511", 
-      "zip_path": "examples/extensions/mappy.zip"
+      "source_hash": "4f9ce20e8352148b0a2c1cd91c212fd67b5e61f1", 
+      "zip_path": "examples\\extensions\\mappy.zip"
     }, 
     {
       "api_calls": [
@@ -998,9 +1007,9 @@
         "tabs"
       ], 
       "icon": "merge_windows_128.png", 
-      "id": "b2f5f8a790e16f091a7e4e0a39b2d0a6d32e3a6d", 
+      "id": "d72b4e8576fb00ad176957738099c930cffcfb9e", 
       "name": "Merge Windows", 
-      "path": "examples/api/windows/merge_windows/", 
+      "path": "examples\\api\\windows\\merge_windows\\", 
       "protocols": [], 
       "search_string": "MERGE WINDOWS MERGES ALL OF THE BROWSERS WINDOWS INTO THE CURRENT WINDOW BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.MOVE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT", 
       "source_files": [
@@ -1008,7 +1017,7 @@
         "manifest.json"
       ], 
       "source_hash": "4b5fe52788e0bef2f3871b36105eb53cc760c454", 
-      "zip_path": "examples/api/windows/merge_windows.zip"
+      "zip_path": "examples\\api\\windows\\merge_windows.zip"
     }, 
     {
       "api_calls": [
@@ -1026,9 +1035,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e", 
+      "id": "af975d20117c15a36dff66ef5a1ebca92f653969", 
       "name": "Message Timer", 
-      "path": "examples/api/messaging/timer/", 
+      "path": "examples\\api\\messaging\\timer\\", 
       "protocols": [], 
       "search_string": "MESSAGE TIMER TIMES HOW LONG IT TAKES TO SEND A MESSAGE TO A CONTENT SCRIPT AND BACK. BROWSER_ACTION POPUP TABS CHROME.EXTENSION.ONCONNECT CHROME.EXTENSION.ONREQUEST CHROME.TABS.CONNECT CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.SENDREQUEST", 
       "source_files": [
@@ -1037,7 +1046,7 @@
         "popup.html"
       ], 
       "source_hash": "927cf398a95a665beb64f56a4bfb791b98a8ee96", 
-      "zip_path": "examples/api/messaging/timer.zip"
+      "zip_path": "examples\\api\\messaging\\timer.zip"
     }, 
     {
       "api_calls": [
@@ -1056,17 +1065,17 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "4f6785ec4f937add6728615682dd37c9a42d9548", 
+      "id": "7772f091557a50889effa6e5b19e83b4cf80399b", 
       "name": "My Bookmarks", 
-      "path": "examples/api/bookmarks/basic/", 
+      "path": "examples\\api\\bookmarks\\basic\\", 
       "protocols": [], 
       "search_string": "MY BOOKMARKS A BROWSER ACTION WITH A POPUP DUMP OF ALL BOOKMARKS, INCLUDING SEARCH, ADD, EDIT AND DELETE. BOOKMARKS BROWSER_ACTION POPUP TABS CHROME.BOOKMARKS.CREATE CHROME.BOOKMARKS.GET CHROME.BOOKMARKS.GETTREE CHROME.BOOKMARKS.REMOVE CHROME.BOOKMARKS.UPDATE CHROME.TABS.CREATE", 
       "source_files": [
         "manifest.json", 
         "popup.html"
       ], 
-      "source_hash": "4f7509c56c2943cf8aedf1ee0b4b4a7d1e49f7d3", 
-      "zip_path": "examples/api/bookmarks/basic.zip"
+      "source_hash": "5fd4c8e159a36d2462e9691db12d77a27684d6b7", 
+      "zip_path": "examples\\api\\bookmarks\\basic.zip"
     }, 
     {
       "api_calls": [
@@ -1079,11 +1088,11 @@
         "tabs"
       ], 
       "icon": "news_icon.png", 
-      "id": "597015d3bcce3da693b02314afd607bec4f55291", 
+      "id": "28c933f585b0903a56f9a16658aa26cf61f9da0f", 
       "name": "News Reader", 
-      "path": "examples/extensions/news_a11y/", 
+      "path": "examples\\extensions\\news_a11y\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE", 
       "source_files": [
@@ -1091,7 +1100,7 @@
         "manifest.json"
       ], 
       "source_hash": "af7474bf0d3ef1a407f27ae0900167a1408ead35", 
-      "zip_path": "examples/extensions/news_a11y.zip"
+      "zip_path": "examples\\extensions\\news_a11y.zip"
     }, 
     {
       "api_calls": [
@@ -1105,23 +1114,23 @@
         "tabs"
       ], 
       "icon": "news_icon.png", 
-      "id": "6444e5c8ae112a6a433909c5e770669cd16e2e5f", 
+      "id": "80e7eac29801029c81ecaabb7c7021bbd0ceea88", 
       "name": "News Reader", 
-      "path": "examples/extensions/news_i18n/", 
+      "path": "examples\\extensions\\news_i18n\\", 
       "protocols": [
-        "http://", 
-        "http://"
+        "http:\/\/", 
+        "http:\/\/"
       ], 
       "search_string": "NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE", 
       "source_files": [
-        "_locales/en/messages.json", 
-        "_locales/es/messages.json", 
-        "_locales/sr/messages.json", 
+        "_locales\\en\\messages.json", 
+        "_locales\\es\\messages.json", 
+        "_locales\\sr\\messages.json", 
         "feed.html", 
         "manifest.json"
       ], 
       "source_hash": "381268f1183beaeba8d6596e736dc2c00a55fd21", 
-      "zip_path": "examples/extensions/news_i18n.zip"
+      "zip_path": "examples\\extensions\\news_i18n.zip"
     }, 
     {
       "api_calls": [
@@ -1137,28 +1146,28 @@
         "popup", 
         "tabs"
       ], 
-      "icon": "images/news_icon.png", 
-      "id": "3aea027164cb9b732ba4a8c51cb93708891726ef", 
+      "icon": "images\/news_icon.png", 
+      "id": "e9e5f15da193c45aad4d49ced748dfbbd6c904b3", 
       "name": "News Reader (by Google)", 
-      "path": "examples/extensions/news/", 
+      "path": "examples\\extensions\\news\\", 
       "protocols": [
-        "http://"
+        "http:\/\/"
       ], 
       "search_string": "NEWS READER (BY GOOGLE) DISPLAYS THE LATEST STORIES FROM GOOGLE NEWS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETURL CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE", 
       "source_files": [
-        "_locales/en/messages.json", 
-        "css/feed.css", 
-        "css/options.css", 
-        "javascript/feed.js", 
-        "javascript/options.js", 
-        "javascript/util.js", 
+        "_locales\\en\\messages.json", 
+        "css\\feed.css", 
+        "css\\options.css", 
+        "javascript\\feed.js", 
+        "javascript\\options.js", 
+        "javascript\\util.js", 
         "manifest.json", 
-        "views/background.html", 
-        "views/feed.html", 
-        "views/options.html"
+        "views\\background.html", 
+        "views\\feed.html", 
+        "views\\options.html"
       ], 
       "source_hash": "cc21920e101dd4d4c535f4842e3f0ab4be285166", 
-      "zip_path": "examples/extensions/news.zip"
+      "zip_path": "examples\\extensions\\news.zip"
     }, 
     {
       "api_calls": [
@@ -1172,9 +1181,9 @@
         "tabs"
       ], 
       "icon": "128.png", 
-      "id": "f799e26ceef2367cf836f24bcb47df4398b0df58", 
+      "id": "324e557c216dd6edbeb0112ed53d55a05b5e6112", 
       "name": "Notification Demo", 
-      "path": "examples/api/notifications/", 
+      "path": "examples\\api\\notifications\\", 
       "protocols": [], 
       "search_string": "NOTIFICATION DEMO SHOWS OFF DESKTOP NOTIFICATIONS, WHICH ARE TOAST WINDOWS THAT POP UP ON THE DESKTOP. BACKGROUND_PAGE NOTIFICATIONS OPTIONS_PAGE TABS CHROME.TABS.CREATE", 
       "source_files": [
@@ -1184,7 +1193,7 @@
         "options.html"
       ], 
       "source_hash": "bc2985ef75d717779cb6e1e523a3e063067c3494", 
-      "zip_path": "examples/api/notifications.zip"
+      "zip_path": "examples\\api\\notifications.zip"
     }, 
     {
       "api_calls": [
@@ -1196,9 +1205,9 @@
         "background_page"
       ], 
       "icon": null, 
-      "id": "e787b322bddbc6289bb31b7d7550b1bf6456a80b", 
+      "id": "85a9f4cfd3645dfc4d1d90cc559261b689803626", 
       "name": "Omnibox Example", 
-      "path": "examples/api/omnibox/simple-example/", 
+      "path": "examples\\api\\omnibox\\simple-example\\", 
       "protocols": [], 
       "search_string": "OMNIBOX EXAMPLE TO USE, TYPE OMNIX PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE CHROME.OMNIBOX.ONINPUTCHANGED CHROME.OMNIBOX.ONINPUTENTERED", 
       "source_files": [
@@ -1206,7 +1215,7 @@
         "manifest.json"
       ], 
       "source_hash": "21f142aad0637086ec08923a11ce3dee70e42bc6", 
-      "zip_path": "examples/api/omnibox/simple-example.zip"
+      "zip_path": "examples\\api\\omnibox\\simple-example.zip"
     }, 
     {
       "api_calls": [
@@ -1220,9 +1229,9 @@
         "page_action"
       ], 
       "icon": "sandwich-128.png", 
-      "id": "8d0a50b57c26bb498be592e871001ffed91541b4", 
+      "id": "56bbb002845c9ada93807b2f83d51447adf146fd", 
       "name": "Page action by content", 
-      "path": "examples/api/pageAction/pageaction_by_content/", 
+      "path": "examples\\api\\pageAction\\pageaction_by_content\\", 
       "protocols": [], 
       "search_string": "PAGE ACTION BY CONTENT SHOWS A PAGE ACTION FOR HTML PAGES CONTAINING THE WORD SANDWICH BACKGROUND_PAGE PAGE_ACTION CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.PAGEACTION.SHOW", 
       "source_files": [
@@ -1231,7 +1240,7 @@
         "manifest.json"
       ], 
       "source_hash": "0f4b881b1bc2e2fd6098fd219ca061b72a9654b7", 
-      "zip_path": "examples/api/pageAction/pageaction_by_content.zip"
+      "zip_path": "examples\\api\\pageAction\\pageaction_by_content.zip"
     }, 
     {
       "api_calls": [
@@ -1245,9 +1254,9 @@
         "tabs"
       ], 
       "icon": "icon-128.png", 
-      "id": "80b86ccc6e8520660fa591caa565826f0ed1b12c", 
+      "id": "65afad56921c30f207a30f5ecf929e06b712f552", 
       "name": "Page action by URL", 
-      "path": "examples/api/pageAction/pageaction_by_url/", 
+      "path": "examples\\api\\pageAction\\pageaction_by_url\\", 
       "protocols": [], 
       "search_string": "PAGE ACTION BY URL SHOWS A PAGE ACTION FOR URLS WHICH HAVE THE LETTER G IN THEM. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.SHOW CHROME.TABS.ONUPDATED", 
       "source_files": [
@@ -1255,7 +1264,7 @@
         "manifest.json"
       ], 
       "source_hash": "732ef0951e1d6ff4afedb884b0e63cb342bb1499", 
-      "zip_path": "examples/api/pageAction/pageaction_by_url.zip"
+      "zip_path": "examples\\api\\pageAction\\pageaction_by_url.zip"
     }, 
     {
       "api_calls": [
@@ -1286,36 +1295,36 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "d74c3c18a1c1dd18b035149105a306f837c8823e", 
+      "id": "7446de67bf18dc34b5ff0fb4e1d9d7d166339bb9", 
       "name": "Page Benchmarker", 
-      "path": "examples/extensions/benchmark/", 
+      "path": "examples\\extensions\\benchmark\\", 
       "protocols": [
-        "https://", 
-        "http://"
+        "https:\/\/", 
+        "http:\/\/"
       ], 
       "search_string": "PAGE BENCHMARKER CHROMIUM PAGE BENCHMARKER. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.CONNECT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETEXTENSIONTABS CHROME.EXTENSION.GETURL CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETCURRENT", 
       "source_files": [
         "background.html", 
-        "jquery/jquery-1.4.2.min.js", 
-        "jquery/jquery-ui-1.8.4.custom.min.js", 
-        "jquery/jquery.client.js", 
-        "jquery/jquery.flot.dashes.js", 
-        "jquery/jquery.flot.js", 
-        "jquery/jquery.flot.min.js", 
-        "jquery/jquery.flot.navigate.js", 
-        "jquery/jquery.flot.valuelabels.js", 
-        "jst/jsevalcontext.js", 
-        "jst/jstemplate.js", 
-        "jst/jstemplate_test.js", 
-        "jst/util.js", 
+        "jquery\\jquery-1.4.2.min.js", 
+        "jquery\\jquery-ui-1.8.4.custom.min.js", 
+        "jquery\\jquery.client.js", 
+        "jquery\\jquery.flot.dashes.js", 
+        "jquery\\jquery.flot.js", 
+        "jquery\\jquery.flot.min.js", 
+        "jquery\\jquery.flot.navigate.js", 
+        "jquery\\jquery.flot.valuelabels.js", 
+        "jst\\jsevalcontext.js", 
+        "jst\\jstemplate.js", 
+        "jst\\jstemplate_test.js", 
+        "jst\\util.js", 
         "manifest.json", 
         "options.html", 
         "script.js", 
-        "util/sorttable.js", 
-        "util/table2CSV.js"
+        "util\\sorttable.js", 
+        "util\\table2CSV.js"
       ], 
-      "source_hash": "7e592dbd3446353f7d98d1760f7cd773035aaaad", 
-      "zip_path": "examples/extensions/benchmark.zip"
+      "source_hash": "8a8cf6896eab009a372e9ec091a41e8e6fed4f1b", 
+      "zip_path": "examples\\extensions\\benchmark.zip"
     }, 
     {
       "api_calls": [
@@ -1329,12 +1338,12 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "e6ae17ab4ccfd7e059c8c01f25760ca5d894c7fd", 
+      "id": "a9ea9e35b2e9990e488afeb97407655ea14fc8dc", 
       "name": "Print this page", 
-      "path": "examples/api/browserAction/print/", 
+      "path": "examples\\api\\browserAction\\print\\", 
       "protocols": [
-        "http://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "PRINT THIS PAGE ADDS A PRINT BUTTON TO THE BROWSER. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.UPDATE", 
       "source_files": [
@@ -1342,7 +1351,7 @@
         "manifest.json"
       ], 
       "source_hash": "be980117222f6b041bb012c5a0793040cef747b6", 
-      "zip_path": "examples/api/browserAction/print.zip"
+      "zip_path": "examples\\api\\browserAction\\print.zip"
     }, 
     {
       "api_calls": [
@@ -1356,9 +1365,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "beff6ecd9677dea0a7c648c5042165b48bb66f09", 
+      "id": "455ec3784d8094b318eac572bc092ec07c5286b0", 
       "name": "Process Monitor", 
-      "path": "examples/api/processes/process_monitor/", 
+      "path": "examples\\api\\processes\\process_monitor\\", 
       "protocols": [], 
       "search_string": "PROCESS MONITOR ADDS A BROWSER ACTION THAT MONITORS RESOURCE USAGE OF ALL BROWSER PROCESSES. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.ONUPDATED", 
       "source_files": [
@@ -1366,7 +1375,7 @@
         "popup.html"
       ], 
       "source_hash": "a4d002a65d5ec54ef4495f8b5552a260119df739", 
-      "zip_path": "examples/api/processes/process_monitor.zip"
+      "zip_path": "examples\\api\\processes\\process_monitor.zip"
     }, 
     {
       "api_calls": [
@@ -1386,15 +1395,15 @@
         "browser_action", 
         "tabs"
       ], 
-      "icon": "img/icon-128.png", 
-      "id": "56a8d2ac24ca7bba78fd88ad57f43fc13c784497", 
+      "icon": "img\/icon-128.png", 
+      "id": "545d6989740a0e7f57a9751c2ebc0e250053a08f", 
       "name": "Sample - OAuth Contacts", 
-      "path": "examples/extensions/oauth_contacts/", 
+      "path": "examples\\extensions\\oauth_contacts\\", 
       "protocols": [
-        "http://", 
-        "https://", 
-        "https://", 
-        "https://"
+        "http:\/\/", 
+        "https:\/\/", 
+        "https:\/\/", 
+        "https:\/\/"
       ], 
       "search_string": "SAMPLE - OAUTH CONTACTS USES OAUTH TO CONNECT TO GOOGLES CONTACTS SERVICE AND DISPLAY A LIST OF YOUR CONTACTS. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE", 
       "source_files": [
@@ -1406,7 +1415,7 @@
         "manifest.json"
       ], 
       "source_hash": "e9afbd588b1593c9d3e9b9612ac242c781871f34", 
-      "zip_path": "examples/extensions/oauth_contacts.zip"
+      "zip_path": "examples\\extensions\\oauth_contacts.zip"
     }, 
     {
       "api_calls": [
@@ -1420,9 +1429,9 @@
         "experimental"
       ], 
       "icon": "sandwich-128.png", 
-      "id": "38f6e1e17756ede38b1364c7114a738ca717dcbb", 
+      "id": "39a3d4c4282ee5090652938decfb6df79b626151", 
       "name": "SandwichBar", 
-      "path": "examples/api/infobars/sandwichbar/", 
+      "path": "examples\\api\\infobars\\sandwichbar\\", 
       "protocols": [], 
       "search_string": "SANDWICHBAR SHOWS AN INFOBAR ON PAGES WHICH CONTAIN THE WORD SANDWICH BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.INFOBARS.SHOW CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST", 
       "source_files": [
@@ -1432,7 +1441,7 @@
         "manifest.json"
       ], 
       "source_hash": "890d698634e5228ef7da8ffca3008f843b9a7cab", 
-      "zip_path": "examples/api/infobars/sandwichbar.zip"
+      "zip_path": "examples\\api\\infobars\\sandwichbar.zip"
     }, 
     {
       "api_calls": [
@@ -1453,9 +1462,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "fc89b35755483af30b66cd72cefa34a43a3e8312", 
+      "id": "364415e46171be6479a095b214eab9783a4648d2", 
       "name": "Show Tabs in Process", 
-      "path": "examples/api/processes/show_tabs/", 
+      "path": "examples\\api\\processes\\show_tabs\\", 
       "protocols": [], 
       "search_string": "SHOW TABS IN PROCESS ADDS A BROWSER ACTION SHOWING WHICH TABS SHARE THE CURRENT TABS PROCESS. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.GETPROCESSIDFORTAB CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.UPDATE", 
       "source_files": [
@@ -1463,7 +1472,7 @@
         "popup.html"
       ], 
       "source_hash": "c9818c3c4c2e4fae0a7cc29588514e050356fd52", 
-      "zip_path": "examples/api/processes/show_tabs.zip"
+      "zip_path": "examples\\api\\processes\\show_tabs.zip"
     }, 
     {
       "api_calls": [
@@ -1501,9 +1510,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "230463f2d5c3d4d0ca13c230e1f00f2aae0a8a64", 
+      "id": "ad0d399dfc6d92af6ee9b759d7792a0d0bb85370", 
       "name": "Tab Inspector", 
-      "path": "examples/api/tabs/inspector/", 
+      "path": "examples\\api\\tabs\\inspector\\", 
       "protocols": [], 
       "search_string": "TAB INSPECTOR UTILITY FOR WORKING WITH THE EXTENSION TABS API BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.MOVE CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.CREATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.GETLASTFOCUSED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED CHROME.WINDOWS.REMOVE CHROME.WINDOWS.UPDATE", 
       "source_files": [
@@ -1513,7 +1522,7 @@
         "tabs_api.html"
       ], 
       "source_hash": "3076b39a4302d8e86f456e6d7367129187cce0c0", 
-      "zip_path": "examples/api/tabs/inspector.zip"
+      "zip_path": "examples\\api\\tabs\\inspector.zip"
     }, 
     {
       "api_calls": [
@@ -1531,9 +1540,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "e1697cacebad05218798bf3e8a0f724517f0e8c3", 
+      "id": "1e28bcf89e80466f155ab3a01a76cf5f60cb4104", 
       "name": "Test Screenshot Extension", 
-      "path": "examples/api/tabs/screenshot/", 
+      "path": "examples\\api\\tabs\\screenshot\\", 
       "protocols": [], 
       "search_string": "TEST SCREENSHOT EXTENSION DEMONSTRATE SCREENSHOT FUNCTIONALITY IN THE CHROME.TABS API. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.EXTENSION.GETVIEWS CHROME.TABS.CAPTUREVISIBLETAB CHROME.TABS.CREATE CHROME.TABS.ONUPDATED", 
       "source_files": [
@@ -1543,7 +1552,7 @@
         "screenshot.js"
       ], 
       "source_hash": "6be9b92850e86ce311cc12a2cf0cda3b47ab5d58", 
-      "zip_path": "examples/api/tabs/screenshot.zip"
+      "zip_path": "examples\\api\\tabs\\screenshot.zip"
     }, 
     {
       "api_calls": [
@@ -1558,9 +1567,9 @@
         "tabs"
       ], 
       "icon": null, 
-      "id": "b3de91ab04b7d7a2670ca7ee9d740eb42cead0b6", 
+      "id": "7b375c0f2c88517b42a5a341ac77e0762b481233", 
       "name": "Typed URL History", 
-      "path": "examples/api/history/showHistory/", 
+      "path": "examples\\api\\history\\showHistory\\", 
       "protocols": [], 
       "search_string": "TYPED URL HISTORY READS YOUR HISTORY, AND SHOWS THE TOP TEN PAGES YOU GO TO BY TYPING THE URL. BROWSER_ACTION HISTORY TABS CHROME.HISTORY.GETVISITS CHROME.HISTORY.SEARCH CHROME.TABS.CREATE", 
       "source_files": [
@@ -1569,7 +1578,7 @@
         "typedUrls.js"
       ], 
       "source_hash": "72d5c3586feefc692c63039ce8bdb5f9d366c0e2", 
-      "zip_path": "examples/api/history/showHistory.zip"
+      "zip_path": "examples\\api\\history\\showHistory.zip"
     }
   ]
 }
\ No newline at end of file
diff --git a/chrome/common/extensions/docs/static/browserAction.html b/chrome/common/extensions/docs/static/browserAction.html
index 40da968..dbc3a53 100644
--- a/chrome/common/extensions/docs/static/browserAction.html
+++ b/chrome/common/extensions/docs/static/browserAction.html
@@ -47,7 +47,7 @@
   "name": "My extension",
   ...
   <b>"browser_action": {
-    "default_icon": "images/icon19.png", <em>// <b>required</b></em>
+    "default_icon": "images/icon19.png", <em>// optional</em>
     "default_title": "Google Mail",      <em>// optional; shown in tooltip</em>
     "default_popup": "popup.html"        <em>// optional</em>
   }</b>,
@@ -57,8 +57,7 @@
 <h2 id="ui">Parts of the UI</h2>
 
 <p>
-A browser action must have an <a href="#icon">icon</a>.
-It can also have
+A browser action can have an <a href="#icon">icon</a>,
 a <a href="#tooltip">tooltip</a>,
 a <a href="#badge">badge</a>,
 and a <a href="#popups">popup</a>.
diff --git a/chrome/common/extensions/docs/static/experimental.tts.html b/chrome/common/extensions/docs/static/experimental.tts.html
new file mode 100644
index 0000000..fb2a772
--- /dev/null
+++ b/chrome/common/extensions/docs/static/experimental.tts.html
@@ -0,0 +1,146 @@
+<p id="classSummary">
+Use the <code>chrome.experimental.tts</code> module to play synthesized
+text-to-speech (TTS) from your extension or packaged app, or to register
+as a speech provider for other extensions and packaged apps that want to speak.
+</p>
+
+<p class="note"><b>Give us feedback:</b> If you have suggestions,
+especially changes that should be made before stabilizing the first
+version of this API, please send your ideas to the
+<a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">chromium-extensions</a>
+group.</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>To enable this experimental API, visit
+<b>chrome://flags</b> and enable <b>Experimental Extension APIs</b>.
+
+<p>Chrome provides native support for speech on Windows (using SAPI
+5), Mac OS X, and Chrome OS, using speech synthesis capabilities
+provided by the operating system. On all platforms, the user can
+install extensions that register themselves as alternative speech
+synthesis providers.</p>
+
+<h2 id="generating_speech">Generating speech</h2>
+
+<p>Call <code>speak()</code> from your extension or
+packaged app to speak. For example:</p>
+
+<pre>chrome.experimental.tts.speak('Hello, world.');</pre>
+
+<p>You can provide options that control various properties of the speech,
+such as its rate, pitch, and more. For example:</p>
+
+<pre>chrome.experimental.tts.speak('Hello, world.', {'rate': 0.8});</pre>
+
+<p>It's also a good idea to specify the locale so that a synthesizer
+supporting that language (and regional dialect, if applicable) is chosen.</p>
+
+<pre>chrome.experimental.tts.speak(
+    'Hello, world.',
+    {
+      'locale': 'en-US',
+      'rate': 0.8
+    });</pre>
+
+<p>Not all speech engines will support all options.</p>
+
+<p>You can also pass a callback function that will be called when the
+speech has finished. For example, suppose we have an image on our page
+displaying a picture of a face with a closed mouth. We could open the mouth
+while speaking, and close it when done.</p>
+
+<pre>faceImage.src = 'open_mouth.png';
+chrome.experimental.tts.speak(
+    'Hello, world.', null, function() {
+      faceImage.src = 'closed_mouth.png';
+    });
+</pre>
+
+<p>To stop speaking immediately, just call <code>stop()</code>. Call
+<code>isSpeaking()</code> to find out if a TTS engine is currently speaking.</p>
+
+<p>You can check to see if an error occurred by checking
+<code>chrome.extension.lastError</code> inside the callback function.</p>
+
+<h2 id="ssml">SSML markup</h2>
+
+<p>Utterances used in this API may include markup using the
+<a href="http://www.w3.org/TR/speech-synthesis">Speech Synthesis Markup
+Language (SSML)</a>. For example:
+
+<pre>chrome.experimental.tts.speak('The &lt;emphasis&gt;second&lt;/emphasis&gt; word of this sentence was emphasized.');</pre>
+
+<p>Not all speech engines will support all SSML tags, and some may not support
+SSML at all, but all engines are expected to ignore any SSML they don't
+support and still speak the underlying text.</p>
+
+<h2 id="provider">Implementing a speech provider</h2>
+
+<p>An extension can register itself as a speech provider. By doing so, it
+can intercept some or all calls to functions such as
+<code>speak()</code> and <code>stop()</code> and provide an alternate
+implementation. Extensions are free to use any available web technology
+to provide speech, including streaming audio from a server, HTML5 audio,
+Native Client, or Flash. An extension could even do something different
+with the utterances, like display closed captions in a pop-up window or
+send them as log messages to a remote server.</p>
+
+<p>To provide TTS, an extension must first declare all voices it provides
+in the extension manifest, like this:</p>
+
+<pre>{
+  "name": "My TTS Provider",
+  "version": "1.0",
+  <b>"permissions": ["experimental"]
+  "tts": {
+    "voices": [
+      {
+        "voiceName": "Alice",
+        "locale": "en-US",
+        "gender": "female"
+      },
+      {
+        "voiceName": "Pat",
+        "locale": "en-US"
+      }
+    ]
+  },</b>
+  "background_page": "background.html",
+}</pre>
+
+<p>An extension can specify any number of voices. The three
+parameters&mdash;<code>voiceName</code>, <code>locale</code>,
+and <code>gender</code>&mdash;are all optional. If they are all unspecified,
+the extension will handle all speech from all clients. If any of them
+are specified, they can be used to filter speech requests. For
+example, if a voice only supports French, it should set the locale to
+'fr' (or something more specific like 'fr-FR') so that only utterances
+in that locale are routed to that extension.</p>
+
+<p>To handle speech calls, the extension should register listeners
+for <code>onSpeak</code> and <code>onStop</code>, like this:</p>
+
+<pre>var speakListener = function(utterance, options, callback) {
+  ...
+  callback();
+};
+var stopListener = function() {
+  ...
+};
+chrome.experimental.tts.onSpeak.addListener(speakListener);
+chrome.experimental.tts.onStop.addListener(stopListener);</pre>
+
+<p class="warning"><b>Important:</b> Don't forget to call the callback
+function from your speak listener!</p>
+
+<p>If an extension does not register listeners for both
+<code>onSpeak</code> and <code>onStop</code>, it will not intercept any
+speech calls, regardless of what is in the manifest.
+
+<p>The decision of whether or not to send a given speech request to an
+extension is based solely on whether the extension supports the given voice
+parameters in its manifest and has registered listeners
+for <code>onSpeak</code> and <code>onStop</code>. In other words,
+there's no way for an extension to receive a speech request and
+dynamically decide whether to handle it or not.</p>
diff --git a/chrome/common/extensions/docs/static/getstarted.html b/chrome/common/extensions/docs/static/getstarted.html
index 1121b58..f1ec273 100644
--- a/chrome/common/extensions/docs/static/getstarted.html
+++ b/chrome/common/extensions/docs/static/getstarted.html
@@ -65,7 +65,6 @@
       <img src="images/toolsmenu.gif" width="29" height="29" alt=""
         style="margin-top:0" />
       and choosing <b>Tools > Extensions</b>.
-      (On Mac, use <b>Window > Extensions</b>.)
       </li>
 
       <li>
diff --git a/chrome/common/extensions/docs/static/i18n.html b/chrome/common/extensions/docs/static/i18n.html
index 4d0f9b3..abe5c9e 100644
--- a/chrome/common/extensions/docs/static/i18n.html
+++ b/chrome/common/extensions/docs/static/i18n.html
@@ -265,7 +265,7 @@
 
 <pre>
 body {
-  <b>dir: __MSG_@@bidi_dir__;</b>
+  <b>direction: __MSG_@@bidi_dir__;</b>
 }
 
 div#header {
diff --git a/chrome/common/extensions/docs/static/override.html b/chrome/common/extensions/docs/static/override.html
index 6a4848d..83bbd5d 100644
--- a/chrome/common/extensions/docs/static/override.html
+++ b/chrome/common/extensions/docs/static/override.html
@@ -70,6 +70,11 @@
 manifest property.
 </p>
 
+<p class="note">
+<b>Note:</b>
+You cannot override the New Tab page in incognito windows.
+</p>
+
 <p>
 The following screenshots show the default New Tab page
 next to a custom New Tab page.
diff --git a/chrome/common/extensions/docs/static/pageAction.html b/chrome/common/extensions/docs/static/pageAction.html
index 3def87e..0ca6fea 100644
--- a/chrome/common/extensions/docs/static/pageAction.html
+++ b/chrome/common/extensions/docs/static/pageAction.html
@@ -46,7 +46,7 @@
   "name": "My extension",
   ...
   <b>"page_action": {
-    "default_icon": "icons/foo.png", <em>// <b>required</b></em>
+    "default_icon": "icons/foo.png", <em>// optional</em>
     "default_title": "Do action",    <em>// optional; shown in tooltip</em>
     "default_popup": "popup.html"    <em>// optional</em>
   }</b>,
@@ -57,8 +57,8 @@
 
 <p>
 Like browser actions,
-page actions have an icon and
-can also have a tooltip and popup;
+page actions can have an icon,
+a tooltip, and popup;
 they can't have badges, however.
 In addition, page actions can appear and disappear.
 You can find information about icons, tooltips, and popups
@@ -95,15 +95,6 @@
     for features that make sense
     for most pages.
     Use <a href="browserAction.html">browser actions</a> instead.
-  <li><b>Do</b> use icons
-    that are slightly lighter weight
-    than <a href="browserAction.html#icon">browser action icons</a>.
-    Most icons that Chrome displays
-    in the location bar
-    are smaller than 19 pixels.
-    If the edge pixels are used,
-    they are usually only used
-    for a faint shadow.
   <li><b>Don't</b> constantly animate your icon.
     That's just annoying.
 </ul>
diff --git a/chrome/common/extensions/docs/static/permission_warnings.html b/chrome/common/extensions/docs/static/permission_warnings.html
index 4671f58..b70280f 100644
--- a/chrome/common/extensions/docs/static/permission_warnings.html
+++ b/chrome/common/extensions/docs/static/permission_warnings.html
@@ -109,7 +109,7 @@
 <p>
 It can be surprising when adding a permission such as "tabs"
 results in the seemingly unrelated warning
-that the extension can access your browsing history.
+that the extension can access your browsing activity.
 The reason for the warning is that
 although the <code>chrome.tabs</code> API
 might be used only to open new tabs,
@@ -174,7 +174,24 @@
   </td>
   <td>
     <!-- HasEffectiveBrowsingHistoryPermission -->
-     "history" or "tabs" permission
+     "history" permission
+  </td>
+  <td>
+    <p>
+      The "history" permission is required by
+      <a href="history.html"><code>chrome.history</code></a>.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td style="font-weight:bold">
+    <!-- IDS_EXTENSION_PROMPT_WARNING_TABS -->
+    Your tabs and browsing activity
+  </td>
+  <td>
+    <!-- HasEffectiveBrowsingHistoryPermission -->
+     "tabs" permission
   </td>
   <td>
     <p>
@@ -182,15 +199,6 @@
       <a href="tabs.html"><code>chrome.tabs</code></a> and 
       <a href="windows.html"><code>chrome.windows</code></a> modules.
     </p>
-    <p>
-      The "history" permission is required by
-      <a href="history.html"><code>chrome.history</code></a>.
-    </p>
-    <p>
-      Adding "tabs" to an existing extension
-      that already has "history", or vice versa,
-      doesn't cause a warning when the extension is autoupdated.
-    </p>
   </td>
 </tr>
 
diff --git a/chrome/common/extensions/docs/static/themes.html b/chrome/common/extensions/docs/static/themes.html
index 0d04779..651a74d 100644
--- a/chrome/common/extensions/docs/static/themes.html
+++ b/chrome/common/extensions/docs/static/themes.html
@@ -66,7 +66,7 @@
 Colors are in RGB format.
 To find the strings you can use within the "colors" field,
 look for kColor* strings in
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 </p>
 
 <h3 id="images">images</h3>
@@ -75,7 +75,7 @@
 Image resources use paths relative to the root of the extension.
 You can override any of the images that are specified by
 <code>kThemeableImages</code> in
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 Just remove the "IDR_"
 and convert the remaining characters to lowercase.
 For example, <code>IDR_THEME_NTP_BACKGROUND</code>
@@ -92,7 +92,7 @@
 background repeat,
 and an alternate logo.
 To see the properties and the values they can have, see
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 <!-- [PENDING: We should flesh this out.] -->
 </p>
 
@@ -106,7 +106,7 @@
 and are brittle in the case of adding new buttons.
 To find the strings you can use within the "tints" field,
 look for kTint* strings in
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 </p>
 
 <p>
diff --git a/chrome/common/extensions/docs/static/tut_debugging.html b/chrome/common/extensions/docs/static/tut_debugging.html
index 20d46c5..7713e90 100644
--- a/chrome/common/extensions/docs/static/tut_debugging.html
+++ b/chrome/common/extensions/docs/static/tut_debugging.html
@@ -38,7 +38,7 @@
       find the extension files and load them.
       If you don't have a handy copy of the files,
       extract them from this
-      <a href="examples/tutorials/getstarted/getstarted.zip">ZIP file</a>.
+      <a href="examples/tutorials/getstarted.zip">ZIP file</a>.
       See Getting Started if you need
       <a href="getstarted.html#load-ext">instructions
       for loading the extension</a>.
diff --git a/chrome/common/extensions/docs/tabs.html b/chrome/common/extensions/docs/tabs.html
index 91e75e6..1708562 100644
--- a/chrome/common/extensions/docs/tabs.html
+++ b/chrome/common/extensions/docs/tabs.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -274,7 +284,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-captureVisibleTab">captureVisibleTab</a>
@@ -308,7 +318,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onAttached">onAttached</a>
@@ -420,8 +430,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -495,6 +505,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -598,6 +618,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -656,6 +686,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -666,6 +706,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -726,6 +776,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -812,6 +872,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -903,6 +973,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1008,6 +1088,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1018,6 +1108,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1082,6 +1182,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1240,6 +1350,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1298,6 +1418,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1356,6 +1486,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1414,6 +1554,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1472,6 +1622,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1482,6 +1642,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1542,6 +1712,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1628,6 +1808,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1717,6 +1907,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1777,6 +1977,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1863,6 +2073,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1953,6 +2173,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2056,6 +2286,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2114,6 +2354,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2172,6 +2422,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2182,6 +2442,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2240,6 +2510,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2362,6 +2642,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2422,6 +2712,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2510,6 +2810,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2599,6 +2909,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2659,6 +2979,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2758,6 +3088,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2848,6 +3188,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2936,6 +3286,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3025,6 +3385,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3085,6 +3455,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3173,6 +3553,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3263,6 +3653,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3366,6 +3766,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3424,6 +3834,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3482,6 +3902,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3492,6 +3922,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3550,6 +3990,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3673,6 +4123,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3778,6 +4238,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3836,6 +4306,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3846,6 +4326,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3906,6 +4396,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3992,6 +4492,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4083,6 +4593,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4143,6 +4663,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4266,6 +4796,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4326,6 +4866,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4386,6 +4936,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div>
@@ -4443,6 +5003,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4535,6 +5105,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4627,6 +5207,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4732,6 +5322,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4790,6 +5390,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4848,6 +5458,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4858,6 +5478,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -4918,6 +5548,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5004,6 +5644,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5029,10 +5679,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onAttached"></a>
@@ -5048,10 +5697,11 @@
                 <p>Fired when a tab is attached to a window, for example because it was moved between windows.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tabId</var>
               <em>
@@ -5104,14 +5754,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>attachInfo</var>
               <em>
@@ -5211,6 +5871,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5271,6 +5941,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5281,15 +5961,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -5306,10 +5996,11 @@
                 <p>Fires when a tab is created. Note that the tab's URL may not be set at the time this event fires, but you can listen to onUpdated events to be notified when a URL is set.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tab</var>
               <em>
@@ -5360,15 +6051,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -5385,10 +6086,11 @@
                 <p>Fired when a tab is detached from a window, for example because it is being moved between windows.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tabId</var>
               <em>
@@ -5441,14 +6143,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>detachInfo</var>
               <em>
@@ -5548,6 +6260,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5608,6 +6330,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5618,15 +6350,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -5643,10 +6385,11 @@
                 <p>Fires when a tab is moved within a window. Only one move event is fired, representing the tab the user directly moved. Move events are not fired for the other tabs that must move in response. This event is not fired when a tab is moved between windows. For that, see <a href="#event-onDetached">onDetached</a>.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tabId</var>
               <em>
@@ -5699,14 +6442,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>moveInfo</var>
               <em>
@@ -5806,6 +6559,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5866,6 +6629,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5926,6 +6699,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -5936,15 +6719,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -5961,10 +6754,11 @@
                 <p>Fires when a tab is closed.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tabId</var>
               <em>
@@ -6017,14 +6811,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>removeInfo</var>
               <em>
@@ -6122,6 +6926,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6132,15 +6946,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -6157,10 +6981,11 @@
                 <p>Fires when the selected tab in a window changes.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tabId</var>
               <em>
@@ -6211,14 +7036,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>selectInfo</var>
               <em>
@@ -6316,6 +7151,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6326,15 +7171,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -6351,10 +7206,11 @@
                 <p>Fires when a tab is updated.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>tabId</var>
               <em>
@@ -6407,14 +7263,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>changeInfo</var>
               <em>
@@ -6510,6 +7376,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6568,6 +7444,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6626,6 +7512,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6636,14 +7532,24 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div><div>
-                    <div>
+                    </div><div>
+                      <div>
           <dt>
             <var>tab</var>
               <em>
@@ -6694,15 +7600,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -6817,6 +7733,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6875,6 +7801,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6933,6 +7869,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -6991,6 +7937,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7049,6 +8005,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7107,6 +8073,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7165,6 +8141,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7223,6 +8209,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7281,6 +8277,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7339,6 +8345,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -7349,6 +8365,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/template/api_template.html b/chrome/common/extensions/docs/template/api_template.html
index 1b47011..ae5a94d 100644
--- a/chrome/common/extensions/docs/template/api_template.html
+++ b/chrome/common/extensions/docs/template/api_template.html
@@ -21,7 +21,8 @@
                     <span class="enum" jsdisplay="enum">enumerated</span>
                     <span id="typeTemplate">
                       <span jsdisplay="getTypeRef($this)">
-                        <a jsvalues=".href: getTypeRefPage($this) + '#type-' + getTypeRef($this)" jscontent="getTypeRef($this)"> Type</a>
+                        <a jsvalues=".href: getTypeRefPage($this) + '#type-' + getTypeRef($this)"
+                           jscontent="getTypeRef($this)"> Type</a>
                       </span>
                       <span jsdisplay="!getTypeRef($this)">
                         <span jsdisplay="isArray($this)">
@@ -63,6 +64,20 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd jsdisplay="$this.type === 'object' &&
+                         $this.functions && $this.functions.length > 0"
+              jsvalues="$scope:id">
+            <div transclude="methodsTemplate"></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd jsdisplay="$this.type === 'object' &&
+                         $this.events && $this.events.length > 0"
+              jsvalues="$scope:id">
+            <div transclude="eventsTemplate"></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd jsdisplay="isFunction($this) && $this.parameters &&
                          $this.name != 'callback'">
@@ -257,23 +272,23 @@
                     </ol>
                   </li>
                   <li jsdisplay="functions && functions.length > 0">
-                    <a href="#methods">Methods</a>
+                    <a jsvalues=".href:'#' + getAnchorName('global', 'methods')">Methods</a>
                     <ol>
                       <li jsselect="functions.sort(sortByName)"
                           jsdisplay="!($this.nodoc)">
                         <a jscontent="name"
-                           jsvalues=".href:'#method-' + name"
+                           jsvalues=".href:'#' + getAnchorName('method', name)"
                            href="#method-anchor">methodName</a>
                       </li>
                     </ol>
                   </li>
                   <li jsdisplay="events && events.length > 0">
-                    <a href="#events">Events</a>
+                    <a jsvalues=".href:'#' + getAnchorName('global', 'events')">Events</a>
                     <ol>
                       <li jsselect="events.sort(sortByName)"
                           jsdisplay="!($this.nodoc)">
                         <a jscontent="name"
-                           jsvalues=".href:'#event-' + name"
+                           jsvalues=".href:'#' + getAnchorName('event', name)"
                            href="#event-anchor">eventName</a>
                       </li>
                     </ol>
@@ -303,7 +318,7 @@
         <div id="static"></div>
 
         <!-- API PAGE -->
-        <div class="apiPage" jsselect="apiDefinition">
+        <div class="apiPage" jsselect="apiDefinition" jsvalues="$scope:''">
         <a name="apiReference"></a>
         <h2 jscontent="'API reference: ' + getModuleName()">API reference: chrome.apiname </h2>
 
@@ -326,19 +341,20 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div jsdisplay="functions && functions.length > 0" class="apiGroup" id="methods">
-            <a name="methods"></a>
-            <h3>Methods</h3>
+          <div id="methodsTemplate" class="apiGroup"
+               jsdisplay="$this.functions && $this.functions.length > 0">
+            <a jsvalues=".name:getAnchorName('global', 'methods', $scope)"></a>
+            <h3 jscontent="$scope ? 'Methods of ' + $scope : 'Methods'">Methods</h3>
 
             <!-- iterates over all functions -->
             <div class="apiItem" jsselect="functions.sort(sortByName)"
                  jsdisplay="!($this.nodoc)">
-              <a jsvalues=".name:'method-' + name"></a> <!-- method-anchor -->
+              <a jsvalues=".name:getAnchorName('method', name, $scope)"></a> <!-- method-anchor -->
               <h4 jscontent="name">method name</h4>
 
               <div class="summary"><span jsdisplay="returns" jscontent="getTypeName(returns)">void</span>
                   <!-- Note: intentionally longer 80 columns -->
-                  <span jscontent="getFullyQualifiedFunctionName($this)">chrome.module.methodName</span>(<span jsselect="parameters" jsvalues="class:optional ? 'optional' : ''"><span jsdisplay="$index">, </span><span jscontent="getTypeName($this)"></span>
+                  <span jscontent="getFullyQualifiedFunctionName($scope, $this)">chrome.module.methodName</span>(<span jsselect="parameters" jsvalues="class:optional ? 'optional' : ''"><span jsdisplay="$index">, </span><span jscontent="getTypeName($this)"></span>
                       <var><span jscontent="$this.name"></span></var></span>)</div>
 
               <div class="description">
@@ -348,7 +364,7 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
+                <h4 jsdisplay="$this.parameters && $this.parameters.length > 0">Parameters</h4>
                 <dl>
                   <div jsselect="parameters">
                     <div transclude="valueTemplate">
@@ -403,19 +419,19 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div jsdisplay="events && events.length > 0" class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup"
+               jsdisplay="$this.events && $this.events.length > 0">
+            <a jsvalues=".name:getAnchorName('global', 'events', $scope)"></a>
+            <h3 jscontent="$scope ? 'Events of ' + $scope : 'Events'">Events</h3>
             <!-- iterates over all events -->
-            <div jsselect="events.sort(sortByName)" class="apiItem"
+            <div class="apiItem" jsselect="$this.events.sort(sortByName)"
                  jsdisplay="!($this.nodoc)">
-              <a jsvalues=".name:'event-' + name"></a>
+              <a jsvalues=".name:getAnchorName('event', name, $scope)"></a>
               <h4 jscontent="name">event name</h4>
 
               <div class="summary">
                 <!-- Note: intentionally longer 80 columns -->
-                <span jscontent="getModuleName() + '.'" class="subdued">chrome.bookmarks</span><span jscontent="name">onEvent</span><span class="subdued">.addListener</span>(function(<span jscontent="getSignatureString(parameters)">Type param1, Type param2</span>) <span class="subdued">{...}</span>);
+                <span jscontent="(getObjectName($scope) || getModuleName()) + '.'" class="subdued">chrome.bookmarks</span><span jscontent="name">onEvent</span><span class="subdued">.addListener</span>(function(<span jscontent="getSignatureString($this.parameters)">Type param1, Type param2</span>) <span class="subdued">{...}</span>);
               </div>
 
               <div class="description">
@@ -425,14 +441,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div jsselect="parameters">
-                    <div transclude="valueTemplate">
+                <div jsdisplay="parameters && parameters.length > 0">
+                  <h4>Parameters</h4>
+                  <dl>
+                    <div jsselect="parameters">
+                      <div transclude="valueTemplate">
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/themes.html b/chrome/common/extensions/docs/themes.html
index 56c5cf0..d2eafef 100644
--- a/chrome/common/extensions/docs/themes.html
+++ b/chrome/common/extensions/docs/themes.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -280,7 +290,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -288,7 +298,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -379,7 +389,7 @@
 Colors are in RGB format.
 To find the strings you can use within the "colors" field,
 look for kColor* strings in
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 </p>
 
 <h3 id="images">images</h3>
@@ -388,7 +398,7 @@
 Image resources use paths relative to the root of the extension.
 You can override any of the images that are specified by
 <code>kThemeableImages</code> in
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 Just remove the "IDR_"
 and convert the remaining characters to lowercase.
 For example, <code>IDR_THEME_NTP_BACKGROUND</code>
@@ -405,7 +415,7 @@
 background repeat,
 and an alternate logo.
 To see the properties and the values they can have, see
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 <!-- [PENDING: We should flesh this out.] -->
 </p>
 
@@ -419,7 +429,7 @@
 and are brittle in the case of adding new buttons.
 To find the strings you can use within the "tints" field,
 look for kTint* strings in
-<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
+<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/browser_theme_provider.cc"><code>browser_theme_provider.cc</code></a>.
 </p>
 
 <p>
@@ -486,8 +496,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -562,10 +572,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -583,14 +592,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/tut_analytics.html b/chrome/common/extensions/docs/tut_analytics.html
index 4c695ff..47368aa 100644
--- a/chrome/common/extensions/docs/tut_analytics.html
+++ b/chrome/common/extensions/docs/tut_analytics.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -302,7 +312,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -310,7 +320,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -554,8 +564,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -630,10 +640,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -651,14 +660,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/tut_debugging.html b/chrome/common/extensions/docs/tut_debugging.html
index 3111f76..896d392 100644
--- a/chrome/common/extensions/docs/tut_debugging.html
+++ b/chrome/common/extensions/docs/tut_debugging.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -295,7 +305,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -303,7 +313,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -368,7 +378,7 @@
       find the extension files and load them.
       If you don't have a handy copy of the files,
       extract them from this
-      <a href="examples/tutorials/getstarted/getstarted.zip">ZIP file</a>.
+      <a href="examples/tutorials/getstarted.zip">ZIP file</a>.
       See Getting Started if you need
       <a href="getstarted.html#load-ext">instructions
       for loading the extension</a>.
@@ -602,8 +612,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -678,10 +688,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -699,14 +708,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/tut_oauth.html b/chrome/common/extensions/docs/tut_oauth.html
index 1d21c96..e3ee096 100644
--- a/chrome/common/extensions/docs/tut_oauth.html
+++ b/chrome/common/extensions/docs/tut_oauth.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -292,7 +302,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -300,7 +310,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -544,8 +554,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -620,10 +630,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -641,14 +650,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/tutorials.html b/chrome/common/extensions/docs/tutorials.html
index 8657aed..8f55e51 100644
--- a/chrome/common/extensions/docs/tutorials.html
+++ b/chrome/common/extensions/docs/tutorials.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -357,8 +367,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -433,10 +443,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -454,14 +463,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/whats_new.html b/chrome/common/extensions/docs/whats_new.html
index 9e2b8ed..31f2485 100644
--- a/chrome/common/extensions/docs/whats_new.html
+++ b/chrome/common/extensions/docs/whats_new.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -469,8 +479,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -545,10 +555,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -566,14 +575,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/docs/windows.html b/chrome/common/extensions/docs/windows.html
index 6de42ce..a6cb357 100644
--- a/chrome/common/extensions/docs/windows.html
+++ b/chrome/common/extensions/docs/windows.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -281,7 +291,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a href="#global-methods">Methods</a>
                     <ol>
                       <li>
                         <a href="#method-create">create</a>
@@ -301,7 +311,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a href="#global-events">Events</a>
                     <ol>
                       <li>
                         <a href="#event-onCreated">onCreated</a>
@@ -475,6 +485,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -486,8 +506,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a name="global-methods"></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -607,6 +627,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -665,6 +695,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -723,6 +763,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -781,6 +831,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -839,6 +899,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -897,6 +967,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -955,6 +1035,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1013,6 +1103,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1023,6 +1123,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1083,6 +1193,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1169,6 +1289,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1260,6 +1390,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1320,6 +1460,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1408,6 +1558,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1544,6 +1704,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1554,6 +1724,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1614,6 +1794,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1713,6 +1903,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1803,6 +2003,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1891,6 +2101,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -1981,6 +2201,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2069,6 +2299,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2160,6 +2400,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2220,6 +2470,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2343,6 +2603,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2448,6 +2718,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2506,6 +2786,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2564,6 +2854,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2622,6 +2922,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2680,6 +2990,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2690,6 +3010,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2750,6 +3080,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2838,6 +3178,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -2863,10 +3213,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a name="global-events"></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a name="event-onCreated"></a>
@@ -2882,10 +3231,11 @@
                 <p>Fired when a window is created.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>window</var>
               <em>
@@ -2936,15 +3286,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -2961,10 +3321,11 @@
                 <p>Fired when the currently focused window changes. Will be chrome.windows.WINDOW_ID_NONE if all chrome windows have lost focus. Note: On some Linux window managers, WINDOW_ID_NONE will always be sent immediately preceding a switch from one chrome window to another.</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>windowId</var>
               <em>
@@ -3015,15 +3376,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div><div class="apiItem">
@@ -3040,10 +3411,11 @@
                 <p>Fired when a window is removed (closed).</p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
           <dt>
             <var>windowId</var>
               <em>
@@ -3094,15 +3466,25 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
           </dd>
 
         </div>
-                  </div>
-                </dl>
-
+                    </div>
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
@@ -3217,6 +3599,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3275,6 +3667,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3333,6 +3735,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3391,6 +3803,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3449,6 +3871,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3507,6 +3939,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3576,6 +4018,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3634,6 +4086,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3692,6 +4154,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
@@ -3702,6 +4174,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd style="display: none; ">
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd style="display: none; ">
             <div></div>
diff --git a/chrome/common/extensions/docs/xhr.html b/chrome/common/extensions/docs/xhr.html
index 4710c3e..b740325 100644
--- a/chrome/common/extensions/docs/xhr.html
+++ b/chrome/common/extensions/docs/xhr.html
@@ -81,6 +81,16 @@
             </dl>
           </dd>
 
+          <!-- OBJECT METHODS -->
+          <dd>
+            <div></div>
+          </dd>
+
+          <!-- OBJECT EVENT FIELDS -->
+          <dd>
+            <div></div>
+          </dd>
+
           <!-- FUNCTION PARAMETERS -->
           <dd>
             <div></div>
@@ -267,7 +277,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#methods">Methods</a>
+                    <a>Methods</a>
                     <ol>
                       <li>
                         <a href="#method-anchor">methodName</a>
@@ -275,7 +285,7 @@
                     </ol>
                   </li>
                   <li>
-                    <a href="#events">Events</a>
+                    <a>Events</a>
                     <ol>
                       <li>
                         <a href="#event-anchor">eventName</a>
@@ -487,8 +497,8 @@
           </div> <!-- /apiGroup -->
 
           <!-- METHODS -->
-          <div class="apiGroup" id="methods">
-            <a name="methods"></a>
+          <div id="methodsTemplate" class="apiGroup">
+            <a></a>
             <h3>Methods</h3>
 
             <!-- iterates over all functions -->
@@ -563,10 +573,9 @@
           </div>  <!-- /apiGroup -->
 
           <!-- EVENTS -->
-          <div class="apiGroup">
-            <a name="events"></a>
-            <h3 id="events">Events</h3>
-
+          <div id="eventsTemplate" class="apiGroup">
+            <a></a>
+            <h3>Events</h3>
             <!-- iterates over all events -->
             <div class="apiItem">
               <a></a>
@@ -584,14 +593,15 @@
                 </p>
 
                 <!-- PARAMETERS -->
-                <h4>Parameters</h4>
-                <dl>
-                  <div>
+                <div>
+                  <h4>Parameters</h4>
+                  <dl>
                     <div>
+                      <div>
+                      </div>
                     </div>
-                  </div>
-                </dl>
-
+                  </dl>
+                </div>
               </div> <!-- /decription -->
 
             </div> <!-- /apiItem -->
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index bdbb33a..fb96f92 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/base64.h"
 #include "base/basictypes.h"
 #include "base/command_line.h"
@@ -18,6 +17,7 @@
 #include "base/singleton.h"
 #include "base/stl_util-inl.h"
 #include "base/third_party/nss/blapi.h"
+#include "base/string16.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
@@ -30,6 +30,8 @@
 #include "chrome/common/extensions/extension_error_utils.h"
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/extensions/extension_sidebar_defaults.h"
+#include "chrome/common/extensions/extension_sidebar_utils.h"
 #include "chrome/common/extensions/user_script.h"
 #include "chrome/common/url_constants.h"
 #include "googleurl/src/url_util.h"
@@ -37,6 +39,7 @@
 #include "grit/generated_resources.h"
 #include "net/base/registry_controlled_domain.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "webkit/glue/image_decoder.h"
 
 namespace keys = extension_manifest_keys;
@@ -194,6 +197,7 @@
 
 const int Extension::kPageActionIconMaxSize = 19;
 const int Extension::kBrowserActionIconMaxSize = 19;
+const int Extension::kSidebarIconMaxSize = 16;
 
 // Explicit permissions -- permission declaration required.
 const char Extension::kBackgroundPermission[] = "background";
@@ -226,7 +230,7 @@
   { kManagementPermission, IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT },
   { kNotificationPermission, 0 },
   { kProxyPermission, 0 },
-  { kTabPermission, IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY },
+  { kTabPermission, IDS_EXTENSION_PROMPT_WARNING_TABS },
   { kUnlimitedStoragePermission, 0 },
   { kWebstorePrivatePermission, 0 },
 };
@@ -804,6 +808,52 @@
   return result.release();
 }
 
+ExtensionSidebarDefaults* Extension::LoadExtensionSidebarDefaults(
+    const DictionaryValue* extension_sidebar, std::string* error) {
+  scoped_ptr<ExtensionSidebarDefaults> result(new ExtensionSidebarDefaults());
+
+  std::string default_icon;
+  // Read sidebar's |default_icon| (optional).
+  if (extension_sidebar->HasKey(keys::kSidebarDefaultIcon)) {
+    if (!extension_sidebar->GetString(keys::kSidebarDefaultIcon,
+                                      &default_icon) ||
+        default_icon.empty()) {
+      *error = errors::kInvalidSidebarDefaultIconPath;
+      return NULL;
+    }
+    result->set_default_icon_path(default_icon);
+  }
+
+  // Read sidebar's |default_title| (optional).
+  string16 default_title;
+  if (extension_sidebar->HasKey(keys::kSidebarDefaultTitle)) {
+    if (!extension_sidebar->GetString(keys::kSidebarDefaultTitle,
+                                      &default_title)) {
+      *error = errors::kInvalidSidebarDefaultTitle;
+      return NULL;
+    }
+  }
+  result->set_default_title(default_title);
+
+  // Read sidebar's |default_page| (optional).
+  std::string default_page;
+  if (extension_sidebar->HasKey(keys::kSidebarDefaultPage)) {
+    if (!extension_sidebar->GetString(keys::kSidebarDefaultPage,
+                                      &default_page) ||
+        default_page.empty()) {
+      *error = errors::kInvalidSidebarDefaultPage;
+      return NULL;
+    }
+    GURL url = extension_sidebar_utils::ResolveRelativePath(
+        default_page, this, error);
+    if (!url.is_valid())
+      return NULL;
+    result->set_default_page(url);
+  }
+
+  return result.release();
+}
+
 bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) const {
   for (DictionaryValue::key_iterator key = source.begin_keys();
        key != source.end_keys(); ++key) {
@@ -1194,8 +1244,7 @@
 
   std::string file_contents;
   if (!file_util::ReadFileToString(icon_path, &file_contents)) {
-    LOG(ERROR) << "Could not read icon file: "
-               << WideToUTF8(icon_path.ToWStringHack());
+    LOG(ERROR) << "Could not read icon file: " << icon_path.LossyDisplayName();
     return;
   }
 
@@ -1207,7 +1256,7 @@
   *decoded = decoder.Decode(data, file_contents.length());
   if (decoded->empty()) {
     LOG(ERROR) << "Could not decode icon file: "
-               << WideToUTF8(icon_path.ToWStringHack());
+               << icon_path.LossyDisplayName();
     return;
   }
 
@@ -1253,8 +1302,7 @@
   }
 
   // Make a copy of the manifest so we can store it in prefs.
-  manifest_value_.reset(
-      static_cast<DictionaryValue*>(source.DeepCopy()));
+  manifest_value_.reset(source.DeepCopy());
 
   // Initialize the URL.
   extension_url_ =
@@ -1426,8 +1474,7 @@
           return false;
         }
       }
-      theme_images_.reset(
-          static_cast<DictionaryValue*>(images_value->DeepCopy()));
+      theme_images_.reset(images_value->DeepCopy());
     }
 
     DictionaryValue* colors_value;
@@ -1445,7 +1492,7 @@
             ((color_list->GetSize() != 3) &&
              ((color_list->GetSize() != 4) ||
               // For RGBA, the fourth item must be a real or int alpha value
-              (!color_list->GetReal(3, &alpha) &&
+              (!color_list->GetDouble(3, &alpha) &&
                !color_list->GetInteger(3, &alpha_int)))) ||
             // For both RGB and RGBA, the first three items must be ints (R,G,B)
             !color_list->GetInteger(0, &color) ||
@@ -1455,8 +1502,7 @@
           return false;
         }
       }
-      theme_colors_.reset(
-          static_cast<DictionaryValue*>(colors_value->DeepCopy()));
+      theme_colors_.reset(colors_value->DeepCopy());
     }
 
     DictionaryValue* tints_value;
@@ -1469,22 +1515,21 @@
         int vi;
         if (!tints_value->GetListWithoutPathExpansion(*iter, &tint_list) ||
             tint_list->GetSize() != 3 ||
-            !(tint_list->GetReal(0, &v) || tint_list->GetInteger(0, &vi)) ||
-            !(tint_list->GetReal(1, &v) || tint_list->GetInteger(1, &vi)) ||
-            !(tint_list->GetReal(2, &v) || tint_list->GetInteger(2, &vi))) {
+            !(tint_list->GetDouble(0, &v) || tint_list->GetInteger(0, &vi)) ||
+            !(tint_list->GetDouble(1, &v) || tint_list->GetInteger(1, &vi)) ||
+            !(tint_list->GetDouble(2, &v) || tint_list->GetInteger(2, &vi))) {
           *error = errors::kInvalidThemeTints;
           return false;
         }
       }
-      theme_tints_.reset(
-          static_cast<DictionaryValue*>(tints_value->DeepCopy()));
+      theme_tints_.reset(tints_value->DeepCopy());
     }
 
     DictionaryValue* display_properties_value;
     if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
         &display_properties_value)) {
       theme_display_properties_.reset(
-          static_cast<DictionaryValue*>(display_properties_value->DeepCopy()));
+          display_properties_value->DeepCopy());
     }
 
     return true;
@@ -1813,6 +1858,9 @@
 #if defined(TOUCH_UI)
            page != chrome::kChromeUIKeyboardHost &&
 #endif
+#if defined(OS_CHROMEOS)
+           page != chrome::kChromeUIActivationMessageHost &&
+#endif
            page != chrome::kChromeUIBookmarksHost &&
            page != chrome::kChromeUIHistoryHost) ||
           !overrides->GetStringWithoutPathExpansion(*iter, &val)) {
@@ -1852,6 +1900,22 @@
     devtools_url_ = GetResourceURL(devtools_str);
   }
 
+  // Initialize sidebar action (optional).
+  if (source.HasKey(keys::kSidebar)) {
+    DictionaryValue* sidebar_value;
+    if (!source.GetDictionary(keys::kSidebar, &sidebar_value)) {
+      *error = errors::kInvalidSidebar;
+      return false;
+    }
+    if (!HasApiPermission(Extension::kExperimentalPermission)) {
+      *error = errors::kSidebarExperimental;
+      return false;
+    }
+    sidebar_defaults_.reset(LoadExtensionSidebarDefaults(sidebar_value, error));
+    if (!sidebar_defaults_.get())
+      return false;  // Failed to parse sidebar definition.
+  }
+
   // Initialize text-to-speech voices (optional).
   if (source.HasKey(keys::kTts)) {
     DictionaryValue* tts_dict;
@@ -2023,7 +2087,7 @@
 
 // static
 void Extension::SetScriptingWhitelist(
-    const std::vector<std::string>& whitelist) {
+    const Extension::ScriptingWhitelist& whitelist) {
   ScriptingWhitelist* current_whitelist =
       ExtensionConfig::GetInstance()->whitelist();
   current_whitelist->clear();
@@ -2033,6 +2097,11 @@
   }
 }
 
+// static
+const Extension::ScriptingWhitelist* Extension::GetScriptingWhitelist() {
+  return ExtensionConfig::GetInstance()->whitelist();
+}
+
 void Extension::SetCachedImage(const ExtensionResource& source,
                                const SkBitmap& image,
                                const gfx::Size& original_size) const {
@@ -2188,21 +2257,16 @@
   return num_surfaces > 1;
 }
 
-// static
-bool Extension::CanExecuteScriptOnPage(
-    const GURL& page_url, bool can_execute_script_everywhere,
-    const std::vector<URLPattern>* host_permissions,
-    UserScript* script,
-    std::string* error) {
-  DCHECK(!(host_permissions && script)) << "Shouldn't specify both";
-
+bool Extension::CanExecuteScriptOnPage(const GURL& page_url,
+                                       UserScript* script,
+                                       std::string* error) const {
   // The gallery is special-cased as a restricted URL for scripting to prevent
   // access to special JS bindings we expose to the gallery (and avoid things
   // like extensions removing the "report abuse" link).
   // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing
   // against the store app extent?
   if ((page_url.host() == GURL(Extension::ChromeStoreLaunchURL()).host()) &&
-      !can_execute_script_everywhere &&
+      !CanExecuteScriptEverywhere() &&
       !CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kAllowScriptingGallery)) {
     if (error)
@@ -2210,14 +2274,14 @@
     return false;
   }
 
-  if (host_permissions) {
-    for (size_t i = 0; i < host_permissions->size(); ++i) {
-      if ((*host_permissions)[i].MatchesUrl(page_url))
-        return true;
-    }
-  }
-  if (script) {
-    if (script->MatchesUrl(page_url))
+  // If a script is specified, use its matches.
+  if (script)
+    return script->MatchesUrl(page_url);
+
+  // Otherwise, see if this extension has permission to execute script
+  // programmatically on pages.
+  for (size_t i = 0; i < host_permissions_.size(); ++i) {
+    if (host_permissions_[i].MatchesUrl(page_url))
       return true;
   }
 
@@ -2257,6 +2321,14 @@
   return plugins().size() > 0;
 }
 
+bool Extension::ShowConfigureContextMenus() const {
+  // Don't show context menu for component extensions. We might want to show
+  // options for component extension button but now there is no component
+  // extension with options. All other menu items like uninstall have
+  // no sense for component extensions.
+  return location() != Extension::COMPONENT;
+}
+
 bool Extension::IsAPIPermission(const std::string& str) const {
   for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
     if (str == Extension::kPermissions[i].name) {
@@ -2296,8 +2368,7 @@
       extension_path(path),
       extension_location(location) {
   if (manifest)
-    extension_manifest.reset(
-        static_cast<DictionaryValue*>(manifest->DeepCopy()));
+    extension_manifest.reset(manifest->DeepCopy());
 }
 
 ExtensionInfo::~ExtensionInfo() {}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 4c82fd6..0edb6e2 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -20,12 +20,13 @@
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/user_script.h"
 #include "chrome/common/extensions/url_pattern.h"
-#include "gfx/size.h"
 #include "googleurl/src/gurl.h"
+#include "ui/gfx/size.h"
 
 class DictionaryValue;
 class ExtensionAction;
 class ExtensionResource;
+class ExtensionSidebarDefaults;
 class SkBitmap;
 class Version;
 
@@ -151,6 +152,7 @@
   // Max size (both dimensions) for browser and page actions.
   static const int kPageActionIconMaxSize;
   static const int kBrowserActionIconMaxSize;
+  static const int kSidebarIconMaxSize;
 
   // Each permission is a module that the extension is permitted to use.
   //
@@ -306,22 +308,9 @@
   // ExtensionService::IsDownloadFromGallery
   static std::string ChromeStoreLaunchURL();
 
-  // Helper function that consolidates the check for whether the script can
-  // execute into one location. |page_url| is the page that is the candidate
-  // for running the script, |can_execute_script_everywhere| specifies whether
-  // the extension is on the whitelist, |allowed_pages| is a vector of
-  // URLPatterns, listing what access the extension has, |script| is the script
-  // pointer (if content script) and |error| is an optional parameter, which
-  // will receive the error string listing why access was denied.
-  static bool CanExecuteScriptOnPage(
-      const GURL& page_url,
-      bool can_execute_script_everywhere,
-      const std::vector<URLPattern>* allowed_pages,
-      UserScript* script,
-      std::string* error);
-
   // Adds an extension to the scripting whitelist. Used for testing only.
   static void SetScriptingWhitelist(const ScriptingWhitelist& whitelist);
+  static const ScriptingWhitelist* GetScriptingWhitelist();
 
   // Returns true if the extension has the specified API permission.
   static bool HasApiPermission(const std::set<std::string>& api_permissions,
@@ -362,6 +351,9 @@
   // having an NPAPI plugin).
   bool HasFullPermissions() const;
 
+  // Whether context menu should be shown for page and browser actions.
+  bool ShowConfigureContextMenus() const;
+
   // Returns the Homepage URL for this extension. If homepage_url was not
   // specified in the manifest, this returns the Google Gallery URL. For
   // third-party extensions, this returns a blank GURL.
@@ -378,6 +370,7 @@
 
   // Gets the fully resolved absolute launch URL.
   GURL GetFullLaunchURL() const;
+
   // Image cache related methods. These are only valid on the UI thread and
   // not maintained by this class. See ImageLoadingTracker for usage. The
   // |original_size| parameter should be the size of the image at |source|
@@ -389,6 +382,18 @@
                       const gfx::Size& max_size) const;
   SkBitmap GetCachedImage(const ExtensionResource& source,
                           const gfx::Size& max_size) const;
+
+  // Returns true if this extension can execute script on a page. If a
+  // UserScript object is passed, permission to run that specific script is
+  // checked (using its matches list). Otherwise, permission to execute script
+  // programmatically is checked (using the extension's host permission).
+  //
+  // This method is also aware of certain special pages that extensions are
+  // usually not allowed to run script on.
+  bool CanExecuteScriptOnPage(const GURL& page_url,
+                              UserScript* script,
+                              std::string* error) const;
+
   // Returns true if this extension is a COMPONENT extension, or if it is
   // on the whitelist of extensions that can script all pages.
   bool CanExecuteScriptEverywhere() const;
@@ -414,6 +419,9 @@
   const UserScriptList& content_scripts() const { return content_scripts_; }
   ExtensionAction* page_action() const { return page_action_.get(); }
   ExtensionAction* browser_action() const { return browser_action_.get(); }
+  ExtensionSidebarDefaults* sidebar_defaults() const {
+    return sidebar_defaults_.get();
+  }
   const std::vector<PluginInfo>& plugins() const { return plugins_; }
   const GURL& background_url() const { return background_url_; }
   const GURL& options_url() const { return options_url_; }
@@ -533,6 +541,11 @@
   ExtensionAction* LoadExtensionActionHelper(
       const DictionaryValue* extension_action, std::string* error);
 
+  // Helper method to load an ExtensionSidebarDefaults from the sidebar manifest
+  // entry.
+  ExtensionSidebarDefaults* LoadExtensionSidebarDefaults(
+      const DictionaryValue* sidebar, std::string* error);
+
   // Calculates the effective host permissions from the permissions and content
   // script petterns.
   void InitEffectiveHostPermissions();
@@ -626,6 +639,9 @@
   // The extension's browser action, if any.
   scoped_ptr<ExtensionAction> browser_action_;
 
+  // The extension's sidebar, if any.
+  scoped_ptr<ExtensionSidebarDefaults> sidebar_defaults_;
+
   // Optional list of NPAPI plugins and associated properties.
   std::vector<PluginInfo> plugins_;
 
@@ -687,7 +703,11 @@
   // absolute. If relative, it is relative to web_origin.
   std::string launch_web_url_;
 
-  // The type of container to launch into.
+  // The window type that an app's manifest specifies to launch into.
+  // This is not always the window type an app will open into, because
+  // users can override the way each app launches.  See
+  // ExtensionPrefs::GetLaunchContainer(), which looks at a per-app pref
+  // to decide what container an app will launch in.
   extension_misc::LaunchContainer launch_container_;
 
   // The default size of the container when launching. Only respected for
diff --git a/chrome/common/extensions/extension_action.cc b/chrome/common/extensions/extension_action.cc
index 7139fb2..0cb4a0f 100644
--- a/chrome/common/extensions/extension_action.cc
+++ b/chrome/common/extensions/extension_action.cc
@@ -6,15 +6,15 @@
 
 #include <algorithm>
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "chrome/common/badge_util.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "grit/app_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/rect.h"
 
 namespace {
 
diff --git a/chrome/common/extensions/extension_action_unittest.cc b/chrome/common/extensions/extension_action_unittest.cc
index 4413bfe..b9588bf 100644
--- a/chrome/common/extensions/extension_action_unittest.cc
+++ b/chrome/common/extensions/extension_action_unittest.cc
@@ -7,10 +7,10 @@
 #include "base/path_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension_action.h"
-#include "gfx/skia_util.h"
 #include "googleurl/src/gurl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/skia_util.h"
 #include "webkit/glue/image_decoder.h"
 
 using gfx::BitmapsAreEqual;
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index dd15afa..dbde37b 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -52,6 +52,10 @@
 const char* kPluginsPublic = "public";
 const char* kPublicKey = "key";
 const char* kRunAt = "run_at";
+const char* kSidebar = "sidebar";
+const char* kSidebarDefaultIcon = "default_icon";
+const char* kSidebarDefaultPage = "default_page";
+const char* kSidebarDefaultTitle = "default_title";
 const char* kSignature = "signature";
 const char* kTheme = "theme";
 const char* kThemeColors = "colors";
@@ -225,6 +229,14 @@
     "Invalid value for 'plugins[*].public'.";
 const char* kInvalidRunAt =
     "Invalid value for 'content_scripts[*].run_at'.";
+const char* kInvalidSidebar =
+    "Invalid value for 'sidebar'.";
+const char* kInvalidSidebarDefaultIconPath =
+    "Invalid value for 'sidebar.default_icon'.";
+const char* kInvalidSidebarDefaultPage =
+    "Invalid value for 'sidebar.default_page'.";
+const char* kInvalidSidebarDefaultTitle =
+    "Invalid value for 'sidebar.default_title'.";
 const char* kInvalidSignature =
     "Value 'signature' is missing or invalid.";
 const char* kInvalidTheme =
@@ -288,6 +300,9 @@
     "Only one of 'browser_action', 'page_action', and 'app' can be specified.";
 const char* kReservedMessageFound =
     "Reserved key * found in message catalog.";
+const char* kSidebarExperimental =
+    "You must request the 'experimental' permission in order to use the"
+    " Sidebar API.";
 const char* kThemesCannotContainExtensions =
     "A theme cannot contain extensions code.";
 #if defined(OS_CHROMEOS)
@@ -317,4 +332,8 @@
 const char* kBookmarkManagerId = "eemcgdkfndhakfknompkggombfjjjeno";
 const char* kWebStoreAppId = "ahfgeienlihckogmohjhadlkjgocpleb";
 const char* kAppsPromoHistogram = "Extensions.AppsPromo";
+#if defined(OS_CHROMEOS)
+const char* kAccessExtensionPath =
+    "/usr/share/chromeos-assets/accessibility/extensions";
+#endif
 }
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 7f09630..6d91451 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -57,6 +57,10 @@
   extern const char* kPluginsPublic;
   extern const char* kPublicKey;
   extern const char* kRunAt;
+  extern const char* kSidebar;
+  extern const char* kSidebarDefaultIcon;
+  extern const char* kSidebarDefaultPage;
+  extern const char* kSidebarDefaultTitle;
   extern const char* kSignature;
   extern const char* kTheme;
   extern const char* kThemeColors;
@@ -160,6 +164,10 @@
   extern const char* kInvalidPluginsPath;
   extern const char* kInvalidPluginsPublic;
   extern const char* kInvalidRunAt;
+  extern const char* kInvalidSidebar;
+  extern const char* kInvalidSidebarDefaultIconPath;
+  extern const char* kInvalidSidebarDefaultPage;
+  extern const char* kInvalidSidebarDefaultTitle;
   extern const char* kInvalidSignature;
   extern const char* kInvalidTheme;
   extern const char* kInvalidThemeColors;
@@ -191,6 +199,7 @@
   extern const char* kMultipleOverrides;
   extern const char* kOneUISurfaceOnly;
   extern const char* kReservedMessageFound;
+  extern const char* kSidebarExperimental;
   extern const char* kThemesCannotContainExtensions;
   extern const char* kWebContentMustBeEnabled;
 #if defined(OS_CHROMEOS)
@@ -256,8 +265,15 @@
     PROMO_LAUNCH_WEB_STORE,
     PROMO_CLOSE,
     PROMO_EXPIRE,
-    PROMO_BUCKET_BOUNDARY = PROMO_EXPIRE + 1
+    PROMO_SEEN,
+    PROMO_BUCKET_BOUNDARY
   };
+
+#if defined(OS_CHROMEOS)
+  // The directory path on a ChromeOS device where accessibility extensions are
+  // stored.
+  extern const char* kAccessExtensionPath;
+#endif
 }  // extension_misc
 
 #endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_CONSTANTS_H_
diff --git a/chrome/common/extensions/extension_file_util.cc b/chrome/common/extensions/extension_file_util.cc
index e8636be..7aef372 100644
--- a/chrome/common/extensions/extension_file_util.cc
+++ b/chrome/common/extensions/extension_file_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,20 +7,25 @@
 #include <map>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/path_service.h"
 #include "base/scoped_temp_dir.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_action.h"
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/extensions/extension_sidebar_defaults.h"
 #include "chrome/common/json_value_serializer.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
 #include "net/base/file_stream.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace errors = extension_manifest_errors;
 
@@ -156,7 +161,7 @@
           if (!file_util::PathExists(image_path)) {
             *error =
                 l10n_util::GetStringFUTF8(IDS_EXTENSION_INVALID_IMAGE_PATH,
-                    WideToUTF16(image_path.ToWStringHack()));
+                                          image_path.LossyDisplayName());
             return false;
           }
         }
@@ -198,7 +203,7 @@
       *error =
           l10n_util::GetStringFUTF8(
               IDS_EXTENSION_LOAD_PLUGIN_PATH_FAILED,
-              WideToUTF16(plugin.path.ToWStringHack()));
+              plugin.path.LossyDisplayName());
       return false;
     }
   }
@@ -245,7 +250,7 @@
       *error =
           l10n_util::GetStringFUTF8(
               IDS_EXTENSION_LOAD_BACKGROUND_PAGE_FAILED,
-              WideToUTF16(page_path.ToWStringHack()));
+              page_path.LossyDisplayName());
       return false;
     }
   }
@@ -260,7 +265,22 @@
       *error =
           l10n_util::GetStringFUTF8(
               IDS_EXTENSION_LOAD_OPTIONS_PAGE_FAILED,
-              WideToUTF16(options_path.ToWStringHack()));
+              options_path.LossyDisplayName());
+      return false;
+    }
+  }
+
+  // Validate sidebar default page location.
+  ExtensionSidebarDefaults* sidebar_defaults = extension->sidebar_defaults();
+  if (sidebar_defaults && sidebar_defaults->default_page().is_valid()) {
+    FilePath page_path = ExtensionURLToRelativeFilePath(
+        sidebar_defaults->default_page());
+    const FilePath path = extension->GetResource(page_path).GetFilePath();
+    if (path.empty() || !file_util::PathExists(path)) {
+      *error =
+          l10n_util::GetStringFUTF8(
+              IDS_EXTENSION_LOAD_SIDEBAR_PAGE_FAILED,
+              page_path.LossyDisplayName());
       return false;
     }
   }
@@ -292,15 +312,21 @@
   FilePath extension_path;
   for (extension_path = enumerator.Next(); !extension_path.value().empty();
        extension_path = enumerator.Next()) {
-    std::string extension_id = WideToASCII(
-        extension_path.BaseName().ToWStringHack());
+    std::string extension_id;
+
+    FilePath basename = extension_path.BaseName();
+    if (IsStringASCII(basename.value())) {
+      extension_id = UTF16ToASCII(basename.LossyDisplayName());
+      if (!Extension::IdIsValid(extension_id))
+        extension_id.clear();
+    }
 
     // Delete directories that aren't valid IDs.
-    if (!Extension::IdIsValid(extension_id)) {
+    if (extension_id.empty()) {
       LOG(WARNING) << "Invalid extension ID encountered in extensions "
-                      "directory: " << extension_id;
+                      "directory: " << basename.value();
       VLOG(1) << "Deleting invalid extension directory "
-              << WideToASCII(extension_path.ToWStringHack()) << ".";
+              << extension_path.value() << ".";
       file_util::Delete(extension_path, true);  // Recursive.
       continue;
     }
@@ -313,7 +339,7 @@
     // complete, for example, when a plugin is in use at uninstall time.
     if (iter == extension_paths.end()) {
       VLOG(1) << "Deleting unreferenced install for directory "
-              << WideToASCII(extension_path.ToWStringHack()) << ".";
+              << extension_path.LossyDisplayName() << ".";
       file_util::Delete(extension_path, true);  // Recursive.
       continue;
     }
@@ -328,7 +354,7 @@
          version_dir = versions_enumerator.Next()) {
       if (version_dir.BaseName() != iter->second.BaseName()) {
         VLOG(1) << "Deleting old version for directory "
-                << WideToASCII(version_dir.ToWStringHack()) << ".";
+                << version_dir.LossyDisplayName() << ".";
         file_util::Delete(version_dir, true);  // Recursive.
       }
     }
@@ -408,7 +434,7 @@
     if (!file_util::PathExists(messages_path)) {
       *error = base::StringPrintf(
           "%s %s", errors::kLocalesMessagesFileMissing,
-          WideToUTF8(messages_path.ToWStringHack()).c_str());
+          UTF16ToUTF8(messages_path.LossyDisplayName()).c_str());
       return false;
     }
 
@@ -434,14 +460,14 @@
       !file_util::ReadFileToString(path, &content)) {
     *error = l10n_util::GetStringFUTF8(
         message_id,
-        WideToUTF16(relative_path.ToWStringHack()));
+        relative_path.LossyDisplayName());
     return false;
   }
 
   if (!IsStringUTF8(content)) {
     *error = l10n_util::GetStringFUTF8(
         IDS_EXTENSION_BAD_FILE_ENCODING,
-        WideToUTF16(relative_path.ToWStringHack()));
+        relative_path.LossyDisplayName());
     return false;
   }
 
@@ -517,4 +543,70 @@
   return path;
 }
 
+FilePath GetUserDataTempDir() {
+  // We do file IO in this function, but only when the current profile's
+  // Temp directory has never been used before, or in a rare error case.
+  // Developers are not likely to see these situations often, so do an
+  // explicit thread check.
+  base::ThreadRestrictions::AssertIOAllowed();
+
+  // Getting chrome::DIR_USER_DATA_TEMP is failing.  Use histogram to see why.
+  // TODO(skerner): Fix the problem, and remove this code.  crbug.com/70056
+  enum DirectoryCreationResult {
+    SUCCESS = 0,
+
+    CANT_GET_PARENT_PATH,
+    CANT_GET_UDT_PATH,
+    NOT_A_DIRECTORY,
+    CANT_CREATE_DIR,
+    CANT_WRITE_TO_PATH,
+
+    UNSET,
+    NUM_DIRECTORY_CREATION_RESULTS
+  };
+
+  // All paths should set |result|.
+  DirectoryCreationResult result = UNSET;
+
+  FilePath temp_path;
+  if (!PathService::Get(chrome::DIR_USER_DATA_TEMP, &temp_path)) {
+    FilePath parent_path;
+    if (!PathService::Get(chrome::DIR_USER_DATA, &parent_path))
+      result = CANT_GET_PARENT_PATH;
+    else
+      result = CANT_GET_UDT_PATH;
+
+  } else if (file_util::PathExists(temp_path)) {
+
+    // Path exists.  Check that it is a directory we can write to.
+    if (!file_util::DirectoryExists(temp_path)) {
+      result = NOT_A_DIRECTORY;
+
+    } else if (!file_util::PathIsWritable(temp_path)) {
+      result = CANT_WRITE_TO_PATH;
+
+    } else {
+      // Temp is a writable directory.
+      result = SUCCESS;
+    }
+
+  } else if (!file_util::CreateDirectory(temp_path)) {
+    // Path doesn't exist, and we failed to create it.
+    result = CANT_CREATE_DIR;
+
+  } else {
+    // Successfully created the Temp directory.
+    result = SUCCESS;
+  }
+
+  UMA_HISTOGRAM_ENUMERATION("Extensions.GetUserDataTempDir",
+                            result,
+                            NUM_DIRECTORY_CREATION_RESULTS);
+
+  if (result == SUCCESS)
+    return temp_path;
+
+  return FilePath();
+}
+
 }  // namespace extension_file_util
diff --git a/chrome/common/extensions/extension_file_util.h b/chrome/common/extensions/extension_file_util.h
index f6a72bc..b26b564 100644
--- a/chrome/common/extensions/extension_file_util.h
+++ b/chrome/common/extensions/extension_file_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -76,6 +76,12 @@
 // Get a relative file path from a chrome-extension:// URL.
 FilePath ExtensionURLToRelativeFilePath(const GURL& url);
 
+// Get a path to a temp directory for unpacking an extension.
+// This is essentially PathService::Get(chrome::DIR_USER_DATA_TEMP, ...),
+// with a histogram that allows us to understand why it is failing.
+// Return an empty file path on failure.
+FilePath GetUserDataTempDir();
+
 }  // namespace extension_file_util
 
 #endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_FILE_UTIL_H_
diff --git a/chrome/common/extensions/extension_icon_set.cc b/chrome/common/extensions/extension_icon_set.cc
index 1f1dd21..fc1ac58 100644
--- a/chrome/common/extensions/extension_icon_set.cc
+++ b/chrome/common/extensions/extension_icon_set.cc
@@ -15,7 +15,7 @@
 }
 
 void ExtensionIconSet::Add(int size, const std::string& path) {
-  DCHECK(path.size() > 0 && path[0] != '/');
+  CHECK(path.size() > 0 && path[0] != '/');
   map_[size] = path;
 }
 
@@ -50,10 +50,14 @@
 }
 
 bool ExtensionIconSet::ContainsPath(const std::string& path) const {
-  DCHECK(path.size() > 0 && path[0] != '/');
+  if (path.empty())
+    return false;
+
+  CHECK(path[0] != '/') <<
+      "ExtensionIconSet stores icon paths without leading slash.";
+
   for (IconMap::const_iterator iter = map_.begin(); iter != map_.end();
        ++iter) {
-    LOG(ERROR) << iter->second << " , " << path;
     if (iter->second == path)
       return true;
   }
diff --git a/chrome/common/extensions/extension_icon_set_unittest.cc b/chrome/common/extensions/extension_icon_set_unittest.cc
index 4da96bc..9bd1ec5 100644
--- a/chrome/common/extensions/extension_icon_set_unittest.cc
+++ b/chrome/common/extensions/extension_icon_set_unittest.cc
@@ -44,6 +44,7 @@
   EXPECT_TRUE(icons.ContainsPath("foo"));
   EXPECT_TRUE(icons.ContainsPath("bar"));
   EXPECT_FALSE(icons.ContainsPath("baz"));
+  EXPECT_FALSE(icons.ContainsPath(""));
 
   icons.Clear();
   EXPECT_FALSE(icons.ContainsPath("foo"));
diff --git a/chrome/common/extensions/extension_l10n_util.cc b/chrome/common/extensions/extension_l10n_util.cc
index 994ab83..dff8f5e 100644
--- a/chrome/common/extensions/extension_l10n_util.cc
+++ b/chrome/common/extensions/extension_l10n_util.cc
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/linked_ptr.h"
 #include "base/logging.h"
@@ -20,6 +19,7 @@
 #include "chrome/common/extensions/extension_message_bundle.h"
 #include "chrome/common/json_value_serializer.h"
 #include "chrome/common/url_constants.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/uloc.h"
 
 namespace errors = extension_manifest_errors;
diff --git a/chrome/common/extensions/extension_l10n_util_unittest.cc b/chrome/common/extensions/extension_l10n_util_unittest.cc
index 0ec7e97..5a318bc 100644
--- a/chrome/common/extensions/extension_l10n_util_unittest.cc
+++ b/chrome/common/extensions/extension_l10n_util_unittest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "app/l10n_util.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
 #include "base/linked_ptr.h"
@@ -16,6 +15,7 @@
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/extension_message_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace errors = extension_manifest_errors;
 namespace keys = extension_manifest_keys;
diff --git a/chrome/common/extensions/extension_localization_peer.cc b/chrome/common/extensions/extension_localization_peer.cc
index e04bd0b..a01b601 100644
--- a/chrome/common/extensions/extension_localization_peer.cc
+++ b/chrome/common/extensions/extension_localization_peer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -66,17 +66,18 @@
 }
 
 void ExtensionLocalizationPeer::OnCompletedRequest(
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info,
     const base::Time& completion_time) {
   // Make sure we delete ourselves at the end of this call.
   scoped_ptr<ExtensionLocalizationPeer> this_deleter(this);
 
   // Give sub-classes a chance at altering the data.
-  if (status.status() != URLRequestStatus::SUCCESS) {
+  if (status.status() != net::URLRequestStatus::SUCCESS) {
     // We failed to load the resource.
     original_peer_->OnReceivedResponse(response_info_, true);
-    URLRequestStatus status(URLRequestStatus::CANCELED, net::ERR_ABORTED);
+    net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
+                                 net::ERR_ABORTED);
     original_peer_->OnCompletedRequest(status, security_info, completion_time);
     return;
   }
diff --git a/chrome/common/extensions/extension_localization_peer_unittest.cc b/chrome/common/extensions/extension_localization_peer_unittest.cc
index dc67d5b..87cea6b 100644
--- a/chrome/common/extensions/extension_localization_peer_unittest.cc
+++ b/chrome/common/extensions/extension_localization_peer_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -69,7 +69,7 @@
   MOCK_METHOD1(OnDownloadedData, void(int len));
   MOCK_METHOD2(OnReceivedData, void(const char* data, int len));
   MOCK_METHOD3(OnCompletedRequest, void(
-      const URLRequestStatus& status,
+      const net::URLRequestStatus& status,
       const std::string& security_info,
       const base::Time& completion_time));
 
@@ -141,10 +141,10 @@
 
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_, true));
   EXPECT_CALL(*original_peer_, OnCompletedRequest(
-    IsURLRequestEqual(URLRequestStatus::CANCELED), "", base::Time()));
+    IsURLRequestEqual(net::URLRequestStatus::CANCELED), "", base::Time()));
 
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::FAILED);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::FAILED);
   filter_peer->OnCompletedRequest(status, "", base::Time());
 }
 
@@ -157,10 +157,10 @@
 
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_, true));
   EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      IsURLRequestEqual(URLRequestStatus::SUCCESS), "", base::Time()));
+      IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time()));
 
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::SUCCESS);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::SUCCESS);
   filter_peer->OnCompletedRequest(status, "", base::Time());
 }
 
@@ -178,10 +178,11 @@
 
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_, true)).Times(2);
   EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      IsURLRequestEqual(URLRequestStatus::SUCCESS), "", base::Time())).Times(2);
+      IsURLRequestEqual(
+          net::URLRequestStatus::SUCCESS), "", base::Time())).Times(2);
 
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::SUCCESS);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::SUCCESS);
   filter_peer->OnCompletedRequest(status, "", base::Time());
 
   // Test if Send gets called again (it shouldn't be) when first call returned
@@ -215,10 +216,10 @@
 
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_, true));
   EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      IsURLRequestEqual(URLRequestStatus::SUCCESS), "", base::Time()));
+      IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time()));
 
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::SUCCESS);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::SUCCESS);
   filter_peer->OnCompletedRequest(status, "", base::Time());
 }
 
@@ -245,9 +246,9 @@
 
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_, true));
   EXPECT_CALL(*original_peer_, OnCompletedRequest(
-      IsURLRequestEqual(URLRequestStatus::SUCCESS), "", base::Time()));
+      IsURLRequestEqual(net::URLRequestStatus::SUCCESS), "", base::Time()));
 
-  URLRequestStatus status;
-  status.set_status(URLRequestStatus::SUCCESS);
+  net::URLRequestStatus status;
+  status.set_status(net::URLRequestStatus::SUCCESS);
   filter_peer->OnCompletedRequest(status, "", base::Time());
 }
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index f7c8f27..a6bc71f 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -8,11 +8,13 @@
 #include "base/path_service.h"
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_error_utils.h"
+#include "chrome/common/extensions/extension_sidebar_defaults.h"
 #include "chrome/common/json_value_serializer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -271,6 +273,40 @@
   *CommandLine::ForCurrentProcess() = old_command_line;
 }
 
+TEST_F(ExtensionManifestTest, Sidebar) {
+  LoadAndExpectError("sidebar.json",
+      errors::kExperimentalFlagRequired);
+
+  CommandLine old_command_line = *CommandLine::ForCurrentProcess();
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExperimentalExtensionApis);
+
+  LoadAndExpectError("sidebar_no_permissions.json",
+      errors::kSidebarExperimental);
+
+  LoadAndExpectError("sidebar_icon_empty.json",
+      errors::kInvalidSidebarDefaultIconPath);
+  LoadAndExpectError("sidebar_icon_invalid_type.json",
+      errors::kInvalidSidebarDefaultIconPath);
+  LoadAndExpectError("sidebar_page_empty.json",
+      errors::kInvalidSidebarDefaultPage);
+  LoadAndExpectError("sidebar_page_invalid_type.json",
+      errors::kInvalidSidebarDefaultPage);
+  LoadAndExpectError("sidebar_title_invalid_type.json",
+      errors::kInvalidSidebarDefaultTitle);
+
+  scoped_refptr<Extension> extension(LoadAndExpectSuccess("sidebar.json"));
+  ASSERT_TRUE(extension->sidebar_defaults() != NULL);
+  EXPECT_EQ(extension->sidebar_defaults()->default_title(),
+            ASCIIToUTF16("Default title"));
+  EXPECT_EQ(extension->sidebar_defaults()->default_icon_path(),
+            "icon.png");
+  EXPECT_EQ(extension->url().spec() + "sidebar.html",
+            extension->sidebar_defaults()->default_page().spec());
+
+  *CommandLine::ForCurrentProcess() = old_command_line;
+}
+
 TEST_F(ExtensionManifestTest, DisallowHybridApps) {
   LoadAndExpectError("disallow_hybrid_1.json",
                      errors::kHostedAppsCannotIncludeExtensionFeatures);
diff --git a/chrome/common/extensions/extension_message_bundle.cc b/chrome/common/extensions/extension_message_bundle.cc
index ea28c83..e6e00af 100644
--- a/chrome/common/extensions/extension_message_bundle.cc
+++ b/chrome/common/extensions/extension_message_bundle.cc
@@ -7,7 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/hash_tables.h"
 #include "base/i18n/rtl.h"
 #include "base/lazy_instance.h"
@@ -20,6 +19,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_error_utils.h"
 #include "chrome/common/extensions/extension_l10n_util.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace errors = extension_manifest_errors;
 
diff --git a/chrome/common/extensions/extension_resource.cc b/chrome/common/extensions/extension_resource.cc
index e2a5e24..cc88382 100644
--- a/chrome/common/extensions/extension_resource.cc
+++ b/chrome/common/extensions/extension_resource.cc
@@ -19,6 +19,8 @@
       relative_path_(relative_path) {
 }
 
+ExtensionResource::~ExtensionResource() {}
+
 const FilePath& ExtensionResource::GetFilePath() const {
   if (extension_root_.empty() || relative_path_.empty()) {
     DCHECK(full_resource_path_.empty());
diff --git a/chrome/common/extensions/extension_resource.h b/chrome/common/extensions/extension_resource.h
index 86705a8..6fe3773 100644
--- a/chrome/common/extensions/extension_resource.h
+++ b/chrome/common/extensions/extension_resource.h
@@ -22,6 +22,8 @@
                     const FilePath& extension_root,
                     const FilePath& relative_path);
 
+  ~ExtensionResource();
+
   // Returns actual path to the resource (default or locale specific). In the
   // browser process, this will DCHECK if not called on the file thread. To
   // easily load extension images on the UI thread, see ImageLoadingTracker.
diff --git a/chrome/common/extensions/extension_resource_unittest.cc b/chrome/common/extensions/extension_resource_unittest.cc
index e7b3ef0..9f47666 100644
--- a/chrome/common/extensions/extension_resource_unittest.cc
+++ b/chrome/common/extensions/extension_resource_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <algorithm>
 
-#include "app/l10n_util.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
 #include "base/scoped_temp_dir.h"
@@ -13,6 +12,7 @@
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/extension_resource.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 TEST(ExtensionResourceTest, CreateEmptyResource) {
   ExtensionResource resource;
diff --git a/chrome/common/extensions/extension_set.cc b/chrome/common/extensions/extension_set.cc
new file mode 100644
index 0000000..fcf96e6
--- /dev/null
+++ b/chrome/common/extensions/extension_set.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/extension_set.h"
+
+#include "base/logging.h"
+#include "chrome/common/url_constants.h"
+
+ExtensionSet::ExtensionSet() {
+}
+
+ExtensionSet::~ExtensionSet() {
+}
+
+size_t ExtensionSet::size() const {
+  return extensions_.size();
+}
+
+bool ExtensionSet::Contains(const std::string& extension_id) {
+  return extensions_.find(extension_id) != extensions_.end();
+}
+
+void ExtensionSet::Insert(const scoped_refptr<const Extension>& extension) {
+  extensions_[extension->id()] = extension;
+}
+
+void ExtensionSet::Remove(const std::string& id) {
+  extensions_.erase(id);
+}
+
+std::string ExtensionSet::GetIdByURL(const GURL& url) const {
+  if (url.SchemeIs(chrome::kExtensionScheme))
+    return url.host();
+
+  const Extension* extension = GetByURL(url);
+  if (!extension)
+    return "";
+
+  return extension->id();
+}
+
+const Extension* ExtensionSet::GetByURL(const GURL& url) const {
+  if (url.SchemeIs(chrome::kExtensionScheme))
+    return GetByID(url.host());
+
+  ExtensionMap::const_iterator i = extensions_.begin();
+  for (; i != extensions_.end(); ++i) {
+    if (i->second->web_extent().ContainsURL(url))
+      return i->second.get();
+  }
+
+  return NULL;
+}
+
+bool ExtensionSet::InSameExtent(const GURL& old_url,
+                                const GURL& new_url) const {
+  return GetByURL(old_url) == GetByURL(new_url);
+}
+
+const Extension* ExtensionSet::GetByID(const std::string& id) const {
+  ExtensionMap::const_iterator i = extensions_.find(id);
+  if (i != extensions_.end())
+    return i->second.get();
+  else
+    return NULL;
+}
+
+bool ExtensionSet::ExtensionBindingsAllowed(const GURL& url) const {
+  if (url.SchemeIs(chrome::kExtensionScheme))
+    return true;
+
+  ExtensionMap::const_iterator i = extensions_.begin();
+  for (; i != extensions_.end(); ++i) {
+    if (i->second->location() == Extension::COMPONENT &&
+        i->second->web_extent().ContainsURL(url))
+      return true;
+  }
+
+  return false;
+}
diff --git a/chrome/common/extensions/extension_set.h b/chrome/common/extensions/extension_set.h
new file mode 100644
index 0000000..9d00d1d
--- /dev/null
+++ b/chrome/common/extensions/extension_set.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_SET_H_
+#define CHROME_COMMON_EXTENSIONS_EXTENSION_SET_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/ref_counted.h"
+#include "chrome/common/extensions/extension.h"
+#include "googleurl/src/gurl.h"
+
+// The one true extension container. Extensions are identified by their id.
+// Only one extension can be in the set with a given ID.
+class ExtensionSet {
+ public:
+  ExtensionSet();
+  ~ExtensionSet();
+
+  // Gets the number of extensions contained.
+  size_t size() const;
+
+  // Returns true if the set contains the specified extension.
+  bool Contains(const std::string& id);
+
+  // Adds the specified extension to the set. The set becomes an owner. Any
+  // previous extension with the same ID is removed.
+  void Insert(const scoped_refptr<const Extension>& extension);
+
+  // Removes the specified extension.
+  void Remove(const std::string& id);
+
+  // Returns the extension ID that the given URL is a part of, or empty if
+  // none. This includes web URLs that are part of an extension's web extent.
+  std::string GetIdByURL(const GURL& url) const;
+
+  // Returns the Extension that the given URL is a part of, or NULL if none.
+  // This includes web URLs that are part of an extension's web extent.
+  // NOTE: This can return NULL if called before UpdateExtensions receives
+  // bulk extension data (e.g. if called from
+  // EventBindings::HandleContextCreated)
+  const Extension* GetByURL(const GURL& url) const;
+
+  // Returns true if |new_url| is in the extent of the same extension as
+  // |old_url|.  Also returns true if neither URL is in an app.
+  bool InSameExtent(const GURL& old_url, const GURL& new_url) const;
+
+  // Look up an Extension object by id.
+  const Extension* GetByID(const std::string& id) const;
+
+  // Returns true if |url| should get extension api bindings and be permitted
+  // to make api calls. Note that this is independent of what extension
+  // permissions the given extension has been granted.
+  bool ExtensionBindingsAllowed(const GURL& url) const;
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(ExtensionSetTest, ExtensionSet);
+
+  // static
+  typedef std::map<std::string, scoped_refptr<const Extension> > ExtensionMap;
+  ExtensionMap extensions_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionSet);
+};
+
+#endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_SET_H_
diff --git a/chrome/common/extensions/extension_set_unittest.cc b/chrome/common/extensions/extension_set_unittest.cc
new file mode 100644
index 0000000..1b85ac5
--- /dev/null
+++ b/chrome/common/extensions/extension_set_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_set.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+scoped_refptr<Extension> CreateTestExtension(const std::string& name,
+                                             const std::string& launch_url,
+                                             const std::string& extent) {
+#if defined(OS_WIN)
+  FilePath path(FILE_PATH_LITERAL("c:\\"));
+#else
+  FilePath path(FILE_PATH_LITERAL("/"));
+#endif
+  path = path.AppendASCII(name);
+
+  DictionaryValue manifest;
+  manifest.SetString("name", name);
+  manifest.SetString("version", "1");
+
+  if (!launch_url.empty())
+    manifest.SetString("app.launch.web_url", launch_url);
+
+  if (!extent.empty()) {
+    ListValue* urls = new ListValue();
+    manifest.Set("app.urls", urls);
+    urls->Append(Value::CreateStringValue(extent));
+  }
+
+  const bool kRequireKey = false;
+  std::string error;
+  scoped_refptr<Extension> extension(
+      Extension::Create(path, Extension::INTERNAL, manifest, kRequireKey,
+                        &error));
+  EXPECT_TRUE(extension.get()) << error;
+  return extension;
+}
+
+} // namespace
+
+TEST(ExtensionSetTest, ExtensionSet) {
+  scoped_refptr<Extension> ext1(CreateTestExtension(
+      "a", "https://chrome.google.com/launch", "https://chrome.google.com/"));
+
+  scoped_refptr<Extension> ext2(CreateTestExtension(
+      "a", "http://code.google.com/p/chromium",
+      "http://code.google.com/p/chromium/"));
+
+  scoped_refptr<Extension> ext3(CreateTestExtension(
+      "b", "http://dev.chromium.org/", "http://dev.chromium.org/"));
+
+  scoped_refptr<Extension> ext4(CreateTestExtension("c", "", ""));
+
+  ASSERT_TRUE(ext1 && ext2 && ext3 && ext4);
+
+  ExtensionSet extensions;
+
+  // Add an extension.
+  extensions.Insert(ext1);
+  EXPECT_EQ(1u, extensions.size());
+  EXPECT_EQ(ext1, extensions.GetByID(ext1->id()));
+
+  // Since extension2 has same ID, it should overwrite extension1.
+  extensions.Insert(ext2);
+  EXPECT_EQ(1u, extensions.size());
+  EXPECT_EQ(ext2, extensions.GetByID(ext1->id()));
+
+  // Add the other extensions.
+  extensions.Insert(ext3);
+  extensions.Insert(ext4);
+  EXPECT_EQ(3u, extensions.size());
+
+  // Get extension by its chrome-extension:// URL
+  EXPECT_EQ(ext2, extensions.GetByURL(
+      ext2->GetResourceURL("test.html")));
+  EXPECT_EQ(ext3, extensions.GetByURL(
+      ext3->GetResourceURL("test.html")));
+  EXPECT_EQ(ext4, extensions.GetByURL(
+      ext4->GetResourceURL("test.html")));
+
+  // Get extension by web extent.
+  EXPECT_EQ(ext2, extensions.GetByURL(
+      GURL("http://code.google.com/p/chromium/monkey")));
+  EXPECT_EQ(ext3, extensions.GetByURL(
+    GURL("http://dev.chromium.org/design-docs/")));
+  EXPECT_FALSE(extensions.GetByURL(
+      GURL("http://blog.chromium.org/")));
+
+  // Test InSameExtent().
+  EXPECT_TRUE(extensions.InSameExtent(
+      GURL("http://code.google.com/p/chromium/monkey/"),
+      GURL("http://code.google.com/p/chromium/")));
+  EXPECT_FALSE(extensions.InSameExtent(
+      GURL("http://code.google.com/p/chromium/"),
+      GURL("https://code.google.com/p/chromium/")));
+  EXPECT_FALSE(extensions.InSameExtent(
+      GURL("http://code.google.com/p/chromium/"),
+      GURL("http://dev.chromium.org/design-docs/")));
+
+  // Both of these should be NULL, which mean true for InSameExtent.
+  EXPECT_TRUE(extensions.InSameExtent(
+      GURL("http://www.google.com/"),
+      GURL("http://blog.chromium.org/")));
+
+  // Remove one of the extensions.
+  extensions.Remove(ext2->id());
+  EXPECT_EQ(2u, extensions.size());
+  EXPECT_FALSE(extensions.GetByID(ext2->id()));
+}
diff --git a/chrome/common/extensions/extension_sidebar_defaults.h b/chrome/common/extensions/extension_sidebar_defaults.h
new file mode 100644
index 0000000..4e475a4
--- /dev/null
+++ b/chrome/common/extensions/extension_sidebar_defaults.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_SIDEBAR_DEFAULTS_H_
+#define CHROME_COMMON_EXTENSIONS_EXTENSION_SIDEBAR_DEFAULTS_H_
+#pragma once
+
+#include <string>
+
+#include "base/string16.h"
+#include "googleurl/src/gurl.h"
+
+// ExtensionSidebarDefaults encapsulates the default parameters of a sidebar,
+// as defined in the extension manifest.
+class ExtensionSidebarDefaults {
+ public:
+  // Default title, stores manifest default_title key value.
+  void set_default_title(const string16& title) {
+    default_title_ = title;
+  }
+  const string16& default_title() const { return default_title_; }
+
+  // Default icon path, stores manifest default_icon key value.
+  void set_default_icon_path(const std::string& path) {
+    default_icon_path_ = path;
+  }
+  const std::string& default_icon_path() const {
+    return default_icon_path_;
+  }
+
+  // A resolved |url| to extension resource (manifest default_page key value)
+  // to navigate sidebar to by default.
+  void set_default_page(const GURL& url) {
+    default_page_ = url;
+  }
+  const GURL& default_page() const {
+    return default_page_;
+  }
+
+ private:
+  string16 default_title_;
+  std::string default_icon_path_;
+  GURL default_page_;
+};
+
+#endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_SIDEBAR_DEFAULTS_H_
diff --git a/chrome/common/extensions/extension_sidebar_utils.cc b/chrome/common/extensions/extension_sidebar_utils.cc
new file mode 100644
index 0000000..7a419cf
--- /dev/null
+++ b/chrome/common/extensions/extension_sidebar_utils.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/extension_sidebar_utils.h"
+
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_error_utils.h"
+#include "googleurl/src/gurl.h"
+
+namespace {
+
+// Errors.
+const char kInvalidPathError[] = "Invalid path: \"*\".";
+
+}  // namespace
+
+namespace extension_sidebar_utils {
+
+std::string GetExtensionIdByContentId(const std::string& content_id) {
+  // At the moment, content_id == extension_id.
+  return content_id;
+}
+
+GURL ResolveRelativePath(const std::string& relative_path,
+                         const Extension* extension,
+                         std::string* error) {
+  GURL url(extension->GetResourceURL(relative_path));
+  if (!url.is_valid()) {
+    *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidPathError,
+                                                     relative_path);
+    return GURL();
+  }
+  return url;
+}
+
+}  // namespace extension_sidebar_utils
diff --git a/chrome/common/extensions/extension_sidebar_utils.h b/chrome/common/extensions/extension_sidebar_utils.h
new file mode 100644
index 0000000..7fca85b
--- /dev/null
+++ b/chrome/common/extensions/extension_sidebar_utils.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_SIDEBAR_UTILS_H_
+#define CHROME_COMMON_EXTENSIONS_EXTENSION_SIDEBAR_UTILS_H_
+#pragma once
+
+#include <string>
+
+class Extension;
+class GURL;
+
+namespace extension_sidebar_utils {
+
+// Returns id of an extension owning a sidebar identified by |content_id|.
+std::string GetExtensionIdByContentId(const std::string& content_id);
+
+// Resolves |relative_path| relative to |extension|'s url.
+// In case of any problem, returns an empty invalid GURL and |error| receives
+// the corresponding error message.
+GURL ResolveRelativePath(const std::string& relative_path,
+                         const Extension* extension,
+                         std::string* error);
+
+}  // namespace extension_sidebar_utils
+
+#endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_SIDEBAR_UTILS_H_
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 1130302..817062c 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -8,7 +8,6 @@
 #include <gtk/gtk.h>
 #endif
 
-#include "app/l10n_util.h"
 #include "base/format_macros.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
@@ -24,7 +23,6 @@
 #include "chrome/common/extensions/extension_resource.h"
 #include "chrome/common/json_value_serializer.h"
 #include "chrome/common/url_constants.h"
-#include "gfx/codec/png_codec.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/mime_sniffer.h"
 #include "skia/ext/image_operations.h"
@@ -32,6 +30,8 @@
 #include "net/base/mock_host_resolver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace keys = extension_manifest_keys;
 namespace values = extension_manifest_values;
@@ -112,7 +112,7 @@
   scoped_ptr<DictionaryValue> input_value;
 
   // Test missing and invalid versions
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->Remove(keys::kVersion, NULL);
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_EQ(errors::kInvalidVersion, error);
@@ -122,7 +122,7 @@
   EXPECT_EQ(errors::kInvalidVersion, error);
 
   // Test missing and invalid names.
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->Remove(keys::kName, NULL);
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_EQ(errors::kInvalidName, error);
@@ -132,19 +132,19 @@
   EXPECT_EQ(errors::kInvalidName, error);
 
   // Test invalid description
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->SetInteger(keys::kDescription, 42);
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_EQ(errors::kInvalidDescription, error);
 
   // Test invalid icons
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->SetInteger(keys::kIcons, 42);
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_EQ(errors::kInvalidIcons, error);
 
   // Test invalid icon paths
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   DictionaryValue* icons = NULL;
   input_value->GetDictionary(keys::kIcons, &icons);
   ASSERT_FALSE(NULL == icons);
@@ -153,13 +153,13 @@
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidIconPath));
 
   // Test invalid user scripts list
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->SetInteger(keys::kContentScripts, 42);
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_EQ(errors::kInvalidContentScriptsList, error);
 
   // Test invalid user script item
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   ListValue* content_scripts = NULL;
   input_value->GetList(keys::kContentScripts, &content_scripts);
   ASSERT_FALSE(NULL == content_scripts);
@@ -168,7 +168,7 @@
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidContentScript));
 
   // Test missing and invalid matches array
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->GetList(keys::kContentScripts, &content_scripts);
   DictionaryValue* user_script = NULL;
   content_scripts->GetDictionary(0, &user_script);
@@ -195,7 +195,7 @@
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidMatch));
 
   // Test missing and invalid files array
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->GetList(keys::kContentScripts, &content_scripts);
   content_scripts->GetDictionary(0, &user_script);
   user_script->Remove(keys::kJs, NULL);
@@ -237,7 +237,7 @@
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidCss));
 
   // Test missing and invalid permissions array
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   EXPECT_TRUE(extension.InitFromValue(*input_value, true, &error));
   ListValue* permissions = NULL;
   input_value->GetList(keys::kPermissions, &permissions);
@@ -251,7 +251,7 @@
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidPermissions));
 
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->GetList(keys::kPermissions, &permissions);
   permissions->Set(0, Value::CreateIntegerValue(24));
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
@@ -263,7 +263,7 @@
   EXPECT_TRUE(extension.InitFromValue(*input_value, true, &error));
 
   // Multiple page actions are not allowed.
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   DictionaryValue* action = new DictionaryValue;
   action->SetString(keys::kPageActionId, "MyExtensionActionId");
   action->SetString(keys::kName, "MyExtensionActionName");
@@ -275,13 +275,13 @@
   EXPECT_STREQ(errors::kInvalidPageActionsListSize, error.c_str());
 
   // Test invalid options page url.
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->Set(keys::kOptionsPage, Value::CreateNullValue());
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidOptionsPage));
 
   // Test invalid/empty default locale.
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->Set(keys::kDefaultLocale, Value::CreateIntegerValue(5));
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidDefaultLocale));
@@ -291,7 +291,7 @@
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidDefaultLocale));
 
   // Test invalid minimum_chrome_version.
-  input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy()));
+  input_value.reset(valid_value->DeepCopy());
   input_value->Set(keys::kMinimumChromeVersion, Value::CreateIntegerValue(42));
   EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
   EXPECT_TRUE(MatchPattern(error, errors::kInvalidMinimumChromeVersion));
@@ -486,13 +486,13 @@
   scoped_ptr<DictionaryValue> copy;
 
   // First remove id key.
-  copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
+  copy.reset(input.DeepCopy());
   copy->Remove(keys::kPageActionId, NULL);
   action.reset(extension.LoadExtensionActionHelper(copy.get(), &error_msg));
   ASSERT_TRUE(NULL != action.get());
 
   // Then remove the name key. It's optional, so no error.
-  copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
+  copy.reset(input.DeepCopy());
   copy->Remove(keys::kName, NULL);
   action.reset(extension.LoadExtensionActionHelper(copy.get(), &error_msg));
   ASSERT_TRUE(NULL != action.get());
@@ -500,7 +500,7 @@
   ASSERT_TRUE(error_msg.empty());
 
   // Then remove the icon paths key.
-  copy.reset(static_cast<DictionaryValue*>(input.DeepCopy()));
+  copy.reset(input.DeepCopy());
   copy->Remove(keys::kPageActionIcons, NULL);
   action.reset(extension.LoadExtensionActionHelper(copy.get(), &error_msg));
   ASSERT_TRUE(NULL != action.get());
diff --git a/chrome/common/extensions/update_manifest.cc b/chrome/common/extensions/update_manifest.cc
index c75aa01..d2ceda7 100644
--- a/chrome/common/extensions/update_manifest.cc
+++ b/chrome/common/extensions/update_manifest.cc
@@ -19,6 +19,10 @@
 static const char* kExpectedGupdateXmlns =
     "http://www.google.com/update2/response";
 
+UpdateManifest::Result::Result() {}
+
+UpdateManifest::Result::~Result() {}
+
 UpdateManifest::Results::Results() : daystart_elapsed_seconds(kNoDaystart) {}
 
 UpdateManifest::Results::~Results() {}
diff --git a/chrome/common/extensions/update_manifest.h b/chrome/common/extensions/update_manifest.h
index 16a4f01..89e0f8b 100644
--- a/chrome/common/extensions/update_manifest.h
+++ b/chrome/common/extensions/update_manifest.h
@@ -36,6 +36,9 @@
 
   // The result of parsing one <app> tag in an xml update check manifest.
   struct Result {
+    Result();
+    ~Result();
+
     std::string extension_id;
     std::string version;
     std::string browser_min_version;
diff --git a/chrome/common/extensions/url_pattern.h b/chrome/common/extensions/url_pattern.h
index c0f17af..56deed5 100644
--- a/chrome/common/extensions/url_pattern.h
+++ b/chrome/common/extensions/url_pattern.h
@@ -114,6 +114,14 @@
   // Parse() instead, which returns success or failure.
   URLPattern(int valid_schemes, const std::string& pattern);
 
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+  // Note: don't use this directly. This exists so URLPattern can be used
+  // with STL containers.  Starting with Visual Studio 2010, we can't have this
+  // method private and use "friend class std::vector<URLPattern>;" as we used
+  // to do.
+  URLPattern();
+#endif
+
   ~URLPattern();
 
   // Gets the bitmask of valid schemes.
@@ -201,11 +209,13 @@
   };
 
  private:
+#if !(defined(_MSC_VER) && _MSC_VER >= 1600)
   friend class std::vector<URLPattern>;
 
   // Note: don't use this directly. This exists so URLPattern can be used
   // with STL containers.
   URLPattern();
+#endif
 
   // A bitmask containing the schemes which are considered valid for this
   // pattern. Parse() uses this to decide whether a pattern contains a valid
diff --git a/chrome/common/file_system/file_system_dispatcher.h b/chrome/common/file_system/file_system_dispatcher.h
index 21bc792..bc84d2a 100644
--- a/chrome/common/file_system/file_system_dispatcher.h
+++ b/chrome/common/file_system/file_system_dispatcher.h
@@ -31,7 +31,7 @@
   ~FileSystemDispatcher();
 
   // IPC::Channel::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& msg);
+  virtual bool OnMessageReceived(const IPC::Message& msg);
 
   bool OpenFileSystem(const GURL& origin_url,
                       fileapi::FileSystemType type,
diff --git a/chrome/common/file_system/webfilesystem_callback_dispatcher.cc b/chrome/common/file_system/webfilesystem_callback_dispatcher.cc
index 24a162a..f549ade 100644
--- a/chrome/common/file_system/webfilesystem_callback_dispatcher.cc
+++ b/chrome/common/file_system/webfilesystem_callback_dispatcher.cc
@@ -10,10 +10,10 @@
 #include "base/file_util_proxy.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileSystemCallbacks.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebFileInfo;
diff --git a/chrome/common/file_system/webfilesystem_impl.cc b/chrome/common/file_system/webfilesystem_impl.cc
index 5b180f6..9f5a0ea 100644
--- a/chrome/common/file_system/webfilesystem_impl.cc
+++ b/chrome/common/file_system/webfilesystem_impl.cc
@@ -8,9 +8,9 @@
 #include "chrome/common/file_system/webfilesystem_callback_dispatcher.h"
 #include "chrome/common/file_system/webfilewriter_impl.h"
 #include "chrome/common/child_thread.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileSystemCallbacks.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebFileInfo;
diff --git a/chrome/common/file_system/webfilesystem_impl.h b/chrome/common/file_system/webfilesystem_impl.h
index fc051e0..9aad3f5 100644
--- a/chrome/common/file_system/webfilesystem_impl.h
+++ b/chrome/common/file_system/webfilesystem_impl.h
@@ -6,7 +6,7 @@
 #define CHROME_COMMON_FILE_SYSTEM_WEBFILESYSTEM_IMPL_H_
 
 #include "base/basictypes.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h"
 
 namespace WebKit {
 class WebFileWriter;
diff --git a/chrome/common/gfx_resource_provider.cc b/chrome/common/gfx_resource_provider.cc
new file mode 100644
index 0000000..8cee034
--- /dev/null
+++ b/chrome/common/gfx_resource_provider.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/gfx_resource_provider.h"
+
+#include "base/string_piece.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace chrome {
+
+base::StringPiece GfxResourceProvider(int key) {
+  return ResourceBundle::GetSharedInstance().GetRawDataResource(key);
+}
+
+}  // namespace chrome
diff --git a/chrome/common/gfx_resource_provider.h b/chrome/common/gfx_resource_provider.h
new file mode 100644
index 0000000..41b67b8
--- /dev/null
+++ b/chrome/common/gfx_resource_provider.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_GFX_RESOURCE_PROVIDER_H_
+#define CHROME_COMMON_GFX_RESOURCE_PROVIDER_H_
+#pragma once
+
+namespace base {
+class StringPiece;
+}
+
+namespace chrome {
+
+// This is called indirectly by the gfx theme code to access resources.
+base::StringPiece GfxResourceProvider(int key);
+
+}  // namespace chrome
+
+#endif // CHROME_COMMON_GFX_RESOURCE_PROVIDER_H_
diff --git a/chrome/common/gpu_info.cc b/chrome/common/gpu_info.cc
index 744fdfc..ff9caae 100644
--- a/chrome/common/gpu_info.cc
+++ b/chrome/common/gpu_info.cc
@@ -1,22 +1,29 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/common/gpu_info.h"
 
 GPUInfo::GPUInfo()
-    : progress_(kUninitialized),
+    : level_(kUninitialized),
       vendor_id_(0),
       device_id_(0),
-      driver_version_(L""),
+      driver_vendor_(""),
+      driver_version_(""),
       pixel_shader_version_(0),
       vertex_shader_version_(0),
       gl_version_(0),
+      gl_version_string_(""),
+      gl_vendor_(""),
+      gl_renderer_(""),
+      gl_extensions_(""),
       can_lose_context_(false) {
 }
 
-GPUInfo::Progress GPUInfo::progress() const {
-  return progress_;
+GPUInfo::~GPUInfo() {}
+
+GPUInfo::Level GPUInfo::level() const {
+  return level_;
 }
 
 base::TimeDelta GPUInfo::initialization_time() const {
@@ -31,7 +38,11 @@
   return device_id_;
 }
 
-std::wstring GPUInfo::driver_version() const {
+std::string GPUInfo::driver_vendor() const {
+  return driver_vendor_;
+}
+
+std::string GPUInfo::driver_version() const {
   return driver_version_;
 }
 
@@ -47,34 +58,74 @@
   return gl_version_;
 }
 
+std::string GPUInfo::gl_version_string() const {
+  return gl_version_string_;
+}
+
+std::string GPUInfo::gl_vendor() const {
+  return gl_vendor_;
+}
+
+std::string GPUInfo::gl_renderer() const {
+  return gl_renderer_;
+}
+
+std::string GPUInfo::gl_extensions() const {
+  return gl_extensions_;
+}
 
 bool GPUInfo::can_lose_context() const {
   return can_lose_context_;
 }
 
+void GPUInfo::SetLevel(Level level) {
+  level_ = level;
+}
+
 void GPUInfo::SetInitializationTime(
     const base::TimeDelta& initialization_time) {
   initialization_time_ = initialization_time;
 }
 
-
-void GPUInfo::SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
-                              const std::wstring& driver_version,
-                              uint32 pixel_shader_version,
-                              uint32 vertex_shader_version,
-                              uint32 gl_version,
-                              bool can_lose_context) {
+void GPUInfo::SetVideoCardInfo(uint32 vendor_id, uint32 device_id) {
   vendor_id_ = vendor_id;
   device_id_ = device_id;
-  driver_version_ = driver_version;
-  pixel_shader_version_ = pixel_shader_version;
-  vertex_shader_version_ = vertex_shader_version;
-  gl_version_ = gl_version;
-  can_lose_context_ = can_lose_context;
 }
 
-void GPUInfo::SetProgress(Progress progress) {
-  progress_ = progress;
+void GPUInfo::SetDriverInfo(const std::string& driver_vendor,
+                            const std::string& driver_version) {
+  driver_vendor_ = driver_vendor;
+  driver_version_ = driver_version;
+}
+
+void GPUInfo::SetShaderVersion(uint32 pixel_shader_version,
+                               uint32 vertex_shader_version) {
+  pixel_shader_version_ = pixel_shader_version;
+  vertex_shader_version_ = vertex_shader_version;
+}
+
+void GPUInfo::SetGLVersion(uint32 gl_version) {
+  gl_version_ = gl_version;
+}
+
+void GPUInfo::SetGLVersionString(const std::string& gl_version_string) {
+  gl_version_string_ = gl_version_string;
+}
+
+void GPUInfo::SetGLVendor(const std::string& gl_vendor) {
+  gl_vendor_ = gl_vendor;
+}
+
+void GPUInfo::SetGLRenderer(const std::string& gl_renderer) {
+  gl_renderer_ = gl_renderer;
+}
+
+void GPUInfo::SetGLExtensions(const std::string& gl_extensions) {
+  gl_extensions_ = gl_extensions;
+}
+
+void GPUInfo::SetCanLoseContext(bool can_lose_context) {
+  can_lose_context_ = can_lose_context;
 }
 
 #if defined(OS_WIN)
diff --git a/chrome/common/gpu_info.h b/chrome/common/gpu_info.h
index b8f7cc6..3b8e0e6 100644
--- a/chrome/common/gpu_info.h
+++ b/chrome/common/gpu_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/scoped_ptr.h"
 #include "base/time.h"
 #include "build/build_config.h"
 #include "chrome/common/dx_diag_node.h"
@@ -19,17 +20,18 @@
 class GPUInfo {
  public:
   GPUInfo();
-  ~GPUInfo() {}
+  ~GPUInfo();
 
-  enum Progress {
+  enum Level {
     kUninitialized,
     kPartial,
+    kCompleting,
     kComplete,
   };
 
   // Returns whether this GPUInfo has been partially or fully initialized with
   // information.
-  Progress progress() const;
+  Level level() const;
 
   // The amount of time taken to get from the process starting to the message
   // loop being pumped.
@@ -42,42 +44,73 @@
   // Device ids are unique to vendor, not to one another.
   uint32 device_id() const;
 
+  // Return the vendor of the graphics driver currently installed.
+  std::string driver_vendor() const;
+
   // Return the version of the graphics driver currently installed.
-  // This will typically be something
-  std::wstring driver_version() const;
+  std::string driver_version() const;
 
   // Return the version of the pixel/fragment shader used by the gpu.
-  // This will typically be a number less than 10 so storing as a float
-  // should be okay.
+  // Major version in the second lowest 8 bits, minor in the lowest 8 bits,
+  // eg version 2.5 would be 0x00000205.
   uint32 pixel_shader_version() const;
 
   // Return the version of the vertex shader used by the gpu.
-  // This will typically be a number less than 10 so storing as a float
-  // should be okay.
+  // Major version in the second lowest 8 bits, minor in the lowest 8 bits,
+  // eg version 2.5 would be 0x00000205.
   uint32 vertex_shader_version() const;
 
   // Return the version of OpenGL we are using.
-  // Major version in the high word, minor in the low word, eg version 2.5
-  // would be 0x00020005.
+  // Major version in the second lowest 8 bits, minor in the lowest 8 bits,
+  // eg version 2.5 would be 0x00000205.
   // Returns 0 if we're not using OpenGL, say because we're going through
   // D3D instead.
+  // TODO(zmo): should be able to tell if it's GL or GLES.
   uint32 gl_version() const;
 
+  // Return the GL_VERSION string.
+  // Return "" if we are not using OpenGL.
+  std::string gl_version_string() const;
+
+  // Return the GL_VENDOR string.
+  // Return "" if we are not using OpenGL.
+  std::string gl_vendor() const;
+
+  // Return the GL_RENDERER string.
+  // Return "" if we are not using OpenGL.
+  std::string gl_renderer() const;
+
+  // Return the GL_EXTENSIONS string.
+  // Return "" if we are not using OpenGL.
+  std::string gl_extensions() const;
+
   // Return the device semantics, i.e. whether the Vista and Windows 7 specific
   // semantics are available.
   bool can_lose_context() const;
 
-  void SetProgress(Progress progress);
+  void SetLevel(Level level);
 
   void SetInitializationTime(const base::TimeDelta& initialization_time);
 
-  // Populate variables with passed in values
-  void SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
-                       const std::wstring& driver_version,
-                       uint32 pixel_shader_version,
-                       uint32 vertex_shader_version,
-                       uint32 gl_version,
-                       bool can_lose_context);
+  void SetVideoCardInfo(uint32 vendor_id, uint32 device_id);
+
+  void SetDriverInfo(const std::string& driver_vendor,
+                     const std::string& driver_version);
+
+  void SetShaderVersion(uint32 pixel_shader_version,
+                        uint32 vertex_shader_version);
+
+  void SetGLVersion(uint32 gl_version);
+
+  void SetGLVersionString(const std::string& gl_vendor_string);
+
+  void SetGLVendor(const std::string& gl_vendor);
+
+  void SetGLRenderer(const std::string& gl_renderer);
+
+  void SetGLExtensions(const std::string& gl_extensions);
+
+  void SetCanLoseContext(bool can_lose_context);
 
 #if defined(OS_WIN)
   // The information returned by the DirectX Diagnostics Tool.
@@ -87,14 +120,19 @@
 #endif
 
  private:
-  Progress progress_;
+  Level level_;
   base::TimeDelta initialization_time_;
   uint32 vendor_id_;
   uint32 device_id_;
-  std::wstring driver_version_;
+  std::string driver_vendor_;
+  std::string driver_version_;
   uint32 pixel_shader_version_;
   uint32 vertex_shader_version_;
   uint32 gl_version_;
+  std::string gl_version_string_;
+  std::string gl_vendor_;
+  std::string gl_renderer_;
+  std::string gl_extensions_;
   bool can_lose_context_;
 
 #if defined(OS_WIN)
diff --git a/chrome/common/gpu_info_unittest.cc b/chrome/common/gpu_info_unittest.cc
index a209aa9..34630e8 100644
--- a/chrome/common/gpu_info_unittest.cc
+++ b/chrome/common/gpu_info_unittest.cc
@@ -8,9 +8,18 @@
 // Test that an empty GPUInfo has valid members
 TEST(GPUInfoBasicTest, EmptyGPUInfo) {
   GPUInfo gpu_info;
+  EXPECT_EQ(gpu_info.level(), GPUInfo::kUninitialized);
+  EXPECT_EQ(gpu_info.initialization_time().ToInternalValue(), 0);
   EXPECT_EQ(gpu_info.vendor_id(), 0u);
   EXPECT_EQ(gpu_info.device_id(), 0u);
-  EXPECT_EQ(gpu_info.driver_version(), L"");
+  EXPECT_EQ(gpu_info.driver_vendor(), "");
+  EXPECT_EQ(gpu_info.driver_version(), "");
   EXPECT_EQ(gpu_info.pixel_shader_version(), 0u);
   EXPECT_EQ(gpu_info.vertex_shader_version(), 0u);
+  EXPECT_EQ(gpu_info.gl_version(), 0u);
+  EXPECT_EQ(gpu_info.gl_version_string(), "");
+  EXPECT_EQ(gpu_info.gl_vendor(), "");
+  EXPECT_EQ(gpu_info.gl_renderer(), "");
+  EXPECT_EQ(gpu_info.gl_extensions(), "");
+  EXPECT_EQ(gpu_info.can_lose_context(), false);
 }
diff --git a/chrome/common/gpu_messages.cc b/chrome/common/gpu_messages.cc
index 9d5c32e..b46babe 100644
--- a/chrome/common/gpu_messages.cc
+++ b/chrome/common/gpu_messages.cc
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/string_piece.h"
+#include "base/sys_string_conversions.h"
 #include "chrome/common/gpu_create_command_buffer_config.h"
 #include "chrome/common/gpu_info.h"
 #include "chrome/common/dx_diag_node.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "ipc/ipc_channel_handle.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 #define IPC_MESSAGE_IMPL
 #include "chrome/common/gpu_messages.h"
@@ -126,14 +128,19 @@
 #endif  // if defined(OS_MACOSX)
 
 void ParamTraits<GPUInfo> ::Write(Message* m, const param_type& p) {
-  WriteParam(m, static_cast<int32>(p.progress()));
+  WriteParam(m, static_cast<int32>(p.level()));
   WriteParam(m, p.initialization_time());
   WriteParam(m, p.vendor_id());
   WriteParam(m, p.device_id());
+  WriteParam(m, p.driver_vendor());
   WriteParam(m, p.driver_version());
   WriteParam(m, p.pixel_shader_version());
   WriteParam(m, p.vertex_shader_version());
   WriteParam(m, p.gl_version());
+  WriteParam(m, p.gl_version_string());
+  WriteParam(m, p.gl_vendor());
+  WriteParam(m, p.gl_renderer());
+  WriteParam(m, p.gl_extensions());
   WriteParam(m, p.can_lose_context());
 
 #if defined(OS_WIN)
@@ -142,36 +149,48 @@
 }
 
 bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
-  int32 progress;
+  int32 level;
   base::TimeDelta initialization_time;
   uint32 vendor_id;
   uint32 device_id;
-  std::wstring driver_version;
+  std::string driver_vendor;
+  std::string driver_version;
   uint32 pixel_shader_version;
   uint32 vertex_shader_version;
   uint32 gl_version;
+  std::string gl_version_string;
+  std::string gl_vendor;
+  std::string gl_renderer;
+  std::string gl_extensions;
   bool can_lose_context;
-  bool ret = ReadParam(m, iter, &progress);
+  bool ret = ReadParam(m, iter, &level);
   ret = ret && ReadParam(m, iter, &initialization_time);
   ret = ret && ReadParam(m, iter, &vendor_id);
   ret = ret && ReadParam(m, iter, &device_id);
+  ret = ret && ReadParam(m, iter, &driver_vendor);
   ret = ret && ReadParam(m, iter, &driver_version);
   ret = ret && ReadParam(m, iter, &pixel_shader_version);
   ret = ret && ReadParam(m, iter, &vertex_shader_version);
   ret = ret && ReadParam(m, iter, &gl_version);
+  ret = ret && ReadParam(m, iter, &gl_version_string);
+  ret = ret && ReadParam(m, iter, &gl_vendor);
+  ret = ret && ReadParam(m, iter, &gl_renderer);
+  ret = ret && ReadParam(m, iter, &gl_extensions);
   ret = ret && ReadParam(m, iter, &can_lose_context);
-  p->SetProgress(static_cast<GPUInfo::Progress>(progress));
+  p->SetLevel(static_cast<GPUInfo::Level>(level));
   if (!ret)
     return false;
 
   p->SetInitializationTime(initialization_time);
-  p->SetGraphicsInfo(vendor_id,
-                     device_id,
-                     driver_version,
-                     pixel_shader_version,
-                     vertex_shader_version,
-                     gl_version,
-                     can_lose_context);
+  p->SetVideoCardInfo(vendor_id, device_id);
+  p->SetDriverInfo(driver_vendor, driver_version);
+  p->SetShaderVersion(pixel_shader_version, vertex_shader_version);
+  p->SetGLVersion(gl_version);
+  p->SetGLVersionString(gl_version_string);
+  p->SetGLVendor(gl_vendor);
+  p->SetGLRenderer(gl_renderer);
+  p->SetGLExtensions(gl_extensions);
+  p->SetCanLoseContext(can_lose_context);
 
 #if defined(OS_WIN)
   DxDiagNode dx_diagnostics;
@@ -185,16 +204,38 @@
 }
 
 void ParamTraits<GPUInfo> ::Log(const param_type& p, std::string* l) {
-  l->append(base::StringPrintf("<GPUInfo> %d %d %x %x %ls %d",
-                               p.progress(),
+  l->append(base::StringPrintf("<GPUInfo> %d %d %x %x %s %s %x %x %x %d",
+                               p.level(),
                                static_cast<int32>(
                                    p.initialization_time().InMilliseconds()),
                                p.vendor_id(),
                                p.device_id(),
+                               p.driver_vendor().c_str(),
                                p.driver_version().c_str(),
+                               p.pixel_shader_version(),
+                               p.vertex_shader_version(),
+                               p.gl_version(),
                                p.can_lose_context()));
 }
 
+
+void ParamTraits<GPUInfo::Level> ::Write(Message* m, const param_type& p) {
+  WriteParam(m, static_cast<int32>(p));
+}
+
+bool ParamTraits<GPUInfo::Level> ::Read(const Message* m,
+                                    void** iter,
+                                    param_type* p) {
+  int32 level;
+  bool ret = ReadParam(m, iter, &level);
+  *p = static_cast<GPUInfo::Level>(level);
+  return ret;
+}
+
+void ParamTraits<GPUInfo::Level> ::Log(const param_type& p, std::string* l) {
+  LogParam(static_cast<int32>(p), l);
+}
+
 void ParamTraits<DxDiagNode> ::Write(Message* m, const param_type& p) {
   WriteParam(m, p.values);
   WriteParam(m, p.children);
@@ -212,36 +253,6 @@
   l->append("<DxDiagNode>");
 }
 
-void ParamTraits<gpu::CommandBuffer::State> ::Write(Message* m,
-                                                    const param_type& p) {
-  WriteParam(m, p.num_entries);
-  WriteParam(m, p.get_offset);
-  WriteParam(m, p.put_offset);
-  WriteParam(m, p.token);
-  WriteParam(m, static_cast<int32>(p.error));
-}
-
-bool ParamTraits<gpu::CommandBuffer::State> ::Read(const Message* m,
-                                                   void** iter,
-                                                   param_type* p) {
-  int32 temp;
-  if (ReadParam(m, iter, &p->num_entries) &&
-      ReadParam(m, iter, &p->get_offset) &&
-      ReadParam(m, iter, &p->put_offset) &&
-      ReadParam(m, iter, &p->token) &&
-      ReadParam(m, iter, &temp)) {
-    p->error = static_cast<gpu::error::Error>(temp);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-void ParamTraits<gpu::CommandBuffer::State> ::Log(const param_type& p,
-                                                  std::string* l) {
-  l->append("<CommandBuffer::State>");
-}
-
 void ParamTraits<GPUCreateCommandBufferConfig> ::Write(
     Message* m, const param_type& p) {
   WriteParam(m, p.allowed_extensions);
diff --git a/chrome/common/gpu_messages.h b/chrome/common/gpu_messages.h
index 387d2b1..2e89a25 100644
--- a/chrome/common/gpu_messages.h
+++ b/chrome/common/gpu_messages.h
@@ -10,8 +10,8 @@
 #include "base/process.h"
 #include "chrome/common/common_param_traits.h"
 #include "chrome/common/gpu_param_traits.h"
-#include "gfx/native_widget_types.h"
 #include "gpu/command_buffer/common/command_buffer.h"
+#include "ui/gfx/native_widget_types.h"
 
 #include "chrome/common/gpu_messages_internal.h"
 
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
index 22da39a..635362a 100644
--- a/chrome/common/gpu_messages_internal.h
+++ b/chrome/common/gpu_messages_internal.h
@@ -6,6 +6,7 @@
 #include <string>
 
 #include "base/shared_memory.h"
+#include "chrome/common/gpu_info.h"
 #include "chrome/common/gpu_video_common.h"
 #include "ipc/ipc_message_macros.h"
 
@@ -53,9 +54,18 @@
 // asynchronously.) Results in a GpuHostMsg_SynchronizeReply.
 IPC_MESSAGE_CONTROL0(GpuMsg_Synchronize)
 
+// Tells the GPU process to create a new command buffer that renders directly
+// to a native view. A corresponding GpuCommandBufferStub is created.
+IPC_MESSAGE_CONTROL4(GpuMsg_CreateViewCommandBuffer,
+                     gfx::PluginWindowHandle, /* view */
+                     int32, /* render_view_id */
+                     int32, /* renderer_id */
+                     GPUCreateCommandBufferConfig /* init_params */)
+
 // Tells the GPU process to create a context for collecting graphics card
 // information.
-IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo)
+IPC_MESSAGE_CONTROL1(GpuMsg_CollectGraphicsInfo,
+                     GPUInfo::Level /* level */)
 
 #if defined(OS_MACOSX)
 // Tells the GPU process that the browser process handled the swap
@@ -84,35 +94,61 @@
 
 //------------------------------------------------------------------------------
 // GPU Host Messages
-// These are messages from the GPU process to the browser.
-// Response to a GpuHostMsg_EstablishChannel message.
+// These are messages to the browser.
+
+// A renderer sends this when it wants to create a connection to the GPU
+// process. The browser will create the GPU process if necessary, and will
+// return a handle to the channel via a GpuChannelEstablished message.
+IPC_MESSAGE_CONTROL0(GpuHostMsg_EstablishGpuChannel)
+
+// A renderer sends this to the browser process to provide a synchronization
+// point for GPU operations, in particular to make sure the GPU channel has
+// been established.
+IPC_SYNC_MESSAGE_CONTROL0_0(GpuHostMsg_SynchronizeGpu)
+
+// A renderer sends this to the browser process when it wants to
+// create a GL context associated with the given view_id.
+IPC_SYNC_MESSAGE_CONTROL2_1(GpuHostMsg_CreateViewCommandBuffer,
+                            int32, /* render_view_id */
+                            GPUCreateCommandBufferConfig, /* init_params */
+                            int32 /* route_id */)
+
+// Response from GPU to a GpuHostMsg_EstablishChannel message.
 IPC_MESSAGE_CONTROL2(GpuHostMsg_ChannelEstablished,
                      IPC::ChannelHandle, /* channel_handle */
                      GPUInfo /* GPU logging stats */)
 
-// Response to a GpuMsg_Synchronize message.
-IPC_MESSAGE_CONTROL0(GpuHostMsg_SynchronizeReply)
+// Respond from GPU to a GpuMsg_CreateViewCommandBuffer message.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_CommandBufferCreated,
+                     int32 /* route_id */)
 
-// Response to a GpuMsg_CollectGraphicsInfo.
+// Request from GPU to free the browser resources associated with the
+// command buffer.
+IPC_MESSAGE_CONTROL3(GpuHostMsg_DestroyCommandBuffer,
+                     gfx::PluginWindowHandle, /* view */
+                     int32, /* render_view_id */
+                     int32 /* renderer_id */)
+
+// Response from GPU to a GpuMsg_CollectGraphicsInfo.
 IPC_MESSAGE_CONTROL1(GpuHostMsg_GraphicsInfoCollected,
                      GPUInfo /* GPU logging stats */)
 
+// Message from GPU to add a GPU log message to the about:gpu page.
+IPC_MESSAGE_CONTROL3(GpuHostMsg_OnLogMessage,
+                     int /*severity*/,
+                     std::string /* header */,
+                     std::string /* message */)
+
+// Response from GPU to a GpuMsg_Synchronize message.
+IPC_MESSAGE_CONTROL0(GpuHostMsg_SynchronizeReply)
+
 #if defined(OS_LINUX)
-// Get the XID for a view ID.
-IPC_SYNC_MESSAGE_CONTROL1_1(GpuHostMsg_GetViewXID,
-                            gfx::NativeViewId, /* view */
-                            unsigned long /* xid */)
-
-// Release the lock on the window.
-// If the associated view has been destroyed, destroy the window.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_ReleaseXID,
-                     unsigned long /* xid */)
-
+// Resize the window that is being drawn into. It's important that this
+// resize be synchronized with the swapping of the front and back buffers.
 IPC_SYNC_MESSAGE_CONTROL2_1(GpuHostMsg_ResizeXID,
                             unsigned long, /* xid */
                             gfx::Size, /* size */
                             bool /* success */)
-
 #elif defined(OS_MACOSX)
 // This message, used on Mac OS X 10.6 and later (where IOSurface is
 // supported), is sent from the GPU process to the browser to indicate that a
@@ -128,12 +164,6 @@
 IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
                      GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
 #elif defined(OS_WIN)
-// Get the HWND for the compositor window and if necessary, create it
-IPC_SYNC_MESSAGE_CONTROL2_1(GpuHostMsg_GetCompositorHostWindow,
-                            int32, /* renderer_id */
-                            int32, /* render_view_id */
-                            gfx::PluginWindowHandle /* compositor_host_id */)
-
 IPC_MESSAGE_CONTROL2(GpuHostMsg_ScheduleComposite,
                      int32, /* renderer_id */
                      int32 /* render_view_id */)
@@ -142,15 +172,6 @@
 //------------------------------------------------------------------------------
 // GPU Channel Messages
 // These are messages from a renderer process to the GPU process.
-// Tells the GPU process to create a new command buffer that renders directly
-// to a native view. The |render_view_id| is currently needed only on Mac OS
-// X in order to identify the window on the browser side into which the
-// rendering results go. A corresponding GpuCommandBufferStub is created.
-IPC_SYNC_MESSAGE_CONTROL3_1(GpuChannelMsg_CreateViewCommandBuffer,
-                            gfx::NativeViewId, /* view */
-                            int32, /* render_view_id */
-                            GPUCreateCommandBufferConfig, /* init_params */
-                            int32 /* route_id */)
 
 // Tells the GPU process to create a new command buffer that renders to an
 // offscreen frame buffer. If parent_route_id is not zero, the texture backing
diff --git a/chrome/common/gpu_messages_unittest.cc b/chrome/common/gpu_messages_unittest.cc
index 904d9da..4e2da79 100644
--- a/chrome/common/gpu_messages_unittest.cc
+++ b/chrome/common/gpu_messages_unittest.cc
@@ -12,14 +12,18 @@
 // Test GPUInfo serialization
 TEST(GPUIPCMessageTest, GPUInfo) {
   GPUInfo input;
-  // Test variables taken from Lenovo T61
-  input.SetProgress(GPUInfo::kPartial);
+  // Test variables taken from HP Z600 Workstation
+  input.SetLevel(GPUInfo::kPartial);
   input.SetInitializationTime(base::TimeDelta::FromMilliseconds(100));
-  input.SetGraphicsInfo(0x10de, 0x429, L"6.14.11.7715",
-                        0xffff0300,
-                        0xfffe0300,
-                        0x00010005,
-                        true);
+  input.SetVideoCardInfo(0x10de, 0x0658);
+  input.SetDriverInfo("NVIDIA", "195.36.24");
+  input.SetShaderVersion(0x0162, 0x0162);
+  input.SetGLVersion(0x0302);
+  input.SetGLVersionString("3.2.0 NVIDIA 195.36.24");
+  input.SetGLVendor("NVIDIA Corporation");
+  input.SetGLRenderer("Quadro FX 380/PCI/SSE2");
+  input.SetGLExtensions("GL_ARB_texture_rg GL_ARB_window_pos");
+  input.SetCanLoseContext(false);
 
   IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
   IPC::WriteParam(&msg, input);
@@ -27,18 +31,24 @@
   GPUInfo output;
   void* iter = NULL;
   EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
-  EXPECT_EQ(input.progress(), output.progress());
+  EXPECT_EQ(input.level(), output.level());
   EXPECT_EQ(input.initialization_time().InMilliseconds(),
             output.initialization_time().InMilliseconds());
   EXPECT_EQ(input.vendor_id(), output.vendor_id());
   EXPECT_EQ(input.device_id(), output.device_id());
+  EXPECT_EQ(input.driver_vendor(), output.driver_vendor());
   EXPECT_EQ(input.driver_version(), output.driver_version());
   EXPECT_EQ(input.pixel_shader_version(), output.pixel_shader_version());
   EXPECT_EQ(input.vertex_shader_version(), output.vertex_shader_version());
   EXPECT_EQ(input.gl_version(), output.gl_version());
+  EXPECT_EQ(input.gl_version_string(), output.gl_version_string());
+  EXPECT_EQ(input.gl_vendor(), output.gl_vendor());
+  EXPECT_EQ(input.gl_renderer(), output.gl_renderer());
+  EXPECT_EQ(input.gl_extensions(), output.gl_extensions());
   EXPECT_EQ(input.can_lose_context(), output.can_lose_context());
 
   std::string log_message;
   IPC::LogParam(output, &log_message);
-  EXPECT_STREQ("<GPUInfo> 1 100 10de 429 6.14.11.7715 1", log_message.c_str());
+  EXPECT_STREQ("<GPUInfo> 1 100 10de 658 NVIDIA 195.36.24 162 162 302 0",
+               log_message.c_str());
 }
diff --git a/chrome/common/gpu_param_traits.h b/chrome/common/gpu_param_traits.h
index 3ebaca0..1c1c9c0 100644
--- a/chrome/common/gpu_param_traits.h
+++ b/chrome/common/gpu_param_traits.h
@@ -12,10 +12,11 @@
 #include "chrome/common/dx_diag_node.h"
 #include "chrome/common/gpu_create_command_buffer_config.h"
 #include "chrome/common/gpu_info.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
+#include "gpu/ipc/gpu_command_buffer_traits.h"
 #include "gpu/command_buffer/common/command_buffer.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 #if defined(OS_MACOSX)
 // Parameters for the GpuHostMsg_AcceleratedSurfaceSetIOSurface
@@ -72,16 +73,16 @@
 };
 
 template <>
-struct ParamTraits<DxDiagNode> {
-  typedef DxDiagNode param_type;
+struct ParamTraits<GPUInfo::Level> {
+  typedef GPUInfo::Level param_type;
   static void Write(Message* m, const param_type& p);
   static bool Read(const Message* m, void** iter, param_type* p);
   static void Log(const param_type& p, std::string* l);
 };
 
 template <>
-struct ParamTraits<gpu::CommandBuffer::State> {
-  typedef gpu::CommandBuffer::State param_type;
+struct ParamTraits<DxDiagNode> {
+  typedef DxDiagNode param_type;
   static void Write(Message* m, const param_type& p);
   static bool Read(const Message* m, void** iter, param_type* p);
   static void Log(const param_type& p, std::string* l);
diff --git a/chrome/common/gpu_plugin.cc b/chrome/common/gpu_plugin.cc
index 4600638..fd4c680 100644
--- a/chrome/common/gpu_plugin.cc
+++ b/chrome/common/gpu_plugin.cc
@@ -15,28 +15,21 @@
 
 void RegisterInternalGPUPlugin() {
 #if defined(ENABLE_GPU)
-  static const std::wstring kWideMimeType = ASCIIToWide(
-      "application/vnd.google.chrome.gpu-plugin");
-  static const webkit::npapi::PluginVersionInfo kGPUPluginInfo = {
-    FilePath(FILE_PATH_LITERAL("gpu-plugin")),
-    L"GPU Plug-in",
-    L"GPU Rendering Plug-in",
-    L"1",
-    kWideMimeType.c_str(),
-    L"",
-    L"",
-    {
+  const webkit::npapi::PluginEntryPoints entry_points = {
 #if !defined(OS_POSIX) || defined(OS_MACOSX)
-      gpu_plugin::NP_GetEntryPoints,
+    gpu_plugin::NP_GetEntryPoints,
 #endif
-      gpu_plugin::NP_Initialize,
-      gpu_plugin::NP_Shutdown
-    }
+    gpu_plugin::NP_Initialize,
+    gpu_plugin::NP_Shutdown
   };
 
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableGPUPlugin))
     webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(
-        kGPUPluginInfo);
+        FilePath(FILE_PATH_LITERAL("gpu-plugin")),
+        "GPU Plug-in",
+        "GPU Rendering Plug-in",
+        "application/vnd.google.chrome.gpu-plugin",
+        entry_points);
 #endif  // ENABLE_GPU
 }
 
diff --git a/chrome/common/hi_res_timer_manager.h b/chrome/common/hi_res_timer_manager.h
new file mode 100644
index 0000000..25c02cd
--- /dev/null
+++ b/chrome/common/hi_res_timer_manager.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_COMMON_HI_RES_TIMER_MANAGER_H_
+#define CHROME_COMMON_HI_RES_TIMER_MANAGER_H_
+#pragma once
+
+#include "ui/base/system_monitor/system_monitor.h"
+
+// Ensures that the Windows high resolution timer is only used
+// when not running on battery power.
+class HighResolutionTimerManager : public ui::SystemMonitor::PowerObserver {
+ public:
+  HighResolutionTimerManager();
+  virtual ~HighResolutionTimerManager();
+
+  // ui::SystemMonitor::PowerObserver:
+  virtual void OnPowerStateChange(bool on_battery_power);
+
+ private:
+  // Enable or disable the faster multimedia timer.
+  void UseHiResClock(bool use);
+
+  bool hi_res_clock_used_;
+
+  DISALLOW_COPY_AND_ASSIGN(HighResolutionTimerManager);
+};
+
+#endif  // CHROME_COMMON_HI_RES_TIMER_MANAGER_H_
diff --git a/chrome/common/hi_res_timer_manager_posix.cc b/chrome/common/hi_res_timer_manager_posix.cc
new file mode 100644
index 0000000..fc9c1ba
--- /dev/null
+++ b/chrome/common/hi_res_timer_manager_posix.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/hi_res_timer_manager.h"
+
+// On POSIX we don't need to do anything special with the system timer.
+
+HighResolutionTimerManager::HighResolutionTimerManager()
+    : hi_res_clock_used_(false) {
+}
+
+HighResolutionTimerManager::~HighResolutionTimerManager() {
+}
+
+void HighResolutionTimerManager::OnPowerStateChange(bool on_battery_power) {
+}
+
+void HighResolutionTimerManager::UseHiResClock(bool use) {
+}
diff --git a/chrome/common/hi_res_timer_manager_win.cc b/chrome/common/hi_res_timer_manager_win.cc
new file mode 100644
index 0000000..c165222
--- /dev/null
+++ b/chrome/common/hi_res_timer_manager_win.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/hi_res_timer_manager.h"
+
+#include "base/time.h"
+
+HighResolutionTimerManager::HighResolutionTimerManager()
+    : hi_res_clock_used_(false) {
+  ui::SystemMonitor* system_monitor = ui::SystemMonitor::Get();
+  system_monitor->AddObserver(this);
+  UseHiResClock(!system_monitor->BatteryPower());
+}
+
+HighResolutionTimerManager::~HighResolutionTimerManager() {
+  ui::SystemMonitor::Get()->RemoveObserver(this);
+  UseHiResClock(false);
+}
+
+void HighResolutionTimerManager::OnPowerStateChange(bool on_battery_power) {
+  UseHiResClock(!on_battery_power);
+}
+
+void HighResolutionTimerManager::UseHiResClock(bool use) {
+  if (use == hi_res_clock_used_)
+    return;
+  base::Time::EnableHighResolutionTimer(use);
+}
diff --git a/chrome/common/indexed_db_key.cc b/chrome/common/indexed_db_key.cc
index 0379c30..050b941 100644
--- a/chrome/common/indexed_db_key.cc
+++ b/chrome/common/indexed_db_key.cc
@@ -5,7 +5,7 @@
 #include "chrome/common/indexed_db_key.h"
 
 #include "base/logging.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 using WebKit::WebIDBKey;
 
diff --git a/chrome/common/indexed_db_key.h b/chrome/common/indexed_db_key.h
index b740c10..47f1872 100644
--- a/chrome/common/indexed_db_key.h
+++ b/chrome/common/indexed_db_key.h
@@ -8,7 +8,7 @@
 
 #include "base/basictypes.h"
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBKey.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h"
 
 class IndexedDBKey {
  public:
diff --git a/chrome/common/indexed_db_messages.cc b/chrome/common/indexed_db_messages.cc
deleted file mode 100644
index c7c0e22..0000000
--- a/chrome/common/indexed_db_messages.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/common_param_traits.h"
-
-#define IPC_MESSAGE_IMPL
-#include "chrome/common/indexed_db_messages.h"
-
-IndexedDBHostMsg_FactoryOpen_Params::IndexedDBHostMsg_FactoryOpen_Params()
-    : routing_id(0),
-      response_id(0),
-      maximum_size(0) {
-}
-
-IndexedDBHostMsg_FactoryOpen_Params::~IndexedDBHostMsg_FactoryOpen_Params() {
-}
-
-IndexedDBHostMsg_DatabaseCreateObjectStore_Params::
-    IndexedDBHostMsg_DatabaseCreateObjectStore_Params()
-    : auto_increment(false),
-      transaction_id(0),
-      idb_database_id(0) {
-}
-
-IndexedDBHostMsg_DatabaseCreateObjectStore_Params::
-    ~IndexedDBHostMsg_DatabaseCreateObjectStore_Params() {
-}
-
-IndexedDBHostMsg_IndexOpenCursor_Params::
-    IndexedDBHostMsg_IndexOpenCursor_Params()
-    : response_id(0),
-      lower_open(false),
-      upper_open(false),
-      direction(0),
-      idb_index_id(0),
-      transaction_id(0) {
-}
-
-IndexedDBHostMsg_IndexOpenCursor_Params::
-    ~IndexedDBHostMsg_IndexOpenCursor_Params() {
-}
-
-
-IndexedDBHostMsg_ObjectStorePut_Params::
-    IndexedDBHostMsg_ObjectStorePut_Params()
-    : idb_object_store_id(0),
-      response_id(0),
-      add_only(false),
-      transaction_id(0) {
-}
-
-IndexedDBHostMsg_ObjectStorePut_Params::
-~IndexedDBHostMsg_ObjectStorePut_Params() {
-}
-
-IndexedDBHostMsg_ObjectStoreCreateIndex_Params::
-    IndexedDBHostMsg_ObjectStoreCreateIndex_Params()
-    : unique(false),
-      transaction_id(0),
-      idb_object_store_id(0) {
-}
-
-IndexedDBHostMsg_ObjectStoreCreateIndex_Params::
-    ~IndexedDBHostMsg_ObjectStoreCreateIndex_Params() {
-}
-
-
-IndexedDBHostMsg_ObjectStoreOpenCursor_Params::
-    IndexedDBHostMsg_ObjectStoreOpenCursor_Params()
-    : response_id(0),
-      lower_open(false),
-      upper_open(false),
-      direction(0),
-      idb_object_store_id(0),
-      transaction_id(0) {
-}
-
-IndexedDBHostMsg_ObjectStoreOpenCursor_Params::
-    ~IndexedDBHostMsg_ObjectStoreOpenCursor_Params() {
-}
-
-namespace IPC {
-
-void ParamTraits<IndexedDBHostMsg_FactoryOpen_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.routing_id);
-  WriteParam(m, p.response_id);
-  WriteParam(m, p.origin);
-  WriteParam(m, p.name);
-  WriteParam(m, p.maximum_size);
-}
-
-bool ParamTraits<IndexedDBHostMsg_FactoryOpen_Params>::Read(const Message* m,
-                                                            void** iter,
-                                                            param_type* p) {
-  return
-      ReadParam(m, iter, &p->routing_id) &&
-      ReadParam(m, iter, &p->response_id) &&
-      ReadParam(m, iter, &p->origin) &&
-      ReadParam(m, iter, &p->name) &&
-      ReadParam(m, iter, &p->maximum_size);
-}
-
-void ParamTraits<IndexedDBHostMsg_FactoryOpen_Params>::Log(const param_type& p,
-                                                           std::string* l) {
-  l->append("(");
-  LogParam(p.routing_id, l);
-  l->append(", ");
-  LogParam(p.response_id, l);
-  l->append(", ");
-  LogParam(p.origin, l);
-  l->append(", ");
-  LogParam(p.name, l);
-  l->append(", ");
-  LogParam(p.maximum_size, l);
-  l->append(")");
-}
-
-void ParamTraits<IndexedDBHostMsg_DatabaseCreateObjectStore_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.name);
-  WriteParam(m, p.key_path);
-  WriteParam(m, p.auto_increment);
-  WriteParam(m, p.transaction_id);
-  WriteParam(m, p.idb_database_id);
-}
-
-bool ParamTraits<IndexedDBHostMsg_DatabaseCreateObjectStore_Params>::Read(
-    const Message* m,
-    void** iter,
-    param_type* p) {
-  return
-      ReadParam(m, iter, &p->name) &&
-      ReadParam(m, iter, &p->key_path) &&
-      ReadParam(m, iter, &p->auto_increment) &&
-      ReadParam(m, iter, &p->transaction_id) &&
-      ReadParam(m, iter, &p->idb_database_id);
-}
-
-void ParamTraits<IndexedDBHostMsg_DatabaseCreateObjectStore_Params>::Log(
-    const param_type& p,
-    std::string* l) {
-  l->append("(");
-  LogParam(p.name, l);
-  l->append(", ");
-  LogParam(p.key_path, l);
-  l->append(", ");
-  LogParam(p.auto_increment, l);
-  l->append(", ");
-  LogParam(p.transaction_id, l);
-  l->append(", ");
-  LogParam(p.idb_database_id, l);
-  l->append(")");
-}
-
-void ParamTraits<IndexedDBHostMsg_IndexOpenCursor_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.response_id);
-  WriteParam(m, p.lower_key);
-  WriteParam(m, p.upper_key);
-  WriteParam(m, p.lower_open);
-  WriteParam(m, p.upper_open);
-  WriteParam(m, p.direction);
-  WriteParam(m, p.idb_index_id);
-  WriteParam(m, p.transaction_id);
-}
-
-bool ParamTraits<IndexedDBHostMsg_IndexOpenCursor_Params>::Read(
-    const Message* m,
-    void** iter,
-    param_type* p) {
-  return
-      ReadParam(m, iter, &p->response_id) &&
-      ReadParam(m, iter, &p->lower_key) &&
-      ReadParam(m, iter, &p->upper_key) &&
-      ReadParam(m, iter, &p->lower_open) &&
-      ReadParam(m, iter, &p->upper_open) &&
-      ReadParam(m, iter, &p->direction) &&
-      ReadParam(m, iter, &p->idb_index_id) &&
-      ReadParam(m, iter, &p->transaction_id);
-}
-
-void ParamTraits<IndexedDBHostMsg_IndexOpenCursor_Params>::Log(
-    const param_type& p,
-    std::string* l) {
-  l->append("(");
-  LogParam(p.response_id, l);
-  l->append(", ");
-  LogParam(p.lower_key, l);
-  l->append(", ");
-  LogParam(p.upper_key, l);
-  l->append(", ");
-  LogParam(p.lower_open, l);
-  l->append(", ");
-  LogParam(p.upper_open, l);
-  l->append(", ");
-  LogParam(p.direction, l);
-  l->append(", ");
-  LogParam(p.idb_index_id, l);
-  l->append(",");
-  LogParam(p.transaction_id, l);
-  l->append(")");
-}
-
-void ParamTraits<IndexedDBHostMsg_ObjectStorePut_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.idb_object_store_id);
-  WriteParam(m, p.response_id);
-  WriteParam(m, p.serialized_value);
-  WriteParam(m, p.key);
-  WriteParam(m, p.add_only);
-  WriteParam(m, p.transaction_id);
-}
-
-bool ParamTraits<IndexedDBHostMsg_ObjectStorePut_Params>::Read(
-    const Message* m,
-    void** iter,
-    param_type* p) {
-  return
-      ReadParam(m, iter, &p->idb_object_store_id) &&
-      ReadParam(m, iter, &p->response_id) &&
-      ReadParam(m, iter, &p->serialized_value) &&
-      ReadParam(m, iter, &p->key) &&
-      ReadParam(m, iter, &p->add_only) &&
-      ReadParam(m, iter, &p->transaction_id);
-}
-
-void ParamTraits<IndexedDBHostMsg_ObjectStorePut_Params>::Log(
-    const param_type& p,
-    std::string* l) {
-  l->append("(");
-  LogParam(p.idb_object_store_id, l);
-  l->append(", ");
-  LogParam(p.response_id, l);
-  l->append(", ");
-  LogParam(p.serialized_value, l);
-  l->append(", ");
-  LogParam(p.key, l);
-  l->append(", ");
-  LogParam(p.add_only, l);
-  l->append(", ");
-  LogParam(p.transaction_id, l);
-  l->append(")");
-}
-
-void ParamTraits<IndexedDBHostMsg_ObjectStoreCreateIndex_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.name);
-  WriteParam(m, p.key_path);
-  WriteParam(m, p.unique);
-  WriteParam(m, p.transaction_id);
-  WriteParam(m, p.idb_object_store_id);
-}
-
-bool ParamTraits<IndexedDBHostMsg_ObjectStoreCreateIndex_Params>::Read(
-    const Message* m,
-    void** iter,
-    param_type* p) {
-  return
-      ReadParam(m, iter, &p->name) &&
-      ReadParam(m, iter, &p->key_path) &&
-      ReadParam(m, iter, &p->unique) &&
-      ReadParam(m, iter, &p->transaction_id) &&
-      ReadParam(m, iter, &p->idb_object_store_id);
-}
-
-void ParamTraits<IndexedDBHostMsg_ObjectStoreCreateIndex_Params>::Log(
-    const param_type& p,
-    std::string* l) {
-  l->append("(");
-  LogParam(p.name, l);
-  l->append(", ");
-  LogParam(p.key_path, l);
-  l->append(", ");
-  LogParam(p.unique, l);
-  l->append(", ");
-  LogParam(p.transaction_id, l);
-  l->append(", ");
-  LogParam(p.idb_object_store_id, l);
-  l->append(")");
-}
-
-void ParamTraits<IndexedDBHostMsg_ObjectStoreOpenCursor_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.response_id);
-  WriteParam(m, p.lower_key);
-  WriteParam(m, p.upper_key);
-  WriteParam(m, p.lower_open);
-  WriteParam(m, p.upper_open);
-  WriteParam(m, p.direction);
-  WriteParam(m, p.idb_object_store_id);
-  WriteParam(m, p.transaction_id);
-}
-
-bool ParamTraits<IndexedDBHostMsg_ObjectStoreOpenCursor_Params>::Read(
-    const Message* m,
-    void** iter,
-    param_type* p) {
-  return
-      ReadParam(m, iter, &p->response_id) &&
-      ReadParam(m, iter, &p->lower_key) &&
-      ReadParam(m, iter, &p->upper_key) &&
-      ReadParam(m, iter, &p->lower_open) &&
-      ReadParam(m, iter, &p->upper_open) &&
-      ReadParam(m, iter, &p->direction) &&
-      ReadParam(m, iter, &p->idb_object_store_id) &&
-      ReadParam(m, iter, &p->transaction_id);
-}
-
-void ParamTraits<IndexedDBHostMsg_ObjectStoreOpenCursor_Params>::Log(
-    const param_type& p,
-    std::string* l) {
-  l->append("(");
-  LogParam(p.response_id, l);
-  l->append(", ");
-  LogParam(p.lower_key, l);
-  l->append(", ");
-  LogParam(p.upper_key, l);
-  l->append(", ");
-  LogParam(p.lower_open, l);
-  l->append(", ");
-  LogParam(p.upper_open, l);
-  l->append(", ");
-  LogParam(p.direction, l);
-  l->append(", ");
-  LogParam(p.idb_object_store_id, l);
-  l->append(",");
-  LogParam(p.transaction_id, l);
-  l->append(")");
-}
-
-}  // namespace IPC
diff --git a/chrome/common/indexed_db_messages.h b/chrome/common/indexed_db_messages.h
index 8eb77eb..4203f61 100644
--- a/chrome/common/indexed_db_messages.h
+++ b/chrome/common/indexed_db_messages.h
@@ -2,222 +2,125 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_COMMON_INDEXED_DB_MESSAGES_H_
-#define CHROME_COMMON_INDEXED_DB_MESSAGES_H_
-#pragma once
+// Message definition file, included multiple times, hence no include guard.
+
+#include <vector>
 
 #include "chrome/common/indexed_db_key.h"
 #include "chrome/common/indexed_db_param_traits.h"
 #include "chrome/common/serialized_script_value.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_param_traits.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebExceptionCode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBObjectStore.h"
 
 #define IPC_MESSAGE_START IndexedDBMsgStart
 
+// Argument structures used in messages
+
+IPC_ENUM_TRAITS(WebKit::WebIDBObjectStore::PutMode)
+
 // Used to open an indexed database.
-struct IndexedDBHostMsg_FactoryOpen_Params {
-  IndexedDBHostMsg_FactoryOpen_Params();
-  ~IndexedDBHostMsg_FactoryOpen_Params();
-
+IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryOpen_Params)
   // The routing ID of the view initiating the open.
-  int32 routing_id;
-
+  IPC_STRUCT_MEMBER(int32, routing_id)
   // The response should have this id.
-  int32 response_id;
-
+  IPC_STRUCT_MEMBER(int32, response_id)
   // The origin doing the initiating.
-  string16 origin;
-
+  IPC_STRUCT_MEMBER(string16, origin)
   // The name of the database.
-  string16 name;
-
+  IPC_STRUCT_MEMBER(string16, name)
   // The maximum size of the database.
-  uint64 maximum_size;
-};
+  IPC_STRUCT_MEMBER(uint64, maximum_size)
+IPC_STRUCT_END()
 
 // Used to create an object store.
-struct IndexedDBHostMsg_DatabaseCreateObjectStore_Params {
-  IndexedDBHostMsg_DatabaseCreateObjectStore_Params();
-  ~IndexedDBHostMsg_DatabaseCreateObjectStore_Params();
-
+IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseCreateObjectStore_Params)
   // The name of the object store.
-  string16 name;
-
+  IPC_STRUCT_MEMBER(string16, name)
   // The keyPath of the object store.
-  NullableString16 key_path;
-
+  IPC_STRUCT_MEMBER(NullableString16, key_path)
   // Whether the object store created should have a key generator.
-  bool auto_increment;
-
+  IPC_STRUCT_MEMBER(bool, auto_increment)
   // The transaction this is associated with.
-  int32 transaction_id;
-
+  IPC_STRUCT_MEMBER(int32, transaction_id)
   // The database the object store belongs to.
-  int32 idb_database_id;
-};
+  IPC_STRUCT_MEMBER(int32, idb_database_id)
+IPC_STRUCT_END()
 
 // Used to open both cursors and object cursors in IndexedDB.
-struct IndexedDBHostMsg_IndexOpenCursor_Params {
-  IndexedDBHostMsg_IndexOpenCursor_Params();
-  ~IndexedDBHostMsg_IndexOpenCursor_Params();
-
+IPC_STRUCT_BEGIN(IndexedDBHostMsg_IndexOpenCursor_Params)
   // The response should have this id.
-  int32 response_id;
-
+  IPC_STRUCT_MEMBER(int32, response_id)
   // The serialized lower key.
-  IndexedDBKey lower_key;
-
+  IPC_STRUCT_MEMBER(IndexedDBKey, lower_key)
   // The serialized upper key.
-  IndexedDBKey upper_key;
-
+  IPC_STRUCT_MEMBER(IndexedDBKey, upper_key)
   // Is the lower bound open?
-  bool lower_open;
-
+  IPC_STRUCT_MEMBER(bool, lower_open)
   // Is the upper bound open?
-  bool upper_open;
-
+  IPC_STRUCT_MEMBER(bool, upper_open)
   // The direction of this cursor.
-  int32 direction;
-
+  IPC_STRUCT_MEMBER(int32, direction)
   // The index the index belongs to.
-  int32 idb_index_id;
-
+  IPC_STRUCT_MEMBER(int32, idb_index_id)
   // The transaction this request belongs to.
-  int transaction_id;
-};
+  IPC_STRUCT_MEMBER(int, transaction_id)
+IPC_STRUCT_END()
 
 // Used to set a value in an object store.
-struct IndexedDBHostMsg_ObjectStorePut_Params {
-  IndexedDBHostMsg_ObjectStorePut_Params();
-  ~IndexedDBHostMsg_ObjectStorePut_Params();
-
+IPC_STRUCT_BEGIN(IndexedDBHostMsg_ObjectStorePut_Params)
   // The object store's id.
-  int32 idb_object_store_id;
-
+  IPC_STRUCT_MEMBER(int32, idb_object_store_id)
   // The id any response should contain.
-  int32 response_id;
-
+  IPC_STRUCT_MEMBER(int32, response_id)
   // The value to set.
-  SerializedScriptValue serialized_value;
-
+  IPC_STRUCT_MEMBER(SerializedScriptValue, serialized_value)
   // The key to set it on (may not be "valid"/set in some cases).
-  IndexedDBKey key;
-
-  // If it already exists, don't update (just return an error).
-  bool add_only;
-
+  IPC_STRUCT_MEMBER(IndexedDBKey, key)
+  // Whether this is an add or a put.
+  IPC_STRUCT_MEMBER(WebKit::WebIDBObjectStore::PutMode, put_mode)
   // The transaction it's associated with.
-  int transaction_id;
-};
+  IPC_STRUCT_MEMBER(int, transaction_id)
+IPC_STRUCT_END()
 
 // Used to create an index.
-struct IndexedDBHostMsg_ObjectStoreCreateIndex_Params {
-  IndexedDBHostMsg_ObjectStoreCreateIndex_Params();
-  ~IndexedDBHostMsg_ObjectStoreCreateIndex_Params();
-
+IPC_STRUCT_BEGIN(IndexedDBHostMsg_ObjectStoreCreateIndex_Params)
   // The name of the index.
-  string16 name;
-
+  IPC_STRUCT_MEMBER(string16, name)
   // The keyPath of the index.
-  NullableString16 key_path;
-
+  IPC_STRUCT_MEMBER(NullableString16, key_path)
   // Whether the index created has unique keys.
-  bool unique;
-
+  IPC_STRUCT_MEMBER(bool, unique)
   // The transaction this is associated with.
-  int32 transaction_id;
-
+  IPC_STRUCT_MEMBER(int32, transaction_id)
   // The object store the index belongs to.
-  int32 idb_object_store_id;
-};
+  IPC_STRUCT_MEMBER(int32, idb_object_store_id)
+IPC_STRUCT_END()
 
 // Used to open an IndexedDB cursor.
-struct IndexedDBHostMsg_ObjectStoreOpenCursor_Params {
-  IndexedDBHostMsg_ObjectStoreOpenCursor_Params();
-  ~IndexedDBHostMsg_ObjectStoreOpenCursor_Params();
-
+IPC_STRUCT_BEGIN(IndexedDBHostMsg_ObjectStoreOpenCursor_Params)
   // The response should have this id.
-  int32 response_id;
-
+  IPC_STRUCT_MEMBER(int32, response_id)
   // The serialized lower key.
-  IndexedDBKey lower_key;
-
+  IPC_STRUCT_MEMBER(IndexedDBKey, lower_key)
   // The serialized upper key.
-  IndexedDBKey upper_key;
-
+  IPC_STRUCT_MEMBER(IndexedDBKey, upper_key)
   // Is the lower bound open?
-  bool lower_open;
-
+  IPC_STRUCT_MEMBER(bool, lower_open)
   // Is the upper bound open?
-  bool upper_open;
-
+  IPC_STRUCT_MEMBER(bool, upper_open)
   // The direction of this cursor.
-  int32 direction;
-
+  IPC_STRUCT_MEMBER(int32, direction)
   // The object store the cursor belongs to.
-  int32 idb_object_store_id;
-
+  IPC_STRUCT_MEMBER(int32, idb_object_store_id)
   // The transaction this request belongs to.
-  int transaction_id;
-};
-
-namespace IPC {
-template <>
-struct ParamTraits<IndexedDBHostMsg_FactoryOpen_Params> {
-  typedef IndexedDBHostMsg_FactoryOpen_Params param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<IndexedDBHostMsg_DatabaseCreateObjectStore_Params> {
-  typedef IndexedDBHostMsg_DatabaseCreateObjectStore_Params param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<IndexedDBHostMsg_IndexOpenCursor_Params> {
-  typedef IndexedDBHostMsg_IndexOpenCursor_Params param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<IndexedDBHostMsg_ObjectStorePut_Params> {
-  typedef IndexedDBHostMsg_ObjectStorePut_Params param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<IndexedDBHostMsg_ObjectStoreCreateIndex_Params> {
-  typedef IndexedDBHostMsg_ObjectStoreCreateIndex_Params param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<IndexedDBHostMsg_ObjectStoreOpenCursor_Params> {
-  typedef IndexedDBHostMsg_ObjectStoreOpenCursor_Params param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-}  // namespace IPC
+  IPC_STRUCT_MEMBER(int, transaction_id)
+IPC_STRUCT_END()
 
 // Indexed DB messages sent from the browser to the renderer.
 
 // IDBCallback message handlers.
-IPC_MESSAGE_CONTROL1(IndexedDBMsg_CallbacksSuccessNull,
-                     int32 /* response_id */)
 IPC_MESSAGE_CONTROL2(IndexedDBMsg_CallbacksSuccessIDBCursor,
                      int32 /* response_id */,
                      int32 /* cursor_id */)
@@ -243,6 +146,8 @@
                      int32 /* response_id */,
                      int /* code */,
                      string16 /* message */)
+IPC_MESSAGE_CONTROL1(IndexedDBMsg_CallbacksBlocked,
+                     int32 /* response_id */)
 
 // IDBTransactionCallback message handlers.
 IPC_MESSAGE_CONTROL1(IndexedDBMsg_TransactionCallbacksAbort,
@@ -343,6 +248,14 @@
                             int32, /* idb_transaction_id */
                             WebKit::WebExceptionCode /* ec */)
 
+// WebIDBDatabase::close() message.
+IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseOpen,
+                     int32 /* idb_database_id */)
+
+// WebIDBDatabase::close() message.
+IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseClose,
+                     int32 /* idb_database_id */)
+
 // WebIDBDatabase::~WebIDBDatabase() message.
 IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseDestroyed,
                      int32 /* idb_database_id */)
@@ -433,6 +346,13 @@
                             int32, /* transaction_id */
                             WebKit::WebExceptionCode /* ec */)
 
+// WebIDBObjectStore::clear() message.
+IPC_SYNC_MESSAGE_CONTROL3_1(IndexedDBHostMsg_ObjectStoreClear,
+                            int32, /* idb_object_store_id */
+                            int32, /* response_id */
+                            int32, /* transaction_id */
+                            WebKit::WebExceptionCode /* ec */)
+
 // WebIDBObjectStore::createIndex() message.
 IPC_SYNC_MESSAGE_CONTROL1_2(IndexedDBHostMsg_ObjectStoreCreateIndex,
                             IndexedDBHostMsg_ObjectStoreCreateIndex_Params,
@@ -490,4 +410,3 @@
 IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_TransactionDestroyed,
                      int32 /* idb_transaction_id */)
 
-#endif  // CHROME_COMMON_INDEXED_DB_MESSAGES_H_
diff --git a/chrome/common/ipc_test_sink.cc b/chrome/common/ipc_test_sink.cc
deleted file mode 100644
index 69d328c..0000000
--- a/chrome/common/ipc_test_sink.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/ipc_test_sink.h"
-#include "ipc/ipc_message.h"
-
-namespace IPC {
-
-TestSink::TestSink() {
-}
-
-TestSink::~TestSink() {
-}
-
-bool TestSink::Send(IPC::Message* message) {
-  OnMessageReceived(*message);
-  delete message;
-  return true;
-}
-
-bool TestSink::OnMessageReceived(const Message& msg) {
-  messages_.push_back(Message(msg));
-  return true;
-}
-
-void TestSink::ClearMessages() {
-  messages_.clear();
-}
-
-const Message* TestSink::GetMessageAt(size_t index) const {
-  if (index >= messages_.size())
-    return NULL;
-  return &messages_[index];
-}
-
-const Message* TestSink::GetFirstMessageMatching(uint32 id) const {
-  for (size_t i = 0; i < messages_.size(); i++) {
-    if (messages_[i].type() == id)
-      return &messages_[i];
-  }
-  return NULL;
-}
-
-const Message* TestSink::GetUniqueMessageMatching(uint32 id) const {
-  size_t found_index = 0;
-  size_t found_count = 0;
-  for (size_t i = 0; i < messages_.size(); i++) {
-    if (messages_[i].type() == id) {
-      found_count++;
-      found_index = i;
-    }
-  }
-  if (found_count != 1)
-    return NULL;  // Didn't find a unique one.
-  return &messages_[found_index];
-}
-
-}  // namespace IPC
diff --git a/chrome/common/ipc_test_sink.h b/chrome/common/ipc_test_sink.h
deleted file mode 100644
index 05720d4..0000000
--- a/chrome/common/ipc_test_sink.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_IPC_TEST_SINK_H_
-#define CHROME_COMMON_IPC_TEST_SINK_H_
-#pragma once
-
-#include <utility>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "ipc/ipc_channel.h"
-
-namespace IPC {
-
-class Message;
-
-// This test sink provides a "sink" for IPC messages that are sent. It allows
-// the caller to query messages received in various different ways.  It is
-// designed for tests for objects that use the IPC system.
-//
-// Typical usage:
-//
-//   test_sink.ClearMessages();
-//   do_something();
-//
-//   // We should have gotten exactly one update state message.
-//   EXPECT_TRUE(test_sink.GetUniqeMessageMatching(ViewHostMsg_Update::ID));
-//   // ...and no start load messages.
-//   EXPECT_FALSE(test_sink.GetFirstMessageMatching(ViewHostMsg_Start::ID));
-//
-//   // Now inspect a message. This assumes a message that was declared like
-//   // this: IPC_MESSAGE_ROUTED2(ViewMsg_Foo, bool, int)
-//   IPC::Message* msg = test_sink.GetFirstMessageMatching(ViewMsg_Foo::ID));
-//   ASSERT_TRUE(msg);
-//   bool first_param;
-//   int second_param;
-//   ViewMsg_Foo::Read(msg, &first_param, &second_param);
-//
-//   // Go on to the next phase of the test.
-//   test_sink.ClearMessages();
-//
-// To hook up the sink, all you need to do is call OnMessageReceived when a
-// message is received.
-class TestSink : public IPC::Channel {
- public:
-  TestSink();
-  ~TestSink();
-
-  // Interface in IPC::Channel. This copies the message to the sink and then
-  // deletes it.
-  virtual bool Send(IPC::Message* message);
-
-  // Used by the source of the messages to send the message to the sink. This
-  // will make a copy of the message and store it in the list.
-  bool OnMessageReceived(const Message& msg);
-
-  // Returns the number of messages in the queue.
-  size_t message_count() const { return messages_.size(); }
-
-  // Clears the message queue of saved messages.
-  void ClearMessages();
-
-  // Returns the message at the given index in the queue. The index may be out
-  // of range, in which case the return value is NULL. The returned pointer will
-  // only be valid until another message is received or the list is cleared.
-  const Message* GetMessageAt(size_t index) const;
-
-  // Returns the first message with the given ID in the queue. If there is no
-  // message with the given ID, returns NULL. The returned pointer will only be
-  // valid until another message is received or the list is cleared.
-  const Message* GetFirstMessageMatching(uint32 id) const;
-
-  // Returns the message with the given ID in the queue. If there is no such
-  // message or there is more than one of that message, this will return NULL
-  // (with the expectation that you'll do an ASSERT_TRUE() on the result).
-  // The returned pointer will only be valid until another message is received
-  // or the list is cleared.
-  const Message* GetUniqueMessageMatching(uint32 id) const;
-
- private:
-  // The actual list of received messages.
-  std::vector<Message> messages_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSink);
-};
-
-}  // namespace IPC
-
-#endif  // CHROME_COMMON_IPC_TEST_SINK_H_
diff --git a/chrome/common/json_pref_store.cc b/chrome/common/json_pref_store.cc
index f5ff728..63e11d9 100644
--- a/chrome/common/json_pref_store.cc
+++ b/chrome/common/json_pref_store.cc
@@ -84,13 +84,6 @@
   std::string error_msg;
   scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg));
   if (!value.get()) {
-#if defined(GOOGLE_CHROME_BUILD)
-    // This log could be used for more detailed client-side error diagnosis,
-    // but since this triggers often with unit tests, we need to disable it
-    // in non-official builds.
-    PLOG(ERROR) << "Error reading Preferences: " << error_msg << " " <<
-        path_.value();
-#endif
     PrefReadError error;
     switch (error_code) {
       case JSONFileValueSerializer::JSON_ACCESS_DENIED:
diff --git a/chrome/common/json_pref_store_unittest.cc b/chrome/common/json_pref_store_unittest.cc
index 2d1e1df..1b98aa9 100644
--- a/chrome/common/json_pref_store_unittest.cc
+++ b/chrome/common/json_pref_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 #include "base/message_loop.h"
 #include "base/message_loop_proxy.h"
 #include "base/path_service.h"
+#include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
@@ -53,10 +54,11 @@
 TEST_F(JsonPrefStoreTest, NonExistentFile) {
   FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
   ASSERT_FALSE(file_util::PathExists(bogus_input_file));
-  JsonPrefStore pref_store(bogus_input_file, message_loop_proxy_.get());
+  scoped_refptr<JsonPrefStore> pref_store =
+      new JsonPrefStore(bogus_input_file, message_loop_proxy_.get());
   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
-            pref_store.ReadPrefs());
-  EXPECT_FALSE(pref_store.ReadOnly());
+            pref_store->ReadPrefs());
+  EXPECT_FALSE(pref_store->ReadOnly());
 }
 
 // Test fallback behavior for an invalid file.
@@ -64,10 +66,11 @@
   FilePath invalid_file_original = data_dir_.AppendASCII("invalid.json");
   FilePath invalid_file = test_dir_.AppendASCII("invalid.json");
   ASSERT_TRUE(file_util::CopyFile(invalid_file_original, invalid_file));
-  JsonPrefStore pref_store(invalid_file, message_loop_proxy_.get());
+  scoped_refptr<JsonPrefStore> pref_store =
+      new JsonPrefStore(invalid_file, message_loop_proxy_.get());
   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
-            pref_store.ReadPrefs());
-  EXPECT_FALSE(pref_store.ReadOnly());
+            pref_store->ReadPrefs());
+  EXPECT_FALSE(pref_store->ReadOnly());
 
   // The file should have been moved aside.
   EXPECT_FALSE(file_util::PathExists(invalid_file));
@@ -84,9 +87,10 @@
   // Test that the persistent value can be loaded.
   FilePath input_file = test_dir_.AppendASCII("write.json");
   ASSERT_TRUE(file_util::PathExists(input_file));
-  JsonPrefStore pref_store(input_file, message_loop_proxy_.get());
-  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store.ReadPrefs());
-  ASSERT_FALSE(pref_store.ReadOnly());
+  scoped_refptr<JsonPrefStore> pref_store =
+      new JsonPrefStore(input_file, message_loop_proxy_.get());
+  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
+  ASSERT_FALSE(pref_store->ReadOnly());
 
   // The JSON file looks like this:
   // {
@@ -106,52 +110,52 @@
 
   Value* actual;
   EXPECT_EQ(PrefStore::READ_OK,
-            pref_store.GetValue(prefs::kHomePage, &actual));
+            pref_store->GetValue(prefs::kHomePage, &actual));
   std::string string_value;
   EXPECT_TRUE(actual->GetAsString(&string_value));
   EXPECT_EQ(cnn, string_value);
 
   const char kSomeDirectory[] = "some_directory";
 
-  EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kSomeDirectory, &actual));
+  EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kSomeDirectory, &actual));
   FilePath::StringType path;
   EXPECT_TRUE(actual->GetAsString(&path));
   EXPECT_EQ(FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
   FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
 
-  pref_store.SetValue(kSomeDirectory,
-                      Value::CreateStringValue(some_path.value()));
-  EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kSomeDirectory, &actual));
+  pref_store->SetValue(kSomeDirectory,
+                       Value::CreateStringValue(some_path.value()));
+  EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kSomeDirectory, &actual));
   EXPECT_TRUE(actual->GetAsString(&path));
   EXPECT_EQ(some_path.value(), path);
 
   // Test reading some other data types from sub-dictionaries.
   EXPECT_EQ(PrefStore::READ_OK,
-            pref_store.GetValue(kNewWindowsInTabs, &actual));
+            pref_store->GetValue(kNewWindowsInTabs, &actual));
   bool boolean = false;
   EXPECT_TRUE(actual->GetAsBoolean(&boolean));
   EXPECT_TRUE(boolean);
 
-  pref_store.SetValue(kNewWindowsInTabs,
+  pref_store->SetValue(kNewWindowsInTabs,
                       Value::CreateBooleanValue(false));
   EXPECT_EQ(PrefStore::READ_OK,
-            pref_store.GetValue(kNewWindowsInTabs, &actual));
+            pref_store->GetValue(kNewWindowsInTabs, &actual));
   EXPECT_TRUE(actual->GetAsBoolean(&boolean));
   EXPECT_FALSE(boolean);
 
-  EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kMaxTabs, &actual));
+  EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kMaxTabs, &actual));
   int integer = 0;
   EXPECT_TRUE(actual->GetAsInteger(&integer));
   EXPECT_EQ(20, integer);
-  pref_store.SetValue(kMaxTabs, Value::CreateIntegerValue(10));
-  EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kMaxTabs, &actual));
+  pref_store->SetValue(kMaxTabs, Value::CreateIntegerValue(10));
+  EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kMaxTabs, &actual));
   EXPECT_TRUE(actual->GetAsInteger(&integer));
   EXPECT_EQ(10, integer);
 
-  pref_store.SetValue(kLongIntPref,
+  pref_store->SetValue(kLongIntPref,
                       Value::CreateStringValue(
                           base::Int64ToString(214748364842LL)));
-  EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kLongIntPref, &actual));
+  EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kLongIntPref, &actual));
   EXPECT_TRUE(actual->GetAsString(&string_value));
   int64 value;
   base::StringToInt64(string_value, &value);
@@ -161,7 +165,7 @@
   FilePath output_file = input_file;
   FilePath golden_output_file = data_dir_.AppendASCII("write.golden.json");
   ASSERT_TRUE(file_util::PathExists(golden_output_file));
-  ASSERT_TRUE(pref_store.WritePrefs());
+  ASSERT_TRUE(pref_store->WritePrefs());
   MessageLoop::current()->RunAllPending();
   EXPECT_TRUE(file_util::TextContentsEqual(golden_output_file, output_file));
   ASSERT_TRUE(file_util::Delete(output_file, false));
diff --git a/chrome/common/json_schema_validator.cc b/chrome/common/json_schema_validator.cc
index a76b2d9..7da218f 100644
--- a/chrome/common/json_schema_validator.cc
+++ b/chrome/common/json_schema_validator.cc
@@ -7,16 +7,16 @@
 #include <cfloat>
 #include <cmath>
 
-#include "app/l10n_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/values.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
 double GetNumberValue(Value* value) {
   double result = 0;
-  if (value->GetAsReal(&result))
+  if (value->GetAsDouble(&result))
     return result;
 
   int int_result = 0;
@@ -30,7 +30,7 @@
 
 bool GetNumberFromDictionary(DictionaryValue* value, const std::string& key,
                              double* number) {
-  if (value->GetReal(key, number))
+  if (value->GetDouble(key, number))
     return true;
 
   int int_value = 0;
@@ -97,9 +97,9 @@
       return "boolean";
     case Value::TYPE_INTEGER:
       return "integer";
-    case Value::TYPE_REAL: {
+    case Value::TYPE_DOUBLE: {
       double double_value = 0;
-      value->GetAsReal(&double_value);
+      value->GetAsDouble(&double_value);
       if (std::abs(double_value) <= std::pow(2.0, DBL_MANT_DIG) &&
           double_value == floor(double_value)) {
         return "integer";
@@ -269,9 +269,9 @@
         break;
 
       case Value::TYPE_INTEGER:
-      case Value::TYPE_REAL:
+      case Value::TYPE_DOUBLE:
         if (instance->IsType(Value::TYPE_INTEGER) ||
-            instance->IsType(Value::TYPE_REAL)) {
+            instance->IsType(Value::TYPE_DOUBLE)) {
           if (GetNumberValue(choice) == GetNumberValue(instance))
             return;
         }
diff --git a/chrome/common/json_schema_validator_unittest_base.cc b/chrome/common/json_schema_validator_unittest_base.cc
index 782d6bc..6d2c1bb 100644
--- a/chrome/common/json_schema_validator_unittest_base.cc
+++ b/chrome/common/json_schema_validator_unittest_base.cc
@@ -441,18 +441,18 @@
               scoped_ptr<Value>(Value::CreateIntegerValue(100)).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
-              scoped_ptr<Value>(Value::CreateRealValue(88.88)).get(),
+              scoped_ptr<Value>(Value::CreateDoubleValue(88.88)).get(),
               schema.get(), NULL);
 
   ExpectNotValid(
       TEST_SOURCE,
-      scoped_ptr<Value>(Value::CreateRealValue(0.5)).get(),
+      scoped_ptr<Value>(Value::CreateDoubleValue(0.5)).get(),
       schema.get(), NULL, "",
       JSONSchemaValidator::FormatErrorMessage(
           JSONSchemaValidator::kNumberMinimum, "1"));
   ExpectNotValid(
       TEST_SOURCE,
-      scoped_ptr<Value>(Value::CreateRealValue(100.1)).get(),
+      scoped_ptr<Value>(Value::CreateDoubleValue(100.1)).get(),
       schema.get(), NULL, "",
       JSONSchemaValidator::FormatErrorMessage(
           JSONSchemaValidator::kNumberMaximum, "100"));
@@ -472,23 +472,23 @@
   EXPECT_EQ("integer", JSONSchemaValidator::GetJSONSchemaType(
       scoped_ptr<Value>(Value::CreateIntegerValue(0)).get()));
   EXPECT_EQ("integer", JSONSchemaValidator::GetJSONSchemaType(
-      scoped_ptr<Value>(Value::CreateRealValue(42)).get()));
+      scoped_ptr<Value>(Value::CreateDoubleValue(42)).get()));
   EXPECT_EQ("integer", JSONSchemaValidator::GetJSONSchemaType(
       scoped_ptr<Value>(
-          Value::CreateRealValue(pow(2.0, DBL_MANT_DIG))).get()));
+          Value::CreateDoubleValue(pow(2.0, DBL_MANT_DIG))).get()));
   EXPECT_EQ("integer", JSONSchemaValidator::GetJSONSchemaType(
       scoped_ptr<Value>(
-          Value::CreateRealValue(pow(-2.0, DBL_MANT_DIG))).get()));
+          Value::CreateDoubleValue(pow(-2.0, DBL_MANT_DIG))).get()));
 
   // "number" is only used for non-integral numbers, or numbers beyond what
   // double can accurately represent.
   EXPECT_EQ("number", JSONSchemaValidator::GetJSONSchemaType(
-      scoped_ptr<Value>(Value::CreateRealValue(88.8)).get()));
+      scoped_ptr<Value>(Value::CreateDoubleValue(88.8)).get()));
   EXPECT_EQ("number", JSONSchemaValidator::GetJSONSchemaType(
-      scoped_ptr<Value>(Value::CreateRealValue(
+      scoped_ptr<Value>(Value::CreateDoubleValue(
           pow(2.0, DBL_MANT_DIG) * 2)).get()));
   EXPECT_EQ("number", JSONSchemaValidator::GetJSONSchemaType(
-      scoped_ptr<Value>(Value::CreateRealValue(
+      scoped_ptr<Value>(Value::CreateDoubleValue(
           pow(-2.0, DBL_MANT_DIG) * 2)).get()));
 
   EXPECT_EQ("string", JSONSchemaValidator::GetJSONSchemaType(
@@ -520,10 +520,10 @@
 
   schema->SetString("type", "number");
   ExpectValid(TEST_SOURCE,
-              scoped_ptr<Value>(Value::CreateRealValue(88.8)).get(),
+              scoped_ptr<Value>(Value::CreateDoubleValue(88.8)).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
-              scoped_ptr<Value>(Value::CreateRealValue(42)).get(),
+              scoped_ptr<Value>(Value::CreateDoubleValue(42)).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
               scoped_ptr<Value>(Value::CreateIntegerValue(42)).get(),
@@ -537,18 +537,18 @@
               scoped_ptr<Value>(Value::CreateIntegerValue(42)).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
-              scoped_ptr<Value>(Value::CreateRealValue(42)).get(),
+              scoped_ptr<Value>(Value::CreateDoubleValue(42)).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
               scoped_ptr<Value>(Value::CreateIntegerValue(0)).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
               scoped_ptr<Value>(
-                  Value::CreateRealValue(pow(2.0, DBL_MANT_DIG))).get(),
+                  Value::CreateDoubleValue(pow(2.0, DBL_MANT_DIG))).get(),
               schema.get(), NULL);
   ExpectValid(TEST_SOURCE,
               scoped_ptr<Value>(
-                  Value::CreateRealValue(pow(-2.0, DBL_MANT_DIG))).get(),
+                  Value::CreateDoubleValue(pow(-2.0, DBL_MANT_DIG))).get(),
               schema.get(), NULL);
 
   schema->SetString("type", "boolean");
@@ -600,14 +600,14 @@
 
   schema->SetString("type", "integer");
   ExpectNotValid(TEST_SOURCE,
-                 scoped_ptr<Value>(Value::CreateRealValue(88.8)).get(),
+                 scoped_ptr<Value>(Value::CreateDoubleValue(88.8)).get(),
                  schema.get(), NULL, "",
                  JSONSchemaValidator::FormatErrorMessage(
                      JSONSchemaValidator::kInvalidType, "integer", "number"));
 
   schema->SetString("type", "integer");
   ExpectNotValid(TEST_SOURCE,
-                 scoped_ptr<Value>(Value::CreateRealValue(88.8)).get(),
+                 scoped_ptr<Value>(Value::CreateDoubleValue(88.8)).get(),
                  schema.get(), NULL, "",
                  JSONSchemaValidator::FormatErrorMessage(
                      JSONSchemaValidator::kInvalidType, "integer", "number"));
diff --git a/chrome/common/json_value_serializer_unittest.cc b/chrome/common/json_value_serializer_unittest.cc
index b3f3e0d..c52aa06 100644
--- a/chrome/common/json_value_serializer_unittest.cc
+++ b/chrome/common/json_value_serializer_unittest.cc
@@ -17,7 +17,7 @@
 
 TEST(JSONValueSerializerTest, Roundtrip) {
   const std::string original_serialization =
-    "{\"bool\":true,\"int\":42,\"list\":[1,2],\"null\":null,\"real\":3.14}";
+    "{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}";
   JSONStringValueSerializer serializer(original_serialization);
   scoped_ptr<Value> root(serializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(root.get());
@@ -38,9 +38,9 @@
   ASSERT_TRUE(root_dict->GetInteger("int", &int_value));
   ASSERT_EQ(42, int_value);
 
-  double real_value = 0.0;
-  ASSERT_TRUE(root_dict->GetReal("real", &real_value));
-  ASSERT_DOUBLE_EQ(3.14, real_value);
+  double double_value = 0.0;
+  ASSERT_TRUE(root_dict->GetDouble("double", &double_value));
+  ASSERT_DOUBLE_EQ(3.14, double_value);
 
   // We shouldn't be able to write using this serializer, since it was
   // initialized with a const string.
@@ -63,10 +63,10 @@
   const std::string pretty_serialization =
     "{" JSON_NEWLINE
     "   \"bool\": true," JSON_NEWLINE
+    "   \"double\": 3.14," JSON_NEWLINE
     "   \"int\": 42," JSON_NEWLINE
     "   \"list\": [ 1, 2 ]," JSON_NEWLINE
-    "   \"null\": null," JSON_NEWLINE
-    "   \"real\": 3.14" JSON_NEWLINE
+    "   \"null\": null" JSON_NEWLINE
     "}" JSON_NEWLINE;
 #undef JSON_NEWLINE
   ASSERT_EQ(pretty_serialization, test_serialization);
diff --git a/chrome/common/jstemplate_builder.cc b/chrome/common/jstemplate_builder.cc
index 628edd7..35e4b3a 100644
--- a/chrome/common/jstemplate_builder.cc
+++ b/chrome/common/jstemplate_builder.cc
@@ -7,12 +7,11 @@
 
 #include "chrome/common/jstemplate_builder.h"
 
-#include "app/resource_bundle.h"
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "chrome/common/json_value_serializer.h"
-
 #include "grit/common_resources.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace jstemplate_builder {
 
diff --git a/chrome/common/libxml_utils.cc b/chrome/common/libxml_utils.cc
index 009f0d3..61d4237 100644
--- a/chrome/common/libxml_utils.cc
+++ b/chrome/common/libxml_utils.cc
@@ -5,8 +5,10 @@
 #include "chrome/common/libxml_utils.h"
 
 #include "base/compiler_specific.h"
+#include "base/file_path.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
 
 #include "libxml/xmlreader.h"
 
@@ -49,11 +51,19 @@
   return reader_ != NULL;
 }
 
-bool XmlReader::LoadFile(const std::string& file_path) {
-
+bool XmlReader::LoadFile(const FilePath& file_path) {
   const int kParseOptions = XML_PARSE_RECOVER |  // recover on errors
                             XML_PARSE_NONET;     // forbid network access
-  reader_ = xmlReaderForFile(file_path.c_str(), NULL, kParseOptions);
+  reader_ = xmlReaderForFile(
+#if defined(OS_WIN)
+      // libxml takes UTF-8 paths on Windows; search the source for
+      // xmlWrapOpenUtf8 to see it converting UTF-8 back to wide
+      // characters.
+      WideToUTF8(file_path.value()).c_str(),
+#else
+      file_path.value().c_str(),
+#endif
+      NULL, kParseOptions);
   return reader_ != NULL;
 }
 
diff --git a/chrome/common/libxml_utils.h b/chrome/common/libxml_utils.h
index 55a935c..cf53341 100644
--- a/chrome/common/libxml_utils.h
+++ b/chrome/common/libxml_utils.h
@@ -11,6 +11,8 @@
 #include "libxml/xmlreader.h"
 #include "libxml/xmlwriter.h"
 
+class FilePath;
+
 // Converts a libxml xmlChar* into a UTF-8 std::string.
 // NULL inputs produce an empty string.
 std::string XmlStringToStdString(const xmlChar* xmlstring);
@@ -47,7 +49,7 @@
   bool Load(const std::string& input);
 
   // Load a document into the reader from a file.  Returns false on error.
-  bool LoadFile(const std::string& file_path);
+  bool LoadFile(const FilePath& file_path);
 
   // Wrappers around libxml functions -----------------------------------------
 
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index c607f21..e0f92d9 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -40,6 +40,7 @@
 #include "base/path_service.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "chrome/common/chrome_paths.h"
@@ -58,6 +59,9 @@
 // InitChromeLogging() and the beginning of CleanupChromeLogging().
 static bool chrome_logging_initialized_ = false;
 
+// Set if we caled InitChromeLogging() but failed to initialize.
+static bool chrome_logging_failed_ = false;
+
 // This should be true for exactly the period between the end of
 // InitChromeLogging() and the beginning of CleanupChromeLogging().
 static bool chrome_logging_redirected_ = false;
@@ -213,15 +217,24 @@
   // defaults to the profile dir.
   FilePath log_path = GetSessionLogFile(command_line);
 
+  // Creating symlink causes us to do blocking IO on UI thread.
+  // Temporarily allow it until we fix http://crbug.com/61143
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   // Always force a new symlink when redirecting.
   FilePath target_path = SetUpSymlinkIfNeeded(log_path, true);
 
+  logging::DcheckState dcheck_state =
+      command_line.HasSwitch(switches::kEnableDCHECK) ?
+      logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
+      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
+
   // ChromeOS always logs through the symlink, so it shouldn't be
   // deleted if it already exists.
   if (!InitLogging(log_path.value().c_str(),
                    DetermineLogMode(command_line),
                    logging::LOCK_LOG_FILE,
-                   logging::APPEND_TO_OLD_LOG_FILE)) {
+                   logging::APPEND_TO_OLD_LOG_FILE,
+                   dcheck_state)) {
     LOG(ERROR) << "Unable to initialize logging to " << log_path.value();
     RemoveSymlinkAndLog(log_path, target_path);
   } else {
@@ -262,21 +275,29 @@
   delete_old_log_file = logging::APPEND_TO_OLD_LOG_FILE;
 #endif
 
+  logging::DcheckState dcheck_state =
+      command_line.HasSwitch(switches::kEnableDCHECK) ?
+      logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
+      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
+
   bool success = InitLogging(log_path.value().c_str(),
                              DetermineLogMode(command_line),
                              logging::LOCK_LOG_FILE,
-                             delete_old_log_file);
+                             delete_old_log_file,
+                             dcheck_state);
 
 #if defined(OS_CHROMEOS)
   if (!success) {
     PLOG(ERROR) << "Unable to initialize logging to " << log_path.value()
                 << " (which should be a link to " << target_path.value() << ")";
     RemoveSymlinkAndLog(log_path, target_path);
+    chrome_logging_failed_ = true;
     return;
   }
 #else
   if (!success) {
     PLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
+    chrome_logging_failed_ = true;
     return;
   }
 #endif
@@ -326,6 +347,9 @@
 // This is a no-op, but we'll keep it around in case
 // we need to do more cleanup in the future.
 void CleanupChromeLogging() {
+  if (chrome_logging_failed_)
+    return;  // We failed to initiailize logging, no cleanup.
+
   DCHECK(chrome_logging_initialized_) <<
     "Attempted to clean up logging when it wasn't initialized.";
 
diff --git a/chrome/common/metrics_helpers.cc b/chrome/common/metrics_helpers.cc
index c452937..644df78 100644
--- a/chrome/common/metrics_helpers.cc
+++ b/chrome/common/metrics_helpers.cc
@@ -52,7 +52,7 @@
         buffer_(NULL),
         writer_(NULL) {
     buffer_ = xmlBufferCreate();
-    DCHECK(buffer_);
+    CHECK(buffer_);
 
     #if defined(OS_CHROMEOS)
       writer_ = xmlNewTextWriterDoc(&doc_, /* compression */ 0);
@@ -151,6 +151,8 @@
 
 int MetricsLogBase::GetEncodedLogSize() {
   DCHECK(locked_);
+  CHECK(xml_wrapper_);
+  CHECK(xml_wrapper_->buffer());
   return xml_wrapper_->buffer()->use;
 }
 
diff --git a/chrome/common/native_web_keyboard_event.h b/chrome/common/native_web_keyboard_event.h
index 1ed0cb1..f27aa78 100644
--- a/chrome/common/native_web_keyboard_event.h
+++ b/chrome/common/native_web_keyboard_event.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "base/basictypes.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
diff --git a/chrome/common/native_web_keyboard_event_linux.cc b/chrome/common/native_web_keyboard_event_linux.cc
index 7165c98..46fafd5 100644
--- a/chrome/common/native_web_keyboard_event_linux.cc
+++ b/chrome/common/native_web_keyboard_event_linux.cc
@@ -6,7 +6,7 @@
 
 #include <gdk/gdk.h>
 
-#include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/gtk/WebInputEventFactory.h"
 
 using WebKit::WebInputEventFactory;
 
diff --git a/chrome/common/native_web_keyboard_event_mac.mm b/chrome/common/native_web_keyboard_event_mac.mm
index 0c11033..1fe53ae 100644
--- a/chrome/common/native_web_keyboard_event_mac.mm
+++ b/chrome/common/native_web_keyboard_event_mac.mm
@@ -6,7 +6,7 @@
 
 #import <AppKit/AppKit.h>
 
-#include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFactory.h"
 
 using WebKit::WebInputEventFactory;
 
diff --git a/chrome/common/native_web_keyboard_event_win.cc b/chrome/common/native_web_keyboard_event_win.cc
index 7608ec6..3f03d28 100644
--- a/chrome/common/native_web_keyboard_event_win.cc
+++ b/chrome/common/native_web_keyboard_event_win.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/common/native_web_keyboard_event.h"
 
-#include "third_party/WebKit/WebKit/chromium/public/win/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
 
 using WebKit::WebInputEventFactory;
 using WebKit::WebKeyboardEvent;
diff --git a/chrome/common/native_window_notification_source.h b/chrome/common/native_window_notification_source.h
index a8e5cae..240820e 100644
--- a/chrome/common/native_window_notification_source.h
+++ b/chrome/common/native_window_notification_source.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "chrome/common/notification_source.h"
-#include "gfx/native_widget_types.h"
+#include "ui/gfx/native_widget_types.h"
 
 // Specialization of the Source class for native windows.  On Windows, these are
 // HWNDs rather than pointers, and since the Source class expects a pointer
diff --git a/chrome/common/net/gaia/gaia_auth_consumer.cc b/chrome/common/net/gaia/gaia_auth_consumer.cc
new file mode 100644
index 0000000..7c47b60
--- /dev/null
+++ b/chrome/common/net/gaia/gaia_auth_consumer.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+
+GaiaAuthConsumer::ClientLoginResult::ClientLoginResult()
+    : two_factor(false) {
+}
+
+GaiaAuthConsumer::ClientLoginResult::ClientLoginResult(
+    const std::string& new_sid,
+    const std::string& new_lsid,
+    const std::string& new_token,
+    const std::string& new_data)
+    : sid(new_sid),
+      lsid(new_lsid),
+      token(new_token),
+      data(new_data),
+      two_factor(false) {}
+
+GaiaAuthConsumer::ClientLoginResult::~ClientLoginResult() {}
+
+bool GaiaAuthConsumer::ClientLoginResult::operator==(
+    const ClientLoginResult &b) const {
+  return sid == b.sid &&
+      lsid == b.lsid &&
+      token == b.token &&
+      data == b.data &&
+      two_factor == b.two_factor;
+}
diff --git a/chrome/common/net/gaia/gaia_auth_consumer.h b/chrome/common/net/gaia/gaia_auth_consumer.h
index d498e6c..4d6c37d 100644
--- a/chrome/common/net/gaia/gaia_auth_consumer.h
+++ b/chrome/common/net/gaia/gaia_auth_consumer.h
@@ -15,24 +15,14 @@
 class GaiaAuthConsumer {
  public:
   struct ClientLoginResult {
-    inline ClientLoginResult() : two_factor(false) {}
-    inline ClientLoginResult(const std::string& new_sid,
-                             const std::string& new_lsid,
-                             const std::string& new_token,
-                             const std::string& new_data)
-        : sid(new_sid),
-          lsid(new_lsid),
-          token(new_token),
-          data(new_data),
-          two_factor(false) {}
+    ClientLoginResult();
+    ClientLoginResult(const std::string& new_sid,
+                      const std::string& new_lsid,
+                      const std::string& new_token,
+                      const std::string& new_data);
+    ~ClientLoginResult();
 
-    inline bool operator==(const ClientLoginResult &b) const {
-      return sid == b.sid &&
-             lsid == b.lsid &&
-             token == b.token &&
-             data == b.data &&
-             two_factor == b.two_factor;
-    }
+    bool operator==(const ClientLoginResult &b) const;
 
     std::string sid;
     std::string lsid;
diff --git a/chrome/common/net/gaia/gaia_auth_fetcher.cc b/chrome/common/net/gaia/gaia_auth_fetcher.cc
index 0499168..520c135 100644
--- a/chrome/common/net/gaia/gaia_auth_fetcher.cc
+++ b/chrome/common/net/gaia/gaia_auth_fetcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -314,10 +314,10 @@
 // static
 GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError(
     const std::string& data,
-    const URLRequestStatus& status) {
+    const net::URLRequestStatus& status) {
 
   if (!status.is_success()) {
-    if (status.status() == URLRequestStatus::CANCELED) {
+    if (status.status() == net::URLRequestStatus::CANCELED) {
       return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
     } else {
       LOG(WARNING) << "Could not reach Google Accounts servers: errno "
@@ -361,10 +361,11 @@
   }
 
   NOTREACHED();
+  return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
 }
 
 void GaiaAuthFetcher::OnClientLoginFetched(const std::string& data,
-                                           const URLRequestStatus& status,
+                                           const net::URLRequestStatus& status,
                                            int response_code) {
 
   if (status.is_success() && response_code == RC_REQUEST_OK) {
@@ -382,7 +383,7 @@
 
 void GaiaAuthFetcher::OnIssueAuthTokenFetched(
     const std::string& data,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code) {
   if (status.is_success() && response_code == RC_REQUEST_OK) {
     // Only the bare token is returned in the body of this Gaia call
@@ -396,7 +397,7 @@
 
 void GaiaAuthFetcher::OnGetUserInfoFetched(
     const std::string& data,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code) {
   using std::vector;
   using std::string;
@@ -420,7 +421,7 @@
 
 void GaiaAuthFetcher::OnURLFetchComplete(const URLFetcher* source,
                                          const GURL& url,
-                                         const URLRequestStatus& status,
+                                         const net::URLRequestStatus& status,
                                          int response_code,
                                          const ResponseCookies& cookies,
                                          const std::string& data) {
diff --git a/chrome/common/net/gaia/gaia_auth_fetcher_unittest.cc b/chrome/common/net/gaia/gaia_auth_fetcher_unittest.cc
index c7814c9..0830766 100644
--- a/chrome/common/net/gaia/gaia_auth_fetcher_unittest.cc
+++ b/chrome/common/net/gaia/gaia_auth_fetcher_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -115,7 +115,7 @@
 
 TEST_F(GaiaAuthFetcherTest, LoginNetFailure) {
   int error_no = net::ERR_CONNECTION_RESET;
-  URLRequestStatus status(URLRequestStatus::FAILED, error_no);
+  net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no);
 
   GoogleServiceAuthError expected_error =
       GoogleServiceAuthError::FromConnectionError(error_no);
@@ -137,7 +137,7 @@
 
 TEST_F(GaiaAuthFetcherTest, TokenNetFailure) {
   int error_no = net::ERR_CONNECTION_RESET;
-  URLRequestStatus status(URLRequestStatus::FAILED, error_no);
+  net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no);
 
   GoogleServiceAuthError expected_error =
       GoogleServiceAuthError::FromConnectionError(error_no);
@@ -160,7 +160,7 @@
 
 TEST_F(GaiaAuthFetcherTest, LoginDenied) {
   std::string data("Error=BadAuthentication");
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
 
   GoogleServiceAuthError expected_error(
       GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
@@ -220,7 +220,7 @@
 
   GaiaAuthFetcher auth(&consumer, std::string(),
       profile_.GetRequestContext());
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   auth.OnURLFetchComplete(NULL,
                           client_login_source_,
                           status,
@@ -236,7 +236,7 @@
 
   GaiaAuthFetcher auth(&consumer, std::string(),
       profile_.GetRequestContext());
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   auth.OnURLFetchComplete(NULL,
                           issue_auth_token_source_,
                           status,
@@ -270,7 +270,7 @@
 
   GaiaAuthFetcher auth(&consumer, std::string(),
       profile_.GetRequestContext());
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   auth.OnURLFetchComplete(NULL,
                           client_login_source_,
                           status,
@@ -280,7 +280,7 @@
 }
 
 TEST_F(GaiaAuthFetcherTest, CaptchaParse) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   std::string data = "Url=http://www.google.com/login/captcha\n"
                      "Error=CaptchaRequired\n"
                      "CaptchaToken=CCTOKEN\n"
@@ -299,7 +299,7 @@
 }
 
 TEST_F(GaiaAuthFetcherTest, AccountDeletedError) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   std::string data = "Error=AccountDeleted\n";
   GoogleServiceAuthError error =
       GaiaAuthFetcher::GenerateAuthError(data, status);
@@ -307,7 +307,7 @@
 }
 
 TEST_F(GaiaAuthFetcherTest, AccountDisabledError) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   std::string data = "Error=AccountDisabled\n";
   GoogleServiceAuthError error =
       GaiaAuthFetcher::GenerateAuthError(data, status);
@@ -315,7 +315,7 @@
 }
 
 TEST_F(GaiaAuthFetcherTest,BadAuthenticationError) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   std::string data = "Error=BadAuthentication\n";
   GoogleServiceAuthError error =
       GaiaAuthFetcher::GenerateAuthError(data, status);
@@ -323,7 +323,7 @@
 }
 
 TEST_F(GaiaAuthFetcherTest,IncomprehensibleError) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   std::string data = "Error=Gobbledygook\n";
   GoogleServiceAuthError error =
       GaiaAuthFetcher::GenerateAuthError(data, status);
@@ -331,7 +331,7 @@
 }
 
 TEST_F(GaiaAuthFetcherTest,ServiceUnavailableError) {
-  URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+  net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
   std::string data = "Error=ServiceUnavailable\n";
   GoogleServiceAuthError error =
       GaiaAuthFetcher::GenerateAuthError(data, status);
@@ -403,12 +403,13 @@
 
   URLFetcher::set_factory(NULL);
   EXPECT_TRUE(auth.HasPendingFetch());
-  auth.OnURLFetchComplete(NULL,
-                          client_login_source_,
-                          URLRequestStatus(URLRequestStatus::SUCCESS, 0),
-                          RC_REQUEST_OK,
-                          cookies_,
-                          "SID=sid\nLSID=lsid\nAuth=auth\n");
+  auth.OnURLFetchComplete(
+      NULL,
+      client_login_source_,
+      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
+      RC_REQUEST_OK,
+      cookies_,
+      "SID=sid\nLSID=lsid\nAuth=auth\n");
   EXPECT_FALSE(auth.HasPendingFetch());
 }
 
@@ -427,12 +428,13 @@
 
   URLFetcher::set_factory(NULL);
   EXPECT_TRUE(auth.HasPendingFetch());
-  auth.OnURLFetchComplete(NULL,
-                          issue_auth_token_source_,
-                          URLRequestStatus(URLRequestStatus::SUCCESS, 0),
-                          RC_REQUEST_OK,
-                          cookies_,
-                          "token");
+  auth.OnURLFetchComplete(
+      NULL,
+      issue_auth_token_source_,
+      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
+      RC_REQUEST_OK,
+      cookies_,
+      "token");
   EXPECT_FALSE(auth.HasPendingFetch());
 }
 
@@ -451,11 +453,12 @@
 
   URLFetcher::set_factory(NULL);
   EXPECT_TRUE(auth.HasPendingFetch());
-  auth.OnURLFetchComplete(NULL,
-                          issue_auth_token_source_,
-                          URLRequestStatus(URLRequestStatus::SUCCESS, 0),
-                          RC_FORBIDDEN,
-                          cookies_,
-                          "");
+  auth.OnURLFetchComplete(
+      NULL,
+      issue_auth_token_source_,
+      net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0),
+      RC_FORBIDDEN,
+      cookies_,
+      "");
   EXPECT_FALSE(auth.HasPendingFetch());
 }
diff --git a/chrome/common/net/gaia/gaia_auth_fetcher_unittest.h b/chrome/common/net/gaia/gaia_auth_fetcher_unittest.h
index 4676a26..65235b1 100644
--- a/chrome/common/net/gaia/gaia_auth_fetcher_unittest.h
+++ b/chrome/common/net/gaia/gaia_auth_fetcher_unittest.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -32,17 +32,17 @@
   ~MockFetcher() {}
 
   void Start() {
-    URLRequestStatus::Status code;
+    net::URLRequestStatus::Status code;
     int http_code;
     if (success_) {
       http_code = RC_REQUEST_OK;
-      code = URLRequestStatus::SUCCESS;
+      code = net::URLRequestStatus::SUCCESS;
     } else {
       http_code = RC_FORBIDDEN;
-      code = URLRequestStatus::FAILED;
+      code = net::URLRequestStatus::FAILED;
     }
 
-    URLRequestStatus status(code, 0);
+    net::URLRequestStatus status(code, 0);
     delegate()->OnURLFetchComplete(NULL,
                                    url_,
                                    status,
diff --git a/chrome/common/net/gaia/gaia_authenticator.h b/chrome/common/net/gaia/gaia_authenticator.h
index be1b2d9..ce0500d 100644
--- a/chrome/common/net/gaia/gaia_authenticator.h
+++ b/chrome/common/net/gaia/gaia_authenticator.h
@@ -250,7 +250,7 @@
     return auth_results_;
   }
 
-  typedef EventChannel<GaiaAuthEvent, Lock> Channel;
+  typedef EventChannel<GaiaAuthEvent, base::Lock> Channel;
 
   inline Channel* channel() const {
     return channel_;
diff --git a/chrome/common/net/gaia/google_service_auth_error.cc b/chrome/common/net/gaia/google_service_auth_error.cc
new file mode 100644
index 0000000..78595eb
--- /dev/null
+++ b/chrome/common/net/gaia/google_service_auth_error.cc
@@ -0,0 +1,110 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/common/net/gaia/google_service_auth_error.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "net/base/net_errors.h"
+
+GoogleServiceAuthError::Captcha::Captcha(
+    const std::string& t, const GURL& img, const GURL& unlock)
+    : token(t), image_url(img), unlock_url(unlock) {}
+
+bool GoogleServiceAuthError::operator==(
+    const GoogleServiceAuthError &b) const {
+  return (state_ == b.state_ &&
+          network_error_ == b.network_error_ &&
+          captcha_.token == b.captcha_.token &&
+          captcha_.image_url == b.captcha_.image_url &&
+          captcha_.unlock_url == b.captcha_.unlock_url);
+}
+
+GoogleServiceAuthError::GoogleServiceAuthError(State s)
+    : state_(s),
+      captcha_("", GURL(), GURL()),
+      network_error_(0) {
+  // If the caller has no idea, then we just set it to a generic failure.
+  if (s == CONNECTION_FAILED) {
+    network_error_ = net::ERR_FAILED;
+  }
+}
+
+GoogleServiceAuthError
+    GoogleServiceAuthError::FromConnectionError(int error) {
+  return GoogleServiceAuthError(CONNECTION_FAILED, error);
+}
+
+GoogleServiceAuthError GoogleServiceAuthError::FromCaptchaChallenge(
+    const std::string& captcha_token,
+    const GURL& captcha_image_url,
+    const GURL& captcha_unlock_url) {
+  return GoogleServiceAuthError(CAPTCHA_REQUIRED, captcha_token,
+                                captcha_image_url, captcha_unlock_url);
+}
+
+GoogleServiceAuthError GoogleServiceAuthError::None() {
+  return GoogleServiceAuthError(NONE);
+}
+
+const GoogleServiceAuthError::State& GoogleServiceAuthError::state() const {
+  return state_;
+}
+
+const GoogleServiceAuthError::Captcha& GoogleServiceAuthError::captcha() const {
+  return captcha_;
+}
+
+int GoogleServiceAuthError::network_error() const {
+  return network_error_;
+}
+
+DictionaryValue* GoogleServiceAuthError::ToValue() const {
+  DictionaryValue* value = new DictionaryValue();
+  std::string state_str;
+  switch (state_) {
+#define STATE_CASE(x) case x: state_str = #x; break
+    STATE_CASE(NONE);
+    STATE_CASE(INVALID_GAIA_CREDENTIALS);
+    STATE_CASE(USER_NOT_SIGNED_UP);
+    STATE_CASE(CONNECTION_FAILED);
+    STATE_CASE(CAPTCHA_REQUIRED);
+    STATE_CASE(ACCOUNT_DELETED);
+    STATE_CASE(ACCOUNT_DISABLED);
+    STATE_CASE(SERVICE_UNAVAILABLE);
+    STATE_CASE(TWO_FACTOR);
+    STATE_CASE(REQUEST_CANCELED);
+    STATE_CASE(HOSTED_NOT_ALLOWED);
+#undef STATE_CASE
+    default:
+      NOTREACHED();
+      break;
+  }
+  value->SetString("state", state_str);
+  if (state_ == CAPTCHA_REQUIRED) {
+    DictionaryValue* captcha_value = new DictionaryValue();
+    value->Set("captcha", captcha_value);
+    captcha_value->SetString("token", captcha_.token);
+    captcha_value->SetString("imageUrl", captcha_.image_url.spec());
+    captcha_value->SetString("unlockUrl", captcha_.unlock_url.spec());
+  } else if (state_ == CONNECTION_FAILED) {
+    value->SetString("networkError", net::ErrorToString(network_error_));
+  }
+  return value;
+}
+
+GoogleServiceAuthError::GoogleServiceAuthError(State s, int error)
+    : state_(s),
+      captcha_("", GURL(), GURL()),
+      network_error_(error) {}
+
+GoogleServiceAuthError::GoogleServiceAuthError(
+    State s, const std::string& captcha_token,
+    const GURL& captcha_image_url,
+    const GURL& captcha_unlock_url)
+    : state_(s),
+      captcha_(captcha_token, captcha_image_url, captcha_unlock_url),
+      network_error_(0) {}
diff --git a/chrome/common/net/gaia/google_service_auth_error.h b/chrome/common/net/gaia/google_service_auth_error.h
index 032f59f..747df44 100644
--- a/chrome/common/net/gaia/google_service_auth_error.h
+++ b/chrome/common/net/gaia/google_service_auth_error.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -24,9 +24,10 @@
 #pragma once
 
 #include <string>
-#include "base/logging.h"
+
 #include "googleurl/src/gurl.h"
-#include "net/base/net_errors.h"
+
+class DictionaryValue;
 
 class GoogleServiceAuthError {
  public:
@@ -79,78 +80,48 @@
 
   // Additional data for CAPTCHA_REQUIRED errors.
   struct Captcha {
-    Captcha() {}
-    Captcha(const std::string& t, const GURL& img, const GURL& unlock)
-        : token(t), image_url(img), unlock_url(unlock) {}
+    Captcha(const std::string& t, const GURL& img, const GURL& unlock);
     std::string token;  // Globally identifies the specific CAPTCHA challenge.
     GURL image_url;     // The CAPTCHA image to show the user.
     GURL unlock_url;    // Pretty unlock page containing above captcha.
   };
 
   // For test only.
-  inline bool operator==(const GoogleServiceAuthError &b) const {
-    return (state_ == b.state_ &&
-            network_error_ == b.network_error_ &&
-            captcha_.token == b.captcha_.token &&
-            captcha_.image_url == b.captcha_.image_url &&
-            captcha_.unlock_url == b.captcha_.unlock_url);
-  }
+  bool operator==(const GoogleServiceAuthError &b) const;
 
   // Construct a GoogleServiceAuthError from a State with no additional data.
-  explicit GoogleServiceAuthError(State s)
-      : state_(s),
-        captcha_("", GURL(), GURL()),
-        network_error_(0) {
-    // If the caller has no idea, then we just set it to a generic failure.
-    if (s == CONNECTION_FAILED) {
-      network_error_ = net::ERR_FAILED;
-    }
-  }
+  explicit GoogleServiceAuthError(State s);
 
   // Construct a GoogleServiceAuthError from a network error.
   // It will be created with CONNECTION_FAILED set.
-  static GoogleServiceAuthError FromConnectionError(int error) {
-    return GoogleServiceAuthError(CONNECTION_FAILED, error);
-  }
+  static GoogleServiceAuthError FromConnectionError(int error);
 
   // Construct a CAPTCHA_REQUIRED error with CAPTCHA challenge data.
   static GoogleServiceAuthError FromCaptchaChallenge(
       const std::string& captcha_token,
       const GURL& captcha_image_url,
-      const GURL& captcha_unlock_url) {
-    return GoogleServiceAuthError(CAPTCHA_REQUIRED, captcha_token,
-                                  captcha_image_url, captcha_unlock_url);
-  }
+      const GURL& captcha_unlock_url);
 
   // Provided for convenience for clients needing to reset an instance to NONE.
   // (avoids err_ = GoogleServiceAuthError(GoogleServiceAuthError::NONE), due
   // to explicit class and State enum relation. Note: shouldn't be inlined!
-  static const GoogleServiceAuthError None() {
-    static const GoogleServiceAuthError e(NONE);
-    return e;
-  }
+  static GoogleServiceAuthError None();
 
   // The error information.
-  const State& state() const { return state_; }
-  const Captcha& captcha() const { return captcha_; }
-  int network_error() const {
-    return network_error_;
-  }
+  const State& state() const;
+  const Captcha& captcha() const;
+  int network_error() const;
+
+  // Returns info about this object in a dictionary.  Caller takes
+  // ownership of returned dictionary.
+  DictionaryValue* ToValue() const;
 
  private:
-  GoogleServiceAuthError(State s, int error)
-      : state_(s),
-        captcha_("", GURL(), GURL()),
-        network_error_(error) {
-  }
+  GoogleServiceAuthError(State s, int error);
 
   GoogleServiceAuthError(State s, const std::string& captcha_token,
                          const GURL& captcha_image_url,
-                         const GURL& captcha_unlock_url)
-      : state_(s),
-        captcha_(captcha_token, captcha_image_url, captcha_unlock_url),
-        network_error_(0) {
-  }
+                         const GURL& captcha_unlock_url);
 
   State state_;
   Captcha captcha_;
diff --git a/chrome/common/net/gaia/google_service_auth_error_unittest.cc b/chrome/common/net/gaia/google_service_auth_error_unittest.cc
new file mode 100644
index 0000000..f4fde5f
--- /dev/null
+++ b/chrome/common/net/gaia/google_service_auth_error_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/common/net/gaia/google_service_auth_error.h"
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/test/values_test_util.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using test::ExpectStringValue;
+
+class GoogleServiceAuthErrorTest : public testing::Test {};
+
+void TestSimpleState(GoogleServiceAuthError::State state) {
+  GoogleServiceAuthError error(state);
+  scoped_ptr<DictionaryValue> value(error.ToValue());
+  EXPECT_EQ(1u, value->size());
+  std::string state_str;
+  EXPECT_TRUE(value->GetString("state", &state_str));
+  EXPECT_FALSE(state_str.empty());
+  EXPECT_NE("CONNECTION_FAILED", state_str);
+  EXPECT_NE("CAPTCHA_REQUIRED", state_str);
+}
+
+TEST_F(GoogleServiceAuthErrorTest, SimpleToValue) {
+  for (int i = GoogleServiceAuthError::NONE;
+       i <= GoogleServiceAuthError::USER_NOT_SIGNED_UP; ++i) {
+    TestSimpleState(static_cast<GoogleServiceAuthError::State>(i));
+  }
+}
+
+TEST_F(GoogleServiceAuthErrorTest, None) {
+  GoogleServiceAuthError error(GoogleServiceAuthError::None());
+  scoped_ptr<DictionaryValue> value(error.ToValue());
+  EXPECT_EQ(1u, value->size());
+  ExpectStringValue("NONE", *value, "state");
+}
+
+TEST_F(GoogleServiceAuthErrorTest, ConnectionFailed) {
+  GoogleServiceAuthError error(
+      GoogleServiceAuthError::FromConnectionError(net::OK));
+  scoped_ptr<DictionaryValue> value(error.ToValue());
+  EXPECT_EQ(2u, value->size());
+  ExpectStringValue("CONNECTION_FAILED", *value, "state");
+  ExpectStringValue("net::OK", *value, "networkError");
+}
+
+TEST_F(GoogleServiceAuthErrorTest, CaptchaChallenge) {
+  GoogleServiceAuthError error(
+      GoogleServiceAuthError::FromCaptchaChallenge(
+          "captcha_token", GURL("http://www.google.com"),
+          GURL("http://www.bing.com")));
+  scoped_ptr<DictionaryValue> value(error.ToValue());
+  EXPECT_EQ(2u, value->size());
+  ExpectStringValue("CAPTCHA_REQUIRED", *value, "state");
+  DictionaryValue* captcha_value = NULL;
+  EXPECT_TRUE(value->GetDictionary("captcha", &captcha_value));
+  ASSERT_TRUE(captcha_value);
+  ExpectStringValue("captcha_token", *captcha_value, "token");
+  ExpectStringValue("http://www.google.com/", *captcha_value, "imageUrl");
+  ExpectStringValue("http://www.bing.com/", *captcha_value, "unlockUrl");
+}
+
+}  // namespace
diff --git a/chrome/common/net/net_resource_provider.cc b/chrome/common/net/net_resource_provider.cc
index c64c81d..346d763 100644
--- a/chrome/common/net/net_resource_provider.cc
+++ b/chrome/common/net/net_resource_provider.cc
@@ -6,14 +6,14 @@
 
 #include <string>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/string_piece.h"
 #include "base/values.h"
 #include "chrome/common/jstemplate_builder.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/net_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
diff --git a/chrome/common/net/test_url_fetcher_factory.cc b/chrome/common/net/test_url_fetcher_factory.cc
index 8336dfd..869e9be 100644
--- a/chrome/common/net/test_url_fetcher_factory.cc
+++ b/chrome/common/net/test_url_fetcher_factory.cc
@@ -1,8 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/common/net/test_url_fetcher_factory.h"
+
 #include <string>
 
 #include "base/compiler_specific.h"
@@ -18,6 +19,10 @@
       original_url_(url) {
 }
 
+TestURLFetcherFactory::TestURLFetcherFactory() {}
+
+TestURLFetcherFactory::~TestURLFetcherFactory() {}
+
 URLFetcher* TestURLFetcherFactory::CreateURLFetcher(
     int id,
     const GURL& url,
@@ -67,9 +72,9 @@
   // This is the method which actually calls the delegate that is passed in the
   // constructor.
   void RunDelegate() {
-    URLRequestStatus status;
-    status.set_status(success_ ? URLRequestStatus::SUCCESS :
-                                 URLRequestStatus::FAILED);
+    net::URLRequestStatus status;
+    status.set_status(success_ ? net::URLRequestStatus::SUCCESS :
+                                 net::URLRequestStatus::FAILED);
     delegate()->OnURLFetchComplete(this, url_, status, success_ ? 200 : 500,
                                    ResponseCookies(), response_data_);
   }
@@ -86,6 +91,10 @@
   DISALLOW_COPY_AND_ASSIGN(FakeURLFetcher);
 };
 
+FakeURLFetcherFactory::FakeURLFetcherFactory() {}
+
+FakeURLFetcherFactory::~FakeURLFetcherFactory() {}
+
 URLFetcher* FakeURLFetcherFactory::CreateURLFetcher(
     int id,
     const GURL& url,
diff --git a/chrome/common/net/test_url_fetcher_factory.h b/chrome/common/net/test_url_fetcher_factory.h
index 73f4b46..65625a4 100644
--- a/chrome/common/net/test_url_fetcher_factory.h
+++ b/chrome/common/net/test_url_fetcher_factory.h
@@ -76,7 +76,8 @@
 // are registered in a map by the id passed to the create method.
 class TestURLFetcherFactory : public URLFetcher::Factory {
  public:
-  TestURLFetcherFactory() {}
+  TestURLFetcherFactory();
+  virtual ~TestURLFetcherFactory();
 
   virtual URLFetcher* CreateURLFetcher(int id,
                                        const GURL& url,
@@ -128,7 +129,8 @@
 
 class FakeURLFetcherFactory : public URLFetcher::Factory {
  public:
-  FakeURLFetcherFactory() {}
+  FakeURLFetcherFactory();
+  virtual ~FakeURLFetcherFactory();
 
   // If no fake response is set for the given URL this method will return NULL.
   // Otherwise, it will return a URLFetcher object which will respond with the
diff --git a/chrome/common/net/url_fetcher.cc b/chrome/common/net/url_fetcher.cc
index 53112f3..150dbab 100644
--- a/chrome/common/net/url_fetcher.cc
+++ b/chrome/common/net/url_fetcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,7 +8,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/message_loop_proxy.h"
 #include "base/scoped_ptr.h"
 #include "base/stl_util-inl.h"
@@ -95,7 +94,7 @@
   void StartURLRequest();
   void StartURLRequestWhenAppropriate();
   void CancelURLRequest();
-  void OnCompletedURLRequest(const URLRequestStatus& status);
+  void OnCompletedURLRequest(const net::URLRequestStatus& status);
   void NotifyMalformedContent();
 
   // Deletes the request, removes it from the registry, and removes the
@@ -106,6 +105,12 @@
   // |original_url_| and |url_|.
   base::TimeTicks GetBackoffReleaseTime();
 
+  void CompleteAddingUploadDataChunk(const std::string& data);
+
+  // Adds a block of data to be uploaded in a POST body. This can only be called
+  // after Start().
+  void AppendChunkToUpload(const std::string& data);
+
   URLFetcher* fetcher_;              // Corresponding fetcher object
   GURL original_url_;                // The URL we were asked to fetch
   GURL url_;                         // The URL we eventually wound up at
@@ -131,6 +136,8 @@
 
   std::string upload_content_;       // HTTP POST payload
   std::string upload_content_type_;  // MIME type of POST payload
+  std::string referrer_;             // HTTP Referer header value
+  bool is_chunked_upload_;           // True if using chunked transfer encoding
 
   // Used to determine how long to wait before making a request or doing a
   // retry.
@@ -230,6 +237,7 @@
       load_flags_(net::LOAD_NORMAL),
       response_code_(-1),
       buffer_(new net::IOBuffer(kBufferSize)),
+      is_chunked_upload_(false),
       num_retries_(0),
       was_cancelled_(false) {
 }
@@ -291,6 +299,26 @@
   OnReadCompleted(request_.get(), bytes_read);
 }
 
+void URLFetcher::Core::CompleteAddingUploadDataChunk(
+    const std::string& content) {
+  DCHECK(is_chunked_upload_);
+  DCHECK(request_.get());
+  if (content.length()) {
+    request_->AppendChunkToUpload(content.data(),
+                                  static_cast<int>(content.length()));
+  } else {
+    request_->MarkEndOfChunks();
+  }
+}
+
+void URLFetcher::Core::AppendChunkToUpload(const std::string& content) {
+  DCHECK(delegate_loop_proxy_);
+  CHECK(io_message_loop_proxy_.get());
+  io_message_loop_proxy_->PostTask(
+      FROM_HERE,
+      NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content));
+}
+
 void URLFetcher::Core::OnReadCompleted(net::URLRequest* request,
                                        int bytes_read) {
   DCHECK(request == request_);
@@ -343,22 +371,27 @@
   if (!g_interception_enabled) {
     flags = flags | net::LOAD_DISABLE_INTERCEPT;
   }
+  if (is_chunked_upload_)
+    request_->EnableChunkedUpload();
   request_->set_load_flags(flags);
   request_->set_context(request_context_getter_->GetURLRequestContext());
+  request_->set_referrer(referrer_);
 
   switch (request_type_) {
     case GET:
       break;
 
     case POST:
-      DCHECK(!upload_content_.empty());
+      DCHECK(!upload_content_.empty() || is_chunked_upload_);
       DCHECK(!upload_content_type_.empty());
 
       request_->set_method("POST");
       extra_request_headers_.SetHeader(net::HttpRequestHeaders::kContentType,
                                        upload_content_type_);
-      request_->AppendBytesToUpload(upload_content_.data(),
-                                    static_cast<int>(upload_content_.size()));
+      if (!upload_content_.empty()) {
+        request_->AppendBytesToUpload(
+            upload_content_.data(), static_cast<int>(upload_content_.length()));
+      }
       break;
 
     case HEAD:
@@ -417,7 +450,8 @@
   was_cancelled_ = true;
 }
 
-void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
+void URLFetcher::Core::OnCompletedURLRequest(
+    const net::URLRequestStatus& status) {
   DCHECK(delegate_loop_proxy_->BelongsToCurrentThread());
 
   // Checks the response from server.
@@ -481,14 +515,37 @@
 
 void URLFetcher::set_upload_data(const std::string& upload_content_type,
                                  const std::string& upload_content) {
+  DCHECK(!core_->is_chunked_upload_);
   core_->upload_content_type_ = upload_content_type;
   core_->upload_content_ = upload_content;
 }
 
+void URLFetcher::set_chunked_upload(const std::string& content_type) {
+  DCHECK(core_->is_chunked_upload_ ||
+         (core_->upload_content_type_.empty() &&
+          core_->upload_content_.empty()));
+  core_->upload_content_type_ = content_type;
+  core_->upload_content_.clear();
+  core_->is_chunked_upload_ = true;
+}
+
+void URLFetcher::AppendChunkToUpload(const std::string& data) {
+  DCHECK(data.length());
+  core_->AppendChunkToUpload(data);
+}
+
+void URLFetcher::MarkEndOfChunks() {
+  core_->AppendChunkToUpload(std::string());
+}
+
 const std::string& URLFetcher::upload_data() const {
   return core_->upload_content_;
 }
 
+void URLFetcher::set_referrer(const std::string& referrer) {
+  core_->referrer_ = referrer;
+}
+
 void URLFetcher::set_load_flags(int load_flags) {
   core_->load_flags_ = load_flags;
 }
diff --git a/chrome/common/net/url_fetcher.h b/chrome/common/net/url_fetcher.h
index 8c42398..524e7cb 100644
--- a/chrome/common/net/url_fetcher.h
+++ b/chrome/common/net/url_fetcher.h
@@ -136,6 +136,21 @@
   void set_upload_data(const std::string& upload_content_type,
                        const std::string& upload_content);
 
+  // Indicates that the POST data is sent via chunked transfer encoding.
+  // This may only be called before calling Start().
+  // Use AppendChunkToUpload() to give the data chunks after calling Start().
+  void set_chunked_upload(const std::string& upload_content_type);
+
+  // Adds the given bytes to a request's POST data transmitted using chunked
+  // transfer encoding.
+  // This method should be called ONLY after calling Start().
+  void AppendChunkToUpload(const std::string& data);
+
+  // Signals the end of a chunked transfer encoded data stream. This method
+  // should be called ONLY after calling Start(), set_chunked_upload() and
+  // typically one or more calls to AppendChunkToUpload.
+  void MarkEndOfChunks();
+
   // Set one or more load flags as defined in net/base/load_flags.h.  Must be
   // called before the request is started.
   void set_load_flags(int load_flags);
@@ -143,11 +158,15 @@
   // Returns the current load flags.
   int load_flags() const;
 
+  // The referrer URL for the request. Must be called before the request is
+  // started.
+  void set_referrer(const std::string& referrer);
+
   // Set extra headers on the request.  Must be called before the request
   // is started.
   void set_extra_request_headers(const std::string& extra_request_headers);
 
-  // Set the URLRequestContext on the request.  Must be called before the
+  // Set the net::URLRequestContext on the request.  Must be called before the
   // request is started.
 #ifdef ANDROID
   // TODO: Upstream.
diff --git a/chrome/common/net/url_fetcher_unittest.cc b/chrome/common/net/url_fetcher_unittest.cc
index 1618892..0d36f02 100644
--- a/chrome/common/net/url_fetcher_unittest.cc
+++ b/chrome/common/net/url_fetcher_unittest.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/message_loop_proxy.h"
-#include "base/threading/thread.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
 #include "build/build_config.h"
 #include "chrome/common/chrome_plugin_lib.h"
 #include "chrome/common/net/url_fetcher.h"
 #include "chrome/common/net/url_request_context_getter.h"
 #include "net/http/http_response_headers.h"
 #include "net/test/test_server.h"
+#include "net/url_request/url_request_test_util.h"
 #include "net/url_request/url_request_throttler_manager.h"
-#include "net/url_request/url_request_unittest.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(USE_NSS)
@@ -34,7 +34,7 @@
       base::MessageLoopProxy* io_message_loop_proxy)
           : io_message_loop_proxy_(io_message_loop_proxy) {
   }
-  virtual URLRequestContext* GetURLRequestContext() {
+  virtual net::URLRequestContext* GetURLRequestContext() {
     if (!context_)
       context_ = new TestURLRequestContext();
     return context_;
@@ -49,7 +49,7 @@
  private:
   ~TestURLRequestContextGetter() {}
 
-  scoped_refptr<URLRequestContext> context_;
+  scoped_refptr<net::URLRequestContext> context_;
 };
 
 class URLFetcherTest : public testing::Test, public URLFetcher::Delegate {
@@ -62,7 +62,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -108,7 +108,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -120,7 +120,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -133,7 +133,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -149,7 +149,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -165,7 +165,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -181,7 +181,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -206,7 +206,7 @@
       : io_message_loop_proxy_(io_message_loop_proxy),
         context_created_(false, false) {
   }
-  virtual URLRequestContext* GetURLRequestContext() {
+  virtual net::URLRequestContext* GetURLRequestContext() {
     if (!context_) {
       context_ = new CancelTestURLRequestContext();
       context_created_.Signal();
@@ -225,7 +225,7 @@
 
   scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
   base::WaitableEvent context_created_;
-  scoped_refptr<URLRequestContext> context_;
+  scoped_refptr<net::URLRequestContext> context_;
 };
 
 // Version of URLFetcherTest that tests retying the same request twice.
@@ -234,7 +234,7 @@
   // URLFetcher::Delegate
   virtual void OnURLFetchComplete(const URLFetcher* source,
                                   const GURL& url,
-                                  const URLRequestStatus& status,
+                                  const net::URLRequestStatus& status,
                                   int response_code,
                                   const ResponseCookies& cookies,
                                   const std::string& data);
@@ -269,7 +269,7 @@
 
 void URLFetcherTest::OnURLFetchComplete(const URLFetcher* source,
                                         const GURL& url,
-                                        const URLRequestStatus& status,
+                                        const net::URLRequestStatus& status,
                                         int response_code,
                                         const ResponseCookies& cookies,
                                         const std::string& data) {
@@ -297,7 +297,7 @@
 
 void URLFetcherPostTest::OnURLFetchComplete(const URLFetcher* source,
                                             const GURL& url,
-                                            const URLRequestStatus& status,
+                                            const net::URLRequestStatus& status,
                                             int response_code,
                                             const ResponseCookies& cookies,
                                             const std::string& data) {
@@ -309,7 +309,7 @@
 void URLFetcherHeadersTest::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -330,12 +330,13 @@
   fetcher_->Start();
 }
 
-void URLFetcherProtectTest::OnURLFetchComplete(const URLFetcher* source,
-                                               const GURL& url,
-                                               const URLRequestStatus& status,
-                                               int response_code,
-                                               const ResponseCookies& cookies,
-                                               const std::string& data) {
+void URLFetcherProtectTest::OnURLFetchComplete(
+    const URLFetcher* source,
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
+    const std::string& data) {
   const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
   if (response_code >= 500) {
     // Now running ServerUnavailable test.
@@ -374,7 +375,7 @@
 void URLFetcherProtectTestPassedThrough::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -413,13 +414,13 @@
 void URLFetcherBadHTTPSTest::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
   // This part is different from URLFetcherTest::OnURLFetchComplete
   // because this test expects the request to be cancelled.
-  EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
   EXPECT_EQ(net::ERR_ABORTED, status.os_error());
   EXPECT_EQ(-1, response_code);
   EXPECT_TRUE(cookies.empty());
@@ -437,18 +438,19 @@
   fetcher_->set_request_context(context_getter);
   fetcher_->set_max_retries(2);
   fetcher_->Start();
-  // We need to wait for the creation of the URLRequestContext, since we
+  // We need to wait for the creation of the net::URLRequestContext, since we
   // rely on it being destroyed as a signal to end the test.
   context_getter->WaitForContextCreation();
   CancelRequest();
 }
 
-void URLFetcherCancelTest::OnURLFetchComplete(const URLFetcher* source,
-                                              const GURL& url,
-                                              const URLRequestStatus& status,
-                                              int response_code,
-                                              const ResponseCookies& cookies,
-                                              const std::string& data) {
+void URLFetcherCancelTest::OnURLFetchComplete(
+    const URLFetcher* source,
+    const GURL& url,
+    const net::URLRequestStatus& status,
+    int response_code,
+    const ResponseCookies& cookies,
+    const std::string& data) {
   // We should have cancelled the request before completion.
   ADD_FAILURE();
   delete fetcher_;
@@ -465,7 +467,7 @@
 void URLFetcherMultipleAttemptTest::OnURLFetchComplete(
     const URLFetcher* source,
     const GURL& url,
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     int response_code,
     const ResponseCookies& cookies,
     const std::string& data) {
@@ -499,7 +501,12 @@
   MessageLoop::current()->Run();
 }
 
+#if defined(OS_MACOSX)
+// SIGSEGV on Mac: http://crbug.com/60426
+TEST_F(URLFetcherTest, DISABLED_DifferentThreadsTest) {
+#else
 TEST_F(URLFetcherTest, DifferentThreadsTest) {
+#endif
   net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
   ASSERT_TRUE(test_server.Start());
 
@@ -516,7 +523,12 @@
   MessageLoop::current()->Run();
 }
 
+#if defined(OS_MACOSX)
+// SIGSEGV on Mac: http://crbug.com/60426
+TEST_F(URLFetcherPostTest, DISABLED_Basic) {
+#else
 TEST_F(URLFetcherPostTest, Basic) {
+#endif
   net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
   ASSERT_TRUE(test_server.Start());
 
@@ -600,7 +612,12 @@
   net::URLRequestThrottlerManager::GetInstance()->EraseEntryForTests(url);
 }
 
+#if defined(OS_MACOSX)
+// SIGSEGV on Mac: http://crbug.com/60426
+TEST_F(URLFetcherBadHTTPSTest, DISABLED_BadHTTPSTest) {
+#else
 TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) {
+#endif
   net::TestServer::HTTPSOptions https_options(
       net::TestServer::HTTPSOptions::CERT_EXPIRED);
   net::TestServer test_server(https_options, FilePath(kDocRoot));
@@ -610,7 +627,12 @@
   MessageLoop::current()->Run();
 }
 
+#if defined(OS_MACOSX)
+// SIGSEGV on Mac: http://crbug.com/60426
+TEST_F(URLFetcherCancelTest, DISABLED_ReleasesContext) {
+#else
 TEST_F(URLFetcherCancelTest, ReleasesContext) {
+#endif
   net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(kDocRoot));
   ASSERT_TRUE(test_server.Start());
 
diff --git a/chrome/common/net/url_request_context_getter.h b/chrome/common/net/url_request_context_getter.h
index 0c060e5..8b75a74 100644
--- a/chrome/common/net/url_request_context_getter.h
+++ b/chrome/common/net/url_request_context_getter.h
@@ -20,7 +20,7 @@
 
 struct URLRequestContextGetterTraits;
 
-// Interface for retrieving an URLRequestContext.
+// Interface for retrieving an net::URLRequestContext.
 class URLRequestContextGetter
     : public base::RefCountedThreadSafe<URLRequestContextGetter,
                                         URLRequestContextGetterTraits> {
@@ -31,7 +31,7 @@
   // implementations can override it.
   virtual net::CookieStore* GetCookieStore();
   // Returns a MessageLoopProxy corresponding to the thread on which the
-  // request IO happens (the thread on which the returned URLRequestContext
+  // request IO happens (the thread on which the returned net::URLRequestContext
   // may be used).
   virtual scoped_refptr<base::MessageLoopProxy>
       GetIOMessageLoopProxy() const = 0;
diff --git a/chrome/common/net/url_request_intercept_job.cc b/chrome/common/net/url_request_intercept_job.cc
index 641a8e8..89b0c55 100644
--- a/chrome/common/net/url_request_intercept_job.cc
+++ b/chrome/common/net/url_request_intercept_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -91,10 +91,11 @@
   if (rv == CPERR_IO_PENDING) {
     read_buffer_ = dest;
     read_buffer_size_ = dest_size;
-    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
   } else {
     // TODO(mpcomplete): better error code
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
+    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                     net::ERR_FAILED));
   }
 
   return false;
@@ -208,8 +209,8 @@
 
 void URLRequestInterceptJob::OnStartCompleted(int result) {
   if (result != CPERR_SUCCESS) {
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
-                                net::ERR_CONNECTION_FAILED));
+    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                     net::ERR_CONNECTION_FAILED));
     return;
   }
 
@@ -218,11 +219,12 @@
 
 void URLRequestInterceptJob::OnReadCompleted(int bytes_read) {
   if (bytes_read < 0) {
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
+    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                     net::ERR_FAILED));
     return;
   }
 
-  SetStatus(URLRequestStatus());  // clear the async flag
+  SetStatus(net::URLRequestStatus());  // clear the async flag
   NotifyReadComplete(bytes_read);
 }
 
diff --git a/chrome/common/net/x509_certificate_model.cc b/chrome/common/net/x509_certificate_model.cc
index 0ec2bff..2d4ffd0 100644
--- a/chrome/common/net/x509_certificate_model.cc
+++ b/chrome/common/net/x509_certificate_model.cc
@@ -6,9 +6,9 @@
 
 #include <unicode/uidna.h>
 
-#include "app/l10n_util.h"
 #include "base/utf_string_conversions.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace x509_certificate_model {
 
@@ -16,7 +16,7 @@
   // Convert the ASCII input to a string16 for ICU.
   string16 input16;
   input16.reserve(input.length());
-  std::copy(input.begin(), input.end(), std::back_inserter(input16));
+  input16.insert(input16.end(), input.begin(), input.end());
 
   string16 output16;
   output16.resize(input.length());
diff --git a/chrome/common/notification_service.cc b/chrome/common/notification_service.cc
index 4414cc6..06e4819 100644
--- a/chrome/common/notification_service.cc
+++ b/chrome/common/notification_service.cc
@@ -133,7 +133,7 @@
       // This may not be completely fixable -- see
       // http://code.google.com/p/chromium/issues/detail?id=11010 .
       VLOG(1) << observer_counts_[i] << " notification observer(s) leaked "
-                 " of notification type " << i;
+                 "of notification type " << i;
     }
   }
 #endif
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 8dbc2a3..0c39093 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -149,6 +149,12 @@
     // are provided.
     RESOURCE_RECEIVED_REDIRECT,
 
+    // A new window is created in response to a request from a renderer. The
+    // source will be a Source<TabContents> corresponding to the tab the
+    // request originates from.  Details in the form of a
+    // ViewHostMsg_CreateWindow_Params object are provided.
+    CREATING_NEW_WINDOW,
+
     // SSL ---------------------------------------------------------------------
 
     // Updating the SSL security indicators (the lock icon and such) proceeds
@@ -444,6 +450,35 @@
     // the RenderWidgetHost, the details are not used.
     RENDER_WIDGET_HOST_DESTROYED,
 
+    // Sent when the widget is about to paint. The source is the
+    // RenderWidgetHost, the details are not used.
+    RENDER_WIDGET_HOST_WILL_PAINT,
+
+    // Sent after the widget has painted. The source is the RenderWidgetHost,
+    // the details are not used.
+    RENDER_WIDGET_HOST_DID_PAINT,
+
+    // Indicates the RenderWidgetHost is about to destroy the backing store. The
+    // backing store will still be valid when this call is made. The source is
+    // the RenderWidgetHost, the details is the BackingStore.
+    RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE,
+
+    // Indicates that the RenderWidgetHost just updated the backing store. The
+    // source is the RenderWidgetHost, the details are not used.
+    RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
+
+    // This notifies the observer that a PaintAtSizeACK was received. The source
+    // is the RenderWidgetHost, the details are an instance of
+    // RenderWidgetHost::PaintAtSizeAckDetails.
+    RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
+
+    // This notifies the observer that a HandleInputEventACK was received. The
+    // source is the RenderWidgetHost, the details are the type of event
+    // received.
+    // Note: The RenderWidgetHost may be deallocated at this point.
+    // Used only in testing.
+    RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
+
     // Sent from ~RenderViewHost. The source is the TabContents.
     RENDER_VIEW_HOST_DELETED,
 
@@ -491,9 +526,10 @@
     // guaranteed to be valid after the notification.
     WEB_CACHE_STATS_OBSERVED,
 
-    // The focused element inside a page has changed.  The source is the render
-    // view host for the page.  The details are a Details<const bool> that
-    // indicates whether or not an editable node was focused.
+    // The focused element inside a page has changed.  The source is the
+    // TabContents containing the render view host for the page. The details is
+    // a Details<const bool> that indicates whether or not an editable node was
+    // focused.
     FOCUS_CHANGED_IN_PAGE,
 
     // Notification posted from ExecuteJavascriptInWebFrameNotifyResult. The
@@ -569,10 +605,6 @@
     // interception.  No details are expected.
     CHROME_PLUGIN_UNLOADED,
 
-    // This is sent in the RenderView when previously blocked plugins on a page
-    // should be loaded. The source is the RenderView. No details are expected.
-    SHOULD_LOAD_PLUGINS,
-
     // Sent by the PluginUpdater when there is a change of plugin
     // enable/disable status.
     PLUGIN_ENABLE_STATUS_CHANGED,
@@ -752,19 +784,10 @@
 
     // Autocomplete ------------------------------------------------------------
 
-    // Sent by the autocomplete controller at least once per query, each time
-    // new matches are available, subject to rate-limiting/coalescing to reduce
-    // the number of updates.  The details hold the AutocompleteResult that
-    // observers should use if they want to see the updated matches.
+    // Sent by the autocomplete controller each time the result set updates.
+    // The details is a boolean indicating if the default match has changed.
     AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
 
-    // Sent by the autocomplete controller immediately after synchronous matches
-    // become available, and thereafter at the same time that
-    // AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED is sent.  The details hold the
-    // AutocompleteResult that observers should use if they want to see the
-    // up-to-date matches.
-    AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED,
-
     // This is sent when an item of the Omnibox popup is selected. The source
     // is the profile.
     OMNIBOX_OPENED_URL,
@@ -789,8 +812,9 @@
 
     // Shutdown ----------------------------------------------------------------
 
-    // Sent on the browser IO thread when an URLRequestContext is released by
-    // its owning Profile.  The source is a pointer to the URLRequestContext.
+    // Sent on the browser IO thread when an net::URLRequestContext is released
+    // by its owning Profile.  The source is a pointer to the
+    // net::URLRequestContext.
     URL_REQUEST_CONTEXT_RELEASED,
 
     // Sent when WM_ENDSESSION has been received, after the browsers have been
@@ -1136,20 +1160,6 @@
     // session data.
     FOREIGN_SESSION_DISABLED,
 
-    // The syncer requires a passphrase to decrypt sensitive updates. This
-    // notification is sent when the first sensitive data type is setup by the
-    // user as well as anytime any the passphrase is changed in another synced
-    // client.  The source is the SyncBackendHost wanting a passphrase.  The
-    // details are a boolean: true if the passphrase is required for decryption,
-    // false if only required for encryption.
-    SYNC_PASSPHRASE_REQUIRED,
-
-    // Sent when the passphrase provided by the user is accepted. After this
-    // notification is sent, updates to sensitive nodes are encrypted using the
-    // accepted passphrase.  The source is the SyncBackendHost that accepted
-    // the passphrase.  No details.
-    SYNC_PASSPHRASE_ACCEPTED,
-
     // Sent when the set of data types that should be synced has been modified
     // externally (eg. by the dom_ui options screen).
     // The source is the Profile, there are no details.
@@ -1294,6 +1304,9 @@
     // |webkit_glue::PasswordForm|s that were affected.
     LOGINS_CHANGED,
 
+    // Sent when the applications in the NTP app launcher have been reordered.
+    EXTENSION_LAUNCHER_REORDERED,
+
     // Count (must be last) ----------------------------------------------------
     // Used to determine the number of notification types.  Not valid as
     // a type parameter when registering for or posting notifications.
diff --git a/chrome/common/pepper_messages.cc b/chrome/common/pepper_messages.cc
new file mode 100644
index 0000000..60dad0d
--- /dev/null
+++ b/chrome/common/pepper_messages.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/common/common_param_traits.h"
+#include "ppapi/c/private/ppb_flash.h"
+
+#define IPC_MESSAGE_IMPL
+#include "chrome/common/pepper_messages.h"
+
+namespace IPC {
+
+void ParamTraits<PP_Flash_NetAddress>::Write(Message* m, const param_type& p) {
+  WriteParam(m, p.size);
+  m->WriteBytes(p.data, static_cast<int>(p.size));
+}
+
+bool ParamTraits<PP_Flash_NetAddress>::Read(const Message* m,
+                                            void** iter,
+                                            param_type* p) {
+  uint16 size;
+  if (!ReadParam(m, iter, &size))
+    return false;
+  if (size > sizeof(p->data))
+    return false;
+  p->size = size;
+
+  const char* data;
+  if (!m->ReadBytes(iter, &data, size))
+    return false;
+  memcpy(p->data, data, size);
+  return true;
+}
+
+void ParamTraits<PP_Flash_NetAddress>::Log(const param_type& p,
+                                           std::string* l) {
+  l->append("<PP_Flash_NetAddress (");
+  LogParam(p.size, l);
+  l->append(" bytes)>");
+}
+
+}  // namespace IPC
diff --git a/chrome/common/pepper_messages.h b/chrome/common/pepper_messages.h
new file mode 100644
index 0000000..60bf768
--- /dev/null
+++ b/chrome/common/pepper_messages.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_PEPPER_MESSAGES_H_
+#define CHROME_COMMON_PEPPER_MESSAGES_H_
+#pragma once
+
+#include "chrome/common/common_param_traits.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_platform_file.h"
+
+#define IPC_MESSAGE_START PepperMsgStart
+
+struct PP_Flash_NetAddress;
+
+namespace IPC {
+
+template <>
+struct ParamTraits<PP_Flash_NetAddress> {
+  typedef PP_Flash_NetAddress param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
+}  // namespace IPC
+
+// Pepper (non-file-system) messages sent from the browser to the renderer.
+
+// The response to PepperMsg_ConnectTcp(Address).
+IPC_MESSAGE_ROUTED4(PepperMsg_ConnectTcpACK,
+                    int /* request_id */,
+                    IPC::PlatformFileForTransit /* socket */,
+                    PP_Flash_NetAddress /* local_addr */,
+                    PP_Flash_NetAddress /* remote_addr */)
+
+// Pepper (non-file-system) messages sent from the renderer to the browser.
+
+IPC_MESSAGE_CONTROL4(PepperMsg_ConnectTcp,
+                     int /* routing_id */,
+                     int /* request_id */,
+                     std::string /* host */,
+                     uint16 /* port */)
+
+IPC_MESSAGE_CONTROL3(PepperMsg_ConnectTcpAddress,
+                     int /* routing_id */,
+                     int /* request_id */,
+                     PP_Flash_NetAddress /* addr */)
+
+#endif  // CHROME_COMMON_PEPPER_MESSAGES_H_
diff --git a/chrome/common/pepper_plugin_registry.cc b/chrome/common/pepper_plugin_registry.cc
index 343a646..891e75e 100644
--- a/chrome/common/pepper_plugin_registry.cc
+++ b/chrome/common/pepper_plugin_registry.cc
@@ -15,68 +15,91 @@
 #include "chrome/common/chrome_switches.h"
 #include "remoting/client/plugin/pepper_entrypoints.h"
 
-const char* PepperPluginRegistry::kPDFPluginName = "Chrome PDF Viewer";
-const char* PepperPluginRegistry::kPDFPluginMimeType = "application/pdf";
-const char* PepperPluginRegistry::kPDFPluginExtension = "pdf";
-const char* PepperPluginRegistry::kPDFPluginDescription =
-    "Portable Document Format";
+namespace {
 
-const char* PepperPluginRegistry::kNaClPluginName = "Chrome NaCl";
-const char* PepperPluginRegistry::kNaClPluginMimeType =
-    "application/x-ppapi-nacl-srpc";
-const char* PepperPluginRegistry::kNaClPluginExtension = "nexe";
-const char* PepperPluginRegistry::kNaClPluginDescription =
-    "Native Client Executable";
+const char* kPDFPluginName = "Chrome PDF Viewer";
+const char* kPDFPluginMimeType = "application/pdf";
+const char* kPDFPluginExtension = "pdf";
+const char* kPDFPluginDescription = "Portable Document Format";
 
+const char* kNaClPluginName = "Chrome NaCl";
+const char* kNaClPluginMimeType = "application/x-nacl";
+const char* kNaClPluginExtension = "nexe";
+const char* kNaClPluginDescription = "Native Client Executable";
 
-PepperPluginInfo::PepperPluginInfo()
-    : is_internal(false),
-      is_out_of_process(false) {
-}
+#if defined(ENABLE_REMOTING)
+const char* kRemotingPluginMimeType = "pepper-application/x-chromoting";
+#endif
 
-PepperPluginInfo::~PepperPluginInfo() {}
+// Appends the known built-in plugins to the given vector. Some built-in
+// plugins are "internal" which means they are compiled into the Chrome binary,
+// and some are extra shared libraries distributed with the browser (these are
+// not marked internal, aside from being automatically registered, they're just
+// regular plugins).
+void ComputeBuiltInPlugins(std::vector<PepperPluginInfo>* plugins) {
+  // PDF.
+  //
+  // Once we're sandboxed, we can't know if the PDF plugin is available or not;
+  // but (on Linux) this function is always called once before we're sandboxed.
+  // So the first time through test if the file is available and then skip the
+  // check on subsequent calls if yes.
+  static bool skip_pdf_file_check = false;
+  FilePath path;
+  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) {
+    if (skip_pdf_file_check || file_util::PathExists(path)) {
+      PepperPluginInfo pdf;
+      pdf.path = path;
+      pdf.name = kPDFPluginName;
+      pdf.mime_types.push_back(kPDFPluginMimeType);
+      pdf.file_extensions = kPDFPluginExtension;
+      pdf.type_descriptions = kPDFPluginDescription;
+      plugins->push_back(pdf);
 
-// static
-PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
-  static PepperPluginRegistry* registry = NULL;
-  // This object leaks.  It is a temporary hack to work around a crash.
-  // http://code.google.com/p/chromium/issues/detail?id=63234
-  if (!registry)
-    registry = new PepperPluginRegistry;
-  return registry;
-}
-
-// static
-void PepperPluginRegistry::GetList(std::vector<PepperPluginInfo>* plugins) {
-  InternalPluginInfoList internal_plugin_info;
-  GetInternalPluginInfo(&internal_plugin_info);
-  for (InternalPluginInfoList::const_iterator it =
-         internal_plugin_info.begin();
-       it != internal_plugin_info.end();
-       ++it) {
-    plugins->push_back(*it);
-  }
-
-  GetPluginInfoFromSwitch(plugins);
-  GetExtraPlugins(plugins);
-}
-
-// static
-void PepperPluginRegistry::PreloadModules() {
-  std::vector<PepperPluginInfo> plugins;
-  GetList(&plugins);
-  for (size_t i = 0; i < plugins.size(); ++i) {
-    if (!plugins[i].is_internal && !plugins[i].is_out_of_process) {
-      base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path);
-      LOG_IF(WARNING, !library) << "Unable to load plugin "
-                                << plugins[i].path.value();
+      skip_pdf_file_check = true;
     }
   }
+
+  // Native client.
+  //
+  // Verify that we enable nacl on the command line. The name of the switch
+  // varies between the browser and renderer process.
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl) &&
+      PathService::Get(chrome::FILE_NACL_PLUGIN, &path) &&
+      file_util::PathExists(path)) {
+    PepperPluginInfo nacl;
+    nacl.path = path;
+    nacl.name = kNaClPluginName;
+    nacl.mime_types.push_back(kNaClPluginMimeType);
+
+    // TODO(bbudge) Remove this mime type after NaCl tree has been updated.
+    const char* kNaClPluginOldMimeType = "application/x-ppapi-nacl-srpc";
+    nacl.mime_types.push_back(kNaClPluginOldMimeType);
+
+    nacl.file_extensions = kNaClPluginExtension;
+    nacl.type_descriptions = kNaClPluginDescription;
+    plugins->push_back(nacl);
+  }
+
+  // Remoting.
+#if defined(ENABLE_REMOTING)
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableRemoting)) {
+    PepperPluginInfo info;
+    info.is_internal = true;
+    info.path = FilePath(FILE_PATH_LITERAL("internal-chromoting"));
+    info.mime_types.push_back(kRemotingPluginMimeType);
+    info.internal_entry_points.get_interface = remoting::PPP_GetInterface;
+    info.internal_entry_points.initialize_module =
+        remoting::PPP_InitializeModule;
+    info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule;
+
+    plugins->push_back(info);
+  }
+#endif
 }
 
-// static
-void PepperPluginRegistry::GetPluginInfoFromSwitch(
-    std::vector<PepperPluginInfo>* plugins) {
+// Appends any plugins from the command line to the given vector.
+void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
   const std::string value =
       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kRegisterPepperPlugins);
@@ -116,8 +139,10 @@
 #endif
     if (name_parts.size() > 1)
       plugin.name = name_parts[1];
-    if (name_parts.size() > 2)
+    if (name_parts.size() > 2) {
+      plugin.description = name_parts[2];
       plugin.type_descriptions = name_parts[2];
+    }
     for (size_t j = 1; j < parts.size(); ++j)
       plugin.mime_types.push_back(parts[j]);
 
@@ -125,102 +150,56 @@
   }
 }
 
-// static
-void PepperPluginRegistry::GetExtraPlugins(
-    std::vector<PepperPluginInfo>* plugins) {
-  // Once we're sandboxed, we can't know if the PDF plugin is
-  // available or not; but (on Linux) this function is always called
-  // once before we're sandboxed.  So the first time through test if
-  // the file is available and then skip the check on subsequent calls
-  // if yes.
-  static bool skip_pdf_file_check = false;
-  FilePath path;
-  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) {
-    if (skip_pdf_file_check || file_util::PathExists(path)) {
-      PepperPluginInfo pdf;
-      pdf.path = path;
-      pdf.name = kPDFPluginName;
-      pdf.mime_types.push_back(kPDFPluginMimeType);
-      pdf.file_extensions = kPDFPluginExtension;
-      pdf.type_descriptions = kPDFPluginDescription;
-      plugins->push_back(pdf);
+}  // namespace
 
-      skip_pdf_file_check = true;
-    }
-  }
+const char* PepperPluginRegistry::kPDFPluginName = ::kPDFPluginName;
 
-  // Verify that we enable nacl on the command line.  The name of the
-  // switch varies between the browser and renderer process.
-  bool enable_nacl =
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl) ||
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kInternalNaCl);
-
-  static bool skip_nacl_file_check = false;
-  if (enable_nacl && PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) {
-    if (skip_nacl_file_check || file_util::PathExists(path)) {
-      PepperPluginInfo nacl;
-      nacl.path = path;
-      nacl.name = kNaClPluginName;
-      nacl.mime_types.push_back(kNaClPluginMimeType);
-      nacl.file_extensions = kNaClPluginExtension;
-      nacl.type_descriptions = kNaClPluginDescription;
-      plugins->push_back(nacl);
-
-      skip_nacl_file_check = true;
-    }
-  }
+PepperPluginInfo::PepperPluginInfo()
+    : is_internal(false),
+      is_out_of_process(false) {
 }
 
-PepperPluginRegistry::InternalPluginInfo::InternalPluginInfo() {
-  is_internal = true;
+PepperPluginInfo::~PepperPluginInfo() {}
+
+// static
+PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
+  static PepperPluginRegistry* registry = NULL;
+  // This object leaks.  It is a temporary hack to work around a crash.
+  // http://code.google.com/p/chromium/issues/detail?id=63234
+  if (!registry)
+    registry = new PepperPluginRegistry;
+  return registry;
 }
 
 // static
-void PepperPluginRegistry::GetInternalPluginInfo(
-    InternalPluginInfoList* plugin_info) {
-  // Currently, to centralize the internal plugin registration logic, we
-  // hardcode the list of plugins, mimetypes, and registration information
-  // in this function.  This is gross, but because the GetList() function is
-  // called from both the renderer and browser the other option is to force a
-  // special register function for each plugin to be called by both
-  // RendererMain() and BrowserMain().  This seemed like the better tradeoff.
-  //
-  // TODO(ajwong): Think up a better way to maintain the plugin registration
-  // information. Perhaps by construction of a singly linked list of
-  // plugin initializers that is built with static initializers?
-
-#if defined(ENABLE_REMOTING)
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableRemoting)) {
-    InternalPluginInfo info;
-    // Add the chromoting plugin.
-    DCHECK(info.is_internal);
-    info.path =
-        FilePath(FILE_PATH_LITERAL("internal-chromoting"));
-    info.mime_types.push_back("pepper-application/x-chromoting");
-    info.entry_points.get_interface = remoting::PPP_GetInterface;
-    info.entry_points.initialize_module = remoting::PPP_InitializeModule;
-    info.entry_points.shutdown_module = remoting::PPP_ShutdownModule;
-
-    plugin_info->push_back(info);
-  }
-#endif
+void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) {
+  ComputeBuiltInPlugins(plugins);
+  ComputePluginsFromCommandLine(plugins);
 }
 
-bool PepperPluginRegistry::RunOutOfProcessForPlugin(
-    const FilePath& path) const {
-  // TODO(brettw) don't recompute this every time. But since this Pepper
-  // switch is only for development, it's OK for now.
+// static
+void PepperPluginRegistry::PreloadModules() {
   std::vector<PepperPluginInfo> plugins;
-  GetList(&plugins);
+  ComputeList(&plugins);
   for (size_t i = 0; i < plugins.size(); ++i) {
-    if (path == plugins[i].path)
-      return plugins[i].is_out_of_process;
+    if (!plugins[i].is_internal && !plugins[i].is_out_of_process) {
+      base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path);
+      LOG_IF(WARNING, !library) << "Unable to load plugin "
+                                << plugins[i].path.value();
+    }
   }
-  return false;
 }
 
-webkit::ppapi::PluginModule* PepperPluginRegistry::GetModule(
+const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
+    const FilePath& path) const {
+  for (size_t i = 0; i < plugin_list_.size(); ++i) {
+    if (path == plugin_list_[i].path)
+      return &plugin_list_[i];
+  }
+  return NULL;
+}
+
+webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule(
     const FilePath& path) {
   NonOwningModuleMap::iterator it = live_modules_.find(path);
   if (it == live_modules_.end())
@@ -258,44 +237,32 @@
 }
 
 PepperPluginRegistry::PepperPluginRegistry() {
-  InternalPluginInfoList internal_plugin_info;
-  GetInternalPluginInfo(&internal_plugin_info);
+  ComputeList(&plugin_list_);
 
-  // Register modules for these suckers.
-  for (InternalPluginInfoList::const_iterator it =
-         internal_plugin_info.begin();
-       it != internal_plugin_info.end();
-       ++it) {
-    const FilePath& path = it->path;
-    scoped_refptr<webkit::ppapi::PluginModule> module(
-        new webkit::ppapi::PluginModule(this));
-    if (!module->InitAsInternalPlugin(it->entry_points)) {
-      DLOG(ERROR) << "Failed to load pepper module: " << path.value();
-      continue;
+  // Note that in each case, AddLiveModule must be called before completing
+  // initialization. If we bail out (in the continue clauses) before saving
+  // the initialized module, it will still try to unregister itself in its
+  // destructor.
+  for (size_t i = 0; i < plugin_list_.size(); i++) {
+    const PepperPluginInfo& current = plugin_list_[i];
+    if (current.is_out_of_process)
+      continue;  // Out of process plugins need no special pre-initialization.
+
+    scoped_refptr<webkit::ppapi::PluginModule> module =
+        new webkit::ppapi::PluginModule(current.name, this);
+    AddLiveModule(current.path, module);
+    if (current.is_internal) {
+      if (!module->InitAsInternalPlugin(current.internal_entry_points)) {
+        DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
+        continue;
+      }
+    } else {
+      // Preload all external plugins we're not running out of process.
+      if (!module->InitAsLibrary(current.path)) {
+        DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
+        continue;
+      }
     }
-    module->set_name(it->name);
-    preloaded_modules_[path] = module;
-    AddLiveModule(path, module);
-  }
-
-  // Add the modules specified on the command line last so that they can
-  // override the internal plugins.
-  std::vector<PepperPluginInfo> plugins;
-  GetPluginInfoFromSwitch(&plugins);
-  GetExtraPlugins(&plugins);
-  for (size_t i = 0; i < plugins.size(); ++i) {
-    if (plugins[i].is_out_of_process)
-      continue;  // Only preload in-process plugins.
-
-    const FilePath& path = plugins[i].path;
-    scoped_refptr<webkit::ppapi::PluginModule> module(
-        new webkit::ppapi::PluginModule(this));
-    if (!module->InitAsLibrary(path)) {
-      DLOG(ERROR) << "Failed to load pepper module: " << path.value();
-      continue;
-    }
-    module->set_name(plugins[i].name);
-    preloaded_modules_[path] = module;
-    AddLiveModule(path, module);
+    preloaded_modules_[current.path] = module;
   }
 }
diff --git a/chrome/common/pepper_plugin_registry.h b/chrome/common/pepper_plugin_registry.h
index 0dd8b15..18233ea 100644
--- a/chrome/common/pepper_plugin_registry.h
+++ b/chrome/common/pepper_plugin_registry.h
@@ -19,6 +19,8 @@
   ~PepperPluginInfo();
 
   // Indicates internal plugins for which there's not actually a library.
+  // These plugins are implemented in the Chrome binary using a separate set
+  // of entry points (see internal_entry_points below).
   // Defaults to false.
   bool is_internal;
 
@@ -31,6 +33,10 @@
   std::string description;
   std::string file_extensions;
   std::string type_descriptions;
+
+  // When is_internal is set, this contains the function pointers to the
+  // entry points for the internal plugins.
+  webkit::ppapi::PluginModule::EntryPoints internal_entry_points;
 };
 
 // This class holds references to all of the known pepper plugin modules.
@@ -44,35 +50,32 @@
   ~PepperPluginRegistry();
 
   static const char* kPDFPluginName;
-  static const char* kPDFPluginMimeType;
-  static const char* kPDFPluginExtension;
-  static const char* kPDFPluginDescription;
-
-  static const char* kNaClPluginName;
-  static const char* kNaClPluginMimeType;
-  static const char* kNaClPluginExtension;
-  static const char* kNaClPluginDescription;
 
   static PepperPluginRegistry* GetInstance();
 
-  // Returns the list of known pepper plugins.  This method is static so that
-  // it can be used by the browser process, which has no need to load the
-  // pepper plugin modules.
-  static void GetList(std::vector<PepperPluginInfo>* plugins);
+  // Computes the list of known pepper plugins.
+  //
+  // This method is static so that it can be used by the browser process, which
+  // has no need to load the pepper plugin modules. It will re-compute the
+  // plugin list every time it is called. Generally, code in the registry should
+  // be using the cached plugin_list_ instead.
+  static void ComputeList(std::vector<PepperPluginInfo>* plugins);
 
   // Loads the (native) libraries but does not initialize them (i.e., does not
   // call PPP_InitializeModule). This is needed by the zygote on Linux to get
   // access to the plugins before entering the sandbox.
   static void PreloadModules();
 
-  // Returns true if the given plugin is a pepper plugin that should be run
-  // out of process.
-  bool RunOutOfProcessForPlugin(const FilePath& path) const;
+  // Retrieves the information associated with the given plugin path. The
+  // return value will be NULL if there is no such plugin.
+  //
+  // The returned pointer is owned by the PluginRegistry.
+  const PepperPluginInfo* GetInfoForPlugin(const FilePath& path) const;
 
   // Returns an existing loaded module for the given path. It will search for
   // both preloaded in-process or currently active out-of-process plugins
   // matching the given name. Returns NULL if the plugin hasn't been loaded.
-  webkit::ppapi::PluginModule* GetModule(const FilePath& path);
+  webkit::ppapi::PluginModule* GetLiveModule(const FilePath& path);
 
   // Notifies the registry that a new non-preloaded module has been created.
   // This is normally called for out-of-process plugins. Once this is called,
@@ -85,18 +88,13 @@
       webkit::ppapi::PluginModule* destroyed_module);
 
  private:
-  static void GetPluginInfoFromSwitch(std::vector<PepperPluginInfo>* plugins);
-  static void GetExtraPlugins(std::vector<PepperPluginInfo>* plugins);
-
-  struct InternalPluginInfo : public PepperPluginInfo {
-    InternalPluginInfo();  // Sets |is_internal|.
-    webkit::ppapi::PluginModule::EntryPoints entry_points;
-  };
-  typedef std::vector<InternalPluginInfo> InternalPluginInfoList;
-  static void GetInternalPluginInfo(InternalPluginInfoList* plugin_info);
-
   PepperPluginRegistry();
 
+  // All known pepper plugins.
+  std::vector<PepperPluginInfo> plugin_list_;
+
+  // Plugins that have been preloaded so they can be executed in-process in
+  // the renderer (the sandbox prevents on-demand loading).
   typedef std::map<FilePath, scoped_refptr<webkit::ppapi::PluginModule> >
       OwningModuleMap;
   OwningModuleMap preloaded_modules_;
diff --git a/chrome/common/persistent_pref_store.h b/chrome/common/persistent_pref_store.h
index 9e2fb0a..e0eb8dc 100644
--- a/chrome/common/persistent_pref_store.h
+++ b/chrome/common/persistent_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,7 +11,7 @@
 #include <chrome/common/pref_store.h>
 
 // This interface is complementary to the PrefStore interface, declaring
-// additional functionatliy that adds support for setting values and persisting
+// additional functionality that adds support for setting values and persisting
 // the data to some backing store.
 class PersistentPrefStore : public PrefStore {
  public:
diff --git a/chrome/common/plugin_messages.cc b/chrome/common/plugin_messages.cc
index d9117ff..26d2aec 100644
--- a/chrome/common/plugin_messages.cc
+++ b/chrome/common/plugin_messages.cc
@@ -57,8 +57,8 @@
 PluginMsg_UpdateGeometry_Param::PluginMsg_UpdateGeometry_Param()
     : transparent(false),
 #if !defined(OS_MACOSX)
-      windowless_buffer(NULL),
-      background_buffer(NULL)
+      windowless_buffer(TransportDIB::DefaultHandleValue()),
+      background_buffer(TransportDIB::DefaultHandleValue())
 #else
       ack_key(-1)
 #endif  // !defined(OS_MACOSX)
diff --git a/chrome/common/plugin_messages.h b/chrome/common/plugin_messages.h
index 4753c9d..721312d 100644
--- a/chrome/common/plugin_messages.h
+++ b/chrome/common/plugin_messages.h
@@ -18,13 +18,13 @@
 #include "base/string_number_conversions.h"
 #include "chrome/common/common_param_traits.h"
 #include "chrome/common/webkit_param_traits.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/rect.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_utils.h"
 #include "third_party/npapi/bindings/npapi.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
 #include "webkit/glue/npruntime_util.h"
 
 // Name prefix of the event handle when a message box is displayed.
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index 54ba2eb..98ed543 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -4,8 +4,8 @@
 
 #include "base/shared_memory.h"
 #include "build/build_config.h"
-#include "gfx/native_widget_types.h"
 #include "ipc/ipc_message_macros.h"
+#include "ui/gfx/native_widget_types.h"
 #include "webkit/glue/webcursor.h"
 
 #if defined(OS_POSIX)
@@ -234,7 +234,7 @@
                     gfx::Rect /* window_frame */,
                     gfx::Rect /* view_frame */)
 
-IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionConfirmed,
+IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionCompleted,
                     string16 /* text */)
 #endif
 
@@ -305,8 +305,8 @@
 #endif
 
 IPC_MESSAGE_CONTROL3(PluginMsg_ClearSiteData,
+                     std::string, /* site */
                      uint64, /* flags */
-                     std::string, /* domain */
                      base::Time /* begin_time */)
 
 
@@ -403,8 +403,10 @@
 IPC_MESSAGE_ROUTED1(PluginHostMsg_UpdateGeometry_ACK,
                     int /* ack_key */)
 
-IPC_MESSAGE_ROUTED1(PluginHostMsg_SetImeEnabled,
-                    bool /* enabled */)
+IPC_MESSAGE_ROUTED1(PluginHostMsg_FocusChanged,
+                    bool /* focused */)
+
+IPC_MESSAGE_ROUTED0(PluginHostMsg_StartIme)
 
 // This message, used in Mac OS X 10.5 and earlier, is sent from the plug-in
 // process to the renderer process to indicate that the plug-in allocated a
diff --git a/chrome/common/policy_constants.cc b/chrome/common/policy_constants.cc
deleted file mode 100644
index 8ed8934..0000000
--- a/chrome/common/policy_constants.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/policy_constants.h"
-
-namespace policy {
-
-#if defined(OS_WIN)
-#if defined(GOOGLE_CHROME_BUILD)
-const wchar_t kRegistrySubKey[] = L"SOFTWARE\\Policies\\Google\\Chrome";
-#else
-const wchar_t kRegistrySubKey[] = L"SOFTWARE\\Policies\\Chromium";
-#endif
-#endif
-
-namespace key {
-
-const char kHomepageLocation[] = "HomepageLocation";
-const char kHomepageIsNewTabPage[] = "HomepageIsNewTabPage";
-const char kRestoreOnStartup[] = "RestoreOnStartup";
-const char kURLsToRestoreOnStartup[] = "RestoreOnStartupURLs";
-const char kDefaultSearchProviderEnabled[] = "DefaultSearchProviderEnabled";
-const char kDefaultSearchProviderName[] = "DefaultSearchProviderName";
-const char kDefaultSearchProviderKeyword[] = "DefaultSearchProviderKeyword";
-const char kDefaultSearchProviderSearchURL[] =
-    "DefaultSearchProviderSearchURL";
-const char kDefaultSearchProviderSuggestURL[] =
-    "DefaultSearchProviderSuggestURL";
-const char kDefaultSearchProviderIconURL[] =
-    "DefaultSearchProviderIconURL";
-const char kDefaultSearchProviderEncodings[] =
-    "DefaultSearchProviderEncodings";
-const char kDisableSpdy[] = "DisableSpdy";
-// We consider the name ProxyMode more apt than ProxyServerMode but could
-// not change it after publishing that name for the win registry and policy
-// config files.
-const char kProxyMode[] = "ProxyServerMode";
-const char kProxyServer[] = "ProxyServer";
-const char kProxyPacUrl[] = "ProxyPacUrl";
-const char kProxyBypassList[] = "ProxyBypassList";
-const char kAlternateErrorPagesEnabled[] = "AlternateErrorPagesEnabled";
-const char kSearchSuggestEnabled[] = "SearchSuggestEnabled";
-const char kDnsPrefetchingEnabled[] = "DnsPrefetchingEnabled";
-const char kSafeBrowsingEnabled[] = "SafeBrowsingEnabled";
-const char kMetricsReportingEnabled[] = "MetricsReportingEnabled";
-const char kPasswordManagerEnabled[] = "PasswordManagerEnabled";
-const char kPasswordManagerAllowShowPasswords[] =
-    "PasswordManagerAllowShowPasswords";
-const char kDisabledPlugins[] = "DisabledPlugins";
-const char kAutoFillEnabled[] = "AutoFillEnabled";
-const char kApplicationLocaleValue[] = "ApplicationLocaleValue";
-const char kSyncDisabled[] = "SyncDisabled";
-const char kExtensionInstallAllowList[] = "ExtensionInstallWhitelist";
-const char kExtensionInstallDenyList[] = "ExtensionInstallBlacklist";
-const char kExtensionInstallForceList[] = "ExtensionInstallForcelist";
-const char kShowHomeButton[] = "ShowHomeButton";
-const char kPrintingEnabled[] = "PrintingEnabled";
-const char kJavascriptEnabled[] = "JavascriptEnabled";
-const char kSavingBrowserHistoryDisabled[] = "SavingBrowserHistoryDisabled";
-const char kDeveloperToolsDisabled[] = "DeveloperToolsDisabled";
-const char kBlockThirdPartyCookies[] = "BlockThirdPartyCookies";
-const char kDefaultCookiesSetting[] = "DefaultCookiesSetting";
-const char kDefaultImagesSetting[] = "DefaultImagesSetting";
-const char kDefaultJavaScriptSetting[] = "DefaultJavaScriptSetting";
-const char kDefaultPluginsSetting[] = "DefaultPluginsSetting";
-const char kDefaultPopupsSetting[] = "DefaultPopupsSetting";
-const char kDefaultNotificationSetting[] = "DefaultNotificationSetting";
-const char kDefaultGeolocationSetting[] = "DefaultGeolocationSetting";
-const char kAuthSchemes[] = "AuthSchemes";
-const char kDisableAuthNegotiateCnameLookup[] =
-    "DisableAuthNegotiateCnameLookup";
-const char kEnableAuthNegotiatePort[] = "EnableAuthNegotiatePort";
-const char kAuthServerWhitelist[] = "AuthServerWhitelist";
-const char kAuthNegotiateDelegateWhitelist[] = "AuthNegotiateDelegateWhitelist";
-const char kGSSAPILibraryName[] = "GSSAPILibraryName";
-const char kDisable3DAPIs[] = "Disable3DAPIs";
-
-// Chrome Frame specific policy constants
-const char kChromeFrameRendererSettings[] = "ChromeFrameRendererSettings";
-const char kRenderInChromeFrameList[] = "RenderInChromeFrameList";
-const char kRenderInHostList[] = "RenderInHostList";
-const char kChromeFrameContentTypes[] = "ChromeFrameContentTypes";
-
-#if defined(OS_CHROMEOS)
-// ChromeOS policy constants
-const char kChromeOsLockOnIdleSuspend[] = "ChromeOsLockOnIdleSuspend";
-#endif
-
-}  // namespace key
-
-}  // namespace policy
diff --git a/chrome/common/policy_constants.h b/chrome/common/policy_constants.h
deleted file mode 100644
index 279197e..0000000
--- a/chrome/common/policy_constants.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_POLICY_CONSTANTS_H_
-#define CHROME_COMMON_POLICY_CONSTANTS_H_
-#pragma once
-
-#include "build/build_config.h"
-
-namespace policy {
-
-#if defined(OS_WIN)
-// The windows registry path we read the policy configuration from.
-extern const wchar_t kRegistrySubKey[];
-#endif
-
-// Key names for the policy settings.
-namespace key {
-
-extern const char kHomepageLocation[];
-extern const char kHomepageIsNewTabPage[];
-extern const char kRestoreOnStartup[];
-extern const char kURLsToRestoreOnStartup[];
-extern const char kDefaultSearchProviderEnabled[];
-extern const char kDefaultSearchProviderName[];
-extern const char kDefaultSearchProviderKeyword[];
-extern const char kDefaultSearchProviderSearchURL[];
-extern const char kDefaultSearchProviderSuggestURL[];
-extern const char kDefaultSearchProviderIconURL[];
-extern const char kDefaultSearchProviderEncodings[];
-extern const char kDisableSpdy[];
-extern const char kProxyMode[];
-extern const char kProxyServer[];
-extern const char kProxyPacUrl[];
-extern const char kProxyBypassList[];
-extern const char kAlternateErrorPagesEnabled[];
-extern const char kSearchSuggestEnabled[];
-extern const char kDnsPrefetchingEnabled[];
-extern const char kSafeBrowsingEnabled[];
-extern const char kMetricsReportingEnabled[];
-extern const char kPasswordManagerEnabled[];
-extern const char kPasswordManagerAllowShowPasswords[];
-extern const char kDisabledPlugins[];
-extern const char kAutoFillEnabled[];
-extern const char kApplicationLocaleValue[];
-extern const char kSyncDisabled[];
-extern const char kExtensionInstallAllowList[];
-extern const char kExtensionInstallDenyList[];
-extern const char kExtensionInstallForceList[];
-extern const char kShowHomeButton[];
-extern const char kPrintingEnabled[];
-extern const char kJavascriptEnabled[];
-extern const char kSavingBrowserHistoryDisabled[];
-extern const char kDeveloperToolsDisabled[];
-extern const char kBlockThirdPartyCookies[];
-extern const char kDefaultCookiesSetting[];
-extern const char kDefaultImagesSetting[];
-extern const char kDefaultJavaScriptSetting[];
-extern const char kDefaultPluginsSetting[];
-extern const char kDefaultPopupsSetting[];
-extern const char kDefaultNotificationSetting[];
-extern const char kDefaultGeolocationSetting[];
-extern const char kAuthSchemes[];
-extern const char kDisableAuthNegotiateCnameLookup[];
-extern const char kEnableAuthNegotiatePort[];
-extern const char kAuthServerWhitelist[];
-extern const char kAuthNegotiateDelegateWhitelist[];
-extern const char kGSSAPILibraryName[];
-extern const char kDisable3DAPIs[];
-
-// Chrome Frame specific policy constants
-extern const char kChromeFrameRendererSettings[];
-extern const char kRenderInChromeFrameList[];
-extern const char kRenderInHostList[];
-extern const char kChromeFrameContentTypes[];
-
-#if defined(OS_CHROMEOS)
-// ChromeOS policy constants
-extern const char kChromeOsLockOnIdleSuspend[];
-#endif
-
-}  // namespace key
-
-}  // namespace policy
-
-#endif  // CHROME_COMMON_POLICY_CONSTANTS_H_
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 502afd9..f3ddcc3 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -46,8 +46,38 @@
 // while user's profile determines his personal locale preference.
 const char kApplicationLocale[] = "intl.app_locale";
 #if defined(OS_CHROMEOS)
-// Non-syncable item.  Used for two-step initialization of locale in ChromeOS
-// because synchronization of kApplicationLocale is not instant.
+// Locale preference of device' owner.  ChromeOS device appears in this locale
+// after startup/wakeup/signout.
+const char kOwnerLocale[] = "intl.owner_locale";
+// Locale accepted by user.  Non-syncable.
+// Used to determine whether we need to show Locale Change notification.
+const char kApplicationLocaleAccepted[] = "intl.app_locale_accepted";
+// Non-syncable item.
+// It is used in two distinct ways.
+// (1) Used for two-step initialization of locale in ChromeOS
+//     because synchronization of kApplicationLocale is not instant.
+// (2) Used to detect locale change.  Locale change is detected by
+//     LocaleChangeGuard in case values of kApplicationLocaleBackup and
+//     kApplicationLocale are both non-empty and differ.
+// Following is a table showing how state of those prefs may change upon
+// common real-life use cases:
+//                                  AppLocale Backup Accepted
+// Initial login                       -        A       -
+// Sync                                B        A       -
+// Accept (B)                          B        B       B
+// -----------------------------------------------------------
+// Initial login                       -        A       -
+// No sync and second login            A        A       -
+// Change options                      B        B       -
+// -----------------------------------------------------------
+// Initial login                       -        A       -
+// Sync                                A        A       -
+// Locale changed on login screen      A        C       -
+// Accept (A)                          A        A       A
+// -----------------------------------------------------------
+// Initial login                       -        A       -
+// Sync                                B        A       -
+// Revert                              A        A       -
 const char kApplicationLocaleBackup[] = "intl.app_locale_backup";
 #endif
 
@@ -131,6 +161,9 @@
 const char kSafeBrowsingReportingEnabled[] =
     "safebrowsing.reporting_enabled";
 
+// Boolean that is true when Incognito support is enabled.
+const char kIncognitoEnabled[] = "incognito.enabled";
+
 // Boolean that is true when Suggest support is enabled.
 const char kSearchSuggestEnabled[] = "search.suggest_enabled";
 
@@ -245,11 +278,13 @@
 
 // Used to migrate preferences from local state to user preferences to
 // enable multiple profiles.
-// Holds possible values:
-// 0: no preferences migrated yet.
-// 1: dns prefetching preferences stored in user preferences.
+// BITMASK with possible values (see browser_prefs.cc for enum):
+// 0: No preferences migrated.
+// 1: DNS preferences migrated: kDnsPrefetchingStartupList and HostReferralList
+// 2: Browser window preferences migrated: kDevToolsSplitLocation and
+//    kBrowserWindowPlacement
 const char kMultipleProfilePrefMigration[] =
-    "profile.multiple_profile_prefs_version";
+    "local_state.multiple_profile_prefs_version";
 
 #if defined(USE_NSS) || defined(USE_OPENSSL)
 // Prefs for SSLConfigServicePref.  Currently, these are only present on
@@ -260,6 +295,12 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+// An integer pref to initially mute volume if 1.
+const char kAudioMute[] = "settings.audio.mute";
+
+// A double pref to set initial volume.
+const char kAudioVolume[] = "settings.audio.volume";
+
 // A boolean pref set to true if TapToClick is being done in browser.
 const char kTapToClickEnabled[] = "settings.touchpad.enable_tap_to_click";
 
@@ -467,7 +508,6 @@
 const char kDeleteCookies[] = "browser.clear_data.cookies";
 const char kDeletePasswords[] = "browser.clear_data.passwords";
 const char kDeleteFormData[] = "browser.clear_data.form_data";
-const char kDeleteLSOData[] = "browser.clear_data.lso_data";
 const char kDeleteTimePeriod[] = "browser.clear_data.time_period";
 
 // Whether there is a Flash version installed that supports clearing LSO data.
@@ -528,10 +568,21 @@
 // enable it by default, we'll want to do so only once.
 const char kPluginsEnabledInternalPDF[] = "plugins.enabled_internal_pdf3";
 
+const char kPluginsShowSetReaderDefaultInfobar[] =
+    "plugins.show_set_reader_default";
+
+// Whether about:plugins is shown in the details mode or not.
+const char kPluginsShowDetails[] = "plugins.show_details";
+
 // Boolean that indicates whether we should check if we are the default browser
 // on start-up.
 const char kCheckDefaultBrowser[] = "browser.check_default_browser";
 
+// Policy setting whether default browser check should be disabled and default
+// browser registration should take place.
+const char kDefaultBrowserSettingEnabled[] =
+    "browser.default_browser_setting_enabled";
+
 #if defined(OS_MACOSX)
 // Boolean that indicates whether the application should show the info bar
 // asking the user to set up automatic updates when Keystone promotion is
@@ -587,11 +638,6 @@
 // storage, etc..) should be deleted on exit.
 const char kClearSiteDataOnExit[] = "profile.clear_site_data_on_exit";
 
-// Boolean that is true when plug-in locally stored data ("Flash cookies")
-// should be deleted on exit.
-const char kClearPluginLSODataOnExit[] =
-    "profile.clear_plugin_lso_data_on_exit";
-
 // Double that indicates the default zoom level.
 const char kDefaultZoomLevel[] = "profile.default_zoom_level";
 
@@ -628,6 +674,11 @@
 
 const char kPinnedTabs[] = "pinned_tabs";
 
+// Integer that specifies the policy refresh rate in milliseconds. Not all
+// values are meaningful, so it is clamped to a sane range by the policy
+// provider.
+const char kPolicyRefreshRate[] = "policy.refresh_rate";
+
 // Integer containing the default Geolocation content setting.
 const char kGeolocationDefaultContentSetting[] =
     "geolocation.default_content_setting";
@@ -743,6 +794,20 @@
 const char kStabilityChildProcessCrashCount[] =
     "user_experience_metrics.stability.child_process_crash_count";
 
+// On Chrome OS, total number of non-Chrome user process crashes
+// since the last report.
+const char kStabilityOtherUserCrashCount[] =
+    "user_experience_metrics.stability.other_user_crash_count";
+
+// On Chrome OS, total number of kernel crashes since the last report.
+const char kStabilityKernelCrashCount[] =
+    "user_experience_metrics.stability.kernel_crash_count";
+
+// On Chrome OS, total number of unclean system shutdowns since the
+// last report.
+const char kStabilitySystemUncleanShutdownCount[] =
+    "user_experience_metrics.stability.system_unclean_shutdowns";
+
 // Number of times the browser has been able to register crash reporting.
 const char kStabilityBreakpadRegistrationSuccess[] =
     "user_experience_metrics.stability.breakpad_registration_ok";
@@ -810,6 +875,10 @@
 // String which specifies where to save html files to by default.
 const char kSaveFileDefaultDirectory[] = "savefile.default_directory";
 
+// The type used to save the page. See the enum SavePackage::SavePackageType in
+// the chrome/browser/download/save_package.h for the possible values.
+const char kSaveFileType[] = "savefile.type";
+
 // String which specifies the last directory that was chosen for uploading
 // or opening a file.
 const char kSelectFileLastDirectory[] = "selectfile.last_directory";
@@ -996,16 +1065,27 @@
 const char kNTPCustomLogoStart[] = "ntp.alt_logo_start";
 const char kNTPCustomLogoEnd[] = "ntp.alt_logo_end";
 
-// Dates between which the NTP should show a promotional line downloaded
-// from the promo server.
-const char kNTPPromoStart[] = "ntp.promo_start";
-const char kNTPPromoEnd[] = "ntp.promo_end";
+// Whether promo should be shown to Dev builds, Beta and Dev, or all builds.
+const char kNTPPromoBuild[] = "ntp.promo_build";
+
+// True if user has explicitly closed the promo line.
+const char kNTPPromoClosed[] = "ntp.promo_closed";
+
+// Users are randomly divided into 16 groups in order to slowly roll out
+// special promos.
+const char kNTPPromoGroup[] = "ntp.promo_group";
+
+// Amount of time each promo group should be shown a promo that is being slowly
+// rolled out, in hours.
+const char kNTPPromoGroupTimeSlice[] = "ntp.promo_group_timeslice";
 
 // Promo line from server.
 const char kNTPPromoLine[] = "ntp.promo_line";
 
-// True if user has explicitly closed the promo line.
-const char kNTPPromoClosed[] = "ntp.promo_closed";
+// Dates between which the NTP should show a promotional line downloaded
+// from the promo server.
+const char kNTPPromoStart[] = "ntp.promo_start";
+const char kNTPPromoEnd[] = "ntp.promo_end";
 
 const char kDevToolsDisabled[] = "devtools.disabled";
 
@@ -1116,6 +1196,10 @@
 // Dictionary for transient storage of settings that should go into signed
 // settings storage before owner has been assigned.
 const char kSignedSettingsTempStorage[] = "signed_settings_temp_storage";
+
+// The hardware keyboard layout of the device. This should look like
+// "xkb:us::eng".
+const char kHardwareKeyboardLayout[] = "intl.hardware_keyboard";
 #endif
 
 // *************** SERVICE PREFS ***************
@@ -1139,18 +1223,8 @@
 // Used by the service process to determine if the remoting host is enabled.
 const char kRemotingHostEnabled[] = "remoting.host_enabled";
 
-// Integer to specify the type of proxy settings.
-// See ProxyPrefs for possible values and interactions with the other proxy
-// preferences.
-const char kProxyMode[] = "proxy.mode";
-// String specifying the proxy server. For a specification of the expected
-// syntax see net::ProxyConfig::ProxyRules::ParseFromString().
-const char kProxyServer[] = "proxy.server";
-// URL to the proxy .pac file.
-const char kProxyPacUrl[] = "proxy.pac_url";
-// String containing proxy bypass rules. For a specification of the
-// expected syntax see net::ProxyBypassRules::ParseFromString().
-const char kProxyBypassList[] = "proxy.bypass_list";
+// Preference to story proxy settings.
+const char kProxy[] = "proxy";
 
 // Preferences that are exclusivly used to store managed values for default
 // content settings.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 29766a1..8fe066d 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -27,6 +27,8 @@
 extern const char kApplicationLocale[];
 #if defined(OS_CHROMEOS)
 extern const char kApplicationLocaleBackup[];
+extern const char kApplicationLocaleAccepted[];
+extern const char kOwnerLocale[];
 #endif
 
 extern const char kDefaultCharset[];
@@ -61,6 +63,7 @@
 extern const char kFormAutofillEnabled[];  // OBSOLETE
 extern const char kSafeBrowsingEnabled[];
 extern const char kSafeBrowsingReportingEnabled[];
+extern const char kIncognitoEnabled[];
 extern const char kSearchSuggestEnabled[];
 extern const char kCookieBehavior[];  // OBSOLETE
 extern const char kDefaultSearchProviderEnabled[];
@@ -96,6 +99,8 @@
 extern const char kTLS1Enabled[];
 #endif
 #if defined(OS_CHROMEOS)
+extern const char kAudioMute[];
+extern const char kAudioVolume[];
 extern const char kTapToClickEnabled[];
 extern const char kTouchpadSensitivity[];
 extern const char kLanguageCurrentInputMethod[];
@@ -173,7 +178,6 @@
 extern const char kDeleteCookies[];
 extern const char kDeletePasswords[];
 extern const char kDeleteFormData[];
-extern const char kDeleteLSOData[];
 extern const char kClearPluginLSODataEnabled[];
 extern const char kEnableSpellCheck[];
 extern const char kEnabledLabsExperiments[];
@@ -202,7 +206,10 @@
 extern const char kPluginsPluginsList[];
 extern const char kPluginsPluginsBlacklist[];
 extern const char kPluginsEnabledInternalPDF[];
+extern const char kPluginsShowSetReaderDefaultInfobar[];
+extern const char kPluginsShowDetails[];
 extern const char kCheckDefaultBrowser[];
+extern const char kDefaultBrowserSettingEnabled[];
 #if defined(OS_MACOSX)
 extern const char kShowUpdatePromotionInfoBar[];
 #endif
@@ -219,7 +226,6 @@
 extern const char kBlockThirdPartyCookies[];
 extern const char kBlockNonsandboxedPlugins[];
 extern const char kClearSiteDataOnExit[];
-extern const char kClearPluginLSODataOnExit[];
 extern const char kDefaultZoomLevel[];
 extern const char kPerHostZoomLevels[];
 extern const char kAutoFillEnabled[];
@@ -232,6 +238,7 @@
 extern const char kUseVerticalTabs[];
 extern const char kEnableTranslate[];
 extern const char kPinnedTabs[];
+extern const char kPolicyRefreshRate[];
 
 // Local state
 extern const char kMetricsClientID[];
@@ -258,6 +265,9 @@
 extern const char kStabilityLastTimestampSec[];
 extern const char kStabilityRendererHangCount[];
 extern const char kStabilityChildProcessCrashCount[];
+extern const char kStabilityOtherUserCrashCount[];
+extern const char kStabilityKernelCrashCount[];
+extern const char kStabilitySystemUncleanShutdownCount[];
 
 extern const char kStabilityBreakpadRegistrationSuccess[];
 extern const char kStabilityBreakpadRegistrationFail[];
@@ -289,6 +299,7 @@
 extern const char kDownloadDirUpgraded[];
 
 extern const char kSaveFileDefaultDirectory[];
+extern const char kSaveFileType[];
 
 extern const char kSelectFileLastDirectory[];
 
@@ -363,6 +374,9 @@
 extern const char kNTPPromoEnd[];
 extern const char kNTPPromoLine[];
 extern const char kNTPPromoClosed[];
+extern const char kNTPPromoGroup[];
+extern const char kNTPPromoGroupTimeSlice[];
+extern const char kNTPPromoBuild[];
 
 extern const char kDevToolsDisabled[];
 extern const char kDevToolsOpenDocked[];
@@ -412,10 +426,7 @@
 extern const char kRemotingHasSetupCompleted[];
 extern const char kRemotingHostEnabled[];
 
-extern const char kProxyMode[];
-extern const char kProxyServer[];
-extern const char kProxyPacUrl[];
-extern const char kProxyBypassList[];
+extern const char kProxy[];
 
 extern const char kManagedDefaultCookiesSetting[];
 extern const char kManagedDefaultImagesSetting[];
@@ -425,6 +436,7 @@
 
 #if defined(OS_CHROMEOS)
 extern const char kSignedSettingsTempStorage[];
+extern const char kHardwareKeyboardLayout[];
 #endif
 
 extern const char kRegisteredBackgroundContents[];
diff --git a/chrome/common/pref_store.h b/chrome/common/pref_store.h
index 35818a0..819a764 100644
--- a/chrome/common/pref_store.h
+++ b/chrome/common/pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/ref_counted.h"
 
 class Value;
 
@@ -19,7 +20,7 @@
 // CommandLinePrefStore, which bridges command line options to preferences and
 // ConfigurationPolicyPrefStore, which is used for hooking up configuration
 // policy with the preference subsystem.
-class PrefStore {
+class PrefStore : public base::RefCounted<PrefStore> {
  public:
   // Observer interface for monitoring PrefStore.
   class Observer {
@@ -43,7 +44,6 @@
   };
 
   PrefStore() {}
-  virtual ~PrefStore() {}
 
   // Add and remove observers.
   virtual void AddObserver(Observer* observer) {}
@@ -57,6 +57,11 @@
   // |result| value remains with the PrefStore.
   virtual ReadResult GetValue(const std::string& key, Value** result) const = 0;
 
+ protected:
+  friend class base::RefCounted<PrefStore>;
+  virtual ~PrefStore() {}
+
+ private:
   DISALLOW_COPY_AND_ASSIGN(PrefStore);
 };
 
diff --git a/chrome/common/profiling.cc b/chrome/common/profiling.cc
new file mode 100644
index 0000000..bf67885
--- /dev/null
+++ b/chrome/common/profiling.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/profiling.h"
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/debug/profiler.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_switches.h"
+
+namespace {
+std::string GetProfileName() {
+  static const char kDefaultProfileName[] = "chrome-profile-{pid}";
+  static std::string profile_name;
+
+  if (profile_name.empty()) {
+    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+    if (command_line.HasSwitch(switches::kProfilingFile))
+      profile_name = command_line.GetSwitchValueASCII(switches::kProfilingFile);
+    else
+      profile_name = std::string(kDefaultProfileName);
+    std::string process_type =
+        command_line.GetSwitchValueASCII(switches::kProcessType);
+    std::string type = process_type.empty() ?
+        std::string("browser") : std::string(process_type);
+    ReplaceSubstringsAfterOffset(&profile_name, 0, "{type}", type.c_str());
+  }
+  return profile_name;
+}
+
+void FlushProfilingData() {
+  static const int kProfilingFlushSeconds = 10;
+
+  if (!Profiling::BeingProfiled())
+    return;
+
+  base::debug::FlushProfiling();
+  static int flush_seconds = 0;
+  if (!flush_seconds) {
+    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+    std::string profiling_flush =
+        command_line.GetSwitchValueASCII(switches::kProfilingFlush);
+    if (!profiling_flush.empty()) {
+      flush_seconds = atoi(profiling_flush.c_str());
+      DCHECK(flush_seconds > 0);
+    } else {
+      flush_seconds = kProfilingFlushSeconds;
+    }
+  }
+  MessageLoop::current()->PostDelayedTask(FROM_HERE,
+      NewRunnableFunction(FlushProfilingData),
+      flush_seconds * 1000);
+}
+
+} // namespace
+
+// static
+void Profiling::ProcessStarted() {
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  std::string process_type =
+      command_line.GetSwitchValueASCII(switches::kProcessType);
+
+  if (command_line.HasSwitch(switches::kProfilingAtStart)) {
+    std::string process_type_to_start =
+        command_line.GetSwitchValueASCII(switches::kProfilingAtStart);
+    if (process_type == process_type_to_start)
+      Start();
+  }
+}
+
+// static
+void Profiling::Start() {
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  bool flush = command_line.HasSwitch(switches::kProfilingFlush);
+  base::debug::StartProfiling(GetProfileName());
+
+  // Schedule profile data flushing for single process because it doesn't
+  // get written out correctly on exit.
+  if (flush && MessageLoop::current())
+    FlushProfilingData();
+}
+
+// static
+void Profiling::Stop() {
+  base::debug::StopProfiling();
+}
+
+// static
+bool Profiling::BeingProfiled() {
+  return base::debug::BeingProfiled();
+}
+
+// static
+void Profiling::Toggle() {
+  if (BeingProfiled())
+    Stop();
+  else
+    Start();
+}
+
+// static
+void Profiling::MainMessageLoopStarted() {
+  if (BeingProfiled()) {
+    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+    bool flush = command_line.HasSwitch(switches::kProfilingFlush);
+    if (flush)
+      FlushProfilingData();
+  }
+}
diff --git a/chrome/common/profiling.h b/chrome/common/profiling.h
new file mode 100644
index 0000000..21aebd1
--- /dev/null
+++ b/chrome/common/profiling.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_PROFILING_H_
+#define CHROME_COMMON_PROFILING_H_
+#pragma once
+
+#include "build/build_config.h"
+
+#include "base/basictypes.h"
+#include "base/debug/profiler.h"
+
+// The Profiling class manages the interaction with a sampling based profiler.
+// Its function is controlled by the kProfilingAtStart, kProfilingFile, and
+// kProfilingFlush command line values.
+// All of the API should only be called from the main thread of the process.
+class Profiling {
+ public:
+  // Called early in a process' life to allow profiling of startup time.
+  // the presence of kProfilingAtStart is checked.
+  static void ProcessStarted();
+
+  // Start profiling.
+  static void Start();
+
+  // Stop profiling and write out profiling file.
+  static void Stop();
+
+  // Returns true if the process is being profiled.
+  static bool BeingProfiled();
+
+  // Called when the main message loop is started, so that automatic flushing
+  // of the profile data file can be done.
+  static void MainMessageLoopStarted();
+
+  // Toggle profiling on/off.
+  static void Toggle();
+
+ private:
+  // Do not instantiate this class.
+  Profiling();
+
+  DISALLOW_COPY_AND_ASSIGN(Profiling);
+};
+
+#endif  // CHROME_COMMON_PROFILING_H_
+
diff --git a/chrome/common/property_bag.h b/chrome/common/property_bag.h
index 0a44892..da3ae48 100644
--- a/chrome/common/property_bag.h
+++ b/chrome/common/property_bag.h
@@ -16,7 +16,7 @@
 
 // A property bag holds a generalized list of arbitrary metadata called
 // properties. Each property is a class type derived from PropertyBag::Prop
-// that can bet set and retrieved.
+// that can be set and retrieved.
 //
 // The property bag is not read or written directly. Instead, callers go
 // through a PropertyAccessor. The Accessor generates the unique IDs that
diff --git a/chrome/common/remoting/chromoting_host_info.cc b/chrome/common/remoting/chromoting_host_info.cc
new file mode 100644
index 0000000..acb0ce5
--- /dev/null
+++ b/chrome/common/remoting/chromoting_host_info.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/common/remoting/chromoting_host_info.h"
+
+namespace remoting {
+
+ChromotingHostInfo::ChromotingHostInfo()
+    : enabled(false) {
+}
+
+ChromotingHostInfo::~ChromotingHostInfo() {}
+
+}  // namespace remoting
diff --git a/chrome/common/remoting/chromoting_host_info.h b/chrome/common/remoting/chromoting_host_info.h
index e803eef..f1816da 100644
--- a/chrome/common/remoting/chromoting_host_info.h
+++ b/chrome/common/remoting/chromoting_host_info.h
@@ -11,6 +11,9 @@
 
 // This struct is used for ServiceHostMsg_ChromotingHost_Info IPC message.
 struct ChromotingHostInfo {
+  ChromotingHostInfo();
+  ~ChromotingHostInfo();
+
   std::string host_id;
   std::string hostname;
   std::string public_key;
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index 69b73be..5df43f7 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -9,21 +9,17 @@
 #include "chrome/common/gpu_param_traits.h"
 #include "chrome/common/render_messages_params.h"
 #include "chrome/common/resource_response.h"
-#include "chrome/common/speech_input_result.h"
 #include "chrome/common/thumbnail_score.h"
 #include "chrome/common/web_apps.h"
-#include "gfx/rect.h"
 #include "ipc/ipc_channel_handle.h"
 #include "media/audio/audio_buffers_state.h"
 #include "net/base/upload_data.h"
 #include "net/http/http_response_headers.h"
-#include "ppapi/c/private/ppb_flash.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/rect.h"
 #include "webkit/appcache/appcache_interfaces.h"
 #include "webkit/blob/blob_data.h"
-#include "webkit/glue/form_field.h"
-#include "webkit/glue/password_form.h"
 #include "webkit/glue/resource_loader_bridge.h"
 #include "webkit/glue/webaccessibility.h"
 #include "webkit/glue/webcookie.h"
@@ -59,12 +55,18 @@
       case WebMenuItem::OPTION:
         type = "OPTION";
         break;
+      case WebMenuItem::CHECKABLE_OPTION:
+        type = "CHECKABLE_OPTION";
+        break;
       case WebMenuItem::GROUP:
         type = "GROUP";
         break;
       case WebMenuItem::SEPARATOR:
         type = "SEPARATOR";
         break;
+      case WebMenuItem::SUBMENU:
+        type = "SUBMENU";
+        break;
       default:
         type = "UNKNOWN";
         break;
@@ -73,49 +75,6 @@
   }
 };
 
-
-void ParamTraits<webkit_glue::FormField>::Write(Message* m,
-                                                const param_type& p) {
-  WriteParam(m, p.label());
-  WriteParam(m, p.name());
-  WriteParam(m, p.value());
-  WriteParam(m, p.form_control_type());
-  WriteParam(m, p.max_length());
-  WriteParam(m, p.is_autofilled());
-  WriteParam(m, p.option_strings());
-}
-
-bool ParamTraits<webkit_glue::FormField>::Read(const Message* m, void** iter,
-                                               param_type* p) {
-  string16 label, name, value, form_control_type;
-  int max_length = 0;
-  bool is_autofilled;
-  std::vector<string16> options;
-  bool result = ReadParam(m, iter, &label);
-  result = result && ReadParam(m, iter, &name);
-  result = result && ReadParam(m, iter, &value);
-  result = result && ReadParam(m, iter, &form_control_type);
-  result = result && ReadParam(m, iter, &max_length);
-  result = result && ReadParam(m, iter, &is_autofilled);
-  result = result && ReadParam(m, iter, &options);
-  if (!result)
-    return false;
-
-  p->set_label(label);
-  p->set_name(name);
-  p->set_value(value);
-  p->set_form_control_type(form_control_type);
-  p->set_max_length(max_length);
-  p->set_autofilled(is_autofilled);
-  p->set_option_strings(options);
-  return true;
-}
-
-void ParamTraits<webkit_glue::FormField>::Log(const param_type& p,
-                                              std::string* l) {
-  l->append("<FormField>");
-}
-
 #if defined(OS_MACOSX)
 void ParamTraits<FontDescriptor>::Write(Message* m, const param_type& p) {
   WriteParam(m, p.font_name);
@@ -125,9 +84,9 @@
 bool ParamTraits<FontDescriptor>::Read(const Message* m,
                                        void** iter,
                                        param_type* p) {
-  return(
+  return
       ReadParam(m, iter, &p->font_name) &&
-      ReadParam(m, iter, &p->font_point_size));
+      ReadParam(m, iter, &p->font_point_size);
 }
 
 void ParamTraits<FontDescriptor>::Log(const param_type& p, std::string* l) {
@@ -135,6 +94,31 @@
 }
 #endif
 
+void ParamTraits<webkit_glue::CustomContextMenuContext>::Write(
+    Message* m,
+    const param_type& p) {
+  WriteParam(m, p.is_pepper_menu);
+  WriteParam(m, p.request_id);
+}
+
+bool ParamTraits<webkit_glue::CustomContextMenuContext>::Read(const Message* m,
+                                                              void** iter,
+                                                              param_type* p) {
+  return
+      ReadParam(m, iter, &p->is_pepper_menu) &&
+      ReadParam(m, iter, &p->request_id);
+}
+
+void ParamTraits<webkit_glue::CustomContextMenuContext>::Log(
+    const param_type& p,
+    std::string* l) {
+  l->append("(");
+  LogParam(p.is_pepper_menu, l);
+  l->append(", ");
+  LogParam(p.request_id, l);
+  l->append(")");
+}
+
 void ParamTraits<ContextMenuParams>::Write(Message* m, const param_type& p) {
   WriteParam(m, p.media_type);
   WriteParam(m, p.x);
@@ -159,6 +143,7 @@
   WriteParam(m, p.edit_flags);
   WriteParam(m, p.security_info);
   WriteParam(m, p.frame_charset);
+  WriteParam(m, p.custom_context);
   WriteParam(m, p.custom_items);
 }
 
@@ -188,6 +173,7 @@
       ReadParam(m, iter, &p->edit_flags) &&
       ReadParam(m, iter, &p->security_info) &&
       ReadParam(m, iter, &p->frame_charset) &&
+      ReadParam(m, iter, &p->custom_context) &&
       ReadParam(m, iter, &p->custom_items);
 }
 
@@ -301,26 +287,6 @@
   l->append(")");
 }
 
-void ParamTraits<webkit_glue::PasswordFormFillData>::Write(
-    Message* m, const param_type& p) {
-  WriteParam(m, p.basic_data);
-  WriteParam(m, p.additional_logins);
-  WriteParam(m, p.wait_for_username);
-}
-
-bool ParamTraits<webkit_glue::PasswordFormFillData>::Read(
-    const Message* m, void** iter, param_type* r) {
-  return
-      ReadParam(m, iter, &r->basic_data) &&
-      ReadParam(m, iter, &r->additional_logins) &&
-      ReadParam(m, iter, &r->wait_for_username);
-}
-
-void ParamTraits<webkit_glue::PasswordFormFillData>::Log(const param_type& p,
-                                                         std::string* l) {
-  l->append("<PasswordFormFillData>");
-}
-
 void ParamTraits<scoped_refptr<net::HttpResponseHeaders> >::Write(
     Message* m, const param_type& p) {
   WriteParam(m, p.get() != NULL);
@@ -565,48 +531,22 @@
 }
 
 void ParamTraits<SyncLoadResult>::Write(Message* m, const param_type& p) {
-    ParamTraits<ResourceResponseHead>::Write(m, p);
-    WriteParam(m, p.final_url);
-    WriteParam(m, p.data);
-  }
+  ParamTraits<ResourceResponseHead>::Write(m, p);
+  WriteParam(m, p.final_url);
+  WriteParam(m, p.data);
+}
 
 bool ParamTraits<SyncLoadResult>::Read(const Message* m, void** iter,
                                        param_type* r) {
-    return
-      ParamTraits<ResourceResponseHead>::Read(m, iter, r) &&
-      ReadParam(m, iter, &r->final_url) &&
-      ReadParam(m, iter, &r->data);
-  }
+  return
+    ParamTraits<ResourceResponseHead>::Read(m, iter, r) &&
+    ReadParam(m, iter, &r->final_url) &&
+    ReadParam(m, iter, &r->data);
+}
 
 void ParamTraits<SyncLoadResult>::Log(const param_type& p, std::string* l) {
-    // log more?
-    ParamTraits<webkit_glue::ResourceResponseInfo>::Log(p, l);
-  }
-
-void ParamTraits<webkit_glue::FormData>::Write(Message* m,
-                                               const param_type& p) {
-  WriteParam(m, p.name);
-  WriteParam(m, p.method);
-  WriteParam(m, p.origin);
-  WriteParam(m, p.action);
-  WriteParam(m, p.user_submitted);
-  WriteParam(m, p.fields);
-}
-
-bool ParamTraits<webkit_glue::FormData>::Read(const Message* m, void** iter,
-                                              param_type* p) {
-  return
-      ReadParam(m, iter, &p->name) &&
-      ReadParam(m, iter, &p->method) &&
-      ReadParam(m, iter, &p->origin) &&
-      ReadParam(m, iter, &p->action) &&
-      ReadParam(m, iter, &p->user_submitted) &&
-      ReadParam(m, iter, &p->fields);
-}
-
-void ParamTraits<webkit_glue::FormData>::Log(const param_type& p,
-                                             std::string* l) {
-  l->append("<FormData>");
+  // log more?
+  ParamTraits<webkit_glue::ResourceResponseInfo>::Log(p, l);
 }
 
 void ParamTraits<RendererPreferences>::Write(Message* m, const param_type& p) {
@@ -724,13 +664,17 @@
   WriteParam(m, p.frame_flattening_enabled);
   WriteParam(m, p.allow_universal_access_from_file_urls);
   WriteParam(m, p.allow_file_access_from_file_urls);
+  WriteParam(m, p.webaudio_enabled);
   WriteParam(m, p.experimental_webgl_enabled);
+  WriteParam(m, p.gl_multisampling_enabled);
   WriteParam(m, p.show_composited_layer_borders);
   WriteParam(m, p.accelerated_compositing_enabled);
   WriteParam(m, p.accelerated_2d_canvas_enabled);
+  WriteParam(m, p.accelerated_plugins_enabled);
   WriteParam(m, p.accelerated_layers_enabled);
   WriteParam(m, p.accelerated_video_enabled);
   WriteParam(m, p.memory_info_enabled);
+  WriteParam(m, p.interactive_form_validation_enabled);
 }
 
 bool ParamTraits<WebPreferences>::Read(const Message* m, void** iter,
@@ -776,13 +720,17 @@
       ReadParam(m, iter, &p->frame_flattening_enabled) &&
       ReadParam(m, iter, &p->allow_universal_access_from_file_urls) &&
       ReadParam(m, iter, &p->allow_file_access_from_file_urls) &&
+      ReadParam(m, iter, &p->webaudio_enabled) &&
       ReadParam(m, iter, &p->experimental_webgl_enabled) &&
+      ReadParam(m, iter, &p->gl_multisampling_enabled) &&
       ReadParam(m, iter, &p->show_composited_layer_borders) &&
       ReadParam(m, iter, &p->accelerated_compositing_enabled) &&
       ReadParam(m, iter, &p->accelerated_2d_canvas_enabled) &&
+      ReadParam(m, iter, &p->accelerated_plugins_enabled) &&
       ReadParam(m, iter, &p->accelerated_layers_enabled) &&
       ReadParam(m, iter, &p->accelerated_video_enabled) &&
-      ReadParam(m, iter, &p->memory_info_enabled);
+      ReadParam(m, iter, &p->memory_info_enabled) &&
+      ReadParam(m, iter, &p->interactive_form_validation_enabled);
 }
 
 void ParamTraits<WebPreferences>::Log(const param_type& p, std::string* l) {
@@ -826,9 +774,12 @@
 void ParamTraits<WebMenuItem>::Write(Message* m, const param_type& p) {
   WriteParam(m, p.label);
   WriteParam(m, p.type);
+  WriteParam(m, p.action);
+  WriteParam(m, p.rtl);
+  WriteParam(m, p.has_directional_override);
   WriteParam(m, p.enabled);
   WriteParam(m, p.checked);
-  WriteParam(m, p.action);
+  WriteParam(m, p.submenu);
 }
 
 bool ParamTraits<WebMenuItem>::Read(const Message* m,
@@ -837,9 +788,12 @@
   return
       ReadParam(m, iter, &p->label) &&
       ReadParam(m, iter, &p->type) &&
+      ReadParam(m, iter, &p->action) &&
+      ReadParam(m, iter, &p->rtl) &&
+      ReadParam(m, iter, &p->has_directional_override) &&
       ReadParam(m, iter, &p->enabled) &&
       ReadParam(m, iter, &p->checked) &&
-      ReadParam(m, iter, &p->action);
+      ReadParam(m, iter, &p->submenu);
 }
 
 void ParamTraits<WebMenuItem>::Log(const param_type& p, std::string* l) {
@@ -848,11 +802,17 @@
   l->append(", ");
   LogParam(p.type, l);
   l->append(", ");
+  LogParam(p.action, l);
+  l->append(", ");
+  LogParam(p.rtl, l);
+  l->append(", ");
+  LogParam(p.has_directional_override, l);
+  l->append(", ");
   LogParam(p.enabled, l);
   l->append(", ");
   LogParam(p.checked, l);
   l->append(", ");
-  LogParam(p.action, l);
+  LogParam(p.submenu, l);
   l->append(")");
 }
 
@@ -1216,55 +1176,4 @@
   l->append(")");
 }
 
-void ParamTraits<speech_input::SpeechInputResultItem>::Write(
-    Message* m, const param_type& p) {
-  WriteParam(m, p.utterance);
-  WriteParam(m, p.confidence);
-}
-
-bool ParamTraits<speech_input::SpeechInputResultItem>::Read(const Message* m,
-                                                            void** iter,
-                                                            param_type* p) {
-  return ReadParam(m, iter, &p->utterance) &&
-         ReadParam(m, iter, &p->confidence);
-}
-
-void ParamTraits<speech_input::SpeechInputResultItem>::Log(const param_type& p,
-                                                           std::string* l) {
-  l->append("(");
-  LogParam(p.utterance, l);
-  l->append(":");
-  LogParam(p.confidence, l);
-  l->append(")");
-}
-
-void ParamTraits<PP_Flash_NetAddress>::Write(Message* m, const param_type& p) {
-  WriteParam(m, p.size);
-  m->WriteBytes(p.data, p.size);
-}
-
-bool ParamTraits<PP_Flash_NetAddress>::Read(const Message* m,
-                                            void** iter,
-                                            param_type* p) {
-  uint16 size;
-  if (!ReadParam(m, iter, &size))
-    return false;
-  if (size > sizeof(p->data))
-    return false;
-  p->size = size;
-
-  const char* data;
-  if (!m->ReadBytes(iter, &data, size))
-    return false;
-  memcpy(p->data, data, size);
-  return true;
-}
-
-void ParamTraits<PP_Flash_NetAddress>::Log(const param_type& p,
-                                           std::string* l) {
-  l->append("<PP_Flash_NetAddress (");
-  LogParam(p.size, l);
-  l->append(" bytes)>");
-}
-
 }  // namespace IPC
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 258734a..2e94d53 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -11,7 +11,6 @@
 
 // TODO(erg): This list has been temporarily annotated by erg while doing work
 // on which headers to pull out.
-#include "app/clipboard/clipboard.h"                   // enum
 #include "base/basictypes.h"
 #include "base/ref_counted.h"
 #include "base/string16.h"
@@ -23,6 +22,7 @@
 #include "chrome/common/webkit_param_traits.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/ipc_platform_file.h"                     // ifdefed typedef.
+#include "ui/base/clipboard/clipboard.h"                   // enum
 #include "webkit/appcache/appcache_interfaces.h"  // enum appcache::Status
 #include "webkit/fileapi/file_system_types.h"  // enum fileapi::FileSystemType
 
@@ -48,14 +48,8 @@
 class BlobData;
 }
 
-namespace speech_input {
-struct SpeechInputResultItem;
-}
-
 namespace webkit_glue {
-struct FormData;
-class FormField;
-struct PasswordFormFillData;
+struct CustomContextMenuContext;
 struct ResourceDevToolsInfo;
 struct ResourceLoadTimingInfo;
 struct ResourceResponseInfo;
@@ -111,8 +105,7 @@
 struct ViewMsg_New_Params;
 struct ViewHostMsg_CreateWindow_Params;
 struct ViewHostMsg_RunFileChooser_Params;
-struct ViewMsg_ExtensionRendererInfo;
-struct ViewMsg_ExtensionsUpdated_Params;
+struct ViewMsg_ExtensionLoaded_Params;
 struct ViewMsg_DeviceOrientationUpdated_Params;
 struct ViewHostMsg_DomMessage_Params;
 struct ViewHostMsg_AccessibilityNotification_Params;
@@ -126,17 +119,20 @@
   kPreferredSizeHeightThisIsSlow = 1 << 1,
 };
 
-namespace IPC {
-
-// Traits for FormField_Params structure to pack/unpack.
-template <>
-struct ParamTraits<webkit_glue::FormField> {
-  typedef webkit_glue::FormField param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
+// Command values for the cmd parameter of the
+// ViewHost_JavaScriptStressTestControl message. For each command the parameter
+// passed has a different meaning:
+// For the command kJavaScriptStressTestSetStressRunType the parameter it the
+// type taken from the enumeration v8::Testing::StressType.
+// For the command kJavaScriptStressTestPrepareStressRun the parameter it the
+// number of the stress run about to take place.
+enum ViewHostMsg_JavaScriptStressTestControl_Commands {
+  kJavaScriptStressTestSetStressRunType = 0,
+  kJavaScriptStressTestPrepareStressRun = 1,
 };
 
+namespace IPC {
+
 #if defined(OS_MACOSX)
 // Traits for FontDescriptor structure to pack/unpack.
 template <>
@@ -149,6 +145,14 @@
 #endif
 
 template <>
+struct ParamTraits<webkit_glue::CustomContextMenuContext> {
+  typedef webkit_glue::CustomContextMenuContext param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
 struct ParamTraits<ContextMenuParams> {
   typedef ContextMenuParams param_type;
   static void Write(Message* m, const param_type& p);
@@ -181,15 +185,6 @@
   static void Log(const param_type& p, std::string* l);
 };
 
-// Traits for webkit_glue::PasswordFormDomManager::FillData.
-template <>
-struct ParamTraits<webkit_glue::PasswordFormFillData> {
-  typedef webkit_glue::PasswordFormFillData param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* r);
-  static void Log(const param_type& p, std::string* l);
-};
-
 template <>
 struct ParamTraits<scoped_refptr<net::HttpResponseHeaders> > {
   typedef scoped_refptr<net::HttpResponseHeaders> param_type;
@@ -240,15 +235,6 @@
   static void Log(const param_type& p, std::string* l);
 };
 
-// Traits for FormData structure to pack/unpack.
-template <>
-struct ParamTraits<webkit_glue::FormData> {
-  typedef webkit_glue::FormData param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
 // Traits for reading/writing CSS Colors
 template <>
 struct ParamTraits<CSSColors::CSSColorName> {
@@ -431,30 +417,30 @@
 };
 
 template <>
-struct ParamTraits<Clipboard::Buffer> {
-  typedef Clipboard::Buffer param_type;
+struct ParamTraits<ui::Clipboard::Buffer> {
+  typedef ui::Clipboard::Buffer param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteInt(p);
   }
   static bool Read(const Message* m, void** iter, param_type* p) {
     int buffer;
-    if (!m->ReadInt(iter, &buffer) || !Clipboard::IsValidBuffer(buffer))
+    if (!m->ReadInt(iter, &buffer) || !ui::Clipboard::IsValidBuffer(buffer))
       return false;
-    *p = Clipboard::FromInt(buffer);
+    *p = ui::Clipboard::FromInt(buffer);
     return true;
   }
   static void Log(const param_type& p, std::string* l) {
     std::string type;
     switch (p) {
-      case Clipboard::BUFFER_STANDARD:
+      case ui::Clipboard::BUFFER_STANDARD:
         type = "BUFFER_STANDARD";
         break;
 #if defined(USE_X11)
-      case Clipboard::BUFFER_SELECTION:
+      case ui::Clipboard::BUFFER_SELECTION:
         type = "BUFFER_SELECTION";
         break;
 #endif
-      case Clipboard::BUFFER_DRAG:
+      case ui::Clipboard::BUFFER_DRAG:
         type = "BUFFER_DRAG";
         break;
       default:
@@ -544,22 +530,6 @@
   static void Log(const param_type& p, std::string* l);
 };
 
-template <>
-struct ParamTraits<speech_input::SpeechInputResultItem> {
-  typedef speech_input::SpeechInputResultItem param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<PP_Flash_NetAddress> {
-  typedef PP_Flash_NetAddress param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
 }  // namespace IPC
 
 #include "chrome/common/render_messages_internal.h"
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 9436e1a..b20dc5f 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,21 +15,19 @@
 #include "base/platform_file.h"
 #include "base/sync_socket.h"
 #include "chrome/common/content_settings.h"
+#include "chrome/common/extensions/extension.h"
 #include "chrome/common/geoposition.h"
 #include "chrome/common/nacl_types.h"
 #include "chrome/common/notification_type.h"
 #include "chrome/common/page_zoom.h"
-#include "chrome/common/speech_input_result.h"
 #include "chrome/common/translate_errors.h"
 #include "chrome/common/window_container_type.h"
 #include "ipc/ipc_message_macros.h"
 #include "media/audio/audio_buffers_state.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerAction.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
 #include "webkit/glue/context_menu.h"
-#include "webkit/glue/form_data.h"
-#include "webkit/glue/password_form_dom_manager.h"
 #include "webkit/glue/webdropdata.h"
 #include "webkit/plugins/npapi/webplugininfo.h"
 
@@ -51,7 +49,6 @@
 
 class Value;
 class GPUInfo;
-struct PP_Flash_NetAddress;
 class SkBitmap;
 struct ThumbnailScore;
 class WebCursor;
@@ -94,6 +91,10 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_SetCSSColors,
                     std::vector<CSSColors::CSSColorMapping>)
 
+// Asks the browser for a unique routing ID.
+IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GenerateRoutingID,
+                            int /* routing_id */)
+
 // Tells the renderer to create a new view.
 // This message is slightly different, the view it takes (via
 // ViewMsg_New_Params) is the view to create, the message itself is sent as a
@@ -126,6 +127,8 @@
                     gfx::Point, /* location */
                     WebKit::WebMediaPlayerAction)
 
+IPC_MESSAGE_ROUTED0(ViewMsg_PrintNodeUnderContextMenu)
+
 // Tells the render view to close.
 IPC_MESSAGE_ROUTED0(ViewMsg_Close)
 
@@ -214,7 +217,7 @@
 // Parameters
 // * edit_commands (see chrome/common/edit_command_types.h)
 //   Contains one or more edit commands.
-// See third_party/WebKit/WebCore/editing/EditorCommand.cpp for detailed
+// See third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp for detailed
 // definition of webkit edit commands.
 //
 // This message must be sent just before sending a key event.
@@ -354,7 +357,7 @@
 // Sent when the request has been completed.
 IPC_MESSAGE_ROUTED4(ViewMsg_Resource_RequestComplete,
                     int /* request_id */,
-                    URLRequestStatus /* status */,
+                    net::URLRequestStatus /* status */,
                     std::string /* security info */,
                     base::Time /* completion_time */)
 
@@ -461,15 +464,6 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_ReservePageIDRange,
                     int  /* size_of_range */)
 
-// Fill a form with data and optionally submit it
-IPC_MESSAGE_ROUTED1(ViewMsg_FormFill,
-                    webkit_glue::FormData /* form */)
-
-// Fill a password form and prepare field autocomplete for multiple
-// matching logins.
-IPC_MESSAGE_ROUTED1(ViewMsg_FillPasswordForm,
-                    webkit_glue::PasswordFormFillData)
-
 // D&d drop target messages.
 IPC_MESSAGE_ROUTED4(ViewMsg_DragTargetDragEnter,
                     WebDropData /* drop_data */,
@@ -502,9 +496,9 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_AllowBindings,
                     int /* enabled_bindings_flags */)
 
-// Tell the renderer to add a property to the DOMUI binding object.  This
-// only works if we allowed DOMUI bindings.
-IPC_MESSAGE_ROUTED2(ViewMsg_SetDOMUIProperty,
+// Tell the renderer to add a property to the WebUI binding object.  This
+// only works if we allowed WebUI bindings.
+IPC_MESSAGE_ROUTED2(ViewMsg_SetWebUIProperty,
                     std::string /* property_name */,
                     std::string /* property_value_json */)
 
@@ -561,6 +555,9 @@
 // Tells the render view to load all blocked plugins.
 IPC_MESSAGE_ROUTED0(ViewMsg_LoadBlockedPlugins)
 
+// Tells the render view a prerendered page is about to be displayed.
+IPC_MESSAGE_ROUTED0(ViewMsg_DisplayPrerenderedPage)
+
 IPC_MESSAGE_ROUTED1(ViewMsg_RunFileChooserResponse,
                     std::vector<FilePath> /* selected files */)
 
@@ -647,7 +644,7 @@
 IPC_MESSAGE_ROUTED0(ViewMsg_DisassociateFromPopupCount)
 
 // The browser sends this to a renderer process in response to a
-// ViewHostMsg_EstablishGpuChannel message.
+// GpuHostMsg_EstablishGpuChannel message.
 IPC_MESSAGE_CONTROL2(ViewMsg_GpuChannelEstablished,
                      IPC::ChannelHandle /* handle to channel */,
                      GPUInfo /* stats about GPU process*/)
@@ -692,21 +689,6 @@
                      int /* host_id */,
                      GURL /* manifest_url */)
 
-// Reply to the ViewHostMsg_QueryFormFieldAutoFill message with the
-// AutoFill suggestions.
-IPC_MESSAGE_ROUTED5(ViewMsg_AutoFillSuggestionsReturned,
-                    int /* id of the request message */,
-                    std::vector<string16> /* names */,
-                    std::vector<string16> /* labels */,
-                    std::vector<string16> /* icons */,
-                    std::vector<int> /* unique_ids */)
-
-// Reply to the ViewHostMsg_FillAutoFillFormData message with the
-// AutoFill form data.
-IPC_MESSAGE_ROUTED2(ViewMsg_AutoFillFormDataFilled,
-                    int /* id of the request message */,
-                    webkit_glue::FormData /* form data */)
-
 // Sent by the Browser process to alert a window about whether a it should
 // allow a scripted window.close(). The renderer assumes every new window is a
 // blocked popup until notified otherwise.
@@ -781,6 +763,10 @@
 IPC_MESSAGE_CONTROL1(ViewMsg_Extension_SetFunctionNames,
                      std::vector<std::string>)
 
+// TODO(aa): SetAPIPermissions, SetHostPermissions, and possibly
+// UpdatePageActions should be replaced with just sending additional data in
+// ExtensionLoaded. See: crbug.com/70516.
+
 // Tell the renderer process which permissions the given extension has. See
 // Extension::Permissions for which elements correspond to which permissions.
 IPC_MESSAGE_CONTROL2(ViewMsg_Extension_SetAPIPermissions,
@@ -799,6 +785,17 @@
                      std::string /* extension_id */,
                      std::vector<std::string> /* page_action_ids */)
 
+// Notifies the renderer that an extension was loaded in the browser.
+IPC_MESSAGE_CONTROL1(ViewMsg_ExtensionLoaded, ViewMsg_ExtensionLoaded_Params);
+
+// Notifies the renderer that an extension was unloaded in the browser.
+IPC_MESSAGE_CONTROL1(ViewMsg_ExtensionUnloaded, std::string);
+
+// Updates the scripting whitelist for extensions in the render process. This is
+// only used for testing.
+IPC_MESSAGE_CONTROL1(ViewMsg_Extension_SetScriptingWhitelist,
+                     Extension::ScriptingWhitelist /* extenison ids */);
+
 // Changes the text direction of the currently selected input field (if any).
 IPC_MESSAGE_ROUTED1(ViewMsg_SetTextDirection,
                     WebKit::WebTextDirection /* direction */)
@@ -822,19 +819,21 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_EnablePreferredSizeChangedMode, int /*flags*/)
 
 IPC_MESSAGE_ROUTED4(ViewMsg_SearchBoxChange,
-                    string16 /*value*/,
-                    bool /*verbatim*/,
-                    int /*selection_start*/,
-                    int /*selection_end*/)
+                    string16 /* value */,
+                    bool /* verbatim */,
+                    int /* selection_start */,
+                    int /* selection_end */)
 IPC_MESSAGE_ROUTED2(ViewMsg_SearchBoxSubmit,
-                    string16 /*value*/,
-                    bool /*verbatim*/)
+                    string16 /* value */,
+                    bool /* verbatim */)
 IPC_MESSAGE_ROUTED0(ViewMsg_SearchBoxCancel)
 IPC_MESSAGE_ROUTED1(ViewMsg_SearchBoxResize,
-                    gfx::Rect /*search_box_bounds*/)
-IPC_MESSAGE_ROUTED2(ViewMsg_DetermineIfPageSupportsInstant,
-                    string16 /*value*/,
-                    bool /* verbatim */)
+                    gfx::Rect /* search_box_bounds */)
+IPC_MESSAGE_ROUTED4(ViewMsg_DetermineIfPageSupportsInstant,
+                    string16 /* value*/,
+                    bool /* verbatim */,
+                    int /* selection_start */,
+                    int /* selection_end */)
 
 // Used to tell the renderer not to add scrollbars with height and
 // width below a threshold.
@@ -880,8 +879,8 @@
                     gfx::Rect /* window frame */,
                     gfx::Rect /* content view frame */)
 
-// Tell the renderer that text has been retured from plugin IME.
-IPC_MESSAGE_ROUTED2(ViewMsg_PluginImeCompositionConfirmed,
+// Tell the renderer that plugin IME has completed.
+IPC_MESSAGE_ROUTED2(ViewMsg_PluginImeCompositionCompleted,
                     string16 /* text */,
                     int /* plugin_id */)
 #endif
@@ -956,7 +955,8 @@
                      bool /* enable */)
 
 // Executes custom context menu action that was provided from WebKit.
-IPC_MESSAGE_ROUTED1(ViewMsg_CustomContextMenuAction,
+IPC_MESSAGE_ROUTED2(ViewMsg_CustomContextMenuAction,
+                    webkit_glue::CustomContextMenuContext /* custom_context */,
                     unsigned /* action */)
 
 // Tells the renderer to translate the page contents from one language to
@@ -990,10 +990,6 @@
 IPC_MESSAGE_CONTROL1(ViewMsg_SetIsIncognitoProcess,
                      bool /* is_incognito_processs */)
 
-// Notification that the list of extensions has been updated.
-IPC_MESSAGE_CONTROL1(ViewMsg_ExtensionsUpdated,
-                     ViewMsg_ExtensionsUpdated_Params)
-
 // Enable accessibility in the renderer process.
 IPC_MESSAGE_ROUTED0(ViewMsg_EnableAccessibility)
 
@@ -1010,22 +1006,6 @@
 // message was processed and it can send addition notifications.
 IPC_MESSAGE_ROUTED0(ViewMsg_AccessibilityNotifications_ACK)
 
-// Relay a speech recognition result, either partial or final.
-IPC_MESSAGE_ROUTED2(ViewMsg_SpeechInput_SetRecognitionResult,
-                    int /* request id */,
-                    speech_input::SpeechInputResultArray /* result */)
-
-// Indicate that speech recognizer has stopped recording and started
-// recognition.
-IPC_MESSAGE_ROUTED1(ViewMsg_SpeechInput_RecordingComplete,
-                    int /* request id */)
-
-// Indicate that speech recognizer has completed recognition. This will be
-// the last message sent in response to a
-// ViewHostMsg_SpeechInput_StartRecognition.
-IPC_MESSAGE_ROUTED1(ViewMsg_SpeechInput_RecognitionComplete,
-                    int /* request id */)
-
 // Notification that the device's orientation has changed.
 IPC_MESSAGE_ROUTED1(ViewMsg_DeviceOrientationUpdated,
                     ViewMsg_DeviceOrientationUpdated_Params)
@@ -1068,6 +1048,10 @@
 IPC_MESSAGE_CONTROL1(ViewMsg_SetPhishingModel,
                      IPC::PlatformFileForTransit /* model_file */)
 
+// Tells the renderer to begin phishing detection for the given toplevel URL
+// which it has started loading.
+IPC_MESSAGE_ROUTED1(ViewMsg_StartPhishingDetection, GURL)
+
 // External popup menus.
 IPC_MESSAGE_ROUTED1(ViewMsg_SelectPopupMenuItem,
                     int /* selected index, -1 means no selection */)
@@ -1076,12 +1060,10 @@
 IPC_MESSAGE_CONTROL1(ViewMsg_SpeechInput_SetFeatureEnabled,
                      bool /* enabled */)
 
-// The response to ViewHostMsg_PepperConnectTcp(Address).
-IPC_MESSAGE_ROUTED4(ViewMsg_PepperConnectTcpACK,
-                    int /* request_id */,
-                    IPC::PlatformFileForTransit /* socket */,
-                    PP_Flash_NetAddress /* local_addr */,
-                    PP_Flash_NetAddress /* remote_addr */)
+// Sent in response to a ViewHostMsg_ContextMenu to let the renderer know that
+// the menu has been closed.
+IPC_MESSAGE_ROUTED1(ViewMsg_ContextMenuClosed,
+                    webkit_glue::CustomContextMenuContext /* custom_context */)
 
 //-----------------------------------------------------------------------------
 // TabContents messages
@@ -1105,9 +1087,8 @@
 
 // Similar to ViewHostMsg_CreateWidget except the widget is a full screen
 // window.
-IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_CreateFullscreenWidget,
+IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_CreateFullscreenWidget,
                             int /* opener_id */,
-                            WebKit::WebPopupType /* popup type */,
                             int /* route_id */)
 
 // These three messages are sent to the parent RenderViewHost to display the
@@ -1240,8 +1221,9 @@
 IPC_MESSAGE_ROUTED0(ViewHostMsg_DidDisplayInsecureContent)
 
 // Sent when the renderer runs insecure content in a secure origin.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_DidRunInsecureContent,
-                    std::string  /* security_origin */)
+IPC_MESSAGE_ROUTED2(ViewHostMsg_DidRunInsecureContent,
+                    std::string  /* security_origin */,
+                    GURL         /* target URL */);
 
 // Sent when the renderer starts a provisional load for a frame.
 IPC_MESSAGE_ROUTED3(ViewHostMsg_DidStartProvisionalLoadForFrame,
@@ -1394,7 +1376,8 @@
 // |actual_mime_type| is the actual mime type supported by the
 // plugin found that match the URL given (one for each item in
 // |info|).
-IPC_SYNC_MESSAGE_CONTROL3_4(ViewHostMsg_GetPluginInfo,
+IPC_SYNC_MESSAGE_CONTROL4_4(ViewHostMsg_GetPluginInfo,
+                            int /* routing_id */,
                             GURL /* url */,
                             GURL /* policy_url */,
                             std::string /* mime_type */,
@@ -1524,7 +1507,7 @@
 
 // A message from HTML-based UI.  When (trusted) Javascript calls
 // send(message, args), this message is sent to the browser.
-IPC_MESSAGE_ROUTED3(ViewHostMsg_DOMUISend,
+IPC_MESSAGE_ROUTED3(ViewHostMsg_WebUISend,
                     GURL /* source_url */,
                     std::string  /* message */,
                     std::string  /* args (as a JSON string) */)
@@ -1539,7 +1522,8 @@
 // create a plugin.  The browser will create the plugin process if
 // necessary, and will return a handle to the channel on success.
 // On error an empty string is returned.
-IPC_SYNC_MESSAGE_CONTROL2_2(ViewHostMsg_OpenChannelToPlugin,
+IPC_SYNC_MESSAGE_CONTROL3_2(ViewHostMsg_OpenChannelToPlugin,
+                            int /* routing_id */,
                             GURL /* url */,
                             std::string /* mime_type */,
                             IPC::ChannelHandle /* channel_handle */,
@@ -1554,17 +1538,6 @@
                             base::ProcessHandle /* plugin_process_handle */,
                             IPC::ChannelHandle /* handle to channel */)
 
-// A renderer sends this to the browser process when it wants to
-// create connect to the GPU.  The browser will create the GPU process if
-// necessary, and will return a handle to the channel via
-// a GpuChannelEstablished message.
-IPC_MESSAGE_CONTROL0(ViewHostMsg_EstablishGpuChannel)
-
-// A renderer sends this to the browser process to provide a synchronization
-// point for GPU operations, in particular to make sure the GPU channel has
-// been established.
-IPC_SYNC_MESSAGE_CONTROL0_0(ViewHostMsg_SynchronizeGpu)
-
 // A renderer sends this to the browser process when it wants to start
 // a new instance of the Native Client process. The browser will launch
 // the process and return a handle to an IMC channel.
@@ -1594,41 +1567,41 @@
 
 // This message is used when the object list does not contain a bitmap.
 IPC_MESSAGE_CONTROL1(ViewHostMsg_ClipboardWriteObjectsAsync,
-    Clipboard::ObjectMap /* objects */)
+    ui::Clipboard::ObjectMap /* objects */)
 // This message is used when the object list contains a bitmap.
 // It is synchronized so that the renderer knows when it is safe to
 // free the shared memory used to transfer the bitmap.
 IPC_SYNC_MESSAGE_CONTROL2_0(ViewHostMsg_ClipboardWriteObjectsSync,
-    Clipboard::ObjectMap /* objects */,
+    ui::Clipboard::ObjectMap /* objects */,
     base::SharedMemoryHandle /* bitmap handle */)
 IPC_SYNC_MESSAGE_CONTROL2_1(ViewHostMsg_ClipboardIsFormatAvailable,
                             std::string /* format */,
-                            Clipboard::Buffer /* buffer */,
+                            ui::Clipboard::Buffer /* buffer */,
                             bool /* result */)
 IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_ClipboardReadText,
-                            Clipboard::Buffer /* buffer */,
+                            ui::Clipboard::Buffer /* buffer */,
                             string16 /* result */)
 IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_ClipboardReadAsciiText,
-                            Clipboard::Buffer  /* buffer */,
+                            ui::Clipboard::Buffer  /* buffer */,
                             std::string /* result */)
 IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ClipboardReadHTML,
-                            Clipboard::Buffer  /* buffer */,
+                            ui::Clipboard::Buffer  /* buffer */,
                             string16 /* markup */,
                             GURL /* url */)
 
 IPC_SYNC_MESSAGE_CONTROL1_3(ViewHostMsg_ClipboardReadAvailableTypes,
-                            Clipboard::Buffer /* buffer */,
+                            ui::Clipboard::Buffer /* buffer */,
                             bool /* result */,
                             std::vector<string16> /* types */,
                             bool /* contains filenames */)
 IPC_SYNC_MESSAGE_CONTROL2_3(ViewHostMsg_ClipboardReadData,
-                            Clipboard::Buffer /* buffer */,
+                            ui::Clipboard::Buffer /* buffer */,
                             string16 /* type */,
                             bool /* succeeded */,
                             string16 /* data */,
                             string16 /* metadata */)
 IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ClipboardReadFilenames,
-                            Clipboard::Buffer /* buffer */,
+                            ui::Clipboard::Buffer /* buffer */,
                             bool /* result */,
                             std::vector<string16> /* filenames */)
 
@@ -1671,25 +1644,6 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_RunFileChooser,
                     ViewHostMsg_RunFileChooser_Params)
 
-// Notification that forms have been seen that are candidates for
-// filling/submitting by the AutoFillManager.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_FormsSeen,
-                    std::vector<webkit_glue::FormData> /* forms */)
-
-// Notification that password forms have been seen that are candidates for
-// filling/submitting by the password manager.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_PasswordFormsFound,
-                    std::vector<webkit_glue::PasswordForm> /* forms */)
-
-// Notification that initial layout has occurred and the following password
-// forms are visible on the page (e.g. not set to display:none.)
-IPC_MESSAGE_ROUTED1(ViewHostMsg_PasswordFormsVisible,
-                    std::vector<webkit_glue::PasswordForm> /* forms */)
-
-// Notification that a form has been submitted.  The user hit the button.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_FormSubmitted,
-                    webkit_glue::FormData /* form */)
-
 // Used to tell the parent the user started dragging in the content area. The
 // WebDropData struct contains contextual information about the pieces of the
 // page the user dragged. The parent uses this notification to initiate a
@@ -2034,35 +1988,6 @@
                             std::vector<appcache::AppCacheResourceInfo>
                             /* resources out */)
 
-// Queries the browser for AutoFill suggestions for a form input field.
-IPC_MESSAGE_ROUTED3(ViewHostMsg_QueryFormFieldAutoFill,
-                    int /* id of this message */,
-                    webkit_glue::FormData /* the form */,
-                    webkit_glue::FormField /* the form field */)
-
-// Sent when the popup with AutoFill suggestions for a form is shown.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_DidShowAutoFillSuggestions)
-
-// Instructs the browser to fill in the values for a form using AutoFill
-// profile data.
-IPC_MESSAGE_ROUTED4(ViewHostMsg_FillAutoFillFormData,
-                    int /* id of this message */,
-                    webkit_glue::FormData /* the form  */,
-                    webkit_glue::FormField /* the form field  */,
-                    int /* profile unique ID */)
-
-// Sent when a form is previewed or filled with AutoFill suggestions.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_DidFillAutoFillFormData)
-
-// Instructs the browser to remove the specified Autocomplete entry from the
-// database.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_RemoveAutocompleteEntry,
-                    string16 /* field name */,
-                    string16 /* value */)
-
-// Instructs the browser to show the AutoFill dialog.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_ShowAutoFillDialog)
-
 // Get the list of proxies to use for |url|, as a semicolon delimited list
 // of "<TYPE> <HOST>:<PORT>" | "DIRECT". See also
 // PluginProcessHostMsg_ResolveProxy which does the same thing.
@@ -2126,6 +2051,14 @@
                      std::string /* extension_id */,
                      std::string /* name */)
 
+// Message sent from renderer to the browser to update the state of a command.
+// The |command| parameter is a RenderViewCommand. The |checked_state| parameter
+// is a CommandCheckedState.
+IPC_MESSAGE_ROUTED3(ViewHostMsg_CommandStateChanged,
+                    int /* command */,
+                    bool /* is_enabled */,
+                    int /* checked_state */)
+
 #if defined(OS_MACOSX)
 // On OSX, we cannot allocated shared memory from within the sandbox, so
 // this call exists for the renderer to ask the browser to allocate memory
@@ -2146,11 +2079,14 @@
 IPC_MESSAGE_CONTROL1(ViewHostMsg_FreeTransportDIB,
                      TransportDIB::Id /* DIB id */)
 
-// Instructs the browser to start or stop plugin IME.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_SetPluginImeEnabled,
-                    bool, /* enabled */
+// Informs the browser that a plugin has gained or lost focus.
+IPC_MESSAGE_ROUTED2(ViewHostMsg_PluginFocusChanged,
+                    bool, /* focused */
                     int /* plugin_id */)
 
+// Instructs the browser to start plugin IME.
+IPC_MESSAGE_ROUTED0(ViewHostMsg_StartPluginIme)
+
 //---------------------------------------------------------------------------
 // Messages related to accelerated plugins
 
@@ -2239,7 +2175,7 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowDesktopNotification,
                     ViewHostMsg_ShowNotification_Params)
 IPC_MESSAGE_ROUTED1(ViewHostMsg_CancelDesktopNotification,
-                    int /* notification_id */ )
+                    int /* notification_id */)
 IPC_MESSAGE_ROUTED2(ViewHostMsg_RequestNotificationPermission,
                     GURL /* origin */,
                     int /* callback_context */)
@@ -2449,30 +2385,6 @@
                     int /* maximum_percent */,
                     bool /* remember */)
 
-// Requests the speech input service to start speech recognition on behalf of
-// the given |render_view_id|.
-IPC_MESSAGE_CONTROL5(ViewHostMsg_SpeechInput_StartRecognition,
-                     int /* render_view_id */,
-                     int /* request_id */,
-                     gfx::Rect /* element_rect */,
-                     std::string /* language */,
-                     std::string /* grammar */)
-
-// Requests the speech input service to cancel speech recognition on behalf of
-// the given |render_view_id|. If speech recognition is not happening nor or
-// is happening on behalf of some other render view, this call does nothing.
-IPC_MESSAGE_CONTROL2(ViewHostMsg_SpeechInput_CancelRecognition,
-                     int /* render_view_id */,
-                     int /* request id */)
-
-// Requests the speech input service to stop audio recording on behalf of
-// the given |render_view_id|. Any audio recorded so far will be fed to the
-// speech recognizer. If speech recognition is not happening nor or is
-// happening on behalf of some other render view, this call does nothing.
-IPC_MESSAGE_CONTROL2(ViewHostMsg_SpeechInput_StopRecording,
-                     int /* render_view_id */,
-                     int /* request id */)
-
 //---------------------------------------------------------------------------
 // Device orientation services messages:
 
@@ -2593,10 +2505,9 @@
 // Client-Side Phishing Detector ---------------------------------------------
 // Inform the browser that the current URL is phishing according to the
 // client-side phishing detector.
-IPC_MESSAGE_ROUTED3(ViewHostMsg_DetectedPhishingSite,
+IPC_MESSAGE_ROUTED2(ViewHostMsg_DetectedPhishingSite,
                     GURL /* phishing_url */,
-                    double /* phishing_score */,
-                    SkBitmap /* thumbnail */)
+                    double /* phishing_score */)
 
 // Response from ViewMsg_ScriptEvalRequest. The ID is the parameter supplied
 // to ViewMsg_ScriptEvalRequest. The result has the value returned by the
@@ -2610,15 +2521,13 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateContentRestrictions,
                     int /* restrictions */)
 
-// Pepper-related messages -----------------------------------------------------
+// The currently displayed PDF has an unsupported feature.
+IPC_MESSAGE_ROUTED0(ViewHostMsg_PDFHasUnsupportedFeature)
 
-IPC_MESSAGE_CONTROL4(ViewHostMsg_PepperConnectTcp,
-                     int /* routing_id */,
-                     int /* request_id */,
-                     std::string /* host */,
-                     uint16 /* port */)
+// JavaScript related messages -----------------------------------------------
 
-IPC_MESSAGE_CONTROL3(ViewHostMsg_PepperConnectTcpAddress,
-                     int /* routing_id */,
-                     int /* request_id */,
-                     PP_Flash_NetAddress /* addr */)
+// Notify the JavaScript engine in the render to change its parameters
+// while performing stress testing.
+IPC_MESSAGE_ROUTED2(ViewMsg_JavaScriptStressTestControl,
+                    int /* cmd */,
+                    int /* param */)
diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc
index 7fab193..3362704 100644
--- a/chrome/common/render_messages_params.cc
+++ b/chrome/common/render_messages_params.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/common/navigation_gesture.h"
 #include "chrome/common/common_param_traits.h"
+#include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/render_messages.h"
 #include "net/base/upload_data.h"
 
@@ -60,7 +61,7 @@
 
 ViewHostMsg_Resource_Request::ViewHostMsg_Resource_Request()
     : load_flags(0),
-      origin_child_id(0),
+      origin_pid(0),
       resource_type(ResourceType::MAIN_FRAME),
       request_context(0),
       appcache_host_id(0),
@@ -81,7 +82,8 @@
       max_shrink(0),
       desired_dpi(0),
       document_cookie(0),
-      selection_only(false) {
+      selection_only(false),
+      supports_alpha_blend(true) {
 }
 
 ViewMsg_Print_Params::~ViewMsg_Print_Params() {
@@ -96,13 +98,15 @@
          min_shrink == rhs.min_shrink &&
          max_shrink == rhs.max_shrink &&
          desired_dpi == rhs.desired_dpi &&
-         selection_only == rhs.selection_only;
+         selection_only == rhs.selection_only &&
+         supports_alpha_blend == rhs.supports_alpha_blend;
 }
 
 bool ViewMsg_Print_Params::IsEmpty() const {
   return !document_cookie && !desired_dpi && !max_shrink && !min_shrink &&
          !dpi && printable_size.IsEmpty() && !selection_only &&
-         page_size.IsEmpty() && !margin_top && !margin_left;
+         page_size.IsEmpty() && !margin_top && !margin_left &&
+         !supports_alpha_blend;
 }
 
 ViewMsg_PrintPage_Params::ViewMsg_PrintPage_Params()
@@ -231,7 +235,8 @@
     : opener_id(0),
       user_gesture(false),
       window_container_type(WINDOW_CONTAINER_TYPE_NORMAL),
-      session_storage_namespace_id(0) {
+      session_storage_namespace_id(0),
+      opener_frame_id(0) {
 }
 
 ViewHostMsg_CreateWindow_Params::~ViewHostMsg_CreateWindow_Params() {
@@ -244,20 +249,6 @@
 ViewHostMsg_RunFileChooser_Params::~ViewHostMsg_RunFileChooser_Params() {
 }
 
-ViewMsg_ExtensionRendererInfo::ViewMsg_ExtensionRendererInfo()
-    : location(Extension::INVALID),
-      allowed_to_execute_script_everywhere(false) {
-}
-
-ViewMsg_ExtensionRendererInfo::~ViewMsg_ExtensionRendererInfo() {
-}
-
-ViewMsg_ExtensionsUpdated_Params::ViewMsg_ExtensionsUpdated_Params() {
-}
-
-ViewMsg_ExtensionsUpdated_Params::~ViewMsg_ExtensionsUpdated_Params() {
-}
-
 ViewMsg_DeviceOrientationUpdated_Params::
     ViewMsg_DeviceOrientationUpdated_Params()
     : can_provide_alpha(false),
@@ -281,6 +272,59 @@
 ViewHostMsg_DomMessage_Params::~ViewHostMsg_DomMessage_Params() {
 }
 
+ViewMsg_ExtensionLoaded_Params::ViewMsg_ExtensionLoaded_Params() {
+}
+
+ViewMsg_ExtensionLoaded_Params::~ViewMsg_ExtensionLoaded_Params() {
+}
+
+ViewMsg_ExtensionLoaded_Params::ViewMsg_ExtensionLoaded_Params(
+    const ViewMsg_ExtensionLoaded_Params& other)
+    : manifest(other.manifest->DeepCopy()),
+      location(other.location),
+      path(other.path),
+      id(other.id) {
+}
+
+ViewMsg_ExtensionLoaded_Params::ViewMsg_ExtensionLoaded_Params(
+    const Extension* extension)
+    : manifest(new DictionaryValue()),
+      location(extension->location()),
+      path(extension->path()),
+      id(extension->id()) {
+  // As we need more bits of extension data in the renderer, add more keys to
+  // this list.
+  const char* kRendererExtensionKeys[] = {
+    extension_manifest_keys::kPublicKey,
+    extension_manifest_keys::kName,
+    extension_manifest_keys::kVersion,
+    extension_manifest_keys::kIcons,
+    extension_manifest_keys::kPermissions,
+    extension_manifest_keys::kApp
+  };
+
+  // Copy only the data we need.
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRendererExtensionKeys); ++i) {
+    Value* temp = NULL;
+    if (extension->manifest_value()->Get(kRendererExtensionKeys[i], &temp))
+      manifest->Set(kRendererExtensionKeys[i], temp->DeepCopy());
+  }
+}
+
+scoped_refptr<Extension>
+    ViewMsg_ExtensionLoaded_Params::ConvertToExtension() const {
+  // Extensions that are loaded unpacked won't have a key.
+  const bool kRequireKey = false;
+  std::string error;
+
+  scoped_refptr<Extension> extension(
+      Extension::Create(path, location, *manifest, kRequireKey, &error));
+  if (!extension.get())
+    LOG(ERROR) << "Error deserializing extension: " << error;
+
+  return extension;
+}
+
 namespace IPC {
 
 // Self contained templates which are only used inside serializing Params
@@ -313,6 +357,10 @@
         event = "NavigationType_RESTORE";
         break;
 
+      case ViewMsg_Navigate_Params::PRERENDER:
+        event = "NavigationType_PRERENDER";
+        break;
+
       case ViewMsg_Navigate_Params::NORMAL:
         event = "NavigationType_NORMA";
         break;
@@ -783,6 +831,7 @@
   WriteParam(m, p.dx);
   WriteParam(m, p.dy);
   WriteParam(m, p.scroll_rect);
+  WriteParam(m, p.scroll_offset);
   WriteParam(m, p.copy_rects);
   WriteParam(m, p.view_size);
   WriteParam(m, p.resizer_rect);
@@ -798,6 +847,7 @@
       ReadParam(m, iter, &p->dx) &&
       ReadParam(m, iter, &p->dy) &&
       ReadParam(m, iter, &p->scroll_rect) &&
+      ReadParam(m, iter, &p->scroll_offset) &&
       ReadParam(m, iter, &p->copy_rects) &&
       ReadParam(m, iter, &p->view_size) &&
       ReadParam(m, iter, &p->resizer_rect) &&
@@ -874,7 +924,7 @@
   WriteParam(m, p.main_frame_origin);
   WriteParam(m, p.headers);
   WriteParam(m, p.load_flags);
-  WriteParam(m, p.origin_child_id);
+  WriteParam(m, p.origin_pid);
   WriteParam(m, p.resource_type);
   WriteParam(m, p.request_context);
   WriteParam(m, p.appcache_host_id);
@@ -897,7 +947,7 @@
       ReadParam(m, iter, &r->main_frame_origin) &&
       ReadParam(m, iter, &r->headers) &&
       ReadParam(m, iter, &r->load_flags) &&
-      ReadParam(m, iter, &r->origin_child_id) &&
+      ReadParam(m, iter, &r->origin_pid) &&
       ReadParam(m, iter, &r->resource_type) &&
       ReadParam(m, iter, &r->request_context) &&
       ReadParam(m, iter, &r->appcache_host_id) &&
@@ -923,7 +973,7 @@
   l->append(", ");
   LogParam(p.load_flags, l);
   l->append(", ");
-  LogParam(p.origin_child_id, l);
+  LogParam(p.origin_pid, l);
   l->append(", ");
   LogParam(p.resource_type, l);
   l->append(", ");
@@ -952,6 +1002,7 @@
   WriteParam(m, p.desired_dpi);
   WriteParam(m, p.document_cookie);
   WriteParam(m, p.selection_only);
+  WriteParam(m, p.supports_alpha_blend);
 }
 
 bool ParamTraits<ViewMsg_Print_Params>::Read(const Message* m,
@@ -966,7 +1017,8 @@
       ReadParam(m, iter, &p->max_shrink) &&
       ReadParam(m, iter, &p->desired_dpi) &&
       ReadParam(m, iter, &p->document_cookie) &&
-      ReadParam(m, iter, &p->selection_only);
+      ReadParam(m, iter, &p->selection_only) &&
+      ReadParam(m, iter, &p->supports_alpha_blend);
 }
 
 void ParamTraits<ViewMsg_Print_Params>::Log(const param_type& p,
@@ -1345,6 +1397,10 @@
   WriteParam(m, p.window_container_type);
   WriteParam(m, p.session_storage_namespace_id);
   WriteParam(m, p.frame_name);
+  WriteParam(m, p.opener_frame_id);
+  WriteParam(m, p.opener_url);
+  WriteParam(m, p.opener_security_origin);
+  WriteParam(m, p.target_url);
 }
 
 bool ParamTraits<ViewHostMsg_CreateWindow_Params>::Read(const Message* m,
@@ -1355,7 +1411,11 @@
       ReadParam(m, iter, &p->user_gesture) &&
       ReadParam(m, iter, &p->window_container_type) &&
       ReadParam(m, iter, &p->session_storage_namespace_id) &&
-      ReadParam(m, iter, &p->frame_name);
+      ReadParam(m, iter, &p->frame_name) &&
+      ReadParam(m, iter, &p->opener_frame_id) &&
+      ReadParam(m, iter, &p->opener_url) &&
+      ReadParam(m, iter, &p->opener_security_origin) &&
+      ReadParam(m, iter, &p->target_url);
 }
 
 void ParamTraits<ViewHostMsg_CreateWindow_Params>::Log(const param_type& p,
@@ -1370,6 +1430,14 @@
   LogParam(p.session_storage_namespace_id, l);
   l->append(", ");
   LogParam(p.frame_name, l);
+  l->append(", ");
+  LogParam(p.opener_frame_id, l);
+  l->append(", ");
+  LogParam(p.opener_url, l);
+  l->append(", ");
+  LogParam(p.opener_security_origin, l);
+  l->append(", ");
+  LogParam(p.target_url, l);
   l->append(")");
 }
 
@@ -1427,51 +1495,25 @@
   LogParam(p.accept_types, l);
 }
 
-void ParamTraits<ViewMsg_ExtensionRendererInfo>::Write(Message* m,
-                                                       const param_type& p) {
-  WriteParam(m, p.id);
-  WriteParam(m, p.web_extent);
-  WriteParam(m, p.name);
-  WriteParam(m, p.icon_url);
+void ParamTraits<ViewMsg_ExtensionLoaded_Params>::Write(Message* m,
+                                                        const param_type& p) {
   WriteParam(m, p.location);
-  WriteParam(m, p.allowed_to_execute_script_everywhere);
-  WriteParam(m, p.host_permissions);
+  WriteParam(m, p.path);
+  WriteParam(m, *(p.manifest));
 }
 
-bool ParamTraits<ViewMsg_ExtensionRendererInfo>::Read(const Message* m,
-                                                      void** iter,
-                                                      param_type* p) {
-  return ReadParam(m, iter, &p->id) &&
-      ReadParam(m, iter, &p->web_extent) &&
-      ReadParam(m, iter, &p->name) &&
-      ReadParam(m, iter, &p->icon_url) &&
-      ReadParam(m, iter, &p->location) &&
-      ReadParam(m, iter, &p->allowed_to_execute_script_everywhere) &&
-      ReadParam(m, iter, &p->host_permissions);
+bool ParamTraits<ViewMsg_ExtensionLoaded_Params>::Read(const Message* m,
+                                                       void** iter,
+                                                       param_type* p) {
+  p->manifest.reset(new DictionaryValue());
+  return ReadParam(m, iter, &p->location) &&
+         ReadParam(m, iter, &p->path) &&
+         ReadParam(m, iter, p->manifest.get());
 }
 
-void ParamTraits<ViewMsg_ExtensionRendererInfo>::Log(const param_type& p,
-                                                     std::string* l) {
-  LogParam(p.id, l);
-}
-
-void ParamTraits<ViewMsg_ExtensionsUpdated_Params>::Write(
-    Message* m,
-    const param_type& p) {
-  WriteParam(m, p.extensions);
-}
-
-bool ParamTraits<ViewMsg_ExtensionsUpdated_Params>::Read(
-    const Message* m,
-    void** iter,
-    param_type* p) {
-  return ReadParam(m, iter, &p->extensions);
-}
-
-void ParamTraits<ViewMsg_ExtensionsUpdated_Params>::Log(
-    const param_type& p,
-    std::string* l) {
-  LogParam(p.extensions, l);
+void ParamTraits<ViewMsg_ExtensionLoaded_Params>::Log(const param_type& p,
+                                                      std::string* l) {
+  l->append(p.id);
 }
 
 void ParamTraits<ViewMsg_DeviceOrientationUpdated_Params>::Write(
diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h
index 97817d2..7bf95e0 100644
--- a/chrome/common/render_messages_params.h
+++ b/chrome/common/render_messages_params.h
@@ -25,12 +25,12 @@
 #include "chrome/common/renderer_preferences.h"
 #include "chrome/common/serialized_script_value.h"
 #include "chrome/common/window_container_type.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_param_traits.h"
 #include "media/audio/audio_parameters.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "webkit/glue/password_form.h"
 #include "webkit/glue/resource_type.h"
 #include "webkit/glue/webaccessibility.h"
@@ -62,6 +62,9 @@
     // the page's cache policy is ignored and we load from the cache.
     RESTORE,
 
+    // Speculatively prerendering the page.
+    PRERENDER,
+
     // Navigation type not categorized by the other types.
     NORMAL
   };
@@ -341,6 +344,9 @@
   // The rectangular region to scroll.
   gfx::Rect scroll_rect;
 
+  // The scroll offset of the render view.
+  gfx::Size scroll_offset;
+
   // The regions of the bitmap (in view coords) that contain updated pixels.
   // In the case of scrolling, this includes the scroll damage rect.
   std::vector<gfx::Rect> copy_rects;
@@ -450,16 +456,15 @@
   // net::URLRequest load flags (0 by default).
   int load_flags;
 
-  // Unique ID of process that originated this request. For normal renderer
-  // requests, this will be the ID of the renderer. For plugin requests routed
-  // through the renderer, this will be the plugin's ID.
-  int origin_child_id;
+  // Process ID from which this request originated, or zero if it originated
+  // in the renderer itself.
+  int origin_pid;
 
   // What this resource load is for (main frame, sub-frame, sub-resource,
   // object).
   ResourceType::Type resource_type;
 
-  // Used by plugin->browser requests to get the correct URLRequestContext.
+  // Used by plugin->browser requests to get the correct net::URLRequestContext.
   uint32 request_context;
 
   // Indicates which frame (or worker context) the request is being loaded into,
@@ -520,6 +525,9 @@
   // Should only print currently selected text.
   bool selection_only;
 
+  // Does the printer support alpha blending?
+  bool supports_alpha_blend;
+
   // Warning: do not compare document_cookie.
   bool Equals(const ViewMsg_Print_Params& rhs) const;
 
@@ -552,7 +560,7 @@
   std::vector<int> pages;
 };
 
-//Parameters to describe a rendered document.
+// Parameters to describe a rendered document.
 struct ViewHostMsg_DidPreviewDocument_Params {
   ViewHostMsg_DidPreviewDocument_Params();
   ~ViewHostMsg_DidPreviewDocument_Params();
@@ -778,6 +786,19 @@
   // The name of the resulting frame that should be created (empty if none
   // has been specified).
   string16 frame_name;
+
+  // The frame identifier of the frame initiating the open.
+  int64 opener_frame_id;
+
+  // The URL of the frame initiating the open.
+  GURL opener_url;
+
+  // The security origin of the frame initiating the open.
+  std::string opener_security_origin;
+
+  // The URL that will be loaded in the new window (empty if none has been
+  // sepcified).
+  GURL target_url;
 };
 
 struct ViewHostMsg_RunFileChooser_Params {
@@ -813,25 +834,31 @@
   string16 accept_types;
 };
 
-struct ViewMsg_ExtensionRendererInfo {
-  ViewMsg_ExtensionRendererInfo();
-  ~ViewMsg_ExtensionRendererInfo();
+struct ViewMsg_ExtensionLoaded_Params {
+  ViewMsg_ExtensionLoaded_Params();
+  ~ViewMsg_ExtensionLoaded_Params();
+  explicit ViewMsg_ExtensionLoaded_Params(const Extension* extension);
 
-  std::string id;
-  ExtensionExtent web_extent;
-  std::string name;
-  GURL icon_url;
+  // A copy constructor is needed because this structure can end up getting
+  // copied inside the IPC machinery on gcc <= 4.2.
+  ViewMsg_ExtensionLoaded_Params(
+      const ViewMsg_ExtensionLoaded_Params& other);
+
+  // Creates a new extension from the data in this object.
+  scoped_refptr<Extension> ConvertToExtension() const;
+
+  // The subset of the extension manifest data we send to renderers.
+  scoped_ptr<DictionaryValue> manifest;
+
+  // The location the extension was installed from.
   Extension::Location location;
-  bool allowed_to_execute_script_everywhere;
-  std::vector<URLPattern> host_permissions;
-};
 
-struct ViewMsg_ExtensionsUpdated_Params {
-  ViewMsg_ExtensionsUpdated_Params();
-  ~ViewMsg_ExtensionsUpdated_Params();
+  // The path the extension was loaded from. This is used in the renderer only
+  // to generate the extension ID for extensions that are loaded unpacked.
+  FilePath path;
 
-  // Describes the installed extension apps and the URLs they cover.
-  std::vector<ViewMsg_ExtensionRendererInfo> extensions;
+  // We keep this separate so that it can be used in logging.
+  std::string id;
 };
 
 struct ViewMsg_DeviceOrientationUpdated_Params {
@@ -1089,16 +1116,8 @@
 };
 
 template <>
-struct ParamTraits<ViewMsg_ExtensionRendererInfo> {
-  typedef ViewMsg_ExtensionRendererInfo param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, void** iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<ViewMsg_ExtensionsUpdated_Params> {
-  typedef ViewMsg_ExtensionsUpdated_Params param_type;
+struct ParamTraits<ViewMsg_ExtensionLoaded_Params> {
+  typedef ViewMsg_ExtensionLoaded_Params param_type;
   static void Write(Message* m, const param_type& p);
   static bool Read(const Message* m, void** iter, param_type* p);
   static void Log(const param_type& p, std::string* l);
diff --git a/chrome/common/render_messages_unittest.cc b/chrome/common/render_messages_unittest.cc
index b24efde..dea3146 100644
--- a/chrome/common/render_messages_unittest.cc
+++ b/chrome/common/render_messages_unittest.cc
@@ -9,7 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/glue/web_io_operators.h"
 #include "webkit/glue/webaccessibility.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
 
 TEST(RenderMessagesUnittest, WebAccessibility) {
   // Test a simple case.
diff --git a/chrome/common/render_view_commands.h b/chrome/common/render_view_commands.h
new file mode 100644
index 0000000..541e7ea
--- /dev/null
+++ b/chrome/common/render_view_commands.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_COMMON_RENDER_VIEW_COMMANDS_H_
+#define CHROME_COMMON_RENDER_VIEW_COMMANDS_H_
+#pragma once
+
+// These identify commands that the renderer process enables or disables
+// in the browser process. For example, this is used on the Mac to keep
+// the spell check menu commands in sync with the renderer state.
+enum RenderViewCommand {
+  RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK,
+};
+
+enum RenderViewCommandCheckedState {
+  RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED,
+  RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED,
+  RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED,
+};
+
+
+#endif  // CHROME_COMMON_RENDER_VIEW_COMMANDS_H_
diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc
index e4747b9..86321b5 100644
--- a/chrome/common/resource_dispatcher.cc
+++ b/chrome/common/resource_dispatcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -106,7 +106,7 @@
   request_.main_frame_origin = request_info.main_frame_origin;
   request_.headers = request_info.headers;
   request_.load_flags = request_info.load_flags;
-  request_.origin_child_id = request_info.requestor_pid;
+  request_.origin_pid = request_info.requestor_pid;
   request_.resource_type = request_info.request_type;
   request_.request_context = request_info.request_context;
   request_.appcache_host_id = request_info.appcache_host_id;
@@ -213,7 +213,7 @@
 void IPCResourceLoaderBridge::SyncLoad(SyncLoadResponse* response) {
   if (request_id_ != -1) {
     NOTREACHED() << "Starting a request twice";
-    response->status.set_status(URLRequestStatus::FAILED);
+    response->status.set_status(net::URLRequestStatus::FAILED);
     return;
   }
 
@@ -224,7 +224,7 @@
                                                    request_, &result);
   // NOTE: This may pump events (see RenderThread::Send).
   if (!dispatcher_->message_sender()->Send(msg)) {
-    response->status.set_status(URLRequestStatus::FAILED);
+    response->status.set_status(net::URLRequestStatus::FAILED);
     return;
   }
 
@@ -402,6 +402,11 @@
   if (request_info->peer->OnReceivedRedirect(new_url, info,
                                             &has_new_first_party_for_cookies,
                                             &new_first_party_for_cookies)) {
+    // Double-check if the request is still around. The call above could
+    // potentially remove it.
+    request_info = GetPendingRequestInfo(request_id);
+    if (!request_info)
+      return;
     request_info->pending_redirect_message.reset(
         new ViewHostMsg_FollowRedirect(routing_id, request_id,
                                        has_new_first_party_for_cookies,
@@ -423,7 +428,7 @@
 }
 
 void ResourceDispatcher::OnRequestComplete(int request_id,
-                                           const URLRequestStatus& status,
+                                           const net::URLRequestStatus& status,
                                            const std::string& security_info,
                                            const base::Time& completion_time) {
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
@@ -432,7 +437,7 @@
 
   webkit_glue::ResourceLoaderBridge::Peer* peer = request_info->peer;
 
-  if (status.status() == URLRequestStatus::CANCELED &&
+  if (status.status() == net::URLRequestStatus::CANCELED &&
       status.os_error() != net::ERR_ABORTED) {
     // Resource canceled with a specific error are filtered.
     SecurityFilterPeer* new_peer =
diff --git a/chrome/common/resource_dispatcher.h b/chrome/common/resource_dispatcher.h
index 823af81..c9c4be5 100644
--- a/chrome/common/resource_dispatcher.h
+++ b/chrome/common/resource_dispatcher.h
@@ -29,7 +29,7 @@
   ~ResourceDispatcher();
 
   // IPC::Channel::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& message);
+  virtual bool OnMessageReceived(const IPC::Message& message);
 
   // Creates a ResourceLoaderBridge for this type of dispatcher, this is so
   // this can be tested regardless of the ResourceLoaderBridge::Create
diff --git a/chrome/common/resource_dispatcher_unittest.cc b/chrome/common/resource_dispatcher_unittest.cc
index e5d6dfd..3e846f9 100644
--- a/chrome/common/resource_dispatcher_unittest.cc
+++ b/chrome/common/resource_dispatcher_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -64,7 +64,7 @@
     data_.append(data, len);
   }
 
-  virtual void OnCompletedRequest(const URLRequestStatus& status,
+  virtual void OnCompletedRequest(const net::URLRequestStatus& status,
                                   const std::string& security_info,
                                   const base::Time& completion_time) {
     EXPECT_FALSE(complete_);
@@ -231,7 +231,7 @@
     set_defer_loading(true);
 
     ResourceResponseHead response_head;
-    response_head.status.set_status(URLRequestStatus::SUCCESS);
+    response_head.status.set_status(net::URLRequestStatus::SUCCESS);
 
     IPC::Message* response_message =
         new ViewMsg_Resource_ReceivedResponse(0, 0, response_head);
@@ -284,7 +284,7 @@
     set_defer_loading(false);
   }
 
-  virtual void OnCompletedRequest(const URLRequestStatus& status,
+  virtual void OnCompletedRequest(const net::URLRequestStatus& status,
                                   const std::string& security_info,
                                   const base::Time& completion_time) {
   }
@@ -293,7 +293,7 @@
   virtual void SetUp() {
     ResourceDispatcherTest::SetUp();
     shared_handle_.Delete(kShmemSegmentName);
-    EXPECT_EQ(true, shared_handle_.CreateNamed(kShmemSegmentName, false, 100));
+    EXPECT_TRUE(shared_handle_.CreateNamed(kShmemSegmentName, false, 100));
   }
 
   virtual void TearDown() {
diff --git a/chrome/common/resource_response.h b/chrome/common/resource_response.h
index 058a811..a5284df 100644
--- a/chrome/common/resource_response.h
+++ b/chrome/common/resource_response.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -21,7 +21,7 @@
   ~ResourceResponseHead();
 
   // The response status.
-  URLRequestStatus status;
+  net::URLRequestStatus status;
 
   // Whether we should apply a filter to this resource that replaces
   // localization templates with the appropriate localized strings.  This is set
diff --git a/chrome/common/sandbox_init_wrapper_linux.cc b/chrome/common/sandbox_init_wrapper_linux.cc
index daf02d3..ffb711d 100644
--- a/chrome/common/sandbox_init_wrapper_linux.cc
+++ b/chrome/common/sandbox_init_wrapper_linux.cc
@@ -5,7 +5,6 @@
 #include "chrome/common/sandbox_init_wrapper.h"
 
 #include "base/command_line.h"
-#include "chrome/common/chrome_switches.h"
 
 bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
                                            const std::string& process_type) {
diff --git a/chrome/common/sandbox_init_wrapper_win.cc b/chrome/common/sandbox_init_wrapper_win.cc
index 5d4399a..a18632e 100644
--- a/chrome/common/sandbox_init_wrapper_win.cc
+++ b/chrome/common/sandbox_init_wrapper_win.cc
@@ -1,10 +1,12 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/common/sandbox_init_wrapper.h"
 
 #include "base/command_line.h"
+#include "base/logging.h"
+
 #include "chrome/common/chrome_switches.h"
 
 void SandboxInitWrapper::SetServices(sandbox::SandboxInterfaceInfo* info) {
@@ -12,6 +14,9 @@
     broker_services_ = info->broker_services;
     target_services_ = info->target_services;
   }
+  // Both interface pointers cannot be non-zero. A process can either
+  // be a target or a broker but not both.
+  DCHECK(!(target_services_ && broker_services_));
 }
 
 bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
@@ -22,12 +27,16 @@
       (process_type == switches::kExtensionProcess) ||
       (process_type == switches::kWorkerProcess) ||
       (process_type == switches::kNaClLoaderProcess) ||
-      (process_type == switches::kUtilityProcess) ||
-      (process_type == switches::kPluginProcess &&
-       command_line.HasSwitch(switches::kSafePlugins))) {
+      (process_type == switches::kUtilityProcess)) {
+    // The above five process types must be sandboxed unless --no-sandbox
+    // is present in the command line.
     if (!target_services_)
       return false;
-    target_services_->Init();
+  } else {
+    // Other process types might or might not be sandboxed.
+    // TODO(cpu): clean this mess.
+    if (!target_services_)
+      return true;
   }
-  return true;
+  return (sandbox::SBOX_ALL_OK == target_services_->Init());
 }
diff --git a/chrome/common/sandbox_policy.cc b/chrome/common/sandbox_policy.cc
index 7436ad2..16049e8 100644
--- a/chrome/common/sandbox_policy.cc
+++ b/chrome/common/sandbox_policy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "app/win/win_util.h"
 #include "base/command_line.h"
 #include "base/debug/debugger.h"
 #include "base/debug/trace_event.h"
@@ -64,6 +63,7 @@
   L"radhslib.dll",                // Radiant Naomi Internet Filter.
   L"radprlib.dll",                // Radiant Naomi Internet Filter.
   L"rlhook.dll",                  // Trustware Bufferzone.
+  L"rpchromebrowserrecordhelper.dll",  // RealPlayer.
   L"r3hook.dll",                  // Kaspersky Internet Security.
   L"sahook.dll",                  // McAfee Site Advisor.
   L"sbrige.dll",                  // Unknown.
@@ -325,8 +325,13 @@
   if (0 == ::GetShortPathNameW(plugin_path.value().c_str(),
                                short_path, arraysize(short_path)))
     return false;
+  // Here is the kicker, if the user has disabled 8.3 (short path) support
+  // on the volume GetShortPathNameW does not fail but simply returns the
+  // input path. In this case if the path had any spaces then rundll32 will
+  // incorrectly interpret its parameters. So we quote the path, even though
+  // the kb/164787 says you should not.
   std::wstring cmd_final =
-      base::StringPrintf(L"%ls %ls,BrokerMain browser=chrome",
+      base::StringPrintf(L"%ls \"%ls\",BrokerMain browser=chrome",
                          rundll.value().c_str(),
                          short_path);
   base::ProcessHandle process;
@@ -358,31 +363,35 @@
 }
 
 // Creates a sandbox for the built-in flash plugin running in a restricted
-// environment. This is a work in progress and for the time being do not
-// pay attention to the duplication between this function and the above
-// function. For more information see bug 50796.
+// environment. This policy is in continual flux as flash changes
+// capabilities. For more information see bug 50796.
 bool ApplyPolicyForBuiltInFlashPlugin(sandbox::TargetPolicy* policy) {
-  // TODO(cpu): Lock down the job level more.
   policy->SetJobLevel(sandbox::JOB_UNPROTECTED, 0);
+  // Vista and Win7 get a weaker token but have low integrity.
+  if (base::win::GetVersion() > base::win::VERSION_XP) {
+    policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
+                          sandbox::USER_INTERACTIVE);
+    policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+  } else {
+    policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
+                          sandbox::USER_LIMITED);
 
-  sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
+    if (!AddKeyAndSubkeys(L"HKEY_LOCAL_MACHINE\\SOFTWARE",
+                          sandbox::TargetPolicy::REG_ALLOW_READONLY,
+                          policy))
+      return false;
+    if (!AddKeyAndSubkeys(L"HKEY_LOCAL_MACHINE\\SYSTEM",
+                          sandbox::TargetPolicy::REG_ALLOW_READONLY,
+                          policy))
+      return false;
 
-  if (base::win::GetVersion() > base::win::VERSION_XP)
-    initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS;
+    if (!AddKeyAndSubkeys(L"HKEY_CURRENT_USER\\SOFTWARE",
+                          sandbox::TargetPolicy::REG_ALLOW_READONLY,
+                          policy))
+      return false;
+  }
 
-  policy->SetTokenLevel(initial_token, sandbox::USER_LIMITED);
-  policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
-
-  // TODO(cpu): Proxy registry access and remove these policies.
-  if (!AddKeyAndSubkeys(L"HKEY_CURRENT_USER\\SOFTWARE\\ADOBE",
-                        sandbox::TargetPolicy::REG_ALLOW_ANY,
-                        policy))
-    return false;
-
-  if (!AddKeyAndSubkeys(L"HKEY_CURRENT_USER\\SOFTWARE\\MACROMEDIA",
-                        sandbox::TargetPolicy::REG_ALLOW_ANY,
-                        policy))
-    return false;
+  AddDllEvictionPolicy(policy);
   return true;
 }
 
@@ -602,14 +611,14 @@
   if (!exposed_dir.empty()) {
     result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
                              sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                             exposed_dir.ToWStringHack().c_str());
+                             exposed_dir.value().c_str());
     if (result != sandbox::SBOX_ALL_OK)
       return 0;
 
     FilePath exposed_files = exposed_dir.AppendASCII("*");
     result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
                              sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                             exposed_files.ToWStringHack().c_str());
+                             exposed_files.value().c_str());
     if (result != sandbox::SBOX_ALL_OK)
       return 0;
   }
diff --git a/chrome/common/section_util_win.cc b/chrome/common/section_util_win.cc
new file mode 100644
index 0000000..449151c
--- /dev/null
+++ b/chrome/common/section_util_win.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/section_util_win.h"
+
+namespace chrome {
+
+HANDLE GetSectionFromProcess(HANDLE section, HANDLE process, bool read_only) {
+  HANDLE valid_section = NULL;
+  DWORD access = STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ;
+  if (!read_only)
+    access |= FILE_MAP_WRITE;
+  DuplicateHandle(process, section, GetCurrentProcess(), &valid_section, access,
+                  FALSE, 0);
+  return valid_section;
+}
+
+HANDLE GetSectionForProcess(HANDLE section, HANDLE process, bool read_only) {
+  HANDLE valid_section = NULL;
+  DWORD access = STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ;
+  if (!read_only)
+    access |= FILE_MAP_WRITE;
+  DuplicateHandle(GetCurrentProcess(), section, process, &valid_section, access,
+                  FALSE, 0);
+  return valid_section;
+}
+
+}  // namespace chrome
diff --git a/chrome/common/section_util_win.h b/chrome/common/section_util_win.h
new file mode 100644
index 0000000..a3c849e
--- /dev/null
+++ b/chrome/common/section_util_win.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_COMMON_SECTION_UTIL_WIN_H_
+#define CHROME_COMMON_SECTION_UTIL_WIN_H_
+#pragma once
+
+#include <windows.h>
+
+namespace chrome {
+
+// Duplicates a section handle from another process to the current process.
+// Returns the new valid handle if the function succeed. NULL otherwise.
+HANDLE GetSectionFromProcess(HANDLE section, HANDLE process, bool read_only);
+
+// Duplicates a section handle from the current process for use in another
+// process. Returns the new valid handle or NULL on failure.
+HANDLE GetSectionForProcess(HANDLE section, HANDLE process, bool read_only);
+
+}  // namespace chrome
+
+#endif  // CHROME_COMMON_SECTION_UTIL_WIN_H_
diff --git a/chrome/common/security_filter_peer.cc b/chrome/common/security_filter_peer.cc
index 3be8864..93277a8 100644
--- a/chrome/common/security_filter_peer.cc
+++ b/chrome/common/security_filter_peer.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/common/security_filter_peer.h"
 
-#include "app/l10n_util.h"
 #include "grit/generated_resources.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
+#include "ui/base/l10n/l10n_util.h"
 
 SecurityFilterPeer::SecurityFilterPeer(
     webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
@@ -84,7 +84,7 @@
   NOTREACHED();
 }
 
-void SecurityFilterPeer::OnCompletedRequest(const URLRequestStatus& status,
+void SecurityFilterPeer::OnCompletedRequest(const net::URLRequestStatus& status,
                                             const std::string& security_info,
                                             const base::Time& completion_time) {
   NOTREACHED();
@@ -143,17 +143,18 @@
   data_.append(data, len);
 }
 
-void BufferedPeer::OnCompletedRequest(const URLRequestStatus& status,
+void BufferedPeer::OnCompletedRequest(const net::URLRequestStatus& status,
                                       const std::string& security_info,
                                       const base::Time& completion_time) {
   // Make sure we delete ourselves at the end of this call.
   scoped_ptr<BufferedPeer> this_deleter(this);
 
   // Give sub-classes a chance at altering the data.
-  if (status.status() != URLRequestStatus::SUCCESS || !DataReady()) {
+  if (status.status() != net::URLRequestStatus::SUCCESS || !DataReady()) {
     // Pretend we failed to load the resource.
     original_peer_->OnReceivedResponse(response_info_, true);
-    URLRequestStatus status(URLRequestStatus::CANCELED, net::ERR_ABORTED);
+    net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
+                                 net::ERR_ABORTED);
     original_peer_->OnCompletedRequest(status, security_info, completion_time);
     return;
   }
@@ -192,7 +193,7 @@
 }
 
 void ReplaceContentPeer::OnCompletedRequest(
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info,
     const base::Time& completion_time) {
   webkit_glue::ResourceResponseInfo info;
@@ -203,7 +204,7 @@
   if (!data_.empty())
     original_peer_->OnReceivedData(data_.data(),
                                    static_cast<int>(data_.size()));
-  original_peer_->OnCompletedRequest(URLRequestStatus(),
+  original_peer_->OnCompletedRequest(net::URLRequestStatus(),
                                      security_info,
                                      completion_time);
 
diff --git a/chrome/common/serialized_script_value.cc b/chrome/common/serialized_script_value.cc
index deff44c..407fb97 100644
--- a/chrome/common/serialized_script_value.cc
+++ b/chrome/common/serialized_script_value.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/common/serialized_script_value.h"
 
-#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 using WebKit::WebSerializedScriptValue;
 
diff --git a/chrome/common/service_process_util.cc b/chrome/common/service_process_util.cc
index bcbac69..458f662 100644
--- a/chrome/common/service_process_util.cc
+++ b/chrome/common/service_process_util.cc
@@ -2,12 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "base/file_util.h"
 #include "base/logging.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
 #include "base/path_service.h"
 #include "base/process_util.h"
+#include "base/sha1.h"
 #include "base/singleton.h"
 #include "base/string16.h"
+#include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "base/version.h"
@@ -34,29 +39,6 @@
   return GetServiceProcessScopedName("_service_shmem");
 }
 
-// Reads the named shared memory to get the shared data. Returns false if no
-// matching shared memory was found.
-bool GetServiceProcessSharedData(std::string* version, base::ProcessId* pid) {
-  scoped_ptr<base::SharedMemory> shared_mem_service_data;
-  shared_mem_service_data.reset(new base::SharedMemory());
-  ServiceProcessSharedData* service_data = NULL;
-  if (shared_mem_service_data.get() &&
-      shared_mem_service_data->Open(GetServiceProcessSharedMemName(), true) &&
-      shared_mem_service_data->Map(sizeof(ServiceProcessSharedData))) {
-    service_data = reinterpret_cast<ServiceProcessSharedData*>(
-        shared_mem_service_data->memory());
-    // Make sure the version in shared memory is null-terminated. If it is not,
-    // treat it as invalid.
-    if (version && memchr(service_data->service_process_version, '\0',
-                          sizeof(service_data->service_process_version)))
-      *version = service_data->service_process_version;
-    if (pid)
-      *pid = service_data->service_process_pid;
-    return true;
-  }
-  return false;
-}
-
 enum ServiceProcessRunningState {
   SERVICE_NOT_RUNNING,
   SERVICE_OLDER_VERSION_RUNNING,
@@ -65,12 +47,20 @@
 };
 
 ServiceProcessRunningState GetServiceProcessRunningState(
-    std::string* service_version_out) {
+    std::string* service_version_out, base::ProcessId* pid_out) {
   std::string version;
-  GetServiceProcessSharedData(&version, NULL);
-  if (version.empty())
+  if (!GetServiceProcessSharedData(&version, pid_out))
     return SERVICE_NOT_RUNNING;
 
+#if defined(OS_POSIX)
+  // We only need to check for service running on POSIX because Windows cleans
+  // up shared memory files when an app crashes, so there isn't a chance of
+  // us reading bogus data from shared memory for an app that has died.
+  if (!CheckServiceProcessReady()) {
+    return SERVICE_NOT_RUNNING;
+  }
+#endif  // defined(OS_POSIX)
+
   // At this time we have a version string. Set the out param if it exists.
   if (service_version_out)
     *service_version_out = version;
@@ -105,23 +95,22 @@
   return SERVICE_SAME_VERSION_RUNNING;
 }
 
-
 }  // namespace
 
 // Return a name that is scoped to this instance of the service process. We
-// use the user-data-dir as a scoping prefix.
+// use the hash of the user-data-dir as a scoping prefix. We can't use
+// the user-data-dir itself as we have limits on the size of the lock names.
 std::string GetServiceProcessScopedName(const std::string& append_str) {
   FilePath user_data_dir;
   PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
 #if defined(OS_WIN)
-  std::string scoped_name = WideToUTF8(user_data_dir.value());
+  std::string user_data_dir_path = WideToUTF8(user_data_dir.value());
 #elif defined(OS_POSIX)
-  std::string scoped_name = user_data_dir.value();
+  std::string user_data_dir_path = user_data_dir.value();
 #endif  // defined(OS_WIN)
-  std::replace(scoped_name.begin(), scoped_name.end(), '\\', '!');
-  std::replace(scoped_name.begin(), scoped_name.end(), '/', '!');
-  scoped_name.append(append_str);
-  return scoped_name;
+  std::string hash = base::SHA1HashString(user_data_dir_path);
+  std::string hex_hash = base::HexEncode(hash.c_str(), hash.length());
+  return hex_hash + "." + append_str;
 }
 
 // Return a name that is scoped to this instance of the service process. We
@@ -141,16 +130,40 @@
   return GetServiceProcessScopedVersionedName("_service_ipc");
 }
 
-base::ProcessId GetServiceProcessPid() {
-  base::ProcessId pid = 0;
-  GetServiceProcessSharedData(NULL, &pid);
-  return pid;
+// Reads the named shared memory to get the shared data. Returns false if no
+// matching shared memory was found.
+bool GetServiceProcessSharedData(std::string* version, base::ProcessId* pid) {
+  scoped_ptr<base::SharedMemory> shared_mem_service_data;
+  shared_mem_service_data.reset(new base::SharedMemory());
+  ServiceProcessSharedData* service_data = NULL;
+  if (shared_mem_service_data.get() &&
+      shared_mem_service_data->Open(GetServiceProcessSharedMemName(), true) &&
+      shared_mem_service_data->Map(sizeof(ServiceProcessSharedData))) {
+    service_data = reinterpret_cast<ServiceProcessSharedData*>(
+        shared_mem_service_data->memory());
+    // Make sure the version in shared memory is null-terminated. If it is not,
+    // treat it as invalid.
+    if (version && memchr(service_data->service_process_version, '\0',
+                          sizeof(service_data->service_process_version)))
+      *version = service_data->service_process_version;
+    if (pid)
+      *pid = service_data->service_process_pid;
+    return true;
+  }
+  return false;
 }
 
 ServiceProcessState::ServiceProcessState() : state_(NULL) {
 }
 
 ServiceProcessState::~ServiceProcessState() {
+  if (shared_mem_service_data_.get()) {
+    // Delete needs a pool wrapped around it because it calls some Obj-C on Mac,
+    // and since ServiceProcessState is a singleton, it gets destructed after
+    // the standard NSAutoreleasePools have already been cleaned up.
+    base::mac::ScopedNSAutoreleasePool pool;
+    shared_mem_service_data_->Delete(GetServiceProcessSharedMemName());
+  }
   TearDownState();
 }
 
@@ -165,30 +178,26 @@
   }
   // Now that we have the singleton, take care of killing an older version, if
   // it exists.
-  if (ShouldHandleOtherVersion() && !HandleOtherVersion())
+  if (!HandleOtherVersion())
     return false;
 
-  // TODO(sanjeevr): We can probably use the shared mem as the sole singleton
-  // mechanism. For that the shared mem class needs to return whether it created
-  // new instance or opened an existing one. Also shared memory on Linux uses
-  // a file on disk which is not deleted when the process exits.
-
-  // Now that we have the singleton, let is also write the version we are using
-  // to shared memory. This can be used by a newer service to signal us to exit.
+  // Write the version we are using to shared memory. This can be used by a
+  // newer service to signal us to exit.
   return CreateSharedData();
 }
 
 bool ServiceProcessState::HandleOtherVersion() {
   std::string running_version;
+  base::ProcessId process_id;
   ServiceProcessRunningState state =
-      GetServiceProcessRunningState(&running_version);
+      GetServiceProcessRunningState(&running_version, &process_id);
   switch (state) {
     case SERVICE_SAME_VERSION_RUNNING:
     case SERVICE_NEWER_VERSION_RUNNING:
       return false;
     case SERVICE_OLDER_VERSION_RUNNING:
       // If an older version is running, kill it.
-      ForceServiceProcessShutdown(running_version);
+      ForceServiceProcessShutdown(running_version, process_id);
       break;
     case SERVICE_NOT_RUNNING:
       break;
@@ -209,8 +218,8 @@
     return false;
   }
 
-  scoped_ptr<base::SharedMemory> shared_mem_service_data;
-  shared_mem_service_data.reset(new base::SharedMemory());
+  scoped_ptr<base::SharedMemory> shared_mem_service_data(
+      new base::SharedMemory());
   if (!shared_mem_service_data.get())
     return false;
 
@@ -233,8 +242,11 @@
   return true;
 }
 
-
 std::string ServiceProcessState::GetAutoRunKey() {
   return GetServiceProcessScopedName("_service_run");
 }
 
+void ServiceProcessState::SignalStopped() {
+  TearDownState();
+  shared_mem_service_data_.reset();
+}
diff --git a/chrome/common/service_process_util.h b/chrome/common/service_process_util.h
index 6f2685e..175499d 100644
--- a/chrome/common/service_process_util.h
+++ b/chrome/common/service_process_util.h
@@ -10,7 +10,12 @@
 #include "base/process.h"
 #include "base/scoped_ptr.h"
 #include "base/shared_memory.h"
-#include "base/task.h"
+
+class Task;
+
+namespace base {
+  class MessageLoopProxy;
+}
 
 template <typename T> struct DefaultSingletonTraits;
 
@@ -33,16 +38,17 @@
 // IPC commands.
 bool CheckServiceProcessReady();
 
-// Returns the process id of the currently running service process. Returns 0
-// if no service process is running.
+// Returns the process id and version of the currently running service process.
 // Note: DO NOT use this check whether the service process is ready because
-// a non-zero return value only means that the process is running and not that
-// it is ready to receive IPC commands. This method is only exposed for testing.
-base::ProcessId GetServiceProcessPid();
+// a true return value only means that some process shared data was available,
+// and not that the process is ready to receive IPC commands, or even running.
+// This method is only exposed for testing.
+bool GetServiceProcessSharedData(std::string* version, base::ProcessId* pid);
 // --------------------------------------------------------------------------
 
 // Forces a service process matching the specified version to shut down.
-bool ForceServiceProcessShutdown(const std::string& version);
+bool ForceServiceProcessShutdown(const std::string& version,
+                                 base::ProcessId process_id);
 
 // This is a class that is used by the service process to signal events and
 // share data with external clients. This class lives in this file because the
@@ -61,7 +67,10 @@
   // This method is called when the service process is running and initialized.
   // |shutdown_task| is invoked when we get a shutdown request from another
   // process (in the same thread that called SignalReady). It can be NULL.
-  void SignalReady(Task* shutdown_task);
+  // |message_loop_proxy| must be of type IO and is the loop that POSIX uses
+  // to monitor the service process.
+  bool SignalReady(
+      base::MessageLoopProxy* message_loop_proxy, Task* shutdown_task);
 
   // Signal that the service process is stopped.
   void SignalStopped();
@@ -93,8 +102,6 @@
   // Tear down the platform specific state.
   void TearDownState();
 
-  // Allows each platform to specify whether it supports killing older versions.
-  bool ShouldHandleOtherVersion();
   // An opaque object that maintains state. The actual definition of this is
   // platform dependent.
   struct StateData;
diff --git a/chrome/common/service_process_util_posix.cc b/chrome/common/service_process_util_posix.cc
index e547223..7deebaa 100644
--- a/chrome/common/service_process_util_posix.cc
+++ b/chrome/common/service_process_util_posix.cc
@@ -4,14 +4,23 @@
 
 #include "chrome/common/service_process_util.h"
 
+#include <signal.h>
+#include <unistd.h>
+
 #include "base/file_util.h"
 #include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/message_pump_libevent.h"
 #include "base/path_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_version_info.h"
+#include "chrome/common/multi_process_lock.h"
 
 namespace {
 
+int g_signal_socket = -1;
+
 // Gets the name of the lock file for service process.
 FilePath GetServiceProcessLockFilePath() {
   FilePath user_data_dir;
@@ -21,45 +30,181 @@
   return user_data_dir.Append(lock_file_name);
 }
 
+// Attempts to take a lock named |name|. If |waiting| is true then this will
+// make multiple attempts to acquire the lock.
+// Caller is responsible for ownership of the MultiProcessLock.
+MultiProcessLock* TakeNamedLock(const std::string& name, bool waiting) {
+  scoped_ptr<MultiProcessLock> lock(MultiProcessLock::Create(name));
+  if (lock == NULL) return NULL;
+  bool got_lock = false;
+  for (int i = 0; i < 10; ++i) {
+    if (lock->TryLock()) {
+      got_lock = true;
+      break;
+    }
+    if (!waiting) break;
+    base::PlatformThread::Sleep(100 * i);
+  }
+  if (!got_lock) {
+    lock.reset();
+  }
+  return lock.release();
+}
+
+MultiProcessLock* TakeServiceRunningLock(bool waiting) {
+  std::string lock_name =
+      GetServiceProcessScopedName("_service_running");
+  return TakeNamedLock(lock_name, waiting);
+}
+
+MultiProcessLock* TakeServiceInitializingLock(bool waiting) {
+  std::string lock_name =
+      GetServiceProcessScopedName("_service_initializing");
+  return TakeNamedLock(lock_name, waiting);
+}
+
 }  // namespace
 
-bool ForceServiceProcessShutdown(const std::string& version) {
-  NOTIMPLEMENTED();
-  return false;
-}
+// Watches for |kShutDownMessage| to be written to the file descriptor it is
+// watching. When it reads |kShutDownMessage|, it performs |shutdown_task_|.
+// Used here to monitor the socket listening to g_signal_socket.
+class ServiceProcessShutdownMonitor
+    : public base::MessagePumpLibevent::Watcher {
+ public:
 
-bool CheckServiceProcessReady() {
-  const FilePath path = GetServiceProcessLockFilePath();
-  return file_util::PathExists(path);
-}
+  enum {
+    kShutDownMessage = 0xdecea5e
+  };
 
-struct ServiceProcessState::StateData {
-  // No state yet for Posix.
+  explicit ServiceProcessShutdownMonitor(Task* shutdown_task)
+      : shutdown_task_(shutdown_task) {
+  }
+
+  virtual ~ServiceProcessShutdownMonitor();
+
+  virtual void OnFileCanReadWithoutBlocking(int fd);
+  virtual void OnFileCanWriteWithoutBlocking(int fd);
+
+ private:
+  scoped_ptr<Task> shutdown_task_;
 };
 
-bool ServiceProcessState::TakeSingletonLock() {
-  // TODO(sanjeevr): Implement singleton mechanism for POSIX.
+ServiceProcessShutdownMonitor::~ServiceProcessShutdownMonitor() {
+}
+
+void ServiceProcessShutdownMonitor::OnFileCanReadWithoutBlocking(int fd) {
+  if (shutdown_task_.get()) {
+    int buffer;
+    int length = read(fd, &buffer, sizeof(buffer));
+    if ((length == sizeof(buffer)) && (buffer == kShutDownMessage)) {
+      shutdown_task_->Run();
+      shutdown_task_.reset();
+    } else if (length > 0) {
+      LOG(ERROR) << "Unexpected read: " << buffer;
+    } else if (length == 0) {
+      LOG(ERROR) << "Unexpected fd close";
+    } else if (length < 0) {
+      PLOG(ERROR) << "read";
+    }
+  }
+}
+
+void ServiceProcessShutdownMonitor::OnFileCanWriteWithoutBlocking(int fd) {
   NOTIMPLEMENTED();
+}
+
+// "Forced" Shutdowns on POSIX are done via signals. The magic signal for
+// a shutdown is SIGTERM. "write" is a signal safe function. PLOG(ERROR) is
+// not, but we don't ever expect it to be called.
+static void SigTermHandler(int sig, siginfo_t* info, void* uap) {
+  // TODO(dmaclach): add security here to make sure that we are being shut
+  //                 down by an appropriate process.
+  int message = ServiceProcessShutdownMonitor::kShutDownMessage;
+  if (write(g_signal_socket, &message, sizeof(message)) < 0) {
+    PLOG(ERROR) << "write";
+  }
+}
+
+// See comment for SigTermHandler.
+bool ForceServiceProcessShutdown(const std::string& version,
+                                 base::ProcessId process_id) {
+  if (kill(process_id, SIGTERM) < 0) {
+    PLOG(ERROR) << "kill";
+    return false;
+  }
   return true;
 }
 
-void ServiceProcessState::SignalReady(Task* shutdown_task) {
-  // TODO(hclam): Implement better mechanism for these platform.
-  // Also we need to save shutdown task. For now we just delete the shutdown
-  // task because we have not way to listen for shutdown requests.
-  delete shutdown_task;
-  const FilePath path = GetServiceProcessLockFilePath();
-  FILE* file = file_util::OpenFile(path, "wb+");
-  if (!file)
-    return;
-  VLOG(1) << "Created Service Process lock file: " << path.value();
-  file_util::TruncateFile(file) && file_util::CloseFile(file);
+bool CheckServiceProcessReady() {
+  scoped_ptr<MultiProcessLock> running_lock(TakeServiceRunningLock(false));
+  return running_lock.get() == NULL;
 }
 
-void ServiceProcessState::SignalStopped() {
-  const FilePath path = GetServiceProcessLockFilePath();
-  file_util::Delete(path, false);
-  shared_mem_service_data_.reset();
+struct ServiceProcessState::StateData
+    : public base::RefCountedThreadSafe<ServiceProcessState::StateData> {
+  scoped_ptr<MultiProcessLock> initializing_lock_;
+  scoped_ptr<MultiProcessLock> running_lock_;
+  scoped_ptr<ServiceProcessShutdownMonitor> shut_down_monitor_;
+  base::MessagePumpLibevent::FileDescriptorWatcher watcher_;
+  int sockets_[2];
+  struct sigaction old_action_;
+  bool set_action_;
+
+  // WatchFileDescriptor needs to be set up by the thread that is going
+  // to be monitoring it.
+  void SignalReady() {
+    CHECK(MessageLoopForIO::current()->WatchFileDescriptor(
+        sockets_[0], true, MessageLoopForIO::WATCH_READ,
+        &watcher_, shut_down_monitor_.get()));
+    g_signal_socket = sockets_[1];
+
+    // Set up signal handler for SIGTERM.
+    struct sigaction action;
+    action.sa_sigaction = SigTermHandler;
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = SA_SIGINFO;
+    if (sigaction(SIGTERM, &action, &old_action_) == 0) {
+      // If the old_action is not default, somebody else has installed a
+      // a competing handler. Our handler is going to override it so it
+      // won't be called. If this occurs it needs to be fixed.
+      DCHECK_EQ(old_action_.sa_handler, SIG_DFL);
+      set_action_ = true;
+      initializing_lock_.reset();
+    } else {
+      PLOG(ERROR) << "sigaction";
+    }
+  }
+};
+
+bool ServiceProcessState::TakeSingletonLock() {
+  CHECK(!state_);
+  state_ = new StateData;
+  state_->AddRef();
+  state_->sockets_[0] = -1;
+  state_->sockets_[1] = -1;
+  state_->set_action_ = false;
+  state_->initializing_lock_.reset(TakeServiceInitializingLock(true));
+  return state_->initializing_lock_.get();
+}
+
+bool ServiceProcessState::SignalReady(
+    base::MessageLoopProxy* message_loop_proxy, Task* shutdown_task) {
+  CHECK(state_);
+  CHECK_EQ(g_signal_socket, -1);
+
+  state_->running_lock_.reset(TakeServiceRunningLock(true));
+  if (state_->running_lock_.get() == NULL) {
+    return false;
+  }
+  state_->shut_down_monitor_.reset(
+      new ServiceProcessShutdownMonitor(shutdown_task));
+  if (pipe(state_->sockets_) < 0) {
+    PLOG(ERROR) << "pipe";
+    return false;
+  }
+  message_loop_proxy->PostTask(FROM_HERE,
+      NewRunnableMethod(state_, &ServiceProcessState::StateData::SignalReady));
+  return true;
 }
 
 bool ServiceProcessState::AddToAutoRun() {
@@ -73,11 +218,20 @@
 }
 
 void ServiceProcessState::TearDownState() {
+  g_signal_socket = -1;
+  if (state_) {
+    if (state_->sockets_[0] != -1) {
+      close(state_->sockets_[0]);
+    }
+    if (state_->sockets_[1] != -1) {
+      close(state_->sockets_[1]);
+    }
+    if (state_->set_action_) {
+      if (sigaction(SIGTERM, &state_->old_action_, NULL) < 0) {
+        PLOG(ERROR) << "sigaction";
+      }
+    }
+    state_->Release();
+    state_ = NULL;
+  }
 }
-
-bool ServiceProcessState::ShouldHandleOtherVersion() {
-  // On POSIX, the shared memory is a file in disk. We may have a stale file
-  // lying around from a previous run. So the check is not reliable.
-  return false;
-}
-
diff --git a/chrome/common/service_process_util_unittest.cc b/chrome/common/service_process_util_unittest.cc
index 58b68e1..ad6b257 100644
--- a/chrome/common/service_process_util_unittest.cc
+++ b/chrome/common/service_process_util_unittest.cc
@@ -5,10 +5,25 @@
 #include "base/at_exit.h"
 #include "base/process_util.h"
 #include "base/string_util.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/service_process_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
 
+namespace {
+
+bool g_good_shutdown = false;
+
+void ShutdownTask(MessageLoop* loop) {
+  // Quit the main message loop.
+  ASSERT_FALSE(g_good_shutdown);
+  g_good_shutdown = true;
+  loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+}
+
+}  // namespace
 
 TEST(ServiceProcessUtilTest, ScopedVersionedName) {
   std::string test_str = "test";
@@ -19,55 +34,126 @@
   EXPECT_NE(std::string::npos, scoped_name.find(version_info.Version()));
 }
 
-class ServiceProcessStateTest : public testing::Test {
+class ServiceProcessStateTest : public base::MultiProcessTest {
+ public:
+  ServiceProcessStateTest();
+  ~ServiceProcessStateTest();
+  virtual void SetUp();
+  base::MessageLoopProxy* IOMessageLoopProxy() {
+    return io_thread_.message_loop_proxy();
+  }
+  void LaunchAndWait(const std::string& name);
+
  private:
   // This is used to release the ServiceProcessState singleton after each test.
   base::ShadowingAtExitManager at_exit_manager_;
+  base::Thread io_thread_;
 };
 
-#if defined(OS_WIN)
-// Singleton-ness is only implemented on Windows.
-// TODO(sanjeev): Rewrite this test to spawn a new process and test using the
-// ServiceProcessState singleton across processes.
-/*
-TEST_F(ServiceProcessStateTest, Singleton) {
-  ServiceProcessState state;
-  EXPECT_TRUE(state.Initialize());
-  // The second instance should fail to Initialize.
-  ServiceProcessState another_state;
-  EXPECT_FALSE(another_state.Initialize());
+ServiceProcessStateTest::ServiceProcessStateTest()
+    : io_thread_("ServiceProcessStateTestThread") {
 }
-*/
-#endif  // defined(OS_WIN)
+
+ServiceProcessStateTest::~ServiceProcessStateTest() {
+}
+
+void ServiceProcessStateTest::SetUp() {
+  base::Thread::Options options(MessageLoop::TYPE_IO, 0);
+  ASSERT_TRUE(io_thread_.StartWithOptions(options));
+}
+
+void ServiceProcessStateTest::LaunchAndWait(const std::string& name) {
+  base::ProcessHandle handle = SpawnChild(name, false);
+  ASSERT_TRUE(handle);
+  int exit_code = 0;
+  ASSERT_TRUE(base::WaitForExitCode(handle, &exit_code));
+  ASSERT_EQ(exit_code, 0);
+}
+
+TEST_F(ServiceProcessStateTest, Singleton) {
+  ServiceProcessState* state = ServiceProcessState::GetInstance();
+  ASSERT_TRUE(state->Initialize());
+  LaunchAndWait("ServiceProcessStateTestSingleton");
+}
 
 TEST_F(ServiceProcessStateTest, ReadyState) {
-#if defined(OS_WIN)
-  // On Posix, we use a lock file on disk to signal readiness. This lock file
-  // could be lying around from previous crashes which could cause
-  // CheckServiceProcessReady to lie. On Windows, we use a named event so we
-  // don't have this issue. Until we have a more stable signalling mechanism on
-  // Posix, this check will only execute on Windows.
-  EXPECT_FALSE(CheckServiceProcessReady());
-#endif  // defined(OS_WIN)
+  ASSERT_FALSE(CheckServiceProcessReady());
   ServiceProcessState* state = ServiceProcessState::GetInstance();
-  EXPECT_TRUE(state->Initialize());
-  state->SignalReady(NULL);
-  EXPECT_TRUE(CheckServiceProcessReady());
+  ASSERT_TRUE(state->Initialize());
+  ASSERT_TRUE(state->SignalReady(IOMessageLoopProxy(), NULL));
+  LaunchAndWait("ServiceProcessStateTestReadyTrue");
   state->SignalStopped();
-  EXPECT_FALSE(CheckServiceProcessReady());
+  LaunchAndWait("ServiceProcessStateTestReadyFalse");
 }
 
 TEST_F(ServiceProcessStateTest, SharedMem) {
+  std::string version;
+  base::ProcessId pid;
 #if defined(OS_WIN)
   // On Posix, named shared memory uses a file on disk. This file
   // could be lying around from previous crashes which could cause
   // GetServiceProcessPid to lie. On Windows, we use a named event so we
   // don't have this issue. Until we have a more stable shared memory
   // implementation on Posix, this check will only execute on Windows.
-  EXPECT_EQ(0, GetServiceProcessPid());
+  ASSERT_FALSE(GetServiceProcessSharedData(&version, &pid));
 #endif  // defined(OS_WIN)
   ServiceProcessState* state = ServiceProcessState::GetInstance();
+  ASSERT_TRUE(state->Initialize());
+  ASSERT_TRUE(GetServiceProcessSharedData(&version, &pid));
+  ASSERT_EQ(base::GetCurrentProcId(), pid);
+}
+
+TEST_F(ServiceProcessStateTest, ForceShutdown) {
+  base::ProcessHandle handle = SpawnChild("ServiceProcessStateTestShutdown",
+                                          true);
+  ASSERT_TRUE(handle);
+  for (int i = 0; !CheckServiceProcessReady() && i < 10; ++i) {
+    base::PlatformThread::Sleep(TestTimeouts::tiny_timeout_ms());
+  }
+  ASSERT_TRUE(CheckServiceProcessReady());
+  std::string version;
+  base::ProcessId pid;
+  ASSERT_TRUE(GetServiceProcessSharedData(&version, &pid));
+  ASSERT_TRUE(ForceServiceProcessShutdown(version, pid));
+  int exit_code = 0;
+  ASSERT_TRUE(base::WaitForExitCodeWithTimeout(handle,
+      &exit_code, TestTimeouts::action_timeout_ms() * 2));
+  ASSERT_EQ(exit_code, 0);
+}
+
+MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestSingleton) {
+  ServiceProcessState* state = ServiceProcessState::GetInstance();
+  EXPECT_FALSE(state->Initialize());
+  return 0;
+}
+
+MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyTrue) {
+  EXPECT_TRUE(CheckServiceProcessReady());
+  return 0;
+}
+
+MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyFalse) {
+  EXPECT_FALSE(CheckServiceProcessReady());
+  return 0;
+}
+
+MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestShutdown) {
+  MessageLoop message_loop;
+  message_loop.set_thread_name("ServiceProcessStateTestShutdownMainThread");
+  base::Thread io_thread_("ServiceProcessStateTestShutdownIOThread");
+  base::Thread::Options options(MessageLoop::TYPE_IO, 0);
+  EXPECT_TRUE(io_thread_.StartWithOptions(options));
+  ServiceProcessState* state = ServiceProcessState::GetInstance();
   EXPECT_TRUE(state->Initialize());
-  EXPECT_EQ(base::GetCurrentProcId(), GetServiceProcessPid());
+  EXPECT_TRUE(state->SignalReady(io_thread_.message_loop_proxy(),
+                                 NewRunnableFunction(&ShutdownTask,
+                                                     MessageLoop::current())));
+  message_loop.PostDelayedTask(FROM_HERE,
+                               new MessageLoop::QuitTask(),
+                               TestTimeouts::action_max_timeout_ms());
+  EXPECT_FALSE(g_good_shutdown);
+  message_loop.Run();
+  EXPECT_TRUE(g_good_shutdown);
+  return 0;
 }
 
diff --git a/chrome/common/service_process_util_win.cc b/chrome/common/service_process_util_win.cc
index eb784a5..f9a1816 100644
--- a/chrome/common/service_process_util_win.cc
+++ b/chrome/common/service_process_util_win.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/string16.h"
+#include "base/task.h"
 #include "base/utf_string_conversions.h"
 #include "base/win/object_watcher.h"
 #include "base/win/scoped_handle.h"
@@ -54,7 +55,8 @@
 
 }  // namespace
 
-bool ForceServiceProcessShutdown(const std::string& version) {
+bool ForceServiceProcessShutdown(const std::string& version,
+                                 base::ProcessId process_id) {
   base::win::ScopedHandle shutdown_event;
   std::string versioned_name = version;
   versioned_name.append("_service_shutdown_evt");
@@ -99,20 +101,19 @@
   return true;
 }
 
-void ServiceProcessState::SignalReady(Task* shutdown_task) {
+bool ServiceProcessState::SignalReady(
+    base::MessageLoopProxy* message_loop_proxy, Task* shutdown_task) {
   DCHECK(state_);
   DCHECK(state_->ready_event.IsValid());
-  SetEvent(state_->ready_event.Get());
+  if (!SetEvent(state_->ready_event.Get())) {
+    return false;
+  }
   if (shutdown_task) {
     state_->shutdown_monitor.reset(
         new ServiceProcessShutdownMonitor(shutdown_task));
     state_->shutdown_monitor->Start();
   }
-}
-
-void ServiceProcessState::SignalStopped() {
-  TearDownState();
-  shared_mem_service_data_.reset();
+  return true;
 }
 
 bool ServiceProcessState::AddToAutoRun() {
@@ -140,7 +141,3 @@
   delete state_;
   state_ = NULL;
 }
-
-bool ServiceProcessState::ShouldHandleOtherVersion() {
-  return true;
-}
diff --git a/chrome/common/socket_stream_dispatcher.cc b/chrome/common/socket_stream_dispatcher.cc
index af95d5c..a7e484a 100644
--- a/chrome/common/socket_stream_dispatcher.cc
+++ b/chrome/common/socket_stream_dispatcher.cc
@@ -141,10 +141,10 @@
 
   socket_id_ = all_bridges.Add(this);
   DCHECK_NE(socket_id_, chrome_common_net::kNoSocketId);
+  AddRef();  // Released in OnClosed().
   if (child_thread_->Send(
       new ViewHostMsg_SocketStream_Connect(url, socket_id_))) {
     DVLOG(1) << "Connect socket_id=" << socket_id_;
-    AddRef();  // Released in OnClosed().
     // TODO(ukai): timeout to OnConnected.
   } else {
     LOG(ERROR) << "IPC SocketStream_Connect failed.";
diff --git a/chrome/common/socket_stream_dispatcher.h b/chrome/common/socket_stream_dispatcher.h
index 01c5421..38da8a6 100644
--- a/chrome/common/socket_stream_dispatcher.h
+++ b/chrome/common/socket_stream_dispatcher.h
@@ -27,14 +27,14 @@
 class SocketStreamDispatcher : public IPC::Channel::Listener {
  public:
   SocketStreamDispatcher();
-  ~SocketStreamDispatcher() {}
+  virtual ~SocketStreamDispatcher() {}
 
   static webkit_glue::WebSocketStreamHandleBridge* CreateBridge(
       WebKit::WebSocketStreamHandle* handle,
       webkit_glue::WebSocketStreamHandleDelegate* delegate);
 
   // IPC::Channel::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& msg);
+  virtual bool OnMessageReceived(const IPC::Message& msg);
 
  private:
   void OnConnected(int socket_id, int max_amount_send_allowed);
diff --git a/chrome/common/speech_input_messages.cc b/chrome/common/speech_input_messages.cc
new file mode 100644
index 0000000..c93062f
--- /dev/null
+++ b/chrome/common/speech_input_messages.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2011 The Chromium 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 "chrome/common/common_param_traits.h"
+
+#define IPC_MESSAGE_IMPL
+#include "chrome/common/speech_input_messages.h"
+
+SpeechInputHostMsg_StartRecognition_Params::
+SpeechInputHostMsg_StartRecognition_Params()
+    : render_view_id(0),
+      request_id(0) {
+}
+
+SpeechInputHostMsg_StartRecognition_Params::
+~SpeechInputHostMsg_StartRecognition_Params() {
+}
+
+namespace IPC {
+
+void ParamTraits<speech_input::SpeechInputResultItem>::Write(
+    Message* m, const param_type& p) {
+  WriteParam(m, p.utterance);
+  WriteParam(m, p.confidence);
+}
+
+bool ParamTraits<speech_input::SpeechInputResultItem>::Read(const Message* m,
+                                                            void** iter,
+                                                            param_type* p) {
+  return ReadParam(m, iter, &p->utterance) &&
+         ReadParam(m, iter, &p->confidence);
+}
+
+void ParamTraits<speech_input::SpeechInputResultItem>::Log(const param_type& p,
+                                                           std::string* l) {
+  l->append("(");
+  LogParam(p.utterance, l);
+  l->append(":");
+  LogParam(p.confidence, l);
+  l->append(")");
+}
+
+void ParamTraits<SpeechInputHostMsg_StartRecognition_Params>::Write(
+    Message* m,
+    const param_type& p) {
+  WriteParam(m, p.render_view_id);
+  WriteParam(m, p.request_id);
+  WriteParam(m, p.element_rect);
+  WriteParam(m, p.language);
+  WriteParam(m, p.grammar);
+  WriteParam(m, p.origin_url);
+}
+
+bool ParamTraits<SpeechInputHostMsg_StartRecognition_Params>::Read(
+    const Message* m, void** iter, param_type* p) {
+  return
+      ReadParam(m, iter, &p->render_view_id) &&
+      ReadParam(m, iter, &p->request_id) &&
+      ReadParam(m, iter, &p->element_rect) &&
+      ReadParam(m, iter, &p->language) &&
+      ReadParam(m, iter, &p->grammar) &&
+      ReadParam(m, iter, &p->origin_url);
+}
+
+void ParamTraits<SpeechInputHostMsg_StartRecognition_Params>::Log(
+    const param_type& p, std::string* l) {
+  l->append("(");
+  LogParam(p.render_view_id, l);
+  l->append(", ");
+  LogParam(p.request_id, l);
+  l->append(", ");
+  LogParam(p.element_rect, l);
+  l->append(", ");
+  LogParam(p.language, l);
+  l->append(", ");
+  LogParam(p.grammar, l);
+  l->append(", ");
+  LogParam(p.origin_url, l);
+  l->append(")");
+}
+
+}  // namespace IPC
diff --git a/chrome/common/speech_input_messages.h b/chrome/common/speech_input_messages.h
new file mode 100644
index 0000000..c46ac02
--- /dev/null
+++ b/chrome/common/speech_input_messages.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium 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 CHROME_COMMON_SPEECH_INPUT_MESSAGES_H_
+#define CHROME_COMMON_SPEECH_INPUT_MESSAGES_H_
+#pragma once
+
+#include "chrome/common/speech_input_result.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_param_traits.h"
+#include "ui/gfx/rect.h"
+
+#define IPC_MESSAGE_START SpeechInputMsgStart
+
+namespace speech_input {
+struct SpeechInputResultItem;
+}
+
+// Used to start a speech recognition session.
+struct SpeechInputHostMsg_StartRecognition_Params {
+  SpeechInputHostMsg_StartRecognition_Params();
+  ~SpeechInputHostMsg_StartRecognition_Params();
+
+  int render_view_id;  // The render view requesting speech recognition.
+  int request_id;  // Request ID used within the render view.
+  gfx::Rect element_rect;  // Position of the UI element in page coordinates.
+  std::string language;  // Language to use for speech recognition.
+  std::string grammar;  // Speech grammar given by the speech input element.
+  std::string origin_url;  // URL of the page (or iframe if applicable).
+};
+
+namespace IPC {
+
+template <>
+struct ParamTraits<speech_input::SpeechInputResultItem> {
+  typedef speech_input::SpeechInputResultItem param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<SpeechInputHostMsg_StartRecognition_Params> {
+  typedef SpeechInputHostMsg_StartRecognition_Params param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
+}  // namespace IPC
+
+// Speech input messages sent from the renderer to the browser.
+
+// Requests the speech input service to start speech recognition on behalf of
+// the given |render_view_id|.
+IPC_MESSAGE_CONTROL1(SpeechInputHostMsg_StartRecognition,
+                     SpeechInputHostMsg_StartRecognition_Params)
+
+// Requests the speech input service to cancel speech recognition on behalf of
+// the given |render_view_id|. If speech recognition is not happening or
+// is happening on behalf of some other render view, this call does nothing.
+IPC_MESSAGE_CONTROL2(SpeechInputHostMsg_CancelRecognition,
+                     int /* render_view_id */,
+                     int /* request_id */)
+
+// Requests the speech input service to stop audio recording on behalf of
+// the given |render_view_id|. Any audio recorded so far will be fed to the
+// speech recognizer. If speech recognition is not happening nor or is
+// happening on behalf of some other render view, this call does nothing.
+IPC_MESSAGE_CONTROL2(SpeechInputHostMsg_StopRecording,
+                     int /* render_view_id */,
+                     int /* request_id */)
+
+// Speech input messages sent from the browser to the renderer.
+
+// Relay a speech recognition result, either partial or final.
+IPC_MESSAGE_ROUTED2(SpeechInputMsg_SetRecognitionResult,
+                    int /* request_id */,
+                    speech_input::SpeechInputResultArray /* result */)
+
+// Indicate that speech recognizer has stopped recording and started
+// recognition.
+IPC_MESSAGE_ROUTED1(SpeechInputMsg_RecordingComplete,
+                    int /* request_id */)
+
+// Indicate that speech recognizer has completed recognition. This will be
+// the last message sent in response to a
+// ViewHostMsg_SpeechInput_StartRecognition.
+IPC_MESSAGE_ROUTED1(SpeechInputMsg_RecognitionComplete,
+                    int /* request_id */)
+
+#endif  // CHROME_COMMON_SPEECH_INPUT_MESSAGES_H_
diff --git a/chrome/common/spellcheck_common.cc b/chrome/common/spellcheck_common.cc
index c52dcba..33234dc 100644
--- a/chrome/common/spellcheck_common.cc
+++ b/chrome/common/spellcheck_common.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -73,9 +73,6 @@
   // with additional words found by the translation team.
   static const char kDefaultVersionString[] = "-1-2";
 
-  // The following dictionaries have either not been augmented with additional
-  // words (version 1-1) or have new words, as well as an upgraded dictionary
-  // as of Feb 2009 (version 1-3).
   static const struct {
     // The language input.
     const char* language;
@@ -83,9 +80,7 @@
     // The corresponding version.
     const char* version;
   } special_version_string[] = {
-    {"en-AU", "-1-1"},
-    {"en-GB", "-1-1"},
-    {"es-ES", "-1-1"},
+    {"es-ES", "-1-1"}, // 1-1: Have not been augmented with addtional words.
     {"nl-NL", "-1-1"},
     {"sv-SE", "-1-1"},
     {"he-IL", "-1-1"},
@@ -93,14 +88,15 @@
     {"hi-IN", "-1-1"},
     {"tr-TR", "-1-1"},
     {"et-EE", "-1-1"},
-    {"fr-FR", "-2-0"}, // Hunspell fr(modern) 3.7 + Chromium delta.
-    {"lt-LT", "-1-3"},
+    {"lt-LT", "-1-3"}, // 1-3 (Feb 2009): new words, as well as an upgraded
+                       // dictionary.
     {"pl-PL", "-1-3"},
+    {"fr-FR", "-2-0"}, // 2-0 (2010): upgraded dictionaries.
     {"hu-HU", "-2-0"},
     {"ro-RO", "-2-0"},
     {"ru-RU", "-2-0"},
     {"bg-BG", "-2-0"},
-    {"sr", "-2-0"},
+    {"sr",    "-2-0"},
     {"uk-UA", "-2-0"},
   };
 
diff --git a/chrome/common/sqlite_utils.cc b/chrome/common/sqlite_utils.cc
index 9d16c7f..15ae2c2 100644
--- a/chrome/common/sqlite_utils.cc
+++ b/chrome/common/sqlite_utils.cc
@@ -7,11 +7,11 @@
 #include <list>
 
 #include "base/file_path.h"
-#include "base/lock.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/stl_util-inl.h"
 #include "base/string16.h"
+#include "base/synchronization/lock.h"
 
 // The vanilla error handler implements the common fucntionality for all the
 // error handlers. Specialized error handlers are expected to only override
@@ -67,13 +67,13 @@
 
  private:
   void AddHandler(SQLErrorHandler* handler) {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     errors_.push_back(handler);
   }
 
   typedef std::list<SQLErrorHandler*> ErrorList;
   ErrorList errors_;
-  Lock lock_;
+  base::Lock lock_;
 };
 
 static base::LazyInstance<DefaultSQLErrorHandlerFactory>
diff --git a/chrome/common/switch_utils_unittest.cc b/chrome/common/switch_utils_unittest.cc
index 2c73b17..46a17d6 100644
--- a/chrome/common/switch_utils_unittest.cc
+++ b/chrome/common/switch_utils_unittest.cc
@@ -5,7 +5,6 @@
 #include "chrome/common/switch_utils.h"
 
 #include "base/command_line.h"
-#include "chrome/common/chrome_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(SwitchUtilsTest, RemoveSwitches) {
diff --git a/chrome/common/thumbnail_score.cc b/chrome/common/thumbnail_score.cc
index dc7856d..f878e31 100644
--- a/chrome/common/thumbnail_score.cc
+++ b/chrome/common/thumbnail_score.cc
@@ -5,12 +5,15 @@
 #include "chrome/common/thumbnail_score.h"
 
 #include "base/logging.h"
+#include "base/stringprintf.h"
 
 using base::Time;
 using base::TimeDelta;
 
 const TimeDelta ThumbnailScore::kUpdateThumbnailTime = TimeDelta::FromDays(1);
 const double ThumbnailScore::kThumbnailMaximumBoringness = 0.94;
+// Per crbug.com/65936#c4, 91.83% of thumbnail scores are less than 0.70.
+const double ThumbnailScore::kThumbnailInterestingEnoughBoringness = 0.70;
 const double ThumbnailScore::kThumbnailDegradePerHour = 0.01;
 
 // Calculates a numeric score from traits about where a snapshot was
@@ -70,6 +73,16 @@
       redirect_hops_from_dest == rhs.redirect_hops_from_dest;
 }
 
+std::string ThumbnailScore::ToString() const {
+  return StringPrintf("boring_score: %f, at_top %d, good_clipping %d, "
+                      "time_at_snapshot: %f, redirect_hops_from_dest: %d",
+                      boring_score,
+                      at_top,
+                      good_clipping,
+                      time_at_snapshot.ToDoubleT(),
+                      redirect_hops_from_dest);
+}
+
 bool ShouldReplaceThumbnailWith(const ThumbnailScore& current,
                                 const ThumbnailScore& replacement) {
   int current_type = GetThumbnailType(current.good_clipping, current.at_top);
@@ -116,3 +129,16 @@
   return current.boring_score >= ThumbnailScore::kThumbnailMaximumBoringness &&
       replacement.boring_score < ThumbnailScore::kThumbnailMaximumBoringness;
 }
+
+bool ThumbnailScore::ShouldConsiderUpdating() {
+  const TimeDelta time_elapsed = Time::Now() - time_at_snapshot;
+  // Consider the current thumbnail to be new and interesting enough if
+  // the following critera are met.
+  const bool new_and_interesting_enough =
+      (time_elapsed < kUpdateThumbnailTime &&
+       good_clipping && at_top &&
+       boring_score < kThumbnailInterestingEnoughBoringness);
+  // We want to generate a new thumbnail when the current thumbnail is
+  // sufficiently old or uninteresting.
+  return !new_and_interesting_enough;
+}
diff --git a/chrome/common/thumbnail_score.h b/chrome/common/thumbnail_score.h
index 30bcf8f..39fe0e2 100644
--- a/chrome/common/thumbnail_score.h
+++ b/chrome/common/thumbnail_score.h
@@ -6,6 +6,7 @@
 #define CHROME_COMMON_THUMBNAIL_SCORE_H_
 #pragma once
 
+#include <string>
 #include "base/time.h"
 
 // A set of metadata about a Thumbnail.
@@ -27,6 +28,9 @@
   // Tests for equivalence between two ThumbnailScore objects.
   bool Equals(const ThumbnailScore& rhs) const;
 
+  // Returns string representation of this object.
+  std::string ToString() const;
+
   // How "boring" a thumbnail is. The boring score is the 0,1 ranged
   // percentage of pixels that are the most common luma. Higher boring
   // scores indicate that a higher percentage of a bitmap are all the
@@ -67,6 +71,10 @@
   // How bad a thumbnail needs to be before we completely ignore it.
   static const double kThumbnailMaximumBoringness;
 
+  // We consider a thumbnail interesting enough if the boring score is
+  // lower than this.
+  static const double kThumbnailInterestingEnoughBoringness;
+
   // Time before we take a worse thumbnail (subject to
   // kThumbnailMaximumBoringness) over what's currently in the database
   // for freshness.
@@ -74,6 +82,11 @@
 
   // Penalty of how much more boring a thumbnail should be per hour.
   static const double kThumbnailDegradePerHour;
+
+  // Checks whether we should consider updating a new thumbnail based on
+  // this score. For instance, we don't have to update a new thumbnail
+  // if the current thumbnail is new and interesting enough.
+  bool ShouldConsiderUpdating();
 };
 
 // Checks whether we should replace one thumbnail with another.
diff --git a/chrome/common/thumbnail_score_unittest.cc b/chrome/common/thumbnail_score_unittest.cc
index 14d79dd..1defee3 100644
--- a/chrome/common/thumbnail_score_unittest.cc
+++ b/chrome/common/thumbnail_score_unittest.cc
@@ -52,3 +52,27 @@
   lotsa_redirects.redirect_hops_from_dest = 4;
   EXPECT_FALSE(ShouldReplaceThumbnailWith(no_redirects, lotsa_redirects));
 }
+
+TEST(ThumbnailScoreTest, ShouldConsiderUpdating) {
+  ThumbnailScore score;
+  // By default, the score is 1.0, meaning very boring, thus we should
+  // generate a new thumbnail.
+  EXPECT_DOUBLE_EQ(1.0, score.boring_score);
+  EXPECT_TRUE(score.ShouldConsiderUpdating());
+
+  // Make it very interesting, but this is not enough.
+  score.boring_score = 0.0;
+  EXPECT_TRUE(score.ShouldConsiderUpdating());
+
+  // good_clipping is important, but sill not enough.
+  score.good_clipping = true;
+  EXPECT_TRUE(score.ShouldConsiderUpdating());
+
+  // at_top is important. Finally, the thumbnail is new and interesting enough.
+  score.at_top = true;
+  EXPECT_FALSE(score.ShouldConsiderUpdating());
+
+  // Make it old. Then, it's no longer new enough.
+  score.time_at_snapshot -= ThumbnailScore::kUpdateThumbnailTime;
+  EXPECT_TRUE(score.ShouldConsiderUpdating());
+}
diff --git a/chrome/common/time_format.cc b/chrome/common/time_format.cc
index 9de3a40..249aae2 100644
--- a/chrome/common/time_format.cc
+++ b/chrome/common/time_format.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "app/l10n_util.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
@@ -15,6 +14,7 @@
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "unicode/datefmt.h"
 #include "unicode/locid.h"
 #include "unicode/plurfmt.h"
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index e4c56fc..719ffd4 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -1,5 +1,4 @@
-
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,6 +17,7 @@
 const char kDataScheme[] = "data";
 const char kExtensionScheme[] = "chrome-extension";
 const char kFileScheme[] = "file";
+const char kFileSystemScheme[] = "filesystem";
 const char kFtpScheme[] = "ftp";
 const char kGearsScheme[] = "gears";
 const char kHttpScheme[] = "http";
@@ -51,6 +51,7 @@
 const char kAboutCacheURL[] = "about:cache";
 const char kAboutConflicts[] = "about:conflicts";
 const char kAboutCrashURL[] = "about:crash";
+const char kAboutKillURL[] = "about:kill";
 const char kAboutCreditsURL[] = "about:credits";
 const char kAboutDNSURL[] = "about:dns";
 const char kAboutFlagsURL[] = "about:flags";
@@ -63,6 +64,8 @@
 const char kAboutNetInternalsURL[] = "about:net-internals";
 const char kAboutPluginsURL[] = "about:plugins";
 const char kAboutShorthangURL[] = "about:shorthang";
+const char kAboutSyncURL[] = "about:sync";
+const char kAboutSyncInternalsURL[] = "about:sync-internals";
 const char kAboutTermsURL[] = "about:terms";
 const char kAboutVaporwareURL[] = "about:vaporware";
 const char kAboutVersionURL[] = "about:version";
@@ -96,6 +99,7 @@
 
 #if defined(OS_CHROMEOS)
 const char kChromeUIAboutOSCreditsURL[] = "chrome://about/os-credits";
+const char kChromeUIActivationMessage[] = "chrome://activationmessage/";
 const char kChromeUIFileBrowseURL[] = "chrome://filebrowse/";
 const char kChromeUIImageBurnerURL[] = "chrome://imageburner/";
 const char kChromeUIKeyboardOverlayURL[] = "chrome://keyboardoverlay/";
@@ -131,12 +135,14 @@
 const char kChromeUIResourcesHost[] = "resources";
 const char kChromeUIScreenshotPath[] = "screenshots";
 const char kChromeUISettingsHost[] = "settings";
+const char kChromeUISyncInternalsHost[] = "sync-internals";
 const char kChromeUISyncResourcesHost[] = "syncresources";
 const char kChromeUITextfieldsHost[] = "textfields";
 const char kChromeUIThemePath[] = "theme";
 const char kChromeUIThumbnailPath[] = "thumb";
 
 #if defined(OS_CHROMEOS)
+const char kChromeUIActivationMessageHost[] = "activationmessage";
 const char kChromeUIFileBrowseHost[] = "filebrowse";
 const char kChromeUIImageBurnerHost[] = "imageburner";
 const char kChromeUIKeyboardOverlayHost[] = "keyboardoverlay";
@@ -163,6 +169,8 @@
 const char kNetworkViewInternalsURL[] = "chrome://net-internals/";
 const char kNetworkViewCacheURL[] = "chrome://view-http-cache/";
 
+const char kSyncViewInternalsURL[] = "chrome://sync-internals/";
+
 // GPU sub pages
 const char kGpuInternalsURL[] = "chrome://gpu-internals/";
 
@@ -172,6 +180,7 @@
 const char kBrowserOptionsSubPage[] =  "browser";
 const char kClearBrowserDataSubPage[] = "clearBrowserDataOverlay";
 const char kContentSettingsSubPage[] = "content";
+const char kContentSettingsExceptionsSubPage[] = "contentExceptions";
 const char kDefaultOptionsSubPage[] =  "";
 const char kImportDataSubPage[] = "importDataOverlay";
 const char kPersonalOptionsSubPage[] =  "personal";
@@ -204,6 +213,15 @@
     "http://www.google.com/support/chrome/bin/answer.py?answer=95669";
 #endif
 
+// TODO: These are currently placeholders that point to the crash
+// docs.  See bug http://crosbug.com/10711
+const char kKillReasonURL[] =
+#if defined(OS_CHROMEOS)
+    "http://www.google.com/support/chromeos/bin/answer.py?answer=1047340";
+#else
+    "http://www.google.com/support/chrome/bin/answer.py?answer=95669";
+#endif
+
 const char kPrivacyLearnMoreURL[] =
 #if defined(OS_CHROMEOS)
     "http://www.google.com/support/chromeos/bin/answer.py?answer=1047334";
@@ -214,7 +232,10 @@
 const char kChromiumProjectURL[] = "http://code.google.com/chromium/";
 
 const char kLearnMoreReportingURL[] =
-    "http://www.google.com/support/chrome/bin/answer.py?answer=96817&amp;";
+    "http://www.google.com/support/chrome/bin/answer.py?answer=96817";
+
+const char kOutdatedPluginLearnMoreURL[] =
+    "http://www.google.com/support/chrome/bin/answer.py?answer=1181003";
 
 void RegisterChromeSchemes() {
   // Don't need "chrome-internal" which was used in old versions of Chrome for
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 50d1a5c..6bc0165 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,11 +15,12 @@
 extern const char kBlobScheme[];
 extern const char kChromeDevToolsScheme[];
 extern const char kChromeInternalScheme[];
-extern const char kChromeUIScheme[];  // The scheme used for DOMUIs.
+extern const char kChromeUIScheme[];  // The scheme used for WebUIs.
 extern const char kCrosScheme[];      // The scheme used for ChromeOS.
 extern const char kDataScheme[];
 extern const char kExtensionScheme[];
 extern const char kFileScheme[];
+extern const char kFileSystemScheme[];
 extern const char kFtpScheme[];
 extern const char kGearsScheme[];
 extern const char kHttpScheme[];
@@ -44,6 +45,7 @@
 extern const char kAboutConflicts[];
 extern const char kAboutCacheURL[];
 extern const char kAboutCrashURL[];
+extern const char kAboutKillURL[];
 extern const char kAboutCreditsURL[];
 extern const char kAboutDNSURL[];
 extern const char kAboutFlagsURL[];
@@ -56,6 +58,8 @@
 extern const char kAboutNetInternalsURL[];
 extern const char kAboutPluginsURL[];
 extern const char kAboutShorthangURL[];
+extern const char kAboutSyncURL[];
+extern const char kAboutSyncInternalsURL[];
 extern const char kAboutTermsURL[];
 extern const char kAboutVaporwareURL[];
 extern const char kAboutVersionURL[];
@@ -87,6 +91,7 @@
 
 #if defined(OS_CHROMEOS)
 extern const char kChromeUIAboutOSCreditsURL[];
+extern const char kChromeUIActivationMessage[];
 extern const char kChromeUIFileBrowseURL[];
 extern const char kChromeUIImageBurnerURL[];
 extern const char kChromeUIKeyboardOverlayURL[];
@@ -122,12 +127,14 @@
 extern const char kChromeUIResourcesHost[];
 extern const char kChromeUIScreenshotPath[];
 extern const char kChromeUISettingsHost[];
+extern const char kChromeUISyncInternalsHost[];
 extern const char kChromeUISyncResourcesHost[];
 extern const char kChromeUITextfieldsHost[];
 extern const char kChromeUIThemePath[];
 extern const char kChromeUIThumbnailPath[];
 
 #if defined(OS_CHROMEOS)
+extern const char kChromeUIActivationMessageHost[];
 extern const char kChromeUIFileBrowseHost[];
 extern const char kChromeUIImageBurnerHost[];
 extern const char kChromeUIKeyboardOverlayHost[];
@@ -159,6 +166,9 @@
 extern const char kNetworkViewCacheURL[];
 extern const char kNetworkViewInternalsURL[];
 
+// Sync related URLs.
+extern const char kSyncViewInternalsURL[];
+
 // GPU related URLs
 extern const char kGpuInternalsURL[];
 
@@ -168,6 +178,7 @@
 extern const char kBrowserOptionsSubPage[];
 extern const char kClearBrowserDataSubPage[];
 extern const char kContentSettingsSubPage[];
+extern const char kContentSettingsExceptionsSubPage[];
 extern const char kDefaultOptionsSubPage[];
 extern const char kImportDataSubPage[];
 extern const char kPersonalOptionsSubPage[];
@@ -188,6 +199,9 @@
 // "Learn more" URL for "Aw snap" page.
 extern const char kCrashReasonURL[];
 
+// "Learn more" URL for killed tab page.
+extern const char kKillReasonURL[];
+
 // "Learn more" URL for the Privacy section under Options.
 extern const char kPrivacyLearnMoreURL[];
 
@@ -198,6 +212,9 @@
 // first run dialog.
 extern const char kLearnMoreReportingURL[];
 
+// The URL for the "Learn more" page for the blocked/outdated plugin infobar.
+extern const char kOutdatedPluginLearnMoreURL[];
+
 // Call near the beginning of startup to register Chrome's internal URLs that
 // should be parsed as "standard" with the googleurl library.
 void RegisterChromeSchemes();
diff --git a/chrome/common/utility_messages_internal.h b/chrome/common/utility_messages_internal.h
index 5381155..11e07f2 100644
--- a/chrome/common/utility_messages_internal.h
+++ b/chrome/common/utility_messages_internal.h
@@ -6,13 +6,13 @@
 #include <vector>
 
 #include "base/platform_file.h"
-#include "gfx/rect.h"
 #include "ipc/ipc_message_macros.h"
 #include "printing/backend/print_backend.h"
 #include "printing/page_range.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/rect.h"
 
-#define IPC_MESSAGE_START NaClMsgStart
+#define IPC_MESSAGE_START UtilityMsgStart
 
 class FilePath;
 class IndexedDBKey;
diff --git a/chrome/common/web_apps.cc b/chrome/common/web_apps.cc
index b9c390c..47682fa 100644
--- a/chrome/common/web_apps.cc
+++ b/chrome/common/web_apps.cc
@@ -7,8 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
 #include "base/json/json_reader.h"
 #include "base/string16.h"
 #include "base/string_number_conversions.h"
@@ -16,17 +14,19 @@
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/common/json_schema_validator.h"
-#include "gfx/size.h"
 #include "googleurl/src/gurl.h"
 #include "grit/common_resources.h"
 #include "grit/generated_resources.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/size.h"
 #include "webkit/glue/dom_operations.h"
 
 using WebKit::WebDocument;
diff --git a/chrome/common/web_apps.h b/chrome/common/web_apps.h
index 91f2023..7e7c9cb 100644
--- a/chrome/common/web_apps.h
+++ b/chrome/common/web_apps.h
@@ -11,8 +11,8 @@
 
 #include "base/string16.h"
 #include "googleurl/src/gurl.h"
-#include "gfx/size.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/size.h"
 
 namespace WebKit {
 class WebDocument;
diff --git a/chrome/common/web_database_observer_impl.cc b/chrome/common/web_database_observer_impl.cc
index b683b72..bc027d0 100644
--- a/chrome/common/web_database_observer_impl.cc
+++ b/chrome/common/web_database_observer_impl.cc
@@ -8,8 +8,8 @@
 #include "base/message_loop.h"
 #include "base/string16.h"
 #include "chrome/common/database_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDatabase.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 WebDatabaseObserverImpl::WebDatabaseObserverImpl(
     IPC::Message::Sender* sender)
diff --git a/chrome/common/web_database_observer_impl.h b/chrome/common/web_database_observer_impl.h
index 84101c8..bb47472 100644
--- a/chrome/common/web_database_observer_impl.h
+++ b/chrome/common/web_database_observer_impl.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "ipc/ipc_message.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDatabaseObserver.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDatabaseObserver.h"
 #include "webkit/database/database_connections.h"
 
 class WebDatabaseObserverImpl : public WebKit::WebDatabaseObserver {
diff --git a/chrome/common/webblobregistry_impl.cc b/chrome/common/webblobregistry_impl.cc
index 3ab2fa4..cd74d50 100644
--- a/chrome/common/webblobregistry_impl.cc
+++ b/chrome/common/webblobregistry_impl.cc
@@ -6,9 +6,9 @@
 
 #include "base/ref_counted.h"
 #include "chrome/common/render_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebBlobData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
 #include "webkit/blob/blob_data.h"
 
 using WebKit::WebBlobData;
diff --git a/chrome/common/webblobregistry_impl.h b/chrome/common/webblobregistry_impl.h
index 79bd06c..73395d9 100644
--- a/chrome/common/webblobregistry_impl.h
+++ b/chrome/common/webblobregistry_impl.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include "ipc/ipc_message.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebBlobRegistry.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobRegistry.h"
 
 namespace WebKit {
 class WebBlobData;
diff --git a/chrome/common/webkit_param_traits.cc b/chrome/common/webkit_param_traits.cc
index 909d7fd..12c885a 100644
--- a/chrome/common/webkit_param_traits.cc
+++ b/chrome/common/webkit_param_traits.cc
@@ -5,10 +5,10 @@
 #include "chrome/common/webkit_param_traits.h"
 
 #include "base/format_macros.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerAction.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
 
 namespace IPC {
 
diff --git a/chrome/common/webkit_param_traits.h b/chrome/common/webkit_param_traits.h
index 6014f25..8d540c9 100644
--- a/chrome/common/webkit_param_traits.h
+++ b/chrome/common/webkit_param_traits.h
@@ -25,15 +25,15 @@
 #pragma once
 
 #include "ipc/ipc_message_utils.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextInputType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextInputType.h"
 
 namespace WebKit {
 struct WebCompositionUnderline;
diff --git a/chrome/common/webmessageportchannel_impl.cc b/chrome/common/webmessageportchannel_impl.cc
index 0778871..5326983 100644
--- a/chrome/common/webmessageportchannel_impl.cc
+++ b/chrome/common/webmessageportchannel_impl.cc
@@ -7,8 +7,8 @@
 #include "chrome/common/child_process.h"
 #include "chrome/common/child_thread.h"
 #include "chrome/common/worker_messages.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMessagePortChannelClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMessagePortChannelClient.h"
 
 using WebKit::WebMessagePortChannel;
 using WebKit::WebMessagePortChannelArray;
@@ -53,7 +53,7 @@
 
 void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) {
   // Must lock here since client_ is called on the main thread.
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   client_ = client;
 }
 
@@ -105,7 +105,7 @@
 bool WebMessagePortChannelImpl::tryGetMessage(
     WebString* message,
     WebMessagePortChannelArray& channels) {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (message_queue_.empty())
     return false;
 
@@ -194,7 +194,7 @@
     const string16& message,
     const std::vector<int>& sent_message_port_ids,
     const std::vector<int>& new_routing_ids) {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   Message msg;
   msg.message = message;
   if (!sent_message_port_ids.empty()) {
@@ -215,7 +215,7 @@
   std::vector<QueuedMessage> queued_messages;
 
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     queued_messages.reserve(message_queue_.size());
     while (!message_queue_.empty()) {
       string16 message = message_queue_.front().message;
diff --git a/chrome/common/webmessageportchannel_impl.h b/chrome/common/webmessageportchannel_impl.h
index 0199ebb..846a546 100644
--- a/chrome/common/webmessageportchannel_impl.h
+++ b/chrome/common/webmessageportchannel_impl.h
@@ -10,11 +10,11 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/string16.h"
 #include "base/ref_counted.h"
+#include "base/synchronization/lock.h"
 #include "ipc/ipc_channel.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMessagePortChannel.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMessagePortChannel.h"
 
 // This is thread safe.
 class WebMessagePortChannelImpl
@@ -67,7 +67,7 @@
   MessageQueue message_queue_;
 
   WebKit::WebMessagePortChannelClient* client_;
-  Lock lock_;  // Locks access to above.
+  base::Lock lock_;  // Locks access to above.
 
   int route_id_;  // The routing id for this object.
   int message_port_id_;  // A globally unique identifier for this message port.
diff --git a/chrome/common/window_container_type.cc b/chrome/common/window_container_type.cc
index b33618e..519fea3 100644
--- a/chrome/common/window_container_type.cc
+++ b/chrome/common/window_container_type.cc
@@ -5,9 +5,9 @@
 #include "chrome/common/window_container_type.h"
 
 #include "base/string_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebWindowFeatures.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
 
 namespace {
 
diff --git a/chrome/common/worker_thread_ticker.cc b/chrome/common/worker_thread_ticker.cc
index 909cc8d..abbda88 100644
--- a/chrome/common/worker_thread_ticker.cc
+++ b/chrome/common/worker_thread_ticker.cc
@@ -44,7 +44,7 @@
 
 bool WorkerThreadTicker::RegisterTickHandler(Callback *tick_handler) {
   DCHECK(tick_handler);
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   // You cannot change the list of handlers when the timer is running.
   // You need to call Stop first.
   if (IsRunning())
@@ -55,7 +55,7 @@
 
 bool WorkerThreadTicker::UnregisterTickHandler(Callback *tick_handler) {
   DCHECK(tick_handler);
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   // You cannot change the list of handlers when the timer is running.
   // You need to call Stop first.
   if (IsRunning()) {
@@ -74,7 +74,7 @@
 bool WorkerThreadTicker::Start() {
   // Do this in a lock because we don't want 2 threads to
   // call Start at the same time
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (IsRunning())
     return false;
   if (!timer_thread_.Start())
@@ -87,7 +87,7 @@
 bool WorkerThreadTicker::Stop() {
   // Do this in a lock because we don't want 2 threads to
   // call Stop at the same time
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   if (!IsRunning())
     return false;
   is_running_ = false;
diff --git a/chrome/common/worker_thread_ticker.h b/chrome/common/worker_thread_ticker.h
index d18feec..07f85eb 100644
--- a/chrome/common/worker_thread_ticker.h
+++ b/chrome/common/worker_thread_ticker.h
@@ -8,7 +8,7 @@
 
 #include <vector>
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
 
 // This class provides the following functionality:
@@ -74,7 +74,7 @@
   typedef std::vector<Callback*> TickHandlerListType;
 
   // Lock to protect is_running_ and tick_handler_list_
-  Lock lock_;
+  base::Lock lock_;
 
   base::Thread timer_thread_;
   bool is_running_;
diff --git a/chrome/common/zip.cc b/chrome/common/zip.cc
index 3e24b53..d5ff5d0 100644
--- a/chrome/common/zip.cc
+++ b/chrome/common/zip.cc
@@ -206,7 +206,7 @@
   int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
   if (stream.Open(src_dir, flags) != 0) {
     LOG(ERROR) << "Could not open stream for path "
-               << WideToASCII(src_dir.ToWStringHack());
+               << src_dir.value();
     return false;
   }
 
@@ -217,7 +217,7 @@
     if (num_bytes > 0) {
       if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) {
         LOG(ERROR) << "Could not write data to zip for path "
-                   << WideToASCII(src_dir.ToWStringHack());
+                   << src_dir.value();
         return false;
       }
     }
@@ -296,7 +296,7 @@
           file_util::FileEnumerator::DIRECTORIES));
   for (FilePath path = file_enumerator.Next(); !path.value().empty();
        path = file_enumerator.Next()) {
-    if (!include_hidden_files && path.BaseName().ToWStringHack()[0] == L'.')
+    if (!include_hidden_files && path.BaseName().value()[0] == '.')
       continue;
 
     if (!AddEntryToZip(zip_file, path, src_dir)) {
diff --git a/net/DEPS b/net/DEPS
index 49f0344..d4488e7 100644
--- a/net/DEPS
+++ b/net/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+third_party/libevent",
+  "+third_party/nss",
   "+third_party/zlib",
   "+sdch/open_vcdiff",
 ]
diff --git a/net/base/address_list.cc b/net/base/address_list.cc
index ea1ee1e..14ee0d6 100644
--- a/net/base/address_list.cc
+++ b/net/base/address_list.cc
@@ -101,18 +101,6 @@
 AddressList::AddressList() {
 }
 
-AddressList::AddressList(const AddressList& addresslist)
-    : data_(addresslist.data_) {
-}
-
-AddressList::~AddressList() {
-}
-
-AddressList& AddressList::operator=(const AddressList& addresslist) {
-  data_ = addresslist.data_;
-  return *this;
-}
-
 AddressList::AddressList(const IPAddressNumber& address, int port,
                          bool canonicalize_name) {
   struct addrinfo* ai = new addrinfo;
@@ -160,6 +148,18 @@
   SetPort(port);
 }
 
+AddressList::AddressList(const AddressList& addresslist)
+    : data_(addresslist.data_) {
+}
+
+AddressList::~AddressList() {
+}
+
+AddressList& AddressList::operator=(const AddressList& addresslist) {
+  data_ = addresslist.data_;
+  return *this;
+}
+
 void AddressList::Adopt(struct addrinfo* head) {
   data_ = new Data(head, true /*is_system_created*/);
 }
@@ -195,14 +195,6 @@
   return GetPortFromAddrinfo(data_->head);
 }
 
-bool AddressList::GetCanonicalName(std::string* canonical_name) const {
-  DCHECK(canonical_name);
-  if (!data_ || !data_->head->ai_canonname)
-    return false;
-  canonical_name->assign(data_->head->ai_canonname);
-  return true;
-}
-
 void AddressList::SetFrom(const AddressList& src, int port) {
   if (src.GetPort() == port) {
     // We can reference the data from |src| directly.
@@ -214,6 +206,14 @@
   }
 }
 
+bool AddressList::GetCanonicalName(std::string* canonical_name) const {
+  DCHECK(canonical_name);
+  if (!data_ || !data_->head->ai_canonname)
+    return false;
+  canonical_name->assign(data_->head->ai_canonname);
+  return true;
+}
+
 void AddressList::Reset() {
   data_ = NULL;
 }
diff --git a/net/base/capturing_net_log.cc b/net/base/capturing_net_log.cc
index c6d3424..2daa73a 100644
--- a/net/base/capturing_net_log.cc
+++ b/net/base/capturing_net_log.cc
@@ -25,12 +25,27 @@
 
 CapturingNetLog::~CapturingNetLog() {}
 
+void CapturingNetLog::GetEntries(EntryList* entry_list) const {
+  base::AutoLock lock(lock_);
+  *entry_list = entries_;
+}
+
+void CapturingNetLog::Clear() {
+  base::AutoLock lock(lock_);
+  entries_.clear();
+}
+
+void CapturingNetLog::SetLogLevel(NetLog::LogLevel log_level) {
+  base::AutoLock lock(lock_);
+  log_level_ = log_level;
+}
+
 void CapturingNetLog::AddEntry(EventType type,
                                const base::TimeTicks& time,
                                const Source& source,
                                EventPhase phase,
                                EventParameters* extra_parameters) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   Entry entry(type, time, source, phase, extra_parameters);
   if (entries_.size() + 1 < max_num_entries_)
     entries_.push_back(entry);
@@ -41,25 +56,10 @@
 }
 
 NetLog::LogLevel CapturingNetLog::GetLogLevel() const {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
   return log_level_;
 }
 
-void CapturingNetLog::GetEntries(EntryList* entry_list) const {
-  AutoLock lock(lock_);
-  *entry_list = entries_;
-}
-
-void CapturingNetLog::Clear() {
-  AutoLock lock(lock_);
-  entries_.clear();
-}
-
-void CapturingNetLog::SetLogLevel(NetLog::LogLevel log_level) {
-  AutoLock lock(lock_);
-  log_level_ = log_level;
-}
-
 CapturingBoundNetLog::CapturingBoundNetLog(const NetLog::Source& source,
                                            CapturingNetLog* net_log)
     : source_(source), capturing_net_log_(net_log) {
diff --git a/net/base/capturing_net_log.h b/net/base/capturing_net_log.h
index 193d641..a7406af 100644
--- a/net/base/capturing_net_log.h
+++ b/net/base/capturing_net_log.h
@@ -10,9 +10,9 @@
 
 #include "base/atomicops.h"
 #include "base/basictypes.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "net/base/net_log.h"
 
@@ -47,6 +47,13 @@
   explicit CapturingNetLog(size_t max_num_entries);
   virtual ~CapturingNetLog();
 
+  // Returns the list of all entries in the log.
+  void GetEntries(EntryList* entry_list) const;
+
+  void Clear();
+
+  void SetLogLevel(NetLog::LogLevel log_level);
+
   // NetLog implementation:
   virtual void AddEntry(EventType type,
                         const base::TimeTicks& time,
@@ -56,16 +63,9 @@
   virtual uint32 NextID();
   virtual LogLevel GetLogLevel() const;
 
-  // Returns the list of all entries in the log.
-  void GetEntries(EntryList* entry_list) const;
-
-  void Clear();
-
-  void SetLogLevel(NetLog::LogLevel log_level);
-
  private:
   // Needs to be "mutable" so can use it in GetEntries().
-  mutable Lock lock_;
+  mutable base::Lock lock_;
 
   // Last assigned source ID.  Incremented to get the next one.
   base::subtle::Atomic32 last_id_;
diff --git a/net/base/cert_database.h b/net/base/cert_database.h
index 5ffb6a2..69290ab 100644
--- a/net/base/cert_database.h
+++ b/net/base/cert_database.h
@@ -16,6 +16,7 @@
 
 namespace net {
 
+class CryptoModule;
 class X509Certificate;
 typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
 
@@ -72,10 +73,16 @@
   // instance of all certificates.)
   void ListCerts(CertificateList* certs);
 
-  // Import certificates and private keys from PKCS #12 blob.
+  // Get the default module.
+  // The returned pointer must be stored in a scoped_refptr<CryptoModule>.
+  CryptoModule* GetDefaultModule() const;
+
+  // Import certificates and private keys from PKCS #12 blob into the module.
   // Returns OK or a network error code such as ERR_PKCS12_IMPORT_BAD_PASSWORD
   // or ERR_PKCS12_IMPORT_ERROR.
-  int ImportFromPKCS12(const std::string& data, const string16& password);
+  int ImportFromPKCS12(net::CryptoModule* module,
+                       const std::string& data,
+                       const string16& password);
 
   // Export the given certificates and private keys into a PKCS #12 blob,
   // storing into |output|.
diff --git a/net/base/cert_database_mac.cc b/net/base/cert_database_mac.cc
index b0afd50..e90a712 100644
--- a/net/base/cert_database_mac.cc
+++ b/net/base/cert_database_mac.cc
@@ -7,8 +7,8 @@
 #include <Security/Security.h>
 
 #include "base/crypto/cssm_init.h"
-#include "base/lock.h"
 #include "base/logging.h"
+#include "base/synchronization/lock.h"
 #include "net/base/net_errors.h"
 #include "net/base/x509_certificate.h"
 
@@ -43,7 +43,7 @@
 int CertDatabase::AddUserCert(X509Certificate* cert) {
   OSStatus err;
   {
-    AutoLock locked(base::GetMacSecurityServicesLock());
+    base::AutoLock locked(base::GetMacSecurityServicesLock());
     err = SecCertificateAddToKeychain(cert->os_cert_handle(), NULL);
   }
   switch (err) {
diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc
index a32a7a3..db2c47a 100644
--- a/net/base/cert_database_nss.cc
+++ b/net/base/cert_database_nss.cc
@@ -12,7 +12,9 @@
 
 #include "base/logging.h"
 #include "base/nss_util.h"
+#include "base/nss_util_internal.h"
 #include "base/scoped_ptr.h"
+#include "net/base/crypto_module.h"
 #include "net/base/net_errors.h"
 #include "net/base/x509_certificate.h"
 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
@@ -106,9 +108,23 @@
   CERT_DestroyCertList(cert_list);
 }
 
+CryptoModule* CertDatabase::GetDefaultModule() const {
+  CryptoModule* module =
+      CryptoModule::CreateFromHandle(base::GetDefaultNSSKeySlot());
+  // The module is already referenced when returned from GetDefaultNSSKeymodule,
+  // so we need to deref it once.
+  PK11_FreeSlot(module->os_module_handle());
+
+  return module;
+}
+
 int CertDatabase::ImportFromPKCS12(
-    const std::string& data, const string16& password) {
-  return psm::nsPKCS12Blob_Import(data.data(), data.size(), password);
+    net::CryptoModule* module,
+    const std::string& data,
+    const string16& password) {
+  return psm::nsPKCS12Blob_Import(module->os_module_handle(),
+                                  data.data(), data.size(),
+                                  password);
 }
 
 int CertDatabase::ExportToPKCS12(
diff --git a/net/base/cert_database_nss_unittest.cc b/net/base/cert_database_nss_unittest.cc
index 8e69104..081aeb6 100644
--- a/net/base/cert_database_nss_unittest.cc
+++ b/net/base/cert_database_nss_unittest.cc
@@ -10,16 +10,17 @@
 #include "base/crypto/scoped_nss_types.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
+#include "base/lazy_instance.h"
 #include "base/nss_util.h"
 #include "base/nss_util_internal.h"
 #include "base/path_service.h"
 #include "base/scoped_temp_dir.h"
-#include "base/singleton.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "net/base/cert_database.h"
 #include "net/base/cert_status_flags.h"
 #include "net/base/cert_verify_result.h"
+#include "net/base/crypto_module.h"
 #include "net/base/net_errors.h"
 #include "net/base/x509_certificate.h"
 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
@@ -104,30 +105,40 @@
 class CertDatabaseNSSTest : public testing::Test {
  public:
   virtual void SetUp() {
-    ASSERT_TRUE(temp_db_dir_.CreateUniqueTempDir());
-    ASSERT_TRUE(
-        base::OpenTestNSSDB(temp_db_dir_.path(), "CertDatabaseNSSTest db"));
-    slot_.reset(base::GetDefaultNSSKeySlot());
+    if (!temp_db_initialized_) {
+      ASSERT_TRUE(temp_db_dir_.Get().CreateUniqueTempDir());
+      ASSERT_TRUE(
+          base::OpenTestNSSDB(temp_db_dir_.Get().path(),
+                              "CertDatabaseNSSTest db"));
+      temp_db_initialized_ = true;
+    }
+    slot_ = cert_db_.GetDefaultModule();
 
     // Test db should be empty at start of test.
-    EXPECT_EQ(0U, ListCertsInSlot(slot_.get()).size());
+    EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
   }
   virtual void TearDown() {
     // Don't try to cleanup if the setup failed.
-    ASSERT_TRUE(slot_.get());
+    ASSERT_TRUE(slot_->os_module_handle());
 
-    EXPECT_TRUE(CleanupSlotContents(slot_.get()));
-    EXPECT_EQ(0U, ListCertsInSlot(slot_.get()).size());
+    EXPECT_TRUE(CleanupSlotContents(slot_->os_module_handle()));
+    EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
   }
 
  protected:
-  base::ScopedPK11Slot slot_;
+  scoped_refptr<CryptoModule> slot_;
   CertDatabase cert_db_;
 
  private:
-  ScopedTempDir temp_db_dir_;
+  static base::LazyInstance<ScopedTempDir> temp_db_dir_;
+  static bool temp_db_initialized_;
 };
 
+// static
+base::LazyInstance<ScopedTempDir> CertDatabaseNSSTest::temp_db_dir_(
+    base::LINKER_INITIALIZED);
+bool CertDatabaseNSSTest::temp_db_initialized_ = false;
+
 TEST_F(CertDatabaseNSSTest, ListCerts) {
   // This test isn't terribly useful, though it will at least let valgrind test
   // for leaks.
@@ -142,18 +153,22 @@
   std::string pkcs12_data = ReadTestFile("client.p12");
 
   EXPECT_EQ(ERR_PKCS12_IMPORT_BAD_PASSWORD,
-            cert_db_.ImportFromPKCS12(pkcs12_data, ASCIIToUTF16("")));
+            cert_db_.ImportFromPKCS12(slot_,
+                                      pkcs12_data,
+                                      ASCIIToUTF16("")));
 
   // Test db should still be empty.
-  EXPECT_EQ(0U, ListCertsInSlot(slot_.get()).size());
+  EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
 }
 
 TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AndExportAgain) {
   std::string pkcs12_data = ReadTestFile("client.p12");
 
-  EXPECT_EQ(OK, cert_db_.ImportFromPKCS12(pkcs12_data, ASCIIToUTF16("12345")));
+  EXPECT_EQ(OK, cert_db_.ImportFromPKCS12(slot_,
+                                          pkcs12_data,
+                                          ASCIIToUTF16("12345")));
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   scoped_refptr<X509Certificate> cert(cert_list[0]);
 
@@ -179,12 +194,12 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_SSL,
-                                         &failed));
+  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_SSL,
+                                     &failed));
 
   EXPECT_EQ(0U, failed.size());
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   scoped_refptr<X509Certificate> cert(cert_list[0]);
   EXPECT_EQ("Test CA", cert->subject().common_name);
@@ -211,12 +226,12 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_EMAIL,
-                                         &failed));
+  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_EMAIL,
+                                     &failed));
 
   EXPECT_EQ(0U, failed.size());
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   scoped_refptr<X509Certificate> cert(cert_list[0]);
   EXPECT_EQ("Test CA", cert->subject().common_name);
@@ -242,12 +257,12 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_OBJ_SIGN,
-                                         &failed));
+  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_OBJ_SIGN,
+                                     &failed));
 
   EXPECT_EQ(0U, failed.size());
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   scoped_refptr<X509Certificate> cert(cert_list[0]);
   EXPECT_EQ("Test CA", cert->subject().common_name);
@@ -273,8 +288,8 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true,
-            cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_SSL, &failed));
+  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_SSL,
+                                     &failed));
   ASSERT_EQ(1U, failed.size());
   // Note: this compares pointers directly.  It's okay in this case because
   // ImportCACerts returns the same pointers that were passed in.  In the
@@ -282,7 +297,7 @@
   EXPECT_EQ(certs[0], failed[0].certificate);
   EXPECT_EQ(ERR_IMPORT_CA_CERT_NOT_CA, failed[0].net_error);
 
-  EXPECT_EQ(0U, ListCertsInSlot(slot_.get()).size());
+  EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
 }
 
 TEST_F(CertDatabaseNSSTest, ImportCACertHierarchy) {
@@ -297,7 +312,7 @@
   // work (see
   // http://mxr.mozilla.org/mozilla/source/security/nss/lib/certhigh/certvfy.c#752
   // "XXX This choice of trustType seems arbitrary.")
-  EXPECT_EQ(true, cert_db_.ImportCACerts(
+  EXPECT_TRUE(cert_db_.ImportCACerts(
       certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
       &failed));
 
@@ -305,7 +320,7 @@
   EXPECT_EQ("www.us.army.mil", failed[0].certificate->subject().common_name);
   EXPECT_EQ(ERR_IMPORT_CA_CERT_NOT_CA, failed[0].net_error);
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(2U, cert_list.size());
   EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
   EXPECT_EQ("DOD CA-17", cert_list[1]->subject().common_name);
@@ -317,12 +332,12 @@
 
   // First import just the root.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(
+  EXPECT_TRUE(cert_db_.ImportCACerts(
       certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
       &failed));
 
   EXPECT_EQ(0U, failed.size());
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
 
@@ -332,7 +347,7 @@
   // Now import with the other certs in the list too.  Even though the root is
   // already present, we should still import the rest.
   failed.clear();
-  EXPECT_EQ(true, cert_db_.ImportCACerts(
+  EXPECT_TRUE(cert_db_.ImportCACerts(
       certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
       &failed));
 
@@ -342,7 +357,7 @@
   EXPECT_EQ("www.us.army.mil", failed[1].certificate->subject().common_name);
   EXPECT_EQ(ERR_IMPORT_CA_CERT_NOT_CA, failed[1].net_error);
 
-  cert_list = ListCertsInSlot(slot_.get());
+  cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(2U, cert_list.size());
   EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
   EXPECT_EQ("DOD CA-17", cert_list[1]->subject().common_name);
@@ -355,8 +370,7 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(certs, CertDatabase::UNTRUSTED,
-                                         &failed));
+  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::UNTRUSTED, &failed));
 
   ASSERT_EQ(1U, failed.size());
   EXPECT_EQ("DOD CA-17", failed[0].certificate->subject().common_name);
@@ -364,7 +378,7 @@
   // SEC_ERROR_UNTRUSTED_ISSUER
   EXPECT_EQ(ERR_FAILED, failed[0].net_error);
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
 }
@@ -377,13 +391,13 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(
+  EXPECT_TRUE(cert_db_.ImportCACerts(
       certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
       &failed));
 
   EXPECT_EQ(0U, failed.size());
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(3U, cert_list.size());
   EXPECT_EQ("DOD CA-13", cert_list[0]->subject().common_name);
   EXPECT_EQ("DoD Root CA 2", cert_list[1]->subject().common_name);
@@ -401,7 +415,7 @@
 
   // Import it.
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportCACerts(
+  EXPECT_TRUE(cert_db_.ImportCACerts(
       certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL |
       CertDatabase::TRUSTED_OBJ_SIGN, &failed));
 
@@ -413,7 +427,7 @@
   EXPECT_EQ("DOD CA-17", failed[1].certificate->subject().common_name);
   EXPECT_EQ(ERR_FAILED, failed[1].net_error);
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   EXPECT_EQ("Test CA", cert_list[0]->subject().common_name);
 }
@@ -429,11 +443,11 @@
   ASSERT_EQ(2U, certs.size());
 
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportServerCert(certs, &failed));
+  EXPECT_TRUE(cert_db_.ImportServerCert(certs, &failed));
 
   EXPECT_EQ(0U, failed.size());
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(2U, cert_list.size());
   scoped_refptr<X509Certificate> goog_cert(cert_list[0]);
   scoped_refptr<X509Certificate> thawte_cert(cert_list[1]);
@@ -457,11 +471,11 @@
   ASSERT_TRUE(ReadCertIntoList("punycodetest.der", &certs));
 
   CertDatabase::ImportCertFailureList failed;
-  EXPECT_EQ(true, cert_db_.ImportServerCert(certs, &failed));
+  EXPECT_TRUE(cert_db_.ImportServerCert(certs, &failed));
 
   EXPECT_EQ(0U, failed.size());
 
-  CertificateList cert_list = ListCertsInSlot(slot_.get());
+  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
   ASSERT_EQ(1U, cert_list.size());
   scoped_refptr<X509Certificate> puny_cert(cert_list[0]);
 
diff --git a/net/base/cert_database_openssl.cc b/net/base/cert_database_openssl.cc
index ec5ec24..51a2308 100644
--- a/net/base/cert_database_openssl.cc
+++ b/net/base/cert_database_openssl.cc
@@ -40,7 +40,14 @@
   NOTIMPLEMENTED();
 }
 
-int CertDatabase::ImportFromPKCS12(const std::string& data,
+CryptoModule* CertDatabase::GetDefaultModule() const {
+  // TODO(bulach): implement me.
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+int CertDatabase::ImportFromPKCS12(net::CryptoModule* module,
+                                   const std::string& data,
                                    const string16& password) {
   // TODO(bulach): implement me.
   NOTIMPLEMENTED();
diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc
index 3d22dec..a3755aa 100644
--- a/net/base/cert_verifier.cc
+++ b/net/base/cert_verifier.cc
@@ -5,9 +5,9 @@
 #include "net/base/cert_verifier.h"
 
 #include "base/compiler_specific.h"
-#include "base/lock.h"
 #include "base/message_loop.h"
 #include "base/stl_util-inl.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/worker_pool.h"
 #include "net/base/net_errors.h"
 #include "net/base/x509_certificate.h"
@@ -109,6 +109,8 @@
     delete this;
   }
 
+  bool canceled() const { return !callback_; }
+
  private:
   CompletionCallback* callback_;
   CertVerifyResult* verify_result_;
@@ -145,7 +147,7 @@
   // deleted.
   void Cancel() {
     DCHECK_EQ(MessageLoop::current(), origin_loop_);
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     canceled_ = true;
   }
 
@@ -174,7 +176,7 @@
       // after the PostTask, but before unlocking |lock_|. If we do not lock in
       // this case, we will end up deleting a locked Lock, which can lead to
       // memory leaks or worse errors.
-      AutoLock locked(lock_);
+      base::AutoLock locked(lock_);
       if (!canceled_) {
         cert_verifier_->HandleResult(cert_, hostname_, flags_,
                                      error_, verify_result_);
@@ -196,7 +198,7 @@
 
     bool canceled;
     {
-      AutoLock locked(lock_);
+      base::AutoLock locked(lock_);
       canceled = canceled_;
       if (!canceled) {
         origin_loop_->PostTask(
@@ -215,7 +217,7 @@
   CertVerifier* const cert_verifier_;
 
   // lock_ protects canceled_.
-  Lock lock_;
+  base::Lock lock_;
 
   // If canceled_ is true,
   // * origin_loop_ cannot be accessed by the worker thread,
@@ -236,8 +238,10 @@
   }
 
   ~CertVerifierJob() {
-    if (worker_)
+    if (worker_) {
       worker_->Cancel();
+      DeleteAllCanceled();
+    }
   }
 
   void AddRequest(CertVerifierRequest* request) {
@@ -261,6 +265,17 @@
     }
   }
 
+  void DeleteAllCanceled() {
+    for (std::vector<CertVerifierRequest*>::iterator
+         i = requests_.begin(); i != requests_.end(); i++) {
+      if ((*i)->canceled()) {
+        delete *i;
+      } else {
+        LOG(DFATAL) << "CertVerifierRequest leaked!";
+      }
+    }
+  }
+
   std::vector<CertVerifierRequest*> requests_;
   CertVerifierWorker* worker_;
 };
@@ -328,14 +343,15 @@
     CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
                                                         this);
     job = new CertVerifierJob(worker);
-    inflight_.insert(std::make_pair(key, job));
     if (!worker->Start()) {
-      inflight_.erase(key);
       delete job;
       delete worker;
       *out_req = NULL;
-      return ERR_FAILED;  // TODO(wtc): Log an error message.
+      // TODO(wtc): log to the NetLog.
+      LOG(ERROR) << "CertVerifierWorker couldn't be started.";
+      return ERR_INSUFFICIENT_RESOURCES;  // Just a guess.
     }
+    inflight_.insert(std::make_pair(key, job));
   }
 
   CertVerifierRequest* request =
diff --git a/net/base/cert_verifier.h b/net/base/cert_verifier.h
index f0df67a..c0fc9fc 100644
--- a/net/base/cert_verifier.h
+++ b/net/base/cert_verifier.h
@@ -28,14 +28,14 @@
   CachedCertVerifyResult();
   ~CachedCertVerifyResult();
 
+  // Returns true if |current_time| is greater than or equal to |expiry|.
+  bool HasExpired(base::Time current_time) const;
+
   int error;  // The return value of CertVerifier::Verify.
   CertVerifyResult result;  // The output of CertVerifier::Verify.
 
   // The time at which the certificate verification result expires.
   base::Time expiry;
-
-  // Returns true if |current_time| is greater than or equal to |expiry|.
-  bool HasExpired(base::Time current_time) const;
 };
 
 // CertVerifier represents a service for verifying certificates.
diff --git a/net/base/cert_verifier_unittest.cc b/net/base/cert_verifier_unittest.cc
index ca5e1f4..c49a5f4 100644
--- a/net/base/cert_verifier_unittest.cc
+++ b/net/base/cert_verifier_unittest.cc
@@ -257,4 +257,26 @@
   }
 }
 
+// Tests that a canceled request is not leaked.
+TEST_F(CertVerifierTest, CancelRequestThenQuit) {
+  CertVerifier verifier;
+
+  FilePath certs_dir = GetTestCertsDirectory();
+  scoped_refptr<X509Certificate> google_cert(
+      ImportCertFromFile(certs_dir, "google.single.der"));
+  ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert);
+
+  int error;
+  CertVerifyResult verify_result;
+  TestCompletionCallback callback;
+  CertVerifier::RequestHandle request_handle;
+
+  error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+                          &callback, &request_handle);
+  ASSERT_EQ(ERR_IO_PENDING, error);
+  ASSERT_TRUE(request_handle != NULL);
+  verifier.CancelRequest(request_handle);
+  // Destroy |verifier| by going out of scope.
+}
+
 }  // namespace net
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc
index d246557..73ad5aa 100644
--- a/net/base/cookie_monster.cc
+++ b/net/base/cookie_monster.cc
@@ -98,178 +98,26 @@
 const int kVlogSetCookies = 7;
 const int kVlogGetCookies = 9;
 
-}  // namespace
-
-// static
-bool CookieMonster::enable_file_scheme_ = false;
-
-// static
-void CookieMonster::EnableFileScheme() {
-  enable_file_scheme_ = true;
+// Mozilla sorts on the path length (longest first), and then it
+// sorts by creation time (oldest first).
+// The RFC says the sort order for the domain attribute is undefined.
+bool CookieSorter(CookieMonster::CanonicalCookie* cc1,
+                  CookieMonster::CanonicalCookie* cc2) {
+  if (cc1->Path().length() == cc2->Path().length())
+    return cc1->CreationDate() < cc2->CreationDate();
+  return cc1->Path().length() > cc2->Path().length();
 }
 
-CookieMonster::CookieMonster(PersistentCookieStore* store, Delegate* delegate)
-    : initialized_(false),
-      expiry_and_key_scheme_(expiry_and_key_default_),
-      store_(store),
-      last_access_threshold_(
-          TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
-      delegate_(delegate),
-      last_statistic_record_time_(Time::Now()) {
-  InitializeHistograms();
-  SetDefaultCookieableSchemes();
-}
+bool LRUCookieSorter(const CookieMonster::CookieMap::iterator& it1,
+                     const CookieMonster::CookieMap::iterator& it2) {
+  // Cookies accessed less recently should be deleted first.
+  if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
+    return it1->second->LastAccessDate() < it2->second->LastAccessDate();
 
-CookieMonster::~CookieMonster() {
-  DeleteAll(false);
-}
-
-// Initialize all histogram counter variables used in this class.
-//
-// Normal histogram usage involves using the macros defined in
-// histogram.h, which automatically takes care of declaring these
-// variables (as statics), initializing them, and accumulating into
-// them, all from a single entry point.  Unfortunately, that solution
-// doesn't work for the CookieMonster, as it's vulnerable to races between
-// separate threads executing the same functions and hence initializing the
-// same static variables.  There isn't a race danger in the histogram
-// accumulation calls; they are written to be resilient to simultaneous
-// calls from multiple threads.
-//
-// The solution taken here is to have per-CookieMonster instance
-// variables that are constructed during CookieMonster construction.
-// Note that these variables refer to the same underlying histogram,
-// so we still race (but safely) with other CookieMonster instances
-// for accumulation.
-//
-// To do this we've expanded out the individual histogram macros calls,
-// with declarations of the variables in the class decl, initialization here
-// (done from the class constructor) and direct calls to the accumulation
-// methods where needed.  The specific histogram macro calls on which the
-// initialization is based are included in comments below.
-void CookieMonster::InitializeHistograms() {
-  // From UMA_HISTOGRAM_CUSTOM_COUNTS
-  histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
-      "Cookie.ExpirationDurationMinutes",
-      1, kMinutesInTenYears, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_between_access_interval_minutes_ = base::Histogram::FactoryGet(
-      "Cookie.BetweenAccessIntervalMinutes",
-      1, kMinutesInTenYears, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_evicted_last_access_minutes_ = base::Histogram::FactoryGet(
-      "Cookie.EvictedLastAccessMinutes",
-      1, kMinutesInTenYears, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_count_ = base::Histogram::FactoryGet(
-      "Cookie.Count", 1, 4000, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_domain_count_ = base::Histogram::FactoryGet(
-      "Cookie.DomainCount", 1, 4000, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_etldp1_count_ = base::Histogram::FactoryGet(
-      "Cookie.Etldp1Count", 1, 4000, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_domain_per_etldp1_count_ = base::Histogram::FactoryGet(
-      "Cookie.DomainPerEtldp1Count", 1, 4000, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-
-  // From UMA_HISTOGRAM_COUNTS_10000 & UMA_HISTOGRAM_CUSTOM_COUNTS
-  histogram_number_duplicate_db_cookies_ = base::Histogram::FactoryGet(
-      "Net.NumDuplicateCookiesInDb", 1, 10000, 50,
-      base::Histogram::kUmaTargetedHistogramFlag);
-
-  // From UMA_HISTOGRAM_ENUMERATION
-  histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet(
-      "Cookie.DeletionCause", 1,
-      DELETE_COOKIE_LAST_ENTRY - 1, DELETE_COOKIE_LAST_ENTRY,
-      base::Histogram::kUmaTargetedHistogramFlag);
-
-  // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
-  histogram_time_get_ = base::Histogram::FactoryTimeGet("Cookie.TimeGet",
-      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
-      50, base::Histogram::kUmaTargetedHistogramFlag);
-  histogram_time_load_ = base::Histogram::FactoryTimeGet("Cookie.TimeLoad",
-      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
-      50, base::Histogram::kUmaTargetedHistogramFlag);
-}
-
-void CookieMonster::InitStore() {
-  DCHECK(store_) << "Store must exist to initialize";
-
-  TimeTicks beginning_time(TimeTicks::Now());
-
-  // Initialize the store and sync in any saved persistent cookies.  We don't
-  // care if it's expired, insert it so it can be garbage collected, removed,
-  // and sync'd.
-  std::vector<CanonicalCookie*> cookies;
-  // Reserve space for the maximum amount of cookies a database should have.
-  // This prevents multiple vector growth / copies as we append cookies.
-  cookies.reserve(kMaxCookies);
-  store_->Load(&cookies);
-
-  // Avoid ever letting cookies with duplicate creation times into the store;
-  // that way we don't have to worry about what sections of code are safe
-  // to call while it's in that state.
-  std::set<int64> creation_times;
-
-  // Presumably later than any access time in the store.
-  Time earliest_access_time;
-
-  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
-       it != cookies.end(); ++it) {
-    int64 cookie_creation_time = (*it)->CreationDate().ToInternalValue();
-
-    if (creation_times.insert(cookie_creation_time).second) {
-      InternalInsertCookie(GetKey((*it)->Domain()), *it, false);
-      const Time cookie_access_time((*it)->LastAccessDate());
-      if (earliest_access_time.is_null() ||
-          cookie_access_time < earliest_access_time)
-        earliest_access_time = cookie_access_time;
-    } else {
-      LOG(ERROR) << base::StringPrintf("Found cookies with duplicate creation "
-                                       "times in backing store: "
-                                       "{name='%s', domain='%s', path='%s'}",
-                                       (*it)->Name().c_str(),
-                                       (*it)->Domain().c_str(),
-                                       (*it)->Path().c_str());
-      // We've been given ownership of the cookie and are throwing it
-      // away; reclaim the space.
-      delete (*it);
-    }
-  }
-  earliest_access_time_= earliest_access_time;
-
-  // After importing cookies from the PersistentCookieStore, verify that
-  // none of our other constraints are violated.
-  //
-  // In particular, the backing store might have given us duplicate cookies.
-  EnsureCookiesMapIsValid();
-
-  histogram_time_load_->AddTime(TimeTicks::Now() - beginning_time);
-}
-
-void CookieMonster::EnsureCookiesMapIsValid() {
-  lock_.AssertAcquired();
-
-  int num_duplicates_trimmed = 0;
-
-  // Iterate through all the of the cookies, grouped by host.
-  CookieMap::iterator prev_range_end = cookies_.begin();
-  while (prev_range_end != cookies_.end()) {
-    CookieMap::iterator cur_range_begin = prev_range_end;
-    const std::string key = cur_range_begin->first;  // Keep a copy.
-    CookieMap::iterator cur_range_end = cookies_.upper_bound(key);
-    prev_range_end = cur_range_end;
-
-    // Ensure no equivalent cookies for this host.
-    num_duplicates_trimmed +=
-        TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end);
-  }
-
-  // Record how many duplicates were found in the database.
-  // See InitializeHistograms() for details.
-  histogram_cookie_deletion_cause_->Add(num_duplicates_trimmed);
+  // In rare cases we might have two cookies with identical last access times.
+  // To preserve the stability of the sort, in these cases prefer to delete
+  // older cookies over newer ones.  CreationDate() is guaranteed to be unique.
+  return it1->second->CreationDate() < it2->second->CreationDate();
 }
 
 // Our strategy to find duplicates is:
@@ -277,7 +125,7 @@
 //     {list of cookies with this signature, sorted by creation time}.
 // (2) For each list with more than 1 entry, keep the cookie having the
 //     most recent creation time, and delete the others.
-namespace {
+//
 // Two cookies are considered equivalent if they have the same domain,
 // name, and path.
 struct CookieSignature {
@@ -309,123 +157,224 @@
   std::string domain;
   std::string path;
 };
+
+// Returns the effective TLD+1 for a given host. This only makes sense for http
+// and https schemes. For other schemes, the host will be returned unchanged
+// (minus any leading period).
+std::string GetEffectiveDomain(const std::string& scheme,
+                               const std::string& host) {
+  if (scheme == "http" || scheme == "https")
+    return RegistryControlledDomainService::GetDomainAndRegistry(host);
+
+  if (!CookieMonster::DomainIsHostOnly(host))
+    return host.substr(1);
+  return host;
 }
 
-int CookieMonster::TrimDuplicateCookiesForKey(
-    const std::string& key,
-    CookieMap::iterator begin,
-    CookieMap::iterator end) {
-  lock_.AssertAcquired();
+// Determine the actual cookie domain based on the domain string passed
+// (if any) and the URL from which the cookie came.
+// On success returns true, and sets cookie_domain to either a
+//   -host cookie domain (ex: "google.com")
+//   -domain cookie domain (ex: ".google.com")
+bool GetCookieDomainWithString(const GURL& url,
+                               const std::string& domain_string,
+                               std::string* result) {
+  const std::string url_host(url.host());
 
-  // Set of cookies ordered by creation time.
-  typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
-
-  // Helper map we populate to find the duplicates.
-  typedef std::map<CookieSignature, CookieSet> EquivalenceMap;
-  EquivalenceMap equivalent_cookies;
-
-  // The number of duplicate cookies that have been found.
-  int num_duplicates = 0;
-
-  // Iterate through all of the cookies in our range, and insert them into
-  // the equivalence map.
-  for (CookieMap::iterator it = begin; it != end; ++it) {
-    DCHECK_EQ(key, it->first);
-    CanonicalCookie* cookie = it->second;
-
-    CookieSignature signature(cookie->Name(), cookie->Domain(),
-                              cookie->Path());
-    CookieSet& set = equivalent_cookies[signature];
-
-    // We found a duplicate!
-    if (!set.empty())
-      num_duplicates++;
-
-    // We save the iterator into |cookies_| rather than the actual cookie
-    // pointer, since we may need to delete it later.
-    bool insert_success = set.insert(it).second;
-    DCHECK(insert_success) <<
-        "Duplicate creation times found in duplicate cookie name scan.";
+  // If no domain was specified in the domain string, default to a host cookie.
+  // We match IE/Firefox in allowing a domain=IPADDR if it matches the url
+  // ip address hostname exactly.  It should be treated as a host cookie.
+  if (domain_string.empty() ||
+      (url.HostIsIPAddress() && url_host == domain_string)) {
+    *result = url_host;
+    DCHECK(CookieMonster::DomainIsHostOnly(*result));
+    return true;
   }
 
-  // If there were no duplicates, we are done!
-  if (num_duplicates == 0)
-    return 0;
+  // Get the normalized domain specified in cookie line.
+  // Note: The RFC says we can reject a cookie if the domain
+  // attribute does not start with a dot. IE/FF/Safari however, allow a cookie
+  // of the form domain=my.domain.com, treating it the same as
+  // domain=.my.domain.com -- for compatibility we do the same here.  Firefox
+  // also treats domain=.....my.domain.com like domain=.my.domain.com, but
+  // neither IE nor Safari do this, and we don't either.
+  url_canon::CanonHostInfo ignored;
+  std::string cookie_domain(net::CanonicalizeHost(domain_string, &ignored));
+  if (cookie_domain.empty())
+    return false;
+  if (cookie_domain[0] != '.')
+    cookie_domain = "." + cookie_domain;
 
-  // Make sure we find everything below that we did above.
-  int num_duplicates_found = 0;
+  // Ensure |url| and |cookie_domain| have the same domain+registry.
+  const std::string url_scheme(url.scheme());
+  const std::string url_domain_and_registry(
+      GetEffectiveDomain(url_scheme, url_host));
+  if (url_domain_and_registry.empty())
+    return false;  // IP addresses/intranet hosts can't set domain cookies.
+  const std::string cookie_domain_and_registry(
+      GetEffectiveDomain(url_scheme, cookie_domain));
+  if (url_domain_and_registry != cookie_domain_and_registry)
+    return false;  // Can't set a cookie on a different domain + registry.
 
-  // Otherwise, delete all the duplicate cookies, both from our in-memory store
-  // and from the backing store.
-  for (EquivalenceMap::iterator it = equivalent_cookies.begin();
-       it != equivalent_cookies.end();
-       ++it) {
-    const CookieSignature& signature = it->first;
-    CookieSet& dupes = it->second;
+  // Ensure |url_host| is |cookie_domain| or one of its subdomains.  Given that
+  // we know the domain+registry are the same from the above checks, this is
+  // basically a simple string suffix check.
+  if ((url_host.length() < cookie_domain.length()) ?
+      (cookie_domain != ("." + url_host)) :
+      url_host.compare(url_host.length() - cookie_domain.length(),
+                       cookie_domain.length(), cookie_domain))
+    return false;
 
-    if (dupes.size() <= 1)
-      continue;  // This cookiename/path has no duplicates.
-    num_duplicates_found += dupes.size() - 1;
+  *result = cookie_domain;
+  return true;
+}
 
-    // Since |dups| is sorted by creation time (descending), the first cookie
-    // is the most recent one, so we will keep it. The rest are duplicates.
-    dupes.erase(dupes.begin());
+// Determine the cookie domain to use for setting the specified cookie.
+bool GetCookieDomain(const GURL& url,
+                     const CookieMonster::ParsedCookie& pc,
+                     std::string* result) {
+  std::string domain_string;
+  if (pc.HasDomain())
+    domain_string = pc.Domain();
+  return GetCookieDomainWithString(url, domain_string, result);
+}
 
-    LOG(ERROR) << base::StringPrintf(
-        "Found %d duplicate cookies for host='%s', "
-        "with {name='%s', domain='%s', path='%s'}",
-        static_cast<int>(dupes.size()),
-        key.c_str(),
-        signature.name.c_str(),
-        signature.domain.c_str(),
-        signature.path.c_str());
+std::string CanonPathWithString(const GURL& url,
+                                const std::string& path_string) {
+  // The RFC says the path should be a prefix of the current URL path.
+  // However, Mozilla allows you to set any path for compatibility with
+  // broken websites.  We unfortunately will mimic this behavior.  We try
+  // to be generous and accept cookies with an invalid path attribute, and
+  // default the path to something reasonable.
 
-    // Remove all the cookies identified by |dupes|. It is valid to delete our
-    // list of iterators one at a time, since |cookies_| is a multimap (they
-    // don't invalidate existing iterators following deletion).
-    for (CookieSet::iterator dupes_it = dupes.begin();
-         dupes_it != dupes.end();
-         ++dupes_it) {
-      InternalDeleteCookie(*dupes_it, true /*sync_to_store*/,
-                           DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
-    }
+  // The path was supplied in the cookie, we'll take it.
+  if (!path_string.empty() && path_string[0] == '/')
+    return path_string;
+
+  // The path was not supplied in the cookie or invalid, we will default
+  // to the current URL path.
+  // """Defaults to the path of the request URL that generated the
+  //    Set-Cookie response, up to, but not including, the
+  //    right-most /."""
+  // How would this work for a cookie on /?  We will include it then.
+  const std::string& url_path = url.path();
+
+  size_t idx = url_path.find_last_of('/');
+
+  // The cookie path was invalid or a single '/'.
+  if (idx == 0 || idx == std::string::npos)
+    return std::string("/");
+
+  // Return up to the rightmost '/'.
+  return url_path.substr(0, idx);
+}
+
+std::string CanonPath(const GURL& url,
+                      const CookieMonster::ParsedCookie& pc) {
+  std::string path_string;
+  if (pc.HasPath())
+    path_string = pc.Path();
+  return CanonPathWithString(url, path_string);
+}
+
+Time CanonExpirationInternal(const CookieMonster::ParsedCookie& pc,
+                             const Time& current) {
+  // First, try the Max-Age attribute.
+  uint64 max_age = 0;
+  if (pc.HasMaxAge() &&
+#ifdef COMPILER_MSVC
+      sscanf_s(
+#else
+      sscanf(
+#endif
+             pc.MaxAge().c_str(), " %" PRIu64, &max_age) == 1) {
+    return current + TimeDelta::FromSeconds(max_age);
   }
-  DCHECK_EQ(num_duplicates, num_duplicates_found);
 
-  return num_duplicates;
+  // Try the Expires attribute.
+  if (pc.HasExpires())
+    return CookieMonster::ParseCookieTime(pc.Expires());
+
+  // Invalid or no expiration, persistent cookie.
+  return Time();
 }
 
-void CookieMonster::SetDefaultCookieableSchemes() {
-  // Note: file must be the last scheme.
-  static const char* kDefaultCookieableSchemes[] = { "http", "https", "file" };
-  int num_schemes = enable_file_scheme_ ? 3 : 2;
-  SetCookieableSchemes(kDefaultCookieableSchemes, num_schemes);
+Time CanonExpiration(const CookieMonster::ParsedCookie& pc,
+                     const Time& current,
+                     const CookieOptions& options) {
+  Time expiration_time = CanonExpirationInternal(pc, current);
+
+  if (options.force_session()) {
+    // Only override the expiry  adte if it's in the future. If the expiry date
+    // is before the creation date, the cookie is supposed to be deleted.
+    if (expiration_time.is_null() || expiration_time > current)
+      return Time();
+  }
+
+  return expiration_time;
 }
 
-void CookieMonster::SetExpiryAndKeyScheme(ExpiryAndKeyScheme key_scheme) {
-  DCHECK(!initialized_);
-  expiry_and_key_scheme_ = key_scheme;
+// Helper for GarbageCollection.  If |cookie_its->size() > num_max|, remove the
+// |num_max - num_purge| most recently accessed cookies from cookie_its.
+// (In other words, leave the entries that are candidates for
+// eviction in cookie_its.)  The cookies returned will be in order sorted by
+// access time, least recently accessed first.  The access time of the least
+// recently accessed entry not returned will be placed in
+// |*lra_removed| if that pointer is set.  FindLeastRecentlyAccessed
+// returns false if no manipulation is done (because the list size is less
+// than num_max), true otherwise.
+bool FindLeastRecentlyAccessed(
+    size_t num_max,
+    size_t num_purge,
+    Time* lra_removed,
+    std::vector<CookieMonster::CookieMap::iterator>* cookie_its) {
+  DCHECK_LE(num_purge, num_max);
+  if (cookie_its->size() > num_max) {
+    VLOG(kVlogGarbageCollection)
+        << "FindLeastRecentlyAccessed() Deep Garbage Collect.";
+    num_purge += cookie_its->size() - num_max;
+    DCHECK_GT(cookie_its->size(), num_purge);
+
+    // Add 1 so that we can get the last time left in the store.
+    std::partial_sort(cookie_its->begin(), cookie_its->begin() + num_purge + 1,
+                      cookie_its->end(), LRUCookieSorter);
+    *lra_removed =
+        (*(cookie_its->begin() + num_purge))->second->LastAccessDate();
+    cookie_its->erase(cookie_its->begin() + num_purge, cookie_its->end());
+    return true;
+  }
+  return false;
 }
 
-void CookieMonster::SetClearPersistentStoreOnExit(bool clear_local_store) {
-  if(store_)
-    store_->SetClearLocalStateOnExit(clear_local_store);
+}  // namespace
+
+// static
+bool CookieMonster::enable_file_scheme_ = false;
+
+CookieMonster::CookieMonster(PersistentCookieStore* store, Delegate* delegate)
+    : initialized_(false),
+      expiry_and_key_scheme_(expiry_and_key_default_),
+      store_(store),
+      last_access_threshold_(
+          TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
+      delegate_(delegate),
+      last_statistic_record_time_(Time::Now()) {
+  InitializeHistograms();
+  SetDefaultCookieableSchemes();
 }
 
-void CookieMonster::FlushStore(Task* completion_task) {
-  AutoLock autolock(lock_);
-  if (initialized_ && store_)
-    store_->Flush(completion_task);
-  else if (completion_task)
-    MessageLoop::current()->PostTask(FROM_HERE, completion_task);
-}
-
-// The system resolution is not high enough, so we can have multiple
-// set cookies that result in the same system time.  When this happens, we
-// increment by one Time unit.  Let's hope computers don't get too fast.
-Time CookieMonster::CurrentTime() {
-  return std::max(Time::Now(),
-      Time::FromInternalValue(last_time_seen_.ToInternalValue() + 1));
+CookieMonster::CookieMonster(PersistentCookieStore* store,
+                             Delegate* delegate,
+                             int last_access_threshold_milliseconds)
+    : initialized_(false),
+      expiry_and_key_scheme_(expiry_and_key_default_),
+      store_(store),
+      last_access_threshold_(base::TimeDelta::FromMilliseconds(
+          last_access_threshold_milliseconds)),
+      delegate_(delegate),
+      last_statistic_record_time_(base::Time::Now()) {
+  InitializeHistograms();
+  SetDefaultCookieableSchemes();
 }
 
 // Parse a cookie expiration time.  We try to be lenient, but we need to
@@ -550,220 +499,187 @@
   return (domain_string.empty() || domain_string[0] != '.');
 }
 
-// Returns the effective TLD+1 for a given host. This only makes sense for http
-// and https schemes. For other schemes, the host will be returned unchanged
-// (minus any leading period).
-static std::string GetEffectiveDomain(const std::string& scheme,
-                                      const std::string& host) {
-  if (scheme == "http" || scheme == "https")
-    return RegistryControlledDomainService::GetDomainAndRegistry(host);
+bool CookieMonster::SetCookieWithDetails(
+    const GURL& url, const std::string& name, const std::string& value,
+    const std::string& domain, const std::string& path,
+    const base::Time& expiration_time, bool secure, bool http_only) {
+  base::AutoLock autolock(lock_);
 
-  if (!CookieMonster::DomainIsHostOnly(host))
-    return host.substr(1);
-  return host;
-}
-
-// A wrapper around RegistryControlledDomainService::GetDomainAndRegistry
-// to make clear we're creating a key for our local map.  Here and
-// in FindCookiesForHostAndDomain() are the only two places where
-// we need to conditionalize based on key type.
-//
-// Note that this key algorithm explicitly ignores the scheme.  This is
-// because when we're entering cookies into the map from the backing store,
-// we in general won't have the scheme at that point.
-// In practical terms, this means that file cookies will be stored
-// in the map either by an empty string or by UNC name (and will be
-// limited by kMaxCookiesPerHost), and extension cookies will be stored
-// based on the single extension id, as the extension id won't have the
-// form of a DNS host and hence GetKey() will return it unchanged.
-//
-// Arguably the right thing to do here is to make the key
-// algorithm dependent on the scheme, and make sure that the scheme is
-// available everywhere the key must be obtained (specfically at backing
-// store load time).  This would require either changing the backing store
-// database schema to include the scheme (far more trouble than it's worth), or
-// separating out file cookies into their own CookieMonster instance and
-// thus restricting each scheme to a single cookie monster (which might
-// be worth it, but is still too much trouble to solve what is currently a
-// non-problem).
-std::string CookieMonster::GetKey(const std::string& domain) const {
-  if (expiry_and_key_scheme_ == EKS_DISCARD_RECENT_AND_PURGE_DOMAIN)
-    return domain;
-
-  std::string effective_domain(
-      RegistryControlledDomainService::GetDomainAndRegistry(domain));
-  if (effective_domain.empty())
-    effective_domain = domain;
-
-  if (!effective_domain.empty() && effective_domain[0] == '.')
-    return effective_domain.substr(1);
-  return effective_domain;
-}
-
-// Determine the actual cookie domain based on the domain string passed
-// (if any) and the URL from which the cookie came.
-// On success returns true, and sets cookie_domain to either a
-//   -host cookie domain (ex: "google.com")
-//   -domain cookie domain (ex: ".google.com")
-static bool GetCookieDomainWithString(const GURL& url,
-                                      const std::string& domain_string,
-                                      std::string* result) {
-  const std::string url_host(url.host());
-
-  // If no domain was specified in the domain string, default to a host cookie.
-  // We match IE/Firefox in allowing a domain=IPADDR if it matches the url
-  // ip address hostname exactly.  It should be treated as a host cookie.
-  if (domain_string.empty() ||
-      (url.HostIsIPAddress() && url_host == domain_string)) {
-    *result = url_host;
-    DCHECK(CookieMonster::DomainIsHostOnly(*result));
-    return true;
-  }
-
-  // Get the normalized domain specified in cookie line.
-  // Note: The RFC says we can reject a cookie if the domain
-  // attribute does not start with a dot. IE/FF/Safari however, allow a cookie
-  // of the form domain=my.domain.com, treating it the same as
-  // domain=.my.domain.com -- for compatibility we do the same here.  Firefox
-  // also treats domain=.....my.domain.com like domain=.my.domain.com, but
-  // neither IE nor Safari do this, and we don't either.
-  url_canon::CanonHostInfo ignored;
-  std::string cookie_domain(net::CanonicalizeHost(domain_string, &ignored));
-  if (cookie_domain.empty())
-    return false;
-  if (cookie_domain[0] != '.')
-    cookie_domain = "." + cookie_domain;
-
-  // Ensure |url| and |cookie_domain| have the same domain+registry.
-  const std::string url_scheme(url.scheme());
-  const std::string url_domain_and_registry(
-      GetEffectiveDomain(url_scheme, url_host));
-  if (url_domain_and_registry.empty())
-    return false;  // IP addresses/intranet hosts can't set domain cookies.
-  const std::string cookie_domain_and_registry(
-      GetEffectiveDomain(url_scheme, cookie_domain));
-  if (url_domain_and_registry != cookie_domain_and_registry)
-    return false;  // Can't set a cookie on a different domain + registry.
-
-  // Ensure |url_host| is |cookie_domain| or one of its subdomains.  Given that
-  // we know the domain+registry are the same from the above checks, this is
-  // basically a simple string suffix check.
-  if ((url_host.length() < cookie_domain.length()) ?
-      (cookie_domain != ("." + url_host)) :
-      url_host.compare(url_host.length() - cookie_domain.length(),
-                       cookie_domain.length(), cookie_domain))
+  if (!HasCookieableScheme(url))
     return false;
 
-  *result = cookie_domain;
-  return true;
+  InitIfNecessary();
+
+  Time creation_time = CurrentTime();
+  last_time_seen_ = creation_time;
+
+  scoped_ptr<CanonicalCookie> cc;
+  cc.reset(CanonicalCookie::Create(
+      url, name, value, domain, path,
+      creation_time, expiration_time,
+      secure, http_only));
+
+  if (!cc.get())
+    return false;
+
+  CookieOptions options;
+  options.set_include_httponly();
+  return SetCanonicalCookie(&cc, creation_time, options);
 }
 
-// Determine the cookie domain to use for setting the specified cookie.
-static bool GetCookieDomain(const GURL& url,
-                            const CookieMonster::ParsedCookie& pc,
-                            std::string* result) {
-  std::string domain_string;
-  if (pc.HasDomain())
-    domain_string = pc.Domain();
-  return GetCookieDomainWithString(url, domain_string, result);
+
+CookieList CookieMonster::GetAllCookies() {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
+
+  // This function is being called to scrape the cookie list for management UI
+  // or similar.  We shouldn't show expired cookies in this list since it will
+  // just be confusing to users, and this function is called rarely enough (and
+  // is already slow enough) that it's OK to take the time to garbage collect
+  // the expired cookies now.
+  //
+  // Note that this does not prune cookies to be below our limits (if we've
+  // exceeded them) the way that calling GarbageCollect() would.
+  GarbageCollectExpired(Time::Now(),
+                        CookieMapItPair(cookies_.begin(), cookies_.end()),
+                        NULL);
+
+  // Copy the CanonicalCookie pointers from the map so that we can use the same
+  // sorter as elsewhere, then copy the result out.
+  std::vector<CanonicalCookie*> cookie_ptrs;
+  cookie_ptrs.reserve(cookies_.size());
+  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end(); ++it)
+    cookie_ptrs.push_back(it->second);
+  std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
+
+  CookieList cookie_list;
+  cookie_list.reserve(cookie_ptrs.size());
+  for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
+       it != cookie_ptrs.end(); ++it)
+    cookie_list.push_back(**it);
+
+  return cookie_list;
 }
 
-static std::string CanonPathWithString(const GURL& url,
-                                       const std::string& path_string) {
-  // The RFC says the path should be a prefix of the current URL path.
-  // However, Mozilla allows you to set any path for compatibility with
-  // broken websites.  We unfortunately will mimic this behavior.  We try
-  // to be generous and accept cookies with an invalid path attribute, and
-  // default the path to something reasonable.
+CookieList CookieMonster::GetAllCookiesForURLWithOptions(
+    const GURL& url,
+    const CookieOptions& options) {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
 
-  // The path was supplied in the cookie, we'll take it.
-  if (!path_string.empty() && path_string[0] == '/')
-    return path_string;
+  std::vector<CanonicalCookie*> cookie_ptrs;
+  FindCookiesForHostAndDomain(url, options, false, &cookie_ptrs);
+  std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
 
-  // The path was not supplied in the cookie or invalid, we will default
-  // to the current URL path.
-  // """Defaults to the path of the request URL that generated the
-  //    Set-Cookie response, up to, but not including, the
-  //    right-most /."""
-  // How would this work for a cookie on /?  We will include it then.
-  const std::string& url_path = url.path();
+  CookieList cookies;
+  for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
+       it != cookie_ptrs.end(); it++)
+    cookies.push_back(**it);
 
-  size_t idx = url_path.find_last_of('/');
-
-  // The cookie path was invalid or a single '/'.
-  if (idx == 0 || idx == std::string::npos)
-    return std::string("/");
-
-  // Return up to the rightmost '/'.
-  return url_path.substr(0, idx);
+  return cookies;
 }
 
-static std::string CanonPath(const GURL& url,
-                             const CookieMonster::ParsedCookie& pc) {
-  std::string path_string;
-  if (pc.HasPath())
-    path_string = pc.Path();
-  return CanonPathWithString(url, path_string);
+CookieList CookieMonster::GetAllCookiesForURL(const GURL& url) {
+  CookieOptions options;
+  options.set_include_httponly();
+
+  return GetAllCookiesForURLWithOptions(url, options);
 }
 
-static Time CanonExpirationInternal(const CookieMonster::ParsedCookie& pc,
-                                    const Time& current) {
-  // First, try the Max-Age attribute.
-  uint64 max_age = 0;
-  if (pc.HasMaxAge() &&
-#ifdef COMPILER_MSVC
-      sscanf_s(
-#else
-      sscanf(
-#endif
-             pc.MaxAge().c_str(), " %" PRIu64, &max_age) == 1) {
-    return current + TimeDelta::FromSeconds(max_age);
+int CookieMonster::DeleteAll(bool sync_to_store) {
+  base::AutoLock autolock(lock_);
+  if (sync_to_store)
+    InitIfNecessary();
+
+  int num_deleted = 0;
+  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
+    CookieMap::iterator curit = it;
+    ++it;
+    InternalDeleteCookie(curit, sync_to_store,
+                         sync_to_store ? DELETE_COOKIE_EXPLICIT :
+                             DELETE_COOKIE_DONT_RECORD /* Destruction. */);
+    ++num_deleted;
   }
 
-  // Try the Expires attribute.
-  if (pc.HasExpires())
-    return CookieMonster::ParseCookieTime(pc.Expires());
-
-  // Invalid or no expiration, persistent cookie.
-  return Time();
+  return num_deleted;
 }
 
-static Time CanonExpiration(const CookieMonster::ParsedCookie& pc,
-                            const Time& current,
-                            const CookieOptions& options) {
-  Time expiration_time = CanonExpirationInternal(pc, current);
+int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
+                                           const Time& delete_end,
+                                           bool sync_to_store) {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
 
-  if (options.force_session()) {
-    // Only override the expiry  adte if it's in the future. If the expiry date
-    // is before the creation date, the cookie is supposed to be deleted.
-    if (expiration_time.is_null() || expiration_time > current)
-      return Time();
-  }
+  int num_deleted = 0;
+  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
+    CookieMap::iterator curit = it;
+    CanonicalCookie* cc = curit->second;
+    ++it;
 
-  return expiration_time;
-}
-
-bool CookieMonster::HasCookieableScheme(const GURL& url) {
-  lock_.AssertAcquired();
-
-  // Make sure the request is on a cookie-able url scheme.
-  for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
-    // We matched a scheme.
-    if (url.SchemeIs(cookieable_schemes_[i].c_str())) {
-      // We've matched a supported scheme.
-      return true;
+    if (cc->CreationDate() >= delete_begin &&
+        (delete_end.is_null() || cc->CreationDate() < delete_end)) {
+      InternalDeleteCookie(curit, sync_to_store, DELETE_COOKIE_EXPLICIT);
+      ++num_deleted;
     }
   }
 
-  // The scheme didn't match any in our whitelist.
-  VLOG(kVlogPerCookieMonster) << "WARNING: Unsupported cookie scheme: "
-                              << url.scheme();
+  return num_deleted;
+}
+
+int CookieMonster::DeleteAllCreatedAfter(const Time& delete_begin,
+                                         bool sync_to_store) {
+  return DeleteAllCreatedBetween(delete_begin, Time(), sync_to_store);
+}
+
+int CookieMonster::DeleteAllForHost(const GURL& url) {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
+
+  if (!HasCookieableScheme(url))
+    return 0;
+
+  const std::string scheme(url.scheme());
+  const std::string host(url.host());
+
+  // We store host cookies in the store by their canonical host name;
+  // domain cookies are stored with a leading ".".  So this is a pretty
+  // simple lookup and per-cookie delete.
+  int num_deleted = 0;
+  for (CookieMapItPair its = cookies_.equal_range(GetKey(host));
+       its.first != its.second;) {
+    CookieMap::iterator curit = its.first;
+    ++its.first;
+
+    const CanonicalCookie* const cc = curit->second;
+
+    // Delete only on a match as a host cookie.
+    if (cc->IsHostCookie() && cc->IsDomainMatch(scheme, host)) {
+      num_deleted++;
+
+      InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
+    }
+  }
+  return num_deleted;
+}
+
+bool CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
+
+  for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
+       its.first != its.second; ++its.first) {
+    // The creation date acts as our unique index...
+    if (its.first->second->CreationDate() == cookie.CreationDate()) {
+      InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
+      return true;
+    }
+  }
   return false;
 }
 
 void CookieMonster::SetCookieableSchemes(
     const char* schemes[], size_t num_schemes) {
-  AutoLock autolock(lock_);
+  base::AutoLock autolock(lock_);
 
   // Cookieable Schemes must be set before first use of function.
   DCHECK(!initialized_);
@@ -773,6 +689,445 @@
                              schemes, schemes + num_schemes);
 }
 
+void CookieMonster::SetExpiryAndKeyScheme(ExpiryAndKeyScheme key_scheme) {
+  DCHECK(!initialized_);
+  expiry_and_key_scheme_ = key_scheme;
+}
+
+void CookieMonster::SetClearPersistentStoreOnExit(bool clear_local_store) {
+  if (store_)
+    store_->SetClearLocalStateOnExit(clear_local_store);
+}
+
+// static
+void CookieMonster::EnableFileScheme() {
+  enable_file_scheme_ = true;
+}
+
+void CookieMonster::FlushStore(Task* completion_task) {
+  base::AutoLock autolock(lock_);
+  if (initialized_ && store_)
+    store_->Flush(completion_task);
+  else if (completion_task)
+    MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+}
+
+bool CookieMonster::SetCookieWithOptions(const GURL& url,
+                                         const std::string& cookie_line,
+                                         const CookieOptions& options) {
+  base::AutoLock autolock(lock_);
+
+  if (!HasCookieableScheme(url)) {
+    return false;
+  }
+
+  InitIfNecessary();
+
+  return SetCookieWithCreationTimeAndOptions(url, cookie_line, Time(), options);
+}
+
+std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
+                                                 const CookieOptions& options) {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
+
+  if (!HasCookieableScheme(url)) {
+    return std::string();
+  }
+
+  TimeTicks start_time(TimeTicks::Now());
+
+  // Get the cookies for this host and its domain(s).
+  std::vector<CanonicalCookie*> cookies;
+  FindCookiesForHostAndDomain(url, options, true, &cookies);
+  std::sort(cookies.begin(), cookies.end(), CookieSorter);
+
+  std::string cookie_line;
+  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
+       it != cookies.end(); ++it) {
+    if (it != cookies.begin())
+      cookie_line += "; ";
+    // In Mozilla if you set a cookie like AAAA, it will have an empty token
+    // and a value of AAAA.  When it sends the cookie back, it will send AAAA,
+    // so we need to avoid sending =AAAA for a blank token value.
+    if (!(*it)->Name().empty())
+      cookie_line += (*it)->Name() + "=";
+    cookie_line += (*it)->Value();
+  }
+
+  histogram_time_get_->AddTime(TimeTicks::Now() - start_time);
+
+  VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
+
+  return cookie_line;
+}
+
+void CookieMonster::DeleteCookie(const GURL& url,
+                                 const std::string& cookie_name) {
+  base::AutoLock autolock(lock_);
+  InitIfNecessary();
+
+  if (!HasCookieableScheme(url))
+    return;
+
+  CookieOptions options;
+  options.set_include_httponly();
+  // Get the cookies for this host and its domain(s).
+  std::vector<CanonicalCookie*> cookies;
+  FindCookiesForHostAndDomain(url, options, true, &cookies);
+  std::set<CanonicalCookie*> matching_cookies;
+
+  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
+       it != cookies.end(); ++it) {
+    if ((*it)->Name() != cookie_name)
+      continue;
+    if (url.path().find((*it)->Path()))
+      continue;
+    matching_cookies.insert(*it);
+  }
+
+  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
+    CookieMap::iterator curit = it;
+    ++it;
+    if (matching_cookies.find(curit->second) != matching_cookies.end()) {
+      InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
+    }
+  }
+}
+
+CookieMonster* CookieMonster::GetCookieMonster() {
+  return this;
+}
+
+CookieMonster::~CookieMonster() {
+  DeleteAll(false);
+}
+
+bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
+                                              const std::string& cookie_line,
+                                              const base::Time& creation_time) {
+  base::AutoLock autolock(lock_);
+
+  if (!HasCookieableScheme(url)) {
+    return false;
+  }
+
+  InitIfNecessary();
+  return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
+                                             CookieOptions());
+}
+
+void CookieMonster::InitStore() {
+  DCHECK(store_) << "Store must exist to initialize";
+
+  TimeTicks beginning_time(TimeTicks::Now());
+
+  // Initialize the store and sync in any saved persistent cookies.  We don't
+  // care if it's expired, insert it so it can be garbage collected, removed,
+  // and sync'd.
+  std::vector<CanonicalCookie*> cookies;
+  // Reserve space for the maximum amount of cookies a database should have.
+  // This prevents multiple vector growth / copies as we append cookies.
+  cookies.reserve(kMaxCookies);
+  store_->Load(&cookies);
+
+  // Avoid ever letting cookies with duplicate creation times into the store;
+  // that way we don't have to worry about what sections of code are safe
+  // to call while it's in that state.
+  std::set<int64> creation_times;
+
+  // Presumably later than any access time in the store.
+  Time earliest_access_time;
+
+  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
+       it != cookies.end(); ++it) {
+    int64 cookie_creation_time = (*it)->CreationDate().ToInternalValue();
+
+    if (creation_times.insert(cookie_creation_time).second) {
+      InternalInsertCookie(GetKey((*it)->Domain()), *it, false);
+      const Time cookie_access_time((*it)->LastAccessDate());
+      if (earliest_access_time.is_null() ||
+          cookie_access_time < earliest_access_time)
+        earliest_access_time = cookie_access_time;
+    } else {
+      LOG(ERROR) << base::StringPrintf("Found cookies with duplicate creation "
+                                       "times in backing store: "
+                                       "{name='%s', domain='%s', path='%s'}",
+                                       (*it)->Name().c_str(),
+                                       (*it)->Domain().c_str(),
+                                       (*it)->Path().c_str());
+      // We've been given ownership of the cookie and are throwing it
+      // away; reclaim the space.
+      delete (*it);
+    }
+  }
+  earliest_access_time_= earliest_access_time;
+
+  // After importing cookies from the PersistentCookieStore, verify that
+  // none of our other constraints are violated.
+  //
+  // In particular, the backing store might have given us duplicate cookies.
+  EnsureCookiesMapIsValid();
+
+  histogram_time_load_->AddTime(TimeTicks::Now() - beginning_time);
+}
+
+void CookieMonster::EnsureCookiesMapIsValid() {
+  lock_.AssertAcquired();
+
+  int num_duplicates_trimmed = 0;
+
+  // Iterate through all the of the cookies, grouped by host.
+  CookieMap::iterator prev_range_end = cookies_.begin();
+  while (prev_range_end != cookies_.end()) {
+    CookieMap::iterator cur_range_begin = prev_range_end;
+    const std::string key = cur_range_begin->first;  // Keep a copy.
+    CookieMap::iterator cur_range_end = cookies_.upper_bound(key);
+    prev_range_end = cur_range_end;
+
+    // Ensure no equivalent cookies for this host.
+    num_duplicates_trimmed +=
+        TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end);
+  }
+
+  // Record how many duplicates were found in the database.
+  // See InitializeHistograms() for details.
+  histogram_cookie_deletion_cause_->Add(num_duplicates_trimmed);
+}
+
+int CookieMonster::TrimDuplicateCookiesForKey(
+    const std::string& key,
+    CookieMap::iterator begin,
+    CookieMap::iterator end) {
+  lock_.AssertAcquired();
+
+  // Set of cookies ordered by creation time.
+  typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
+
+  // Helper map we populate to find the duplicates.
+  typedef std::map<CookieSignature, CookieSet> EquivalenceMap;
+  EquivalenceMap equivalent_cookies;
+
+  // The number of duplicate cookies that have been found.
+  int num_duplicates = 0;
+
+  // Iterate through all of the cookies in our range, and insert them into
+  // the equivalence map.
+  for (CookieMap::iterator it = begin; it != end; ++it) {
+    DCHECK_EQ(key, it->first);
+    CanonicalCookie* cookie = it->second;
+
+    CookieSignature signature(cookie->Name(), cookie->Domain(),
+                              cookie->Path());
+    CookieSet& set = equivalent_cookies[signature];
+
+    // We found a duplicate!
+    if (!set.empty())
+      num_duplicates++;
+
+    // We save the iterator into |cookies_| rather than the actual cookie
+    // pointer, since we may need to delete it later.
+    bool insert_success = set.insert(it).second;
+    DCHECK(insert_success) <<
+        "Duplicate creation times found in duplicate cookie name scan.";
+  }
+
+  // If there were no duplicates, we are done!
+  if (num_duplicates == 0)
+    return 0;
+
+  // Make sure we find everything below that we did above.
+  int num_duplicates_found = 0;
+
+  // Otherwise, delete all the duplicate cookies, both from our in-memory store
+  // and from the backing store.
+  for (EquivalenceMap::iterator it = equivalent_cookies.begin();
+       it != equivalent_cookies.end();
+       ++it) {
+    const CookieSignature& signature = it->first;
+    CookieSet& dupes = it->second;
+
+    if (dupes.size() <= 1)
+      continue;  // This cookiename/path has no duplicates.
+    num_duplicates_found += dupes.size() - 1;
+
+    // Since |dups| is sorted by creation time (descending), the first cookie
+    // is the most recent one, so we will keep it. The rest are duplicates.
+    dupes.erase(dupes.begin());
+
+    LOG(ERROR) << base::StringPrintf(
+        "Found %d duplicate cookies for host='%s', "
+        "with {name='%s', domain='%s', path='%s'}",
+        static_cast<int>(dupes.size()),
+        key.c_str(),
+        signature.name.c_str(),
+        signature.domain.c_str(),
+        signature.path.c_str());
+
+    // Remove all the cookies identified by |dupes|. It is valid to delete our
+    // list of iterators one at a time, since |cookies_| is a multimap (they
+    // don't invalidate existing iterators following deletion).
+    for (CookieSet::iterator dupes_it = dupes.begin();
+         dupes_it != dupes.end();
+         ++dupes_it) {
+      InternalDeleteCookie(*dupes_it, true /*sync_to_store*/,
+                           DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
+    }
+  }
+  DCHECK_EQ(num_duplicates, num_duplicates_found);
+
+  return num_duplicates;
+}
+
+void CookieMonster::SetDefaultCookieableSchemes() {
+  // Note: file must be the last scheme.
+  static const char* kDefaultCookieableSchemes[] = { "http", "https", "file" };
+  int num_schemes = enable_file_scheme_ ? 3 : 2;
+  SetCookieableSchemes(kDefaultCookieableSchemes, num_schemes);
+}
+
+
+void CookieMonster::FindCookiesForHostAndDomain(
+    const GURL& url,
+    const CookieOptions& options,
+    bool update_access_time,
+    std::vector<CanonicalCookie*>* cookies) {
+  lock_.AssertAcquired();
+
+  const Time current_time(CurrentTime());
+
+  // Probe to save statistics relatively frequently.  We do it here rather
+  // than in the set path as many websites won't set cookies, and we
+  // want to collect statistics whenever the browser's being used.
+  RecordPeriodicStats(current_time);
+
+  if (expiry_and_key_scheme_ == EKS_DISCARD_RECENT_AND_PURGE_DOMAIN) {
+    // Can just dispatch to FindCookiesForKey
+    const std::string key(GetKey(url.host()));
+    FindCookiesForKey(key, url, options, current_time,
+                      update_access_time, cookies);
+  } else {
+    // Need to probe for all domains that might have relevant
+    // cookies for us.
+
+    // Query for the full host, For example: 'a.c.blah.com'.
+    std::string key(GetKey(url.host()));
+    FindCookiesForKey(key, url, options, current_time, update_access_time,
+                      cookies);
+
+    // See if we can search for domain cookies, i.e. if the host has a TLD + 1.
+    const std::string domain(GetEffectiveDomain(url.scheme(), key));
+    if (domain.empty())
+      return;
+    DCHECK_LE(domain.length(), key.length());
+    DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(),
+                             domain));
+
+    // Walk through the string and query at the dot points (GURL should have
+    // canonicalized the dots, so this should be safe).  Stop once we reach the
+    // domain + registry; we can't write cookies past this point, and with some
+    // registrars other domains can, in which case we don't want to read their
+    // cookies.
+    for (key = "." + key; key.length() > domain.length(); ) {
+      FindCookiesForKey(key, url, options, current_time, update_access_time,
+                        cookies);
+      const size_t next_dot = key.find('.', 1);  // Skip over leading dot.
+      key.erase(0, next_dot);
+    }
+  }
+}
+
+void CookieMonster::FindCookiesForKey(
+    const std::string& key,
+    const GURL& url,
+    const CookieOptions& options,
+    const Time& current,
+    bool update_access_time,
+    std::vector<CanonicalCookie*>* cookies) {
+  lock_.AssertAcquired();
+
+  const std::string scheme(url.scheme());
+  const std::string host(url.host());
+  bool secure = url.SchemeIsSecure();
+
+  for (CookieMapItPair its = cookies_.equal_range(key);
+       its.first != its.second; ) {
+    CookieMap::iterator curit = its.first;
+    CanonicalCookie* cc = curit->second;
+    ++its.first;
+
+    // If the cookie is expired, delete it.
+    if (cc->IsExpired(current)) {
+      InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
+      continue;
+    }
+
+    // Filter out HttpOnly cookies, per options.
+    if (options.exclude_httponly() && cc->IsHttpOnly())
+      continue;
+
+    // Filter out secure cookies unless we're https.
+    if (!secure && cc->IsSecure())
+      continue;
+
+    // Filter out cookies that don't apply to this domain.
+    if (expiry_and_key_scheme_ == EKS_KEEP_RECENT_AND_PURGE_ETLDP1
+        && !cc->IsDomainMatch(scheme, host))
+      continue;
+
+    if (!cc->IsOnPath(url.path()))
+      continue;
+
+    // Add this cookie to the set of matching cookies.  Update the access
+    // time if we've been requested to do so.
+    if (update_access_time) {
+      InternalUpdateCookieAccessTime(cc, current);
+    }
+    cookies->push_back(cc);
+  }
+}
+
+bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
+                                              const CanonicalCookie& ecc,
+                                              bool skip_httponly) {
+  lock_.AssertAcquired();
+
+  bool found_equivalent_cookie = false;
+  bool skipped_httponly = false;
+  for (CookieMapItPair its = cookies_.equal_range(key);
+       its.first != its.second; ) {
+    CookieMap::iterator curit = its.first;
+    CanonicalCookie* cc = curit->second;
+    ++its.first;
+
+    if (ecc.IsEquivalent(*cc)) {
+      // We should never have more than one equivalent cookie, since they should
+      // overwrite each other.
+      CHECK(!found_equivalent_cookie) <<
+          "Duplicate equivalent cookies found, cookie store is corrupted.";
+      if (skip_httponly && cc->IsHttpOnly()) {
+        skipped_httponly = true;
+      } else {
+        InternalDeleteCookie(curit, true, DELETE_COOKIE_OVERWRITE);
+      }
+      found_equivalent_cookie = true;
+    }
+  }
+  return skipped_httponly;
+}
+
+void CookieMonster::InternalInsertCookie(const std::string& key,
+                                         CanonicalCookie* cc,
+                                         bool sync_to_store) {
+  lock_.AssertAcquired();
+
+  if (cc->IsPersistent() && store_ && sync_to_store)
+    store_->AddCookie(*cc);
+  cookies_.insert(CookieMap::value_type(key, cc));
+  if (delegate_.get())
+    delegate_->OnCookieChanged(*cc, false);
+}
+
 bool CookieMonster::SetCookieWithCreationTimeAndOptions(
     const GURL& url,
     const std::string& cookie_line,
@@ -824,49 +1179,6 @@
   return SetCanonicalCookie(&cc, creation_time, options);
 }
 
-bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
-                                              const std::string& cookie_line,
-                                              const base::Time& creation_time) {
-  AutoLock autolock(lock_);
-
-  if (!HasCookieableScheme(url)) {
-    return false;
-  }
-
-  InitIfNecessary();
-  return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
-                                             CookieOptions());
-}
-
-bool CookieMonster::SetCookieWithDetails(
-    const GURL& url, const std::string& name, const std::string& value,
-    const std::string& domain, const std::string& path,
-    const base::Time& expiration_time, bool secure, bool http_only) {
-
-  AutoLock autolock(lock_);
-
-  if (!HasCookieableScheme(url))
-    return false;
-
-  InitIfNecessary();
-
-  Time creation_time = CurrentTime();
-  last_time_seen_ = creation_time;
-
-  scoped_ptr<CanonicalCookie> cc;
-  cc.reset(CanonicalCookie::Create(
-      url, name, value, domain, path,
-      creation_time, expiration_time,
-      secure, http_only));
-
-  if (!cc.get())
-    return false;
-
-  CookieOptions options;
-  options.set_include_httponly();
-  return SetCanonicalCookie(&cc, creation_time, options);
-}
-
 bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
                                        const Time& creation_time,
                                        const CookieOptions& options) {
@@ -898,18 +1210,6 @@
   return true;
 }
 
-void CookieMonster::InternalInsertCookie(const std::string& key,
-                                         CanonicalCookie* cc,
-                                         bool sync_to_store) {
-  lock_.AssertAcquired();
-
-  if (cc->IsPersistent() && store_ && sync_to_store)
-    store_->AddCookie(*cc);
-  cookies_.insert(CookieMap::value_type(key, cc));
-  if (delegate_.get())
-    delegate_->OnCookieChanged(*cc, false);
-}
-
 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
                                                    const Time& current) {
   lock_.AssertAcquired();
@@ -950,98 +1250,6 @@
   delete cc;
 }
 
-bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
-                                              const CanonicalCookie& ecc,
-                                              bool skip_httponly) {
-  lock_.AssertAcquired();
-
-  bool found_equivalent_cookie = false;
-  bool skipped_httponly = false;
-  for (CookieMapItPair its = cookies_.equal_range(key);
-       its.first != its.second; ) {
-    CookieMap::iterator curit = its.first;
-    CanonicalCookie* cc = curit->second;
-    ++its.first;
-
-    if (ecc.IsEquivalent(*cc)) {
-      // We should never have more than one equivalent cookie, since they should
-      // overwrite each other.
-      CHECK(!found_equivalent_cookie) <<
-          "Duplicate equivalent cookies found, cookie store is corrupted.";
-      if (skip_httponly && cc->IsHttpOnly()) {
-        skipped_httponly = true;
-      } else {
-        InternalDeleteCookie(curit, true, DELETE_COOKIE_OVERWRITE);
-      }
-      found_equivalent_cookie = true;
-    }
-  }
-  return skipped_httponly;
-}
-
-static bool LRUCookieSorter(const CookieMonster::CookieMap::iterator& it1,
-                            const CookieMonster::CookieMap::iterator& it2) {
-  // Cookies accessed less recently should be deleted first.
-  if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
-    return it1->second->LastAccessDate() < it2->second->LastAccessDate();
-
-  // In rare cases we might have two cookies with identical last access times.
-  // To preserve the stability of the sort, in these cases prefer to delete
-  // older cookies over newer ones.  CreationDate() is guaranteed to be unique.
-  return it1->second->CreationDate() < it2->second->CreationDate();
-}
-
-// Helper for GarbageCollection.  If |cookie_its->size() > num_max|, remove the
-// |num_max - num_purge| most recently accessed cookies from cookie_its.
-// (In other words, leave the entries that are candidates for
-// eviction in cookie_its.)  The cookies returned will be in order sorted by
-// access time, least recently accessed first.  The access time of the least
-// recently accessed entry not returned will be placed in
-// |*lra_removed| if that pointer is set.  FindLeastRecentlyAccessed
-// returns false if no manipulation is done (because the list size is less
-// than num_max), true otherwise.
-static bool FindLeastRecentlyAccessed(
-    size_t num_max,
-    size_t num_purge,
-    Time* lra_removed,
-    std::vector<CookieMonster::CookieMap::iterator>* cookie_its) {
-  DCHECK_LE(num_purge, num_max);
-  if (cookie_its->size() > num_max) {
-    VLOG(kVlogGarbageCollection)
-        << "FindLeastRecentlyAccessed() Deep Garbage Collect.";
-    num_purge += cookie_its->size() - num_max;
-    DCHECK_GT(cookie_its->size(), num_purge);
-
-    // Add 1 so that we can get the last time left in the store.
-    std::partial_sort(cookie_its->begin(), cookie_its->begin() + num_purge + 1,
-                      cookie_its->end(), LRUCookieSorter);
-    *lra_removed =
-        (*(cookie_its->begin() + num_purge))->second->LastAccessDate();
-    cookie_its->erase(cookie_its->begin() + num_purge, cookie_its->end());
-    return true;
-  }
-  return false;
-}
-
-int CookieMonster::GarbageCollectDeleteList(
-    const Time& current,
-    const Time& keep_accessed_after,
-    DeletionCause cause,
-    std::vector<CookieMap::iterator>& cookie_its) {
-  int num_deleted = 0;
-  for (std::vector<CookieMap::iterator>::iterator it = cookie_its.begin();
-       it != cookie_its.end(); it++) {
-    if (keep_accessed_after.is_null() ||
-        (*it)->second->LastAccessDate() < keep_accessed_after) {
-      histogram_evicted_last_access_minutes_->Add(
-          (current - (*it)->second->LastAccessDate()).InMinutes());
-      InternalDeleteCookie((*it), true, cause);
-      num_deleted++;
-    }
-  }
-  return num_deleted;
-}
-
 // Domain expiry behavior is unchanged by key/expiry scheme (the
 // meaning of the key is different, but that's not visible to this
 // routine).  Global garbage collection is dependent on key/expiry
@@ -1148,352 +1356,80 @@
   return num_deleted;
 }
 
-int CookieMonster::DeleteAll(bool sync_to_store) {
-  AutoLock autolock(lock_);
-  if (sync_to_store)
-    InitIfNecessary();
-
+int CookieMonster::GarbageCollectDeleteList(
+    const Time& current,
+    const Time& keep_accessed_after,
+    DeletionCause cause,
+    std::vector<CookieMap::iterator>& cookie_its) {
   int num_deleted = 0;
-  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
-    CookieMap::iterator curit = it;
-    ++it;
-    InternalDeleteCookie(curit, sync_to_store,
-                         sync_to_store ? DELETE_COOKIE_EXPLICIT :
-                             DELETE_COOKIE_DONT_RECORD /* Destruction. */);
-    ++num_deleted;
-  }
-
-  return num_deleted;
-}
-
-int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
-                                           const Time& delete_end,
-                                           bool sync_to_store) {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
-
-  int num_deleted = 0;
-  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
-    CookieMap::iterator curit = it;
-    CanonicalCookie* cc = curit->second;
-    ++it;
-
-    if (cc->CreationDate() >= delete_begin &&
-        (delete_end.is_null() || cc->CreationDate() < delete_end)) {
-      InternalDeleteCookie(curit, sync_to_store, DELETE_COOKIE_EXPLICIT);
-      ++num_deleted;
-    }
-  }
-
-  return num_deleted;
-}
-
-int CookieMonster::DeleteAllCreatedAfter(const Time& delete_begin,
-                                         bool sync_to_store) {
-  return DeleteAllCreatedBetween(delete_begin, Time(), sync_to_store);
-}
-
-int CookieMonster::DeleteAllForHost(const GURL& url) {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
-
-  if (!HasCookieableScheme(url))
-    return 0;
-
-  const std::string scheme(url.scheme());
-  const std::string host(url.host());
-
-  // We store host cookies in the store by their canonical host name;
-  // domain cookies are stored with a leading ".".  So this is a pretty
-  // simple lookup and per-cookie delete.
-  int num_deleted = 0;
-  for (CookieMapItPair its = cookies_.equal_range(GetKey(host));
-       its.first != its.second;) {
-    CookieMap::iterator curit = its.first;
-    ++its.first;
-
-    const CanonicalCookie* const cc = curit->second;
-
-    // Delete only on a match as a host cookie.
-    if (cc->IsHostCookie() && cc->IsDomainMatch(scheme, host)) {
+  for (std::vector<CookieMap::iterator>::iterator it = cookie_its.begin();
+       it != cookie_its.end(); it++) {
+    if (keep_accessed_after.is_null() ||
+        (*it)->second->LastAccessDate() < keep_accessed_after) {
+      histogram_evicted_last_access_minutes_->Add(
+          (current - (*it)->second->LastAccessDate()).InMinutes());
+      InternalDeleteCookie((*it), true, cause);
       num_deleted++;
-
-      InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
     }
   }
   return num_deleted;
 }
 
-bool CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
+// A wrapper around RegistryControlledDomainService::GetDomainAndRegistry
+// to make clear we're creating a key for our local map.  Here and
+// in FindCookiesForHostAndDomain() are the only two places where
+// we need to conditionalize based on key type.
+//
+// Note that this key algorithm explicitly ignores the scheme.  This is
+// because when we're entering cookies into the map from the backing store,
+// we in general won't have the scheme at that point.
+// In practical terms, this means that file cookies will be stored
+// in the map either by an empty string or by UNC name (and will be
+// limited by kMaxCookiesPerHost), and extension cookies will be stored
+// based on the single extension id, as the extension id won't have the
+// form of a DNS host and hence GetKey() will return it unchanged.
+//
+// Arguably the right thing to do here is to make the key
+// algorithm dependent on the scheme, and make sure that the scheme is
+// available everywhere the key must be obtained (specfically at backing
+// store load time).  This would require either changing the backing store
+// database schema to include the scheme (far more trouble than it's worth), or
+// separating out file cookies into their own CookieMonster instance and
+// thus restricting each scheme to a single cookie monster (which might
+// be worth it, but is still too much trouble to solve what is currently a
+// non-problem).
+std::string CookieMonster::GetKey(const std::string& domain) const {
+  if (expiry_and_key_scheme_ == EKS_DISCARD_RECENT_AND_PURGE_DOMAIN)
+    return domain;
 
-  for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
-       its.first != its.second; ++its.first) {
-    // The creation date acts as our unique index...
-    if (its.first->second->CreationDate() == cookie.CreationDate()) {
-      InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
+  std::string effective_domain(
+      RegistryControlledDomainService::GetDomainAndRegistry(domain));
+  if (effective_domain.empty())
+    effective_domain = domain;
+
+  if (!effective_domain.empty() && effective_domain[0] == '.')
+    return effective_domain.substr(1);
+  return effective_domain;
+}
+
+bool CookieMonster::HasCookieableScheme(const GURL& url) {
+  lock_.AssertAcquired();
+
+  // Make sure the request is on a cookie-able url scheme.
+  for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
+    // We matched a scheme.
+    if (url.SchemeIs(cookieable_schemes_[i].c_str())) {
+      // We've matched a supported scheme.
       return true;
     }
   }
+
+  // The scheme didn't match any in our whitelist.
+  VLOG(kVlogPerCookieMonster) << "WARNING: Unsupported cookie scheme: "
+                              << url.scheme();
   return false;
 }
 
-// Mozilla sorts on the path length (longest first), and then it
-// sorts by creation time (oldest first).
-// The RFC says the sort order for the domain attribute is undefined.
-static bool CookieSorter(CookieMonster::CanonicalCookie* cc1,
-                         CookieMonster::CanonicalCookie* cc2) {
-  if (cc1->Path().length() == cc2->Path().length())
-    return cc1->CreationDate() < cc2->CreationDate();
-  return cc1->Path().length() > cc2->Path().length();
-}
-
-bool CookieMonster::SetCookieWithOptions(const GURL& url,
-                                         const std::string& cookie_line,
-                                         const CookieOptions& options) {
-  AutoLock autolock(lock_);
-
-  if (!HasCookieableScheme(url)) {
-    return false;
-  }
-
-  InitIfNecessary();
-
-  return SetCookieWithCreationTimeAndOptions(url, cookie_line, Time(), options);
-}
-
-std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
-                                                 const CookieOptions& options) {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
-
-  if (!HasCookieableScheme(url)) {
-    return std::string();
-  }
-
-  TimeTicks start_time(TimeTicks::Now());
-
-  // Get the cookies for this host and its domain(s).
-  std::vector<CanonicalCookie*> cookies;
-  FindCookiesForHostAndDomain(url, options, true, &cookies);
-  std::sort(cookies.begin(), cookies.end(), CookieSorter);
-
-  std::string cookie_line;
-  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
-       it != cookies.end(); ++it) {
-    if (it != cookies.begin())
-      cookie_line += "; ";
-    // In Mozilla if you set a cookie like AAAA, it will have an empty token
-    // and a value of AAAA.  When it sends the cookie back, it will send AAAA,
-    // so we need to avoid sending =AAAA for a blank token value.
-    if (!(*it)->Name().empty())
-      cookie_line += (*it)->Name() + "=";
-    cookie_line += (*it)->Value();
-  }
-
-  histogram_time_get_->AddTime(TimeTicks::Now() - start_time);
-
-  VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
-
-  return cookie_line;
-}
-
-void CookieMonster::DeleteCookie(const GURL& url,
-                                 const std::string& cookie_name) {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
-
-  if (!HasCookieableScheme(url))
-    return;
-
-  CookieOptions options;
-  options.set_include_httponly();
-  // Get the cookies for this host and its domain(s).
-  std::vector<CanonicalCookie*> cookies;
-  FindCookiesForHostAndDomain(url, options, true, &cookies);
-  std::set<CanonicalCookie*> matching_cookies;
-
-  for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
-       it != cookies.end(); ++it) {
-    if ((*it)->Name() != cookie_name)
-      continue;
-    if (url.path().find((*it)->Path()))
-      continue;
-    matching_cookies.insert(*it);
-  }
-
-  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
-    CookieMap::iterator curit = it;
-    ++it;
-    if (matching_cookies.find(curit->second) != matching_cookies.end()) {
-      InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
-    }
-  }
-}
-
-CookieMonster* CookieMonster::GetCookieMonster() {
-  return this;
-}
-
-CookieList CookieMonster::GetAllCookies() {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
-
-  // This function is being called to scrape the cookie list for management UI
-  // or similar.  We shouldn't show expired cookies in this list since it will
-  // just be confusing to users, and this function is called rarely enough (and
-  // is already slow enough) that it's OK to take the time to garbage collect
-  // the expired cookies now.
-  //
-  // Note that this does not prune cookies to be below our limits (if we've
-  // exceeded them) the way that calling GarbageCollect() would.
-  GarbageCollectExpired(Time::Now(),
-                        CookieMapItPair(cookies_.begin(), cookies_.end()),
-                        NULL);
-
-  // Copy the CanonicalCookie pointers from the map so that we can use the same
-  // sorter as elsewhere, then copy the result out.
-  std::vector<CanonicalCookie*> cookie_ptrs;
-  cookie_ptrs.reserve(cookies_.size());
-  for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end(); ++it)
-    cookie_ptrs.push_back(it->second);
-  std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
-
-  CookieList cookie_list;
-  cookie_list.reserve(cookie_ptrs.size());
-  for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
-       it != cookie_ptrs.end(); ++it)
-    cookie_list.push_back(**it);
-
-  return cookie_list;
-}
-
-CookieList CookieMonster::GetAllCookiesForURLWithOptions(
-    const GURL& url,
-    const CookieOptions& options) {
-  AutoLock autolock(lock_);
-  InitIfNecessary();
-
-  std::vector<CanonicalCookie*> cookie_ptrs;
-  FindCookiesForHostAndDomain(url, options, false, &cookie_ptrs);
-  std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
-
-  CookieList cookies;
-  for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
-       it != cookie_ptrs.end(); it++)
-    cookies.push_back(**it);
-
-  return cookies;
-}
-
-CookieList CookieMonster::GetAllCookiesForURL(const GURL& url) {
-  CookieOptions options;
-  options.set_include_httponly();
-
-  return GetAllCookiesForURLWithOptions(url, options);
-}
-
-void CookieMonster::FindCookiesForHostAndDomain(
-    const GURL& url,
-    const CookieOptions& options,
-    bool update_access_time,
-    std::vector<CanonicalCookie*>* cookies) {
-  lock_.AssertAcquired();
-
-  const Time current_time(CurrentTime());
-
-  // Probe to save statistics relatively frequently.  We do it here rather
-  // than in the set path as many websites won't set cookies, and we
-  // want to collect statistics whenever the browser's being used.
-  RecordPeriodicStats(current_time);
-
-  if (expiry_and_key_scheme_ == EKS_DISCARD_RECENT_AND_PURGE_DOMAIN) {
-    // Can just dispatch to FindCookiesForKey
-    const std::string key(GetKey(url.host()));
-    FindCookiesForKey(key, url, options, current_time,
-                      update_access_time, cookies);
-  } else {
-    // Need to probe for all domains that might have relevant
-    // cookies for us.
-
-    // Query for the full host, For example: 'a.c.blah.com'.
-    std::string key(GetKey(url.host()));
-    FindCookiesForKey(key, url, options, current_time, update_access_time,
-                      cookies);
-
-    // See if we can search for domain cookies, i.e. if the host has a TLD + 1.
-    const std::string domain(GetEffectiveDomain(url.scheme(), key));
-    if (domain.empty())
-      return;
-    DCHECK_LE(domain.length(), key.length());
-    DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(),
-                             domain));
-
-    // Walk through the string and query at the dot points (GURL should have
-    // canonicalized the dots, so this should be safe).  Stop once we reach the
-    // domain + registry; we can't write cookies past this point, and with some
-    // registrars other domains can, in which case we don't want to read their
-    // cookies.
-    for (key = "." + key; key.length() > domain.length(); ) {
-      FindCookiesForKey(key, url, options, current_time, update_access_time,
-                        cookies);
-      const size_t next_dot = key.find('.', 1);  // Skip over leading dot.
-      key.erase(0, next_dot);
-    }
-  }
-}
-
-void CookieMonster::FindCookiesForKey(
-    const std::string& key,
-    const GURL& url,
-    const CookieOptions& options,
-    const Time& current,
-    bool update_access_time,
-    std::vector<CanonicalCookie*>* cookies) {
-  lock_.AssertAcquired();
-
-  const std::string scheme(url.scheme());
-  const std::string host(url.host());
-  bool secure = url.SchemeIsSecure();
-
-  for (CookieMapItPair its = cookies_.equal_range(key);
-       its.first != its.second; ) {
-    CookieMap::iterator curit = its.first;
-    CanonicalCookie* cc = curit->second;
-    ++its.first;
-
-    // If the cookie is expired, delete it.
-    if (cc->IsExpired(current)) {
-      InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
-      continue;
-    }
-
-    // Filter out HttpOnly cookies, per options.
-    if (options.exclude_httponly() && cc->IsHttpOnly())
-      continue;
-
-    // Filter out secure cookies unless we're https.
-    if (!secure && cc->IsSecure())
-      continue;
-
-    // Filter out cookies that don't apply to this domain.
-    if (expiry_and_key_scheme_ == EKS_KEEP_RECENT_AND_PURGE_ETLDP1
-        && !cc->IsDomainMatch(scheme, host))
-      continue;
-
-    if (!cc->IsOnPath(url.path()))
-      continue;
-
-    // Add this cookie to the set of matching cookies.  Update the access
-    // time if we've been requested to do so.
-    if (update_access_time) {
-      InternalUpdateCookieAccessTime(cc, current);
-    }
-    cookies->push_back(cc);
-  }
-}
-
 // Test to see if stats should be recorded, and record them if so.
 // The goal here is to get sampling for the average browser-hour of
 // activity.  We won't take samples when the web isn't being surfed,
@@ -1549,6 +1485,85 @@
   last_statistic_record_time_ = current_time;
 }
 
+// Initialize all histogram counter variables used in this class.
+//
+// Normal histogram usage involves using the macros defined in
+// histogram.h, which automatically takes care of declaring these
+// variables (as statics), initializing them, and accumulating into
+// them, all from a single entry point.  Unfortunately, that solution
+// doesn't work for the CookieMonster, as it's vulnerable to races between
+// separate threads executing the same functions and hence initializing the
+// same static variables.  There isn't a race danger in the histogram
+// accumulation calls; they are written to be resilient to simultaneous
+// calls from multiple threads.
+//
+// The solution taken here is to have per-CookieMonster instance
+// variables that are constructed during CookieMonster construction.
+// Note that these variables refer to the same underlying histogram,
+// so we still race (but safely) with other CookieMonster instances
+// for accumulation.
+//
+// To do this we've expanded out the individual histogram macros calls,
+// with declarations of the variables in the class decl, initialization here
+// (done from the class constructor) and direct calls to the accumulation
+// methods where needed.  The specific histogram macro calls on which the
+// initialization is based are included in comments below.
+void CookieMonster::InitializeHistograms() {
+  // From UMA_HISTOGRAM_CUSTOM_COUNTS
+  histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
+      "Cookie.ExpirationDurationMinutes",
+      1, kMinutesInTenYears, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_between_access_interval_minutes_ = base::Histogram::FactoryGet(
+      "Cookie.BetweenAccessIntervalMinutes",
+      1, kMinutesInTenYears, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_evicted_last_access_minutes_ = base::Histogram::FactoryGet(
+      "Cookie.EvictedLastAccessMinutes",
+      1, kMinutesInTenYears, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_count_ = base::Histogram::FactoryGet(
+      "Cookie.Count", 1, 4000, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_domain_count_ = base::Histogram::FactoryGet(
+      "Cookie.DomainCount", 1, 4000, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_etldp1_count_ = base::Histogram::FactoryGet(
+      "Cookie.Etldp1Count", 1, 4000, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_domain_per_etldp1_count_ = base::Histogram::FactoryGet(
+      "Cookie.DomainPerEtldp1Count", 1, 4000, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+
+  // From UMA_HISTOGRAM_COUNTS_10000 & UMA_HISTOGRAM_CUSTOM_COUNTS
+  histogram_number_duplicate_db_cookies_ = base::Histogram::FactoryGet(
+      "Net.NumDuplicateCookiesInDb", 1, 10000, 50,
+      base::Histogram::kUmaTargetedHistogramFlag);
+
+  // From UMA_HISTOGRAM_ENUMERATION
+  histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet(
+      "Cookie.DeletionCause", 1,
+      DELETE_COOKIE_LAST_ENTRY - 1, DELETE_COOKIE_LAST_ENTRY,
+      base::Histogram::kUmaTargetedHistogramFlag);
+
+  // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
+  histogram_time_get_ = base::Histogram::FactoryTimeGet("Cookie.TimeGet",
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+      50, base::Histogram::kUmaTargetedHistogramFlag);
+  histogram_time_load_ = base::Histogram::FactoryTimeGet("Cookie.TimeLoad",
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+      50, base::Histogram::kUmaTargetedHistogramFlag);
+}
+
+
+// The system resolution is not high enough, so we can have multiple
+// set cookies that result in the same system time.  When this happens, we
+// increment by one Time unit.  Let's hope computers don't get too fast.
+Time CookieMonster::CurrentTime() {
+  return std::max(Time::Now(),
+      Time::FromInternalValue(last_time_seen_.ToInternalValue() + 1));
+}
+
 CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line)
     : is_valid_(false),
       path_index_(0),
@@ -1608,6 +1623,21 @@
 const char CookieMonster::ParsedCookie::kValueSeparator[] = ";";
 const char CookieMonster::ParsedCookie::kTokenSeparator[] = ";=";
 
+// Create a cookie-line for the cookie.  For debugging only!
+// If we want to use this for something more than debugging, we
+// should rewrite it better...
+std::string CookieMonster::ParsedCookie::DebugString() const {
+  std::string out;
+  for (PairList::const_iterator it = pairs_.begin();
+       it != pairs_.end(); ++it) {
+    out.append(it->first);
+    out.append("=");
+    out.append(it->second);
+    out.append("; ");
+  }
+  return out;
+}
+
 std::string::const_iterator CookieMonster::ParsedCookie::FindFirstTerminator(
     const std::string& s) {
   std::string::const_iterator end = s.end();
@@ -1835,22 +1865,10 @@
   }
 }
 
-// Create a cookie-line for the cookie.  For debugging only!
-// If we want to use this for something more than debugging, we
-// should rewrite it better...
-std::string CookieMonster::ParsedCookie::DebugString() const {
-  std::string out;
-  for (PairList::const_iterator it = pairs_.begin();
-       it != pairs_.end(); ++it) {
-    out.append(it->first);
-    out.append("=");
-    out.append(it->second);
-    out.append("; ");
-  }
-  return out;
-}
-
-CookieMonster::CanonicalCookie::CanonicalCookie() {
+CookieMonster::CanonicalCookie::CanonicalCookie()
+    : has_expires_(false),
+      secure_(false),
+      httponly_(false) {
 }
 
 CookieMonster::CanonicalCookie::CanonicalCookie(const std::string& name,
@@ -1902,20 +1920,6 @@
   domain_ = cookie_domain;
 }
 
-CookieMonster::CookieMonster(PersistentCookieStore* store,
-                             Delegate* delegate,
-                             int last_access_threshold_milliseconds)
-    : initialized_(false),
-      expiry_and_key_scheme_(expiry_and_key_default_),
-      store_(store),
-      last_access_threshold_(base::TimeDelta::FromMilliseconds(
-          last_access_threshold_milliseconds)),
-      delegate_(delegate),
-      last_statistic_record_time_(base::Time::Now()) {
-  InitializeHistograms();
-  SetDefaultCookieableSchemes();
-}
-
 CookieMonster::CanonicalCookie::~CanonicalCookie() {
 }
 
diff --git a/net/base/cookie_monster.h b/net/base/cookie_monster.h
index 3b4bfd2..58a9c4f 100644
--- a/net/base/cookie_monster.h
+++ b/net/base/cookie_monster.h
@@ -15,9 +15,9 @@
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/lock.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "base/time.h"
 #include "net/base/cookie_store.h"
@@ -130,25 +130,6 @@
   // i.e. it doesn't begin with a leading '.' character.
   static bool DomainIsHostOnly(const std::string& domain_string);
 
-  // CookieStore implementation.
-
-  // Sets the cookies specified by |cookie_list| returned from |url|
-  // with options |options| in effect.
-  virtual bool SetCookieWithOptions(const GURL& url,
-                                    const std::string& cookie_line,
-                                    const CookieOptions& options);
-
-  // Gets all cookies that apply to |url| given |options|.
-  // The returned cookies are ordered by longest path, then earliest
-  // creation date.
-  virtual std::string GetCookiesWithOptions(const GURL& url,
-                                            const CookieOptions& options);
-
-  // Deletes all cookies with that might apply to |url| that has |cookie_name|.
-  virtual void DeleteCookie(const GURL& url, const std::string& cookie_name);
-
-  virtual CookieMonster* GetCookieMonster();
-
   // Sets a cookie given explicit user-provided cookie attributes. The cookie
   // name, value, domain, etc. are each provided as separate strings. This
   // function expects each attribute to be well-formed. It will check for
@@ -222,7 +203,6 @@
   // to enable support, but it should only be used for testing. Bug 1157243.
   // Must be called before creating a CookieMonster instance.
   static void EnableFileScheme();
-  static bool enable_file_scheme_;
 
   // Flush the backing store (if any) to disk and post the given task when done.
   // WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE.
@@ -231,9 +211,26 @@
   // to the thread you actually want to be notified on.
   void FlushStore(Task* completion_task);
 
- private:
-  ~CookieMonster();
+  // CookieStore implementation.
 
+  // Sets the cookies specified by |cookie_list| returned from |url|
+  // with options |options| in effect.
+  virtual bool SetCookieWithOptions(const GURL& url,
+                                    const std::string& cookie_line,
+                                    const CookieOptions& options);
+
+  // Gets all cookies that apply to |url| given |options|.
+  // The returned cookies are ordered by longest path, then earliest
+  // creation date.
+  virtual std::string GetCookiesWithOptions(const GURL& url,
+                                            const CookieOptions& options);
+
+  // Deletes all cookies with that might apply to |url| that has |cookie_name|.
+  virtual void DeleteCookie(const GURL& url, const std::string& cookie_name);
+
+  virtual CookieMonster* GetCookieMonster();
+
+ private:
   // Testing support.
   // For SetCookieWithCreationTime.
   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest,
@@ -253,6 +250,28 @@
   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, GetKey);
   FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestGetKey);
 
+  enum DeletionCause {
+    DELETE_COOKIE_EXPLICIT,
+    DELETE_COOKIE_OVERWRITE,
+    DELETE_COOKIE_EXPIRED,
+    DELETE_COOKIE_EVICTED,
+    DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE,
+    DELETE_COOKIE_DONT_RECORD,  // e.g. For final cleanup after flush to store.
+    DELETE_COOKIE_EVICTED_DOMAIN,
+    DELETE_COOKIE_EVICTED_GLOBAL,
+
+    // Cookies evicted during domain level garbage collection that
+    // were accessed longer ago than kSafeFromGlobalPurgeDays
+    DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE,
+
+    // Cookies evicted during domain level garbage collection that
+    // were accessed more rencelyt than kSafeFromGlobalPurgeDays
+    // (and thus would have been preserved by global garbage collection).
+    DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE,
+
+    DELETE_COOKIE_LAST_ENTRY
+  };
+
   // Cookie garbage collection thresholds.  Based off of the Mozilla defaults.
   // When the number of cookies gets to k{Domain,}MaxCookies
   // purge down to k{Domain,}MaxCookies - k{Domain,}PurgeCookies.
@@ -285,6 +304,11 @@
   static const ExpiryAndKeyScheme expiry_and_key_default_ =
       EKS_KEEP_RECENT_AND_PURGE_ETLDP1;
 
+  // Record statistics every kRecordStatisticsIntervalSeconds of uptime.
+  static const int kRecordStatisticsIntervalSeconds = 10 * 60;
+
+  ~CookieMonster();
+
   bool SetCookieWithCreationTime(const GURL& url,
                                  const std::string& cookie_line,
                                  const base::Time& creation_time);
@@ -363,28 +387,6 @@
   void InternalUpdateCookieAccessTime(CanonicalCookie* cc,
                                       const base::Time& current_time);
 
-  enum DeletionCause {
-    DELETE_COOKIE_EXPLICIT,
-    DELETE_COOKIE_OVERWRITE,
-    DELETE_COOKIE_EXPIRED,
-    DELETE_COOKIE_EVICTED,
-    DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE,
-    DELETE_COOKIE_DONT_RECORD,  // e.g. For final cleanup after flush to store.
-    DELETE_COOKIE_EVICTED_DOMAIN,
-    DELETE_COOKIE_EVICTED_GLOBAL,
-
-    // Cookies evicted during domain level garbage collection that
-    // were accessed longer ago than kSafeFromGlobalPurgeDays
-    DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE,
-
-    // Cookies evicted during domain level garbage collection that
-    // were accessed more rencelyt than kSafeFromGlobalPurgeDays
-    // (and thus would have been preserved by global garbage collection).
-    DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE,
-
-    DELETE_COOKIE_LAST_ENTRY
-  };
-
   // |deletion_cause| argument is for collecting statistics.
   void InternalDeleteCookie(CookieMap::iterator it, bool sync_to_store,
                             DeletionCause deletion_cause);
@@ -422,13 +424,19 @@
   bool HasCookieableScheme(const GURL& url);
 
   // Statistics support
-  // Record statistics every kRecordStatisticsIntervalSeconds of uptime.
-  static const int kRecordStatisticsIntervalSeconds = 10 * 60;
 
   // This function should be called repeatedly, and will record
   // statistics if a sufficient time period has passed.
   void RecordPeriodicStats(const base::Time& current_time);
 
+  // Initialize the above variables; should only be called from
+  // the constructor.
+  void InitializeHistograms();
+
+  // The resolution of our time isn't enough, so we do something
+  // ugly and increment when we've seen the same time twice.
+  base::Time CurrentTime();
+
   // Histogram variables; see CookieMonster::InitializeHistograms() in
   // cookie_monster.cc for details.
   scoped_refptr<base::Histogram> histogram_expiration_duration_minutes_;
@@ -443,10 +451,6 @@
   scoped_refptr<base::Histogram> histogram_time_get_;
   scoped_refptr<base::Histogram> histogram_time_load_;
 
-  // Initialize the above variables; should only be called from
-  // the constructor.
-  void InitializeHistograms();
-
   CookieMap cookies_;
 
   // Indicates whether the cookie store has been initialized. This happens
@@ -459,9 +463,6 @@
 
   scoped_refptr<PersistentCookieStore> store_;
 
-  // The resolution of our time isn't enough, so we do something
-  // ugly and increment when we've seen the same time twice.
-  base::Time CurrentTime();
   base::Time last_time_seen_;
 
   // Minimum delay after updating a cookie's LastAccessDate before we will
@@ -484,10 +485,12 @@
   scoped_refptr<Delegate> delegate_;
 
   // Lock for thread-safety
-  Lock lock_;
+  base::Lock lock_;
 
   base::Time last_statistic_record_time_;
 
+  static bool enable_file_scheme_;
+
   DISALLOW_COPY_AND_ASSIGN(CookieMonster);
 };
 
diff --git a/net/base/cookie_monster_perftest.cc b/net/base/cookie_monster_perftest.cc
index 8c64d9a..68ac4cc 100644
--- a/net/base/cookie_monster_perftest.cc
+++ b/net/base/cookie_monster_perftest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "net/base/cookie_monster.h"
 
 #include "base/perftimer.h"
diff --git a/net/base/cookie_monster_store_test.h b/net/base/cookie_monster_store_test.h
index 84ead74..951c055 100644
--- a/net/base/cookie_monster_store_test.h
+++ b/net/base/cookie_monster_store_test.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,12 +7,13 @@
 // that need to test out CookieMonster interactions with the backing store.
 // It should only be included by test code.
 
-#include "base/message_loop.h"
-#include "base/time.h"
 #include "net/base/cookie_monster.h"
-#include "testing/gtest/include/gtest/gtest.h"
 
-namespace {
+namespace base {
+class Time;
+}
+
+namespace net {
 
 // Describes a call to one of the 3 functions of PersistentCookieStore.
 struct CookieStoreCommand {
@@ -39,53 +40,33 @@
  public:
   typedef std::vector<CookieStoreCommand> CommandList;
 
-  MockPersistentCookieStore() : load_return_value_(true) {
-  }
-
-  virtual bool Load(
-      std::vector<net::CookieMonster::CanonicalCookie*>* out_cookies) {
-    bool ok = load_return_value_;
-    if (ok)
-      *out_cookies = load_result_;
-    return ok;
-  }
-
-  virtual void AddCookie(const net::CookieMonster::CanonicalCookie& cookie) {
-    commands_.push_back(
-        CookieStoreCommand(CookieStoreCommand::ADD, cookie));
-  }
-
-  virtual void UpdateCookieAccessTime(
-      const net::CookieMonster::CanonicalCookie& cookie) {
-    commands_.push_back(CookieStoreCommand(
-        CookieStoreCommand::UPDATE_ACCESS_TIME, cookie));
-  }
-
-  virtual void DeleteCookie(
-      const net::CookieMonster::CanonicalCookie& cookie) {
-    commands_.push_back(
-        CookieStoreCommand(CookieStoreCommand::REMOVE, cookie));
-  }
-
-  virtual void Flush(Task* completion_task) {
-    if (completion_task)
-      MessageLoop::current()->PostTask(FROM_HERE, completion_task);
-  }
-
-  // No files are created so nothing to clear either
-  virtual void SetClearLocalStateOnExit(bool clear_local_state) {}
+  MockPersistentCookieStore();
+  virtual ~MockPersistentCookieStore();
 
   void SetLoadExpectation(
       bool return_value,
-      const std::vector<net::CookieMonster::CanonicalCookie*>& result) {
-    load_return_value_ = return_value;
-    load_result_ = result;
-  }
+      const std::vector<net::CookieMonster::CanonicalCookie*>& result);
 
   const CommandList& commands() const {
     return commands_;
   }
 
+  virtual bool Load(
+      std::vector<net::CookieMonster::CanonicalCookie*>* out_cookies);
+
+  virtual void AddCookie(const net::CookieMonster::CanonicalCookie& cookie);
+
+  virtual void UpdateCookieAccessTime(
+      const net::CookieMonster::CanonicalCookie& cookie);
+
+  virtual void DeleteCookie(
+      const net::CookieMonster::CanonicalCookie& cookie);
+
+  virtual void Flush(Task* completion_task);
+
+  // No files are created so nothing to clear either
+  virtual void SetClearLocalStateOnExit(bool clear_local_state);
+
  private:
   CommandList commands_;
 
@@ -102,21 +83,18 @@
   typedef std::pair<net::CookieMonster::CanonicalCookie, bool>
       CookieNotification;
 
-  MockCookieMonsterDelegate() {}
-
-  virtual void OnCookieChanged(
-      const net::CookieMonster::CanonicalCookie& cookie,
-      bool removed) {
-    CookieNotification notification(cookie, removed);
-    changes_.push_back(notification);
-  }
+  MockCookieMonsterDelegate();
 
   const std::vector<CookieNotification>& changes() const { return changes_; }
 
   void reset() { changes_.clear(); }
 
+  virtual void OnCookieChanged(
+      const net::CookieMonster::CanonicalCookie& cookie,
+      bool removed);
+
  private:
-  virtual ~MockCookieMonsterDelegate() {}
+  virtual ~MockCookieMonsterDelegate();
 
   std::vector<CookieNotification> changes_;
 
@@ -124,84 +102,40 @@
 };
 
 // Helper to build a list of CanonicalCookie*s.
-static void AddCookieToList(
+void AddCookieToList(
     const std::string& key,
     const std::string& cookie_line,
     const base::Time& creation_time,
-    std::vector<net::CookieMonster::CanonicalCookie*>* out_list) {
-
-  // Parse the cookie line.
-  net::CookieMonster::ParsedCookie pc(cookie_line);
-  EXPECT_TRUE(pc.IsValid());
-
-  // This helper is simplistic in interpreting a parsed cookie, in order to
-  // avoid duplicated CookieMonster's CanonPath() and CanonExpiration()
-  // functions. Would be nice to export them, and re-use here.
-  EXPECT_FALSE(pc.HasMaxAge());
-  EXPECT_TRUE(pc.HasPath());
-  base::Time cookie_expires = pc.HasExpires() ?
-      net::CookieMonster::ParseCookieTime(pc.Expires()) : base::Time();
-  std::string cookie_path = pc.Path();
-
-  scoped_ptr<net::CookieMonster::CanonicalCookie> cookie(
-      new net::CookieMonster::CanonicalCookie(
-          pc.Name(), pc.Value(), key, cookie_path,
-          pc.IsSecure(), pc.IsHttpOnly(),
-          creation_time, creation_time,
-          !cookie_expires.is_null(),
-          cookie_expires));
-
-  out_list->push_back(cookie.release());
-}
+    std::vector<net::CookieMonster::CanonicalCookie*>* out_list);
 
 // Just act like a backing database.  Keep cookie information from
 // Add/Update/Delete and regurgitate it when Load is called.
 class MockSimplePersistentCookieStore
     : public net::CookieMonster::PersistentCookieStore {
+ public:
+  MockSimplePersistentCookieStore();
+  virtual ~MockSimplePersistentCookieStore();
+
+  virtual bool Load(
+      std::vector<net::CookieMonster::CanonicalCookie*>* out_cookies);
+
+  virtual void AddCookie(
+      const net::CookieMonster::CanonicalCookie& cookie);
+
+  virtual void UpdateCookieAccessTime(
+      const net::CookieMonster::CanonicalCookie& cookie);
+
+  virtual void DeleteCookie(
+      const net::CookieMonster::CanonicalCookie& cookie);
+
+  virtual void Flush(Task* completion_task);
+
+  virtual void SetClearLocalStateOnExit(bool clear_local_state);
+
  private:
   typedef std::map<int64, net::CookieMonster::CanonicalCookie>
       CanonicalCookieMap;
 
- public:
-  virtual bool Load(
-      std::vector<net::CookieMonster::CanonicalCookie*>* out_cookies) {
-    for (CanonicalCookieMap::const_iterator it = cookies_.begin();
-         it != cookies_.end(); it++)
-      out_cookies->push_back(
-          new net::CookieMonster::CanonicalCookie(it->second));
-    return true;
-  }
-
-  virtual void AddCookie(
-      const net::CookieMonster::CanonicalCookie& cookie) {
-    int64 creation_time = cookie.CreationDate().ToInternalValue();
-    EXPECT_TRUE(cookies_.find(creation_time) == cookies_.end());
-    cookies_[creation_time] = cookie;
-  }
-
-  virtual void UpdateCookieAccessTime(
-      const net::CookieMonster::CanonicalCookie& cookie) {
-    int64 creation_time = cookie.CreationDate().ToInternalValue();
-    ASSERT_TRUE(cookies_.find(creation_time) != cookies_.end());
-    cookies_[creation_time].SetLastAccessDate(base::Time::Now());
-  }
-
-  virtual void DeleteCookie(
-      const net::CookieMonster::CanonicalCookie& cookie) {
-    int64 creation_time = cookie.CreationDate().ToInternalValue();
-    CanonicalCookieMap::iterator it = cookies_.find(creation_time);
-    ASSERT_TRUE(it != cookies_.end());
-    cookies_.erase(it);
-  }
-
-  virtual void Flush(Task* completion_task) {
-    if (completion_task)
-      MessageLoop::current()->PostTask(FROM_HERE, completion_task);
-  }
-
-  virtual void SetClearLocalStateOnExit(bool clear_local_state) {}
-
- private:
   CanonicalCookieMap cookies_;
 };
 
@@ -213,32 +147,9 @@
 // Do two SetCookies().  Return whether each of the two SetCookies() took
 // longer than |gc_perf_micros| to complete, and how many cookie were
 // left in the store afterwards.
-static net::CookieMonster* CreateMonsterFromStoreForGC(
+net::CookieMonster* CreateMonsterFromStoreForGC(
     int num_cookies,
     int num_old_cookies,
-    int days_old) {
-  base::Time current(base::Time::Now());
-  base::Time past_creation(base::Time::Now() - base::TimeDelta::FromDays(1000));
-  scoped_refptr<MockSimplePersistentCookieStore> store(
-      new MockSimplePersistentCookieStore);
-  // Must expire to be persistent
-  for (int i = 0; i < num_old_cookies; i++) {
-    net::CookieMonster::CanonicalCookie cc(
-        "a", "1", StringPrintf("h%05d.izzle", i), "/path", false, false,
-        past_creation + base::TimeDelta::FromMicroseconds(i),
-        current - base::TimeDelta::FromDays(days_old),
-        true, current + base::TimeDelta::FromDays(30));
-    store->AddCookie(cc);
-  }
-  for (int i = num_old_cookies; i < num_cookies; i++) {
-    net::CookieMonster::CanonicalCookie cc(
-        "a", "1", StringPrintf("h%05d.izzle", i), "/path", false, false,
-        past_creation + base::TimeDelta::FromMicroseconds(i), current,
-        true, current + base::TimeDelta::FromDays(30));
-    store->AddCookie(cc);
-  }
+    int days_old);
 
-  return new net::CookieMonster(store, NULL);
-}
-
-}  // namespace
+}  // namespace net
diff --git a/net/base/cookie_monster_unittest.cc b/net/base/cookie_monster_unittest.cc
index f431674..caaad67 100644
--- a/net/base/cookie_monster_unittest.cc
+++ b/net/base/cookie_monster_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc
index a0f6317..5f17511 100644
--- a/net/base/directory_lister.cc
+++ b/net/base/directory_lister.cc
@@ -39,64 +39,6 @@
   int error;
 };
 
-// Comparator for sorting lister results. This uses the locale aware filename
-// comparison function on the filenames for sorting in the user's locale.
-// Static.
-bool DirectoryLister::CompareAlphaDirsFirst(const DirectoryListerData& a,
-                                            const DirectoryListerData& b) {
-  // Parent directory before all else.
-  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a.info)))
-    return true;
-  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b.info)))
-    return false;
-
-  // Directories before regular files.
-  bool a_is_directory = file_util::FileEnumerator::IsDirectory(a.info);
-  bool b_is_directory = file_util::FileEnumerator::IsDirectory(b.info);
-  if (a_is_directory != b_is_directory)
-    return a_is_directory;
-
-  return file_util::LocaleAwareCompareFilenames(
-      file_util::FileEnumerator::GetFilename(a.info),
-      file_util::FileEnumerator::GetFilename(b.info));
-}
-
-// Static.
-bool DirectoryLister::CompareDate(const DirectoryListerData& a,
-                                  const DirectoryListerData& b) {
-  // Parent directory before all else.
-  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a.info)))
-    return true;
-  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b.info)))
-    return false;
-
-  // Directories before regular files.
-  bool a_is_directory = file_util::FileEnumerator::IsDirectory(a.info);
-  bool b_is_directory = file_util::FileEnumerator::IsDirectory(b.info);
-  if (a_is_directory != b_is_directory)
-    return a_is_directory;
-#if defined(OS_POSIX)
-  return a.info.stat.st_mtime > b.info.stat.st_mtime;
-#elif defined(OS_WIN)
-  if (a.info.ftLastWriteTime.dwHighDateTime ==
-      b.info.ftLastWriteTime.dwHighDateTime) {
-    return a.info.ftLastWriteTime.dwLowDateTime >
-           b.info.ftLastWriteTime.dwLowDateTime;
-  } else {
-    return a.info.ftLastWriteTime.dwHighDateTime >
-           b.info.ftLastWriteTime.dwHighDateTime;
-  }
-#endif
-}
-
-// Comparator for sorting find result by paths. This uses the locale-aware
-// comparison function on the filenames for sorting in the user's locale.
-// Static.
-bool DirectoryLister::CompareFullPath(const DirectoryListerData& a,
-                                      const DirectoryListerData& b) {
-  return file_util::LocaleAwareCompareFilenames(a.path, b.path);
-}
-
 DirectoryLister::DirectoryLister(const FilePath& dir,
                                  DirectoryListerDelegate* delegate)
     : dir_(dir),
@@ -121,15 +63,6 @@
   DCHECK(!dir.value().empty());
 }
 
-DirectoryLister::~DirectoryLister() {
-  if (thread_) {
-    // This is a bug and we should stop joining this thread.
-    // http://crbug.com/65331
-    base::ThreadRestrictions::ScopedAllowIO allow_io;
-    base::PlatformThread::Join(thread_);
-  }
-}
-
 bool DirectoryLister::Start() {
   // spawn a thread to enumerate the specified directory
 
@@ -216,6 +149,73 @@
   message_loop_->PostTask(FROM_HERE, e);
 }
 
+DirectoryLister::~DirectoryLister() {
+  if (thread_) {
+    // This is a bug and we should stop joining this thread.
+    // http://crbug.com/65331
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    base::PlatformThread::Join(thread_);
+  }
+}
+
+// Comparator for sorting lister results. This uses the locale aware filename
+// comparison function on the filenames for sorting in the user's locale.
+// Static.
+bool DirectoryLister::CompareAlphaDirsFirst(const DirectoryListerData& a,
+                                            const DirectoryListerData& b) {
+  // Parent directory before all else.
+  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a.info)))
+    return true;
+  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b.info)))
+    return false;
+
+  // Directories before regular files.
+  bool a_is_directory = file_util::FileEnumerator::IsDirectory(a.info);
+  bool b_is_directory = file_util::FileEnumerator::IsDirectory(b.info);
+  if (a_is_directory != b_is_directory)
+    return a_is_directory;
+
+  return file_util::LocaleAwareCompareFilenames(
+      file_util::FileEnumerator::GetFilename(a.info),
+      file_util::FileEnumerator::GetFilename(b.info));
+}
+
+// Static.
+bool DirectoryLister::CompareDate(const DirectoryListerData& a,
+                                  const DirectoryListerData& b) {
+  // Parent directory before all else.
+  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(a.info)))
+    return true;
+  if (file_util::IsDotDot(file_util::FileEnumerator::GetFilename(b.info)))
+    return false;
+
+  // Directories before regular files.
+  bool a_is_directory = file_util::FileEnumerator::IsDirectory(a.info);
+  bool b_is_directory = file_util::FileEnumerator::IsDirectory(b.info);
+  if (a_is_directory != b_is_directory)
+    return a_is_directory;
+#if defined(OS_POSIX)
+  return a.info.stat.st_mtime > b.info.stat.st_mtime;
+#elif defined(OS_WIN)
+  if (a.info.ftLastWriteTime.dwHighDateTime ==
+      b.info.ftLastWriteTime.dwHighDateTime) {
+    return a.info.ftLastWriteTime.dwLowDateTime >
+           b.info.ftLastWriteTime.dwLowDateTime;
+  } else {
+    return a.info.ftLastWriteTime.dwHighDateTime >
+           b.info.ftLastWriteTime.dwHighDateTime;
+  }
+#endif
+}
+
+// Comparator for sorting find result by paths. This uses the locale-aware
+// comparison function on the filenames for sorting in the user's locale.
+// Static.
+bool DirectoryLister::CompareFullPath(const DirectoryListerData& a,
+                                      const DirectoryListerData& b) {
+  return file_util::LocaleAwareCompareFilenames(a.path, b.path);
+}
+
 void DirectoryLister::OnReceivedData(const DirectoryListerData* data,
                                      int count) {
   // Since the delegate can clear itself during the OnListFile callback, we
diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h
index 368c783..26ac0d7 100644
--- a/net/base/directory_lister.h
+++ b/net/base/directory_lister.h
@@ -88,6 +88,8 @@
   friend class base::RefCountedThreadSafe<DirectoryLister>;
   friend class DirectoryDataEvent;
 
+  ~DirectoryLister();
+
   // Comparison methods for sorting, chosen based on |sort_|.
   static bool CompareAlphaDirsFirst(const DirectoryListerData& a,
                                     const DirectoryListerData& b);
@@ -96,8 +98,6 @@
   static bool CompareFullPath(const DirectoryListerData& a,
                               const DirectoryListerData& b);
 
-  ~DirectoryLister();
-
   void OnReceivedData(const DirectoryListerData* data, int count);
   void OnDone(int error);
 
diff --git a/net/base/dns_util.h b/net/base/dns_util.h
index 1120140..d86fcb9 100644
--- a/net/base/dns_util.h
+++ b/net/base/dns_util.h
@@ -28,6 +28,8 @@
 
 // DNS resource record types. See
 // http://www.iana.org/assignments/dns-parameters
+// WARNING: if you're adding any new values here you may need to add them to
+// dnsrr_resolver.cc:DnsRRIsParsedByWindows.
 
 static const uint16 kDNS_CNAME = 5;
 static const uint16 kDNS_TXT = 16;
diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc
index cdb305f..a1988e6 100644
--- a/net/base/dnsrr_resolver.cc
+++ b/net/base/dnsrr_resolver.cc
@@ -8,12 +8,16 @@
 #include <resolv.h>
 #endif
 
-#include "base/lock.h"
+#if defined(OS_WIN)
+#include <windns.h>
+#endif
+
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
 #include "base/singleton.h"
 #include "base/stl_util-inl.h"
 #include "base/string_piece.h"
+#include "base/synchronization/lock.h"
 #include "base/task.h"
 #include "base/threading/worker_pool.h"
 #include "net/base/dns_reload_timer.h"
@@ -70,10 +74,30 @@
 //
 //                                      Post
 
-
-
 namespace net {
 
+#if defined(OS_WIN)
+// DnsRRIsParsedByWindows returns true if Windows knows how to parse the given
+// RR type. RR data is returned in a DNS_RECORD structure which may be raw (if
+// Windows doesn't parse it) or may be a parse result. It's unclear how this
+// API is intended to evolve in the future. If Windows adds support for new RR
+// types in a future version a client which expected raw data will break.
+// See http://msdn.microsoft.com/en-us/library/ms682082(v=vs.85).aspx
+static bool DnsRRIsParsedByWindows(uint16 rrtype) {
+  // We only cover the types which are defined in dns_util.h
+  switch (rrtype) {
+    case kDNS_CNAME:
+    case kDNS_TXT:
+    case kDNS_DS:
+    case kDNS_RRSIG:
+    case kDNS_DNSKEY:
+      return true;
+    default:
+      return false;
+  }
+}
+#endif
+
 static const uint16 kClassIN = 1;
 // kMaxCacheEntries is the number of RRResponse objects that we'll cache.
 static const unsigned kMaxCacheEntries = 32;
@@ -144,7 +168,7 @@
   // deleted.
   void Cancel() {
     DCHECK_EQ(MessageLoop::current(), origin_loop_);
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     canceled_ = true;
   }
 
@@ -233,9 +257,67 @@
       return;
     }
 
+    // See http://msdn.microsoft.com/en-us/library/ms682016(v=vs.85).aspx
+    PDNS_RECORD record = NULL;
+    DNS_STATUS status =
+        DnsQuery_A(name_.c_str(), rrtype_, DNS_QUERY_STANDARD,
+                   NULL /* pExtra (reserved) */, &record, NULL /* pReserved */);
     response_.fetch_time = base::Time::Now();
-    response_.negative = true;
-    result_ = ERR_NAME_NOT_RESOLVED;
+    response_.name = name_;
+    response_.dnssec = false;
+    response_.ttl = 0;
+
+    if (status != 0) {
+      response_.negative = true;
+      result_ = ERR_NAME_NOT_RESOLVED;
+    } else {
+      response_.negative = false;
+      result_ = OK;
+      for (DNS_RECORD* cur = record; cur; cur = cur->pNext) {
+        if (cur->wType == rrtype_) {
+          response_.ttl = record->dwTtl;
+          // Windows will parse some types of resource records. If we want one
+          // of these types then we have to reserialise the record.
+          switch (rrtype_) {
+            case kDNS_TXT: {
+              // http://msdn.microsoft.com/en-us/library/ms682109(v=vs.85).aspx
+              const DNS_TXT_DATA* txt = &cur->Data.TXT;
+              std::string rrdata;
+
+              for (DWORD i = 0; i < txt->dwStringCount; i++) {
+                // Although the string is typed as a PWSTR, it's actually just
+                // an ASCII byte-string.  Also, the string must be < 256
+                // elements because the length in the DNS packet is a single
+                // byte.
+                const char* s = reinterpret_cast<char*>(txt->pStringArray[i]);
+                size_t len = strlen(s);
+                DCHECK_LT(len, 256u);
+                char len8 = static_cast<char>(len);
+                rrdata.push_back(len8);
+                rrdata += s;
+              }
+              response_.rrdatas.push_back(rrdata);
+              break;
+            }
+            default:
+              if (DnsRRIsParsedByWindows(rrtype_)) {
+                // Windows parses this type, but we don't have code to unparse
+                // it.
+                NOTREACHED() << "you need to add code for the RR type here";
+                response_.negative = true;
+                result_ = ERR_INVALID_ARGUMENT;
+              } else {
+                // This type is given to us raw.
+                response_.rrdatas.push_back(
+                    std::string(reinterpret_cast<char*>(&cur->Data),
+                                cur->wDataLength));
+              }
+          }
+        }
+      }
+    }
+
+    DnsRecordListFree(record, DnsFreeRecordList);
     Finish();
   }
 
@@ -271,7 +353,7 @@
       // after the PostTask, but before unlocking |lock_|. If we do not lock in
       // this case, we will end up deleting a locked Lock, which can lead to
       // memory leaks or worse errors.
-      AutoLock locked(lock_);
+      base::AutoLock locked(lock_);
       if (!canceled_)
         dnsrr_resolver_->HandleResult(name_, rrtype_, result_, response_);
     }
@@ -291,7 +373,7 @@
 
     bool canceled;
     {
-      AutoLock locked(lock_);
+      base::AutoLock locked(lock_);
       canceled = canceled_;
       if (!canceled) {
         origin_loop_->PostTask(
@@ -309,7 +391,7 @@
   MessageLoop* const origin_loop_;
   DnsRRResolver* const dnsrr_resolver_;
 
-  Lock lock_;
+  base::Lock lock_;
   bool canceled_;
 
   int result_;
@@ -417,6 +499,7 @@
         if (offset >= packet_len_)
           return false;
         p = &packet_[offset];
+        len = packet_len_ - offset;
       } else if ((d & 0xc0) == 0) {
         uint8 label_len = d;
         if (len < label_len)
diff --git a/net/base/dnsrr_resolver.h b/net/base/dnsrr_resolver.h
index 9cc5bb8..3280774 100644
--- a/net/base/dnsrr_resolver.h
+++ b/net/base/dnsrr_resolver.h
@@ -26,6 +26,14 @@
   RRResponse();
   ~RRResponse();
 
+  // HasExpired returns true if |fetch_time| + |ttl| is less than
+  // |current_time|.
+  bool HasExpired(base::Time current_time) const;
+
+  // For testing only
+  bool ParseFromResponse(const uint8* data, unsigned len,
+                         uint16 rrtype_requested);
+
   // name contains the canonical name of the resulting domain. If the queried
   // name was a CNAME then this can differ.
   std::string name;
@@ -42,14 +50,6 @@
   // negative is true if this is a negative cache entry, i.e. is a placeholder
   // to remember that a given RR doesn't exist.
   bool negative;
-
-  // HasExpired returns true if |fetch_time| + |ttl| is less than
-  // |current_time|.
-  bool HasExpired(base::Time current_time) const;
-
-  // For testing only
-  bool ParseFromResponse(const uint8* data, unsigned len,
-                         uint16 rrtype_requested);
 };
 
 class BoundNetLog;
@@ -69,6 +69,8 @@
 class DnsRRResolver : public base::NonThreadSafe,
                       public NetworkChangeNotifier::Observer {
  public:
+  typedef intptr_t Handle;
+
   enum {
     kInvalidHandle = 0,
   };
@@ -79,8 +81,6 @@
     FLAG_WANT_DNSSEC = 1,
   };
 
-  typedef intptr_t Handle;
-
   DnsRRResolver();
   ~DnsRRResolver();
 
diff --git a/net/base/dnsrr_resolver_unittest.cc b/net/base/dnsrr_resolver_unittest.cc
index dfa904a..560052a 100644
--- a/net/base/dnsrr_resolver_unittest.cc
+++ b/net/base/dnsrr_resolver_unittest.cc
@@ -17,8 +17,6 @@
 class DnsRRResolverTest : public testing::Test {
 };
 
-#if defined(OS_LINUX)
-
 class ExplodingCallback : public CallbackRunner<Tuple1<int> > {
  public:
   virtual void RunWithParams(const Tuple1<int>& params) {
@@ -26,8 +24,39 @@
   }
 };
 
-// This test is disabled because it depends on the external network to pass.
-// However, it may be useful when chaging the code.
+// These tests are disabled because they depend on the external network to
+// pass. However, they may be useful when chaging the code.
+TEST_F(DnsRRResolverTest, DISABLED_ResolveReal) {
+  RRResponse response;
+  TestCompletionCallback callback;
+  DnsRRResolver resolver;
+  DnsRRResolver::Handle handle;
+
+  handle = resolver.Resolve("test.imperialviolet.org", 13172, 0,
+                            &callback, &response, 0, BoundNetLog());
+  ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
+  ASSERT_EQ(OK, callback.WaitForResult());
+  ASSERT_EQ(1u, response.rrdatas.size());
+  LOG(ERROR) << "result length " << response.rrdatas[0].size();
+  LOG(ERROR) << "result is " << response.rrdatas[0];
+}
+
+TEST_F(DnsRRResolverTest, DISABLED_ResolveReal2) {
+  RRResponse response;
+  TestCompletionCallback callback;
+  DnsRRResolver resolver;
+  DnsRRResolver::Handle handle;
+
+  handle = resolver.Resolve("google.com", kDNS_TXT, 0,
+                            &callback, &response, 0, BoundNetLog());
+  ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
+  ASSERT_EQ(OK, callback.WaitForResult());
+  ASSERT_EQ(1u, response.rrdatas.size());
+  LOG(ERROR) << "result length " << response.rrdatas[0].size();
+  LOG(ERROR) << "result is " << response.rrdatas[0];
+}
+
+
 TEST_F(DnsRRResolverTest, Resolve) {
   RRResponse response;
   TestCompletionCallback callback;
@@ -55,7 +84,7 @@
   ASSERT_EQ(1u, resolver.cache_hits());
   ASSERT_EQ(0u, resolver.inflight_joins());
 
-  // Test that a callback is never made. This depends on there before another
+  // Test that a callback is never made. This depends on there being another
   // test after this one which will pump the MessageLoop.
   ExplodingCallback callback3;
   handle = resolver.Resolve("www.testing.notatld", kDNS_TESTING, 0,
@@ -94,6 +123,7 @@
   ASSERT_EQ(1u, resolver.inflight_joins());
 }
 
+#if defined(OS_POSIX)
 // This is a DNS packet resulting from querying a recursive resolver for a TXT
 // record for agl._pka.imperialviolet.org. You should be able to get a
 // replacement from a packet capture should it ever be needed.
@@ -178,7 +208,6 @@
     response.ParseFromResponse(copy, sizeof(copy), kDNS_TXT);
   }
 }
-
-#endif  // OS_LINUX
+#endif
 
 }  // namespace net
diff --git a/net/base/dnssec_chain_verifier.cc b/net/base/dnssec_chain_verifier.cc
index 2dbacbc..e6d31ee 100644
--- a/net/base/dnssec_chain_verifier.cc
+++ b/net/base/dnssec_chain_verifier.cc
@@ -109,9 +109,11 @@
 A CERT record is presented for www.l.google.com. The verification is complete.
 */
 
+namespace {
+
 // This is the 2048-bit DNS root key: http://www.iana.org/dnssec
 // 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
-static const unsigned char kRootKey[] = {
+const unsigned char kRootKey[] = {
  0x01, 0x01, 0x03, 0x08, 0x03, 0x01, 0x00, 0x01, 0xa8, 0x00, 0x20, 0xa9, 0x55,
  0x66, 0xba, 0x42, 0xe8, 0x86, 0xbb, 0x80, 0x4c, 0xda, 0x84, 0xe4, 0x7e, 0xf5,
  0x6d, 0xbd, 0x7a, 0xec, 0x61, 0x26, 0x15, 0x55, 0x2c, 0xec, 0x90, 0x6d, 0x21,
@@ -136,7 +138,32 @@
 };
 
 // kRootKeyID is the key id for kRootKey
-static const uint16 kRootKeyID = 19036;
+const uint16 kRootKeyID = 19036;
+
+// CountLabels returns the number of DNS labels in |a|, which must be in DNS,
+// length-prefixed form.
+unsigned CountLabels(base::StringPiece a) {
+  for (unsigned c = 0;; c++) {
+    if (!a.size())
+      return c;
+    uint8 label_len = a.data()[0];
+    a.remove_prefix(1);
+    DCHECK_GE(a.size(), label_len);
+    a.remove_prefix(label_len);
+  }
+}
+
+// RemoveLeadingLabel removes the first label from |a|, which must be in DNS,
+// length-prefixed form.
+void RemoveLeadingLabel(base::StringPiece* a) {
+  if (!a->size())
+    return;
+  uint8 label_len = a->data()[0];
+  a->remove_prefix(1);
+  a->remove_prefix(label_len);
+}
+
+}  // namespace
 
 namespace net {
 
@@ -217,6 +244,142 @@
   return rrdatas_;
 }
 
+// static
+std::map<std::string, std::string>
+DNSSECChainVerifier::ParseTLSTXTRecord(base::StringPiece rrdata) {
+  std::map<std::string, std::string> ret;
+
+  if (rrdata.empty())
+    return ret;
+
+  std::string txt;
+  txt.reserve(rrdata.size());
+
+  // TXT records are a series of 8-bit length prefixed substrings that we
+  // concatenate into |txt|
+  while (!rrdata.empty()) {
+    unsigned len = rrdata[0];
+    if (len == 0 || len + 1 > rrdata.size())
+      return ret;
+    txt.append(rrdata.data() + 1, len);
+    rrdata.remove_prefix(len + 1);
+  }
+
+  // We append a space to |txt| to make the parsing code, below, cleaner.
+  txt.append(" ");
+
+  // RECORD = KV (' '+ KV)*
+  // KV = KEY '=' VALUE
+  // KEY = [a-zA-Z0-9]+
+  // VALUE = [^ \0]*
+
+  enum State {
+    STATE_KEY,
+    STATE_VALUE,
+    STATE_SPACE,
+  };
+
+  State state = STATE_KEY;
+
+  std::map<std::string, std::string> m;
+
+  unsigned start = 0;
+  std::string key;
+
+  for (unsigned i = 0; i < txt.size(); i++) {
+    char c = txt[i];
+    if (c == 0)
+      return ret;  // NUL values are never allowed.
+
+    switch (state) {
+      case STATE_KEY:
+        if (c == '=') {
+          if (i == start)
+            return ret;  // zero length keys are not allowed.
+          key = txt.substr(start, i - start);
+          start = i + 1;
+          state = STATE_VALUE;
+          continue;
+        }
+        if (!IsAsciiAlpha(c) && !IsAsciiDigit(c))
+          return ret;  // invalid key value
+        break;
+      case STATE_VALUE:
+        if (c == ' ') {
+          if (m.find(key) == m.end())
+            m.insert(make_pair(key, txt.substr(start, i - start)));
+          state = STATE_SPACE;
+          continue;
+        }
+        break;
+      case STATE_SPACE:
+        if (c != ' ') {
+          start = i;
+          i--;
+          state = STATE_KEY;
+          continue;
+        }
+        break;
+      default:
+        NOTREACHED();
+        return ret;
+    }
+  }
+
+  if (state != STATE_SPACE)
+    return ret;
+
+  ret.swap(m);
+  return ret;
+}
+
+// MatchingLabels returns the number of labels which |a| and |b| share,
+// counting right-to-left from the root. |a| and |b| must be DNS,
+// length-prefixed names. All names match at the root label, so this always
+// returns a value >= 1.
+
+// static
+unsigned DNSSECChainVerifier::MatchingLabels(base::StringPiece a,
+                                             base::StringPiece b) {
+  unsigned c = 0;
+  unsigned a_labels = CountLabels(a);
+  unsigned b_labels = CountLabels(b);
+
+  while (a_labels > b_labels) {
+    RemoveLeadingLabel(&a);
+    a_labels--;
+  }
+  while (b_labels > a_labels) {
+    RemoveLeadingLabel(&b);
+    b_labels--;
+  }
+
+  for (;;) {
+    if (!a.size()) {
+      if (!b.size())
+        return c;
+      return 0;
+    }
+    if (!b.size())
+      return 0;
+    uint8 a_length = a.data()[0];
+    a.remove_prefix(1);
+    uint8 b_length = b.data()[0];
+    b.remove_prefix(1);
+    DCHECK_GE(a.size(), a_length);
+    DCHECK_GE(b.size(), b_length);
+
+    if (a_length == b_length && memcmp(a.data(), b.data(), a_length) == 0) {
+      c++;
+    } else {
+      c = 0;
+    }
+
+    a.remove_prefix(a_length);
+    b.remove_prefix(b_length);
+  }
+}
+
 // U8 reads, and removes, a single byte from |chain_|
 bool DNSSECChainVerifier::U8(uint8* v) {
   if (chain_.size() < 1)
@@ -468,19 +631,6 @@
   return OK;
 }
 
-// CountLabels returns the number of DNS labels in |a|, which must be in DNS,
-// length-prefixed form.
-static unsigned CountLabels(base::StringPiece a) {
-  for (unsigned c = 0;; c++) {
-    if (!a.size())
-      return c;
-    uint8 label_len = a.data()[0];
-    a.remove_prefix(1);
-    DCHECK_GE(a.size(), label_len);
-    a.remove_prefix(label_len);
-  }
-}
-
 // LeaveZone transitions out of the current zone, either by following DS
 // records to validate the entry key of the next zone, or because the final
 // resource records are given.
@@ -660,150 +810,4 @@
   return OK;
 }
 
-// static
-std::map<std::string, std::string>
-DNSSECChainVerifier::ParseTLSTXTRecord(base::StringPiece rrdata) {
-  std::map<std::string, std::string> ret;
-
-  if (rrdata.empty())
-    return ret;
-
-  std::string txt;
-  txt.reserve(rrdata.size());
-
-  // TXT records are a series of 8-bit length prefixed substrings that we
-  // concatenate into |txt|
-  while (!rrdata.empty()) {
-    unsigned len = rrdata[0];
-    if (len == 0 || len + 1 > rrdata.size())
-      return ret;
-    txt.append(rrdata.data() + 1, len);
-    rrdata.remove_prefix(len + 1);
-  }
-
-  // We append a space to |txt| to make the parsing code, below, cleaner.
-  txt.append(" ");
-
-  // RECORD = KV (' '+ KV)*
-  // KV = KEY '=' VALUE
-  // KEY = [a-zA-Z0-9]+
-  // VALUE = [^ \0]*
-
-  enum State {
-    STATE_KEY,
-    STATE_VALUE,
-    STATE_SPACE,
-  };
-
-  State state = STATE_KEY;
-
-  std::map<std::string, std::string> m;
-
-  unsigned start = 0;
-  std::string key;
-
-  for (unsigned i = 0; i < txt.size(); i++) {
-    char c = txt[i];
-    if (c == 0)
-      return ret;  // NUL values are never allowed.
-
-    switch (state) {
-      case STATE_KEY:
-        if (c == '=') {
-          if (i == start)
-            return ret;  // zero length keys are not allowed.
-          key = txt.substr(start, i - start);
-          start = i + 1;
-          state = STATE_VALUE;
-          continue;
-        }
-        if (!IsAsciiAlpha(c) && !IsAsciiDigit(c))
-          return ret;  // invalid key value
-        break;
-      case STATE_VALUE:
-        if (c == ' ') {
-          if (m.find(key) == m.end())
-            m.insert(make_pair(key, txt.substr(start, i - start)));
-          state = STATE_SPACE;
-          continue;
-        }
-        break;
-      case STATE_SPACE:
-        if (c != ' ') {
-          start = i;
-          i--;
-          state = STATE_KEY;
-          continue;
-        }
-        break;
-      default:
-        NOTREACHED();
-        return ret;
-    }
-  }
-
-  if (state != STATE_SPACE)
-    return ret;
-
-  ret.swap(m);
-  return ret;
-}
-
-// RemoveLeadingLabel removes the first label from |a|, which must be in DNS,
-// length-prefixed form.
-static void RemoveLeadingLabel(base::StringPiece* a) {
-  if (!a->size())
-    return;
-  uint8 label_len = a->data()[0];
-  a->remove_prefix(1);
-  a->remove_prefix(label_len);
-}
-
-// MatchingLabels returns the number of labels which |a| and |b| share,
-// counting right-to-left from the root. |a| and |b| must be DNS,
-// length-prefixed names. All names match at the root label, so this always
-// returns a value >= 1.
-
-// static
-unsigned DNSSECChainVerifier::MatchingLabels(base::StringPiece a,
-                                             base::StringPiece b) {
-  unsigned c = 0;
-  unsigned a_labels = CountLabels(a);
-  unsigned b_labels = CountLabels(b);
-
-  while (a_labels > b_labels) {
-    RemoveLeadingLabel(&a);
-    a_labels--;
-  }
-  while (b_labels > a_labels) {
-    RemoveLeadingLabel(&b);
-    b_labels--;
-  }
-
-  for (;;) {
-    if (!a.size()) {
-      if (!b.size())
-        return c;
-      return 0;
-    }
-    if (!b.size())
-      return 0;
-    uint8 a_length = a.data()[0];
-    a.remove_prefix(1);
-    uint8 b_length = b.data()[0];
-    b.remove_prefix(1);
-    DCHECK_GE(a.size(), a_length);
-    DCHECK_GE(b.size(), b_length);
-
-    if (a_length == b_length && memcmp(a.data(), b.data(), a_length) == 0) {
-      c++;
-    } else {
-      c = 0;
-    }
-
-    a.remove_prefix(a_length);
-    b.remove_prefix(b_length);
-  }
-}
-
 }  // namespace net
diff --git a/net/base/dnssec_keyset.cc b/net/base/dnssec_keyset.cc
index 70aa217..c7f8606 100644
--- a/net/base/dnssec_keyset.cc
+++ b/net/base/dnssec_keyset.cc
@@ -15,6 +15,19 @@
 #include "base/time.h"
 #include "net/base/dns_util.h"
 
+namespace {
+
+// These are encoded AlgorithmIdentifiers for the given signature algorithm.
+const unsigned char kRSAWithSHA1[] = {
+  0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5, 5, 0
+};
+
+const unsigned char kRSAWithSHA256[] = {
+  0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 5, 0
+};
+
+}  // namespace
+
 namespace net {
 
 DNSSECKeySet::DNSSECKeySet()
@@ -35,33 +48,6 @@
   return true;
 }
 
-// static
-uint16 DNSSECKeySet::DNSKEYToKeyID(const base::StringPiece& dnskey) {
-  const unsigned char* data =
-      reinterpret_cast<const unsigned char*>(dnskey.data());
-
-  // RFC 4043: App B
-  uint32 ac = 0;
-  for (unsigned i = 0; i < dnskey.size(); i++) {
-    if (i & 1) {
-      ac += data[i];
-    } else {
-      ac += static_cast<uint32>(data[i]) << 8;
-    }
-  }
-  ac += (ac >> 16) & 0xffff;
-  return ac;
-}
-
-// These are encoded AlgorithmIdentifiers for the given signature algorithm.
-static const unsigned char kRSAWithSHA1[] = {
-  0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5, 5, 0
-};
-
-static const unsigned char kRSAWithSHA256[] = {
-  0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 5, 0
-};
-
 bool DNSSECKeySet::CheckSignature(
     const base::StringPiece& name,
     const base::StringPiece& zone,
@@ -180,10 +166,109 @@
   return false;
 }
 
+// static
+uint16 DNSSECKeySet::DNSKEYToKeyID(const base::StringPiece& dnskey) {
+  const unsigned char* data =
+      reinterpret_cast<const unsigned char*>(dnskey.data());
+
+  // RFC 4043: App B
+  uint32 ac = 0;
+  for (unsigned i = 0; i < dnskey.size(); i++) {
+    if (i & 1) {
+      ac += data[i];
+    } else {
+      ac += static_cast<uint32>(data[i]) << 8;
+    }
+  }
+  ac += (ac >> 16) & 0xffff;
+  return ac;
+}
+
 void DNSSECKeySet::IgnoreTimestamps() {
   ignore_timestamps_ = true;
 }
 
+bool DNSSECKeySet::VerifySignature(
+    base::StringPiece signature_algorithm,
+    base::StringPiece signature,
+    base::StringPiece public_key,
+    base::StringPiece signed_data) {
+  // This code is largely a copy-and-paste from
+  // base/crypto/signature_verifier_nss.cc. We can't change
+  // base::SignatureVerifier to always use NSS because we want the ability to
+  // be FIPS 140-2 compliant. However, we can't use base::SignatureVerifier
+  // here because some platforms don't support SHA256 signatures. Therefore, we
+  // use NSS directly.
+
+  base::EnsureNSSInit();
+
+  CERTSubjectPublicKeyInfo* spki = NULL;
+  SECItem spki_der;
+  spki_der.type = siBuffer;
+  spki_der.data = (uint8*) public_key.data();
+  spki_der.len = public_key.size();
+  spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
+  if (!spki)
+    return false;
+  SECKEYPublicKey* pub_key = SECKEY_ExtractPublicKey(spki);
+  SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
+  if (!pub_key)
+    return false;
+
+  PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+  if (!arena) {
+    SECKEY_DestroyPublicKey(pub_key);
+    return false;
+  }
+
+  SECItem sig_alg_der;
+  sig_alg_der.type = siBuffer;
+  sig_alg_der.data = (uint8*) signature_algorithm.data();
+  sig_alg_der.len = signature_algorithm.size();
+  SECAlgorithmID sig_alg_id;
+  SECStatus rv;
+  rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate,
+                              &sig_alg_der);
+  if (rv != SECSuccess) {
+    SECKEY_DestroyPublicKey(pub_key);
+    PORT_FreeArena(arena, PR_TRUE);
+    return false;
+  }
+
+  SECItem sig;
+  sig.type = siBuffer;
+  sig.data = (uint8*) signature.data();
+  sig.len = signature.size();
+  SECOidTag hash_alg_tag;
+  VFYContext* vfy_context =
+      VFY_CreateContextWithAlgorithmID(pub_key, &sig,
+                                       &sig_alg_id, &hash_alg_tag,
+                                       NULL);
+  SECKEY_DestroyPublicKey(pub_key);
+  PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id.
+  if (!vfy_context) {
+    // A corrupted RSA signature could be detected without the data, so
+    // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
+    // (-8182).
+    return false;
+  }
+
+  rv = VFY_Begin(vfy_context);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+  rv = VFY_Update(vfy_context, (uint8*) signed_data.data(), signed_data.size());
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+  rv = VFY_End(vfy_context);
+  VFY_DestroyContext(vfy_context, PR_TRUE);
+
+  return rv == SECSuccess;
+}
+
 // This is an ASN.1 encoded AlgorithmIdentifier for RSA
 static const unsigned char kASN1AlgorithmIdentifierRSA[] = {
   0x30,  //   SEQUENCE
@@ -373,85 +458,4 @@
   return std::string(reinterpret_cast<char*>(out.get()), j);
 }
 
-bool DNSSECKeySet::VerifySignature(
-    base::StringPiece signature_algorithm,
-    base::StringPiece signature,
-    base::StringPiece public_key,
-    base::StringPiece signed_data) {
-  // This code is largely a copy-and-paste from
-  // base/crypto/signature_verifier_nss.cc. We can't change
-  // base::SignatureVerifier to always use NSS because we want the ability to
-  // be FIPS 140-2 compliant. However, we can't use base::SignatureVerifier
-  // here because some platforms don't support SHA256 signatures. Therefore, we
-  // use NSS directly.
-
-  base::EnsureNSSInit();
-
-  CERTSubjectPublicKeyInfo* spki = NULL;
-  SECItem spki_der;
-  spki_der.type = siBuffer;
-  spki_der.data = (uint8*) public_key.data();
-  spki_der.len = public_key.size();
-  spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
-  if (!spki)
-    return false;
-  SECKEYPublicKey* pub_key = SECKEY_ExtractPublicKey(spki);
-  SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
-  if (!pub_key)
-    return false;
-
-  PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-  if (!arena) {
-    SECKEY_DestroyPublicKey(pub_key);
-    return false;
-  }
-
-  SECItem sig_alg_der;
-  sig_alg_der.type = siBuffer;
-  sig_alg_der.data = (uint8*) signature_algorithm.data();
-  sig_alg_der.len = signature_algorithm.size();
-  SECAlgorithmID sig_alg_id;
-  SECStatus rv;
-  rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate,
-                              &sig_alg_der);
-  if (rv != SECSuccess) {
-    SECKEY_DestroyPublicKey(pub_key);
-    PORT_FreeArena(arena, PR_TRUE);
-    return false;
-  }
-
-  SECItem sig;
-  sig.type = siBuffer;
-  sig.data = (uint8*) signature.data();
-  sig.len = signature.size();
-  SECOidTag hash_alg_tag;
-  VFYContext* vfy_context =
-      VFY_CreateContextWithAlgorithmID(pub_key, &sig,
-                                       &sig_alg_id, &hash_alg_tag,
-                                       NULL);
-  SECKEY_DestroyPublicKey(pub_key);
-  PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id.
-  if (!vfy_context) {
-    // A corrupted RSA signature could be detected without the data, so
-    // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
-    // (-8182).
-    return false;
-  }
-
-  rv = VFY_Begin(vfy_context);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-  rv = VFY_Update(vfy_context, (uint8*) signed_data.data(), signed_data.size());
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-  rv = VFY_End(vfy_context);
-  VFY_DestroyContext(vfy_context, PR_TRUE);
-
-  return rv == SECSuccess;
-}
-
 }  // namespace net
diff --git a/net/base/escape.cc b/net/base/escape.cc
index 5479b82..ae8411b 100644
--- a/net/base/escape.cc
+++ b/net/base/escape.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -192,9 +192,9 @@
 
 // Convert the string to a sequence of bytes and then % escape anything
 // except alphanumerics and !'()*-._~
-std::wstring EscapeQueryParamValueUTF8(const std::wstring& text,
-                                       bool use_plus) {
-  return UTF8ToWide(Escape(WideToUTF8(text), kQueryCharmap, use_plus));
+string16 EscapeQueryParamValueUTF8(const string16& text,
+                                   bool use_plus) {
+  return UTF8ToUTF16(Escape(UTF16ToUTF8(text), kQueryCharmap, use_plus));
 }
 
 // non-printable, non-7bit, and (including space)  "#%:<>?[\]^`{|}
diff --git a/net/base/escape.h b/net/base/escape.h
index 39447a5..faa7bd3 100644
--- a/net/base/escape.h
+++ b/net/base/escape.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -125,8 +125,8 @@
 bool EscapeQueryParamValue(const string16& text, const char* codepage,
                            bool use_plus, string16* escaped);
 
-// A specialized version of EscapeQueryParamValue for wide strings that
+// A specialized version of EscapeQueryParamValue for string16s that
 // assumes the codepage is UTF8.  This is provided as a convenience.
-std::wstring EscapeQueryParamValueUTF8(const std::wstring& text, bool use_plus);
+string16 EscapeQueryParamValueUTF8(const string16& text, bool use_plus);
 
 #endif  // NET_BASE_ESCAPE_H_
diff --git a/net/base/escape_unittest.cc b/net/base/escape_unittest.cc
index 04a040e..60d4ae3 100644
--- a/net/base/escape_unittest.cc
+++ b/net/base/escape_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -66,7 +66,8 @@
   };
   for (size_t i = 0; i < arraysize(escape_cases); ++i) {
     EscapeCase value = escape_cases[i];
-    EXPECT_EQ(value.output, EscapeQueryParamValueUTF8(value.input, true));
+    EXPECT_EQ(WideToUTF16Hack(value.output),
+              EscapeQueryParamValueUTF8(WideToUTF16Hack(value.input), true));
   }
 
   const EscapeCase escape_cases_no_plus[] = {
@@ -76,7 +77,8 @@
   };
   for (size_t i = 0; i < arraysize(escape_cases_no_plus); ++i) {
     EscapeCase value = escape_cases_no_plus[i];
-    EXPECT_EQ(value.output, EscapeQueryParamValueUTF8(value.input, false));
+    EXPECT_EQ(WideToUTF16Hack(value.output),
+              EscapeQueryParamValueUTF8(WideToUTF16Hack(value.input), false));
   }
 
   // Test all the values in we're supposed to be escaping.
@@ -114,12 +116,10 @@
   string16 wide;
   EXPECT_TRUE(EscapeQueryParamValue(test_str, base::kCodepageUTF8, true,
                                     &wide));
-  EXPECT_EQ(UTF16ToWideHack(wide),
-            EscapeQueryParamValueUTF8(UTF16ToWideHack(test_str), true));
+  EXPECT_EQ(wide, EscapeQueryParamValueUTF8(test_str, true));
   EXPECT_TRUE(EscapeQueryParamValue(test_str, base::kCodepageUTF8, false,
                                     &wide));
-  EXPECT_EQ(UTF16ToWideHack(wide),
-            EscapeQueryParamValueUTF8(UTF16ToWideHack(test_str), false));
+  EXPECT_EQ(wide, EscapeQueryParamValueUTF8(test_str, false));
 }
 
 TEST(EscapeTest, EscapePath) {
diff --git a/net/base/file_stream.h b/net/base/file_stream.h
index 6a53204..52e9ce9 100644
--- a/net/base/file_stream.h
+++ b/net/base/file_stream.h
@@ -130,6 +130,7 @@
   //
   // This method should not be called if the stream was opened READ_ONLY.
   int Flush();
+
  private:
   class AsyncContext;
   friend class AsyncContext;
diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc
index bdc51ce..5484f09 100644
--- a/net/base/file_stream_posix.cc
+++ b/net/base/file_stream_posix.cc
@@ -458,13 +458,6 @@
   }
 }
 
-int FileStream::Flush() {
-  if (!IsOpen())
-    return ERR_UNEXPECTED;
-
-  return FlushFile(file_);
-}
-
 int64 FileStream::Truncate(int64 bytes) {
   if (!IsOpen())
     return ERR_UNEXPECTED;
@@ -482,4 +475,11 @@
   return result == 0 ? seek_position : MapErrorCode(errno);
 }
 
+int FileStream::Flush() {
+  if (!IsOpen())
+    return ERR_UNEXPECTED;
+
+  return FlushFile(file_);
+}
+
 }  // namespace net
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index b93d886..7c2ef50 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/callback.h"
 #include "base/file_util.h"
+#include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/platform_file.h"
 #include "net/base/file_stream.h"
diff --git a/net/base/filter.cc b/net/base/filter.cc
index 5e47ecb..38e6651 100644
--- a/net/base/filter.cc
+++ b/net/base/filter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -39,6 +39,8 @@
 FilterContext::~FilterContext() {
 }
 
+Filter::~Filter() {}
+
 Filter* Filter::Factory(const std::vector<FilterType>& filter_types,
                         const FilterContext& filter_context) {
   DCHECK_GT(filter_context.GetInputStreamBufferSize(), 0);
@@ -56,6 +58,59 @@
   return filter_list;
 }
 
+Filter::FilterStatus Filter::ReadData(char* dest_buffer, int* dest_len) {
+  const int dest_buffer_capacity = *dest_len;
+  if (last_status_ == FILTER_ERROR)
+    return last_status_;
+  if (!next_filter_.get())
+    return last_status_ = ReadFilteredData(dest_buffer, dest_len);
+  if (last_status_ == FILTER_NEED_MORE_DATA && !stream_data_len())
+    return next_filter_->ReadData(dest_buffer, dest_len);
+
+  do {
+    if (next_filter_->last_status() == FILTER_NEED_MORE_DATA) {
+      PushDataIntoNextFilter();
+      if (FILTER_ERROR == last_status_)
+        return FILTER_ERROR;
+    }
+    *dest_len = dest_buffer_capacity;  // Reset the input/output parameter.
+    next_filter_->ReadData(dest_buffer, dest_len);
+    if (FILTER_NEED_MORE_DATA == last_status_)
+        return next_filter_->last_status();
+
+    // In the case where this filter has data internally, and is indicating such
+    // with a last_status_ of FILTER_OK, but at the same time the next filter in
+    // the chain indicated it FILTER_NEED_MORE_DATA, we have to be cautious
+    // about confusing the caller.  The API confusion can appear if we return
+    // FILTER_OK (suggesting we have more data in aggregate), but yet we don't
+    // populate our output buffer.  When that is the case, we need to
+    // alternately call our filter element, and the next_filter element until we
+    // get out of this state (by pumping data into the next filter until it
+    // outputs data, or it runs out of data and reports that it NEED_MORE_DATA.)
+  } while (FILTER_OK == last_status_ &&
+           FILTER_NEED_MORE_DATA == next_filter_->last_status() &&
+           0 == *dest_len);
+
+  if (next_filter_->last_status() == FILTER_ERROR)
+    return FILTER_ERROR;
+  return FILTER_OK;
+}
+
+bool Filter::FlushStreamBuffer(int stream_data_len) {
+  DCHECK(stream_data_len <= stream_buffer_size_);
+  if (stream_data_len <= 0 || stream_data_len > stream_buffer_size_)
+    return false;
+
+  DCHECK(stream_buffer());
+  // Bail out if there is more data in the stream buffer to be filtered.
+  if (!stream_buffer() || stream_data_len_)
+    return false;
+
+  next_stream_data_ = stream_buffer()->data();
+  stream_data_len_ = stream_data_len;
+  return true;
+}
+
 // static
 Filter::FilterType Filter::ConvertEncodingToType(
     const std::string& filter_type) {
@@ -129,13 +184,13 @@
     // It was not an SDCH request, so we'll just record stats.
     if (1 < encoding_types->size()) {
       // Multiple filters were intended to only be used for SDCH (thus far!)
-      SdchManager::SdchErrorRecovery(
-          SdchManager::MULTIENCODING_FOR_NON_SDCH_REQUEST);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::MULTIENCODING_FOR_NON_SDCH_REQUEST);
     }
     if ((1 == encoding_types->size()) &&
         (FILTER_TYPE_SDCH == encoding_types->front())) {
-        SdchManager::SdchErrorRecovery(
-            SdchManager::SDCH_CONTENT_ENCODE_FOR_NON_SDCH_REQUEST);
+        net::SdchManager::SdchErrorRecovery(
+            net::SdchManager::SDCH_CONTENT_ENCODE_FOR_NON_SDCH_REQUEST);
     }
     return;
   }
@@ -155,8 +210,8 @@
     // no-op pass through filter if it doesn't get gzip headers where expected.
     if (1 == encoding_types->size()) {
       encoding_types->push_back(FILTER_TYPE_GZIP_HELPING_SDCH);
-      SdchManager::SdchErrorRecovery(
-          SdchManager::OPTIONAL_GUNZIP_ENCODING_ADDED);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::OPTIONAL_GUNZIP_ENCODING_ADDED);
     }
     return;
   }
@@ -190,11 +245,14 @@
     // Suspicious case: Advertised dictionary, but server didn't use sdch, and
     // we're HTML tagged.
     if (encoding_types->empty()) {
-      SdchManager::SdchErrorRecovery(SdchManager::ADDED_CONTENT_ENCODING);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::ADDED_CONTENT_ENCODING);
     } else if (1 == encoding_types->size()) {
-      SdchManager::SdchErrorRecovery(SdchManager::FIXED_CONTENT_ENCODING);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::FIXED_CONTENT_ENCODING);
     } else {
-      SdchManager::SdchErrorRecovery(SdchManager::FIXED_CONTENT_ENCODINGS);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::FIXED_CONTENT_ENCODINGS);
     }
   } else {
     // Remarkable case!?!  We advertised an SDCH dictionary, content-encoding
@@ -206,14 +264,14 @@
     // start with "text/html" for some other reason??  We'll report this as a
     // fixup to a binary file, but it probably really is text/html (some how).
     if (encoding_types->empty()) {
-      SdchManager::SdchErrorRecovery(
-          SdchManager::BINARY_ADDED_CONTENT_ENCODING);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::BINARY_ADDED_CONTENT_ENCODING);
     } else if (1 == encoding_types->size()) {
-      SdchManager::SdchErrorRecovery(
-          SdchManager::BINARY_FIXED_CONTENT_ENCODING);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::BINARY_FIXED_CONTENT_ENCODING);
     } else {
-      SdchManager::SdchErrorRecovery(
-          SdchManager::BINARY_FIXED_CONTENT_ENCODINGS);
+      net::SdchManager::SdchErrorRecovery(
+          net::SdchManager::BINARY_FIXED_CONTENT_ENCODINGS);
     }
   }
 
@@ -232,48 +290,6 @@
   return;
 }
 
-// static
-Filter* Filter::PrependNewFilter(FilterType type_id,
-                                 const FilterContext& filter_context,
-                                 Filter* filter_list) {
-  Filter* first_filter = NULL;  // Soon to be start of chain.
-  switch (type_id) {
-    case FILTER_TYPE_GZIP_HELPING_SDCH:
-    case FILTER_TYPE_DEFLATE:
-    case FILTER_TYPE_GZIP: {
-      scoped_ptr<GZipFilter> gz_filter(new GZipFilter(filter_context));
-      if (gz_filter->InitBuffer()) {
-        if (gz_filter->InitDecoding(type_id)) {
-          first_filter = gz_filter.release();
-        }
-      }
-      break;
-    }
-    case FILTER_TYPE_SDCH:
-    case FILTER_TYPE_SDCH_POSSIBLE: {
-      scoped_ptr<SdchFilter> sdch_filter(new SdchFilter(filter_context));
-      if (sdch_filter->InitBuffer()) {
-        if (sdch_filter->InitDecoding(type_id)) {
-          first_filter = sdch_filter.release();
-        }
-      }
-      break;
-    }
-    default: {
-      break;
-    }
-  }
-
-  if (!first_filter) {
-    // Cleanup and exit, since we can't construct this filter list.
-    delete filter_list;
-    return NULL;
-  }
-
-  first_filter->next_filter_.reset(filter_list);
-  return first_filter;
-}
-
 Filter::Filter(const FilterContext& filter_context)
     : stream_buffer_(NULL),
       stream_buffer_size_(0),
@@ -284,25 +300,11 @@
       filter_context_(filter_context) {
 }
 
-Filter::~Filter() {}
-
-bool Filter::InitBuffer() {
-  int buffer_size = filter_context_.GetInputStreamBufferSize();
-  DCHECK_GT(buffer_size, 0);
-  if (buffer_size <= 0 || stream_buffer())
-    return false;
-
-  stream_buffer_ = new net::IOBuffer(buffer_size);
-
-  if (stream_buffer()) {
-    stream_buffer_size_ = buffer_size;
-    return true;
-  }
-
-  return false;
+Filter::FilterStatus Filter::ReadFilteredData(char* dest_buffer,
+                                              int* dest_len) {
+  return Filter::FILTER_ERROR;
 }
 
-
 Filter::FilterStatus Filter::CopyOut(char* dest_buffer, int* dest_len) {
   int out_len;
   int input_len = *dest_len;
@@ -324,48 +326,64 @@
   }
 }
 
+// static
+Filter* Filter::PrependNewFilter(FilterType type_id,
+                                 const FilterContext& filter_context,
+                                 Filter* filter_list) {
+  Filter* first_filter = NULL;  // Soon to be start of chain.
+  switch (type_id) {
+    case FILTER_TYPE_GZIP_HELPING_SDCH:
+    case FILTER_TYPE_DEFLATE:
+    case FILTER_TYPE_GZIP: {
+      scoped_ptr<net::GZipFilter> gz_filter(
+          new net::GZipFilter(filter_context));
+      if (gz_filter->InitBuffer()) {
+        if (gz_filter->InitDecoding(type_id)) {
+          first_filter = gz_filter.release();
+        }
+      }
+      break;
+    }
+    case FILTER_TYPE_SDCH:
+    case FILTER_TYPE_SDCH_POSSIBLE: {
+      scoped_ptr<net::SdchFilter> sdch_filter(
+          new net::SdchFilter(filter_context));
+      if (sdch_filter->InitBuffer()) {
+        if (sdch_filter->InitDecoding(type_id)) {
+          first_filter = sdch_filter.release();
+        }
+      }
+      break;
+    }
+    default: {
+      break;
+    }
+  }
 
-Filter::FilterStatus Filter::ReadFilteredData(char* dest_buffer,
-                                              int* dest_len) {
-  return Filter::FILTER_ERROR;
+  if (!first_filter) {
+    // Cleanup and exit, since we can't construct this filter list.
+    delete filter_list;
+    return NULL;
+  }
+
+  first_filter->next_filter_.reset(filter_list);
+  return first_filter;
 }
 
-Filter::FilterStatus Filter::ReadData(char* dest_buffer, int* dest_len) {
-  const int dest_buffer_capacity = *dest_len;
-  if (last_status_ == FILTER_ERROR)
-    return last_status_;
-  if (!next_filter_.get())
-    return last_status_ = ReadFilteredData(dest_buffer, dest_len);
-  if (last_status_ == FILTER_NEED_MORE_DATA && !stream_data_len())
-    return next_filter_->ReadData(dest_buffer, dest_len);
+bool Filter::InitBuffer() {
+  int buffer_size = filter_context_.GetInputStreamBufferSize();
+  DCHECK_GT(buffer_size, 0);
+  if (buffer_size <= 0 || stream_buffer())
+    return false;
 
-  do {
-    if (next_filter_->last_status() == FILTER_NEED_MORE_DATA) {
-      PushDataIntoNextFilter();
-      if (FILTER_ERROR == last_status_)
-        return FILTER_ERROR;
-    }
-    *dest_len = dest_buffer_capacity;  // Reset the input/output parameter.
-    next_filter_->ReadData(dest_buffer, dest_len);
-    if (FILTER_NEED_MORE_DATA == last_status_)
-        return next_filter_->last_status();
+  stream_buffer_ = new net::IOBuffer(buffer_size);
 
-    // In the case where this filter has data internally, and is indicating such
-    // with a last_status_ of FILTER_OK, but at the same time the next filter in
-    // the chain indicated it FILTER_NEED_MORE_DATA, we have to be cautious
-    // about confusing the caller.  The API confusion can appear if we return
-    // FILTER_OK (suggesting we have more data in aggregate), but yet we don't
-    // populate our output buffer.  When that is the case, we need to
-    // alternately call our filter element, and the next_filter element until we
-    // get out of this state (by pumping data into the next filter until it
-    // outputs data, or it runs out of data and reports that it NEED_MORE_DATA.)
-  } while (FILTER_OK == last_status_ &&
-           FILTER_NEED_MORE_DATA == next_filter_->last_status() &&
-           0 == *dest_len);
+  if (stream_buffer()) {
+    stream_buffer_size_ = buffer_size;
+    return true;
+  }
 
-  if (next_filter_->last_status() == FILTER_ERROR)
-    return FILTER_ERROR;
-  return FILTER_OK;
+  return false;
 }
 
 void Filter::PushDataIntoNextFilter() {
@@ -375,19 +393,3 @@
   if (FILTER_ERROR != last_status_)
     next_filter_->FlushStreamBuffer(next_size);
 }
-
-
-bool Filter::FlushStreamBuffer(int stream_data_len) {
-  DCHECK(stream_data_len <= stream_buffer_size_);
-  if (stream_data_len <= 0 || stream_data_len > stream_buffer_size_)
-    return false;
-
-  DCHECK(stream_buffer());
-  // Bail out if there is more data in the stream buffer to be filtered.
-  if (!stream_buffer() || stream_data_len_)
-    return false;
-
-  next_stream_data_ = stream_buffer()->data();
-  stream_data_len_ = stream_data_len;
-  return true;
-}
diff --git a/net/base/filter.h b/net/base/filter.h
index d00a351..c6004e9 100644
--- a/net/base/filter.h
+++ b/net/base/filter.h
@@ -199,9 +199,10 @@
                                  std::vector<FilterType>* encoding_types);
 
  protected:
+  FRIEND_TEST_ALL_PREFIXES(SdchFilterTest, ContentTypeId);
+
   explicit Filter(const FilterContext& filter_context);
 
-  FRIEND_TEST_ALL_PREFIXES(SdchFilterTest, ContentTypeId);
   // Filters the data stored in stream_buffer_ and writes the output into the
   // dest_buffer passed in.
   //
diff --git a/net/base/filter_unittest.cc b/net/base/filter_unittest.cc
index 75fee20..c65c3de 100644
--- a/net/base/filter_unittest.cc
+++ b/net/base/filter_unittest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "net/base/filter.h"
-#include "net/base/filter_unittest.h"
+#include "net/base/mock_filter_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class FilterTest : public testing::Test {
@@ -36,7 +36,7 @@
 // Check various fixups that modify content encoding lists.
 TEST(FilterTest, ApacheGzip) {
   const int kInputBufferSize(100);
-  MockFilterContext filter_context(kInputBufferSize);
+  net::MockFilterContext filter_context(kInputBufferSize);
   filter_context.SetSdchResponse(false);
 
   // Check that redundant gzip mime type removes only solo gzip encoding.
@@ -85,7 +85,7 @@
   // Handle content encodings including SDCH.
   const std::string kTextHtmlMime("text/html");
   const int kInputBufferSize(100);
-  MockFilterContext filter_context(kInputBufferSize);
+  net::MockFilterContext filter_context(kInputBufferSize);
   filter_context.SetSdchResponse(true);
 
   std::vector<Filter::FilterType> encoding_types;
@@ -123,7 +123,7 @@
   // Handle interesting case where entire SDCH encoding assertion "got lost."
   const std::string kTextHtmlMime("text/html");
   const int kInputBufferSize(100);
-  MockFilterContext filter_context(kInputBufferSize);
+  net::MockFilterContext filter_context(kInputBufferSize);
   filter_context.SetSdchResponse(true);
 
   std::vector<Filter::FilterType> encoding_types;
@@ -159,7 +159,7 @@
 
 TEST(FilterTest, Svgz) {
   const int kInputBufferSize(100);
-  MockFilterContext filter_context(kInputBufferSize);
+  net::MockFilterContext filter_context(kInputBufferSize);
 
   // Check that svgz files are only decompressed when not downloading.
   const std::string kSvgzMime("image/svg+xml");
@@ -208,7 +208,7 @@
 TEST(FilterTest, UnsupportedMimeGzip) {
   // From issue 8170 - handling files with Content-Encoding: x-gzip
   const int kInputBufferSize(100);
-  MockFilterContext filter_context(kInputBufferSize);
+  net::MockFilterContext filter_context(kInputBufferSize);
   std::vector<Filter::FilterType> encoding_types;
   const std::string kTarMime("application/x-tar");
   const std::string kCpioMime("application/x-cpio");
@@ -296,7 +296,7 @@
   // From issue 16430 - Files with supported mime types should be decompressed,
   // even though these files end in .gz/.tgz.
   const int kInputBufferSize(100);
-  MockFilterContext filter_context(kInputBufferSize);
+  net::MockFilterContext filter_context(kInputBufferSize);
   std::vector<Filter::FilterType> encoding_types;
   const std::string kGzUrl("http://ignore.com/foo.gz");
   const std::string kUrl("http://ignore.com/foo");
diff --git a/net/base/filter_unittest.h b/net/base/filter_unittest.h
deleted file mode 100644
index a45e353..0000000
--- a/net/base/filter_unittest.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef NET_BASE_FILTER_UNITTEST_H_
-#define NET_BASE_FILTER_UNITTEST_H_
-#pragma once
-
-#include <string>
-
-#include "googleurl/src/gurl.h"
-#include "net/base/filter.h"
-
-//------------------------------------------------------------------------------
-class MockFilterContext : public FilterContext {
- public:
-  explicit MockFilterContext(int buffer_size)
-    : buffer_size_(buffer_size),
-      is_cached_content_(false),
-      is_download_(false),
-      is_sdch_response_(false),
-      response_code_(-1) {
-  }
-
-  void SetBufferSize(int buffer_size) { buffer_size_ = buffer_size; }
-  void SetMimeType(const std::string& mime_type) { mime_type_ = mime_type; }
-  void SetURL(const GURL& gurl) { gurl_ = gurl; }
-  void SetRequestTime(const base::Time time) { request_time_ = time; }
-  void SetCached(bool is_cached) { is_cached_content_ = is_cached; }
-  void SetDownload(bool is_download) { is_download_ = is_download; }
-  void SetResponseCode(int response_code) { response_code_ = response_code; }
-  void SetSdchResponse(bool is_sdch_response) {
-    is_sdch_response_ = is_sdch_response;
-  }
-
-  virtual bool GetMimeType(std::string* mime_type) const {
-    *mime_type = mime_type_;
-    return true;
-  }
-
-  // What URL was used to access this data?
-  // Return false if gurl is not present.
-  virtual bool GetURL(GURL* gurl) const {
-    *gurl = gurl_;
-    return true;
-  }
-
-  // What was this data requested from a server?
-  virtual base::Time GetRequestTime() const {
-    return request_time_;
-  }
-
-  // Is data supplied from cache, or fresh across the net?
-  virtual bool IsCachedContent() const { return is_cached_content_; }
-
-  // Is this a download?
-  virtual bool IsDownload() const { return is_download_; }
-
-  // Was this data flagged as a response to a request with an SDCH dictionary?
-  virtual bool IsSdchResponse() const { return is_sdch_response_; }
-
-  // How many bytes were fed to filter(s) so far?
-  virtual int64 GetByteReadCount() const { return 0; }
-
-  virtual int GetResponseCode() const { return response_code_; }
-
-  // What is the desirable input buffer size for these filters?
-  virtual int GetInputStreamBufferSize() const { return buffer_size_; }
-
-  virtual void RecordPacketStats(StatisticSelector statistic) const {}
-
- private:
-  int buffer_size_;
-  std::string mime_type_;
-  GURL gurl_;
-  base::Time request_time_;
-  bool is_cached_content_;
-  bool is_download_;
-  bool is_sdch_response_;
-  int response_code_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockFilterContext);
-};
-
-#endif  // NET_BASE_FILTER_UNITTEST_H_
diff --git a/net/base/gzip_filter.cc b/net/base/gzip_filter.cc
index f1920da..7248f2d 100644
--- a/net/base/gzip_filter.cc
+++ b/net/base/gzip_filter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,6 +22,7 @@
 #include "base/logging.h"
 #include "net/base/gzip_header.h"
 
+namespace net {
 
 GZipFilter::GZipFilter(const FilterContext& filter_context)
     : Filter(filter_context),
@@ -308,3 +309,5 @@
       next_stream_data_ = NULL;
   }
 }
+
+}  // namespace net
diff --git a/net/base/gzip_filter.h b/net/base/gzip_filter.h
index afdc970..b37a5b1 100644
--- a/net/base/gzip_filter.h
+++ b/net/base/gzip_filter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,16 +12,20 @@
 // GZipFilter is a subclass of Filter. See the latter's header file filter.h
 // for sample usage.
 
-#ifndef NET_BASE_GZIP_FILTER_H__
-#define NET_BASE_GZIP_FILTER_H__
+#ifndef NET_BASE_GZIP_FILTER_H_
+#define NET_BASE_GZIP_FILTER_H_
 #pragma once
 
+#include "base/basictypes.h"
 #include "base/scoped_ptr.h"
 #include "net/base/filter.h"
 
-class GZipHeader;
 typedef struct z_stream_s z_stream;
 
+namespace net {
+
+class GZipHeader;
+
 class GZipFilter : public Filter {
  public:
   explicit GZipFilter(const FilterContext& filter_context);
@@ -140,4 +144,6 @@
   DISALLOW_COPY_AND_ASSIGN(GZipFilter);
 };
 
+}  // namespace net
+
 #endif  // NET_BASE_GZIP_FILTER_H__
diff --git a/net/base/gzip_filter_unittest.cc b/net/base/gzip_filter_unittest.cc
index 8ca1f4d..758418c 100644
--- a/net/base/gzip_filter_unittest.cc
+++ b/net/base/gzip_filter_unittest.cc
@@ -20,8 +20,8 @@
 #include "base/file_util.h"
 #include "base/path_service.h"
 #include "base/scoped_ptr.h"
-#include "net/base/filter_unittest.h"
 #include "net/base/gzip_filter.h"
+#include "net/base/mock_filter_context.h"
 #include "net/base/io_buffer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -243,7 +243,7 @@
   // Decode the compressed data with filter
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_DEFLATE);
-  MockFilterContext filter_context(kDefaultBufferSize);
+  net::MockFilterContext filter_context(kDefaultBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   memcpy(filter->stream_buffer()->data(), deflate_encode_buffer_,
@@ -264,7 +264,7 @@
   // Decode the compressed data with filter
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_GZIP);
-  MockFilterContext filter_context(kDefaultBufferSize);
+  net::MockFilterContext filter_context(kDefaultBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   memcpy(filter->stream_buffer()->data(), gzip_encode_buffer_,
@@ -286,7 +286,7 @@
 TEST_F(GZipUnitTest, DecodeWithSmallBuffer) {
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_DEFLATE);
-  MockFilterContext filter_context(kSmallBufferSize);
+  net::MockFilterContext filter_context(kSmallBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(),
@@ -301,7 +301,7 @@
 TEST_F(GZipUnitTest, DecodeWithOneByteBuffer) {
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_GZIP);
-  MockFilterContext filter_context(1);
+  net::MockFilterContext filter_context(1);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(),
@@ -313,7 +313,7 @@
 TEST_F(GZipUnitTest, DecodeWithSmallOutputBuffer) {
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_DEFLATE);
-  MockFilterContext filter_context(kDefaultBufferSize);
+  net::MockFilterContext filter_context(kDefaultBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(),
@@ -326,7 +326,7 @@
 TEST_F(GZipUnitTest, DecodeWithOneByteInputAndOutputBuffer) {
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_GZIP);
-  MockFilterContext filter_context(1);
+  net::MockFilterContext filter_context(1);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(),
@@ -345,7 +345,7 @@
   // Decode the corrupted data with filter
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_DEFLATE);
-  MockFilterContext filter_context(kDefaultBufferSize);
+  net::MockFilterContext filter_context(kDefaultBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   char corrupt_decode_buffer[kDefaultBufferSize];
@@ -372,7 +372,7 @@
   // Decode the corrupted data with filter
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_DEFLATE);
-  MockFilterContext filter_context(kDefaultBufferSize);
+  net::MockFilterContext filter_context(kDefaultBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   char corrupt_decode_buffer[kDefaultBufferSize];
@@ -396,7 +396,7 @@
   // Decode the corrupted data with filter
   std::vector<Filter::FilterType> filter_types;
   filter_types.push_back(Filter::FILTER_TYPE_GZIP);
-  MockFilterContext filter_context(kDefaultBufferSize);
+  net::MockFilterContext filter_context(kDefaultBufferSize);
   scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
   ASSERT_TRUE(filter.get());
   char corrupt_decode_buffer[kDefaultBufferSize];
diff --git a/net/base/gzip_header.cc b/net/base/gzip_header.cc
index 654c6b1..2b8c454 100644
--- a/net/base/gzip_header.cc
+++ b/net/base/gzip_header.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,17 +12,22 @@
 
 #include "base/logging.h"
 
+namespace net {
+
 const uint8 GZipHeader::magic[] = { 0x1f, 0x8b };
 
-// ----------------------------------------------------------------------
-// GZipHeader::ReadMore()
-//    Attempt to parse the beginning of the given buffer as a gzip
-//    header. If these bytes do not constitute a complete gzip header,
-//    return INCOMPLETE_HEADER. If these bytes do not constitute a
-//    *valid* gzip header, return INVALID_HEADER. If we find a
-//    complete header, return COMPLETE_HEADER and set the pointer
-//    pointed to by header_end to the first byte beyond the gzip header.
-// ----------------------------------------------------------------------
+GZipHeader::GZipHeader() {
+  Reset();
+}
+
+GZipHeader::~GZipHeader() {
+}
+
+void GZipHeader::Reset() {
+  state_        = IN_HEADER_ID1;
+  flags_        = 0;
+  extra_length_ = 0;
+}
 
 GZipHeader::Status GZipHeader::ReadMore(const char* inbuf, int inbuf_len,
                                         const char** header_end) {
@@ -178,3 +183,5 @@
     return INCOMPLETE_HEADER;
   }
 }
+
+}  // namespace net
diff --git a/net/base/gzip_header.h b/net/base/gzip_header.h
index c245de2..85c284a 100644
--- a/net/base/gzip_header.h
+++ b/net/base/gzip_header.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,6 +18,8 @@
 
 #include "base/basictypes.h"
 
+namespace net {
+
 class GZipHeader {
  public:
   enum Status {
@@ -26,19 +28,11 @@
     INVALID_HEADER,       // found something invalid in the header
   };
 
-  GZipHeader() {
-    Reset();
-  }
-
-  ~GZipHeader() {
-  }
+  GZipHeader();
+  ~GZipHeader();
 
   // Wipe the slate clean and start from scratch.
-  void Reset() {
-    state_        = IN_HEADER_ID1;
-    flags_        = 0;
-    extra_length_ = 0;
-  }
+  void Reset();
 
   // Attempt to parse the given buffer as the next installment of
   // bytes from a gzip header. If the bytes we've seen so far do not
@@ -47,7 +41,8 @@
   // gzip header, return INVALID_HEADER. When we've seen a complete
   // gzip header, return COMPLETE_HEADER and set the pointer pointed
   // to by header_end to the first byte beyond the gzip header.
-  Status ReadMore(const char* inbuf, int inbuf_len,
+  Status ReadMore(const char* inbuf,
+                  int inbuf_len,
                   const char** header_end);
  private:
   enum {                       // flags (see RFC)
@@ -91,6 +86,10 @@
   int    state_;  // our current State in the parsing FSM: an int so we can ++
   uint8  flags_;         // the flags byte of the header ("FLG" in the RFC)
   uint16 extra_length_;  // how much of the "extra field" we have yet to read
+
+  DISALLOW_COPY_AND_ASSIGN(GZipHeader);
 };
 
+}  // namespace net
+
 #endif  // NET_BASE_GZIP_HEADER_H_
diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc
index a8b642a..49678a2 100644
--- a/net/base/host_resolver.cc
+++ b/net/base/host_resolver.cc
@@ -19,9 +19,6 @@
       priority_(MEDIUM) {
 }
 
-HostResolver::HostResolver() {
-}
-
 HostResolver::~HostResolver() {
 }
 
@@ -33,6 +30,9 @@
   return NULL;
 }
 
+HostResolver::HostResolver() {
+}
+
 SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver)
     : resolver_(resolver),
       cur_request_(NULL),
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
index a30f320..48bc985 100644
--- a/net/base/host_resolver_impl.cc
+++ b/net/base/host_resolver_impl.cc
@@ -18,12 +18,12 @@
 #include "base/compiler_specific.h"
 #include "base/debug/debugger.h"
 #include "base/debug/stack_trace.h"
-#include "base/lock.h"
 #include "base/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/worker_pool.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
@@ -408,7 +408,7 @@
     // Mark the job as cancelled, so when worker thread completes it will
     // not try to post completion to origin loop.
     {
-      AutoLock locked(origin_loop_lock_);
+      base::AutoLock locked(origin_loop_lock_);
       origin_loop_ = NULL;
     }
 
@@ -485,7 +485,7 @@
     // The origin loop could go away while we are trying to post to it, so we
     // need to call its PostTask method inside a lock.  See ~HostResolver.
     {
-      AutoLock locked(origin_loop_lock_);
+      base::AutoLock locked(origin_loop_lock_);
       if (origin_loop_) {
         origin_loop_->PostTask(FROM_HERE,
                                NewRunnableMethod(this, &Job::OnLookupComplete));
@@ -606,7 +606,7 @@
   RequestsList requests_;  // The requests waiting on this job.
 
   // Used to post ourselves onto the origin thread.
-  Lock origin_loop_lock_;
+  base::Lock origin_loop_lock_;
   MessageLoop* origin_loop_;
 
   // Hold an owning reference to the HostResolverProc that we are going to use.
@@ -664,7 +664,7 @@
     DCHECK(IsOnOriginThread());
     resolver_ = NULL;  // Read/write ONLY on origin thread.
     {
-      AutoLock locked(origin_loop_lock_);
+      base::AutoLock locked(origin_loop_lock_);
       // Origin loop may be destroyed before we can use it!
       origin_loop_ = NULL;  // Write ONLY on origin thread.
     }
@@ -698,7 +698,7 @@
     // The origin loop could go away while we are trying to post to it, so we
     // need to call its PostTask method inside a lock.  See ~HostResolver.
     {
-      AutoLock locked(origin_loop_lock_);
+      base::AutoLock locked(origin_loop_lock_);
       if (origin_loop_) {
         origin_loop_->PostTask(FROM_HERE, reply);
         return;
@@ -725,7 +725,7 @@
   HostResolverImpl* resolver_;
 
   // Used to post ourselves onto the origin thread.
-  Lock origin_loop_lock_;
+  base::Lock origin_loop_lock_;
   MessageLoop* origin_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob);
@@ -947,6 +947,24 @@
     delete job_pools_[i];
 }
 
+void HostResolverImpl::ProbeIPv6Support() {
+  DCHECK(CalledOnValidThread());
+  DCHECK(!ipv6_probe_monitoring_);
+  ipv6_probe_monitoring_ = true;
+  OnIPAddressChanged();  // Give initial setup call.
+}
+
+void HostResolverImpl::SetPoolConstraints(JobPoolIndex pool_index,
+                                          size_t max_outstanding_jobs,
+                                          size_t max_pending_requests) {
+  DCHECK(CalledOnValidThread());
+  CHECK_GE(pool_index, 0);
+  CHECK_LT(pool_index, POOL_COUNT);
+  CHECK(jobs_.empty()) << "Can only set constraints during setup";
+  JobPool* pool = job_pools_[pool_index];
+  pool->SetConstraints(max_outstanding_jobs, max_pending_requests);
+}
+
 int HostResolverImpl::Resolve(const RequestInfo& info,
                               AddressList* addresses,
                               CompletionCallback* callback,
@@ -1128,13 +1146,6 @@
   return default_address_family_;
 }
 
-void HostResolverImpl::ProbeIPv6Support() {
-  DCHECK(CalledOnValidThread());
-  DCHECK(!ipv6_probe_monitoring_);
-  ipv6_probe_monitoring_ = true;
-  OnIPAddressChanged();  // Give initial setup call.
-}
-
 HostResolverImpl* HostResolverImpl::GetAsHostResolverImpl() {
   return this;
 }
@@ -1149,17 +1160,6 @@
   shutdown_ = true;
 }
 
-void HostResolverImpl::SetPoolConstraints(JobPoolIndex pool_index,
-                                          size_t max_outstanding_jobs,
-                                          size_t max_pending_requests) {
-  DCHECK(CalledOnValidThread());
-  CHECK_GE(pool_index, 0);
-  CHECK_LT(pool_index, POOL_COUNT);
-  CHECK(jobs_.empty()) << "Can only set constraints during setup";
-  JobPool* pool = job_pools_[pool_index];
-  pool->SetConstraints(max_outstanding_jobs, max_pending_requests);
-}
-
 void HostResolverImpl::AddOutstandingJob(Job* job) {
   scoped_refptr<Job>& found_job = jobs_[job->key()];
   DCHECK(!found_job);
@@ -1308,28 +1308,6 @@
   source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
 }
 
-void HostResolverImpl::OnIPAddressChanged() {
-  if (cache_.get())
-    cache_->clear();
-  if (ipv6_probe_monitoring_) {
-    DCHECK(!shutdown_);
-    if (shutdown_)
-      return;
-    DiscardIPv6ProbeJob();
-    ipv6_probe_job_ = new IPv6ProbeJob(this);
-    ipv6_probe_job_->Start();
-  }
-#if defined(OS_LINUX)
-  if (HaveOnlyLoopbackAddresses()) {
-    additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
-  } else {
-    additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY;
-  }
-#endif
-  AbortAllInProgressJobs();
-  // |this| may be deleted inside AbortAllInProgressJobs().
-}
-
 void HostResolverImpl::DiscardIPv6ProbeJob() {
   if (ipv6_probe_job_.get()) {
     ipv6_probe_job_->Cancel();
@@ -1351,12 +1329,6 @@
   DiscardIPv6ProbeJob();
 }
 
-// static
-HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest(
-    const Request* req) {
-  return POOL_NORMAL;
-}
-
 bool HostResolverImpl::CanCreateJobForPool(const JobPool& pool) const {
   DCHECK_LE(jobs_.size(), max_jobs_);
 
@@ -1368,6 +1340,12 @@
   return pool.CanCreateJob();
 }
 
+// static
+HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest(
+    const Request* req) {
+  return POOL_NORMAL;
+}
+
 void HostResolverImpl::ProcessQueuedRequests() {
   // Find the highest priority request that can be scheduled.
   Request* top_req = NULL;
@@ -1461,4 +1439,26 @@
   }
 }
 
+void HostResolverImpl::OnIPAddressChanged() {
+  if (cache_.get())
+    cache_->clear();
+  if (ipv6_probe_monitoring_) {
+    DCHECK(!shutdown_);
+    if (shutdown_)
+      return;
+    DiscardIPv6ProbeJob();
+    ipv6_probe_job_ = new IPv6ProbeJob(this);
+    ipv6_probe_job_->Start();
+  }
+#if defined(OS_LINUX)
+  if (HaveOnlyLoopbackAddresses()) {
+    additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
+  } else {
+    additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY;
+  }
+#endif
+  AbortAllInProgressJobs();
+  // |this| may be deleted inside AbortAllInProgressJobs().
+}
+
 }  // namespace net
diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h
index d6d82d0..a571bb7 100644
--- a/net/base/host_resolver_impl.h
+++ b/net/base/host_resolver_impl.h
@@ -87,29 +87,10 @@
   // be called.
   virtual ~HostResolverImpl();
 
-  // HostResolver methods:
-  virtual int Resolve(const RequestInfo& info,
-                      AddressList* addresses,
-                      CompletionCallback* callback,
-                      RequestHandle* out_req,
-                      const BoundNetLog& source_net_log);
-  virtual void CancelRequest(RequestHandle req);
-  virtual void AddObserver(HostResolver::Observer* observer);
-  virtual void RemoveObserver(HostResolver::Observer* observer);
-
-  // Set address family, and disable IPv6 probe support.
-  virtual void SetDefaultAddressFamily(AddressFamily address_family);
-  virtual AddressFamily GetDefaultAddressFamily() const;
-
   // Continuously observe whether IPv6 is supported, and set the allowable
   // address family to IPv4 iff IPv6 is not supported.
   void ProbeIPv6Support();
 
-  virtual HostResolverImpl* GetAsHostResolverImpl();
-
-  // TODO(eroman): hack for http://crbug.com/15513
-  virtual void Shutdown();
-
   // Returns the cache this resolver uses, or NULL if caching is disabled.
   HostCache* cache() { return cache_.get(); }
 
@@ -128,6 +109,25 @@
                           size_t max_outstanding_jobs,
                           size_t max_pending_requests);
 
+  // HostResolver methods:
+  virtual int Resolve(const RequestInfo& info,
+                      AddressList* addresses,
+                      CompletionCallback* callback,
+                      RequestHandle* out_req,
+                      const BoundNetLog& source_net_log);
+  virtual void CancelRequest(RequestHandle req);
+  virtual void AddObserver(HostResolver::Observer* observer);
+  virtual void RemoveObserver(HostResolver::Observer* observer);
+
+  // Set address family, and disable IPv6 probe support.
+  virtual void SetDefaultAddressFamily(AddressFamily address_family);
+  virtual AddressFamily GetDefaultAddressFamily() const;
+
+  virtual HostResolverImpl* GetAsHostResolverImpl();
+
+  // TODO(eroman): hack for http://crbug.com/15513
+  virtual void Shutdown();
+
  private:
   class Job;
   class JobPool;
@@ -185,9 +185,6 @@
                        int request_id,
                        const RequestInfo& info);
 
-  // NetworkChangeNotifier::Observer methods:
-  virtual void OnIPAddressChanged();
-
   // Notify IPv6ProbeJob not to call back, and discard reference to the job.
   void DiscardIPv6ProbeJob();
 
@@ -226,6 +223,9 @@
   // Aborts all in progress jobs (but might start new ones).
   void AbortAllInProgressJobs();
 
+  // NetworkChangeNotifier::Observer methods:
+  virtual void OnIPAddressChanged();
+
   // Cache of host resolution results.
   scoped_ptr<HostCache> cache_;
 
diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc
index 4d26ab9..8d418e9 100644
--- a/net/base/host_resolver_impl_unittest.cc
+++ b/net/base/host_resolver_impl_unittest.cc
@@ -92,7 +92,7 @@
                       int* os_error) {
     event_.Wait();
     {
-      AutoLock l(lock_);
+      base::AutoLock l(lock_);
       capture_list_.push_back(CaptureEntry(hostname, address_family));
     }
     return ResolveUsingPrevious(hostname, address_family,
@@ -102,7 +102,7 @@
   CaptureList GetCaptureList() const {
     CaptureList copy;
     {
-      AutoLock l(lock_);
+      base::AutoLock l(lock_);
       copy = capture_list_;
     }
     return copy;
@@ -112,7 +112,7 @@
   ~CapturingHostResolverProc() {}
 
   CaptureList capture_list_;
-  mutable Lock lock_;
+  mutable base::Lock lock_;
   base::WaitableEvent event_;
 };
 
diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc
index 36f0a4b..73f4881 100644
--- a/net/base/host_resolver_proc.cc
+++ b/net/base/host_resolver_proc.cc
@@ -64,6 +64,25 @@
     SetPreviousProc(default_proc_);
 }
 
+HostResolverProc::~HostResolverProc() {
+}
+
+int HostResolverProc::ResolveUsingPrevious(
+    const std::string& host,
+    AddressFamily address_family,
+    HostResolverFlags host_resolver_flags,
+    AddressList* addrlist,
+    int* os_error) {
+  if (previous_proc_) {
+    return previous_proc_->Resolve(host, address_family, host_resolver_flags,
+                                   addrlist, os_error);
+  }
+
+  // Final fallback is the system resolver.
+  return SystemHostResolverProc(host, address_family, host_resolver_flags,
+                                addrlist, os_error);
+}
+
 void HostResolverProc::SetPreviousProc(HostResolverProc* proc) {
   HostResolverProc* current_previous = previous_proc_;
   previous_proc_ = NULL;
@@ -98,25 +117,6 @@
   return default_proc_;
 }
 
-HostResolverProc::~HostResolverProc() {
-}
-
-int HostResolverProc::ResolveUsingPrevious(
-    const std::string& host,
-    AddressFamily address_family,
-    HostResolverFlags host_resolver_flags,
-    AddressList* addrlist,
-    int* os_error) {
-  if (previous_proc_) {
-    return previous_proc_->Resolve(host, address_family, host_resolver_flags,
-                                   addrlist, os_error);
-  }
-
-  // Final fallback is the system resolver.
-  return SystemHostResolverProc(host, address_family, host_resolver_flags,
-                                addrlist, os_error);
-}
-
 int SystemHostResolverProc(const std::string& host,
                            AddressFamily address_family,
                            HostResolverFlags host_resolver_flags,
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc
index dfd4d38..7e5a1fe 100644
--- a/net/base/io_buffer.cc
+++ b/net/base/io_buffer.cc
@@ -52,11 +52,6 @@
       used_(0) {
 }
 
-DrainableIOBuffer::~DrainableIOBuffer() {
-  // The buffer is owned by the |base_| instance.
-  data_ = NULL;
-}
-
 void DrainableIOBuffer::DidConsume(int bytes) {
   SetOffset(used_ + bytes);
 }
@@ -76,16 +71,17 @@
   data_ = base_->data() + used_;
 }
 
+DrainableIOBuffer::~DrainableIOBuffer() {
+  // The buffer is owned by the |base_| instance.
+  data_ = NULL;
+}
+
 GrowableIOBuffer::GrowableIOBuffer()
     : IOBuffer(),
       capacity_(0),
       offset_(0) {
 }
 
-GrowableIOBuffer::~GrowableIOBuffer() {
-  data_ = NULL;
-}
-
 void GrowableIOBuffer::SetCapacity(int capacity) {
   DCHECK(capacity >= 0);
   // realloc will crash if it fails.
@@ -111,14 +107,17 @@
   return real_data_.get();
 }
 
-PickledIOBuffer::PickledIOBuffer() : IOBuffer() {}
+GrowableIOBuffer::~GrowableIOBuffer() {
+  data_ = NULL;
+}
 
-PickledIOBuffer::~PickledIOBuffer() { data_ = NULL; }
+PickledIOBuffer::PickledIOBuffer() : IOBuffer() {}
 
 void PickledIOBuffer::Done() {
   data_ = const_cast<char*>(static_cast<const char*>(pickle_.data()));
 }
 
+PickledIOBuffer::~PickledIOBuffer() { data_ = NULL; }
 
 WrappedIOBuffer::WrappedIOBuffer(const char* data)
     : IOBuffer(const_cast<char*>(data)) {
diff --git a/net/base/keygen_handler.h b/net/base/keygen_handler.h
index 5ca6027..817720d 100644
--- a/net/base/keygen_handler.h
+++ b/net/base/keygen_handler.h
@@ -8,8 +8,16 @@
 
 #include <string>
 
+#include "base/scoped_ptr.h"
+#include "build/build_config.h"
 #include "googleurl/src/gurl.h"
 
+#if defined(USE_NSS)
+namespace base {
+class CryptoModuleBlockingPasswordDelegate;
+};
+#endif  // defined(USE_NSS)
+
 namespace net {
 
 // This class handles keypair generation for generating client
@@ -22,9 +30,10 @@
   // Creates a handler that will generate a key with the given key size and
   // incorporate the |challenge| into the Netscape SPKAC structure. The request
   // for the key originated from |url|.
-  inline KeygenHandler(int key_size_in_bits,
-                       const std::string& challenge,
-                       const GURL& url);
+  KeygenHandler(int key_size_in_bits,
+                const std::string& challenge,
+                const GURL& url);
+  ~KeygenHandler();
 
   // Actually generates the key-pair and the cert request (SPKAC), and returns
   // a base64-encoded string suitable for use as the form value of <keygen>.
@@ -33,22 +42,27 @@
   // Exposed only for unit tests.
   void set_stores_key(bool store) { stores_key_ = store;}
 
+#if defined(USE_NSS)
+  // Register the password delegate to be used if the token is unauthenticated.
+  // GenKeyAndSignChallenge runs on a worker thread, so using the blocking
+  // password callback is okay here.
+  // Takes ownership of the delegate.
+  void set_crypto_module_password_delegate(
+      base::CryptoModuleBlockingPasswordDelegate* delegate);
+#endif  // defined(USE_NSS)
+
  private:
   int key_size_in_bits_;  // key size in bits (usually 2048)
   std::string challenge_;  // challenge string sent by server
   GURL url_;  // the URL that requested the key
   bool stores_key_;  // should the generated key-pair be stored persistently?
+#if defined(USE_NSS)
+  // The callback for requesting a password to the PKCS#11 token.
+  scoped_ptr<base::CryptoModuleBlockingPasswordDelegate>
+      crypto_module_password_delegate_;
+#endif  // defined(USE_NSS)
 };
 
-KeygenHandler::KeygenHandler(int key_size_in_bits,
-                             const std::string& challenge,
-                             const GURL& url)
-    : key_size_in_bits_(key_size_in_bits),
-      challenge_(challenge),
-      url_(url),
-      stores_key_(true) {
-}
-
 }  // namespace net
 
 #endif  // NET_BASE_KEYGEN_HANDLER_H_
diff --git a/net/base/keygen_handler_mac.cc b/net/base/keygen_handler_mac.cc
index fdad99e..df9ce4a 100644
--- a/net/base/keygen_handler_mac.cc
+++ b/net/base/keygen_handler_mac.cc
@@ -10,10 +10,10 @@
 
 #include "base/base64.h"
 #include "base/crypto/cssm_init.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/sys_string_conversions.h"
 
 // These are in Security.framework but not declared in a public header.
@@ -234,7 +234,7 @@
   }
   base::mac::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain);
   {
-    AutoLock locked(base::GetMacSecurityServicesLock());
+    base::AutoLock locked(base::GetMacSecurityServicesLock());
     err = SecKeyCreatePair(
         keychain,
         CSSM_ALGID_RSA,
@@ -261,7 +261,7 @@
   OSStatus err;
   const CSSM_ACCESS_CREDENTIALS* credentials = NULL;
   {
-    AutoLock locked(base::GetMacSecurityServicesLock());
+    base::AutoLock locked(base::GetMacSecurityServicesLock());
     err = SecKeyGetCredentials(key,
                                CSSM_ACL_AUTHORIZATION_SIGN,
                                kSecCredentialTypeDefault,
@@ -274,7 +274,7 @@
 
   CSSM_CSP_HANDLE csp_handle = 0;
   {
-    AutoLock locked(base::GetMacSecurityServicesLock());
+    base::AutoLock locked(base::GetMacSecurityServicesLock());
     err = SecKeyGetCSPHandle(key, &csp_handle);
   }
   if (err) {
@@ -284,7 +284,7 @@
 
   const CSSM_KEY* cssm_key = NULL;
   {
-    AutoLock locked(base::GetMacSecurityServicesLock());
+    base::AutoLock locked(base::GetMacSecurityServicesLock());
     err = SecKeyGetCSSMKey(key, &cssm_key);
   }
   if (err) {
diff --git a/net/base/keygen_handler_nss.cc b/net/base/keygen_handler_nss.cc
index 215244c..74fb9a6 100644
--- a/net/base/keygen_handler_nss.cc
+++ b/net/base/keygen_handler_nss.cc
@@ -4,6 +4,11 @@
 
 #include "net/base/keygen_handler.h"
 
+#include "base/crypto/crypto_module_blocking_password_delegate.h"
+#include "base/crypto/scoped_nss_types.h"
+#include "base/logging.h"
+#include "base/nss_util.h"
+#include "base/nss_util_internal.h"
 #include "net/third_party/mozilla_security_manager/nsKeygenHandler.h"
 
 // PSM = Mozilla's Personal Security Manager.
@@ -12,8 +17,30 @@
 namespace net {
 
 std::string KeygenHandler::GenKeyAndSignChallenge() {
+  // Ensure NSS is initialized.
+  base::EnsureNSSInit();
+
+  // TODO(mattm): allow choosing which slot to generate and store the key?
+  base::ScopedPK11Slot slot(base::GetDefaultNSSKeySlot());
+  if (!slot.get()) {
+    LOG(ERROR) << "Couldn't get internal key slot!";
+    return std::string();
+  }
+
+  // Authenticate to the token.
+  if (SECSuccess != PK11_Authenticate(slot.get(), PR_TRUE,
+                                      crypto_module_password_delegate_.get())) {
+    LOG(ERROR) << "Couldn't authenticate to internal key slot!";
+    return std::string();
+  }
+
   return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_, url_,
-                                     stores_key_);
+                                     slot.get(), stores_key_);
+}
+
+void KeygenHandler::set_crypto_module_password_delegate(
+    base::CryptoModuleBlockingPasswordDelegate* delegate) {
+  crypto_module_password_delegate_.reset(delegate);
 }
 
 }  // namespace net
diff --git a/net/base/listen_socket.cc b/net/base/listen_socket.cc
index 445d57d..6ca8dcc 100644
--- a/net/base/listen_socket.cc
+++ b/net/base/listen_socket.cc
@@ -44,6 +44,44 @@
 const int ListenSocket::kSocketError = -1;
 #endif
 
+ListenSocket* ListenSocket::Listen(std::string ip, int port,
+                                   ListenSocketDelegate* del) {
+  SOCKET s = Listen(ip, port);
+  if (s == kInvalidSocket) {
+    // TODO(erikkay): error handling
+  } else {
+    ListenSocket* sock = new ListenSocket(s, del);
+    sock->Listen();
+    return sock;
+  }
+  return NULL;
+}
+
+void ListenSocket::Send(const char* bytes, int len, bool append_linefeed) {
+  SendInternal(bytes, len);
+  if (append_linefeed) {
+    SendInternal("\r\n", 2);
+  }
+}
+
+void ListenSocket::Send(const std::string& str, bool append_linefeed) {
+  Send(str.data(), static_cast<int>(str.length()), append_linefeed);
+}
+
+void ListenSocket::PauseReads() {
+  DCHECK(!reads_paused_);
+  reads_paused_ = true;
+}
+
+void ListenSocket::ResumeReads() {
+  DCHECK(reads_paused_);
+  reads_paused_ = false;
+  if (has_pending_reads_) {
+    has_pending_reads_ = false;
+    Read();
+  }
+}
+
 ListenSocket::ListenSocket(SOCKET s, ListenSocketDelegate *del)
     : socket_(s),
       socket_delegate_(del),
@@ -69,6 +107,11 @@
 SOCKET ListenSocket::Listen(std::string ip, int port) {
   SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (s != kInvalidSocket) {
+#if defined(OS_POSIX)
+    // Allow rapid reuse.
+    static const int kOn = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
+#endif
     sockaddr_in addr;
     memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
@@ -86,28 +129,6 @@
   return s;
 }
 
-ListenSocket* ListenSocket::Listen(std::string ip, int port,
-                                   ListenSocketDelegate* del) {
-  SOCKET s = Listen(ip, port);
-  if (s == kInvalidSocket) {
-    // TODO(erikkay): error handling
-  } else {
-    ListenSocket* sock = new ListenSocket(s, del);
-    sock->Listen();
-    return sock;
-  }
-  return NULL;
-}
-
-void ListenSocket::Listen() {
-  int backlog = 10;  // TODO(erikkay): maybe don't allow any backlog?
-  listen(socket_, backlog);
-  // TODO(erikkay): error handling
-#if defined(OS_POSIX)
-  WatchSocket(WAITING_ACCEPT);
-#endif
-}
-
 SOCKET ListenSocket::Accept(SOCKET s) {
   sockaddr_in from;
   socklen_t from_len = sizeof(from);
@@ -119,6 +140,45 @@
   return conn;
 }
 
+void ListenSocket::SendInternal(const char* bytes, int len) {
+  char* send_buf = const_cast<char *>(bytes);
+  int len_left = len;
+  while (true) {
+    int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
+    if (sent == len_left) {  // A shortcut to avoid extraneous checks.
+      break;
+    }
+    if (sent == kSocketError) {
+#if defined(OS_WIN)
+      if (WSAGetLastError() != WSAEWOULDBLOCK) {
+        LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
+#elif defined(OS_POSIX)
+      if (errno != EWOULDBLOCK && errno != EAGAIN) {
+        LOG(ERROR) << "send failed: errno==" << errno;
+#endif
+        break;
+      }
+      // Otherwise we would block, and now we have to wait for a retry.
+      // Fall through to PlatformThread::YieldCurrentThread()
+    } else {
+      // sent != len_left according to the shortcut above.
+      // Shift the buffer start and send the remainder after a short while.
+      send_buf += sent;
+      len_left -= sent;
+    }
+    base::PlatformThread::YieldCurrentThread();
+  }
+}
+
+void ListenSocket::Listen() {
+  int backlog = 10;  // TODO(erikkay): maybe don't allow any backlog?
+  listen(socket_, backlog);
+  // TODO(erikkay): error handling
+#if defined(OS_POSIX)
+  WatchSocket(WAITING_ACCEPT);
+#endif
+}
+
 void ListenSocket::Accept() {
   SOCKET conn = Accept(socket_);
   if (conn != kInvalidSocket) {
@@ -166,17 +226,6 @@
   } while (len == kReadBufSize);
 }
 
-void ListenSocket::CloseSocket(SOCKET s) {
-  if (s && s != kInvalidSocket) {
-    UnwatchSocket();
-#if defined(OS_WIN)
-    closesocket(s);
-#elif defined(OS_POSIX)
-    close(s);
-#endif
-  }
-}
-
 void ListenSocket::Close() {
 #if defined(OS_POSIX)
   if (wait_state_ == WAITING_CLOSE)
@@ -186,12 +235,15 @@
   socket_delegate_->DidClose(this);
 }
 
-void ListenSocket::UnwatchSocket() {
+void ListenSocket::CloseSocket(SOCKET s) {
+  if (s && s != kInvalidSocket) {
+    UnwatchSocket();
 #if defined(OS_WIN)
-  watcher_.StopWatching();
+    closesocket(s);
 #elif defined(OS_POSIX)
-  watcher_.StopWatchingFileDescriptor();
+    close(s);
 #endif
+  }
 }
 
 void ListenSocket::WatchSocket(WaitState state) {
@@ -206,59 +258,12 @@
 #endif
 }
 
-void ListenSocket::SendInternal(const char* bytes, int len) {
-  char* send_buf = const_cast<char *>(bytes);
-  int len_left = len;
-  while (true) {
-    int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
-    if (sent == len_left) {  // A shortcut to avoid extraneous checks.
-      break;
-    }
-    if (sent == kSocketError) {
+void ListenSocket::UnwatchSocket() {
 #if defined(OS_WIN)
-      if (WSAGetLastError() != WSAEWOULDBLOCK) {
-        LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
+  watcher_.StopWatching();
 #elif defined(OS_POSIX)
-      if (errno != EWOULDBLOCK && errno != EAGAIN) {
-        LOG(ERROR) << "send failed: errno==" << errno;
+  watcher_.StopWatchingFileDescriptor();
 #endif
-        break;
-      }
-      // Otherwise we would block, and now we have to wait for a retry.
-      // Fall through to PlatformThread::YieldCurrentThread()
-    } else {
-      // sent != len_left according to the shortcut above.
-      // Shift the buffer start and send the remainder after a short while.
-      send_buf += sent;
-      len_left -= sent;
-    }
-    base::PlatformThread::YieldCurrentThread();
-  }
-}
-
-void ListenSocket::Send(const char* bytes, int len, bool append_linefeed) {
-  SendInternal(bytes, len);
-  if (append_linefeed) {
-    SendInternal("\r\n", 2);
-  }
-}
-
-void ListenSocket::Send(const std::string& str, bool append_linefeed) {
-  Send(str.data(), static_cast<int>(str.length()), append_linefeed);
-}
-
-void ListenSocket::PauseReads() {
-  DCHECK(!reads_paused_);
-  reads_paused_ = true;
-}
-
-void ListenSocket::ResumeReads() {
-  DCHECK(reads_paused_);
-  reads_paused_ = false;
-  if (has_pending_reads_) {
-    has_pending_reads_ = false;
-    Read();
-  }
 }
 
 // TODO(ibrar): We can add these functions into OS dependent files
diff --git a/net/base/listen_socket.h b/net/base/listen_socket.h
index 641ae51..086705e 100644
--- a/net/base/listen_socket.h
+++ b/net/base/listen_socket.h
@@ -76,6 +76,13 @@
  protected:
   friend class base::RefCountedThreadSafe<ListenSocket>;
 
+  enum WaitState {
+    NOT_WAITING      = 0,
+    WAITING_ACCEPT   = 1,
+    WAITING_READ     = 3,
+    WAITING_CLOSE    = 4
+  };
+
   static const SOCKET kInvalidSocket;
   static const int kSocketError;
 
@@ -93,12 +100,6 @@
   virtual void Close();
   virtual void CloseSocket(SOCKET s);
 
-  enum WaitState {
-    NOT_WAITING      = 0,
-    WAITING_ACCEPT   = 1,
-    WAITING_READ     = 3,
-    WAITING_CLOSE    = 4
-  };
   // Pass any value in case of Windows, because in Windows
   // we are not using state.
   void WatchSocket(WaitState state);
@@ -110,12 +111,12 @@
   base::win::ObjectWatcher watcher_;
   HANDLE socket_event_;
 #elif defined(OS_POSIX)
-  WaitState wait_state_;
-  // The socket's libevent wrapper
-  MessageLoopForIO::FileDescriptorWatcher watcher_;
   // Called by MessagePumpLibevent when the socket is ready to do I/O
   virtual void OnFileCanReadWithoutBlocking(int fd);
   virtual void OnFileCanWriteWithoutBlocking(int fd);
+  WaitState wait_state_;
+  // The socket's libevent wrapper
+  MessageLoopForIO::FileDescriptorWatcher watcher_;
 #endif
 
   SOCKET socket_;
diff --git a/net/base/listen_socket_unittest.cc b/net/base/listen_socket_unittest.cc
index 23dd089..75beeec 100644
--- a/net/base/listen_socket_unittest.cc
+++ b/net/base/listen_socket_unittest.cc
@@ -19,8 +19,12 @@
 static const char kLoopback[] = "127.0.0.1";
 static const int kDefaultTimeoutMs = 5000;
 
-ListenSocket* ListenSocketTester::DoListen() {
-  return ListenSocket::Listen(kLoopback, kTestPort, this);
+ListenSocketTester::ListenSocketTester()
+    : thread_(NULL),
+      loop_(NULL),
+      server_(NULL),
+      connection_(NULL),
+      cv_(&lock_) {
 }
 
 void ListenSocketTester::SetUp() {
@@ -73,13 +77,13 @@
 }
 
 void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) {
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
   queue_.push_back(action);
   cv_.Broadcast();
 }
 
 void ListenSocketTester::NextAction() {
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
   while (queue_.empty())
     cv_.Wait();
   last_action_ = queue_.front();
@@ -121,36 +125,6 @@
   ReportAction(ListenSocketTestAction(ACTION_SEND));
 }
 
-void ListenSocketTester::DidAccept(ListenSocket *server,
-                                   ListenSocket *connection) {
-  connection_ = connection;
-  connection_->AddRef();
-  ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
-}
-
-void ListenSocketTester::DidRead(ListenSocket *connection,
-                                 const char* data,
-                                 int len) {
-  std::string str(data, len);
-  ReportAction(ListenSocketTestAction(ACTION_READ, str));
-}
-
-void ListenSocketTester::DidClose(ListenSocket *sock) {
-  ReportAction(ListenSocketTestAction(ACTION_CLOSE));
-}
-
-bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
-  int len = static_cast<int>(str.length());
-  int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
-  if (send_len == SOCKET_ERROR) {
-    LOG(ERROR) << "send failed: " << errno;
-    return false;
-  } else if (send_len != len) {
-    return false;
-  }
-  return true;
-}
-
 void ListenSocketTester::TestClientSend() {
   ASSERT_TRUE(Send(test_socket_, kHelloWorld));
   NextAction();
@@ -200,6 +174,42 @@
   ASSERT_STREQ(buf, kHelloWorld);
 }
 
+bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
+  int len = static_cast<int>(str.length());
+  int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
+  if (send_len == SOCKET_ERROR) {
+    LOG(ERROR) << "send failed: " << errno;
+    return false;
+  } else if (send_len != len) {
+    return false;
+  }
+  return true;
+}
+
+void ListenSocketTester::DidAccept(ListenSocket *server,
+                                   ListenSocket *connection) {
+  connection_ = connection;
+  connection_->AddRef();
+  ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
+}
+
+void ListenSocketTester::DidRead(ListenSocket *connection,
+                                 const char* data,
+                                 int len) {
+  std::string str(data, len);
+  ReportAction(ListenSocketTestAction(ACTION_READ, str));
+}
+
+void ListenSocketTester::DidClose(ListenSocket *sock) {
+  ReportAction(ListenSocketTestAction(ACTION_CLOSE));
+}
+
+ListenSocketTester::~ListenSocketTester() {}
+
+ListenSocket* ListenSocketTester::DoListen() {
+  return ListenSocket::Listen(kLoopback, kTestPort, this);
+}
+
 
 class ListenSocketTest: public PlatformTest {
  public:
diff --git a/net/base/listen_socket_unittest.h b/net/base/listen_socket_unittest.h
index f283cb0..f54fc31 100644
--- a/net/base/listen_socket_unittest.h
+++ b/net/base/listen_socket_unittest.h
@@ -68,24 +68,11 @@
     public ListenSocket::ListenSocketDelegate,
     public base::RefCountedThreadSafe<ListenSocketTester> {
 
- protected:
-  friend class base::RefCountedThreadSafe<ListenSocketTester>;
-
-  virtual ~ListenSocketTester() {}
-
-  virtual ListenSocket* DoListen();
-
  public:
-  ListenSocketTester()
-      : thread_(NULL),
-        loop_(NULL),
-        server_(NULL),
-        connection_(NULL),
-        cv_(&lock_) {
-  }
+  ListenSocketTester();
 
-  virtual void SetUp();
-  virtual void TearDown();
+  void SetUp();
+  void TearDown();
 
   void ReportAction(const ListenSocketTestAction& action);
   void NextAction();
@@ -96,10 +83,6 @@
   void Shutdown();
   void Listen();
   void SendFromTester();
-  virtual void DidAccept(ListenSocket *server, ListenSocket *connection);
-  virtual void DidRead(ListenSocket *connection, const char* data, int len);
-  virtual void DidClose(ListenSocket *sock);
-  virtual bool Send(SOCKET sock, const std::string& str);
   // verify the send/read from client to server
   void TestClientSend();
   // verify send/read of a longer string
@@ -107,6 +90,13 @@
   // verify a send/read from server to client
   void TestServerSend();
 
+  virtual bool Send(SOCKET sock, const std::string& str);
+
+  // ListenSocket::ListenSocketDelegate:
+  virtual void DidAccept(ListenSocket *server, ListenSocket *connection);
+  virtual void DidRead(ListenSocket *connection, const char* data, int len);
+  virtual void DidClose(ListenSocket *sock);
+
   scoped_ptr<base::Thread> thread_;
   MessageLoopForIO* loop_;
   ListenSocket* server_;
@@ -119,6 +109,13 @@
   base::Lock lock_;  // protects |queue_| and wraps |cv_|
   base::ConditionVariable cv_;
   std::deque<ListenSocketTestAction> queue_;
+
+ protected:
+  friend class base::RefCountedThreadSafe<ListenSocketTester>;
+
+  virtual ~ListenSocketTester();
+
+  virtual ListenSocket* DoListen();
 };
 
 #endif  // NET_BASE_LISTEN_SOCKET_UNITTEST_H_
diff --git a/net/base/mapped_host_resolver.h b/net/base/mapped_host_resolver.h
index 4a94fba..0f84f6a 100644
--- a/net/base/mapped_host_resolver.h
+++ b/net/base/mapped_host_resolver.h
@@ -25,17 +25,6 @@
   explicit MappedHostResolver(HostResolver* impl);
   virtual ~MappedHostResolver();
 
-  // HostResolver methods:
-  virtual int Resolve(const RequestInfo& info,
-                      AddressList* addresses,
-                      CompletionCallback* callback,
-                      RequestHandle* out_req,
-                      const BoundNetLog& net_log);
-  virtual void CancelRequest(RequestHandle req);
-  virtual void AddObserver(Observer* observer);
-  virtual void RemoveObserver(Observer* observer);
-  virtual HostResolverImpl* GetAsHostResolverImpl();
-
   // Adds a rule to this mapper. The format of the rule can be one of:
   //
   //   "MAP" <hostname_pattern> <replacement_host> [":" <replacement_port>]
@@ -53,6 +42,17 @@
     rules_.SetRulesFromString(rules_string);
   }
 
+  // HostResolver methods:
+  virtual int Resolve(const RequestInfo& info,
+                      AddressList* addresses,
+                      CompletionCallback* callback,
+                      RequestHandle* out_req,
+                      const BoundNetLog& net_log);
+  virtual void CancelRequest(RequestHandle req);
+  virtual void AddObserver(Observer* observer);
+  virtual void RemoveObserver(Observer* observer);
+  virtual HostResolverImpl* GetAsHostResolverImpl();
+
  private:
   scoped_ptr<HostResolver> impl_;
 
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index 1a52b99..bd16462 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -146,6 +146,8 @@
   MAGIC_NUMBER("image/tiff", "II*")
   MAGIC_NUMBER("image/tiff", "MM\x00*")
   MAGIC_NUMBER("audio/mpeg", "ID3")
+  MAGIC_NUMBER("image/webp", "RIFF....WEBPVP8 ")
+  MAGIC_NUMBER("video/webm", "\x1A\x45\xDF\xA3")
   // TODO(abarth): we don't handle partial byte matches yet
   // MAGIC_NUMBER("video/mpeg", "\x00\x00\x01\xB")
   // MAGIC_NUMBER("audio/mpeg", "\xFF\xE")
@@ -215,6 +217,19 @@
   return counter;
 }
 
+// Compare content header to a magic number where magic_entry can contain '.'
+// for single character of anything, allowing some bytes to be skipped.
+static bool MagicCmp(const char* magic_entry, const char* content, size_t len) {
+  while (len) {
+    if ((*magic_entry != '.') && (*magic_entry != *content))
+      return false;
+    ++magic_entry;
+    ++content;
+    --len;
+  }
+  return true;
+}
+
 static bool MatchMagicNumber(const char* content, size_t size,
                              const MagicNumber* magic_entry,
                              std::string* result) {
@@ -239,7 +254,7 @@
     }
   } else {
     if (size >= len)
-      match = (memcmp(magic_entry->magic, content, len) == 0);
+      match = MagicCmp(magic_entry->magic, content, len);
   }
 
   if (match) {
@@ -251,7 +266,8 @@
 
 static bool CheckForMagicNumbers(const char* content, size_t size,
                                  const MagicNumber* magic, size_t magic_len,
-                                 base::Histogram* counter, std::string* result) {
+                                 base::Histogram* counter,
+                                 std::string* result) {
   for (size_t i = 0; i < magic_len; ++i) {
     if (MatchMagicNumber(content, size, &(magic[i]), result)) {
       if (counter) counter->Add(static_cast<int>(i));
diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc
index a1817a2..dfce49f 100644
--- a/net/base/mock_host_resolver.cc
+++ b/net/base/mock_host_resolver.cc
@@ -45,37 +45,8 @@
 
 }  // namespace
 
-MockHostResolverBase::MockHostResolverBase(bool use_caching)
-    : use_caching_(use_caching) {
-  Reset(NULL);
-}
-
 MockHostResolverBase::~MockHostResolverBase() {}
 
-int MockHostResolverBase::Resolve(const RequestInfo& info,
-                                  AddressList* addresses,
-                                  CompletionCallback* callback,
-                                  RequestHandle* out_req,
-                                  const BoundNetLog& net_log) {
-  if (synchronous_mode_) {
-    callback = NULL;
-    out_req = NULL;
-  }
-  return impl_->Resolve(info, addresses, callback, out_req, net_log);
-}
-
-void MockHostResolverBase::CancelRequest(RequestHandle req) {
-  impl_->CancelRequest(req);
-}
-
-void MockHostResolverBase::AddObserver(Observer* observer) {
-  impl_->AddObserver(observer);
-}
-
-void MockHostResolverBase::RemoveObserver(Observer* observer) {
-  impl_->RemoveObserver(observer);
-}
-
 void MockHostResolverBase::Reset(HostResolverProc* interceptor) {
   synchronous_mode_ = false;
 
@@ -107,6 +78,35 @@
   impl_.reset(new HostResolverImpl(proc, cache, 50u, NULL));
 }
 
+int MockHostResolverBase::Resolve(const RequestInfo& info,
+                                  AddressList* addresses,
+                                  CompletionCallback* callback,
+                                  RequestHandle* out_req,
+                                  const BoundNetLog& net_log) {
+  if (synchronous_mode_) {
+    callback = NULL;
+    out_req = NULL;
+  }
+  return impl_->Resolve(info, addresses, callback, out_req, net_log);
+}
+
+void MockHostResolverBase::CancelRequest(RequestHandle req) {
+  impl_->CancelRequest(req);
+}
+
+void MockHostResolverBase::AddObserver(Observer* observer) {
+  impl_->AddObserver(observer);
+}
+
+void MockHostResolverBase::RemoveObserver(Observer* observer) {
+  impl_->RemoveObserver(observer);
+}
+
+MockHostResolverBase::MockHostResolverBase(bool use_caching)
+    : use_caching_(use_caching) {
+  Reset(NULL);
+}
+
 //-----------------------------------------------------------------------------
 
 struct RuleBasedHostResolverProc::Rule {
@@ -144,9 +144,6 @@
     : HostResolverProc(previous) {
 }
 
-RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
-}
-
 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
                                         const std::string& replacement) {
   AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
@@ -258,6 +255,9 @@
                               host_resolver_flags, addrlist, os_error);
 }
 
+RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
+}
+
 //-----------------------------------------------------------------------------
 
 WaitingHostResolverProc::WaitingHostResolverProc(HostResolverProc* previous)
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 8f94c4a..ab4b45f 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -220,6 +220,15 @@
 // body might include a description of why the request failed.
 NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140)
 
+// We were unable to sign the CertificateVerify data of an SSL client auth
+// handshake with the client certificate's private key.
+//
+// Possible causes for this include the user implicitly or explicitly
+// denying access to the private key, the private key may not be valid for
+// signing, the key may be relying on a cached handle which is no longer
+// valid, or the CSP won't allow arbitrary data to be signed.
+NET_ERROR(SSL_CLIENT_AUTH_SIGNATURE_FAILED, -141)
+
 // Certificate error codes
 //
 // The values of certificate error codes must be consecutive.
diff --git a/net/base/net_log.cc b/net/base/net_log.cc
index 0f1bac4..4484a8a 100644
--- a/net/base/net_log.cc
+++ b/net/base/net_log.cc
@@ -127,20 +127,6 @@
   }
 }
 
-NetLog::LogLevel BoundNetLog::GetLogLevel() const {
-  if (net_log_)
-    return net_log_->GetLogLevel();
-  return NetLog::LOG_BASIC;
-}
-
-bool BoundNetLog::IsLoggingBytes() const {
-  return GetLogLevel() == NetLog::LOG_ALL;
-}
-
-bool BoundNetLog::IsLoggingAllEvents() const {
-  return GetLogLevel() <= NetLog::LOG_ALL_BUT_BYTES;
-}
-
 void BoundNetLog::AddEvent(
     NetLog::EventType event_type,
     const scoped_refptr<NetLog::EventParameters>& params) const {
@@ -171,6 +157,20 @@
   }
 }
 
+NetLog::LogLevel BoundNetLog::GetLogLevel() const {
+  if (net_log_)
+    return net_log_->GetLogLevel();
+  return NetLog::LOG_BASIC;
+}
+
+bool BoundNetLog::IsLoggingBytes() const {
+  return GetLogLevel() == NetLog::LOG_ALL;
+}
+
+bool BoundNetLog::IsLoggingAllEvents() const {
+  return GetLogLevel() <= NetLog::LOG_ALL_BUT_BYTES;
+}
+
 // static
 BoundNetLog BoundNetLog::Make(NetLog* net_log,
                               NetLog::SourceType source_type) {
diff --git a/net/base/net_log.h b/net/base/net_log.h
index 1d37129..eb88038 100644
--- a/net/base/net_log.h
+++ b/net/base/net_log.h
@@ -34,8 +34,6 @@
 // TODO(eroman): Remove the 'const' qualitifer from the BoundNetLog methods.
 // TODO(eroman): Start a new Source each time net::URLRequest redirects
 //               (simpler to reason about each as a separate entity).
-// TODO(mmenke): Replace EndEvent calls with EndEventWithNetErrorCode, where
-//               appropriate.
 
 class NetLog {
  public:
diff --git a/net/base/net_test_suite.h b/net/base/net_test_suite.h
index 8ebc4e7..274d067 100644
--- a/net/base/net_test_suite.h
+++ b/net/base/net_test_suite.h
@@ -6,53 +6,33 @@
 #define NET_BASE_NET_TEST_SUITE_H_
 #pragma once
 
-#include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/test/test_suite.h"
 #include "build/build_config.h"
 #include "net/base/mock_host_resolver.h"
-#if defined(USE_NSS)
-#include "net/ocsp/nss_ocsp.h"
-#endif
+
+class MessageLoop;
+
+namespace net {
+class NetworkChangeNotifier;
+}
 
 class NetTestSuite : public base::TestSuite {
  public:
-  NetTestSuite(int argc, char** argv) : TestSuite(argc, argv) {
-  }
+  NetTestSuite(int argc, char** argv);
+  virtual ~NetTestSuite();
 
-  virtual void Initialize() {
-    TestSuite::Initialize();
-    InitializeTestThread();
-  }
+  virtual void Initialize();
+
+  virtual void Shutdown();
+
+ protected:
 
   // Called from within Initialize(), but separate so that derived classes
   // can initialize the NetTestSuite instance only and not
   // TestSuite::Initialize().  TestSuite::Initialize() performs some global
   // initialization that can only be done once.
-  void InitializeTestThread() {
-    network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock());
-
-    host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL);
-    scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
-    // In case any attempts are made to resolve host names, force them all to
-    // be mapped to localhost.  This prevents DNS queries from being sent in
-    // the process of running these unit tests.
-    host_resolver_proc_->AddRule("*", "127.0.0.1");
-
-    message_loop_.reset(new MessageLoopForIO());
-  }
-
-  virtual void Shutdown() {
-#if defined(USE_NSS)
-    net::ShutdownOCSP();
-#endif
-
-    // We want to destroy this here before the TestSuite continues to tear down
-    // the environment.
-    message_loop_.reset();
-
-    TestSuite::Shutdown();
-  }
+  void InitializeTestThread();
 
  private:
   scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index 1562951..b82264c 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -4,8 +4,6 @@
 
 #include "net/base/net_util.h"
 
-#include <algorithm>
-#include <map>
 #include <unicode/regex.h>
 #include <unicode/ucnv.h>
 #include <unicode/uidna.h>
@@ -13,13 +11,14 @@
 #include <unicode/uniset.h>
 #include <unicode/uscript.h>
 #include <unicode/uset.h>
+#include <algorithm>
+#include <map>
 
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
 #include <winsock2.h>
-#include <ws2tcpip.h>
 #include <wspiapi.h>  // Needed for Win2k compat.
 #elif defined(OS_POSIX)
 #include <fcntl.h>
@@ -29,10 +28,13 @@
 #include <netdb.h>
 #include <net/if.h>
 #include <netinet/in.h>
+<<<<<<< HEAD
 #if defined(__BIONIC__) && defined(ANDROID)
 #include <netinet/in6.h>
 #endif
 #include <sys/socket.h>
+=======
+>>>>>>> chromium.org at r11.0.672.0
 #endif
 
 #include "base/base64.h"
@@ -43,7 +45,6 @@
 #include "base/i18n/icu_string_conversions.h"
 #include "base/i18n/time_formatting.h"
 #include "base/json/string_escape.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
@@ -56,6 +57,7 @@
 #include "base/string_tokenizer.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#include "base/synchronization/lock.h"
 #include "base/sys_string_conversions.h"
 #include "base/time.h"
 #include "base/utf_offset_string_conversions.h"
@@ -152,7 +154,7 @@
   6668, // Alternate IRC [Apple addition]
   6669, // Alternate IRC [Apple addition]
   0xFFFF, // Used to block all invalid port numbers (see
-          // third_party/WebKit/WebCore/platform/KURLGoogle.cpp, port())
+          // third_party/WebKit/Source/WebCore/platform/KURLGoogle.cpp, port())
 };
 
 // FTP overrides the following restricted ports.
@@ -555,7 +557,7 @@
   map.insert(std::make_pair(lang, lang_set));
 }
 
-static Lock lang_set_lock;
+static base::Lock lang_set_lock;
 
 // Returns true if all the characters in component_characters are used by
 // the language |lang|.
@@ -565,7 +567,7 @@
   icu::UnicodeSet* lang_set;
   // We're called from both the UI thread and the history thread.
   {
-    AutoLock lock(lang_set_lock);
+    base::AutoLock lock(lang_set_lock);
     if (!GetExemplarSetForLang(lang, &lang_set)) {
       UErrorCode status = U_ZERO_ERROR;
       ULocaleData* uld = ulocdata_open(lang.c_str(), &status);
@@ -903,10 +905,9 @@
 
   // Copy everything before the username (the scheme and the separators.)
   // These are ASCII.
-  std::copy(spec.begin(),
+  url_string.insert(url_string.end(), spec.begin(),
       spec.begin() + parsed.CountCharactersBefore(url_parse::Parsed::USERNAME,
-                                                  true),
-      std::back_inserter(url_string));
+                                                  true));
 
   const wchar_t kHTTP[] = L"http://";
   const char kFTP[] = "ftp.";
@@ -975,8 +976,9 @@
   if (parsed.port.is_nonempty()) {
     url_string.push_back(':');
     new_parsed->port.begin = url_string.length();
-    std::copy(spec.begin() + parsed.port.begin,
-              spec.begin() + parsed.port.end(), std::back_inserter(url_string));
+    url_string.insert(url_string.end(),
+                      spec.begin() + parsed.port.begin,
+                      spec.begin() + parsed.port.end());
     new_parsed->port.len = url_string.length() - new_parsed->port.begin;
   } else {
     new_parsed->port.reset();
@@ -1198,7 +1200,7 @@
   // Convert the ASCII input to a wide string for ICU.
   string16 input16;
   input16.reserve(host_len);
-  std::copy(host, host + host_len, std::back_inserter(input16));
+  input16.insert(input16.end(), host, host + host_len);
 
   string16 out16;
   size_t output_offset = offset_for_adjustment ?
@@ -1382,38 +1384,37 @@
       text.substr(www.length()) : text;
 }
 
-FilePath GetSuggestedFilename(const GURL& url,
+string16 GetSuggestedFilename(const GURL& url,
                               const std::string& content_disposition,
                               const std::string& referrer_charset,
-                              const FilePath& default_name) {
+                              const string16& default_name) {
+  // TODO: this function to be updated to match the httpbis recommendations.
+  // Talk to abarth for the latest news.
+
   // We don't translate this fallback string, "download". If localization is
   // needed, the caller should provide localized fallback default_name.
-  static const FilePath::CharType kFinalFallbackName[] =
-      FILE_PATH_LITERAL("download");
+  static const char* kFinalFallbackName = "download";
 
   // about: and data: URLs don't have file names, but esp. data: URLs may
   // contain parts that look like ones (i.e., contain a slash).
   // Therefore we don't attempt to divine a file name out of them.
   if (url.SchemeIs("about") || url.SchemeIs("data")) {
-    return default_name.empty() ? FilePath(kFinalFallbackName) : default_name;
+    return default_name.empty() ? ASCIIToUTF16(kFinalFallbackName)
+                                : default_name;
   }
 
-  const std::string filename_from_cd = GetFileNameFromCD(content_disposition,
-                                                         referrer_charset);
-#if defined(OS_WIN)
-  FilePath::StringType filename = UTF8ToWide(filename_from_cd);
-#elif defined(OS_POSIX)
-  FilePath::StringType filename = filename_from_cd;
-#endif
+  std::string filename = GetFileNameFromCD(content_disposition,
+                                           referrer_charset);
 
   if (!filename.empty()) {
-    // Remove any path information the server may have sent, take the name
-    // only.
-    filename = FilePath(filename).BaseName().value();
+    // Replace any path information the server may have sent, by changing
+    // path separators with underscores.
+    ReplaceSubstringsAfterOffset(&filename, 0, "/", "_");
+    ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_");
 
     // Next, remove "." from the beginning and end of the file name to avoid
     // tricks with hidden files, "..", and "."
-    TrimString(filename, FILE_PATH_LITERAL("."), &filename);
+    TrimString(filename, ".", &filename);
   }
   if (filename.empty()) {
     if (url.is_valid()) {
@@ -1431,18 +1432,14 @@
                    &decoded_filename);
       }
 
-#if defined(OS_WIN)
-      filename = UTF8ToWide(decoded_filename);
-#elif defined(OS_POSIX)
       filename = decoded_filename;
-#endif
     }
   }
 
 #if defined(OS_WIN)
   { // Handle CreateFile() stripping trailing dots and spaces on filenames
     // http://support.microsoft.com/kb/115827
-    std::string::size_type pos = filename.find_last_not_of(L" .");
+    std::string::size_type pos = filename.find_last_not_of(" .");
     if (pos == std::string::npos)
       filename.resize(0);
     else
@@ -1450,30 +1447,32 @@
   }
 #endif
   // Trim '.' once more.
-  TrimString(filename, FILE_PATH_LITERAL("."), &filename);
+  TrimString(filename, ".", &filename);
 
   // If there's no filename or it gets trimed to be empty, use
   // the URL hostname or default_name
   if (filename.empty()) {
     if (!default_name.empty()) {
-      filename = default_name.value();
+      return default_name;
     } else if (url.is_valid()) {
       // Some schemes (e.g. file) do not have a hostname. Even though it's
       // not likely to reach here, let's hardcode the last fallback name.
       // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451)
-      filename = url.host().empty() ? kFinalFallbackName :
-#if defined(OS_WIN)
-          UTF8ToWide(url.host());
-#elif defined(OS_POSIX)
-          url.host();
-#endif
+      filename = url.host().empty() ? kFinalFallbackName : url.host();
     } else {
       NOTREACHED();
     }
   }
 
-  file_util::ReplaceIllegalCharactersInPath(&filename, '-');
-  return FilePath(filename);
+#if defined(OS_WIN)
+  string16 path = UTF8ToUTF16(filename);
+  file_util::ReplaceIllegalCharactersInPath(&path, '-');
+  return path;
+#else
+  std::string path = filename;
+  file_util::ReplaceIllegalCharactersInPath(&path, '-');
+  return UTF8ToUTF16(path);
+#endif
 }
 
 bool IsPortAllowedByDefault(int port) {
@@ -1586,6 +1585,11 @@
 }
 
 std::string NetAddressToString(const struct addrinfo* net_address) {
+  return NetAddressToString(net_address->ai_addr, net_address->ai_addrlen);
+}
+
+std::string NetAddressToString(const struct sockaddr* net_address,
+                               socklen_t address_len) {
 #if defined(OS_WIN)
   EnsureWinsockInit();
 #endif
@@ -1593,22 +1597,28 @@
   // This buffer is large enough to fit the biggest IPv6 string.
   char buffer[INET6_ADDRSTRLEN];
 
-  int result = getnameinfo(net_address->ai_addr,
-      net_address->ai_addrlen, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST);
+  int result = getnameinfo(net_address, address_len, buffer, sizeof(buffer),
+                           NULL, 0, NI_NUMERICHOST);
 
   if (result != 0) {
-    DVLOG(1) << "getnameinfo() failed with " << result;
+    DVLOG(1) << "getnameinfo() failed with " << result << ": "
+             << gai_strerror(result);
     buffer[0] = '\0';
   }
   return std::string(buffer);
 }
 
 std::string NetAddressToStringWithPort(const struct addrinfo* net_address) {
-  std::string ip_address_string = NetAddressToString(net_address);
+  return NetAddressToStringWithPort(
+      net_address->ai_addr, net_address->ai_addrlen);
+}
+std::string NetAddressToStringWithPort(const struct sockaddr* net_address,
+                                       socklen_t address_len) {
+  std::string ip_address_string = NetAddressToString(net_address, address_len);
   if (ip_address_string.empty())
     return std::string();  // Failed.
 
-  int port = GetPortFromAddrinfo(net_address);
+  int port = GetPortFromSockaddr(net_address, address_len);
 
   if (ip_address_string.find(':') != std::string::npos) {
     // Surround with square brackets to avoid ambiguity.
@@ -2052,17 +2062,38 @@
 }
 
 // Returns the port field of the sockaddr in |info|.
-uint16* GetPortFieldFromAddrinfo(const struct addrinfo* info) {
+uint16* GetPortFieldFromAddrinfo(struct addrinfo* info) {
+  const struct addrinfo* const_info = info;
+  const uint16* port_field = GetPortFieldFromAddrinfo(const_info);
+  return const_cast<uint16*>(port_field);
+}
+
+const uint16* GetPortFieldFromAddrinfo(const struct addrinfo* info) {
   DCHECK(info);
-  if (info->ai_family == AF_INET) {
-    DCHECK_EQ(sizeof(sockaddr_in), static_cast<size_t>(info->ai_addrlen));
-    struct sockaddr_in* sockaddr =
-        reinterpret_cast<struct sockaddr_in*>(info->ai_addr);
+  const struct sockaddr* address = info->ai_addr;
+  DCHECK(address);
+  DCHECK_EQ(info->ai_family, address->sa_family);
+  return GetPortFieldFromSockaddr(address, info->ai_addrlen);
+}
+
+int GetPortFromAddrinfo(const struct addrinfo* info) {
+  const uint16* port_field = GetPortFieldFromAddrinfo(info);
+  if (!port_field)
+    return -1;
+  return ntohs(*port_field);
+}
+
+const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address,
+                                       socklen_t address_len) {
+  if (address->sa_family == AF_INET) {
+    DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len));
+    const struct sockaddr_in* sockaddr =
+        reinterpret_cast<const struct sockaddr_in*>(address);
     return &sockaddr->sin_port;
-  } else if (info->ai_family == AF_INET6) {
-    DCHECK_EQ(sizeof(sockaddr_in6), static_cast<size_t>(info->ai_addrlen));
-    struct sockaddr_in6* sockaddr =
-        reinterpret_cast<struct sockaddr_in6*>(info->ai_addr);
+  } else if (address->sa_family == AF_INET6) {
+    DCHECK_LE(sizeof(sockaddr_in6), static_cast<size_t>(address_len));
+    const struct sockaddr_in6* sockaddr =
+        reinterpret_cast<const struct sockaddr_in6*>(address);
     return &sockaddr->sin6_port;
   } else {
     NOTREACHED();
@@ -2070,8 +2101,8 @@
   }
 }
 
-int GetPortFromAddrinfo(const struct addrinfo* info) {
-  uint16* port_field = GetPortFieldFromAddrinfo(info);
+int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) {
+  const uint16* port_field = GetPortFieldFromSockaddr(address, address_len);
   if (!port_field)
     return -1;
   return ntohs(*port_field);
diff --git a/net/base/net_util.h b/net/base/net_util.h
index bb145e0..935eab6 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -8,8 +8,11 @@
 
 #include "build/build_config.h"
 
-#ifdef OS_WIN
+#if defined(OS_WIN)
 #include <windows.h>
+#include <ws2tcpip.h>
+#elif defined(OS_POSIX)
+#include <sys/socket.h>
 #endif
 
 #include <string>
@@ -107,10 +110,14 @@
 // Returns the string representation of an address, like "192.168.0.1".
 // Returns empty string on failure.
 std::string NetAddressToString(const struct addrinfo* net_address);
+std::string NetAddressToString(const struct sockaddr* net_address,
+                               socklen_t address_len);
 
 // Same as NetAddressToString, but additionally includes the port number. For
 // example: "192.168.0.1:99" or "[::1]:80".
 std::string NetAddressToStringWithPort(const struct addrinfo* net_address);
+std::string NetAddressToStringWithPort(const struct sockaddr* net_address,
+                                       socklen_t address_len);
 
 // Returns the hostname of the current system. Returns empty string on failure.
 std::string GetHostName();
@@ -259,10 +266,10 @@
 // file:///). referrer_charset is used as one of charsets
 // to interpret a raw 8bit string in C-D header (after interpreting
 // as UTF-8 fails). See the comment for GetFilenameFromCD for more details.
-FilePath GetSuggestedFilename(const GURL& url,
+string16 GetSuggestedFilename(const GURL& url,
                               const std::string& content_disposition,
                               const std::string& referrer_charset,
-                              const FilePath& default_name);
+                              const string16& default_name);
 
 // Checks the given port against a list of ports which are restricted by
 // default.  Returns true if the port is allowed, false if it is restricted.
@@ -404,11 +411,18 @@
                            size_t prefix_length_in_bits);
 
 // Returns the port field of the sockaddr in |info|.
-uint16* GetPortFieldFromAddrinfo(const struct addrinfo* info);
+const uint16* GetPortFieldFromAddrinfo(const struct addrinfo* info);
+uint16* GetPortFieldFromAddrinfo(struct addrinfo* info);
 
 // Returns the value of |info's| port (in host byte ordering).
 int GetPortFromAddrinfo(const struct addrinfo* info);
 
+// Same except for struct sockaddr.
+const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address,
+                                       socklen_t address_len);
+int GetPortFromSockaddr(const struct sockaddr* address,
+                        socklen_t address_len);
+
 }  // namespace net
 
 #endif  // NET_BASE_NET_UTIL_H_
diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc
index 77d3a00..ebb3574 100644
--- a/net/base/net_util_unittest.cc
+++ b/net/base/net_util_unittest.cc
@@ -1098,7 +1098,12 @@
      "Content-disposition: attachment; filename=\"../test.html\"",
      "",
      L"",
-     L"test.html"},
+     L"_test.html"},
+    {"http://www.google.com/",
+     "Content-disposition: attachment; filename=\"..\\test.html\"",
+     "",
+     L"",
+     L"_test.html"},
     {"http://www.google.com/",
      "Content-disposition: attachment; filename=\"..\"",
      "",
@@ -1214,21 +1219,12 @@
 #endif
   };
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
-#if defined(OS_WIN)
-    FilePath default_name(test_cases[i].default_filename);
-#else
-    FilePath default_name(
-        base::SysWideToNativeMB(test_cases[i].default_filename));
-#endif
-    FilePath filename = net::GetSuggestedFilename(
+    std::wstring default_name = test_cases[i].default_filename;
+    string16 filename = net::GetSuggestedFilename(
         GURL(test_cases[i].url), test_cases[i].content_disp_header,
-        test_cases[i].referrer_charset, default_name);
-#if defined(OS_WIN)
-    EXPECT_EQ(std::wstring(test_cases[i].expected_filename), filename.value())
-#else
-    EXPECT_EQ(base::SysWideToNativeMB(test_cases[i].expected_filename),
-              filename.value())
-#endif
+        test_cases[i].referrer_charset, WideToUTF16(default_name));
+    EXPECT_EQ(std::wstring(test_cases[i].expected_filename),
+              UTF16ToWide(filename))
       << "Iteration " << i << ": " << test_cases[i].url;
   }
 }
diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc
index a6d37c1..dac93a9 100644
--- a/net/base/net_util_win.cc
+++ b/net/base/net_util_win.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "net/base/net_util.h"
 
 #include "base/file_path.h"
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc
index afec17d..bd3528a 100644
--- a/net/base/network_config_watcher_mac.cc
+++ b/net/base/network_config_watcher_mac.cc
@@ -10,6 +10,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/mac/scoped_cftyperef.h"
 
 namespace net {
@@ -54,10 +55,18 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}
 
 NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() {
+  // Allow IO because Stop() calls PlatformThread::Join(), which is a blocking
+  // operation. This is expected during shutdown.
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
   Stop();
 }
 
 void NetworkConfigWatcherMacThread::Init() {
+  // Disallow IO to make sure NetworkConfigWatcherMacThread's helper thread does
+  // not perform blocking operations.
+  base::ThreadRestrictions::SetIOAllowed(false);
+
   // TODO(willchan): Look to see if there's a better signal for when it's ok to
   // initialize this, rather than just delaying it by a fixed time.
   const int kInitializationDelayMS = 1000;
diff --git a/net/base/openssl_memory_private_key_store.cc b/net/base/openssl_memory_private_key_store.cc
index 6b65dbe..5572b67 100644
--- a/net/base/openssl_memory_private_key_store.cc
+++ b/net/base/openssl_memory_private_key_store.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/openssl_util.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 #include "net/base/x509_certificate.h"
 
 namespace net {
@@ -26,7 +27,7 @@
   }
 
   virtual ~OpenSSLMemoryKeyStore() {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     for (std::vector<EVP_PKEY*>::iterator it = keys_.begin();
          it != keys_.end(); ++it) {
       EVP_PKEY_free(*it);
@@ -35,13 +36,13 @@
 
   virtual bool StorePrivateKey(const GURL& url, EVP_PKEY* pkey) {
     CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     keys_.push_back(pkey);
     return true;
   }
 
   virtual EVP_PKEY* FetchPrivateKey(EVP_PKEY* pkey) {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     for (std::vector<EVP_PKEY*>::iterator it = keys_.begin();
          it != keys_.end(); ++it) {
       if (EVP_PKEY_cmp(*it, pkey) == 1)
@@ -52,7 +53,7 @@
 
  private:
   std::vector<EVP_PKEY*> keys_;
-  Lock lock_;
+  base::Lock lock_;
 
   DISALLOW_COPY_AND_ASSIGN(OpenSSLMemoryKeyStore);
 };
diff --git a/net/base/platform_mime_util_win.cc b/net/base/platform_mime_util_win.cc
index b93008b..f9a9391 100644
--- a/net/base/platform_mime_util_win.cc
+++ b/net/base/platform_mime_util_win.cc
@@ -28,8 +28,8 @@
 bool PlatformMimeUtil::GetPreferredExtensionForMimeType(
     const std::string& mime_type, FilePath::StringType* ext) const {
   std::wstring key(L"MIME\\Database\\Content Type\\" + UTF8ToWide(mime_type));
-  if (!base::win::RegKey(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ).ReadValue(
-          L"Extension", ext)) {
+  if (base::win::RegKey(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ).ReadValue(
+          L"Extension", ext) != ERROR_SUCCESS) {
     return false;
   }
   // Strip off the leading dot, this should always be the case.
diff --git a/net/base/registry_controlled_domain.cc b/net/base/registry_controlled_domain.cc
index 88eccd0..1ee8874 100644
--- a/net/base/registry_controlled_domain.cc
+++ b/net/base/registry_controlled_domain.cc
@@ -51,12 +51,14 @@
 
 namespace net {
 
-static const int kExceptionRule = 1;
-static const int kWildcardRule = 2;
+namespace {
 
-RegistryControlledDomainService::RegistryControlledDomainService()
-    : find_domain_function_(Perfect_Hash::FindDomain) {
-}
+const int kExceptionRule = 1;
+const int kWildcardRule = 2;
+
+RegistryControlledDomainService* test_instance_;
+
+}  // namespace
 
 // static
 std::string RegistryControlledDomainService::GetDomainAndRegistry(
@@ -155,6 +157,34 @@
 }
 
 // static
+RegistryControlledDomainService* RegistryControlledDomainService::GetInstance()
+{
+  if (test_instance_)
+    return test_instance_;
+
+  return Singleton<RegistryControlledDomainService>::get();
+}
+
+RegistryControlledDomainService::RegistryControlledDomainService()
+    : find_domain_function_(Perfect_Hash::FindDomain) {
+}
+
+// static
+RegistryControlledDomainService* RegistryControlledDomainService::SetInstance(
+    RegistryControlledDomainService* instance) {
+  RegistryControlledDomainService* old_instance = test_instance_;
+  test_instance_ = instance;
+  return old_instance;
+}
+
+// static
+void RegistryControlledDomainService::UseFindDomainFunction(
+    FindDomainPtr function) {
+  RegistryControlledDomainService* instance = GetInstance();
+  instance->find_domain_function_ = function;
+}
+
+// static
 std::string RegistryControlledDomainService::GetDomainAndRegistryImpl(
     const std::string& host) {
   DCHECK(!host.empty());
@@ -261,30 +291,4 @@
   return allow_unknown_registries ? (host.length() - curr_start) : 0;
 }
 
-static RegistryControlledDomainService* test_instance_;
-
-// static
-RegistryControlledDomainService* RegistryControlledDomainService::SetInstance(
-    RegistryControlledDomainService* instance) {
-  RegistryControlledDomainService* old_instance = test_instance_;
-  test_instance_ = instance;
-  return old_instance;
-}
-
-// static
-RegistryControlledDomainService* RegistryControlledDomainService::GetInstance()
-{
-  if (test_instance_)
-    return test_instance_;
-
-  return Singleton<RegistryControlledDomainService>::get();
-}
-
-// static
-void RegistryControlledDomainService::UseFindDomainFunction(
-    FindDomainPtr function) {
-  RegistryControlledDomainService* instance = GetInstance();
-  instance->find_domain_function_ = function;
-}
-
 }  // namespace net
diff --git a/net/base/sdch_filter.cc b/net/base/sdch_filter.cc
index cc9a1d6..2be75db 100644
--- a/net/base/sdch_filter.cc
+++ b/net/base/sdch_filter.cc
@@ -1,7 +1,9 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/base/sdch_filter.h"
+
 #include <limits.h>
 #include <ctype.h>
 #include <algorithm>
@@ -9,11 +11,12 @@
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
-#include "net/base/sdch_filter.h"
 #include "net/base/sdch_manager.h"
 
 #include "sdch/open-vcdiff/src/google/vcdecoder.h"
 
+namespace net {
+
 SdchFilter::SdchFilter(const FilterContext& filter_context)
     : Filter(filter_context),
       decoding_status_(DECODING_UNINITIALIZED),
@@ -383,3 +386,5 @@
   }
   return amount;
 }
+
+}  // namespace net
diff --git a/net/base/sdch_filter.h b/net/base/sdch_filter.h
index 963cf32..9eac007 100644
--- a/net/base/sdch_filter.h
+++ b/net/base/sdch_filter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,9 +22,11 @@
 #include "net/base/sdch_manager.h"
 
 namespace open_vcdiff {
-  class VCDiffStreamingDecoder;
+class VCDiffStreamingDecoder;
 }
 
+namespace net {
+
 class SdchFilter : public Filter {
  public:
   explicit SdchFilter(const FilterContext& filter_context);
@@ -115,4 +117,6 @@
   DISALLOW_COPY_AND_ASSIGN(SdchFilter);
 };
 
+}  // namespace net
+
 #endif  // NET_BASE_SDCH_FILTER_H_
diff --git a/net/base/sdch_filter_unittest.cc b/net/base/sdch_filter_unittest.cc
index 675a135..45ed6f0 100644
--- a/net/base/sdch_filter_unittest.cc
+++ b/net/base/sdch_filter_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,12 +17,14 @@
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "net/base/filter.h"
-#include "net/base/filter_unittest.h"
 #include "net/base/io_buffer.h"
+#include "net/base/mock_filter_context.h"
 #include "net/base/sdch_filter.h"
 #include "net/url_request/url_request_http_job.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace net {
+
 //------------------------------------------------------------------------------
 // Provide sample data and compression results with a sample VCDIFF dictionary.
 // Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary.
@@ -1404,3 +1406,5 @@
   EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url));
   EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url2));
 }
+
+}  // namespace net
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc
index 18976c9..4d99426 100644
--- a/net/base/sdch_manager.cc
+++ b/net/base/sdch_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -13,8 +13,7 @@
 #include "net/base/registry_controlled_domain.h"
 #include "net/url_request/url_request_http_job.h"
 
-using base::Time;
-using base::TimeDelta;
+namespace net {
 
 //------------------------------------------------------------------------------
 // static
@@ -28,16 +27,20 @@
 
 //------------------------------------------------------------------------------
 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text,
-    size_t offset, const std::string& client_hash, const GURL& gurl,
-    const std::string& domain, const std::string& path, const Time& expiration,
-    const std::set<int> ports)
-      : text_(dictionary_text, offset),
-        client_hash_(client_hash),
-        url_(gurl),
-        domain_(domain),
-        path_(path),
-        expiration_(expiration),
-        ports_(ports) {
+                                    size_t offset,
+                                    const std::string& client_hash,
+                                    const GURL& gurl,
+                                    const std::string& domain,
+                                    const std::string& path,
+                                    const base::Time& expiration,
+                                    const std::set<int>& ports)
+    : text_(dictionary_text, offset),
+      client_hash_(client_hash),
+      url_(gurl),
+      domain_(domain),
+      path_(path),
+      expiration_(expiration),
+      ports_(ports) {
 }
 
 SdchManager::Dictionary::~Dictionary() {
@@ -66,7 +69,7 @@
     return false;
   if (target_url.SchemeIsSecure())
     return false;
-  if (Time::Now() > expiration_)
+  if (base::Time::Now() > expiration_)
     return false;
   return true;
 }
@@ -77,7 +80,7 @@
 // static
 bool SdchManager::Dictionary::CanSet(const std::string& domain,
                                      const std::string& path,
-                                     const std::set<int> ports,
+                                     const std::set<int>& ports,
                                      const GURL& dictionary_url) {
   if (!SdchManager::Global()->IsInSupportedDomain(dictionary_url))
     return false;
@@ -370,7 +373,7 @@
 
   std::string domain, path;
   std::set<int> ports;
-  Time expiration(Time::Now() + TimeDelta::FromDays(30));
+  base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30));
 
   if (dictionary_text.empty()) {
     SdchErrorRecovery(DICTIONARY_HAS_NO_TEXT);
@@ -415,7 +418,7 @@
       } else if (name == "max-age") {
         int64 seconds;
         base::StringToInt64(value, &seconds);
-        expiration = Time::Now() + TimeDelta::FromSeconds(seconds);
+        expiration = base::Time::Now() + base::TimeDelta::FromSeconds(seconds);
       } else if (name == "port") {
         int port;
         base::StringToInt(value, &port);
@@ -543,3 +546,5 @@
     }
   }
 }
+
+}  // namespace net
diff --git a/net/base/sdch_manager.h b/net/base/sdch_manager.h
index d53be00..b37e4ad 100644
--- a/net/base/sdch_manager.h
+++ b/net/base/sdch_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -31,6 +31,8 @@
 #include "base/time.h"
 #include "googleurl/src/gurl.h"
 
+namespace net {
+
 //------------------------------------------------------------------------------
 // Create a public interface to help us load SDCH dictionaries.
 // The SdchManager class allows registration to support this interface.
@@ -49,6 +51,7 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(SdchFetcher);
 };
+
 //------------------------------------------------------------------------------
 
 class SdchManager {
@@ -171,10 +174,14 @@
     // Construct a vc-diff usable dictionary from the dictionary_text starting
     // at the given offset.  The supplied client_hash should be used to
     // advertise the dictionary's availability relative to the suppplied URL.
-    Dictionary(const std::string& dictionary_text, size_t offset,
-               const std::string& client_hash, const GURL& url,
-               const std::string& domain, const std::string& path,
-               const base::Time& expiration, const std::set<int> ports);
+    Dictionary(const std::string& dictionary_text,
+               size_t offset,
+               const std::string& client_hash,
+               const GURL& url,
+               const std::string& domain,
+               const std::string& path,
+               const base::Time& expiration,
+               const std::set<int>& ports);
     ~Dictionary();
 
     const GURL& url() const { return url_; }
@@ -187,7 +194,7 @@
     // Security methods to check if we can establish a new dictionary with the
     // given data, that arrived in response to get of dictionary_url.
     static bool CanSet(const std::string& domain, const std::string& path,
-                       const std::set<int> ports, const GURL& dictionary_url);
+                       const std::set<int>& ports, const GURL& dictionary_url);
 
     // Security method to check if we can use a dictionary to decompress a
     // target that arrived with a reference to this dictionary.
@@ -365,4 +372,6 @@
   DISALLOW_COPY_AND_ASSIGN(SdchManager);
 };
 
+}  // namespace net
+
 #endif  // NET_BASE_SDCH_MANAGER_H_
diff --git a/net/base/ssl_cert_request_info.cc b/net/base/ssl_cert_request_info.cc
index bb91632..b7728e5 100644
--- a/net/base/ssl_cert_request_info.cc
+++ b/net/base/ssl_cert_request_info.cc
@@ -11,6 +11,11 @@
 SSLCertRequestInfo::SSLCertRequestInfo() {
 }
 
+void SSLCertRequestInfo::Reset() {
+  host_and_port.clear();
+  client_certs.clear();
+}
+
 SSLCertRequestInfo::~SSLCertRequestInfo() {
 }
 
diff --git a/net/base/ssl_cert_request_info.h b/net/base/ssl_cert_request_info.h
index 22eecfe..a180ed9 100644
--- a/net/base/ssl_cert_request_info.h
+++ b/net/base/ssl_cert_request_info.h
@@ -22,6 +22,8 @@
  public:
   SSLCertRequestInfo();
 
+  void Reset();
+
   // The host and port of the SSL server that requested client authentication.
   std::string host_and_port;
 
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index d6df3ea..e18179d 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -23,9 +23,8 @@
     : rev_checking_enabled(true), ssl3_enabled(true),
       tls1_enabled(true), dnssec_enabled(false), snap_start_enabled(false),
       dns_cert_provenance_checking_enabled(false),
-      session_resume_disabled(false), mitm_proxies_allowed(false),
-      false_start_enabled(true), send_client_cert(false),
-      verify_ev_cert(false), ssl3_fallback(false) {
+      mitm_proxies_allowed(false), false_start_enabled(true),
+      send_client_cert(false), verify_ev_cert(false), ssl3_fallback(false) {
 }
 
 SSLConfig::~SSLConfig() {
@@ -43,9 +42,6 @@
     : observer_list_(ObserverList<Observer>::NOTIFY_EXISTING_ONLY) {
 }
 
-SSLConfigService::~SSLConfigService() {
-}
-
 // static
 SSLConfigService* SSLConfigService::CreateSystemSSLConfigService() {
 #if defined(OS_WIN)
@@ -104,16 +100,6 @@
 static bool g_dns_cert_provenance_checking = false;
 
 // static
-void SSLConfigService::SetSSLConfigFlags(SSLConfig* ssl_config) {
-  ssl_config->dnssec_enabled = g_dnssec_enabled;
-  ssl_config->false_start_enabled = g_false_start_enabled;
-  ssl_config->mitm_proxies_allowed = g_mitm_proxies_allowed;
-  ssl_config->snap_start_enabled = g_snap_start_enabled;
-  ssl_config->dns_cert_provenance_checking_enabled =
-      g_dns_cert_provenance_checking;
-}
-
-// static
 void SSLConfigService::EnableDNSSEC() {
   g_dnssec_enabled = true;
 }
@@ -134,16 +120,6 @@
 }
 
 // static
-void SSLConfigService::DisableFalseStart() {
-  g_false_start_enabled = false;
-}
-
-// static
-bool SSLConfigService::false_start_enabled() {
-  return g_false_start_enabled;
-}
-
-// static
 void SSLConfigService::AllowMITMProxies() {
   g_mitm_proxies_allowed = true;
 }
@@ -154,6 +130,16 @@
 }
 
 // static
+void SSLConfigService::DisableFalseStart() {
+  g_false_start_enabled = false;
+}
+
+// static
+bool SSLConfigService::false_start_enabled() {
+  return g_false_start_enabled;
+}
+
+// static
 void SSLConfigService::EnableDNSCertProvenanceChecking() {
   g_dns_cert_provenance_checking = true;
 }
@@ -171,6 +157,19 @@
   observer_list_.RemoveObserver(observer);
 }
 
+SSLConfigService::~SSLConfigService() {
+}
+
+// static
+void SSLConfigService::SetSSLConfigFlags(SSLConfig* ssl_config) {
+  ssl_config->dnssec_enabled = g_dnssec_enabled;
+  ssl_config->false_start_enabled = g_false_start_enabled;
+  ssl_config->mitm_proxies_allowed = g_mitm_proxies_allowed;
+  ssl_config->snap_start_enabled = g_snap_start_enabled;
+  ssl_config->dns_cert_provenance_checking_enabled =
+      g_dns_cert_provenance_checking;
+}
+
 void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
                                            const SSLConfig& new_config) {
   if (orig_config.rev_checking_enabled != new_config.rev_checking_enabled ||
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index 0a9d569..413d076 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.h
@@ -35,11 +35,6 @@
   // True if we'll do async checks for certificate provenance using DNS.
   bool dns_cert_provenance_checking_enabled;
 
-  // TODO(hclam): This option is used to simplify the SSLServerSocketNSS
-  // implementation and should be removed when session caching is implemented.
-  // See http://crbug.com/67236 for more details.
-  bool session_resume_disabled;  // Don't allow session resume.
-
   // Cipher suites which should be explicitly prevented from being used in
   // addition to those disabled by the net built-in policy -- by default, all
   // cipher suites supported by the underlying SSL implementation will be
diff --git a/net/base/ssl_config_service_win.cc b/net/base/ssl_config_service_win.cc
index ca20e79..dbdedb4 100644
--- a/net/base/ssl_config_service_win.cc
+++ b/net/base/ssl_config_service_win.cc
@@ -63,17 +63,15 @@
   // http://crbug.com/61455
   base::ThreadRestrictions::ScopedAllowIO allow_io;
   RegKey internet_settings;
-  if (!internet_settings.Open(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
-                              KEY_READ))
+  if (internet_settings.Open(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
+                             KEY_READ) != ERROR_SUCCESS)
     return false;
 
-  DWORD revocation;
-  if (!internet_settings.ReadValueDW(kRevocationValueName, &revocation))
-    revocation = REVOCATION_DEFAULT;
+  DWORD revocation = REVOCATION_DEFAULT;
+  internet_settings.ReadValueDW(kRevocationValueName, &revocation);
 
-  DWORD protocols;
-  if (!internet_settings.ReadValueDW(kProtocolsValueName, &protocols))
-    protocols = PROTOCOLS_DEFAULT;
+  DWORD protocols = PROTOCOLS_DEFAULT;
+  internet_settings.ReadValueDW(kProtocolsValueName, &protocols);
 
   config->rev_checking_enabled = (revocation != 0);
   config->ssl3_enabled = ((protocols & SSL3) != 0);
@@ -120,9 +118,9 @@
   base::ThreadRestrictions::ScopedAllowIO allow_io;
   RegKey internet_settings(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
                            KEY_READ | KEY_WRITE);
-  DWORD value;
-  if (!internet_settings.ReadValueDW(kProtocolsValueName, &value))
-    value = PROTOCOLS_DEFAULT;
+  DWORD value = PROTOCOLS_DEFAULT;
+  internet_settings.ReadValueDW(kProtocolsValueName, &value);
+
   if (enabled)
     value |= version;
   else
diff --git a/net/base/ssl_config_service_win_unittest.cc b/net/base/ssl_config_service_win_unittest.cc
index 7669d99..6a87760 100644
--- a/net/base/ssl_config_service_win_unittest.cc
+++ b/net/base/ssl_config_service_win_unittest.cc
@@ -38,9 +38,9 @@
 TEST(SSLConfigServiceWinTest, GetNowTest) {
   // Verify that the constructor sets the correct default values.
   net::SSLConfig config;
-  EXPECT_EQ(true, config.rev_checking_enabled);
-  EXPECT_EQ(true, config.ssl3_enabled);
-  EXPECT_EQ(true, config.tls1_enabled);
+  EXPECT_TRUE(config.rev_checking_enabled);
+  EXPECT_TRUE(config.ssl3_enabled);
+  EXPECT_TRUE(config.tls1_enabled);
 
   bool rv = net::SSLConfigServiceWin::GetSSLConfigNow(&config);
   EXPECT_TRUE(rv);
@@ -151,4 +151,3 @@
   // Restore the original SSL3 setting.
   net::SSLConfigServiceWin::SetSSL3Enabled(config_save.ssl3_enabled);
 }
-
diff --git a/net/base/ssl_false_start_blacklist.txt b/net/base/ssl_false_start_blacklist.txt
index aec6142..c13d71d 100644
--- a/net/base/ssl_false_start_blacklist.txt
+++ b/net/base/ssl_false_start_blacklist.txt
@@ -174,6 +174,7 @@
 amo-signature.net
 amo-top.net
 ampecommerce.com
+amsbwm.org
 amsi.alliedgroup.net
 amwaylive.com
 analytics.sonymusic.com
@@ -740,6 +741,7 @@
 cms.whereilive.com.au
 cnw.albertaequestrian.com
 cnw.hcbc.ca
+co-labs.org
 codarts.nl
 coddy.com
 cofunds.co.uk
@@ -859,7 +861,9 @@
 cwa.telecomputing.no
 cwt.no
 cwtnordic.com
+cyberobservatories.net
 cybershoppersonline.com
+cybs.rogers.com
 d-ikt.no
 d-starjob.com
 d115.de
@@ -879,6 +883,7 @@
 datatel.com
 davidson.edu
 davisregional.com
+daymet.org
 dbpn.com
 dc.myflorida.com
 dc110.4shared.com
@@ -931,6 +936,7 @@
 djmmusic.com
 dl.com
 dl.rakuten.co.jp
+dlese.org
 dmgov.org
 dmz.rgcweb.org
 docmesa.com
@@ -1354,6 +1360,7 @@
 geonosis.itsso.gc.ca
 georgefox.edu
 gepartsrebates.com
+gepon.org
 germfree.org
 get1931roadster.com
 get1933caddy.com
@@ -1454,6 +1461,7 @@
 ggy.com
 gilmorehealth.com
 giltcdn.com
+gisclimatechange.org
 global2.mtsallstream.com
 glove.mizunoballpark.com
 glowinghealth.com.au
@@ -1993,6 +2001,7 @@
 level.mol.hu
 lexor.lsp.at
 lexsan.vestingonline.nl
+lgelements.com
 lh.k12.ar.us
 library.failteireland.ie
 liemerscollege.nl
@@ -2678,8 +2687,11 @@
 myevolver.com
 myexterran.com
 myfauquierhealth.org
+myflcourtaccess.com
 myfldocs.com
 myfloodonline.com
+myfloridacounty.com
+myfloridaremit.com
 myfluvaccine.com
 mygetmighytighty.com
 mygiftregistry.co.za
@@ -2814,6 +2826,7 @@
 nrwbank.com
 ns002.toshiba-sol.co.jp
 ns11mm.sept11mm.org
+nsdlnetwork.org
 nsw.gov.au
 nswmentors.com
 ntdira.com
@@ -3522,6 +3535,7 @@
 s.ixiaa.com
 s.ncp.imrworldwide.com
 s1defense.com
+s2task.globe.gov
 saab-leadengine.de
 saas.dynamate.eu
 saas.it-telcom.nl
@@ -4029,6 +4043,7 @@
 tco.cfbt-inspections.com
 tcspost.thomassen.com
 tdj.ac.jp
+teachingboxes.org
 teachingpersonnel.com
 teambrandon.ca
 tecdlr.com
@@ -4048,6 +4063,7 @@
 testdrivereward.com
 testdriveunlimited2.com
 tewkesburyschool.org
+tfelements.com
 tge.cl
 tgn.co.jp
 tgw.com
@@ -4139,6 +4155,7 @@
 tosti-asia.com
 totalcore.com
 touchnbrush.tv
+touchnet.com
 toutatice.fr
 tpmail.transplace.com
 tracs.txstate.edu
@@ -4217,6 +4234,7 @@
 uatoa.americanexpress.com
 ube-ind.co.jp
 ubi.pt
+ucar.edu
 ucf.edu
 uci.edu
 uckac.edu
@@ -4463,6 +4481,7 @@
 wcupa.edu
 wcvpn.wartburg.edu
 wdpartnersonline.com
+weathercoalition.org
 web-opas.osakaya.co.jp
 web-pl.daikin.co.jp
 web-vpn.hefr.ch
diff --git a/net/base/static_cookie_policy.cc b/net/base/static_cookie_policy.cc
index 0ff6ead..19e0a16 100644
--- a/net/base/static_cookie_policy.cc
+++ b/net/base/static_cookie_policy.cc
@@ -16,9 +16,13 @@
                                       CompletionCallback* callback) {
   switch (type_) {
     case StaticCookiePolicy::ALLOW_ALL_COOKIES:
+    case StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES:
       return OK;
-    case StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES:
-      return OK;
+    case StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES:
+      if (first_party_for_cookies.is_empty())
+        return OK;  // Empty first-party URL indicates a first-party request.
+      return RegistryControlledDomainService::SameDomainOrHost(
+          url, first_party_for_cookies) ? OK : ERR_ACCESS_DENIED;
     case StaticCookiePolicy::BLOCK_ALL_COOKIES:
       return ERR_ACCESS_DENIED;
     default:
@@ -34,7 +38,8 @@
   switch (type_) {
     case StaticCookiePolicy::ALLOW_ALL_COOKIES:
       return OK;
-    case StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES:
+    case StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES:
+    case StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES:
       if (first_party_for_cookies.is_empty())
         return OK;  // Empty first-party URL indicates a first-party request.
       return RegistryControlledDomainService::SameDomainOrHost(
diff --git a/net/base/static_cookie_policy.h b/net/base/static_cookie_policy.h
index 4633161..815aadc 100644
--- a/net/base/static_cookie_policy.h
+++ b/net/base/static_cookie_policy.h
@@ -23,10 +23,17 @@
 //
 class StaticCookiePolicy : public CookiePolicy {
  public:
+  // Do not change the order of these types as they are persisted in
+  // preferences.
   enum Type {
-    ALLOW_ALL_COOKIES = 0,      // Do not perform any cookie blocking.
-    BLOCK_THIRD_PARTY_COOKIES,  // Prevent third-party cookies from being set.
-    BLOCK_ALL_COOKIES           // Disable cookies.
+    // Do not perform any cookie blocking.
+    ALLOW_ALL_COOKIES = 0,
+    // Prevent only third-party cookies from being set.
+    BLOCK_SETTING_THIRD_PARTY_COOKIES,
+    // Block all cookies (third-party or not) from begin set or read.
+    BLOCK_ALL_COOKIES,
+    // Prevent only third-party cookies from being set or read.
+    BLOCK_ALL_THIRD_PARTY_COOKIES
   };
 
   StaticCookiePolicy()
diff --git a/net/base/static_cookie_policy_unittest.cc b/net/base/static_cookie_policy_unittest.cc
index 35c1a82..57dc4fa 100644
--- a/net/base/static_cookie_policy_unittest.cc
+++ b/net/base/static_cookie_policy_unittest.cc
@@ -62,8 +62,8 @@
   EXPECT_EQ(net::OK, CanSetCookie(url_google_, GURL()));
 }
 
-TEST_F(StaticCookiePolicyTest, BlockThirdPartyCookiesTest) {
-  SetPolicyType(net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES);
+TEST_F(StaticCookiePolicyTest, BlockSettingThirdPartyCookiesTest) {
+  SetPolicyType(net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
 
   EXPECT_EQ(net::OK, CanGetCookies(url_google_, url_google_));
   EXPECT_EQ(net::OK, CanGetCookies(url_google_, url_google_secure_));
@@ -78,6 +78,22 @@
   EXPECT_EQ(net::OK, CanSetCookie(url_google_, GURL()));
 }
 
+TEST_F(StaticCookiePolicyTest, BlockAllThirdPartyCookiesTest) {
+  SetPolicyType(net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES);
+
+  EXPECT_EQ(net::OK, CanGetCookies(url_google_, url_google_));
+  EXPECT_EQ(net::OK, CanGetCookies(url_google_, url_google_secure_));
+  EXPECT_EQ(net::OK, CanGetCookies(url_google_, url_google_mail_));
+  EXPECT_NE(net::OK, CanGetCookies(url_google_, url_google_analytics_));
+  EXPECT_EQ(net::OK, CanGetCookies(url_google_, GURL()));
+
+  EXPECT_EQ(net::OK, CanSetCookie(url_google_, url_google_));
+  EXPECT_EQ(net::OK, CanSetCookie(url_google_, url_google_secure_));
+  EXPECT_EQ(net::OK, CanSetCookie(url_google_, url_google_mail_));
+  EXPECT_NE(net::OK, CanSetCookie(url_google_, url_google_analytics_));
+  EXPECT_EQ(net::OK, CanSetCookie(url_google_, GURL()));
+}
+
 TEST_F(StaticCookiePolicyTest, BlockAllCookiesTest) {
   SetPolicyType(net::StaticCookiePolicy::BLOCK_ALL_COOKIES);
 
diff --git a/net/base/test_completion_callback.h b/net/base/test_completion_callback.h
index b4a005b..ba578d4 100644
--- a/net/base/test_completion_callback.h
+++ b/net/base/test_completion_callback.h
@@ -7,9 +7,6 @@
 #pragma once
 
 #include "base/callback.h"
-#include "base/message_loop.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_errors.h"
 
 //-----------------------------------------------------------------------------
 // completion callback helper
@@ -24,37 +21,16 @@
 //
 class TestCompletionCallback : public CallbackRunner< Tuple1<int> > {
  public:
-  TestCompletionCallback()
-      : result_(0),
-        have_result_(false),
-        waiting_for_result_(false) {
-  }
+  TestCompletionCallback();
+  virtual ~TestCompletionCallback();
 
-  int WaitForResult() {
-    DCHECK(!waiting_for_result_);
-    while (!have_result_) {
-      waiting_for_result_ = true;
-      MessageLoop::current()->Run();
-      waiting_for_result_ = false;
-    }
-    have_result_ = false;  // auto-reset for next callback
-    return result_;
-  }
+  int WaitForResult();
 
-  int GetResult(int result) {
-    if (net::ERR_IO_PENDING != result)
-      return result;
-    return WaitForResult();
-  }
+  int GetResult(int result);
 
   bool have_result() const { return have_result_; }
 
-  virtual void RunWithParams(const Tuple1<int>& params) {
-    result_ = params.a;
-    have_result_ = true;
-    if (waiting_for_result_)
-      MessageLoop::current()->Quit();
-  }
+  virtual void RunWithParams(const Tuple1<int>& params);
 
  private:
   int result_;
diff --git a/net/base/test_completion_callback_unittest.cc b/net/base/test_completion_callback_unittest.cc
index a0ae9bf..1b9d71d 100644
--- a/net/base/test_completion_callback_unittest.cc
+++ b/net/base/test_completion_callback_unittest.cc
@@ -4,6 +4,9 @@
 
 // Illustrates how to use worker threads that issue completion callbacks
 
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
 #include "base/threading/worker_pool.h"
 #include "net/base/completion_callback.h"
 #include "net/base/test_completion_callback.h"
@@ -55,7 +58,7 @@
   ExampleEmployer* employer_;
   CompletionCallback* callback_;
   // Used to post ourselves onto the origin thread.
-  Lock origin_loop_lock_;
+  base::Lock origin_loop_lock_;
   MessageLoop* origin_loop_;
 };
 
@@ -68,7 +71,7 @@
   // The origin loop could go away while we are trying to post to it, so we
   // need to call its PostTask method inside a lock.  See ~ExampleEmployer.
   {
-    AutoLock locked(origin_loop_lock_);
+    base::AutoLock locked(origin_loop_lock_);
     if (origin_loop_) {
       origin_loop_->PostTask(FROM_HERE, reply);
       reply = NULL;
diff --git a/net/base/transport_security_state.cc b/net/base/transport_security_state.cc
index 32b7566..aed714c 100644
--- a/net/base/transport_security_state.cc
+++ b/net/base/transport_security_state.cc
@@ -100,6 +100,23 @@
   return false;
 }
 
+void TransportSecurityState::DeleteSince(const base::Time& time) {
+  bool dirtied = false;
+
+  std::map<std::string, DomainState>::iterator i = enabled_hosts_.begin();
+  while (i != enabled_hosts_.end()) {
+    if (i->second.created >= time) {
+      dirtied = true;
+      enabled_hosts_.erase(i++);
+    } else {
+      i++;
+    }
+  }
+
+  if (dirtied)
+    DirtyNotify();
+}
+
 // MaxAgeToInt converts a string representation of a number of seconds into a
 // int. We use strtol in order to handle overflow correctly. The string may
 // contain an arbitary number which we should truncate correctly rather than
@@ -248,8 +265,8 @@
        i = enabled_hosts_.begin(); i != enabled_hosts_.end(); ++i) {
     DictionaryValue* state = new DictionaryValue;
     state->SetBoolean("include_subdomains", i->second.include_subdomains);
-    state->SetReal("created", i->second.created.ToDoubleT());
-    state->SetReal("expiry", i->second.expiry.ToDoubleT());
+    state->SetDouble("created", i->second.created.ToDoubleT());
+    state->SetDouble("expiry", i->second.expiry.ToDoubleT());
 
     switch (i->second.mode) {
       case DomainState::MODE_STRICT:
@@ -300,7 +317,7 @@
 
     if (!state->GetBoolean("include_subdomains", &include_subdomains) ||
         !state->GetString("mode", &mode_string) ||
-        !state->GetReal("expiry", &expiry)) {
+        !state->GetDouble("expiry", &expiry)) {
       continue;
     }
 
@@ -319,7 +336,7 @@
 
     base::Time expiry_time = base::Time::FromDoubleT(expiry);
     base::Time created_time;
-    if (state->GetReal("created", &created)) {
+    if (state->GetDouble("created", &created)) {
       created_time = base::Time::FromDoubleT(created);
     } else {
       // We're migrating an old entry with no creation date. Make sure we
@@ -350,23 +367,6 @@
   return true;
 }
 
-void TransportSecurityState::DeleteSince(const base::Time& time) {
-  bool dirtied = false;
-
-  std::map<std::string, DomainState>::iterator i = enabled_hosts_.begin();
-  while (i != enabled_hosts_.end()) {
-    if (i->second.created >= time) {
-      dirtied = true;
-      enabled_hosts_.erase(i++);
-    } else {
-      i++;
-    }
-  }
-
-  if (dirtied)
-    DirtyNotify();
-}
-
 TransportSecurityState::~TransportSecurityState() {
 }
 
@@ -436,6 +436,9 @@
     {17, false, "\002id\010mayfirst\003org"},
     {20, false, "\005lists\010mayfirst\003org"},
     {19, true, "\015splendidbacon\003com"},
+    {19, false, "\006health\006google\003com"},
+    {21, false, "\010checkout\006google\003com"},
+    {19, false, "\006chrome\006google\003com"},
   };
   static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
 
diff --git a/net/base/upload_data.cc b/net/base/upload_data.cc
index 5b23eff..436522f 100644
--- a/net/base/upload_data.cc
+++ b/net/base/upload_data.cc
@@ -6,6 +6,7 @@
 
 #include "base/file_util.h"
 #include "base/logging.h"
+#include "base/string_util.h"
 #include "net/base/file_stream.h"
 #include "net/base/net_errors.h"
 
@@ -19,6 +20,7 @@
     : type_(TYPE_BYTES),
       file_range_offset_(0),
       file_range_length_(kuint64max),
+      is_last_chunk_(false),
       override_content_length_(false),
       content_length_computed_(false),
       content_length_(-1),
@@ -30,11 +32,23 @@
   delete file_stream_;
 }
 
+void UploadData::Element::SetToChunk(const char* bytes, int bytes_len) {
+  std::string chunk_length = StringPrintf("%X\r\n", bytes_len);
+  bytes_.clear();
+  bytes_.insert(bytes_.end(), chunk_length.data(),
+                chunk_length.data() + chunk_length.length());
+  bytes_.insert(bytes_.end(), bytes, bytes + bytes_len);
+  const char* crlf = "\r\n";
+  bytes_.insert(bytes_.end(), crlf, crlf + 2);
+  type_ = TYPE_CHUNK;
+  is_last_chunk_ = (bytes_len == 0);
+}
+
 uint64 UploadData::Element::GetContentLength() {
   if (override_content_length_ || content_length_computed_)
     return content_length_;
 
-  if (type_ == TYPE_BYTES)
+  if (type_ == TYPE_BYTES || type_ == TYPE_CHUNK)
     return static_cast<uint64>(bytes_.size());
   else if (type_ == TYPE_BLOB)
     // The blob reference will be resolved later.
@@ -109,10 +123,14 @@
   return file.release();
 }
 
-UploadData::UploadData() : identifier_(0) {
+UploadData::UploadData()
+    : identifier_(0),
+      chunk_callback_(NULL),
+      is_chunked_(false) {
 }
 
 void UploadData::AppendBytes(const char* bytes, int bytes_len) {
+  DCHECK(!is_chunked_);
   if (bytes_len > 0) {
     elements_.push_back(Element());
     elements_.back().SetToBytes(bytes, bytes_len);
@@ -120,6 +138,7 @@
 }
 
 void UploadData::AppendFile(const FilePath& file_path) {
+  DCHECK(!is_chunked_);
   elements_.push_back(Element());
   elements_.back().SetToFilePath(file_path);
 }
@@ -127,16 +146,30 @@
 void UploadData::AppendFileRange(const FilePath& file_path,
                                  uint64 offset, uint64 length,
                                  const base::Time& expected_modification_time) {
+  DCHECK(!is_chunked_);
   elements_.push_back(Element());
   elements_.back().SetToFilePathRange(file_path, offset, length,
                                       expected_modification_time);
 }
 
 void UploadData::AppendBlob(const GURL& blob_url) {
+  DCHECK(!is_chunked_);
   elements_.push_back(Element());
   elements_.back().SetToBlobUrl(blob_url);
 }
 
+void UploadData::AppendChunk(const char* bytes, int bytes_len) {
+  DCHECK(is_chunked_);
+  elements_.push_back(Element());
+  elements_.back().SetToChunk(bytes, bytes_len);
+  if (chunk_callback_)
+    chunk_callback_->OnChunkAvailable();
+}
+
+void UploadData::set_chunk_callback(ChunkCallback* callback) {
+  chunk_callback_ = callback;
+}
+
 uint64 UploadData::GetContentLength() {
   uint64 len = 0;
   std::vector<Element>::iterator it = elements_.begin();
diff --git a/net/base/upload_data.h b/net/base/upload_data.h
index 6f72162..e746f65 100644
--- a/net/base/upload_data.h
+++ b/net/base/upload_data.h
@@ -19,12 +19,27 @@
 
 class FileStream;
 
+// Interface implemented by callers who require callbacks when new chunks
+// of data are added.
+class ChunkCallback {
+ public:
+  // Invoked when a new data chunk was given for a chunked transfer upload.
+  virtual void OnChunkAvailable() = 0;
+
+ protected:
+  virtual ~ChunkCallback() {}
+};
+
 class UploadData : public base::RefCounted<UploadData> {
  public:
   enum Type {
     TYPE_BYTES,
     TYPE_FILE,
-    TYPE_BLOB
+    TYPE_BLOB,
+
+    // A block of bytes to be sent in chunked encoding immediately, without
+    // waiting for rest of the data.
+    TYPE_CHUNK,
   };
 
   class Element {
@@ -33,6 +48,12 @@
     ~Element();
 
     Type type() const { return type_; }
+    // Explicitly sets the type of this Element. Used during IPC
+    // marshalling.
+    void set_type(Type type) {
+      type_ = type;
+    }
+
     const std::vector<char>& bytes() const { return bytes_; }
     const FilePath& file_path() const { return file_path_; }
     uint64 file_range_offset() const { return file_range_offset_; }
@@ -72,6 +93,17 @@
       blob_url_ = blob_url;
     }
 
+    // Though similar to bytes, a chunk indicates that the element is sent via
+    // chunked transfer encoding and not buffered until the full upload data
+    // is available.
+    void SetToChunk(const char* bytes, int bytes_len);
+
+    bool is_last_chunk() const { return is_last_chunk_; }
+    // Sets whether this is the last chunk. Used during IPC marshalling.
+    void set_is_last_chunk(bool is_last_chunk) {
+      is_last_chunk_ = is_last_chunk;
+    }
+
     // Returns the byte-length of the element.  For files that do not exist, 0
     // is returned.  This is done for consistency with Mozilla.
     // Once called, this function will always return the same value.
@@ -97,6 +129,7 @@
     uint64 file_range_length_;
     base::Time expected_file_modification_time_;
     GURL blob_url_;
+    bool is_last_chunk_;
     bool override_content_length_;
     bool content_length_computed_;
     uint64 content_length_;
@@ -119,6 +152,18 @@
 
   void AppendBlob(const GURL& blob_url);
 
+  // Adds the given chunk of bytes to be sent immediately with chunked transfer
+  // encoding. Set bytes_len to zero for the last chunk.
+  void AppendChunk(const char* bytes, int bytes_len);
+
+  // Sets the callback to be invoked when a new chunk is available to upload.
+  void set_chunk_callback(ChunkCallback* callback);
+
+  // Initializes the object to send chunks of upload data over time rather
+  // than all at once.
+  void set_is_chunked(bool set) { is_chunked_ = set; }
+  bool is_chunked() const { return is_chunked_; }
+
   // Returns the total size in bytes of the data to upload.
   uint64 GetContentLength();
 
@@ -145,6 +190,8 @@
 
   std::vector<Element> elements_;
   int64 identifier_;
+  ChunkCallback* chunk_callback_;
+  bool is_chunked_;
 
   DISALLOW_COPY_AND_ASSIGN(UploadData);
 };
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc
index 6405549..dabfdd7 100644
--- a/net/base/upload_data_stream.cc
+++ b/net/base/upload_data_stream.cc
@@ -12,6 +12,9 @@
 
 namespace net {
 
+UploadDataStream::~UploadDataStream() {
+}
+
 UploadDataStream* UploadDataStream::Create(UploadData* data, int* error_code) {
   scoped_ptr<UploadDataStream> stream(new UploadDataStream(data));
   int rv = stream->FillBuf();
@@ -23,45 +26,44 @@
   return stream.release();
 }
 
-UploadDataStream::UploadDataStream(UploadData* data)
-    : data_(data),
-      buf_(new IOBuffer(kBufSize)),
-      buf_len_(0),
-      next_element_(data->elements()->begin()),
-      next_element_offset_(0),
-      next_element_remaining_(0),
-      total_size_(data->GetContentLength()),
-      current_position_(0),
-      eof_(false) {
-}
-
-UploadDataStream::~UploadDataStream() {
-}
-
-void UploadDataStream::DidConsume(size_t num_bytes) {
+void UploadDataStream::MarkConsumedAndFillBuffer(size_t num_bytes) {
   DCHECK_LE(num_bytes, buf_len_);
   DCHECK(!eof_);
 
-  buf_len_ -= num_bytes;
-  if (buf_len_)
-    memmove(buf_->data(), buf_->data() + num_bytes, buf_len_);
+  if (num_bytes) {
+    buf_len_ -= num_bytes;
+    if (buf_len_)
+      memmove(buf_->data(), buf_->data() + num_bytes, buf_len_);
+  }
 
   FillBuf();
 
   current_position_ += num_bytes;
 }
 
-int UploadDataStream::FillBuf() {
-  std::vector<UploadData::Element>::iterator end =
-      data_->elements()->end();
+UploadDataStream::UploadDataStream(UploadData* data)
+    : data_(data),
+      buf_(new IOBuffer(kBufSize)),
+      buf_len_(0),
+      next_element_(0),
+      next_element_offset_(0),
+      next_element_remaining_(0),
+      total_size_(data->is_chunked() ? 0 : data->GetContentLength()),
+      current_position_(0),
+      eof_(false) {
+}
 
-  while (buf_len_ < kBufSize && next_element_ != end) {
+int UploadDataStream::FillBuf() {
+  std::vector<UploadData::Element>& elements = *data_->elements();
+
+  while (buf_len_ < kBufSize && next_element_ < elements.size()) {
     bool advance_to_next_element = false;
 
-    UploadData::Element& element = *next_element_;
+    UploadData::Element& element = elements[next_element_];
 
     size_t size_remaining = kBufSize - buf_len_;
-    if (element.type() == UploadData::TYPE_BYTES) {
+    if (element.type() == UploadData::TYPE_BYTES ||
+        element.type() == UploadData::TYPE_CHUNK) {
       const std::vector<char>& d = element.bytes();
       size_t count = d.size() - next_element_offset_;
 
@@ -140,8 +142,12 @@
     }
   }
 
-  if (next_element_ == end && !buf_len_)
-    eof_ = true;
+  if (next_element_ == elements.size() && !buf_len_) {
+    if (!data_->is_chunked() ||
+        (!elements.empty() && elements.back().is_last_chunk())) {
+      eof_ = true;
+    }
+  }
 
   return OK;
 }
diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h
index d513125..c3044fc 100644
--- a/net/base/upload_data_stream.h
+++ b/net/base/upload_data_stream.h
@@ -20,13 +20,13 @@
 
 class UploadDataStream {
  public:
+  ~UploadDataStream();
+
   // Returns a new instance of UploadDataStream if it can be created and
   // initialized successfully. If not, NULL will be returned and the error
   // code will be set if the output parameter error_code is not empty.
   static UploadDataStream* Create(UploadData* data, int* error_code);
 
-  ~UploadDataStream();
-
   // Returns the stream's buffer and buffer length.
   IOBuffer* buf() const { return buf_; }
   size_t buf_len() const { return buf_len_; }
@@ -34,7 +34,12 @@
   // Call to indicate that a portion of the stream's buffer was consumed.  This
   // call modifies the stream's buffer so that it contains the next segment of
   // the upload data to be consumed.
-  void DidConsume(size_t num_bytes);
+  void MarkConsumedAndFillBuffer(size_t num_bytes);
+
+  // Sets the callback to be invoked when new chunks are available to upload.
+  void set_chunk_callback(ChunkCallback* callback) {
+    data_->set_chunk_callback(callback);
+  }
 
   // Returns the total size of the data stream and the current position.
   // size() is not to be used to determine whether the stream has ended
@@ -43,11 +48,15 @@
   uint64 size() const { return total_size_; }
   uint64 position() const { return current_position_; }
 
+  bool is_chunked() const { return data_->is_chunked(); }
+
   // Returns whether there is no more data to read, regardless of whether
   // position < size.
   bool eof() const { return eof_; }
 
  private:
+  enum { kBufSize = 16384 };
+
   // Protects from public access since now we have a static creator function
   // which will do both creation and initialization and might return an error.
   explicit UploadDataStream(UploadData* data);
@@ -63,12 +72,11 @@
   // always at the front of the buffer.  If we cannot send all of the buffer at
   // once, then we memmove the remaining portion and back-fill the buffer for
   // the next "write" call.  buf_len_ indicates how much data is in the buffer.
-  enum { kBufSize = 16384 };
   scoped_refptr<IOBuffer> buf_;
   size_t buf_len_;
 
-  // Iterator to the upload element to be written to the send buffer next.
-  std::vector<UploadData::Element>::iterator next_element_;
+  // Index of the upload element to be written to the send buffer next.
+  size_t next_element_;
 
   // The byte offset into next_element_'s data buffer if the next element is
   // a TYPE_BYTES element.
diff --git a/net/base/upload_data_stream_unittest.cc b/net/base/upload_data_stream_unittest.cc
index 8a21ad6..780bd23 100644
--- a/net/base/upload_data_stream_unittest.cc
+++ b/net/base/upload_data_stream_unittest.cc
@@ -50,7 +50,7 @@
       UploadDataStream::Create(upload_data_, NULL));
   ASSERT_TRUE(stream.get());
   while (!stream->eof()) {
-    stream->DidConsume(stream->buf_len());
+    stream->MarkConsumedAndFillBuffer(stream->buf_len());
   }
 }
 
@@ -76,7 +76,7 @@
   uint64 read_counter = 0;
   while (!stream->eof()) {
     read_counter += stream->buf_len();
-    stream->DidConsume(stream->buf_len());
+    stream->MarkConsumedAndFillBuffer(stream->buf_len());
   }
   // UpdateDataStream will pad out the file with 0 bytes so that the HTTP
   // transaction doesn't hang.  Therefore we expected the full size.
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc
index 7385743..6469537 100644
--- a/net/base/x509_certificate.cc
+++ b/net/base/x509_certificate.cc
@@ -64,7 +64,7 @@
 
   // You must acquire this lock before using any private data of this object.
   // You must not block while holding this lock.
-  Lock lock_;
+  base::Lock lock_;
 
   // The certificate cache.  You must acquire |lock_| before using |cache_|.
   CertMap cache_;
@@ -79,7 +79,7 @@
 // Insert |cert| into the cache.  The cache does NOT AddRef |cert|.
 // Any existing certificate with the same fingerprint will be replaced.
 void X509CertificateCache::Insert(X509Certificate* cert) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   DCHECK(!IsNullFingerprint(cert->fingerprint())) <<
       "Only insert certs with real fingerprints.";
@@ -89,7 +89,7 @@
 // Remove |cert| from the cache.  The cache does not assume that |cert| is
 // already in the cache.
 void X509CertificateCache::Remove(X509Certificate* cert) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   CertMap::iterator pos(cache_.find(cert->fingerprint()));
   if (pos == cache_.end())
@@ -101,7 +101,7 @@
 // not exist, this method returns NULL.
 X509Certificate* X509CertificateCache::Find(
     const SHA1Fingerprint& fingerprint) {
-  AutoLock lock(lock_);
+  base::AutoLock lock(lock_);
 
   CertMap::iterator pos(cache_.find(fingerprint));
   if (pos == cache_.end())
@@ -121,6 +121,19 @@
   return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
 }
 
+X509Certificate::X509Certificate(const std::string& subject,
+                                 const std::string& issuer,
+                                 base::Time start_date,
+                                 base::Time expiration_date)
+    : subject_(subject),
+      issuer_(issuer),
+      valid_start_(start_date),
+      valid_expiry_(expiration_date),
+      cert_handle_(NULL),
+      source_(SOURCE_UNUSED) {
+  memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
+}
+
 // static
 X509Certificate* X509Certificate::CreateFromHandle(
     OSCertHandle cert_handle,
@@ -283,40 +296,6 @@
   return results;
 }
 
-X509Certificate::X509Certificate(OSCertHandle cert_handle,
-                                 Source source,
-                                 const OSCertHandles& intermediates)
-    : cert_handle_(DupOSCertHandle(cert_handle)),
-      source_(source) {
-  // Copy/retain the intermediate cert handles.
-  for (size_t i = 0; i < intermediates.size(); ++i)
-    intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i]));
-  // Platform-specific initialization.
-  Initialize();
-}
-
-X509Certificate::X509Certificate(const std::string& subject,
-                                 const std::string& issuer,
-                                 base::Time start_date,
-                                 base::Time expiration_date)
-    : subject_(subject),
-      issuer_(issuer),
-      valid_start_(start_date),
-      valid_expiry_(expiration_date),
-      cert_handle_(NULL),
-      source_(SOURCE_UNUSED) {
-  memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
-}
-
-X509Certificate::~X509Certificate() {
-  // We might not be in the cache, but it is safe to remove ourselves anyway.
-  g_x509_certificate_cache.Get().Remove(this);
-  if (cert_handle_)
-    FreeOSCertHandle(cert_handle_);
-  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
-    FreeOSCertHandle(intermediate_ca_certs_[i]);
-}
-
 bool X509Certificate::HasExpired() const {
   return base::Time::Now() > valid_expiry();
 }
@@ -345,4 +324,25 @@
   return true;
 }
 
+X509Certificate::X509Certificate(OSCertHandle cert_handle,
+                                 Source source,
+                                 const OSCertHandles& intermediates)
+    : cert_handle_(DupOSCertHandle(cert_handle)),
+      source_(source) {
+  // Copy/retain the intermediate cert handles.
+  for (size_t i = 0; i < intermediates.size(); ++i)
+    intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i]));
+  // Platform-specific initialization.
+  Initialize();
+}
+
+X509Certificate::~X509Certificate() {
+  // We might not be in the cache, but it is safe to remove ourselves anyway.
+  g_x509_certificate_cache.Get().Remove(this);
+  if (cert_handle_)
+    FreeOSCertHandle(cert_handle_);
+  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
+    FreeOSCertHandle(intermediate_ca_certs_[i]);
+}
+
 }  // namespace net
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index b3fa006..77ad155 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -24,7 +24,7 @@
 #include <CoreFoundation/CFArray.h>
 #include <Security/SecBase.h>
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #elif defined(USE_OPENSSL)
 // Forward declaration; real one in <x509.h>
 struct x509_st;
@@ -383,7 +383,7 @@
 #if defined(OS_MACOSX)
   // Blocks multiple threads from verifying the cert simultaneously.
   // (Marked mutable because it's used in a const method.)
-  mutable Lock verification_lock_;
+  mutable base::Lock verification_lock_;
 #endif
 
   // Where the certificate comes from.
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index fd965cb..3cc1e08 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -8,8 +8,13 @@
 #include <Security/Security.h>
 #include <time.h>
 
+#include <vector>
+
+#include "base/crypto/cssm_init.h"
+#include "base/crypto/rsa_private_key.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/nss_util.h"
 #include "base/pickle.h"
 #include "base/singleton.h"
 #include "base/mac/scoped_cftyperef.h"
@@ -18,6 +23,7 @@
 #include "net/base/cert_verify_result.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_root_certs.h"
+#include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h"
 
 using base::mac::ScopedCFTypeRef;
 using base::Time;
@@ -369,6 +375,99 @@
   }
 }
 
+struct CSSMOIDString {
+  const CSSM_OID* oid_;
+  std::string string_;
+};
+
+typedef std::vector<CSSMOIDString> CSSMOIDStringVector;
+
+bool CERTNameToCSSMOIDVector(CERTName* name, CSSMOIDStringVector* out_values) {
+  struct OIDCSSMMap {
+    SECOidTag sec_OID_;
+    const CSSM_OID* cssm_OID_;
+  };
+
+  const OIDCSSMMap kOIDs[] = {
+      { SEC_OID_AVA_COMMON_NAME, &CSSMOID_CommonName },
+      { SEC_OID_AVA_COUNTRY_NAME, &CSSMOID_CountryName },
+      { SEC_OID_AVA_LOCALITY, &CSSMOID_LocalityName },
+      { SEC_OID_AVA_STATE_OR_PROVINCE, &CSSMOID_StateProvinceName },
+      { SEC_OID_AVA_STREET_ADDRESS, &CSSMOID_StreetAddress },
+      { SEC_OID_AVA_ORGANIZATION_NAME, &CSSMOID_OrganizationName },
+      { SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, &CSSMOID_OrganizationalUnitName },
+      { SEC_OID_AVA_DN_QUALIFIER, &CSSMOID_DNQualifier },
+      { SEC_OID_RFC1274_UID, &CSSMOID_UniqueIdentifier },
+      { SEC_OID_PKCS9_EMAIL_ADDRESS, &CSSMOID_EmailAddress },
+  };
+
+  CERTRDN** rdns = name->rdns;
+  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
+    CERTAVA** avas = rdns[rdn]->avas;
+    for (size_t pair = 0; avas[pair] != 0; ++pair) {
+      SECOidTag tag = CERT_GetAVATag(avas[pair]);
+      if (tag == SEC_OID_UNKNOWN) {
+        return false;
+      }
+      CSSMOIDString oidString;
+      bool found_oid = false;
+      for (size_t oid = 0; oid < ARRAYSIZE_UNSAFE(kOIDs); ++oid) {
+        if (kOIDs[oid].sec_OID_ == tag) {
+          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
+          if (!decode_item)
+            return false;
+
+          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
+          std::string value(reinterpret_cast<char*>(decode_item->data),
+                            decode_item->len);
+          oidString.oid_ = kOIDs[oid].cssm_OID_;
+          oidString.string_ = value;
+          out_values->push_back(oidString);
+          SECITEM_FreeItem(decode_item, PR_TRUE);
+          found_oid = true;
+          break;
+        }
+      }
+      if (!found_oid) {
+        DLOG(ERROR) << "Unrecognized OID: " << tag;
+      }
+    }
+  }
+  return true;
+}
+
+class ScopedCertName {
+ public:
+  explicit ScopedCertName(CERTName* name) : name_(name) { }
+  ~ScopedCertName() {
+    if (name_) CERT_DestroyName(name_);
+  }
+  operator CERTName*() { return name_; }
+
+ private:
+  CERTName* name_;
+};
+
+class ScopedEncodedCertResults {
+ public:
+  explicit ScopedEncodedCertResults(CSSM_TP_RESULT_SET* results)
+      : results_(results) { }
+  ~ScopedEncodedCertResults() {
+    if (results_) {
+      CSSM_ENCODED_CERT* encCert =
+          reinterpret_cast<CSSM_ENCODED_CERT*>(results_->Results);
+      for (uint32 i = 0; i < results_->NumberOfResults; i++) {
+        base::CSSMFree(encCert[i].CertBlob.Data);
+      }
+    }
+    base::CSSMFree(results_->Results);
+    base::CSSMFree(results_);
+  }
+
+private:
+  CSSM_TP_RESULT_SET* results_;
+};
+
 }  // namespace
 
 void X509Certificate::Initialize() {
@@ -406,8 +505,138 @@
     const std::string& subject,
     uint32 serial_number,
     base::TimeDelta valid_duration) {
-  // TODO(port): Implement.
-  return NULL;
+  DCHECK(key);
+  DCHECK(!subject.empty());
+
+  if (valid_duration.InSeconds() > UINT32_MAX) {
+     LOG(ERROR) << "valid_duration too big" << valid_duration.InSeconds();
+     valid_duration = base::TimeDelta::FromSeconds(UINT32_MAX);
+  }
+
+  // There is a comment in
+  // http://www.opensource.apple.com/source/security_certtool/security_certtool-31828/src/CertTool.cpp
+  // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have
+  // their high bit set. We will continue though and mask it out below.
+  if (serial_number & 0x80000000)
+    LOG(ERROR) << "serial_number has high bit set " << serial_number;
+
+  // NSS is used to parse the subject string into a set of
+  // CSSM_OID/string pairs. There doesn't appear to be a system routine for
+  // parsing Distinguished Name strings.
+  base::EnsureNSSInit();
+
+  CSSMOIDStringVector subject_name_oids;
+  ScopedCertName subject_name(
+      CERT_AsciiToName(const_cast<char*>(subject.c_str())));
+  if (!CERTNameToCSSMOIDVector(subject_name, &subject_name_oids)) {
+    DLOG(ERROR) << "Unable to generate CSSMOIDMap from " << subject;
+    return NULL;
+  }
+
+  // Convert the map of oid/string pairs into an array of
+  // CSSM_APPLE_TP_NAME_OIDs.
+  std::vector<CSSM_APPLE_TP_NAME_OID> cssm_subject_names;
+  for(CSSMOIDStringVector::iterator iter = subject_name_oids.begin();
+      iter != subject_name_oids.end(); ++iter) {
+    CSSM_APPLE_TP_NAME_OID cssm_subject_name;
+    cssm_subject_name.oid = iter->oid_;
+    cssm_subject_name.string = iter->string_.c_str();
+    cssm_subject_names.push_back(cssm_subject_name);
+  }
+
+  if (cssm_subject_names.size() == 0) {
+    DLOG(ERROR) << "cssm_subject_names.size() == 0. Input: " << subject;
+    return NULL;
+  }
+
+  // Set up a certificate request.
+  CSSM_APPLE_TP_CERT_REQUEST certReq;
+  memset(&certReq, 0, sizeof(certReq));
+  certReq.cspHand = base::GetSharedCSPHandle();
+  certReq.clHand = base::GetSharedCLHandle();
+    // See comment about serial numbers above.
+  certReq.serialNumber = serial_number & 0x7fffffff;
+  certReq.numSubjectNames = cssm_subject_names.size();
+  certReq.subjectNames = &cssm_subject_names[0];
+  certReq.numIssuerNames = 0; // Root.
+  certReq.issuerNames = NULL;
+  certReq.issuerNameX509 = NULL;
+  certReq.certPublicKey = key->public_key();
+  certReq.issuerPrivateKey = key->key();
+  // These are the Apple defaults.
+  certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA;
+  certReq.signatureOid = CSSMOID_SHA1WithRSA;
+  certReq.notBefore = 0;
+  certReq.notAfter = static_cast<uint32>(valid_duration.InSeconds());
+  certReq.numExtensions = 0;
+  certReq.extensions = NULL;
+  certReq.challengeString = NULL;
+
+  CSSM_TP_REQUEST_SET reqSet;
+  reqSet.NumberOfRequests = 1;
+  reqSet.Requests = &certReq;
+
+  CSSM_FIELD policyId;
+  memset(&policyId, 0, sizeof(policyId));
+  policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
+
+  CSSM_TP_CALLERAUTH_CONTEXT callerAuthContext;
+  memset(&callerAuthContext, 0, sizeof(callerAuthContext));
+  callerAuthContext.Policy.NumberOfPolicyIds = 1;
+  callerAuthContext.Policy.PolicyIds = &policyId;
+
+  CSSM_TP_HANDLE tp_handle = base::GetSharedTPHandle();
+  CSSM_DATA refId;
+  memset(&refId, 0, sizeof(refId));
+  sint32 estTime;
+  CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tp_handle, NULL,
+      CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, &reqSet, &callerAuthContext,
+       &estTime, &refId);
+  if(crtn) {
+    DLOG(ERROR) << "CSSM_TP_SubmitCredRequest failed " << crtn;
+    return NULL;
+  }
+
+  CSSM_BOOL confirmRequired;
+  CSSM_TP_RESULT_SET *resultSet = NULL;
+  crtn = CSSM_TP_RetrieveCredResult(tp_handle, &refId, NULL, &estTime,
+                                    &confirmRequired, &resultSet);
+  ScopedEncodedCertResults scopedResults(resultSet);
+  base::CSSMFree(refId.Data);
+  if (crtn) {
+    DLOG(ERROR) << "CSSM_TP_RetrieveCredResult failed " << crtn;
+    return NULL;
+  }
+
+  if (confirmRequired) {
+    // Potential leak here of resultSet. |confirmRequired| should never be
+    // true.
+    DLOG(ERROR) << "CSSM_TP_RetrieveCredResult required confirmation";
+    return NULL;
+  }
+
+  if (resultSet->NumberOfResults != 1) {
+     DLOG(ERROR) << "Unexpected number of results: "
+                 << resultSet->NumberOfResults;
+    return NULL;
+  }
+
+  CSSM_ENCODED_CERT* encCert =
+      reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results);
+  base::mac::ScopedCFTypeRef<SecCertificateRef> scoped_cert;
+  SecCertificateRef certificate_ref = NULL;
+  OSStatus os_status =
+      SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType,
+                                   encCert->CertEncoding, &certificate_ref);
+  if (os_status != 0) {
+    DLOG(ERROR) << "SecCertificateCreateFromData failed: " << os_status;
+    return NULL;
+  }
+  scoped_cert.reset(certificate_ref);
+
+  return CreateFromHandle(
+     scoped_cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
+     X509Certificate::OSCertHandles());
 }
 
 void X509Certificate::Persist(Pickle* pickle) {
@@ -471,7 +700,7 @@
   // of sporadic crashes in the SecTrustEvaluate call below, way down inside
   // Apple's cert code, which we suspect are caused by a thread-safety issue.
   // So as a speculative fix allow only one thread to use SecTrust on this cert.
-  AutoLock lock(verification_lock_);
+  base::AutoLock lock(verification_lock_);
 
   SecTrustRef trust_ref = NULL;
   status = SecTrustCreateWithCertificates(cert_array, ssl_policy, &trust_ref);
@@ -934,6 +1163,7 @@
 
   CFArrayRef cert_chain = NULL;
   result = CopyCertChain(cert_handle_, &cert_chain);
+  ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain);
   if (result) {
     LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
     return chain.release();
@@ -947,7 +1177,6 @@
                          cert_chain,
                          CFRangeMake(1, chain_count - 1));
     }
-    CFRelease(cert_chain);
   }
 
   return chain.release();
diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc
index dba5ef3..54af784 100644
--- a/net/base/x509_certificate_unittest.cc
+++ b/net/base/x509_certificate_unittest.cc
@@ -659,9 +659,9 @@
 }
 #endif  // defined(OS_MACOSX)
 
-#if defined(USE_NSS) || defined(OS_WIN)
-// This test creates a signed cert from a private key and then verify content
-// of the certificate.
+#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+// This test creates a self-signed cert from a private key and then verify the
+// content of the certificate.
 TEST(X509CertificateTest, CreateSelfSigned) {
   scoped_ptr<base::RSAPrivateKey> private_key(
       base::RSAPrivateKey::Create(1024));
@@ -671,6 +671,102 @@
 
   EXPECT_EQ("subject", cert->subject().GetDisplayName());
   EXPECT_FALSE(cert->HasExpired());
+
+  const uint8 private_key_info[] = {
+    0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30,
+    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+    0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01,
+    0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b,
+    0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61,
+    0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08,
+    0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64,
+    0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4,
+    0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a,
+    0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f,
+    0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f,
+    0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17,
+    0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5,
+    0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff,
+    0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85,
+    0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9,
+    0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5,
+    0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18,
+    0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93,
+    0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01,
+    0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89,
+    0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb,
+    0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7,
+    0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd,
+    0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95,
+    0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6,
+    0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc,
+    0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e,
+    0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b,
+    0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed,
+    0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa,
+    0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38,
+    0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee,
+    0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e,
+    0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e,
+    0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46,
+    0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00,
+    0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c,
+    0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7,
+    0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82,
+    0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89,
+    0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42,
+    0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8,
+    0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2,
+    0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81,
+    0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1,
+    0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72,
+    0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f,
+    0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62,
+    0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c,
+    0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c,
+    0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6,
+    0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b,
+    0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04,
+    0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9,
+    0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda,
+    0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58,
+    0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93,
+    0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae,
+    0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35,
+    0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17,
+    0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41,
+    0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30,
+    0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1,
+    0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0,
+    0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d,
+    0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd,
+    0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69,
+    0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39,
+    0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7,
+    0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f,
+    0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35,
+    0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99,
+    0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6,
+    0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3,
+    0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb,
+    0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca,
+    0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3,
+    0xb1, 0xc5, 0x15, 0xf3
+  };
+
+  std::vector<uint8> input;
+  input.resize(sizeof(private_key_info));
+  memcpy(&input.front(), private_key_info, sizeof(private_key_info));
+
+  private_key.reset(base::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+  ASSERT_TRUE(private_key.get());
+
+  cert = net::X509Certificate::CreateSelfSigned(
+      private_key.get(), "CN=subject", 1, base::TimeDelta::FromDays(1));
+
+  EXPECT_EQ("subject", cert->subject().GetDisplayName());
+  EXPECT_FALSE(cert->HasExpired());
 }
 
 TEST(X509CertificateTest, GetDEREncoded) {
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
index 663563d..fed56e3 100644
--- a/net/base/x509_certificate_win.cc
+++ b/net/base/x509_certificate_win.cc
@@ -94,10 +94,9 @@
 int MapCertChainErrorStatusToCertStatus(DWORD error_status) {
   int cert_status = 0;
 
-  // CERT_TRUST_IS_NOT_TIME_NESTED means a subject certificate's time validity
-  // does not nest correctly within its issuer's time validity.
+  // We don't include CERT_TRUST_IS_NOT_TIME_NESTED because it's obsolete and
+  // we wouldn't consider it an error anyway
   const DWORD kDateInvalidErrors = CERT_TRUST_IS_NOT_TIME_VALID |
-                                   CERT_TRUST_IS_NOT_TIME_NESTED |
                                    CERT_TRUST_CTL_IS_NOT_TIME_VALID;
   if (error_status & kDateInvalidErrors)
     cert_status |= CERT_STATUS_DATE_INVALID;
@@ -146,6 +145,18 @@
   return cert_status;
 }
 
+void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded,
+                              SYSTEMTIME* system_time) {
+  system_time->wYear = exploded.year;
+  system_time->wMonth = exploded.month;
+  system_time->wDayOfWeek = exploded.day_of_week;
+  system_time->wDay = exploded.day_of_month;
+  system_time->wHour = exploded.hour;
+  system_time->wMinute = exploded.minute;
+  system_time->wSecond = exploded.second;
+  system_time->wMilliseconds = exploded.millisecond;
+}
+
 //-----------------------------------------------------------------------------
 
 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the
@@ -513,17 +524,17 @@
   DWORD encoded_subject_length = 0;
   if (!CertStrToName(
           X509_ASN_ENCODING,
-          const_cast<wchar_t*>(w_subject.c_str()),
+          w_subject.c_str(),
           CERT_X500_NAME_STR, NULL, NULL, &encoded_subject_length, NULL)) {
     return NULL;
   }
 
-  scoped_array<char> encoded_subject(new char[encoded_subject_length]);
+  scoped_array<BYTE> encoded_subject(new BYTE[encoded_subject_length]);
   if (!CertStrToName(
           X509_ASN_ENCODING,
-          const_cast<wchar_t*>(w_subject.c_str()),
+          w_subject.c_str(),
           CERT_X500_NAME_STR, NULL,
-          reinterpret_cast<BYTE*>(encoded_subject.get()),
+          encoded_subject.get(),
           &encoded_subject_length, NULL)) {
     return NULL;
   }
@@ -531,33 +542,32 @@
   CERT_NAME_BLOB subject_name;
   memset(&subject_name, 0, sizeof(subject_name));
   subject_name.cbData = encoded_subject_length;
-  subject_name.pbData = reinterpret_cast<BYTE*>(encoded_subject.get());
+  subject_name.pbData = encoded_subject.get();
 
   CRYPT_ALGORITHM_IDENTIFIER sign_algo;
   memset(&sign_algo, 0, sizeof(sign_algo));
   sign_algo.pszObjId = szOID_RSA_SHA1RSA;
 
-  base::Time not_valid = base::Time::Now() + valid_duration;
+  base::Time not_before = base::Time::Now();
+  base::Time not_after = not_before + valid_duration;
   base::Time::Exploded exploded;
-  not_valid.UTCExplode(&exploded);
 
-  // Create the system time struct representing our exploded time.
-  SYSTEMTIME system_time;
-  system_time.wYear = exploded.year;
-  system_time.wMonth = exploded.month;
-  system_time.wDayOfWeek = exploded.day_of_week;
-  system_time.wDay = exploded.day_of_month;
-  system_time.wHour = exploded.hour;
-  system_time.wMinute = exploded.minute;
-  system_time.wSecond = exploded.second;
-  system_time.wMilliseconds = exploded.millisecond;
+  // Create the system time structs representing our exploded times.
+  not_before.UTCExplode(&exploded);
+  SYSTEMTIME start_time;
+  ExplodedTimeToSystemTime(exploded, &start_time);
+  not_after.UTCExplode(&exploded);
+  SYSTEMTIME end_time;
+  ExplodedTimeToSystemTime(exploded, &end_time);
 
   PCCERT_CONTEXT cert_handle =
       CertCreateSelfSignCertificate(key->provider(), &subject_name,
-                                    CERT_CREATE_SELFSIGN_NO_KEY_INFO,
-                                    NULL, &sign_algo, 0, &system_time, 0);
+                                    CERT_CREATE_SELFSIGN_NO_KEY_INFO, NULL,
+                                    &sign_algo, &start_time, &end_time, NULL);
   DCHECK(cert_handle) << "Failed to create self-signed certificate: "
-                      << logging::GetLastSystemErrorCode();
+                      << GetLastError();
+  if (!cert_handle)
+    return NULL;
 
   X509Certificate* cert = CreateFromHandle(cert_handle,
                                            SOURCE_LONE_CERT_IMPORT,
diff --git a/net/base/x509_openssl_util.cc b/net/base/x509_openssl_util.cc
index 35871ad..fe3d27d 100644
--- a/net/base/x509_openssl_util.cc
+++ b/net/base/x509_openssl_util.cc
@@ -4,6 +4,8 @@
 
 #include "net/base/x509_openssl_util.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 #include "base/string_piece.h"
 #include "base/string_util.h"
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc
index 347dc0f..3f57a03 100644
--- a/net/disk_cache/backend_impl.cc
+++ b/net/disk_cache/backend_impl.cc
@@ -174,13 +174,16 @@
 
   // Field trials involve static objects so we have to do this only once.
   first = false;
-  scoped_refptr<base::FieldTrial> trial1(
-      new base::FieldTrial("CacheSize", 10));
   std::string group1 = base::StringPrintf("CacheSizeGroup_%d", size_group);
-  trial1->AppendGroup(group1, base::FieldTrial::kAllRemainingProbability);
+  int totalProbability = 10;
+  scoped_refptr<base::FieldTrial> trial1(
+      new base::FieldTrial("CacheSize", totalProbability, group1, 2011, 6, 30));
+  trial1->AppendGroup(group1, totalProbability);
 
+  // After June 30, 2011 builds, it will always be in default group.
   scoped_refptr<base::FieldTrial> trial2(
-      new base::FieldTrial("CacheThrottle", 100));
+      new base::FieldTrial(
+          "CacheThrottle", 100, "CacheThrottle_Default", 2011, 6, 30));
   int group2a = trial2->AppendGroup("CacheThrottle_On", 10);  // 10 % in.
   trial2->AppendGroup("CacheThrottle_Off", 10);  // 10 % control.
 
@@ -341,34 +344,6 @@
 
 // ------------------------------------------------------------------------
 
-// If the initialization of the cache fails, and force is true, we will discard
-// the whole cache and create a new one. In order to process a potentially large
-// number of files, we'll rename the cache folder to old_ + original_name +
-// number, (located on the same parent folder), and spawn a worker thread to
-// delete all the files on all the stale cache folders. The whole process can
-// still fail if we are not able to rename the cache folder (for instance due to
-// a sharing violation), and in that case a cache for this profile (on the
-// desired path) cannot be created.
-//
-// Static.
-int BackendImpl::CreateBackend(const FilePath& full_path, bool force,
-                               int max_bytes, net::CacheType type,
-                               uint32 flags, base::MessageLoopProxy* thread,
-                               net::NetLog* net_log, Backend** backend,
-                               CompletionCallback* callback) {
-  DCHECK(callback);
-  CacheCreator* creator = new CacheCreator(full_path, force, max_bytes, type,
-                                           flags, thread, net_log, backend,
-                                           callback);
-  // This object will self-destroy when finished.
-  return creator->Run();
-}
-
-int BackendImpl::Init(CompletionCallback* callback) {
-  background_queue_.Init(callback);
-  return net::ERR_IO_PENDING;
-}
-
 BackendImpl::BackendImpl(const FilePath& path,
                          base::MessageLoopProxy* cache_thread,
                          net::NetLog* net_log)
@@ -433,7 +408,33 @@
   }
 }
 
-// ------------------------------------------------------------------------
+// If the initialization of the cache fails, and force is true, we will discard
+// the whole cache and create a new one. In order to process a potentially large
+// number of files, we'll rename the cache folder to old_ + original_name +
+// number, (located on the same parent folder), and spawn a worker thread to
+// delete all the files on all the stale cache folders. The whole process can
+// still fail if we are not able to rename the cache folder (for instance due to
+// a sharing violation), and in that case a cache for this profile (on the
+// desired path) cannot be created.
+//
+// Static.
+int BackendImpl::CreateBackend(const FilePath& full_path, bool force,
+                               int max_bytes, net::CacheType type,
+                               uint32 flags, base::MessageLoopProxy* thread,
+                               net::NetLog* net_log, Backend** backend,
+                               CompletionCallback* callback) {
+  DCHECK(callback);
+  CacheCreator* creator = new CacheCreator(full_path, force, max_bytes, type,
+                                           flags, thread, net_log, backend,
+                                           callback);
+  // This object will self-destroy when finished.
+  return creator->Run();
+}
+
+int BackendImpl::Init(CompletionCallback* callback) {
+  background_queue_.Init(callback);
+  return net::ERR_IO_PENDING;
+}
 
 int BackendImpl::SyncInit() {
   DCHECK(!init_);
@@ -678,7 +679,8 @@
   uint32 hash = Hash(key);
   Trace("Open hash 0x%x", hash);
 
-  EntryImpl* cache_entry = MatchEntry(key, hash, false);
+  bool error;
+  EntryImpl* cache_entry = MatchEntry(key, hash, false, Addr(), &error);
   if (!cache_entry) {
     stats_.OnEvent(Stats::OPEN_MISS);
     return NULL;
@@ -712,11 +714,13 @@
   if (entry_address.is_initialized()) {
     // We have an entry already. It could be the one we are looking for, or just
     // a hash conflict.
-    EntryImpl* old_entry = MatchEntry(key, hash, false);
+    bool error;
+    EntryImpl* old_entry = MatchEntry(key, hash, false, Addr(), &error);
     if (old_entry)
       return ResurrectEntry(old_entry);
 
-    EntryImpl* parent_entry = MatchEntry(key, hash, true);
+    EntryImpl* parent_entry = MatchEntry(key, hash, true, Addr(), &error);
+    DCHECK(!error);
     if (parent_entry) {
       parent.swap(&parent_entry);
     } else if (data_->table[hash & mask_]) {
@@ -901,7 +905,9 @@
 void BackendImpl::InternalDoomEntry(EntryImpl* entry) {
   uint32 hash = entry->GetHash();
   std::string key = entry->GetKey();
-  EntryImpl* parent_entry = MatchEntry(key, hash, true);
+  Addr entry_addr = entry->entry()->address();
+  bool error;
+  EntryImpl* parent_entry = MatchEntry(key, hash, true, entry_addr, &error);
   CacheAddr child(entry->GetNextAddress());
 
   Trace("Doom entry 0x%p", entry);
@@ -912,7 +918,7 @@
   if (parent_entry) {
     parent_entry->SetNextAddress(Addr(child));
     parent_entry->Release();
-  } else {
+  } else if (!error) {
     data_->table[hash & mask_] = child;
   }
 
@@ -1141,7 +1147,7 @@
   if (!throttle_requests_)
     return;
 
-  const int kMaxNormalDelayMS = 100;
+  const int kMaxNormalDelayMS = 460;
 
   bool throttling = io_delay_ > kMaxNormalDelayMS;
 
@@ -1237,6 +1243,16 @@
     background_queue_.StopQueingOperations();
 }
 
+void BackendImpl::TrimForTest(bool empty) {
+  eviction_.SetTestMode();
+  eviction_.TrimCache(empty);
+}
+
+void BackendImpl::TrimDeletedListForTest(bool empty) {
+  eviction_.SetTestMode();
+  eviction_.TrimDeletedList(empty);
+}
+
 int BackendImpl::SelfCheck() {
   if (!init_) {
     LOG(ERROR) << "Init failed";
@@ -1458,6 +1474,7 @@
   int64 errors = stats_.GetCounter(Stats::FATAL_ERROR);
   int64 full_dooms = stats_.GetCounter(Stats::DOOM_CACHE);
   int64 partial_dooms = stats_.GetCounter(Stats::DOOM_RECENT);
+  int64 last_report = stats_.GetCounter(Stats::LAST_REPORT);
 
   PrepareForRestart();
   if (failure) {
@@ -1476,6 +1493,7 @@
     stats_.SetCounter(Stats::FATAL_ERROR, errors);
     stats_.SetCounter(Stats::DOOM_CACHE, full_dooms);
     stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms);
+    stats_.SetCounter(Stats::LAST_REPORT, last_report);
   }
 }
 
@@ -1557,16 +1575,28 @@
 }
 
 EntryImpl* BackendImpl::MatchEntry(const std::string& key, uint32 hash,
-                                   bool find_parent) {
+                                   bool find_parent, Addr entry_addr,
+                                   bool* match_error) {
   Addr address(data_->table[hash & mask_]);
   scoped_refptr<EntryImpl> cache_entry, parent_entry;
   EntryImpl* tmp = NULL;
   bool found = false;
+  std::set<CacheAddr> visited;
+  *match_error = false;
 
   for (;;) {
     if (disabled_)
       break;
 
+    if (visited.find(address.value()) != visited.end()) {
+      // It's possible for a buggy version of the code to write a loop. Just
+      // break it.
+      Trace("Hash collision loop 0x%x", address.value());
+      address.set_value(0);
+      parent_entry->SetNextAddress(address);
+    }
+    visited.insert(address.value());
+
     if (!address.is_initialized()) {
       if (find_parent)
         found = true;
@@ -1602,6 +1632,7 @@
 
       // Restart the search.
       address.set_value(data_->table[hash & mask_]);
+      visited.clear();
       continue;
     }
 
@@ -1610,6 +1641,11 @@
       if (!cache_entry->Update())
         cache_entry = NULL;
       found = true;
+      if (find_parent && entry_addr.value() != address.value()) {
+        Trace("Entry not on the index 0x%x", address.value());
+        *match_error = true;
+        parent_entry = NULL;
+      }
       break;
     }
     if (!cache_entry->Update())
@@ -1667,7 +1703,7 @@
           OpenFollowingEntryFromList(forward, iterator->list,
                                      &iterator->nodes[i], &temp);
       } else {
-        temp = GetEnumeratedEntry(iterator->nodes[i], false);
+        temp = GetEnumeratedEntry(iterator->nodes[i]);
       }
 
       entries[i].swap(&temp);  // The entry was already addref'd.
@@ -1724,7 +1760,7 @@
   Rankings::ScopedRankingsBlock next(&rankings_, next_block);
   *from_entry = NULL;
 
-  *next_entry = GetEnumeratedEntry(next.get(), false);
+  *next_entry = GetEnumeratedEntry(next.get());
   if (!*next_entry)
     return false;
 
@@ -1732,8 +1768,7 @@
   return true;
 }
 
-EntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next,
-                                           bool to_evict) {
+EntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next) {
   if (!next || disabled_)
     return NULL;
 
@@ -1748,12 +1783,19 @@
     return NULL;
   }
 
-  // There is no need to store the entry to disk if we want to delete it.
-  if (!to_evict && !entry->Update()) {
+  if (!entry->Update()) {
     entry->Release();
     return NULL;
   }
 
+  // Note that it is unfortunate (but possible) for this entry to be clean, but
+  // not actually the real entry. In other words, we could have lost this entry
+  // from the index, and it could have been replaced with a newer one. It's not
+  // worth checking that this entry is "the real one", so we just return it and
+  // let the enumeration continue; this entry will be evicted at some point, and
+  // the regular path will work with the real entry. With time, this problem
+  // will disasappear because this scenario is just a bug.
+
   // Make sure that we save the key for later.
   entry->GetKey();
 
@@ -1805,7 +1847,7 @@
 void BackendImpl::DestroyInvalidEntryFromEnumeration(EntryImpl* entry) {
   std::string key = entry->GetKey();
   entry->SetPointerForInvalidEntry(GetCurrentEntryId());
-  CacheAddr next_entry = entry->entry()->Data()->next;
+  CacheAddr next_entry = entry->GetNextAddress();
   if (!next_entry) {
     DestroyInvalidEntry(entry);
     entry->Release();
@@ -1898,6 +1940,9 @@
             static_cast<int>(stats_.GetCounter(Stats::DOOM_CACHE)));
   CACHE_UMA(COUNTS_10000, "TotalDoomRecentEntries", 0,
             static_cast<int>(stats_.GetCounter(Stats::DOOM_RECENT)));
+  stats_.SetCounter(Stats::FATAL_ERROR, 0);
+  stats_.SetCounter(Stats::DOOM_CACHE, 0);
+  stats_.SetCounter(Stats::DOOM_RECENT, 0);
 
   int64 total_hours = stats_.GetCounter(Stats::TIMER) / 120;
   if (!data_->header.create_time || !data_->header.lru.filled) {
diff --git a/net/disk_cache/backend_impl.h b/net/disk_cache/backend_impl.h
index 74a1eaf..be491e6 100644
--- a/net/disk_cache/backend_impl.h
+++ b/net/disk_cache/backend_impl.h
@@ -240,6 +240,14 @@
   // Starts or stops throttling requests.
   void ThrottleRequestsForTest(bool throttle);
 
+  // Trims an entry (all if |empty| is true) from the list of deleted
+  // entries. This method should be called directly on the cache thread.
+  void TrimForTest(bool empty);
+
+  // Trims an entry (all if |empty| is true) from the list of deleted
+  // entries. This method should be called directly on the cache thread.
+  void TrimDeletedListForTest(bool empty);
+
   // Peforms a simple self-check, and returns the number of dirty items
   // or an error code (negative value).
   int SelfCheck();
@@ -280,8 +288,13 @@
 
   // Returns a given entry from the cache. The entry to match is determined by
   // key and hash, and the returned entry may be the matched one or it's parent
-  // on the list of entries with the same hash (or bucket).
-  EntryImpl* MatchEntry(const std::string& key, uint32 hash, bool find_parent);
+  // on the list of entries with the same hash (or bucket). To look for a parent
+  // of a given entry, |entry_addr| should be grabbed from that entry, so that
+  // if it doesn't match the entry on the index, we know that it was replaced
+  // with a new entry; in this case |*match_error| will be set to true and the
+  // return value will be NULL.
+  EntryImpl* MatchEntry(const std::string& key, uint32 hash, bool find_parent,
+                        Addr entry_addr, bool* match_error);
 
   // Opens the next or previous entry on a cache iteration.
   EntryImpl* OpenFollowingEntry(bool forward, void** iter);
@@ -293,9 +306,8 @@
                                   CacheRankingsBlock** from_entry,
                                   EntryImpl** next_entry);
 
-  // Returns the entry that is pointed by |next|. If we are trimming the cache,
-  // |to_evict| should be true so that we don't perform extra disk writes.
-  EntryImpl* GetEnumeratedEntry(CacheRankingsBlock* next, bool to_evict);
+  // Returns the entry that is pointed by |next|.
+  EntryImpl* GetEnumeratedEntry(CacheRankingsBlock* next);
 
   // Re-opens an entry that was previously deleted.
   EntryImpl* ResurrectEntry(EntryImpl* deleted_entry);
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index 05f17f6..1760837 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -49,6 +49,7 @@
   void BackendRecoverInsert();
   void BackendRecoverRemove();
   void BackendInvalidEntry2();
+  void BackendInvalidEntry3();
   void BackendNotMarkedButDirty(const std::string& name);
   void BackendDoomAll();
   void BackendDoomAll2();
@@ -1318,7 +1319,96 @@
   BackendInvalidEntry2();
 }
 
+// Tests that we don't crash or hang when enumerating this cache.
+void DiskCacheBackendTest::BackendInvalidEntry3() {
+  SetMask(0x1);  // 2-entry table.
+  SetMaxSize(0x3000);  // 12 kB.
+  DisableFirstCleanup();
+  InitCache();
+
+  disk_cache::Entry* entry;
+  void* iter = NULL;
+  while (OpenNextEntry(&iter, &entry) == net::OK) {
+    entry->Close();
+  }
+}
+
+TEST_F(DiskCacheBackendTest, InvalidEntry3) {
+  ASSERT_TRUE(CopyTestCache("dirty_entry3"));
+  BackendInvalidEntry3();
+}
+
 TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry3) {
+  ASSERT_TRUE(CopyTestCache("dirty_entry4"));
+  SetNewEviction();
+  BackendInvalidEntry3();
+  DisableIntegrityCheck();
+}
+
+// Test that we handle a dirty entry on the LRU list, already replaced with
+// the same key, and with hash collisions.
+TEST_F(DiskCacheBackendTest, InvalidEntry4) {
+  ASSERT_TRUE(CopyTestCache("dirty_entry3"));
+  SetMask(0x1);  // 2-entry table.
+  SetMaxSize(0x3000);  // 12 kB.
+  DisableFirstCleanup();
+  InitCache();
+
+  TrimForTest(false);
+}
+
+// Test that we handle a dirty entry on the deleted list, already replaced with
+// the same key, and with hash collisions.
+TEST_F(DiskCacheBackendTest, InvalidEntry5) {
+  ASSERT_TRUE(CopyTestCache("dirty_entry4"));
+  SetNewEviction();
+  SetMask(0x1);  // 2-entry table.
+  SetMaxSize(0x3000);  // 12 kB.
+  DisableFirstCleanup();
+  InitCache();
+
+  TrimDeletedListForTest(false);
+}
+
+// Tests that we don't hang when there is a loop on the hash collision list.
+// The test cache could be a result of bug 69135.
+TEST_F(DiskCacheBackendTest, BadNextEntry1) {
+  ASSERT_TRUE(CopyTestCache("list_loop2"));
+  SetMask(0x1);  // 2-entry table.
+  SetMaxSize(0x3000);  // 12 kB.
+  DisableFirstCleanup();
+  InitCache();
+
+  // The second entry points at itselft, and the first entry is not accessible
+  // though the index, but it is at the head of the LRU.
+
+  disk_cache::Entry* entry;
+  ASSERT_EQ(net::OK, CreateEntry("The first key", &entry));
+  entry->Close();
+
+  TrimForTest(false);
+  TrimForTest(false);
+  ASSERT_EQ(net::OK, OpenEntry("The first key", &entry));
+  entry->Close();
+  EXPECT_EQ(1, cache_->GetEntryCount());
+}
+
+// Tests that we don't hang when there is a loop on the hash collision list.
+// The test cache could be a result of bug 69135.
+TEST_F(DiskCacheBackendTest, BadNextEntry2) {
+  ASSERT_TRUE(CopyTestCache("list_loop3"));
+  SetMask(0x1);  // 2-entry table.
+  SetMaxSize(0x3000);  // 12 kB.
+  DisableFirstCleanup();
+  InitCache();
+
+  // There is a wide loop of 5 entries.
+
+  disk_cache::Entry* entry;
+  ASSERT_NE(net::OK, OpenEntry("Not present key", &entry));
+}
+
+TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) {
   ASSERT_TRUE(CopyTestCache("bad_rankings3"));
   DisableFirstCleanup();
   SetNewEviction();
diff --git a/net/disk_cache/bitmap.cc b/net/disk_cache/bitmap.cc
index e025090..6c9aceb 100644
--- a/net/disk_cache/bitmap.cc
+++ b/net/disk_cache/bitmap.cc
@@ -4,6 +4,8 @@
 
 #include "net/disk_cache/bitmap.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 
 namespace {
@@ -38,6 +40,31 @@
 
 namespace disk_cache {
 
+Bitmap::Bitmap(int num_bits, bool clear_bits)
+    : num_bits_(num_bits),
+      array_size_(RequiredArraySize(num_bits)),
+      alloc_(true) {
+  map_ = new uint32[array_size_];
+
+  // Initialize all of the bits.
+  if (clear_bits)
+    Clear();
+}
+
+Bitmap::Bitmap(uint32* map, int num_bits, int num_words)
+    : map_(map),
+      num_bits_(num_bits),
+      // If size is larger than necessary, trim because array_size_ is used
+      // as a bound by various methods.
+      array_size_(std::min(RequiredArraySize(num_bits), num_words)),
+      alloc_(false) {
+}
+
+Bitmap::~Bitmap() {
+  if (alloc_)
+    delete [] map_;
+}
+
 void Bitmap::Resize(int num_bits, bool clear_bits) {
   DCHECK(alloc_ || !map_);
   const int old_maxsize = num_bits_;
@@ -105,24 +132,6 @@
   memcpy(map_, map, std::min(size, array_size_) * sizeof(*map_));
 }
 
-void Bitmap::SetWordBits(int start, int len, bool value) {
-  DCHECK_LT(len, kIntBits);
-  DCHECK_GE(len, 0);
-  if (!len)
-    return;
-
-  int word = start / kIntBits;
-  int offset = start % kIntBits;
-
-  uint32 to_add = 0xffffffff << len;
-  to_add = (~to_add) << offset;
-  if (value) {
-    map_[word] |= to_add;
-  } else {
-    map_[word] &= ~to_add;
-  }
-}
-
 void Bitmap::SetRange(int begin, int end, bool value) {
   DCHECK_LE(begin, end);
   int start_offset = begin & (kIntBits - 1);
@@ -281,4 +290,22 @@
   return end - *index;
 }
 
+void Bitmap::SetWordBits(int start, int len, bool value) {
+  DCHECK_LT(len, kIntBits);
+  DCHECK_GE(len, 0);
+  if (!len)
+    return;
+
+  int word = start / kIntBits;
+  int offset = start % kIntBits;
+
+  uint32 to_add = 0xffffffff << len;
+  to_add = (~to_add) << offset;
+  if (value) {
+    map_[word] |= to_add;
+  } else {
+    map_[word] &= ~to_add;
+  }
+}
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/bitmap.h b/net/disk_cache/bitmap.h
index 8e24e15..8b3324c 100644
--- a/net/disk_cache/bitmap.h
+++ b/net/disk_cache/bitmap.h
@@ -6,8 +6,6 @@
 #define NET_DISK_CACHE_BITMAP_H_
 #pragma once
 
-#include <algorithm>
-
 #include "base/basictypes.h"
 
 namespace disk_cache {
@@ -19,30 +17,14 @@
 
   // This constructor will allocate on a uint32 boundary. If |clear_bits| is
   // false, the bitmap bits will not be initialized.
-  Bitmap(int num_bits, bool clear_bits)
-     : num_bits_(num_bits), array_size_(RequiredArraySize(num_bits)),
-       alloc_(true) {
-    map_ = new uint32[array_size_];
-
-    // Initialize all of the bits.
-    if (clear_bits)
-      Clear();
-  }
+  Bitmap(int num_bits, bool clear_bits);
 
   // Constructs a Bitmap with the actual storage provided by the caller. |map|
   // has to be valid until this object destruction. |num_bits| is the number of
   // bits in the bitmap, and |num_words| is the size of |map| in 32-bit words.
-  Bitmap(uint32* map, int num_bits, int num_words)
-     : map_(map), num_bits_(num_bits),
-       // If size is larger than necessary, trim because array_size_ is used
-       // as a bound by various methods.
-       array_size_(std::min(RequiredArraySize(num_bits), num_words)),
-       alloc_(false) {}
+  Bitmap(uint32* map, int num_bits, int num_words);
 
-  ~Bitmap() {
-    if (alloc_)
-      delete[] map_;
-  }
+  ~Bitmap();
 
   // Resizes the bitmap.
   // If |num_bits| < Size(), the extra bits will be discarded.
diff --git a/net/disk_cache/block_files.cc b/net/disk_cache/block_files.cc
index 3eb4e35..faa9706 100644
--- a/net/disk_cache/block_files.cc
+++ b/net/disk_cache/block_files.cc
@@ -220,6 +220,91 @@
   return true;
 }
 
+MappedFile* BlockFiles::GetFile(Addr address) {
+  DCHECK(thread_checker_->CalledOnValidThread());
+  DCHECK(block_files_.size() >= 4);
+  DCHECK(address.is_block_file() || !address.is_initialized());
+  if (!address.is_initialized())
+    return NULL;
+
+  int file_index = address.FileNumber();
+  if (static_cast<unsigned int>(file_index) >= block_files_.size() ||
+      !block_files_[file_index]) {
+    // We need to open the file
+    if (!OpenBlockFile(file_index))
+      return NULL;
+  }
+  DCHECK(block_files_.size() >= static_cast<unsigned int>(file_index));
+  return block_files_[file_index];
+}
+
+bool BlockFiles::CreateBlock(FileType block_type, int block_count,
+                             Addr* block_address) {
+  DCHECK(thread_checker_->CalledOnValidThread());
+  if (block_type < RANKINGS || block_type > BLOCK_4K ||
+      block_count < 1 || block_count > 4)
+    return false;
+  if (!init_)
+    return false;
+
+  MappedFile* file = FileForNewBlock(block_type, block_count);
+  if (!file)
+    return false;
+
+  BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer());
+
+  int target_size = 0;
+  for (int i = block_count; i <= 4; i++) {
+    if (header->empty[i - 1]) {
+      target_size = i;
+      break;
+    }
+  }
+
+  DCHECK(target_size);
+  int index;
+  if (!CreateMapBlock(target_size, block_count, header, &index))
+    return false;
+
+  Addr address(block_type, block_count, header->this_file, index);
+  block_address->set_value(address.value());
+  Trace("CreateBlock 0x%x", address.value());
+  return true;
+}
+
+void BlockFiles::DeleteBlock(Addr address, bool deep) {
+  DCHECK(thread_checker_->CalledOnValidThread());
+  if (!address.is_initialized() || address.is_separate_file())
+    return;
+
+  if (!zero_buffer_) {
+    zero_buffer_ = new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4];
+    memset(zero_buffer_, 0, Addr::BlockSizeForFileType(BLOCK_4K) * 4);
+  }
+  MappedFile* file = GetFile(address);
+  if (!file)
+    return;
+
+  Trace("DeleteBlock 0x%x", address.value());
+
+  BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer());
+  DeleteMapBlock(address.start_block(), address.num_blocks(), header);
+
+  size_t size = address.BlockSize() * address.num_blocks();
+  size_t offset = address.start_block() * address.BlockSize() +
+                  kBlockHeaderSize;
+  if (deep)
+    file->Write(zero_buffer_, size, offset);
+
+  if (!header->num_entries) {
+    // This file is now empty. Let's try to delete it.
+    FileType type = Addr::RequiredFileType(header->entry_size);
+    if (Addr::BlockSizeForFileType(RANKINGS) == header->entry_size)
+      type = RANKINGS;
+    RemoveEmptyFile(type);
+  }
+}
+
 void BlockFiles::CloseFiles() {
   if (init_) {
     DCHECK(thread_checker_->CalledOnValidThread());
@@ -346,24 +431,6 @@
   return true;
 }
 
-MappedFile* BlockFiles::GetFile(Addr address) {
-  DCHECK(thread_checker_->CalledOnValidThread());
-  DCHECK(block_files_.size() >= 4);
-  DCHECK(address.is_block_file() || !address.is_initialized());
-  if (!address.is_initialized())
-    return NULL;
-
-  int file_index = address.FileNumber();
-  if (static_cast<unsigned int>(file_index) >= block_files_.size() ||
-      !block_files_[file_index]) {
-    // We need to open the file
-    if (!OpenBlockFile(file_index))
-      return NULL;
-  }
-  DCHECK(block_files_.size() >= static_cast<unsigned int>(file_index));
-  return block_files_[file_index];
-}
-
 bool BlockFiles::GrowBlockFile(MappedFile* file, BlockFileHeader* header) {
   if (kMaxBlocks == header->max_entries)
     return false;
@@ -489,73 +556,6 @@
   }
 }
 
-bool BlockFiles::CreateBlock(FileType block_type, int block_count,
-                             Addr* block_address) {
-  DCHECK(thread_checker_->CalledOnValidThread());
-  if (block_type < RANKINGS || block_type > BLOCK_4K ||
-      block_count < 1 || block_count > 4)
-    return false;
-  if (!init_)
-    return false;
-
-  MappedFile* file = FileForNewBlock(block_type, block_count);
-  if (!file)
-    return false;
-
-  BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer());
-
-  int target_size = 0;
-  for (int i = block_count; i <= 4; i++) {
-    if (header->empty[i - 1]) {
-      target_size = i;
-      break;
-    }
-  }
-
-  DCHECK(target_size);
-  int index;
-  if (!CreateMapBlock(target_size, block_count, header, &index))
-    return false;
-
-  Addr address(block_type, block_count, header->this_file, index);
-  block_address->set_value(address.value());
-  Trace("CreateBlock 0x%x", address.value());
-  return true;
-}
-
-void BlockFiles::DeleteBlock(Addr address, bool deep) {
-  DCHECK(thread_checker_->CalledOnValidThread());
-  if (!address.is_initialized() || address.is_separate_file())
-    return;
-
-  if (!zero_buffer_) {
-    zero_buffer_ = new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4];
-    memset(zero_buffer_, 0, Addr::BlockSizeForFileType(BLOCK_4K) * 4);
-  }
-  MappedFile* file = GetFile(address);
-  if (!file)
-    return;
-
-  Trace("DeleteBlock 0x%x", address.value());
-
-  BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer());
-  DeleteMapBlock(address.start_block(), address.num_blocks(), header);
-
-  size_t size = address.BlockSize() * address.num_blocks();
-  size_t offset = address.start_block() * address.BlockSize() +
-                  kBlockHeaderSize;
-  if (deep)
-    file->Write(zero_buffer_, size, offset);
-
-  if (!header->num_entries) {
-    // This file is now empty. Let's try to delete it.
-    FileType type = Addr::RequiredFileType(header->entry_size);
-    if (Addr::BlockSizeForFileType(RANKINGS) == header->entry_size)
-      type = RANKINGS;
-    RemoveEmptyFile(type);
-  }
-}
-
 bool BlockFiles::FixBlockFileHeader(MappedFile* file) {
   BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer());
   int file_size = static_cast<int>(file->GetLength());
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc
index 6c9b91c..41d1caf 100644
--- a/net/disk_cache/disk_cache_test_base.cc
+++ b/net/disk_cache/disk_cache_test_base.cc
@@ -15,15 +15,25 @@
   MessageLoop::current()->RunAllPending();
 }
 
-void DiskCacheTestWithCache::SetMaxSize(int size) {
-  size_ = size;
-  if (cache_impl_)
-    EXPECT_TRUE(cache_impl_->SetMaxSize(size));
-
-  if (mem_cache_)
-    EXPECT_TRUE(mem_cache_->SetMaxSize(size));
+DiskCacheTestWithCache::DiskCacheTestWithCache()
+    : cache_(NULL),
+      cache_impl_(NULL),
+      mem_cache_(NULL),
+      mask_(0),
+      size_(0),
+      type_(net::DISK_CACHE),
+      memory_only_(false),
+      implementation_(false),
+      force_creation_(false),
+      new_eviction_(false),
+      first_cleanup_(true),
+      integrity_(true),
+      use_current_thread_(false),
+      cache_thread_("CacheThread") {
 }
 
+DiskCacheTestWithCache::~DiskCacheTestWithCache() {}
+
 void DiskCacheTestWithCache::InitCache() {
   if (mask_ || new_eviction_)
     implementation_ = true;
@@ -38,86 +48,6 @@
     ASSERT_EQ(0, cache_->GetEntryCount());
 }
 
-void DiskCacheTestWithCache::InitMemoryCache() {
-  if (!implementation_) {
-    cache_ = disk_cache::MemBackendImpl::CreateBackend(size_);
-    return;
-  }
-
-  mem_cache_ = new disk_cache::MemBackendImpl();
-  cache_ = mem_cache_;
-  ASSERT_TRUE(NULL != cache_);
-
-  if (size_)
-    EXPECT_TRUE(mem_cache_->SetMaxSize(size_));
-
-  ASSERT_TRUE(mem_cache_->Init());
-}
-
-void DiskCacheTestWithCache::InitDiskCache() {
-  FilePath path = GetCacheFilePath();
-  if (first_cleanup_)
-    ASSERT_TRUE(DeleteCache(path));
-
-  if (!cache_thread_.IsRunning()) {
-    EXPECT_TRUE(cache_thread_.StartWithOptions(
-                    base::Thread::Options(MessageLoop::TYPE_IO, 0)));
-  }
-  ASSERT_TRUE(cache_thread_.message_loop() != NULL);
-
-  if (implementation_)
-    return InitDiskCacheImpl(path);
-
-  scoped_refptr<base::MessageLoopProxy> thread =
-      use_current_thread_ ? base::MessageLoopProxy::CreateForCurrentThread() :
-                            cache_thread_.message_loop_proxy();
-
-  TestCompletionCallback cb;
-  int rv = disk_cache::BackendImpl::CreateBackend(
-               path, force_creation_, size_, type_,
-               disk_cache::kNoRandom, thread, NULL, &cache_, &cb);
-  ASSERT_EQ(net::OK, cb.GetResult(rv));
-}
-
-void DiskCacheTestWithCache::InitDiskCacheImpl(const FilePath& path) {
-  scoped_refptr<base::MessageLoopProxy> thread =
-      use_current_thread_ ? base::MessageLoopProxy::CreateForCurrentThread() :
-                            cache_thread_.message_loop_proxy();
-  if (mask_)
-    cache_impl_ = new disk_cache::BackendImpl(path, mask_, thread, NULL);
-  else
-    cache_impl_ = new disk_cache::BackendImpl(path, thread, NULL);
-
-  cache_ = cache_impl_;
-  ASSERT_TRUE(NULL != cache_);
-
-  if (size_)
-    EXPECT_TRUE(cache_impl_->SetMaxSize(size_));
-
-  if (new_eviction_)
-    cache_impl_->SetNewEviction();
-
-  cache_impl_->SetType(type_);
-  cache_impl_->SetFlags(disk_cache::kNoRandom);
-  TestCompletionCallback cb;
-  int rv = cache_impl_->Init(&cb);
-  ASSERT_EQ(net::OK, cb.GetResult(rv));
-}
-
-void DiskCacheTestWithCache::TearDown() {
-  MessageLoop::current()->RunAllPending();
-  delete cache_;
-  if (cache_thread_.IsRunning())
-    cache_thread_.Stop();
-
-  if (!memory_only_ && integrity_) {
-    FilePath path = GetCacheFilePath();
-    EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_));
-  }
-
-  PlatformTest::TearDown();
-}
-
 // We are expected to leak memory when simulating crashes.
 void DiskCacheTestWithCache::SimulateCrash() {
   ASSERT_TRUE(implementation_ && !memory_only_);
@@ -138,6 +68,15 @@
   cache_impl_->SetUnitTestMode();
 }
 
+void DiskCacheTestWithCache::SetMaxSize(int size) {
+  size_ = size;
+  if (cache_impl_)
+    EXPECT_TRUE(cache_impl_->SetMaxSize(size));
+
+  if (mem_cache_)
+    EXPECT_TRUE(mem_cache_->SetMaxSize(size));
+}
+
 int DiskCacheTestWithCache::OpenEntry(const std::string& key,
                                       disk_cache::Entry** entry) {
   TestCompletionCallback cb;
@@ -236,3 +175,112 @@
   int rv = entry->WriteSparseData(offset, buf, len, &cb);
   return cb.GetResult(rv);
 }
+
+// Simple task to run part of a test from the cache thread.
+class TrimTask : public Task {
+ public:
+  TrimTask(disk_cache::BackendImpl* backend, bool deleted, bool empty)
+      : backend_(backend),
+        deleted_(deleted),
+        empty_(empty) {}
+
+  virtual void Run() {
+    if (deleted_)
+      backend_->TrimDeletedListForTest(empty_);
+    else
+      backend_->TrimForTest(empty_);
+  }
+
+ protected:
+  disk_cache::BackendImpl* backend_;
+  bool deleted_;
+  bool empty_;
+};
+
+void DiskCacheTestWithCache::TrimForTest(bool empty) {
+  RunTaskForTest(new TrimTask(cache_impl_, false, empty));
+}
+
+void DiskCacheTestWithCache::TrimDeletedListForTest(bool empty) {
+  RunTaskForTest(new TrimTask(cache_impl_, true, empty));
+}
+
+void DiskCacheTestWithCache::TearDown() {
+  MessageLoop::current()->RunAllPending();
+  delete cache_;
+  if (cache_thread_.IsRunning())
+    cache_thread_.Stop();
+
+  if (!memory_only_ && integrity_) {
+    FilePath path = GetCacheFilePath();
+    EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_));
+  }
+
+  PlatformTest::TearDown();
+}
+
+void DiskCacheTestWithCache::InitMemoryCache() {
+  if (!implementation_) {
+    cache_ = disk_cache::MemBackendImpl::CreateBackend(size_);
+    return;
+  }
+
+  mem_cache_ = new disk_cache::MemBackendImpl();
+  cache_ = mem_cache_;
+  ASSERT_TRUE(NULL != cache_);
+
+  if (size_)
+    EXPECT_TRUE(mem_cache_->SetMaxSize(size_));
+
+  ASSERT_TRUE(mem_cache_->Init());
+}
+
+void DiskCacheTestWithCache::InitDiskCache() {
+  FilePath path = GetCacheFilePath();
+  if (first_cleanup_)
+    ASSERT_TRUE(DeleteCache(path));
+
+  if (!cache_thread_.IsRunning()) {
+    EXPECT_TRUE(cache_thread_.StartWithOptions(
+                    base::Thread::Options(MessageLoop::TYPE_IO, 0)));
+  }
+  ASSERT_TRUE(cache_thread_.message_loop() != NULL);
+
+  if (implementation_)
+    return InitDiskCacheImpl(path);
+
+  scoped_refptr<base::MessageLoopProxy> thread =
+      use_current_thread_ ? base::MessageLoopProxy::CreateForCurrentThread() :
+                            cache_thread_.message_loop_proxy();
+
+  TestCompletionCallback cb;
+  int rv = disk_cache::BackendImpl::CreateBackend(
+               path, force_creation_, size_, type_,
+               disk_cache::kNoRandom, thread, NULL, &cache_, &cb);
+  ASSERT_EQ(net::OK, cb.GetResult(rv));
+}
+
+void DiskCacheTestWithCache::InitDiskCacheImpl(const FilePath& path) {
+  scoped_refptr<base::MessageLoopProxy> thread =
+      use_current_thread_ ? base::MessageLoopProxy::CreateForCurrentThread() :
+                            cache_thread_.message_loop_proxy();
+  if (mask_)
+    cache_impl_ = new disk_cache::BackendImpl(path, mask_, thread, NULL);
+  else
+    cache_impl_ = new disk_cache::BackendImpl(path, thread, NULL);
+
+  cache_ = cache_impl_;
+  ASSERT_TRUE(NULL != cache_);
+
+  if (size_)
+    EXPECT_TRUE(cache_impl_->SetMaxSize(size_));
+
+  if (new_eviction_)
+    cache_impl_->SetNewEviction();
+
+  cache_impl_->SetType(type_);
+  cache_impl_->SetFlags(disk_cache::kNoRandom);
+  TestCompletionCallback cb;
+  int rv = cache_impl_->Init(&cb);
+  ASSERT_EQ(net::OK, cb.GetResult(rv));
+}
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h
index 13b3879..f535896 100644
--- a/net/disk_cache/disk_cache_test_base.h
+++ b/net/disk_cache/disk_cache_test_base.h
@@ -40,15 +40,10 @@
 // Provides basic support for cache related tests.
 class DiskCacheTestWithCache : public DiskCacheTest {
  protected:
-  DiskCacheTestWithCache()
-      : cache_(NULL), cache_impl_(NULL), mem_cache_(NULL), mask_(0), size_(0),
-        type_(net::DISK_CACHE), memory_only_(false), implementation_(false),
-        force_creation_(false), new_eviction_(false), first_cleanup_(true),
-        integrity_(true), use_current_thread_(false),
-        cache_thread_("CacheThread") {}
+  DiskCacheTestWithCache();
+  virtual ~DiskCacheTestWithCache();
 
   void InitCache();
-  virtual void TearDown();
   void SimulateCrash();
   void SetTestMode();
 
@@ -112,6 +107,17 @@
   int WriteSparseData(disk_cache::Entry* entry, int64 offset,
                       net::IOBuffer* buf, int len);
 
+  // Asks the cache to trim a an entry. If |empty| is true, the whole entry is
+  // deleted.
+  void TrimForTest(bool empty);
+
+  // Asks the cache to trim a an entry from the deleted list. If |empty| is
+  // true, the whole entry is deleted.
+  void TrimDeletedListForTest(bool empty);
+
+  // DiskCacheTest:
+  virtual void TearDown();
+
   // cache_ will always have a valid object, regardless of how the cache was
   // initialized. The implementation pointers can be NULL.
   disk_cache::Backend* cache_;
diff --git a/net/disk_cache/disk_cache_test_util.h b/net/disk_cache/disk_cache_test_util.h
index a0dbf21..f957447 100644
--- a/net/disk_cache/disk_cache_test_util.h
+++ b/net/disk_cache/disk_cache_test_util.h
@@ -61,8 +61,8 @@
   explicit CallbackTest(bool reuse);
   virtual ~CallbackTest();
 
-  virtual void RunWithParams(const Tuple1<int>& params);
   int result() const { return result_; }
+  virtual void RunWithParams(const Tuple1<int>& params);
 
  private:
   int result_;
diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc
index ff05e11..57d4d83 100644
--- a/net/disk_cache/entry_impl.cc
+++ b/net/disk_cache/entry_impl.cc
@@ -589,6 +589,7 @@
 }
 
 void EntryImpl::SetNextAddress(Addr address) {
+  DCHECK_NE(address.value(), entry_.address().value());
   entry_.Data()->next = address.value();
   bool success = entry_.Store();
   DCHECK(success);
diff --git a/net/disk_cache/eviction.cc b/net/disk_cache/eviction.cc
index 0173c16..6ba053b 100644
--- a/net/disk_cache/eviction.cc
+++ b/net/disk_cache/eviction.cc
@@ -82,6 +82,7 @@
   delay_trim_ = false;
   trim_delays_ = 0;
   init_ = true;
+  test_mode_ = false;
   in_experiment_ = (header_->experiment == EXPERIMENT_DELETED_LIST_IN);
 }
 
@@ -125,11 +126,13 @@
       // This entry is not being used by anybody.
       // Do NOT use node as an iterator after this point.
       rankings_->TrackRankingsBlock(node.get(), false);
-      if (!EvictEntry(node.get(), empty))
+      if (!EvictEntry(node.get(), empty) && !test_mode_)
         continue;
 
       if (!empty) {
         backend_->OnEvent(Stats::TRIM_ENTRY);
+        if (test_mode_)
+          break;
 
         if ((TimeTicks::Now() - start).InMilliseconds() > 20) {
           MessageLoop::current()->PostTask(FROM_HERE,
@@ -182,6 +185,15 @@
     return OnDestroyEntryV2(entry);
 }
 
+void Eviction::SetTestMode() {
+  test_mode_ = true;
+}
+
+void Eviction::TrimDeletedList(bool empty) {
+  DCHECK(test_mode_ && new_eviction_);
+  TrimDeleted(empty);
+}
+
 void Eviction::PostDelayedTrim() {
   // Prevent posting multiple tasks.
   if (delay_trim_)
@@ -242,7 +254,7 @@
 }
 
 bool Eviction::EvictEntry(CacheRankingsBlock* node, bool empty) {
-  EntryImpl* entry = backend_->GetEnumeratedEntry(node, true);
+  EntryImpl* entry = backend_->GetEnumeratedEntry(node);
   if (!entry) {
     Trace("NewEntry failed on Trim 0x%x", node->address().value());
     return false;
@@ -320,9 +332,12 @@
         // This entry is not being used by anybody.
         // Do NOT use node as an iterator after this point.
         rankings_->TrackRankingsBlock(node.get(), false);
-        if (!EvictEntry(node.get(), empty))
+        if (!EvictEntry(node.get(), empty) && !test_mode_)
           continue;
 
+        if (!empty && test_mode_)
+          break;
+
         if (!empty && (TimeTicks::Now() - start).InMilliseconds() > 20) {
           MessageLoop::current()->PostTask(FROM_HERE,
               factory_.NewRunnableMethod(&Eviction::TrimCache, false));
@@ -336,7 +351,8 @@
 
   if (empty) {
     TrimDeleted(true);
-  } else if (header_->lru.sizes[Rankings::DELETED] > header_->num_entries / 4) {
+  } else if (header_->lru.sizes[Rankings::DELETED] > header_->num_entries / 4 &&
+             !test_mode_) {
     MessageLoop::current()->PostTask(FROM_HERE,
         factory_.NewRunnableMethod(&Eviction::TrimDeleted, empty));
   }
@@ -451,6 +467,8 @@
     node.reset(next.release());
     next.reset(rankings_->GetPrev(node.get(), Rankings::DELETED));
     deleted |= RemoveDeletedNode(node.get());
+    if (test_mode_)
+      break;
   }
 
   // Normally we use 25% for each list. The experiment doubles the number of
@@ -459,10 +477,11 @@
   // lists intact.
   int max_length = in_experiment_ ? header_->num_entries * 2 / 5 :
                                     header_->num_entries / 4;
-  if (deleted && !empty &&
-      header_->lru.sizes[Rankings::DELETED] > max_length)
+  if (deleted && !empty && !test_mode_ &&
+      header_->lru.sizes[Rankings::DELETED] > max_length) {
     MessageLoop::current()->PostTask(FROM_HERE,
         factory_.NewRunnableMethod(&Eviction::TrimDeleted, false));
+  }
 
   CACHE_UMA(AGE_MS, "TotalTrimDeletedTime", 0, start);
   Trace("*** Trim Deleted end ***");
@@ -470,19 +489,12 @@
 }
 
 bool Eviction::RemoveDeletedNode(CacheRankingsBlock* node) {
-  EntryImpl* entry;
-  bool dirty;
-  if (backend_->NewEntry(Addr(node->Data()->contents), &entry, &dirty)) {
+  EntryImpl* entry = backend_->GetEnumeratedEntry(node);
+  if (!entry) {
     Trace("NewEntry failed on Trim 0x%x", node->address().value());
     return false;
   }
 
-  // TODO(rvargas): figure out how to deal with corruption at this point (dirty
-  // entries that live in this list).
-  if (node->Data()->dirty) {
-    // We ignore the failure; we're removing the entry anyway.
-    entry->Update();
-  }
   bool doomed = (entry->entry()->Data()->state == ENTRY_DOOMED);
   entry->entry()->Data()->state = ENTRY_DOOMED;
   entry->DoomImpl();
diff --git a/net/disk_cache/eviction.h b/net/disk_cache/eviction.h
index 0f5eeb7..26f88fe 100644
--- a/net/disk_cache/eviction.h
+++ b/net/disk_cache/eviction.h
@@ -40,6 +40,10 @@
   void OnDoomEntry(EntryImpl* entry);
   void OnDestroyEntry(EntryImpl* entry);
 
+  // Testing interface.
+  void SetTestMode();
+  void TrimDeletedList(bool empty);
+
  private:
   void PostDelayedTrim();
   void DelayedTrim();
@@ -75,6 +79,7 @@
   bool trimming_;
   bool delay_trim_;
   bool init_;
+  bool test_mode_;
   bool in_experiment_;
   ScopedRunnableMethodFactory<Eviction> factory_;
 
diff --git a/net/disk_cache/file_posix.cc b/net/disk_cache/file_posix.cc
index 01dafd3..087ff13 100644
--- a/net/disk_cache/file_posix.cc
+++ b/net/disk_cache/file_posix.cc
@@ -189,11 +189,6 @@
   return true;
 }
 
-File::~File() {
-  if (platform_file_)
-    close(platform_file_);
-}
-
 base::PlatformFile File::platform_file() const {
   return platform_file_;
 }
@@ -255,19 +250,6 @@
   return AsyncWrite(buffer, buffer_len, offset, callback, completed);
 }
 
-bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
-                      FileIOCallback* callback, bool* completed) {
-  DCHECK(init_);
-  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
-    return false;
-
-  GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback);
-
-  if (completed)
-    *completed = false;
-  return true;
-}
-
 bool File::SetLength(size_t length) {
   DCHECK(init_);
   if (length > ULONG_MAX)
@@ -290,4 +272,22 @@
   DeleteFileInFlightIO();
 }
 
+File::~File() {
+  if (IsValid())
+    close(platform_file_);
+}
+
+bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
+                      FileIOCallback* callback, bool* completed) {
+  DCHECK(init_);
+  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
+    return false;
+
+  GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback);
+
+  if (completed)
+    *completed = false;
+  return true;
+}
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/mapped_file_posix.cc b/net/disk_cache/mapped_file_posix.cc
index f9a361b..9abfa5c 100644
--- a/net/disk_cache/mapped_file_posix.cc
+++ b/net/disk_cache/mapped_file_posix.cc
@@ -32,16 +32,6 @@
   return buffer_;
 }
 
-MappedFile::~MappedFile() {
-  if (!init_)
-    return;
-
-  if (buffer_) {
-    int ret = munmap(buffer_, view_size_);
-    DCHECK(0 == ret);
-  }
-}
-
 bool MappedFile::Load(const FileBlock* block) {
   size_t offset = block->offset() + view_size_;
   return Read(block->buffer(), block->size(), offset);
@@ -52,4 +42,14 @@
   return Write(block->buffer(), block->size(), offset);
 }
 
+MappedFile::~MappedFile() {
+  if (!init_)
+    return;
+
+  if (buffer_) {
+    int ret = munmap(buffer_, view_size_);
+    DCHECK(0 == ret);
+  }
+}
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/mem_entry_impl.cc b/net/disk_cache/mem_entry_impl.cc
index a9e599c..30599f4 100644
--- a/net/disk_cache/mem_entry_impl.cc
+++ b/net/disk_cache/mem_entry_impl.cc
@@ -48,12 +48,66 @@
     data_size_[i] = 0;
 }
 
-MemEntryImpl::~MemEntryImpl() {
-  for (int i = 0; i < NUM_STREAMS; i++)
-    backend_->ModifyStorageSize(data_size_[i], 0);
-  backend_->ModifyStorageSize(static_cast<int32>(key_.size()), 0);
+// ------------------------------------------------------------------------
+
+bool MemEntryImpl::CreateEntry(const std::string& key) {
+  key_ = key;
+  Time current = Time::Now();
+  last_modified_ = current;
+  last_used_ = current;
+  Open();
+  backend_->ModifyStorageSize(0, static_cast<int32>(key.size()));
+  return true;
 }
 
+void MemEntryImpl::InternalDoom() {
+  doomed_ = true;
+  if (!ref_count_) {
+    if (type() == kParentEntry) {
+      // If this is a parent entry, we need to doom all the child entries.
+      if (children_.get()) {
+        EntryMap children;
+        children.swap(*children_);
+        for (EntryMap::iterator i = children.begin();
+             i != children.end(); ++i) {
+          // Since a pointer to this object is also saved in the map, avoid
+          // dooming it.
+          if (i->second != this)
+            i->second->Doom();
+        }
+        DCHECK(children_->size() == 0);
+      }
+    } else {
+      // If this is a child entry, detach it from the parent.
+      parent_->DetachChild(child_id_);
+    }
+    delete this;
+  }
+}
+
+void MemEntryImpl::Open() {
+  // Only a parent entry can be opened.
+  // TODO(hclam): make sure it's correct to not apply the concept of ref
+  // counting to child entry.
+  DCHECK(type() == kParentEntry);
+  ref_count_++;
+  DCHECK(ref_count_ >= 0);
+  DCHECK(!doomed_);
+}
+
+bool MemEntryImpl::InUse() {
+  if (type() == kParentEntry) {
+    return ref_count_ > 0;
+  } else {
+    // A child entry is always not in use. The consequence is that a child entry
+    // can always be evicted while the associated parent entry is currently in
+    // used (i.e. opened).
+    return false;
+  }
+}
+
+// ------------------------------------------------------------------------
+
 void MemEntryImpl::Doom() {
   if (doomed_)
     return;
@@ -263,6 +317,29 @@
   return io_buf->BytesConsumed();
 }
 
+int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
+                                    CompletionCallback* callback) {
+  return GetAvailableRange(offset, len, start);
+}
+
+bool MemEntryImpl::CouldBeSparse() const {
+  DCHECK_EQ(kParentEntry, type());
+  return (children_.get() != NULL);
+}
+
+int MemEntryImpl::ReadyForSparseIO(
+    net::CompletionCallback* completion_callback) {
+  return net::OK;
+}
+
+// ------------------------------------------------------------------------
+
+MemEntryImpl::~MemEntryImpl() {
+  for (int i = 0; i < NUM_STREAMS; i++)
+    backend_->ModifyStorageSize(data_size_[i], 0);
+  backend_->ModifyStorageSize(static_cast<int32>(key_.size()), 0);
+}
+
 int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start) {
   DCHECK(type() == kParentEntry);
   DCHECK(start);
@@ -307,81 +384,6 @@
   return 0;
 }
 
-int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
-                                    CompletionCallback* callback) {
-  return GetAvailableRange(offset, len, start);
-}
-
-bool MemEntryImpl::CouldBeSparse() const {
-  DCHECK_EQ(kParentEntry, type());
-  return (children_.get() != NULL);
-}
-
-int MemEntryImpl::ReadyForSparseIO(
-    net::CompletionCallback* completion_callback) {
-  return net::OK;
-}
-
-// ------------------------------------------------------------------------
-
-bool MemEntryImpl::CreateEntry(const std::string& key) {
-  key_ = key;
-  Time current = Time::Now();
-  last_modified_ = current;
-  last_used_ = current;
-  Open();
-  backend_->ModifyStorageSize(0, static_cast<int32>(key.size()));
-  return true;
-}
-
-void MemEntryImpl::InternalDoom() {
-  doomed_ = true;
-  if (!ref_count_) {
-    if (type() == kParentEntry) {
-      // If this is a parent entry, we need to doom all the child entries.
-      if (children_.get()) {
-        EntryMap children;
-        children.swap(*children_);
-        for (EntryMap::iterator i = children.begin();
-             i != children.end(); ++i) {
-          // Since a pointer to this object is also saved in the map, avoid
-          // dooming it.
-          if (i->second != this)
-            i->second->Doom();
-        }
-        DCHECK(children_->size() == 0);
-      }
-    } else {
-      // If this is a child entry, detach it from the parent.
-      parent_->DetachChild(child_id_);
-    }
-    delete this;
-  }
-}
-
-void MemEntryImpl::Open() {
-  // Only a parent entry can be opened.
-  // TODO(hclam): make sure it's correct to not apply the concept of ref
-  // counting to child entry.
-  DCHECK(type() == kParentEntry);
-  ref_count_++;
-  DCHECK(ref_count_ >= 0);
-  DCHECK(!doomed_);
-}
-
-bool MemEntryImpl::InUse() {
-  if (type() == kParentEntry) {
-    return ref_count_ > 0;
-  } else {
-    // A child entry is always not in use. The consequence is that a child entry
-    // can always be evicted while the associated parent entry is currently in
-    // used (i.e. opened).
-    return false;
-  }
-}
-
-// ------------------------------------------------------------------------
-
 void MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) {
   int entry_size = GetDataSize(index);
 
diff --git a/net/disk_cache/mem_entry_impl.h b/net/disk_cache/mem_entry_impl.h
index 573a306..f4ac4ef 100644
--- a/net/disk_cache/mem_entry_impl.h
+++ b/net/disk_cache/mem_entry_impl.h
@@ -52,28 +52,6 @@
 
   explicit MemEntryImpl(MemBackendImpl* backend);
 
-  // Entry interface.
-  virtual void Doom();
-  virtual void Close();
-  virtual std::string GetKey() const;
-  virtual base::Time GetLastUsed() const;
-  virtual base::Time GetLastModified() const;
-  virtual int32 GetDataSize(int index) const;
-  virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
-                       net::CompletionCallback* completion_callback);
-  virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
-                        net::CompletionCallback* completion_callback,
-                        bool truncate);
-  virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
-                             net::CompletionCallback* completion_callback);
-  virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
-                              net::CompletionCallback* completion_callback);
-  virtual int GetAvailableRange(int64 offset, int len, int64* start,
-                                CompletionCallback* callback);
-  virtual bool CouldBeSparse() const;
-  virtual void CancelSparseIO() {}
-  virtual int ReadyForSparseIO(net::CompletionCallback* completion_callback);
-
   // Performs the initialization of a EntryImpl that will be added to the
   // cache.
   bool CreateEntry(const std::string& key);
@@ -104,6 +82,28 @@
     return parent_ ? kChildEntry : kParentEntry;
   }
 
+  // Entry interface.
+  virtual void Doom();
+  virtual void Close();
+  virtual std::string GetKey() const;
+  virtual base::Time GetLastUsed() const;
+  virtual base::Time GetLastModified() const;
+  virtual int32 GetDataSize(int index) const;
+  virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
+                       net::CompletionCallback* completion_callback);
+  virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
+                        net::CompletionCallback* completion_callback,
+                        bool truncate);
+  virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
+                             net::CompletionCallback* completion_callback);
+  virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
+                              net::CompletionCallback* completion_callback);
+  virtual int GetAvailableRange(int64 offset, int len, int64* start,
+                                CompletionCallback* callback);
+  virtual bool CouldBeSparse() const;
+  virtual void CancelSparseIO() {}
+  virtual int ReadyForSparseIO(net::CompletionCallback* completion_callback);
+
  private:
   typedef base::hash_map<int, MemEntryImpl*> EntryMap;
 
diff --git a/net/disk_cache/rankings.cc b/net/disk_cache/rankings.cc
index c8e0a7d..00db40a 100644
--- a/net/disk_cache/rankings.cc
+++ b/net/disk_cache/rankings.cc
@@ -228,58 +228,6 @@
   control_data_ = NULL;
 }
 
-bool Rankings::GetRanking(CacheRankingsBlock* rankings) {
-  if (!rankings->address().is_initialized())
-    return false;
-
-  TimeTicks start = TimeTicks::Now();
-  if (!rankings->Load())
-    return false;
-
-  if (!SanityCheck(rankings, true)) {
-    backend_->CriticalError(ERR_INVALID_LINKS);
-    return false;
-  }
-
-  backend_->OnEvent(Stats::OPEN_RANKINGS);
-
-  // "dummy" is the old "pointer" value, so it has to be 0.
-  if (!rankings->Data()->dirty && !rankings->Data()->dummy)
-    return true;
-
-  EntryImpl* entry = backend_->GetOpenEntry(rankings);
-  if (backend_->GetCurrentEntryId() != rankings->Data()->dirty || !entry) {
-    // We cannot trust this entry, but we cannot initiate a cleanup from this
-    // point (we may be in the middle of a cleanup already). Just get rid of
-    // the invalid pointer and continue; the entry will be deleted when detected
-    // from a regular open/create path.
-    rankings->Data()->dummy = 0;
-    rankings->Data()->dirty = backend_->GetCurrentEntryId() - 1;
-    if (!rankings->Data()->dirty)
-      rankings->Data()->dirty--;
-    return true;
-  }
-
-  // Note that we should not leave this module without deleting rankings first.
-  rankings->SetData(entry->rankings()->Data());
-
-  CACHE_UMA(AGE_MS, "GetRankings", 0, start);
-  return true;
-}
-
-void Rankings::ConvertToLongLived(CacheRankingsBlock* rankings) {
-  if (rankings->own_data())
-    return;
-
-  // We cannot return a shared node because we are not keeping a reference
-  // to the entry that owns the buffer. Make this node a copy of the one that
-  // we have, and let the iterator logic update it when the entry changes.
-  CacheRankingsBlock temp(NULL, Addr(0));
-  *temp.Data() = *rankings->Data();
-  rankings->StopSharingData();
-  *rankings->Data() = *temp.Data();
-}
-
 void Rankings::Insert(CacheRankingsBlock* node, bool modified, List list) {
   Trace("Insert 0x%x l %d", node->address().value(), list);
   DCHECK(node->HasData());
@@ -443,116 +391,6 @@
   CACHE_UMA(AGE_MS, "UpdateRank", 0, start);
 }
 
-void Rankings::CompleteTransaction() {
-  Addr node_addr(static_cast<CacheAddr>(control_data_->transaction));
-  if (!node_addr.is_initialized() || node_addr.is_separate_file()) {
-    NOTREACHED();
-    LOG(ERROR) << "Invalid rankings info.";
-    return;
-  }
-
-  Trace("CompleteTransaction 0x%x", node_addr.value());
-
-  CacheRankingsBlock node(backend_->File(node_addr), node_addr);
-  if (!node.Load())
-    return;
-
-  node.Data()->dummy = 0;
-  node.Store();
-
-  Addr& my_head = heads_[control_data_->operation_list];
-  Addr& my_tail = tails_[control_data_->operation_list];
-
-  // We want to leave the node inside the list. The entry must me marked as
-  // dirty, and will be removed later. Otherwise, we'll get assertions when
-  // attempting to remove the dirty entry.
-  if (INSERT == control_data_->operation) {
-    Trace("FinishInsert h:0x%x t:0x%x", my_head.value(), my_tail.value());
-    FinishInsert(&node);
-  } else if (REMOVE == control_data_->operation) {
-    Trace("RevertRemove h:0x%x t:0x%x", my_head.value(), my_tail.value());
-    RevertRemove(&node);
-  } else {
-    NOTREACHED();
-    LOG(ERROR) << "Invalid operation to recover.";
-  }
-}
-
-void Rankings::FinishInsert(CacheRankingsBlock* node) {
-  control_data_->transaction = 0;
-  control_data_->operation = 0;
-  Addr& my_head = heads_[control_data_->operation_list];
-  Addr& my_tail = tails_[control_data_->operation_list];
-  if (my_head.value() != node->address().value()) {
-    if (my_tail.value() == node->address().value()) {
-      // This part will be skipped by the logic of Insert.
-      node->Data()->next = my_tail.value();
-    }
-
-    Insert(node, true, static_cast<List>(control_data_->operation_list));
-  }
-
-  // Tell the backend about this entry.
-  backend_->RecoveredEntry(node);
-}
-
-void Rankings::RevertRemove(CacheRankingsBlock* node) {
-  Addr next_addr(node->Data()->next);
-  Addr prev_addr(node->Data()->prev);
-  if (!next_addr.is_initialized() || !prev_addr.is_initialized()) {
-    // The operation actually finished. Nothing to do.
-    control_data_->transaction = 0;
-    return;
-  }
-  if (next_addr.is_separate_file() || prev_addr.is_separate_file()) {
-    NOTREACHED();
-    LOG(WARNING) << "Invalid rankings info.";
-    control_data_->transaction = 0;
-    return;
-  }
-
-  CacheRankingsBlock next(backend_->File(next_addr), next_addr);
-  CacheRankingsBlock prev(backend_->File(prev_addr), prev_addr);
-  if (!next.Load() || !prev.Load())
-    return;
-
-  CacheAddr node_value = node->address().value();
-  DCHECK(prev.Data()->next == node_value ||
-         prev.Data()->next == prev_addr.value() ||
-         prev.Data()->next == next.address().value());
-  DCHECK(next.Data()->prev == node_value ||
-         next.Data()->prev == next_addr.value() ||
-         next.Data()->prev == prev.address().value());
-
-  if (node_value != prev_addr.value())
-    prev.Data()->next = node_value;
-  if (node_value != next_addr.value())
-    next.Data()->prev = node_value;
-
-  List my_list = static_cast<List>(control_data_->operation_list);
-  Addr& my_head = heads_[my_list];
-  Addr& my_tail = tails_[my_list];
-  if (!my_head.is_initialized() || !my_tail.is_initialized()) {
-    my_head.set_value(node_value);
-    my_tail.set_value(node_value);
-    WriteHead(my_list);
-    WriteTail(my_list);
-  } else if (my_head.value() == next.address().value()) {
-    my_head.set_value(node_value);
-    prev.Data()->next = next.address().value();
-    WriteHead(my_list);
-  } else if (my_tail.value() == prev.address().value()) {
-    my_tail.set_value(node_value);
-    next.Data()->prev = prev.address().value();
-    WriteTail(my_list);
-  }
-
-  next.Store();
-  prev.Store();
-  control_data_->transaction = 0;
-  control_data_->operation = 0;
-}
-
 CacheRankingsBlock* Rankings::GetNext(CacheRankingsBlock* node, List list) {
   ScopedRankingsBlock next(this);
   if (!node) {
@@ -691,6 +529,168 @@
   control_data_->tails[list] = tails_[list].value();
 }
 
+bool Rankings::GetRanking(CacheRankingsBlock* rankings) {
+  if (!rankings->address().is_initialized())
+    return false;
+
+  TimeTicks start = TimeTicks::Now();
+  if (!rankings->Load())
+    return false;
+
+  if (!SanityCheck(rankings, true)) {
+    backend_->CriticalError(ERR_INVALID_LINKS);
+    return false;
+  }
+
+  backend_->OnEvent(Stats::OPEN_RANKINGS);
+
+  // "dummy" is the old "pointer" value, so it has to be 0.
+  if (!rankings->Data()->dirty && !rankings->Data()->dummy)
+    return true;
+
+  EntryImpl* entry = backend_->GetOpenEntry(rankings);
+  if (backend_->GetCurrentEntryId() != rankings->Data()->dirty || !entry) {
+    // We cannot trust this entry, but we cannot initiate a cleanup from this
+    // point (we may be in the middle of a cleanup already). Just get rid of
+    // the invalid pointer and continue; the entry will be deleted when detected
+    // from a regular open/create path.
+    rankings->Data()->dummy = 0;
+    rankings->Data()->dirty = backend_->GetCurrentEntryId() - 1;
+    if (!rankings->Data()->dirty)
+      rankings->Data()->dirty--;
+    return true;
+  }
+
+  // Note that we should not leave this module without deleting rankings first.
+  rankings->SetData(entry->rankings()->Data());
+
+  CACHE_UMA(AGE_MS, "GetRankings", 0, start);
+  return true;
+}
+
+void Rankings::ConvertToLongLived(CacheRankingsBlock* rankings) {
+  if (rankings->own_data())
+    return;
+
+  // We cannot return a shared node because we are not keeping a reference
+  // to the entry that owns the buffer. Make this node a copy of the one that
+  // we have, and let the iterator logic update it when the entry changes.
+  CacheRankingsBlock temp(NULL, Addr(0));
+  *temp.Data() = *rankings->Data();
+  rankings->StopSharingData();
+  *rankings->Data() = *temp.Data();
+}
+
+void Rankings::CompleteTransaction() {
+  Addr node_addr(static_cast<CacheAddr>(control_data_->transaction));
+  if (!node_addr.is_initialized() || node_addr.is_separate_file()) {
+    NOTREACHED();
+    LOG(ERROR) << "Invalid rankings info.";
+    return;
+  }
+
+  Trace("CompleteTransaction 0x%x", node_addr.value());
+
+  CacheRankingsBlock node(backend_->File(node_addr), node_addr);
+  if (!node.Load())
+    return;
+
+  node.Data()->dummy = 0;
+  node.Store();
+
+  Addr& my_head = heads_[control_data_->operation_list];
+  Addr& my_tail = tails_[control_data_->operation_list];
+
+  // We want to leave the node inside the list. The entry must me marked as
+  // dirty, and will be removed later. Otherwise, we'll get assertions when
+  // attempting to remove the dirty entry.
+  if (INSERT == control_data_->operation) {
+    Trace("FinishInsert h:0x%x t:0x%x", my_head.value(), my_tail.value());
+    FinishInsert(&node);
+  } else if (REMOVE == control_data_->operation) {
+    Trace("RevertRemove h:0x%x t:0x%x", my_head.value(), my_tail.value());
+    RevertRemove(&node);
+  } else {
+    NOTREACHED();
+    LOG(ERROR) << "Invalid operation to recover.";
+  }
+}
+
+void Rankings::FinishInsert(CacheRankingsBlock* node) {
+  control_data_->transaction = 0;
+  control_data_->operation = 0;
+  Addr& my_head = heads_[control_data_->operation_list];
+  Addr& my_tail = tails_[control_data_->operation_list];
+  if (my_head.value() != node->address().value()) {
+    if (my_tail.value() == node->address().value()) {
+      // This part will be skipped by the logic of Insert.
+      node->Data()->next = my_tail.value();
+    }
+
+    Insert(node, true, static_cast<List>(control_data_->operation_list));
+  }
+
+  // Tell the backend about this entry.
+  backend_->RecoveredEntry(node);
+}
+
+void Rankings::RevertRemove(CacheRankingsBlock* node) {
+  Addr next_addr(node->Data()->next);
+  Addr prev_addr(node->Data()->prev);
+  if (!next_addr.is_initialized() || !prev_addr.is_initialized()) {
+    // The operation actually finished. Nothing to do.
+    control_data_->transaction = 0;
+    return;
+  }
+  if (next_addr.is_separate_file() || prev_addr.is_separate_file()) {
+    NOTREACHED();
+    LOG(WARNING) << "Invalid rankings info.";
+    control_data_->transaction = 0;
+    return;
+  }
+
+  CacheRankingsBlock next(backend_->File(next_addr), next_addr);
+  CacheRankingsBlock prev(backend_->File(prev_addr), prev_addr);
+  if (!next.Load() || !prev.Load())
+    return;
+
+  CacheAddr node_value = node->address().value();
+  DCHECK(prev.Data()->next == node_value ||
+         prev.Data()->next == prev_addr.value() ||
+         prev.Data()->next == next.address().value());
+  DCHECK(next.Data()->prev == node_value ||
+         next.Data()->prev == next_addr.value() ||
+         next.Data()->prev == prev.address().value());
+
+  if (node_value != prev_addr.value())
+    prev.Data()->next = node_value;
+  if (node_value != next_addr.value())
+    next.Data()->prev = node_value;
+
+  List my_list = static_cast<List>(control_data_->operation_list);
+  Addr& my_head = heads_[my_list];
+  Addr& my_tail = tails_[my_list];
+  if (!my_head.is_initialized() || !my_tail.is_initialized()) {
+    my_head.set_value(node_value);
+    my_tail.set_value(node_value);
+    WriteHead(my_list);
+    WriteTail(my_list);
+  } else if (my_head.value() == next.address().value()) {
+    my_head.set_value(node_value);
+    prev.Data()->next = next.address().value();
+    WriteHead(my_list);
+  } else if (my_tail.value() == prev.address().value()) {
+    my_tail.set_value(node_value);
+    next.Data()->prev = prev.address().value();
+    WriteTail(my_list);
+  }
+
+  next.Store();
+  prev.Store();
+  control_data_->transaction = 0;
+  control_data_->operation = 0;
+}
+
 bool Rankings::CheckEntry(CacheRankingsBlock* rankings) {
   if (!rankings->Data()->dummy)
     return true;
diff --git a/net/disk_cache/sparse_control.cc b/net/disk_cache/sparse_control.cc
index ebc8250..bd8908f 100644
--- a/net/disk_cache/sparse_control.cc
+++ b/net/disk_cache/sparse_control.cc
@@ -52,7 +52,7 @@
       public disk_cache::FileIOCallback {
  public:
   ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name)
-      : backend_(backend->GetWeakPtr()), name_(name) {}
+      : backend_(backend->GetWeakPtr()), name_(name), signature_(0) {}
 
   virtual void OnFileIOComplete(int bytes_copied);
 
diff --git a/net/disk_cache/stats.cc b/net/disk_cache/stats.cc
index 5222112..d9a9d12 100644
--- a/net/disk_cache/stats.cc
+++ b/net/disk_cache/stats.cc
@@ -116,6 +116,12 @@
   return StoreStats(backend, *address, stats);
 }
 
+Stats::Stats() : backend_(NULL) {
+}
+
+Stats::~Stats() {
+}
+
 bool Stats::Init(BackendImpl* backend, uint32* storage_addr) {
   OnDiskStats stats;
   Addr address(*storage_addr);
@@ -153,86 +159,6 @@
   return true;
 }
 
-Stats::Stats() : backend_(NULL) {
-}
-
-Stats::~Stats() {
-}
-
-// The array will be filled this way:
-//  index      size
-//    0       [0, 1024)
-//    1    [1024, 2048)
-//    2    [2048, 4096)
-//    3      [4K, 6K)
-//      ...
-//   10     [18K, 20K)
-//   11     [20K, 24K)
-//   12     [24k, 28K)
-//      ...
-//   15     [36k, 40K)
-//   16     [40k, 64K)
-//   17     [64K, 128K)
-//   18    [128K, 256K)
-//      ...
-//   23      [4M, 8M)
-//   24      [8M, 16M)
-//   25     [16M, 32M)
-//   26     [32M, 64M)
-//   27     [64M, ...)
-int Stats::GetStatsBucket(int32 size) {
-  if (size < 1024)
-    return 0;
-
-  // 10 slots more, until 20K.
-  if (size < 20 * 1024)
-    return size / 2048 + 1;
-
-  // 5 slots more, from 20K to 40K.
-  if (size < 40 * 1024)
-    return (size - 20 * 1024) / 4096 + 11;
-
-  // From this point on, use a logarithmic scale.
-  int result =  LogBase2(size) + 1;
-
-  COMPILE_ASSERT(kDataSizesLength > 16, update_the_scale);
-  if (result >= kDataSizesLength)
-    result = kDataSizesLength - 1;
-
-  return result;
-}
-
-int Stats::GetBucketRange(size_t i) const {
-  if (i < 2)
-    return static_cast<int>(1024 * i);
-
-  if (i < 12)
-    return static_cast<int>(2048 * (i - 1));
-
-  if (i < 17)
-    return static_cast<int>(4096 * (i - 11)) + 20 * 1024;
-
-  int n = 64 * 1024;
-  if (i > static_cast<size_t>(kDataSizesLength)) {
-    NOTREACHED();
-    i = kDataSizesLength;
-  }
-
-  i -= 17;
-  n <<= i;
-  return n;
-}
-
-void Stats::Snapshot(StatsHistogram::StatsSamples* samples) const {
-  samples->GetCounts()->resize(kDataSizesLength);
-  for (int i = 0; i < kDataSizesLength; i++) {
-    int count = data_sizes_[i];
-    if (count < 0)
-      count = 0;
-    samples->GetCounts()->at(i) = count;
-  }
-}
-
 void Stats::ModifyStorageStats(int32 old_size, int32 new_size) {
   // We keep a counter of the data block size on an array where each entry is
   // the adjusted log base 2 of the size. The first entry counts blocks of 256
@@ -286,15 +212,6 @@
   return GetRatio(RESURRECT_HIT, CREATE_HIT);
 }
 
-int Stats::GetRatio(Counters hit, Counters miss) const {
-  int64 ratio = GetCounter(hit) * 100;
-  if (!ratio)
-    return 0;
-
-  ratio /= (GetCounter(hit) + GetCounter(miss));
-  return static_cast<int>(ratio);
-}
-
 void Stats::ResetRatios() {
   SetCounter(OPEN_HIT, 0);
   SetCounter(OPEN_MISS, 0);
@@ -326,4 +243,87 @@
   StoreStats(backend_, address, &stats);
 }
 
+int Stats::GetBucketRange(size_t i) const {
+  if (i < 2)
+    return static_cast<int>(1024 * i);
+
+  if (i < 12)
+    return static_cast<int>(2048 * (i - 1));
+
+  if (i < 17)
+    return static_cast<int>(4096 * (i - 11)) + 20 * 1024;
+
+  int n = 64 * 1024;
+  if (i > static_cast<size_t>(kDataSizesLength)) {
+    NOTREACHED();
+    i = kDataSizesLength;
+  }
+
+  i -= 17;
+  n <<= i;
+  return n;
+}
+
+void Stats::Snapshot(StatsHistogram::StatsSamples* samples) const {
+  samples->GetCounts()->resize(kDataSizesLength);
+  for (int i = 0; i < kDataSizesLength; i++) {
+    int count = data_sizes_[i];
+    if (count < 0)
+      count = 0;
+    samples->GetCounts()->at(i) = count;
+  }
+}
+
+// The array will be filled this way:
+//  index      size
+//    0       [0, 1024)
+//    1    [1024, 2048)
+//    2    [2048, 4096)
+//    3      [4K, 6K)
+//      ...
+//   10     [18K, 20K)
+//   11     [20K, 24K)
+//   12     [24k, 28K)
+//      ...
+//   15     [36k, 40K)
+//   16     [40k, 64K)
+//   17     [64K, 128K)
+//   18    [128K, 256K)
+//      ...
+//   23      [4M, 8M)
+//   24      [8M, 16M)
+//   25     [16M, 32M)
+//   26     [32M, 64M)
+//   27     [64M, ...)
+int Stats::GetStatsBucket(int32 size) {
+  if (size < 1024)
+    return 0;
+
+  // 10 slots more, until 20K.
+  if (size < 20 * 1024)
+    return size / 2048 + 1;
+
+  // 5 slots more, from 20K to 40K.
+  if (size < 40 * 1024)
+    return (size - 20 * 1024) / 4096 + 11;
+
+  // From this point on, use a logarithmic scale.
+  int result =  LogBase2(size) + 1;
+
+  COMPILE_ASSERT(kDataSizesLength > 16, update_the_scale);
+  if (result >= kDataSizesLength)
+    result = kDataSizesLength - 1;
+
+  return result;
+}
+
+int Stats::GetRatio(Counters hit, Counters miss) const {
+  int64 ratio = GetCounter(hit) * 100;
+  if (!ratio)
+    return 0;
+
+  ratio /= (GetCounter(hit) + GetCounter(miss));
+  return static_cast<int>(ratio);
+}
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/stats_histogram.cc b/net/disk_cache/stats_histogram.cc
index 366a7e1..39c9056 100644
--- a/net/disk_cache/stats_histogram.cc
+++ b/net/disk_cache/stats_histogram.cc
@@ -15,6 +15,12 @@
 // Static.
 const Stats* StatsHistogram::stats_ = NULL;
 
+StatsHistogram::~StatsHistogram() {
+  // Only cleanup what we set.
+  if (init_)
+    stats_ = NULL;
+}
+
 scoped_refptr<StatsHistogram> StatsHistogram::StatsHistogramFactoryGet(
     const std::string& name) {
   scoped_refptr<Histogram> histogram(NULL);
@@ -59,12 +65,6 @@
   return true;
 }
 
-StatsHistogram::~StatsHistogram() {
-  // Only cleanup what we set.
-  if (init_)
-    stats_ = NULL;
-}
-
 Histogram::Sample StatsHistogram::ranges(size_t i) const {
   DCHECK(stats_);
   return stats_->GetBucketRange(i);
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc
index 34ef519..fcb222f 100644
--- a/net/ftp/ftp_directory_listing_parser_ls.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -39,10 +39,13 @@
       text[0] != '-')
     return false;
 
+  // Do not check the rest of the string. Some servers fail to properly
+  // separate this column from the next column (number of links), resulting
+  // in additional characters at the end. Also, sometimes there is a "+"
+  // sign at the end indicating the file has ACLs set.
   return (LooksLikeUnixPermission(text.substr(1, 3)) &&
           LooksLikeUnixPermission(text.substr(4, 3)) &&
-          LooksLikeUnixPermission(text.substr(7, 3)) &&
-          (text.substr(10).empty() || text.substr(10) == ASCIIToUTF16("+")));
+          LooksLikeUnixPermission(text.substr(7, 3)));
 }
 
 bool LooksLikePermissionDeniedError(const string16& text) {
diff --git a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
index ea4f094..88bbecd 100644
--- a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
@@ -81,6 +81,12 @@
     { "-rw-r--r-- 1 ftpadmin ftpadmin125435904 Apr  9  2008 .pureftpd-upload",
       net::FtpDirectoryListingEntry::FILE, ".pureftpd-upload", 0,
       2008, 4, 9, 0, 0 },
+
+    // Tests for "ls -l" style listing with number of links
+    // not separated from permission listing (http://crbug.com/70394).
+    { "drwxr-xr-x1732 266      111        90112 Jun 21  2001 .rda_2",
+      net::FtpDirectoryListingEntry::DIRECTORY, ".rda_2", -1,
+      2001, 6, 21, 0, 0 },
   };
   for (size_t i = 0; i < arraysize(good_cases); i++) {
     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
@@ -134,8 +140,6 @@
     "-rw-r--r-- 1 ftp ftp 528 Foo 01 2007 README",
     "drwxrwxrwx   1 owner    group               0 Sep 13  0:3 audio",
 
-    "d-wx-wx-wt++  4 ftp 989 512 Dec  8 15:54 incoming",
-    "d-wx-wx-wt$  4 ftp 989 512 Dec  8 15:54 incoming",
     "-qqqqqqqqq+  2 sys          512 Mar 27  2009 pub",
   };
   for (size_t i = 0; i < arraysize(bad_cases); i++) {
diff --git a/net/ftp/ftp_directory_listing_parser_vms.h b/net/ftp/ftp_directory_listing_parser_vms.h
index 118365d..6f7fb73 100644
--- a/net/ftp/ftp_directory_listing_parser_vms.h
+++ b/net/ftp/ftp_directory_listing_parser_vms.h
@@ -26,10 +26,6 @@
   virtual FtpDirectoryListingEntry PopEntry();
 
  private:
-  // Consumes listing line which is expected to be a directory listing entry
-  // (and not a comment etc). Returns true on success.
-  bool ConsumeEntryLine(const string16& line);
-
   enum State {
     STATE_INITIAL,
 
@@ -46,7 +42,13 @@
 
     // Indicates that we have successfully received all parts of the listing.
     STATE_END,
-  } state_;
+  };
+
+  // Consumes listing line which is expected to be a directory listing entry
+  // (and not a comment etc). Returns true on success.
+  bool ConsumeEntryLine(const string16& line);
+
+  State state_;
 
   // VMS can use two physical lines if the filename is long. The first line will
   // contain the filename, and the second line everything else. Store the
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 0285e08..d012818 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -204,6 +204,20 @@
 FtpNetworkTransaction::~FtpNetworkTransaction() {
 }
 
+int FtpNetworkTransaction::Stop(int error) {
+  if (command_sent_ == COMMAND_QUIT)
+    return error;
+
+  next_state_ = STATE_CTRL_WRITE_QUIT;
+  last_error_ = error;
+  return OK;
+}
+
+int FtpNetworkTransaction::RestartIgnoringLastError(
+    CompletionCallback* callback) {
+  return ERR_NOT_IMPLEMENTED;
+}
+
 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info,
                                  CompletionCallback* callback,
                                  const BoundNetLog& net_log) {
@@ -226,15 +240,6 @@
   return rv;
 }
 
-int FtpNetworkTransaction::Stop(int error) {
-  if (command_sent_ == COMMAND_QUIT)
-    return error;
-
-  next_state_ = STATE_CTRL_WRITE_QUIT;
-  last_error_ = error;
-  return OK;
-}
-
 int FtpNetworkTransaction::RestartWithAuth(const string16& username,
                                            const string16& password,
                                            CompletionCallback* callback) {
@@ -250,11 +255,6 @@
   return rv;
 }
 
-int FtpNetworkTransaction::RestartIgnoringLastError(
-    CompletionCallback* callback) {
-  return ERR_NOT_IMPLEMENTED;
-}
-
 int FtpNetworkTransaction::Read(IOBuffer* buf,
                                 int buf_len,
                                 CompletionCallback* callback) {
@@ -302,34 +302,37 @@
   return 0;
 }
 
-// Used to prepare and send FTP command.
-int FtpNetworkTransaction::SendFtpCommand(const std::string& command,
-                                          Command cmd) {
-  // If we send a new command when we still have unprocessed responses
-  // for previous commands, the response receiving code will have no way to know
-  // which responses are for which command.
-  DCHECK(!ctrl_response_buffer_->ResponseAvailable());
+void FtpNetworkTransaction::ResetStateForRestart() {
+  command_sent_ = COMMAND_NONE;
+  user_callback_ = NULL;
+  response_ = FtpResponseInfo();
+  read_ctrl_buf_ = new IOBuffer(kCtrlBufLen);
+  ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer());
+  read_data_buf_ = NULL;
+  read_data_buf_len_ = 0;
+  if (write_buf_)
+    write_buf_->SetOffset(0);
+  last_error_ = OK;
+  data_connection_port_ = 0;
+  ctrl_socket_.reset();
+  data_socket_.reset();
+  next_state_ = STATE_NONE;
+}
 
-  DCHECK(!write_command_buf_);
-  DCHECK(!write_buf_);
+void FtpNetworkTransaction::DoCallback(int rv) {
+  DCHECK(rv != ERR_IO_PENDING);
+  DCHECK(user_callback_);
 
-  if (!IsValidFTPCommandString(command)) {
-    // Callers should validate the command themselves and return a more specific
-    // error code.
-    NOTREACHED();
-    return Stop(ERR_UNEXPECTED);
-  }
+  // Since Run may result in Read being called, clear callback_ up front.
+  CompletionCallback* c = user_callback_;
+  user_callback_ = NULL;
+  c->Run(rv);
+}
 
-  command_sent_ = cmd;
-
-  write_command_buf_ = new IOBufferWithSize(command.length() + 2);
-  write_buf_ = new DrainableIOBuffer(write_command_buf_,
-                                     write_command_buf_->size());
-  memcpy(write_command_buf_->data(), command.data(), command.length());
-  memcpy(write_command_buf_->data() + command.length(), kCRLF, 2);
-
-  next_state_ = STATE_CTRL_WRITE;
-  return OK;
+void FtpNetworkTransaction::OnIOComplete(int result) {
+  int rv = DoLoop(result);
+  if (rv != ERR_IO_PENDING)
+    DoCallback(rv);
 }
 
 int FtpNetworkTransaction::ProcessCtrlResponse() {
@@ -403,37 +406,34 @@
   return rv;
 }
 
-void FtpNetworkTransaction::ResetStateForRestart() {
-  command_sent_ = COMMAND_NONE;
-  user_callback_ = NULL;
-  response_ = FtpResponseInfo();
-  read_ctrl_buf_ = new IOBuffer(kCtrlBufLen);
-  ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer());
-  read_data_buf_ = NULL;
-  read_data_buf_len_ = 0;
-  if (write_buf_)
-    write_buf_->SetOffset(0);
-  last_error_ = OK;
-  data_connection_port_ = 0;
-  ctrl_socket_.reset();
-  data_socket_.reset();
-  next_state_ = STATE_NONE;
-}
+// Used to prepare and send FTP command.
+int FtpNetworkTransaction::SendFtpCommand(const std::string& command,
+                                          Command cmd) {
+  // If we send a new command when we still have unprocessed responses
+  // for previous commands, the response receiving code will have no way to know
+  // which responses are for which command.
+  DCHECK(!ctrl_response_buffer_->ResponseAvailable());
 
-void FtpNetworkTransaction::DoCallback(int rv) {
-  DCHECK(rv != ERR_IO_PENDING);
-  DCHECK(user_callback_);
+  DCHECK(!write_command_buf_);
+  DCHECK(!write_buf_);
 
-  // Since Run may result in Read being called, clear callback_ up front.
-  CompletionCallback* c = user_callback_;
-  user_callback_ = NULL;
-  c->Run(rv);
-}
+  if (!IsValidFTPCommandString(command)) {
+    // Callers should validate the command themselves and return a more specific
+    // error code.
+    NOTREACHED();
+    return Stop(ERR_UNEXPECTED);
+  }
 
-void FtpNetworkTransaction::OnIOComplete(int result) {
-  int rv = DoLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoCallback(rv);
+  command_sent_ = cmd;
+
+  write_command_buf_ = new IOBufferWithSize(command.length() + 2);
+  write_buf_ = new DrainableIOBuffer(write_command_buf_,
+                                     write_command_buf_->size());
+  memcpy(write_command_buf_->data(), command.data(), command.length());
+  memcpy(write_command_buf_->data() + command.length(), kCRLF, 2);
+
+  next_state_ = STATE_CTRL_WRITE;
+  return OK;
 }
 
 std::string FtpNetworkTransaction::GetRequestPathForFtpCommand(
@@ -947,56 +947,6 @@
   return OK;
 }
 
-// SIZE command
-int FtpNetworkTransaction::DoCtrlWriteSIZE() {
-  std::string command = "SIZE " + GetRequestPathForFtpCommand(false);
-  next_state_ = STATE_CTRL_READ;
-  return SendFtpCommand(command, COMMAND_SIZE);
-}
-
-int FtpNetworkTransaction::ProcessResponseSIZE(
-    const FtpCtrlResponse& response) {
-  switch (GetErrorClass(response.status_code)) {
-    case ERROR_CLASS_INITIATED:
-      break;
-    case ERROR_CLASS_OK:
-      if (response.lines.size() != 1)
-        return Stop(ERR_INVALID_RESPONSE);
-      int64 size;
-      if (!base::StringToInt64(response.lines[0], &size))
-        return Stop(ERR_INVALID_RESPONSE);
-      if (size < 0)
-        return Stop(ERR_INVALID_RESPONSE);
-
-      // A successful response to SIZE does not mean the resource is a file.
-      // Some FTP servers (for example, the qnx one) send a SIZE even for
-      // directories.
-      response_.expected_content_size = size;
-      break;
-    case ERROR_CLASS_INFO_NEEDED:
-      break;
-    case ERROR_CLASS_TRANSIENT_ERROR:
-      break;
-    case ERROR_CLASS_PERMANENT_ERROR:
-      // It's possible that SIZE failed because the path is a directory.
-      if (resource_type_ == RESOURCE_TYPE_UNKNOWN &&
-          response.status_code != 550) {
-        return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
-      }
-      break;
-    default:
-      NOTREACHED();
-      return Stop(ERR_UNEXPECTED);
-  }
-
-  if (resource_type_ == RESOURCE_TYPE_FILE)
-    next_state_ = STATE_CTRL_WRITE_RETR;
-  else
-    next_state_ = STATE_CTRL_WRITE_CWD;
-
-  return OK;
-}
-
 // RETR command
 int FtpNetworkTransaction::DoCtrlWriteRETR() {
   std::string command = "RETR " + GetRequestPathForFtpCommand(false);
@@ -1048,6 +998,56 @@
   return OK;
 }
 
+// SIZE command
+int FtpNetworkTransaction::DoCtrlWriteSIZE() {
+  std::string command = "SIZE " + GetRequestPathForFtpCommand(false);
+  next_state_ = STATE_CTRL_READ;
+  return SendFtpCommand(command, COMMAND_SIZE);
+}
+
+int FtpNetworkTransaction::ProcessResponseSIZE(
+    const FtpCtrlResponse& response) {
+  switch (GetErrorClass(response.status_code)) {
+    case ERROR_CLASS_INITIATED:
+      break;
+    case ERROR_CLASS_OK:
+      if (response.lines.size() != 1)
+        return Stop(ERR_INVALID_RESPONSE);
+      int64 size;
+      if (!base::StringToInt64(response.lines[0], &size))
+        return Stop(ERR_INVALID_RESPONSE);
+      if (size < 0)
+        return Stop(ERR_INVALID_RESPONSE);
+
+      // A successful response to SIZE does not mean the resource is a file.
+      // Some FTP servers (for example, the qnx one) send a SIZE even for
+      // directories.
+      response_.expected_content_size = size;
+      break;
+    case ERROR_CLASS_INFO_NEEDED:
+      break;
+    case ERROR_CLASS_TRANSIENT_ERROR:
+      break;
+    case ERROR_CLASS_PERMANENT_ERROR:
+      // It's possible that SIZE failed because the path is a directory.
+      if (resource_type_ == RESOURCE_TYPE_UNKNOWN &&
+          response.status_code != 550) {
+        return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
+      }
+      break;
+    default:
+      NOTREACHED();
+      return Stop(ERR_UNEXPECTED);
+  }
+
+  if (resource_type_ == RESOURCE_TYPE_FILE)
+    next_state_ = STATE_CTRL_WRITE_RETR;
+  else
+    next_state_ = STATE_CTRL_WRITE_CWD;
+
+  return OK;
+}
+
 // CWD command
 int FtpNetworkTransaction::DoCtrlWriteCWD() {
   std::string command = "CWD " + GetRequestPathForFtpCommand(true);
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index 678308a..c4516a4 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -31,15 +31,16 @@
                         ClientSocketFactory* socket_factory);
   virtual ~FtpNetworkTransaction();
 
+  virtual int Stop(int error);
+  virtual int RestartIgnoringLastError(CompletionCallback* callback);
+
   // FtpTransaction methods:
   virtual int Start(const FtpRequestInfo* request_info,
                     CompletionCallback* callback,
                     const BoundNetLog& net_log);
-  virtual int Stop(int error);
   virtual int RestartWithAuth(const string16& username,
                               const string16& password,
                               CompletionCallback* callback);
-  virtual int RestartIgnoringLastError(CompletionCallback* callback);
   virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
   virtual const FtpResponseInfo* GetResponseInfo() const;
   virtual LoadState GetLoadState() const;
@@ -87,6 +88,36 @@
     RESOURCE_TYPE_DIRECTORY,
   };
 
+  enum State {
+    // Control connection states:
+    STATE_CTRL_RESOLVE_HOST,
+    STATE_CTRL_RESOLVE_HOST_COMPLETE,
+    STATE_CTRL_CONNECT,
+    STATE_CTRL_CONNECT_COMPLETE,
+    STATE_CTRL_READ,
+    STATE_CTRL_READ_COMPLETE,
+    STATE_CTRL_WRITE,
+    STATE_CTRL_WRITE_COMPLETE,
+    STATE_CTRL_WRITE_USER,
+    STATE_CTRL_WRITE_PASS,
+    STATE_CTRL_WRITE_SYST,
+    STATE_CTRL_WRITE_TYPE,
+    STATE_CTRL_WRITE_EPSV,
+    STATE_CTRL_WRITE_PASV,
+    STATE_CTRL_WRITE_PWD,
+    STATE_CTRL_WRITE_RETR,
+    STATE_CTRL_WRITE_SIZE,
+    STATE_CTRL_WRITE_CWD,
+    STATE_CTRL_WRITE_LIST,
+    STATE_CTRL_WRITE_QUIT,
+    // Data connection states:
+    STATE_DATA_CONNECT,
+    STATE_DATA_CONNECT_COMPLETE,
+    STATE_DATA_READ,
+    STATE_DATA_READ_COMPLETE,
+    STATE_NONE
+  };
+
   // Resets the members of the transaction so it can be restarted.
   void ResetStateForRestart();
 
@@ -211,35 +242,6 @@
   scoped_ptr<ClientSocket> ctrl_socket_;
   scoped_ptr<ClientSocket> data_socket_;
 
-  enum State {
-    // Control connection states:
-    STATE_CTRL_RESOLVE_HOST,
-    STATE_CTRL_RESOLVE_HOST_COMPLETE,
-    STATE_CTRL_CONNECT,
-    STATE_CTRL_CONNECT_COMPLETE,
-    STATE_CTRL_READ,
-    STATE_CTRL_READ_COMPLETE,
-    STATE_CTRL_WRITE,
-    STATE_CTRL_WRITE_COMPLETE,
-    STATE_CTRL_WRITE_USER,
-    STATE_CTRL_WRITE_PASS,
-    STATE_CTRL_WRITE_SYST,
-    STATE_CTRL_WRITE_TYPE,
-    STATE_CTRL_WRITE_EPSV,
-    STATE_CTRL_WRITE_PASV,
-    STATE_CTRL_WRITE_PWD,
-    STATE_CTRL_WRITE_RETR,
-    STATE_CTRL_WRITE_SIZE,
-    STATE_CTRL_WRITE_CWD,
-    STATE_CTRL_WRITE_LIST,
-    STATE_CTRL_WRITE_QUIT,
-    // Data connection states:
-    STATE_DATA_CONNECT,
-    STATE_DATA_CONNECT_COMPLETE,
-    STATE_DATA_READ,
-    STATE_DATA_READ_COMPLETE,
-    STATE_NONE
-  };
   State next_state_;
 };
 
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index 1b1dfaf..7021cfb 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -13,12 +13,32 @@
 
 namespace net {
 
+DiskCacheBasedSSLHostInfo::CallbackImpl::CallbackImpl(
+    const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj,
+    void (DiskCacheBasedSSLHostInfo::*meth)(int))
+    : obj_(obj),
+      meth_(meth),
+      backend_(NULL),
+      entry_(NULL) {
+}
+
+DiskCacheBasedSSLHostInfo::CallbackImpl::~CallbackImpl() {}
+
+void DiskCacheBasedSSLHostInfo::CallbackImpl::RunWithParams(
+    const Tuple1<int>& params) {
+  if (!obj_) {
+    delete this;
+  } else {
+    DispatchToMethod(obj_.get(), meth_, params);
+  }
+}
+
 DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo(
     const std::string& hostname,
     const SSLConfig& ssl_config,
+    CertVerifier* cert_verifier,
     HttpCache* http_cache)
-    : SSLHostInfo(hostname, ssl_config,
-                  http_cache->network_layer()->GetSession()->cert_verifier()),
+    : SSLHostInfo(hostname, ssl_config, cert_verifier),
       weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
       callback_(new CallbackImpl(weak_ptr_factory_.GetWeakPtr(),
                                  &DiskCacheBasedSSLHostInfo::DoLoop)),
@@ -37,6 +57,35 @@
   DoLoop(OK);
 }
 
+int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(state_ != GET_BACKEND);
+
+  if (ready_)
+    return OK;
+  if (callback) {
+    DCHECK(!user_callback_);
+    user_callback_ = callback;
+  }
+  return ERR_IO_PENDING;
+}
+
+void DiskCacheBasedSSLHostInfo::Persist() {
+  DCHECK(CalledOnValidThread());
+  DCHECK(state_ != GET_BACKEND);
+
+  DCHECK(new_data_.empty());
+  CHECK(ready_);
+  DCHECK(user_callback_ == NULL);
+  new_data_ = Serialize();
+
+  if (!backend_)
+    return;
+
+  state_ = CREATE;
+  DoLoop(OK);
+}
+
 DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() {
   DCHECK(!user_callback_);
   if (entry_)
@@ -95,24 +144,6 @@
   } while (rv != ERR_IO_PENDING && state_ != NONE);
 }
 
-bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const {
-  switch (state_) {
-    case GET_BACKEND_COMPLETE:
-    case OPEN_COMPLETE:
-    case READ_COMPLETE:
-    case CREATE_COMPLETE:
-    case WRITE_COMPLETE:
-      return true;
-    default:
-      return false;
-  }
-}
-
-int DiskCacheBasedSSLHostInfo::DoGetBackend() {
-  state_ = GET_BACKEND_COMPLETE;
-  return http_cache_->GetBackend(callback_->backend_pointer(), callback_);
-}
-
 int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) {
   if (rv == OK) {
     backend_ = callback_->backend();
@@ -123,11 +154,6 @@
   return OK;
 }
 
-int DiskCacheBasedSSLHostInfo::DoOpen() {
-  state_ = OPEN_COMPLETE;
-  return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_);
-}
-
 int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) {
   if (rv == OK) {
     entry_ = callback_->entry();
@@ -139,6 +165,39 @@
   return OK;
 }
 
+int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) {
+  if (rv > 0)
+    data_ = std::string(read_buffer_->data(), rv);
+
+  state_ = WAIT_FOR_DATA_READY_DONE;
+  return OK;
+}
+
+int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
+  state_ = SET_DONE;
+  return OK;
+}
+
+int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) {
+  if (rv != OK) {
+    state_ = SET_DONE;
+  } else {
+    entry_ = callback_->entry();
+    state_ = WRITE;
+  }
+  return OK;
+}
+
+int DiskCacheBasedSSLHostInfo::DoGetBackend() {
+  state_ = GET_BACKEND_COMPLETE;
+  return http_cache_->GetBackend(callback_->backend_pointer(), callback_);
+}
+
+int DiskCacheBasedSSLHostInfo::DoOpen() {
+  state_ = OPEN_COMPLETE;
+  return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_);
+}
+
 int DiskCacheBasedSSLHostInfo::DoRead() {
   const int32 size = entry_->GetDataSize(0 /* index */);
   if (!size) {
@@ -152,12 +211,19 @@
                           size, callback_);
 }
 
-int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) {
-  if (rv > 0)
-    data_ = std::string(read_buffer_->data(), rv);
+int DiskCacheBasedSSLHostInfo::DoWrite() {
+  write_buffer_ = new IOBuffer(new_data_.size());
+  memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
+  state_ = WRITE_COMPLETE;
 
-  state_ = WAIT_FOR_DATA_READY_DONE;
-  return OK;
+  return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_,
+                           new_data_.size(), callback_, true /* truncate */);
+}
+
+int DiskCacheBasedSSLHostInfo::DoCreate() {
+  DCHECK(entry_ == NULL);
+  state_ = CREATE_COMPLETE;
+  return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_);
 }
 
 int DiskCacheBasedSSLHostInfo::WaitForDataReadyDone() {
@@ -181,65 +247,6 @@
   return OK;
 }
 
-int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(state_ != GET_BACKEND);
-
-  if (ready_)
-    return OK;
-  if (callback) {
-    DCHECK(!user_callback_);
-    user_callback_ = callback;
-  }
-  return ERR_IO_PENDING;
-}
-
-void DiskCacheBasedSSLHostInfo::Persist() {
-  DCHECK(CalledOnValidThread());
-  DCHECK(state_ != GET_BACKEND);
-
-  DCHECK(new_data_.empty());
-  CHECK(ready_);
-  DCHECK(user_callback_ == NULL);
-  new_data_ = Serialize();
-
-  if (!backend_)
-    return;
-
-  state_ = CREATE;
-  DoLoop(OK);
-}
-
-int DiskCacheBasedSSLHostInfo::DoCreate() {
-  DCHECK(entry_ == NULL);
-  state_ = CREATE_COMPLETE;
-  return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_);
-}
-
-int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) {
-  if (rv != OK) {
-    state_ = SET_DONE;
-  } else {
-    entry_ = callback_->entry();
-    state_ = WRITE;
-  }
-  return OK;
-}
-
-int DiskCacheBasedSSLHostInfo::DoWrite() {
-  write_buffer_ = new IOBuffer(new_data_.size());
-  memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
-  state_ = WRITE_COMPLETE;
-
-  return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_,
-                           new_data_.size(), callback_, true /* truncate */);
-}
-
-int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
-  state_ = SET_DONE;
-  return OK;
-}
-
 int DiskCacheBasedSSLHostInfo::SetDone() {
   if (entry_)
     entry_->Close();
@@ -248,4 +255,17 @@
   return OK;
 }
 
-} // namespace net
+bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const {
+  switch (state_) {
+    case GET_BACKEND_COMPLETE:
+    case OPEN_COMPLETE:
+    case READ_COMPLETE:
+    case CREATE_COMPLETE:
+    case WRITE_COMPLETE:
+      return true;
+    default:
+      return false;
+  }
+}
+
+}  // namespace net
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index c094163..905a3a9 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H
-#define NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H
+#ifndef NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H_
+#define NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H_
 
 #include <string>
 
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/weak_ptr.h"
@@ -29,6 +28,7 @@
  public:
   DiskCacheBasedSSLHostInfo(const std::string& hostname,
                             const SSLConfig& ssl_config,
+                            CertVerifier* cert_verifier,
                             HttpCache* http_cache);
 
   // Implementation of SSLHostInfo
@@ -53,37 +53,30 @@
     NONE,
   };
 
-  ~DiskCacheBasedSSLHostInfo();
-
   class CallbackImpl : public CallbackRunner<Tuple1<int> > {
    public:
     CallbackImpl(const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj,
-                 void (DiskCacheBasedSSLHostInfo::*meth) (int))
-        : obj_(obj),
-          meth_(meth) {
-    }
-
-    virtual void RunWithParams(const Tuple1<int>& params) {
-      if (!obj_) {
-        delete this;
-      } else {
-        DispatchToMethod(obj_.get(), meth_, params);
-      }
-    }
+                 void (DiskCacheBasedSSLHostInfo::*meth)(int));
+    virtual ~CallbackImpl();
 
     disk_cache::Backend** backend_pointer() { return &backend_; }
     disk_cache::Entry** entry_pointer() { return &entry_; }
     disk_cache::Backend* backend() const { return backend_; }
     disk_cache::Entry* entry() const { return entry_; }
 
+    // CallbackRunner<Tuple1<int> >:
+    virtual void RunWithParams(const Tuple1<int>& params);
+
    private:
     base::WeakPtr<DiskCacheBasedSSLHostInfo> obj_;
-    void (DiskCacheBasedSSLHostInfo::*meth_) (int);
+    void (DiskCacheBasedSSLHostInfo::*meth_)(int);
 
     disk_cache::Backend* backend_;
     disk_cache::Entry* entry_;
   };
 
+  virtual ~DiskCacheBasedSSLHostInfo();
+
   std::string key() const;
 
   void DoLoop(int rv);
@@ -97,11 +90,12 @@
   int DoGetBackend();
   int DoOpen();
   int DoRead();
-  int DoCreate();
   int DoWrite();
+  int DoCreate();
 
   // WaitForDataReadyDone is the terminal state of the read operation.
   int WaitForDataReadyDone();
+
   // SetDone is the terminal state of the write operation.
   int SetDone();
 
@@ -125,4 +119,4 @@
 
 }  // namespace net
 
-#endif  // NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H
+#endif  // NET_HTTP_DISK_CACHE_BASED_SSL_HOST_INFO_H_
diff --git a/net/http/http_alternate_protocols.cc b/net/http/http_alternate_protocols.cc
index 3e6b488..28c52dc 100644
--- a/net/http/http_alternate_protocols.cc
+++ b/net/http/http_alternate_protocols.cc
@@ -5,6 +5,7 @@
 #include "net/http/http_alternate_protocols.h"
 
 #include "base/logging.h"
+#include "base/stringprintf.h"
 #include "base/stl_util-inl.h"
 
 namespace net {
@@ -15,6 +16,28 @@
   "npn-spdy/2",
 };
 
+const char* HttpAlternateProtocols::ProtocolToString(
+    HttpAlternateProtocols::Protocol protocol) {
+  switch (protocol) {
+    case HttpAlternateProtocols::NPN_SPDY_1:
+    case HttpAlternateProtocols::NPN_SPDY_2:
+      return HttpAlternateProtocols::kProtocolStrings[protocol];
+    case HttpAlternateProtocols::BROKEN:
+      return "Broken";
+    case HttpAlternateProtocols::UNINITIALIZED:
+      return "Uninitialized";
+    default:
+      NOTREACHED();
+      return "";
+  }
+}
+
+
+std::string HttpAlternateProtocols::PortProtocolPair::ToString() const {
+  return base::StringPrintf("%d:%s", port,
+                            HttpAlternateProtocols::ProtocolToString(protocol));
+}
+
 // static
 HttpAlternateProtocols::PortProtocolPair*
     HttpAlternateProtocols::forced_alternate_protocol_ = NULL;
diff --git a/net/http/http_alternate_protocols.h b/net/http/http_alternate_protocols.h
index d5f9d77..10b1a06 100644
--- a/net/http/http_alternate_protocols.h
+++ b/net/http/http_alternate_protocols.h
@@ -34,10 +34,14 @@
       return port == other.port && protocol == other.protocol;
     }
 
+    std::string ToString() const;
+
     uint16 port;
     Protocol protocol;
   };
 
+  typedef std::map<HostPortPair, PortProtocolPair> ProtocolMap;
+
   static const char kHeader[];
   static const char* const kProtocolStrings[NUM_ALTERNATE_PROTOCOLS];
 
@@ -64,6 +68,8 @@
   // attempts to set the alternate protocol for |http_host_port_pair| will fail.
   void MarkBrokenAlternateProtocolFor(const HostPortPair& http_host_port_pair);
 
+  const ProtocolMap& protocol_map() const { return protocol_map_; }
+
   // Debugging to simulate presence of an AlternateProtocol.
   // If we don't have an alternate protocol in the map for any given host/port
   // pair, force this ProtocolPortPair.
@@ -71,10 +77,10 @@
   static void DisableForcedAlternateProtocol();
 
  private:
-  typedef std::map<HostPortPair, PortProtocolPair> ProtocolMap;
-
   ProtocolMap protocol_map_;
 
+  static const char* ProtocolToString(Protocol protocol);
+
   // The forced alternate protocol.  If not-null, there is a protocol being
   // forced.
   static PortProtocolPair* forced_alternate_protocol_;
diff --git a/net/http/http_auth.cc b/net/http/http_auth.cc
index e7002cf..d5d6e0c 100644
--- a/net/http/http_auth.cc
+++ b/net/http/http_auth.cc
@@ -26,7 +26,7 @@
     const HttpResponseHeaders* headers,
     Target target,
     const GURL& origin,
-    const std::set<std::string>& disabled_schemes,
+    const std::set<Scheme>& disabled_schemes,
     const BoundNetLog& net_log,
     scoped_ptr<HttpAuthHandler>* handler) {
   DCHECK(http_auth_handler_factory);
@@ -47,7 +47,7 @@
       continue;
     }
     if (cur.get() && (!best.get() || best->score() < cur->score()) &&
-        (disabled_schemes.find(cur->scheme()) == disabled_schemes.end()))
+        (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end()))
       best.swap(cur);
   }
   handler->swap(best);
@@ -58,15 +58,16 @@
     HttpAuthHandler* handler,
     const HttpResponseHeaders* headers,
     Target target,
-    const std::set<std::string>& disabled_schemes,
+    const std::set<Scheme>& disabled_schemes,
     std::string* challenge_used) {
   DCHECK(handler);
   DCHECK(headers);
   DCHECK(challenge_used);
   challenge_used->clear();
-  const std::string& current_scheme = handler->scheme();
+  HttpAuth::Scheme current_scheme = handler->auth_scheme();
   if (disabled_schemes.find(current_scheme) != disabled_schemes.end())
     return HttpAuth::AUTHORIZATION_RESULT_REJECT;
+  std::string current_scheme_name = SchemeToString(current_scheme);
   const std::string header_name = GetChallengeHeaderName(target);
   void* iter = NULL;
   std::string challenge;
@@ -74,7 +75,7 @@
       HttpAuth::AUTHORIZATION_RESULT_INVALID;
   while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
     HttpAuth::ChallengeTokenizer props(challenge.begin(), challenge.end());
-    if (!LowerCaseEqualsASCII(props.scheme(), current_scheme.c_str()))
+    if (!LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str()))
       continue;
     authorization_result = handler->HandleAnotherChallenge(&props);
     if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) {
@@ -86,6 +87,24 @@
   return HttpAuth::AUTHORIZATION_RESULT_REJECT;
 }
 
+HttpUtil::NameValuePairsIterator HttpAuth::ChallengeTokenizer::param_pairs()
+    const {
+  return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
+}
+
+std::string HttpAuth::ChallengeTokenizer::base64_param() const {
+  // Strip off any padding.
+  // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
+  //
+  // Our base64 decoder requires that the length be a multiple of 4.
+  int encoded_length = params_end_ - params_begin_;
+  while (encoded_length > 0 && encoded_length % 4 != 0 &&
+         params_begin_[encoded_length - 1] == '=') {
+    --encoded_length;
+  }
+  return std::string(params_begin_, params_begin_ + encoded_length);
+}
+
 void HttpAuth::ChallengeTokenizer::Init(std::string::const_iterator begin,
                                         std::string::const_iterator end) {
   // The first space-separated token is the auth-scheme.
@@ -106,24 +125,6 @@
   HttpUtil::TrimLWS(&params_begin_, &params_end_);
 }
 
-HttpUtil::NameValuePairsIterator HttpAuth::ChallengeTokenizer::param_pairs()
-    const {
-  return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
-}
-
-std::string HttpAuth::ChallengeTokenizer::base64_param() const {
-  // Strip off any padding.
-  // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
-  //
-  // Our base64 decoder requires that the length be a multiple of 4.
-  int encoded_length = params_end_ - params_begin_;
-  while (encoded_length > 0 && encoded_length % 4 != 0 &&
-         params_begin_[encoded_length - 1] == '=') {
-    --encoded_length;
-  }
-  return std::string(params_begin_, params_begin_ + encoded_length);
-}
-
 // static
 std::string HttpAuth::GetChallengeHeaderName(Target target) {
   switch (target) {
@@ -151,9 +152,34 @@
 }
 
 // static
-std::string HttpAuth::GetAuthTargetString(
-    HttpAuth::Target target) {
-  return target == HttpAuth::AUTH_PROXY ? "proxy" : "server";
+std::string HttpAuth::GetAuthTargetString(Target target) {
+  switch (target) {
+    case AUTH_PROXY:
+      return "proxy";
+    case AUTH_SERVER:
+      return "server";
+    default:
+      NOTREACHED();
+      return "";
+  }
+}
+
+// static
+const char* HttpAuth::SchemeToString(Scheme scheme) {
+  static const char* const kSchemeNames[] = {
+    "basic",
+    "digest",
+    "ntlm",
+    "negotiate",
+    "mock",
+  };
+  COMPILE_ASSERT(arraysize(kSchemeNames) == AUTH_SCHEME_MAX,
+                 http_auth_scheme_names_incorrect_size);
+  if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) {
+    NOTREACHED();
+    return "invalid_scheme";
+  }
+  return kSchemeNames[scheme];
 }
 
 }  // namespace net
diff --git a/net/http/http_auth.h b/net/http/http_auth.h
index 0034b1f..ef779a1 100644
--- a/net/http/http_auth.h
+++ b/net/http/http_auth.h
@@ -80,6 +80,15 @@
     IDENT_SRC_DEFAULT_CREDENTIALS,
   };
 
+  enum Scheme {
+    AUTH_SCHEME_BASIC = 0,
+    AUTH_SCHEME_DIGEST,
+    AUTH_SCHEME_NTLM,
+    AUTH_SCHEME_NEGOTIATE,
+    AUTH_SCHEME_MOCK,
+    AUTH_SCHEME_MAX,
+  };
+
   // Helper structure used by HttpNetworkTransaction to track
   // the current identity being used for authorization.
   struct Identity {
@@ -103,6 +112,9 @@
   // messages.
   static std::string GetAuthTargetString(Target target);
 
+  // Returns a string representation of an authentication Scheme.
+  static const char* SchemeToString(Scheme scheme);
+
   // Iterate through the challenge headers, and pick the best one that
   // we support. Obtains the implementation class for handling the challenge,
   // and passes it back in |*handler|. If no supported challenge was found,
@@ -117,7 +129,7 @@
       const HttpResponseHeaders* headers,
       Target target,
       const GURL& origin,
-      const std::set<std::string>& disabled_schemes,
+      const std::set<Scheme>& disabled_schemes,
       const BoundNetLog& net_log,
       scoped_ptr<HttpAuthHandler>* handler);
 
@@ -146,7 +158,7 @@
       HttpAuthHandler* handler,
       const HttpResponseHeaders* headers,
       Target target,
-      const std::set<std::string>& disabled_schemes,
+      const std::set<Scheme>& disabled_schemes,
       std::string* challenge_used);
 
   // Breaks up a challenge string into the the auth scheme and parameter list,
diff --git a/net/http/http_auth_cache.cc b/net/http/http_auth_cache.cc
index cc80861..95d0d69 100644
--- a/net/http/http_auth_cache.cc
+++ b/net/http/http_auth_cache.cc
@@ -68,7 +68,7 @@
 // Performance: O(n), where n is the number of realm entries.
 HttpAuthCache::Entry* HttpAuthCache::Lookup(const GURL& origin,
                                             const std::string& realm,
-                                            const std::string& scheme) {
+                                            HttpAuth::Scheme scheme) {
   CheckOriginIsValid(origin);
 
   // Linear scan through the realm entries.
@@ -104,7 +104,7 @@
 
 HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
                                          const std::string& realm,
-                                         const std::string& scheme,
+                                         HttpAuth::Scheme scheme,
                                          const std::string& auth_challenge,
                                          const string16& username,
                                          const string16& password,
@@ -143,8 +143,15 @@
 HttpAuthCache::Entry::~Entry() {
 }
 
+void HttpAuthCache::Entry::UpdateStaleChallenge(
+    const std::string& auth_challenge) {
+  auth_challenge_ = auth_challenge;
+  nonce_count_ = 1;
+}
+
 HttpAuthCache::Entry::Entry()
-    : nonce_count_(0) {
+    : scheme_(HttpAuth::AUTH_SCHEME_MAX),
+      nonce_count_(0) {
 }
 
 void HttpAuthCache::Entry::AddPath(const std::string& path) {
@@ -175,15 +182,9 @@
   return false;
 }
 
-void HttpAuthCache::Entry::UpdateStaleChallenge(
-    const std::string& auth_challenge) {
-  auth_challenge_ = auth_challenge;
-  nonce_count_ = 1;
-}
-
 bool HttpAuthCache::Remove(const GURL& origin,
                            const std::string& realm,
-                           const std::string& scheme,
+                           HttpAuth::Scheme scheme,
                            const string16& username,
                            const string16& password) {
   for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) {
@@ -201,7 +202,7 @@
 
 bool HttpAuthCache::UpdateStaleChallenge(const GURL& origin,
                                          const std::string& realm,
-                                         const std::string& scheme,
+                                         HttpAuth::Scheme scheme,
                                          const std::string& auth_challenge) {
   HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme);
   if (!entry)
diff --git a/net/http/http_auth_cache.h b/net/http/http_auth_cache.h
index b6c382c..a130956 100644
--- a/net/http/http_auth_cache.h
+++ b/net/http/http_auth_cache.h
@@ -13,6 +13,7 @@
 #include "base/ref_counted.h"
 #include "base/string16.h"
 #include "googleurl/src/gurl.h"
+#include "net/http/http_auth.h"
 
 namespace net {
 
@@ -42,10 +43,11 @@
   // scheme |scheme|.
   //   |origin| - the {scheme, host, port} of the server.
   //   |realm|  - case sensitive realm string.
-  //   |scheme| - case sensitive authentication scheme, should be lower-case.
+  //   |scheme| - the authentication scheme (i.e. basic, negotiate).
   //   returns  - the matched entry or NULL.
-  Entry* Lookup(const GURL& origin, const std::string& realm,
-                const std::string& scheme);
+  Entry* Lookup(const GURL& origin,
+                const std::string& realm,
+                HttpAuth::Scheme scheme);
 
   // Find the entry on server |origin| whose protection space includes
   // |path|. This uses the assumption in RFC 2617 section 2 that deeper
@@ -62,7 +64,7 @@
   // paths list.
   //   |origin|   - the {scheme, host, port} of the server.
   //   |realm|    - the auth realm for the challenge.
-  //   |scheme|   - the authentication scheme for the challenge.
+  //   |scheme|   - the authentication scheme (i.e. basic, negotiate).
   //   |username| - login information for the realm.
   //   |password| - login information for the realm.
   //   |path|     - absolute path for a resource contained in the protection
@@ -70,7 +72,7 @@
   //   returns    - the entry that was just added/updated.
   Entry* Add(const GURL& origin,
              const std::string& realm,
-             const std::string& scheme,
+             HttpAuth::Scheme scheme,
              const std::string& auth_challenge,
              const string16& username,
              const string16& password,
@@ -80,13 +82,13 @@
   // if one exists AND if the cached identity matches (|username|, |password|).
   //   |origin|   - the {scheme, host, port} of the server.
   //   |realm|    - case sensitive realm string.
-  //   |scheme|   - authentication scheme
+  //   |scheme|   - the authentication scheme (i.e. basic, negotiate).
   //   |username| - condition to match.
   //   |password| - condition to match.
   //   returns    - true if an entry was removed.
   bool Remove(const GURL& origin,
               const std::string& realm,
-              const std::string& scheme,
+              HttpAuth::Scheme scheme,
               const string16& username,
               const string16& password);
 
@@ -97,7 +99,7 @@
   // cache, false otherwise.
   bool UpdateStaleChallenge(const GURL& origin,
                             const std::string& realm,
-                            const std::string& scheme,
+                            HttpAuth::Scheme scheme,
                             const std::string& auth_challenge);
 
  private:
@@ -119,8 +121,8 @@
     return realm_;
   }
 
-  // The authentication scheme string of the challenge
-  const std::string scheme() const {
+  // The authentication scheme of the challenge.
+  HttpAuth::Scheme scheme() const {
     return scheme_;
   }
 
@@ -161,10 +163,10 @@
   // Returns true if |dir| is contained within the realm's protection space.
   bool HasEnclosingPath(const std::string& dir);
 
-  // |origin_| contains the {scheme, host, port} of the server.
+  // |origin_| contains the {protocol, host, port} of the server.
   GURL origin_;
   std::string realm_;
-  std::string scheme_;
+  HttpAuth::Scheme scheme_;
 
   // Identity.
   std::string auth_challenge_;
diff --git a/net/http/http_auth_cache_unittest.cc b/net/http/http_auth_cache_unittest.cc
index 2c28969..e940527 100644
--- a/net/http/http_auth_cache_unittest.cc
+++ b/net/http/http_auth_cache_unittest.cc
@@ -19,10 +19,11 @@
 
 class MockAuthHandler : public HttpAuthHandler {
  public:
-  MockAuthHandler(const char* scheme, const std::string& realm,
+  MockAuthHandler(HttpAuth::Scheme scheme,
+                  const std::string& realm,
                   HttpAuth::Target target) {
     // Can't use initializer list since these are members of the base class.
-    scheme_ = scheme;
+    auth_scheme_ = scheme;
     realm_ = realm;
     score_ = 1;
     target_ = target;
@@ -53,8 +54,6 @@
   ~MockAuthHandler() {}
 };
 
-const char* kBasic = "basic";
-const char* kDigest = "digest";
 const char* kRealm1 = "Realm1";
 const char* kRealm2 = "Realm2";
 const char* kRealm3 = "Realm3";
@@ -80,48 +79,58 @@
   // Add cache entries for 3 realms: "Realm1", "Realm2", "Realm3"
 
   scoped_ptr<HttpAuthHandler> realm1_handler(
-      new MockAuthHandler(kBasic, kRealm1, HttpAuth::AUTH_SERVER));
-  cache.Add(origin, realm1_handler->realm(), realm1_handler->scheme(),
+      new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC,
+                          kRealm1,
+                          HttpAuth::AUTH_SERVER));
+  cache.Add(origin, realm1_handler->realm(), realm1_handler->auth_scheme(),
             "Basic realm=Realm1", ASCIIToUTF16("realm1-user"),
             ASCIIToUTF16("realm1-password"), "/foo/bar/index.html");
 
   scoped_ptr<HttpAuthHandler> realm2_handler(
-      new MockAuthHandler(kBasic, kRealm2, HttpAuth::AUTH_SERVER));
-  cache.Add(origin, realm2_handler->realm(), realm2_handler->scheme(),
+      new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC,
+                          kRealm2,
+                          HttpAuth::AUTH_SERVER));
+  cache.Add(origin, realm2_handler->realm(), realm2_handler->auth_scheme(),
             "Basic realm=Realm2", ASCIIToUTF16("realm2-user"),
             ASCIIToUTF16("realm2-password"), "/foo2/index.html");
 
   scoped_ptr<HttpAuthHandler> realm3_basic_handler(
-      new MockAuthHandler(kBasic, kRealm3, HttpAuth::AUTH_PROXY));
+      new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC,
+                          kRealm3,
+                          HttpAuth::AUTH_PROXY));
   cache.Add(origin, realm3_basic_handler->realm(),
-            realm3_basic_handler->scheme(), "Basic realm=Realm3",
+            realm3_basic_handler->auth_scheme(), "Basic realm=Realm3",
             ASCIIToUTF16("realm3-basic-user"),
             ASCIIToUTF16("realm3-basic-password"), "");
 
   scoped_ptr<HttpAuthHandler> realm3_digest_handler(
-      new MockAuthHandler(kDigest, kRealm3, HttpAuth::AUTH_PROXY));
+      new MockAuthHandler(HttpAuth::AUTH_SCHEME_DIGEST,
+                          kRealm3,
+                          HttpAuth::AUTH_PROXY));
   cache.Add(origin, realm3_digest_handler->realm(),
-            realm3_digest_handler->scheme(), "Digest realm=Realm3",
+            realm3_digest_handler->auth_scheme(), "Digest realm=Realm3",
             ASCIIToUTF16("realm3-digest-user"),
             ASCIIToUTF16("realm3-digest-password"), "/baz/index.html");
 
   // There is no Realm4
-  entry = cache.Lookup(origin, kRealm4, kBasic);
+  entry = cache.Lookup(origin, kRealm4, HttpAuth::AUTH_SCHEME_BASIC);
   EXPECT_TRUE(NULL == entry);
 
   // While Realm3 does exist, the origin scheme is wrong.
   entry = cache.Lookup(GURL("https://www.google.com"), kRealm3,
-                       kBasic);
+                       HttpAuth::AUTH_SCHEME_BASIC);
   EXPECT_TRUE(NULL == entry);
 
   // Realm, origin scheme ok, authentication scheme wrong
-  entry = cache.Lookup(GURL("http://www.google.com"), kRealm1, kDigest);
+  entry = cache.Lookup
+      (GURL("http://www.google.com"), kRealm1, HttpAuth::AUTH_SCHEME_DIGEST);
   EXPECT_TRUE(NULL == entry);
 
   // Valid lookup by origin, realm, scheme.
-  entry = cache.Lookup(GURL("http://www.google.com:80"), kRealm3, kBasic);
+  entry = cache.Lookup(
+      GURL("http://www.google.com:80"), kRealm3, HttpAuth::AUTH_SCHEME_BASIC);
   ASSERT_FALSE(NULL == entry);
-  EXPECT_EQ(kBasic, entry->scheme());
+  EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
   EXPECT_EQ(kRealm3, entry->realm());
   EXPECT_EQ("Basic realm=Realm3", entry->auth_challenge());
   EXPECT_EQ(ASCIIToUTF16("realm3-basic-user"), entry->username());
@@ -129,25 +138,27 @@
 
   // Valid lookup by origin, realm, scheme when there's a duplicate
   // origin, realm in the cache
-  entry = cache.Lookup(GURL("http://www.google.com:80"), kRealm3, kDigest);
+  entry = cache.Lookup(
+      GURL("http://www.google.com:80"), kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
   ASSERT_FALSE(NULL == entry);
-  EXPECT_EQ(kDigest, entry->scheme());
+  EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, entry->scheme());
   EXPECT_EQ(kRealm3, entry->realm());
   EXPECT_EQ("Digest realm=Realm3", entry->auth_challenge());
   EXPECT_EQ(ASCIIToUTF16("realm3-digest-user"), entry->username());
   EXPECT_EQ(ASCIIToUTF16("realm3-digest-password"), entry->password());
 
   // Valid lookup by realm.
-  entry = cache.Lookup(origin, kRealm2, kBasic);
+  entry = cache.Lookup(origin, kRealm2, HttpAuth::AUTH_SCHEME_BASIC);
   ASSERT_FALSE(NULL == entry);
-  EXPECT_EQ(kBasic, entry->scheme());
+  EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
   EXPECT_EQ(kRealm2, entry->realm());
   EXPECT_EQ("Basic realm=Realm2", entry->auth_challenge());
   EXPECT_EQ(ASCIIToUTF16("realm2-user"), entry->username());
   EXPECT_EQ(ASCIIToUTF16("realm2-password"), entry->password());
 
   // Check that subpaths are recognized.
-  HttpAuthCache::Entry* realm2_entry = cache.Lookup(origin, kRealm2, kBasic);
+  HttpAuthCache::Entry* realm2_entry = cache.Lookup(
+      origin, kRealm2, HttpAuth::AUTH_SCHEME_BASIC);
   EXPECT_FALSE(NULL == realm2_entry);
   // Positive tests:
   entry = cache.LookupByPath(origin, "/foo2/index.html");
@@ -171,7 +182,7 @@
 
   // Confirm we find the same realm, different auth scheme by path lookup
   HttpAuthCache::Entry* realm3_digest_entry =
-      cache.Lookup(origin, kRealm3, kDigest);
+      cache.Lookup(origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
   EXPECT_FALSE(NULL == realm3_digest_entry);
   entry = cache.LookupByPath(origin, "/baz/index.html");
   EXPECT_TRUE(realm3_digest_entry == entry);
@@ -182,7 +193,7 @@
 
   // Confirm we find the same realm, different auth scheme by path lookup
   HttpAuthCache::Entry* realm3DigestEntry =
-      cache.Lookup(origin, kRealm3, kDigest);
+      cache.Lookup(origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
   EXPECT_FALSE(NULL == realm3DigestEntry);
   entry = cache.LookupByPath(origin, "/baz/index.html");
   EXPECT_TRUE(realm3DigestEntry == entry);
@@ -194,7 +205,7 @@
   // Lookup using empty path (may be used for proxy).
   entry = cache.LookupByPath(origin, "");
   EXPECT_FALSE(NULL == entry);
-  EXPECT_EQ(kBasic, entry->scheme());
+  EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
   EXPECT_EQ(kRealm3, entry->realm());
 }
 
@@ -238,17 +249,18 @@
   const std::string auth_challenge = "Basic realm=MyRealm";
 
   scoped_ptr<HttpAuthHandler> handler(
-      new MockAuthHandler(kBasic, "MyRealm", HttpAuth::AUTH_SERVER));
-
+      new MockAuthHandler(
+          HttpAuth::AUTH_SCHEME_BASIC, "MyRealm", HttpAuth::AUTH_SERVER));
   HttpAuthCache::Entry* orig_entry = cache.Add(
-      origin, handler->realm(), handler->scheme(), auth_challenge,
+      origin, handler->realm(), handler->auth_scheme(), auth_challenge,
       ASCIIToUTF16("user1"), ASCIIToUTF16("password1"), "/x/y/z/");
-  cache.Add(origin, handler->realm(), handler->scheme(), auth_challenge,
+  cache.Add(origin, handler->realm(), handler->auth_scheme(), auth_challenge,
             ASCIIToUTF16("user2"), ASCIIToUTF16("password2"), "/z/y/x/");
-  cache.Add(origin, handler->realm(), handler->scheme(), auth_challenge,
+  cache.Add(origin, handler->realm(), handler->auth_scheme(), auth_challenge,
             ASCIIToUTF16("user3"), ASCIIToUTF16("password3"), "/z/y");
 
-  HttpAuthCache::Entry* entry = cache.Lookup(origin, "MyRealm", kBasic);
+  HttpAuthCache::Entry* entry = cache.Lookup(
+      origin, "MyRealm", HttpAuth::AUTH_SCHEME_BASIC);
 
   EXPECT_TRUE(entry == orig_entry);
   EXPECT_EQ(ASCIIToUTF16("user3"), entry->username());
@@ -263,64 +275,80 @@
   GURL origin("http://foobar2.com");
 
   scoped_ptr<HttpAuthHandler> realm1_handler(
-      new MockAuthHandler(kBasic, kRealm1, HttpAuth::AUTH_SERVER));
+      new MockAuthHandler(
+          HttpAuth::AUTH_SCHEME_BASIC, kRealm1, HttpAuth::AUTH_SERVER));
 
   scoped_ptr<HttpAuthHandler> realm2_handler(
-      new MockAuthHandler(kBasic, kRealm2, HttpAuth::AUTH_SERVER));
+      new MockAuthHandler(
+          HttpAuth::AUTH_SCHEME_BASIC, kRealm2, HttpAuth::AUTH_SERVER));
 
   scoped_ptr<HttpAuthHandler> realm3_basic_handler(
-      new MockAuthHandler(kBasic, kRealm3, HttpAuth::AUTH_SERVER));
+      new MockAuthHandler(
+          HttpAuth::AUTH_SCHEME_BASIC, kRealm3, HttpAuth::AUTH_SERVER));
 
   scoped_ptr<HttpAuthHandler> realm3_digest_handler(
-      new MockAuthHandler(kDigest, kRealm3, HttpAuth::AUTH_SERVER));
+      new MockAuthHandler(
+          HttpAuth::AUTH_SCHEME_DIGEST, kRealm3, HttpAuth::AUTH_SERVER));
 
   HttpAuthCache cache;
-  cache.Add(origin, realm1_handler->realm(), realm1_handler->scheme(),
+  cache.Add(origin, realm1_handler->realm(), realm1_handler->auth_scheme(),
             "basic realm=Realm1", kAlice, k123, "/");
-  cache.Add(origin, realm2_handler->realm(), realm2_handler->scheme(),
+  cache.Add(origin, realm2_handler->realm(), realm2_handler->auth_scheme(),
             "basic realm=Realm2", ASCIIToUTF16("bob"), ASCIIToUTF16("princess"),
             "/");
   cache.Add(origin, realm3_basic_handler->realm(),
-            realm3_basic_handler->scheme(), "basic realm=Realm3",
+            realm3_basic_handler->auth_scheme(), "basic realm=Realm3",
             kAdmin, kPassword, "/");
   cache.Add(origin, realm3_digest_handler->realm(),
-            realm3_digest_handler->scheme(), "digest realm=Realm3",
+            realm3_digest_handler->auth_scheme(), "digest realm=Realm3",
             kRoot, kWileCoyote, "/");
 
   // Fails, because there is no realm "Realm4".
-  EXPECT_FALSE(cache.Remove(origin, kRealm4, kBasic, kAlice, k123));
+  EXPECT_FALSE(cache.Remove(
+      origin, kRealm4, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k123));
 
   // Fails because the origin is wrong.
-  EXPECT_FALSE(cache.Remove(
-      GURL("http://foobar2.com:100"), kRealm1, kBasic, kAlice, k123));
+  EXPECT_FALSE(cache.Remove(GURL("http://foobar2.com:100"),
+                            kRealm1,
+                            HttpAuth::AUTH_SCHEME_BASIC,
+                            kAlice,
+                            k123));
 
   // Fails because the username is wrong.
-  EXPECT_FALSE(cache.Remove(origin, kRealm1, kBasic, kAlice2, k123));
+  EXPECT_FALSE(cache.Remove(
+      origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice2, k123));
 
   // Fails because the password is wrong.
-  EXPECT_FALSE(cache.Remove(origin, kRealm1, kBasic, kAlice, k1234));
+  EXPECT_FALSE(cache.Remove(
+      origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k1234));
 
   // Fails because the authentication type is wrong.
-  EXPECT_FALSE(cache.Remove(origin, kRealm1, kDigest, kAlice, k123));
+  EXPECT_FALSE(cache.Remove(
+      origin, kRealm1, HttpAuth::AUTH_SCHEME_DIGEST, kAlice, k123));
 
   // Succeeds.
-  EXPECT_TRUE(cache.Remove(origin, kRealm1, kBasic, kAlice, k123));
+  EXPECT_TRUE(cache.Remove(
+      origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k123));
 
   // Fails because we just deleted the entry!
-  EXPECT_FALSE(cache.Remove(origin, kRealm1, kBasic, kAlice, k123));
+  EXPECT_FALSE(cache.Remove(
+      origin, kRealm1, HttpAuth::AUTH_SCHEME_BASIC, kAlice, k123));
 
   // Succeed when there are two authentication types for the same origin,realm.
-  EXPECT_TRUE(cache.Remove(origin, kRealm3, kDigest, kRoot, kWileCoyote));
+  EXPECT_TRUE(cache.Remove(
+      origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST, kRoot, kWileCoyote));
 
   // Succeed as above, but when entries were added in opposite order
   cache.Add(origin, realm3_digest_handler->realm(),
-            realm3_digest_handler->scheme(), "digest realm=Realm3",
+            realm3_digest_handler->auth_scheme(), "digest realm=Realm3",
             kRoot, kWileCoyote, "/");
-  EXPECT_TRUE(cache.Remove(origin, kRealm3, kBasic, kAdmin, kPassword));
+  EXPECT_TRUE(cache.Remove(
+      origin, kRealm3, HttpAuth::AUTH_SCHEME_BASIC, kAdmin, kPassword));
 
   // Make sure that removing one entry still leaves the other available for
   // lookup.
-  HttpAuthCache::Entry* entry = cache.Lookup(origin, kRealm3, kDigest);
+  HttpAuthCache::Entry* entry = cache.Lookup(
+      origin, kRealm3, HttpAuth::AUTH_SCHEME_DIGEST);
   EXPECT_FALSE(NULL == entry);
 }
 
@@ -328,11 +356,12 @@
   HttpAuthCache cache;
   GURL origin("http://foobar2.com");
   scoped_ptr<HttpAuthHandler> digest_handler(
-      new MockAuthHandler(kDigest, kRealm1, HttpAuth::AUTH_PROXY));
+      new MockAuthHandler(
+          HttpAuth::AUTH_SCHEME_DIGEST, kRealm1, HttpAuth::AUTH_PROXY));
   HttpAuthCache::Entry* entry_pre = cache.Add(
       origin,
       digest_handler->realm(),
-      digest_handler->scheme(),
+      digest_handler->auth_scheme(),
       "Digest realm=Realm1,"
       "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\"",
       ASCIIToUTF16("realm-digest-user"),
@@ -347,7 +376,7 @@
   bool update_success = cache.UpdateStaleChallenge(
       origin,
       digest_handler->realm(),
-      digest_handler->scheme(),
+      digest_handler->auth_scheme(),
       "Digest realm=Realm1,"
       "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
       "stale=\"true\"");
@@ -358,7 +387,7 @@
   HttpAuthCache::Entry* entry_post = cache.Lookup(
       origin,
       digest_handler->realm(),
-      digest_handler->scheme());
+      digest_handler->auth_scheme());
   ASSERT_TRUE(entry_post != NULL);
   EXPECT_EQ(2, entry_post->IncrementNonceCount());
 
@@ -366,7 +395,7 @@
   bool update_failure = cache.UpdateStaleChallenge(
       origin,
       kRealm2,
-      digest_handler->scheme(),
+      digest_handler->auth_scheme(),
       "Digest realm=Realm2,"
       "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
       "stale=\"true\"");
@@ -392,13 +421,14 @@
   }
 
   void AddPathToRealm(int realm_i, int path_i) {
-    cache_.Add(origin_, GenerateRealm(realm_i), kBasic, "",
+    cache_.Add(origin_, GenerateRealm(realm_i), HttpAuth::AUTH_SCHEME_BASIC, "",
                kUsername, kPassword, GeneratePath(realm_i, path_i));
   }
 
   void CheckRealmExistence(int realm_i, bool exists) {
     const HttpAuthCache::Entry* entry =
-        cache_.Lookup(origin_, GenerateRealm(realm_i), kBasic);
+        cache_.Lookup(
+            origin_, GenerateRealm(realm_i), HttpAuth::AUTH_SCHEME_BASIC);
     if (exists) {
       EXPECT_FALSE(entry == NULL);
       EXPECT_EQ(GenerateRealm(realm_i), entry->realm());
diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc
index ddd0bdb..f438ea4 100644
--- a/net/http/http_auth_controller.cc
+++ b/net/http/http_auth_controller.cc
@@ -96,8 +96,8 @@
   DCHECK_EQ(first_thread, base::PlatformThread::CurrentId());
 #endif
 
-  HttpAuthHandler::AuthScheme auth_scheme = handler->auth_scheme();
-  DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuthHandler::AUTH_SCHEME_MAX);
+  HttpAuth::Scheme auth_scheme = handler->auth_scheme();
+  DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuth::AUTH_SCHEME_MAX);
 
   // Record start and rejection events for authentication.
   //
@@ -111,7 +111,7 @@
   //   Negotiate Start: 6
   //   Negotiate Reject: 7
   static const int kEventBucketsEnd =
-      HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_EVENT_MAX;
+      HttpAuth::AUTH_SCHEME_MAX * AUTH_EVENT_MAX;
   int event_bucket = auth_scheme * AUTH_EVENT_MAX + auth_event;
   DCHECK(event_bucket >= 0 && event_bucket < kEventBucketsEnd);
   UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthCount", event_bucket,
@@ -139,7 +139,7 @@
   if (auth_event != AUTH_EVENT_START)
     return;
   static const int kTargetBucketsEnd =
-      HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_TARGET_MAX;
+      HttpAuth::AUTH_SCHEME_MAX * AUTH_TARGET_MAX;
   AuthTarget auth_target = DetermineAuthTarget(handler);
   int target_bucket = auth_scheme * AUTH_TARGET_MAX + auth_target;
   DCHECK(target_bucket >= 0 && target_bucket < kTargetBucketsEnd);
@@ -282,7 +282,7 @@
       case HttpAuth::AUTHORIZATION_RESULT_STALE:
         if (http_auth_cache_->UpdateStaleChallenge(auth_origin_,
                                                    handler_->realm(),
-                                                   handler_->scheme(),
+                                                   handler_->auth_scheme(),
                                                    challenge_used)) {
           handler_.reset();
           identity_ = HttpAuth::Identity();
@@ -388,7 +388,7 @@
       break;
     default:
       http_auth_cache_->Add(auth_origin_, handler_->realm(),
-                            handler_->scheme(), handler_->challenge(),
+                            handler_->auth_scheme(), handler_->challenge(),
                             identity_.username, identity_.password,
                             auth_path_);
       break;
@@ -426,7 +426,7 @@
   // Note: we require the username/password to match before invalidating
   // since the entry in the cache may be newer than what we used last time.
   http_auth_cache_->Remove(auth_origin_, handler_->realm(),
-                           handler_->scheme(), identity_.username,
+                           handler_->auth_scheme(), identity_.username,
                            identity_.password);
 }
 
@@ -453,7 +453,7 @@
   // Check the auth cache for a realm entry.
   HttpAuthCache::Entry* entry =
       http_auth_cache_->Lookup(auth_origin_, handler_->realm(),
-                               handler_->scheme());
+                               handler_->auth_scheme());
 
   if (entry) {
     identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
@@ -487,7 +487,8 @@
   auth_info_ = new AuthChallengeInfo;
   auth_info_->is_proxy = target_ == HttpAuth::AUTH_PROXY;
   auth_info_->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin_));
-  auth_info_->scheme = ASCIIToWide(handler_->scheme());
+  auth_info_->scheme = ASCIIToWide(
+      HttpAuth::SchemeToString(handler_->auth_scheme()));
   // TODO(eroman): decode realm according to RFC 2047.
   auth_info_->realm = ASCIIToWide(handler_->realm());
 }
@@ -497,7 +498,7 @@
   // This error occurs with GSSAPI, if the user has not already logged in.
   // In that case, disable the current scheme as it cannot succeed.
   if (result == ERR_MISSING_AUTH_CREDENTIALS) {
-    DisableAuthScheme(handler_->scheme());
+    DisableAuthScheme(handler_->auth_scheme());
     auth_token_.clear();
     result = OK;
   }
@@ -513,12 +514,12 @@
   return auth_info_;
 }
 
-bool HttpAuthController::IsAuthSchemeDisabled(const std::string& scheme) const {
+bool HttpAuthController::IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const {
   DCHECK(CalledOnValidThread());
   return disabled_schemes_.find(scheme) != disabled_schemes_.end();
 }
 
-void HttpAuthController::DisableAuthScheme(const std::string& scheme) {
+void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) {
   DCHECK(CalledOnValidThread());
   disabled_schemes_.insert(scheme);
 }
diff --git a/net/http/http_auth_controller.h b/net/http/http_auth_controller.h
index 85d9fa1..0b7f430 100644
--- a/net/http/http_auth_controller.h
+++ b/net/http/http_auth_controller.h
@@ -69,8 +69,8 @@
 
   virtual scoped_refptr<AuthChallengeInfo> auth_info();
 
-  virtual bool IsAuthSchemeDisabled(const std::string& scheme) const;
-  virtual void DisableAuthScheme(const std::string& scheme);
+  virtual bool IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const;
+  virtual void DisableAuthScheme(HttpAuth::Scheme scheme);
 
  private:
   // So that we can mock this object.
@@ -146,7 +146,7 @@
   HttpAuthCache* const http_auth_cache_;
   HttpAuthHandlerFactory* const http_auth_handler_factory_;
 
-  std::set<std::string> disabled_schemes_;
+  std::set<HttpAuth::Scheme> disabled_schemes_;
 
   CompletionCallbackImpl<HttpAuthController> io_callback_;
   CompletionCallback* user_callback_;
diff --git a/net/http/http_auth_filter.cc b/net/http/http_auth_filter.cc
index a61e7f7..2109e4d 100644
--- a/net/http/http_auth_filter.cc
+++ b/net/http/http_auth_filter.cc
@@ -24,21 +24,6 @@
 HttpAuthFilterWhitelist::~HttpAuthFilterWhitelist() {
 }
 
-void HttpAuthFilterWhitelist::SetWhitelist(
-    const std::string& server_whitelist) {
-  rules_.ParseFromString(server_whitelist);
-}
-
-bool HttpAuthFilterWhitelist::IsValid(const GURL& url,
-                                      HttpAuth::Target target) const {
-  if ((target != HttpAuth::AUTH_SERVER) && (target != HttpAuth::AUTH_PROXY))
-    return false;
-  // All proxies pass
-  if (target == HttpAuth::AUTH_PROXY)
-    return true;
-  return rules_.Matches(url);
-}
-
 // Add a new domain |filter| to the whitelist, if it's not already there
 bool HttpAuthFilterWhitelist::AddFilter(const std::string& filter,
                                         HttpAuth::Target target) {
@@ -55,4 +40,19 @@
   rules_.AddRuleToBypassLocal();
 }
 
+bool HttpAuthFilterWhitelist::IsValid(const GURL& url,
+                                      HttpAuth::Target target) const {
+  if ((target != HttpAuth::AUTH_SERVER) && (target != HttpAuth::AUTH_PROXY))
+    return false;
+  // All proxies pass
+  if (target == HttpAuth::AUTH_PROXY)
+    return true;
+  return rules_.Matches(url);
+}
+
+void HttpAuthFilterWhitelist::SetWhitelist(
+    const std::string& server_whitelist) {
+  rules_.ParseFromString(server_whitelist);
+}
+
 }  // namespace net
diff --git a/net/http/http_auth_filter.h b/net/http/http_auth_filter.h
index 334bc91..81d414c 100644
--- a/net/http/http_auth_filter.h
+++ b/net/http/http_auth_filter.h
@@ -37,9 +37,6 @@
   explicit HttpAuthFilterWhitelist(const std::string& server_whitelist);
   virtual ~HttpAuthFilterWhitelist();
 
-  // HttpAuthFilter methods:
-  virtual bool IsValid(const GURL& url, HttpAuth::Target target) const;
-
   // Adds an individual URL |filter| to the list, of the specified |target|.
   bool AddFilter(const std::string& filter, HttpAuth::Target target);
 
@@ -48,6 +45,9 @@
 
   const ProxyBypassRules& rules() const { return rules_; }
 
+  // HttpAuthFilter methods:
+  virtual bool IsValid(const GURL& url, HttpAuth::Target target) const;
+
  private:
   // Installs the whitelist.
   // |server_whitelist| is parsed by ProxyBypassRules.
diff --git a/net/http/http_auth_gssapi_posix_unittest.cc b/net/http/http_auth_gssapi_posix_unittest.cc
index f83acb4..43a3285 100644
--- a/net/http/http_auth_gssapi_posix_unittest.cc
+++ b/net/http/http_auth_gssapi_posix_unittest.cc
@@ -109,23 +109,20 @@
       1,                              // Locally initiated
       1);                             // Open
   test::MockGSSAPILibrary::SecurityContextQuery queries[] = {
-    { "Negotiate",                    // Package name
-      GSS_S_CONTINUE_NEEDED,          // Major response code
-      0,                              // Minor response code
-      context1,                       // Context
-      { 0, NULL },                           // Expected input token
-      { arraysize(kAuthResponse),
-        const_cast<char*>(kAuthResponse) }   // Output token
-    },
-    { "Negotiate",                    // Package name
-      GSS_S_COMPLETE,                 // Major response code
-      0,                              // Minor response code
-      context2,                       // Context
-      { arraysize(kAuthResponse),
-        const_cast<char*>(kAuthResponse) },  // Expected input token
-      { arraysize(kAuthResponse),
-        const_cast<char*>(kAuthResponse) }   // Output token
-    },
+    test::MockGSSAPILibrary::SecurityContextQuery(
+        "Negotiate",            // Package name
+        GSS_S_CONTINUE_NEEDED,  // Major response code
+        0,                      // Minor response code
+        context1,               // Context
+        NULL,                   // Expected input token
+        kAuthResponse),         // Output token
+    test::MockGSSAPILibrary::SecurityContextQuery(
+        "Negotiate",            // Package name
+        GSS_S_COMPLETE,         // Major response code
+        0,                      // Minor response code
+        context2,               // Context
+        kAuthResponse,          // Expected input token
+        kAuthResponse)          // Output token
   };
 
   for (size_t i = 0; i < arraysize(queries); ++i) {
diff --git a/net/http/http_auth_handler.cc b/net/http/http_auth_handler.cc
index 130123b..51bd6aa 100644
--- a/net/http/http_auth_handler.cc
+++ b/net/http/http_auth_handler.cc
@@ -5,14 +5,12 @@
 #include "net/http/http_auth_handler.h"
 
 #include "base/logging.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
 #include "net/base/net_errors.h"
 
 namespace net {
 
 HttpAuthHandler::HttpAuthHandler()
-    : auth_scheme_(AUTH_SCHEME_MAX),
+    : auth_scheme_(HttpAuth::AUTH_SCHEME_MAX),
       score_(-1),
       target_(HttpAuth::AUTH_NONE),
       properties_(-1),
@@ -41,10 +39,9 @@
 
   // Init() is expected to set the scheme, realm, score, and properties.  The
   // realm may be empty.
-  DCHECK(!ok || !scheme().empty());
   DCHECK(!ok || score_ != -1);
   DCHECK(!ok || properties_ != -1);
-  DCHECK(!ok || auth_scheme_ != AUTH_SCHEME_MAX);
+  DCHECK(!ok || auth_scheme_ != HttpAuth::AUTH_SCHEME_MAX);
 
   return ok;
 }
diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h
index 65340df..0a574e5 100644
--- a/net/http/http_auth_handler.h
+++ b/net/http/http_auth_handler.h
@@ -22,14 +22,6 @@
 // HttpAuthHandler objects are typically created by an HttpAuthHandlerFactory.
 class HttpAuthHandler {
  public:
-  enum AuthScheme {
-    AUTH_SCHEME_BASIC = 0,
-    AUTH_SCHEME_DIGEST,
-    AUTH_SCHEME_NTLM,
-    AUTH_SCHEME_NEGOTIATE,
-    AUTH_SCHEME_MAX,
-  };
-
   HttpAuthHandler();
   virtual ~HttpAuthHandler();
 
@@ -84,15 +76,10 @@
                         std::string* auth_token);
 
   // The authentication scheme as an enumerated value.
-  AuthScheme auth_scheme() const {
+  HttpAuth::Scheme auth_scheme() const {
     return auth_scheme_;
   }
 
-  // Lowercase name of the auth scheme
-  const std::string& scheme() const {
-    return scheme_;
-  }
-
   // The realm value that was parsed during Init().
   const std::string& realm() const {
     return realm_;
@@ -171,10 +158,7 @@
                                     std::string* auth_token) = 0;
 
   // The auth-scheme as an enumerated value.
-  AuthScheme auth_scheme_;
-
-  // The lowercase auth-scheme {"basic", "digest", "ntlm", "negotiate"}
-  std::string scheme_;
+  HttpAuth::Scheme auth_scheme_;
 
   // The realm.  Used by "basic" and "digest".
   std::string realm_;
diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc
index 8ee775d..e48aa67 100644
--- a/net/http/http_auth_handler_basic.cc
+++ b/net/http/http_auth_handler_basic.cc
@@ -23,8 +23,7 @@
 // We allow it to be compatibility with certain embedded webservers that don't
 // include a realm (see http://crbug.com/20984.)
 bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) {
-  auth_scheme_ = AUTH_SCHEME_BASIC;
-  scheme_ = "basic";
+  auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC;
   score_ = 1;
   properties_ = 0;
   return ParseChallenge(challenge);
diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc
index 2b103f4..e8cb819 100644
--- a/net/http/http_auth_handler_digest.cc
+++ b/net/http/http_auth_handler_digest.cc
@@ -74,6 +74,193 @@
   return nonce_;
 }
 
+HttpAuthHandlerDigest::Factory::Factory()
+    : nonce_generator_(new DynamicNonceGenerator()) {
+}
+
+HttpAuthHandlerDigest::Factory::~Factory() {
+}
+
+void HttpAuthHandlerDigest::Factory::set_nonce_generator(
+    const NonceGenerator* nonce_generator) {
+  nonce_generator_.reset(nonce_generator);
+}
+
+int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
+    HttpAuth::ChallengeTokenizer* challenge,
+    HttpAuth::Target target,
+    const GURL& origin,
+    CreateReason reason,
+    int digest_nonce_count,
+    const BoundNetLog& net_log,
+    scoped_ptr<HttpAuthHandler>* handler) {
+  // TODO(cbentzel): Move towards model of parsing in the factory
+  //                 method and only constructing when valid.
+  scoped_ptr<HttpAuthHandler> tmp_handler(
+      new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get()));
+  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+    return ERR_INVALID_RESPONSE;
+  handler->swap(tmp_handler);
+  return OK;
+}
+
+HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
+    HttpAuth::ChallengeTokenizer* challenge) {
+  // Even though Digest is not connection based, a "second round" is parsed
+  // to differentiate between stale and rejected responses.
+  // Note that the state of the current handler is not mutated - this way if
+  // there is a rejection the realm hasn't changed.
+  if (!LowerCaseEqualsASCII(challenge->scheme(), "digest"))
+    return HttpAuth::AUTHORIZATION_RESULT_INVALID;
+
+  HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
+
+  // Try to find the "stale" value.
+  while (parameters.GetNext()) {
+    if (!LowerCaseEqualsASCII(parameters.name(), "stale"))
+      continue;
+    if (LowerCaseEqualsASCII(parameters.value(), "true"))
+      return HttpAuth::AUTHORIZATION_RESULT_STALE;
+  }
+
+  return HttpAuth::AUTHORIZATION_RESULT_REJECT;
+}
+
+bool HttpAuthHandlerDigest::Init(HttpAuth::ChallengeTokenizer* challenge) {
+  return ParseChallenge(challenge);
+}
+
+int HttpAuthHandlerDigest::GenerateAuthTokenImpl(
+    const string16* username,
+    const string16* password,
+    const HttpRequestInfo* request,
+    CompletionCallback* callback,
+    std::string* auth_token) {
+  // Generate a random client nonce.
+  std::string cnonce = nonce_generator_->GenerateNonce();
+
+  // Extract the request method and path -- the meaning of 'path' is overloaded
+  // in certain cases, to be a hostname.
+  std::string method;
+  std::string path;
+  GetRequestMethodAndPath(request, &method, &path);
+
+  *auth_token = AssembleCredentials(method, path,
+                                    *username,
+                                    *password,
+                                    cnonce, nonce_count_);
+  return OK;
+}
+
+HttpAuthHandlerDigest::HttpAuthHandlerDigest(
+    int nonce_count, const NonceGenerator* nonce_generator)
+    : stale_(false),
+      algorithm_(ALGORITHM_UNSPECIFIED),
+      qop_(QOP_UNSPECIFIED),
+      nonce_count_(nonce_count),
+      nonce_generator_(nonce_generator) {
+  DCHECK(nonce_generator_);
+}
+
+HttpAuthHandlerDigest::~HttpAuthHandlerDigest() {
+}
+
+// The digest challenge header looks like:
+//   WWW-Authenticate: Digest
+//     [realm="<realm-value>"]
+//     nonce="<nonce-value>"
+//     [domain="<list-of-URIs>"]
+//     [opaque="<opaque-token-value>"]
+//     [stale="<true-or-false>"]
+//     [algorithm="<digest-algorithm>"]
+//     [qop="<list-of-qop-values>"]
+//     [<extension-directive>]
+//
+// Note that according to RFC 2617 (section 1.2) the realm is required.
+// However we allow it to be omitted, in which case it will default to the
+// empty string.
+//
+// This allowance is for better compatibility with webservers that fail to
+// send the realm (See http://crbug.com/20984 for an instance where a
+// webserver was not sending the realm with a BASIC challenge).
+bool HttpAuthHandlerDigest::ParseChallenge(
+    HttpAuth::ChallengeTokenizer* challenge) {
+  auth_scheme_ = HttpAuth::AUTH_SCHEME_DIGEST;
+  score_ = 2;
+  properties_ = ENCRYPTS_IDENTITY;
+
+  // Initialize to defaults.
+  stale_ = false;
+  algorithm_ = ALGORITHM_UNSPECIFIED;
+  qop_ = QOP_UNSPECIFIED;
+  realm_ = nonce_ = domain_ = opaque_ = std::string();
+
+  // FAIL -- Couldn't match auth-scheme.
+  if (!LowerCaseEqualsASCII(challenge->scheme(), "digest"))
+    return false;
+
+  HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
+
+  // Loop through all the properties.
+  while (parameters.GetNext()) {
+    // FAIL -- couldn't parse a property.
+    if (!ParseChallengeProperty(parameters.name(),
+                                parameters.value()))
+      return false;
+  }
+
+  // Check if tokenizer failed.
+  if (!parameters.valid())
+    return false;
+
+  // Check that a minimum set of properties were provided.
+  if (nonce_.empty())
+    return false;
+
+  return true;
+}
+
+bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name,
+                                                   const std::string& value) {
+  if (LowerCaseEqualsASCII(name, "realm")) {
+    realm_ = value;
+  } else if (LowerCaseEqualsASCII(name, "nonce")) {
+    nonce_ = value;
+  } else if (LowerCaseEqualsASCII(name, "domain")) {
+    domain_ = value;
+  } else if (LowerCaseEqualsASCII(name, "opaque")) {
+    opaque_ = value;
+  } else if (LowerCaseEqualsASCII(name, "stale")) {
+    // Parse the stale boolean.
+    stale_ = LowerCaseEqualsASCII(value, "true");
+  } else if (LowerCaseEqualsASCII(name, "algorithm")) {
+    // Parse the algorithm.
+    if (LowerCaseEqualsASCII(value, "md5")) {
+      algorithm_ = ALGORITHM_MD5;
+    } else if (LowerCaseEqualsASCII(value, "md5-sess")) {
+      algorithm_ = ALGORITHM_MD5_SESS;
+    } else {
+      DVLOG(1) << "Unknown value of algorithm";
+      return false;  // FAIL -- unsupported value of algorithm.
+    }
+  } else if (LowerCaseEqualsASCII(name, "qop")) {
+    // Parse the comma separated list of qops.
+    // auth is the only supported qop, and all other values are ignored.
+    HttpUtil::ValuesIterator qop_values(value.begin(), value.end(), ',');
+    qop_ = QOP_UNSPECIFIED;
+    while (qop_values.GetNext()) {
+      if (LowerCaseEqualsASCII(qop_values.value(), "auth")) {
+        qop_ = QOP_AUTH;
+        break;
+      }
+    }
+  } else {
+    DVLOG(1) << "Skipping unrecognized digest property";
+    // TODO(eroman): perhaps we should fail instead of silently skipping?
+  }
+  return true;
+}
+
 // static
 std::string HttpAuthHandlerDigest::QopToString(QualityOfProtection qop) {
   switch (qop) {
@@ -103,41 +290,6 @@
   }
 }
 
-HttpAuthHandlerDigest::HttpAuthHandlerDigest(
-    int nonce_count, const NonceGenerator* nonce_generator)
-    : stale_(false),
-      algorithm_(ALGORITHM_UNSPECIFIED),
-      qop_(QOP_UNSPECIFIED),
-      nonce_count_(nonce_count),
-      nonce_generator_(nonce_generator) {
-  DCHECK(nonce_generator_);
-}
-
-HttpAuthHandlerDigest::~HttpAuthHandlerDigest() {
-}
-
-int HttpAuthHandlerDigest::GenerateAuthTokenImpl(
-    const string16* username,
-    const string16* password,
-    const HttpRequestInfo* request,
-    CompletionCallback* callback,
-    std::string* auth_token) {
-  // Generate a random client nonce.
-  std::string cnonce = nonce_generator_->GenerateNonce();
-
-  // Extract the request method and path -- the meaning of 'path' is overloaded
-  // in certain cases, to be a hostname.
-  std::string method;
-  std::string path;
-  GetRequestMethodAndPath(request, &method, &path);
-
-  *auth_token = AssembleCredentials(method, path,
-                                    *username,
-                                    *password,
-                                    cnonce, nonce_count_);
-  return OK;
-}
-
 void HttpAuthHandlerDigest::GetRequestMethodAndPath(
     const HttpRequestInfo* request,
     std::string* method,
@@ -220,157 +372,4 @@
   return authorization;
 }
 
-bool HttpAuthHandlerDigest::Init(HttpAuth::ChallengeTokenizer* challenge) {
-  return ParseChallenge(challenge);
-}
-
-HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
-    HttpAuth::ChallengeTokenizer* challenge) {
-  // Even though Digest is not connection based, a "second round" is parsed
-  // to differentiate between stale and rejected responses.
-  // Note that the state of the current handler is not mutated - this way if
-  // there is a rejection the realm hasn't changed.
-  if (!LowerCaseEqualsASCII(challenge->scheme(), "digest"))
-    return HttpAuth::AUTHORIZATION_RESULT_INVALID;
-
-  HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
-
-  // Try to find the "stale" value.
-  while (parameters.GetNext()) {
-    if (!LowerCaseEqualsASCII(parameters.name(), "stale"))
-      continue;
-    if (LowerCaseEqualsASCII(parameters.value(), "true"))
-      return HttpAuth::AUTHORIZATION_RESULT_STALE;
-  }
-
-  return HttpAuth::AUTHORIZATION_RESULT_REJECT;
-}
-
-// The digest challenge header looks like:
-//   WWW-Authenticate: Digest
-//     [realm="<realm-value>"]
-//     nonce="<nonce-value>"
-//     [domain="<list-of-URIs>"]
-//     [opaque="<opaque-token-value>"]
-//     [stale="<true-or-false>"]
-//     [algorithm="<digest-algorithm>"]
-//     [qop="<list-of-qop-values>"]
-//     [<extension-directive>]
-//
-// Note that according to RFC 2617 (section 1.2) the realm is required.
-// However we allow it to be omitted, in which case it will default to the
-// empty string.
-//
-// This allowance is for better compatibility with webservers that fail to
-// send the realm (See http://crbug.com/20984 for an instance where a
-// webserver was not sending the realm with a BASIC challenge).
-bool HttpAuthHandlerDigest::ParseChallenge(
-    HttpAuth::ChallengeTokenizer* challenge) {
-  auth_scheme_ = AUTH_SCHEME_DIGEST;
-  scheme_ = "digest";
-  score_ = 2;
-  properties_ = ENCRYPTS_IDENTITY;
-
-  // Initialize to defaults.
-  stale_ = false;
-  algorithm_ = ALGORITHM_UNSPECIFIED;
-  qop_ = QOP_UNSPECIFIED;
-  realm_ = nonce_ = domain_ = opaque_ = std::string();
-
-  // FAIL -- Couldn't match auth-scheme.
-  if (!LowerCaseEqualsASCII(challenge->scheme(), "digest"))
-    return false;
-
-  HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
-
-  // Loop through all the properties.
-  while (parameters.GetNext()) {
-    // FAIL -- couldn't parse a property.
-    if (!ParseChallengeProperty(parameters.name(),
-                                parameters.value()))
-      return false;
-  }
-
-  // Check if tokenizer failed.
-  if (!parameters.valid())
-    return false;
-
-  // Check that a minimum set of properties were provided.
-  if (nonce_.empty())
-    return false;
-
-  return true;
-}
-
-bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name,
-                                                   const std::string& value) {
-  if (LowerCaseEqualsASCII(name, "realm")) {
-    realm_ = value;
-  } else if (LowerCaseEqualsASCII(name, "nonce")) {
-    nonce_ = value;
-  } else if (LowerCaseEqualsASCII(name, "domain")) {
-    domain_ = value;
-  } else if (LowerCaseEqualsASCII(name, "opaque")) {
-    opaque_ = value;
-  } else if (LowerCaseEqualsASCII(name, "stale")) {
-    // Parse the stale boolean.
-    stale_ = LowerCaseEqualsASCII(value, "true");
-  } else if (LowerCaseEqualsASCII(name, "algorithm")) {
-    // Parse the algorithm.
-    if (LowerCaseEqualsASCII(value, "md5")) {
-      algorithm_ = ALGORITHM_MD5;
-    } else if (LowerCaseEqualsASCII(value, "md5-sess")) {
-      algorithm_ = ALGORITHM_MD5_SESS;
-    } else {
-      DVLOG(1) << "Unknown value of algorithm";
-      return false;  // FAIL -- unsupported value of algorithm.
-    }
-  } else if (LowerCaseEqualsASCII(name, "qop")) {
-    // Parse the comma separated list of qops.
-    // auth is the only supported qop, and all other values are ignored.
-    HttpUtil::ValuesIterator qop_values(value.begin(), value.end(), ',');
-    qop_ = QOP_UNSPECIFIED;
-    while (qop_values.GetNext()) {
-      if (LowerCaseEqualsASCII(qop_values.value(), "auth")) {
-        qop_ = QOP_AUTH;
-        break;
-      }
-    }
-  } else {
-    DVLOG(1) << "Skipping unrecognized digest property";
-    // TODO(eroman): perhaps we should fail instead of silently skipping?
-  }
-  return true;
-}
-
-HttpAuthHandlerDigest::Factory::Factory()
-    : nonce_generator_(new DynamicNonceGenerator()) {
-}
-
-HttpAuthHandlerDigest::Factory::~Factory() {
-}
-
-void HttpAuthHandlerDigest::Factory::set_nonce_generator(
-    const NonceGenerator* nonce_generator) {
-  nonce_generator_.reset(nonce_generator);
-}
-
-int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
-    HttpAuth::ChallengeTokenizer* challenge,
-    HttpAuth::Target target,
-    const GURL& origin,
-    CreateReason reason,
-    int digest_nonce_count,
-    const BoundNetLog& net_log,
-    scoped_ptr<HttpAuthHandler>* handler) {
-  // TODO(cbentzel): Move towards model of parsing in the factory
-  //                 method and only constructing when valid.
-  scoped_ptr<HttpAuthHandler> tmp_handler(
-      new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get()));
-  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
-    return ERR_INVALID_RESPONSE;
-  handler->swap(tmp_handler);
-  return OK;
-}
-
 }  // namespace net
diff --git a/net/http/http_auth_handler_digest.h b/net/http/http_auth_handler_digest.h
index c319f5d..fca77e4 100644
--- a/net/http/http_auth_handler_digest.h
+++ b/net/http/http_auth_handler_digest.h
@@ -62,6 +62,9 @@
     Factory();
     virtual ~Factory();
 
+    // This factory owns the passed in |nonce_generator|.
+    void set_nonce_generator(const NonceGenerator* nonce_generator);
+
     virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
                                   HttpAuth::Target target,
                                   const GURL& origin,
@@ -70,9 +73,6 @@
                                   const BoundNetLog& net_log,
                                   scoped_ptr<HttpAuthHandler>* handler);
 
-    // This factory owns the passed in |nonce_generator|.
-    void set_nonce_generator(const NonceGenerator* nonce_generator);
-
    private:
     scoped_ptr<const NonceGenerator> nonce_generator_;
   };
diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc
index 7d34cff..8cf7d3e 100644
--- a/net/http/http_auth_handler_factory.cc
+++ b/net/http/http_auth_handler_factory.cc
@@ -79,6 +79,46 @@
 
 }  // namespace
 
+HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() {
+}
+
+HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() {
+  STLDeleteContainerPairSecondPointers(factory_map_.begin(),
+                                       factory_map_.end());
+}
+
+void HttpAuthHandlerRegistryFactory::SetURLSecurityManager(
+    const std::string& scheme,
+    URLSecurityManager* security_manager) {
+  HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme);
+  if (factory)
+    factory->set_url_security_manager(security_manager);
+}
+
+void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory(
+    const std::string& scheme,
+    HttpAuthHandlerFactory* factory) {
+  std::string lower_scheme = StringToLowerASCII(scheme);
+  FactoryMap::iterator it = factory_map_.find(lower_scheme);
+  if (it != factory_map_.end()) {
+    delete it->second;
+  }
+  if (factory)
+    factory_map_[lower_scheme] = factory;
+  else
+    factory_map_.erase(it);
+}
+
+HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory(
+    const std::string& scheme) const {
+  std::string lower_scheme = StringToLowerASCII(scheme);
+  FactoryMap::const_iterator it = factory_map_.find(lower_scheme);
+  if (it == factory_map_.end()) {
+    return NULL;                  // |scheme| is not registered.
+  }
+  return it->second;
+}
+
 // static
 HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
     const std::vector<std::string>& supported_schemes,
@@ -124,36 +164,6 @@
   return registry_factory;
 }
 
-HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() {
-}
-
-HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() {
-  STLDeleteContainerPairSecondPointers(factory_map_.begin(),
-                                       factory_map_.end());
-}
-
-void HttpAuthHandlerRegistryFactory::SetURLSecurityManager(
-    const std::string& scheme,
-    URLSecurityManager* security_manager) {
-  HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme);
-  if (factory)
-    factory->set_url_security_manager(security_manager);
-}
-
-void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory(
-    const std::string& scheme,
-    HttpAuthHandlerFactory* factory) {
-  std::string lower_scheme = StringToLowerASCII(scheme);
-  FactoryMap::iterator it = factory_map_.find(lower_scheme);
-  if (it != factory_map_.end()) {
-    delete it->second;
-  }
-  if (factory)
-    factory_map_[lower_scheme] = factory;
-  else
-    factory_map_.erase(it);
-}
-
 int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
     HttpAuth::ChallengeTokenizer* challenge,
     HttpAuth::Target target,
@@ -178,14 +188,4 @@
                                        digest_nonce_count, net_log, handler);
 }
 
-HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory(
-    const std::string& scheme) const {
-  std::string lower_scheme = StringToLowerASCII(scheme);
-  FactoryMap::const_iterator it = factory_map_.find(lower_scheme);
-  if (it == factory_map_.end()) {
-    return NULL;                  // |scheme| is not registered.
-  }
-  return it->second;
-}
-
 }  // namespace net
diff --git a/net/http/http_auth_handler_factory.h b/net/http/http_auth_handler_factory.h
index 2879aed..1e4134f 100644
--- a/net/http/http_auth_handler_factory.h
+++ b/net/http/http_auth_handler_factory.h
@@ -28,6 +28,11 @@
 // objects that it creates.
 class HttpAuthHandlerFactory {
  public:
+  enum CreateReason {
+    CREATE_CHALLENGE,     // Create a handler in response to a challenge.
+    CREATE_PREEMPTIVE,    // Create a handler preemptively.
+  };
+
   HttpAuthHandlerFactory() : url_security_manager_(NULL) {}
   virtual ~HttpAuthHandlerFactory() {}
 
@@ -42,11 +47,6 @@
     return url_security_manager_;
   }
 
-  enum CreateReason {
-    CREATE_CHALLENGE,  // Create a handler in response to a challenge.
-    CREATE_PREEMPTIVE,    // Create a handler preemptively.
-  };
-
   // Creates an HttpAuthHandler object based on the authentication
   // challenge specified by |*challenge|. |challenge| must point to a valid
   // non-NULL tokenizer.
@@ -152,16 +152,6 @@
   // registry factory is destroyed.
   HttpAuthHandlerFactory* GetSchemeFactory(const std::string& scheme) const;
 
-  // Creates an auth handler by dispatching out to the registered factories
-  // based on the first token in |challenge|.
-  virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
-                                HttpAuth::Target target,
-                                const GURL& origin,
-                                CreateReason reason,
-                                int digest_nonce_count,
-                                const BoundNetLog& net_log,
-                                scoped_ptr<HttpAuthHandler>* handler);
-
   // Creates an HttpAuthHandlerRegistryFactory.
   //
   // |supported_schemes| is a list of authentication schemes. Valid values
@@ -189,6 +179,16 @@
       bool negotiate_disable_cname_lookup,
       bool negotiate_enable_port);
 
+  // Creates an auth handler by dispatching out to the registered factories
+  // based on the first token in |challenge|.
+  virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
+                                HttpAuth::Target target,
+                                const GURL& origin,
+                                CreateReason reason,
+                                int digest_nonce_count,
+                                const BoundNetLog& net_log,
+                                scoped_ptr<HttpAuthHandler>* handler);
+
  private:
   typedef std::map<std::string, HttpAuthHandlerFactory*> FactoryMap;
 
diff --git a/net/http/http_auth_handler_factory_unittest.cc b/net/http/http_auth_handler_factory_unittest.cc
index 0b90f19..3145c4b 100644
--- a/net/http/http_auth_handler_factory_unittest.cc
+++ b/net/http/http_auth_handler_factory_unittest.cc
@@ -7,6 +7,7 @@
 #include "net/base/net_errors.h"
 #include "net/http/http_auth_handler.h"
 #include "net/http/http_auth_handler_factory.h"
+#include "net/http/mock_allow_url_security_manager.h"
 #include "net/http/url_security_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -97,7 +98,7 @@
 
 TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
   scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
-  URLSecurityManagerAllow url_security_manager;
+  MockAllowURLSecurityManager url_security_manager;
   scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
       HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
   http_auth_handler_factory->SetURLSecurityManager(
@@ -114,7 +115,7 @@
         &handler);
     EXPECT_EQ(OK, rv);
     ASSERT_FALSE(handler.get() == NULL);
-    EXPECT_STREQ("basic", handler->scheme().c_str());
+    EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, handler->auth_scheme());
     EXPECT_STREQ("FooBar", handler->realm().c_str());
     EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
     EXPECT_FALSE(handler->encrypts_identity());
@@ -141,7 +142,7 @@
         &handler);
     EXPECT_EQ(OK, rv);
     ASSERT_FALSE(handler.get() == NULL);
-    EXPECT_STREQ("digest", handler->scheme().c_str());
+    EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, handler->auth_scheme());
     EXPECT_STREQ("FooBar", handler->realm().c_str());
     EXPECT_EQ(HttpAuth::AUTH_PROXY, handler->target());
     EXPECT_TRUE(handler->encrypts_identity());
@@ -157,7 +158,7 @@
         &handler);
     EXPECT_EQ(OK, rv);
     ASSERT_FALSE(handler.get() == NULL);
-    EXPECT_STREQ("ntlm", handler->scheme().c_str());
+    EXPECT_EQ(HttpAuth::AUTH_SCHEME_NTLM, handler->auth_scheme());
     EXPECT_STREQ("", handler->realm().c_str());
     EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
     EXPECT_TRUE(handler->encrypts_identity());
@@ -173,7 +174,7 @@
         &handler);
     EXPECT_EQ(OK, rv);
     ASSERT_FALSE(handler.get() == NULL);
-    EXPECT_STREQ("negotiate", handler->scheme().c_str());
+    EXPECT_EQ(HttpAuth::AUTH_SCHEME_NEGOTIATE, handler->auth_scheme());
     EXPECT_STREQ("", handler->realm().c_str());
     EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
     EXPECT_TRUE(handler->encrypts_identity());
diff --git a/net/http/http_auth_handler_mock.cc b/net/http/http_auth_handler_mock.cc
index 0a49169..aad1bd1 100644
--- a/net/http/http_auth_handler_mock.cc
+++ b/net/http/http_auth_handler_mock.cc
@@ -71,14 +71,6 @@
   generate_rv_ = rv;
 }
 
-bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) {
-  auth_scheme_ = AUTH_SCHEME_BASIC;
-  scheme_ = "mock";
-  score_ = 1;
-  properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
-  return true;
-}
-
 HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallenge(
     HttpAuth::ChallengeTokenizer* challenge) {
   if (!is_connection_based())
@@ -88,6 +80,17 @@
   return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
 }
 
+bool HttpAuthHandlerMock::NeedsIdentity() {
+  return first_round_;
+}
+
+bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) {
+  auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
+  score_ = 1;
+  properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
+  return true;
+}
+
 int HttpAuthHandlerMock::GenerateAuthTokenImpl(const string16* username,
                                                const string16* password,
                                                const HttpRequestInfo* request,
diff --git a/net/http/http_auth_handler_mock.h b/net/http/http_auth_handler_mock.h
index bef8b2b..473ca2e 100644
--- a/net/http/http_auth_handler_mock.h
+++ b/net/http/http_auth_handler_mock.h
@@ -29,32 +29,6 @@
     RESOLVE_TESTED,
   };
 
-  HttpAuthHandlerMock();
-
-  virtual ~HttpAuthHandlerMock();
-
-  void SetResolveExpectation(Resolve resolve);
-
-  virtual bool NeedsCanonicalName();
-
-  virtual int ResolveCanonicalName(HostResolver* host_resolver,
-                                   CompletionCallback* callback);
-
-  virtual bool NeedsIdentity() { return first_round_; }
-
-  void SetGenerateExpectation(bool async, int rv);
-
-  void set_connection_based(bool connection_based) {
-    connection_based_ = connection_based;
-  }
-
-  const GURL& request_url() const {
-    return request_url_;
-  }
-
-  HttpAuth::AuthorizationResult HandleAnotherChallenge(
-      HttpAuth::ChallengeTokenizer* challenge);
-
   // The Factory class simply returns the same handler each time
   // CreateAuthHandler is called.
   class Factory : public HttpAuthHandlerFactory {
@@ -68,6 +42,7 @@
       do_init_from_challenge_ = do_init_from_challenge;
     }
 
+    // HttpAuthHandlerFactory:
     virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
                                   HttpAuth::Target target,
                                   const GURL& origin,
@@ -81,6 +56,33 @@
     bool do_init_from_challenge_;
   };
 
+  HttpAuthHandlerMock();
+
+  virtual ~HttpAuthHandlerMock();
+
+  void SetResolveExpectation(Resolve resolve);
+
+  virtual bool NeedsCanonicalName();
+
+  virtual int ResolveCanonicalName(HostResolver* host_resolver,
+                                   CompletionCallback* callback);
+
+
+  void SetGenerateExpectation(bool async, int rv);
+
+  void set_connection_based(bool connection_based) {
+    connection_based_ = connection_based;
+  }
+
+  const GURL& request_url() const {
+    return request_url_;
+  }
+
+  // HttpAuthHandler:
+  virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
+      HttpAuth::ChallengeTokenizer* challenge);
+  virtual bool NeedsIdentity();
+
  protected:
   virtual bool Init(HttpAuth::ChallengeTokenizer* challenge);
 
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc
index 2544728..a96902d 100644
--- a/net/http/http_auth_handler_negotiate.cc
+++ b/net/http/http_auth_handler_negotiate.cc
@@ -16,6 +16,68 @@
 
 namespace net {
 
+HttpAuthHandlerNegotiate::Factory::Factory()
+    : disable_cname_lookup_(false),
+      use_port_(false),
+#if defined(OS_WIN)
+      max_token_length_(0),
+      first_creation_(true),
+      is_unsupported_(false),
+#endif
+      auth_library_(NULL) {
+}
+
+HttpAuthHandlerNegotiate::Factory::~Factory() {
+}
+
+void HttpAuthHandlerNegotiate::Factory::set_host_resolver(
+    HostResolver* resolver) {
+  resolver_ = resolver;
+}
+
+int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
+    HttpAuth::ChallengeTokenizer* challenge,
+    HttpAuth::Target target,
+    const GURL& origin,
+    CreateReason reason,
+    int digest_nonce_count,
+    const BoundNetLog& net_log,
+    scoped_ptr<HttpAuthHandler>* handler) {
+#if defined(OS_WIN)
+  if (is_unsupported_ || reason == CREATE_PREEMPTIVE)
+    return ERR_UNSUPPORTED_AUTH_SCHEME;
+  if (max_token_length_ == 0) {
+    int rv = DetermineMaxTokenLength(auth_library_.get(), NEGOSSP_NAME,
+                                     &max_token_length_);
+    if (rv == ERR_UNSUPPORTED_AUTH_SCHEME)
+      is_unsupported_ = true;
+    if (rv != OK)
+      return rv;
+  }
+  // TODO(cbentzel): Move towards model of parsing in the factory
+  //                 method and only constructing when valid.
+  scoped_ptr<HttpAuthHandler> tmp_handler(
+      new HttpAuthHandlerNegotiate(auth_library_.get(), max_token_length_,
+                                   url_security_manager(), resolver_,
+                                   disable_cname_lookup_, use_port_));
+  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+    return ERR_INVALID_RESPONSE;
+  handler->swap(tmp_handler);
+  return OK;
+#elif defined(OS_POSIX)
+  // TODO(ahendrickson): Move towards model of parsing in the factory
+  //                     method and only constructing when valid.
+  scoped_ptr<HttpAuthHandler> tmp_handler(
+      new HttpAuthHandlerNegotiate(auth_library_.get(), url_security_manager(),
+                                   resolver_, disable_cname_lookup_,
+                                   use_port_));
+  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+    return ERR_INVALID_RESPONSE;
+  handler->swap(tmp_handler);
+  return OK;
+#endif
+}
+
 HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
     AuthLibrary* auth_library,
 #if defined(OS_WIN)
@@ -46,89 +108,6 @@
 HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() {
 }
 
-int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl(
-    const string16* username,
-    const string16* password,
-    const HttpRequestInfo* request,
-    CompletionCallback* callback,
-    std::string* auth_token) {
-  DCHECK(user_callback_ == NULL);
-  DCHECK((username == NULL) == (password == NULL));
-  DCHECK(auth_token_ == NULL);
-  auth_token_ = auth_token;
-  if (already_called_) {
-    DCHECK((!has_username_and_password_ && username == NULL) ||
-           (has_username_and_password_ && *username == username_ &&
-            *password == password_));
-    next_state_ = STATE_GENERATE_AUTH_TOKEN;
-  } else {
-    already_called_ = true;
-    if (username) {
-      has_username_and_password_ = true;
-      username_ = *username;
-      password_ = *password;
-    }
-    next_state_ = STATE_RESOLVE_CANONICAL_NAME;
-  }
-  int rv = DoLoop(OK);
-  if (rv == ERR_IO_PENDING)
-    user_callback_ = callback;
-  return rv;
-}
-
-// The Negotiate challenge header looks like:
-//   WWW-Authenticate: NEGOTIATE auth-data
-bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) {
-#if defined(OS_POSIX)
-  if (!auth_system_.Init()) {
-    VLOG(1) << "can't initialize GSSAPI library";
-    return false;
-  }
-  // GSSAPI does not provide a way to enter username/password to
-  // obtain a TGT. If the default credentials are not allowed for
-  // a particular site (based on whitelist), fall back to a
-  // different scheme.
-  if (!AllowsDefaultCredentials())
-    return false;
-#endif
-  if (CanDelegate())
-    auth_system_.Delegate();
-  auth_scheme_ = AUTH_SCHEME_NEGOTIATE;
-  scheme_ = "negotiate";
-  score_ = 4;
-  properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
-  HttpAuth::AuthorizationResult auth_result =
-      auth_system_.ParseChallenge(challenge);
-  return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT);
-}
-
-HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge(
-    HttpAuth::ChallengeTokenizer* challenge) {
-  return auth_system_.ParseChallenge(challenge);
-}
-
-// Require identity on first pass instead of second.
-bool HttpAuthHandlerNegotiate::NeedsIdentity() {
-  return auth_system_.NeedsIdentity();
-}
-
-bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
-  if (target_ == HttpAuth::AUTH_PROXY)
-    return true;
-  if (!url_security_manager_)
-    return false;
-  return url_security_manager_->CanUseDefaultCredentials(origin_);
-}
-
-bool HttpAuthHandlerNegotiate::CanDelegate() const {
-  // TODO(cbentzel): Should delegation be allowed on proxies?
-  if (target_ == HttpAuth::AUTH_PROXY)
-    return false;
-  if (!url_security_manager_)
-    return false;
-  return url_security_manager_->CanDelegate(origin_);
-}
-
 std::wstring HttpAuthHandlerNegotiate::CreateSPN(
     const AddressList& address_list, const GURL& origin) {
   // Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI,
@@ -178,6 +157,93 @@
   }
 }
 
+HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge(
+    HttpAuth::ChallengeTokenizer* challenge) {
+  return auth_system_.ParseChallenge(challenge);
+}
+
+// Require identity on first pass instead of second.
+bool HttpAuthHandlerNegotiate::NeedsIdentity() {
+  return auth_system_.NeedsIdentity();
+}
+
+bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
+  if (target_ == HttpAuth::AUTH_PROXY)
+    return true;
+  if (!url_security_manager_)
+    return false;
+  return url_security_manager_->CanUseDefaultCredentials(origin_);
+}
+
+// The Negotiate challenge header looks like:
+//   WWW-Authenticate: NEGOTIATE auth-data
+bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) {
+#if defined(OS_POSIX)
+  if (!auth_system_.Init()) {
+    VLOG(1) << "can't initialize GSSAPI library";
+    return false;
+  }
+  // GSSAPI does not provide a way to enter username/password to
+  // obtain a TGT. If the default credentials are not allowed for
+  // a particular site (based on whitelist), fall back to a
+  // different scheme.
+  if (!AllowsDefaultCredentials())
+    return false;
+#endif
+  if (CanDelegate())
+    auth_system_.Delegate();
+  auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE;
+  score_ = 4;
+  properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+  HttpAuth::AuthorizationResult auth_result =
+      auth_system_.ParseChallenge(challenge);
+  return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT);
+}
+
+int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl(
+    const string16* username,
+    const string16* password,
+    const HttpRequestInfo* request,
+    CompletionCallback* callback,
+    std::string* auth_token) {
+  DCHECK(user_callback_ == NULL);
+  DCHECK((username == NULL) == (password == NULL));
+  DCHECK(auth_token_ == NULL);
+  auth_token_ = auth_token;
+  if (already_called_) {
+    DCHECK((!has_username_and_password_ && username == NULL) ||
+           (has_username_and_password_ && *username == username_ &&
+            *password == password_));
+    next_state_ = STATE_GENERATE_AUTH_TOKEN;
+  } else {
+    already_called_ = true;
+    if (username) {
+      has_username_and_password_ = true;
+      username_ = *username;
+      password_ = *password;
+    }
+    next_state_ = STATE_RESOLVE_CANONICAL_NAME;
+  }
+  int rv = DoLoop(OK);
+  if (rv == ERR_IO_PENDING)
+    user_callback_ = callback;
+  return rv;
+}
+
+void HttpAuthHandlerNegotiate::OnIOComplete(int result) {
+  int rv = DoLoop(result);
+  if (rv != ERR_IO_PENDING)
+    DoCallback(rv);
+}
+
+void HttpAuthHandlerNegotiate::DoCallback(int rv) {
+  DCHECK(rv != ERR_IO_PENDING);
+  DCHECK(user_callback_);
+  CompletionCallback* callback = user_callback_;
+  user_callback_ = NULL;
+  callback->Run(rv);
+}
+
 int HttpAuthHandlerNegotiate::DoLoop(int result) {
   DCHECK(next_state_ != STATE_NONE);
 
@@ -254,80 +320,13 @@
   return rv;
 }
 
-void HttpAuthHandlerNegotiate::OnIOComplete(int result) {
-  int rv = DoLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoCallback(rv);
-}
-
-void HttpAuthHandlerNegotiate::DoCallback(int rv) {
-  DCHECK(rv != ERR_IO_PENDING);
-  DCHECK(user_callback_);
-  CompletionCallback* callback = user_callback_;
-  user_callback_ = NULL;
-  callback->Run(rv);
-}
-
-HttpAuthHandlerNegotiate::Factory::Factory()
-    : disable_cname_lookup_(false),
-      use_port_(false),
-#if defined(OS_WIN)
-      max_token_length_(0),
-      first_creation_(true),
-      is_unsupported_(false),
-#endif
-      auth_library_(NULL) {
-}
-
-HttpAuthHandlerNegotiate::Factory::~Factory() {
-}
-
-void HttpAuthHandlerNegotiate::Factory::set_host_resolver(
-    HostResolver* resolver) {
-  resolver_ = resolver;
-}
-
-int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
-    HttpAuth::ChallengeTokenizer* challenge,
-    HttpAuth::Target target,
-    const GURL& origin,
-    CreateReason reason,
-    int digest_nonce_count,
-    const BoundNetLog& net_log,
-    scoped_ptr<HttpAuthHandler>* handler) {
-#if defined(OS_WIN)
-  if (is_unsupported_ || reason == CREATE_PREEMPTIVE)
-    return ERR_UNSUPPORTED_AUTH_SCHEME;
-  if (max_token_length_ == 0) {
-    int rv = DetermineMaxTokenLength(auth_library_.get(), NEGOSSP_NAME,
-                                     &max_token_length_);
-    if (rv == ERR_UNSUPPORTED_AUTH_SCHEME)
-      is_unsupported_ = true;
-    if (rv != OK)
-      return rv;
-  }
-  // TODO(cbentzel): Move towards model of parsing in the factory
-  //                 method and only constructing when valid.
-  scoped_ptr<HttpAuthHandler> tmp_handler(
-      new HttpAuthHandlerNegotiate(auth_library_.get(), max_token_length_,
-                                   url_security_manager(), resolver_,
-                                   disable_cname_lookup_, use_port_));
-  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
-    return ERR_INVALID_RESPONSE;
-  handler->swap(tmp_handler);
-  return OK;
-#elif defined(OS_POSIX)
-  // TODO(ahendrickson): Move towards model of parsing in the factory
-  //                     method and only constructing when valid.
-  scoped_ptr<HttpAuthHandler> tmp_handler(
-      new HttpAuthHandlerNegotiate(auth_library_.get(), url_security_manager(),
-                                   resolver_, disable_cname_lookup_,
-                                   use_port_));
-  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
-    return ERR_INVALID_RESPONSE;
-  handler->swap(tmp_handler);
-  return OK;
-#endif
+bool HttpAuthHandlerNegotiate::CanDelegate() const {
+  // TODO(cbentzel): Should delegation be allowed on proxies?
+  if (target_ == HttpAuth::AUTH_PROXY)
+    return false;
+  if (!url_security_manager_)
+    return false;
+  return url_security_manager_->CanDelegate(origin_);
 }
 
 }  // namespace net
diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h
index a19d182..de2a6e6 100644
--- a/net/http/http_auth_handler_negotiate.h
+++ b/net/http/http_auth_handler_negotiate.h
@@ -64,6 +64,12 @@
 
     void set_host_resolver(HostResolver* host_resolver);
 
+    // Sets the system library to use, thereby assuming ownership of
+    // |auth_library|.
+    void set_library(AuthLibrary* auth_library) {
+      auth_library_.reset(auth_library);
+    }
+
     virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
                                   HttpAuth::Target target,
                                   const GURL& origin,
@@ -72,12 +78,6 @@
                                   const BoundNetLog& net_log,
                                   scoped_ptr<HttpAuthHandler>* handler);
 
-    // Sets the system library to use, thereby assuming ownership of
-    // |auth_library|.
-    void set_library(AuthLibrary* auth_library) {
-      auth_library_.reset(auth_library);
-    }
-
    private:
     bool disable_cname_lookup_;
     bool use_port_;
@@ -101,17 +101,16 @@
 
   virtual ~HttpAuthHandlerNegotiate();
 
-  virtual bool NeedsIdentity();
-
-  virtual bool AllowsDefaultCredentials();
-
-  virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
-      HttpAuth::ChallengeTokenizer* challenge);
-
   // These are public for unit tests
   std::wstring CreateSPN(const AddressList& address_list, const GURL& orign);
   const std::wstring& spn() const { return spn_; }
 
+  // HttpAuthHandler:
+  virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
+      HttpAuth::ChallengeTokenizer* challenge);
+  virtual bool NeedsIdentity();
+  virtual bool AllowsDefaultCredentials();
+
  protected:
   virtual bool Init(HttpAuth::ChallengeTokenizer* challenge);
 
diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc
index 684ff55..cdaa5f3 100644
--- a/net/http/http_auth_handler_negotiate_unittest.cc
+++ b/net/http/http_auth_handler_negotiate_unittest.cc
@@ -10,6 +10,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/http/http_request_info.h"
+#include "net/http/mock_allow_url_security_manager.h"
 #if defined(OS_WIN)
 #include "net/http/mock_sspi_library_win.h"
 #elif defined(OS_POSIX)
@@ -36,7 +37,7 @@
     resolver_->rules()->AddIPLiteralRule("alias", "10.0.0.2",
                                            "canonical.example.com");
 
-    url_security_manager_.reset(new URLSecurityManagerAllow());
+    url_security_manager_.reset(new MockAllowURLSecurityManager());
     factory_.reset(new HttpAuthHandlerNegotiate::Factory());
     factory_->set_url_security_manager(url_security_manager_.get());
     factory_->set_library(auth_library_);
@@ -115,23 +116,20 @@
         1,                              // Locally initiated
         1);                             // Open
     test::MockGSSAPILibrary::SecurityContextQuery queries[] = {
-      { "Negotiate",                    // Package name
+    test::MockGSSAPILibrary::SecurityContextQuery(
+        "Negotiate",                    // Package name
         GSS_S_CONTINUE_NEEDED,          // Major response code
         0,                              // Minor response code
         context1,                       // Context
-        { 0, NULL },                           // Expected input token
-        { arraysize(kAuthResponse),
-          const_cast<char*>(kAuthResponse) }   // Output token
-      },
-      { "Negotiate",                    // Package name
+        NULL,                           // Expected input token
+        kAuthResponse),                 // Output token
+    test::MockGSSAPILibrary::SecurityContextQuery(
+        "Negotiate",                    // Package name
         GSS_S_COMPLETE,                 // Major response code
         0,                              // Minor response code
         context2,                       // Context
-        { arraysize(kAuthResponse),
-          const_cast<char*>(kAuthResponse) },  // Expected input token
-        { arraysize(kAuthResponse),
-          const_cast<char*>(kAuthResponse) }   // Output token
-      },
+        kAuthResponse,                  // Expected input token
+        kAuthResponse)                  // Output token
     };
 
     for (size_t i = 0; i < arraysize(queries); ++i) {
@@ -158,14 +156,13 @@
         0,                              // Context flags
         1,                              // Locally initiated
         0);                             // Open
-    test::MockGSSAPILibrary::SecurityContextQuery query = {
-      "Negotiate",                    // Package name
-      major_status,                   // Major response code
-      minor_status,                   // Minor response code
-      context,                        // Context
-      { 0, NULL },                    // Expected input token
-      { 0, NULL }                     // Output token
-    };
+    test::MockGSSAPILibrary::SecurityContextQuery query(
+        "Negotiate",                    // Package name
+        major_status,                   // Major response code
+        minor_status,                   // Minor response code
+        context,                        // Context
+        NULL,                           // Expected input token
+        NULL);                          // Output token
 
     mock_library->ExpectSecurityContext(query.expected_package,
                                         query.response_code,
diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc
index f987e48..5090918 100644
--- a/net/http/http_auth_handler_ntlm.cc
+++ b/net/http/http_auth_handler_ntlm.cc
@@ -15,6 +15,19 @@
 
 namespace net {
 
+HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge(
+    HttpAuth::ChallengeTokenizer* challenge) {
+  return ParseChallenge(challenge, false);
+}
+
+bool HttpAuthHandlerNTLM::Init(HttpAuth::ChallengeTokenizer* tok) {
+  auth_scheme_ = HttpAuth::AUTH_SCHEME_NTLM;
+  score_ = 3;
+  properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+
+  return ParseChallenge(tok, true) == HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
+}
+
 int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
     const string16* username,
     const string16* password,
@@ -92,20 +105,6 @@
 #endif
 }
 
-bool HttpAuthHandlerNTLM::Init(HttpAuth::ChallengeTokenizer* tok) {
-  auth_scheme_ = AUTH_SCHEME_NTLM;
-  scheme_ = "ntlm";
-  score_ = 3;
-  properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
-
-  return ParseChallenge(tok, true) == HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
-}
-
-HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge(
-    HttpAuth::ChallengeTokenizer* challenge) {
-  return ParseChallenge(challenge, false);
-}
-
 // The NTLM challenge header looks like:
 //   WWW-Authenticate: NTLM auth-data
 HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::ParseChallenge(
diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h
index 831e43d..ae7c78b 100644
--- a/net/http/http_auth_handler_ntlm.h
+++ b/net/http/http_auth_handler_ntlm.h
@@ -114,6 +114,10 @@
       HttpAuth::ChallengeTokenizer* challenge);
 
  protected:
+  // This function acquires a credentials handle in the SSPI implementation.
+  // It does nothing in the portable implementation.
+  int InitializeBeforeFirstChallenge();
+
   virtual bool Init(HttpAuth::ChallengeTokenizer* tok);
 
   virtual int GenerateAuthTokenImpl(const string16* username,
@@ -122,10 +126,6 @@
                                     CompletionCallback* callback,
                                     std::string* auth_token);
 
-  // This function acquires a credentials handle in the SSPI implementation.
-  // It does nothing in the portable implementation.
-  int InitializeBeforeFirstChallenge();
-
  private:
   ~HttpAuthHandlerNTLM();
 
diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc
index d3abc98..fac37c8 100644
--- a/net/http/http_auth_handler_ntlm_portable.cc
+++ b/net/http/http_auth_handler_ntlm_portable.cc
@@ -643,14 +643,11 @@
 HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() {
 }
 
-HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
-  // Wipe our copy of the password from memory, to reduce the chance of being
-  // written to the paging file on disk.
-  ZapString(&password_);
-}
-
 bool HttpAuthHandlerNTLM::NeedsIdentity() {
-  return !auth_data_.empty();
+  // This gets called for each round-trip.  Only require identity on
+  // the first call (when auth_data_ is empty).  On subsequent calls,
+  // we use the initially established identity.
+  return auth_data_.empty();
 }
 
 bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
@@ -659,6 +656,16 @@
   return false;
 }
 
+int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
+  return OK;
+}
+
+HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
+  // Wipe our copy of the password from memory, to reduce the chance of being
+  // written to the paging file on disk.
+  ZapString(&password_);
+}
+
 // static
 HttpAuthHandlerNTLM::GenerateRandomProc
 HttpAuthHandlerNTLM::SetGenerateRandomProc(
@@ -676,6 +683,12 @@
   return old_proc;
 }
 
+HttpAuthHandlerNTLM::Factory::Factory() {
+}
+
+HttpAuthHandlerNTLM::Factory::~Factory() {
+}
+
 int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
                                       uint32 in_token_len,
                                       void** out_token,
@@ -702,16 +715,6 @@
   return rv;
 }
 
-int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
-  return OK;
-}
-
-HttpAuthHandlerNTLM::Factory::Factory() {
-}
-
-HttpAuthHandlerNTLM::Factory::~Factory() {
-}
-
 int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
     HttpAuth::ChallengeTokenizer* challenge,
     HttpAuth::Target target,
diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc
index c5264cd..1a629f1 100644
--- a/net/http/http_auth_sspi_win.cc
+++ b/net/http/http_auth_sspi_win.cc
@@ -27,6 +27,9 @@
     case SEC_E_INSUFFICIENT_MEMORY:
       return ERR_OUT_OF_MEMORY;
     case SEC_E_INTERNAL_ERROR:
+      LOG(WARNING)
+          << "AcquireCredentialsHandle returned unexpected status 0x"
+          << std::hex << status;
       return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
     case SEC_E_NO_CREDENTIALS:
     case SEC_E_NOT_OWNER:
@@ -37,7 +40,7 @@
       return ERR_UNSUPPORTED_AUTH_SCHEME;
     default:
       LOG(WARNING)
-          << "AcquireSecurityCredentials returned undocumented status 0x"
+          << "AcquireCredentialsHandle returned undocumented status 0x"
           << std::hex << status;
       return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS;
   }
diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc
index 63ae3b0..6788be2 100644
--- a/net/http/http_auth_unittest.cc
+++ b/net/http/http_auth_unittest.cc
@@ -17,6 +17,7 @@
 #include "net/http/http_auth_handler_mock.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_util.h"
+#include "net/http/mock_allow_url_security_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
@@ -26,7 +27,7 @@
 HttpAuthHandlerMock* CreateMockHandler(bool connection_based) {
   HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
   auth_handler->set_connection_based(connection_based);
-  std::string challenge_text = "Mock";
+  std::string challenge_text = "Basic";
   HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
                                          challenge_text.end());
   GURL origin("www.example.com");
@@ -48,7 +49,7 @@
     std::string* challenge_used) {
   scoped_ptr<HttpAuthHandlerMock> mock_handler(
       CreateMockHandler(connection_based));
-  std::set<std::string> disabled_schemes;
+  std::set<HttpAuth::Scheme> disabled_schemes;
   scoped_refptr<HttpResponseHeaders> headers(
       HeadersFromResponseText(headers_text));
   return HttpAuth::HandleChallengeResponse(
@@ -64,57 +65,58 @@
 TEST(HttpAuthTest, ChooseBestChallenge) {
   static const struct {
     const char* headers;
-    const char* challenge_scheme;
+    HttpAuth::Scheme challenge_scheme;
     const char* challenge_realm;
   } tests[] = {
     {
+      // Basic is the only challenge type, pick it.
       "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
       "www-authenticate: Basic realm=\"BasicRealm\"\n",
 
-      // Basic is the only challenge type, pick it.
-      "basic",
+      HttpAuth::AUTH_SCHEME_BASIC,
       "BasicRealm",
     },
     {
+      // Fake is the only challenge type, but it is unsupported.
       "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n"
       "www-authenticate: Fake realm=\"FooBar\"\n",
 
-      // Fake is the only challenge type, but it is unsupported.
-      "",
+      HttpAuth::AUTH_SCHEME_MAX,
       "",
     },
     {
+      // Pick Digest over Basic.
       "www-authenticate: Basic realm=\"FooBar\"\n"
       "www-authenticate: Fake realm=\"FooBar\"\n"
       "www-authenticate: nonce=\"aaaaaaaaaa\"\n"
       "www-authenticate: Digest realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"\n",
 
-      // Pick Digset over Basic
-      "digest",
+      HttpAuth::AUTH_SCHEME_DIGEST,
       "DigestRealm",
     },
     {
+      // Handle an empty header correctly.
       "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
       "www-authenticate:\n",
 
-      // Handle null header value.
-      "",
+      HttpAuth::AUTH_SCHEME_MAX,
       "",
     },
     {
-      "WWW-Authenticate: Negotiate\n"
-      "WWW-Authenticate: NTLM\n",
-
+      // Choose Negotiate over NTLM on all platforms.
       // TODO(ahendrickson): This may be flaky on Linux and OSX as it
       // relies on being able to load one of the known .so files
       // for gssapi.
-      "negotiate",
+      "WWW-Authenticate: Negotiate\n"
+      "WWW-Authenticate: NTLM\n",
+
+      HttpAuth::AUTH_SCHEME_NEGOTIATE,
       "",
     }
   };
   GURL origin("http://www.example.com");
-  std::set<std::string> disabled_schemes;
-  URLSecurityManagerAllow url_security_manager;
+  std::set<HttpAuth::Scheme> disabled_schemes;
+  MockAllowURLSecurityManager url_security_manager;
   scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
   scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
       HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
@@ -138,10 +140,10 @@
                                   &handler);
 
     if (handler.get()) {
-      EXPECT_STREQ(tests[i].challenge_scheme, handler->scheme().c_str());
+      EXPECT_EQ(tests[i].challenge_scheme, handler->auth_scheme());
       EXPECT_STREQ(tests[i].challenge_realm, handler->realm().c_str());
     } else {
-      EXPECT_STREQ("", tests[i].challenge_scheme);
+      EXPECT_EQ(HttpAuth::AUTH_SCHEME_MAX, tests[i].challenge_scheme);
       EXPECT_STREQ("", tests[i].challenge_realm);
     }
   }
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index 061bb30..3e69d7a 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -25,6 +25,8 @@
       request_info_(NULL) {
 }
 
+HttpBasicStream::~HttpBasicStream() {}
+
 int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info,
                                       const BoundNetLog& net_log,
                                       CompletionCallback* callback) {
@@ -52,8 +54,6 @@
                               callback);
 }
 
-HttpBasicStream::~HttpBasicStream() {}
-
 uint64 HttpBasicStream::GetUploadProgress() const {
   return parser_->GetUploadProgress();
 }
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 5710491..7c35f69 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -34,10 +34,38 @@
 #include "net/http/http_response_info.h"
 #include "net/http/http_util.h"
 #include "net/socket/ssl_host_info.h"
-#include "net/spdy/spdy_session_pool.h"
 
 namespace net {
 
+namespace {
+
+HttpNetworkSession* CreateNetworkSession(
+    HostResolver* host_resolver,
+    CertVerifier* cert_verifier,
+    DnsRRResolver* dnsrr_resolver,
+    DnsCertProvenanceChecker* dns_cert_checker,
+    ProxyService* proxy_service,
+    SSLHostInfoFactory* ssl_host_info_factory,
+    SSLConfigService* ssl_config_service,
+    HttpAuthHandlerFactory* http_auth_handler_factory,
+    HttpNetworkDelegate* network_delegate,
+    NetLog* net_log) {
+  HttpNetworkSession::Params params;
+  params.host_resolver = host_resolver;
+  params.cert_verifier = cert_verifier;
+  params.dnsrr_resolver = dnsrr_resolver;
+  params.dns_cert_checker = dns_cert_checker;
+  params.proxy_service = proxy_service;
+  params.ssl_host_info_factory = ssl_host_info_factory;
+  params.ssl_config_service = ssl_config_service;
+  params.http_auth_handler_factory = http_auth_handler_factory;
+  params.network_delegate = network_delegate;
+  params.net_log = net_log;
+  return new HttpNetworkSession(params);
+}
+
+}  // namespace
+
 HttpCache::DefaultBackend::DefaultBackend(CacheType type,
                                           const FilePath& path,
                                           int max_bytes,
@@ -264,21 +292,23 @@
 
 class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory {
  public:
-  explicit SSLHostInfoFactoryAdaptor(HttpCache* http_cache)
-      : http_cache_(http_cache) {
+  SSLHostInfoFactoryAdaptor(CertVerifier* cert_verifier, HttpCache* http_cache)
+      : cert_verifier_(cert_verifier),
+        http_cache_(http_cache) {
   }
 
-  SSLHostInfo* GetForHost(const std::string& hostname,
-                          const SSLConfig& ssl_config) {
-    return new DiskCacheBasedSSLHostInfo(hostname, ssl_config, http_cache_);
+  virtual SSLHostInfo* GetForHost(const std::string& hostname,
+                                  const SSLConfig& ssl_config) {
+    return new DiskCacheBasedSSLHostInfo(
+        hostname, ssl_config, cert_verifier_, http_cache_);
   }
 
  private:
+  CertVerifier* const cert_verifier_;
   HttpCache* const http_cache_;
 };
 
 //-----------------------------------------------------------------------------
-
 HttpCache::HttpCache(HostResolver* host_resolver,
                      CertVerifier* cert_verifier,
                      DnsRRResolver* dnsrr_resolver,
@@ -294,22 +324,35 @@
       building_backend_(false),
       mode_(NORMAL),
       ssl_host_info_factory_(new SSLHostInfoFactoryAdaptor(
-            ALLOW_THIS_IN_INITIALIZER_LIST(this))),
-      network_layer_(HttpNetworkLayer::CreateFactory(host_resolver,
-          cert_verifier, dnsrr_resolver, dns_cert_checker_,
-          ssl_host_info_factory_.get(),
-          proxy_service, ssl_config_service,
-          http_auth_handler_factory, network_delegate, net_log)),
+          cert_verifier,
+          ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+      network_layer_(
+          new HttpNetworkLayer(
+              CreateNetworkSession(
+                  host_resolver,
+                  cert_verifier,
+                  dnsrr_resolver,
+                  dns_cert_checker_,
+                  proxy_service,
+                  ssl_host_info_factory_.get(),
+                  ssl_config_service,
+                  http_auth_handler_factory,
+                  network_delegate,
+                  net_log))),
       ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
 }
 
+
 HttpCache::HttpCache(HttpNetworkSession* session,
                      BackendFactory* backend_factory)
     : net_log_(session->net_log()),
       backend_factory_(backend_factory),
       building_backend_(false),
       mode_(NORMAL),
-      network_layer_(HttpNetworkLayer::CreateFactory(session)),
+      ssl_host_info_factory_(new SSLHostInfoFactoryAdaptor(
+          session->cert_verifier(),
+          ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+      network_layer_(new HttpNetworkLayer(session)),
       ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
 }
 
@@ -383,29 +426,6 @@
   return disk_cache_.get();
 }
 
-int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
-  // Do lazy initialization of disk cache if needed.
-  if (!disk_cache_.get())
-    CreateBackend(NULL, NULL);  // We don't care about the result.
-
-  trans->reset(new HttpCache::Transaction(this));
-  return OK;
-}
-
-HttpCache* HttpCache::GetCache() {
-  return this;
-}
-
-HttpNetworkSession* HttpCache::GetSession() {
-  net::HttpNetworkLayer* network =
-      static_cast<net::HttpNetworkLayer*>(network_layer_.get());
-  return network->GetSession();
-}
-
-void HttpCache::Suspend(bool suspend) {
-  network_layer_->Suspend(suspend);
-}
-
 // static
 bool HttpCache::ParseResponseInfo(const char* data, int len,
                                   HttpResponseInfo* response_info,
@@ -442,6 +462,29 @@
   }
 }
 
+int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
+  // Do lazy initialization of disk cache if needed.
+  if (!disk_cache_.get())
+    CreateBackend(NULL, NULL);  // We don't care about the result.
+
+  trans->reset(new HttpCache::Transaction(this));
+  return OK;
+}
+
+HttpCache* HttpCache::GetCache() {
+  return this;
+}
+
+HttpNetworkSession* HttpCache::GetSession() {
+  net::HttpNetworkLayer* network =
+      static_cast<net::HttpNetworkLayer*>(network_layer_.get());
+  return network->GetSession();
+}
+
+void HttpCache::Suspend(bool suspend) {
+  network_layer_->Suspend(suspend);
+}
+
 //-----------------------------------------------------------------------------
 
 int HttpCache::CreateBackend(disk_cache::Backend** backend,
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 0641ca4..cdbddfe 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -60,8 +60,6 @@
                   public base::SupportsWeakPtr<HttpCache>,
                   public base::NonThreadSafe {
  public:
-  ~HttpCache();
-
   // The cache mode of operation.
   enum Mode {
     // Normal mode just behaves like a standard web cache.
@@ -133,7 +131,7 @@
   // The disk cache is initialized lazily (by CreateTransaction) in  this case.
   // Provide an existing HttpNetworkSession, the cache can construct a
   // network layer with a shared HttpNetworkSession in order for multiple
-  // network layers to share information (e.g. authenication data). The
+  // network layers to share information (e.g. authentication data). The
   // HttpCache takes ownership of the |backend_factory|.
   HttpCache(HttpNetworkSession* session, BackendFactory* backend_factory);
 
@@ -145,6 +143,8 @@
             NetLog* net_log,
             BackendFactory* backend_factory);
 
+  ~HttpCache();
+
   HttpTransactionFactory* network_layer() { return network_layer_.get(); }
 
   // Retrieves the cache backend for this HttpCache instance. If the backend
@@ -157,12 +157,6 @@
   // Returns the current backend (can be NULL).
   disk_cache::Backend* GetCurrentBackend();
 
-  // HttpTransactionFactory implementation:
-  virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
-  virtual HttpCache* GetCache();
-  virtual HttpNetworkSession* GetSession();
-  virtual void Suspend(bool suspend);
-
   // Given a header data blob, convert it to a response info object.
   static bool ParseResponseInfo(const char* data, int len,
                                 HttpResponseInfo* response_info,
@@ -184,6 +178,12 @@
   // immediately, but they will not be reusable. This is for debugging.
   void CloseCurrentConnections();
 
+  // HttpTransactionFactory implementation:
+  virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
+  virtual HttpCache* GetCache();
+  virtual HttpNetworkSession* GetSession();
+  virtual void Suspend(bool suspend);
+
  protected:
   // Disk cache entry data indices.
   enum {
@@ -211,20 +211,21 @@
   typedef std::list<WorkItem*> WorkItemList;
 
   struct ActiveEntry {
+    explicit ActiveEntry(disk_cache::Entry* entry);
+    ~ActiveEntry();
+
     disk_cache::Entry* disk_entry;
     Transaction*       writer;
     TransactionList    readers;
     TransactionList    pending_queue;
     bool               will_process_pending_queue;
     bool               doomed;
-
-    explicit ActiveEntry(disk_cache::Entry* entry);
-    ~ActiveEntry();
   };
 
   typedef base::hash_map<std::string, ActiveEntry*> ActiveEntriesMap;
   typedef base::hash_map<std::string, PendingOp*> PendingOpsMap;
   typedef std::set<ActiveEntry*> ActiveEntriesSet;
+  typedef base::hash_map<std::string, int> PlaybackCacheMap;
 
   // Methods ------------------------------------------------------------------
 
@@ -355,9 +356,9 @@
 
   Mode mode_;
 
-  scoped_ptr<SSLHostInfoFactoryAdaptor> ssl_host_info_factory_;
+  const scoped_ptr<SSLHostInfoFactoryAdaptor> ssl_host_info_factory_;
 
-  scoped_ptr<HttpTransactionFactory> network_layer_;
+  const scoped_ptr<HttpTransactionFactory> network_layer_;
   scoped_ptr<disk_cache::Backend> disk_cache_;
 
   // The set of active entries indexed by cache key.
@@ -371,7 +372,6 @@
 
   ScopedRunnableMethodFactory<HttpCache> task_factory_;
 
-  typedef base::hash_map<std::string, int> PlaybackCacheMap;
   scoped_ptr<PlaybackCacheMap> playback_cache_map_;
 
   DISALLOW_COPY_AND_ASSIGN(HttpCache);
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index b506edc..32386f0 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -163,6 +163,70 @@
   cache_.reset();
 }
 
+int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
+                                          CompletionCallback* callback) {
+  DCHECK(buf);
+  DCHECK_GT(buf_len, 0);
+  DCHECK(callback);
+  if (!cache_ || !entry_)
+    return ERR_UNEXPECTED;
+
+  // We don't need to track this operation for anything.
+  // It could be possible to check if there is something already written and
+  // avoid writing again (it should be the same, right?), but let's allow the
+  // caller to "update" the contents with something new.
+  return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
+                                       callback, true);
+}
+
+// Histogram data from the end of 2010 show the following distribution of
+// response headers:
+//
+//   Content-Length............... 87%
+//   Date......................... 98%
+//   Last-Modified................ 49%
+//   Etag......................... 19%
+//   Accept-Ranges: bytes......... 25%
+//   Accept-Ranges: none.......... 0.4%
+//   Strong Validator............. 50%
+//   Strong Validator + ranges.... 24%
+//   Strong Validator + CL........ 49%
+//
+bool HttpCache::Transaction::AddTruncatedFlag() {
+  DCHECK(mode_ & WRITE);
+
+  // Don't set the flag for sparse entries.
+  if (partial_.get() && !truncated_)
+    return true;
+
+  // Double check that there is something worth keeping.
+  if (!entry_->disk_entry->GetDataSize(kResponseContentIndex))
+    return false;
+
+  if (response_.headers->GetContentLength() <= 0 ||
+      response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
+      !response_.headers->HasStrongValidators())
+    return false;
+
+  truncated_ = true;
+  target_state_ = STATE_NONE;
+  next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
+  DoLoop(OK);
+  return true;
+}
+
+LoadState HttpCache::Transaction::GetWriterLoadState() const {
+  if (network_trans_.get())
+    return network_trans_->GetLoadState();
+  if (entry_ || !request_)
+    return LOAD_STATE_IDLE;
+  return LOAD_STATE_WAITING_FOR_CACHE;
+}
+
+const BoundNetLog& HttpCache::Transaction::net_log() const {
+  return net_log_;
+}
+
 int HttpCache::Transaction::Start(const HttpRequestInfo* request,
                                   CompletionCallback* callback,
                                   const BoundNetLog& net_log) {
@@ -338,70 +402,6 @@
   return final_upload_progress_;
 }
 
-int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
-                                          CompletionCallback* callback) {
-  DCHECK(buf);
-  DCHECK_GT(buf_len, 0);
-  DCHECK(callback);
-  if (!cache_ || !entry_)
-    return ERR_UNEXPECTED;
-
-  // We don't need to track this operation for anything.
-  // It could be possible to check if there is something already written and
-  // avoid writing again (it should be the same, right?), but let's allow the
-  // caller to "update" the contents with something new.
-  return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
-                                       callback, true);
-}
-
-// Histogram data from the end of 2010 show the following distribution of
-// response headers:
-//
-//   Content-Length............... 87%
-//   Date......................... 98%
-//   Last-Modified................ 49%
-//   Etag......................... 19%
-//   Accept-Ranges: bytes......... 25%
-//   Accept-Ranges: none.......... 0.4%
-//   Strong Validator............. 50%
-//   Strong Validator + ranges.... 24%
-//   Strong Validator + CL........ 49%
-//
-bool HttpCache::Transaction::AddTruncatedFlag() {
-  DCHECK(mode_ & WRITE);
-
-  // Don't set the flag for sparse entries.
-  if (partial_.get() && !truncated_)
-    return true;
-
-  // Double check that there is something worth keeping.
-  if (!entry_->disk_entry->GetDataSize(kResponseContentIndex))
-    return false;
-
-  if (response_.headers->GetContentLength() <= 0 ||
-      response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
-      !response_.headers->HasStrongValidators())
-    return false;
-
-  truncated_ = true;
-  target_state_ = STATE_NONE;
-  next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
-  DoLoop(OK);
-  return true;
-}
-
-LoadState HttpCache::Transaction::GetWriterLoadState() const {
-  if (network_trans_.get())
-    return network_trans_->GetLoadState();
-  if (entry_ || !request_)
-    return LOAD_STATE_IDLE;
-  return LOAD_STATE_WAITING_FOR_CACHE;
-}
-
-const BoundNetLog& HttpCache::Transaction::net_log() const {
-  return net_log_;
-}
-
 //-----------------------------------------------------------------------------
 
 void HttpCache::Transaction::DoCallback(int rv) {
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 316c15b..81160d5 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -28,25 +28,6 @@
 // factory.
 class HttpCache::Transaction : public HttpTransaction {
  public:
-  Transaction(HttpCache* cache);
-  virtual ~Transaction();
-
-  // HttpTransaction methods:
-  virtual int Start(const HttpRequestInfo*, CompletionCallback*,
-                    const BoundNetLog&);
-  virtual int RestartIgnoringLastError(CompletionCallback* callback);
-  virtual int RestartWithCertificate(X509Certificate* client_cert,
-                                     CompletionCallback* callback);
-  virtual int RestartWithAuth(const string16& username,
-                              const string16& password,
-                              CompletionCallback* callback);
-  virtual bool IsReadyToRestartForAuth();
-  virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
-  virtual void StopCaching();
-  virtual const HttpResponseInfo* GetResponseInfo() const;
-  virtual LoadState GetLoadState() const;
-  virtual uint64 GetUploadProgress(void) const;
-
   // The transaction has the following modes, which apply to how it may access
   // its cache entry.
   //
@@ -76,6 +57,9 @@
     UPDATE          = READ_META | WRITE,  // READ_WRITE & ~READ_DATA
   };
 
+  Transaction(HttpCache* cache);
+  virtual ~Transaction();
+
   Mode mode() const { return mode_; }
 
   const std::string& key() const { return cache_key_; }
@@ -112,6 +96,22 @@
 
   const BoundNetLog& net_log() const;
 
+  // HttpTransaction methods:
+  virtual int Start(const HttpRequestInfo*, CompletionCallback*,
+                    const BoundNetLog&);
+  virtual int RestartIgnoringLastError(CompletionCallback* callback);
+  virtual int RestartWithCertificate(X509Certificate* client_cert,
+                                     CompletionCallback* callback);
+  virtual int RestartWithAuth(const string16& username,
+                              const string16& password,
+                              CompletionCallback* callback);
+  virtual bool IsReadyToRestartForAuth();
+  virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
+  virtual void StopCaching();
+  virtual const HttpResponseInfo* GetResponseInfo() const;
+  virtual LoadState GetLoadState() const;
+  virtual uint64 GetUploadProgress(void) const;
+
  private:
   static const size_t kNumValidationHeaders = 2;
   // Helper struct to pair a header name with its value, for
diff --git a/net/http/http_net_log_params.h b/net/http/http_net_log_params.h
index 1631363..c32250e 100644
--- a/net/http/http_net_log_params.h
+++ b/net/http/http_net_log_params.h
@@ -24,8 +24,6 @@
   NetLogHttpRequestParameter(const std::string& line,
                              const HttpRequestHeaders& headers);
 
-  virtual Value* ToValue() const;
-
   const HttpRequestHeaders& GetHeaders() const {
     return headers_;
   }
@@ -34,6 +32,9 @@
     return line_;
   }
 
+  // NetLog::EventParameters
+  virtual Value* ToValue() const;
+
  private:
   virtual ~NetLogHttpRequestParameter();
 
@@ -48,12 +49,13 @@
   explicit NetLogHttpResponseParameter(
       const scoped_refptr<HttpResponseHeaders>& headers);
 
-  virtual Value* ToValue() const;
-
   const HttpResponseHeaders& GetHeaders() const {
     return *headers_;
   }
 
+  // NetLog::EventParameters
+  virtual Value* ToValue() const;
+
  private:
   virtual ~NetLogHttpResponseParameter();
 
diff --git a/net/http/http_network_delegate.h b/net/http/http_network_delegate.h
index 6b60aba..1533bc3 100644
--- a/net/http/http_network_delegate.h
+++ b/net/http/http_network_delegate.h
@@ -9,9 +9,13 @@
 namespace net {
 
 class HttpRequestHeaders;
+class URLRequest;
 
 class HttpNetworkDelegate {
  public:
+  // Called before a request is sent.
+  virtual void OnBeforeURLRequest(net::URLRequest* request) = 0;
+
   // Called right before the HTTP headers are sent.  Allows the delegate to
   // read/write |headers| before they get sent out.
   virtual void OnSendHttpRequest(HttpRequestHeaders* headers) = 0;
diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc
index 9a11034..73e6f8d 100644
--- a/net/http/http_network_layer.cc
+++ b/net/http/http_network_layer.cc
@@ -10,121 +10,14 @@
 #include "base/string_util.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_network_transaction.h"
-#include "net/socket/client_socket_factory.h"
 #include "net/spdy/spdy_framer.h"
 #include "net/spdy/spdy_session.h"
-#include "net/spdy/spdy_session_pool.h"
 
 namespace net {
 
 //-----------------------------------------------------------------------------
-
-// static
-HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
-    HostResolver* host_resolver,
-    CertVerifier* cert_verifier,
-    DnsRRResolver* dnsrr_resolver,
-    DnsCertProvenanceChecker* dns_cert_checker,
-    SSLHostInfoFactory* ssl_host_info_factory,
-    ProxyService* proxy_service,
-    SSLConfigService* ssl_config_service,
-    HttpAuthHandlerFactory* http_auth_handler_factory,
-    HttpNetworkDelegate* network_delegate,
-    NetLog* net_log) {
-  DCHECK(proxy_service);
-
-  return new HttpNetworkLayer(ClientSocketFactory::GetDefaultFactory(),
-                              host_resolver, cert_verifier, dnsrr_resolver,
-                              dns_cert_checker,
-                              ssl_host_info_factory, proxy_service,
-                              ssl_config_service, http_auth_handler_factory,
-                              network_delegate,
-                              net_log);
-}
-
-// static
-HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
-    HttpNetworkSession* session) {
-  DCHECK(session);
-
-  return new HttpNetworkLayer(session);
-}
-
-//-----------------------------------------------------------------------------
-HttpNetworkLayer::HttpNetworkLayer(
-    ClientSocketFactory* socket_factory,
-    HostResolver* host_resolver,
-    CertVerifier* cert_verifier,
-    DnsRRResolver* dnsrr_resolver,
-    DnsCertProvenanceChecker* dns_cert_checker,
-    SSLHostInfoFactory* ssl_host_info_factory,
-    ProxyService* proxy_service,
-    SSLConfigService* ssl_config_service,
-    HttpAuthHandlerFactory* http_auth_handler_factory,
-    HttpNetworkDelegate* network_delegate,
-    NetLog* net_log)
-    : socket_factory_(socket_factory),
-      host_resolver_(host_resolver),
-      cert_verifier_(cert_verifier),
-      dnsrr_resolver_(dnsrr_resolver),
-      dns_cert_checker_(dns_cert_checker),
-      ssl_host_info_factory_(ssl_host_info_factory),
-      proxy_service_(proxy_service),
-      ssl_config_service_(ssl_config_service),
-      session_(NULL),
-      spdy_session_pool_(NULL),
-      http_auth_handler_factory_(http_auth_handler_factory),
-      network_delegate_(network_delegate),
-      net_log_(net_log),
-      suspended_(false) {
-  DCHECK(proxy_service_);
-  DCHECK(ssl_config_service_.get());
-}
-
-HttpNetworkLayer::HttpNetworkLayer(
-    ClientSocketFactory* socket_factory,
-    HostResolver* host_resolver,
-    CertVerifier* cert_verifier,
-    DnsRRResolver* dnsrr_resolver,
-    DnsCertProvenanceChecker* dns_cert_checker,
-    SSLHostInfoFactory* ssl_host_info_factory,
-    ProxyService* proxy_service,
-    SSLConfigService* ssl_config_service,
-    SpdySessionPool* spdy_session_pool,
-    HttpAuthHandlerFactory* http_auth_handler_factory,
-    HttpNetworkDelegate* network_delegate,
-    NetLog* net_log)
-    : socket_factory_(socket_factory),
-      host_resolver_(host_resolver),
-      cert_verifier_(cert_verifier),
-      dnsrr_resolver_(dnsrr_resolver),
-      dns_cert_checker_(dns_cert_checker),
-      ssl_host_info_factory_(ssl_host_info_factory),
-      proxy_service_(proxy_service),
-      ssl_config_service_(ssl_config_service),
-      session_(NULL),
-      spdy_session_pool_(spdy_session_pool),
-      http_auth_handler_factory_(http_auth_handler_factory),
-      network_delegate_(network_delegate),
-      net_log_(net_log),
-      suspended_(false) {
-  DCHECK(proxy_service_);
-  DCHECK(ssl_config_service_.get());
-}
-
 HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session)
-    : socket_factory_(ClientSocketFactory::GetDefaultFactory()),
-      host_resolver_(NULL),
-      cert_verifier_(NULL),
-      dnsrr_resolver_(NULL),
-      dns_cert_checker_(NULL),
-      ssl_host_info_factory_(NULL),
-      ssl_config_service_(NULL),
-      session_(session),
-      spdy_session_pool_(NULL),
-      http_auth_handler_factory_(NULL),
-      network_delegate_(NULL),
-      net_log_(NULL),
+    : session_(session),
       suspended_(false) {
   DCHECK(session_.get());
 }
@@ -132,56 +25,14 @@
 HttpNetworkLayer::~HttpNetworkLayer() {
 }
 
-int HttpNetworkLayer::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
-  if (suspended_)
-    return ERR_NETWORK_IO_SUSPENDED;
+//-----------------------------------------------------------------------------
 
-  trans->reset(new HttpNetworkTransaction(GetSession()));
-  return OK;
-}
+// static
+HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
+    HttpNetworkSession* session) {
+  DCHECK(session);
 
-HttpCache* HttpNetworkLayer::GetCache() {
-  return NULL;
-}
-
-void HttpNetworkLayer::Suspend(bool suspend) {
-  suspended_ = suspend;
-
-  if (suspend && session_)
-    session_->tcp_socket_pool()->CloseIdleSockets();
-}
-
-HttpNetworkSession* HttpNetworkLayer::GetSession() {
-  if (!session_) {
-    DCHECK(proxy_service_);
-    if (!spdy_session_pool_.get())
-      spdy_session_pool_.reset(new SpdySessionPool(ssl_config_service_));
-    session_ = new HttpNetworkSession(
-        host_resolver_,
-        cert_verifier_,
-        dnsrr_resolver_,
-        dns_cert_checker_,
-        ssl_host_info_factory_,
-        proxy_service_,
-        socket_factory_,
-        ssl_config_service_,
-        spdy_session_pool_.release(),
-        http_auth_handler_factory_,
-        network_delegate_,
-        net_log_);
-    // These were just temps for lazy-initializing HttpNetworkSession.
-    host_resolver_ = NULL;
-    cert_verifier_ = NULL;
-    dnsrr_resolver_ = NULL;
-    dns_cert_checker_ = NULL;
-    ssl_host_info_factory_ = NULL;
-    proxy_service_ = NULL;
-    socket_factory_ = NULL;
-    http_auth_handler_factory_ = NULL;
-    net_log_ = NULL;
-    network_delegate_ = NULL;
-  }
-  return session_;
+  return new HttpNetworkLayer(session);
 }
 
 // static
@@ -277,4 +128,30 @@
     }
   }
 }
+
+//-----------------------------------------------------------------------------
+
+int HttpNetworkLayer::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
+  if (suspended_)
+    return ERR_NETWORK_IO_SUSPENDED;
+
+  trans->reset(new HttpNetworkTransaction(GetSession()));
+  return OK;
+}
+
+HttpCache* HttpNetworkLayer::GetCache() {
+  return NULL;
+}
+
+HttpNetworkSession* HttpNetworkLayer::GetSession() {
+  return session_;
+}
+
+void HttpNetworkLayer::Suspend(bool suspend) {
+  suspended_ = suspend;
+
+  if (suspend && session_)
+    session_->tcp_socket_pool()->CloseIdleSockets();
+}
+
 }  // namespace net
diff --git a/net/http/http_network_layer.h b/net/http/http_network_layer.h
index 730b5c7..da92761 100644
--- a/net/http/http_network_layer.h
+++ b/net/http/http_network_layer.h
@@ -32,52 +32,11 @@
 class HttpNetworkLayer : public HttpTransactionFactory,
                          public base::NonThreadSafe {
  public:
-  // |socket_factory|, |proxy_service|, |host_resolver|, etc. must remain
-  // valid for the lifetime of HttpNetworkLayer.
-  // TODO(wtc): we only need the next constructor.
-  HttpNetworkLayer(ClientSocketFactory* socket_factory,
-                   HostResolver* host_resolver,
-                   CertVerifier* cert_verifier,
-                   DnsRRResolver* dnsrr_resolver,
-                   DnsCertProvenanceChecker* dns_cert_checker,
-                   SSLHostInfoFactory* ssl_host_info_factory,
-                   ProxyService* proxy_service,
-                   SSLConfigService* ssl_config_service,
-                   HttpAuthHandlerFactory* http_auth_handler_factory,
-                   HttpNetworkDelegate* network_delegate,
-                   NetLog* net_log);
-  HttpNetworkLayer(
-      ClientSocketFactory* socket_factory,
-      HostResolver* host_resolver,
-      CertVerifier* cert_verifier,
-      DnsRRResolver* dnsrr_resolver,
-      DnsCertProvenanceChecker* dns_cert_checker,
-      SSLHostInfoFactory* ssl_host_info_factory,
-      ProxyService* proxy_service,
-      SSLConfigService* ssl_config_service,
-      SpdySessionPool* spdy_session_pool,
-      HttpAuthHandlerFactory* http_auth_handler_factory,
-      HttpNetworkDelegate* network_delegate,
-      NetLog* net_log);
-
   // Construct a HttpNetworkLayer with an existing HttpNetworkSession which
   // contains a valid ProxyService.
   explicit HttpNetworkLayer(HttpNetworkSession* session);
-  ~HttpNetworkLayer();
+  virtual ~HttpNetworkLayer();
 
-  // This function hides the details of how a network layer gets instantiated
-  // and allows other implementations to be substituted.
-  static HttpTransactionFactory* CreateFactory(
-      HostResolver* host_resolver,
-      CertVerifier* cert_verifier,
-      DnsRRResolver* dnsrr_resolver,
-      DnsCertProvenanceChecker* dns_cert_checker,
-      SSLHostInfoFactory* ssl_host_info_factory,
-      ProxyService* proxy_service,
-      SSLConfigService* ssl_config_service,
-      HttpAuthHandlerFactory* http_auth_handler_factory,
-      HttpNetworkDelegate* network_delegate,
-      NetLog* net_log);
   // Create a transaction factory that instantiate a network layer over an
   // existing network session. Network session contains some valuable
   // information (e.g. authentication data) that we want to share across
@@ -86,12 +45,6 @@
   // when network session is shared.
   static HttpTransactionFactory* CreateFactory(HttpNetworkSession* session);
 
-  // HttpTransactionFactory methods:
-  virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
-  virtual HttpCache* GetCache();
-  virtual HttpNetworkSession* GetSession();
-  virtual void Suspend(bool suspend);
-
   // Enable the spdy protocol.
   // Without calling this function, SPDY is disabled.  The mode can be:
   //   ""            : (default) SSL and compression are enabled, flow
@@ -102,29 +55,14 @@
   //   "none"        : disables both SSL and compression.
   static void EnableSpdy(const std::string& mode);
 
+  // HttpTransactionFactory methods:
+  virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
+  virtual HttpCache* GetCache();
+  virtual HttpNetworkSession* GetSession();
+  virtual void Suspend(bool suspend);
+
  private:
-  // The factory we will use to create network sockets.
-  ClientSocketFactory* socket_factory_;
-
-  // The host resolver, proxy service, etc. that will be used when lazily
-  // creating |session_|.
-  HostResolver* host_resolver_;
-  CertVerifier* cert_verifier_;
-  DnsRRResolver* dnsrr_resolver_;
-  DnsCertProvenanceChecker* dns_cert_checker_;
-  SSLHostInfoFactory* ssl_host_info_factory_;
-  scoped_refptr<ProxyService> proxy_service_;
-
-  // The SSL config service being used for the session.
-  scoped_refptr<SSLConfigService> ssl_config_service_;
-
-  scoped_refptr<HttpNetworkSession> session_;
-  scoped_ptr<SpdySessionPool> spdy_session_pool_;
-
-  HttpAuthHandlerFactory* http_auth_handler_factory_;
-  HttpNetworkDelegate* network_delegate_;
-  NetLog* net_log_;
-
+  const scoped_refptr<HttpNetworkSession> session_;
   bool suspended_;
 };
 
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 2720c10..5120fac 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -7,9 +7,11 @@
 #include "net/base/net_log.h"
 #include "net/base/ssl_config_service_defaults.h"
 #include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
 #include "net/http/http_transaction_unittest.h"
 #include "net/proxy/proxy_service.h"
 #include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_session_pool.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -18,118 +20,93 @@
 namespace {
 
 class HttpNetworkLayerTest : public PlatformTest {
+ protected:
+  HttpNetworkLayerTest()
+      : proxy_service_(ProxyService::CreateDirect()),
+        ssl_config_service_(new SSLConfigServiceDefaults) {
+    HttpNetworkSession::Params session_params;
+    session_params.client_socket_factory = &mock_socket_factory_;
+    session_params.host_resolver = &host_resolver_;
+    session_params.cert_verifier = &cert_verifier_;
+    session_params.proxy_service = proxy_service_;
+    session_params.ssl_config_service = ssl_config_service_;
+    network_session_ = new HttpNetworkSession(session_params);
+    factory_.reset(new HttpNetworkLayer(network_session_));
+  }
+
+  MockClientSocketFactory mock_socket_factory_;
+  MockHostResolver host_resolver_;
+  CertVerifier cert_verifier_;
+  const scoped_refptr<ProxyService> proxy_service_;
+  const scoped_refptr<SSLConfigService> ssl_config_service_;
+  scoped_refptr<HttpNetworkSession> network_session_;
+  scoped_ptr<HttpNetworkLayer> factory_;
 };
 
 TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
-  MockHostResolver host_resolver;
-  net::CertVerifier cert_verifier;
-  net::HttpNetworkLayer factory(
-      NULL,
-      &host_resolver,
-      &cert_verifier,
-      NULL /* dnsrr_resolver */,
-      NULL /* dns_cert_checker */,
-      NULL /* ssl_host_info_factory */,
-      net::ProxyService::CreateDirect(),
-      new net::SSLConfigServiceDefaults,
-      NULL,
-      NULL,
-      NULL);
-
-  scoped_ptr<net::HttpTransaction> trans;
-  int rv = factory.CreateTransaction(&trans);
-  EXPECT_EQ(net::OK, rv);
+  scoped_ptr<HttpTransaction> trans;
+  int rv = factory_->CreateTransaction(&trans);
+  EXPECT_EQ(OK, rv);
   EXPECT_TRUE(trans.get() != NULL);
 }
 
 TEST_F(HttpNetworkLayerTest, Suspend) {
-  MockHostResolver host_resolver;
-  net::CertVerifier cert_verifier;
-  net::HttpNetworkLayer factory(
-      NULL,
-      &host_resolver,
-      &cert_verifier,
-      NULL /* dnsrr_resolver */,
-      NULL /* dns_cert_checker */,
-      NULL /* ssl_host_info_factory */,
-      net::ProxyService::CreateDirect(),
-      new net::SSLConfigServiceDefaults,
-      NULL,
-      NULL,
-      NULL);
-
-  scoped_ptr<net::HttpTransaction> trans;
-  int rv = factory.CreateTransaction(&trans);
-  EXPECT_EQ(net::OK, rv);
+  scoped_ptr<HttpTransaction> trans;
+  int rv = factory_->CreateTransaction(&trans);
+  EXPECT_EQ(OK, rv);
 
   trans.reset();
 
-  factory.Suspend(true);
+  factory_->Suspend(true);
 
-  rv = factory.CreateTransaction(&trans);
-  EXPECT_EQ(net::ERR_NETWORK_IO_SUSPENDED, rv);
+  rv = factory_->CreateTransaction(&trans);
+  EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, rv);
 
   ASSERT_TRUE(trans == NULL);
 
-  factory.Suspend(false);
+  factory_->Suspend(false);
 
-  rv = factory.CreateTransaction(&trans);
-  EXPECT_EQ(net::OK, rv);
+  rv = factory_->CreateTransaction(&trans);
+  EXPECT_EQ(OK, rv);
 }
 
 TEST_F(HttpNetworkLayerTest, GET) {
-  net::MockClientSocketFactory mock_socket_factory;
-  net::MockRead data_reads[] = {
-    net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
-    net::MockRead("hello world"),
-    net::MockRead(false, net::OK),
+  MockRead data_reads[] = {
+    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
+    MockRead("hello world"),
+    MockRead(false, OK),
   };
-  net::MockWrite data_writes[] = {
-    net::MockWrite("GET / HTTP/1.1\r\n"
+  MockWrite data_writes[] = {
+    MockWrite("GET / HTTP/1.1\r\n"
                    "Host: www.google.com\r\n"
                    "Connection: keep-alive\r\n"
                    "User-Agent: Foo/1.0\r\n\r\n"),
   };
-  net::StaticSocketDataProvider data(data_reads, arraysize(data_reads),
+  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
                                      data_writes, arraysize(data_writes));
-  mock_socket_factory.AddSocketDataProvider(&data);
-
-  MockHostResolver host_resolver;
-  net::CertVerifier cert_verifier;
-  net::HttpNetworkLayer factory(
-      &mock_socket_factory,
-      &host_resolver,
-      &cert_verifier,
-      NULL /* dnsrr_resolver */,
-      NULL /* dns_cert_checker */,
-      NULL /* ssl_host_info_factory */,
-      net::ProxyService::CreateDirect(),
-      new net::SSLConfigServiceDefaults,
-      NULL,
-      NULL,
-      NULL);
+  mock_socket_factory_.AddSocketDataProvider(&data);
 
   TestCompletionCallback callback;
 
-  scoped_ptr<net::HttpTransaction> trans;
-  int rv = factory.CreateTransaction(&trans);
-  EXPECT_EQ(net::OK, rv);
-
-  net::HttpRequestInfo request_info;
+  HttpRequestInfo request_info;
   request_info.url = GURL("http://www.google.com/");
   request_info.method = "GET";
-  request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
+  request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
                                        "Foo/1.0");
-  request_info.load_flags = net::LOAD_NORMAL;
+  request_info.load_flags = LOAD_NORMAL;
 
-  rv = trans->Start(&request_info, &callback, net::BoundNetLog());
-  if (rv == net::ERR_IO_PENDING)
+  scoped_ptr<HttpTransaction> trans;
+  int rv = factory_->CreateTransaction(&trans);
+  EXPECT_EQ(OK, rv);
+
+  rv = trans->Start(&request_info, &callback, BoundNetLog());
+  if (rv == ERR_IO_PENDING)
     rv = callback.WaitForResult();
-  ASSERT_EQ(net::OK, rv);
+  ASSERT_EQ(OK, rv);
 
   std::string contents;
   rv = ReadTransaction(trans.get(), &contents);
-  EXPECT_EQ(net::OK, rv);
+  EXPECT_EQ(OK, rv);
   EXPECT_EQ("hello world", contents);
 }
 
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index e3de475..b50b6e9 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -13,51 +13,38 @@
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_response_body_drainer.h"
 #include "net/http/url_security_manager.h"
+#include "net/socket/client_socket_factory.h"
 #include "net/spdy/spdy_session_pool.h"
 
 namespace net {
 
 // TODO(mbelshe): Move the socket factories into HttpStreamFactory.
-HttpNetworkSession::HttpNetworkSession(
-    HostResolver* host_resolver,
-    CertVerifier* cert_verifier,
-    DnsRRResolver* dnsrr_resolver,
-    DnsCertProvenanceChecker* dns_cert_checker,
-    SSLHostInfoFactory* ssl_host_info_factory,
-    ProxyService* proxy_service,
-    ClientSocketFactory* client_socket_factory,
-    SSLConfigService* ssl_config_service,
-    SpdySessionPool* spdy_session_pool,
-    HttpAuthHandlerFactory* http_auth_handler_factory,
-    HttpNetworkDelegate* network_delegate,
-    NetLog* net_log)
-    : socket_factory_(client_socket_factory),
-      host_resolver_(host_resolver),
-      cert_verifier_(cert_verifier),
-      dnsrr_resolver_(dnsrr_resolver),
-      dns_cert_checker_(dns_cert_checker),
-      proxy_service_(proxy_service),
-      ssl_config_service_(ssl_config_service),
-      socket_pool_manager_(net_log,
-                           client_socket_factory,
-                           host_resolver,
-                           cert_verifier,
-                           dnsrr_resolver,
-                           dns_cert_checker,
-                           ssl_host_info_factory,
-                           proxy_service,
-                           ssl_config_service),
-      spdy_session_pool_(spdy_session_pool),
-      http_auth_handler_factory_(http_auth_handler_factory),
-      network_delegate_(network_delegate),
-      net_log_(net_log) {
-  DCHECK(proxy_service);
-  DCHECK(ssl_config_service);
+HttpNetworkSession::HttpNetworkSession(const Params& params)
+    : cert_verifier_(NULL),
+      proxy_service_(params.proxy_service),
+      ssl_config_service_(params.ssl_config_service),
+      socket_pool_manager_(params.net_log,
+                           params.client_socket_factory ?
+                               params.client_socket_factory :
+                               ClientSocketFactory::GetDefaultFactory(),
+                           params.host_resolver,
+                           params.cert_verifier,
+                           params.dnsrr_resolver,
+                           params.dns_cert_checker,
+                           params.ssl_host_info_factory,
+                           params.proxy_service,
+                           params.ssl_config_service),
+      spdy_session_pool_(params.ssl_config_service),
+      http_auth_handler_factory_(params.http_auth_handler_factory),
+      network_delegate_(params.network_delegate),
+      net_log_(params.net_log) {
+  DCHECK(params.proxy_service);
+  DCHECK(params.ssl_config_service);
 }
 
 HttpNetworkSession::~HttpNetworkSession() {
   STLDeleteElements(&response_drainers_);
-  spdy_session_pool_->CloseAllSessions();
+  spdy_session_pool_.CloseAllSessions();
 }
 
 void HttpNetworkSession::AddResponseDrainer(HttpResponseBodyDrainer* drainer) {
@@ -72,7 +59,7 @@
 }
 
 Value* HttpNetworkSession::SpdySessionPoolInfoToValue() const {
-  return spdy_session_pool_->SpdySessionPoolInfoToValue();
+  return spdy_session_pool_.SpdySessionPoolInfoToValue();
 }
 
 }  //  namespace net
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index b36d7f7..36cb652 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -6,22 +6,17 @@
 #define NET_HTTP_HTTP_NETWORK_SESSION_H_
 #pragma once
 
-#include <map>
 #include <set>
 #include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/host_resolver.h"
 #include "net/base/ssl_client_auth_cache.h"
-#include "net/base/ssl_config_service.h"
 #include "net/http/http_alternate_protocols.h"
 #include "net/http/http_auth_cache.h"
-#include "net/http/http_network_delegate.h"
-#include "net/http/http_network_transaction.h"
 #include "net/http/http_stream_factory.h"
-#include "net/proxy/proxy_service.h"
 #include "net/socket/client_socket_pool_manager.h"
+#include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_settings_storage.h"
 
 class Value;
@@ -32,34 +27,49 @@
 class ClientSocketFactory;
 class DnsCertProvenanceChecker;
 class DnsRRResolver;
+class HostResolver;
 class HttpAuthHandlerFactory;
 class HttpNetworkDelegate;
 class HttpNetworkSessionPeer;
 class HttpProxyClientSocketPool;
 class HttpResponseBodyDrainer;
-class SpdySessionPool;
-class SOCKSClientSocketPool;
-class SSLClientSocketPool;
+class NetLog;
+class ProxyService;
+class SSLConfigService;
 class SSLHostInfoFactory;
-class TCPClientSocketPool;
 
 // This class holds session objects used by HttpNetworkTransaction objects.
 class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
                            public base::NonThreadSafe {
  public:
-  HttpNetworkSession(
-      HostResolver* host_resolver,
-      CertVerifier* cert_verifier,
-      DnsRRResolver* dnsrr_resolver,
-      DnsCertProvenanceChecker* dns_cert_checker,
-      SSLHostInfoFactory* ssl_host_info_factory,
-      ProxyService* proxy_service,
-      ClientSocketFactory* client_socket_factory,
-      SSLConfigService* ssl_config_service,
-      SpdySessionPool* spdy_session_pool,
-      HttpAuthHandlerFactory* http_auth_handler_factory,
-      HttpNetworkDelegate* network_delegate,
-      NetLog* net_log);
+  struct Params {
+    Params()
+        : client_socket_factory(NULL),
+          host_resolver(NULL),
+          cert_verifier(NULL),
+          dnsrr_resolver(NULL),
+          dns_cert_checker(NULL),
+          proxy_service(NULL),
+          ssl_host_info_factory(NULL),
+          ssl_config_service(NULL),
+          http_auth_handler_factory(NULL),
+          network_delegate(NULL),
+          net_log(NULL) {}
+
+    ClientSocketFactory* client_socket_factory;
+    HostResolver* host_resolver;
+    CertVerifier* cert_verifier;
+    DnsRRResolver* dnsrr_resolver;
+    DnsCertProvenanceChecker* dns_cert_checker;
+    ProxyService* proxy_service;
+    SSLHostInfoFactory* ssl_host_info_factory;
+    SSLConfigService* ssl_config_service;
+    HttpAuthHandlerFactory* http_auth_handler_factory;
+    HttpNetworkDelegate* network_delegate;
+    NetLog* net_log;
+  };
+
+  explicit HttpNetworkSession(const Params& params);
 
   HttpAuthCache* auth_cache() { return &auth_cache_; }
   SSLClientAuthCache* ssl_client_auth_cache() {
@@ -108,17 +118,10 @@
     return socket_pool_manager_.GetSocketPoolForSSLWithProxy(proxy_server);
   }
 
-  // SSL sockets come from the socket_factory().
-  ClientSocketFactory* socket_factory() { return socket_factory_; }
-  HostResolver* host_resolver() { return host_resolver_; }
   CertVerifier* cert_verifier() { return cert_verifier_; }
-  DnsRRResolver* dnsrr_resolver() { return dnsrr_resolver_; }
-  DnsCertProvenanceChecker* dns_cert_checker() {
-    return dns_cert_checker_;
-  }
   ProxyService* proxy_service() { return proxy_service_; }
   SSLConfigService* ssl_config_service() { return ssl_config_service_; }
-  SpdySessionPool* spdy_session_pool() { return spdy_session_pool_.get(); }
+  SpdySessionPool* spdy_session_pool() { return &spdy_session_pool_; }
   HttpAuthHandlerFactory* http_auth_handler_factory() {
     return http_auth_handler_factory_;
   }
@@ -154,24 +157,19 @@
 
   ~HttpNetworkSession();
 
-  ClientSocketFactory* const socket_factory_;
   HttpAuthCache auth_cache_;
   SSLClientAuthCache ssl_client_auth_cache_;
   HttpAlternateProtocols alternate_protocols_;
-  HostResolver* const host_resolver_;
   CertVerifier* cert_verifier_;
-  DnsRRResolver* dnsrr_resolver_;
-  DnsCertProvenanceChecker* dns_cert_checker_;
+  // Not const since it's modified by HttpNetworkSessionPeer for testing.
   scoped_refptr<ProxyService> proxy_service_;
-  scoped_refptr<SSLConfigService> ssl_config_service_;
+  const scoped_refptr<SSLConfigService> ssl_config_service_;
   ClientSocketPoolManager socket_pool_manager_;
-  // TODO(willchan): Move this out to IOThread so it can be shared across
-  // URLRequestContexts.
-  scoped_ptr<SpdySessionPool> spdy_session_pool_;
+  SpdySessionPool spdy_session_pool_;
   HttpStreamFactory http_stream_factory_;
-  HttpAuthHandlerFactory* http_auth_handler_factory_;
+  HttpAuthHandlerFactory* const http_auth_handler_factory_;
   HttpNetworkDelegate* const network_delegate_;
-  NetLog* net_log_;
+  NetLog* const net_log_;
   SpdySettingsStorage spdy_settings_;
   std::set<HttpResponseBodyDrainer*> response_drainers_;
 };
diff --git a/net/http/http_network_session_peer.h b/net/http/http_network_session_peer.h
index 13f3fa7..398488b 100644
--- a/net/http/http_network_session_peer.h
+++ b/net/http/http_network_session_peer.h
@@ -6,66 +6,41 @@
 #define NET_HTTP_HTTP_NETWORK_SESSION_PEER_H_
 #pragma once
 
-#include "net/http/http_network_session.h"
-#include "net/http/http_proxy_client_socket_pool.h"
-#include "net/socket/socks_client_socket_pool.h"
-#include "net/socket/ssl_client_socket_pool.h"
+#include "base/ref_counted.h"
 
 namespace net {
 
+class HostPortPair;
+class HttpNetworkSession;
+class HttpProxyClientSocketPool;
+class ProxyService;
+class SOCKSClientSocketPool;
+class SSLClientSocketPool;
+class TCPClientSocketPool;
+
 class HttpNetworkSessionPeer {
  public:
   explicit HttpNetworkSessionPeer(
-      const scoped_refptr<HttpNetworkSession>& session)
-      : session_(session) {}
+      const scoped_refptr<HttpNetworkSession>& session);
+  ~HttpNetworkSessionPeer();
 
-  void SetTCPSocketPool(TCPClientSocketPool* pool) {
-    session_->socket_pool_manager_.tcp_socket_pool_.reset(pool);
-  }
+  void SetTCPSocketPool(TCPClientSocketPool* pool);
 
   void SetSocketPoolForSOCKSProxy(
       const HostPortPair& socks_proxy,
-      SOCKSClientSocketPool* pool) {
-    ClientSocketPoolManager* socket_pool_manager =
-        &session_->socket_pool_manager_;
-
-    // Call through the public interface to force initialization of the
-    // wrapped socket pools.
-    delete socket_pool_manager->GetSocketPoolForSOCKSProxy(socks_proxy);
-    socket_pool_manager->socks_socket_pools_[socks_proxy] = pool;
-  }
+      SOCKSClientSocketPool* pool);
 
   void SetSocketPoolForHTTPProxy(
       const HostPortPair& http_proxy,
-      HttpProxyClientSocketPool* pool) {
-    ClientSocketPoolManager* socket_pool_manager =
-        &session_->socket_pool_manager_;
+      HttpProxyClientSocketPool* pool);
 
-    // Call through the public interface to force initialization of the
-    // wrapped socket pools.
-    delete socket_pool_manager->GetSocketPoolForHTTPProxy(http_proxy);
-    socket_pool_manager->http_proxy_socket_pools_[http_proxy] = pool;
-  }
-
-  void SetSSLSocketPool(SSLClientSocketPool* pool) {
-    session_->socket_pool_manager_.ssl_socket_pool_.reset(pool);
-  }
+  void SetSSLSocketPool(SSLClientSocketPool* pool);
 
   void SetSocketPoolForSSLWithProxy(
       const HostPortPair& proxy_host,
-      SSLClientSocketPool* pool) {
-    ClientSocketPoolManager* socket_pool_manager =
-        &session_->socket_pool_manager_;
+      SSLClientSocketPool* pool);
 
-    // Call through the public interface to force initialization of the
-    // wrapped socket pools.
-    delete socket_pool_manager->GetSocketPoolForSSLWithProxy(proxy_host);
-    socket_pool_manager->ssl_socket_pools_for_proxies_[proxy_host] = pool;
-  }
-
-  void SetProxyService(ProxyService* proxy_service) {
-    session_->proxy_service_ = proxy_service;
-  }
+  void SetProxyService(ProxyService* proxy_service);
 
  private:
   const scoped_refptr<HttpNetworkSession> session_;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 64a4fa7..128497f 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -33,6 +33,7 @@
 #include "net/http/http_basic_stream.h"
 #include "net/http/http_chunked_decoder.h"
 #include "net/http/http_net_log_params.h"
+#include "net/http/http_network_delegate.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_proxy_client_socket.h"
 #include "net/http/http_proxy_client_socket_pool.h"
@@ -76,6 +77,19 @@
                                     http_host_port_pair);
 }
 
+// Returns true if |error| is a client certificate authentication error.
+bool IsClientCertificateError(int error) {
+  switch (error) {
+    case ERR_BAD_SSL_CLIENT_AUTH_CERT:
+    case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
+    case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
+    case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
+      return true;
+    default:
+      return false;
+  }
+}
+
 }  // namespace
 
 //-----------------------------------------------------------------------------
@@ -486,7 +500,8 @@
         break;
       case STATE_SEND_REQUEST_COMPLETE:
         rv = DoSendRequestComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv);
         break;
       case STATE_READ_HEADERS:
         DCHECK_EQ(OK, rv);
@@ -495,7 +510,8 @@
         break;
       case STATE_READ_HEADERS_COMPLETE:
         rv = DoReadHeadersComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
         break;
       case STATE_READ_BODY:
         DCHECK_EQ(OK, rv);
@@ -504,7 +520,8 @@
         break;
       case STATE_READ_BODY_COMPLETE:
         rv = DoReadBodyComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv);
         break;
       case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
         DCHECK_EQ(OK, rv);
@@ -514,8 +531,8 @@
         break;
       case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
         rv = DoDrainBodyForAuthRestartComplete(rv);
-        net_log_.EndEvent(
-            NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv);
         break;
       default:
         NOTREACHED() << "bad state";
@@ -554,6 +571,10 @@
     return OK;
   }
 
+  // Handle possible handshake errors that may have occurred if the stream
+  // used SSL for one or more of the layers.
+  result = HandleSSLHandshakeError(result);
+
   // At this point we are done with the stream_request_.
   stream_request_.reset();
   return result;
@@ -696,23 +717,6 @@
     result = HandleCertificateRequest(result);
     if (result == OK)
       return result;
-  } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
-              result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
-             ssl_config_.tls1_enabled &&
-             !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
-    // Some buggy servers select DEFLATE compression when offered and then
-    // fail to ever decompress anything. They will send a fatal alert telling
-    // us this. Normally we would pick this up during the handshake because
-    // our Finished message is compressed and we'll never get the server's
-    // Finished if it fails to process ours.
-    //
-    // However, with False Start, we'll believe that the handshake is
-    // complete as soon as we've /sent/ our Finished message. In this case,
-    // we only find out that the server is buggy here, when we try to read
-    // the initial reply.
-    session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
-    ResetConnectionAndRequestForResend();
-    return OK;
   }
 
   if (result < 0 && result != ERR_CONNECTION_CLOSED)
@@ -1024,20 +1028,29 @@
   return OK;
 }
 
-// This method determines whether it is safe to resend the request after an
-// IO error.  It can only be called in response to request header or body
-// write errors or response header read errors.  It should not be used in
-// other cases, such as a Connect error.
-int HttpNetworkTransaction::HandleIOError(int error) {
+// TODO(rch): This does not correctly handle errors when an SSL proxy is
+// being used, as all of the errors are handled as if they were generated
+// by the endpoint host, request_->url, rather than considering if they were
+// generated by the SSL proxy. http://crbug.com/69329
+int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
+  DCHECK(request_);
+  if (ssl_config_.send_client_cert &&
+      (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
+    session_->ssl_client_auth_cache()->Remove(
+        GetHostAndPort(request_->url));
+  }
+
   switch (error) {
-    // If we try to reuse a connection that the server is in the process of
-    // closing, we may end up successfully writing out our request (or a
-    // portion of our request) only to find a connection error when we try to
-    // read from (or finish writing to) the socket.
-    case ERR_CONNECTION_RESET:
-    case ERR_CONNECTION_CLOSED:
-    case ERR_CONNECTION_ABORTED:
-      if (ShouldResendRequest(error)) {
+    case ERR_SSL_PROTOCOL_ERROR:
+    case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
+    case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
+    case ERR_SSL_BAD_RECORD_MAC_ALERT:
+      if (ssl_config_.tls1_enabled &&
+          !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
+        // This could be a TLS-intolerant server, an SSL 3.0 server that
+        // chose a TLS-only cipher suite or a server with buggy DEFLATE
+        // support. Turn off TLS 1.0, DEFLATE support and retry.
+        session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
         ResetConnectionAndRequestForResend();
         error = OK;
       }
@@ -1056,6 +1069,37 @@
   return error;
 }
 
+// This method determines whether it is safe to resend the request after an
+// IO error.  It can only be called in response to request header or body
+// write errors or response header read errors.  It should not be used in
+// other cases, such as a Connect error.
+int HttpNetworkTransaction::HandleIOError(int error) {
+  // SSL errors may happen at any time during the stream and indicate issues
+  // with the underlying connection. Because the peer may request
+  // renegotiation at any time, check and handle any possible SSL handshake
+  // related errors. In addition to renegotiation, TLS False/Snap Start may
+  // cause SSL handshake errors to be delayed until the first or second Write
+  // (Snap Start) or the first Read (False & Snap Start) on the underlying
+  // connection.
+  error = HandleSSLHandshakeError(error);
+
+  switch (error) {
+    // If we try to reuse a connection that the server is in the process of
+    // closing, we may end up successfully writing out our request (or a
+    // portion of our request) only to find a connection error when we try to
+    // read from (or finish writing to) the socket.
+    case ERR_CONNECTION_RESET:
+    case ERR_CONNECTION_CLOSED:
+    case ERR_CONNECTION_ABORTED:
+      if (ShouldResendRequest(error)) {
+        ResetConnectionAndRequestForResend();
+        error = OK;
+      }
+      break;
+  }
+  return error;
+}
+
 void HttpNetworkTransaction::ResetStateForRestart() {
   ResetStateForAuthRestart();
   stream_.reset();
@@ -1191,22 +1235,6 @@
   return description;
 }
 
-// TODO(gavinp): re-adjust this once SPDY v3 has three priority bits,
-// eliminating the need for this folding.
-int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) {
-  DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES);
-  switch (priority) {
-    case LOWEST:
-      return SPDY_PRIORITY_LOWEST-1;
-    case IDLE:
-      return SPDY_PRIORITY_LOWEST;
-    default:
-      return priority;
-  }
-}
-
-
-
 #undef STATE_CASE
 
 }  // namespace net
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index dfcee41..66b6b29 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -137,6 +137,11 @@
   // Called to handle a client certificate request.
   int HandleCertificateRequest(int error);
 
+  // Called to possibly recover from an SSL handshake error.  Sets next_state_
+  // and returns OK if recovering from the error.  Otherwise, the same error
+  // code is returned.
+  int HandleSSLHandshakeError(int error);
+
   // Called to possibly recover from the given error.  Sets next_state_ and
   // returns OK if recovering from the error.  Otherwise, the same error code
   // is returned.
@@ -249,8 +254,6 @@
   DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction);
 };
 
-int ConvertRequestPriorityToSpdyPriority(RequestPriority priority);
-
 }  // namespace net
 
 #endif  // NET_HTTP_HTTP_NETWORK_TRANSACTION_H_
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 260de13..8c87136 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -20,6 +20,7 @@
 #include "net/base/net_log.h"
 #include "net/base/net_log_unittest.h"
 #include "net/base/request_priority.h"
+#include "net/base/ssl_cert_request_info.h"
 #include "net/base/ssl_config_service_defaults.h"
 #include "net/base/ssl_info.h"
 #include "net/base/test_completion_callback.h"
@@ -101,18 +102,16 @@
 };
 
 HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
-  return new HttpNetworkSession(session_deps->host_resolver.get(),
-                                session_deps->cert_verifier.get(),
-                                NULL /* dnsrr_resolver */,
-                                NULL /* dns_cert_checker */,
-                                NULL /* ssl_host_info_factory */,
-                                session_deps->proxy_service,
-                                &session_deps->socket_factory,
-                                session_deps->ssl_config_service,
-                                new SpdySessionPool(NULL),
-                                session_deps->http_auth_handler_factory.get(),
-                                NULL,
-                                session_deps->net_log);
+  net::HttpNetworkSession::Params params;
+  params.client_socket_factory = &session_deps->socket_factory;
+  params.host_resolver = session_deps->host_resolver.get();
+  params.cert_verifier = session_deps->cert_verifier.get();
+  params.proxy_service = session_deps->proxy_service;
+  params.ssl_config_service = session_deps->ssl_config_service;
+  params.http_auth_handler_factory =
+      session_deps->http_auth_handler_factory.get();
+  params.net_log = session_deps->net_log;
+  return new HttpNetworkSession(params);
 }
 
 class HttpNetworkTransactionTest : public PlatformTest {
@@ -147,15 +146,15 @@
                                         size_t reads_count) {
     SimpleGetHelperResult out;
 
-    SessionDependencies session_deps;
-    scoped_ptr<HttpTransaction> trans(
-        new HttpNetworkTransaction(CreateSession(&session_deps)));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/");
     request.load_flags = 0;
 
+    SessionDependencies session_deps;
+    scoped_ptr<HttpTransaction> trans(
+        new HttpNetworkTransaction(CreateSession(&session_deps)));
+
     StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
     session_deps.socket_factory.AddSocketDataProvider(&data);
 
@@ -253,7 +252,8 @@
 template<typename ParentPool>
 class CaptureGroupNameSocketPool : public ParentPool {
  public:
-  explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
+  CaptureGroupNameSocketPool(HostResolver* host_resolver,
+                             CertVerifier* cert_verifier);
 
   const std::string last_group_name_received() const {
     return last_group_name_;
@@ -271,7 +271,8 @@
   virtual void CancelRequest(const std::string& group_name,
                              ClientSocketHandle* handle) {}
   virtual void ReleaseSocket(const std::string& group_name,
-                             ClientSocket* socket) {}
+                             ClientSocket* socket,
+                             int id) {}
   virtual void CloseIdleSockets() {}
   virtual int IdleSocketCount() const {
     return 0;
@@ -302,20 +303,21 @@
 
 template<typename ParentPool>
 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
-    HttpNetworkSession* session)
-    : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
+    HostResolver* host_resolver,
+    CertVerifier* /* cert_verifier */)
+    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
 
 template<>
 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
-    HttpNetworkSession* session)
-    : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
-                                NULL, NULL) {}
+    HostResolver* host_resolver,
+    CertVerifier* /* cert_verifier */)
+    : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
 
 template<>
 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
-    HttpNetworkSession* session)
-    : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
-                          session->cert_verifier(), NULL, NULL,
+    HostResolver* host_resolver,
+    CertVerifier* cert_verifier)
+    : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
                           NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
 
 //-----------------------------------------------------------------------------
@@ -563,15 +565,15 @@
 // Do a request using the HEAD method. Verify that we don't try to read the
 // message body (since HEAD has none).
 TEST_F(HttpNetworkTransactionTest, Head) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "HEAD";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes1[] = {
     MockWrite("HEAD / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -641,13 +643,13 @@
   };
 
   for (int i = 0; i < 2; ++i) {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     TestCompletionCallback callback;
 
     int rv = trans->Start(&request, &callback, BoundNetLog());
@@ -670,10 +672,6 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, Ignores100) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "POST";
   request.url = GURL("http://www.foo.com/");
@@ -681,6 +679,10 @@
   request.upload_data->AppendBytes("foo", 3);
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockRead data_reads[] = {
     MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
     MockRead("HTTP/1.0 200 OK\r\n\r\n"),
@@ -714,15 +716,15 @@
 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
 // HTTP/1.1 and the two status headers are read in one read.
 TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.foo.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockRead data_reads[] = {
     MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
              "HTTP/1.1 200 OK\r\n\r\n"),
@@ -753,15 +755,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "POST";
   request.url = GURL("http://www.foo.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockRead data_reads[] = {
     MockRead(false, "HTTP/1.0 100 Continue\r\n"),
     MockRead(true, 0),
@@ -784,15 +786,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "POST";
   request.url = GURL("http://www.foo.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockRead data_reads[] = {
     MockRead(true, 0),
   };
@@ -812,14 +814,14 @@
 // transaction to resend the request.
 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
     const MockRead& read_failure) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.foo.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockRead data1_reads[] = {
     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
     MockRead("hello"),
@@ -875,15 +877,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockRead data_reads[] = {
     MockRead(true, ERR_CONNECTION_RESET),
     MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
@@ -929,14 +931,14 @@
 // Test that we correctly reuse a keep-alive connection after not explicitly
 // reading the body.
 TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.foo.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   // Note that because all these reads happen in the same
   // StaticSocketDataProvider, it shows that the same socket is being reused for
   // all transactions.
@@ -1024,15 +1026,15 @@
 // Test the request-challenge-retry sequence for basic auth.
 // (basic auth is the easiest to mock, because it has no randomness).
 TEST_F(HttpNetworkTransactionTest, BasicAuth) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1109,15 +1111,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1152,14 +1154,14 @@
 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
 // connection.
 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1227,14 +1229,14 @@
 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
 // connection and with no response body to drain.
 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1300,14 +1302,14 @@
 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
 // connection and with a large response body to drain.
 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1381,14 +1383,14 @@
 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
 // connection, but the server gets impatient and closes the connection.
 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1472,18 +1474,18 @@
 // Test the request-challenge-retry sequence for basic auth, over a connection
 // that requires a restart when setting up an SSL tunnel.
 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
-  // Configure against proxy server "myproxy:70".
-  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
-  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
-  session_deps.net_log = log.bound().net_log();
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("https://www.google.com/");
   // when the no authentication data flag is set.
   request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
 
+  // Configure against proxy server "myproxy:70".
+  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+  session_deps.net_log = log.bound().net_log();
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes1[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1582,6 +1584,13 @@
 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
 // proxy connection, when setting up an SSL tunnel.
 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  // Ensure that proxy authentication is attempted even
+  // when the no authentication data flag is set.
+  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+
   // Configure against proxy server "myproxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -1590,13 +1599,6 @@
 
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  // Ensure that proxy authentication is attempted even
-  // when the no authentication data flag is set.
-  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
-
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes1[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1696,6 +1698,11 @@
 // Test that we don't read the response body when we fail to establish a tunnel,
 // even if the user cancels the proxy's auth attempt.
 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against proxy server "myproxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
 
@@ -1703,11 +1710,6 @@
 
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1754,16 +1756,16 @@
 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
 TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
-  // We are using a DIRECT connection (i.e. no proxy) for this session.
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  // We are using a DIRECT connection (i.e. no proxy) for this session.
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -1799,15 +1801,15 @@
 // response came from the proxy or the server, so it is treated as if the proxy
 // issued the challenge.
 TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+
   SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
   session_deps.net_log = log.bound().net_log();
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes1[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -1856,16 +1858,16 @@
 
 // Test a simple get through an HTTPS Proxy.
 TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+
   // Configure against https proxy server "proxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
   session_deps.net_log = log.bound().net_log();
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-
   // Since we have proxy, should use full url
   MockWrite data_writes1[] = {
     MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
@@ -1910,17 +1912,17 @@
 
 // Test a SPDY get through an HTTPS Proxy.
 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against https proxy server "proxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
   session_deps.net_log = log.bound().net_log();
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-  request.load_flags = 0;
-
   // fetch http://www.google.com/ via SPDY
   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
                                                    false));
@@ -1969,6 +1971,11 @@
 
 // Test a SPDY get through an HTTPS Proxy.
 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against https proxy server "proxy:70".
   SessionDependencies session_deps(
       ProxyService::CreateFixed("https://proxy:70"));
@@ -1976,11 +1983,6 @@
   session_deps.net_log = log.bound().net_log();
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-  request.load_flags = 0;
-
   // The first request will be a bare GET, the second request will be a
   // GET with a Proxy-Authorization header.
   scoped_ptr<spdy::SpdyFrame> req_get(
@@ -2076,6 +2078,11 @@
 
 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against https proxy server "proxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -2084,11 +2091,6 @@
 
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   // CONNECT to www.google.com:443 via SPDY
   scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
   // fetch https://www.google.com/ via HTTP
@@ -2154,6 +2156,11 @@
 
 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against https proxy server "proxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -2162,11 +2169,6 @@
 
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   // CONNECT to www.google.com:443 via SPDY
   scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
   // fetch https://www.google.com/ via SPDY
@@ -2228,6 +2230,11 @@
 
 // Test a SPDY CONNECT failure through an HTTPS Proxy.
 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against https proxy server "proxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
@@ -2236,11 +2243,6 @@
 
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   // CONNECT to www.google.com:443 via SPDY
   scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
   scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
@@ -2289,18 +2291,18 @@
 
 // Test the challenge-response-retry sequence through an HTTPS Proxy
 TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
-  // Configure against https proxy server "proxy:70".
-  SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
-  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
-  session_deps.net_log = log.bound().net_log();
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   // when the no authentication data flag is set.
   request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
 
+  // Configure against https proxy server "proxy:70".
+  SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
+  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+  session_deps.net_log = log.bound().net_log();
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   // Since we have proxy, should use full url
   MockWrite data_writes1[] = {
     MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
@@ -2381,16 +2383,16 @@
 
 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
     const MockRead& status, int expected_status) {
-  // Configure against proxy server "myproxy:70".
-  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
-
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("https://www.google.com/");
   request.load_flags = 0;
 
+  // Configure against proxy server "myproxy:70".
+  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -2593,17 +2595,17 @@
 // authentication. Again, this uses basic auth for both since that is
 // the simplest to mock.
 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+  request.load_flags = 0;
+
   SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
 
   // Configure against proxy server "myproxy:70".
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
       CreateSession(&session_deps)));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-  request.load_flags = 0;
-
   MockWrite data_writes1[] = {
     MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -2730,16 +2732,16 @@
 
 // Enter the correct password and authenticate successfully.
 TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
-                                                    MockGetHostName);
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://172.22.68.17/kids/login.aspx");
   request.load_flags = 0;
 
+  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
+                                                    MockGetHostName);
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockWrite data_writes1[] = {
     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
               "Host: 172.22.68.17\r\n"
@@ -2822,28 +2824,37 @@
   rv = callback1.WaitForResult();
   EXPECT_EQ(OK, rv);
 
-  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
-  TestCompletionCallback callback2;
-  rv = trans->RestartWithAuth(string16(), string16(), &callback2);
-  EXPECT_EQ(ERR_IO_PENDING, rv);
-  rv = callback2.WaitForResult();
-  EXPECT_EQ(OK, rv);
   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
 
   const HttpResponseInfo* response = trans->GetResponseInfo();
-  ASSERT_FALSE(response == NULL);
+  ASSERT_TRUE(response != NULL);
 
   // The password prompt info should have been set in
   // response->auth_challenge.
-  EXPECT_FALSE(response->auth_challenge.get() == NULL);
+  ASSERT_FALSE(response->auth_challenge.get() == NULL);
 
   EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
   EXPECT_EQ(L"", response->auth_challenge->realm);
   EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
 
+  TestCompletionCallback callback2;
+
+  rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
+  EXPECT_EQ(ERR_IO_PENDING, rv);
+
+  rv = callback2.WaitForResult();
+  EXPECT_EQ(OK, rv);
+
+  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
+
+  response = trans->GetResponseInfo();
+  ASSERT_TRUE(response != NULL);
+
+  EXPECT_TRUE(response->auth_challenge.get() == NULL);
+
   TestCompletionCallback callback3;
 
-  rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
+  rv = trans->RestartWithAuth(string16(), string16(), &callback3);
   EXPECT_EQ(ERR_IO_PENDING, rv);
 
   rv = callback3.WaitForResult();
@@ -2851,23 +2862,22 @@
 
   response = trans->GetResponseInfo();
   ASSERT_FALSE(response == NULL);
-
   EXPECT_TRUE(response->auth_challenge.get() == NULL);
   EXPECT_EQ(13, response->headers->GetContentLength());
 }
 
 // Enter a wrong password, and then the correct one.
 TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
-  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
-                                                    MockGetHostName);
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://172.22.68.17/kids/login.aspx");
   request.load_flags = 0;
 
+  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
+                                                    MockGetHostName);
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
   MockWrite data_writes1[] = {
     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
               "Host: 172.22.68.17\r\n"
@@ -3001,12 +3011,6 @@
   rv = callback1.WaitForResult();
   EXPECT_EQ(OK, rv);
 
-  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
-  TestCompletionCallback callback2;
-  rv = trans->RestartWithAuth(string16(), string16(), &callback2);
-  EXPECT_EQ(ERR_IO_PENDING, rv);
-  rv = callback2.WaitForResult();
-  EXPECT_EQ(OK, rv);
   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
 
   const HttpResponseInfo* response = trans->GetResponseInfo();
@@ -3019,25 +3023,25 @@
   EXPECT_EQ(L"", response->auth_challenge->realm);
   EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
 
-  TestCompletionCallback callback3;
+  TestCompletionCallback callback2;
 
   // Enter the wrong password.
-  rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
+  rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
   EXPECT_EQ(ERR_IO_PENDING, rv);
 
-  rv = callback3.WaitForResult();
+  rv = callback2.WaitForResult();
   EXPECT_EQ(OK, rv);
 
   EXPECT_TRUE(trans->IsReadyToRestartForAuth());
-  TestCompletionCallback callback4;
-  rv = trans->RestartWithAuth(string16(), string16(), &callback4);
+  TestCompletionCallback callback3;
+  rv = trans->RestartWithAuth(string16(), string16(), &callback3);
   EXPECT_EQ(ERR_IO_PENDING, rv);
-  rv = callback4.WaitForResult();
+  rv = callback3.WaitForResult();
   EXPECT_EQ(OK, rv);
   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
 
   response = trans->GetResponseInfo();
-  EXPECT_FALSE(response == NULL);
+  ASSERT_TRUE(response != NULL);
 
   // The password prompt info should have been set in response->auth_challenge.
   EXPECT_FALSE(response->auth_challenge.get() == NULL);
@@ -3046,10 +3050,21 @@
   EXPECT_EQ(L"", response->auth_challenge->realm);
   EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
 
-  TestCompletionCallback callback5;
+  TestCompletionCallback callback4;
 
   // Now enter the right password.
-  rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
+  rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
+  EXPECT_EQ(ERR_IO_PENDING, rv);
+
+  rv = callback4.WaitForResult();
+  EXPECT_EQ(OK, rv);
+
+  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
+
+  TestCompletionCallback callback5;
+
+  // One more roundtrip
+  rv = trans->RestartWithAuth(string16(), string16(), &callback5);
   EXPECT_EQ(ERR_IO_PENDING, rv);
 
   rv = callback5.WaitForResult();
@@ -3065,15 +3080,15 @@
 // After some maximum number of bytes is consumed, the transaction should
 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
 TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   // Respond with 300 kb of headers (we should fail after 256 kb).
   std::string large_headers_string;
   FillLargeHeadersString(&large_headers_string, 300 * 1024);
@@ -3103,6 +3118,11 @@
 // establish tunnel.
 // http://code.google.com/p/chromium/issues/detail?id=3772
 TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   // Configure against proxy server "myproxy:70".
   SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
 
@@ -3110,11 +3130,6 @@
 
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes1[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -3161,16 +3176,16 @@
 
 // Make sure that we recycle a socket after reading all of the response body.
 TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
-  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
   MockRead data_reads[] = {
     // A part of the response body is received with the response headers.
     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
@@ -3371,11 +3386,6 @@
 // Make sure that we recycle a socket after a zero-length response.
 // http://crbug.com/9880
 TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
-  SessionDependencies session_deps;
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-
-  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
@@ -3384,6 +3394,11 @@
                      "rt=prt.2642,ol.2649,xjs.2951");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
   MockRead data_reads[] = {
     MockRead("HTTP/1.1 204 No Content\r\n"
              "Content-Length: 0\r\n"
@@ -3516,15 +3531,15 @@
 // an identity in the URL. The request should be sent as normal, but when
 // it fails the identity from the URL is used to answer the challenge.
 TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   // Note: the URL has a username:password in it.
   request.url = GURL("http://foo:b@r@www.google.com/");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   // The password contains an escaped character -- for this test to pass it
   // will need to be unescaped by HttpNetworkTransaction.
   EXPECT_EQ("b%40r", request.url.password());
@@ -3598,10 +3613,6 @@
 // an incorrect identity in the URL. The identity from the URL should be used
 // only once.
 TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   // Note: the URL has a username:password in it.  The password "baz" is
@@ -3610,6 +3621,10 @@
 
   request.load_flags = LOAD_NORMAL;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes1[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -3715,13 +3730,13 @@
 
   // Transaction 1: authenticate (foo, bar) on MyRealm1
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/x/y/z");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /x/y/z HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -3794,8 +3809,6 @@
 
   // Transaction 2: authenticate (foo2, bar2) on MyRealm2
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     // Note that Transaction 1 was at /x/y/z, so this is in the same
@@ -3803,6 +3816,8 @@
     request.url = GURL("http://www.google.com/x/y/a/b");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -3880,13 +3895,13 @@
   // Transaction 3: Resend a request in MyRealm's protection space --
   // succeed with preemptive authorization.
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/x/y/z2");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -3927,13 +3942,13 @@
   // Transaction 4: request another URL in MyRealm (however the
   // url is not known to belong to the protection space, so no pre-auth).
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/x/1");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /x/1 HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -3996,13 +4011,13 @@
   // Transaction 5: request a URL in MyRealm, but the server rejects the
   // cached identity. Should invalidate and re-prompt.
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/p/q/t");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /p/q/t HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -4114,13 +4129,13 @@
 
   // Transaction 1: authenticate (foo, bar) on MyRealm1
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     request.url = GURL("http://www.google.com/x/y/z");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /x/y/z HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -4196,8 +4211,6 @@
   // This will preemptively add an Authorization header which should have an
   // "nc" value of 2 (as compared to 1 in the first use.
   {
-    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
     HttpRequestInfo request;
     request.method = "GET";
     // Note that Transaction 1 was at /x/y/z, so this is in the same
@@ -4205,6 +4218,8 @@
     request.url = GURL("http://www.google.com/x/y/a/b");
     request.load_flags = 0;
 
+    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
     MockWrite data_writes1[] = {
       MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
                 "Host: www.google.com\r\n"
@@ -4285,15 +4300,15 @@
 
 // Test HTTPS connections to a site with a bad certificate
 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("https://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -4786,16 +4801,16 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
                                   "Chromium Ultra Awesome X Edition");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -4825,16 +4840,16 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
-  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("https://www.google.com/");
   request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
                                   "Chromium Ultra Awesome X Edition");
 
+  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -4863,16 +4878,16 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
   request.referrer = GURL("http://the.previous.site.com/");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -4902,14 +4917,14 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "POST";
   request.url = GURL("http://www.google.com/");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("POST / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -4939,14 +4954,14 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "PUT";
   request.url = GURL("http://www.google.com/");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("PUT / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -4976,14 +4991,14 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "HEAD";
   request.url = GURL("http://www.google.com/");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("HEAD / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -5013,15 +5028,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = LOAD_BYPASS_CACHE;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -5053,15 +5068,15 @@
 
 TEST_F(HttpNetworkTransactionTest,
        BuildRequest_CacheControlValidateCache) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = LOAD_VALIDATE_CACHE;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -5091,15 +5106,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.extra_headers.SetHeader("FooHeader", "Bar");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -5129,10 +5144,6 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
@@ -5140,6 +5151,10 @@
   request.extra_headers.SetHeader("hEllo", "Kitty");
   request.extra_headers.SetHeader("FoO", "bar");
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockWrite data_writes[] = {
     MockWrite("GET / HTTP/1.1\r\n"
               "Host: www.google.com\r\n"
@@ -5170,17 +5185,17 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+  request.load_flags = 0;
+
   SessionDependencies session_deps(
       ProxyService::CreateFixed("socks4://myproxy:1080"));
 
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(CreateSession(&session_deps)));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-  request.load_flags = 0;
-
   char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
   char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
 
@@ -5221,17 +5236,17 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   SessionDependencies session_deps(
       ProxyService::CreateFixed("socks4://myproxy:1080"));
 
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(CreateSession(&session_deps)));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
   unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
 
@@ -5277,17 +5292,17 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+  request.load_flags = 0;
+
   SessionDependencies session_deps(
       ProxyService::CreateFixed("socks5://myproxy:1080"));
 
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(CreateSession(&session_deps)));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-  request.load_flags = 0;
-
   const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
   const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
   const char kSOCKS5OkRequest[] = {
@@ -5342,17 +5357,17 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("https://www.google.com/");
+  request.load_flags = 0;
+
   SessionDependencies session_deps(
       ProxyService::CreateFixed("socks5://myproxy:1080"));
 
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(CreateSession(&session_deps)));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.google.com/");
-  request.load_flags = 0;
-
   const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
   const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
   const unsigned char kSOCKS5OkRequest[] = {
@@ -5437,13 +5452,13 @@
 int GroupNameTransactionHelper(
     const std::string& url,
     const scoped_refptr<HttpNetworkSession>& session) {
-  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL(url);
   request.load_flags = 0;
 
+  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
   TestCompletionCallback callback;
 
   // We do not complete this request, the dtor will clean the transaction up.
@@ -5494,10 +5509,10 @@
 
     HttpNetworkSessionPeer peer(session);
     CaptureGroupNameTCPSocketPool* tcp_conn_pool =
-        new CaptureGroupNameTCPSocketPool(session);
+        new CaptureGroupNameTCPSocketPool(NULL, NULL);
     peer.SetTCPSocketPool(tcp_conn_pool);
     CaptureGroupNameSSLSocketPool* ssl_conn_pool =
-        new CaptureGroupNameSSLSocketPool(session.get());
+        new CaptureGroupNameSSLSocketPool(NULL, NULL);
     peer.SetSSLSocketPool(ssl_conn_pool);
 
     EXPECT_EQ(ERR_IO_PENDING,
@@ -5548,10 +5563,10 @@
 
     HostPortPair proxy_host("http_proxy", 80);
     CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
-        new CaptureGroupNameHttpProxySocketPool(session);
+        new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
     peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
     CaptureGroupNameSSLSocketPool* ssl_conn_pool =
-        new CaptureGroupNameSSLSocketPool(session);
+        new CaptureGroupNameSSLSocketPool(NULL, NULL);
     peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
 
     EXPECT_EQ(ERR_IO_PENDING,
@@ -5613,10 +5628,10 @@
 
     HostPortPair proxy_host("socks_proxy", 1080);
     CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
-        new CaptureGroupNameSOCKSSocketPool(session);
+        new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
     peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
     CaptureGroupNameSSLSocketPool* ssl_conn_pool =
-        new CaptureGroupNameSSLSocketPool(session);
+        new CaptureGroupNameSSLSocketPool(NULL, NULL);
     peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
 
     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
@@ -5635,6 +5650,10 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+
   SessionDependencies session_deps(
       ProxyService::CreateFixed("myproxy:70;foobar:80"));
 
@@ -5645,10 +5664,6 @@
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(CreateSession(&session_deps)));
 
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("http://www.google.com/");
-
   TestCompletionCallback callback;
 
   int rv = trans->Start(&request, &callback, BoundNetLog());
@@ -5705,6 +5720,12 @@
   EXPECT_TRUE(referrer.is_valid());
   ResolutionReferrerObserver resolution_observer(referrer);
 
+  // Issue a request, containing an HTTP referrer.
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.referrer = referrer;
+  request.url = GURL("http://www.google.com/");
+
   SessionDependencies session_deps;
   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
       CreateSession(&session_deps)));
@@ -5719,12 +5740,6 @@
   StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
   session_deps.socket_factory.AddSocketDataProvider(&data);
 
-  // Issue a request, containing an HTTP referrer.
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.referrer = referrer;
-  request.url = GURL("http://www.google.com/");
-
   // Run the request until it fails reading from the socket.
   TestCompletionCallback callback;
   int rv = trans->Start(&request, &callback, BoundNetLog());
@@ -5739,6 +5754,12 @@
 // Base test to make sure that when the load flags for a request specify to
 // bypass the cache, the DNS cache is not used.
 void BypassHostCacheOnRefreshHelper(int load_flags) {
+  // Issue a request, asking to bypass the cache(s).
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.load_flags = load_flags;
+  request.url = GURL("http://www.google.com/");
+
   SessionDependencies session_deps;
 
   // Select a host resolver that does caching.
@@ -5774,12 +5795,6 @@
   StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
   session_deps.socket_factory.AddSocketDataProvider(&data);
 
-  // Issue a request, asking to bypass the cache(s).
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.load_flags = load_flags;
-  request.url = GURL("http://www.google.com/");
-
   // Run the request.
   TestCompletionCallback callback;
   rv = trans->Start(&request, &callback, BoundNetLog());
@@ -5995,15 +6010,15 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   MockRead data_reads[] = {
     MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
     MockRead(false, OK),
@@ -6031,16 +6046,16 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
-  SessionDependencies session_deps;
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "POST";
   request.url = GURL("http://www.google.com/upload");
   request.upload_data = new UploadData;
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   FilePath temp_file_path;
   ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
   const uint64 kFakeSize = 100000;  // file is actually blank
@@ -6084,6 +6099,12 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
+  HttpRequestInfo request;
+  request.method = "POST";
+  request.url = GURL("http://www.google.com/upload");
+  request.upload_data = new UploadData;
+  request.load_flags = 0;
+
   // If we try to upload an unreadable file, the network stack should report
   // the file size as zero and upload zero bytes for that file.
   SessionDependencies session_deps;
@@ -6097,12 +6118,6 @@
                                    temp_file_content.length()));
   ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
 
-  HttpRequestInfo request;
-  request.method = "POST";
-  request.url = GURL("http://www.google.com/upload");
-  request.upload_data = new UploadData;
-  request.load_flags = 0;
-
   std::vector<UploadData::Element> elements;
   UploadData::Element element;
   element.SetToFilePath(temp_file);
@@ -6141,6 +6156,12 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
+  HttpRequestInfo request;
+  request.method = "POST";
+  request.url = GURL("http://www.google.com/upload");
+  request.upload_data = new UploadData;
+  request.load_flags = 0;
+
   SessionDependencies session_deps;
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(CreateSession(&session_deps)));
@@ -6152,12 +6173,6 @@
   ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
                                    temp_file_contents.length()));
 
-  HttpRequestInfo request;
-  request.method = "POST";
-  request.url = GURL("http://www.google.com/upload");
-  request.upload_data = new UploadData;
-  request.load_flags = 0;
-
   std::vector<UploadData::Element> elements;
   UploadData::Element element;
   element.SetToFilePath(temp_file);
@@ -6919,15 +6934,14 @@
 
   SSLConfig ssl_config;
   session->ssl_config_service()->GetSSLConfig(&ssl_config);
-  ClientSocket* socket = connection->release_socket();
-  socket = session->socket_factory()->CreateSSLClientSocket(
-      socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */,
-      session->cert_verifier());
-  connection->set_socket(socket);
-  EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
+  scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
+  ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
+      connection.release(), HostPortPair("" , 443), ssl_config,
+      NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL));
+  EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
   EXPECT_EQ(OK, callback.WaitForResult());
 
-  EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
+  EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
                                                    true, OK));
 
   trans.reset(new HttpNetworkTransaction(session));
@@ -7383,15 +7397,30 @@
                                   origin, BoundNetLog());
   auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
 
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
-  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
-
   int rv = OK;
   const HttpResponseInfo* response = NULL;
   HttpRequestInfo request;
   request.method = "GET";
   request.url = origin;
   request.load_flags = 0;
+
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+  // Use a TCP Socket Pool with only one connection per group. This is used
+  // to validate that the TCP socket is not released to the pool between
+  // each round of multi-round authentication.
+  HttpNetworkSessionPeer session_peer(session);
+  ClientSocketPoolHistograms tcp_pool_histograms("SmallTCP");
+  TCPClientSocketPool* tcp_pool = new TCPClientSocketPool(
+      50,  // Max sockets for pool
+      1,   // Max sockets per group
+      &tcp_pool_histograms,
+      session_deps.host_resolver.get(),
+      &session_deps.socket_factory,
+      session_deps.net_log);
+  session_peer.SetTCPSocketPool(tcp_pool);
+
+  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
   TestCompletionCallback callback;
 
   const MockWrite kGet(
@@ -7424,7 +7453,9 @@
     // Third round
     kGetAuth,
     // Fourth round
-    kGetAuth
+    kGetAuth,
+    // Competing request
+    kGet,
   };
   MockRead reads[] = {
     // First round
@@ -7435,12 +7466,16 @@
     kServerChallenge,
     // Fourth round
     kSuccess,
+    // Competing response
+    kSuccess,
   };
   StaticSocketDataProvider data_provider(reads, arraysize(reads),
                                          writes, arraysize(writes));
   session_deps.socket_factory.AddSocketDataProvider(&data_provider);
 
-  // First round
+  const char* const kSocketGroup = "www.example.com:80";
+
+  // First round of authentication.
   auth_handler->SetGenerateExpectation(false, OK);
   rv = trans->Start(&request, &callback, BoundNetLog());
   if (rv == ERR_IO_PENDING)
@@ -7449,8 +7484,21 @@
   response = trans->GetResponseInfo();
   ASSERT_FALSE(response == NULL);
   EXPECT_FALSE(response->auth_challenge.get() == NULL);
+  EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
 
-  // Second round
+  // In between rounds, another request comes in for the same domain.
+  // It should not be able to grab the TCP socket that trans has already
+  // claimed.
+  scoped_ptr<HttpTransaction> trans_compete(
+      new HttpNetworkTransaction(session));
+  TestCompletionCallback callback_compete;
+  rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
+  EXPECT_EQ(ERR_IO_PENDING, rv);
+  // callback_compete.WaitForResult at this point would stall forever,
+  // since the HttpNetworkTransaction does not release the request back to
+  // the pool until after authentication completes.
+
+  // Second round of authentication.
   auth_handler->SetGenerateExpectation(false, OK);
   rv = trans->RestartWithAuth(kFoo, kBar, &callback);
   if (rv == ERR_IO_PENDING)
@@ -7459,8 +7507,9 @@
   response = trans->GetResponseInfo();
   ASSERT_FALSE(response == NULL);
   EXPECT_TRUE(response->auth_challenge.get() == NULL);
+  EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
 
-  // Third round
+  // Third round of authentication.
   auth_handler->SetGenerateExpectation(false, OK);
   rv = trans->RestartWithAuth(string16(), string16(), &callback);
   if (rv == ERR_IO_PENDING)
@@ -7469,8 +7518,9 @@
   response = trans->GetResponseInfo();
   ASSERT_FALSE(response == NULL);
   EXPECT_TRUE(response->auth_challenge.get() == NULL);
+  EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
 
-  // Fourth round
+  // Fourth round of authentication, which completes successfully.
   auth_handler->SetGenerateExpectation(false, OK);
   rv = trans->RestartWithAuth(string16(), string16(), &callback);
   if (rv == ERR_IO_PENDING)
@@ -7479,6 +7529,34 @@
   response = trans->GetResponseInfo();
   ASSERT_FALSE(response == NULL);
   EXPECT_TRUE(response->auth_challenge.get() == NULL);
+  EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
+
+  // Read the body since the fourth round was successful. This will also
+  // release the socket back to the pool.
+  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
+  rv = trans->Read(io_buf, io_buf->size(), &callback);
+  if (rv == ERR_IO_PENDING)
+    rv = callback.WaitForResult();
+  EXPECT_EQ(3, rv);
+  rv = trans->Read(io_buf, io_buf->size(), &callback);
+  EXPECT_EQ(0, rv);
+  // There are still 0 idle sockets, since the trans_compete transaction
+  // will be handed it immediately after trans releases it to the group.
+  EXPECT_EQ(0, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
+
+  // The competing request can now finish. Wait for the headers and then
+  // read the body.
+  rv = callback_compete.WaitForResult();
+  EXPECT_EQ(OK, rv);
+  rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
+  if (rv == ERR_IO_PENDING)
+    rv = callback.WaitForResult();
+  EXPECT_EQ(3, rv);
+  rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
+  EXPECT_EQ(0, rv);
+
+  // Finally, the socket is released to the group.
+  EXPECT_EQ(1, tcp_pool->IdleSocketCountInGroup(kSocketGroup));
 }
 
 class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
@@ -7858,16 +7936,16 @@
     MockRead(false, OK),
   };
 
-  SessionDependencies session_deps;
-  session_deps.host_resolver->set_synchronous_mode(true);
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(CreateSession(&session_deps)));
-
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.google.com/");
   request.load_flags = 0;
 
+  SessionDependencies session_deps;
+  session_deps.host_resolver->set_synchronous_mode(true);
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
   StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
   data.set_connect_data(mock_connect);
   session_deps.socket_factory.AddSocketDataProvider(&data);
@@ -8118,6 +8196,11 @@
 // Given a net error, cause that error to be returned from the first Write()
 // call and verify that the HttpTransaction fails with that error.
 static void CheckErrorIsPassedBack(int error, bool async) {
+  net::HttpRequestInfo request_info;
+  request_info.url = GURL("https://www.example.com/");
+  request_info.method = "GET";
+  request_info.load_flags = net::LOAD_NORMAL;
+
   SessionDependencies session_deps;
 
   SSLSocketDataProvider ssl_data(async, OK);
@@ -8132,11 +8215,6 @@
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
   scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
 
-  net::HttpRequestInfo request_info;
-  request_info.url = GURL("https://www.example.com/");
-  request_info.method = "GET";
-  request_info.load_flags = net::LOAD_NORMAL;
-
   TestCompletionCallback callback;
   int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
   if (rv == net::ERR_IO_PENDING)
@@ -8159,6 +8237,11 @@
 
 // Test that the transaction is restarted in the event of an NPN misprediction.
 TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
+  net::HttpRequestInfo request_info;
+  request_info.url = GURL("https://www.example.com/");
+  request_info.method = "GET";
+  request_info.load_flags = net::LOAD_NORMAL;
+
   SessionDependencies session_deps;
 
   SSLSocketDataProvider ssl_data1(true /* async */, OK);
@@ -8190,11 +8273,6 @@
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
   scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
 
-  net::HttpRequestInfo request_info;
-  request_info.url = GURL("https://www.example.com/");
-  request_info.method = "GET";
-  request_info.load_flags = net::LOAD_NORMAL;
-
   TestCompletionCallback callback;
   int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
   if (rv == net::ERR_IO_PENDING)
@@ -8207,4 +8285,303 @@
   EXPECT_EQ("hello world", contents);
 }
 
+// Ensure that a client certificate is removed from the SSL client auth
+// cache when:
+//  1) No proxy is involved.
+//  2) TLS False Start is disabled.
+//  3) The initial TLS handshake requests a client certificate.
+//  4) The client supplies an invalid/unacceptable certificate.
+TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
+  net::HttpRequestInfo request_info;
+  request_info.url = GURL("https://www.example.com/");
+  request_info.method = "GET";
+  request_info.load_flags = net::LOAD_NORMAL;
+
+  SessionDependencies session_deps;
+
+  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
+  cert_request->host_and_port = "www.example.com:443";
+
+  // [ssl_]data1 contains the data for the first SSL handshake. When a
+  // CertificateRequest is received for the first time, the handshake will
+  // be aborted to allow the caller to provide a certificate.
+  SSLSocketDataProvider ssl_data1(true /* async */,
+                                  net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
+  ssl_data1.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
+  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data1);
+
+  // [ssl_]data2 contains the data for the second SSL handshake. When TLS
+  // False Start is not being used, the result of the SSL handshake will be
+  // returned as part of the SSLClientSocket::Connect() call. This test
+  // matches the result of a server sending a handshake_failure alert,
+  // rather than a Finished message, because it requires a client
+  // certificate and none was supplied.
+  SSLSocketDataProvider ssl_data2(true /* async */,
+                                  net::ERR_SSL_PROTOCOL_ERROR);
+  ssl_data2.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
+  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data2);
+
+  // [ssl_]data3 contains the data for the third SSL handshake. When a
+  // connection to a server fails during an SSL handshake,
+  // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
+  // connection was attempted with TLSv1. This is transparent to the caller
+  // of the HttpNetworkTransaction. Because this test failure is due to
+  // requiring a client certificate, this fallback handshake should also
+  // fail.
+  SSLSocketDataProvider ssl_data3(true /* async */,
+                                  net::ERR_SSL_PROTOCOL_ERROR);
+  ssl_data3.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
+  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data3);
+
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
+
+  // Begin the SSL handshake with the peer. This consumes ssl_data1.
+  TestCompletionCallback callback;
+  int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
+  ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+  // Complete the SSL handshake, which should abort due to requiring a
+  // client certificate.
+  rv = callback.WaitForResult();
+  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+
+  // Indicate that no certificate should be supplied. From the perspective
+  // of SSLClientCertCache, NULL is just as meaningful as a real
+  // certificate, so this is the same as supply a
+  // legitimate-but-unacceptable certificate.
+  rv = trans->RestartWithCertificate(NULL, &callback);
+  ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+  // Ensure the certificate was added to the client auth cache before
+  // allowing the connection to continue restarting.
+  scoped_refptr<X509Certificate> client_cert;
+  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+                                                       &client_cert));
+  ASSERT_EQ(NULL, client_cert.get());
+
+  // Restart the handshake. This will consume ssl_data2, which fails, and
+  // then consume ssl_data3, which should also fail. The result code is
+  // checked against what ssl_data3 should return.
+  rv = callback.WaitForResult();
+  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
+
+  // Ensure that the client certificate is removed from the cache on a
+  // handshake failure.
+  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+                                                        &client_cert));
+}
+
+// Ensure that a client certificate is removed from the SSL client auth
+// cache when:
+//  1) No proxy is involved.
+//  2) TLS False Start is enabled.
+//  3) The initial TLS handshake requests a client certificate.
+//  4) The client supplies an invalid/unacceptable certificate.
+TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
+  net::HttpRequestInfo request_info;
+  request_info.url = GURL("https://www.example.com/");
+  request_info.method = "GET";
+  request_info.load_flags = net::LOAD_NORMAL;
+
+  SessionDependencies session_deps;
+
+  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
+  cert_request->host_and_port = "www.example.com:443";
+
+  // When TLS False Start is used, SSLClientSocket::Connect() calls will
+  // return successfully after reading up to the peer's Certificate message.
+  // This is to allow the caller to call SSLClientSocket::Write(), which can
+  // enqueue application data to be sent in the same packet as the
+  // ChangeCipherSpec and Finished messages.
+  // The actual handshake will be finished when SSLClientSocket::Read() is
+  // called, which expects to process the peer's ChangeCipherSpec and
+  // Finished messages. If there was an error negotiating with the peer,
+  // such as due to the peer requiring a client certificate when none was
+  // supplied, the alert sent by the peer won't be processed until Read() is
+  // called.
+
+  // Like the non-False Start case, when a client certificate is requested by
+  // the peer, the handshake is aborted during the Connect() call.
+  // [ssl_]data1 represents the initial SSL handshake with the peer.
+  SSLSocketDataProvider ssl_data1(true /* async */,
+                                  net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
+  ssl_data1.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
+  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data1);
+
+  // When a client certificate is supplied, Connect() will not be aborted
+  // when the peer requests the certificate. Instead, the handshake will
+  // artificially succeed, allowing the caller to write the HTTP request to
+  // the socket. The handshake messages are not processed until Read() is
+  // called, which then detects that the handshake was aborted, due to the
+  // peer sending a handshake_failure because it requires a client
+  // certificate.
+  SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
+  ssl_data2.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
+  net::MockRead data2_reads[] = {
+    net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
+  };
+  net::StaticSocketDataProvider data2(
+      data2_reads, arraysize(data2_reads), NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data2);
+
+  // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
+  // the data for the SSL handshake once the TLSv1 connection falls back to
+  // SSLv3. It has the same behaviour as [ssl_]data2.
+  SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
+  ssl_data3.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
+  net::StaticSocketDataProvider data3(
+      data2_reads, arraysize(data2_reads), NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data3);
+
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
+
+  // Begin the initial SSL handshake.
+  TestCompletionCallback callback;
+  int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
+  ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+  // Complete the SSL handshake, which should abort due to requiring a
+  // client certificate.
+  rv = callback.WaitForResult();
+  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+
+  // Indicate that no certificate should be supplied. From the perspective
+  // of SSLClientCertCache, NULL is just as meaningful as a real
+  // certificate, so this is the same as supply a
+  // legitimate-but-unacceptable certificate.
+  rv = trans->RestartWithCertificate(NULL, &callback);
+  ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+  // Ensure the certificate was added to the client auth cache before
+  // allowing the connection to continue restarting.
+  scoped_refptr<X509Certificate> client_cert;
+  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+                                                       &client_cert));
+  ASSERT_EQ(NULL, client_cert.get());
+
+
+  // Restart the handshake. This will consume ssl_data2, which fails, and
+  // then consume ssl_data3, which should also fail. The result code is
+  // checked against what ssl_data3 should return.
+  rv = callback.WaitForResult();
+  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
+
+  // Ensure that the client certificate is removed from the cache on a
+  // handshake failure.
+  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+                                                        &client_cert));
+}
+
+// Ensure that a client certificate is removed from the SSL client auth
+// cache when:
+//  1) An HTTPS proxy is involved.
+//  3) The HTTPS proxy requests a client certificate.
+//  4) The client supplies an invalid/unacceptable certificate for the
+//     proxy.
+// The test is repeated twice, first for connecting to an HTTPS endpoint,
+// then for connecting to an HTTP endpoint.
+TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
+  SessionDependencies session_deps(
+      ProxyService::CreateFixed("https://proxy:70"));
+  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+  session_deps.net_log = log.bound().net_log();
+
+  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
+  cert_request->host_and_port = "proxy:70";
+
+  // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
+  // [ssl_]data[1-3]. Rather than represending the endpoint
+  // (www.example.com:443), they represent failures with the HTTPS proxy
+  // (proxy:70).
+  SSLSocketDataProvider ssl_data1(true /* async */,
+                                  net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
+  ssl_data1.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
+  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data1);
+
+  SSLSocketDataProvider ssl_data2(true /* async */,
+                                  net::ERR_SSL_PROTOCOL_ERROR);
+  ssl_data2.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
+  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data2);
+
+  SSLSocketDataProvider ssl_data3(true /* async */,
+                                  net::ERR_SSL_PROTOCOL_ERROR);
+  ssl_data3.cert_request_info = cert_request.get();
+  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
+  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data3);
+
+  net::HttpRequestInfo requests[2];
+  requests[0].url = GURL("https://www.example.com/");
+  requests[0].method = "GET";
+  requests[0].load_flags = net::LOAD_NORMAL;
+
+  requests[1].url = GURL("http://www.example.com/");
+  requests[1].method = "GET";
+  requests[1].load_flags = net::LOAD_NORMAL;
+
+  for (size_t i = 0; i < arraysize(requests); ++i) {
+    session_deps.socket_factory.ResetNextMockIndexes();
+    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+    scoped_ptr<HttpNetworkTransaction> trans(
+        new HttpNetworkTransaction(session));
+
+    // Begin the SSL handshake with the proxy.
+    TestCompletionCallback callback;
+    int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
+    ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+    // Complete the SSL handshake, which should abort due to requiring a
+    // client certificate.
+    rv = callback.WaitForResult();
+    ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+
+    // Indicate that no certificate should be supplied. From the perspective
+    // of SSLClientCertCache, NULL is just as meaningful as a real
+    // certificate, so this is the same as supply a
+    // legitimate-but-unacceptable certificate.
+    rv = trans->RestartWithCertificate(NULL, &callback);
+    ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+    // Ensure the certificate was added to the client auth cache before
+    // allowing the connection to continue restarting.
+    scoped_refptr<X509Certificate> client_cert;
+    ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
+                                                         &client_cert));
+    ASSERT_EQ(NULL, client_cert.get());
+    // Ensure the certificate was NOT cached for the endpoint. This only
+    // applies to HTTPS requests, but is fine to check for HTTP requests.
+    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+                                                          &client_cert));
+
+    // Restart the handshake. This will consume ssl_data2, which fails, and
+    // then consume ssl_data3, which should also fail. The result code is
+    // checked against what ssl_data3 should return.
+    rv = callback.WaitForResult();
+    ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
+
+    // Now that the new handshake has failed, ensure that the client
+    // certificate was removed from the client auth cache.
+    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
+                                                          &client_cert));
+    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
+                                                          &client_cert));
+  }
+}
+
 }  // namespace net
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index ce108b1..4932da0 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -62,6 +62,24 @@
   Disconnect();
 }
 
+int HttpProxyClientSocket::RestartWithAuth(CompletionCallback* callback) {
+  DCHECK_EQ(STATE_NONE, next_state_);
+  DCHECK(!user_callback_);
+
+  int rv = PrepareForAuthRestart();
+  if (rv != OK)
+    return rv;
+
+  rv = DoLoop(OK);
+  if (rv == ERR_IO_PENDING)
+    user_callback_ = callback;
+  return rv;
+}
+
+const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const {
+  return response_.headers ? &response_ : NULL;
+}
+
 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() {
   return new HttpBasicStream(transport_.release(),
                              http_stream_parser_.release(), false);
@@ -99,67 +117,6 @@
   return rv;
 }
 
-int HttpProxyClientSocket::RestartWithAuth(CompletionCallback* callback) {
-  DCHECK_EQ(STATE_NONE, next_state_);
-  DCHECK(!user_callback_);
-
-  int rv = PrepareForAuthRestart();
-  if (rv != OK)
-    return rv;
-
-  rv = DoLoop(OK);
-  if (rv == ERR_IO_PENDING)
-    user_callback_ = callback;
-  return rv;
-}
-
-int HttpProxyClientSocket::PrepareForAuthRestart() {
-  if (!response_.headers.get())
-    return ERR_CONNECTION_RESET;
-
-  bool keep_alive = false;
-  if (response_.headers->IsKeepAlive() &&
-      http_stream_parser_->CanFindEndOfResponse()) {
-    if (!http_stream_parser_->IsResponseBodyComplete()) {
-      next_state_ = STATE_DRAIN_BODY;
-      drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
-      return OK;
-    }
-    keep_alive = true;
-  }
-
-  // We don't need to drain the response body, so we act as if we had drained
-  // the response body.
-  return DidDrainBodyForAuthRestart(keep_alive);
-}
-
-int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
-  if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
-    next_state_ = STATE_GENERATE_AUTH_TOKEN;
-    transport_->set_is_reused(true);
-  } else {
-    // This assumes that the underlying transport socket is a TCP socket,
-    // since only TCP sockets are restartable.
-    next_state_ = STATE_TCP_RESTART;
-    transport_->socket()->Disconnect();
-  }
-
-  // Reset the other member variables.
-  drain_buf_ = NULL;
-  parser_buf_ = NULL;
-  http_stream_parser_.reset();
-  request_line_.clear();
-  request_headers_.Clear();
-  response_ = HttpResponseInfo();
-  return OK;
-}
-
-void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
-  LOG(WARNING) << "Blocked proxy response with status " << response_code
-               << " to CONNECT request for "
-               << GetHostAndPort(request_.url) << ".";
-}
-
 void HttpProxyClientSocket::Disconnect() {
   if (transport_.get())
     transport_->socket()->Disconnect();
@@ -255,6 +212,64 @@
   return transport_->socket()->GetPeerAddress(address);
 }
 
+int HttpProxyClientSocket::PrepareForAuthRestart() {
+  if (!response_.headers.get())
+    return ERR_CONNECTION_RESET;
+
+  bool keep_alive = false;
+  if (response_.headers->IsKeepAlive() &&
+      http_stream_parser_->CanFindEndOfResponse()) {
+    if (!http_stream_parser_->IsResponseBodyComplete()) {
+      next_state_ = STATE_DRAIN_BODY;
+      drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
+      return OK;
+    }
+    keep_alive = true;
+  }
+
+  // We don't need to drain the response body, so we act as if we had drained
+  // the response body.
+  return DidDrainBodyForAuthRestart(keep_alive);
+}
+
+int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
+  if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
+    next_state_ = STATE_GENERATE_AUTH_TOKEN;
+    transport_->set_is_reused(true);
+  } else {
+    // This assumes that the underlying transport socket is a TCP socket,
+    // since only TCP sockets are restartable.
+    next_state_ = STATE_TCP_RESTART;
+    transport_->socket()->Disconnect();
+  }
+
+  // Reset the other member variables.
+  drain_buf_ = NULL;
+  parser_buf_ = NULL;
+  http_stream_parser_.reset();
+  request_line_.clear();
+  request_headers_.Clear();
+  response_ = HttpResponseInfo();
+  return OK;
+}
+
+int HttpProxyClientSocket::HandleAuthChallenge() {
+  DCHECK(response_.headers);
+
+  int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_);
+  response_.auth_challenge = auth_->auth_info();
+  if (rv == OK)
+    return ERR_PROXY_AUTH_REQUESTED;
+
+  return rv;
+}
+
+void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
+  LOG(WARNING) << "Blocked proxy response with status " << response_code
+               << " to CONNECT request for "
+               << GetHostAndPort(request_.url) << ".";
+}
+
 void HttpProxyClientSocket::DoCallback(int result) {
   DCHECK_NE(ERR_IO_PENDING, result);
   DCHECK(user_callback_);
@@ -291,25 +306,25 @@
         break;
       case STATE_SEND_REQUEST:
         DCHECK_EQ(OK, rv);
-        net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
-                            NULL);
+        net_log_.BeginEvent(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, NULL);
         rv = DoSendRequest();
         break;
       case STATE_SEND_REQUEST_COMPLETE:
         rv = DoSendRequestComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
-                          NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
         break;
       case STATE_READ_HEADERS:
         DCHECK_EQ(OK, rv);
-        net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
-                            NULL);
+        net_log_.BeginEvent(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, NULL);
         rv = DoReadHeaders();
         break;
       case STATE_READ_HEADERS_COMPLETE:
         rv = DoReadHeadersComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
-                          NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
         break;
       case STATE_DRAIN_BODY:
         DCHECK_EQ(OK, rv);
@@ -479,15 +494,4 @@
   return result;
 }
 
-int HttpProxyClientSocket::HandleAuthChallenge() {
-  DCHECK(response_.headers);
-
-  int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_);
-  response_.auth_challenge = auth_->auth_info();
-  if (rv == OK)
-    return ERR_PROXY_AUTH_REQUESTED;
-
-  return rv;
-}
-
 }  // namespace net
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index ef53c2d..daede3c 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -56,12 +56,6 @@
   // RestartWithAuth.
   int RestartWithAuth(CompletionCallback* callback);
 
-  const HttpResponseInfo* GetConnectResponseInfo() const {
-    return response_.headers ? &response_ : NULL;
-  }
-
-  virtual HttpStream* CreateConnectResponseStream();
-
   const scoped_refptr<HttpAuthController>& auth_controller() {
     return auth_;
   }
@@ -70,14 +64,21 @@
     return using_spdy_;
   }
 
-  // ClientSocket methods:
+  // ProxyClientSocket methods:
+  virtual const HttpResponseInfo* GetConnectResponseInfo() const;
+  virtual HttpStream* CreateConnectResponseStream();
 
+<<<<<<< HEAD
   // Authenticates to the Http Proxy and then passes data freely.
   virtual int Connect(CompletionCallback* callback
 #ifdef ANDROID
                       , bool wait_for_connect
 #endif
                      );
+=======
+  // ClientSocket methods:
+  virtual int Connect(CompletionCallback* callback);
+>>>>>>> chromium.org at r11.0.672.0
   virtual void Disconnect();
   virtual bool IsConnected() const;
   virtual bool IsConnectedAndIdle() const;
@@ -90,10 +91,8 @@
   // Socket methods:
   virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
   virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
-
   virtual bool SetReceiveBufferSize(int32 size);
   virtual bool SetSendBufferSize(int32 size);
-
   virtual int GetPeerAddress(AddressList* address) const;
 
  private:
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index d297542..fd875ca 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -111,12 +111,11 @@
   }
 }
 
-int HttpProxyConnectJob::ConnectInternal() {
-  if (params_->tcp_params())
-    next_state_ = STATE_TCP_CONNECT;
-  else
-    next_state_ = STATE_SSL_CONNECT;
-  return DoLoop(OK);
+void HttpProxyConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
+  if (error_response_info_.cert_request_info) {
+    handle->set_ssl_error_response_info(error_response_info_);
+    handle->set_is_ssl_error(true);
+  }
 }
 
 void HttpProxyConnectJob::OnIOComplete(int result) {
@@ -254,11 +253,33 @@
   return result;
 }
 
-void HttpProxyConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
-  if (error_response_info_.cert_request_info) {
-    handle->set_ssl_error_response_info(error_response_info_);
-    handle->set_is_ssl_error(true);
+int HttpProxyConnectJob::DoHttpProxyConnect() {
+  next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE;
+  const HostResolver::RequestInfo& tcp_destination = params_->destination();
+  const HostPortPair& proxy_server = tcp_destination.host_port_pair();
+
+  // Add a HttpProxy connection on top of the tcp socket.
+  transport_socket_.reset(
+      new HttpProxyClientSocket(transport_socket_handle_.release(),
+                                params_->request_url(),
+                                params_->user_agent(),
+                                params_->endpoint(),
+                                proxy_server,
+                                params_->http_auth_cache(),
+                                params_->http_auth_handler_factory(),
+                                params_->tunnel(),
+                                using_spdy_,
+                                params_->ssl_params() != NULL));
+  return transport_socket_->Connect(&callback_);
+}
+
+int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
+  if (result == OK || result == ERR_PROXY_AUTH_REQUESTED ||
+      result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
+      set_socket(transport_socket_.release());
   }
+
+  return result;
 }
 
 int HttpProxyConnectJob::DoSpdyProxyCreateStream() {
@@ -316,6 +337,7 @@
                                    );
 }
 
+<<<<<<< HEAD
 #ifdef ANDROID
 // TODO(kristianm): Find out if Connect should block
 #endif
@@ -350,6 +372,14 @@
   }
 
   return result;
+=======
+int HttpProxyConnectJob::ConnectInternal() {
+  if (params_->tcp_params())
+    next_state_ = STATE_TCP_CONNECT;
+  else
+    next_state_ = STATE_SSL_CONNECT;
+  return DoLoop(OK);
+>>>>>>> chromium.org at r11.0.672.0
 }
 
 HttpProxyClientSocketPool::
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h
index 39a8896..70d4bba 100644
--- a/net/http/http_proxy_client_socket_pool.h
+++ b/net/http/http_proxy_client_socket_pool.h
@@ -129,15 +129,6 @@
     STATE_NONE,
   };
 
-  // Begins the tcp connection and the optional Http proxy tunnel.  If the
-  // request is not immediately servicable (likely), the request will return
-  // ERR_IO_PENDING. An OK return from this function or the callback means
-  // that the connection is established; ERR_PROXY_AUTH_REQUESTED means
-  // that the tunnel needs authentication credentials, the socket will be
-  // returned in this case, and must be release back to the pool; or
-  // a standard net error code will be returned.
-  virtual int ConnectInternal();
-
   void OnIOComplete(int result);
 
   // Runs the state transition loop.
@@ -156,6 +147,15 @@
   int DoSpdyProxyCreateStream();
   int DoSpdyProxyCreateStreamComplete(int result);
 
+  // Begins the tcp connection and the optional Http proxy tunnel.  If the
+  // request is not immediately servicable (likely), the request will return
+  // ERR_IO_PENDING. An OK return from this function or the callback means
+  // that the connection is established; ERR_PROXY_AUTH_REQUESTED means
+  // that the tunnel needs authentication credentials, the socket will be
+  // returned in this case, and must be release back to the pool; or
+  // a standard net error code will be returned.
+  virtual int ConnectInternal();
+
   scoped_refptr<HttpProxySocketParams> params_;
   TCPClientSocketPool* const tcp_pool_;
   SSLClientSocketPool* const ssl_pool_;
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 8c6d545..359a058 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -20,7 +20,6 @@
 #include "net/socket/client_socket_pool_histograms.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/spdy_protocol.h"
-#include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -60,13 +59,12 @@
             &tcp_histograms_,
             &socket_factory_),
         ssl_histograms_("MockSSL"),
+        proxy_service_(ProxyService::CreateDirect()),
         ssl_config_service_(new SSLConfigServiceDefaults),
-        host_resolver_(new MockHostResolver),
-        cert_verifier_(new CertVerifier),
         ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
                          &ssl_histograms_,
-                         host_resolver_.get(),
-                         cert_verifier_.get(),
+                         &host_resolver_,
+                         &cert_verifier_,
                          NULL /* dnsrr_resolver */,
                          NULL /* dns_cert_checker */,
                          NULL /* ssl_host_info_factory */,
@@ -77,19 +75,8 @@
                          ssl_config_service_.get(),
                          BoundNetLog().net_log()),
         http_auth_handler_factory_(
-            HttpAuthHandlerFactory::CreateDefault(host_resolver_.get())),
-        session_(new HttpNetworkSession(host_resolver_.get(),
-                                        cert_verifier_.get(),
-                                        NULL /* dnsrr_resolver */,
-                                        NULL /* dns_cert_checker */,
-                                        NULL /* ssl_host_info_factory */,
-                                        ProxyService::CreateDirect(),
-                                        &socket_factory_,
-                                        new SSLConfigServiceDefaults,
-                                        new SpdySessionPool(NULL),
-                                        http_auth_handler_factory_.get(),
-                                        NULL,
-                                        NULL)),
+            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
+        session_(CreateNetworkSession()),
         http_proxy_histograms_("HttpProxyUnitTest"),
         ssl_data_(NULL),
         data_(NULL),
@@ -107,8 +94,13 @@
   void AddAuthToCache() {
     const string16 kFoo(ASCIIToUTF16("foo"));
     const string16 kBar(ASCIIToUTF16("bar"));
-    session_->auth_cache()->Add(GURL("http://proxy/"), "MyRealm1", "Basic",
-                                "Basic realm=MyRealm1", kFoo, kBar, "/");
+    session_->auth_cache()->Add(GURL("http://proxy/"),
+                                "MyRealm1",
+                                HttpAuth::AUTH_SCHEME_BASIC,
+                                "Basic realm=MyRealm1",
+                                kFoo,
+                                kBar,
+                                "/");
   }
 
   scoped_refptr<TCPSocketParams> GetTcpParams() {
@@ -184,6 +176,17 @@
     ssl_data_->was_npn_negotiated = true;
   }
 
+  HttpNetworkSession* CreateNetworkSession() {
+    HttpNetworkSession::Params params;
+    params.host_resolver = &host_resolver_;
+    params.cert_verifier = &cert_verifier_;
+    params.proxy_service = proxy_service_;
+    params.client_socket_factory = &socket_factory_;
+    params.ssl_config_service = ssl_config_service_;
+    params.http_auth_handler_factory = http_auth_handler_factory_.get();
+    return new HttpNetworkSession(params);
+  }
+
  private:
   SSLConfig ssl_config_;
 
@@ -193,13 +196,14 @@
   DeterministicMockClientSocketFactory socket_factory_;
   MockTCPClientSocketPool tcp_socket_pool_;
   ClientSocketPoolHistograms ssl_histograms_;
-  scoped_refptr<SSLConfigService> ssl_config_service_;
-  scoped_ptr<HostResolver> host_resolver_;
-  scoped_ptr<CertVerifier> cert_verifier_;
+  MockHostResolver host_resolver_;
+  CertVerifier cert_verifier_;
+  const scoped_refptr<ProxyService> proxy_service_;
+  const scoped_refptr<SSLConfigService> ssl_config_service_;
   SSLClientSocketPool ssl_socket_pool_;
 
-  scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
-  scoped_refptr<HttpNetworkSession> session_;
+  const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
+  const scoped_refptr<HttpNetworkSession> session_;
   ClientSocketPoolHistograms http_proxy_histograms_;
 
  protected:
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc
index fc2ebcd..9d523c1 100644
--- a/net/http/http_request_headers.cc
+++ b/net/http/http_request_headers.cc
@@ -30,6 +30,7 @@
 const char HttpRequestHeaders::kRange[] = "Range";
 const char HttpRequestHeaders::kReferer[] = "Referer";
 const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
+const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding";
 
 HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() {
 }
@@ -85,6 +86,13 @@
     headers_.push_back(HeaderKeyValuePair(key.as_string(), value.as_string()));
 }
 
+void HttpRequestHeaders::SetHeaderIfMissing(const base::StringPiece& key,
+                                            const base::StringPiece& value) {
+  HeaderVector::iterator it = FindHeader(key);
+  if (it == headers_.end())
+    headers_.push_back(HeaderKeyValuePair(key.as_string(), value.as_string()));
+}
+
 void HttpRequestHeaders::RemoveHeader(const base::StringPiece& key) {
   HeaderVector::iterator it = FindHeader(key);
   if (it != headers_.end())
diff --git a/net/http/http_request_headers.h b/net/http/http_request_headers.h
index 734194a..ef4b60d 100644
--- a/net/http/http_request_headers.h
+++ b/net/http/http_request_headers.h
@@ -73,6 +73,7 @@
   static const char kRange[];
   static const char kReferer[];
   static const char kUserAgent[];
+  static const char kTransferEncoding[];
 
   HttpRequestHeaders();
   ~HttpRequestHeaders();
@@ -95,6 +96,12 @@
   // in the vector remains the same.  When comparing |key|, case is ignored.
   void SetHeader(const base::StringPiece& key, const base::StringPiece& value);
 
+  // Sets the header value pair for |key| and |value|, if |key| does not exist.
+  // If |key| already exists, the call is a no-op.
+  // When comparing |key|, case is ignored.
+  void SetHeaderIfMissing(const base::StringPiece& key,
+                          const base::StringPiece& value);
+
   // Removes the first header that matches (case insensitive) |key|.
   void RemoveHeader(const base::StringPiece& key);
 
diff --git a/net/http/http_request_headers_unittest.cc b/net/http/http_request_headers_unittest.cc
index f3abfbe..384ceeb 100644
--- a/net/http/http_request_headers_unittest.cc
+++ b/net/http/http_request_headers_unittest.cc
@@ -67,6 +67,14 @@
   EXPECT_EQ("Foo: Bar\r\nBar:\r\n\r\n", headers.ToString());
 }
 
+TEST(HttpRequestHeaders, SetHeaderIfMissing) {
+  HttpRequestHeaders headers;
+  headers.SetHeaderIfMissing("Foo", "Bar");
+  EXPECT_EQ("Foo: Bar\r\n\r\n", headers.ToString());
+  headers.SetHeaderIfMissing("Foo", "Baz");
+  EXPECT_EQ("Foo: Bar\r\n\r\n", headers.ToString());
+}
+
 TEST(HttpRequestHeaders, RemoveHeader) {
   HttpRequestHeaders headers;
   headers.SetHeader("Foo", "bar");
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index 76304f8..5745865 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -16,7 +16,6 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_stream.h"
 #include "net/proxy/proxy_service.h"
-#include "net/spdy/spdy_session_pool.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
@@ -174,23 +173,23 @@
 class HttpResponseBodyDrainerTest : public testing::Test {
  protected:
   HttpResponseBodyDrainerTest()
-      : session_(new HttpNetworkSession(
-          NULL /* host_resolver */,
-          NULL /* dnsrr_resolver */,
-          NULL /* dns_cert_checker */,
-          NULL,
-          NULL /* ssl_host_info_factory */,
-          ProxyService::CreateDirect(),
-          NULL,
-          new SSLConfigServiceDefaults,
-          new SpdySessionPool(NULL),
-          NULL,
-          NULL,
-          NULL)),
+      : proxy_service_(ProxyService::CreateDirect()),
+        ssl_config_service_(new SSLConfigServiceDefaults),
+        session_(CreateNetworkSession()),
         mock_stream_(new MockHttpStream(&result_waiter_)),
         drainer_(new HttpResponseBodyDrainer(mock_stream_)) {}
+
   ~HttpResponseBodyDrainerTest() {}
 
+  HttpNetworkSession* CreateNetworkSession() const {
+    HttpNetworkSession::Params params;
+    params.proxy_service = proxy_service_;
+    params.ssl_config_service = ssl_config_service_;
+    return new HttpNetworkSession(params);
+  }
+
+  scoped_refptr<ProxyService> proxy_service_;
+  scoped_refptr<SSLConfigService> ssl_config_service_;
   const scoped_refptr<HttpNetworkSession> session_;
   CloseResultWaiter result_waiter_;
   MockHttpStream* const mock_stream_;  // Owned by |drainer_|.
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index c2d098c..5bf2beb 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -12,6 +12,7 @@
 #include <algorithm>
 
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/pickle.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
@@ -85,13 +86,69 @@
   return true;
 }
 
+// Functions for histogram initialization.  The code 0 is put in the
+// response map to track response codes that are invalid.
+// TODO(gavinp): Greatly prune the collected codes once we learn which
+// ones are not sent in practice, to reduce upload size & memory use.
+
+enum {
+  HISTOGRAM_MIN_HTTP_RESPONSE_CODE = 100,
+  HISTOGRAM_MAX_HTTP_RESPONSE_CODE = 599,
+};
+
+std::vector<int> GetAllHttpResponseCodes() {
+  std::vector<int> codes;
+  codes.reserve(
+      HISTOGRAM_MAX_HTTP_RESPONSE_CODE - HISTOGRAM_MIN_HTTP_RESPONSE_CODE + 2);
+  codes.push_back(0);
+  for (int i = HISTOGRAM_MIN_HTTP_RESPONSE_CODE;
+       i <= HISTOGRAM_MAX_HTTP_RESPONSE_CODE; ++i)
+    codes.push_back(i);
+  return codes;
+}
+
+int MapHttpResponseCode(int code) {
+  if (HISTOGRAM_MIN_HTTP_RESPONSE_CODE <= code &&
+      code <= HISTOGRAM_MAX_HTTP_RESPONSE_CODE)
+    return code;
+  return 0;
+}
+
 }  // namespace
 
+struct HttpResponseHeaders::ParsedHeader {
+  // A header "continuation" contains only a subsequent value for the
+  // preceding header.  (Header values are comma separated.)
+  bool is_continuation() const { return name_begin == name_end; }
+
+  std::string::const_iterator name_begin;
+  std::string::const_iterator name_end;
+  std::string::const_iterator value_begin;
+  std::string::const_iterator value_end;
+};
+
 //-----------------------------------------------------------------------------
 
 HttpResponseHeaders::HttpResponseHeaders(const std::string& raw_input)
     : response_code_(-1) {
   Parse(raw_input);
+
+  // The most important thing to do with this histogram is find out
+  // the existence of unusual HTTP response codes.  As it happens
+  // right now, there aren't double-constructions of response headers
+  // using this constructor, so our counts should also be accurate,
+  // without instantiating the histogram in two places.  It is also
+  // important that this histogram not collect data in the other
+  // constructor, which rebuilds an histogram from a pickle, since
+  // that would actually create a double call between the original
+  // HttpResponseHeader that was serialized, and initialization of the
+  // new object from that pickle.
+  UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.HttpResponseCode",
+                                   MapHttpResponseCode(response_code_),
+                                   // Note the third argument is only
+                                   // evaluated once, see macro
+                                   // definition for details.
+                                   GetAllHttpResponseCodes());
 }
 
 HttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle, void** iter)
@@ -359,30 +416,6 @@
   output->push_back('\n');
 }
 
-void HttpResponseHeaders::GetRawHeaders(std::string* output) const {
-  if (!output)
-    return;
-  output->erase();
-  const char* headers_string = raw_headers().c_str();
-  size_t headers_length = raw_headers().length();
-  if (!headers_string)
-    return;
-  // The headers_string is a NULL-terminated status line, followed by NULL-
-  // terminated headers.
-  std::string raw_string = headers_string;
-  size_t current_length = strlen(headers_string) + 1;
-  while (headers_length > current_length) {
-    // Move to the next header, and append it.
-    headers_string += current_length;
-    headers_length -= current_length;
-    raw_string += "\n";
-    raw_string += headers_string;
-    // Get the next header location.
-    current_length = strlen(headers_string) + 1;
-  }
-  *output = raw_string;
-}
-
 bool HttpResponseHeaders::GetNormalizedHeader(const std::string& name,
                                               std::string* value) const {
   // If you hit this assertion, please use EnumerateHeader instead!
@@ -494,7 +527,7 @@
   return FindHeader(0, name) != std::string::npos;
 }
 
-HttpResponseHeaders::HttpResponseHeaders() {
+HttpResponseHeaders::HttpResponseHeaders() : response_code_(-1) {
 }
 
 HttpResponseHeaders::~HttpResponseHeaders() {
diff --git a/net/http/http_response_headers.h b/net/http/http_response_headers.h
index 2b556b3..3c2eae0 100644
--- a/net/http/http_response_headers.h
+++ b/net/http/http_response_headers.h
@@ -100,9 +100,6 @@
   //
   void GetNormalizedHeaders(std::string* output) const;
 
-  // Gets the raw stored headers, in human-readable form.
-  void GetRawHeaders(std::string* output) const;
-
   // Fetch the "normalized" value of a single header, where all values for the
   // header name are separated by commas.  See the GetNormalizedHeaders for
   // format details.  Returns false if this header wasn't found.
@@ -254,16 +251,7 @@
   typedef base::hash_set<std::string> HeaderSet;
 
   // The members of this structure point into raw_headers_.
-  struct ParsedHeader {
-    std::string::const_iterator name_begin;
-    std::string::const_iterator name_end;
-    std::string::const_iterator value_begin;
-    std::string::const_iterator value_end;
-
-    // A header "continuation" contains only a subsequent value for the
-    // preceding header.  (Header values are comma separated.)
-    bool is_continuation() const { return name_begin == name_end; }
-  };
+  struct ParsedHeader;
   typedef std::vector<ParsedHeader> HeaderList;
 
   HttpResponseHeaders();
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index b575f48..4673d58 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -32,14 +32,6 @@
 // static
 bool HttpStreamFactory::ignore_certificate_errors_ = false;
 
-// static
-void HttpStreamFactory::SetHostMappingRules(const std::string& rules) {
-  HostMappingRules* host_mapping_rules = new HostMappingRules();
-  host_mapping_rules->SetRulesFromString(rules);
-  delete host_mapping_rules_;
-  host_mapping_rules_ = host_mapping_rules;
-}
-
 HttpStreamFactory::HttpStreamFactory() {
 }
 
@@ -53,6 +45,14 @@
   }
 }
 
+// static
+void HttpStreamFactory::SetHostMappingRules(const std::string& rules) {
+  HostMappingRules* host_mapping_rules = new HostMappingRules();
+  host_mapping_rules->SetRulesFromString(rules);
+  delete host_mapping_rules_;
+  host_mapping_rules_ = host_mapping_rules;
+}
+
 StreamRequest* HttpStreamFactory::RequestStream(
     const HttpRequestInfo* request_info,
     SSLConfig* ssl_config,
diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h
index 3bb6d2f..97bd79c 100644
--- a/net/http/http_stream_factory.h
+++ b/net/http/http_stream_factory.h
@@ -34,35 +34,6 @@
   HttpStreamFactory();
   virtual ~HttpStreamFactory();
 
-  // StreamFactory Interface
-  virtual StreamRequest* RequestStream(const HttpRequestInfo* info,
-                                       SSLConfig* ssl_config,
-                                       ProxyInfo* proxy_info,
-                                       HttpNetworkSession* session,
-                                       StreamRequest::Delegate* delegate,
-                                       const BoundNetLog& net_log);
-
-  virtual int PreconnectStreams(int num_streams,
-                                const HttpRequestInfo* info,
-                                SSLConfig* ssl_config,
-                                ProxyInfo* proxy_info,
-                                HttpNetworkSession* session,
-                                const BoundNetLog& net_log,
-                                CompletionCallback* callback);
-
-  virtual void AddTLSIntolerantServer(const GURL& url);
-  virtual bool IsTLSIntolerantServer(const GURL& url);
-
-  virtual void ProcessAlternateProtocol(
-      HttpAlternateProtocols* alternate_protocols,
-      const std::string& alternate_protocol_str,
-      const HostPortPair& http_host_port_pair);
-
-  virtual GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
-
-  // HttpStreamRequest::PreconnectDelegate API
-  virtual void OnPreconnectsComplete(HttpStreamRequest* request, int result);
-
   // Static settings
 
   // Turns spdy on or off.
@@ -122,6 +93,31 @@
 
   static void SetHostMappingRules(const std::string& rules);
 
+  // StreamFactory Interface
+  virtual StreamRequest* RequestStream(const HttpRequestInfo* info,
+                                       SSLConfig* ssl_config,
+                                       ProxyInfo* proxy_info,
+                                       HttpNetworkSession* session,
+                                       StreamRequest::Delegate* delegate,
+                                       const BoundNetLog& net_log);
+  virtual int PreconnectStreams(int num_streams,
+                                const HttpRequestInfo* info,
+                                SSLConfig* ssl_config,
+                                ProxyInfo* proxy_info,
+                                HttpNetworkSession* session,
+                                const BoundNetLog& net_log,
+                                CompletionCallback* callback);
+  virtual void AddTLSIntolerantServer(const GURL& url);
+  virtual bool IsTLSIntolerantServer(const GURL& url);
+  virtual void ProcessAlternateProtocol(
+      HttpAlternateProtocols* alternate_protocols,
+      const std::string& alternate_protocol_str,
+      const HostPortPair& http_host_port_pair);
+  virtual GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
+
+  // HttpStreamRequest::PreconnectDelegate API
+  virtual void OnPreconnectsComplete(HttpStreamRequest* request, int result);
+
  private:
   typedef std::map<HttpStreamRequest*, CompletionCallback*> RequestCallbackMap;
   RequestCallbackMap request_callback_map_;
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 646f79c..617d885 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -17,6 +17,7 @@
 #include "net/http/http_network_session_peer.h"
 #include "net/http/http_request_info.h"
 #include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_session.h"
 #include "net/spdy/spdy_session_pool.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -45,18 +46,16 @@
 };
 
 HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
-  return new HttpNetworkSession(session_deps->host_resolver.get(),
-                                session_deps->cert_verifier.get(),
-                                NULL /* dnsrr_resolver */,
-                                NULL /* dns_cert_checker */,
-                                NULL /* ssl_host_info_factory */,
-                                session_deps->proxy_service,
-                                &session_deps->socket_factory,
-                                session_deps->ssl_config_service,
-                                new SpdySessionPool(NULL),
-                                session_deps->http_auth_handler_factory.get(),
-                                NULL,
-                                session_deps->net_log);
+  HttpNetworkSession::Params params;
+  params.host_resolver = session_deps->host_resolver.get();
+  params.cert_verifier = session_deps->cert_verifier.get();
+  params.proxy_service = session_deps->proxy_service;
+  params.ssl_config_service = session_deps->ssl_config_service;
+  params.client_socket_factory = &session_deps->socket_factory;
+  params.http_auth_handler_factory =
+      session_deps->http_auth_handler_factory.get();
+  params.net_log = session_deps->net_log;
+  return new HttpNetworkSession(params);
 }
 
 struct TestCase {
@@ -96,7 +95,8 @@
 template<typename ParentPool>
 class CapturePreconnectsSocketPool : public ParentPool {
  public:
-  explicit CapturePreconnectsSocketPool(HttpNetworkSession* session);
+  CapturePreconnectsSocketPool(HostResolver* host_resolver,
+                               CertVerifier* cert_verifier);
 
   int last_num_streams() const {
     return last_num_streams_;
@@ -124,7 +124,8 @@
     ADD_FAILURE();
   }
   virtual void ReleaseSocket(const std::string& group_name,
-                             ClientSocket* socket) {
+                             ClientSocket* socket,
+                             int id) {
     ADD_FAILURE();
   }
   virtual void CloseIdleSockets() {
@@ -162,21 +163,22 @@
 
 template<typename ParentPool>
 CapturePreconnectsSocketPool<ParentPool>::CapturePreconnectsSocketPool(
-    HttpNetworkSession* session)
-    : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
+    HostResolver* host_resolver, CertVerifier* /* cert_verifier */)
+    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL),
+      last_num_streams_(-1) {}
 
 template<>
 CapturePreconnectsHttpProxySocketPool::CapturePreconnectsSocketPool(
-    HttpNetworkSession* session)
-    : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
-                                NULL, NULL) {}
+    HostResolver* host_resolver, CertVerifier* /* cert_verifier */)
+    : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL),
+      last_num_streams_(-1) {}
 
 template<>
 CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool(
-    HttpNetworkSession* session)
-    : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
-                          session->cert_verifier(), NULL, NULL,
-                          NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
+    HostResolver* host_resolver, CertVerifier* cert_verifier)
+    : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
+                          NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+      last_num_streams_(-1) {}
 
 TEST(HttpStreamFactoryTest, PreconnectDirect) {
   for (size_t i = 0; i < arraysize(kTests); ++i) {
@@ -184,10 +186,14 @@
     scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
     HttpNetworkSessionPeer peer(session);
     CapturePreconnectsTCPSocketPool* tcp_conn_pool =
-        new CapturePreconnectsTCPSocketPool(session);
+        new CapturePreconnectsTCPSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
     peer.SetTCPSocketPool(tcp_conn_pool);
     CapturePreconnectsSSLSocketPool* ssl_conn_pool =
-        new CapturePreconnectsSSLSocketPool(session.get());
+        new CapturePreconnectsSSLSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
     peer.SetSSLSocketPool(ssl_conn_pool);
     EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
     if (kTests[i].ssl)
@@ -204,10 +210,14 @@
     HttpNetworkSessionPeer peer(session);
     HostPortPair proxy_host("http_proxy", 80);
     CapturePreconnectsHttpProxySocketPool* http_proxy_pool =
-        new CapturePreconnectsHttpProxySocketPool(session);
+        new CapturePreconnectsHttpProxySocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
     peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
     CapturePreconnectsSSLSocketPool* ssl_conn_pool =
-        new CapturePreconnectsSSLSocketPool(session);
+        new CapturePreconnectsSSLSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
     peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
     EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
     if (kTests[i].ssl)
@@ -225,10 +235,14 @@
     HttpNetworkSessionPeer peer(session);
     HostPortPair proxy_host("socks_proxy", 1080);
     CapturePreconnectsSOCKSSocketPool* socks_proxy_pool =
-        new CapturePreconnectsSOCKSSocketPool(session);
+        new CapturePreconnectsSOCKSSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
     peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_proxy_pool);
     CapturePreconnectsSSLSocketPool* ssl_conn_pool =
-        new CapturePreconnectsSSLSocketPool(session);
+        new CapturePreconnectsSSLSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
     peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
     EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
     if (kTests[i].ssl)
@@ -238,6 +252,39 @@
   }
 }
 
+TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
+  for (size_t i = 0; i < arraysize(kTests); ++i) {
+    SessionDependencies session_deps(ProxyService::CreateDirect());
+    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+    HttpNetworkSessionPeer peer(session);
+
+    // Set an existing SpdySession in the pool.
+    HostPortPair host_port_pair("www.google.com", 443);
+    HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
+    scoped_refptr<SpdySession> spdy_session =
+        session->spdy_session_pool()->Get(
+            pair, session->mutable_spdy_settings(), BoundNetLog());
+
+    CapturePreconnectsTCPSocketPool* tcp_conn_pool =
+        new CapturePreconnectsTCPSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
+    peer.SetTCPSocketPool(tcp_conn_pool);
+    CapturePreconnectsSSLSocketPool* ssl_conn_pool =
+        new CapturePreconnectsSSLSocketPool(
+            session_deps.host_resolver.get(),
+            session_deps.cert_verifier.get());
+    peer.SetSSLSocketPool(ssl_conn_pool);
+    EXPECT_EQ(OK, PreconnectHelper(kTests[i], session));
+    // We shouldn't be preconnecting if we have an existing session, which is
+    // the case for https://www.google.com.
+    if (kTests[i].ssl)
+      EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
+    else
+      EXPECT_EQ(kTests[i].num_streams, tcp_conn_pool->last_num_streams());
+  }
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 2a3fb15..20ebd87 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -43,7 +43,10 @@
   DCHECK_EQ(0, read_buffer->offset());
 }
 
-HttpStreamParser::~HttpStreamParser() {}
+HttpStreamParser::~HttpStreamParser() {
+  if (request_body_ != NULL && request_body_->is_chunked())
+    request_body_->set_chunk_callback(NULL);
+}
 
 int HttpStreamParser::SendRequest(const std::string& request_line,
                                   const HttpRequestHeaders& headers,
@@ -67,6 +70,8 @@
   request_headers_ = new DrainableIOBuffer(headers_io_buf,
                                            headers_io_buf->size());
   request_body_.reset(request_body);
+  if (request_body_ != NULL && request_body_->is_chunked())
+    request_body_->set_chunk_callback(this);
 
   io_state_ = STATE_SENDING_HEADERS;
   int result = DoLoop(OK);
@@ -143,6 +148,16 @@
   }
 }
 
+void HttpStreamParser::OnChunkAvailable() {
+  // This method may get called while sending the headers or body, so check
+  // before processing the new data. If we were still initializing or sending
+  // headers, we will automatically start reading the chunks once we get into
+  // STATE_SENDING_BODY so nothing to do here.
+  DCHECK(io_state_ == STATE_SENDING_HEADERS || io_state_ == STATE_SENDING_BODY);
+  if (io_state_ == STATE_SENDING_BODY)
+    OnIOComplete(0);
+}
+
 int HttpStreamParser::DoLoop(int result) {
   bool can_do_more = true;
   do {
@@ -169,7 +184,8 @@
         break;
       case STATE_READ_HEADERS_COMPLETE:
         result = DoReadHeadersComplete(result);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result);
         break;
       case STATE_BODY_PENDING:
         DCHECK(result != ERR_IO_PENDING);
@@ -208,12 +224,16 @@
       // We'll record the count of uncoalesced packets IFF coalescing will help,
       // and otherwise we'll use an enum to tell why it won't help.
       enum COALESCE_POTENTIAL {
-        NO_ADVANTAGE = 0,   // Coalescing won't reduce packet count.
-        HEADER_ONLY = 1,    // There is only a header packet (can't coalesce).
-        COALESCE_POTENTIAL_MAX = 30 // Various cases of coalasced savings.
+        // Coalescing won't reduce packet count.
+        NO_ADVANTAGE = 0,
+        // There is only a header packet or we have a request body but the
+        // request body isn't available yet (can't coalesce).
+        HEADER_ONLY = 1,
+        // Various cases of coalasced savings.
+        COALESCE_POTENTIAL_MAX = 30
       };
       size_t coalesce = HEADER_ONLY;
-      if (request_body_ != NULL) {
+      if (request_body_ != NULL && !request_body_->is_chunked()) {
         const size_t kBytesPerPacket = 1430;
         uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) /
                               kBytesPerPacket;
@@ -236,7 +256,8 @@
     result = connection_->socket()->Write(request_headers_,
                                           bytes_remaining,
                                           &io_callback_);
-  } else if (request_body_ != NULL && request_body_->size()) {
+  } else if (request_body_ != NULL &&
+             (request_body_->is_chunked() || request_body_->size())) {
     io_state_ = STATE_SENDING_BODY;
     result = OK;
   } else {
@@ -246,13 +267,17 @@
 }
 
 int HttpStreamParser::DoSendBody(int result) {
-  if (result > 0)
-    request_body_->DidConsume(result);
+  request_body_->MarkConsumedAndFillBuffer(result);
 
   if (!request_body_->eof()) {
     int buf_len = static_cast<int>(request_body_->buf_len());
-    result = connection_->socket()->Write(request_body_->buf(), buf_len,
-                                          &io_callback_);
+    if (buf_len) {
+      result = connection_->socket()->Write(request_body_->buf(), buf_len,
+                                            &io_callback_);
+    } else {
+      // More POST data is to come hence wait for the callback.
+      result = ERR_IO_PENDING;
+    }
   } else {
     io_state_ = STATE_REQUEST_SENT;
   }
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h
index bbd551f..5f7e943 100644
--- a/net/http/http_stream_parser.h
+++ b/net/http/http_stream_parser.h
@@ -26,7 +26,7 @@
 class SSLCertRequestInfo;
 class SSLInfo;
 
-class HttpStreamParser {
+class HttpStreamParser  : public ChunkCallback {
  public:
   // Any data in |read_buffer| will be used before reading from the socket
   // and any data left over after parsing the stream will be put into
@@ -71,6 +71,9 @@
 
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
 
+  // ChunkCallback methods.
+  virtual void OnChunkAvailable();
+
  private:
   // FOO_COMPLETE states implement the second half of potentially asynchronous
   // operations and don't necessarily mean that FOO is complete.
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index 242f899..8794ea2 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -492,8 +492,11 @@
     // Check first if we have a spdy session for this group.  If so, then go
     // straight to using that.
     HostPortProxyPair pair(endpoint_, proxy_info()->proxy_server());
-    if (!preconnect_delegate_ &&
-        session_->spdy_session_pool()->HasSession(pair)) {
+    if (session_->spdy_session_pool()->HasSession(pair)) {
+      // If we're preconnecting, but we already have a SpdySession, we don't
+      // actually need to preconnect any sockets, so we're done.
+      if (preconnect_delegate_)
+        return OK;
       using_spdy_ = true;
       next_state_ = STATE_CREATE_STREAM;
       return OK;
@@ -769,7 +772,7 @@
       }
     }
     if (result < 0)
-      return HandleSSLHandshakeError(result);
+      return result;
   }
 
   next_state_ = STATE_CREATE_STREAM;
@@ -917,6 +920,18 @@
     ssl_config()->tls1_enabled = false;
   }
 
+  if (proxy_info()->is_https() && ssl_config()->send_client_cert) {
+    // When connecting through an HTTPS proxy, disable TLS False Start so
+    // that client authentication errors can be distinguished between those
+    // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
+    // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
+    // ERR_BAD_SSL_CLIENT_AUTH_CERT).
+    // TODO(rch): This assumes that the HTTPS proxy will only request a
+    // client certificate during the initial handshake.
+    // http://crbug.com/59292
+    ssl_config()->false_start_enabled = false;
+  }
+
   UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
                             static_cast<int>(ssl_config()->ssl3_fallback), 2);
 
@@ -1005,6 +1020,11 @@
     return error;
   }
 
+  if (proxy_info()->is_https() && ssl_config()->send_client_cert) {
+    session_->ssl_client_auth_cache()->Remove(
+        proxy_info()->proxy_server().host_port_pair().ToString());
+  }
+
   int rv = session_->proxy_service()->ReconsiderProxyAfterError(
       request_info().url, proxy_info(), &io_callback_, &pac_request_,
       net_log_);
@@ -1051,35 +1071,6 @@
   return error;
 }
 
-int HttpStreamRequest::HandleSSLHandshakeError(int error) {
-  if (ssl_config()->send_client_cert &&
-      (error == ERR_SSL_PROTOCOL_ERROR ||
-       error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
-    session_->ssl_client_auth_cache()->Remove(
-        GetHostAndPort(request_info().url));
-  }
-
-  switch (error) {
-    case ERR_SSL_PROTOCOL_ERROR:
-    case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
-    case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
-    case ERR_SSL_BAD_RECORD_MAC_ALERT:
-      if (ssl_config()->tls1_enabled &&
-          !SSLConfigService::IsKnownStrictTLSServer(
-          request_info().url.host())) {
-        // This could be a TLS-intolerant server, an SSL 3.0 server that
-        // chose a TLS-only cipher suite or a server with buggy DEFLATE
-        // support. Turn off TLS 1.0, DEFLATE support and retry.
-        factory_->AddTLSIntolerantServer(request_info().url);
-        next_state_ = STATE_INIT_CONNECTION;
-        DCHECK(!connection_.get() || !connection_->socket());
-        error = OK;
-      }
-      break;
-  }
-  return error;
-}
-
 void HttpStreamRequest::SwitchToSpdyMode() {
   if (HttpStreamFactory::spdy_enabled())
     using_spdy_ = true;
diff --git a/net/http/http_stream_request.h b/net/http/http_stream_request.h
index 62ba5d8..fca2332 100644
--- a/net/http/http_stream_request.h
+++ b/net/http/http_stream_request.h
@@ -172,11 +172,6 @@
   // Called to handle a client certificate request.
   int HandleCertificateRequest(int error);
 
-  // Called to possibly recover from an SSL handshake error.  Sets next_state_
-  // and returns OK if recovering from the error.  Otherwise, the same error
-  // code is returned.
-  int HandleSSLHandshakeError(int error);
-
   // Moves this stream request into SPDY mode.
   void SwitchToSpdyMode();
 
diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc
index 518c1f8..fabfb01 100644
--- a/net/http/http_transaction_unittest.cc
+++ b/net/http/http_transaction_unittest.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "net/http/http_transaction_unittest.h"
 
-#include "base/hash_tables.h"
+#include <algorithm>
+
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "net/base/net_errors.h"
@@ -16,6 +17,11 @@
 #include "net/http/http_transaction.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+typedef base::hash_map<std::string, const MockTransaction*> MockTransactionMap;
+static MockTransactionMap mock_transactions;
+}  // namespace
+
 //-----------------------------------------------------------------------------
 // mock transaction data
 
@@ -104,18 +110,6 @@
   &kRangeGET_Transaction
 };
 
-typedef base::hash_map<std::string, const MockTransaction*>
-MockTransactionMap;
-static MockTransactionMap mock_transactions;
-
-void AddMockTransaction(const MockTransaction* trans) {
-  mock_transactions[GURL(trans->url).spec()] = trans;
-}
-
-void RemoveMockTransaction(const MockTransaction* trans) {
-  mock_transactions.erase(GURL(trans->url).spec());
-}
-
 const MockTransaction* FindMockTransaction(const GURL& url) {
   // look for overrides:
   MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
@@ -130,12 +124,222 @@
   return NULL;
 }
 
+void AddMockTransaction(const MockTransaction* trans) {
+  mock_transactions[GURL(trans->url).spec()] = trans;
+}
+
+void RemoveMockTransaction(const MockTransaction* trans) {
+  mock_transactions.erase(GURL(trans->url).spec());
+}
+
+MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
+  url = GURL(t.url);
+  method = t.method;
+  extra_headers.AddHeadersFromString(t.request_headers);
+  load_flags = t.load_flags;
+}
 
 //-----------------------------------------------------------------------------
 
 // static
 int TestTransactionConsumer::quit_counter_ = 0;
 
+TestTransactionConsumer::TestTransactionConsumer(
+    net::HttpTransactionFactory* factory)
+    : state_(IDLE),
+      trans_(NULL),
+      error_(net::OK) {
+  // Disregard the error code.
+  factory->CreateTransaction(&trans_);
+  ++quit_counter_;
+}
+
+TestTransactionConsumer::~TestTransactionConsumer() {
+}
+
+void TestTransactionConsumer::Start(const net::HttpRequestInfo* request,
+                                    const net::BoundNetLog& net_log) {
+  state_ = STARTING;
+  int result = trans_->Start(request, this, net_log);
+  if (result != net::ERR_IO_PENDING)
+    DidStart(result);
+}
+
+void TestTransactionConsumer::DidStart(int result) {
+  if (result != net::OK) {
+    DidFinish(result);
+  } else {
+    Read();
+  }
+}
+
+void TestTransactionConsumer::DidRead(int result) {
+  if (result <= 0) {
+    DidFinish(result);
+  } else {
+    content_.append(read_buf_->data(), result);
+    Read();
+  }
+}
+
+void TestTransactionConsumer::DidFinish(int result) {
+  state_ = DONE;
+  error_ = result;
+  if (--quit_counter_ == 0)
+    MessageLoop::current()->Quit();
+}
+
+void TestTransactionConsumer::Read() {
+  state_ = READING;
+  read_buf_ = new net::IOBuffer(1024);
+  int result = trans_->Read(read_buf_, 1024, this);
+  if (result != net::ERR_IO_PENDING)
+    DidRead(result);
+}
+
+void TestTransactionConsumer::RunWithParams(const Tuple1<int>& params) {
+  int result = params.a;
+  switch (state_) {
+    case STARTING:
+      DidStart(result);
+      break;
+    case READING:
+      DidRead(result);
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
+
+MockNetworkTransaction::MockNetworkTransaction() :
+    ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), data_cursor_(0) {
+}
+
+MockNetworkTransaction::~MockNetworkTransaction() {}
+
+int MockNetworkTransaction::Start(const net::HttpRequestInfo* request,
+                                  net::CompletionCallback* callback,
+                                  const net::BoundNetLog& net_log) {
+  const MockTransaction* t = FindMockTransaction(request->url);
+  if (!t)
+    return net::ERR_FAILED;
+
+  std::string resp_status = t->status;
+  std::string resp_headers = t->response_headers;
+  std::string resp_data = t->data;
+  if (t->handler)
+    (t->handler)(request, &resp_status, &resp_headers, &resp_data);
+
+  std::string header_data = base::StringPrintf(
+      "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
+  std::replace(header_data.begin(), header_data.end(), '\n', '\0');
+
+  response_.request_time = base::Time::Now();
+  if (!t->request_time.is_null())
+    response_.request_time = t->request_time;
+
+  response_.was_cached = false;
+
+  response_.response_time = base::Time::Now();
+  if (!t->response_time.is_null())
+    response_.response_time = t->response_time;
+
+  response_.headers = new net::HttpResponseHeaders(header_data);
+  response_.ssl_info.cert_status = t->cert_status;
+  data_ = resp_data;
+  test_mode_ = t->test_mode;
+
+  if (test_mode_ & TEST_MODE_SYNC_NET_START)
+    return net::OK;
+
+  CallbackLater(callback, net::OK);
+  return net::ERR_IO_PENDING;
+}
+
+int MockNetworkTransaction::RestartIgnoringLastError(
+    net::CompletionCallback* callback) {
+  return net::ERR_FAILED;
+}
+
+int MockNetworkTransaction::RestartWithCertificate(
+    net::X509Certificate* client_cert,
+    net::CompletionCallback* callback) {
+  return net::ERR_FAILED;
+}
+
+int MockNetworkTransaction::RestartWithAuth(const string16& username,
+                                            const string16& password,
+                                            net::CompletionCallback* callback) {
+  return net::ERR_FAILED;
+}
+
+bool MockNetworkTransaction::IsReadyToRestartForAuth() {
+  return false;
+}
+
+int MockNetworkTransaction::Read(net::IOBuffer* buf, int buf_len,
+                                 net::CompletionCallback* callback) {
+  int data_len = static_cast<int>(data_.size());
+  int num = std::min(buf_len, data_len - data_cursor_);
+  if (num) {
+    memcpy(buf->data(), data_.data() + data_cursor_, num);
+    data_cursor_ += num;
+  }
+  if (test_mode_ & TEST_MODE_SYNC_NET_READ)
+    return num;
+
+  CallbackLater(callback, num);
+  return net::ERR_IO_PENDING;
+}
+
+void MockNetworkTransaction::StopCaching() {}
+
+const net::HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
+  return &response_;
+}
+
+net::LoadState MockNetworkTransaction::GetLoadState() const {
+  if (data_cursor_)
+    return net::LOAD_STATE_READING_RESPONSE;
+  return net::LOAD_STATE_IDLE;
+}
+
+uint64 MockNetworkTransaction::GetUploadProgress() const {
+  return 0;
+}
+
+void MockNetworkTransaction::CallbackLater(net::CompletionCallback* callback,
+                                           int result) {
+  MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
+      &MockNetworkTransaction::RunCallback, callback, result));
+}
+
+void MockNetworkTransaction::RunCallback(net::CompletionCallback* callback,
+                                         int result) {
+  callback->Run(result);
+}
+
+MockNetworkLayer::MockNetworkLayer() : transaction_count_(0) {}
+
+MockNetworkLayer::~MockNetworkLayer() {}
+
+int MockNetworkLayer::CreateTransaction(
+    scoped_ptr<net::HttpTransaction>* trans) {
+  transaction_count_++;
+  trans->reset(new MockNetworkTransaction());
+  return net::OK;
+}
+
+net::HttpCache* MockNetworkLayer::GetCache() {
+  return NULL;
+}
+
+net::HttpNetworkSession* MockNetworkLayer::GetSession() {
+  return NULL;
+}
+
+void MockNetworkLayer::Suspend(bool suspend) {}
 
 //-----------------------------------------------------------------------------
 // helpers
diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h
index 3149534..0a11bb5 100644
--- a/net/http/http_transaction_unittest.h
+++ b/net/http/http_transaction_unittest.h
@@ -8,15 +8,11 @@
 
 #include "net/http/http_transaction.h"
 
-#include <algorithm>
 #include <string>
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "base/message_loop.h"
 #include "base/string16.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
 #include "net/base/io_buffer.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
@@ -27,6 +23,10 @@
 #include "net/http/http_response_headers.h"
 #include "net/http/http_response_info.h"
 
+namespace net {
+class IOBuffer;
+}
+
 //-----------------------------------------------------------------------------
 // mock transaction data
 
@@ -97,12 +97,7 @@
 
 class MockHttpRequest : public net::HttpRequestInfo {
  public:
-  explicit MockHttpRequest(const MockTransaction& t) {
-    url = GURL(t.url);
-    method = t.method;
-    extra_headers.AddHeadersFromString(t.request_headers);
-    load_flags = t.load_flags;
-  }
+  explicit MockHttpRequest(const MockTransaction& t);
 };
 
 //-----------------------------------------------------------------------------
@@ -110,25 +105,11 @@
 
 class TestTransactionConsumer : public CallbackRunner< Tuple1<int> > {
  public:
-  explicit TestTransactionConsumer(net::HttpTransactionFactory* factory)
-      : state_(IDLE),
-        trans_(NULL),
-        error_(net::OK) {
-    // Disregard the error code.
-    factory->CreateTransaction(&trans_);
-    ++quit_counter_;
-  }
-
-  ~TestTransactionConsumer() {
-  }
+  explicit TestTransactionConsumer(net::HttpTransactionFactory* factory);
+  virtual ~TestTransactionConsumer();
 
   void Start(const net::HttpRequestInfo* request,
-             const net::BoundNetLog& net_log) {
-    state_ = STARTING;
-    int result = trans_->Start(request, this, net_log);
-    if (result != net::ERR_IO_PENDING)
-      DidStart(result);
-  }
+             const net::BoundNetLog& net_log);
 
   bool is_done() const { return state_ == DONE; }
   int error() const { return error_; }
@@ -139,60 +120,22 @@
   const std::string& content() const { return content_; }
 
  private:
-  // Callback implementation:
-  virtual void RunWithParams(const Tuple1<int>& params) {
-    int result = params.a;
-    switch (state_) {
-      case STARTING:
-        DidStart(result);
-        break;
-      case READING:
-        DidRead(result);
-        break;
-      default:
-        NOTREACHED();
-    }
-  }
-
-  void DidStart(int result) {
-    if (result != net::OK) {
-      DidFinish(result);
-    } else {
-      Read();
-    }
-  }
-
-  void DidRead(int result) {
-    if (result <= 0) {
-      DidFinish(result);
-    } else {
-      content_.append(read_buf_->data(), result);
-      Read();
-    }
-  }
-
-  void DidFinish(int result) {
-    state_ = DONE;
-    error_ = result;
-    if (--quit_counter_ == 0)
-      MessageLoop::current()->Quit();
-  }
-
-  void Read() {
-    state_ = READING;
-    read_buf_ = new net::IOBuffer(1024);
-    int result = trans_->Read(read_buf_, 1024, this);
-    if (result != net::ERR_IO_PENDING)
-      DidRead(result);
-  }
-
   enum State {
     IDLE,
     STARTING,
     READING,
     DONE
-  } state_;
+  };
 
+  void DidStart(int result);
+  void DidRead(int result);
+  void DidFinish(int result);
+  void Read();
+
+  // Callback implementation:
+  virtual void RunWithParams(const Tuple1<int>& params);
+
+  State state_;
   scoped_ptr<net::HttpTransaction> trans_;
   std::string content_;
   scoped_refptr<net::IOBuffer> read_buf_;
@@ -210,107 +153,38 @@
 // HttpCache implementation.
 class MockNetworkTransaction : public net::HttpTransaction {
  public:
-  MockNetworkTransaction() :
-      ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), data_cursor_(0) {
-  }
+  MockNetworkTransaction();
+  virtual ~MockNetworkTransaction();
 
   virtual int Start(const net::HttpRequestInfo* request,
                     net::CompletionCallback* callback,
-                    const net::BoundNetLog& net_log) {
-    const MockTransaction* t = FindMockTransaction(request->url);
-    if (!t)
-      return net::ERR_FAILED;
+                    const net::BoundNetLog& net_log);
 
-    std::string resp_status = t->status;
-    std::string resp_headers = t->response_headers;
-    std::string resp_data = t->data;
-    if (t->handler)
-      (t->handler)(request, &resp_status, &resp_headers, &resp_data);
-
-    std::string header_data = base::StringPrintf(
-        "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
-    std::replace(header_data.begin(), header_data.end(), '\n', '\0');
-
-    response_.request_time = base::Time::Now();
-    if (!t->request_time.is_null())
-      response_.request_time = t->request_time;
-
-    response_.was_cached = false;
-
-    response_.response_time = base::Time::Now();
-    if (!t->response_time.is_null())
-      response_.response_time = t->response_time;
-
-    response_.headers = new net::HttpResponseHeaders(header_data);
-    response_.ssl_info.cert_status = t->cert_status;
-    data_ = resp_data;
-    test_mode_ = t->test_mode;
-
-    if (test_mode_ & TEST_MODE_SYNC_NET_START)
-      return net::OK;
-
-    CallbackLater(callback, net::OK);
-    return net::ERR_IO_PENDING;
-  }
-
-  virtual int RestartIgnoringLastError(net::CompletionCallback* callback) {
-    return net::ERR_FAILED;
-  }
+  virtual int RestartIgnoringLastError(net::CompletionCallback* callback);
 
   virtual int RestartWithCertificate(net::X509Certificate* client_cert,
-                                     net::CompletionCallback* callback) {
-    return net::ERR_FAILED;
-  }
+                                     net::CompletionCallback* callback);
 
   virtual int RestartWithAuth(const string16& username,
                               const string16& password,
-                              net::CompletionCallback* callback) {
-    return net::ERR_FAILED;
-  }
+                              net::CompletionCallback* callback);
 
-  virtual bool IsReadyToRestartForAuth() {
-    return false;
-  }
+  virtual bool IsReadyToRestartForAuth();
 
   virtual int Read(net::IOBuffer* buf, int buf_len,
-                   net::CompletionCallback* callback) {
-    int data_len = static_cast<int>(data_.size());
-    int num = std::min(buf_len, data_len - data_cursor_);
-    if (num) {
-      memcpy(buf->data(), data_.data() + data_cursor_, num);
-      data_cursor_ += num;
-    }
-    if (test_mode_ & TEST_MODE_SYNC_NET_READ)
-      return num;
+                   net::CompletionCallback* callback);
 
-    CallbackLater(callback, num);
-    return net::ERR_IO_PENDING;
-  }
+  virtual void StopCaching();
 
-  virtual void StopCaching() {}
+  virtual const net::HttpResponseInfo* GetResponseInfo() const;
 
-  virtual const net::HttpResponseInfo* GetResponseInfo() const {
-    return &response_;
-  }
+  virtual net::LoadState GetLoadState() const;
 
-  virtual net::LoadState GetLoadState() const {
-    if (data_cursor_)
-      return net::LOAD_STATE_READING_RESPONSE;
-    return net::LOAD_STATE_IDLE;
-  }
-
-  virtual uint64 GetUploadProgress() const {
-    return 0;
-  }
+  virtual uint64 GetUploadProgress() const;
 
  private:
-  void CallbackLater(net::CompletionCallback* callback, int result) {
-    MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
-        &MockNetworkTransaction::RunCallback, callback, result));
-  }
-  void RunCallback(net::CompletionCallback* callback, int result) {
-    callback->Run(result);
-  }
+  void CallbackLater(net::CompletionCallback* callback, int result);
+  void RunCallback(net::CompletionCallback* callback, int result);
 
   ScopedRunnableMethodFactory<MockNetworkTransaction> task_factory_;
   net::HttpResponseInfo response_;
@@ -321,32 +195,21 @@
 
 class MockNetworkLayer : public net::HttpTransactionFactory {
  public:
-  MockNetworkLayer() : transaction_count_(0) {
-  }
-
-  virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) {
-    transaction_count_++;
-    trans->reset(new MockNetworkTransaction());
-    return net::OK;
-  }
-
-  virtual net::HttpCache* GetCache() {
-    return NULL;
-  }
-
-  virtual net::HttpNetworkSession* GetSession() {
-    return NULL;
-  }
-
-  virtual void Suspend(bool suspend) {}
+  MockNetworkLayer();
+  virtual ~MockNetworkLayer();
 
   int transaction_count() const { return transaction_count_; }
 
+  // net::HttpTransactionFactory:
+  virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans);
+  virtual net::HttpCache* GetCache();
+  virtual net::HttpNetworkSession* GetSession();
+  virtual void Suspend(bool suspend);
+
  private:
   int transaction_count_;
 };
 
-
 //-----------------------------------------------------------------------------
 // helpers
 
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index bf56136..0f28c83 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -674,9 +674,14 @@
 
   // Add a content length header?
   if (upload_data_stream) {
-    request_headers->SetHeader(
-        HttpRequestHeaders::kContentLength,
-        base::Uint64ToString(upload_data_stream->size()));
+    if (upload_data_stream->is_chunked()) {
+      request_headers->SetHeader(
+          HttpRequestHeaders::kTransferEncoding, "chunked");
+    } else {
+      request_headers->SetHeader(
+          HttpRequestHeaders::kContentLength,
+          base::Uint64ToString(upload_data_stream->size()));
+    }
   } else if (request_info->method == "POST" || request_info->method == "PUT" ||
              request_info->method == "HEAD") {
     // An empty POST/PUT request still needs a content length.  As for HEAD,
diff --git a/net/http/mock_gssapi_library_posix.cc b/net/http/mock_gssapi_library_posix.cc
index ec69964..5ae4721 100644
--- a/net/http/mock_gssapi_library_posix.cc
+++ b/net/http/mock_gssapi_library_posix.cc
@@ -188,12 +188,70 @@
   open = other.open;
 }
 
+MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery()
+    : expected_package(),
+      response_code(0),
+      minor_response_code(0),
+      context_info() {
+  expected_input_token.length = 0;
+  expected_input_token.value = NULL;
+  output_token.length = 0;
+  output_token.value = NULL;
+}
+
+MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery(
+    const std::string& in_expected_package,
+    OM_uint32 in_response_code,
+    OM_uint32 in_minor_response_code,
+    const test::GssContextMockImpl& in_context_info,
+    const char* in_expected_input_token,
+    const char* in_output_token)
+    : expected_package(in_expected_package),
+      response_code(in_response_code),
+      minor_response_code(in_minor_response_code),
+      context_info(in_context_info) {
+  if (in_expected_input_token) {
+    expected_input_token.length = strlen(in_expected_input_token);
+    expected_input_token.value = const_cast<char*>(in_expected_input_token);
+  } else {
+    expected_input_token.length = 0;
+    expected_input_token.value = NULL;
+  }
+
+  if (in_output_token) {
+    output_token.length = strlen(in_output_token);
+    output_token.value = const_cast<char*>(in_output_token);
+  } else {
+    output_token.length = 0;
+    output_token.value = NULL;
+  }
+}
+
+MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() {}
+
 MockGSSAPILibrary::MockGSSAPILibrary() {
 }
 
 MockGSSAPILibrary::~MockGSSAPILibrary() {
 }
 
+void MockGSSAPILibrary::ExpectSecurityContext(
+    const std::string& expected_package,
+    OM_uint32 response_code,
+    OM_uint32 minor_response_code,
+    const GssContextMockImpl& context_info,
+    const gss_buffer_desc& expected_input_token,
+    const gss_buffer_desc& output_token) {
+  SecurityContextQuery security_query;
+  security_query.expected_package = expected_package;
+  security_query.response_code = response_code;
+  security_query.minor_response_code = minor_response_code;
+  security_query.context_info.Assign(context_info);
+  security_query.expected_input_token = expected_input_token;
+  security_query.output_token = output_token;
+  expected_security_queries_.push_back(security_query);
+}
+
 bool MockGSSAPILibrary::Init() {
   return true;
 }
@@ -417,23 +475,6 @@
   return GSS_S_COMPLETE;
 }
 
-void MockGSSAPILibrary::ExpectSecurityContext(
-    const std::string& expected_package,
-    OM_uint32 response_code,
-    OM_uint32 minor_response_code,
-    const GssContextMockImpl& context_info,
-    const gss_buffer_desc& expected_input_token,
-    const gss_buffer_desc& output_token) {
-  SecurityContextQuery security_query;
-  security_query.expected_package = expected_package;
-  security_query.response_code = response_code;
-  security_query.minor_response_code = minor_response_code;
-  security_query.context_info.Assign(context_info);
-  security_query.expected_input_token = expected_input_token;
-  security_query.output_token = output_token;
-  expected_security_queries_.push_back(security_query);
-}
-
 }  // namespace test
 
 }  // namespace net
diff --git a/net/http/mock_gssapi_library_posix.h b/net/http/mock_gssapi_library_posix.h
index 15e14f2..aad5de8 100644
--- a/net/http/mock_gssapi_library_posix.h
+++ b/net/http/mock_gssapi_library_posix.h
@@ -45,10 +45,70 @@
 // the system GSSAPI library calls.
 class MockGSSAPILibrary : public GSSAPILibrary {
  public:
+  // Unit tests need access to this. "Friend"ing didn't help.
+  struct SecurityContextQuery {
+    SecurityContextQuery();
+    SecurityContextQuery(const std::string& expected_package,
+                         OM_uint32 response_code,
+                         OM_uint32 minor_response_code,
+                         const test::GssContextMockImpl& context_info,
+                         const char* expected_input_token,
+                         const char* output_token);
+    ~SecurityContextQuery();
+
+    std::string expected_package;
+    OM_uint32 response_code;
+    OM_uint32 minor_response_code;
+    test::GssContextMockImpl context_info;
+    gss_buffer_desc expected_input_token;
+    gss_buffer_desc output_token;
+  };
 
   MockGSSAPILibrary();
   virtual ~MockGSSAPILibrary();
 
+  // Establishes an expectation for a |init_sec_context()| call.
+  //
+  // Each expectation established by |ExpectSecurityContext()| must be
+  // matched by a call to |init_sec_context()| during the lifetime of
+  // the MockGSSAPILibrary. The |expected_package| argument must equal the
+  // value associated with the |target_name| argument to |init_sec_context()|
+  // for there to be a match. The expectations also establish an explicit
+  // ordering.
+  //
+  // For example, this sequence will be successful.
+  //   MockGSSAPILibrary lib;
+  //   lib.ExpectSecurityContext("NTLM", ...)
+  //   lib.ExpectSecurityContext("Negotiate", ...)
+  //   lib.init_sec_context("NTLM", ...)
+  //   lib.init_sec_context("Negotiate", ...)
+  //
+  // This sequence will fail since the queries do not occur in the order
+  // established by the expectations.
+  //   MockGSSAPILibrary lib;
+  //   lib.ExpectSecurityContext("NTLM", ...)
+  //   lib.ExpectSecurityContext("Negotiate", ...)
+  //   lib.init_sec_context("Negotiate", ...)
+  //   lib.init_sec_context("NTLM", ...)
+  //
+  // This sequence will fail because there were not enough queries.
+  //   MockGSSAPILibrary lib;
+  //   lib.ExpectSecurityContext("NTLM", ...)
+  //   lib.ExpectSecurityContext("Negotiate", ...)
+  //   lib.init_sec_context("NTLM", ...)
+  //
+  // |response_code| is used as the return value for |init_sec_context()|.
+  // If |response_code| is GSS_S_COMPLETE,
+  //
+  // |context_info| is the expected value of the |**context_handle| in after
+  // |init_sec_context()| returns.
+  void ExpectSecurityContext(const std::string& expected_package,
+                             OM_uint32 response_code,
+                             OM_uint32 minor_response_code,
+                             const test::GssContextMockImpl& context_info,
+                             const gss_buffer_desc& expected_input_token,
+                             const gss_buffer_desc& output_token);
+
   // GSSAPILibrary methods:
 
   // Initializes the library, including any necessary dynamic libraries.
@@ -116,58 +176,6 @@
       int* locally_initiated,
       int* open);
 
-  // Establishes an expectation for a |init_sec_context()| call.
-  //
-  // Each expectation established by |ExpectSecurityContext()| must be
-  // matched by a call to |init_sec_context()| during the lifetime of
-  // the MockGSSAPILibrary. The |expected_package| argument must equal the
-  // value associated with the |target_name| argument to |init_sec_context()|
-  // for there to be a match. The expectations also establish an explicit
-  // ordering.
-  //
-  // For example, this sequence will be successful.
-  //   MockGSSAPILibrary lib;
-  //   lib.ExpectSecurityContext("NTLM", ...)
-  //   lib.ExpectSecurityContext("Negotiate", ...)
-  //   lib.init_sec_context("NTLM", ...)
-  //   lib.init_sec_context("Negotiate", ...)
-  //
-  // This sequence will fail since the queries do not occur in the order
-  // established by the expectations.
-  //   MockGSSAPILibrary lib;
-  //   lib.ExpectSecurityContext("NTLM", ...)
-  //   lib.ExpectSecurityContext("Negotiate", ...)
-  //   lib.init_sec_context("Negotiate", ...)
-  //   lib.init_sec_context("NTLM", ...)
-  //
-  // This sequence will fail because there were not enough queries.
-  //   MockGSSAPILibrary lib;
-  //   lib.ExpectSecurityContext("NTLM", ...)
-  //   lib.ExpectSecurityContext("Negotiate", ...)
-  //   lib.init_sec_context("NTLM", ...)
-  //
-  // |response_code| is used as the return value for |init_sec_context()|.
-  // If |response_code| is GSS_S_COMPLETE,
-  //
-  // |context_info| is the expected value of the |**context_handle| in after
-  // |init_sec_context()| returns.
-  void ExpectSecurityContext(const std::string& expected_package,
-                             OM_uint32 response_code,
-                             OM_uint32 minor_response_code,
-                             const test::GssContextMockImpl& context_info,
-                             const gss_buffer_desc& expected_input_token,
-                             const gss_buffer_desc& output_token);
-
-  // Unit tests need access to this. "Friend"ing didn't help.
-  struct SecurityContextQuery {
-    std::string expected_package;
-    OM_uint32 response_code;
-    OM_uint32 minor_response_code;
-    test::GssContextMockImpl context_info;
-    gss_buffer_desc expected_input_token;
-    gss_buffer_desc output_token;
-  };
-
  private:
   FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPICycle);
 
diff --git a/net/http/url_security_manager.h b/net/http/url_security_manager.h
index c6a5ec9..119d6bd 100644
--- a/net/http/url_security_manager.h
+++ b/net/http/url_security_manager.h
@@ -74,25 +74,6 @@
   DISALLOW_COPY_AND_ASSIGN(URLSecurityManagerWhitelist);
 };
 
-#if defined(UNIT_TEST)
-// An URLSecurityManager which is very permissive.
-class URLSecurityManagerAllow : public URLSecurityManager {
- public:
-  URLSecurityManagerAllow() {}
-  virtual ~URLSecurityManagerAllow() {}
-
-  virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const {
-    return true;
-  }
-  virtual bool CanDelegate(const GURL& auth_origin) const {
-    return true;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(URLSecurityManagerAllow);
-};
-#endif  // defined(UNIT_TEST)
-
 }  // namespace net
 
 #endif  // NET_HTTP_URL_SECURITY_MANAGER_H_
diff --git a/net/net.gyp b/net/net.gyp
index 649544a..7d5236f 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -54,6 +54,8 @@
         'base/cookie_policy.h',
         'base/cookie_store.cc',
         'base/cookie_store.h',
+        'base/crypto_module.h',
+        'base/crypto_module_nss.cc',
         'base/data_url.cc',
         'base/data_url.h',
         'base/directory_lister.cc',
@@ -64,7 +66,6 @@
         'base/dnssec_chain_verifier.h',
         'base/dnssec_keyset.cc',
         'base/dnssec_keyset.h',
-        'base/dnssec_proto.h',
         'base/dns_util.cc',
         'base/dns_util.h',
         'base/dnsrr_resolver.cc',
@@ -96,6 +97,7 @@
         'base/host_resolver_proc.h',
         'base/io_buffer.cc',
         'base/io_buffer.h',
+        'base/keygen_handler.cc',
         'base/keygen_handler.h',
         'base/keygen_handler_mac.cc',
         'base/keygen_handler_nss.cc',
@@ -186,7 +188,6 @@
         'base/transport_security_state.cc',
         'base/transport_security_state.h',
         'base/sys_addrinfo.h',
-        'base/test_completion_callback.h',
         'base/upload_data.cc',
         'base/upload_data.h',
         'base/upload_data_stream.cc',
@@ -257,6 +258,7 @@
           {  # else: OS is not in the above list
             'sources!': [
               'base/cert_database_nss.cc',
+              'base/crypto_module_nss.cc',
               'base/keygen_handler_nss.cc',
               'base/test_root_certs_nss.cc',
               'base/x509_certificate_nss.cc',
@@ -274,6 +276,7 @@
         [ 'use_openssl==1', {
             'sources!': [
               'base/cert_database_nss.cc',
+              'base/crypto_module_nss.cc',
               'base/dnssec_keyset.cc',
               'base/dnssec_keyset.h',
               'base/keygen_handler_nss.cc',
@@ -485,6 +488,7 @@
         'http/http_network_layer.h',
         'http/http_network_session.cc',
         'http/http_network_session.h',
+        'http/http_network_session_peer.cc',
         'http/http_network_session_peer.h',
         'http/http_network_transaction.cc',
         'http/http_network_transaction.h',
@@ -624,6 +628,7 @@
         'socket/ssl_server_socket.h',
         'socket/ssl_server_socket_nss.cc',
         'socket/ssl_server_socket_nss.h',
+        'socket/ssl_server_socket_openssl.cc',
         'socket/ssl_host_info.cc',
         'socket/ssl_host_info.h',
         'socket/tcp_client_socket.cc',
@@ -765,6 +770,7 @@
             'sources!': [
               'socket/ssl_client_socket_openssl.cc',
               'socket/ssl_client_socket_openssl.h',
+              'socket/ssl_server_socket_openssl.cc',
             ],
           },
         ],
@@ -862,21 +868,20 @@
         'base/escape_unittest.cc',
         'base/file_stream_unittest.cc',
         'base/filter_unittest.cc',
-        'base/filter_unittest.h',
         'base/gzip_filter_unittest.cc',
         'base/host_cache_unittest.cc',
         'base/host_mapping_rules_unittest.cc',
         'base/host_resolver_impl_unittest.cc',
         'base/keygen_handler_unittest.cc',
-        'base/leak_annotations.h',
         'base/listen_socket_unittest.cc',
         'base/listen_socket_unittest.h',
         'base/mapped_host_resolver_unittest.cc',
         'base/mime_sniffer_unittest.cc',
         'base/mime_util_unittest.cc',
+        'base/mock_filter_context.cc',
+        'base/mock_filter_context.h',
         'base/net_log_unittest.cc',
         'base/net_log_unittest.h',
-        'base/net_test_suite.h',
         'base/net_util_unittest.cc',
         'base/pem_tokenizer_unittest.cc',
         'base/registry_controlled_domain_unittest.cc',
@@ -943,13 +948,14 @@
         'http/http_transaction_unittest.h',
         'http/http_util_unittest.cc',
         'http/http_vary_data_unittest.cc',
+        'http/mock_allow_url_security_manager.cc',
+        'http/mock_allow_url_security_manager.h',
         'http/mock_gssapi_library_posix.cc',
         'http/mock_gssapi_library_posix.h',
         'http/mock_sspi_library_win.h',
         'http/mock_sspi_library_win.cc',
         'http/url_security_manager_unittest.cc',
         'proxy/init_proxy_resolver_unittest.cc',
-        'proxy/mock_proxy_resolver.h',
         'proxy/multi_threaded_proxy_resolver_unittest.cc',
         'proxy/proxy_bypass_rules_unittest.cc',
         'proxy/proxy_config_service_linux_unittest.cc',
@@ -993,7 +999,6 @@
         'url_request/url_request_job_tracker_unittest.cc',
         'url_request/url_request_throttler_unittest.cc',
         'url_request/url_request_unittest.cc',
-        'url_request/url_request_unittest.h',
         'url_request/view_cache_helper_unittest.cc',
         'websockets/websocket_frame_handler_unittest.cc',
         'websockets/websocket_handshake_draft75_unittest.cc',
@@ -1154,8 +1159,16 @@
       'sources': [
         'base/cert_test_util.cc',
         'base/cert_test_util.h',
+        'base/cookie_monster_store_test.cc',
+        'base/cookie_monster_store_test.h',
+        'base/net_test_suite.cc',
+        'base/net_test_suite.h',
+        'base/test_completion_callback.cc',
+        'base/test_completion_callback.h',
         'disk_cache/disk_cache_test_util.cc',
         'disk_cache/disk_cache_test_util.h',
+        'proxy/mock_proxy_resolver.cc',
+        'proxy/mock_proxy_resolver.h',
         'proxy/proxy_config_service_common_unittest.cc',
         'proxy/proxy_config_service_common_unittest.h',
         'socket/socket_test_util.cc',
@@ -1166,6 +1179,8 @@
         'test/test_server_posix.cc',
         'test/test_server_win.cc',
         'test/test_server.h',
+        'url_request/url_request_test_util.cc',
+        'url_request/url_request_test_util.h',
       ],
       'conditions': [
         ['inside_chromium_build==1', {
@@ -1272,14 +1287,16 @@
         'tools/fetch/http_listen_socket.h',
         'tools/fetch/http_server.cc',
         'tools/fetch/http_server.h',
+        'tools/fetch/http_server_request_info.cc',
         'tools/fetch/http_server_request_info.h',
+        'tools/fetch/http_server_response_info.cc',
         'tools/fetch/http_server_response_info.h',
         'tools/fetch/http_session.cc',
         'tools/fetch/http_session.h',
       ],
     },
     {
-      'target_name': 'http_listen_socket',
+      'target_name': 'http_server',
       'type': '<(library)',
       'dependencies': [
         'net',
@@ -1288,24 +1305,13 @@
       ],
       'msvs_guid': 'FCB894A4-CC6C-48C2-B495-52C80527E9BE',
       'sources': [
-        'server/http_listen_socket.cc',
-        'server/http_listen_socket.h',
+        'server/http_server.cc',
+        'server/http_server.h',
         'server/http_server_request_info.cc',
         'server/http_server_request_info.h',
       ],
     },
     {
-      'target_name': 'hresolv',
-      'type': 'executable',
-      'dependencies': [
-        'net_base',
-      ],
-      'msvs_guid': 'FF1BAC48-D326-4CB4-96DA-8B03DE23ED6E',
-      'sources': [
-        'tools/hresolv/hresolv.cc',
-      ],
-    },
-    {
       'target_name': 'dnssec_chain_verify',
       'type': 'executable',
       'dependencies': [
@@ -1347,6 +1353,8 @@
              'tools/dump_cache/url_utilities.h',
              'tools/dump_cache/url_utilities.cc',
 
+             'tools/flip_server/acceptor_thread.h',
+             'tools/flip_server/acceptor_thread.cc',
              'tools/flip_server/balsa_enums.h',
              'tools/flip_server/balsa_frame.cc',
              'tools/flip_server/balsa_frame.h',
@@ -1356,21 +1364,41 @@
              'tools/flip_server/balsa_headers_token_utils.h',
              'tools/flip_server/balsa_visitor_interface.h',
              'tools/flip_server/buffer_interface.h',
+             'tools/flip_server/constants.h',
              'tools/flip_server/create_listener.cc',
              'tools/flip_server/create_listener.h',
              'tools/flip_server/epoll_server.cc',
              'tools/flip_server/epoll_server.h',
+             'tools/flip_server/flip_config.cc',
+             'tools/flip_server/flip_config.h',
              'tools/flip_server/flip_in_mem_edsm_server.cc',
+             'tools/flip_server/http_interface.cc',
+             'tools/flip_server/http_interface.h',
              'tools/flip_server/http_message_constants.cc',
              'tools/flip_server/http_message_constants.h',
              'tools/flip_server/loadtime_measurement.h',
+             'tools/flip_server/mem_cache.h',
+             'tools/flip_server/mem_cache.cc',
              'tools/flip_server/porting.txt',
+             'tools/flip_server/output_ordering.cc',
+             'tools/flip_server/output_ordering.h',
              'tools/flip_server/ring_buffer.cc',
              'tools/flip_server/ring_buffer.h',
              'tools/flip_server/simple_buffer.cc',
              'tools/flip_server/simple_buffer.h',
+             'tools/flip_server/sm_connection.cc',
+             'tools/flip_server/sm_connection.h',
+             'tools/flip_server/sm_interface.h',
              'tools/flip_server/split.h',
              'tools/flip_server/split.cc',
+             'tools/flip_server/spdy_ssl.cc',
+             'tools/flip_server/spdy_ssl.h',
+             'tools/flip_server/spdy_interface.cc',
+             'tools/flip_server/spdy_interface.h',
+             'tools/flip_server/spdy_util.cc',
+             'tools/flip_server/spdy_util.h',
+             'tools/flip_server/streamer_interface.cc',
+             'tools/flip_server/streamer_interface.h',
              'tools/flip_server/string_piece_utils.h',
              'tools/flip_server/thread.h',
              'tools/flip_server/url_to_filename_encoder.h',
@@ -1417,6 +1445,7 @@
           'type': 'executable',
           'dependencies': [
             'net',
+            'net_test_support',
             '../base/base.gyp:base',
           ],
           'sources': [
diff --git a/net/ocsp/nss_ocsp.cc b/net/ocsp/nss_ocsp.cc
index 78eb7f5..f4a5443 100644
--- a/net/ocsp/nss_ocsp.cc
+++ b/net/ocsp/nss_ocsp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,7 +17,6 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
@@ -25,6 +24,7 @@
 #include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
 #include "base/time.h"
 #include "googleurl/src/gurl.h"
@@ -39,7 +39,7 @@
 
 // Protects |g_request_context|.
 pthread_mutex_t g_request_context_lock = PTHREAD_MUTEX_INITIALIZER;
-static URLRequestContext* g_request_context = NULL;
+static net::URLRequestContext* g_request_context = NULL;
 
 class OCSPRequestSession;
 
@@ -349,7 +349,7 @@
     DCHECK(!request_);
 
     pthread_mutex_lock(&g_request_context_lock);
-    URLRequestContext* url_request_context = g_request_context;
+    net::URLRequestContext* url_request_context = g_request_context;
     pthread_mutex_unlock(&g_request_context_lock);
 
     if (url_request_context == NULL)
@@ -575,7 +575,7 @@
                             SEC_HTTP_SERVER_SESSION* pSession) {
   VLOG(1) << "OCSP create session: host=" << host << " port=" << portnum;
   pthread_mutex_lock(&g_request_context_lock);
-  URLRequestContext* request_context = g_request_context;
+  net::URLRequestContext* request_context = g_request_context;
   pthread_mutex_unlock(&g_request_context_lock);
   if (request_context == NULL) {
     LOG(ERROR) << "No URLRequestContext for OCSP handler.";
diff --git a/net/proxy/init_proxy_resolver.cc b/net/proxy/init_proxy_resolver.cc
index 4bf250e..c60dd21 100644
--- a/net/proxy/init_proxy_resolver.cc
+++ b/net/proxy/init_proxy_resolver.cc
@@ -151,8 +151,10 @@
 
 int InitProxyResolver::DoWaitComplete(int result) {
   DCHECK_EQ(OK, result);
-  if (wait_delay_.ToInternalValue() != 0)
-    net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_WAIT, NULL);
+  if (wait_delay_.ToInternalValue() != 0) {
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_INIT_PROXY_RESOLVER_WAIT,
+                                      result);
+  }
   next_state_ = GetStartState();
   return OK;
 }
@@ -185,14 +187,10 @@
 int InitProxyResolver::DoFetchPacScriptComplete(int result) {
   DCHECK(resolver_->expects_pac_bytes());
 
-  if (result == OK) {
-    net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, NULL);
-  } else {
-    net_log_.EndEvent(
-        NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT,
-        make_scoped_refptr(new NetLogIntegerParameter("net_error", result)));
+  net_log_.EndEventWithNetErrorCode(
+      NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result);
+  if (result != OK)
     return TryToFallbackPacUrl(result);
-  }
 
   next_state_ = STATE_SET_PAC_SCRIPT;
   return result;
@@ -219,12 +217,10 @@
 }
 
 int InitProxyResolver::DoSetPacScriptComplete(int result) {
-  if (result != OK) {
-    net_log_.EndEvent(
-        NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT,
-        make_scoped_refptr(new NetLogIntegerParameter("net_error", result)));
+  net_log_.EndEventWithNetErrorCode(
+      NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result);
+  if (result != OK)
     return TryToFallbackPacUrl(result);
-  }
 
   // Let the caller know which automatic setting we ended up initializing the
   // resolver for (there may have been multiple fallbacks to choose from.)
@@ -240,7 +236,6 @@
     }
   }
 
-  net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL);
   return result;
 }
 
diff --git a/net/proxy/init_proxy_resolver.h b/net/proxy/init_proxy_resolver.h
index 2691be5..ec6bfc1 100644
--- a/net/proxy/init_proxy_resolver.h
+++ b/net/proxy/init_proxy_resolver.h
@@ -63,6 +63,15 @@
            CompletionCallback* callback);
 
  private:
+  struct PacURL {
+    PacURL(bool auto_detect, const GURL& url)
+        : auto_detect(auto_detect), url(url) {}
+    bool auto_detect;
+    GURL url;
+  };
+
+  typedef std::vector<PacURL> UrlList;
+
   enum State {
     STATE_NONE,
     STATE_WAIT,
@@ -73,15 +82,6 @@
     STATE_SET_PAC_SCRIPT_COMPLETE,
   };
 
-  struct PacURL {
-    PacURL(bool auto_detect, const GURL& url)
-        : auto_detect(auto_detect), url(url) {}
-    bool auto_detect;
-    GURL url;
-  };
-
-  typedef std::vector<PacURL> UrlList;
-
   // Returns ordered list of PAC urls to try for |config|.
   UrlList BuildPacUrlsFallbackList(const ProxyConfig& config) const;
 
diff --git a/net/proxy/init_proxy_resolver_unittest.cc b/net/proxy/init_proxy_resolver_unittest.cc
index c1a69d1..b0d416d 100644
--- a/net/proxy/init_proxy_resolver_unittest.cc
+++ b/net/proxy/init_proxy_resolver_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -187,7 +187,7 @@
   EXPECT_EQ(rule.text(), resolver.script_data()->utf16());
 
   // Check the NetLog was filled correctly.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(6u, entries.size());
@@ -224,7 +224,7 @@
   EXPECT_EQ(NULL, resolver.script_data());
 
   // Check the NetLog was filled correctly.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(4u, entries.size());
@@ -338,7 +338,7 @@
   // Check the NetLog was filled correctly.
   // (Note that the Fetch and Set states are repeated since both WPAD and custom
   // PAC scripts are tried).
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(11u, entries.size());
@@ -453,7 +453,7 @@
   EXPECT_EQ(NULL, resolver.script_data());
 
   // Check the NetLog was filled correctly.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(6u, entries.size());
@@ -493,7 +493,7 @@
   EXPECT_EQ(NULL, resolver.script_data());
 
   // Check the NetLog was filled correctly.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(4u, entries.size());
diff --git a/net/proxy/mock_proxy_resolver.h b/net/proxy/mock_proxy_resolver.h
index 880612b..bdc2ec6 100644
--- a/net/proxy/mock_proxy_resolver.h
+++ b/net/proxy/mock_proxy_resolver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,13 +8,13 @@
 
 #include <vector>
 
-#include "base/logging.h"
 #include "base/scoped_ptr.h"
-#include "base/message_loop.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/net_errors.h"
 #include "net/proxy/proxy_resolver.h"
 
+class MessageLoop;
+
 namespace net {
 
 // Asynchronous mock proxy resolver. All requests complete asynchronously,
@@ -26,31 +26,18 @@
     Request(MockAsyncProxyResolverBase* resolver,
             const GURL& url,
             ProxyInfo* results,
-            CompletionCallback* callback)
-        : resolver_(resolver),
-          url_(url),
-          results_(results),
-          callback_(callback),
-          origin_loop_(MessageLoop::current()) {
-    }
+            CompletionCallback* callback);
 
     const GURL& url() const { return url_; }
     ProxyInfo* results() const { return results_; }
     CompletionCallback* callback() const { return callback_; }
 
-    void CompleteNow(int rv) {
-      CompletionCallback* callback = callback_;
-
-      // May delete |this|.
-      resolver_->RemovePendingRequest(this);
-
-      callback->Run(rv);
-    }
+    void CompleteNow(int rv);
 
    private:
     friend class base::RefCounted<Request>;
 
-    ~Request() {}
+    virtual ~Request();
 
     MockAsyncProxyResolverBase* resolver_;
     const GURL url_;
@@ -64,23 +51,12 @@
     SetPacScriptRequest(
         MockAsyncProxyResolverBase* resolver,
         const scoped_refptr<ProxyResolverScriptData>& script_data,
-        CompletionCallback* callback)
-        : resolver_(resolver),
-          script_data_(script_data),
-          callback_(callback),
-          origin_loop_(MessageLoop::current()) {
-    }
+        CompletionCallback* callback);
+    ~SetPacScriptRequest();
 
     const ProxyResolverScriptData* script_data() const { return script_data_; }
 
-    void CompleteNow(int rv) {
-       CompletionCallback* callback = callback_;
-
-      // Will delete |this|.
-      resolver_->RemovePendingSetPacScriptRequest(this);
-
-      callback->Run(rv);
-    }
+    void CompleteNow(int rv);
 
    private:
     MockAsyncProxyResolverBase* resolver_;
@@ -91,41 +67,22 @@
 
   typedef std::vector<scoped_refptr<Request> > RequestsList;
 
+  virtual ~MockAsyncProxyResolverBase();
+
   // ProxyResolver implementation:
   virtual int GetProxyForURL(const GURL& url,
                              ProxyInfo* results,
                              CompletionCallback* callback,
                              RequestHandle* request_handle,
-                             const BoundNetLog& /*net_log*/) {
-    scoped_refptr<Request> request = new Request(this, url, results, callback);
-    pending_requests_.push_back(request);
+                             const BoundNetLog& /*net_log*/);
 
-    if (request_handle)
-      *request_handle = reinterpret_cast<RequestHandle>(request.get());
-
-    // Test code completes the request by calling request->CompleteNow().
-    return ERR_IO_PENDING;
-  }
-
-  virtual void CancelRequest(RequestHandle request_handle) {
-    scoped_refptr<Request> request = reinterpret_cast<Request*>(request_handle);
-    cancelled_requests_.push_back(request);
-    RemovePendingRequest(request);
-  }
+  virtual void CancelRequest(RequestHandle request_handle);
 
   virtual int SetPacScript(
       const scoped_refptr<ProxyResolverScriptData>& script_data,
-      CompletionCallback* callback) {
-    DCHECK(!pending_set_pac_script_request_.get());
-    pending_set_pac_script_request_.reset(
-        new SetPacScriptRequest(this, script_data, callback));
-    // Finished when user calls SetPacScriptRequest::CompleteNow().
-    return ERR_IO_PENDING;
-  }
+      CompletionCallback* callback);
 
-  virtual void CancelSetPacScript() {
-    // Do nothing (caller was responsible for completing the request).
-  }
+  virtual void CancelSetPacScript();
 
   const RequestsList& pending_requests() const {
     return pending_requests_;
@@ -135,25 +92,14 @@
     return cancelled_requests_;
   }
 
-  SetPacScriptRequest* pending_set_pac_script_request() const {
-    return pending_set_pac_script_request_.get();
-  }
+  SetPacScriptRequest* pending_set_pac_script_request() const;
 
-  void RemovePendingRequest(Request* request) {
-    RequestsList::iterator it = std::find(
-        pending_requests_.begin(), pending_requests_.end(), request);
-    DCHECK(it != pending_requests_.end());
-    pending_requests_.erase(it);
-  }
+  void RemovePendingRequest(Request* request);
 
-  void RemovePendingSetPacScriptRequest(SetPacScriptRequest* request) {
-    DCHECK_EQ(request, pending_set_pac_script_request());
-    pending_set_pac_script_request_.reset();
-  }
+  void RemovePendingSetPacScriptRequest(SetPacScriptRequest* request);
 
  protected:
-  explicit MockAsyncProxyResolverBase(bool expects_pac_bytes)
-      : ProxyResolver(expects_pac_bytes) {}
+  explicit MockAsyncProxyResolverBase(bool expects_pac_bytes);
 
  private:
   RequestsList pending_requests_;
diff --git a/net/proxy/multi_threaded_proxy_resolver.cc b/net/proxy/multi_threaded_proxy_resolver.cc
index ad1228c..87e25b0 100644
--- a/net/proxy/multi_threaded_proxy_resolver.cc
+++ b/net/proxy/multi_threaded_proxy_resolver.cc
@@ -8,6 +8,7 @@
 #include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_log.h"
 #include "net/proxy/proxy_info.h"
@@ -336,8 +337,13 @@
   // to avoid deadlocks.
   resolver_->Shutdown();
 
-  // Join the worker thread.
-  thread_.reset();
+  {
+    // See http://crbug.com/69710.
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+    // Join the worker thread.
+    thread_.reset();
+  }
 
   // Cancel any outstanding job.
   if (outstanding_job_) {
diff --git a/net/proxy/multi_threaded_proxy_resolver_unittest.cc b/net/proxy/multi_threaded_proxy_resolver_unittest.cc
index 78409e5..8d2907c 100644
--- a/net/proxy/multi_threaded_proxy_resolver_unittest.cc
+++ b/net/proxy/multi_threaded_proxy_resolver_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/proxy/multi_threaded_proxy_resolver.h"
 
+#include "base/message_loop.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
diff --git a/net/proxy/polling_proxy_config_service.cc b/net/proxy/polling_proxy_config_service.cc
index 98a164d..7526c19 100644
--- a/net/proxy/polling_proxy_config_service.cc
+++ b/net/proxy/polling_proxy_config_service.cc
@@ -4,10 +4,10 @@
 
 #include "net/proxy/polling_proxy_config_service.h"
 
-#include "base/lock.h"
 #include "base/message_loop_proxy.h"
 #include "base/observer_list.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/worker_pool.h"
 #include "net/proxy/proxy_config.h"
 
@@ -32,7 +32,7 @@
   // Called when the parent PollingProxyConfigService is destroyed
   // (observers should not be called past this point).
   void Orphan() {
-    AutoLock l(lock_);
+    base::AutoLock l(lock_);
     origin_loop_proxy_ = NULL;
   }
 
@@ -99,7 +99,7 @@
     ProxyConfig config;
     func(&config);
 
-    AutoLock l(lock_);
+    base::AutoLock l(lock_);
     if (origin_loop_proxy_) {
       origin_loop_proxy_->PostTask(
           FROM_HERE,
@@ -145,7 +145,7 @@
   base::TimeTicks last_poll_time_;
   base::TimeDelta poll_interval_;
 
-  Lock lock_;
+  base::Lock lock_;
   scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_;
 
   bool have_initialized_origin_loop_;
@@ -154,16 +154,6 @@
   bool poll_task_queued_;
 };
 
-PollingProxyConfigService::PollingProxyConfigService(
-    base::TimeDelta poll_interval,
-    GetConfigFunction get_config_func)
-    : core_(new Core(poll_interval, get_config_func)) {
-}
-
-PollingProxyConfigService::~PollingProxyConfigService() {
-  core_->Orphan();
-}
-
 void PollingProxyConfigService::AddObserver(Observer* observer) {
   core_->AddObserver(observer);
 }
@@ -180,6 +170,16 @@
   core_->OnLazyPoll();
 }
 
+PollingProxyConfigService::PollingProxyConfigService(
+    base::TimeDelta poll_interval,
+    GetConfigFunction get_config_func)
+    : core_(new Core(poll_interval, get_config_func)) {
+}
+
+PollingProxyConfigService::~PollingProxyConfigService() {
+  core_->Orphan();
+}
+
 void PollingProxyConfigService::CheckForChangesNow() {
   core_->CheckForChangesNow();
 }
diff --git a/net/proxy/proxy_config.cc b/net/proxy/proxy_config.cc
index ce14358..70e6549 100644
--- a/net/proxy/proxy_config.cc
+++ b/net/proxy/proxy_config.cc
@@ -32,17 +32,6 @@
 ProxyConfig::ProxyRules::~ProxyRules() {
 }
 
-bool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const {
-  return type == other.type &&
-         single_proxy == other.single_proxy &&
-         proxy_for_http == other.proxy_for_http &&
-         proxy_for_https == other.proxy_for_https &&
-         proxy_for_ftp == other.proxy_for_ftp &&
-         fallback_proxy == other.fallback_proxy &&
-         bypass_rules.Equals(other.bypass_rules) &&
-         reverse_bypass == other.reverse_bypass;
-}
-
 void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) {
   if (empty()) {
     result->UseDirect();
@@ -146,6 +135,17 @@
   return NULL;  // No mapping for this scheme. Use direct.
 }
 
+bool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const {
+  return type == other.type &&
+         single_proxy == other.single_proxy &&
+         proxy_for_http == other.proxy_for_http &&
+         proxy_for_https == other.proxy_for_https &&
+         proxy_for_ftp == other.proxy_for_ftp &&
+         fallback_proxy == other.fallback_proxy &&
+         bypass_rules.Equals(other.bypass_rules) &&
+         reverse_bypass == other.reverse_bypass;
+}
+
 ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
     const std::string& scheme) {
   DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type);
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
index 3867df1..893a8e5 100644
--- a/net/proxy/proxy_config_service_linux.cc
+++ b/net/proxy/proxy_config_service_linux.cc
@@ -26,6 +26,7 @@
 #include "base/string_tokenizer.h"
 #include "base/string_util.h"
 #include "base/task.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/timer.h"
 #include "base/nix/xdg_util.h"
 #include "googleurl/src/url_canon.h"
@@ -435,6 +436,9 @@
       : inotify_fd_(-1), notify_delegate_(NULL), indirect_manual_(false),
         auto_no_pac_(false), reversed_bypass_list_(false),
         env_var_getter_(env_var_getter), file_loop_(NULL) {
+    // This has to be called on the UI thread (http://crbug.com/69057).
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+
     // Derive the location of the kde config dir from the environment.
     std::string home;
     if (env_var_getter->GetVar("KDEHOME", &home) && !home.empty()) {
@@ -502,6 +506,8 @@
 
   virtual bool Init(MessageLoop* glib_default_loop,
                     MessageLoopForIO* file_loop) {
+    // This has to be called on the UI thread (http://crbug.com/69057).
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
     DCHECK(inotify_fd_ < 0);
     inotify_fd_ = inotify_init();
     if (inotify_fd_ < 0) {
diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc
index 849fc24..3c2fbff 100644
--- a/net/proxy/proxy_config_service_win.cc
+++ b/net/proxy/proxy_config_service_win.cc
@@ -42,7 +42,7 @@
   bool StartWatching(base::win::ObjectWatcher::Delegate* delegate) {
     // Try to create a watch event for the registry key (which watches the
     // sibling tree as well).
-    if (!key_.StartWatching())
+    if (key_.StartWatching() != ERROR_SUCCESS)
       return false;
 
     // Now setup an ObjectWatcher for this event, so we get OnObjectSignaled()
@@ -54,7 +54,7 @@
   }
 
   bool CreateRegKey(HKEY rootkey, const wchar_t* subkey) {
-    return key_.Create(rootkey, subkey, KEY_NOTIFY);
+    return key_.Create(rootkey, subkey, KEY_NOTIFY) == ERROR_SUCCESS;
   }
 
   HANDLE watch_event() const {
diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc
index 236e707..011aab9 100644
--- a/net/proxy/proxy_list.cc
+++ b/net/proxy/proxy_list.cc
@@ -86,17 +86,6 @@
   return proxies_[0];
 }
 
-std::string ProxyList::ToPacString() const {
-  std::string proxy_list;
-  std::vector<ProxyServer>::const_iterator iter = proxies_.begin();
-  for (; iter != proxies_.end(); ++iter) {
-    if (!proxy_list.empty())
-      proxy_list += ";";
-    proxy_list += iter->ToPacString();
-  }
-  return proxy_list.empty() ? std::string() : proxy_list;
-}
-
 void ProxyList::SetFromPacString(const std::string& pac_string) {
   StringTokenizer entry_tok(pac_string, ";");
   proxies_.clear();
@@ -115,6 +104,17 @@
   }
 }
 
+std::string ProxyList::ToPacString() const {
+  std::string proxy_list;
+  std::vector<ProxyServer>::const_iterator iter = proxies_.begin();
+  for (; iter != proxies_.end(); ++iter) {
+    if (!proxy_list.empty())
+      proxy_list += ";";
+    proxy_list += iter->ToPacString();
+  }
+  return proxy_list.empty() ? std::string() : proxy_list;
+}
+
 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) {
   // Number of minutes to wait before retrying a bad proxy server.
   const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5);
diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h
index 28bdcd0..6cd340f 100644
--- a/net/proxy/proxy_resolver_v8.h
+++ b/net/proxy/proxy_resolver_v8.h
@@ -40,6 +40,8 @@
 
   virtual ~ProxyResolverV8();
 
+  ProxyResolverJSBindings* js_bindings() const { return js_bindings_.get(); }
+
   // ProxyResolver implementation:
   virtual int GetProxyForURL(const GURL& url,
                              ProxyInfo* results,
@@ -54,8 +56,6 @@
       const scoped_refptr<ProxyResolverScriptData>& script_data,
       CompletionCallback* /*callback*/);
 
-  ProxyResolverJSBindings* js_bindings() const { return js_bindings_.get(); }
-
  private:
   // Context holds the Javascript state for the most recently loaded PAC
   // script. It corresponds with the data from the last call to
diff --git a/net/proxy/proxy_script_fetcher_impl.cc b/net/proxy/proxy_script_fetcher_impl.cc
index 0a54046..bc245a2 100644
--- a/net/proxy/proxy_script_fetcher_impl.cc
+++ b/net/proxy/proxy_script_fetcher_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -73,7 +73,7 @@
     URLRequestContext* url_request_context)
     : ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
       url_request_context_(url_request_context),
-      buf_(new net::IOBuffer(kBufSize)),
+      buf_(new IOBuffer(kBufSize)),
       next_id_(0),
       cur_request_(NULL),
       cur_request_id_(0),
@@ -86,10 +86,34 @@
 }
 
 ProxyScriptFetcherImpl::~ProxyScriptFetcherImpl() {
-  // The net::URLRequest's destructor will cancel the outstanding request, and
+  // The URLRequest's destructor will cancel the outstanding request, and
   // ensure that the delegate (this) is not called again.
 }
 
+base::TimeDelta ProxyScriptFetcherImpl::SetTimeoutConstraint(
+    base::TimeDelta timeout) {
+  base::TimeDelta prev = max_duration_;
+  max_duration_ = timeout;
+  return prev;
+}
+
+size_t ProxyScriptFetcherImpl::SetSizeConstraint(size_t size_bytes) {
+  size_t prev = max_response_bytes_;
+  max_response_bytes_ = size_bytes;
+  return prev;
+}
+
+void ProxyScriptFetcherImpl::OnResponseCompleted(URLRequest* request) {
+  DCHECK_EQ(request, cur_request_.get());
+
+  // Use |result_code_| as the request's error if we have already set it to
+  // something specific.
+  if (result_code_ == OK && !request->status().is_success())
+    result_code_ = request->status().os_error();
+
+  FetchCompleted();
+}
+
 int ProxyScriptFetcherImpl::Fetch(const GURL& url,
                                   string16* text,
                                   CompletionCallback* callback) {
@@ -99,7 +123,7 @@
   DCHECK(callback);
   DCHECK(text);
 
-  cur_request_.reset(new net::URLRequest(url, this));
+  cur_request_.reset(new URLRequest(url, this));
   cur_request_->set_context(url_request_context_);
   cur_request_->set_method("GET");
 
@@ -129,7 +153,7 @@
 }
 
 void ProxyScriptFetcherImpl::Cancel() {
-  // ResetCurRequestState will free the net::URLRequest, which will cause
+  // ResetCurRequestState will free the URLRequest, which will cause
   // cancellation.
   ResetCurRequestState();
 }
@@ -138,7 +162,7 @@
   return url_request_context_;
 }
 
-void ProxyScriptFetcherImpl::OnAuthRequired(net::URLRequest* request,
+void ProxyScriptFetcherImpl::OnAuthRequired(URLRequest* request,
                                             AuthChallengeInfo* auth_info) {
   DCHECK_EQ(request, cur_request_.get());
   // TODO(eroman):
@@ -147,7 +171,7 @@
   request->CancelAuth();
 }
 
-void ProxyScriptFetcherImpl::OnSSLCertificateError(net::URLRequest* request,
+void ProxyScriptFetcherImpl::OnSSLCertificateError(URLRequest* request,
                                                    int cert_error,
                                                    X509Certificate* cert) {
   DCHECK_EQ(request, cur_request_.get());
@@ -157,7 +181,7 @@
   request->Cancel();
 }
 
-void ProxyScriptFetcherImpl::OnResponseStarted(net::URLRequest* request) {
+void ProxyScriptFetcherImpl::OnResponseStarted(URLRequest* request) {
   DCHECK_EQ(request, cur_request_.get());
 
   if (!request->status().is_success()) {
@@ -191,7 +215,7 @@
   ReadBody(request);
 }
 
-void ProxyScriptFetcherImpl::OnReadCompleted(net::URLRequest* request,
+void ProxyScriptFetcherImpl::OnReadCompleted(URLRequest* request,
                                              int num_bytes) {
   DCHECK_EQ(request, cur_request_.get());
   if (ConsumeBytesRead(request, num_bytes)) {
@@ -200,18 +224,7 @@
   }
 }
 
-void ProxyScriptFetcherImpl::OnResponseCompleted(net::URLRequest* request) {
-  DCHECK_EQ(request, cur_request_.get());
-
-  // Use |result_code_| as the request's error if we have already set it to
-  // something specific.
-  if (result_code_ == OK && !request->status().is_success())
-    result_code_ = request->status().os_error();
-
-  FetchCompleted();
-}
-
-void ProxyScriptFetcherImpl::ReadBody(net::URLRequest* request) {
+void ProxyScriptFetcherImpl::ReadBody(URLRequest* request) {
   // Read as many bytes as are available synchronously.
   while (true) {
     int num_bytes;
@@ -226,7 +239,7 @@
   }
 }
 
-bool ProxyScriptFetcherImpl::ConsumeBytesRead(net::URLRequest* request,
+bool ProxyScriptFetcherImpl::ConsumeBytesRead(URLRequest* request,
                                               int num_bytes) {
   if (num_bytes <= 0) {
     // Error while reading, or EOF.
@@ -277,7 +290,7 @@
 }
 
 void ProxyScriptFetcherImpl::OnTimeout(int id) {
-  // Timeout tasks may outlive the net::URLRequest they reference. Make sure it
+  // Timeout tasks may outlive the URLRequest they reference. Make sure it
   // is still applicable.
   if (cur_request_id_ != id)
     return;
@@ -287,17 +300,4 @@
   cur_request_->Cancel();
 }
 
-base::TimeDelta ProxyScriptFetcherImpl::SetTimeoutConstraint(
-    base::TimeDelta timeout) {
-  base::TimeDelta prev = max_duration_;
-  max_duration_ = timeout;
-  return prev;
-}
-
-size_t ProxyScriptFetcherImpl::SetSizeConstraint(size_t size_bytes) {
-  size_t prev = max_response_bytes_;
-  max_response_bytes_ = size_bytes;
-  return prev;
-}
-
 }  // namespace net
diff --git a/net/proxy/proxy_script_fetcher_impl.h b/net/proxy/proxy_script_fetcher_impl.h
index bd141f3..e3abb55 100644
--- a/net/proxy/proxy_script_fetcher_impl.h
+++ b/net/proxy/proxy_script_fetcher_impl.h
@@ -25,7 +25,7 @@
 // Implementation of ProxyScriptFetcher that downloads scripts using the
 // specified request context.
 class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
-                               public net::URLRequest::Delegate {
+                               public URLRequest::Delegate {
  public:
   // Creates a ProxyScriptFetcher that issues requests through
   // |url_request_context|. |url_request_context| must remain valid for the
@@ -37,33 +37,35 @@
 
   virtual ~ProxyScriptFetcherImpl();
 
-  // ProxyScriptFetcher methods:
+  // Used by unit-tests to modify the default limits.
+  base::TimeDelta SetTimeoutConstraint(base::TimeDelta timeout);
+  size_t SetSizeConstraint(size_t size_bytes);
 
+  virtual void OnResponseCompleted(URLRequest* request);
+
+  // ProxyScriptFetcher methods:
   virtual int Fetch(const GURL& url, string16* text,
                     CompletionCallback* callback);
   virtual void Cancel();
   virtual URLRequestContext* GetRequestContext();
 
-  // net::URLRequest::Delegate methods:
-  virtual void OnAuthRequired(net::URLRequest* request,
+  // URLRequest::Delegate methods:
+  virtual void OnAuthRequired(URLRequest* request,
                               AuthChallengeInfo* auth_info);
-  virtual void OnSSLCertificateError(net::URLRequest* request, int cert_error,
+  virtual void OnSSLCertificateError(URLRequest* request, int cert_error,
                                      X509Certificate* cert);
-  virtual void OnResponseStarted(net::URLRequest* request);
-  virtual void OnReadCompleted(net::URLRequest* request, int num_bytes);
-  virtual void OnResponseCompleted(net::URLRequest* request);
-
-  // Used by unit-tests to modify the default limits.
-  base::TimeDelta SetTimeoutConstraint(base::TimeDelta timeout);
-  size_t SetSizeConstraint(size_t size_bytes);
+  virtual void OnResponseStarted(URLRequest* request);
+  virtual void OnReadCompleted(URLRequest* request, int num_bytes);
 
  private:
+  enum { kBufSize = 4096 };
+
   // Read more bytes from the response.
-  void ReadBody(net::URLRequest* request);
+  void ReadBody(URLRequest* request);
 
   // Handles a response from Read(). Returns true if we should continue trying
   // to read. |num_bytes| is 0 for EOF, and < 0 on errors.
-  bool ConsumeBytesRead(net::URLRequest* request, int num_bytes);
+  bool ConsumeBytesRead(URLRequest* request, int num_bytes);
 
   // Called once the request has completed to notify the caller of
   // |response_code_| and |response_text_|.
@@ -82,15 +84,14 @@
   // The context used for making network requests.
   URLRequestContext* url_request_context_;
 
-  // Buffer that net::URLRequest writes into.
-  enum { kBufSize = 4096 };
-  scoped_refptr<net::IOBuffer> buf_;
+  // Buffer that URLRequest writes into.
+  scoped_refptr<IOBuffer> buf_;
 
   // The next ID to use for |cur_request_| (monotonically increasing).
   int next_id_;
 
   // The current (in progress) request, or NULL.
-  scoped_ptr<net::URLRequest> cur_request_;
+  scoped_ptr<URLRequest> cur_request_;
 
   // State for current request (only valid when |cur_request_| is not NULL):
 
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index 043f71e..ce92986 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,14 +15,19 @@
 #include "net/base/test_completion_callback.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/http/http_cache.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/http/http_network_session.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
+namespace net {
+
 // TODO(eroman):
 //   - Test canceling an outstanding request.
 //   - Test deleting ProxyScriptFetcher while a request is in progress.
 
+namespace {
+
 const FilePath::CharType kDocRoot[] =
     FILE_PATH_LITERAL("net/data/proxy_script_fetcher_unittest");
 
@@ -35,20 +40,24 @@
 class RequestContext : public URLRequestContext {
  public:
   RequestContext() {
-    net::ProxyConfig no_proxy;
+    ProxyConfig no_proxy;
     host_resolver_ =
-        net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
+        CreateSystemHostResolver(HostResolver::kDefaultParallelism,
                                       NULL, NULL);
-    cert_verifier_ = new net::CertVerifier;
-    proxy_service_ = net::ProxyService::CreateFixed(no_proxy);
-    ssl_config_service_ = new net::SSLConfigServiceDefaults;
+    cert_verifier_ = new CertVerifier;
+    proxy_service_ = ProxyService::CreateFixed(no_proxy);
+    ssl_config_service_ = new SSLConfigServiceDefaults;
 
-    http_transaction_factory_ = new net::HttpCache(
-        net::HttpNetworkLayer::CreateFactory(host_resolver_, cert_verifier_,
-            NULL, NULL, NULL, proxy_service_, ssl_config_service_, NULL, NULL,
-            NULL),
-        NULL,
-        net::HttpCache::DefaultBackend::InMemory(0));
+    HttpNetworkSession::Params params;
+    params.host_resolver = host_resolver_;
+    params.cert_verifier = cert_verifier_;
+    params.proxy_service = proxy_service_;
+    params.ssl_config_service = ssl_config_service_;
+    scoped_refptr<HttpNetworkSession> network_session(
+        new HttpNetworkSession(params));
+    http_transaction_factory_ = new HttpCache(
+        network_session,
+        HttpCache::DefaultBackend::InMemory(0));
   }
 
  private:
@@ -59,9 +68,6 @@
   }
 };
 
-// Required to be in net namespace by FRIEND_TEST.
-namespace net {
-
 // Get a file:// url relative to net/data/proxy/proxy_script_fetcher_unittest.
 GURL GetTestFileUrl(const std::string& relpath) {
   FilePath path;
@@ -73,18 +79,20 @@
   return GURL(base_url.spec() + "/" + relpath);
 }
 
+}  // namespace
+
 class ProxyScriptFetcherImplTest : public PlatformTest {
  public:
   ProxyScriptFetcherImplTest()
-      : test_server_(net::TestServer::TYPE_HTTP, FilePath(kDocRoot)) {
+      : test_server_(TestServer::TYPE_HTTP, FilePath(kDocRoot)) {
   }
 
   static void SetUpTestCase() {
-    net::URLRequest::AllowFileAccess();
+    URLRequest::AllowFileAccess();
   }
 
  protected:
-  net::TestServer test_server_;
+  TestServer test_server_;
 };
 
 TEST_F(ProxyScriptFetcherImplTest, FileUrl) {
diff --git a/net/proxy/proxy_server.cc b/net/proxy/proxy_server.cc
index 0bcf89c..eb160dc 100644
--- a/net/proxy/proxy_server.cc
+++ b/net/proxy/proxy_server.cc
@@ -15,11 +15,12 @@
 
 namespace {
 
-// Parse the proxy type from a PAC string, to a ProxyServer::Scheme.
+// Parses the proxy type from a PAC string, to a ProxyServer::Scheme.
 // This mapping is case-insensitive. If no type could be matched
 // returns SCHEME_INVALID.
-ProxyServer::Scheme GetSchemeFromPacType(std::string::const_iterator begin,
-                                         std::string::const_iterator end) {
+ProxyServer::Scheme GetSchemeFromPacTypeInternal(
+    std::string::const_iterator begin,
+    std::string::const_iterator end) {
   if (LowerCaseEqualsASCII(begin, end, "proxy"))
     return ProxyServer::SCHEME_HTTP;
   if (LowerCaseEqualsASCII(begin, end, "socks")) {
@@ -40,11 +41,11 @@
   return ProxyServer::SCHEME_INVALID;
 }
 
-// Parse the proxy scheme from a URL-like representation, to a
-// ProxyServer::Scheme.  This corresponds with the values used in
+// Parses the proxy scheme from a URL-like representation, to a
+// ProxyServer::Scheme. This corresponds with the values used in
 // ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID.
-ProxyServer::Scheme GetSchemeFromURI(std::string::const_iterator begin,
-                                     std::string::const_iterator end) {
+ProxyServer::Scheme GetSchemeFromURIInternal(std::string::const_iterator begin,
+                                             std::string::const_iterator end) {
   if (LowerCaseEqualsASCII(begin, end, "http"))
     return ProxyServer::SCHEME_HTTP;
   if (LowerCaseEqualsASCII(begin, end, "socks4"))
@@ -110,7 +111,7 @@
       (end - colon) >= 3 &&
       *(colon + 1) == '/' &&
       *(colon + 2) == '/') {
-    scheme = GetSchemeFromURI(begin, colon);
+    scheme = GetSchemeFromURIInternal(begin, colon);
     begin = colon + 3;  // Skip past the "://"
   }
 
@@ -161,7 +162,7 @@
   }
 
   // Everything to the left of the space is the scheme.
-  Scheme scheme = GetSchemeFromPacType(begin, space);
+  Scheme scheme = GetSchemeFromPacTypeInternal(begin, space);
 
   // And everything to the right of the space is the
   // <host>[":" <port>].
@@ -204,6 +205,11 @@
 }
 
 // static
+ProxyServer::Scheme ProxyServer::GetSchemeFromURI(const std::string& scheme) {
+  return GetSchemeFromURIInternal(scheme.begin(), scheme.end());
+}
+
+// static
 ProxyServer ProxyServer::FromSchemeHostAndPort(
     Scheme scheme,
     std::string::const_iterator begin,
diff --git a/net/proxy/proxy_server.h b/net/proxy/proxy_server.h
index 3786ddb..3167252 100644
--- a/net/proxy/proxy_server.h
+++ b/net/proxy/proxy_server.h
@@ -128,6 +128,12 @@
   // scheme. Returns -1 if unknown.
   static int GetDefaultPortForScheme(Scheme scheme);
 
+  // Parses the proxy scheme from a URL-like representation, to a
+  // ProxyServer::Scheme. This corresponds with the values used in
+  // ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID.
+  // |scheme| can be one of http, https, socks, socks4, socks5, direct.
+  static Scheme GetSchemeFromURI(const std::string& scheme);
+
   bool operator==(const ProxyServer& other) const {
     return scheme_ == other.scheme_ &&
            host_port_pair_.Equals(other.host_port_pair_);
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc
index 7dec769..95f8bbc 100644
--- a/net/proxy/proxy_service_unittest.cc
+++ b/net/proxy/proxy_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -132,7 +132,7 @@
   EXPECT_TRUE(info.is_direct());
 
   // Check the NetLog was filled correctly.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(3u, entries.size());
@@ -179,7 +179,7 @@
   EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
 
   // Check the NetLog was filled correctly.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_EQ(5u, entries.size());
@@ -1157,7 +1157,7 @@
   EXPECT_FALSE(callback1.have_result());  // Cancelled.
   EXPECT_FALSE(callback2.have_result());  // Cancelled.
 
-  net::CapturingNetLog::EntryList entries1;
+  CapturingNetLog::EntryList entries1;
   log1.GetEntries(&entries1);
 
   // Check the NetLog for request 1 (which was cancelled) got filled properly.
@@ -1690,7 +1690,7 @@
   // In particular, PROXY_CONFIG_CHANGED should have only been emitted once
   // (for the initial setup), and NOT a second time when the IP address
   // changed.
-  net::CapturingNetLog::EntryList entries;
+  CapturingNetLog::EntryList entries;
   log.GetEntries(&entries);
 
   EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
diff --git a/net/proxy/sync_host_resolver_bridge.cc b/net/proxy/sync_host_resolver_bridge.cc
index 37a847f..80270f6 100644
--- a/net/proxy/sync_host_resolver_bridge.cc
+++ b/net/proxy/sync_host_resolver_bridge.cc
@@ -6,8 +6,8 @@
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
-#include "base/lock.h"
 #include "base/message_loop.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_log.h"
@@ -26,7 +26,7 @@
 
   // Returns true if Shutdown() has been called.
   bool HasShutdown() const {
-    AutoLock l(lock_);
+    base::AutoLock l(lock_);
     return HasShutdownLocked();
   }
 
@@ -66,7 +66,7 @@
   bool has_shutdown_;
 
   // Mutex to guard accesses to |has_shutdown_|.
-  mutable Lock lock_;
+      mutable base::Lock lock_;
 
   DISALLOW_COPY_AND_ASSIGN(Core);
 };
@@ -121,7 +121,7 @@
   event_.Wait();
 
   {
-    AutoLock l(lock_);
+    base::AutoLock l(lock_);
     if (HasShutdownLocked())
       return ERR_ABORTED;
     event_.Reset();
@@ -139,7 +139,7 @@
   }
 
   {
-    AutoLock l(lock_);
+    base::AutoLock l(lock_);
     has_shutdown_ = true;
   }
 
diff --git a/net/server/http_listen_socket.cc b/net/server/http_listen_socket.cc
deleted file mode 100644
index a946bd9..0000000
--- a/net/server/http_listen_socket.cc
+++ /dev/null
@@ -1,357 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <arpa/inet.h>
-#endif
-
-#include <map>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/md5.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "net/server/http_listen_socket.h"
-#include "net/server/http_server_request_info.h"
-
-// must run in the IO thread
-HttpListenSocket::HttpListenSocket(SOCKET s,
-                                   HttpListenSocket::Delegate* delegate)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(ListenSocket(s, this)),
-      delegate_(delegate),
-      is_web_socket_(false) {
-}
-
-// must run in the IO thread
-HttpListenSocket::~HttpListenSocket() {
-}
-
-void HttpListenSocket::Accept() {
-  SOCKET conn = ListenSocket::Accept(socket_);
-  DCHECK_NE(conn, ListenSocket::kInvalidSocket);
-  if (conn == ListenSocket::kInvalidSocket) {
-    // TODO
-  } else {
-    scoped_refptr<HttpListenSocket> sock(
-        new HttpListenSocket(conn, delegate_));
-#if defined(OS_POSIX)
-      sock->WatchSocket(WAITING_READ);
-#endif
-    // it's up to the delegate to AddRef if it wants to keep it around
-    DidAccept(this, sock);
-  }
-}
-
-HttpListenSocket* HttpListenSocket::Listen(
-    const std::string& ip,
-    int port,
-    HttpListenSocket::Delegate* delegate) {
-  SOCKET s = ListenSocket::Listen(ip, port);
-  if (s == ListenSocket::kInvalidSocket) {
-    // TODO (ibrar): error handling
-  } else {
-    HttpListenSocket *serv = new HttpListenSocket(s, delegate);
-    serv->Listen();
-    return serv;
-  }
-  return NULL;
-}
-
-std::string GetHeaderValue(
-    const HttpServerRequestInfo& request,
-    const std::string& header_name) {
-  HttpServerRequestInfo::HeadersMap::iterator it =
-      request.headers.find(header_name);
-  if (it != request.headers.end())
-    return it->second;
-  return "";
-}
-
-uint32 WebSocketKeyFingerprint(const std::string& str) {
-  std::string result;
-  const char* pChar = str.c_str();
-  int length = str.length();
-  int spaces = 0;
-  for (int i = 0; i < length; ++i) {
-    if (pChar[i] >= '0' && pChar[i] <= '9')
-      result.append(&pChar[i], 1);
-    else if (pChar[i] == ' ')
-      spaces++;
-  }
-  if (spaces == 0)
-    return 0;
-  int64 number = 0;
-  if (!base::StringToInt64(result, &number))
-    return 0;
-  return htonl(static_cast<uint32>(number / spaces));
-}
-
-void HttpListenSocket::AcceptWebSocket(const HttpServerRequestInfo& request) {
-  std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1");
-  std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2");
-
-  uint32 fp1 = WebSocketKeyFingerprint(key1);
-  uint32 fp2 = WebSocketKeyFingerprint(key2);
-
-  char data[16];
-  memcpy(data, &fp1, 4);
-  memcpy(data + 4, &fp2, 4);
-  memcpy(data + 8, &request.data[0], 8);
-
-  MD5Digest digest;
-  MD5Sum(data, 16, &digest);
-
-  std::string origin = GetHeaderValue(request, "Origin");
-  std::string host = GetHeaderValue(request, "Host");
-  std::string location = "ws://" + host + request.path;
-  is_web_socket_ = true;
-  Send(base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
-                          "Upgrade: WebSocket\r\n"
-                          "Connection: Upgrade\r\n"
-                          "Sec-WebSocket-Origin: %s\r\n"
-                          "Sec-WebSocket-Location: %s\r\n"
-                          "\r\n",
-                          origin.c_str(),
-                          location.c_str()));
-  Send(reinterpret_cast<char*>(digest.a), 16);
-}
-
-void HttpListenSocket::SendOverWebSocket(const std::string& data) {
-  DCHECK(is_web_socket_);
-  char message_start = 0;
-  char message_end = -1;
-  Send(&message_start, 1);
-  Send(data);
-  Send(&message_end, 1);
-}
-
-void HttpListenSocket::Send200(const std::string& data,
-                               const std::string& content_type) {
-  Send(base::StringPrintf("HTTP/1.1 200 OK\r\n"
-                          "Content-Type:%s\r\n"
-                          "Content-Length:%d\r\n"
-                          "\r\n",
-                          content_type.c_str(),
-                          static_cast<int>(data.length())));
-  Send(data);
-}
-
-void HttpListenSocket::Send404() {
-  Send("HTTP/1.1 404 Not Found\r\n"
-       "Content-Length: 0\r\n"
-       "\r\n");
-}
-
-void HttpListenSocket::Send500(const std::string& message) {
-  Send(base::StringPrintf("HTTP/1.1 500 Internal Error\r\n"
-                          "Content-Type:text/html\r\n"
-                          "Content-Length:%d\r\n"
-                          "\r\n"
-                          "%s",
-                          static_cast<int>(message.length()),
-                          message.c_str()));
-}
-
-//
-// HTTP Request Parser
-// This HTTP request parser uses a simple state machine to quickly parse
-// through the headers.  The parser is not 100% complete, as it is designed
-// for use in this simple test driver.
-//
-// Known issues:
-//   - does not handle whitespace on first HTTP line correctly.  Expects
-//     a single space between the method/url and url/protocol.
-
-// Input character types.
-enum header_parse_inputs {
-  INPUT_SPACE,
-  INPUT_CR,
-  INPUT_LF,
-  INPUT_COLON,
-  INPUT_00,
-  INPUT_FF,
-  INPUT_DEFAULT,
-  MAX_INPUTS,
-};
-
-// Parser states.
-enum header_parse_states {
-  ST_METHOD,     // Receiving the method
-  ST_URL,        // Receiving the URL
-  ST_PROTO,      // Receiving the protocol
-  ST_HEADER,     // Starting a Request Header
-  ST_NAME,       // Receiving a request header name
-  ST_SEPARATOR,  // Receiving the separator between header name and value
-  ST_VALUE,      // Receiving a request header value
-  ST_WS_READY,   // Ready to receive web socket frame
-  ST_WS_FRAME,   // Receiving WebSocket frame
-  ST_WS_CLOSE,   // Closing the connection WebSocket connection
-  ST_DONE,       // Parsing is complete and successful
-  ST_ERR,        // Parsing encountered invalid syntax.
-  MAX_STATES
-};
-
-// State transition table
-int parser_state[MAX_STATES][MAX_INPUTS] = {
-/* METHOD    */ { ST_URL,       ST_ERR,      ST_ERR,      ST_ERR,       ST_ERR,      ST_ERR,      ST_METHOD },
-/* URL       */ { ST_PROTO,     ST_ERR,      ST_ERR,      ST_URL,       ST_ERR,      ST_ERR,      ST_URL },
-/* PROTOCOL  */ { ST_ERR,       ST_HEADER,   ST_NAME,     ST_ERR,       ST_ERR,      ST_ERR,      ST_PROTO },
-/* HEADER    */ { ST_ERR,       ST_ERR,      ST_NAME,     ST_ERR,       ST_ERR,      ST_ERR,      ST_ERR },
-/* NAME      */ { ST_SEPARATOR, ST_DONE,     ST_ERR,      ST_SEPARATOR, ST_ERR,      ST_ERR,      ST_NAME },
-/* SEPARATOR */ { ST_SEPARATOR, ST_ERR,      ST_ERR,      ST_SEPARATOR, ST_ERR,      ST_ERR,      ST_VALUE },
-/* VALUE     */ { ST_VALUE,     ST_HEADER,   ST_NAME,     ST_VALUE,     ST_ERR,      ST_ERR,      ST_VALUE },
-/* WS_READY  */ { ST_ERR,       ST_ERR,      ST_ERR,      ST_ERR,       ST_WS_FRAME, ST_WS_CLOSE, ST_ERR},
-/* WS_FRAME  */ { ST_WS_FRAME,  ST_WS_FRAME, ST_WS_FRAME, ST_WS_FRAME,  ST_ERR,      ST_WS_READY, ST_WS_FRAME },
-/* WS_CLOSE  */ { ST_ERR,       ST_ERR,      ST_ERR,      ST_ERR,       ST_WS_CLOSE, ST_ERR,      ST_ERR },
-/* DONE      */ { ST_DONE,      ST_DONE,     ST_DONE,     ST_DONE,      ST_DONE,     ST_DONE,     ST_DONE },
-/* ERR       */ { ST_ERR,       ST_ERR,      ST_ERR,      ST_ERR,       ST_ERR,      ST_ERR,      ST_ERR }
-};
-
-// Convert an input character to the parser's input token.
-int charToInput(char ch) {
-  switch(ch) {
-    case ' ':
-      return INPUT_SPACE;
-    case '\r':
-      return INPUT_CR;
-    case '\n':
-      return INPUT_LF;
-    case ':':
-      return INPUT_COLON;
-    case 0x0:
-      return INPUT_00;
-    case static_cast<char>(-1):
-      return INPUT_FF;
-  }
-  return INPUT_DEFAULT;
-}
-
-bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) {
-  int pos = 0;
-  int data_len = recv_data_.length();
-  int state = is_web_socket_ ? ST_WS_READY : ST_METHOD;
-  std::string buffer;
-  std::string header_name;
-  std::string header_value;
-  while (pos < data_len) {
-    char ch = recv_data_[pos++];
-    int input = charToInput(ch);
-    int next_state = parser_state[state][input];
-
-    bool transition = (next_state != state);
-    if (transition) {
-      // Do any actions based on state transitions.
-      switch (state) {
-        case ST_METHOD:
-          info->method = buffer;
-          buffer.clear();
-          break;
-        case ST_URL:
-          info->path = buffer;
-          buffer.clear();
-          break;
-        case ST_PROTO:
-          // TODO(mbelshe): Deal better with parsing protocol.
-          DCHECK(buffer == "HTTP/1.1");
-          buffer.clear();
-          break;
-        case ST_NAME:
-          header_name = buffer;
-          buffer.clear();
-          break;
-        case ST_VALUE:
-          header_value = buffer;
-          // TODO(mbelshe): Deal better with duplicate headers
-          DCHECK(info->headers.find(header_name) == info->headers.end());
-          info->headers[header_name] = header_value;
-          buffer.clear();
-          break;
-        case ST_SEPARATOR:
-          buffer.append(&ch, 1);
-          break;
-        case ST_WS_FRAME:
-          recv_data_ = recv_data_.substr(pos);
-          info->data = buffer;
-          buffer.clear();
-          return true;
-          break;
-      }
-      state = next_state;
-    } else {
-      // Do any actions based on current state
-      switch (state) {
-        case ST_METHOD:
-        case ST_URL:
-        case ST_PROTO:
-        case ST_VALUE:
-        case ST_NAME:
-        case ST_WS_FRAME:
-          buffer.append(&ch, 1);
-          break;
-        case ST_DONE:
-          recv_data_ = recv_data_.substr(pos);
-          info->data = recv_data_;
-          recv_data_.clear();
-          return true;
-        case ST_WS_CLOSE:
-          is_web_socket_ = false;
-          return false;
-        case ST_ERR:
-          return false;
-      }
-    }
-  }
-  // No more characters, but we haven't finished parsing yet.
-  return false;
-}
-
-void HttpListenSocket::Close() {
-  ListenSocket::Close();
-}
-
-void HttpListenSocket::Listen() {
-  ListenSocket::Listen();
-}
-
-void HttpListenSocket::DidAccept(ListenSocket* server,
-                                 ListenSocket* connection) {
-  connection->AddRef();
-}
-
-void HttpListenSocket::DidRead(ListenSocket*,
-                               const char* data,
-                               int len) {
-  recv_data_.append(data, len);
-  while (recv_data_.length()) {
-    HttpServerRequestInfo request;
-    if (!ParseHeaders(&request))
-      break;
-
-    if (is_web_socket_) {
-      delegate_->OnWebSocketMessage(this, request.data);
-      continue;
-    }
-
-    std::string connection = GetHeaderValue(request, "Connection");
-    if (connection == "Upgrade") {
-      // Is this WebSocket and if yes, upgrade the connection.
-      std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1");
-      std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2");
-      if (!key1.empty() && !key2.empty()) {
-        delegate_->OnWebSocketRequest(this, request);
-        continue;
-      }
-    }
-    delegate_->OnHttpRequest(this, request);
-  }
-}
-
-void HttpListenSocket::DidClose(ListenSocket* sock) {
-  delegate_->OnClose(this);
-  sock->Release();
-}
diff --git a/net/server/http_listen_socket.h b/net/server/http_listen_socket.h
deleted file mode 100644
index 8b0bbc2..0000000
--- a/net/server/http_listen_socket.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SERVER_HTTP_LISTEN_SOCKET_H_
-#define NET_SERVER_HTTP_LISTEN_SOCKET_H_
-#pragma once
-
-#include "net/base/listen_socket.h"
-
-class HttpServerRequestInfo;
-
-// Implements a simple HTTP listen socket on top of the raw socket interface.
-class HttpListenSocket : public ListenSocket,
-                         public ListenSocket::ListenSocketDelegate {
- public:
-  class Delegate {
-   public:
-    virtual void OnHttpRequest(HttpListenSocket* socket,
-                               const HttpServerRequestInfo& info) = 0;
-
-    virtual void OnWebSocketRequest(HttpListenSocket* socket,
-                                    const HttpServerRequestInfo& info) = 0;
-
-    virtual void OnWebSocketMessage(HttpListenSocket* socket,
-                                    const std::string& data) = 0;
-
-    virtual void OnClose(HttpListenSocket* socket) = 0;
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  virtual void Accept();
-
-  static HttpListenSocket* Listen(const std::string& ip,
-                                  int port,
-                                  HttpListenSocket::Delegate* delegate);
-
-  void AcceptWebSocket(const HttpServerRequestInfo& request);
-
-  void SendOverWebSocket(const std::string& data);
-
-  void Send200(const std::string& data, const std::string& mime_type);
-  void Send404();
-  void Send500(const std::string& message);
-
-  virtual void Close();
-  virtual void Listen();
-
-  // ListenSocketDelegate
-  virtual void DidAccept(ListenSocket* server, ListenSocket* connection);
-  virtual void DidRead(ListenSocket* connection, const char* data, int len);
-  virtual void DidClose(ListenSocket* sock);
-
- private:
-  static const int kReadBufSize = 16 * 1024;
-  HttpListenSocket(SOCKET s, HttpListenSocket::Delegate* del);
-  virtual ~HttpListenSocket();
-
-  // Expects the raw data to be stored in recv_data_. If parsing is successful,
-  // will remove the data parsed from recv_data_, leaving only the unused
-  // recv data.
-  bool ParseHeaders(HttpServerRequestInfo* info);
-
-  HttpListenSocket::Delegate* delegate_;
-  bool is_web_socket_;
-  std::string recv_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(HttpListenSocket);
-};
-
-#endif // NET_SERVER_HTTP_LISTEN_SOCKET_H_
diff --git a/net/socket/client_socket.cc b/net/socket/client_socket.cc
index 6b12841..3792c5c 100644
--- a/net/socket/client_socket.cc
+++ b/net/socket/client_socket.cc
@@ -66,42 +66,6 @@
   // are intentionally preserved.
 }
 
-void ClientSocket::UseHistory::EmitPreconnectionHistograms() const {
-  DCHECK(!subresource_speculation_ || !omnibox_speculation_);
-  // 0 ==> non-speculative, never connected.
-  // 1 ==> non-speculative never used (but connected).
-  // 2 ==> non-speculative and used.
-  // 3 ==> omnibox_speculative never connected.
-  // 4 ==> omnibox_speculative never used (but connected).
-  // 5 ==> omnibox_speculative and used.
-  // 6 ==> subresource_speculative never connected.
-  // 7 ==> subresource_speculative never used (but connected).
-  // 8 ==> subresource_speculative and used.
-  int result;
-  if (was_used_to_convey_data_)
-    result = 2;
-  else if (was_ever_connected_)
-    result = 1;
-  else
-    result = 0;  // Never used, and not really connected.
-
-  if (omnibox_speculation_)
-    result += 3;
-  else if (subresource_speculation_)
-    result += 6;
-  UMA_HISTOGRAM_ENUMERATION("Net.PreconnectUtilization2", result, 9);
-
-  static const bool connect_backup_jobs_fieldtrial =
-      base::FieldTrialList::Find("ConnnectBackupJobs") &&
-      !base::FieldTrialList::Find("ConnnectBackupJobs")->group_name().empty();
-  if (connect_backup_jobs_fieldtrial) {
-    UMA_HISTOGRAM_ENUMERATION(
-        base::FieldTrial::MakeName("Net.PreconnectUtilization2",
-                                   "ConnnectBackupJobs"),
-        result, 9);
-  }
-}
-
 void ClientSocket::UseHistory::set_was_ever_connected() {
   DCHECK(!was_used_to_convey_data_);
   was_ever_connected_ = true;
@@ -144,6 +108,42 @@
   return was_used_to_convey_data_;
 }
 
+void ClientSocket::UseHistory::EmitPreconnectionHistograms() const {
+  DCHECK(!subresource_speculation_ || !omnibox_speculation_);
+  // 0 ==> non-speculative, never connected.
+  // 1 ==> non-speculative never used (but connected).
+  // 2 ==> non-speculative and used.
+  // 3 ==> omnibox_speculative never connected.
+  // 4 ==> omnibox_speculative never used (but connected).
+  // 5 ==> omnibox_speculative and used.
+  // 6 ==> subresource_speculative never connected.
+  // 7 ==> subresource_speculative never used (but connected).
+  // 8 ==> subresource_speculative and used.
+  int result;
+  if (was_used_to_convey_data_)
+    result = 2;
+  else if (was_ever_connected_)
+    result = 1;
+  else
+    result = 0;  // Never used, and not really connected.
+
+  if (omnibox_speculation_)
+    result += 3;
+  else if (subresource_speculation_)
+    result += 6;
+  UMA_HISTOGRAM_ENUMERATION("Net.PreconnectUtilization2", result, 9);
+
+  static const bool connect_backup_jobs_fieldtrial =
+      base::FieldTrialList::Find("ConnnectBackupJobs") &&
+      !base::FieldTrialList::Find("ConnnectBackupJobs")->group_name().empty();
+  if (connect_backup_jobs_fieldtrial) {
+    UMA_HISTOGRAM_ENUMERATION(
+        base::FieldTrial::MakeName("Net.PreconnectUtilization2",
+                                   "ConnnectBackupJobs"),
+        result, 9);
+  }
+}
+
 void ClientSocket::LogByteTransfer(const BoundNetLog& net_log,
                                    NetLog::EventType event_type,
                                    int byte_count,
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index f4da066..dd201f9 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -79,17 +79,6 @@
 
 }  // namespace
 
-// static
-ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
-  return g_default_client_socket_factory.Pointer();
-}
-
-// static
-void ClientSocketFactory::SetSSLClientSocketFactory(
-    SSLClientSocketFactory factory) {
-  g_ssl_factory = factory;
-}
-
 // Deprecated function (http://crbug.com/37810) that takes a ClientSocket.
 SSLClientSocket* ClientSocketFactory::CreateSSLClientSocket(
     ClientSocket* transport_socket,
@@ -104,4 +93,15 @@
                                NULL /* DnsCertProvenanceChecker */);
 }
 
+// static
+ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
+  return g_default_client_socket_factory.Pointer();
+}
+
+// static
+void ClientSocketFactory::SetSSLClientSocketFactory(
+    SSLClientSocketFactory factory) {
+  g_ssl_factory = factory;
+}
+
 }  // namespace net
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h
index 406b9bb..8c5da88 100644
--- a/net/socket/client_socket_handle.h
+++ b/net/socket/client_socket_handle.h
@@ -31,12 +31,12 @@
 //
 class ClientSocketHandle {
  public:
-  typedef enum {
+  enum SocketReuseType {
     UNUSED = 0,   // unused socket that just finished connecting
     UNUSED_IDLE,  // unused socket that has been idle for awhile
     REUSED_IDLE,  // previously used socket
     NUM_TYPES,
-  } SocketReuseType;
+  };
 
   ClientSocketHandle();
   ~ClientSocketHandle();
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 871966f..de7ac05 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -114,10 +114,8 @@
 }
 
 void ConnectJob::LogConnectCompletion(int net_error) {
-  scoped_refptr<NetLog::EventParameters> params;
-  if (net_error != OK)
-    params = new NetLogIntegerParameter("net_error", net_error);
-  net_log().EndEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT, params);
+  net_log().EndEventWithNetErrorCode(
+      NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT, net_error);
 }
 
 void ConnectJob::OnTimeout() {
@@ -222,7 +220,7 @@
 
   int rv = RequestSocketInternal(group_name, request);
   if (rv != ERR_IO_PENDING) {
-    request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, NULL);
+    request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv);
     CHECK(!request->handle()->is_initialized());
     delete request;
   } else {
@@ -252,12 +250,11 @@
   // RequestSocketsInternal() may delete the group.
   bool deleted_group = false;
 
+  int rv = OK;
   for (int num_iterations_left = num_sockets;
        group->NumActiveSocketSlots() < num_sockets &&
        num_iterations_left > 0 ; num_iterations_left--) {
-    int rv = RequestSocketInternal(group_name, &request);
-    // TODO(willchan): Possibly check for ERR_PRECONNECT_MAX_SOCKET_LIMIT so we
-    // can log it into the NetLog.
+    rv = RequestSocketInternal(group_name, &request);
     if (rv < 0 && rv != ERR_IO_PENDING) {
       // We're encountering a synchronous error.  Give up.
       if (!ContainsKey(group_map_, group_name))
@@ -276,8 +273,10 @@
   if (!deleted_group && group->IsEmpty())
     RemoveGroup(group_name);
 
-  request.net_log().EndEvent(
-      NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS, NULL);
+  if (rv == ERR_IO_PENDING)
+    rv = OK;
+  request.net_log().EndEventWithNetErrorCode(
+      NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS, rv);
 }
 
 int ClientSocketPoolBaseHelper::RequestSocketInternal(
@@ -359,8 +358,12 @@
     group->AddJob(connect_job.release());
   } else {
     LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
-    connect_job->GetAdditionalErrorState(handle);
-    ClientSocket* error_socket = connect_job->ReleaseSocket();
+    ClientSocket* error_socket = NULL;
+    if (!preconnecting) {
+      DCHECK(handle);
+      connect_job->GetAdditionalErrorState(handle);
+      error_socket = connect_job->ReleaseSocket();
+    }
     if (error_socket) {
       HandOutSocket(error_socket, false /* not reused */, handle,
                     base::TimeDelta(), group, request->net_log());
@@ -798,8 +801,8 @@
         HandOutSocket(socket.release(), false /* unused socket */, r->handle(),
                       base::TimeDelta(), group, r->net_log());
       }
-      r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, make_scoped_refptr(
-          new NetLogIntegerParameter("net_error", result)));
+      r->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL,
+                                            result);
       InvokeUserCallbackLater(r->handle(), r->callback(), result);
     } else {
       RemoveConnectJob(job, group);
@@ -859,10 +862,7 @@
     if (group->IsEmpty())
       RemoveGroup(group_name);
 
-    scoped_refptr<NetLog::EventParameters> params;
-    if (rv != OK)
-      params = new NetLogIntegerParameter("net_error", rv);
-    request->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL, params);
+    request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv);
     InvokeUserCallbackLater(
         request->handle(), request->callback(), rv);
   }
diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h
index dbb3dc4..e35e93f 100644
--- a/net/socket/client_socket_pool_base.h
+++ b/net/socket/client_socket_pool_base.h
@@ -158,14 +158,14 @@
     : public ConnectJob::Delegate,
       public NetworkChangeNotifier::Observer {
  public:
+  typedef uint32 Flags;
+
   // Used to specify specific behavior for the ClientSocketPool.
   enum Flag {
     NORMAL = 0,  // Normal behavior.
     NO_IDLE_SOCKETS = 0x1,  // Do not return an idle socket. Create a new one.
   };
 
-  typedef uint32 Flags;
-
   class Request {
    public:
     Request(ClientSocketHandle* handle,
@@ -270,12 +270,6 @@
     return ClientSocketPool::kMaxConnectRetryIntervalMs;
   }
 
-  // ConnectJob::Delegate methods:
-  virtual void OnConnectJobComplete(int result, ConnectJob* job);
-
-  // NetworkChangeNotifier::Observer methods:
-  virtual void OnIPAddressChanged();
-
   int NumConnectJobsInGroup(const std::string& group_name) const {
     return group_map_.find(group_name)->second->jobs().size();
   }
@@ -301,14 +295,18 @@
   static void set_connect_backup_jobs_enabled(bool enabled);
   void EnableConnectBackupJobs();
 
+  // ConnectJob::Delegate methods:
+  virtual void OnConnectJobComplete(int result, ConnectJob* job);
+
+  // NetworkChangeNotifier::Observer methods:
+  virtual void OnIPAddressChanged();
+
  private:
   friend class base::RefCounted<ClientSocketPoolBaseHelper>;
 
   // Entry for a persistent socket which became idle at time |start_time|.
   struct IdleSocket {
     IdleSocket() : socket(NULL) {}
-    ClientSocket* socket;
-    base::TimeTicks start_time;
 
     // An idle socket should be removed if it can't be reused, or has been idle
     // for too long. |now| is the current time value (TimeTicks::Now()).
@@ -319,6 +317,9 @@
     // mistaken for the beginning of the next response if we were to reuse the
     // socket for a new request.
     bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
+
+    ClientSocket* socket;
+    base::TimeTicks start_time;
   };
 
   typedef std::deque<const Request* > RequestQueue;
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index c6092d7..803966b 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -2928,6 +2928,13 @@
                         BoundNetLog());
 
   ASSERT_FALSE(pool_->HasGroup("a"));
+
+  connect_job_factory_->set_job_type(
+      TestConnectJob::kMockAdditionalErrorStateJob);
+  pool_->RequestSockets("a", &params_, kDefaultMaxSocketsPerGroup,
+                        BoundNetLog());
+
+  ASSERT_FALSE(pool_->HasGroup("a"));
 }
 
 TEST_F(ClientSocketPoolBaseTest, RequestSocketsMultipleTimesDoesNothing) {
diff --git a/net/socket/dns_cert_provenance_checker.cc b/net/socket/dns_cert_provenance_checker.cc
index 665a16a..33487c5 100644
--- a/net/socket/dns_cert_provenance_checker.cc
+++ b/net/socket/dns_cert_provenance_checker.cc
@@ -218,6 +218,22 @@
 
 }  // namespace
 
+DnsCertProvenanceChecker::Delegate::~Delegate() {
+}
+
+DnsCertProvenanceChecker::~DnsCertProvenanceChecker() {
+}
+
+void DnsCertProvenanceChecker::DoAsyncLookup(
+    const std::string& hostname,
+    const std::vector<base::StringPiece>& der_certs,
+    DnsRRResolver* dnsrr_resolver,
+    Delegate* delegate) {
+  DnsCertProvenanceCheck* check = new DnsCertProvenanceCheck(
+      hostname, dnsrr_resolver, delegate, der_certs);
+  check->Start();
+}
+
 // static
 std::string DnsCertProvenanceChecker::BuildEncryptedReport(
     const std::string& hostname,
@@ -318,32 +334,16 @@
                      outer.size());
 }
 
-void DnsCertProvenanceChecker::DoAsyncLookup(
-    const std::string& hostname,
-    const std::vector<base::StringPiece>& der_certs,
-    DnsRRResolver* dnsrr_resolver,
-    Delegate* delegate) {
-  DnsCertProvenanceCheck* check = new DnsCertProvenanceCheck(
-      hostname, dnsrr_resolver, delegate, der_certs);
-  check->Start();
-}
-
-DnsCertProvenanceChecker::Delegate::~Delegate() {
-}
-
-DnsCertProvenanceChecker::~DnsCertProvenanceChecker() {
-}
-
 }  // namespace net
 
 #else  // USE_OPENSSL
 
 namespace net {
 
-std::string DnsCertProvenanceChecker::BuildEncryptedReport(
-    const std::string& hostname,
-    const std::vector<std::string>& der_certs) {
-  return "";
+DnsCertProvenanceChecker::Delegate::~Delegate() {
+}
+
+DnsCertProvenanceChecker::~DnsCertProvenanceChecker() {
 }
 
 void DnsCertProvenanceChecker::DoAsyncLookup(
@@ -353,10 +353,10 @@
     Delegate* delegate) {
 }
 
-DnsCertProvenanceChecker::Delegate::~Delegate() {
-}
-
-DnsCertProvenanceChecker::~DnsCertProvenanceChecker() {
+std::string DnsCertProvenanceChecker::BuildEncryptedReport(
+    const std::string& hostname,
+    const std::vector<std::string>& der_certs) {
+  return "";
 }
 
 }  // namespace net
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc
index 1ad1f1c..f791574 100644
--- a/net/socket/nss_ssl_util.cc
+++ b/net/socket/nss_ssl_util.cc
@@ -9,6 +9,8 @@
 #include <ssl.h>
 #include <sslerr.h>
 
+#include <string>
+
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/nss_util.h"
@@ -155,6 +157,16 @@
 
     case SEC_ERROR_INVALID_ARGS:
       return ERR_INVALID_ARGUMENT;
+    case SEC_ERROR_NO_KEY:
+      return ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY;
+    case SEC_ERROR_INVALID_KEY:
+    case SSL_ERROR_SIGN_HASHES_FAILURE:
+      return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+    // A handshake (initial or renegotiation) may fail because some signature
+    // (for example, the signature in the ServerKeyExchange message for an
+    // ephemeral Diffie-Hellman cipher suite) is invalid.
+    case SEC_ERROR_BAD_SIGNATURE:
+      return ERR_SSL_PROTOCOL_ERROR;
 
     case SSL_ERROR_SSL_DISABLED:
       return ERR_NO_SSL_VERSIONS_ENABLED;
@@ -176,12 +188,11 @@
 
     default: {
       if (IS_SSL_ERROR(err)) {
-        LOG(WARNING) << "Unknown SSL error " << err <<
-            " mapped to net::ERR_SSL_PROTOCOL_ERROR";
+        LOG(WARNING) << "Unknown SSL error " << err
+                     << " mapped to net::ERR_SSL_PROTOCOL_ERROR";
         return ERR_SSL_PROTOCOL_ERROR;
       }
-      LOG(WARNING) << "Unknown error " << err <<
-          " mapped to net::ERR_FAILED";
+      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
       return ERR_FAILED;
     }
   }
@@ -193,10 +204,6 @@
     // If the server closed on us, it is a protocol error.
     // Some TLS-intolerant servers do this when we request TLS.
     case PR_END_OF_FILE_ERROR:
-    // The handshake may fail because some signature (for example, the
-    // signature in the ServerKeyExchange message for an ephemeral
-    // Diffie-Hellman cipher suite) is invalid.
-    case SEC_ERROR_BAD_SIGNATURE:
       return ERR_SSL_PROTOCOL_ERROR;
     default:
       return MapNSSError(err);
diff --git a/net/socket/nss_ssl_util.h b/net/socket/nss_ssl_util.h
index 64bf3cf..2a53fc7 100644
--- a/net/socket/nss_ssl_util.h
+++ b/net/socket/nss_ssl_util.h
@@ -6,7 +6,7 @@
 // ssl_server_socket_nss.cc to share common functions of NSS.
 
 #ifndef NET_SOCKET_NSS_SSL_UTIL_H_
-#define NEt_SOCKET_NSS_SSL_UTIL_H_
+#define NET_SOCKET_NSS_SSL_UTIL_H_
 
 #include <prerror.h>
 
@@ -28,7 +28,7 @@
 // Map NSS error code to network error code.
 int MapNSSError(PRErrorCode err);
 
-// Map NSS handshake error to network error code.
+// Map NSS error code from the first SSL handshake to network error code.
 int MapNSSHandshakeError(PRErrorCode err);
 
 }  // namespace net
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index d88399d..d5ee9ae 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -15,6 +15,7 @@
 #include "net/base/address_family.h"
 #include "net/base/auth.h"
 #include "net/base/host_resolver_proc.h"
+#include "net/base/ssl_cert_request_info.h"
 #include "net/base/ssl_info.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_request_headers.h"
@@ -115,439 +116,6 @@
 
 }  // namespace
 
-MockClientSocket::MockClientSocket(net::NetLog* net_log)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
-      connected_(false),
-      net_log_(NetLog::Source(), net_log) {
-}
-
-void MockClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
-  NOTREACHED();
-}
-
-void MockClientSocket::GetSSLCertRequestInfo(
-    net::SSLCertRequestInfo* cert_request_info) {
-}
-
-SSLClientSocket::NextProtoStatus
-MockClientSocket::GetNextProto(std::string* proto) {
-  proto->clear();
-  return SSLClientSocket::kNextProtoUnsupported;
-}
-
-void MockClientSocket::Disconnect() {
-  connected_ = false;
-}
-
-bool MockClientSocket::IsConnected() const {
-  return connected_;
-}
-
-bool MockClientSocket::IsConnectedAndIdle() const {
-  return connected_;
-}
-
-int MockClientSocket::GetPeerAddress(AddressList* address) const {
-  return net::SystemHostResolverProc("localhost", ADDRESS_FAMILY_UNSPECIFIED,
-                                     0, address, NULL);
-}
-
-void MockClientSocket::RunCallbackAsync(net::CompletionCallback* callback,
-                                        int result) {
-  MessageLoop::current()->PostTask(FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &MockClientSocket::RunCallback, callback, result));
-}
-
-void MockClientSocket::RunCallback(net::CompletionCallback* callback,
-                                   int result) {
-  if (callback)
-    callback->Run(result);
-}
-
-MockTCPClientSocket::MockTCPClientSocket(const net::AddressList& addresses,
-                                         net::NetLog* net_log,
-                                         net::SocketDataProvider* data)
-    : MockClientSocket(net_log),
-      addresses_(addresses),
-      data_(data),
-      read_offset_(0),
-      read_data_(false, net::ERR_UNEXPECTED),
-      need_read_data_(true),
-      peer_closed_connection_(false),
-      pending_buf_(NULL),
-      pending_buf_len_(0),
-      pending_callback_(NULL),
-      was_used_to_convey_data_(false) {
-  DCHECK(data_);
-  data_->Reset();
-}
-
-int MockTCPClientSocket::Connect(net::CompletionCallback* callback) {
-  if (connected_)
-    return net::OK;
-  connected_ = true;
-  peer_closed_connection_ = false;
-  if (data_->connect_data().async) {
-    RunCallbackAsync(callback, data_->connect_data().result);
-    return net::ERR_IO_PENDING;
-  }
-  return data_->connect_data().result;
-}
-
-void MockTCPClientSocket::Disconnect() {
-  MockClientSocket::Disconnect();
-  pending_callback_ = NULL;
-}
-
-bool MockTCPClientSocket::IsConnected() const {
-  return connected_ && !peer_closed_connection_;
-}
-
-int MockTCPClientSocket::Read(net::IOBuffer* buf, int buf_len,
-                              net::CompletionCallback* callback) {
-  if (!connected_)
-    return net::ERR_UNEXPECTED;
-
-  // If the buffer is already in use, a read is already in progress!
-  DCHECK(pending_buf_ == NULL);
-
-  // Store our async IO data.
-  pending_buf_ = buf;
-  pending_buf_len_ = buf_len;
-  pending_callback_ = callback;
-
-  if (need_read_data_) {
-    read_data_ = data_->GetNextRead();
-    if (read_data_.result == ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ) {
-      // This MockRead is just a marker to instruct us to set
-      // peer_closed_connection_.  Skip it and get the next one.
-      read_data_ = data_->GetNextRead();
-      peer_closed_connection_ = true;
-    }
-    // ERR_IO_PENDING means that the SocketDataProvider is taking responsibility
-    // to complete the async IO manually later (via OnReadComplete).
-    if (read_data_.result == ERR_IO_PENDING) {
-      DCHECK(callback);  // We need to be using async IO in this case.
-      return ERR_IO_PENDING;
-    }
-    need_read_data_ = false;
-  }
-
-  return CompleteRead();
-}
-
-int MockTCPClientSocket::Write(net::IOBuffer* buf, int buf_len,
-                               net::CompletionCallback* callback) {
-  DCHECK(buf);
-  DCHECK_GT(buf_len, 0);
-
-  if (!connected_)
-    return net::ERR_UNEXPECTED;
-
-  std::string data(buf->data(), buf_len);
-  net::MockWriteResult write_result = data_->OnWrite(data);
-
-  was_used_to_convey_data_ = true;
-
-  if (write_result.async) {
-    RunCallbackAsync(callback, write_result.result);
-    return net::ERR_IO_PENDING;
-  }
-
-  return write_result.result;
-}
-
-void MockTCPClientSocket::OnReadComplete(const MockRead& data) {
-  // There must be a read pending.
-  DCHECK(pending_buf_);
-  // You can't complete a read with another ERR_IO_PENDING status code.
-  DCHECK_NE(ERR_IO_PENDING, data.result);
-  // Since we've been waiting for data, need_read_data_ should be true.
-  DCHECK(need_read_data_);
-
-  read_data_ = data;
-  need_read_data_ = false;
-
-  // The caller is simulating that this IO completes right now.  Don't
-  // let CompleteRead() schedule a callback.
-  read_data_.async = false;
-
-  net::CompletionCallback* callback = pending_callback_;
-  int rv = CompleteRead();
-  RunCallback(callback, rv);
-}
-
-int MockTCPClientSocket::CompleteRead() {
-  DCHECK(pending_buf_);
-  DCHECK(pending_buf_len_ > 0);
-
-  was_used_to_convey_data_ = true;
-
-  // Save the pending async IO data and reset our |pending_| state.
-  net::IOBuffer* buf = pending_buf_;
-  int buf_len = pending_buf_len_;
-  net::CompletionCallback* callback = pending_callback_;
-  pending_buf_ = NULL;
-  pending_buf_len_ = 0;
-  pending_callback_ = NULL;
-
-  int result = read_data_.result;
-  DCHECK(result != ERR_IO_PENDING);
-
-  if (read_data_.data) {
-    if (read_data_.data_len - read_offset_ > 0) {
-      result = std::min(buf_len, read_data_.data_len - read_offset_);
-      memcpy(buf->data(), read_data_.data + read_offset_, result);
-      read_offset_ += result;
-      if (read_offset_ == read_data_.data_len) {
-        need_read_data_ = true;
-        read_offset_ = 0;
-      }
-    } else {
-      result = 0;  // EOF
-    }
-  }
-
-  if (read_data_.async) {
-    DCHECK(callback);
-    RunCallbackAsync(callback, result);
-    return net::ERR_IO_PENDING;
-  }
-  return result;
-}
-
-DeterministicMockTCPClientSocket::DeterministicMockTCPClientSocket(
-    net::NetLog* net_log, net::DeterministicSocketData* data)
-    : MockClientSocket(net_log),
-      write_pending_(false),
-      write_callback_(NULL),
-      write_result_(0),
-      read_data_(),
-      read_buf_(NULL),
-      read_buf_len_(0),
-      read_pending_(false),
-      read_callback_(NULL),
-      data_(data),
-      was_used_to_convey_data_(false) {}
-
-void DeterministicMockTCPClientSocket::OnReadComplete(const MockRead& data) {}
-
-// TODO(erikchen): Support connect sequencing.
-int DeterministicMockTCPClientSocket::Connect(
-    net::CompletionCallback* callback) {
-  if (connected_)
-    return net::OK;
-  connected_ = true;
-  if (data_->connect_data().async) {
-    RunCallbackAsync(callback, data_->connect_data().result);
-    return net::ERR_IO_PENDING;
-  }
-  return data_->connect_data().result;
-}
-
-void DeterministicMockTCPClientSocket::Disconnect() {
-  MockClientSocket::Disconnect();
-}
-
-bool DeterministicMockTCPClientSocket::IsConnected() const {
-  return connected_;
-}
-
-int DeterministicMockTCPClientSocket::Write(
-    net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
-  DCHECK(buf);
-  DCHECK_GT(buf_len, 0);
-
-  if (!connected_)
-    return net::ERR_UNEXPECTED;
-
-  std::string data(buf->data(), buf_len);
-  net::MockWriteResult write_result = data_->OnWrite(data);
-
-  if (write_result.async) {
-    write_callback_ = callback;
-    write_result_ = write_result.result;
-    DCHECK(write_callback_ != NULL);
-    write_pending_ = true;
-    return net::ERR_IO_PENDING;
-  }
-
-  was_used_to_convey_data_ = true;
-  write_pending_ = false;
-  return write_result.result;
-}
-
-int DeterministicMockTCPClientSocket::Read(
-    net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
-  if (!connected_)
-    return net::ERR_UNEXPECTED;
-
-  read_data_ = data_->GetNextRead();
-  // The buffer should always be big enough to contain all the MockRead data. To
-  // use small buffers, split the data into multiple MockReads.
-  DCHECK_LE(read_data_.data_len, buf_len);
-
-  read_buf_ = buf;
-  read_buf_len_ = buf_len;
-  read_callback_ = callback;
-
-  if (read_data_.async || (read_data_.result == ERR_IO_PENDING)) {
-    read_pending_ = true;
-    DCHECK(read_callback_);
-    return ERR_IO_PENDING;
-  }
-
-  was_used_to_convey_data_ = true;
-  return CompleteRead();
-}
-
-void DeterministicMockTCPClientSocket::CompleteWrite() {
-  was_used_to_convey_data_ = true;
-  write_pending_ = false;
-  write_callback_->Run(write_result_);
-}
-
-int DeterministicMockTCPClientSocket::CompleteRead() {
-  DCHECK_GT(read_buf_len_, 0);
-  DCHECK_LE(read_data_.data_len, read_buf_len_);
-  DCHECK(read_buf_);
-
-  was_used_to_convey_data_ = true;
-
-  if (read_data_.result == ERR_IO_PENDING)
-    read_data_ = data_->GetNextRead();
-  DCHECK_NE(ERR_IO_PENDING, read_data_.result);
-  // If read_data_.async is true, we do not need to wait, since this is already
-  // the callback. Therefore we don't even bother to check it.
-  int result = read_data_.result;
-
-  if (read_data_.data_len > 0) {
-    DCHECK(read_data_.data);
-    result = std::min(read_buf_len_, read_data_.data_len);
-    memcpy(read_buf_->data(), read_data_.data, result);
-  }
-
-  if (read_pending_) {
-    read_pending_ = false;
-    read_callback_->Run(result);
-  }
-
-  return result;
-}
-
-class MockSSLClientSocket::ConnectCallback
-    : public net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback> {
- public:
-  ConnectCallback(MockSSLClientSocket *ssl_client_socket,
-                  net::CompletionCallback* user_callback,
-                  int rv)
-      : ALLOW_THIS_IN_INITIALIZER_LIST(
-          net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback>(
-                this, &ConnectCallback::Wrapper)),
-        ssl_client_socket_(ssl_client_socket),
-        user_callback_(user_callback),
-        rv_(rv) {
-  }
-
- private:
-  void Wrapper(int rv) {
-    if (rv_ == net::OK)
-      ssl_client_socket_->connected_ = true;
-    user_callback_->Run(rv_);
-    delete this;
-  }
-
-  MockSSLClientSocket* ssl_client_socket_;
-  net::CompletionCallback* user_callback_;
-  int rv_;
-};
-
-MockSSLClientSocket::MockSSLClientSocket(
-    net::ClientSocketHandle* transport_socket,
-    const HostPortPair& host_port_pair,
-    const net::SSLConfig& ssl_config,
-    SSLHostInfo* ssl_host_info,
-    net::SSLSocketDataProvider* data)
-    : MockClientSocket(transport_socket->socket()->NetLog().net_log()),
-      transport_(transport_socket),
-      data_(data),
-      is_npn_state_set_(false),
-      new_npn_value_(false) {
-  DCHECK(data_);
-  delete ssl_host_info;  // we take ownership but don't use it.
-}
-
-MockSSLClientSocket::~MockSSLClientSocket() {
-  Disconnect();
-}
-
-int MockSSLClientSocket::Connect(net::CompletionCallback* callback) {
-  ConnectCallback* connect_callback = new ConnectCallback(
-      this, callback, data_->connect.result);
-  int rv = transport_->socket()->Connect(connect_callback);
-  if (rv == net::OK) {
-    delete connect_callback;
-    if (data_->connect.result == net::OK)
-      connected_ = true;
-    if (data_->connect.async) {
-      RunCallbackAsync(callback, data_->connect.result);
-      return net::ERR_IO_PENDING;
-    }
-    return data_->connect.result;
-  }
-  return rv;
-}
-
-void MockSSLClientSocket::Disconnect() {
-  MockClientSocket::Disconnect();
-  if (transport_->socket() != NULL)
-    transport_->socket()->Disconnect();
-}
-
-bool MockSSLClientSocket::IsConnected() const {
-  return transport_->socket()->IsConnected();
-}
-
-bool MockSSLClientSocket::WasEverUsed() const {
-  return transport_->socket()->WasEverUsed();
-}
-
-bool MockSSLClientSocket::UsingTCPFastOpen() const {
-  return transport_->socket()->UsingTCPFastOpen();
-}
-
-int MockSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
-                              net::CompletionCallback* callback) {
-  return transport_->socket()->Read(buf, buf_len, callback);
-}
-
-int MockSSLClientSocket::Write(net::IOBuffer* buf, int buf_len,
-                               net::CompletionCallback* callback) {
-  return transport_->socket()->Write(buf, buf_len, callback);
-}
-
-void MockSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
-  ssl_info->Reset();
-}
-
-SSLClientSocket::NextProtoStatus MockSSLClientSocket::GetNextProto(
-    std::string* proto) {
-  *proto = data_->next_proto;
-  return data_->next_proto_status;
-}
-
-bool MockSSLClientSocket::was_npn_negotiated() const {
-  if (is_npn_state_set_)
-    return new_npn_value_;
-  return data_->was_npn_negotiated;
-}
-
-bool MockSSLClientSocket::set_was_npn_negotiated(bool negotiated) {
-  is_npn_state_set_ = true;
-  return new_npn_value_ = negotiated;
-}
-
 StaticSocketDataProvider::StaticSocketDataProvider()
     : reads_(NULL),
       read_index_(0),
@@ -571,6 +139,26 @@
 
 StaticSocketDataProvider::~StaticSocketDataProvider() {}
 
+const MockRead& StaticSocketDataProvider::PeekRead() const {
+  DCHECK(!at_read_eof());
+  return reads_[read_index_];
+}
+
+const MockWrite& StaticSocketDataProvider::PeekWrite() const {
+  DCHECK(!at_write_eof());
+  return writes_[write_index_];
+}
+
+const MockRead& StaticSocketDataProvider::PeekRead(size_t index) const {
+  DCHECK_LT(index, read_count_);
+  return reads_[index];
+}
+
+const MockWrite& StaticSocketDataProvider::PeekWrite(size_t index) const {
+  DCHECK_LT(index, write_count_);
+  return writes_[index];
+}
+
 MockRead StaticSocketDataProvider::GetNextRead() {
   DCHECK(!at_read_eof());
   reads_[read_index_].time_stamp = base::Time::Now();
@@ -609,26 +197,6 @@
   return MockWriteResult(w->async, result);
 }
 
-const MockRead& StaticSocketDataProvider::PeekRead() const {
-  DCHECK(!at_read_eof());
-  return reads_[read_index_];
-}
-
-const MockWrite& StaticSocketDataProvider::PeekWrite() const {
-  DCHECK(!at_write_eof());
-  return writes_[write_index_];
-}
-
-const MockRead& StaticSocketDataProvider::PeekRead(size_t index) const {
-  DCHECK_LT(index, read_count_);
-  return reads_[index];
-}
-
-const MockWrite& StaticSocketDataProvider::PeekWrite(size_t index) const {
-  DCHECK_LT(index, write_count_);
-  return writes_[index];
-}
-
 void StaticSocketDataProvider::Reset() {
   read_index_ = 0;
   write_index_ = 0;
@@ -689,6 +257,11 @@
 DelayedSocketData::~DelayedSocketData() {
 }
 
+void DelayedSocketData::ForceNextRead() {
+  write_delay_ = 0;
+  CompleteRead();
+}
+
 MockRead DelayedSocketData::GetNextRead() {
   if (write_delay_ > 0)
     return MockRead(true, ERR_IO_PENDING);
@@ -715,11 +288,6 @@
     socket()->OnReadComplete(GetNextRead());
 }
 
-void DelayedSocketData::ForceNextRead() {
-  write_delay_ = 0;
-  CompleteRead();
-}
-
 OrderedSocketData::OrderedSocketData(
     MockRead* reads, size_t reads_count, MockWrite* writes, size_t writes_count)
     : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
@@ -737,6 +305,29 @@
   set_connect_data(connect);
 }
 
+void OrderedSocketData::EndLoop() {
+  // If we've already stopped the loop, don't do it again until we've advanced
+  // to the next sequence_number.
+  NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_ << ": EndLoop()";
+  if (loop_stop_stage_ > 0) {
+    const MockRead& next_read = StaticSocketDataProvider::PeekRead();
+    if ((next_read.sequence_number & ~MockRead::STOPLOOP) >
+        loop_stop_stage_) {
+      NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_
+                                << ": Clearing stop index";
+      loop_stop_stage_ = 0;
+    } else {
+      return;
+    }
+  }
+  // Record the sequence_number at which we stopped the loop.
+  NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_
+                            << ": Posting Quit at read " << read_index();
+  loop_stop_stage_ = sequence_number_;
+  if (callback_)
+    callback_->RunWithParams(Tuple1<int>(ERR_IO_PENDING));
+}
+
 MockRead OrderedSocketData::GetNextRead() {
   factory_.RevokeAll();
   blocked_ = false;
@@ -786,29 +377,6 @@
   StaticSocketDataProvider::Reset();
 }
 
-void OrderedSocketData::EndLoop() {
-  // If we've already stopped the loop, don't do it again until we've advanced
-  // to the next sequence_number.
-  NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_ << ": EndLoop()";
-  if (loop_stop_stage_ > 0) {
-    const MockRead& next_read = StaticSocketDataProvider::PeekRead();
-    if ((next_read.sequence_number & ~MockRead::STOPLOOP) >
-        loop_stop_stage_) {
-      NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_
-                                << ": Clearing stop index";
-      loop_stop_stage_ = 0;
-    } else {
-      return;
-    }
-  }
-  // Record the sequence_number at which we stopped the loop.
-  NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_
-                            << ": Posting Quit at read " << read_index();
-  loop_stop_stage_ = sequence_number_;
-  if (callback_)
-    callback_->RunWithParams(Tuple1<int>(ERR_IO_PENDING));
-}
-
 void OrderedSocketData::CompleteRead() {
   if (socket()) {
     NET_TRACE(INFO, "  *** ") << "Stage " << sequence_number_;
@@ -828,6 +396,49 @@
       stopped_(false),
       print_debug_(false) {}
 
+DeterministicSocketData::~DeterministicSocketData() {}
+
+void DeterministicSocketData::Run() {
+  SetStopped(false);
+  int counter = 0;
+  // Continue to consume data until all data has run out, or the stopped_ flag
+  // has been set. Consuming data requires two separate operations -- running
+  // the tasks in the message loop, and explicitly invoking the read/write
+  // callbacks (simulating network I/O). We check our conditions between each,
+  // since they can change in either.
+  while ((!at_write_eof() || !at_read_eof()) && !stopped()) {
+    if (counter % 2 == 0)
+      MessageLoop::current()->RunAllPending();
+    if (counter % 2 == 1) {
+      InvokeCallbacks();
+    }
+    counter++;
+  }
+  // We're done consuming new data, but it is possible there are still some
+  // pending callbacks which we expect to complete before returning.
+  while (socket_ && (socket_->write_pending() || socket_->read_pending()) &&
+         !stopped()) {
+    InvokeCallbacks();
+    MessageLoop::current()->RunAllPending();
+  }
+  SetStopped(false);
+}
+
+void DeterministicSocketData::RunFor(int steps) {
+  StopAfter(steps);
+  Run();
+}
+
+void DeterministicSocketData::SetStop(int seq) {
+  DCHECK_LT(sequence_number_, seq);
+  stopping_sequence_number_ = seq;
+  stopped_ = false;
+}
+
+void DeterministicSocketData::StopAfter(int seq) {
+  SetStop(sequence_number_ + seq);
+}
+
 MockRead DeterministicSocketData::GetNextRead() {
   current_read_ = StaticSocketDataProvider::PeekRead();
   EXPECT_LE(sequence_number_, current_read_.sequence_number);
@@ -913,37 +524,6 @@
   NOTREACHED();
 }
 
-void DeterministicSocketData::RunFor(int steps) {
-  StopAfter(steps);
-  Run();
-}
-
-void DeterministicSocketData::Run() {
-  SetStopped(false);
-  int counter = 0;
-  // Continue to consume data until all data has run out, or the stopped_ flag
-  // has been set. Consuming data requires two separate operations -- running
-  // the tasks in the message loop, and explicitly invoking the read/write
-  // callbacks (simulating network I/O). We check our conditions between each,
-  // since they can change in either.
-  while ((!at_write_eof() || !at_read_eof()) && !stopped()) {
-    if (counter % 2 == 0)
-      MessageLoop::current()->RunAllPending();
-    if (counter % 2 == 1) {
-      InvokeCallbacks();
-    }
-    counter++;
-  }
-  // We're done consuming new data, but it is possible there are still some
-  // pending callbacks which we expect to complete before returning.
-  while (socket_ && (socket_->write_pending() || socket_->read_pending()) &&
-         !stopped()) {
-    InvokeCallbacks();
-    MessageLoop::current()->RunAllPending();
-  }
-  SetStopped(false);
-}
-
 void DeterministicSocketData::InvokeCallbacks() {
   if (socket_ && socket_->write_pending() &&
       (current_write().sequence_number == sequence_number())) {
@@ -967,7 +547,6 @@
     SetStopped(true);
 }
 
-
 MockClientSocketFactory::MockClientSocketFactory() {}
 
 MockClientSocketFactory::~MockClientSocketFactory() {}
@@ -1025,55 +604,493 @@
   return socket;
 }
 
-DeterministicMockClientSocketFactory::DeterministicMockClientSocketFactory() {}
-
-DeterministicMockClientSocketFactory::~DeterministicMockClientSocketFactory() {}
-
-void DeterministicMockClientSocketFactory::AddSocketDataProvider(
-    DeterministicSocketData* data) {
-  mock_data_.Add(data);
+MockClientSocket::MockClientSocket(net::NetLog* net_log)
+    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
+      connected_(false),
+      net_log_(NetLog::Source(), net_log) {
 }
 
-void DeterministicMockClientSocketFactory::AddSSLSocketDataProvider(
-    SSLSocketDataProvider* data) {
-  mock_ssl_data_.Add(data);
+bool MockClientSocket::SetReceiveBufferSize(int32 size) {
+  return true;
 }
 
-void DeterministicMockClientSocketFactory::ResetNextMockIndexes() {
-  mock_data_.ResetNextIndex();
-  mock_ssl_data_.ResetNextIndex();
+bool MockClientSocket::SetSendBufferSize(int32 size) {
+  return true;
 }
 
-MockSSLClientSocket* DeterministicMockClientSocketFactory::
-    GetMockSSLClientSocket(size_t index) const {
-  DCHECK_LT(index, ssl_client_sockets_.size());
-  return ssl_client_sockets_[index];
+void MockClientSocket::Disconnect() {
+  connected_ = false;
 }
 
-ClientSocket* DeterministicMockClientSocketFactory::CreateTCPClientSocket(
-    const AddressList& addresses,
-    net::NetLog* net_log,
-    const net::NetLog::Source& source) {
-  DeterministicSocketData* data_provider = mock_data().GetNext();
-  DeterministicMockTCPClientSocket* socket =
-      new DeterministicMockTCPClientSocket(net_log, data_provider);
-  data_provider->set_socket(socket->AsWeakPtr());
-  tcp_client_sockets().push_back(socket);
-  return socket;
+bool MockClientSocket::IsConnected() const {
+  return connected_;
 }
 
-SSLClientSocket* DeterministicMockClientSocketFactory::CreateSSLClientSocket(
-    ClientSocketHandle* transport_socket,
-    const HostPortPair& host_and_port,
-    const SSLConfig& ssl_config,
+bool MockClientSocket::IsConnectedAndIdle() const {
+  return connected_;
+}
+
+int MockClientSocket::GetPeerAddress(AddressList* address) const {
+  return net::SystemHostResolverProc("localhost", ADDRESS_FAMILY_UNSPECIFIED,
+                                     0, address, NULL);
+}
+
+const BoundNetLog& MockClientSocket::NetLog() const {
+  return net_log_;
+}
+
+void MockClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
+  NOTREACHED();
+}
+
+void MockClientSocket::GetSSLCertRequestInfo(
+    net::SSLCertRequestInfo* cert_request_info) {
+}
+
+SSLClientSocket::NextProtoStatus
+MockClientSocket::GetNextProto(std::string* proto) {
+  proto->clear();
+  return SSLClientSocket::kNextProtoUnsupported;
+}
+
+MockClientSocket::~MockClientSocket() {}
+
+void MockClientSocket::RunCallbackAsync(net::CompletionCallback* callback,
+                                        int result) {
+  MessageLoop::current()->PostTask(FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &MockClientSocket::RunCallback, callback, result));
+}
+
+void MockClientSocket::RunCallback(net::CompletionCallback* callback,
+                                   int result) {
+  if (callback)
+    callback->Run(result);
+}
+
+MockTCPClientSocket::MockTCPClientSocket(const net::AddressList& addresses,
+                                         net::NetLog* net_log,
+                                         net::SocketDataProvider* data)
+    : MockClientSocket(net_log),
+      addresses_(addresses),
+      data_(data),
+      read_offset_(0),
+      read_data_(false, net::ERR_UNEXPECTED),
+      need_read_data_(true),
+      peer_closed_connection_(false),
+      pending_buf_(NULL),
+      pending_buf_len_(0),
+      pending_callback_(NULL),
+      was_used_to_convey_data_(false) {
+  DCHECK(data_);
+  data_->Reset();
+}
+
+int MockTCPClientSocket::Read(net::IOBuffer* buf, int buf_len,
+                              net::CompletionCallback* callback) {
+  if (!connected_)
+    return net::ERR_UNEXPECTED;
+
+  // If the buffer is already in use, a read is already in progress!
+  DCHECK(pending_buf_ == NULL);
+
+  // Store our async IO data.
+  pending_buf_ = buf;
+  pending_buf_len_ = buf_len;
+  pending_callback_ = callback;
+
+  if (need_read_data_) {
+    read_data_ = data_->GetNextRead();
+    if (read_data_.result == ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ) {
+      // This MockRead is just a marker to instruct us to set
+      // peer_closed_connection_.  Skip it and get the next one.
+      read_data_ = data_->GetNextRead();
+      peer_closed_connection_ = true;
+    }
+    // ERR_IO_PENDING means that the SocketDataProvider is taking responsibility
+    // to complete the async IO manually later (via OnReadComplete).
+    if (read_data_.result == ERR_IO_PENDING) {
+      DCHECK(callback);  // We need to be using async IO in this case.
+      return ERR_IO_PENDING;
+    }
+    need_read_data_ = false;
+  }
+
+  return CompleteRead();
+}
+
+int MockTCPClientSocket::Write(net::IOBuffer* buf, int buf_len,
+                               net::CompletionCallback* callback) {
+  DCHECK(buf);
+  DCHECK_GT(buf_len, 0);
+
+  if (!connected_)
+    return net::ERR_UNEXPECTED;
+
+  std::string data(buf->data(), buf_len);
+  net::MockWriteResult write_result = data_->OnWrite(data);
+
+  was_used_to_convey_data_ = true;
+
+  if (write_result.async) {
+    RunCallbackAsync(callback, write_result.result);
+    return net::ERR_IO_PENDING;
+  }
+
+  return write_result.result;
+}
+
+int MockTCPClientSocket::Connect(net::CompletionCallback* callback) {
+  if (connected_)
+    return net::OK;
+  connected_ = true;
+  peer_closed_connection_ = false;
+  if (data_->connect_data().async) {
+    RunCallbackAsync(callback, data_->connect_data().result);
+    return net::ERR_IO_PENDING;
+  }
+  return data_->connect_data().result;
+}
+
+void MockTCPClientSocket::Disconnect() {
+  MockClientSocket::Disconnect();
+  pending_callback_ = NULL;
+}
+
+bool MockTCPClientSocket::IsConnected() const {
+  return connected_ && !peer_closed_connection_;
+}
+
+bool MockTCPClientSocket::IsConnectedAndIdle() const {
+  return IsConnected();
+}
+
+bool MockTCPClientSocket::WasEverUsed() const {
+  return was_used_to_convey_data_;
+}
+
+bool MockTCPClientSocket::UsingTCPFastOpen() const {
+  return false;
+}
+
+void MockTCPClientSocket::OnReadComplete(const MockRead& data) {
+  // There must be a read pending.
+  DCHECK(pending_buf_);
+  // You can't complete a read with another ERR_IO_PENDING status code.
+  DCHECK_NE(ERR_IO_PENDING, data.result);
+  // Since we've been waiting for data, need_read_data_ should be true.
+  DCHECK(need_read_data_);
+
+  read_data_ = data;
+  need_read_data_ = false;
+
+  // The caller is simulating that this IO completes right now.  Don't
+  // let CompleteRead() schedule a callback.
+  read_data_.async = false;
+
+  net::CompletionCallback* callback = pending_callback_;
+  int rv = CompleteRead();
+  RunCallback(callback, rv);
+}
+
+int MockTCPClientSocket::CompleteRead() {
+  DCHECK(pending_buf_);
+  DCHECK(pending_buf_len_ > 0);
+
+  was_used_to_convey_data_ = true;
+
+  // Save the pending async IO data and reset our |pending_| state.
+  net::IOBuffer* buf = pending_buf_;
+  int buf_len = pending_buf_len_;
+  net::CompletionCallback* callback = pending_callback_;
+  pending_buf_ = NULL;
+  pending_buf_len_ = 0;
+  pending_callback_ = NULL;
+
+  int result = read_data_.result;
+  DCHECK(result != ERR_IO_PENDING);
+
+  if (read_data_.data) {
+    if (read_data_.data_len - read_offset_ > 0) {
+      result = std::min(buf_len, read_data_.data_len - read_offset_);
+      memcpy(buf->data(), read_data_.data + read_offset_, result);
+      read_offset_ += result;
+      if (read_offset_ == read_data_.data_len) {
+        need_read_data_ = true;
+        read_offset_ = 0;
+      }
+    } else {
+      result = 0;  // EOF
+    }
+  }
+
+  if (read_data_.async) {
+    DCHECK(callback);
+    RunCallbackAsync(callback, result);
+    return net::ERR_IO_PENDING;
+  }
+  return result;
+}
+
+DeterministicMockTCPClientSocket::DeterministicMockTCPClientSocket(
+    net::NetLog* net_log, net::DeterministicSocketData* data)
+    : MockClientSocket(net_log),
+      write_pending_(false),
+      write_callback_(NULL),
+      write_result_(0),
+      read_data_(),
+      read_buf_(NULL),
+      read_buf_len_(0),
+      read_pending_(false),
+      read_callback_(NULL),
+      data_(data),
+      was_used_to_convey_data_(false) {}
+
+DeterministicMockTCPClientSocket::~DeterministicMockTCPClientSocket() {}
+
+void DeterministicMockTCPClientSocket::CompleteWrite() {
+  was_used_to_convey_data_ = true;
+  write_pending_ = false;
+  write_callback_->Run(write_result_);
+}
+
+int DeterministicMockTCPClientSocket::CompleteRead() {
+  DCHECK_GT(read_buf_len_, 0);
+  DCHECK_LE(read_data_.data_len, read_buf_len_);
+  DCHECK(read_buf_);
+
+  was_used_to_convey_data_ = true;
+
+  if (read_data_.result == ERR_IO_PENDING)
+    read_data_ = data_->GetNextRead();
+  DCHECK_NE(ERR_IO_PENDING, read_data_.result);
+  // If read_data_.async is true, we do not need to wait, since this is already
+  // the callback. Therefore we don't even bother to check it.
+  int result = read_data_.result;
+
+  if (read_data_.data_len > 0) {
+    DCHECK(read_data_.data);
+    result = std::min(read_buf_len_, read_data_.data_len);
+    memcpy(read_buf_->data(), read_data_.data, result);
+  }
+
+  if (read_pending_) {
+    read_pending_ = false;
+    read_callback_->Run(result);
+  }
+
+  return result;
+}
+
+int DeterministicMockTCPClientSocket::Write(
+    net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
+  DCHECK(buf);
+  DCHECK_GT(buf_len, 0);
+
+  if (!connected_)
+    return net::ERR_UNEXPECTED;
+
+  std::string data(buf->data(), buf_len);
+  net::MockWriteResult write_result = data_->OnWrite(data);
+
+  if (write_result.async) {
+    write_callback_ = callback;
+    write_result_ = write_result.result;
+    DCHECK(write_callback_ != NULL);
+    write_pending_ = true;
+    return net::ERR_IO_PENDING;
+  }
+
+  was_used_to_convey_data_ = true;
+  write_pending_ = false;
+  return write_result.result;
+}
+
+int DeterministicMockTCPClientSocket::Read(
+    net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
+  if (!connected_)
+    return net::ERR_UNEXPECTED;
+
+  read_data_ = data_->GetNextRead();
+  // The buffer should always be big enough to contain all the MockRead data. To
+  // use small buffers, split the data into multiple MockReads.
+  DCHECK_LE(read_data_.data_len, buf_len);
+
+  read_buf_ = buf;
+  read_buf_len_ = buf_len;
+  read_callback_ = callback;
+
+  if (read_data_.async || (read_data_.result == ERR_IO_PENDING)) {
+    read_pending_ = true;
+    DCHECK(read_callback_);
+    return ERR_IO_PENDING;
+  }
+
+  was_used_to_convey_data_ = true;
+  return CompleteRead();
+}
+
+// TODO(erikchen): Support connect sequencing.
+int DeterministicMockTCPClientSocket::Connect(
+    net::CompletionCallback* callback) {
+  if (connected_)
+    return net::OK;
+  connected_ = true;
+  if (data_->connect_data().async) {
+    RunCallbackAsync(callback, data_->connect_data().result);
+    return net::ERR_IO_PENDING;
+  }
+  return data_->connect_data().result;
+}
+
+void DeterministicMockTCPClientSocket::Disconnect() {
+  MockClientSocket::Disconnect();
+}
+
+bool DeterministicMockTCPClientSocket::IsConnected() const {
+  return connected_;
+}
+
+bool DeterministicMockTCPClientSocket::IsConnectedAndIdle() const {
+  return IsConnected();
+}
+
+bool DeterministicMockTCPClientSocket::WasEverUsed() const {
+  return was_used_to_convey_data_;
+}
+
+bool DeterministicMockTCPClientSocket::UsingTCPFastOpen() const {
+  return false;
+}
+
+void DeterministicMockTCPClientSocket::OnReadComplete(const MockRead& data) {}
+
+class MockSSLClientSocket::ConnectCallback
+    : public net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback> {
+ public:
+  ConnectCallback(MockSSLClientSocket *ssl_client_socket,
+                  net::CompletionCallback* user_callback,
+                  int rv)
+      : ALLOW_THIS_IN_INITIALIZER_LIST(
+          net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback>(
+                this, &ConnectCallback::Wrapper)),
+        ssl_client_socket_(ssl_client_socket),
+        user_callback_(user_callback),
+        rv_(rv) {
+  }
+
+ private:
+  void Wrapper(int rv) {
+    if (rv_ == net::OK)
+      ssl_client_socket_->connected_ = true;
+    user_callback_->Run(rv_);
+    delete this;
+  }
+
+  MockSSLClientSocket* ssl_client_socket_;
+  net::CompletionCallback* user_callback_;
+  int rv_;
+};
+
+MockSSLClientSocket::MockSSLClientSocket(
+    net::ClientSocketHandle* transport_socket,
+    const HostPortPair& host_port_pair,
+    const net::SSLConfig& ssl_config,
     SSLHostInfo* ssl_host_info,
-    CertVerifier* cert_verifier,
-    DnsCertProvenanceChecker* dns_cert_checker) {
-  MockSSLClientSocket* socket =
-      new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
-                              ssl_host_info, mock_ssl_data_.GetNext());
-  ssl_client_sockets_.push_back(socket);
-  return socket;
+    net::SSLSocketDataProvider* data)
+    : MockClientSocket(transport_socket->socket()->NetLog().net_log()),
+      transport_(transport_socket),
+      data_(data),
+      is_npn_state_set_(false),
+      new_npn_value_(false) {
+  DCHECK(data_);
+  delete ssl_host_info;  // we take ownership but don't use it.
+}
+
+MockSSLClientSocket::~MockSSLClientSocket() {
+  Disconnect();
+}
+
+int MockSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
+                              net::CompletionCallback* callback) {
+  return transport_->socket()->Read(buf, buf_len, callback);
+}
+
+int MockSSLClientSocket::Write(net::IOBuffer* buf, int buf_len,
+                               net::CompletionCallback* callback) {
+  return transport_->socket()->Write(buf, buf_len, callback);
+}
+
+int MockSSLClientSocket::Connect(net::CompletionCallback* callback) {
+  ConnectCallback* connect_callback = new ConnectCallback(
+      this, callback, data_->connect.result);
+  int rv = transport_->socket()->Connect(connect_callback);
+  if (rv == net::OK) {
+    delete connect_callback;
+    if (data_->connect.result == net::OK)
+      connected_ = true;
+    if (data_->connect.async) {
+      RunCallbackAsync(callback, data_->connect.result);
+      return net::ERR_IO_PENDING;
+    }
+    return data_->connect.result;
+  }
+  return rv;
+}
+
+void MockSSLClientSocket::Disconnect() {
+  MockClientSocket::Disconnect();
+  if (transport_->socket() != NULL)
+    transport_->socket()->Disconnect();
+}
+
+bool MockSSLClientSocket::IsConnected() const {
+  return transport_->socket()->IsConnected();
+}
+
+bool MockSSLClientSocket::WasEverUsed() const {
+  return transport_->socket()->WasEverUsed();
+}
+
+bool MockSSLClientSocket::UsingTCPFastOpen() const {
+  return transport_->socket()->UsingTCPFastOpen();
+}
+
+void MockSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
+  ssl_info->Reset();
+}
+
+void MockSSLClientSocket::GetSSLCertRequestInfo(
+    net::SSLCertRequestInfo* cert_request_info) {
+  DCHECK(cert_request_info);
+  if (data_->cert_request_info) {
+    cert_request_info->host_and_port =
+        data_->cert_request_info->host_and_port;
+    cert_request_info->client_certs = data_->cert_request_info->client_certs;
+  } else {
+    cert_request_info->Reset();
+  }
+}
+
+SSLClientSocket::NextProtoStatus MockSSLClientSocket::GetNextProto(
+    std::string* proto) {
+  *proto = data_->next_proto;
+  return data_->next_proto_status;
+}
+
+bool MockSSLClientSocket::was_npn_negotiated() const {
+  if (is_npn_state_set_)
+    return new_npn_value_;
+  return data_->was_npn_negotiated;
+}
+
+bool MockSSLClientSocket::set_was_npn_negotiated(bool negotiated) {
+  is_npn_state_set_ = true;
+  return new_npn_value_ = negotiated;
+}
+
+void MockSSLClientSocket::OnReadComplete(const MockRead& data) {
+  NOTIMPLEMENTED();
 }
 
 TestSocketRequest::TestSocketRequest(
@@ -1202,6 +1219,8 @@
       cancel_count_(0) {
 }
 
+MockTCPClientSocketPool::~MockTCPClientSocketPool() {}
+
 int MockTCPClientSocketPool::RequestSocket(const std::string& group_name,
                                            const void* socket_params,
                                            RequestPriority priority,
@@ -1234,7 +1253,56 @@
   delete socket;
 }
 
-MockTCPClientSocketPool::~MockTCPClientSocketPool() {}
+DeterministicMockClientSocketFactory::DeterministicMockClientSocketFactory() {}
+
+DeterministicMockClientSocketFactory::~DeterministicMockClientSocketFactory() {}
+
+void DeterministicMockClientSocketFactory::AddSocketDataProvider(
+    DeterministicSocketData* data) {
+  mock_data_.Add(data);
+}
+
+void DeterministicMockClientSocketFactory::AddSSLSocketDataProvider(
+    SSLSocketDataProvider* data) {
+  mock_ssl_data_.Add(data);
+}
+
+void DeterministicMockClientSocketFactory::ResetNextMockIndexes() {
+  mock_data_.ResetNextIndex();
+  mock_ssl_data_.ResetNextIndex();
+}
+
+MockSSLClientSocket* DeterministicMockClientSocketFactory::
+    GetMockSSLClientSocket(size_t index) const {
+  DCHECK_LT(index, ssl_client_sockets_.size());
+  return ssl_client_sockets_[index];
+}
+
+ClientSocket* DeterministicMockClientSocketFactory::CreateTCPClientSocket(
+    const AddressList& addresses,
+    net::NetLog* net_log,
+    const net::NetLog::Source& source) {
+  DeterministicSocketData* data_provider = mock_data().GetNext();
+  DeterministicMockTCPClientSocket* socket =
+      new DeterministicMockTCPClientSocket(net_log, data_provider);
+  data_provider->set_socket(socket->AsWeakPtr());
+  tcp_client_sockets().push_back(socket);
+  return socket;
+}
+
+SSLClientSocket* DeterministicMockClientSocketFactory::CreateSSLClientSocket(
+    ClientSocketHandle* transport_socket,
+    const HostPortPair& host_and_port,
+    const SSLConfig& ssl_config,
+    SSLHostInfo* ssl_host_info,
+    CertVerifier* cert_verifier,
+    DnsCertProvenanceChecker* dns_cert_checker) {
+  MockSSLClientSocket* socket =
+      new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
+                              ssl_host_info, mock_ssl_data_.GetNext());
+  ssl_client_sockets_.push_back(socket);
+  return socket;
+}
 
 MockSOCKSClientSocketPool::MockSOCKSClientSocketPool(
     int max_sockets,
@@ -1246,6 +1314,8 @@
       tcp_pool_(tcp_pool) {
 }
 
+MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() {}
+
 int MockSOCKSClientSocketPool::RequestSocket(const std::string& group_name,
                                              const void* socket_params,
                                              RequestPriority priority,
@@ -1267,8 +1337,6 @@
   return tcp_pool_->ReleaseSocket(group_name, socket, id);
 }
 
-MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() {}
-
 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
 const int kSOCKS5GreetRequestLength = arraysize(kSOCKS5GreetRequest);
 
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 91f8fc9..4a15f37 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -182,11 +182,12 @@
   bool at_read_eof() const { return read_index_ >= read_count_; }
   bool at_write_eof() const { return write_index_ >= write_count_; }
 
+  virtual void CompleteRead() {}
+
   // SocketDataProvider methods:
   virtual MockRead GetNextRead();
   virtual MockWriteResult OnWrite(const std::string& data);
   virtual void Reset();
-  virtual void CompleteRead() {}
 
  private:
   MockRead* reads_;
@@ -208,16 +209,16 @@
   DynamicSocketDataProvider();
   virtual ~DynamicSocketDataProvider();
 
-  // SocketDataProvider methods:
-  virtual MockRead GetNextRead();
-  virtual MockWriteResult OnWrite(const std::string& data) = 0;
-  virtual void Reset();
-
   int short_read_limit() const { return short_read_limit_; }
   void set_short_read_limit(int limit) { short_read_limit_ = limit; }
 
   void allow_unconsumed_reads(bool allow) { allow_unconsumed_reads_ = allow; }
 
+  // SocketDataProvider methods:
+  virtual MockRead GetNextRead();
+  virtual MockWriteResult OnWrite(const std::string& data) = 0;
+  virtual void Reset();
+
  protected:
   // The next time there is a read from this socket, it will return |data|.
   // Before calling SimulateRead next time, the previous data must be consumed.
@@ -245,12 +246,14 @@
   SSLSocketDataProvider(bool async, int result)
       : connect(async, result),
         next_proto_status(SSLClientSocket::kNextProtoUnsupported),
-        was_npn_negotiated(false) { }
+        was_npn_negotiated(false),
+        cert_request_info(NULL) { }
 
   MockConnect connect;
   SSLClientSocket::NextProtoStatus next_proto_status;
   std::string next_proto;
   bool was_npn_negotiated;
+  net::SSLCertRequestInfo* cert_request_info;
 };
 
 // A DataProvider where the client must write a request before the reads (e.g.
@@ -282,11 +285,13 @@
                     MockWrite* writes, size_t writes_count);
   ~DelayedSocketData();
 
+  void ForceNextRead();
+
+  // StaticSocketDataProvider:
   virtual MockRead GetNextRead();
   virtual MockWriteResult OnWrite(const std::string& data);
   virtual void Reset();
   virtual void CompleteRead();
-  void ForceNextRead();
 
  private:
   int write_delay_;
@@ -325,11 +330,6 @@
                     MockRead* reads, size_t reads_count,
                     MockWrite* writes, size_t writes_count);
 
-  virtual MockRead GetNextRead();
-  virtual MockWriteResult OnWrite(const std::string& data);
-  virtual void Reset();
-  virtual void CompleteRead();
-
   void SetCompletionCallback(CompletionCallback* callback) {
     callback_ = callback;
   }
@@ -337,6 +337,12 @@
   // Posts a quit message to the current message loop, if one is running.
   void EndLoop();
 
+  // StaticSocketDataProvider:
+  virtual MockRead GetNextRead();
+  virtual MockWriteResult OnWrite(const std::string& data);
+  virtual void Reset();
+  virtual void CompleteRead();
+
  private:
   friend class base::RefCounted<OrderedSocketData>;
   virtual ~OrderedSocketData();
@@ -414,6 +420,29 @@
   // |writes| the list of MockWrite completions.
   DeterministicSocketData(MockRead* reads, size_t reads_count,
                           MockWrite* writes, size_t writes_count);
+  virtual ~DeterministicSocketData();
+
+  // Consume all the data up to the give stop point (via SetStop()).
+  void Run();
+
+  // Set the stop point to be |steps| from now, and then invoke Run().
+  void RunFor(int steps);
+
+  // Stop at step |seq|, which must be in the future.
+  virtual void SetStop(int seq);
+
+  // Stop |seq| steps after the current step.
+  virtual void StopAfter(int seq);
+  bool stopped() const { return stopped_; }
+  void SetStopped(bool val) { stopped_ = val; }
+  MockRead& current_read() { return current_read_; }
+  MockRead& current_write() { return current_write_; }
+  int sequence_number() const { return sequence_number_; }
+  void set_socket(base::WeakPtr<DeterministicMockTCPClientSocket> socket) {
+    socket_ = socket;
+  }
+
+  // StaticSocketDataProvider:
 
   // When the socket calls Read(), that calls GetNextRead(), and expects either
   // ERR_IO_PENDING or data.
@@ -423,37 +452,9 @@
   // checks to make sure the written data matches the expected data. The
   // callback will not be invoked until its sequence number is reached.
   virtual MockWriteResult OnWrite(const std::string& data);
-
   virtual void Reset();
-
   virtual void CompleteRead() {}
 
-  // Consume all the data up to the give stop point (via SetStop()).
-  void Run();
-
-  // Set the stop point to be |steps| from now, and then invoke Run().
-  void RunFor(int steps);
-
-  // Stop at step |seq|, which must be in the future.
-  virtual void SetStop(int seq) {
-    DCHECK_LT(sequence_number_, seq);
-    stopping_sequence_number_ = seq;
-    stopped_ = false;
-  }
-
-  // Stop |seq| steps after the current step.
-  virtual void StopAfter(int seq) {
-    SetStop(sequence_number_ + seq);
-  }
-  bool stopped() const { return stopped_; }
-  void SetStopped(bool val) { stopped_ = val; }
-  MockRead& current_read() { return current_read_; }
-  MockRead& current_write() { return current_write_; }
-  int sequence_number() const { return sequence_number_; }
-  void set_socket(base::WeakPtr<DeterministicMockTCPClientSocket> socket) {
-    socket_ = socket;
-  }
-
  private:
   // Invoke the read and write callbacks, if the timing is appropriate.
   void InvokeCallbacks();
@@ -469,7 +470,6 @@
   bool print_debug_;
 };
 
-
 // Holds an array of SocketDataProvider elements.  As Mock{TCP,SSL}ClientSocket
 // objects get instantiated, they take their data from the i'th element of this
 // array.
@@ -527,6 +527,13 @@
   // created.
   MockSSLClientSocket* GetMockSSLClientSocket(size_t index) const;
 
+  SocketDataProviderArray<SocketDataProvider>& mock_data() {
+    return mock_data_;
+  }
+  std::vector<MockTCPClientSocket*>& tcp_client_sockets() {
+    return tcp_client_sockets_;
+  }
+
   // ClientSocketFactory
   virtual ClientSocket* CreateTCPClientSocket(
       const AddressList& addresses,
@@ -539,12 +546,6 @@
       SSLHostInfo* ssl_host_info,
       CertVerifier* cert_verifier,
       DnsCertProvenanceChecker* dns_cert_checker);
-  SocketDataProviderArray<SocketDataProvider>& mock_data() {
-    return mock_data_;
-  }
-  std::vector<MockTCPClientSocket*>& tcp_client_sockets() {
-    return tcp_client_sockets_;
-  }
 
  private:
   SocketDataProviderArray<SocketDataProvider> mock_data_;
@@ -558,13 +559,29 @@
 class MockClientSocket : public net::SSLClientSocket {
  public:
   explicit MockClientSocket(net::NetLog* net_log);
+
+  // If an async IO is pending because the SocketDataProvider returned
+  // ERR_IO_PENDING, then the MockClientSocket waits until this OnReadComplete
+  // is called to complete the asynchronous read operation.
+  // data.async is ignored, and this read is completed synchronously as
+  // part of this call.
+  virtual void OnReadComplete(const MockRead& data) = 0;
+
+  // Socket methods:
+  virtual int Read(net::IOBuffer* buf, int buf_len,
+                   net::CompletionCallback* callback) = 0;
+  virtual int Write(net::IOBuffer* buf, int buf_len,
+                    net::CompletionCallback* callback) = 0;
+  virtual bool SetReceiveBufferSize(int32 size);
+  virtual bool SetSendBufferSize(int32 size);
+
   // ClientSocket methods:
   virtual int Connect(net::CompletionCallback* callback) = 0;
   virtual void Disconnect();
   virtual bool IsConnected() const;
   virtual bool IsConnectedAndIdle() const;
   virtual int GetPeerAddress(AddressList* address) const;
-  virtual const BoundNetLog& NetLog() const { return net_log_;}
+  virtual const BoundNetLog& NetLog() const;
   virtual void SetSubresourceSpeculation() {}
   virtual void SetOmniboxSpeculation() {}
 
@@ -574,23 +591,8 @@
       net::SSLCertRequestInfo* cert_request_info);
   virtual NextProtoStatus GetNextProto(std::string* proto);
 
-  // Socket methods:
-  virtual int Read(net::IOBuffer* buf, int buf_len,
-                   net::CompletionCallback* callback) = 0;
-  virtual int Write(net::IOBuffer* buf, int buf_len,
-                    net::CompletionCallback* callback) = 0;
-  virtual bool SetReceiveBufferSize(int32 size) { return true; }
-  virtual bool SetSendBufferSize(int32 size) { return true; }
-
-  // If an async IO is pending because the SocketDataProvider returned
-  // ERR_IO_PENDING, then the MockClientSocket waits until this OnReadComplete
-  // is called to complete the asynchronous read operation.
-  // data.async is ignored, and this read is completed synchronously as
-  // part of this call.
-  virtual void OnReadComplete(const MockRead& data) = 0;
-
  protected:
-  virtual ~MockClientSocket() {}
+  virtual ~MockClientSocket();
   void RunCallbackAsync(net::CompletionCallback* callback, int result);
   void RunCallback(net::CompletionCallback*, int result);
 
@@ -607,13 +609,7 @@
   MockTCPClientSocket(const net::AddressList& addresses, net::NetLog* net_log,
                       net::SocketDataProvider* socket);
 
-  // ClientSocket methods:
-  virtual int Connect(net::CompletionCallback* callback);
-  virtual void Disconnect();
-  virtual bool IsConnected() const;
-  virtual bool IsConnectedAndIdle() const { return IsConnected(); }
-  virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
-  virtual bool UsingTCPFastOpen() const { return false; }
+  net::AddressList addresses() const { return addresses_; }
 
   // Socket methods:
   virtual int Read(net::IOBuffer* buf, int buf_len,
@@ -621,9 +617,16 @@
   virtual int Write(net::IOBuffer* buf, int buf_len,
                     net::CompletionCallback* callback);
 
-  virtual void OnReadComplete(const MockRead& data);
+  // ClientSocket methods:
+  virtual int Connect(net::CompletionCallback* callback);
+  virtual void Disconnect();
+  virtual bool IsConnected() const;
+  virtual bool IsConnectedAndIdle() const;
+  virtual bool WasEverUsed() const;
+  virtual bool UsingTCPFastOpen() const;
 
-  net::AddressList addresses() const { return addresses_; }
+  // MockClientSocket:
+  virtual void OnReadComplete(const MockRead& data);
 
  private:
   int CompleteRead();
@@ -652,27 +655,30 @@
  public:
   DeterministicMockTCPClientSocket(net::NetLog* net_log,
       net::DeterministicSocketData* data);
-
-  // ClientSocket methods:
-  virtual int Connect(net::CompletionCallback* callback);
-  virtual void Disconnect();
-  virtual bool IsConnected() const;
-  virtual bool IsConnectedAndIdle() const { return IsConnected(); }
-  virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
-  virtual bool UsingTCPFastOpen() const { return false; }
-
-  // Socket methods:
-  virtual int Write(net::IOBuffer* buf, int buf_len,
-                    net::CompletionCallback* callback);
-  virtual int Read(net::IOBuffer* buf, int buf_len,
-                   net::CompletionCallback* callback);
+  virtual ~DeterministicMockTCPClientSocket();
 
   bool write_pending() const { return write_pending_; }
   bool read_pending() const { return read_pending_; }
 
   void CompleteWrite();
   int CompleteRead();
-  void OnReadComplete(const MockRead& data);
+
+  // Socket:
+  virtual int Write(net::IOBuffer* buf, int buf_len,
+                    net::CompletionCallback* callback);
+  virtual int Read(net::IOBuffer* buf, int buf_len,
+                   net::CompletionCallback* callback);
+
+  // ClientSocket:
+  virtual int Connect(net::CompletionCallback* callback);
+  virtual void Disconnect();
+  virtual bool IsConnected() const;
+  virtual bool IsConnectedAndIdle() const;
+  virtual bool WasEverUsed() const;
+  virtual bool UsingTCPFastOpen() const;
+
+  // MockClientSocket:
+  virtual void OnReadComplete(const MockRead& data);
 
  private:
   bool write_pending_;
@@ -697,7 +703,13 @@
       const net::SSLConfig& ssl_config,
       SSLHostInfo* ssl_host_info,
       net::SSLSocketDataProvider* socket);
-  ~MockSSLClientSocket();
+  virtual ~MockSSLClientSocket();
+
+  // Socket methods:
+  virtual int Read(net::IOBuffer* buf, int buf_len,
+                   net::CompletionCallback* callback);
+  virtual int Write(net::IOBuffer* buf, int buf_len,
+                    net::CompletionCallback* callback);
 
   // ClientSocket methods:
   virtual int Connect(net::CompletionCallback* callback);
@@ -706,20 +718,16 @@
   virtual bool WasEverUsed() const;
   virtual bool UsingTCPFastOpen() const;
 
-  // Socket methods:
-  virtual int Read(net::IOBuffer* buf, int buf_len,
-                   net::CompletionCallback* callback);
-  virtual int Write(net::IOBuffer* buf, int buf_len,
-                    net::CompletionCallback* callback);
-
   // SSLClientSocket methods:
   virtual void GetSSLInfo(net::SSLInfo* ssl_info);
+  virtual void GetSSLCertRequestInfo(
+      net::SSLCertRequestInfo* cert_request_info);
   virtual NextProtoStatus GetNextProto(std::string* proto);
   virtual bool was_npn_negotiated() const;
   virtual bool set_was_npn_negotiated(bool negotiated);
 
   // This MockSocket does not implement the manual async IO feature.
-  virtual void OnReadComplete(const MockRead& data) { NOTIMPLEMENTED(); }
+  virtual void OnReadComplete(const MockRead& data);
 
  private:
   class ConnectCallback;
@@ -874,6 +882,13 @@
   // created.
   MockSSLClientSocket* GetMockSSLClientSocket(size_t index) const;
 
+  SocketDataProviderArray<DeterministicSocketData>& mock_data() {
+    return mock_data_;
+  }
+  std::vector<DeterministicMockTCPClientSocket*>& tcp_client_sockets() {
+    return tcp_client_sockets_;
+  }
+
   // ClientSocketFactory
   virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses,
                                               NetLog* net_log,
@@ -886,13 +901,6 @@
       CertVerifier* cert_verifier,
       DnsCertProvenanceChecker* dns_cert_checker);
 
-  SocketDataProviderArray<DeterministicSocketData>& mock_data() {
-    return mock_data_;
-  }
-  std::vector<DeterministicMockTCPClientSocket*>& tcp_client_sockets() {
-    return tcp_client_sockets_;
-  }
-
  private:
   SocketDataProviderArray<DeterministicSocketData> mock_data_;
   SocketDataProviderArray<SSLSocketDataProvider> mock_ssl_data_;
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index b2c5df9..f6d4b79 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -90,7 +90,7 @@
   if (rv == ERR_IO_PENDING) {
     user_callback_ = callback;
   } else {
-    net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv);
   }
   return rv;
 }
@@ -213,7 +213,7 @@
         break;
       case STATE_GREET_WRITE_COMPLETE:
         rv = DoGreetWriteComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_SOCKS5_GREET_WRITE, NULL);
+        net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv);
         break;
       case STATE_GREET_READ:
         DCHECK_EQ(OK, rv);
@@ -222,7 +222,7 @@
         break;
       case STATE_GREET_READ_COMPLETE:
         rv = DoGreetReadComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_SOCKS5_GREET_READ, NULL);
+        net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv);
         break;
       case STATE_HANDSHAKE_WRITE:
         DCHECK_EQ(OK, rv);
@@ -231,7 +231,8 @@
         break;
       case STATE_HANDSHAKE_WRITE_COMPLETE:
         rv = DoHandshakeWriteComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv);
         break;
       case STATE_HANDSHAKE_READ:
         DCHECK_EQ(OK, rv);
@@ -240,7 +241,8 @@
         break;
       case STATE_HANDSHAKE_READ_COMPLETE:
         rv = DoHandshakeReadComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv);
         break;
       default:
         NOTREACHED() << "bad state";
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index 47c654e..f007437 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -123,7 +123,7 @@
   if (rv == ERR_IO_PENDING) {
     user_callback_ = callback;
   } else {
-    net_log_.EndEvent(NetLog::TYPE_SOCKS_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS_CONNECT, rv);
   }
   return rv;
 }
@@ -230,7 +230,7 @@
   DCHECK_NE(STATE_NONE, next_state_);
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING) {
-    net_log_.EndEvent(NetLog::TYPE_SOCKS_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS_CONNECT, rv);
     DoCallback(rv);
   }
 }
diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc
index f7f75b1..0686885 100644
--- a/net/socket/socks_client_socket_pool.cc
+++ b/net/socket/socks_client_socket_pool.cc
@@ -82,11 +82,6 @@
   }
 }
 
-int SOCKSConnectJob::ConnectInternal() {
-  next_state_ = STATE_TCP_CONNECT;
-  return DoLoop(OK);
-}
-
 void SOCKSConnectJob::OnIOComplete(int result) {
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING)
@@ -174,6 +169,11 @@
   return result;
 }
 
+int SOCKSConnectJob::ConnectInternal() {
+  next_state_ = STATE_TCP_CONNECT;
+  return DoLoop(OK);
+}
+
 ConnectJob* SOCKSClientSocketPool::SOCKSConnectJobFactory::NewConnectJob(
     const std::string& group_name,
     const PoolBase::Request& request,
diff --git a/net/socket/socks_client_socket_pool.h b/net/socket/socks_client_socket_pool.h
index fd19820..47637ef 100644
--- a/net/socket/socks_client_socket_pool.h
+++ b/net/socket/socks_client_socket_pool.h
@@ -81,11 +81,6 @@
     STATE_NONE,
   };
 
-  // Begins the tcp connection and the SOCKS handshake.  Returns OK on success
-  // and ERR_IO_PENDING if it cannot immediately service the request.
-  // Otherwise, it returns a net error code.
-  virtual int ConnectInternal();
-
   void OnIOComplete(int result);
 
   // Runs the state transition loop.
@@ -96,6 +91,11 @@
   int DoSOCKSConnect();
   int DoSOCKSConnectComplete(int result);
 
+  // Begins the tcp connection and the SOCKS handshake.  Returns OK on success
+  // and ERR_IO_PENDING if it cannot immediately service the request.
+  // Otherwise, it returns a net error code.
+  virtual int ConnectInternal();
+
   scoped_refptr<SOCKSSocketParams> socks_params_;
   TCPClientSocketPool* const tcp_pool_;
   HostResolver* const resolver_;
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index 868e13d..2f0329a 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -14,7 +14,6 @@
 #include "base/lazy_instance.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/string_util.h"
-#include "base/sys_info.h"
 #include "net/base/address_list.h"
 #include "net/base/cert_verifier.h"
 #include "net/base/io_buffer.h"
@@ -141,27 +140,6 @@
 };
 #endif
 
-// On OS X 10.5.x, SSLHandshake() is broken with respect to renegotiation
-// handshakes, and the only way to advance the handshake state machine is
-// to use SSLRead(), which transparently re-handshakes and then reads
-// application data. Using SSLRead() to pump the handshake, rather than
-// SSLHandshake(), is not presently implemented, so on 10.5.x, SSL
-// renegotiation is disabled entirely. On 10.6.x, SSLHandshake() behaves as
-// expected/documented, so renegotiation is supported.
-struct RenegotiationBroken {
-  RenegotiationBroken() : broken(false) {
-    int32 major, minor, bugfix;
-    base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
-    if (major < 10 || (major == 10 && minor < 6))
-      broken = true;
-  }
-
-  bool broken;
-};
-
-base::LazyInstance<RenegotiationBroken> g_renegotiation_broken(
-    base::LINKER_INITIALIZED);
-
 // For an explanation of the Mac OS X error codes, please refer to:
 // http://developer.apple.com/mac/library/documentation/Security/Reference/secureTransportRef/Reference/reference.html
 int NetErrorFromOSStatus(OSStatus status) {
@@ -562,6 +540,7 @@
       renegotiating_(false),
       client_cert_requested_(false),
       ssl_context_(NULL),
+      bytes_read_after_renegotiation_(0),
       pending_send_error_(OK),
       net_log_(transport_socket->socket()->NetLog()) {
   // Sort the list of ciphers to disable, since disabling ciphers on Mac
@@ -592,7 +571,7 @@
 
   int rv = InitializeSSLContext();
   if (rv != OK) {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
     return rv;
   }
 
@@ -601,7 +580,7 @@
   if (rv == ERR_IO_PENDING) {
     user_connect_callback_ = callback;
   } else {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
   }
   return rv;
 }
@@ -935,7 +914,7 @@
       DoReadCallback(rv);
       return;
     }
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
     DoConnectCallback(rv);
   }
 }
@@ -1032,7 +1011,55 @@
 int SSLClientSocketMac::DoHandshake() {
   client_cert_requested_ = false;
 
-  OSStatus status = SSLHandshake(ssl_context_);
+  OSStatus status;
+  if (!renegotiating_) {
+    status = SSLHandshake(ssl_context_);
+  } else {
+    // Renegotiation can only be detected by a call to DoPayloadRead(),
+    // which means |user_read_buf_| should be valid.
+    DCHECK(user_read_buf_);
+
+    // On OS X 10.5.x, SSLSetSessionOption with
+    // kSSLSessionOptionBreakOnServerAuth is broken for renegotiation, as
+    // SSLRead() does not internally handle errSSLServerAuthCompleted being
+    // returned during handshake. In order to support certificate validation
+    // after a renegotiation, SSLRead() sets |renegotiating_| to be true and
+    // returns errSSLWouldBlock when it detects an attempt to read the
+    // ServerHello after responding to a HelloRequest. It would be
+    // appropriate to call SSLHandshake() at this point to restart the
+    // handshake state machine, however, on 10.5.x, SSLHandshake() is buggy
+    // and will always return noErr (indicating handshake completion),
+    // without doing any actual work. Because of this, the only way to
+    // advance SecureTransport's internal handshake state machine is to
+    // continuously call SSLRead() until the handshake is marked complete.
+    // Once the handshake is completed, if it completed successfully, the
+    // user read callback is invoked with |bytes_read_after_renegotiation_|
+    // as the callback result. On 10.6.0+, both errSSLServerAuthCompleted
+    // and SSLHandshake() work as expected, so this strange workaround is
+    // only necessary while OS X 10.5.x is still supported.
+    bytes_read_after_renegotiation_ = 0;
+    status = SSLRead(ssl_context_, user_read_buf_->data(),
+                     user_read_buf_len_, &bytes_read_after_renegotiation_);
+    if (bytes_read_after_renegotiation_ > 0) {
+      // With SecureTransport, as of 10.6.5, if application data is read,
+      // then the handshake should be completed. This is because
+      // SecureTransport does not (yet) support exchanging application data
+      // in the midst of handshakes. This is permitted in the TLS
+      // specification, as peers may exchange messages using the previous
+      // cipher spec up until they exchange ChangeCipherSpec messages.
+      // However, in addition to SecureTransport not supporting this, we do
+      // not permit callers to enter Read() or Write() when a handshake is
+      // occurring, in part due to the deception that happens in
+      // SSLWriteCallback(). Thus we need to make sure the handshake is
+      // truly completed before processing application data, and if any was
+      // read before the handshake is completed, it will be dropped and the
+      // connection aborted.
+      SSLSessionState session_state = kSSLIdle;
+      status = SSLGetSessionState(ssl_context_, &session_state);
+      if (session_state != kSSLConnected)
+        status = errSSLProtocol;
+    }
+  }
 
   SSLClientCertificateState client_cert_state;
   if (SSLGetClientCertificateState(ssl_context_, &client_cert_state) != noErr)
@@ -1149,9 +1176,6 @@
   OSStatus status = SSLRead(ssl_context_, user_read_buf_->data(),
                             user_read_buf_len_, &processed);
   if (status == errSSLWouldBlock && renegotiating_) {
-    if (g_renegotiation_broken.Get().broken)
-      return ERR_SSL_RENEGOTIATION_REQUESTED;
-
     CHECK_EQ(static_cast<size_t>(0), processed);
     next_handshake_state_ = STATE_HANDSHAKE;
     return DoHandshakeLoop(OK);
@@ -1198,12 +1222,13 @@
 }
 
 int SSLClientSocketMac::DoCompletedRenegotiation(int result) {
-  // The user had a read in progress, which was usurped by the renegotiation.
-  // Restart the read sequence.
+  // The user had a read in progress, which was interrupted by the
+  // renegotiation. Return the application data that was processed after the
+  // handshake completed.
   next_handshake_state_ = STATE_COMPLETED_HANDSHAKE;
   if (result != OK)
     return result;
-  return DoPayloadRead();
+  return bytes_read_after_renegotiation_;
 }
 
 void SSLClientSocketMac::DidCompleteRenegotiation() {
diff --git a/net/socket/ssl_client_socket_mac.h b/net/socket/ssl_client_socket_mac.h
index 0a43e2f..502ef6d 100644
--- a/net/socket/ssl_client_socket_mac.h
+++ b/net/socket/ssl_client_socket_mac.h
@@ -153,6 +153,10 @@
   bool client_cert_requested_;
   SSLContextRef ssl_context_;
 
+  // During a renegotiation, the amount of application data read following
+  // the handshake's completion.
+  size_t bytes_read_after_renegotiation_;
+
   // These buffers hold data retrieved from/sent to the underlying transport
   // before it's fed to the SSL engine.
   std::vector<char> send_buffer_;
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index b12c59d..fcace50 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -60,12 +60,15 @@
 #include <sslerr.h>
 #include <sslproto.h>
 
+#include <algorithm>
 #include <limits>
+#include <map>
 
 #include "base/compiler_specific.h"
-#include "base/metrics/histogram.h"
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/nss_util.h"
+#include "base/singleton.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
@@ -92,9 +95,6 @@
 #include "net/socket/ssl_error_params.h"
 #include "net/socket/ssl_host_info.h"
 
-#if defined(USE_SYSTEM_SSL)
-#include <dlfcn.h>
-#endif
 #if defined(OS_WIN)
 #include <windows.h>
 #include <wincrypt.h>
@@ -102,6 +102,8 @@
 #include <Security/SecBase.h>
 #include <Security/SecCertificate.h>
 #include <Security/SecIdentity.h>
+#elif defined(USE_NSS)
+#include <dlfcn.h>
 #endif
 
 static const int kRecvBufferSize = 4096;
@@ -112,25 +114,64 @@
 // and some will time out such sockets quite aggressively.
 static const int kCorkTimeoutMs = 200;
 
-#if defined(OS_LINUX)
+#if defined(OS_WIN)
+// CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be
+// set on Windows XP without error. There is some overhead from the server
+// sending the OCSP response if it supports the extension, for the subset of
+// XP clients who will request it but be unable to use it, but this is an
+// acceptable trade-off for simplicity of implementation.
+static bool IsOCSPStaplingSupported() {
+  return true;
+}
+#elif defined(USE_NSS)
+typedef SECStatus
+(*CacheOCSPResponseFromSideChannelFunction)(
+    CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
+    SECItem *encodedResponse, void *pwArg);
+
 // On Linux, we dynamically link against the system version of libnss3.so. In
 // order to continue working on systems without up-to-date versions of NSS we
-// declare CERT_CacheOCSPResponseFromSideChannel to be a weak symbol. If, at
-// run time, we find that the symbol didn't resolve then we can avoid calling
-// the function.
-extern SECStatus
-CERT_CacheOCSPResponseFromSideChannel(
-    CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
-    SECItem *encodedResponse, void *pwArg) __attribute__((weak));
+// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym.
 
-static bool HaveCacheOCSPResponseFromSideChannelFunction() {
-  return CERT_CacheOCSPResponseFromSideChannel != NULL;
+// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any
+// runtime symbol resolution that we need.
+class RuntimeLibNSSFunctionPointers {
+ public:
+  CacheOCSPResponseFromSideChannelFunction
+  GetCacheOCSPResponseFromSideChannelFunction() {
+    return cache_ocsp_response_from_side_channel_;
+  }
+
+  static RuntimeLibNSSFunctionPointers* GetInstance() {
+    return Singleton<RuntimeLibNSSFunctionPointers>::get();
+  }
+
+ private:
+  friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>;
+
+  RuntimeLibNSSFunctionPointers() {
+    cache_ocsp_response_from_side_channel_ =
+        (CacheOCSPResponseFromSideChannelFunction)
+        dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel");
+  }
+
+  CacheOCSPResponseFromSideChannelFunction
+      cache_ocsp_response_from_side_channel_;
+};
+
+static CacheOCSPResponseFromSideChannelFunction
+GetCacheOCSPResponseFromSideChannelFunction() {
+  return RuntimeLibNSSFunctionPointers::GetInstance()
+    ->GetCacheOCSPResponseFromSideChannelFunction();
+}
+
+static bool IsOCSPStaplingSupported() {
+  return GetCacheOCSPResponseFromSideChannelFunction() != NULL;
 }
 #else
-// On other platforms we use the system's certificate validation functions.
-// Thus we need, in the future, to plumb the OCSP response into those system
-// functions. Until then, we act as if we didn't support OCSP stapling.
-static bool HaveCacheOCSPResponseFromSideChannelFunction() {
+// TODO(agl): Figure out if we can plumb the OCSP response into Mac's system
+// certificate validation functions.
+static bool IsOCSPStaplingSupported() {
   return false;
 }
 #endif
@@ -249,6 +290,162 @@
   CERTCertificate** certs_;
 };
 
+void DestroyCertificates(CERTCertificate** certs, unsigned len) {
+  for (unsigned i = 0; i < len; i++)
+    CERT_DestroyCertificate(certs[i]);
+}
+
+// DNSValidationResult enumerates the possible outcomes from processing a
+// set of DNS records.
+enum DNSValidationResult {
+  DNSVR_SUCCESS,   // the cert is immediately acceptable.
+  DNSVR_FAILURE,   // the cert is unconditionally rejected.
+  DNSVR_CONTINUE,  // perform CA validation as usual.
+};
+
+// VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and
+// checks them against the given certificate.
+//   dnssec: if true then the TXT records are DNSSEC validated. In this case,
+//       DNSVR_SUCCESS may be returned.
+//    server_cert_nss: the certificate to validate
+//    rrdatas: the TXT records for the current domain.
+DNSValidationResult VerifyTXTRecords(
+    bool dnssec,
+    CERTCertificate* server_cert_nss,
+    const std::vector<base::StringPiece>& rrdatas) {
+  bool found_well_formed_record = false;
+  bool matched_record = false;
+
+  for (std::vector<base::StringPiece>::const_iterator
+       i = rrdatas.begin(); i != rrdatas.end(); ++i) {
+    std::map<std::string, std::string> m(
+        DNSSECChainVerifier::ParseTLSTXTRecord(*i));
+    if (m.empty())
+      continue;
+
+    std::map<std::string, std::string>::const_iterator j;
+    j = m.find("v");
+    if (j == m.end() || j->second != "tls1")
+      continue;
+
+    j = m.find("ha");
+
+    HASH_HashType hash_algorithm;
+    unsigned hash_length;
+    if (j == m.end() || j->second == "sha1") {
+      hash_algorithm = HASH_AlgSHA1;
+      hash_length = SHA1_LENGTH;
+    } else if (j->second == "sha256") {
+      hash_algorithm = HASH_AlgSHA256;
+      hash_length = SHA256_LENGTH;
+    } else {
+      continue;
+    }
+
+    j = m.find("h");
+    if (j == m.end())
+      continue;
+
+    std::vector<uint8> given_hash;
+    if (!base::HexStringToBytes(j->second, &given_hash))
+      continue;
+
+    if (given_hash.size() != hash_length)
+      continue;
+
+    uint8 calculated_hash[SHA256_LENGTH];  // SHA256 is the largest.
+    SECStatus rv;
+
+    j = m.find("hr");
+    if (j == m.end() || j->second == "pubkey") {
+      rv = HASH_HashBuf(hash_algorithm, calculated_hash,
+                        server_cert_nss->derPublicKey.data,
+                        server_cert_nss->derPublicKey.len);
+    } else if (j->second == "cert") {
+      rv = HASH_HashBuf(hash_algorithm, calculated_hash,
+                        server_cert_nss->derCert.data,
+                        server_cert_nss->derCert.len);
+    } else {
+      continue;
+    }
+
+    if (rv != SECSuccess)
+      NOTREACHED();
+
+    found_well_formed_record = true;
+
+    if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) {
+      matched_record = true;
+      if (dnssec)
+        return DNSVR_SUCCESS;
+    }
+  }
+
+  if (found_well_formed_record && !matched_record)
+    return DNSVR_FAILURE;
+
+  return DNSVR_CONTINUE;
+}
+
+// CheckDNSSECChain tries to validate a DNSSEC chain embedded in
+// |server_cert_nss_|. It returns true iff a chain is found that proves the
+// value of a TXT record that contains a valid public key fingerprint.
+DNSValidationResult CheckDNSSECChain(
+    const std::string& hostname,
+    CERTCertificate* server_cert_nss) {
+  if (!server_cert_nss)
+    return DNSVR_CONTINUE;
+
+  // CERT_FindCertExtensionByOID isn't exported so we have to install an OID,
+  // get a tag for it and find the extension by using that tag.
+  static SECOidTag dnssec_chain_tag;
+  static bool dnssec_chain_tag_valid;
+  if (!dnssec_chain_tag_valid) {
+    // It's harmless if multiple threads enter this block concurrently.
+    static const uint8 kDNSSECChainOID[] =
+        // 1.3.6.1.4.1.11129.2.1.4
+        // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
+        //  certificateExtensions.dnssecEmbeddedChain)
+        {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04};
+    SECOidData oid_data;
+    memset(&oid_data, 0, sizeof(oid_data));
+    oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID);
+    oid_data.oid.len = sizeof(kDNSSECChainOID);
+    oid_data.desc = "DNSSEC chain";
+    oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
+    dnssec_chain_tag = SECOID_AddEntry(&oid_data);
+    DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag);
+    dnssec_chain_tag_valid = true;
+  }
+
+  SECItem dnssec_embedded_chain;
+  SECStatus rv = CERT_FindCertExtension(server_cert_nss,
+      dnssec_chain_tag, &dnssec_embedded_chain);
+  if (rv != SECSuccess)
+    return DNSVR_CONTINUE;
+
+  base::StringPiece chain(
+      reinterpret_cast<char*>(dnssec_embedded_chain.data),
+      dnssec_embedded_chain.len);
+  std::string dns_hostname;
+  if (!DNSDomainFromDot(hostname, &dns_hostname))
+    return DNSVR_CONTINUE;
+  DNSSECChainVerifier verifier(dns_hostname, chain);
+  DNSSECChainVerifier::Error err = verifier.Verify();
+  if (err != DNSSECChainVerifier::OK) {
+    LOG(ERROR) << "DNSSEC chain verification failed: " << err;
+    return DNSVR_CONTINUE;
+  }
+
+  if (verifier.rrtype() != kDNS_TXT)
+    return DNSVR_CONTINUE;
+
+  DNSValidationResult r = VerifyTXTRecords(
+      true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas());
+  SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
+  return r;
+}
+
 }  // namespace
 
 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
@@ -293,7 +490,8 @@
       predicted_npn_status_(kNextProtoUnsupported),
       predicted_npn_proto_used_(false),
       ssl_host_info_(ssl_host_info),
-      dns_cert_checker_(dns_ctx) {
+      dns_cert_checker_(dns_ctx),
+      valid_thread_id_(base::kInvalidThreadId) {
   EnterFunction("");
 }
 
@@ -303,155 +501,94 @@
   LeaveFunction("");
 }
 
-int SSLClientSocketNSS::Init() {
+// static
+void SSLClientSocketNSS::ClearSessionCache() {
+  SSL_ClearSessionCache();
+}
+
+void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
   EnterFunction("");
-  // Initialize the NSS SSL library in a threadsafe way.  This also
-  // initializes the NSS base library.
-  EnsureNSSSSLInit();
-  if (!NSS_IsInitialized())
-    return ERR_UNEXPECTED;
-#if !defined(OS_MACOSX) && !defined(OS_WIN)
-  // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
-  // by MessageLoopForIO::current().
-  // X509Certificate::Verify() runs on a worker thread of CertVerifier.
-  EnsureOCSPInit();
-#endif
+  ssl_info->Reset();
 
-  LeaveFunction("");
-  return OK;
-}
-
-// SaveSnapStartInfo extracts the information needed to perform a Snap Start
-// with this server in the future (if any) and tells |ssl_host_info_| to
-// preserve it.
-void SSLClientSocketNSS::SaveSnapStartInfo() {
-  if (!ssl_host_info_.get())
-    return;
-
-  // If the SSLHostInfo hasn't managed to load from disk yet then we can't save
-  // anything.
-  if (ssl_host_info_->WaitForDataReady(NULL) != OK)
-    return;
-
-  SECStatus rv;
-  SSLSnapStartResult snap_start_type;
-  rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return;
-  }
-  net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START,
-                    new NetLogIntegerParameter("type", snap_start_type));
-  if (snap_start_type == SSL_SNAP_START_FULL ||
-      snap_start_type == SSL_SNAP_START_RESUME) {
-    // If we did a successful Snap Start then our information was correct and
-    // there's no point saving it again.
+  if (!server_cert_) {
+    LOG(DFATAL) << "!server_cert_";
     return;
   }
 
-  const unsigned char* hello_data;
-  unsigned hello_data_len;
-  rv = SSL_GetPredictedServerHelloData(nss_fd_, &hello_data, &hello_data_len);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return;
-  }
-  if (hello_data_len > std::numeric_limits<uint16>::max())
-    return;
-  SSLHostInfo::State* state = ssl_host_info_->mutable_state();
-  state->server_hello =
-      std::string(reinterpret_cast<const char *>(hello_data), hello_data_len);
+  ssl_info->cert_status = server_cert_verify_result_->cert_status;
+  DCHECK(server_cert_ != NULL);
+  ssl_info->cert = server_cert_;
+  ssl_info->connection_status = ssl_connection_status_;
 
-  if (hello_data_len > 0) {
-    state->npn_valid = true;
-    state->npn_status = GetNextProto(&state->npn_protocol);
+  PRUint16 cipher_suite =
+      SSLConnectionStatusToCipherSuite(ssl_connection_status_);
+  SSLCipherSuiteInfo cipher_info;
+  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
+                                        &cipher_info, sizeof(cipher_info));
+  if (ok == SECSuccess) {
+    ssl_info->security_bits = cipher_info.effectiveKeyBits;
   } else {
-    state->npn_valid = false;
+    ssl_info->security_bits = -1;
+    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
+                << " for cipherSuite " << cipher_suite;
   }
-
-  state->certs.clear();
-  PeerCertificateChain certs(nss_fd_);
-  for (unsigned i = 0; i < certs.size(); i++) {
-    if (certs[i]->derCert.len > std::numeric_limits<uint16>::max())
-      return;
-
-    state->certs.push_back(std::string(
-          reinterpret_cast<char*>(certs[i]->derCert.data),
-          certs[i]->derCert.len));
-  }
-
-  ssl_host_info_->Persist();
+  LeaveFunction("");
 }
 
-static void DestroyCertificates(CERTCertificate** certs, unsigned len) {
-  for (unsigned i = 0; i < len; i++)
-    CERT_DestroyCertificate(certs[i]);
+void SSLClientSocketNSS::GetSSLCertRequestInfo(
+    SSLCertRequestInfo* cert_request_info) {
+  EnterFunction("");
+  // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair
+  cert_request_info->host_and_port = host_and_port_.ToString();
+  cert_request_info->client_certs = client_certs_;
+  LeaveFunction(cert_request_info->client_certs.size());
 }
 
-// LoadSnapStartInfo parses |info|, which contains data previously serialised
-// by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello
-// data on the NSS socket. Returns true on success. If this function returns
-// false, the caller should try a normal TLS handshake.
-bool SSLClientSocketNSS::LoadSnapStartInfo() {
-  const SSLHostInfo::State& state(ssl_host_info_->state());
-
-  if (state.server_hello.empty() ||
-      state.certs.empty() ||
-      !state.npn_valid) {
-    return false;
+SSLClientSocket::NextProtoStatus
+SSLClientSocketNSS::GetNextProto(std::string* proto) {
+#if defined(SSL_NEXT_PROTO_NEGOTIATED)
+  if (!handshake_callback_called_) {
+    DCHECK(pseudo_connected_);
+    predicted_npn_proto_used_ = true;
+    *proto = predicted_npn_proto_;
+    return predicted_npn_status_;
   }
 
-  SECStatus rv;
-  rv = SSL_SetPredictedServerHelloData(
-      nss_fd_,
-      reinterpret_cast<const uint8*>(state.server_hello.data()),
-      state.server_hello.size());
-  DCHECK_EQ(SECSuccess, rv);
-
-  const std::vector<std::string>& certs_in = state.certs;
-  scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
-  for (size_t i = 0; i < certs_in.size(); i++) {
-    SECItem derCert;
-    derCert.data =
-        const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
-    derCert.len = certs_in[i].size();
-    certs[i] = CERT_NewTempCertificate(
-        CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
-        PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
-    if (!certs[i]) {
-      DestroyCertificates(&certs[0], i);
-      NOTREACHED();
-      return false;
-    }
+  unsigned char buf[255];
+  int state;
+  unsigned len;
+  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
+  if (rv != SECSuccess) {
+    NOTREACHED() << "Error return from SSL_GetNextProto: " << rv;
+    proto->clear();
+    return kNextProtoUnsupported;
   }
-
-  rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
-  DestroyCertificates(&certs[0], certs_in.size());
-  DCHECK_EQ(SECSuccess, rv);
-
-  if (state.npn_valid) {
-    predicted_npn_status_ = state.npn_status;
-    predicted_npn_proto_ = state.npn_protocol;
+  // We don't check for truncation because sizeof(buf) is large enough to hold
+  // the maximum protocol size.
+  switch (state) {
+    case SSL_NEXT_PROTO_NO_SUPPORT:
+      proto->clear();
+      return kNextProtoUnsupported;
+    case SSL_NEXT_PROTO_NEGOTIATED:
+      *proto = std::string(reinterpret_cast<char*>(buf), len);
+      return kNextProtoNegotiated;
+    case SSL_NEXT_PROTO_NO_OVERLAP:
+      *proto = std::string(reinterpret_cast<char*>(buf), len);
+      return kNextProtoNoOverlap;
+    default:
+      NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state;
+      proto->clear();
+      return kNextProtoUnsupported;
   }
-
-  return true;
+#else
+  // No NPN support in the libssl that we are building with.
+  proto->clear();
+  return kNextProtoUnsupported;
+#endif
 }
 
-bool SSLClientSocketNSS::IsNPNProtocolMispredicted() {
-  DCHECK(handshake_callback_called_);
-  if (!predicted_npn_proto_used_)
-    return false;
-  std::string npn_proto;
-  GetNextProto(&npn_proto);
-  return predicted_npn_proto_ != npn_proto;
-}
-
-void SSLClientSocketNSS::UncorkAfterTimeout() {
-  corked_ = false;
-  int nsent;
-  do {
-    nsent = BufferSend();
-  } while (nsent > 0);
+void SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) {
+  dnssec_provider_ = provider;
 }
 
 #ifdef ANDROID
@@ -473,17 +610,19 @@
   DCHECK(!user_write_buf_);
   DCHECK(!pseudo_connected_);
 
+  EnsureThreadIdAssigned();
+
   net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
 
   int rv = Init();
   if (rv != OK) {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
     return rv;
   }
 
   rv = InitializeSSLOptions();
   if (rv != OK) {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
     return rv;
   }
 
@@ -492,7 +631,7 @@
   if (!UsingTCPFastOpen()) {
     rv = InitializeSSLPeerName();
     if (rv != OK) {
-      net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+      net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
       return rv;
     }
   }
@@ -512,256 +651,29 @@
       user_connect_callback_ = callback;
     }
   } else {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
   }
 
   LeaveFunction("");
   return rv > OK ? OK : rv;
 }
 
-int SSLClientSocketNSS::InitializeSSLOptions() {
-  // Transport connected, now hook it up to nss
-  // TODO(port): specify rx and tx buffer sizes separately
-  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
-  if (nss_fd_ == NULL) {
-    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
-  }
-
-  // Grab pointer to buffers
-  nss_bufs_ = memio_GetSecret(nss_fd_);
-
-  /* Create SSL state machine */
-  /* Push SSL onto our fake I/O socket */
-  nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
-  if (nss_fd_ == NULL) {
-    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
-    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
-  }
-  // TODO(port): set more ssl options!  Check errors!
-
-  int rv;
-
-  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
-    return ERR_UNEXPECTED;
-  }
-
-  // Don't do V2 compatible hellos because they don't support TLS extensions.
-  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
-    return ERR_UNEXPECTED;
-  }
-
-  for (std::vector<uint16>::const_iterator it =
-           ssl_config_.disabled_cipher_suites.begin();
-       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
-    // This will fail if the specified cipher is not implemented by NSS, but
-    // the failure is harmless.
-    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
-  }
-
-#ifdef SSL_ENABLE_SESSION_TICKETS
-  // Support RFC 5077
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(
-        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
-  }
-#else
-  #error "You need to install NSS-3.12 or later to build chromium"
-#endif
-
-  rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE,
-                     ssl_config_.session_resume_disabled);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE");
-    return ERR_UNEXPECTED;
-  }
-
-#ifdef SSL_ENABLE_DEFLATE
-  // Some web servers have been found to break if TLS is used *or* if DEFLATE
-  // is advertised. Thus, if TLS is disabled (probably because we are doing
-  // SSLv3 fallback), we disable DEFLATE also.
-  // See http://crbug.com/31628
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
-  if (rv != SECSuccess)
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE");
-#endif
-
-#ifdef SSL_ENABLE_FALSE_START
-  rv = SSL_OptionSet(
-      nss_fd_, SSL_ENABLE_FALSE_START,
-      ssl_config_.false_start_enabled &&
-      !SSLConfigService::IsKnownFalseStartIncompatibleServer(
-          host_and_port_.host()));
-  if (rv != SECSuccess)
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
-#endif
-
-#ifdef SSL_ENABLE_SNAP_START
-  // TODO(agl): check that SSL_ENABLE_SNAP_START actually does something in the
-  // current NSS code.
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SNAP_START,
-                     ssl_config_.snap_start_enabled);
-  if (rv != SECSuccess)
-    VLOG(1) << "SSL_ENABLE_SNAP_START failed.  Old system nss?";
-#endif
-
-#ifdef SSL_ENABLE_RENEGOTIATION
-  // Deliberately disable this check for now: http://crbug.com/55410
-  if (false &&
-      SSLConfigService::IsKnownStrictTLSServer(host_and_port_.host()) &&
-      !ssl_config_.mitm_proxies_allowed) {
-    rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
-    if (rv != SECSuccess) {
-      LogFailedNSSFunction(
-          net_log_, "SSL_OptionSet", "SSL_REQUIRE_SAFE_NEGOTIATION");
-    }
-    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
-                       SSL_RENEGOTIATE_REQUIRES_XTN);
-  } else {
-    // We allow servers to request renegotiation. Since we're a client,
-    // prohibiting this is rather a waste of time. Only servers are in a
-    // position to prevent renegotiation attacks.
-    // http://extendedsubset.com/?p=8
-
-    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
-                       SSL_RENEGOTIATE_TRANSITIONAL);
-  }
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(
-        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
-  }
-#endif  // SSL_ENABLE_RENEGOTIATION
-
-#ifdef SSL_NEXT_PROTO_NEGOTIATED
-  if (!ssl_config_.next_protos.empty()) {
-    rv = SSL_SetNextProtoNego(
-       nss_fd_,
-       reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()),
-       ssl_config_.next_protos.size());
-    if (rv != SECSuccess)
-      LogFailedNSSFunction(net_log_, "SSL_SetNextProtoNego", "");
-  }
-#endif
-
-#ifdef SSL_ENABLE_OCSP_STAPLING
-  if (HaveCacheOCSPResponseFromSideChannelFunction() &&
-      !ssl_config_.snap_start_enabled) {
-    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
-    if (rv != SECSuccess)
-      LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", "");
-  }
-#endif
-
-  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
-    return ERR_UNEXPECTED;
-  }
-
-#if defined(NSS_PLATFORM_CLIENT_AUTH)
-  rv = SSL_GetPlatformClientAuthDataHook(nss_fd_, PlatformClientAuthHandler,
-                                         this);
-#else
-  rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
-#endif
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_GetClientAuthDataHook", "");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
-    return ERR_UNEXPECTED;
-  }
-
-  // Tell SSL the hostname we're trying to connect to.
-  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
-
-  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
-  SSL_ResetHandshake(nss_fd_, 0);
-
-  return OK;
-}
-
-int SSLClientSocketNSS::InitializeSSLPeerName() {
-  // Tell NSS who we're connected to
-  AddressList peer_address;
-  int err = transport_->socket()->GetPeerAddress(&peer_address);
-  if (err != OK)
-    return err;
-
-  const struct addrinfo* ai = peer_address.head();
-
-  PRNetAddr peername;
-  memset(&peername, 0, sizeof(peername));
-  DCHECK_LE(ai->ai_addrlen, sizeof(peername));
-  size_t len = std::min(static_cast<size_t>(ai->ai_addrlen),
-                        sizeof(peername));
-  memcpy(&peername, ai->ai_addr, len);
-
-  // Adjust the address family field for BSD, whose sockaddr
-  // structure has a one-byte length and one-byte address family
-  // field at the beginning.  PRNetAddr has a two-byte address
-  // family field at the beginning.
-  peername.raw.family = ai->ai_addr->sa_family;
-
-  memio_SetPeerName(nss_fd_, &peername);
-
-  // Set the peer ID for session reuse.  This is necessary when we create an
-  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
-  // rather than the destination server's address in that case.
-  std::string peer_id = host_and_port_.ToString();
-  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
-  if (rv != SECSuccess)
-    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
-
-  peername_initialized_ = true;
-  return OK;
-}
-
 void SSLClientSocketNSS::Disconnect() {
   EnterFunction("");
 
+  // Shut down anything that may call us back (through buffer_send_callback_,
+  // buffer_recv_callback, or handshake_io_callback_).
+  verifier_.reset();
+  transport_->socket()->Disconnect();
+
+  CHECK(CalledOnValidThread());
+
   // TODO(wtc): Send SSL close_notify alert.
   if (nss_fd_ != NULL) {
     PR_Close(nss_fd_);
     nss_fd_ = NULL;
   }
 
-  // Shut down anything that may call us back (through buffer_send_callback_,
-  // buffer_recv_callback, or handshake_io_callback_).
-  verifier_.reset();
-  transport_->socket()->Disconnect();
-
   // Reset object state
   transport_send_busy_   = false;
   transport_recv_busy_   = false;
@@ -952,11 +864,246 @@
   return transport_->socket()->SetSendBufferSize(size);
 }
 
-// static
-void SSLClientSocketNSS::ClearSessionCache() {
-  SSL_ClearSessionCache();
+int SSLClientSocketNSS::Init() {
+  EnterFunction("");
+  // Initialize the NSS SSL library in a threadsafe way.  This also
+  // initializes the NSS base library.
+  EnsureNSSSSLInit();
+  if (!NSS_IsInitialized())
+    return ERR_UNEXPECTED;
+#if !defined(OS_MACOSX) && !defined(OS_WIN)
+  // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
+  // by MessageLoopForIO::current().
+  // X509Certificate::Verify() runs on a worker thread of CertVerifier.
+  EnsureOCSPInit();
+#endif
+
+  LeaveFunction("");
+  return OK;
 }
 
+int SSLClientSocketNSS::InitializeSSLOptions() {
+  // Transport connected, now hook it up to nss
+  // TODO(port): specify rx and tx buffer sizes separately
+  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
+  if (nss_fd_ == NULL) {
+    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
+  }
+
+  // Grab pointer to buffers
+  nss_bufs_ = memio_GetSecret(nss_fd_);
+
+  /* Create SSL state machine */
+  /* Push SSL onto our fake I/O socket */
+  nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
+  if (nss_fd_ == NULL) {
+    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
+    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
+  }
+  // TODO(port): set more ssl options!  Check errors!
+
+  int rv;
+
+  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
+    return ERR_UNEXPECTED;
+  }
+
+  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
+    return ERR_UNEXPECTED;
+  }
+
+  // Don't do V2 compatible hellos because they don't support TLS extensions.
+  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
+    return ERR_UNEXPECTED;
+  }
+
+  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
+    return ERR_UNEXPECTED;
+  }
+
+  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
+    return ERR_UNEXPECTED;
+  }
+
+  for (std::vector<uint16>::const_iterator it =
+           ssl_config_.disabled_cipher_suites.begin();
+       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
+    // This will fail if the specified cipher is not implemented by NSS, but
+    // the failure is harmless.
+    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
+  }
+
+#ifdef SSL_ENABLE_SESSION_TICKETS
+  // Support RFC 5077
+  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(
+        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
+  }
+#else
+  #error "You need to install NSS-3.12 or later to build chromium"
+#endif
+
+#ifdef SSL_ENABLE_DEFLATE
+  // Some web servers have been found to break if TLS is used *or* if DEFLATE
+  // is advertised. Thus, if TLS is disabled (probably because we are doing
+  // SSLv3 fallback), we disable DEFLATE also.
+  // See http://crbug.com/31628
+  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
+  if (rv != SECSuccess)
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE");
+#endif
+
+#ifdef SSL_ENABLE_FALSE_START
+  rv = SSL_OptionSet(
+      nss_fd_, SSL_ENABLE_FALSE_START,
+      ssl_config_.false_start_enabled &&
+      !SSLConfigService::IsKnownFalseStartIncompatibleServer(
+          host_and_port_.host()));
+  if (rv != SECSuccess)
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
+#endif
+
+#ifdef SSL_ENABLE_SNAP_START
+  // TODO(agl): check that SSL_ENABLE_SNAP_START actually does something in the
+  // current NSS code.
+  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SNAP_START,
+                     ssl_config_.snap_start_enabled);
+  if (rv != SECSuccess)
+    VLOG(1) << "SSL_ENABLE_SNAP_START failed.  Old system nss?";
+#endif
+
+#ifdef SSL_ENABLE_RENEGOTIATION
+  // Deliberately disable this check for now: http://crbug.com/55410
+  if (false &&
+      SSLConfigService::IsKnownStrictTLSServer(host_and_port_.host()) &&
+      !ssl_config_.mitm_proxies_allowed) {
+    rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
+    if (rv != SECSuccess) {
+      LogFailedNSSFunction(
+          net_log_, "SSL_OptionSet", "SSL_REQUIRE_SAFE_NEGOTIATION");
+    }
+    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
+                       SSL_RENEGOTIATE_REQUIRES_XTN);
+  } else {
+    // We allow servers to request renegotiation. Since we're a client,
+    // prohibiting this is rather a waste of time. Only servers are in a
+    // position to prevent renegotiation attacks.
+    // http://extendedsubset.com/?p=8
+
+    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
+                       SSL_RENEGOTIATE_TRANSITIONAL);
+  }
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(
+        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
+  }
+#endif  // SSL_ENABLE_RENEGOTIATION
+
+#ifdef SSL_NEXT_PROTO_NEGOTIATED
+  if (!ssl_config_.next_protos.empty()) {
+    rv = SSL_SetNextProtoNego(
+       nss_fd_,
+       reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()),
+       ssl_config_.next_protos.size());
+    if (rv != SECSuccess)
+      LogFailedNSSFunction(net_log_, "SSL_SetNextProtoNego", "");
+  }
+#endif
+
+#ifdef SSL_ENABLE_OCSP_STAPLING
+  if (IsOCSPStaplingSupported() && !ssl_config_.snap_start_enabled) {
+    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
+    if (rv != SECSuccess)
+      LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", "");
+  }
+#endif
+
+  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
+    return ERR_UNEXPECTED;
+  }
+
+  rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
+    return ERR_UNEXPECTED;
+  }
+
+#if defined(NSS_PLATFORM_CLIENT_AUTH)
+  rv = SSL_GetPlatformClientAuthDataHook(nss_fd_, PlatformClientAuthHandler,
+                                         this);
+#else
+  rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
+#endif
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_GetClientAuthDataHook", "");
+    return ERR_UNEXPECTED;
+  }
+
+  rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
+  if (rv != SECSuccess) {
+    LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
+    return ERR_UNEXPECTED;
+  }
+
+  // Tell SSL the hostname we're trying to connect to.
+  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
+
+  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
+  SSL_ResetHandshake(nss_fd_, 0);
+
+  return OK;
+}
+
+int SSLClientSocketNSS::InitializeSSLPeerName() {
+  // Tell NSS who we're connected to
+  AddressList peer_address;
+  int err = transport_->socket()->GetPeerAddress(&peer_address);
+  if (err != OK)
+    return err;
+
+  const struct addrinfo* ai = peer_address.head();
+
+  PRNetAddr peername;
+  memset(&peername, 0, sizeof(peername));
+  DCHECK_LE(ai->ai_addrlen, sizeof(peername));
+  size_t len = std::min(static_cast<size_t>(ai->ai_addrlen),
+                        sizeof(peername));
+  memcpy(&peername, ai->ai_addr, len);
+
+  // Adjust the address family field for BSD, whose sockaddr
+  // structure has a one-byte length and one-byte address family
+  // field at the beginning.  PRNetAddr has a two-byte address
+  // family field at the beginning.
+  peername.raw.family = ai->ai_addr->sa_family;
+
+  memio_SetPeerName(nss_fd_, &peername);
+
+  // Set the peer ID for session reuse.  This is necessary when we create an
+  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
+  // rather than the destination server's address in that case.
+  std::string peer_id = host_and_port_.ToString();
+  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
+  if (rv != SECSuccess)
+    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
+
+  peername_initialized_ = true;
+  return OK;
+}
+
+
 // Sets server_cert_ and server_cert_nss_ if not yet set.
 // Returns server_cert_.
 X509Certificate *SSLClientSocketNSS::UpdateServerCert() {
@@ -1035,91 +1182,6 @@
     ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK;
 }
 
-void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
-  EnterFunction("");
-  ssl_info->Reset();
-
-  if (!server_cert_) {
-    LOG(DFATAL) << "!server_cert_";
-    return;
-  }
-
-  ssl_info->cert_status = server_cert_verify_result_->cert_status;
-  DCHECK(server_cert_ != NULL);
-  ssl_info->cert = server_cert_;
-  ssl_info->connection_status = ssl_connection_status_;
-
-  PRUint16 cipher_suite =
-      SSLConnectionStatusToCipherSuite(ssl_connection_status_);
-  SSLCipherSuiteInfo cipher_info;
-  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
-                                        &cipher_info, sizeof(cipher_info));
-  if (ok == SECSuccess) {
-    ssl_info->security_bits = cipher_info.effectiveKeyBits;
-  } else {
-    ssl_info->security_bits = -1;
-    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
-                << " for cipherSuite " << cipher_suite;
-  }
-  LeaveFunction("");
-}
-
-void SSLClientSocketNSS::GetSSLCertRequestInfo(
-    SSLCertRequestInfo* cert_request_info) {
-  EnterFunction("");
-  // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair
-  cert_request_info->host_and_port = host_and_port_.ToString();
-  cert_request_info->client_certs = client_certs_;
-  LeaveFunction(cert_request_info->client_certs.size());
-}
-
-SSLClientSocket::NextProtoStatus
-SSLClientSocketNSS::GetNextProto(std::string* proto) {
-#if defined(SSL_NEXT_PROTO_NEGOTIATED)
-  if (!handshake_callback_called_) {
-    DCHECK(pseudo_connected_);
-    predicted_npn_proto_used_ = true;
-    *proto = predicted_npn_proto_;
-    return predicted_npn_status_;
-  }
-
-  unsigned char buf[255];
-  int state;
-  unsigned len;
-  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
-  if (rv != SECSuccess) {
-    NOTREACHED() << "Error return from SSL_GetNextProto: " << rv;
-    proto->clear();
-    return kNextProtoUnsupported;
-  }
-  // We don't check for truncation because sizeof(buf) is large enough to hold
-  // the maximum protocol size.
-  switch (state) {
-    case SSL_NEXT_PROTO_NO_SUPPORT:
-      proto->clear();
-      return kNextProtoUnsupported;
-    case SSL_NEXT_PROTO_NEGOTIATED:
-      *proto = std::string(reinterpret_cast<char*>(buf), len);
-      return kNextProtoNegotiated;
-    case SSL_NEXT_PROTO_NO_OVERLAP:
-      *proto = std::string(reinterpret_cast<char*>(buf), len);
-      return kNextProtoNoOverlap;
-    default:
-      NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state;
-      proto->clear();
-      return kNextProtoUnsupported;
-  }
-#else
-  // No NPN support in the libssl that we are building with.
-  proto->clear();
-  return kNextProtoUnsupported;
-#endif
-}
-
-void SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) {
-  dnssec_provider_ = provider;
-}
-
 void SSLClientSocketNSS::DoReadCallback(int rv) {
   EnterFunction(rv);
   DCHECK(rv != ERR_IO_PENDING);
@@ -1171,7 +1233,7 @@
   EnterFunction(result);
   int rv = DoHandshakeLoop(result);
   if (rv != ERR_IO_PENDING) {
-    net_log_.EndEvent(net::NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(net::NetLog::TYPE_SSL_CONNECT, rv);
     // If we pseudo connected for Snap Start, then we won't have a connect
     // callback.
     if (user_connect_callback_)
@@ -1234,109 +1296,6 @@
   LeaveFunction("");
 }
 
-// Do network I/O between the given buffer and the given socket.
-// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
-bool SSLClientSocketNSS::DoTransportIO() {
-  EnterFunction("");
-  bool network_moved = false;
-  if (nss_bufs_ != NULL) {
-    int nsent = BufferSend();
-    int nreceived = BufferRecv();
-    network_moved = (nsent > 0 || nreceived >= 0);
-  }
-  LeaveFunction(network_moved);
-  return network_moved;
-}
-
-// Return 0 for EOF,
-// > 0 for bytes transferred immediately,
-// < 0 for error (or the non-error ERR_IO_PENDING).
-int SSLClientSocketNSS::BufferSend(void) {
-  if (transport_send_busy_)
-    return ERR_IO_PENDING;
-
-  EnterFunction("");
-  const char* buf1;
-  const char* buf2;
-  unsigned int len1, len2;
-  memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
-  const unsigned int len = len1 + len2;
-
-  if (corked_ && len < kRecvBufferSize / 2)
-    return 0;
-
-  int rv = 0;
-  if (len) {
-    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
-    memcpy(send_buffer->data(), buf1, len1);
-    memcpy(send_buffer->data() + len1, buf2, len2);
-    rv = transport_->socket()->Write(send_buffer, len,
-                                     &buffer_send_callback_);
-    if (rv == ERR_IO_PENDING) {
-      transport_send_busy_ = true;
-    } else {
-      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
-    }
-  }
-
-  LeaveFunction(rv);
-  return rv;
-}
-
-void SSLClientSocketNSS::BufferSendComplete(int result) {
-  EnterFunction(result);
-
-  // In the case of TCP FastOpen, connect is now finished.
-  if (!peername_initialized_ && UsingTCPFastOpen())
-    InitializeSSLPeerName();
-
-  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
-  transport_send_busy_ = false;
-  OnSendComplete(result);
-  LeaveFunction("");
-}
-
-
-int SSLClientSocketNSS::BufferRecv(void) {
-  if (transport_recv_busy_) return ERR_IO_PENDING;
-
-  char *buf;
-  int nb = memio_GetReadParams(nss_bufs_, &buf);
-  EnterFunction(nb);
-  int rv;
-  if (!nb) {
-    // buffer too full to read into, so no I/O possible at moment
-    rv = ERR_IO_PENDING;
-  } else {
-    recv_buffer_ = new IOBuffer(nb);
-    rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_);
-    if (rv == ERR_IO_PENDING) {
-      transport_recv_busy_ = true;
-    } else {
-      if (rv > 0)
-        memcpy(buf, recv_buffer_->data(), rv);
-      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
-      recv_buffer_ = NULL;
-    }
-  }
-  LeaveFunction(rv);
-  return rv;
-}
-
-void SSLClientSocketNSS::BufferRecvComplete(int result) {
-  EnterFunction(result);
-  if (result > 0) {
-    char *buf;
-    memio_GetReadParams(nss_bufs_, &buf);
-    memcpy(buf, recv_buffer_->data(), result);
-  }
-  recv_buffer_ = NULL;
-  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
-  transport_recv_busy_ = false;
-  OnRecvComplete(result);
-  LeaveFunction("");
-}
-
 int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
   EnterFunction(last_io_result);
   bool network_moved;
@@ -1443,6 +1402,743 @@
   return rv;
 }
 
+int SSLClientSocketNSS::DoSnapStartLoadInfo() {
+  EnterFunction("");
+  int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
+  GotoState(STATE_HANDSHAKE);
+
+  if (rv == OK) {
+    if (ssl_host_info_->WaitForCertVerification(NULL) == OK) {
+      if (LoadSnapStartInfo()) {
+        pseudo_connected_ = true;
+        GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
+        if (user_connect_callback_)
+          DoConnectCallback(OK);
+      }
+    } else if (!ssl_host_info_->state().server_hello.empty()) {
+      // A non-empty ServerHello suggests that we would have tried a Snap Start
+      // connection.
+      base::TimeTicks now = base::TimeTicks::Now();
+      const base::TimeDelta duration =
+          now - ssl_host_info_->verification_start_time();
+      UMA_HISTOGRAM_TIMES("Net.SSLSnapStartNeededVerificationInMs", duration);
+      VLOG(1) << "Cannot snap start because verification isn't ready. "
+              << "Wanted verification after "
+              << duration.InMilliseconds() << "ms";
+    }
+  } else {
+    DCHECK_EQ(ERR_IO_PENDING, rv);
+    GotoState(STATE_SNAP_START_LOAD_INFO);
+  }
+
+  LeaveFunction("");
+  return rv;
+}
+
+int SSLClientSocketNSS::DoSnapStartWaitForWrite() {
+  EnterFunction("");
+  // In this state, we're waiting for the first Write call so that we can merge
+  // it into the Snap Start handshake.
+  if (!user_write_buf_) {
+    // We'll lie and say that we're connected in order that someone will call
+    // Write.
+    GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
+    DCHECK(!user_connect_callback_);
+    LeaveFunction("");
+    return ERR_IO_PENDING;
+  }
+
+  // This is the largest Snap Start application data payload that we'll try to
+  // use. A TCP client can only send three frames of data without an ACK and,
+  // at 2048 bytes, this leaves some space for the rest of the ClientHello
+  // (including possible session ticket).
+  static const int kMaxSnapStartPayloadSize = 2048;
+
+  if (user_write_buf_len_ > kMaxSnapStartPayloadSize) {
+    user_write_buf_len_ = kMaxSnapStartPayloadSize;
+    // When we complete the handshake and call user_write_callback_ we'll say
+    // that we only wrote |kMaxSnapStartPayloadSize| bytes. That way the rest
+    // of the payload will be presented to |Write| again and transmitted as
+    // normal application data.
+  }
+
+  SECStatus rv = SSL_SetSnapStartApplicationData(
+      nss_fd_, reinterpret_cast<const unsigned char*>(user_write_buf_->data()),
+      user_write_buf_len_);
+  DCHECK_EQ(SECSuccess, rv);
+
+  GotoState(STATE_HANDSHAKE);
+  LeaveFunction("");
+  return OK;
+}
+
+int SSLClientSocketNSS::DoHandshake() {
+  EnterFunction("");
+  int net_error = net::OK;
+  SECStatus rv = SSL_ForceHandshake(nss_fd_);
+
+  if (client_auth_cert_needed_) {
+    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
+    net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+                      make_scoped_refptr(new SSLErrorParams(net_error, 0)));
+    // If the handshake already succeeded (because the server requests but
+    // doesn't require a client cert), we need to invalidate the SSL session
+    // so that we won't try to resume the non-client-authenticated session in
+    // the next handshake.  This will cause the server to ask for a client
+    // cert again.
+    if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) {
+      LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
+    }
+  } else if (rv == SECSuccess) {
+    if (handshake_callback_called_) {
+      if (eset_mitm_detected_) {
+        net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION;
+      } else {
+        // We need to see if the predicted certificate chain (in
+        // |ssl_host_info_->state().certs) matches the actual certificate chain
+        // before we call SaveSnapStartInfo, as that will update
+        // |ssl_host_info_|.
+        if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) {
+          PeerCertificateChain certs(nss_fd_);
+          const SSLHostInfo::State& state = ssl_host_info_->state();
+          predicted_cert_chain_correct_ = certs.size() == state.certs.size();
+          if (predicted_cert_chain_correct_) {
+            for (unsigned i = 0; i < certs.size(); i++) {
+              if (certs[i]->derCert.len != state.certs[i].size() ||
+                  memcmp(certs[i]->derCert.data, state.certs[i].data(),
+                         certs[i]->derCert.len) != 0) {
+                predicted_cert_chain_correct_ = false;
+                break;
+              }
+            }
+          }
+        }
+
+#if defined(SSL_ENABLE_OCSP_STAPLING)
+        // TODO(agl): figure out how to plumb an OCSP response into the Mac
+        // system library and update IsOCSPStaplingSupported for Mac.
+        if (!predicted_cert_chain_correct_ && IsOCSPStaplingSupported()) {
+          unsigned int len = 0;
+          SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len);
+          if (len) {
+            const unsigned int orig_len = len;
+            scoped_array<uint8> ocsp_response(new uint8[orig_len]);
+            SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len);
+            DCHECK_EQ(orig_len, len);
+
+#if defined(OS_WIN)
+            CRYPT_DATA_BLOB ocsp_response_blob;
+            ocsp_response_blob.cbData = len;
+            ocsp_response_blob.pbData = ocsp_response.get();
+            BOOL ok = CertSetCertificateContextProperty(
+                server_cert_->os_cert_handle(),
+                CERT_OCSP_RESPONSE_PROP_ID,
+                CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
+                &ocsp_response_blob);
+            if (!ok) {
+              VLOG(1) << "Failed to set OCSP response property: "
+                      << GetLastError();
+            }
+#elif defined(USE_NSS)
+            CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
+                GetCacheOCSPResponseFromSideChannelFunction();
+            SECItem ocsp_response_item;
+            ocsp_response_item.type = siBuffer;
+            ocsp_response_item.data = ocsp_response.get();
+            ocsp_response_item.len = len;
+
+            cache_ocsp_response(
+                CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(),
+                &ocsp_response_item, NULL);
+#endif
+          }
+        }
+#endif
+
+        SaveSnapStartInfo();
+        // SSL handshake is completed. It's possible that we mispredicted the
+        // NPN agreed protocol. In this case, we've just sent a request in the
+        // wrong protocol! The higher levels of this network stack aren't
+        // prepared for switching the protocol like that so we make up an error
+        // and rely on the fact that the request will be retried.
+        if (IsNPNProtocolMispredicted()) {
+          LOG(WARNING) << "Mispredicted NPN protocol for "
+                       << host_and_port_.ToString();
+          net_error = ERR_SSL_SNAP_START_NPN_MISPREDICTION;
+        } else {
+          // Let's verify the certificate.
+          GotoState(STATE_VERIFY_DNSSEC);
+        }
+      }
+      // Done!
+    } else {
+      // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 -
+      // SSL_ForceHandshake returned SECSuccess prematurely.
+      rv = SECFailure;
+      net_error = ERR_SSL_PROTOCOL_ERROR;
+      net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+                        make_scoped_refptr(new SSLErrorParams(net_error, 0)));
+    }
+  } else {
+    PRErrorCode prerr = PR_GetError();
+    net_error = HandleNSSError(prerr, true);
+
+    // If not done, stay in this state
+    if (net_error == ERR_IO_PENDING) {
+      GotoState(STATE_HANDSHAKE);
+    } else {
+      LOG(ERROR) << "handshake failed; NSS error code " << prerr
+                 << ", net_error " << net_error;
+      net_log_.AddEvent(
+          NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+          make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
+    }
+  }
+
+  LeaveFunction("");
+  return net_error;
+}
+
+int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
+  if (ssl_config_.dns_cert_provenance_checking_enabled &&
+      dns_cert_checker_) {
+    PeerCertificateChain certs(nss_fd_);
+    dns_cert_checker_->DoAsyncVerification(
+        host_and_port_.host(), certs.AsStringPieceVector());
+  }
+
+  if (ssl_config_.dnssec_enabled) {
+    DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(),
+                                             server_cert_nss_);
+    if (r == DNSVR_SUCCESS) {
+      local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
+      server_cert_verify_result_ = &local_server_cert_verify_result_;
+      GotoState(STATE_VERIFY_CERT_COMPLETE);
+      return OK;
+    }
+  }
+
+  if (dnssec_provider_ == NULL) {
+    GotoState(STATE_VERIFY_CERT);
+    return OK;
+  }
+
+  GotoState(STATE_VERIFY_DNSSEC_COMPLETE);
+  RRResponse* response;
+  dnssec_wait_start_time_ = base::Time::Now();
+  return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_);
+}
+
+int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
+  RRResponse* response;
+  int err = dnssec_provider_->GetDNSSECRecords(&response, NULL);
+  DCHECK_EQ(err, OK);
+
+  const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_;
+  HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed);
+
+  GotoState(STATE_VERIFY_CERT);
+  if (!response || response->rrdatas.empty())
+    return OK;
+
+  std::vector<base::StringPiece> records;
+  records.resize(response->rrdatas.size());
+  for (unsigned i = 0; i < response->rrdatas.size(); i++)
+    records[i] = base::StringPiece(response->rrdatas[i]);
+  DNSValidationResult r =
+      VerifyTXTRecords(response->dnssec, server_cert_nss_, records);
+
+  if (!ssl_config_.dnssec_enabled) {
+    // If DNSSEC is not enabled we don't take any action based on the result,
+    // except to record the latency, above.
+    return OK;
+  }
+
+  switch (r) {
+    case DNSVR_FAILURE:
+      GotoState(STATE_VERIFY_CERT_COMPLETE);
+      local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS;
+      server_cert_verify_result_ = &local_server_cert_verify_result_;
+      return ERR_CERT_NOT_IN_DNS;
+    case DNSVR_CONTINUE:
+      GotoState(STATE_VERIFY_CERT);
+      break;
+    case DNSVR_SUCCESS:
+      local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
+      server_cert_verify_result_ = &local_server_cert_verify_result_;
+      GotoState(STATE_VERIFY_CERT_COMPLETE);
+      break;
+    default:
+      NOTREACHED();
+      GotoState(STATE_VERIFY_CERT);
+  }
+
+  return OK;
+}
+
+int SSLClientSocketNSS::DoVerifyCert(int result) {
+  DCHECK(server_cert_);
+
+  GotoState(STATE_VERIFY_CERT_COMPLETE);
+  start_cert_verification_time_ = base::TimeTicks::Now();
+
+  if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() &&
+      predicted_cert_chain_correct_) {
+    // If the SSLHostInfo had a prediction for the certificate chain of this
+    // server then it will have optimistically started a verification of that
+    // chain. So, if the prediction was correct, we should wait for that
+    // verification to finish rather than start our own.
+    net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL);
+    UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2);
+    base::TimeTicks end_time = ssl_host_info_->verification_end_time();
+    if (end_time.is_null())
+      end_time = base::TimeTicks::Now();
+    UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved",
+                        end_time - ssl_host_info_->verification_start_time());
+    server_cert_verify_result_ = &ssl_host_info_->cert_verify_result();
+    return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_);
+  } else {
+    UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2);
+  }
+
+  int flags = 0;
+  if (ssl_config_.rev_checking_enabled)
+    flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
+  if (ssl_config_.verify_ev_cert)
+    flags |= X509Certificate::VERIFY_EV_CERT;
+  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
+  server_cert_verify_result_ = &local_server_cert_verify_result_;
+  return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
+                           &local_server_cert_verify_result_,
+                           &handshake_io_callback_);
+}
+
+// Derived from AuthCertificateCallback() in
+// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
+int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
+  verifier_.reset();
+
+  if (!start_cert_verification_time_.is_null()) {
+    base::TimeDelta verify_time =
+        base::TimeTicks::Now() - start_cert_verification_time_;
+    if (result == OK)
+        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
+    else
+        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
+  }
+
+  // We used to remember the intermediate CA certs in the NSS database
+  // persistently.  However, NSS opens a connection to the SQLite database
+  // during NSS initialization and doesn't close the connection until NSS
+  // shuts down.  If the file system where the database resides is gone,
+  // the database connection goes bad.  What's worse, the connection won't
+  // recover when the file system comes back.  Until this NSS or SQLite bug
+  // is fixed, we need to  avoid using the NSS database for non-essential
+  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
+  // http://crbug.com/15630 for more info.
+
+  // If we have been explicitly told to accept this certificate, override the
+  // result of verifier_.Verify.
+  // Eventually, we should cache the cert verification results so that we don't
+  // need to call verifier_.Verify repeatedly.  But for now we need to do this.
+  // Alternatively, we could use the cert's status that we stored along with
+  // the cert in the allowed_bad_certs vector.
+  if (IsCertificateError(result) &&
+      ssl_config_.IsAllowedBadCert(server_cert_)) {
+    VLOG(1) << "accepting bad SSL certificate, as user told us to";
+    result = OK;
+  }
+
+  if (result == OK)
+    LogConnectionTypeMetrics();
+
+  completed_handshake_ = true;
+
+  // If we merged a Write call into the handshake we need to make the
+  // callback now.
+  if (user_write_callback_) {
+    corked_ = false;
+    if (result != OK) {
+      DoWriteCallback(result);
+    } else {
+      SSLSnapStartResult snap_start_type;
+      SECStatus rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
+      DCHECK_EQ(rv, SECSuccess);
+      DCHECK_NE(snap_start_type, SSL_SNAP_START_NONE);
+      if (snap_start_type == SSL_SNAP_START_RECOVERY ||
+          snap_start_type == SSL_SNAP_START_RESUME_RECOVERY) {
+        // If we mispredicted the server's handshake then Snap Start will have
+        // triggered a recovery mode. The misprediction could have been caused
+        // by the server having a different certificate so the application data
+        // wasn't resent. Now that we have verified the certificate, we need to
+        // resend the application data.
+        int bytes_written = DoPayloadWrite();
+        if (bytes_written != ERR_IO_PENDING)
+          DoWriteCallback(bytes_written);
+      } else {
+        DoWriteCallback(user_write_buf_len_);
+      }
+    }
+  }
+
+  if (user_read_callback_) {
+    int rv = DoReadLoop(OK);
+    if (rv != ERR_IO_PENDING)
+      DoReadCallback(rv);
+  }
+
+  // Exit DoHandshakeLoop and return the result to the caller to Connect.
+  DCHECK(next_handshake_state_ == STATE_NONE);
+  return result;
+}
+
+int SSLClientSocketNSS::DoPayloadRead() {
+  EnterFunction(user_read_buf_len_);
+  DCHECK(user_read_buf_);
+  DCHECK_GT(user_read_buf_len_, 0);
+  int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
+  if (client_auth_cert_needed_) {
+    // We don't need to invalidate the non-client-authenticated SSL session
+    // because the server will renegotiate anyway.
+    LeaveFunction("");
+    rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
+    net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
+                      make_scoped_refptr(new SSLErrorParams(rv, 0)));
+    return rv;
+  }
+  if (rv >= 0) {
+    LogData(user_read_buf_->data(), rv);
+    LeaveFunction("");
+    return rv;
+  }
+  PRErrorCode prerr = PR_GetError();
+  if (prerr == PR_WOULD_BLOCK_ERROR) {
+    LeaveFunction("");
+    return ERR_IO_PENDING;
+  }
+  LeaveFunction("");
+  rv = HandleNSSError(prerr, false);
+  net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
+                    make_scoped_refptr(new SSLErrorParams(rv, prerr)));
+  return rv;
+}
+
+int SSLClientSocketNSS::DoPayloadWrite() {
+  EnterFunction(user_write_buf_len_);
+  DCHECK(user_write_buf_);
+  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
+  if (rv >= 0) {
+    LogData(user_write_buf_->data(), rv);
+    LeaveFunction("");
+    return rv;
+  }
+  PRErrorCode prerr = PR_GetError();
+  if (prerr == PR_WOULD_BLOCK_ERROR) {
+    LeaveFunction("");
+    return ERR_IO_PENDING;
+  }
+  LeaveFunction("");
+  rv = HandleNSSError(prerr, false);
+  net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
+                    make_scoped_refptr(new SSLErrorParams(rv, prerr)));
+  return rv;
+}
+
+void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
+  UpdateConnectionTypeHistograms(CONNECTION_SSL);
+  if (server_cert_verify_result_->has_md5)
+    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
+  if (server_cert_verify_result_->has_md2)
+    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
+  if (server_cert_verify_result_->has_md4)
+    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
+  if (server_cert_verify_result_->has_md5_ca)
+    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
+  if (server_cert_verify_result_->has_md2_ca)
+    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
+  int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_);
+  switch (ssl_version) {
+    case SSL_CONNECTION_VERSION_SSL2:
+      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
+      break;
+    case SSL_CONNECTION_VERSION_SSL3:
+      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
+      break;
+    case SSL_CONNECTION_VERSION_TLS1:
+      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
+      break;
+    case SSL_CONNECTION_VERSION_TLS1_1:
+      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
+      break;
+    case SSL_CONNECTION_VERSION_TLS1_2:
+      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
+      break;
+  };
+}
+
+// SaveSnapStartInfo extracts the information needed to perform a Snap Start
+// with this server in the future (if any) and tells |ssl_host_info_| to
+// preserve it.
+void SSLClientSocketNSS::SaveSnapStartInfo() {
+  if (!ssl_host_info_.get())
+    return;
+
+  // If the SSLHostInfo hasn't managed to load from disk yet then we can't save
+  // anything.
+  if (ssl_host_info_->WaitForDataReady(NULL) != OK)
+    return;
+
+  SECStatus rv;
+  SSLSnapStartResult snap_start_type;
+  rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return;
+  }
+  net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START,
+                    new NetLogIntegerParameter("type", snap_start_type));
+  if (snap_start_type == SSL_SNAP_START_FULL ||
+      snap_start_type == SSL_SNAP_START_RESUME) {
+    // If we did a successful Snap Start then our information was correct and
+    // there's no point saving it again.
+    return;
+  }
+
+  const unsigned char* hello_data;
+  unsigned hello_data_len;
+  rv = SSL_GetPredictedServerHelloData(nss_fd_, &hello_data, &hello_data_len);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return;
+  }
+  if (hello_data_len > std::numeric_limits<uint16>::max())
+    return;
+  SSLHostInfo::State* state = ssl_host_info_->mutable_state();
+
+  if (hello_data_len > 0) {
+    state->server_hello =
+        std::string(reinterpret_cast<const char *>(hello_data), hello_data_len);
+    state->npn_valid = true;
+    state->npn_status = GetNextProto(&state->npn_protocol);
+  } else {
+    state->server_hello.clear();
+    state->npn_valid = false;
+  }
+
+  state->certs.clear();
+  PeerCertificateChain certs(nss_fd_);
+  for (unsigned i = 0; i < certs.size(); i++) {
+    if (certs[i]->derCert.len > std::numeric_limits<uint16>::max())
+      return;
+
+    state->certs.push_back(std::string(
+          reinterpret_cast<char*>(certs[i]->derCert.data),
+          certs[i]->derCert.len));
+  }
+
+  ssl_host_info_->Persist();
+}
+
+// LoadSnapStartInfo parses |info|, which contains data previously serialised
+// by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello
+// data on the NSS socket. Returns true on success. If this function returns
+// false, the caller should try a normal TLS handshake.
+bool SSLClientSocketNSS::LoadSnapStartInfo() {
+  const SSLHostInfo::State& state(ssl_host_info_->state());
+
+  if (state.server_hello.empty() ||
+      state.certs.empty() ||
+      !state.npn_valid) {
+    return false;
+  }
+
+  SECStatus rv;
+  rv = SSL_SetPredictedServerHelloData(
+      nss_fd_,
+      reinterpret_cast<const uint8*>(state.server_hello.data()),
+      state.server_hello.size());
+  DCHECK_EQ(SECSuccess, rv);
+
+  const std::vector<std::string>& certs_in = state.certs;
+  scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
+  for (size_t i = 0; i < certs_in.size(); i++) {
+    SECItem derCert;
+    derCert.data =
+        const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
+    derCert.len = certs_in[i].size();
+    certs[i] = CERT_NewTempCertificate(
+        CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
+        PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
+    if (!certs[i]) {
+      DestroyCertificates(&certs[0], i);
+      NOTREACHED();
+      return false;
+    }
+  }
+
+  rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
+  DestroyCertificates(&certs[0], certs_in.size());
+  DCHECK_EQ(SECSuccess, rv);
+
+  if (state.npn_valid) {
+    predicted_npn_status_ = state.npn_status;
+    predicted_npn_proto_ = state.npn_protocol;
+  }
+
+  return true;
+}
+
+bool SSLClientSocketNSS::IsNPNProtocolMispredicted() {
+  DCHECK(handshake_callback_called_);
+  if (!predicted_npn_proto_used_)
+    return false;
+  std::string npn_proto;
+  GetNextProto(&npn_proto);
+  return predicted_npn_proto_ != npn_proto;
+}
+
+void SSLClientSocketNSS::UncorkAfterTimeout() {
+  corked_ = false;
+  int nsent;
+  do {
+    nsent = BufferSend();
+  } while (nsent > 0);
+}
+
+// Do network I/O between the given buffer and the given socket.
+// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
+bool SSLClientSocketNSS::DoTransportIO() {
+  EnterFunction("");
+  bool network_moved = false;
+  if (nss_bufs_ != NULL) {
+    int nsent = BufferSend();
+    int nreceived = BufferRecv();
+    network_moved = (nsent > 0 || nreceived >= 0);
+  }
+  LeaveFunction(network_moved);
+  return network_moved;
+}
+
+// Return 0 for EOF,
+// > 0 for bytes transferred immediately,
+// < 0 for error (or the non-error ERR_IO_PENDING).
+int SSLClientSocketNSS::BufferSend(void) {
+  if (transport_send_busy_)
+    return ERR_IO_PENDING;
+
+  EnterFunction("");
+  const char* buf1;
+  const char* buf2;
+  unsigned int len1, len2;
+  memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
+  const unsigned int len = len1 + len2;
+
+  if (corked_ && len < kRecvBufferSize / 2)
+    return 0;
+
+  int rv = 0;
+  if (len) {
+    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
+    memcpy(send_buffer->data(), buf1, len1);
+    memcpy(send_buffer->data() + len1, buf2, len2);
+    rv = transport_->socket()->Write(send_buffer, len,
+                                     &buffer_send_callback_);
+    if (rv == ERR_IO_PENDING) {
+      transport_send_busy_ = true;
+    } else {
+      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
+    }
+  }
+
+  LeaveFunction(rv);
+  return rv;
+}
+
+void SSLClientSocketNSS::BufferSendComplete(int result) {
+  EnterFunction(result);
+
+  // In the case of TCP FastOpen, connect is now finished.
+  if (!peername_initialized_ && UsingTCPFastOpen())
+    InitializeSSLPeerName();
+
+  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
+  transport_send_busy_ = false;
+  OnSendComplete(result);
+  LeaveFunction("");
+}
+
+int SSLClientSocketNSS::BufferRecv(void) {
+  if (transport_recv_busy_) return ERR_IO_PENDING;
+
+  char *buf;
+  int nb = memio_GetReadParams(nss_bufs_, &buf);
+  EnterFunction(nb);
+  int rv;
+  if (!nb) {
+    // buffer too full to read into, so no I/O possible at moment
+    rv = ERR_IO_PENDING;
+  } else {
+    recv_buffer_ = new IOBuffer(nb);
+    rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_);
+    if (rv == ERR_IO_PENDING) {
+      transport_recv_busy_ = true;
+    } else {
+      if (rv > 0)
+        memcpy(buf, recv_buffer_->data(), rv);
+      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
+      recv_buffer_ = NULL;
+    }
+  }
+  LeaveFunction(rv);
+  return rv;
+}
+
+void SSLClientSocketNSS::BufferRecvComplete(int result) {
+  EnterFunction(result);
+  if (result > 0) {
+    char *buf;
+    memio_GetReadParams(nss_bufs_, &buf);
+    memcpy(buf, recv_buffer_->data(), result);
+  }
+  recv_buffer_ = NULL;
+  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
+  transport_recv_busy_ = false;
+  OnRecvComplete(result);
+  LeaveFunction("");
+}
+
+int SSLClientSocketNSS::HandleNSSError(PRErrorCode nss_error,
+                                       bool handshake_error) {
+  int net_error = handshake_error ? MapNSSHandshakeError(nss_error) :
+                                    MapNSSError(nss_error);
+
+#if defined(OS_WIN)
+  // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
+  // os_cert_handle() as an optimization. However, if the certificate
+  // private key is stored on a smart card, and the smart card is removed,
+  // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again,
+  // preventing client certificate authentication. Because the
+  // X509Certificate may outlive the individual SSLClientSocketNSS, due to
+  // caching in X509Certificate, this failure ends up preventing client
+  // certificate authentication with the same certificate for all future
+  // attempts, even after the smart card has been re-inserted. By setting
+  // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will
+  // typically be freed. This allows a new HCRYPTPROV to be obtained from
+  // the certificate on the next attempt, which should succeed if the smart
+  // card has been re-inserted, or will typically prompt the user to
+  // re-insert the smart card if not.
+  if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY ||
+       net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) &&
+      ssl_config_.send_client_cert && ssl_config_.client_cert) {
+    CertSetCertificateContextProperty(
+        ssl_config_.client_cert->os_cert_handle(),
+        CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
+  }
+#endif
+
+  return net_error;
+}
+
 // static
 // NSS calls this if an incoming certificate needs to be verified.
 // Do nothing but return SECSuccess.
@@ -1520,69 +2216,24 @@
     if (that->ssl_config_.client_cert) {
       PCCERT_CONTEXT cert_context =
           that->ssl_config_.client_cert->os_cert_handle();
-      if (VLOG_IS_ON(1)) {
-        do {
-          DWORD size_needed = 0;
-          BOOL got_info = CertGetCertificateContextProperty(
-              cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size_needed);
-          if (!got_info) {
-            VLOG(1) << "Failed to get key prov info size " << GetLastError();
-            break;
-          }
-          std::vector<BYTE> raw_info(size_needed);
-          got_info = CertGetCertificateContextProperty(
-              cert_context, CERT_KEY_PROV_INFO_PROP_ID, &raw_info[0],
-              &size_needed);
-          if (!got_info) {
-            VLOG(1) << "Failed to get key prov info " << GetLastError();
-            break;
-          }
-          PCRYPT_KEY_PROV_INFO info =
-              reinterpret_cast<PCRYPT_KEY_PROV_INFO>(&raw_info[0]);
-          VLOG(1) << "Container Name: " << info->pwszContainerName
-                  << "\nProvider Name: " << info->pwszProvName
-                  << "\nProvider Type: " << info->dwProvType
-                  << "\nFlags: " << info->dwFlags
-                  << "\nProvider Param Count: " << info->cProvParam
-                  << "\nKey Specifier: " << info->dwKeySpec;
-        } while (false);
+      PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
+          PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
+      if (!key_context)
+        return SECFailure;
+      key_context->cbSize = sizeof(*key_context);
 
-        do {
-          DWORD size_needed = 0;
-          BOOL got_identifier = CertGetCertificateContextProperty(
-              cert_context, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size_needed);
-          if (!got_identifier) {
-            VLOG(1) << "Failed to get key identifier size "
-                    << GetLastError();
-            break;
-          }
-          std::vector<BYTE> raw_id(size_needed);
-          got_identifier = CertGetCertificateContextProperty(
-              cert_context, CERT_KEY_IDENTIFIER_PROP_ID, &raw_id[0],
-              &size_needed);
-          if (!got_identifier) {
-            VLOG(1) << "Failed to get key identifier " << GetLastError();
-            break;
-          }
-          VLOG(1) << "Key Identifier: " << base::HexEncode(&raw_id[0],
-                                                           size_needed);
-        } while (false);
-      }
-      HCRYPTPROV provider = NULL;
-      DWORD key_spec = AT_KEYEXCHANGE;
       BOOL must_free = FALSE;
       BOOL acquired_key = CryptAcquireCertificatePrivateKey(
-          cert_context,
-          CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
-          NULL, &provider, &key_spec, &must_free);
-      if (acquired_key && provider) {
-        DCHECK_NE(key_spec, CERT_NCRYPT_KEY_SPEC);
+          cert_context, CRYPT_ACQUIRE_CACHE_FLAG, NULL,
+          &key_context->hCryptProv, &key_context->dwKeySpec, &must_free);
+      if (acquired_key && key_context->hCryptProv) {
+        DCHECK_NE(key_context->dwKeySpec, CERT_NCRYPT_KEY_SPEC);
 
         // The certificate cache may have been updated/used, in which case,
         // duplicate the existing handle, since NSS will free it when no
         // longer in use.
         if (!must_free)
-          CryptContextAddRef(provider, NULL, 0);
+          CryptContextAddRef(key_context->hCryptProv, NULL, 0);
 
         SECItem der_cert;
         der_cert.type = siDERCertBuffer;
@@ -1608,10 +2259,10 @@
               db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
           CERT_AddCertToListTail(*result_certs, intermediate);
         }
-        // TODO(wtc): |key_spec| should be passed along with |provider|.
-        *result_private_key = reinterpret_cast<void*>(provider);
+        *result_private_key = key_context;
         return SECSuccess;
       }
+      PORT_Free(key_context);
       LOG(WARNING) << "Client cert found without private key";
     }
     // Send no client certificate.
@@ -1728,7 +2379,7 @@
       if (chain && identity && os_error == noErr) {
         // TODO(rsleevi): Error checking for NSS allocation errors.
         *result_certs = CERT_NewCertList();
-        *result_private_key = reinterpret_cast<void*>(private_key);
+        *result_private_key = private_key;
 
         for (CFIndex i = 0; i < CFArrayGetCount(chain); ++i) {
           CSSM_DATA cert_data;
@@ -1884,616 +2535,17 @@
   that->UpdateConnectionStatus();
 }
 
-int SSLClientSocketNSS::DoSnapStartLoadInfo() {
-  EnterFunction("");
-  int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
-  GotoState(STATE_HANDSHAKE);
-
-  if (rv == OK) {
-    if (ssl_host_info_->WaitForCertVerification(NULL) == OK) {
-      if (LoadSnapStartInfo()) {
-        pseudo_connected_ = true;
-        GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
-        if (user_connect_callback_)
-          DoConnectCallback(OK);
-      }
-    } else if (!ssl_host_info_->state().server_hello.empty()) {
-      // A non-empty ServerHello suggests that we would have tried a Snap Start
-      // connection.
-      base::TimeTicks now = base::TimeTicks::Now();
-      const base::TimeDelta duration =
-          now - ssl_host_info_->verification_start_time();
-      UMA_HISTOGRAM_TIMES("Net.SSLSnapStartNeededVerificationInMs", duration);
-      VLOG(1) << "Cannot snap start because verification isn't ready. "
-              << "Wanted verification after "
-              << duration.InMilliseconds() << "ms";
-    }
-  } else {
-    DCHECK_EQ(ERR_IO_PENDING, rv);
-    GotoState(STATE_SNAP_START_LOAD_INFO);
-  }
-
-  LeaveFunction("");
-  return rv;
+void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
+  base::AutoLock auto_lock(lock_);
+  if (valid_thread_id_ != base::kInvalidThreadId)
+    return;
+  valid_thread_id_ = base::PlatformThread::CurrentId();
 }
 
-int SSLClientSocketNSS::DoSnapStartWaitForWrite() {
-  EnterFunction("");
-  // In this state, we're waiting for the first Write call so that we can merge
-  // it into the Snap Start handshake.
-  if (!user_write_buf_) {
-    // We'll lie and say that we're connected in order that someone will call
-    // Write.
-    GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
-    DCHECK(!user_connect_callback_);
-    LeaveFunction("");
-    return ERR_IO_PENDING;
-  }
-
-  // This is the largest Snap Start application data payload that we'll try to
-  // use. A TCP client can only send three frames of data without an ACK and,
-  // at 2048 bytes, this leaves some space for the rest of the ClientHello
-  // (including possible session ticket).
-  static const int kMaxSnapStartPayloadSize = 2048;
-
-  if (user_write_buf_len_ > kMaxSnapStartPayloadSize) {
-    user_write_buf_len_ = kMaxSnapStartPayloadSize;
-    // When we complete the handshake and call user_write_callback_ we'll say
-    // that we only wrote |kMaxSnapStartPayloadSize| bytes. That way the rest
-    // of the payload will be presented to |Write| again and transmitted as
-    // normal application data.
-  }
-
-  SECStatus rv = SSL_SetSnapStartApplicationData(
-      nss_fd_, reinterpret_cast<const unsigned char*>(user_write_buf_->data()),
-      user_write_buf_len_);
-  DCHECK_EQ(SECSuccess, rv);
-
-  GotoState(STATE_HANDSHAKE);
-  LeaveFunction("");
-  return OK;
-}
-
-int SSLClientSocketNSS::DoHandshake() {
-  EnterFunction("");
-  int net_error = net::OK;
-  SECStatus rv = SSL_ForceHandshake(nss_fd_);
-
-  if (client_auth_cert_needed_) {
-    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
-    net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
-                      make_scoped_refptr(new SSLErrorParams(net_error, 0)));
-    // If the handshake already succeeded (because the server requests but
-    // doesn't require a client cert), we need to invalidate the SSL session
-    // so that we won't try to resume the non-client-authenticated session in
-    // the next handshake.  This will cause the server to ask for a client
-    // cert again.
-    if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) {
-      LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
-    }
-  } else if (rv == SECSuccess) {
-    if (handshake_callback_called_) {
-      if (eset_mitm_detected_) {
-        net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION;
-      } else {
-        // We need to see if the predicted certificate chain (in
-        // |ssl_host_info_->state().certs) matches the actual certificate chain
-        // before we call SaveSnapStartInfo, as that will update
-        // |ssl_host_info_|.
-        if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) {
-          PeerCertificateChain certs(nss_fd_);
-          const SSLHostInfo::State& state = ssl_host_info_->state();
-          predicted_cert_chain_correct_ = certs.size() == state.certs.size();
-          if (predicted_cert_chain_correct_) {
-            for (unsigned i = 0; i < certs.size(); i++) {
-              if (certs[i]->derCert.len != state.certs[i].size() ||
-                  memcmp(certs[i]->derCert.data, state.certs[i].data(),
-                         certs[i]->derCert.len) != 0) {
-                predicted_cert_chain_correct_ = false;
-                break;
-              }
-            }
-          }
-        }
-
-#if defined(SSL_ENABLE_OCSP_STAPLING)
-        // TODO: we need to be able to plumb an OCSP response into the system
-        // libraries. When we do, HaveCacheOCSPResponseFromSideChannelFunction
-        // needs to be updated for those platforms.
-        if (!predicted_cert_chain_correct_ &&
-            HaveCacheOCSPResponseFromSideChannelFunction()) {
-          unsigned int len = 0;
-          SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len);
-          if (len) {
-            const unsigned int orig_len = len;
-            scoped_array<uint8> ocsp_response(new uint8[orig_len]);
-            SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len);
-            DCHECK_EQ(orig_len, len);
-
-            SECItem ocsp_response_item;
-            ocsp_response_item.type = siBuffer;
-            ocsp_response_item.data = ocsp_response.get();
-            ocsp_response_item.len = len;
-
-            CERT_CacheOCSPResponseFromSideChannel(
-                CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(),
-                &ocsp_response_item, NULL);
-          }
-        }
-#endif
-
-        SaveSnapStartInfo();
-        // SSL handshake is completed. It's possible that we mispredicted the
-        // NPN agreed protocol. In this case, we've just sent a request in the
-        // wrong protocol! The higher levels of this network stack aren't
-        // prepared for switching the protocol like that so we make up an error
-        // and rely on the fact that the request will be retried.
-        if (IsNPNProtocolMispredicted()) {
-          LOG(WARNING) << "Mispredicted NPN protocol for "
-                       << host_and_port_.ToString();
-          net_error = ERR_SSL_SNAP_START_NPN_MISPREDICTION;
-        } else {
-          // Let's verify the certificate.
-          GotoState(STATE_VERIFY_DNSSEC);
-        }
-      }
-      // Done!
-    } else {
-      // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 -
-      // SSL_ForceHandshake returned SECSuccess prematurely.
-      rv = SECFailure;
-      net_error = ERR_SSL_PROTOCOL_ERROR;
-      net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
-                        make_scoped_refptr(new SSLErrorParams(net_error, 0)));
-    }
-  } else {
-    PRErrorCode prerr = PR_GetError();
-    net_error = MapNSSHandshakeError(prerr);
-
-    // If not done, stay in this state
-    if (net_error == ERR_IO_PENDING) {
-      GotoState(STATE_HANDSHAKE);
-    } else {
-      LOG(ERROR) << "handshake failed; NSS error code " << prerr
-                 << ", net_error " << net_error;
-      net_log_.AddEvent(
-          NetLog::TYPE_SSL_HANDSHAKE_ERROR,
-          make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
-    }
-  }
-
-  LeaveFunction("");
-  return net_error;
-}
-
-// DNSValidationResult enumerates the possible outcomes from processing a
-// set of DNS records.
-enum DNSValidationResult {
-  DNSVR_SUCCESS,   // the cert is immediately acceptable.
-  DNSVR_FAILURE,   // the cert is unconditionally rejected.
-  DNSVR_CONTINUE,  // perform CA validation as usual.
-};
-
-// VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and
-// checks them against the given certificate.
-//   dnssec: if true then the TXT records are DNSSEC validated. In this case,
-//       DNSVR_SUCCESS may be returned.
-//    server_cert_nss: the certificate to validate
-//    rrdatas: the TXT records for the current domain.
-static DNSValidationResult VerifyTXTRecords(
-    bool dnssec,
-    CERTCertificate* server_cert_nss,
-    const std::vector<base::StringPiece>& rrdatas) {
-  bool found_well_formed_record = false;
-  bool matched_record = false;
-
-  for (std::vector<base::StringPiece>::const_iterator
-       i = rrdatas.begin(); i != rrdatas.end(); ++i) {
-    std::map<std::string, std::string> m(
-        DNSSECChainVerifier::ParseTLSTXTRecord(*i));
-    if (m.empty())
-      continue;
-
-    std::map<std::string, std::string>::const_iterator j;
-    j = m.find("v");
-    if (j == m.end() || j->second != "tls1")
-      continue;
-
-    j = m.find("ha");
-
-    HASH_HashType hash_algorithm;
-    unsigned hash_length;
-    if (j == m.end() || j->second == "sha1") {
-      hash_algorithm = HASH_AlgSHA1;
-      hash_length = SHA1_LENGTH;
-    } else if (j->second == "sha256") {
-      hash_algorithm = HASH_AlgSHA256;
-      hash_length = SHA256_LENGTH;
-    } else {
-      continue;
-    }
-
-    j = m.find("h");
-    if (j == m.end())
-      continue;
-
-    std::vector<uint8> given_hash;
-    if (!base::HexStringToBytes(j->second, &given_hash))
-      continue;
-
-    if (given_hash.size() != hash_length)
-      continue;
-
-    uint8 calculated_hash[SHA256_LENGTH];  // SHA256 is the largest.
-    SECStatus rv;
-
-    j = m.find("hr");
-    if (j == m.end() || j->second == "pubkey") {
-      rv = HASH_HashBuf(hash_algorithm, calculated_hash,
-                        server_cert_nss->derPublicKey.data,
-                        server_cert_nss->derPublicKey.len);
-    } else if (j->second == "cert") {
-      rv = HASH_HashBuf(hash_algorithm, calculated_hash,
-                        server_cert_nss->derCert.data,
-                        server_cert_nss->derCert.len);
-    } else {
-      continue;
-    }
-
-    if (rv != SECSuccess)
-      NOTREACHED();
-
-    found_well_formed_record = true;
-
-    if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) {
-      matched_record = true;
-      if (dnssec)
-        return DNSVR_SUCCESS;
-    }
-  }
-
-  if (found_well_formed_record && !matched_record)
-    return DNSVR_FAILURE;
-
-  return DNSVR_CONTINUE;
-}
-
-
-// CheckDNSSECChain tries to validate a DNSSEC chain embedded in
-// |server_cert_nss_|. It returns true iff a chain is found that proves the
-// value of a TXT record that contains a valid public key fingerprint.
-static DNSValidationResult CheckDNSSECChain(
-    const std::string& hostname,
-    CERTCertificate* server_cert_nss) {
-  if (!server_cert_nss)
-    return DNSVR_CONTINUE;
-
-  // CERT_FindCertExtensionByOID isn't exported so we have to install an OID,
-  // get a tag for it and find the extension by using that tag.
-  static SECOidTag dnssec_chain_tag;
-  static bool dnssec_chain_tag_valid;
-  if (!dnssec_chain_tag_valid) {
-    // It's harmless if multiple threads enter this block concurrently.
-    static const uint8 kDNSSECChainOID[] =
-        // 1.3.6.1.4.1.11129.2.1.4
-        // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
-        //  certificateExtensions.dnssecEmbeddedChain)
-        {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04};
-    SECOidData oid_data;
-    memset(&oid_data, 0, sizeof(oid_data));
-    oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID);
-    oid_data.oid.len = sizeof(kDNSSECChainOID);
-    oid_data.desc = "DNSSEC chain";
-    oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
-    dnssec_chain_tag = SECOID_AddEntry(&oid_data);
-    DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag);
-    dnssec_chain_tag_valid = true;
-  }
-
-  SECItem dnssec_embedded_chain;
-  SECStatus rv = CERT_FindCertExtension(server_cert_nss,
-      dnssec_chain_tag, &dnssec_embedded_chain);
-  if (rv != SECSuccess)
-    return DNSVR_CONTINUE;
-
-  base::StringPiece chain(
-      reinterpret_cast<char*>(dnssec_embedded_chain.data),
-      dnssec_embedded_chain.len);
-  std::string dns_hostname;
-  if (!DNSDomainFromDot(hostname, &dns_hostname))
-    return DNSVR_CONTINUE;
-  DNSSECChainVerifier verifier(dns_hostname, chain);
-  DNSSECChainVerifier::Error err = verifier.Verify();
-  if (err != DNSSECChainVerifier::OK) {
-    LOG(ERROR) << "DNSSEC chain verification failed: " << err;
-    return DNSVR_CONTINUE;
-  }
-
-  if (verifier.rrtype() != kDNS_TXT)
-    return DNSVR_CONTINUE;
-
-  DNSValidationResult r = VerifyTXTRecords(
-      true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas());
-  SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
-  return r;
-}
-
-int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
-  if (ssl_config_.dns_cert_provenance_checking_enabled &&
-      dns_cert_checker_) {
-    PeerCertificateChain certs(nss_fd_);
-    dns_cert_checker_->DoAsyncVerification(
-        host_and_port_.host(), certs.AsStringPieceVector());
-  }
-
-  if (ssl_config_.dnssec_enabled) {
-    DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(),
-                                             server_cert_nss_);
-    if (r == DNSVR_SUCCESS) {
-      local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
-      server_cert_verify_result_ = &local_server_cert_verify_result_;
-      GotoState(STATE_VERIFY_CERT_COMPLETE);
-      return OK;
-    }
-  }
-
-  if (dnssec_provider_ == NULL) {
-    GotoState(STATE_VERIFY_CERT);
-    return OK;
-  }
-
-  GotoState(STATE_VERIFY_DNSSEC_COMPLETE);
-  RRResponse* response;
-  dnssec_wait_start_time_ = base::Time::Now();
-  return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_);
-}
-
-int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
-  RRResponse* response;
-  int err = dnssec_provider_->GetDNSSECRecords(&response, NULL);
-  DCHECK_EQ(err, OK);
-
-  const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_;
-  HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed);
-
-  GotoState(STATE_VERIFY_CERT);
-  if (!response || response->rrdatas.empty())
-    return OK;
-
-  std::vector<base::StringPiece> records;
-  records.resize(response->rrdatas.size());
-  for (unsigned i = 0; i < response->rrdatas.size(); i++)
-    records[i] = base::StringPiece(response->rrdatas[i]);
-  DNSValidationResult r =
-      VerifyTXTRecords(response->dnssec, server_cert_nss_, records);
-
-  if (!ssl_config_.dnssec_enabled) {
-    // If DNSSEC is not enabled we don't take any action based on the result,
-    // except to record the latency, above.
-    return OK;
-  }
-
-  switch (r) {
-    case DNSVR_FAILURE:
-      GotoState(STATE_VERIFY_CERT_COMPLETE);
-      local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS;
-      server_cert_verify_result_ = &local_server_cert_verify_result_;
-      return ERR_CERT_NOT_IN_DNS;
-    case DNSVR_CONTINUE:
-      GotoState(STATE_VERIFY_CERT);
-      break;
-    case DNSVR_SUCCESS:
-      local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
-      server_cert_verify_result_ = &local_server_cert_verify_result_;
-      GotoState(STATE_VERIFY_CERT_COMPLETE);
-      break;
-    default:
-      NOTREACHED();
-      GotoState(STATE_VERIFY_CERT);
-  }
-
-  return OK;
-}
-
-int SSLClientSocketNSS::DoVerifyCert(int result) {
-  DCHECK(server_cert_);
-
-  GotoState(STATE_VERIFY_CERT_COMPLETE);
-  start_cert_verification_time_ = base::TimeTicks::Now();
-
-  if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() &&
-      predicted_cert_chain_correct_) {
-    // If the SSLHostInfo had a prediction for the certificate chain of this
-    // server then it will have optimistically started a verification of that
-    // chain. So, if the prediction was correct, we should wait for that
-    // verification to finish rather than start our own.
-    net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL);
-    UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2);
-    base::TimeTicks end_time = ssl_host_info_->verification_end_time();
-    if (end_time.is_null())
-      end_time = base::TimeTicks::Now();
-    UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved",
-                        end_time - ssl_host_info_->verification_start_time());
-    server_cert_verify_result_ = &ssl_host_info_->cert_verify_result();
-    return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_);
-  } else {
-    UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2);
-  }
-
-  int flags = 0;
-  if (ssl_config_.rev_checking_enabled)
-    flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
-  if (ssl_config_.verify_ev_cert)
-    flags |= X509Certificate::VERIFY_EV_CERT;
-  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
-  server_cert_verify_result_ = &local_server_cert_verify_result_;
-  return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
-                           &local_server_cert_verify_result_,
-                           &handshake_io_callback_);
-}
-
-// Derived from AuthCertificateCallback() in
-// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
-int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
-  verifier_.reset();
-
-
-  if (!start_cert_verification_time_.is_null()) {
-    base::TimeDelta verify_time =
-        base::TimeTicks::Now() - start_cert_verification_time_;
-    if (result == OK)
-        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
-    else
-        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
-  }
-
-  // We used to remember the intermediate CA certs in the NSS database
-  // persistently.  However, NSS opens a connection to the SQLite database
-  // during NSS initialization and doesn't close the connection until NSS
-  // shuts down.  If the file system where the database resides is gone,
-  // the database connection goes bad.  What's worse, the connection won't
-  // recover when the file system comes back.  Until this NSS or SQLite bug
-  // is fixed, we need to  avoid using the NSS database for non-essential
-  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
-  // http://crbug.com/15630 for more info.
-
-  // If we have been explicitly told to accept this certificate, override the
-  // result of verifier_.Verify.
-  // Eventually, we should cache the cert verification results so that we don't
-  // need to call verifier_.Verify repeatedly.  But for now we need to do this.
-  // Alternatively, we could use the cert's status that we stored along with
-  // the cert in the allowed_bad_certs vector.
-  if (IsCertificateError(result) &&
-      ssl_config_.IsAllowedBadCert(server_cert_)) {
-    VLOG(1) << "accepting bad SSL certificate, as user told us to";
-    result = OK;
-  }
-
-  if (result == OK)
-    LogConnectionTypeMetrics();
-
-  completed_handshake_ = true;
-
-  // If we merged a Write call into the handshake we need to make the
-  // callback now.
-  if (user_write_callback_) {
-    corked_ = false;
-    if (result != OK) {
-      DoWriteCallback(result);
-    } else {
-      SSLSnapStartResult snap_start_type;
-      SECStatus rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
-      DCHECK_EQ(rv, SECSuccess);
-      DCHECK_NE(snap_start_type, SSL_SNAP_START_NONE);
-      if (snap_start_type == SSL_SNAP_START_RECOVERY ||
-          snap_start_type == SSL_SNAP_START_RESUME_RECOVERY) {
-        // If we mispredicted the server's handshake then Snap Start will have
-        // triggered a recovery mode. The misprediction could have been caused
-        // by the server having a different certificate so the application data
-        // wasn't resent. Now that we have verified the certificate, we need to
-        // resend the application data.
-        int bytes_written = DoPayloadWrite();
-        if (bytes_written != ERR_IO_PENDING)
-          DoWriteCallback(bytes_written);
-      } else {
-        DoWriteCallback(user_write_buf_len_);
-      }
-    }
-  }
-
-  if (user_read_callback_) {
-    int rv = DoReadLoop(OK);
-    if (rv != ERR_IO_PENDING)
-      DoReadCallback(rv);
-  }
-
-  // Exit DoHandshakeLoop and return the result to the caller to Connect.
-  DCHECK(next_handshake_state_ == STATE_NONE);
-  return result;
-}
-
-int SSLClientSocketNSS::DoPayloadRead() {
-  EnterFunction(user_read_buf_len_);
-  DCHECK(user_read_buf_);
-  DCHECK_GT(user_read_buf_len_, 0);
-  int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
-  if (client_auth_cert_needed_) {
-    // We don't need to invalidate the non-client-authenticated SSL session
-    // because the server will renegotiate anyway.
-    LeaveFunction("");
-    rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
-    net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
-                      make_scoped_refptr(new SSLErrorParams(rv, 0)));
-    return rv;
-  }
-  if (rv >= 0) {
-    LogData(user_read_buf_->data(), rv);
-    LeaveFunction("");
-    return rv;
-  }
-  PRErrorCode prerr = PR_GetError();
-  if (prerr == PR_WOULD_BLOCK_ERROR) {
-    LeaveFunction("");
-    return ERR_IO_PENDING;
-  }
-  LeaveFunction("");
-  rv = MapNSSError(prerr);
-  net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
-                    make_scoped_refptr(new SSLErrorParams(rv, prerr)));
-  return rv;
-}
-
-int SSLClientSocketNSS::DoPayloadWrite() {
-  EnterFunction(user_write_buf_len_);
-  DCHECK(user_write_buf_);
-  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
-  if (rv >= 0) {
-    LogData(user_write_buf_->data(), rv);
-    LeaveFunction("");
-    return rv;
-  }
-  PRErrorCode prerr = PR_GetError();
-  if (prerr == PR_WOULD_BLOCK_ERROR) {
-    LeaveFunction("");
-    return ERR_IO_PENDING;
-  }
-  LeaveFunction("");
-  rv = MapNSSError(prerr);
-  net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
-                    make_scoped_refptr(new SSLErrorParams(rv, prerr)));
-  return rv;
-}
-
-void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
-  UpdateConnectionTypeHistograms(CONNECTION_SSL);
-  if (server_cert_verify_result_->has_md5)
-    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
-  if (server_cert_verify_result_->has_md2)
-    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
-  if (server_cert_verify_result_->has_md4)
-    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
-  if (server_cert_verify_result_->has_md5_ca)
-    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
-  if (server_cert_verify_result_->has_md2_ca)
-    UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
-  int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_);
-  switch (ssl_version) {
-    case SSL_CONNECTION_VERSION_SSL2:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
-      break;
-    case SSL_CONNECTION_VERSION_SSL3:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
-      break;
-    case SSL_CONNECTION_VERSION_TLS1:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
-      break;
-    case SSL_CONNECTION_VERSION_TLS1_1:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
-      break;
-    case SSL_CONNECTION_VERSION_TLS1_2:
-      UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
-      break;
-  };
+bool SSLClientSocketNSS::CalledOnValidThread() const {
+  EnsureThreadIdAssigned();
+  base::AutoLock auto_lock(lock_);
+  return valid_thread_id_ == base::PlatformThread::CurrentId();
 }
 
 }  // namespace net
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index 6389db8..8add875 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -15,6 +15,8 @@
 #include <vector>
 
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
 #include "base/time.h"
 #include "base/timer.h"
 #include "net/base/cert_verify_result.h"
@@ -53,6 +55,9 @@
                      DnsCertProvenanceChecker* dnsrr_resolver);
   ~SSLClientSocketNSS();
 
+  // For tests
+  static void ClearSessionCache();
+
   // SSLClientSocket methods:
   virtual void GetSSLInfo(SSLInfo* ssl_info);
   virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
@@ -81,10 +86,20 @@
   virtual bool SetReceiveBufferSize(int32 size);
   virtual bool SetSendBufferSize(int32 size);
 
-  // For tests
-  static void ClearSessionCache();
-
  private:
+  enum State {
+    STATE_NONE,
+    STATE_SNAP_START_LOAD_INFO,
+    STATE_SNAP_START_WAIT_FOR_WRITE,
+    STATE_HANDSHAKE,
+    STATE_VERIFY_DNSSEC,
+    STATE_VERIFY_DNSSEC_COMPLETE,
+    STATE_VERIFY_CERT,
+    STATE_VERIFY_CERT_COMPLETE,
+  };
+
+  int Init();
+
   // Initializes NSS SSL options.  Returns a net error code.
   int InitializeSSLOptions();
 
@@ -119,7 +134,6 @@
   int DoPayloadRead();
   int DoPayloadWrite();
   void LogConnectionTypeMetrics() const;
-  int Init();
   void SaveSnapStartInfo();
   bool LoadSnapStartInfo();
   bool IsNPNProtocolMispredicted();
@@ -127,10 +141,14 @@
 
   bool DoTransportIO();
   int BufferSend(void);
-  int BufferRecv(void);
   void BufferSendComplete(int result);
+  int BufferRecv(void);
   void BufferRecvComplete(int result);
 
+  // Handles an NSS error generated while handshaking or performing IO.
+  // Returns a network error code mapped from the original NSS error.
+  int HandleNSSError(PRErrorCode error, bool handshake_error);
+
   // NSS calls this when checking certificates. We pass 'this' as the first
   // argument.
   static SECStatus OwnAuthCertHandler(void* arg, PRFileDesc* socket,
@@ -153,6 +171,11 @@
   // argument.
   static void HandshakeCallback(PRFileDesc* socket, void* arg);
 
+  // The following methods are for debugging bug 65948. Will remove this code
+  // after fixing bug 65948.
+  void EnsureThreadIdAssigned() const;
+  bool CalledOnValidThread() const;
+
   CompletionCallbackImpl<SSLClientSocketNSS> buffer_send_callback_;
   CompletionCallbackImpl<SSLClientSocketNSS> buffer_recv_callback_;
   bool transport_send_busy_;
@@ -228,16 +251,6 @@
   // The time when we started waiting for DNSSEC records.
   base::Time dnssec_wait_start_time_;
 
-  enum State {
-    STATE_NONE,
-    STATE_SNAP_START_LOAD_INFO,
-    STATE_SNAP_START_WAIT_FOR_WRITE,
-    STATE_HANDSHAKE,
-    STATE_VERIFY_DNSSEC,
-    STATE_VERIFY_DNSSEC_COMPLETE,
-    STATE_VERIFY_CERT,
-    STATE_VERIFY_CERT_COMPLETE,
-  };
   State next_handshake_state_;
 
   // The NSS SSL state machine
@@ -260,6 +273,14 @@
 
   scoped_ptr<SSLHostInfo> ssl_host_info_;
   DnsCertProvenanceChecker* const dns_cert_checker_;
+
+  // The following two variables are added for debugging bug 65948. Will
+  // remove this code after fixing bug 65948.
+  // Added the following code Debugging in release mode.
+  mutable base::Lock lock_;
+  // This is mutable so that CalledOnValidThread can set it.
+  // It's guarded by |lock_|.
+  mutable base::PlatformThreadId valid_thread_id_;
 };
 
 }  // namespace net
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 23d53f3..7244103 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -13,10 +13,10 @@
 #include <string>
 #endif
 
-#include "base/lock.h"
 #include "base/metrics/histogram.h"
 #include "base/openssl_util.h"
 #include "base/singleton.h"
+#include "base/synchronization/lock.h"
 #include "net/base/cert_verifier.h"
 #include "net/base/net_errors.h"
 #include "net/base/openssl_private_key_store.h"
@@ -210,7 +210,7 @@
     // Declare the session cleaner-upper before the lock, so any call into
     // OpenSSL to free the session will happen after the lock is released.
     base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
 
     DCHECK_EQ(0U, session_map_.count(session));
     std::pair<HostPortMap::iterator, bool> res =
@@ -232,7 +232,7 @@
     // Declare the session cleaner-upper before the lock, so any call into
     // OpenSSL to free the session will happen after the lock is released.
     base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
 
     SessionMap::iterator it = session_map_.find(session);
     if (it == session_map_.end())
@@ -249,7 +249,7 @@
   // Looks up the host:port in the cache, and if a session is found it is added
   // to |ssl|, returning true on success.
   bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port) {
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     HostPortMap::iterator it = host_port_map_.find(host_and_port);
     if (it == host_port_map_.end())
       return false;
@@ -277,7 +277,7 @@
   SessionMap session_map_;
 
   // Protects access to both the above maps.
-  Lock lock_;
+  base::Lock lock_;
 
   DISALLOW_COPY_AND_ASSIGN(SSLSessionCache);
 };
@@ -637,8 +637,9 @@
 
   // Set up new ssl object.
   if (!Init()) {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
-    return ERR_UNEXPECTED;
+    int result = ERR_UNEXPECTED;
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
+    return result;
   }
 
   // Set SSL to client mode. Handshake happens in the loop below.
@@ -649,7 +650,7 @@
   if (rv == ERR_IO_PENDING) {
     user_connect_callback_ = callback;
   } else {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
   }
 
   return rv > OK ? OK : rv;
@@ -1001,7 +1002,7 @@
 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
   int rv = DoHandshakeLoop(result);
   if (rv != ERR_IO_PENDING) {
-    net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
     DoConnectCallback(rv);
   }
 }
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index d899c16..c436fc0 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -130,24 +130,16 @@
   }
 }
 
-int SSLConnectJob::ConnectInternal() {
-  switch (params_->proxy()) {
-    case ProxyServer::SCHEME_DIRECT:
-      next_state_ = STATE_TCP_CONNECT;
-      break;
-    case ProxyServer::SCHEME_HTTP:
-    case ProxyServer::SCHEME_HTTPS:
-      next_state_ = STATE_TUNNEL_CONNECT;
-      break;
-    case ProxyServer::SCHEME_SOCKS4:
-    case ProxyServer::SCHEME_SOCKS5:
-      next_state_ = STATE_SOCKS_CONNECT;
-      break;
-    default:
-      NOTREACHED() << "unknown proxy type";
-      break;
+void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
+  // Headers in |error_response_info_| indicate a proxy tunnel setup
+  // problem. See DoTunnelConnectComplete.
+  if (error_response_info_.headers) {
+    handle->set_pending_http_proxy_connection(
+        transport_socket_handle_.release());
   }
-  return DoLoop(OK);
+  handle->set_ssl_error_response_info(error_response_info_);
+  if (!ssl_connect_start_time_.is_null())
+    handle->set_is_ssl_error(true);
 }
 
 void SSLConnectJob::OnIOComplete(int result) {
@@ -211,10 +203,10 @@
                                              params_->ssl_config()));
   }
 
-  if (dnsrr_resolver_)
-    ssl_host_info_->StartDnsLookup(dnsrr_resolver_);
-
   if (ssl_host_info_.get()) {
+    if (dnsrr_resolver_)
+      ssl_host_info_->StartDnsLookup(dnsrr_resolver_);
+
     // This starts fetching the SSL host info from the disk cache for Snap
     // Start.
     ssl_host_info_->Start();
@@ -285,18 +277,6 @@
   return result;
 }
 
-void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
-  // Headers in |error_response_info_| indicate a proxy tunnel setup
-  // problem. See DoTunnelConnectComplete.
-  if (error_response_info_.headers) {
-    handle->set_pending_http_proxy_connection(
-        transport_socket_handle_.release());
-  }
-  handle->set_ssl_error_response_info(error_response_info_);
-  if (!ssl_connect_start_time_.is_null())
-    handle->set_is_ssl_error(true);
-}
-
 int SSLConnectJob::DoSSLConnect() {
   next_state_ = STATE_SSL_CONNECT_COMPLETE;
   // Reset the timeout to just the time allowed for the SSL handshake.
@@ -374,15 +354,24 @@
   return result;
 }
 
-ConnectJob* SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
-    const std::string& group_name,
-    const PoolBase::Request& request,
-    ConnectJob::Delegate* delegate) const {
-  return new SSLConnectJob(group_name, request.params(), ConnectionTimeout(),
-                           tcp_pool_, socks_pool_, http_proxy_pool_,
-                           client_socket_factory_, host_resolver_,
-                           cert_verifier_, dnsrr_resolver_, dns_cert_checker_,
-                           ssl_host_info_factory_, delegate, net_log_);
+int SSLConnectJob::ConnectInternal() {
+  switch (params_->proxy()) {
+    case ProxyServer::SCHEME_DIRECT:
+      next_state_ = STATE_TCP_CONNECT;
+      break;
+    case ProxyServer::SCHEME_HTTP:
+    case ProxyServer::SCHEME_HTTPS:
+      next_state_ = STATE_TUNNEL_CONNECT;
+      break;
+    case ProxyServer::SCHEME_SOCKS4:
+    case ProxyServer::SCHEME_SOCKS5:
+      next_state_ = STATE_SOCKS_CONNECT;
+      break;
+    default:
+      NOTREACHED() << "unknown proxy type";
+      break;
+  }
+  return DoLoop(OK);
 }
 
 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
@@ -461,6 +450,17 @@
     ssl_config_service_->RemoveObserver(this);
 }
 
+ConnectJob* SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
+    const std::string& group_name,
+    const PoolBase::Request& request,
+    ConnectJob::Delegate* delegate) const {
+  return new SSLConnectJob(group_name, request.params(), ConnectionTimeout(),
+                           tcp_pool_, socks_pool_, http_proxy_pool_,
+                           client_socket_factory_, host_resolver_,
+                           cert_verifier_, dnsrr_resolver_, dns_cert_checker_,
+                           ssl_host_info_factory_, delegate, net_log_);
+}
+
 int SSLClientSocketPool::RequestSocket(const std::string& group_name,
                                        const void* socket_params,
                                        RequestPriority priority,
@@ -517,10 +517,6 @@
   return base_.GetLoadState(group_name, handle);
 }
 
-void SSLClientSocketPool::OnSSLConfigChanged() {
-  Flush();
-}
-
 DictionaryValue* SSLClientSocketPool::GetInfoAsValue(
     const std::string& name,
     const std::string& type,
@@ -556,4 +552,8 @@
   return base_.histograms();
 }
 
+void SSLClientSocketPool::OnSSLConfigChanged() {
+  Flush();
+}
+
 }  // namespace net
diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h
index 70da04f..b16ff11 100644
--- a/net/socket/ssl_client_socket_pool.h
+++ b/net/socket/ssl_client_socket_pool.h
@@ -128,11 +128,6 @@
     STATE_NONE,
   };
 
-  // Starts the SSL connection process.  Returns OK on success and
-  // ERR_IO_PENDING if it cannot immediately service the request.
-  // Otherwise, it returns a net error code.
-  virtual int ConnectInternal();
-
   void OnIOComplete(int result);
 
   // Runs the state transition loop.
@@ -147,6 +142,11 @@
   int DoSSLConnect();
   int DoSSLConnectComplete(int result);
 
+  // Starts the SSL connection process.  Returns OK on success and
+  // ERR_IO_PENDING if it cannot immediately service the request.
+  // Otherwise, it returns a net error code.
+  virtual int ConnectInternal();
+
   scoped_refptr<SSLSocketParams> params_;
   TCPClientSocketPool* const tcp_pool_;
   SOCKSClientSocketPool* const socks_pool_;
@@ -235,14 +235,14 @@
   virtual ClientSocketPoolHistograms* histograms() const;
 
  private:
+  typedef ClientSocketPoolBase<SSLSocketParams> PoolBase;
+
   // SSLConfigService::Observer methods:
 
   // When the user changes the SSL config, we flush all idle sockets so they
   // won't get re-used.
   virtual void OnSSLConfigChanged();
 
-  typedef ClientSocketPoolBase<SSLSocketParams> PoolBase;
-
   class SSLConnectJobFactory : public PoolBase::ConnectJobFactory {
    public:
     SSLConnectJobFactory(
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 37e21ca..e211591 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -19,7 +19,6 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
-#include "net/socket/client_socket_factory.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool_histograms.h"
 #include "net/socket/socket_test_util.h"
@@ -36,22 +35,11 @@
 class SSLClientSocketPoolTest : public testing::Test {
  protected:
   SSLClientSocketPoolTest()
-      : host_resolver_(new MockHostResolver),
-        cert_verifier_(new CertVerifier),
+      : proxy_service_(ProxyService::CreateDirect()),
+        ssl_config_service_(new SSLConfigServiceDefaults),
         http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault(
-            host_resolver_.get())),
-        session_(new HttpNetworkSession(host_resolver_.get(),
-                                        cert_verifier_.get(),
-                                        NULL /* dnsrr_resolver */,
-                                        NULL /* dns_cert_checker */,
-                                        NULL /* ssl_host_info_factory */,
-                                        ProxyService::CreateDirect(),
-                                        &socket_factory_,
-                                        new SSLConfigServiceDefaults,
-                                        new SpdySessionPool(NULL),
-                                        http_auth_handler_factory_.get(),
-                                        NULL,
-                                        NULL)),
+            &host_resolver_)),
+        session_(CreateNetworkSession()),
         direct_tcp_socket_params_(new TCPSocketParams(
             HostPortPair("host", 443), MEDIUM, GURL(), false)),
         tcp_histograms_("MockTCP"),
@@ -84,7 +72,7 @@
             kMaxSockets,
             kMaxSocketsPerGroup,
             &http_proxy_histograms_,
-            host_resolver_.get(),
+            &host_resolver_,
             &tcp_socket_pool_,
             NULL,
             NULL) {
@@ -129,15 +117,33 @@
   void AddAuthToCache() {
     const string16 kFoo(ASCIIToUTF16("foo"));
     const string16 kBar(ASCIIToUTF16("bar"));
-    session_->auth_cache()->Add(GURL("http://proxy:443/"), "MyRealm1", "Basic",
-                                "Basic realm=MyRealm1", kFoo, kBar, "/");
+    session_->auth_cache()->Add(GURL("http://proxy:443/"),
+                                "MyRealm1",
+                                HttpAuth::AUTH_SCHEME_BASIC,
+                                "Basic realm=MyRealm1",
+                                kFoo,
+                                kBar,
+                                "/");
+  }
+
+  HttpNetworkSession* CreateNetworkSession() {
+    HttpNetworkSession::Params params;
+    params.host_resolver = &host_resolver_;
+    params.cert_verifier = &cert_verifier_;
+    params.proxy_service = proxy_service_;
+    params.client_socket_factory = &socket_factory_;
+    params.ssl_config_service = ssl_config_service_;
+    params.http_auth_handler_factory = http_auth_handler_factory_.get();
+    return new HttpNetworkSession(params);
   }
 
   MockClientSocketFactory socket_factory_;
-  scoped_ptr<HostResolver> host_resolver_;
-  scoped_ptr<CertVerifier> cert_verifier_;
-  scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
-  scoped_refptr<HttpNetworkSession> session_;
+  MockHostResolver host_resolver_;
+  CertVerifier cert_verifier_;
+  const scoped_refptr<ProxyService> proxy_service_;
+  const scoped_refptr<SSLConfigService> ssl_config_service_;
+  const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
+  const scoped_refptr<HttpNetworkSession> session_;
 
   scoped_refptr<TCPSocketParams> direct_tcp_socket_params_;
   ClientSocketPoolHistograms tcp_histograms_;
diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
index 1d8c039..735e0ab 100644
--- a/net/socket/ssl_client_socket_win.cc
+++ b/net/socket/ssl_client_socket_win.cc
@@ -9,9 +9,9 @@
 
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
-#include "base/lock.h"
 #include "base/stl_util-inl.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/utf_string_conversions.h"
 #include "net/base/cert_verifier.h"
 #include "net/base/connection_type_histograms.h"
@@ -149,7 +149,7 @@
     DCHECK(0 < ssl_version_mask &&
            ssl_version_mask < arraysize(anonymous_creds_));
     CredHandleClass* handle;
-    AutoLock lock(lock_);
+    base::AutoLock lock(lock_);
     if (client_cert) {
       CredHandleMapKey key = std::make_pair(client_cert, ssl_version_mask);
       CredHandleMap::const_iterator it = client_cert_creds_.find(key);
@@ -184,7 +184,7 @@
                               PCCERT_CONTEXT client_cert,
                               int ssl_version_mask);
 
-  Lock lock_;
+  base::Lock lock_;
 
   // Anonymous (no client certificate) CredHandles for all possible
   // combinations of SSL versions.  Defined as an array for fast lookup.
diff --git a/net/socket/ssl_host_info.cc b/net/socket/ssl_host_info.cc
index 1fcc053..5131949 100644
--- a/net/socket/ssl_host_info.cc
+++ b/net/socket/ssl_host_info.cc
@@ -57,15 +57,8 @@
 }
 
 void SSLHostInfo::StartDnsLookup(DnsRRResolver* dnsrr_resolver) {
-#if defined(OS_LINUX)
   dnsrr_resolver_ = dnsrr_resolver;
-  dns_callback_ = NewCallback(this, &SSLHostInfo::DnsComplete);
-  dns_lookup_start_time_ = base::TimeTicks::Now();
-
-  dns_handle_ = dnsrr_resolver->Resolve(
-      hostname_, kDNS_CAA, DnsRRResolver::FLAG_WANT_DNSSEC, dns_callback_,
-      &dns_response_, 0, BoundNetLog());
-#endif
+  // Note: currently disabled.
 }
 
 const SSLHostInfo::State& SSLHostInfo::state() const {
@@ -218,16 +211,6 @@
   }
 }
 
-void SSLHostInfo::DnsComplete(int rv) {
-  dns_handle_ = DnsRRResolver::kInvalidHandle;
-  delete dns_callback_;
-  dns_callback_ = NULL;
-
-  const base::TimeTicks now = base::TimeTicks::Now();
-  const base::TimeDelta elapsed = now - dns_lookup_start_time_;
-  UMA_HISTOGRAM_TIMES("Net.SSLHostInfoDNSLookup", elapsed);
-}
-
 SSLHostInfoFactory::~SSLHostInfoFactory() {}
 
 }  // namespace net
diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h
index c384e2e..b99bf87 100644
--- a/net/socket/ssl_host_info.h
+++ b/net/socket/ssl_host_info.h
@@ -123,10 +123,6 @@
   // ParseInner is a helper function for Parse.
   bool ParseInner(const std::string& data);
 
-  // DnsComplete is a callback function which is called when our DNS resolution
-  // completes.
-  void DnsComplete(int rv);
-
   // This is the hostname that we'll validate the certificates against.
   const std::string hostname_;
   bool cert_parsing_failed_;
@@ -146,6 +142,7 @@
   DnsRRResolver::Handle dns_handle_;
   RRResponse dns_response_;
   base::TimeTicks dns_lookup_start_time_;
+  base::TimeTicks cert_verification_finished_time_;
 };
 
 class SSLHostInfoFactory {
diff --git a/net/socket/ssl_server_socket_nss.cc b/net/socket/ssl_server_socket_nss.cc
index 2e47fb8..4d33863 100644
--- a/net/socket/ssl_server_socket_nss.cc
+++ b/net/socket/ssl_server_socket_nss.cc
@@ -90,36 +90,20 @@
   }
 }
 
-int SSLServerSocketNSS::Init() {
-  // Initialize the NSS SSL library in a threadsafe way.  This also
-  // initializes the NSS base library.
-  EnsureNSSSSLInit();
-  if (!NSS_IsInitialized())
-    return ERR_UNEXPECTED;
-#if !defined(OS_MACOSX) && !defined(OS_WIN)
-  // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
-  // by MessageLoopForIO::current().
-  // X509Certificate::Verify() runs on a worker thread of CertVerifier.
-  EnsureOCSPInit();
-#endif
-
-  return OK;
-}
-
 int SSLServerSocketNSS::Accept(CompletionCallback* callback) {
   net_log_.BeginEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
 
   int rv = Init();
   if (rv != OK) {
     LOG(ERROR) << "Failed to initialize NSS";
-    net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_ACCEPT, rv);
     return rv;
   }
 
   rv = InitializeSSLOptions();
   if (rv != OK) {
     LOG(ERROR) << "Failed to initialize SSL options";
-    net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_ACCEPT, rv);
     return rv;
   }
 
@@ -134,7 +118,7 @@
   if (rv == ERR_IO_PENDING) {
     user_accept_callback_ = callback;
   } else {
-    net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_ACCEPT, rv);
   }
 
   return rv > OK ? OK : rv;
@@ -183,27 +167,12 @@
   return rv;
 }
 
-// static
-// NSS calls this if an incoming certificate needs to be verified.
-// Do nothing but return SECSuccess.
-// This is called only in full handshake mode.
-// Peer certificate is retrieved in HandshakeCallback() later, which is called
-// in full handshake mode or in resumption handshake mode.
-SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
-                                                 PRFileDesc* socket,
-                                                 PRBool checksig,
-                                                 PRBool is_server) {
-  // TODO(hclam): Implement.
-  // Tell NSS to not verify the certificate.
-  return SECSuccess;
+bool SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
+  return false;
 }
 
-// static
-// NSS calls this when handshake is completed.
-// After the SSL handshake is finished we need to verify the certificate.
-void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
-                                           void* arg) {
-  // TODO(hclam): Implement.
+bool SSLServerSocketNSS::SetSendBufferSize(int32 size) {
+  return false;
 }
 
 int SSLServerSocketNSS::InitializeSSLOptions() {
@@ -292,12 +261,6 @@
     return ERR_UNEXPECTED;
   }
 
-  rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE");
-    return ERR_UNEXPECTED;
-  }
-
   rv = SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
   if (rv != SECSuccess) {
     LogFailedNSSFunction(net_log_, "SSL_ConfigureServerSessionIDCache", "");
@@ -349,9 +312,15 @@
   der_private_key_info.data =
       const_cast<unsigned char*>(&key_vector.front());
   der_private_key_info.len = key_vector.size();
+  // The server's RSA private key must be imported into NSS with the
+  // following key usage bits:
+  // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
+  // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
+  //   exchange algorithms.
+  const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
   rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
       slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
-      KU_DIGITAL_SIGNATURE, &private_key, NULL);
+      key_usage, &private_key, NULL);
   PK11_FreeSlot(slot);
   if (rv != SECSuccess) {
     CERT_DestroyCertificate(cert);
@@ -381,6 +350,47 @@
   return OK;
 }
 
+void SSLServerSocketNSS::OnSendComplete(int result) {
+  if (next_handshake_state_ == STATE_HANDSHAKE) {
+    // In handshake phase.
+    OnHandshakeIOComplete(result);
+    return;
+  }
+
+  if (!user_write_buf_ || !completed_handshake_)
+    return;
+
+  int rv = DoWriteLoop(result);
+  if (rv != ERR_IO_PENDING)
+    DoWriteCallback(rv);
+}
+
+void SSLServerSocketNSS::OnRecvComplete(int result) {
+  if (next_handshake_state_ == STATE_HANDSHAKE) {
+    // In handshake phase.
+    OnHandshakeIOComplete(result);
+    return;
+  }
+
+  // Network layer received some data, check if client requested to read
+  // decrypted data.
+  if (!user_read_buf_ || !completed_handshake_)
+    return;
+
+  int rv = DoReadLoop(result);
+  if (rv != ERR_IO_PENDING)
+    DoReadCallback(rv);
+}
+
+void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
+  int rv = DoHandshakeLoop(result);
+  if (rv != ERR_IO_PENDING) {
+    net_log_.EndEventWithNetErrorCode(net::NetLog::TYPE_SSL_ACCEPT, rv);
+    if (user_accept_callback_)
+      DoAcceptCallback(rv);
+  }
+}
+
 // Return 0 for EOF,
 // > 0 for bytes transferred immediately,
 // < 0 for error (or the non-error ERR_IO_PENDING).
@@ -453,81 +463,6 @@
   OnRecvComplete(result);
 }
 
-void SSLServerSocketNSS::OnSendComplete(int result) {
-  if (next_handshake_state_ == STATE_HANDSHAKE) {
-    // In handshake phase.
-    OnHandshakeIOComplete(result);
-    return;
-  }
-
-  if (!user_write_buf_ || !completed_handshake_)
-    return;
-
-  int rv = DoWriteLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoWriteCallback(rv);
-}
-
-void SSLServerSocketNSS::OnRecvComplete(int result) {
-  if (next_handshake_state_ == STATE_HANDSHAKE) {
-    // In handshake phase.
-    OnHandshakeIOComplete(result);
-    return;
-  }
-
-  // Network layer received some data, check if client requested to read
-  // decrypted data.
-  if (!user_read_buf_ || !completed_handshake_)
-    return;
-
-  int rv = DoReadLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoReadCallback(rv);
-}
-
-void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
-  int rv = DoHandshakeLoop(result);
-  if (rv != ERR_IO_PENDING) {
-    net_log_.EndEvent(net::NetLog::TYPE_SSL_ACCEPT, NULL);
-    if (user_accept_callback_)
-      DoAcceptCallback(rv);
-  }
-}
-
-void SSLServerSocketNSS::DoAcceptCallback(int rv) {
-  DCHECK_NE(rv, ERR_IO_PENDING);
-
-  CompletionCallback* c = user_accept_callback_;
-  user_accept_callback_ = NULL;
-  c->Run(rv > OK ? OK : rv);
-}
-
-void SSLServerSocketNSS::DoReadCallback(int rv) {
-  DCHECK(rv != ERR_IO_PENDING);
-  DCHECK(user_read_callback_);
-
-  // Since Run may result in Read being called, clear |user_read_callback_|
-  // up front.
-  CompletionCallback* c = user_read_callback_;
-  user_read_callback_ = NULL;
-  user_read_buf_ = NULL;
-  user_read_buf_len_ = 0;
-  c->Run(rv);
-}
-
-void SSLServerSocketNSS::DoWriteCallback(int rv) {
-  DCHECK(rv != ERR_IO_PENDING);
-  DCHECK(user_write_callback_);
-
-  // Since Run may result in Write being called, clear |user_write_callback_|
-  // up front.
-  CompletionCallback* c = user_write_callback_;
-  user_write_callback_ = NULL;
-  user_write_buf_ = NULL;
-  user_write_buf_len_ = 0;
-  c->Run(rv);
-}
-
 // Do network I/O between the given buffer and the given socket.
 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
 bool SSLServerSocketNSS::DoTransportIO() {
@@ -674,4 +609,77 @@
   return net_error;
 }
 
+void SSLServerSocketNSS::DoAcceptCallback(int rv) {
+  DCHECK_NE(rv, ERR_IO_PENDING);
+
+  CompletionCallback* c = user_accept_callback_;
+  user_accept_callback_ = NULL;
+  c->Run(rv > OK ? OK : rv);
+}
+
+void SSLServerSocketNSS::DoReadCallback(int rv) {
+  DCHECK(rv != ERR_IO_PENDING);
+  DCHECK(user_read_callback_);
+
+  // Since Run may result in Read being called, clear |user_read_callback_|
+  // up front.
+  CompletionCallback* c = user_read_callback_;
+  user_read_callback_ = NULL;
+  user_read_buf_ = NULL;
+  user_read_buf_len_ = 0;
+  c->Run(rv);
+}
+
+void SSLServerSocketNSS::DoWriteCallback(int rv) {
+  DCHECK(rv != ERR_IO_PENDING);
+  DCHECK(user_write_callback_);
+
+  // Since Run may result in Write being called, clear |user_write_callback_|
+  // up front.
+  CompletionCallback* c = user_write_callback_;
+  user_write_callback_ = NULL;
+  user_write_buf_ = NULL;
+  user_write_buf_len_ = 0;
+  c->Run(rv);
+}
+
+// static
+// NSS calls this if an incoming certificate needs to be verified.
+// Do nothing but return SECSuccess.
+// This is called only in full handshake mode.
+// Peer certificate is retrieved in HandshakeCallback() later, which is called
+// in full handshake mode or in resumption handshake mode.
+SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
+                                                 PRFileDesc* socket,
+                                                 PRBool checksig,
+                                                 PRBool is_server) {
+  // TODO(hclam): Implement.
+  // Tell NSS to not verify the certificate.
+  return SECSuccess;
+}
+
+// static
+// NSS calls this when handshake is completed.
+// After the SSL handshake is finished we need to verify the certificate.
+void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
+                                           void* arg) {
+  // TODO(hclam): Implement.
+}
+
+int SSLServerSocketNSS::Init() {
+  // Initialize the NSS SSL library in a threadsafe way.  This also
+  // initializes the NSS base library.
+  EnsureNSSSSLInit();
+  if (!NSS_IsInitialized())
+    return ERR_UNEXPECTED;
+#if !defined(OS_MACOSX) && !defined(OS_WIN)
+  // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
+  // by MessageLoopForIO::current().
+  // X509Certificate::Verify() runs on a worker thread of CertVerifier.
+  EnsureOCSPInit();
+#endif
+
+  return OK;
+}
+
 }  // namespace net
diff --git a/net/socket/ssl_server_socket_nss.h b/net/socket/ssl_server_socket_nss.h
index 3883c9b..1289272 100644
--- a/net/socket/ssl_server_socket_nss.h
+++ b/net/socket/ssl_server_socket_nss.h
@@ -42,11 +42,14 @@
                    CompletionCallback* callback);
   virtual int Write(IOBuffer* buf, int buf_len,
                     CompletionCallback* callback);
-  virtual bool SetReceiveBufferSize(int32 size) { return false; }
-  virtual bool SetSendBufferSize(int32 size) { return false; }
+  virtual bool SetReceiveBufferSize(int32 size);
+  virtual bool SetSendBufferSize(int32 size);
 
  private:
-  virtual int Init();
+  enum State {
+    STATE_NONE,
+    STATE_HANDSHAKE,
+  };
 
   int InitializeSSLOptions();
 
@@ -59,8 +62,8 @@
   int BufferRecv();
   void BufferRecvComplete(int result);
   bool DoTransportIO();
-  int DoPayloadWrite();
   int DoPayloadRead();
+  int DoPayloadWrite();
 
   int DoHandshakeLoop(int last_io_result);
   int DoReadLoop(int result);
@@ -76,6 +79,8 @@
                                       PRBool is_server);
   static void HandshakeCallback(PRFileDesc* socket, void* arg);
 
+  virtual int Init();
+
   // Members used to send and receive buffer.
   CompletionCallbackImpl<SSLServerSocketNSS> buffer_send_callback_;
   CompletionCallbackImpl<SSLServerSocketNSS> buffer_recv_callback_;
@@ -118,10 +123,6 @@
   // Private key used by the server.
   scoped_ptr<base::RSAPrivateKey> key_;
 
-  enum State {
-    STATE_NONE,
-    STATE_HANDSHAKE,
-  };
   State next_handshake_state_;
   bool completed_handshake_;
 
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 781a3f4..122d183 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -241,7 +241,6 @@
     ssl_config.snap_start_enabled = false;
     ssl_config.ssl3_enabled = true;
     ssl_config.tls1_enabled = true;
-    ssl_config.session_resume_disabled = true;
 
     // Certificate provided by the host doesn't need authority.
     net::SSLConfig::CertAndStatus cert_and_status;
@@ -283,9 +282,6 @@
 TEST_F(SSLServerSocketTest, Handshake) {
   Initialize();
 
-  if (!base::CheckNSSVersion("3.12.8"))
-    return;
-
   TestCompletionCallback connect_callback;
   TestCompletionCallback accept_callback;
 
@@ -306,24 +302,21 @@
 TEST_F(SSLServerSocketTest, DataTransfer) {
   Initialize();
 
-  if (!base::CheckNSSVersion("3.12.8"))
-    return;
-
   TestCompletionCallback connect_callback;
   TestCompletionCallback accept_callback;
 
   // Establish connection.
   int client_ret = client_socket_->Connect(&connect_callback);
-  EXPECT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING);
+  ASSERT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING);
 
   int server_ret = server_socket_->Accept(&accept_callback);
-  EXPECT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING);
+  ASSERT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING);
 
   if (client_ret == net::ERR_IO_PENDING) {
-    EXPECT_EQ(net::OK, connect_callback.WaitForResult());
+    ASSERT_EQ(net::OK, connect_callback.WaitForResult());
   }
   if (server_ret == net::ERR_IO_PENDING) {
-    EXPECT_EQ(net::OK, accept_callback.WaitForResult());
+    ASSERT_EQ(net::OK, accept_callback.WaitForResult());
   }
 
   const int kReadBufSize = 1024;
diff --git a/net/socket/tcp_client_socket_libevent.cc b/net/socket/tcp_client_socket_libevent.cc
index ca8b5fd..bf8850c 100644
--- a/net/socket/tcp_client_socket_libevent.cc
+++ b/net/socket/tcp_client_socket_libevent.cc
@@ -19,6 +19,7 @@
 #include "base/metrics/stats_counters.h"
 #include "base/string_util.h"
 #include "net/base/address_list_net_log_param.h"
+#include "net/base/connection_type_histograms.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_log.h"
@@ -55,7 +56,11 @@
   }
 #if defined(OS_LINUX)
   // Set seconds until first TCP keep alive.
+<<<<<<< HEAD
   optval = 25;
+=======
+  optval = 45;
+>>>>>>> chromium.org at r11.0.672.0
   if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen)) {
     PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd;
     return;
@@ -546,10 +551,33 @@
 }
 
 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) {
-  scoped_refptr<NetLog::EventParameters> params;
-  if (net_error != OK)
-    params = new NetLogIntegerParameter("net_error", net_error);
-  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, params);
+  if (net_error == OK)
+    UpdateConnectionTypeHistograms(CONNECTION_ANY);
+
+  if (net_error != OK) {
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
+    return;
+  }
+
+  struct sockaddr_storage source_address;
+  socklen_t addrlen = sizeof(source_address);
+  int rv = getsockname(
+      socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
+  if (rv != 0) {
+    PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: ";
+    NOTREACHED();
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
+    return;
+  }
+
+  const std::string source_address_str =
+      NetAddressToStringWithPort(
+          reinterpret_cast<const struct sockaddr*>(&source_address),
+          sizeof(source_address));
+  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
+                    make_scoped_refptr(new NetLogStringParameter(
+                        "source address",
+                        source_address_str)));
 }
 
 void TCPClientSocketLibevent::DoReadCallback(int rv) {
diff --git a/net/socket/tcp_client_socket_pool.cc b/net/socket/tcp_client_socket_pool.cc
index d490111..bc708d6 100644
--- a/net/socket/tcp_client_socket_pool.cc
+++ b/net/socket/tcp_client_socket_pool.cc
@@ -105,12 +105,6 @@
   }
 }
 
-int TCPConnectJob::ConnectInternal() {
-  next_state_ = STATE_RESOLVE_HOST;
-  start_time_ = base::TimeTicks::Now();
-  return DoLoop(OK);
-}
-
 void TCPConnectJob::OnIOComplete(int result) {
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING)
@@ -200,6 +194,12 @@
   return result;
 }
 
+int TCPConnectJob::ConnectInternal() {
+  next_state_ = STATE_RESOLVE_HOST;
+  start_time_ = base::TimeTicks::Now();
+  return DoLoop(OK);
+}
+
 ConnectJob* TCPClientSocketPool::TCPConnectJobFactory::NewConnectJob(
     const std::string& group_name,
     const PoolBase::Request& request,
diff --git a/net/socket/tcp_client_socket_pool.h b/net/socket/tcp_client_socket_pool.h
index c0c7808..d93d2be 100644
--- a/net/socket/tcp_client_socket_pool.h
+++ b/net/socket/tcp_client_socket_pool.h
@@ -82,11 +82,6 @@
     STATE_NONE,
   };
 
-  // Begins the host resolution and the TCP connect.  Returns OK on success
-  // and ERR_IO_PENDING if it cannot immediately service the request.
-  // Otherwise, it returns a net error code.
-  virtual int ConnectInternal();
-
   void OnIOComplete(int result);
 
   // Runs the state transition loop.
@@ -97,6 +92,11 @@
   int DoTCPConnect();
   int DoTCPConnectComplete(int result);
 
+  // Begins the host resolution and the TCP connect.  Returns OK on success
+  // and ERR_IO_PENDING if it cannot immediately service the request.
+  // Otherwise, it returns a net error code.
+  virtual int ConnectInternal();
+
   scoped_refptr<TCPSocketParams> params_;
   ClientSocketFactory* const client_socket_factory_;
   CompletionCallbackImpl<TCPConnectJob> callback_;
diff --git a/net/socket/tcp_client_socket_win.cc b/net/socket/tcp_client_socket_win.cc
index 262ccd4..ba28a41 100644
--- a/net/socket/tcp_client_socket_win.cc
+++ b/net/socket/tcp_client_socket_win.cc
@@ -4,6 +4,8 @@
 
 #include "net/socket/tcp_client_socket_win.h"
 
+#include <mstcpip.h>
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory_debug.h"
@@ -739,20 +741,58 @@
   //    http://technet.microsoft.com/en-us/library/bb726981.aspx
   const BOOL kDisableNagle = TRUE;
   int rv = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY,
-      reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle));
+                      reinterpret_cast<const char*>(&kDisableNagle),
+                      sizeof(kDisableNagle));
   DCHECK(!rv) << "Could not disable nagle";
 
-  // Disregard any failure in disabling nagle.
+  // Enable TCP Keep-Alive to prevent NAT routers from timing out TCP
+  // connections. See http://crbug.com/27400 for details.
+
+  struct tcp_keepalive keepalive_vals = {
+    1, // TCP keep-alive on.
+    45000,  // Wait 45s until sending first TCP keep-alive packet.
+    45000,  // Wait 45s between sending TCP keep-alive packets.
+  };
+  DWORD bytes_returned = 0xABAB;
+  rv = WSAIoctl(socket_, SIO_KEEPALIVE_VALS, &keepalive_vals,
+                sizeof(keepalive_vals), NULL, 0,
+                &bytes_returned, NULL, NULL);
+  DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket_
+              << " [error: " << WSAGetLastError() << "].";
+
+  // Disregard any failure in disabling nagle or enabling TCP Keep-Alive.
   return 0;
 }
 
 void TCPClientSocketWin::LogConnectCompletion(int net_error) {
-  scoped_refptr<NetLog::EventParameters> params;
-  if (net_error != OK)
-    params = new NetLogIntegerParameter("net_error", net_error);
-  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, params);
   if (net_error == OK)
     UpdateConnectionTypeHistograms(CONNECTION_ANY);
+
+  if (net_error != OK) {
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
+    return;
+  }
+
+  struct sockaddr_storage source_address;
+  socklen_t addrlen = sizeof(source_address);
+  int rv = getsockname(
+      socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
+  if (rv != 0) {
+    LOG(ERROR) << "getsockname() [rv: " << rv
+               << "] error: " << WSAGetLastError();
+    NOTREACHED();
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
+    return;
+  }
+
+  const std::string source_address_str =
+      NetAddressToStringWithPort(
+          reinterpret_cast<const struct sockaddr*>(&source_address),
+          sizeof(source_address));
+  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
+                    make_scoped_refptr(new NetLogStringParameter(
+                        "source address",
+                        source_address_str)));
 }
 
 void TCPClientSocketWin::DoReadCallback(int rv) {
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc
index 21c8e74..7733c5d 100644
--- a/net/socket_stream/socket_stream.cc
+++ b/net/socket_stream/socket_stream.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -39,12 +39,13 @@
 namespace net {
 
 SocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {}
-SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
 
 void SocketStream::ResponseHeaders::Realloc(size_t new_size) {
   headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
 }
 
+SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
+
 SocketStream::SocketStream(const GURL& url, Delegate* delegate)
     : delegate_(delegate),
       url_(url),
@@ -78,12 +79,6 @@
   DCHECK(delegate_);
 }
 
-SocketStream::~SocketStream() {
-  set_context(NULL);
-  DCHECK(!delegate_);
-  DCHECK(!pac_request_);
-}
-
 SocketStream::UserData* SocketStream::GetUserData(
     const void* key) const {
   UserDataMap::const_iterator found = user_data_.find(key);
@@ -96,6 +91,10 @@
   user_data_[key] = linked_ptr<UserData>(data);
 }
 
+bool SocketStream::is_secure() const {
+  return url_.SchemeIs("wss");
+}
+
 void SocketStream::set_context(URLRequestContext* context) {
   scoped_refptr<URLRequestContext> prev_context = context_;
 
@@ -200,26 +199,6 @@
       NewRunnableMethod(this, &SocketStream::DoClose));
 }
 
-void SocketStream::DoClose() {
-  closing_ = true;
-  // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing
-  // connection.  If next_state_ is STATE_AUTH_REQUIRED, it's waiting for
-  // restarting.  In these states, we'll close the SocketStream now.
-  if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) {
-    DoLoop(ERR_ABORTED);
-    return;
-  }
-  // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
-  // the SocketStream.
-  // If it's writing now, we should defer the closing after the current
-  // writing is completed.
-  if (next_state_ == STATE_READ_WRITE && !current_write_buf_)
-    DoLoop(ERR_ABORTED);
-
-  // In other next_state_, we'll wait for callback of other APIs, such as
-  // ResolveProxy().
-}
-
 void SocketStream::RestartWithAuth(
     const string16& username, const string16& password) {
   DCHECK(MessageLoop::current()) <<
@@ -255,28 +234,6 @@
   Close();
 }
 
-void SocketStream::Finish(int result) {
-  DCHECK(MessageLoop::current()) <<
-      "The current MessageLoop must exist";
-  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
-      "The current MessageLoop must be TYPE_IO";
-  DCHECK_LE(result, OK);
-  if (result == OK)
-    result = ERR_CONNECTION_CLOSED;
-  DCHECK_EQ(next_state_, STATE_NONE);
-  DVLOG(1) << "Finish result=" << net::ErrorToString(result);
-  if (delegate_)
-    delegate_->OnError(this, result);
-
-  metrics_->OnClose();
-  Delegate* delegate = delegate_;
-  delegate_ = NULL;
-  if (delegate) {
-    delegate->OnClose(this);
-  }
-  Release();
-}
-
 void SocketStream::SetHostResolver(HostResolver* host_resolver) {
   DCHECK(host_resolver);
   host_resolver_ = host_resolver;
@@ -288,10 +245,58 @@
   factory_ = factory;
 }
 
+SocketStream::~SocketStream() {
+  set_context(NULL);
+  DCHECK(!delegate_);
+  DCHECK(!pac_request_);
+}
+
 void SocketStream::CopyAddrInfo(struct addrinfo* head) {
   addresses_.Copy(head, true);
 }
 
+void SocketStream::DoClose() {
+  closing_ = true;
+  // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing
+  // connection.  If next_state_ is STATE_AUTH_REQUIRED, it's waiting for
+  // restarting.  In these states, we'll close the SocketStream now.
+  if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) {
+    DoLoop(ERR_ABORTED);
+    return;
+  }
+  // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
+  // the SocketStream.
+  // If it's writing now, we should defer the closing after the current
+  // writing is completed.
+  if (next_state_ == STATE_READ_WRITE && !current_write_buf_)
+    DoLoop(ERR_ABORTED);
+
+  // In other next_state_, we'll wait for callback of other APIs, such as
+  // ResolveProxy().
+}
+
+void SocketStream::Finish(int result) {
+  DCHECK(MessageLoop::current()) <<
+      "The current MessageLoop must exist";
+  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
+      "The current MessageLoop must be TYPE_IO";
+  DCHECK_LE(result, OK);
+  if (result == OK)
+    result = ERR_CONNECTION_CLOSED;
+  DCHECK_EQ(next_state_, STATE_NONE);
+  DVLOG(1) << "Finish result=" << ErrorToString(result);
+  if (delegate_)
+    delegate_->OnError(this, result);
+
+  metrics_->OnClose();
+  Delegate* delegate = delegate_;
+  delegate_ = NULL;
+  if (delegate) {
+    delegate->OnClose(this);
+  }
+  Release();
+}
+
 int SocketStream::DidEstablishConnection() {
   if (!socket_.get() || !socket_->IsConnected()) {
     next_state_ = STATE_CLOSE;
@@ -450,9 +455,8 @@
     // close the connection.
     if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
       DCHECK_EQ(next_state_, STATE_CLOSE);
-      net_log_.EndEvent(
-          NetLog::TYPE_SOCKET_STREAM_CONNECT,
-          make_scoped_refptr(new NetLogIntegerParameter("net_error", result)));
+      net_log_.EndEventWithNetErrorCode(
+          NetLog::TYPE_SOCKET_STREAM_CONNECT, result);
     }
   } while (result != ERR_IO_PENDING);
 }
@@ -535,7 +539,7 @@
   if (result == OK && delegate_) {
     next_state_ = STATE_TCP_CONNECT;
     result = delegate_->OnStartOpenConnection(this, &io_callback_);
-    if (result == net::ERR_IO_PENDING)
+    if (result == ERR_IO_PENDING)
       metrics_->OnWaitConnection();
   } else {
     next_state_ = STATE_CLOSE;
@@ -614,7 +618,8 @@
     // Support basic authentication scheme only, because we don't have
     // HttpRequestInfo.
     // TODO(ukai): Add support other authentication scheme.
-    if (auth_handler_.get() && auth_handler_->scheme() == "basic") {
+    if (auth_handler_.get() &&
+        auth_handler_->auth_scheme() == HttpAuth::AUTH_SCHEME_BASIC) {
       HttpRequestInfo request_info;
       std::string auth_token;
       int rv = auth_handler_->GenerateAuthToken(
@@ -749,7 +754,8 @@
         auth_info_->is_proxy = true;
         auth_info_->host_and_port =
             ASCIIToWide(proxy_info_.proxy_server().host_port_pair().ToString());
-        auth_info_->scheme = ASCIIToWide(auth_handler_->scheme());
+        auth_info_->scheme = ASCIIToWide(
+            HttpAuth::SchemeToString(auth_handler_->auth_scheme()));
         auth_info_->realm = ASCIIToWide(auth_handler_->realm());
         // Wait until RestartWithAuth or Close is called.
         MessageLoop::current()->PostTask(
@@ -944,7 +950,7 @@
     if (auth_identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP)
       auth_cache_.Remove(auth_origin,
                          auth_handler_->realm(),
-                         auth_handler_->scheme(),
+                         auth_handler_->auth_scheme(),
                          auth_identity_.username,
                          auth_identity_.password);
     auth_handler_.reset();
@@ -952,7 +958,7 @@
   }
 
   auth_identity_.invalid = true;
-  std::set<std::string> disabled_schemes;
+  std::set<HttpAuth::Scheme> disabled_schemes;
   HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, headers,
                                 HttpAuth::AUTH_PROXY,
                                 auth_origin, disabled_schemes,
@@ -964,8 +970,8 @@
   if (auth_handler_->NeedsIdentity()) {
     // We only support basic authentication scheme now.
     // TODO(ukai): Support other authentication scheme.
-    HttpAuthCache::Entry* entry =
-      auth_cache_.Lookup(auth_origin, auth_handler_->realm(), "basic");
+    HttpAuthCache::Entry* entry = auth_cache_.Lookup(
+        auth_origin, auth_handler_->realm(), HttpAuth::AUTH_SCHEME_BASIC);
     if (entry) {
       auth_identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
       auth_identity_.invalid = false;
@@ -984,14 +990,14 @@
   if (delegate_ && auth_info_.get())
     delegate_->OnAuthRequired(this, auth_info_.get());
   else
-    DoLoop(net::ERR_UNEXPECTED);
+    DoLoop(ERR_UNEXPECTED);
 }
 
 void SocketStream::DoRestartWithAuth() {
   DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
   auth_cache_.Add(ProxyAuthOrigin(),
                   auth_handler_->realm(),
-                  auth_handler_->scheme(),
+                  auth_handler_->auth_scheme(),
                   auth_handler_->challenge(),
                   auth_identity_.username,
                   auth_identity_.password,
@@ -1021,10 +1027,6 @@
   return result;
 }
 
-bool SocketStream::is_secure() const {
-  return url_.SchemeIs("wss");
-}
-
 SSLConfigService* SocketStream::ssl_config_service() const {
   return context_->ssl_config_service();
 }
diff --git a/net/socket_stream/socket_stream.h b/net/socket_stream/socket_stream.h
index b2afd1b..7b7599e 100644
--- a/net/socket_stream/socket_stream.h
+++ b/net/socket_stream/socket_stream.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/net/socket_stream/socket_stream_job_manager.cc b/net/socket_stream/socket_stream_job_manager.cc
index de2f0a8..105fc3e 100644
--- a/net/socket_stream/socket_stream_job_manager.cc
+++ b/net/socket_stream/socket_stream_job_manager.cc
@@ -31,7 +31,7 @@
 
   const std::string& scheme = url.scheme();  // already lowercase
 
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
   FactoryMap::const_iterator found = factories_.find(scheme);
   if (found != factories_.end()) {
     SocketStreamJob* job = found->second(url, delegate);
@@ -46,7 +46,7 @@
 SocketStreamJob::ProtocolFactory*
 SocketStreamJobManager::RegisterProtocolFactory(
     const std::string& scheme, SocketStreamJob::ProtocolFactory* factory) {
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
 
   SocketStreamJob::ProtocolFactory* old_factory;
   FactoryMap::iterator found = factories_.find(scheme);
diff --git a/net/socket_stream/socket_stream_job_manager.h b/net/socket_stream/socket_stream_job_manager.h
index fbd572d..c9050f6 100644
--- a/net/socket_stream/socket_stream_job_manager.h
+++ b/net/socket_stream/socket_stream_job_manager.h
@@ -35,7 +35,7 @@
   SocketStreamJobManager();
   ~SocketStreamJobManager();
 
-  mutable Lock lock_;
+  mutable base::Lock lock_;
   FactoryMap factories_;
 
   DISALLOW_COPY_AND_ASSIGN(SocketStreamJobManager);
diff --git a/net/socket_stream/socket_stream_metrics.h b/net/socket_stream/socket_stream_metrics.h
index 946a065..66a9ffd 100644
--- a/net/socket_stream/socket_stream_metrics.h
+++ b/net/socket_stream/socket_stream_metrics.h
@@ -18,6 +18,22 @@
 
 class SocketStreamMetrics {
  public:
+  enum ProtocolType {
+    PROTOCOL_UNKNOWN,
+    PROTOCOL_WEBSOCKET,
+    PROTOCOL_WEBSOCKET_SECURE,
+    NUM_PROTOCOL_TYPES,
+  };
+
+  enum ConnectionType {
+    CONNECTION_NONE,
+    ALL_CONNECTIONS,
+    TUNNEL_CONNECTION,
+    SOCKS_CONNECTION,
+    SSL_CONNECTION,
+    NUM_CONNECTION_TYPES,
+  };
+
   explicit SocketStreamMetrics(const GURL& url);
   ~SocketStreamMetrics();
 
@@ -31,21 +47,6 @@
   void OnWrite(int len);
   void OnClose();
 
-  enum ProtocolType {
-    PROTOCOL_UNKNOWN,
-    PROTOCOL_WEBSOCKET,
-    PROTOCOL_WEBSOCKET_SECURE,
-    NUM_PROTOCOL_TYPES,
-  };
-  enum ConnectionType {
-    CONNECTION_NONE,
-    ALL_CONNECTIONS,
-    TUNNEL_CONNECTION,
-    SOCKS_CONNECTION,
-    SSL_CONNECTION,
-    NUM_CONNECTION_TYPES,
-  };
-
  private:
   void CountProtocolType(ProtocolType protocol_type);
   void CountConnectionType(ConnectionType connection_type);
diff --git a/net/socket_stream/socket_stream_unittest.cc b/net/socket_stream/socket_stream_unittest.cc
index 832b0ab..24a0ff0 100644
--- a/net/socket_stream/socket_stream_unittest.cc
+++ b/net/socket_stream/socket_stream_unittest.cc
@@ -14,7 +14,7 @@
 #include "net/base/test_completion_callback.h"
 #include "net/socket/socket_test_util.h"
 #include "net/socket_stream/socket_stream.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
diff --git a/net/spdy/spdy_frame_builder.cc b/net/spdy/spdy_frame_builder.cc
index eed6eb2..c9d82e2 100644
--- a/net/spdy/spdy_frame_builder.cc
+++ b/net/spdy/spdy_frame_builder.cc
@@ -103,19 +103,14 @@
   return ReadBytes(iter, data, *length);
 }
 
-char* SpdyFrameBuilder::BeginWrite(size_t length) {
-  size_t needed_size = length_ + length;
-  if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
-    return NULL;
+bool SpdyFrameBuilder::WriteString(const std::string& value) {
+  if (value.size() > 0xffff)
+    return false;
 
-#ifdef ARCH_CPU_64_BITS
-  DCHECK_LE(length, std::numeric_limits<uint32>::max());
-#endif
+  if (!WriteUInt16(static_cast<int>(value.size())))
+    return false;
 
-  return buffer_ + length_;
-}
-
-void SpdyFrameBuilder::EndWrite(char* dest, int length) {
+  return WriteBytes(value.data(), static_cast<uint16>(value.size()));
 }
 
 bool SpdyFrameBuilder::WriteBytes(const void* data, uint16 data_len) {
@@ -132,16 +127,6 @@
   return true;
 }
 
-bool SpdyFrameBuilder::WriteString(const std::string& value) {
-  if (value.size() > 0xffff)
-    return false;
-
-  if (!WriteUInt16(static_cast<int>(value.size())))
-    return false;
-
-  return WriteBytes(value.data(), static_cast<uint16>(value.size()));
-}
-
 char* SpdyFrameBuilder::BeginWriteData(uint16 length) {
   DCHECK_EQ(variable_buffer_offset_, 0U) <<
     "There can only be one variable buffer in a SpdyFrameBuilder";
@@ -161,6 +146,21 @@
   return data_ptr;
 }
 
+char* SpdyFrameBuilder::BeginWrite(size_t length) {
+  size_t needed_size = length_ + length;
+  if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
+    return NULL;
+
+#ifdef ARCH_CPU_64_BITS
+  DCHECK_LE(length, std::numeric_limits<uint32>::max());
+#endif
+
+  return buffer_ + length_;
+}
+
+void SpdyFrameBuilder::EndWrite(char* dest, int length) {
+}
+
 bool SpdyFrameBuilder::Resize(size_t new_capacity) {
   if (new_capacity <= capacity_)
     return true;
diff --git a/net/spdy/spdy_frame_builder.h b/net/spdy/spdy_frame_builder.h
index 548cfda..36a3f53 100644
--- a/net/spdy/spdy_frame_builder.h
+++ b/net/spdy/spdy_frame_builder.h
@@ -33,7 +33,6 @@
 class SpdyFrameBuilder {
  public:
   SpdyFrameBuilder();
-  ~SpdyFrameBuilder();
 
   // Initializes a SpdyFrameBuilder from a const block of data.  The data is
   // not copied; instead the data is merely referenced by this
@@ -41,6 +40,8 @@
   // this way.
   SpdyFrameBuilder(const char* data, int data_len);
 
+  ~SpdyFrameBuilder();
+
   // Returns the size of the SpdyFrameBuilder's data.
   int length() const { return length_; }
 
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index ed21610..9a3203b 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -19,8 +19,39 @@
 #include "third_party/zlib/zlib.h"
 #endif
 
+namespace {
+
+// The following compression setting are based on Brian Olson's analysis. See
+// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
+// for more details.
+const int kCompressorLevel = 9;
+const int kCompressorWindowSizeInBits = 11;
+const int kCompressorMemLevel = 1;
+
+uLong dictionary_id = 0;
+
+}  // namespace
+
 namespace spdy {
 
+// This is just a hacked dictionary to use for shrinking HTTP-like headers.
+// TODO(mbelshe): Use a scientific methodology for computing the dictionary.
+const char SpdyFramer::kDictionary[] =
+  "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
+  "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
+  "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
+  "-agent10010120020120220320420520630030130230330430530630740040140240340440"
+  "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
+  "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
+  "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
+  "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
+  "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
+  "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
+  "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
+  "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
+  ".1statusversionurl";
+const int SpdyFramer::kDictionarySize = arraysize(kDictionary);
+
 // By default is compression on or off.
 bool SpdyFramer::compression_default_ = true;
 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion;
@@ -71,92 +102,6 @@
   delete [] current_frame_buffer_;
 }
 
-void SpdyFramer::Reset() {
-  state_ = SPDY_RESET;
-  error_code_ = SPDY_NO_ERROR;
-  remaining_payload_ = 0;
-  remaining_control_payload_ = 0;
-  current_frame_len_ = 0;
-  if (current_frame_capacity_ != kControlFrameBufferInitialSize) {
-    delete [] current_frame_buffer_;
-    current_frame_buffer_ = 0;
-    current_frame_capacity_ = 0;
-    ExpandControlFrameBuffer(kControlFrameBufferInitialSize);
-  }
-}
-
-const char* SpdyFramer::StateToString(int state) {
-  switch (state) {
-    case SPDY_ERROR:
-      return "ERROR";
-    case SPDY_DONE:
-      return "DONE";
-    case SPDY_AUTO_RESET:
-      return "AUTO_RESET";
-    case SPDY_RESET:
-      return "RESET";
-    case SPDY_READING_COMMON_HEADER:
-      return "READING_COMMON_HEADER";
-    case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
-      return "INTERPRET_CONTROL_FRAME_COMMON_HEADER";
-    case SPDY_CONTROL_FRAME_PAYLOAD:
-      return "CONTROL_FRAME_PAYLOAD";
-    case SPDY_IGNORE_REMAINING_PAYLOAD:
-      return "IGNORE_REMAINING_PAYLOAD";
-    case SPDY_FORWARD_STREAM_FRAME:
-      return "FORWARD_STREAM_FRAME";
-  }
-  return "UNKNOWN_STATE";
-}
-
-size_t SpdyFramer::BytesSafeToRead() const {
-  switch (state_) {
-    case SPDY_ERROR:
-    case SPDY_DONE:
-    case SPDY_AUTO_RESET:
-    case SPDY_RESET:
-      return 0;
-    case SPDY_READING_COMMON_HEADER:
-      DCHECK_LT(current_frame_len_, SpdyFrame::size());
-      return SpdyFrame::size() - current_frame_len_;
-    case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
-      return 0;
-    case SPDY_CONTROL_FRAME_PAYLOAD:
-    case SPDY_IGNORE_REMAINING_PAYLOAD:
-    case SPDY_FORWARD_STREAM_FRAME:
-      return remaining_payload_;
-  }
-  // We should never get to here.
-  return 0;
-}
-
-void SpdyFramer::set_error(SpdyError error) {
-  DCHECK(visitor_);
-  error_code_ = error;
-  CHANGE_STATE(SPDY_ERROR);
-  visitor_->OnError(this);
-}
-
-const char* SpdyFramer::ErrorCodeToString(int error_code) {
-  switch (error_code) {
-    case SPDY_NO_ERROR:
-      return "NO_ERROR";
-    case SPDY_INVALID_CONTROL_FRAME:
-      return "INVALID_CONTROL_FRAME";
-    case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
-      return "CONTROL_PAYLOAD_TOO_LARGE";
-    case SPDY_ZLIB_INIT_FAILURE:
-      return "ZLIB_INIT_FAILURE";
-    case SPDY_UNSUPPORTED_VERSION:
-      return "UNSUPPORTED_VERSION";
-    case SPDY_DECOMPRESS_FAILURE:
-      return "DECOMPRESS_FAILURE";
-    case SPDY_COMPRESS_FAILURE:
-      return "COMPRESS_FAILURE";
-  }
-  return "UNKNOWN_ERROR";
-}
-
 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
   DCHECK(visitor_);
   DCHECK(data);
@@ -211,6 +156,429 @@
   return original_len - len;
 }
 
+void SpdyFramer::Reset() {
+  state_ = SPDY_RESET;
+  error_code_ = SPDY_NO_ERROR;
+  remaining_payload_ = 0;
+  remaining_control_payload_ = 0;
+  current_frame_len_ = 0;
+  if (current_frame_capacity_ != kControlFrameBufferInitialSize) {
+    delete [] current_frame_buffer_;
+    current_frame_buffer_ = 0;
+    current_frame_capacity_ = 0;
+    ExpandControlFrameBuffer(kControlFrameBufferInitialSize);
+  }
+}
+
+bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame,
+                                  SpdyHeaderBlock* block) {
+  SpdyControlFrame control_frame(frame->data(), false);
+  uint32 type = control_frame.type();
+  if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS)
+    return false;
+
+  // Find the header data within the control frame.
+  scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame));
+  if (!decompressed_frame.get())
+    return false;
+
+  const char *header_data = NULL;
+  int header_length = 0;
+
+  switch (type) {
+    case SYN_STREAM:
+      {
+        SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false);
+        header_data = syn_frame.header_block();
+        header_length = syn_frame.header_block_len();
+      }
+      break;
+    case SYN_REPLY:
+      {
+        SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false);
+        header_data = syn_frame.header_block();
+        header_length = syn_frame.header_block_len();
+      }
+      break;
+    case HEADERS:
+      {
+        SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false);
+        header_data = header_frame.header_block();
+        header_length = header_frame.header_block_len();
+      }
+      break;
+  }
+
+  SpdyFrameBuilder builder(header_data, header_length);
+  void* iter = NULL;
+  uint16 num_headers;
+  if (builder.ReadUInt16(&iter, &num_headers)) {
+    int index;
+    for (index = 0; index < num_headers; ++index) {
+      std::string name;
+      std::string value;
+      if (!builder.ReadString(&iter, &name))
+        break;
+      if (!builder.ReadString(&iter, &value))
+        break;
+      if (!name.size() || !value.size())
+        return false;
+      if (block->find(name) == block->end()) {
+        (*block)[name] = value;
+      } else {
+        return false;
+      }
+    }
+    return index == num_headers &&
+        iter == header_data + header_length;
+  }
+  return false;
+}
+
+SpdySynStreamControlFrame* SpdyFramer::CreateSynStream(
+    SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority,
+    SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
+  SpdyFrameBuilder frame;
+
+  DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0));
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+  DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask);
+
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(SYN_STREAM);
+  frame.WriteUInt32(0);  // Placeholder for the length and flags
+  frame.WriteUInt32(stream_id);
+  frame.WriteUInt32(associated_stream_id);
+  frame.WriteUInt16(ntohs(priority) << 6);  // Priority.
+
+  frame.WriteUInt16(headers->size());  // Number of headers.
+  SpdyHeaderBlock::iterator it;
+  for (it = headers->begin(); it != headers->end(); ++it) {
+    bool wrote_header;
+    wrote_header = frame.WriteString(it->first);
+    wrote_header &= frame.WriteString(it->second);
+    DCHECK(wrote_header);
+  }
+
+  // Write the length and flags.
+  size_t length = frame.length() - SpdyFrame::size();
+  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
+  FlagsAndLength flags_length;
+  flags_length.length_ = htonl(static_cast<uint32>(length));
+  DCHECK_EQ(0, flags & ~kControlFlagsMask);
+  flags_length.flags_[0] = flags;
+  frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
+
+  scoped_ptr<SpdyFrame> syn_frame(frame.take());
+  if (compressed) {
+    return reinterpret_cast<SpdySynStreamControlFrame*>(
+        CompressFrame(*syn_frame.get()));
+  }
+  return reinterpret_cast<SpdySynStreamControlFrame*>(syn_frame.release());
+}
+
+SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id,
+    SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
+  DCHECK_GT(stream_id, 0u);
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+
+  SpdyFrameBuilder frame;
+
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(SYN_REPLY);
+  frame.WriteUInt32(0);  // Placeholder for the length and flags.
+  frame.WriteUInt32(stream_id);
+  frame.WriteUInt16(0);  // Unused
+
+  frame.WriteUInt16(headers->size());  // Number of headers.
+  SpdyHeaderBlock::iterator it;
+  for (it = headers->begin(); it != headers->end(); ++it) {
+    bool wrote_header;
+    wrote_header = frame.WriteString(it->first);
+    wrote_header &= frame.WriteString(it->second);
+    DCHECK(wrote_header);
+  }
+
+  // Write the length and flags.
+  size_t length = frame.length() - SpdyFrame::size();
+  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
+  FlagsAndLength flags_length;
+  flags_length.length_ = htonl(static_cast<uint32>(length));
+  DCHECK_EQ(0, flags & ~kControlFlagsMask);
+  flags_length.flags_[0] = flags;
+  frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
+
+  scoped_ptr<SpdyFrame> reply_frame(frame.take());
+  if (compressed) {
+    return reinterpret_cast<SpdySynReplyControlFrame*>(
+        CompressFrame(*reply_frame.get()));
+  }
+  return reinterpret_cast<SpdySynReplyControlFrame*>(reply_frame.release());
+}
+
+/* static */
+SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id,
+                                                       SpdyStatusCodes status) {
+  DCHECK_GT(stream_id, 0u);
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+  DCHECK_NE(status, INVALID);
+  DCHECK_LT(status, NUM_STATUS_CODES);
+
+  SpdyFrameBuilder frame;
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(RST_STREAM);
+  frame.WriteUInt32(8);
+  frame.WriteUInt32(stream_id);
+  frame.WriteUInt32(status);
+  return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take());
+}
+
+/* static */
+SpdySettingsControlFrame* SpdyFramer::CreateSettings(
+    const SpdySettings& values) {
+  SpdyFrameBuilder frame;
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(SETTINGS);
+  size_t settings_size = SpdySettingsControlFrame::size() - SpdyFrame::size() +
+      8 * values.size();
+  frame.WriteUInt32(settings_size);
+  frame.WriteUInt32(values.size());
+  SpdySettings::const_iterator it = values.begin();
+  while (it != values.end()) {
+    frame.WriteUInt32(it->first.id_);
+    frame.WriteUInt32(it->second);
+    ++it;
+  }
+  return reinterpret_cast<SpdySettingsControlFrame*>(frame.take());
+}
+
+/* static */
+SpdyControlFrame* SpdyFramer::CreateNopFrame() {
+  SpdyFrameBuilder frame;
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(NOOP);
+  frame.WriteUInt32(0);
+  return reinterpret_cast<SpdyControlFrame*>(frame.take());
+}
+
+/* static */
+SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway(
+    SpdyStreamId last_accepted_stream_id) {
+  DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask);
+
+  SpdyFrameBuilder frame;
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(GOAWAY);
+  size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size();
+  frame.WriteUInt32(go_away_size);
+  frame.WriteUInt32(last_accepted_stream_id);
+  return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take());
+}
+
+SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id,
+    SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
+  // Basically the same as CreateSynReply().
+  DCHECK_GT(stream_id, 0u);
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+
+  SpdyFrameBuilder frame;
+  frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion);
+  frame.WriteUInt16(HEADERS);
+  frame.WriteUInt32(0);  // Placeholder for the length and flags.
+  frame.WriteUInt32(stream_id);
+  frame.WriteUInt16(0);  // Unused
+
+  frame.WriteUInt16(headers->size());  // Number of headers.
+  SpdyHeaderBlock::iterator it;
+  for (it = headers->begin(); it != headers->end(); ++it) {
+    bool wrote_header;
+    wrote_header = frame.WriteString(it->first);
+    wrote_header &= frame.WriteString(it->second);
+    DCHECK(wrote_header);
+  }
+
+  // Write the length and flags.
+  size_t length = frame.length() - SpdyFrame::size();
+  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
+  FlagsAndLength flags_length;
+  flags_length.length_ = htonl(static_cast<uint32>(length));
+  DCHECK_EQ(0, flags & ~kControlFlagsMask);
+  flags_length.flags_[0] = flags;
+  frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
+
+  scoped_ptr<SpdyFrame> headers_frame(frame.take());
+  if (compressed) {
+    return reinterpret_cast<SpdyHeadersControlFrame*>(
+        CompressFrame(*headers_frame.get()));
+  }
+  return reinterpret_cast<SpdyHeadersControlFrame*>(headers_frame.release());
+}
+
+/* static */
+SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate(
+    SpdyStreamId stream_id,
+    uint32 delta_window_size) {
+  DCHECK_GT(stream_id, 0u);
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+  DCHECK_GT(delta_window_size, 0u);
+  DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize);
+
+  SpdyFrameBuilder frame;
+  frame.WriteUInt16(kControlFlagMask | spdy_version_);
+  frame.WriteUInt16(WINDOW_UPDATE);
+  size_t window_update_size = SpdyWindowUpdateControlFrame::size() -
+      SpdyFrame::size();
+  frame.WriteUInt32(window_update_size);
+  frame.WriteUInt32(stream_id);
+  frame.WriteUInt32(delta_window_size);
+  return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take());
+}
+
+/* static */
+bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
+                               SpdySettings* settings) {
+  DCHECK_EQ(frame->type(), SETTINGS);
+  DCHECK(settings);
+
+  SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
+  void* iter = NULL;
+  for (size_t index = 0; index < frame->num_entries(); ++index) {
+    uint32 id;
+    uint32 value;
+    if (!parser.ReadUInt32(&iter, &id))
+      return false;
+    if (!parser.ReadUInt32(&iter, &value))
+      return false;
+    settings->insert(settings->end(), std::make_pair(id, value));
+  }
+  return true;
+}
+
+SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
+                                           const char* data,
+                                           uint32 len, SpdyDataFlags flags) {
+  SpdyFrameBuilder frame;
+
+  DCHECK_GT(stream_id, 0u);
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+  frame.WriteUInt32(stream_id);
+
+  DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask));
+  FlagsAndLength flags_length;
+  flags_length.length_ = htonl(len);
+  DCHECK_EQ(0, flags & ~kDataFlagsMask);
+  flags_length.flags_[0] = flags;
+  frame.WriteBytes(&flags_length, sizeof(flags_length));
+
+  frame.WriteBytes(data, len);
+  scoped_ptr<SpdyFrame> data_frame(frame.take());
+  SpdyDataFrame* rv;
+  if (flags & DATA_FLAG_COMPRESSED) {
+    rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get()));
+  } else {
+    rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
+  }
+
+  if (flags & DATA_FLAG_FIN) {
+    CleanupCompressorForStream(stream_id);
+  }
+
+  return rv;
+}
+
+SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
+  if (frame.is_control_frame()) {
+    return CompressControlFrame(
+        reinterpret_cast<const SpdyControlFrame&>(frame));
+  }
+  return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
+}
+
+SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
+  if (frame.is_control_frame()) {
+    return DecompressControlFrame(
+        reinterpret_cast<const SpdyControlFrame&>(frame));
+  }
+  return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
+}
+
+SpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) {
+  int size = SpdyFrame::size() + frame.length();
+  SpdyFrame* new_frame = new SpdyFrame(size);
+  memcpy(new_frame->data(), frame.data(), size);
+  return new_frame;
+}
+
+bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const {
+  // The important frames to compress are those which contain large
+  // amounts of compressible data - namely the headers in the SYN_STREAM
+  // and SYN_REPLY.
+  // TODO(mbelshe): Reconcile this with the spec when the spec is
+  // explicit about which frames compress and which do not.
+  if (frame.is_control_frame()) {
+    const SpdyControlFrame& control_frame =
+        reinterpret_cast<const SpdyControlFrame&>(frame);
+    return control_frame.type() == SYN_STREAM ||
+           control_frame.type() == SYN_REPLY;
+  }
+
+  const SpdyDataFrame& data_frame =
+      reinterpret_cast<const SpdyDataFrame&>(frame);
+  return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
+}
+
+const char* SpdyFramer::StateToString(int state) {
+  switch (state) {
+    case SPDY_ERROR:
+      return "ERROR";
+    case SPDY_DONE:
+      return "DONE";
+    case SPDY_AUTO_RESET:
+      return "AUTO_RESET";
+    case SPDY_RESET:
+      return "RESET";
+    case SPDY_READING_COMMON_HEADER:
+      return "READING_COMMON_HEADER";
+    case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
+      return "INTERPRET_CONTROL_FRAME_COMMON_HEADER";
+    case SPDY_CONTROL_FRAME_PAYLOAD:
+      return "CONTROL_FRAME_PAYLOAD";
+    case SPDY_IGNORE_REMAINING_PAYLOAD:
+      return "IGNORE_REMAINING_PAYLOAD";
+    case SPDY_FORWARD_STREAM_FRAME:
+      return "FORWARD_STREAM_FRAME";
+  }
+  return "UNKNOWN_STATE";
+}
+
+const char* SpdyFramer::ErrorCodeToString(int error_code) {
+  switch (error_code) {
+    case SPDY_NO_ERROR:
+      return "NO_ERROR";
+    case SPDY_INVALID_CONTROL_FRAME:
+      return "INVALID_CONTROL_FRAME";
+    case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
+      return "CONTROL_PAYLOAD_TOO_LARGE";
+    case SPDY_ZLIB_INIT_FAILURE:
+      return "ZLIB_INIT_FAILURE";
+    case SPDY_UNSUPPORTED_VERSION:
+      return "UNSUPPORTED_VERSION";
+    case SPDY_DECOMPRESS_FAILURE:
+      return "DECOMPRESS_FAILURE";
+    case SPDY_COMPRESS_FAILURE:
+      return "COMPRESS_FAILURE";
+  }
+  return "UNKNOWN_ERROR";
+}
+
+void SpdyFramer::set_enable_compression(bool value) {
+  enable_compression_ = value;
+}
+
+void SpdyFramer::set_enable_compression_default(bool value) {
+  compression_default_ = value;
+}
+
 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
   // This should only be called when we're in the SPDY_READING_COMMON_HEADER
   // state.
@@ -431,361 +799,6 @@
   return original_len - len;
 }
 
-void SpdyFramer::ExpandControlFrameBuffer(size_t size) {
-  size_t alloc_size = size + SpdyFrame::size();
-  DCHECK_LT(alloc_size, kControlFrameBufferMaxSize);
-  if (alloc_size <= current_frame_capacity_)
-    return;
-  char* new_buffer = new char[alloc_size];
-  memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
-  delete [] current_frame_buffer_;
-  current_frame_capacity_ = alloc_size;
-  current_frame_buffer_ = new_buffer;
-}
-
-bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame,
-                                  SpdyHeaderBlock* block) {
-  SpdyControlFrame control_frame(frame->data(), false);
-  uint32 type = control_frame.type();
-  if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS)
-    return false;
-
-  // Find the header data within the control frame.
-  scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame));
-  if (!decompressed_frame.get())
-    return false;
-
-  const char *header_data = NULL;
-  int header_length = 0;
-
-  switch (type) {
-    case SYN_STREAM:
-      {
-        SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false);
-        header_data = syn_frame.header_block();
-        header_length = syn_frame.header_block_len();
-      }
-      break;
-    case SYN_REPLY:
-      {
-        SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false);
-        header_data = syn_frame.header_block();
-        header_length = syn_frame.header_block_len();
-      }
-      break;
-    case HEADERS:
-      {
-        SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false);
-        header_data = header_frame.header_block();
-        header_length = header_frame.header_block_len();
-      }
-      break;
-  }
-
-  SpdyFrameBuilder builder(header_data, header_length);
-  void* iter = NULL;
-  uint16 num_headers;
-  if (builder.ReadUInt16(&iter, &num_headers)) {
-    int index;
-    for (index = 0; index < num_headers; ++index) {
-      std::string name;
-      std::string value;
-      if (!builder.ReadString(&iter, &name))
-        break;
-      if (!builder.ReadString(&iter, &value))
-        break;
-      if (!name.size() || !value.size())
-        return false;
-      if (block->find(name) == block->end()) {
-        (*block)[name] = value;
-      } else {
-        return false;
-      }
-    }
-    return index == num_headers &&
-        iter == header_data + header_length;
-  }
-  return false;
-}
-
-/* static */
-bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
-                               SpdySettings* settings) {
-  DCHECK_EQ(frame->type(), SETTINGS);
-  DCHECK(settings);
-
-  SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
-  void* iter = NULL;
-  for (size_t index = 0; index < frame->num_entries(); ++index) {
-    uint32 id;
-    uint32 value;
-    if (!parser.ReadUInt32(&iter, &id))
-      return false;
-    if (!parser.ReadUInt32(&iter, &value))
-      return false;
-    settings->insert(settings->end(), std::make_pair(id, value));
-  }
-  return true;
-}
-
-SpdySynStreamControlFrame* SpdyFramer::CreateSynStream(
-    SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority,
-    SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
-  SpdyFrameBuilder frame;
-
-  DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0));
-  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-  DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask);
-
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(SYN_STREAM);
-  frame.WriteUInt32(0);  // Placeholder for the length and flags
-  frame.WriteUInt32(stream_id);
-  frame.WriteUInt32(associated_stream_id);
-  frame.WriteUInt16(ntohs(priority) << 6);  // Priority.
-
-  frame.WriteUInt16(headers->size());  // Number of headers.
-  SpdyHeaderBlock::iterator it;
-  for (it = headers->begin(); it != headers->end(); ++it) {
-    bool wrote_header;
-    wrote_header = frame.WriteString(it->first);
-    wrote_header &= frame.WriteString(it->second);
-    DCHECK(wrote_header);
-  }
-
-  // Write the length and flags.
-  size_t length = frame.length() - SpdyFrame::size();
-  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
-  FlagsAndLength flags_length;
-  flags_length.length_ = htonl(static_cast<uint32>(length));
-  DCHECK_EQ(0, flags & ~kControlFlagsMask);
-  flags_length.flags_[0] = flags;
-  frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
-
-  scoped_ptr<SpdyFrame> syn_frame(frame.take());
-  if (compressed) {
-    return reinterpret_cast<SpdySynStreamControlFrame*>(
-        CompressFrame(*syn_frame.get()));
-  }
-  return reinterpret_cast<SpdySynStreamControlFrame*>(syn_frame.release());
-}
-
-SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id,
-    SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
-  DCHECK_GT(stream_id, 0u);
-  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-
-  SpdyFrameBuilder frame;
-
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(SYN_REPLY);
-  frame.WriteUInt32(0);  // Placeholder for the length and flags.
-  frame.WriteUInt32(stream_id);
-  frame.WriteUInt16(0);  // Unused
-
-  frame.WriteUInt16(headers->size());  // Number of headers.
-  SpdyHeaderBlock::iterator it;
-  for (it = headers->begin(); it != headers->end(); ++it) {
-    bool wrote_header;
-    wrote_header = frame.WriteString(it->first);
-    wrote_header &= frame.WriteString(it->second);
-    DCHECK(wrote_header);
-  }
-
-  // Write the length and flags.
-  size_t length = frame.length() - SpdyFrame::size();
-  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
-  FlagsAndLength flags_length;
-  flags_length.length_ = htonl(static_cast<uint32>(length));
-  DCHECK_EQ(0, flags & ~kControlFlagsMask);
-  flags_length.flags_[0] = flags;
-  frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
-
-  scoped_ptr<SpdyFrame> reply_frame(frame.take());
-  if (compressed) {
-    return reinterpret_cast<SpdySynReplyControlFrame*>(
-        CompressFrame(*reply_frame.get()));
-  }
-  return reinterpret_cast<SpdySynReplyControlFrame*>(reply_frame.release());
-}
-
-/* static */
-SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id,
-                                                       SpdyStatusCodes status) {
-  DCHECK_GT(stream_id, 0u);
-  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-  DCHECK_NE(status, INVALID);
-  DCHECK_LT(status, NUM_STATUS_CODES);
-
-  SpdyFrameBuilder frame;
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(RST_STREAM);
-  frame.WriteUInt32(8);
-  frame.WriteUInt32(stream_id);
-  frame.WriteUInt32(status);
-  return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take());
-}
-
-/* static */
-SpdySettingsControlFrame* SpdyFramer::CreateSettings(
-    const SpdySettings& values) {
-  SpdyFrameBuilder frame;
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(SETTINGS);
-  size_t settings_size = SpdySettingsControlFrame::size() - SpdyFrame::size() +
-      8 * values.size();
-  frame.WriteUInt32(settings_size);
-  frame.WriteUInt32(values.size());
-  SpdySettings::const_iterator it = values.begin();
-  while (it != values.end()) {
-    frame.WriteUInt32(it->first.id_);
-    frame.WriteUInt32(it->second);
-    ++it;
-  }
-  return reinterpret_cast<SpdySettingsControlFrame*>(frame.take());
-}
-
-/* static */
-SpdyControlFrame* SpdyFramer::CreateNopFrame() {
-  SpdyFrameBuilder frame;
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(NOOP);
-  frame.WriteUInt32(0);
-  return reinterpret_cast<SpdyControlFrame*>(frame.take());
-}
-
-/* static */
-SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway(
-    SpdyStreamId last_accepted_stream_id) {
-  DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask);
-
-  SpdyFrameBuilder frame;
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(GOAWAY);
-  size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size();
-  frame.WriteUInt32(go_away_size);
-  frame.WriteUInt32(last_accepted_stream_id);
-  return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take());
-}
-
-SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id,
-    SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
-  // Basically the same as CreateSynReply().
-  DCHECK_GT(stream_id, 0u);
-  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-
-  SpdyFrameBuilder frame;
-  frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion);
-  frame.WriteUInt16(HEADERS);
-  frame.WriteUInt32(0);  // Placeholder for the length and flags.
-  frame.WriteUInt32(stream_id);
-  frame.WriteUInt16(0);  // Unused
-
-  frame.WriteUInt16(headers->size());  // Number of headers.
-  SpdyHeaderBlock::iterator it;
-  for (it = headers->begin(); it != headers->end(); ++it) {
-    bool wrote_header;
-    wrote_header = frame.WriteString(it->first);
-    wrote_header &= frame.WriteString(it->second);
-    DCHECK(wrote_header);
-  }
-
-  // Write the length and flags.
-  size_t length = frame.length() - SpdyFrame::size();
-  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
-  FlagsAndLength flags_length;
-  flags_length.length_ = htonl(static_cast<uint32>(length));
-  DCHECK_EQ(0, flags & ~kControlFlagsMask);
-  flags_length.flags_[0] = flags;
-  frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
-
-  scoped_ptr<SpdyFrame> headers_frame(frame.take());
-  if (compressed) {
-    return reinterpret_cast<SpdyHeadersControlFrame*>(
-        CompressFrame(*headers_frame.get()));
-  }
-  return reinterpret_cast<SpdyHeadersControlFrame*>(headers_frame.release());
-}
-
-/* static */
-SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate(
-    SpdyStreamId stream_id,
-    uint32 delta_window_size) {
-  DCHECK_GT(stream_id, 0u);
-  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-  DCHECK_GT(delta_window_size, 0u);
-  DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize);
-
-  SpdyFrameBuilder frame;
-  frame.WriteUInt16(kControlFlagMask | spdy_version_);
-  frame.WriteUInt16(WINDOW_UPDATE);
-  size_t window_update_size = SpdyWindowUpdateControlFrame::size() -
-      SpdyFrame::size();
-  frame.WriteUInt32(window_update_size);
-  frame.WriteUInt32(stream_id);
-  frame.WriteUInt32(delta_window_size);
-  return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take());
-}
-
-SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
-                                           const char* data,
-                                           uint32 len, SpdyDataFlags flags) {
-  SpdyFrameBuilder frame;
-
-  DCHECK_GT(stream_id, 0u);
-  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-  frame.WriteUInt32(stream_id);
-
-  DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask));
-  FlagsAndLength flags_length;
-  flags_length.length_ = htonl(len);
-  DCHECK_EQ(0, flags & ~kDataFlagsMask);
-  flags_length.flags_[0] = flags;
-  frame.WriteBytes(&flags_length, sizeof(flags_length));
-
-  frame.WriteBytes(data, len);
-  scoped_ptr<SpdyFrame> data_frame(frame.take());
-  SpdyDataFrame* rv;
-  if (flags & DATA_FLAG_COMPRESSED) {
-    rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get()));
-  } else {
-    rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
-  }
-
-  if (flags & DATA_FLAG_FIN) {
-    CleanupCompressorForStream(stream_id);
-  }
-
-  return rv;
-}
-
-// The following compression setting are based on Brian Olson's analysis. See
-// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
-// for more details.
-static const int kCompressorLevel = 9;
-static const int kCompressorWindowSizeInBits = 11;
-static const int kCompressorMemLevel = 1;
-
-// This is just a hacked dictionary to use for shrinking HTTP-like headers.
-// TODO(mbelshe): Use a scientific methodology for computing the dictionary.
-const char SpdyFramer::kDictionary[] =
-  "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
-  "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
-  "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
-  "-agent10010120020120220320420520630030130230330430530630740040140240340440"
-  "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
-  "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
-  "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
-  "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
-  "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
-  "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
-  "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
-  "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
-  ".1statusversionurl";
-const int SpdyFramer::kDictionarySize = arraysize(kDictionary);
-
-static uLong dictionary_id = 0;
-
 z_stream* SpdyFramer::GetHeaderCompressor() {
   if (header_compressor_.get())
     return header_compressor_.get();  // Already initialized.
@@ -873,74 +886,6 @@
   return stream_decompressors_[stream_id] = decompressor.release();
 }
 
-bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
-                                    int* payload_length,
-                                    int* header_length,
-                                    const char** payload) const {
-  size_t frame_size;
-  if (frame.is_control_frame()) {
-    const SpdyControlFrame& control_frame =
-        reinterpret_cast<const SpdyControlFrame&>(frame);
-    switch (control_frame.type()) {
-      case SYN_STREAM:
-        {
-          const SpdySynStreamControlFrame& syn_frame =
-              reinterpret_cast<const SpdySynStreamControlFrame&>(frame);
-          frame_size = SpdySynStreamControlFrame::size();
-          *payload_length = syn_frame.header_block_len();
-          *header_length = frame_size;
-          *payload = frame.data() + *header_length;
-        }
-        break;
-      case SYN_REPLY:
-        {
-          const SpdySynReplyControlFrame& syn_frame =
-              reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
-          frame_size = SpdySynReplyControlFrame::size();
-          *payload_length = syn_frame.header_block_len();
-          *header_length = frame_size;
-          *payload = frame.data() + *header_length;
-        }
-        break;
-      case HEADERS:
-        {
-          const SpdyHeadersControlFrame& headers_frame =
-              reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
-          frame_size = SpdyHeadersControlFrame::size();
-          *payload_length = headers_frame.header_block_len();
-          *header_length = frame_size;
-          *payload = frame.data() + *header_length;
-        }
-        break;
-      default:
-        // TODO(mbelshe): set an error?
-        return false;  // We can't compress this frame!
-    }
-  } else {
-    frame_size = SpdyFrame::size();
-    *header_length = frame_size;
-    *payload_length = frame.length();
-    *payload = frame.data() + SpdyFrame::size();
-  }
-  return true;
-}
-
-SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
-  if (frame.is_control_frame()) {
-    return CompressControlFrame(
-        reinterpret_cast<const SpdyControlFrame&>(frame));
-  }
-  return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
-}
-
-SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
-  if (frame.is_control_frame()) {
-    return DecompressControlFrame(
-        reinterpret_cast<const SpdyControlFrame&>(frame));
-  }
-  return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
-}
-
 SpdyControlFrame* SpdyFramer::CompressControlFrame(
     const SpdyControlFrame& frame) {
   z_stream* compressor = GetHeaderCompressor();
@@ -950,6 +895,14 @@
       CompressFrameWithZStream(frame, compressor));
 }
 
+SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
+  z_stream* compressor = GetStreamCompressor(frame.stream_id());
+  if (!compressor)
+    return NULL;
+  return reinterpret_cast<SpdyDataFrame*>(
+      CompressFrameWithZStream(frame, compressor));
+}
+
 SpdyControlFrame* SpdyFramer::DecompressControlFrame(
     const SpdyControlFrame& frame) {
   z_stream* decompressor = GetHeaderDecompressor();
@@ -959,14 +912,6 @@
       DecompressFrameWithZStream(frame, decompressor));
 }
 
-SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
-  z_stream* compressor = GetStreamCompressor(frame.stream_id());
-  if (!compressor)
-    return NULL;
-  return reinterpret_cast<SpdyDataFrame*>(
-      CompressFrameWithZStream(frame, compressor));
-}
-
 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
   z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
   if (!decompressor)
@@ -1145,37 +1090,96 @@
   stream_decompressors_.clear();
 }
 
-SpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) {
-  int size = SpdyFrame::size() + frame.length();
-  SpdyFrame* new_frame = new SpdyFrame(size);
-  memcpy(new_frame->data(), frame.data(), size);
-  return new_frame;
+size_t SpdyFramer::BytesSafeToRead() const {
+  switch (state_) {
+    case SPDY_ERROR:
+    case SPDY_DONE:
+    case SPDY_AUTO_RESET:
+    case SPDY_RESET:
+      return 0;
+    case SPDY_READING_COMMON_HEADER:
+      DCHECK_LT(current_frame_len_, SpdyFrame::size());
+      return SpdyFrame::size() - current_frame_len_;
+    case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
+      return 0;
+    case SPDY_CONTROL_FRAME_PAYLOAD:
+    case SPDY_IGNORE_REMAINING_PAYLOAD:
+    case SPDY_FORWARD_STREAM_FRAME:
+      return remaining_payload_;
+  }
+  // We should never get to here.
+  return 0;
 }
 
-bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const {
-  // The important frames to compress are those which contain large
-  // amounts of compressible data - namely the headers in the SYN_STREAM
-  // and SYN_REPLY.
-  // TODO(mbelshe): Reconcile this with the spec when the spec is
-  // explicit about which frames compress and which do not.
+void SpdyFramer::set_error(SpdyError error) {
+  DCHECK(visitor_);
+  error_code_ = error;
+  CHANGE_STATE(SPDY_ERROR);
+  visitor_->OnError(this);
+}
+
+void SpdyFramer::ExpandControlFrameBuffer(size_t size) {
+  size_t alloc_size = size + SpdyFrame::size();
+  DCHECK_LT(alloc_size, kControlFrameBufferMaxSize);
+  if (alloc_size <= current_frame_capacity_)
+    return;
+  char* new_buffer = new char[alloc_size];
+  memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
+  delete [] current_frame_buffer_;
+  current_frame_capacity_ = alloc_size;
+  current_frame_buffer_ = new_buffer;
+}
+
+bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
+                                    int* payload_length,
+                                    int* header_length,
+                                    const char** payload) const {
+  size_t frame_size;
   if (frame.is_control_frame()) {
     const SpdyControlFrame& control_frame =
         reinterpret_cast<const SpdyControlFrame&>(frame);
-    return control_frame.type() == SYN_STREAM ||
-           control_frame.type() == SYN_REPLY;
+    switch (control_frame.type()) {
+      case SYN_STREAM:
+        {
+          const SpdySynStreamControlFrame& syn_frame =
+              reinterpret_cast<const SpdySynStreamControlFrame&>(frame);
+          frame_size = SpdySynStreamControlFrame::size();
+          *payload_length = syn_frame.header_block_len();
+          *header_length = frame_size;
+          *payload = frame.data() + *header_length;
+        }
+        break;
+      case SYN_REPLY:
+        {
+          const SpdySynReplyControlFrame& syn_frame =
+              reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
+          frame_size = SpdySynReplyControlFrame::size();
+          *payload_length = syn_frame.header_block_len();
+          *header_length = frame_size;
+          *payload = frame.data() + *header_length;
+        }
+        break;
+      case HEADERS:
+        {
+          const SpdyHeadersControlFrame& headers_frame =
+              reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
+          frame_size = SpdyHeadersControlFrame::size();
+          *payload_length = headers_frame.header_block_len();
+          *header_length = frame_size;
+          *payload = frame.data() + *header_length;
+        }
+        break;
+      default:
+        // TODO(mbelshe): set an error?
+        return false;  // We can't compress this frame!
+    }
+  } else {
+    frame_size = SpdyFrame::size();
+    *header_length = frame_size;
+    *payload_length = frame.length();
+    *payload = frame.data() + SpdyFrame::size();
   }
-
-  const SpdyDataFrame& data_frame =
-      reinterpret_cast<const SpdyDataFrame&>(frame);
-  return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
-}
-
-void SpdyFramer::set_enable_compression(bool value) {
-  enable_compression_ = value;
-}
-
-void SpdyFramer::set_enable_compression_default(bool value) {
-  compression_default_ = value;
+  return true;
 }
 
 }  // namespace spdy
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 15acff7..6a6abb2 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -264,7 +264,7 @@
 
 bool SpdyHttpStream::OnSendBodyComplete(int status) {
   CHECK(request_body_stream_.get());
-  request_body_stream_->DidConsume(status);
+  request_body_stream_->MarkConsumedAndFillBuffer(status);
   return request_body_stream_->eof();
 }
 
diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc
index e367c42..bf7376a 100644
--- a/net/spdy/spdy_http_utils.cc
+++ b/net/spdy/spdy_http_utils.cc
@@ -107,4 +107,18 @@
 
 }
 
+// TODO(gavinp): re-adjust this once SPDY v3 has three priority bits,
+// eliminating the need for this folding.
+int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) {
+  DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES);
+  switch (priority) {
+    case LOWEST:
+      return SPDY_PRIORITY_LOWEST - 1;
+    case IDLE:
+      return SPDY_PRIORITY_LOWEST;
+    default:
+      return priority;
+  }
+}
+
 }  // namespace net
diff --git a/net/spdy/spdy_http_utils.h b/net/spdy/spdy_http_utils.h
index 40f0254..855d264 100644
--- a/net/spdy/spdy_http_utils.h
+++ b/net/spdy/spdy_http_utils.h
@@ -6,6 +6,7 @@
 #define NET_SPDY_SPDY_HTTP_UTILS_H_
 #pragma once
 
+#include "net/base/request_priority.h"
 #include "net/spdy/spdy_framer.h"
 
 namespace net {
@@ -29,6 +30,8 @@
                                       spdy::SpdyHeaderBlock* headers,
                                       bool direct);
 
+int ConvertRequestPriorityToSpdyPriority(RequestPriority priority);
+
 }  // namespace net
 
 #endif  // NET_SPDY_SPDY_HTTP_UTILS_H_
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 586f7dc..de248cb 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -1,7 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/http/http_network_transaction.h"
+
 #include <string>
 #include <vector>
 
@@ -10,10 +12,11 @@
 #include "net/http/http_network_session_peer.h"
 #include "net/http/http_transaction_unittest.h"
 #include "net/spdy/spdy_http_stream.h"
+#include "net/spdy/spdy_http_utils.h"
 #include "net/spdy/spdy_session.h"
 #include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_test_util.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/platform_test.h"
 
 //-----------------------------------------------------------------------------
@@ -2252,7 +2255,7 @@
     MessageLoop::current()->Run();
     EXPECT_EQ(1, d.response_started_count());
     EXPECT_FALSE(d.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
     std::string contents("hello!");
     EXPECT_EQ(contents, d.data_received());
   }
@@ -2390,7 +2393,7 @@
     MessageLoop::current()->Run();
     EXPECT_EQ(1, d2.response_started_count());
     EXPECT_FALSE(d2.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::SUCCESS, r2.status().status());
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
     std::string contents2("hello!");
     EXPECT_EQ(contents2, d2.data_received());
   }
@@ -3262,17 +3265,16 @@
 }
 
 // Verify that we don't crash on some corrupt frames.
-// TODO(eroman): Renable this test, see http://crbug.com/48588
-TEST_P(SpdyNetworkTransactionTest, DISABLED_CorruptFrameSessionError) {
-  // This is the length field with a big number
-  scoped_ptr<spdy::SpdyFrame> syn_reply_massive_length(
+TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
+  // This is the length field that's too short.
+  scoped_ptr<spdy::SpdyFrame> syn_reply_wrong_length(
       ConstructSpdyGetSynReply(NULL, 0, 1));
-  syn_reply_massive_length->set_length(0x111126);
+  syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4);
 
   struct SynReplyTests {
     const spdy::SpdyFrame* syn_reply;
   } test_cases[] = {
-    { syn_reply_massive_length.get(), },
+    { syn_reply_wrong_length.get(), },
   };
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index 6d743d2..9e203ce 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -59,6 +59,10 @@
   Disconnect();
 }
 
+const HttpResponseInfo* SpdyProxyClientSocket::GetConnectResponseInfo() const {
+  return response_.headers ? &response_ : NULL;
+}
+
 HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() {
   DCHECK(response_stream_.get());
   return response_stream_.release();
@@ -275,19 +279,19 @@
         break;
       case STATE_SEND_REQUEST:
         DCHECK_EQ(OK, rv);
-        net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
-                            NULL);
+        net_log_.BeginEvent(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, NULL);
         rv = DoSendRequest();
         break;
       case STATE_SEND_REQUEST_COMPLETE:
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
         rv = DoSendRequestComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
-                          NULL);
         break;
       case STATE_READ_REPLY_COMPLETE:
         rv = DoReadReplyComplete(rv);
-        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
-                          NULL);
+        net_log_.EndEventWithNetErrorCode(
+            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
         break;
       default:
         NOTREACHED() << "bad state";
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index 64bcd6a..5192dbd 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -60,10 +60,7 @@
   }
 
   // ProxyClientSocket methods:
-
-  virtual const HttpResponseInfo* GetConnectResponseInfo() const {
-    return response_.headers ? &response_ : NULL;
-  }
+  virtual const HttpResponseInfo* GetConnectResponseInfo() const;
 
   // In the event of a non-200 response to the CONNECT request, this
   // method may be called to return an HttpStream in order to read
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc
index c4c5f2c..e4483bd 100644
--- a/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -16,6 +16,7 @@
 #include "net/socket/client_socket_factory.h"
 #include "net/socket/tcp_client_socket.h"
 #include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_http_utils.h"
 #include "net/spdy/spdy_protocol.h"
 #include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_test_util.h"
@@ -84,8 +85,13 @@
   void AddAuthToCache() {
     const string16 kFoo(ASCIIToUTF16("foo"));
     const string16 kBar(ASCIIToUTF16("bar"));
-    session_->auth_cache()->Add(GURL(kProxyUrl), "MyRealm1", "Basic",
-                                "Basic realm=MyRealm1", kFoo, kBar, "/");
+    session_->auth_cache()->Add(GURL(kProxyUrl),
+                                "MyRealm1",
+                                HttpAuth::AUTH_SCHEME_BASIC,
+                                "Basic realm=MyRealm1",
+                                kFoo,
+                                kBar,
+                                "/");
   }
 
   void Run(int steps) {
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index cbc1365..c268ee4 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -23,7 +23,9 @@
 #include "net/http/http_network_session.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/spdy/spdy_frame_builder.h"
+#include "net/spdy/spdy_http_utils.h"
 #include "net/spdy/spdy_protocol.h"
+#include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_settings_storage.h"
 #include "net/spdy/spdy_stream.h"
 
@@ -257,10 +259,12 @@
 }
 
 SpdySession::~SpdySession() {
-  state_ = CLOSED;
+  if (state_ != CLOSED) {
+    state_ = CLOSED;
 
-  // Cleanup all the streams.
-  CloseAllStreams(net::ERR_ABORTED);
+    // Cleanup all the streams.
+    CloseAllStreams(net::ERR_ABORTED);
+  }
 
   if (connection_->is_initialized()) {
     // With Spdy we can't recycle sockets.
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 6268a4f..3afa7c0 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -200,28 +200,19 @@
   friend class base::RefCounted<SpdySession>;
   FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GetActivePushStream);
 
-  enum State {
-    IDLE,
-    CONNECTING,
-    CONNECTED,
-    CLOSED
-  };
-
-  enum { kDefaultMaxConcurrentStreams = 10 };
-
   struct PendingCreateStream {
-    const GURL* url;
-    RequestPriority priority;
-    scoped_refptr<SpdyStream>* spdy_stream;
-    const BoundNetLog* stream_net_log;
-    CompletionCallback* callback;
-
     PendingCreateStream(const GURL& url, RequestPriority priority,
                         scoped_refptr<SpdyStream>* spdy_stream,
                         const BoundNetLog& stream_net_log,
                         CompletionCallback* callback)
         : url(&url), priority(priority), spdy_stream(spdy_stream),
           stream_net_log(&stream_net_log), callback(callback) { }
+
+    const GURL* url;
+    RequestPriority priority;
+    scoped_refptr<SpdyStream>* spdy_stream;
+    const BoundNetLog* stream_net_log;
+    CompletionCallback* callback;
   };
   typedef std::queue<PendingCreateStream, std::list< PendingCreateStream> >
       PendingCreateStreamQueue;
@@ -242,6 +233,15 @@
   typedef std::map<const scoped_refptr<SpdyStream>*, CallbackResultPair>
       PendingCallbackMap;
 
+  enum State {
+    IDLE,
+    CONNECTING,
+    CONNECTED,
+    CLOSED
+  };
+
+  enum { kDefaultMaxConcurrentStreams = 10 };
+
   virtual ~SpdySession();
 
   void ProcessPendingCreateStreams();
@@ -251,13 +251,6 @@
       scoped_refptr<SpdyStream>* spdy_stream,
       const BoundNetLog& stream_net_log);
 
-  // SpdyFramerVisitorInterface
-  virtual void OnError(spdy::SpdyFramer*);
-  virtual void OnStreamFrameData(spdy::SpdyStreamId stream_id,
-                                 const char* data,
-                                 size_t len);
-  virtual void OnControl(const spdy::SpdyControlFrame* frame);
-
   // Control frame handlers.
   void OnSyn(const spdy::SpdySynStreamControlFrame& frame,
              const linked_ptr<spdy::SpdyHeaderBlock>& headers);
@@ -325,6 +318,13 @@
   // can be deferred to the MessageLoop, so we avoid re-entrancy problems.
   void InvokeUserStreamCreationCallback(scoped_refptr<SpdyStream>* stream);
 
+  // SpdyFramerVisitorInterface:
+  virtual void OnError(spdy::SpdyFramer*);
+  virtual void OnStreamFrameData(spdy::SpdyStreamId stream_id,
+                                 const char* data,
+                                 size_t len);
+  virtual void OnControl(const spdy::SpdyControlFrame* frame);
+
   // Callbacks for the Spdy session.
   CompletionCallbackImpl<SpdySession> read_callback_;
   CompletionCallbackImpl<SpdySession> write_callback_;
@@ -439,12 +439,12 @@
                          spdy::SpdyStreamId id,
                          spdy::SpdyStreamId associated_stream);
 
-  virtual Value* ToValue() const;
-
   const linked_ptr<spdy::SpdyHeaderBlock>& GetHeaders() const {
     return headers_;
   }
 
+  virtual Value* ToValue() const;
+
  private:
   virtual ~NetLogSpdySynParameter();
 
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index aa807af..50bb20b 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -114,15 +114,15 @@
     RemoveSessionList(session->host_port_proxy_pair());
 }
 
-Value* SpdySessionPool::SpdySessionPoolInfoToValue() {
+Value* SpdySessionPool::SpdySessionPoolInfoToValue() const {
   ListValue* list = new ListValue();
 
   SpdySessionsMap::const_iterator spdy_session_pool_it = sessions_.begin();
   for (SpdySessionsMap::const_iterator it = sessions_.begin();
-       it != sessions_.end(); it++) {
+       it != sessions_.end(); ++it) {
     SpdySessionList* sessions = it->second;
     for (SpdySessionList::const_iterator session = sessions->begin();
-         session != sessions->end(); session++) {
+         session != sessions->end(); ++session) {
       list->Append(session->get()->GetInfoAsValue());
     }
   }
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 6b346f6..1a0d536 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -90,7 +90,7 @@
 
   // Creates a Value summary of the state of the spdy session pool. The caller
   // responsible for deleting the returned value.
-  Value* SpdySessionPoolInfoToValue();
+  Value* SpdySessionPoolInfoToValue() const;
 
   // NetworkChangeNotifier::Observer methods:
 
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 8b76cd9..44848e3 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -5,6 +5,7 @@
 #include "net/spdy/spdy_session.h"
 
 #include "net/spdy/spdy_io_buffer.h"
+#include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_stream.h"
 #include "net/spdy/spdy_test_util.h"
 #include "testing/platform_test.h"
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index 3bf0a23..9c7b934 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/spdy/spdy_stream.h"
 #include "base/ref_counted.h"
+#include "net/spdy/spdy_http_utils.h"
 #include "net/spdy/spdy_session.h"
 #include "net/spdy/spdy_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/spdy/spdy_test_util.cc b/net/spdy/spdy_test_util.cc
index 3a7f771..5340f22 100644
--- a/net/spdy/spdy_test_util.cc
+++ b/net/spdy/spdy_test_util.cc
@@ -9,8 +9,10 @@
 #include "base/basictypes.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
+#include "net/http/http_network_session.h"
 #include "net/http/http_network_transaction.h"
 #include "net/spdy/spdy_framer.h"
+#include "net/spdy/spdy_http_utils.h"
 
 namespace net {
 
@@ -290,7 +292,7 @@
     type,                         // Kind = Syn
     stream_id,                    // Stream ID
     associated_stream_id,         // Associated stream ID
-    net::ConvertRequestPriorityToSpdyPriority(request_priority),
+    ConvertRequestPriorityToSpdyPriority(request_priority),
                                   // Priority
     flags,                        // Control Flags
     compressed,                   // Compressed
@@ -852,6 +854,94 @@
   return total_len;
 }
 
+SpdySessionDependencies::SpdySessionDependencies()
+    : host_resolver(new MockHostResolver),
+      cert_verifier(new CertVerifier),
+      proxy_service(ProxyService::CreateDirect()),
+      ssl_config_service(new SSLConfigServiceDefaults),
+      socket_factory(new MockClientSocketFactory),
+      deterministic_socket_factory(new DeterministicMockClientSocketFactory),
+      http_auth_handler_factory(
+          HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {
+  // Note: The CancelledTransaction test does cleanup by running all
+  // tasks in the message loop (RunAllPending).  Unfortunately, that
+  // doesn't clean up tasks on the host resolver thread; and
+  // TCPConnectJob is currently not cancellable.  Using synchronous
+  // lookups allows the test to shutdown cleanly.  Until we have
+  // cancellable TCPConnectJobs, use synchronous lookups.
+  host_resolver->set_synchronous_mode(true);
+}
+
+SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service)
+    : host_resolver(new MockHostResolver),
+      cert_verifier(new CertVerifier),
+      proxy_service(proxy_service),
+      ssl_config_service(new SSLConfigServiceDefaults),
+      socket_factory(new MockClientSocketFactory),
+      deterministic_socket_factory(new DeterministicMockClientSocketFactory),
+      http_auth_handler_factory(
+          HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {}
+
+SpdySessionDependencies::~SpdySessionDependencies() {}
+
+// static
+HttpNetworkSession* SpdySessionDependencies::SpdyCreateSession(
+    SpdySessionDependencies* session_deps) {
+  net::HttpNetworkSession::Params params;
+  params.client_socket_factory = session_deps->socket_factory.get();
+  params.host_resolver = session_deps->host_resolver.get();
+  params.cert_verifier = session_deps->cert_verifier.get();
+  params.proxy_service = session_deps->proxy_service;
+  params.ssl_config_service = session_deps->ssl_config_service;
+  params.http_auth_handler_factory =
+      session_deps->http_auth_handler_factory.get();
+  return new HttpNetworkSession(params);
+}
+
+// static
+HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
+    SpdySessionDependencies* session_deps) {
+  net::HttpNetworkSession::Params params;
+  params.client_socket_factory =
+      session_deps->deterministic_socket_factory.get();
+  params.host_resolver = session_deps->host_resolver.get();
+  params.cert_verifier = session_deps->cert_verifier.get();
+  params.proxy_service = session_deps->proxy_service;
+  params.ssl_config_service = session_deps->ssl_config_service;
+  params.http_auth_handler_factory =
+      session_deps->http_auth_handler_factory.get();
+  return new HttpNetworkSession(params);
+}
+
+SpdyURLRequestContext::SpdyURLRequestContext() {
+  host_resolver_ = new MockHostResolver();
+  cert_verifier_ = new CertVerifier;
+  proxy_service_ = ProxyService::CreateDirect();
+  ssl_config_service_ = new SSLConfigServiceDefaults;
+  http_auth_handler_factory_ = HttpAuthHandlerFactory::CreateDefault(
+      host_resolver_);
+  net::HttpNetworkSession::Params params;
+  params.client_socket_factory = &socket_factory_;
+  params.host_resolver = host_resolver_;
+  params.cert_verifier = cert_verifier_;
+  params.proxy_service = proxy_service_;
+  params.ssl_config_service = ssl_config_service_;
+  params.http_auth_handler_factory = http_auth_handler_factory_;
+  params.network_delegate = network_delegate_;
+  scoped_refptr<HttpNetworkSession> network_session(
+      new HttpNetworkSession(params));
+  http_transaction_factory_ = new HttpCache(
+      network_session,
+      HttpCache::DefaultBackend::InMemory(0));
+}
+
+SpdyURLRequestContext::~SpdyURLRequestContext() {
+  delete http_transaction_factory_;
+  delete http_auth_handler_factory_;
+  delete cert_verifier_;
+  delete host_resolver_;
+}
+
 const SpdyHeaderInfo make_spdy_header(spdy::SpdyControlType type) {
   const SpdyHeaderInfo kHeader = {
     type,                         // Kind = Syn
diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h
index 1b052fa..7bd78b6 100644
--- a/net/spdy/spdy_test_util.h
+++ b/net/spdy/spdy_test_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,7 +19,6 @@
 #include "net/proxy/proxy_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_session_pool.h"
 #include "net/url_request/url_request_context.h"
 
 namespace net {
@@ -326,34 +325,17 @@
 class SpdySessionDependencies {
  public:
   // Default set of dependencies -- "null" proxy service.
-  SpdySessionDependencies()
-      : host_resolver(new MockHostResolver),
-        cert_verifier(new CertVerifier),
-        proxy_service(ProxyService::CreateDirect()),
-        ssl_config_service(new SSLConfigServiceDefaults),
-        socket_factory(new MockClientSocketFactory),
-        deterministic_socket_factory(new DeterministicMockClientSocketFactory),
-        http_auth_handler_factory(
-            HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {
-          // Note: The CancelledTransaction test does cleanup by running all
-          // tasks in the message loop (RunAllPending).  Unfortunately, that
-          // doesn't clean up tasks on the host resolver thread; and
-          // TCPConnectJob is currently not cancellable.  Using synchronous
-          // lookups allows the test to shutdown cleanly.  Until we have
-          // cancellable TCPConnectJobs, use synchronous lookups.
-          host_resolver->set_synchronous_mode(true);
-        }
+  SpdySessionDependencies();
 
   // Custom proxy service dependency.
-  explicit SpdySessionDependencies(ProxyService* proxy_service)
-      : host_resolver(new MockHostResolver),
-        cert_verifier(new CertVerifier),
-        proxy_service(proxy_service),
-        ssl_config_service(new SSLConfigServiceDefaults),
-        socket_factory(new MockClientSocketFactory),
-        deterministic_socket_factory(new DeterministicMockClientSocketFactory),
-        http_auth_handler_factory(
-            HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {}
+  explicit SpdySessionDependencies(ProxyService* proxy_service);
+
+  ~SpdySessionDependencies();
+
+  static HttpNetworkSession* SpdyCreateSession(
+      SpdySessionDependencies* session_deps);
+  static HttpNetworkSession* SpdyCreateSessionDeterministic(
+      SpdySessionDependencies* session_deps);
 
   // NOTE: host_resolver must be ordered before http_auth_handler_factory.
   scoped_ptr<MockHostResolverBase> host_resolver;
@@ -363,75 +345,16 @@
   scoped_ptr<MockClientSocketFactory> socket_factory;
   scoped_ptr<DeterministicMockClientSocketFactory> deterministic_socket_factory;
   scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
-
-  static HttpNetworkSession* SpdyCreateSession(
-      SpdySessionDependencies* session_deps) {
-    return new HttpNetworkSession(session_deps->host_resolver.get(),
-                                  session_deps->cert_verifier.get(),
-                                  NULL /* dnsrr_resolver */,
-                                  NULL /* dns_cert_checker */,
-                                  NULL /* ssl_host_info_factory */,
-                                  session_deps->proxy_service,
-                                  session_deps->socket_factory.get(),
-                                  session_deps->ssl_config_service,
-                                  new SpdySessionPool(NULL),
-                                  session_deps->http_auth_handler_factory.get(),
-                                  NULL,
-                                  NULL);
-  }
-  static HttpNetworkSession* SpdyCreateSessionDeterministic(
-      SpdySessionDependencies* session_deps) {
-    return new HttpNetworkSession(session_deps->host_resolver.get(),
-                                  session_deps->cert_verifier.get(),
-                                  NULL /* dnsrr_resolver */,
-                                  NULL /* dns_cert_checker */,
-                                  NULL /* ssl_host_info_factory */,
-                                  session_deps->proxy_service,
-                                  session_deps->
-                                      deterministic_socket_factory.get(),
-                                  session_deps->ssl_config_service,
-                                  new SpdySessionPool(NULL),
-                                  session_deps->http_auth_handler_factory.get(),
-                                  NULL,
-                                  NULL);
-  }
 };
 
 class SpdyURLRequestContext : public URLRequestContext {
  public:
-  SpdyURLRequestContext() {
-    host_resolver_ = new MockHostResolver();
-    cert_verifier_ = new CertVerifier;
-    proxy_service_ = ProxyService::CreateDirect();
-    ssl_config_service_ = new SSLConfigServiceDefaults;
-    http_auth_handler_factory_ = HttpAuthHandlerFactory::CreateDefault(
-        host_resolver_);
-    http_transaction_factory_ = new net::HttpCache(
-        new HttpNetworkLayer(&socket_factory_,
-                             host_resolver_,
-                             cert_verifier_,
-                             NULL /* dnsrr_resolver */,
-                             NULL /* dns_cert_checker */,
-                             NULL /* ssl_host_info_factory */,
-                             proxy_service_,
-                             ssl_config_service_,
-                             new SpdySessionPool(NULL),
-                             http_auth_handler_factory_,
-                             network_delegate_,
-                             NULL),
-        NULL /* net_log */,
-        net::HttpCache::DefaultBackend::InMemory(0));
-  }
+  SpdyURLRequestContext();
 
   MockClientSocketFactory& socket_factory() { return socket_factory_; }
 
  protected:
-  virtual ~SpdyURLRequestContext() {
-    delete http_transaction_factory_;
-    delete http_auth_handler_factory_;
-    delete cert_verifier_;
-    delete host_resolver_;
-  }
+  virtual ~SpdyURLRequestContext();
 
  private:
   MockClientSocketFactory socket_factory_;
diff --git a/net/test/test_server.cc b/net/test/test_server.cc
index 9722dc1..8f5f3d2 100644
--- a/net/test/test_server.cc
+++ b/net/test/test_server.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,6 +28,7 @@
 #include "googleurl/src/gurl.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/host_resolver.h"
+#include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/base/test_root_certs.h"
 #include "net/socket/tcp_client_socket.h"
@@ -104,25 +105,6 @@
   Stop();
 }
 
-void TestServer::Init(const FilePath& document_root) {
-  // At this point, the port that the testserver will listen on is unknown.
-  // The testserver will listen on an ephemeral port, and write the port
-  // number out over a pipe that this TestServer object will read from. Once
-  // that is complete, the host_port_pair_ will contain the actual port.
-  host_port_pair_ = HostPortPair(GetHostname(type_, https_options_), 0);
-  process_handle_ = base::kNullProcessHandle;
-
-  FilePath src_dir;
-  PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
-
-  document_root_ = src_dir.Append(document_root);
-
-  certificates_dir_ = src_dir.Append(FILE_PATH_LITERAL("net"))
-                       .Append(FILE_PATH_LITERAL("data"))
-                       .Append(FILE_PATH_LITERAL("ssl"))
-                       .Append(FILE_PATH_LITERAL("certificates"));
-}
-
 bool TestServer::Start() {
   if (type_ == TYPE_HTTPS) {
     if (!LoadTestRootCert())
@@ -275,6 +257,25 @@
   return true;
 }
 
+void TestServer::Init(const FilePath& document_root) {
+  // At this point, the port that the testserver will listen on is unknown.
+  // The testserver will listen on an ephemeral port, and write the port
+  // number out over a pipe that this TestServer object will read from. Once
+  // that is complete, the host_port_pair_ will contain the actual port.
+  host_port_pair_ = HostPortPair(GetHostname(type_, https_options_), 0);
+  process_handle_ = base::kNullProcessHandle;
+
+  FilePath src_dir;
+  PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
+
+  document_root_ = src_dir.Append(document_root);
+
+  certificates_dir_ = src_dir.Append(FILE_PATH_LITERAL("net"))
+                       .Append(FILE_PATH_LITERAL("data"))
+                       .Append(FILE_PATH_LITERAL("ssl"))
+                       .Append(FILE_PATH_LITERAL("certificates"));
+}
+
 bool TestServer::SetPythonPath() {
   FilePath third_party_dir;
   if (!PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir)) {
@@ -294,8 +295,9 @@
   // Locate the Python code generated by the protocol buffers compiler.
   FilePath pyproto_code_dir;
   if (!GetPyProtoPath(&pyproto_code_dir)) {
-    LOG(ERROR) << "Failed to get python dir for generated code.";
-    return false;
+    LOG(WARNING) << "Cannot find pyproto dir for generated code. "
+                 << "Testserver features that rely on it will not work";
+    return true;
   }
 
   AppendToPythonPath(pyproto_code_dir);
@@ -306,7 +308,31 @@
   return true;
 }
 
-FilePath TestServer::GetRootCertificatePath() {
+bool TestServer::ParseServerData(const std::string& server_data) {
+  VLOG(1) << "Server data: " << server_data;
+  base::JSONReader json_reader;
+  scoped_ptr<Value> value(json_reader.JsonToValue(server_data, true, false));
+  if (!value.get() ||
+      !value->IsType(Value::TYPE_DICTIONARY)) {
+    LOG(ERROR) << "Could not parse server data: "
+               << json_reader.GetErrorMessage();
+    return false;
+  }
+  server_data_.reset(static_cast<DictionaryValue*>(value.release()));
+  int port = 0;
+  if (!server_data_->GetInteger("port", &port)) {
+    LOG(ERROR) << "Could not find port value";
+    return false;
+  }
+  if ((port <= 0) || (port > kuint16max)) {
+    LOG(ERROR) << "Invalid port value: " << port;
+    return false;
+  }
+  host_port_pair_.set_port(port);
+  return true;
+}
+
+FilePath TestServer::GetRootCertificatePath() const {
   return certificates_dir_.AppendASCII("root_ca_cert.crt");
 }
 
@@ -319,6 +345,13 @@
   command_line->AppendSwitchASCII("port",
                                   base::IntToString(host_port_pair_.port()));
   command_line->AppendSwitchPath("data-dir", document_root_);
+  command_line->AppendSwitchPath("policy-cert-chain",
+                                 certificates_dir_.AppendASCII("ok_cert.pem"));
+  command_line->AppendSwitchPath("policy-cert-chain", GetRootCertificatePath());
+
+  if (logging::GetMinLogLevel() == logging::LOG_VERBOSE) {
+    command_line->AppendArg("--log-to-console");
+  }
 
   if (type_ == TYPE_FTP) {
     command_line->AppendArg("-f");
@@ -364,28 +397,4 @@
   return true;
 }
 
-bool TestServer::ParseServerData(const std::string& server_data) {
-  VLOG(1) << "Server data: " << server_data;
-  base::JSONReader json_reader;
-  scoped_ptr<Value> value(json_reader.JsonToValue(server_data, true, false));
-  if (!value.get() ||
-      !value->IsType(Value::TYPE_DICTIONARY)) {
-    LOG(ERROR) << "Could not parse server data: "
-               << json_reader.GetErrorMessage();
-    return false;
-  }
-  server_data_.reset(static_cast<DictionaryValue*>(value.release()));
-  int port = 0;
-  if (!server_data_->GetInteger("port", &port)) {
-    LOG(ERROR) << "Could not find port value";
-    return false;
-  }
-  if ((port <= 0) || (port > kuint16max)) {
-    LOG(ERROR) << "Invalid port value: " << port;
-    return false;
-  }
-  host_port_pair_.set_port(port);
-  return true;
-}
-
 }  // namespace net
diff --git a/net/test/test_server.h b/net/test/test_server.h
index 6d93fc8..03a4dfc 100644
--- a/net/test/test_server.h
+++ b/net/test/test_server.h
@@ -35,6 +35,8 @@
 // that can provide various responses useful for testing.
 class TestServer {
  public:
+  typedef std::pair<std::string, std::string> StringPair;
+
   enum Type {
     TYPE_FTP,
     TYPE_HTTP,
@@ -126,7 +128,6 @@
                                  const std::string& user,
                                  const std::string& password) const;
 
-  typedef std::pair<std::string, std::string> StringPair;
   static bool GetFilePathWithReplacements(
       const std::string& original_path,
       const std::vector<StringPair>& text_to_replace,
@@ -149,7 +150,7 @@
   bool ParseServerData(const std::string& server_data) WARN_UNUSED_RESULT;
 
   // Returns path to the root certificate.
-  FilePath GetRootCertificatePath();
+  FilePath GetRootCertificatePath() const;
 
   // Load the test root cert, if it hasn't been loaded yet.
   bool LoadTestRootCert() WARN_UNUSED_RESULT;
diff --git a/net/tools/dnssec_chain_verify/dnssec_chain_verify.cc b/net/tools/dnssec_chain_verify/dnssec_chain_verify.cc
index a1c5270..b27c375 100644
--- a/net/tools/dnssec_chain_verify/dnssec_chain_verify.cc
+++ b/net/tools/dnssec_chain_verify/dnssec_chain_verify.cc
@@ -4,6 +4,7 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "base/at_exit.h"
 #include "net/base/dns_util.h"
diff --git a/net/tools/dump_cache/cache_dumper.cc b/net/tools/dump_cache/cache_dumper.cc
index 9eee058..0335516 100644
--- a/net/tools/dump_cache/cache_dumper.cc
+++ b/net/tools/dump_cache/cache_dumper.cc
@@ -83,7 +83,7 @@
   // There is no way to prepend to a filename.  We simply *have*
   // to convert to a wstring to do this.
   std::wstring name = kLongFilenamePrefix;
-  name.append(entry_path_.ToWStringHack());
+  name.append(entry_path_.value());
   entry_path_ = FilePath(name);
 #endif
 
diff --git a/net/tools/dump_cache/dump_files.cc b/net/tools/dump_cache/dump_files.cc
index 2f37c5d..8f65df3 100644
--- a/net/tools/dump_cache/dump_files.cc
+++ b/net/tools/dump_cache/dump_files.cc
@@ -6,6 +6,7 @@
 // to the actual files (they still may change if an error is detected on the
 // files).
 
+#include <set>
 #include <stdio.h>
 #include <string>
 
@@ -67,6 +68,7 @@
   for (int i = 0; i < 5; i++) {
     printf("head %d: 0x%x\n", i, header.lru.heads[i]);
     printf("tail %d: 0x%x\n", i, header.lru.tails[i]);
+    printf("size %d: 0x%x\n", i, header.lru.sizes[i]);
   }
   printf("transaction: 0x%x\n", header.lru.transaction);
   printf("operation: %d\n", header.lru.operation);
@@ -131,6 +133,7 @@
   disk_cache::Index* index_;
   int current_hash_;
   disk_cache::CacheAddr next_addr_;
+  std::set<disk_cache::CacheAddr> dumped_entries_;
   DISALLOW_COPY_AND_ASSIGN(CacheDumper);
 };
 
@@ -154,17 +157,19 @@
 }
 
 bool CacheDumper::GetEntry(disk_cache::EntryStore* entry) {
+  if (dumped_entries_.find(next_addr_) != dumped_entries_.end()) {
+    printf("Loop detected\n");
+    next_addr_ = 0;
+    current_hash_++;
+  }
+
   if (next_addr_) {
-    if (LoadEntry(next_addr_, entry)) {
-      next_addr_ = entry->next;
-      if (!next_addr_)
-        current_hash_++;
+    if (LoadEntry(next_addr_, entry))
       return true;
-    } else {
-      printf("Unable to load entry at address 0x%x\n", next_addr_);
-      next_addr_ = 0;
-      current_hash_++;
-    }
+
+    printf("Unable to load entry at address 0x%x\n", next_addr_);
+    next_addr_ = 0;
+    current_hash_++;
   }
 
   for (int i = current_hash_; i < index_->header.table_len; i++) {
@@ -172,14 +177,10 @@
     // dumping every entry that we can find.
     if (index_->table[i]) {
       current_hash_ = i;
-      if (LoadEntry(index_->table[i], entry)) {
-        next_addr_ = entry->next;
-        if (!next_addr_)
-          current_hash_++;
+      if (LoadEntry(index_->table[i], entry))
         return true;
-      } else {
-        printf("Unable to load entry at address 0x%x\n", index_->table[i]);
-      }
+
+      printf("Unable to load entry at address 0x%x\n", index_->table[i]);
     }
   }
   return false;
@@ -198,6 +199,15 @@
 
   memcpy(entry, entry_block.Data(), sizeof(*entry));
   printf("Entry at 0x%x\n", addr);
+
+  // Prepare for the next entry to load.
+  next_addr_ = entry->next;
+  if (next_addr_) {
+    dumped_entries_.insert(addr);
+  } else {
+    current_hash_++;
+    dumped_entries_.clear();
+  }
   return true;
 }
 
@@ -283,10 +293,10 @@
 
   std::wstring pattern(kDataPrefix);
   pattern.append(L"*");
-  file_util::FileEnumerator iter(FilePath::FromWStringHack(input_path), false,
+  file_util::FileEnumerator iter(FilePath(input_path), false,
                                  file_util::FileEnumerator::FILES, pattern);
-  for (std::wstring file = iter.Next().ToWStringHack(); !file.empty();
-       file = iter.Next().ToWStringHack()) {
+  for (std::wstring file = iter.Next().value(); !file.empty();
+       file = iter.Next().value()) {
     DumpBlockHeader(file);
   }
 
diff --git a/net/tools/dump_cache/upgrade.cc b/net/tools/dump_cache/upgrade.cc
index 7b86237..6d79b73 100644
--- a/net/tools/dump_cache/upgrade.cc
+++ b/net/tools/dump_cache/upgrade.cc
@@ -12,6 +12,7 @@
 #include "base/win/scoped_handle.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/disk_cache/backend_impl.h"
 #include "net/disk_cache/entry_impl.h"
diff --git a/net/tools/dump_cache/url_to_filename_encoder.cc b/net/tools/dump_cache/url_to_filename_encoder.cc
index 84d79c7..4ca4a51 100644
--- a/net/tools/dump_cache/url_to_filename_encoder.cc
+++ b/net/tools/dump_cache/url_to_filename_encoder.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <stdlib.h>
+
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "net/base/net_util.h"
diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc
index 0d9682f..31e4001 100644
--- a/net/tools/fetch/fetch_client.cc
+++ b/net/tools/fetch/fetch_client.cc
@@ -20,10 +20,10 @@
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
 #include "net/http/http_request_info.h"
 #include "net/http/http_transaction.h"
 #include "net/proxy/proxy_service.h"
-#include "net/socket/client_socket_factory.h"
 
 void usage(const char* program_name) {
   printf("usage: %s --url=<url>  [--n=<clients>] [--stats] [--use_cache]\n",
@@ -149,24 +149,21 @@
   net::HttpTransactionFactory* factory = NULL;
   scoped_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory(
       net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
+
+  net::HttpNetworkSession::Params session_params;
+  session_params.host_resolver = host_resolver.get();
+  session_params.cert_verifier = cert_verifier.get();
+  session_params.proxy_service = proxy_service;
+  session_params.http_auth_handler_factory = http_auth_handler_factory.get();
+  session_params.ssl_config_service = ssl_config_service;
+
+  scoped_refptr<net::HttpNetworkSession> network_session(
+      new net::HttpNetworkSession(session_params));
   if (use_cache) {
-    factory = new net::HttpCache(host_resolver.get(), cert_verifier.get(),
-        NULL, NULL, proxy_service, ssl_config_service,
-        http_auth_handler_factory.get(), NULL, NULL,
-        net::HttpCache::DefaultBackend::InMemory(0));
+    factory = new net::HttpCache(network_session,
+                                 net::HttpCache::DefaultBackend::InMemory(0));
   } else {
-    factory = new net::HttpNetworkLayer(
-        net::ClientSocketFactory::GetDefaultFactory(),
-        host_resolver.get(),
-        cert_verifier.get(),
-        NULL /* dnsrr_resolver */,
-        NULL /* dns_cert_checker */,
-        NULL /* ssl_host_info_factory */,
-        proxy_service,
-        ssl_config_service,
-        http_auth_handler_factory.get(),
-        NULL,
-        NULL);
+    factory = new net::HttpNetworkLayer(network_session);
   }
 
   {
diff --git a/net/tools/fetch/http_listen_socket.cc b/net/tools/fetch/http_listen_socket.cc
index 0db714f..78d924d 100644
--- a/net/tools/fetch/http_listen_socket.cc
+++ b/net/tools/fetch/http_listen_socket.cc
@@ -24,6 +24,10 @@
 HttpListenSocket::~HttpListenSocket() {
 }
 
+void HttpListenSocket::Listen() {
+  ListenSocket::Listen();
+}
+
 void HttpListenSocket::Accept() {
   SOCKET conn = ListenSocket::Accept(socket_);
   DCHECK_NE(conn, ListenSocket::kInvalidSocket);
diff --git a/net/tools/fetch/http_listen_socket.h b/net/tools/fetch/http_listen_socket.h
index 781ac32..82f5312 100644
--- a/net/tools/fetch/http_listen_socket.h
+++ b/net/tools/fetch/http_listen_socket.h
@@ -28,7 +28,7 @@
   static HttpListenSocket* Listen(const std::string& ip, int port,
                                   HttpListenSocket::Delegate* delegate);
 
-  void Listen() { ListenSocket::Listen(); }
+  virtual void Listen();
   virtual void Accept();
 
   // Send a server response.
diff --git a/net/tools/fetch/http_server_request_info.h b/net/tools/fetch/http_server_request_info.h
index 2b7cfb5..9a94dcd 100644
--- a/net/tools/fetch/http_server_request_info.h
+++ b/net/tools/fetch/http_server_request_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,7 +17,8 @@
 // does).
 class HttpServerRequestInfo : public net::HttpRequestInfo {
  public:
-  HttpServerRequestInfo() : net::HttpRequestInfo() {}
+  HttpServerRequestInfo();
+  virtual ~HttpServerRequestInfo();
 
   // A map of the names -> values for HTTP headers.
   std::map<std::string, std::string> headers;
diff --git a/net/tools/fetch/http_server_response_info.h b/net/tools/fetch/http_server_response_info.h
index 7a8bb1f..d0ef863 100644
--- a/net/tools/fetch/http_server_response_info.h
+++ b/net/tools/fetch/http_server_response_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,9 +12,8 @@
 // Meta information about a server response.
 class HttpServerResponseInfo {
  public:
-  HttpServerResponseInfo()
-      : status(200), content_length(0), connection_close(false) {
-  }
+  HttpServerResponseInfo();
+  ~HttpServerResponseInfo();
 
   // The response protocol.
   std::string protocol;
diff --git a/net/tools/flip_server/balsa_frame.cc b/net/tools/flip_server/balsa_frame.cc
index 9b8173e..6a46685 100644
--- a/net/tools/flip_server/balsa_frame.cc
+++ b/net/tools/flip_server/balsa_frame.cc
@@ -33,6 +33,29 @@
 static const char kTransferEncoding[] = "transfer-encoding";
 static const size_t kTransferEncodingSize = sizeof(kTransferEncoding) - 1;
 
+BalsaFrame::BalsaFrame()
+    : last_char_was_slash_r_(false),
+      saw_non_newline_char_(false),
+      start_was_space_(true),
+      chunk_length_character_extracted_(false),
+      is_request_(true),
+      request_was_head_(false),
+      max_header_length_(16 * 1024),
+      max_request_uri_length_(2048),
+      visitor_(&do_nothing_visitor_),
+      chunk_length_remaining_(0),
+      content_length_remaining_(0),
+      last_slash_n_loc_(NULL),
+      last_recorded_slash_n_loc_(NULL),
+      last_slash_n_idx_(0),
+      term_chars_(0),
+      parse_state_(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE),
+      last_error_(BalsaFrameEnums::NO_ERROR),
+      headers_(NULL) {
+}
+
+BalsaFrame::~BalsaFrame() {}
+
 void BalsaFrame::Reset() {
   last_char_was_slash_r_ = false;
   saw_non_newline_char_ = false;
@@ -1259,7 +1282,7 @@
     // header_length_after equals max_header_length_ and we are still in the
     // parse_state_  BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE we know for
     // sure that the headers limit will be crossed later on
-    if ((parse_state_ == BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE)) {
+    if (parse_state_ == BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE) {
       // Note that headers_ is valid only if we are still reading headers.
       const size_t header_length_after =
           headers_->GetReadableBytesFromHeaderStream();
diff --git a/net/tools/flip_server/balsa_frame.h b/net/tools/flip_server/balsa_frame.h
index 6c0b1d0..74ff7bc 100644
--- a/net/tools/flip_server/balsa_frame.h
+++ b/net/tools/flip_server/balsa_frame.h
@@ -47,27 +47,8 @@
                                          '\n';
   static const uint32 kValidTerm2Mask = 0xFF << 8 |
                                         0xFF;
-  BalsaFrame() :
-      last_char_was_slash_r_(false),
-      saw_non_newline_char_(false),
-      start_was_space_(true),
-      chunk_length_character_extracted_(false),
-      is_request_(true),
-      request_was_head_(false),
-      max_header_length_(16 * 1024),
-      max_request_uri_length_(2048),
-      visitor_(&do_nothing_visitor_),
-      chunk_length_remaining_(0),
-      content_length_remaining_(0),
-      last_slash_n_loc_(NULL),
-      last_recorded_slash_n_loc_(NULL),
-      last_slash_n_idx_(0),
-      term_chars_(0),
-      parse_state_(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE),
-      last_error_(BalsaFrameEnums::NO_ERROR),
-      headers_(NULL) {}
-
-  ~BalsaFrame() {}
+  BalsaFrame();
+  ~BalsaFrame();
 
   // Reset reinitializes all the member variables of the framer and clears the
   // attached header object (but doesn't change the pointer value headers_).
diff --git a/net/tools/flip_server/balsa_headers.cc b/net/tools/flip_server/balsa_headers.cc
index 74364a2..80a68fa 100644
--- a/net/tools/flip_server/balsa_headers.cc
+++ b/net/tools/flip_server/balsa_headers.cc
@@ -76,6 +76,175 @@
    return os;
  }
 
+BalsaBuffer::~BalsaBuffer() {
+  CleanupBlocksStartingFrom(0);
+}
+
+// Returns the total amount of memory used by the buffer blocks.
+size_t BalsaBuffer::GetTotalBufferBlockSize() const {
+  size_t buffer_size = 0;
+  for (Blocks::const_iterator iter = blocks_.begin();
+       iter != blocks_.end();
+       ++iter) {
+    buffer_size += iter->buffer_size;
+  }
+  return buffer_size;
+}
+
+void BalsaBuffer::WriteToContiguousBuffer(const base::StringPiece& sp) {
+  if (sp.empty()) {
+    return;
+  }
+  CHECK(can_write_to_contiguous_buffer_);
+  DCHECK_GE(blocks_.size(), 1u);
+  if (blocks_[0].buffer == NULL && sp.size() <= blocksize_) {
+    blocks_[0] = AllocBlock();
+    memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
+  } else if (blocks_[0].bytes_free < sp.size()) {
+    // the first block isn't big enough, resize it.
+    const size_t old_storage_size_used = blocks_[0].bytes_used();
+    const size_t new_storage_size = old_storage_size_used + sp.size();
+    char* new_storage = new char[new_storage_size];
+    char* old_storage = blocks_[0].buffer;
+    if (old_storage_size_used) {
+      memcpy(new_storage, old_storage, old_storage_size_used);
+    }
+    memcpy(new_storage + old_storage_size_used, sp.data(), sp.size());
+    blocks_[0].buffer = new_storage;
+    blocks_[0].bytes_free = sp.size();
+    blocks_[0].buffer_size = new_storage_size;
+    delete[] old_storage;
+  } else {
+    memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
+  }
+  blocks_[0].bytes_free -= sp.size();
+}
+
+base::StringPiece BalsaBuffer::Write(const base::StringPiece& sp,
+                                     Blocks::size_type* block_buffer_idx) {
+  if (sp.empty()) {
+    return sp;
+  }
+  char* storage = Reserve(sp.size(), block_buffer_idx);
+  memcpy(storage, sp.data(), sp.size());
+  return base::StringPiece(storage, sp.size());
+}
+
+char* BalsaBuffer::Reserve(size_t size,
+                           Blocks::size_type* block_buffer_idx) {
+  // There should always be a 'first_block', even if it
+  // contains nothing.
+  DCHECK_GE(blocks_.size(), 1u);
+  BufferBlock* block = NULL;
+  Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
+  for (; block_idx < blocks_.size(); ++block_idx) {
+    if (blocks_[block_idx].bytes_free >= size) {
+      block = &blocks_[block_idx];
+      break;
+    }
+  }
+  if (block == NULL) {
+    if (blocksize_ < size) {
+      blocks_.push_back(AllocCustomBlock(size));
+    } else {
+      blocks_.push_back(AllocBlock());
+    }
+    block = &blocks_.back();
+  }
+
+  char* storage = block->start_of_unused_bytes();
+  block->bytes_free -= size;
+  if (block_buffer_idx) {
+    *block_buffer_idx = block_idx;
+  }
+  return storage;
+}
+
+void BalsaBuffer::Clear() {
+  CHECK(!blocks_.empty());
+  if (blocksize_ == blocks_[0].buffer_size) {
+    CleanupBlocksStartingFrom(1);
+    blocks_[0].bytes_free = blocks_[0].buffer_size;
+  } else {
+    CleanupBlocksStartingFrom(0);
+    blocks_.push_back(AllocBlock());
+  }
+  DCHECK_GE(blocks_.size(), 1u);
+  can_write_to_contiguous_buffer_ = true;
+}
+
+void BalsaBuffer::Swap(BalsaBuffer* b) {
+  blocks_.swap(b->blocks_);
+  std::swap(can_write_to_contiguous_buffer_,
+            b->can_write_to_contiguous_buffer_);
+  std::swap(blocksize_, b->blocksize_);
+}
+
+void BalsaBuffer::CopyFrom(const BalsaBuffer& b) {
+  CleanupBlocksStartingFrom(0);
+  blocks_.resize(b.blocks_.size());
+  for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
+    blocks_[i] = CopyBlock(b.blocks_[i]);
+  }
+  blocksize_ = b.blocksize_;
+  can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
+}
+
+BalsaBuffer::BalsaBuffer()
+    : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {
+  blocks_.push_back(AllocBlock());
+}
+
+BalsaBuffer::BalsaBuffer(size_t blocksize) :
+    blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {
+  blocks_.push_back(AllocBlock());
+}
+
+BalsaBuffer::BufferBlock BalsaBuffer::AllocBlock() {
+  return AllocCustomBlock(blocksize_);
+}
+
+BalsaBuffer::BufferBlock BalsaBuffer::AllocCustomBlock(size_t blocksize) {
+  return BufferBlock(new char[blocksize], blocksize, blocksize);
+}
+
+BalsaBuffer::BufferBlock BalsaBuffer::CopyBlock(const BufferBlock& b) {
+  BufferBlock block = b;
+  if (b.buffer == NULL) {
+    return block;
+  }
+
+  block.buffer = new char[b.buffer_size];
+  memcpy(block.buffer, b.buffer, b.bytes_used());
+  return block;
+}
+
+void BalsaBuffer::CleanupBlocksStartingFrom(Blocks::size_type start_idx) {
+  for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) {
+    delete[] blocks_[i].buffer;
+  }
+  blocks_.resize(start_idx);
+}
+
+BalsaHeaders::BalsaHeaders()
+    : balsa_buffer_(4096),
+      content_length_(0),
+      content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
+      parsed_response_code_(0),
+      firstline_buffer_base_idx_(0),
+      whitespace_1_idx_(0),
+      non_whitespace_1_idx_(0),
+      whitespace_2_idx_(0),
+      non_whitespace_2_idx_(0),
+      whitespace_3_idx_(0),
+      non_whitespace_3_idx_(0),
+      whitespace_4_idx_(0),
+      end_of_firstline_idx_(0),
+      transfer_encoding_is_chunked_(false) {
+}
+
+BalsaHeaders::~BalsaHeaders() {}
+
 void BalsaHeaders::Clear() {
   balsa_buffer_.Clear();
   transfer_encoding_is_chunked_ = false;
diff --git a/net/tools/flip_server/balsa_headers.h b/net/tools/flip_server/balsa_headers.h
index b51b7f4..f2b7612 100644
--- a/net/tools/flip_server/balsa_headers.h
+++ b/net/tools/flip_server/balsa_headers.h
@@ -96,20 +96,10 @@
 
   typedef std::vector<BufferBlock> Blocks;
 
-  ~BalsaBuffer() {
-    CleanupBlocksStartingFrom(0);
-  }
+  ~BalsaBuffer();
 
   // Returns the total amount of memory used by the buffer blocks.
-  size_t GetTotalBufferBlockSize() const {
-    size_t buffer_size = 0;
-    for (Blocks::const_iterator iter = blocks_.begin();
-         iter != blocks_.end();
-         ++iter) {
-      buffer_size += iter->buffer_size;
-    }
-    return buffer_size;
-  }
+  size_t GetTotalBufferBlockSize() const;
 
   const char* GetPtr(Blocks::size_type block_idx) const {
     DCHECK_LT(block_idx, blocks_.size())
@@ -144,34 +134,7 @@
   // for reasons of efficiency, requires that the buffer from which it parses
   // the headers be contiguous.
   //
-  void WriteToContiguousBuffer(const base::StringPiece& sp) {
-    if (sp.empty()) {
-      return;
-    }
-    CHECK(can_write_to_contiguous_buffer_);
-    DCHECK_GE(blocks_.size(), 1u);
-    if (blocks_[0].buffer == NULL && sp.size() <= blocksize_) {
-      blocks_[0] = AllocBlock();
-      memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
-    } else if (blocks_[0].bytes_free < sp.size()) {
-      // the first block isn't big enough, resize it.
-      const size_t old_storage_size_used = blocks_[0].bytes_used();
-      const size_t new_storage_size = old_storage_size_used + sp.size();
-      char* new_storage = new char[new_storage_size];
-      char* old_storage = blocks_[0].buffer;
-      if (old_storage_size_used) {
-        memcpy(new_storage, old_storage, old_storage_size_used);
-      }
-      memcpy(new_storage + old_storage_size_used, sp.data(), sp.size());
-      blocks_[0].buffer = new_storage;
-      blocks_[0].bytes_free = sp.size();
-      blocks_[0].buffer_size = new_storage_size;
-      delete[] old_storage;
-    } else {
-      memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
-    }
-    blocks_[0].bytes_free -= sp.size();
-  }
+  void WriteToContiguousBuffer(const base::StringPiece& sp);
 
   void NoMoreWriteToContiguousBuffer() {
     can_write_to_contiguous_buffer_ = false;
@@ -184,79 +147,20 @@
   // the first block IFF the NoMoreWriteToContiguousBuffer function has
   // been called since the last Clear/Construction.
   base::StringPiece Write(const base::StringPiece& sp,
-                    Blocks::size_type* block_buffer_idx) {
-    if (sp.empty()) {
-      return sp;
-    }
-    char* storage = Reserve(sp.size(), block_buffer_idx);
-    memcpy(storage, sp.data(), sp.size());
-    return base::StringPiece(storage, sp.size());
-  }
+                          Blocks::size_type* block_buffer_idx);
 
   // Reserves "permanent" storage of the size indicated. Returns a pointer to
   // the beginning of that storage, and assigns the index of the block used to
   // block_buffer_idx. This function uses the first block IFF the
   // NoMoreWriteToContiguousBuffer function has been called since the last
   // Clear/Construction.
-  char* Reserve(size_t size,
-                Blocks::size_type* block_buffer_idx) {
-    // There should always be a 'first_block', even if it
-    // contains nothing.
-    DCHECK_GE(blocks_.size(), 1u);
-    BufferBlock* block = NULL;
-    Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
-    for (; block_idx < blocks_.size(); ++block_idx) {
-      if (blocks_[block_idx].bytes_free >= size) {
-        block = &blocks_[block_idx];
-        break;
-      }
-    }
-    if (block == NULL) {
-      if (blocksize_ < size) {
-        blocks_.push_back(AllocCustomBlock(size));
-      } else {
-        blocks_.push_back(AllocBlock());
-      }
-      block = &blocks_.back();
-    }
+  char* Reserve(size_t size, Blocks::size_type* block_buffer_idx);
 
-    char* storage = block->start_of_unused_bytes();
-    block->bytes_free -= size;
-    if (block_buffer_idx) {
-      *block_buffer_idx = block_idx;
-    }
-    return storage;
-  }
+  void Clear();
 
-  void Clear() {
-    CHECK(!blocks_.empty());
-    if (blocksize_ == blocks_[0].buffer_size) {
-      CleanupBlocksStartingFrom(1);
-      blocks_[0].bytes_free = blocks_[0].buffer_size;
-    } else {
-      CleanupBlocksStartingFrom(0);
-      blocks_.push_back(AllocBlock());
-    }
-    DCHECK_GE(blocks_.size(), 1u);
-    can_write_to_contiguous_buffer_ = true;
-  }
+  void Swap(BalsaBuffer* b);
 
-  void Swap(BalsaBuffer* b) {
-    blocks_.swap(b->blocks_);
-    std::swap(can_write_to_contiguous_buffer_,
-              b->can_write_to_contiguous_buffer_);
-    std::swap(blocksize_, b->blocksize_);
-  }
-
-  void CopyFrom(const BalsaBuffer& b) {
-    CleanupBlocksStartingFrom(0);
-    blocks_.resize(b.blocks_.size());
-    for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
-      blocks_[i] = CopyBlock(b.blocks_[i]);
-    }
-    blocksize_ = b.blocksize_;
-    can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
-  }
+  void CopyFrom(const BalsaBuffer& b);
 
   const char* StartOfFirstBlock() const {
     return blocks_[0].buffer;
@@ -275,44 +179,20 @@
   size_t bytes_used(size_t idx) const { return blocks_[idx].bytes_used(); }
 
  protected:
-  BalsaBuffer() :
-      blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {
-    blocks_.push_back(AllocBlock());
-  }
+  BalsaBuffer();
 
-  explicit BalsaBuffer(size_t blocksize) :
-      blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {
-    blocks_.push_back(AllocBlock());
-  }
+  explicit BalsaBuffer(size_t blocksize);
 
-  BufferBlock AllocBlock() {
-    return AllocCustomBlock(blocksize_);
-  }
+  BufferBlock AllocBlock();
 
-  BufferBlock AllocCustomBlock(size_t blocksize) {
-    return BufferBlock(new char[blocksize], blocksize, blocksize);
-  }
+  BufferBlock AllocCustomBlock(size_t blocksize);
 
-  BufferBlock CopyBlock(const BufferBlock& b) {
-    BufferBlock block = b;
-    if (b.buffer == NULL) {
-      return block;
-    }
-
-    block.buffer = new char[b.buffer_size];
-    memcpy(block.buffer, b.buffer, b.bytes_used());
-    return block;
-  }
+  BufferBlock CopyBlock(const BufferBlock& b);
 
   // Cleans up the object.
   // The block at start_idx, and all subsequent blocks
   // will be cleared and have associated memory deleted.
-  void CleanupBlocksStartingFrom(Blocks::size_type start_idx) {
-    for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) {
-      delete[] blocks_[i].buffer;
-    }
-    blocks_.resize(start_idx);
-  }
+  void CleanupBlocksStartingFrom(Blocks::size_type start_idx);
 
   // A container of BufferBlocks
   Blocks blocks_;
@@ -696,21 +576,8 @@
   // TODO(fenix): Revisit the amount of bytes initially allocated to the second
   // block of the balsa_buffer_. It may make sense to pre-allocate some amount
   // (roughly the amount we'd append in new headers such as X-User-Ip, etc.)
-  BalsaHeaders() :
-      balsa_buffer_(4096),
-      content_length_(0),
-      content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
-      parsed_response_code_(0),
-      firstline_buffer_base_idx_(0),
-      whitespace_1_idx_(0),
-      non_whitespace_1_idx_(0),
-      whitespace_2_idx_(0),
-      non_whitespace_2_idx_(0),
-      whitespace_3_idx_(0),
-      non_whitespace_3_idx_(0),
-      whitespace_4_idx_(0),
-      end_of_firstline_idx_(0),
-      transfer_encoding_is_chunked_(false) { }
+  BalsaHeaders();
+  ~BalsaHeaders();
 
   const_header_lines_iterator header_lines_begin() {
     return HeaderLinesBeginHelper<const_header_lines_iterator>();
diff --git a/net/tools/flip_server/create_listener.cc b/net/tools/flip_server/create_listener.cc
index 59a03a6..4676912 100644
--- a/net/tools/flip_server/create_listener.cc
+++ b/net/tools/flip_server/create_listener.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/tools/flip_server/create_listener.h"
+
 #include <arpa/inet.h>   // for inet_ntop
 #include <errno.h>       // for strerror
 #include <netdb.h>       // for getaddrinfo and getnameinfo
@@ -14,8 +16,6 @@
 #include <unistd.h>      // for exit()
 #include <ostream>
 
-#include "net/tools/flip_server/create_listener.h"
-
 #include "base/logging.h"
 
 namespace net {
diff --git a/net/tools/flip_server/epoll_server.cc b/net/tools/flip_server/epoll_server.cc
index f78663c..e8219b0 100644
--- a/net/tools/flip_server/epoll_server.cc
+++ b/net/tools/flip_server/epoll_server.cc
@@ -221,6 +221,10 @@
   cb->OnRegistration(this, fd, event_mask);
 }
 
+int EpollServer::GetFlags(int fd) {
+  return fcntl(fd, F_GETFL, 0);
+}
+
 void EpollServer::SetNonblocking(int fd) {
   int flags = GetFlags(fd);
   if (flags == -1) {
@@ -244,6 +248,13 @@
   }
 }
 
+int EpollServer::epoll_wait_impl(int epfd,
+                                 struct epoll_event* events,
+                                 int max_events,
+                                 int timeout_in_ms) {
+  return epoll_wait(epfd, events, max_events, timeout_in_ms);
+}
+
 void EpollServer::RegisterFDForWrite(int fd, CB* cb) {
   RegisterFD(fd, cb, EPOLLOUT);
 }
@@ -485,6 +496,13 @@
   return base::Time::Now().ToInternalValue();
 }
 
+int64 EpollServer::ApproximateNowInUsec() const {
+  if (recorded_now_in_us_ != 0) {
+    return recorded_now_in_us_;
+  }
+  return this->NowInUsec();
+}
+
 std::string EpollServer::EventMaskToString(int event_mask) {
   std::string s;
   if (event_mask & EPOLLIN) s += "EPOLLIN ";
diff --git a/net/tools/flip_server/epoll_server.h b/net/tools/flip_server/epoll_server.h
index bbcb188..c50afae 100644
--- a/net/tools/flip_server/epoll_server.h
+++ b/net/tools/flip_server/epoll_server.h
@@ -440,12 +440,7 @@
   // Returns:
   //   the "approximate" current time as number of microseconds since the Unix
   //   epoch.
-  virtual int64 ApproximateNowInUsec() const {
-    if (recorded_now_in_us_ != 0) {
-      return recorded_now_in_us_;
-    }
-    return this->NowInUsec();
-  }
+  virtual int64 ApproximateNowInUsec() const;
 
   static std::string EventMaskToString(int event_mask);
 
@@ -497,22 +492,19 @@
   static const int kMinimumEffectiveAlarmQuantum;
  protected:
 
-  // These have to be in the .h file so that we can override them in tests.
-  virtual inline int GetFlags(int fd) { return fcntl(fd, F_GETFL, 0); }
+  virtual int GetFlags(int fd);
   inline int SetFlags(int fd, int flags) {
     return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
   }
 
-  virtual void SetNonblocking (int fd);
+  virtual void SetNonblocking(int fd);
 
   // This exists here so that we can override this function in unittests
   // in order to make effective mock EpollServer objects.
   virtual int epoll_wait_impl(int epfd,
                               struct epoll_event* events,
                               int max_events,
-                              int timeout_in_ms) {
-    return epoll_wait(epfd, events, max_events, timeout_in_ms);
-  }
+                              int timeout_in_ms);
 
   // this struct is used internally, and is never used by anything external
   // to this class. Some of its members are declared mutable to get around the
diff --git a/net/tools/flip_server/flip_config.h b/net/tools/flip_server/flip_config.h
index fdf0f46..3c5b920 100644
--- a/net/tools/flip_server/flip_config.h
+++ b/net/tools/flip_server/flip_config.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,14 +8,13 @@
 
 #include <arpa/inet.h>  // in_addr_t
 
+#include <string>
+#include <vector>
+
 #include "base/logging.h"
 #include "net/tools/flip_server/create_listener.h"
 
-#include <vector>
-#include <string>
-
-using std::string;
-using std::vector;
+namespace net {
 
 enum FlipHandlerType {
     FLIP_HANDLER_PROXY,
@@ -24,165 +23,78 @@
 };
 
 class FlipAcceptor {
-public:
-   enum FlipHandlerType flip_handler_type_;
-   string listen_ip_;
-   string listen_port_;
-   string ssl_cert_filename_;
-   string ssl_key_filename_;
-   string http_server_ip_;
-   string http_server_port_;
-   string https_server_ip_;
-   string https_server_port_;
-   int spdy_only_;
-   int accept_backlog_size_;
-   bool disable_nagle_;
-   int accepts_per_wake_;
-   int listen_fd_;
-   void* memory_cache_;
+ public:
+  FlipAcceptor(enum FlipHandlerType flip_handler_type,
+               std::string listen_ip,
+               std::string listen_port,
+               std::string ssl_cert_filename,
+               std::string ssl_key_filename,
+               std::string http_server_ip,
+               std::string http_server_port,
+               std::string https_server_ip,
+               std::string https_server_port,
+               int spdy_only,
+               int accept_backlog_size,
+               bool disable_nagle,
+               int accepts_per_wake,
+               bool reuseport,
+               bool wait_for_iface,
+               void *memory_cache);
+  ~FlipAcceptor();
 
-   FlipAcceptor(enum FlipHandlerType flip_handler_type,
-                string listen_ip,
-                string listen_port,
-                string ssl_cert_filename,
-                string ssl_key_filename,
-                string http_server_ip,
-                string http_server_port,
-                string https_server_ip,
-                string https_server_port,
-                int spdy_only,
-                int accept_backlog_size,
-                bool disable_nagle,
-                int accepts_per_wake,
-                bool reuseport,
-                bool wait_for_iface,
-                void *memory_cache) :
-       flip_handler_type_(flip_handler_type),
-       listen_ip_(listen_ip),
-       listen_port_(listen_port),
-       ssl_cert_filename_(ssl_cert_filename),
-       ssl_key_filename_(ssl_key_filename),
-       http_server_ip_(http_server_ip),
-       http_server_port_(http_server_port),
-       https_server_ip_(https_server_ip),
-       https_server_port_(https_server_port),
-       spdy_only_(spdy_only),
-       accept_backlog_size_(accept_backlog_size),
-       disable_nagle_(disable_nagle),
-       accepts_per_wake_(accepts_per_wake),
-       memory_cache_(memory_cache)
-   {
-     VLOG(1) << "Attempting to listen on " << listen_ip_.c_str() << ":"
-             << listen_port_.c_str();
-     if (!https_server_ip_.size())
-       https_server_ip_ = http_server_ip_;
-     if (!https_server_port_.size())
-       https_server_port_ = http_server_port_;
-
-     while (1) {
-       int ret = net::CreateListeningSocket(listen_ip_,
-                                            listen_port_,
-                                            true,
-                                            accept_backlog_size_,
-                                            true,
-                                            reuseport,
-                                            wait_for_iface,
-                                            disable_nagle_,
-                                            &listen_fd_);
-       if ( ret == 0 ) {
-         break;
-       } else if ( ret == -3 && wait_for_iface ) {
-         // Binding error EADDRNOTAVAIL was encounted. We need
-         // to wait for the interfaces to raised. try again.
-         usleep(200000);
-       } else {
-         LOG(ERROR) << "Unable to create listening socket for: ret = " << ret
-                    << ": " << listen_ip_.c_str() << ":"
-                    << listen_port_.c_str();
-         return;
-       }
-     }
-     net::SetNonBlocking(listen_fd_);
-     VLOG(1) << "Listening on socket: ";
-     if (flip_handler_type == FLIP_HANDLER_PROXY)
-       VLOG(1) << "\tType         : Proxy";
-     else if (FLIP_HANDLER_SPDY_SERVER)
-       VLOG(1) << "\tType         : SPDY Server";
-     else if (FLIP_HANDLER_HTTP_SERVER)
-       VLOG(1) << "\tType         : HTTP Server";
-     VLOG(1) << "\tIP           : " << listen_ip_;
-     VLOG(1) << "\tPort         : " << listen_port_;
-     VLOG(1) << "\tHTTP Server  : " << http_server_ip_ << ":"
-             << http_server_port_;
-     VLOG(1) << "\tHTTPS Server : " << https_server_ip_ << ":"
-             << https_server_port_;
-     VLOG(1) << "\tSSL          : "
-             << (ssl_cert_filename.size()?"true":"false");
-     VLOG(1) << "\tCertificate  : " << ssl_cert_filename;
-     VLOG(1) << "\tKey          : " << ssl_key_filename;
-     VLOG(1) << "\tSpdy Only    : " << (spdy_only?"true":"flase");
-   }
-   ~FlipAcceptor () {}
+  enum FlipHandlerType flip_handler_type_;
+  std::string listen_ip_;
+  std::string listen_port_;
+  std::string ssl_cert_filename_;
+  std::string ssl_key_filename_;
+  std::string http_server_ip_;
+  std::string http_server_port_;
+  std::string https_server_ip_;
+  std::string https_server_port_;
+  int spdy_only_;
+  int accept_backlog_size_;
+  bool disable_nagle_;
+  int accepts_per_wake_;
+  int listen_fd_;
+  void* memory_cache_;
+  int ssl_session_expiry_;
+  bool ssl_disable_compression_;
+  int idle_socket_timeout_s_;
 };
 
 class FlipConfig {
-public:
-   std::vector <FlipAcceptor*> acceptors_;
-   double server_think_time_in_s_;
-   enum logging::LoggingDestination log_destination_;
-   string log_filename_;
-   bool forward_ip_header_enabled_;
-   string forward_ip_header_;
-   bool wait_for_iface_;
-   int ssl_session_expiry_;
-   bool ssl_disable_compression_;
+ public:
+  FlipConfig();
+  ~FlipConfig();
 
-   FlipConfig() :
-       server_think_time_in_s_(0),
-       log_destination_(logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG),
-       forward_ip_header_enabled_(false),
-       wait_for_iface_(false),
-       ssl_session_expiry_(300),
-       ssl_disable_compression_(false)
-       {}
+  void AddAcceptor(enum FlipHandlerType flip_handler_type,
+                   std::string listen_ip,
+                   std::string listen_port,
+                   std::string ssl_cert_filename,
+                   std::string ssl_key_filename,
+                   std::string http_server_ip,
+                   std::string http_server_port,
+                   std::string https_server_ip,
+                   std::string https_server_port,
+                   int spdy_only,
+                   int accept_backlog_size,
+                   bool disable_nagle,
+                   int accepts_per_wake,
+                   bool reuseport,
+                   bool wait_for_iface,
+                   void *memory_cache);
 
-   ~FlipConfig() {}
-
-   void AddAcceptor(enum FlipHandlerType flip_handler_type,
-                    string listen_ip,
-                    string listen_port,
-                    string ssl_cert_filename,
-                    string ssl_key_filename,
-                    string http_server_ip,
-                    string http_server_port,
-                    string https_server_ip,
-                    string https_server_port,
-                    int spdy_only,
-                    int accept_backlog_size,
-                    bool disable_nagle,
-                    int accepts_per_wake,
-                    bool reuseport,
-                    bool wait_for_iface,
-                    void *memory_cache) {
-       // TODO(mbelshe): create a struct FlipConfigArgs{} for the arguments.
-       acceptors_.push_back(new FlipAcceptor(flip_handler_type,
-                                             listen_ip,
-                                             listen_port,
-                                             ssl_cert_filename,
-                                             ssl_key_filename,
-                                             http_server_ip,
-                                             http_server_port,
-                                             https_server_ip,
-                                             https_server_port,
-                                             spdy_only,
-                                             accept_backlog_size,
-                                             disable_nagle,
-                                             accepts_per_wake,
-                                             reuseport,
-                                             wait_for_iface,
-                                             memory_cache));
-   }
-
+  std::vector<FlipAcceptor*> acceptors_;
+  double server_think_time_in_s_;
+  enum logging::LoggingDestination log_destination_;
+  std::string log_filename_;
+  bool wait_for_iface_;
+  int ssl_session_expiry_;
+  bool ssl_disable_compression_;
+  int idle_socket_timeout_s_;
 };
 
-#endif
+}  // namespace
+
+#endif  // NET_TOOLS_FLIP_PROXY_CONFIG_H
+
diff --git a/net/tools/flip_server/flip_in_mem_edsm_server.cc b/net/tools/flip_server/flip_in_mem_edsm_server.cc
index a378e72..ef27afa 100644
--- a/net/tools/flip_server/flip_in_mem_edsm_server.cc
+++ b/net/tools/flip_server/flip_in_mem_edsm_server.cc
@@ -2,64 +2,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <dirent.h>
-#include <netinet/tcp.h>  // For TCP_NODELAY
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <openssl/err.h>
-#include <openssl/ssl.h>
+#include <errno.h>
 #include <signal.h>
+#include <sys/file.h>
 
-#include <deque>
 #include <iostream>
-#include <limits>
+#include <string>
 #include <vector>
-#include <list>
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/threading/simple_thread.h"
+#include "base/synchronization/lock.h"
 #include "base/timer.h"
-#include "base/lock.h"
-#include "net/spdy/spdy_frame_builder.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "net/tools/dump_cache/url_to_filename_encoder.h"
-#include "net/tools/dump_cache/url_utilities.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_frame.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
-#include "net/tools/flip_server/buffer_interface.h"
-#include "net/tools/flip_server/epoll_server.h"
-#include "net/tools/flip_server/ring_buffer.h"
-#include "net/tools/flip_server/simple_buffer.h"
-#include "net/tools/flip_server/split.h"
+#include "net/tools/flip_server/acceptor_thread.h"
+#include "net/tools/flip_server/constants.h"
 #include "net/tools/flip_server/flip_config.h"
+#include "net/tools/flip_server/output_ordering.h"
+#include "net/tools/flip_server/sm_connection.h"
+#include "net/tools/flip_server/sm_interface.h"
+#include "net/tools/flip_server/spdy_interface.h"
+#include "net/tools/flip_server/split.h"
 
-////////////////////////////////////////////////////////////////////////////////
-
-using std::deque;
-using std::list;
-using std::map;
-using std::ostream;
-using std::pair;
-using std::string;
-using std::vector;
 using std::cout;
-
-////////////////////////////////////////////////////////////////////////////////
-
-#define IPV4_PRINTABLE_FORMAT(IP) (((IP)>>0)&0xff),(((IP)>>8)&0xff), \
-                                 (((IP)>>16)&0xff),(((IP)>>24)&0xff)
-
-#define ACCEPTOR_CLIENT_IDENT acceptor_->listen_ip_ << ":" \
-                               << acceptor_->listen_port_ << " "
-
-#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0"
-
-#define SSL_CTX_DEFAULT_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
+using std::cerr;
 
 // If true, then disables the nagle algorithm);
 bool FLAGS_disable_nagle = true;
@@ -73,2848 +38,20 @@
 // The size of the TCP accept backlog);
 int32 FLAGS_accept_backlog_size = 1024;
 
-// The directory where cache locates);
-string FLAGS_cache_base_dir = ".";
-
-// If true, then encode url to filename);
-bool FLAGS_need_to_encode_url = false;
-
 // If set to false a single socket will be used. If set to true
 //  then a new socket will be created for each accept thread.
 //  Note that this only works with kernels that support
 //  SO_REUSEPORT);
 bool FLAGS_reuseport = false;
 
+// Flag to force spdy, even if NPN is not negotiated.
+bool FLAGS_force_spdy = false;
+
 // The amount of time the server delays before sending back the
 //  reply);
 double FLAGS_server_think_time_in_s = 0;
 
-// Does the server send X-Subresource headers);
-bool FLAGS_use_xsub = false;
-
-// Does the server send X-Associated-Content headers);
-bool FLAGS_use_xac = false;
-
-// Does the server compress data frames);
-bool FLAGS_use_compression = false;
-
-////////////////////////////////////////////////////////////////////////////////
-
-using base::StringPiece;
-using base::SimpleThread;
-using net::BalsaFrame;
-using net::BalsaFrameEnums;
-using net::BalsaHeaders;
-using net::BalsaHeadersEnums;
-using net::BalsaVisitorInterface;
-using net::EpollAlarmCallbackInterface;
-using net::EpollCallbackInterface;
-using net::EpollEvent;
-using net::EpollServer;
-using net::RingBuffer;
-using net::SimpleBuffer;
-using net::SplitStringPieceToVector;
-using net::UrlUtilities;
-using spdy::CONTROL_FLAG_NONE;
-using spdy::DATA_FLAG_COMPRESSED;
-using spdy::DATA_FLAG_FIN;
-using spdy::RST_STREAM;
-using spdy::SYN_REPLY;
-using spdy::SYN_STREAM;
-using spdy::SpdyControlFrame;
-using spdy::SpdySettingsControlFrame;
-using spdy::SpdyDataFlags;
-using spdy::SpdyDataFrame;
-using spdy::SpdyRstStreamControlFrame;
-using spdy::SpdyFrame;
-using spdy::SpdyFrameBuilder;
-using spdy::SpdyFramer;
-using spdy::SpdyFramerVisitorInterface;
-using spdy::SpdyHeaderBlock;
-using spdy::SpdyStreamId;
-using spdy::SpdySynReplyControlFrame;
-using spdy::SpdySynStreamControlFrame;
-
-FlipConfig g_proxy_config;
-
-////////////////////////////////////////////////////////////////////////////////
-
-void PrintSslError() {
-  char buf[128];  // this buffer must be at least 120 chars long.
-  int error_num = ERR_get_error();
-  while (error_num != 0) {
-    LOG(ERROR) << ERR_error_string(error_num, buf);
-    error_num = ERR_get_error();
-  }
-}
-
-static int ssl_set_npn_callback(SSL *s,
-                                const unsigned char **data,
-                                unsigned int *len,
-                                void *arg)
-{
-  VLOG(1) <<  "SSL NPN callback: advertising protocols.";
-  *data = (const unsigned char *) NEXT_PROTO_STRING;
-  *len = strlen(NEXT_PROTO_STRING);
-  return SSL_TLSEXT_ERR_OK;
-}
-////////////////////////////////////////////////////////////////////////////////
-
-// Creates a socket with domain, type and protocol parameters.
-// Assigns the return value of socket() to *fd.
-// Returns errno if an error occurs, else returns zero.
-int CreateSocket(int domain, int type, int protocol, int *fd) {
-  CHECK(fd != NULL);
-  *fd = ::socket(domain, type, protocol);
-  return (*fd == -1) ? errno : 0;
-}
-
-// Encode the URL.
-string EncodeURL(string uri, string host, string method) {
-  if (!FLAGS_need_to_encode_url) {
-    // TODO(mbelshe): if uri is fully qualified, need to strip protocol/host.
-    return string(method + "_" + uri);
-  }
-
-  string filename;
-  if (uri[0] == '/') {
-    // uri is not fully qualified.
-    filename = net::UrlToFilenameEncoder::Encode(
-        "http://" + host + uri, method + "_/", false);
-  } else {
-    filename = net::UrlToFilenameEncoder::Encode(uri, method + "_/", false);
-  }
-  return filename;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct SSLState {
-  SSL_METHOD* ssl_method;
-  SSL_CTX* ssl_ctx;
-};
-
-// SSL stuff
-void spdy_init_ssl(SSLState* state,
-                   string ssl_cert_name,
-                   string ssl_key_name,
-                   bool use_npn) {
-  SSL_library_init();
-  PrintSslError();
-
-  SSL_load_error_strings();
-  PrintSslError();
-
-  state->ssl_method = SSLv23_method();
-  state->ssl_ctx = SSL_CTX_new(state->ssl_method);
-  if (!state->ssl_ctx) {
-    PrintSslError();
-    LOG(FATAL) << "Unable to create SSL context";
-  }
-  // Disable SSLv2 support.
-  SSL_CTX_set_options(state->ssl_ctx,
-                      SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE);
-  if (SSL_CTX_use_certificate_file(state->ssl_ctx,
-                                   ssl_cert_name.c_str(),
-                                   SSL_FILETYPE_PEM) <= 0) {
-    PrintSslError();
-    LOG(FATAL) << "Unable to use cert.pem as SSL cert.";
-  }
-  if (SSL_CTX_use_PrivateKey_file(state->ssl_ctx,
-                                  ssl_key_name.c_str(),
-                                  SSL_FILETYPE_PEM) <= 0) {
-    PrintSslError();
-    LOG(FATAL) << "Unable to use key.pem as SSL key.";
-  }
-  if (!SSL_CTX_check_private_key(state->ssl_ctx)) {
-    PrintSslError();
-    LOG(FATAL) << "The cert.pem and key.pem files don't match";
-  }
-  if (use_npn) {
-    SSL_CTX_set_next_protos_advertised_cb(state->ssl_ctx,
-                                          ssl_set_npn_callback, NULL);
-  }
-  VLOG(1) << "SSL CTX default cipher list: " << SSL_CTX_DEFAULT_CIPHER_LIST;
-  SSL_CTX_set_cipher_list(state->ssl_ctx, SSL_CTX_DEFAULT_CIPHER_LIST);
-
-  VLOG(1) << "SSL CTX session expiry: " << g_proxy_config.ssl_session_expiry_
-          << " seconds";
-  SSL_CTX_set_timeout(state->ssl_ctx, g_proxy_config.ssl_session_expiry_);
-
-#ifdef SSL_MODE_RELEASE_BUFFERS
-  VLOG(1) << "SSL CTX: Setting Release Buffers mode.";
-  SSL_CTX_set_mode(state->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
-
-  // Proper methods to disable compression don't exist until 0.9.9+. For now
-  // we must manipulate the stack of compression methods directly.
-  if (g_proxy_config.ssl_disable_compression_) {
-    STACK_OF(SSL_COMP) *ssl_comp_methods = SSL_COMP_get_compression_methods();
-    int num_methods = sk_SSL_COMP_num(ssl_comp_methods);
-    int i;
-    for (i = 0; i < num_methods; i++) {
-      static_cast<void>(sk_SSL_COMP_delete(ssl_comp_methods, i));
-    }
-  }
-}
-
-SSL* spdy_new_ssl(SSL_CTX* ssl_ctx) {
-  SSL* ssl = SSL_new(ssl_ctx);
-  PrintSslError();
-
-  SSL_set_accept_state(ssl);
-  PrintSslError();
-
-  return ssl;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-const int kMSS = 1460;
-const int kInitialDataSendersThreshold = (2 * kMSS) - SpdyFrame::size();
-const int kNormalSegmentSize = (2 * kMSS) - SpdyFrame::size();
-
-////////////////////////////////////////////////////////////////////////////////
-
-class DataFrame {
- public:
-  const char* data;
-  size_t size;
-  bool delete_when_done;
-  size_t index;
-  DataFrame() : data(NULL), size(0), delete_when_done(false), index(0) {}
-  void MaybeDelete() {
-    if (delete_when_done) {
-      delete[] data;
-    }
-  }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class StoreBodyAndHeadersVisitor: public BalsaVisitorInterface {
- public:
-  BalsaHeaders headers;
-  string body;
-  bool error_;
-
-  virtual void ProcessBodyInput(const char *input, size_t size) {}
-  virtual void ProcessBodyData(const char *input, size_t size) {
-    body.append(input, size);
-  }
-  virtual void ProcessHeaderInput(const char *input, size_t size) {}
-  virtual void ProcessTrailerInput(const char *input, size_t size) {}
-  virtual void ProcessHeaders(const BalsaHeaders& headers) {
-    // nothing to do here-- we're assuming that the BalsaFrame has
-    // been handed our headers.
-  }
-  virtual void ProcessRequestFirstLine(const char* line_input,
-                                       size_t line_length,
-                                       const char* method_input,
-                                       size_t method_length,
-                                       const char* request_uri_input,
-                                       size_t request_uri_length,
-                                       const char* version_input,
-                                       size_t version_length) {}
-  virtual void ProcessResponseFirstLine(const char *line_input,
-                                        size_t line_length,
-                                        const char *version_input,
-                                        size_t version_length,
-                                        const char *status_input,
-                                        size_t status_length,
-                                        const char *reason_input,
-                                        size_t reason_length) {}
-  virtual void ProcessChunkLength(size_t chunk_length) {}
-  virtual void ProcessChunkExtensions(const char *input, size_t size) {}
-  virtual void HeaderDone() {}
-  virtual void MessageDone() {}
-  virtual void HandleHeaderError(BalsaFrame* framer) { HandleError(); }
-  virtual void HandleHeaderWarning(BalsaFrame* framer) { HandleError(); }
-  virtual void HandleChunkingError(BalsaFrame* framer) { HandleError(); }
-  virtual void HandleBodyError(BalsaFrame* framer) { HandleError(); }
-
-  void HandleError() { error_ = true; }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct FileData {
-  void CopyFrom(const FileData& file_data) {
-    headers = new BalsaHeaders;
-    headers->CopyFrom(*(file_data.headers));
-    filename = file_data.filename;
-    related_files = file_data.related_files;
-    body = file_data.body;
-  }
-  FileData(BalsaHeaders* h, const string& b) : headers(h), body(b) {}
-  FileData() {}
-  BalsaHeaders* headers;
-  string filename;
-  vector< pair<int, string> > related_files;   // priority, filename
-  string body;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class MemCacheIter {
- public:
-  MemCacheIter() :
-      file_data(NULL),
-      priority(0),
-      transformed_header(false),
-      body_bytes_consumed(0),
-      stream_id(0),
-      max_segment_size(kInitialDataSendersThreshold),
-      bytes_sent(0) {}
-  explicit MemCacheIter(FileData* fd) :
-      file_data(fd),
-      priority(0),
-      transformed_header(false),
-      body_bytes_consumed(0),
-      stream_id(0),
-      max_segment_size(kInitialDataSendersThreshold),
-      bytes_sent(0) {}
-  FileData* file_data;
-  int priority;
-  bool transformed_header;
-  size_t body_bytes_consumed;
-  uint32 stream_id;
-  uint32 max_segment_size;
-  size_t bytes_sent;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class MemoryCache {
- public:
-  typedef map<string, FileData> Files;
-
- public:
-  Files files_;
-  string cwd_;
-
-  void CloneFrom(const MemoryCache& mc) {
-    for (Files::const_iterator i = mc.files_.begin();
-         i != mc.files_.end();
-         ++i) {
-      Files::iterator out_i =
-        files_.insert(make_pair(i->first, FileData())).first;
-      out_i->second.CopyFrom(i->second);
-      cwd_ = mc.cwd_;
-    }
-  }
-
-  void AddFiles() {
-    deque<string> paths;
-    cwd_ = FLAGS_cache_base_dir;
-    paths.push_back(cwd_ + "/GET_");
-    DIR* current_dir = NULL;
-    while (!paths.empty()) {
-      while (current_dir == NULL && !paths.empty()) {
-        string current_dir_name = paths.front();
-        VLOG(1) << "Attempting to open dir: \"" << current_dir_name << "\"";
-        current_dir = opendir(current_dir_name.c_str());
-        paths.pop_front();
-
-        if (current_dir == NULL) {
-          perror("Unable to open directory. ");
-          current_dir_name.clear();
-          continue;
-        }
-
-        if (current_dir) {
-          VLOG(1) << "Succeeded opening";
-          for (struct dirent* dir_data = readdir(current_dir);
-               dir_data != NULL;
-               dir_data = readdir(current_dir)) {
-            string current_entry_name =
-              current_dir_name + "/" + dir_data->d_name;
-            if (dir_data->d_type == DT_REG) {
-              VLOG(1) << "Found file: " << current_entry_name;
-              ReadAndStoreFileContents(current_entry_name.c_str());
-            } else if (dir_data->d_type == DT_DIR) {
-              VLOG(1) << "Found subdir: " << current_entry_name;
-              if (string(dir_data->d_name) != "." &&
-                  string(dir_data->d_name) != "..") {
-                VLOG(1) << "Adding to search path: " << current_entry_name;
-                paths.push_front(current_entry_name);
-              }
-            }
-          }
-          VLOG(1) << "Oops, no data left. Closing dir.";
-          closedir(current_dir);
-          current_dir = NULL;
-        }
-      }
-    }
-  }
-
-  void ReadToString(const char* filename, string* output) {
-    output->clear();
-    int fd = open(filename, 0, "r");
-    if (fd == -1)
-      return;
-    char buffer[4096];
-    ssize_t read_status = read(fd, buffer, sizeof(buffer));
-    while (read_status > 0) {
-      output->append(buffer, static_cast<size_t>(read_status));
-      do {
-        read_status = read(fd, buffer, sizeof(buffer));
-      } while (read_status <= 0 && errno == EINTR);
-    }
-    close(fd);
-  }
-
-  void ReadAndStoreFileContents(const char* filename) {
-    StoreBodyAndHeadersVisitor visitor;
-    BalsaFrame framer;
-    framer.set_balsa_visitor(&visitor);
-    framer.set_balsa_headers(&(visitor.headers));
-    string filename_contents;
-    ReadToString(filename, &filename_contents);
-
-    // Ugly hack to make everything look like 1.1.
-    if (filename_contents.find("HTTP/1.0") == 0)
-      filename_contents[7] = '1';
-
-    size_t pos = 0;
-    size_t old_pos = 0;
-    while (true) {
-      old_pos = pos;
-      pos += framer.ProcessInput(filename_contents.data() + pos,
-                                 filename_contents.size() - pos);
-      if (framer.Error() || pos == old_pos) {
-        LOG(ERROR) << "Unable to make forward progress, or error"
-          " framing file: " << filename;
-        if (framer.Error()) {
-          LOG(INFO) << "********************************************ERROR!";
-          return;
-        }
-        return;
-      }
-      if (framer.MessageFullyRead()) {
-        // If no Content-Length or Transfer-Encoding was captured in the
-        // file, then the rest of the data is the body.  Many of the captures
-        // from within Chrome don't have content-lengths.
-        if (!visitor.body.length())
-          visitor.body = filename_contents.substr(pos);
-        break;
-      }
-    }
-    visitor.headers.RemoveAllOfHeader("content-length");
-    visitor.headers.RemoveAllOfHeader("transfer-encoding");
-    visitor.headers.RemoveAllOfHeader("connection");
-    visitor.headers.AppendHeader("transfer-encoding", "chunked");
-    visitor.headers.AppendHeader("connection", "keep-alive");
-
-    // Experiment with changing headers for forcing use of cached
-    // versions of content.
-    // TODO(mbelshe) REMOVE ME
-#if 0
-    // TODO(mbelshe) append current date.
-    visitor.headers.RemoveAllOfHeader("date");
-    if (visitor.headers.HasHeader("expires")) {
-      visitor.headers.RemoveAllOfHeader("expires");
-      visitor.headers.AppendHeader("expires",
-                                 "Fri, 30 Aug, 2019 12:00:00 GMT");
-    }
-#endif
-    BalsaHeaders* headers = new BalsaHeaders;
-    headers->CopyFrom(visitor.headers);
-    string filename_stripped = string(filename).substr(cwd_.size() + 1);
-//    LOG(INFO) << "Adding file (" << visitor.body.length() << " bytes): "
-//              << filename_stripped;
-    files_[filename_stripped] = FileData();
-    FileData& fd = files_[filename_stripped];
-    fd = FileData(headers, visitor.body);
-    fd.filename = string(filename_stripped,
-                         filename_stripped.find_first_of('/'));
-    if (headers->HasHeader("X-Associated-Content")) {
-      string content = headers->GetHeader("X-Associated-Content").as_string();
-      vector<StringPiece> urls_and_priorities;
-      SplitStringPieceToVector(content, "||", &urls_and_priorities, true);
-      VLOG(1) << "Examining X-Associated-Content header";
-      for (unsigned int i = 0; i < urls_and_priorities.size(); ++i) {
-        const StringPiece& url_and_priority_pair = urls_and_priorities[i];
-        vector<StringPiece> url_and_priority;
-        SplitStringPieceToVector(url_and_priority_pair, "??",
-                                 &url_and_priority, true);
-        if (url_and_priority.size() >= 2) {
-          string priority_string(url_and_priority[0].data(),
-                                 url_and_priority[0].size());
-          string filename_string(url_and_priority[1].data(),
-                                 url_and_priority[1].size());
-          long priority;
-          char* last_eaten_char;
-          priority = strtol(priority_string.c_str(), &last_eaten_char, 0);
-          if (last_eaten_char ==
-              priority_string.c_str() + priority_string.size()) {
-            pair<int, string> entry(priority, filename_string);
-            VLOG(1) << "Adding associated content: " << filename_string;
-            fd.related_files.push_back(entry);
-          }
-        }
-      }
-    }
-  }
-
-  // Called at runtime to update learned headers
-  // |url| is a url which contains a referrer header.
-  // |referrer| is the referring URL
-  // Adds an X-Subresource or X-Associated-Content to |referer| for |url|
-  void UpdateHeaders(string referrer, string file_url) {
-    if (!FLAGS_use_xac && !FLAGS_use_xsub)
-      return;
-
-    string referrer_host_path =
-      net::UrlToFilenameEncoder::Encode(referrer, "GET_/", false);
-
-    FileData* fd1 = GetFileData(string("GET_") + file_url);
-    if (!fd1) {
-      LOG(ERROR) << "Updating headers for unknown url: " << file_url;
-      return;
-    }
-    string url = fd1->headers->GetHeader("X-Original-Url").as_string();
-    string content_type = fd1->headers->GetHeader("Content-Type").as_string();
-    if (content_type.length() == 0) {
-      LOG(ERROR) << "Skipping subresource with unknown content-type";
-      return;
-    }
-    // Now, lets see if this is the same host or not
-    bool same_host = (UrlUtilities::GetUrlHost(referrer) ==
-                      UrlUtilities::GetUrlHost(url));
-
-    // This is a hacked algorithm for figuring out what priority
-    // to use with pushed content.
-    int priority = 4;
-    if (content_type.find("css") != string::npos)
-      priority = 1;
-    else if (content_type.find("cript") != string::npos)
-      priority = 1;
-    else if (content_type.find("html") != string::npos)
-      priority = 2;
-
-    LOG(ERROR) << "Attempting update for " << referrer_host_path;
-
-    FileData* fd2 = GetFileData(referrer_host_path);
-    if (fd2 != NULL) {
-      // If they are on the same host, we'll use X-Associated-Content
-      string header_name;
-      string new_value;
-      string delimiter;
-      bool related_files = false;
-      if (same_host && FLAGS_use_xac) {
-        header_name = "X-Associated-Content";
-        char pri_ch = priority + '0';
-        new_value = pri_ch + string("??") + url;
-        delimiter = "||";
-        related_files = true;
-      } else {
-        if (!FLAGS_use_xsub)
-          return;
-        header_name = "X-Subresource";
-        new_value = content_type + "!!" + url;
-        delimiter = "!!";
-      }
-
-      if (fd2->headers->HasNonEmptyHeader(header_name)) {
-        string existing_header =
-            fd2->headers->GetHeader(header_name).as_string();
-        if (existing_header.find(url) != string::npos)
-          return;  // header already recorded
-
-        // Don't let these lists grow too long for low pri stuff.
-        // TODO(mbelshe) We need better algorithms for this.
-        if (existing_header.length() > 256 && priority > 2)
-          return;
-
-        new_value = existing_header + delimiter + new_value;
-      }
-
-      LOG(INFO) << "Recording " << header_name << " for " << new_value;
-      fd2->headers->ReplaceOrAppendHeader(header_name, new_value);
-
-      // Add it to the related files so that it will actually get sent out.
-      if (related_files) {
-        pair<int, string> entry(4, file_url);
-        fd2->related_files.push_back(entry);
-      }
-    } else {
-      LOG(ERROR) << "Failed to update headers:";
-      LOG(ERROR) << "FAIL url: " << url;
-      LOG(ERROR) << "FAIL ref: " << referrer_host_path;
-    }
-  }
-
-  FileData* GetFileData(const string& filename) {
-    Files::iterator fi = files_.end();
-    if (filename.compare(filename.length() - 5, 5, ".html", 5) == 0) {
-      string new_filename(filename.data(), filename.size() - 5);
-      new_filename += ".http";
-      fi = files_.find(new_filename);
-    }
-    if (fi == files_.end())
-      fi = files_.find(filename);
-
-    if (fi == files_.end()) {
-      return NULL;
-    }
-    return &(fi->second);
-  }
-
-  bool AssignFileData(const string& filename, MemCacheIter* mci) {
-    mci->file_data = GetFileData(filename);
-    if (mci->file_data == NULL) {
-      LOG(ERROR) << "Could not find file data for " << filename;
-      return false;
-    }
-    return true;
-  }
-};
-
-class NotifierInterface {
- public:
-  virtual ~NotifierInterface() {}
-  virtual void Notify() = 0;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class SMConnectionPoolInterface;
-
-class SMInterface {
- public:
-  virtual void InitSMInterface(SMInterface* sm_other_interface,
-                               int32 server_idx) = 0;
-  virtual void InitSMConnection(SMConnectionPoolInterface* connection_pool,
-                                SMInterface* sm_interface,
-                                EpollServer* epoll_server,
-                                int fd,
-                                string server_ip,
-                                string server_port,
-                                bool use_ssl)  = 0;
-  virtual size_t ProcessReadInput(const char* data, size_t len) = 0;
-  virtual size_t ProcessWriteInput(const char* data, size_t len) = 0;
-  virtual void SetStreamID(uint32 stream_id) = 0;
-  virtual bool MessageFullyRead() const = 0;
-  virtual bool Error() const = 0;
-  virtual const char* ErrorAsString() const = 0;
-  virtual void Reset() = 0;
-  virtual void ResetForNewInterface(int32 server_idx) = 0;
-  // ResetForNewConnection is used for interfaces which control SMConnection
-  // objects. When called an interface may put its connection object into
-  // a reusable instance pool. Currently this is what the HttpSM interface
-  // does.
-  virtual void ResetForNewConnection() = 0;
-  virtual void Cleanup() = 0;
-
-  virtual int PostAcceptHook() = 0;
-
-  virtual void NewStream(uint32 stream_id, uint32 priority,
-                         const string& filename) = 0;
-  virtual void SendEOF(uint32 stream_id) = 0;
-  virtual void SendErrorNotFound(uint32 stream_id) = 0;
-  virtual size_t SendSynStream(uint32 stream_id,
-                              const BalsaHeaders& headers) = 0;
-  virtual size_t SendSynReply(uint32 stream_id,
-                              const BalsaHeaders& headers) = 0;
-  virtual void SendDataFrame(uint32 stream_id, const char* data, int64 len,
-                             uint32 flags, bool compress) = 0;
-  virtual void GetOutput() = 0;
-
-  virtual ~SMInterface() {}
-};
-
-class SMConnectionInterface {
- public:
-   virtual ~SMConnectionInterface() {}
-   virtual void ReadyToSend() = 0;
-   virtual EpollServer* epoll_server() = 0;
-};
-
-class HttpSM;
-class SMConnection;
-
-typedef list<DataFrame> OutputList;
-
-class SMConnectionPoolInterface {
- public:
-  virtual ~SMConnectionPoolInterface() {}
-  // SMConnections will use this:
-  virtual void SMConnectionDone(SMConnection* connection) = 0;
-};
-
-SMInterface* NewStreamerSM(SMConnection* connection,
-                           SMInterface* sm_interface,
-                           EpollServer* epoll_server,
-                           FlipAcceptor* acceptor);
-
-SMInterface* NewSpdySM(SMConnection* connection,
-                       SMInterface* sm_interface,
-                       EpollServer* epoll_server,
-                       MemoryCache* memory_cache,
-                       FlipAcceptor* acceptor);
-
-SMInterface* NewHttpSM(SMConnection* connection,
-                       SMInterface* sm_interface,
-                       EpollServer* epoll_server,
-                       MemoryCache* memory_cache,
-                       FlipAcceptor* acceptor);
-
-////////////////////////////////////////////////////////////////////////////////
-
-class SMConnection:  public SMConnectionInterface,
-                     public EpollCallbackInterface,
-                     public NotifierInterface {
- private:
-  SMConnection(EpollServer* epoll_server,
-               SSLState* ssl_state,
-               MemoryCache* memory_cache,
-               FlipAcceptor* acceptor,
-               string log_prefix)
-      : fd_(-1),
-        events_(0),
-        registered_in_epoll_server_(false),
-        initialized_(false),
-        protocol_detected_(false),
-        connection_complete_(false),
-        connection_pool_(NULL),
-        epoll_server_(epoll_server),
-        ssl_state_(ssl_state),
-        memory_cache_(memory_cache),
-        acceptor_(acceptor),
-        read_buffer_(4096*10),
-        sm_spdy_interface_(NULL),
-        sm_http_interface_(NULL),
-        sm_streamer_interface_(NULL),
-        sm_interface_(NULL),
-        log_prefix_(log_prefix),
-        max_bytes_sent_per_dowrite_(4096),
-        ssl_(NULL)
-        {}
-
-  int fd_;
-  int events_;
-
-  bool registered_in_epoll_server_;
-  bool initialized_;
-  bool protocol_detected_;
-  bool connection_complete_;
-
-  SMConnectionPoolInterface* connection_pool_;
-
-  EpollServer *epoll_server_;
-  SSLState *ssl_state_;
-  MemoryCache* memory_cache_;
-  FlipAcceptor *acceptor_;
-  string client_ip_;
-
-  RingBuffer read_buffer_;
-
-  OutputList output_list_;
-  SMInterface* sm_spdy_interface_;
-  SMInterface* sm_http_interface_;
-  SMInterface* sm_streamer_interface_;
-  SMInterface* sm_interface_;
-  string log_prefix_;
-
-  size_t max_bytes_sent_per_dowrite_;
-
-  SSL* ssl_;
- public:
-  string server_ip_;
-  string server_port_;
-
-  EpollServer* epoll_server() { return epoll_server_; }
-  OutputList* output_list() { return &output_list_; }
-  MemoryCache* memory_cache() { return memory_cache_; }
-  void ReadyToSend() {
-    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-            << "Setting ready to send: EPOLLIN | EPOLLOUT";
-    epoll_server_->SetFDReady(fd_, EPOLLIN | EPOLLOUT);
-  }
-  void EnqueueDataFrame(const DataFrame& df) {
-    output_list_.push_back(df);
-    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "EnqueueDataFrame: "
-            << "size = " << df.size << ": Setting FD ready.";
-    ReadyToSend();
-  }
-  int fd() { return fd_; }
-
- public:
-  ~SMConnection() {
-    if (initialized()) {
-      Reset();
-    }
-  }
-  static SMConnection* NewSMConnection(EpollServer* epoll_server,
-                                       SSLState *ssl_state,
-                                       MemoryCache* memory_cache,
-                                       FlipAcceptor *acceptor,
-                                       string log_prefix) {
-    return new SMConnection(epoll_server, ssl_state, memory_cache,
-                            acceptor, log_prefix);
-  }
-
-  bool initialized() const { return initialized_; }
-  string client_ip() const { return client_ip_; }
-
-  void InitSMConnection(SMConnectionPoolInterface* connection_pool,
-                        SMInterface* sm_interface,
-                        EpollServer* epoll_server,
-                        int fd,
-                        string server_ip,
-                        string server_port,
-                        bool use_ssl) {
-    if (initialized_) {
-      LOG(FATAL) << "Attempted to initialize already initialized server";
-      return;
-    }
-
-    if (fd == -1) {
-      // If fd == -1, then we are initializing a new connection that will
-      // connect to the backend.
-      //
-      // ret:  -1 == error
-      //        0 == connection in progress
-      //        1 == connection complete
-      // TODO: is_numeric_host_address value needs to be detected
-      server_ip_ = server_ip;
-      server_port_ = server_port;
-      int ret = net::CreateConnectedSocket(&fd_,
-                                           server_ip,
-                                           server_port,
-                                           true,
-                                           acceptor_->disable_nagle_);
-
-      if (ret < 0) {
-        LOG(ERROR) << "-1 Could not create connected socket";
-        return;
-      } else if (ret == 1) {
-        DCHECK_NE(-1, fd_);
-        connection_complete_ = true;
-        VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                << "Connection complete to: " << server_ip_ << ":"
-                << server_port_ << " ";
-      }
-      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-              << "Connecting to server: " << server_ip_ << ":"
-                << server_port_ << " ";
-    } else {
-      // If fd != -1 then we are initializing a connection that has just been
-      // accepted from the listen socket.
-      connection_complete_ = true;
-      if (epoll_server_ && registered_in_epoll_server_ && fd_ != -1) {
-        epoll_server_->UnregisterFD(fd_);
-      }
-      if (fd_ != -1) {
-        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                 << "Closing pre-existing fd";
-        close(fd_);
-        fd_ = -1;
-      }
-
-      fd_ = fd;
-      struct sockaddr sock_addr;
-      socklen_t addr_size = sizeof(sock_addr);
-      addr_size = sizeof(sock_addr);
-      int res = getsockname(fd_, &sock_addr, &addr_size);
-      if (res < 0) {
-        LOG(ERROR) << "Could not get socket address for fd " << fd_
-                   << ": getsockname: " << strerror(errno);
-      } else {
-        struct sockaddr_in *sock_addr_in = (struct sockaddr_in *)&sock_addr;
-        char ip[16];
-        snprintf(ip, sizeof(ip), "%d.%d.%d.%d",
-                IPV4_PRINTABLE_FORMAT(sock_addr_in->sin_addr.s_addr));
-        client_ip_ = ip;
-      }
-    }
-
-    registered_in_epoll_server_ = false;
-    initialized_ = true;
-
-    connection_pool_ = connection_pool;
-    epoll_server_ = epoll_server;
-
-    if (sm_interface) {
-      sm_interface_ = sm_interface;
-      protocol_detected_ = true;
-    }
-
-    read_buffer_.Clear();
-
-    epoll_server_->RegisterFD(fd_, this, EPOLLIN | EPOLLOUT | EPOLLET);
-
-    if (use_ssl) {
-      ssl_ = spdy_new_ssl(ssl_state_->ssl_ctx);
-      SSL_set_fd(ssl_, fd_);
-      PrintSslError();
-    }
-  }
-
-  int Send(const char* data, int len, int flags) {
-    ssize_t bytes_written = 0;
-    if (ssl_) {
-      // Write smallish chunks to SSL so that we don't have large
-      // multi-packet TLS records to receive before being able to handle
-      // the data.
-      while(len > 0) {
-        const int kMaxTLSRecordSize = 1460;
-        const char* ptr = &(data[bytes_written]);
-        int chunksize = std::min(len, kMaxTLSRecordSize);
-        int rv = SSL_write(ssl_, ptr, chunksize);
-        if (rv <= 0) {
-          switch(SSL_get_error(ssl_, rv)) {
-            case SSL_ERROR_WANT_READ:
-            case SSL_ERROR_WANT_WRITE:
-            case SSL_ERROR_WANT_ACCEPT:
-            case SSL_ERROR_WANT_CONNECT:
-              rv = -2;
-              break;
-            default:
-              PrintSslError();
-              break;
-          }
-          // If we wrote some data, return that count.  Otherwise
-          // return the stall error.
-          return bytes_written > 0 ? bytes_written : rv;
-        }
-        bytes_written += rv;
-        len -= rv;
-        if (rv != chunksize)
-          break;  // If we couldn't write everything, we're implicitly stalled
-      }
-    } else {
-      bytes_written = send(fd_, data, len, flags);
-    }
-    return bytes_written;
-  }
-
-  // the following are from the EpollCallbackInterface
-  virtual void OnRegistration(EpollServer* eps, int fd, int event_mask) {
-    registered_in_epoll_server_ = true;
-  }
-  virtual void OnModification(int fd, int event_mask) { }
-  virtual void OnEvent(int fd, EpollEvent* event) {
-    events_ |= event->in_events;
-    HandleEvents();
-    if (events_) {
-      event->out_ready_mask = events_;
-      events_ = 0;
-    }
-  }
-  virtual void OnUnregistration(int fd, bool replaced) {
-    registered_in_epoll_server_ = false;
-  }
-  virtual void OnShutdown(EpollServer* eps, int fd) {
-    Cleanup("OnShutdown");
-    return;
-  }
-
-  void Cleanup(const char* cleanup) {
-    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Cleanup";
-    if (!initialized_) {
-      return;
-    }
-    Reset();
-    if (connection_pool_) {
-      connection_pool_->SMConnectionDone(this);
-    }
-    if (sm_interface_) {
-      sm_interface_->ResetForNewConnection();
-    }
-  }
-
- private:
-  void HandleEvents() {
-    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Received: "
-            << EpollServer::EventMaskToString(events_).c_str();
-
-    if (events_ & EPOLLIN) {
-      if (!DoRead())
-        goto handle_close_or_error;
-    }
-
-    if (events_ & EPOLLOUT) {
-      // Check if we have connected or not
-      if (connection_complete_ == false) {
-        int sock_error;
-        socklen_t sock_error_len = sizeof(sock_error);
-        int ret = getsockopt(fd_, SOL_SOCKET, SO_ERROR, &sock_error,
-                              &sock_error_len);
-        if (ret != 0) {
-          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                  << "getsockopt error: " << errno << ": " << strerror(errno);
-          goto handle_close_or_error;
-        }
-        if (sock_error == 0) {
-          connection_complete_ = true;
-          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                  << "Connection complete to " << server_ip_ << ":"
-                << server_port_ << " ";
-        } else if (sock_error == EINPROGRESS) {
-          return;
-        } else {
-          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                  << "error connecting to server";
-          goto handle_close_or_error;
-        }
-      }
-      if (!DoWrite())
-        goto handle_close_or_error;
-    }
-
-    if (events_ & (EPOLLHUP | EPOLLERR)) {
-      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "!!! Got HUP or ERR";
-      goto handle_close_or_error;
-    }
-    return;
-
-    handle_close_or_error:
-    Cleanup("HandleEvents");
-  }
-
-  bool DoRead() {
-    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "DoRead()";
-    while (!read_buffer_.Full()) {
-      char* bytes;
-      int size;
-      if (fd_ == -1) {
-        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                << "DoRead(): fd_ == -1. Invalid FD. Returning false";
-        return false;
-      }
-      read_buffer_.GetWritablePtr(&bytes, &size);
-      ssize_t bytes_read = 0;
-      if (ssl_) {
-        bytes_read = SSL_read(ssl_, bytes, size);
-        if (bytes_read < 0) {
-          switch(SSL_get_error(ssl_, bytes_read)) {
-            case SSL_ERROR_WANT_READ:
-            case SSL_ERROR_WANT_WRITE:
-            case SSL_ERROR_WANT_ACCEPT:
-            case SSL_ERROR_WANT_CONNECT:
-              events_ &= ~EPOLLIN;
-              goto done;
-            default:
-              PrintSslError();
-              break;
-          }
-        }
-      } else {
-        bytes_read = recv(fd_, bytes, size, MSG_DONTWAIT);
-      }
-      int stored_errno = errno;
-      if (bytes_read == -1) {
-        switch (stored_errno) {
-          case EAGAIN:
-            events_ &= ~EPOLLIN;
-            VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                    << "Got EAGAIN while reading";
-            goto done;
-          case EINTR:
-            VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                    << "Got EINTR while reading";
-            continue;
-          default:
-            VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                    << "While calling recv, got error: "
-                    << (ssl_?"(ssl error)":strerror(stored_errno));
-            goto error_or_close;
-        }
-      } else if (bytes_read > 0) {
-        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "read " << bytes_read
-                 << " bytes";
-        if (!protocol_detected_) {
-          if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
-            // Http Server
-            protocol_detected_ = true;
-            if (!sm_http_interface_) {
-              VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                      << "Created HTTP interface.";
-              sm_http_interface_ = NewHttpSM(this, NULL, epoll_server_,
-                                             memory_cache_, acceptor_);
-            } else {
-              VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                      << "Reusing HTTP interface.";
-            }
-            sm_interface_ = sm_http_interface_;
-          } else if (ssl_) {
-            protocol_detected_ = true;
-            if (SSL_session_reused(ssl_) == 0) {
-              VLOG(1) << "Session status: renegotiated";
-            } else {
-              VLOG(1) << "Session status: resumed";
-            }
-            const unsigned char *npn_proto;
-            unsigned int npn_proto_len;
-            SSL_get0_next_proto_negotiated(ssl_, &npn_proto, &npn_proto_len);
-            if (npn_proto_len > 0) {
-              string npn_proto_str((const char *)npn_proto, npn_proto_len);
-              VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                      << "NPN protocol detected: " << npn_proto_str;
-            } else {
-              VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                      << "NPN protocol detected: none";
-              if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) {
-                VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                        << "NPN protocol: Could not negotiate SPDY protocol.";
-                goto error_or_close;
-              }
-            }
-            if (npn_proto_len > 0 &&
-                 !strncmp((char *)npn_proto, "spdy/2", npn_proto_len)) {
-              if (!sm_spdy_interface_) {
-                sm_spdy_interface_ = NewSpdySM(this, NULL, epoll_server_,
-                                               memory_cache_, acceptor_);
-                VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                        << "Created SPDY interface.";
-              } else {
-                VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                        << "Reusing SPDY interface.";
-              }
-              sm_interface_ = sm_spdy_interface_;
-            } else if (acceptor_->spdy_only_) {
-              VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                      << "SPDY proxy only, closing HTTPS connection.";
-              goto error_or_close;
-            } else {
-              if (!sm_streamer_interface_) {
-                sm_streamer_interface_ = NewStreamerSM(this, NULL,
-                                                       epoll_server_,
-                                                       acceptor_);
-                VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                        << "Created Streamer interface.";
-              } else {
-                VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                        << "Reusing Streamer interface: ";
-              }
-              sm_interface_ = sm_streamer_interface_;
-            }
-          }
-          if (sm_interface_->PostAcceptHook() == 0) {
-            goto error_or_close;
-          }
-        }
-        read_buffer_.AdvanceWritablePtr(bytes_read);
-        if (!DoConsumeReadData()) {
-          goto error_or_close;
-        }
-        continue;
-      } else {  // bytes_read == 0
-        VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                << "0 bytes read with recv call.";
-      }
-      goto error_or_close;
-    }
-   done:
-    return true;
-
-    error_or_close:
-    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-            << "DoRead(): error_or_close. "
-            << "Cleaning up, then returning false";
-    Cleanup("DoRead");
-    return false;
-  }
-
-  bool DoConsumeReadData() {
-    char* bytes;
-    int size;
-    read_buffer_.GetReadablePtr(&bytes, &size);
-    while (size != 0) {
-      size_t bytes_consumed = sm_interface_->ProcessReadInput(bytes, size);
-      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "consumed "
-              << bytes_consumed << " bytes";
-      if (bytes_consumed == 0) {
-        break;
-      }
-      read_buffer_.AdvanceReadablePtr(bytes_consumed);
-      if (sm_interface_->MessageFullyRead()) {
-        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                << "HandleRequestFullyRead: Setting EPOLLOUT";
-        HandleResponseFullyRead();
-        events_ |= EPOLLOUT;
-      } else if (sm_interface_->Error()) {
-        LOG(ERROR) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                   << "Framer error detected: Setting EPOLLOUT: "
-                   << sm_interface_->ErrorAsString();
-        // this causes everything to be closed/cleaned up.
-        events_ |= EPOLLOUT;
-        return false;
-      }
-      read_buffer_.GetReadablePtr(&bytes, &size);
-    }
-    return true;
-  }
-
-  void WriteResponse() {
-    // this happens asynchronously from separate threads
-    // feeding files into the output buffer.
-  }
-
-  void HandleResponseFullyRead() {
-    sm_interface_->Cleanup();
-  }
-
-  void Notify() {
-  }
-
-  bool DoWrite() {
-    size_t bytes_sent = 0;
-    int flags = MSG_NOSIGNAL | MSG_DONTWAIT;
-    if (fd_ == -1) {
-      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-              << "DoWrite: fd == -1. Returning false.";
-      return false;
-    }
-    if (output_list_.empty()) {
-      VLOG(2) << log_prefix_ << "DoWrite: Output list empty.";
-      if (sm_interface_) {
-        sm_interface_->GetOutput();
-      }
-      if (output_list_.empty()) {
-        events_ &= ~EPOLLOUT;
-      }
-    }
-    while (!output_list_.empty()) {
-      VLOG(2) << log_prefix_ << "DoWrite: Items in output list: "
-              << output_list_.size();
-      if (bytes_sent >= max_bytes_sent_per_dowrite_) {
-        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                << " byte sent >= max bytes sent per write: Setting EPOLLOUT";
-        events_ |= EPOLLOUT;
-        break;
-      }
-      if (sm_interface_ && output_list_.size() < 2) {
-        sm_interface_->GetOutput();
-      }
-      DataFrame& data_frame = output_list_.front();
-      const char*  bytes = data_frame.data;
-      int size = data_frame.size;
-      bytes += data_frame.index;
-      size -= data_frame.index;
-      DCHECK_GE(size, 0);
-      if (size <= 0) {
-        // Empty data frame. Indicates end of data from client.
-        // Uncork the socket.
-        int state = 0;
-        VLOG(2) << log_prefix_ << "Empty data frame, uncorking socket.";
-        setsockopt( fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof( state ) );
-        data_frame.MaybeDelete();
-        output_list_.pop_front();
-        continue;
-      }
-
-      flags = MSG_NOSIGNAL | MSG_DONTWAIT;
-      if (output_list_.size() > 1) {
-        VLOG(2) << log_prefix_ << "Outlist size: " << output_list_.size()
-                << ": Adding MSG_MORE flag";
-        flags |= MSG_MORE;
-      }
-      VLOG(2) << log_prefix_ << "Attempting to send " << size << " bytes.";
-      ssize_t bytes_written = Send(bytes, size, flags);
-      int stored_errno = errno;
-      if (bytes_written == -1) {
-        switch (stored_errno) {
-          case EAGAIN:
-            events_ &= ~EPOLLOUT;
-            VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                    << "Got EAGAIN while writing";
-            goto done;
-          case EINTR:
-            VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                    << "Got EINTR while writing";
-            continue;
-          default:
-            VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-                    << "While calling send, got error: " << stored_errno
-                    << ": " << (ssl_?"":strerror(stored_errno));
-            goto error_or_close;
-        }
-      } else if (bytes_written > 0) {
-        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Wrote: "
-                << bytes_written << " bytes";
-        data_frame.index += bytes_written;
-        bytes_sent += bytes_written;
-        continue;
-      } else if (bytes_written == -2) {
-        // -2 handles SSL_ERROR_WANT_* errors
-        events_ &= ~EPOLLOUT;
-        goto done;
-      }
-      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-              << "0 bytes written with send call.";
-      goto error_or_close;
-    }
-   done:
-    return true;
-
-   error_or_close:
-    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
-            << "DoWrite: error_or_close. Returning false "
-            << "after cleaning up";
-    Cleanup("DoWrite");
-    return false;
-  }
-
-  friend ostream& operator<<(ostream& os, const SMConnection& c) {
-    os << &c << "\n";
-    return os;
-  }
-
-  void Reset() {
-    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Resetting";
-    if (ssl_) {
-      SSL_shutdown(ssl_);
-      PrintSslError();
-      SSL_free(ssl_);
-      PrintSslError();
-    }
-    if (registered_in_epoll_server_) {
-      epoll_server_->UnregisterFD(fd_);
-      registered_in_epoll_server_ = false;
-    }
-    if (fd_ >= 0) {
-      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Closing connection";
-      close(fd_);
-      fd_ = -1;
-    }
-    read_buffer_.Clear();
-    initialized_ = false;
-    protocol_detected_ = false;
-    events_ = 0;
-    output_list_.clear();
-  }
-
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class OutputOrdering {
- public:
-  typedef list<MemCacheIter> PriorityRing;
-
-  typedef map<uint32, PriorityRing> PriorityMap;
-
-  struct PriorityMapPointer {
-    PriorityMapPointer(): ring(NULL), alarm_enabled(false) {}
-    PriorityRing* ring;
-    PriorityRing::iterator it;
-    bool alarm_enabled;
-    EpollServer::AlarmRegToken alarm_token;
-  };
-  typedef map<uint32, PriorityMapPointer> StreamIdToPriorityMap;
-
-  StreamIdToPriorityMap stream_ids_;
-  PriorityMap priority_map_;
-  PriorityRing first_data_senders_;
-  uint32 first_data_senders_threshold_;  // when you've passed this, you're no
-                                         // longer a first_data_sender...
-  SMConnectionInterface* connection_;
-  EpollServer* epoll_server_;
-
-  explicit OutputOrdering(SMConnectionInterface* connection) :
-        first_data_senders_threshold_(kInitialDataSendersThreshold),
-        connection_(connection) {
-    if (connection) {
-      epoll_server_ = connection->epoll_server();
-    }
-  }
-
-  void Reset() {
-    while (!stream_ids_.empty()) {
-      StreamIdToPriorityMap::iterator sitpmi = stream_ids_.begin();
-      PriorityMapPointer& pmp = sitpmi->second;
-      if (pmp.alarm_enabled) {
-        epoll_server_->UnregisterAlarm(pmp.alarm_token);
-      }
-      stream_ids_.erase(sitpmi);
-    }
-    priority_map_.clear();
-    first_data_senders_.clear();
-  }
-
-  bool ExistsInPriorityMaps(uint32 stream_id) {
-    StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id);
-    return sitpmi != stream_ids_.end();
-  }
-
-  struct BeginOutputtingAlarm : public EpollAlarmCallbackInterface {
-   public:
-    BeginOutputtingAlarm(OutputOrdering* oo,
-                         OutputOrdering::PriorityMapPointer* pmp,
-                         const MemCacheIter& mci) :
-        output_ordering_(oo), pmp_(pmp), mci_(mci), epoll_server_(NULL) {}
-
-    int64 OnAlarm() {
-      OnUnregistration();
-      output_ordering_->MoveToActive(pmp_, mci_);
-      VLOG(2) << "ON ALARM! Should now start to output...";
-      delete this;
-      return 0;
-    }
-    void OnRegistration(const EpollServer::AlarmRegToken& tok,
-                        EpollServer* eps) {
-      epoll_server_ = eps;
-      pmp_->alarm_token = tok;
-      pmp_->alarm_enabled = true;
-    }
-    void OnUnregistration() {
-      pmp_->alarm_enabled = false;
-    }
-    void OnShutdown(EpollServer* eps) {
-      OnUnregistration();
-    }
-    ~BeginOutputtingAlarm() {
-      if (epoll_server_ && pmp_->alarm_enabled)
-        epoll_server_->UnregisterAlarm(pmp_->alarm_token);
-    }
-   private:
-    OutputOrdering* output_ordering_;
-    OutputOrdering::PriorityMapPointer* pmp_;
-    MemCacheIter mci_;
-    EpollServer* epoll_server_;
-  };
-
-  void MoveToActive(PriorityMapPointer* pmp, MemCacheIter mci) {
-    VLOG(2) << "Moving to active!";
-    first_data_senders_.push_back(mci);
-    pmp->ring = &first_data_senders_;
-    pmp->it = first_data_senders_.end();
-    --pmp->it;
-    connection_->ReadyToSend();
-  }
-
-  void AddToOutputOrder(const MemCacheIter& mci) {
-    if (ExistsInPriorityMaps(mci.stream_id))
-      LOG(ERROR) << "OOps, already was inserted here?!";
-
-    double think_time_in_s = g_proxy_config.server_think_time_in_s_;
-    string x_server_latency =
-      mci.file_data->headers->GetHeader("X-Server-Latency").as_string();
-    if (x_server_latency.size() != 0) {
-      char* endp;
-      double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp);
-      if (endp != x_server_latency.c_str() + x_server_latency.size()) {
-        LOG(ERROR) << "Unable to understand X-Server-Latency of: "
-                   << x_server_latency << " for resource: "
-                   <<  mci.file_data->filename.c_str();
-      } else {
-        think_time_in_s = tmp_think_time_in_s;
-      }
-    }
-    StreamIdToPriorityMap::iterator sitpmi;
-    sitpmi = stream_ids_.insert(
-        pair<uint32, PriorityMapPointer>(mci.stream_id,
-                                         PriorityMapPointer())).first;
-    PriorityMapPointer& pmp = sitpmi->second;
-
-    BeginOutputtingAlarm* boa = new BeginOutputtingAlarm(this, &pmp, mci);
-    VLOG(1) << "Server think time: " << think_time_in_s;
-    epoll_server_->RegisterAlarmApproximateDelta(
-        think_time_in_s * 1000000, boa);
-  }
-
-  void SpliceToPriorityRing(PriorityRing::iterator pri) {
-    MemCacheIter& mci = *pri;
-    PriorityMap::iterator pmi = priority_map_.find(mci.priority);
-    if (pmi == priority_map_.end()) {
-      pmi = priority_map_.insert(
-          pair<uint32, PriorityRing>(mci.priority, PriorityRing())).first;
-    }
-
-    pmi->second.splice(pmi->second.end(),
-                       first_data_senders_,
-                       pri);
-    StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(mci.stream_id);
-    sitpmi->second.ring = &(pmi->second);
-  }
-
-  MemCacheIter* GetIter() {
-    while (!first_data_senders_.empty()) {
-      MemCacheIter& mci = first_data_senders_.front();
-      if (mci.bytes_sent >= first_data_senders_threshold_) {
-        SpliceToPriorityRing(first_data_senders_.begin());
-      } else {
-        first_data_senders_.splice(first_data_senders_.end(),
-                                  first_data_senders_,
-                                  first_data_senders_.begin());
-        mci.max_segment_size = kInitialDataSendersThreshold;
-        return &mci;
-      }
-    }
-    while (!priority_map_.empty()) {
-      PriorityRing& first_ring = priority_map_.begin()->second;
-      if (first_ring.empty()) {
-        priority_map_.erase(priority_map_.begin());
-        continue;
-      }
-      MemCacheIter& mci = first_ring.front();
-      first_ring.splice(first_ring.end(),
-                        first_ring,
-                        first_ring.begin());
-      mci.max_segment_size = kNormalSegmentSize;
-      return &mci;
-    }
-    return NULL;
-  }
-
-  void RemoveStreamId(uint32 stream_id) {
-    StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id);
-    if (sitpmi == stream_ids_.end())
-      return;
-    PriorityMapPointer& pmp = sitpmi->second;
-    if (pmp.alarm_enabled) {
-      epoll_server_->UnregisterAlarm(pmp.alarm_token);
-    } else {
-      pmp.ring->erase(pmp.it);
-    }
-
-    stream_ids_.erase(sitpmi);
-  }
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-class SpdySM : public SpdyFramerVisitorInterface, public SMInterface {
- private:
-  uint64 seq_num_;
-  SpdyFramer* spdy_framer_;
-
-  SMConnection* connection_;
-  OutputList* client_output_list_;
-  OutputOrdering client_output_ordering_;
-  uint32 next_outgoing_stream_id_;
-  EpollServer* epoll_server_;
-  FlipAcceptor* acceptor_;
-  MemoryCache* memory_cache_;
-  vector<SMInterface*> server_interface_list;
-  vector<int32> unused_server_interface_list;
-  typedef map<uint32,SMInterface*> StreamToSmif;
-  StreamToSmif stream_to_smif_;
- public:
-  SpdySM(SMConnection* connection,
-         SMInterface* sm_http_interface,
-         EpollServer* epoll_server,
-         MemoryCache* memory_cache,
-         FlipAcceptor* acceptor)
-         : seq_num_(0),
-           spdy_framer_(new SpdyFramer),
-           connection_(connection),
-           client_output_list_(connection->output_list()),
-           client_output_ordering_(connection),
-           next_outgoing_stream_id_(2),
-           epoll_server_(epoll_server),
-           acceptor_(acceptor),
-           memory_cache_(memory_cache) {
-    spdy_framer_->set_visitor(this);
-  }
-
-  ~SpdySM() {
-    delete spdy_framer_;
-  }
-
-  void InitSMInterface(SMInterface* sm_http_interface,
-                       int32 server_idx) { }
-
-  void InitSMConnection(SMConnectionPoolInterface* connection_pool,
-                        SMInterface* sm_interface,
-                        EpollServer* epoll_server,
-                        int fd,
-                        string server_ip,
-                        string server_port,
-                        bool use_ssl) {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT
-            << "SpdySM: Initializing server connection.";
-    connection_->InitSMConnection(connection_pool, sm_interface,
-                                  epoll_server, fd, server_ip, server_port,
-                                  use_ssl);
-  }
-
- private:
-  virtual void OnError(SpdyFramer* framer) {
-    /* do nothing with this right now */
-  }
-
-  SMInterface* NewConnectionInterface() {
-    SMConnection* server_connection =
-      SMConnection::NewSMConnection(epoll_server_, NULL,
-                                    memory_cache_, acceptor_,
-                                    "http_conn: ");
-    if (server_connection == NULL) {
-      LOG(ERROR) << "SpdySM: Could not create server connection";
-      return NULL;
-    }
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Creating new HTTP interface";
-    SMInterface *sm_http_interface = NewHttpSM(server_connection, this,
-                                               epoll_server_, memory_cache_,
-                                               acceptor_);
-    return sm_http_interface;
-  }
-
-  SMInterface* FindOrMakeNewSMConnectionInterface(string server_ip,
-                                                  string server_port) {
-    SMInterface *sm_http_interface;
-    int32 server_idx;
-    if (unused_server_interface_list.empty()) {
-      sm_http_interface = NewConnectionInterface();
-      server_idx = server_interface_list.size();
-      server_interface_list.push_back(sm_http_interface);
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT
-              << "SpdySM: Making new server connection on index: "
-              << server_idx;
-    } else {
-      server_idx = unused_server_interface_list.back();
-      unused_server_interface_list.pop_back();
-      sm_http_interface = server_interface_list.at(server_idx);
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Reusing connection on "
-              << "index: " << server_idx;
-    }
-
-    sm_http_interface->InitSMInterface(this, server_idx);
-    sm_http_interface->InitSMConnection(NULL, sm_http_interface,
-                                        epoll_server_, -1,
-                                        server_ip, server_port, false);
-
-    return sm_http_interface;
-  }
-
-  int SpdyHandleNewStream(const SpdyControlFrame* frame,
-                          string *http_data,
-                          bool *is_https_scheme)
-  {
-    bool parsed_headers = false;
-    SpdyHeaderBlock headers;
-    const SpdySynStreamControlFrame* syn_stream =
-      reinterpret_cast<const SpdySynStreamControlFrame*>(frame);
-
-    *is_https_scheme = false;
-    parsed_headers = spdy_framer_->ParseHeaderBlock(frame, &headers);
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSyn("
-            << syn_stream->stream_id() << ")";
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: headers parsed?: "
-            << (parsed_headers? "yes": "no");
-    if (parsed_headers) {
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: # headers: "
-              << headers.size();
-    }
-    SpdyHeaderBlock::iterator url = headers.find("url");
-    SpdyHeaderBlock::iterator method = headers.find("method");
-    if (url == headers.end() || method == headers.end()) {
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: didn't find method or url "
-              << "or method. Not creating stream";
-      return 0;
-    }
-
-    SpdyHeaderBlock::iterator scheme = headers.find("scheme");
-    if (scheme->second.compare("https") == 0) {
-      *is_https_scheme = true;
-    }
-
-    string uri = UrlUtilities::GetUrlPath(url->second);
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) {
-      SpdyHeaderBlock::iterator referer = headers.find("referer");
-      if (referer != headers.end() && method->second == "GET") {
-        memory_cache_->UpdateHeaders(referer->second, url->second);
-      }
-      string host = UrlUtilities::GetUrlHost(url->second);
-      VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second
-              << " " << uri;
-      string filename = EncodeURL(uri, host, method->second);
-      NewStream(syn_stream->stream_id(),
-                reinterpret_cast<const SpdySynStreamControlFrame*>(frame)->
-                priority(),
-                filename);
-    } else {
-      SpdyHeaderBlock::iterator version = headers.find("version");
-      *http_data += method->second + " " + uri + " " + version->second + "\r\n";
-      VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second << " "
-              << uri << " " << version->second;
-      for (SpdyHeaderBlock::iterator i = headers.begin();
-           i != headers.end(); ++i) {
-        *http_data += i->first + ": " + i->second + "\r\n";
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":"
-                << i->second.c_str();
-      }
-      if (g_proxy_config.forward_ip_header_enabled_) {
-        // X-Client-Cluster-IP header
-        *http_data += g_proxy_config.forward_ip_header_ + ": " +
-                      connection_->client_ip() + "\r\n";
-      }
-      *http_data += "\r\n";
-    }
-
-    VLOG(3) << ACCEPTOR_CLIENT_IDENT << "SpdySM: HTTP Request:\n" << http_data;
-    return 1;
-  }
-
-  virtual void OnControl(const SpdyControlFrame* frame) {
-    SpdyHeaderBlock headers;
-    bool parsed_headers = false;
-    switch (frame->type()) {
-      case SYN_STREAM:
-        {
-        const SpdySynStreamControlFrame* syn_stream =
-            reinterpret_cast<const SpdySynStreamControlFrame*>(frame);
-
-          string http_data;
-          bool is_https_scheme;
-          int ret = SpdyHandleNewStream(frame, &http_data, &is_https_scheme);
-          if (!ret) {
-            LOG(ERROR) << "SpdySM: Could not convert spdy into http.";
-            break;
-          }
-
-          if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-            string server_ip;
-            string server_port;
-            if (is_https_scheme) {
-              server_ip = acceptor_->https_server_ip_;
-              server_port = acceptor_->https_server_port_;
-            } else {
-              server_ip = acceptor_->http_server_ip_;
-              server_port = acceptor_->http_server_port_;
-            }
-            SMInterface *sm_http_interface =
-              FindOrMakeNewSMConnectionInterface(server_ip, server_port);
-            stream_to_smif_[syn_stream->stream_id()] = sm_http_interface;
-            sm_http_interface->SetStreamID(syn_stream->stream_id());
-            sm_http_interface->ProcessWriteInput(http_data.c_str(),
-                                                 http_data.size());
-          }
-        }
-        break;
-
-      case SYN_REPLY:
-        parsed_headers = spdy_framer_->ParseHeaderBlock(frame, &headers);
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSynReply(" <<
-          reinterpret_cast<const SpdySynReplyControlFrame*>(frame)->stream_id()
-          << ")";
-        break;
-      case RST_STREAM:
-        {
-        const SpdyRstStreamControlFrame* rst_stream =
-            reinterpret_cast<const SpdyRstStreamControlFrame*>(frame);
-          VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnRst("
-                  << rst_stream->stream_id() << ")";
-          client_output_ordering_.RemoveStreamId(rst_stream ->stream_id());
-        }
-        break;
-
-      default:
-        LOG(ERROR) << "SpdySM: Unknown control frame type";
-    }
-  }
-  virtual void OnStreamFrameData(SpdyStreamId stream_id,
-                                 const char* data, size_t len) {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: StreamData(" << stream_id
-            << ", [" << len << "])";
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-          stream_to_smif_[stream_id]->ProcessWriteInput(data, len);
-    }
-  }
-
- public:
-  size_t ProcessReadInput(const char* data, size_t len) {
-    return spdy_framer_->ProcessInput(data, len);
-  }
-
-  size_t ProcessWriteInput(const char* data, size_t len) {
-    return 0;
-  }
-
-  bool MessageFullyRead() const {
-    return spdy_framer_->MessageFullyRead();
-  }
-
-  void SetStreamID(uint32 stream_id) {}
-
-  bool Error() const {
-    return spdy_framer_->HasError();
-  }
-
-  const char* ErrorAsString() const {
-    DCHECK(Error());
-    return SpdyFramer::ErrorCodeToString(spdy_framer_->error_code());
-  }
-
-  void Reset() {
-  }
-
-  void ResetForNewInterface(int32 server_idx) {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Reset for new interface: "
-            << "server_idx: " << server_idx;
-    unused_server_interface_list.push_back(server_idx);
-  }
-
-  void ResetForNewConnection() {
-    // seq_num is not cleared, intentionally.
-    delete spdy_framer_;
-    spdy_framer_ = new SpdyFramer;
-    spdy_framer_->set_visitor(this);
-    client_output_ordering_.Reset();
-    next_outgoing_stream_id_ = 2;
-  }
-
-  // SMInterface's Cleanup is currently only called by SMConnection after a
-  // protocol message as been fully read. Spdy's SMInterface does not need
-  // to do any cleanup at this time.
-  // TODO (klindsay) This method is probably not being used properly and
-  // some logic review and method renaming is probably in order.
-  void Cleanup() {}
-
-  // Send a settings frame and possibly some NOOP packets to force
-  // opening of cwnd
-  int PostAcceptHook() {
-    ssize_t bytes_written;
-    spdy::SpdySettings settings;
-    spdy::SettingsFlagsAndId settings_id(0);
-    settings_id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
-    settings.push_back(spdy::SpdySetting(settings_id, 100));
-    scoped_ptr<SpdySettingsControlFrame>
-      settings_frame(spdy_framer_->CreateSettings(settings));
-
-    char* bytes = settings_frame->data();
-    size_t size = SpdyFrame::size() + settings_frame->length();
-    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending Settings Frame";
-    bytes_written = connection_->Send(bytes, size,
-                                      MSG_NOSIGNAL | MSG_DONTWAIT);
-    if (static_cast<size_t>(bytes_written) != size) {
-      LOG(ERROR) << "Trouble sending SETTINGS frame! (" << errno << ")";
-      if (errno == EAGAIN) {
-        return 0;
-      }
-    }
-    return 1;
-  }
-
-  void AddAssociatedContent(FileData* file_data) {
-    for (unsigned int i = 0; i < file_data->related_files.size(); ++i) {
-      pair<int, string>& related_file = file_data->related_files[i];
-      MemCacheIter mci;
-      string filename  = "GET_";
-      filename += related_file.second;
-      if (!memory_cache_->AssignFileData(filename, &mci)) {
-        VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Unable to find associated "
-                << "content for: " << filename;
-        continue;
-      }
-      VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Adding associated content: "
-              << filename;
-      mci.stream_id = next_outgoing_stream_id_;
-      next_outgoing_stream_id_ += 2;
-      mci.priority =  related_file.first;
-      AddToOutputOrder(mci);
-    }
-  }
-
-  void NewStream(uint32 stream_id, uint32 priority, const string& filename) {
-    MemCacheIter mci;
-    mci.stream_id = stream_id;
-    mci.priority = priority;
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) {
-      if (!memory_cache_->AssignFileData(filename, &mci)) {
-        // error creating new stream.
-        VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound";
-        SendErrorNotFound(stream_id);
-      } else {
-        AddToOutputOrder(mci);
-        if (FLAGS_use_xac) {
-          AddAssociatedContent(mci.file_data);
-        }
-      }
-    } else {
-      AddToOutputOrder(mci);
-    }
-  }
-
-  void AddToOutputOrder(const MemCacheIter& mci) {
-    client_output_ordering_.AddToOutputOrder(mci);
-  }
-
-  void SendEOF(uint32 stream_id) {
-    SendEOFImpl(stream_id);
-  }
-
-  void SendErrorNotFound(uint32 stream_id) {
-    SendErrorNotFoundImpl(stream_id);
-  }
-
-  void SendOKResponse(uint32 stream_id, string* output) {
-    SendOKResponseImpl(stream_id, output);
-  }
-
-  size_t SendSynStream(uint32 stream_id, const BalsaHeaders& headers) {
-    return SendSynStreamImpl(stream_id, headers);
-  }
-
-  size_t SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
-    return SendSynReplyImpl(stream_id, headers);
-  }
-
-  void SendDataFrame(uint32 stream_id, const char* data, int64 len,
-                     uint32 flags, bool compress) {
-    SpdyDataFlags spdy_flags = static_cast<SpdyDataFlags>(flags);
-    SendDataFrameImpl(stream_id, data, len, spdy_flags, compress);
-  }
-
-  SpdyFramer* spdy_framer() { return spdy_framer_; }
-
- private:
-  void SendEOFImpl(uint32 stream_id) {
-    SendDataFrame(stream_id, NULL, 0, DATA_FLAG_FIN, false);
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending EOF: " << stream_id;
-    KillStream(stream_id);
-  }
-
-  void SendErrorNotFoundImpl(uint32 stream_id) {
-    BalsaHeaders my_headers;
-    my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found");
-    SendSynReplyImpl(stream_id, my_headers);
-    SendDataFrame(stream_id, "wtf?", 4, DATA_FLAG_FIN, false);
-    client_output_ordering_.RemoveStreamId(stream_id);
-  }
-
-  void SendOKResponseImpl(uint32 stream_id, string* output) {
-    BalsaHeaders my_headers;
-    my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
-    SendSynReplyImpl(stream_id, my_headers);
-    SendDataFrame(
-        stream_id, output->c_str(), output->size(), DATA_FLAG_FIN, false);
-    client_output_ordering_.RemoveStreamId(stream_id);
-  }
-
-  void KillStream(uint32 stream_id) {
-    client_output_ordering_.RemoveStreamId(stream_id);
-  }
-
-  void CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) {
-    for (BalsaHeaders::const_header_lines_iterator hi =
-         headers.header_lines_begin();
-         hi != headers.header_lines_end();
-         ++hi) {
-      SpdyHeaderBlock::iterator fhi = dest.find(hi->first.as_string());
-      if (fhi == dest.end()) {
-        dest[hi->first.as_string()] = hi->second.as_string();
-      } else {
-        dest[hi->first.as_string()] = (
-            string(fhi->second.data(), fhi->second.size()) + "," +
-            string(hi->second.data(), hi->second.size()));
-      }
-    }
-
-    // These headers have no value
-    dest.erase("X-Associated-Content");  // TODO(mbelshe): case-sensitive
-    dest.erase("X-Original-Url");  // TODO(mbelshe): case-sensitive
-  }
-
-  size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) {
-    SpdyHeaderBlock block;
-    block["method"] = headers.request_method().as_string();
-    if (!headers.HasHeader("status"))
-      block["status"] = headers.response_code().as_string();
-    if (!headers.HasHeader("version"))
-      block["version"] =headers.response_version().as_string();
-    if (headers.HasHeader("X-Original-Url")) {
-      string original_url = headers.GetHeader("X-Original-Url").as_string();
-      block["path"] = UrlUtilities::GetUrlPath(original_url);
-    } else {
-      block["path"] = headers.request_uri().as_string();
-    }
-    CopyHeaders(block, headers);
-
-    SpdySynStreamControlFrame* fsrcf =
-      spdy_framer_->CreateSynStream(stream_id, 0, 0, CONTROL_FLAG_NONE, true,
-                                    &block);
-    DataFrame df;
-    df.size = fsrcf->length() + SpdyFrame::size();
-    size_t df_size = df.size;
-    df.data = fsrcf->data();
-    df.delete_when_done = true;
-    EnqueueDataFrame(df);
-
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynStreamheader "
-            << stream_id;
-    return df_size;
-  }
-
-  size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
-    SpdyHeaderBlock block;
-    CopyHeaders(block, headers);
-    block["status"] = headers.response_code().as_string() + " " +
-                      headers.response_reason_phrase().as_string();
-    block["version"] = headers.response_version().as_string();
-
-    SpdySynReplyControlFrame* fsrcf =
-      spdy_framer_->CreateSynReply(stream_id, CONTROL_FLAG_NONE, true, &block);
-    DataFrame df;
-    df.size = fsrcf->length() + SpdyFrame::size();
-    size_t df_size = df.size;
-    df.data = fsrcf->data();
-    df.delete_when_done = true;
-    EnqueueDataFrame(df);
-
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynReplyheader "
-            << stream_id;
-    return df_size;
-  }
-
-  void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
-                         SpdyDataFlags flags, bool compress) {
-    // Force compression off if disabled via command line.
-    if (!FLAGS_use_compression)
-      flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_COMPRESSED);
-
-    // TODO(mbelshe):  We can't compress here - before going into the
-    //                 priority queue.  Compression needs to be done
-    //                 with late binding.
-    SpdyDataFrame* fdf = spdy_framer_->CreateDataFrame(stream_id, data, len,
-                                                       flags);
-    DataFrame df;
-    df.size = fdf->length() + SpdyFrame::size();
-    df.data = fdf->data();
-    df.delete_when_done = true;
-    EnqueueDataFrame(df);
-
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending data frame "
-            << stream_id << " [" << len << "] shrunk to " << fdf->length();
-  }
-
-  void EnqueueDataFrame(const DataFrame& df) {
-    connection_->EnqueueDataFrame(df);
-  }
-
-  void GetOutput() {
-    while (client_output_list_->size() < 2) {
-      MemCacheIter* mci = client_output_ordering_.GetIter();
-      if (mci == NULL) {
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT
-                << "SpdySM: GetOutput: nothing to output!?";
-        return;
-      }
-      if (!mci->transformed_header) {
-        mci->transformed_header = true;
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput transformed "
-                << "header stream_id: [" << mci->stream_id << "]";
-        if ((mci->stream_id % 2) == 0) {
-          // this is a server initiated stream.
-          // Ideally, we'd do a 'syn-push' here, instead of a syn-reply.
-          BalsaHeaders headers;
-          headers.CopyFrom(*(mci->file_data->headers));
-          headers.ReplaceOrAppendHeader("status", "200");
-          headers.ReplaceOrAppendHeader("version", "http/1.1");
-          headers.SetRequestFirstlineFromStringPieces("PUSH",
-                                                      mci->file_data->filename,
-                                                      "");
-          mci->bytes_sent = SendSynStream(mci->stream_id, headers);
-        } else {
-          BalsaHeaders headers;
-          headers.CopyFrom(*(mci->file_data->headers));
-          mci->bytes_sent = SendSynReply(mci->stream_id, headers);
-        }
-        return;
-      }
-      if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput "
-                << "remove_stream_id: [" << mci->stream_id << "]";
-        SendEOF(mci->stream_id);
-        return;
-      }
-      size_t num_to_write =
-        mci->file_data->body.size() - mci->body_bytes_consumed;
-      if (num_to_write > mci->max_segment_size)
-        num_to_write = mci->max_segment_size;
-
-      bool should_compress = false;
-      if (!mci->file_data->headers->HasHeader("content-encoding")) {
-        if (mci->file_data->headers->HasHeader("content-type")) {
-          string content_type =
-              mci->file_data->headers->GetHeader("content-type").as_string();
-          if (content_type.find("image") == content_type.npos)
-            should_compress = true;
-        }
-      }
-
-      SendDataFrame(mci->stream_id,
-                    mci->file_data->body.data() + mci->body_bytes_consumed,
-                    num_to_write, 0, should_compress);
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput SendDataFrame["
-              << mci->stream_id << "]: " << num_to_write;
-      mci->body_bytes_consumed += num_to_write;
-      mci->bytes_sent += num_to_write;
-    }
-  }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class HttpSM : public BalsaVisitorInterface, public SMInterface {
- private:
-  uint64 seq_num_;
-  BalsaFrame* http_framer_;
-  BalsaHeaders headers_;
-  uint32 stream_id_;
-  int32 server_idx_;
-
-  SMConnection* connection_;
-  SMInterface* sm_spdy_interface_;
-  OutputList* output_list_;
-  OutputOrdering output_ordering_;
-  MemoryCache* memory_cache_;
-  FlipAcceptor* acceptor_;
- public:
-  explicit HttpSM(SMConnection* connection,
-                  SMInterface* sm_spdy_interface,
-                  EpollServer* epoll_server,
-                  MemoryCache* memory_cache,
-                  FlipAcceptor* acceptor) :
-      seq_num_(0),
-      http_framer_(new BalsaFrame),
-      stream_id_(0),
-      server_idx_(-1),
-      connection_(connection),
-      sm_spdy_interface_(sm_spdy_interface),
-      output_list_(connection->output_list()),
-      output_ordering_(connection),
-      memory_cache_(connection->memory_cache()),
-      acceptor_(acceptor) {
-    http_framer_->set_balsa_visitor(this);
-    http_framer_->set_balsa_headers(&headers_);
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-      http_framer_->set_is_request(false);
-    }
-  }
- private:
-  typedef map<string, uint32> ClientTokenMap;
- private:
-    virtual void ProcessBodyInput(const char *input, size_t size) {
-    }
-    virtual void ProcessBodyData(const char *input, size_t size) {
-      if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process Body Data: stream "
-                << stream_id_ << ": size " << size;
-        sm_spdy_interface_->SendDataFrame(stream_id_, input, size, 0, false);
-      }
-    }
-    virtual void ProcessHeaderInput(const char *input, size_t size) {
-    }
-    virtual void ProcessTrailerInput(const char *input, size_t size) {}
-    virtual void ProcessHeaders(const BalsaHeaders& headers) {
-      if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
-        string host =
-          UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string());
-        string method = headers.request_method().as_string();
-        VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Received Request: "
-                << headers.request_uri().as_string() << " " << method;
-        string filename = EncodeURL(headers.request_uri().as_string(),
-                                    host, method);
-        NewStream(stream_id_, 0, filename);
-        stream_id_ += 2;
-      } else {
-        VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Received Response from "
-                << connection_->server_ip_ << ":"
-                << connection_->server_port_ << " ";
-        sm_spdy_interface_->SendSynReply(stream_id_, headers);
-      }
-    }
-    virtual void ProcessRequestFirstLine(const char* line_input,
-                                         size_t line_length,
-                                         const char* method_input,
-                                         size_t method_length,
-                                         const char* request_uri_input,
-                                         size_t request_uri_length,
-                                         const char* version_input,
-                                         size_t version_length) {}
-    virtual void ProcessResponseFirstLine(const char *line_input,
-                                          size_t line_length,
-                                          const char *version_input,
-                                          size_t version_length,
-                                          const char *status_input,
-                                          size_t status_length,
-                                          const char *reason_input,
-                                          size_t reason_length) {}
-    virtual void ProcessChunkLength(size_t chunk_length) {}
-    virtual void ProcessChunkExtensions(const char *input, size_t size) {}
-    virtual void HeaderDone() {}
-    virtual void MessageDone() {
-      if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone. Sending EOF: "
-                << "stream " << stream_id_;
-        sm_spdy_interface_->SendEOF(stream_id_);
-      } else {
-        VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone.";
-      }
-    }
-    virtual void HandleHeaderError(BalsaFrame* framer) {
-      HandleError();
-    }
-    virtual void HandleHeaderWarning(BalsaFrame* framer) {}
-    virtual void HandleChunkingError(BalsaFrame* framer) {
-      HandleError();
-    }
-    virtual void HandleBodyError(BalsaFrame* framer) {
-      HandleError();
-    }
-
-    void HandleError() {
-      VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
-    }
-
- public:
-  ~HttpSM() {
-    Reset();
-    delete http_framer_;
-  }
-
-  void InitSMInterface(SMInterface* sm_spdy_interface,
-                       int32 server_idx)
-  {
-    sm_spdy_interface_ = sm_spdy_interface;
-    server_idx_ = server_idx;
-  }
-
-  void InitSMConnection(SMConnectionPoolInterface* connection_pool,
-                        SMInterface* sm_interface,
-                        EpollServer* epoll_server,
-                        int fd,
-                        string server_ip,
-                        string server_port,
-                        bool use_ssl)
-  {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Initializing server "
-            << "connection.";
-    connection_->InitSMConnection(connection_pool, sm_interface,
-                                  epoll_server, fd, server_ip, server_port,
-                                  use_ssl);
-  }
-
-  size_t ProcessReadInput(const char* data, size_t len) {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process read input: stream "
-            << stream_id_;
-    return http_framer_->ProcessInput(data, len);
-  }
-
-  size_t ProcessWriteInput(const char* data, size_t len) {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process write input: size "
-            << len << ": stream " << stream_id_;
-    char * dataPtr = new char[len];
-    memcpy(dataPtr, data, len);
-    DataFrame data_frame;
-    data_frame.data = (const char *)dataPtr;
-    data_frame.size = len;
-    data_frame.delete_when_done = true;
-    connection_->EnqueueDataFrame(data_frame);
-    return len;
-  }
-
-  bool MessageFullyRead() const {
-    return http_framer_->MessageFullyRead();
-  }
-
-  void SetStreamID(uint32 stream_id) {
-    stream_id_ = stream_id;
-  }
-
-  bool Error() const {
-    return http_framer_->Error();
-  }
-
-  const char* ErrorAsString() const {
-    return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode());
-  }
-
-  void Reset() {
-    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream "
-            << stream_id_;
-    http_framer_->Reset();
-  }
-
-  void ResetForNewInterface(int32 server_idx) {
-  }
-
-  void ResetForNewConnection() {
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-      VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
-        << "to: " << connection_->server_ip_ << ":"
-        << connection_->server_port_ << " ";
-    }
-    seq_num_ = 0;
-    output_ordering_.Reset();
-    http_framer_->Reset();
-    if (sm_spdy_interface_) {
-      sm_spdy_interface_->ResetForNewInterface(server_idx_);
-    }
-  }
-
-  void Cleanup() {
-    if (!(acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER)) {
-      connection_->Cleanup("HttpSM Request Fully Read: stream_id " +
-                           stream_id_);
-    }
-  }
-
-  int PostAcceptHook() {
-    return 1;
-  }
-
-  void NewStream(uint32 stream_id, uint32 priority, const string& filename) {
-    MemCacheIter mci;
-    mci.stream_id = stream_id;
-    mci.priority = priority;
-    if (!memory_cache_->AssignFileData(filename, &mci)) {
-      // error creating new stream.
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound";
-      SendErrorNotFound(stream_id);
-    } else {
-      AddToOutputOrder(mci);
-    }
-  }
-
-  void AddToOutputOrder(const MemCacheIter& mci) {
-    output_ordering_.AddToOutputOrder(mci);
-  }
-
-  void SendEOF(uint32 stream_id) {
-    SendEOFImpl(stream_id);
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
-      sm_spdy_interface_->ResetForNewInterface(server_idx_);
-    }
-  }
-
-  void SendErrorNotFound(uint32 stream_id) {
-    SendErrorNotFoundImpl(stream_id);
-  }
-
-  void SendOKResponse(uint32 stream_id, string* output) {
-    SendOKResponseImpl(stream_id, output);
-  }
-
-  size_t SendSynStream(uint32 stream_id, const BalsaHeaders& headers) {
-    return 0;
-  }
-
-  size_t SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
-    return SendSynReplyImpl(stream_id, headers);
-  }
-
-  void SendDataFrame(uint32 stream_id, const char* data, int64 len,
-                     uint32 flags, bool compress) {
-    SendDataFrameImpl(stream_id, data, len, flags, compress);
-  }
-
-  BalsaFrame* spdy_framer() { return http_framer_; }
-
- private:
-  void SendEOFImpl(uint32 stream_id) {
-    DataFrame df;
-    df.data = "0\r\n\r\n";
-    df.size = 5;
-    df.delete_when_done = false;
-    EnqueueDataFrame(df);
-    if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
-      Reset();
-    }
-  }
-
-  void SendErrorNotFoundImpl(uint32 stream_id) {
-    BalsaHeaders my_headers;
-    my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found");
-    my_headers.RemoveAllOfHeader("content-length");
-    my_headers.AppendHeader("transfer-encoding", "chunked");
-    SendSynReplyImpl(stream_id, my_headers);
-    SendDataFrame(stream_id, "wtf?", 4, 0, false);
-    SendEOFImpl(stream_id);
-    output_ordering_.RemoveStreamId(stream_id);
-  }
-
-  void SendOKResponseImpl(uint32 stream_id, string* output) {
-    BalsaHeaders my_headers;
-    my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
-    my_headers.RemoveAllOfHeader("content-length");
-    my_headers.AppendHeader("transfer-encoding", "chunked");
-    SendSynReplyImpl(stream_id, my_headers);
-    SendDataFrame(stream_id, output->c_str(), output->size(), 0, false);
-    SendEOFImpl(stream_id);
-    output_ordering_.RemoveStreamId(stream_id);
-  }
-
-  size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
-    SimpleBuffer sb;
-    headers.WriteHeaderAndEndingToBuffer(&sb);
-    DataFrame df;
-    df.size = sb.ReadableBytes();
-    char* buffer = new char[df.size];
-    df.data = buffer;
-    df.delete_when_done = true;
-    sb.Read(buffer, df.size);
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
-            << stream_id_;
-    size_t df_size = df.size;
-    EnqueueDataFrame(df);
-    return df_size;
-  }
-
-  size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) {
-    SimpleBuffer sb;
-    headers.WriteHeaderAndEndingToBuffer(&sb);
-    DataFrame df;
-    df.size = sb.ReadableBytes();
-    char* buffer = new char[df.size];
-    df.data = buffer;
-    df.delete_when_done = true;
-    sb.Read(buffer, df.size);
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
-            << stream_id_;
-    size_t df_size = df.size;
-    EnqueueDataFrame(df);
-    return df_size;
-  }
-
-  void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
-                         uint32 flags, bool compress) {
-    char chunk_buf[128];
-    snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len);
-    string chunk_description(chunk_buf);
-    DataFrame df;
-    df.size = chunk_description.size() + len + 2;
-    char* buffer = new char[df.size];
-    df.data = buffer;
-    df.delete_when_done = true;
-    memcpy(buffer, chunk_description.data(), chunk_description.size());
-    memcpy(buffer + chunk_description.size(), data, len);
-    memcpy(buffer + chunk_description.size() + len, "\r\n", 2);
-    EnqueueDataFrame(df);
-  }
-
-  void EnqueueDataFrame(const DataFrame& df) {
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Enqueue data frame: stream "
-            << stream_id_;
-    connection_->EnqueueDataFrame(df);
-  }
-
-  void GetOutput() {
-    MemCacheIter* mci = output_ordering_.GetIter();
-    if (mci == NULL) {
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput: nothing to "
-              << "output!?: stream " << stream_id_;
-      return;
-    }
-    if (!mci->transformed_header) {
-      mci->bytes_sent = SendSynReply(mci->stream_id,
-                                     *(mci->file_data->headers));
-      mci->transformed_header = true;
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
-              << "header stream_id: [" << mci->stream_id << "]";
-      return;
-    }
-    if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
-      SendEOF(mci->stream_id);
-      output_ordering_.RemoveStreamId(mci->stream_id);
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: ["
-              << mci->stream_id << "]";
-      return;
-    }
-    size_t num_to_write =
-      mci->file_data->body.size() - mci->body_bytes_consumed;
-    if (num_to_write > mci->max_segment_size)
-      num_to_write = mci->max_segment_size;
-    SendDataFrame(mci->stream_id,
-                  mci->file_data->body.data() + mci->body_bytes_consumed,
-                  num_to_write, 0, true);
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
-            << mci->stream_id << "]: " << num_to_write;
-    mci->body_bytes_consumed += num_to_write;
-    mci->bytes_sent += num_to_write;
-  }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class StreamerSM : public SMInterface {
- private:
-   SMConnection* connection_;
-   SMInterface* sm_other_interface_;
-   EpollServer* epoll_server_;
-   FlipAcceptor* acceptor_;
- public:
-   explicit StreamerSM(SMConnection* connection,
-                       SMInterface* sm_other_interface,
-                       EpollServer* epoll_server,
-                       FlipAcceptor* acceptor) :
-   connection_(connection),
-   sm_other_interface_(sm_other_interface),
-   epoll_server_(epoll_server),
-   acceptor_(acceptor)
-   {
-     VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Creating StreamerSM object";
-   }
-   ~StreamerSM() {
-     VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Destroying StreamerSM object";
-     Reset();
-   }
-
-   void InitSMInterface(SMInterface* sm_other_interface,
-                        int32 server_idx)
-   {
-     sm_other_interface_ = sm_other_interface;
-   }
-
-   void InitSMConnection(SMConnectionPoolInterface* connection_pool,
-                         SMInterface* sm_interface,
-                         EpollServer* epoll_server,
-                         int fd,
-                         string server_ip,
-                         string server_port,
-                         bool use_ssl)
-   {
-     VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Initializing server "
-             << "connection.";
-     connection_->InitSMConnection(connection_pool, sm_interface,
-                                   epoll_server, fd, server_ip,
-                                   server_port, use_ssl);
-   }
-
-   size_t ProcessReadInput(const char* data, size_t len) {
-     return sm_other_interface_->ProcessWriteInput(data, len);
-   }
-
-   size_t ProcessWriteInput(const char* data, size_t len) {
-     char * dataPtr = new char[len];
-     memcpy(dataPtr, data, len);
-     DataFrame df;
-     df.data = (const char *)dataPtr;
-     df.size = len;
-     df.delete_when_done = true;
-     connection_->EnqueueDataFrame(df);
-     return len;
-   }
-
-   bool MessageFullyRead() const {
-     return false;
-   }
-
-   void SetStreamID(uint32 stream_id) {}
-
-   bool Error() const {
-     return false;
-   }
-
-   const char* ErrorAsString() const {
-     return "(none)";
-   }
-
-   void Reset() {
-     VLOG(1) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Reset";
-     connection_->Cleanup("Server Reset");
-   }
-
-   void ResetForNewInterface(int32 server_idx) {
-   }
-
-   void ResetForNewConnection() {
-     sm_other_interface_->Reset();
-   }
-
-   void Cleanup() {
-   }
-
-   int PostAcceptHook() {
-     if (!sm_other_interface_) {
-       SMConnection *server_connection =
-         SMConnection::NewSMConnection(epoll_server_, NULL, NULL,
-                                       acceptor_, "server_conn: ");
-       if (server_connection == NULL) {
-         LOG(ERROR) << "StreamerSM: Could not create server conenction.";
-         return 0;
-       }
-       VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Creating new server "
-               << "connection.";
-       sm_other_interface_ = new StreamerSM(server_connection, this,
-                                            epoll_server_, acceptor_);
-       sm_other_interface_->InitSMInterface(this, 0);
-     }
-     // The Streamer interface is used to stream HTTPS connections, so we
-     // will always use the https_server_ip/port here.
-     sm_other_interface_->InitSMConnection(NULL, sm_other_interface_,
-                                           epoll_server_, -1,
-                                           acceptor_->https_server_ip_,
-                                           acceptor_->https_server_port_,
-                                           false);
-
-     return 1;
-   }
-
-   void NewStream(uint32 stream_id, uint32 priority, const string& filename) {
-   }
-
-   void AddToOutputOrder(const MemCacheIter& mci) {
-   }
-
-   void SendEOF(uint32 stream_id) {
-   }
-
-   void SendErrorNotFound(uint32 stream_id) {
-   }
-
-   void SendOKResponse(uint32 stream_id, string output) {
-   }
-
-   size_t SendSynStream(uint32 stream_id, const BalsaHeaders& headers) {
-     return 0;
-   }
-
-   size_t SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
-     return 0;
-   }
-
-   void SendDataFrame(uint32 stream_id, const char* data, int64 len,
-                      uint32 flags, bool compress) {
-   }
-
- private:
-   void SendEOFImpl(uint32 stream_id) {
-   }
-
-   void SendErrorNotFoundImpl(uint32 stream_id) {
-   }
-
-   void SendOKResponseImpl(uint32 stream_id, string* output) {
-   }
-
-   size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
-     return 0;
-   }
-
-   size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) {
-     return 0;
-   }
-
-   void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
-                          uint32 flags, bool compress) {
-   }
-
-   void GetOutput() {
-   }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class Notification {
- public:
-   explicit Notification(bool value) : value_(value) {}
-
-   void Notify() {
-     AutoLock al(lock_);
-     value_ = true;
-   }
-   bool HasBeenNotified() {
-     AutoLock al(lock_);
-     return value_;
-   }
-   bool value_;
-   Lock lock_;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-class SMAcceptorThread : public SimpleThread,
-                         public EpollCallbackInterface,
-                         public SMConnectionPoolInterface {
-  EpollServer epoll_server_;
-  FlipAcceptor *acceptor_;
-  SSLState *ssl_state_;
-  bool use_ssl_;
-
-  vector<SMConnection*> unused_server_connections_;
-  vector<SMConnection*> tmp_unused_server_connections_;
-  vector<SMConnection*> allocated_server_connections_;
-  Notification quitting_;
-  MemoryCache* memory_cache_;
- public:
-
-  SMAcceptorThread(FlipAcceptor *acceptor,
-                   MemoryCache* memory_cache) :
-      SimpleThread("SMAcceptorThread"),
-      acceptor_(acceptor),
-      ssl_state_(NULL),
-      use_ssl_(false),
-      quitting_(false),
-      memory_cache_(memory_cache)
-  {
-    if (!acceptor->ssl_cert_filename_.empty() &&
-        !acceptor->ssl_cert_filename_.empty()) {
-      ssl_state_ = new SSLState;
-      bool use_npn = true;
-      if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
-        use_npn = false;
-      }
-      spdy_init_ssl(ssl_state_, acceptor_->ssl_cert_filename_,
-                    acceptor_->ssl_key_filename_, use_npn);
-      use_ssl_ = true;
-    }
-  }
-
-  ~SMAcceptorThread() {
-    for (vector<SMConnection*>::iterator i =
-         allocated_server_connections_.begin();
-         i != allocated_server_connections_.end();
-         ++i) {
-      delete *i;
-    }
-  }
-
-  SMConnection* NewConnection() {
-    SMConnection* server =
-      SMConnection::NewSMConnection(&epoll_server_, ssl_state_,
-                                    memory_cache_, acceptor_,
-                                    "client_conn: ");
-    allocated_server_connections_.push_back(server);
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Making new server.";
-    return server;
-  }
-
-  SMConnection* FindOrMakeNewSMConnection() {
-    if (unused_server_connections_.empty()) {
-      return NewConnection();
-    }
-    SMConnection* server = unused_server_connections_.back();
-    unused_server_connections_.pop_back();
-    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Reusing server.";
-    return server;
-  }
-
-  void InitWorker() {
-    epoll_server_.RegisterFD(acceptor_->listen_fd_, this, EPOLLIN | EPOLLET);
-  }
-
-  void HandleConnection(int server_fd) {
-    int on = 1;
-    int rc;
-    if (acceptor_->disable_nagle_) {
-      rc = setsockopt(server_fd, IPPROTO_TCP,  TCP_NODELAY,
-                      reinterpret_cast<char*>(&on), sizeof(on));
-      if (rc < 0) {
-        close(server_fd);
-        LOG(ERROR) << "setsockopt() failed fd=" + server_fd;
-        return;
-      }
-    }
-
-    SMConnection* server_connection = FindOrMakeNewSMConnection();
-    if (server_connection == NULL) {
-      VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Closing fd " << server_fd;
-      close(server_fd);
-      return;
-    }
-    server_connection->InitSMConnection(this,
-                                        NULL,
-                                        &epoll_server_,
-                                        server_fd,
-                                        "", "",
-                                        use_ssl_);
-  }
-
-  void AcceptFromListenFD() {
-    if (acceptor_->accepts_per_wake_ > 0) {
-      for (int i = 0; i < acceptor_->accepts_per_wake_; ++i) {
-        struct sockaddr address;
-        socklen_t socklen = sizeof(address);
-        int fd = accept(acceptor_->listen_fd_, &address, &socklen);
-        if (fd == -1) {
-          if (errno != 11) {
-            VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Acceptor: accept fail("
-                    << acceptor_->listen_fd_ << "): " << errno << ": "
-                    << strerror(errno);
-          }
-          break;
-        }
-        VLOG(1) << ACCEPTOR_CLIENT_IDENT << " Accepted connection";
-        HandleConnection(fd);
-      }
-    } else {
-      while (true) {
-        struct sockaddr address;
-        socklen_t socklen = sizeof(address);
-        int fd = accept(acceptor_->listen_fd_, &address, &socklen);
-        if (fd == -1) {
-          if (errno != 11) {
-            VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Acceptor: accept fail("
-                    << acceptor_->listen_fd_ << "): " << errno << ": "
-                    << strerror(errno);
-          }
-          break;
-        }
-        VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Accepted connection";
-        HandleConnection(fd);
-      }
-    }
-  }
-
-  // EpollCallbackInteface virtual functions.
-  virtual void OnRegistration(EpollServer* eps, int fd, int event_mask) { }
-  virtual void OnModification(int fd, int event_mask) { }
-  virtual void OnEvent(int fd, EpollEvent* event) {
-    if (event->in_events | EPOLLIN) {
-      VLOG(2) << ACCEPTOR_CLIENT_IDENT
-              << "Acceptor: Accepting based upon epoll events";
-      AcceptFromListenFD();
-    }
-  }
-  virtual void OnUnregistration(int fd, bool replaced) { }
-  virtual void OnShutdown(EpollServer* eps, int fd) { }
-
-  void Quit() {
-    quitting_.Notify();
-  }
-
-  void Run() {
-    while (!quitting_.HasBeenNotified()) {
-      epoll_server_.set_timeout_in_us(10 * 1000);  // 10 ms
-      epoll_server_.WaitForEventsAndExecuteCallbacks();
-      unused_server_connections_.insert(unused_server_connections_.end(),
-                                        tmp_unused_server_connections_.begin(),
-                                        tmp_unused_server_connections_.end());
-      tmp_unused_server_connections_.clear();
-    }
-  }
-
-  // SMConnections will use this:
-  virtual void SMConnectionDone(SMConnection* sc) {
-    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Done with connection.";
-    tmp_unused_server_connections_.push_back(sc);
-  }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-SMInterface* NewStreamerSM(SMConnection* connection,
-                           SMInterface* sm_interface,
-                           EpollServer* epoll_server,
-                           FlipAcceptor* acceptor) {
-  return new StreamerSM(connection, sm_interface, epoll_server, acceptor);
-}
-
-
-SMInterface* NewSpdySM(SMConnection* connection,
-                       SMInterface* sm_interface,
-                       EpollServer* epoll_server,
-                       MemoryCache* memory_cache,
-                       FlipAcceptor* acceptor) {
-  return new SpdySM(connection, sm_interface, epoll_server,
-                    memory_cache, acceptor);
-}
-
-SMInterface* NewHttpSM(SMConnection* connection,
-                       SMInterface* sm_interface,
-                       EpollServer* epoll_server,
-                       MemoryCache* memory_cache,
-                       FlipAcceptor* acceptor) {
-  return new HttpSM(connection, sm_interface, epoll_server,
-                    memory_cache, acceptor);
-}
+net::FlipConfig g_proxy_config;
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -2938,7 +75,7 @@
   // Make stdin nonblocking. Yes this is done each time. Oh well.
   fcntl(0, F_SETFL, O_NONBLOCK);
   char c;
-  string maybequit;
+  std::string maybequit;
   while (read(0, &c, 1) > 0) {
     maybequit += c;
   }
@@ -2958,12 +95,76 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+static bool wantExit = false;
+static bool wantLogClose = false;
+void SignalHandler(int signum)
+{
+  switch(signum) {
+    case SIGTERM:
+    case SIGINT:
+      wantExit = true;
+      break;
+    case SIGHUP:
+      wantLogClose = true;
+      break;
+  }
+}
+
+static int OpenPidFile(const char *pidfile)
+{
+  int fd;
+  struct stat pid_stat;
+  int ret;
+
+  fd = open(pidfile, O_RDWR | O_CREAT, 0600);
+  if (fd == -1) {
+      cerr << "Could not open pid file '" << pidfile << "' for reading.\n";
+      exit(1);
+  }
+
+  ret = flock(fd, LOCK_EX | LOCK_NB);
+  if (ret == -1) {
+    if (errno == EWOULDBLOCK) {
+      cerr << "Flip server is already running.\n";
+    } else {
+      cerr << "Error getting lock on pid file: " << strerror(errno) << "\n";
+    }
+    exit(1);
+  }
+
+  if (fstat(fd, &pid_stat) == -1) {
+    cerr << "Could not stat pid file '" << pidfile << "': " << strerror(errno)
+         << "\n";
+  }
+  if (pid_stat.st_size != 0) {
+    if (ftruncate(fd, pid_stat.st_size) == -1) {
+      cerr << "Could not truncate pid file '" << pidfile << "': "
+           << strerror(errno) << "\n";
+    }
+  }
+
+  char pid_str[8];
+  snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+  int bytes = static_cast<int>(strlen(pid_str));
+  if (write(fd, pid_str, strlen(pid_str)) != bytes) {
+    cerr << "Could not write pid file: " << strerror(errno) << "\n";
+    close(fd);
+    exit(1);
+  }
+
+  return fd;
+}
+
 int main (int argc, char**argv)
 {
   unsigned int i = 0;
   bool wait_for_iface = false;
+  int pidfile_fd;
 
   signal(SIGPIPE, SIG_IGN);
+  signal(SIGTERM, SignalHandler);
+  signal(SIGINT, SignalHandler);
+  signal(SIGHUP, SignalHandler);
 
   CommandLine::Init(argc, argv);
   CommandLine cl(argc, argv);
@@ -2985,10 +186,10 @@
          << "\t    through the proxy listen ip:port.\n";
     cout << "\t--forward-ip-header=<header name>\n";
     cout << "\n  Server options:\n";
-    cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],\n"
-         << "\t               [ssl key filename]\"\n";
-    cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],\n"
-         << "\t               [ssl key filename]\"\n";
+    cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],"
+         << "\n\t               [ssl key filename]\"\n";
+    cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],"
+         << "\n\t               [ssl key filename]\"\n";
     cout << "\t  * Leaving the ssl cert and key fields empty will disable ssl"
          << " for the\n"
          << "\t    http and spdy flip servers\n";
@@ -3000,22 +201,27 @@
          << " raised.\n";
     cout << "\t--ssl-session-expiry=<seconds> (default is 300)\n";
     cout << "\t--ssl-disable-compression\n";
+    cout << "\t--idle-timeout=<seconds> (default is 300)\n";
+    cout << "\t--pidfile=<filepath> (default /var/run/flip-server.pid)\n";
     cout << "\t--help\n";
     exit(0);
   }
 
-  g_proxy_config.server_think_time_in_s_ = FLAGS_server_think_time_in_s;
+  if (cl.HasSwitch("pidfile")) {
+    pidfile_fd = OpenPidFile(cl.GetSwitchValueASCII("pidfile").c_str());
+  } else {
+    pidfile_fd = OpenPidFile(PIDFILE);
+  }
+
+  net::OutputOrdering::set_server_think_time_in_s(FLAGS_server_think_time_in_s);
 
   if (cl.HasSwitch("forward-ip-header")) {
-    g_proxy_config.forward_ip_header_enabled_ = true;
-    g_proxy_config.forward_ip_header_ =
-      cl.GetSwitchValueASCII("forward-ip-header");
-  } else {
-    g_proxy_config.forward_ip_header_enabled_ = false;
+    net::SpdySM::set_forward_ip_header(
+        cl.GetSwitchValueASCII("forward-ip-header"));
   }
 
   if (cl.HasSwitch("logdest")) {
-    string log_dest_value = cl.GetSwitchValueASCII("logdest");
+    std::string log_dest_value = cl.GetSwitchValueASCII("logdest");
     if (log_dest_value.compare("file") == 0) {
       g_proxy_config.log_destination_ = logging::LOG_ONLY_TO_FILE;
     } else if (log_dest_value.compare("system") == 0) {
@@ -3046,35 +252,49 @@
   }
 
   if (cl.HasSwitch("ssl-session-expiry")) {
-    string session_expiry = cl.GetSwitchValueASCII("ssl-session-expiry");
-    g_proxy_config.ssl_session_expiry_ = atoi( session_expiry.c_str() );
+    std::string session_expiry = cl.GetSwitchValueASCII("ssl-session-expiry");
+    g_proxy_config.ssl_session_expiry_ = atoi(session_expiry.c_str());
   }
 
   if (cl.HasSwitch("ssl-disable-compression")) {
     g_proxy_config.ssl_disable_compression_ = true;
   }
 
+  if (cl.HasSwitch("idle-timeout")) {
+    g_proxy_config.idle_socket_timeout_s_ =
+      atoi(cl.GetSwitchValueASCII("idle-timeout").c_str());
+  }
+
+  if (cl.HasSwitch("force_spdy"))
+    net::SMConnection::set_force_spdy(true);
+
   InitLogging(g_proxy_config.log_filename_.c_str(),
               g_proxy_config.log_destination_,
               logging::DONT_LOCK_LOG_FILE,
-              logging::APPEND_TO_OLD_LOG_FILE);
+              logging::APPEND_TO_OLD_LOG_FILE,
+              logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
 
   LOG(INFO) << "Flip SPDY proxy started with configuration:";
   LOG(INFO) << "Logging destination     : " << g_proxy_config.log_destination_;
   LOG(INFO) << "Log file                : " << g_proxy_config.log_filename_;
   LOG(INFO) << "Forward IP Header       : "
-            << (g_proxy_config.forward_ip_header_enabled_ ?
-                g_proxy_config.forward_ip_header_ : "(disabled)");
+            << (net::SpdySM::forward_ip_header().length() ?
+               net::SpdySM::forward_ip_header() : "<disabled>");
   LOG(INFO) << "Wait for interfaces     : " << (wait_for_iface?"true":"false");
   LOG(INFO) << "Accept backlog size     : " << FLAGS_accept_backlog_size;
   LOG(INFO) << "Accepts per wake        : " << FLAGS_accepts_per_wake;
   LOG(INFO) << "Disable nagle           : "
             << (FLAGS_disable_nagle?"true":"false");
-  LOG(INFO) << "Reuseport               : " << (FLAGS_reuseport?"true":"false");
+  LOG(INFO) << "Reuseport               : "
+            << (FLAGS_reuseport?"true":"false");
+  LOG(INFO) << "Force SPDY              : "
+            << (FLAGS_force_spdy?"true":"false");
   LOG(INFO) << "SSL session expiry      : "
             << g_proxy_config.ssl_session_expiry_;
   LOG(INFO) << "SSL disable compression : "
             << g_proxy_config.ssl_disable_compression_;
+  LOG(INFO) << "Connection idle timeout : "
+            << g_proxy_config.idle_socket_timeout_s_;
 
   // Proxy Acceptors
   while (true) {
@@ -3084,13 +304,13 @@
     if (!cl.HasSwitch(name.str())) {
       break;
     }
-    string value = cl.GetSwitchValueASCII(name.str());
-    vector<std::string> valueArgs = split(value, ',');
+    std::string value = cl.GetSwitchValueASCII(name.str());
+    std::vector<std::string> valueArgs = split(value, ',');
     CHECK_EQ((unsigned int)9, valueArgs.size());
     int spdy_only = atoi(valueArgs[8].c_str());
     // If wait_for_iface is enabled, then this call will block
     // indefinitely until the interface is raised.
-    g_proxy_config.AddAcceptor(FLIP_HANDLER_PROXY,
+    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_PROXY,
                                valueArgs[0], valueArgs[1],
                                valueArgs[2], valueArgs[3],
                                valueArgs[4], valueArgs[5],
@@ -3105,12 +325,12 @@
   }
 
   // Spdy Server Acceptor
-  MemoryCache spdy_memory_cache;
+  net::MemoryCache spdy_memory_cache;
   if (cl.HasSwitch("spdy-server")) {
     spdy_memory_cache.AddFiles();
-    string value = cl.GetSwitchValueASCII("spdy-server");
-    vector<std::string> valueArgs = split(value, ',');
-    g_proxy_config.AddAcceptor(FLIP_HANDLER_SPDY_SERVER,
+    std::string value = cl.GetSwitchValueASCII("spdy-server");
+    std::vector<std::string> valueArgs = split(value, ',');
+    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_SPDY_SERVER,
                                valueArgs[0], valueArgs[1],
                                valueArgs[2], valueArgs[3],
                                "", "", "", "",
@@ -3124,12 +344,12 @@
   }
 
   // Spdy Server Acceptor
-  MemoryCache http_memory_cache;
+  net::MemoryCache http_memory_cache;
   if (cl.HasSwitch("http-server")) {
     http_memory_cache.AddFiles();
-    string value = cl.GetSwitchValueASCII("http-server");
-    vector<std::string> valueArgs = split(value, ',');
-    g_proxy_config.AddAcceptor(FLIP_HANDLER_HTTP_SERVER,
+    std::string value = cl.GetSwitchValueASCII("http-server");
+    std::vector<std::string> valueArgs = split(value, ',');
+    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_HTTP_SERVER,
                                valueArgs[0], valueArgs[1],
                                valueArgs[2], valueArgs[3],
                                "", "", "", "",
@@ -3142,13 +362,14 @@
                                &http_memory_cache);
   }
 
-  vector<SMAcceptorThread*> sm_worker_threads_;
+  std::vector<net::SMAcceptorThread*> sm_worker_threads_;
 
   for (i = 0; i < g_proxy_config.acceptors_.size(); i++) {
-    FlipAcceptor *acceptor = g_proxy_config.acceptors_[i];
+    net::FlipAcceptor *acceptor = g_proxy_config.acceptors_[i];
 
-    sm_worker_threads_.push_back(new SMAcceptorThread(acceptor,
-                                     (MemoryCache *)acceptor->memory_cache_));
+    sm_worker_threads_.push_back(
+        new net::SMAcceptorThread(acceptor,
+                                  (net::MemoryCache *)acceptor->memory_cache_));
     // Note that spdy_memory_cache is not threadsafe, it is merely
     // thread compatible. Thus, if ever we are to spawn multiple threads,
     // we either must make the MemoryCache threadsafe, or use
@@ -3161,7 +382,14 @@
     sm_worker_threads_.back()->Start();
   }
 
-  while (true) {
+  while (!wantExit) {
+    // Close logfile when HUP signal is received. Logging system will
+    // automatically reopen on next log message.
+    if ( wantLogClose ) {
+      wantLogClose = false;
+      VLOG(1) << "HUP received, reopening log file.";
+      logging::CloseLogFile();
+    }
     if (GotQuitFromStdin()) {
       for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
         sm_worker_threads_[i]->Quit();
@@ -3169,10 +397,13 @@
       for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
         sm_worker_threads_[i]->Join();
       }
-      return 0;
+      break;
     }
     usleep(1000*10);  // 10 ms
   }
 
+  unlink(PIDFILE);
+  close(pidfile_fd);
   return 0;
 }
+
diff --git a/net/tools/flip_server/ring_buffer.cc b/net/tools/flip_server/ring_buffer.cc
index 2662edf..81e9e9e 100644
--- a/net/tools/flip_server/ring_buffer.cc
+++ b/net/tools/flip_server/ring_buffer.cc
@@ -15,6 +15,8 @@
       write_idx_(0) {
 }
 
+RingBuffer::~RingBuffer() {}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 int RingBuffer::ReadableBytes() const {
@@ -35,6 +37,18 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+bool RingBuffer::Empty() const {
+  return ReadableBytes() == 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool RingBuffer::Full() const {
+  return ReadableBytes() == BufferSize();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 // Returns the number of characters written.
 // Appends up-to-'size' bytes to the ringbuffer.
 int RingBuffer::Write(const char* bytes, int size) {
diff --git a/net/tools/flip_server/ring_buffer.h b/net/tools/flip_server/ring_buffer.h
index 75ad0ec..ac482b6 100644
--- a/net/tools/flip_server/ring_buffer.h
+++ b/net/tools/flip_server/ring_buffer.h
@@ -26,7 +26,7 @@
 class RingBuffer : public BufferInterface {
  public:
   explicit RingBuffer(int buffer_size);
-  virtual ~RingBuffer() { }
+  virtual ~RingBuffer();
 
   // Resize the buffer to the size specified here.  If the buffer_size passed
   // in here is smaller than the amount of data in the buffer, then the oldest
@@ -42,8 +42,8 @@
   virtual int BufferSize() const;
   virtual int BytesFree() const;
 
-  virtual bool Empty() const { return ReadableBytes() == 0; }
-  virtual bool Full() const { return ReadableBytes() == BufferSize(); }
+  virtual bool Empty() const;
+  virtual bool Full() const;
 
   // returns the number of characters written.
   // appends up-to-'size' bytes to the ringbuffer.
diff --git a/net/tools/flip_server/split.cc b/net/tools/flip_server/split.cc
index 7e3329a..6ab50cf 100644
--- a/net/tools/flip_server/split.cc
+++ b/net/tools/flip_server/split.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/tools/flip_server/split.h"
+
 #include <string.h>
 
 #include <vector>
diff --git a/net/tools/hresolv/hresolv.cc b/net/tools/hresolv/hresolv.cc
deleted file mode 100644
index 24d73a8..0000000
--- a/net/tools/hresolv/hresolv.cc
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// hrseolv is a command line utility which runs the HostResolver in the
-// Chromium network stack.
-//
-// The user specifies the hosts to lookup and when to look them up.
-// The hosts must be specified in order.
-// The hosts can be contained in a file or on the command line. If no
-// time is specified, the resolv is assumed to be the same time as the
-// previous host - which is an offset of 0 for the very first host.
-//
-// The user can also control whether the lookups happen asynchronously
-// or synchronously by specifying --async on the command line.
-//
-// Future ideas:
-//   Specify whether the lookup is speculative.
-//   Interleave synchronous and asynchronous lookups.
-//   Specify the address family.
-
-#include <stdio.h>
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/message_loop.h"
-#include "base/string_number_conversions.h"
-#include "base/string_split.h"
-#include "base/string_util.h"
-#include "base/threading/thread.h"
-#include "base/time.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/base/host_resolver_impl.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/sys_addrinfo.h"
-
-struct FlagName {
-  int flag;
-  const char* name;
-};
-
-static const FlagName kAddrinfoFlagNames[] = {
-  {AI_PASSIVE, "AI_PASSIVE"},
-  {AI_CANONNAME, "AI_CANONNAME"},
-  {AI_NUMERICHOST, "AI_NUMERICHOST"},
-  {AI_V4MAPPED, "AI_V4MAPPED"},
-  {AI_ALL, "AI_ALL"},
-  {AI_ADDRCONFIG, "AI_ADDRCONFIG"},
-#if !defined(OS_MACOSX)
-  {AI_NUMERICSERV, "AI_NUMERICSERV"},
-#endif
-};
-
-std::string FormatAddrinfoFlags(int ai_flags) {
-  std::string flag_names;
-  for (unsigned int i = 0; i < arraysize(kAddrinfoFlagNames); ++i) {
-    const FlagName& flag_name = kAddrinfoFlagNames[i];
-    if (ai_flags & flag_name.flag) {
-      ai_flags &= ~flag_name.flag;
-      if (!flag_names.empty()) {
-        flag_names += "|";
-      }
-      flag_names += flag_name.name;
-    }
-  }
-  if (ai_flags) {
-    if (!flag_names.empty()) {
-      flag_names += "|";
-    }
-    base::StringAppendF(&flag_names, "0x%x", ai_flags);
-  }
-  return flag_names;
-}
-
-const char* GetNameOfFlag(const FlagName* flag_names,
-                          unsigned int num_flag_names,
-                          int flag) {
-  for (unsigned int i = 0; i < num_flag_names; ++i) {
-    const FlagName& flag_name = flag_names[i];
-    if (flag_name.flag == flag) {
-      return flag_name.name;
-    }
-  }
-  return "UNKNOWN";
-}
-
-static const FlagName kFamilyFlagNames[] = {
-  {AF_UNSPEC, "AF_UNSPEC"},
-  {AF_INET, "AF_INET"},
-  {AF_INET6, "AF_INET6"},
-};
-
-const char* FormatAddrinfoFamily(int ai_family) {
-  return GetNameOfFlag(kFamilyFlagNames,
-                       arraysize(kFamilyFlagNames),
-                       ai_family);
-}
-
-static const FlagName kSocktypeFlagNames[] = {
-  {SOCK_STREAM, "SOCK_STREAM"},
-  {SOCK_DGRAM, "SOCK_DGRAM"},
-  {SOCK_RAW, "SOCK_RAW"},
-};
-
-const char* FormatAddrinfoSocktype(int ai_socktype) {
-  return GetNameOfFlag(kSocktypeFlagNames,
-                       arraysize(kSocktypeFlagNames),
-                       ai_socktype);
-}
-
-static const FlagName kProtocolFlagNames[] = {
-  {IPPROTO_TCP, "IPPROTO_TCP"},
-  {IPPROTO_UDP, "IPPROTO_UDP"},
-};
-
-const char* FormatAddrinfoProtocol(int ai_protocol) {
-  return GetNameOfFlag(kProtocolFlagNames,
-                       arraysize(kProtocolFlagNames),
-                       ai_protocol);
-}
-
-std::string FormatAddrinfoDetails(const struct addrinfo& ai,
-                                  const char* indent) {
-  std::string ai_flags = FormatAddrinfoFlags(ai.ai_flags);
-  const char* ai_family = FormatAddrinfoFamily(ai.ai_family);
-  const char* ai_socktype = FormatAddrinfoSocktype(ai.ai_socktype);
-  const char* ai_protocol = FormatAddrinfoProtocol(ai.ai_protocol);
-  std::string ai_addr = net::NetAddressToString(&ai);
-  std::string ai_canonname;
-  if (ai.ai_canonname) {
-    ai_canonname = base::StringPrintf("%s  ai_canonname: %s\n",
-                                      indent,
-                                      ai.ai_canonname);
-  }
-  return base::StringPrintf("%saddrinfo {\n"
-                            "%s  ai_flags: %s\n"
-                            "%s  ai_family: %s\n"
-                            "%s  ai_socktype: %s\n"
-                            "%s  ai_protocol: %s\n"
-                            "%s  ai_addrlen: %d\n"
-                            "%s  ai_addr: %s\n"
-                            "%s"
-                            "%s}\n",
-                            indent,
-                            indent, ai_flags.c_str(),
-                            indent, ai_family,
-                            indent, ai_socktype,
-                            indent, ai_protocol,
-                            indent, ai.ai_addrlen,
-                            indent, ai_addr.c_str(),
-                            ai_canonname.c_str(),
-                            indent);
-}
-
-std::string FormatAddressList(const net::AddressList& address_list,
-                              const std::string& host) {
-  std::string ret_string;
-  base::StringAppendF(&ret_string, "AddressList {\n");
-  base::StringAppendF(&ret_string, "  Host: %s\n", host.c_str());
-  for (const struct addrinfo* it = address_list.head();
-       it != NULL;
-       it = it->ai_next) {
-    base::StringAppendF(&ret_string, "%s",
-                        FormatAddrinfoDetails(*it, "  ").c_str());
-  }
-  base::StringAppendF(&ret_string, "}\n");
-  return ret_string;
-}
-
-class ResolverInvoker;
-
-// DelayedResolve contains state for a DNS resolution to be performed later.
-class DelayedResolve : public base::RefCounted<DelayedResolve> {
- public:
-  DelayedResolve(const std::string& host, bool is_async,
-                 net::HostResolver* resolver,
-                 ResolverInvoker* invoker)
-      : host_(host),
-        address_list_(),
-        is_async_(is_async),
-        resolver_(resolver),
-        invoker_(invoker),
-        ALLOW_THIS_IN_INITIALIZER_LIST(
-            io_callback_(this, &DelayedResolve::OnResolveComplete)) {
-  }
-
-  void Start() {
-    net::CompletionCallback* callback = (is_async_) ? &io_callback_ : NULL;
-    net::HostResolver::RequestInfo request_info(net::HostPortPair(host_, 80));
-    int rv = resolver_->Resolve(request_info,
-                                &address_list_,
-                                callback,
-                                NULL,
-                                net::BoundNetLog());
-    if (rv != net::ERR_IO_PENDING) {
-      OnResolveComplete(rv);
-    }
-  }
-
- private:
-
-  // Without this, VC++ complains about the private destructor below.
-  friend class base::RefCounted<DelayedResolve>;
-
-  // The destructor is called by Release.
-  ~DelayedResolve() {}
-
-  void OnResolveComplete(int result);
-
-  std::string host_;
-  net::AddressList address_list_;
-  bool is_async_;
-  net::HostResolver* const resolver_;
-  ResolverInvoker* invoker_;
-  net::CompletionCallbackImpl<DelayedResolve> io_callback_;
-};
-
-
-struct HostAndTime {
-  // The host to resolve, i.e. www.google.com
-  std::string host;
-  // Time since the start of this program to actually kick off the resolution.
-  int delta_in_milliseconds;
-};
-
-// Invokes a sequence of host resolutions at specified times.
-class ResolverInvoker {
- public:
-  explicit ResolverInvoker(net::HostResolver* resolver)
-      : message_loop_(MessageLoop::TYPE_DEFAULT),
-        resolver_(resolver),
-        remaining_requests_(0) {
-  }
-
-  ~ResolverInvoker() {
-  }
-
-  // Resolves all specified hosts in the order provided. hosts_and_times is
-  // assumed to be ordered by the delta_in_milliseconds field. There is no
-  // guarantee that the resolutions will complete in the order specified when
-  // async is true. There is no guarantee that the DNS queries will be issued
-  // at exactly the time specified by delta_in_milliseconds, but they are
-  // guaranteed to be issued at a time >= delta_in_milliseconds.
-  //
-  // When async is true, HostResolver::Resolve will issue the DNS lookups
-  // asynchronously - this can be used to have multiple requests in flight at
-  // the same time.
-  //
-  // ResolveAll will block until all resolutions are complete.
-  void ResolveAll(const std::vector<HostAndTime>& hosts_and_times,
-                  bool async) {
-    // Schedule all tasks on our message loop, and then run.
-    int num_requests = hosts_and_times.size();
-    remaining_requests_ = num_requests;
-    for (int i = 0; i < num_requests; ++i) {
-      const HostAndTime& host_and_time = hosts_and_times[i];
-      const std::string& host = host_and_time.host;
-      DelayedResolve* resolve_request = new DelayedResolve(host,
-        async, resolver_, this);
-      resolve_request->AddRef();
-      message_loop_.PostDelayedTask(
-          FROM_HERE,
-          NewRunnableMethod(resolve_request, &DelayedResolve::Start),
-          host_and_time.delta_in_milliseconds);
-    }
-    message_loop_.Run();
-  }
-
- private:
-  friend class DelayedResolve;
-
-  void OnResolved(int err, net::AddressList* address_list,
-                  const std::string& host) {
-    if (err == net::OK) {
-      printf("%s", FormatAddressList(*address_list, host).c_str());
-    } else {
-      printf("Error resolving %s\n", host.c_str());
-    }
-    DCHECK(remaining_requests_ > 0);
-    --remaining_requests_;
-    if (remaining_requests_ == 0) {
-      message_loop_.Quit();
-    }
-  }
-
-  MessageLoop message_loop_;
-  net::HostResolver* const resolver_;
-  int remaining_requests_;
-};
-
-void DelayedResolve::OnResolveComplete(int result) {
-  invoker_->OnResolved(result, &address_list_, host_);
-  this->Release();
-}
-
-struct CommandLineOptions {
-  CommandLineOptions()
-      : verbose(false),
-        async(false),
-        cache_size(100),
-        cache_ttl(50),
-        input_path() {
-  }
-
-  bool verbose;
-  bool async;
-  int cache_size;
-  int cache_ttl;
-  FilePath input_path;
-};
-
-const char* kAsync = "async";
-const char* kCacheSize = "cache-size";
-const char* kCacheTtl = "cache-ttl";
-const char* kInputPath = "input-path";
-
-// Parses the command line values. Returns false if there is a problem,
-// options otherwise.
-bool ParseCommandLine(CommandLine* command_line, CommandLineOptions* options) {
-  options->async = command_line->HasSwitch(kAsync);
-  if (command_line->HasSwitch(kCacheSize)) {
-    std::string cache_size = command_line->GetSwitchValueASCII(kCacheSize);
-    bool valid_size = base::StringToInt(cache_size, &options->cache_size);
-    if (valid_size) {
-      valid_size = options->cache_size >= 0;
-    }
-    if (!valid_size) {
-      printf("Invalid --cachesize value: %s\n", cache_size.c_str());
-      return false;
-    }
-  }
-
-  if (command_line->HasSwitch(kCacheTtl)) {
-    std::string cache_ttl = command_line->GetSwitchValueASCII(kCacheTtl);
-    bool valid_ttl = base::StringToInt(cache_ttl, &options->cache_ttl);
-    if (valid_ttl) {
-      valid_ttl = options->cache_ttl >= 0;
-    }
-    if (!valid_ttl) {
-      printf("Invalid --cachettl value: %s\n", cache_ttl.c_str());
-      return false;
-    }
-  }
-
-  if (command_line->HasSwitch(kInputPath)) {
-    options->input_path = command_line->GetSwitchValuePath(kInputPath);
-  }
-
-  return true;
-}
-
-bool ReadHostsAndTimesFromLooseValues(
-    const std::vector<CommandLine::StringType>& args,
-    std::vector<HostAndTime>* hosts_and_times) {
-  for (std::vector<CommandLine::StringType>::const_iterator it =
-           args.begin();
-       it != args.end();
-       ++it) {
-    // TODO(cbentzel): Read time offset.
-#if defined(OS_WIN)
-    HostAndTime host_and_time = {WideToASCII(*it), 0};
-#else
-    HostAndTime host_and_time = {*it, 0};
-#endif
-    hosts_and_times->push_back(host_and_time);
-  }
-  return true;
-}
-
-bool ReadHostsAndTimesFromFile(const FilePath& path,
-                               std::vector<HostAndTime>* hosts_and_times) {
-  // TODO(cbentzel): There are smarter and safer ways to do this.
-  std::string file_contents;
-  if (!file_util::ReadFileToString(path, &file_contents)) {
-    return false;
-  }
-  std::vector<std::string> lines;
-  // TODO(cbentzel): This should probably handle CRLF-style separators as well.
-  // Maybe it's worth adding functionality like this to base tools.
-  base::SplitString(file_contents, '\n', &lines);
-  std::vector<std::string>::const_iterator line_end = lines.end();
-  int previous_timestamp = 0;
-  for (std::vector<std::string>::const_iterator it = lines.begin();
-       it != line_end;
-       ++it) {
-    std::vector<std::string> tokens;
-    base::SplitStringAlongWhitespace(*it, &tokens);
-    switch (tokens.size()) {
-      case 0:
-        // Unexpected, but keep going.
-        break;
-      case 1: {
-        HostAndTime host_and_time = {tokens[0], previous_timestamp};
-        hosts_and_times->push_back(host_and_time);
-        break;
-      }
-      case 2: {
-        int timestamp;
-        if (!base::StringToInt(tokens[1], &timestamp)) {
-          // Unexpected value - keep going.
-        }
-        if (timestamp < previous_timestamp) {
-          // Unexpected value - ignore.
-        }
-        previous_timestamp = timestamp;
-        HostAndTime host_and_time = {tokens[0], timestamp};
-        hosts_and_times->push_back(host_and_time);
-        break;
-      }
-      default:
-        DCHECK(false);
-        break;
-    }
-  }
-  return true;
-}
-
-int main(int argc, char** argv) {
-  base::AtExitManager at_exit_manager;
-  CommandLine::Init(argc, argv);
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  CommandLineOptions options;
-  if (!ParseCommandLine(command_line, &options)) {
-    exit(1);
-  }
-
-  // Get the hosts and times - either from a file or command line options.
-  // TODO(cbentzel): Add stdin support to POSIX versions - not sure if
-  // there's an equivalent in Windows.
-  // TODO(cbentzel): If really large, may not want to spool the whole
-  // file into memory.
-  std::vector<HostAndTime> hosts_and_times;
-  if (options.input_path.empty()) {
-    if (!ReadHostsAndTimesFromLooseValues(command_line->args(),
-                                          &hosts_and_times)) {
-      exit(1);
-    }
-  } else {
-    if (!ReadHostsAndTimesFromFile(options.input_path, &hosts_and_times)) {
-      exit(1);
-    }
-  }
-
-  net::HostCache* cache = new net::HostCache(
-      options.cache_size,
-      base::TimeDelta::FromMilliseconds(options.cache_ttl),
-      base::TimeDelta::FromSeconds(0));
-
-  net::HostResolverImpl host_resolver(NULL, cache, 100u, NULL);
-  ResolverInvoker invoker(&host_resolver);
-  invoker.ResolveAll(hosts_and_times, options.async);
-
-  CommandLine::Reset();
-  return 0;
-}
diff --git a/net/tools/testserver/chromiumsync.py b/net/tools/testserver/chromiumsync.py
index b678238..56006d0 100755
--- a/net/tools/testserver/chromiumsync.py
+++ b/net/tools/testserver/chromiumsync.py
@@ -36,6 +36,7 @@
     TOP_LEVEL,  # The type of the 'Google Chrome' folder.
     APPS,
     AUTOFILL,
+    AUTOFILL_PROFILE,
     BOOKMARK,
     EXTENSIONS,
     NIGORI,
@@ -43,7 +44,7 @@
     PREFERENCE,
     SESSION,
     THEME,
-    TYPED_URL) = range(11)
+    TYPED_URL) = range(12)
 
 # Well-known server tag of the top level "Google Chrome" folder.
 TOP_LEVEL_FOLDER_TAG = 'google_chrome'
@@ -53,6 +54,7 @@
 SYNC_TYPE_TO_EXTENSION = {
     APPS: app_specifics_pb2.app,
     AUTOFILL: autofill_specifics_pb2.autofill,
+    AUTOFILL_PROFILE: autofill_specifics_pb2.autofill_profile,
     BOOKMARK: bookmark_specifics_pb2.bookmark,
     EXTENSIONS: extension_specifics_pb2.extension,
     NIGORI: nigori_specifics_pb2.nigori,
@@ -248,6 +250,8 @@
                     parent_tag='google_chrome', sync_type=PREFERENCE),
       PermanentItem('google_chrome_autofill', name='Autofill',
                     parent_tag='google_chrome', sync_type=AUTOFILL),
+      PermanentItem('google_chrome_autofill_profiles', name='Autofill Profiles',
+                    parent_tag='google_chrome', sync_type=AUTOFILL_PROFILE),
       PermanentItem('google_chrome_extensions', name='Extensions',
                     parent_tag='google_chrome', sync_type=EXTENSIONS),
       PermanentItem('google_chrome_passwords', name='Passwords',
@@ -489,7 +493,7 @@
 
   def _CopyOverImmutableFields(self, entry):
     """Preserve immutable fields by copying pre-commit state.
-    
+
     Args:
       entry: A sync entity from the client.
     """
@@ -611,7 +615,7 @@
     if not self._CheckParentIdForCommit(entry):
       return None
 
-    self._CopyOverImmutableFields(entry);  
+    self._CopyOverImmutableFields(entry);
 
     # At this point, the commit is definitely going to happen.
 
diff --git a/net/tools/testserver/device_management.py b/net/tools/testserver/device_management.py
index d715227..00254c1 100644
--- a/net/tools/testserver/device_management.py
+++ b/net/tools/testserver/device_management.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python2.5
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -7,21 +7,47 @@
 
 This implements a simple cloud policy test server that can be used to test
 chrome's device management service client. The policy information is read from
-from files in a directory. The files should contain policy definitions in JSON
-format, using the top-level dictionary as a key/value store. The format is
-identical to what the Linux implementation reads from /etc. Here is an example:
+the file named device_management in the server's data directory. It contains
+enforced and recommended policies for the device and user scope, and a list
+of managed users.
+
+The format of the file is JSON. The root dictionary contains a list under the
+key "managed_users". It contains auth tokens for which the server will claim
+that the user is managed. The token string "*" indicates that all users are
+claimed to be managed. Other keys in the root dictionary identify request
+scopes. Each request scope is described by a dictionary that holds two
+sub-dictionaries: "mandatory" and "recommended". Both these hold the policy
+definitions as key/value stores, their format is identical to what the Linux
+implementation reads from /etc.
+
+Example:
 
 {
-  "HomepageLocation" : "http://www.chromium.org"
+  "chromeos/device": {
+    "mandatory": {
+      "HomepageLocation" : "http://www.chromium.org"
+    },
+    "recommended": {
+      "JavascriptEnabled": false,
+    },
+  },
+  "managed_users": [
+    "secret123456"
+  ]
 }
 
+
 """
 
 import cgi
 import logging
+import os
 import random
 import re
 import sys
+import time
+import tlslite
+import tlslite.api
 
 # The name and availability of the json module varies in python versions.
 try:
@@ -33,6 +59,8 @@
     json = None
 
 import device_management_backend_pb2 as dm
+import cloud_policy_pb2 as cp
+
 
 class RequestHandler(object):
   """Decodes and handles device management requests from clients.
@@ -95,9 +123,29 @@
       return self.ProcessUnregister(rmsg.unregister_request)
     elif request_type == 'policy':
       return self.ProcessPolicy(rmsg.policy_request)
+    elif request_type == 'cloud_policy':
+      return self.ProcessCloudPolicyRequest(rmsg.cloud_policy_request)
+    elif request_type == 'managed_check':
+      return self.ProcessManagedCheck(rmsg.managed_check_request)
     else:
       return (400, 'Invalid request parameter')
 
+  def CheckGoogleLogin(self):
+    """Extracts the GoogleLogin auth token from the HTTP request, and
+    returns it. Returns None if the token is not present.
+    """
+    match = re.match('GoogleLogin auth=(\\w+)',
+                     self._headers.getheader('Authorization', ''))
+    if not match:
+      return None
+    return match.group(1)
+
+  def GetDeviceName(self):
+    """Returns the name for the currently authenticated device based on its
+    device id.
+    """
+    return 'chromeos-' + self.GetUniqueParam('deviceid')
+
   def ProcessRegister(self, msg):
     """Handles a register request.
 
@@ -111,11 +159,8 @@
       A tuple of HTTP status code and response data to send to the client.
     """
     # Check the auth token and device ID.
-    match = re.match('GoogleLogin auth=(\\w+)',
-                     self._headers.getheader('Authorization', ''))
-    if not match:
+    if not self.CheckGoogleLogin():
       return (403, 'No authorization')
-    auth_token = match.group(1)
 
     device_id = self.GetUniqueParam('deviceid')
     if not device_id:
@@ -128,6 +173,7 @@
     response = dm.DeviceManagementResponse()
     response.error = dm.DeviceManagementResponse.SUCCESS
     response.register_response.device_management_token = dmtoken
+    response.register_response.device_name = self.GetDeviceName()
 
     self.DumpMessage('Response', response)
 
@@ -162,11 +208,44 @@
 
     return (200, response.SerializeToString())
 
+  def ProcessManagedCheck(self, msg):
+    """Handles a 'managed check' request.
+
+    Queries the list of managed users and responds the client if their user
+    is managed or not.
+
+    Args:
+      msg: The ManagedCheckRequest message received from the client.
+
+    Returns:
+      A tuple of HTTP status code and response data to send to the client.
+    """
+    # Check the management token.
+    auth = self.CheckGoogleLogin()
+    if not auth:
+      return (403, 'No authorization')
+
+    managed_check_response = dm.ManagedCheckResponse()
+    if ('*' in self._server.policy['managed_users'] or
+        auth in self._server.policy['managed_users']):
+      managed_check_response.mode = dm.ManagedCheckResponse.MANAGED;
+    else:
+      managed_check_response.mode = dm.ManagedCheckResponse.UNMANAGED;
+
+    # Prepare and send the response.
+    response = dm.DeviceManagementResponse()
+    response.error = dm.DeviceManagementResponse.SUCCESS
+    response.managed_check_response.CopyFrom(managed_check_response)
+
+    self.DumpMessage('Response', response)
+
+    return (200, response.SerializeToString())
+
   def ProcessPolicy(self, msg):
     """Handles a policy request.
 
     Checks for authorization, encodes the policy into protobuf representation
-    and constructs the repsonse.
+    and constructs the response.
 
     Args:
       msg: The DevicePolicyRequest message received from the client.
@@ -186,11 +265,12 @@
 
     # Respond only if the client requested policy for the cros/device scope,
     # since that's where chrome policy is supposed to live in.
-    if msg.policy_scope == 'chromeos/device':
+    if msg.policy_scope in self._server.policy:
+      policy = self._server.policy[msg.policy_scope]['mandatory']
       setting = response.policy_response.setting.add()
       setting.policy_key = 'chrome-policy'
       policy_value = dm.GenericSetting()
-      for (key, value) in self._server.policy.iteritems():
+      for (key, value) in policy.iteritems():
         entry = policy_value.named_value.add()
         entry.name = key
         entry_value = dm.GenericValue()
@@ -214,6 +294,113 @@
 
     return (200, response.SerializeToString())
 
+  def SetProtobufMessageField(self, group_message, field, field_value):
+    '''Sets a field in a protobuf message.
+
+    Args:
+      group_message: The protobuf message.
+      field: The field of the message to set, it shuold be a member of
+          group_message.DESCRIPTOR.fields.
+      field_value: The value to set.
+    '''
+    if field.label == field.LABEL_REPEATED:
+      assert type(field_value) == list
+      assert field.type == field.TYPE_STRING
+      list_field = group_message.__getattribute__(field.name)
+      for list_item in field_value:
+        list_field.append(list_item)
+    else:
+      # Simple cases:
+      if field.type == field.TYPE_BOOL:
+        assert type(field_value) == bool
+      elif field.type == field.TYPE_STRING:
+        assert type(field_value) == str
+      elif field.type == field.TYPE_INT64:
+        assert type(field_value) == int
+      else:
+        raise Exception('Unknown field type %s' % field.type_name)
+      group_message.__setattr__(field.name, field_value)
+
+  def GatherPolicySettings(self, settings, policies):
+    '''Copies all the policies from a dictionary into a protobuf of type
+    CloudPolicySettings.
+
+    Args:
+      settings: The destination: a CloudPolicySettings protobuf.
+      policies: The source: a dictionary containing policies under keys
+          'recommended' and 'mandatory'.
+    '''
+    for group in settings.DESCRIPTOR.fields:
+      # Create protobuf message for group.
+      group_message = eval('cp.' + group.message_type.name + '()')
+      # We assume that this policy group will be recommended, and only switch
+      # it to mandatory if at least one of its members is mandatory.
+      group_message.policy_options.mode = cp.PolicyOptions.RECOMMENDED
+      # Indicates if at least one field was set in |group_message|.
+      got_fields = False
+      # Iterate over fields of the message and feed them from the
+      # policy config file.
+      for field in group_message.DESCRIPTOR.fields:
+        field_value = None
+        if field.name in policies['mandatory']:
+          group_message.policy_options.mode = cp.PolicyOptions.MANDATORY
+          field_value = policies['mandatory'][field.name]
+        elif field.name in policies['recommended']:
+          field_value = policies['recommended'][field.name]
+        if field_value != None:
+          got_fields = True
+          self.SetProtobufMessageField(group_message, field, field_value)
+      if got_fields:
+        settings.__getattribute__(group.name).CopyFrom(group_message)
+
+  def ProcessCloudPolicyRequest(self, msg):
+    """Handles a cloud policy request. (New protocol for policy requests.)
+
+    Checks for authorization, encodes the policy into protobuf representation,
+    signs it and constructs the repsonse.
+
+    Args:
+      msg: The CloudPolicyRequest message received from the client.
+
+    Returns:
+      A tuple of HTTP status code and response data to send to the client.
+    """
+    token, response = self.CheckToken()
+    if not token:
+      return response
+
+    settings = cp.CloudPolicySettings()
+
+    if msg.policy_scope in self._server.policy:
+      # Respond is only given if the scope is specified in the config file.
+      # Normally 'chromeos/device' and 'chromeos/user' should be accepted.
+      self.GatherPolicySettings(settings,
+                                self._server.policy[msg.policy_scope])
+
+    # Construct response
+    signed_response = dm.SignedCloudPolicyResponse()
+    signed_response.settings.CopyFrom(settings)
+    signed_response.timestamp = int(time.time())
+    signed_response.request_token = token;
+    signed_response.device_name = self.GetDeviceName()
+
+    cloud_response = dm.CloudPolicyResponse()
+    cloud_response.signed_response = signed_response.SerializeToString()
+    signed_data = cloud_response.signed_response
+    cloud_response.signature = (
+        self._server.private_key.hashAndSign(signed_data).tostring())
+    for certificate in self._server.cert_chain:
+      cloud_response.certificate_chain.append(
+          certificate.writeBytes().tostring())
+
+    response = dm.DeviceManagementResponse()
+    response.error = dm.DeviceManagementResponse.SUCCESS
+    response.cloud_policy_response.CopyFrom(cloud_response)
+
+    self.DumpMessage('Response', response)
+
+    return (200, response.SerializeToString())
+
   def CheckToken(self):
     """Helper for checking whether the client supplied a valid DM token.
 
@@ -254,11 +441,13 @@
 class TestServer(object):
   """Handles requests and keeps global service state."""
 
-  def __init__(self, policy_path):
+  def __init__(self, policy_path, policy_cert_chain):
     """Initializes the server.
 
     Args:
       policy_path: Names the file to read JSON-formatted policy from.
+      policy_cert_chain: List of paths to X.509 certificate files of the
+          certificate chain used for signing responses.
     """
     self._registered_devices = {}
     self.policy = {}
@@ -270,6 +459,20 @@
       except IOError:
         print 'Failed to load policy from %s' % policy_path
 
+    self.private_key = None
+    self.cert_chain = []
+    for cert_path in policy_cert_chain:
+      try:
+        cert_text = open(cert_path).read()
+      except IOError:
+        print 'Failed to load certificate from %s' % cert_path
+      certificate = tlslite.api.X509()
+      certificate.parse(cert_text)
+      self.cert_chain.append(certificate)
+      if self.private_key is None:
+        self.private_key = tlslite.api.parsePEMKey(cert_text, private=True)
+        assert self.private_key != None
+
   def HandleRequest(self, path, headers, request):
     """Handles a request.
 
diff --git a/net/tools/testserver/run_testserver.cc b/net/tools/testserver/run_testserver.cc
index 650b415..bfaa682 100644
--- a/net/tools/testserver/run_testserver.cc
+++ b/net/tools/testserver/run_testserver.cc
@@ -24,10 +24,12 @@
   CommandLine::Init(argc, argv);
   CommandLine* command_line = CommandLine::ForCurrentProcess();
 
-  if (!logging::InitLogging(FILE_PATH_LITERAL("testserver.log"),
-                            logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
-                            logging::LOCK_LOG_FILE,
-                            logging::APPEND_TO_OLD_LOG_FILE)) {
+  if (!logging::InitLogging(
+          FILE_PATH_LITERAL("testserver.log"),
+          logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
+          logging::LOCK_LOG_FILE,
+          logging::APPEND_TO_OLD_LOG_FILE,
+          logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS)) {
     printf("Error: could not initialize logging. Exiting.\n");
     return -1;
   }
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index acfafae..871e540 100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python2.4
-# Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -593,6 +593,26 @@
 
     return True
 
+  def ReadRequestBody(self):
+    """This function reads the body of the current HTTP request, handling
+    both plain and chunked transfer encoded requests."""
+
+    if self.headers.getheader('transfer-encoding') != 'chunked':
+      length = int(self.headers.getheader('content-length'))
+      return self.rfile.read(length)
+
+    # Read the request body as chunks.
+    body = ""
+    while True:
+      line = self.rfile.readline()
+      length = int(line, 16)
+      if length == 0:
+        self.rfile.readline()
+        break
+      body += self.rfile.read(length)
+      self.rfile.read(2)
+    return body
+
   def EchoHandler(self):
     """This handler just echoes back the payload of the request, for testing
     form submission."""
@@ -603,9 +623,7 @@
     self.send_response(200)
     self.send_header('Content-type', 'text/html')
     self.end_headers()
-    length = int(self.headers.getheader('content-length'))
-    request = self.rfile.read(length)
-    self.wfile.write(request)
+    self.wfile.write(self.ReadRequestBody())
     return True
 
   def EchoTitleHandler(self):
@@ -617,8 +635,7 @@
     self.send_response(200)
     self.send_header('Content-type', 'text/html')
     self.end_headers()
-    length = int(self.headers.getheader('content-length'))
-    request = self.rfile.read(length)
+    request = self.ReadRequestBody()
     self.wfile.write('<html><head><title>')
     self.wfile.write(request)
     self.wfile.write('</title></head></html>')
@@ -642,8 +659,7 @@
       '<h1>Request Body:</h1><pre>')
 
     if self.command == 'POST' or self.command == 'PUT':
-      length = int(self.headers.getheader('content-length'))
-      qs = self.rfile.read(length)
+      qs = self.ReadRequestBody()
       params = cgi.parse_qs(qs, keep_blank_values=1)
 
       for param in params:
@@ -745,7 +761,7 @@
 
     # Consume a request body if present.
     if self.command == 'POST' or self.command == 'PUT' :
-      self.rfile.read(int(self.headers.getheader('content-length')))
+      self.ReadRequestBody()
 
     _, _, url_path, _, query, _ = urlparse.urlparse(self.path)
     sub_path = url_path[len(prefix):]
@@ -1262,14 +1278,14 @@
     if not self._ShouldHandleRequest("/device_management"):
       return False
 
-    length = int(self.headers.getheader('content-length'))
-    raw_request = self.rfile.read(length)
+    raw_request = self.ReadRequestBody()
 
     if not self.server._device_management_handler:
       import device_management
       policy_path = os.path.join(self.server.data_dir, 'device_management')
       self.server._device_management_handler = (
-          device_management.TestServer(policy_path))
+          device_management.TestServer(policy_path,
+                                       self.server.policy_cert_chain))
 
     http_response, raw_reply = (
         self.server._device_management_handler.HandleRequest(self.path,
@@ -1373,8 +1389,11 @@
 
 def main(options, args):
   logfile = open('testserver.log', 'w')
-  sys.stdout = FileMultiplexer(sys.stdout, logfile)
   sys.stderr = FileMultiplexer(sys.stderr, logfile)
+  if options.log_to_console:
+    sys.stdout = FileMultiplexer(sys.stdout, logfile)
+  else:
+    sys.stdout = logfile
 
   port = options.port
 
@@ -1404,6 +1423,7 @@
     server.file_root_url = options.file_root_url
     server_data['port'] = server.server_port
     server._device_management_handler = None
+    server.policy_cert_chain = options.policy_cert_chain
   elif options.server_type == SERVER_SYNC:
     server = SyncHTTPServer(('127.0.0.1', port), SyncPageHandler)
     print 'Sync HTTP server started on port %d...' % server.server_port
@@ -1472,6 +1492,11 @@
                            const=SERVER_SYNC, default=SERVER_HTTP,
                            dest='server_type',
                            help='start up a sync server.')
+  option_parser.add_option('', '--log-to-console', action='store_const',
+                           const=True, default=False,
+                           dest='log_to_console',
+                           help='Enables or disables sys.stdout logging to '
+                           'the console.')
   option_parser.add_option('', '--port', default='0', type='int',
                            help='Port used by the server. If unspecified, the '
                            'server will listen on an ephemeral port.')
@@ -1502,6 +1527,13 @@
   option_parser.add_option('', '--startup-pipe', type='int',
                            dest='startup_pipe',
                            help='File handle of pipe to parent process')
+  option_parser.add_option('', '--policy-cert-chain', action='append',
+                           help='Specify a path to a certificate file to sign '
+                                'policy responses. This option may be used '
+                                'multiple times to define a certificate chain. '
+                                'The first element will be used for signing, '
+                                'the last element should be the root '
+                                'certificate.')
   options, args = option_parser.parse_args()
 
   sys.exit(main(options, args))
diff --git a/net/tools/tld_cleanup/tld_cleanup.cc b/net/tools/tld_cleanup/tld_cleanup.cc
index e055577..be723c4 100644
--- a/net/tools/tld_cleanup/tld_cleanup.cc
+++ b/net/tools/tld_cleanup/tld_cleanup.cc
@@ -266,10 +266,12 @@
   FilePath log_filename;
   PathService::Get(base::DIR_EXE, &log_filename);
   log_filename = log_filename.AppendASCII("tld_cleanup.log");
-  logging::InitLogging(log_filename.value().c_str(),
-                       destination,
-                       logging::LOCK_LOG_FILE,
-                       logging::DELETE_OLD_LOG_FILE);
+  logging::InitLogging(
+      log_filename.value().c_str(),
+      destination,
+      logging::LOCK_LOG_FILE,
+      logging::DELETE_OLD_LOG_FILE,
+      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
 
   icu_util::Initialize();
 
diff --git a/net/url_request/https_prober.cc b/net/url_request/https_prober.cc
index bdafcf6..89d1d20 100644
--- a/net/url_request/https_prober.cc
+++ b/net/url_request/https_prober.cc
@@ -10,12 +10,6 @@
 
 namespace net {
 
-HTTPSProber::HTTPSProber() {
-}
-
-HTTPSProber::~HTTPSProber() {
-}
-
 // static
 HTTPSProber* HTTPSProber::GetInstance() {
   return Singleton<HTTPSProber>::get();
@@ -46,26 +40,6 @@
   return true;
 }
 
-void HTTPSProber::Success(net::URLRequest* request) {
-  DoCallback(request, true);
-}
-
-void HTTPSProber::Failure(net::URLRequest* request) {
-  DoCallback(request, false);
-}
-
-void HTTPSProber::DoCallback(net::URLRequest* request, bool result) {
-  std::map<std::string, HTTPSProberDelegate*>::iterator i =
-    inflight_probes_.find(request->original_url().host());
-  DCHECK(i != inflight_probes_.end());
-
-  HTTPSProberDelegate* delegate = i->second;
-  inflight_probes_.erase(i);
-  probed_.insert(request->original_url().host());
-  delete request;
-  delegate->ProbeComplete(result);
-}
-
 void HTTPSProber::OnAuthRequired(net::URLRequest* request,
                                  net::AuthChallengeInfo* auth_info) {
   Success(request);
@@ -89,4 +63,30 @@
   NOTREACHED();
 }
 
+HTTPSProber::HTTPSProber() {
+}
+
+HTTPSProber::~HTTPSProber() {
+}
+
+void HTTPSProber::Success(net::URLRequest* request) {
+  DoCallback(request, true);
+}
+
+void HTTPSProber::Failure(net::URLRequest* request) {
+  DoCallback(request, false);
+}
+
+void HTTPSProber::DoCallback(net::URLRequest* request, bool result) {
+  std::map<std::string, HTTPSProberDelegate*>::iterator i =
+    inflight_probes_.find(request->original_url().host());
+  DCHECK(i != inflight_probes_.end());
+
+  HTTPSProberDelegate* delegate = i->second;
+  inflight_probes_.erase(i);
+  probed_.insert(request->original_url().host());
+  delete request;
+  delegate->ProbeComplete(result);
+}
+
 }  // namespace net
diff --git a/net/url_request/https_prober.h b/net/url_request/https_prober.h
index 6540224..0e2d725 100644
--- a/net/url_request/https_prober.h
+++ b/net/url_request/https_prober.h
@@ -63,6 +63,8 @@
   virtual void OnReadCompleted(net::URLRequest* request, int bytes_read);
 
  private:
+  friend struct DefaultSingletonTraits<HTTPSProber>;
+
   HTTPSProber();
   ~HTTPSProber();
 
@@ -73,7 +75,6 @@
   std::map<std::string, HTTPSProberDelegate*> inflight_probes_;
   std::set<std::string> probed_;
 
-  friend struct DefaultSingletonTraits<HTTPSProber>;
   DISALLOW_COPY_AND_ASSIGN(HTTPSProber);
 };
 
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 26a9da2..c2d0f4f 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -13,6 +13,7 @@
 #include "net/base/net_log.h"
 #include "net/base/ssl_cert_request_info.h"
 #include "net/base/upload_data.h"
+#include "net/http/http_network_delegate.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_util.h"
 #include "net/url_request/url_request_context.h"
@@ -160,6 +161,27 @@
                            expected_modification_time);
 }
 
+void URLRequest::EnableChunkedUpload() {
+  DCHECK(!upload_ || upload_->is_chunked());
+  if (!upload_) {
+    upload_ = new UploadData();
+    upload_->set_is_chunked(true);
+  }
+}
+
+void URLRequest::AppendChunkToUpload(const char* bytes, int bytes_len) {
+  DCHECK(upload_);
+  DCHECK(upload_->is_chunked());
+  DCHECK_GT(bytes_len, 0);
+  upload_->AppendChunk(bytes, bytes_len);
+}
+
+void URLRequest::MarkEndOfChunks() {
+  DCHECK(upload_);
+  DCHECK(upload_->is_chunked());
+  upload_->AppendChunk(NULL, 0);
+}
+
 void URLRequest::set_upload(net::UploadData* upload) {
   upload_ = upload;
 }
@@ -325,6 +347,11 @@
   DCHECK(!is_pending_);
   DCHECK(!job_);
 
+  // TODO(mpcomplete): pass in request ID?
+  // TODO(mpcomplete): allow delegate to potentially delay/cancel request.
+  if (context_ && context_->network_delegate())
+    context_->network_delegate()->OnBeforeURLRequest(this);
+
   net_log_.BeginEvent(
       net::NetLog::TYPE_URL_REQUEST_START_JOB,
       make_scoped_refptr(new URLRequestStartEventParameters(
@@ -490,7 +517,6 @@
   // one.
   net_log_.EndEvent(net::NetLog::TYPE_URL_REQUEST_START_JOB, NULL);
 
-  job_->Kill();
   OrphanJob();
 
   response_info_ = net::HttpResponseInfo();
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 3561a29..3f399a6 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -58,6 +58,21 @@
 //
 class URLRequest : public base::NonThreadSafe {
  public:
+  // Callback function implemented by protocol handlers to create new jobs.
+  // The factory may return NULL to indicate an error, which will cause other
+  // factories to be queried.  If no factory handles the request, then the
+  // default job will be used.
+  typedef URLRequestJob* (ProtocolFactory)(URLRequest* request,
+                                           const std::string& scheme);
+
+  // HTTP request/response header IDs (via some preprocessor fun) for use with
+  // SetRequestHeaderById and GetResponseHeaderById.
+  enum {
+#define HTTP_ATOM(x) HTTP_ ## x,
+#include "net/http/http_atom_list.h"
+#undef HTTP_ATOM
+  };
+
   // Derive from this class and add your own data members to associate extra
   // information with a URLRequest. Use GetUserData(key) and SetUserData()
   class UserData {
@@ -66,13 +81,6 @@
     virtual ~UserData() {}
   };
 
-  // Callback function implemented by protocol handlers to create new jobs.
-  // The factory may return NULL to indicate an error, which will cause other
-  // factories to be queried.  If no factory handles the request, then the
-  // default job will be used.
-  typedef URLRequestJob* (ProtocolFactory)(URLRequest* request,
-                                           const std::string& scheme);
-
   // This class handles network interception.  Use with
   // (Un)RegisterRequestInterceptor.
   class Interceptor {
@@ -312,6 +320,20 @@
     AppendFileRangeToUpload(file_path, 0, kuint64max, base::Time());
   }
 
+  // Indicates that the request body should be sent using chunked transfer
+  // encoding. This method may only be called before Start() is called.
+  void EnableChunkedUpload();
+
+  // Appends the given bytes to the request's upload data to be sent
+  // immediately via chunked transfer encoding. When all data has been sent,
+  // call MarkEndOfChunks() to indicate the end of upload data.
+  //
+  // This method may be called only after calling EnableChunkedUpload().
+  void AppendChunkToUpload(const char* bytes, int bytes_len);
+
+  // Indicates the end of a chunked transfer encoded request body.
+  void MarkEndOfChunks();
+
   // Set the upload data directly.
   void set_upload(net::UploadData* upload);
 
@@ -509,14 +531,6 @@
   // cancel the request instead, call Cancel().
   void ContinueDespiteLastError();
 
-  // HTTP request/response header IDs (via some preprocessor fun) for use with
-  // SetRequestHeaderById and GetResponseHeaderById.
-  enum {
-#define HTTP_ATOM(x) HTTP_ ## x,
-#include "net/http/http_atom_list.h"
-#undef HTTP_ATOM
-  };
-
   // Returns true if performance profiling should be enabled on the
   // URLRequestJob serving this request.
   bool enable_profiling() const { return enable_profiling_; }
@@ -568,6 +582,7 @@
 
  private:
   friend class URLRequestJob;
+  typedef std::map<const void*, linked_ptr<UserData> > UserDataMap;
 
   void StartJob(URLRequestJob* job);
 
@@ -620,7 +635,6 @@
   bool is_pending_;
 
   // Externally-defined data accessible by key
-  typedef std::map<const void*, linked_ptr<UserData> > UserDataMap;
   UserDataMap user_data_;
 
   // Whether to enable performance profiling on the job serving this request.
diff --git a/net/url_request/url_request_about_job.cc b/net/url_request/url_request_about_job.cc
index b8dab1a..f48e72a 100644
--- a/net/url_request/url_request_about_job.cc
+++ b/net/url_request/url_request_about_job.cc
@@ -12,16 +12,16 @@
 
 namespace net {
 
+URLRequestAboutJob::URLRequestAboutJob(URLRequest* request)
+    : URLRequestJob(request) {
+}
+
 // static
 URLRequestJob* URLRequestAboutJob::Factory(URLRequest* request,
                                            const std::string& scheme) {
   return new URLRequestAboutJob(request);
 }
 
-URLRequestAboutJob::URLRequestAboutJob(URLRequest* request)
-    : URLRequestJob(request) {
-}
-
 void URLRequestAboutJob::Start() {
   // Start reading asynchronously so that all error reporting and data
   // callbacks happen as they would for network requests.
diff --git a/net/url_request/url_request_about_job.h b/net/url_request/url_request_about_job.h
index 7617208..4703830 100644
--- a/net/url_request/url_request_about_job.h
+++ b/net/url_request/url_request_about_job.h
@@ -17,13 +17,14 @@
  public:
   explicit URLRequestAboutJob(URLRequest* request);
 
+  static URLRequest::ProtocolFactory Factory;
+
+  // URLRequestJob:
   virtual void Start();
   virtual bool GetMimeType(std::string* mime_type) const;
 
-  static URLRequest::ProtocolFactory Factory;
-
  private:
-  ~URLRequestAboutJob();
+  virtual ~URLRequestAboutJob();
 
   void StartAsync();
 };
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 8e0f3bd..6eb075c 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -25,6 +25,10 @@
       is_main_(false) {
 }
 
+void URLRequestContext::set_cookie_store(CookieStore* cookie_store) {
+  cookie_store_ = cookie_store;
+}
+
 const std::string& URLRequestContext::GetUserAgent(const GURL& url) const {
   return EmptyString();
 }
@@ -32,8 +36,4 @@
 URLRequestContext::~URLRequestContext() {
 }
 
-void URLRequestContext::set_cookie_store(CookieStore* cookie_store) {
-  cookie_store_ = cookie_store;
-}
-
 }  // namespace net
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index d7e360d..14678e0 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -115,6 +115,11 @@
     return ftp_transaction_factory_;
   }
 
+  void set_network_delegate(HttpNetworkDelegate* network_delegate) {
+    network_delegate_ = network_delegate;
+  }
+  HttpNetworkDelegate* network_delegate() { return network_delegate_; }
+
   // Gets the cookie store for this context (may be null, in which case
   // cookies are not stored).
   CookieStore* cookie_store() { return cookie_store_.get(); }
@@ -197,7 +202,4 @@
 
 }  // namespace net
 
-// TODO(tfarina): Fix the callers and remove this!
-typedef net::URLRequestContext URLRequestContext;
-
 #endif  // NET_URL_REQUEST_URL_REQUEST_CONTEXT_H_
diff --git a/net/url_request/url_request_data_job.cc b/net/url_request/url_request_data_job.cc
index 30b22fb..9e239d3 100644
--- a/net/url_request/url_request_data_job.cc
+++ b/net/url_request/url_request_data_job.cc
@@ -10,16 +10,16 @@
 
 namespace net {
 
+URLRequestDataJob::URLRequestDataJob(URLRequest* request)
+    : URLRequestSimpleJob(request) {
+}
+
 // static
 URLRequestJob* URLRequestDataJob::Factory(URLRequest* request,
                                           const std::string& scheme) {
   return new URLRequestDataJob(request);
 }
 
-URLRequestDataJob::URLRequestDataJob(URLRequest* request)
-    : URLRequestSimpleJob(request) {
-}
-
 bool URLRequestDataJob::GetData(std::string* mime_type,
                                 std::string* charset,
                                 std::string* data) const {
diff --git a/net/url_request/url_request_data_job.h b/net/url_request/url_request_data_job.h
index e00d43c..766296f 100644
--- a/net/url_request/url_request_data_job.h
+++ b/net/url_request/url_request_data_job.h
@@ -19,12 +19,13 @@
  public:
   explicit URLRequestDataJob(URLRequest* request);
 
+  static URLRequest::ProtocolFactory Factory;
+
+  // URLRequestSimpleJob
   virtual bool GetData(std::string* mime_type,
                        std::string* charset,
                        std::string* data) const;
 
-  static URLRequest::ProtocolFactory Factory;
-
  private:
   ~URLRequestDataJob();
 
diff --git a/net/url_request/url_request_file_dir_job.cc b/net/url_request/url_request_file_dir_job.cc
index badb6b8..1cc15be 100644
--- a/net/url_request/url_request_file_dir_job.cc
+++ b/net/url_request/url_request_file_dir_job.cc
@@ -33,20 +33,6 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
 }
 
-URLRequestFileDirJob::~URLRequestFileDirJob() {
-  DCHECK(read_pending_ == false);
-  DCHECK(lister_ == NULL);
-}
-
-void URLRequestFileDirJob::Start() {
-  // Start reading asynchronously so that all error reporting and data
-  // callbacks happen as they would for network requests.
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &URLRequestFileDirJob::StartAsync));
-}
-
 void URLRequestFileDirJob::StartAsync() {
   DCHECK(!lister_);
 
@@ -63,6 +49,15 @@
   NotifyHeadersComplete();
 }
 
+void URLRequestFileDirJob::Start() {
+  // Start reading asynchronously so that all error reporting and data
+  // callbacks happen as they would for network requests.
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &URLRequestFileDirJob::StartAsync));
+}
+
 void URLRequestFileDirJob::Kill() {
   if (canceled_)
     return;
@@ -174,6 +169,11 @@
   Release();  // The Lister is finished; may delete *this*
 }
 
+URLRequestFileDirJob::~URLRequestFileDirJob() {
+  DCHECK(read_pending_ == false);
+  DCHECK(lister_ == NULL);
+}
+
 void URLRequestFileDirJob::CloseLister() {
   if (lister_) {
     lister_->Cancel();
@@ -182,25 +182,6 @@
   }
 }
 
-bool URLRequestFileDirJob::FillReadBuffer(char *buf, int buf_size,
-                                          int *bytes_read) {
-  DCHECK(bytes_read);
-
-  *bytes_read = 0;
-
-  int count = std::min(buf_size, static_cast<int>(data_.size()));
-  if (count) {
-    memcpy(buf, &data_[0], count);
-    data_.erase(0, count);
-    *bytes_read = count;
-    return true;
-  } else if (list_complete_) {
-    // EOF
-    return true;
-  }
-  return false;
-}
-
 void URLRequestFileDirJob::CompleteRead() {
   if (read_pending_) {
     int bytes_read;
@@ -221,4 +202,23 @@
   }
 }
 
+bool URLRequestFileDirJob::FillReadBuffer(char *buf, int buf_size,
+                                          int *bytes_read) {
+  DCHECK(bytes_read);
+
+  *bytes_read = 0;
+
+  int count = std::min(buf_size, static_cast<int>(data_.size()));
+  if (count) {
+    memcpy(buf, &data_[0], count);
+    data_.erase(0, count);
+    *bytes_read = count;
+    return true;
+  } else if (list_complete_) {
+    // EOF
+    return true;
+  }
+  return false;
+}
+
 }  // namespace net
diff --git a/net/url_request/url_request_file_dir_job.h b/net/url_request/url_request_file_dir_job.h
index 2b40a98..f938417 100644
--- a/net/url_request/url_request_file_dir_job.h
+++ b/net/url_request/url_request_file_dir_job.h
@@ -22,9 +22,12 @@
  public:
   URLRequestFileDirJob(URLRequest* request, const FilePath& dir_path);
 
+  bool list_complete() const { return list_complete_; }
+
+  virtual void StartAsync();
+
   // Overridden from URLRequestJob:
   virtual void Start();
-  virtual void StartAsync();
   virtual void Kill();
   virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
   virtual bool GetMimeType(std::string* mime_type) const;
@@ -35,12 +38,11 @@
       const DirectoryLister::DirectoryListerData& data);
   virtual void OnListDone(int error);
 
-  bool list_complete() const { return list_complete_; }
-
  private:
   virtual ~URLRequestFileDirJob();
 
   void CloseLister();
+
   // When we have data and a read has been pending, this function
   // will fill the response buffer and notify the request
   // appropriately.
diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc
index adc6f44..0f4c423 100644
--- a/net/url_request/url_request_file_job.cc
+++ b/net/url_request/url_request_file_job.cc
@@ -23,6 +23,7 @@
 #include "base/message_loop.h"
 #include "base/platform_file.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/worker_pool.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
@@ -50,7 +51,7 @@
   void Resolve(const FilePath& file_path) {
     base::PlatformFileInfo file_info;
     bool exists = file_util::GetFileInfo(file_path, &file_info);
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     if (owner_loop_) {
       owner_loop_->PostTask(FROM_HERE, NewRunnableMethod(
           this, &AsyncResolver::ReturnResults, exists, file_info));
@@ -60,7 +61,7 @@
   void Cancel() {
     owner_ = NULL;
 
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     owner_loop_ = NULL;
   }
 
@@ -76,11 +77,22 @@
 
   URLRequestFileJob* owner_;
 
-  Lock lock_;
+  base::Lock lock_;
   MessageLoop* owner_loop_;
 };
 #endif
 
+URLRequestFileJob::URLRequestFileJob(URLRequest* request,
+                                     const FilePath& file_path)
+    : URLRequestJob(request),
+      file_path_(file_path),
+      ALLOW_THIS_IN_INITIALIZER_LIST(
+          io_callback_(this, &URLRequestFileJob::DidRead)),
+      is_directory_(false),
+      remaining_bytes_(0),
+      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+}
+
 // static
 URLRequestJob* URLRequestFileJob::Factory(URLRequest* request,
                                           const std::string& scheme) {
@@ -110,22 +122,33 @@
   return new URLRequestFileJob(request, file_path);
 }
 
-URLRequestFileJob::URLRequestFileJob(URLRequest* request,
-                                     const FilePath& file_path)
-    : URLRequestJob(request),
-      file_path_(file_path),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          io_callback_(this, &URLRequestFileJob::DidRead)),
-      is_directory_(false),
-      remaining_bytes_(0),
-      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
-}
+#if defined(OS_CHROMEOS)
+static const char* const kLocalAccessWhiteList[] = {
+  "/home/chronos/user/Downloads",
+  "/media",
+  "/mnt/partner_partition",
+  "/usr/share/chromeos-assets",
+  "/tmp",
+  "/var/log",
+};
 
-URLRequestFileJob::~URLRequestFileJob() {
-#if defined(OS_WIN)
-  DCHECK(!async_resolver_);
-#endif
+// static
+bool URLRequestFileJob::AccessDisabled(const FilePath& file_path) {
+  if (URLRequest::IsFileAccessAllowed()) {  // for tests.
+    return false;
+  }
+
+  for (size_t i = 0; i < arraysize(kLocalAccessWhiteList); ++i) {
+    const FilePath white_listed_path(kLocalAccessWhiteList[i]);
+    // FilePath::operator== should probably handle trailing seperators.
+    if (white_listed_path == file_path.StripTrailingSeparators() ||
+        white_listed_path.IsParent(file_path)) {
+      return false;
+    }
+  }
+  return true;
 }
+#endif
 
 void URLRequestFileJob::Start() {
 #if defined(OS_WIN)
@@ -203,6 +226,43 @@
   return false;
 }
 
+bool URLRequestFileJob::IsRedirectResponse(GURL* location,
+                                           int* http_status_code) {
+  if (is_directory_) {
+    // This happens when we discovered the file is a directory, so needs a
+    // slash at the end of the path.
+    std::string new_path = request_->url().path();
+    new_path.push_back('/');
+    GURL::Replacements replacements;
+    replacements.SetPathStr(new_path);
+
+    *location = request_->url().ReplaceComponents(replacements);
+    *http_status_code = 301;  // simulate a permanent redirect
+    return true;
+  }
+
+#if defined(OS_WIN)
+  // Follow a Windows shortcut.
+  // We just resolve .lnk file, ignore others.
+  if (!LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
+    return false;
+
+  FilePath new_path = file_path_;
+  bool resolved;
+  resolved = file_util::ResolveShortcut(&new_path);
+
+  // If shortcut is not resolved succesfully, do not redirect.
+  if (!resolved)
+    return false;
+
+  *location = FilePathToFileURL(new_path);
+  *http_status_code = 301;
+  return true;
+#else
+  return false;
+#endif
+}
+
 bool URLRequestFileJob::GetContentEncodings(
     std::vector<Filter::FilterType>* encoding_types) {
   DCHECK(encoding_types->empty());
@@ -244,6 +304,12 @@
   }
 }
 
+URLRequestFileJob::~URLRequestFileJob() {
+#if defined(OS_WIN)
+  DCHECK(!async_resolver_);
+#endif
+}
+
 void URLRequestFileJob::DidResolve(
     bool exists, const base::PlatformFileInfo& file_info) {
 #if defined(OS_WIN)
@@ -322,69 +388,4 @@
   NotifyReadComplete(result);
 }
 
-bool URLRequestFileJob::IsRedirectResponse(GURL* location,
-                                           int* http_status_code) {
-  if (is_directory_) {
-    // This happens when we discovered the file is a directory, so needs a
-    // slash at the end of the path.
-    std::string new_path = request_->url().path();
-    new_path.push_back('/');
-    GURL::Replacements replacements;
-    replacements.SetPathStr(new_path);
-
-    *location = request_->url().ReplaceComponents(replacements);
-    *http_status_code = 301;  // simulate a permanent redirect
-    return true;
-  }
-
-#if defined(OS_WIN)
-  // Follow a Windows shortcut.
-  // We just resolve .lnk file, ignore others.
-  if (!LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
-    return false;
-
-  FilePath new_path = file_path_;
-  bool resolved;
-  resolved = file_util::ResolveShortcut(&new_path);
-
-  // If shortcut is not resolved succesfully, do not redirect.
-  if (!resolved)
-    return false;
-
-  *location = FilePathToFileURL(new_path);
-  *http_status_code = 301;
-  return true;
-#else
-  return false;
-#endif
-}
-
-#if defined(OS_CHROMEOS)
-static const char* const kLocalAccessWhiteList[] = {
-  "/home/chronos/user/Downloads",
-  "/media",
-  "/mnt/partner_partition",
-  "/usr/share/chromeos-assets",
-  "/tmp",
-  "/var/log",
-};
-
-// static
-bool URLRequestFileJob::AccessDisabled(const FilePath& file_path) {
-  if (URLRequest::IsFileAccessAllowed()) {  // for tests.
-    return false;
-  }
-
-  for (size_t i = 0; i < arraysize(kLocalAccessWhiteList); ++i) {
-    const FilePath white_listed_path(kLocalAccessWhiteList[i]);
-    // FilePath::operator== should probably handle trailing seperators.
-    if (white_listed_path == file_path.StripTrailingSeparators() ||
-        white_listed_path.IsParent(file_path)) {
-      return false;
-    }
-  }
-  return true;
-}
-#endif
-
 }  // namespace net
diff --git a/net/url_request/url_request_file_job.h b/net/url_request/url_request_file_job.h
index 1a09b04..4dbcb0b 100644
--- a/net/url_request/url_request_file_job.h
+++ b/net/url_request/url_request_file_job.h
@@ -28,6 +28,13 @@
  public:
   URLRequestFileJob(URLRequest* request, const FilePath& file_path);
 
+  static URLRequest::ProtocolFactory Factory;
+
+#if defined(OS_CHROMEOS)
+  static bool AccessDisabled(const FilePath& file_path);
+#endif
+
+  // URLRequestJob:
   virtual void Start();
   virtual void Kill();
   virtual bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read);
@@ -37,12 +44,6 @@
   virtual bool GetMimeType(std::string* mime_type) const;
   virtual void SetExtraRequestHeaders(const HttpRequestHeaders& headers);
 
-  static URLRequest::ProtocolFactory Factory;
-
-#if defined(OS_CHROMEOS)
-  static bool AccessDisabled(const FilePath& file_path);
-#endif
-
  protected:
   virtual ~URLRequestFileJob();
 
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc
index d52fef5..a076d48 100644
--- a/net/url_request/url_request_filter.cc
+++ b/net/url_request/url_request_filter.cc
@@ -12,12 +12,7 @@
 
 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
 
-// static
-URLRequestFilter* URLRequestFilter::GetInstance() {
-  if (!shared_instance_)
-    shared_instance_ = new URLRequestFilter;
-  return shared_instance_;
-}
+URLRequestFilter::~URLRequestFilter() {}
 
 // static
 net::URLRequestJob* URLRequestFilter::Factory(net::URLRequest* request,
@@ -26,7 +21,12 @@
   return GetInstance()->FindRequestHandler(request, scheme);
 }
 
-URLRequestFilter::~URLRequestFilter() {}
+// static
+URLRequestFilter* URLRequestFilter::GetInstance() {
+  if (!shared_instance_)
+    shared_instance_ = new URLRequestFilter;
+  return shared_instance_;
+}
 
 void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
     const std::string& hostname, net::URLRequest::ProtocolFactory* factory) {
diff --git a/net/url_request/url_request_filter.h b/net/url_request/url_request_filter.h
index 9138b87..ec80cb3 100644
--- a/net/url_request/url_request_filter.h
+++ b/net/url_request/url_request_filter.h
@@ -39,12 +39,12 @@
   typedef base::hash_map<std::string, net::URLRequest::ProtocolFactory*>
       UrlHandlerMap;
 
-  // Singleton instance for use.
-  static URLRequestFilter* GetInstance();
+  ~URLRequestFilter();
 
   static net::URLRequest::ProtocolFactory Factory;
 
-  ~URLRequestFilter();
+  // Singleton instance for use.
+  static URLRequestFilter* GetInstance();
 
   void AddHostnameHandler(const std::string& scheme,
                           const std::string& hostname,
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index ea9b23c..8c170ff 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -29,9 +29,6 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
 }
 
-URLRequestFtpJob::~URLRequestFtpJob() {
-}
-
 // static
 URLRequestJob* URLRequestFtpJob::Factory(URLRequest* request,
                                          const std::string& scheme) {
@@ -55,6 +52,105 @@
   return false;
 }
 
+URLRequestFtpJob::~URLRequestFtpJob() {
+}
+
+void URLRequestFtpJob::StartTransaction() {
+  // Create a transaction.
+  DCHECK(!transaction_.get());
+  DCHECK(request_->context());
+  DCHECK(request_->context()->ftp_transaction_factory());
+
+  transaction_.reset(
+      request_->context()->ftp_transaction_factory()->CreateTransaction());
+
+  // No matter what, we want to report our status as IO pending since we will
+  // be notifying our consumer asynchronously via OnStartCompleted.
+  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+  int rv;
+  if (transaction_.get()) {
+    rv = transaction_->Start(
+        &request_info_, &start_callback_, request_->net_log());
+    if (rv == ERR_IO_PENDING)
+      return;
+  } else {
+    rv = ERR_FAILED;
+  }
+  // The transaction started synchronously, but we need to notify the
+  // URLRequest delegate via the message loop.
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &URLRequestFtpJob::OnStartCompleted, rv));
+}
+
+void URLRequestFtpJob::OnStartCompleted(int result) {
+  // Clear the IO_PENDING status
+  SetStatus(URLRequestStatus());
+
+  // FTP obviously doesn't have HTTP Content-Length header. We have to pass
+  // the content size information manually.
+  set_expected_content_size(
+      transaction_->GetResponseInfo()->expected_content_size);
+
+  if (result == OK) {
+    NotifyHeadersComplete();
+  } else if (transaction_->GetResponseInfo()->needs_auth) {
+    GURL origin = request_->url().GetOrigin();
+    if (server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH) {
+      request_->context()->ftp_auth_cache()->Remove(origin,
+                                                    server_auth_->username,
+                                                    server_auth_->password);
+    } else if (!server_auth_) {
+      server_auth_ = new AuthData();
+    }
+    server_auth_->state = AUTH_STATE_NEED_AUTH;
+
+    FtpAuthCache::Entry* cached_auth =
+        request_->context()->ftp_auth_cache()->Lookup(origin);
+
+    if (cached_auth) {
+      // Retry using cached auth data.
+      SetAuth(cached_auth->username, cached_auth->password);
+    } else {
+      // Prompt for a username/password.
+      NotifyHeadersComplete();
+    }
+  } else {
+    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
+  }
+}
+
+void URLRequestFtpJob::OnReadCompleted(int result) {
+  read_in_progress_ = false;
+  if (result == 0) {
+    NotifyDone(URLRequestStatus());
+  } else if (result < 0) {
+    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
+  } else {
+    // Clear the IO_PENDING status
+    SetStatus(URLRequestStatus());
+  }
+  NotifyReadComplete(result);
+}
+
+void URLRequestFtpJob::RestartTransactionWithAuth() {
+  DCHECK(server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH);
+
+  // No matter what, we want to report our status as IO pending since we will
+  // be notifying our consumer asynchronously via OnStartCompleted.
+  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+
+  int rv = transaction_->RestartWithAuth(server_auth_->username,
+                                         server_auth_->password,
+                                         &start_callback_);
+  if (rv == ERR_IO_PENDING)
+    return;
+
+  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &URLRequestFtpJob::OnStartCompleted, rv));
+}
+
 void URLRequestFtpJob::Start() {
   DCHECK(!transaction_.get());
   request_info_.url = request_->url();
@@ -147,100 +243,4 @@
   return false;
 }
 
-void URLRequestFtpJob::OnStartCompleted(int result) {
-  // Clear the IO_PENDING status
-  SetStatus(URLRequestStatus());
-
-  // FTP obviously doesn't have HTTP Content-Length header. We have to pass
-  // the content size information manually.
-  set_expected_content_size(
-      transaction_->GetResponseInfo()->expected_content_size);
-
-  if (result == OK) {
-    NotifyHeadersComplete();
-  } else if (transaction_->GetResponseInfo()->needs_auth) {
-    GURL origin = request_->url().GetOrigin();
-    if (server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH) {
-      request_->context()->ftp_auth_cache()->Remove(origin,
-                                                    server_auth_->username,
-                                                    server_auth_->password);
-    } else if (!server_auth_) {
-      server_auth_ = new AuthData();
-    }
-    server_auth_->state = AUTH_STATE_NEED_AUTH;
-
-    FtpAuthCache::Entry* cached_auth =
-        request_->context()->ftp_auth_cache()->Lookup(origin);
-
-    if (cached_auth) {
-      // Retry using cached auth data.
-      SetAuth(cached_auth->username, cached_auth->password);
-    } else {
-      // Prompt for a username/password.
-      NotifyHeadersComplete();
-    }
-  } else {
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
-  }
-}
-
-void URLRequestFtpJob::OnReadCompleted(int result) {
-  read_in_progress_ = false;
-  if (result == 0) {
-    NotifyDone(URLRequestStatus());
-  } else if (result < 0) {
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
-  } else {
-    // Clear the IO_PENDING status
-    SetStatus(URLRequestStatus());
-  }
-  NotifyReadComplete(result);
-}
-
-void URLRequestFtpJob::RestartTransactionWithAuth() {
-  DCHECK(server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH);
-
-  // No matter what, we want to report our status as IO pending since we will
-  // be notifying our consumer asynchronously via OnStartCompleted.
-  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
-  int rv = transaction_->RestartWithAuth(server_auth_->username,
-                                         server_auth_->password,
-                                         &start_callback_);
-  if (rv == ERR_IO_PENDING)
-    return;
-
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      this, &URLRequestFtpJob::OnStartCompleted, rv));
-}
-
-void URLRequestFtpJob::StartTransaction() {
-  // Create a transaction.
-  DCHECK(!transaction_.get());
-  DCHECK(request_->context());
-  DCHECK(request_->context()->ftp_transaction_factory());
-
-  transaction_.reset(
-      request_->context()->ftp_transaction_factory()->CreateTransaction());
-
-  // No matter what, we want to report our status as IO pending since we will
-  // be notifying our consumer asynchronously via OnStartCompleted.
-  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-  int rv;
-  if (transaction_.get()) {
-    rv = transaction_->Start(
-        &request_info_, &start_callback_, request_->net_log());
-    if (rv == ERR_IO_PENDING)
-      return;
-  } else {
-    rv = ERR_FAILED;
-  }
-  // The transaction started synchronously, but we need to notify the
-  // URLRequest delegate via the message loop.
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &URLRequestFtpJob::OnStartCompleted, rv));
-}
-
 }  // namespace net
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h
index ed65214..fe85ba3 100644
--- a/net/url_request/url_request_ftp_job.h
+++ b/net/url_request/url_request_ftp_job.h
@@ -24,7 +24,6 @@
 // provides an implementation for FTP.
 class URLRequestFtpJob : public URLRequestJob {
  public:
-
   explicit URLRequestFtpJob(URLRequest* request);
 
   static URLRequestJob* Factory(URLRequest* request,
@@ -36,6 +35,15 @@
  private:
   virtual ~URLRequestFtpJob();
 
+  void StartTransaction();
+
+  void OnStartCompleted(int result);
+  void OnReadCompleted(int result);
+
+  void RestartTransactionWithAuth();
+
+  void LogFtpServerType(char server_type);
+
   // Overridden from URLRequestJob:
   virtual void Start();
   virtual void Kill();
@@ -51,15 +59,6 @@
   virtual uint64 GetUploadProgress() const;
   virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
 
-  void StartTransaction();
-
-  void OnStartCompleted(int result);
-  void OnReadCompleted(int result);
-
-  void RestartTransactionWithAuth();
-
-  void LogFtpServerType(char server_type);
-
   FtpRequestInfo request_info_;
   scoped_ptr<FtpTransaction> transaction_;
 
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 7870320..c7605a3 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -117,6 +117,7 @@
   return new URLRequestHttpJob(request);
 }
 
+
 URLRequestHttpJob::URLRequestHttpJob(URLRequest* request)
     : URLRequestJob(request),
       response_info_(NULL),
@@ -142,484 +143,6 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
 }
 
-URLRequestHttpJob::~URLRequestHttpJob() {
-  DCHECK(!sdch_test_control_ || !sdch_test_activated_);
-  if (!IsCachedContent()) {
-    if (sdch_test_control_)
-      RecordPacketStats(SDCH_EXPERIMENT_HOLDBACK);
-    if (sdch_test_activated_)
-      RecordPacketStats(SDCH_EXPERIMENT_DECODE);
-  }
-  // Make sure SDCH filters are told to emit histogram data while this class
-  // can still service the IsCachedContent() call.
-  DestroyFilters();
-
-  if (sdch_dictionary_url_.is_valid()) {
-    // Prior to reaching the destructor, request_ has been set to a NULL
-    // pointer, so request_->url() is no longer valid in the destructor, and we
-    // use an alternate copy |request_info_.url|.
-    SdchManager* manager = SdchManager::Global();
-    // To be extra safe, since this is a "different time" from when we decided
-    // to get the dictionary, we'll validate that an SdchManager is available.
-    // At shutdown time, care is taken to be sure that we don't delete this
-    // globally useful instance "too soon," so this check is just defensive
-    // coding to assure that IF the system is shutting down, we don't have any
-    // problem if the manager was deleted ahead of time.
-    if (manager)  // Defensive programming.
-      manager->FetchDictionary(request_info_.url, sdch_dictionary_url_);
-  }
-}
-
-void URLRequestHttpJob::SetUpload(UploadData* upload) {
-  DCHECK(!transaction_.get()) << "cannot change once started";
-  request_info_.upload_data = upload;
-}
-
-void URLRequestHttpJob::SetExtraRequestHeaders(
-    const HttpRequestHeaders& headers) {
-  DCHECK(!transaction_.get()) << "cannot change once started";
-  request_info_.extra_headers.CopyFrom(headers);
-}
-
-void URLRequestHttpJob::Start() {
-  DCHECK(!transaction_.get());
-
-  // Ensure that we do not send username and password fields in the referrer.
-  GURL referrer(request_->GetSanitizedReferrer());
-
-  request_info_.url = request_->url();
-  request_info_.referrer = referrer;
-  request_info_.method = request_->method();
-  request_info_.load_flags = request_->load_flags();
-  request_info_.priority = request_->priority();
-
-  if (request_->context()) {
-    request_info_.extra_headers.SetHeader(
-        HttpRequestHeaders::kUserAgent,
-        request_->context()->GetUserAgent(request_->url()));
-  }
-
-  AddExtraHeaders();
-  AddCookieHeaderAndStart();
-}
-
-void URLRequestHttpJob::Kill() {
-  if (!transaction_.get())
-    return;
-
-  DestroyTransaction();
-  URLRequestJob::Kill();
-}
-
-LoadState URLRequestHttpJob::GetLoadState() const {
-  return transaction_.get() ?
-      transaction_->GetLoadState() : LOAD_STATE_IDLE;
-}
-
-uint64 URLRequestHttpJob::GetUploadProgress() const {
-  return transaction_.get() ? transaction_->GetUploadProgress() : 0;
-}
-
-bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
-  DCHECK(transaction_.get());
-
-  if (!response_info_)
-    return false;
-
-  return response_info_->headers->GetMimeType(mime_type);
-}
-
-bool URLRequestHttpJob::GetCharset(std::string* charset) {
-  DCHECK(transaction_.get());
-
-  if (!response_info_)
-    return false;
-
-  return response_info_->headers->GetCharset(charset);
-}
-
-void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
-  DCHECK(request_);
-  DCHECK(transaction_.get());
-
-  if (response_info_)
-    *info = *response_info_;
-}
-
-bool URLRequestHttpJob::GetResponseCookies(
-    std::vector<std::string>* cookies) {
-  DCHECK(transaction_.get());
-
-  if (!response_info_)
-    return false;
-
-  // TODO(darin): Why are we extracting response cookies again?  Perhaps we
-  // should just leverage response_cookies_.
-
-  cookies->clear();
-  FetchResponseCookies(response_info_, cookies);
-  return true;
-}
-
-int URLRequestHttpJob::GetResponseCode() const {
-  DCHECK(transaction_.get());
-
-  if (!response_info_)
-    return -1;
-
-  return response_info_->headers->response_code();
-}
-
-bool URLRequestHttpJob::GetContentEncodings(
-    std::vector<Filter::FilterType>* encoding_types) {
-  DCHECK(transaction_.get());
-  if (!response_info_)
-    return false;
-  DCHECK(encoding_types->empty());
-
-  std::string encoding_type;
-  void* iter = NULL;
-  while (response_info_->headers->EnumerateHeader(&iter, "Content-Encoding",
-                                                  &encoding_type)) {
-    encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
-  }
-
-  // Even if encoding types are empty, there is a chance that we need to add
-  // some decoding, as some proxies strip encoding completely. In such cases,
-  // we may need to add (for example) SDCH filtering (when the context suggests
-  // it is appropriate).
-  Filter::FixupEncodingTypes(*this, encoding_types);
-
-  return !encoding_types->empty();
-}
-
-bool URLRequestHttpJob::IsCachedContent() const {
-  return is_cached_content_;
-}
-
-bool URLRequestHttpJob::IsSdchResponse() const {
-  return sdch_dictionary_advertised_;
-}
-
-bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
-  // We only allow redirects to certain "safe" protocols.  This does not
-  // restrict redirects to externally handled protocols.  Our consumer would
-  // need to take care of those.
-
-  if (!URLRequest::IsHandledURL(location))
-    return true;
-
-  static const char* kSafeSchemes[] = {
-    "http",
-    "https",
-    "ftp"
-  };
-
-  for (size_t i = 0; i < arraysize(kSafeSchemes); ++i) {
-    if (location.SchemeIs(kSafeSchemes[i]))
-      return true;
-  }
-
-  return false;
-}
-
-bool URLRequestHttpJob::NeedsAuth() {
-  int code = GetResponseCode();
-  if (code == -1)
-    return false;
-
-  // Check if we need either Proxy or WWW Authentication.  This could happen
-  // because we either provided no auth info, or provided incorrect info.
-  switch (code) {
-    case 407:
-      if (proxy_auth_state_ == AUTH_STATE_CANCELED)
-        return false;
-      proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
-      return true;
-    case 401:
-      if (server_auth_state_ == AUTH_STATE_CANCELED)
-        return false;
-      server_auth_state_ = AUTH_STATE_NEED_AUTH;
-      return true;
-  }
-  return false;
-}
-
-void URLRequestHttpJob::GetAuthChallengeInfo(
-    scoped_refptr<AuthChallengeInfo>* result) {
-  DCHECK(transaction_.get());
-  DCHECK(response_info_);
-
-  // sanity checks:
-  DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
-         server_auth_state_ == AUTH_STATE_NEED_AUTH);
-  DCHECK(response_info_->headers->response_code() == 401 ||
-         response_info_->headers->response_code() == 407);
-
-  *result = response_info_->auth_challenge;
-}
-
-void URLRequestHttpJob::SetAuth(const string16& username,
-                                const string16& password) {
-  DCHECK(transaction_.get());
-
-  // Proxy gets set first, then WWW.
-  if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
-    proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
-  } else {
-    DCHECK(server_auth_state_ == AUTH_STATE_NEED_AUTH);
-    server_auth_state_ = AUTH_STATE_HAVE_AUTH;
-  }
-
-  RestartTransactionWithAuth(username, password);
-}
-
-void URLRequestHttpJob::RestartTransactionWithAuth(
-    const string16& username,
-    const string16& password) {
-  username_ = username;
-  password_ = password;
-
-  // These will be reset in OnStartCompleted.
-  response_info_ = NULL;
-  response_cookies_.clear();
-
-  // Update the cookies, since the cookie store may have been updated from the
-  // headers in the 401/407. Since cookies were already appended to
-  // extra_headers, we need to strip them out before adding them again.
-  request_info_.extra_headers.RemoveHeader(
-      HttpRequestHeaders::kCookie);
-
-  AddCookieHeaderAndStart();
-}
-
-void URLRequestHttpJob::CancelAuth() {
-  // Proxy gets set first, then WWW.
-  if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
-    proxy_auth_state_ = AUTH_STATE_CANCELED;
-  } else {
-    DCHECK(server_auth_state_ == AUTH_STATE_NEED_AUTH);
-    server_auth_state_ = AUTH_STATE_CANCELED;
-  }
-
-  // These will be reset in OnStartCompleted.
-  response_info_ = NULL;
-  response_cookies_.clear();
-
-  // OK, let the consumer read the error page...
-  //
-  // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
-  // which will cause the consumer to receive OnResponseStarted instead of
-  // OnAuthRequired.
-  //
-  // We have to do this via InvokeLater to avoid "recursing" the consumer.
-  //
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &URLRequestHttpJob::OnStartCompleted, OK));
-}
-
-void URLRequestHttpJob::ContinueWithCertificate(
-    X509Certificate* client_cert) {
-  DCHECK(transaction_.get());
-
-  DCHECK(!response_info_) << "should not have a response yet";
-
-  // No matter what, we want to report our status as IO pending since we will
-  // be notifying our consumer asynchronously via OnStartCompleted.
-  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
-  int rv = transaction_->RestartWithCertificate(client_cert, &start_callback_);
-  if (rv == ERR_IO_PENDING)
-    return;
-
-  // The transaction started synchronously, but we need to notify the
-  // URLRequest delegate via the message loop.
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &URLRequestHttpJob::OnStartCompleted, rv));
-}
-
-void URLRequestHttpJob::ContinueDespiteLastError() {
-  // If the transaction was destroyed, then the job was cancelled.
-  if (!transaction_.get())
-    return;
-
-  DCHECK(!response_info_) << "should not have a response yet";
-
-  // No matter what, we want to report our status as IO pending since we will
-  // be notifying our consumer asynchronously via OnStartCompleted.
-  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
-  int rv = transaction_->RestartIgnoringLastError(&start_callback_);
-  if (rv == ERR_IO_PENDING)
-    return;
-
-  // The transaction started synchronously, but we need to notify the
-  // URLRequest delegate via the message loop.
-  MessageLoop::current()->PostTask(
-      FROM_HERE,
-      method_factory_.NewRunnableMethod(
-          &URLRequestHttpJob::OnStartCompleted, rv));
-}
-
-bool URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size,
-                                    int *bytes_read) {
-  DCHECK_NE(buf_size, 0);
-  DCHECK(bytes_read);
-  DCHECK(!read_in_progress_);
-
-  int rv = transaction_->Read(buf, buf_size, &read_callback_);
-  if (rv >= 0) {
-    *bytes_read = rv;
-    return true;
-  }
-
-  if (rv == ERR_IO_PENDING) {
-    read_in_progress_ = true;
-    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-  } else {
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
-  }
-
-  return false;
-}
-
-void URLRequestHttpJob::StopCaching() {
-  if (transaction_.get())
-    transaction_->StopCaching();
-}
-
-void URLRequestHttpJob::OnCanGetCookiesCompleted(int policy) {
-  // If the request was destroyed, then there is no more work to do.
-  if (request_ && request_->delegate()) {
-    if (request_->context()->cookie_store()) {
-      if (policy == ERR_ACCESS_DENIED) {
-        request_->delegate()->OnGetCookies(request_, true);
-      } else if (policy == OK) {
-        request_->delegate()->OnGetCookies(request_, false);
-        CookieOptions options;
-        options.set_include_httponly();
-        std::string cookies =
-            request_->context()->cookie_store()->GetCookiesWithOptions(
-                request_->url(), options);
-        if (!cookies.empty()) {
-          request_info_.extra_headers.SetHeader(
-              HttpRequestHeaders::kCookie, cookies);
-        }
-      }
-    }
-    // We may have been canceled within OnGetCookies.
-    if (GetStatus().is_success()) {
-      StartTransaction();
-    } else {
-      NotifyCanceled();
-    }
-  }
-  Release();  // Balance AddRef taken in AddCookieHeaderAndStart
-}
-
-void URLRequestHttpJob::OnCanSetCookieCompleted(int policy) {
-  // If the request was destroyed, then there is no more work to do.
-  if (request_ && request_->delegate()) {
-    if (request_->context()->cookie_store()) {
-      if (policy == ERR_ACCESS_DENIED) {
-        request_->delegate()->OnSetCookie(
-            request_,
-            response_cookies_[response_cookies_save_index_],
-            CookieOptions(),
-            true);
-      } else if (policy == OK || policy == OK_FOR_SESSION_ONLY) {
-        // OK to save the current response cookie now.
-        CookieOptions options;
-        options.set_include_httponly();
-        if (policy == OK_FOR_SESSION_ONLY)
-          options.set_force_session();
-        request_->context()->cookie_store()->SetCookieWithOptions(
-            request_->url(), response_cookies_[response_cookies_save_index_],
-            options);
-        request_->delegate()->OnSetCookie(
-            request_,
-            response_cookies_[response_cookies_save_index_],
-            options,
-            false);
-      }
-    }
-    response_cookies_save_index_++;
-    // We may have been canceled within OnSetCookie.
-    if (GetStatus().is_success()) {
-      SaveNextCookie();
-    } else {
-      NotifyCanceled();
-    }
-  }
-  Release();  // Balance AddRef taken in SaveNextCookie
-}
-
-void URLRequestHttpJob::OnStartCompleted(int result) {
-  // If the request was destroyed, then there is no more work to do.
-  if (!request_ || !request_->delegate())
-    return;
-
-  // If the transaction was destroyed, then the job was cancelled, and
-  // we can just ignore this notification.
-  if (!transaction_.get())
-    return;
-
-  // Clear the IO_PENDING status
-  SetStatus(URLRequestStatus());
-
-  if (result == OK) {
-    SaveCookiesAndNotifyHeadersComplete();
-  } else if (ShouldTreatAsCertificateError(result)) {
-    // We encountered an SSL certificate error.  Ask our delegate to decide
-    // what we should do.
-    // TODO(wtc): also pass ssl_info.cert_status, or just pass the whole
-    // ssl_info.
-    request_->delegate()->OnSSLCertificateError(
-        request_, result, transaction_->GetResponseInfo()->ssl_info.cert);
-  } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
-    request_->delegate()->OnCertificateRequested(
-        request_, transaction_->GetResponseInfo()->cert_request_info);
-  } else {
-    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
-  }
-}
-
-void URLRequestHttpJob::OnReadCompleted(int result) {
-  read_in_progress_ = false;
-
-  if (result == 0) {
-    NotifyDone(URLRequestStatus());
-  } else if (result < 0) {
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
-  } else {
-    // Clear the IO_PENDING status
-    SetStatus(URLRequestStatus());
-  }
-
-  NotifyReadComplete(result);
-}
-
-bool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
-  if (!IsCertificateError(result))
-    return false;
-
-  // Check whether our context is using Strict-Transport-Security.
-  if (!context_->transport_security_state())
-    return true;
-
-  TransportSecurityState::DomainState domain_state;
-  // TODO(agl): don't ignore opportunistic mode.
-  const bool r = context_->transport_security_state()->IsEnabledForHost(
-      &domain_state, request_info_.url.host());
-
-  return !r || domain_state.mode ==
-               TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
-}
-
 void URLRequestHttpJob::NotifyHeadersComplete() {
   DCHECK(!response_info_);
 
@@ -696,15 +219,8 @@
     rv = request_->context()->http_transaction_factory()->CreateTransaction(
         &transaction_);
     if (rv == OK) {
-      if (!throttling_entry_->IsDuringExponentialBackoff() ||
-          !net::URLRequestThrottlerManager::GetInstance()->
-              enforce_throttling()) {
-        rv = transaction_->Start(
-            &request_info_, &start_callback_, request_->net_log());
-      } else {
-        // Special error code for the exponential back-off module.
-        rv = ERR_TEMPORARILY_THROTTLED;
-      }
+      rv = transaction_->Start(
+          &request_info_, &start_callback_, request_->net_log());
       // Make sure the context is alive for the duration of the
       // transaction.
       context_ = request_->context();
@@ -780,22 +296,12 @@
   if (context) {
     // Only add default Accept-Language and Accept-Charset if the request
     // didn't have them specified.
-    if (!request_info_.extra_headers.HasHeader(
-        HttpRequestHeaders::kAcceptLanguage)) {
-      request_info_.extra_headers.SetHeader(
-          HttpRequestHeaders::kAcceptLanguage,
-#ifdef ANDROID
-          context->GetAcceptLanguage());
-#else
-          context->accept_language());
-#endif
-    }
-    if (!request_info_.extra_headers.HasHeader(
-        HttpRequestHeaders::kAcceptCharset)) {
-      request_info_.extra_headers.SetHeader(
-          HttpRequestHeaders::kAcceptCharset,
-          context->accept_charset());
-    }
+    request_info_.extra_headers.SetHeaderIfMissing(
+        HttpRequestHeaders::kAcceptLanguage,
+        context->accept_language());
+    request_info_.extra_headers.SetHeaderIfMissing(
+        HttpRequestHeaders::kAcceptCharset,
+        context->accept_charset());
   }
 }
 
@@ -970,4 +476,505 @@
   }
 }
 
+void URLRequestHttpJob::OnCanGetCookiesCompleted(int policy) {
+  // If the request was destroyed, then there is no more work to do.
+  if (request_ && request_->delegate()) {
+    if (request_->context()->cookie_store()) {
+      if (policy == ERR_ACCESS_DENIED) {
+        request_->delegate()->OnGetCookies(request_, true);
+      } else if (policy == OK) {
+        request_->delegate()->OnGetCookies(request_, false);
+        CookieOptions options;
+        options.set_include_httponly();
+        std::string cookies =
+            request_->context()->cookie_store()->GetCookiesWithOptions(
+                request_->url(), options);
+        if (!cookies.empty()) {
+          request_info_.extra_headers.SetHeader(
+              HttpRequestHeaders::kCookie, cookies);
+        }
+      }
+    }
+    // We may have been canceled within OnGetCookies.
+    if (GetStatus().is_success()) {
+      StartTransaction();
+    } else {
+      NotifyCanceled();
+    }
+  }
+  Release();  // Balance AddRef taken in AddCookieHeaderAndStart
+}
+
+void URLRequestHttpJob::OnCanSetCookieCompleted(int policy) {
+  // If the request was destroyed, then there is no more work to do.
+  if (request_ && request_->delegate()) {
+    if (request_->context()->cookie_store()) {
+      if (policy == ERR_ACCESS_DENIED) {
+        request_->delegate()->OnSetCookie(
+            request_,
+            response_cookies_[response_cookies_save_index_],
+            CookieOptions(),
+            true);
+      } else if (policy == OK || policy == OK_FOR_SESSION_ONLY) {
+        // OK to save the current response cookie now.
+        CookieOptions options;
+        options.set_include_httponly();
+        if (policy == OK_FOR_SESSION_ONLY)
+          options.set_force_session();
+        request_->context()->cookie_store()->SetCookieWithOptions(
+            request_->url(), response_cookies_[response_cookies_save_index_],
+            options);
+        request_->delegate()->OnSetCookie(
+            request_,
+            response_cookies_[response_cookies_save_index_],
+            options,
+            false);
+      }
+    }
+    response_cookies_save_index_++;
+    // We may have been canceled within OnSetCookie.
+    if (GetStatus().is_success()) {
+      SaveNextCookie();
+    } else {
+      NotifyCanceled();
+    }
+  }
+  Release();  // Balance AddRef taken in SaveNextCookie
+}
+
+void URLRequestHttpJob::OnStartCompleted(int result) {
+  // If the request was destroyed, then there is no more work to do.
+  if (!request_ || !request_->delegate())
+    return;
+
+  // If the transaction was destroyed, then the job was cancelled, and
+  // we can just ignore this notification.
+  if (!transaction_.get())
+    return;
+
+  // Clear the IO_PENDING status
+  SetStatus(URLRequestStatus());
+
+  if (result == OK) {
+    SaveCookiesAndNotifyHeadersComplete();
+  } else if (ShouldTreatAsCertificateError(result)) {
+    // We encountered an SSL certificate error.  Ask our delegate to decide
+    // what we should do.
+    // TODO(wtc): also pass ssl_info.cert_status, or just pass the whole
+    // ssl_info.
+    request_->delegate()->OnSSLCertificateError(
+        request_, result, transaction_->GetResponseInfo()->ssl_info.cert);
+  } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+    request_->delegate()->OnCertificateRequested(
+        request_, transaction_->GetResponseInfo()->cert_request_info);
+  } else {
+    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
+  }
+}
+
+void URLRequestHttpJob::OnReadCompleted(int result) {
+  read_in_progress_ = false;
+
+  if (result == 0) {
+    NotifyDone(URLRequestStatus());
+  } else if (result < 0) {
+    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
+  } else {
+    // Clear the IO_PENDING status
+    SetStatus(URLRequestStatus());
+  }
+
+  NotifyReadComplete(result);
+}
+
+bool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
+  if (!IsCertificateError(result))
+    return false;
+
+  // Check whether our context is using Strict-Transport-Security.
+  if (!context_->transport_security_state())
+    return true;
+
+  TransportSecurityState::DomainState domain_state;
+  // TODO(agl): don't ignore opportunistic mode.
+  const bool r = context_->transport_security_state()->IsEnabledForHost(
+      &domain_state, request_info_.url.host());
+
+  return !r || domain_state.mode ==
+               TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
+}
+
+void URLRequestHttpJob::RestartTransactionWithAuth(
+    const string16& username,
+    const string16& password) {
+  username_ = username;
+  password_ = password;
+
+  // These will be reset in OnStartCompleted.
+  response_info_ = NULL;
+  response_cookies_.clear();
+
+  // Update the cookies, since the cookie store may have been updated from the
+  // headers in the 401/407. Since cookies were already appended to
+  // extra_headers, we need to strip them out before adding them again.
+  request_info_.extra_headers.RemoveHeader(
+      HttpRequestHeaders::kCookie);
+
+  AddCookieHeaderAndStart();
+}
+
+void URLRequestHttpJob::SetUpload(UploadData* upload) {
+  DCHECK(!transaction_.get()) << "cannot change once started";
+  request_info_.upload_data = upload;
+}
+
+void URLRequestHttpJob::SetExtraRequestHeaders(
+    const HttpRequestHeaders& headers) {
+  DCHECK(!transaction_.get()) << "cannot change once started";
+  request_info_.extra_headers.CopyFrom(headers);
+}
+
+void URLRequestHttpJob::Start() {
+  DCHECK(!transaction_.get());
+
+  // Ensure that we do not send username and password fields in the referrer.
+  GURL referrer(request_->GetSanitizedReferrer());
+
+  request_info_.url = request_->url();
+  request_info_.referrer = referrer;
+  request_info_.method = request_->method();
+  request_info_.load_flags = request_->load_flags();
+  request_info_.priority = request_->priority();
+
+  if (request_->context()) {
+    request_info_.extra_headers.SetHeaderIfMissing(
+        HttpRequestHeaders::kUserAgent,
+        request_->context()->GetUserAgent(request_->url()));
+  }
+
+  AddExtraHeaders();
+  AddCookieHeaderAndStart();
+}
+
+void URLRequestHttpJob::Kill() {
+  if (!transaction_.get())
+    return;
+
+  DestroyTransaction();
+  URLRequestJob::Kill();
+}
+
+LoadState URLRequestHttpJob::GetLoadState() const {
+  return transaction_.get() ?
+      transaction_->GetLoadState() : LOAD_STATE_IDLE;
+}
+
+uint64 URLRequestHttpJob::GetUploadProgress() const {
+  return transaction_.get() ? transaction_->GetUploadProgress() : 0;
+}
+
+bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
+  DCHECK(transaction_.get());
+
+  if (!response_info_)
+    return false;
+
+  return response_info_->headers->GetMimeType(mime_type);
+}
+
+bool URLRequestHttpJob::GetCharset(std::string* charset) {
+  DCHECK(transaction_.get());
+
+  if (!response_info_)
+    return false;
+
+  return response_info_->headers->GetCharset(charset);
+}
+
+void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
+  DCHECK(request_);
+  DCHECK(transaction_.get());
+
+  if (response_info_)
+    *info = *response_info_;
+}
+
+bool URLRequestHttpJob::GetResponseCookies(
+    std::vector<std::string>* cookies) {
+  DCHECK(transaction_.get());
+
+  if (!response_info_)
+    return false;
+
+  // TODO(darin): Why are we extracting response cookies again?  Perhaps we
+  // should just leverage response_cookies_.
+
+  cookies->clear();
+  FetchResponseCookies(response_info_, cookies);
+  return true;
+}
+
+int URLRequestHttpJob::GetResponseCode() const {
+  DCHECK(transaction_.get());
+
+  if (!response_info_)
+    return -1;
+
+  return response_info_->headers->response_code();
+}
+
+bool URLRequestHttpJob::GetContentEncodings(
+    std::vector<Filter::FilterType>* encoding_types) {
+  DCHECK(transaction_.get());
+  if (!response_info_)
+    return false;
+  DCHECK(encoding_types->empty());
+
+  std::string encoding_type;
+  void* iter = NULL;
+  while (response_info_->headers->EnumerateHeader(&iter, "Content-Encoding",
+                                                  &encoding_type)) {
+    encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
+  }
+
+  // Even if encoding types are empty, there is a chance that we need to add
+  // some decoding, as some proxies strip encoding completely. In such cases,
+  // we may need to add (for example) SDCH filtering (when the context suggests
+  // it is appropriate).
+  Filter::FixupEncodingTypes(*this, encoding_types);
+
+  return !encoding_types->empty();
+}
+
+bool URLRequestHttpJob::IsCachedContent() const {
+  return is_cached_content_;
+}
+
+bool URLRequestHttpJob::IsSdchResponse() const {
+  return sdch_dictionary_advertised_;
+}
+
+bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
+  // We only allow redirects to certain "safe" protocols.  This does not
+  // restrict redirects to externally handled protocols.  Our consumer would
+  // need to take care of those.
+
+  if (!URLRequest::IsHandledURL(location))
+    return true;
+
+  static const char* kSafeSchemes[] = {
+    "http",
+    "https",
+    "ftp"
+  };
+
+  for (size_t i = 0; i < arraysize(kSafeSchemes); ++i) {
+    if (location.SchemeIs(kSafeSchemes[i]))
+      return true;
+  }
+
+<<<<<<< HEAD
+  URLRequestContext* context = request_->context();
+  if (context) {
+    // Only add default Accept-Language and Accept-Charset if the request
+    // didn't have them specified.
+    if (!request_info_.extra_headers.HasHeader(
+        HttpRequestHeaders::kAcceptLanguage)) {
+      request_info_.extra_headers.SetHeader(
+          HttpRequestHeaders::kAcceptLanguage,
+#ifdef ANDROID
+          context->GetAcceptLanguage());
+#else
+          context->accept_language());
+#endif
+    }
+    if (!request_info_.extra_headers.HasHeader(
+        HttpRequestHeaders::kAcceptCharset)) {
+      request_info_.extra_headers.SetHeader(
+          HttpRequestHeaders::kAcceptCharset,
+          context->accept_charset());
+    }
+=======
+  return false;
+}
+
+bool URLRequestHttpJob::NeedsAuth() {
+  int code = GetResponseCode();
+  if (code == -1)
+    return false;
+
+  // Check if we need either Proxy or WWW Authentication.  This could happen
+  // because we either provided no auth info, or provided incorrect info.
+  switch (code) {
+    case 407:
+      if (proxy_auth_state_ == AUTH_STATE_CANCELED)
+        return false;
+      proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
+      return true;
+    case 401:
+      if (server_auth_state_ == AUTH_STATE_CANCELED)
+        return false;
+      server_auth_state_ = AUTH_STATE_NEED_AUTH;
+      return true;
+>>>>>>> chromium.org at r11.0.672.0
+  }
+  return false;
+}
+
+void URLRequestHttpJob::GetAuthChallengeInfo(
+    scoped_refptr<AuthChallengeInfo>* result) {
+  DCHECK(transaction_.get());
+  DCHECK(response_info_);
+
+  // sanity checks:
+  DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
+         server_auth_state_ == AUTH_STATE_NEED_AUTH);
+  DCHECK(response_info_->headers->response_code() == 401 ||
+         response_info_->headers->response_code() == 407);
+
+  *result = response_info_->auth_challenge;
+}
+
+void URLRequestHttpJob::SetAuth(const string16& username,
+                                const string16& password) {
+  DCHECK(transaction_.get());
+
+  // Proxy gets set first, then WWW.
+  if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
+    proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
+  } else {
+    DCHECK(server_auth_state_ == AUTH_STATE_NEED_AUTH);
+    server_auth_state_ = AUTH_STATE_HAVE_AUTH;
+  }
+
+  RestartTransactionWithAuth(username, password);
+}
+
+void URLRequestHttpJob::CancelAuth() {
+  // Proxy gets set first, then WWW.
+  if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
+    proxy_auth_state_ = AUTH_STATE_CANCELED;
+  } else {
+    DCHECK(server_auth_state_ == AUTH_STATE_NEED_AUTH);
+    server_auth_state_ = AUTH_STATE_CANCELED;
+  }
+
+  // These will be reset in OnStartCompleted.
+  response_info_ = NULL;
+  response_cookies_.clear();
+
+  // OK, let the consumer read the error page...
+  //
+  // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
+  // which will cause the consumer to receive OnResponseStarted instead of
+  // OnAuthRequired.
+  //
+  // We have to do this via InvokeLater to avoid "recursing" the consumer.
+  //
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &URLRequestHttpJob::OnStartCompleted, OK));
+}
+
+void URLRequestHttpJob::ContinueWithCertificate(
+    X509Certificate* client_cert) {
+  DCHECK(transaction_.get());
+
+  DCHECK(!response_info_) << "should not have a response yet";
+
+  // No matter what, we want to report our status as IO pending since we will
+  // be notifying our consumer asynchronously via OnStartCompleted.
+  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+
+  int rv = transaction_->RestartWithCertificate(client_cert, &start_callback_);
+  if (rv == ERR_IO_PENDING)
+    return;
+
+  // The transaction started synchronously, but we need to notify the
+  // URLRequest delegate via the message loop.
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &URLRequestHttpJob::OnStartCompleted, rv));
+}
+
+void URLRequestHttpJob::ContinueDespiteLastError() {
+  // If the transaction was destroyed, then the job was cancelled.
+  if (!transaction_.get())
+    return;
+
+  DCHECK(!response_info_) << "should not have a response yet";
+
+  // No matter what, we want to report our status as IO pending since we will
+  // be notifying our consumer asynchronously via OnStartCompleted.
+  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+
+  int rv = transaction_->RestartIgnoringLastError(&start_callback_);
+  if (rv == ERR_IO_PENDING)
+    return;
+
+  // The transaction started synchronously, but we need to notify the
+  // URLRequest delegate via the message loop.
+  MessageLoop::current()->PostTask(
+      FROM_HERE,
+      method_factory_.NewRunnableMethod(
+          &URLRequestHttpJob::OnStartCompleted, rv));
+}
+
+bool URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size,
+                                    int *bytes_read) {
+  DCHECK_NE(buf_size, 0);
+  DCHECK(bytes_read);
+  DCHECK(!read_in_progress_);
+
+  int rv = transaction_->Read(buf, buf_size, &read_callback_);
+  if (rv >= 0) {
+    *bytes_read = rv;
+    return true;
+  }
+
+  if (rv == ERR_IO_PENDING) {
+    read_in_progress_ = true;
+    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+  } else {
+    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
+  }
+
+  return false;
+}
+
+void URLRequestHttpJob::StopCaching() {
+  if (transaction_.get())
+    transaction_->StopCaching();
+}
+
+URLRequestHttpJob::~URLRequestHttpJob() {
+  DCHECK(!sdch_test_control_ || !sdch_test_activated_);
+  if (!IsCachedContent()) {
+    if (sdch_test_control_)
+      RecordPacketStats(SDCH_EXPERIMENT_HOLDBACK);
+    if (sdch_test_activated_)
+      RecordPacketStats(SDCH_EXPERIMENT_DECODE);
+  }
+  // Make sure SDCH filters are told to emit histogram data while this class
+  // can still service the IsCachedContent() call.
+  DestroyFilters();
+
+  if (sdch_dictionary_url_.is_valid()) {
+    // Prior to reaching the destructor, request_ has been set to a NULL
+    // pointer, so request_->url() is no longer valid in the destructor, and we
+    // use an alternate copy |request_info_.url|.
+    SdchManager* manager = SdchManager::Global();
+    // To be extra safe, since this is a "different time" from when we decided
+    // to get the dictionary, we'll validate that an SdchManager is available.
+    // At shutdown time, care is taken to be sure that we don't delete this
+    // globally useful instance "too soon," so this check is just defensive
+    // coding to assure that IF the system is shutting down, we don't have any
+    // problem if the manager was deleted ahead of time.
+    if (manager)  // Defensive programming.
+      manager->FetchDictionary(request_info_.url, sdch_dictionary_url_);
+  }
+}
+
 }  // namespace net
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index fbd8baf..3f9356e 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -34,6 +34,31 @@
  protected:
   explicit URLRequestHttpJob(URLRequest* request);
 
+  // Shadows URLRequestJob's version of this method so we can grab cookies.
+  void NotifyHeadersComplete();
+
+  void DestroyTransaction();
+  void StartTransaction();
+  void AddExtraHeaders();
+  void AddCookieHeaderAndStart();
+  void SaveCookiesAndNotifyHeadersComplete();
+  void SaveNextCookie();
+  void FetchResponseCookies(const HttpResponseInfo* response_info,
+                            std::vector<std::string>* cookies);
+
+  // Process the Strict-Transport-Security header, if one exists.
+  void ProcessStrictTransportSecurityHeader();
+
+  void OnCanGetCookiesCompleted(int result);
+  void OnCanSetCookieCompleted(int result);
+  void OnStartCompleted(int result);
+  void OnReadCompleted(int result);
+
+  bool ShouldTreatAsCertificateError(int result);
+
+  void RestartTransactionWithAuth(const string16& username,
+                                  const string16& password);
+
   // Overridden from URLRequestJob:
   virtual void SetUpload(UploadData* upload);
   virtual void SetExtraRequestHeaders(const HttpRequestHeaders& headers);
@@ -61,31 +86,6 @@
   virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
   virtual void StopCaching();
 
-  // Shadows URLRequestJob's version of this method so we can grab cookies.
-  void NotifyHeadersComplete();
-
-  void DestroyTransaction();
-  void StartTransaction();
-  void AddExtraHeaders();
-  void AddCookieHeaderAndStart();
-  void SaveCookiesAndNotifyHeadersComplete();
-  void SaveNextCookie();
-  void FetchResponseCookies(const HttpResponseInfo* response_info,
-                            std::vector<std::string>* cookies);
-
-  // Process the Strict-Transport-Security header, if one exists.
-  void ProcessStrictTransportSecurityHeader();
-
-  void OnCanGetCookiesCompleted(int result);
-  void OnCanSetCookieCompleted(int result);
-  void OnStartCompleted(int result);
-  void OnReadCompleted(int result);
-
-  bool ShouldTreatAsCertificateError(int result);
-
-  void RestartTransactionWithAuth(const string16& username,
-                                  const string16& password);
-
   // Keep a reference to the url request context to be sure it's not deleted
   // before us.
   scoped_refptr<URLRequestContext> context_;
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 0c54c10..ac05127 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -53,10 +53,6 @@
   g_url_request_job_tracker.AddNewJob(this);
 }
 
-URLRequestJob::~URLRequestJob() {
-  g_url_request_job_tracker.RemoveJob(this);
-}
-
 void URLRequestJob::SetUpload(net::UploadData* upload) {
 }
 
@@ -75,6 +71,68 @@
   request_ = NULL;
 }
 
+// This function calls ReadData to get stream data. If a filter exists, passes
+// the data to the attached filter. Then returns the output from filter back to
+// the caller.
+bool URLRequestJob::Read(net::IOBuffer* buf, int buf_size, int *bytes_read) {
+  bool rv = false;
+
+  DCHECK_LT(buf_size, 1000000);  // sanity check
+  DCHECK(buf);
+  DCHECK(bytes_read);
+  DCHECK(filtered_read_buffer_ == NULL);
+  DCHECK_EQ(0, filtered_read_buffer_len_);
+
+  *bytes_read = 0;
+
+  // Skip Filter if not present
+  if (!filter_.get()) {
+    rv = ReadRawDataHelper(buf, buf_size, bytes_read);
+  } else {
+    // Save the caller's buffers while we do IO
+    // in the filter's buffers.
+    filtered_read_buffer_ = buf;
+    filtered_read_buffer_len_ = buf_size;
+
+    if (ReadFilteredData(bytes_read)) {
+      rv = true;   // we have data to return
+    } else {
+      rv = false;  // error, or a new IO is pending
+    }
+  }
+  if (rv && *bytes_read == 0)
+    NotifyDone(URLRequestStatus());
+  return rv;
+}
+
+void URLRequestJob::StopCaching() {
+  // Nothing to do here.
+}
+
+net::LoadState URLRequestJob::GetLoadState() const {
+  return net::LOAD_STATE_IDLE;
+}
+
+uint64 URLRequestJob::GetUploadProgress() const {
+  return 0;
+}
+
+bool URLRequestJob::GetCharset(std::string* charset) {
+  return false;
+}
+
+void URLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
+}
+
+bool URLRequestJob::GetResponseCookies(std::vector<std::string>* cookies) {
+  return false;
+}
+
+bool URLRequestJob::GetContentEncodings(
+    std::vector<Filter::FilterType>* encoding_types) {
+  return false;
+}
+
 void URLRequestJob::SetupFilter() {
   std::vector<Filter::FilterType> encoding_types;
   if (GetContentEncodings(&encoding_types)) {
@@ -158,8 +216,11 @@
   FollowRedirect(redirect_url, redirect_status_code);
 }
 
-int64 URLRequestJob::GetByteReadCount() const {
-  return filter_input_byte_count_;
+URLRequestJobMetrics* URLRequestJob::RetrieveMetrics() {
+  if (is_profiling())
+    return metrics_.release();
+  else
+    return NULL;
 }
 
 bool URLRequestJob::GetMimeType(std::string* mime_type) const {
@@ -177,80 +238,6 @@
   if (!request_)
     return base::Time();
   return request_->request_time();
-};
-
-bool URLRequestJob::IsCachedContent() const {
-  return false;
-}
-
-int URLRequestJob::GetResponseCode() const {
-  return -1;
-}
-
-int URLRequestJob::GetInputStreamBufferSize() const {
-  return kFilterBufSize;
-}
-
-// This function calls ReadData to get stream data. If a filter exists, passes
-// the data to the attached filter. Then returns the output from filter back to
-// the caller.
-bool URLRequestJob::Read(net::IOBuffer* buf, int buf_size, int *bytes_read) {
-  bool rv = false;
-
-  DCHECK_LT(buf_size, 1000000);  // sanity check
-  DCHECK(buf);
-  DCHECK(bytes_read);
-  DCHECK(filtered_read_buffer_ == NULL);
-  DCHECK_EQ(0, filtered_read_buffer_len_);
-
-  *bytes_read = 0;
-
-  // Skip Filter if not present
-  if (!filter_.get()) {
-    rv = ReadRawDataHelper(buf, buf_size, bytes_read);
-  } else {
-    // Save the caller's buffers while we do IO
-    // in the filter's buffers.
-    filtered_read_buffer_ = buf;
-    filtered_read_buffer_len_ = buf_size;
-
-    if (ReadFilteredData(bytes_read)) {
-      rv = true;   // we have data to return
-    } else {
-      rv = false;  // error, or a new IO is pending
-    }
-  }
-  if (rv && *bytes_read == 0)
-    NotifyDone(URLRequestStatus());
-  return rv;
-}
-
-void URLRequestJob::StopCaching() {
-  // Nothing to do here.
-}
-
-net::LoadState URLRequestJob::GetLoadState() const {
-  return net::LOAD_STATE_IDLE;
-}
-
-uint64 URLRequestJob::GetUploadProgress() const {
-  return 0;
-}
-
-bool URLRequestJob::GetCharset(std::string* charset) {
-  return false;
-}
-
-void URLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
-}
-
-bool URLRequestJob::GetResponseCookies(std::vector<std::string>* cookies) {
-  return false;
-}
-
-bool URLRequestJob::GetContentEncodings(
-    std::vector<Filter::FilterType>* encoding_types) {
-  return false;
 }
 
 bool URLRequestJob::IsDownload() const {
@@ -261,471 +248,20 @@
   return false;
 }
 
-bool URLRequestJob::ReadRawDataForFilter(int* bytes_read) {
-  bool rv = false;
-
-  DCHECK(bytes_read);
-  DCHECK(filter_.get());
-
-  *bytes_read = 0;
-
-  // Get more pre-filtered data if needed.
-  // TODO(mbelshe): is it possible that the filter needs *MORE* data
-  //    when there is some data already in the buffer?
-  if (!filter_->stream_data_len() && !is_done()) {
-    net::IOBuffer* stream_buffer = filter_->stream_buffer();
-    int stream_buffer_size = filter_->stream_buffer_size();
-    rv = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read);
-  }
-  return rv;
-}
-
-void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) {
-  g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code);
-
-  int rv = request_->Redirect(location, http_status_code);
-  if (rv != net::OK)
-    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
-}
-
-void URLRequestJob::FilteredDataRead(int bytes_read) {
-  DCHECK(filter_.get());  // don't add data if there is no filter
-  filter_->FlushStreamBuffer(bytes_read);
-}
-
-bool URLRequestJob::ReadFilteredData(int* bytes_read) {
-  DCHECK(filter_.get());  // don't add data if there is no filter
-  DCHECK(filtered_read_buffer_ != NULL);  // we need to have a buffer to fill
-  DCHECK_GT(filtered_read_buffer_len_, 0);  // sanity check
-  DCHECK_LT(filtered_read_buffer_len_, 1000000);  // sanity check
-  DCHECK(raw_read_buffer_ == NULL);  // there should be no raw read buffer yet
-
-  bool rv = false;
-  *bytes_read = 0;
-
-  if (is_done())
-    return true;
-
-  if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) {
-    // We don't have any raw data to work with, so
-    // read from the socket.
-    int filtered_data_read;
-    if (ReadRawDataForFilter(&filtered_data_read)) {
-      if (filtered_data_read > 0) {
-        filter_->FlushStreamBuffer(filtered_data_read);  // Give data to filter.
-      } else {
-        return true;  // EOF
-      }
-    } else {
-      return false;  // IO Pending (or error)
-    }
-  }
-
-  if ((filter_->stream_data_len() || filter_needs_more_output_space_)
-      && !is_done()) {
-    // Get filtered data.
-    int filtered_data_len = filtered_read_buffer_len_;
-    Filter::FilterStatus status;
-    int output_buffer_size = filtered_data_len;
-    status = filter_->ReadData(filtered_read_buffer_->data(),
-                               &filtered_data_len);
-
-    if (filter_needs_more_output_space_ && 0 == filtered_data_len) {
-      // filter_needs_more_output_space_ was mistaken... there are no more bytes
-      // and we should have at least tried to fill up the filter's input buffer.
-      // Correct the state, and try again.
-      filter_needs_more_output_space_ = false;
-      return ReadFilteredData(bytes_read);
-    }
-
-    switch (status) {
-      case Filter::FILTER_DONE: {
-        filter_needs_more_output_space_ = false;
-        *bytes_read = filtered_data_len;
-        rv = true;
-        break;
-      }
-      case Filter::FILTER_NEED_MORE_DATA: {
-        filter_needs_more_output_space_ =
-            (filtered_data_len == output_buffer_size);
-        // We have finished filtering all data currently in the buffer.
-        // There might be some space left in the output buffer. One can
-        // consider reading more data from the stream to feed the filter
-        // and filling up the output buffer. This leads to more complicated
-        // buffer management and data notification mechanisms.
-        // We can revisit this issue if there is a real perf need.
-        if (filtered_data_len > 0) {
-          *bytes_read = filtered_data_len;
-          rv = true;
-        } else {
-          // Read again since we haven't received enough data yet (e.g., we may
-          // not have a complete gzip header yet)
-          rv = ReadFilteredData(bytes_read);
-        }
-        break;
-      }
-      case Filter::FILTER_OK: {
-        filter_needs_more_output_space_ =
-            (filtered_data_len == output_buffer_size);
-        *bytes_read = filtered_data_len;
-        rv = true;
-        break;
-      }
-      case Filter::FILTER_ERROR: {
-        filter_needs_more_output_space_ = false;
-        NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
-                   net::ERR_CONTENT_DECODING_FAILED));
-        rv = false;
-        break;
-      }
-      default: {
-        NOTREACHED();
-        filter_needs_more_output_space_ = false;
-        rv = false;
-        break;
-      }
-    }
-  } else {
-    // we are done, or there is no data left.
-    rv = true;
-  }
-
-  if (rv) {
-    // When we successfully finished a read, we no longer need to
-    // save the caller's buffers. Release our reference.
-    filtered_read_buffer_ = NULL;
-    filtered_read_buffer_len_ = 0;
-  }
-  return rv;
-}
-
-bool URLRequestJob::ReadRawDataHelper(net::IOBuffer* buf, int buf_size,
-                                      int* bytes_read) {
-  DCHECK(!request_->status().is_io_pending());
-  DCHECK(raw_read_buffer_ == NULL);
-
-  // Keep a pointer to the read buffer, so we have access to it in the
-  // OnRawReadComplete() callback in the event that the read completes
-  // asynchronously.
-  raw_read_buffer_ = buf;
-  bool rv = ReadRawData(buf, buf_size, bytes_read);
-
-  if (!request_->status().is_io_pending()) {
-    // If the read completes synchronously, either success or failure,
-    // invoke the OnRawReadComplete callback so we can account for the
-    // completed read.
-    OnRawReadComplete(*bytes_read);
-  }
-  return rv;
-}
-
-bool URLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
-                                int *bytes_read) {
-  DCHECK(bytes_read);
-  *bytes_read = 0;
-  NotifyDone(URLRequestStatus());
+bool URLRequestJob::IsCachedContent() const {
   return false;
 }
 
-URLRequestJobMetrics* URLRequestJob::RetrieveMetrics() {
-  if (is_profiling())
-    return metrics_.release();
-  else
-    return NULL;
+int64 URLRequestJob::GetByteReadCount() const {
+  return filter_input_byte_count_;
 }
 
-void URLRequestJob::NotifyHeadersComplete() {
-  if (!request_ || !request_->delegate())
-    return;  // The request was destroyed, so there is no more work to do.
-
-  if (has_handled_response_)
-    return;
-
-  DCHECK(!request_->status().is_io_pending());
-
-  // Initialize to the current time, and let the subclass optionally override
-  // the time stamps if it has that information.  The default request_time is
-  // set by net::URLRequest before it calls our Start method.
-  request_->response_info_.response_time = Time::Now();
-  GetResponseInfo(&request_->response_info_);
-
-  // When notifying the delegate, the delegate can release the request
-  // (and thus release 'this').  After calling to the delgate, we must
-  // check the request pointer to see if it still exists, and return
-  // immediately if it has been destroyed.  self_preservation ensures our
-  // survival until we can get out of this method.
-  scoped_refptr<URLRequestJob> self_preservation(this);
-
-  GURL new_location;
-  int http_status_code;
-  if (IsRedirectResponse(&new_location, &http_status_code)) {
-    const GURL& url = request_->url();
-
-    // Move the reference fragment of the old location to the new one if the
-    // new one has none. This duplicates mozilla's behavior.
-    if (url.is_valid() && url.has_ref() && !new_location.has_ref()) {
-      GURL::Replacements replacements;
-      // Reference the |ref| directly out of the original URL to avoid a
-      // malloc.
-      replacements.SetRef(url.spec().data(),
-                          url.parsed_for_possibly_invalid_spec().ref);
-      new_location = new_location.ReplaceComponents(replacements);
-    }
-
-    bool defer_redirect = false;
-    request_->ReceivedRedirect(new_location, &defer_redirect);
-
-    // Ensure that the request wasn't detached or destroyed in ReceivedRedirect
-    if (!request_ || !request_->delegate())
-      return;
-
-    // If we were not cancelled, then maybe follow the redirect.
-    if (request_->status().is_success()) {
-      if (defer_redirect) {
-        deferred_redirect_url_ = new_location;
-        deferred_redirect_status_code_ = http_status_code;
-      } else {
-        FollowRedirect(new_location, http_status_code);
-      }
-      return;
-    }
-  } else if (NeedsAuth()) {
-    scoped_refptr<net::AuthChallengeInfo> auth_info;
-    GetAuthChallengeInfo(&auth_info);
-    // Need to check for a NULL auth_info because the server may have failed
-    // to send a challenge with the 401 response.
-    if (auth_info) {
-      request_->delegate()->OnAuthRequired(request_, auth_info);
-      // Wait for SetAuth or CancelAuth to be called.
-      return;
-    }
-  }
-
-  has_handled_response_ = true;
-  if (request_->status().is_success()) {
-    SetupFilter();
-
-    // Check if this content appears to be compressible.
-    std::string mime_type;
-    if (GetMimeType(&mime_type) &&
-        (net::IsSupportedJavascriptMimeType(mime_type.c_str()) ||
-        net::IsSupportedNonImageMimeType(mime_type.c_str()))) {
-      is_compressible_content_ = true;
-    }
-  }
-
-  if (!filter_.get()) {
-    std::string content_length;
-    request_->GetResponseHeaderByName("content-length", &content_length);
-    if (!content_length.empty())
-      base::StringToInt64(content_length, &expected_content_size_);
-  } else {
-    // Chrome today only sends "Accept-Encoding" for compression schemes.
-    // So, if there is a filter on the response, we know that the content
-    // was compressed.
-    is_compressed_ = true;
-  }
-
-  request_->ResponseStarted();
+int URLRequestJob::GetResponseCode() const {
+  return -1;
 }
 
-void URLRequestJob::NotifyStartError(const URLRequestStatus &status) {
-  DCHECK(!has_handled_response_);
-  has_handled_response_ = true;
-  if (request_) {
-    request_->set_status(status);
-    request_->ResponseStarted();
-  }
-}
-
-void URLRequestJob::NotifyReadComplete(int bytes_read) {
-  if (!request_ || !request_->delegate())
-    return;  // The request was destroyed, so there is no more work to do.
-
-  // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome
-  // unit_tests have been fixed to not trip this.
-  //DCHECK(!request_->status().is_io_pending());
-
-  // The headers should be complete before reads complete
-  DCHECK(has_handled_response_);
-
-  OnRawReadComplete(bytes_read);
-
-  // Don't notify if we had an error.
-  if (!request_->status().is_success())
-    return;
-
-  // When notifying the delegate, the delegate can release the request
-  // (and thus release 'this').  After calling to the delgate, we must
-  // check the request pointer to see if it still exists, and return
-  // immediately if it has been destroyed.  self_preservation ensures our
-  // survival until we can get out of this method.
-  scoped_refptr<URLRequestJob> self_preservation(this);
-
-  prefilter_bytes_read_ += bytes_read;
-  if (filter_.get()) {
-    // Tell the filter that it has more data
-    FilteredDataRead(bytes_read);
-
-    // Filter the data.
-    int filter_bytes_read = 0;
-    if (ReadFilteredData(&filter_bytes_read)) {
-      postfilter_bytes_read_ += filter_bytes_read;
-      request_->delegate()->OnReadCompleted(request_, filter_bytes_read);
-    }
-  } else {
-    postfilter_bytes_read_ += bytes_read;
-    request_->delegate()->OnReadCompleted(request_, bytes_read);
-  }
-}
-
-void URLRequestJob::NotifyDone(const URLRequestStatus &status) {
-  DCHECK(!done_) << "Job sending done notification twice";
-  if (done_)
-    return;
-  done_ = true;
-
-  RecordCompressionHistograms();
-
-  if (is_profiling() && metrics_->total_bytes_read_ > 0) {
-    // There are valid IO statistics. Fill in other fields of metrics for
-    // profiling consumers to retrieve information.
-    metrics_->original_url_.reset(new GURL(request_->original_url()));
-    metrics_->end_time_ = TimeTicks::Now();
-    metrics_->success_ = status.is_success();
-
-    if (!(request_->original_url() == request_->url())) {
-      metrics_->url_.reset(new GURL(request_->url()));
-    }
-  } else {
-    metrics_.reset();
-  }
-
-
-  // Unless there was an error, we should have at least tried to handle
-  // the response before getting here.
-  DCHECK(has_handled_response_ || !status.is_success());
-
-  // As with NotifyReadComplete, we need to take care to notice if we were
-  // destroyed during a delegate callback.
-  if (request_) {
-    request_->set_is_pending(false);
-    // With async IO, it's quite possible to have a few outstanding
-    // requests.  We could receive a request to Cancel, followed shortly
-    // by a successful IO.  For tracking the status(), once there is
-    // an error, we do not change the status back to success.  To
-    // enforce this, only set the status if the job is so far
-    // successful.
-    if (request_->status().is_success())
-      request_->set_status(status);
-  }
-
-  g_url_request_job_tracker.OnJobDone(this, status);
-
-  // Complete this notification later.  This prevents us from re-entering the
-  // delegate if we're done because of a synchronous call.
-  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
-      this, &URLRequestJob::CompleteNotifyDone));
-}
-
-void URLRequestJob::CompleteNotifyDone() {
-  // Check if we should notify the delegate that we're done because of an error.
-  if (request_ &&
-      !request_->status().is_success() &&
-      request_->delegate()) {
-    // We report the error differently depending on whether we've called
-    // OnResponseStarted yet.
-    if (has_handled_response_) {
-      // We signal the error by calling OnReadComplete with a bytes_read of -1.
-      request_->delegate()->OnReadCompleted(request_, -1);
-    } else {
-      has_handled_response_ = true;
-      request_->ResponseStarted();
-    }
-  }
-}
-
-void URLRequestJob::NotifyCanceled() {
-  if (!done_) {
-    NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED,
-                                net::ERR_ABORTED));
-  }
-}
-
-void URLRequestJob::NotifyRestartRequired() {
-  DCHECK(!has_handled_response_);
-  if (GetStatus().status() != URLRequestStatus::CANCELED)
-    request_->Restart();
-}
-
-bool URLRequestJob::FilterHasData() {
-    return filter_.get() && filter_->stream_data_len();
-}
-
-void URLRequestJob::OnRawReadComplete(int bytes_read) {
-  DCHECK(raw_read_buffer_);
-  if (bytes_read > 0) {
-    RecordBytesRead(bytes_read);
-  }
-  raw_read_buffer_ = NULL;
-}
-
-void URLRequestJob::RecordBytesRead(int bytes_read) {
-  if (is_profiling()) {
-    ++(metrics_->number_of_read_IO_);
-    metrics_->total_bytes_read_ += bytes_read;
-  }
-  filter_input_byte_count_ += bytes_read;
-  UpdatePacketReadTimes();  // Facilitate stats recording if it is active.
-  g_url_request_job_tracker.OnBytesRead(this, raw_read_buffer_->data(),
-                                        bytes_read);
-}
-
-const URLRequestStatus URLRequestJob::GetStatus() {
-  if (request_)
-    return request_->status();
-  // If the request is gone, we must be cancelled.
-  return URLRequestStatus(URLRequestStatus::CANCELED,
-                          net::ERR_ABORTED);
-}
-
-void URLRequestJob::SetStatus(const URLRequestStatus &status) {
-  if (request_)
-    request_->set_status(status);
-}
-
-void URLRequestJob::UpdatePacketReadTimes() {
-  if (!packet_timing_enabled_)
-    return;
-
-  if (filter_input_byte_count_ <= bytes_observed_in_packets_) {
-    DCHECK(filter_input_byte_count_ == bytes_observed_in_packets_);
-    return;  // No new bytes have arrived.
-  }
-
-  if (!bytes_observed_in_packets_)
-    request_time_snapshot_ = GetRequestTime();
-
-  final_packet_time_ = base::Time::Now();
-  const size_t kTypicalPacketSize = 1430;
-  while (filter_input_byte_count_ > bytes_observed_in_packets_) {
-    ++observed_packet_count_;
-    if (max_packets_timed_ > packet_times_.size()) {
-      packet_times_.push_back(final_packet_time_);
-      DCHECK(static_cast<size_t>(observed_packet_count_) ==
-             packet_times_.size());
-    }
-    bytes_observed_in_packets_ += kTypicalPacketSize;
-  }
-  // Since packets may not be full, we'll remember the number of bytes we've
-  // accounted for in packets thus far.
-  bytes_observed_in_packets_ = filter_input_byte_count_;
-}
-
-void URLRequestJob::EnablePacketCounting(size_t max_packets_timed) {
-  if (max_packets_timed_ < max_packets_timed)
-    max_packets_timed_ = max_packets_timed;
-  packet_timing_enabled_ = true;
+int URLRequestJob::GetInputStreamBufferSize() const {
+  return kFilterBufSize;
 }
 
 void URLRequestJob::RecordPacketStats(StatisticSelector statistic) const {
@@ -862,6 +398,470 @@
   }
 }
 
+URLRequestJob::~URLRequestJob() {
+  g_url_request_job_tracker.RemoveJob(this);
+}
+
+void URLRequestJob::NotifyHeadersComplete() {
+  if (!request_ || !request_->delegate())
+    return;  // The request was destroyed, so there is no more work to do.
+
+  if (has_handled_response_)
+    return;
+
+  DCHECK(!request_->status().is_io_pending());
+
+  // Initialize to the current time, and let the subclass optionally override
+  // the time stamps if it has that information.  The default request_time is
+  // set by net::URLRequest before it calls our Start method.
+  request_->response_info_.response_time = Time::Now();
+  GetResponseInfo(&request_->response_info_);
+
+  // When notifying the delegate, the delegate can release the request
+  // (and thus release 'this').  After calling to the delgate, we must
+  // check the request pointer to see if it still exists, and return
+  // immediately if it has been destroyed.  self_preservation ensures our
+  // survival until we can get out of this method.
+  scoped_refptr<URLRequestJob> self_preservation(this);
+
+  GURL new_location;
+  int http_status_code;
+  if (IsRedirectResponse(&new_location, &http_status_code)) {
+    const GURL& url = request_->url();
+
+    // Move the reference fragment of the old location to the new one if the
+    // new one has none. This duplicates mozilla's behavior.
+    if (url.is_valid() && url.has_ref() && !new_location.has_ref()) {
+      GURL::Replacements replacements;
+      // Reference the |ref| directly out of the original URL to avoid a
+      // malloc.
+      replacements.SetRef(url.spec().data(),
+                          url.parsed_for_possibly_invalid_spec().ref);
+      new_location = new_location.ReplaceComponents(replacements);
+    }
+
+    bool defer_redirect = false;
+    request_->ReceivedRedirect(new_location, &defer_redirect);
+
+    // Ensure that the request wasn't detached or destroyed in ReceivedRedirect
+    if (!request_ || !request_->delegate())
+      return;
+
+    // If we were not cancelled, then maybe follow the redirect.
+    if (request_->status().is_success()) {
+      if (defer_redirect) {
+        deferred_redirect_url_ = new_location;
+        deferred_redirect_status_code_ = http_status_code;
+      } else {
+        FollowRedirect(new_location, http_status_code);
+      }
+      return;
+    }
+  } else if (NeedsAuth()) {
+    scoped_refptr<net::AuthChallengeInfo> auth_info;
+    GetAuthChallengeInfo(&auth_info);
+    // Need to check for a NULL auth_info because the server may have failed
+    // to send a challenge with the 401 response.
+    if (auth_info) {
+      request_->delegate()->OnAuthRequired(request_, auth_info);
+      // Wait for SetAuth or CancelAuth to be called.
+      return;
+    }
+  }
+
+  has_handled_response_ = true;
+  if (request_->status().is_success()) {
+    SetupFilter();
+
+    // Check if this content appears to be compressible.
+    std::string mime_type;
+    if (GetMimeType(&mime_type) &&
+        (net::IsSupportedJavascriptMimeType(mime_type.c_str()) ||
+        net::IsSupportedNonImageMimeType(mime_type.c_str()))) {
+      is_compressible_content_ = true;
+    }
+  }
+
+  if (!filter_.get()) {
+    std::string content_length;
+    request_->GetResponseHeaderByName("content-length", &content_length);
+    if (!content_length.empty())
+      base::StringToInt64(content_length, &expected_content_size_);
+  } else {
+    // Chrome today only sends "Accept-Encoding" for compression schemes.
+    // So, if there is a filter on the response, we know that the content
+    // was compressed.
+    is_compressed_ = true;
+  }
+
+  request_->ResponseStarted();
+}
+
+void URLRequestJob::NotifyReadComplete(int bytes_read) {
+  if (!request_ || !request_->delegate())
+    return;  // The request was destroyed, so there is no more work to do.
+
+  // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome
+  // unit_tests have been fixed to not trip this.
+  //DCHECK(!request_->status().is_io_pending());
+
+  // The headers should be complete before reads complete
+  DCHECK(has_handled_response_);
+
+  OnRawReadComplete(bytes_read);
+
+  // Don't notify if we had an error.
+  if (!request_->status().is_success())
+    return;
+
+  // When notifying the delegate, the delegate can release the request
+  // (and thus release 'this').  After calling to the delgate, we must
+  // check the request pointer to see if it still exists, and return
+  // immediately if it has been destroyed.  self_preservation ensures our
+  // survival until we can get out of this method.
+  scoped_refptr<URLRequestJob> self_preservation(this);
+
+  prefilter_bytes_read_ += bytes_read;
+  if (filter_.get()) {
+    // Tell the filter that it has more data
+    FilteredDataRead(bytes_read);
+
+    // Filter the data.
+    int filter_bytes_read = 0;
+    if (ReadFilteredData(&filter_bytes_read)) {
+      postfilter_bytes_read_ += filter_bytes_read;
+      request_->delegate()->OnReadCompleted(request_, filter_bytes_read);
+    }
+  } else {
+    postfilter_bytes_read_ += bytes_read;
+    request_->delegate()->OnReadCompleted(request_, bytes_read);
+  }
+}
+
+void URLRequestJob::NotifyStartError(const URLRequestStatus &status) {
+  DCHECK(!has_handled_response_);
+  has_handled_response_ = true;
+  if (request_) {
+    request_->set_status(status);
+    request_->ResponseStarted();
+  }
+}
+
+void URLRequestJob::NotifyDone(const URLRequestStatus &status) {
+  DCHECK(!done_) << "Job sending done notification twice";
+  if (done_)
+    return;
+  done_ = true;
+
+  RecordCompressionHistograms();
+
+  if (is_profiling() && metrics_->total_bytes_read_ > 0) {
+    // There are valid IO statistics. Fill in other fields of metrics for
+    // profiling consumers to retrieve information.
+    metrics_->original_url_.reset(new GURL(request_->original_url()));
+    metrics_->end_time_ = TimeTicks::Now();
+    metrics_->success_ = status.is_success();
+
+    if (!(request_->original_url() == request_->url())) {
+      metrics_->url_.reset(new GURL(request_->url()));
+    }
+  } else {
+    metrics_.reset();
+  }
+
+
+  // Unless there was an error, we should have at least tried to handle
+  // the response before getting here.
+  DCHECK(has_handled_response_ || !status.is_success());
+
+  // As with NotifyReadComplete, we need to take care to notice if we were
+  // destroyed during a delegate callback.
+  if (request_) {
+    request_->set_is_pending(false);
+    // With async IO, it's quite possible to have a few outstanding
+    // requests.  We could receive a request to Cancel, followed shortly
+    // by a successful IO.  For tracking the status(), once there is
+    // an error, we do not change the status back to success.  To
+    // enforce this, only set the status if the job is so far
+    // successful.
+    if (request_->status().is_success())
+      request_->set_status(status);
+  }
+
+  g_url_request_job_tracker.OnJobDone(this, status);
+
+  // Complete this notification later.  This prevents us from re-entering the
+  // delegate if we're done because of a synchronous call.
+  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+      this, &URLRequestJob::CompleteNotifyDone));
+}
+
+void URLRequestJob::CompleteNotifyDone() {
+  // Check if we should notify the delegate that we're done because of an error.
+  if (request_ &&
+      !request_->status().is_success() &&
+      request_->delegate()) {
+    // We report the error differently depending on whether we've called
+    // OnResponseStarted yet.
+    if (has_handled_response_) {
+      // We signal the error by calling OnReadComplete with a bytes_read of -1.
+      request_->delegate()->OnReadCompleted(request_, -1);
+    } else {
+      has_handled_response_ = true;
+      request_->ResponseStarted();
+    }
+  }
+}
+
+void URLRequestJob::NotifyCanceled() {
+  if (!done_) {
+    NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED,
+                                net::ERR_ABORTED));
+  }
+}
+
+void URLRequestJob::NotifyRestartRequired() {
+  DCHECK(!has_handled_response_);
+  if (GetStatus().status() != URLRequestStatus::CANCELED)
+    request_->Restart();
+}
+
+bool URLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
+                                int *bytes_read) {
+  DCHECK(bytes_read);
+  *bytes_read = 0;
+  NotifyDone(URLRequestStatus());
+  return false;
+}
+
+void URLRequestJob::FilteredDataRead(int bytes_read) {
+  DCHECK(filter_.get());  // don't add data if there is no filter
+  filter_->FlushStreamBuffer(bytes_read);
+}
+
+bool URLRequestJob::ReadFilteredData(int* bytes_read) {
+  DCHECK(filter_.get());  // don't add data if there is no filter
+  DCHECK(filtered_read_buffer_ != NULL);  // we need to have a buffer to fill
+  DCHECK_GT(filtered_read_buffer_len_, 0);  // sanity check
+  DCHECK_LT(filtered_read_buffer_len_, 1000000);  // sanity check
+  DCHECK(raw_read_buffer_ == NULL);  // there should be no raw read buffer yet
+
+  bool rv = false;
+  *bytes_read = 0;
+
+  if (is_done())
+    return true;
+
+  if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) {
+    // We don't have any raw data to work with, so
+    // read from the socket.
+    int filtered_data_read;
+    if (ReadRawDataForFilter(&filtered_data_read)) {
+      if (filtered_data_read > 0) {
+        filter_->FlushStreamBuffer(filtered_data_read);  // Give data to filter.
+      } else {
+        return true;  // EOF
+      }
+    } else {
+      return false;  // IO Pending (or error)
+    }
+  }
+
+  if ((filter_->stream_data_len() || filter_needs_more_output_space_)
+      && !is_done()) {
+    // Get filtered data.
+    int filtered_data_len = filtered_read_buffer_len_;
+    Filter::FilterStatus status;
+    int output_buffer_size = filtered_data_len;
+    status = filter_->ReadData(filtered_read_buffer_->data(),
+                               &filtered_data_len);
+
+    if (filter_needs_more_output_space_ && 0 == filtered_data_len) {
+      // filter_needs_more_output_space_ was mistaken... there are no more bytes
+      // and we should have at least tried to fill up the filter's input buffer.
+      // Correct the state, and try again.
+      filter_needs_more_output_space_ = false;
+      return ReadFilteredData(bytes_read);
+    }
+
+    switch (status) {
+      case Filter::FILTER_DONE: {
+        filter_needs_more_output_space_ = false;
+        *bytes_read = filtered_data_len;
+        rv = true;
+        break;
+      }
+      case Filter::FILTER_NEED_MORE_DATA: {
+        filter_needs_more_output_space_ =
+            (filtered_data_len == output_buffer_size);
+        // We have finished filtering all data currently in the buffer.
+        // There might be some space left in the output buffer. One can
+        // consider reading more data from the stream to feed the filter
+        // and filling up the output buffer. This leads to more complicated
+        // buffer management and data notification mechanisms.
+        // We can revisit this issue if there is a real perf need.
+        if (filtered_data_len > 0) {
+          *bytes_read = filtered_data_len;
+          rv = true;
+        } else {
+          // Read again since we haven't received enough data yet (e.g., we may
+          // not have a complete gzip header yet)
+          rv = ReadFilteredData(bytes_read);
+        }
+        break;
+      }
+      case Filter::FILTER_OK: {
+        filter_needs_more_output_space_ =
+            (filtered_data_len == output_buffer_size);
+        *bytes_read = filtered_data_len;
+        rv = true;
+        break;
+      }
+      case Filter::FILTER_ERROR: {
+        filter_needs_more_output_space_ = false;
+        NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
+                   net::ERR_CONTENT_DECODING_FAILED));
+        rv = false;
+        break;
+      }
+      default: {
+        NOTREACHED();
+        filter_needs_more_output_space_ = false;
+        rv = false;
+        break;
+      }
+    }
+  } else {
+    // we are done, or there is no data left.
+    rv = true;
+  }
+
+  if (rv) {
+    // When we successfully finished a read, we no longer need to
+    // save the caller's buffers. Release our reference.
+    filtered_read_buffer_ = NULL;
+    filtered_read_buffer_len_ = 0;
+  }
+  return rv;
+}
+
+void URLRequestJob::EnablePacketCounting(size_t max_packets_timed) {
+  if (max_packets_timed_ < max_packets_timed)
+    max_packets_timed_ = max_packets_timed;
+  packet_timing_enabled_ = true;
+}
+
+const URLRequestStatus URLRequestJob::GetStatus() {
+  if (request_)
+    return request_->status();
+  // If the request is gone, we must be cancelled.
+  return URLRequestStatus(URLRequestStatus::CANCELED,
+                          net::ERR_ABORTED);
+}
+
+void URLRequestJob::SetStatus(const URLRequestStatus &status) {
+  if (request_)
+    request_->set_status(status);
+}
+
+bool URLRequestJob::ReadRawDataForFilter(int* bytes_read) {
+  bool rv = false;
+
+  DCHECK(bytes_read);
+  DCHECK(filter_.get());
+
+  *bytes_read = 0;
+
+  // Get more pre-filtered data if needed.
+  // TODO(mbelshe): is it possible that the filter needs *MORE* data
+  //    when there is some data already in the buffer?
+  if (!filter_->stream_data_len() && !is_done()) {
+    net::IOBuffer* stream_buffer = filter_->stream_buffer();
+    int stream_buffer_size = filter_->stream_buffer_size();
+    rv = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read);
+  }
+  return rv;
+}
+
+bool URLRequestJob::ReadRawDataHelper(net::IOBuffer* buf, int buf_size,
+                                      int* bytes_read) {
+  DCHECK(!request_->status().is_io_pending());
+  DCHECK(raw_read_buffer_ == NULL);
+
+  // Keep a pointer to the read buffer, so we have access to it in the
+  // OnRawReadComplete() callback in the event that the read completes
+  // asynchronously.
+  raw_read_buffer_ = buf;
+  bool rv = ReadRawData(buf, buf_size, bytes_read);
+
+  if (!request_->status().is_io_pending()) {
+    // If the read completes synchronously, either success or failure,
+    // invoke the OnRawReadComplete callback so we can account for the
+    // completed read.
+    OnRawReadComplete(*bytes_read);
+  }
+  return rv;
+}
+
+void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) {
+  g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code);
+
+  int rv = request_->Redirect(location, http_status_code);
+  if (rv != net::OK)
+    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
+}
+
+void URLRequestJob::OnRawReadComplete(int bytes_read) {
+  DCHECK(raw_read_buffer_);
+  if (bytes_read > 0) {
+    RecordBytesRead(bytes_read);
+  }
+  raw_read_buffer_ = NULL;
+}
+
+void URLRequestJob::RecordBytesRead(int bytes_read) {
+  if (is_profiling()) {
+    ++(metrics_->number_of_read_IO_);
+    metrics_->total_bytes_read_ += bytes_read;
+  }
+  filter_input_byte_count_ += bytes_read;
+  UpdatePacketReadTimes();  // Facilitate stats recording if it is active.
+  g_url_request_job_tracker.OnBytesRead(this, raw_read_buffer_->data(),
+                                        bytes_read);
+}
+
+bool URLRequestJob::FilterHasData() {
+    return filter_.get() && filter_->stream_data_len();
+}
+
+void URLRequestJob::UpdatePacketReadTimes() {
+  if (!packet_timing_enabled_)
+    return;
+
+  if (filter_input_byte_count_ <= bytes_observed_in_packets_) {
+    DCHECK(filter_input_byte_count_ == bytes_observed_in_packets_);
+    return;  // No new bytes have arrived.
+  }
+
+  if (!bytes_observed_in_packets_)
+    request_time_snapshot_ = GetRequestTime();
+
+  final_packet_time_ = base::Time::Now();
+  const size_t kTypicalPacketSize = 1430;
+  while (filter_input_byte_count_ > bytes_observed_in_packets_) {
+    ++observed_packet_count_;
+    if (max_packets_timed_ > packet_times_.size()) {
+      packet_times_.push_back(final_packet_time_);
+      DCHECK(static_cast<size_t>(observed_packet_count_) ==
+             packet_times_.size());
+    }
+    bytes_observed_in_packets_ += kTypicalPacketSize;
+  }
+  // Since packets may not be full, we'll remember the number of bytes we've
+  // accounted for in packets thus far.
+  bytes_observed_in_packets_ = filter_input_byte_count_;
+}
+
 // The common type of histogram we use for all compression-tracking histograms.
 #define COMPRESSION_HISTOGRAM(name, sample) \
     do { \
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 23a3232..3ac648b 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -129,13 +129,6 @@
   virtual bool GetContentEncodings(
       std::vector<Filter::FilterType>* encoding_types);
 
-  // Find out if this is a download.
-  virtual bool IsDownload() const;
-
-  // Find out if this is a response to a request that advertised an SDCH
-  // dictionary.  Only makes sense for some types of requests.
-  virtual bool IsSdchResponse() const;
-
   // Called to setup stream filter for this request. An example of filter is
   // content encoding/decoding.
   void SetupFilter();
@@ -208,6 +201,8 @@
   virtual bool GetMimeType(std::string* mime_type) const;
   virtual bool GetURL(GURL* gurl) const;
   virtual base::Time GetRequestTime() const;
+  virtual bool IsDownload() const;
+  virtual bool IsSdchResponse() const;
   virtual bool IsCachedContent() const;
   virtual int64 GetByteReadCount() const;
   virtual int GetResponseCode() const;
@@ -277,16 +272,16 @@
   // to get SDCH to emit stats.
   void DestroyFilters() { filter_.reset(); }
 
-  // The request that initiated this job. This value MAY BE NULL if the
-  // request was released by DetachRequest().
-  net::URLRequest* request_;
-
   // The status of the job.
   const net::URLRequestStatus GetStatus();
 
   // Set the status of the job.
   void SetStatus(const net::URLRequestStatus& status);
 
+  // The request that initiated this job. This value MAY BE NULL if the
+  // request was released by DetachRequest().
+  net::URLRequest* request_;
+
   // Whether the job is doing performance profiling
   bool is_profiling_;
 
diff --git a/net/url_request/url_request_job_manager.cc b/net/url_request/url_request_job_manager.cc
index 9f08fd0..caa73ad 100644
--- a/net/url_request/url_request_job_manager.cc
+++ b/net/url_request/url_request_job_manager.cc
@@ -41,15 +41,6 @@
 #endif
 };
 
-URLRequestJobManager::URLRequestJobManager() : enable_file_access_(false) {
-#ifndef NDEBUG
-  allowed_thread_ = 0;
-  allowed_thread_initialized_ = false;
-#endif
-}
-
-URLRequestJobManager::~URLRequestJobManager() {}
-
 // static
 URLRequestJobManager* URLRequestJobManager::GetInstance() {
   return Singleton<URLRequestJobManager>::get();
@@ -154,7 +145,7 @@
 bool URLRequestJobManager::SupportsScheme(const std::string& scheme) const {
   // The set of registered factories may change on another thread.
   {
-    AutoLock locked(lock_);
+    base::AutoLock locked(lock_);
     if (factories_.find(scheme) != factories_.end())
       return true;
   }
@@ -173,7 +164,7 @@
   DCHECK(IsAllowedThread());
 #endif
 
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
 
   net::URLRequest::ProtocolFactory* old_factory;
   FactoryMap::iterator i = factories_.find(scheme);
@@ -196,7 +187,7 @@
   DCHECK(IsAllowedThread());
 #endif
 
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
 
   DCHECK(std::find(interceptors_.begin(), interceptors_.end(), interceptor) ==
          interceptors_.end());
@@ -209,7 +200,7 @@
   DCHECK(IsAllowedThread());
 #endif
 
-  AutoLock locked(lock_);
+  base::AutoLock locked(lock_);
 
   InterceptorList::iterator i =
       std::find(interceptors_.begin(), interceptors_.end(), interceptor);
@@ -217,4 +208,13 @@
   interceptors_.erase(i);
 }
 
+URLRequestJobManager::URLRequestJobManager() : enable_file_access_(false) {
+#ifndef NDEBUG
+  allowed_thread_ = 0;
+  allowed_thread_initialized_ = false;
+#endif
+}
+
+URLRequestJobManager::~URLRequestJobManager() {}
+
 }  // namespace net
diff --git a/net/url_request/url_request_job_manager.h b/net/url_request/url_request_job_manager.h
index 34e3a58..ca9ada9 100644
--- a/net/url_request/url_request_job_manager.h
+++ b/net/url_request/url_request_job_manager.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "base/lock.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 #include "net/url_request/url_request.h"
 
@@ -76,17 +76,7 @@
   URLRequestJobManager();
   ~URLRequestJobManager();
 
-  mutable Lock lock_;
-  FactoryMap factories_;
-  InterceptorList interceptors_;
-  bool enable_file_access_;
-
 #ifndef NDEBUG
-  // We use this to assert that CreateJob and the registration functions all
-  // run on the same thread.
-  mutable base::PlatformThreadId allowed_thread_;
-  mutable bool allowed_thread_initialized_;
-
   // The first guy to call this function sets the allowed thread.  This way we
   // avoid needing to define that thread externally.  Since we expect all
   // callers to be on the same thread, we don't worry about threads racing to
@@ -110,8 +100,18 @@
     return true;
 #endif
   }
+
+  // We use this to assert that CreateJob and the registration functions all
+  // run on the same thread.
+  mutable base::PlatformThreadId allowed_thread_;
+  mutable bool allowed_thread_initialized_;
 #endif
 
+  mutable base::Lock lock_;
+  FactoryMap factories_;
+  InterceptorList interceptors_;
+  bool enable_file_access_;
+
   DISALLOW_COPY_AND_ASSIGN(URLRequestJobManager);
 };
 
diff --git a/net/url_request/url_request_job_tracker.h b/net/url_request/url_request_job_tracker.h
index 4a03cf7..42a146f 100644
--- a/net/url_request/url_request_job_tracker.h
+++ b/net/url_request/url_request_job_tracker.h
@@ -32,6 +32,8 @@
   // The observer's methods are called on the thread that called AddObserver.
   class JobObserver {
    public:
+    virtual ~JobObserver() {}
+
     // Called after the given job has been added to the list
     virtual void OnJobAdded(URLRequestJob* job) = 0;
 
@@ -54,8 +56,6 @@
     // duration of the OnBytesRead callback.
     virtual void OnBytesRead(URLRequestJob* job, const char* buf,
                              int byte_count) = 0;
-
-    virtual ~JobObserver() {}
   };
 
   URLRequestJobTracker();
diff --git a/net/url_request/url_request_job_tracker_unittest.cc b/net/url_request/url_request_job_tracker_unittest.cc
index bd62ef7..df6448b 100644
--- a/net/url_request/url_request_job_tracker_unittest.cc
+++ b/net/url_request/url_request_job_tracker_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -14,7 +14,7 @@
 #include "net/url_request/url_request_job.h"
 #include "net/url_request/url_request_job_tracker.h"
 #include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -54,7 +54,7 @@
   MOCK_METHOD1(OnJobAdded, void(net::URLRequestJob* job));
   MOCK_METHOD1(OnJobRemoved, void(net::URLRequestJob* job));
   MOCK_METHOD2(OnJobDone, void(net::URLRequestJob* job,
-                               const URLRequestStatus& status));
+                               const net::URLRequestStatus& status));
   MOCK_METHOD3(OnJobRedirect, void(net::URLRequestJob* job,
                                    const GURL& location,
                                    int status_code));
@@ -64,7 +64,7 @@
 };
 
 // A net::URLRequestJob that returns static content for given URLs. We do
-// not use URLRequestTestJob here because URLRequestTestJob fakes
+// not use net::URLRequestTestJob here because net::URLRequestTestJob fakes
 // async operations by calling ReadRawData synchronously in an async
 // callback. This test requires a net::URLRequestJob that returns false for
 // async reads, in order to exercise the real async read codepath.
@@ -94,12 +94,12 @@
     response_data_.erase(0, bytes_to_read);
 
     if (async_reads_) {
-      SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+      SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
       MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
           this, &URLRequestJobTrackerTestJob::OnReadCompleted,
           bytes_to_read));
     } else {
-      SetStatus(URLRequestStatus());
+      SetStatus(net::URLRequestStatus());
       *bytes_read = bytes_to_read;
     }
     return !async_reads_;
@@ -107,9 +107,9 @@
 
   void OnReadCompleted(int status) {
     if (status == 0) {
-      NotifyDone(URLRequestStatus());
+      NotifyDone(net::URLRequestStatus());
     } else if (status > 0) {
-      SetStatus(URLRequestStatus());
+      SetStatus(net::URLRequestStatus());
     } else {
       ASSERT_FALSE(true) << "Unexpected OnReadCompleted callback.";
     }
@@ -136,7 +136,7 @@
   const bool async_reads_;
 };
 
-// Google Mock Matcher to check two URLRequestStatus instances for
+// Google Mock Matcher to check two net::URLRequestStatus instances for
 // equality.
 MATCHER_P(StatusEq, other, "") {
   return (arg.status() == other.status() &&
@@ -172,7 +172,8 @@
     EXPECT_CALL(observer, OnBytesRead(NotNull(),
                                       MemEq(body.data(), body.size()),
                                       Eq(static_cast<int>(body.size()))));
-    EXPECT_CALL(observer, OnJobDone(NotNull(), StatusEq(URLRequestStatus())));
+    EXPECT_CALL(observer, OnJobDone(NotNull(),
+                StatusEq(net::URLRequestStatus())));
     EXPECT_CALL(observer, OnJobRemoved(NotNull()));
 
     // Attach our observer and perform the resource fetch.
diff --git a/net/url_request/url_request_status.h b/net/url_request/url_request_status.h
index 332e7e9..1c50cc3 100644
--- a/net/url_request/url_request_status.h
+++ b/net/url_request/url_request_status.h
@@ -68,7 +68,4 @@
 
 }  // namespace net
 
-// TODO(tfarina): Fix the callers and remove this!
-typedef net::URLRequestStatus URLRequestStatus;
-
 #endif  // NET_URL_REQUEST_URL_REQUEST_STATUS_H_
diff --git a/net/url_request/url_request_test_job.cc b/net/url_request/url_request_test_job.cc
index 4aa7c16..0d0bc5d 100644
--- a/net/url_request/url_request_test_job.cc
+++ b/net/url_request/url_request_test_job.cc
@@ -13,13 +13,13 @@
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
 
+namespace net {
+
 // This emulates the global message loop for the test URL request class, since
 // this is only test code, it's probably not too dangerous to have this static
 // object.
 static std::vector< scoped_refptr<URLRequestTestJob> > g_pending_jobs;
 
-namespace net {
-
 // static getters for known URLs
 GURL URLRequestTestJob::test_url_1() {
   return GURL("test:url1");
diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h
index 252c173..133565e 100644
--- a/net/url_request/url_request_test_job.h
+++ b/net/url_request/url_request_test_job.h
@@ -138,7 +138,4 @@
 
 }  // namespace net
 
-// TODO(tfarina): Fix the callers and remove this!
-typedef net::URLRequestTestJob URLRequestTestJob;
-
 #endif  // NET_URL_REQUEST_URL_REQUEST_TEST_JOB_H_
diff --git a/net/url_request/url_request_throttler_entry.cc b/net/url_request/url_request_throttler_entry.cc
index 4abb438..e5da528 100644
--- a/net/url_request/url_request_throttler_entry.cc
+++ b/net/url_request/url_request_throttler_entry.cc
@@ -65,17 +65,36 @@
   Initialize();
 }
 
-URLRequestThrottlerEntry::~URLRequestThrottlerEntry() {
-}
+bool URLRequestThrottlerEntry::IsEntryOutdated() const {
+  if (entry_lifetime_ms_ == -1)
+    return false;
 
-void URLRequestThrottlerEntry::Initialize() {
-  // Since this method is called by the constructors, GetTimeNow() (a virtual
-  // method) is not used.
-  exponential_backoff_release_time_ = base::TimeTicks::Now();
-  failure_count_ = 0;
-  latest_response_was_failure_ = false;
+  base::TimeTicks now = GetTimeNow();
 
-  sliding_window_release_time_ = base::TimeTicks::Now();
+  // If there are send events in the sliding window period, we still need this
+  // entry.
+  if (send_log_.size() > 0 &&
+      send_log_.back() + sliding_window_period_ > now) {
+    return false;
+  }
+
+  int64 unused_since_ms =
+      (now - exponential_backoff_release_time_).InMilliseconds();
+
+  // Release time is further than now, we are managing it.
+  if (unused_since_ms < 0)
+    return false;
+
+  // latest_response_was_failure_ is true indicates that the latest one or
+  // more requests encountered server errors or had malformed response bodies.
+  // In that case, we don't want to collect the entry unless it hasn't been used
+  // for longer than the maximum allowed back-off.
+  if (latest_response_was_failure_)
+    return unused_since_ms > std::max(maximum_backoff_ms_, entry_lifetime_ms_);
+
+  // Otherwise, consider the entry is outdated if it hasn't been used for the
+  // specified lifetime period.
+  return unused_since_ms > entry_lifetime_ms_;
 }
 
 bool URLRequestThrottlerEntry::IsDuringExponentialBackoff() const {
@@ -153,38 +172,6 @@
   }
 }
 
-bool URLRequestThrottlerEntry::IsEntryOutdated() const {
-  if (entry_lifetime_ms_ == -1)
-    return false;
-
-  base::TimeTicks now = GetTimeNow();
-
-  // If there are send events in the sliding window period, we still need this
-  // entry.
-  if (send_log_.size() > 0 &&
-      send_log_.back() + sliding_window_period_ > now) {
-    return false;
-  }
-
-  int64 unused_since_ms =
-      (now - exponential_backoff_release_time_).InMilliseconds();
-
-  // Release time is further than now, we are managing it.
-  if (unused_since_ms < 0)
-    return false;
-
-  // latest_response_was_failure_ is true indicates that the latest one or
-  // more requests encountered server errors or had malformed response bodies.
-  // In that case, we don't want to collect the entry unless it hasn't been used
-  // for longer than the maximum allowed back-off.
-  if (latest_response_was_failure_)
-    return unused_since_ms > std::max(maximum_backoff_ms_, entry_lifetime_ms_);
-
-  // Otherwise, consider the entry is outdated if it hasn't been used for the
-  // specified lifetime period.
-  return unused_since_ms > entry_lifetime_ms_;
-}
-
 void URLRequestThrottlerEntry::ReceivedContentWasMalformed() {
   // For any response that is marked as malformed now, we have probably
   // considered it as a success when receiving it and decreased the failure
@@ -199,6 +186,19 @@
   exponential_backoff_release_time_ = CalculateExponentialBackoffReleaseTime();
 }
 
+URLRequestThrottlerEntry::~URLRequestThrottlerEntry() {
+}
+
+void URLRequestThrottlerEntry::Initialize() {
+  // Since this method is called by the constructors, GetTimeNow() (a virtual
+  // method) is not used.
+  exponential_backoff_release_time_ = base::TimeTicks::Now();
+  failure_count_ = 0;
+  latest_response_was_failure_ = false;
+
+  sliding_window_release_time_ = base::TimeTicks::Now();
+}
+
 base::TimeTicks
     URLRequestThrottlerEntry::CalculateExponentialBackoffReleaseTime() {
   double delay = initial_backoff_ms_;
diff --git a/net/url_request/url_request_throttler_entry.h b/net/url_request/url_request_throttler_entry.h
index ac33fa1..4026237 100644
--- a/net/url_request/url_request_throttler_entry.h
+++ b/net/url_request/url_request_throttler_entry.h
@@ -68,6 +68,10 @@
                            double jitter_factor,
                            int maximum_backoff_ms);
 
+  // Used by the manager, returns true if the entry needs to be garbage
+  // collected.
+  bool IsEntryOutdated() const;
+
   // Implementation of URLRequestThrottlerEntryInterface.
   virtual bool IsDuringExponentialBackoff() const;
   virtual int64 ReserveSendingTimeForNextRequest(
@@ -77,10 +81,6 @@
       const URLRequestThrottlerHeaderInterface* response);
   virtual void ReceivedContentWasMalformed();
 
-  // Used by the manager, returns true if the entry needs to be garbage
-  // collected.
-  bool IsEntryOutdated() const;
-
  protected:
   virtual ~URLRequestThrottlerEntry();
 
diff --git a/net/url_request/url_request_throttler_manager.cc b/net/url_request/url_request_throttler_manager.cc
index 04e05c9..526e4b5 100644
--- a/net/url_request/url_request_throttler_manager.cc
+++ b/net/url_request/url_request_throttler_manager.cc
@@ -4,7 +4,65 @@
 
 #include "net/url_request/url_request_throttler_manager.h"
 
+#include <list>
+
+#include "base/logging.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
+
+namespace {
+
+// AccessLog records threads that have accessed the URLRequestThrottlerManager
+// singleton object.
+// TODO(yzshen): It is used for diagnostic purpose and should be removed once we
+// figure out crbug.com/71721
+class AccessLog {
+ public:
+  static const size_t kAccessLogSize = 4;
+
+  AccessLog() {
+    for (size_t i = 0; i < kAccessLogSize; ++i) {
+      thread_ids_[i] = base::kInvalidThreadId;
+      urls_[i][0] = '\0';
+    }
+  }
+
+  AccessLog(const AccessLog& log) {
+    base::AutoLock auto_lock(log.lock_);
+    for (size_t i = 0; i < kAccessLogSize; ++i) {
+      thread_ids_[i] = log.thread_ids_[i];
+      base::strlcpy(urls_[i], log.urls_[i], kUrlBufferSize);
+    }
+  }
+
+  void Add(base::PlatformThreadId id, const GURL& url) {
+    base::AutoLock auto_lock(lock_);
+    for (size_t i = 0; i < kAccessLogSize; ++i) {
+      if (thread_ids_[i] == id) {
+        return;
+      } else if (thread_ids_[i] == base::kInvalidThreadId) {
+        DCHECK(i == 0);
+        thread_ids_[i] = id;
+        base::strlcpy(urls_[i], url.spec().c_str(), kUrlBufferSize);
+        return;
+      }
+    }
+  }
+
+ private:
+  static const size_t kUrlBufferSize = 128;
+
+  mutable base::Lock lock_;
+  base::PlatformThreadId thread_ids_[kAccessLogSize];
+  // Records the URL argument of the first RegisterRequestUrl() call on each
+  // thread.
+  char urls_[kAccessLogSize][kUrlBufferSize];
+};
+
+AccessLog access_log;
+
+}  // namespace
 
 namespace net {
 
@@ -17,6 +75,9 @@
 
 scoped_refptr<URLRequestThrottlerEntryInterface>
     URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) {
+  if (record_access_log_)
+    access_log.Add(base::PlatformThread::CurrentId(), url);
+
   // Normalize the url.
   std::string url_id = GetIdFromUrl(url);
 
@@ -24,16 +85,52 @@
   GarbageCollectEntriesIfNecessary();
 
   // Find the entry in the map or create it.
-  scoped_refptr<URLRequestThrottlerEntry>& entry = url_entries_[url_id];
-  if (entry == NULL)
-    entry = new URLRequestThrottlerEntry();
+  UrlEntryMap::iterator i = url_entries_.find(url_id);
+  if (i == url_entries_.end()) {
+    scoped_refptr<URLRequestThrottlerEntry> entry(
+        new URLRequestThrottlerEntry());
+    // Explicitly check whether the new operation is successful or not, in order
+    // to track down crbug.com/71721
+    CHECK(entry.get());
 
-  return entry;
+    url_entries_.insert(std::make_pair(url_id, entry));
+    return entry;
+  } else {
+    CHECK(i->second.get());
+    return i->second;
+  }
+}
+
+void URLRequestThrottlerManager::OverrideEntryForTests(
+    const GURL& url,
+    URLRequestThrottlerEntry* entry) {
+  if (entry == NULL)
+    return;
+
+  // Normalize the url.
+  std::string url_id = GetIdFromUrl(url);
+
+  // Periodically garbage collect old entries.
+  GarbageCollectEntriesIfNecessary();
+
+  url_entries_[url_id] = entry;
+}
+
+void URLRequestThrottlerManager::EraseEntryForTests(const GURL& url) {
+  // Normalize the url.
+  std::string url_id = GetIdFromUrl(url);
+  url_entries_.erase(url_id);
+}
+
+void URLRequestThrottlerManager::InitializeOptions(bool enforce_throttling) {
+  enforce_throttling_ = enforce_throttling;
+  record_access_log_ = true;
 }
 
 URLRequestThrottlerManager::URLRequestThrottlerManager()
     : requests_since_last_gc_(0),
-      enforce_throttling_(true) {
+      enforce_throttling_(true),
+      record_access_log_(false) {
 }
 
 URLRequestThrottlerManager::~URLRequestThrottlerManager() {
@@ -58,23 +155,6 @@
   return StringToLowerASCII(id.spec());
 }
 
-void URLRequestThrottlerManager::GarbageCollectEntries() {
-  UrlEntryMap::iterator i = url_entries_.begin();
-
-  while (i != url_entries_.end()) {
-    if ((i->second)->IsEntryOutdated()) {
-      url_entries_.erase(i++);
-    } else {
-      ++i;
-    }
-  }
-
-  // In case something broke we want to make sure not to grow indefinitely.
-  while (url_entries_.size() > kMaximumNumberOfEntries) {
-    url_entries_.erase(url_entries_.begin());
-  }
-}
-
 void URLRequestThrottlerManager::GarbageCollectEntriesIfNecessary() {
   requests_since_last_gc_++;
   if (requests_since_last_gc_ < kRequestsBetweenCollecting)
@@ -84,25 +164,32 @@
   GarbageCollectEntries();
 }
 
-void URLRequestThrottlerManager::OverrideEntryForTests(
-    const GURL& url,
-    URLRequestThrottlerEntry* entry) {
-  if (entry == NULL)
-    return;
+void URLRequestThrottlerManager::GarbageCollectEntries() {
+  volatile AccessLog access_log_copy(access_log);
 
-  // Normalize the url.
-  std::string url_id = GetIdFromUrl(url);
+  // The more efficient way to remove outdated entries is iterating over all the
+  // elements in the map, and removing those outdated ones during the process.
+  // However, one hypothesis about the cause of crbug.com/71721 is that some
+  // kind of iterator error happens when we change the map during iteration. As
+  // a result, we write the code this way in order to track down the bug.
+  std::list<std::string> outdated_keys;
+  for (UrlEntryMap::iterator entry_iter = url_entries_.begin();
+       entry_iter != url_entries_.end(); ++entry_iter) {
+    std::string key = entry_iter->first;
+    CHECK(entry_iter->second.get());
 
-  // Periodically garbage collect old entries.
-  GarbageCollectEntriesIfNecessary();
+    if ((entry_iter->second)->IsEntryOutdated())
+      outdated_keys.push_back(key);
+  }
+  for (std::list<std::string>::iterator key_iter = outdated_keys.begin();
+       key_iter != outdated_keys.end(); ++key_iter) {
+    url_entries_.erase(*key_iter);
+  }
 
-  url_entries_[url_id] = entry;
-}
-
-void URLRequestThrottlerManager::EraseEntryForTests(const GURL& url) {
-  // Normalize the url.
-  std::string url_id = GetIdFromUrl(url);
-  url_entries_.erase(url_id);
+  // In case something broke we want to make sure not to grow indefinitely.
+  while (url_entries_.size() > kMaximumNumberOfEntries) {
+    url_entries_.erase(url_entries_.begin());
+  }
 }
 
 }  // namespace net
diff --git a/net/url_request/url_request_throttler_manager.h b/net/url_request/url_request_throttler_manager.h
index 98211d9..456e84c 100644
--- a/net/url_request/url_request_throttler_manager.h
+++ b/net/url_request/url_request_throttler_manager.h
@@ -49,9 +49,7 @@
   // It is only used by unit tests.
   void EraseEntryForTests(const GURL& url);
 
-  void set_enforce_throttling(bool enforce_throttling) {
-    enforce_throttling_ = enforce_throttling;
-  }
+  void InitializeOptions(bool enforce_throttling);
 
   bool enforce_throttling() const { return enforce_throttling_; }
 
@@ -70,6 +68,7 @@
   // which garbage collecting happens is adjustable with the
   // kRequestBetweenCollecting constant.
   void GarbageCollectEntriesIfNecessary();
+
   // Method that does the actual work of garbage collecting.
   void GarbageCollectEntries();
 
@@ -103,6 +102,12 @@
   // period.
   bool enforce_throttling_;
 
+  // Whether to record threads that have accessed the URLRequestThrottlerManager
+  // singleton object.
+  // TODO(yzshen): It is used for diagnostic purpose and should be removed once
+  // we figure out crbug.com/71721
+  bool record_access_log_;
+
   DISALLOW_COPY_AND_ASSIGN(URLRequestThrottlerManager);
 };
 
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 4be2ec5..26185bd 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -1,9 +1,7 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/url_request/url_request_unittest.h"
-
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
@@ -23,6 +21,7 @@
 #include "base/process_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_piece.h"
+#include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
 #include "net/base/cookie_monster.h"
@@ -47,6 +46,7 @@
 #include "net/url_request/url_request_file_dir_job.h"
 #include "net/url_request/url_request_http_job.h"
 #include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -150,7 +150,7 @@
     }
     uploadBytes[kMsgSize] = '\0';
 
-    scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+    scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
 
     for (int i = 0; i < kIterations; ++i) {
       TestDelegate d;
@@ -176,6 +176,31 @@
     delete[] uploadBytes;
   }
 
+  void AddChunksToUpload(TestURLRequest* r) {
+    r->AppendChunkToUpload("a", 1);
+    r->AppendChunkToUpload("bcd", 3);
+    r->AppendChunkToUpload("this is a longer chunk than before.", 35);
+    r->AppendChunkToUpload("\r\n\r\n", 4);
+    r->AppendChunkToUpload("0", 1);
+    r->AppendChunkToUpload("2323", 4);
+    r->MarkEndOfChunks();
+  }
+
+  void VerifyReceivedDataMatchesChunks(TestURLRequest* r, TestDelegate* d) {
+    // This should match the chunks sent by AddChunksToUpload().
+    const char* expected_data =
+        "abcdthis is a longer chunk than before.\r\n\r\n02323";
+
+    ASSERT_EQ(1, d->response_started_count()) << "request failed: " <<
+        (int) r->status().status() << ", os error: " << r->status().os_error();
+
+    EXPECT_FALSE(d->received_data_before_response());
+
+    ASSERT_EQ(strlen(expected_data), static_cast<size_t>(d->bytes_received()));
+    EXPECT_EQ(0, memcmp(d->data_received().c_str(), expected_data,
+                        strlen(expected_data)));
+  }
+
   net::TestServer test_server_;
 };
 
@@ -197,7 +222,7 @@
 
     MessageLoop::current()->Run();
 
-    EXPECT_EQ(URLRequestStatus::FAILED, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::FAILED, r.status().status());
     EXPECT_EQ(net::ERR_TUNNEL_CONNECTION_FAILED, r.status().os_error());
     EXPECT_EQ(1, d.response_started_count());
     // We should not have followed the redirect.
@@ -222,7 +247,7 @@
 
     MessageLoop::current()->Run();
 
-    EXPECT_EQ(URLRequestStatus::FAILED, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::FAILED, r.status().status());
     EXPECT_EQ(net::ERR_TUNNEL_CONNECTION_FAILED, r.status().os_error());
   }
 }
@@ -475,7 +500,7 @@
     EXPECT_EQ(1, d.response_started_count());
     EXPECT_EQ(0, d.bytes_received());
     EXPECT_FALSE(d.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::CANCELED, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, r.status().status());
   }
 }
 
@@ -499,7 +524,7 @@
     // or it could have been all the bytes.
     // EXPECT_EQ(0, d.bytes_received());
     EXPECT_FALSE(d.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::CANCELED, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, r.status().status());
   }
 }
 
@@ -531,7 +556,7 @@
 TEST_F(URLRequestTestHTTP, CancelTest5) {
   ASSERT_TRUE(test_server_.Start());
 
-  scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+  scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
 
   // populate cache
   {
@@ -540,7 +565,7 @@
     r.set_context(context);
     r.Start();
     MessageLoop::current()->Run();
-    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
   }
 
   // cancel read from cache (see bug 990242)
@@ -552,7 +577,7 @@
     r.Cancel();
     MessageLoop::current()->Run();
 
-    EXPECT_EQ(URLRequestStatus::CANCELED, r.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, r.status().status());
     EXPECT_EQ(1, d.response_started_count());
     EXPECT_EQ(0, d.bytes_received());
     EXPECT_FALSE(d.received_data_before_response());
@@ -638,6 +663,43 @@
   }
 }
 
+TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) {
+  ASSERT_TRUE(test_server_.Start());
+
+  TestDelegate d;
+  {
+    TestURLRequest r(test_server_.GetURL("echo"), &d);
+    r.EnableChunkedUpload();
+    r.set_method("POST");
+    AddChunksToUpload(&r);
+    r.Start();
+    EXPECT_TRUE(r.is_pending());
+
+    MessageLoop::current()->Run();
+
+    VerifyReceivedDataMatchesChunks(&r, &d);
+  }
+}
+
+TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) {
+  ASSERT_TRUE(test_server_.Start());
+
+  TestDelegate d;
+  {
+    TestURLRequest r(test_server_.GetURL("echo"), &d);
+    r.EnableChunkedUpload();
+    r.set_method("POST");
+    r.Start();
+    EXPECT_TRUE(r.is_pending());
+
+    MessageLoop::current()->RunAllPending();
+    AddChunksToUpload(&r);
+    MessageLoop::current()->Run();
+
+    VerifyReceivedDataMatchesChunks(&r, &d);
+  }
+}
+
 TEST_F(URLRequestTest, AboutBlankTest) {
   TestDelegate d;
   {
@@ -1031,7 +1093,7 @@
   req.Start();
   MessageLoop::current()->Run();
 
-  EXPECT_EQ(URLRequestStatus::FAILED, req.status().status());
+  EXPECT_EQ(net::URLRequestStatus::FAILED, req.status().status());
   EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, req.status().os_error());
 }
 
@@ -1044,7 +1106,7 @@
   req.Start();
   MessageLoop::current()->Run();
 
-  EXPECT_EQ(URLRequestStatus::FAILED, req.status().status());
+  EXPECT_EQ(net::URLRequestStatus::FAILED, req.status().status());
   EXPECT_EQ(net::ERR_INVALID_URL, req.status().os_error());
 }
 
@@ -1075,7 +1137,7 @@
     EXPECT_EQ(1, d.response_started_count());
     EXPECT_EQ(0, d.bytes_received());
     EXPECT_FALSE(d.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
   }
 }
 
@@ -1097,7 +1159,7 @@
 
     EXPECT_EQ(1, d.response_started_count());
     EXPECT_FALSE(d.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::SUCCESS, req.status().status());
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS, req.status().status());
 
     FilePath path;
     PathService::Get(base::DIR_SOURCE_ROOT, &path);
@@ -1131,14 +1193,14 @@
     EXPECT_EQ(1, d.response_started_count());
     EXPECT_EQ(0, d.bytes_received());
     EXPECT_FALSE(d.received_data_before_response());
-    EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
   }
 }
 
 TEST_F(URLRequestTestHTTP, VaryHeader) {
   ASSERT_TRUE(test_server_.Start());
 
-  scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+  scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
 
   // populate the cache
   {
@@ -1184,7 +1246,7 @@
 TEST_F(URLRequestTestHTTP, BasicAuth) {
   ASSERT_TRUE(test_server_.Start());
 
-  scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+  scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
 
   // populate the cache
   {
@@ -1234,7 +1296,7 @@
   // Request a page that will give a 401 containing a Set-Cookie header.
   // Verify that when the transaction is restarted, it includes the new cookie.
   {
-    scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+    scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
     TestDelegate d;
     d.set_username(kUser);
     d.set_password(kSecret);
@@ -1255,7 +1317,7 @@
   // Same test as above, except this time the restart is initiated earlier
   // (without user intervention since identity is embedded in the URL).
   {
-    scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+    scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
     TestDelegate d;
 
     GURL::Replacements replacements;
@@ -1283,7 +1345,7 @@
   net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
   ASSERT_TRUE(test_server.Start());
 
-  scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+  scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
 
   // Set up a cookie.
   {
@@ -1332,7 +1394,7 @@
   net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath());
   ASSERT_TRUE(test_server.Start());
 
-  scoped_refptr<URLRequestContext> context(new TestURLRequestContext());
+  scoped_refptr<net::URLRequestContext> context(new TestURLRequestContext());
 
   // Set up a cookie.
   {
@@ -1678,7 +1740,7 @@
 
     MessageLoop::current()->Run();
 
-    EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
 
     EXPECT_EQ(1, d.blocked_get_cookies_count());
     EXPECT_EQ(0, d.blocked_set_cookie_count());
@@ -1707,7 +1769,7 @@
 
     MessageLoop::current()->Run();
 
-    EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+    EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
 
     // Even though the response will contain 3 set-cookie headers, we expect
     // only one to be blocked as that first one will cause OnSetCookie to be
@@ -1820,10 +1882,10 @@
 }
 
 // Custom URLRequestJobs for use with interceptor tests
-class RestartTestJob : public URLRequestTestJob {
+class RestartTestJob : public net::URLRequestTestJob {
  public:
   explicit RestartTestJob(net::URLRequest* request)
-    : URLRequestTestJob(request, true) {}
+    : net::URLRequestTestJob(request, true) {}
  protected:
   virtual void StartAsync() {
     this->NotifyRestartRequired();
@@ -1832,10 +1894,10 @@
   ~RestartTestJob() {}
 };
 
-class CancelTestJob : public URLRequestTestJob {
+class CancelTestJob : public net::URLRequestTestJob {
  public:
   explicit CancelTestJob(net::URLRequest* request)
-    : URLRequestTestJob(request, true) {}
+    : net::URLRequestTestJob(request, true) {}
  protected:
   virtual void StartAsync() {
     request_->Cancel();
@@ -1844,10 +1906,10 @@
   ~CancelTestJob() {}
 };
 
-class CancelThenRestartTestJob : public URLRequestTestJob {
+class CancelThenRestartTestJob : public net::URLRequestTestJob {
  public:
   explicit CancelThenRestartTestJob(net::URLRequest* request)
-      : URLRequestTestJob(request, true) {
+      : net::URLRequestTestJob(request, true) {
   }
  protected:
   virtual void StartAsync() {
@@ -1899,16 +1961,16 @@
       simulate_main_network_error_ = false;
       did_simulate_error_main_ = true;
       // will error since the requeted url is not one of its canned urls
-      return new URLRequestTestJob(request, true);
+      return new net::URLRequestTestJob(request, true);
     }
     if (!intercept_main_request_)
       return NULL;
     intercept_main_request_ = false;
     did_intercept_main_ = true;
-    return new URLRequestTestJob(request,
-                                 main_headers_,
-                                 main_data_,
-                                 true);
+    return new net::URLRequestTestJob(request,
+                                      main_headers_,
+                                      main_data_,
+                                      true);
   }
 
   virtual net::URLRequestJob* MaybeInterceptRedirect(net::URLRequest* request,
@@ -1922,10 +1984,10 @@
       return NULL;
     intercept_redirect_ = false;
     did_intercept_redirect_ = true;
-    return new URLRequestTestJob(request,
-                                 redirect_headers_,
-                                 redirect_data_,
-                                 true);
+    return new net::URLRequestTestJob(request,
+                                      redirect_headers_,
+                                      redirect_data_,
+                                      true);
   }
 
   virtual net::URLRequestJob* MaybeInterceptResponse(net::URLRequest* request) {
@@ -1938,10 +2000,10 @@
       return NULL;
     intercept_final_response_ = false;
     did_intercept_final_ = true;
-    return new URLRequestTestJob(request,
-                                 final_headers_,
-                                 final_data_,
-                                 true);
+    return new net::URLRequestTestJob(request,
+                                      final_headers_,
+                                      final_data_,
+                                      true);
   }
 
   // Whether to intercept the main request, and if so the response to return.
@@ -1985,11 +2047,11 @@
   // Static getters for canned response header and data strings
 
   static std::string ok_data() {
-    return URLRequestTestJob::test_data_1();
+    return net::URLRequestTestJob::test_data_1();
   }
 
   static std::string ok_headers() {
-    return URLRequestTestJob::test_headers();
+    return net::URLRequestTestJob::test_headers();
   }
 
   static std::string redirect_data() {
@@ -1997,7 +2059,7 @@
   }
 
   static std::string redirect_headers() {
-    return URLRequestTestJob::test_redirect_headers();
+    return net::URLRequestTestJob::test_redirect_headers();
   }
 
   static std::string error_data() {
@@ -2005,7 +2067,7 @@
   }
 
   static std::string error_headers() {
-    return URLRequestTestJob::test_error_headers();
+    return net::URLRequestTestJob::test_error_headers();
   }
 };
 
@@ -2192,7 +2254,7 @@
 
   // Check we see a canceled request
   EXPECT_FALSE(req.status().is_success());
-  EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
 }
 
 TEST_F(URLRequestTest, InterceptRespectsCancelRedirect) {
@@ -2224,7 +2286,7 @@
 
   // Check we see a canceled request
   EXPECT_FALSE(req.status().is_success());
-  EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
 }
 
 TEST_F(URLRequestTest, InterceptRespectsCancelFinal) {
@@ -2248,7 +2310,7 @@
 
   // Check we see a canceled request
   EXPECT_FALSE(req.status().is_success());
-  EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
 }
 
 TEST_F(URLRequestTest, InterceptRespectsCancelInRestart) {
@@ -2274,7 +2336,7 @@
 
   // Check we see a canceled request
   EXPECT_FALSE(req.status().is_success());
-  EXPECT_EQ(URLRequestStatus::CANCELED, req.status().status());
+  EXPECT_EQ(net::URLRequestStatus::CANCELED, req.status().status());
 }
 
 class URLRequestTestFTP : public URLRequestTest {
@@ -2642,3 +2704,35 @@
   MessageLoop::current()->Run();
   EXPECT_EQ(std::string("koi-8r"), d.data_received());
 }
+
+// Check that default User-Agent header is sent.
+TEST_F(URLRequestTestHTTP, DefaultUserAgent) {
+  ASSERT_TRUE(test_server_.Start());
+
+  TestDelegate d;
+  TestURLRequest req(test_server_.GetURL("echoheader?User-Agent"), &d);
+  req.set_context(new TestURLRequestContext());
+  req.Start();
+  MessageLoop::current()->Run();
+  EXPECT_EQ(req.context()->GetUserAgent(req.url()), d.data_received());
+}
+
+// Check that if request overrides the User-Agent header,
+// the default is not appended.
+TEST_F(URLRequestTestHTTP, OverrideUserAgent) {
+  ASSERT_TRUE(test_server_.Start());
+
+  TestDelegate d;
+  TestURLRequest
+      req(test_server_.GetURL("echoheaderoverride?User-Agent"), &d);
+  req.set_context(new TestURLRequestContext());
+  net::HttpRequestHeaders headers;
+  headers.SetHeader(net::HttpRequestHeaders::kUserAgent, "Lynx (textmode)");
+  req.SetExtraRequestHeaders(headers);
+  req.Start();
+  MessageLoop::current()->Run();
+  // If the net tests are being run with ChromeFrame then we need to allow for
+  // the 'chromeframe' suffix which is added to the user agent before the
+  // closing parentheses.
+  EXPECT_TRUE(StartsWithASCII(d.data_received(), "Lynx (textmode", true));
+}
diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h
deleted file mode 100644
index c336b41..0000000
--- a/net/url_request/url_request_unittest.h
+++ /dev/null
@@ -1,405 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_
-#define NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_
-#pragma once
-
-#include <stdlib.h>
-
-#include <sstream>
-#include <string>
-
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/process_util.h"
-#include "base/string_util.h"
-#include "base/string16.h"
-#include "base/threading/thread.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "net/base/cert_verifier.h"
-#include "net/base/cookie_monster.h"
-#include "net/base/cookie_policy.h"
-#include "net/base/host_resolver.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/ssl_config_service_defaults.h"
-#include "net/disk_cache/disk_cache.h"
-#include "net/ftp/ftp_network_layer.h"
-#include "net/http/http_auth_handler_factory.h"
-#include "net/http/http_cache.h"
-#include "net/http/http_network_layer.h"
-#include "net/test/test_server.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/proxy/proxy_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "googleurl/src/url_util.h"
-
-using base::TimeDelta;
-
-//-----------------------------------------------------------------------------
-
-class TestCookiePolicy : public net::CookiePolicy {
- public:
-  enum Options {
-    NO_GET_COOKIES = 1 << 0,
-    NO_SET_COOKIE  = 1 << 1,
-    ASYNC          = 1 << 2,
-    FORCE_SESSION  = 1 << 3,
-  };
-
-  explicit TestCookiePolicy(int options_bit_mask)
-      : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
-        options_(options_bit_mask),
-        callback_(NULL) {
-  }
-
-  virtual int CanGetCookies(const GURL& url, const GURL& first_party,
-                            net::CompletionCallback* callback) {
-    if ((options_ & ASYNC) && callback) {
-      callback_ = callback;
-      MessageLoop::current()->PostTask(FROM_HERE,
-          method_factory_.NewRunnableMethod(
-              &TestCookiePolicy::DoGetCookiesPolicy, url, first_party));
-      return net::ERR_IO_PENDING;
-    }
-
-    if (options_ & NO_GET_COOKIES)
-      return net::ERR_ACCESS_DENIED;
-
-    return net::OK;
-  }
-
-  virtual int CanSetCookie(const GURL& url, const GURL& first_party,
-                           const std::string& cookie_line,
-                           net::CompletionCallback* callback) {
-    if ((options_ & ASYNC) && callback) {
-      callback_ = callback;
-      MessageLoop::current()->PostTask(FROM_HERE,
-          method_factory_.NewRunnableMethod(
-              &TestCookiePolicy::DoSetCookiePolicy, url, first_party,
-              cookie_line));
-      return net::ERR_IO_PENDING;
-    }
-
-    if (options_ & NO_SET_COOKIE)
-      return net::ERR_ACCESS_DENIED;
-
-    if (options_ & FORCE_SESSION)
-      return net::OK_FOR_SESSION_ONLY;
-
-    return net::OK;
-  }
-
- private:
-  void DoGetCookiesPolicy(const GURL& url, const GURL& first_party) {
-    int policy = CanGetCookies(url, first_party, NULL);
-
-    DCHECK(callback_);
-    net::CompletionCallback* callback = callback_;
-    callback_ = NULL;
-    callback->Run(policy);
-  }
-
-  void DoSetCookiePolicy(const GURL& url, const GURL& first_party,
-                         const std::string& cookie_line) {
-    int policy = CanSetCookie(url, first_party, cookie_line, NULL);
-
-    DCHECK(callback_);
-    net::CompletionCallback* callback = callback_;
-    callback_ = NULL;
-    callback->Run(policy);
-  }
-
-  ScopedRunnableMethodFactory<TestCookiePolicy> method_factory_;
-  int options_;
-  net::CompletionCallback* callback_;
-};
-
-//-----------------------------------------------------------------------------
-
-class TestURLRequestContext : public URLRequestContext {
- public:
-  TestURLRequestContext() {
-    host_resolver_ =
-        net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
-                                      NULL, NULL);
-    proxy_service_ = net::ProxyService::CreateDirect();
-    Init();
-  }
-
-  explicit TestURLRequestContext(const std::string& proxy) {
-    host_resolver_  =
-        net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
-                                      NULL, NULL);
-    net::ProxyConfig proxy_config;
-    proxy_config.proxy_rules().ParseFromString(proxy);
-    proxy_service_ = net::ProxyService::CreateFixed(proxy_config);
-    Init();
-  }
-
-  void set_cookie_policy(net::CookiePolicy* policy) {
-    cookie_policy_ = policy;
-  }
-
- protected:
-  virtual ~TestURLRequestContext() {
-    delete ftp_transaction_factory_;
-    delete http_transaction_factory_;
-    delete http_auth_handler_factory_;
-    delete cert_verifier_;
-    delete host_resolver_;
-  }
-
- private:
-  void Init() {
-    cert_verifier_ = new net::CertVerifier;
-    ftp_transaction_factory_ = new net::FtpNetworkLayer(host_resolver_);
-    ssl_config_service_ = new net::SSLConfigServiceDefaults;
-    http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
-        host_resolver_);
-    http_transaction_factory_ = new net::HttpCache(
-        net::HttpNetworkLayer::CreateFactory(host_resolver_,
-                                             cert_verifier_,
-                                             NULL /* dnsrr_resolver */,
-                                             NULL /* dns_cert_checker */,
-                                             NULL /* ssl_host_info_factory */,
-                                             proxy_service_,
-                                             ssl_config_service_,
-                                             http_auth_handler_factory_,
-                                             network_delegate_,
-                                             NULL),
-        NULL /* net_log */,
-        net::HttpCache::DefaultBackend::InMemory(0));
-    // In-memory cookie store.
-    cookie_store_ = new net::CookieMonster(NULL, NULL);
-    accept_language_ = "en-us,fr";
-    accept_charset_ = "iso-8859-1,*,utf-8";
-  }
-};
-
-//-----------------------------------------------------------------------------
-
-class TestURLRequest : public net::URLRequest {
- public:
-  TestURLRequest(const GURL& url, Delegate* delegate)
-      : net::URLRequest(url, delegate) {
-    set_context(new TestURLRequestContext());
-  }
-};
-
-//-----------------------------------------------------------------------------
-
-class TestDelegate : public net::URLRequest::Delegate {
- public:
-  TestDelegate()
-      : cancel_in_rr_(false),
-        cancel_in_rs_(false),
-        cancel_in_rd_(false),
-        cancel_in_rd_pending_(false),
-        cancel_in_getcookiesblocked_(false),
-        cancel_in_setcookieblocked_(false),
-        quit_on_complete_(true),
-        quit_on_redirect_(false),
-        allow_certificate_errors_(false),
-        response_started_count_(0),
-        received_bytes_count_(0),
-        received_redirect_count_(0),
-        blocked_get_cookies_count_(0),
-        blocked_set_cookie_count_(0),
-        set_cookie_count_(0),
-        received_data_before_response_(false),
-        request_failed_(false),
-        have_certificate_errors_(false),
-        buf_(new net::IOBuffer(kBufferSize)) {
-  }
-
-  virtual void OnReceivedRedirect(net::URLRequest* request, const GURL& new_url,
-                                  bool* defer_redirect) {
-    received_redirect_count_++;
-    if (quit_on_redirect_) {
-      *defer_redirect = true;
-      MessageLoop::current()->Quit();
-    } else if (cancel_in_rr_) {
-      request->Cancel();
-    }
-  }
-
-  virtual void OnResponseStarted(net::URLRequest* request) {
-    // It doesn't make sense for the request to have IO pending at this point.
-    DCHECK(!request->status().is_io_pending());
-
-    response_started_count_++;
-    if (cancel_in_rs_) {
-      request->Cancel();
-      OnResponseCompleted(request);
-    } else if (!request->status().is_success()) {
-      DCHECK(request->status().status() == URLRequestStatus::FAILED ||
-             request->status().status() == URLRequestStatus::CANCELED);
-      request_failed_ = true;
-      OnResponseCompleted(request);
-    } else {
-      // Initiate the first read.
-      int bytes_read = 0;
-      if (request->Read(buf_, kBufferSize, &bytes_read))
-        OnReadCompleted(request, bytes_read);
-      else if (!request->status().is_io_pending())
-        OnResponseCompleted(request);
-    }
-  }
-
-  virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) {
-    // It doesn't make sense for the request to have IO pending at this point.
-    DCHECK(!request->status().is_io_pending());
-
-    if (response_started_count_ == 0)
-      received_data_before_response_ = true;
-
-    if (cancel_in_rd_)
-      request->Cancel();
-
-    if (bytes_read >= 0) {
-      // There is data to read.
-      received_bytes_count_ += bytes_read;
-
-      // consume the data
-      data_received_.append(buf_->data(), bytes_read);
-    }
-
-    // If it was not end of stream, request to read more.
-    if (request->status().is_success() && bytes_read > 0) {
-      bytes_read = 0;
-      while (request->Read(buf_, kBufferSize, &bytes_read)) {
-        if (bytes_read > 0) {
-          data_received_.append(buf_->data(), bytes_read);
-          received_bytes_count_ += bytes_read;
-        } else {
-          break;
-        }
-      }
-    }
-    if (!request->status().is_io_pending())
-      OnResponseCompleted(request);
-    else if (cancel_in_rd_pending_)
-      request->Cancel();
-  }
-
-  virtual void OnResponseCompleted(net::URLRequest* request) {
-    if (quit_on_complete_)
-      MessageLoop::current()->Quit();
-  }
-
-  void OnAuthRequired(net::URLRequest* request,
-                      net::AuthChallengeInfo* auth_info) {
-    if (!username_.empty() || !password_.empty()) {
-      request->SetAuth(username_, password_);
-    } else {
-      request->CancelAuth();
-    }
-  }
-
-  virtual void OnSSLCertificateError(net::URLRequest* request,
-                                     int cert_error,
-                                     net::X509Certificate* cert) {
-    // The caller can control whether it needs all SSL requests to go through,
-    // independent of any possible errors, or whether it wants SSL errors to
-    // cancel the request.
-    have_certificate_errors_ = true;
-    if (allow_certificate_errors_)
-      request->ContinueDespiteLastError();
-    else
-      request->Cancel();
-  }
-
-  virtual void OnGetCookies(net::URLRequest* request, bool blocked_by_policy) {
-    if (blocked_by_policy) {
-      blocked_get_cookies_count_++;
-      if (cancel_in_getcookiesblocked_)
-        request->Cancel();
-    }
-  }
-
-  virtual void OnSetCookie(net::URLRequest* request,
-                           const std::string& cookie_line,
-                           const net::CookieOptions& options,
-                           bool blocked_by_policy) {
-    if (blocked_by_policy) {
-      blocked_set_cookie_count_++;
-      if (cancel_in_setcookieblocked_)
-        request->Cancel();
-    } else {
-      set_cookie_count_++;
-    }
-  }
-
-  void set_cancel_in_received_redirect(bool val) { cancel_in_rr_ = val; }
-  void set_cancel_in_response_started(bool val) { cancel_in_rs_ = val; }
-  void set_cancel_in_received_data(bool val) { cancel_in_rd_ = val; }
-  void set_cancel_in_received_data_pending(bool val) {
-    cancel_in_rd_pending_ = val;
-  }
-  void set_cancel_in_get_cookies_blocked(bool val) {
-    cancel_in_getcookiesblocked_ = val;
-  }
-  void set_cancel_in_set_cookie_blocked(bool val) {
-    cancel_in_setcookieblocked_ = val;
-  }
-  void set_quit_on_complete(bool val) { quit_on_complete_ = val; }
-  void set_quit_on_redirect(bool val) { quit_on_redirect_ = val; }
-  void set_allow_certificate_errors(bool val) {
-    allow_certificate_errors_ = val;
-  }
-  void set_username(const string16& u) { username_ = u; }
-  void set_password(const string16& p) { password_ = p; }
-
-  // query state
-  const std::string& data_received() const { return data_received_; }
-  int bytes_received() const { return static_cast<int>(data_received_.size()); }
-  int response_started_count() const { return response_started_count_; }
-  int received_redirect_count() const { return received_redirect_count_; }
-  int blocked_get_cookies_count() const { return blocked_get_cookies_count_; }
-  int blocked_set_cookie_count() const { return blocked_set_cookie_count_; }
-  int set_cookie_count() const { return set_cookie_count_; }
-  bool received_data_before_response() const {
-    return received_data_before_response_;
-  }
-  bool request_failed() const { return request_failed_; }
-  bool have_certificate_errors() const { return have_certificate_errors_; }
-
- private:
-  static const int kBufferSize = 4096;
-  // options for controlling behavior
-  bool cancel_in_rr_;
-  bool cancel_in_rs_;
-  bool cancel_in_rd_;
-  bool cancel_in_rd_pending_;
-  bool cancel_in_getcookiesblocked_;
-  bool cancel_in_setcookieblocked_;
-  bool quit_on_complete_;
-  bool quit_on_redirect_;
-  bool allow_certificate_errors_;
-
-  string16 username_;
-  string16 password_;
-
-  // tracks status of callbacks
-  int response_started_count_;
-  int received_bytes_count_;
-  int received_redirect_count_;
-  int blocked_get_cookies_count_;
-  int blocked_set_cookie_count_;
-  int set_cookie_count_;
-  bool received_data_before_response_;
-  bool request_failed_;
-  bool have_certificate_errors_;
-  std::string data_received_;
-
-  // our read buffer
-  scoped_refptr<net::IOBuffer> buf_;
-};
-
-#endif  // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_
diff --git a/net/url_request/view_cache_helper_unittest.cc b/net/url_request/view_cache_helper_unittest.cc
index 3903c2b..5a656f2 100644
--- a/net/url_request/view_cache_helper_unittest.cc
+++ b/net/url_request/view_cache_helper_unittest.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "net/url_request/view_cache_helper.h"
 
 #include "base/pickle.h"
+#include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/http/http_cache.h"
@@ -13,7 +14,7 @@
 
 namespace {
 
-class TestURLRequestContext : public URLRequestContext {
+class TestURLRequestContext : public net::URLRequestContext {
  public:
   TestURLRequestContext();
 
@@ -81,7 +82,7 @@
   entry->Close();
 }
 
-void FillCache(URLRequestContext* context) {
+void FillCache(net::URLRequestContext* context) {
   TestCompletionCallback cb;
   disk_cache::Backend* cache;
   int rv =
diff --git a/net/websockets/websocket.h b/net/websockets/websocket.h
index ec1297a..f4c1168 100644
--- a/net/websockets/websocket.h
+++ b/net/websockets/websocket.h
@@ -6,7 +6,7 @@
 // It is intended to be used for live experiment of WebSocket connectivity
 // metrics.
 // Note that it is not used for WebKit's WebSocket communication.
-// See third_party/WebKit/WebCore/websockets/ instead.
+// See third_party/WebKit/Source/WebCore/websockets/ instead.
 
 #ifndef NET_WEBSOCKETS_WEBSOCKET_H_
 #define NET_WEBSOCKETS_WEBSOCKET_H_
diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc
index 43d8509..2133cfa 100644
--- a/net/websockets/websocket_job_unittest.cc
+++ b/net/websockets/websocket_job_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -263,7 +263,7 @@
 
   bool sent = websocket_->SendData(kHandshakeRequestMessage,
                                    strlen(kHandshakeRequestMessage));
-  EXPECT_EQ(true, sent);
+  EXPECT_TRUE(sent);
   MessageLoop::current()->RunAllPending();
   EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
@@ -308,7 +308,7 @@
 
   bool sent = websocket_->SendData(kHandshakeRequestMessage,
                                    strlen(kHandshakeRequestMessage));
-  EXPECT_EQ(true, sent);
+  EXPECT_TRUE(sent);
   // We assume request is sent in one data chunk (from WebKit)
   // We don't support streaming request.
   MessageLoop::current()->RunAllPending();
@@ -390,7 +390,7 @@
 
   bool sent = websocket_->SendData(kHandshakeRequestMessage,
                                    strlen(kHandshakeRequestMessage));
-  EXPECT_EQ(true, sent);
+  EXPECT_TRUE(sent);
   MessageLoop::current()->RunAllPending();
   EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
@@ -477,7 +477,7 @@
 
   bool sent = websocket_->SendData(kHandshakeRequestMessage,
                                    strlen(kHandshakeRequestMessage));
-  EXPECT_EQ(true, sent);
+  EXPECT_TRUE(sent);
   MessageLoop::current()->RunAllPending();
   EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
diff --git a/net/websockets/websocket_unittest.cc b/net/websockets/websocket_unittest.cc
index e711266..8c412d9 100644
--- a/net/websockets/websocket_unittest.cc
+++ b/net/websockets/websocket_unittest.cc
@@ -11,7 +11,7 @@
 #include "net/base/mock_host_resolver.h"
 #include "net/base/test_completion_callback.h"
 #include "net/socket/socket_test_util.h"
-#include "net/url_request/url_request_unittest.h"
+#include "net/url_request/url_request_test_util.h"
 #include "net/websockets/websocket.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/testing/README.chromium b/testing/README.chromium
deleted file mode 100644
index d6642ca..0000000
--- a/testing/README.chromium
+++ /dev/null
@@ -1,35 +0,0 @@
-We include a snapshot of gmock from http://googlemock.googlecode.com/svn/trunk.
-(Why not pull from it directly via DEPS?  Because it uses svn:externals, which
-confuses gclient.)
-
-Current revision: 282
-
-
--- HOW TO USE --
-
-If you are unfamiliar with gmock, there is an example of how to write a test
-based on gmock in base/gmock_unittest.cc.  To use gmock, just add a dependency
-onto testing/gmock.gyp:gmock in your gyp target.
-
-For more general informaiton, there is a lot of good documentation availble on
-the googlemock website:
-
-  http://code.google.com/p/googlemock/
-
-In particular, the "For Dummies" guide is a good place to start.  The
-"CheatSheet" and "CookBook" are better as references.
-
-
--- RECREATING PACKAGE --
-
-Example:
-
-    svn export --ignore-externals \
-        http://googlemock.googlecode.com/svn/trunk/ gmock
-
-When checking out a copy from svn, --ignore-externals should be used to avoid
-getting an extra copy of gtest.
-
-This command will grab the head of trunk. Optionally, -r [revision number] to
-can be passed to svn export if you want a specific revision.  The current
-revision of the source is listed at the top of the README.
diff --git a/testing/gmock/msvc/gmock-spec-builders_test.vcproj b/testing/gmock/msvc/gmock-spec-builders_test.vcproj
old mode 100644
new mode 100755
diff --git a/testing/gmock/scripts/gmock-config.in b/testing/gmock/scripts/gmock-config.in
old mode 100644
new mode 100755
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index 0c68ec6..16b9d11 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -150,7 +150,6 @@
         'overrides/talk/xmllite/qname.cc',
         'overrides/talk/xmllite/qname.h',
 
-        'source/talk/base/DiskCacheStd.h',
         'source/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h',
         'source/talk/base/asyncfile.cc',
         'source/talk/base/asyncfile.h',
@@ -182,7 +181,6 @@
         'source/talk/base/diskcache.h',
         'source/talk/base/event.cc',
         'source/talk/base/event.h',
-        'source/talk/base/fakenetwork.h',
         'source/talk/base/fileutils.cc',
         'source/talk/base/fileutils.h',
         'source/talk/base/fileutils_mock.h',
@@ -190,7 +188,6 @@
         'source/talk/base/firewallsocketserver.h',
         'source/talk/base/flags.cc',
         'source/talk/base/flags.h',
-        'source/talk/base/hash.h',
         'source/talk/base/helpers.cc',
         'source/talk/base/helpers.h',
         'source/talk/base/host.cc',
@@ -213,7 +210,6 @@
         'source/talk/base/messagehandler.h',
         'source/talk/base/messagequeue.cc',
         'source/talk/base/messagequeue.h',
-        'source/talk/base/netfw.h',
         'source/talk/base/nethelpers.cc',
         'source/talk/base/nethelpers.h',
         'source/talk/base/network.cc',
@@ -312,7 +308,6 @@
         ['OS=="win"', {
           'sources': [
             'overrides/talk/base/win32socketinit.cc',
-            'source/talk/base/convert.h',  # win32 only
             'source/talk/base/schanneladapter.cc',
             'source/talk/base/schanneladapter.h',
             'source/talk/base/win32.h',
diff --git a/third_party/modp_b64/LICENSE.html b/third_party/modp_b64/LICENSE.html
new file mode 100644
index 0000000..e156351
--- /dev/null
+++ b/third_party/modp_b64/LICENSE.html
@@ -0,0 +1,296 @@
+
+
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<!-- ViewVC :: http://www.viewvc.org/ -->
+<head>
+<title>[chrome] Log of /trunk/src/third_party/modp_b64/LICENSE</title>
+<meta name="generator" content="ViewVC 1.0.9" />
+<link rel="stylesheet" href="/viewvc/*docroot*/styles.css" type="text/css" />
+
+</head>
+<body>
+<div class="vc_navheader">
+
+<form method="get" action="/viewvc/">
+
+<table style="padding:0.1em;">
+<tr>
+<td>
+<strong>
+
+<a href="/viewvc/chrome/?pathrev=74924">
+
+[chrome]</a>
+/
+
+<a href="/viewvc/chrome/trunk/?pathrev=74924">
+
+trunk</a>
+/
+
+<a href="/viewvc/chrome/trunk/src/?pathrev=74924">
+
+src</a>
+/
+
+<a href="/viewvc/chrome/trunk/src/third_party/?pathrev=74924">
+
+third_party</a>
+/
+
+<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/?pathrev=74924">
+
+modp_b64</a>
+/
+
+
+
+LICENSE
+
+
+</strong>
+
+</td>
+<td style="text-align:right;">
+
+
+<strong>Repository:</strong>
+<select name="root" onchange="submit()">
+
+
+<option value="*viewroots*">Repository Listing</option>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<optgroup label="Subversion Repositories"><option selected="selected">chrome</option><option>native_client</option></optgroup>
+
+</select>
+<input type="submit" value="Go" />
+
+</td>
+</tr>
+</table>
+
+</form>
+
+</div>
+<div style="float: right; padding: 5px;"><a href="http://www.viewvc.org/"><img src="/viewvc/*docroot*/images/logo.png" alt="ViewVC logotype" width="128" height="48" /></a></div>
+<h1>Log of /trunk/src/third_party/modp_b64/LICENSE</h1>
+
+<p style="margin:0;">
+
+<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/?pathrev=74924"><img src="/viewvc/*docroot*/images/back_small.png" width="16" height="16" alt="Parent Directory" /> Parent Directory</a>
+
+
+
+
+</p>
+
+<hr />
+<table class="auto">
+
+
+
+<tr>
+<td>Links to HEAD:</td>
+<td>
+(<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE?view=markup">view</a>)
+(<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE">download</a>)
+
+(<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE?view=annotate">annotate</a>)
+</td>
+</tr>
+
+
+
+<tr>
+<td>Sticky Revision:</td>
+<td><form method="get" action="/viewvc/chrome" style="display: inline">
+<div style="display: inline">
+<input type="hidden" name="orig_pathrev" value="74924" /><input type="hidden" name="orig_pathtype" value="FILE" /><input type="hidden" name="orig_view" value="log" /><input type="hidden" name="orig_path" value="trunk/src/third_party/modp_b64/LICENSE" /><input type="hidden" name="view" value="redirect_pathrev" />
+
+<input type="text" name="pathrev" value="74924" size="6"/>
+
+<input type="submit" value="Set" />
+</div>
+</form>
+
+<form method="get" action="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE" style="display: inline">
+<div style="display: inline">
+<input type="hidden" name="view" value="log" />
+
+<input type="submit" value="Clear" />
+
+</div>
+</form>
+
+</td>
+</tr>
+</table>
+ 
+
+
+
+
+
+
+
+
+<div>
+<hr />
+
+<a name="rev44656"></a>
+
+
+Revision <a href="/viewvc/chrome?view=rev&amp;revision=44656"><strong>44656</strong></a> -
+
+(<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE?revision=44656&amp;view=markup&amp;pathrev=74924">view</a>)
+
+(<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE?revision=44656&amp;pathrev=74924">download</a>)
+
+(<a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE?annotate=44656&amp;pathrev=74924">annotate</a>)
+
+
+
+- <a href="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE?view=log&amp;r1=44656&amp;pathrev=74924">[select for diffs]</a>
+
+
+
+
+<br />
+
+Added
+
+<em>Thu Apr 15 15:29:44 2010 UTC</em> (13 months, 2 weeks ago) by <em>evan@chromium.org</em>
+
+
+
+
+
+
+
+<br />File length: 1721 byte(s)
+
+
+
+
+
+
+
+
+
+
+<pre class="vc_log">Pass tools/licenses.py for more directories.
+
+We're now down to only 4 dirs that don't pass the license checker.
+They will require separate changes.
+
+Modify the license checker to only print failing dirs.
+
+BUG=39240
+
+Review URL: <a href="http://codereview.chromium.org/1530040">http://codereview.chromium.org/1530040</a></pre>
+</div>
+
+ 
+
+
+
+ <hr />
+<p><a name="diff"></a>
+This form allows you to request diffs between any two revisions of this file.
+For each of the two "sides" of the diff,
+
+enter a numeric revision.
+
+</p>
+<form method="get" action="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE" id="diff_select">
+<table cellpadding="2" cellspacing="0" class="auto">
+<tr>
+<td>&nbsp;</td>
+<td>
+<input type="hidden" name="pathrev" value="74924" /><input type="hidden" name="view" value="diff" />
+Diffs between
+
+<input type="text" size="12" name="r1"
+value="44656" />
+
+and
+
+<input type="text" size="12" name="r2" value="44656" />
+
+</td>
+</tr>
+<tr>
+<td>&nbsp;</td>
+<td>
+Type of Diff should be a
+<select name="diff_format" onchange="submit()">
+<option value="h" selected="selected">Colored Diff</option>
+<option value="l" >Long Colored Diff</option>
+<option value="u" >Unidiff</option>
+<option value="c" >Context Diff</option>
+<option value="s" >Side by Side</option>
+</select>
+<input type="submit" value=" Get Diffs " />
+</td>
+</tr>
+</table>
+</form>
+
+
+<form method="get" action="/viewvc/chrome/trunk/src/third_party/modp_b64/LICENSE">
+<div>
+<hr />
+<a name="logsort"></a>
+<input type="hidden" name="view" value="log" /><input type="hidden" name="pathrev" value="74924" />
+Sort log by:
+<select name="logsort" onchange="submit()">
+<option value="cvs" >Not sorted</option>
+<option value="date" selected="selected">Commit date</option>
+<option value="rev" >Revision</option>
+</select>
+<input type="submit" value=" Sort " />
+</div>
+</form>
+
+
+<hr />
+<table>
+<tr>
+<td><address><a href="mailto:cvs-admin@insert.your.domain.here">No admin address has been configured</a></address></td>
+<td style="text-align: right;"><strong><a href="/viewvc/*docroot*/help_log.html">ViewVC Help</a></strong></td>
+</tr>
+<tr>
+<td>Powered by <a href="http://viewvc.tigris.org/">ViewVC 1.0.9</a></td>
+<td style="text-align: right;">&nbsp;</td>
+</tr>
+</table>
+</body>
+</html>
+
+
diff --git a/third_party/modp_b64/README.chromium b/third_party/modp_b64/README.chromium
index fc30450..16588b5 100644
--- a/third_party/modp_b64/README.chromium
+++ b/third_party/modp_b64/README.chromium
@@ -1,8 +1,9 @@
 Name: modp base64 decoder
-URL: http://modp.com/release/base64/
+Short Name: stringencoders
+URL: http://code.google.com/p/stringencoders/
+Version: unknown
 
-See the header of modp_b64.cc for the license terms.
-
+Description:
 The modp_b64.c file was modified to remove the inclusion of modp's config.h
 and to fix compilation errors that occur under VC8.  The file was renamed
 modp_b64.cc to force it to be compiled as C++ so that the inclusion of
diff --git a/third_party/modp_b64/modp_b64.gyp b/third_party/modp_b64/modp_b64.gyp
index 4ed34f4..1c346e0 100644
--- a/third_party/modp_b64/modp_b64.gyp
+++ b/third_party/modp_b64/modp_b64.gyp
@@ -6,7 +6,7 @@
   'targets': [
     {
       'target_name': 'modp_b64',
-      'type': '<(library)',
+      'type': 'static_library',
       'msvs_guid': '7100F41F-868D-4E99-80A2-AF8E6574749D',
       'sources': [
         'modp_b64.cc',
diff --git a/webkit/glue/DEPS b/webkit/glue/DEPS
index 0a36ef7..e4479d5 100644
--- a/webkit/glue/DEPS
+++ b/webkit/glue/DEPS
@@ -4,6 +4,7 @@
   "+media",
   "+skia/ext",
   "+skia/include",
+  "+ui",
   "+webkit/tools/test_shell",  # Needed for test shell tests.
 
   # This is not actually a directory, but npruntime_util.cc includes a file
diff --git a/webkit/glue/alt_error_page_resource_fetcher.h b/webkit/glue/alt_error_page_resource_fetcher.h
index 86671df..3cccaf4 100644
--- a/webkit/glue/alt_error_page_resource_fetcher.h
+++ b/webkit/glue/alt_error_page_resource_fetcher.h
@@ -8,7 +8,7 @@
 #include "base/callback.h"
 #include "base/scoped_ptr.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
 
 namespace WebKit {
 class WebFrame;
diff --git a/webkit/glue/context_menu.cc b/webkit/glue/context_menu.cc
index bdfe790..6db5c51 100644
--- a/webkit/glue/context_menu.cc
+++ b/webkit/glue/context_menu.cc
@@ -4,6 +4,15 @@
 
 #include "webkit/glue/context_menu.h"
 
+namespace webkit_glue {
+
+CustomContextMenuContext::CustomContextMenuContext()
+    : is_pepper_menu(false),
+      request_id(0) {
+}
+
+}  // namespace webkit_glue
+
 ContextMenuParams::ContextMenuParams() {
 }
 
@@ -30,6 +39,7 @@
       edit_flags(data.editFlags),
       security_info(data.securityInfo),
       frame_charset(data.frameEncoding.utf8()) {
+  custom_context.is_pepper_menu = false;
   for (size_t i = 0; i < data.customItems.size(); ++i)
     custom_items.push_back(WebMenuItem(data.customItems[i]));
 }
diff --git a/webkit/glue/context_menu.h b/webkit/glue/context_menu.h
index c87de41..2f38807 100644
--- a/webkit/glue/context_menu.h
+++ b/webkit/glue/context_menu.h
@@ -12,8 +12,20 @@
 #include "googleurl/src/gurl.h"
 #include "webkit/glue/webmenuitem.h"
 
-#include "third_party/WebKit/WebKit/chromium/public/WebContextMenuData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
 
+namespace webkit_glue {
+
+struct CustomContextMenuContext {
+  bool is_pepper_menu;
+  int request_id;
+
+  CustomContextMenuContext();
+};
+
+}  // namespace webkit_glue
+
+// TODO(viettrungluu): Put this in the webkit_glue namespace.
 // Parameters structure for ViewHostMsg_ContextMenu.
 // FIXME(beng): This would be more useful in the future and more efficient
 //              if the parameters here weren't so literally mapped to what
@@ -94,6 +106,7 @@
   // The character encoding of the frame on which the menu is invoked.
   std::string frame_charset;
 
+  webkit_glue::CustomContextMenuContext custom_context;
   std::vector<WebMenuItem> custom_items;
 
   ContextMenuParams();
diff --git a/webkit/glue/context_menu_unittest.cc b/webkit/glue/context_menu_unittest.cc
index 9cefc9f..7f54afd 100644
--- a/webkit/glue/context_menu_unittest.cc
+++ b/webkit/glue/context_menu_unittest.cc
@@ -11,7 +11,8 @@
 #include "base/file_util.h"
 #include "base/message_loop.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
 #include "webkit/tools/test_shell/test_webview_delegate.h"
diff --git a/webkit/glue/cpp_bound_class.cc b/webkit/glue/cpp_bound_class.cc
index c5d15b6..9688e4d 100644
--- a/webkit/glue/cpp_bound_class.cc
+++ b/webkit/glue/cpp_bound_class.cc
@@ -15,9 +15,9 @@
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/cpp_bound_class.h"
 
 using WebKit::WebBindings;
diff --git a/webkit/glue/cpp_bound_class_unittest.cc b/webkit/glue/cpp_bound_class_unittest.cc
index f2ef018..fd6691f 100644
--- a/webkit/glue/cpp_bound_class_unittest.cc
+++ b/webkit/glue/cpp_bound_class_unittest.cc
@@ -10,10 +10,10 @@
 
 #include "base/message_loop.h"
 #include "base/string_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/cpp_binding_example.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
@@ -230,8 +230,7 @@
   CheckJavaScriptSuccess(js);
 }
 
-// Disabled, http://crbug.com/68445.
-TEST_F(CppBoundClassTest, DISABLED_InvokeMethods) {
+TEST_F(CppBoundClassTest, InvokeMethods) {
   // The expression on the left is expected to return the value on the right.
   static const std::string tests[] = {
     "example.echoValue(true)", "true",
diff --git a/webkit/glue/cpp_variant.cc b/webkit/glue/cpp_variant.cc
index 0d16cdd..699f7f1 100644
--- a/webkit/glue/cpp_variant.cc
+++ b/webkit/glue/cpp_variant.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // This file contains definitions for CppVariant.
 
 #include <limits>
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
 #include "webkit/glue/cpp_variant.h"
 #include "base/logging.h"
 #include "base/string_util.h"
@@ -211,14 +211,14 @@
   return value.boolValue;
 }
 
-std::vector<std::string> CppVariant::ToStringVector() const {
+std::vector<CppVariant> CppVariant::ToVector() const {
   DCHECK(isObject());
-  std::vector<std::string> string_vector;
+  std::vector<CppVariant> vector;
   NPObject* np_value = value.objectValue;
   NPIdentifier length_id = WebBindings::getStringIdentifier("length");
 
   if (WebBindings::hasProperty(NULL, np_value, length_id)) {
-    NPVariant length_value;
+    CppVariant length_value;
     if (WebBindings::getProperty(NULL, np_value, length_id, &length_value)) {
       int length = 0;
       // The length is a double in some cases.
@@ -226,30 +226,25 @@
         length = static_cast<int>(NPVARIANT_TO_DOUBLE(length_value));
       else if (NPVARIANT_IS_INT32(length_value))
         length = NPVARIANT_TO_INT32(length_value);
-      WebBindings::releaseVariantValue(&length_value);
+      else
+        NOTREACHED();
 
       // For sanity, only allow 60000 items.
       length = std::min(60000, length);
       for (int i = 0; i < length; ++i) {
         // Get each of the items.
-        std::string index = base::StringPrintf("%d", i);
-        NPIdentifier index_id = WebBindings::getStringIdentifier(index.c_str());
-        if (WebBindings::hasProperty(NULL, np_value, index_id)) {
-          NPVariant index_value;
-          if (WebBindings::getProperty(NULL, np_value, index_id, &index_value)) {
-            if (NPVARIANT_IS_STRING(index_value)) {
-              std::string string(
-                  NPVARIANT_TO_STRING(index_value).UTF8Characters,
-                  NPVARIANT_TO_STRING(index_value).UTF8Length);
-              string_vector.push_back(string);
-            }
-            WebBindings::releaseVariantValue(&index_value);
-          }
+        NPIdentifier index = WebBindings::getIntIdentifier(i);
+        if (WebBindings::hasProperty(NULL, np_value, index)) {
+          CppVariant index_value;
+          if (WebBindings::getProperty(NULL, np_value, index, &index_value))
+            vector.push_back(index_value);
         }
       }
     }
+  } else {
+    NOTREACHED();
   }
-  return string_vector;
+  return vector;
 }
 
 bool CppVariant::Invoke(const std::string& method, const CppVariant* args,
diff --git a/webkit/glue/cpp_variant.h b/webkit/glue/cpp_variant.h
index 34f843a..01efd7d 100644
--- a/webkit/glue/cpp_variant.h
+++ b/webkit/glue/cpp_variant.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -89,14 +89,15 @@
   bool isObject() const { return (type == NPVariantType_Object); }
 
   // Converters.  The CppVariant must be of a type convertible to these values.
-  // For example, ToInteger() works only if isNumber() is true.
+  // For example, ToInt32() works only if isNumber() is true.
   std::string ToString() const;
   int32_t ToInt32() const;
   double ToDouble() const;
   bool ToBoolean() const;
-  // Returns a vector of strings for the specified argument. This is useful
-  // for converting a JavaScript array of strings into a vector of strings.
-  std::vector<std::string> ToStringVector() const;
+  // Returns a vector of CppVariant for the specified variant. This should only
+  // be called on an Object. If the object has no "length" property an empty
+  // vector is returned.
+  std::vector<CppVariant> ToVector() const;
 
   // Invoke method of the given name on an object with the supplied arguments.
   // The first argument should be the object on which the method is to be
diff --git a/webkit/glue/cpp_variant_unittest.cc b/webkit/glue/cpp_variant_unittest.cc
index 43c78de..f3c6b61 100644
--- a/webkit/glue/cpp_variant_unittest.cc
+++ b/webkit/glue/cpp_variant_unittest.cc
@@ -1,10 +1,13 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/compiler_specific.h"
+#include "base/string_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
 #include "webkit/glue/cpp_variant.h"
 
 using WebKit::WebBindings;
@@ -273,7 +276,7 @@
   CppVariant cpp;
   cpp.Set(true);
   EXPECT_EQ(NPVariantType_Bool, cpp.type);
-  EXPECT_EQ(true, cpp.value.boolValue);
+  EXPECT_TRUE(cpp.value.boolValue);
 
   cpp.Set(5);
   EXPECT_EQ(NPVariantType_Int32, cpp.type);
@@ -424,3 +427,67 @@
   WebBindings::releaseObject(obj);
   CheckObject(cpp);
 }
+
+bool MockNPHasPropertyFunction(NPObject *npobj, NPIdentifier name) {
+  return true;
+}
+
+bool MockNPGetPropertyFunction(NPObject *npobj, NPIdentifier name,
+                               NPVariant *result) {
+  if (WebBindings::getStringIdentifier("length") == name) {
+    DOUBLE_TO_NPVARIANT(4, *result);
+  } else if (WebBindings::getIntIdentifier(0) == name) {
+    DOUBLE_TO_NPVARIANT(0, *result);
+  } else if (WebBindings::getIntIdentifier(1) == name) {
+    BOOLEAN_TO_NPVARIANT(true, *result);
+  } else if (WebBindings::getIntIdentifier(2) == name) {
+    NULL_TO_NPVARIANT(*result);
+  } else if (WebBindings::getIntIdentifier(3) == name) {
+    const char* s = "string";
+    size_t length = strlen(s);
+    char* mem = static_cast<char*>(malloc(length + 1));
+    base::strlcpy(mem, s, length + 1);
+    STRINGZ_TO_NPVARIANT(mem, *result);
+  }
+
+  return true;
+}
+
+TEST(CppVariantTest, ToVector) {
+  NPClass array_like_class = {
+      NP_CLASS_STRUCT_VERSION,
+      0, // NPAllocateFunctionPtr allocate;
+      0, // NPDeallocateFunctionPtr deallocate;
+      0, // NPInvalidateFunctionPtr invalidate;
+      0, // NPHasMethodFunctionPtr hasMethod;
+      0, // NPInvokeFunctionPtr invoke;
+      0, // NPInvokeDefaultFunctionPtr invokeDefault;
+      MockNPHasPropertyFunction, // NPHasPropertyFunctionPtr hasProperty;
+      MockNPGetPropertyFunction, // NPGetPropertyFunctionPtr getProperty;
+      0, // NPSetPropertyFunctionPtr setProperty;
+      0, // NPRemovePropertyFunctionPtr removeProperty;
+      0, // NPEnumerationFunctionPtr enumerate;
+      0 // NPConstructFunctionPtr construct;
+      };
+
+  NPObject* obj = WebBindings::createObject(NULL, &array_like_class);
+
+  CppVariant cpp;
+  cpp.Set(obj);
+
+  std::vector<CppVariant> cpp_vector = cpp.ToVector();
+  EXPECT_EQ(4u, cpp_vector.size());
+
+  EXPECT_TRUE(cpp_vector[0].isDouble());
+  EXPECT_EQ(0, cpp_vector[0].ToDouble());
+
+  EXPECT_TRUE(cpp_vector[1].isBool());
+  EXPECT_EQ(true, cpp_vector[1].ToBoolean());
+
+  EXPECT_TRUE(cpp_vector[2].isNull());
+
+  EXPECT_TRUE(cpp_vector[3].isString());
+  CheckString("string", cpp_vector[3]);
+
+  WebBindings::releaseObject(obj);
+}
diff --git a/webkit/glue/devtools_strings.grd b/webkit/glue/devtools_strings.grd
deleted file mode 100644
index 36f14ca..0000000
--- a/webkit/glue/devtools_strings.grd
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- This file contains definitions of strings that are specific to
-Google Chrome Developer Tools. -->
-
-<grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
-  <outputs>
-    <output filename="devtoolsStrings_am.js" type="js_map_format" lang="am" />
-    <output filename="devtoolsStrings_ar.js" type="js_map_format" lang="ar" />
-    <output filename="devtoolsStrings_bg.js" type="js_map_format" lang="bg" />
-    <output filename="devtoolsStrings_bn.js" type="js_map_format" lang="bn" />
-    <output filename="devtoolsStrings_ca.js" type="js_map_format" lang="ca" />
-    <output filename="devtoolsStrings_cs.js" type="js_map_format" lang="cs" />
-    <output filename="devtoolsStrings_da.js" type="js_map_format" lang="da" />
-    <output filename="devtoolsStrings_de.js" type="js_map_format" lang="de" />
-    <output filename="devtoolsStrings_el.js" type="js_map_format" lang="el" />
-    <output filename="devtoolsStrings_en-GB.js" type="js_map_format" lang="en-GB" />
-    <output filename="devtoolsStrings_en-US.js" type="js_map_format" lang="en" />
-    <output filename="devtoolsStrings_es.js" type="js_map_format" lang="es" />
-    <output filename="devtoolsStrings_es-419.js" type="js_map_format" lang="es-419" />
-    <output filename="devtoolsStrings_et.js" type="js_map_format" lang="et" />
-    <output filename="devtoolsStrings_fa.js" type="js_map_format" lang="fa" />
-    <output filename="devtoolsStrings_fi.js" type="js_map_format" lang="fi" />
-    <output filename="devtoolsStrings_fil.js" type="js_map_format" lang="fil" />
-    <output filename="devtoolsStrings_fr.js" type="js_map_format" lang="fr" />
-    <output filename="devtoolsStrings_gu.js" type="js_map_format" lang="gu" />
-    <output filename="devtoolsStrings_he.js" type="js_map_format" lang="he" />
-    <output filename="devtoolsStrings_hi.js" type="js_map_format" lang="hi" />
-    <output filename="devtoolsStrings_hr.js" type="js_map_format" lang="hr" />
-    <output filename="devtoolsStrings_hu.js" type="js_map_format" lang="hu" />
-    <output filename="devtoolsStrings_id.js" type="js_map_format" lang="id" />
-    <output filename="devtoolsStrings_it.js" type="js_map_format" lang="it" />
-    <output filename="devtoolsStrings_ja.js" type="js_map_format" lang="ja" />
-    <output filename="devtoolsStrings_kn.js" type="js_map_format" lang="kn" />
-    <output filename="devtoolsStrings_ko.js" type="js_map_format" lang="ko" />
-    <output filename="devtoolsStrings_lt.js" type="js_map_format" lang="lt" />
-    <output filename="devtoolsStrings_lv.js" type="js_map_format" lang="lv" />
-    <output filename="devtoolsStrings_ml.js" type="js_map_format" lang="ml" />
-    <output filename="devtoolsStrings_mr.js" type="js_map_format" lang="mr" />
-    <output filename="devtoolsStrings_nl.js" type="js_map_format" lang="nl" />
-    <!-- The translation console uses 'no' for Norwegian Bokmål. It should
-         be 'nb'. -->
-    <output filename="devtoolsStrings_nb.js" type="js_map_format" lang="no" />
-    <output filename="devtoolsStrings_or.js" type="js_map_format" lang="or" />
-    <output filename="devtoolsStrings_pl.js" type="js_map_format" lang="pl" />
-    <output filename="devtoolsStrings_pt-BR.js" type="js_map_format" lang="pt-BR" />
-    <output filename="devtoolsStrings_pt-PT.js" type="js_map_format" lang="pt-PT" />
-    <output filename="devtoolsStrings_ro.js" type="js_map_format" lang="ro" />
-    <output filename="devtoolsStrings_ru.js" type="js_map_format" lang="ru" />
-    <output filename="devtoolsStrings_sk.js" type="js_map_format" lang="sk" />
-    <output filename="devtoolsStrings_sl.js" type="js_map_format" lang="sl" />
-    <output filename="devtoolsStrings_sr.js" type="js_map_format" lang="sr" />
-    <output filename="devtoolsStrings_sv.js" type="js_map_format" lang="sv" />
-    <output filename="devtoolsStrings_sw.js" type="js_map_format" lang="sw" />
-    <output filename="devtoolsStrings_ta.js" type="js_map_format" lang="ta" />
-    <output filename="devtoolsStrings_te.js" type="js_map_format" lang="te" />
-    <output filename="devtoolsStrings_th.js" type="js_map_format" lang="th" />
-    <output filename="devtoolsStrings_tr.js" type="js_map_format" lang="tr" />
-    <output filename="devtoolsStrings_uk.js" type="js_map_format" lang="uk" />
-    <output filename="devtoolsStrings_vi.js" type="js_map_format" lang="vi" />
-    <output filename="devtoolsStrings_zh-CN.js" type="js_map_format" lang="zh-CN" />
-    <output filename="devtoolsStrings_zh-TW.js" type="js_map_format" lang="zh-TW" />
-  </outputs>
-  <translations>
-    <!-- TODO add references to each of the XTB files (from the Translation
-    Console) that contain translations of messages in your project.  Each
-    takes a form like <file path="english.xtb" />.  Remember that all file
-    references are relative to this .grd file. -->
-  </translations>
-  <release seq="1">
-    <messages fallback_to_english="true">
-      <message name="IDS_FAILED_TO_RESOLVE_CHILDREN" desc="Message indicating that resolving element children has failed.">
-        Failed to resolve children: <ph name="ERROR">%s<ex>Allocation failure</ex></ph>
-      </message>
-      <message name="IDS_CORRUPT_OBJECT" desc="Error message showing corrupt object.">
-        Corrupted object: <ph name="OBJECT">%s<ex>bad</ex></ph>
-      </message>
-      <message name="IDS_SCOPE_VARS_FAILURE" desc="Error message indicating failure to resolve scope variables.">
-        Failed to resolve scope variables: <ph name="ERROR">%s<ex>Undefined variable</ex></ph>
-      </message>
-      <message name="IDS_PROCESSING_PROFILE" desc="Message indicating that profile is being processed.">
-        Processing...
-      </message>
-      <message name="IDS_PROFILE_TICKS_PROCESSED" desc="Message showing how many ticks are already processed.">
-        <ph name="COUNT">%d<ex>1000</ex></ph> ticks processed
-      </message>
-      <message name="IDS_NO_SOURCE" desc="Label for a script with no source.">
-        &lt;source is not available&gt;
-      </message>
-      <message name="IDS_UNKNOWN_SCOPE_TYPE" desc="Label for an unknown scope type.">
-        &lt;Unknown scope type&gt;
-      </message>
-      <message name="IDS_WINDOW_HEADER" desc="DevTools window header.">
-        Developer Tools - <ph name="URL">%s<ex>http://www.example.com/</ex></ph>
-      </message>
-      <message name="IDS_HEAP_TAB_TITLE" desc="Title of the heap profiler tab.">
-        Heap
-      </message>
-      <message name="IDS_TAKE_HEAP_SNAPSHOT" desc="Title of a button that takes heap snapshot.">
-        Take heap snapshot.
-      </message>
-      <message name="IDS_HEAP_SNAPSHOT" desc="Heap snapshot title.">
-        Snapshot <ph name="COUNT">%d<ex>1</ex></ph>
-      </message>
-      <message name="IDS_HEAP_USAGE" desc="Heap usage.">
-        Used <ph name="USED">%1$s<ex>100MB</ex></ph> of <ph name="CAPACITY">%2$s<ex>200MB</ex></ph> (<ph name="PERCENT">%3$.0f<ex>50</ex></ph>%%)
-      </message>
-      <message name="IDS_HEAP_SNAPSHOT_GRID_CONSTRUCTOR" desc="Title of a heap snapshot grid column showing object's constructor name.">
-        Constructor
-      </message>
-      <message name="IDS_HEAP_SNAPSHOT_GRID_COUNT" desc="Title of a heap snapshot grid column showing objects count.">
-        Count
-      </message>
-      <message name="IDS_HEAP_SNAPSHOT_GRID_COUNT_DELTA" desc="Title of a heap snapshot grid column showing delta of objects count.">
-        ± Count
-      </message>
-      <message name="IDS_HEAP_SNAPSHOT_GRID_SIZE_DELTA" desc="Title of a heap snapshot grid column showing delta of objects size.">
-        ± Size
-      </message>
-      <message name="IDS_HEAP_SNAPSHOT_COMPARED_TO" desc="An option to choose a snapshot to compare current snapshot with.">
-        Compared to <ph name="BASE">%s<ex>Snapshot 1</ex></ph>
-      </message>
-      <message name="IDS_ABSOLUTE_OBJ_COUNTS_AND_SIZES" desc="An option to show absolute objects counts and sizes.">
-        Show absolute counts and sizes.
-      </message>
-      <message name="IDS_PERCENTAGE_OBJ_COUNTS_AND_SIZES" desc="An option to show objects counts and sizes as percentages.">
-        Show counts and sizes as percentages.
-      </message>
-      <message name="IDS_NEW_OBJECTS_IN_DELTA" desc="Indicates that object instances are new compared to base state.">
-        new
-      </message>
-      <message name="IDS_DELETED_OBJECTS_IN_DELTA" desc="Indicates that object instances have disappeared compared to base state.">
-        deleted
-      </message>
-      <message name="IDS_VERY_LARGE_DELTA" desc="Shows very large delta in percents">
-        <ph name="SIGN">%s<ex>+</ex></ph> >1000%%
-      </message>
-      <message name="IDS_SHARE_IN_PERCENTS_SIGNED" desc="Share in percents, with sign.">
-        <ph name="SIGN">%$1s<ex>+</ex></ph><ph name="SHARE">%$2.2f<ex>5</ex></ph>%%
-      </message>
-      <message name="IDS_SIGNED_DELTA" desc="Signed delta.">
-        %$1s%$2d
-      </message>
-      <message name="IDS_SIGNED_STRING_DELTA" desc="Signed string delta.">
-        %$1s%$2s
-      </message>
-      <message name="IDS_OBJECTS_AND_DATA_SIZE_LABEL" desc="Label for objects and data size legend item.">
-        Objects and Data
-      </message>
-      <message name="IDS_CODE_SIZE_LABEL" desc="Label for code size legend item.">
-        Code
-      </message>
-    </messages>
-  </release>
-</grit>
diff --git a/webkit/glue/dom_operations.cc b/webkit/glue/dom_operations.cc
index 07c43b2..2533f57 100644
--- a/webkit/glue/dom_operations.cc
+++ b/webkit/glue/dom_operations.cc
@@ -9,17 +9,17 @@
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/string_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebAnimationController.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNodeCollection.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAnimationController.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeCollection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 
 using WebKit::WebAnimationController;
 using WebKit::WebDocument;
diff --git a/webkit/glue/dom_operations_unittest.cc b/webkit/glue/dom_operations_unittest.cc
index fac49c6..8d8d96b 100644
--- a/webkit/glue/dom_operations_unittest.cc
+++ b/webkit/glue/dom_operations_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/utf_string_conversions.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request_context.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/dom_operations.h"
 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
diff --git a/webkit/glue/dom_serializer_unittest.cc b/webkit/glue/dom_serializer_unittest.cc
index 62b5a3d..7bf3f62 100644
--- a/webkit/glue/dom_serializer_unittest.cc
+++ b/webkit/glue/dom_serializer_unittest.cc
@@ -10,20 +10,20 @@
 #include "base/utf_string_conversions.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request_context.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNodeCollection.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPageSerializer.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPageSerializerClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeCollection.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializer.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializerClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/dom_operations.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
diff --git a/webkit/glue/form_field.cc b/webkit/glue/form_field.cc
index bcc9926..82cac6a 100644
--- a/webkit/glue/form_field.cc
+++ b/webkit/glue/form_field.cc
@@ -6,9 +6,9 @@
 
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebOptionElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSelectElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebOptionElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSelectElement.h"
 
 using WebKit::WebFormControlElement;
 using WebKit::WebElement;
diff --git a/webkit/glue/form_field.h b/webkit/glue/form_field.h
index 23b7380..1874c44 100644
--- a/webkit/glue/form_field.h
+++ b/webkit/glue/form_field.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFormControlElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/ftp_directory_listing_response_delegate.cc b/webkit/glue/ftp_directory_listing_response_delegate.cc
index 80737db..0a2542b 100644
--- a/webkit/glue/ftp_directory_listing_response_delegate.cc
+++ b/webkit/glue/ftp_directory_listing_response_delegate.cc
@@ -18,8 +18,8 @@
 #include "net/base/net_util.h"
 #include "net/ftp/ftp_directory_listing_parser.h"
 #include "net/ftp/ftp_server_type_histograms.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
 
 using net::FtpDirectoryListingEntry;
 
diff --git a/webkit/glue/ftp_directory_listing_response_delegate.h b/webkit/glue/ftp_directory_listing_response_delegate.h
index e259c1e..9502761 100644
--- a/webkit/glue/ftp_directory_listing_response_delegate.h
+++ b/webkit/glue/ftp_directory_listing_response_delegate.h
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "net/ftp/ftp_directory_listing_buffer.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 
 namespace WebKit {
 class WebURLLoader;
diff --git a/webkit/glue/glue_serialize.cc b/webkit/glue/glue_serialize.cc
index 5b76784..df055fe 100644
--- a/webkit/glue/glue_serialize.cc
+++ b/webkit/glue/glue_serialize.cc
@@ -9,14 +9,14 @@
 #include "base/pickle.h"
 #include "base/utf_string_conversions.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHistoryItem.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPBody.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebData;
diff --git a/webkit/glue/glue_serialize.h b/webkit/glue/glue_serialize.h
index 303fe3a..3c5ee31 100644
--- a/webkit/glue/glue_serialize.h
+++ b/webkit/glue/glue_serialize.h
@@ -11,7 +11,7 @@
 #define WEBKIT_GLUE_GLUE_SERIALIZE_H_
 
 #include <string>
-#include "third_party/WebKit/WebKit/chromium/public/WebHistoryItem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/glue_serialize_unittest.cc b/webkit/glue/glue_serialize_unittest.cc
index 342696d..eebd9bf 100644
--- a/webkit/glue/glue_serialize_unittest.cc
+++ b/webkit/glue/glue_serialize_unittest.cc
@@ -7,9 +7,9 @@
 #include "base/pickle.h"
 #include "base/string_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPBody.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
 #include "webkit/glue/glue_serialize.h"
 #include "webkit/glue/web_io_operators.h"
 
diff --git a/webkit/glue/idb_bindings.cc b/webkit/glue/idb_bindings.cc
index 4af085f..c565f94 100644
--- a/webkit/glue/idb_bindings.cc
+++ b/webkit/glue/idb_bindings.cc
@@ -8,10 +8,10 @@
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBKey.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebIDBKeyPath.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyPath.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "v8/include/v8.h"
 
 namespace webkit_glue {
diff --git a/webkit/glue/iframe_redirect_unittest.cc b/webkit/glue/iframe_redirect_unittest.cc
index 9170d19..de98175 100644
--- a/webkit/glue/iframe_redirect_unittest.cc
+++ b/webkit/glue/iframe_redirect_unittest.cc
@@ -6,12 +6,12 @@
 
 #include "base/file_util.h"
 #include "base/string_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDataSource.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
 
diff --git a/webkit/glue/image_decoder.cc b/webkit/glue/image_decoder.cc
index 6850909..2982961 100644
--- a/webkit/glue/image_decoder.cc
+++ b/webkit/glue/image_decoder.cc
@@ -4,9 +4,9 @@
 
 #include "webkit/glue/image_decoder.h"
 
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebImage.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 #if WEBKIT_USING_CG
diff --git a/webkit/glue/image_decoder.h b/webkit/glue/image_decoder.h
index 62d9253..b19c8ef 100644
--- a/webkit/glue/image_decoder.h
+++ b/webkit/glue/image_decoder.h
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
-#include "gfx/size.h"
+#include "ui/gfx/size.h"
 
 class SkBitmap;
 
diff --git a/webkit/glue/image_resource_fetcher.cc b/webkit/glue/image_resource_fetcher.cc
index 6185834..65d80bd 100644
--- a/webkit/glue/image_resource_fetcher.cc
+++ b/webkit/glue/image_resource_fetcher.cc
@@ -5,8 +5,8 @@
 #include "webkit/glue/image_resource_fetcher.h"
 
 #include "base/callback.h"
-#include "gfx/size.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "ui/gfx/size.h"
 #include "webkit/glue/image_decoder.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -47,8 +47,12 @@
     // If we get here, it means no image from server or couldn't decode the
     // response as an image. The delegate will see a null image, indicating
     // that an error occurred.
-  callback_->Run(this, bitmap);
-  callback_.reset();
+
+  // Take care to clear callback_ before running the callback as it may lead to
+  // our destruction.
+  scoped_ptr<Callback> callback;
+  callback.swap(callback_);
+  callback->Run(this, bitmap);
 }
 
 }  // namespace webkit_glue
diff --git a/webkit/glue/inspector_strings.grd b/webkit/glue/inspector_strings.grd
index 22f147d..54fe5c6 100644
--- a/webkit/glue/inspector_strings.grd
+++ b/webkit/glue/inspector_strings.grd
@@ -4,8 +4,8 @@
 each locale. Specifically, these are UI strings that are used by WebKit
 Inspector that need to be translated for each locale.-->
 
-<!-- These strings and string descriptions were taken from
-WebKit/WebCore/English.lproj/localizedStrings.js @ revision 46732
+<!-- These strings and string descriptions were taken from WebKit
+Source/WebCore/English.lproj/localizedStrings.js @ revision 76508
 so we include the original license below:
 
 /*
@@ -43,6 +43,9 @@
   <outputs>
     <output filename="inspectorStrings_am.js" type="js_map_format" lang="am" />
     <output filename="inspectorStrings_ar.js" type="js_map_format" lang="ar" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="inspectorStrings_ast.js" type="js_map_format" lang="ast" />
+    </if>
     <output filename="inspectorStrings_bg.js" type="js_map_format" lang="bg" />
     <output filename="inspectorStrings_bn.js" type="js_map_format" lang="bn" />
     <output filename="inspectorStrings_ca.js" type="js_map_format" lang="ca" />
@@ -55,10 +58,16 @@
     <output filename="inspectorStrings_es.js" type="js_map_format" lang="es" />
     <output filename="inspectorStrings_es-419.js" type="js_map_format" lang="es-419" />
     <output filename="inspectorStrings_et.js" type="js_map_format" lang="et" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="inspectorStrings_eu.js" type="js_map_format" lang="eu" />
+    </if>
     <output filename="inspectorStrings_fa.js" type="js_map_format" lang="fa" />
     <output filename="inspectorStrings_fi.js" type="js_map_format" lang="fi" />
     <output filename="inspectorStrings_fil.js" type="js_map_format" lang="fil" />
     <output filename="inspectorStrings_fr.js" type="js_map_format" lang="fr" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="inspectorStrings_gl.js" type="js_map_format" lang="gl" />
+    </if>
     <output filename="inspectorStrings_gu.js" type="js_map_format" lang="gu" />
     <output filename="inspectorStrings_he.js" type="js_map_format" lang="he" />
     <output filename="inspectorStrings_hi.js" type="js_map_format" lang="hi" />
@@ -67,8 +76,14 @@
     <output filename="inspectorStrings_id.js" type="js_map_format" lang="id" />
     <output filename="inspectorStrings_it.js" type="js_map_format" lang="it" />
     <output filename="inspectorStrings_ja.js" type="js_map_format" lang="ja" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="inspectorStrings_ka.js" type="js_map_format" lang="ka" />
+    </if>
     <output filename="inspectorStrings_kn.js" type="js_map_format" lang="kn" />
     <output filename="inspectorStrings_ko.js" type="js_map_format" lang="ko" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="inspectorStrings_ku.js" type="js_map_format" lang="ku" />
+    </if>
     <output filename="inspectorStrings_lt.js" type="js_map_format" lang="lt" />
     <output filename="inspectorStrings_lv.js" type="js_map_format" lang="lv" />
     <output filename="inspectorStrings_ml.js" type="js_map_format" lang="ml" />
@@ -77,7 +92,6 @@
     <!-- The translation console uses 'no' for Norwegian Bokmål. It should
          be 'nb'. -->
     <output filename="inspectorStrings_nb.js" type="js_map_format" lang="no" />
-    <output filename="inspectorStrings_or.js" type="js_map_format" lang="or" />
     <output filename="inspectorStrings_pl.js" type="js_map_format" lang="pl" />
     <output filename="inspectorStrings_pt-BR.js" type="js_map_format" lang="pt-BR" />
     <output filename="inspectorStrings_pt-PT.js" type="js_map_format" lang="pt-PT" />
@@ -92,28 +106,59 @@
     <output filename="inspectorStrings_te.js" type="js_map_format" lang="te" />
     <output filename="inspectorStrings_th.js" type="js_map_format" lang="th" />
     <output filename="inspectorStrings_tr.js" type="js_map_format" lang="tr" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="inspectorStrings_ug.js" type="js_map_format" lang="ug" />
+    </if>
     <output filename="inspectorStrings_uk.js" type="js_map_format" lang="uk" />
     <output filename="inspectorStrings_vi.js" type="js_map_format" lang="vi" />
     <output filename="inspectorStrings_zh-CN.js" type="js_map_format" lang="zh-CN" />
     <output filename="inspectorStrings_zh-TW.js" type="js_map_format" lang="zh-TW" />
   </outputs>
   <translations>
-    <!-- TODO add references to each of the XTB files (from the Translation
-    Console) that contain translations of messages in your project.  Each
-    takes a form like <file path="english.xtb" />.  Remember that all file
-    references are relative to this .grd file. -->
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <file path="../../third_party/launchpad_translations/inspector_strings_ast.xtb" lang="ast" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_ca.xtb" lang="ca" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_de.xtb" lang="de" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_es.xtb" lang="es" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_eu.xtb" lang="eu" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_fi.xtb" lang="fi" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_fr.xtb" lang="fr" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_gl.xtb" lang="gl" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_he.xtb" lang="he" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_id.xtb" lang="id" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_it.xtb" lang="it" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_ku.xtb" lang="ku" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_nl.xtb" lang="nl" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_no.xtb" lang="no" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_pt-BR.xtb" lang="pt-BR" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_ro.xtb" lang="ro" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_ru.xtb" lang="ru" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_sl.xtb" lang="sl" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_sv.xtb" lang="sv" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_ug.xtb" lang="ug" />
+      <file path="../../third_party/launchpad_translations/inspector_strings_zh-CN.xtb" lang="zh-CN" />
+    </if>
   </translations>
   <release seq="1">
     <messages fallback_to_english="true">
-      <message name="IDS_HEADERS_COUNT" desc="Headers count.">
-        ''' (<ph name="COUNT">%d<ex>1</ex></ph>)
+      <message name="IDS_HEADERS_COUNT" desc="Request headers count.">
+        ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
       </message>
-      <message name="IDS_MESSAGE_REPEAT_COUNT" desc="Message repeat count.">
-        ''' (repeated <ph name="COUNT">%d<ex>2</ex></ph> times)
+      <message name="IDS_MESSAGE_REPEATED_TIMES" desc="The number of times a message got repeated.">
+        ''' (repeated <ph name="TIMES">%d<ex>3</ex></ph> times)
+      </message>
+      <message name="IDS_LINES_RANGE" desc="Source code lines range">
+        1 - <ph name="LAST_LINE">%d<ex>1000</ex></ph>
       </message>
       <message name="IDS_SIZE_IN_BYTES" desc="Size in bytes.">
         <ph name="SIZE">%.0f<ex>100</ex></ph>B
       </message>
+      <message name="IDS_SIZE_IN_KILOBYTES_ROUNDED" desc="Size in kilobytes.">
+        <ph name="SIZE">%.0f<ex>100</ex></ph>KB
+      </message>
+      <message name="IDS_SIZE_IN_MEGABYTES_ROUNDED" desc="Size in megabytes.">
+        <ph name="SIZE">%.0f<ex>100</ex></ph>MB
+      </message>
       <message name="IDS_DURATION_IN_MILLISECONDS" desc="Duration in milliseconds.">
         <ph name="DURATION">%.0f<ex>100</ex></ph>ms
       </message>
@@ -132,15 +177,21 @@
       <message name="IDS_SIZE_IN_KILOBYTES" desc="Size in kilobytes.">
         <ph name="SIZE">%.2f<ex>5</ex></ph>KB
       </message>
+      <message name="IDS_SIZE_IN_MEGABYTES" desc="Size in megabytes.">
+        <ph name="SIZE">%.2f<ex>100</ex></ph>MB
+      </message>
       <message name="IDS_DURATION_IN_SECONDS" desc="Duration in seconds.">
         <ph name="DURATION">%.2f<ex>5</ex></ph>s
       </message>
-      <message name="IDS_SIZE_IN_MEGABYTES" desc="Size in megabytes.">
-        <ph name="DURATION">%.3f<ex>5</ex></ph>MB
-      </message>
       <message name="IDS_DURATION_IN_MILLISECONDS_HIGH_PRECISION" desc="Duration in milliseconds, high precision.">
         <ph name="DURATION">%.3f<ex>5</ex></ph>ms
       </message>
+      <message name="IDS_NUMBER_OF_HIDDEN_CONSOLE_MESSAGES" desc="The number of hidden console messages.">
+        <ph name="NUMBER">%d<ex>10</ex></ph> console messages are not shown.
+      </message>
+      <message name="IDS_COOKIES_COUNT_AND_SIZE" desc="Cookies count and size.">
+        <ph name="COUNT">%1$d<ex>10</ex></ph> cookies (<ph name="SIZE">%2$s<ex>10KB</ex></ph>)
+      </message>
       <message name="IDS_ERRORS_COUNT_SINGULAR" desc="Errors count, singular.">
         <ph name="COUNT">%d<ex>1</ex></ph> error
       </message>
@@ -162,6 +213,9 @@
       <message name="IDS_MATCHES_COUNT_PLURAL" desc="Matches count, plural.">
         <ph name="COUNT">%d<ex>2</ex></ph> matches
       </message>
+      <message name="IDS_COUNTS_OF_CAPTURED_RECORDS" desc="Displayed and total counts of captured records.">
+        <ph name="DISPLAYED_COUNT">%1$d<ex>10</ex></ph> of <ph name="TOTAL_COUNT">%2$d<ex>100</ex></ph> captured records are visible
+      </message>
       <message name="IDS_STYLE_CHANGE_SINGULAR" desc="Style changes count, singular.">
         <ph name="COUNT">%d<ex>1</ex></ph> style change
       </message>
@@ -174,12 +228,33 @@
       <message name="IDS_WARNINGS_COUNT_PLURAL" desc="Warnings count, plural.">
         <ph name="COUNT">%d<ex>2</ex></ph> warnings
       </message>
+      <message name="IDS_IMAGE_DIMENSIONS_PIXELS_WITH_NATURAL_SIZE" desc="Image dimensions (uses mutiplication symbol, not x), with natural size.">
+        <ph name="WIDTH">%1$d<ex>100</ex></ph> × <ph name="HEIGHT">%2$d<ex>100</ex></ph> pixels (Natural: <ph name="NATURAL_WIDTH">%3$d<ex>100</ex></ph> × <ph name="NATURAL_HEIGHT">%4$d<ex>100</ex></ph> pixels)
+      </message>
+      <message name="IDS_IMAGE_DIMENSIONS_PIXELS" desc="Image dimensions in pixels (uses mutiplication symbol, not x.)">
+        <ph name="WIDTH">%1$d<ex>100</ex></ph> × <ph name="HEIGHT">%2$d<ex>100</ex></ph> pixels
+      </message>
       <message name="IDS_IMAGE_DIMENSIONS" desc="Image dimensions (uses mutiplication symbol, not x.)">
         <ph name="WIDTH">%1$d<ex>100</ex></ph> × <ph name="HEIGHT">%2$d<ex>100</ex></ph>
       </message>
+      <message name="IDS_RESOURCE_NAME_AND_SIZE" desc="Resource name ans size.">
+        <ph name="NAME">%1$s<ex>foo.html</ex></ph> (<ph name="SIZE">%2$s<ex>10KB</ex></ph>)
+      </message>
+      <message name="IDS_DURATION_AND_TIME" desc="Event duration and time.">
+        <ph name="DURATION">%1$s<ex>5 seconds</ex></ph> (at <ph name="TIME">%2$s<ex>10:25</ex></ph>)
+      </message>
       <message name="IDS_INDICATES_THAT_RESOURCE_IS_RETRIEVED_FROM_CACHE" desc="Indicates that resource is retrieved from cache.">
         <ph name="RESOURCE_NAME">%s<ex>picture.gif</ex></ph> (from cache)
       </message>
+      <message name="IDS_EVENT_DETAILS_TITLE" desc="Event details title.">
+        <ph name="EVENT">%s<ex>Paint</ex></ph> - Details
+      </message>
+      <message name="IDS_BIG_DELTA" desc="Big delta value.">
+        <ph name="SIGN">%s<ex>+</ex></ph> &gt;1000%%
+      </message>
+      <message name="IDS_BYTES_COLLECTED_DURING_GC" desc="Bytes collected during garbage collection.">
+        <ph name="BYTES">%s<ex>10KB</ex></ph> collected
+      </message>
       <message name="IDS_INDICATES_DURATION_OF_RESOURCE_DOWNLOAD" desc="Indicates duration of resource download.">
         <ph name="DURATION">%s<ex>5ms</ex></ph> download
       </message>
@@ -189,24 +264,84 @@
       <message name="IDS_INDICATES_DURATION_AND_LATENCY_OF_RESOURCE_DOWNLOAD" desc="Indicates duration and latency of resource download.">
         <ph name="LATENCY">%1$s<ex>5ms</ex></ph> latency, <ph name="DURATION">%2$s<ex>5ms</ex></ph> download (<ph name="TOTAL">%3$s<ex>10ms</ex></ph> total)
       </message>
+      <message name="IDS_USED_HEAP_SIZE_VALUES" desc="Used heap size values.">
+        <ph name="USED">%1$s<ex>10MB</ex></ph> of <ph name="TOTAL">%2$s<ex>20MB</ex></ph>
+      </message>
+      <message name="IDS_SIGNED_FLOAT_VALUE" desc="Signed value (float).">
+        <ph name="SIGN">%1$s<ex>+</ex></ph><ph name="VALUE">%2$.2f<ex>100</ex></ph>%%
+      </message>
+      <message name="IDS_SIGNED_INTEGER_VALUE" desc="Signed value (integer).">
+        <ph name="SIGN">%1$s<ex>+</ex></ph><ph name="VALUE">%2$d<ex>10</ex></ph>
+      </message>
+      <message name="IDS_SIGNED_SIZE" desc="Signed size.">
+        <ph name="SIGN">%1$s<ex>+</ex></ph><ph name="VALUE">%2$s<ex>10KB</ex></ph>
+      </message>
       <message name="IDS_LABELS_AN_ANONYMOUS_JAVASCRIPT_FUNCTION" desc="Labels an anonymous JavaScript function.">
         (anonymous function)
       </message>
+      <message name="IDS_INTERNAL_SCRIPT" desc="A label for an internal script.">
+        (internal script)
+      </message>
+      <message name="IDS_RESOURCE_FROM_CACHE" desc="A label for a resource from cache.">
+        (from cache)
+      </message>
       <message name="IDS_LABELS_PROGRAM_AS_A_WHOLE" desc="Labels program as a whole.">
         (program)
       </message>
-      <message name="IDS_LABELS_A_SCRIPT_WITH_URL" desc="Labels a script with URL.">
-        (program): <ph name="URL">%s<ex>http://site/script.js</ex></ph>
-      </message>
       <message name="IDS_LABELS_A_TEXT_NODE_IN_HTML_TREE" desc="Labels a text node in HTML tree.">
         (text)
       </message>
+      <message name="IDS_UNABLE_DECODE_VALUE" desc="A message for an undecoded value.">
+        (unable to decode value)
+      </message>
       <message name="IDS_LABELS_A_WHITESPACE_NODE_IN_HTML_TREE" desc="Labels a whitespace node in HTML tree.">
         (whitespace)
       </message>
       <message name="IDS_MATCHES_COUNT_SINGULAR" desc="Matches count, singular.">
         1 match
       </message>
+      <message name="IDS_SOURCE_IS_NOT_AVAILABLE" desc="A message indicating that script source isn't available.">
+        &lt;source is not available&gt;
+      </message>
+      <message name="IDS_APPLICATION_CACHE" desc="Application Cache label.">
+        Application Cache
+      </message>
+      <message name="IDS_ACCEPT_SUGGESTION" desc="Description for an action of accepting a command suggestion.">
+        Accept suggestion
+      </message>
+      <message name="IDS_ACTIVATE_ALL_BREAKPOINTS" desc="A command for activating all breakpoints.">
+        Activate all breakpoints.
+      </message>
+      <message name="IDS_ADD_ATTRIBUTE" desc="A command for adding an attribute.">
+        Add Attribute
+      </message>
+      <message name="IDS_ADD_BREAKPOINT" desc="A command for adding a breakpoint.">
+        Add Breakpoint
+      </message>
+      <message name="IDS_ADD_CONDITIONAL_BREAKPOINT" desc="A command for adding a conditional breakpoint.">
+        Add Conditional Breakpoint…
+      </message>
+      <message name="IDS_ADD_NEW_ROW" desc="A command for adding a row in a table.">
+        Add New
+      </message>
+      <message name="IDS_ADD_WATCH_EXPRESSION" desc="A command for adding a watch expression.">
+        Add
+      </message>
+      <message name="IDS_AGGREGATED_TIME" desc="A label for event aggregated time.">
+        Aggregated Time
+      </message>
+      <message name="IDS_EVENTS_FOR_ALL_NODES" desc="An option to view events for all nodes.">
+        All Nodes
+      </message>
+      <message name="IDS_ALL_PANELS" desc="A label for shortcuts available in all panels.">
+        All Panels
+      </message>
+      <message name="IDS_SHOW_ALL" desc="An option to show all elements (w/o filtering).">
+        All
+      </message>
+      <message name="IDS_ALLOW_DEBUGGING_WORKERS" desc="Allow debugging Web workers.">
+        Allow debugging workers. Enabling this option will replace native workers with the iframe-based JavaScript implementation
+      </message>
       <message name="IDS_SPECIFIES_THAT_SOME_FEATURE_IS_ALWAYS_ENABLED" desc="Specifies that some feature is always enabled.">
         Always enable
       </message>
@@ -216,47 +351,134 @@
       <message name="IDS_ERROR_MESSAGE_DISPLAYED_WHEN_AN_UNEXPECTED_ERROR_OCCURS_DURING_DATABASE_QUERY" desc="Error message displayed when an unexpected error occurs during database query.">
         An unexpected error <ph name="ERROR">%s<ex>No memory</ex></ph> occurred.
       </message>
+      <message name="IDS_BREAK_ON_ANY_XHR" desc="Debugger should break on any XHR request.">
+        Any XHR
+      </message>
+      <message name="IDS_COLOR_AS_AUTHORED" desc="An option to show color value as authored in the stylesheet.">
+        As Authored
+      </message>
+      <message name="IDS_ASSERTION_FAILED" desc="A prefix for an assertion failure message.">
+        Assertion failed:
+      </message>
+      <message name="IDS_BREAK_ON_ATTRIBUTE_MODIFIED" desc="A condition for breaking execution on DOM node attribute modification.">
+        Attribute Modified
+      </message>
+      <message name="IDS_AUDIT_PRESENT_STATE" desc="A label for checkbox enabling audit of page's present state.">
+        Audit Present State
+      </message>
+      <message name="IDS_AUDITS_PANEL" desc="Audits panel label.">
+        Audits
+      </message>
       <message name="IDS_LABEL_OF_A_GRID_COLUMN_SHOWING_AVERAGE_FUNCTION_EXECUTION_TIME" desc="Label of a grid column showing average function execution time.">
         Average
       </message>
+      <message name="IDS_BLOCKING_DURATION" desc="A label for the duration of connection blocking state.">
+        Blocking
+      </message>
       <message name="IDS_LABEL_OF_A_SIDE_PANEL_SHOWING_BREAKPOINTS" desc="Label of a side panel showing breakpoints.">
         Breakpoints
       </message>
+      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_COOKIES" desc="Label for a section showing cookies.">
+        Cookies
+      </message>
+      <message name="IDS_CPU_PROFILES" desc="A label for the CPU profiles list (all caps).">
+        CPU PROFILES
+      </message>
+      <message name="IDS_CALL_SITE_STACK" desc="A label for event call stack.">
+        Call Site stack
+      </message>
       <message name="IDS_LABEL_OF_A_SIDE_PANEL_SHOWING_CALL_STACK" desc="Label of a side panel showing call stack.">
         Call Stack
       </message>
       <message name="IDS_LABEL_OF_A_GRID_COLUMN_SHOWING_FUNCTION_CALL_COUNT" desc="Label of a grid column showing function call count.">
         Calls
       </message>
+      <message name="IDS_CLEAR_CPU_PROFILES" desc="Label of the button for clearing all CPU profiles.">
+        Clear CPU profiles.
+      </message>
+      <message name="IDS_CLEAR_CONSOLE" desc="Label of the button that clears console messages.">
+        Clear Console
+      </message>
+      <message name="IDS_CLEAR_AUDIT_RESULTS" desc="Label of the button cleaning up audits results.">
+        Clear audit results.
+      </message>
       <message name="IDS_HINT_FOR_A_BUTTON_CLEARING_CHANGES_LOG" desc="Hint for a button clearing changes log.">
         Clear changes log.
       </message>
       <message name="IDS_HINT_FOR_A_BUTTON_CLEARING_CONSOLE_LOG" desc="Hint for a button clearing console log.">
         Clear console log.
       </message>
+      <message name="IDS_CLEAR" desc="A label for a button that clears a list.">
+        Clear
+      </message>
+      <message name="IDS_CLICK_TO_CHANGE_COLOR_FORMAT" desc="Click to change color format.">
+        Click to change color format
+      </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_CLOSURE_VARIABLES" desc="Label for a section in the scope chain sidebar that shows closure's variables.">
         Closure
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_COOKIES_CAPS" desc="Label for a section showing cookies.">
-        COOKIES
+      <message name="IDS_RESOURCE_TYPE_CODE" desc="Resource type: Code">
+        Code
+      </message>
+      <message name="IDS_COLLECTED" desc="A label for a column displaying the size of collected garbage.">
+        Collected
+      </message>
+      <message name="IDS_COMPARED_TO" desc="A selector of a heap profile to compare with.">
+        Compared to <ph name="PROFILE_NAME">%s<ex>Snapshot 1</ex></ph>
       </message>
       <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_COMPUTED_STYLE" desc="Label for a section showing computed style.">
         Computed Style
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_COOKIES" desc="Label for a section showing cookies.">
-        Cookies
+      <message name="IDS_CONNECTING" desc="A label for the duration of connection connecting state.">
+        Connecting
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_DATABASES" desc="Label for a section showing databases.">
-        DATABASES
+      <message name="IDS_CONSOLE" desc="A label for the Console panel.">
+        Console
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_DOM" desc="Label for a section showing DOM.">
-        DOM
+      <message name="IDS_CONSTRUCTOR" desc="A label for a cell displaying object constructor name.">
+        Constructor
+      </message>
+      <message name="IDS_CONTENT" desc="A label for a tab displaying resource content.">
+        Content
+      </message>
+      <message name="IDS_CONTINUE_TO_HERE" desc="A command for continuing script execution up to specified position.">
+        Continue to Here
+      </message>
+      <message name="IDS_CONTINUE" desc="A command for continuing script execution.">
+        Continue
+      </message>
+      <message name="IDS_CONTROL_CPU_PROFILING" desc="An instruction on how to start CPU profiling.">
+        Control CPU profiling by pressing the <ph name="BUTTON">%s<ex>button glyph</ex></ph> button on the status bar.
+      </message>
+      <message name="IDS_COPY_AS_HTML" desc="A command for copying node contents as HTML.">
+        Copy as HTML
+      </message>
+      <message name="IDS_COUNT" desc="A label for a column with entities count.">
+        Count
+      </message>
+      <message name="IDS_LABEL_FOR_THE_TAB_SHOWING_DATABASES" desc="Label for the tab showing databases.">
+        Databases
+      </message>
+      <message name="IDS_DNS_LOOKUP" desc="A label for displaying DNS lookup time.">
+        DNS Lookup
+      </message>
+      <message name="IDS_DOM_CONTENT_EVENT_FIRED" desc="A label for the moment of time when DOMContent event fired.">
+        DOMContent event fired
+      </message>
+      <message name="IDS_DON_CONTENT_EVENT" desc="A label for the DOMContent event.">
+        DOMContent event
       </message>
       <message name="IDS_ERROR_MESSAGE_INDICATING_DATABASE_VERSION_MISMATCH" desc="Error message indicating database version mismatch.">
         Database no longer has expected version.
       </message>
-      <message name="IDS_LABEL_FOR_THE_TAB_SHOWING_DATABASES" desc="Label for the tab showing databases.">
-        Databases
+      <message name="IDS_DATABASE_NOT_FOUND" desc="Error message indicating that database is not found.">
+        Database not found.
+      </message>
+      <message name="IDS_DEACTIVATE_ALL_BREAKPOINTS" desc="A command for deactivating all breakpoints.">
+        Deactivate all breakpoints.
+      </message>
+      <message name="IDS_DEBUG_WORKERS" desc="A label for the checkbox enabling Web workers debugging.">
+        Debug
       </message>
       <message name="IDS_MESSAGE_INDICATING_THAT_DEBUGGING_IS_DISABLED" desc="Message indicating that debugging is disabled.">
         Debugging disabled. Click to enable.
@@ -264,128 +486,356 @@
       <message name="IDS_MESSAGE_INDICATING_THAT_DEBUGGING_IS_ENABLED" desc="Message indicating that debugging is enabled.">
         Debugging enabled. Click to disable.
       </message>
-      <message name="IDS_A_HINT_THAT_REMINDS_TO_TURN_ON_DEBUGGER" desc="A hint that reminds to turn on debugger.">
-        Debugging scripts requires you to start the debugger.
+      <message name="IDS_DELETE_NODE" desc="A command for deleting DOM node.">
+        Delete Node
+      </message>
+      <message name="IDS_DELETE_WATCH_EXPRESSION" desc="A command for deleting watch expression.">
+        Delete watch expression.
       </message>
       <message name="IDS_A_BUTTON_FOR_DELETING_DOM_STORAGE_ITEMS" desc="A button for deleting DOM storage items.">
         Delete
       </message>
+      <message name="IDS_DETAILS" desc="A label for additional details about timeline event.">
+        Details
+      </message>
       <message name="IDS_LABEL_OF_IMAGE_DIMENSIONS_GRID_COLUMN" desc="Label of image dimensions grid column.">
         Dimensions
       </message>
+      <message name="IDS_DISABLE_BREAKPOINT" desc="A command to disable a breakpoint.">
+        Disable Breakpoint
+      </message>
       <message name="IDS_HINT_FOR_A_BUTTON_THAT_DOCKS_INSPECTOR_TO_MAIN_WINDOW" desc="Hint for a button that docks Inspector to main window.">
         Dock to main window.
       </message>
+      <message name="IDS_DOCUMENT" desc="Title for the resources of the type Document.">
+        Document
+      </message>
       <message name="IDS_LABEL_FOR_DOCUMENTS_RESOURCE_SECTION" desc="Label for documents resource section.">
         Documents
       </message>
-      <message name="IDS_HINT_FOR_A_BUTTON_THAT_DISABLES_PAUSE_EXECUTION_ON_EXCEPTIONS" desc="Hint for a button that disables pause execution on exceptions.">
-        Don't pause on exceptions.
+      <message name="IDS_COOKIE_DOMAIN" desc="A label for the column displaying cookie's domain name.">
+        Domain
       </message>
-      <message name="IDS_DOUBLE_CLICK_TO_ADD" desc="Instruction on adding an element.">
-        Double-Click to Add
+      <message name="IDS_NO_PAUSE_ON_EXCEPTIONS" desc="The current state: don't pause on exception, after LF: a hint for a button that changes the state.">
+        Don't pause on exceptions.\nClick to Pause on all exceptions.
+      </message>
+      <message name="IDS_TOGGLE_URL_FORMAT" desc="A hint on how to toggle between URL formats.">
+        Double-Click to toggle between URL encoded and decoded formats
+      </message>
+      <message name="IDS_EDIT_ATTRIBUTE_CAPITALIZED" desc="Text for a shortcut for editing a DOM node attrubute.">
+        Edit Attribute
+      </message>
+      <message name="IDS_EDIT_BREAKPOINT" desc="A command for editing breakpoint properties.">
+        Edit Breakpoint…
+      </message>
+      <message name="IDS_EDIT_TEXT" desc="A command for editing DOM node text content.">
+        Edit Text
+      </message>
+      <message name="IDS_EDIT_AS_HTML" desc="A command for editing DOM node as HTML.">
+        Edit as HTML
+      </message>
+      <message name="IDS_EDIT_ATTRIBUTE" desc="A command for editing a DOM node attrubute.">
+        Edit attribute
+      </message>
+      <message name="IDS_EDIT" desc="A command for editing table's node contents.">
+        Edit
+      </message>
+      <message name="IDS_ELEMENTS_PANEL" desc="A label for the HTML elements panel.">
+        Elements Panel
       </message>
       <message name="IDS_LABEL_FOR_HTML_ELEMENTS_PANEL" desc="Label for HTML elements panel.">
         Elements
       </message>
+      <message name="IDS_ENABLE_BREAKPOINT" desc="A label for a checkbox that enables a breakpoint.">
+        Enable Breakpoint
+      </message>
       <message name="IDS_HINT_FOR_A_BUTTON_THAT_ENABLES_DEBUGGING" desc="Hint for a button that enables debugging.">
         Enable Debugging
       </message>
       <message name="IDS_HINT_FOR_A_BUTTON_THAT_ENABLES_PROFILING" desc="Hint for a button that enables profiling.">
         Enable Profiling
       </message>
-      <message name="IDS_HINT_FOR_A_BUTTON_THAT_ENABLES_RESOURCE_TRACKING" desc="Hint for a button that enables resource tracking.">
-        Enable resource tracking
-      </message>
       <message name="IDS_A_WARNING_MESSAGE_ABOUT_DEBUGGING" desc="A warning message about debugging.">
         Enabling debugging will make scripts run slower.
       </message>
       <message name="IDS_A_WARNING_MESSAGE_ABOUT_PROFILING" desc="A warning message about profiling.">
         Enabling profiling will make scripts run slower.
       </message>
-      <message name="IDS_A_WARNING_MESSAGE_ABOUT_RESOURCE_TRACKING" desc="A warning message about resource tracking.">
-        Enabling resource tracking will reload the page and make page loading slower.
+      <message name="IDS_ERRORS_FILTER" desc="A label for the filter in the Console.">
+        Errors
+      </message>
+      <message name="IDS_EVALUATE_SCRIPT_EVENT" desc="A label for the script evaluation event.">
+        Evaluate Script
       </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_EVENT_DOCUMENT_VARIABLES" desc="Label for a section in the scope chain sidebar that shows event document's variables.">
         Event Document
       </message>
+      <message name="IDS_EVENT_LISTENERS" desc="A label for the section showing event listeners.">
+        Event Listeners
+      </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_EVENT_TARGET_VARIABLES" desc="Label for a section in the scope chain sidebar that shows event target's variables.">
         Event Target
       </message>
+      <message name="IDS_EVENT_TYPE" desc="A label for the script events type.">
+        Event
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_EXCLUDES_A_FUNCTION_FROM_EXECUTION_PROFILE" desc="Label for a button that excludes a function from execution profile.">
         Exclude selected function.
       </message>
+      <message name="IDS_EXECUTE_COMMAND" desc="A label for the command for script execution.">
+        Execute command
+      </message>
+      <message name="IDS_EXPAND_COLLAPSE" desc="A command for expanding/collapsing DOM node.">
+        Expand/collapse
+      </message>
+      <message name="IDS_EXPECTED_CONTENT_LENGTH" desc="A label for resource's expected content length.">
+        Expected Content Length
+      </message>
+      <message name="IDS_COOKIE_EXPIRES" desc="A label for the column displaying cookie expiration time.">
+        Expires
+      </message>
+      <message name="IDS_EXPORT_ALL_TO_HAR" desc="A command for exporting all statistics to HAR format.">
+        Export all to HAR
+      </message>
+      <message name="IDS_EXPORT_TO_HAR" desc="A command for exporting certain records to HAR format.">
+        Export to HAR
+      </message>
       <message name="IDS_LABEL_OF_IMAGE_FILE_SIZE_GRID_COLUMN" desc="Label of image file size grid column.">
         File size
       </message>
+      <message name="IDS_STORAGE_FILE_SYSTEM" desc="Storage category: file system.">
+        File System
+      </message>
+      <message name="IDS_FIND_NEXT_PREVIOUS" desc="Title of help section displaying search-related shortcuts.">
+        Find next/previous
+      </message>
+      <message name="IDS_FINISH_LOADING" desc="A label for the page finished loading event.">
+        Finish Loading
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_FOCUSES_ON_A_FUNCTION_FROM_EXECUTION_PROFILE" desc="Label for a button that focuses on a function from execution profile.">
         Focus selected function.
       </message>
+      <message name="IDS_FONT_RESOURCE" desc="Font resource name.">
+        Font
+      </message>
       <message name="IDS_LABEL_FOR_FONTS_RESOURCE_SECTION" desc="Label for fonts resource section.">
         Fonts
       </message>
+      <message name="IDS_FORM_DATA" desc="A title for HTML form data.">
+        Form Data
+      </message>
+      <message name="IDS_FUNCTION_CALL_TIMELINE_EVENT" desc="Function call Timeline event.">
+        Function Call
+      </message>
       <message name="IDS_LABEL_OF_A_GRID_COLUMN_SHOWING_FUNCTION_NAME" desc="Label of a grid column showing function name.">
         Function
       </message>
-      <message name="IDS_LABEL_FOR_GRAPHS_SIDEBAR" desc="Label for graphs sidebar.">
-        GRAPHS
+      <message name="IDS_GC_TIMELINE_EVENT" desc="Garbage collection Timeline event.">
+        GC Event
+      </message>
+      <message name="IDS_HEAP_SNAPSHOT_HELP" desc="Help text on how to get a heap snapshot.">
+        Get a heap snapshot by pressing the <ph name="BUTTON">%s<ex>button glyph</ex></ph> button on the status bar.
       </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_GLOBAL_VARIABLES" desc="Label for a section in the scope chain sidebar that shows global variables.">
         Global
       </message>
-      <message name="IDS_LABEL_INDICATING_THAT_BOTTOM-UP_HEAVY_PROFILE_IS_SHOWN" desc="Label indicating that bottom-up (heavy) profile is shown.">
+      <message name="IDS_GO_TO_LINE_BUTTON" desc="A label for a button that takes you to designated line.">
+        Go
+      </message>
+      <message name="IDS_GO_TO_LINE_LABEL" desc="A label for the input box for enterting line number.">
+        Go to line: 
+      </message>
+      <message name="IDS_HEAP_SNAPSHOTS" desc="A label for the heap snapshots list (all caps).">
+        HEAP SNAPSHOTS
+      </message>
+      <message name="IDS_HSL_COLORS" desc="A label for the option to display colors in HSL format.">
+        HSL Colors
+      </message>
+      <message name="IDS_HTTP" desc="HTTP protocol label.">
+        HTTP
+      </message>
+      <message name="IDS_HEADERS" desc="A label for the section displaying HTTP headers.">
+        Headers
+      </message>
+      <message name="IDS_LABEL_INDICATING_THAT_BOTTOM_UP_HEAVY_PROFILE_IS_SHOWN" desc="Label indicating that bottom-up (heavy) profile is shown.">
         Heavy (Bottom Up)
       </message>
+      <message name="IDS_HEX_COLORS" desc="A label for the option to display colors in hexadecimal format.">
+        Hex Colors
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_HIDES_CHANGES" desc="Label for a button that hides changes view.">
         Hide changes view.
       </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_HIDES_CONSOLE" desc="Label for a button that hides console.">
         Hide console.
       </message>
+      <message name="IDS_HIDE_SHORT_RECORDS" desc="A label for hiding records that has shorter duration than specified.">
+        Hide the records that are shorter than <ph name="DURATION">%s<ex>15 ms</ex></ph>
+      </message>
+      <message name="IDS_IMAGE_RESOURCE" desc="Resource of image type.">
+        Image
+      </message>
       <message name="IDS_LABEL_FOR_IMAGES_RESOURCE_SECTION" desc="Label for images resource section.">
         Images
       </message>
-      <message name="IDS_LABEL_FOR_INLINE_STYLE_ATTRIBUTE" desc="Label for inline style attribute.">
-        Inline Style Attribute
+      <message name="IDS_INCREMENT_DECREMENT_HELP" desc="Help text for shortcuts that increment/decrement values.">
+        Increment/decrement by <ph name="VALUE">%f<ex>10</ex></ph>
+      </message>
+      <message name="IDS_INCREMENT_DECREMENT_HELP_2" desc="Help text for shortcuts that increment/decrement values.">
+        Increment/decrement value
+      </message>
+      <message name="IDS_STYLE_INHERITED_FROM" desc="A label for diplaying the ancestor of the current CSS style.">
+        Inherited from
+      </message>
+      <message name="IDS_INSTALL_TIMER_EVENT" desc="A label for the Install Timer event.">
+        Install Timer
       </message>
       <message name="IDS_LABEL_FOR_A_GRID_COLUMN_SHOWING_PROPERTY_KEY" desc="Label for a grid column showing property key.">
         Key
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_LOCAL_STORAGE" desc="Label for a section showing local storage.">
-        LOCAL STORAGE
+      <message name="IDS_KEYBOARD_SHORTCUTS" desc="A label for the keyboard shortcuts help card.">
+        Keyboard Shortcuts
+      </message>
+      <message name="IDS_LOCAL_STORAGE_LABEL" desc="A label for the section displaying page's local storage contents.">
+        Local Storage
+      </message>
+      <message name="IDS_LAYOUT_EVENT" desc="A label for the layout event.">
+        Layout
+      </message>
+      <message name="IDS_LOAD_EVENT_BAR" desc="A label for the bar indicating load event time.">
+        Load event fired
+      </message>
+      <message name="IDS_LOAD_EVENT" desc="A label for the load event.">
+        Load event
+      </message>
+      <message name="IDS_RESOURCES_LOADING_PROGRESS" desc="Progress for resources loading.">
+        Loading (<ph name="LOADED">%1$d<ex>5</ex></ph> of <ph name="TOTAL">%2$d<ex>10</ex></ph>)
+      </message>
+      <message name="IDS_LOADING_CATEGORY" desc="A label for loading-related category of events.">
+        Loading
+      </message>
+      <message name="IDS_LOCAL_FILES" desc="A label for the section showing local files.">
+        Local Files
       </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_LOCAL_VARIABLES" desc="Label for a section in the scope chain sidebar that shows local variables.">
         Local
       </message>
+      <message name="IDS_EVENT_LOCATION" desc="A label for the event source location.">
+        Location
+      </message>
+      <message name="IDS_LOGS_FILTER" desc="A label for the filter displaying log events.">
+        Logs
+      </message>
+      <message name="IDS_MIME_TYPE" desc="A label for the MIME type.">
+        MIME Type
+      </message>
       <message name="IDS_LABEL_OF_IMAGE_MIME_TYPE_GRID_COLUMN" desc="Label of image MIME type grid column.">
         MIME type
       </message>
+      <message name="IDS_MARK_EVENT" desc="A label for the mark in Timeline events.">
+        Mark
+      </message>
+      <message name="IDS_MATCHED_CSS_RULES" desc="A label for the section displaying CSS rules that match the selected element.">
+        Matched CSS Rules
+      </message>
+      <message name="IDS_MEDIA_RESOURCE" desc="Resource type: Media.">
+        Media
+      </message>
+      <message name="IDS_MEMORY_GRAPH" desc="A label for the memory usage graph.">
+        Memory
+      </message>
       <message name="IDS_LABEL_FOR_HTML_ELEMENT_METRICS_SIDE_PANEL" desc="Label for HTML element metrics side panel.">
         Metrics
       </message>
+      <message name="IDS_NAME" desc="A label for the column displaying entity name.">
+        Name
+      </message>
+      <message name="IDS_NAVIGATE_ELEMENTS_HELP" desc="A title for the help section displaying elements navigation shortcuts.">
+        Navigate elements
+      </message>
+      <message name="IDS_NEW_STYLE_RULE" desc="A command for adding a new style rule.">
+        New Style Rule
+      </message>
+      <message name="IDS_NEXT_PREVIOUS_CALL_FRAME_HELP" desc="A title for the help section displaying call frames navigation shortcuts.">
+        Next/previous call frame
+      </message>
+      <message name="IDS_NEXT_PREVIOUS_COMMAND_HELP" desc="A title for the help section displaying console commands history navigation shortcuts.">
+        Next/previous command
+      </message>
+      <message name="IDS_NEXT_PREVIOUS_LINE_HELP" desc="A title for the help section displaying console lines navigation shortcuts.">
+        Next/previous line
+      </message>
+      <message name="IDS_NEXT_PREVIOUS_PANEL_HELP" desc="A title for the help section displaying panels navigation shortcuts.">
+        Next/previous panel
+      </message>
+      <message name="IDS_NEXT_PREVIOUS_PROPERTY_HELP" desc="A title for the help section displaying panels navigation shortcuts.">
+        Next/previous property
+      </message>
+      <message name="IDS_NEXT_PREVIOUS_SUGGESTION_HELP" desc="A title for the help section displaying panels navigation shortcuts.">
+        Next/previous suggestion
+      </message>
+      <message name="IDS_NO_APPLICATION_CACHE" desc="A message indicating that no Application Cache information is available">
+        No Application Cache information available.
+      </message>
       <message name="IDS_MESSAGE_IN_BREAKPOINTS_SIDEBAR_PANEL_INDICATING_THAT_THERE_ARE_NO_BREAKPOINTS" desc="Message in breakpoints sidebar panel indicating that there are no breakpoints.">
         No Breakpoints
       </message>
+      <message name="IDS_NO_EVENT_LISTENERS" desc="A message indicating that the selected DOM node has no event listeners.">
+        No Event Listeners
+      </message>
       <message name="IDS_MESSAGE_IN_OBJECT_PROPERTIES_SIDEBAR_PANEL_INDICATING_THAT_THERE_ARE_NO_PROPERTIES" desc="Message in object properties sidebar panel indicating that there are no properties.">
         No Properties
       </message>
       <message name="IDS_MESSAGE_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_SHOWING_VARIABLES_ABSENCE" desc="Message for a section in the scope chain sidebar showing variables absence.">
         No Variables
       </message>
-      <message name="IDS_MESSAGE_INDICATING_THAT_SEARCHED_STRING_DOESN'T_FOUND" desc="Message indicating that searched string doesn't found.">
+      <message name="IDS_NO_AUDITS" desc="A message indicating that there are no audit rules to check against.">
+        No audits to run
+      </message>
+      <message name="IDS_NODE_REMOVED_BREAKPOINT" desc="Title for a breakpoint triggering on DOM node removal.">
+        Node Removed
+      </message>
+      <message name="IDS_MESSAGE_INDICATING_THAT_SEARCHED_STRING_DOES_NOT_FOUND" desc="Message indicating that searched string doesn't found.">
         Not Found
       </message>
-      <message name="IDS_MESSAGE_INDICATING_THAT_PROGRAM_ISN'T_PAUSED" desc="Message indicating that program isn't paused.">
+      <message name="IDS_MESSAGE_INDICATING_THAT_PROGRAM_IS_NOT_PAUSED" desc="Message indicating that program isn't paused.">
         Not Paused
       </message>
+      <message name="IDS_OBJECTS_COLUMN" desc="A title for the column displaying JavaScript object names.">
+        Objects
+      </message>
+      <message name="IDS_OFFLINE" desc="Browser state: offline">
+        Offline
+      </message>
+      <message name="IDS_ONLINE" desc="Browser state: online">
+        Online
+      </message>
       <message name="IDS_SPECIFIES_THAT_SOME_FEATURE_IS_ONLY_ENABLED_FOR_CURRENT_SESSION" desc="Specifies that some feature is only enabled for current session.">
         Only enable for this session
       </message>
+      <message name="IDS_OPEN_LINK_IN_NEW_WINDOW" desc="Action: open a link in a new window.">
+        Open Link in New Window
+      </message>
+      <message name="IDS_OPEN_LINK_IN_RESOURCES_PANEL" desc="Action: open a link in the resources panel.">
+        Open Link in Resources Panel
+      </message>
       <message name="IDS_LABEL_FOR_OTHER_RESOURCES_SECTION" desc="Label for other resources section.">
         Other
       </message>
-      <message name="IDS_HINT_FOR_A_BUTTON_THAT_ENABLES_PAUSE_EXECUTION_ON_EXCEPTIONS" desc="Hint for a button that enables pause execution on exceptions.">
-        Pause on exceptions.
+      <message name="IDS_PAINT_EVENT" desc="Paint event name.">
+        Paint
+      </message>
+      <message name="IDS_PARSE_EVENT" desc="Parse event name.">
+        Parse
+      </message>
+      <message name="IDS_PATH" desc="Path of a resource.">
+        Path
+      </message>
+      <message name="IDS_PAUSE_ON_ALL_EXCEPTIONS" desc="Current state: pause on all exceptions. After the \n separator: a hint on how to switch the state.">
+        Pause on all exceptions.\nClick to Pause on uncaught exceptions.
+      </message>
+      <message name="IDS_PAUSE_ON_UNHANDLED_EXCEPTIONS" desc="Current state: pause on unhandled exceptions. After the \n separator: a hint on how to switch the state.">
+        Pause on uncaught exceptions.\nClick to Not pause on exceptions.
       </message>
       <message name="IDS_HINT_FOR_A_BUTTON_THAT_PAUSES_SCRIPT_EXECUTION" desc="Hint for a button that pauses script execution.">
         Pause script execution.
@@ -411,60 +861,168 @@
       <message name="IDS_LABEL_FOR_OBJECT_PROPERTIES_SIDEBAR" desc="Label for object properties sidebar.">
         Properties
       </message>
-      <message name="IDS_LABEL_FOR_THE_PROTOTYPE_PROPERTY" desc="Label for the prototype property.">
-        Prototype
+      <message name="IDS_PROXY_TIMING" desc="A label for the time spent on interacting with proxy server.">
+        Proxy
       </message>
-      <message name="IDS_LABEL_FOR_DATABASE_QUERY" desc="Label for database query.">
-        Query
+      <message name="IDS_PSEUDO_DOUBLE_COLON_ELEMENT" desc="A label for a pseudo element.">
+        Pseudo ::<ph name="NAME">%s<ex>above</ex></ph> element
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_RESOURCES" desc="Label for a section showing resources.">
-        RESOURCES
+      <message name="IDS_PSEUDO_ELEMENT" desc="A label for a pseudo element.">
+        Pseudo element
+      </message>
+      <message name="IDS_HTTP_QUERY_PARAMETERS" desc="HTTP query parameters">
+        Query String Parameters
+      </message>
+      <message name="IDS_TIMELINE_RECORDS_LIST_HEADER_ALL_CAPS" desc="Timeline records list header (all caps.)">
+        RECORDS
+      </message>
+      <message name="IDS_AUDIT_RESULTS_ALL_CAPS" desc="Audit results (all caps.)">
+        RESULTS
+      </message>
+      <message name="IDS_SHOW_COLORS_IN_RGB_FORMAT" desc="Show colors in RGB format.">
+        RGB Colors
+      </message>
+      <message name="IDS_RECALCULATE_STYLES_TIMELINE_EVENT" desc="Recalculate styles Timeline event.">
+        Recalculate Style
+      </message>
+      <message name="IDS_RECEIVE_DATA_TIMELINE_EVENT" desc="Receive data Timeline event.">
+        Receive Data
+      </message>
+      <message name="IDS_RECEIVE_RESPONSE_TIMELINE_EVENT" desc="Receive response Timeline event.">
+        Receive Response
+      </message>
+      <message name="IDS_TIME_SPENT_ON_RECEIVING_A_RESOURCE" desc="Time spent on receiving a resource.">
+        Receiving
+      </message>
+      <message name="IDS_RECORD_BUTTON_LABEL" desc="Record button label.">
+        Record
+      </message>
+      <message name="IDS_RECORDING_CPU_PROFILE_STATUS_MESSAGE" desc="Recording CPU profile (status message).">
+        Recording…
       </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_REFRESHES_CURRENT_VIEW" desc="Label for a button that refreshes current view.">
         Refresh
       </message>
+      <message name="IDS_REMOVE_BREAKPOINT_COMMAND" desc="Remove breakpoint command.">
+        Remove Breakpoint
+      </message>
+      <message name="IDS_REMOVE_TIMER_TIMELINE_EVENT" desc="Remove timer Timeline event.">
+        Remove Timer
+      </message>
+      <message name="IDS_RENDERING_EVENTS_CATEGORY_IN_TIMELINE_PANEL" desc="Rendering events category in Timeline panel.">
+        Rendering
+      </message>
+      <message name="IDS_A_LABEL_FOR_REPEATING_TIMER" desc="A label for repeating timer.">
+        Repeats
+      </message>
+      <message name="IDS_LABEL_FOR_HTTP_REQUEST_COOKIES" desc="Label for HTTP request cookies.">
+        Request Cookies
+      </message>
       <message name="IDS_LABEL_FOR_HTTP_REQUEST_HEADERS" desc="Label for HTTP request headers.">
         Request Headers
       </message>
+      <message name="IDS_HTTP_REQUEST_METHOD" desc="HTTP request method.">
+        Request Method
+      </message>
+      <message name="IDS_A_LABEL_FOR_REQUEST_PAYLOAD" desc="A label for request payload.">
+        Request Payload
+      </message>
+      <message name="IDS_A_LABEL_FOR_REQUEST_URL" desc="A label for request URL.">
+        Request URL
+      </message>
       <message name="IDS_A_WARNING_ABOUT_RESOURCE_TYPE_MISMATCH" desc="A warning about resource type mismatch.">
         Resource interpreted as <ph name="REAL_TYPE">%1$s<ex>text/javascript</ex></ph> but transferred with MIME type <ph name="SPECIFIED_TYPE">%2$s<ex>text/javascript</ex></ph>.
       </message>
-      <message name="IDS_MESSAGE_INDICATING_THAT_RESOURCE_TRACKING_IS_DISABLED" desc="Message indicating that resource tracking is disabled.">
-        Resource tracking disabled. Click to enable.
-      </message>
-      <message name="IDS_MESSAGE_INDICATING_THAT_RESOURCE_TRACKING_IS_ENABLED" desc="Message indicating that resource tracking is enabled.">
-        Resource tracking enabled. Click to disable.
+      <message name="IDS_RESOURCE_IDENTIFIER_LABEL" desc="Resource identifier label.">
+        Resource
       </message>
       <message name="IDS_LABEL_FOR_RESOURCES_TAB" desc="Label for resources tab.">
         Resources
       </message>
+      <message name="IDS_LABEL_FOR_HTTP_REQUEST_RESPONSE_COOKIES" desc="Label for HTTP request response cookies.">
+        Response Cookies
+      </message>
       <message name="IDS_LABEL_FOR_HTTP_REQUEST_RESPONSE_HEADERS" desc="Label for HTTP request response headers.">
         Response Headers
       </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_SHOWS_ALL_FUNCTIONS_IN_PROFILER" desc="Label for a button that shows all functions in profiler.">
         Restore all functions.
       </message>
+      <message name="IDS_REVEAL_IN_ELEMENTS_PANEL" desc="Command to reveal a node in the Elements panel.">
+        Reveal in Elements Panel
+      </message>
       <message name="IDS_LABEL_FOR_NTH_PROFILER_RUN" desc="Label for Nth profiler run.">
         Run <ph name="ID">%d<ex>1</ex></ph>
       </message>
-      <message name="IDS_LABEL_FOR_A_SECTION_SHOWING_SESSION_STORAGE" desc="Label for a section showing session storage.">
-        SESSION STORAGE
+      <message name="IDS_RUN_AUDITS_COMMAND" desc="Run audits command.">
+        Run
+      </message>
+      <message name="IDS_LABEL_FOR_SESSION_ONLY_STORAGE" desc="Label for session-only storage.">
+        Session Storage
+      </message>
+      <message name="IDS_TIME_SPENT_ON_SSL_INTERACTION" desc="Time spent on SSL interaction.">
+        SSL
+      </message>
+      <message name="IDS_SCHEDULE_REQUEST_TIMELINE_EVENT" desc="Schedule Request Timeline event.">
+        Schedule Request
       </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_SCOPE_VARIABLES" desc="Label for a section in the scope chain sidebar that shows scope variables.">
         Scope Variables
       </message>
+      <message name="IDS_EVALUATE_SCRIPT_TIMELINE_EVENT" desc="Evaluate script Timeline event.">
+        Script
+      </message>
+      <message name="IDS_SCRIPTING_EVENTS_CATEGORY_IN_TIMELINE" desc="Scripting events category in Timeline.">
+        Scripting
+      </message>
+      <message name="IDS_SHORTCUTS_SECTION_FOR_THE_SCRIPTS_PANEL" desc="Shortcuts section for the Scripts Panel.">
+        Scripts Panel
+      </message>
       <message name="IDS_LABEL_FOR_SCRIPTS_RESOURCE_SECTION" desc="Label for scripts resource section.">
         Scripts
       </message>
       <message name="IDS_LABEL_INDICATING_CURRENT_SEARCH" desc="Label indicating current search.">
         Search <ph name="STRING">%s<ex>foo</ex></ph>
       </message>
+      <message name="IDS_LABEL_FOR_SEARCH_SHORTCUT" desc="Label for search shortcut.">
+        Search
+      </message>
+      <message name="IDS_COOKIE_SECURITY_ATTRIBUTE" desc="Cookie security attribute.">
+        Secure
+      </message>
+      <message name="IDS_SELECT_ALL_AUDIT_RULES" desc="Select all audit rules.">
+        Select All
+      </message>
       <message name="IDS_HINT_THAT_ELEMENT_SHOULD_BE_SELECTED" desc="Hint that element should be selected.">
         Select an element in the page to inspect it.
       </message>
+      <message name="IDS_HINT_ABOUT_THE_NEED_OF_SELECTING_AUDITS_TO_RUN" desc="Hint about the need of selecting audits to run.">
+        Select audits to run
+      </message>
+      <message name="IDS_DISPLAY_EVENTS_LISTENERS_FOR_SELECTED_NODE_ONLY" desc="Display events listeners for selected node only.">
+        Selected Node Only
+      </message>
+      <message name="IDS_FUNCTION_SELF_EXECUTION_TIME" desc="Function self-execution time.">
+        Self Time
+      </message>
       <message name="IDS_LABEL_OF_A_GRID_COLUMN_SHOWING_FUNCTION_SELF_EXECUTION_TIME" desc="Label of a grid column showing function self execution time.">
         Self
       </message>
+      <message name="IDS_SEND_REQUEST_TIMELINE_EVENT" desc="Send Request Timeline event.">
+        Send Request
+      </message>
+      <message name="IDS_RESOURCE_SENDING_TIME" desc="Resource sending time.">
+        Sending
+      </message>
+      <message name="IDS_LABEL_FOR_A_SESSION_ONLY_COOKIE" desc="Label for a session-only cookie.">
+        Session
+      </message>
+      <message name="IDS_COMMAND_FOR_SHOWING_MORE_HTML_NODES" desc="Command for showing more HTML nodes.">
+        Show All Nodes (<ph name="COUNT">%d<ex>100</ex></ph> More)
+      </message>
+      <message name="IDS_SHOW_ABSOLUTE_COUNTS_AND_SIZES" desc="Show absolute (not percents) counts and sizes for JavaScript objects.">
+        Show absolute counts and sizes.
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_TOGGLING_SHOWING_OF_ABSOLUTE_TIMES" desc="Label for a button toggling showing of absolute times.">
         Show absolute total and self times.
       </message>
@@ -474,6 +1032,9 @@
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_SHOWS_CONSOLE" desc="Label for a button that shows console.">
         Show console.
       </message>
+      <message name="IDS_SHOW_JAVASCRIPT_OBJECTS_COUNTS_AND_SIZES_IN_PERCENTS" desc="Show JavaScript objects counts and sizes in percents.">
+        Show counts and sizes as percentages.
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_ENABLING_SHOWING_OF_INHERITED_STYLES" desc="Label for a button enabling showing of inherited styles.">
         Show inherited
       </message>
@@ -483,46 +1044,58 @@
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_SHOWS_THE_PREVIOUS_SCRIPT_RESOURCE" desc="Label for a button that shows the previous script resource.">
         Show the previous script resource.
       </message>
+      <message name="IDS_LABEL_FOR_A_TIMELINE_EVENTS_FILTER_BASED_ON_EVENTS_DURATION" desc="Label for a Timeline events filter based on events duration.">
+        Show the records that are shorter than <ph name="TIME">%s<ex>15 ms</ex></ph>
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_TOGGLING_SHOWING_TIMES_AS_PERCENTAGES" desc="Label for a button toggling showing times as percentages.">
         Show total and self times as percentages.
       </message>
       <message name="IDS_LABEL_FOR_A_RESOURCE_SIZE_GRAPH_1" desc="Label for a resource size graph.">
         Size
       </message>
-      <message name="IDS_SORT_OPTION_FOR_RESOURCES_GRAPH_2" desc="Sort option for resources graph.">
-        Sort by Duration
+      <message name="IDS_HEAP_SNAPSHOT_TITLE" desc="Heap snapshot title.">
+        Snapshot <ph name="NUMBER">%d<ex>1</ex></ph>
       </message>
-      <message name="IDS_SORT_OPTION_FOR_RESOURCES_GRAPH_3" desc="Sort option for resources graph.">
-        Sort by End Time
+      <message name="IDS_NETWORK_SORT_DURATION" desc="Network resources timeline sorting: by duration.">
+        Duration
       </message>
-      <message name="IDS_SORT_OPTION_FOR_RESOURCES_GRAPH_4" desc="Sort option for resources graph.">
-        Sort by Latency
+      <message name="IDS_NETWORK_SORT_END_TIME" desc="Network resources timeline sorting: by loading end time.">
+        End Time
       </message>
-      <message name="IDS_SORT_OPTION_FOR_RESOURCES_GRAPH_5" desc="Sort option for resources graph.">
-        Sort by Response Time
+      <message name="IDS_NETWORK_SORT_LATENCY" desc="Network resources timeline sorting: by latency.">
+        Latency
       </message>
-      <message name="IDS_SORT_OPTION_FOR_RESOURCES_GRAPH_6" desc="Sort option for resources graph.">
-        Sort by Size
+      <message name="IDS_NETWORK_SORT_RESPONSE_TIME" desc="Network resources timeline sorting: by response time.">
+        Response Time
       </message>
-      <message name="IDS_SORT_OPTION_FOR_RESOURCES_GRAPH_7" desc="Sort option for resources graph.">
-        Sort by Start Time
-      </message>
-      <message name="IDS_LABEL_FOR_SCRIPT_SOURCE" desc="Label for script source.">
-        Source
+      <message name="IDS_NETWORK_SORT_START_TIME" desc="Network resources timeline sorting: by start time.">
+        Start Time
       </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_STARTS_PROFILING" desc="Label for a button that starts profiling.">
         Start profiling.
       </message>
+      <message name="IDS_RESOURCE_STATUS_CODE" desc="Resource loading status code.">
+        Status Code
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_STEPS_INTO_NEXT_FUNCTION_CALL" desc="Label for a button that steps into next function call.">
         Step into next function call.
       </message>
+      <message name="IDS_STEP_INTO_LABEL" desc="Label for a button that steps into next function call.">
+        Step into
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_STEPS_OUT_OF_CURRENT_FUNCTION" desc="Label for a button that steps out of current function.">
         Step out of current function.
       </message>
+      <message name="IDS_STEP_OUT_LABEL" desc="Label for a button that steps out of current function.">
+        Step out
+      </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_STEPS_OVER_NEXT_FUNCTION_CALL" desc="Label for a button that steps over next function call.">
         Step over next function call.
       </message>
-      <message name="IDS_HINT_FOR_A_PAUSE_BUTTON_IN_DEBUGGER,_INDICATING_THAT_DEBUGGER_IS_STEPPING_INTO_NEXT_STATEMENT" desc="Hint for a pause button in debugger, indicating that debugger is stepping into next statement.">
+      <message name="IDS_STEP_OVER_LABEL" desc="Label for a button that steps over next function call.">
+        Step over
+      </message>
+      <message name="IDS_HINT_FOR_A_PAUSE_BUTTON_IN_DEBUGGER_INDICATING_THAT_DEBUGGER_IS_STEPPING_INTO_NEXT_STATEMENT" desc="Hint for a pause button in debugger, indicating that debugger is stepping into next statement.">
         Stepping
       </message>
       <message name="IDS_LABEL_FOR_A_BUTTON_THAT_STOPS_PROFILING" desc="Label for a button that stops profiling.">
@@ -531,30 +1104,69 @@
       <message name="IDS_LABEL_FOR_STYLE_ATTRIBUTE" desc="Label for style attribute.">
         Style Attribute
       </message>
+      <message name="IDS_CSS_STYLES_SIDEBAR_PANE" desc="Label for CSS styles sidebar pane.">
+        Styles Pane
+      </message>
       <message name="IDS_LABEL_FOR_CSS_STYLES_SIDE_PANEL" desc="Label for CSS styles side panel.">
         Styles
       </message>
+      <message name="IDS_RESOURCE_STYLESHEET" desc="Resource type: stylesheet.">
+        Stylesheet
+      </message>
       <message name="IDS_LABEL_FOR_STYLESHEETS_RESOURCE_SECTION" desc="Label for stylesheets resource section.">
         Stylesheets
       </message>
+      <message name="IDS_BREAK_WHEN_SUBTREE_MODIFIED" desc="Breakpoint condition: DOM subtree modified.">
+        Subtree Modified
+      </message>
+      <message name="IDS_TAKE_HEAP_SNAPSHOT_COMMAND" desc="Command: take heap snapshot.">
+        Take heap snapshot.
+      </message>
+      <message name="IDS_BP_CONDITION" desc="Breakpoint condition">
+        The breakpoint on line <ph name="LINE_NUMBER">%d<ex>15</ex></ph> will stop only if this expression is true:
+      </message>
       <message name="IDS_MESSAGE_INDICATING_THAT_DATABASE_TABLE_IS_EMPTY" desc="Message indicating that database table is empty.">
         The “<ph name="TABLE_NAME">%s<ex>foo</ex></ph>”\ntable is empty.
       </message>
-      <message name="IDS_MESSAGE_INDICATING_THAT_CURRENT_SITE_DOESN'T_HAVE_COOKIES" desc="Message indicating that current site doesn't have cookies.">
+      <message name="IDS_MESSAGE_INDICATING_THAT_CURRENT_SITE_DOES_NOT_HAVE_COOKIES" desc="Message indicating that current site doesn't have cookies.">
         This site has no cookies.
       </message>
-      <message name="IDS_MESSAGE_INDICATING_THAT_STORAGE_IS_EMPTY" desc="Message indicating that storage is empty.">
-        This storage is empty.
+      <message name="IDS_NO_TIMING_INFO" desc="Message that a request has no detailed timing info.">
+        This request has no detailed timing info.
       </message>
       <message name="IDS_LABEL_FOR_A_RESOURCE_TIME_GRAPH" desc="Label for a resource time graph.">
         Time
       </message>
+      <message name="IDS_RESOURCES_LOADING_TIMELINE" desc="Resources loading timeline graph label.">
+        Timeline
+      </message>
+      <message name="IDS_TIMELINES_LABEL" desc="Timelines view label.">
+        Timelines
+      </message>
+      <message name="IDS_TIMER_TIMEOUT" desc="Label for timer's timeout value.">
+        Timeout
+      </message>
+      <message name="IDS_TIMER_FIRED_BREAKPOINT" desc="Breakpoint when timer fires.">
+        Timer Fired
+      </message>
+      <message name="IDS_TIMER_ID" desc="Label for timer's ID.">
+        Timer ID
+      </message>
+      <message name="IDS_TIMING_TAB" desc="Label for resources timing tab.">
+        Timing
+      </message>
+      <message name="IDS_TOGGLE_CONSOLE" desc="Label for a button that toggles console visibility.">
+        Toggle console
+      </message>
       <message name="IDS_LABEL_OF_A_GRID_COLUMN_SHOWING_FUNCTION_TOTAL_EXECUTION_TIME" desc="Label of a grid column showing function total execution time.">
         Total
       </message>
-      <message name="IDS_LABEL_INDICATING_THAT_TOP-DOWN_(TREE)_PROFILE_IS_SHOWN" desc="Label indicating that top-down (tree) profile is shown.">
+      <message name="IDS_LABEL_INDICATING_THAT_TOP_DOWN_TREE_PROFILE_IS_SHOWN" desc="Label indicating that top-down (tree) profile is shown.">
         Tree (Top Down)
       </message>
+      <message name="IDS_RESOURCE_TYPE" desc="Network resource type.">
+        Type
+      </message>
       <message name="IDS_HINT_FOR_A_BUTTON_THAT_UNDOCKS_INSPECTOR_FROM_MAIN_WINDOW" desc="Hint for a button that undocks Inspector from main window.">
         Undock into separate window.
       </message>
@@ -564,15 +1176,42 @@
       <message name="IDS_HINT_FOR_A_BUTTON_THAT_TOGGLES_SHOWING_SMALL_RESOURCE_ROWS" desc="Hint for a button that toggles showing small resource rows.">
         Use small resource rows.
       </message>
+      <message name="IDS_USED_HEAP_SIZE" desc="Label for a value showing used JavaScript heap size.">
+        Used Heap Size
+      </message>
       <message name="IDS_LABEL_FOR_A_GRID_COLUMN_SHOWING_PROPERTY_VALUE" desc="Label for a grid column showing property value.">
         Value
       </message>
+      <message name="IDS_RESOURCE_WAITING_TIME" desc="Label for the resource loading wait time.">
+        Waiting
+      </message>
+      <message name="IDS_WARNINGS_FILTER" desc="Console filter for showing warnings.">
+        Warnings
+      </message>
+      <message name="IDS_WATCH_EXPRESSION" desc="Watch expressions sidebar pane.">
+        Watch Expressions
+      </message>
+      <message name="IDS_WELCOME_TO_PROFILES" desc="Welcome message for the profiles panel.">
+        Welcome to the Profiles panel
+      </message>
       <message name="IDS_LABEL_FOR_A_SECTION_IN_THE_SCOPE_CHAIN_SIDEBAR_THAT_SHOWS_WITH_BLOCK_VARIABLES" desc="Label for a section in the scope chain sidebar that shows with block variables.">
         With Block
       </message>
+      <message name="IDS_WORKERS_SIDEBAR" desc="Web Workers sidebar pane label.">
+        Workers
+      </message>
+      <message name="IDS_TIMELINE_XHR_LOAD" desc="Timeline XHR request load event.">
+        XHR Load
+      </message>
+      <message name="IDS_BP_ON_XHR_READY_STATE_CHANGE" desc="Break script execution on XHR ready state change.">
+        XHR Ready State Change
+      </message>
       <message name="IDS_LABEL_FOR_XHR_RESOURCE_SECTION" desc="Label for XHR resource section.">
         XHR
       </message>
+      <message name="IDS_XHR_LOGGING" desc="Enable logging of XHR requests in the Console.">
+        XMLHttpRequest logging
+      </message>
       <message name="IDS_HINT_MESSAGE_ABOUT_POTENTIAL_RESOURCES_COMPRESSION" desc="Hint message about potential resources compression.">
         You could save bandwidth by having your web server compress this transfer with gzip or zlib.
       </message>
@@ -582,8 +1221,14 @@
       <message name="IDS_HINT_MESSAGE_ABOUT_NEED_FOR_ENABLING_PROFILING" desc="Hint message about need for enabling profiling.">
         You need to enable profiling before you can use the Profiles panel.
       </message>
-      <message name="IDS_HINT_MESSAGE_ABOUT_NEED_FOR_ENABLING_RESOURCE_TRACKING" desc="Hint message about need for enabling resource tracking.">
-        You need to enable resource tracking to use this panel.
+      <message name="IDS_AUDITS_NO_DOMAIN" desc="A message if a domain is absent in audit rule.">
+        [empty domain]
+      </message>
+      <message name="IDS_COUNTS_DELTA" desc="Objects count delta column label.">
+        \xb1 Count
+      </message>
+      <message name="IDS_SIZES_DELTA" desc="Objects sizes delta column label.">
+        \xb1 Size
       </message>
       <message name="IDS_LABEL_FOR_A_BOX_SHOWING_HTML_ELEMENT_BORDER_SIZE" desc="Label for a box showing HTML element border size.">
         border
@@ -591,20 +1236,8 @@
       <message name="IDS_LABEL_FOR_A_BOX_SHOWING_HTML_ELEMENT_CONTENT_SIZE" desc="Label for a box showing HTML element content size.">
         content
       </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE" desc="Label for a resource type.">
-        document
-      </message>
-      <message name="IDS_LABEL_FOR_HTML_ELEMENT'S_ATTRIBUTE" desc="Label for HTML element's attribute.">
-        element’s “<ph name="NAME">%s<ex>width</ex></ph>” attribute
-      </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_1" desc="Label for a resource type.">
-        font
-      </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_2" desc="Label for a resource type.">
-        image
-      </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_3" desc="Label for a resource type.">
-        inline stylesheet
+      <message name="IDS_DELETED_OBJECT" desc="JavaScript object deleted.">
+        deleted
       </message>
       <message name="IDS_LABEL_FOR_LINE_POSITION" desc="Label for line position.">
         line <ph name="LINE_NUMBER">%d<ex>25</ex></ph>
@@ -612,8 +1245,11 @@
       <message name="IDS_LABEL_FOR_A_BOX_SHOWING_HTML_ELEMENT_MARGIN_SIZE" desc="Label for a box showing HTML element margin size.">
         margin
       </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_4" desc="Label for a resource type.">
-        other
+      <message name="IDS_NEW_OBJECT" desc="New JavaScript object label.">
+        new
+      </message>
+      <message name="IDS_ALTERNATIVE_SHORTCUT" desc="An alternative for keyboard shortcuts.">
+        or
       </message>
       <message name="IDS_LABEL_FOR_A_BOX_SHOWING_HTML_ELEMENT_PADDING_SIZE" desc="Label for a box showing HTML element padding size.">
         padding
@@ -621,12 +1257,6 @@
       <message name="IDS_LABEL_FOR_A_POSITION" desc="Label for a position.">
         position
       </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_5" desc="Label for a resource type.">
-        script
-      </message>
-      <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_6" desc="Label for a resource type.">
-        stylesheet
-      </message>
       <message name="IDS_LABEL_FOR_A_RESOURCE_TYPE_7" desc="Label for a resource type.">
         user agent stylesheet
       </message>
@@ -636,6 +1266,162 @@
       <message name="IDS_LABEL_VIA_INSPECTOR" desc="Label for a style attribute added via Inspector.">
         via inspector
       </message>
+      <message name="IDS_BP_ON_ATTRIBUTES_MODIFICATIONS" desc="Set breakpoint on DOM node attributes modifications.">
+        Break on Attributes Modifications
+      </message>
+      <message name="IDS_BP_ON_NODE_REMOVAL" desc="Set breakpoint on DOM node removal.">
+        Break on Node Removal
+      </message>
+      <message name="IDS_BP_ON_SUBTREE_MODIFICATIONS" desc="Set breakpoint on DOM node subtree modifications.">
+        Break on Subtree Modifications
+      </message>
+      <message name="IDS_LINK_TO_NODE" desc="Link to DOM node.">
+        &lt;node&gt;
+      </message>
+      <message name="IDS_PAUSED_ON_CHILD_ADDITION_TO_DESCENDANT" desc="Info message for a script break.">
+        Paused on a \"<ph name="BREAKPOINT">%1$s<ex>foo</ex></ph>\" breakpoint set on <ph name="NODE">%2$s<ex>div</ex></ph>, because a new child was added to its descendant <ph name="CHILD">%3$s<ex>span</ex></ph>.
+      </message>
+      <message name="IDS_PAUSED_ON_CHILD_ADDITION" desc="Info message for a script break.">
+        Paused on a \"<ph name="BREAKPOINT">%1$s<ex>foo</ex></ph>\" breakpoint set on <ph name="NODE">%2$s<ex>div</ex></ph>, because a new child was added to that node.
+      </message>
+      <message name="IDS_PAUSED_ON_CHILD_REMOVE" desc="Info message for a script break.">
+        Paused on a \"<ph name="BREAKPOINT">%1$s<ex>foo</ex></ph>\" breakpoint set on <ph name="NODE">%2$s<ex>div</ex></ph>, because its descendant <ph name="CHILD">%3$s<ex>span</ex></ph> was removed.
+      </message>
+      <message name="IDS_PAUSED_ON_BREAKPOINT" desc="Info message for a script break.">
+        Paused on a \"<ph name="NAME">%1$s<ex>foo</ex></ph>\" breakpoint set on <ph name="LOCATION">%2$s<ex>foo.js:25</ex></ph>.
+      </message>
+      <message name="IDS_PAUSED_ON_XHR" desc="Info message for a script break.">
+        Paused on a XMLHttpRequest.
+      </message>
+      <message name="IDS_PAUSED_ON_EVENT_LISTENER" desc="Info message for a script break.">
+        Paused on a \"<ph name="NAME">%s<ex>click</ex></ph>\" Event Listener.
+      </message>
+      <message name="IDS_PAUSED_ON_BREAKPOINT_2" desc="Info message for a script break.">
+        Paused on a JavaScript breakpoint.
+      </message>
+      <message name="IDS_XHR_BREAKPOINT_CONDITION" desc="XHR breakpoint condition.">
+        URL contains \"<ph name="SUBSTRING">%s<ex>google</ex></ph>\"
+      </message>
+      <message name="IDS_NETWORK_PANEL_LABEL" desc="Network panel label.">
+        Network
+      </message>
+      <message name="IDS_RESOURCE_STATUS" desc="Resource status column label.">
+        Status
+      </message>
+      <message name="IDS_RESOURCE_METHOD" desc="Resource retrieve method column label.">
+        Method
+      </message>
+      <message name="IDS_PENDING_RESOURCE" desc="Resource loading is pending.">
+        Pending
+      </message>
+      <message name="IDS_REQUESTS_STATS" desc="Request statistics.">
+        <ph name="COUNT">%d<ex>100</ex></ph> requests
+      </message>
+      <message name="IDS_BYTES_STATISTICS" desc="Bytes statistics.">
+        <ph name="BYTES">%s<ex>100KB</ex></ph> transferred
+      </message>
+      <message name="IDS_LOAD_TIMING" desc="Page loading timing.">
+        <ph name="TOTAL_TIME">%1$s<ex>5s</ex></ph> (onload: <ph name="ONLOAD_TIME">%2$s<ex>1s</ex></ph>, DOMContentLoaded: <ph name="DOMCONTENT_TIME">%3$s<ex>3s</ex></ph>)
+      </message>
+      <message name="IDS_DOM_BREAKPOINTS_SIDEBAR_PANE" desc="DOM Breakpoints sidebar pane title.">
+        DOM Breakpoints
+      </message>
+      <message name="IDS_EVENT_LISTENER_BREAKPOINTS_SIDEBAR_PANE" desc="Event Listeners breakpoints sidebar pane.">
+        Event Listener Breakpoints
+      </message>
+      <message name="IDS_XHR_BREAKPOINTS_SIDEBAR_PANE" desc="XHR Breakpoints sidebar pane.">
+        XHR Breakpoints
+      </message>
+      <message name="IDS_MOUSE_EVENTS" desc="Mouse events category title.">
+        Mouse
+      </message>
+      <message name="IDS_DRAG_EVENTS" desc="Drag events category title.">
+        Drag
+      </message>
+      <message name="IDS_KEYBOARD_EVENTS" desc="Keyboard events category title.">
+        Keyboard
+      </message>
+      <message name="IDS_CLIPBOARD_EVENTS" desc="Clipboard events category title.">
+        Clipboard
+      </message>
+      <message name="IDS_DOM_MUTATION_EVENTS" desc="DOM Mutation events category title.">
+        DOM Mutation
+      </message>
+      <message name="IDS_DEVICE_EVENTS" desc="Device events category title.">
+        Device
+      </message>
+      <message name="IDS_LOAD_EVENTS" desc="Load events category title.">
+        Load
+      </message>
+      <message name="IDS_CONTROL_EVENTS" desc="Control events category title.">
+        Control
+      </message>
+      <message name="IDS_TIMER_EVENTS" desc="Timer events category title.">
+        Timer
+      </message>
+      <message name="IDS_SET_TIMER_BREAKPOINT" desc="Breakpoint on setting a timer.">
+        Set Timer
+      </message>
+      <message name="IDS_CLEAR_TIMER_BREAKPOINT" desc="Breakpoint on clearing a timer.">
+        Clear Timer
+      </message>
+      <message name="IDS_NO_REQUESTS" desc="Help message describing that page reload is needed to capture network requests.">
+        No requests captured. Reload the page to see detailed information on the network activity.
+      </message>
+      <message name="IDS_PERSISTENT_FILE_SYSTEM" desc="Persistent file system storage.">
+        Persistent File System
+      </message>
+      <message name="IDS_TEMPORARY_FILE_SYSTEM" desc="Temporary file system storage.">
+        Temporary File System
+      </message>
+      <message name="IDS_NO_FILE_SYSTEM_ROOT" desc="Error message telling that the root path of the File System storage isn't available.">
+        File System root path not available.
+      </message>
+      <message name="IDS_FILE_SYSTEM_DISABLED" desc="Info message telling that File System storage is disabled.">
+        File System is disabled.
+      </message>
+      <message name="IDS_FILE_SYSTEM_ROOT_ERROR" desc="There was an error retrieving root path for the file system storage.">
+        Error in fetching root path for file system.
+      </message>
+      <message name="IDS_REVEAL_FOLDER" desc="A command to reveal a folder in OS file manager.">
+        Reveal folder in OS
+      </message>
+      <message name="IDS_NO_COOKIES" desc="Message telling that a request has no cookies data.">
+        This request has no cookies.
+      </message>
+      <message name="IDS_ORIGINAL_RESOURCE" desc="A label for a resource indicating that this is an original revision.">
+        (original)
+      </message>
+      <message name="IDS_COORDINATES" desc="On-screen coordinates">
+        (<ph name="X">%1$d<ex>100</ex></ph>, <ph name="Y">%2$d<ex>100</ex></ph>)
+      </message>
+      <message name="IDS_REVERT_TO_REVISION" desc="Revert resource to specified revision.">
+        Revert to this revision
+      </message>
+      <message name="IDS_STORAGE_CATEGOTY_WEBSOCKETS" desc="Storage category: WebSockets.">
+        WebSockets
+      </message>
+      <message name="IDS_STORAGE_CATEGORY_FRAMES" desc="Storage category: Frames.">
+        Frames
+      </message>
+      <message name="IDS_RESPONSE_TEXT_COLUMN" desc="A subtitle for the column showing response text.">
+        Text
+      </message>
+      <message name="IDS_TRANSFER_SIZE" desc="A subtitle for the column showing response transfer size.">
+        Transfer
+      </message>
+      <message name="IDS_PRESERVE_LOG" desc="Preserve network log upon page navigation.">
+        Preserve Log upon Navigation
+      </message>
+      <message name="IDS_GO_TO_LINE_COMMAND" desc="Go to Line command.">
+        Go to Line
+      </message>
+      <message name="IDS_URL" desc="An abbreviation of Uniform Resource Locator.">
+        URL
+      </message>
+      <message name="IDS_FORMAT_SCRIPT_COMMAND" desc="A command to format script source.">
+        Format script.
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/webkit/glue/media/audio_decoder.cc b/webkit/glue/media/audio_decoder.cc
index 3fc05c9..0a236d2 100644
--- a/webkit/glue/media/audio_decoder.cc
+++ b/webkit/glue/media/audio_decoder.cc
@@ -9,7 +9,7 @@
 #include "base/string_util.h"
 #include "base/time.h"
 #include "media/filters/audio_file_reader.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebAudioBus.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioBus.h"
 
 using media::AudioFileReader;
 using media::InMemoryDataReader;
diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc
index b6efa16..913d400 100644
--- a/webkit/glue/media/buffered_data_source.cc
+++ b/webkit/glue/media/buffered_data_source.cc
@@ -38,7 +38,6 @@
       loaded_(false),
       streaming_(false),
       frame_(frame),
-      single_origin_(true),
       loader_(NULL),
       network_activity_(false),
       initialize_callback_(NULL),
@@ -115,7 +114,7 @@
 
 void BufferedDataSource::Stop(media::FilterCallback* callback) {
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     stop_signal_received_ = true;
   }
   if (callback) {
@@ -137,9 +136,25 @@
 // media::DataSource implementation.
 void BufferedDataSource::Read(int64 position, size_t size, uint8* data,
                               media::DataSource::ReadCallback* read_callback) {
+  DCHECK(read_callback);
+
+  {
+    base::AutoLock auto_lock(lock_);
+    DCHECK(!read_callback_.get());
+
+    if (stop_signal_received_ || stopped_on_render_loop_) {
+      read_callback->RunWithParams(
+          Tuple1<size_t>(static_cast<size_t>(media::DataSource::kReadError)));
+      delete read_callback;
+      return;
+    }
+
+    read_callback_.reset(read_callback);
+  }
+
   render_loop_->PostTask(FROM_HERE,
       NewRunnableMethod(this, &BufferedDataSource::ReadTask,
-                        position, static_cast<int>(size), data, read_callback));
+                        position, static_cast<int>(size), data));
 }
 
 bool BufferedDataSource::GetSize(int64* size_out) {
@@ -157,16 +172,18 @@
 
 bool BufferedDataSource::HasSingleOrigin() {
   DCHECK(MessageLoop::current() == render_loop_);
-  return single_origin_;
+  return loader_.get() ? loader_->HasSingleOrigin() : true;
 }
 
 void BufferedDataSource::Abort() {
   DCHECK(MessageLoop::current() == render_loop_);
 
-  // If we are told to abort, immediately return from any pending read
-  // with an error.
-  if (read_callback_.get()) {
-      AutoLock auto_lock(lock_);
+  {
+    base::AutoLock auto_lock(lock_);
+
+    // If we are told to abort, immediately return from any pending read
+    // with an error.
+    if (read_callback_.get())
       DoneRead_Locked(net::ERR_FAILED);
   }
 
@@ -212,19 +229,21 @@
 }
 
 void BufferedDataSource::ReadTask(
-     int64 position, int read_size, uint8* buffer,
-     media::DataSource::ReadCallback* read_callback) {
+    int64 position,
+    int read_size,
+    uint8* buffer) {
   DCHECK(MessageLoop::current() == render_loop_);
-  if (stopped_on_render_loop_)
-    return;
+  {
+    base::AutoLock auto_lock(lock_);
+    if (stopped_on_render_loop_)
+      return;
 
-  DCHECK(!read_callback_.get());
-  DCHECK(read_callback);
+    DCHECK(read_callback_.get());
+  }
 
   // Saves the read parameters.
   read_position_ = position;
   read_size_ = read_size;
-  read_callback_.reset(read_callback);
   read_buffer_ = buffer;
   read_submitted_time_ = base::Time::Now();
   read_attempts_ = 0;
@@ -235,8 +254,14 @@
 
 void BufferedDataSource::CleanupTask() {
   DCHECK(MessageLoop::current() == render_loop_);
-  if (stopped_on_render_loop_)
-    return;
+
+  {
+    base::AutoLock auto_lock(lock_);
+    if (stopped_on_render_loop_)
+      return;
+
+    read_callback_.reset();
+  }
 
   // Stop the watch dog.
   watch_dog_timer_.Stop();
@@ -246,7 +271,6 @@
     loader_->Stop();
 
   // Reset the parameters of the current read request.
-  read_callback_.reset();
   read_position_ = 0;
   read_size_ = 0;
   read_buffer_ = 0;
@@ -262,9 +286,12 @@
   if (stopped_on_render_loop_)
     return;
 
-  // If there's no outstanding read then return early.
-  if (!read_callback_.get())
-    return;
+  {
+    // If there's no outstanding read then return early.
+    base::AutoLock auto_lock(lock_);
+    if (!read_callback_.get())
+      return;
+  }
 
   loader_ = CreateResourceLoader(read_position_, kPositionNotSpecified);
   loader_->SetAllowDefer(!media_is_paused_);
@@ -280,8 +307,11 @@
     return;
 
   // We only care if there is an active read request.
-  if (!read_callback_.get())
-    return;
+  {
+    base::AutoLock auto_lock(lock_);
+    if (!read_callback_.get())
+      return;
+  }
 
   DCHECK(loader_.get());
   base::TimeDelta delta = base::Time::Now() - read_submitted_time_;
@@ -375,9 +405,6 @@
   DCHECK(MessageLoop::current() == render_loop_);
   DCHECK(loader_.get());
 
-  // Check if the request ended up at a different origin via redirect.
-  single_origin_ = url_.GetOrigin() == loader_->url().GetOrigin();
-
   int64 instance_size = loader_->instance_size();
   bool partial_response = loader_->partial_response();
   bool success = error == net::OK;
@@ -414,7 +441,7 @@
   // let tasks on render thread to run but make sure they don't call outside
   // this object when Stop() method is ever called. Locking this method is safe
   // because |lock_| is only acquired in tasks on render thread.
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (stop_signal_received_)
     return;
 
@@ -444,9 +471,6 @@
   DCHECK(MessageLoop::current() == render_loop_);
   DCHECK(loader_.get());
 
-  // Check if the request ended up at a different origin via redirect.
-  single_origin_ = url_.GetOrigin() == loader_->url().GetOrigin();
-
   int64 instance_size = loader_->instance_size();
   bool success = error == net::OK && instance_size != kPositionNotSpecified;
 
@@ -465,7 +489,7 @@
   // let tasks on render thread to run but make sure they don't call outside
   // this object when Stop() method is ever called. Locking this method is safe
   // because |lock_| is only acquired in tasks on render thread.
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (stop_signal_received_)
     return;
 
@@ -504,7 +528,7 @@
   // let tasks on render thread to run but make sure they don't call outside
   // this object when Stop() method is ever called. Locking this method is
   // safe because |lock_| is only acquired in tasks on render thread.
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (stop_signal_received_)
     return;
   DoneRead_Locked(net::ERR_INVALID_RESPONSE);
@@ -534,7 +558,7 @@
   // let tasks on render thread to run but make sure they don't call outside
   // this object when Stop() method is ever called. Locking this method is safe
   // because |lock_| is only acquired in tasks on render thread.
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (stop_signal_received_)
     return;
 
@@ -570,7 +594,7 @@
   // let tasks on render thread to run but make sure they don't call outside
   // this object when Stop() method is ever called. Locking this method is safe
   // because |lock_| is only acquired in tasks on render thread.
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (stop_signal_received_)
     return;
 
diff --git a/webkit/glue/media/buffered_data_source.h b/webkit/glue/media/buffered_data_source.h
index 1c4e3fa..895b259 100644
--- a/webkit/glue/media/buffered_data_source.h
+++ b/webkit/glue/media/buffered_data_source.h
@@ -8,8 +8,8 @@
 #include <string>
 
 #include "base/callback.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
 #include "webkit/glue/media/buffered_resource_loader.h"
 
 namespace webkit_glue {
@@ -62,8 +62,7 @@
   void InitializeTask();
 
   // Task posted to perform actual reading on the render thread.
-  void ReadTask(int64 position, int read_size, uint8* read_buffer,
-                media::DataSource::ReadCallback* read_callback);
+  void ReadTask(int64 position, int read_size, uint8* read_buffer);
 
   // Task posted when Stop() is called. Stops |watch_dog_timer_| and
   // |loader_|, reset Read() variables, and set |stopped_on_render_loop_|
@@ -138,9 +137,6 @@
   // A webframe for loading.
   WebKit::WebFrame* frame_;
 
-  // True if the media resource has a single origin.
-  bool single_origin_;
-
   // A resource loader for the media resource.
   scoped_refptr<BufferedResourceLoader> loader_;
 
@@ -175,7 +171,7 @@
   MessageLoop* render_loop_;
 
   // Protects |stopped_|.
-  Lock lock_;
+  base::Lock lock_;
 
   // Stop signal to suppressing activities. This variable is set on the pipeline
   // thread and read from the render thread.
diff --git a/webkit/glue/media/buffered_data_source_unittest.cc b/webkit/glue/media/buffered_data_source_unittest.cc
index dcb11ec..f370803 100644
--- a/webkit/glue/media/buffered_data_source_unittest.cc
+++ b/webkit/glue/media/buffered_data_source_unittest.cc
@@ -1,15 +1,16 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <algorithm>
 
 #include "base/test/test_timeouts.h"
+#include "media/base/mock_callback.h"
 #include "media/base/mock_filter_host.h"
 #include "media/base/mock_filters.h"
 #include "net/base/net_errors.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 #include "webkit/glue/media/buffered_data_source.h"
 #include "webkit/mocks/mock_webframe.h"
 
@@ -104,7 +105,6 @@
   }
 
   virtual ~BufferedDataSourceTest() {
-    ignore_result(frame_.release());
   }
 
   void ExpectCreateAndStartResourceLoader(int start_error) {
@@ -167,7 +167,6 @@
     ON_CALL(*loader_, Read(_, _, _ , _))
         .WillByDefault(DeleteArg<3>());
 
-    StrictMock<media::MockFilterCallback> callback;
     ON_CALL(*loader_, instance_size())
         .WillByDefault(Return(instance_size));
     ON_CALL(*loader_, partial_response())
@@ -188,18 +187,13 @@
       } else {
         EXPECT_CALL(host_, SetStreaming(true));
       }
-
-      EXPECT_CALL(callback, OnFilterCallback());
-      EXPECT_CALL(callback, OnCallbackDestroyed());
     } else {
       EXPECT_CALL(host_, SetError(media::PIPELINE_ERROR_NETWORK));
       EXPECT_CALL(*loader_, Stop());
-      EXPECT_CALL(callback, OnFilterCallback());
-      EXPECT_CALL(callback, OnCallbackDestroyed());
     }
 
     // Actual initialization of the data source.
-    data_source_->Initialize(url, callback.NewCallback());
+    data_source_->Initialize(url, media::NewExpectedCallback());
     message_loop_->RunAllPending();
 
     if (initialized_ok) {
@@ -220,10 +214,7 @@
       EXPECT_CALL(*loader_, Stop());
     }
 
-    StrictMock<media::MockFilterCallback> callback;
-    EXPECT_CALL(callback, OnFilterCallback());
-    EXPECT_CALL(callback, OnCallbackDestroyed());
-    data_source_->Stop(callback.NewCallback());
+    data_source_->Stop(media::NewExpectedCallback());
     message_loop_->RunAllPending();
   }
 
@@ -501,4 +492,70 @@
   StopDataSource();
 }
 
+// This test makes sure that Stop() does not require a task to run on
+// |message_loop_| before it calls its callback. This prevents accidental
+// introduction of a pipeline teardown deadlock. The pipeline owner blocks
+// the render message loop while waiting for Stop() to complete. Since this
+// object runs on the render message loop, Stop() will not complete if it
+// requires a task to run on the the message loop that is being blocked.
+TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
+  InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
+
+  // Create a callback that lets us verify that it was called before
+  // Stop() returns. This is to make sure that the callback does not
+  // require |message_loop_| to execute tasks before being called.
+  media::MockCallback* stop_callback = media::NewExpectedCallback();
+  bool stop_done_called = false;
+  ON_CALL(*stop_callback, RunWithParams(_))
+      .WillByDefault(Assign(&stop_done_called, true));
+
+  // Stop() the data source like normal.
+  data_source_->Stop(stop_callback);
+
+  // Verify that the callback was called inside the Stop() call.
+  EXPECT_TRUE(stop_done_called);
+
+  message_loop_->RunAllPending();
+}
+
+TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) {
+  InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
+
+  // Setup a way to verify that Read() is not called on the loader.
+  // We are doing this to make sure that the ReadTask() is still on
+  // the message loop queue when Abort() is called.
+  bool read_called = false;
+  ON_CALL(*loader_, Read(_, _, _ , _))
+      .WillByDefault(DoAll(Assign(&read_called, true),
+                           DeleteArg<3>()));
+
+  // Initiate a Read() on the data source, but don't allow the
+  // message loop to run.
+  data_source_->Read(
+      0, 10, buffer_,
+      NewCallback(static_cast<BufferedDataSourceTest*>(this),
+                  &BufferedDataSourceTest::ReadCallback));
+
+  // Call Abort() with the read pending.
+  EXPECT_CALL(*this, ReadCallback(-1));
+  EXPECT_CALL(*loader_, Stop());
+  data_source_->Abort();
+
+  // Verify that Read()'s after the Abort() issue callback with an error.
+  EXPECT_CALL(*this, ReadCallback(-1));
+  data_source_->Read(
+      0, 10, buffer_,
+      NewCallback(static_cast<BufferedDataSourceTest*>(this),
+                  &BufferedDataSourceTest::ReadCallback));
+
+  // Stop() the data source like normal.
+  data_source_->Stop(media::NewExpectedCallback());
+
+  // Allow cleanup task to run.
+  message_loop_->RunAllPending();
+
+  // Verify that Read() was not called on the loader.
+  EXPECT_FALSE(read_called);
+}
+
 }  // namespace webkit_glue
diff --git a/webkit/glue/media/buffered_resource_loader.cc b/webkit/glue/media/buffered_resource_loader.cc
index 61aac72..a86d2dd 100644
--- a/webkit/glue/media/buffered_resource_loader.cc
+++ b/webkit/glue/media/buffered_resource_loader.cc
@@ -7,10 +7,10 @@
 #include "base/format_macros.h"
 #include "base/string_util.h"
 #include "net/base/net_errors.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
 #include "webkit/glue/multipart_response_delegate.h"
 #include "webkit/glue/webkit_glue.h"
 
@@ -61,6 +61,7 @@
       url_(url),
       first_byte_position_(first_byte_position),
       last_byte_position_(last_byte_position),
+      single_origin_(true),
       start_callback_(NULL),
       offset_(0),
       content_length_(kPositionNotSpecified),
@@ -255,6 +256,10 @@
     return;
   }
 
+  // Only allow |single_origin_| if we haven't seen a different origin yet.
+  if (single_origin_)
+    single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
+
   url_ = newRequest.url();
 }
 
@@ -425,6 +430,10 @@
   Release();
 }
 
+bool BufferedResourceLoader::HasSingleOrigin() const {
+  return single_origin_;
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // Helper methods.
 void BufferedResourceLoader::EnableDeferIfNeeded() {
diff --git a/webkit/glue/media/buffered_resource_loader.h b/webkit/glue/media/buffered_resource_loader.h
index 09b05e6..fe01fb4 100644
--- a/webkit/glue/media/buffered_resource_loader.h
+++ b/webkit/glue/media/buffered_resource_loader.h
@@ -8,16 +8,15 @@
 #include <string>
 
 #include "base/callback.h"
-#include "base/lock.h"
 #include "base/scoped_ptr.h"
 #include "base/timer.h"
 #include "googleurl/src/gurl.h"
 #include "media/base/seekable_buffer.h"
 #include "net/base/file_stream.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
 #include "webkit/glue/media/web_data_source.h"
 #include "webkit/glue/webmediaplayer_impl.h"
 
@@ -140,6 +139,8 @@
       WebKit::WebURLLoader* loader,
       const WebKit::WebURLError&);
 
+  bool HasSingleOrigin() const;
+
  protected:
   friend class base::RefCountedThreadSafe<BufferedResourceLoader>;
 
@@ -213,6 +214,7 @@
   GURL url_;
   int64 first_byte_position_;
   int64 last_byte_position_;
+  bool single_origin_;
 
   // Callback method that listens to network events.
   scoped_ptr<NetworkEventCallback> event_callback_;
diff --git a/webkit/glue/media/buffered_resource_loader_unittest.cc b/webkit/glue/media/buffered_resource_loader_unittest.cc
index 8e64c26..dc67edf 100644
--- a/webkit/glue/media/buffered_resource_loader_unittest.cc
+++ b/webkit/glue/media/buffered_resource_loader_unittest.cc
@@ -8,11 +8,11 @@
 #include "base/stringprintf.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrameClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/media/buffered_resource_loader.h"
 #include "webkit/mocks/mock_webframe.h"
 #include "webkit/mocks/mock_weburlloader.h"
@@ -41,6 +41,11 @@
 namespace {
 
 const char* kHttpUrl = "http://test";
+const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing";
+const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2";
+const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2";
+const char kHttpRedirectToDifferentDomainUrl2[] = "http://test2/ing";
+
 const int kDataSize = 1024;
 const int kHttpOK = 200;
 const int kHttpPartialContent = 206;
@@ -67,14 +72,11 @@
 class BufferedResourceLoaderTest : public testing::Test {
  public:
   BufferedResourceLoaderTest() {
-    url_loader_ = new NiceMock<MockWebURLLoader>();
-
     for (int i = 0; i < kDataSize; ++i)
       data_[i] = i;
   }
 
   virtual ~BufferedResourceLoaderTest() {
-    ignore_result(frame_.release());
   }
 
   void Initialize(const char* url, int first_position, int last_position) {
@@ -84,6 +86,7 @@
 
     frame_.reset(new NiceMock<MockWebFrame>());
 
+    url_loader_ = new NiceMock<MockWebURLLoader>();
     loader_ = new BufferedResourceLoader(gurl_,
                                          first_position_, last_position_);
     loader_->SetURLLoaderForTest(url_loader_);
@@ -138,11 +141,22 @@
     EXPECT_TRUE(loader_->partial_response());
   }
 
+  void Redirect(const char* url) {
+    GURL redirectUrl(url);
+    WebKit::WebURLRequest newRequest(redirectUrl);
+    WebKit::WebURLResponse redirectResponse(gurl_);
+
+    loader_->willSendRequest(url_loader_, newRequest, redirectResponse);
+
+    MessageLoop::current()->RunAllPending();
+  }
+
   void StopWhenLoad() {
     InSequence s;
     EXPECT_CALL(*url_loader_, cancel())
         .WillOnce(RequestCanceled(loader_));
     loader_->Stop();
+    loader_ = NULL;
   }
 
   // Helper method to write to |loader_| from |data_|.
@@ -480,7 +494,64 @@
   ReadLoader(20, 5, buffer);
   StopWhenLoad();
 }
+
+// NOTE: This test will need to be reworked a little once
+// http://code.google.com/p/chromium/issues/detail?id=72578
+// is fixed.
+TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
+  // Make sure no redirect case works as expected.
+  Initialize(kHttpUrl, -1, -1);
+  Start();
+  FullResponse(1024);
+  EXPECT_TRUE(loader_->HasSingleOrigin());
+  StopWhenLoad();
+
+  // Test redirect to the same domain.
+  Initialize(kHttpUrl, -1, -1);
+  Start();
+  Redirect(kHttpRedirectToSameDomainUrl1);
+  FullResponse(1024);
+  EXPECT_TRUE(loader_->HasSingleOrigin());
+  StopWhenLoad();
+
+  // Test redirect twice to the same domain.
+  Initialize(kHttpUrl, -1, -1);
+  Start();
+  Redirect(kHttpRedirectToSameDomainUrl1);
+  Redirect(kHttpRedirectToSameDomainUrl2);
+  FullResponse(1024);
+  EXPECT_TRUE(loader_->HasSingleOrigin());
+  StopWhenLoad();
+
+  // Test redirect to a different domain.
+  Initialize(kHttpUrl, -1, -1);
+  Start();
+  Redirect(kHttpRedirectToDifferentDomainUrl1);
+  FullResponse(1024);
+  EXPECT_FALSE(loader_->HasSingleOrigin());
+  StopWhenLoad();
+
+  // Test redirect twice to a different domain.
+  Initialize(kHttpUrl, -1, -1);
+  Start();
+  Redirect(kHttpRedirectToDifferentDomainUrl1);
+  Redirect(kHttpRedirectToDifferentDomainUrl2);
+  FullResponse(1024);
+  EXPECT_FALSE(loader_->HasSingleOrigin());
+  StopWhenLoad();
+
+  // Test to a different domain and then back to the same domain.
+  // NOTE: A different origin was encountered at least once so that
+  //       makes HasSingleOrigin() become false.
+  Initialize(kHttpUrl, -1, -1);
+  Start();
+  Redirect(kHttpRedirectToDifferentDomainUrl1);
+  Redirect(kHttpRedirectToSameDomainUrl1);
+  FullResponse(1024);
+  EXPECT_FALSE(loader_->HasSingleOrigin());
+  StopWhenLoad();
+}
+
 // TODO(hclam): add unit test for defer loading.
 
 }  // namespace webkit_glue
-
diff --git a/webkit/glue/media/simple_data_source.cc b/webkit/glue/media/simple_data_source.cc
index 8869e28..07f7587 100644
--- a/webkit/glue/media/simple_data_source.cc
+++ b/webkit/glue/media/simple_data_source.cc
@@ -10,8 +10,8 @@
 #include "net/base/data_url.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request_status.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
 #include "webkit/glue/webkit_glue.h"
 
 namespace {
@@ -35,12 +35,12 @@
 }
 
 SimpleDataSource::~SimpleDataSource() {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   DCHECK(state_ == UNINITIALIZED || state_ == STOPPED);
 }
 
 void SimpleDataSource::Stop(media::FilterCallback* callback) {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   state_ = STOPPED;
   if (callback) {
     callback->Run();
@@ -54,7 +54,7 @@
 
 void SimpleDataSource::Initialize(const std::string& url,
                                   media::FilterCallback* callback) {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   DCHECK_EQ(state_, UNINITIALIZED);
   DCHECK(callback);
   state_ = INITIALIZING;
@@ -113,7 +113,10 @@
     WebKit::WebURLRequest& newRequest,
     const WebKit::WebURLResponse& redirectResponse) {
   DCHECK(MessageLoop::current() == render_loop_);
-  single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
+
+  // Only allow |single_origin_| if we haven't seen a different origin yet.
+  if (single_origin_)
+    single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
 
   url_ = newRequest.url();
 }
@@ -157,7 +160,7 @@
     WebKit::WebURLLoader* loader,
     double finishTime) {
   DCHECK(MessageLoop::current() == render_loop_);
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   // It's possible this gets called after Stop(), in which case |host_| is no
   // longer valid.
   if (state_ == STOPPED)
@@ -179,7 +182,7 @@
     WebKit::WebURLLoader* loader,
     const WebKit::WebURLError& error) {
   DCHECK(MessageLoop::current() == render_loop_);
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   // It's possible this gets called after Stop(), in which case |host_| is no
   // longer valid.
   if (state_ == STOPPED)
@@ -217,7 +220,7 @@
 
 void SimpleDataSource::StartTask() {
   DCHECK(MessageLoop::current() == render_loop_);
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
 
   // We may have stopped.
   if (state_ == STOPPED)
@@ -253,7 +256,7 @@
 
 void SimpleDataSource::CancelTask() {
   DCHECK(MessageLoop::current() == render_loop_);
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   DCHECK_EQ(state_, STOPPED);
 
   // Cancel any pending requests.
diff --git a/webkit/glue/media/simple_data_source.h b/webkit/glue/media/simple_data_source.h
index f4c83e6..10d93ff 100644
--- a/webkit/glue/media/simple_data_source.h
+++ b/webkit/glue/media/simple_data_source.h
@@ -16,11 +16,11 @@
 #include "base/message_loop.h"
 #include "base/scoped_ptr.h"
 #include "media/base/filters.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 #include "webkit/glue/media/web_data_source.h"
 
 class MessageLoop;
@@ -120,7 +120,7 @@
   State state_;
 
   // Used for accessing |state_|.
-  Lock lock_;
+  base::Lock lock_;
 
   // Filter callbacks.
   scoped_ptr<media::FilterCallback> initialize_callback_;
diff --git a/webkit/glue/media/simple_data_source_unittest.cc b/webkit/glue/media/simple_data_source_unittest.cc
index 55dc913..a9a70a4 100644
--- a/webkit/glue/media/simple_data_source_unittest.cc
+++ b/webkit/glue/media/simple_data_source_unittest.cc
@@ -1,17 +1,17 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/callback.h"
 #include "media/base/filters.h"
+#include "media/base/mock_callback.h"
 #include "media/base/mock_filter_host.h"
 #include "media/base/mock_filters.h"
 #include "net/base/net_errors.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 #include "webkit/glue/media/simple_data_source.h"
 #include "webkit/mocks/mock_webframe.h"
 #include "webkit/mocks/mock_weburlloader.h"
@@ -42,6 +42,10 @@
     "data:text/plain;base64,YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoK";
 const char kDataUrlDecoded[] = "abcdefghijklmnopqrstuvwxyz";
 const char kInvalidUrl[] = "whatever://test";
+const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing";
+const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2";
+const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2";
+const char kHttpRedirectToDifferentDomainUrl2[] = "http://test2/ing";
 
 }  // namespace
 
@@ -56,10 +60,10 @@
   }
 
   virtual ~SimpleDataSourceTest() {
-    ignore_result(frame_.release());
   }
 
-  void InitializeDataSource(const char* url) {
+  void InitializeDataSource(const char* url,
+                            media::MockCallback* callback) {
     gurl_ = GURL(url);
 
     frame_.reset(new NiceMock<MockWebFrame>());
@@ -72,9 +76,7 @@
     data_source_->set_host(&host_);
     data_source_->SetURLLoaderForTest(url_loader_);
 
-    InSequence s;
-
-    data_source_->Initialize(url, callback_.NewCallback());
+    data_source_->Initialize(url, callback);
     MessageLoop::current()->RunAllPending();
   }
 
@@ -96,8 +98,6 @@
     InSequence s;
     EXPECT_CALL(host_, SetTotalBytes(kDataSize));
     EXPECT_CALL(host_, SetBufferedBytes(kDataSize));
-    EXPECT_CALL(callback_, OnFilterCallback());
-    EXPECT_CALL(callback_, OnCallbackDestroyed());
 
     data_source_->didFinishLoading(NULL, 0);
 
@@ -108,8 +108,6 @@
   void RequestFailed() {
     InSequence s;
     EXPECT_CALL(host_, SetError(media::PIPELINE_ERROR_NETWORK));
-    EXPECT_CALL(callback_, OnFilterCallback());
-    EXPECT_CALL(callback_, OnCallbackDestroyed());
 
     WebURLError error;
     error.reason = net::ERR_FAILED;
@@ -119,12 +117,18 @@
     MessageLoop::current()->RunAllPending();
   }
 
-  void DestroyDataSource() {
-    StrictMock<media::MockFilterCallback> callback;
-    EXPECT_CALL(callback, OnFilterCallback());
-    EXPECT_CALL(callback, OnCallbackDestroyed());
+  void Redirect(const char* url) {
+    GURL redirectUrl(url);
+    WebKit::WebURLRequest newRequest(redirectUrl);
+    WebKit::WebURLResponse redirectResponse(gurl_);
 
-    data_source_->Stop(callback.NewCallback());
+    data_source_->willSendRequest(url_loader_, newRequest, redirectResponse);
+
+    MessageLoop::current()->RunAllPending();
+  }
+
+  void DestroyDataSource() {
+    data_source_->Stop(media::NewExpectedCallback());
     MessageLoop::current()->RunAllPending();
 
     data_source_ = NULL;
@@ -150,7 +154,6 @@
   NiceMock<MockWebURLLoader>* url_loader_;
   scoped_refptr<SimpleDataSource> data_source_;
   StrictMock<media::MockFilterHost> host_;
-  StrictMock<media::MockFilterCallback> callback_;
   scoped_ptr<NiceMock<MockWebFrame> > frame_;
 
   char data_[kDataSize];
@@ -159,19 +162,19 @@
 };
 
 TEST_F(SimpleDataSourceTest, InitializeHTTP) {
-  InitializeDataSource(kHttpUrl);
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
   RequestSucceeded(false);
   DestroyDataSource();
 }
 
 TEST_F(SimpleDataSourceTest, InitializeHTTPS) {
-  InitializeDataSource(kHttpsUrl);
+  InitializeDataSource(kHttpsUrl, media::NewExpectedCallback());
   RequestSucceeded(false);
   DestroyDataSource();
 }
 
 TEST_F(SimpleDataSourceTest, InitializeFile) {
-  InitializeDataSource(kFileUrl);
+  InitializeDataSource(kFileUrl, media::NewExpectedCallback());
   RequestSucceeded(true);
   DestroyDataSource();
 }
@@ -191,34 +194,88 @@
   EXPECT_CALL(host_, SetLoaded(true));
   EXPECT_CALL(host_, SetTotalBytes(sizeof(kDataUrlDecoded)));
   EXPECT_CALL(host_, SetBufferedBytes(sizeof(kDataUrlDecoded)));
-  EXPECT_CALL(callback_, OnFilterCallback());
-  EXPECT_CALL(callback_, OnCallbackDestroyed());
 
-  data_source_->Initialize(kDataUrl, callback_.NewCallback());
+  data_source_->Initialize(kDataUrl, media::NewExpectedCallback());
   MessageLoop::current()->RunAllPending();
 
   DestroyDataSource();
 }
 
 TEST_F(SimpleDataSourceTest, RequestFailed) {
-  InitializeDataSource(kHttpUrl);
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
   RequestFailed();
   DestroyDataSource();
 }
 
 TEST_F(SimpleDataSourceTest, StopWhenDownloading) {
-  InitializeDataSource(kHttpUrl);
+  // The callback should be deleted, but not executed.
+  // TODO(scherkus): should this really be the behaviour?  Seems strange...
+  StrictMock<media::MockCallback>* callback =
+      new StrictMock<media::MockCallback>();
+  EXPECT_CALL(*callback, Destructor());
+
+  InitializeDataSource(kHttpUrl, callback);
 
   EXPECT_CALL(*url_loader_, cancel());
-  EXPECT_CALL(callback_, OnCallbackDestroyed());
   DestroyDataSource();
 }
 
 TEST_F(SimpleDataSourceTest, AsyncRead) {
-  InitializeDataSource(kFileUrl);
+  InitializeDataSource(kFileUrl, media::NewExpectedCallback());
   RequestSucceeded(true);
   AsyncRead();
   DestroyDataSource();
 }
 
+// NOTE: This test will need to be reworked a little once
+// http://code.google.com/p/chromium/issues/detail?id=72578
+// is fixed.
+TEST_F(SimpleDataSourceTest, HasSingleOrigin) {
+  // Make sure no redirect case works as expected.
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
+  RequestSucceeded(false);
+  EXPECT_TRUE(data_source_->HasSingleOrigin());
+  DestroyDataSource();
+
+  // Test redirect to the same domain.
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
+  Redirect(kHttpRedirectToSameDomainUrl1);
+  RequestSucceeded(false);
+  EXPECT_TRUE(data_source_->HasSingleOrigin());
+  DestroyDataSource();
+
+  // Test redirect twice to the same domain.
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
+  Redirect(kHttpRedirectToSameDomainUrl1);
+  Redirect(kHttpRedirectToSameDomainUrl2);
+  RequestSucceeded(false);
+  EXPECT_TRUE(data_source_->HasSingleOrigin());
+  DestroyDataSource();
+
+  // Test redirect to a different domain.
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
+  Redirect(kHttpRedirectToDifferentDomainUrl1);
+  RequestSucceeded(false);
+  EXPECT_FALSE(data_source_->HasSingleOrigin());
+  DestroyDataSource();
+
+  // Test redirect twice to a different domain.
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
+  Redirect(kHttpRedirectToDifferentDomainUrl1);
+  Redirect(kHttpRedirectToDifferentDomainUrl2);
+  RequestSucceeded(false);
+  EXPECT_FALSE(data_source_->HasSingleOrigin());
+  DestroyDataSource();
+
+  // Test to a different domain and then back to the same domain.
+  // NOTE: A different origin was encountered at least once so that
+  //       makes HasSingleOrigin() become false.
+  InitializeDataSource(kHttpUrl, media::NewExpectedCallback());
+  Redirect(kHttpRedirectToDifferentDomainUrl1);
+  Redirect(kHttpRedirectToSameDomainUrl1);
+  RequestSucceeded(false);
+  EXPECT_FALSE(data_source_->HasSingleOrigin());
+  DestroyDataSource();
+}
+
 }  // namespace webkit_glue
diff --git a/webkit/glue/media/video_renderer_impl.h b/webkit/glue/media/video_renderer_impl.h
index 34c67d3..b73c099 100644
--- a/webkit/glue/media/video_renderer_impl.h
+++ b/webkit/glue/media/video_renderer_impl.h
@@ -10,13 +10,13 @@
 #ifndef WEBKIT_GLUE_MEDIA_VIDEO_RENDERER_IMPL_H_
 #define WEBKIT_GLUE_MEDIA_VIDEO_RENDERER_IMPL_H_
 
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "media/base/buffers.h"
 #include "media/base/filters.h"
 #include "media/filters/video_renderer_base.h"
 #include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayer.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayer.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 #include "webkit/glue/media/web_video_renderer.h"
 #include "webkit/glue/webmediaplayer_impl.h"
 
diff --git a/webkit/glue/mimetype_unittest.cc b/webkit/glue/mimetype_unittest.cc
index 3f17e79..00be1a5 100644
--- a/webkit/glue/mimetype_unittest.cc
+++ b/webkit/glue/mimetype_unittest.cc
@@ -5,9 +5,9 @@
 #include <string>
 
 #include "base/string_util.h"
-#include "net/url_request/url_request_unittest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "net/url_request/url_request_test_util.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/unittest_test_server.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
diff --git a/webkit/glue/multipart_response_delegate.cc b/webkit/glue/multipart_response_delegate.cc
index b8c7758..d2c47d7 100644
--- a/webkit/glue/multipart_response_delegate.cc
+++ b/webkit/glue/multipart_response_delegate.cc
@@ -9,10 +9,10 @@
 #include "base/string_util.h"
 #include "net/base/net_util.h"
 #include "net/http/http_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
 
 using WebKit::WebHTTPHeaderVisitor;
 using WebKit::WebString;
@@ -291,9 +291,8 @@
       response.httpHeaderField(WebString::fromUTF8("Content-Type")).utf8();
 
   size_t boundary_start_offset = content_type.find("boundary=");
-  if (boundary_start_offset == std::wstring::npos) {
+  if (boundary_start_offset == std::string::npos)
     return false;
-  }
 
   boundary_start_offset += strlen("boundary=");
 
diff --git a/webkit/glue/multipart_response_delegate.h b/webkit/glue/multipart_response_delegate.h
index 0500983..d4583bb 100644
--- a/webkit/glue/multipart_response_delegate.h
+++ b/webkit/glue/multipart_response_delegate.h
@@ -52,7 +52,7 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 
 namespace WebKit {
 class WebURLLoader;
diff --git a/webkit/glue/multipart_response_delegate_unittest.cc b/webkit/glue/multipart_response_delegate_unittest.cc
index 1837cb5..fbefaaa 100644
--- a/webkit/glue/multipart_response_delegate_unittest.cc
+++ b/webkit/glue/multipart_response_delegate_unittest.cc
@@ -5,10 +5,10 @@
 #include <vector>
 
 #include "base/basictypes.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 #include "webkit/glue/multipart_response_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/webkit/glue/npruntime_util.cc b/webkit/glue/npruntime_util.cc
index dfc3a2b..a408770 100644
--- a/webkit/glue/npruntime_util.cc
+++ b/webkit/glue/npruntime_util.cc
@@ -5,7 +5,7 @@
 #include "webkit/glue/npruntime_util.h"
 
 #include "base/pickle.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
 
 using WebKit::WebBindings;
 
diff --git a/webkit/glue/password_form.h b/webkit/glue/password_form.h
index c2967a4..e48420c 100644
--- a/webkit/glue/password_form.h
+++ b/webkit/glue/password_form.h
@@ -10,7 +10,7 @@
 
 #include "base/time.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPasswordFormData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPasswordFormData.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/password_form_dom_manager.cc b/webkit/glue/password_form_dom_manager.cc
index 97f3eef..be4bc76 100644
--- a/webkit/glue/password_form_dom_manager.cc
+++ b/webkit/glue/password_form_dom_manager.cc
@@ -5,8 +5,8 @@
 #include "webkit/glue/password_form_dom_manager.h"
 
 #include "base/logging.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPasswordFormData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPasswordFormData.h"
 #include "webkit/glue/form_field.h"
 
 using WebKit::WebFormElement;
diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h
index 111e8fa..580d8dd 100644
--- a/webkit/glue/plugins/plugin_list.h
+++ b/webkit/glue/plugins/plugin_list.h
@@ -18,7 +18,6 @@
 namespace NPAPI {
 
 typedef webkit::npapi::PluginEntryPoints PluginEntryPoints;
-typedef webkit::npapi::PluginVersionInfo PluginVersionInfo;
 
 class PluginList {
  public:
diff --git a/webkit/glue/regular_expression_unittest.cc b/webkit/glue/regular_expression_unittest.cc
index 39741f8..9713c39 100644
--- a/webkit/glue/regular_expression_unittest.cc
+++ b/webkit/glue/regular_expression_unittest.cc
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRegularExpression.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebTextCaseSensitivity.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivity.h"
 
 using namespace WebKit;
 
diff --git a/webkit/glue/resource_fetcher.cc b/webkit/glue/resource_fetcher.cc
index 9b00805..39cc59c 100644
--- a/webkit/glue/resource_fetcher.cc
+++ b/webkit/glue/resource_fetcher.cc
@@ -5,13 +5,13 @@
 #include "webkit/glue/resource_fetcher.h"
 
 #include "base/logging.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
 
 using base::TimeDelta;
 using WebKit::WebFrame;
@@ -25,8 +25,8 @@
 ResourceFetcher::ResourceFetcher(const GURL& url, WebFrame* frame,
                                  Callback* c)
     : url_(url),
-      callback_(c),
-      completed_(false) {
+      completed_(false),
+      callback_(c) {
   // Can't do anything without a frame.  However, delegate can be NULL (so we
   // can do a http request and ignore the results).
   DCHECK(frame);
@@ -53,6 +53,18 @@
   loader_->loadAsynchronously(request, this);
 }
 
+void ResourceFetcher::RunCallback(const WebURLResponse& response,
+                                  const std::string& data) {
+  if (!callback_.get())
+    return;
+
+  // Take care to clear callback_ before running the callback as it may lead to
+  // our destruction.
+  scoped_ptr<Callback> callback;
+  callback.swap(callback_);
+  callback->Run(response, data);
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // WebURLLoaderClient methods
 
@@ -93,10 +105,7 @@
   DCHECK(!completed_);
   completed_ = true;
 
-  if (callback_.get()) {
-    callback_->Run(response_, data_);
-    callback_.reset();
-  }
+  RunCallback(response_, data_);
 }
 
 void ResourceFetcher::didFail(WebURLLoader* loader, const WebURLError& error) {
@@ -104,10 +113,7 @@
   completed_ = true;
 
   // Go ahead and tell our delegate that we're done.
-  if (callback_.get()) {
-    callback_->Run(WebURLResponse(), std::string());
-    callback_.reset();
-  }
+  RunCallback(WebURLResponse(), std::string());
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/webkit/glue/resource_fetcher.h b/webkit/glue/resource_fetcher.h
index ff00939..eb9411b 100644
--- a/webkit/glue/resource_fetcher.h
+++ b/webkit/glue/resource_fetcher.h
@@ -19,8 +19,8 @@
 #include "base/scoped_ptr.h"
 #include "base/timer.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 
 class GURL;
 
@@ -75,9 +75,6 @@
   // URL we're fetching
   GURL url_;
 
-  // Callback when we're done
-  scoped_ptr<Callback> callback_;
-
   // A copy of the original resource response
   WebKit::WebURLResponse response_;
 
@@ -88,6 +85,12 @@
   // Start the actual download.
   void Start(WebKit::WebFrame* frame);
 
+  void RunCallback(const WebKit::WebURLResponse& response,
+                   const std::string& data);
+
+  // Callback when we're done
+  scoped_ptr<Callback> callback_;
+
   // Buffer to hold the content from the server.
   std::string data_;
 
diff --git a/webkit/glue/resource_fetcher_unittest.cc b/webkit/glue/resource_fetcher_unittest.cc
index 3ac004e..965d285 100644
--- a/webkit/glue/resource_fetcher_unittest.cc
+++ b/webkit/glue/resource_fetcher_unittest.cc
@@ -6,17 +6,14 @@
 
 #include "base/callback.h"
 #include "base/message_loop.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "base/timer.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/unittest_test_server.h"
 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
 
-#if defined(TOOLKIT_USES_GTK)
-#include <gtk/gtk.h>
-#endif
-
 using WebKit::WebFrame;
 using WebKit::WebURLResponse;
 using webkit_glue::ResourceFetcher;
@@ -30,35 +27,34 @@
 };
 
 static const int kMaxWaitTimeMs = 5000;
-static const int kWaitIntervalMs = 100;
 
 class FetcherDelegate {
  public:
   FetcherDelegate()
-      : timer_id_(0), completed_(false), time_elapsed_ms_(0) {
+      : completed_(false),
+        timed_out_(false) {
     // Start a repeating timer waiting for the download to complete.  The
     // callback has to be a static function, so we hold on to our instance.
     FetcherDelegate::instance_ = this;
-    CreateTimer(kWaitIntervalMs);
+    StartTimer();
   }
 
   ResourceFetcher::Callback* NewCallback() {
     return ::NewCallback(this, &FetcherDelegate::OnURLFetchComplete);
   }
 
-  void OnURLFetchComplete(const WebURLResponse& response,
-                          const std::string& data) {
+  virtual void OnURLFetchComplete(const WebURLResponse& response,
+                                  const std::string& data) {
     response_ = response;
     data_ = data;
     completed_ = true;
-    DestroyTimer();
+    timer_.Stop();
     MessageLoop::current()->Quit();
   }
 
   bool completed() const { return completed_; }
-  bool timed_out() const { return time_elapsed_ms_ > kMaxWaitTimeMs; }
+  bool timed_out() const { return timed_out_; }
 
-  int time_elapsed_ms() const { return time_elapsed_ms_; }
   std::string data() const { return data_; }
   const WebURLResponse& response() const { return response_; }
 
@@ -70,78 +66,26 @@
       MessageLoop::current()->Run();
   }
 
-  void CreateTimer(int interval) {
-#if defined(OS_WIN)
-    timer_id_ = ::SetTimer(NULL, NULL, interval,
-                           &FetcherDelegate::TimerCallback);
-#elif defined(TOOLKIT_USES_GTK)
-    timer_id_ = g_timeout_add(interval, &FetcherDelegate::TimerCallback, NULL);
-#elif defined(OS_MACOSX)
-    // CFAbsoluteTime is in seconds and |interval| is in ms, so make sure we
-    // keep the units correct.
-    CFTimeInterval interval_in_seconds = static_cast<double>(interval) / 1000.0;
-    CFAbsoluteTime fire_date =
-        CFAbsoluteTimeGetCurrent() + interval_in_seconds;
-    timer_id_ = CFRunLoopTimerCreate(NULL, fire_date, interval_in_seconds, 0,
-                                     0, FetcherDelegate::TimerCallback, NULL);
-    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer_id_, kCFRunLoopCommonModes);
-#endif
+  void StartTimer() {
+    timer_.Start(base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs),
+                 this,
+                 &FetcherDelegate::TimerFired);
   }
 
-  void DestroyTimer() {
-#if defined(OS_WIN)
-    ::KillTimer(NULL, timer_id_);
-#elif defined(TOOLKIT_USES_GTK)
-    g_source_remove(timer_id_);
-#elif defined(OS_MACOSX)
-    CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer_id_,
-                         kCFRunLoopCommonModes);
-    CFRelease(timer_id_);
-#endif
-  }
-
-#if defined(OS_WIN)
-  // Static timer callback, just passes through to instance version.
-  static VOID CALLBACK TimerCallback(HWND hwnd, UINT msg, UINT_PTR timer_id,
-                                     DWORD ms) {
-    instance_->TimerFired();
-  }
-#elif defined(TOOLKIT_USES_GTK)
-  static gboolean TimerCallback(gpointer data) {
-    instance_->TimerFired();
-    return true;
-  }
-#elif defined(OS_MACOSX)
-  static void TimerCallback(CFRunLoopTimerRef timer, void* info) {
-    instance_->TimerFired();
-  }
-#endif
-
   void TimerFired() {
     ASSERT_FALSE(completed_);
 
-    if (timed_out()) {
-      DestroyTimer();
-      MessageLoop::current()->Quit();
-      FAIL() << "fetch timed out";
-      return;
-    }
-
-    time_elapsed_ms_ += kWaitIntervalMs;
+    timed_out_ = true;
+    MessageLoop::current()->Quit();
+    FAIL() << "fetch timed out";
   }
 
   static FetcherDelegate* instance_;
 
  private:
-#if defined(OS_WIN)
-  UINT_PTR timer_id_;
-#elif defined(TOOLKIT_USES_GTK)
-  guint timer_id_;
-#elif defined(OS_MACOSX)
-  CFRunLoopTimerRef timer_id_;
-#endif
+  base::OneShotTimer<FetcherDelegate> timer_;
   bool completed_;
-  int time_elapsed_ms_;
+  bool timed_out_;
   WebURLResponse response_;
   std::string data_;
 };
@@ -198,7 +142,7 @@
   EXPECT_TRUE(delegate->completed());
   EXPECT_TRUE(delegate->response().isNull());
   EXPECT_EQ(delegate->data(), std::string());
-  EXPECT_TRUE(delegate->time_elapsed_ms() < kMaxWaitTimeMs);
+  EXPECT_FALSE(delegate->timed_out());
 }
 
 TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
@@ -220,7 +164,42 @@
   EXPECT_TRUE(delegate->completed());
   EXPECT_TRUE(delegate->response().isNull());
   EXPECT_EQ(delegate->data(), std::string());
-  EXPECT_TRUE(delegate->time_elapsed_ms() < kMaxWaitTimeMs);
+  EXPECT_FALSE(delegate->timed_out());
+}
+
+class EvilFetcherDelegate : public FetcherDelegate {
+ public:
+  void SetFetcher(ResourceFetcher* fetcher) {
+    fetcher_.reset(fetcher);
+  }
+
+  void OnURLFetchComplete(const WebURLResponse& response,
+                          const std::string& data) {
+    // Destroy the ResourceFetcher here.  We are testing that upon returning
+    // to the ResourceFetcher that it does not crash.
+    fetcher_.reset();
+    FetcherDelegate::OnURLFetchComplete(response, data);
+  }
+
+ private:
+  scoped_ptr<ResourceFetcher> fetcher_;
+};
+
+TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) {
+  ASSERT_TRUE(test_server_.Start());
+
+  WebFrame* frame = test_shell_->webView()->mainFrame();
+
+  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
+  // timeout in 0 sec.
+  GURL url(test_server_.GetURL("slow?1"));
+  scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
+  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
+      url, frame, 0, delegate->NewCallback()));
+  delegate->SetFetcher(fetcher.release());
+
+  delegate->WaitForResponse();
+  EXPECT_FALSE(delegate->timed_out());
 }
 
 }  // namespace
diff --git a/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h
index 85facfa..23ebb35 100644
--- a/webkit/glue/resource_loader_bridge.h
+++ b/webkit/glue/resource_loader_bridge.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -248,7 +248,7 @@
     ~SyncLoadResponse();
 
     // The response status.
-    URLRequestStatus status;
+    net::URLRequestStatus status;
 
     // The final URL of the response.  This may differ from the request URL in
     // the case of a server redirect.
diff --git a/webkit/glue/resources/linux-checkbox-disabled-indeterminate.png b/webkit/glue/resources/linux-checkbox-disabled-indeterminate.png
deleted file mode 100644
index 171d001..0000000
--- a/webkit/glue/resources/linux-checkbox-disabled-indeterminate.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-checkbox-disabled-off.png b/webkit/glue/resources/linux-checkbox-disabled-off.png
deleted file mode 100644
index c916674..0000000
--- a/webkit/glue/resources/linux-checkbox-disabled-off.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-checkbox-disabled-on.png b/webkit/glue/resources/linux-checkbox-disabled-on.png
deleted file mode 100644
index d9ff1c6..0000000
--- a/webkit/glue/resources/linux-checkbox-disabled-on.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-checkbox-indeterminate.png b/webkit/glue/resources/linux-checkbox-indeterminate.png
deleted file mode 100644
index dcde3c1..0000000
--- a/webkit/glue/resources/linux-checkbox-indeterminate.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-checkbox-off.png b/webkit/glue/resources/linux-checkbox-off.png
deleted file mode 100644
index 15cc949..0000000
--- a/webkit/glue/resources/linux-checkbox-off.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-checkbox-on.png b/webkit/glue/resources/linux-checkbox-on.png
deleted file mode 100644
index 4c72e8a..0000000
--- a/webkit/glue/resources/linux-checkbox-on.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-progress-bar.png b/webkit/glue/resources/linux-progress-bar.png
deleted file mode 100644
index 82a20f5..0000000
--- a/webkit/glue/resources/linux-progress-bar.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-progress-border-left.png b/webkit/glue/resources/linux-progress-border-left.png
deleted file mode 100644
index 0dd0e50..0000000
--- a/webkit/glue/resources/linux-progress-border-left.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-progress-border-right.png b/webkit/glue/resources/linux-progress-border-right.png
deleted file mode 100644
index d351b11..0000000
--- a/webkit/glue/resources/linux-progress-border-right.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-progress-value.png b/webkit/glue/resources/linux-progress-value.png
deleted file mode 100644
index 251917b..0000000
--- a/webkit/glue/resources/linux-progress-value.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-radio-disabled-off.png b/webkit/glue/resources/linux-radio-disabled-off.png
deleted file mode 100644
index 97aa6f9..0000000
--- a/webkit/glue/resources/linux-radio-disabled-off.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-radio-disabled-on.png b/webkit/glue/resources/linux-radio-disabled-on.png
deleted file mode 100644
index 07aed36..0000000
--- a/webkit/glue/resources/linux-radio-disabled-on.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-radio-off.png b/webkit/glue/resources/linux-radio-off.png
deleted file mode 100644
index 6a60a70..0000000
--- a/webkit/glue/resources/linux-radio-off.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/resources/linux-radio-on.png b/webkit/glue/resources/linux-radio-on.png
deleted file mode 100644
index cb47411..0000000
--- a/webkit/glue/resources/linux-radio-on.png
+++ /dev/null
Binary files differ
diff --git a/webkit/glue/scoped_clipboard_writer_glue.h b/webkit/glue/scoped_clipboard_writer_glue.h
index 7460ddf..13b96a3 100644
--- a/webkit/glue/scoped_clipboard_writer_glue.h
+++ b/webkit/glue/scoped_clipboard_writer_glue.h
@@ -5,7 +5,7 @@
 #ifndef SCOPED_CLIPBOARD_WRITER_GLUE_H_
 #define SCOPED_CLIPBOARD_WRITER_GLUE_H_
 
-#include "app/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
 
 class SkBitmap;
 
@@ -13,10 +13,10 @@
 class SharedMemory;
 }
 
-class ScopedClipboardWriterGlue : public ScopedClipboardWriter {
+class ScopedClipboardWriterGlue : public ui::ScopedClipboardWriter {
  public:
-  ScopedClipboardWriterGlue(Clipboard* clipboard)
-      : ScopedClipboardWriter(clipboard),
+   ScopedClipboardWriterGlue(ui::Clipboard* clipboard)
+      : ui::ScopedClipboardWriter(clipboard),
         shared_buf_(NULL) {
   }
 
diff --git a/webkit/glue/simple_webmimeregistry_impl.cc b/webkit/glue/simple_webmimeregistry_impl.cc
index d878867..b785be7 100644
--- a/webkit/glue/simple_webmimeregistry_impl.cc
+++ b/webkit/glue/simple_webmimeregistry_impl.cc
@@ -8,7 +8,7 @@
 #include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "net/base/mime_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebString;
diff --git a/webkit/glue/simple_webmimeregistry_impl.h b/webkit/glue/simple_webmimeregistry_impl.h
index f4f4d74..9796894 100644
--- a/webkit/glue/simple_webmimeregistry_impl.h
+++ b/webkit/glue/simple_webmimeregistry_impl.h
@@ -5,7 +5,7 @@
 #ifndef WEBMIMEREGISTRY_IMPL_H_
 #define WEBMIMEREGISTRY_IMPL_H_
 
-#include "third_party/WebKit/WebKit/chromium/public/WebMimeRegistry.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMimeRegistry.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/site_isolation_metrics.cc b/webkit/glue/site_isolation_metrics.cc
index ecc1464..0dca500 100644
--- a/webkit/glue/site_isolation_metrics.cc
+++ b/webkit/glue/site_isolation_metrics.cc
@@ -9,12 +9,12 @@
 #include "base/hash_tables.h"
 #include "base/metrics/histogram.h"
 #include "net/base/mime_sniffer.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 
 using WebKit::WebFrame;
 using WebKit::WebSecurityOrigin;
diff --git a/webkit/glue/site_isolation_metrics.h b/webkit/glue/site_isolation_metrics.h
index 53f1630..c2bd275 100644
--- a/webkit/glue/site_isolation_metrics.h
+++ b/webkit/glue/site_isolation_metrics.h
@@ -5,7 +5,7 @@
 #ifndef WEBKIT_GLUE_SITE_ISOLATION_METRICS_H_
 #define WEBKIT_GLUE_SITE_ISOLATION_METRICS_H_
 
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
 
 namespace WebKit {
 class WebFrame;
diff --git a/webkit/glue/user_agent.cc b/webkit/glue/user_agent.cc
index 4867c27..afd1c83 100644
--- a/webkit/glue/user_agent.cc
+++ b/webkit/glue/user_agent.cc
@@ -22,8 +22,14 @@
 std::string GetProductVersion();
 
 std::string GetWebKitVersion() {
-  return base::StringPrintf("%d.%d", WEBKIT_VERSION_MAJOR,
-                                     WEBKIT_VERSION_MINOR);
+  return base::StringPrintf("%d.%d (%s)",
+                            WEBKIT_VERSION_MAJOR,
+                            WEBKIT_VERSION_MINOR,
+                            WEBKIT_SVN_REVISION);
+}
+
+std::string GetWebKitRevision() {
+  return WEBKIT_SVN_REVISION;
 }
 
 std::string BuildOSCpuInfo() {
diff --git a/webkit/glue/user_agent.h b/webkit/glue/user_agent.h
index 3d1f788..62c8324 100644
--- a/webkit/glue/user_agent.h
+++ b/webkit/glue/user_agent.h
@@ -19,7 +19,7 @@
 // Builds a User-agent compatible string that describes the OS and CPU type.
 std::string BuildOSCpuInfo();
 
-// Returns the WebKit version (major.minor).
+// Returns the WebKit version, in the form "major.minor (branch@revision)".
 std::string GetWebKitVersion();
 
 }  // namespace webkit_glue
diff --git a/webkit/glue/web_io_operators.cc b/webkit/glue/web_io_operators.cc
index 9a53212..c053863 100644
--- a/webkit/glue/web_io_operators.cc
+++ b/webkit/glue/web_io_operators.cc
@@ -4,14 +4,14 @@
 
 #include "webkit/glue/web_io_operators.h"
 
-#include "gfx/point.h"
-#include "gfx/rect.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
 
 #if defined(WCHAR_T_IS_UTF32)
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 #endif  // defined(WCHAR_T_IS_UTF32)
 
 namespace WebKit {
diff --git a/webkit/glue/webaccessibility.cc b/webkit/glue/webaccessibility.cc
index c3ef261..b96266b 100644
--- a/webkit/glue/webaccessibility.cc
+++ b/webkit/glue/webaccessibility.cc
@@ -7,20 +7,20 @@
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityRole.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebAttribute.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocumentType.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFormControlElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNamedNodeMap.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObject.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityRole.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAttribute.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocumentType.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNamedNodeMap.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
 
 using WebKit::WebAccessibilityCache;
 using WebKit::WebAccessibilityRole;
diff --git a/webkit/glue/webaccessibility.h b/webkit/glue/webaccessibility.h
index c073502..081d156 100644
--- a/webkit/glue/webaccessibility.h
+++ b/webkit/glue/webaccessibility.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
 
 namespace WebKit {
 class WebAccessibilityCache;
diff --git a/webkit/glue/webclipboard_impl.cc b/webkit/glue/webclipboard_impl.cc
index 8e3f87b..b917677 100644
--- a/webkit/glue/webclipboard_impl.cc
+++ b/webkit/glue/webclipboard_impl.cc
@@ -1,21 +1,21 @@
-// 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.
+// Copyright (c) 2011 The Chromium 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 "webkit/glue/webclipboard_impl.h"
 
-#include "app/clipboard/clipboard.h"
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/escape.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebImage.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "ui/base/clipboard/clipboard.h"
 #include "webkit/glue/scoped_clipboard_writer_glue.h"
 #include "webkit/glue/webkit_glue.h"
 
@@ -62,19 +62,19 @@
 }
 
 bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
-  Clipboard::FormatType format_type;
-  Clipboard::Buffer buffer_type;
+  ui::Clipboard::FormatType format_type;
+  ui::Clipboard::Buffer buffer_type;
 
   switch (format) {
     case FormatHTML:
-      format_type = Clipboard::GetHtmlFormatType();
+      format_type = ui::Clipboard::GetHtmlFormatType();
       break;
     case FormatSmartPaste:
-      format_type = Clipboard::GetWebKitSmartPasteFormatType();
+      format_type = ui::Clipboard::GetWebKitSmartPasteFormatType();
       break;
     case FormatBookmark:
 #if defined(OS_WIN) || defined(OS_MACOSX)
-      format_type = Clipboard::GetUrlWFormatType();
+      format_type = ui::Clipboard::GetUrlWFormatType();
       break;
 #endif
     default:
@@ -89,11 +89,11 @@
 }
 
 WebString WebClipboardImpl::readPlainText(Buffer buffer) {
-  Clipboard::Buffer buffer_type;
+  ui::Clipboard::Buffer buffer_type;
   if (!ConvertBufferType(buffer, &buffer_type))
     return WebString();
 
-  if (ClipboardIsFormatAvailable(Clipboard::GetPlainTextWFormatType(),
+  if (ClipboardIsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
                                  buffer_type)) {
     string16 text;
     ClipboardReadText(buffer_type, &text);
@@ -101,7 +101,7 @@
       return text;
   }
 
-  if (ClipboardIsFormatAvailable(Clipboard::GetPlainTextFormatType(),
+  if (ClipboardIsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
                                  buffer_type)) {
     std::string text;
     ClipboardReadAsciiText(buffer_type, &text);
@@ -113,7 +113,7 @@
 }
 
 WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url) {
-  Clipboard::Buffer buffer_type;
+  ui::Clipboard::Buffer buffer_type;
   if (!ConvertBufferType(buffer, &buffer_type))
     return WebString();
 
@@ -145,7 +145,7 @@
 
   scw.WriteBookmark(title, url.spec());
   scw.WriteHTML(UTF8ToUTF16(URLToMarkup(url, title)), "");
-  scw.WriteText(UTF8ToUTF16(url.spec()));
+  scw.WriteText(UTF8ToUTF16(std::string(url.spec())));
 }
 
 void WebClipboardImpl::writeImage(
@@ -172,13 +172,15 @@
   }
 }
 
-void WebClipboardImpl::writeData(const WebKit::WebDragData& data) {
+void WebClipboardImpl::writeData(const WebString& type,
+                                 const WebString& data,
+                                 const WebString& metadata) {
   // TODO(dcheng): Implement this stub.
 }
 
 WebVector<WebString> WebClipboardImpl::readAvailableTypes(
     Buffer buffer, bool* contains_filenames) {
-  Clipboard::Buffer buffer_type;
+  ui::Clipboard::Buffer buffer_type;
   std::vector<string16> types;
   if (ConvertBufferType(buffer, &buffer_type)) {
     ClipboardReadAvailableTypes(buffer_type, &types, contains_filenames);
@@ -188,7 +190,7 @@
 
 bool WebClipboardImpl::readData(Buffer buffer, const WebString& type,
                                 WebString* data, WebString* metadata) {
-  Clipboard::Buffer buffer_type;
+  ui::Clipboard::Buffer buffer_type;
   if (!ConvertBufferType(buffer, &buffer_type))
     return false;
 
@@ -203,7 +205,7 @@
 }
 
 WebVector<WebString> WebClipboardImpl::readFilenames(Buffer buffer) {
-  Clipboard::Buffer buffer_type;
+  ui::Clipboard::Buffer buffer_type;
   std::vector<string16> filenames;
   if (ConvertBufferType(buffer, &buffer_type)) {
     ClipboardReadFilenames(buffer_type, &filenames);
@@ -212,16 +214,16 @@
 }
 
 bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
-                                         Clipboard::Buffer* result) {
+                                         ui::Clipboard::Buffer* result) {
   switch (buffer) {
     case BufferStandard:
-      *result = Clipboard::BUFFER_STANDARD;
+      *result = ui::Clipboard::BUFFER_STANDARD;
       break;
     case BufferDrag:
-      *result = Clipboard::BUFFER_DRAG;
+      *result = ui::Clipboard::BUFFER_DRAG;
     case BufferSelection:
 #if defined(USE_X11)
-      *result = Clipboard::BUFFER_SELECTION;
+      *result = ui::Clipboard::BUFFER_SELECTION;
       break;
 #endif
     default:
diff --git a/webkit/glue/webclipboard_impl.h b/webkit/glue/webclipboard_impl.h
index 6a83a6d..ba3e747 100644
--- a/webkit/glue/webclipboard_impl.h
+++ b/webkit/glue/webclipboard_impl.h
@@ -1,12 +1,12 @@
-// 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.
+// Copyright (c) 2011 The Chromium 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 WEBCLIPBOARD_IMPL_H_
 #define WEBCLIPBOARD_IMPL_H_
 
-#include "app/clipboard/clipboard.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebClipboard.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebClipboard.h"
+#include "ui/base/clipboard/clipboard.h"
 
 #include <string>
 
@@ -38,7 +38,10 @@
       const WebKit::WebImage&,
       const WebKit::WebURL& source_url,
       const WebKit::WebString& title);
-  virtual void writeData(const WebKit::WebDragData&);
+  virtual void writeData(
+      const WebKit::WebString& type,
+      const WebKit::WebString& data,
+      const WebKit::WebString& metadata);
 
   virtual WebKit::WebVector<WebKit::WebString> readAvailableTypes(
       Buffer, bool* contains_filenames);
@@ -47,7 +50,7 @@
   virtual WebKit::WebVector<WebKit::WebString> readFilenames(Buffer);
 
  private:
-  bool ConvertBufferType(Buffer, Clipboard::Buffer*);
+  bool ConvertBufferType(Buffer, ui::Clipboard::Buffer*);
 };
 
 }  // namespace webkit_glue
diff --git a/webkit/glue/webcursor.cc b/webkit/glue/webcursor.cc
index fb67b6b..50a0bb6 100644
--- a/webkit/glue/webcursor.cc
+++ b/webkit/glue/webcursor.cc
@@ -6,8 +6,8 @@
 
 #include "base/logging.h"
 #include "base/pickle.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebImage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
 
 using WebKit::WebCursorInfo;
 using WebKit::WebImage;
diff --git a/webkit/glue/webcursor.h b/webkit/glue/webcursor.h
index daad15f..8fb6b9f 100644
--- a/webkit/glue/webcursor.h
+++ b/webkit/glue/webcursor.h
@@ -6,9 +6,9 @@
 #define WEBKIT_GLUE_WEBCURSOR_H_
 
 #include "base/basictypes.h"
-#include "gfx/native_widget_types.h"
-#include "gfx/point.h"
-#include "gfx/size.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/size.h"
 
 #include <vector>
 
diff --git a/webkit/glue/webcursor_gtk.cc b/webkit/glue/webcursor_gtk.cc
index 1ff8316..ca3555a 100644
--- a/webkit/glue/webcursor_gtk.cc
+++ b/webkit/glue/webcursor_gtk.cc
@@ -8,8 +8,8 @@
 #include <gtk/gtk.h>
 
 #include "base/logging.h"
-#include "gfx/gtk_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
+#include "ui/gfx/gtk_util.h"
 
 using WebKit::WebCursorInfo;
 
diff --git a/webkit/glue/webcursor_mac.mm b/webkit/glue/webcursor_mac.mm
index 4c3d69a..680521d 100644
--- a/webkit/glue/webcursor_mac.mm
+++ b/webkit/glue/webcursor_mac.mm
@@ -10,9 +10,9 @@
 #include "app/mac/nsimage_cache.h"
 #include "base/logging.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebImage.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
 
 using WebKit::WebCursorInfo;
 using WebKit::WebImage;
diff --git a/webkit/glue/webcursor_unittest.cc b/webkit/glue/webcursor_unittest.cc
index f449515..eea7926 100644
--- a/webkit/glue/webcursor_unittest.cc
+++ b/webkit/glue/webcursor_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "base/pickle.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
 #include "webkit/glue/webcursor.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
 
diff --git a/webkit/glue/webcursor_win.cc b/webkit/glue/webcursor_win.cc
index 2141969..3399c7c 100644
--- a/webkit/glue/webcursor_win.cc
+++ b/webkit/glue/webcursor_win.cc
@@ -4,10 +4,10 @@
 
 #include "base/logging.h"
 #include "base/pickle.h"
-#include "gfx/gdi_util.h"
 #include "grit/webkit_resources.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
+#include "ui/gfx/gdi_util.h"
 #include "webkit/glue/webcursor.h"
 
 using WebKit::WebCursorInfo;
diff --git a/webkit/glue/webdropdata.cc b/webkit/glue/webdropdata.cc
index cda887d..02c1a4c 100644
--- a/webkit/glue/webdropdata.cc
+++ b/webkit/glue/webdropdata.cc
@@ -4,11 +4,11 @@
 
 #include "webkit/glue/webdropdata.h"
 
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDragData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
 
 using WebKit::WebData;
 using WebKit::WebDragData;
diff --git a/webkit/glue/webdropdata_win.cc b/webkit/glue/webdropdata_win.cc
index bd76090..b550eb9 100644
--- a/webkit/glue/webdropdata_win.cc
+++ b/webkit/glue/webdropdata_win.cc
@@ -8,26 +8,26 @@
 #include <shellapi.h>
 #include <shlobj.h>
 
-#include "app/clipboard/clipboard_util_win.h"
 #include "googleurl/src/gurl.h"
+#include "ui/base/clipboard/clipboard_util_win.h"
 
 // static
 void WebDropData::PopulateWebDropData(IDataObject* data_object,
                                       WebDropData* drop_data) {
   std::wstring url_str;
-  if (ClipboardUtil::GetUrl(data_object, &url_str, &drop_data->url_title,
-                            false)) {
+  if (ui::ClipboardUtil::GetUrl(data_object, &url_str, &drop_data->url_title,
+                                false)) {
     GURL test_url(url_str);
     if (test_url.is_valid())
       drop_data->url = test_url;
   }
-  ClipboardUtil::GetFilenames(data_object, &drop_data->filenames);
-  ClipboardUtil::GetPlainText(data_object, &drop_data->plain_text);
+  ui::ClipboardUtil::GetFilenames(data_object, &drop_data->filenames);
+  ui::ClipboardUtil::GetPlainText(data_object, &drop_data->plain_text);
   std::string base_url;
-  ClipboardUtil::GetHtml(data_object, &drop_data->text_html, &base_url);
+  ui::ClipboardUtil::GetHtml(data_object, &drop_data->text_html, &base_url);
   if (!base_url.empty()) {
     drop_data->html_base_url = GURL(base_url);
   }
-  ClipboardUtil::GetFileContents(data_object,
+  ui::ClipboardUtil::GetFileContents(data_object,
       &drop_data->file_description_filename, &drop_data->file_contents);
 }
diff --git a/webkit/glue/webfileutilities_impl.cc b/webkit/glue/webfileutilities_impl.cc
index 6cea225..5aeeb05 100644
--- a/webkit/glue/webfileutilities_impl.cc
+++ b/webkit/glue/webfileutilities_impl.cc
@@ -9,8 +9,8 @@
 #include "base/logging.h"
 #include "net/base/file_stream.h"
 #include "net/base/net_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebString;
diff --git a/webkit/glue/webfileutilities_impl.h b/webkit/glue/webfileutilities_impl.h
index c1ef986..14d7a42 100644
--- a/webkit/glue/webfileutilities_impl.h
+++ b/webkit/glue/webfileutilities_impl.h
@@ -6,7 +6,7 @@
 #define WEBFILEUTILITIES_IMPL_H_
 
 #include "base/platform_file.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileUtilities.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileUtilities.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/webframe_unittest.cc b/webkit/glue/webframe_unittest.cc
index 6ffaf84..abe13c3 100644
--- a/webkit/glue/webframe_unittest.cc
+++ b/webkit/glue/webframe_unittest.cc
@@ -5,11 +5,11 @@
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
 
 using WebKit::WebFrame;
diff --git a/webkit/glue/webkit_glue.cc b/webkit/glue/webkit_glue.cc
index fe3edd9..6d76c71 100644
--- a/webkit/glue/webkit_glue.cc
+++ b/webkit/glue/webkit_glue.cc
@@ -26,20 +26,20 @@
 #include "skia/ext/skia_utils_mac.h"
 #endif
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebGlyphCache.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHistoryItem.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebImage.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebGlyphCache.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #if defined(OS_WIN)
-#include "third_party/WebKit/WebKit/chromium/public/win/WebInputEventFactory.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
 #endif
 #include "webkit/glue/glue_serialize.h"
 #include "webkit/glue/user_agent.h"
@@ -240,21 +240,6 @@
                       is_current));
 }
 
-void ResetBeforeTestRun(WebView* view) {
-  WebFrame* web_frame = view->mainFrame();
-
-  // Reset the main frame name since tests always expect it to be empty.  It
-  // is normally not reset between page loads (even in IE and FF).
-  if (web_frame)
-    web_frame->setName(WebString());
-
-#if defined(OS_WIN)
-  // Reset the last click information so the clicks generated from previous
-  // test aren't inherited (otherwise can mistake single/double/triple clicks)
-  WebKit::WebInputEventFactory::resetLastClickState();
-#endif
-}
-
 #ifndef NDEBUG
 // The log macro was having problems due to collisions with WTF, so we just
 // code here what that would have inlined.
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index e64f667..4a3d03f 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -6,7 +6,7 @@
   'variables': {
     'conditions': [
       ['inside_chromium_build==0', {
-        'webkit_src_dir': '../../../..',
+        'webkit_src_dir': '../../../../..',
       },{
         'webkit_src_dir': '../../third_party/WebKit',
       }],
@@ -45,7 +45,7 @@
         {
           'action_name': 'webkit_chromium_resources',
           'variables': {
-            'input_path': '<(webkit_src_dir)/WebKit/chromium/WebKit.grd',
+            'input_path': '<(webkit_src_dir)/Source/WebKit/chromium/WebKit.grd',
           },
           'inputs': [
             '<!@(<(grit_info_cmd) --inputs <(input_path))',
@@ -120,13 +120,23 @@
         {
           'action_name': 'webkit_version',
           'inputs': [
-            '../build/webkit_version.py',
-            '<(webkit_src_dir)/Source/WebCore/Configurations/Version.xcconfig',
+            '<(script)',
+            '<(webkit_src_dir)<(version_file)',
+            '../../build/util/lastchange.py',  # Used by the script.
           ],
           'outputs': [
             '<(INTERMEDIATE_DIR)/webkit_version.h',
           ],
-          'action': ['python', '<@(_inputs)', '<(INTERMEDIATE_DIR)'],
+          'action': ['python', '<(script)', '<(webkit_src_dir)',
+                     '<(version_file)', '<(INTERMEDIATE_DIR)'],
+          'variables': {
+            'script': '../build/webkit_version.py',
+            # version_file is a relative path from |webkit_src_dir| to
+            # the version file.  But gyp will eat the variable unless
+            # it looks like an absolute path, so write it like one and
+            # then use it carefully above.
+            'version_file': '/Source/WebCore/Configurations/Version.xcconfig',
+          },
         },
       ],
       'include_dirs': [
@@ -182,7 +192,6 @@
         '../plugins/npapi/gtk_plugin_container_manager.h',
         '../plugins/npapi/npapi_extension_thunk.cc',
         '../plugins/npapi/npapi_extension_thunk.h',
-        '../plugins/npapi/nphostapi.h',
         '../plugins/npapi/plugin_constants_win.cc',
         '../plugins/npapi/plugin_constants_win.h',
         '../plugins/npapi/plugin_group.cc',
@@ -212,7 +221,6 @@
         '../plugins/npapi/plugin_string_stream.h',
         '../plugins/npapi/plugin_web_event_converter_mac.h',
         '../plugins/npapi/plugin_web_event_converter_mac.mm',
-        '../plugins/npapi/ppb_private.h',
         '../plugins/npapi/quickdraw_drawing_manager_mac.cc',
         '../plugins/npapi/quickdraw_drawing_manager_mac.h',
         '../plugins/npapi/webplugin.cc',
@@ -288,6 +296,8 @@
         '../plugins/ppapi/ppb_flash_impl.cc',
         '../plugins/ppapi/ppb_flash_impl.h',
         '../plugins/ppapi/ppb_flash_impl_linux.cc',
+        '../plugins/ppapi/ppb_flash_menu_impl.cc',
+        '../plugins/ppapi/ppb_flash_menu_impl.h',
         '../plugins/ppapi/ppb_font_impl.cc',
         '../plugins/ppapi/ppb_font_impl.h',
         '../plugins/ppapi/ppb_gles_chromium_texture_mapping_impl.cc',
@@ -302,7 +312,6 @@
         '../plugins/ppapi/ppb_nacl_private_impl.h',
         '../plugins/ppapi/ppb_opengles_impl.cc',
         '../plugins/ppapi/ppb_opengles_impl.h',
-        '../plugins/ppapi/ppb_pdf.h',
         '../plugins/ppapi/ppb_pdf_impl.cc',
         '../plugins/ppapi/ppb_pdf_impl.h',
         '../plugins/ppapi/ppb_scrollbar_impl.cc',
@@ -415,6 +424,7 @@
         'webkitclient_impl.h',
         'webmediaplayer_impl.h',
         'webmediaplayer_impl.cc',
+        'webmenuitem.cc',
         'webmenuitem.h',
         'webmenurunner_mac.h',
         'webmenurunner_mac.mm',
@@ -473,7 +483,7 @@
           'sources/': [['exclude', '_mac\\.(cc|mm)$']],
           'sources!': [
             'webthemeengine_impl_mac.cc',
-          ],          
+          ],
         }, {  # else: OS=="mac"
           'sources/': [['exclude', 'plugin_(lib|list)_posix\\.cc$']],
           'link_settings': {
@@ -513,11 +523,11 @@
           'conditions': [
             ['inside_chromium_build==1 and component=="shared_library"', {
               'dependencies': [
-                '<(DEPTH)/third_party/WebKit/WebKit/chromium/WebKit.gyp:webkit',
+                '<(DEPTH)/third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:webkit',
                 '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
                ],
                'export_dependent_settings': [
-                 '<(DEPTH)/third_party/WebKit/WebKit/chromium/WebKit.gyp:webkit',
+                 '<(DEPTH)/third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:webkit',
                  '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
                ],
             }],
@@ -531,4 +541,41 @@
       ],
     },
   ],
+  'conditions': [
+    ['use_third_party_translations==1', {
+      'targets': [
+        {
+          'target_name': 'inspector_strings',
+          'type': 'none',
+          'variables': {
+            'grit_out_dir': '<(PRODUCT_DIR)/resources/inspector/l10n',
+          },
+          'actions': [
+            {
+              'action_name': 'inspector_strings',
+              'variables': {
+                'input_path': './inspector_strings.grd',
+              },
+              'inputs': [
+                '<!@(<(grit_info_cmd) --inputs <(input_path))',
+              ],
+              'outputs': [
+                '<!@(<(grit_info_cmd) --outputs \'<(grit_out_dir)\' <(input_path))',
+              ],
+              'action': ['<@(grit_cmd)',
+                         '-i', '<(input_path)', 'build',
+                         '-o', '<(grit_out_dir)',
+                         '<@(grit_defines)'],
+              'message': 'Generating resources from <(input_path)',
+            },
+          ],
+          'conditions': [
+            ['OS=="win"', {
+              'dependencies': ['<(DEPTH)/build/win/system.gyp:cygwin'],
+            }],
+          ],
+        },
+      ],
+    }],
+  ],
 }
diff --git a/webkit/glue/webkit_glue.h b/webkit/glue/webkit_glue.h
index 38ea659..5df2aea 100644
--- a/webkit/glue/webkit_glue.h
+++ b/webkit/glue/webkit_glue.h
@@ -14,12 +14,12 @@
 #include <string>
 #include <vector>
 
-#include "app/clipboard/clipboard.h"
 #include "base/file_path.h"
 #include "base/platform_file.h"
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFileError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileError.h"
+#include "ui/base/clipboard/clipboard.h"
 
 class GURL;
 class SkBitmap;
@@ -90,9 +90,6 @@
 string16 DumpHistoryState(const std::string& history_state, int indent,
                           bool is_current);
 
-// Cleans up state left over from the previous test run.
-void ResetBeforeTestRun(WebKit::WebView* view);
-
 // Returns the WebKit version (major.minor).
 std::string GetWebKitVersion();
 
@@ -189,32 +186,33 @@
 // Glue to access the clipboard.
 
 // Get a clipboard that can be used to construct a ScopedClipboardWriterGlue.
-Clipboard* ClipboardGetClipboard();
+ui::Clipboard* ClipboardGetClipboard();
 
 // Tests whether the clipboard contains a certain format
-bool ClipboardIsFormatAvailable(const Clipboard::FormatType& format,
-                                Clipboard::Buffer buffer);
+bool ClipboardIsFormatAvailable(const ui::Clipboard::FormatType& format,
+                                ui::Clipboard::Buffer buffer);
 
 // Reads UNICODE text from the clipboard, if available.
-void ClipboardReadText(Clipboard::Buffer buffer, string16* result);
+void ClipboardReadText(ui::Clipboard::Buffer buffer, string16* result);
 
 // Reads ASCII text from the clipboard, if available.
-void ClipboardReadAsciiText(Clipboard::Buffer buffer, std::string* result);
+void ClipboardReadAsciiText(ui::Clipboard::Buffer buffer, std::string* result);
 
 // Reads HTML from the clipboard, if available.
-void ClipboardReadHTML(Clipboard::Buffer buffer, string16* markup, GURL* url);
+void ClipboardReadHTML(ui::Clipboard::Buffer buffer, string16* markup,
+                       GURL* url);
 
 // Reads the available types from the clipboard, if available.
-bool ClipboardReadAvailableTypes(Clipboard::Buffer buffer,
+bool ClipboardReadAvailableTypes(ui::Clipboard::Buffer buffer,
                                  std::vector<string16>* types,
                                  bool* contains_filenames);
 
 // Reads one type of data from the clipboard, if available.
-bool ClipboardReadData(Clipboard::Buffer buffer, const string16& type,
+bool ClipboardReadData(ui::Clipboard::Buffer buffer, const string16& type,
                        string16* data, string16* metadata);
 
 // Reads filenames from the clipboard, if available.
-bool ClipboardReadFilenames(Clipboard::Buffer buffer,
+bool ClipboardReadFilenames(ui::Clipboard::Buffer buffer,
                             std::vector<string16>* filenames);
 
 // Gets the directory where the application data and libraries exist.  This
diff --git a/webkit/glue/webkit_resources.grd b/webkit/glue/webkit_resources.grd
index 94d4286..a11dae9 100644
--- a/webkit/glue/webkit_resources.grd
+++ b/webkit/glue/webkit_resources.grd
@@ -64,7 +64,7 @@
       <include name="IDR_PDF_BUTTON_ZOOMIN_PRESSED" file="resources\pdf_button_zoomin_pressed.png" type="BINDATA" />
       <include name="IDR_PDF_BUTTON_ZOOMOUT" file="resources\pdf_button_zoomout.png" type="BINDATA" />
       <include name="IDR_PDF_BUTTON_ZOOMOUT_HOVER" file="resources\pdf_button_zoomout_hover.png" type="BINDATA" />
-      <include name="IDR_PDF_BUTTON_ZOOMOUT_PRESSED" file="resources\pdf_button_zoomout_pressed.png" type="BINDATA" />      
+      <include name="IDR_PDF_BUTTON_ZOOMOUT_PRESSED" file="resources\pdf_button_zoomout_pressed.png" type="BINDATA" />
       <include name="IDR_PDF_THUMBNAIL_0" file="resources\pdf_thumbnail_0.png" type="BINDATA" />
       <include name="IDR_PDF_THUMBNAIL_1" file="resources\pdf_thumbnail_1.png" type="BINDATA" />
       <include name="IDR_PDF_THUMBNAIL_2" file="resources\pdf_thumbnail_2.png" type="BINDATA" />
@@ -76,23 +76,6 @@
       <include name="IDR_PDF_THUMBNAIL_8" file="resources\pdf_thumbnail_8.png" type="BINDATA" />
       <include name="IDR_PDF_THUMBNAIL_9" file="resources\pdf_thumbnail_9.png" type="BINDATA" />
       <include name="IDR_PDF_THUMBNAIL_NUM_BACKGROUND" file="resources\pdf_thumbnail_num_background.png" type="BINDATA" />
-
-      <if expr="os == 'linux2' or os.find('bsd') != -1 or os == 'sunos5'">
-        <include name="IDR_LINUX_CHECKBOX_DISABLED_INDETERMINATE" file="resources\linux-checkbox-disabled-indeterminate.png" type="BINDATA" />
-        <include name="IDR_LINUX_CHECKBOX_DISABLED_OFF" file="resources\linux-checkbox-disabled-off.png" type="BINDATA" />
-        <include name="IDR_LINUX_CHECKBOX_DISABLED_ON" file="resources\linux-checkbox-disabled-on.png" type="BINDATA" />
-        <include name="IDR_LINUX_CHECKBOX_INDETERMINATE" file="resources\linux-checkbox-indeterminate.png" type="BINDATA" />
-        <include name="IDR_LINUX_CHECKBOX_OFF" file="resources\linux-checkbox-off.png" type="BINDATA" />
-        <include name="IDR_LINUX_CHECKBOX_ON" file="resources\linux-checkbox-on.png" type="BINDATA" />
-        <include name="IDR_LINUX_RADIO_DISABLED_OFF" file="resources\linux-radio-disabled-off.png" type="BINDATA" />
-        <include name="IDR_LINUX_RADIO_DISABLED_ON" file="resources\linux-radio-disabled-on.png" type="BINDATA" />
-        <include name="IDR_LINUX_RADIO_OFF" file="resources\linux-radio-off.png" type="BINDATA" />
-        <include name="IDR_LINUX_RADIO_ON" file="resources\linux-radio-on.png" type="BINDATA" />
-        <include name="IDR_PROGRESS_BAR" file="resources\linux-progress-bar.png" type="BINDATA" />
-        <include name="IDR_PROGRESS_BORDER_LEFT" file="resources\linux-progress-border-left.png" type="BINDATA" />
-        <include name="IDR_PROGRESS_BORDER_RIGHT" file="resources\linux-progress-border-right.png" type="BINDATA" />
-        <include name="IDR_PROGRESS_VALUE" file="resources\linux-progress-value.png" type="BINDATA" />
-      </if>
     </includes>
   </release>
 </grit>
diff --git a/webkit/glue/webkit_strings.grd b/webkit/glue/webkit_strings.grd
index 651acf0..ae88dc9 100644
--- a/webkit/glue/webkit_strings.grd
+++ b/webkit/glue/webkit_strings.grd
@@ -102,6 +102,9 @@
 
     <output filename="webkit_strings_am.pak" type="data_package" lang="am" />
     <output filename="webkit_strings_ar.pak" type="data_package" lang="ar" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="webkit_strings_ast.pak" type="data_package" lang="ast" />
+    </if>
     <output filename="webkit_strings_bg.pak" type="data_package" lang="bg" />
     <output filename="webkit_strings_bn.pak" type="data_package" lang="bn" />
     <output filename="webkit_strings_ca.pak" type="data_package" lang="ca" />
@@ -114,10 +117,16 @@
     <output filename="webkit_strings_es.pak" type="data_package" lang="es" />
     <output filename="webkit_strings_es-419.pak" type="data_package" lang="es-419" />
     <output filename="webkit_strings_et.pak" type="data_package" lang="et" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="webkit_strings_eu.pak" type="data_package" lang="eu" />
+    </if>
     <output filename="webkit_strings_fa.pak" type="data_package" lang="fa" />
     <output filename="webkit_strings_fi.pak" type="data_package" lang="fi" />
     <output filename="webkit_strings_fil.pak" type="data_package" lang="fil" />
     <output filename="webkit_strings_fr.pak" type="data_package" lang="fr" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="webkit_strings_gl.pak" type="data_package" lang="gl" />
+    </if>
     <output filename="webkit_strings_gu.pak" type="data_package" lang="gu" />
     <output filename="webkit_strings_he.pak" type="data_package" lang="he" />
     <output filename="webkit_strings_hi.pak" type="data_package" lang="hi" />
@@ -126,8 +135,14 @@
     <output filename="webkit_strings_id.pak" type="data_package" lang="id" />
     <output filename="webkit_strings_it.pak" type="data_package" lang="it" />
     <output filename="webkit_strings_ja.pak" type="data_package" lang="ja" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="webkit_strings_ka.pak" type="data_package" lang="ka" />
+    </if>
     <output filename="webkit_strings_kn.pak" type="data_package" lang="kn" />
     <output filename="webkit_strings_ko.pak" type="data_package" lang="ko" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="webkit_strings_ku.pak" type="data_package" lang="ku" />
+    </if>
     <output filename="webkit_strings_lt.pak" type="data_package" lang="lt" />
     <output filename="webkit_strings_lv.pak" type="data_package" lang="lv" />
     <output filename="webkit_strings_ml.pak" type="data_package" lang="ml" />
@@ -150,6 +165,9 @@
     <output filename="webkit_strings_te.pak" type="data_package" lang="te" />
     <output filename="webkit_strings_th.pak" type="data_package" lang="th" />
     <output filename="webkit_strings_tr.pak" type="data_package" lang="tr" />
+    <if expr="pp_ifdef('use_third_party_translations')">
+      <output filename="webkit_strings_ug.pak" type="data_package" lang="ug" />
+    </if>
     <output filename="webkit_strings_uk.pak" type="data_package" lang="uk" />
     <output filename="webkit_strings_vi.pak" type="data_package" lang="vi" />
     <output filename="webkit_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
@@ -158,6 +176,7 @@
   <translations>
     <file path="resources/webkit_strings_am.xtb" lang="am" />
     <file path="resources/webkit_strings_ar.xtb" lang="ar" />
+    <file path="../../third_party/launchpad_translations/webkit_strings_ast.xtb" lang="ast" />
     <file path="resources/webkit_strings_bg.xtb" lang="bg" />
     <file path="resources/webkit_strings_bn.xtb" lang="bn" />
     <file path="resources/webkit_strings_ca.xtb" lang="ca" />
@@ -169,10 +188,12 @@
     <file path="resources/webkit_strings_es.xtb" lang="es" />
     <file path="resources/webkit_strings_es-419.xtb" lang="es-419" />
     <file path="resources/webkit_strings_et.xtb" lang="et" />
+    <file path="../../third_party/launchpad_translations/webkit_strings_eu.xtb" lang="eu" />
     <file path="resources/webkit_strings_fa.xtb" lang="fa" />
     <file path="resources/webkit_strings_fi.xtb" lang="fi" />
     <file path="resources/webkit_strings_fil.xtb" lang="fil" />
     <file path="resources/webkit_strings_fr.xtb" lang="fr" />
+    <file path="../../third_party/launchpad_translations/webkit_strings_gl.xtb" lang="gl" />
     <file path="resources/webkit_strings_gu.xtb" lang="gu" />
     <file path="resources/webkit_strings_hi.xtb" lang="hi" />
     <file path="resources/webkit_strings_hr.xtb" lang="hr" />
@@ -184,6 +205,7 @@
     <file path="resources/webkit_strings_ja.xtb" lang="ja" />
     <file path="resources/webkit_strings_kn.xtb" lang="kn" />
     <file path="resources/webkit_strings_ko.xtb" lang="ko" />
+    <file path="../../third_party/launchpad_translations/webkit_strings_ku.xtb" lang="ku" />
     <file path="resources/webkit_strings_lt.xtb" lang="lt" />
     <file path="resources/webkit_strings_lv.xtb" lang="lv" />
     <file path="resources/webkit_strings_ml.xtb" lang="ml" />
@@ -204,6 +226,7 @@
     <file path="resources/webkit_strings_te.xtb" lang="te" />
     <file path="resources/webkit_strings_th.xtb" lang="th" />
     <file path="resources/webkit_strings_tr.xtb" lang="tr" />
+    <file path="../../third_party/launchpad_translations/webkit_strings_ug.xtb" lang="ug" />
     <file path="resources/webkit_strings_uk.xtb" lang="uk" />
     <file path="resources/webkit_strings_vi.xtb" lang="vi" />
     <file path="resources/webkit_strings_zh-CN.xtb" lang="zh-CN" />
diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc
index faf2926..701d5c3 100644
--- a/webkit/glue/webkitclient_impl.cc
+++ b/webkit/glue/webkitclient_impl.cc
@@ -13,7 +13,6 @@
 #include <vector>
 
 #include "base/debug/trace_event.h"
-#include "base/lock.h"
 #include "base/message_loop.h"
 #include "base/metrics/stats_counters.h"
 #include "base/metrics/histogram.h"
@@ -22,18 +21,20 @@
 #include "base/singleton.h"
 #include "base/string_number_conversions.h"
 #include "base/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
+#include "grit/webkit_chromium_resources.h"
 #include "grit/webkit_resources.h"
 #include "grit/webkit_strings.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebCookie.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrameClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPluginListBuilder.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCookie.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginListBuilder.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
 #include "webkit/glue/media/audio_decoder.h"
 #include "webkit/plugins/npapi/plugin_instance.h"
 #include "webkit/plugins/npapi/webplugininfo.h"
@@ -78,7 +79,7 @@
   // Returns true if the cached value is fresh.
   // Returns false if the cached value is stale, or if |cached_value| is NULL.
   bool IsCachedValueValid(size_t* cached_value) {
-    AutoLock scoped_lock(lock_);
+    base::AutoLock scoped_lock(lock_);
     if (!cached_value)
       return false;
     if (base::Time::Now() - last_updated_time_ > cache_valid_time_)
@@ -89,7 +90,7 @@
 
   // Setter for |memory_value_|, refreshes |last_updated_time_|.
   void SetMemoryValue(const size_t value) {
-    AutoLock scoped_lock(lock_);
+    base::AutoLock scoped_lock(lock_);
     memory_value_ = value;
     last_updated_time_ = base::Time::Now();
   }
@@ -104,7 +105,7 @@
   // The last time the cached value was updated.
   base::Time last_updated_time_;
 
-  Lock lock_;
+  base::Lock lock_;
 };
 
 }  // anonymous namespace
@@ -291,6 +292,59 @@
   TRACE_EVENT_END(name, id, extra);
 }
 
+namespace {
+
+WebData loadAudioSpatializationResource(const char* name) {
+#ifdef IDR_AUDIO_SPATIALIZATION_T000_P000
+  const size_t kExpectedSpatializationNameLength = 31;
+  if (strlen(name) != kExpectedSpatializationNameLength) {
+    return WebData();
+  }
+
+  // Extract the azimuth and elevation from the resource name.
+  int azimuth = 0;
+  int elevation = 0;
+  int values_parsed =
+      sscanf(name, "IRC_Composite_C_R0195_T%3d_P%3d", &azimuth, &elevation);
+  if (values_parsed != 2) {
+    return WebData();
+  }
+
+  // The resource index values go through the elevations first, then azimuths.
+  const int kAngleSpacing = 15;
+
+  // 0 <= elevation <= 90 (or 315 <= elevation <= 345)
+  // in increments of 15 degrees.
+  int elevation_index =
+      elevation <= 90 ? elevation / kAngleSpacing :
+      7 + (elevation - 315) / kAngleSpacing;
+  bool is_elevation_index_good = 0 <= elevation_index && elevation_index < 10;
+
+  // 0 <= azimuth < 360 in increments of 15 degrees.
+  int azimuth_index = azimuth / kAngleSpacing;
+  bool is_azimuth_index_good = 0 <= azimuth_index && azimuth_index < 24;
+
+  const int kNumberOfElevations = 10;
+  const int kNumberOfAudioResources = 240;
+  int resource_index = kNumberOfElevations * azimuth_index + elevation_index;
+  bool is_resource_index_good = 0 <= resource_index &&
+      resource_index < kNumberOfAudioResources;
+
+  if (is_azimuth_index_good && is_elevation_index_good &&
+      is_resource_index_good) {
+    const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000;
+    base::StringPiece resource =
+        GetDataResource(kFirstAudioResourceIndex + resource_index);
+    return WebData(resource.data(), resource.size());
+  }
+#endif  // IDR_AUDIO_SPATIALIZATION_T000_P000
+
+  NOTREACHED();
+  return WebData();
+}
+
+}  // namespace
+
 WebData WebKitClientImpl::loadResource(const char* name) {
   struct {
     const char* name;
@@ -323,29 +377,17 @@
     { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD },
     { "soloCC", IDR_AUTOFILL_CC_SOLO },
     { "visaCC", IDR_AUTOFILL_CC_VISA },
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-    // TODO(port): rename these to "skia" instead of "Linux".
-    { "linuxCheckboxDisabledIndeterminate",
-        IDR_LINUX_CHECKBOX_DISABLED_INDETERMINATE },
-    { "linuxCheckboxDisabledOff", IDR_LINUX_CHECKBOX_DISABLED_OFF },
-    { "linuxCheckboxDisabledOn", IDR_LINUX_CHECKBOX_DISABLED_ON },
-    { "linuxCheckboxIndeterminate", IDR_LINUX_CHECKBOX_INDETERMINATE },
-    { "linuxCheckboxOff", IDR_LINUX_CHECKBOX_OFF },
-    { "linuxCheckboxOn", IDR_LINUX_CHECKBOX_ON },
-    { "linuxRadioDisabledOff", IDR_LINUX_RADIO_DISABLED_OFF },
-    { "linuxRadioDisabledOn", IDR_LINUX_RADIO_DISABLED_ON },
-    { "linuxRadioOff", IDR_LINUX_RADIO_OFF },
-    { "linuxRadioOn", IDR_LINUX_RADIO_ON },
-    { "linuxProgressBar", IDR_PROGRESS_BAR },
-    { "linuxProgressBorderLeft", IDR_PROGRESS_BORDER_LEFT },
-    { "linuxProgressBorderRight", IDR_PROGRESS_BORDER_RIGHT },
-    { "linuxProgressValue", IDR_PROGRESS_VALUE },
-#endif
   };
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i) {
-    if (!strcmp(name, resources[i].name)) {
-      base::StringPiece resource = GetDataResource(resources[i].id);
-      return WebData(resource.data(), resource.size());
+
+  // Check the name prefix to see if it's an audio resource.
+  if (StartsWithASCII(name, "IRC_Composite", true)) {
+    return loadAudioSpatializationResource(name);
+  } else {
+    for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i) {
+      if (!strcmp(name, resources[i].name)) {
+        base::StringPiece resource = GetDataResource(resources[i].id);
+        return WebData(resource.data(), resource.size());
+      }
     }
   }
   // TODO(jhawkins): Restore this NOTREACHED once WK stops sending in empty
diff --git a/webkit/glue/webkitclient_impl.h b/webkit/glue/webkitclient_impl.h
index 42b436d..302a99f 100644
--- a/webkit/glue/webkitclient_impl.h
+++ b/webkit/glue/webkitclient_impl.h
@@ -7,7 +7,7 @@
 
 #include "base/platform_file.h"
 #include "base/timer.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
 #if defined(OS_WIN)
 #include "webkit/glue/webthemeengine_impl_win.h"
 #elif defined(OS_LINUX)
diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc
index 005c7cf..9d51910 100644
--- a/webkit/glue/webmediaplayer_impl.cc
+++ b/webkit/glue/webmediaplayer_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,10 +19,10 @@
 #include "media/filters/ffmpeg_video_decoder.h"
 #include "media/filters/null_audio_renderer.h"
 #include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVideoFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
 #include "webkit/glue/media/buffered_data_source.h"
 #include "webkit/glue/media/simple_data_source.h"
 #include "webkit/glue/media/video_renderer_impl.h"
@@ -59,6 +59,25 @@
 const float kMinRate = 0.0625f;
 const float kMaxRate = 16.0f;
 
+// Platform independent method for converting and rounding floating point
+// seconds to an int64 timestamp.
+//
+// Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details.
+base::TimeDelta ConvertSecondsToTimestamp(float seconds) {
+  float microseconds = seconds * base::Time::kMicrosecondsPerSecond;
+  float integer = ceilf(microseconds);
+  float difference = integer - microseconds;
+
+  // Round down if difference is large enough.
+  if ((microseconds > 0 && difference > 0.5f) ||
+      (microseconds <= 0 && difference >= 0.5f)) {
+    integer -= 1.0f;
+  }
+
+  // Now we can safely cast to int64 microseconds.
+  return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer));
+}
+
 }  // namespace
 
 namespace webkit_glue {
@@ -80,7 +99,7 @@
 }
 
 void WebMediaPlayerImpl::Proxy::Repaint() {
-  AutoLock auto_lock(lock_);
+  base::AutoLock auto_lock(lock_);
   if (outstanding_repaints_ < kMaxOutstandingRepaints) {
     ++outstanding_repaints_;
 
@@ -164,7 +183,7 @@
 void WebMediaPlayerImpl::Proxy::RepaintTask() {
   DCHECK(MessageLoop::current() == render_loop_);
   {
-    AutoLock auto_lock(lock_);
+    base::AutoLock auto_lock(lock_);
     --outstanding_repaints_;
     DCHECK_GE(outstanding_repaints_, 0);
   }
@@ -225,13 +244,14 @@
 
 WebMediaPlayerImpl::WebMediaPlayerImpl(
     WebKit::WebMediaPlayerClient* client,
-    media::FilterCollection* collection)
+    media::FilterCollection* collection,
+    media::MessageLoopFactory* message_loop_factory)
     : network_state_(WebKit::WebMediaPlayer::Empty),
       ready_state_(WebKit::WebMediaPlayer::HaveNothing),
       main_loop_(NULL),
       filter_collection_(collection),
       pipeline_(NULL),
-      pipeline_thread_("PipelineThread"),
+      message_loop_factory_(message_loop_factory),
       paused_(true),
       seeking_(false),
       playback_rate_(0.0f),
@@ -247,13 +267,14 @@
     WebKit::WebFrame* frame,
     bool use_simple_data_source,
     scoped_refptr<WebVideoRenderer> web_video_renderer) {
-  // Create the pipeline and its thread.
-  if (!pipeline_thread_.Start()) {
+  MessageLoop* pipeline_message_loop =
+      message_loop_factory_->GetMessageLoop("PipelineThread");
+  if (!pipeline_message_loop) {
     NOTREACHED() << "Could not start PipelineThread";
     return false;
   }
 
-  pipeline_ = new media::PipelineImpl(pipeline_thread_.message_loop());
+  pipeline_ = new media::PipelineImpl(pipeline_message_loop);
 
   // Also we want to be notified of |main_loop_| destruction.
   main_loop_->AddDestructionObserver(this);
@@ -290,9 +311,12 @@
   }
 
   // Add in the default filter factories.
-  filter_collection_->AddDemuxer(new media::FFmpegDemuxer());
-  filter_collection_->AddAudioDecoder(new media::FFmpegAudioDecoder());
-  filter_collection_->AddVideoDecoder(new media::FFmpegVideoDecoder(NULL));
+  filter_collection_->AddDemuxer(new media::FFmpegDemuxer(
+      message_loop_factory_->GetMessageLoop("DemuxThread")));
+  filter_collection_->AddAudioDecoder(new media::FFmpegAudioDecoder(
+      message_loop_factory_->GetMessageLoop("AudioDecoderThread")));
+  filter_collection_->AddVideoDecoder(new media::FFmpegVideoDecoder(
+      message_loop_factory_->GetMessageLoop("VideoDecoderThread"), NULL));
   filter_collection_->AddAudioRenderer(new media::NullAudioRenderer());
 
   return true;
@@ -369,10 +393,7 @@
     return;
   }
 
-  // Try to preserve as much accuracy as possible.
-  float microseconds = seconds * base::Time::kMicrosecondsPerSecond;
-  base::TimeDelta seek_time =
-      base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds));
+  base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
 
   // Update our paused time.
   if (paused_) {
@@ -794,9 +815,10 @@
     pipeline_->Stop(NewCallback(this,
         &WebMediaPlayerImpl::PipelineStoppedCallback));
     pipeline_stopped_.Wait();
-    pipeline_thread_.Stop();
   }
 
+  message_loop_factory_.reset();
+
   // And then detach the proxy, it may live on the render thread for a little
   // longer until all the tasks are finished.
   if (proxy_) {
diff --git a/webkit/glue/webmediaplayer_impl.h b/webkit/glue/webmediaplayer_impl.h
index abb1c60..cfc200f 100644
--- a/webkit/glue/webmediaplayer_impl.h
+++ b/webkit/glue/webmediaplayer_impl.h
@@ -53,19 +53,20 @@
 #ifndef WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_
 #define WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_
 
-#include "base/lock.h"
 #include "base/message_loop.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/threading/thread.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
 #include "media/base/filters.h"
+#include "media/base/message_loop_factory.h"
 #include "media/base/pipeline.h"
 #include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayer.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayerClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayer.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
 
 class GURL;
 
@@ -148,7 +149,7 @@
     scoped_refptr<WebDataSource> data_source_;
     scoped_refptr<WebVideoRenderer> video_renderer_;
 
-    Lock lock_;
+    base::Lock lock_;
     int outstanding_repaints_;
   };
 
@@ -175,7 +176,8 @@
   //
   // Callers must call |Initialize()| before they can use the object.
   WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client,
-                     media::FilterCollection* collection);
+                     media::FilterCollection* collection,
+                     media::MessageLoopFactory* message_loop_factory);
   virtual ~WebMediaPlayerImpl();
 
   // Finalizes initialization of the object.
@@ -288,7 +290,8 @@
 
   // The actual pipeline and the thread it runs on.
   scoped_refptr<media::Pipeline> pipeline_;
-  base::Thread pipeline_thread_;
+
+  scoped_ptr<media::MessageLoopFactory> message_loop_factory_;
 
   // Playback state.
   //
diff --git a/webkit/glue/webmenuitem.h b/webkit/glue/webmenuitem.h
index 4b0fdc3..685033e 100644
--- a/webkit/glue/webmenuitem.h
+++ b/webkit/glue/webmenuitem.h
@@ -1,12 +1,14 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef WEBMENUITEM_H_
 #define WEBMENUITEM_H_
 
+#include <vector>
+
 #include "base/string16.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebMenuItemInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h"
 
 // Container for information about entries in an HTML select popup menu and
 // custom entries of the context menu.
@@ -15,25 +17,23 @@
     OPTION    = WebKit::WebMenuItemInfo::Option,
     CHECKABLE_OPTION = WebKit::WebMenuItemInfo::CheckableOption,
     GROUP     = WebKit::WebMenuItemInfo::Group,
-    SEPARATOR = WebKit::WebMenuItemInfo::Separator
+    SEPARATOR = WebKit::WebMenuItemInfo::Separator,
+    SUBMENU  // This is currently only used by Pepper, not by WebKit.
   };
 
+  WebMenuItem();
+  WebMenuItem(const WebKit::WebMenuItemInfo& item);
+  WebMenuItem(const WebMenuItem& item);
+  ~WebMenuItem();
+
   string16 label;
   Type type;
   unsigned action;
+  bool rtl;
+  bool has_directional_override;
   bool enabled;
   bool checked;
-
-  WebMenuItem() : type(OPTION), action(0), enabled(false), checked(false) {
-  }
-
-  WebMenuItem(const WebKit::WebMenuItemInfo& item)
-      : label(item.label),
-        type(static_cast<Type>(item.type)),
-        action(item.action),
-        enabled(item.enabled),
-        checked(item.checked) {
-  }
+  std::vector<WebMenuItem> submenu;
 };
 
 #endif  // WEBMENUITEM_H_
diff --git a/webkit/glue/webmenurunner_mac.h b/webkit/glue/webmenurunner_mac.h
index c56eeeb..eccb1ef 100644
--- a/webkit/glue/webmenurunner_mac.h
+++ b/webkit/glue/webmenurunner_mac.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -33,6 +33,9 @@
 
   // The font size being used for the menu.
   CGFloat fontSize_;
+
+  // Whether the menu should be displayed right-aligned.
+  BOOL rightAligned_;
 }
 
 // Initializes the MenuDelegate with a list of items sent from WebKit.
diff --git a/webkit/glue/webmenurunner_mac.mm b/webkit/glue/webmenurunner_mac.mm
index 3e1376a..7dce0a6 100644
--- a/webkit/glue/webmenurunner_mac.mm
+++ b/webkit/glue/webmenurunner_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,28 +6,31 @@
 
 #include "base/sys_string_conversions.h"
 
-namespace {
-
-const CGFloat kPopupXOffset = -10.0f;
-BOOL gNewNSMenuAPI;
-
-}  // namespace
-
 #if !defined(MAC_OS_X_VERSION_10_6) || \
     MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
-@interface NSMenu (SnowLeopardSDKDeclarations)
-- (BOOL)popUpMenuPositioningItem:(NSMenuItem *)item
-                      atLocation:(NSPoint)location
-                          inView:(NSView *)view;
-- (void)setFont:(NSFont *)font;
+enum {
+  NSUserInterfaceLayoutDirectionLeftToRight = 0,
+  NSUserInterfaceLayoutDirectionRightToLeft = 1
+};
+typedef NSInteger NSUserInterfaceLayoutDirection;
+
+@interface NSCell (SnowLeopardSDKDeclarations)
+- (void)setUserInterfaceLayoutDirection:
+    (NSUserInterfaceLayoutDirection)layoutDirection;
 @end
+
+enum {
+  NSTextWritingDirectionEmbedding = (0 << 1),
+  NSTextWritingDirectionOverride = (1 << 1)
+};
+
+static NSString* NSWritingDirectionAttributeName = @"NSWritingDirection";
 #endif
 
 @interface WebMenuRunner (PrivateAPI)
 
 // Worker function used during initialization.
-- (void)addItem:(const WebMenuItem&)item
- withAttributes:(NSDictionary*)attrs;
+- (void)addItem:(const WebMenuItem&)item;
 
 // A callback for the menu controller object to call when an item is selected
 // from the menu. This is not called if the menu is dismissed without a
@@ -41,39 +44,19 @@
 - (id)initWithItems:(const std::vector<WebMenuItem>&)items
            fontSize:(CGFloat)fontSize
        rightAligned:(BOOL)rightAligned {
-  static BOOL newNSMenuAPIInitialized = NO;
-  if (!newNSMenuAPIInitialized) {
-    newNSMenuAPIInitialized = YES;
-    gNewNSMenuAPI = [NSMenu instancesRespondToSelector:
-        @selector(popUpMenuPositioningItem:atLocation:inView:)] &&
-        [NSMenu instancesRespondToSelector:@selector(setFont:)];
-  }
-
   if ((self = [super init])) {
     menu_.reset([[NSMenu alloc] initWithTitle:@""]);
-    if (gNewNSMenuAPI)
-      [menu_ setFont:[NSFont menuFontOfSize:fontSize]];
     [menu_ setAutoenablesItems:NO];
     index_ = -1;
     fontSize_ = fontSize;
-    scoped_nsobject<NSDictionary> attrs;
-    if (rightAligned) {
-      // NB: Right-aligning menu items in this manner is known to not work in
-      // Mac OS X 10.5.
-      scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
-          [[NSMutableParagraphStyle alloc] init]);
-      [paragraphStyle setAlignment:NSRightTextAlignment];
-      attrs.reset([[NSDictionary alloc] initWithObjectsAndKeys:
-          paragraphStyle, NSParagraphStyleAttributeName, nil]);
-    }
+    rightAligned_ = rightAligned;
     for (size_t i = 0; i < items.size(); ++i)
-      [self addItem:items[i] withAttributes:attrs];
+      [self addItem:items[i]];
   }
   return self;
 }
 
-- (void)addItem:(const WebMenuItem&)item
- withAttributes:(NSDictionary*)attrs {
+- (void)addItem:(const WebMenuItem&)item {
   if (item.type == WebMenuItem::SEPARATOR) {
     [menu_ addItem:[NSMenuItem separatorItem]];
     return;
@@ -85,12 +68,38 @@
                                    keyEquivalent:@""];
   [menuItem setEnabled:(item.enabled && item.type != WebMenuItem::GROUP)];
   [menuItem setTarget:self];
-  if (attrs) {
-    scoped_nsobject<NSAttributedString> attrTitle(
-        [[NSAttributedString alloc] initWithString:title
-                                        attributes:attrs]);
-    [menuItem setAttributedTitle:attrTitle];
+
+  // Set various alignment/language attributes. Note that many (if not most) of
+  // these attributes are functional only on 10.6 and above.
+  scoped_nsobject<NSMutableDictionary> attrs(
+      [[NSMutableDictionary alloc] initWithCapacity:3]);
+  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+      [[NSMutableParagraphStyle alloc] init]);
+  [paragraphStyle setAlignment:rightAligned_ ? NSRightTextAlignment
+                                             : NSLeftTextAlignment];
+  NSWritingDirection writingDirection =
+      item.rtl ? NSWritingDirectionRightToLeft
+               : NSWritingDirectionLeftToRight;
+  [paragraphStyle setBaseWritingDirection:writingDirection];
+  [attrs setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
+
+  if (item.has_directional_override) {
+    scoped_nsobject<NSNumber> directionValue(
+        [[NSNumber alloc] initWithInteger:
+            writingDirection + NSTextWritingDirectionOverride]);
+    scoped_nsobject<NSArray> directionArray(
+        [[NSArray alloc] initWithObjects:directionValue.get(), nil]);
+    [attrs setObject:directionArray forKey:NSWritingDirectionAttributeName];
   }
+
+  [attrs setObject:[NSFont menuFontOfSize:fontSize_]
+            forKey:NSFontAttributeName];
+
+  scoped_nsobject<NSAttributedString> attrTitle(
+      [[NSAttributedString alloc] initWithString:title
+                                      attributes:attrs]);
+  [menuItem setAttributedTitle:attrTitle];
+
   [menuItem setTag:[menu_ numberOfItems] - 1];
 }
 
@@ -104,53 +113,41 @@
 
 - (void)menuItemSelected:(id)sender {
   menuItemWasChosen_ = YES;
-  if (gNewNSMenuAPI)
-    index_ = [sender tag];
 }
 
 - (void)runMenuInView:(NSView*)view
            withBounds:(NSRect)bounds
          initialIndex:(int)index {
-  if (gNewNSMenuAPI) {
-    // index might be out of bounds, in which case we set no selection.
-    NSMenuItem* selectedItem = [menu_ itemWithTag:index];
-    if (selectedItem) {
-      [selectedItem setState:NSOnState];
-    } else {
-      selectedItem = [menu_ itemWithTag:0];
-    }
-    NSPoint anchor = NSMakePoint(NSMinX(bounds) + kPopupXOffset,
-                                 NSMaxY(bounds));
-    [menu_ popUpMenuPositioningItem:selectedItem
-                         atLocation:anchor
-                             inView:view];
-  } else {
-    // Set up the button cell, converting to NSView coordinates. The menu is
-    // positioned such that the currently selected menu item appears over the
-    // popup button, which is the expected Mac popup menu behavior.
-    NSPopUpButtonCell* button = [[NSPopUpButtonCell alloc] initTextCell:@""
-                                                              pullsDown:NO];
-    [button autorelease];
-    [button setMenu:menu_];
-    // We use selectItemWithTag below so if the index is out-of-bounds nothing
-    // bad happens.
-    [button selectItemWithTag:index];
-    [button setFont:[NSFont menuFontOfSize:fontSize_]];
+  // Set up the button cell, converting to NSView coordinates. The menu is
+  // positioned such that the currently selected menu item appears over the
+  // popup button, which is the expected Mac popup menu behavior.
+  NSPopUpButtonCell* button = [[NSPopUpButtonCell alloc] initTextCell:@""
+                                                            pullsDown:NO];
+  [button autorelease];
+  [button setMenu:menu_];
+  // We use selectItemWithTag below so if the index is out-of-bounds nothing
+  // bad happens.
+  [button selectItemWithTag:index];
 
-    // Create a dummy view to associate the popup with, since the OS will use
-    // that view for positioning the menu.
-    NSView* dummyView = [[[NSView alloc] initWithFrame:bounds] autorelease];
-    [view addSubview:dummyView];
-    NSRect dummyBounds = [dummyView convertRect:bounds fromView:view];
-
-    // Display the menu, and set a flag if a menu item was chosen.
-    [button performClickWithFrame:dummyBounds inView:dummyView];
-
-    if ([self menuItemWasChosen])
-      index_ = [button indexOfSelectedItem];
-
-    [dummyView removeFromSuperview];
+  if (rightAligned_ &&
+      [button respondsToSelector:@selector(setUserInterfaceLayoutDirection:)]) {
+    [button setUserInterfaceLayoutDirection:
+        NSUserInterfaceLayoutDirectionRightToLeft];
   }
+
+  // Create a dummy view to associate the popup with, since the OS will use
+  // that view for positioning the menu.
+  NSView* dummyView = [[[NSView alloc] initWithFrame:bounds] autorelease];
+  [view addSubview:dummyView];
+  NSRect dummyBounds = [dummyView convertRect:bounds fromView:view];
+
+  // Display the menu, and set a flag if a menu item was chosen.
+  [button performClickWithFrame:dummyBounds inView:dummyView];
+
+  if ([self menuItemWasChosen])
+    index_ = [button indexOfSelectedItem];
+
+  [dummyView removeFromSuperview];
 }
 
 - (int)indexOfSelectedItem {
diff --git a/webkit/glue/webpasswordautocompletelistener_impl.cc b/webkit/glue/webpasswordautocompletelistener_impl.cc
index 280ce43..20ecf60 100644
--- a/webkit/glue/webpasswordautocompletelistener_impl.cc
+++ b/webkit/glue/webpasswordautocompletelistener_impl.cc
@@ -10,9 +10,9 @@
 #include <vector>
 
 #include "base/string_util.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 
 using WebKit::WebFrame;
 using WebKit::WebView;
diff --git a/webkit/glue/webpasswordautocompletelistener_impl.h b/webkit/glue/webpasswordautocompletelistener_impl.h
index 6badcb7..067c6c2 100644
--- a/webkit/glue/webpasswordautocompletelistener_impl.h
+++ b/webkit/glue/webpasswordautocompletelistener_impl.h
@@ -10,8 +10,8 @@
 
 #include "base/basictypes.h"
 #include "base/scoped_ptr.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebPasswordAutocompleteListener.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPasswordAutocompleteListener.h"
 #include "webkit/glue/password_form_dom_manager.h"
 
 using WebKit::WebInputElement;
diff --git a/webkit/glue/webpreferences.cc b/webkit/glue/webpreferences.cc
index 02092de..03c87bf 100644
--- a/webkit/glue/webpreferences.cc
+++ b/webkit/glue/webpreferences.cc
@@ -6,12 +6,12 @@
 
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRuntimeFeatures.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSettings.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSettings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/glue/webkit_glue.h"
 
 using WebKit::WebRuntimeFeatures;
@@ -60,13 +60,17 @@
       frame_flattening_enabled(false),
       allow_universal_access_from_file_urls(false),
       allow_file_access_from_file_urls(false),
+      webaudio_enabled(false),
       experimental_webgl_enabled(false),
+      gl_multisampling_enabled(true),
       show_composited_layer_borders(false),
       accelerated_compositing_enabled(false),
       accelerated_layers_enabled(false),
       accelerated_video_enabled(false),
       accelerated_2d_canvas_enabled(false),
-      memory_info_enabled(false) {
+      accelerated_plugins_enabled(false),
+      memory_info_enabled(false),
+      interactive_form_validation_enabled(true) {
 }
 
 WebPreferences::~WebPreferences() {
@@ -140,12 +144,18 @@
   // but also because it cause a possible crash in Editor::hasBidiSelection().
   settings->setTextDirectionSubmenuInclusionBehaviorNeverIncluded();
 
+  // Enable the web audio API if requested on the command line.
+  settings->setWebAudioEnabled(webaudio_enabled);
+
   // Enable experimental WebGL support if requested on command line
   // and support is compiled in.
   bool enable_webgl =
       WebRuntimeFeatures::isWebGLEnabled() && experimental_webgl_enabled;
   settings->setExperimentalWebGLEnabled(enable_webgl);
 
+  // Disable GL multisampling if requested on command line.
+  settings->setOpenGLMultisamplingEnabled(gl_multisampling_enabled);
+
   // Display colored borders around composited render layers if requested
   // on command line.
   settings->setShowDebugBorders(show_composited_layer_borders);
@@ -157,16 +167,18 @@
   settings->setAccelerated2dCanvasEnabled(accelerated_2d_canvas_enabled);
 
   // Enabling accelerated layers from the command line enabled accelerated
-  // 3D CSS, Video, Plugins, and Animations.
+  // 3D CSS, Video, and Animations.
   settings->setAcceleratedCompositingFor3DTransformsEnabled(
       accelerated_layers_enabled);
   settings->setAcceleratedCompositingForVideoEnabled(
       accelerated_video_enabled);
-  settings->setAcceleratedCompositingForPluginsEnabled(
-      accelerated_layers_enabled);
   settings->setAcceleratedCompositingForAnimationEnabled(
       accelerated_layers_enabled);
 
+  // Enabling accelerated plugins if specified from the command line.
+  settings->setAcceleratedCompositingForPluginsEnabled(
+      accelerated_plugins_enabled);
+
   // WebGL and accelerated 2D canvas are always gpu composited.
   settings->setAcceleratedCompositingForCanvasEnabled(
       enable_webgl || accelerated_2d_canvas_enabled);
@@ -182,4 +194,7 @@
   // Tabs to link is not part of the settings. WebCore calls
   // ChromeClient::tabsToLinks which is part of the glue code.
   web_view->setTabsToLinks(tabs_to_links);
+
+  settings->setInteractiveFormValidationEnabled(
+      interactive_form_validation_enabled);
 }
diff --git a/webkit/glue/webpreferences.h b/webkit/glue/webpreferences.h
index b14d323..468e9b4 100644
--- a/webkit/glue/webpreferences.h
+++ b/webkit/glue/webpreferences.h
@@ -5,8 +5,8 @@
 // A struct for managing webkit's settings.
 //
 // Adding new values to this class probably involves updating
-// WebKit::WebSettings, common/render_messages.h, and
-// browser/profile.cc.
+// WebKit::WebSettings, common/render_messages.cc, browser/tab_contents/
+// render_view_host_delegate_helper.cc, and browser/profiles/profile.cc.
 
 #ifndef WEBKIT_GLUE_WEBPREFERENCES_H__
 #define WEBKIT_GLUE_WEBPREFERENCES_H__
@@ -66,13 +66,17 @@
   bool frame_flattening_enabled;
   bool allow_universal_access_from_file_urls;
   bool allow_file_access_from_file_urls;
+  bool webaudio_enabled;
   bool experimental_webgl_enabled;
+  bool gl_multisampling_enabled;
   bool show_composited_layer_borders;
   bool accelerated_compositing_enabled;
   bool accelerated_layers_enabled;
   bool accelerated_video_enabled;
   bool accelerated_2d_canvas_enabled;
+  bool accelerated_plugins_enabled;
   bool memory_info_enabled;
+  bool interactive_form_validation_enabled;
 
   // We try to keep the default values the same as the default values in
   // chrome, except for the cases where it would require lots of extra work for
diff --git a/webkit/glue/websocketstreamhandle_impl.cc b/webkit/glue/websocketstreamhandle_impl.cc
index 6a56393..d1c7ba0 100644
--- a/webkit/glue/websocketstreamhandle_impl.cc
+++ b/webkit/glue/websocketstreamhandle_impl.cc
@@ -12,9 +12,9 @@
 #include "base/logging.h"
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSocketStreamHandleClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSocketStreamHandleClient.h"
 #include "webkit/glue/websocketstreamhandle_bridge.h"
 #include "webkit/glue/websocketstreamhandle_delegate.h"
 
diff --git a/webkit/glue/websocketstreamhandle_impl.h b/webkit/glue/websocketstreamhandle_impl.h
index f8a08f4..81ae68c 100644
--- a/webkit/glue/websocketstreamhandle_impl.h
+++ b/webkit/glue/websocketstreamhandle_impl.h
@@ -6,7 +6,7 @@
 #define WEBKIT_GLUE_WEBSOCKETSTREAMHANDLE_IMPL_H_
 
 #include "base/ref_counted.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSocketStreamHandle.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSocketStreamHandle.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/webthemeengine_impl_linux.cc b/webkit/glue/webthemeengine_impl_linux.cc
index d5cc9b4..6d9fc5b 100644
--- a/webkit/glue/webthemeengine_impl_linux.cc
+++ b/webkit/glue/webthemeengine_impl_linux.cc
@@ -4,10 +4,10 @@
 
 #include "webkit/glue/webthemeengine_impl_linux.h"
 
-#include "gfx/native_theme_linux.h"
 #include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
+#include "ui/gfx/native_theme_linux.h"
 
 using WebKit::WebCanvas;
 using WebKit::WebColor;
@@ -34,10 +34,28 @@
       return gfx::NativeThemeLinux::kScrollbarHorizontalThumb;
     case WebKit::WebThemeEngine::PartScrollbarVerticalThumb:
       return gfx::NativeThemeLinux::kScrollbarVerticalThumb;
-    case WebKit::WebThemeEngine::PartScrollbarHoriztonalTrack:
+    case WebKit::WebThemeEngine::PartScrollbarHorizontalTrack:
       return gfx::NativeThemeLinux::kScrollbarHorizontalTrack;
     case WebKit::WebThemeEngine::PartScrollbarVerticalTrack:
       return gfx::NativeThemeLinux::kScrollbarVerticalTrack;
+    case WebKit::WebThemeEngine::PartCheckbox:
+      return gfx::NativeThemeLinux::kCheckbox;
+    case WebKit::WebThemeEngine::PartRadio:
+      return gfx::NativeThemeLinux::kRadio;
+    case WebKit::WebThemeEngine::PartButton:
+      return gfx::NativeThemeLinux::kPushButton;
+    case WebKit::WebThemeEngine::PartTextField:
+      return gfx::NativeThemeLinux::kTextField;
+    case WebKit::WebThemeEngine::PartMenuList:
+      return gfx::NativeThemeLinux::kMenuList;
+    case WebKit::WebThemeEngine::PartSliderTrack:
+      return gfx::NativeThemeLinux::kSliderTrack;
+    case WebKit::WebThemeEngine::PartSliderThumb:
+      return gfx::NativeThemeLinux::kSliderThumb;
+    case WebKit::WebThemeEngine::PartInnerSpinButton:
+      return gfx::NativeThemeLinux::kInnerSpinButton;
+    case WebKit::WebThemeEngine::PartProgressBar:
+      return gfx::NativeThemeLinux::kProgressBar;
     default:
       return gfx::NativeThemeLinux::kScrollbarDownArrow;
   }
@@ -49,7 +67,7 @@
     case WebKit::WebThemeEngine::StateDisabled:
       return gfx::NativeThemeLinux::kDisabled;
     case WebKit::WebThemeEngine::StateHover:
-      return gfx::NativeThemeLinux::kHover;
+      return gfx::NativeThemeLinux::kHovered;
     case WebKit::WebThemeEngine::StateNormal:
       return gfx::NativeThemeLinux::kNormal;
     case WebKit::WebThemeEngine::StatePressed:
@@ -64,21 +82,79 @@
     WebKit::WebThemeEngine::State state,
     const WebKit::WebThemeEngine::ExtraParams* extra_params,
     gfx::NativeThemeLinux::ExtraParams* native_theme_extra_params) {
-  if (part == WebKit::WebThemeEngine::PartScrollbarHoriztonalTrack ||
-      part == WebKit::WebThemeEngine::PartScrollbarVerticalTrack) {
-    native_theme_extra_params->scrollbar_track.track_x =
-        extra_params->scrollbarTrack.trackX;
-    native_theme_extra_params->scrollbar_track.track_y =
-        extra_params->scrollbarTrack.trackY;
-    native_theme_extra_params->scrollbar_track.track_width =
-        extra_params->scrollbarTrack.trackWidth;
-    native_theme_extra_params->scrollbar_track.track_height =
-        extra_params->scrollbarTrack.trackHeight;
+  switch (part) {
+    case WebKit::WebThemeEngine::PartScrollbarHorizontalTrack:
+    case WebKit::WebThemeEngine::PartScrollbarVerticalTrack:
+      native_theme_extra_params->scrollbar_track.track_x =
+          extra_params->scrollbarTrack.trackX;
+      native_theme_extra_params->scrollbar_track.track_y =
+          extra_params->scrollbarTrack.trackY;
+      native_theme_extra_params->scrollbar_track.track_width =
+          extra_params->scrollbarTrack.trackWidth;
+      native_theme_extra_params->scrollbar_track.track_height =
+          extra_params->scrollbarTrack.trackHeight;
+      break;
+    case WebKit::WebThemeEngine::PartCheckbox:
+      native_theme_extra_params->button.checked = extra_params->button.checked;
+      native_theme_extra_params->button.indeterminate =
+          extra_params->button.indeterminate;
+      break;
+    case WebKit::WebThemeEngine::PartRadio:
+      native_theme_extra_params->button.checked = extra_params->button.checked;
+      break;
+    case WebKit::WebThemeEngine::PartButton:
+      native_theme_extra_params->button.is_default =
+          extra_params->button.isDefault;
+      native_theme_extra_params->button.background_color =
+          extra_params->button.backgroundColor;
+      break;
+    case WebKit::WebThemeEngine::PartTextField:
+      native_theme_extra_params->text_field.is_text_area =
+          extra_params->textField.isTextArea;
+      native_theme_extra_params->text_field.is_listbox =
+          extra_params->textField.isListbox;
+      native_theme_extra_params->text_field.background_color =
+          extra_params->textField.backgroundColor;
+      break;
+    case WebKit::WebThemeEngine::PartMenuList:
+      native_theme_extra_params->menu_list.arrow_x =
+          extra_params->menuList.arrowX;
+      native_theme_extra_params->menu_list.arrow_y =
+          extra_params->menuList.arrowY;
+      native_theme_extra_params->menu_list.background_color =
+          extra_params->menuList.backgroundColor;
+      break;
+    case WebKit::WebThemeEngine::PartSliderTrack:
+    case WebKit::WebThemeEngine::PartSliderThumb:
+      native_theme_extra_params->slider.vertical =
+          extra_params->slider.vertical;
+      native_theme_extra_params->slider.in_drag = extra_params->slider.inDrag;
+      break;
+    case WebKit::WebThemeEngine::PartInnerSpinButton:
+      native_theme_extra_params->inner_spin.spin_up =
+          extra_params->innerSpin.spinUp;
+      native_theme_extra_params->inner_spin.read_only =
+          extra_params->innerSpin.readOnly;
+      break;
+    case WebKit::WebThemeEngine::PartProgressBar:
+      native_theme_extra_params->progress_bar.determinate =
+          extra_params->progressBar.determinate;
+      native_theme_extra_params->progress_bar.value_rect_x =
+          extra_params->progressBar.valueRectX;
+      native_theme_extra_params->progress_bar.value_rect_y =
+          extra_params->progressBar.valueRectY;
+      native_theme_extra_params->progress_bar.value_rect_width =
+          extra_params->progressBar.valueRectWidth;
+      native_theme_extra_params->progress_bar.value_rect_height =
+          extra_params->progressBar.valueRectHeight;
+      break;
+    default:
+      break;  // Parts that have no extra params get here.
   }
 }
 
 WebKit::WebSize WebThemeEngineImpl::getSize(WebKit::WebThemeEngine::Part part) {
-  return gfx::NativeThemeLinux::instance()->GetSize(NativeThemePart(part));
+  return gfx::NativeThemeLinux::instance()->GetPartSize(NativeThemePart(part));
 }
 
 void WebThemeEngineImpl::paint(
diff --git a/webkit/glue/webthemeengine_impl_linux.h b/webkit/glue/webthemeengine_impl_linux.h
index 265b80c..3dcba6d 100644
--- a/webkit/glue/webthemeengine_impl_linux.h
+++ b/webkit/glue/webthemeengine_impl_linux.h
@@ -5,7 +5,7 @@
 #ifndef WEBTHEMEENGINE_IMPL_LINUX_H_
 #define WEBTHEMEENGINE_IMPL_LINUX_H_
 
-#include "third_party/WebKit/WebKit/chromium/public/linux/WebThemeEngine.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebThemeEngine.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/webthemeengine_impl_mac.cc b/webkit/glue/webthemeengine_impl_mac.cc
index ac28334..cafc316 100644
--- a/webkit/glue/webthemeengine_impl_mac.cc
+++ b/webkit/glue/webthemeengine_impl_mac.cc
@@ -6,8 +6,8 @@
 
 #include <Carbon/Carbon.h>
 
-#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
 
 using WebKit::WebCanvas;
 using WebKit::WebRect;
diff --git a/webkit/glue/webthemeengine_impl_mac.h b/webkit/glue/webthemeengine_impl_mac.h
index 788cba3..6b0415f 100644
--- a/webkit/glue/webthemeengine_impl_mac.h
+++ b/webkit/glue/webthemeengine_impl_mac.h
@@ -5,7 +5,7 @@
 #ifndef WEBKIT_GLUE_WEBTHEMEENGINE_IMPL_MAC_H_
 #define WEBKIT_GLUE_WEBTHEMEENGINE_IMPL_MAC_H_
 
-#include "third_party/WebKit/WebKit/chromium/public/mac/WebThemeEngine.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebThemeEngine.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/webthemeengine_impl_win.cc b/webkit/glue/webthemeengine_impl_win.cc
index 85dc113..a6344b6 100644
--- a/webkit/glue/webthemeengine_impl_win.cc
+++ b/webkit/glue/webthemeengine_impl_win.cc
@@ -4,10 +4,10 @@
 
 #include "webkit/glue/webthemeengine_impl_win.h"
 
-#include "gfx/native_theme_win.h"
 #include "skia/ext/platform_canvas.h"
 #include "skia/ext/skia_utils_win.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
+#include "ui/gfx/native_theme_win.h"
 
 using WebKit::WebCanvas;
 using WebKit::WebColor;
diff --git a/webkit/glue/webthemeengine_impl_win.h b/webkit/glue/webthemeengine_impl_win.h
index 6e749c4..ecdbec2 100644
--- a/webkit/glue/webthemeengine_impl_win.h
+++ b/webkit/glue/webthemeengine_impl_win.h
@@ -5,7 +5,7 @@
 #ifndef WEBTHEMEENGINE_IMPL_WIN_H_
 #define WEBTHEMEENGINE_IMPL_WIN_H_
 
-#include "third_party/WebKit/WebKit/chromium/public/win/WebThemeEngine.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebThemeEngine.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc
index 0372567..d4b5162 100644
--- a/webkit/glue/weburlloader_impl.cc
+++ b/webkit/glue/weburlloader_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,15 +18,15 @@
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
 #include "net/http/http_response_headers.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebHTTPLoadInfo.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebSecurityPolicy.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoadTiming.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPLoadInfo.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoadTiming.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
 #include "webkit/glue/ftp_directory_listing_response_delegate.h"
 #include "webkit/glue/multipart_response_delegate.h"
 #include "webkit/glue/resource_loader_bridge.h"
@@ -69,10 +69,8 @@
     const std::string& value_utf8 = value.utf8();
 
     // Skip over referrer headers found in the header map because we already
-    // pulled it out as a separate parameter.  We likewise prune the UA since
-    // that will be added back by the network layer.
-    if (LowerCaseEqualsASCII(name_utf8, "referer") ||
-        LowerCaseEqualsASCII(name_utf8, "user-agent"))
+    // pulled it out as a separate parameter.
+    if (LowerCaseEqualsASCII(name_utf8, "referer"))
       return;
 
     // Skip over "Cache-Control: max-age=0" header if the corresponding
@@ -146,11 +144,12 @@
 // Extracts the information from a data: url.
 bool GetInfoFromDataURL(const GURL& url,
                         ResourceResponseInfo* info,
-                        std::string* data, URLRequestStatus* status) {
+                        std::string* data,
+                        net::URLRequestStatus* status) {
   std::string mime_type;
   std::string charset;
   if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
-    *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0);
+    *status = net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0);
     info->request_time = Time::Now();
     info->response_time = Time::Now();
     info->headers = NULL;
@@ -162,7 +161,8 @@
     return true;
   }
 
-  *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL);
+  *status = net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                  net::ERR_INVALID_URL);
   return false;
 }
 
@@ -244,8 +244,8 @@
   // pass it to GetSuggestedFilename.
   std::string value;
   if (headers->EnumerateHeader(NULL, "content-disposition", &value)) {
-    response->setSuggestedFileName(FilePathToWebString(
-        net::GetSuggestedFilename(url, value, "", FilePath())));
+    response->setSuggestedFileName(
+        net::GetSuggestedFilename(url, value, "", string16()));
   }
 
   Time time_val;
@@ -294,10 +294,9 @@
   virtual void OnDownloadedData(int len);
   virtual void OnReceivedData(const char* data, int len);
   virtual void OnReceivedCachedMetadata(const char* data, int len);
-  virtual void OnCompletedRequest(
-      const URLRequestStatus& status,
-      const std::string& security_info,
-      const base::Time& completion_time);
+  virtual void OnCompletedRequest(const net::URLRequestStatus& status,
+                                  const std::string& security_info,
+                                  const base::Time& completion_time);
 
  private:
   friend class base::RefCounted<Context>;
@@ -404,12 +403,6 @@
   if (!request.allowStoredCredentials())
     load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
 
-  // TODO(jcampan): in the non out-of-process plugin case the request does not
-  // have a requestor_pid. Find a better place to set this.
-  int requestor_pid = request.requestorProcessID();
-  if (requestor_pid == 0)
-    requestor_pid = base::GetCurrentProcId();
-
   HeaderFlattener flattener(load_flags);
   request.visitHTTPHeaderFields(&flattener);
 
@@ -430,7 +423,10 @@
   request_info.main_frame_origin = main_frame_origin;
   request_info.headers = flattener.GetBuffer();
   request_info.load_flags = load_flags;
-  request_info.requestor_pid = requestor_pid;
+  // requestor_pid only needs to be non-zero if the request originates outside
+  // the render process, so we can use requestorProcessID even for requests
+  // from in-process plugins.
+  request_info.requestor_pid = request.requestorProcessID();
   request_info.request_type = FromTargetType(request.targetType());
   request_info.appcache_host_id = request.appCacheHostID();
   request_info.routing_id = request.requestorID();
@@ -621,7 +617,7 @@
 }
 
 void WebURLLoaderImpl::Context::OnCompletedRequest(
-    const URLRequestStatus& status,
+    const net::URLRequestStatus& status,
     const std::string& security_info,
     const base::Time& completion_time) {
   if (ftp_listing_delegate_.get()) {
@@ -638,9 +634,9 @@
   completed_bridge_.swap(bridge_);
 
   if (client_) {
-    if (status.status() != URLRequestStatus::SUCCESS) {
+    if (status.status() != net::URLRequestStatus::SUCCESS) {
       int error_code;
-      if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) {
+      if (status.status() == net::URLRequestStatus::HANDLED_EXTERNALLY) {
         // By marking this request as aborted we insure that we don't navigate
         // to an error page.
         error_code = net::ERR_ABORTED;
@@ -691,7 +687,7 @@
 
 void WebURLLoaderImpl::Context::HandleDataURL() {
   ResourceResponseInfo info;
-  URLRequestStatus status;
+  net::URLRequestStatus status;
   std::string data;
 
   if (GetInfoFromDataURL(request_.url(), &info, &data, &status)) {
@@ -724,9 +720,10 @@
 
   // TODO(tc): For file loads, we may want to include a more descriptive
   // status code or status text.
-  const URLRequestStatus::Status& status = sync_load_response.status.status();
-  if (status != URLRequestStatus::SUCCESS &&
-      status != URLRequestStatus::HANDLED_EXTERNALLY) {
+  const net::URLRequestStatus::Status& status =
+      sync_load_response.status.status();
+  if (status != net::URLRequestStatus::SUCCESS &&
+      status != net::URLRequestStatus::HANDLED_EXTERNALLY) {
     response.setURL(final_url);
     error.domain = WebString::fromUTF8(net::kErrorDomain);
     error.reason = sync_load_response.status.os_error();
diff --git a/webkit/glue/weburlloader_impl.h b/webkit/glue/weburlloader_impl.h
index f9e5a0b..9a39911 100644
--- a/webkit/glue/weburlloader_impl.h
+++ b/webkit/glue/weburlloader_impl.h
@@ -6,7 +6,7 @@
 #define WEBKIT_GLUE_WEBURLLOADER_IMPL_H_
 
 #include "base/ref_counted.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
 
 namespace webkit_glue {
 
diff --git a/webkit/glue/webvideoframe_impl.cc b/webkit/glue/webvideoframe_impl.cc
index bfb1d53..c2e115d 100644
--- a/webkit/glue/webvideoframe_impl.cc
+++ b/webkit/glue/webvideoframe_impl.cc
@@ -5,7 +5,7 @@
 #include "webkit/glue/webvideoframe_impl.h"
 
 #include "media/base/video_frame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVideoFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
 
 using namespace WebKit;
 
diff --git a/webkit/glue/webvideoframe_impl.h b/webkit/glue/webvideoframe_impl.h
index 5454089..0aca052 100644
--- a/webkit/glue/webvideoframe_impl.h
+++ b/webkit/glue/webvideoframe_impl.h
@@ -6,7 +6,7 @@
 #define WEBKIT_GLUE_WEBVIDEOFRAME_IMPL_H_
 
 #include "media/base/video_frame.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebVideoFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
 
 using namespace WebKit;
 
diff --git a/webkit/glue/webview_unittest.cc b/webkit/glue/webview_unittest.cc
index 22c9cea..1d3d2ea 100644
--- a/webkit/glue/webview_unittest.cc
+++ b/webkit/glue/webview_unittest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "webkit/tools/test_shell/test_shell_test.h"
 
 using WebKit::WebView;
diff --git a/webkit/glue/window_open_disposition.h b/webkit/glue/window_open_disposition.h
index 24495f1..c9bfa0a 100644
--- a/webkit/glue/window_open_disposition.h
+++ b/webkit/glue/window_open_disposition.h
@@ -5,7 +5,7 @@
 #ifndef WEBKIT_GLUE_WINDOW_OPEN_DISPOSITION_H_
 #define WEBKIT_GLUE_WINDOW_OPEN_DISPOSITION_H_
 
-#include "third_party/WebKit/WebKit/chromium/public/WebNavigationPolicy.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNavigationPolicy.h"
 
 enum WindowOpenDisposition {
   SUPPRESS_OPEN,